From 3002010db67633448c9733611886f7d45db1f2f3 Mon Sep 17 00:00:00 2001 From: svcmobrel-release Date: Thu, 3 Aug 2023 21:10:38 -0700 Subject: [PATCH] Updating prebuilts and/or headers df74e654e27c07ba2b83fc80f46368c1aa63d713 - optee_src_build.sh d15f50688485e11293e0d0bd66d73655e79f7718 - nvcommon_build.sh 94631ac9bb0297e7d636c0b76fbb046abbb62df2 - optee/tegra234-optee.dts f17a52a204d42c6699bdc375e3aace6bcdcfdbf9 - optee/tegra194-optee.dts e7fe1d82e00a66f594a738016d2c3f0040ba065a - optee/optee_os/MAINTAINERS 8c2c72f00c2c6eef765a45d8b8eee4adca4b43a0 - optee/optee_os/CHANGELOG.md bf1387b548dae92223ef175a7d56e4f88d6cfe84 - optee/optee_os/Makefile 6bf9bd872a69d8c13e8dcac71fac8d094646251d - optee/optee_os/README.md 370d68b1c9485f254e7c701c31e3c74fd16cacd7 - optee/optee_os/LICENSE 3a608e255399bb5cf2302bb52e533d81c469ecce - optee/optee_os/LICENSE.NVIDIA 96558a7a79bf90ebde8720b0087c9c578efa981b - optee/optee_os/.checkpatch.conf 25ecfc13bc9b5205cb9db1ffb015fa973c8a754b - optee/optee_os/typedefs.checkpatch edc01ccf3e16f1a4bdb1908f57a4722d3bfa203a - optee/optee_os/scripts/checkpatch.sh c92fcf555467abe77b88cea98e805eaa6eca5462 - optee/optee_os/scripts/gen_ld_sects.py 24ab5b3587dac3d8b99136338a79a57b38027da9 - optee/optee_os/scripts/mem_usage.py 31f300bb6c5a381759d5e2a3b54e42039be66dd5 - optee/optee_os/scripts/sign_helper_kms.py ff71ab8e19870db30e4a8fba666168c645f37126 - optee/optee_os/scripts/tee_bin_parser.py f5129e67acb9e8d845d39e92497f7de01ae50522 - optee/optee_os/scripts/symbolize.py ab4324da2d6fb92edbcaa95bc23911ed63e4514d - optee/optee_os/scripts/arm32_sysreg.py cfc4d70e52ea54f55638942bf254588c218d311f - optee/optee_os/scripts/ts_bin_to_c.py e13049cc7ecc4774a0b40b42d6a72617f540db8d - optee/optee_os/scripts/bin_to_c.py 76a908634bfe89773fd70c57fd77d712c4bc89ee - optee/optee_os/scripts/sign_encrypt.py ffaf1fbbaa6d01cecaeae7d8ce75f8315240228d - optee/optee_os/scripts/pem_to_pub_c.py 08b1957d02a5f8fb853138fa4b3f2b8b04f8d847 - optee/optee_os/scripts/update_changelog.py e6692bdad99dbf466f146fe7169981ae542eb6cd - optee/optee_os/scripts/get_maintainer.py bf2d92432e259f18d97d2a955e3192aa3c98813f - optee/optee_os/scripts/checkpatch_inc.sh b1241b7d0c39f88fb4382637396901002f682b69 - optee/optee_os/scripts/gen_tee_bin.py f8bce245ce0b6610d39e02928e25307a5b6cc818 - optee/optee_os/scripts/print_tee_hash.py 570bf1d2a225e0124496bc57c287ff0991fd023a - optee/optee_os/scripts/gen_stmm_hex.py d302da149f2f0d0b11b9c365bf3add51a131b8a9 - optee/optee_os/scripts/gen_ldelf_hex.py c5d1a1d261c8bada5f949335bffe29a029d03e05 - optee/optee_os/ldelf/syscalls_a32.S 4b036af7eee80c9d1402b0b1dcd09cab729a7a9b - optee/optee_os/ldelf/pauth.c db3db1aeff618f5696eb16e7076b63464784267e - optee/optee_os/ldelf/syscalls_asm.S 7126b1fbc89ca63285473f1123be50f2547e8783 - optee/optee_os/ldelf/ta_elf_rel.c f38c4636b6798cab2823555649a59b72061b756b - optee/optee_os/ldelf/ldelf.ld.S cb079ab7bac5d488cf5375c1b028130bcb2c7997 - optee/optee_os/ldelf/sys.h d875d1a5979daa09b5b535d0a3f040c86a60f078 - optee/optee_os/ldelf/start_rv64.S 139e3f4826e35954af3c3bfe5112f11c1bd0db62 - optee/optee_os/ldelf/syscalls_rv.S 34de0a40ccfb6261b73bd7bad69bc8deae4d7b83 - optee/optee_os/ldelf/main.c 87d8438d725c689049dabad1a58459a5efaaef0a - optee/optee_os/ldelf/dl.c 6be295fcd01de4a3c85a70f622f14d21dd0f9e95 - optee/optee_os/ldelf/ta_elf.c f133be54ea11df978fa33a5afe3a2d8ed8c8f035 - optee/optee_os/ldelf/pauth.h 29a349fad517b13af907e7705113c3831dccd9e9 - optee/optee_os/ldelf/syscalls_a64.S b8dfc91cf5557585f6b8ca8bf02de131b81a8761 - optee/optee_os/ldelf/ta_elf.h 611d7981c55b4c62f5b13677c04a314e1a2f3218 - optee/optee_os/ldelf/dl.h 20655cc8868222c793eaf2045022fe254ae72f73 - optee/optee_os/ldelf/ftrace.c ecc193b3d2a051728bc5d4e5841c8bdc021b6d35 - optee/optee_os/ldelf/sys.c 9201638e87d7051478eaabddd7ca1d9054f35f5f - optee/optee_os/ldelf/tlsdesc_rel_a64.S 13ded24e6da6026069baf1c4dd3159b6410f5308 - optee/optee_os/ldelf/start_a64.S a270591f1efb8037df1d1369287b15f5f2964e0c - optee/optee_os/ldelf/start_a32.S af3868e37b5f97fafb0a1843478916e687050325 - optee/optee_os/ldelf/ftrace.h e753e305779ac38002c5db612439fd95d3e9a20d - optee/optee_os/ldelf/include/ldelf_syscalls.h 9d6a14f727a55f4691af8e78834e23c243a1be39 - optee/optee_os/ldelf/include/ldelf.h 73be8d9cc10ccf4ecc646ab51ec17b8bbb51177c - optee/optee_os/core/mm/fobj.c d8a0dde12ce3d5eec6373fbf9d3a5292b73a9f57 - optee/optee_os/core/mm/mobj.c c3f15722f779f9fa7c746d6926c361ad9acf253b - optee/optee_os/core/mm/tee_mm.c 448b224d13da51447f6e1b98759ee562d8214172 - optee/optee_os/core/mm/vm.c cda2e1ec5f1aa6988d7c008a9bdf0036834affbc - optee/optee_os/core/mm/core_mmu.c 4c81a53362b3a07b1dabb5a197f0e3ec26117bee - optee/optee_os/core/mm/file.c 22edc57cadee3b6787489b0d44956d4bbeec2ab6 - optee/optee_os/core/tests/ftmn_boot_tests.c fdcbba144185422b3358f9b1e37648325785bd3b - optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S 2055966a05cfa317cfedd7b7fa61120de3887b6d - optee/optee_os/core/arch/riscv/kernel/arch_scall.c ff0583c210b0d08923058c5b88884af14a634d23 - optee/optee_os/core/arch/riscv/kernel/thread_rv.S de03d1758884a3e0e0f7ea910139d312790963d1 - optee/optee_os/core/arch/riscv/kernel/arch_scall_rv.S 0f43c49d2273009469484b2cc76a2b941e4d9d68 - optee/optee_os/core/arch/riscv/kernel/cache_helpers_rv.S ae816f807c281348a9c45477cf12d500dbedc2b4 - optee/optee_os/core/arch/riscv/kernel/abort.c 66cbb4c5aaec299ae2ada34564f853e51dda0c88 - optee/optee_os/core/arch/riscv/kernel/entry.S f28a3e13c2adddd945644d7e1c854918769a51db - optee/optee_os/core/arch/riscv/kernel/asm-defines.c 5cdff36d678ecaf259d131b235eaae03cd6ac555 - optee/optee_os/core/arch/riscv/kernel/sbi_console.c 30e9802c7448df47767d12a2646fefdc0d2b2f63 - optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c 328d1c384a1fa2a526647211cd7cb002ed0e405f - optee/optee_os/core/arch/riscv/kernel/sbi.c 07c3499c0be1a28930978ace71005cfbed42ffe8 - optee/optee_os/core/arch/riscv/kernel/thread_arch.c 7f1c0c47cf8d4455d3bb56977982a34a008a7fbe - optee/optee_os/core/arch/riscv/kernel/spinlock.S 6c73b5fc6d37345ad9f610b7c2fedb763caa640c - optee/optee_os/core/arch/riscv/kernel/boot.c ef752dba0afbc3441defa0ce7f596275e4eacdf6 - optee/optee_os/core/arch/riscv/kernel/idle.c 651df224b31ff54d4fb317a17064937a491e94a0 - optee/optee_os/core/arch/riscv/kernel/kern.ld.S f955830a97a8a4231a0876fd8d1b2fc8bf3fabff - optee/optee_os/core/arch/riscv/include/riscv.h aaf4ec0db08de01b5e8012ce949710f9dcf0f993 - optee/optee_os/core/arch/riscv/include/encoding.h 38bc96a69aa9f591d848f9d2e8142862a8e2b624 - optee/optee_os/core/arch/riscv/include/riscv_macros.S 2e5b805bffc68fffc3c98a3a1b5c7868a2d175f9 - optee/optee_os/core/arch/riscv/include/sbi.h 50020758ad41a07b9fd0fc1986413e61fceea469 - optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h f90a39605a177515f57172f8bfcac31468bec502 - optee/optee_os/core/arch/riscv/include/mm/generic_ram_layout.h 9b0914d8eab20042998f50ed711cf154e3a65901 - optee/optee_os/core/arch/riscv/include/kernel/time.h 73b1c65df1603ea0e0f934fb8bcf951c475ab1de - optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h 0c4cbba16aac1f17267a36ecda588756cfd3277c - optee/optee_os/core/arch/riscv/include/kernel/clint.h 072f3b42da8ea82d534b28a5f3b298c6bcbfd9a9 - optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h 1121c6b1cd7d9f9ada431b691b4fa06bc14c8bea - optee/optee_os/core/arch/riscv/include/kernel/misc_arch.h d52408d38337f5b9bd967661199d3207bc29ef62 - optee/optee_os/core/arch/riscv/include/kernel/tee_l2cc_mutex.h 826a1d5fe853d5d25e39ce6e66d577e479b11016 - optee/optee_os/core/arch/riscv/include/kernel/stmm_sp.h 8cc637a0b1fa21930752c33d1cc58d647bc81179 - optee/optee_os/core/arch/riscv/include/kernel/arch_scall.h b3be5129fb98824666e9dbe5734dd1f811ab97d4 - optee/optee_os/core/arch/riscv/include/kernel/cache_helpers_arch.h 9ff069cbffd055e8fc24029279eafec7c295b34a - optee/optee_os/core/arch/riscv/include/kernel/secure_partition.h a407be51b81a27f999cf225a9ddba777cbd7ac31 - optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h 3c92f821bb1cb8889d1ff4a5c047a465faceaca8 - optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h 25fbb2839f929c582b956f5d3efb8930b8001a21 - optee/optee_os/core/arch/riscv/plat-spike/platform_config.h 13929110b72beaf2860119c208b13d15c270a4e2 - optee/optee_os/core/arch/riscv/plat-spike/main.c f4d75a0309e2040dbb1ca13717a13dfa6be01e03 - optee/optee_os/core/arch/riscv/plat-spike/kern.ld.S 558db749b68778acc836e96fc170bc823ab0e441 - optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.c 359b98fad7ce1225b5fb675394acb32df9e74380 - optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.h 0e70c8d59484616ecdb0c1b5c5c9581fdc86ae24 - optee/optee_os/core/arch/riscv/plat-virt/platform_config.h fc3e11858f322992f6f271cdebedd8d4d22daa5c - optee/optee_os/core/arch/riscv/plat-virt/main.c a1a353aa32ebd77dd5c2966ff38e024d0e8938bb - optee/optee_os/core/arch/arm/plat-k3/platform_config.h 61851f968e6974914e4ece81f9769761fbdf4a86 - optee/optee_os/core/arch/arm/plat-k3/main.c 4cc70212f3fc61c9fd17876bbc6170b0548bcddf - optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.c 2020136e5c1ef325c92bc319ebb5f582d8d1b447 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.h 96e780127fe944086f4e057b31baea9b2fa125e2 - optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.h a918fd9f66105e822efddf7848f7bdf38418656e - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h 934412647964baa2217cd31f41cc1e96e1691313 - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h cbad8ded2c71cdb2604713b866cbb2ef88fb879f - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c 5b5e14b90101fd4c4b62a395517fa027a0d3cd61 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c a72f2a95976d21b776dd99c722162a461e575190 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c e8c669f6cd515061ddc1fac878644149427040c8 - optee/optee_os/core/arch/arm/plat-rockchip/psci_rk322x.c 86e640e06414afd26ad833d31867572408fd251a - optee/optee_os/core/arch/arm/plat-rockchip/platform_config.h bdf9159293e4276febcee2971495ac1b293f9c05 - optee/optee_os/core/arch/arm/plat-rockchip/platform_px30.c 46a2594f3aa4681ffd83538ff397c8e3bf3974ca - optee/optee_os/core/arch/arm/plat-rockchip/grf.h de4933508c95b4cc044fec515f190d8ff6ebfdc0 - optee/optee_os/core/arch/arm/plat-rockchip/common.h 23bc0f69590154217ef6aa3bf2994644e95460ff - optee/optee_os/core/arch/arm/plat-rockchip/main.c 0a8ff2cde4d20336967135064473ce0e27a74ab8 - optee/optee_os/core/arch/arm/plat-rockchip/platform_rk3399.c 384be00889fd82aa785e7d07fa9f819c764557c4 - optee/optee_os/core/arch/arm/plat-rockchip/platform.h 55fa18d095461797359151b9c915092623f26367 - optee/optee_os/core/arch/arm/plat-rockchip/platform.c b74b363d6e2a566d4a03278aaacaf9391d505a44 - optee/optee_os/core/arch/arm/plat-rockchip/cru.h 1853ca66ab2f40919fcb69448e1b866eb2bc9e4b - optee/optee_os/core/arch/arm/plat-rockchip/core_pos_a32.S 24c8244ba3044caed1943ad05138413c6db6ab2e - optee/optee_os/core/arch/arm/plat-rockchip/platform_rk322x.c 971d879311868f34f4ebf712ba6de5f9f0ea6f35 - optee/optee_os/core/arch/arm/plat-rockchip/plat_init.S 1db073f2c2461a415ef38ec49964e57e0bbb91a1 - optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c fbf52bc1a50fae147acaeca0138d7dc640a88275 - optee/optee_os/core/arch/arm/mm/pgt_cache.c 97833bee07659a62e8ae1fd84785699502dd3027 - optee/optee_os/core/arch/arm/mm/core_mmu_v7.c 8e0dd71c8033f999a5bc20eea5e67308b91bcbf8 - optee/optee_os/core/arch/arm/mm/mobj_ffa.c e6f86e9d7f1972ae55f5ca9938620da5246c59b8 - optee/optee_os/core/arch/arm/mm/sp_mem.c dd9bfba08ae055c5ec8f97267c700a1526ff774c - optee/optee_os/core/arch/arm/mm/core_mmu.c 9007b3e86aaee64aababa1855ee5e8a53ad4b987 - optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c 014f76e8da8e41ddcb44997962ae5ed43c0c5adc - optee/optee_os/core/arch/arm/mm/tee_pager.c 7b9a469836ce4379d91402d65fd684661f49b0ea - optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h 178685f16c79b3f0dd48d1b8fb551d428ab67b68 - optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a32.S be2b439ddca86087d85c34efb54fc3e4cfbfc772 - optee/optee_os/core/arch/arm/plat-vexpress/main.c 390b45a60cc4219e64e58f0ca0ea2890dc31a351 - optee/optee_os/core/arch/arm/plat-vexpress/vendor_props.c cbbb4b7ba94d66daba35e4e8de0e1ea8f3975534 - optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a64.S 1e704fbe287361b0b3f5ce3637b260c8d1740c64 - optee/optee_os/core/arch/arm/plat-sam/platform_config.h d452ceba090437688ae1658171bcda10e43263b4 - optee/optee_os/core/arch/arm/plat-sam/tz_matrix.h e99e2242a257c7200f0fbe85c4e9d6524551effe - optee/optee_os/core/arch/arm/plat-sam/matrix.c 86f20052c0aa65ddfcab873b3b6141abfb4efcca - optee/optee_os/core/arch/arm/plat-sam/matrix.h c85debf71cacdc0e53e262424984cec5fece885f - optee/optee_os/core/arch/arm/plat-sam/sama5d2.h f04b1753cc27916946e5415343e2976328330716 - optee/optee_os/core/arch/arm/plat-sam/sam_sfr.c 23568f555834f144fec9951e708608b0fc1f3e72 - optee/optee_os/core/arch/arm/plat-sam/main.c 9e03ab42551128401c4786a75250b1db1cd4922d - optee/optee_os/core/arch/arm/plat-sam/sam_pl310.c 91fd5dd0e7ed91073e6858e4a603e2028166a440 - optee/optee_os/core/arch/arm/plat-sam/freq.c 05ae55b82f1b86db41cd5dec856b760b9cbac2db - optee/optee_os/core/arch/arm/plat-sam/sam_sfr.h 51975d5a6d4516cacb42fd70885043c1f8b6fbf1 - optee/optee_os/core/arch/arm/plat-sam/pm/psci.c e163a9a58cd5dacad7354b43af80bcc98377198f - optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h d71fe9727d8c848f74ebf421e52d41874966c63a - optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c bfd010647330fd2fbafb08a6d68018496917c18f - optee/optee_os/core/arch/arm/plat-imx/mmdc.c 13e40fd4f55de4dc5467690339cf670d76621be0 - optee/optee_os/core/arch/arm/plat-imx/imx-common.c 584afcf20fad8029781743589f1d8b888d4d7edf - optee/optee_os/core/arch/arm/plat-imx/platform_config.h 6b46c0394b08058417bc2e944755e80f03294068 - optee/optee_os/core/arch/arm/plat-imx/imx-regs.h 52eae24d48e8e56160dd7b94e68bba26eb530dd8 - optee/optee_os/core/arch/arm/plat-imx/imx_pm.h 19f7be18a342945b17601d7b48c613ea1468eaa2 - optee/optee_os/core/arch/arm/plat-imx/a9_plat_init.S d9b0648c8e36c59fdae8fb59cf9f73a55b9bb1f3 - optee/optee_os/core/arch/arm/plat-imx/mmdc.h c35c8cbec5594f84ab070a6f2cf5699a257c9e97 - optee/optee_os/core/arch/arm/plat-imx/main.c adedaaade5c7177a170c74433b126fb1bd75463b - optee/optee_os/core/arch/arm/plat-imx/sm_platform_handler.c 9dd99c00f7ebbed992c4d8e608ab3716943036e9 - optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c 764fa6e4d0b52fc075ffcb78ba6986ed14d1b58f - optee/optee_os/core/arch/arm/plat-imx/imx_pm_asm_defines.c 98e0fc14280969c4814e9bcf1d2d4421c60f5b2c - optee/optee_os/core/arch/arm/plat-imx/imx_src.c 576710aa6118eebca00bfa8024c4f48ad57b89ec - optee/optee_os/core/arch/arm/plat-imx/a7_plat_init.S fd1bb378da6d088df88b2239b006b4abb715d0c9 - optee/optee_os/core/arch/arm/plat-imx/imx.h 658c3b177340e2efe74ac7cfe5a0c688aeadf90d - optee/optee_os/core/arch/arm/plat-imx/imx_pl310.h 7a47d9b9d80c3ff0539ada4663d95c9e7bdac984 - optee/optee_os/core/arch/arm/plat-imx/tzc380.c 6c0a9e819b3e4b156c47a4761eef280bcfd0ab2f - optee/optee_os/core/arch/arm/plat-imx/config/imx6sll.h 2d95ab53312d29b23061b747e96c695708612d8d - optee/optee_os/core/arch/arm/plat-imx/config/imx6qdlsolo.h be59b37f3baf5d18ad949415e77e4c09a1a2ebb3 - optee/optee_os/core/arch/arm/plat-imx/config/imx6sl.h 93a6155f6f294fddb38ac1947f5dce49d68f71d5 - optee/optee_os/core/arch/arm/plat-imx/config/imx6sx.h fd5c0094f7478ca392710675be72762df5522ebc - optee/optee_os/core/arch/arm/plat-imx/pm/gpcv2.c 383f57d643594c46ec3f7a0b6342fb8d976e6566 - optee/optee_os/core/arch/arm/plat-imx/pm/imx7_suspend.c 68c57702c19d7b9cc0d9a7e5d39968c182cb2129 - optee/optee_os/core/arch/arm/plat-imx/pm/pm-imx7.c 8713d58f831e01a4cd24103e702ada984ed748b7 - optee/optee_os/core/arch/arm/plat-imx/pm/psci.c 245cf6f7ca67610e492c7b95b945f66d2b7829ee - optee/optee_os/core/arch/arm/plat-imx/pm/psci-cpuidle-imx7.S 640fb698681bfca764520cc693b288ff48625deb - optee/optee_os/core/arch/arm/plat-imx/pm/psci-suspend-imx7.S 034c5104ca928cc8bd7b6a3358cdcd84136211bc - optee/optee_os/core/arch/arm/plat-imx/pm/cpuidle-imx7d.c 0ab3222c89bd29af45b6838cb1126597ea378f7f - optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp.h 1fc0e208fd97087384233268cbda1cce852b796b - optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h 46dc26d459e4a5adb2a904c7f6b4c5ef4546ab75 - optee/optee_os/core/arch/arm/plat-imx/registers/imx8m-crm.h 55f6aaaf23e460dbfd791e81c80dd5de5d3bfbfa - optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp-crm.h e9be4cf1ba19e2e02c3e7a89623e1c67e49737ee - optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h b355b4bb04068d735c1faa8039e1ade0d88d60d2 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6-crm.h f93579c365bf08fb597488903040c0b92041517d - optee/optee_os/core/arch/arm/plat-imx/registers/imx8q.h 3931a5db91c6b50993dba75c296966e3e9416994 - optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp-crm.h c418919325c1927ee3ba3fdc8043d323e630c7e1 - optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h e8e364071825472444c0223168929efe4a9385d2 - optee/optee_os/core/arch/arm/plat-imx/registers/imx93.h 1a557c230d0c95aeb775b8f02c4a5294b829132e - optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp.h 443dd0395348c2b831b9ea34e1d0df567e22dfa4 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6-dcp.h 7df27071dbcbeb1f977a02e17445136fa22a3749 - optee/optee_os/core/arch/arm/plat-imx/registers/imx7-crm.h e7cc05f8f313444c45b38132967f4b1393085a94 - optee/optee_os/core/arch/arm/plat-hikey/platform_config.h fd0dd2e67f5f756333f60c8a6f150e5605c8259a - optee/optee_os/core/arch/arm/plat-hikey/main.c 9899b78e83cfa336552e36d0be06113de438bf15 - optee/optee_os/core/arch/arm/plat-hikey/hikey_peripherals.h 79b3882bc2b3c0bf0492d2dc0385354668138f7b - optee/optee_os/core/arch/arm/plat-hikey/spi_test.c 1ec6602a1f0bc43336d5045adcf92c45c39c4423 - optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h 1afa2f2d04c2c6ba8be7c4d06ef97fefbb03fad3 - optee/optee_os/core/arch/arm/plat-mediatek/main.c b1b7de5b516440a686f80083730d8a139d7cad97 - optee/optee_os/core/arch/arm/plat-synquacer/synquacer_rng_pta.h 596136d3b40cd1cbae47d4ed48a5b4d246e08dfe - optee/optee_os/core/arch/arm/plat-synquacer/platform_config.h f7a4aebaabf328850a24fb10ee67d11494346bca - optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.c 0ed37a1910492656246f85705f9b93df490f10eb - optee/optee_os/core/arch/arm/plat-synquacer/main.c 0b99d0c7135e7f0002ef7a51d63461307e66203b - optee/optee_os/core/arch/arm/plat-bcm/platform_config.h 92cb86eafac038fc02be252efc14c3e3316f27af - optee/optee_os/core/arch/arm/plat-bcm/crc32.h 3d4f18ba7a9634be9a46f900264cb0132fd65654 - optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.h b867c067653be4032105afc77ee562740d8d241e - optee/optee_os/core/arch/arm/plat-bcm/main.c 435d5321e6d484c095ede7a5b320ec92fddb3025 - optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.c db3ddcb5c48ff30c64e8b561ed5300400d67bca1 - optee/optee_os/core/arch/arm/plat-bcm/crc32.c 84db75f5c982cafdce7ebdb1f5080253cc0f15d7 - optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h 105fcd115c8f37f13c3f1617c6e564dce1a1a50f - optee/optee_os/core/arch/arm/plat-stm32mp1/reset.S 02204c43ef491bc5768cc1dd754c14e96a79c402 - optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h 0347bb1185d401c31ba23382067c63801859b98a - optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c 41fc0d480726ccac287c2341b62956a102d2b134 - optee/optee_os/core/arch/arm/plat-stm32mp1/boot_api.h 374484f26498072118ccdcb034fe90dba4c5ba13 - optee/optee_os/core/arch/arm/plat-stm32mp1/main.c 085787300ce325b32fffae16ae2889f02e925f20 - optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c 4cd706376b2b8e9f29529251f6e8dd0f97b45a2d - optee/optee_os/core/arch/arm/plat-stm32mp1/link_dummies_paged.c 70226b5b77dd3722328a07eb44802b30f9c7926e - optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c a1238faa3df41c0c66412e3b032255e1cd4988eb - optee/optee_os/core/arch/arm/plat-stm32mp1/scripts/stm32image.py a3ac99fd762c9216188d37d084dd70008fbe1199 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h 61bf4808eef711cc1f7e49f85642e691865fbac5 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h aba3134290522c123b965727423536367134df31 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c 36a643ca9888123735aee8f3a13fac3544304bdc - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h 5ce02d8d7ff756a903800fa1b2634052ba695738 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c d51b20c506376c9a4d0d94786e6de3d46e871540 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c 976f6cd43eb43bf7d8923851c1305a326bd1180a - optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c 536663cb01d75d67a4021fe8314c5ae79909dbd8 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h 4e92814caf4d208f3424697ce4a54cbceba75632 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c d335d9bb50b2453d365ca88f3f18520fdd0a1086 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c e7ec6cb3b0018db5664ccd87d3ab1529e5d5713e - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h 11ce785f6bdd56fdc8b32c6c2174a9b49b96b230 - optee/optee_os/core/arch/arm/plat-uniphier/platform_config.h 84c6815e58e7c13740a2e365505da1aa9d87a325 - optee/optee_os/core/arch/arm/plat-uniphier/main.c c043a9411306559a982b5d09ae419821ff026bd0 - optee/optee_os/core/arch/arm/plat-uniphier/kern.ld.S 012cc9cc5cd4d1213266d657558cd6c1fb998e1f - optee/optee_os/core/arch/arm/plat-hisilicon/platform_config.h bf4be1dd46e6278e5b9b8b6a40b710d90007d915 - optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S 114f50b1c0140361479b38126c3cc1d0607a3f91 - optee/optee_os/core/arch/arm/plat-hisilicon/main.c 1e0932868e4fc72946b4b12a3650c383dcdd7a79 - optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100.h 92415c6775326559b08df1d2a9976b3e1ebb0a72 - optee/optee_os/core/arch/arm/plat-hisilicon/psci.c 43dcd40dee8c1bca63526b7590768c430e2b9eb4 - optee/optee_os/core/arch/arm/plat-corstone1000/platform_config.h a955b4ec9fb79d3fd9dcab27f3d88534ba669c6e - optee/optee_os/core/arch/arm/plat-corstone1000/main.c 9421c26b6ce38f1d5da0e2f431afc0cab732f0e6 - optee/optee_os/core/arch/arm/sm/std_smc.c 0fbfd45981f9512d688a49c32add4297540c689e - optee/optee_os/core/arch/arm/sm/pm_a32.S 615d9401894c37dec5e5ebe9bcdb678df854564e - optee/optee_os/core/arch/arm/sm/psci-helper.S d15ae1ce071edbfc8d4d4de7c944cb1d8712136e - optee/optee_os/core/arch/arm/sm/sm.c bbd1df35108340d6d4e6179926681fb794f8ce12 - optee/optee_os/core/arch/arm/sm/sm_private.h 8a9cd4bad5748dac76110944be1fb3442e98b2f6 - optee/optee_os/core/arch/arm/sm/psci.c 45960371e7a1224c4d067ff3c172952b7d616998 - optee/optee_os/core/arch/arm/sm/sm_a32.S 79b02c9017b471e73d8c11acc7f91278ec851f2b - optee/optee_os/core/arch/arm/sm/pm.c 2701a5021cec550314803b83b43e5a3fa6f6aadb - optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi abbe0e5a7c63995c207b1995649e3a6ed6b4221a - optee/optee_os/core/arch/arm/dts/stm32mp15xc.dtsi c07147cb14bc871e069f3be8248fc2c79e311949 - optee/optee_os/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi d23af59b64d5380f6f9c8ca37a1a5b1af3e9f93c - optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1_ek.dts 9be7fd7b5c30eae1dc855f6bfca353c455dd812b - optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts 5c329735e2a8eb85255d6ddd7a56064d03034cb2 - optee/optee_os/core/arch/arm/dts/stm32mp151.dtsi 1985ea8670dc7c7937541f6b2da9c30c41ee000d - optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi c8ec256ae55cb6c849aa51624b9974259884b159 - optee/optee_os/core/arch/arm/dts/at91-sama5d2_xplained.dts 2701a5021cec550314803b83b43e5a3fa6f6aadb - optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi 0f41a6ee8e489bec0d79a976edb540945506d498 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi 9df393dc1bdde2c8ab9deca10271f9135234a752 - optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi c801e4c35f00786835f0cd63b71559a146086866 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi 41aa3da18dcb49b316aefc9ad5eed7dc2664dabc - optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1.dts 794650f14bc79f9ccc2033efdc81da79623d351d - optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts 0cc38427ae1b225d88d000f9438b7cc34e883b30 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi 6510b2294cc4aeb2601cce6f17cffc6eee8c58dc - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi 8fccbbae61ee6f2694b88563c096e640101dae55 - optee/optee_os/core/arch/arm/dts/sama5d2.dtsi ce82c06ac99261e680a62585d80c90e9dfe941fb - optee/optee_os/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts 6ed7397e2751cabb21fc7e87b53983b9117d2e26 - optee/optee_os/core/arch/arm/dts/sama5d2-pinfunc.h e28863664f28385599bf66b2a690760e4c1bd63d - optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts 6c18e9690a909c9b4898d1d609cdf3874e22d19a - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi 361479ac7684841706aca2fdb4c3d2c9f8e0e13e - optee/optee_os/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi 94f010962fb67b20e43e2f44cb3f317f624d91e1 - optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts d26bbcf985b7523a6af715be4feb22233be74ba5 - optee/optee_os/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi d7230a1568081b9a39b151bbe38f188691b2b84b - optee/optee_os/core/arch/arm/dts/fsl-lx2160a-rdb.dts b318d72ed3eee6e4bd7d8ecdb5b1eba8dfc31f89 - optee/optee_os/core/arch/arm/dts/stm32mp157.dtsi 9dea507c72c9eec09336578711a432b198478a56 - optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1.dtsi d6dbda8b14af74b3a63db810c4c4ed53bfb097bc - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi 0c1276612681bf9f22517513242e678c22551542 - optee/optee_os/core/arch/arm/dts/stm32mp153.dtsi 194fd8067d397ca409c3380341a5de0277269382 - optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi f8387a2601ba505a39c886a752ab25e6ece458de - optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi 8d99ad09575f0e8344e4caa6f4ac16f66108f22e - optee/optee_os/core/arch/arm/dts/stm32mp15-pinctrl.dtsi 676f90d7c25eb035af4475d83d6e355f07ac0634 - optee/optee_os/core/arch/arm/dts/embedded_dtb_test.dts 9f93f18baccbb7718af6c571e70dfecb3529b694 - optee/optee_os/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi 23b592b2e03dead1636f2110cd64531ec92bf807 - optee/optee_os/core/arch/arm/dts/stm32mp133.dtsi ad3b5f3ede872c44e014eb6ca5a69329195968a6 - optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts e793accc60529af1c41651063de57ef9cd0a0b5e - optee/optee_os/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts 62934ca38185da79af035ba4a82f62ae3a33f4ac - optee/optee_os/core/arch/arm/dts/hikey.dts 7098d09c9fd4f2accc2e23713ad9a3b676026ac2 - optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi 7c4d0d445cc32c31b4a4b2a2c01cd773605e3494 - optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi fb4be0e25bdca79fcf443034897f81e669e42d88 - optee/optee_os/core/arch/arm/dts/fsl-lx2160a-qds.dts afc997b206bbdc6c60cd9f08308b7b53832eac0b - optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S 933f5b3256795b2ffea6b7b93d75365f865599b3 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a32.S 09cb511f6b571c162ae284911b5af9c702dd5130 - optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.h 0cd13267dd6db52ed1ff3742dcb7adb15bdff8cd - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.c 913da3b19e7cc7244ff858f2bace0bc38736fb06 - optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S fb5f716381766749999f0032bf39f39bf88af12e - optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S 6e006d07e0e25f49c5af73e0e522f6f97963275c - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_aese_a64.S 47012ceb6af70d59a7666ca551814aa811efe9e8 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.h 1ab432ea10e0e0edf03b0ce17bb5277fea163578 - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce.c 9c1f14fdc223c00af03fe8b922a520419b7fd0b9 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce.c cf714bfd8657a2fff8112b3b94d7e476d51e2e60 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce_a64.S 2c3ba8b73e012b48da6c8ff12c635f8fa109e5a8 - optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.c f59a39b271b322f5bdd6baebdedb3ef701a78b02 - optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce_a64.S 0b84c15b4796a2a23a095ae2d6d037677510760a - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a64.S 2da4cbb016071dacfbbd7c99799a27ad6d8c56a7 - optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce_a64.S d857b4b442486f2ac052ee687cb6d6f424843433 - optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce.c bb50a2e7fffd5945ce8214bf57ad9d55135b46c0 - optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce.c 45797af469d803907920fecce84f86fbe684a40c - optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce.c 02305ae36a17490cecdc906c0970e8625ea9e6a1 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.c cb5a3413393627c5fb4626c2315e2e12bf01abf1 - optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a32.S 0c1913711dd52b93cfe5d2d476a3a050a5bae97d - optee/optee_os/core/arch/arm/crypto/aes-gcm-ce.c ad5becb659037cf49bdc0fccc768675b2ce55068 - optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce_a64.S f7d7763974a8359b3d84d7c848542872c9a1a1b4 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.h ad9a80c4d43acd03ae5d27e14df6dfee3abc4e05 - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a32.S 56e9da14883d74e8eca3a4c7737185590cf14c08 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a64.S f413d0ba2e04b6ef2802475a9132687b2f19237a - optee/optee_os/core/arch/arm/plat-ls/platform_config.h cc663051dbd6ba5fbd15bd4409b7ba732dcdc025 - optee/optee_os/core/arch/arm/plat-ls/main.c 095caecf26786efe69779aab593c67447f44b9c2 - optee/optee_os/core/arch/arm/plat-ls/plat_init.S 43ecf7e39e7a28c27b7b79a3615e3614939834bf - optee/optee_os/core/arch/arm/plat-sprd/platform_config.h 40b290a479f2ef757ef2505ac996b953a69ca654 - optee/optee_os/core/arch/arm/plat-sprd/console.c 259bdb7ec46936003362575b273afd3f3a9981a7 - optee/optee_os/core/arch/arm/plat-sprd/main.c 92467f9b57e8dd5b4962ccd05ea4929ab2dd6c4d - optee/optee_os/core/arch/arm/plat-rzn1/platform_config.h 1b82881f2b80531fc7743309c38c8e9370969ef1 - optee/optee_os/core/arch/arm/plat-rzn1/rzn1_tz.h c9a02f7b7f7b87ffbcb1b4817f13f0a9ce102e7a - optee/optee_os/core/arch/arm/plat-rzn1/rzn1_regauth.h 6a09760ea59ffdf2d2d519d19a27687600c51a08 - optee/optee_os/core/arch/arm/plat-rzn1/main.c 48ef8147e12f826d7e87c67d7c12e3932d317546 - optee/optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c 245d63c49ace44a4319be3f8b9882e520bf67448 - optee/optee_os/core/arch/arm/plat-rzn1/psci.c 776215d1f8598a5514e759d70ae400a8101f835a - optee/optee_os/core/arch/arm/plat-rzn1/a7_plat_init.S 176317554a2541fa4a9d6504dbe52227bdcb5083 - optee/optee_os/core/arch/arm/tee/cache.c df18a9464597e6dbc2844ec1e5d735db00c74f37 - optee/optee_os/core/arch/arm/tee/svc_cache.c 9b3b72c3d28cd1ef84a46454ad1d2d20550608d2 - optee/optee_os/core/arch/arm/tee/entry_fast.c ebfaf4c6f38995b655230d2d5e3981d0ab12f8b6 - optee/optee_os/core/arch/arm/plat-d06/platform_config.h af303d7bdec46d72f8dc191b59424ff83ab7e2ed - optee/optee_os/core/arch/arm/plat-d06/main.c ca3077b3f16c93f5d5350d4b21c08770138bc3af - optee/optee_os/core/arch/arm/plat-d06/core_pos_a64.S 8694a8f4be2551b1bf8f1abcb17284a8b202e5af - optee/optee_os/core/arch/arm/plat-zynq7k/platform_config.h e8a97315a58b289054e1f3fb5418cba746b5633e - optee/optee_os/core/arch/arm/plat-zynq7k/platform_smc.h 19b5c8130f55a17a4ee903fba47f5bbafe9ac918 - optee/optee_os/core/arch/arm/plat-zynq7k/main.c 55fee8bf238c661a2f59118cbea5d8fca29471f3 - optee/optee_os/core/arch/arm/plat-zynq7k/plat_init.S 94a132cb905aa39756cd3bd0c4cd0bb955893219 - optee/optee_os/core/arch/arm/plat-amlogic/platform_config.h 397906387ace258a7976d69aaba14ef9a4cde8c4 - optee/optee_os/core/arch/arm/plat-amlogic/main.c b1793c2149008cfc5c242a3fbbfcdfecfb082b4b - optee/optee_os/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py eba718605aa45932a4b80632aa65d8cb35dc2b22 - optee/optee_os/core/arch/arm/plat-versal/platform_config.h d0493efb594dfef8ab3869060ea8de26d977ddc4 - optee/optee_os/core/arch/arm/plat-versal/main.c e2b43db2de0208697b4c88f2f0562d58a4b0b2fb - optee/optee_os/core/arch/arm/plat-d02/platform_config.h 9581f5fca967939ce5938afcc66f47c28a64b41a - optee/optee_os/core/arch/arm/plat-d02/main.c d4139567b62848e1c43b6759cd767e034e10db73 - optee/optee_os/core/arch/arm/plat-poplar/platform_config.h 2ce2abb04e66b937356a0863cb1bdfec5c66673a - optee/optee_os/core/arch/arm/plat-poplar/main.c 8fa033ec5237e06aef907c0f641f208388793c26 - optee/optee_os/core/arch/arm/plat-poplar/hi3798cv200.h 59bad93e3d397c859768a3a8f7e46ad98f2ba3d4 - optee/optee_os/core/arch/arm/kernel/arch_scall.c eafaba99cd9d60eacf4a3babbd16c0a6daa4c283 - optee/optee_os/core/arch/arm/kernel/thread_a32.S f9a92f478e19fbf1059649d6208b99ca6613b311 - optee/optee_os/core/arch/arm/kernel/cache_helpers_a64.S 44470d3e7b9cdbed041ae13408e647edc645aa74 - optee/optee_os/core/arch/arm/kernel/misc_a32.S 96fd19a3b4462b4a6bf63b89dd394fb644df9cb3 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S 705b09bc40f35f83a32b350e673c59728258e250 - optee/optee_os/core/arch/arm/kernel/stmm_sp.c d347c9bafe24140b9717de8891d9659b01333e07 - optee/optee_os/core/arch/arm/kernel/arch_scall_a32.S c10de505f0de2bc6ced1f9349ecfb51f0c5d306b - optee/optee_os/core/arch/arm/kernel/virtualization.c af8d99e369132adac450a89f4b07fbbada85156d - optee/optee_os/core/arch/arm/kernel/misc_a64.S b4d64fa787d883488032c460e9bdd9219c8b7e6b - optee/optee_os/core/arch/arm/kernel/link_dummy.ld 09ae96d24a26b79da3b4d74657264ac8fa57e7ee - optee/optee_os/core/arch/arm/kernel/timer_a64.c 6253299ed089d1eccd655faf0ef4921a3b090d0c - optee/optee_os/core/arch/arm/kernel/abort.c 26f9cf452d8776f7612c50294f57057815bb3dc6 - optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S c98d9153adf3b0cfde1af189f873d59ff8b88af6 - optee/optee_os/core/arch/arm/kernel/link_dummies_init.c 8ebc782c56e8a49cbb1a1842f396de645f1f46a7 - optee/optee_os/core/arch/arm/kernel/cache_helpers_a32.S 6a5fe12b6846231d6aa70e92f7b4220683c41c24 - optee/optee_os/core/arch/arm/kernel/entry_a32.S cbc0913df63d07ee9b46ed402d9d9cfb57dc8f23 - optee/optee_os/core/arch/arm/kernel/thread_a64.S 333d53646d0a8f7c4b5f3f5cecece5725a8f0dde - optee/optee_os/core/arch/arm/kernel/asm-defines.c 63ea63ab5d506208970d6f5b8738ee82850aefe3 - optee/optee_os/core/arch/arm/kernel/unwind_arm32.c cff200d2106d26baf930f16e6caa8634adebbe08 - optee/optee_os/core/arch/arm/kernel/vfp_a64.S 056cac06f5cc8f43b14154ddbf1cd5d8c382ab74 - optee/optee_os/core/arch/arm/kernel/tlb_helpers_a64.S 000f63612d84b18bd33c3bb7a7ad17308e32b296 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a32.S cfe9209c0f08602f20df8752df4016c257305627 - optee/optee_os/core/arch/arm/kernel/vfp.c 9a79a97751b816a6976bd36948874edb22b17563 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c 23d2ba34a5f3de4b7c12134cd6ffcb8e4957e672 - optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S 24e1db339b48a73b6aaafcfca9047c7855896faf - optee/optee_os/core/arch/arm/kernel/rpc_io_i2c.c c591321644c6fd32d600a9a797daf4cdc48647d2 - optee/optee_os/core/arch/arm/kernel/spin_lock_a64.S 9e422c03938a8b32edd015a653d5dac29880a5e2 - optee/optee_os/core/arch/arm/kernel/unwind_arm64.c e6509a63f63d52f3595d0f5b65346f6b569b8dcd - optee/optee_os/core/arch/arm/kernel/thread.c 79bd325bd306a65c018341c52386b41e92028f08 - optee/optee_os/core/arch/arm/kernel/thread_spmc_a32.S 5ca340af84791488b272c18d84af4e49b1c94f7e - optee/optee_os/core/arch/arm/kernel/tlb_helpers_a32.S 623bd09a42ef354ab3d4335998660c788d656cb0 - optee/optee_os/core/arch/arm/kernel/thread_spmc.c 4d98d1a3c20f4e424fd4140949c712f1769daf93 - optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c b5ebdeae94cfe7fd7a32f0be15e8a28b230cd175 - optee/optee_os/core/arch/arm/kernel/tee_l2cc_mutex.c d6c09e6c39b889a25fcb82340f1725f9d0427d59 - optee/optee_os/core/arch/arm/kernel/arch_scall_a64.S 6ab260ed8b0c118bdef56c78beeaa3887daf4059 - optee/optee_os/core/arch/arm/kernel/boot.c 170f9fade8d4cfd3805f2aa2383b7f3d358507df - optee/optee_os/core/arch/arm/kernel/idle.c 99dbd4c6ced9d21fbf6db2c3e7c6755d8c6bce28 - optee/optee_os/core/arch/arm/kernel/vfp_a32.S 9d0bd8480809254b743bf3d766efe7c3cdc70034 - optee/optee_os/core/arch/arm/kernel/kern.ld.S 289f0d3d108c7e83aedd70c9b92133b7a036f000 - optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c 599bd7fb683e3e1c0eddc71e66e5eb979e8e7c28 - optee/optee_os/core/arch/arm/kernel/spin_lock_a32.S da85ea618bd809353d036a244165f159f124bfa6 - optee/optee_os/core/arch/arm/kernel/entry_a64.S c5547aac70334a836d7a0d7a3711e972962679a3 - optee/optee_os/core/arch/arm/kernel/secure_partition.c a3d562edc0d696f64d77e9c96d86c9a88451b5a1 - optee/optee_os/core/arch/arm/kernel/vfp_private.h b1157e1c8f98a0bee2b0edcd3e766193dd29a126 - optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c 4eb9e4b6f2b6b8f595acf22a683d831fee0ef40f - optee/optee_os/core/arch/arm/kernel/unwind_private.h 784a5cea3b2741f04facdeaf7bfac0e093630875 - optee/optee_os/core/arch/arm/plat-stm/platform_config.h fd20baae7413cd701b88ba6dfeb2a294a9eeb452 - optee/optee_os/core/arch/arm/plat-stm/rng_support.c b6fdb7e3086bc494442508848064feb6c72f2ca3 - optee/optee_os/core/arch/arm/plat-stm/main.c bdd38a0220aac82b0aafa97e8f1993cb27e0ac1f - optee/optee_os/core/arch/arm/plat-stm/tz_a9init.S 4e93d8d25766b05b285896a4944c227f8b4da442 - optee/optee_os/core/arch/arm/plat-sunxi/platform_config.h 46ed9632901e137bb6316c0586d6982df7101499 - optee/optee_os/core/arch/arm/plat-sunxi/main.c eaa619f9de58ee047ca541b4c238b2afb5b83b6a - optee/optee_os/core/arch/arm/plat-sunxi/psci.c 2399244b8020942c1b3a3cb924194e8770560051 - optee/optee_os/core/arch/arm/plat-sunxi/plat_init.S 728f6a99ffec19cfff92195c3e68080f0dcfacbc - optee/optee_os/core/arch/arm/include/arm64.h c3a08b120460a25968597b72b59a0634e94dd49b - optee/optee_os/core/arch/arm/include/hafnium.h 55298b41d3e8800e2aeebd746e9e1371142fbd6e - optee/optee_os/core/arch/arm/include/smccc.h 6b7dc1082fa7e1b101e95c0588ea1b1224cfe5a8 - optee/optee_os/core/arch/arm/include/ffa.h ef7bffd960c06d3d1f3248123500188bfb08cd13 - optee/optee_os/core/arch/arm/include/pta_stmm.h 3ed813b9b977510b9907819fa2443a03eda8ca4b - optee/optee_os/core/arch/arm/include/optee_ffa.h b994483c8394f9eef531d2c379fd9ca5a1b60fed - optee/optee_os/core/arch/arm/include/arm32.h 7003b864c28695954a41184611e55102dc8e7500 - optee/optee_os/core/arch/arm/include/arm64_macros.S 81aefd662cc3b7d6278de360ede9cd9545c3f7b2 - optee/optee_os/core/arch/arm/include/arm.h ff294f026e09453cbd1ffb3cbc764befc573676c - optee/optee_os/core/arch/arm/include/arm32_macros.S 1cea08afcf4cab7bbff31ea3666c5360c4c03498 - optee/optee_os/core/arch/arm/include/arm32_macros_cortex_a9.S 6bb78d1526e06ec55a411f86926c1feb69fbdff8 - optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h ffc908df97e9fd07da49d5df02ac4da1bb8b6d13 - optee/optee_os/core/arch/arm/include/mm/generic_ram_layout.h c0f44a85d8dc7ed7ee51a4395e3456f05265a0c1 - optee/optee_os/core/arch/arm/include/sm/psci.h 1570da79c88e5ce844afe3665b7835f325fd5594 - optee/optee_os/core/arch/arm/include/sm/teesmc_opteed.h abb9582e539a959b54458d29c0351dcc9b3a6e0c - optee/optee_os/core/arch/arm/include/sm/pm.h cabb67de891151838399c123a02c367be10dd244 - optee/optee_os/core/arch/arm/include/sm/optee_smc.h 7f4e2bd9aea7292a7cb66e4be4ee5e118c3d5c3d - optee/optee_os/core/arch/arm/include/sm/teesmc_opteed_macros.h ce5b9f00424203fbd6eace4a72a28b9f82658bb1 - optee/optee_os/core/arch/arm/include/sm/sm.h 51ee5fce8f3aa7306e4e111ebf920128f72ce1d8 - optee/optee_os/core/arch/arm/include/sm/std_smc.h 5a07f5963ad453f3de5e43330199b116240912f4 - optee/optee_os/core/arch/arm/include/crypto/ghash-ce-core.h 71f59143dc113e32eafbaf32749a68b80304cd37 - optee/optee_os/core/arch/arm/include/tee/entry_fast.h 1713fc8bf0923bc7dfbe82b8a445b10d9848bdc2 - optee/optee_os/core/arch/arm/include/scmi/scmi_server.h d567e405f7457e2a5a572391254b503cfc11712e - optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h 109240ea4c259327060af80955d32015e628c786 - optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h 0777b5e2b4ca54beddbbf59fed4ea20936487e3c - optee/optee_os/core/arch/arm/include/kernel/tlb_helpers.h 03a55634fef67a071aa1f0f3cd89ba24743675b0 - optee/optee_os/core/arch/arm/include/kernel/misc_arch.h 72a3f7bc0e57ea00dce12cbb73e41a20f90fbfdc - optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h 37af9222c63c149803c61dab6a9f91a50be335d0 - optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h 9284944a0055f114d23e121c972c412ae97b7f7e - optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h b95d779051d2b0e70152491dc1046ef721584d7a - optee/optee_os/core/arch/arm/include/kernel/stmm_sp.h 2360143179a1f2cfd4a3cbbbc03448bb6790d698 - optee/optee_os/core/arch/arm/include/kernel/arch_scall.h 59802332e69d96bb3641667a395d02f3c2fcd82f - optee/optee_os/core/arch/arm/include/kernel/cache_helpers_arch.h 0607a5b2b01b53cceee3b47ccee320d2fb27bda9 - optee/optee_os/core/arch/arm/include/kernel/vfp.h b65be7335b7bf4f535466fc90543e45ecf9f8733 - optee/optee_os/core/arch/arm/include/kernel/secure_partition.h b956d886be34a123153e72af01e2f4f4cbfc2dcf - optee/optee_os/core/arch/arm/include/kernel/delay_arch.h 84b9ebb0e017dd1d8594f810924e78a79a73aa09 - optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_def.h 38b584ff94d19eb4ee5a09924512512856c7946a - optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h 9e791243466051df2420efe6b2a0b1c5354fc679 - optee/optee_os/core/arch/arm/include/kernel/thread_arch.h dd54ce3d620f2b22180ef201aeecf74b5b4480ad - optee/optee_os/core/arch/arm/plat-rzg/platform_config.h d3d7fc01ca1db9ed9c42923fc3abf988ee8f35e0 - optee/optee_os/core/arch/arm/plat-rzg/main.c b3d21a1017a2f66d52d2f6da7f671715aba08021 - optee/optee_os/core/arch/arm/plat-rpi3/platform_config.h 84b7b56e93417a949b15de5348e3b01f21ccd448 - optee/optee_os/core/arch/arm/plat-rpi3/main.c 49dbe1b862ab1676a3186ddc9f6c7650820902d7 - optee/optee_os/core/arch/arm/plat-totalcompute/platform_config.h 8c7bb877e78282e8229e60073e1b5416c9a0d122 - optee/optee_os/core/arch/arm/plat-totalcompute/main.c 00e4e12466db95649e17c7dce132fd03e23b837c - optee/optee_os/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts 8cf15d5f8508083811e9df9e81f5de5d6f6861fa - optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h 22c8392cd3c7d3efdbe4ab3b68a650710be862b1 - optee/optee_os/core/arch/arm/plat-zynqmp/main.c acb5b7a67e6e3a2c8309d3b5cd972a643437c4ad - optee/optee_os/core/arch/arm/plat-marvell/platform_config.h 1789c7a402691f5c378f2108a0ffddac22926472 - optee/optee_os/core/arch/arm/plat-marvell/main.c 382e9ecd3c29e2e17e189e59fd3427c1c682e199 - optee/optee_os/core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c 5277b6c495f09f7293c54198cbee638bbfdb0254 - optee/optee_os/core/arch/arm/plat-marvell/otx2/core_pos.S 4ff87aa9e6aeaf3d88e17943ead649009d0b0fb2 - optee/optee_os/core/arch/arm/plat-marvell/armada3700/hal_sec_perf.c e5ec049ffef670a29b7cade4d9d9f96abef549f6 - optee/optee_os/core/arch/arm/plat-rcar/platform_config.h 4e0482b88d52f8a7d6adf974d0e5015f13872f65 - optee/optee_os/core/arch/arm/plat-rcar/hw_rng.c 40b8edfff755528bf204681a8f80de74a95a6673 - optee/optee_os/core/arch/arm/plat-rcar/romapi.c b713d037582ce7c9f21402a91665b067ed931ff7 - optee/optee_os/core/arch/arm/plat-rcar/rcar.h 8e4974b5fef12aa6421a66df3916ac232029a809 - optee/optee_os/core/arch/arm/plat-rcar/main.c 9ca9f50ac43c9276ee67375c8e915f0827e349d9 - optee/optee_os/core/arch/arm/plat-rcar/core_pos_a64.S f8a2662937d568146b977cdedf2e268e5b1f6b6e - optee/optee_os/core/arch/arm/plat-rcar/romapi.h 15d328d6ef35c2f6a4c4f5a69f4eb2a571802c1c - optee/optee_os/core/arch/arm/plat-rcar/romapi_call.S d838c4f3e30ef56f81d51a7b6ef1a31df3657c31 - optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h 82e665e55b85c8f52413d062164e161349d25bbd - optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c 6631e40f0ad62f389ac0fc0c59e142b9313bb246 - optee/optee_os/core/arch/arm/plat-aspeed/core_pos_a32.S 4b7308420adcb67b60e528f1beab6c68377d6e2a - optee/optee_os/core/arch/arm/plat-tegra/platform_config.h c19a206b427ed76090247d074c9b81a0c6dadfc4 - optee/optee_os/core/arch/arm/plat-tegra/main.c 1046d8e53fbfdcc9ffd8a63a012cccfb40cafacf - optee/optee_os/core/arch/arm/plat-tegra/tegra_common.h 798efa99d464a96c2b70639a3c25ba14f618c29b - optee/optee_os/core/arch/arm/plat-tegra/README.tegra_secure_storage 608a97cee50965f940169862e6754dd17612fadf - optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a15.h f185f9e1ea859d9f4233cffc8c78fcbe72e4c090 - optee/optee_os/core/arch/arm/plat-ti/platform_config.h 2a0bf39e0ef3f1dfa764058f0142b54a53a92006 - optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a9.h ee95c68b68df1476e39ee0a9d3d4f3f1053168e8 - optee/optee_os/core/arch/arm/plat-ti/a9_plat_init.S 233c224aabab101937a19dca5c2de23d699eea8b - optee/optee_os/core/arch/arm/plat-ti/main.c 537927d745de820a0b09ef12a56515a53e68bcef - optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a15.c c3c107d238f7f96e38416cbd2ce783cb5c5231be - optee/optee_os/core/arch/arm/plat-ti/ti_pl310.c ec14532de7ea2afbf4bb14220372faf052e0d77c - optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a9.c 5222bea7254df96932e51593a9aec12808fe2584 - optee/optee_os/core/crypto/crypto.c 6ee664faf892cf6eb54780694431dbc599714a4c - optee/optee_os/core/crypto/aes-gcm-sw.c 5e7555e339aca88d6573eef4844fe96171e073ef - optee/optee_os/core/crypto/sm4.c e68ca1aeee7c839ed6427892eba453b827fe73a5 - optee/optee_os/core/crypto/sm4-ecb.c 057545a9e027cdd9daa7be1500acbb767b134a5a - optee/optee_os/core/crypto/rng_hw.c 82c796645d5446d81b6013ad6338920da67f8ee6 - optee/optee_os/core/crypto/sm4.h 3c8f23a338eea10aca5682c64d8a12902fc433f5 - optee/optee_os/core/crypto/sm2-kdf.c 5a46f6fc2ccfeff927d3588c22e667102497a4ce - optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c be1aa6aee3798fdc77ebc0a6b37bf5a80fc3baee - optee/optee_os/core/crypto/sm4-ctr.c 35204fa717049aa26af2abef06d5466dd22b09a0 - optee/optee_os/core/crypto/sm3-hash.c 2bfc17f9e38fa5fd9c637a5cd1ddcce6300ced48 - optee/optee_os/core/crypto/rng_fortuna.c f5e19ab8d6191ffddbd796f4b194c1b9fcab79b9 - optee/optee_os/core/crypto/sm3-hmac.c ed4f8a199dfc091202a84e729efc08be8166e573 - optee/optee_os/core/crypto/sm3.h 2e625c76a0a14b6b74d7b3be0b8af4e28516d53a - optee/optee_os/core/crypto/aes-gcm.c ec9b32fd9bc56871bc638975a31eb271543b4753 - optee/optee_os/core/crypto/cbc-mac.c e73ae6d522f149d7ffc117d3f026bd44fcd262c0 - optee/optee_os/core/crypto/aes-cts.c 8a9f6567ac8b3d0894830f0876d17d71e94435e4 - optee/optee_os/core/crypto/sm3.c a730ddd73aac7bf7e2f4530cb84b4139920cc30e - optee/optee_os/core/crypto/sm4_accel.c 4a9aec205bda6db9f341b00e62940610c4e3e728 - optee/optee_os/core/crypto/signed_hdr.c 7b6658854eec61d103f730922493a99440ca594d - optee/optee_os/core/crypto/sm4-cbc.c 5e36787d311129f8c3649eed00a7bc54de3dc471 - optee/optee_os/core/crypto/sm4-xts.c 8f90f483de2c041395379c1d91a3cd1739dbd6b8 - optee/optee_os/core/drivers/pl011.c e0f77456c7a5e485619186caeaf812b3dc8eb572 - optee/optee_os/core/drivers/stm32_etzpc.c e241e2600db481b9c897bc48b71104c3aaa5bbbf - optee/optee_os/core/drivers/bcm_hwrng.c 45fe58e31faea84f641347c7bd70e426567d781b - optee/optee_os/core/drivers/serial8250_uart.c f2395342fb43346befc286959fa01114b0ff28e2 - optee/optee_os/core/drivers/versal_mbox.c a4098254e952201f7b1f513d7bfa85c753805466 - optee/optee_os/core/drivers/atmel_tcb.c 514313602dfb100842f336c91efef495a658b3a9 - optee/optee_os/core/drivers/stih_asc.c 61fd12b4c0e6e8d4afffed71c182286581de4837 - optee/optee_os/core/drivers/ns16550.c 8457979f3ce7a5ad5eff7c23b2887fe3d61a29d7 - optee/optee_os/core/drivers/xiphera_trng.c 0dde4c0ccc9de1c9506849f158f4d0bfe08c7716 - optee/optee_os/core/drivers/atmel_rstc.c 5f7af6748259588f30732bd198cada68ea449968 - optee/optee_os/core/drivers/versal_nvm.c 20036824317b2f8dbae5d8cdb283f557e3c303c2 - optee/optee_os/core/drivers/gic.c 99907094047bf316222d7f0af9b7b043693a92fd - optee/optee_os/core/drivers/imx_uart.c 32c848c3a2f49db8076d0ef95094acec87a733f4 - optee/optee_os/core/drivers/stm32_gpio.c 9f608bd36d7697b68b44c50cf8070bcfa4c872c0 - optee/optee_os/core/drivers/imx_rngb.c 2ace80614760dbbe872200c0405c3e28fe6a5880 - optee/optee_os/core/drivers/cdns_uart.c 8294666cb76a8dde2dc2f1155586de082381312b - optee/optee_os/core/drivers/hi16xx_uart.c c527277e48632898dea03473e67ca39837e75ed6 - optee/optee_os/core/drivers/atmel_wdt.c 9203d1e334c03870efbb1296fc2b9151c8971267 - optee/optee_os/core/drivers/imx_sc_api.c 5df98204d9e9768c88e295bfa8d2d03829a8bf4e - optee/optee_os/core/drivers/stm32_iwdg.c d89b4120ce4c2335a04d1f4aaf73b8e188140fba - optee/optee_os/core/drivers/ls_i2c.c f8a2cf16ad82a5a58a932430f4155678097f4ef4 - optee/optee_os/core/drivers/ls_sec_mon.c 1f8114767f04f10575e9d516120b9e8004560045 - optee/optee_os/core/drivers/zynqmp_csudma.c e26dcea60a7bdcf95acd06bb25f806e8b4d3d9ff - optee/optee_os/core/drivers/bcm_gpio.c 89ce33aaddb1581c98d889695b695d3f91d1abac - optee/optee_os/core/drivers/stm32_shared_io.c 2897acd81f2d1a3996adb59bd9dec1f0000f919c - optee/optee_os/core/drivers/versal_puf.c 336c2f714f6f3c8267473f821b95e998a63e3cd1 - optee/optee_os/core/drivers/versal_sha3_384.c 8ee4e7f2733f1ef421e3756f06c95acbcd347f3a - optee/optee_os/core/drivers/dra7_rng.c 06bb93003d3938898dfe3d7c010a1c6e586904b9 - optee/optee_os/core/drivers/imx_csu.c 56729058749c51344648a227f7c1d01e42fc1074 - optee/optee_os/core/drivers/sp805_wdt.c 90ef3f7cef8ca0b5ea51d6514433067919d92331 - optee/optee_os/core/drivers/versal_trng.c 04ff6a848f0dd5e16fb7fd76e95ce39785601df1 - optee/optee_os/core/drivers/mvebu_uart.c 6d0051bd667e06cafa0f116b864e5dcf5fa33e8a - optee/optee_os/core/drivers/stm32_bsec.c 1a1293e8adb1512031e4d88e30e903190c5e1313 - optee/optee_os/core/drivers/stpmic1.c 5bd6ae3906b725a1aa8d858e722579faf7b67c40 - optee/optee_os/core/drivers/stm32mp15_huk.c 09898d9b6b3ce2ff6bfaca61a6b13f0b9cd4efab - optee/optee_os/core/drivers/tzc400.c 29302475f05ea928763d589f7149ac31fb251bc6 - optee/optee_os/core/drivers/zynqmp_csu_puf.c 54a609280735c84a28f8d94cc34c03b2316634fe - optee/optee_os/core/drivers/versal_huk.c ca1d9008dba817311983779a55983721de2934b1 - optee/optee_os/core/drivers/atmel_saic.c 2a6d458de7f3a2a8cb965dba5a4ca10f43a80590 - optee/optee_os/core/drivers/imx_ele.c ea929d989338338849fbef43e268bf7a5cc2b79f - optee/optee_os/core/drivers/ls_sfp.c d727565a02416f45a77d93a9d363380f5f38ad79 - optee/optee_os/core/drivers/imx_scu.c a2703ae9f0253d154cc43d443d13e3a182189d68 - optee/optee_os/core/drivers/ls_gpio.c 0cdb9912f3a35cdd9d52951d5f489087f96d327b - optee/optee_os/core/drivers/amlogic_uart.c 285a03d5b9f6657a5a74f219b40e639aac379b41 - optee/optee_os/core/drivers/zynqmp_csu_aes.c 47509d9c897d567527308698b101326d495b6f43 - optee/optee_os/core/drivers/versal_pm.c 033052ada215ccb3f67e6643ef12c4b5665f0448 - optee/optee_os/core/drivers/atmel_shdwc_a32.S 418074ffc87f92ed37f80669e102b0253d4ee809 - optee/optee_os/core/drivers/versal_gpio.c 72c106642fd5baba523177b44cceb0e2dd268bb5 - optee/optee_os/core/drivers/zynqmp_pm.c 15006081e89bc8300728779c6253899a10614a9b - optee/optee_os/core/drivers/imx_caam.c 8d04ceb536a6bf4d80820154070d8c7c642edb42 - optee/optee_os/core/drivers/sprd_uart.c 488329789386ed718c577ec619a4315c61bfad80 - optee/optee_os/core/drivers/imx_i2c.c 52c9fd38c2174bf6f84138c477cbee17c48cbded - optee/optee_os/core/drivers/bcm_sotp.c 9a6399d3b9a2944a5cfebf5b6c67e29dc97474e5 - optee/optee_os/core/drivers/pl022_spi.c a89150d72a6f70cd6f3b353a068286f44896bb15 - optee/optee_os/core/drivers/smccc_trng.c 948cecf6b04d477d3c372bc0c5f60955101cebdf - optee/optee_os/core/drivers/imx_snvs.c 1427572daefd0b1d7949a5bf943320c3ce4b9733 - optee/optee_os/core/drivers/imx_ocotp.c 990afc221925acee24e98912d3ed7b0ee1af523f - optee/optee_os/core/drivers/atmel_rtc.c 42b41e7d6dba7a7d9a97f8a296aa72adc0a42be5 - optee/optee_os/core/drivers/lpc_uart.c ce40785f0b0ea3723ad09029522fe31e030e844c - optee/optee_os/core/drivers/stm32_uart.c 5b608ade5b6d8d262288fdc49165d0e0fb72f72b - optee/optee_os/core/drivers/imx_lpuart.c b44d33205ab5012349af7f1b4b06f026b1546f32 - optee/optee_os/core/drivers/atmel_piobu.c 23eed3a3d72852b8eda78fe73dfa5b7f7e5cb44d - optee/optee_os/core/drivers/zynqmp_huk.c 5e6a71e4a41dcf21ee3c8baaff79ae2274c6c5f0 - optee/optee_os/core/drivers/atmel_trng.c cfe1327aad5f492ff8e56e386fa5081ddf52163c - optee/optee_os/core/drivers/ls_dspi.c c96f731961fc579a4966cae12e597d72c1ed06f3 - optee/optee_os/core/drivers/atmel_uart.c 3d3d4af031ac66f9ce00f6553ce09e3556648825 - optee/optee_os/core/drivers/atmel_shdwc.c f709e939aa07ae260dd8d822762ef4e35442d96b - optee/optee_os/core/drivers/stm32_i2c.c ba938d917edc42fd1e53f93a707cc9ff5ff45686 - optee/optee_os/core/drivers/scif.c 342f4d81b439bab50c12c3fb029b495683d4cae4 - optee/optee_os/core/drivers/imx_wdog.c 8c9bd89348d37d78be7efd291fc5f9279a62093d - optee/optee_os/core/drivers/cbmem_console.c 9fbe74cf959bf2b80b39c4cf5ff6d4cc0ed64759 - optee/optee_os/core/drivers/tegra_combined_uart.c 5e0cb642d735a12ab5988ae85b3a92aa9ffef6f3 - optee/optee_os/core/drivers/hi16xx_rng.c a9e721b1faeb4865248d3c188b56278116a3185f - optee/optee_os/core/drivers/pl061_gpio.c 380dc2101277f2f474462baa5fcd9e75b84de26d - optee/optee_os/core/drivers/hfic.c 445c04d3c6c114e8ec7bc1ad63a137c0880cec74 - optee/optee_os/core/drivers/stm32_rng.c 707867f2731e424b641a7ec3409ee954fb610f37 - optee/optee_os/core/drivers/tzc380.c 9c0fffe583ce8197aac49fa87c158bec166776ec - optee/optee_os/core/drivers/stm32_tamp.c fbee23ad24545aea0bd9fd6ae6b67e9acc2ef16f - optee/optee_os/core/drivers/scmi-msg/base.h 93be063666a6a98dd1fa8f45bba0c3ca91136171 - optee/optee_os/core/drivers/scmi-msg/voltage_domain.h ac6217df4e25acd1b996d379ee7dc022ea03e8a8 - optee/optee_os/core/drivers/scmi-msg/shm_msg.c 1420d3d8ef64053f5b6cbf009539fd6ddddf6e95 - optee/optee_os/core/drivers/scmi-msg/common.h 6bd5b105161e0e51561bae3c976f9f6e87c4f7cb - optee/optee_os/core/drivers/scmi-msg/smt.c b6dc570c20e25ebbb69c815e65c4e3a77f6cf00d - optee/optee_os/core/drivers/scmi-msg/reset_domain.h a5fb58a50b0ccc0dde34d6fa91b0b03c5e0ca554 - optee/optee_os/core/drivers/scmi-msg/voltage_domain.c 189d1a32fdc699c67e4da64ae26380a2b3facd66 - optee/optee_os/core/drivers/scmi-msg/clock.h 15a98472af569d660b8ba57d3e4515f74ad49743 - optee/optee_os/core/drivers/scmi-msg/clock.c 13ed9520d3f452a3b5919a38066b702cc2f31c5b - optee/optee_os/core/drivers/scmi-msg/reset_domain.c 33be09787080f4627f5fdc10d7378880994ded05 - optee/optee_os/core/drivers/scmi-msg/entry.c cf9d967498746a73d9d033a11d89d20a95631dc6 - optee/optee_os/core/drivers/scmi-msg/base.c cac2399fb0ad43f3819d37590fd2003b3032c550 - optee/optee_os/core/drivers/clk/clk-stm32mp15.c a27d2bdf0f8ea5a83d19a186c35a2a73678b4a41 - optee/optee_os/core/drivers/clk/clk_dt.c c8f48d30481a1983d8c5991574a486ed83ebef49 - optee/optee_os/core/drivers/clk/clk-stm32-core.h 489775781cf7e044f1fcb8ae91603dbe93719b5f - optee/optee_os/core/drivers/clk/clk-stm32-core.c d1e1be84172c7598f0ad0f44f8cf0c3098e6da2a - optee/optee_os/core/drivers/clk/clk.c e8b58becff76b0a467f5e772157d6c0a5994b8b6 - optee/optee_os/core/drivers/clk/clk-stm32mp13.c 98169c49a2b31260fbbbbe0a0394251d9b62cc4f - optee/optee_os/core/drivers/clk/fixed_clk.c 18acdc71569e2a780d0476642f03bc85218be532 - optee/optee_os/core/drivers/clk/sam/at91_plldiv.c 530a8ac463371dd1e9b7fa1c1ca9e30c7958808b - optee/optee_os/core/drivers/clk/sam/at91_system.c e90a1c0ffe8e8d869859768ddc4f978630f52990 - optee/optee_os/core/drivers/clk/sam/at91_pll.c c01c18400e840f1e7f911c70a8c24034e5b1683d - optee/optee_os/core/drivers/clk/sam/at91_clk.h 83d717ffdc6556064facb9e09df34abe6ea88ad6 - optee/optee_os/core/drivers/clk/sam/at91_generated.c 9254662590d96a635dd41164bcf9c0bf2e3d37c1 - optee/optee_os/core/drivers/clk/sam/at91_pmc.h 1050ecd58ec5f9140571e29544df45407324d89c - optee/optee_os/core/drivers/clk/sam/at91_audio_pll.c d24e2fc27571f5703eab7cd4f047097d88badd50 - optee/optee_os/core/drivers/clk/sam/at91_master.c 25e39dd6ad71ca3d8a60a03850e2cbeae18124a2 - optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c 09d3398f4208842a4fe083227c808cfc2add46b6 - optee/optee_os/core/drivers/clk/sam/at91_pmc.c 13078eaf7868f4a2a4dcd703d8eadc76630f1b3d - optee/optee_os/core/drivers/clk/sam/at91_usb.c 1cf0a55892076fb8587178bf570a91ba7a2ba82a - optee/optee_os/core/drivers/clk/sam/at91_main.c 81082b7a678856f1ac9a91da0e5a4600cfbd853f - optee/optee_os/core/drivers/clk/sam/at91_sckc.c 48f146dde6d5ca943dbc1c3d3e909da6c816cb42 - optee/optee_os/core/drivers/clk/sam/at91_peripheral.c 1ad7203186a86ea2d38ddba1ce87469d1e139a94 - optee/optee_os/core/drivers/clk/sam/at91_utmi.c 152f3551f54e3ee176d8a09bd21b8692d3d34ae0 - optee/optee_os/core/drivers/clk/sam/at91_h32mx.c c99eceb036f865d8c6c2df48b7dd402af247fd34 - optee/optee_os/core/drivers/clk/sam/at91_programmable.c 3cc6160c3ae52400111c85d3c4ce08d787630856 - optee/optee_os/core/drivers/clk/sam/at91_i2s_mux.c 0d6b0a14fd3b05ba3c8c21eb1a895e8e3ba465e4 - optee/optee_os/core/drivers/imx/dcp/dcp.c 34825682d3731dc9ea51680257ae795e76a288f2 - optee/optee_os/core/drivers/imx/dcp/dcp_huk.c 590ea022b10a9c7283c5ffc2433de61c90148fb2 - optee/optee_os/core/drivers/imx/dcp/dcp_utils.c 2b2febd277aeda9813289b22b87000c559b8e4d8 - optee/optee_os/core/drivers/imx/dcp/include/local.h 2086f64aaa2a6e6c7903ab74de13c177b978297d - optee/optee_os/core/drivers/imx/dcp/include/dcp_utils.h 04647d26da9ca3ed1c605d85f2e47ef0622718ac - optee/optee_os/core/drivers/imx/mu/imx_mu_platform.h b88af5fadc01a2b51585e2d02ec338e77a314d41 - optee/optee_os/core/drivers/imx/mu/imx_mu_8q.c 082b0667861563360b7c1e69c17d6e4f6721d7f7 - optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c ff98f09ac7d7e546907420f56e3219c2ca02504f - optee/optee_os/core/drivers/imx/mu/imx_mu.c b1b96d68d4bf3e82a538f91afea8b87b5c0f43f6 - optee/optee_os/core/drivers/rtc/rtc.c e2ede389a1c5a24403439cd397bc8a69fc16ac0d - optee/optee_os/core/drivers/crypto/se050/session.c 3238acd7dd2e169621bbe8ab9e9f93372f6b111b - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/scp_config.c 6e42bccb8cc7140adefd2baee2a8f2b2c9757348 - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c ad754aaaf0b0850065a9e68027ee82642a44e817 - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/info.c 4732906bb4ca33cb409bd901b0c94c24a26055a4 - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_user_apis.h 215eeb31aae8342063f2c7eeded5fcb3979691da - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h ceb2e995fdceecea2d1bb9a5610a21f958a520e2 - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_sss_apis.h 374c26b225f2311ce209fecac1317c2566d76f5b - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050.h 08160ebfd7c03896165877326736450c0d5524ae - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_utils.h fe046635d5ea4979e83d3bab636fa885d6ea42b8 - optee/optee_os/core/drivers/crypto/se050/adaptors/apis/user.c 938beed49b7219bc5de5f01b93c9a51b0fdb40f3 - optee/optee_os/core/drivers/crypto/se050/adaptors/apis/apdu.c 95e8665d3b38e2efdd05f50abd94fe9c48a3d2d7 - optee/optee_os/core/drivers/crypto/se050/adaptors/apis/sss.c 05b8cb927ce8c6dc6b2c3391b71366cf1b9dfc89 - optee/optee_os/core/drivers/crypto/se050/glue/user.c 75e0506e1992b38a38a83d6805b15b095924a783 - optee/optee_os/core/drivers/crypto/se050/glue/i2c.c a73abf5d66f2a00e0357ab9c0deaddb53066be52 - optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c 64681be01124b403991ca09721e4e6c6e023b72e - optee/optee_os/core/drivers/crypto/se050/glue/i2c_imx.c bc9e0c1bff88a8c8a8b844d676d9ac9d76658357 - optee/optee_os/core/drivers/crypto/se050/glue/include/i2c_native.h ad85ac6e521999bc864eeb2cb25141446897db07 - optee/optee_os/core/drivers/crypto/se050/core/ecc.c acd04d6ec81f1e8fcd19581e8e7d194f372b861d - optee/optee_os/core/drivers/crypto/se050/core/ctr.c 54cf708e2d7e054324c1de7b52356234447a555f - optee/optee_os/core/drivers/crypto/se050/core/rsa.c ddc645a154efbbe06890e01fc9d2e8456eba3849 - optee/optee_os/core/drivers/crypto/se050/core/apdu.c a9660506e78ca0a2ec416668e5f142dc5b0198c8 - optee/optee_os/core/drivers/crypto/se050/core/die_id.c ee63e46c72d0cdd406a4eff3afc3de61bfc5867e - optee/optee_os/core/drivers/crypto/se050/core/scp03.c 683291b35269db2584defc67cad6d2006d59b805 - optee/optee_os/core/drivers/crypto/se050/core/rng.c 2bfc19e0e0e85d9305249130e474588e60b28f37 - optee/optee_os/core/drivers/crypto/se050/core/cipher.c 82381f16e979c73561a13cc26b1b69fcf01e470a - optee/optee_os/core/drivers/crypto/se050/core/storage.c 77ac6992ffdbc505fd3b8113c9335ea835c5f6c1 - optee/optee_os/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h 96d553c170bdeb1a217af81953ee6ccc6704d2b7 - optee/optee_os/core/drivers/crypto/stm32/authenc.c 06f4d05c0b8dff1db83d75e507975331028c073c - optee/optee_os/core/drivers/crypto/stm32/common.h f77e2cd5cbc8e1df18178a112fe9b5d5f26d1feb - optee/optee_os/core/drivers/crypto/stm32/cipher.c 601b922f3c15a1c4d5abb05d995f5735c1e356b9 - optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.h 0ac0dd86b4ea75cbb4c4a484ef80d598a4e1c214 - optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c 7a1b972e1faf39f6c1c11e018fadf7690c0812e2 - optee/optee_os/core/drivers/crypto/versal/ecc.c 098e2cd056d7c0109c48e1c0fe7fa13577cdd79e - optee/optee_os/core/drivers/crypto/versal/authenc.c 0c3d0695339eaa6535604758e28d42e1177c52cd - optee/optee_os/core/drivers/crypto/versal/rsa.c 828360f1fe0d8cb9892dd9b467df8cf52e119eea - optee/optee_os/core/drivers/crypto/versal/ipi.c a7d7f00d8287e6bad7ec81709ec0463d5f483dcb - optee/optee_os/core/drivers/crypto/versal/include/ipi.h bb297b79a3f0cc6cb59b1a18f8d19242c9fc12b7 - optee/optee_os/core/drivers/crypto/crypto_api/drvcrypt.c 8ddc0db04f5251ffd3c0beb7d3947298685d5cf4 - optee/optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c e867ba1d32e367e1e498b6fd909c71127118cb1b - optee/optee_os/core/drivers/crypto/crypto_api/hash/hash.c 5e52cbf60af910c8238cdc945b75c611ab59ad08 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_mac.h b70e470e5e716917b0983224109234da6d526139 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.h 87afd69b37267a86f8bf7b3ddbc405754070bbd0 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h 4ce630f92142f1498cc8d9085650c1c0a691d53e - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h 622acb83b02d0d5e1f8cc107df2871c1d99220b5 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_math.h 208419d7c303ed2af4a123d73612ffc734f88acb - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_cipher.h ccc63fa2a34f969b16948eb42489b17fba61d352 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_hash.h f8f01711239d5a9fc6ece9f19e40d2f805b04c3a - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h a6e4483d1fd80f6f7f23a89a9e1ead0fbfcf65d9 - optee/optee_os/core/drivers/crypto/crypto_api/mac/mac.c 46947c70982d23fe999c5a70666a676833b13725 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/ecc.c 7ac822e6fdd1cdb08537631b7e8a3a823a0af57e - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsa.c 28add33c1c1a025afa5b36e5712026f17bbc9906 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsamgf.c 44b952198a07c95768b173ec708d14ea89702579 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/dh.c 979dd11c468df335b342654f7263949e51d1535a - optee/optee_os/core/drivers/crypto/crypto_api/acipher/dsa.c 38819ea8744620f296d47e0b1cab78567242c9fc - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsassa.c d235d21c1de200d48e91b12063eb2f8f1caf0881 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/local.h 3502395b082081a4c3f6e68c5f0774a90715d7bd - optee/optee_os/core/drivers/crypto/crypto_api/math/modulus.c 30d67ef67cd36d0794f2055d1705d14905f3ab0b - optee/optee_os/core/drivers/crypto/crypto_api/authenc/authenc.c 5104681db824caa455d34ffcb91e6bad1b8afad7 - optee/optee_os/core/drivers/crypto/crypto_api/oid/hash_oid.c e1c98e3cd50456380895acb8ca60b8a7622d18e6 - optee/optee_os/core/drivers/crypto/caam/caam_jr.c 5abf9725310659d557245e78b391f46a589f065a - optee/optee_os/core/drivers/crypto/caam/caam_pwr.c e50b088ae52c3e7016bce9511e39b1adfa3f0b4a - optee/optee_os/core/drivers/crypto/caam/caam_desc.c d5eb08887d58acfbb2e4bcda329360d893542698 - optee/optee_os/core/drivers/crypto/caam/caam_rng.c 6c30a2cf57a18929413f7684818e9304122d6f7b - optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c 0f4455a2b7723d3cc63f4f0d0623d29b0363b39a - optee/optee_os/core/drivers/crypto/caam/utils/utils_status.c 7c483d7465e733ab3503e26d161daafaa25755be - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v2.c a34c25f439fb74912fddf47fac4b0295ba1effa6 - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v1.c 06d77bc7f344869783912b109cd485ef4e8590ad - optee/optee_os/core/drivers/crypto/caam/utils/utils_mem.c 130800ee65979019cc2117d690340aaa75cd92a9 - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt.c 5d02c1b842f54635bbb53a03214ed2f577c3c5fc - optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c dc70d7f20e3b0430b6dd2fe0dd0261c929d3db6a - optee/optee_os/core/drivers/crypto/caam/utils/utils_delay.c 981c3652730c78df0fa0ab1841ce939ae699d9f9 - optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher.c 764e2643f5c29164046e1b31a10f8446246827dc - optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_mac.c 149c2203a9171fda3be98cdeace47e7be4d8c8aa - optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_xts.c b1050722e24889ba59c987cb274897949dcd39a7 - optee/optee_os/core/drivers/crypto/caam/cipher/local.h eb43fbde76dd94674bb94f9d314b9c0246403ac0 - optee/optee_os/core/drivers/crypto/caam/blob/caam_blob.c 59ec0c7059f65e67d8cde311155d4f1e67a49718 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_cfg.c d375b61195f07cb019b6c1c76272b00409fd8626 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_clk.c 38aeeeb79c278658c50da69fcb72b23ff70336ae - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c 37d6f6801f8b77cfaa1e789b65d9bc5e1b44bdbe - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_jr.c b2e468ca406a0ecd02357d0d17e4018a6c68bd49 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_ctrl.c aa940d1d85879826ef54d8a93ceac16d8134c9f9 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h ae43fe99412d31c2f21f732a6798cda49fa12d3d - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c fdb4775e9056e6c476ffae9721aee7a2c72a56ce - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_jr.c b438abbdc31d4fba647e29cb04348c3fe1a2bc5c - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_ctrl.c 0901279b007af3228bc982ccf06934c1d9fe6796 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h 044fc74646036cc6edface5539cace597bd88854 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c 56e2dab762555ca397562646cd9baed2266557c3 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c 9e09a7307c115a9661cac5d5c5a1792502220bfa - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_jr.c 75e141d842a44be2fc54fc9aa3d6233d43786cf8 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c b9b5aa7dd5bb89200b350e92c937684405b8abe7 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c e7c18e488182d4bf3c8c821885db52c980fb5f7a - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/version_regs.h 53b9f1b589e80b574aadd27d61ab737db2d5a9fd - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/rng_regs.h 5d8a12ee896ae3c8e60ef64f2bc85b31aef2d9c7 - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/jr_regs.h a8796a5f28445049f810dd2b2cf6bd4700d39090 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c dc2680e783f647bce21513453573f8f426d9ae8d - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c fdb4bbc22ae4a6acae04a6b7205f78f74e7847ba - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7ulp.c 08fa37b12c023eb7169ed6b3c069ecde04fb9ed1 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_jr.c 08ea1bfa1f790800d596ee9616bae2ec31390970 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_ctrl.c fee09baaa8fd82c62ecca9d059220329bb51e466 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h 7bbd78ddb18f062b0ee9521f445979c6acb2ee1e - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c a70a4c8d70b51affd3d9132d1923186a531b7f4b - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_jr.c 72df54a7f3d911d758cad690990fec5962c2ceb4 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_ctrl.c dc66e73bb6be55941cae77b073fdaab8d4badfc5 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h ad05613f64dba65f1576f358f3d0ad0182e393f3 - optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_clk.c 13a69ec0385f79f1b8ad1c9de90b79c0a2c82365 - optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_jr.c 63e5eb66976364a49eabd3680df526f36f7c51cc - optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_ctrl.c db232940b3c2f122c53b11e6dec5e70c5ec347d8 - optee/optee_os/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h 731f10c0a7fe34860f0d1d21271b01a8a378b1a9 - optee/optee_os/core/drivers/crypto/caam/hash/caam_hash.c d8824580f4b1889d9a23ddd2047c3b102b9e7a17 - optee/optee_os/core/drivers/crypto/caam/hash/local.h 9dec343ffefc374f9d58367446ae2c277213ddd1 - optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c bf2aef86b551be9c94f477b1372400abf9f59015 - optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c 42cc84af73a8980ed1e51aac57b7ac2bfe8ea567 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_cfg.h c396344d76de6f758e9164a0658037d2e37cc128 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h d23a06ce5206f043b33f8ee8d4e6bfd62d8bb981 - optee/optee_os/core/drivers/crypto/caam/include/caam_types.h ee68dcf290038d3ebad07beabb3517b5860bc3f5 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_delay.h 912d6553b392b20581d016f9eba91479662d6062 - optee/optee_os/core/drivers/crypto/caam/include/caam_blob.h f60708cc4c84df857fc20cdef0710a388ecd56f8 - optee/optee_os/core/drivers/crypto/caam/include/caam_io.h aedd672ed034e8265f35ebab812a5af4135e94d2 - optee/optee_os/core/drivers/crypto/caam/include/caam_rng.h 898dd496c1a8f25b592f261d9d13a74d3873ff7e - optee/optee_os/core/drivers/crypto/caam/include/caam_pwr.h 547857b357f6594d407d46fcab2f93fa7074d3cd - optee/optee_os/core/drivers/crypto/caam/include/caam_common.h 2ffbbb6180a3ba5fcc49f2958836e6391a2c7375 - optee/optee_os/core/drivers/crypto/caam/include/caam_hash.h ab44fa3086f2ca8ca281d8763ba59777b975a36b - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h 7be3b8463755df707782bdaee0ed26c692c0f32b - optee/optee_os/core/drivers/crypto/caam/include/caam_jr_status.h a7a136dc1c5717e89fecc502f4095a9779b501bd - optee/optee_os/core/drivers/crypto/caam/include/caam_trace.h 2f780d7215aa1c23b998dfe17edabba1d0f4b1f9 - optee/optee_os/core/drivers/crypto/caam/include/caam_acipher.h 7c8acb595959705bbf481d1ffcdda173637dccbf - optee/optee_os/core/drivers/crypto/caam/include/caam_mp.h eb20c569c7f68eb8f8a1eb16eb82c24a8ac4cd9b - optee/optee_os/core/drivers/crypto/caam/include/caam_jr.h 3a804ad72278dc57b300a9df498d00db63fcefb6 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_dmaobj.h 0d6de8f72472e2554ab7666852ac52a37175465f - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_sgt.h 3cefd9acd10d65bb6c61f2e0aec31f43e48f6abb - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_mem.h 3ecf5ab643e7f3b2c6be73330969a5795d9bdc91 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h dcc86d041d08d62d6fe7acb03e2380804af1118b - optee/optee_os/core/drivers/crypto/caam/include/caam_cipher.h 21e39b796944181921ccaee48afdda1cf8ce8f83 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_jr.h 97d9212dd201d4169891e6f997efd5f8ddc5e761 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h 74a055714e2db637adc0291d19cea1c02974e030 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_clk.h dfa82d15074fd452691032b408318d2d1a7aec79 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h 631d3ce5a38c82b07ae1a14ee6b6cb5ef95d32ba - optee/optee_os/core/drivers/crypto/caam/include/caam_status.h cfa13823918f625810c9958b6499358d179c8960 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h 86a25c32839f837b88bfe27425e26e7e19cf539b - optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_dsa.c cf64c3301a86696cbee97860cf765d5e34201d6b - optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c 7b9390d54de54fa7f6778b6a73a75799cb97fe1f - optee/optee_os/core/drivers/crypto/caam/acipher/caam_math.c 804d375b59635219ecb0c4299c9e76ba786aaf67 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c 237af92d1c928b929d3fa6ba1d315e2c2fcdfb99 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c d1a64f1df7575f96b575be706a12850ac65679df - optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c f677ba67d639efb7e1d7aebdc1a4b96eca37fa2f - optee/optee_os/core/drivers/crypto/caam/acipher/local.h 6e7f0ea0e73e8e81ba1d5d68c82bbe0ed635e645 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c 2702c09d55cbed00cd7326d5d6e35b12126fbe96 - optee/optee_os/core/drivers/crypto/aspeed/crypto_ast2600.c 0167f0613b4286349c7403ea6c9a7dfe0a322533 - optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.c ecc8a0a2fa12870fc85783fb7f60d717f6bf40d5 - optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.h 86b14f8200d61eabffb946fd45954dcfac30aaa0 - optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c 6ea97a6c89fdbbb425562f878dd045fd6f626046 - optee/optee_os/core/drivers/rstctrl/rstctrl.c 399fa3fd4b68a0c3ca446add566a9e832be98b0a - optee/optee_os/core/drivers/pm/sam/at91_pm.c 92ac150fcb4f3fbb4d74e1307ae620bf0202b800 - optee/optee_os/core/drivers/pm/sam/pm_suspend.S 2932a82f88cd223444a2033a5f5062b6ebdfaaf6 - optee/optee_os/core/drivers/pm/sam/pm-defines.c 2e32e7c1e67c58880615aa62d62335f62174b937 - optee/optee_os/core/drivers/pm/sam/at91_pm.h 4af2105f9cb20e8151aae7f9f5b9343f9c80cc2e - optee/optee_os/core/drivers/pm/sam/pm_resume.S 49865544561297dc1688131470c0baaa35112a86 - optee/optee_os/core/drivers/bnxt/bnxt.c a7009131f76447718645c703ed1373bd329a4528 - optee/optee_os/core/drivers/bnxt/bnxt_fw.c 7651789fc830ed002efb38c51f34bda32a3e8e46 - optee/optee_os/core/drivers/bnxt/bnxt_images.c eaf0dd04206e96958dd712422ba4074ba614a6b5 - optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c 01aeb814d645694dbb3a7b6cba73a8dbdb00b2c5 - optee/optee_os/core/drivers/tegra/t234/tegra_rpmb.c a718ebfe121008337695ef87878037c2484b3aec - optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c d0c05c35bf7b3a14be8f22ef4a1aadbe280144bb - optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc_errno.h 8d24d3ea306d62a7b45f1c29f17840741197790d - optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h 17ddfcb103fb3b6272fb935b6ffcf6c9277d809e - optee/optee_os/core/drivers/tegra/common/tegra_driver_se.c db6b2d8179fcbc42da79480d5ee5d0ee046b8459 - optee/optee_os/core/drivers/tegra/common/tegra_driver_rng1.c 35b07964703e174bb7f7a9f27cee4b91714cdbd5 - optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c 32ad38d98650ec84007d8cdb4403018429dc15d6 - optee/optee_os/core/drivers/tegra/common/tegra_driver_clear_keyslots.c d4654766a46d1186e241c2e252b6d38ac9f71355 - optee/optee_os/core/drivers/tegra/common/tegra_driver_common.c e858eda88f3475db60107c22c48bc8d6ed3a7376 - optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.c 9d22d8ce9d81f74a8b3ac51470f60e7d72cf6000 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h 423d81cfccb43c9bab466aa03a25b2c86171822b - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h 542a320020446e6712e8518616780ed091faf0de - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_rng1.h 352d6c58d195d5c44b8e06c006e713fe506dc77e - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_common.h 7def8f5aebb2ff74cb2cb235598b76028947c523 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h c67e3cfb2ca9a5fa42769943cc7e64cd190651af - optee/optee_os/core/drivers/tegra/t194/tegra_se_aes.c 59b8fddcab1c4118b35c29a98d2e68efe471715a - optee/optee_os/core/drivers/tegra/t194/tegra_rpmb.c 3b96618ecaf4ddecb14a6af70d8f80d32724299d - optee/optee_os/core/drivers/tegra/t194/tegra_se_mgnt.c 953bf57f233bd74754d5258a5f6314cf7f1630c5 - optee/optee_os/core/drivers/tegra/t194/fuse.c e09c85691a66c623638973ebd587a1986680786d - optee/optee_os/core/drivers/tegra/t194/tegra_se_rng1.c 88ee29ff327c35524c79fd85e9c71ffff90df695 - optee/optee_os/core/drivers/tegra/t194/include/tegra_se_mgnt.h 2b1700dd12edcb736b9a5686f7fc95244f99a3e3 - optee/optee_os/core/drivers/wdt/watchdog_sm.c 11ae5906c65655bea1e0310e78fe9a2cd6f87709 - optee/optee_os/core/drivers/wdt/watchdog.c 7da841080f45a989a835a1fec30f6aa50d847b10 - optee/optee_os/core/drivers/i2c/i2c.c 6487ae2b83e597215d95fe540fcc7732890e0476 - optee/optee_os/core/drivers/i2c/atmel_i2c.c 3c93fa1fbf115515f5e1313b315ae7219e5bbe3f - optee/optee_os/core/tee/tee_time_generic.c 4d1fd828c84228949b6c57be1bf8ea7308f9cd67 - optee/optee_os/core/tee/tee_svc_cryp.c a00d48ecd6498ccba17eb691531f55e5e28eee49 - optee/optee_os/core/tee/tee_fs_rpc.c 2e7ad7afbede1e2a3987b894d9873b465df96cae - optee/optee_os/core/tee/tee_cryp_utl.c de0fd7c15631ce6187f89853a49fb30885602259 - optee/optee_os/core/tee/entry_std.c a1202328842c81639257318e2047a9e13b1802c0 - optee/optee_os/core/tee/uuid.c 6e9cf712089a20c55658ccfb34bce7115bdbe8f0 - optee/optee_os/core/tee/tee_svc.c ecb2d26f414109ce193325dc9c4aa0f51e6e81a9 - optee/optee_os/core/tee/tee_nvme_rpmb_fs.c 08651bd34dfb58168c78b29130516a563e1ab641 - optee/optee_os/core/tee/tee_svc_storage.c 36310dbe4c631f1eeb23f3ff8426f6ac27c1411c - optee/optee_os/core/tee/fs_dirfile.c 3de9da311b1fe8b3b7083179e376833293549ba3 - optee/optee_os/core/tee/tee_ree_fs.c 6e4a71bdec69aaedf5d9b1ac47e4297b4818ffef - optee/optee_os/core/tee/tee_obj.c ac18ee9e1ba6fb05ab7f2ca924c0936970c93d76 - optee/optee_os/core/tee/tee_fs_key_manager.c cb0c0c8fbcc1c033fbb259e50dfe3965e52013cc - optee/optee_os/core/tee/tee_rpmb_fs.c 7d9ae05cceeb683b0462d33c6def015ac53f4ed0 - optee/optee_os/core/tee/fs_htree.c fc58bf53b6b42bf286bd64683b86c6d31dc3a517 - optee/optee_os/core/tee/tee_cryp_concat_kdf.c 5922ca2dabf34fd3e6e67f6771d4c9a81cdcf5d5 - optee/optee_os/core/tee/tadb.c 4ca9c10d9b17380efab8d45d2de31948c98a16e5 - optee/optee_os/core/tee/tee_ta_enc_manager.c 7cf451d55302cfc19cc672245872a7bc06438f79 - optee/optee_os/core/tee/socket.c 3c86c49eae08e6e289fdc93ba24b2a7cb49f1b11 - optee/optee_os/core/tee/tee_pobj.c 0113d24cd422be94cfe071e76abab0409c9d69cc - optee/optee_os/core/tee/tee_supp_plugin_rpc.c a2028063632c8857bed15d993063a7fd353ee9c0 - optee/optee_os/core/tee/tee_cryp_hkdf.c dd81c49e2b9da8f822e7246d08cecde9f28fc2a7 - optee/optee_os/core/tee/tee_cryp_pbkdf2.c 7aeef825f355d2436dc4fd47d92ca857decaa195 - optee/optee_os/core/kernel/spin_lock_debug.c 9323261c4542f4f78ce0668852a81df361a9953e - optee/optee_os/core/kernel/initcall.c 7d0ada42e3e9e9fd9e14c60a53e62fc5c0a5a023 - optee/optee_os/core/kernel/ldelf_syscalls.c 94e2c0c379ce289434664a0320006df2fbae034b - optee/optee_os/core/kernel/msg_param.c 0a7dbadbb9b02d2767cbb75fdaaa8f36c95853a5 - optee/optee_os/core/kernel/tee_ta_manager.c 95db84ed2db1edad93dd163e910a57e8a493e1af - optee/optee_os/core/kernel/ubsan.c ad3214582c294d2157bf0094e356be8877650aa9 - optee/optee_os/core/kernel/console.c 103d74f02824b46e307830b5f0b2a5e0685c68d6 - optee/optee_os/core/kernel/dt_driver.c 5507bde30082bac9d1a101094c3f7cde4e04e1ff - optee/optee_os/core/kernel/wait_queue.c 59ff0a3736635fe8ceca714aa629bcfc9cd518f0 - optee/optee_os/core/kernel/dt.c 1beba0db1ff1f826641fd640ce1927e68758f838 - optee/optee_os/core/kernel/early_ta.c 3fc5e9e411b1ae45c0e4cae4b8a6bb864f0af29a - optee/optee_os/core/kernel/mutex.c e935ef062cf6f49e0a970956b28f70243e48b06d - optee/optee_os/core/kernel/trace_ext.c 1790af643118a654c31b61378ea1bf4510484835 - optee/optee_os/core/kernel/embedded_ts.c af2e20cbb543df6547a140deb039888cf8560fe4 - optee/optee_os/core/kernel/asan.c 4be3395d930addfce9c97be3cee349556b9b9b6e - optee/optee_os/core/kernel/ree_fs_ta.c 9975d02cd73795987cd451389809dfce9a902e9b - optee/optee_os/core/kernel/user_mode_ctx.c 93b8d5e48af159d7ca5fa174b79d935f05dbaa8b - optee/optee_os/core/kernel/tee_time_ree.c 4931d22ebf9d5389b6bb8c59af1c129a4940e031 - optee/optee_os/core/kernel/interrupt.c 601f8df7890b8b38b123509a94b8f05bb40105ca - optee/optee_os/core/kernel/scall.c 02448f355229caa2a32a4411c3198eb084395320 - optee/optee_os/core/kernel/lockdep.c 3e9c3ee98dbe0f91714a5f2df5f1d5efc3e8d831 - optee/optee_os/core/kernel/notif.c f854d339faf497fd0d027dac4594eb6c84548129 - optee/optee_os/core/kernel/user_ta.c 34c3fe34974039ae46f116dd60ce4b21a9fc901b - optee/optee_os/core/kernel/tee_time.c 7be1928ee7e34f7f47f52b99bce43e0024f06a44 - optee/optee_os/core/kernel/assert.c 907f7e88942ef24b0c59476c762dfeb7b3b2375e - optee/optee_os/core/kernel/tpm.c 221e610e4adbc3cd9e97867d9d1ae548a818fdfd - optee/optee_os/core/kernel/ts_manager.c 2a6a7890436dd84f6d5cd90ba647014156d06967 - optee/optee_os/core/kernel/thread.c c5144935485fc83d941a9c80668ace38c73633fc - optee/optee_os/core/kernel/huk_subkey.c f5d7654e570bb5bec7e4a93e3e08a88601cdb56c - optee/optee_os/core/kernel/user_access.c f4b199a80f0476f43f34060f72493f81a289748e - optee/optee_os/core/kernel/otp_stubs.c a1ef5afe68f55b5660aae6406acd31080c5af73a - optee/optee_os/core/kernel/tee_misc.c 813e8ed14c578b5b735b29cae3bbb42af9f03a58 - optee/optee_os/core/kernel/handle.c 3f891a5b83a8c9f2a82a468d79ea21efb2399b10 - optee/optee_os/core/kernel/panic.c 8abe5fcfb8a632e1c77c0e0f92bbc0414f1e2857 - optee/optee_os/core/kernel/mutex_lockdep.c 6ba41c747462a65ec025b7f099e70c4f0fb04cc1 - optee/optee_os/core/kernel/ldelf_loader.c 1962b8040874d00636c9541f532f3ee5b2ef4f16 - optee/optee_os/core/kernel/scattered_array.c 21449d26573f5cefed595f37780b901b7b937304 - optee/optee_os/core/kernel/mutex_lockdep.h 484e911f8c30e048b696a55ca84ec1b45d0a6839 - optee/optee_os/core/kernel/pseudo_ta.c de1675480ef4043349e0bc3875749598f8092a54 - optee/optee_os/core/kernel/show_conf.c e0f7be46eb2d862733bba0c834997c6d4203d425 - optee/optee_os/core/kernel/pm.c 54e613f652bc14d6ba8684814fe8dae398c800b9 - optee/optee_os/core/kernel/delay.c e3cfba43bda2276f238dec15e574a1d5b70bc7e2 - optee/optee_os/core/kernel/dt_driver_test.c 309c59c03e9e9577dff0819b23e420d73280278b - optee/optee_os/core/kernel/refcount.c c017d6ad6fee751242776e60c631fe9d1ffbb42f - optee/optee_os/core/kernel/secstor_ta.c a45b57d0b4aadf1d209b8ab2ef53b359fef4a276 - optee/optee_os/core/include/gen-asm-defines.h fe35bcb23450f547f7b098c1dc83a86e94884a96 - optee/optee_os/core/include/rng_support.h 5130acc35038686b8e096d0af60300156bb1fd91 - optee/optee_os/core/include/initcall.h 418f28494fe899852d688a2c61470ea0b87ea139 - optee/optee_os/core/include/console.h 0fe00321b7624b03757e3175805922dd46ccb50a - optee/optee_os/core/include/keep.h c41e2bca18dd7445ca83d477da79e00e5b1f6046 - optee/optee_os/core/include/io.h 129133eb0ba4e4b73eaf1d84710e580b22e10009 - optee/optee_os/core/include/spi.h 76a3a307fcae8ca4315d47c57222dfdbf7db3af7 - optee/optee_os/core/include/bench.h 8caab014052baad250b6a2fdfd50f4b5b4020264 - optee/optee_os/core/include/signed_hdr.h a368caa21683937ca27d5854e743a1d5359cd46d - optee/optee_os/core/include/ta_pub_key.h 6cd050c7ddd4d5c1022f00bf74e621a0a04818df - optee/optee_os/core/include/scattered_array.h fa6b95e58563f8332731f989e0d1bca1fffbbac4 - optee/optee_os/core/include/optee_rpc_cmd.h 5748d7d2f9ad14c08033135fa29ea471cf6fd1e4 - optee/optee_os/core/include/gpio.h 4baa40de63545ddbcfb6dc86b9cedfcd4359a44c - optee/optee_os/core/include/optee_msg.h c97a01f7bba80935fcbf2dafe9e946d43c247e1b - optee/optee_os/core/include/mm/sp_mem.h 30b8bfeb037aa430b36a9d62a9d906834dcf8903 - optee/optee_os/core/include/mm/fobj.h 33fa0dc8e82a82e1ef188ba26a539792cfe3767c - optee/optee_os/core/include/mm/mobj.h 985a54afd09d327768ec4d1e05e94e7bfa7355ca - optee/optee_os/core/include/mm/tee_mmu_types.h a6c2241b6f11dd5ebe72620c9997e5783bada425 - optee/optee_os/core/include/mm/pgt_cache.h 3813eb3d7bca8b05bf4d8df687119a55c902d925 - optee/optee_os/core/include/mm/tee_mm.h 2657238352e3ca4c25aedc808f05e904ff697330 - optee/optee_os/core/include/mm/tee_pager.h 493b72f34c04bd89c57c5ead3a53240b0d6ba642 - optee/optee_os/core/include/mm/vm.h 1af89b4c6e2cc87501b23b0f12e2365c613a6996 - optee/optee_os/core/include/mm/core_memprot.h 80ac097aa1c99ae9da69fca47169085d49b572a2 - optee/optee_os/core/include/mm/core_mmu.h 3ab7ecf667fa906a144379998f686f44c83c2394 - optee/optee_os/core/include/mm/file.h ccc329ed438598e8306a1a164a17d28a7b30ca79 - optee/optee_os/core/include/dt-bindings/clock/at91.h c82fd3d48caa51f67f6bb71f5637c491c8869afb - optee/optee_os/core/include/dt-bindings/clock/stm32mp1-clks.h 700be76cdd56cf4beca99964e8bef7679ca119a4 - optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clksrc.h 6ee67bde9c0ae2dd9f7b6db105f90afd017ac1dc - optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h 1e7ab5294d740390ffb703e0912f612c043e1ce3 - optee/optee_os/core/include/dt-bindings/dma/at91.h 23149233a025ca8a0b84821b398694bbf0bfdf4e - optee/optee_os/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h b07457cf8179a2129c3e2cbdf8afc8cfd94f6875 - optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h 51c769451ca1c189b2b01b45473d6fb93157a4f2 - optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h 19bb520476cff77efd84b0106f690c4dd972bd63 - optee/optee_os/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h 75e3b85cfb7663af28a4aeabd71f5d9171713d1b - optee/optee_os/core/include/dt-bindings/reset/stm32mp13-resets.h 6f7d303afc4981c5aaf8ae4eedae611976aa5b7e - optee/optee_os/core/include/dt-bindings/reset/stm32mp1-resets.h dcd9135e8790bfdbf7e925e8e5c9d421b5e89041 - optee/optee_os/core/include/dt-bindings/pinctrl/stm32-pinfunc.h 736b382bd5ae6f63e95b0ec473a146ffe182294e - optee/optee_os/core/include/dt-bindings/gpio/atmel,piobu.h f0ee73ec026d62a1125c4410ba4a0a72b924d09f - optee/optee_os/core/include/dt-bindings/gpio/gpio.h 8bbae85d2c9ec2416cc28a15f3d8e79d19c9847c - optee/optee_os/core/include/dt-bindings/interrupt-controller/arm-gic.h c09a35772e7498a4ece6515946754488ec651860 - optee/optee_os/core/include/dt-bindings/interrupt-controller/irq.h 3d11a04568b27618db9569d34ed229c92f24f7cc - optee/optee_os/core/include/dt-bindings/mfd/st,stpmic1.h dd5621d99484ecb0900f61801adab7e10d37f0f1 - optee/optee_os/core/include/dt-bindings/mfd/atmel-flexcom.h bb5104c1046fab4b7b59c7c5a4b7bcc11bc975d1 - optee/optee_os/core/include/crypto/sm2-kdf.h fb2b7a8d8b1e4d72673e7746b2209b7ce0705ab6 - optee/optee_os/core/include/crypto/crypto_se.h eef0ead7045789d8587d0a0a470491a3138a9c3b - optee/optee_os/core/include/crypto/internal_aes-gcm.h 3c37642b6f4bfefdcae5a1697faef8aa2b82b756 - optee/optee_os/core/include/crypto/crypto_accel.h a725d527edaf0a1dc858a9c5ba4740dde46a647a - optee/optee_os/core/include/crypto/crypto_impl.h 868a62eff03e1a25a10d061392adece3469e1cf5 - optee/optee_os/core/include/crypto/crypto.h 573aef790439e7f8668bf6d5be663c9504f9273a - optee/optee_os/core/include/drivers/tzc380.h 4bee46ff90df0433979e547ff28194293739570b - optee/optee_os/core/include/drivers/stih_asc.h ba280c416a5feaf1576cfdb84a7f4c6c10f95bd1 - optee/optee_os/core/include/drivers/imx_wdog.h 631cc4ec89ffe0c7e2eb61ef0c441a265c1cff11 - optee/optee_os/core/include/drivers/versal_pm.h 209a9de5a95c149ed87d06209a00416aca6bdf59 - optee/optee_os/core/include/drivers/versal_puf.h 04f9993ffd5c2f798953978835626f7d91793c27 - optee/optee_os/core/include/drivers/zynqmp_pm.h d9e6e80aa5d27c1fcf9c1edc4895e62394b0d4d4 - optee/optee_os/core/include/drivers/versal_nvm.h 6d429cc510e8a7657953b5312b459f26e03494d8 - optee/optee_os/core/include/drivers/imx_snvs.h a30ec174c1201d5297ef6ee8356cea3f0fbcf512 - optee/optee_os/core/include/drivers/rstctrl.h 9c339b4eecb10745f1cd1a5edb6c60a9d5854b19 - optee/optee_os/core/include/drivers/sp805_wdt.h cca1719ab46702da66faa45ee2e674cbf56e0936 - optee/optee_os/core/include/drivers/zynqmp_csu_puf.h 8b6ce4ad485b93603cb3a306654cd097e40508f9 - optee/optee_os/core/include/drivers/wdt.h 648ece0e1c404051cf7840a3caa294b090ac0947 - optee/optee_os/core/include/drivers/pl061_gpio.h 0eaea95f747c036c18d965a634e304c3819d6a00 - optee/optee_os/core/include/drivers/atmel_rstc.h 96e732bccb33868cd127943ce6fb12f5c9f68487 - optee/optee_os/core/include/drivers/ns16550.h 807fef6f8992f0fea2edc92c55deb829eb8e8be4 - optee/optee_os/core/include/drivers/versal_gpio.h 6267fd81bf3990311590c922d90fc4cecd83ea5b - optee/optee_os/core/include/drivers/hi16xx_uart.h 82d4883130bac9ae57b009986c8a8cf82f34f53b - optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h 90f5cecf44f1353954b9f509e72380c23dae5481 - optee/optee_os/core/include/drivers/zynqmp_csu_aes.h 3eab3b939280e8984b98283ca0325b82ae90fa88 - optee/optee_os/core/include/drivers/serial8250_uart.h 2e3c9c2926bbbc02de43b280cb53d39b021200df - optee/optee_os/core/include/drivers/clk_dt.h 0858c735ecd0b0f69511c80da83b88cb428ae108 - optee/optee_os/core/include/drivers/versal_sha3_384.h 9fecf61927af88057778f180eaa3f37588e42a69 - optee/optee_os/core/include/drivers/serial.h a989968154cdc25bcf61e8bf07f8586a30eb61a4 - optee/optee_os/core/include/drivers/stm32_i2c.h fae1d97a03ad4920ce240b22f5fe477866b1ce74 - optee/optee_os/core/include/drivers/stm32_uart.h f6c06a7e3d38d67183bbde4814b1b4fc68226fda - optee/optee_os/core/include/drivers/stm32_shared_io.h fa33f522c3cb38d765763701719a079010068a81 - optee/optee_os/core/include/drivers/atmel_uart.h d5dfc765162bdef02e9e02dd12d30d08eeadb409 - optee/optee_os/core/include/drivers/hfic.h d4025e0f4dc505c8928a4b46ce1d39a18d4b7786 - optee/optee_os/core/include/drivers/atmel_saic.h 21f16be3e12698442b37c7fbd4b2cf9b5e1eb2da - optee/optee_os/core/include/drivers/mvebu_uart.h d2608b476c0a3e6772cbc28ea1b2b555091784fc - optee/optee_os/core/include/drivers/atmel_rtc.h 17e4e2d1b983087461bfcc4bbfbd70e8b3ae1dac - optee/optee_os/core/include/drivers/ls_sfp.h 850d68c54c252aaad1b085a02dd9755cdafbf8d1 - optee/optee_os/core/include/drivers/pl011.h 5a5250f891c8e3fd01fe97da71d746ab170d70f8 - optee/optee_os/core/include/drivers/zynqmp_efuse.h f79ce31669141d007d3d46c0510c83271a074888 - optee/optee_os/core/include/drivers/zynqmp_huk.h 967a082f3664b603f92282dc6fbeab8b6b48a5fe - optee/optee_os/core/include/drivers/stm32_bsec.h 7ec39bbfed1d291fab370eb45582e3387233babd - optee/optee_os/core/include/drivers/rtc.h f4a11c9f29e893a7d4398704cf87f9025181fafc - optee/optee_os/core/include/drivers/lpc_uart.h d3f5bdbf1140a7acc6783fb34bf37bb7bf908822 - optee/optee_os/core/include/drivers/stm32_gpio.h 6f702cd255c663f52ccc829b19c4b0922c5a424a - optee/optee_os/core/include/drivers/scmi-msg.h 7f3ef46e25244f20b8ad05b4953dc9bdc01db532 - optee/optee_os/core/include/drivers/stm32mp13_rcc.h ed0702ba8e49ca5d2b8fde5b754911bdd2120b71 - optee/optee_os/core/include/drivers/imx_i2c.h c17bb19360d4833803c17e03dcbeeb35f1ea9db4 - optee/optee_os/core/include/drivers/bcm_sotp.h d6e344ad9b81930944052a2aa7439fea4f98e7a3 - optee/optee_os/core/include/drivers/imx_sc_api.h bc7cd62a50be3ff1fe02b16ac03930cd0dfcd250 - optee/optee_os/core/include/drivers/i2c.h e6b7e53a5566ba0e35f80a7ef10778c3e94a322c - optee/optee_os/core/include/drivers/stm32_etzpc.h 91b6d3c752a3d89e785356b8589c47726ff68d98 - optee/optee_os/core/include/drivers/zynqmp_csudma.h 270363e25fe0225609b0ffe1465e58e30181cd29 - optee/optee_os/core/include/drivers/amlogic_uart.h e2313ad621f3429650c5a66e403ac36467a63d00 - optee/optee_os/core/include/drivers/scif.h 85176c6d326f482d19d97007de5c3ec8d04b620b - optee/optee_os/core/include/drivers/gic.h fdec23a82da4b29851ee791c9f774fbcd9a3ef53 - optee/optee_os/core/include/drivers/stpmic1.h 6110fa3ecbd1bb7185abcee753303ad1090d1aca - optee/optee_os/core/include/drivers/ls_i2c.h 6c1691ca8fd41135a8d571021414095918e1ddae - optee/optee_os/core/include/drivers/stpmic1_regulator.h b0bd034bd589dd4037f5d2c08c927680967378fe - optee/optee_os/core/include/drivers/bcm_hwrng.h 03e62f840c1787e03eeef8e2651241d857e9db43 - optee/optee_os/core/include/drivers/bcm_gpio.h 58ddebbef8bd6c594d871fb476d88a5f9831153d - optee/optee_os/core/include/drivers/ls_sec_mon.h ccf8b37d1e3c2b88218a2f4a5527a5351e578154 - optee/optee_os/core/include/drivers/stm32_iwdg.h 13f6bae233237743e412afcd68f284c9ed5dbaa0 - optee/optee_os/core/include/drivers/clk.h 15c9e1f1141527fddac70ab4b2c014fc7d6bc9fe - optee/optee_os/core/include/drivers/sprd_uart.h 0052e6343728b9d0478a53e48d52e63fdf849444 - optee/optee_os/core/include/drivers/pl022_spi.h ffdb782c56f2fad968e061ada29b9f9fbf53b964 - optee/optee_os/core/include/drivers/caam_extension.h 5ff0b0a51178c901092daedd19fb97ba89033676 - optee/optee_os/core/include/drivers/imx_uart.h 0d14069df1c50f642343da9b04da98feaaa60fed - optee/optee_os/core/include/drivers/cbmem_console.h aa9e92efc98f9e0aa945c7a89dbc24edeccf22a8 - optee/optee_os/core/include/drivers/cdns_uart.h b1d5544ff4f3ab0503a7b7403cafc67a0893bc29 - optee/optee_os/core/include/drivers/tzc400.h 6afdb461835883d1f14f1359a5c3400225542c53 - optee/optee_os/core/include/drivers/ls_gpio.h 406ff8e0cfe26a1e6e63621ffa9ac1176426c376 - optee/optee_os/core/include/drivers/tegra_combined_uart.h d23e095f310bc590363cdcd5017e718a87f5d987 - optee/optee_os/core/include/drivers/imx_ocotp.h abea729d88bd897be58ed6c9534b6d37cf914d57 - optee/optee_os/core/include/drivers/zynqmp_csu.h b86965bb5304387c459eeff497e0bd9b83c5ddf4 - optee/optee_os/core/include/drivers/ls_dspi.h 20aa80be5a165588b6d87d778ae56cb924f4f8dd - optee/optee_os/core/include/drivers/scmi.h 54f6572933ae458e1115bd8d43337c0955900239 - optee/optee_os/core/include/drivers/atmel_shdwc.h bbd9f402bd751cfe638fb2585b52d940de3cd704 - optee/optee_os/core/include/drivers/stm32_tamp.h 01e3e3b8a4910f25dfdfdd865b70e885b8eb5151 - optee/optee_os/core/include/drivers/versal_mbox.h 5a4750980a258bf284a226cd8646a4d9a4f20486 - optee/optee_os/core/include/drivers/imx_mu.h 70c182404c24a9fa1b059962400b894e241bb626 - optee/optee_os/core/include/drivers/stm32mp1_rcc.h f15cc62ed1de06587145c0fb453cb291930709a5 - optee/optee_os/core/include/drivers/bcm/bnxt.h ab510c035d99dbaa743189d33aad9ea7118657ee - optee/optee_os/core/include/drivers/imx/dcp.h 33ea27d3d7b5742a187f56005a3c9ef39258ca2a - optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h 6d6fe341171b0aff38656211fbd1e2080b8784a0 - optee/optee_os/core/include/drivers/tegra/tegra_fuse.h 9caf071db678be64cccc5729f716abe5d1b44353 - optee/optee_os/core/include/drivers/tegra/tegra_se_kdf.h 4a198e834d4cbdca4a981db0189327d923feca02 - optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h 85b2be535e1d7a67ad7dcc13cbef547e8a1fdc22 - optee/optee_os/core/include/drivers/tegra/tegra_se_aes.h c43a36c90b5dc3d59157a90b64bc67387c6eeb80 - optee/optee_os/core/include/drivers/tegra/tegra_se_rng.h 077a260e86e358ef193c8be4014a2e153f873680 - optee/optee_os/core/include/drivers/sam/at91_ddr.h b08482914acc95186b72c3958214552a60f2cecf - optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h 56b607a2dea23df516e984c6fc8fcd88f15d5d40 - optee/optee_os/core/include/tee/cache.h 442eb415369cd5a3b0ce0122ade4dad47a62e645 - optee/optee_os/core/include/tee/svc_cache.h 6251efcc663e5b7b2d2e3909adaabba03fb68f05 - optee/optee_os/core/include/tee/tee_fs_key_manager.h 657ef3fdd6eee0127813cbbc0b30f96b020ddad7 - optee/optee_os/core/include/tee/fs_htree.h ae129424808a418e6bac7c413d61d8e68b77f1a5 - optee/optee_os/core/include/tee/tee_fs_rpc.h abea67617b2ab0ac70350ff3fe67b738eaa3645d - optee/optee_os/core/include/tee/uuid.h 261ffac302a6e4dfc609d264ab8a2f5c8f611cd6 - optee/optee_os/core/include/tee/entry_std.h 985b521fdf5c6b861009db340a64b69916629c81 - optee/optee_os/core/include/tee/tee_obj.h 9c9452532e8c96703b27a5fa32a17686296b03aa - optee/optee_os/core/include/tee/tee_cryp_utl.h c3d0c51429849d97786fb4e47f9a1903d00f27f3 - optee/optee_os/core/include/tee/tee_ta_enc_manager.h 75b991d9820ed21b0e6aaae7716292815e436105 - optee/optee_os/core/include/tee/fs_dirfile.h 83624d48c6657bc88f152412c4b188cb45c321c4 - optee/optee_os/core/include/tee/tee_svc.h fd483467f8bbbd73a4715c099b3cef4143fd9fa2 - optee/optee_os/core/include/tee/tee_svc_storage.h 49a43384e80403de5b68e7c51b49d0ab2cb72c20 - optee/optee_os/core/include/tee/tadb.h 4d806cb789bea5d77548fff5db9fd2efaba6e6c1 - optee/optee_os/core/include/tee/tee_cryp_concat_kdf.h 751b511848af0dffbda5a13f33e56b5edce71560 - optee/optee_os/core/include/tee/tee_cryp_pbkdf2.h 904e71454435133456b0c322cf904d5c59bdf624 - optee/optee_os/core/include/tee/tee_cryp_hkdf.h 282d054a700343402b5ffbf55003e16a0e40d567 - optee/optee_os/core/include/tee/tee_fs.h 736098ff42612ea5b4b62eb75748c077b386bad0 - optee/optee_os/core/include/tee/tee_svc_cryp.h 5d5bc9425b1ee3986b607bda1c87fe7358ac446e - optee/optee_os/core/include/tee/tee_pobj.h 13d33b2eec5bee8db2ab00fdf9d382e998437f6e - optee/optee_os/core/include/kernel/tee_common_otp.h a3920a6899bce55bcd3fa5d64f5bb7ca1e8b76e4 - optee/optee_os/core/include/kernel/time_source.h 7de5f721ad13121bcf2d0de7f6a9ea4143dd9f86 - optee/optee_os/core/include/kernel/user_ta.h c39885dc2548b8d6723071bcc766bb513e3ef78b - optee/optee_os/core/include/kernel/user_mode_ctx.h 079022f97400edf9b24bc33342d83d5a29904660 - optee/optee_os/core/include/kernel/pm.h 343ecd6ccd2cab4352a674c9ab3a15b1c1ba21c0 - optee/optee_os/core/include/kernel/misc.h 6a70452c8b44c8e2c5cd9b2882d9b5b2523e6d6f - optee/optee_os/core/include/kernel/ts_store.h 0e119d6c1c012d0e897cd92f4d1e69edb103d332 - optee/optee_os/core/include/kernel/trace_ta.h c1f5708a89345bd1d1e59c0998656cb1b410984d - optee/optee_os/core/include/kernel/cache_helpers.h f8c3e09feb3eb6829317622723491376e16ad403 - optee/optee_os/core/include/kernel/ldelf_loader.h 4b118e15613afc9762f5fffac4cf75718a1e2365 - optee/optee_os/core/include/kernel/embedded_ts.h 5981e9060b7c5809d07b6470818fbc8106b6ba1c - optee/optee_os/core/include/kernel/timer.h 03869d1183dcc5a128c46283d613b819c265b46f - optee/optee_os/core/include/kernel/user_access.h 156f0676f16613690d53954d8970a207696ad998 - optee/optee_os/core/include/kernel/boot.h 08718b75d19035055180740c78363d96b950f76f - optee/optee_os/core/include/kernel/scall.h 43d7208ecc74a9e5dae1a0f3a0952edbd3f50444 - optee/optee_os/core/include/kernel/dt_driver.h 1f01922d333b66cb291425b1df13da258ce3c63a - optee/optee_os/core/include/kernel/ldelf_syscalls.h 590c3ba3b3785bd1b70f32788080caa459b55454 - optee/optee_os/core/include/kernel/tpm.h 50ad6b5029b19a50602abf8eb47e8e9899f1c5b6 - optee/optee_os/core/include/kernel/mutex.h ea06c194fd6a73003ffa0e05277da5d7e959ad86 - optee/optee_os/core/include/kernel/dt.h 3c866070d82642a38f13295e6f77062550edf5ad - optee/optee_os/core/include/kernel/msg_param.h bd8e3321c7ecc34efa571fc5e86b54d71cb6528c - optee/optee_os/core/include/kernel/thread.h ad2a242f3d2159af1fbab6dd61510bffc9c4ab5b - optee/optee_os/core/include/kernel/wait_queue.h 625040376d7bc280e4dffbe23e77e046dbf40e2d - optee/optee_os/core/include/kernel/asan.h e4719588b0cc670eee34fbf59d8d50f39cdbdc45 - optee/optee_os/core/include/kernel/thread_private.h 20b6809c10b27e0f3f68a37fb3e63acdbb2ed77c - optee/optee_os/core/include/kernel/early_ta.h c2ecc11bbd7e8f0f5790187e95cf6e75d3de949f - optee/optee_os/core/include/kernel/delay.h dec752b6f205f5aaebb155fc59b0b0dfb271fb92 - optee/optee_os/core/include/kernel/ts_manager.h 008387623d8bffb1af193f51ceef6a0e1ee50d27 - optee/optee_os/core/include/kernel/huk_subkey.h 2557d4fe44597586a3ba561a107751dcc6371950 - optee/optee_os/core/include/kernel/user_mode_ctx_struct.h 7beb0d03bbf670fec4501a0f47399d2688f320ea - optee/optee_os/core/include/kernel/tee_common.h 7a061ef229094709080ea9495ad8bc590c005d4d - optee/optee_os/core/include/kernel/tee_ta_manager.h 583639447d8f7259b6621ac01705f412b6077543 - optee/optee_os/core/include/kernel/tee_misc.h 9580dfe1f16580758041e227e65811d04ca384b6 - optee/optee_os/core/include/kernel/lockdep.h 0f7eb297ee9d4dbf0e98871bec56c6dc261ba775 - optee/optee_os/core/include/kernel/abort.h 794f29e2701b79021aa45108e202b7dd5b569624 - optee/optee_os/core/include/kernel/chip_services.h 475dea2eb1f1a4e0e1d015e9237c945140be9040 - optee/optee_os/core/include/kernel/virtualization.h c7f3799e8db3911f324d4cb4892e433edaab0059 - optee/optee_os/core/include/kernel/unwind.h 9edd15d57bd1a295e7318d5910137712e72bf085 - optee/optee_os/core/include/kernel/linker.h 4b1ffaeb0730cb0bfc64e8e63c6bf3191816c516 - optee/optee_os/core/include/kernel/rpc_io_i2c.h 67fe768ec9472c46198b28bd25d0ba5672840d37 - optee/optee_os/core/include/kernel/tee_time.h 224aab4a1ea0d969da205086d9438a0975c6c8bd - optee/optee_os/core/include/kernel/interrupt.h 42bbd277b0848f680a125342d00ce386bd6eb605 - optee/optee_os/core/include/kernel/spinlock.h 340dc639cdcc2c5510554711d03b760103b790d5 - optee/optee_os/core/include/kernel/handle.h f2ab69b044d5bcce9b58ca8ccb79b83d50b5fb70 - optee/optee_os/core/include/kernel/notif.h 3e8149ef20283bc5089ca8714a3a698349e96d37 - optee/optee_os/core/include/kernel/pseudo_ta.h ff1ad215df335bbc1bf5a8365c96c64746e4388d - optee/optee_os/core/include/kernel/refcount.h 843ea779e8ef15af5a338c3845356280d56bbff2 - optee/optee_os/core/include/kernel/panic.h ed2772a8c2274cf02551a2a21cfbc33a7d81c2dd - optee/optee_os/core/lib/libfdt/fdt_rw.c a6759c569917866b44961c88629ae4f3f07ea686 - optee/optee_os/core/lib/libfdt/README.license 966e9a4b174cc33c3ba6126614b919ca0bfd09e4 - optee/optee_os/core/lib/libfdt/fdt_overlay.c 78de4be67ce92f5b90ff1ab89c2ba46a1a34da7d - optee/optee_os/core/lib/libfdt/fdt_ro.c 5ac5dba57124ad85911a67c10cf941f08ae861bd - optee/optee_os/core/lib/libfdt/libfdt_internal.h 0da7a6ee0118d32ca78e772cbf5a81f0cd62af9a - optee/optee_os/core/lib/libfdt/fdt.c 1c8f13cf72490970da6d19a7a3d3c06f18770f07 - optee/optee_os/core/lib/libfdt/fdt_wip.c e01b7a0052b837a4650f2c9ac75ad38c40edc583 - optee/optee_os/core/lib/libfdt/fdt_empty_tree.c e5657b776e8466d0d7c9578591d9c2ef45ef2799 - optee/optee_os/core/lib/libfdt/fdt_strerror.c 55fc5d2ffcba07e29948822d0b12e4bf5546b8b8 - optee/optee_os/core/lib/libfdt/fdt_addresses.c fd3af5baadbf42cca01d1a438cc826ae85a21f97 - optee/optee_os/core/lib/libfdt/fdt_sw.c c90d25bb7b217171ad9437ee0bc8d4e0c5c7f4d3 - optee/optee_os/core/lib/libfdt/include/libfdt_env.h 7cf2619336867b335fe8f3c919607242477ccfa0 - optee/optee_os/core/lib/libfdt/include/libfdt.h 265155048eb725a03c49a45a27f322ca6f3dfe6b - optee/optee_os/core/lib/libfdt/include/fdt.h edf93d4bfb11950ac75aade2faf0bf05d0aaff47 - optee/optee_os/core/lib/zlib/zutil.h 8770ab43c9050b824c646f6e6cee8b3c0628cbda - optee/optee_os/core/lib/zlib/inffixed.h 47e5da9b88163c7194af9b7b6a17fb46ca08b009 - optee/optee_os/core/lib/zlib/inflate.h 36c4f51e48f8320621c5739dd2ee69ef0d973a21 - optee/optee_os/core/lib/zlib/gzguts.h 00b226f75f6beab393031f6893b2868c707d0d0c - optee/optee_os/core/lib/zlib/inftrees.c 8139ab5dd86e53ccbde7ba4e78200db4cd79f9a9 - optee/optee_os/core/lib/zlib/inftrees.h 1e0b1438feffed910661d48b2b793a5f7c308f06 - optee/optee_os/core/lib/zlib/zutil.c eb37e780cdfe0dbafb29c0fa8629125c6e19bd6a - optee/optee_os/core/lib/zlib/adler32.c 206b2054814df6c3f42f29c045d584c6a25c462f - optee/optee_os/core/lib/zlib/inflate.c 5121bcf9ae9f1eb58b39c4debbc5931e5be16434 - optee/optee_os/core/lib/zlib/inffast.c 341003df806d2bcfcbd194fc3f9da99919b918a9 - optee/optee_os/core/lib/zlib/inffast.h 4192c931405d13fabed42ec8725255502d35fbcc - optee/optee_os/core/lib/zlib/zlib.h ce569e81ab26f5eb8d922b18be6561af7876c4e8 - optee/optee_os/core/lib/zlib/zconf.h 79b1451ee0197c749cd4f07450ed2d374f1c3cee - optee/optee_os/core/lib/scmi-server/scmi_server.c 619aa8e61beb89b2df060ca24485432e8269b5fd - optee/optee_os/core/lib/scmi-server/include/optee_scmi.h 36ca35680a4370d4f993961371d80d2e7b777458 - optee/optee_os/core/lib/libtomcrypt/acipher_helpers.h ef50fbda210143489722c5c073b049220aee69ce - optee/optee_os/core/lib/libtomcrypt/cbc.c 2449139582c992c16e854441a9adf477c7b7cbd9 - optee/optee_os/core/lib/libtomcrypt/gcm.c 518d56bb8519843ed52fc2ba83bc4fb568576c65 - optee/optee_os/core/lib/libtomcrypt/ecc.c a001afe7f955e43839c5e0d73be3db5db77d94d3 - optee/optee_os/core/lib/libtomcrypt/ecb.c 9197499a951acd6f4952270e28672de2d04696ca - optee/optee_os/core/lib/libtomcrypt/ctr.c bd085d21425692efa0737d43fe957bf83da73e8c - optee/optee_os/core/lib/libtomcrypt/des2_key.h 3ff597cbe112f20a809342d56622442a8a427ef0 - optee/optee_os/core/lib/libtomcrypt/rsa.c bc5761862d3f2bdc223bbd894e1edffc89db0614 - optee/optee_os/core/lib/libtomcrypt/aes.c ac9a9648fe065d77e8a07c0f153c16784b90b675 - optee/optee_os/core/lib/libtomcrypt/cmac.c a53dd03d8ef444dc1ee628dd000ca066984be89d - optee/optee_os/core/lib/libtomcrypt/sha256_accel.c b1d9c45ed1f78bc67c1bf788fd2478f835b86f80 - optee/optee_os/core/lib/libtomcrypt/aes_accel.c d406e89a395c613f397920c807ff31640f85073c - optee/optee_os/core/lib/libtomcrypt/x25519.c 466eb4dd083c77261b455c56dfb3036243b0992e - optee/optee_os/core/lib/libtomcrypt/sha1_accel.c f2db1584836afadf8108bc4068ada599727f3a85 - optee/optee_os/core/lib/libtomcrypt/sm2-pke.c 2fc6c08d346f75feec7f1c1633ccf1ddc1ac7736 - optee/optee_os/core/lib/libtomcrypt/hmac.c 1f8c0a64e4cf8b1399017599666898c92a705a3f - optee/optee_os/core/lib/libtomcrypt/dh.c 181064609b067d38f551f69dcacc2d7a6ee4c249 - optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c a2ecdde9b88869f00656b532502bf2e1c9c778bf - optee/optee_os/core/lib/libtomcrypt/shake.c 6d7a529ebaf23ae4f3fb74ea1d5774041d190880 - optee/optee_os/core/lib/libtomcrypt/dsa.c 72b382fc200ec2a39395f48c821d263bb827cd3c - optee/optee_os/core/lib/libtomcrypt/sha512_accel.c bf7cfd733029fd500704f55382b02cd8fba1b84e - optee/optee_os/core/lib/libtomcrypt/hash.c 627ba519b1c58c51f6ba86d4c3efcf948e497db9 - optee/optee_os/core/lib/libtomcrypt/sm2-kep.c 4c84ceade0de9502fa8805960179c1dddbff19f6 - optee/optee_os/core/lib/libtomcrypt/tomcrypt.c 422469b123ee31fdd517259a2ff73fe03da28d95 - optee/optee_os/core/lib/libtomcrypt/ed25519.c d71f169898b1d8fda6a85945b52a67c6499afaa3 - optee/optee_os/core/lib/libtomcrypt/mpi_desc.c 191319cf67c91dac0437c501694f9973ada49045 - optee/optee_os/core/lib/libtomcrypt/xts.c f38de7925c7043b9c008b228fe88f291f90fe671 - optee/optee_os/core/lib/libtomcrypt/sha3_accel.c 99aa558ed75d6462b266bdab24faa189c03b4563 - optee/optee_os/core/lib/libtomcrypt/ccm.c 999e42770e9ee014be2004a0f9ce41d08a2002ac - optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_mp.h 5c28c3c8b5fdb83a197148d44816e8b005affa3e - optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_init.h c991e82af32c3fd33d4ca7f63a43c46aaa3a8af5 - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd320.c bbb1244d51ea6efa2a0d6fd5ff5d1a6b507eb3cb - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd128.c c4e009d4708e3b97b2d83467411f582076ec374b - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha1.c 699622196fe40d368c4aa87afa335085d2d7cbd8 - optee/optee_os/core/lib/libtomcrypt/src/hashes/md2.c a24770ddff20aa047ca6e50ed3b40f67fb229213 - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd256.c 3c19181cce8bd461cc6a736ec3f3940ec737bcdd - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd160.c 82aa1b04a2ce5276fd516e96169dc1b0c2432bb6 - optee/optee_os/core/lib/libtomcrypt/src/hashes/md5.c f0e38b2df179903a5c62a5d1223c27d9468f2b55 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3_test.c f7476e6db75e35d781ab4d7ac8fbbb76133f2158 - optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c 17750b4d62fad12b1ae16ef01a8ffa2cac05fe1a - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3.c 1767c79b4e8637fd2636ed3e5d54dcd37cebae04 - optee/optee_os/core/lib/libtomcrypt/src/hashes/tiger.c 50f0d32cf7879499990c4ec792546db1e812dfaf - optee/optee_os/core/lib/libtomcrypt/src/hashes/md4.c 436cc2c14c7f7f513d234253ebce325da3441faf - optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2b.c d4fe8714b77fd3ad07260899bc8b5307e2d44e68 - optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c 5c4268acde331fa5dfc75643f9edc2c04189e29c - optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirl.c 63de08d2a37229f4bc2e4138db49d71e7f5786d0 - optee/optee_os/core/lib/libtomcrypt/src/hashes/chc/chc.c 3b7138b66d581516a8dd7568842636ce576e8f33 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c 18123fb06342b70d7c8af10d2c72fd07b75e1d2c - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha384.c 91834258fd0a291b0c2e8b5a43b6bd8f7278bca6 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c 3d396867f33dd56b9cb7f66e66c902badeee4bfc - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha224.c 3ff874c5735dc5e5d895621a56ed2a379f35f3fa - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512.c f25a1dad013d500b85f3eef3b3570f30a88b8937 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha256.c 123f4981edadc5f102d34b0ba1b5a187c185bba8 - optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_file.c 0143b2df7c00d23cf21ee3f0a263e80cfb42788e - optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c 01fc3d71a3f1525612e644839c7a707c1e5a1af5 - optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c 06ac2272160baaf80405c2bc2d9ef9a5295548b4 - optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c b1696e891350ceb540ac60bc6d4fc5601ae109b1 - optee/optee_os/core/lib/libtomcrypt/src/prngs/chacha20.c 91b049316fd473eb33d4807d7b5aaa9a00844a82 - optee/optee_os/core/lib/libtomcrypt/src/prngs/rc4.c 9931d364f7feeae167aaad25aabc387977444f87 - optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c 94ca15102c5937a658d63a00e39be8d7ce0a25fe - optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c e618ce5c3d8409cf47b68ba9621e64262846a123 - optee/optee_os/core/lib/libtomcrypt/src/prngs/sprng.c 65bdd642447c1d4dfc26f0f35958f0e1f9dbf51b - optee/optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c 4b6959d31d2cd9d600c17adca9edd2b7fbb70bb8 - optee/optee_os/core/lib/libtomcrypt/src/prngs/fortuna.c 0175635dc4f43317153da8fa639515156755da5c - optee/optee_os/core/lib/libtomcrypt/src/prngs/sober128.c 51e23c33fc2f379b97fdbb9128414859204e00a4 - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c cc60780ba62cc198b8657fb2994150ebdbd9aabd - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c 15c26663221b68b94b5e2f66b93c1b4468d6b956 - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c 43f7927b89b648f1b642bbe96a30329482a96706 - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c e554ce2b664e1b21e037000eab5b05a464e2f913 - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c 0370402bb2b440618f27fff3e9a7d3e2219a348e - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c 7c4f40cf2659b91a59b92ee79867fc47b44affe1 - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128tab.c ff214c34d15c197a91a236c37775d89e959c1bec - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c 18ce9329f7f80ff15e4e96615479074600a7ec87 - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream_memory.c d6981e9defa0ed7bd29fdde4dff9567394bf672e - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream.c 421494432d61682c13c00cb14769af324f4694e7 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_done.c 0ecad8f59cf056ac38226599bdef384c2e52c733 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_setup.c a1c69b888c2662b3db2c4343318cfed05ce1a262 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c 2f7b628448c81541c1e80e9cd8cd61e1489736f8 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.c 408fed5f27e4bb531ec7c18c4ea4b85e1b3e25b4 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.c 95e2d29cf4201f1cc469997b0aef539883229f02 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c 76550dd06cbcff27a2d8ac4d8f8ef0428da2a4ba - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c 19529a1c91610536d1f56e09d8f7f0c1c44ed1fb - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c 1e3ea925d7df004fe7994bcedc4d5e0d9551c09d - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c d7ddc63403a0836fcb998d8a80e1d253aad3fac4 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c 51497c0e6a261a2ebe26056565149049e7154e05 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c c086c739c64705448b06feec7107cd47dedf997e - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_memory.c bfa49e2602c5cdee29bb880f6558844a31175fc9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_test.c a4f8195e9e117c1053f0272b7b26bc835bdc5337 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c 5d403e317c9deb62133d017412250702a48683d9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c b8a013b428ced9671422b507d6833d25312bd823 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.c e8f1fb8eb2b962abfef86027594a70a50023e9d9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c c1487e9b5be5b8d3a2662a6e37a477cf5c86bb8f - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c 21ad37425084eb46c5dd6d7917ce29b0758fe98e - optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit.c 4aca9bfe042afdad9b57f2241c99597911fcb7a8 - optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit_memory.c 41b01b20223d2bb66ac8f419cf6f8435c9867f86 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c 2e8ea32ff629fd7635676de6611f85ef9285eee6 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c f9f61c74b98bf0afefdd73ff10efad3fafc465b2 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c cf8ba7e0b9c7428652d258729d7790277015c181 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_start.c ad7cdbcaef35b7db424ce95e64bf87baf2f4164a - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c 06cbb137bfc9d209674f552805083aeb3ae1516e - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c 2140195d11a6c4c204d39ed215e9600018bd23cf - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_done.c 85a32e2be465b69f7a4132892ad684cbcd8ea293 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_test.c 3dea7eb14320987637e14b812e161c7efa873b76 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c 336fd44e027effb81725392b176eb6fe5112e371 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_done.c 769fbede217b0ef928a9b5939e849a6efd2d0e01 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_init.c 75a66324c9304c63a62bc2a97fbc8ea51df97255 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c a2a2185a5cbe8319ecd9e65dbb720317d63814ad - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c 4a3b1b9453c09f7842de157e91770af0c0ed7415 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c e6d6ea2e6d96293a8daf46f6c0748936ccc3527b - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c 747a817bfdd38ce834a9198f1e176c1fe227b3bd - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c f07be7c3adc027be7917e3d412fe07dcd829fb1e - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c f3d6327ce4ffdabcd4e94091f0c4d616198e8f04 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c 9e461ccf05f3b82c258302f4a3eb873038978a89 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c 4ec1b143f43bb9aac8d870e9bad201ea008c17c3 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c eb172f92954aa6843672b7d7bc9707f7448bc1c4 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c 6cb5287688b6eee249f4ccc152104c13fc0579f1 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c 2301f47f63701715e30b0a1d5a7bcf2ff97644ff - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c 207351014a29ed0dce3fcaa0898b5c563262e0e1 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c f5dfcba990f115b494ccd95e958582ca983bfb31 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c 3a750d0cc44888f039a609e54a400af43310abcd - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c 7d9c7698b787a53e3bd28940cdd444746994860b - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c 56f1ea6d8684edf6bbfc6e96fec03f21f3ec7879 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c a5a54f70612eca541d03a7a560aba8cdff0b4df3 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c d6eb82ef3d2185e358f7226af8bb34ffff297694 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c ca7bed22fee4c69c65394f0811f17e8a4a3b3ea9 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c 2997b2353ddb192f89b3ec278ad91cdc8d7f2b62 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c ee5c9c1fd94d09694078522a5a470058f1aa78ea - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c c9abd410a11d44eb94910ab6d95bafc4e75fcbe7 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c 0303400a05e16078ca1944029c36280472d79869 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c cf2740b0fb974b94f1cc08890920c5e95f703310 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c 265e8429da2df62461fd0b313a0120c58034bd0b - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c b03f3351e97f9628fb7921eda85ae3f0b0534156 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c 6186f3e377626cce35518099044023ede1954ee7 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c 7cbf93842dddca33e61a035f80d15e15d1e0c609 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c 89d10d95e8d542d75a69d8f580d6ba6448096006 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c ad10e437f618657cf5b5e3ffc20fb6c5219a6db8 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c 6343e513ad46501c7b3c7dc039c8b246ea927590 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c 89b75f314fad2f247f3c02a8d043c69822182beb - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c 6166a8f10c3d96dd48d974f0c420288c79faaeed - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c 3e8b2b92ce4faeef2ac7282bb0e58253ed01bc41 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c 2f93fc0a9e1afdf93c263f75675e15d9aae63cf6 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c 4a0d52f29c5da69ba1248de543b53f80f00f0358 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c a1361518be72e5f0a2c22cf2e99afc5155c64421 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c a0941ac3c7a39107c7f3049a9ce6b7cc3d120c58 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c 7b1c5747593a58fdf9669888bd86df7718579054 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c cf505805e8a15d2a7e342491371d6f38a799f8e3 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c f162118759bca19c0f87c3807df85b6373ae5644 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c d071d7e805d688ccaaf2b3f8c3b7bc5d68bbba1e - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c 60ead8187339abc082c6fb5cfa8ca4a07d5bd3d1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c 3f6fff56e90836bbb49e7e0f2ea08ef20a25dcc7 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c 792b2c41264e5daf5d14ec67d327f8bfd079d994 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c 38d9de8caef78490c170d9f138c49db6374e6a02 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c 9dd030615b3a2c6b70c7e24dc125673f88550909 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c 6799d4d2d91f4e12e8d866fd920ae847eb66d5e6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c 19aceaaa2254b78b3210d81efdb82d2909a5edbe - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c 650667de1f0e3d2308872cf4537ae49498239261 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c 9b663e83c3004ebe1725ad851bde5f946c0e6150 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c 4dd6870aa2c7606e90a94d802fa383dd8515b825 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c 487cb958837ebcf06f92ef604fb17b4a495bbd64 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c 7d45e3754a326d8386f2e536d6baa81554378581 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c 7c091098e78cd1fb572b8b2e843ac04d30099719 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c ce658863c830e150ad4cc3c3bf741b91dfa68c6c - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c 5f19a3d36e36aa4d6fd83ace3219f06916e307a9 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_done.c 946301da12005f65f7f0a5d5cd79114186db81e7 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_init.c df0f2138b4cb5a037739e226490a0d08bd268048 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c 5de251abffe4c5d5eea6c9deb2b5a3dd7c128147 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c d3aff516bc303de0bedf794c42305bb770b41629 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c 5fd053c692f154fa517d1a66afac3bf88a666dc1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c 83f9d3b22b6bd8960fde8524bcd094d2fd1bad6b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c 4c0669699a2b11b52aacda4fd2c617d5695da4c1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c 069dc6544fea4923f5ffc9ed6cb508d1e3be4b16 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c fb2baeda2808e719b2543a5bf4e92e86c5a8475f - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c 87188dae93ef2263dd1baa4207faf5551bf57bff - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c 93e89b145ff46fcae1c653ee70c2061ac539e737 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c 16d4c4b33c5e68749766312b86e074433514c453 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c af7e5ec699439a45de3f29a72e6779709ebce7ac - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c 727b4d190bb993d395c276fdc4b6772e7507af6f - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c 9874e24493855b4ccab70b0ff538125c23e3515b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c a1a4e685352d4984fd5d49522bcd50c4492ea66c - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c 2d89b89d0738d4db5b761d40f9cd02510f413933 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c 0af7bc735a8720e5b936a261204b1aa73a0943f5 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c 5cc80740578579a16d394fdd144d7d71daabfa35 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c 559a51a7d6a1d21918f5908f788bb294acf88bee - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c 00df47ac677f1c073e872b02d89d034defae3198 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c 9de6e2171df8c3c6a974888bfde2f9333e56e12a - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c 55555aa0f46d7b4575242255f0729e9da8593aff - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c 268ca7b0eb4a15158fd3f58ae75ddaa90a8f7eaa - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c 3199f0f705460b9182e1e9b543e800f7d26b305b - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c cf42e3ab0129e2962618a2b9b261e9ea20e0bcf2 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c 8f82752538241e4f3c3f48ccdb5bf6fd41d7e889 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c f60e6c18f07779e8b066581926c51522a92069d6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_done.c 782a71b6b10b0305491529ce9963ace0c26a38f6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_test.c c5f08bda970ba7d30ff7bee44fda96f5e6515caf - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_init.c 633dfd755ba58507be81b2d70c2d483d28ca9597 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c 30473a74f19214129f69b8b067d6d2d5a87a7364 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c f8f818328098018b9bc6836915dbfc34bafbf574 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.c d4dca139aea0166092d5665e29064ddda8901842 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_process.c a91a5e3eaa7bcde10bc135c0f63feaf78724d5ca - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c 9eb480ccdf51a957a9391e17f2740e53048dd90a - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c e045e646861478e232fea83658bd42d37547f4fb - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.c 62851dedaffe4829a9e1d62149db76a1986abd9b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c f8665c5b620a773ad0a216d19c5abc141e016573 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_init.c 9a94ec21fc09797428df52cdd5e9fd31d0692885 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c ff2dcdde770c5904024d8bd59763632a301e9790 - optee/optee_os/core/lib/libtomcrypt/src/misc/burn_stack.c 746776871c1d225104237b1021e530a23d5c1fd0 - optee/optee_os/core/lib/libtomcrypt/src/misc/compare_testvector.c ad0c66e6a4431f567b49915d01f026888538f63e - optee/optee_os/core/lib/libtomcrypt/src/misc/error_to_string.c 6adfd2c5e4b416a65be0e9e7d0b6a24c1a3589d1 - optee/optee_os/core/lib/libtomcrypt/src/misc/adler32.c 5c187006ec54c463347d528d5671b8e92f9b762b - optee/optee_os/core/lib/libtomcrypt/src/misc/copy_or_zeromem.c f4059601bb534681d08bbf29b543f5bc37d29267 - optee/optee_os/core/lib/libtomcrypt/src/misc/zeromem.c 90dd180fc585755ec6db549d5d69653fe83ed6ab - optee/optee_os/core/lib/libtomcrypt/src/misc/mem_neq.c c129c049a7b7b18cdb44284f93430835d0001761 - optee/optee_os/core/lib/libtomcrypt/src/misc/crc32.c 4b83b978826b5dc7e68898bde8d396e51a73583e - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c c2fe66c77a5e4ba8a09979753ec8fa3b1c9530ae - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c d0feb5c364be991806af64380cd3a6e5d7062ab3 - optee/optee_os/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c 1d1ff4347844de6a3d1d111125194a55c55cf30e - optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_pad.c 3c3c7ed1c6223f40663fab3cc95afff608de638c - optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_depad.c e0622cab6f654c9d78768c0037a71e91c7c904d8 - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes2.c 5e2328959d1d9fa3dfe651bc8390f56e97cfeeb9 - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes.c 8ea5fa890004eae1957192d67e017a2f68ad820f - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes1.c 779555900035522f3dacfa9d8dcb18c310e78d2e - optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf.c 78d7c916e74e8dba0076ccd8a784ef784d2a3473 - optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf_test.c abb752921991a5264ecf76f92d09589c9477d1d6 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c 63d0675dee46f130dd505b9ef11305f66b51d5ef - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c 81f55ffa10b11eb901eb4a3e44acce81c2582f84 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c a98c18ecdba584f662232ca582bb88b502daee55 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c d92b5cc31e60e6581ee77b6e9780353b967e8321 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt.c 0090a8c4b12094134c7e3fcdd6c82cd26327c271 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c 233015470408b5b2e38773c5b1127762f545a856 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c 5c81f4d8d18f6544665cf9385fabb100324f2323 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c 96342e249d7c747d11849bf1a4a2cfa99139134f - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c c261fdd28c1198d33aeccd35a7728d324671e3b1 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c dd27864633e7f1746e256cc07e47437bbbb4bc97 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c 1221efc9a518048e34fe881a93fe5c765524f34e - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c 26a169c33ea38516c1421f536f7bbeeb2983f01c - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c c22b0f36bb603c5a4cc0e043d1fc84ed5615c82a - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c 6809767adc93fcb15bd91fdd9e99a6264937a6ef - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c 18b723be741bf36e94966af24f7f0da9fa256f26 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c 23eb56683e5cb3b2a6203532f2261e1146584ee2 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c 9e47537140b5988fba0847120d3e311f83085ac8 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c 34b218af0b0d226b125bb51da3c2016bcde2eb62 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c 70ff3cb0ee05909a347b56392e40b79171d1d3ce - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c 07ad1815506e2a82911ec0c3fbb9dbe66466efde - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c f1821b4e1d8e159fc9eebb3c49abfe0f6eef8da9 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c d15ddf5b26ce2f13c726a540479ac62355bc4ab3 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c 80d8a64decdaeb241abf260380e42f406eb7e132 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c d4220e04397554fa19428f3ff33ebc5b80d93d7d - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c 28e1308aa1d2f79105cf6aedb36a9ea1664e3567 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c 082f0d654b13f0b93cbe1d28f01726941f0bac78 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c 994a86f2bda5d048c5755b0e7819184195f24ce9 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c 474440e2037216fed3c26f124fd92a96e2bf51d8 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c 209b907a121df459daa08c8ab473adaedc01f56b - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c 20925129239360b39ed195a0d8b6b99d59b890f2 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c 4a0a598b182902b1813bb584ef6dd3ae446d0c70 - optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c 6b7496efa00caecdbe62a0a85ac0ac8b7a637d57 - optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c 1a73cc544c8c9a3bb0d77497a5a92900c5acef58 - optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_encode.c e6d0978d88f10edcb4164e550bac09364d5a72e2 - optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_decode.c 2e8f9163643ed6d0b41b646077f77fa7c179ffcc - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c 4f6812ba75aa737fd7f24b4148cdf1b3a99e59e4 - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c 11a7db8b0e76dc35b70e854992156d2f75f98688 - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c f5d1d5c1f347ba72d7eecf6995812bd9b0443efc - optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_decode.c c2fa3c8655b71dc36a48c5aa409c9ed586f9c8d0 - optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_encode.c b4f980accf155a8df885c69266a8b2154992181a - optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_decode.c eb9ee827d87cbf5ee6013ea99a318a0e5c477a57 - optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_encode.c 9d2d04084cdc6c4c56cec3479af1ccb74619fe42 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc5.c 819970a30ad279c10add699d9bb08c1023039bbc - optee/optee_os/core/lib/libtomcrypt/src/ciphers/anubis.c 60505e6a888a893c8edf9d6065362453230d0d78 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/des.c 9748ebff9d560f59b42bb6c8c1dedc71dccbc225 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc2.c 02474538dadafba33694c8ecab5fc2e6d00a7281 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/khazad.c 06e4fcdd40cc84f756e818ffb70a63da8066c7a1 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/kasumi.c b0f8a843a280133fbab3d261ce7a7486c5f20bb2 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/cast5.c 48cdd948011ecd3e9298f56dce531d60ede7608d - optee/optee_os/core/lib/libtomcrypt/src/ciphers/idea.c 398a2df01e72511a00c4fd56ef10ba61c9e08ae4 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/kseed.c e28e47ef72883f05ef629df3d495fddfda0372f9 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/skipjack.c cfc7412e0fbe23e14536db6836f3da2102c02e06 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/xtea.c c870397dc946312c9c0304e8f132b1fe87eb18c3 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/tea.c 461cbf82c045454db297fe16c3c478c4cde8fadd - optee/optee_os/core/lib/libtomcrypt/src/ciphers/noekeon.c 840013cf542fd64a45cdea8afb965f8aa0e51df8 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/multi2.c 4e35739fffcd60f1f9971113810a08c7c7fb114e - optee/optee_os/core/lib/libtomcrypt/src/ciphers/camellia.c 0e87ea79442a67dec4fad902f2df7a827f1c233f - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc6.c 783f175a7e6e630e954aa409e43cc67a854e2921 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/blowfish.c d48e4087de75284fb9aa215069515ac90849dd5f - optee/optee_os/core/lib/libtomcrypt/src/ciphers/serpent.c 4d6e2810b820eb2b29529f2bb429d35841b3bdd5 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes.c 48a4a60cd68d5143a1998139b830ee8fa7e56faf - optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c f7eb0744775bb897d006417c91c5f5b4aac5dd92 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer.c 31702a5acb225e761e0a4cd0e4b4e0e31c5206e3 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer_tab.c 5f2865f98ba1100f2d497f84b78a20571393885b - optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/saferp.c b6e57c2661c58975ca885c612932e68bfeb45d9e - optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c 4a6bb1fb9b2eed818cf6aebf8d6fc78f108db521 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c 49b2782b96dbf7d798398be0b39ba922e5a21bf1 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_math.h 4cdf5186a0f57233bdeac68a7db9e2e488806fd7 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h ed9c10d0285b377accb1e2494f6286e154bed777 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h 23b6ced88dc0c3124f432f3017aba8b385df4866 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h 6e3431e86381584751e3fe17d1f783454fad2f52 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h 6603ac9ecc182ac6407d2a5bdd90f3baa4552f58 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_private.h 4e5b33b2454acbfaa9b2ab42a0a03fcabc598d30 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt.h 44976f48c4f37ff61e8b03ca839b1a65f273117f - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h 47a31bfd38f96720df80f298c98d96cb435b3ad3 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h 660c8803aeecea2223f2075be243bfdf24187599 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h 2e713c6c463faaebb4e01472732e51d74aa5b185 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h 941fea915f92af82307b36234f5ce179c0fd3025 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h d86162251e3b48c30f090b3d893a17106c1b59d3 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h b024a3e54d8b78ef88bc56740995d089836bfc81 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h c4d8079f35569279e5f30da5d4666d1a145c29e1 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h 406b6b0422373c9c2a3c3f85df960bd5fd4134d8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c 131a94c18f4c6d67111f71772ce64e30b214b7c6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c bbaf6a67e160f4064a99efb50a56e264bcd9722d - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c 344a33caba6182cfa38c93b69be392fdb85ac4c9 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c 7e7beaf2f29e72101e3ff7ff9cde8d32af8b6305 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c 9765d9c7ad353767665e26aa27114aed5064b9d5 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c f97b4369ca4a6cee89a277cd05e60345fcc88377 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c 7a444c752e2d4df2d1384ce8f9a56dff42a02347 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c 357e06818540426a6b09b30b6265482454ba9342 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c 2d5bca5df73d8684673df1d6ab38bae6f25cd304 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c 7bb1feddfc1ba6fcb69cb4ef537c5a0dfafb8d1e - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c f804f75c30cacbad97b14cac9f9603f27f4ee67f - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c fa6b0f40cef3e152cec36c4ccd8d895e10dc60ca - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c 67055fc35186b6aa83df93e46da7bcbbe92b1f5c - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_set.c 41df11b40913dcd9ec153132f10f527896611190 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c 94fb2295b17b0d88234119fb717d678ec352c9d1 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_get_size.c 47347830be6ee382ced26f00e0be055570804c49 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c 9a424e42fb17d230990378f002faa44cd171738f - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c 87a49a80c12d41e8594da7524050eba34e5f96f0 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c 9f43d136949b104d186b32b4e272ab71212d140b - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c a47196953806fe0b060f66e17a9f5c26db46a788 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c 38f5811d94e0c86e4215591ed40917dbde19a7f8 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c 01b964e18bfa23b2d17ae36580bb114f096fb07c - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c 979846f85b72946ff810edf5eafeca166d4283fd - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c 9701778bd557f9eb30009b82a995c5e31167eff1 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c 071f6f93d133ca61acdffd03ca03180bd812032b - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c 32efc4a6c51bd46b2e5123cff17d55cc8560d582 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c 3c7f07f8405b9f895d89a3ea2090632df8c19cc8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c e428a8a7e8121639e668ea708f09f5a768e4d12e - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c 26547d5e1492512ed28376c853daeed24108f559 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c 7fa48553c905b29d4a54176091d6fce2114399d4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_verify.c 3e1ac45da9df45134fb091ec1709d5464f79d2ef - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_sign.c bca50dcf7601a449f350e48f0db458f6e0377f15 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c 8d59b1b306078e34f08e267a5aa226debdf7551d - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c d06add7d54e686364cb1d56bc5c23a69c71597c3 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.c 82232e2e87681ab9ba1ecb3a51e964671eeb710a - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_make_key.c d32c3211c9738e6edeec863035ebddca34d496fe - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_check_pubkey.c 952b34bccc6c1b05ad9de3bcddb1cca3b46b4e58 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c ec26e921ae1e3e3d36d45dc1e9485f2ce7793529 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set.c e304ed0a492309f8b0055a4e147f87970fdf38bc - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export.c fb90bf4aa59ee4d6f4371b1ed062a7efdf83462e - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c 3f0628db016f76777bae6ec89728511a7cb6cfa5 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh.c 9c29bb5f9a40d49dc22a8b7c3f62c2fb6930eec9 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_shared_secret.c 2517e59c7961fc7b73ed472569df670355137213 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export_key.c af78940c2ff22884837509d7ba94f767ac3af81e - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_import.c a1886213cc203cfe7e6ef49271838e7d967f53bd - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_free.c 3b82a4885c17b3d11eae9d1f870da34e6cae9f0f - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c 4b2dbab5e2aa90bd324218ea5674fef8777f8473 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c fa3c683b57ff8087a2fd90fb5c6accf72d63ffd8 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c 272952cb667172cf8fba5e852b5b8147d03f3534 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c f547d958caecd824b0b17b1355530bcc788c20ca - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c a55666907f63f401c00cfa793eac033bc2226339 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c 5dc0463320e60a8062e4bb3b76301bfbb72227a5 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c 0803f50e230a9797701852fd02cdc9821544fa74 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c b2e238370d7a369638a2b76d7c64b726f3eb53eb - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c 2893671ff36eba57509da1721ac9e5cf8567b6db - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c b6d3f3a6c24debd170f1ec62a74d682113250cff - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c b0a3bbbaf6fb172cc402a25cfd4114abb554850c - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c bb5f98cabbead6be93d785dcc286f45498d5c0c9 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c 7da5513cb4e6ebca0d19c35d74509deb172ebac6 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c 0287f0fa69106c0067f42dcf123ce01e29d98031 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c 42aa854ffcb3552db4fb57796569ea830db3d9e1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c 6b5a515a99122e80c6c6b9aa06a86e21ee73b3fa - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c bc4963f87689adb59ace0786a7b43d6a677b8512 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c 280c3e6ecb5e86ef00f694afb173a251ce58babc - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c cf05860092837c42f574e893b097a13b3374da04 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c a5205a7b0f315b2ebe0a2ced975772f8a1057571 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c b482130a4f79e28597bcb38ab42cff07c19787a6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c 8149696ce9b92edc4b72e701857542c66a19265d - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc.c 5b57ce74997f89ba8f1107d442aca33bb2dc01e4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c 4703d1e4bec1f70e5e1b17f15db6ee3a4046b47c - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c b1285aa85f707bd46b815f2a877d32bd8573987d - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c 1303993f215f0d4001ad7ac1dac13696058b33aa - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c fe473b8190607030112719eb24493f1941c3e619 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export_openssl.c 1860b05d1e6d84e49e6bde6665be70d81cc9c8a1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c 450bf440ad3be5053c0d9c6d7926d5cdcd9714be - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c bf20409e528c89116d228521a61e12ec29b6b8e5 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c b51764d8bd42b7561f41b8a977e021f720d461f6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c c5c1644f8bcfb94a1e9dc96faf3657ba2ebb4266 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c b818e0a65fbcb65e56211555e7979eb98ece81a0 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c 1931064b040780af5b1dfe453878c4cffbec7c7d - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c c3b19e86b94901366e718206c46cd3cc4432b417 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c c8932926feb1db7458a4121747277fbf302deca4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c 966e686fb8e1225167a2e3a7c6df50b0540fa9c6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c f03fb73a557258c6ea41d3193cd6bd750a62245e - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c 257ac82c33135561dfe7b5c7edecb5a2d0cdf7e1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c 1fb03ce919d517f2cdd83c378d731a39ff656df8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c 450616e20f9d56c11a1adb892a3645a93741b105 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c 015e8b1e8df2b67df5666581c49ed3b443a17ebd - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c 3e64593819f63544e4b0a5e7d7aca57eb34eade6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c fbe398aee3a10e7dcb094e86282410752aa1a8b7 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c 1c00b1e26aaf1253c27c4f23b98535e45a041610 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c 4204640f642d5ddb2df36d5eb318b13aed778172 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c d8f5cf749289d6a9c685c94b34909b764e1d7689 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c 96db40ce102160544ab24dfd2a14926461815e18 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c f527339cc3a30c2b3135771f132f79c94331a0d8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c df15dd31ef7691042508e5eb5a7963483113cfc1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c 1a11b95c51b4280fc073baaebd5f749bf0b623c0 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c 8c6f5460141c1ee2b6fe1887243f5ee6ab21da0e - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c a9ba477ca5b2713fbf6217fa2b25888a448773dc - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_shared_secret.c cbc194b08bb465a7b3cea249824712fda8857789 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c 9e8045a9b7b85a4fd345a8606dda5a4529102a84 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c 812929f4e13a575e58aeceea8cd3c5db95ab2189 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_export.c 0672fb6756a04c5eec2b963d2b2e9798f5d94c5b - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_make_key.c f2e15ff205094f5a30ffd289282806adf3bfa02c - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.c ea6f9fec8d29d2a40e34eca954bf19601646c1fb - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c aafed90e2fb679630e5f4234ead1dbcc220b5ca8 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c c9b6246d4dfd821f49c4cfb15b0b6bc3414d69bd - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c ad22ad01c3f0cfb81fcc6eb155f0e48df5223102 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c bdfcc0fc58006df5d8906f179fb339eeece8a99d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c cdc82def06cef9eb373fb549f277544af32d2d40 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c ca628b8ab6300f40be2d696eb9c06cec680f4e87 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c 1292bcd4021db8959c6d5042550705be1b170daf - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c 28a82e82ca20ba6d4ef0d5d0da2afd9994aea550 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c 3fc70309a59d43216aa49ab5477df50823a97232 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c ddc24ebe07f30aff933f0dcacceca877f7a8c912 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c 3ca43288d74863f2acf8e0553554f4110d572e56 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c c66a829d9f1a1a0e936357a82b563385c99b38f3 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c 3547f3191ec66412dcb8347be374eca128c03c11 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c 16be383d4118fcac43cee6cf8550a7b4027ace1e - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c aedf07da8f7d1b98991abe3e3e74d0760c207630 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c c5977a968d09b999595cf145d3429a62599ca661 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c 36b1d4df09d77914a9621e323848927e19b9e482 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c ca146db1227ca30261685565e96aad77b75b5577 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c a7b792db24f08ecaf3dc061773572acce6754633 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c e597c83e6003b94ef2d3664d81d39ef668416724 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c 6dc60f80f7af76c0a1b5992f03ddea0435b439ec - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c cdbe2378f68d5da22b7a94428334cb11343dd5ff - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c 8eedec47a421b47090137b1e2da8eb203fdef911 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c 8412b0b3c04480ca5f376fefe953156f97d32d51 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c 769cca541575ba36865f25e1673640cad524581b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c 8a688cc8917314414fb10e6bf7557ac9b22f42d6 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c 24de714f216931c3f599fc8d1e2deb86c21b847d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c 2da5ad73ec9c0ef261a7a06266369434fbeddc4f - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c 9a3485d1bfab9d30eaf363de36eddaec1464396b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c 291e2e946e23e0e29c802af28ecfb68aa74a3179 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c df1aa22c0a11a444fa3e307b084eb35b6d651a88 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c f65972e7e1e35ea9bf3c750f6d2fbd3c22de8df1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c b85ec531d4f44b87eb3be27290a2aaddc246d62b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c 2c41e8e870f523500c8fb60f9d88b90dd079c9ab - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c 715c09b19bbef0a9d89511be2ba47db3eb184457 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c b64eaf809c7884f4963eabf55cbae2037d4aeb1f - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c 424afeec6f07fd7906055c91c9951d455c69033c - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c f3830f9b7b3e4c414480974538e07a107e11eb09 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c 6040a83b18f15c48008263edc7586ab2682a2650 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c e45dcd69212ceaa620d3a68584c8cc3d8d7d7abc - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c 2e24598b6fabfaad933446c87bd5a064a275e144 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c d82b04231f128724960a64f0099c8af38548d2d7 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c 61c080828e48973c7e450aca6d6e998b893001fa - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c 7a3773c30383a7999306b37627b17630b85eddf1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c 5ae066c005e04dc7f013a783713675e77547f565 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c e9d1241660244c310419ea1378b9ae323a7ac61d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c 18ca4c581baeb6b0fc04572980c8ff2c540588f1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c 6d28b44c01e719209cf6726c110c6b0601e3ba50 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c 9d6bf8a3d490c881c022ec153b9dfd96d4798be1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c 13994ec081d65c83c2a411ecce60211f79aa7f8a - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c 5c2277093dc1c4f2d6b877f924200805c950e697 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c 4ab4dd3b5bbbb87afcfc52966eb024bb4d0c8234 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c e50711035dcfcaa4d0c1fc32f433be0aa8d98689 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c 52132cd7a799e297b872a524bda661601b33e5a3 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c be4a439c97860d7aaf286c7ff16597491596101f - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c 3ed9c426a6a4649858e87dfe5a61277fc5aab712 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c f387f820036c9bddff6210310aafe78d14e6c4f6 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c 5cff49720c80fe773da512a51dbaaac7ef7a8eb8 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c 0fcf9b8d13534b36c44fbab36118578551653494 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c 2e7715416f0b9b81765354e9b71ac389bc674bdb - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c fde5cba0f1fbdcfa0af606a17b90c2ece77fdfee - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c efb086030db7d8223ec9f72497920413fe5b9cb1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c d6404b3d1b805e9236eb4d91f784191692cb4f3b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c 65c73948627beeb228b285cceb082340770d5dd1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c daee17f76d3539a02d8567dc943b2b3217098786 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_file.c 7314b670b2c1a382ba1017ccd3b3806fe451aad6 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c 5e2fa3a8a8b8c0d38d74aa0bab4d4cc206166453 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory.c 2588957db97d4b727a20206702de592edae7afb9 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_init.c 3657dea6098b394ec68f7c996eb8c2525646dafb - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_done.c a081274e2f9dcc2ed96ec2a4db00ededed0ec9e8 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_test.c 5a792633cf4c62bb31894bcce5bb07e78763b88e - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_process.c 7ec5d863f61666d818632fd057c4fe9bc1a879f0 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_done.c de921bd15503ba513e2979be7113493b8c679ac9 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_init.c 78be422e4801b343c32f4a4574075488109af2e0 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c 8fa264dc57c925de0f8f36ad8848c8b278694d5a - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_test.c 683da90e66dec7dfc447bac38e35dbee802d3b57 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_file.c 5c61eca352761007c4111cf83cabf66f712cb67c - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_process.c 9b028196ee6d1b9299d41bc2c6d66cacd1011ed3 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory.c fd77eaabb5a5ffddd12e2f91920bd8e657aaff2f - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c 21ade96dad372a77d13f421cc9c1f8d2290e239c - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c 74a84dcfca09518e42ab725a717c8aedc0fb9f84 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c 1336042d04c7dd5b0ee965be9d037bf654049339 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c 0e00b9ac2e143fc27c3122a3f3d9bc87d8282076 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c 539c06612340597abac186f272ceeec032082a08 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c eb8f24748a3fbff1fabe0be3ce91f76ace71528b - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c 0371334e645562a86984c83f6257967f26cf1464 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c 4a8d8ec6fb7faf70d806473ae0d8a3d1c9d3cc5d - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c 86f1332253c798f3fdfa01762ed1c64949a69794 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.c 6f1f256d9e8a6ee6660406b43866a0dd79fbd255 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c 31e9ff14eef67741c7e79e9b1a4e478222f794b9 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_file.c f9cbe3b6dd912225eefc54f7dee30754e366cf62 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305.c 5300bb1eab429d1a602a848c46b9dbed916d1860 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory.c 224913f37550084d0b6a11c46a674e2560b9f6de - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c 9bccb9e3b0ce1b901cd5e52d30d7b54b1e8c5674 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c c2f957e54093361abef389519c1a79136dfb5124 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c 278c6feea087176001778da10154df788711b864 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c 149949542f34fe4521472a0d3740f4ac64b23050 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c b27bb0657c7accb0df147f4bf193b12933a9d970 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c c987048ee653d7b9e528924cd4ea2041d81ffbd3 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c 93f44519ebb2341e9ca27ec077a77a455641dba9 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c 13a4a399570926073872b210027dc5539d30d44e - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c 420e593df278e8c4bce349965dc185a1654e27b7 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c 9bf71a86a4483d4e404521f696f591017b261b9e - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c 208bbe5ced04c13eb0e1d3b24e76f5c81345cd04 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c 7ef84ee8949eea9fb48ef217f1c8ff24f6adf1d7 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c 196fd89dd21f7f943fca9702ed9616a27edc7221 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c e853e7da65047812f5c09f5ed42bc85f5b2256db - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_file.c e29b12ee69c044ee575a389f95878c7498a62af9 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c 361ba0aee5e365c0c0cb186cb4aefdac17289943 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c 114da72cefd715009a772baebd50f69a3237da72 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c 8151c66fd55cb82b2e4252f211a7d14de20599e1 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c b8c88d3152a2d9384baf86c1ec61ebb26f13660f - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c f86f622ff3761a9086d7779d77559eddf2774ece - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c a3529bef5d5ca05f194021b998a1d7ba5fdec700 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c ac3fb83b5d619e067782a032452e215cc2ccc3b4 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c bbf18f6d75557cfdbb5aec0cb00e3df605536d68 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c bfdb58bcc629f18e9ee0daf89aaccb205454e950 - optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_memory.c 40dc7c58ad7c36c78900489dd9043971310b0824 - optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_test.c 23f68588e1e7259db12eff911680272b1742519d - optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican.c 9974963705cf2ee6ede4a5f04102ba8237fe707e - optee/optee_os/core/lib/libtomcrypt/src/math/tfm_desc.c 0519f4dfb1ed6bcad6119da63132e2cb99a1ed77 - optee/optee_os/core/lib/libtomcrypt/src/math/ltm_desc.c 829f687603d1caba9543ddddb56af948b6a6369e - optee/optee_os/core/lib/libtomcrypt/src/math/multi.c 6eb1e1c16c036e2717dc3ab41e98acde07da53a8 - optee/optee_os/core/lib/libtomcrypt/src/math/rand_bn.c 2ca00d67d4090191db790a545cd86d609c5678eb - optee/optee_os/core/lib/libtomcrypt/src/math/gmp_desc.c 4107a71b931755873657a1db5c1d361d3baad0e5 - optee/optee_os/core/lib/libtomcrypt/src/math/radix_to_bin.c 64535e883ae11fec86629844a95e9c1d7f02a486 - optee/optee_os/core/lib/libtomcrypt/src/math/rand_prime.c 5a3aef9006609eab6327112f5508e2991e7a678e - optee/optee_os/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c 8eb767695e5573271863a44feebb74683f2f7ff6 - optee/optee_os/core/pta/benchmark.c 6284c967a1103f26724ff4dfe45af409bfbbf948 - optee/optee_os/core/pta/secstor_ta_mgmt.c 35fdbb1aef5536f3741a6fd8413c617d3fc6ac1f - optee/optee_os/core/pta/scmi.c 1a3dee6c0209f34eb5cc01113ffa6b544f5cebf8 - optee/optee_os/core/pta/attestation.c 4e1b614df9067b7a1f2158f1d5111c1925483f9b - optee/optee_os/core/pta/apdu.c 5464c3291d0ccd05a1742d955c828fb6bff76cf7 - optee/optee_os/core/pta/system.c 4b7b26064a5527653817507ced6b5d36e09d75dd - optee/optee_os/core/pta/rtc.c 3ea15c610f4ecba8788d1055a06e13c3b6aeea5f - optee/optee_os/core/pta/scp03.c 14015171ba8ab23dce63f6011ecd0899f08137c1 - optee/optee_os/core/pta/hwrng.c 8217fd671d72116cf6419307db3308a18014e422 - optee/optee_os/core/pta/stats.c 6a748b8c571c2b207c9db79b56b491192bf22379 - optee/optee_os/core/pta/gprof.c 45844fe0a6df40bac193ad48ae86eef7eecbeb4a - optee/optee_os/core/pta/device.c 92265a3a661a4862d09043e5c3ed8787895b4d23 - optee/optee_os/core/pta/bcm/bnxt.c 5d347d3376095cbc05c1ae47cb6d4ac6f74ef5b5 - optee/optee_os/core/pta/bcm/sotp.c 9548805f4cdf2d64fe66f30a4518b5738878b0b9 - optee/optee_os/core/pta/bcm/gpio.c 1d96880636f5a98568edf08f68e5e4b38291da17 - optee/optee_os/core/pta/bcm/wdt.c c53ce6db2d7519d9bd08c02472fe525fbb768a6c - optee/optee_os/core/pta/bcm/elog.c 8accf96a33e318180c18fd79729c3476c4e4a567 - optee/optee_os/core/pta/bcm/hwrng.c f76d93f72808e78fe854329128254e40a8ae64ef - optee/optee_os/core/pta/imx/digprog.c 0b56b4c47bf29b408b9832b6a57ca5277c05a16e - optee/optee_os/core/pta/imx/manufacturing_protection.c 1141e0df408fb0977880fbd63e8a1575a2a81e8d - optee/optee_os/core/pta/imx/ocotp.c 1828d31f10e6236e1f4f6c98f71f34b61827f092 - optee/optee_os/core/pta/tests/misc.c 773d0fc2245c86d75271917a6eef93910cd5a5f2 - optee/optee_os/core/pta/tests/misc.h 598beefd2c0b1d1ed3caf79b7ee3f6fd4315b410 - optee/optee_os/core/pta/tests/mutex.c a27586aab31e93cb9ce669c13e202c989d6f3e00 - optee/optee_os/core/pta/tests/lockdep.c 64e6434dfd3be13b965104477ee440eec10fbaa2 - optee/optee_os/core/pta/tests/fs_htree.c 9d5f604852b526c4c03348962f3d622ead341452 - optee/optee_os/core/pta/tests/invoke.c 5334d9f03de114b60edb9b9b5e7037b10eea8c69 - optee/optee_os/core/pta/tests/aes_perf.c 5b825d9894d2ed56396b487aaa3d994d6860b837 - optee/optee_os/core/pta/k3/otp.c 9f086ff5817b522588e0b043af390b20bc659347 - optee/optee_os/core/pta/tegra/jetson_t234_decrypt_cpubl_payload.c 169bda07f69b89df46b79e7a085d3fc44595d2ec - optee/optee_os/core/pta/tegra/jetson_decrypt_cpubl_payload.h 2cbe5352d0e151803629138882b8b410cd377bef - optee/optee_os/core/pta/tegra/jetson_user_key_pta.c 186b949fc854bc97be7883a0f85300a6113bce2c - optee/optee_os/core/pta/tegra/jetson_t194_decrypt_cpubl_payload.c 83d3b7f9616db0d5e42b621f55691ec5d505b4dc - optee/optee_os/core/pta/stm32mp/bsec_pta.c be4c6a3071f47d6d836b24e210bc1d446aa9afcc - optee/optee_os/lib/libdl/dlfcn.c 902b546a61d836961ed0f5fe348b564b0583755a - optee/optee_os/lib/libdl/include/dlfcn.h 2ece28422760c949f999a648997f0e4f232ccf24 - optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md 69a1029c5445fbf82397087777714675c6aed1e5 - optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog 34cd5767e5498e0e9fbc3ea30953dbb7a30cc6f6 - optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md e2ad0770f50a3b483b020e4015860e4802e3b9ab - optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md 9c4135419c10fb8160ed25ba74f2e655dd524114 - optee/optee_os/lib/libmbedtls/mbedtls/README.md 2b8b815229aa8a61e483fb4ba0588b8b6c491890 - optee/optee_os/lib/libmbedtls/mbedtls/LICENSE acf6955c96e7b062fb476682cca44221182ce556 - optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md c5c0de3138dcf3adf8478d316468a72d544a833b - optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h 83fcbb151b339ff236e86dce0b26c7f4a24f4ca3 - optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c f48433f7b983f2e4bc0dd945c94ad7da76d5f4df - optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c 1e1202a1a70b33fc56dfc5e187c17011edb30e3d - optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c f8f18a16efdfd7aaa581fc625d16b1c3e55ce4c1 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c 315ee16fbc23682b7e4d5757716b16f5cd02bc4c - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c 1b8905fce80fe974d94b8c622fe8f1c9ffac330d - optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c 559b9e2bea2960c9394c7f3d6c3ce853a86da592 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c bdedcce806f7e967428c250acae28d2acefae2a0 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_srv.c 29af5c956f2a788693c3f61103071b8bed4ec090 - optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c 322993cbc8151f3520b8022f9f95ff9a3c20a182 - optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c 21c1eb3144519a4d6b901bc7c4710d2e46ead2e5 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c f5b2d834025f50f1f657e75b119ffb5eca0ce04d - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c 63f97dee98c3e121f09f1a92ce5a4db660b69055 - optee/optee_os/lib/libmbedtls/mbedtls/library/arc4.c 8c4d1ea180d89beaf123ffa211485ec970338882 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c 27337042477fbc35ca34acdb6ed9d142ac8fad20 - optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c e2802f6140845c3bf4498eaf768e5f76af606817 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c c518169e89e4a6a9741c048118a20187a9b5c9d5 - optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c efe4b23e8a0c98b570563531ddb3284914370a94 - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_invasive.h e4f22fee91436d0c50a565246c300a07adda1ed7 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c 260858d5b01b92f1a8f1bcbd987cd005e93a120f - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c a89fcca6031d01abe7a86696de3b42bb4a839986 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c efc6fd614fa60d6706cc4d36d961646d92edc8e1 - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c 271f6cfabb363b38f50d995deedbe2a97ee17223 - optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c 4935912b62ab72b3f50e5eaf29df7d5ce2b9e01b - optee/optee_os/lib/libmbedtls/mbedtls/library/md2.c fac77be2fd3e8b7fe8fbc68b56e8107eb47cab72 - optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c 453e24f27239b9150880e9edbafc1096ef2df104 - optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c c274b5a7e841aa574404844167c3f0c3d14c4397 - optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c 71b284a0544487e2958b45a953b397c5d5edd41b - optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c 3ba0ae44b8c9142c37d6b3eec1bb283353c29b1f - optee/optee_os/lib/libmbedtls/mbedtls/library/des.c 9413a59ef6b7123ce68204057686900330e067b2 - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c b6f08f5eec4486713b955968cd08783799e79c70 - optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c 6c8836c3ee0092aa55203d6b340e2a88ab1ad9bd - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c 9ca35438a2848ad8bdbf3810fe6b660abc0b6cb9 - optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c 38089efff8e763ca84f68899aa27a12aee37d52e - optee/optee_os/lib/libmbedtls/mbedtls/library/version.c eef47ec15328369abecebd4a9c3bf1d7d5a061d7 - optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c 622cef7a11f54b42f48a8a2acbe628943e1f037b - optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c 91bf49b8e21a175232f8f9ac0a27e7e29344e351 - optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c 61082dbe6e7a14d79f82c525f5bb500235b37448 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c a4fd9926ce0bf5211b4b61e2e83574f522a10eec - optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c fc5fa6471e433ad425b79bfbdd938becb5cbe10b - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c 9ddeb707be554648d86dbf8b3bd105cebf911eb6 - optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c adcbba8a5604dfc87c5fe2315b816fa96c5f7d7e - optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c f85c4897537e66e26f7b00502beb5f1b8b98460b - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c b255f5117b8d7c51edf2e480ea74bf97759e7a08 - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_internal.c b12c4de77452103680a51e14ebc8262beaaa1945 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c 6f78ed043b58503736206088d7114d6640a7e699 - optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c 18c9db10ef79e7521984a3ca7f367808e1ec1694 - optee/optee_os/lib/libmbedtls/mbedtls/library/md.c c31f931b210d449cd6e0418ee3f64599bbf66148 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c fa87c2cb698c3f1d4814e062984c0e3a18dc3389 - optee/optee_os/lib/libmbedtls/mbedtls/library/common.h c52c9609c2c6a156b85487c6c29dd205aca6489c - optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c f23224aa8aa469d56af749fea346db46e7f42400 - optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c 2c0509b66770248ba1f87c8701d23ebafb826fef - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h ff2f47eab3d90d25a4a3feca4c9c97d29e5b8837 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c 5cb4e9ad752529bb18f635e12f2e7a4653ceae0b - optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c 2a5883a66ffb4f0bf72035d66cd93a1da1212a50 - optee/optee_os/lib/libmbedtls/mbedtls/library/xtea.c 6ccacdbcb3d6683215a378812ac9c07a95d15b52 - optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c eff5827f73dc11e94f0cdb521b69c886b6d977bf - optee/optee_os/lib/libmbedtls/mbedtls/library/havege.c 6bc1bb1090d17c6661707282b09e6eb1a829b41c - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c ddc711088ca1bbfb07baefe70610dba57b3ed987 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c 5d28c38c58ee292a7fad605958ca7bb50a68e7a4 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h fa172fc71f540bbfc7442d35fc4e6bb8d66c32a0 - optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c a852ceb607571260156072fa6312d959950c6d85 - optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c 1b7eea33bb1515eb89b6cdd0a39214ca1233187e - optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c b1e5a79d68a7a1ec7f0275df720f96ef736ab374 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c a6b69690f3cd334d2902f9ee2bf9cf96549e0c89 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c 96e03b56195a5d547890a933bf2586653d4bbfdc - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c da2586312dc78f3baed16f9321ff36678be19a73 - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h d2fb6454dfe04574a6194efbeff38a1b67b3d0f0 - optee/optee_os/lib/libmbedtls/mbedtls/library/md4.c fc8e38cb560a03ad03584ddd456fd0b0402e3b07 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cli.c 1ec5e59dd3a1462a5fd643e8bb24f38deaf554a4 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c 2def7447401b608adce999138281423a3102b8af - optee/optee_os/lib/libmbedtls/mbedtls/library/error.c 75f272323fdb02057934dffc82b676c20a1a34e9 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c 8fed6dfadaaf2677ddc9e6da823396b060bcca16 - optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c 142ac144081804afe7d4e8fc50cff380303e0b02 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs11.c bc1b782ddea9e8c505bac2d0674df882749dd9b0 - optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c 9947e648b9c9cd3133a8d7a283afe20fc0142362 - optee/optee_os/lib/libmbedtls/mbedtls/library/certs.c 8cc3416707d175080cb571ca699249b993481ee0 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c 581c1aabeaadfff8296d06359503afeea30bb8fa - optee/optee_os/lib/libmbedtls/mbedtls/library/base64.c 0e792d29724a824da680ae05d8fcfffb924ea6ef - optee/optee_os/lib/libmbedtls/mbedtls/library/blowfish.c 39ec52f39c7a19416093db88d93a2d0850b6471a - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c 132e8598402370bf01ad8f97a2fd020c89e3649e - optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c 9033f80cc2775bdf8642698f000b1f14c17c2531 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c 8e110f23ff047d8ad91cf150b21dda15a8c51fd8 - optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c ebc9d7694d77dc95c9a26e172b1778334df73a71 - optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c e246ca77d621222a8aa12f52a8984410aea9785b - optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c b908bc4417b8167c769fda2487b88a62b987ed0f - optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c f7f70eab033df0e2aa8f73f3e56e4ecf01967b46 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h 7a8fd1f6b729f3ad210ea034763ec05999fc1499 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h c5fc28af127a0a2ec0b26b5a10db2916e8f46537 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h 2297980e8e469ca536cb0d8f6953f27288d83afd - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h c3786d1c03cc2779e4b50925d85b988380615922 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h fdab353d59e781049e2839fe8c0bd9fe5c7376f9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h da3320bde8f57af08bff72700a80d8f95d96b6c6 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h 73e972973c69f84a622ac147a84ea7b15f4a526f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h ba12324cbba3f3db8cc8241a119702ff0abe8026 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h 35916f94391efa0b5cbebe9b8e50842832671015 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h 82385e900e1d154fbde1b7048606ab6d682b07ea - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h 3cd46cd245df5c87b55bb5efc77dc6f5142657f0 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h 24d59951a54278751304dc0abc30bc19d34a04f8 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h 88ed65ff99b7a98bdc81116adf4b3cf3b93c3698 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config.h 0a7d606dfa4d654a551d1b0a2ca188e7b08c17be - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h aaf629ff227c300525b34bfb14b4169d1e0da989 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md4.h 3ff671bde0767ebc75fe6252c3fec712c4c70332 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h d876bd7b141720bb5c553f5c74e806e65ed34068 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h f68ba04bf10e7ae5460af4cd3a0a0aeef75e1b1c - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h 86fd1279228501f3a8124e575516862cae64f274 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h 2f556b5bb16c79df9985b5515f4efd98b8e9d36e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h e510c5c9d18bb20e5a0db4b7feafd16978ea97e7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h 1fd549849be8d4b4e5f2df80e9e0521b3f77af66 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h fd9c07978180a4ddaf4dc878c64425b6fff60d58 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h 3421e523a4eb7a40b760ae0fef477c206fe1c0a1 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/havege.h 05e40045faab7912fe526f549ed02e8e728accc9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h 2e912771a4bb2c76b64a5e33e8e4cf959bda360a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h 988814b4760d2244e329efc2f5a695a90b06b98a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h 0050c84a3902d0103eef8e3790304a672ad80651 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h 81184c66cf49b3a5fddf6f414045dacbba683c94 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h d112a7ee17bef0546621b7cb32492e267fe14e62 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h 382613af5b38ad8b21776442aa78c648f076ef3d - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h 61ef986ba7df9eb5e9af42d4350290efd2c6cc20 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h 6946d05f02bae8db69c2d8fe537bf1fd4e93c6c7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h 86ee6f8982ebee49fcbb54593bcfc4608ea03022 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h f02f5e69a9c8edafcaccd9257271628e5d451069 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h 42ef4ce799699bc086a6cecaee5e5f1248b52b89 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h 695db14013c2730f69e207f528656845bc4d98fb - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md2.h 3c23e8d56fc0fc5ca288a6b23d7d1e72689fce30 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h a182f69d5e8305d19faf1b88f3c6443f0c998d38 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h 7105549c051d678722d5b3c4b5a6eab6664ffe39 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h bf8042d59b2ba674077ef56511948fb2057bcb92 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h 9559b189986fa0cc09ddf64b2af4cb427195b47b - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h 3d4c418e2a25efd04b957f4a184e17a1173175d9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h 87dbe26bb03c986fcbb4adb6484e23669e3e8fe4 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h ef6dc18a06fe96400c6fc925e0eb3805631ff930 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h 879fc92ce266212bd186509f7c9639b64b914388 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h 6dcc94a51079bacc8ac9dd2f8cc2d886baaa5e53 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h b4b7b0fd5cb9db5e05afea5ace2811809ecd17ff - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h 97a63ba6760938a6a84ce283a36ba5e193958bf7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h d1d0f5c6aab7d5cbd9ea97e6e9b6dad1ab961341 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h 3be0e79f3eccb1145cadb7d9d57fdb2bd6b5056f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h 7ba60fe8dbf1a8014980df4d02edd15edf1d8376 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h 7c1598cb9035f535cb60545302c735df638672ef - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h e8934d06b86a0d71bb8e3a8e061b2aa7ddc811d5 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h f1bf57f612067bf2e4df95ff7a4135368a8fda50 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h 8391f7564988437ecbcbe07aa53684b8f883f4fe - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h 5d75d5424716ad4ad724d932ad1e2a0f4816d19b - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h b5bd802a71034f41daaa5d0f3cbad9840adaddb8 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h 8e7f7f04a47bd1833a9b06fada69ab68beb1f29e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/certs.h 587c56d3cde1593fd3344eaaa7a85ad96468054f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h ffcc5d17de9dc2b0f1abf9dd48f99cc8597c8d01 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h 6a23d17bd6e89b823200ec15a2e1aa1a6eeb75ee - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h 831d497ea55442be6258d188b7106ae6b407275d - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h 58d14a3da288383e17a50162b7ee8676aa39e30b - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h 8e69d040c9f7f246f2ed05821a0c12b8b479fba2 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h 2ea32a77038f43ab89a11a66e8ebe28467d2aef7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h 33753b5d5cad4c1743fd00279037e092bb447b06 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h 4cbcf3ca5862d0d701a55325388bc7dc46e97011 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h b29c34b6cc5f246b5f4770f0ff8e740a3ba995da - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h 64fba94be26b0bc251bdc4dbbc123b9c6d47ba27 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h 303d2fa577d2570f5862b2f24ed080db63839e3d - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h 5499103f9e51faf154bddc54e08336587fcd23e8 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h b9adc12e4a406da08cf6736975a560b5a2cf63ca - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h 25a8519a8e435600c9e9f0e4fb73628e8c26308c - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net.h 8f5a31b8baa24df22d43316bd594a9ee90d9b485 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h 3516e070c31eabeb823c760af684046cfbc8ca57 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h bab8fdc0f1df4dad69f3ec9e718c9a40081c486e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h 83b0ba9cd31fa8443be607606a5ed2ae11f69b1a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h f9dc451695e690dbe1efad8f404eec60095d44e8 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h 0ce5c274e6c19b4f0b153fa0ab9c55ea8622d82a - optee/optee_os/lib/libmbedtls/core/bignum.c c5faad859e41c84415cee53c68129957632a203e - optee/optee_os/lib/libmbedtls/core/mbed_helpers.h 17b0020bb8d91bb229a17505c5830912086d7dcc - optee/optee_os/lib/libmbedtls/core/ecc.c 98b5b0189cbb8c50b0e303790d23dbf9681647cc - optee/optee_os/lib/libmbedtls/core/sm2-dsa.h b68da531ca86368d8d211961616d067dca104cf2 - optee/optee_os/lib/libmbedtls/core/aes_cbc.c 9eac1bef00d42cb5d29355da4ff216ab65029708 - optee/optee_os/lib/libmbedtls/core/des3_ecb.c 201268ac06f2c70661d14ec18b1290902998eb64 - optee/optee_os/lib/libmbedtls/core/rsa.c e9ad5e77639fed16cb29a614b7ded9aafd47232f - optee/optee_os/lib/libmbedtls/core/aes.c 44c09d4b791e9fc7eb12c3090186b990a05f4484 - optee/optee_os/lib/libmbedtls/core/cmac.c 4be86702d2f54b1d3c9fa62c47c1c16e8f9a5210 - optee/optee_os/lib/libmbedtls/core/sm2-pke.h a86c6c8bf63ea21ef2492f49cbc071f2f23a1d35 - optee/optee_os/lib/libmbedtls/core/mbed_helpers.c 3a1838593a7cbf67a1966456b9e4e441e14368ea - optee/optee_os/lib/libmbedtls/core/aes_ecb.c 3eb60b38bd9b87944a242c659ad68d8aaa8e220f - optee/optee_os/lib/libmbedtls/core/aes_ctr.c bc4a14352a35d7f28ca65fda6e4625eaad768ef2 - optee/optee_os/lib/libmbedtls/core/sm2-pke.c bc890bd3de1fadc56b5b900e0d3f378f35e60250 - optee/optee_os/lib/libmbedtls/core/hmac.c 9f8f69d3262f16988e954e72c755c3e4706bde9d - optee/optee_os/lib/libmbedtls/core/dh.c 1e3080bd5db0189b057a3f4fa1d45dae9ce59c72 - optee/optee_os/lib/libmbedtls/core/des_ecb.c 95257f1b9669bd55e715296a5db0520dfef94dfa - optee/optee_os/lib/libmbedtls/core/des3_cbc.c 89b5b1b09c6141ce6cae83b42b24106dbf5d19d7 - optee/optee_os/lib/libmbedtls/core/sm2-dsa.c 4a3549fe50b6596fa95703bdad942578f79ff095 - optee/optee_os/lib/libmbedtls/core/des_cbc.c 314159d576fa3458bb67bf9f6ab24f9852fcc617 - optee/optee_os/lib/libmbedtls/core/hash.c 7cf5fb5fdbffcf6f9ad1ffefde20cb30eb66d58f - optee/optee_os/lib/libmbedtls/core/sm2-kep.c 27d0d017d652207089357343fefde8822d574a56 - optee/optee_os/lib/libmbedtls/core/tomcrypt.c af0ca4eb18666ddc7ea8c06659fc1253a3d96416 - optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h 82d195f6948af776b75bb8bcc34cb945ab8eb1fe - optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h 61a92d97bc038e1636f35968f5a75f708383e065 - optee/optee_os/lib/libmbedtls/include/aes_alt.h 51ba88c458d47c0829585e30ed93e07a7f5ee183 - optee/optee_os/lib/libutils/ext/mempool.c 47c2201804ad35107c694730f37c017ee288ee01 - optee/optee_os/lib/libutils/ext/fault_mitigation.c 8d6b22214c57ad89d47fbf50c9d2a28ec11c2951 - optee/optee_os/lib/libutils/ext/snprintk.c 9fd93f109631c93c98f7d21f4b2bc03867d03097 - optee/optee_os/lib/libutils/ext/trace.c ce50432f4d5515d5ce9fb398b5098b9c0ec12c38 - optee/optee_os/lib/libutils/ext/pthread_stubs.c 53a0650d0e1a37aefbb511bb3f422ca162180c36 - optee/optee_os/lib/libutils/ext/strlcpy.c ffad6974fa755ea998a6801173ebf69647d8e204 - optee/optee_os/lib/libutils/ext/memzero_explicit.c 7a501727fe2d0e89ac822ec9ecfc06ac9387eb69 - optee/optee_os/lib/libutils/ext/strlcat.c 89ebb1873af1f851bc8fc67e813f81eb6a676a2c - optee/optee_os/lib/libutils/ext/consttime_memcmp.c eeaf7cbef43d983ce60db9ac8731767dc6bbf22b - optee/optee_os/lib/libutils/ext/nex_strdup.c ece984c44b615c403bcea03f8d97fec4569856f1 - optee/optee_os/lib/libutils/ext/arch/riscv/atomic_rv.S 527c3d07f4d854cb770425c1d1bb43d87d25a622 - optee/optee_os/lib/libutils/ext/arch/arm/aeabi_unwind.c 7249fff01b1ca0cec36cca67bec4a1395ee4224f - optee/optee_os/lib/libutils/ext/arch/arm/atomic_a32.S ff0eea4f25438d8836034710afb20c6ff62d9805 - optee/optee_os/lib/libutils/ext/arch/arm/atomic_a64.S 3c9419abbdb07dffd661757f2b8acbc0c49e971b - optee/optee_os/lib/libutils/ext/arch/arm/memtag.c c76559d831152142d5a0612b9a2ba8988ead0414 - optee/optee_os/lib/libutils/ext/arch/arm/auxval.c adf6c7b011707e03c48439a6a7de0b07e91d5e59 - optee/optee_os/lib/libutils/ext/arch/arm/mcount_a64.S fcd9b20bfb493ed1ef33987681cef3c072605105 - optee/optee_os/lib/libutils/ext/arch/arm/mcount_a32.S 0e9c096815b105d29d59a8cfadaaeb5e7a3b7998 - optee/optee_os/lib/libutils/ext/include/arm64_bti.S 296cc431c36cb1c06ef0965e569bb8f0028aaa86 - optee/optee_os/lib/libutils/ext/include/bitstring.h 0c4e420d80821bc2e9d1c85cb5488cdba9b2dfb0 - optee/optee_os/lib/libutils/ext/include/config.h dd93b7320673f243262308cadb21031730b3eb4d - optee/optee_os/lib/libutils/ext/include/asm.S e0f599207b28b33bf06b5e1c02b650d0e1a2d7c5 - optee/optee_os/lib/libutils/ext/include/trace_levels.h 603efb52be462838f3f8f8f5ddb20258ac30f353 - optee/optee_os/lib/libutils/ext/include/types_ext.h 82c8f1ff88d4550ef30a6295467a3c9a89a49f64 - optee/optee_os/lib/libutils/ext/include/fault_mitigation.h d4f08bbbde731d1464ddd75a103de8d6d5cdf013 - optee/optee_os/lib/libutils/ext/include/util.h 70ac170a6c79b30435a4b8fef9cf7e98ea61e9a9 - optee/optee_os/lib/libutils/ext/include/printk.h af2b6927c92cd80ffae87a12bf87645f43748dd8 - optee/optee_os/lib/libutils/ext/include/atomic.h d0fd7d83680885f9a71f56435b92b078f79e14df - optee/optee_os/lib/libutils/ext/include/mempool.h 80947d734f9aa0143f5cc2a9565cfe10081f306c - optee/optee_os/lib/libutils/ext/include/trace.h ce8e8d219a06d536dfb044bd004db98fd595d438 - optee/optee_os/lib/libutils/ext/include/stdlib_ext.h 183abaee8b69b529765cdd0e2523118f88c563a2 - optee/optee_os/lib/libutils/ext/include/compiler.h 6d52c01d26b5f87893d70ca173d1fd712d53f4a5 - optee/optee_os/lib/libutils/ext/include/confine_array_index.h 5d1943eba944ecd7ffb277b76460ab47a379f73f - optee/optee_os/lib/libutils/ext/include/memtag.h 93a77e57894a180ceb9cbf485c96b316b0223286 - optee/optee_os/lib/libutils/ext/include/string_ext.h b5e7d766670b001150bb9d2fb65a689a8c9f3ca0 - optee/optee_os/lib/libutils/ext/include/speculation_barrier.h 86bb497d1cf2b492514391182b51ce9f223003c1 - optee/optee_os/lib/libutils/ext/ftrace/ftrace.c d252604ab38468dc215d8fff7e20420e53adb60d - optee/optee_os/lib/libutils/ext/ftrace/ftrace.h fd0766e5127d24a75662d988de4c18f5686b3020 - optee/optee_os/lib/libutils/isoc/isalnum.c f3a4dd8bf719bba595428ad39e580b4bdb83c0f2 - optee/optee_os/lib/libutils/isoc/isprint.c 69389cffd2f2392d520b42fb8a877d88184eb7ce - optee/optee_os/lib/libutils/isoc/fputc.c 78241abd2dfcf669e50f78ed7af96d4ab11eee84 - optee/optee_os/lib/libutils/isoc/bget_malloc.c 3849e364a583d8e2a6b06c73b88cbff340651414 - optee/optee_os/lib/libutils/isoc/isdigit.c 07859d16a6f156a7b7d53976c3ea35d8c181c050 - optee/optee_os/lib/libutils/isoc/strdup.c 15d9b02b2f680e631dc3cb4acb612c5051534577 - optee/optee_os/lib/libutils/isoc/snprintf.c 44884a714f6031d8c9899eda446ab6bd902d63bc - optee/optee_os/lib/libutils/isoc/bget.doc afbd6bbf47f8aceef9ce91f60a65246aa8579e52 - optee/optee_os/lib/libutils/isoc/write.c adf5b4c7851eccb3ab23eaa51e2c67aaea646dba - optee/optee_os/lib/libutils/isoc/ispunct.c 3c0076665f570bb3894f7975c7af19546b24b949 - optee/optee_os/lib/libutils/isoc/stack_check.c cc419cf9b3049ca5a067f8efc8b87fb21d16cc17 - optee/optee_os/lib/libutils/isoc/bget.h aae0aea5aeb4c700916f3a0cb796958a066f2033 - optee/optee_os/lib/libutils/isoc/islower.c 9bef02b228d5d11a675a74e974644af7f91dc6ec - optee/optee_os/lib/libutils/isoc/iscntrl.c 465dccda5f6216b5156acdf8d97692de7a6bc618 - optee/optee_os/lib/libutils/isoc/tolower.c 3871de5c02c34257cb8c03aea71c406eca1389eb - optee/optee_os/lib/libutils/isoc/isupper.c bd92a4e902b8f071cb08e11be594c2cc03b13e0b - optee/optee_os/lib/libutils/isoc/qsort.c 3072e334c9965c360ee485346541f37b1cade0ce - optee/optee_os/lib/libutils/isoc/strndup.c d7303541082db306fa6b0447bd5aca62f4cb8169 - optee/optee_os/lib/libutils/isoc/bget.c 66446d12deb5b2f6768b0037c5cd7f6bda49c01a - optee/optee_os/lib/libutils/isoc/fwrite.c bdba22e240af00ccb765dec28ab938c5e3619bd3 - optee/optee_os/lib/libutils/isoc/isalpha.c 29a7857f6999a06d58d700ca9bd712c157595adc - optee/optee_os/lib/libutils/isoc/isxdigit.c e50bee77ddab437d58aec0c7d06ad8e70066d752 - optee/optee_os/lib/libutils/isoc/isgraph.c b2a87efad81c7fc35f3f17a1507b650945a64089 - optee/optee_os/lib/libutils/isoc/fputs.c 486e4ec67949ba32eb52d521355b28c032ea31d4 - optee/optee_os/lib/libutils/isoc/fp.c 08ed68e1c3fcaca243143f636c99d7b1c7c325bf - optee/optee_os/lib/libutils/isoc/sprintf.c fbbd10cc345ddfe50e1ca5ec8a2e936b5cfe396a - optee/optee_os/lib/libutils/isoc/toupper.c a426f426e3093d41ca84adcdf9eefd3d37354379 - optee/optee_os/lib/libutils/isoc/isspace.c 6054fbc2e1ca96c1f5291cab671fc90d7ce00fa5 - optee/optee_os/lib/libutils/isoc/newlib/memchr.c 2424e0252f73a9e6fea420e9f7f2967538d56444 - optee/optee_os/lib/libutils/isoc/newlib/_ansi.h 4536b43b4035e668869db96685c3e398be901a40 - optee/optee_os/lib/libutils/isoc/newlib/strtoul.c c62c5a7633896186fdfc21ab5992c569d0b93d28 - optee/optee_os/lib/libutils/isoc/newlib/strnlen.c afd073d96ce316d15f065f34576779bf31b11b4a - optee/optee_os/lib/libutils/isoc/newlib/strtok_r.c 5a9624425bf1040b1f7f44f5391b07f0f54eb969 - optee/optee_os/lib/libutils/isoc/newlib/strstr.c 3eaef3643d7bc2740a34226b2b66dca0fd662558 - optee/optee_os/lib/libutils/isoc/newlib/strrchr.c f4be3b2ac744128b112751c273f2850ec6277a45 - optee/optee_os/lib/libutils/isoc/newlib/abs.c 0800e9eb716a2e65ba7a95b2fbd873749abb41ec - optee/optee_os/lib/libutils/isoc/newlib/strcmp.c ffc219c3a21638f7e62d3b658ee6c4a3dad8e628 - optee/optee_os/lib/libutils/isoc/newlib/strncmp.c 5c1c0c4053502cfc23acb11a61aef64e6a9f7383 - optee/optee_os/lib/libutils/isoc/newlib/strcpy.c ca1b181d9d51ccd041f7a54adb83afacde6591b7 - optee/optee_os/lib/libutils/isoc/newlib/bcmp.c 108514868e87a312a98be4104fdfa5f0b689a956 - optee/optee_os/lib/libutils/isoc/newlib/memcmp.c 5f94025cb7d772e0b69eb04008405feb9ef86a0c - optee/optee_os/lib/libutils/isoc/newlib/strlen.c 811f31f56bd454989b15ad39bd9201411a4971f2 - optee/optee_os/lib/libutils/isoc/newlib/memset.c 5604c3647615806cbfd5068d684f1127272226c0 - optee/optee_os/lib/libutils/isoc/newlib/str-two-way.h b1d845daf20cc5443488f37fac3559c721bcfb45 - optee/optee_os/lib/libutils/isoc/newlib/memcpy.c e0298efe1346c7206253a9f0f174acc71479f134 - optee/optee_os/lib/libutils/isoc/newlib/strchr.c ad3617f14072481d06acd4c17903f9eaf3301223 - optee/optee_os/lib/libutils/isoc/newlib/memmove.c f78df3e9bb90074ab9ac143f5e62bed8c2557796 - optee/optee_os/lib/libutils/isoc/newlib/strncpy.c 646239269fb199ffdc49b9001bd8beeded3a1e32 - optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S 24bfedc4ffd1c78df045ab1c725bd811b0531bee - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S 0f25fedd6c6f397a39b1254cce305242fe230e0b - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c 99b85b897d6a461c3fa3c1f9bd54fb771c45ae5c - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c 4d6df8e998067ae07c67580b5f7f261238c7cdb6 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S 30211cfa366caf873a7801a7ac8e5828d0518b42 - optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S 6a325e1881f32b8ca7c74367132e75f9318aff08 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c dbc715c45b8998c5276e4a7f3dfc71bd81a03947 - optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a64.S c9a1019f6ff1967d8aa48f5b5e7fc42a42660937 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c eea63204ff2fd371e116939e14a504bd9d17de4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.html 0ef83486a7270a31dab5ced482dfaec14b9a5b4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64.c 920cf94c441178943a1442a168fb4649cfe755d2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128Sig.c c841c237414b6697fc42f3a261082257cec7dbec - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c 1843081e5eaa9f77ccd80c3cba04e650ceee756b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c ea9e18329087b88e680a9b0e1dc3f73d78ffc97b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128SigM.c 5bd19e6fff94dd11976e8f78f6ef8b9af01d33d2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c e14e58254cc0fe0ce4710d073c7a4c41961df960 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c 49a30ac92f2823400a43a7b0789def54eac5d67e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c 25ad3859febf3093e91de0392cb0d7c98d3e9dcd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32.c 89e1c8f8d93bed98125ee2c0e27f4ad4b87f5f9e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64.c 3e4e1cde87c7d37013c4665489e22a5e653b9e75 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c 60cccf04237a9a059b26075b3bc4742662905190 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c f3c0c6bf5032a3f329e5637aa49336a98dc365f1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c eed7248a2360c629c3dc0b39a7b019c718c1f8f8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c 9c753ee79b20998c7b9c420d50cd9ca84b18a3f4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c 2e201e03147cc253f93e31812b6cc1fa19c54acc - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c f7e21606f0f60046e7ed31a99520969bf3cff7c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c 6772aca13808c91d5fbc62b23e65a9aba99df8ef - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c 6b7125daba8bb60ca3e2db6c38bf5cbc5df906ea - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c b28464c7ae4ca7eb7416555259cf21f36e3906ba - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c c32eb171afa353fe6d96c9fcc1b6bc9116ba3237 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c 136777686e7e2c7b3decdc75d9cb9e0f802b4dec - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c 440066ddfc6cb2460e07a86d2552d5aa6978ca47 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c 6ab2cbbff35bbae58c14a90419c2dd153b667063 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c 3f17bb81a05b30c928c6f3dcbd9d6c33f6dd808b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c 9cd0d76126fdd8add379caa20c766668256efb6e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c ef40011bbd21ac40df712f0f16dc844ee06aa453 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_add.c e6ad1063b924e4b96a1801d49b960b3d8534342e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c a5d1d8aa31fb5646e96d1f889729bd9eb7867e9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c 188a513a8b2102d97b435bddcaa70a13422fd36b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c c9372c8b60f9e67962d30179a0595294d74953a2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c 809dcde66eb6eff4e7af6a71ab240cdae5c11097 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c c62a95ceba02a10b8f43ebf0b1621e6a814f07ad - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c f79c163815f902511ac25f8f5a391149043a846b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c 68c9d3e3654c5107bd58185d3632d6e8c4b04687 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c 1d4036336aa49d6961f510e234caf45cba50d995 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c 5d1495da9f0d75aa3f5fa75b43c5edbc95dc1ae9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f64.c fab91920cf859d0f22562a98eea05a843806e70e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c f1663c2acfcb26909b23e18b18c43a4aecee1908 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80.c ed1a42257f7a11ddfb2896bb3db8fa6b6b799910 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c 3e0d54c15411c2c997b29fa7132f305ba0986d0c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c 47e7b19a3c969e8c6acf899992a2b3dc02ee894f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRight128.c a56defbdfcb63c086c83b3754d2848c2d67b561c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c fd6492962962b16aeabef92ff9542da4aae05f26 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c bf60482d7a8c7573451dd9d358a4f59882b4ecd8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c 23659a34fd66f6a163767159d9191aece60e9833 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c c8fa83b76113c38831b0a21b4b6359fe6976b133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c 7749e3a634b0f7cb154a734be194e52d612310c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c 60a64ea74aeaa87b706af4f0c880e551d68ee8f6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c 0db18e1a005858944af9123bb29580ebac102bac - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c 14119b8fcb0828e0621f0d1c0b3130721abcf3a8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c b4f539877d9b40f21099ed92d2e18a9f57f28566 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c cddf72a19a53f1cc1e2077dbf7e9269f0ba5cf16 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c cc614514257c6b0a721ebfbf2f2eb22e764e75e4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c 60f8ae03f26507e95f988d859c2a779d957c4efa - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c 8c11bd928370bc41568ae3c44ed648224268134b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToExtF80M.c ddf3732777273f55557aa33c85aaea98c3017a0d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c cc9936a7e89313dabf987a759166c6b627c5697f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128M.c fb78669ac8ebe25845bdac20fd3007ac6ed6e254 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c 74978af5148ccce4ca51465a934e52d8ff03fb9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c e550bcef98e4bc5091eac085dd5972d58c2bab09 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c 6eb4a2a36946f25f5528e564a0391b709127224b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c 5adc627cc2a4ed39719943fac8c29517f3d39bbe - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c 03ee79d8d396bc6778c8bd477647f5e7b2035214 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c 7bed7a39e5684ce23986346806ce19c0a2d198a4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c d2e10d43888a0af127c80ebb29261c8c424b217e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c 3d89aeb6e7880b1152564ff98fac17e80a4beab4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c 3088c598cdb456e47e280fd0bc369fb0d5e6d2f9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c e4be027468e7ee598e8835dfe5c58692978be102 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c 672608ed7c1150531f5d4e2b3aa274de76f24f44 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80.c 260bca4ccf486c140c36950f988253e30be3f9e2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c 27897b3a3e2b0f5cfd67ca737c35af7cc360c3cf - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64.c 32ee0bb66ee86e9f4d4f49c23487905e3e09715e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c 3314b591c37fbe10125dd1047b564db3968c7246 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c 6f034e453e9efaa8477ac48fed5ff48d6320f99a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c 20cc97dd02d91a85b8d58ab1373f550058a5a4ce - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c e0f5d8c33a9db5f50d0fc16b09808a48a8b052b5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c 25066beb2f05f436d718c8073ec11ad550f53ef1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF64.c 345b454a7bf01265db26b15ff80f98692e81fc5f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c 644f4fb69b6d67725a586cb47755d4472694dc54 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c 3c7d728ab8fa5d0e345c67d53f5335d672d8fd5a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c ff0afa5079cd15008d3d3386ac73d3b62a0c4d79 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c 9a156cc904d7427a794de20f093bdff4a44cc12f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c d7dec92efc7a7503386861fc8a67b770c78d50fd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c 467dcd8f83fcddef3d3402ebcc2c08822c68621e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c 5e4ff4edf1d3a006c61ca3098f1919088d42dd66 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c 2355160c0a3526eb32abd1d54fb01083a1fbe18a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c 6ba3f71a3a306c79f58d469163b33f810aa8faa8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c 623ab3fb8b679ac1b86f7c366eb192d128358f16 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128.c c3d4d8448c3e622688342aa49d892b84716125a5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c 8a4a364a4b4f144bc47fb5e28144cfe82dd3b585 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalExtF80Sig.c c7030401c4589ebe4ca9df47cdf4473be706e9c8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c 7edbff34e15aeda6b14e5e01fa34a2e4ec230d88 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c 757e08593f768490c92840e212583a4ec63dbbf9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF64.c 3166b1b25c791f37186ac5ace33c6369720cd72d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c 39e684d513bd8e1bc18146fe5b6b41ca6abfb889 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c a4bba6333e9a92cef62ff68ef528240c29173398 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c d724729fe9aff2647d82d44cf7c98ef024550f4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c 28ed562132fa508b794485f84e37ffebf0f45c03 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c 5547439bc882d6cb17257578b63ed5dea9e85ad3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c 4cc44bf1f32b533112fceaf74f2116052c251f45 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c d11f89d0268036c5e2190b2001b08b46df5a1496 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c 0ac05f3c78dd89e1084687237ede90311fc758d6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF64Sig.c a8cd508101d5d02ae58933c2b91b0638fe9ce308 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c d5a7b42551a9289e11b502dcd611101098d47502 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c 02501e2df1729d1c331ab6288158859f5302a791 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32.c f06279e2d0e5d4a308a35ce0eae73d18ff2b0ad1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c f394231a827adbe842d2249d968ff138ad99c20b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c 7fbcbd3346af638125a977564bb94e3a4112db4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c a6ea63bd09a37c67ab0db5c7378603bc343f7c4a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c 4cc27ddd980713ad95fd12a90c077df01999893f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c 06c8f4bcf358da5b2930df117ecc0f2324a59b3f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c 35820af43505df9a372d4e74e3f0550a3af9a249 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c 321d4491ee122d9ff20f50a5fd4708eec3a9bbc4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c e5c280ffda9fadc7cf51f4e49ba880138473c188 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c 2a8c469188ac72f1647a4e23121d6baab2f46881 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c 64b0e4b0e7bb5d8073e937068421026aa213bb57 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c 04b228218122ee8f024959ef831393289d417e7e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c 67a5f98ae9f74d18b7c83f145618185127a93260 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c b971ed0265436f05a8f8f5eb8653de23e49747f1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c 9fb6f1767a51f28d28e6af39ffaedc9883363298 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c 2fc25c51a836eb30d5a0215659d5fd8b4dbda2e8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c 359da64e36a5f411cf383e3fd0f83a248a1dd066 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f64.c 9fbd0b33c76b78481c512902dc4d9a0d67f4f210 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c 3fef81240caee61991a4a7c3ffa8e6d6e2e8066b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c 2211257786a567ae6daea47fa4ddd31c0339d328 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c 3155ae7f402b23659c4ff5e89bd77c5599ee23e0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.c 1e172d64c3dbd60e0e9ffcbcc7a0225702f04848 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c 0020d431a9fe3314ba42c1dafe946fbd2ef7e606 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c 2679177fa989374186316764ed9a90c42e38edd7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c 6504b9481457cfd6e39a69e7066fe09ffbbdb258 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c a091e47127bd1311d2cd2b78353ee99ddfc54100 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c 6a29d35180197bb865f52b54695f07430e3e06db - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c a44f15f379846d39821c025d6b7afe2f94cb4411 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sqrt.c 4dbe7ada2eae098c62ec673be2cb2452390c0a78 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c c50d86d027171a9f2481e8f7c1cb4308f1cf1d3a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64.c fc451ef01165565a1d593b0e2572eb8e37aa72a3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c 83db5e18b844bed794c0f1690aa2aa28ed93e4dd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64.c f5755b53bfa3d4ada8ed3be7b2e264ca31c83e9b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c 58782db3382eb567580f7105c6c8d88dd1a6fc67 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64.c ea2befd81aa697654bc1baf2a7da10508ae8b9ce - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c 61fb9da8313a688f608a43d8aa36ac9861c74c75 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c b6e5c30069ee1bfdeb29301eb988d9b5ef1e6fd7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_remStepMBy32.c 57500b9bade8439c0c3f06cbb999f6ba13952ad9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c b37dddeca4634f2e81fadc1fe8c9ec9f9643c56c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c e0d12d5167bae0c40dc2ee4e8eb79ccb7d7f8709 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c 1d30d31c5765c77e617b9969b778019b60c4b1bd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64.c bbb2e442ce63abe6d694eab84ce821e2ec210522 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c c425d403c3b3dfaed940888bca06384b967e8e5e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c e6b71c319835a3d037818d3ca0d1468b2dd3c325 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64.c 9611fba0e534169527d66900db62b107e96b8e2a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c 625d048386528b1c63a19813ace77ab7484e1876 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c 61342ccf516ad5891a6f2eb1980d37329501ea4e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c 62e6926f729011d5c3aa3af610ce0b916b919eb4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c df4f91f5c1ef40d1eaec328ca6b879bf095951a7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c 2d988cd65efb881d8f5103b71c9f6b121121ef6d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c 4042678da076368eb21bb4ded888e17dd2109b55 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c 6e91b9e38753aa8aa2094b6b40b596796bd11b3d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c 01cd4ad4fff8805cc5bf43533b1576d7e170925b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c bbe0db256dda63763f1a09d9af66cfbfa51c69f6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c a91c926882ae26c3a59dc8885fabc6e86ce9465e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c 0fb28e0101aaab0bd33ae51a05e4b522cea887b3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64.c c87f6f4eb78569c01e3fd0c6caed99232b37a378 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c fb72828cc90ce8ac0bb436552fbd39bee0f11d35 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c c42aa8ca5eb2a847874b705199b3033ae8fc00ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c 0529a095355f150e35063942c7aec7276033842d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c 80f53f88a6f924eaf40e9f79955bdfff87f72d14 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64.c 5728e535d2903cca9e9558dddf7a571e606a385e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c 8fd3330c1a032cc7c4a7ad995996169ac7f0805d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c 39eaa261c0332f55f617941b8bf51f30dfa288bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c 6ee82c2c62f3442cc1c0b2e9ef6b0b85da32cf3c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c 876085f70200480ee30305fa6463d7c6504e7e77 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c 019af317356453e7119ac20be4c98c0a1c83f8af - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c e5f8702f5072f781a5b4ef72c7ec4db154d75965 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c 84791d4f50e8187197aeca69dbef6a333d167fc1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c 29d181916bd52d0effa525808e4e4564f56b5ed3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c 2cbd145a4e3465e12bfd47dc4a52fd75c4e0b427 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c 7aeebb299243e2d857eef25300233d709662a1be - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c 7db7c6e3e7ed45f7c7ed16ea6935cc7fdba73da3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c 6c279773b785568a5567bfe33f5a6082265b9efb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c 9e7235e0ad3872a7b6f005a0203e63508f11eaab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c 622a359dab67eedd5448775dc3204d4f48039034 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64.c 1fb366479cad4034726000f4f22cdbcdcb95a4c0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c dd1f8b3669ce1b87360bd05963ce288acfd9f386 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c a05a89d48fe8216f0fa0babd342a60249c72cef2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c 73622cf9aea053c968f1922c8a206030cab025a9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c 9cdcb1720d52c0b09ac2ab14aab047bfe940304a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c 63a8a8dcae334e46b7fbc7ebc687e8d6c011fb7a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c b8189771723e965a9e94712bfa8135b04f844af1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c 12d0070692fad1189770f55c41aab025bee462a7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c e33d236ac36ab3726429718fa699498e908afb21 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c f81c603cb90e956ee8dde34149ac6bd684d4c70a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c 2af1a8917871bcc8c0560e709aa28418d004c97e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c 9783f22f581b7feca4f86660b538b214dd32b129 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c faf4056d360eb6faeccac416f54caa2a1a8bae9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64.c 0fa1c7015b7c39efbe07d739a03f2a83b85745b8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c d0375fd187a2ec8138e6a29c04afb951176c31bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c 6de7ad17814ec3532d2cc20927580d8cb52c44de - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c 5f3d886dc9c8533c8093c13f3b4242c66ba17e5a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c 3ad627bba48b5bb63c11c5e86c0081d283f4a13c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c 28af646437af4de6033b2176542a5d805636323e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c 04822aab5f0c58ebdfca756670ddbddf4524258b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_add.c 97a45958e5ea33d1fed598272e527b7f72a9d8ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c 71874d6de8e801c14005d5b1f68170c3c6c6baba - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c bc52a98da5add09bb146c15a8cc1e524e1e36989 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c 9b35552cd723623625c63511e14b0e559d678f4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c 4e4a329eebd8c7675a57c1b06f75ff4ac326b2e1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c 327934b641bc5a6a891fd19aab7b9f0363952a0c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c 1a1af8af29ddb0214656df304b31583e97bbe044 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c acd11d468d7a20b0e4381a8b7168e186b7d49d4b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c 5cd984d2fe4bfa79945c464d200d7b17d205b475 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToExtF80M.c 1aff280581ce3e0a033ebdb2257a5095804f4a18 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c 993bf55183ee975278a5e4c34e658f6f7bd3702e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c 7233f7a2c75705b0b4173168df45777f969cae96 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c bb4b86c5d78b77f1babf89d73c262ab3e47b6832 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c 0f29c869a8f46f705f24531b2826deabe579032f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c 97688d5996165455b0ead5c1973e36b6d096c21f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c 71d3ef74fe02e7fe6891e4db41241c5b2e615643 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c db04e48a5c823e4f060cc56187b01cbb89ee1afc - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c 039cc691a2609fb90724786e7ed7be17b006803f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c dda54df5d890a969ba663a54ceae83c6492d7866 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c f02ad3fb3c3e82d60532e677d475a578ecdf6a1d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c a473fd92baf36ab51a725b665f964a7a082f4eb3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c de37f2fef538ee89236273ac956585b2d58a15ab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c 70a0a4dddf509479def6ff905d493e6a50c1bacd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c 4802d692dda23c6bdb15e682f8895eaa2e02a824 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c a8129c9fa34f996b39adef2e0620dd63b5ab655e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c 495735b890e1bebb53e4e2cef50ffda57a242662 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c add3de1ad7693fb4a2a5453483938b93b287e275 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c c5fd85ea4a5cf0a00edfc6cb66cf20b3e7100062 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c 890504face9da670bb9338c6587d893fd632819b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c e9570bb5907e357489fdf310d629201fb63fe691 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c d5160582645bf346bf920e38f896596319da591b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c bf81966f25644611be0129d9ef8aaf0f5c6da21e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c dd00b7472e373b2a72b05389fd8c595c9e688831 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c 20b550200dc22a4995a52f7bb20f8177c851d08b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c 1a5d352e9bacfa36ecd8ef231155053713acece0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c ebd71c72d17dd55dc010988fcc223aeb9679ee6f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c c0e3f7568f5ce015eb6724ca13dcdebf3846138f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c 23a84b7f28ce5a2345b3d037ccc8f2707163d262 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c d586657c54173f413fa72807b84027e1beeb6234 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c d64953149b1077f8e6d0848e2fd5506136e6f2d6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_add.c 54fed28ecc0bb163f71b7d5f47c960063b16f0f0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c 62cbafb0d4719707254e3021383d31fd007b3971 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c 082138b2e89a050296984be3e3d195746735edfa - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c 33dedf42e83eb53f8ce20395143a01a73b412457 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c 3c754eb220ded3a7e9c82cb01c7ed8adc2144452 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c a04e210c7ba96d0c982f31acdc218a4a63b5326d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c c04c45b92e29225e1d2e3decc3dfc108ae63b093 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c 641b01960569783533397d0ed1cdbb00695a3578 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c d594421c568958d475a5939b2bc14c195493768f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c f815fd87ebd1c160aa9ddb1c232c1de58da01072 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32.c badda43bf474995d00db78fe6ae6b40268e9f90f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c 5aa2d29c4f2ecefdd83adab4927c2dba794a0a43 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c d688f7a888e0e7b33a166af94044edc80100754e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c 5158c6ca5efcc7ee5067415f6df5988c4b3645ed - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c 73f1f3cdf7a70d4d02ddd5d73f8198482d373296 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128M.c d3cdaf7ed2016c9f9764a514ec05b2dd6f86fc85 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64Extra.c 0d9fe463bfee7b28f85650d68588f7fb47358282 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c b390f4671e459aa98a5e6eba67989a524df502c6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c 7c39994169fccf5700f2fe944d8b94d912a07723 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c 289aeaf52ea847d12eab9ab91e1b080ae5cc4774 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c 684615f62d1f460768c6b9cf951bbe7d82b7aa4e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c 5bddd155904f96e1af61acc11b87973856d66810 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c 5d919ea71a15f028ff7b85cd73d9543cbe322b06 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c 4189613b8730aaff62a01f6254b071b9fd3c8cb6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c 7a1740bacdd6fbf37b3e9ad6b304b772722041c2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c 513a918766d59060a56eb14f936404c5a807d54d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f64.c b33f24777a60c2b658a6463c17c19f932c67cefe - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add128.c b48f6bd306c3509038d6c4d283bc189d517d3b4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c 0f3d7b35ae34828864a226e8b123484e88b8cd13 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c 016a9e65ca19c7f5d3561d54a3fcbddfb6a310ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft64To96M.c 73e3351f07e2c7c7d591555895c25042a56c82fd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c 302b57e7a9ad056c7936806892309cb4de6ffc96 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c 868cee0046c6b1426f45136804fd662b030f263e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c 52fee0fd73c94d2e2f5a21a55f082e1963b1569b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c 67e0a5407af29f70e8a1cd10563b7aaec9ccbcdb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c 7c65ad2301cc6e79aa3392bdb9010a7ce81b0c38 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c 94e7fa32804e73cff91d5bfa140aebbbb55fe6cb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c f58e104619733d72884d1de3ce89eedacb671595 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h b6b8b672735a45d7c495bf8af1fa94d1c8e6556c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c 52bc24f91ee7846596274fb2b29654539fd3fa00 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c 35b37030a4086b22b7974082589b33ca07ccc8bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c 7d5189099e205be2e0420013770668fb8b96e133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c 7e3b18d1139373153529a43d88c469da845d393b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c 74a3e6c966c47167bebd7abdfb17797124ee9279 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c 1c390c99fc7405c9a44b4117383cce7de291c13e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c 4a66a4eaba41707a706d22a724ff5853260d070c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c 2c9f36c79b5d80fe13893b8c9b9f9c94273c1c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c 70de120b27bf3bf6917bf2a9536aad6fe8536358 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c 784083a6783d1d5de48e4b5a95ccb43b8103bfff - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c 8c5a81c2b54db7d09ea4a08a43171c7f9ed3cbe7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c b0822433062f48471e106e268f79f079d1a1cd55 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c d8fc85a2746e3c31e70de675027af01735ba105f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c 7dc9295fddc66cd74761fa03a90c65985b964c08 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c cc1a5d99c9f6833e79108373c21162c7fb65a742 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c 868cee0046c6b1426f45136804fd662b030f263e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c 52fee0fd73c94d2e2f5a21a55f082e1963b1569b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c 67e0a5407af29f70e8a1cd10563b7aaec9ccbcdb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c 7c65ad2301cc6e79aa3392bdb9010a7ce81b0c38 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c 94e7fa32804e73cff91d5bfa140aebbbb55fe6cb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c ade8c323e356c3e70af2424ed9e2ca0ccabc68c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h b6b8b672735a45d7c495bf8af1fa94d1c8e6556c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c 52bc24f91ee7846596274fb2b29654539fd3fa00 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c 35b37030a4086b22b7974082589b33ca07ccc8bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c 7d5189099e205be2e0420013770668fb8b96e133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c 7e3b18d1139373153529a43d88c469da845d393b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c 5e2ab65ab8c5b830b547afdfac8b72c1a7b193f5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c 1c390c99fc7405c9a44b4117383cce7de291c13e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c 4a66a4eaba41707a706d22a724ff5853260d070c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c 2c9f36c79b5d80fe13893b8c9b9f9c94273c1c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c 70de120b27bf3bf6917bf2a9536aad6fe8536358 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c 93bd291166335a88ca0721d5beaebd9599a2475e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c 8c5a81c2b54db7d09ea4a08a43171c7f9ed3cbe7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c 3b12a5a00c5ee315f9665165cc0160e7e4e7b946 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c d8fc85a2746e3c31e70de675027af01735ba105f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c 7dc9295fddc66cd74761fa03a90c65985b964c08 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c 1afdc66c33767a868d162893776bf6d3ba9f1247 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.h 8450fc5ca89f94b128b1d1d4608903ffd0de498b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h 5ab0e0aaf3ae2f7637cf1c42709cdad267a20850 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat.h 0d0858bee5e0636c53a6f5b4a484f08b979495a9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitives.h 3b6c666fa3fd1fcdb96504690f34db6740d85b2f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h 2b66ebd06a1b0c7e7626aceab2192011d72a70ab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/Makefile 39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/platform.h 6be19d4409b8a6cafc0be14b9b5ffdf052c7b25b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/Makefile 39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/platform.h 6cbdecb56028446ec09651ef96ade55402b23a2d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/Makefile 39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/platform.h fc40163df60fca883cf8105128b0e2044b4e5c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/Makefile 18484ed24a14a759985a39574bf4d1c56cfe1939 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/platform.h 19237050b884871548365d61622e85253f30ffd1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/Makefile 18484ed24a14a759985a39574bf4d1c56cfe1939 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/platform.h 140c840a66dc59f8b8460c7e18349faba5989be1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/Makefile 39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/platform.h 140c840a66dc59f8b8460c7e18349faba5989be1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/Makefile 39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/platform.h 6be19d4409b8a6cafc0be14b9b5ffdf052c7b25b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/Makefile 39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/platform.h 90d2bc9a9afc3396f0a2271c1d79a76287c2516a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.html 75e9aa350d3aae45b151a9bbe2f6e70ccad11c7f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html 9170d3167dcd72c685ebc6ca6250eee2eefd0c45 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-source.html cbaa68e47415bdb2b68ad13c2037e03cd231fd60 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/arm32_include/platform.h f1ba2ffbb8b80c3d2c8baf5ad09f2d1883ccc95e - optee/optee_os/lib/libutils/isoc/include/wchar.h eb700f736fea47a51c03069d099ff492d566f45b - optee/optee_os/lib/libutils/isoc/include/time.h 15ec9c6af06bd04877ce230bac8bfa3ce26a23e9 - optee/optee_os/lib/libutils/isoc/include/unistd.h 9edc066dbedabb03c6479c2dfc962125c09207b5 - optee/optee_os/lib/libutils/isoc/include/memory.h b704c2144f4058cc83eff91c732a965487af7f2f - optee/optee_os/lib/libutils/isoc/include/signal.h 9978646994c635cccfd0082f5e183aa8817ee114 - optee/optee_os/lib/libutils/isoc/include/setjmp.h d107150611ad4db054a4c134a03cb4072e5b978f - optee/optee_os/lib/libutils/isoc/include/strings.h 5fbd70f4fe7a023e3b9c3c6997b0cc042bec58d8 - optee/optee_os/lib/libutils/isoc/include/inttypes.h 7146a287e1507a73b42aa6ae46d72881a5b318a8 - optee/optee_os/lib/libutils/isoc/include/stdlib.h 1b5da4e5962171c39a2b4762a169e12e50dd6641 - optee/optee_os/lib/libutils/isoc/include/stdio.h 0e27c8f74b3f066a60b8b79fe1951ecc76c12fb3 - optee/optee_os/lib/libutils/isoc/include/malloc.h 353c7b2a8c73f6458ed0e92d380fe01ff4dea900 - optee/optee_os/lib/libutils/isoc/include/assert.h e7fdba9acf2bc6ddc6d25cd852eeff72855d143d - optee/optee_os/lib/libutils/isoc/include/limits.h e83da5f07c33bc84bb291affe6480214bb4e6f9a - optee/optee_os/lib/libutils/isoc/include/ctype.h 44f78c63d935ad93ce68039331f214dcc699f6e1 - optee/optee_os/lib/libutils/isoc/include/stdint.h 8629e94b3bc7a9b628d559492f6859405e065233 - optee/optee_os/lib/libutils/isoc/include/string.h ea09b9213223627399f059ff48bc083ac9652a96 - optee/optee_os/lib/libutils/isoc/include/sys/queue.h f39fd14f91c4f1b1a6c2636a7abfaa0cad378a37 - optee/optee_os/lib/libutils/isoc/include/sys/types.h e646420d5133d287b223a251d711caef5077d8aa - optee/optee_os/lib/libutils/isoc/include/sys/cdefs.h cd3c2b81c2fa7237a975213bafcf7ac4e67ff177 - optee/optee_os/lib/libutee/tee_socket_private.h 6a2bd30d6d4442e50515c09a081afd22562e62a8 - optee/optee_os/lib/libutee/base64.h 2a8949363bf9be408cbddf09c072982132988ffc - optee/optee_os/lib/libutee/abort.c 4a67c07665addfbe2d7f5a4405dc1cb2b8a44f45 - optee/optee_os/lib/libutee/tee_api_arith_mpi.c 55c2020c1066f0e0ccee7396effb27bc63af0b5e - optee/optee_os/lib/libutee/tee_api_operations.c 8fa85961841aca5f32b051d7c2137dce6048c90a - optee/optee_os/lib/libutee/trace_ext.c 9389ec3691da465689f9ef3c7e4a843bdad07389 - optee/optee_os/lib/libutee/tee_tcpudp_socket.c b692cdf8031f1a5f56a40e3a331b86bf6ad0c81f - optee/optee_os/lib/libutee/tee_api.c 3cd93276aee5c3e854a28469d4249e285836e0cc - optee/optee_os/lib/libutee/tee_api_property.c 077681c818e3003b52065a80dbacbd498dff6b29 - optee/optee_os/lib/libutee/tee_api_private.h 61ba39ae5f3db7e446666d29227a87474f4a6117 - optee/optee_os/lib/libutee/tee_socket_pta.c 756eb32d34c8adc8518381acb1da0e71abfc07c9 - optee/optee_os/lib/libutee/assert.c b1398a9a37ee47f2718169316310a4a16c61166c - optee/optee_os/lib/libutee/tee_uuid_from_str.c dc820097b9daaecdbebb44d2745b59ab6c868b3c - optee/optee_os/lib/libutee/user_ta_entry_compat.c bc9153018927868009fb5a5e6df2a409ecb13f4c - optee/optee_os/lib/libutee/tee_system_pta.c 45c1ba4438be0ecfb4d4bca51534640836b8c995 - optee/optee_os/lib/libutee/tee_api_panic.c 505da116e55bfaee3c94a6db710ef70a860f9bf1 - optee/optee_os/lib/libutee/tcb.c b4d75c22cea319de57b7d095ce76316fa38d1506 - optee/optee_os/lib/libutee/base64.c 8b5165f5a04ab8a7602713559fe272670f5b5aab - optee/optee_os/lib/libutee/user_ta_entry.c de26a71b90cb412c9efc752727836f54fb1d95b9 - optee/optee_os/lib/libutee/tee_api_objects.c b2ceb3db7e2bb09feef1e3551cfe2f2000b8bc66 - optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S 137080dcbc697e48f567709fe3fda2528f5d40fa - optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S b1ff8027d8f72d6043aefff12c169937335d77c2 - optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a32.S a2170433362124e5401cea1cf6f4dafaca653856 - optee/optee_os/lib/libutee/arch/arm/gprof/gmon.h 2e2b03efa22c915b6ab0a59c54793e918ae83560 - optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.h 16e0dc83cf08600fd769832ff1d21611782da066 - optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.c 1a3e524ad810227480d10b0d8426c780c85328bb - optee/optee_os/lib/libutee/arch/arm/gprof/gprof.c be6fc3000484b65889ef0ddf1e7a926e364575a8 - optee/optee_os/lib/libutee/arch/arm/gprof/gmon_out.h 80eb8b37eb87886d40dc390c74bfae90f83ea208 - optee/optee_os/lib/libutee/include/pta_socket.h a990d751d99ca55773e11d46acf4794e93181cf6 - optee/optee_os/lib/libutee/include/pta_benchmark.h 1ee95d67db99aa4b7dab212672290e1dcf51e1e6 - optee/optee_os/lib/libutee/include/tee_api_types.h 7812d9a6cf27c9c8cb718a2a8824323576ccaf38 - optee/optee_os/lib/libutee/include/tee_api_compat.h 0311b7bfd98a444eeef7c7c89d4e942a84ea6787 - optee/optee_os/lib/libutee/include/tee_ta_api.h ce4bc2d3ed7f6c3ecb68a1f98a7f368f7369a286 - optee/optee_os/lib/libutee/include/utee_syscalls_asm.S 398b00b2fdfc1d0dd1987e95722a21a6de7413bc - optee/optee_os/lib/libutee/include/pta_device.h f5d83909e5071e2affc98fc56ac4b941e00ef03a - optee/optee_os/lib/libutee/include/pta_apdu.h d6494aea8b2d08af66c5b03901a962d4c23afa5c - optee/optee_os/lib/libutee/include/pta_secstor_ta_mgmt.h f4adab9015698b3a5ad156216c44340a86567794 - optee/optee_os/lib/libutee/include/link.h dfe89d4404a213f5751887db149a30135cd07f9a - optee/optee_os/lib/libutee/include/pta_scp03.h 793d80272b98715200cd83435c35de534049b96e - optee/optee_os/lib/libutee/include/__tee_isocket_defines.h bc735eb7fc5fe9fa8e31ddfe2f98dca62b95ec9e - optee/optee_os/lib/libutee/include/tee_arith_internal.h d6461788cfe9c7fa1812938fccf00428981ca21f - optee/optee_os/lib/libutee/include/pta_rtc.h 0914ffb8eea917ca32ddfd5e9d1e07b08242a132 - optee/optee_os/lib/libutee/include/elf64.h 5e23b121b492913159ac492c975bc689fe4fe9d5 - optee/optee_os/lib/libutee/include/utee_syscalls.h 47e7cf8af6ad09392aa45b94e88e4cc07e54520e - optee/optee_os/lib/libutee/include/tee_syscall_numbers.h aff5768a908441b37ad3a28350e0b0f6bf0007b0 - optee/optee_os/lib/libutee/include/tee_api_defines.h aa09af74960113ccd4fb8827d07e4b9140aacf8f - optee/optee_os/lib/libutee/include/arm_user_sysreg.h 1cb2546168ca45afe3e8ee0cd818c13e6019c425 - optee/optee_os/lib/libutee/include/elf_common.h 62fdcf80906b4877ba0a4d22e69a0c75e98e8b9b - optee/optee_os/lib/libutee/include/pta_imx_manufacturing_protection.h 34686e9ef3d016d68cb94ca12b860c89349b5eca - optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines_extensions.h 9c2c1f4769d19646dfe1493dfaa1007b8c538af0 - optee/optee_os/lib/libutee/include/rng_pta_client.h 5d2f8542dbd85a819207cf9201d5c104d1f45799 - optee/optee_os/lib/libutee/include/arm64_user_sysreg.h 989a3f3ba297d8913c040b838c9cab1a5103308f - optee/optee_os/lib/libutee/include/pta_attestation.h 41b79406ff05bc4d3528fca688813e7f88e7d135 - optee/optee_os/lib/libutee/include/tee_isocket.h ebea83d32048f9808bd31f5e2dabc5c0314057bb - optee/optee_os/lib/libutee/include/__tee_ipsocket.h 376f36da862c7024aec13565c1d6af9518cf3f01 - optee/optee_os/lib/libutee/include/pta_jetson_user_key.h 8572ff4140b947a4e4a4b5752d8265fe1ea5b348 - optee/optee_os/lib/libutee/include/pta_scmi_client.h d1eb626d04bb19cbf07f7e9b1a69eaf8593b16ce - optee/optee_os/lib/libutee/include/utee_defines.h 083e406c1b8993f6c0226bf312fcd140b1bc2cc4 - optee/optee_os/lib/libutee/include/pta_imx_digprog.h 5a4c5c4386df019b937e53bdfca5e05bf5f10921 - optee/optee_os/lib/libutee/include/pta_invoke_tests.h faeceac8862bbe02c984a8839b1e1cae06319dba - optee/optee_os/lib/libutee/include/pta_rng.h 8981169f89ce2d195a17112b676bb8552d21ad4c - optee/optee_os/lib/libutee/include/tee_api.h f6b88edde49c7f79eebc0c3f861b6f19ff685fd1 - optee/optee_os/lib/libutee/include/tee_udpsocket.h 5ca4833e2188ae7c12e8b39f0448c7f3627571c7 - optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines.h bfd21882753009a9bff306c49ea3d6ba0a27715d - optee/optee_os/lib/libutee/include/pta_stm32mp_bsec.h 0f06e417dc0b4434790db823616a67697a157404 - optee/optee_os/lib/libutee/include/__tee_udpsocket_defines.h ed871d9884b5e4c5c7801d8dfc5f77f30d79d4ec - optee/optee_os/lib/libutee/include/tee_tcpsocket.h 8ddaf3ec29e785a63a8b8ba266c13abdce68c125 - optee/optee_os/lib/libutee/include/elf32.h c603b51b2bfba8baa7cb2c4dfbaaa421d9461207 - optee/optee_os/lib/libutee/include/tee_api_defines_extensions.h 6cf7866d8d5f2388b28df78b419553de615ec055 - optee/optee_os/lib/libutee/include/user_ta_header.h 591d4ed947e32e0c72a95a7a2514221f1cf9490d - optee/optee_os/lib/libutee/include/pta_gprof.h e3514bd732b3d0be323aae77cdfcbfb736b42fdb - optee/optee_os/lib/libutee/include/tee_internal_api.h c4e212610ccdc55f55421917a843a5b8ddb567c2 - optee/optee_os/lib/libutee/include/pta_imx_ocotp.h 9155ede1378206e1762eb2696d1589cb2b620ee6 - optee/optee_os/lib/libutee/include/utee_types.h aa7d01574e3506e0ee2f42cdb251145908b75381 - optee/optee_os/lib/libutee/include/elf.h 5e08d24c95ed9a2dbbcf69ef3896898ad97abc8a - optee/optee_os/lib/libutee/include/tee_internal_api_extensions.h 24acf5f9664ccd81af1147a5e2f875e5a303d97a - optee/optee_os/lib/libutee/include/pta_system.h d84b15deba3ac3edfa192902098d7b012e19893c - optee/optee_os/lib/libutee/include/k3/otp_keywriting_ta.h 739a223e693f30815eb57c7b1bdae6bc5e2c8028 - optee/optee_os/lib/libunw/unwind_arm32.c a7b80ca6cb33642237a2a0ecfdc7ad3827cef4c7 - optee/optee_os/lib/libunw/unwind_arm64.c 62096636f7a228af8aad98afd445a8ce4e9ba81a - optee/optee_os/lib/libunw/include/unw/unwind.h d3c54bb6b126358f60fecee23a0d6064d3ad12e0 - optee/optee_os/prebuilt/t234/libcommon_crypto.a 4ec1a9b7d2f64d94ccdaa889afe2cba025e5b33b - optee/optee_os/keys/default_ta.pem 91c83678702ef358777559205b8c2c775789c87a - optee/optee_os/ta/user_ta_header.c 32f326f4c0f102b4ee4c9ba88d7d1760b803237c - optee/optee_os/ta/pkcs11/Makefile a6e947a9f3f7337320b8940c40d8441cb477073a - optee/optee_os/ta/pkcs11/scripts/verify-helpers.sh e766a0c478f5e52ce2ea56f842f8e012f68427af - optee/optee_os/ta/pkcs11/scripts/dump_ec_curve_params.sh 5329b77d3056c08cdeb14ecdea7b81110262fc24 - optee/optee_os/ta/pkcs11/include/pkcs11_ta.h b10094c63a4f11d5d590d53e1c73d6f587d0dfdb - optee/optee_os/ta/pkcs11/src/attributes.c b44775c01d993d49402ab222d398850976d8bbc9 - optee/optee_os/ta/pkcs11/src/object.c 4b7dbda490ed1c5ac55d3357b440a8f012c647d5 - optee/optee_os/ta/pkcs11/src/persistent_token.c 5f8de729864d1ad926d2f9ec4ef37e8ff38ceb70 - optee/optee_os/ta/pkcs11/src/serializer.c eb55922796647a3afae81a788f1ce67eaaaba09d - optee/optee_os/ta/pkcs11/src/sanitize_object.c 9ba0514e3a2e9581cf9564462df013a0494f745d - optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c aee16d7bf1c5d2a0c39c6a5112cec71f528421b3 - optee/optee_os/ta/pkcs11/src/user_ta_header_defines.h 0e3dca0597af48781c952400ea4ecad857110eef - optee/optee_os/ta/pkcs11/src/serializer.h 9e799d40bc5157fad91180105d091bf81c2695ab - optee/optee_os/ta/pkcs11/src/processing_digest.c 26dc92427964930f69b616be7c77b90da4bcb8df - optee/optee_os/ta/pkcs11/src/object.h 2a2615470b5e9f0946dbf9e32ee11fe0b4dff621 - optee/optee_os/ta/pkcs11/src/pkcs11_token.c fb13a7d2381ef0bc40438bc32f4406ee2690d914 - optee/optee_os/ta/pkcs11/src/processing_aes.c 0aa2868227123053da7d9368bc3640a839d4e682 - optee/optee_os/ta/pkcs11/src/processing_rsa.c aaff008a064e973b8f57ec40853d5935a7fd36cd - optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h a199684d2e257ba2568ad8c8d6788b9e4e8abcab - optee/optee_os/ta/pkcs11/src/token_capabilities.h c1bc93345d7db093a5ac9ce255a1f1b9b04f9b41 - optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h 8d8b0a84e056fa008bf4be504cddf4b5f059389a - optee/optee_os/ta/pkcs11/src/handle.c f5f2eae047cb155a42ed528fb8b2f574970fe2a2 - optee/optee_os/ta/pkcs11/src/processing_symm.c 5cf92c8affd431f709ff970b2f42fab1b0a96ad2 - optee/optee_os/ta/pkcs11/src/processing_ec.c deec6a53392a9c38fca095c61a072b80ec426224 - optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c 0ffa60c477bc8ee08f506cf0302096d0982314b1 - optee/optee_os/ta/pkcs11/src/pkcs11_token.h 03111d59e4b6c3a54517680ae126d3498a8d2b9e - optee/optee_os/ta/pkcs11/src/processing.c 406de9608e4061b2c61b5af8605bcd7f389e4bf3 - optee/optee_os/ta/pkcs11/src/handle.h 8a63bd474856b01d14303d306048e3981ddf19c4 - optee/optee_os/ta/pkcs11/src/entry.c 4ad6fb1144fae7c02fd7ef269c1a4af2c25ca38c - optee/optee_os/ta/pkcs11/src/token_capabilities.c f96d820c677acbc73e09670a4747a0c925f319d2 - optee/optee_os/ta/pkcs11/src/processing_asymm.c 84b21a00a4d1908760573381497ecc1584892ee3 - optee/optee_os/ta/pkcs11/src/processing.h 894d688c805cbbca2bde46ae5dfcf38092d7e8dd - optee/optee_os/ta/pkcs11/src/attributes.h 9d7de06484bf080c9fb9d2922ea6a4d808edce81 - optee/optee_os/ta/pkcs11/src/sanitize_object.h 353da6ac448fb9756cfa1b97c162df13d0174fac - optee/optee_os/ta/arch/riscv/ta.ld.S 44f007aca97998b425d27b7af67779c039d4d8d7 - optee/optee_os/ta/arch/arm/ta_entry_a32.S a5b56b622eb2fde139565fba51a74c5de3806afe - optee/optee_os/ta/arch/arm/ta.ld.S 78100b9031d82bc62fe38e0650f780d2c18f2f5b - optee/optee_os/ta/avb/user_ta_header_defines.h cc0a07d6f59b29a9ec0e01f5ca6a378b3d445248 - optee/optee_os/ta/avb/Makefile 49328831e03037ff1c84c1721fb97905781904e0 - optee/optee_os/ta/avb/entry.c 04d61d12d0b618ec98f1f36f7aac7e7f6a0bada7 - optee/optee_os/ta/avb/include/ta_avb.h b28af208dabadef396024e4007f36154699e975b - optee/optee_os/ta/trusted_keys/user_ta_header_defines.h 50fac4ba9aede25524155ad8cd8cdd905f195a87 - optee/optee_os/ta/trusted_keys/entry.c 8ff25744520aea7259967d34911798667d2cf6fd - optee/optee_os/ta/trusted_keys/include/trusted_keys.h bf52776d687b57bc5e886b2f4e7a0f7ece62b0b7 - optee/samples/Makefile b2def2faca96323618fae5d302c50260bccb869e - optee/samples/LICENSE 22d6ec718c65f0f1fab50d6a32d64857f975eb83 - optee/samples/hwkey-agent/Makefile d641b8218d5f3af3869eb24210d632d9accc789e - optee/samples/hwkey-agent/README b2def2faca96323618fae5d302c50260bccb869e - optee/samples/hwkey-agent/LICENSE d8d2851c68cdbcc9138bf2542d445f73ab2ebe44 - optee/samples/hwkey-agent/host/Makefile 59f6594fdd5e77aaf03788a08a39999ffd8b86e5 - optee/samples/hwkey-agent/host/hwkey_agent_ca.c 3e73868f9048110e8fce23a71343f5d0db256281 - optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh 04735615008d1c575afd724156b78c21d77766ea - optee/samples/hwkey-agent/host/tool/gen_ekb/README e000cd877e89200d16afabb3f5778d4ce0bc072b - optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py 65d0125074f02769fd68a3b9db5c1f440a076ec6 - optee/samples/hwkey-agent/ta/hwkey_agent_ta.c 01a5ebf5ecbf58a06002ad10b902e18d78d452d8 - optee/samples/hwkey-agent/ta/user_ta_header_defines.h 5054796c29272096d67dbf4fa7453f9bfa3ad280 - optee/samples/hwkey-agent/ta/Makefile f1652fd24c49bf7be742b2e2081280bcd33d2ddd - optee/samples/hwkey-agent/ta/include/hwkey_agent_ta.h 85cb555a484a3191da2b234f4c2121addebc83a5 - optee/samples/luks-srv/Makefile 6fb1ad386475e975804bd789938f171a0e634bf9 - optee/samples/luks-srv/README b2def2faca96323618fae5d302c50260bccb869e - optee/samples/luks-srv/LICENSE ba0f3f4839fe17b652aa8a9e18d0f5fe602f4662 - optee/samples/luks-srv/host/Makefile 8577e960a7ba6fea952165100b467fd6b4fb1902 - optee/samples/luks-srv/host/luks_srv_ca.c 6d3ac3cebb74c4f088accfac2d48654ea788769b - optee/samples/luks-srv/host/tool/gen_luks_passphrase/example.sh 42761539497633e52d70529a0c963678c1e2b9e8 - optee/samples/luks-srv/host/tool/gen_luks_passphrase/README ea3aeef7e946314ca0a3dc1f6b2c64099963b8e8 - optee/samples/luks-srv/host/tool/gen_luks_passphrase/gen_luks_passphrase.py 9198ad9d0108d1f0c5411e43cfcdbbb011dc6ddd - optee/samples/luks-srv/ta/user_ta_header_defines.h 7dcf0c69657674d5c8d84f037993856ccdabf784 - optee/samples/luks-srv/ta/luks_srv_ta.c fa3f0583c33f15560475d2899643217e9b8bdedd - optee/samples/luks-srv/ta/Makefile 80db8ae67e3a08227b8feeb7c71d80c97e620988 - optee/samples/luks-srv/ta/include/luks_srv_ta.h 21ee084c6b208974935df6b5626f27e4cbb8e053 - optee/optee_client/Makefile 1be3a93bb56c46ee4d4693b47ddd7c4c5487ffd3 - optee/optee_client/README.md a7d910ff308216f427e9a4776d72cfe84e2915ad - optee/optee_client/LICENSE c9b3bb5ab0a3d0252ed93cfc3578e3991ee2b994 - optee/optee_client/typedefs.checkpatch c9c46f6d84c395db9e62599d15980f06cf993db7 - optee/optee_client/libckteec/Makefile f25fe667d7155f39694414e63dac8d54adb5e264 - optee/optee_client/libckteec/include/pkcs11_ta.h 7d66a5a9955374f577b36eda3684c254841edbda - optee/optee_client/libckteec/include/ck_debug.h cbd1cf1d939303ee17050057c176ddb7498b1598 - optee/optee_client/libckteec/include/pkcs11.h 53de33af06e51fb21fe2f24c2c0665a45baeb3b8 - optee/optee_client/libckteec/src/ck_helpers.h a4b2b6fc00af2b337386db3fc110f54709a248bb - optee/optee_client/libckteec/src/serializer.c 28f837a80c95ceb3f72437386993f46469f861e9 - optee/optee_client/libckteec/src/serialize_ck.h 4a7c34adbc6006ef9230bb1919ca520891b9823a - optee/optee_client/libckteec/src/invoke_ta.c e640a280681f076f112beee518ea1adff965c818 - optee/optee_client/libckteec/src/local_utils.h 0db1379449cb2cdae53a7b480a402e8c43457431 - optee/optee_client/libckteec/src/serializer.h a36127385f3d497598291e167cfc4147e48861ed - optee/optee_client/libckteec/src/pkcs11_processing.h af95d0df955aaa2ab03f767ed5368a2d461eb337 - optee/optee_client/libckteec/src/pkcs11_token.c 48b8562a4200b00fe6382797789d8e694186c620 - optee/optee_client/libckteec/src/invoke_ta.h 04e59fc9b03985ed9c71fb751bcf60dc050aa517 - optee/optee_client/libckteec/src/ck_helpers.c f88324eb36dec1f8579a56f5e446475ced59b52d - optee/optee_client/libckteec/src/ck_debug.c ff70441ef0fe6caa58fb618ff6343691f6a5440f - optee/optee_client/libckteec/src/serialize_ck.c 178b53aac43cdfc719b04be256672168226a3e4e - optee/optee_client/libckteec/src/pkcs11_processing.c 3d1d16bc8a998c7382d0e5deb177e421613cbdb9 - optee/optee_client/libckteec/src/pkcs11_token.h 145e33a2859354e90473957df5bdd430b63f437c - optee/optee_client/libckteec/src/pkcs11_api.c d6e6c51b13d0f6f61ae51ff3da8b8f51b3ac433e - optee/optee_client/scripts/checkpatch_inc.sh 668dfffd684890e7dd9bedbfd635db0df9af35d8 - optee/optee_client/public/teec_trace.h 5009e68a037662f4c9aa73a569a2ffa76983dd05 - optee/optee_client/public/tee_client_api.h 43da45835976c93e70ec5ad1ed02b891a0dbe000 - optee/optee_client/public/tee_plugin_method.h 08cc148a2aa7668b539ec815dcfcd4ba6ee64ca1 - optee/optee_client/public/tee_bench.h c6e011ef6751f07449bffe9fd19006a15b8624b5 - optee/optee_client/public/tee_client_api_extensions.h c2eeeb99eea300a1748db00f9803a548f2282c49 - optee/optee_client/libteeacl/Makefile ee867d9d7bddd079e18e86b614ddb0951d3a79ce - optee/optee_client/libteeacl/include/teeacl.h d44856b3c2e641d34dc08c44aa14df8111f0f2a0 - optee/optee_client/libteeacl/src/tee_uuid.c 3842833a20a863d971c8d33f5e101ccc77e88c62 - optee/optee_client/libteeacl/src/group.c 0ddc947d4bafad6f4a3d62517c539706e25b6cd0 - optee/optee_client/libteec/Makefile 65b3d16f29fb30f1241ad61acff018a0dc2e6f88 - optee/optee_client/libteec/libteec.pc.in 6f319e289afeaa66b6058c8f2397e66d4bd79b70 - optee/optee_client/libteec/include/teec_benchmark.h 15278a332dd772f0c91e486e562d10ba1b9cb6df - optee/optee_client/libteec/include/linux/tee.h 67f6aec80cb155ca0bb850b4b38b6cf0042917c8 - optee/optee_client/libteec/src/teec_benchmark.c d842563e16728b8e4b8e70f1fd7522598235d843 - optee/optee_client/libteec/src/teec_trace.c 72b02b7343819ffef928481f93f3d02afeb55b88 - optee/optee_client/libteec/src/tee_client_api.c 162069bdee10a33e7ff8e9680386d51bd7eaffff - optee/optee_client/libseteec/Makefile 2219ff4dd85f1c6a0ee11024a1834c7d17124a79 - optee/optee_client/libseteec/include/se_tee.h f5d83909e5071e2affc98fc56ac4b941e00ef03a - optee/optee_client/libseteec/src/pta_apdu.h dfe89d4404a213f5751887db149a30135cd07f9a - optee/optee_client/libseteec/src/pta_scp03.h eb52a5aa690916e1cdb6e9d58fd746762ac03bbc - optee/optee_client/libseteec/src/se.c 874f552974cb3d5f17a63dd2ba50582a28e2d28e - optee/optee_client/ci/Dockerfile.ubuntu 2a0b9b82ad279a7127d4fb8fa2c4c4bb0bbfb62e - optee/optee_client/ci/Dockerfile.debian 02f2418592552d63eb73b6480b2b59962b800f2a - optee/optee_client/tee-supplicant/Makefile 8fbfe192d68bdb1e126598cb730e7c11f511960d - optee/optee_client/tee-supplicant/src/hmac_sha2.h f24b5d7b4681f11f33d735e96c6193f040d61420 - optee/optee_client/tee-supplicant/src/rpmb.c 120c38c9db67c7f01f10865b26742c3d2ae3aabe - optee/optee_client/tee-supplicant/src/teec_ta_load.h f5b0fdcf3343c38ff2495f438044546952d538e2 - optee/optee_client/tee-supplicant/src/tee_supp_fs.c 5387e1fcf4e95d497b72ee814d729c4c90adb740 - optee/optee_client/tee-supplicant/src/plugin.h 07af4053379b51e5d33dda8ac2eda2181ae23a02 - optee/optee_client/tee-supplicant/src/nvme_rpmb.c eb428488f05ca6049614557e2a89abbe531b1e24 - optee/optee_client/tee-supplicant/src/sha2.c 2b4e00ad1b9e0f3a5e7c2efbef6591de41a0e409 - optee/optee_client/tee-supplicant/src/sha2.h ad3a9ab261d5a20d083f5cefdfb13c93c3222cd9 - optee/optee_client/tee-supplicant/src/teec_ta_load.c a80eb6caf9c8732d74f0fc4c329a4222995ec6c8 - optee/optee_client/tee-supplicant/src/__tee_isocket_defines.h f04b1790f669de1573516dc81fe3f4eefcb59c1f - optee/optee_client/tee-supplicant/src/rpmb.h f17cf7d08bb300eb71cf0b2ca503f505c269e761 - optee/optee_client/tee-supplicant/src/tee_socket.h da6b261a72fe9cce7fef5e8d85d300790dd5b158 - optee/optee_client/tee-supplicant/src/tee_supplicant.c efbb5dce35c8d8f138142500a0d6ca7df0a01dd4 - optee/optee_client/tee-supplicant/src/tee_supplicant.h ea069507eb088c8be58fd316e1182d94fdcfffb6 - optee/optee_client/tee-supplicant/src/optee_msg_supplicant.h 593518d07f2abcdc15942f188796aaa0bb12d4c6 - optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h 946a1750a3bd2cb7ee8a0934d7df7849d1649aee - optee/optee_client/tee-supplicant/src/__tee_ipsocket.h 1f145b8b2fe3882017290f627f46dfc328a7c144 - optee/optee_client/tee-supplicant/src/handle.c 4a38f4ea1eea116c78d27b03a2cbfb92f8ea3a97 - optee/optee_client/tee-supplicant/src/tee_supp_fs.h 721aca20ceeacd1648d0f7204c85f69b282fe101 - optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines.h 945a945fa92b85f4b7003123e4ef27a588bdc2bd - optee/optee_client/tee-supplicant/src/hmac_sha2.c b81a505561be6982f3eea681e266827c8236583c - optee/optee_client/tee-supplicant/src/__tee_udpsocket_defines.h 9763ee4354d75e34559e80fe8dda7bb158c4c5d0 - optee/optee_client/tee-supplicant/src/handle.h f1107acfa97784e2a91a1a393dd6198fc4a4a222 - optee/optee_client/tee-supplicant/src/prof.h 2eeff0bb8ad1aaf5594e87a9faa9b9bffa63ee8f - optee/optee_client/tee-supplicant/src/plugin.c a5f3a0cb9e4309400c0c22dc574de3c8eef67a65 - optee/optee_client/tee-supplicant/src/nvme_rpmb.h a16a80d873293f74d73baf53721eb5019ded25cf - optee/optee_client/tee-supplicant/src/tee_socket.c bed7d31fece3711cc20a9418d51d24ef7fe3391b - optee/optee_client/tee-supplicant/src/prof.c 1764bfc2b32f604e3b3b7d735ce13aebfbd84d74 - optee/optee_test/Makefile 30a64b524a40d63d6e6f97698875a98100706c59 - optee/optee_test/LICENSE.md 1677c508f843daf45fcf3a1e8c23dacf24f2f222 - optee/optee_test/README.md 9f9d1e370fe395412ffa6a5bc7d21a13586d1551 - optee/optee_test/typedefs.checkpatch d178f675a81f53b7e725d270b25fadc6b064d6f8 - optee/optee_test/scripts/checkpatch.sh 5d1d72def657b4edb305b87edbff271b1a4e0c81 - optee/optee_test/scripts/rsp_to_gcm_test.py 72d26f74f4c2afb8675278b599c37c055eeeee59 - optee/optee_test/scripts/file_to_c.py c035f30f1e5286ab496634f87b76fca573244cec - optee/optee_test/host/supp_plugin/test_supp_plugin.c c6f2d858387614cd7e1ba883db5977638bbcfd55 - optee/optee_test/host/supp_plugin/Makefile fa35e416cf42119ff66e1a064a4d5db8c785118e - optee/optee_test/host/supp_plugin/include/test_supp_plugin.h 2ede51c8890d3520381c8cbef3b37e41fba5ae38 - optee/optee_test/host/openssl/include/openssl/ecdsa.h 0b02b031e6e3e70e62bf1b49e9c2e1cecfcfc53e - optee/optee_test/host/openssl/include/openssl/rsa.h d957c5aee3bd2927a6600aa410806835df0afa64 - optee/optee_test/host/openssl/include/openssl/pqueue.h 4b807b363eb139b490d51878492a987b9f0fbadf - optee/optee_test/host/openssl/include/openssl/pkcs12.h 09b47f0d80884577cc93c8a315e2f257f866f71e - optee/optee_test/host/openssl/include/openssl/whrlpool.h b31cf4d26ccbefd0c519bd475ea515f8cad8be06 - optee/optee_test/host/openssl/include/openssl/comp.h 36fbc7d4b2c4a903cce70e18132610a96a7f605f - optee/optee_test/host/openssl/include/openssl/krb5_asn.h 521646326a376805c0087b4ac4e587e312e48a86 - optee/optee_test/host/openssl/include/openssl/rc2.h 6e2539151422b3aa13de79253cd6ca1c9a51ee0f - optee/optee_test/host/openssl/include/openssl/md4.h aeca6068019b931b7d13625ebd103d216bca02dd - optee/optee_test/host/openssl/include/openssl/asn1_mac.h f67566f6be946527f9fd7377f6d0497fe8b46311 - optee/optee_test/host/openssl/include/openssl/lhash.h 007afd8fc88d891a1e00f03bc5a8d4a91d1efb30 - optee/optee_test/host/openssl/include/openssl/dh.h 2b2d1d499c5edf35ef3f9ac62bececf383d41ac8 - optee/optee_test/host/openssl/include/openssl/ebcdic.h 7a76095422e2ee1f5fb153ba7c0c2ef9433ea6b8 - optee/optee_test/host/openssl/include/openssl/rc4.h 8f83d8e48dcc303c8728abdc98037de8201324cd - optee/optee_test/host/openssl/include/openssl/hmac.h 0aa379746d3f24d0b687810aaaf0713ac8d86cac - optee/optee_test/host/openssl/include/openssl/cast.h 2048939555964c40f69cdefc57dcea55871b5e21 - optee/optee_test/host/openssl/include/openssl/mdc2.h 5dbab49158bcb4a23e2a0bf815685b7af61f2deb - optee/optee_test/host/openssl/include/openssl/aes.h d71fa389c798ef55aeb8e8b585fc1162e31bdcc2 - optee/optee_test/host/openssl/include/openssl/opensslv.h b57a6862b5e685a8307d9223bb7503a7d455beed - optee/optee_test/host/openssl/include/openssl/e_os2.h 833548d5315aae6cb83981ec70013ca82d8ba523 - optee/optee_test/host/openssl/include/openssl/stack.h f2d2c1d8957a3a90515fad312be14bd33b7457ae - optee/optee_test/host/openssl/include/openssl/ocsp.h 3990fba87a08e52c857f2d84c339515db4d5961b - optee/optee_test/host/openssl/include/openssl/ossl_typ.h 4617f3f1b34e51a83332ce79f96b7d21ee8850b8 - optee/optee_test/host/openssl/include/openssl/rand.h 1ac129425f344b32376a91e54598a3dfa0f5fd5e - optee/optee_test/host/openssl/include/openssl/pkcs7.h 81b3cbbc6aec76fe305933bb36fbe6cccc40060a - optee/optee_test/host/openssl/include/openssl/asn1.h 37a6ce9452aba6d49d2187b0b511cdc7fbc74f79 - optee/optee_test/host/openssl/include/openssl/des.h b363b25219a1c9eacee176d89341d73f1c48fc2c - optee/optee_test/host/openssl/include/openssl/bn.h 2ace7c1f67fc524df92ae2ae2664d1c801133683 - optee/optee_test/host/openssl/include/openssl/symhacks.h fb15a076c1eb0858fe09e6810ad86e3a8991a9ce - optee/optee_test/host/openssl/include/openssl/x509v3.h 9f1ac5a09d7973c8cd30e0298ac1d1be1a0d6886 - optee/optee_test/host/openssl/include/openssl/blowfish.h 4b7d9942149c0c6118f6cfd9c003f90d588296b3 - optee/optee_test/host/openssl/include/openssl/conf.h d18c728f023f12638001d15986c50433e663a09c - optee/optee_test/host/openssl/include/openssl/pem2.h 7eeea32830643e2f0f4d15395206df2be5df49c4 - optee/optee_test/host/openssl/include/openssl/ecdh.h dcfb707bab9b356d55f13464fd8d7e11a3bdea22 - optee/optee_test/host/openssl/include/openssl/md5.h 84e95faa34c5a831ee71a5f5dcbb646201b3ebb9 - optee/optee_test/host/openssl/include/openssl/des_old.h b6b3c01be13efb980c8906da0393538b4c3719c7 - optee/optee_test/host/openssl/include/openssl/seed.h 7244a5772f23284c8bd43229143a1593bb09f056 - optee/optee_test/host/openssl/include/openssl/sha.h 91b236bcae76db131199e0e286ac95943640a75c - optee/optee_test/host/openssl/include/openssl/bio.h eae391c729397d3c5ad18e6910ce855e200507bb - optee/optee_test/host/openssl/include/openssl/opensslconf.h eac535357ab50226b3107ae08f15db1a440545b7 - optee/optee_test/host/openssl/include/openssl/srtp.h 7a4605500282f7f93bf6a9d81906d951840f0b02 - optee/optee_test/host/openssl/include/openssl/ui.h f23cbec4815cddcfe918ef1922900963069b9e41 - optee/optee_test/host/openssl/include/openssl/cms.h e9da708e470b8d2252e9b09393e5c4580b1f4bb6 - optee/optee_test/host/openssl/include/openssl/ripemd.h 91fd336279423d8e0ccfcd3fe23df9b480034889 - optee/optee_test/host/openssl/include/openssl/x509_vfy.h 54dd565d744fbcfa3e38942843caa0ecc019a910 - optee/optee_test/host/openssl/include/openssl/ssl2.h 3871fe3539f575999166622f5f3295fb9b9ae673 - optee/optee_test/host/openssl/include/openssl/buffer.h e2ba178670ae93680fb28a3b57fff7f6917355e1 - optee/optee_test/host/openssl/include/openssl/kssl.h 2c6c8cda8629b0d3dda1efc8f1a5ebd445e91955 - optee/optee_test/host/openssl/include/openssl/engine.h f2463bfe32222c40ede22c3029699bf0a72ebcc5 - optee/optee_test/host/openssl/include/openssl/ec.h 2f638be4aded9c65a4b26ba81b30866b9dd161de - optee/optee_test/host/openssl/include/openssl/pem.h 8950cfbc3480ab12e4820970075260196620fe62 - optee/optee_test/host/openssl/include/openssl/ssl.h 6d1f831d4539dda2a411e59d8a6b796f3182de46 - optee/optee_test/host/openssl/include/openssl/modes.h 5e329424d948cbb1c0d9dd3ebb4186628f2187a8 - optee/optee_test/host/openssl/include/openssl/ts.h 348d7310a404d8ea1ebb6643a5ce6f0825ab9cdd - optee/optee_test/host/openssl/include/openssl/conf_api.h 3983b476f0abceec9b60bb53eebdfe56fad3a5fa - optee/optee_test/host/openssl/include/openssl/idea.h c8c527ee5e92b3a1ecffcec43a430403632a3add - optee/optee_test/host/openssl/include/openssl/camellia.h fa9bfab1d6d9e91f5277755673e3cb5b03705e91 - optee/optee_test/host/openssl/include/openssl/dtls1.h 9e6782cd54849b4c6bbdac9bac3bac212a8cec90 - optee/optee_test/host/openssl/include/openssl/obj_mac.h 5ae3cd2824e759e5db6b4db2e8c1822522106ede - optee/optee_test/host/openssl/include/openssl/ssl23.h 23ea4c0c2a08169c3b483dbfc029ad2ca6ffef06 - optee/optee_test/host/openssl/include/openssl/ssl3.h 44533c0a69f2f7b36d3cb7f4b5988f6cdde1ddf1 - optee/optee_test/host/openssl/include/openssl/x509.h 91d7ca042ccce5880c8e269596f308ae0b9ea926 - optee/optee_test/host/openssl/include/openssl/evp.h b41be35897beb8a5a5e4335933691bb60a0866ea - optee/optee_test/host/openssl/include/openssl/srp.h 71d0dc5dcf2d6f948006266274599e59df948640 - optee/optee_test/host/openssl/include/openssl/cmac.h a5f237896f32dc70faa6ee3dc24759a9db5aff2c - optee/optee_test/host/openssl/include/openssl/crypto.h c60c090361a630efae68bdd14760bb2e6562fe41 - optee/optee_test/host/openssl/include/openssl/ui_compat.h 6d98c86e1e6c3cda9df339540539b819f9ee038f - optee/optee_test/host/openssl/include/openssl/tls1.h ead277c7cf2b9d4210347bbe980c0ea419cd8ad5 - optee/optee_test/host/openssl/include/openssl/txt_db.h 1afa8c4dffa42c03657b47d7d6a317c0d09fafc6 - optee/optee_test/host/openssl/include/openssl/dsa.h 3a84c50fc7a71ea781a04dcd3d1915a83c0193c6 - optee/optee_test/host/openssl/include/openssl/safestack.h 95a13ac793b2a71b4ae39c72da0f18012db54268 - optee/optee_test/host/openssl/include/openssl/dso.h 385087b8e5f37ef32cbbf8af02de4f24acab85df - optee/optee_test/host/openssl/include/openssl/asn1t.h 8a674b7fa0641dff8c2b55e565149cdb3d208fb8 - optee/optee_test/host/openssl/include/openssl/objects.h dc45fa098993e12071562269ab765bf9160fa670 - optee/optee_test/host/openssl/include/openssl/err.h 386831d0bd03bc34d096121a9412f212a82507e7 - optee/optee_test/host/openssl/lib/aarch64/libcrypto.a 2f90ea6f809369b37a3d482750a9616ae008aa5c - optee/optee_test/host/openssl/lib/arm/libcrypto.a d9f2461c2a9d755472e666b2c5b60fe21ae7f431 - optee/optee_test/host/xtest/regression_8100.c 4e533d0531c352071ee236302dab1c2fed2068d6 - optee/optee_test/host/xtest/install_ta.h 80a9b9f4795682feb072795a92f15c630eefa57d - optee/optee_test/host/xtest/sdp_basic.h 4ed1b27140db56a58e598a1d47e2eee729363f6c - optee/optee_test/host/xtest/xtest_test.c 032a232dd66725d849cb168cfb5ed48cc19a2023 - optee/optee_test/host/xtest/xtest_test.h 01ce700dbb77213e51c372e4e6dc61082d7da4fe - optee/optee_test/host/xtest/regression_8000.c 12ca0aa8361d1e3bdbf54e11e288ca087745ce14 - optee/optee_test/host/xtest/benchmark_1000.c 3203c2511c56b80cf0757ce40aff2627e1589f54 - optee/optee_test/host/xtest/regression_5000.c e1fb4f35907beabaf3b0dbe646b45d64d4aa5d03 - optee/optee_test/host/xtest/stats.h 47d40cdaa11a5c163ebe1b3f530bc7706b43fefd - optee/optee_test/host/xtest/hash_perf.c 4f006a99a3d317def8f48cbcd1450ab4132eda31 - optee/optee_test/host/xtest/regression_1000.c 1c0d518167dbd004a55feb971308505c53869a40 - optee/optee_test/host/xtest/sock_server.h 68d3a5e5deb31ba074b1848cf8e1ab7b3ee6606a - optee/optee_test/host/xtest/regression_4100.c d300a7ef8b1675a42dbf548bc666f0a25b52f241 - optee/optee_test/host/xtest/regression_4000.c 34252d1d1af13adc2316a7646dd79af124e5f2c0 - optee/optee_test/host/xtest/Makefile 6c62f544374fa83651ea1885eee47d0811ed10a9 - optee/optee_test/host/xtest/sdp_basic.c 6074430df45012584a40484c4ed72373bcbbe599 - optee/optee_test/host/xtest/benchmark_2000.c 175414663dc68fd21ab80cf3420337256d7570c4 - optee/optee_test/host/xtest/xtest_uuid_helpers.c fcc29faa1a7c09980dd59d6d420b3c4c944fa09d - optee/optee_test/host/xtest/xtest_main.c ee2eb88f341b89c3f0408931d30d5bbf17dd5b1b - optee/optee_test/host/xtest/ffa_spmc_1000.c 14686c51c1e1fc99b03e351c11aed2874aee799d - optee/optee_test/host/xtest/install_ta.c 4cc77b90af91e615a64ae04893fdffa7939db84c - optee/optee_test/host/xtest/LICENSE 5943cfc12866b99e42e14fd92203ed1767ab893a - optee/optee_test/host/xtest/stats.c 4b76e6786bed1ae8da806d21ac567198a5bebdd8 - optee/optee_test/host/xtest/rand_stream.h aba50362fcc1ac3ba6d33e204435ca7a84cfb20e - optee/optee_test/host/xtest/regression_4000_data.h f3517bebcb21463533c4004d029833eaf5cde12f - optee/optee_test/host/xtest/xtest_uuid_helpers.h 16276b9d01ba73bf3bb21cb41ff264f3d0126d20 - optee/optee_test/host/xtest/sock_server.c a611cff7cdaf3b04d87eef15c299048990ec3ea1 - optee/optee_test/host/xtest/xtest_helpers.h 2396216346fc9cde6fa94372e0bb7a14d0bc4fc1 - optee/optee_test/host/xtest/pkcs11_1000.c 9f00cd47e998059a38459f0c6eb06c7b4662bf83 - optee/optee_test/host/xtest/regression_6000.c d5fc61a73a10975c5945aa67296797824b64b8b4 - optee/optee_test/host/xtest/rand_stream.c 52b11c0af213c40771048607e3da5eb5943e0d98 - optee/optee_test/host/xtest/regression_2000.c 9f2e5d4fab27dc73f38eb0289cd64269900bf3e7 - optee/optee_test/host/xtest/aes_perf.c d4e67633393e1eafbf02639e218f430a71cb978d - optee/optee_test/host/xtest/xtest_helpers.c bb316ac26e30020622adeecd07ddf9139e9202c2 - optee/optee_test/host/xtest/crypto_common.h e6ac80b711f1a44d2eb77e1c618fe7f3270205be - optee/optee_test/host/xtest/nist/186-2ecdsatestvectors.h a8012c439058a9ab645990d2efcd10447bc34324 - optee/optee_test/host/xtest/nist/ecccdhtestvectors.h 99f104f79f66a659ea913d475077f7503b8a1c51 - optee/optee_test/host/xtest/nist/186-3dsatestvectors.h dd01f2d86e9e0e0a15aab712c3828f76e4c6e2fc - optee/optee_test/host/xtest/adbg/include/adbg.h cf415448a59978f2a427eddeb129a7080f5b5dbf - optee/optee_test/host/xtest/adbg/src/adbg_expect.c f465eee2e09e054182205ae7c53f7253604401b9 - optee/optee_test/host/xtest/adbg/src/adbg_run.c fd1a3702bdc602b4b70535b00d38b9443e275607 - optee/optee_test/host/xtest/adbg/src/adbg_int.h bef73e2c136bf2a04bc8cf33b2052afac83535c1 - optee/optee_test/host/xtest/adbg/src/adbg_case.c e62cdf03f6bf82c09ca10f285a951c1018bbe70d - optee/optee_test/host/xtest/adbg/src/adbg_log.c 877fc553d7b1b08364cb1189bf4cdc3b6cf3c0e6 - optee/optee_test/host/xtest/adbg/src/security_utils_hex.c 4f57fda84526a6b64ecc3eccc008e18b97fc3523 - optee/optee_test/host/xtest/adbg/src/security_utils_hex.h 825ea0288d353fbf26dd5cb0e56be8db4e7bf245 - optee/optee_test/host/xtest/adbg/src/adbg_enum.c 35ce411007e4e624913b8da87f51325be763d65d - optee/optee_test/host/xtest/gp/prepare_suite.sh 78e225e2b8581d7bd917bf1c007f4fee5b1d088b - optee/optee_test/host/xtest/gp/TEE_Crypto_API.xsl 488980fe7c4d8999c8466da403ef5b2811727e7d - optee/optee_test/host/xtest/gp/TEE_TimeArithm_API.xsl d00562756b00f6607632030c58bbd3576f7c13aa - optee/optee_test/host/xtest/gp/TEE_Internal_API.xsl 39dbed853b87d4a916b95de14d5e23a8f434bfb2 - optee/optee_test/host/xtest/gp/TEE.xsl baf0c6e02b9300a37bd4409628cea730d71faa5f - optee/optee_test/host/xtest/gp/TEE_DataStorage_API.xsl c6196ca75d7d48f6e14cc561eefaa9f320adc598 - optee/optee_test/host/xtest/gp/include/xml_datastorage_api.h 93a968118f5345200d7a4d9d78443ada60e64227 - optee/optee_test/host/xtest/gp/include/xml_crypto_api.h 438135b73e49aaad9e34b6863f5bc922f1013b64 - optee/optee_test/host/xtest/gp/include/xml_common_api.h 9d3445c797b4be4516d15baa3e11c682dd8b4918 - optee/optee_test/host/xtest/gp/include/xml_internal_api.h 1af3df59426284098690de7d43586a5e4fd37db9 - optee/optee_test/host/xtest/gp/include/xml_timearithm_api.h 7b0cf45da16221e265fbd01221f541b851cb9e21 - optee/optee_test/host/xtest/gp/include/xml_client_api.h 5bdbfb7c09b73b8ee3f012bb4c05c5655a2e426c - optee/optee_test/host/xtest/gp/patches/0012-TTA_TCF-remove-TEE_MemMove-from-CmdTEEGetPropertyAsX.patch 146a6228e298272ab7e73778962df356d9198311 - optee/optee_test/host/xtest/gp/patches/0010-TEE_DataStorage_API.xml.patch 496f8635c2c0110849cb7e095423e036dae754ec - optee/optee_test/host/xtest/gp/patches/0014-Pass-upper-32-bits-of-TEE_PropSetHandle-in-value.b.patch 705d65243c1e46af9f9642bb84f45b2daeff957f - optee/optee_test/host/xtest/gp/patches/0008-TEE.xml.patch 4f9aca322840391a171d320f3e9d5976b257fa41 - optee/optee_test/host/xtest/gp/patches/0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch 0c86f63bc803a23617fb13ba1479108edaf5dac5 - optee/optee_test/host/xtest/gp/patches/0009-TEE_Internal_API.xml.patch cbc872e82c403faa84376db8efc78150338e2693 - optee/optee_test/host/xtest/gp/patches/0004-TTA_Arithmetical-patch.patch c834f47f97dd115566b874fa7e4a6d40d064d939 - optee/optee_test/host/xtest/gp/patches/0013-Disable-Invoke_GetTAPersistentTimeNotSet_and_SetTAPe.patch 163d266dd45cad8536da0f2e1f5c625fc45e2e52 - optee/optee_test/host/xtest/gp/patches/0005-GP_defs.h-enable-debug-prints.patch f0098e4814dc81f9ecae74036f354210e6c33a50 - optee/optee_test/host/xtest/gp/patches/0003-TTA_TCF-patch.patch 4436ae2a8726be665c4adbc30899d7dbcf721afd - optee/optee_test/host/xtest/gp/patches/0002-TTAs-add-files-needed-to-compile.patch 34223b3e49b6b18b8bf88abf784fac10a0648a10 - optee/optee_test/host/xtest/gp/patches/0015-Enable-compatibility-with-TEE-Internal-Core-API-v1.1.patch 93fe519236e63a82aec4fa2e267aa9c10a9cf3e2 - optee/optee_test/host/xtest/gp/patches/0007-TTAs-revert-to-v1.1-types.patch cc1ccad0b05569188be42a4e6fad9069b9b44d05 - optee/optee_test/host/xtest/gp/patches/0011-TEE_Crypto_API.xml.patch aa6291df45558c38403e3272c86920d0441aace1 - optee/optee_test/host/xtest/include/uapi/linux/arm_ffa_user.h ca513a618e76b7425f4f1350e90c7b74d4778eac - optee/optee_test/cert/my.crt 4c8bd2753f58de91b618d71902216b93834e1b18 - optee/optee_test/cert/ca.key 1f75eacaea5baa5f8ecd35d3c8df7e746c3f73a9 - optee/optee_test/cert/mid.srl 5870a0a431a6e7fd1fb251ada8f25d58c79a762a - optee/optee_test/cert/mid.csr f11ba7468488761597018fef555faaa8dcf0049f - optee/optee_test/cert/ca.crt cf7626a2e6fdd3e5cd2455117e6ff59e38cc3a99 - optee/optee_test/cert/mid.key c858311b53e86391299c5bc0c30a39801b3893a3 - optee/optee_test/cert/mid.ext 6f108292e83a3a3555b56add6fba6bfc75bb1d03 - optee/optee_test/cert/my.key 89bb7582daae987e60e094aebfd5b2b073e9ac62 - optee/optee_test/cert/my.conf 93503a34df30013f6f47e50cde65662d3e5d3a8c - optee/optee_test/cert/mid.conf 6b932b1ab7b3565ddb4557b31b13ff823577f997 - optee/optee_test/cert/my.csr 9162a5682d5d26b3df6021cc646498709aadc3e9 - optee/optee_test/cert/ca.srl c1c1370410a6251da1f2a65d4bb6799b6695ae46 - optee/optee_test/cert/mid.crt d9a4193c1df764fc72c7e49efeeb550f84c6dcb0 - optee/optee_test/ta/identity_subkey2.bin 8890459880f4ef0eb20f8a28b727540e789f07a3 - optee/optee_test/ta/identity_subkey2.pem 5d45a78f116ff6a6a5ce6227b1dd705d86a1a640 - optee/optee_test/ta/mid_level_subkey.pem 787a4239906f6e69dc5f12f7eb194950ab92fbdd - optee/optee_test/ta/Makefile 2f0deec19c000366d2fd6d627f9b4363213eef7a - optee/optee_test/ta/mid_level_subkey.bin 494d296fe7e6b7bc0f500a343c6a33cf9f0b05a3 - optee/optee_test/ta/top_level_subkey.bin 525fc4d0105b2261ed118a2d96d2cbf71cba2432 - optee/optee_test/ta/top_level_subkey.pem c16239ae81d65b85bdbf88f1ec1695ce06a10c24 - optee/optee_test/ta/aes_perf/ta_entry.c 571347fdcd744e2ab03261542891ebb469e61c85 - optee/optee_test/ta/aes_perf/Makefile 7fbb1b605782db00da42f6acd94c45b8535df785 - optee/optee_test/ta/aes_perf/ta_aes_perf.c 837e306e61195565be0391ea2ee9c24557c82908 - optee/optee_test/ta/aes_perf/include/user_ta_header_defines.h 3367296a9f889d9d13d77d03830ca17f9c6786db - optee/optee_test/ta/aes_perf/include/ta_aes_perf_priv.h 24d404e8f61876d1768f09f4d5f698c2fba3fddd - optee/optee_test/ta/aes_perf/include/ta_aes_perf.h dfa325b63f0b17c8ef3c8e1e055e4f8dc2135812 - optee/optee_test/ta/storage_benchmark/benchmark.c 126f0a0f43f2045ed64ac151420ff2750039cae6 - optee/optee_test/ta/storage_benchmark/ta_entry.c a7891e77ba72a13303bee70e3469d5b66c4dd0ff - optee/optee_test/ta/storage_benchmark/Makefile 350b57d8d13e85db59890347995fb8b25902941d - optee/optee_test/ta/storage_benchmark/include/storage_benchmark.h e69f771764df6d0ccfead0a6b563545f3f43b159 - optee/optee_test/ta/storage_benchmark/include/user_ta_header_defines.h 44317f3ee1e0f27bc5889d02e634bcddc250334a - optee/optee_test/ta/storage_benchmark/include/ta_storage_benchmark.h 63727dbe77411a56de4384f2647ac604df1bb77e - optee/optee_test/ta/sims_keepalive/ta_entry.c 3e93b929b783566f5933da6daf3bf178b60f0ac9 - optee/optee_test/ta/sims_keepalive/Makefile 17584ab846d09d2e11a0c62ee9c12f7eb00a89f2 - optee/optee_test/ta/sims_keepalive/ta_sims_keepalive.c 8b0caca8445e731ff595dca61af1768b26fc70df - optee/optee_test/ta/sims_keepalive/include/user_ta_header_defines.h 1b55cdb55165cb46dd80757553d9aab34a61dcd3 - optee/optee_test/ta/sims_keepalive/include/ta_sims_keepalive_test.h 3762c8d8188b6fd5c0e0216aa0dfbc1a81c33bd4 - optee/optee_test/ta/sdp_basic/Makefile 03a7ec19dd525347d073d1ef9887d1c32e2ec843 - optee/optee_test/ta/sdp_basic/ta_sdp_basic.c a0178fe3ab1e1cd9204c5868dfb36eed00a7d800 - optee/optee_test/ta/sdp_basic/include/ta_sdp_basic.h 9123b67fb31c5aa32dc2d54b9a1d2dcff27b3996 - optee/optee_test/ta/sdp_basic/include/user_ta_header_defines.h b33588442f2691e00ae34677fee3503279ec4251 - optee/optee_test/ta/concurrent/ta_entry.c 403faf3efbd2a187981acd30a58067dcb43d4d2f - optee/optee_test/ta/concurrent/Makefile b203b24b6fb092d32555949aece3d104a945d314 - optee/optee_test/ta/concurrent/include/user_ta_header_defines.h 81d9fc2603da64f6aca629d4c1f6152ce40f4299 - optee/optee_test/ta/concurrent/include/ta_concurrent.h 3231e66bc961e72de9759c2d801cf7e081611183 - optee/optee_test/ta/large/ta_entry.c 5558acac0905fc8f55ec7451c6cafff4654c532c - optee/optee_test/ta/large/Makefile 78c0f90194587f8ec4696ed9937eab82bd2d6102 - optee/optee_test/ta/large/include/ta_large.h 04b692b46b7c145c2fe975bb20250626d9e5680e - optee/optee_test/ta/large/include/user_ta_header_defines.h b0992bc9d242a926b54b8162b36f7f219c278624 - optee/optee_test/ta/os_test_lib/os_test_lib.c 192ebe9f6d76a6b9d3938a69c72663ef7b627fff - optee/optee_test/ta/os_test_lib/Makefile e0089857c48d5c57869ad4d411a71a2a3ba33f80 - optee/optee_test/ta/os_test_lib/os_test_lib_cxx.cpp e868bceb0a3e38d9c81f3fece9efc1ced6e9b1b9 - optee/optee_test/ta/os_test_lib/include/os_test_lib.h fd20f8c7b48682f3cb154209d193c38ef5fa8afa - optee/optee_test/ta/storage2/ta_entry.c 3777dde2c0aee5f993ddf5f6e2899d578554736d - optee/optee_test/ta/storage2/Makefile b5ccb3b112baffad3e3afb89d72d7cc8a922ce1c - optee/optee_test/ta/storage2/storage.c 1c8f590037f4f9235325a760a6e10589ac820492 - optee/optee_test/ta/storage2/include/user_ta_header_defines.h 8ace73b1298eb7b4679a5f6a93533d147c6165f0 - optee/optee_test/ta/storage2/include/storage.h 739bf20897d248851d4e26908cc4a58f70ff9e98 - optee/optee_test/ta/os_test/ta_entry.c c845f1bef062d33dd7e59d0647155b05ef5ed6ac - optee/optee_test/ta/os_test/attestation.c a4ae385c460bad98c3f1bb74e4cd6d78a3d1c569 - optee/optee_test/ta/os_test/cxx_tests.cpp 0821f97bb6d0e672f229f163d91a44db3b3cfc21 - optee/optee_test/ta/os_test/pauth_a64.S 0455da7d426f2d9c91e8d1f0ceedcbcdc25b7e63 - optee/optee_test/ta/os_test/cxx_tests.h efba276afd39d7103c04a55a36060b6da949183b - optee/optee_test/ta/os_test/os_test.c 81b48e32f421e3809c799370e7d5a84be82e4007 - optee/optee_test/ta/os_test/test_float_subj.c e00637d3dc4e177f4693a591711c655a84f82c6e - optee/optee_test/ta/os_test/Makefile 30c95077d893a72f6dd6f25698b9e3c4c90c7173 - optee/optee_test/ta/os_test/ta_arm_pauth.c f99ecd7a7d1466b6ae095553f19b144a3b5e05a6 - optee/optee_test/ta/os_test/cxx_tests_c.c 4b24fec7bb0779f54df830b2accd4589c58ee714 - optee/optee_test/ta/os_test/test_float_subj.h 7c34f62620b2c3cf1e435dc2f06b5bc695a0ffca - optee/optee_test/ta/os_test/init.c 9f19100db2cc1610f815fafd087f583d78880d0d - optee/optee_test/ta/os_test/include/ta_os_test.h c250edae8e50b81ddc7f2d82b74533be8ce36484 - optee/optee_test/ta/os_test/include/user_ta_header_defines.h 9a31e7f47747984b55fcfd8f87f8c3eda3903943 - optee/optee_test/ta/os_test/include/tb_asserts.h 263c19c932534cb04ff5681cf3331201d72711ec - optee/optee_test/ta/os_test/include/tb_macros.h ef669e3a5af86a9d7433680efe47e7475ebae840 - optee/optee_test/ta/os_test/include/testframework.h dfa926eae1baeaa723c73c36a5a87108a941f0a8 - optee/optee_test/ta/os_test/include/os_test.h c0f2b4917d2e7e2c64767ce20c51277d030da95e - optee/optee_test/ta/os_test/include/init.h 615513981a90fabad2bd36d67b4ece7b3e63bfe6 - optee/optee_test/ta/supp_plugin/ta_entry.c e3deb7bd3c13099679c0218b2daabc17547fb2aa - optee/optee_test/ta/supp_plugin/Makefile 97d8481ac3b8dd32d148d69acc3da07308fb759a - optee/optee_test/ta/supp_plugin/include/user_ta_header_defines.h a6d7b87593d95249d1adf41e1ed2855be8557092 - optee/optee_test/ta/supp_plugin/include/ta_supp_plugin.h f041af378514b0adb83e13683c439bdfda633a38 - optee/optee_test/ta/tpm_log_test/ta_entry.c 159ab9161f614e0e78c7ed8ad589b1da7dc49313 - optee/optee_test/ta/tpm_log_test/Makefile 05d9586c179dfa463023108f57186c397f67b168 - optee/optee_test/ta/tpm_log_test/include/ta_tpm_log.h 15979122b263375291e30ed248816c707e51aa9d - optee/optee_test/ta/tpm_log_test/include/user_ta_header_defines.h 071de3ab826aea3082b54036a436e42d20e5e829 - optee/optee_test/ta/tpm_log_test/include/ta_tpm_log_test.h 63727dbe77411a56de4384f2647ac604df1bb77e - optee/optee_test/ta/miss/ta_entry.c 6902d41cad5e1a7fdd792070ee6fe09543fd0a36 - optee/optee_test/ta/miss/Makefile 17584ab846d09d2e11a0c62ee9c12f7eb00a89f2 - optee/optee_test/ta/miss/ta_miss.c 7577f16d52d892d26d2aba97100c391696f1b4e0 - optee/optee_test/ta/miss/include/user_ta_header_defines.h e8cc80687d4a1d454c124c0288798e280142a723 - optee/optee_test/ta/miss/include/ta_miss_test.h 246ca7646c82ccb61f14a0b439ec943d8850f0dd - optee/optee_test/ta/storage/ta_entry.c a29dec4b78281324f1e479a7648b636feef1d163 - optee/optee_test/ta/storage/Makefile 9fdefd261cbb4dfe3fcdfb05749fd3acaa8383bb - optee/optee_test/ta/storage/storage.c cbcf995c4fce7f48869248f9f3bf912195d4873e - optee/optee_test/ta/storage/include/user_ta_header_defines.h b958d8b7c770808b61bfb420a9d39473b275e4c4 - optee/optee_test/ta/storage/include/storage.h 96b12ede29af7df11c0b54a3d3924599f9ad0de4 - optee/optee_test/ta/enc_fs/include/enc_fs_key_manager_test.h e1b35b65fffd182965ab59d513da17f3bc2cb637 - optee/optee_test/ta/socket/ta_entry.c dfc1e1eb35732695271ed55f42d20a4f3d65dd85 - optee/optee_test/ta/socket/Makefile 7caf8e51e601aad92bfa2080fd1d462af34a690f - optee/optee_test/ta/socket/include/user_ta_header_defines.h 60c71c4fd9746b52eff3180768cadfb42246ad63 - optee/optee_test/ta/socket/include/ta_socket.h a2d1207a964e7c839176e0c9beb333de1aa5114d - optee/optee_test/ta/sims/ta_entry.c b27b844ff53c4ce9ea4b37becfc73759661121c9 - optee/optee_test/ta/sims/ta_sims.c 62093428f73279ad6337e6b83de79cdc9638aa07 - optee/optee_test/ta/sims/Makefile d89af8095b36e083626767c864548995a05f5be0 - optee/optee_test/ta/sims/include/user_ta_header_defines.h 11789923a6ea66b45d579f62db7b637f475896b5 - optee/optee_test/ta/sims/include/ta_sims_test.h 3c47004c9fc79085a49889e5e0a2f74eb9672619 - optee/optee_test/ta/sims/include/ta_sims.h 3a18196418d2722e402a8427f7c603fbb0001208 - optee/optee_test/ta/hash_perf/ta_entry.c c55f5d16d5adcee00938fe1809a49f80f8b4466c - optee/optee_test/ta/hash_perf/Makefile fe7cfa7b09ca126fe985f184990efd82c5364016 - optee/optee_test/ta/hash_perf/ta_hash_perf.c 9e4cddd8c6ca6c49ccf2a9c071940659a8404666 - optee/optee_test/ta/hash_perf/include/user_ta_header_defines.h 30630325b3b69827882db59d7c22880109f1aed7 - optee/optee_test/ta/hash_perf/include/ta_hash_perf.h 3ab83f366683236b9a32ce8c776846709795c9fd - optee/optee_test/ta/hash_perf/include/ta_hash_perf_priv.h 0205269ec12a07945fa15e1f01beacd396129c02 - optee/optee_test/ta/crypt/ta_entry.c a35bf9387750436613dd75a04109a0ac26abb4ad - optee/optee_test/ta/crypt/mbedtls_taf.c 2f8d16642c23418d96eae0799cdbb319adae9bd2 - optee/optee_test/ta/crypt/aes_taf.c 6d536756fbdc5623379b5c8c68b3383c6c3c7535 - optee/optee_test/ta/crypt/aes_impl.c 707f95e800674bd769a22f4b05b0f86bde9bdda0 - optee/optee_test/ta/crypt/Makefile f22bc5e3e7d42fae8b515ed89e6d52e14853097d - optee/optee_test/ta/crypt/arith_taf.c cda695cd368148125b67d4b5049b4b5e44f19d4d - optee/optee_test/ta/crypt/sha2_taf.c 71541fecba370d8d5d888ff889cc55a649e0f6e3 - optee/optee_test/ta/crypt/handle.c 0f5728bb87da64faea76a4d60859ffc6ee7cfb0e - optee/optee_test/ta/crypt/seed_rng_taf.c 62f575dd691dc4df07cd85b6aaf381bb1fa129df - optee/optee_test/ta/crypt/handle.h ae237aa24606ab8442252be914264ebc32acb3f1 - optee/optee_test/ta/crypt/derive_key_taf.c 89299c5c290be38d0509309892bd9bf67946a552 - optee/optee_test/ta/crypt/sha2_impl.c 08792d69cd8404668362c47a42015e3ed15a03e2 - optee/optee_test/ta/crypt/cryp_taf.c 98b131e0650e8848c202b367de6afd9713234b23 - optee/optee_test/ta/crypt/include/cryp_taf.h 81c28b5d39b57c60583003aa3b19d4e9355be3e8 - optee/optee_test/ta/crypt/include/aes_taf.h 65726ede28ff3980980f0786f73da00bf00f7adf - optee/optee_test/ta/crypt/include/aes_impl.h e39b6697e3f099db9e9210630f403279d821b01d - optee/optee_test/ta/crypt/include/user_ta_header_defines.h f922975017d8e69cf55d924ad3475f48207c778c - optee/optee_test/ta/crypt/include/sha2_taf.h dedb18c14d2c13ecb2666beff2d43a1c6f2b1f4c - optee/optee_test/ta/crypt/include/derive_key_taf.h bece95c11da1deff583de5cccb73aeb047b13bb3 - optee/optee_test/ta/crypt/include/seed_rng_taf.h 971b7e4384dfd449056d2d98600938baaa13b45c - optee/optee_test/ta/crypt/include/arith_taf.h 751a9eda488bdee96dd4666819f86792eb94e63c - optee/optee_test/ta/crypt/include/mbedtls_taf.h 59bb92661052957ededa8bf444418db0f792e5df - optee/optee_test/ta/crypt/include/sha2_impl.h d6094f43aff3a5e99b1b4916e6f0616f4b506c4e - optee/optee_test/ta/crypt/include/ta_crypt.h 34655a75cdbf9b1cf1a0f475a835630aa77d76ad - optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl.c 0b8f95e1cc815a73f1913f8b1cd1199b86afd777 - optee/optee_test/ta/os_test_lib_dl/Makefile 9d8c78ff226d9cd3e8f8be315142adc0bdc791d5 - optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl_cxx.cpp 36e93c9c976420202d3962d3af744a06481e4bda - optee/optee_test/ta/os_test_lib_dl/include/os_test_lib_dl.h 28e50e4d884a51351b0454dcf8971ea8619becb2 - optee/optee_test/ta/rpc_test/ta_entry.c db39d7c16208c8b18547c18b524c4d4d8d8533a6 - optee/optee_test/ta/rpc_test/Makefile 515cd2121fffeb7e284eb41a47cd39f68e8caee3 - optee/optee_test/ta/rpc_test/ta_rpc.c bb5b31def49e12cb5ca13946631064fdab7f3ce1 - optee/optee_test/ta/rpc_test/include/user_ta_header_defines.h daf6f0380173f9c72cb5ab411c7e145635102403 - optee/optee_test/ta/rpc_test/include/ta_rpc.h 5a06508a48d77c9bc4d4483f2c1064bc11547f17 - optee/optee_test/ta/rpc_test/include/ta_rpc_test.h 729fae7d04cb0ca43a757f92763e4accc4b12b47 - optee/optee_test/ta/include/ta_storage.h e98d28dd7d955c5f1430b86d1f9fa9a293f2c6a5 - optee/optee_test/ta/subkey1/ta_entry.c ab190ed1cbd92987955bd1b18cf1125760e00235 - optee/optee_test/ta/subkey1/Makefile fccce5046748bb0a2c4bf866d2ee4099789327e9 - optee/optee_test/ta/subkey1/include/ta_subkey1.h 3ef18fee5ed3f12595bcae5cd670e9b614bddccb - optee/optee_test/ta/subkey1/include/user_ta_header_defines.h 327bcd861d17179ed6eec837ae40d93f6d4d5171 - optee/optee_test/ta/create_fail_test/ta_entry.c 969daad84d451c2beaaeb0205d361045b135c899 - optee/optee_test/ta/create_fail_test/Makefile 28f22d74fc72b507d9530a7788812714f4ccd2be - optee/optee_test/ta/create_fail_test/include/user_ta_header_defines.h f8ff5608bd441c5bb14ba4e0d1ac825036c0be26 - optee/optee_test/ta/create_fail_test/include/ta_create_fail_test.h c5741796e6b99090e6fd99dc03a6bbcfe6871028 - optee/optee_test/ta/concurrent_large/ta_entry.c 305e7a10ae0489f83dfe773f06b47ad314bb9771 - optee/optee_test/ta/concurrent_large/Makefile 51f374f9df753de95e0ee8a082c29395bed8625a - optee/optee_test/ta/concurrent_large/include/ta_concurrent_large.h 6fc98a616100591a9ba17fe01d8cd7f30c449420 - optee/optee_test/ta/concurrent_large/include/user_ta_header_defines.h 3484bf8a9bd48d0fd2c66b682574dcbd80ae59e7 - optee/optee_test/ta/subkey2/ta_entry.c 56e682b335cbdbb4b053f31838a28d596ea0dbf5 - optee/optee_test/ta/subkey2/Makefile d1217850bdabdc5c5f402556a4dd76a32af19d03 - optee/optee_test/ta/subkey2/include/user_ta_header_defines.h 786d2761de772f9af4885b058126e8596a16e194 - optee/optee_test/ta/subkey2/include/ta_subkey2.h 9752d870fbaca8ae7c1554096be6f228b5a0efaf - optee/optee_test/ta/bti_test/ta_entry.c 19e490a77411c75a67b54eb0684edc9dc35f7192 - optee/optee_test/ta/bti_test/Makefile 02a75c4818fde432ee44ba7d161b5c27851a796b - optee/optee_test/ta/bti_test/bti_stubs_a64.S a59733e35df2f166b33f45d74ffcad1404144624 - optee/optee_test/ta/bti_test/ta_arm_bti.c 7f829607eda29dcb8ef45bfba360ed98db860871 - optee/optee_test/ta/bti_test/include/ta_arm_bti_priv.h 3d48258f0e002fce82e638e430b603a76c11d113 - optee/optee_test/ta/bti_test/include/user_ta_header_defines.h a6569f27e231e4466e5b7f08f63a13626cf26810 - optee/optee_test/ta/bti_test/include/ta_arm_bti.h Change-Id: Icb2675cfb16e05a69d4805505d2324ad63cc6bc0 --- commitFile.txt | 2899 +++ nvcommon_build.sh | 58 + optee/atf_and_optee_README.txt | 139 + optee/optee_client/.github/workflows/ci.yml | 51 + .../optee_client/.github/workflows/stales.yml | 27 + optee/optee_client/Android.mk | 107 + optee/optee_client/CMakeLists.txt | 50 + optee/optee_client/CMakeToolchain.txt | 3 + optee/optee_client/LICENSE | 27 + optee/optee_client/Makefile | 173 + optee/optee_client/README.md | 10 + optee/optee_client/android_flags.mk | 27 + optee/optee_client/ci/Dockerfile.debian | 21 + optee/optee_client/ci/Dockerfile.ubuntu | 30 + optee/optee_client/config.mk | 79 + optee/optee_client/flags.mk | 37 + optee/optee_client/libckteec/CMakeLists.txt | 77 + optee/optee_client/libckteec/Makefile | 78 + .../libckteec/include/CMakeLists.txt | 12 + .../optee_client/libckteec/include/ck_debug.h | 41 + optee/optee_client/libckteec/include/pkcs11.h | 1248 ++ .../libckteec/include/pkcs11_ta.h | 1332 ++ optee/optee_client/libckteec/src/ck_debug.c | 460 + optee/optee_client/libckteec/src/ck_helpers.c | 29 + optee/optee_client/libckteec/src/ck_helpers.h | 29 + optee/optee_client/libckteec/src/invoke_ta.c | 360 + optee/optee_client/libckteec/src/invoke_ta.h | 103 + .../optee_client/libckteec/src/local_utils.h | 16 + optee/optee_client/libckteec/src/pkcs11_api.c | 1473 ++ .../libckteec/src/pkcs11_processing.c | 1705 ++ .../libckteec/src/pkcs11_processing.h | 139 + .../optee_client/libckteec/src/pkcs11_token.c | 841 + .../optee_client/libckteec/src/pkcs11_token.h | 59 + .../optee_client/libckteec/src/serialize_ck.c | 791 + .../optee_client/libckteec/src/serialize_ck.h | 23 + optee/optee_client/libckteec/src/serializer.c | 76 + optee/optee_client/libckteec/src/serializer.h | 34 + optee/optee_client/libseteec/CMakeLists.txt | 65 + optee/optee_client/libseteec/Makefile | 71 + .../libseteec/include/CMakeLists.txt | 7 + optee/optee_client/libseteec/include/se_tee.h | 90 + optee/optee_client/libseteec/src/pta_apdu.h | 47 + optee/optee_client/libseteec/src/pta_scp03.h | 31 + optee/optee_client/libseteec/src/se.c | 149 + optee/optee_client/libteeacl/CMakeLists.txt | 53 + optee/optee_client/libteeacl/Makefile | 77 + optee/optee_client/libteeacl/include/teeacl.h | 99 + optee/optee_client/libteeacl/src/group.c | 98 + optee/optee_client/libteeacl/src/tee_uuid.c | 35 + optee/optee_client/libteec/CMakeLists.txt | 78 + optee/optee_client/libteec/Makefile | 70 + .../optee_client/libteec/include/linux/tee.h | 417 + .../libteec/include/teec_benchmark.h | 37 + optee/optee_client/libteec/libteec.pc.in | 21 + .../optee_client/libteec/src/tee_client_api.c | 958 + .../optee_client/libteec/src/teec_benchmark.c | 221 + optee/optee_client/libteec/src/teec_trace.c | 141 + optee/optee_client/public/CMakeLists.txt | 25 + optee/optee_client/public/tee_bench.h | 77 + optee/optee_client/public/tee_client_api.h | 555 + .../public/tee_client_api_extensions.h | 57 + optee/optee_client/public/tee_plugin_method.h | 20 + optee/optee_client/public/teec_trace.h | 147 + optee/optee_client/scripts/checkpatch_inc.sh | 49 + .../tee-supplicant/CMakeLists.txt | 119 + optee/optee_client/tee-supplicant/Makefile | 107 + .../tee-supplicant/src/__tee_ipsocket.h | 37 + .../src/__tee_isocket_defines.h | 40 + .../src/__tee_tcpsocket_defines.h | 37 + .../src/__tee_tcpsocket_defines_extensions.h | 35 + .../src/__tee_udpsocket_defines.h | 41 + .../optee_client/tee-supplicant/src/handle.c | 175 + .../optee_client/tee-supplicant/src/handle.h | 82 + .../tee-supplicant/src/hmac_sha2.c | 126 + .../tee-supplicant/src/hmac_sha2.h | 74 + .../tee-supplicant/src/nvme_rpmb.c | 596 + .../tee-supplicant/src/nvme_rpmb.h | 16 + .../tee-supplicant/src/optee_msg_supplicant.h | 307 + .../optee_client/tee-supplicant/src/plugin.c | 233 + .../optee_client/tee-supplicant/src/plugin.h | 50 + optee/optee_client/tee-supplicant/src/prof.c | 137 + optee/optee_client/tee-supplicant/src/prof.h | 54 + optee/optee_client/tee-supplicant/src/rpmb.c | 989 + optee/optee_client/tee-supplicant/src/rpmb.h | 37 + optee/optee_client/tee-supplicant/src/sha2.c | 249 + optee/optee_client/tee-supplicant/src/sha2.h | 75 + .../tee-supplicant/src/tee_socket.c | 848 + .../tee-supplicant/src/tee_socket.h | 49 + .../tee-supplicant/src/tee_supp_fs.c | 681 + .../tee-supplicant/src/tee_supp_fs.h | 37 + .../tee-supplicant/src/tee_supplicant.c | 995 + .../tee-supplicant/src/tee_supplicant.h | 58 + .../tee-supplicant/src/teec_ta_load.c | 192 + .../tee-supplicant/src/teec_ta_load.h | 55 + .../tee-supplicant/tee_supplicant_android.mk | 74 + optee/optee_client/typedefs.checkpatch | 80 + optee/optee_os/.checkpatch.conf | 13 + optee/optee_os/.github/issue_template.md | 21 + .../optee_os/.github/pull_request_template.md | 19 + .../optee_os/.github/workflows/ci-cancel.yml | 22 + optee/optee_os/.github/workflows/ci.yml | 387 + optee/optee_os/.github/workflows/stales.yml | 27 + optee/optee_os/CHANGELOG.md | 1675 ++ optee/optee_os/LICENSE | 45 + optee/optee_os/LICENSE.NVIDIA | 141 + optee/optee_os/MAINTAINERS | 310 + optee/optee_os/Makefile | 127 + optee/optee_os/README.md | 7 + optee/optee_os/core/arch/arm/arm.mk | 445 + .../optee_os/core/arch/arm/cpu/cortex-a15.mk | 10 + optee/optee_os/core/arch/arm/cpu/cortex-a5.mk | 10 + optee/optee_os/core/arch/arm/cpu/cortex-a7.mk | 9 + optee/optee_os/core/arch/arm/cpu/cortex-a9.mk | 12 + .../core/arch/arm/cpu/cortex-armv8-0.mk | 10 + .../core/arch/arm/crypto/aes-gcm-ce.c | 231 + .../core/arch/arm/crypto/aes_armv8a_ce.c | 249 + .../core/arch/arm/crypto/aes_armv8a_ce.h | 32 + .../arch/arm/crypto/aes_modes_armv8a_ce_a32.S | 531 + .../arch/arm/crypto/aes_modes_armv8a_ce_a64.S | 664 + .../core/arch/arm/crypto/ghash-ce-core_a32.S | 241 + .../core/arch/arm/crypto/ghash-ce-core_a64.S | 650 + .../core/arch/arm/crypto/sha1_armv8a_ce.c | 21 + .../core/arch/arm/crypto/sha1_armv8a_ce_a32.S | 114 + .../core/arch/arm/crypto/sha1_armv8a_ce_a64.S | 125 + .../core/arch/arm/crypto/sha256_armv8a_ce.c | 21 + .../arch/arm/crypto/sha256_armv8a_ce_a32.S | 112 + .../arch/arm/crypto/sha256_armv8a_ce_a64.S | 136 + .../core/arch/arm/crypto/sha3_armv8a_ce.c | 25 + .../core/arch/arm/crypto/sha3_armv8a_ce_a64.S | 233 + .../core/arch/arm/crypto/sha512_armv8a_ce.c | 21 + .../arch/arm/crypto/sha512_armv8a_ce_a64.S | 204 + .../core/arch/arm/crypto/sm3_armv8a_ce.c | 22 + .../core/arch/arm/crypto/sm3_armv8a_ce_a64.S | 142 + .../arch/arm/crypto/sm4_armv8a_aese_a64.S | 1122 + .../core/arch/arm/crypto/sm4_armv8a_ce.c | 105 + .../core/arch/arm/crypto/sm4_armv8a_ce.h | 28 + .../core/arch/arm/crypto/sm4_armv8a_ce_a64.S | 1030 + .../core/arch/arm/crypto/sm4_armv8a_neon.c | 105 + .../core/arch/arm/crypto/sm4_armv8a_neon.h | 29 + optee/optee_os/core/arch/arm/crypto/sub.mk | 47 + .../core/arch/arm/dts/at91-sama5d27_som1.dtsi | 153 + .../arch/arm/dts/at91-sama5d27_som1_ek.dts | 527 + .../arch/arm/dts/at91-sama5d27_wlsom1.dtsi | 314 + .../arch/arm/dts/at91-sama5d27_wlsom1_ek.dts | 250 + .../arch/arm/dts/at91-sama5d2_xplained.dts | 739 + .../core/arch/arm/dts/dt_driver_test.dtsi | 51 + .../core/arch/arm/dts/embedded_dtb_test.dts | 11 + .../core/arch/arm/dts/fsl-lx2160a-qds.dts | 333 + .../core/arch/arm/dts/fsl-lx2160a-rdb.dts | 161 + .../core/arch/arm/dts/fsl-lx2160a.dtsi | 1385 ++ optee/optee_os/core/arch/arm/dts/hikey.dts | 22 + .../core/arch/arm/dts/sama5d2-pinfunc.h | 885 + optee/optee_os/core/arch/arm/dts/sama5d2.dtsi | 1205 + .../core/arch/arm/dts/stm32mp13-pinctrl.dtsi | 46 + .../core/arch/arm/dts/stm32mp131.dtsi | 375 + .../core/arch/arm/dts/stm32mp133.dtsi | 7 + .../core/arch/arm/dts/stm32mp135.dtsi | 7 + .../core/arch/arm/dts/stm32mp135f-dk.dts | 242 + .../core/arch/arm/dts/stm32mp13xc.dtsi | 16 + .../core/arch/arm/dts/stm32mp13xf.dtsi | 16 + .../core/arch/arm/dts/stm32mp15-pinctrl.dtsi | 2279 ++ .../core/arch/arm/dts/stm32mp151.dtsi | 1851 ++ .../core/arch/arm/dts/stm32mp153.dtsi | 59 + .../core/arch/arm/dts/stm32mp157.dtsi | 37 + .../arm/dts/stm32mp157a-dhcor-avenger96.dts | 38 + .../core/arch/arm/dts/stm32mp157a-dk1.dts | 42 + .../arch/arm/dts/stm32mp157c-dhcom-pdk2.dts | 29 + .../core/arch/arm/dts/stm32mp157c-dk2.dts | 111 + .../core/arch/arm/dts/stm32mp157c-ed1.dts | 417 + .../core/arch/arm/dts/stm32mp157c-ev1.dts | 393 + .../core/arch/arm/dts/stm32mp15xc.dtsi | 18 + .../arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi | 322 + .../arch/arm/dts/stm32mp15xx-dhcom-som.dtsi | 544 + .../arm/dts/stm32mp15xx-dhcor-avenger96.dtsi | 438 + .../arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi | 23 + .../arch/arm/dts/stm32mp15xx-dhcor-som.dtsi | 279 + .../core/arch/arm/dts/stm32mp15xx-dkx.dtsi | 734 + .../arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi | 85 + .../arch/arm/dts/stm32mp15xxab-pinctrl.dtsi | 57 + .../arch/arm/dts/stm32mp15xxac-pinctrl.dtsi | 73 + .../arch/arm/dts/stm32mp15xxad-pinctrl.dtsi | 57 + optee/optee_os/core/arch/arm/include/arm.h | 191 + optee/optee_os/core/arch/arm/include/arm32.h | 281 + .../core/arch/arm/include/arm32_macros.S | 26 + .../arch/arm/include/arm32_macros_cortex_a9.S | 45 + optee/optee_os/core/arch/arm/include/arm64.h | 466 + .../core/arch/arm/include/arm64_macros.S | 150 + .../arch/arm/include/crypto/ghash-ce-core.h | 43 + optee/optee_os/core/arch/arm/include/ffa.h | 235 + .../optee_os/core/arch/arm/include/hafnium.h | 45 + .../core/arch/arm/include/kernel/arch_scall.h | 56 + .../arm/include/kernel/cache_helpers_arch.h | 26 + .../core/arch/arm/include/kernel/delay_arch.h | 52 + .../core/arch/arm/include/kernel/misc_arch.h | 20 + .../arm/include/kernel/secure_partition.h | 111 + .../arch/arm/include/kernel/spmc_sp_handler.h | 42 + .../core/arch/arm/include/kernel/stmm_sp.h | 197 + .../arch/arm/include/kernel/tee_l2cc_mutex.h | 50 + .../arch/arm/include/kernel/thread_arch.h | 458 + .../arm/include/kernel/thread_private_arch.h | 243 + .../arch/arm/include/kernel/thread_spmc.h | 39 + .../arch/arm/include/kernel/tlb_helpers.h | 51 + .../arch/arm/include/kernel/tz_proc_def.h | 91 + .../arch/arm/include/kernel/tz_ssvce_def.h | 128 + .../arch/arm/include/kernel/tz_ssvce_pl310.h | 24 + .../core/arch/arm/include/kernel/vfp.h | 106 + .../core/arch/arm/include/mm/core_mmu_arch.h | 217 + .../arch/arm/include/mm/generic_ram_layout.h | 184 + .../core/arch/arm/include/optee_ffa.h | 164 + .../optee_os/core/arch/arm/include/pta_stmm.h | 25 + .../core/arch/arm/include/scmi/scmi_server.h | 73 + .../core/arch/arm/include/sm/optee_smc.h | 708 + optee/optee_os/core/arch/arm/include/sm/pm.h | 51 + .../optee_os/core/arch/arm/include/sm/psci.h | 81 + optee/optee_os/core/arch/arm/include/sm/sm.h | 145 + .../core/arch/arm/include/sm/std_smc.h | 39 + .../core/arch/arm/include/sm/teesmc_opteed.h | 120 + .../arm/include/sm/teesmc_opteed_macros.h | 13 + optee/optee_os/core/arch/arm/include/smccc.h | 36 + .../core/arch/arm/include/tee/entry_fast.h | 33 + optee/optee_os/core/arch/arm/kernel/abort.c | 581 + .../core/arch/arm/kernel/arch_scall.c | 141 + .../core/arch/arm/kernel/arch_scall_a32.S | 106 + .../core/arch/arm/kernel/arch_scall_a64.S | 198 + .../arch/arm/kernel/arm32_gicv3_sysreg.txt | 40 + .../core/arch/arm/kernel/arm32_sysreg.txt | 146 + .../core/arch/arm/kernel/asm-defines.c | 158 + optee/optee_os/core/arch/arm/kernel/boot.c | 1724 ++ .../core/arch/arm/kernel/cache_helpers_a32.S | 268 + .../core/arch/arm/kernel/cache_helpers_a64.S | 241 + .../optee_os/core/arch/arm/kernel/entry_a32.S | 925 + .../optee_os/core/arch/arm/kernel/entry_a64.S | 756 + optee/optee_os/core/arch/arm/kernel/idle.c | 13 + optee/optee_os/core/arch/arm/kernel/kern.ld.S | 499 + optee/optee_os/core/arch/arm/kernel/link.mk | 263 + .../core/arch/arm/kernel/link_dummies_init.c | 30 + .../core/arch/arm/kernel/link_dummies_paged.c | 58 + .../core/arch/arm/kernel/link_dummy.ld | 105 + .../optee_os/core/arch/arm/kernel/misc_a32.S | 108 + .../optee_os/core/arch/arm/kernel/misc_a64.S | 55 + .../core/arch/arm/kernel/rpc_io_i2c.c | 62 + .../core/arch/arm/kernel/secure_partition.c | 1648 ++ .../core/arch/arm/kernel/spin_lock_a32.S | 79 + .../core/arch/arm/kernel/spin_lock_a64.S | 92 + .../core/arch/arm/kernel/spmc_sp_handler.c | 1142 + optee/optee_os/core/arch/arm/kernel/stmm_sp.c | 1132 + optee/optee_os/core/arch/arm/kernel/sub.mk | 83 + .../core/arch/arm/kernel/tee_l2cc_mutex.c | 136 + .../arch/arm/kernel/tee_time_arm_cntpct.c | 75 + optee/optee_os/core/arch/arm/kernel/thread.c | 1175 + .../core/arch/arm/kernel/thread_a32.S | 990 + .../core/arch/arm/kernel/thread_a64.S | 1339 ++ .../core/arch/arm/kernel/thread_optee_smc.c | 715 + .../arch/arm/kernel/thread_optee_smc_a32.S | 255 + .../arch/arm/kernel/thread_optee_smc_a64.S | 261 + .../core/arch/arm/kernel/thread_spmc.c | 1526 ++ .../core/arch/arm/kernel/thread_spmc_a32.S | 136 + .../core/arch/arm/kernel/thread_spmc_a64.S | 190 + .../optee_os/core/arch/arm/kernel/timer_a64.c | 68 + .../core/arch/arm/kernel/tlb_helpers_a32.S | 37 + .../core/arch/arm/kernel/tlb_helpers_a64.S | 41 + .../core/arch/arm/kernel/tz_ssvce_pl310_a32.S | 224 + .../core/arch/arm/kernel/unwind_arm32.c | 133 + .../core/arch/arm/kernel/unwind_arm64.c | 101 + .../core/arch/arm/kernel/unwind_private.h | 23 + optee/optee_os/core/arch/arm/kernel/vfp.c | 127 + optee/optee_os/core/arch/arm/kernel/vfp_a32.S | 54 + optee/optee_os/core/arch/arm/kernel/vfp_a64.S | 50 + .../core/arch/arm/kernel/vfp_private.h | 31 + .../core/arch/arm/kernel/virtualization.c | 425 + optee/optee_os/core/arch/arm/mm/core_mmu.c | 218 + .../optee_os/core/arch/arm/mm/core_mmu_lpae.c | 1354 ++ optee/optee_os/core/arch/arm/mm/core_mmu_v7.c | 827 + .../optee_os/core/arch/arm/mm/mobj_dyn_shm.c | 468 + optee/optee_os/core/arch/arm/mm/mobj_ffa.c | 623 + optee/optee_os/core/arch/arm/mm/pgt_cache.c | 873 + optee/optee_os/core/arch/arm/mm/sp_mem.c | 337 + optee/optee_os/core/arch/arm/mm/sub.mk | 25 + optee/optee_os/core/arch/arm/mm/tee_pager.c | 2048 ++ .../core/arch/arm/plat-amlogic/conf.mk | 17 + .../core/arch/arm/plat-amlogic/link.mk | 17 + .../core/arch/arm/plat-amlogic/main.c | 20 + .../arch/arm/plat-amlogic/platform_config.h | 20 + .../arm/plat-amlogic/scripts/aml_bin2img.py | 127 + .../core/arch/arm/plat-amlogic/sub.mk | 2 + .../core/arch/arm/plat-aspeed/conf.mk | 23 + .../core/arch/arm/plat-aspeed/core_pos_a32.S | 16 + .../arch/arm/plat-aspeed/platform_ast2600.c | 109 + .../arch/arm/plat-aspeed/platform_config.h | 30 + .../optee_os/core/arch/arm/plat-aspeed/sub.mk | 2 + .../core/arch/arm/plat-bcm/bcm_elog.c | 58 + .../core/arch/arm/plat-bcm/bcm_elog.h | 35 + optee/optee_os/core/arch/arm/plat-bcm/conf.mk | 43 + optee/optee_os/core/arch/arm/plat-bcm/crc32.c | 88 + optee/optee_os/core/arch/arm/plat-bcm/crc32.h | 17 + optee/optee_os/core/arch/arm/plat-bcm/main.c | 86 + .../core/arch/arm/plat-bcm/platform_config.h | 75 + optee/optee_os/core/arch/arm/plat-bcm/sub.mk | 4 + .../core/arch/arm/plat-corstone1000/conf.mk | 44 + .../core/arch/arm/plat-corstone1000/main.c | 46 + .../arm/plat-corstone1000/platform_config.h | 39 + .../core/arch/arm/plat-corstone1000/sub.mk | 2 + optee/optee_os/core/arch/arm/plat-d02/conf.mk | 34 + optee/optee_os/core/arch/arm/plat-d02/main.c | 24 + .../core/arch/arm/plat-d02/platform_config.h | 73 + optee/optee_os/core/arch/arm/plat-d02/sub.mk | 2 + optee/optee_os/core/arch/arm/plat-d06/conf.mk | 28 + .../core/arch/arm/plat-d06/core_pos_a64.S | 48 + optee/optee_os/core/arch/arm/plat-d06/main.c | 20 + .../core/arch/arm/plat-d06/platform_config.h | 20 + optee/optee_os/core/arch/arm/plat-d06/sub.mk | 3 + .../optee_os/core/arch/arm/plat-hikey/conf.mk | 64 + .../arch/arm/plat-hikey/hikey_peripherals.h | 96 + .../optee_os/core/arch/arm/plat-hikey/main.c | 145 + .../arch/arm/plat-hikey/platform_config.h | 154 + .../core/arch/arm/plat-hikey/spi_test.c | 279 + .../optee_os/core/arch/arm/plat-hikey/sub.mk | 5 + .../core/arch/arm/plat-hisilicon/conf.mk | 61 + .../arch/arm/plat-hisilicon/hi3519av100.h | 28 + .../plat-hisilicon/hi3519av100_plat_init.S | 84 + .../core/arch/arm/plat-hisilicon/main.c | 32 + .../arch/arm/plat-hisilicon/platform_config.h | 19 + .../core/arch/arm/plat-hisilicon/psci.c | 92 + .../core/arch/arm/plat-hisilicon/sub.mk | 4 + .../core/arch/arm/plat-imx/a7_plat_init.S | 56 + .../core/arch/arm/plat-imx/a9_plat_init.S | 138 + optee/optee_os/core/arch/arm/plat-imx/conf.mk | 521 + .../arch/arm/plat-imx/config/imx6qdlsolo.h | 117 + .../core/arch/arm/plat-imx/config/imx6sl.h | 71 + .../core/arch/arm/plat-imx/config/imx6sll.h | 71 + .../core/arch/arm/plat-imx/config/imx6sx.h | 73 + .../core/arch/arm/plat-imx/imx-common.c | 195 + .../core/arch/arm/plat-imx/imx-regs.h | 89 + optee/optee_os/core/arch/arm/plat-imx/imx.h | 59 + .../core/arch/arm/plat-imx/imx_pl310.c | 125 + .../core/arch/arm/plat-imx/imx_pl310.h | 15 + .../optee_os/core/arch/arm/plat-imx/imx_pm.h | 97 + .../arch/arm/plat-imx/imx_pm_asm_defines.c | 83 + .../optee_os/core/arch/arm/plat-imx/imx_src.c | 29 + optee/optee_os/core/arch/arm/plat-imx/link.mk | 9 + optee/optee_os/core/arch/arm/plat-imx/main.c | 132 + optee/optee_os/core/arch/arm/plat-imx/mmdc.c | 45 + optee/optee_os/core/arch/arm/plat-imx/mmdc.h | 28 + .../core/arch/arm/plat-imx/platform_config.h | 59 + .../core/arch/arm/plat-imx/pm/cpuidle-imx7d.c | 228 + .../core/arch/arm/plat-imx/pm/gpcv2.c | 61 + .../core/arch/arm/plat-imx/pm/imx7_suspend.c | 71 + .../core/arch/arm/plat-imx/pm/pm-imx7.c | 239 + .../arch/arm/plat-imx/pm/psci-cpuidle-imx7.S | 765 + .../arch/arm/plat-imx/pm/psci-suspend-imx7.S | 692 + .../optee_os/core/arch/arm/plat-imx/pm/psci.c | 249 + .../optee_os/core/arch/arm/plat-imx/pm/sub.mk | 4 + .../arch/arm/plat-imx/registers/imx6-crm.h | 860 + .../arch/arm/plat-imx/registers/imx6-dcp.h | 100 + .../core/arch/arm/plat-imx/registers/imx6.h | 168 + .../arch/arm/plat-imx/registers/imx7-crm.h | 112 + .../core/arch/arm/plat-imx/registers/imx7.h | 76 + .../arch/arm/plat-imx/registers/imx7ulp-crm.h | 17 + .../arch/arm/plat-imx/registers/imx7ulp.h | 61 + .../arch/arm/plat-imx/registers/imx8m-crm.h | 40 + .../core/arch/arm/plat-imx/registers/imx8m.h | 65 + .../core/arch/arm/plat-imx/registers/imx8q.h | 21 + .../arch/arm/plat-imx/registers/imx8ulp-crm.h | 14 + .../arch/arm/plat-imx/registers/imx8ulp.h | 25 + .../core/arch/arm/plat-imx/registers/imx93.h | 15 + .../arch/arm/plat-imx/sm_platform_handler.c | 60 + optee/optee_os/core/arch/arm/plat-imx/sub.mk | 24 + .../optee_os/core/arch/arm/plat-imx/tzc380.c | 102 + optee/optee_os/core/arch/arm/plat-k3/conf.mk | 34 + .../core/arch/arm/plat-k3/drivers/sa2ul.c | 148 + .../core/arch/arm/plat-k3/drivers/sa2ul.h | 16 + .../core/arch/arm/plat-k3/drivers/sa2ul_rng.c | 148 + .../core/arch/arm/plat-k3/drivers/sec_proxy.c | 292 + .../core/arch/arm/plat-k3/drivers/sec_proxy.h | 47 + .../core/arch/arm/plat-k3/drivers/sub.mk | 4 + .../core/arch/arm/plat-k3/drivers/ti_sci.c | 451 + .../core/arch/arm/plat-k3/drivers/ti_sci.h | 171 + .../arm/plat-k3/drivers/ti_sci_protocol.h | 382 + optee/optee_os/core/arch/arm/plat-k3/main.c | 97 + .../core/arch/arm/plat-k3/platform_config.h | 102 + optee/optee_os/core/arch/arm/plat-k3/sub.mk | 3 + optee/optee_os/core/arch/arm/plat-ls/conf.mk | 126 + optee/optee_os/core/arch/arm/plat-ls/main.c | 231 + .../core/arch/arm/plat-ls/plat_init.S | 87 + .../core/arch/arm/plat-ls/platform_config.h | 124 + optee/optee_os/core/arch/arm/plat-ls/sub.mk | 3 + .../plat-marvell/armada3700/hal_sec_perf.c | 263 + .../plat-marvell/armada7k8k/hal_sec_perf.c | 295 + .../core/arch/arm/plat-marvell/conf.mk | 101 + .../core/arch/arm/plat-marvell/main.c | 126 + .../arch/arm/plat-marvell/otx2/core_pos.S | 16 + .../arch/arm/plat-marvell/platform_config.h | 142 + .../core/arch/arm/plat-marvell/sub.mk | 7 + .../core/arch/arm/plat-mediatek/conf.mk | 68 + .../core/arch/arm/plat-mediatek/main.c | 49 + .../arch/arm/plat-mediatek/platform_config.h | 102 + .../core/arch/arm/plat-mediatek/sub.mk | 2 + .../core/arch/arm/plat-poplar/conf.mk | 29 + .../core/arch/arm/plat-poplar/hi3798cv200.h | 14 + .../optee_os/core/arch/arm/plat-poplar/main.c | 28 + .../arch/arm/plat-poplar/platform_config.h | 149 + .../optee_os/core/arch/arm/plat-poplar/sub.mk | 2 + .../optee_os/core/arch/arm/plat-rcar/conf.mk | 42 + .../core/arch/arm/plat-rcar/core_pos_a64.S | 73 + .../optee_os/core/arch/arm/plat-rcar/hw_rng.c | 55 + .../optee_os/core/arch/arm/plat-rcar/link.mk | 5 + optee/optee_os/core/arch/arm/plat-rcar/main.c | 106 + .../core/arch/arm/plat-rcar/platform_config.h | 112 + optee/optee_os/core/arch/arm/plat-rcar/rcar.h | 21 + .../optee_os/core/arch/arm/plat-rcar/romapi.c | 155 + .../optee_os/core/arch/arm/plat-rcar/romapi.h | 26 + .../core/arch/arm/plat-rcar/romapi_call.S | 98 + optee/optee_os/core/arch/arm/plat-rcar/sub.mk | 6 + .../core/arch/arm/plat-rockchip/common.h | 27 + .../core/arch/arm/plat-rockchip/conf.mk | 63 + .../arch/arm/plat-rockchip/core_pos_a32.S | 18 + .../core/arch/arm/plat-rockchip/cru.h | 53 + .../core/arch/arm/plat-rockchip/grf.h | 17 + .../core/arch/arm/plat-rockchip/main.c | 53 + .../core/arch/arm/plat-rockchip/plat_init.S | 18 + .../core/arch/arm/plat-rockchip/platform.c | 46 + .../core/arch/arm/plat-rockchip/platform.h | 12 + .../arch/arm/plat-rockchip/platform_config.h | 96 + .../arch/arm/plat-rockchip/platform_px30.c | 51 + .../arch/arm/plat-rockchip/platform_rk322x.c | 37 + .../arch/arm/plat-rockchip/platform_rk3399.c | 49 + .../core/arch/arm/plat-rockchip/psci_rk322x.c | 376 + .../core/arch/arm/plat-rockchip/sub.mk | 12 + .../optee_os/core/arch/arm/plat-rpi3/conf.mk | 29 + optee/optee_os/core/arch/arm/plat-rpi3/main.c | 47 + .../core/arch/arm/plat-rpi3/platform_config.h | 71 + optee/optee_os/core/arch/arm/plat-rpi3/sub.mk | 2 + optee/optee_os/core/arch/arm/plat-rzg/conf.mk | 43 + optee/optee_os/core/arch/arm/plat-rzg/link.mk | 3 + optee/optee_os/core/arch/arm/plat-rzg/main.c | 35 + .../core/arch/arm/plat-rzg/platform_config.h | 53 + optee/optee_os/core/arch/arm/plat-rzg/sub.mk | 2 + .../core/arch/arm/plat-rzn1/a7_plat_init.S | 64 + .../optee_os/core/arch/arm/plat-rzn1/conf.mk | 28 + optee/optee_os/core/arch/arm/plat-rzn1/main.c | 112 + .../core/arch/arm/plat-rzn1/platform_config.h | 32 + optee/optee_os/core/arch/arm/plat-rzn1/psci.c | 88 + .../core/arch/arm/plat-rzn1/rzn1_regauth.h | 29 + .../core/arch/arm/plat-rzn1/rzn1_tz.h | 39 + .../arch/arm/plat-rzn1/sm_platform_handler.c | 100 + optee/optee_os/core/arch/arm/plat-rzn1/sub.mk | 5 + optee/optee_os/core/arch/arm/plat-sam/conf.mk | 93 + optee/optee_os/core/arch/arm/plat-sam/freq.c | 42 + optee/optee_os/core/arch/arm/plat-sam/main.c | 351 + .../optee_os/core/arch/arm/plat-sam/matrix.c | 730 + .../optee_os/core/arch/arm/plat-sam/matrix.h | 50 + .../nsec-service/sm_platform_handler.c | 46 + .../arch/arm/plat-sam/nsec-service/smc_ids.h | 18 + .../arch/arm/plat-sam/nsec-service/sub.mk | 3 + .../core/arch/arm/plat-sam/platform_config.h | 90 + .../optee_os/core/arch/arm/plat-sam/pm/psci.c | 93 + .../optee_os/core/arch/arm/plat-sam/pm/sub.mk | 1 + .../core/arch/arm/plat-sam/sam_pl310.c | 68 + .../optee_os/core/arch/arm/plat-sam/sam_sfr.c | 62 + .../optee_os/core/arch/arm/plat-sam/sam_sfr.h | 39 + .../optee_os/core/arch/arm/plat-sam/sama5d2.h | 274 + optee/optee_os/core/arch/arm/plat-sam/sub.mk | 6 + .../core/arch/arm/plat-sam/tz_matrix.h | 114 + .../optee_os/core/arch/arm/plat-sprd/conf.mk | 12 + .../core/arch/arm/plat-sprd/console.c | 47 + optee/optee_os/core/arch/arm/plat-sprd/main.c | 62 + .../core/arch/arm/plat-sprd/platform_config.h | 88 + optee/optee_os/core/arch/arm/plat-sprd/sub.mk | 3 + optee/optee_os/core/arch/arm/plat-stm/conf.mk | 45 + optee/optee_os/core/arch/arm/plat-stm/main.c | 151 + .../core/arch/arm/plat-stm/platform_config.h | 210 + .../core/arch/arm/plat-stm/rng_support.c | 131 + optee/optee_os/core/arch/arm/plat-stm/sub.mk | 5 + .../core/arch/arm/plat-stm/tz_a9init.S | 70 + .../core/arch/arm/plat-stm32mp1/boot_api.h | 22 + .../core/arch/arm/plat-stm32mp1/conf.mk | 351 + .../plat-stm32mp1/drivers/stm32mp1_etzpc.h | 156 + .../arm/plat-stm32mp1/drivers/stm32mp1_pmic.c | 643 + .../arm/plat-stm32mp1/drivers/stm32mp1_pmic.h | 48 + .../arm/plat-stm32mp1/drivers/stm32mp1_pwr.c | 88 + .../arm/plat-stm32mp1/drivers/stm32mp1_pwr.h | 34 + .../plat-stm32mp1/drivers/stm32mp1_syscfg.c | 101 + .../arch/arm/plat-stm32mp1/drivers/sub.mk | 3 + .../core/arch/arm/plat-stm32mp1/link.mk | 24 + .../arm/plat-stm32mp1/link_dummies_paged.c | 9 + .../core/arch/arm/plat-stm32mp1/main.c | 546 + .../arm/plat-stm32mp1/nsec-service/bsec_svc.c | 67 + .../arm/plat-stm32mp1/nsec-service/bsec_svc.h | 21 + .../plat-stm32mp1/nsec-service/stm32mp1_smc.h | 106 + .../nsec-service/stm32mp1_svc_setup.c | 72 + .../arm/plat-stm32mp1/nsec-service/sub.mk | 4 + .../core/arch/arm/plat-stm32mp1/plat_tzc400.c | 117 + .../arch/arm/plat-stm32mp1/platform_config.h | 223 + .../core/arch/arm/plat-stm32mp1/pm/psci.c | 275 + .../core/arch/arm/plat-stm32mp1/pm/sub.mk | 1 + .../core/arch/arm/plat-stm32mp1/reset.S | 27 + .../core/arch/arm/plat-stm32mp1/scmi_server.c | 967 + .../arm/plat-stm32mp1/scripts/stm32image.py | 140 + .../arch/arm/plat-stm32mp1/shared_resources.c | 690 + .../core/arch/arm/plat-stm32mp1/stm32_util.h | 329 + .../core/arch/arm/plat-stm32mp1/sub.mk | 12 + .../optee_os/core/arch/arm/plat-sunxi/conf.mk | 45 + .../optee_os/core/arch/arm/plat-sunxi/main.c | 183 + .../core/arch/arm/plat-sunxi/plat_init.S | 48 + .../arch/arm/plat-sunxi/platform_config.h | 62 + .../optee_os/core/arch/arm/plat-sunxi/psci.c | 163 + .../optee_os/core/arch/arm/plat-sunxi/sub.mk | 4 + .../core/arch/arm/plat-synquacer/conf.mk | 22 + .../core/arch/arm/plat-synquacer/main.c | 79 + .../arch/arm/plat-synquacer/platform_config.h | 33 + .../core/arch/arm/plat-synquacer/rng_pta.c | 359 + .../core/arch/arm/plat-synquacer/sub.mk | 3 + .../arm/plat-synquacer/synquacer_rng_pta.h | 11 + .../plat-tegra/README.tegra_secure_storage | 29 + .../optee_os/core/arch/arm/plat-tegra/conf.mk | 129 + .../optee_os/core/arch/arm/plat-tegra/link.mk | 13 + .../optee_os/core/arch/arm/plat-tegra/main.c | 43 + .../arch/arm/plat-tegra/platform_config.h | 12 + .../optee_os/core/arch/arm/plat-tegra/sub.mk | 11 + .../core/arch/arm/plat-tegra/tegra_common.h | 18 + .../core/arch/arm/plat-ti/a9_plat_init.S | 94 + .../arch/arm/plat-ti/api_monitor_index_a15.h | 33 + .../arch/arm/plat-ti/api_monitor_index_a9.h | 35 + optee/optee_os/core/arch/arm/plat-ti/conf.mk | 39 + optee/optee_os/core/arch/arm/plat-ti/main.c | 134 + .../core/arch/arm/plat-ti/platform_config.h | 144 + .../arm/plat-ti/sm_platform_handler_a15.c | 80 + .../arch/arm/plat-ti/sm_platform_handler_a9.c | 83 + optee/optee_os/core/arch/arm/plat-ti/sub.mk | 6 + .../optee_os/core/arch/arm/plat-ti/ti_pl310.c | 41 + .../core/arch/arm/plat-totalcompute/conf.mk | 45 + .../fdts/optee_sp_manifest.dts | 36 + .../core/arch/arm/plat-totalcompute/main.c | 59 + .../arm/plat-totalcompute/platform_config.h | 49 + .../core/arch/arm/plat-totalcompute/sub.mk | 2 + .../core/arch/arm/plat-uniphier/conf.mk | 46 + .../core/arch/arm/plat-uniphier/kern.ld.S | 2 + .../core/arch/arm/plat-uniphier/main.c | 60 + .../arch/arm/plat-uniphier/platform_config.h | 54 + .../core/arch/arm/plat-uniphier/sub.mk | 2 + .../core/arch/arm/plat-versal/conf.mk | 88 + .../optee_os/core/arch/arm/plat-versal/main.c | 127 + .../arch/arm/plat-versal/platform_config.h | 64 + .../optee_os/core/arch/arm/plat-versal/sub.mk | 2 + .../core/arch/arm/plat-vexpress/conf.mk | 152 + .../arm/plat-vexpress/juno_core_pos_a32.S | 19 + .../arm/plat-vexpress/juno_core_pos_a64.S | 17 + .../core/arch/arm/plat-vexpress/main.c | 255 + .../arch/arm/plat-vexpress/platform_config.h | 151 + .../core/arch/arm/plat-vexpress/sub.mk | 7 + .../arch/arm/plat-vexpress/vendor_props.c | 71 + .../core/arch/arm/plat-zynq7k/conf.mk | 22 + .../optee_os/core/arch/arm/plat-zynq7k/main.c | 219 + .../core/arch/arm/plat-zynq7k/plat_init.S | 104 + .../arch/arm/plat-zynq7k/platform_config.h | 251 + .../core/arch/arm/plat-zynq7k/platform_smc.h | 82 + .../optee_os/core/arch/arm/plat-zynq7k/sub.mk | 3 + .../core/arch/arm/plat-zynqmp/conf.mk | 90 + .../optee_os/core/arch/arm/plat-zynqmp/main.c | 120 + .../arch/arm/plat-zynqmp/platform_config.h | 117 + .../optee_os/core/arch/arm/plat-zynqmp/sub.mk | 2 + optee/optee_os/core/arch/arm/sm/pm.c | 50 + optee/optee_os/core/arch/arm/sm/pm_a32.S | 202 + optee/optee_os/core/arch/arm/sm/psci-helper.S | 49 + optee/optee_os/core/arch/arm/sm/psci.c | 204 + optee/optee_os/core/arch/arm/sm/sm.c | 108 + optee/optee_os/core/arch/arm/sm/sm_a32.S | 424 + optee/optee_os/core/arch/arm/sm/sm_private.h | 12 + optee/optee_os/core/arch/arm/sm/std_smc.c | 78 + optee/optee_os/core/arch/arm/sm/sub.mk | 4 + optee/optee_os/core/arch/arm/tee/cache.c | 57 + optee/optee_os/core/arch/arm/tee/entry_fast.c | 347 + optee/optee_os/core/arch/arm/tee/sub.mk | 8 + optee/optee_os/core/arch/arm/tee/svc_cache.c | 38 + .../core/arch/riscv/include/encoding.h | 4892 ++++ .../arch/riscv/include/kernel/arch_scall.h | 33 + .../riscv/include/kernel/cache_helpers_arch.h | 9 + .../core/arch/riscv/include/kernel/clint.h | 57 + .../arch/riscv/include/kernel/delay_arch.h | 25 + .../arch/riscv/include/kernel/misc_arch.h | 9 + .../riscv/include/kernel/secure_partition.h | 37 + .../core/arch/riscv/include/kernel/stmm_sp.h | 40 + .../riscv/include/kernel/tee_l2cc_mutex.h | 8 + .../arch/riscv/include/kernel/thread_arch.h | 248 + .../include/kernel/thread_private_arch.h | 85 + .../core/arch/riscv/include/kernel/time.h | 38 + .../arch/riscv/include/kernel/tlb_helpers.h | 16 + .../arch/riscv/include/mm/core_mmu_arch.h | 133 + .../riscv/include/mm/generic_ram_layout.h | 191 + .../optee_os/core/arch/riscv/include/riscv.h | 371 + .../core/arch/riscv/include/riscv_macros.S | 70 + optee/optee_os/core/arch/riscv/include/sbi.h | 46 + optee/optee_os/core/arch/riscv/include/sub.mk | 1 + optee/optee_os/core/arch/riscv/kernel/abort.c | 395 + .../core/arch/riscv/kernel/arch_scall.c | 91 + .../core/arch/riscv/kernel/arch_scall_rv.S | 63 + .../core/arch/riscv/kernel/asm-defines.c | 77 + optee/optee_os/core/arch/riscv/kernel/boot.c | 154 + .../core/arch/riscv/kernel/cache_helpers_rv.S | 62 + optee/optee_os/core/arch/riscv/kernel/entry.S | 224 + optee/optee_os/core/arch/riscv/kernel/idle.c | 15 + .../optee_os/core/arch/riscv/kernel/kern.ld.S | 275 + optee/optee_os/core/arch/riscv/kernel/link.mk | 143 + optee/optee_os/core/arch/riscv/kernel/sbi.c | 44 + .../core/arch/riscv/kernel/sbi_console.c | 65 + .../core/arch/riscv/kernel/spinlock.S | 42 + optee/optee_os/core/arch/riscv/kernel/sub.mk | 14 + .../core/arch/riscv/kernel/tee_time_rdtime.c | 29 + .../core/arch/riscv/kernel/thread_arch.c | 613 + .../core/arch/riscv/kernel/thread_rv.S | 376 + optee/optee_os/core/arch/riscv/mm/sub.mk | 1 + .../core/arch/riscv/mm/tlb_helpers_rv.S | 26 + .../core/arch/riscv/plat-spike/conf.mk | 77 + .../core/arch/riscv/plat-spike/drivers/htif.c | 77 + .../core/arch/riscv/plat-spike/drivers/htif.h | 25 + .../core/arch/riscv/plat-spike/drivers/sub.mk | 1 + .../core/arch/riscv/plat-spike/kern.ld.S | 16 + .../core/arch/riscv/plat-spike/main.c | 29 + .../arch/riscv/plat-spike/platform_config.h | 17 + .../core/arch/riscv/plat-spike/sub.mk | 3 + .../core/arch/riscv/plat-virt/conf.mk | 36 + .../optee_os/core/arch/riscv/plat-virt/main.c | 44 + .../arch/riscv/plat-virt/platform_config.h | 95 + .../optee_os/core/arch/riscv/plat-virt/sub.mk | 2 + optee/optee_os/core/arch/riscv/riscv.mk | 211 + optee/optee_os/core/arch/riscv/tee/sub.mk | 0 optee/optee_os/core/core.mk | 176 + optee/optee_os/core/crypto.mk | 304 + optee/optee_os/core/crypto/aes-cts.c | 258 + .../optee_os/core/crypto/aes-gcm-ghash-tbl.c | 145 + optee/optee_os/core/crypto/aes-gcm-sw.c | 143 + optee/optee_os/core/crypto/aes-gcm.c | 549 + optee/optee_os/core/crypto/cbc-mac.c | 248 + optee/optee_os/core/crypto/crypto.c | 930 + optee/optee_os/core/crypto/rng_fortuna.c | 531 + optee/optee_os/core/crypto/rng_hw.c | 31 + optee/optee_os/core/crypto/signed_hdr.c | 391 + optee/optee_os/core/crypto/sm2-kdf.c | 70 + optee/optee_os/core/crypto/sm3-hash.c | 113 + optee/optee_os/core/crypto/sm3-hmac.c | 113 + optee/optee_os/core/crypto/sm3.c | 309 + optee/optee_os/core/crypto/sm3.h | 38 + optee/optee_os/core/crypto/sm4-cbc.c | 107 + optee/optee_os/core/crypto/sm4-ctr.c | 104 + optee/optee_os/core/crypto/sm4-ecb.c | 102 + optee/optee_os/core/crypto/sm4-xts.c | 117 + optee/optee_os/core/crypto/sm4.c | 351 + optee/optee_os/core/crypto/sm4.h | 31 + optee/optee_os/core/crypto/sm4_accel.c | 65 + optee/optee_os/core/crypto/sub.mk | 45 + optee/optee_os/core/drivers/amlogic_uart.c | 76 + optee/optee_os/core/drivers/atmel_piobu.c | 384 + optee/optee_os/core/drivers/atmel_rstc.c | 70 + optee/optee_os/core/drivers/atmel_rtc.c | 321 + optee/optee_os/core/drivers/atmel_saic.c | 357 + optee/optee_os/core/drivers/atmel_shdwc.c | 191 + optee/optee_os/core/drivers/atmel_shdwc_a32.S | 79 + optee/optee_os/core/drivers/atmel_tcb.c | 202 + optee/optee_os/core/drivers/atmel_trng.c | 121 + optee/optee_os/core/drivers/atmel_uart.c | 104 + optee/optee_os/core/drivers/atmel_wdt.c | 284 + optee/optee_os/core/drivers/bcm_gpio.c | 209 + optee/optee_os/core/drivers/bcm_hwrng.c | 83 + optee/optee_os/core/drivers/bcm_sotp.c | 287 + optee/optee_os/core/drivers/bnxt/bnxt.c | 226 + optee/optee_os/core/drivers/bnxt/bnxt_fw.c | 697 + .../optee_os/core/drivers/bnxt/bnxt_images.c | 122 + optee/optee_os/core/drivers/bnxt/sub.mk | 3 + optee/optee_os/core/drivers/cbmem_console.c | 184 + optee/optee_os/core/drivers/cdns_uart.c | 133 + .../core/drivers/clk/clk-stm32-core.c | 605 + .../core/drivers/clk/clk-stm32-core.h | 257 + .../optee_os/core/drivers/clk/clk-stm32mp13.c | 2663 +++ .../optee_os/core/drivers/clk/clk-stm32mp15.c | 1569 ++ optee/optee_os/core/drivers/clk/clk.c | 312 + optee/optee_os/core/drivers/clk/clk_dt.c | 213 + optee/optee_os/core/drivers/clk/fixed_clk.c | 77 + .../core/drivers/clk/sam/at91_audio_pll.c | 390 + .../optee_os/core/drivers/clk/sam/at91_clk.h | 236 + .../core/drivers/clk/sam/at91_generated.c | 180 + .../core/drivers/clk/sam/at91_h32mx.c | 76 + .../core/drivers/clk/sam/at91_i2s_mux.c | 73 + .../optee_os/core/drivers/clk/sam/at91_main.c | 314 + .../core/drivers/clk/sam/at91_master.c | 181 + .../core/drivers/clk/sam/at91_peripheral.c | 190 + .../optee_os/core/drivers/clk/sam/at91_pll.c | 306 + .../core/drivers/clk/sam/at91_plldiv.c | 65 + .../optee_os/core/drivers/clk/sam/at91_pmc.c | 290 + .../optee_os/core/drivers/clk/sam/at91_pmc.h | 260 + .../core/drivers/clk/sam/at91_programmable.c | 165 + .../optee_os/core/drivers/clk/sam/at91_sckc.c | 42 + .../core/drivers/clk/sam/at91_system.c | 95 + .../optee_os/core/drivers/clk/sam/at91_usb.c | 122 + .../optee_os/core/drivers/clk/sam/at91_utmi.c | 138 + .../core/drivers/clk/sam/sama5d2_clk.c | 606 + optee/optee_os/core/drivers/clk/sam/sub.mk | 8 + optee/optee_os/core/drivers/clk/sub.mk | 8 + .../drivers/crypto/aspeed/crypto_ast2600.c | 50 + .../core/drivers/crypto/aspeed/hace_ast2600.c | 400 + .../core/drivers/crypto/aspeed/hace_ast2600.h | 18 + .../core/drivers/crypto/aspeed/sub.mk | 4 + .../drivers/crypto/caam/acipher/caam_dh.c | 493 + .../drivers/crypto/caam/acipher/caam_dsa.c | 777 + .../drivers/crypto/caam/acipher/caam_ecc.c | 719 + .../drivers/crypto/caam/acipher/caam_math.c | 125 + .../crypto/caam/acipher/caam_prime_dsa.c | 758 + .../crypto/caam/acipher/caam_prime_rsa.c | 863 + .../drivers/crypto/caam/acipher/caam_rsa.c | 1580 ++ .../core/drivers/crypto/caam/acipher/local.h | 48 + .../core/drivers/crypto/caam/acipher/sub.mk | 7 + .../core/drivers/crypto/caam/blob/caam_blob.c | 82 + .../core/drivers/crypto/caam/blob/sub.mk | 3 + .../core/drivers/crypto/caam/caam_ctrl.c | 180 + .../core/drivers/crypto/caam/caam_desc.c | 164 + .../core/drivers/crypto/caam/caam_jr.c | 684 + .../core/drivers/crypto/caam/caam_pwr.c | 183 + .../core/drivers/crypto/caam/caam_rng.c | 570 + .../drivers/crypto/caam/cipher/caam_cipher.c | 901 + .../crypto/caam/cipher/caam_cipher_mac.c | 816 + .../crypto/caam/cipher/caam_cipher_xts.c | 260 + .../core/drivers/crypto/caam/cipher/local.h | 118 + .../core/drivers/crypto/caam/cipher/sub.mk | 5 + .../core/drivers/crypto/caam/crypto.mk | 198 + .../drivers/crypto/caam/hal/common/hal_cfg.c | 99 + .../crypto/caam/hal/common/hal_cfg_dt.c | 137 + .../drivers/crypto/caam/hal/common/hal_ctrl.c | 256 + .../drivers/crypto/caam/hal/common/hal_jr.c | 246 + .../drivers/crypto/caam/hal/common/hal_rng.c | 149 + .../caam/hal/common/registers/jr_regs.h | 72 + .../caam/hal/common/registers/rng_regs.h | 119 + .../caam/hal/common/registers/version_regs.h | 80 + .../drivers/crypto/caam/hal/common/sub.mk | 9 + .../crypto/caam/hal/imx_6_7/hal_clk_mx6.c | 43 + .../crypto/caam/hal/imx_6_7/hal_clk_mx7.c | 23 + .../crypto/caam/hal/imx_6_7/hal_clk_mx7ulp.c | 21 + .../crypto/caam/hal/imx_6_7/hal_ctrl.c | 45 + .../drivers/crypto/caam/hal/imx_6_7/hal_jr.c | 93 + .../caam/hal/imx_6_7/registers/ctrl_regs.h | 56 + .../drivers/crypto/caam/hal/imx_6_7/sub.mk | 9 + .../drivers/crypto/caam/hal/imx_8m/hal_clk.c | 12 + .../drivers/crypto/caam/hal/imx_8m/hal_ctrl.c | 16 + .../drivers/crypto/caam/hal/imx_8m/hal_jr.c | 89 + .../caam/hal/imx_8m/registers/ctrl_regs.h | 41 + .../drivers/crypto/caam/hal/imx_8m/sub.mk | 7 + .../drivers/crypto/caam/hal/imx_8q/hal_cfg.c | 9 + .../drivers/crypto/caam/hal/imx_8q/hal_clk.c | 10 + .../drivers/crypto/caam/hal/imx_8q/hal_ctrl.c | 10 + .../drivers/crypto/caam/hal/imx_8q/hal_jr.c | 31 + .../drivers/crypto/caam/hal/imx_8q/hal_rng.c | 20 + .../caam/hal/imx_8q/registers/ctrl_regs.h | 39 + .../drivers/crypto/caam/hal/imx_8q/sub.mk | 9 + .../crypto/caam/hal/imx_8ulp/hal_clk.c | 21 + .../crypto/caam/hal/imx_8ulp/hal_ctrl.c | 17 + .../drivers/crypto/caam/hal/imx_8ulp/hal_jr.c | 90 + .../caam/hal/imx_8ulp/registers/ctrl_regs.h | 44 + .../drivers/crypto/caam/hal/imx_8ulp/sub.mk | 7 + .../core/drivers/crypto/caam/hal/ls/hal_clk.c | 12 + .../drivers/crypto/caam/hal/ls/hal_ctrl.c | 13 + .../core/drivers/crypto/caam/hal/ls/hal_jr.c | 35 + .../crypto/caam/hal/ls/registers/ctrl_regs.h | 41 + .../core/drivers/crypto/caam/hal/ls/sub.mk | 7 + .../core/drivers/crypto/caam/hal/sub.mk | 19 + .../core/drivers/crypto/caam/hash/caam_hash.c | 719 + .../drivers/crypto/caam/hash/caam_hash_mac.c | 349 + .../core/drivers/crypto/caam/hash/local.h | 94 + .../core/drivers/crypto/caam/hash/sub.mk | 4 + .../crypto/caam/include/caam_acipher.h | 87 + .../drivers/crypto/caam/include/caam_blob.h | 24 + .../drivers/crypto/caam/include/caam_cipher.h | 38 + .../drivers/crypto/caam/include/caam_common.h | 51 + .../caam/include/caam_desc_ccb_defines.h | 59 + .../crypto/caam/include/caam_desc_defines.h | 715 + .../crypto/caam/include/caam_desc_helper.h | 550 + .../crypto/caam/include/caam_hal_cfg.h | 76 + .../crypto/caam/include/caam_hal_clk.h | 19 + .../crypto/caam/include/caam_hal_ctrl.h | 98 + .../drivers/crypto/caam/include/caam_hal_jr.h | 139 + .../crypto/caam/include/caam_hal_rng.h | 50 + .../drivers/crypto/caam/include/caam_hash.h | 41 + .../drivers/crypto/caam/include/caam_io.h | 36 + .../drivers/crypto/caam/include/caam_jr.h | 116 + .../crypto/caam/include/caam_jr_status.h | 38 + .../drivers/crypto/caam/include/caam_mp.h | 37 + .../drivers/crypto/caam/include/caam_pwr.h | 59 + .../drivers/crypto/caam/include/caam_rng.h | 20 + .../drivers/crypto/caam/include/caam_status.h | 29 + .../drivers/crypto/caam/include/caam_trace.h | 325 + .../drivers/crypto/caam/include/caam_types.h | 42 + .../crypto/caam/include/caam_utils_delay.h | 17 + .../crypto/caam/include/caam_utils_dmaobj.h | 193 + .../crypto/caam/include/caam_utils_mem.h | 139 + .../crypto/caam/include/caam_utils_sgt.h | 149 + .../crypto/caam/include/caam_utils_status.h | 27 + .../core/drivers/crypto/caam/mp/caam_mp.c | 405 + .../core/drivers/crypto/caam/mp/sub.mk | 3 + .../optee_os/core/drivers/crypto/caam/sub.mk | 15 + .../core/drivers/crypto/caam/utils/sub.mk | 9 + .../drivers/crypto/caam/utils/utils_delay.c | 20 + .../drivers/crypto/caam/utils/utils_dmaobj.c | 1411 ++ .../drivers/crypto/caam/utils/utils_mem.c | 351 + .../drivers/crypto/caam/utils/utils_sgt.c | 165 + .../drivers/crypto/caam/utils/utils_sgt_v1.c | 60 + .../drivers/crypto/caam/utils/utils_sgt_v2.c | 64 + .../drivers/crypto/caam/utils/utils_status.c | 60 + .../drivers/crypto/crypto_api/acipher/dh.c | 97 + .../drivers/crypto/crypto_api/acipher/dsa.c | 230 + .../drivers/crypto/crypto_api/acipher/ecc.c | 596 + .../drivers/crypto/crypto_api/acipher/local.h | 34 + .../drivers/crypto/crypto_api/acipher/rsa.c | 504 + .../crypto/crypto_api/acipher/rsamgf.c | 105 + .../crypto/crypto_api/acipher/rsassa.c | 932 + .../drivers/crypto/crypto_api/acipher/sub.mk | 4 + .../crypto/crypto_api/authenc/authenc.c | 332 + .../drivers/crypto/crypto_api/authenc/sub.mk | 1 + .../drivers/crypto/crypto_api/cipher/cipher.c | 198 + .../drivers/crypto/crypto_api/cipher/sub.mk | 1 + .../core/drivers/crypto/crypto_api/drvcrypt.c | 35 + .../drivers/crypto/crypto_api/hash/hash.c | 29 + .../drivers/crypto/crypto_api/hash/sub.mk | 1 + .../crypto/crypto_api/include/drvcrypt.h | 88 + .../crypto_api/include/drvcrypt_acipher.h | 237 + .../crypto_api/include/drvcrypt_asn1_oid.h | 151 + .../crypto_api/include/drvcrypt_authenc.h | 99 + .../crypto_api/include/drvcrypt_cipher.h | 72 + .../crypto/crypto_api/include/drvcrypt_hash.h | 30 + .../crypto/crypto_api/include/drvcrypt_mac.h | 39 + .../crypto/crypto_api/include/drvcrypt_math.h | 47 + .../core/drivers/crypto/crypto_api/mac/mac.c | 34 + .../core/drivers/crypto/crypto_api/mac/sub.mk | 1 + .../drivers/crypto/crypto_api/math/modulus.c | 62 + .../drivers/crypto/crypto_api/math/sub.mk | 1 + .../drivers/crypto/crypto_api/oid/hash_oid.c | 40 + .../core/drivers/crypto/crypto_api/oid/sub.mk | 1 + .../core/drivers/crypto/crypto_api/sub.mk | 10 + .../drivers/crypto/se050/adaptors/apis/apdu.c | 733 + .../drivers/crypto/se050/adaptors/apis/sss.c | 225 + .../drivers/crypto/se050/adaptors/apis/user.c | 152 + .../crypto/se050/adaptors/include/se050.h | 50 + .../se050/adaptors/include/se050_apdu_apis.h | 84 + .../se050/adaptors/include/se050_sss_apis.h | 40 + .../se050/adaptors/include/se050_user_apis.h | 26 + .../se050/adaptors/include/se050_utils.h | 60 + .../core/drivers/crypto/se050/adaptors/sub.mk | 12 + .../crypto/se050/adaptors/utils/info.c | 240 + .../crypto/se050/adaptors/utils/scp_config.c | 474 + .../crypto/se050/adaptors/utils/utils.c | 191 + .../core/drivers/crypto/se050/core/apdu.c | 26 + .../core/drivers/crypto/se050/core/cipher.c | 84 + .../core/drivers/crypto/se050/core/ctr.c | 166 + .../core/drivers/crypto/se050/core/die_id.c | 30 + .../core/drivers/crypto/se050/core/ecc.c | 810 + .../core/include/se050_cipher_algorithms.h | 21 + .../core/drivers/crypto/se050/core/rng.c | 37 + .../core/drivers/crypto/se050/core/rsa.c | 933 + .../core/drivers/crypto/se050/core/scp03.c | 30 + .../core/drivers/crypto/se050/core/storage.c | 108 + .../core/drivers/crypto/se050/core/sub.mk | 15 + .../core/drivers/crypto/se050/crypto.mk | 104 + .../core/drivers/crypto/se050/glue/i2c.c | 66 + .../core/drivers/crypto/se050/glue/i2c_imx.c | 38 + .../drivers/crypto/se050/glue/i2c_stm32.c | 91 + .../crypto/se050/glue/include/i2c_native.h | 16 + .../core/drivers/crypto/se050/glue/user.c | 95 + .../core/drivers/crypto/se050/session.c | 129 + .../optee_os/core/drivers/crypto/se050/sub.mk | 15 + .../core/drivers/crypto/stm32/authenc.c | 375 + .../core/drivers/crypto/stm32/cipher.c | 146 + .../core/drivers/crypto/stm32/common.h | 14 + .../core/drivers/crypto/stm32/crypto.mk | 21 + .../core/drivers/crypto/stm32/stm32_cryp.c | 1318 ++ .../core/drivers/crypto/stm32/stm32_cryp.h | 78 + .../optee_os/core/drivers/crypto/stm32/sub.mk | 3 + optee/optee_os/core/drivers/crypto/sub.mk | 13 + .../core/drivers/crypto/versal/authenc.c | 870 + .../core/drivers/crypto/versal/crypto.mk | 11 + .../optee_os/core/drivers/crypto/versal/ecc.c | 469 + .../core/drivers/crypto/versal/include/ipi.h | 96 + .../optee_os/core/drivers/crypto/versal/ipi.c | 110 + .../optee_os/core/drivers/crypto/versal/rsa.c | 344 + .../core/drivers/crypto/versal/sub.mk | 6 + optee/optee_os/core/drivers/dra7_rng.c | 189 + optee/optee_os/core/drivers/gic.c | 524 + optee/optee_os/core/drivers/hfic.c | 82 + optee/optee_os/core/drivers/hi16xx_rng.c | 100 + optee/optee_os/core/drivers/hi16xx_uart.c | 141 + optee/optee_os/core/drivers/i2c/atmel_i2c.c | 367 + optee/optee_os/core/drivers/i2c/i2c.c | 32 + optee/optee_os/core/drivers/i2c/sub.mk | 2 + optee/optee_os/core/drivers/imx/dcp/dcp.c | 776 + optee/optee_os/core/drivers/imx/dcp/dcp_huk.c | 98 + .../optee_os/core/drivers/imx/dcp/dcp_utils.c | 93 + .../core/drivers/imx/dcp/include/dcp_utils.h | 80 + .../core/drivers/imx/dcp/include/local.h | 13 + optee/optee_os/core/drivers/imx/dcp/sub.mk | 5 + optee/optee_os/core/drivers/imx/mu/imx_mu.c | 152 + .../optee_os/core/drivers/imx/mu/imx_mu_8q.c | 88 + .../core/drivers/imx/mu/imx_mu_8ulp.c | 81 + .../core/drivers/imx/mu/imx_mu_platform.h | 43 + optee/optee_os/core/drivers/imx/mu/sub.mk | 5 + optee/optee_os/core/drivers/imx/sub.mk | 2 + optee/optee_os/core/drivers/imx_caam.c | 71 + optee/optee_os/core/drivers/imx_csu.c | 156 + optee/optee_os/core/drivers/imx_ele.c | 547 + optee/optee_os/core/drivers/imx_i2c.c | 571 + optee/optee_os/core/drivers/imx_lpuart.c | 131 + optee/optee_os/core/drivers/imx_ocotp.c | 288 + optee/optee_os/core/drivers/imx_rngb.c | 220 + optee/optee_os/core/drivers/imx_sc_api.c | 309 + optee/optee_os/core/drivers/imx_scu.c | 38 + optee/optee_os/core/drivers/imx_snvs.c | 192 + optee/optee_os/core/drivers/imx_uart.c | 203 + optee/optee_os/core/drivers/imx_wdog.c | 166 + optee/optee_os/core/drivers/lpc_uart.c | 108 + optee/optee_os/core/drivers/ls_dspi.c | 608 + optee/optee_os/core/drivers/ls_gpio.c | 242 + optee/optee_os/core/drivers/ls_i2c.c | 417 + optee/optee_os/core/drivers/ls_sec_mon.c | 161 + optee/optee_os/core/drivers/ls_sfp.c | 406 + optee/optee_os/core/drivers/mvebu_uart.c | 145 + optee/optee_os/core/drivers/ns16550.c | 91 + optee/optee_os/core/drivers/pl011.c | 233 + optee/optee_os/core/drivers/pl022_spi.c | 509 + optee/optee_os/core/drivers/pl061_gpio.c | 217 + optee/optee_os/core/drivers/pm/sam/at91_pm.c | 484 + optee/optee_os/core/drivers/pm/sam/at91_pm.h | 41 + .../optee_os/core/drivers/pm/sam/pm-defines.c | 18 + .../optee_os/core/drivers/pm/sam/pm_resume.S | 17 + .../optee_os/core/drivers/pm/sam/pm_suspend.S | 520 + optee/optee_os/core/drivers/pm/sam/sub.mk | 2 + optee/optee_os/core/drivers/pm/sub.mk | 1 + optee/optee_os/core/drivers/rstctrl/rstctrl.c | 50 + .../core/drivers/rstctrl/stm32_rstctrl.c | 232 + optee/optee_os/core/drivers/rstctrl/sub.mk | 2 + optee/optee_os/core/drivers/rtc/rtc.c | 21 + optee/optee_os/core/drivers/rtc/sub.mk | 1 + optee/optee_os/core/drivers/scif.c | 95 + optee/optee_os/core/drivers/scmi-msg/base.c | 193 + optee/optee_os/core/drivers/scmi-msg/base.h | 85 + optee/optee_os/core/drivers/scmi-msg/clock.c | 389 + optee/optee_os/core/drivers/scmi-msg/clock.h | 165 + optee/optee_os/core/drivers/scmi-msg/common.h | 150 + optee/optee_os/core/drivers/scmi-msg/entry.c | 143 + .../core/drivers/scmi-msg/reset_domain.c | 194 + .../core/drivers/scmi-msg/reset_domain.h | 139 + .../optee_os/core/drivers/scmi-msg/shm_msg.c | 101 + optee/optee_os/core/drivers/scmi-msg/smt.c | 168 + optee/optee_os/core/drivers/scmi-msg/sub.mk | 7 + .../core/drivers/scmi-msg/voltage_domain.c | 409 + .../core/drivers/scmi-msg/voltage_domain.h | 135 + optee/optee_os/core/drivers/serial8250_uart.c | 169 + optee/optee_os/core/drivers/smccc_trng.c | 220 + optee/optee_os/core/drivers/sp805_wdt.c | 138 + optee/optee_os/core/drivers/sprd_uart.c | 97 + optee/optee_os/core/drivers/stih_asc.c | 53 + optee/optee_os/core/drivers/stm32_bsec.c | 894 + optee/optee_os/core/drivers/stm32_etzpc.c | 344 + optee/optee_os/core/drivers/stm32_gpio.c | 439 + optee/optee_os/core/drivers/stm32_i2c.c | 1558 ++ optee/optee_os/core/drivers/stm32_iwdg.c | 412 + optee/optee_os/core/drivers/stm32_rng.c | 549 + optee/optee_os/core/drivers/stm32_shared_io.c | 39 + optee/optee_os/core/drivers/stm32_tamp.c | 314 + optee/optee_os/core/drivers/stm32_uart.c | 191 + optee/optee_os/core/drivers/stm32mp15_huk.c | 215 + optee/optee_os/core/drivers/stpmic1.c | 1022 + optee/optee_os/core/drivers/sub.mk | 91 + .../common/include/tegra_driver_common.h | 14 + .../tegra/common/include/tegra_driver_fuse.h | 21 + .../tegra/common/include/tegra_driver_rng1.h | 21 + .../tegra/common/include/tegra_driver_se.h | 32 + .../common/include/tegra_driver_srv_intf.h | 48 + .../optee_os/core/drivers/tegra/common/sub.mk | 8 + .../common/tegra_driver_clear_keyslots.c | 26 + .../tegra/common/tegra_driver_common.c | 20 + .../drivers/tegra/common/tegra_driver_fuse.c | 73 + .../drivers/tegra/common/tegra_driver_rng1.c | 80 + .../drivers/tegra/common/tegra_driver_se.c | 69 + .../tegra/common/tegra_driver_srv_intf.c | 119 + optee/optee_os/core/drivers/tegra/sub.mk | 9 + optee/optee_os/core/drivers/tegra/t194/fuse.c | 149 + .../tegra/t194/include/tegra_se_mgnt.h | 64 + optee/optee_os/core/drivers/tegra/t194/sub.mk | 8 + .../core/drivers/tegra/t194/tegra_rpmb.c | 78 + .../core/drivers/tegra/t194/tegra_se_aes.c | 596 + .../core/drivers/tegra/t194/tegra_se_mgnt.c | 238 + .../core/drivers/tegra/t194/tegra_se_rng1.c | 392 + .../drivers/tegra/t234/include/tegra_se_ccc.h | 41 + .../tegra/t234/include/tegra_se_ccc_errno.h | 63 + optee/optee_os/core/drivers/tegra/t234/sub.mk | 6 + .../core/drivers/tegra/t234/tegra_fuse.c | 147 + .../core/drivers/tegra/t234/tegra_rpmb.c | 103 + .../drivers/tegra/t234/tegra_se_aes_rng.c | 333 + .../core/drivers/tegra_combined_uart.c | 98 + optee/optee_os/core/drivers/tzc380.c | 362 + optee/optee_os/core/drivers/tzc400.c | 490 + optee/optee_os/core/drivers/versal_gpio.c | 262 + optee/optee_os/core/drivers/versal_huk.c | 335 + optee/optee_os/core/drivers/versal_mbox.c | 378 + optee/optee_os/core/drivers/versal_nvm.c | 1005 + optee/optee_os/core/drivers/versal_pm.c | 215 + optee/optee_os/core/drivers/versal_puf.c | 277 + optee/optee_os/core/drivers/versal_sha3_384.c | 102 + optee/optee_os/core/drivers/versal_trng.c | 1149 + optee/optee_os/core/drivers/wdt/sub.mk | 2 + optee/optee_os/core/drivers/wdt/watchdog.c | 18 + optee/optee_os/core/drivers/wdt/watchdog_sm.c | 81 + optee/optee_os/core/drivers/xiphera_trng.c | 187 + optee/optee_os/core/drivers/zynqmp_csu_aes.c | 415 + optee/optee_os/core/drivers/zynqmp_csu_puf.c | 74 + optee/optee_os/core/drivers/zynqmp_csudma.c | 146 + optee/optee_os/core/drivers/zynqmp_huk.c | 234 + optee/optee_os/core/drivers/zynqmp_pm.c | 198 + optee/optee_os/core/include/bench.h | 60 + optee/optee_os/core/include/console.h | 55 + optee/optee_os/core/include/crypto/crypto.h | 417 + .../core/include/crypto/crypto_accel.h | 70 + .../core/include/crypto/crypto_impl.h | 556 + .../optee_os/core/include/crypto/crypto_se.h | 49 + .../core/include/crypto/internal_aes-gcm.h | 134 + optee/optee_os/core/include/crypto/sm2-kdf.h | 13 + .../core/include/drivers/amlogic_uart.h | 16 + .../core/include/drivers/atmel_rstc.h | 24 + .../optee_os/core/include/drivers/atmel_rtc.h | 22 + .../core/include/drivers/atmel_saic.h | 48 + .../core/include/drivers/atmel_shdwc.h | 64 + .../core/include/drivers/atmel_uart.h | 41 + .../optee_os/core/include/drivers/bcm/bnxt.h | 45 + .../optee_os/core/include/drivers/bcm_gpio.h | 33 + .../optee_os/core/include/drivers/bcm_hwrng.h | 13 + .../optee_os/core/include/drivers/bcm_sotp.h | 34 + .../core/include/drivers/caam_extension.h | 45 + .../core/include/drivers/cbmem_console.h | 13 + .../optee_os/core/include/drivers/cdns_uart.h | 43 + optee/optee_os/core/include/drivers/clk.h | 197 + optee/optee_os/core/include/drivers/clk_dt.h | 112 + optee/optee_os/core/include/drivers/gic.h | 49 + optee/optee_os/core/include/drivers/hfic.h | 17 + .../core/include/drivers/hi16xx_uart.h | 26 + optee/optee_os/core/include/drivers/i2c.h | 348 + optee/optee_os/core/include/drivers/imx/dcp.h | 195 + optee/optee_os/core/include/drivers/imx_i2c.h | 17 + optee/optee_os/core/include/drivers/imx_mu.h | 68 + .../optee_os/core/include/drivers/imx_ocotp.h | 22 + .../core/include/drivers/imx_sc_api.h | 33 + .../optee_os/core/include/drivers/imx_snvs.h | 28 + .../optee_os/core/include/drivers/imx_uart.h | 42 + .../optee_os/core/include/drivers/imx_wdog.h | 66 + .../optee_os/core/include/drivers/lpc_uart.h | 53 + optee/optee_os/core/include/drivers/ls_dspi.h | 70 + optee/optee_os/core/include/drivers/ls_gpio.h | 52 + optee/optee_os/core/include/drivers/ls_i2c.h | 197 + .../core/include/drivers/ls_sec_mon.h | 79 + optee/optee_os/core/include/drivers/ls_sfp.h | 172 + .../core/include/drivers/mvebu_uart.h | 42 + optee/optee_os/core/include/drivers/ns16550.h | 65 + optee/optee_os/core/include/drivers/pl011.h | 21 + .../optee_os/core/include/drivers/pl022_spi.h | 46 + .../core/include/drivers/pl061_gpio.h | 29 + .../core/include/drivers/pm/sam/atmel_pm.h | 69 + optee/optee_os/core/include/drivers/rstctrl.h | 235 + optee/optee_os/core/include/drivers/rtc.h | 130 + .../core/include/drivers/sam/at91_ddr.h | 187 + optee/optee_os/core/include/drivers/scif.h | 44 + .../optee_os/core/include/drivers/scmi-msg.h | 391 + optee/optee_os/core/include/drivers/scmi.h | 30 + optee/optee_os/core/include/drivers/serial.h | 46 + .../core/include/drivers/serial8250_uart.h | 22 + .../optee_os/core/include/drivers/sp805_wdt.h | 69 + .../optee_os/core/include/drivers/sprd_uart.h | 43 + .../optee_os/core/include/drivers/stih_asc.h | 21 + .../core/include/drivers/stm32_bsec.h | 180 + .../core/include/drivers/stm32_etzpc.h | 88 + .../core/include/drivers/stm32_gpio.h | 184 + .../optee_os/core/include/drivers/stm32_i2c.h | 268 + .../core/include/drivers/stm32_iwdg.h | 33 + .../core/include/drivers/stm32_shared_io.h | 29 + .../core/include/drivers/stm32_tamp.h | 56 + .../core/include/drivers/stm32_uart.h | 42 + .../core/include/drivers/stm32mp13_rcc.h | 1879 ++ .../core/include/drivers/stm32mp1_rcc.h | 566 + .../include/drivers/stm32mp_dt_bindings.h | 21 + optee/optee_os/core/include/drivers/stpmic1.h | 244 + .../core/include/drivers/stpmic1_regulator.h | 57 + .../core/include/drivers/tegra/tegra_fuse.h | 27 + .../core/include/drivers/tegra/tegra_se_aes.h | 23 + .../core/include/drivers/tegra/tegra_se_kdf.h | 54 + .../include/drivers/tegra/tegra_se_keyslot.h | 73 + .../core/include/drivers/tegra/tegra_se_rng.h | 19 + .../include/drivers/tegra_combined_uart.h | 25 + optee/optee_os/core/include/drivers/tzc380.h | 231 + optee/optee_os/core/include/drivers/tzc400.h | 250 + .../core/include/drivers/versal_gpio.h | 38 + .../core/include/drivers/versal_mbox.h | 34 + .../core/include/drivers/versal_nvm.h | 273 + .../optee_os/core/include/drivers/versal_pm.h | 15 + .../core/include/drivers/versal_puf.h | 78 + .../core/include/drivers/versal_sha3_384.h | 17 + optee/optee_os/core/include/drivers/wdt.h | 120 + .../core/include/drivers/zynqmp_csu.h | 46 + .../core/include/drivers/zynqmp_csu_aes.h | 40 + .../core/include/drivers/zynqmp_csu_puf.h | 15 + .../core/include/drivers/zynqmp_csudma.h | 31 + .../core/include/drivers/zynqmp_efuse.h | 56 + .../core/include/drivers/zynqmp_huk.h | 33 + .../optee_os/core/include/drivers/zynqmp_pm.h | 66 + .../core/include/dt-bindings/clock/at91.h | 45 + .../include/dt-bindings/clock/stm32mp1-clks.h | 277 + .../dt-bindings/clock/stm32mp13-clks.h | 230 + .../dt-bindings/clock/stm32mp13-clksrc.h | 384 + .../core/include/dt-bindings/dma/at91.h | 57 + .../include/dt-bindings/gpio/atmel,piobu.h | 50 + .../core/include/dt-bindings/gpio/gpio.h | 42 + .../dt-bindings/iio/adc/at91-sama5d2_adc.h | 18 + .../interrupt-controller/arm-gic.h | 23 + .../dt-bindings/interrupt-controller/irq.h | 20 + .../include/dt-bindings/mfd/atmel-flexcom.h | 15 + .../core/include/dt-bindings/mfd/st,stpmic1.h | 50 + .../dt-bindings/pinctrl/stm32-pinfunc.h | 43 + .../regulator/active-semi,8945a-regulator.h | 30 + .../regulator/st,stm32mp13-regulator.h | 35 + .../regulator/st,stm32mp15-regulator.h | 29 + .../dt-bindings/reset/stm32mp1-resets.h | 124 + .../dt-bindings/reset/stm32mp13-resets.h | 101 + optee/optee_os/core/include/gen-asm-defines.h | 12 + optee/optee_os/core/include/gpio.h | 43 + optee/optee_os/core/include/initcall.h | 108 + optee/optee_os/core/include/io.h | 276 + optee/optee_os/core/include/keep.h | 48 + optee/optee_os/core/include/kernel/abort.h | 44 + optee/optee_os/core/include/kernel/asan.h | 60 + optee/optee_os/core/include/kernel/boot.h | 125 + .../core/include/kernel/cache_helpers.h | 45 + .../core/include/kernel/chip_services.h | 12 + optee/optee_os/core/include/kernel/delay.h | 40 + optee/optee_os/core/include/kernel/dt.h | 321 + .../optee_os/core/include/kernel/dt_driver.h | 250 + optee/optee_os/core/include/kernel/early_ta.h | 18 + .../core/include/kernel/embedded_ts.h | 36 + optee/optee_os/core/include/kernel/handle.h | 52 + .../optee_os/core/include/kernel/huk_subkey.h | 60 + .../optee_os/core/include/kernel/interrupt.h | 131 + .../core/include/kernel/ldelf_loader.h | 24 + .../core/include/kernel/ldelf_syscalls.h | 42 + optee/optee_os/core/include/kernel/linker.h | 126 + optee/optee_os/core/include/kernel/lockdep.h | 157 + optee/optee_os/core/include/kernel/misc.h | 26 + .../optee_os/core/include/kernel/msg_param.h | 84 + optee/optee_os/core/include/kernel/mutex.h | 105 + optee/optee_os/core/include/kernel/notif.h | 171 + optee/optee_os/core/include/kernel/panic.h | 42 + optee/optee_os/core/include/kernel/pm.h | 169 + .../optee_os/core/include/kernel/pseudo_ta.h | 64 + optee/optee_os/core/include/kernel/refcount.h | 69 + .../optee_os/core/include/kernel/rpc_io_i2c.h | 38 + optee/optee_os/core/include/kernel/scall.h | 40 + optee/optee_os/core/include/kernel/spinlock.h | 132 + .../optee_os/core/include/kernel/tee_common.h | 38 + .../core/include/kernel/tee_common_otp.h | 24 + optee/optee_os/core/include/kernel/tee_misc.h | 71 + .../core/include/kernel/tee_ta_manager.h | 174 + optee/optee_os/core/include/kernel/tee_time.h | 21 + optee/optee_os/core/include/kernel/thread.h | 392 + .../core/include/kernel/thread_private.h | 93 + .../core/include/kernel/time_source.h | 20 + optee/optee_os/core/include/kernel/timer.h | 15 + optee/optee_os/core/include/kernel/tpm.h | 51 + optee/optee_os/core/include/kernel/trace_ta.h | 20 + .../optee_os/core/include/kernel/ts_manager.h | 66 + optee/optee_os/core/include/kernel/ts_store.h | 84 + optee/optee_os/core/include/kernel/unwind.h | 30 + .../core/include/kernel/user_access.h | 45 + .../core/include/kernel/user_mode_ctx.h | 34 + .../include/kernel/user_mode_ctx_struct.h | 56 + optee/optee_os/core/include/kernel/user_ta.h | 73 + .../core/include/kernel/virtualization.h | 116 + .../optee_os/core/include/kernel/wait_queue.h | 64 + optee/optee_os/core/include/mm/core_memprot.h | 119 + optee/optee_os/core/include/mm/core_mmu.h | 686 + optee/optee_os/core/include/mm/file.h | 109 + optee/optee_os/core/include/mm/fobj.h | 206 + optee/optee_os/core/include/mm/mobj.h | 325 + optee/optee_os/core/include/mm/pgt_cache.h | 139 + optee/optee_os/core/include/mm/sp_mem.h | 84 + optee/optee_os/core/include/mm/tee_mm.h | 119 + .../optee_os/core/include/mm/tee_mmu_types.h | 155 + optee/optee_os/core/include/mm/tee_pager.h | 285 + optee/optee_os/core/include/mm/vm.h | 108 + optee/optee_os/core/include/optee_msg.h | 345 + optee/optee_os/core/include/optee_rpc_cmd.h | 400 + optee/optee_os/core/include/rng_support.h | 12 + optee/optee_os/core/include/scattered_array.h | 129 + optee/optee_os/core/include/signed_hdr.h | 228 + optee/optee_os/core/include/spi.h | 41 + optee/optee_os/core/include/ta_pub_key.h | 15 + optee/optee_os/core/include/tee/cache.h | 12 + optee/optee_os/core/include/tee/entry_std.h | 26 + optee/optee_os/core/include/tee/fs_dirfile.h | 154 + optee/optee_os/core/include/tee/fs_htree.h | 174 + optee/optee_os/core/include/tee/svc_cache.h | 17 + optee/optee_os/core/include/tee/tadb.h | 66 + .../core/include/tee/tee_cryp_concat_kdf.h | 17 + .../optee_os/core/include/tee/tee_cryp_hkdf.h | 16 + .../core/include/tee/tee_cryp_pbkdf2.h | 16 + .../optee_os/core/include/tee/tee_cryp_utl.h | 34 + optee/optee_os/core/include/tee/tee_fs.h | 121 + .../core/include/tee/tee_fs_key_manager.h | 30 + optee/optee_os/core/include/tee/tee_fs_rpc.h | 49 + optee/optee_os/core/include/tee/tee_obj.h | 41 + optee/optee_os/core/include/tee/tee_pobj.h | 46 + .../core/include/tee/tee_supp_plugin_rpc.h | 17 + optee/optee_os/core/include/tee/tee_svc.h | 77 + .../optee_os/core/include/tee/tee_svc_cryp.h | 96 + .../core/include/tee/tee_svc_storage.h | 64 + .../core/include/tee/tee_ta_enc_manager.h | 22 + optee/optee_os/core/include/tee/uuid.h | 35 + optee/optee_os/core/kernel/asan.c | 284 + optee/optee_os/core/kernel/assert.c | 29 + optee/optee_os/core/kernel/console.c | 168 + optee/optee_os/core/kernel/delay.c | 62 + optee/optee_os/core/kernel/dt.c | 439 + optee/optee_os/core/kernel/dt_driver.c | 805 + optee/optee_os/core/kernel/dt_driver_test.c | 524 + optee/optee_os/core/kernel/early_ta.c | 63 + optee/optee_os/core/kernel/embedded_ts.c | 216 + optee/optee_os/core/kernel/handle.c | 100 + optee/optee_os/core/kernel/huk_subkey.c | 107 + optee/optee_os/core/kernel/initcall.c | 66 + optee/optee_os/core/kernel/interrupt.c | 140 + optee/optee_os/core/kernel/ldelf_loader.c | 456 + optee/optee_os/core/kernel/ldelf_syscalls.c | 549 + optee/optee_os/core/kernel/lockdep.c | 513 + optee/optee_os/core/kernel/msg_param.c | 149 + optee/optee_os/core/kernel/mutex.c | 456 + optee/optee_os/core/kernel/mutex_lockdep.c | 73 + optee/optee_os/core/kernel/mutex_lockdep.h | 37 + optee/optee_os/core/kernel/notif.c | 221 + optee/optee_os/core/kernel/otp_stubs.c | 61 + optee/optee_os/core/kernel/panic.c | 39 + optee/optee_os/core/kernel/pm.c | 145 + optee/optee_os/core/kernel/pseudo_ta.c | 329 + optee/optee_os/core/kernel/ree_fs_ta.c | 807 + optee/optee_os/core/kernel/refcount.c | 52 + optee/optee_os/core/kernel/scall.c | 297 + optee/optee_os/core/kernel/scattered_array.c | 11 + optee/optee_os/core/kernel/secstor_ta.c | 87 + optee/optee_os/core/kernel/show_conf.c | 19 + optee/optee_os/core/kernel/spin_lock_debug.c | 42 + optee/optee_os/core/kernel/sub.mk | 60 + optee/optee_os/core/kernel/tee_misc.c | 141 + optee/optee_os/core/kernel/tee_ta_manager.c | 1178 + optee/optee_os/core/kernel/tee_time.c | 66 + optee/optee_os/core/kernel/tee_time_ree.c | 40 + optee/optee_os/core/kernel/thread.c | 673 + optee/optee_os/core/kernel/tpm.c | 150 + optee/optee_os/core/kernel/trace_ext.c | 63 + optee/optee_os/core/kernel/ts_manager.c | 75 + optee/optee_os/core/kernel/ubsan.c | 221 + optee/optee_os/core/kernel/user_access.c | 111 + optee/optee_os/core/kernel/user_mode_ctx.c | 29 + optee/optee_os/core/kernel/user_ta.c | 500 + optee/optee_os/core/kernel/wait_queue.c | 212 + optee/optee_os/core/lib/libfdt/README.license | 56 + optee/optee_os/core/lib/libfdt/fdt.c | 291 + .../optee_os/core/lib/libfdt/fdt_addresses.c | 101 + .../optee_os/core/lib/libfdt/fdt_empty_tree.c | 38 + optee/optee_os/core/lib/libfdt/fdt_overlay.c | 881 + optee/optee_os/core/lib/libfdt/fdt_ro.c | 898 + optee/optee_os/core/lib/libfdt/fdt_rw.c | 476 + optee/optee_os/core/lib/libfdt/fdt_strerror.c | 59 + optee/optee_os/core/lib/libfdt/fdt_sw.c | 376 + optee/optee_os/core/lib/libfdt/fdt_wip.c | 94 + optee/optee_os/core/lib/libfdt/include/fdt.h | 66 + .../optee_os/core/lib/libfdt/include/libfdt.h | 2071 ++ .../core/lib/libfdt/include/libfdt_env.h | 96 + .../core/lib/libfdt/libfdt_internal.h | 51 + optee/optee_os/core/lib/libfdt/sub.mk | 6 + .../core/lib/libtomcrypt/acipher_helpers.h | 105 + optee/optee_os/core/lib/libtomcrypt/aes.c | 49 + .../optee_os/core/lib/libtomcrypt/aes_accel.c | 244 + optee/optee_os/core/lib/libtomcrypt/cbc.c | 140 + optee/optee_os/core/lib/libtomcrypt/ccm.c | 231 + optee/optee_os/core/lib/libtomcrypt/cmac.c | 117 + optee/optee_os/core/lib/libtomcrypt/ctr.c | 113 + .../optee_os/core/lib/libtomcrypt/des2_key.h | 22 + optee/optee_os/core/lib/libtomcrypt/dh.c | 81 + optee/optee_os/core/lib/libtomcrypt/dsa.c | 199 + optee/optee_os/core/lib/libtomcrypt/ecb.c | 138 + optee/optee_os/core/lib/libtomcrypt/ecc.c | 542 + optee/optee_os/core/lib/libtomcrypt/ed25519.c | 200 + optee/optee_os/core/lib/libtomcrypt/gcm.c | 219 + optee/optee_os/core/lib/libtomcrypt/hash.c | 233 + optee/optee_os/core/lib/libtomcrypt/hmac.c | 172 + .../lib/libtomcrypt/include/tomcrypt_init.h | 11 + .../lib/libtomcrypt/include/tomcrypt_mp.h | 15 + .../optee_os/core/lib/libtomcrypt/mpi_desc.c | 779 + optee/optee_os/core/lib/libtomcrypt/rsa.c | 682 + .../core/lib/libtomcrypt/sha1_accel.c | 202 + .../core/lib/libtomcrypt/sha256_accel.c | 213 + .../core/lib/libtomcrypt/sha3_accel.c | 245 + .../core/lib/libtomcrypt/sha512_accel.c | 184 + optee/optee_os/core/lib/libtomcrypt/shake.c | 123 + optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c | 249 + optee/optee_os/core/lib/libtomcrypt/sm2-kep.c | 443 + optee/optee_os/core/lib/libtomcrypt/sm2-pke.c | 515 + .../lib/libtomcrypt/src/ciphers/aes/aes.c | 744 + .../lib/libtomcrypt/src/ciphers/aes/aes_tab.c | 1022 + .../lib/libtomcrypt/src/ciphers/aes/sub.mk | 5 + .../core/lib/libtomcrypt/src/ciphers/anubis.c | 1550 ++ .../lib/libtomcrypt/src/ciphers/blowfish.c | 658 + .../lib/libtomcrypt/src/ciphers/camellia.c | 720 + .../core/lib/libtomcrypt/src/ciphers/cast5.c | 705 + .../core/lib/libtomcrypt/src/ciphers/des.c | 2093 ++ .../core/lib/libtomcrypt/src/ciphers/idea.c | 250 + .../core/lib/libtomcrypt/src/ciphers/kasumi.c | 307 + .../core/lib/libtomcrypt/src/ciphers/khazad.c | 840 + .../core/lib/libtomcrypt/src/ciphers/kseed.c | 366 + .../core/lib/libtomcrypt/src/ciphers/multi2.c | 309 + .../lib/libtomcrypt/src/ciphers/noekeon.c | 317 + .../core/lib/libtomcrypt/src/ciphers/rc2.c | 408 + .../core/lib/libtomcrypt/src/ciphers/rc5.c | 323 + .../core/lib/libtomcrypt/src/ciphers/rc6.c | 324 + .../lib/libtomcrypt/src/ciphers/safer/safer.c | 484 + .../libtomcrypt/src/ciphers/safer/safer_tab.c | 54 + .../libtomcrypt/src/ciphers/safer/saferp.c | 567 + .../lib/libtomcrypt/src/ciphers/serpent.c | 717 + .../lib/libtomcrypt/src/ciphers/skipjack.c | 334 + .../core/lib/libtomcrypt/src/ciphers/sub.mk | 2 + .../core/lib/libtomcrypt/src/ciphers/tea.c | 209 + .../libtomcrypt/src/ciphers/twofish/twofish.c | 706 + .../src/ciphers/twofish/twofish_tab.c | 486 + .../core/lib/libtomcrypt/src/ciphers/xtea.c | 251 + .../libtomcrypt/src/encauth/ccm/ccm_add_aad.c | 53 + .../src/encauth/ccm/ccm_add_nonce.c | 106 + .../libtomcrypt/src/encauth/ccm/ccm_done.c | 55 + .../libtomcrypt/src/encauth/ccm/ccm_init.c | 64 + .../libtomcrypt/src/encauth/ccm/ccm_memory.c | 372 + .../libtomcrypt/src/encauth/ccm/ccm_process.c | 78 + .../libtomcrypt/src/encauth/ccm/ccm_reset.c | 25 + .../libtomcrypt/src/encauth/ccm/ccm_test.c | 274 + .../lib/libtomcrypt/src/encauth/ccm/sub.mk | 6 + .../chachapoly/chacha20poly1305_add_aad.c | 28 + .../chachapoly/chacha20poly1305_decrypt.c | 38 + .../chachapoly/chacha20poly1305_done.c | 36 + .../chachapoly/chacha20poly1305_encrypt.c | 37 + .../chachapoly/chacha20poly1305_init.c | 20 + .../chachapoly/chacha20poly1305_memory.c | 72 + .../chachapoly/chacha20poly1305_setiv.c | 58 + .../chacha20poly1305_setiv_rfc7905.c | 30 + .../chachapoly/chacha20poly1305_test.c | 159 + .../src/encauth/eax/eax_addheader.c | 26 + .../libtomcrypt/src/encauth/eax/eax_decrypt.c | 38 + .../encauth/eax/eax_decrypt_verify_memory.c | 99 + .../libtomcrypt/src/encauth/eax/eax_done.c | 82 + .../libtomcrypt/src/encauth/eax/eax_encrypt.c | 39 + .../eax/eax_encrypt_authenticate_memory.c | 70 + .../libtomcrypt/src/encauth/eax/eax_init.c | 132 + .../libtomcrypt/src/encauth/eax/eax_test.c | 249 + .../libtomcrypt/src/encauth/gcm/gcm_add_aad.c | 114 + .../libtomcrypt/src/encauth/gcm/gcm_add_iv.c | 82 + .../libtomcrypt/src/encauth/gcm/gcm_done.c | 80 + .../libtomcrypt/src/encauth/gcm/gcm_gf_mult.c | 209 + .../libtomcrypt/src/encauth/gcm/gcm_init.c | 95 + .../libtomcrypt/src/encauth/gcm/gcm_memory.c | 113 + .../libtomcrypt/src/encauth/gcm/gcm_mult_h.c | 47 + .../src/encauth/gcm/gcm_mult_h_arm_ce.c | 48 + .../libtomcrypt/src/encauth/gcm/gcm_process.c | 150 + .../libtomcrypt/src/encauth/gcm/gcm_reset.c | 32 + .../libtomcrypt/src/encauth/gcm/gcm_test.c | 407 + .../lib/libtomcrypt/src/encauth/gcm/sub.mk | 13 + .../libtomcrypt/src/encauth/ocb/ocb_decrypt.c | 67 + .../encauth/ocb/ocb_decrypt_verify_memory.c | 74 + .../src/encauth/ocb/ocb_done_decrypt.c | 68 + .../src/encauth/ocb/ocb_done_encrypt.c | 34 + .../libtomcrypt/src/encauth/ocb/ocb_encrypt.c | 60 + .../ocb/ocb_encrypt_authenticate_memory.c | 72 + .../libtomcrypt/src/encauth/ocb/ocb_init.c | 129 + .../lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c | 30 + .../src/encauth/ocb/ocb_shift_xor.c | 27 + .../libtomcrypt/src/encauth/ocb/ocb_test.c | 205 + .../libtomcrypt/src/encauth/ocb/s_ocb_done.c | 136 + .../src/encauth/ocb3/ocb3_add_aad.c | 96 + .../src/encauth/ocb3/ocb3_decrypt.c | 76 + .../src/encauth/ocb3/ocb3_decrypt_last.c | 101 + .../encauth/ocb3/ocb3_decrypt_verify_memory.c | 100 + .../libtomcrypt/src/encauth/ocb3/ocb3_done.c | 82 + .../src/encauth/ocb3/ocb3_encrypt.c | 76 + .../ocb3/ocb3_encrypt_authenticate_memory.c | 72 + .../src/encauth/ocb3/ocb3_encrypt_last.c | 102 + .../libtomcrypt/src/encauth/ocb3/ocb3_init.c | 186 + .../src/encauth/ocb3/ocb3_int_ntz.c | 29 + .../src/encauth/ocb3/ocb3_int_xor_blocks.c | 30 + .../libtomcrypt/src/encauth/ocb3/ocb3_test.c | 299 + .../core/lib/libtomcrypt/src/encauth/sub.mk | 2 + .../core/lib/libtomcrypt/src/hashes/blake2b.c | 628 + .../core/lib/libtomcrypt/src/hashes/blake2s.c | 603 + .../core/lib/libtomcrypt/src/hashes/chc/chc.c | 302 + .../libtomcrypt/src/hashes/helper/hash_file.c | 43 + .../src/hashes/helper/hash_filehandle.c | 64 + .../src/hashes/helper/hash_memory.c | 59 + .../src/hashes/helper/hash_memory_multi.c | 78 + .../lib/libtomcrypt/src/hashes/helper/sub.mk | 4 + .../core/lib/libtomcrypt/src/hashes/md2.c | 240 + .../core/lib/libtomcrypt/src/hashes/md4.c | 296 + .../core/lib/libtomcrypt/src/hashes/md5.c | 356 + .../core/lib/libtomcrypt/src/hashes/rmd128.c | 396 + .../core/lib/libtomcrypt/src/hashes/rmd160.c | 455 + .../core/lib/libtomcrypt/src/hashes/rmd256.c | 420 + .../core/lib/libtomcrypt/src/hashes/rmd320.c | 485 + .../core/lib/libtomcrypt/src/hashes/sha1.c | 276 + .../lib/libtomcrypt/src/hashes/sha2/sha224.c | 119 + .../lib/libtomcrypt/src/hashes/sha2/sha256.c | 322 + .../lib/libtomcrypt/src/hashes/sha2/sha384.c | 124 + .../lib/libtomcrypt/src/hashes/sha2/sha512.c | 303 + .../libtomcrypt/src/hashes/sha2/sha512_224.c | 120 + .../libtomcrypt/src/hashes/sha2/sha512_256.c | 120 + .../lib/libtomcrypt/src/hashes/sha2/sub.mk | 13 + .../core/lib/libtomcrypt/src/hashes/sha3.c | 378 + .../lib/libtomcrypt/src/hashes/sha3_test.c | 719 + .../core/lib/libtomcrypt/src/hashes/sub.mk | 14 + .../core/lib/libtomcrypt/src/hashes/tiger.c | 796 + .../lib/libtomcrypt/src/hashes/whirl/whirl.c | 296 + .../libtomcrypt/src/hashes/whirl/whirltab.c | 586 + .../lib/libtomcrypt/src/headers/tomcrypt.h | 95 + .../libtomcrypt/src/headers/tomcrypt_argchk.h | 38 + .../src/headers/tomcrypt_arm_neon.h | 19 + .../libtomcrypt/src/headers/tomcrypt_cfg.h | 323 + .../libtomcrypt/src/headers/tomcrypt_cipher.h | 1160 + .../libtomcrypt/src/headers/tomcrypt_custom.h | 751 + .../libtomcrypt/src/headers/tomcrypt_hash.h | 503 + .../libtomcrypt/src/headers/tomcrypt_mac.h | 567 + .../libtomcrypt/src/headers/tomcrypt_macros.h | 454 + .../libtomcrypt/src/headers/tomcrypt_math.h | 527 + .../libtomcrypt/src/headers/tomcrypt_misc.h | 179 + .../lib/libtomcrypt/src/headers/tomcrypt_pk.h | 803 + .../libtomcrypt/src/headers/tomcrypt_pkcs.h | 99 + .../src/headers/tomcrypt_private.h | 500 + .../libtomcrypt/src/headers/tomcrypt_prng.h | 223 + .../libtomcrypt/src/mac/blake2/blake2bmac.c | 56 + .../src/mac/blake2/blake2bmac_file.c | 78 + .../src/mac/blake2/blake2bmac_memory.c | 38 + .../src/mac/blake2/blake2bmac_memory_multi.c | 52 + .../src/mac/blake2/blake2bmac_test.c | 304 + .../libtomcrypt/src/mac/blake2/blake2smac.c | 56 + .../src/mac/blake2/blake2smac_file.c | 78 + .../src/mac/blake2/blake2smac_memory.c | 38 + .../src/mac/blake2/blake2smac_memory_multi.c | 52 + .../src/mac/blake2/blake2smac_test.c | 304 + .../core/lib/libtomcrypt/src/mac/f9/f9_done.c | 65 + .../core/lib/libtomcrypt/src/mac/f9/f9_file.c | 87 + .../core/lib/libtomcrypt/src/mac/f9/f9_init.c | 58 + .../lib/libtomcrypt/src/mac/f9/f9_memory.c | 59 + .../libtomcrypt/src/mac/f9/f9_memory_multi.c | 78 + .../lib/libtomcrypt/src/mac/f9/f9_process.c | 66 + .../core/lib/libtomcrypt/src/mac/f9/f9_test.c | 66 + .../lib/libtomcrypt/src/mac/hmac/hmac_done.c | 96 + .../lib/libtomcrypt/src/mac/hmac/hmac_file.c | 90 + .../lib/libtomcrypt/src/mac/hmac/hmac_init.c | 94 + .../libtomcrypt/src/mac/hmac/hmac_memory.c | 76 + .../src/mac/hmac/hmac_memory_multi.c | 80 + .../libtomcrypt/src/mac/hmac/hmac_process.c | 31 + .../lib/libtomcrypt/src/mac/hmac/hmac_test.c | 618 + .../core/lib/libtomcrypt/src/mac/hmac/sub.mk | 7 + .../lib/libtomcrypt/src/mac/omac/omac_done.c | 74 + .../lib/libtomcrypt/src/mac/omac/omac_file.c | 87 + .../lib/libtomcrypt/src/mac/omac/omac_init.c | 89 + .../libtomcrypt/src/mac/omac/omac_memory.c | 73 + .../src/mac/omac/omac_memory_multi.c | 78 + .../libtomcrypt/src/mac/omac/omac_process.c | 80 + .../lib/libtomcrypt/src/mac/omac/omac_test.c | 93 + .../core/lib/libtomcrypt/src/mac/omac/sub.mk | 7 + .../lib/libtomcrypt/src/mac/pelican/pelican.c | 154 + .../src/mac/pelican/pelican_memory.c | 47 + .../src/mac/pelican/pelican_test.c | 103 + .../lib/libtomcrypt/src/mac/pmac/pmac_done.c | 62 + .../lib/libtomcrypt/src/mac/pmac/pmac_file.c | 88 + .../lib/libtomcrypt/src/mac/pmac/pmac_init.c | 138 + .../libtomcrypt/src/mac/pmac/pmac_memory.c | 62 + .../src/mac/pmac/pmac_memory_multi.c | 77 + .../lib/libtomcrypt/src/mac/pmac/pmac_ntz.c | 27 + .../libtomcrypt/src/mac/pmac/pmac_process.c | 88 + .../libtomcrypt/src/mac/pmac/pmac_shift_xor.c | 32 + .../lib/libtomcrypt/src/mac/pmac/pmac_test.c | 144 + .../libtomcrypt/src/mac/poly1305/poly1305.c | 258 + .../src/mac/poly1305/poly1305_file.c | 83 + .../src/mac/poly1305/poly1305_memory.c | 43 + .../src/mac/poly1305/poly1305_memory_multi.c | 57 + .../src/mac/poly1305/poly1305_test.c | 46 + .../core/lib/libtomcrypt/src/mac/sub.mk | 2 + .../lib/libtomcrypt/src/mac/xcbc/xcbc_done.c | 65 + .../lib/libtomcrypt/src/mac/xcbc/xcbc_file.c | 87 + .../lib/libtomcrypt/src/mac/xcbc/xcbc_init.c | 96 + .../libtomcrypt/src/mac/xcbc/xcbc_memory.c | 59 + .../src/mac/xcbc/xcbc_memory_multi.c | 78 + .../libtomcrypt/src/mac/xcbc/xcbc_process.c | 63 + .../lib/libtomcrypt/src/mac/xcbc/xcbc_test.c | 116 + .../src/math/fp/ltc_ecc_fp_mulmod.c | 1580 ++ .../core/lib/libtomcrypt/src/math/fp/sub.mk | 1 + .../core/lib/libtomcrypt/src/math/gmp_desc.c | 658 + .../core/lib/libtomcrypt/src/math/ltm_desc.c | 560 + .../core/lib/libtomcrypt/src/math/multi.c | 94 + .../lib/libtomcrypt/src/math/radix_to_bin.c | 52 + .../core/lib/libtomcrypt/src/math/rand_bn.c | 65 + .../lib/libtomcrypt/src/math/rand_prime.c | 78 + .../core/lib/libtomcrypt/src/math/sub.mk | 4 + .../core/lib/libtomcrypt/src/math/tfm_desc.c | 857 + .../core/lib/libtomcrypt/src/misc/adler32.c | 123 + .../src/misc/base16/base16_decode.c | 65 + .../src/misc/base16/base16_encode.c | 64 + .../src/misc/base32/base32_decode.c | 111 + .../src/misc/base32/base32_encode.c | 86 + .../src/misc/base64/base64_decode.c | 229 + .../src/misc/base64/base64_encode.c | 159 + .../lib/libtomcrypt/src/misc/base64/sub.mk | 2 + .../lib/libtomcrypt/src/misc/bcrypt/bcrypt.c | 191 + .../lib/libtomcrypt/src/misc/burn_stack.c | 23 + .../libtomcrypt/src/misc/compare_testvector.c | 81 + .../libtomcrypt/src/misc/copy_or_zeromem.c | 51 + .../core/lib/libtomcrypt/src/misc/crc32.c | 193 + .../lib/libtomcrypt/src/misc/crypt/crypt.c | 552 + .../libtomcrypt/src/misc/crypt/crypt_argchk.c | 17 + .../src/misc/crypt/crypt_cipher_descriptor.c | 13 + .../src/misc/crypt/crypt_cipher_is_valid.c | 24 + .../src/misc/crypt/crypt_constants.c | 290 + .../src/misc/crypt/crypt_find_cipher.c | 29 + .../src/misc/crypt/crypt_find_cipher_any.c | 38 + .../src/misc/crypt/crypt_find_cipher_id.c | 27 + .../src/misc/crypt/crypt_find_hash.c | 28 + .../src/misc/crypt/crypt_find_hash_any.c | 37 + .../src/misc/crypt/crypt_find_hash_id.c | 27 + .../src/misc/crypt/crypt_find_hash_oid.c | 23 + .../src/misc/crypt/crypt_find_prng.c | 29 + .../libtomcrypt/src/misc/crypt/crypt_fsa.c | 46 + .../src/misc/crypt/crypt_hash_descriptor.c | 13 + .../src/misc/crypt/crypt_hash_is_valid.c | 24 + .../libtomcrypt/src/misc/crypt/crypt_inits.c | 81 + .../src/misc/crypt/crypt_ltc_mp_descriptor.c | 6 + .../src/misc/crypt/crypt_prng_descriptor.c | 12 + .../src/misc/crypt/crypt_prng_is_valid.c | 24 + .../misc/crypt/crypt_prng_rng_descriptor.c | 7 + .../misc/crypt/crypt_register_all_ciphers.c | 99 + .../misc/crypt/crypt_register_all_hashes.c | 95 + .../src/misc/crypt/crypt_register_all_prngs.c | 38 + .../src/misc/crypt/crypt_register_cipher.c | 42 + .../src/misc/crypt/crypt_register_hash.c | 42 + .../src/misc/crypt/crypt_register_prng.c | 42 + .../libtomcrypt/src/misc/crypt/crypt_sizes.c | 351 + .../src/misc/crypt/crypt_unregister_cipher.c | 32 + .../src/misc/crypt/crypt_unregister_hash.c | 32 + .../src/misc/crypt/crypt_unregister_prng.c | 32 + .../lib/libtomcrypt/src/misc/crypt/sub.mk | 22 + .../libtomcrypt/src/misc/error_to_string.c | 68 + .../core/lib/libtomcrypt/src/misc/hkdf/hkdf.c | 135 + .../lib/libtomcrypt/src/misc/hkdf/hkdf_test.c | 284 + .../core/lib/libtomcrypt/src/misc/mem_neq.c | 53 + .../src/misc/padding/padding_depad.c | 90 + .../src/misc/padding/padding_pad.c | 151 + .../core/lib/libtomcrypt/src/misc/pbes/pbes.c | 73 + .../lib/libtomcrypt/src/misc/pbes/pbes1.c | 117 + .../lib/libtomcrypt/src/misc/pbes/pbes2.c | 198 + .../core/lib/libtomcrypt/src/misc/pbes/sub.mk | 3 + .../libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c | 82 + .../src/misc/pkcs12/pkcs12_utf8_to_utf16.c | 60 + .../lib/libtomcrypt/src/misc/pkcs12/sub.mk | 2 + .../lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c | 185 + .../lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c | 121 + .../libtomcrypt/src/misc/pkcs5/pkcs_5_test.c | 221 + .../lib/libtomcrypt/src/misc/pkcs5/sub.mk | 2 + .../src/misc/ssh/ssh_decode_sequence_multi.c | 167 + .../src/misc/ssh/ssh_encode_sequence_multi.c | 160 + .../core/lib/libtomcrypt/src/misc/ssh/sub.mk | 2 + .../core/lib/libtomcrypt/src/misc/sub.mk | 9 + .../core/lib/libtomcrypt/src/misc/zeromem.c | 20 + .../libtomcrypt/src/modes/cbc/cbc_decrypt.c | 84 + .../lib/libtomcrypt/src/modes/cbc/cbc_done.c | 30 + .../libtomcrypt/src/modes/cbc/cbc_encrypt.c | 85 + .../lib/libtomcrypt/src/modes/cbc/cbc_getiv.c | 34 + .../lib/libtomcrypt/src/modes/cbc/cbc_setiv.c | 32 + .../lib/libtomcrypt/src/modes/cbc/cbc_start.c | 50 + .../core/lib/libtomcrypt/src/modes/cbc/sub.mk | 6 + .../libtomcrypt/src/modes/cfb/cfb_decrypt.c | 55 + .../lib/libtomcrypt/src/modes/cfb/cfb_done.c | 30 + .../libtomcrypt/src/modes/cfb/cfb_encrypt.c | 53 + .../lib/libtomcrypt/src/modes/cfb/cfb_getiv.c | 34 + .../lib/libtomcrypt/src/modes/cfb/cfb_setiv.c | 40 + .../lib/libtomcrypt/src/modes/cfb/cfb_start.c | 54 + .../core/lib/libtomcrypt/src/modes/cfb/sub.mk | 6 + .../libtomcrypt/src/modes/ctr/ctr_decrypt.c | 30 + .../lib/libtomcrypt/src/modes/ctr/ctr_done.c | 30 + .../libtomcrypt/src/modes/ctr/ctr_encrypt.c | 140 + .../lib/libtomcrypt/src/modes/ctr/ctr_getiv.c | 34 + .../lib/libtomcrypt/src/modes/ctr/ctr_setiv.c | 44 + .../lib/libtomcrypt/src/modes/ctr/ctr_start.c | 89 + .../lib/libtomcrypt/src/modes/ctr/ctr_test.c | 73 + .../core/lib/libtomcrypt/src/modes/ctr/sub.mk | 6 + .../libtomcrypt/src/modes/ecb/ecb_decrypt.c | 48 + .../lib/libtomcrypt/src/modes/ecb/ecb_done.c | 30 + .../libtomcrypt/src/modes/ecb/ecb_encrypt.c | 48 + .../lib/libtomcrypt/src/modes/ecb/ecb_start.c | 36 + .../core/lib/libtomcrypt/src/modes/ecb/sub.mk | 4 + .../lib/libtomcrypt/src/modes/f8/f8_decrypt.c | 31 + .../lib/libtomcrypt/src/modes/f8/f8_done.c | 30 + .../lib/libtomcrypt/src/modes/f8/f8_encrypt.c | 91 + .../lib/libtomcrypt/src/modes/f8/f8_getiv.c | 34 + .../lib/libtomcrypt/src/modes/f8/f8_setiv.c | 40 + .../lib/libtomcrypt/src/modes/f8/f8_start.c | 86 + .../libtomcrypt/src/modes/f8/f8_test_mode.c | 64 + .../core/lib/libtomcrypt/src/modes/f8/sub.mk | 6 + .../libtomcrypt/src/modes/lrw/lrw_decrypt.c | 39 + .../lib/libtomcrypt/src/modes/lrw/lrw_done.c | 31 + .../libtomcrypt/src/modes/lrw/lrw_encrypt.c | 39 + .../lib/libtomcrypt/src/modes/lrw/lrw_getiv.c | 34 + .../libtomcrypt/src/modes/lrw/lrw_process.c | 109 + .../lib/libtomcrypt/src/modes/lrw/lrw_setiv.c | 68 + .../lib/libtomcrypt/src/modes/lrw/lrw_start.c | 92 + .../lib/libtomcrypt/src/modes/lrw/lrw_test.c | 124 + .../core/lib/libtomcrypt/src/modes/lrw/sub.mk | 7 + .../libtomcrypt/src/modes/ofb/ofb_decrypt.c | 31 + .../lib/libtomcrypt/src/modes/ofb/ofb_done.c | 30 + .../libtomcrypt/src/modes/ofb/ofb_encrypt.c | 48 + .../lib/libtomcrypt/src/modes/ofb/ofb_getiv.c | 34 + .../lib/libtomcrypt/src/modes/ofb/ofb_setiv.c | 40 + .../lib/libtomcrypt/src/modes/ofb/ofb_start.c | 48 + .../core/lib/libtomcrypt/src/modes/ofb/sub.mk | 6 + .../core/lib/libtomcrypt/src/modes/sub.mk | 4 + .../core/lib/libtomcrypt/src/modes/xts/sub.mk | 5 + .../libtomcrypt/src/modes/xts/xts_decrypt.c | 146 + .../lib/libtomcrypt/src/modes/xts/xts_done.c | 21 + .../libtomcrypt/src/modes/xts/xts_encrypt.c | 147 + .../lib/libtomcrypt/src/modes/xts/xts_init.c | 51 + .../libtomcrypt/src/modes/xts/xts_mult_x.c | 29 + .../lib/libtomcrypt/src/modes/xts/xts_test.c | 296 + .../pk/asn1/der/bit/der_decode_bit_string.c | 77 + .../asn1/der/bit/der_decode_raw_bit_string.c | 84 + .../pk/asn1/der/bit/der_encode_bit_string.c | 72 + .../asn1/der/bit/der_encode_raw_bit_string.c | 75 + .../pk/asn1/der/bit/der_length_bit_string.c | 36 + .../libtomcrypt/src/pk/asn1/der/bit/sub.mk | 5 + .../pk/asn1/der/boolean/der_decode_boolean.c | 35 + .../pk/asn1/der/boolean/der_encode_boolean.c | 39 + .../pk/asn1/der/boolean/der_length_boolean.c | 23 + .../src/pk/asn1/der/boolean/sub.mk | 3 + .../pk/asn1/der/choice/der_decode_choice.c | 222 + .../libtomcrypt/src/pk/asn1/der/choice/sub.mk | 1 + .../der/custom_type/der_decode_custom_type.c | 427 + .../der/custom_type/der_encode_custom_type.c | 229 + .../der/custom_type/der_length_custom_type.c | 204 + .../src/pk/asn1/der/custom_type/sub.mk | 3 + .../src/pk/asn1/der/general/der_asn1_maps.c | 157 + .../der/general/der_decode_asn1_identifier.c | 123 + .../asn1/der/general/der_decode_asn1_length.c | 59 + .../der/general/der_encode_asn1_identifier.c | 86 + .../asn1/der/general/der_encode_asn1_length.c | 117 + .../der/general/der_length_asn1_identifier.c | 23 + .../asn1/der/general/der_length_asn1_length.c | 22 + .../src/pk/asn1/der/general/sub.mk | 7 + .../der_decode_generalizedtime.c | 135 + .../der_encode_generalizedtime.c | 98 + .../der_length_generalizedtime.c | 48 + .../src/pk/asn1/der/generalizedtime/sub.mk | 3 + .../pk/asn1/der/ia5/der_decode_ia5_string.c | 73 + .../pk/asn1/der/ia5/der_encode_ia5_string.c | 61 + .../pk/asn1/der/ia5/der_length_ia5_string.c | 172 + .../libtomcrypt/src/pk/asn1/der/ia5/sub.mk | 3 + .../pk/asn1/der/integer/der_decode_integer.c | 68 + .../pk/asn1/der/integer/der_encode_integer.c | 105 + .../pk/asn1/der/integer/der_length_integer.c | 55 + .../src/pk/asn1/der/integer/sub.mk | 3 + .../der_decode_object_identifier.c | 94 + .../der_encode_object_identifier.c | 92 + .../der_length_object_identifier.c | 77 + .../src/pk/asn1/der/object_identifier/sub.mk | 3 + .../asn1/der/octet/der_decode_octet_string.c | 69 + .../asn1/der/octet/der_encode_octet_string.c | 62 + .../asn1/der/octet/der_length_octet_string.c | 33 + .../libtomcrypt/src/pk/asn1/der/octet/sub.mk | 3 + .../der_decode_printable_string.c | 73 + .../der_encode_printable_string.c | 61 + .../der_length_printable_string.c | 144 + .../src/pk/asn1/der/printable_string/sub.mk | 3 + .../der/sequence/der_decode_sequence_ex.c | 28 + .../der/sequence/der_decode_sequence_flexi.c | 541 + .../der/sequence/der_decode_sequence_multi.c | 183 + .../der/sequence/der_encode_sequence_ex.c | 203 + .../der/sequence/der_encode_sequence_multi.c | 141 + .../asn1/der/sequence/der_length_sequence.c | 180 + .../pk/asn1/der/sequence/der_sequence_free.c | 53 + .../asn1/der/sequence/der_sequence_shrink.c | 40 + .../src/pk/asn1/der/sequence/sub.mk | 7 + .../src/pk/asn1/der/set/der_encode_set.c | 74 + .../src/pk/asn1/der/set/der_encode_setof.c | 151 + .../libtomcrypt/src/pk/asn1/der/set/sub.mk | 2 + .../short_integer/der_decode_short_integer.c | 60 + .../short_integer/der_encode_short_integer.c | 85 + .../short_integer/der_length_short_integer.c | 52 + .../src/pk/asn1/der/short_integer/sub.mk | 3 + .../lib/libtomcrypt/src/pk/asn1/der/sub.mk | 17 + .../der_decode_teletex_string.c | 72 + .../der_length_teletex_string.c | 188 + .../src/pk/asn1/der/teletex_string/sub.mk | 2 + .../pk/asn1/der/utctime/der_decode_utctime.c | 116 + .../pk/asn1/der/utctime/der_encode_utctime.c | 71 + .../pk/asn1/der/utctime/der_length_utctime.c | 34 + .../src/pk/asn1/der/utctime/sub.mk | 3 + .../pk/asn1/der/utf8/der_decode_utf8_string.c | 117 + .../pk/asn1/der/utf8/der_encode_utf8_string.c | 76 + .../pk/asn1/der/utf8/der_length_utf8_string.c | 81 + .../libtomcrypt/src/pk/asn1/der/utf8/sub.mk | 4 + .../libtomcrypt/src/pk/asn1/oid/pk_get_oid.c | 37 + .../libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c | 44 + .../libtomcrypt/src/pk/asn1/oid/pk_oid_str.c | 82 + .../lib/libtomcrypt/src/pk/asn1/oid/sub.mk | 2 + .../src/pk/asn1/pkcs8/pkcs8_decode_flexi.c | 97 + .../core/lib/libtomcrypt/src/pk/asn1/sub.mk | 2 + .../x509_decode_public_key_from_certificate.c | 109 + .../x509_decode_subject_public_key_info.c | 119 + .../x509_encode_subject_public_key_info.c | 66 + .../core/lib/libtomcrypt/src/pk/dh/dh.c | 227 + .../libtomcrypt/src/pk/dh/dh_check_pubkey.c | 55 + .../lib/libtomcrypt/src/pk/dh/dh_export.c | 52 + .../lib/libtomcrypt/src/pk/dh/dh_export_key.c | 37 + .../core/lib/libtomcrypt/src/pk/dh/dh_free.c | 18 + .../libtomcrypt/src/pk/dh/dh_generate_key.c | 90 + .../lib/libtomcrypt/src/pk/dh/dh_import.c | 89 + .../lib/libtomcrypt/src/pk/dh/dh_make_key.c | 141 + .../core/lib/libtomcrypt/src/pk/dh/dh_set.c | 114 + .../libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c | 44 + .../libtomcrypt/src/pk/dh/dh_shared_secret.c | 70 + .../core/lib/libtomcrypt/src/pk/dh/sub.mk | 13 + .../libtomcrypt/src/pk/dsa/dsa_decrypt_key.c | 129 + .../libtomcrypt/src/pk/dsa/dsa_encrypt_key.c | 118 + .../lib/libtomcrypt/src/pk/dsa/dsa_export.c | 100 + .../lib/libtomcrypt/src/pk/dsa/dsa_free.c | 23 + .../libtomcrypt/src/pk/dsa/dsa_generate_key.c | 37 + .../libtomcrypt/src/pk/dsa/dsa_generate_pqg.c | 234 + .../lib/libtomcrypt/src/pk/dsa/dsa_import.c | 143 + .../lib/libtomcrypt/src/pk/dsa/dsa_make_key.c | 31 + .../core/lib/libtomcrypt/src/pk/dsa/dsa_set.c | 102 + .../src/pk/dsa/dsa_set_pqg_dsaparam.c | 57 + .../src/pk/dsa/dsa_shared_secret.c | 60 + .../libtomcrypt/src/pk/dsa/dsa_sign_hash.c | 142 + .../libtomcrypt/src/pk/dsa/dsa_verify_hash.c | 127 + .../libtomcrypt/src/pk/dsa/dsa_verify_key.c | 189 + .../core/lib/libtomcrypt/src/pk/dsa/sub.mk | 12 + .../src/pk/ec25519/ec25519_crypto_ctx.c | 41 + .../src/pk/ec25519/ec25519_export.c | 90 + .../src/pk/ec25519/ec25519_import_pkcs8.c | 87 + .../lib/libtomcrypt/src/pk/ec25519/sub.mk | 3 + .../libtomcrypt/src/pk/ec25519/tweetnacl.c | 491 + .../core/lib/libtomcrypt/src/pk/ecc/ecc.c | 447 + .../src/pk/ecc/ecc_ansi_x963_export.c | 24 + .../src/pk/ecc/ecc_ansi_x963_import.c | 52 + .../libtomcrypt/src/pk/ecc/ecc_decrypt_key.c | 133 + .../libtomcrypt/src/pk/ecc/ecc_encrypt_key.c | 120 + .../lib/libtomcrypt/src/pk/ecc/ecc_export.c | 61 + .../src/pk/ecc/ecc_export_openssl.c | 167 + .../libtomcrypt/src/pk/ecc/ecc_find_curve.c | 247 + .../lib/libtomcrypt/src/pk/ecc/ecc_free.c | 28 + .../lib/libtomcrypt/src/pk/ecc/ecc_get_key.c | 50 + .../libtomcrypt/src/pk/ecc/ecc_get_oid_str.c | 22 + .../lib/libtomcrypt/src/pk/ecc/ecc_get_size.c | 26 + .../lib/libtomcrypt/src/pk/ecc/ecc_import.c | 100 + .../src/pk/ecc/ecc_import_openssl.c | 120 + .../libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c | 186 + .../libtomcrypt/src/pk/ecc/ecc_import_x509.c | 116 + .../lib/libtomcrypt/src/pk/ecc/ecc_make_key.c | 73 + .../libtomcrypt/src/pk/ecc/ecc_recover_key.c | 260 + .../libtomcrypt/src/pk/ecc/ecc_set_curve.c | 80 + .../src/pk/ecc/ecc_set_curve_internal.c | 119 + .../lib/libtomcrypt/src/pk/ecc/ecc_set_key.c | 56 + .../src/pk/ecc/ecc_shared_secret.c | 66 + .../libtomcrypt/src/pk/ecc/ecc_sign_hash.c | 181 + .../lib/libtomcrypt/src/pk/ecc/ecc_sizes.c | 36 + .../src/pk/ecc/ecc_ssh_ecdsa_encode_name.c | 65 + .../libtomcrypt/src/pk/ecc/ecc_verify_hash.c | 206 + .../src/pk/ecc/ltc_ecc_export_point.c | 53 + .../src/pk/ecc/ltc_ecc_import_point.c | 61 + .../libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c | 62 + .../src/pk/ecc/ltc_ecc_is_point_at_infinity.c | 53 + .../lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c | 63 + .../libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c | 192 + .../libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c | 204 + .../src/pk/ecc/ltc_ecc_mulmod_timing.c | 151 + .../libtomcrypt/src/pk/ecc/ltc_ecc_points.c | 62 + .../src/pk/ecc/ltc_ecc_projective_add_point.c | 198 + .../src/pk/ecc/ltc_ecc_projective_dbl_point.c | 182 + .../src/pk/ecc/ltc_ecc_verify_key.c | 59 + .../core/lib/libtomcrypt/src/pk/ecc/sub.mk | 20 + .../src/pk/ed25519/ed25519_export.c | 31 + .../src/pk/ed25519/ed25519_import.c | 35 + .../src/pk/ed25519/ed25519_import_pkcs8.c | 28 + .../src/pk/ed25519/ed25519_import_raw.c | 41 + .../src/pk/ed25519/ed25519_import_x509.c | 45 + .../src/pk/ed25519/ed25519_make_key.c | 35 + .../libtomcrypt/src/pk/ed25519/ed25519_sign.c | 126 + .../src/pk/ed25519/ed25519_verify.c | 134 + .../lib/libtomcrypt/src/pk/ed25519/sub.mk | 7 + .../libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c | 39 + .../libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c | 96 + .../src/pk/pkcs1/pkcs_1_oaep_decode.c | 175 + .../src/pk/pkcs1/pkcs_1_oaep_encode.c | 161 + .../libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c | 24 + .../src/pk/pkcs1/pkcs_1_pss_decode.c | 167 + .../src/pk/pkcs1/pkcs_1_pss_encode.c | 164 + .../src/pk/pkcs1/pkcs_1_v1_5_decode.c | 102 + .../src/pk/pkcs1/pkcs_1_v1_5_encode.c | 99 + .../core/lib/libtomcrypt/src/pk/pkcs1/sub.mk | 9 + .../libtomcrypt/src/pk/rsa/rsa_decrypt_key.c | 93 + .../libtomcrypt/src/pk/rsa/rsa_encrypt_key.c | 92 + .../lib/libtomcrypt/src/pk/rsa/rsa_export.c | 91 + .../lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c | 172 + .../lib/libtomcrypt/src/pk/rsa/rsa_get_size.c | 30 + .../lib/libtomcrypt/src/pk/rsa/rsa_import.c | 143 + .../libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c | 116 + .../libtomcrypt/src/pk/rsa/rsa_import_x509.c | 54 + .../core/lib/libtomcrypt/src/pk/rsa/rsa_key.c | 103 + .../lib/libtomcrypt/src/pk/rsa/rsa_make_key.c | 165 + .../core/lib/libtomcrypt/src/pk/rsa/rsa_set.c | 123 + .../libtomcrypt/src/pk/rsa/rsa_sign_hash.c | 136 + .../src/pk/rsa/rsa_sign_saltlen_get.c | 37 + .../libtomcrypt/src/pk/rsa/rsa_verify_hash.c | 198 + .../core/lib/libtomcrypt/src/pk/rsa/sub.mk | 9 + .../core/lib/libtomcrypt/src/pk/sub.mk | 11 + .../core/lib/libtomcrypt/src/pk/x25519/sub.mk | 4 + .../libtomcrypt/src/pk/x25519/x25519_export.c | 31 + .../libtomcrypt/src/pk/x25519/x25519_import.c | 35 + .../src/pk/x25519/x25519_import_pkcs8.c | 28 + .../src/pk/x25519/x25519_import_raw.c | 41 + .../src/pk/x25519/x25519_import_x509.c | 45 + .../src/pk/x25519/x25519_make_key.c | 41 + .../src/pk/x25519/x25519_shared_secret.c | 42 + .../core/lib/libtomcrypt/src/prngs/chacha20.c | 218 + .../core/lib/libtomcrypt/src/prngs/fortuna.c | 520 + .../core/lib/libtomcrypt/src/prngs/rc4.c | 221 + .../lib/libtomcrypt/src/prngs/rng_get_bytes.c | 152 + .../lib/libtomcrypt/src/prngs/rng_make_prng.c | 81 + .../core/lib/libtomcrypt/src/prngs/sober128.c | 220 + .../core/lib/libtomcrypt/src/prngs/sprng.c | 152 + .../core/lib/libtomcrypt/src/prngs/sub.mk | 7 + .../core/lib/libtomcrypt/src/prngs/yarrow.c | 323 + .../src/stream/chacha/chacha_crypt.c | 91 + .../src/stream/chacha/chacha_done.c | 20 + .../src/stream/chacha/chacha_ivctr32.c | 37 + .../src/stream/chacha/chacha_ivctr64.c | 37 + .../src/stream/chacha/chacha_keystream.c | 28 + .../src/stream/chacha/chacha_memory.c | 41 + .../src/stream/chacha/chacha_setup.c | 57 + .../src/stream/chacha/chacha_test.c | 74 + .../libtomcrypt/src/stream/rabbit/rabbit.c | 447 + .../src/stream/rabbit/rabbit_memory.c | 40 + .../libtomcrypt/src/stream/rc4/rc4_stream.c | 101 + .../src/stream/rc4/rc4_stream_memory.c | 31 + .../lib/libtomcrypt/src/stream/rc4/rc4_test.c | 33 + .../src/stream/salsa20/salsa20_crypt.c | 86 + .../src/stream/salsa20/salsa20_done.c | 20 + .../src/stream/salsa20/salsa20_ivctr64.c | 38 + .../src/stream/salsa20/salsa20_keystream.c | 29 + .../src/stream/salsa20/salsa20_memory.c | 35 + .../src/stream/salsa20/salsa20_setup.c | 59 + .../src/stream/salsa20/salsa20_test.c | 86 + .../src/stream/salsa20/xsalsa20_memory.c | 34 + .../src/stream/salsa20/xsalsa20_setup.c | 127 + .../src/stream/salsa20/xsalsa20_test.c | 90 + .../src/stream/sober128/sober128_stream.c | 333 + .../stream/sober128/sober128_stream_memory.c | 35 + .../src/stream/sober128/sober128_test.c | 43 + .../src/stream/sober128/sober128tab.c | 166 + .../src/stream/sosemanuk/sosemanuk.c | 807 + .../src/stream/sosemanuk/sosemanuk_memory.c | 35 + .../src/stream/sosemanuk/sosemanuk_test.c | 79 + .../optee_os/core/lib/libtomcrypt/src/sub.mk | 9 + optee/optee_os/core/lib/libtomcrypt/sub.mk | 154 + .../optee_os/core/lib/libtomcrypt/tomcrypt.c | 169 + optee/optee_os/core/lib/libtomcrypt/x25519.c | 109 + optee/optee_os/core/lib/libtomcrypt/xts.c | 130 + .../core/lib/scmi-server/conf-optee-fvp.mk | 22 + .../lib/scmi-server/conf-optee-stm32mp1.mk | 18 + optee/optee_os/core/lib/scmi-server/conf.mk | 78 + .../core/lib/scmi-server/include/optee_scmi.h | 21 + .../core/lib/scmi-server/scmi_server.c | 86 + .../core/lib/scmi-server/sub-optee-fvp.mk | 17 + .../lib/scmi-server/sub-optee-stm32mp1.mk | 10 + optee/optee_os/core/lib/scmi-server/sub.mk | 208 + optee/optee_os/core/lib/zlib/adler32.c | 187 + optee/optee_os/core/lib/zlib/gzguts.h | 220 + optee/optee_os/core/lib/zlib/inffast.c | 324 + optee/optee_os/core/lib/zlib/inffast.h | 12 + optee/optee_os/core/lib/zlib/inffixed.h | 94 + optee/optee_os/core/lib/zlib/inflate.c | 1593 ++ optee/optee_os/core/lib/zlib/inflate.h | 127 + optee/optee_os/core/lib/zlib/inftrees.c | 305 + optee/optee_os/core/lib/zlib/inftrees.h | 63 + optee/optee_os/core/lib/zlib/sub.mk | 8 + optee/optee_os/core/lib/zlib/zconf.h | 544 + optee/optee_os/core/lib/zlib/zlib.h | 1936 ++ optee/optee_os/core/lib/zlib/zutil.c | 326 + optee/optee_os/core/lib/zlib/zutil.h | 275 + optee/optee_os/core/mm/core_mmu.c | 2535 +++ optee/optee_os/core/mm/file.c | 209 + optee/optee_os/core/mm/fobj.c | 818 + optee/optee_os/core/mm/mobj.c | 762 + optee/optee_os/core/mm/sub.mk | 8 + optee/optee_os/core/mm/tee_mm.c | 394 + optee/optee_os/core/mm/vm.c | 1402 ++ optee/optee_os/core/pta/apdu.c | 88 + optee/optee_os/core/pta/attestation.c | 770 + optee/optee_os/core/pta/bcm/bnxt.c | 134 + optee/optee_os/core/pta/bcm/elog.c | 250 + optee/optee_os/core/pta/bcm/gpio.c | 195 + optee/optee_os/core/pta/bcm/hwrng.c | 78 + optee/optee_os/core/pta/bcm/sotp.c | 101 + optee/optee_os/core/pta/bcm/sub.mk | 6 + optee/optee_os/core/pta/bcm/wdt.c | 171 + optee/optee_os/core/pta/benchmark.c | 215 + optee/optee_os/core/pta/device.c | 102 + optee/optee_os/core/pta/gprof.c | 184 + optee/optee_os/core/pta/hwrng.c | 80 + optee/optee_os/core/pta/imx/digprog.c | 32 + .../core/pta/imx/manufacturing_protection.c | 122 + optee/optee_os/core/pta/imx/ocotp.c | 75 + optee/optee_os/core/pta/imx/sub.mk | 3 + optee/optee_os/core/pta/k3/otp.c | 119 + optee/optee_os/core/pta/k3/sub.mk | 1 + optee/optee_os/core/pta/rtc.c | 195 + optee/optee_os/core/pta/scmi.c | 248 + optee/optee_os/core/pta/scp03.c | 43 + optee/optee_os/core/pta/secstor_ta_mgmt.c | 189 + optee/optee_os/core/pta/stats.c | 203 + optee/optee_os/core/pta/stm32mp/bsec_pta.c | 301 + optee/optee_os/core/pta/stm32mp/sub.mk | 1 + optee/optee_os/core/pta/sub.mk | 22 + optee/optee_os/core/pta/system.c | 363 + .../pta/tegra/jetson_decrypt_cpubl_payload.h | 78 + .../tegra/jetson_t194_decrypt_cpubl_payload.c | 226 + .../tegra/jetson_t234_decrypt_cpubl_payload.c | 312 + .../core/pta/tegra/jetson_user_key_pta.c | 907 + optee/optee_os/core/pta/tegra/sub.mk | 10 + optee/optee_os/core/pta/tests/aes_perf.c | 222 + optee/optee_os/core/pta/tests/fs_htree.c | 623 + optee/optee_os/core/pta/tests/invoke.c | 449 + optee/optee_os/core/pta/tests/lockdep.c | 201 + optee/optee_os/core/pta/tests/misc.c | 580 + optee/optee_os/core/pta/tests/misc.h | 40 + optee/optee_os/core/pta/tests/mutex.c | 92 + optee/optee_os/core/pta/tests/sub.mk | 7 + optee/optee_os/core/sub.mk | 90 + optee/optee_os/core/tee/entry_std.c | 609 + optee/optee_os/core/tee/fs_dirfile.c | 394 + optee/optee_os/core/tee/fs_htree.c | 929 + optee/optee_os/core/tee/socket.c | 258 + optee/optee_os/core/tee/sub.mk | 51 + optee/optee_os/core/tee/tadb.c | 783 + optee/optee_os/core/tee/tee_cryp_concat_kdf.c | 69 + optee/optee_os/core/tee/tee_cryp_hkdf.c | 161 + optee/optee_os/core/tee/tee_cryp_pbkdf2.c | 114 + optee/optee_os/core/tee/tee_cryp_utl.c | 218 + optee/optee_os/core/tee/tee_fs_key_manager.c | 277 + optee/optee_os/core/tee/tee_fs_rpc.c | 223 + optee/optee_os/core/tee/tee_nvme_rpmb_fs.c | 3023 +++ optee/optee_os/core/tee/tee_obj.c | 87 + optee/optee_os/core/tee/tee_pobj.c | 191 + optee/optee_os/core/tee/tee_ree_fs.c | 1018 + optee/optee_os/core/tee/tee_rpmb_fs.c | 3108 +++ optee/optee_os/core/tee/tee_supp_plugin_rpc.c | 78 + optee/optee_os/core/tee/tee_svc.c | 1115 + optee/optee_os/core/tee/tee_svc_cryp.c | 4489 ++++ optee/optee_os/core/tee/tee_svc_storage.c | 937 + optee/optee_os/core/tee/tee_ta_enc_manager.c | 65 + optee/optee_os/core/tee/tee_time_generic.c | 137 + optee/optee_os/core/tee/uuid.c | 48 + optee/optee_os/core/tests/ftmn_boot_tests.c | 208 + optee/optee_os/core/tests/sub.mk | 1 + optee/optee_os/keys/default_ta.pem | 27 + optee/optee_os/ldelf/dl.c | 38 + optee/optee_os/ldelf/dl.h | 16 + optee/optee_os/ldelf/ftrace.c | 90 + optee/optee_os/ldelf/ftrace.h | 24 + optee/optee_os/ldelf/include/ldelf.h | 146 + optee/optee_os/ldelf/include/ldelf_syscalls.h | 33 + optee/optee_os/ldelf/ldelf.ld.S | 90 + optee/optee_os/ldelf/ldelf.mk | 58 + optee/optee_os/ldelf/link.mk | 59 + optee/optee_os/ldelf/main.c | 180 + optee/optee_os/ldelf/pauth.c | 15 + optee/optee_os/ldelf/pauth.h | 15 + optee/optee_os/ldelf/start_a32.S | 59 + optee/optee_os/ldelf/start_a64.S | 64 + optee/optee_os/ldelf/start_rv64.S | 61 + optee/optee_os/ldelf/sub.mk | 15 + optee/optee_os/ldelf/sys.c | 89 + optee/optee_os/ldelf/sys.h | 52 + optee/optee_os/ldelf/syscalls_a32.S | 51 + optee/optee_os/ldelf/syscalls_a64.S | 33 + optee/optee_os/ldelf/syscalls_asm.S | 20 + optee/optee_os/ldelf/syscalls_rv.S | 31 + optee/optee_os/ldelf/ta_elf.c | 1989 ++ optee/optee_os/ldelf/ta_elf.h | 150 + optee/optee_os/ldelf/ta_elf_rel.c | 752 + optee/optee_os/ldelf/tlsdesc_rel_a64.S | 21 + optee/optee_os/lib/libdl/dlfcn.c | 119 + optee/optee_os/lib/libdl/include/dlfcn.h | 22 + optee/optee_os/lib/libdl/sub.mk | 2 + optee/optee_os/lib/libmbedtls/core/aes.c | 104 + optee/optee_os/lib/libmbedtls/core/aes_cbc.c | 143 + optee/optee_os/lib/libmbedtls/core/aes_ctr.c | 172 + optee/optee_os/lib/libmbedtls/core/aes_ecb.c | 143 + optee/optee_os/lib/libmbedtls/core/bignum.c | 101 + optee/optee_os/lib/libmbedtls/core/cmac.c | 182 + optee/optee_os/lib/libmbedtls/core/des3_cbc.c | 128 + optee/optee_os/lib/libmbedtls/core/des3_ecb.c | 126 + optee/optee_os/lib/libmbedtls/core/des_cbc.c | 121 + optee/optee_os/lib/libmbedtls/core/des_ecb.c | 117 + optee/optee_os/lib/libmbedtls/core/dh.c | 142 + optee/optee_os/lib/libmbedtls/core/ecc.c | 564 + optee/optee_os/lib/libmbedtls/core/hash.c | 243 + optee/optee_os/lib/libmbedtls/core/hmac.c | 173 + .../lib/libmbedtls/core/mbed_helpers.c | 33 + .../lib/libmbedtls/core/mbed_helpers.h | 42 + optee/optee_os/lib/libmbedtls/core/rsa.c | 781 + optee/optee_os/lib/libmbedtls/core/sm2-dsa.c | 268 + optee/optee_os/lib/libmbedtls/core/sm2-dsa.h | 20 + optee/optee_os/lib/libmbedtls/core/sm2-kep.c | 499 + optee/optee_os/lib/libmbedtls/core/sm2-pke.c | 452 + optee/optee_os/lib/libmbedtls/core/sm2-pke.h | 19 + optee/optee_os/lib/libmbedtls/core/sub.mk | 32 + optee/optee_os/lib/libmbedtls/core/tomcrypt.c | 15 + .../optee_os/lib/libmbedtls/include/aes_alt.h | 12 + .../include/mbedtls_config_kernel.h | 127 + .../libmbedtls/include/mbedtls_config_uta.h | 70 + optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md | 20 + .../lib/libmbedtls/mbedtls/CONTRIBUTING.md | 81 + .../optee_os/lib/libmbedtls/mbedtls/ChangeLog | 4607 ++++ optee/optee_os/lib/libmbedtls/mbedtls/LICENSE | 202 + .../optee_os/lib/libmbedtls/mbedtls/README.md | 264 + .../lib/libmbedtls/mbedtls/SECURITY.md | 20 + .../lib/libmbedtls/mbedtls/SUPPORT.md | 15 + optee/optee_os/lib/libmbedtls/mbedtls/dco.txt | 37 + .../libmbedtls/mbedtls/include/mbedtls/aes.h | 689 + .../mbedtls/include/mbedtls/aesni.h | 136 + .../libmbedtls/mbedtls/include/mbedtls/arc4.h | 145 + .../libmbedtls/mbedtls/include/mbedtls/aria.h | 373 + .../libmbedtls/mbedtls/include/mbedtls/asn1.h | 616 + .../mbedtls/include/mbedtls/asn1write.h | 370 + .../mbedtls/include/mbedtls/base64.h | 98 + .../mbedtls/include/mbedtls/bignum.h | 1097 + .../mbedtls/include/mbedtls/blowfish.h | 288 + .../mbedtls/include/mbedtls/bn_mul.h | 978 + .../mbedtls/include/mbedtls/camellia.h | 327 + .../libmbedtls/mbedtls/include/mbedtls/ccm.h | 311 + .../mbedtls/include/mbedtls/certs.h | 250 + .../mbedtls/include/mbedtls/chacha20.h | 228 + .../mbedtls/include/mbedtls/chachapoly.h | 359 + .../mbedtls/include/mbedtls/check_config.h | 936 + .../mbedtls/include/mbedtls/cipher.h | 1127 + .../mbedtls/include/mbedtls/cipher_internal.h | 153 + .../libmbedtls/mbedtls/include/mbedtls/cmac.h | 260 + .../mbedtls/include/mbedtls/compat-1.3.h | 2529 +++ .../mbedtls/include/mbedtls/config.h | 7 + .../mbedtls/include/mbedtls/constant_time.h | 45 + .../mbedtls/include/mbedtls/ctr_drbg.h | 611 + .../mbedtls/include/mbedtls/debug.h | 311 + .../libmbedtls/mbedtls/include/mbedtls/des.h | 370 + .../libmbedtls/mbedtls/include/mbedtls/dhm.h | 1103 + .../libmbedtls/mbedtls/include/mbedtls/ecdh.h | 446 + .../mbedtls/include/mbedtls/ecdsa.h | 626 + .../mbedtls/include/mbedtls/ecjpake.h | 275 + .../libmbedtls/mbedtls/include/mbedtls/ecp.h | 1315 ++ .../mbedtls/include/mbedtls/ecp_internal.h | 297 + .../mbedtls/include/mbedtls/entropy.h | 294 + .../mbedtls/include/mbedtls/entropy_poll.h | 108 + .../mbedtls/include/mbedtls/error.h | 217 + .../libmbedtls/mbedtls/include/mbedtls/gcm.h | 327 + .../mbedtls/include/mbedtls/havege.h | 80 + .../libmbedtls/mbedtls/include/mbedtls/hkdf.h | 140 + .../mbedtls/include/mbedtls/hmac_drbg.h | 474 + .../libmbedtls/mbedtls/include/mbedtls/md.h | 493 + .../libmbedtls/mbedtls/include/mbedtls/md2.h | 305 + .../libmbedtls/mbedtls/include/mbedtls/md4.h | 310 + .../libmbedtls/mbedtls/include/mbedtls/md5.h | 310 + .../mbedtls/include/mbedtls/md_internal.h | 90 + .../include/mbedtls/memory_buffer_alloc.h | 149 + .../libmbedtls/mbedtls/include/mbedtls/net.h | 35 + .../mbedtls/include/mbedtls/net_sockets.h | 301 + .../mbedtls/include/mbedtls/nist_kw.h | 182 + .../libmbedtls/mbedtls/include/mbedtls/oid.h | 649 + .../mbedtls/include/mbedtls/padlock.h | 125 + .../libmbedtls/mbedtls/include/mbedtls/pem.h | 153 + .../libmbedtls/mbedtls/include/mbedtls/pk.h | 918 + .../mbedtls/include/mbedtls/pk_internal.h | 140 + .../mbedtls/include/mbedtls/pkcs11.h | 246 + .../mbedtls/include/mbedtls/pkcs12.h | 140 + .../mbedtls/include/mbedtls/pkcs5.h | 111 + .../mbedtls/include/mbedtls/platform.h | 421 + .../mbedtls/include/mbedtls/platform_time.h | 72 + .../mbedtls/include/mbedtls/platform_util.h | 283 + .../mbedtls/include/mbedtls/poly1305.h | 194 + .../mbedtls/include/mbedtls/psa_util.h | 512 + .../mbedtls/include/mbedtls/ripemd160.h | 236 + .../libmbedtls/mbedtls/include/mbedtls/rsa.h | 1351 ++ .../mbedtls/include/mbedtls/rsa_internal.h | 224 + .../libmbedtls/mbedtls/include/mbedtls/sha1.h | 352 + .../mbedtls/include/mbedtls/sha256.h | 300 + .../mbedtls/include/mbedtls/sha512.h | 316 + .../libmbedtls/mbedtls/include/mbedtls/ssl.h | 4427 ++++ .../mbedtls/include/mbedtls/ssl_cache.h | 149 + .../include/mbedtls/ssl_ciphersuites.h | 556 + .../mbedtls/include/mbedtls/ssl_cookie.h | 113 + .../mbedtls/include/mbedtls/ssl_internal.h | 1352 ++ .../mbedtls/include/mbedtls/ssl_ticket.h | 140 + .../mbedtls/include/mbedtls/threading.h | 126 + .../mbedtls/include/mbedtls/timing.h | 151 + .../mbedtls/include/mbedtls/version.h | 110 + .../libmbedtls/mbedtls/include/mbedtls/x509.h | 380 + .../mbedtls/include/mbedtls/x509_crl.h | 172 + .../mbedtls/include/mbedtls/x509_crt.h | 1097 + .../mbedtls/include/mbedtls/x509_csr.h | 306 + .../libmbedtls/mbedtls/include/mbedtls/xtea.h | 139 + .../lib/libmbedtls/mbedtls/library/aes.c | 2189 ++ .../lib/libmbedtls/mbedtls/library/aesni.c | 464 + .../lib/libmbedtls/mbedtls/library/arc4.c | 195 + .../lib/libmbedtls/mbedtls/library/aria.c | 1058 + .../libmbedtls/mbedtls/library/asn1parse.c | 481 + .../libmbedtls/mbedtls/library/asn1write.c | 485 + .../lib/libmbedtls/mbedtls/library/base64.c | 277 + .../lib/libmbedtls/mbedtls/library/bignum.c | 3174 +++ .../lib/libmbedtls/mbedtls/library/blowfish.c | 667 + .../lib/libmbedtls/mbedtls/library/camellia.c | 1087 + .../lib/libmbedtls/mbedtls/library/ccm.c | 546 + .../lib/libmbedtls/mbedtls/library/certs.c | 1746 ++ .../lib/libmbedtls/mbedtls/library/chacha20.c | 558 + .../libmbedtls/mbedtls/library/chachapoly.c | 524 + .../mbedtls/library/check_crypto_config.h | 91 + .../lib/libmbedtls/mbedtls/library/cipher.c | 1676 ++ .../libmbedtls/mbedtls/library/cipher_wrap.c | 2484 +++ .../lib/libmbedtls/mbedtls/library/cmac.c | 1096 + .../lib/libmbedtls/mbedtls/library/common.h | 305 + .../mbedtls/library/constant_time.c | 832 + .../mbedtls/library/constant_time_internal.h | 336 + .../mbedtls/library/constant_time_invasive.h | 51 + .../lib/libmbedtls/mbedtls/library/ctr_drbg.c | 898 + .../lib/libmbedtls/mbedtls/library/debug.c | 422 + .../lib/libmbedtls/mbedtls/library/des.c | 1062 + .../lib/libmbedtls/mbedtls/library/dhm.c | 719 + .../lib/libmbedtls/mbedtls/library/ecdh.c | 729 + .../lib/libmbedtls/mbedtls/library/ecdsa.c | 1012 + .../lib/libmbedtls/mbedtls/library/ecjpake.c | 1141 + .../lib/libmbedtls/mbedtls/library/ecp.c | 3608 +++ .../libmbedtls/mbedtls/library/ecp_curves.c | 1526 ++ .../libmbedtls/mbedtls/library/ecp_invasive.h | 81 + .../lib/libmbedtls/mbedtls/library/entropy.c | 737 + .../libmbedtls/mbedtls/library/entropy_poll.c | 291 + .../lib/libmbedtls/mbedtls/library/error.c | 980 + .../lib/libmbedtls/mbedtls/library/gcm.c | 1003 + .../lib/libmbedtls/mbedtls/library/havege.c | 237 + .../lib/libmbedtls/mbedtls/library/hkdf.c | 189 + .../libmbedtls/mbedtls/library/hmac_drbg.c | 629 + .../lib/libmbedtls/mbedtls/library/md.c | 893 + .../lib/libmbedtls/mbedtls/library/md2.c | 360 + .../lib/libmbedtls/mbedtls/library/md4.c | 461 + .../lib/libmbedtls/mbedtls/library/md5.c | 475 + .../mbedtls/library/memory_buffer_alloc.c | 744 + .../libmbedtls/mbedtls/library/net_sockets.c | 715 + .../lib/libmbedtls/mbedtls/library/nist_kw.c | 713 + .../lib/libmbedtls/mbedtls/library/oid.c | 767 + .../lib/libmbedtls/mbedtls/library/padlock.c | 164 + .../lib/libmbedtls/mbedtls/library/pem.c | 489 + .../lib/libmbedtls/mbedtls/library/pk.c | 642 + .../lib/libmbedtls/mbedtls/library/pk_wrap.c | 1069 + .../lib/libmbedtls/mbedtls/library/pkcs11.c | 238 + .../lib/libmbedtls/mbedtls/library/pkcs12.c | 404 + .../lib/libmbedtls/mbedtls/library/pkcs5.c | 420 + .../lib/libmbedtls/mbedtls/library/pkparse.c | 1545 ++ .../lib/libmbedtls/mbedtls/library/pkwrite.c | 623 + .../lib/libmbedtls/mbedtls/library/platform.c | 386 + .../mbedtls/library/platform_util.c | 133 + .../lib/libmbedtls/mbedtls/library/poly1305.c | 538 + .../libmbedtls/mbedtls/library/ripemd160.c | 536 + .../lib/libmbedtls/mbedtls/library/rsa.c | 2601 +++ .../libmbedtls/mbedtls/library/rsa_internal.c | 486 + .../lib/libmbedtls/mbedtls/library/sha1.c | 553 + .../lib/libmbedtls/mbedtls/library/sha256.c | 585 + .../lib/libmbedtls/mbedtls/library/sha512.c | 660 + .../libmbedtls/mbedtls/library/ssl_cache.c | 345 + .../mbedtls/library/ssl_ciphersuites.c | 2373 ++ .../lib/libmbedtls/mbedtls/library/ssl_cli.c | 4609 ++++ .../libmbedtls/mbedtls/library/ssl_cookie.c | 258 + .../lib/libmbedtls/mbedtls/library/ssl_msg.c | 5991 +++++ .../lib/libmbedtls/mbedtls/library/ssl_srv.c | 4855 ++++ .../libmbedtls/mbedtls/library/ssl_ticket.c | 406 + .../lib/libmbedtls/mbedtls/library/ssl_tls.c | 7742 +++++++ .../mbedtls/library/ssl_tls13_keys.c | 349 + .../mbedtls/library/ssl_tls13_keys.h | 274 + .../libmbedtls/mbedtls/library/threading.c | 187 + .../lib/libmbedtls/mbedtls/library/timing.c | 529 + .../lib/libmbedtls/mbedtls/library/version.c | 44 + .../mbedtls/library/version_features.c | 872 + .../lib/libmbedtls/mbedtls/library/x509.c | 1074 + .../libmbedtls/mbedtls/library/x509_create.c | 374 + .../lib/libmbedtls/mbedtls/library/x509_crl.c | 770 + .../lib/libmbedtls/mbedtls/library/x509_crt.c | 3399 +++ .../lib/libmbedtls/mbedtls/library/x509_csr.c | 414 + .../mbedtls/library/x509write_crt.c | 543 + .../mbedtls/library/x509write_csr.c | 341 + .../lib/libmbedtls/mbedtls/library/xtea.c | 248 + optee/optee_os/lib/libmbedtls/sub.mk | 133 + .../optee_os/lib/libunw/include/unw/unwind.h | 124 + optee/optee_os/lib/libunw/sub.mk | 5 + optee/optee_os/lib/libunw/unwind_arm32.c | 418 + optee/optee_os/lib/libunw/unwind_arm64.c | 92 + optee/optee_os/lib/libutee/abort.c | 18 + .../libutee/arch/arm/arm32_user_sysreg.txt | 14 + .../lib/libutee/arch/arm/gprof/gmon.h | 197 + .../lib/libutee/arch/arm/gprof/gmon_out.h | 119 + .../lib/libutee/arch/arm/gprof/gprof.c | 434 + .../lib/libutee/arch/arm/gprof/gprof_pta.c | 93 + .../lib/libutee/arch/arm/gprof/gprof_pta.h | 19 + .../lib/libutee/arch/arm/gprof/sub.mk | 5 + optee/optee_os/lib/libutee/arch/arm/sub.mk | 9 + .../lib/libutee/arch/arm/utee_syscalls_a32.S | 60 + .../lib/libutee/arch/arm/utee_syscalls_a64.S | 49 + optee/optee_os/lib/libutee/arch/riscv/sub.mk | 3 + .../lib/libutee/arch/riscv/utee_syscalls_rv.S | 28 + optee/optee_os/lib/libutee/assert.c | 28 + optee/optee_os/lib/libutee/base64.c | 128 + optee/optee_os/lib/libutee/base64.h | 16 + .../lib/libutee/include/__tee_ipsocket.h | 15 + .../libutee/include/__tee_isocket_defines.h | 18 + .../libutee/include/__tee_tcpsocket_defines.h | 15 + .../__tee_tcpsocket_defines_extensions.h | 13 + .../libutee/include/__tee_udpsocket_defines.h | 19 + .../lib/libutee/include/arm64_user_sysreg.h | 41 + .../lib/libutee/include/arm_user_sysreg.h | 35 + optee/optee_os/lib/libutee/include/elf.h | 70 + optee/optee_os/lib/libutee/include/elf32.h | 247 + optee/optee_os/lib/libutee/include/elf64.h | 250 + .../optee_os/lib/libutee/include/elf_common.h | 1058 + .../libutee/include/k3/otp_keywriting_ta.h | 55 + optee/optee_os/lib/libutee/include/link.h | 27 + optee/optee_os/lib/libutee/include/pta_apdu.h | 47 + .../lib/libutee/include/pta_attestation.h | 102 + .../lib/libutee/include/pta_benchmark.h | 26 + .../optee_os/lib/libutee/include/pta_device.h | 29 + .../optee_os/lib/libutee/include/pta_gprof.h | 43 + .../lib/libutee/include/pta_imx_digprog.h | 11 + .../pta_imx_manufacturing_protection.h | 35 + .../lib/libutee/include/pta_imx_ocotp.h | 37 + .../lib/libutee/include/pta_invoke_tests.h | 112 + .../lib/libutee/include/pta_jetson_user_key.h | 106 + optee/optee_os/lib/libutee/include/pta_rng.h | 45 + optee/optee_os/lib/libutee/include/pta_rtc.h | 103 + .../lib/libutee/include/pta_scmi_client.h | 84 + .../optee_os/lib/libutee/include/pta_scp03.h | 31 + .../lib/libutee/include/pta_secstor_ta_mgmt.h | 21 + .../optee_os/lib/libutee/include/pta_socket.h | 51 + .../lib/libutee/include/pta_stm32mp_bsec.h | 89 + .../optee_os/lib/libutee/include/pta_system.h | 204 + .../lib/libutee/include/rng_pta_client.h | 13 + optee/optee_os/lib/libutee/include/tee_api.h | 11 + .../lib/libutee/include/tee_api_compat.h | 102 + .../lib/libutee/include/tee_api_defines.h | 697 + .../include/tee_api_defines_extensions.h | 143 + .../lib/libutee/include/tee_api_types.h | 227 + .../lib/libutee/include/tee_arith_internal.h | 60 + .../lib/libutee/include/tee_internal_api.h | 832 + .../include/tee_internal_api_extensions.h | 81 + .../lib/libutee/include/tee_isocket.h | 35 + .../lib/libutee/include/tee_syscall_numbers.h | 88 + .../optee_os/lib/libutee/include/tee_ta_api.h | 12 + .../lib/libutee/include/tee_tcpsocket.h | 21 + .../lib/libutee/include/tee_udpsocket.h | 21 + .../lib/libutee/include/user_ta_header.h | 153 + .../lib/libutee/include/utee_defines.h | 353 + .../lib/libutee/include/utee_syscalls.h | 228 + .../lib/libutee/include/utee_syscalls_asm.S | 124 + .../optee_os/lib/libutee/include/utee_types.h | 70 + optee/optee_os/lib/libutee/sub.mk | 29 + optee/optee_os/lib/libutee/tcb.c | 207 + optee/optee_os/lib/libutee/tee_api.c | 809 + .../optee_os/lib/libutee/tee_api_arith_mpi.c | 1016 + optee/optee_os/lib/libutee/tee_api_objects.c | 1054 + .../optee_os/lib/libutee/tee_api_operations.c | 2712 +++ optee/optee_os/lib/libutee/tee_api_panic.c | 114 + optee/optee_os/lib/libutee/tee_api_private.h | 46 + optee/optee_os/lib/libutee/tee_api_property.c | 629 + .../optee_os/lib/libutee/tee_socket_private.h | 32 + optee/optee_os/lib/libutee/tee_socket_pta.c | 162 + optee/optee_os/lib/libutee/tee_system_pta.c | 111 + .../optee_os/lib/libutee/tee_tcpudp_socket.c | 231 + .../optee_os/lib/libutee/tee_uuid_from_str.c | 78 + optee/optee_os/lib/libutee/trace_ext.c | 105 + optee/optee_os/lib/libutee/user_ta_entry.c | 446 + .../lib/libutee/user_ta_entry_compat.c | 99 + .../lib/libutils/ext/arch/arm/aeabi_unwind.c | 20 + .../lib/libutils/ext/arch/arm/atomic_a32.S | 30 + .../lib/libutils/ext/arch/arm/atomic_a64.S | 31 + .../lib/libutils/ext/arch/arm/auxval.c | 12 + .../lib/libutils/ext/arch/arm/mcount_a32.S | 65 + .../lib/libutils/ext/arch/arm/mcount_a64.S | 85 + .../lib/libutils/ext/arch/arm/memtag.c | 207 + .../optee_os/lib/libutils/ext/arch/arm/sub.mk | 11 + .../lib/libutils/ext/arch/riscv/atomic_rv.S | 22 + .../lib/libutils/ext/arch/riscv/sub.mk | 1 + .../lib/libutils/ext/consttime_memcmp.c | 51 + .../lib/libutils/ext/fault_mitigation.c | 153 + .../optee_os/lib/libutils/ext/ftrace/ftrace.c | 329 + .../optee_os/lib/libutils/ext/ftrace/ftrace.h | 11 + optee/optee_os/lib/libutils/ext/ftrace/sub.mk | 5 + .../lib/libutils/ext/include/arm64_bti.S | 37 + optee/optee_os/lib/libutils/ext/include/asm.S | 89 + .../lib/libutils/ext/include/atomic.h | 66 + .../lib/libutils/ext/include/bitstring.h | 159 + .../lib/libutils/ext/include/compiler.h | 279 + .../lib/libutils/ext/include/config.h | 68 + .../ext/include/confine_array_index.h | 157 + .../libutils/ext/include/fault_mitigation.h | 687 + .../lib/libutils/ext/include/mempool.h | 77 + .../lib/libutils/ext/include/memtag.h | 234 + .../lib/libutils/ext/include/printk.h | 28 + .../ext/include/speculation_barrier.h | 508 + .../lib/libutils/ext/include/stdlib_ext.h | 18 + .../lib/libutils/ext/include/string_ext.h | 55 + .../optee_os/lib/libutils/ext/include/trace.h | 152 + .../lib/libutils/ext/include/trace_levels.h | 36 + .../lib/libutils/ext/include/types_ext.h | 37 + .../optee_os/lib/libutils/ext/include/util.h | 198 + optee/optee_os/lib/libutils/ext/mempool.c | 185 + .../lib/libutils/ext/memzero_explicit.c | 23 + optee/optee_os/lib/libutils/ext/nex_strdup.c | 17 + .../optee_os/lib/libutils/ext/pthread_stubs.c | 21 + optee/optee_os/lib/libutils/ext/snprintk.c | 622 + optee/optee_os/lib/libutils/ext/strlcat.c | 76 + optee/optee_os/lib/libutils/ext/strlcpy.c | 69 + optee/optee_os/lib/libutils/ext/sub.mk | 18 + optee/optee_os/lib/libutils/ext/trace.c | 289 + .../isoc/arch/arm/arm32_aeabi_divmod.c | 151 + .../isoc/arch/arm/arm32_aeabi_divmod_a32.S | 24 + .../isoc/arch/arm/arm32_aeabi_ldivmod.c | 104 + .../isoc/arch/arm/arm32_aeabi_ldivmod_a32.S | 37 + .../isoc/arch/arm/arm32_aeabi_shift.c | 49 + .../isoc/arch/arm/arm32_aeabi_softfloat.c | 295 + .../lib/libutils/isoc/arch/arm/setjmp_a32.S | 281 + .../lib/libutils/isoc/arch/arm/setjmp_a64.S | 106 + .../isoc/arch/arm/softfloat/COPYING.txt | 37 + .../isoc/arch/arm/softfloat/README.html | 49 + .../isoc/arch/arm/softfloat/README.txt | 21 + .../arm/softfloat/arm32_include/platform.h | 41 + .../softfloat/build/Linux-386-GCC/Makefile | 275 + .../softfloat/build/Linux-386-GCC/platform.h | 45 + .../build/Linux-386-SSE2-GCC/Makefile | 275 + .../build/Linux-386-SSE2-GCC/platform.h | 45 + .../softfloat/build/Linux-x86_64-GCC/Makefile | 336 + .../build/Linux-x86_64-GCC/platform.h | 45 + .../arm/softfloat/build/Win32-MinGW/Makefile | 275 + .../softfloat/build/Win32-MinGW/platform.h | 45 + .../softfloat/build/Win32-SSE2-MinGW/Makefile | 275 + .../build/Win32-SSE2-MinGW/platform.h | 45 + .../softfloat/build/Win64-MinGW-w64/Makefile | 336 + .../build/Win64-MinGW-w64/platform.h | 45 + .../build/template-FAST_INT64/Makefile | 337 + .../build/template-FAST_INT64/platform.h | 47 + .../build/template-not-FAST_INT64/Makefile | 275 + .../build/template-not-FAST_INT64/platform.h | 47 + .../arm/softfloat/doc/SoftFloat-history.html | 155 + .../arm/softfloat/doc/SoftFloat-source.html | 590 + .../arch/arm/softfloat/doc/SoftFloat.html | 1453 ++ .../source/8086-SSE/extF80M_isSignalingNaN.c | 58 + .../source/8086-SSE/f128M_isSignalingNaN.c | 61 + .../source/8086-SSE/s_commonNaNToExtF80M.c | 57 + .../source/8086-SSE/s_commonNaNToExtF80UI.c | 57 + .../source/8086-SSE/s_commonNaNToF128M.c | 57 + .../source/8086-SSE/s_commonNaNToF128UI.c | 56 + .../source/8086-SSE/s_commonNaNToF32UI.c | 52 + .../source/8086-SSE/s_commonNaNToF64UI.c | 54 + .../source/8086-SSE/s_extF80MToCommonNaN.c | 63 + .../source/8086-SSE/s_extF80UIToCommonNaN.c | 63 + .../source/8086-SSE/s_f128MToCommonNaN.c | 63 + .../source/8086-SSE/s_f128UIToCommonNaN.c | 66 + .../source/8086-SSE/s_f32UIToCommonNaN.c | 60 + .../source/8086-SSE/s_f64UIToCommonNaN.c | 60 + .../source/8086-SSE/s_propagateNaNExtF80M.c | 108 + .../source/8086-SSE/s_propagateNaNExtF80UI.c | 107 + .../source/8086-SSE/s_propagateNaNF128M.c | 77 + .../source/8086-SSE/s_propagateNaNF128UI.c | 82 + .../source/8086-SSE/s_propagateNaNF32UI.c | 64 + .../source/8086-SSE/s_propagateNaNF64UI.c | 64 + .../source/8086-SSE/softfloat_raiseFlags.c | 53 + .../softfloat/source/8086-SSE/specialize.h | 319 + .../arch/arm/softfloat/source/8086-SSE/sub.mk | 7 + .../source/8086/extF80M_isSignalingNaN.c | 58 + .../source/8086/f128M_isSignalingNaN.c | 61 + .../source/8086/s_commonNaNToExtF80M.c | 57 + .../source/8086/s_commonNaNToExtF80UI.c | 57 + .../source/8086/s_commonNaNToF128M.c | 57 + .../source/8086/s_commonNaNToF128UI.c | 56 + .../source/8086/s_commonNaNToF32UI.c | 52 + .../source/8086/s_commonNaNToF64UI.c | 54 + .../source/8086/s_extF80MToCommonNaN.c | 63 + .../source/8086/s_extF80UIToCommonNaN.c | 63 + .../source/8086/s_f128MToCommonNaN.c | 63 + .../source/8086/s_f128UIToCommonNaN.c | 66 + .../source/8086/s_f32UIToCommonNaN.c | 60 + .../source/8086/s_f64UIToCommonNaN.c | 60 + .../source/8086/s_propagateNaNExtF80M.c | 108 + .../source/8086/s_propagateNaNExtF80UI.c | 107 + .../source/8086/s_propagateNaNF128M.c | 109 + .../source/8086/s_propagateNaNF128UI.c | 106 + .../source/8086/s_propagateNaNF32UI.c | 85 + .../source/8086/s_propagateNaNF64UI.c | 85 + .../source/8086/softfloat_raiseFlags.c | 53 + .../arm/softfloat/source/8086/specialize.h | 319 + .../arch/arm/softfloat/source/extF80M_add.c | 101 + .../arch/arm/softfloat/source/extF80M_div.c | 195 + .../arch/arm/softfloat/source/extF80M_eq.c | 99 + .../softfloat/source/extF80M_eq_signaling.c | 93 + .../arch/arm/softfloat/source/extF80M_le.c | 107 + .../arm/softfloat/source/extF80M_le_quiet.c | 113 + .../arch/arm/softfloat/source/extF80M_lt.c | 107 + .../arm/softfloat/source/extF80M_lt_quiet.c | 113 + .../arch/arm/softfloat/source/extF80M_mul.c | 140 + .../arch/arm/softfloat/source/extF80M_rem.c | 205 + .../arm/softfloat/source/extF80M_roundToInt.c | 170 + .../arch/arm/softfloat/source/extF80M_sqrt.c | 177 + .../arch/arm/softfloat/source/extF80M_sub.c | 101 + .../arm/softfloat/source/extF80M_to_f128M.c | 126 + .../arm/softfloat/source/extF80M_to_f32.c | 111 + .../arm/softfloat/source/extF80M_to_f64.c | 113 + .../arm/softfloat/source/extF80M_to_i32.c | 99 + .../source/extF80M_to_i32_r_minMag.c | 121 + .../arm/softfloat/source/extF80M_to_i64.c | 96 + .../source/extF80M_to_i64_r_minMag.c | 118 + .../arm/softfloat/source/extF80M_to_ui32.c | 98 + .../source/extF80M_to_ui32_r_minMag.c | 106 + .../arm/softfloat/source/extF80M_to_ui64.c | 91 + .../source/extF80M_to_ui64_r_minMag.c | 103 + .../arch/arm/softfloat/source/extF80_add.c | 81 + .../arch/arm/softfloat/source/extF80_div.c | 204 + .../arch/arm/softfloat/source/extF80_eq.c | 74 + .../softfloat/source/extF80_eq_signaling.c | 68 + .../softfloat/source/extF80_isSignalingNaN.c | 52 + .../arch/arm/softfloat/source/extF80_le.c | 74 + .../arm/softfloat/source/extF80_le_quiet.c | 79 + .../arch/arm/softfloat/source/extF80_lt.c | 74 + .../arm/softfloat/source/extF80_lt_quiet.c | 79 + .../arch/arm/softfloat/source/extF80_mul.c | 159 + .../arch/arm/softfloat/source/extF80_rem.c | 228 + .../arm/softfloat/source/extF80_roundToInt.c | 148 + .../arch/arm/softfloat/source/extF80_sqrt.c | 169 + .../arch/arm/softfloat/source/extF80_sub.c | 81 + .../arm/softfloat/source/extF80_to_f128.c | 76 + .../arch/arm/softfloat/source/extF80_to_f32.c | 87 + .../arch/arm/softfloat/source/extF80_to_f64.c | 87 + .../arch/arm/softfloat/source/extF80_to_i32.c | 66 + .../softfloat/source/extF80_to_i32_r_minMag.c | 94 + .../arch/arm/softfloat/source/extF80_to_i64.c | 81 + .../softfloat/source/extF80_to_i64_r_minMag.c | 88 + .../arm/softfloat/source/extF80_to_ui32.c | 65 + .../source/extF80_to_ui32_r_minMag.c | 75 + .../arm/softfloat/source/extF80_to_ui64.c | 74 + .../source/extF80_to_ui64_r_minMag.c | 75 + .../arch/arm/softfloat/source/f128M_add.c | 98 + .../arch/arm/softfloat/source/f128M_div.c | 188 + .../isoc/arch/arm/softfloat/source/f128M_eq.c | 101 + .../arm/softfloat/source/f128M_eq_signaling.c | 93 + .../isoc/arch/arm/softfloat/source/f128M_le.c | 94 + .../arm/softfloat/source/f128M_le_quiet.c | 97 + .../isoc/arch/arm/softfloat/source/f128M_lt.c | 94 + .../arm/softfloat/source/f128M_lt_quiet.c | 97 + .../arch/arm/softfloat/source/f128M_mul.c | 159 + .../arch/arm/softfloat/source/f128M_mulAdd.c | 93 + .../arch/arm/softfloat/source/f128M_rem.c | 183 + .../arm/softfloat/source/f128M_roundToInt.c | 216 + .../arch/arm/softfloat/source/f128M_sqrt.c | 217 + .../arch/arm/softfloat/source/f128M_sub.c | 98 + .../arm/softfloat/source/f128M_to_extF80M.c | 102 + .../arch/arm/softfloat/source/f128M_to_f32.c | 100 + .../arch/arm/softfloat/source/f128M_to_f64.c | 103 + .../arch/arm/softfloat/source/f128M_to_i32.c | 88 + .../softfloat/source/f128M_to_i32_r_minMag.c | 96 + .../arch/arm/softfloat/source/f128M_to_i64.c | 99 + .../softfloat/source/f128M_to_i64_r_minMag.c | 113 + .../arch/arm/softfloat/source/f128M_to_ui32.c | 82 + .../softfloat/source/f128M_to_ui32_r_minMag.c | 90 + .../arch/arm/softfloat/source/f128M_to_ui64.c | 90 + .../softfloat/source/f128M_to_ui64_r_minMag.c | 98 + .../isoc/arch/arm/softfloat/source/f128_add.c | 79 + .../isoc/arch/arm/softfloat/source/f128_div.c | 200 + .../isoc/arch/arm/softfloat/source/f128_eq.c | 74 + .../arm/softfloat/source/f128_eq_signaling.c | 68 + .../softfloat/source/f128_isSignalingNaN.c | 52 + .../isoc/arch/arm/softfloat/source/f128_le.c | 73 + .../arch/arm/softfloat/source/f128_le_quiet.c | 79 + .../isoc/arch/arm/softfloat/source/f128_lt.c | 73 + .../arch/arm/softfloat/source/f128_lt_quiet.c | 79 + .../isoc/arch/arm/softfloat/source/f128_mul.c | 164 + .../arch/arm/softfloat/source/f128_mulAdd.c | 64 + .../isoc/arch/arm/softfloat/source/f128_rem.c | 193 + .../arm/softfloat/source/f128_roundToInt.c | 161 + .../arch/arm/softfloat/source/f128_sqrt.c | 195 + .../isoc/arch/arm/softfloat/source/f128_sub.c | 79 + .../arm/softfloat/source/f128_to_extF80.c | 100 + .../arch/arm/softfloat/source/f128_to_f32.c | 86 + .../arch/arm/softfloat/source/f128_to_f64.c | 91 + .../arch/arm/softfloat/source/f128_to_i32.c | 70 + .../softfloat/source/f128_to_i32_r_minMag.c | 91 + .../arch/arm/softfloat/source/f128_to_i64.c | 86 + .../softfloat/source/f128_to_i64_r_minMag.c | 102 + .../arch/arm/softfloat/source/f128_to_ui32.c | 70 + .../softfloat/source/f128_to_ui32_r_minMag.c | 77 + .../arch/arm/softfloat/source/f128_to_ui64.c | 84 + .../softfloat/source/f128_to_ui64_r_minMag.c | 89 + .../isoc/arch/arm/softfloat/source/f32_add.c | 75 + .../isoc/arch/arm/softfloat/source/f32_div.c | 181 + .../isoc/arch/arm/softfloat/source/f32_eq.c | 67 + .../arm/softfloat/source/f32_eq_signaling.c | 62 + .../arm/softfloat/source/f32_isSignalingNaN.c | 52 + .../isoc/arch/arm/softfloat/source/f32_le.c | 67 + .../arch/arm/softfloat/source/f32_le_quiet.c | 72 + .../isoc/arch/arm/softfloat/source/f32_lt.c | 67 + .../arch/arm/softfloat/source/f32_lt_quiet.c | 72 + .../isoc/arch/arm/softfloat/source/f32_mul.c | 124 + .../arch/arm/softfloat/source/f32_mulAdd.c | 61 + .../isoc/arch/arm/softfloat/source/f32_rem.c | 169 + .../arm/softfloat/source/f32_roundToInt.c | 112 + .../isoc/arch/arm/softfloat/source/f32_sqrt.c | 122 + .../isoc/arch/arm/softfloat/source/f32_sub.c | 75 + .../arch/arm/softfloat/source/f32_to_extF80.c | 94 + .../arm/softfloat/source/f32_to_extF80M.c | 104 + .../arch/arm/softfloat/source/f32_to_f128.c | 89 + .../arch/arm/softfloat/source/f32_to_f128M.c | 106 + .../arch/arm/softfloat/source/f32_to_f64.c | 86 + .../arch/arm/softfloat/source/f32_to_i32.c | 69 + .../softfloat/source/f32_to_i32_r_minMag.c | 81 + .../arch/arm/softfloat/source/f32_to_i64.c | 91 + .../softfloat/source/f32_to_i64_r_minMag.c | 86 + .../arch/arm/softfloat/source/f32_to_ui32.c | 68 + .../softfloat/source/f32_to_ui32_r_minMag.c | 76 + .../arch/arm/softfloat/source/f32_to_ui64.c | 112 + .../softfloat/source/f32_to_ui64_r_minMag.c | 78 + .../isoc/arch/arm/softfloat/source/f64_add.c | 75 + .../isoc/arch/arm/softfloat/source/f64_div.c | 173 + .../isoc/arch/arm/softfloat/source/f64_eq.c | 67 + .../arm/softfloat/source/f64_eq_signaling.c | 62 + .../arm/softfloat/source/f64_isSignalingNaN.c | 52 + .../isoc/arch/arm/softfloat/source/f64_le.c | 68 + .../arch/arm/softfloat/source/f64_le_quiet.c | 73 + .../isoc/arch/arm/softfloat/source/f64_lt.c | 68 + .../arch/arm/softfloat/source/f64_lt_quiet.c | 73 + .../isoc/arch/arm/softfloat/source/f64_mul.c | 151 + .../arch/arm/softfloat/source/f64_mulAdd.c | 61 + .../isoc/arch/arm/softfloat/source/f64_rem.c | 190 + .../arm/softfloat/source/f64_roundToInt.c | 112 + .../isoc/arch/arm/softfloat/source/f64_sqrt.c | 134 + .../isoc/arch/arm/softfloat/source/f64_sub.c | 75 + .../arch/arm/softfloat/source/f64_to_extF80.c | 94 + .../arm/softfloat/source/f64_to_extF80M.c | 104 + .../arch/arm/softfloat/source/f64_to_f128.c | 91 + .../arch/arm/softfloat/source/f64_to_f128M.c | 118 + .../arch/arm/softfloat/source/f64_to_f32.c | 81 + .../arch/arm/softfloat/source/f64_to_i32.c | 65 + .../softfloat/source/f64_to_i32_r_minMag.c | 87 + .../arch/arm/softfloat/source/f64_to_i64.c | 108 + .../softfloat/source/f64_to_i64_r_minMag.c | 88 + .../arch/arm/softfloat/source/f64_to_ui32.c | 64 + .../softfloat/source/f64_to_ui32_r_minMag.c | 76 + .../arch/arm/softfloat/source/f64_to_ui64.c | 98 + .../softfloat/source/f64_to_ui64_r_minMag.c | 81 + .../arch/arm/softfloat/source/i32_to_extF80.c | 66 + .../arm/softfloat/source/i32_to_extF80M.c | 79 + .../arch/arm/softfloat/source/i32_to_f128.c | 65 + .../arch/arm/softfloat/source/i32_to_f128M.c | 82 + .../arch/arm/softfloat/source/i32_to_f32.c | 59 + .../arch/arm/softfloat/source/i32_to_f64.c | 66 + .../arch/arm/softfloat/source/i64_to_extF80.c | 66 + .../arm/softfloat/source/i64_to_extF80M.c | 79 + .../arch/arm/softfloat/source/i64_to_f128.c | 73 + .../arch/arm/softfloat/source/i64_to_f128M.c | 93 + .../arch/arm/softfloat/source/i64_to_f32.c | 71 + .../arch/arm/softfloat/source/i64_to_f64.c | 59 + .../arm/softfloat/source/include/internals.h | 260 + .../softfloat/source/include/primitiveTypes.h | 86 + .../arm/softfloat/source/include/primitives.h | 1136 + .../arm/softfloat/source/include/softfloat.h | 323 + .../source/include/softfloat_types.h | 81 + .../isoc/arch/arm/softfloat/source/s_add128.c | 56 + .../arch/arm/softfloat/source/s_add256M.c | 66 + .../arch/arm/softfloat/source/s_addCarryM.c | 71 + .../arm/softfloat/source/s_addComplCarryM.c | 71 + .../arch/arm/softfloat/source/s_addExtF80M.c | 187 + .../arch/arm/softfloat/source/s_addF128M.c | 212 + .../isoc/arch/arm/softfloat/source/s_addM.c | 71 + .../arm/softfloat/source/s_addMagsExtF80.c | 157 + .../arch/arm/softfloat/source/s_addMagsF128.c | 155 + .../arch/arm/softfloat/source/s_addMagsF32.c | 110 + .../arch/arm/softfloat/source/s_addMagsF64.c | 112 + .../arm/softfloat/source/s_approxRecip32_1.c | 72 + .../softfloat/source/s_approxRecipSqrt32_1.c | 78 + .../arch/arm/softfloat/source/s_compare128M.c | 63 + .../arch/arm/softfloat/source/s_compare96M.c | 63 + .../source/s_compareNonnormExtF80M.c | 112 + .../softfloat/source/s_countLeadingZeros32.c | 65 + .../softfloat/source/s_countLeadingZeros64.c | 74 + .../softfloat/source/s_countLeadingZeros8.c | 60 + .../isoc/arch/arm/softfloat/source/s_eq128.c | 52 + .../arm/softfloat/source/s_invalidExtF80M.c | 50 + .../arm/softfloat/source/s_invalidF128M.c | 54 + .../arch/arm/softfloat/source/s_isNaNF128M.c | 58 + .../isoc/arch/arm/softfloat/source/s_le128.c | 52 + .../isoc/arch/arm/softfloat/source/s_lt128.c | 52 + .../arch/arm/softfloat/source/s_mul128By32.c | 59 + .../arm/softfloat/source/s_mul128MTo256M.c | 101 + .../arm/softfloat/source/s_mul128To256M.c | 72 + .../source/s_mul64ByShifted32To128.c | 57 + .../arch/arm/softfloat/source/s_mul64To128.c | 67 + .../arch/arm/softfloat/source/s_mul64To128M.c | 69 + .../arch/arm/softfloat/source/s_mulAddF128.c | 354 + .../arch/arm/softfloat/source/s_mulAddF128M.c | 383 + .../arch/arm/softfloat/source/s_mulAddF32.c | 205 + .../arch/arm/softfloat/source/s_mulAddF64.c | 497 + .../isoc/arch/arm/softfloat/source/s_negXM.c | 64 + .../arm/softfloat/source/s_normExtF80SigM.c | 53 + .../source/s_normRoundPackMToExtF80M.c | 79 + .../source/s_normRoundPackMToF128M.c | 74 + .../source/s_normRoundPackToExtF80.c | 72 + .../softfloat/source/s_normRoundPackToF128.c | 83 + .../softfloat/source/s_normRoundPackToF32.c | 59 + .../softfloat/source/s_normRoundPackToF64.c | 59 + .../source/s_normSubnormalExtF80Sig.c | 53 + .../softfloat/source/s_normSubnormalF128Sig.c | 66 + .../source/s_normSubnormalF128SigM.c | 62 + .../softfloat/source/s_normSubnormalF32Sig.c | 53 + .../softfloat/source/s_normSubnormalF64Sig.c | 53 + .../arm/softfloat/source/s_remStepMBy32.c | 88 + .../softfloat/source/s_roundPackMToExtF80M.c | 228 + .../softfloat/source/s_roundPackMToF128M.c | 160 + .../arm/softfloat/source/s_roundPackMToI64.c | 86 + .../arm/softfloat/source/s_roundPackMToUI64.c | 80 + .../softfloat/source/s_roundPackToExtF80.c | 215 + .../arm/softfloat/source/s_roundPackToF128.c | 151 + .../arm/softfloat/source/s_roundPackToF32.c | 94 + .../arm/softfloat/source/s_roundPackToF64.c | 97 + .../arm/softfloat/source/s_roundPackToI32.c | 80 + .../arm/softfloat/source/s_roundPackToI64.c | 87 + .../arm/softfloat/source/s_roundPackToUI32.c | 76 + .../arm/softfloat/source/s_roundPackToUI64.c | 81 + .../arch/arm/softfloat/source/s_shiftLeftM.c | 92 + .../softfloat/source/s_shiftNormSigF128M.c | 79 + .../arm/softfloat/source/s_shiftRightJam128.c | 70 + .../source/s_shiftRightJam128Extra.c | 78 + .../softfloat/source/s_shiftRightJam256M.c | 127 + .../arm/softfloat/source/s_shiftRightJam32.c | 53 + .../arm/softfloat/source/s_shiftRightJam64.c | 53 + .../softfloat/source/s_shiftRightJam64Extra.c | 63 + .../arm/softfloat/source/s_shiftRightJamM.c | 102 + .../arch/arm/softfloat/source/s_shiftRightM.c | 92 + .../softfloat/source/s_shortShiftLeft128.c | 56 + .../source/s_shortShiftLeft64To96M.c | 57 + .../arm/softfloat/source/s_shortShiftLeftM.c | 71 + .../softfloat/source/s_shortShiftRight128.c | 56 + .../source/s_shortShiftRightExtendM.c | 74 + .../source/s_shortShiftRightJam128.c | 61 + .../source/s_shortShiftRightJam128Extra.c | 60 + .../softfloat/source/s_shortShiftRightJam64.c | 51 + .../source/s_shortShiftRightJam64Extra.c | 57 + .../softfloat/source/s_shortShiftRightJamM.c | 73 + .../arm/softfloat/source/s_shortShiftRightM.c | 71 + .../isoc/arch/arm/softfloat/source/s_sub128.c | 56 + .../isoc/arch/arm/softfloat/source/s_sub1XM.c | 61 + .../arch/arm/softfloat/source/s_sub256M.c | 66 + .../isoc/arch/arm/softfloat/source/s_subM.c | 71 + .../arm/softfloat/source/s_subMagsExtF80.c | 159 + .../arch/arm/softfloat/source/s_subMagsF128.c | 140 + .../arch/arm/softfloat/source/s_subMagsF32.c | 116 + .../arch/arm/softfloat/source/s_subMagsF64.c | 116 + .../source/s_tryPropagateNaNExtF80M.c | 65 + .../softfloat/source/s_tryPropagateNaNF128M.c | 56 + .../arm/softfloat/source/softfloat_state.c | 49 + .../isoc/arch/arm/softfloat/source/sub.mk | 65 + .../arm/softfloat/source/ui32_to_extF80.c | 60 + .../arm/softfloat/source/ui32_to_extF80M.c | 75 + .../arch/arm/softfloat/source/ui32_to_f128.c | 61 + .../arch/arm/softfloat/source/ui32_to_f128M.c | 77 + .../arch/arm/softfloat/source/ui32_to_f32.c | 58 + .../arch/arm/softfloat/source/ui32_to_f64.c | 61 + .../arm/softfloat/source/ui64_to_extF80.c | 60 + .../arm/softfloat/source/ui64_to_extF80M.c | 75 + .../arch/arm/softfloat/source/ui64_to_f128.c | 69 + .../arch/arm/softfloat/source/ui64_to_f128M.c | 88 + .../arch/arm/softfloat/source/ui64_to_f32.c | 65 + .../arch/arm/softfloat/source/ui64_to_f64.c | 60 + .../libutils/isoc/arch/arm/softfloat/sub.mk | 3 + .../lib/libutils/isoc/arch/arm/sub.mk | 32 + .../lib/libutils/isoc/arch/riscv/setjmp_rv.S | 77 + .../lib/libutils/isoc/arch/riscv/sub.mk | 1 + optee/optee_os/lib/libutils/isoc/bget.c | 1764 ++ optee/optee_os/lib/libutils/isoc/bget.doc | 338 + optee/optee_os/lib/libutils/isoc/bget.h | 55 + .../optee_os/lib/libutils/isoc/bget_malloc.c | 1140 + optee/optee_os/lib/libutils/isoc/fp.c | 16 + optee/optee_os/lib/libutils/isoc/fputc.c | 15 + optee/optee_os/lib/libutils/isoc/fputs.c | 17 + optee/optee_os/lib/libutils/isoc/fwrite.c | 22 + .../lib/libutils/isoc/include/assert.h | 58 + .../lib/libutils/isoc/include/ctype.h | 22 + .../lib/libutils/isoc/include/inttypes.h | 54 + .../lib/libutils/isoc/include/limits.h | 52 + .../lib/libutils/isoc/include/malloc.h | 180 + .../lib/libutils/isoc/include/memory.h | 9 + .../lib/libutils/isoc/include/setjmp.h | 76 + .../lib/libutils/isoc/include/signal.h | 8 + .../lib/libutils/isoc/include/stdint.h | 208 + .../lib/libutils/isoc/include/stdio.h | 45 + .../lib/libutils/isoc/include/stdlib.h | 32 + .../lib/libutils/isoc/include/string.h | 37 + .../lib/libutils/isoc/include/strings.h | 10 + .../lib/libutils/isoc/include/sys/cdefs.h | 24 + .../lib/libutils/isoc/include/sys/queue.h | 721 + .../lib/libutils/isoc/include/sys/types.h | 10 + .../optee_os/lib/libutils/isoc/include/time.h | 13 + .../lib/libutils/isoc/include/unistd.h | 17 + .../lib/libutils/isoc/include/wchar.h | 8 + optee/optee_os/lib/libutils/isoc/isalnum.c | 10 + optee/optee_os/lib/libutils/isoc/isalpha.c | 14 + optee/optee_os/lib/libutils/isoc/iscntrl.c | 12 + optee/optee_os/lib/libutils/isoc/isdigit.c | 12 + optee/optee_os/lib/libutils/isoc/isgraph.c | 12 + optee/optee_os/lib/libutils/isoc/islower.c | 10 + optee/optee_os/lib/libutils/isoc/isprint.c | 12 + optee/optee_os/lib/libutils/isoc/ispunct.c | 10 + optee/optee_os/lib/libutils/isoc/isspace.c | 10 + optee/optee_os/lib/libutils/isoc/isupper.c | 10 + optee/optee_os/lib/libutils/isoc/isxdigit.c | 16 + .../optee_os/lib/libutils/isoc/newlib/_ansi.h | 129 + optee/optee_os/lib/libutils/isoc/newlib/abs.c | 76 + .../optee_os/lib/libutils/isoc/newlib/bcmp.c | 42 + .../lib/libutils/isoc/newlib/memchr.c | 160 + .../lib/libutils/isoc/newlib/memcmp.c | 136 + .../lib/libutils/isoc/newlib/memcpy.c | 135 + .../lib/libutils/isoc/newlib/memmove.c | 157 + .../lib/libutils/isoc/newlib/memset.c | 129 + .../lib/libutils/isoc/newlib/str-two-way.h | 447 + .../lib/libutils/isoc/newlib/strchr.c | 157 + .../lib/libutils/isoc/newlib/strcmp.c | 142 + .../lib/libutils/isoc/newlib/strcpy.c | 132 + .../lib/libutils/isoc/newlib/strlen.c | 120 + .../lib/libutils/isoc/newlib/strncmp.c | 156 + .../lib/libutils/isoc/newlib/strncpy.c | 159 + .../lib/libutils/isoc/newlib/strnlen.c | 81 + .../lib/libutils/isoc/newlib/strrchr.c | 91 + .../lib/libutils/isoc/newlib/strstr.c | 154 + .../lib/libutils/isoc/newlib/strtok_r.c | 97 + .../lib/libutils/isoc/newlib/strtoul.c | 227 + .../optee_os/lib/libutils/isoc/newlib/sub.mk | 28 + optee/optee_os/lib/libutils/isoc/qsort.c | 151 + optee/optee_os/lib/libutils/isoc/snprintf.c | 24 + optee/optee_os/lib/libutils/isoc/sprintf.c | 40 + .../optee_os/lib/libutils/isoc/stack_check.c | 29 + optee/optee_os/lib/libutils/isoc/strdup.c | 16 + optee/optee_os/lib/libutils/isoc/strndup.c | 18 + optee/optee_os/lib/libutils/isoc/sub.mk | 40 + optee/optee_os/lib/libutils/isoc/tolower.c | 12 + optee/optee_os/lib/libutils/isoc/toupper.c | 12 + optee/optee_os/lib/libutils/isoc/write.c | 16 + optee/optee_os/lib/libutils/sub.mk | 2 + optee/optee_os/mk/aosp_optee.mk | 136 + optee/optee_os/mk/cc-option.mk | 17 + optee/optee_os/mk/checkconf.mk | 193 + optee/optee_os/mk/clang.mk | 53 + optee/optee_os/mk/cleandirs.mk | 42 + optee/optee_os/mk/cleanvars.mk | 12 + optee/optee_os/mk/compile.mk | 306 + optee/optee_os/mk/config.mk | 1084 + optee/optee_os/mk/gcc.mk | 36 + optee/optee_os/mk/lib.mk | 101 + optee/optee_os/mk/subdir.mk | 184 + .../optee_os/prebuilt/t234/libcommon_crypto.a | Bin 0 -> 387062 bytes optee/optee_os/scripts/arm32_sysreg.py | 244 + optee/optee_os/scripts/bin_to_c.py | 74 + optee/optee_os/scripts/checkpatch.sh | 112 + optee/optee_os/scripts/checkpatch_inc.sh | 50 + optee/optee_os/scripts/gen_ld_sects.py | 64 + optee/optee_os/scripts/gen_ldelf_hex.py | 152 + optee/optee_os/scripts/gen_stmm_hex.py | 59 + optee/optee_os/scripts/gen_tee_bin.py | 411 + optee/optee_os/scripts/get_maintainer.py | 319 + optee/optee_os/scripts/mem_usage.py | 177 + optee/optee_os/scripts/pem_to_pub_c.py | 71 + optee/optee_os/scripts/print_tee_hash.py | 81 + optee/optee_os/scripts/sign_encrypt.py | 968 + optee/optee_os/scripts/sign_helper_kms.py | 98 + optee/optee_os/scripts/symbolize.py | 568 + optee/optee_os/scripts/tee_bin_parser.py | 61 + optee/optee_os/scripts/ts_bin_to_c.py | 180 + optee/optee_os/scripts/update_changelog.py | 101 + optee/optee_os/ta/arch/arm/ta.ld.S | 104 + optee/optee_os/ta/arch/arm/ta_entry_a32.S | 23 + optee/optee_os/ta/arch/riscv/ta.ld.S | 94 + optee/optee_os/ta/avb/Makefile | 18 + optee/optee_os/ta/avb/entry.c | 402 + optee/optee_os/ta/avb/include/ta_avb.h | 64 + optee/optee_os/ta/avb/sub.mk | 3 + optee/optee_os/ta/avb/user_ta.mk | 2 + .../optee_os/ta/avb/user_ta_header_defines.h | 17 + optee/optee_os/ta/link.mk | 122 + optee/optee_os/ta/link_shlib.mk | 54 + optee/optee_os/ta/mk/build-user-ta.mk | 78 + optee/optee_os/ta/mk/ta_dev_kit.mk | 154 + optee/optee_os/ta/pkcs11/Android.mk | 3 + optee/optee_os/ta/pkcs11/Makefile | 9 + optee/optee_os/ta/pkcs11/include/pkcs11_ta.h | 1324 ++ .../ta/pkcs11/scripts/dump_ec_curve_params.sh | 30 + .../ta/pkcs11/scripts/verify-helpers.sh | 103 + optee/optee_os/ta/pkcs11/src/attributes.c | 457 + optee/optee_os/ta/pkcs11/src/attributes.h | 322 + optee/optee_os/ta/pkcs11/src/entry.c | 373 + optee/optee_os/ta/pkcs11/src/handle.c | 101 + optee/optee_os/ta/pkcs11/src/handle.h | 50 + optee/optee_os/ta/pkcs11/src/object.c | 1237 ++ optee/optee_os/ta/pkcs11/src/object.h | 90 + .../optee_os/ta/pkcs11/src/persistent_token.c | 714 + .../ta/pkcs11/src/pkcs11_attributes.c | 2576 +++ .../ta/pkcs11/src/pkcs11_attributes.h | 211 + optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c | 833 + optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h | 105 + optee/optee_os/ta/pkcs11/src/pkcs11_token.c | 1659 ++ optee/optee_os/ta/pkcs11/src/pkcs11_token.h | 353 + optee/optee_os/ta/pkcs11/src/processing.c | 1287 ++ optee/optee_os/ta/pkcs11/src/processing.h | 270 + optee/optee_os/ta/pkcs11/src/processing_aes.c | 52 + .../optee_os/ta/pkcs11/src/processing_asymm.c | 1112 + .../ta/pkcs11/src/processing_digest.c | 219 + optee/optee_os/ta/pkcs11/src/processing_ec.c | 948 + optee/optee_os/ta/pkcs11/src/processing_rsa.c | 777 + .../optee_os/ta/pkcs11/src/processing_symm.c | 1145 + .../optee_os/ta/pkcs11/src/sanitize_object.c | 431 + .../optee_os/ta/pkcs11/src/sanitize_object.h | 46 + optee/optee_os/ta/pkcs11/src/serializer.c | 195 + optee/optee_os/ta/pkcs11/src/serializer.h | 140 + optee/optee_os/ta/pkcs11/src/sub.mk | 18 + .../ta/pkcs11/src/token_capabilities.c | 462 + .../ta/pkcs11/src/token_capabilities.h | 40 + .../ta/pkcs11/src/user_ta_header_defines.h | 26 + optee/optee_os/ta/pkcs11/sub.mk | 15 + optee/optee_os/ta/pkcs11/user_ta.mk | 8 + optee/optee_os/ta/ta.mk | 215 + optee/optee_os/ta/trusted_keys/entry.c | 344 + .../ta/trusted_keys/include/trusted_keys.h | 35 + optee/optee_os/ta/trusted_keys/sub.mk | 3 + optee/optee_os/ta/trusted_keys/user_ta.mk | 1 + .../ta/trusted_keys/user_ta_header_defines.h | 20 + optee/optee_os/ta/user_ta_header.c | 214 + optee/optee_os/typedefs.checkpatch | 41 + optee/optee_test/.github/issue_template.md | 21 + .../.github/pull_request_template.md | 19 + optee/optee_test/.github/workflows/ci.yml | 34 + .../.github/workflows/stale_issue.yml | 28 + optee/optee_test/Android.mk | 170 + optee/optee_test/CMakeLists.txt | 34 + optee/optee_test/CMakeToolchain.txt | 3 + optee/optee_test/LICENSE.md | 5 + optee/optee_test/Makefile | 95 + optee/optee_test/README.md | 10 + optee/optee_test/cert/README.txt | 20 + optee/optee_test/cert/ca.crt | 21 + optee/optee_test/cert/ca.key | 27 + optee/optee_test/cert/ca.srl | 1 + optee/optee_test/cert/mid.conf | 14 + optee/optee_test/cert/mid.crt | 19 + optee/optee_test/cert/mid.csr | 17 + optee/optee_test/cert/mid.ext | 1 + optee/optee_test/cert/mid.key | 28 + optee/optee_test/cert/mid.srl | 1 + optee/optee_test/cert/my.conf | 13 + optee/optee_test/cert/my.crt | 19 + optee/optee_test/cert/my.csr | 17 + optee/optee_test/cert/my.key | 28 + .../host/openssl/include/openssl/aes.h | 149 + .../host/openssl/include/openssl/asn1.h | 1420 ++ .../host/openssl/include/openssl/asn1_mac.h | 579 + .../host/openssl/include/openssl/asn1t.h | 973 + .../host/openssl/include/openssl/bio.h | 883 + .../host/openssl/include/openssl/blowfish.h | 130 + .../host/openssl/include/openssl/bn.h | 951 + .../host/openssl/include/openssl/buffer.h | 125 + .../host/openssl/include/openssl/camellia.h | 132 + .../host/openssl/include/openssl/cast.h | 107 + .../host/openssl/include/openssl/cmac.h | 82 + .../host/openssl/include/openssl/cms.h | 555 + .../host/openssl/include/openssl/comp.h | 83 + .../host/openssl/include/openssl/conf.h | 268 + .../host/openssl/include/openssl/conf_api.h | 89 + .../host/openssl/include/openssl/crypto.h | 661 + .../host/openssl/include/openssl/des.h | 257 + .../host/openssl/include/openssl/des_old.h | 497 + .../host/openssl/include/openssl/dh.h | 412 + .../host/openssl/include/openssl/dsa.h | 332 + .../host/openssl/include/openssl/dso.h | 451 + .../host/openssl/include/openssl/dtls1.h | 272 + .../host/openssl/include/openssl/e_os2.h | 328 + .../host/openssl/include/openssl/ebcdic.h | 26 + .../host/openssl/include/openssl/ec.h | 1282 ++ .../host/openssl/include/openssl/ecdh.h | 134 + .../host/openssl/include/openssl/ecdsa.h | 335 + .../host/openssl/include/openssl/engine.h | 960 + .../host/openssl/include/openssl/err.h | 390 + .../host/openssl/include/openssl/evp.h | 1628 ++ .../host/openssl/include/openssl/hmac.h | 109 + .../host/openssl/include/openssl/idea.h | 105 + .../host/openssl/include/openssl/krb5_asn.h | 240 + .../host/openssl/include/openssl/kssl.h | 197 + .../host/openssl/include/openssl/lhash.h | 240 + .../host/openssl/include/openssl/md4.h | 119 + .../host/openssl/include/openssl/md5.h | 119 + .../host/openssl/include/openssl/mdc2.h | 94 + .../host/openssl/include/openssl/modes.h | 163 + .../host/openssl/include/openssl/obj_mac.h | 4194 ++++ .../host/openssl/include/openssl/objects.h | 1143 + .../host/openssl/include/openssl/ocsp.h | 637 + .../openssl/include/openssl/opensslconf.h | 270 + .../host/openssl/include/openssl/opensslv.h | 97 + .../host/openssl/include/openssl/ossl_typ.h | 213 + .../host/openssl/include/openssl/pem.h | 617 + .../host/openssl/include/openssl/pem2.h | 70 + .../host/openssl/include/openssl/pkcs12.h | 342 + .../host/openssl/include/openssl/pkcs7.h | 481 + .../host/openssl/include/openssl/pqueue.h | 99 + .../host/openssl/include/openssl/rand.h | 150 + .../host/openssl/include/openssl/rc2.h | 103 + .../host/openssl/include/openssl/rc4.h | 88 + .../host/openssl/include/openssl/ripemd.h | 105 + .../host/openssl/include/openssl/rsa.h | 664 + .../host/openssl/include/openssl/safestack.h | 2672 +++ .../host/openssl/include/openssl/seed.h | 149 + .../host/openssl/include/openssl/sha.h | 214 + .../host/openssl/include/openssl/srp.h | 179 + .../host/openssl/include/openssl/srtp.h | 147 + .../host/openssl/include/openssl/ssl.h | 3163 +++ .../host/openssl/include/openssl/ssl2.h | 265 + .../host/openssl/include/openssl/ssl23.h | 84 + .../host/openssl/include/openssl/ssl3.h | 774 + .../host/openssl/include/openssl/stack.h | 107 + .../host/openssl/include/openssl/symhacks.h | 518 + .../host/openssl/include/openssl/tls1.h | 810 + .../host/openssl/include/openssl/ts.h | 865 + .../host/openssl/include/openssl/txt_db.h | 112 + .../host/openssl/include/openssl/ui.h | 415 + .../host/openssl/include/openssl/ui_compat.h | 88 + .../host/openssl/include/openssl/whrlpool.h | 41 + .../host/openssl/include/openssl/x509.h | 1330 ++ .../host/openssl/include/openssl/x509_vfy.h | 652 + .../host/openssl/include/openssl/x509v3.h | 1055 + .../host/openssl/lib/aarch64/libcrypto.a | Bin 0 -> 3403202 bytes .../host/openssl/lib/arm/libcrypto.a | Bin 0 -> 2800684 bytes .../host/supp_plugin/CMakeLists.txt | 11 + optee/optee_test/host/supp_plugin/Makefile | 24 + .../supp_plugin/include/test_supp_plugin.h | 17 + .../host/supp_plugin/test_supp_plugin.c | 93 + optee/optee_test/host/xtest/CMakeLists.txt | 147 + optee/optee_test/host/xtest/LICENSE | 339 + optee/optee_test/host/xtest/Makefile | 243 + .../optee_test/host/xtest/adbg/include/adbg.h | 259 + .../host/xtest/adbg/src/adbg_case.c | 358 + .../host/xtest/adbg/src/adbg_enum.c | 50 + .../host/xtest/adbg/src/adbg_expect.c | 282 + .../optee_test/host/xtest/adbg/src/adbg_int.h | 76 + .../optee_test/host/xtest/adbg/src/adbg_log.c | 80 + .../optee_test/host/xtest/adbg/src/adbg_run.c | 267 + .../host/xtest/adbg/src/security_utils_hex.c | 239 + .../host/xtest/adbg/src/security_utils_hex.h | 118 + optee/optee_test/host/xtest/aes_perf.c | 674 + optee/optee_test/host/xtest/benchmark_1000.c | 145 + optee/optee_test/host/xtest/benchmark_2000.c | 97 + optee/optee_test/host/xtest/crypto_common.h | 54 + optee/optee_test/host/xtest/ffa_spmc_1000.c | 535 + optee/optee_test/host/xtest/gp/TEE.xsl | 137 + .../host/xtest/gp/TEE_Crypto_API.xsl | 133 + .../host/xtest/gp/TEE_DataStorage_API.xsl | 148 + .../host/xtest/gp/TEE_Internal_API.xsl | 140 + .../host/xtest/gp/TEE_TimeArithm_API.xsl | 151 + .../host/xtest/gp/include/xml_client_api.h | 378 + .../host/xtest/gp/include/xml_common_api.h | 281 + .../host/xtest/gp/include/xml_crypto_api.h | 3589 +++ .../xtest/gp/include/xml_datastorage_api.h | 2017 ++ .../host/xtest/gp/include/xml_internal_api.h | 733 + .../xtest/gp/include/xml_timearithm_api.h | 1003 + ...002-TTAs-add-files-needed-to-compile.patch | 1637 ++ .../xtest/gp/patches/0003-TTA_TCF-patch.patch | 26 + .../patches/0004-TTA_Arithmetical-patch.patch | 26 + .../0005-GP_defs.h-enable-debug-prints.patch | 28 + ...-fix-CmdTEEGetPropertyA-_withoutEnum.patch | 192 + .../0007-TTAs-revert-to-v1.1-types.patch | 90 + .../host/xtest/gp/patches/0008-TEE.xml.patch | 38 + .../patches/0009-TEE_Internal_API.xml.patch | 96 + .../0010-TEE_DataStorage_API.xml.patch | 106 + .../gp/patches/0011-TEE_Crypto_API.xml.patch | 39 + ...EE_MemMove-from-CmdTEEGetPropertyAsX.patch | 34 + ...etTAPersistentTimeNotSet_and_SetTAPe.patch | 38 + ...bits-of-TEE_PropSetHandle-in-value.b.patch | 110 + ...lity-with-TEE-Internal-Core-API-v1.1.patch | 27 + .../optee_test/host/xtest/gp/prepare_suite.sh | 26 + optee/optee_test/host/xtest/hash_perf.c | 494 + .../xtest/include/uapi/linux/arm_ffa_user.h | 79 + optee/optee_test/host/xtest/install_ta.c | 156 + optee/optee_test/host/xtest/install_ta.h | 12 + .../host/xtest/nist/186-2ecdsatestvectors.h | 10518 +++++++++ .../host/xtest/nist/186-3dsatestvectors.h | 18471 ++++++++++++++++ .../host/xtest/nist/ecccdhtestvectors.h | 11245 ++++++++++ optee/optee_test/host/xtest/pkcs11_1000.c | 8749 ++++++++ optee/optee_test/host/xtest/rand_stream.c | 117 + optee/optee_test/host/xtest/rand_stream.h | 20 + optee/optee_test/host/xtest/regression_1000.c | 3274 +++ optee/optee_test/host/xtest/regression_2000.c | 929 + optee/optee_test/host/xtest/regression_4000.c | 6167 ++++++ .../host/xtest/regression_4000_data.h | 8929 ++++++++ optee/optee_test/host/xtest/regression_4100.c | 2770 +++ optee/optee_test/host/xtest/regression_5000.c | 515 + optee/optee_test/host/xtest/regression_6000.c | 2256 ++ optee/optee_test/host/xtest/regression_8000.c | 760 + optee/optee_test/host/xtest/regression_8100.c | 323 + optee/optee_test/host/xtest/sdp_basic.c | 697 + optee/optee_test/host/xtest/sdp_basic.h | 37 + optee/optee_test/host/xtest/sock_server.c | 396 + optee/optee_test/host/xtest/sock_server.h | 43 + optee/optee_test/host/xtest/stats.c | 331 + optee/optee_test/host/xtest/stats.h | 12 + optee/optee_test/host/xtest/xtest_helpers.c | 489 + optee/optee_test/host/xtest/xtest_helpers.h | 115 + optee/optee_test/host/xtest/xtest_main.c | 273 + optee/optee_test/host/xtest/xtest_test.c | 208 + optee/optee_test/host/xtest/xtest_test.h | 146 + .../host/xtest/xtest_uuid_helpers.c | 173 + .../host/xtest/xtest_uuid_helpers.h | 34 + optee/optee_test/scripts/checkpatch.sh | 7 + optee/optee_test/scripts/common.mk | 11 + optee/optee_test/scripts/file_to_c.py | 48 + optee/optee_test/scripts/rsp_to_gcm_test.py | 116 + optee/optee_test/ta/Android.mk | 2 + optee/optee_test/ta/CMakeLists.txt | 28 + optee/optee_test/ta/Makefile | 64 + optee/optee_test/ta/aes_perf/Android.mk | 4 + optee/optee_test/ta/aes_perf/Makefile | 4 + .../ta/aes_perf/include/ta_aes_perf.h | 38 + .../ta/aes_perf/include/ta_aes_perf_priv.h | 16 + .../aes_perf/include/user_ta_header_defines.h | 21 + optee/optee_test/ta/aes_perf/sub.mk | 3 + optee/optee_test/ta/aes_perf/ta_aes_perf.c | 291 + optee/optee_test/ta/aes_perf/ta_entry.c | 71 + optee/optee_test/ta/bti_test/Android.mk | 4 + optee/optee_test/ta/bti_test/Makefile | 2 + optee/optee_test/ta/bti_test/bti_stubs_a64.S | 46 + .../ta/bti_test/include/ta_arm_bti.h | 29 + .../ta/bti_test/include/ta_arm_bti_priv.h | 15 + .../bti_test/include/user_ta_header_defines.h | 18 + optee/optee_test/ta/bti_test/sub.mk | 7 + optee/optee_test/ta/bti_test/ta_arm_bti.c | 60 + optee/optee_test/ta/bti_test/ta_entry.c | 99 + optee/optee_test/ta/concurrent/Android.mk | 4 + optee/optee_test/ta/concurrent/Makefile | 2 + .../ta/concurrent/include/ta_concurrent.h | 45 + .../include/user_ta_header_defines.h | 19 + optee/optee_test/ta/concurrent/sub.mk | 2 + optee/optee_test/ta/concurrent/ta_entry.c | 153 + .../optee_test/ta/concurrent_large/Android.mk | 4 + optee/optee_test/ta/concurrent_large/Makefile | 2 + .../include/ta_concurrent_large.h | 16 + .../include/user_ta_header_defines.h | 19 + optee/optee_test/ta/concurrent_large/sub.mk | 3 + .../optee_test/ta/concurrent_large/ta_entry.c | 153 + .../optee_test/ta/create_fail_test/Android.mk | 4 + optee/optee_test/ta/create_fail_test/Makefile | 2 + .../include/ta_create_fail_test.h | 15 + .../include/user_ta_header_defines.h | 18 + optee/optee_test/ta/create_fail_test/sub.mk | 2 + .../optee_test/ta/create_fail_test/ta_entry.c | 53 + optee/optee_test/ta/crypt/Android.mk | 4 + optee/optee_test/ta/crypt/Makefile | 2 + optee/optee_test/ta/crypt/aes_impl.c | 1249 ++ optee/optee_test/ta/crypt/aes_taf.c | 101 + optee/optee_test/ta/crypt/arith_taf.c | 622 + optee/optee_test/ta/crypt/cryp_taf.c | 824 + optee/optee_test/ta/crypt/derive_key_taf.c | 219 + optee/optee_test/ta/crypt/handle.c | 79 + optee/optee_test/ta/crypt/handle.h | 46 + optee/optee_test/ta/crypt/include/aes_impl.h | 34 + optee/optee_test/ta/crypt/include/aes_taf.h | 20 + optee/optee_test/ta/crypt/include/arith_taf.h | 80 + optee/optee_test/ta/crypt/include/cryp_taf.h | 102 + .../ta/crypt/include/derive_key_taf.h | 15 + .../optee_test/ta/crypt/include/mbedtls_taf.h | 16 + .../ta/crypt/include/seed_rng_taf.h | 13 + optee/optee_test/ta/crypt/include/sha2_impl.h | 80 + optee/optee_test/ta/crypt/include/sha2_taf.h | 18 + optee/optee_test/ta/crypt/include/ta_crypt.h | 654 + .../ta/crypt/include/user_ta_header_defines.h | 18 + optee/optee_test/ta/crypt/mbedtls_taf.c | 344 + optee/optee_test/ta/crypt/seed_rng_taf.c | 46 + optee/optee_test/ta/crypt/sha2_impl.c | 531 + optee/optee_test/ta/crypt/sha2_taf.c | 54 + optee/optee_test/ta/crypt/sub.mk | 31 + optee/optee_test/ta/crypt/ta_entry.c | 334 + .../enc_fs/include/enc_fs_key_manager_test.h | 17 + optee/optee_test/ta/hash_perf/Android.mk | 4 + optee/optee_test/ta/hash_perf/Makefile | 3 + .../ta/hash_perf/include/ta_hash_perf.h | 37 + .../ta/hash_perf/include/ta_hash_perf_priv.h | 16 + .../include/user_ta_header_defines.h | 18 + optee/optee_test/ta/hash_perf/sub.mk | 3 + optee/optee_test/ta/hash_perf/ta_entry.c | 63 + optee/optee_test/ta/hash_perf/ta_hash_perf.c | 202 + optee/optee_test/ta/identity_subkey2.bin | Bin 0 -> 628 bytes optee/optee_test/ta/identity_subkey2.pem | 28 + optee/optee_test/ta/include/ta_storage.h | 52 + optee/optee_test/ta/large/Android.mk | 4 + optee/optee_test/ta/large/Makefile | 2 + optee/optee_test/ta/large/include/ta_large.h | 12 + .../ta/large/include/user_ta_header_defines.h | 18 + optee/optee_test/ta/large/sub.mk | 2 + optee/optee_test/ta/large/ta_entry.c | 61 + optee/optee_test/ta/mid_level_subkey.bin | Bin 0 -> 1320 bytes optee/optee_test/ta/mid_level_subkey.pem | 28 + optee/optee_test/ta/miss/Android.mk | 4 + optee/optee_test/ta/miss/Makefile | 2 + .../optee_test/ta/miss/include/ta_miss_test.h | 14 + .../ta/miss/include/user_ta_header_defines.h | 19 + optee/optee_test/ta/miss/sub.mk | 6 + optee/optee_test/ta/miss/ta_entry.c | 1 + optee/optee_test/ta/miss/ta_miss.c | 1 + optee/optee_test/ta/os_test/Android.mk | 5 + optee/optee_test/ta/os_test/Makefile | 13 + optee/optee_test/ta/os_test/attestation.c | 28 + optee/optee_test/ta/os_test/cxx_tests.cpp | 107 + optee/optee_test/ta/os_test/cxx_tests.h | 12 + optee/optee_test/ta/os_test/cxx_tests_c.c | 11 + optee/optee_test/ta/os_test/include/init.h | 14 + optee/optee_test/ta/os_test/include/os_test.h | 48 + .../ta/os_test/include/ta_os_test.h | 50 + .../ta/os_test/include/tb_asserts.h | 165 + .../optee_test/ta/os_test/include/tb_macros.h | 68 + .../ta/os_test/include/testframework.h | 46 + .../os_test/include/user_ta_header_defines.h | 47 + optee/optee_test/ta/os_test/init.c | 17 + optee/optee_test/ta/os_test/os_test.c | 1575 ++ optee/optee_test/ta/os_test/pauth_a64.S | 23 + optee/optee_test/ta/os_test/sub.mk | 30 + optee/optee_test/ta/os_test/ta_arm_pauth.c | 54 + optee/optee_test/ta/os_test/ta_entry.c | 184 + optee/optee_test/ta/os_test/test_float_subj.c | 197 + optee/optee_test/ta/os_test/test_float_subj.h | 49 + optee/optee_test/ta/os_test_lib/Android.mk | 4 + optee/optee_test/ta/os_test_lib/Makefile | 5 + .../ta/os_test_lib/include/os_test_lib.h | 21 + optee/optee_test/ta/os_test_lib/os_test_lib.c | 32 + .../ta/os_test_lib/os_test_lib_cxx.cpp | 26 + optee/optee_test/ta/os_test_lib/sub.mk | 8 + optee/optee_test/ta/os_test_lib_dl/Android.mk | 4 + optee/optee_test/ta/os_test_lib_dl/Makefile | 5 + .../os_test_lib_dl/include/os_test_lib_dl.h | 15 + .../ta/os_test_lib_dl/os_test_lib_dl.c | 27 + .../ta/os_test_lib_dl/os_test_lib_dl_cxx.cpp | 26 + optee/optee_test/ta/os_test_lib_dl/sub.mk | 7 + optee/optee_test/ta/rpc_test/Android.mk | 4 + optee/optee_test/ta/rpc_test/Makefile | 2 + optee/optee_test/ta/rpc_test/include/ta_rpc.h | 22 + .../ta/rpc_test/include/ta_rpc_test.h | 25 + .../rpc_test/include/user_ta_header_defines.h | 18 + optee/optee_test/ta/rpc_test/sub.mk | 5 + optee/optee_test/ta/rpc_test/ta_entry.c | 80 + optee/optee_test/ta/rpc_test/ta_rpc.c | 166 + optee/optee_test/ta/sdp_basic/Android.mk | 4 + optee/optee_test/ta/sdp_basic/Makefile | 4 + .../ta/sdp_basic/include/ta_sdp_basic.h | 25 + .../include/user_ta_header_defines.h | 21 + optee/optee_test/ta/sdp_basic/sub.mk | 2 + optee/optee_test/ta/sdp_basic/ta_sdp_basic.c | 369 + optee/optee_test/ta/sims/Android.mk | 4 + optee/optee_test/ta/sims/Makefile | 2 + optee/optee_test/ta/sims/include/ta_sims.h | 24 + .../optee_test/ta/sims/include/ta_sims_test.h | 20 + .../ta/sims/include/user_ta_header_defines.h | 20 + optee/optee_test/ta/sims/sub.mk | 4 + optee/optee_test/ta/sims/ta_entry.c | 66 + optee/optee_test/ta/sims/ta_sims.c | 194 + optee/optee_test/ta/sims_keepalive/Android.mk | 4 + optee/optee_test/ta/sims_keepalive/Makefile | 2 + .../include/ta_sims_keepalive_test.h | 14 + .../include/user_ta_header_defines.h | 21 + optee/optee_test/ta/sims_keepalive/sub.mk | 6 + optee/optee_test/ta/sims_keepalive/ta_entry.c | 1 + .../ta/sims_keepalive/ta_sims_keepalive.c | 1 + optee/optee_test/ta/socket/Android.mk | 4 + optee/optee_test/ta/socket/Makefile | 2 + .../optee_test/ta/socket/include/ta_socket.h | 78 + .../socket/include/user_ta_header_defines.h | 19 + optee/optee_test/ta/socket/sub.mk | 2 + optee/optee_test/ta/socket/ta_entry.c | 273 + optee/optee_test/ta/storage/Android.mk | 4 + optee/optee_test/ta/storage/Makefile | 2 + optee/optee_test/ta/storage/include/storage.h | 43 + .../storage/include/user_ta_header_defines.h | 23 + optee/optee_test/ta/storage/storage.c | 664 + optee/optee_test/ta/storage/sub.mk | 4 + optee/optee_test/ta/storage/ta_entry.c | 125 + optee/optee_test/ta/storage2/Android.mk | 4 + optee/optee_test/ta/storage2/Makefile | 2 + .../optee_test/ta/storage2/include/storage.h | 1 + .../storage2/include/user_ta_header_defines.h | 21 + optee/optee_test/ta/storage2/storage.c | 1 + optee/optee_test/ta/storage2/sub.mk | 4 + optee/optee_test/ta/storage2/ta_entry.c | 1 + .../ta/storage_benchmark/Android.mk | 4 + .../optee_test/ta/storage_benchmark/Makefile | 2 + .../ta/storage_benchmark/benchmark.c | 411 + .../include/storage_benchmark.h | 15 + .../include/ta_storage_benchmark.h | 19 + .../include/user_ta_header_defines.h | 18 + optee/optee_test/ta/storage_benchmark/sub.mk | 3 + .../ta/storage_benchmark/ta_entry.c | 52 + optee/optee_test/ta/subkey1/Makefile | 8 + .../ta/subkey1/include/ta_subkey1.h | 12 + .../subkey1/include/user_ta_header_defines.h | 18 + optee/optee_test/ta/subkey1/sub.mk | 2 + optee/optee_test/ta/subkey1/ta_entry.c | 35 + optee/optee_test/ta/subkey2/Makefile | 8 + .../ta/subkey2/include/ta_subkey2.h | 12 + .../subkey2/include/user_ta_header_defines.h | 18 + optee/optee_test/ta/subkey2/sub.mk | 2 + optee/optee_test/ta/subkey2/ta_entry.c | 35 + optee/optee_test/ta/subkey_notes.txt | 73 + optee/optee_test/ta/supp_plugin/Android.mk | 4 + optee/optee_test/ta/supp_plugin/Makefile | 2 + .../ta/supp_plugin/include/ta_supp_plugin.h | 20 + .../include/user_ta_header_defines.h | 17 + optee/optee_test/ta/supp_plugin/sub.mk | 3 + optee/optee_test/ta/supp_plugin/ta_entry.c | 169 + optee/optee_test/ta/ta_common.mk | 3 + optee/optee_test/ta/top_level_subkey.bin | Bin 0 -> 628 bytes optee/optee_test/ta/top_level_subkey.pem | 28 + optee/optee_test/ta/tpm_log_test/Android.mk | 4 + optee/optee_test/ta/tpm_log_test/Makefile | 2 + .../ta/tpm_log_test/include/ta_tpm_log.h | 12 + .../ta/tpm_log_test/include/ta_tpm_log_test.h | 19 + .../include/user_ta_header_defines.h | 17 + optee/optee_test/ta/tpm_log_test/sub.mk | 2 + optee/optee_test/ta/tpm_log_test/ta_entry.c | 180 + optee/optee_test/typedefs.checkpatch | 2 + optee/samples/LICENSE | 23 + optee/samples/Makefile | 35 + optee/samples/hwkey-agent/LICENSE | 23 + optee/samples/hwkey-agent/Makefile | 35 + optee/samples/hwkey-agent/README | 75 + optee/samples/hwkey-agent/host/Makefile | 37 + .../samples/hwkey-agent/host/hwkey_agent_ca.c | 331 + .../hwkey-agent/host/tool/gen_ekb/README | 129 + .../hwkey-agent/host/tool/gen_ekb/example.sh | 45 + .../hwkey-agent/host/tool/gen_ekb/gen_ekb.py | 207 + optee/samples/hwkey-agent/ta/Makefile | 7 + optee/samples/hwkey-agent/ta/hwkey_agent_ta.c | 244 + .../hwkey-agent/ta/include/hwkey_agent_ta.h | 48 + optee/samples/hwkey-agent/ta/sub.mk | 5 + .../hwkey-agent/ta/user_ta_header_defines.h | 17 + optee/samples/luks-srv/LICENSE | 23 + optee/samples/luks-srv/Makefile | 39 + optee/samples/luks-srv/README | 65 + optee/samples/luks-srv/host/Makefile | 42 + optee/samples/luks-srv/host/luks_srv_ca.c | 177 + .../host/tool/gen_luks_passphrase/README | 67 + .../host/tool/gen_luks_passphrase/example.sh | 11 + .../gen_luks_passphrase.py | 98 + optee/samples/luks-srv/ta/Makefile | 7 + .../samples/luks-srv/ta/include/luks_srv_ta.h | 51 + optee/samples/luks-srv/ta/luks_srv_ta.c | 235 + optee/samples/luks-srv/ta/sub.mk | 5 + .../luks-srv/ta/user_ta_header_defines.h | 17 + optee/tegra194-optee.dts | 72 + optee/tegra234-optee.dts | 130 + optee_src_build.sh | 183 + push_info.txt | 1 + 3275 files changed, 738378 insertions(+) create mode 100644 commitFile.txt create mode 100755 nvcommon_build.sh create mode 100644 optee/atf_and_optee_README.txt create mode 100644 optee/optee_client/.github/workflows/ci.yml create mode 100644 optee/optee_client/.github/workflows/stales.yml create mode 100644 optee/optee_client/Android.mk create mode 100644 optee/optee_client/CMakeLists.txt create mode 100644 optee/optee_client/CMakeToolchain.txt create mode 100644 optee/optee_client/LICENSE create mode 100644 optee/optee_client/Makefile create mode 100644 optee/optee_client/README.md create mode 100644 optee/optee_client/android_flags.mk create mode 100644 optee/optee_client/ci/Dockerfile.debian create mode 100644 optee/optee_client/ci/Dockerfile.ubuntu create mode 100644 optee/optee_client/config.mk create mode 100644 optee/optee_client/flags.mk create mode 100644 optee/optee_client/libckteec/CMakeLists.txt create mode 100644 optee/optee_client/libckteec/Makefile create mode 100644 optee/optee_client/libckteec/include/CMakeLists.txt create mode 100644 optee/optee_client/libckteec/include/ck_debug.h create mode 100644 optee/optee_client/libckteec/include/pkcs11.h create mode 100644 optee/optee_client/libckteec/include/pkcs11_ta.h create mode 100644 optee/optee_client/libckteec/src/ck_debug.c create mode 100644 optee/optee_client/libckteec/src/ck_helpers.c create mode 100644 optee/optee_client/libckteec/src/ck_helpers.h create mode 100644 optee/optee_client/libckteec/src/invoke_ta.c create mode 100644 optee/optee_client/libckteec/src/invoke_ta.h create mode 100644 optee/optee_client/libckteec/src/local_utils.h create mode 100644 optee/optee_client/libckteec/src/pkcs11_api.c create mode 100644 optee/optee_client/libckteec/src/pkcs11_processing.c create mode 100644 optee/optee_client/libckteec/src/pkcs11_processing.h create mode 100644 optee/optee_client/libckteec/src/pkcs11_token.c create mode 100644 optee/optee_client/libckteec/src/pkcs11_token.h create mode 100644 optee/optee_client/libckteec/src/serialize_ck.c create mode 100644 optee/optee_client/libckteec/src/serialize_ck.h create mode 100644 optee/optee_client/libckteec/src/serializer.c create mode 100644 optee/optee_client/libckteec/src/serializer.h create mode 100644 optee/optee_client/libseteec/CMakeLists.txt create mode 100644 optee/optee_client/libseteec/Makefile create mode 100644 optee/optee_client/libseteec/include/CMakeLists.txt create mode 100644 optee/optee_client/libseteec/include/se_tee.h create mode 100644 optee/optee_client/libseteec/src/pta_apdu.h create mode 100644 optee/optee_client/libseteec/src/pta_scp03.h create mode 100644 optee/optee_client/libseteec/src/se.c create mode 100644 optee/optee_client/libteeacl/CMakeLists.txt create mode 100644 optee/optee_client/libteeacl/Makefile create mode 100644 optee/optee_client/libteeacl/include/teeacl.h create mode 100644 optee/optee_client/libteeacl/src/group.c create mode 100644 optee/optee_client/libteeacl/src/tee_uuid.c create mode 100644 optee/optee_client/libteec/CMakeLists.txt create mode 100644 optee/optee_client/libteec/Makefile create mode 100644 optee/optee_client/libteec/include/linux/tee.h create mode 100644 optee/optee_client/libteec/include/teec_benchmark.h create mode 100644 optee/optee_client/libteec/libteec.pc.in create mode 100644 optee/optee_client/libteec/src/tee_client_api.c create mode 100644 optee/optee_client/libteec/src/teec_benchmark.c create mode 100644 optee/optee_client/libteec/src/teec_trace.c create mode 100644 optee/optee_client/public/CMakeLists.txt create mode 100644 optee/optee_client/public/tee_bench.h create mode 100644 optee/optee_client/public/tee_client_api.h create mode 100644 optee/optee_client/public/tee_client_api_extensions.h create mode 100644 optee/optee_client/public/tee_plugin_method.h create mode 100644 optee/optee_client/public/teec_trace.h create mode 100644 optee/optee_client/scripts/checkpatch_inc.sh create mode 100644 optee/optee_client/tee-supplicant/CMakeLists.txt create mode 100644 optee/optee_client/tee-supplicant/Makefile create mode 100644 optee/optee_client/tee-supplicant/src/__tee_ipsocket.h create mode 100644 optee/optee_client/tee-supplicant/src/__tee_isocket_defines.h create mode 100644 optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines.h create mode 100644 optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h create mode 100644 optee/optee_client/tee-supplicant/src/__tee_udpsocket_defines.h create mode 100644 optee/optee_client/tee-supplicant/src/handle.c create mode 100644 optee/optee_client/tee-supplicant/src/handle.h create mode 100644 optee/optee_client/tee-supplicant/src/hmac_sha2.c create mode 100644 optee/optee_client/tee-supplicant/src/hmac_sha2.h create mode 100644 optee/optee_client/tee-supplicant/src/nvme_rpmb.c create mode 100644 optee/optee_client/tee-supplicant/src/nvme_rpmb.h create mode 100644 optee/optee_client/tee-supplicant/src/optee_msg_supplicant.h create mode 100644 optee/optee_client/tee-supplicant/src/plugin.c create mode 100644 optee/optee_client/tee-supplicant/src/plugin.h create mode 100644 optee/optee_client/tee-supplicant/src/prof.c create mode 100644 optee/optee_client/tee-supplicant/src/prof.h create mode 100644 optee/optee_client/tee-supplicant/src/rpmb.c create mode 100644 optee/optee_client/tee-supplicant/src/rpmb.h create mode 100644 optee/optee_client/tee-supplicant/src/sha2.c create mode 100644 optee/optee_client/tee-supplicant/src/sha2.h create mode 100644 optee/optee_client/tee-supplicant/src/tee_socket.c create mode 100644 optee/optee_client/tee-supplicant/src/tee_socket.h create mode 100644 optee/optee_client/tee-supplicant/src/tee_supp_fs.c create mode 100644 optee/optee_client/tee-supplicant/src/tee_supp_fs.h create mode 100644 optee/optee_client/tee-supplicant/src/tee_supplicant.c create mode 100644 optee/optee_client/tee-supplicant/src/tee_supplicant.h create mode 100644 optee/optee_client/tee-supplicant/src/teec_ta_load.c create mode 100644 optee/optee_client/tee-supplicant/src/teec_ta_load.h create mode 100644 optee/optee_client/tee-supplicant/tee_supplicant_android.mk create mode 100644 optee/optee_client/typedefs.checkpatch create mode 100644 optee/optee_os/.checkpatch.conf create mode 100644 optee/optee_os/.github/issue_template.md create mode 100644 optee/optee_os/.github/pull_request_template.md create mode 100644 optee/optee_os/.github/workflows/ci-cancel.yml create mode 100644 optee/optee_os/.github/workflows/ci.yml create mode 100644 optee/optee_os/.github/workflows/stales.yml create mode 100644 optee/optee_os/CHANGELOG.md create mode 100644 optee/optee_os/LICENSE create mode 100644 optee/optee_os/LICENSE.NVIDIA create mode 100644 optee/optee_os/MAINTAINERS create mode 100644 optee/optee_os/Makefile create mode 100644 optee/optee_os/README.md create mode 100644 optee/optee_os/core/arch/arm/arm.mk create mode 100644 optee/optee_os/core/arch/arm/cpu/cortex-a15.mk create mode 100644 optee/optee_os/core/arch/arm/cpu/cortex-a5.mk create mode 100644 optee/optee_os/core/arch/arm/cpu/cortex-a7.mk create mode 100644 optee/optee_os/core/arch/arm/cpu/cortex-a9.mk create mode 100644 optee/optee_os/core/arch/arm/cpu/cortex-armv8-0.mk create mode 100644 optee/optee_os/core/arch/arm/crypto/aes-gcm-ce.c create mode 100644 optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.c create mode 100644 optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.h create mode 100644 optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S create mode 100644 optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a32.S create mode 100644 optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce.c create mode 100644 optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a32.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce.c create mode 100644 optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a32.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce.c create mode 100644 optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce.c create mode 100644 optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce.c create mode 100644 optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sm4_armv8a_aese_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.c create mode 100644 optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.h create mode 100644 optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce_a64.S create mode 100644 optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.c create mode 100644 optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.h create mode 100644 optee/optee_os/core/arch/arm/crypto/sub.mk create mode 100644 optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1_ek.dts create mode 100644 optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts create mode 100644 optee/optee_os/core/arch/arm/dts/at91-sama5d2_xplained.dts create mode 100644 optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/embedded_dtb_test.dts create mode 100644 optee/optee_os/core/arch/arm/dts/fsl-lx2160a-qds.dts create mode 100644 optee/optee_os/core/arch/arm/dts/fsl-lx2160a-rdb.dts create mode 100644 optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/hikey.dts create mode 100644 optee/optee_os/core/arch/arm/dts/sama5d2-pinfunc.h create mode 100644 optee/optee_os/core/arch/arm/dts/sama5d2.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp133.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp151.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp153.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp157.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1.dts create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xc.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi create mode 100644 optee/optee_os/core/arch/arm/include/arm.h create mode 100644 optee/optee_os/core/arch/arm/include/arm32.h create mode 100644 optee/optee_os/core/arch/arm/include/arm32_macros.S create mode 100644 optee/optee_os/core/arch/arm/include/arm32_macros_cortex_a9.S create mode 100644 optee/optee_os/core/arch/arm/include/arm64.h create mode 100644 optee/optee_os/core/arch/arm/include/arm64_macros.S create mode 100644 optee/optee_os/core/arch/arm/include/crypto/ghash-ce-core.h create mode 100644 optee/optee_os/core/arch/arm/include/ffa.h create mode 100644 optee/optee_os/core/arch/arm/include/hafnium.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/arch_scall.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/cache_helpers_arch.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/delay_arch.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/misc_arch.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/secure_partition.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/stmm_sp.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/thread_arch.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/tlb_helpers.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_def.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h create mode 100644 optee/optee_os/core/arch/arm/include/kernel/vfp.h create mode 100644 optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h create mode 100644 optee/optee_os/core/arch/arm/include/mm/generic_ram_layout.h create mode 100644 optee/optee_os/core/arch/arm/include/optee_ffa.h create mode 100644 optee/optee_os/core/arch/arm/include/pta_stmm.h create mode 100644 optee/optee_os/core/arch/arm/include/scmi/scmi_server.h create mode 100644 optee/optee_os/core/arch/arm/include/sm/optee_smc.h create mode 100644 optee/optee_os/core/arch/arm/include/sm/pm.h create mode 100644 optee/optee_os/core/arch/arm/include/sm/psci.h create mode 100644 optee/optee_os/core/arch/arm/include/sm/sm.h create mode 100644 optee/optee_os/core/arch/arm/include/sm/std_smc.h create mode 100644 optee/optee_os/core/arch/arm/include/sm/teesmc_opteed.h create mode 100644 optee/optee_os/core/arch/arm/include/sm/teesmc_opteed_macros.h create mode 100644 optee/optee_os/core/arch/arm/include/smccc.h create mode 100644 optee/optee_os/core/arch/arm/include/tee/entry_fast.h create mode 100644 optee/optee_os/core/arch/arm/kernel/abort.c create mode 100644 optee/optee_os/core/arch/arm/kernel/arch_scall.c create mode 100644 optee/optee_os/core/arch/arm/kernel/arch_scall_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/arch_scall_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/arm32_gicv3_sysreg.txt create mode 100644 optee/optee_os/core/arch/arm/kernel/arm32_sysreg.txt create mode 100644 optee/optee_os/core/arch/arm/kernel/asm-defines.c create mode 100644 optee/optee_os/core/arch/arm/kernel/boot.c create mode 100644 optee/optee_os/core/arch/arm/kernel/cache_helpers_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/cache_helpers_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/entry_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/entry_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/idle.c create mode 100644 optee/optee_os/core/arch/arm/kernel/kern.ld.S create mode 100644 optee/optee_os/core/arch/arm/kernel/link.mk create mode 100644 optee/optee_os/core/arch/arm/kernel/link_dummies_init.c create mode 100644 optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c create mode 100644 optee/optee_os/core/arch/arm/kernel/link_dummy.ld create mode 100644 optee/optee_os/core/arch/arm/kernel/misc_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/misc_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/rpc_io_i2c.c create mode 100644 optee/optee_os/core/arch/arm/kernel/secure_partition.c create mode 100644 optee/optee_os/core/arch/arm/kernel/spin_lock_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/spin_lock_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c create mode 100644 optee/optee_os/core/arch/arm/kernel/stmm_sp.c create mode 100644 optee/optee_os/core/arch/arm/kernel/sub.mk create mode 100644 optee/optee_os/core/arch/arm/kernel/tee_l2cc_mutex.c create mode 100644 optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c create mode 100644 optee/optee_os/core/arch/arm/kernel/thread.c create mode 100644 optee/optee_os/core/arch/arm/kernel/thread_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/thread_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c create mode 100644 optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/thread_spmc.c create mode 100644 optee/optee_os/core/arch/arm/kernel/thread_spmc_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/timer_a64.c create mode 100644 optee/optee_os/core/arch/arm/kernel/tlb_helpers_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/tlb_helpers_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/unwind_arm32.c create mode 100644 optee/optee_os/core/arch/arm/kernel/unwind_arm64.c create mode 100644 optee/optee_os/core/arch/arm/kernel/unwind_private.h create mode 100644 optee/optee_os/core/arch/arm/kernel/vfp.c create mode 100644 optee/optee_os/core/arch/arm/kernel/vfp_a32.S create mode 100644 optee/optee_os/core/arch/arm/kernel/vfp_a64.S create mode 100644 optee/optee_os/core/arch/arm/kernel/vfp_private.h create mode 100644 optee/optee_os/core/arch/arm/kernel/virtualization.c create mode 100644 optee/optee_os/core/arch/arm/mm/core_mmu.c create mode 100644 optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c create mode 100644 optee/optee_os/core/arch/arm/mm/core_mmu_v7.c create mode 100644 optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c create mode 100644 optee/optee_os/core/arch/arm/mm/mobj_ffa.c create mode 100644 optee/optee_os/core/arch/arm/mm/pgt_cache.c create mode 100644 optee/optee_os/core/arch/arm/mm/sp_mem.c create mode 100644 optee/optee_os/core/arch/arm/mm/sub.mk create mode 100644 optee/optee_os/core/arch/arm/mm/tee_pager.c create mode 100644 optee/optee_os/core/arch/arm/plat-amlogic/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-amlogic/link.mk create mode 100644 optee/optee_os/core/arch/arm/plat-amlogic/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-amlogic/platform_config.h create mode 100755 optee/optee_os/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py create mode 100644 optee/optee_os/core/arch/arm/plat-amlogic/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-aspeed/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-aspeed/core_pos_a32.S create mode 100644 optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c create mode 100644 optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-aspeed/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.c create mode 100644 optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.h create mode 100644 optee/optee_os/core/arch/arm/plat-bcm/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-bcm/crc32.c create mode 100644 optee/optee_os/core/arch/arm/plat-bcm/crc32.h create mode 100644 optee/optee_os/core/arch/arm/plat-bcm/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-bcm/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-bcm/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-corstone1000/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-corstone1000/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-corstone1000/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-corstone1000/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-d02/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-d02/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-d02/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-d02/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-d06/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-d06/core_pos_a64.S create mode 100644 optee/optee_os/core/arch/arm/plat-d06/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-d06/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-d06/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-hikey/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-hikey/hikey_peripherals.h create mode 100644 optee/optee_os/core/arch/arm/plat-hikey/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-hikey/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-hikey/spi_test.c create mode 100644 optee/optee_os/core/arch/arm/plat-hikey/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-hisilicon/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100.h create mode 100644 optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-hisilicon/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-hisilicon/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-hisilicon/psci.c create mode 100644 optee/optee_os/core/arch/arm/plat-hisilicon/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-imx/a7_plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-imx/a9_plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-imx/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-imx/config/imx6qdlsolo.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/config/imx6sl.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/config/imx6sll.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/config/imx6sx.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/imx-common.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/imx-regs.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/imx.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/imx_pl310.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/imx_pm.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/imx_pm_asm_defines.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/imx_src.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/link.mk create mode 100644 optee/optee_os/core/arch/arm/plat-imx/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/mmdc.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/mmdc.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/pm/cpuidle-imx7d.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/pm/gpcv2.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/pm/imx7_suspend.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/pm/pm-imx7.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/pm/psci-cpuidle-imx7.S create mode 100644 optee/optee_os/core/arch/arm/plat-imx/pm/psci-suspend-imx7.S create mode 100644 optee/optee_os/core/arch/arm/plat-imx/pm/psci.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/pm/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx6-crm.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx6-dcp.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx7-crm.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp-crm.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx8m-crm.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx8q.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp-crm.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/registers/imx93.h create mode 100644 optee/optee_os/core/arch/arm/plat-imx/sm_platform_handler.c create mode 100644 optee/optee_os/core/arch/arm/plat-imx/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-imx/tzc380.c create mode 100644 optee/optee_os/core/arch/arm/plat-k3/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.h create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.c create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.h create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h create mode 100644 optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h create mode 100644 optee/optee_os/core/arch/arm/plat-k3/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-k3/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-k3/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-ls/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-ls/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-ls/plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-ls/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-ls/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-marvell/armada3700/hal_sec_perf.c create mode 100644 optee/optee_os/core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c create mode 100644 optee/optee_os/core/arch/arm/plat-marvell/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-marvell/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-marvell/otx2/core_pos.S create mode 100644 optee/optee_os/core/arch/arm/plat-marvell/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-marvell/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-mediatek/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-mediatek/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-mediatek/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-poplar/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-poplar/hi3798cv200.h create mode 100644 optee/optee_os/core/arch/arm/plat-poplar/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-poplar/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-poplar/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/core_pos_a64.S create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/hw_rng.c create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/link.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/rcar.h create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/romapi.c create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/romapi.h create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/romapi_call.S create mode 100644 optee/optee_os/core/arch/arm/plat-rcar/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/common.h create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/core_pos_a32.S create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/cru.h create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/grf.h create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/platform.c create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/platform.h create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/platform_px30.c create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/platform_rk322x.c create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/platform_rk3399.c create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/psci_rk322x.c create mode 100644 optee/optee_os/core/arch/arm/plat-rockchip/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rpi3/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rpi3/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-rpi3/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-rpi3/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rzg/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rzg/link.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rzg/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-rzg/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-rzg/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/a7_plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/psci.c create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/rzn1_regauth.h create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/rzn1_tz.h create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c create mode 100644 optee/optee_os/core/arch/arm/plat-rzn1/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-sam/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-sam/freq.c create mode 100644 optee/optee_os/core/arch/arm/plat-sam/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-sam/matrix.c create mode 100644 optee/optee_os/core/arch/arm/plat-sam/matrix.h create mode 100644 optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c create mode 100644 optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h create mode 100644 optee/optee_os/core/arch/arm/plat-sam/nsec-service/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-sam/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-sam/pm/psci.c create mode 100644 optee/optee_os/core/arch/arm/plat-sam/pm/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-sam/sam_pl310.c create mode 100644 optee/optee_os/core/arch/arm/plat-sam/sam_sfr.c create mode 100644 optee/optee_os/core/arch/arm/plat-sam/sam_sfr.h create mode 100644 optee/optee_os/core/arch/arm/plat-sam/sama5d2.h create mode 100644 optee/optee_os/core/arch/arm/plat-sam/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-sam/tz_matrix.h create mode 100644 optee/optee_os/core/arch/arm/plat-sprd/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-sprd/console.c create mode 100644 optee/optee_os/core/arch/arm/plat-sprd/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-sprd/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-sprd/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm/rng_support.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm/tz_a9init.S create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/boot_api.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/link.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/link_dummies_paged.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/pm/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/reset.S create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c create mode 100755 optee/optee_os/core/arch/arm/plat-stm32mp1/scripts/stm32image.py create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h create mode 100644 optee/optee_os/core/arch/arm/plat-stm32mp1/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-sunxi/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-sunxi/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-sunxi/plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-sunxi/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-sunxi/psci.c create mode 100644 optee/optee_os/core/arch/arm/plat-sunxi/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-synquacer/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-synquacer/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-synquacer/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.c create mode 100644 optee/optee_os/core/arch/arm/plat-synquacer/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-synquacer/synquacer_rng_pta.h create mode 100644 optee/optee_os/core/arch/arm/plat-tegra/README.tegra_secure_storage create mode 100644 optee/optee_os/core/arch/arm/plat-tegra/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-tegra/link.mk create mode 100644 optee/optee_os/core/arch/arm/plat-tegra/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-tegra/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-tegra/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-tegra/tegra_common.h create mode 100644 optee/optee_os/core/arch/arm/plat-ti/a9_plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a15.h create mode 100644 optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a9.h create mode 100644 optee/optee_os/core/arch/arm/plat-ti/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-ti/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-ti/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a15.c create mode 100644 optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a9.c create mode 100644 optee/optee_os/core/arch/arm/plat-ti/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-ti/ti_pl310.c create mode 100644 optee/optee_os/core/arch/arm/plat-totalcompute/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts create mode 100644 optee/optee_os/core/arch/arm/plat-totalcompute/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-totalcompute/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-totalcompute/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-uniphier/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-uniphier/kern.ld.S create mode 100644 optee/optee_os/core/arch/arm/plat-uniphier/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-uniphier/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-uniphier/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-versal/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-versal/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-versal/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-versal/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-vexpress/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a32.S create mode 100644 optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a64.S create mode 100644 optee/optee_os/core/arch/arm/plat-vexpress/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-vexpress/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-vexpress/vendor_props.c create mode 100644 optee/optee_os/core/arch/arm/plat-zynq7k/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-zynq7k/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-zynq7k/plat_init.S create mode 100644 optee/optee_os/core/arch/arm/plat-zynq7k/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-zynq7k/platform_smc.h create mode 100644 optee/optee_os/core/arch/arm/plat-zynq7k/sub.mk create mode 100644 optee/optee_os/core/arch/arm/plat-zynqmp/conf.mk create mode 100644 optee/optee_os/core/arch/arm/plat-zynqmp/main.c create mode 100644 optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h create mode 100644 optee/optee_os/core/arch/arm/plat-zynqmp/sub.mk create mode 100644 optee/optee_os/core/arch/arm/sm/pm.c create mode 100644 optee/optee_os/core/arch/arm/sm/pm_a32.S create mode 100644 optee/optee_os/core/arch/arm/sm/psci-helper.S create mode 100644 optee/optee_os/core/arch/arm/sm/psci.c create mode 100644 optee/optee_os/core/arch/arm/sm/sm.c create mode 100644 optee/optee_os/core/arch/arm/sm/sm_a32.S create mode 100644 optee/optee_os/core/arch/arm/sm/sm_private.h create mode 100644 optee/optee_os/core/arch/arm/sm/std_smc.c create mode 100644 optee/optee_os/core/arch/arm/sm/sub.mk create mode 100644 optee/optee_os/core/arch/arm/tee/cache.c create mode 100644 optee/optee_os/core/arch/arm/tee/entry_fast.c create mode 100644 optee/optee_os/core/arch/arm/tee/sub.mk create mode 100644 optee/optee_os/core/arch/arm/tee/svc_cache.c create mode 100644 optee/optee_os/core/arch/riscv/include/encoding.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/arch_scall.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/cache_helpers_arch.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/clint.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/misc_arch.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/secure_partition.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/stmm_sp.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/tee_l2cc_mutex.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/time.h create mode 100644 optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h create mode 100644 optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h create mode 100644 optee/optee_os/core/arch/riscv/include/mm/generic_ram_layout.h create mode 100644 optee/optee_os/core/arch/riscv/include/riscv.h create mode 100644 optee/optee_os/core/arch/riscv/include/riscv_macros.S create mode 100644 optee/optee_os/core/arch/riscv/include/sbi.h create mode 100644 optee/optee_os/core/arch/riscv/include/sub.mk create mode 100644 optee/optee_os/core/arch/riscv/kernel/abort.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/arch_scall.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/arch_scall_rv.S create mode 100644 optee/optee_os/core/arch/riscv/kernel/asm-defines.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/boot.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/cache_helpers_rv.S create mode 100644 optee/optee_os/core/arch/riscv/kernel/entry.S create mode 100644 optee/optee_os/core/arch/riscv/kernel/idle.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/kern.ld.S create mode 100644 optee/optee_os/core/arch/riscv/kernel/link.mk create mode 100644 optee/optee_os/core/arch/riscv/kernel/sbi.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/sbi_console.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/spinlock.S create mode 100644 optee/optee_os/core/arch/riscv/kernel/sub.mk create mode 100644 optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/thread_arch.c create mode 100644 optee/optee_os/core/arch/riscv/kernel/thread_rv.S create mode 100644 optee/optee_os/core/arch/riscv/mm/sub.mk create mode 100644 optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S create mode 100644 optee/optee_os/core/arch/riscv/plat-spike/conf.mk create mode 100644 optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.c create mode 100644 optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.h create mode 100644 optee/optee_os/core/arch/riscv/plat-spike/drivers/sub.mk create mode 100644 optee/optee_os/core/arch/riscv/plat-spike/kern.ld.S create mode 100644 optee/optee_os/core/arch/riscv/plat-spike/main.c create mode 100644 optee/optee_os/core/arch/riscv/plat-spike/platform_config.h create mode 100644 optee/optee_os/core/arch/riscv/plat-spike/sub.mk create mode 100644 optee/optee_os/core/arch/riscv/plat-virt/conf.mk create mode 100644 optee/optee_os/core/arch/riscv/plat-virt/main.c create mode 100644 optee/optee_os/core/arch/riscv/plat-virt/platform_config.h create mode 100644 optee/optee_os/core/arch/riscv/plat-virt/sub.mk create mode 100644 optee/optee_os/core/arch/riscv/riscv.mk create mode 100644 optee/optee_os/core/arch/riscv/tee/sub.mk create mode 100644 optee/optee_os/core/core.mk create mode 100644 optee/optee_os/core/crypto.mk create mode 100644 optee/optee_os/core/crypto/aes-cts.c create mode 100644 optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c create mode 100644 optee/optee_os/core/crypto/aes-gcm-sw.c create mode 100644 optee/optee_os/core/crypto/aes-gcm.c create mode 100644 optee/optee_os/core/crypto/cbc-mac.c create mode 100644 optee/optee_os/core/crypto/crypto.c create mode 100644 optee/optee_os/core/crypto/rng_fortuna.c create mode 100644 optee/optee_os/core/crypto/rng_hw.c create mode 100644 optee/optee_os/core/crypto/signed_hdr.c create mode 100644 optee/optee_os/core/crypto/sm2-kdf.c create mode 100644 optee/optee_os/core/crypto/sm3-hash.c create mode 100644 optee/optee_os/core/crypto/sm3-hmac.c create mode 100644 optee/optee_os/core/crypto/sm3.c create mode 100644 optee/optee_os/core/crypto/sm3.h create mode 100644 optee/optee_os/core/crypto/sm4-cbc.c create mode 100644 optee/optee_os/core/crypto/sm4-ctr.c create mode 100644 optee/optee_os/core/crypto/sm4-ecb.c create mode 100644 optee/optee_os/core/crypto/sm4-xts.c create mode 100644 optee/optee_os/core/crypto/sm4.c create mode 100644 optee/optee_os/core/crypto/sm4.h create mode 100644 optee/optee_os/core/crypto/sm4_accel.c create mode 100644 optee/optee_os/core/crypto/sub.mk create mode 100644 optee/optee_os/core/drivers/amlogic_uart.c create mode 100644 optee/optee_os/core/drivers/atmel_piobu.c create mode 100644 optee/optee_os/core/drivers/atmel_rstc.c create mode 100644 optee/optee_os/core/drivers/atmel_rtc.c create mode 100644 optee/optee_os/core/drivers/atmel_saic.c create mode 100644 optee/optee_os/core/drivers/atmel_shdwc.c create mode 100644 optee/optee_os/core/drivers/atmel_shdwc_a32.S create mode 100644 optee/optee_os/core/drivers/atmel_tcb.c create mode 100644 optee/optee_os/core/drivers/atmel_trng.c create mode 100644 optee/optee_os/core/drivers/atmel_uart.c create mode 100644 optee/optee_os/core/drivers/atmel_wdt.c create mode 100644 optee/optee_os/core/drivers/bcm_gpio.c create mode 100644 optee/optee_os/core/drivers/bcm_hwrng.c create mode 100644 optee/optee_os/core/drivers/bcm_sotp.c create mode 100644 optee/optee_os/core/drivers/bnxt/bnxt.c create mode 100644 optee/optee_os/core/drivers/bnxt/bnxt_fw.c create mode 100644 optee/optee_os/core/drivers/bnxt/bnxt_images.c create mode 100644 optee/optee_os/core/drivers/bnxt/sub.mk create mode 100644 optee/optee_os/core/drivers/cbmem_console.c create mode 100644 optee/optee_os/core/drivers/cdns_uart.c create mode 100644 optee/optee_os/core/drivers/clk/clk-stm32-core.c create mode 100644 optee/optee_os/core/drivers/clk/clk-stm32-core.h create mode 100644 optee/optee_os/core/drivers/clk/clk-stm32mp13.c create mode 100644 optee/optee_os/core/drivers/clk/clk-stm32mp15.c create mode 100644 optee/optee_os/core/drivers/clk/clk.c create mode 100644 optee/optee_os/core/drivers/clk/clk_dt.c create mode 100644 optee/optee_os/core/drivers/clk/fixed_clk.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_audio_pll.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_clk.h create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_generated.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_h32mx.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_i2s_mux.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_main.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_master.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_peripheral.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_pll.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_plldiv.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_pmc.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_pmc.h create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_programmable.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_sckc.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_system.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_usb.c create mode 100644 optee/optee_os/core/drivers/clk/sam/at91_utmi.c create mode 100644 optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c create mode 100644 optee/optee_os/core/drivers/clk/sam/sub.mk create mode 100644 optee/optee_os/core/drivers/clk/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/aspeed/crypto_ast2600.c create mode 100644 optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.c create mode 100644 optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.h create mode 100644 optee/optee_os/core/drivers/crypto/aspeed/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/caam_math.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_dsa.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/local.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/acipher/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/blob/caam_blob.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/blob/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/caam_desc.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/caam_jr.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/caam_pwr.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/caam_rng.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_mac.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_xts.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/cipher/local.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/cipher/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/crypto.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/hal_jr.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/registers/jr_regs.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/registers/rng_regs.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/registers/version_regs.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/common/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7ulp.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_ctrl.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_jr.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_ctrl.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_jr.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_cfg.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_clk.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_ctrl.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_jr.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_ctrl.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_jr.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_clk.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_ctrl.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_jr.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/ls/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/hal/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/hash/caam_hash.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/hash/local.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/hash/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_acipher.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_blob.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_cipher.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_common.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_hal_cfg.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_hal_clk.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_hal_jr.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_hash.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_io.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_jr.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_jr_status.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_mp.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_pwr.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_rng.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_status.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_trace.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_types.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_utils_delay.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_utils_dmaobj.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_utils_mem.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_utils_sgt.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h create mode 100644 optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/mp/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/utils/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/caam/utils/utils_delay.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/utils/utils_mem.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v1.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v2.c create mode 100644 optee/optee_os/core/drivers/crypto/caam/utils/utils_status.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/acipher/dh.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/acipher/dsa.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/acipher/ecc.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/acipher/local.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsa.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsamgf.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsassa.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/acipher/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/authenc/authenc.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/authenc/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/cipher/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/drvcrypt.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/hash/hash.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/hash/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_cipher.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_hash.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_mac.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_math.h create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/mac/mac.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/mac/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/math/modulus.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/math/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/oid/hash_oid.c create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/oid/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/crypto_api/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/apis/apdu.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/apis/sss.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/apis/user.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050.h create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_sss_apis.h create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_user_apis.h create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_utils.h create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/utils/info.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/utils/scp_config.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/apdu.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/cipher.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/ctr.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/die_id.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/ecc.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/rng.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/rsa.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/scp03.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/storage.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/core/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/se050/crypto.mk create mode 100644 optee/optee_os/core/drivers/crypto/se050/glue/i2c.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/glue/i2c_imx.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/glue/include/i2c_native.h create mode 100644 optee/optee_os/core/drivers/crypto/se050/glue/user.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/session.c create mode 100644 optee/optee_os/core/drivers/crypto/se050/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/stm32/authenc.c create mode 100644 optee/optee_os/core/drivers/crypto/stm32/cipher.c create mode 100644 optee/optee_os/core/drivers/crypto/stm32/common.h create mode 100644 optee/optee_os/core/drivers/crypto/stm32/crypto.mk create mode 100644 optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c create mode 100644 optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.h create mode 100644 optee/optee_os/core/drivers/crypto/stm32/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/sub.mk create mode 100644 optee/optee_os/core/drivers/crypto/versal/authenc.c create mode 100644 optee/optee_os/core/drivers/crypto/versal/crypto.mk create mode 100644 optee/optee_os/core/drivers/crypto/versal/ecc.c create mode 100644 optee/optee_os/core/drivers/crypto/versal/include/ipi.h create mode 100644 optee/optee_os/core/drivers/crypto/versal/ipi.c create mode 100644 optee/optee_os/core/drivers/crypto/versal/rsa.c create mode 100644 optee/optee_os/core/drivers/crypto/versal/sub.mk create mode 100644 optee/optee_os/core/drivers/dra7_rng.c create mode 100644 optee/optee_os/core/drivers/gic.c create mode 100644 optee/optee_os/core/drivers/hfic.c create mode 100644 optee/optee_os/core/drivers/hi16xx_rng.c create mode 100644 optee/optee_os/core/drivers/hi16xx_uart.c create mode 100644 optee/optee_os/core/drivers/i2c/atmel_i2c.c create mode 100644 optee/optee_os/core/drivers/i2c/i2c.c create mode 100644 optee/optee_os/core/drivers/i2c/sub.mk create mode 100644 optee/optee_os/core/drivers/imx/dcp/dcp.c create mode 100644 optee/optee_os/core/drivers/imx/dcp/dcp_huk.c create mode 100644 optee/optee_os/core/drivers/imx/dcp/dcp_utils.c create mode 100644 optee/optee_os/core/drivers/imx/dcp/include/dcp_utils.h create mode 100644 optee/optee_os/core/drivers/imx/dcp/include/local.h create mode 100644 optee/optee_os/core/drivers/imx/dcp/sub.mk create mode 100644 optee/optee_os/core/drivers/imx/mu/imx_mu.c create mode 100644 optee/optee_os/core/drivers/imx/mu/imx_mu_8q.c create mode 100644 optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c create mode 100644 optee/optee_os/core/drivers/imx/mu/imx_mu_platform.h create mode 100644 optee/optee_os/core/drivers/imx/mu/sub.mk create mode 100644 optee/optee_os/core/drivers/imx/sub.mk create mode 100644 optee/optee_os/core/drivers/imx_caam.c create mode 100644 optee/optee_os/core/drivers/imx_csu.c create mode 100644 optee/optee_os/core/drivers/imx_ele.c create mode 100644 optee/optee_os/core/drivers/imx_i2c.c create mode 100644 optee/optee_os/core/drivers/imx_lpuart.c create mode 100644 optee/optee_os/core/drivers/imx_ocotp.c create mode 100644 optee/optee_os/core/drivers/imx_rngb.c create mode 100644 optee/optee_os/core/drivers/imx_sc_api.c create mode 100644 optee/optee_os/core/drivers/imx_scu.c create mode 100644 optee/optee_os/core/drivers/imx_snvs.c create mode 100644 optee/optee_os/core/drivers/imx_uart.c create mode 100644 optee/optee_os/core/drivers/imx_wdog.c create mode 100644 optee/optee_os/core/drivers/lpc_uart.c create mode 100644 optee/optee_os/core/drivers/ls_dspi.c create mode 100644 optee/optee_os/core/drivers/ls_gpio.c create mode 100644 optee/optee_os/core/drivers/ls_i2c.c create mode 100644 optee/optee_os/core/drivers/ls_sec_mon.c create mode 100644 optee/optee_os/core/drivers/ls_sfp.c create mode 100644 optee/optee_os/core/drivers/mvebu_uart.c create mode 100644 optee/optee_os/core/drivers/ns16550.c create mode 100644 optee/optee_os/core/drivers/pl011.c create mode 100644 optee/optee_os/core/drivers/pl022_spi.c create mode 100644 optee/optee_os/core/drivers/pl061_gpio.c create mode 100644 optee/optee_os/core/drivers/pm/sam/at91_pm.c create mode 100644 optee/optee_os/core/drivers/pm/sam/at91_pm.h create mode 100644 optee/optee_os/core/drivers/pm/sam/pm-defines.c create mode 100644 optee/optee_os/core/drivers/pm/sam/pm_resume.S create mode 100644 optee/optee_os/core/drivers/pm/sam/pm_suspend.S create mode 100644 optee/optee_os/core/drivers/pm/sam/sub.mk create mode 100644 optee/optee_os/core/drivers/pm/sub.mk create mode 100644 optee/optee_os/core/drivers/rstctrl/rstctrl.c create mode 100644 optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c create mode 100644 optee/optee_os/core/drivers/rstctrl/sub.mk create mode 100644 optee/optee_os/core/drivers/rtc/rtc.c create mode 100644 optee/optee_os/core/drivers/rtc/sub.mk create mode 100644 optee/optee_os/core/drivers/scif.c create mode 100644 optee/optee_os/core/drivers/scmi-msg/base.c create mode 100644 optee/optee_os/core/drivers/scmi-msg/base.h create mode 100644 optee/optee_os/core/drivers/scmi-msg/clock.c create mode 100644 optee/optee_os/core/drivers/scmi-msg/clock.h create mode 100644 optee/optee_os/core/drivers/scmi-msg/common.h create mode 100644 optee/optee_os/core/drivers/scmi-msg/entry.c create mode 100644 optee/optee_os/core/drivers/scmi-msg/reset_domain.c create mode 100644 optee/optee_os/core/drivers/scmi-msg/reset_domain.h create mode 100644 optee/optee_os/core/drivers/scmi-msg/shm_msg.c create mode 100644 optee/optee_os/core/drivers/scmi-msg/smt.c create mode 100644 optee/optee_os/core/drivers/scmi-msg/sub.mk create mode 100644 optee/optee_os/core/drivers/scmi-msg/voltage_domain.c create mode 100644 optee/optee_os/core/drivers/scmi-msg/voltage_domain.h create mode 100644 optee/optee_os/core/drivers/serial8250_uart.c create mode 100644 optee/optee_os/core/drivers/smccc_trng.c create mode 100644 optee/optee_os/core/drivers/sp805_wdt.c create mode 100644 optee/optee_os/core/drivers/sprd_uart.c create mode 100644 optee/optee_os/core/drivers/stih_asc.c create mode 100644 optee/optee_os/core/drivers/stm32_bsec.c create mode 100644 optee/optee_os/core/drivers/stm32_etzpc.c create mode 100644 optee/optee_os/core/drivers/stm32_gpio.c create mode 100644 optee/optee_os/core/drivers/stm32_i2c.c create mode 100644 optee/optee_os/core/drivers/stm32_iwdg.c create mode 100644 optee/optee_os/core/drivers/stm32_rng.c create mode 100644 optee/optee_os/core/drivers/stm32_shared_io.c create mode 100644 optee/optee_os/core/drivers/stm32_tamp.c create mode 100644 optee/optee_os/core/drivers/stm32_uart.c create mode 100644 optee/optee_os/core/drivers/stm32mp15_huk.c create mode 100644 optee/optee_os/core/drivers/stpmic1.c create mode 100644 optee/optee_os/core/drivers/sub.mk create mode 100644 optee/optee_os/core/drivers/tegra/common/include/tegra_driver_common.h create mode 100644 optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h create mode 100644 optee/optee_os/core/drivers/tegra/common/include/tegra_driver_rng1.h create mode 100644 optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h create mode 100644 optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h create mode 100644 optee/optee_os/core/drivers/tegra/common/sub.mk create mode 100644 optee/optee_os/core/drivers/tegra/common/tegra_driver_clear_keyslots.c create mode 100644 optee/optee_os/core/drivers/tegra/common/tegra_driver_common.c create mode 100644 optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c create mode 100644 optee/optee_os/core/drivers/tegra/common/tegra_driver_rng1.c create mode 100644 optee/optee_os/core/drivers/tegra/common/tegra_driver_se.c create mode 100644 optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.c create mode 100644 optee/optee_os/core/drivers/tegra/sub.mk create mode 100644 optee/optee_os/core/drivers/tegra/t194/fuse.c create mode 100644 optee/optee_os/core/drivers/tegra/t194/include/tegra_se_mgnt.h create mode 100644 optee/optee_os/core/drivers/tegra/t194/sub.mk create mode 100644 optee/optee_os/core/drivers/tegra/t194/tegra_rpmb.c create mode 100644 optee/optee_os/core/drivers/tegra/t194/tegra_se_aes.c create mode 100644 optee/optee_os/core/drivers/tegra/t194/tegra_se_mgnt.c create mode 100644 optee/optee_os/core/drivers/tegra/t194/tegra_se_rng1.c create mode 100644 optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h create mode 100644 optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc_errno.h create mode 100644 optee/optee_os/core/drivers/tegra/t234/sub.mk create mode 100644 optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c create mode 100644 optee/optee_os/core/drivers/tegra/t234/tegra_rpmb.c create mode 100644 optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c create mode 100644 optee/optee_os/core/drivers/tegra_combined_uart.c create mode 100644 optee/optee_os/core/drivers/tzc380.c create mode 100644 optee/optee_os/core/drivers/tzc400.c create mode 100644 optee/optee_os/core/drivers/versal_gpio.c create mode 100644 optee/optee_os/core/drivers/versal_huk.c create mode 100644 optee/optee_os/core/drivers/versal_mbox.c create mode 100644 optee/optee_os/core/drivers/versal_nvm.c create mode 100644 optee/optee_os/core/drivers/versal_pm.c create mode 100644 optee/optee_os/core/drivers/versal_puf.c create mode 100644 optee/optee_os/core/drivers/versal_sha3_384.c create mode 100644 optee/optee_os/core/drivers/versal_trng.c create mode 100644 optee/optee_os/core/drivers/wdt/sub.mk create mode 100644 optee/optee_os/core/drivers/wdt/watchdog.c create mode 100644 optee/optee_os/core/drivers/wdt/watchdog_sm.c create mode 100644 optee/optee_os/core/drivers/xiphera_trng.c create mode 100644 optee/optee_os/core/drivers/zynqmp_csu_aes.c create mode 100644 optee/optee_os/core/drivers/zynqmp_csu_puf.c create mode 100644 optee/optee_os/core/drivers/zynqmp_csudma.c create mode 100644 optee/optee_os/core/drivers/zynqmp_huk.c create mode 100644 optee/optee_os/core/drivers/zynqmp_pm.c create mode 100644 optee/optee_os/core/include/bench.h create mode 100644 optee/optee_os/core/include/console.h create mode 100644 optee/optee_os/core/include/crypto/crypto.h create mode 100644 optee/optee_os/core/include/crypto/crypto_accel.h create mode 100644 optee/optee_os/core/include/crypto/crypto_impl.h create mode 100644 optee/optee_os/core/include/crypto/crypto_se.h create mode 100644 optee/optee_os/core/include/crypto/internal_aes-gcm.h create mode 100644 optee/optee_os/core/include/crypto/sm2-kdf.h create mode 100644 optee/optee_os/core/include/drivers/amlogic_uart.h create mode 100644 optee/optee_os/core/include/drivers/atmel_rstc.h create mode 100644 optee/optee_os/core/include/drivers/atmel_rtc.h create mode 100644 optee/optee_os/core/include/drivers/atmel_saic.h create mode 100644 optee/optee_os/core/include/drivers/atmel_shdwc.h create mode 100644 optee/optee_os/core/include/drivers/atmel_uart.h create mode 100644 optee/optee_os/core/include/drivers/bcm/bnxt.h create mode 100644 optee/optee_os/core/include/drivers/bcm_gpio.h create mode 100644 optee/optee_os/core/include/drivers/bcm_hwrng.h create mode 100644 optee/optee_os/core/include/drivers/bcm_sotp.h create mode 100644 optee/optee_os/core/include/drivers/caam_extension.h create mode 100644 optee/optee_os/core/include/drivers/cbmem_console.h create mode 100644 optee/optee_os/core/include/drivers/cdns_uart.h create mode 100644 optee/optee_os/core/include/drivers/clk.h create mode 100644 optee/optee_os/core/include/drivers/clk_dt.h create mode 100644 optee/optee_os/core/include/drivers/gic.h create mode 100644 optee/optee_os/core/include/drivers/hfic.h create mode 100644 optee/optee_os/core/include/drivers/hi16xx_uart.h create mode 100644 optee/optee_os/core/include/drivers/i2c.h create mode 100644 optee/optee_os/core/include/drivers/imx/dcp.h create mode 100644 optee/optee_os/core/include/drivers/imx_i2c.h create mode 100644 optee/optee_os/core/include/drivers/imx_mu.h create mode 100644 optee/optee_os/core/include/drivers/imx_ocotp.h create mode 100644 optee/optee_os/core/include/drivers/imx_sc_api.h create mode 100644 optee/optee_os/core/include/drivers/imx_snvs.h create mode 100644 optee/optee_os/core/include/drivers/imx_uart.h create mode 100644 optee/optee_os/core/include/drivers/imx_wdog.h create mode 100644 optee/optee_os/core/include/drivers/lpc_uart.h create mode 100644 optee/optee_os/core/include/drivers/ls_dspi.h create mode 100644 optee/optee_os/core/include/drivers/ls_gpio.h create mode 100644 optee/optee_os/core/include/drivers/ls_i2c.h create mode 100644 optee/optee_os/core/include/drivers/ls_sec_mon.h create mode 100644 optee/optee_os/core/include/drivers/ls_sfp.h create mode 100644 optee/optee_os/core/include/drivers/mvebu_uart.h create mode 100644 optee/optee_os/core/include/drivers/ns16550.h create mode 100644 optee/optee_os/core/include/drivers/pl011.h create mode 100644 optee/optee_os/core/include/drivers/pl022_spi.h create mode 100644 optee/optee_os/core/include/drivers/pl061_gpio.h create mode 100644 optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h create mode 100644 optee/optee_os/core/include/drivers/rstctrl.h create mode 100644 optee/optee_os/core/include/drivers/rtc.h create mode 100644 optee/optee_os/core/include/drivers/sam/at91_ddr.h create mode 100644 optee/optee_os/core/include/drivers/scif.h create mode 100644 optee/optee_os/core/include/drivers/scmi-msg.h create mode 100644 optee/optee_os/core/include/drivers/scmi.h create mode 100644 optee/optee_os/core/include/drivers/serial.h create mode 100644 optee/optee_os/core/include/drivers/serial8250_uart.h create mode 100644 optee/optee_os/core/include/drivers/sp805_wdt.h create mode 100644 optee/optee_os/core/include/drivers/sprd_uart.h create mode 100644 optee/optee_os/core/include/drivers/stih_asc.h create mode 100644 optee/optee_os/core/include/drivers/stm32_bsec.h create mode 100644 optee/optee_os/core/include/drivers/stm32_etzpc.h create mode 100644 optee/optee_os/core/include/drivers/stm32_gpio.h create mode 100644 optee/optee_os/core/include/drivers/stm32_i2c.h create mode 100644 optee/optee_os/core/include/drivers/stm32_iwdg.h create mode 100644 optee/optee_os/core/include/drivers/stm32_shared_io.h create mode 100644 optee/optee_os/core/include/drivers/stm32_tamp.h create mode 100644 optee/optee_os/core/include/drivers/stm32_uart.h create mode 100644 optee/optee_os/core/include/drivers/stm32mp13_rcc.h create mode 100644 optee/optee_os/core/include/drivers/stm32mp1_rcc.h create mode 100644 optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h create mode 100644 optee/optee_os/core/include/drivers/stpmic1.h create mode 100644 optee/optee_os/core/include/drivers/stpmic1_regulator.h create mode 100644 optee/optee_os/core/include/drivers/tegra/tegra_fuse.h create mode 100644 optee/optee_os/core/include/drivers/tegra/tegra_se_aes.h create mode 100644 optee/optee_os/core/include/drivers/tegra/tegra_se_kdf.h create mode 100644 optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h create mode 100644 optee/optee_os/core/include/drivers/tegra/tegra_se_rng.h create mode 100644 optee/optee_os/core/include/drivers/tegra_combined_uart.h create mode 100644 optee/optee_os/core/include/drivers/tzc380.h create mode 100644 optee/optee_os/core/include/drivers/tzc400.h create mode 100644 optee/optee_os/core/include/drivers/versal_gpio.h create mode 100644 optee/optee_os/core/include/drivers/versal_mbox.h create mode 100644 optee/optee_os/core/include/drivers/versal_nvm.h create mode 100644 optee/optee_os/core/include/drivers/versal_pm.h create mode 100644 optee/optee_os/core/include/drivers/versal_puf.h create mode 100644 optee/optee_os/core/include/drivers/versal_sha3_384.h create mode 100644 optee/optee_os/core/include/drivers/wdt.h create mode 100644 optee/optee_os/core/include/drivers/zynqmp_csu.h create mode 100644 optee/optee_os/core/include/drivers/zynqmp_csu_aes.h create mode 100644 optee/optee_os/core/include/drivers/zynqmp_csu_puf.h create mode 100644 optee/optee_os/core/include/drivers/zynqmp_csudma.h create mode 100644 optee/optee_os/core/include/drivers/zynqmp_efuse.h create mode 100644 optee/optee_os/core/include/drivers/zynqmp_huk.h create mode 100644 optee/optee_os/core/include/drivers/zynqmp_pm.h create mode 100644 optee/optee_os/core/include/dt-bindings/clock/at91.h create mode 100644 optee/optee_os/core/include/dt-bindings/clock/stm32mp1-clks.h create mode 100644 optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h create mode 100644 optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clksrc.h create mode 100644 optee/optee_os/core/include/dt-bindings/dma/at91.h create mode 100644 optee/optee_os/core/include/dt-bindings/gpio/atmel,piobu.h create mode 100644 optee/optee_os/core/include/dt-bindings/gpio/gpio.h create mode 100644 optee/optee_os/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h create mode 100644 optee/optee_os/core/include/dt-bindings/interrupt-controller/arm-gic.h create mode 100644 optee/optee_os/core/include/dt-bindings/interrupt-controller/irq.h create mode 100644 optee/optee_os/core/include/dt-bindings/mfd/atmel-flexcom.h create mode 100644 optee/optee_os/core/include/dt-bindings/mfd/st,stpmic1.h create mode 100644 optee/optee_os/core/include/dt-bindings/pinctrl/stm32-pinfunc.h create mode 100644 optee/optee_os/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h create mode 100644 optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h create mode 100644 optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h create mode 100644 optee/optee_os/core/include/dt-bindings/reset/stm32mp1-resets.h create mode 100644 optee/optee_os/core/include/dt-bindings/reset/stm32mp13-resets.h create mode 100644 optee/optee_os/core/include/gen-asm-defines.h create mode 100644 optee/optee_os/core/include/gpio.h create mode 100644 optee/optee_os/core/include/initcall.h create mode 100644 optee/optee_os/core/include/io.h create mode 100644 optee/optee_os/core/include/keep.h create mode 100644 optee/optee_os/core/include/kernel/abort.h create mode 100644 optee/optee_os/core/include/kernel/asan.h create mode 100644 optee/optee_os/core/include/kernel/boot.h create mode 100644 optee/optee_os/core/include/kernel/cache_helpers.h create mode 100644 optee/optee_os/core/include/kernel/chip_services.h create mode 100644 optee/optee_os/core/include/kernel/delay.h create mode 100644 optee/optee_os/core/include/kernel/dt.h create mode 100644 optee/optee_os/core/include/kernel/dt_driver.h create mode 100644 optee/optee_os/core/include/kernel/early_ta.h create mode 100644 optee/optee_os/core/include/kernel/embedded_ts.h create mode 100644 optee/optee_os/core/include/kernel/handle.h create mode 100644 optee/optee_os/core/include/kernel/huk_subkey.h create mode 100644 optee/optee_os/core/include/kernel/interrupt.h create mode 100644 optee/optee_os/core/include/kernel/ldelf_loader.h create mode 100644 optee/optee_os/core/include/kernel/ldelf_syscalls.h create mode 100644 optee/optee_os/core/include/kernel/linker.h create mode 100644 optee/optee_os/core/include/kernel/lockdep.h create mode 100644 optee/optee_os/core/include/kernel/misc.h create mode 100644 optee/optee_os/core/include/kernel/msg_param.h create mode 100644 optee/optee_os/core/include/kernel/mutex.h create mode 100644 optee/optee_os/core/include/kernel/notif.h create mode 100644 optee/optee_os/core/include/kernel/panic.h create mode 100644 optee/optee_os/core/include/kernel/pm.h create mode 100644 optee/optee_os/core/include/kernel/pseudo_ta.h create mode 100644 optee/optee_os/core/include/kernel/refcount.h create mode 100644 optee/optee_os/core/include/kernel/rpc_io_i2c.h create mode 100644 optee/optee_os/core/include/kernel/scall.h create mode 100644 optee/optee_os/core/include/kernel/spinlock.h create mode 100644 optee/optee_os/core/include/kernel/tee_common.h create mode 100644 optee/optee_os/core/include/kernel/tee_common_otp.h create mode 100644 optee/optee_os/core/include/kernel/tee_misc.h create mode 100644 optee/optee_os/core/include/kernel/tee_ta_manager.h create mode 100644 optee/optee_os/core/include/kernel/tee_time.h create mode 100644 optee/optee_os/core/include/kernel/thread.h create mode 100644 optee/optee_os/core/include/kernel/thread_private.h create mode 100644 optee/optee_os/core/include/kernel/time_source.h create mode 100644 optee/optee_os/core/include/kernel/timer.h create mode 100644 optee/optee_os/core/include/kernel/tpm.h create mode 100644 optee/optee_os/core/include/kernel/trace_ta.h create mode 100644 optee/optee_os/core/include/kernel/ts_manager.h create mode 100644 optee/optee_os/core/include/kernel/ts_store.h create mode 100644 optee/optee_os/core/include/kernel/unwind.h create mode 100644 optee/optee_os/core/include/kernel/user_access.h create mode 100644 optee/optee_os/core/include/kernel/user_mode_ctx.h create mode 100644 optee/optee_os/core/include/kernel/user_mode_ctx_struct.h create mode 100644 optee/optee_os/core/include/kernel/user_ta.h create mode 100644 optee/optee_os/core/include/kernel/virtualization.h create mode 100644 optee/optee_os/core/include/kernel/wait_queue.h create mode 100644 optee/optee_os/core/include/mm/core_memprot.h create mode 100644 optee/optee_os/core/include/mm/core_mmu.h create mode 100644 optee/optee_os/core/include/mm/file.h create mode 100644 optee/optee_os/core/include/mm/fobj.h create mode 100644 optee/optee_os/core/include/mm/mobj.h create mode 100644 optee/optee_os/core/include/mm/pgt_cache.h create mode 100644 optee/optee_os/core/include/mm/sp_mem.h create mode 100644 optee/optee_os/core/include/mm/tee_mm.h create mode 100644 optee/optee_os/core/include/mm/tee_mmu_types.h create mode 100644 optee/optee_os/core/include/mm/tee_pager.h create mode 100644 optee/optee_os/core/include/mm/vm.h create mode 100644 optee/optee_os/core/include/optee_msg.h create mode 100644 optee/optee_os/core/include/optee_rpc_cmd.h create mode 100644 optee/optee_os/core/include/rng_support.h create mode 100644 optee/optee_os/core/include/scattered_array.h create mode 100644 optee/optee_os/core/include/signed_hdr.h create mode 100644 optee/optee_os/core/include/spi.h create mode 100644 optee/optee_os/core/include/ta_pub_key.h create mode 100644 optee/optee_os/core/include/tee/cache.h create mode 100644 optee/optee_os/core/include/tee/entry_std.h create mode 100644 optee/optee_os/core/include/tee/fs_dirfile.h create mode 100644 optee/optee_os/core/include/tee/fs_htree.h create mode 100644 optee/optee_os/core/include/tee/svc_cache.h create mode 100644 optee/optee_os/core/include/tee/tadb.h create mode 100644 optee/optee_os/core/include/tee/tee_cryp_concat_kdf.h create mode 100644 optee/optee_os/core/include/tee/tee_cryp_hkdf.h create mode 100644 optee/optee_os/core/include/tee/tee_cryp_pbkdf2.h create mode 100644 optee/optee_os/core/include/tee/tee_cryp_utl.h create mode 100644 optee/optee_os/core/include/tee/tee_fs.h create mode 100644 optee/optee_os/core/include/tee/tee_fs_key_manager.h create mode 100644 optee/optee_os/core/include/tee/tee_fs_rpc.h create mode 100644 optee/optee_os/core/include/tee/tee_obj.h create mode 100644 optee/optee_os/core/include/tee/tee_pobj.h create mode 100644 optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h create mode 100644 optee/optee_os/core/include/tee/tee_svc.h create mode 100644 optee/optee_os/core/include/tee/tee_svc_cryp.h create mode 100644 optee/optee_os/core/include/tee/tee_svc_storage.h create mode 100644 optee/optee_os/core/include/tee/tee_ta_enc_manager.h create mode 100644 optee/optee_os/core/include/tee/uuid.h create mode 100644 optee/optee_os/core/kernel/asan.c create mode 100644 optee/optee_os/core/kernel/assert.c create mode 100644 optee/optee_os/core/kernel/console.c create mode 100644 optee/optee_os/core/kernel/delay.c create mode 100644 optee/optee_os/core/kernel/dt.c create mode 100644 optee/optee_os/core/kernel/dt_driver.c create mode 100644 optee/optee_os/core/kernel/dt_driver_test.c create mode 100644 optee/optee_os/core/kernel/early_ta.c create mode 100644 optee/optee_os/core/kernel/embedded_ts.c create mode 100644 optee/optee_os/core/kernel/handle.c create mode 100644 optee/optee_os/core/kernel/huk_subkey.c create mode 100644 optee/optee_os/core/kernel/initcall.c create mode 100644 optee/optee_os/core/kernel/interrupt.c create mode 100644 optee/optee_os/core/kernel/ldelf_loader.c create mode 100644 optee/optee_os/core/kernel/ldelf_syscalls.c create mode 100644 optee/optee_os/core/kernel/lockdep.c create mode 100644 optee/optee_os/core/kernel/msg_param.c create mode 100644 optee/optee_os/core/kernel/mutex.c create mode 100644 optee/optee_os/core/kernel/mutex_lockdep.c create mode 100644 optee/optee_os/core/kernel/mutex_lockdep.h create mode 100644 optee/optee_os/core/kernel/notif.c create mode 100644 optee/optee_os/core/kernel/otp_stubs.c create mode 100644 optee/optee_os/core/kernel/panic.c create mode 100644 optee/optee_os/core/kernel/pm.c create mode 100644 optee/optee_os/core/kernel/pseudo_ta.c create mode 100644 optee/optee_os/core/kernel/ree_fs_ta.c create mode 100644 optee/optee_os/core/kernel/refcount.c create mode 100644 optee/optee_os/core/kernel/scall.c create mode 100644 optee/optee_os/core/kernel/scattered_array.c create mode 100644 optee/optee_os/core/kernel/secstor_ta.c create mode 100644 optee/optee_os/core/kernel/show_conf.c create mode 100644 optee/optee_os/core/kernel/spin_lock_debug.c create mode 100644 optee/optee_os/core/kernel/sub.mk create mode 100644 optee/optee_os/core/kernel/tee_misc.c create mode 100644 optee/optee_os/core/kernel/tee_ta_manager.c create mode 100644 optee/optee_os/core/kernel/tee_time.c create mode 100644 optee/optee_os/core/kernel/tee_time_ree.c create mode 100644 optee/optee_os/core/kernel/thread.c create mode 100644 optee/optee_os/core/kernel/tpm.c create mode 100644 optee/optee_os/core/kernel/trace_ext.c create mode 100644 optee/optee_os/core/kernel/ts_manager.c create mode 100644 optee/optee_os/core/kernel/ubsan.c create mode 100644 optee/optee_os/core/kernel/user_access.c create mode 100644 optee/optee_os/core/kernel/user_mode_ctx.c create mode 100644 optee/optee_os/core/kernel/user_ta.c create mode 100644 optee/optee_os/core/kernel/wait_queue.c create mode 100644 optee/optee_os/core/lib/libfdt/README.license create mode 100644 optee/optee_os/core/lib/libfdt/fdt.c create mode 100644 optee/optee_os/core/lib/libfdt/fdt_addresses.c create mode 100644 optee/optee_os/core/lib/libfdt/fdt_empty_tree.c create mode 100644 optee/optee_os/core/lib/libfdt/fdt_overlay.c create mode 100644 optee/optee_os/core/lib/libfdt/fdt_ro.c create mode 100644 optee/optee_os/core/lib/libfdt/fdt_rw.c create mode 100644 optee/optee_os/core/lib/libfdt/fdt_strerror.c create mode 100644 optee/optee_os/core/lib/libfdt/fdt_sw.c create mode 100644 optee/optee_os/core/lib/libfdt/fdt_wip.c create mode 100644 optee/optee_os/core/lib/libfdt/include/fdt.h create mode 100644 optee/optee_os/core/lib/libfdt/include/libfdt.h create mode 100644 optee/optee_os/core/lib/libfdt/include/libfdt_env.h create mode 100644 optee/optee_os/core/lib/libfdt/libfdt_internal.h create mode 100644 optee/optee_os/core/lib/libfdt/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/acipher_helpers.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/aes.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/aes_accel.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/cbc.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/ccm.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/cmac.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/ctr.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/des2_key.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/dh.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/dsa.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/ecb.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/ecc.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/ed25519.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/gcm.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/hmac.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_init.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_mp.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/mpi_desc.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/rsa.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/sha1_accel.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/sha256_accel.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/sha3_accel.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/sha512_accel.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/shake.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/sm2-kep.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/sm2-pke.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/anubis.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/blowfish.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/camellia.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/cast5.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/des.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/idea.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/kasumi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/khazad.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/kseed.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/multi2.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/noekeon.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc2.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc5.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc6.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer_tab.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/saferp.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/serpent.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/skipjack.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/tea.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/ciphers/xtea.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_process.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/encauth/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2b.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/chc/chc.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/md2.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/md4.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/md5.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd128.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd160.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd256.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd320.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha1.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha224.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha256.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha384.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/tiger.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirl.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_math.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_private.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_process.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_process.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/omac/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/fp/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/gmp_desc.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/ltm_desc.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/radix_to_bin.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/rand_bn.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/rand_prime.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/math/tfm_desc.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/adler32.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_decode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_encode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_decode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_encode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_decode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_encode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/base64/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/burn_stack.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/compare_testvector.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/copy_or_zeromem.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crc32.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/error_to_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/mem_neq.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_depad.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_pad.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes1.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes2.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/misc/zeromem.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_start.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/f8/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/xts/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_init.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_check_pubkey.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_free.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_import.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_make_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_shared_secret.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dh/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export_openssl.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_sign.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_verify.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_get_size.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_set.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_export.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_make_key.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_shared_secret.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/chacha20.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/fortuna.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/rc4.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/sober128.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/sprng.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_setup.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128tab.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/src/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/sub.mk create mode 100644 optee/optee_os/core/lib/libtomcrypt/tomcrypt.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/x25519.c create mode 100644 optee/optee_os/core/lib/libtomcrypt/xts.c create mode 100644 optee/optee_os/core/lib/scmi-server/conf-optee-fvp.mk create mode 100644 optee/optee_os/core/lib/scmi-server/conf-optee-stm32mp1.mk create mode 100644 optee/optee_os/core/lib/scmi-server/conf.mk create mode 100644 optee/optee_os/core/lib/scmi-server/include/optee_scmi.h create mode 100644 optee/optee_os/core/lib/scmi-server/scmi_server.c create mode 100644 optee/optee_os/core/lib/scmi-server/sub-optee-fvp.mk create mode 100644 optee/optee_os/core/lib/scmi-server/sub-optee-stm32mp1.mk create mode 100644 optee/optee_os/core/lib/scmi-server/sub.mk create mode 100644 optee/optee_os/core/lib/zlib/adler32.c create mode 100644 optee/optee_os/core/lib/zlib/gzguts.h create mode 100644 optee/optee_os/core/lib/zlib/inffast.c create mode 100644 optee/optee_os/core/lib/zlib/inffast.h create mode 100644 optee/optee_os/core/lib/zlib/inffixed.h create mode 100644 optee/optee_os/core/lib/zlib/inflate.c create mode 100644 optee/optee_os/core/lib/zlib/inflate.h create mode 100644 optee/optee_os/core/lib/zlib/inftrees.c create mode 100644 optee/optee_os/core/lib/zlib/inftrees.h create mode 100644 optee/optee_os/core/lib/zlib/sub.mk create mode 100644 optee/optee_os/core/lib/zlib/zconf.h create mode 100644 optee/optee_os/core/lib/zlib/zlib.h create mode 100644 optee/optee_os/core/lib/zlib/zutil.c create mode 100644 optee/optee_os/core/lib/zlib/zutil.h create mode 100644 optee/optee_os/core/mm/core_mmu.c create mode 100644 optee/optee_os/core/mm/file.c create mode 100644 optee/optee_os/core/mm/fobj.c create mode 100644 optee/optee_os/core/mm/mobj.c create mode 100644 optee/optee_os/core/mm/sub.mk create mode 100644 optee/optee_os/core/mm/tee_mm.c create mode 100644 optee/optee_os/core/mm/vm.c create mode 100644 optee/optee_os/core/pta/apdu.c create mode 100644 optee/optee_os/core/pta/attestation.c create mode 100644 optee/optee_os/core/pta/bcm/bnxt.c create mode 100644 optee/optee_os/core/pta/bcm/elog.c create mode 100644 optee/optee_os/core/pta/bcm/gpio.c create mode 100644 optee/optee_os/core/pta/bcm/hwrng.c create mode 100644 optee/optee_os/core/pta/bcm/sotp.c create mode 100644 optee/optee_os/core/pta/bcm/sub.mk create mode 100644 optee/optee_os/core/pta/bcm/wdt.c create mode 100644 optee/optee_os/core/pta/benchmark.c create mode 100644 optee/optee_os/core/pta/device.c create mode 100644 optee/optee_os/core/pta/gprof.c create mode 100644 optee/optee_os/core/pta/hwrng.c create mode 100644 optee/optee_os/core/pta/imx/digprog.c create mode 100644 optee/optee_os/core/pta/imx/manufacturing_protection.c create mode 100644 optee/optee_os/core/pta/imx/ocotp.c create mode 100644 optee/optee_os/core/pta/imx/sub.mk create mode 100644 optee/optee_os/core/pta/k3/otp.c create mode 100644 optee/optee_os/core/pta/k3/sub.mk create mode 100644 optee/optee_os/core/pta/rtc.c create mode 100644 optee/optee_os/core/pta/scmi.c create mode 100644 optee/optee_os/core/pta/scp03.c create mode 100644 optee/optee_os/core/pta/secstor_ta_mgmt.c create mode 100644 optee/optee_os/core/pta/stats.c create mode 100644 optee/optee_os/core/pta/stm32mp/bsec_pta.c create mode 100644 optee/optee_os/core/pta/stm32mp/sub.mk create mode 100644 optee/optee_os/core/pta/sub.mk create mode 100644 optee/optee_os/core/pta/system.c create mode 100644 optee/optee_os/core/pta/tegra/jetson_decrypt_cpubl_payload.h create mode 100644 optee/optee_os/core/pta/tegra/jetson_t194_decrypt_cpubl_payload.c create mode 100644 optee/optee_os/core/pta/tegra/jetson_t234_decrypt_cpubl_payload.c create mode 100644 optee/optee_os/core/pta/tegra/jetson_user_key_pta.c create mode 100644 optee/optee_os/core/pta/tegra/sub.mk create mode 100644 optee/optee_os/core/pta/tests/aes_perf.c create mode 100644 optee/optee_os/core/pta/tests/fs_htree.c create mode 100644 optee/optee_os/core/pta/tests/invoke.c create mode 100644 optee/optee_os/core/pta/tests/lockdep.c create mode 100644 optee/optee_os/core/pta/tests/misc.c create mode 100644 optee/optee_os/core/pta/tests/misc.h create mode 100644 optee/optee_os/core/pta/tests/mutex.c create mode 100644 optee/optee_os/core/pta/tests/sub.mk create mode 100644 optee/optee_os/core/sub.mk create mode 100644 optee/optee_os/core/tee/entry_std.c create mode 100644 optee/optee_os/core/tee/fs_dirfile.c create mode 100644 optee/optee_os/core/tee/fs_htree.c create mode 100644 optee/optee_os/core/tee/socket.c create mode 100644 optee/optee_os/core/tee/sub.mk create mode 100644 optee/optee_os/core/tee/tadb.c create mode 100644 optee/optee_os/core/tee/tee_cryp_concat_kdf.c create mode 100644 optee/optee_os/core/tee/tee_cryp_hkdf.c create mode 100644 optee/optee_os/core/tee/tee_cryp_pbkdf2.c create mode 100644 optee/optee_os/core/tee/tee_cryp_utl.c create mode 100644 optee/optee_os/core/tee/tee_fs_key_manager.c create mode 100644 optee/optee_os/core/tee/tee_fs_rpc.c create mode 100644 optee/optee_os/core/tee/tee_nvme_rpmb_fs.c create mode 100644 optee/optee_os/core/tee/tee_obj.c create mode 100644 optee/optee_os/core/tee/tee_pobj.c create mode 100644 optee/optee_os/core/tee/tee_ree_fs.c create mode 100644 optee/optee_os/core/tee/tee_rpmb_fs.c create mode 100644 optee/optee_os/core/tee/tee_supp_plugin_rpc.c create mode 100644 optee/optee_os/core/tee/tee_svc.c create mode 100644 optee/optee_os/core/tee/tee_svc_cryp.c create mode 100644 optee/optee_os/core/tee/tee_svc_storage.c create mode 100644 optee/optee_os/core/tee/tee_ta_enc_manager.c create mode 100644 optee/optee_os/core/tee/tee_time_generic.c create mode 100644 optee/optee_os/core/tee/uuid.c create mode 100644 optee/optee_os/core/tests/ftmn_boot_tests.c create mode 100644 optee/optee_os/core/tests/sub.mk create mode 100644 optee/optee_os/keys/default_ta.pem create mode 100644 optee/optee_os/ldelf/dl.c create mode 100644 optee/optee_os/ldelf/dl.h create mode 100644 optee/optee_os/ldelf/ftrace.c create mode 100644 optee/optee_os/ldelf/ftrace.h create mode 100644 optee/optee_os/ldelf/include/ldelf.h create mode 100644 optee/optee_os/ldelf/include/ldelf_syscalls.h create mode 100644 optee/optee_os/ldelf/ldelf.ld.S create mode 100644 optee/optee_os/ldelf/ldelf.mk create mode 100644 optee/optee_os/ldelf/link.mk create mode 100644 optee/optee_os/ldelf/main.c create mode 100644 optee/optee_os/ldelf/pauth.c create mode 100644 optee/optee_os/ldelf/pauth.h create mode 100644 optee/optee_os/ldelf/start_a32.S create mode 100644 optee/optee_os/ldelf/start_a64.S create mode 100644 optee/optee_os/ldelf/start_rv64.S create mode 100644 optee/optee_os/ldelf/sub.mk create mode 100644 optee/optee_os/ldelf/sys.c create mode 100644 optee/optee_os/ldelf/sys.h create mode 100644 optee/optee_os/ldelf/syscalls_a32.S create mode 100644 optee/optee_os/ldelf/syscalls_a64.S create mode 100644 optee/optee_os/ldelf/syscalls_asm.S create mode 100644 optee/optee_os/ldelf/syscalls_rv.S create mode 100644 optee/optee_os/ldelf/ta_elf.c create mode 100644 optee/optee_os/ldelf/ta_elf.h create mode 100644 optee/optee_os/ldelf/ta_elf_rel.c create mode 100644 optee/optee_os/ldelf/tlsdesc_rel_a64.S create mode 100644 optee/optee_os/lib/libdl/dlfcn.c create mode 100644 optee/optee_os/lib/libdl/include/dlfcn.h create mode 100644 optee/optee_os/lib/libdl/sub.mk create mode 100644 optee/optee_os/lib/libmbedtls/core/aes.c create mode 100644 optee/optee_os/lib/libmbedtls/core/aes_cbc.c create mode 100644 optee/optee_os/lib/libmbedtls/core/aes_ctr.c create mode 100644 optee/optee_os/lib/libmbedtls/core/aes_ecb.c create mode 100644 optee/optee_os/lib/libmbedtls/core/bignum.c create mode 100644 optee/optee_os/lib/libmbedtls/core/cmac.c create mode 100644 optee/optee_os/lib/libmbedtls/core/des3_cbc.c create mode 100644 optee/optee_os/lib/libmbedtls/core/des3_ecb.c create mode 100644 optee/optee_os/lib/libmbedtls/core/des_cbc.c create mode 100644 optee/optee_os/lib/libmbedtls/core/des_ecb.c create mode 100644 optee/optee_os/lib/libmbedtls/core/dh.c create mode 100644 optee/optee_os/lib/libmbedtls/core/ecc.c create mode 100644 optee/optee_os/lib/libmbedtls/core/hash.c create mode 100644 optee/optee_os/lib/libmbedtls/core/hmac.c create mode 100644 optee/optee_os/lib/libmbedtls/core/mbed_helpers.c create mode 100644 optee/optee_os/lib/libmbedtls/core/mbed_helpers.h create mode 100644 optee/optee_os/lib/libmbedtls/core/rsa.c create mode 100644 optee/optee_os/lib/libmbedtls/core/sm2-dsa.c create mode 100644 optee/optee_os/lib/libmbedtls/core/sm2-dsa.h create mode 100644 optee/optee_os/lib/libmbedtls/core/sm2-kep.c create mode 100644 optee/optee_os/lib/libmbedtls/core/sm2-pke.c create mode 100644 optee/optee_os/lib/libmbedtls/core/sm2-pke.h create mode 100644 optee/optee_os/lib/libmbedtls/core/sub.mk create mode 100644 optee/optee_os/lib/libmbedtls/core/tomcrypt.c create mode 100644 optee/optee_os/lib/libmbedtls/include/aes_alt.h create mode 100644 optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h create mode 100644 optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/LICENSE create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/README.md create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/dco.txt create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/certs.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/havege.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md2.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md4.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/arc4.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/base64.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/blowfish.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/certs.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/common.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_invasive.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/des.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/error.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/havege.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/md.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/md2.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/md4.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs11.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_internal.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cli.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_srv.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/version.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c create mode 100644 optee/optee_os/lib/libmbedtls/mbedtls/library/xtea.c create mode 100644 optee/optee_os/lib/libmbedtls/sub.mk create mode 100644 optee/optee_os/lib/libunw/include/unw/unwind.h create mode 100644 optee/optee_os/lib/libunw/sub.mk create mode 100644 optee/optee_os/lib/libunw/unwind_arm32.c create mode 100644 optee/optee_os/lib/libunw/unwind_arm64.c create mode 100644 optee/optee_os/lib/libutee/abort.c create mode 100644 optee/optee_os/lib/libutee/arch/arm/arm32_user_sysreg.txt create mode 100644 optee/optee_os/lib/libutee/arch/arm/gprof/gmon.h create mode 100644 optee/optee_os/lib/libutee/arch/arm/gprof/gmon_out.h create mode 100644 optee/optee_os/lib/libutee/arch/arm/gprof/gprof.c create mode 100644 optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.c create mode 100644 optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.h create mode 100644 optee/optee_os/lib/libutee/arch/arm/gprof/sub.mk create mode 100644 optee/optee_os/lib/libutee/arch/arm/sub.mk create mode 100644 optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a32.S create mode 100644 optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S create mode 100644 optee/optee_os/lib/libutee/arch/riscv/sub.mk create mode 100644 optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S create mode 100644 optee/optee_os/lib/libutee/assert.c create mode 100644 optee/optee_os/lib/libutee/base64.c create mode 100644 optee/optee_os/lib/libutee/base64.h create mode 100644 optee/optee_os/lib/libutee/include/__tee_ipsocket.h create mode 100644 optee/optee_os/lib/libutee/include/__tee_isocket_defines.h create mode 100644 optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines.h create mode 100644 optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines_extensions.h create mode 100644 optee/optee_os/lib/libutee/include/__tee_udpsocket_defines.h create mode 100644 optee/optee_os/lib/libutee/include/arm64_user_sysreg.h create mode 100644 optee/optee_os/lib/libutee/include/arm_user_sysreg.h create mode 100644 optee/optee_os/lib/libutee/include/elf.h create mode 100644 optee/optee_os/lib/libutee/include/elf32.h create mode 100644 optee/optee_os/lib/libutee/include/elf64.h create mode 100644 optee/optee_os/lib/libutee/include/elf_common.h create mode 100644 optee/optee_os/lib/libutee/include/k3/otp_keywriting_ta.h create mode 100644 optee/optee_os/lib/libutee/include/link.h create mode 100644 optee/optee_os/lib/libutee/include/pta_apdu.h create mode 100644 optee/optee_os/lib/libutee/include/pta_attestation.h create mode 100644 optee/optee_os/lib/libutee/include/pta_benchmark.h create mode 100644 optee/optee_os/lib/libutee/include/pta_device.h create mode 100644 optee/optee_os/lib/libutee/include/pta_gprof.h create mode 100644 optee/optee_os/lib/libutee/include/pta_imx_digprog.h create mode 100644 optee/optee_os/lib/libutee/include/pta_imx_manufacturing_protection.h create mode 100644 optee/optee_os/lib/libutee/include/pta_imx_ocotp.h create mode 100644 optee/optee_os/lib/libutee/include/pta_invoke_tests.h create mode 100644 optee/optee_os/lib/libutee/include/pta_jetson_user_key.h create mode 100644 optee/optee_os/lib/libutee/include/pta_rng.h create mode 100644 optee/optee_os/lib/libutee/include/pta_rtc.h create mode 100644 optee/optee_os/lib/libutee/include/pta_scmi_client.h create mode 100644 optee/optee_os/lib/libutee/include/pta_scp03.h create mode 100644 optee/optee_os/lib/libutee/include/pta_secstor_ta_mgmt.h create mode 100644 optee/optee_os/lib/libutee/include/pta_socket.h create mode 100644 optee/optee_os/lib/libutee/include/pta_stm32mp_bsec.h create mode 100644 optee/optee_os/lib/libutee/include/pta_system.h create mode 100644 optee/optee_os/lib/libutee/include/rng_pta_client.h create mode 100644 optee/optee_os/lib/libutee/include/tee_api.h create mode 100644 optee/optee_os/lib/libutee/include/tee_api_compat.h create mode 100644 optee/optee_os/lib/libutee/include/tee_api_defines.h create mode 100644 optee/optee_os/lib/libutee/include/tee_api_defines_extensions.h create mode 100644 optee/optee_os/lib/libutee/include/tee_api_types.h create mode 100644 optee/optee_os/lib/libutee/include/tee_arith_internal.h create mode 100644 optee/optee_os/lib/libutee/include/tee_internal_api.h create mode 100644 optee/optee_os/lib/libutee/include/tee_internal_api_extensions.h create mode 100644 optee/optee_os/lib/libutee/include/tee_isocket.h create mode 100644 optee/optee_os/lib/libutee/include/tee_syscall_numbers.h create mode 100644 optee/optee_os/lib/libutee/include/tee_ta_api.h create mode 100644 optee/optee_os/lib/libutee/include/tee_tcpsocket.h create mode 100644 optee/optee_os/lib/libutee/include/tee_udpsocket.h create mode 100644 optee/optee_os/lib/libutee/include/user_ta_header.h create mode 100644 optee/optee_os/lib/libutee/include/utee_defines.h create mode 100644 optee/optee_os/lib/libutee/include/utee_syscalls.h create mode 100644 optee/optee_os/lib/libutee/include/utee_syscalls_asm.S create mode 100644 optee/optee_os/lib/libutee/include/utee_types.h create mode 100644 optee/optee_os/lib/libutee/sub.mk create mode 100644 optee/optee_os/lib/libutee/tcb.c create mode 100644 optee/optee_os/lib/libutee/tee_api.c create mode 100644 optee/optee_os/lib/libutee/tee_api_arith_mpi.c create mode 100644 optee/optee_os/lib/libutee/tee_api_objects.c create mode 100644 optee/optee_os/lib/libutee/tee_api_operations.c create mode 100644 optee/optee_os/lib/libutee/tee_api_panic.c create mode 100644 optee/optee_os/lib/libutee/tee_api_private.h create mode 100644 optee/optee_os/lib/libutee/tee_api_property.c create mode 100644 optee/optee_os/lib/libutee/tee_socket_private.h create mode 100644 optee/optee_os/lib/libutee/tee_socket_pta.c create mode 100644 optee/optee_os/lib/libutee/tee_system_pta.c create mode 100644 optee/optee_os/lib/libutee/tee_tcpudp_socket.c create mode 100644 optee/optee_os/lib/libutee/tee_uuid_from_str.c create mode 100644 optee/optee_os/lib/libutee/trace_ext.c create mode 100644 optee/optee_os/lib/libutee/user_ta_entry.c create mode 100644 optee/optee_os/lib/libutee/user_ta_entry_compat.c create mode 100644 optee/optee_os/lib/libutils/ext/arch/arm/aeabi_unwind.c create mode 100644 optee/optee_os/lib/libutils/ext/arch/arm/atomic_a32.S create mode 100644 optee/optee_os/lib/libutils/ext/arch/arm/atomic_a64.S create mode 100644 optee/optee_os/lib/libutils/ext/arch/arm/auxval.c create mode 100644 optee/optee_os/lib/libutils/ext/arch/arm/mcount_a32.S create mode 100644 optee/optee_os/lib/libutils/ext/arch/arm/mcount_a64.S create mode 100644 optee/optee_os/lib/libutils/ext/arch/arm/memtag.c create mode 100644 optee/optee_os/lib/libutils/ext/arch/arm/sub.mk create mode 100644 optee/optee_os/lib/libutils/ext/arch/riscv/atomic_rv.S create mode 100644 optee/optee_os/lib/libutils/ext/arch/riscv/sub.mk create mode 100644 optee/optee_os/lib/libutils/ext/consttime_memcmp.c create mode 100644 optee/optee_os/lib/libutils/ext/fault_mitigation.c create mode 100644 optee/optee_os/lib/libutils/ext/ftrace/ftrace.c create mode 100644 optee/optee_os/lib/libutils/ext/ftrace/ftrace.h create mode 100644 optee/optee_os/lib/libutils/ext/ftrace/sub.mk create mode 100644 optee/optee_os/lib/libutils/ext/include/arm64_bti.S create mode 100644 optee/optee_os/lib/libutils/ext/include/asm.S create mode 100644 optee/optee_os/lib/libutils/ext/include/atomic.h create mode 100644 optee/optee_os/lib/libutils/ext/include/bitstring.h create mode 100644 optee/optee_os/lib/libutils/ext/include/compiler.h create mode 100644 optee/optee_os/lib/libutils/ext/include/config.h create mode 100644 optee/optee_os/lib/libutils/ext/include/confine_array_index.h create mode 100644 optee/optee_os/lib/libutils/ext/include/fault_mitigation.h create mode 100644 optee/optee_os/lib/libutils/ext/include/mempool.h create mode 100644 optee/optee_os/lib/libutils/ext/include/memtag.h create mode 100644 optee/optee_os/lib/libutils/ext/include/printk.h create mode 100644 optee/optee_os/lib/libutils/ext/include/speculation_barrier.h create mode 100644 optee/optee_os/lib/libutils/ext/include/stdlib_ext.h create mode 100644 optee/optee_os/lib/libutils/ext/include/string_ext.h create mode 100644 optee/optee_os/lib/libutils/ext/include/trace.h create mode 100644 optee/optee_os/lib/libutils/ext/include/trace_levels.h create mode 100644 optee/optee_os/lib/libutils/ext/include/types_ext.h create mode 100644 optee/optee_os/lib/libutils/ext/include/util.h create mode 100644 optee/optee_os/lib/libutils/ext/mempool.c create mode 100644 optee/optee_os/lib/libutils/ext/memzero_explicit.c create mode 100644 optee/optee_os/lib/libutils/ext/nex_strdup.c create mode 100644 optee/optee_os/lib/libutils/ext/pthread_stubs.c create mode 100644 optee/optee_os/lib/libutils/ext/snprintk.c create mode 100644 optee/optee_os/lib/libutils/ext/strlcat.c create mode 100644 optee/optee_os/lib/libutils/ext/strlcpy.c create mode 100644 optee/optee_os/lib/libutils/ext/sub.mk create mode 100644 optee/optee_os/lib/libutils/ext/trace.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a64.S create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/COPYING.txt create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.html create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.txt create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/arm32_include/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/Makefile create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/Makefile create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/Makefile create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/Makefile create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/Makefile create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/Makefile create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/Makefile create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/Makefile create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/platform.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.html create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-source.html create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/sub.mk create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_add.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_add.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sqrt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_add.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitives.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalExtF80Sig.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128Sig.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128SigM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF64Sig.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_remStepMBy32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft64To96M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRight128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64Extra.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/sub.mk create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f64.c create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/sub.mk create mode 100644 optee/optee_os/lib/libutils/isoc/arch/arm/sub.mk create mode 100644 optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S create mode 100644 optee/optee_os/lib/libutils/isoc/arch/riscv/sub.mk create mode 100644 optee/optee_os/lib/libutils/isoc/bget.c create mode 100644 optee/optee_os/lib/libutils/isoc/bget.doc create mode 100644 optee/optee_os/lib/libutils/isoc/bget.h create mode 100644 optee/optee_os/lib/libutils/isoc/bget_malloc.c create mode 100644 optee/optee_os/lib/libutils/isoc/fp.c create mode 100644 optee/optee_os/lib/libutils/isoc/fputc.c create mode 100644 optee/optee_os/lib/libutils/isoc/fputs.c create mode 100644 optee/optee_os/lib/libutils/isoc/fwrite.c create mode 100644 optee/optee_os/lib/libutils/isoc/include/assert.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/ctype.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/inttypes.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/limits.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/malloc.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/memory.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/setjmp.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/signal.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/stdint.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/stdio.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/stdlib.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/string.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/strings.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/sys/cdefs.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/sys/queue.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/sys/types.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/time.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/unistd.h create mode 100644 optee/optee_os/lib/libutils/isoc/include/wchar.h create mode 100644 optee/optee_os/lib/libutils/isoc/isalnum.c create mode 100644 optee/optee_os/lib/libutils/isoc/isalpha.c create mode 100644 optee/optee_os/lib/libutils/isoc/iscntrl.c create mode 100644 optee/optee_os/lib/libutils/isoc/isdigit.c create mode 100644 optee/optee_os/lib/libutils/isoc/isgraph.c create mode 100644 optee/optee_os/lib/libutils/isoc/islower.c create mode 100644 optee/optee_os/lib/libutils/isoc/isprint.c create mode 100644 optee/optee_os/lib/libutils/isoc/ispunct.c create mode 100644 optee/optee_os/lib/libutils/isoc/isspace.c create mode 100644 optee/optee_os/lib/libutils/isoc/isupper.c create mode 100644 optee/optee_os/lib/libutils/isoc/isxdigit.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/_ansi.h create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/abs.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/bcmp.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/memchr.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/memcmp.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/memcpy.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/memmove.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/memset.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/str-two-way.h create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strchr.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strcmp.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strcpy.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strlen.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strncmp.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strncpy.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strnlen.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strrchr.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strstr.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strtok_r.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/strtoul.c create mode 100644 optee/optee_os/lib/libutils/isoc/newlib/sub.mk create mode 100644 optee/optee_os/lib/libutils/isoc/qsort.c create mode 100644 optee/optee_os/lib/libutils/isoc/snprintf.c create mode 100644 optee/optee_os/lib/libutils/isoc/sprintf.c create mode 100644 optee/optee_os/lib/libutils/isoc/stack_check.c create mode 100644 optee/optee_os/lib/libutils/isoc/strdup.c create mode 100644 optee/optee_os/lib/libutils/isoc/strndup.c create mode 100644 optee/optee_os/lib/libutils/isoc/sub.mk create mode 100644 optee/optee_os/lib/libutils/isoc/tolower.c create mode 100644 optee/optee_os/lib/libutils/isoc/toupper.c create mode 100644 optee/optee_os/lib/libutils/isoc/write.c create mode 100644 optee/optee_os/lib/libutils/sub.mk create mode 100644 optee/optee_os/mk/aosp_optee.mk create mode 100644 optee/optee_os/mk/cc-option.mk create mode 100644 optee/optee_os/mk/checkconf.mk create mode 100644 optee/optee_os/mk/clang.mk create mode 100644 optee/optee_os/mk/cleandirs.mk create mode 100644 optee/optee_os/mk/cleanvars.mk create mode 100644 optee/optee_os/mk/compile.mk create mode 100644 optee/optee_os/mk/config.mk create mode 100644 optee/optee_os/mk/gcc.mk create mode 100644 optee/optee_os/mk/lib.mk create mode 100644 optee/optee_os/mk/subdir.mk create mode 100644 optee/optee_os/prebuilt/t234/libcommon_crypto.a create mode 100755 optee/optee_os/scripts/arm32_sysreg.py create mode 100755 optee/optee_os/scripts/bin_to_c.py create mode 100755 optee/optee_os/scripts/checkpatch.sh create mode 100644 optee/optee_os/scripts/checkpatch_inc.sh create mode 100755 optee/optee_os/scripts/gen_ld_sects.py create mode 100755 optee/optee_os/scripts/gen_ldelf_hex.py create mode 100755 optee/optee_os/scripts/gen_stmm_hex.py create mode 100755 optee/optee_os/scripts/gen_tee_bin.py create mode 100755 optee/optee_os/scripts/get_maintainer.py create mode 100755 optee/optee_os/scripts/mem_usage.py create mode 100755 optee/optee_os/scripts/pem_to_pub_c.py create mode 100755 optee/optee_os/scripts/print_tee_hash.py create mode 100755 optee/optee_os/scripts/sign_encrypt.py create mode 100755 optee/optee_os/scripts/sign_helper_kms.py create mode 100755 optee/optee_os/scripts/symbolize.py create mode 100755 optee/optee_os/scripts/tee_bin_parser.py create mode 100755 optee/optee_os/scripts/ts_bin_to_c.py create mode 100755 optee/optee_os/scripts/update_changelog.py create mode 100644 optee/optee_os/ta/arch/arm/ta.ld.S create mode 100644 optee/optee_os/ta/arch/arm/ta_entry_a32.S create mode 100644 optee/optee_os/ta/arch/riscv/ta.ld.S create mode 100644 optee/optee_os/ta/avb/Makefile create mode 100644 optee/optee_os/ta/avb/entry.c create mode 100644 optee/optee_os/ta/avb/include/ta_avb.h create mode 100644 optee/optee_os/ta/avb/sub.mk create mode 100644 optee/optee_os/ta/avb/user_ta.mk create mode 100644 optee/optee_os/ta/avb/user_ta_header_defines.h create mode 100644 optee/optee_os/ta/link.mk create mode 100644 optee/optee_os/ta/link_shlib.mk create mode 100644 optee/optee_os/ta/mk/build-user-ta.mk create mode 100644 optee/optee_os/ta/mk/ta_dev_kit.mk create mode 100644 optee/optee_os/ta/pkcs11/Android.mk create mode 100644 optee/optee_os/ta/pkcs11/Makefile create mode 100644 optee/optee_os/ta/pkcs11/include/pkcs11_ta.h create mode 100755 optee/optee_os/ta/pkcs11/scripts/dump_ec_curve_params.sh create mode 100755 optee/optee_os/ta/pkcs11/scripts/verify-helpers.sh create mode 100644 optee/optee_os/ta/pkcs11/src/attributes.c create mode 100644 optee/optee_os/ta/pkcs11/src/attributes.h create mode 100644 optee/optee_os/ta/pkcs11/src/entry.c create mode 100644 optee/optee_os/ta/pkcs11/src/handle.c create mode 100644 optee/optee_os/ta/pkcs11/src/handle.h create mode 100644 optee/optee_os/ta/pkcs11/src/object.c create mode 100644 optee/optee_os/ta/pkcs11/src/object.h create mode 100644 optee/optee_os/ta/pkcs11/src/persistent_token.c create mode 100644 optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c create mode 100644 optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h create mode 100644 optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c create mode 100644 optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h create mode 100644 optee/optee_os/ta/pkcs11/src/pkcs11_token.c create mode 100644 optee/optee_os/ta/pkcs11/src/pkcs11_token.h create mode 100644 optee/optee_os/ta/pkcs11/src/processing.c create mode 100644 optee/optee_os/ta/pkcs11/src/processing.h create mode 100644 optee/optee_os/ta/pkcs11/src/processing_aes.c create mode 100644 optee/optee_os/ta/pkcs11/src/processing_asymm.c create mode 100644 optee/optee_os/ta/pkcs11/src/processing_digest.c create mode 100644 optee/optee_os/ta/pkcs11/src/processing_ec.c create mode 100644 optee/optee_os/ta/pkcs11/src/processing_rsa.c create mode 100644 optee/optee_os/ta/pkcs11/src/processing_symm.c create mode 100644 optee/optee_os/ta/pkcs11/src/sanitize_object.c create mode 100644 optee/optee_os/ta/pkcs11/src/sanitize_object.h create mode 100644 optee/optee_os/ta/pkcs11/src/serializer.c create mode 100644 optee/optee_os/ta/pkcs11/src/serializer.h create mode 100644 optee/optee_os/ta/pkcs11/src/sub.mk create mode 100644 optee/optee_os/ta/pkcs11/src/token_capabilities.c create mode 100644 optee/optee_os/ta/pkcs11/src/token_capabilities.h create mode 100644 optee/optee_os/ta/pkcs11/src/user_ta_header_defines.h create mode 100644 optee/optee_os/ta/pkcs11/sub.mk create mode 100644 optee/optee_os/ta/pkcs11/user_ta.mk create mode 100644 optee/optee_os/ta/ta.mk create mode 100644 optee/optee_os/ta/trusted_keys/entry.c create mode 100644 optee/optee_os/ta/trusted_keys/include/trusted_keys.h create mode 100644 optee/optee_os/ta/trusted_keys/sub.mk create mode 100644 optee/optee_os/ta/trusted_keys/user_ta.mk create mode 100644 optee/optee_os/ta/trusted_keys/user_ta_header_defines.h create mode 100644 optee/optee_os/ta/user_ta_header.c create mode 100644 optee/optee_os/typedefs.checkpatch create mode 100644 optee/optee_test/.github/issue_template.md create mode 100644 optee/optee_test/.github/pull_request_template.md create mode 100644 optee/optee_test/.github/workflows/ci.yml create mode 100644 optee/optee_test/.github/workflows/stale_issue.yml create mode 100644 optee/optee_test/Android.mk create mode 100644 optee/optee_test/CMakeLists.txt create mode 100644 optee/optee_test/CMakeToolchain.txt create mode 100644 optee/optee_test/LICENSE.md create mode 100644 optee/optee_test/Makefile create mode 100644 optee/optee_test/README.md create mode 100644 optee/optee_test/cert/README.txt create mode 100644 optee/optee_test/cert/ca.crt create mode 100644 optee/optee_test/cert/ca.key create mode 100644 optee/optee_test/cert/ca.srl create mode 100644 optee/optee_test/cert/mid.conf create mode 100644 optee/optee_test/cert/mid.crt create mode 100644 optee/optee_test/cert/mid.csr create mode 100644 optee/optee_test/cert/mid.ext create mode 100644 optee/optee_test/cert/mid.key create mode 100644 optee/optee_test/cert/mid.srl create mode 100644 optee/optee_test/cert/my.conf create mode 100644 optee/optee_test/cert/my.crt create mode 100644 optee/optee_test/cert/my.csr create mode 100644 optee/optee_test/cert/my.key create mode 100644 optee/optee_test/host/openssl/include/openssl/aes.h create mode 100644 optee/optee_test/host/openssl/include/openssl/asn1.h create mode 100644 optee/optee_test/host/openssl/include/openssl/asn1_mac.h create mode 100644 optee/optee_test/host/openssl/include/openssl/asn1t.h create mode 100644 optee/optee_test/host/openssl/include/openssl/bio.h create mode 100644 optee/optee_test/host/openssl/include/openssl/blowfish.h create mode 100644 optee/optee_test/host/openssl/include/openssl/bn.h create mode 100644 optee/optee_test/host/openssl/include/openssl/buffer.h create mode 100644 optee/optee_test/host/openssl/include/openssl/camellia.h create mode 100644 optee/optee_test/host/openssl/include/openssl/cast.h create mode 100644 optee/optee_test/host/openssl/include/openssl/cmac.h create mode 100644 optee/optee_test/host/openssl/include/openssl/cms.h create mode 100644 optee/optee_test/host/openssl/include/openssl/comp.h create mode 100644 optee/optee_test/host/openssl/include/openssl/conf.h create mode 100644 optee/optee_test/host/openssl/include/openssl/conf_api.h create mode 100644 optee/optee_test/host/openssl/include/openssl/crypto.h create mode 100644 optee/optee_test/host/openssl/include/openssl/des.h create mode 100644 optee/optee_test/host/openssl/include/openssl/des_old.h create mode 100644 optee/optee_test/host/openssl/include/openssl/dh.h create mode 100644 optee/optee_test/host/openssl/include/openssl/dsa.h create mode 100644 optee/optee_test/host/openssl/include/openssl/dso.h create mode 100644 optee/optee_test/host/openssl/include/openssl/dtls1.h create mode 100644 optee/optee_test/host/openssl/include/openssl/e_os2.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ebcdic.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ec.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ecdh.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ecdsa.h create mode 100644 optee/optee_test/host/openssl/include/openssl/engine.h create mode 100644 optee/optee_test/host/openssl/include/openssl/err.h create mode 100644 optee/optee_test/host/openssl/include/openssl/evp.h create mode 100644 optee/optee_test/host/openssl/include/openssl/hmac.h create mode 100644 optee/optee_test/host/openssl/include/openssl/idea.h create mode 100644 optee/optee_test/host/openssl/include/openssl/krb5_asn.h create mode 100644 optee/optee_test/host/openssl/include/openssl/kssl.h create mode 100644 optee/optee_test/host/openssl/include/openssl/lhash.h create mode 100644 optee/optee_test/host/openssl/include/openssl/md4.h create mode 100644 optee/optee_test/host/openssl/include/openssl/md5.h create mode 100644 optee/optee_test/host/openssl/include/openssl/mdc2.h create mode 100644 optee/optee_test/host/openssl/include/openssl/modes.h create mode 100644 optee/optee_test/host/openssl/include/openssl/obj_mac.h create mode 100644 optee/optee_test/host/openssl/include/openssl/objects.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ocsp.h create mode 100644 optee/optee_test/host/openssl/include/openssl/opensslconf.h create mode 100644 optee/optee_test/host/openssl/include/openssl/opensslv.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ossl_typ.h create mode 100644 optee/optee_test/host/openssl/include/openssl/pem.h create mode 100644 optee/optee_test/host/openssl/include/openssl/pem2.h create mode 100644 optee/optee_test/host/openssl/include/openssl/pkcs12.h create mode 100644 optee/optee_test/host/openssl/include/openssl/pkcs7.h create mode 100644 optee/optee_test/host/openssl/include/openssl/pqueue.h create mode 100644 optee/optee_test/host/openssl/include/openssl/rand.h create mode 100644 optee/optee_test/host/openssl/include/openssl/rc2.h create mode 100644 optee/optee_test/host/openssl/include/openssl/rc4.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ripemd.h create mode 100644 optee/optee_test/host/openssl/include/openssl/rsa.h create mode 100644 optee/optee_test/host/openssl/include/openssl/safestack.h create mode 100644 optee/optee_test/host/openssl/include/openssl/seed.h create mode 100644 optee/optee_test/host/openssl/include/openssl/sha.h create mode 100644 optee/optee_test/host/openssl/include/openssl/srp.h create mode 100644 optee/optee_test/host/openssl/include/openssl/srtp.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ssl.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ssl2.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ssl23.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ssl3.h create mode 100644 optee/optee_test/host/openssl/include/openssl/stack.h create mode 100644 optee/optee_test/host/openssl/include/openssl/symhacks.h create mode 100644 optee/optee_test/host/openssl/include/openssl/tls1.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ts.h create mode 100644 optee/optee_test/host/openssl/include/openssl/txt_db.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ui.h create mode 100644 optee/optee_test/host/openssl/include/openssl/ui_compat.h create mode 100644 optee/optee_test/host/openssl/include/openssl/whrlpool.h create mode 100644 optee/optee_test/host/openssl/include/openssl/x509.h create mode 100644 optee/optee_test/host/openssl/include/openssl/x509_vfy.h create mode 100644 optee/optee_test/host/openssl/include/openssl/x509v3.h create mode 100644 optee/optee_test/host/openssl/lib/aarch64/libcrypto.a create mode 100644 optee/optee_test/host/openssl/lib/arm/libcrypto.a create mode 100644 optee/optee_test/host/supp_plugin/CMakeLists.txt create mode 100644 optee/optee_test/host/supp_plugin/Makefile create mode 100644 optee/optee_test/host/supp_plugin/include/test_supp_plugin.h create mode 100644 optee/optee_test/host/supp_plugin/test_supp_plugin.c create mode 100644 optee/optee_test/host/xtest/CMakeLists.txt create mode 100644 optee/optee_test/host/xtest/LICENSE create mode 100644 optee/optee_test/host/xtest/Makefile create mode 100644 optee/optee_test/host/xtest/adbg/include/adbg.h create mode 100644 optee/optee_test/host/xtest/adbg/src/adbg_case.c create mode 100644 optee/optee_test/host/xtest/adbg/src/adbg_enum.c create mode 100644 optee/optee_test/host/xtest/adbg/src/adbg_expect.c create mode 100644 optee/optee_test/host/xtest/adbg/src/adbg_int.h create mode 100644 optee/optee_test/host/xtest/adbg/src/adbg_log.c create mode 100644 optee/optee_test/host/xtest/adbg/src/adbg_run.c create mode 100644 optee/optee_test/host/xtest/adbg/src/security_utils_hex.c create mode 100644 optee/optee_test/host/xtest/adbg/src/security_utils_hex.h create mode 100644 optee/optee_test/host/xtest/aes_perf.c create mode 100644 optee/optee_test/host/xtest/benchmark_1000.c create mode 100644 optee/optee_test/host/xtest/benchmark_2000.c create mode 100644 optee/optee_test/host/xtest/crypto_common.h create mode 100644 optee/optee_test/host/xtest/ffa_spmc_1000.c create mode 100644 optee/optee_test/host/xtest/gp/TEE.xsl create mode 100644 optee/optee_test/host/xtest/gp/TEE_Crypto_API.xsl create mode 100644 optee/optee_test/host/xtest/gp/TEE_DataStorage_API.xsl create mode 100644 optee/optee_test/host/xtest/gp/TEE_Internal_API.xsl create mode 100644 optee/optee_test/host/xtest/gp/TEE_TimeArithm_API.xsl create mode 100644 optee/optee_test/host/xtest/gp/include/xml_client_api.h create mode 100644 optee/optee_test/host/xtest/gp/include/xml_common_api.h create mode 100644 optee/optee_test/host/xtest/gp/include/xml_crypto_api.h create mode 100644 optee/optee_test/host/xtest/gp/include/xml_datastorage_api.h create mode 100644 optee/optee_test/host/xtest/gp/include/xml_internal_api.h create mode 100644 optee/optee_test/host/xtest/gp/include/xml_timearithm_api.h create mode 100644 optee/optee_test/host/xtest/gp/patches/0002-TTAs-add-files-needed-to-compile.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0003-TTA_TCF-patch.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0004-TTA_Arithmetical-patch.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0005-GP_defs.h-enable-debug-prints.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0007-TTAs-revert-to-v1.1-types.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0008-TEE.xml.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0009-TEE_Internal_API.xml.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0010-TEE_DataStorage_API.xml.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0011-TEE_Crypto_API.xml.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0012-TTA_TCF-remove-TEE_MemMove-from-CmdTEEGetPropertyAsX.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0013-Disable-Invoke_GetTAPersistentTimeNotSet_and_SetTAPe.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0014-Pass-upper-32-bits-of-TEE_PropSetHandle-in-value.b.patch create mode 100644 optee/optee_test/host/xtest/gp/patches/0015-Enable-compatibility-with-TEE-Internal-Core-API-v1.1.patch create mode 100644 optee/optee_test/host/xtest/gp/prepare_suite.sh create mode 100644 optee/optee_test/host/xtest/hash_perf.c create mode 100644 optee/optee_test/host/xtest/include/uapi/linux/arm_ffa_user.h create mode 100644 optee/optee_test/host/xtest/install_ta.c create mode 100644 optee/optee_test/host/xtest/install_ta.h create mode 100644 optee/optee_test/host/xtest/nist/186-2ecdsatestvectors.h create mode 100644 optee/optee_test/host/xtest/nist/186-3dsatestvectors.h create mode 100644 optee/optee_test/host/xtest/nist/ecccdhtestvectors.h create mode 100644 optee/optee_test/host/xtest/pkcs11_1000.c create mode 100644 optee/optee_test/host/xtest/rand_stream.c create mode 100644 optee/optee_test/host/xtest/rand_stream.h create mode 100644 optee/optee_test/host/xtest/regression_1000.c create mode 100644 optee/optee_test/host/xtest/regression_2000.c create mode 100644 optee/optee_test/host/xtest/regression_4000.c create mode 100644 optee/optee_test/host/xtest/regression_4000_data.h create mode 100644 optee/optee_test/host/xtest/regression_4100.c create mode 100644 optee/optee_test/host/xtest/regression_5000.c create mode 100644 optee/optee_test/host/xtest/regression_6000.c create mode 100644 optee/optee_test/host/xtest/regression_8000.c create mode 100644 optee/optee_test/host/xtest/regression_8100.c create mode 100644 optee/optee_test/host/xtest/sdp_basic.c create mode 100644 optee/optee_test/host/xtest/sdp_basic.h create mode 100644 optee/optee_test/host/xtest/sock_server.c create mode 100644 optee/optee_test/host/xtest/sock_server.h create mode 100644 optee/optee_test/host/xtest/stats.c create mode 100644 optee/optee_test/host/xtest/stats.h create mode 100644 optee/optee_test/host/xtest/xtest_helpers.c create mode 100644 optee/optee_test/host/xtest/xtest_helpers.h create mode 100644 optee/optee_test/host/xtest/xtest_main.c create mode 100644 optee/optee_test/host/xtest/xtest_test.c create mode 100644 optee/optee_test/host/xtest/xtest_test.h create mode 100644 optee/optee_test/host/xtest/xtest_uuid_helpers.c create mode 100644 optee/optee_test/host/xtest/xtest_uuid_helpers.h create mode 100755 optee/optee_test/scripts/checkpatch.sh create mode 100644 optee/optee_test/scripts/common.mk create mode 100755 optee/optee_test/scripts/file_to_c.py create mode 100755 optee/optee_test/scripts/rsp_to_gcm_test.py create mode 100644 optee/optee_test/ta/Android.mk create mode 100644 optee/optee_test/ta/CMakeLists.txt create mode 100644 optee/optee_test/ta/Makefile create mode 100644 optee/optee_test/ta/aes_perf/Android.mk create mode 100644 optee/optee_test/ta/aes_perf/Makefile create mode 100644 optee/optee_test/ta/aes_perf/include/ta_aes_perf.h create mode 100644 optee/optee_test/ta/aes_perf/include/ta_aes_perf_priv.h create mode 100644 optee/optee_test/ta/aes_perf/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/aes_perf/sub.mk create mode 100644 optee/optee_test/ta/aes_perf/ta_aes_perf.c create mode 100644 optee/optee_test/ta/aes_perf/ta_entry.c create mode 100644 optee/optee_test/ta/bti_test/Android.mk create mode 100644 optee/optee_test/ta/bti_test/Makefile create mode 100644 optee/optee_test/ta/bti_test/bti_stubs_a64.S create mode 100644 optee/optee_test/ta/bti_test/include/ta_arm_bti.h create mode 100644 optee/optee_test/ta/bti_test/include/ta_arm_bti_priv.h create mode 100644 optee/optee_test/ta/bti_test/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/bti_test/sub.mk create mode 100644 optee/optee_test/ta/bti_test/ta_arm_bti.c create mode 100644 optee/optee_test/ta/bti_test/ta_entry.c create mode 100644 optee/optee_test/ta/concurrent/Android.mk create mode 100644 optee/optee_test/ta/concurrent/Makefile create mode 100644 optee/optee_test/ta/concurrent/include/ta_concurrent.h create mode 100644 optee/optee_test/ta/concurrent/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/concurrent/sub.mk create mode 100644 optee/optee_test/ta/concurrent/ta_entry.c create mode 100644 optee/optee_test/ta/concurrent_large/Android.mk create mode 100644 optee/optee_test/ta/concurrent_large/Makefile create mode 100644 optee/optee_test/ta/concurrent_large/include/ta_concurrent_large.h create mode 100644 optee/optee_test/ta/concurrent_large/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/concurrent_large/sub.mk create mode 100644 optee/optee_test/ta/concurrent_large/ta_entry.c create mode 100644 optee/optee_test/ta/create_fail_test/Android.mk create mode 100644 optee/optee_test/ta/create_fail_test/Makefile create mode 100644 optee/optee_test/ta/create_fail_test/include/ta_create_fail_test.h create mode 100644 optee/optee_test/ta/create_fail_test/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/create_fail_test/sub.mk create mode 100644 optee/optee_test/ta/create_fail_test/ta_entry.c create mode 100644 optee/optee_test/ta/crypt/Android.mk create mode 100644 optee/optee_test/ta/crypt/Makefile create mode 100644 optee/optee_test/ta/crypt/aes_impl.c create mode 100644 optee/optee_test/ta/crypt/aes_taf.c create mode 100644 optee/optee_test/ta/crypt/arith_taf.c create mode 100644 optee/optee_test/ta/crypt/cryp_taf.c create mode 100644 optee/optee_test/ta/crypt/derive_key_taf.c create mode 100644 optee/optee_test/ta/crypt/handle.c create mode 100644 optee/optee_test/ta/crypt/handle.h create mode 100644 optee/optee_test/ta/crypt/include/aes_impl.h create mode 100644 optee/optee_test/ta/crypt/include/aes_taf.h create mode 100644 optee/optee_test/ta/crypt/include/arith_taf.h create mode 100644 optee/optee_test/ta/crypt/include/cryp_taf.h create mode 100644 optee/optee_test/ta/crypt/include/derive_key_taf.h create mode 100644 optee/optee_test/ta/crypt/include/mbedtls_taf.h create mode 100644 optee/optee_test/ta/crypt/include/seed_rng_taf.h create mode 100644 optee/optee_test/ta/crypt/include/sha2_impl.h create mode 100644 optee/optee_test/ta/crypt/include/sha2_taf.h create mode 100644 optee/optee_test/ta/crypt/include/ta_crypt.h create mode 100644 optee/optee_test/ta/crypt/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/crypt/mbedtls_taf.c create mode 100644 optee/optee_test/ta/crypt/seed_rng_taf.c create mode 100644 optee/optee_test/ta/crypt/sha2_impl.c create mode 100644 optee/optee_test/ta/crypt/sha2_taf.c create mode 100644 optee/optee_test/ta/crypt/sub.mk create mode 100644 optee/optee_test/ta/crypt/ta_entry.c create mode 100644 optee/optee_test/ta/enc_fs/include/enc_fs_key_manager_test.h create mode 100644 optee/optee_test/ta/hash_perf/Android.mk create mode 100644 optee/optee_test/ta/hash_perf/Makefile create mode 100644 optee/optee_test/ta/hash_perf/include/ta_hash_perf.h create mode 100644 optee/optee_test/ta/hash_perf/include/ta_hash_perf_priv.h create mode 100644 optee/optee_test/ta/hash_perf/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/hash_perf/sub.mk create mode 100644 optee/optee_test/ta/hash_perf/ta_entry.c create mode 100644 optee/optee_test/ta/hash_perf/ta_hash_perf.c create mode 100644 optee/optee_test/ta/identity_subkey2.bin create mode 100644 optee/optee_test/ta/identity_subkey2.pem create mode 100644 optee/optee_test/ta/include/ta_storage.h create mode 100644 optee/optee_test/ta/large/Android.mk create mode 100644 optee/optee_test/ta/large/Makefile create mode 100644 optee/optee_test/ta/large/include/ta_large.h create mode 100644 optee/optee_test/ta/large/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/large/sub.mk create mode 100644 optee/optee_test/ta/large/ta_entry.c create mode 100644 optee/optee_test/ta/mid_level_subkey.bin create mode 100644 optee/optee_test/ta/mid_level_subkey.pem create mode 100644 optee/optee_test/ta/miss/Android.mk create mode 100644 optee/optee_test/ta/miss/Makefile create mode 100644 optee/optee_test/ta/miss/include/ta_miss_test.h create mode 100644 optee/optee_test/ta/miss/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/miss/sub.mk create mode 100644 optee/optee_test/ta/miss/ta_entry.c create mode 100644 optee/optee_test/ta/miss/ta_miss.c create mode 100644 optee/optee_test/ta/os_test/Android.mk create mode 100644 optee/optee_test/ta/os_test/Makefile create mode 100644 optee/optee_test/ta/os_test/attestation.c create mode 100644 optee/optee_test/ta/os_test/cxx_tests.cpp create mode 100644 optee/optee_test/ta/os_test/cxx_tests.h create mode 100644 optee/optee_test/ta/os_test/cxx_tests_c.c create mode 100644 optee/optee_test/ta/os_test/include/init.h create mode 100644 optee/optee_test/ta/os_test/include/os_test.h create mode 100644 optee/optee_test/ta/os_test/include/ta_os_test.h create mode 100644 optee/optee_test/ta/os_test/include/tb_asserts.h create mode 100644 optee/optee_test/ta/os_test/include/tb_macros.h create mode 100644 optee/optee_test/ta/os_test/include/testframework.h create mode 100644 optee/optee_test/ta/os_test/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/os_test/init.c create mode 100644 optee/optee_test/ta/os_test/os_test.c create mode 100644 optee/optee_test/ta/os_test/pauth_a64.S create mode 100644 optee/optee_test/ta/os_test/sub.mk create mode 100644 optee/optee_test/ta/os_test/ta_arm_pauth.c create mode 100644 optee/optee_test/ta/os_test/ta_entry.c create mode 100644 optee/optee_test/ta/os_test/test_float_subj.c create mode 100644 optee/optee_test/ta/os_test/test_float_subj.h create mode 100644 optee/optee_test/ta/os_test_lib/Android.mk create mode 100644 optee/optee_test/ta/os_test_lib/Makefile create mode 100644 optee/optee_test/ta/os_test_lib/include/os_test_lib.h create mode 100644 optee/optee_test/ta/os_test_lib/os_test_lib.c create mode 100644 optee/optee_test/ta/os_test_lib/os_test_lib_cxx.cpp create mode 100644 optee/optee_test/ta/os_test_lib/sub.mk create mode 100644 optee/optee_test/ta/os_test_lib_dl/Android.mk create mode 100644 optee/optee_test/ta/os_test_lib_dl/Makefile create mode 100644 optee/optee_test/ta/os_test_lib_dl/include/os_test_lib_dl.h create mode 100644 optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl.c create mode 100644 optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl_cxx.cpp create mode 100644 optee/optee_test/ta/os_test_lib_dl/sub.mk create mode 100644 optee/optee_test/ta/rpc_test/Android.mk create mode 100644 optee/optee_test/ta/rpc_test/Makefile create mode 100644 optee/optee_test/ta/rpc_test/include/ta_rpc.h create mode 100644 optee/optee_test/ta/rpc_test/include/ta_rpc_test.h create mode 100644 optee/optee_test/ta/rpc_test/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/rpc_test/sub.mk create mode 100644 optee/optee_test/ta/rpc_test/ta_entry.c create mode 100644 optee/optee_test/ta/rpc_test/ta_rpc.c create mode 100644 optee/optee_test/ta/sdp_basic/Android.mk create mode 100644 optee/optee_test/ta/sdp_basic/Makefile create mode 100644 optee/optee_test/ta/sdp_basic/include/ta_sdp_basic.h create mode 100644 optee/optee_test/ta/sdp_basic/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/sdp_basic/sub.mk create mode 100644 optee/optee_test/ta/sdp_basic/ta_sdp_basic.c create mode 100644 optee/optee_test/ta/sims/Android.mk create mode 100644 optee/optee_test/ta/sims/Makefile create mode 100644 optee/optee_test/ta/sims/include/ta_sims.h create mode 100644 optee/optee_test/ta/sims/include/ta_sims_test.h create mode 100644 optee/optee_test/ta/sims/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/sims/sub.mk create mode 100644 optee/optee_test/ta/sims/ta_entry.c create mode 100644 optee/optee_test/ta/sims/ta_sims.c create mode 100644 optee/optee_test/ta/sims_keepalive/Android.mk create mode 100644 optee/optee_test/ta/sims_keepalive/Makefile create mode 100644 optee/optee_test/ta/sims_keepalive/include/ta_sims_keepalive_test.h create mode 100644 optee/optee_test/ta/sims_keepalive/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/sims_keepalive/sub.mk create mode 100644 optee/optee_test/ta/sims_keepalive/ta_entry.c create mode 100644 optee/optee_test/ta/sims_keepalive/ta_sims_keepalive.c create mode 100644 optee/optee_test/ta/socket/Android.mk create mode 100644 optee/optee_test/ta/socket/Makefile create mode 100644 optee/optee_test/ta/socket/include/ta_socket.h create mode 100644 optee/optee_test/ta/socket/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/socket/sub.mk create mode 100644 optee/optee_test/ta/socket/ta_entry.c create mode 100644 optee/optee_test/ta/storage/Android.mk create mode 100644 optee/optee_test/ta/storage/Makefile create mode 100644 optee/optee_test/ta/storage/include/storage.h create mode 100644 optee/optee_test/ta/storage/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/storage/storage.c create mode 100644 optee/optee_test/ta/storage/sub.mk create mode 100644 optee/optee_test/ta/storage/ta_entry.c create mode 100644 optee/optee_test/ta/storage2/Android.mk create mode 100644 optee/optee_test/ta/storage2/Makefile create mode 100644 optee/optee_test/ta/storage2/include/storage.h create mode 100644 optee/optee_test/ta/storage2/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/storage2/storage.c create mode 100644 optee/optee_test/ta/storage2/sub.mk create mode 100644 optee/optee_test/ta/storage2/ta_entry.c create mode 100644 optee/optee_test/ta/storage_benchmark/Android.mk create mode 100644 optee/optee_test/ta/storage_benchmark/Makefile create mode 100644 optee/optee_test/ta/storage_benchmark/benchmark.c create mode 100644 optee/optee_test/ta/storage_benchmark/include/storage_benchmark.h create mode 100644 optee/optee_test/ta/storage_benchmark/include/ta_storage_benchmark.h create mode 100644 optee/optee_test/ta/storage_benchmark/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/storage_benchmark/sub.mk create mode 100644 optee/optee_test/ta/storage_benchmark/ta_entry.c create mode 100644 optee/optee_test/ta/subkey1/Makefile create mode 100644 optee/optee_test/ta/subkey1/include/ta_subkey1.h create mode 100644 optee/optee_test/ta/subkey1/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/subkey1/sub.mk create mode 100644 optee/optee_test/ta/subkey1/ta_entry.c create mode 100644 optee/optee_test/ta/subkey2/Makefile create mode 100644 optee/optee_test/ta/subkey2/include/ta_subkey2.h create mode 100644 optee/optee_test/ta/subkey2/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/subkey2/sub.mk create mode 100644 optee/optee_test/ta/subkey2/ta_entry.c create mode 100644 optee/optee_test/ta/subkey_notes.txt create mode 100644 optee/optee_test/ta/supp_plugin/Android.mk create mode 100644 optee/optee_test/ta/supp_plugin/Makefile create mode 100644 optee/optee_test/ta/supp_plugin/include/ta_supp_plugin.h create mode 100644 optee/optee_test/ta/supp_plugin/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/supp_plugin/sub.mk create mode 100644 optee/optee_test/ta/supp_plugin/ta_entry.c create mode 100644 optee/optee_test/ta/ta_common.mk create mode 100644 optee/optee_test/ta/top_level_subkey.bin create mode 100644 optee/optee_test/ta/top_level_subkey.pem create mode 100644 optee/optee_test/ta/tpm_log_test/Android.mk create mode 100644 optee/optee_test/ta/tpm_log_test/Makefile create mode 100644 optee/optee_test/ta/tpm_log_test/include/ta_tpm_log.h create mode 100644 optee/optee_test/ta/tpm_log_test/include/ta_tpm_log_test.h create mode 100644 optee/optee_test/ta/tpm_log_test/include/user_ta_header_defines.h create mode 100644 optee/optee_test/ta/tpm_log_test/sub.mk create mode 100644 optee/optee_test/ta/tpm_log_test/ta_entry.c create mode 100644 optee/optee_test/typedefs.checkpatch create mode 100644 optee/samples/LICENSE create mode 100644 optee/samples/Makefile create mode 100644 optee/samples/hwkey-agent/LICENSE create mode 100644 optee/samples/hwkey-agent/Makefile create mode 100644 optee/samples/hwkey-agent/README create mode 100644 optee/samples/hwkey-agent/host/Makefile create mode 100644 optee/samples/hwkey-agent/host/hwkey_agent_ca.c create mode 100644 optee/samples/hwkey-agent/host/tool/gen_ekb/README create mode 100755 optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh create mode 100755 optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py create mode 100644 optee/samples/hwkey-agent/ta/Makefile create mode 100644 optee/samples/hwkey-agent/ta/hwkey_agent_ta.c create mode 100644 optee/samples/hwkey-agent/ta/include/hwkey_agent_ta.h create mode 100644 optee/samples/hwkey-agent/ta/sub.mk create mode 100644 optee/samples/hwkey-agent/ta/user_ta_header_defines.h create mode 100644 optee/samples/luks-srv/LICENSE create mode 100644 optee/samples/luks-srv/Makefile create mode 100644 optee/samples/luks-srv/README create mode 100644 optee/samples/luks-srv/host/Makefile create mode 100644 optee/samples/luks-srv/host/luks_srv_ca.c create mode 100644 optee/samples/luks-srv/host/tool/gen_luks_passphrase/README create mode 100755 optee/samples/luks-srv/host/tool/gen_luks_passphrase/example.sh create mode 100755 optee/samples/luks-srv/host/tool/gen_luks_passphrase/gen_luks_passphrase.py create mode 100644 optee/samples/luks-srv/ta/Makefile create mode 100644 optee/samples/luks-srv/ta/include/luks_srv_ta.h create mode 100644 optee/samples/luks-srv/ta/luks_srv_ta.c create mode 100644 optee/samples/luks-srv/ta/sub.mk create mode 100644 optee/samples/luks-srv/ta/user_ta_header_defines.h create mode 100644 optee/tegra194-optee.dts create mode 100644 optee/tegra234-optee.dts create mode 100755 optee_src_build.sh create mode 100644 push_info.txt diff --git a/commitFile.txt b/commitFile.txt new file mode 100644 index 0000000..6c3758e --- /dev/null +++ b/commitFile.txt @@ -0,0 +1,2899 @@ +Updating prebuilts and/or headers + +df74e654e27c07ba2b83fc80f46368c1aa63d713 - optee_src_build.sh +d15f50688485e11293e0d0bd66d73655e79f7718 - nvcommon_build.sh +94631ac9bb0297e7d636c0b76fbb046abbb62df2 - optee/tegra234-optee.dts +f17a52a204d42c6699bdc375e3aace6bcdcfdbf9 - optee/tegra194-optee.dts +e7fe1d82e00a66f594a738016d2c3f0040ba065a - optee/optee_os/MAINTAINERS +8c2c72f00c2c6eef765a45d8b8eee4adca4b43a0 - optee/optee_os/CHANGELOG.md +bf1387b548dae92223ef175a7d56e4f88d6cfe84 - optee/optee_os/Makefile +6bf9bd872a69d8c13e8dcac71fac8d094646251d - optee/optee_os/README.md +370d68b1c9485f254e7c701c31e3c74fd16cacd7 - optee/optee_os/LICENSE +3a608e255399bb5cf2302bb52e533d81c469ecce - optee/optee_os/LICENSE.NVIDIA +96558a7a79bf90ebde8720b0087c9c578efa981b - optee/optee_os/.checkpatch.conf +25ecfc13bc9b5205cb9db1ffb015fa973c8a754b - optee/optee_os/typedefs.checkpatch +edc01ccf3e16f1a4bdb1908f57a4722d3bfa203a - optee/optee_os/scripts/checkpatch.sh +c92fcf555467abe77b88cea98e805eaa6eca5462 - optee/optee_os/scripts/gen_ld_sects.py +24ab5b3587dac3d8b99136338a79a57b38027da9 - optee/optee_os/scripts/mem_usage.py +31f300bb6c5a381759d5e2a3b54e42039be66dd5 - optee/optee_os/scripts/sign_helper_kms.py +ff71ab8e19870db30e4a8fba666168c645f37126 - optee/optee_os/scripts/tee_bin_parser.py +f5129e67acb9e8d845d39e92497f7de01ae50522 - optee/optee_os/scripts/symbolize.py +ab4324da2d6fb92edbcaa95bc23911ed63e4514d - optee/optee_os/scripts/arm32_sysreg.py +cfc4d70e52ea54f55638942bf254588c218d311f - optee/optee_os/scripts/ts_bin_to_c.py +e13049cc7ecc4774a0b40b42d6a72617f540db8d - optee/optee_os/scripts/bin_to_c.py +76a908634bfe89773fd70c57fd77d712c4bc89ee - optee/optee_os/scripts/sign_encrypt.py +ffaf1fbbaa6d01cecaeae7d8ce75f8315240228d - optee/optee_os/scripts/pem_to_pub_c.py +08b1957d02a5f8fb853138fa4b3f2b8b04f8d847 - optee/optee_os/scripts/update_changelog.py +e6692bdad99dbf466f146fe7169981ae542eb6cd - optee/optee_os/scripts/get_maintainer.py +bf2d92432e259f18d97d2a955e3192aa3c98813f - optee/optee_os/scripts/checkpatch_inc.sh +b1241b7d0c39f88fb4382637396901002f682b69 - optee/optee_os/scripts/gen_tee_bin.py +f8bce245ce0b6610d39e02928e25307a5b6cc818 - optee/optee_os/scripts/print_tee_hash.py +570bf1d2a225e0124496bc57c287ff0991fd023a - optee/optee_os/scripts/gen_stmm_hex.py +d302da149f2f0d0b11b9c365bf3add51a131b8a9 - optee/optee_os/scripts/gen_ldelf_hex.py +c5d1a1d261c8bada5f949335bffe29a029d03e05 - optee/optee_os/ldelf/syscalls_a32.S +4b036af7eee80c9d1402b0b1dcd09cab729a7a9b - optee/optee_os/ldelf/pauth.c +db3db1aeff618f5696eb16e7076b63464784267e - optee/optee_os/ldelf/syscalls_asm.S +7126b1fbc89ca63285473f1123be50f2547e8783 - optee/optee_os/ldelf/ta_elf_rel.c +f38c4636b6798cab2823555649a59b72061b756b - optee/optee_os/ldelf/ldelf.ld.S +cb079ab7bac5d488cf5375c1b028130bcb2c7997 - optee/optee_os/ldelf/sys.h +d875d1a5979daa09b5b535d0a3f040c86a60f078 - optee/optee_os/ldelf/start_rv64.S +139e3f4826e35954af3c3bfe5112f11c1bd0db62 - optee/optee_os/ldelf/syscalls_rv.S +34de0a40ccfb6261b73bd7bad69bc8deae4d7b83 - optee/optee_os/ldelf/main.c +87d8438d725c689049dabad1a58459a5efaaef0a - optee/optee_os/ldelf/dl.c +6be295fcd01de4a3c85a70f622f14d21dd0f9e95 - optee/optee_os/ldelf/ta_elf.c +f133be54ea11df978fa33a5afe3a2d8ed8c8f035 - optee/optee_os/ldelf/pauth.h +29a349fad517b13af907e7705113c3831dccd9e9 - optee/optee_os/ldelf/syscalls_a64.S +b8dfc91cf5557585f6b8ca8bf02de131b81a8761 - optee/optee_os/ldelf/ta_elf.h +611d7981c55b4c62f5b13677c04a314e1a2f3218 - optee/optee_os/ldelf/dl.h +20655cc8868222c793eaf2045022fe254ae72f73 - optee/optee_os/ldelf/ftrace.c +ecc193b3d2a051728bc5d4e5841c8bdc021b6d35 - optee/optee_os/ldelf/sys.c +9201638e87d7051478eaabddd7ca1d9054f35f5f - optee/optee_os/ldelf/tlsdesc_rel_a64.S +13ded24e6da6026069baf1c4dd3159b6410f5308 - optee/optee_os/ldelf/start_a64.S +a270591f1efb8037df1d1369287b15f5f2964e0c - optee/optee_os/ldelf/start_a32.S +af3868e37b5f97fafb0a1843478916e687050325 - optee/optee_os/ldelf/ftrace.h +e753e305779ac38002c5db612439fd95d3e9a20d - optee/optee_os/ldelf/include/ldelf_syscalls.h +9d6a14f727a55f4691af8e78834e23c243a1be39 - optee/optee_os/ldelf/include/ldelf.h +73be8d9cc10ccf4ecc646ab51ec17b8bbb51177c - optee/optee_os/core/mm/fobj.c +d8a0dde12ce3d5eec6373fbf9d3a5292b73a9f57 - optee/optee_os/core/mm/mobj.c +c3f15722f779f9fa7c746d6926c361ad9acf253b - optee/optee_os/core/mm/tee_mm.c +448b224d13da51447f6e1b98759ee562d8214172 - optee/optee_os/core/mm/vm.c +cda2e1ec5f1aa6988d7c008a9bdf0036834affbc - optee/optee_os/core/mm/core_mmu.c +4c81a53362b3a07b1dabb5a197f0e3ec26117bee - optee/optee_os/core/mm/file.c +22edc57cadee3b6787489b0d44956d4bbeec2ab6 - optee/optee_os/core/tests/ftmn_boot_tests.c +fdcbba144185422b3358f9b1e37648325785bd3b - optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S +2055966a05cfa317cfedd7b7fa61120de3887b6d - optee/optee_os/core/arch/riscv/kernel/arch_scall.c +ff0583c210b0d08923058c5b88884af14a634d23 - optee/optee_os/core/arch/riscv/kernel/thread_rv.S +de03d1758884a3e0e0f7ea910139d312790963d1 - optee/optee_os/core/arch/riscv/kernel/arch_scall_rv.S +0f43c49d2273009469484b2cc76a2b941e4d9d68 - optee/optee_os/core/arch/riscv/kernel/cache_helpers_rv.S +ae816f807c281348a9c45477cf12d500dbedc2b4 - optee/optee_os/core/arch/riscv/kernel/abort.c +66cbb4c5aaec299ae2ada34564f853e51dda0c88 - optee/optee_os/core/arch/riscv/kernel/entry.S +f28a3e13c2adddd945644d7e1c854918769a51db - optee/optee_os/core/arch/riscv/kernel/asm-defines.c +5cdff36d678ecaf259d131b235eaae03cd6ac555 - optee/optee_os/core/arch/riscv/kernel/sbi_console.c +30e9802c7448df47767d12a2646fefdc0d2b2f63 - optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c +328d1c384a1fa2a526647211cd7cb002ed0e405f - optee/optee_os/core/arch/riscv/kernel/sbi.c +07c3499c0be1a28930978ace71005cfbed42ffe8 - optee/optee_os/core/arch/riscv/kernel/thread_arch.c +7f1c0c47cf8d4455d3bb56977982a34a008a7fbe - optee/optee_os/core/arch/riscv/kernel/spinlock.S +6c73b5fc6d37345ad9f610b7c2fedb763caa640c - optee/optee_os/core/arch/riscv/kernel/boot.c +ef752dba0afbc3441defa0ce7f596275e4eacdf6 - optee/optee_os/core/arch/riscv/kernel/idle.c +651df224b31ff54d4fb317a17064937a491e94a0 - optee/optee_os/core/arch/riscv/kernel/kern.ld.S +f955830a97a8a4231a0876fd8d1b2fc8bf3fabff - optee/optee_os/core/arch/riscv/include/riscv.h +aaf4ec0db08de01b5e8012ce949710f9dcf0f993 - optee/optee_os/core/arch/riscv/include/encoding.h +38bc96a69aa9f591d848f9d2e8142862a8e2b624 - optee/optee_os/core/arch/riscv/include/riscv_macros.S +2e5b805bffc68fffc3c98a3a1b5c7868a2d175f9 - optee/optee_os/core/arch/riscv/include/sbi.h +50020758ad41a07b9fd0fc1986413e61fceea469 - optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h +f90a39605a177515f57172f8bfcac31468bec502 - optee/optee_os/core/arch/riscv/include/mm/generic_ram_layout.h +9b0914d8eab20042998f50ed711cf154e3a65901 - optee/optee_os/core/arch/riscv/include/kernel/time.h +73b1c65df1603ea0e0f934fb8bcf951c475ab1de - optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h +0c4cbba16aac1f17267a36ecda588756cfd3277c - optee/optee_os/core/arch/riscv/include/kernel/clint.h +072f3b42da8ea82d534b28a5f3b298c6bcbfd9a9 - optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h +1121c6b1cd7d9f9ada431b691b4fa06bc14c8bea - optee/optee_os/core/arch/riscv/include/kernel/misc_arch.h +d52408d38337f5b9bd967661199d3207bc29ef62 - optee/optee_os/core/arch/riscv/include/kernel/tee_l2cc_mutex.h +826a1d5fe853d5d25e39ce6e66d577e479b11016 - optee/optee_os/core/arch/riscv/include/kernel/stmm_sp.h +8cc637a0b1fa21930752c33d1cc58d647bc81179 - optee/optee_os/core/arch/riscv/include/kernel/arch_scall.h +b3be5129fb98824666e9dbe5734dd1f811ab97d4 - optee/optee_os/core/arch/riscv/include/kernel/cache_helpers_arch.h +9ff069cbffd055e8fc24029279eafec7c295b34a - optee/optee_os/core/arch/riscv/include/kernel/secure_partition.h +a407be51b81a27f999cf225a9ddba777cbd7ac31 - optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h +3c92f821bb1cb8889d1ff4a5c047a465faceaca8 - optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h +25fbb2839f929c582b956f5d3efb8930b8001a21 - optee/optee_os/core/arch/riscv/plat-spike/platform_config.h +13929110b72beaf2860119c208b13d15c270a4e2 - optee/optee_os/core/arch/riscv/plat-spike/main.c +f4d75a0309e2040dbb1ca13717a13dfa6be01e03 - optee/optee_os/core/arch/riscv/plat-spike/kern.ld.S +558db749b68778acc836e96fc170bc823ab0e441 - optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.c +359b98fad7ce1225b5fb675394acb32df9e74380 - optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.h +0e70c8d59484616ecdb0c1b5c5c9581fdc86ae24 - optee/optee_os/core/arch/riscv/plat-virt/platform_config.h +fc3e11858f322992f6f271cdebedd8d4d22daa5c - optee/optee_os/core/arch/riscv/plat-virt/main.c +a1a353aa32ebd77dd5c2966ff38e024d0e8938bb - optee/optee_os/core/arch/arm/plat-k3/platform_config.h +61851f968e6974914e4ece81f9769761fbdf4a86 - optee/optee_os/core/arch/arm/plat-k3/main.c +4cc70212f3fc61c9fd17876bbc6170b0548bcddf - optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.c +2020136e5c1ef325c92bc319ebb5f582d8d1b447 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.h +96e780127fe944086f4e057b31baea9b2fa125e2 - optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.h +a918fd9f66105e822efddf7848f7bdf38418656e - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h +934412647964baa2217cd31f41cc1e96e1691313 - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h +cbad8ded2c71cdb2604713b866cbb2ef88fb879f - optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c +5b5e14b90101fd4c4b62a395517fa027a0d3cd61 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c +a72f2a95976d21b776dd99c722162a461e575190 - optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c +e8c669f6cd515061ddc1fac878644149427040c8 - optee/optee_os/core/arch/arm/plat-rockchip/psci_rk322x.c +86e640e06414afd26ad833d31867572408fd251a - optee/optee_os/core/arch/arm/plat-rockchip/platform_config.h +bdf9159293e4276febcee2971495ac1b293f9c05 - optee/optee_os/core/arch/arm/plat-rockchip/platform_px30.c +46a2594f3aa4681ffd83538ff397c8e3bf3974ca - optee/optee_os/core/arch/arm/plat-rockchip/grf.h +de4933508c95b4cc044fec515f190d8ff6ebfdc0 - optee/optee_os/core/arch/arm/plat-rockchip/common.h +23bc0f69590154217ef6aa3bf2994644e95460ff - optee/optee_os/core/arch/arm/plat-rockchip/main.c +0a8ff2cde4d20336967135064473ce0e27a74ab8 - optee/optee_os/core/arch/arm/plat-rockchip/platform_rk3399.c +384be00889fd82aa785e7d07fa9f819c764557c4 - optee/optee_os/core/arch/arm/plat-rockchip/platform.h +55fa18d095461797359151b9c915092623f26367 - optee/optee_os/core/arch/arm/plat-rockchip/platform.c +b74b363d6e2a566d4a03278aaacaf9391d505a44 - optee/optee_os/core/arch/arm/plat-rockchip/cru.h +1853ca66ab2f40919fcb69448e1b866eb2bc9e4b - optee/optee_os/core/arch/arm/plat-rockchip/core_pos_a32.S +24c8244ba3044caed1943ad05138413c6db6ab2e - optee/optee_os/core/arch/arm/plat-rockchip/platform_rk322x.c +971d879311868f34f4ebf712ba6de5f9f0ea6f35 - optee/optee_os/core/arch/arm/plat-rockchip/plat_init.S +1db073f2c2461a415ef38ec49964e57e0bbb91a1 - optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c +fbf52bc1a50fae147acaeca0138d7dc640a88275 - optee/optee_os/core/arch/arm/mm/pgt_cache.c +97833bee07659a62e8ae1fd84785699502dd3027 - optee/optee_os/core/arch/arm/mm/core_mmu_v7.c +8e0dd71c8033f999a5bc20eea5e67308b91bcbf8 - optee/optee_os/core/arch/arm/mm/mobj_ffa.c +e6f86e9d7f1972ae55f5ca9938620da5246c59b8 - optee/optee_os/core/arch/arm/mm/sp_mem.c +dd9bfba08ae055c5ec8f97267c700a1526ff774c - optee/optee_os/core/arch/arm/mm/core_mmu.c +9007b3e86aaee64aababa1855ee5e8a53ad4b987 - optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c +014f76e8da8e41ddcb44997962ae5ed43c0c5adc - optee/optee_os/core/arch/arm/mm/tee_pager.c +7b9a469836ce4379d91402d65fd684661f49b0ea - optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h +178685f16c79b3f0dd48d1b8fb551d428ab67b68 - optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a32.S +be2b439ddca86087d85c34efb54fc3e4cfbfc772 - optee/optee_os/core/arch/arm/plat-vexpress/main.c +390b45a60cc4219e64e58f0ca0ea2890dc31a351 - optee/optee_os/core/arch/arm/plat-vexpress/vendor_props.c +cbbb4b7ba94d66daba35e4e8de0e1ea8f3975534 - optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a64.S +1e704fbe287361b0b3f5ce3637b260c8d1740c64 - optee/optee_os/core/arch/arm/plat-sam/platform_config.h +d452ceba090437688ae1658171bcda10e43263b4 - optee/optee_os/core/arch/arm/plat-sam/tz_matrix.h +e99e2242a257c7200f0fbe85c4e9d6524551effe - optee/optee_os/core/arch/arm/plat-sam/matrix.c +86f20052c0aa65ddfcab873b3b6141abfb4efcca - optee/optee_os/core/arch/arm/plat-sam/matrix.h +c85debf71cacdc0e53e262424984cec5fece885f - optee/optee_os/core/arch/arm/plat-sam/sama5d2.h +f04b1753cc27916946e5415343e2976328330716 - optee/optee_os/core/arch/arm/plat-sam/sam_sfr.c +23568f555834f144fec9951e708608b0fc1f3e72 - optee/optee_os/core/arch/arm/plat-sam/main.c +9e03ab42551128401c4786a75250b1db1cd4922d - optee/optee_os/core/arch/arm/plat-sam/sam_pl310.c +91fd5dd0e7ed91073e6858e4a603e2028166a440 - optee/optee_os/core/arch/arm/plat-sam/freq.c +05ae55b82f1b86db41cd5dec856b760b9cbac2db - optee/optee_os/core/arch/arm/plat-sam/sam_sfr.h +51975d5a6d4516cacb42fd70885043c1f8b6fbf1 - optee/optee_os/core/arch/arm/plat-sam/pm/psci.c +e163a9a58cd5dacad7354b43af80bcc98377198f - optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h +d71fe9727d8c848f74ebf421e52d41874966c63a - optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c +bfd010647330fd2fbafb08a6d68018496917c18f - optee/optee_os/core/arch/arm/plat-imx/mmdc.c +13e40fd4f55de4dc5467690339cf670d76621be0 - optee/optee_os/core/arch/arm/plat-imx/imx-common.c +584afcf20fad8029781743589f1d8b888d4d7edf - optee/optee_os/core/arch/arm/plat-imx/platform_config.h +6b46c0394b08058417bc2e944755e80f03294068 - optee/optee_os/core/arch/arm/plat-imx/imx-regs.h +52eae24d48e8e56160dd7b94e68bba26eb530dd8 - optee/optee_os/core/arch/arm/plat-imx/imx_pm.h +19f7be18a342945b17601d7b48c613ea1468eaa2 - optee/optee_os/core/arch/arm/plat-imx/a9_plat_init.S +d9b0648c8e36c59fdae8fb59cf9f73a55b9bb1f3 - optee/optee_os/core/arch/arm/plat-imx/mmdc.h +c35c8cbec5594f84ab070a6f2cf5699a257c9e97 - optee/optee_os/core/arch/arm/plat-imx/main.c +adedaaade5c7177a170c74433b126fb1bd75463b - optee/optee_os/core/arch/arm/plat-imx/sm_platform_handler.c +9dd99c00f7ebbed992c4d8e608ab3716943036e9 - optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c +764fa6e4d0b52fc075ffcb78ba6986ed14d1b58f - optee/optee_os/core/arch/arm/plat-imx/imx_pm_asm_defines.c +98e0fc14280969c4814e9bcf1d2d4421c60f5b2c - optee/optee_os/core/arch/arm/plat-imx/imx_src.c +576710aa6118eebca00bfa8024c4f48ad57b89ec - optee/optee_os/core/arch/arm/plat-imx/a7_plat_init.S +fd1bb378da6d088df88b2239b006b4abb715d0c9 - optee/optee_os/core/arch/arm/plat-imx/imx.h +658c3b177340e2efe74ac7cfe5a0c688aeadf90d - optee/optee_os/core/arch/arm/plat-imx/imx_pl310.h +7a47d9b9d80c3ff0539ada4663d95c9e7bdac984 - optee/optee_os/core/arch/arm/plat-imx/tzc380.c +6c0a9e819b3e4b156c47a4761eef280bcfd0ab2f - optee/optee_os/core/arch/arm/plat-imx/config/imx6sll.h +2d95ab53312d29b23061b747e96c695708612d8d - optee/optee_os/core/arch/arm/plat-imx/config/imx6qdlsolo.h +be59b37f3baf5d18ad949415e77e4c09a1a2ebb3 - optee/optee_os/core/arch/arm/plat-imx/config/imx6sl.h +93a6155f6f294fddb38ac1947f5dce49d68f71d5 - optee/optee_os/core/arch/arm/plat-imx/config/imx6sx.h +fd5c0094f7478ca392710675be72762df5522ebc - optee/optee_os/core/arch/arm/plat-imx/pm/gpcv2.c +383f57d643594c46ec3f7a0b6342fb8d976e6566 - optee/optee_os/core/arch/arm/plat-imx/pm/imx7_suspend.c +68c57702c19d7b9cc0d9a7e5d39968c182cb2129 - optee/optee_os/core/arch/arm/plat-imx/pm/pm-imx7.c +8713d58f831e01a4cd24103e702ada984ed748b7 - optee/optee_os/core/arch/arm/plat-imx/pm/psci.c +245cf6f7ca67610e492c7b95b945f66d2b7829ee - optee/optee_os/core/arch/arm/plat-imx/pm/psci-cpuidle-imx7.S +640fb698681bfca764520cc693b288ff48625deb - optee/optee_os/core/arch/arm/plat-imx/pm/psci-suspend-imx7.S +034c5104ca928cc8bd7b6a3358cdcd84136211bc - optee/optee_os/core/arch/arm/plat-imx/pm/cpuidle-imx7d.c +0ab3222c89bd29af45b6838cb1126597ea378f7f - optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp.h +1fc0e208fd97087384233268cbda1cce852b796b - optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h +46dc26d459e4a5adb2a904c7f6b4c5ef4546ab75 - optee/optee_os/core/arch/arm/plat-imx/registers/imx8m-crm.h +55f6aaaf23e460dbfd791e81c80dd5de5d3bfbfa - optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp-crm.h +e9be4cf1ba19e2e02c3e7a89623e1c67e49737ee - optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h +b355b4bb04068d735c1faa8039e1ade0d88d60d2 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6-crm.h +f93579c365bf08fb597488903040c0b92041517d - optee/optee_os/core/arch/arm/plat-imx/registers/imx8q.h +3931a5db91c6b50993dba75c296966e3e9416994 - optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp-crm.h +c418919325c1927ee3ba3fdc8043d323e630c7e1 - optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h +e8e364071825472444c0223168929efe4a9385d2 - optee/optee_os/core/arch/arm/plat-imx/registers/imx93.h +1a557c230d0c95aeb775b8f02c4a5294b829132e - optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp.h +443dd0395348c2b831b9ea34e1d0df567e22dfa4 - optee/optee_os/core/arch/arm/plat-imx/registers/imx6-dcp.h +7df27071dbcbeb1f977a02e17445136fa22a3749 - optee/optee_os/core/arch/arm/plat-imx/registers/imx7-crm.h +e7cc05f8f313444c45b38132967f4b1393085a94 - optee/optee_os/core/arch/arm/plat-hikey/platform_config.h +fd0dd2e67f5f756333f60c8a6f150e5605c8259a - optee/optee_os/core/arch/arm/plat-hikey/main.c +9899b78e83cfa336552e36d0be06113de438bf15 - optee/optee_os/core/arch/arm/plat-hikey/hikey_peripherals.h +79b3882bc2b3c0bf0492d2dc0385354668138f7b - optee/optee_os/core/arch/arm/plat-hikey/spi_test.c +1ec6602a1f0bc43336d5045adcf92c45c39c4423 - optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h +1afa2f2d04c2c6ba8be7c4d06ef97fefbb03fad3 - optee/optee_os/core/arch/arm/plat-mediatek/main.c +b1b7de5b516440a686f80083730d8a139d7cad97 - optee/optee_os/core/arch/arm/plat-synquacer/synquacer_rng_pta.h +596136d3b40cd1cbae47d4ed48a5b4d246e08dfe - optee/optee_os/core/arch/arm/plat-synquacer/platform_config.h +f7a4aebaabf328850a24fb10ee67d11494346bca - optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.c +0ed37a1910492656246f85705f9b93df490f10eb - optee/optee_os/core/arch/arm/plat-synquacer/main.c +0b99d0c7135e7f0002ef7a51d63461307e66203b - optee/optee_os/core/arch/arm/plat-bcm/platform_config.h +92cb86eafac038fc02be252efc14c3e3316f27af - optee/optee_os/core/arch/arm/plat-bcm/crc32.h +3d4f18ba7a9634be9a46f900264cb0132fd65654 - optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.h +b867c067653be4032105afc77ee562740d8d241e - optee/optee_os/core/arch/arm/plat-bcm/main.c +435d5321e6d484c095ede7a5b320ec92fddb3025 - optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.c +db3ddcb5c48ff30c64e8b561ed5300400d67bca1 - optee/optee_os/core/arch/arm/plat-bcm/crc32.c +84db75f5c982cafdce7ebdb1f5080253cc0f15d7 - optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h +105fcd115c8f37f13c3f1617c6e564dce1a1a50f - optee/optee_os/core/arch/arm/plat-stm32mp1/reset.S +02204c43ef491bc5768cc1dd754c14e96a79c402 - optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h +0347bb1185d401c31ba23382067c63801859b98a - optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c +41fc0d480726ccac287c2341b62956a102d2b134 - optee/optee_os/core/arch/arm/plat-stm32mp1/boot_api.h +374484f26498072118ccdcb034fe90dba4c5ba13 - optee/optee_os/core/arch/arm/plat-stm32mp1/main.c +085787300ce325b32fffae16ae2889f02e925f20 - optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c +4cd706376b2b8e9f29529251f6e8dd0f97b45a2d - optee/optee_os/core/arch/arm/plat-stm32mp1/link_dummies_paged.c +70226b5b77dd3722328a07eb44802b30f9c7926e - optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c +a1238faa3df41c0c66412e3b032255e1cd4988eb - optee/optee_os/core/arch/arm/plat-stm32mp1/scripts/stm32image.py +a3ac99fd762c9216188d37d084dd70008fbe1199 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h +61bf4808eef711cc1f7e49f85642e691865fbac5 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h +aba3134290522c123b965727423536367134df31 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c +36a643ca9888123735aee8f3a13fac3544304bdc - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h +5ce02d8d7ff756a903800fa1b2634052ba695738 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c +d51b20c506376c9a4d0d94786e6de3d46e871540 - optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c +976f6cd43eb43bf7d8923851c1305a326bd1180a - optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c +536663cb01d75d67a4021fe8314c5ae79909dbd8 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h +4e92814caf4d208f3424697ce4a54cbceba75632 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c +d335d9bb50b2453d365ca88f3f18520fdd0a1086 - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c +e7ec6cb3b0018db5664ccd87d3ab1529e5d5713e - optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h +11ce785f6bdd56fdc8b32c6c2174a9b49b96b230 - optee/optee_os/core/arch/arm/plat-uniphier/platform_config.h +84c6815e58e7c13740a2e365505da1aa9d87a325 - optee/optee_os/core/arch/arm/plat-uniphier/main.c +c043a9411306559a982b5d09ae419821ff026bd0 - optee/optee_os/core/arch/arm/plat-uniphier/kern.ld.S +012cc9cc5cd4d1213266d657558cd6c1fb998e1f - optee/optee_os/core/arch/arm/plat-hisilicon/platform_config.h +bf4be1dd46e6278e5b9b8b6a40b710d90007d915 - optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S +114f50b1c0140361479b38126c3cc1d0607a3f91 - optee/optee_os/core/arch/arm/plat-hisilicon/main.c +1e0932868e4fc72946b4b12a3650c383dcdd7a79 - optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100.h +92415c6775326559b08df1d2a9976b3e1ebb0a72 - optee/optee_os/core/arch/arm/plat-hisilicon/psci.c +43dcd40dee8c1bca63526b7590768c430e2b9eb4 - optee/optee_os/core/arch/arm/plat-corstone1000/platform_config.h +a955b4ec9fb79d3fd9dcab27f3d88534ba669c6e - optee/optee_os/core/arch/arm/plat-corstone1000/main.c +9421c26b6ce38f1d5da0e2f431afc0cab732f0e6 - optee/optee_os/core/arch/arm/sm/std_smc.c +0fbfd45981f9512d688a49c32add4297540c689e - optee/optee_os/core/arch/arm/sm/pm_a32.S +615d9401894c37dec5e5ebe9bcdb678df854564e - optee/optee_os/core/arch/arm/sm/psci-helper.S +d15ae1ce071edbfc8d4d4de7c944cb1d8712136e - optee/optee_os/core/arch/arm/sm/sm.c +bbd1df35108340d6d4e6179926681fb794f8ce12 - optee/optee_os/core/arch/arm/sm/sm_private.h +8a9cd4bad5748dac76110944be1fb3442e98b2f6 - optee/optee_os/core/arch/arm/sm/psci.c +45960371e7a1224c4d067ff3c172952b7d616998 - optee/optee_os/core/arch/arm/sm/sm_a32.S +79b02c9017b471e73d8c11acc7f91278ec851f2b - optee/optee_os/core/arch/arm/sm/pm.c +2701a5021cec550314803b83b43e5a3fa6f6aadb - optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi +abbe0e5a7c63995c207b1995649e3a6ed6b4221a - optee/optee_os/core/arch/arm/dts/stm32mp15xc.dtsi +c07147cb14bc871e069f3be8248fc2c79e311949 - optee/optee_os/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi +d23af59b64d5380f6f9c8ca37a1a5b1af3e9f93c - optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1_ek.dts +9be7fd7b5c30eae1dc855f6bfca353c455dd812b - optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts +5c329735e2a8eb85255d6ddd7a56064d03034cb2 - optee/optee_os/core/arch/arm/dts/stm32mp151.dtsi +1985ea8670dc7c7937541f6b2da9c30c41ee000d - optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi +c8ec256ae55cb6c849aa51624b9974259884b159 - optee/optee_os/core/arch/arm/dts/at91-sama5d2_xplained.dts +2701a5021cec550314803b83b43e5a3fa6f6aadb - optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi +0f41a6ee8e489bec0d79a976edb540945506d498 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi +9df393dc1bdde2c8ab9deca10271f9135234a752 - optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi +c801e4c35f00786835f0cd63b71559a146086866 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi +41aa3da18dcb49b316aefc9ad5eed7dc2664dabc - optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1.dts +794650f14bc79f9ccc2033efdc81da79623d351d - optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts +0cc38427ae1b225d88d000f9438b7cc34e883b30 - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi +6510b2294cc4aeb2601cce6f17cffc6eee8c58dc - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi +8fccbbae61ee6f2694b88563c096e640101dae55 - optee/optee_os/core/arch/arm/dts/sama5d2.dtsi +ce82c06ac99261e680a62585d80c90e9dfe941fb - optee/optee_os/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts +6ed7397e2751cabb21fc7e87b53983b9117d2e26 - optee/optee_os/core/arch/arm/dts/sama5d2-pinfunc.h +e28863664f28385599bf66b2a690760e4c1bd63d - optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts +6c18e9690a909c9b4898d1d609cdf3874e22d19a - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi +361479ac7684841706aca2fdb4c3d2c9f8e0e13e - optee/optee_os/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi +94f010962fb67b20e43e2f44cb3f317f624d91e1 - optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts +d26bbcf985b7523a6af715be4feb22233be74ba5 - optee/optee_os/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi +d7230a1568081b9a39b151bbe38f188691b2b84b - optee/optee_os/core/arch/arm/dts/fsl-lx2160a-rdb.dts +b318d72ed3eee6e4bd7d8ecdb5b1eba8dfc31f89 - optee/optee_os/core/arch/arm/dts/stm32mp157.dtsi +9dea507c72c9eec09336578711a432b198478a56 - optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1.dtsi +d6dbda8b14af74b3a63db810c4c4ed53bfb097bc - optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi +0c1276612681bf9f22517513242e678c22551542 - optee/optee_os/core/arch/arm/dts/stm32mp153.dtsi +194fd8067d397ca409c3380341a5de0277269382 - optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi +f8387a2601ba505a39c886a752ab25e6ece458de - optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi +8d99ad09575f0e8344e4caa6f4ac16f66108f22e - optee/optee_os/core/arch/arm/dts/stm32mp15-pinctrl.dtsi +676f90d7c25eb035af4475d83d6e355f07ac0634 - optee/optee_os/core/arch/arm/dts/embedded_dtb_test.dts +9f93f18baccbb7718af6c571e70dfecb3529b694 - optee/optee_os/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi +23b592b2e03dead1636f2110cd64531ec92bf807 - optee/optee_os/core/arch/arm/dts/stm32mp133.dtsi +ad3b5f3ede872c44e014eb6ca5a69329195968a6 - optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts +e793accc60529af1c41651063de57ef9cd0a0b5e - optee/optee_os/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts +62934ca38185da79af035ba4a82f62ae3a33f4ac - optee/optee_os/core/arch/arm/dts/hikey.dts +7098d09c9fd4f2accc2e23713ad9a3b676026ac2 - optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi +7c4d0d445cc32c31b4a4b2a2c01cd773605e3494 - optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi +fb4be0e25bdca79fcf443034897f81e669e42d88 - optee/optee_os/core/arch/arm/dts/fsl-lx2160a-qds.dts +afc997b206bbdc6c60cd9f08308b7b53832eac0b - optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S +933f5b3256795b2ffea6b7b93d75365f865599b3 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a32.S +09cb511f6b571c162ae284911b5af9c702dd5130 - optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.h +0cd13267dd6db52ed1ff3742dcb7adb15bdff8cd - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.c +913da3b19e7cc7244ff858f2bace0bc38736fb06 - optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S +fb5f716381766749999f0032bf39f39bf88af12e - optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S +6e006d07e0e25f49c5af73e0e522f6f97963275c - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_aese_a64.S +47012ceb6af70d59a7666ca551814aa811efe9e8 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.h +1ab432ea10e0e0edf03b0ce17bb5277fea163578 - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce.c +9c1f14fdc223c00af03fe8b922a520419b7fd0b9 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce.c +cf714bfd8657a2fff8112b3b94d7e476d51e2e60 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce_a64.S +2c3ba8b73e012b48da6c8ff12c635f8fa109e5a8 - optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.c +f59a39b271b322f5bdd6baebdedb3ef701a78b02 - optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce_a64.S +0b84c15b4796a2a23a095ae2d6d037677510760a - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a64.S +2da4cbb016071dacfbbd7c99799a27ad6d8c56a7 - optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce_a64.S +d857b4b442486f2ac052ee687cb6d6f424843433 - optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce.c +bb50a2e7fffd5945ce8214bf57ad9d55135b46c0 - optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce.c +45797af469d803907920fecce84f86fbe684a40c - optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce.c +02305ae36a17490cecdc906c0970e8625ea9e6a1 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.c +cb5a3413393627c5fb4626c2315e2e12bf01abf1 - optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a32.S +0c1913711dd52b93cfe5d2d476a3a050a5bae97d - optee/optee_os/core/arch/arm/crypto/aes-gcm-ce.c +ad5becb659037cf49bdc0fccc768675b2ce55068 - optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce_a64.S +f7d7763974a8359b3d84d7c848542872c9a1a1b4 - optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.h +ad9a80c4d43acd03ae5d27e14df6dfee3abc4e05 - optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a32.S +56e9da14883d74e8eca3a4c7737185590cf14c08 - optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a64.S +f413d0ba2e04b6ef2802475a9132687b2f19237a - optee/optee_os/core/arch/arm/plat-ls/platform_config.h +cc663051dbd6ba5fbd15bd4409b7ba732dcdc025 - optee/optee_os/core/arch/arm/plat-ls/main.c +095caecf26786efe69779aab593c67447f44b9c2 - optee/optee_os/core/arch/arm/plat-ls/plat_init.S +43ecf7e39e7a28c27b7b79a3615e3614939834bf - optee/optee_os/core/arch/arm/plat-sprd/platform_config.h +40b290a479f2ef757ef2505ac996b953a69ca654 - optee/optee_os/core/arch/arm/plat-sprd/console.c +259bdb7ec46936003362575b273afd3f3a9981a7 - optee/optee_os/core/arch/arm/plat-sprd/main.c +92467f9b57e8dd5b4962ccd05ea4929ab2dd6c4d - optee/optee_os/core/arch/arm/plat-rzn1/platform_config.h +1b82881f2b80531fc7743309c38c8e9370969ef1 - optee/optee_os/core/arch/arm/plat-rzn1/rzn1_tz.h +c9a02f7b7f7b87ffbcb1b4817f13f0a9ce102e7a - optee/optee_os/core/arch/arm/plat-rzn1/rzn1_regauth.h +6a09760ea59ffdf2d2d519d19a27687600c51a08 - optee/optee_os/core/arch/arm/plat-rzn1/main.c +48ef8147e12f826d7e87c67d7c12e3932d317546 - optee/optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c +245d63c49ace44a4319be3f8b9882e520bf67448 - optee/optee_os/core/arch/arm/plat-rzn1/psci.c +776215d1f8598a5514e759d70ae400a8101f835a - optee/optee_os/core/arch/arm/plat-rzn1/a7_plat_init.S +176317554a2541fa4a9d6504dbe52227bdcb5083 - optee/optee_os/core/arch/arm/tee/cache.c +df18a9464597e6dbc2844ec1e5d735db00c74f37 - optee/optee_os/core/arch/arm/tee/svc_cache.c +9b3b72c3d28cd1ef84a46454ad1d2d20550608d2 - optee/optee_os/core/arch/arm/tee/entry_fast.c +ebfaf4c6f38995b655230d2d5e3981d0ab12f8b6 - optee/optee_os/core/arch/arm/plat-d06/platform_config.h +af303d7bdec46d72f8dc191b59424ff83ab7e2ed - optee/optee_os/core/arch/arm/plat-d06/main.c +ca3077b3f16c93f5d5350d4b21c08770138bc3af - optee/optee_os/core/arch/arm/plat-d06/core_pos_a64.S +8694a8f4be2551b1bf8f1abcb17284a8b202e5af - optee/optee_os/core/arch/arm/plat-zynq7k/platform_config.h +e8a97315a58b289054e1f3fb5418cba746b5633e - optee/optee_os/core/arch/arm/plat-zynq7k/platform_smc.h +19b5c8130f55a17a4ee903fba47f5bbafe9ac918 - optee/optee_os/core/arch/arm/plat-zynq7k/main.c +55fee8bf238c661a2f59118cbea5d8fca29471f3 - optee/optee_os/core/arch/arm/plat-zynq7k/plat_init.S +94a132cb905aa39756cd3bd0c4cd0bb955893219 - optee/optee_os/core/arch/arm/plat-amlogic/platform_config.h +397906387ace258a7976d69aaba14ef9a4cde8c4 - optee/optee_os/core/arch/arm/plat-amlogic/main.c +b1793c2149008cfc5c242a3fbbfcdfecfb082b4b - optee/optee_os/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py +eba718605aa45932a4b80632aa65d8cb35dc2b22 - optee/optee_os/core/arch/arm/plat-versal/platform_config.h +d0493efb594dfef8ab3869060ea8de26d977ddc4 - optee/optee_os/core/arch/arm/plat-versal/main.c +e2b43db2de0208697b4c88f2f0562d58a4b0b2fb - optee/optee_os/core/arch/arm/plat-d02/platform_config.h +9581f5fca967939ce5938afcc66f47c28a64b41a - optee/optee_os/core/arch/arm/plat-d02/main.c +d4139567b62848e1c43b6759cd767e034e10db73 - optee/optee_os/core/arch/arm/plat-poplar/platform_config.h +2ce2abb04e66b937356a0863cb1bdfec5c66673a - optee/optee_os/core/arch/arm/plat-poplar/main.c +8fa033ec5237e06aef907c0f641f208388793c26 - optee/optee_os/core/arch/arm/plat-poplar/hi3798cv200.h +59bad93e3d397c859768a3a8f7e46ad98f2ba3d4 - optee/optee_os/core/arch/arm/kernel/arch_scall.c +eafaba99cd9d60eacf4a3babbd16c0a6daa4c283 - optee/optee_os/core/arch/arm/kernel/thread_a32.S +f9a92f478e19fbf1059649d6208b99ca6613b311 - optee/optee_os/core/arch/arm/kernel/cache_helpers_a64.S +44470d3e7b9cdbed041ae13408e647edc645aa74 - optee/optee_os/core/arch/arm/kernel/misc_a32.S +96fd19a3b4462b4a6bf63b89dd394fb644df9cb3 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S +705b09bc40f35f83a32b350e673c59728258e250 - optee/optee_os/core/arch/arm/kernel/stmm_sp.c +d347c9bafe24140b9717de8891d9659b01333e07 - optee/optee_os/core/arch/arm/kernel/arch_scall_a32.S +c10de505f0de2bc6ced1f9349ecfb51f0c5d306b - optee/optee_os/core/arch/arm/kernel/virtualization.c +af8d99e369132adac450a89f4b07fbbada85156d - optee/optee_os/core/arch/arm/kernel/misc_a64.S +b4d64fa787d883488032c460e9bdd9219c8b7e6b - optee/optee_os/core/arch/arm/kernel/link_dummy.ld +09ae96d24a26b79da3b4d74657264ac8fa57e7ee - optee/optee_os/core/arch/arm/kernel/timer_a64.c +6253299ed089d1eccd655faf0ef4921a3b090d0c - optee/optee_os/core/arch/arm/kernel/abort.c +26f9cf452d8776f7612c50294f57057815bb3dc6 - optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S +c98d9153adf3b0cfde1af189f873d59ff8b88af6 - optee/optee_os/core/arch/arm/kernel/link_dummies_init.c +8ebc782c56e8a49cbb1a1842f396de645f1f46a7 - optee/optee_os/core/arch/arm/kernel/cache_helpers_a32.S +6a5fe12b6846231d6aa70e92f7b4220683c41c24 - optee/optee_os/core/arch/arm/kernel/entry_a32.S +cbc0913df63d07ee9b46ed402d9d9cfb57dc8f23 - optee/optee_os/core/arch/arm/kernel/thread_a64.S +333d53646d0a8f7c4b5f3f5cecece5725a8f0dde - optee/optee_os/core/arch/arm/kernel/asm-defines.c +63ea63ab5d506208970d6f5b8738ee82850aefe3 - optee/optee_os/core/arch/arm/kernel/unwind_arm32.c +cff200d2106d26baf930f16e6caa8634adebbe08 - optee/optee_os/core/arch/arm/kernel/vfp_a64.S +056cac06f5cc8f43b14154ddbf1cd5d8c382ab74 - optee/optee_os/core/arch/arm/kernel/tlb_helpers_a64.S +000f63612d84b18bd33c3bb7a7ad17308e32b296 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a32.S +cfe9209c0f08602f20df8752df4016c257305627 - optee/optee_os/core/arch/arm/kernel/vfp.c +9a79a97751b816a6976bd36948874edb22b17563 - optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c +23d2ba34a5f3de4b7c12134cd6ffcb8e4957e672 - optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S +24e1db339b48a73b6aaafcfca9047c7855896faf - optee/optee_os/core/arch/arm/kernel/rpc_io_i2c.c +c591321644c6fd32d600a9a797daf4cdc48647d2 - optee/optee_os/core/arch/arm/kernel/spin_lock_a64.S +9e422c03938a8b32edd015a653d5dac29880a5e2 - optee/optee_os/core/arch/arm/kernel/unwind_arm64.c +e6509a63f63d52f3595d0f5b65346f6b569b8dcd - optee/optee_os/core/arch/arm/kernel/thread.c +79bd325bd306a65c018341c52386b41e92028f08 - optee/optee_os/core/arch/arm/kernel/thread_spmc_a32.S +5ca340af84791488b272c18d84af4e49b1c94f7e - optee/optee_os/core/arch/arm/kernel/tlb_helpers_a32.S +623bd09a42ef354ab3d4335998660c788d656cb0 - optee/optee_os/core/arch/arm/kernel/thread_spmc.c +4d98d1a3c20f4e424fd4140949c712f1769daf93 - optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c +b5ebdeae94cfe7fd7a32f0be15e8a28b230cd175 - optee/optee_os/core/arch/arm/kernel/tee_l2cc_mutex.c +d6c09e6c39b889a25fcb82340f1725f9d0427d59 - optee/optee_os/core/arch/arm/kernel/arch_scall_a64.S +6ab260ed8b0c118bdef56c78beeaa3887daf4059 - optee/optee_os/core/arch/arm/kernel/boot.c +170f9fade8d4cfd3805f2aa2383b7f3d358507df - optee/optee_os/core/arch/arm/kernel/idle.c +99dbd4c6ced9d21fbf6db2c3e7c6755d8c6bce28 - optee/optee_os/core/arch/arm/kernel/vfp_a32.S +9d0bd8480809254b743bf3d766efe7c3cdc70034 - optee/optee_os/core/arch/arm/kernel/kern.ld.S +289f0d3d108c7e83aedd70c9b92133b7a036f000 - optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c +599bd7fb683e3e1c0eddc71e66e5eb979e8e7c28 - optee/optee_os/core/arch/arm/kernel/spin_lock_a32.S +da85ea618bd809353d036a244165f159f124bfa6 - optee/optee_os/core/arch/arm/kernel/entry_a64.S +c5547aac70334a836d7a0d7a3711e972962679a3 - optee/optee_os/core/arch/arm/kernel/secure_partition.c +a3d562edc0d696f64d77e9c96d86c9a88451b5a1 - optee/optee_os/core/arch/arm/kernel/vfp_private.h +b1157e1c8f98a0bee2b0edcd3e766193dd29a126 - optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c +4eb9e4b6f2b6b8f595acf22a683d831fee0ef40f - optee/optee_os/core/arch/arm/kernel/unwind_private.h +784a5cea3b2741f04facdeaf7bfac0e093630875 - optee/optee_os/core/arch/arm/plat-stm/platform_config.h +fd20baae7413cd701b88ba6dfeb2a294a9eeb452 - optee/optee_os/core/arch/arm/plat-stm/rng_support.c +b6fdb7e3086bc494442508848064feb6c72f2ca3 - optee/optee_os/core/arch/arm/plat-stm/main.c +bdd38a0220aac82b0aafa97e8f1993cb27e0ac1f - optee/optee_os/core/arch/arm/plat-stm/tz_a9init.S +4e93d8d25766b05b285896a4944c227f8b4da442 - optee/optee_os/core/arch/arm/plat-sunxi/platform_config.h +46ed9632901e137bb6316c0586d6982df7101499 - optee/optee_os/core/arch/arm/plat-sunxi/main.c +eaa619f9de58ee047ca541b4c238b2afb5b83b6a - optee/optee_os/core/arch/arm/plat-sunxi/psci.c +2399244b8020942c1b3a3cb924194e8770560051 - optee/optee_os/core/arch/arm/plat-sunxi/plat_init.S +728f6a99ffec19cfff92195c3e68080f0dcfacbc - optee/optee_os/core/arch/arm/include/arm64.h +c3a08b120460a25968597b72b59a0634e94dd49b - optee/optee_os/core/arch/arm/include/hafnium.h +55298b41d3e8800e2aeebd746e9e1371142fbd6e - optee/optee_os/core/arch/arm/include/smccc.h +6b7dc1082fa7e1b101e95c0588ea1b1224cfe5a8 - optee/optee_os/core/arch/arm/include/ffa.h +ef7bffd960c06d3d1f3248123500188bfb08cd13 - optee/optee_os/core/arch/arm/include/pta_stmm.h +3ed813b9b977510b9907819fa2443a03eda8ca4b - optee/optee_os/core/arch/arm/include/optee_ffa.h +b994483c8394f9eef531d2c379fd9ca5a1b60fed - optee/optee_os/core/arch/arm/include/arm32.h +7003b864c28695954a41184611e55102dc8e7500 - optee/optee_os/core/arch/arm/include/arm64_macros.S +81aefd662cc3b7d6278de360ede9cd9545c3f7b2 - optee/optee_os/core/arch/arm/include/arm.h +ff294f026e09453cbd1ffb3cbc764befc573676c - optee/optee_os/core/arch/arm/include/arm32_macros.S +1cea08afcf4cab7bbff31ea3666c5360c4c03498 - optee/optee_os/core/arch/arm/include/arm32_macros_cortex_a9.S +6bb78d1526e06ec55a411f86926c1feb69fbdff8 - optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h +ffc908df97e9fd07da49d5df02ac4da1bb8b6d13 - optee/optee_os/core/arch/arm/include/mm/generic_ram_layout.h +c0f44a85d8dc7ed7ee51a4395e3456f05265a0c1 - optee/optee_os/core/arch/arm/include/sm/psci.h +1570da79c88e5ce844afe3665b7835f325fd5594 - optee/optee_os/core/arch/arm/include/sm/teesmc_opteed.h +abb9582e539a959b54458d29c0351dcc9b3a6e0c - optee/optee_os/core/arch/arm/include/sm/pm.h +cabb67de891151838399c123a02c367be10dd244 - optee/optee_os/core/arch/arm/include/sm/optee_smc.h +7f4e2bd9aea7292a7cb66e4be4ee5e118c3d5c3d - optee/optee_os/core/arch/arm/include/sm/teesmc_opteed_macros.h +ce5b9f00424203fbd6eace4a72a28b9f82658bb1 - optee/optee_os/core/arch/arm/include/sm/sm.h +51ee5fce8f3aa7306e4e111ebf920128f72ce1d8 - optee/optee_os/core/arch/arm/include/sm/std_smc.h +5a07f5963ad453f3de5e43330199b116240912f4 - optee/optee_os/core/arch/arm/include/crypto/ghash-ce-core.h +71f59143dc113e32eafbaf32749a68b80304cd37 - optee/optee_os/core/arch/arm/include/tee/entry_fast.h +1713fc8bf0923bc7dfbe82b8a445b10d9848bdc2 - optee/optee_os/core/arch/arm/include/scmi/scmi_server.h +d567e405f7457e2a5a572391254b503cfc11712e - optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h +109240ea4c259327060af80955d32015e628c786 - optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h +0777b5e2b4ca54beddbbf59fed4ea20936487e3c - optee/optee_os/core/arch/arm/include/kernel/tlb_helpers.h +03a55634fef67a071aa1f0f3cd89ba24743675b0 - optee/optee_os/core/arch/arm/include/kernel/misc_arch.h +72a3f7bc0e57ea00dce12cbb73e41a20f90fbfdc - optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h +37af9222c63c149803c61dab6a9f91a50be335d0 - optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h +9284944a0055f114d23e121c972c412ae97b7f7e - optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h +b95d779051d2b0e70152491dc1046ef721584d7a - optee/optee_os/core/arch/arm/include/kernel/stmm_sp.h +2360143179a1f2cfd4a3cbbbc03448bb6790d698 - optee/optee_os/core/arch/arm/include/kernel/arch_scall.h +59802332e69d96bb3641667a395d02f3c2fcd82f - optee/optee_os/core/arch/arm/include/kernel/cache_helpers_arch.h +0607a5b2b01b53cceee3b47ccee320d2fb27bda9 - optee/optee_os/core/arch/arm/include/kernel/vfp.h +b65be7335b7bf4f535466fc90543e45ecf9f8733 - optee/optee_os/core/arch/arm/include/kernel/secure_partition.h +b956d886be34a123153e72af01e2f4f4cbfc2dcf - optee/optee_os/core/arch/arm/include/kernel/delay_arch.h +84b9ebb0e017dd1d8594f810924e78a79a73aa09 - optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_def.h +38b584ff94d19eb4ee5a09924512512856c7946a - optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h +9e791243466051df2420efe6b2a0b1c5354fc679 - optee/optee_os/core/arch/arm/include/kernel/thread_arch.h +dd54ce3d620f2b22180ef201aeecf74b5b4480ad - optee/optee_os/core/arch/arm/plat-rzg/platform_config.h +d3d7fc01ca1db9ed9c42923fc3abf988ee8f35e0 - optee/optee_os/core/arch/arm/plat-rzg/main.c +b3d21a1017a2f66d52d2f6da7f671715aba08021 - optee/optee_os/core/arch/arm/plat-rpi3/platform_config.h +84b7b56e93417a949b15de5348e3b01f21ccd448 - optee/optee_os/core/arch/arm/plat-rpi3/main.c +49dbe1b862ab1676a3186ddc9f6c7650820902d7 - optee/optee_os/core/arch/arm/plat-totalcompute/platform_config.h +8c7bb877e78282e8229e60073e1b5416c9a0d122 - optee/optee_os/core/arch/arm/plat-totalcompute/main.c +00e4e12466db95649e17c7dce132fd03e23b837c - optee/optee_os/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts +8cf15d5f8508083811e9df9e81f5de5d6f6861fa - optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h +22c8392cd3c7d3efdbe4ab3b68a650710be862b1 - optee/optee_os/core/arch/arm/plat-zynqmp/main.c +acb5b7a67e6e3a2c8309d3b5cd972a643437c4ad - optee/optee_os/core/arch/arm/plat-marvell/platform_config.h +1789c7a402691f5c378f2108a0ffddac22926472 - optee/optee_os/core/arch/arm/plat-marvell/main.c +382e9ecd3c29e2e17e189e59fd3427c1c682e199 - optee/optee_os/core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c +5277b6c495f09f7293c54198cbee638bbfdb0254 - optee/optee_os/core/arch/arm/plat-marvell/otx2/core_pos.S +4ff87aa9e6aeaf3d88e17943ead649009d0b0fb2 - optee/optee_os/core/arch/arm/plat-marvell/armada3700/hal_sec_perf.c +e5ec049ffef670a29b7cade4d9d9f96abef549f6 - optee/optee_os/core/arch/arm/plat-rcar/platform_config.h +4e0482b88d52f8a7d6adf974d0e5015f13872f65 - optee/optee_os/core/arch/arm/plat-rcar/hw_rng.c +40b8edfff755528bf204681a8f80de74a95a6673 - optee/optee_os/core/arch/arm/plat-rcar/romapi.c +b713d037582ce7c9f21402a91665b067ed931ff7 - optee/optee_os/core/arch/arm/plat-rcar/rcar.h +8e4974b5fef12aa6421a66df3916ac232029a809 - optee/optee_os/core/arch/arm/plat-rcar/main.c +9ca9f50ac43c9276ee67375c8e915f0827e349d9 - optee/optee_os/core/arch/arm/plat-rcar/core_pos_a64.S +f8a2662937d568146b977cdedf2e268e5b1f6b6e - optee/optee_os/core/arch/arm/plat-rcar/romapi.h +15d328d6ef35c2f6a4c4f5a69f4eb2a571802c1c - optee/optee_os/core/arch/arm/plat-rcar/romapi_call.S +d838c4f3e30ef56f81d51a7b6ef1a31df3657c31 - optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h +82e665e55b85c8f52413d062164e161349d25bbd - optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c +6631e40f0ad62f389ac0fc0c59e142b9313bb246 - optee/optee_os/core/arch/arm/plat-aspeed/core_pos_a32.S +4b7308420adcb67b60e528f1beab6c68377d6e2a - optee/optee_os/core/arch/arm/plat-tegra/platform_config.h +c19a206b427ed76090247d074c9b81a0c6dadfc4 - optee/optee_os/core/arch/arm/plat-tegra/main.c +1046d8e53fbfdcc9ffd8a63a012cccfb40cafacf - optee/optee_os/core/arch/arm/plat-tegra/tegra_common.h +798efa99d464a96c2b70639a3c25ba14f618c29b - optee/optee_os/core/arch/arm/plat-tegra/README.tegra_secure_storage +608a97cee50965f940169862e6754dd17612fadf - optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a15.h +f185f9e1ea859d9f4233cffc8c78fcbe72e4c090 - optee/optee_os/core/arch/arm/plat-ti/platform_config.h +2a0bf39e0ef3f1dfa764058f0142b54a53a92006 - optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a9.h +ee95c68b68df1476e39ee0a9d3d4f3f1053168e8 - optee/optee_os/core/arch/arm/plat-ti/a9_plat_init.S +233c224aabab101937a19dca5c2de23d699eea8b - optee/optee_os/core/arch/arm/plat-ti/main.c +537927d745de820a0b09ef12a56515a53e68bcef - optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a15.c +c3c107d238f7f96e38416cbd2ce783cb5c5231be - optee/optee_os/core/arch/arm/plat-ti/ti_pl310.c +ec14532de7ea2afbf4bb14220372faf052e0d77c - optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a9.c +5222bea7254df96932e51593a9aec12808fe2584 - optee/optee_os/core/crypto/crypto.c +6ee664faf892cf6eb54780694431dbc599714a4c - optee/optee_os/core/crypto/aes-gcm-sw.c +5e7555e339aca88d6573eef4844fe96171e073ef - optee/optee_os/core/crypto/sm4.c +e68ca1aeee7c839ed6427892eba453b827fe73a5 - optee/optee_os/core/crypto/sm4-ecb.c +057545a9e027cdd9daa7be1500acbb767b134a5a - optee/optee_os/core/crypto/rng_hw.c +82c796645d5446d81b6013ad6338920da67f8ee6 - optee/optee_os/core/crypto/sm4.h +3c8f23a338eea10aca5682c64d8a12902fc433f5 - optee/optee_os/core/crypto/sm2-kdf.c +5a46f6fc2ccfeff927d3588c22e667102497a4ce - optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c +be1aa6aee3798fdc77ebc0a6b37bf5a80fc3baee - optee/optee_os/core/crypto/sm4-ctr.c +35204fa717049aa26af2abef06d5466dd22b09a0 - optee/optee_os/core/crypto/sm3-hash.c +2bfc17f9e38fa5fd9c637a5cd1ddcce6300ced48 - optee/optee_os/core/crypto/rng_fortuna.c +f5e19ab8d6191ffddbd796f4b194c1b9fcab79b9 - optee/optee_os/core/crypto/sm3-hmac.c +ed4f8a199dfc091202a84e729efc08be8166e573 - optee/optee_os/core/crypto/sm3.h +2e625c76a0a14b6b74d7b3be0b8af4e28516d53a - optee/optee_os/core/crypto/aes-gcm.c +ec9b32fd9bc56871bc638975a31eb271543b4753 - optee/optee_os/core/crypto/cbc-mac.c +e73ae6d522f149d7ffc117d3f026bd44fcd262c0 - optee/optee_os/core/crypto/aes-cts.c +8a9f6567ac8b3d0894830f0876d17d71e94435e4 - optee/optee_os/core/crypto/sm3.c +a730ddd73aac7bf7e2f4530cb84b4139920cc30e - optee/optee_os/core/crypto/sm4_accel.c +4a9aec205bda6db9f341b00e62940610c4e3e728 - optee/optee_os/core/crypto/signed_hdr.c +7b6658854eec61d103f730922493a99440ca594d - optee/optee_os/core/crypto/sm4-cbc.c +5e36787d311129f8c3649eed00a7bc54de3dc471 - optee/optee_os/core/crypto/sm4-xts.c +8f90f483de2c041395379c1d91a3cd1739dbd6b8 - optee/optee_os/core/drivers/pl011.c +e0f77456c7a5e485619186caeaf812b3dc8eb572 - optee/optee_os/core/drivers/stm32_etzpc.c +e241e2600db481b9c897bc48b71104c3aaa5bbbf - optee/optee_os/core/drivers/bcm_hwrng.c +45fe58e31faea84f641347c7bd70e426567d781b - optee/optee_os/core/drivers/serial8250_uart.c +f2395342fb43346befc286959fa01114b0ff28e2 - optee/optee_os/core/drivers/versal_mbox.c +a4098254e952201f7b1f513d7bfa85c753805466 - optee/optee_os/core/drivers/atmel_tcb.c +514313602dfb100842f336c91efef495a658b3a9 - optee/optee_os/core/drivers/stih_asc.c +61fd12b4c0e6e8d4afffed71c182286581de4837 - optee/optee_os/core/drivers/ns16550.c +8457979f3ce7a5ad5eff7c23b2887fe3d61a29d7 - optee/optee_os/core/drivers/xiphera_trng.c +0dde4c0ccc9de1c9506849f158f4d0bfe08c7716 - optee/optee_os/core/drivers/atmel_rstc.c +5f7af6748259588f30732bd198cada68ea449968 - optee/optee_os/core/drivers/versal_nvm.c +20036824317b2f8dbae5d8cdb283f557e3c303c2 - optee/optee_os/core/drivers/gic.c +99907094047bf316222d7f0af9b7b043693a92fd - optee/optee_os/core/drivers/imx_uart.c +32c848c3a2f49db8076d0ef95094acec87a733f4 - optee/optee_os/core/drivers/stm32_gpio.c +9f608bd36d7697b68b44c50cf8070bcfa4c872c0 - optee/optee_os/core/drivers/imx_rngb.c +2ace80614760dbbe872200c0405c3e28fe6a5880 - optee/optee_os/core/drivers/cdns_uart.c +8294666cb76a8dde2dc2f1155586de082381312b - optee/optee_os/core/drivers/hi16xx_uart.c +c527277e48632898dea03473e67ca39837e75ed6 - optee/optee_os/core/drivers/atmel_wdt.c +9203d1e334c03870efbb1296fc2b9151c8971267 - optee/optee_os/core/drivers/imx_sc_api.c +5df98204d9e9768c88e295bfa8d2d03829a8bf4e - optee/optee_os/core/drivers/stm32_iwdg.c +d89b4120ce4c2335a04d1f4aaf73b8e188140fba - optee/optee_os/core/drivers/ls_i2c.c +f8a2cf16ad82a5a58a932430f4155678097f4ef4 - optee/optee_os/core/drivers/ls_sec_mon.c +1f8114767f04f10575e9d516120b9e8004560045 - optee/optee_os/core/drivers/zynqmp_csudma.c +e26dcea60a7bdcf95acd06bb25f806e8b4d3d9ff - optee/optee_os/core/drivers/bcm_gpio.c +89ce33aaddb1581c98d889695b695d3f91d1abac - optee/optee_os/core/drivers/stm32_shared_io.c +2897acd81f2d1a3996adb59bd9dec1f0000f919c - optee/optee_os/core/drivers/versal_puf.c +336c2f714f6f3c8267473f821b95e998a63e3cd1 - optee/optee_os/core/drivers/versal_sha3_384.c +8ee4e7f2733f1ef421e3756f06c95acbcd347f3a - optee/optee_os/core/drivers/dra7_rng.c +06bb93003d3938898dfe3d7c010a1c6e586904b9 - optee/optee_os/core/drivers/imx_csu.c +56729058749c51344648a227f7c1d01e42fc1074 - optee/optee_os/core/drivers/sp805_wdt.c +90ef3f7cef8ca0b5ea51d6514433067919d92331 - optee/optee_os/core/drivers/versal_trng.c +04ff6a848f0dd5e16fb7fd76e95ce39785601df1 - optee/optee_os/core/drivers/mvebu_uart.c +6d0051bd667e06cafa0f116b864e5dcf5fa33e8a - optee/optee_os/core/drivers/stm32_bsec.c +1a1293e8adb1512031e4d88e30e903190c5e1313 - optee/optee_os/core/drivers/stpmic1.c +5bd6ae3906b725a1aa8d858e722579faf7b67c40 - optee/optee_os/core/drivers/stm32mp15_huk.c +09898d9b6b3ce2ff6bfaca61a6b13f0b9cd4efab - optee/optee_os/core/drivers/tzc400.c +29302475f05ea928763d589f7149ac31fb251bc6 - optee/optee_os/core/drivers/zynqmp_csu_puf.c +54a609280735c84a28f8d94cc34c03b2316634fe - optee/optee_os/core/drivers/versal_huk.c +ca1d9008dba817311983779a55983721de2934b1 - optee/optee_os/core/drivers/atmel_saic.c +2a6d458de7f3a2a8cb965dba5a4ca10f43a80590 - optee/optee_os/core/drivers/imx_ele.c +ea929d989338338849fbef43e268bf7a5cc2b79f - optee/optee_os/core/drivers/ls_sfp.c +d727565a02416f45a77d93a9d363380f5f38ad79 - optee/optee_os/core/drivers/imx_scu.c +a2703ae9f0253d154cc43d443d13e3a182189d68 - optee/optee_os/core/drivers/ls_gpio.c +0cdb9912f3a35cdd9d52951d5f489087f96d327b - optee/optee_os/core/drivers/amlogic_uart.c +285a03d5b9f6657a5a74f219b40e639aac379b41 - optee/optee_os/core/drivers/zynqmp_csu_aes.c +47509d9c897d567527308698b101326d495b6f43 - optee/optee_os/core/drivers/versal_pm.c +033052ada215ccb3f67e6643ef12c4b5665f0448 - optee/optee_os/core/drivers/atmel_shdwc_a32.S +418074ffc87f92ed37f80669e102b0253d4ee809 - optee/optee_os/core/drivers/versal_gpio.c +72c106642fd5baba523177b44cceb0e2dd268bb5 - optee/optee_os/core/drivers/zynqmp_pm.c +15006081e89bc8300728779c6253899a10614a9b - optee/optee_os/core/drivers/imx_caam.c +8d04ceb536a6bf4d80820154070d8c7c642edb42 - optee/optee_os/core/drivers/sprd_uart.c +488329789386ed718c577ec619a4315c61bfad80 - optee/optee_os/core/drivers/imx_i2c.c +52c9fd38c2174bf6f84138c477cbee17c48cbded - optee/optee_os/core/drivers/bcm_sotp.c +9a6399d3b9a2944a5cfebf5b6c67e29dc97474e5 - optee/optee_os/core/drivers/pl022_spi.c +a89150d72a6f70cd6f3b353a068286f44896bb15 - optee/optee_os/core/drivers/smccc_trng.c +948cecf6b04d477d3c372bc0c5f60955101cebdf - optee/optee_os/core/drivers/imx_snvs.c +1427572daefd0b1d7949a5bf943320c3ce4b9733 - optee/optee_os/core/drivers/imx_ocotp.c +990afc221925acee24e98912d3ed7b0ee1af523f - optee/optee_os/core/drivers/atmel_rtc.c +42b41e7d6dba7a7d9a97f8a296aa72adc0a42be5 - optee/optee_os/core/drivers/lpc_uart.c +ce40785f0b0ea3723ad09029522fe31e030e844c - optee/optee_os/core/drivers/stm32_uart.c +5b608ade5b6d8d262288fdc49165d0e0fb72f72b - optee/optee_os/core/drivers/imx_lpuart.c +b44d33205ab5012349af7f1b4b06f026b1546f32 - optee/optee_os/core/drivers/atmel_piobu.c +23eed3a3d72852b8eda78fe73dfa5b7f7e5cb44d - optee/optee_os/core/drivers/zynqmp_huk.c +5e6a71e4a41dcf21ee3c8baaff79ae2274c6c5f0 - optee/optee_os/core/drivers/atmel_trng.c +cfe1327aad5f492ff8e56e386fa5081ddf52163c - optee/optee_os/core/drivers/ls_dspi.c +c96f731961fc579a4966cae12e597d72c1ed06f3 - optee/optee_os/core/drivers/atmel_uart.c +3d3d4af031ac66f9ce00f6553ce09e3556648825 - optee/optee_os/core/drivers/atmel_shdwc.c +f709e939aa07ae260dd8d822762ef4e35442d96b - optee/optee_os/core/drivers/stm32_i2c.c +ba938d917edc42fd1e53f93a707cc9ff5ff45686 - optee/optee_os/core/drivers/scif.c +342f4d81b439bab50c12c3fb029b495683d4cae4 - optee/optee_os/core/drivers/imx_wdog.c +8c9bd89348d37d78be7efd291fc5f9279a62093d - optee/optee_os/core/drivers/cbmem_console.c +9fbe74cf959bf2b80b39c4cf5ff6d4cc0ed64759 - optee/optee_os/core/drivers/tegra_combined_uart.c +5e0cb642d735a12ab5988ae85b3a92aa9ffef6f3 - optee/optee_os/core/drivers/hi16xx_rng.c +a9e721b1faeb4865248d3c188b56278116a3185f - optee/optee_os/core/drivers/pl061_gpio.c +380dc2101277f2f474462baa5fcd9e75b84de26d - optee/optee_os/core/drivers/hfic.c +445c04d3c6c114e8ec7bc1ad63a137c0880cec74 - optee/optee_os/core/drivers/stm32_rng.c +707867f2731e424b641a7ec3409ee954fb610f37 - optee/optee_os/core/drivers/tzc380.c +9c0fffe583ce8197aac49fa87c158bec166776ec - optee/optee_os/core/drivers/stm32_tamp.c +fbee23ad24545aea0bd9fd6ae6b67e9acc2ef16f - optee/optee_os/core/drivers/scmi-msg/base.h +93be063666a6a98dd1fa8f45bba0c3ca91136171 - optee/optee_os/core/drivers/scmi-msg/voltage_domain.h +ac6217df4e25acd1b996d379ee7dc022ea03e8a8 - optee/optee_os/core/drivers/scmi-msg/shm_msg.c +1420d3d8ef64053f5b6cbf009539fd6ddddf6e95 - optee/optee_os/core/drivers/scmi-msg/common.h +6bd5b105161e0e51561bae3c976f9f6e87c4f7cb - optee/optee_os/core/drivers/scmi-msg/smt.c +b6dc570c20e25ebbb69c815e65c4e3a77f6cf00d - optee/optee_os/core/drivers/scmi-msg/reset_domain.h +a5fb58a50b0ccc0dde34d6fa91b0b03c5e0ca554 - optee/optee_os/core/drivers/scmi-msg/voltage_domain.c +189d1a32fdc699c67e4da64ae26380a2b3facd66 - optee/optee_os/core/drivers/scmi-msg/clock.h +15a98472af569d660b8ba57d3e4515f74ad49743 - optee/optee_os/core/drivers/scmi-msg/clock.c +13ed9520d3f452a3b5919a38066b702cc2f31c5b - optee/optee_os/core/drivers/scmi-msg/reset_domain.c +33be09787080f4627f5fdc10d7378880994ded05 - optee/optee_os/core/drivers/scmi-msg/entry.c +cf9d967498746a73d9d033a11d89d20a95631dc6 - optee/optee_os/core/drivers/scmi-msg/base.c +cac2399fb0ad43f3819d37590fd2003b3032c550 - optee/optee_os/core/drivers/clk/clk-stm32mp15.c +a27d2bdf0f8ea5a83d19a186c35a2a73678b4a41 - optee/optee_os/core/drivers/clk/clk_dt.c +c8f48d30481a1983d8c5991574a486ed83ebef49 - optee/optee_os/core/drivers/clk/clk-stm32-core.h +489775781cf7e044f1fcb8ae91603dbe93719b5f - optee/optee_os/core/drivers/clk/clk-stm32-core.c +d1e1be84172c7598f0ad0f44f8cf0c3098e6da2a - optee/optee_os/core/drivers/clk/clk.c +e8b58becff76b0a467f5e772157d6c0a5994b8b6 - optee/optee_os/core/drivers/clk/clk-stm32mp13.c +98169c49a2b31260fbbbbe0a0394251d9b62cc4f - optee/optee_os/core/drivers/clk/fixed_clk.c +18acdc71569e2a780d0476642f03bc85218be532 - optee/optee_os/core/drivers/clk/sam/at91_plldiv.c +530a8ac463371dd1e9b7fa1c1ca9e30c7958808b - optee/optee_os/core/drivers/clk/sam/at91_system.c +e90a1c0ffe8e8d869859768ddc4f978630f52990 - optee/optee_os/core/drivers/clk/sam/at91_pll.c +c01c18400e840f1e7f911c70a8c24034e5b1683d - optee/optee_os/core/drivers/clk/sam/at91_clk.h +83d717ffdc6556064facb9e09df34abe6ea88ad6 - optee/optee_os/core/drivers/clk/sam/at91_generated.c +9254662590d96a635dd41164bcf9c0bf2e3d37c1 - optee/optee_os/core/drivers/clk/sam/at91_pmc.h +1050ecd58ec5f9140571e29544df45407324d89c - optee/optee_os/core/drivers/clk/sam/at91_audio_pll.c +d24e2fc27571f5703eab7cd4f047097d88badd50 - optee/optee_os/core/drivers/clk/sam/at91_master.c +25e39dd6ad71ca3d8a60a03850e2cbeae18124a2 - optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c +09d3398f4208842a4fe083227c808cfc2add46b6 - optee/optee_os/core/drivers/clk/sam/at91_pmc.c +13078eaf7868f4a2a4dcd703d8eadc76630f1b3d - optee/optee_os/core/drivers/clk/sam/at91_usb.c +1cf0a55892076fb8587178bf570a91ba7a2ba82a - optee/optee_os/core/drivers/clk/sam/at91_main.c +81082b7a678856f1ac9a91da0e5a4600cfbd853f - optee/optee_os/core/drivers/clk/sam/at91_sckc.c +48f146dde6d5ca943dbc1c3d3e909da6c816cb42 - optee/optee_os/core/drivers/clk/sam/at91_peripheral.c +1ad7203186a86ea2d38ddba1ce87469d1e139a94 - optee/optee_os/core/drivers/clk/sam/at91_utmi.c +152f3551f54e3ee176d8a09bd21b8692d3d34ae0 - optee/optee_os/core/drivers/clk/sam/at91_h32mx.c +c99eceb036f865d8c6c2df48b7dd402af247fd34 - optee/optee_os/core/drivers/clk/sam/at91_programmable.c +3cc6160c3ae52400111c85d3c4ce08d787630856 - optee/optee_os/core/drivers/clk/sam/at91_i2s_mux.c +0d6b0a14fd3b05ba3c8c21eb1a895e8e3ba465e4 - optee/optee_os/core/drivers/imx/dcp/dcp.c +34825682d3731dc9ea51680257ae795e76a288f2 - optee/optee_os/core/drivers/imx/dcp/dcp_huk.c +590ea022b10a9c7283c5ffc2433de61c90148fb2 - optee/optee_os/core/drivers/imx/dcp/dcp_utils.c +2b2febd277aeda9813289b22b87000c559b8e4d8 - optee/optee_os/core/drivers/imx/dcp/include/local.h +2086f64aaa2a6e6c7903ab74de13c177b978297d - optee/optee_os/core/drivers/imx/dcp/include/dcp_utils.h +04647d26da9ca3ed1c605d85f2e47ef0622718ac - optee/optee_os/core/drivers/imx/mu/imx_mu_platform.h +b88af5fadc01a2b51585e2d02ec338e77a314d41 - optee/optee_os/core/drivers/imx/mu/imx_mu_8q.c +082b0667861563360b7c1e69c17d6e4f6721d7f7 - optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c +ff98f09ac7d7e546907420f56e3219c2ca02504f - optee/optee_os/core/drivers/imx/mu/imx_mu.c +b1b96d68d4bf3e82a538f91afea8b87b5c0f43f6 - optee/optee_os/core/drivers/rtc/rtc.c +e2ede389a1c5a24403439cd397bc8a69fc16ac0d - optee/optee_os/core/drivers/crypto/se050/session.c +3238acd7dd2e169621bbe8ab9e9f93372f6b111b - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/scp_config.c +6e42bccb8cc7140adefd2baee2a8f2b2c9757348 - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c +ad754aaaf0b0850065a9e68027ee82642a44e817 - optee/optee_os/core/drivers/crypto/se050/adaptors/utils/info.c +4732906bb4ca33cb409bd901b0c94c24a26055a4 - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_user_apis.h +215eeb31aae8342063f2c7eeded5fcb3979691da - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h +ceb2e995fdceecea2d1bb9a5610a21f958a520e2 - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_sss_apis.h +374c26b225f2311ce209fecac1317c2566d76f5b - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050.h +08160ebfd7c03896165877326736450c0d5524ae - optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_utils.h +fe046635d5ea4979e83d3bab636fa885d6ea42b8 - optee/optee_os/core/drivers/crypto/se050/adaptors/apis/user.c +938beed49b7219bc5de5f01b93c9a51b0fdb40f3 - optee/optee_os/core/drivers/crypto/se050/adaptors/apis/apdu.c +95e8665d3b38e2efdd05f50abd94fe9c48a3d2d7 - optee/optee_os/core/drivers/crypto/se050/adaptors/apis/sss.c +05b8cb927ce8c6dc6b2c3391b71366cf1b9dfc89 - optee/optee_os/core/drivers/crypto/se050/glue/user.c +75e0506e1992b38a38a83d6805b15b095924a783 - optee/optee_os/core/drivers/crypto/se050/glue/i2c.c +a73abf5d66f2a00e0357ab9c0deaddb53066be52 - optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c +64681be01124b403991ca09721e4e6c6e023b72e - optee/optee_os/core/drivers/crypto/se050/glue/i2c_imx.c +bc9e0c1bff88a8c8a8b844d676d9ac9d76658357 - optee/optee_os/core/drivers/crypto/se050/glue/include/i2c_native.h +ad85ac6e521999bc864eeb2cb25141446897db07 - optee/optee_os/core/drivers/crypto/se050/core/ecc.c +acd04d6ec81f1e8fcd19581e8e7d194f372b861d - optee/optee_os/core/drivers/crypto/se050/core/ctr.c +54cf708e2d7e054324c1de7b52356234447a555f - optee/optee_os/core/drivers/crypto/se050/core/rsa.c +ddc645a154efbbe06890e01fc9d2e8456eba3849 - optee/optee_os/core/drivers/crypto/se050/core/apdu.c +a9660506e78ca0a2ec416668e5f142dc5b0198c8 - optee/optee_os/core/drivers/crypto/se050/core/die_id.c +ee63e46c72d0cdd406a4eff3afc3de61bfc5867e - optee/optee_os/core/drivers/crypto/se050/core/scp03.c +683291b35269db2584defc67cad6d2006d59b805 - optee/optee_os/core/drivers/crypto/se050/core/rng.c +2bfc19e0e0e85d9305249130e474588e60b28f37 - optee/optee_os/core/drivers/crypto/se050/core/cipher.c +82381f16e979c73561a13cc26b1b69fcf01e470a - optee/optee_os/core/drivers/crypto/se050/core/storage.c +77ac6992ffdbc505fd3b8113c9335ea835c5f6c1 - optee/optee_os/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h +96d553c170bdeb1a217af81953ee6ccc6704d2b7 - optee/optee_os/core/drivers/crypto/stm32/authenc.c +06f4d05c0b8dff1db83d75e507975331028c073c - optee/optee_os/core/drivers/crypto/stm32/common.h +f77e2cd5cbc8e1df18178a112fe9b5d5f26d1feb - optee/optee_os/core/drivers/crypto/stm32/cipher.c +601b922f3c15a1c4d5abb05d995f5735c1e356b9 - optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.h +0ac0dd86b4ea75cbb4c4a484ef80d598a4e1c214 - optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c +7a1b972e1faf39f6c1c11e018fadf7690c0812e2 - optee/optee_os/core/drivers/crypto/versal/ecc.c +098e2cd056d7c0109c48e1c0fe7fa13577cdd79e - optee/optee_os/core/drivers/crypto/versal/authenc.c +0c3d0695339eaa6535604758e28d42e1177c52cd - optee/optee_os/core/drivers/crypto/versal/rsa.c +828360f1fe0d8cb9892dd9b467df8cf52e119eea - optee/optee_os/core/drivers/crypto/versal/ipi.c +a7d7f00d8287e6bad7ec81709ec0463d5f483dcb - optee/optee_os/core/drivers/crypto/versal/include/ipi.h +bb297b79a3f0cc6cb59b1a18f8d19242c9fc12b7 - optee/optee_os/core/drivers/crypto/crypto_api/drvcrypt.c +8ddc0db04f5251ffd3c0beb7d3947298685d5cf4 - optee/optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c +e867ba1d32e367e1e498b6fd909c71127118cb1b - optee/optee_os/core/drivers/crypto/crypto_api/hash/hash.c +5e52cbf60af910c8238cdc945b75c611ab59ad08 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_mac.h +b70e470e5e716917b0983224109234da6d526139 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.h +87afd69b37267a86f8bf7b3ddbc405754070bbd0 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h +4ce630f92142f1498cc8d9085650c1c0a691d53e - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h +622acb83b02d0d5e1f8cc107df2871c1d99220b5 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_math.h +208419d7c303ed2af4a123d73612ffc734f88acb - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_cipher.h +ccc63fa2a34f969b16948eb42489b17fba61d352 - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_hash.h +f8f01711239d5a9fc6ece9f19e40d2f805b04c3a - optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h +a6e4483d1fd80f6f7f23a89a9e1ead0fbfcf65d9 - optee/optee_os/core/drivers/crypto/crypto_api/mac/mac.c +46947c70982d23fe999c5a70666a676833b13725 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/ecc.c +7ac822e6fdd1cdb08537631b7e8a3a823a0af57e - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsa.c +28add33c1c1a025afa5b36e5712026f17bbc9906 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsamgf.c +44b952198a07c95768b173ec708d14ea89702579 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/dh.c +979dd11c468df335b342654f7263949e51d1535a - optee/optee_os/core/drivers/crypto/crypto_api/acipher/dsa.c +38819ea8744620f296d47e0b1cab78567242c9fc - optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsassa.c +d235d21c1de200d48e91b12063eb2f8f1caf0881 - optee/optee_os/core/drivers/crypto/crypto_api/acipher/local.h +3502395b082081a4c3f6e68c5f0774a90715d7bd - optee/optee_os/core/drivers/crypto/crypto_api/math/modulus.c +30d67ef67cd36d0794f2055d1705d14905f3ab0b - optee/optee_os/core/drivers/crypto/crypto_api/authenc/authenc.c +5104681db824caa455d34ffcb91e6bad1b8afad7 - optee/optee_os/core/drivers/crypto/crypto_api/oid/hash_oid.c +e1c98e3cd50456380895acb8ca60b8a7622d18e6 - optee/optee_os/core/drivers/crypto/caam/caam_jr.c +5abf9725310659d557245e78b391f46a589f065a - optee/optee_os/core/drivers/crypto/caam/caam_pwr.c +e50b088ae52c3e7016bce9511e39b1adfa3f0b4a - optee/optee_os/core/drivers/crypto/caam/caam_desc.c +d5eb08887d58acfbb2e4bcda329360d893542698 - optee/optee_os/core/drivers/crypto/caam/caam_rng.c +6c30a2cf57a18929413f7684818e9304122d6f7b - optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c +0f4455a2b7723d3cc63f4f0d0623d29b0363b39a - optee/optee_os/core/drivers/crypto/caam/utils/utils_status.c +7c483d7465e733ab3503e26d161daafaa25755be - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v2.c +a34c25f439fb74912fddf47fac4b0295ba1effa6 - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v1.c +06d77bc7f344869783912b109cd485ef4e8590ad - optee/optee_os/core/drivers/crypto/caam/utils/utils_mem.c +130800ee65979019cc2117d690340aaa75cd92a9 - optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt.c +5d02c1b842f54635bbb53a03214ed2f577c3c5fc - optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c +dc70d7f20e3b0430b6dd2fe0dd0261c929d3db6a - optee/optee_os/core/drivers/crypto/caam/utils/utils_delay.c +981c3652730c78df0fa0ab1841ce939ae699d9f9 - optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher.c +764e2643f5c29164046e1b31a10f8446246827dc - optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_mac.c +149c2203a9171fda3be98cdeace47e7be4d8c8aa - optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_xts.c +b1050722e24889ba59c987cb274897949dcd39a7 - optee/optee_os/core/drivers/crypto/caam/cipher/local.h +eb43fbde76dd94674bb94f9d314b9c0246403ac0 - optee/optee_os/core/drivers/crypto/caam/blob/caam_blob.c +59ec0c7059f65e67d8cde311155d4f1e67a49718 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_cfg.c +d375b61195f07cb019b6c1c76272b00409fd8626 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_clk.c +38aeeeb79c278658c50da69fcb72b23ff70336ae - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c +37d6f6801f8b77cfaa1e789b65d9bc5e1b44bdbe - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_jr.c +b2e468ca406a0ecd02357d0d17e4018a6c68bd49 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_ctrl.c +aa940d1d85879826ef54d8a93ceac16d8134c9f9 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h +ae43fe99412d31c2f21f732a6798cda49fa12d3d - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c +fdb4775e9056e6c476ffae9721aee7a2c72a56ce - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_jr.c +b438abbdc31d4fba647e29cb04348c3fe1a2bc5c - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_ctrl.c +0901279b007af3228bc982ccf06934c1d9fe6796 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h +044fc74646036cc6edface5539cace597bd88854 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c +56e2dab762555ca397562646cd9baed2266557c3 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c +9e09a7307c115a9661cac5d5c5a1792502220bfa - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_jr.c +75e141d842a44be2fc54fc9aa3d6233d43786cf8 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c +b9b5aa7dd5bb89200b350e92c937684405b8abe7 - optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c +e7c18e488182d4bf3c8c821885db52c980fb5f7a - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/version_regs.h +53b9f1b589e80b574aadd27d61ab737db2d5a9fd - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/rng_regs.h +5d8a12ee896ae3c8e60ef64f2bc85b31aef2d9c7 - optee/optee_os/core/drivers/crypto/caam/hal/common/registers/jr_regs.h +a8796a5f28445049f810dd2b2cf6bd4700d39090 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c +dc2680e783f647bce21513453573f8f426d9ae8d - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c +fdb4bbc22ae4a6acae04a6b7205f78f74e7847ba - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7ulp.c +08fa37b12c023eb7169ed6b3c069ecde04fb9ed1 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_jr.c +08ea1bfa1f790800d596ee9616bae2ec31390970 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_ctrl.c +fee09baaa8fd82c62ecca9d059220329bb51e466 - optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h +7bbd78ddb18f062b0ee9521f445979c6acb2ee1e - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c +a70a4c8d70b51affd3d9132d1923186a531b7f4b - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_jr.c +72df54a7f3d911d758cad690990fec5962c2ceb4 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_ctrl.c +dc66e73bb6be55941cae77b073fdaab8d4badfc5 - optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h +ad05613f64dba65f1576f358f3d0ad0182e393f3 - optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_clk.c +13a69ec0385f79f1b8ad1c9de90b79c0a2c82365 - optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_jr.c +63e5eb66976364a49eabd3680df526f36f7c51cc - optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_ctrl.c +db232940b3c2f122c53b11e6dec5e70c5ec347d8 - optee/optee_os/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h +731f10c0a7fe34860f0d1d21271b01a8a378b1a9 - optee/optee_os/core/drivers/crypto/caam/hash/caam_hash.c +d8824580f4b1889d9a23ddd2047c3b102b9e7a17 - optee/optee_os/core/drivers/crypto/caam/hash/local.h +9dec343ffefc374f9d58367446ae2c277213ddd1 - optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c +bf2aef86b551be9c94f477b1372400abf9f59015 - optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c +42cc84af73a8980ed1e51aac57b7ac2bfe8ea567 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_cfg.h +c396344d76de6f758e9164a0658037d2e37cc128 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h +d23a06ce5206f043b33f8ee8d4e6bfd62d8bb981 - optee/optee_os/core/drivers/crypto/caam/include/caam_types.h +ee68dcf290038d3ebad07beabb3517b5860bc3f5 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_delay.h +912d6553b392b20581d016f9eba91479662d6062 - optee/optee_os/core/drivers/crypto/caam/include/caam_blob.h +f60708cc4c84df857fc20cdef0710a388ecd56f8 - optee/optee_os/core/drivers/crypto/caam/include/caam_io.h +aedd672ed034e8265f35ebab812a5af4135e94d2 - optee/optee_os/core/drivers/crypto/caam/include/caam_rng.h +898dd496c1a8f25b592f261d9d13a74d3873ff7e - optee/optee_os/core/drivers/crypto/caam/include/caam_pwr.h +547857b357f6594d407d46fcab2f93fa7074d3cd - optee/optee_os/core/drivers/crypto/caam/include/caam_common.h +2ffbbb6180a3ba5fcc49f2958836e6391a2c7375 - optee/optee_os/core/drivers/crypto/caam/include/caam_hash.h +ab44fa3086f2ca8ca281d8763ba59777b975a36b - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h +7be3b8463755df707782bdaee0ed26c692c0f32b - optee/optee_os/core/drivers/crypto/caam/include/caam_jr_status.h +a7a136dc1c5717e89fecc502f4095a9779b501bd - optee/optee_os/core/drivers/crypto/caam/include/caam_trace.h +2f780d7215aa1c23b998dfe17edabba1d0f4b1f9 - optee/optee_os/core/drivers/crypto/caam/include/caam_acipher.h +7c8acb595959705bbf481d1ffcdda173637dccbf - optee/optee_os/core/drivers/crypto/caam/include/caam_mp.h +eb20c569c7f68eb8f8a1eb16eb82c24a8ac4cd9b - optee/optee_os/core/drivers/crypto/caam/include/caam_jr.h +3a804ad72278dc57b300a9df498d00db63fcefb6 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_dmaobj.h +0d6de8f72472e2554ab7666852ac52a37175465f - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_sgt.h +3cefd9acd10d65bb6c61f2e0aec31f43e48f6abb - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_mem.h +3ecf5ab643e7f3b2c6be73330969a5795d9bdc91 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h +dcc86d041d08d62d6fe7acb03e2380804af1118b - optee/optee_os/core/drivers/crypto/caam/include/caam_cipher.h +21e39b796944181921ccaee48afdda1cf8ce8f83 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_jr.h +97d9212dd201d4169891e6f997efd5f8ddc5e761 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h +74a055714e2db637adc0291d19cea1c02974e030 - optee/optee_os/core/drivers/crypto/caam/include/caam_hal_clk.h +dfa82d15074fd452691032b408318d2d1a7aec79 - optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h +631d3ce5a38c82b07ae1a14ee6b6cb5ef95d32ba - optee/optee_os/core/drivers/crypto/caam/include/caam_status.h +cfa13823918f625810c9958b6499358d179c8960 - optee/optee_os/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h +86a25c32839f837b88bfe27425e26e7e19cf539b - optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_dsa.c +cf64c3301a86696cbee97860cf765d5e34201d6b - optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c +7b9390d54de54fa7f6778b6a73a75799cb97fe1f - optee/optee_os/core/drivers/crypto/caam/acipher/caam_math.c +804d375b59635219ecb0c4299c9e76ba786aaf67 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c +237af92d1c928b929d3fa6ba1d315e2c2fcdfb99 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c +d1a64f1df7575f96b575be706a12850ac65679df - optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c +f677ba67d639efb7e1d7aebdc1a4b96eca37fa2f - optee/optee_os/core/drivers/crypto/caam/acipher/local.h +6e7f0ea0e73e8e81ba1d5d68c82bbe0ed635e645 - optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c +2702c09d55cbed00cd7326d5d6e35b12126fbe96 - optee/optee_os/core/drivers/crypto/aspeed/crypto_ast2600.c +0167f0613b4286349c7403ea6c9a7dfe0a322533 - optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.c +ecc8a0a2fa12870fc85783fb7f60d717f6bf40d5 - optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.h +86b14f8200d61eabffb946fd45954dcfac30aaa0 - optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c +6ea97a6c89fdbbb425562f878dd045fd6f626046 - optee/optee_os/core/drivers/rstctrl/rstctrl.c +399fa3fd4b68a0c3ca446add566a9e832be98b0a - optee/optee_os/core/drivers/pm/sam/at91_pm.c +92ac150fcb4f3fbb4d74e1307ae620bf0202b800 - optee/optee_os/core/drivers/pm/sam/pm_suspend.S +2932a82f88cd223444a2033a5f5062b6ebdfaaf6 - optee/optee_os/core/drivers/pm/sam/pm-defines.c +2e32e7c1e67c58880615aa62d62335f62174b937 - optee/optee_os/core/drivers/pm/sam/at91_pm.h +4af2105f9cb20e8151aae7f9f5b9343f9c80cc2e - optee/optee_os/core/drivers/pm/sam/pm_resume.S +49865544561297dc1688131470c0baaa35112a86 - optee/optee_os/core/drivers/bnxt/bnxt.c +a7009131f76447718645c703ed1373bd329a4528 - optee/optee_os/core/drivers/bnxt/bnxt_fw.c +7651789fc830ed002efb38c51f34bda32a3e8e46 - optee/optee_os/core/drivers/bnxt/bnxt_images.c +eaf0dd04206e96958dd712422ba4074ba614a6b5 - optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c +01aeb814d645694dbb3a7b6cba73a8dbdb00b2c5 - optee/optee_os/core/drivers/tegra/t234/tegra_rpmb.c +a718ebfe121008337695ef87878037c2484b3aec - optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c +d0c05c35bf7b3a14be8f22ef4a1aadbe280144bb - optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc_errno.h +8d24d3ea306d62a7b45f1c29f17840741197790d - optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h +17ddfcb103fb3b6272fb935b6ffcf6c9277d809e - optee/optee_os/core/drivers/tegra/common/tegra_driver_se.c +db6b2d8179fcbc42da79480d5ee5d0ee046b8459 - optee/optee_os/core/drivers/tegra/common/tegra_driver_rng1.c +35b07964703e174bb7f7a9f27cee4b91714cdbd5 - optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c +32ad38d98650ec84007d8cdb4403018429dc15d6 - optee/optee_os/core/drivers/tegra/common/tegra_driver_clear_keyslots.c +d4654766a46d1186e241c2e252b6d38ac9f71355 - optee/optee_os/core/drivers/tegra/common/tegra_driver_common.c +e858eda88f3475db60107c22c48bc8d6ed3a7376 - optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.c +9d22d8ce9d81f74a8b3ac51470f60e7d72cf6000 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h +423d81cfccb43c9bab466aa03a25b2c86171822b - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h +542a320020446e6712e8518616780ed091faf0de - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_rng1.h +352d6c58d195d5c44b8e06c006e713fe506dc77e - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_common.h +7def8f5aebb2ff74cb2cb235598b76028947c523 - optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h +c67e3cfb2ca9a5fa42769943cc7e64cd190651af - optee/optee_os/core/drivers/tegra/t194/tegra_se_aes.c +59b8fddcab1c4118b35c29a98d2e68efe471715a - optee/optee_os/core/drivers/tegra/t194/tegra_rpmb.c +3b96618ecaf4ddecb14a6af70d8f80d32724299d - optee/optee_os/core/drivers/tegra/t194/tegra_se_mgnt.c +953bf57f233bd74754d5258a5f6314cf7f1630c5 - optee/optee_os/core/drivers/tegra/t194/fuse.c +e09c85691a66c623638973ebd587a1986680786d - optee/optee_os/core/drivers/tegra/t194/tegra_se_rng1.c +88ee29ff327c35524c79fd85e9c71ffff90df695 - optee/optee_os/core/drivers/tegra/t194/include/tegra_se_mgnt.h +2b1700dd12edcb736b9a5686f7fc95244f99a3e3 - optee/optee_os/core/drivers/wdt/watchdog_sm.c +11ae5906c65655bea1e0310e78fe9a2cd6f87709 - optee/optee_os/core/drivers/wdt/watchdog.c +7da841080f45a989a835a1fec30f6aa50d847b10 - optee/optee_os/core/drivers/i2c/i2c.c +6487ae2b83e597215d95fe540fcc7732890e0476 - optee/optee_os/core/drivers/i2c/atmel_i2c.c +3c93fa1fbf115515f5e1313b315ae7219e5bbe3f - optee/optee_os/core/tee/tee_time_generic.c +4d1fd828c84228949b6c57be1bf8ea7308f9cd67 - optee/optee_os/core/tee/tee_svc_cryp.c +a00d48ecd6498ccba17eb691531f55e5e28eee49 - optee/optee_os/core/tee/tee_fs_rpc.c +2e7ad7afbede1e2a3987b894d9873b465df96cae - optee/optee_os/core/tee/tee_cryp_utl.c +de0fd7c15631ce6187f89853a49fb30885602259 - optee/optee_os/core/tee/entry_std.c +a1202328842c81639257318e2047a9e13b1802c0 - optee/optee_os/core/tee/uuid.c +6e9cf712089a20c55658ccfb34bce7115bdbe8f0 - optee/optee_os/core/tee/tee_svc.c +ecb2d26f414109ce193325dc9c4aa0f51e6e81a9 - optee/optee_os/core/tee/tee_nvme_rpmb_fs.c +08651bd34dfb58168c78b29130516a563e1ab641 - optee/optee_os/core/tee/tee_svc_storage.c +36310dbe4c631f1eeb23f3ff8426f6ac27c1411c - optee/optee_os/core/tee/fs_dirfile.c +3de9da311b1fe8b3b7083179e376833293549ba3 - optee/optee_os/core/tee/tee_ree_fs.c +6e4a71bdec69aaedf5d9b1ac47e4297b4818ffef - optee/optee_os/core/tee/tee_obj.c +ac18ee9e1ba6fb05ab7f2ca924c0936970c93d76 - optee/optee_os/core/tee/tee_fs_key_manager.c +cb0c0c8fbcc1c033fbb259e50dfe3965e52013cc - optee/optee_os/core/tee/tee_rpmb_fs.c +7d9ae05cceeb683b0462d33c6def015ac53f4ed0 - optee/optee_os/core/tee/fs_htree.c +fc58bf53b6b42bf286bd64683b86c6d31dc3a517 - optee/optee_os/core/tee/tee_cryp_concat_kdf.c +5922ca2dabf34fd3e6e67f6771d4c9a81cdcf5d5 - optee/optee_os/core/tee/tadb.c +4ca9c10d9b17380efab8d45d2de31948c98a16e5 - optee/optee_os/core/tee/tee_ta_enc_manager.c +7cf451d55302cfc19cc672245872a7bc06438f79 - optee/optee_os/core/tee/socket.c +3c86c49eae08e6e289fdc93ba24b2a7cb49f1b11 - optee/optee_os/core/tee/tee_pobj.c +0113d24cd422be94cfe071e76abab0409c9d69cc - optee/optee_os/core/tee/tee_supp_plugin_rpc.c +a2028063632c8857bed15d993063a7fd353ee9c0 - optee/optee_os/core/tee/tee_cryp_hkdf.c +dd81c49e2b9da8f822e7246d08cecde9f28fc2a7 - optee/optee_os/core/tee/tee_cryp_pbkdf2.c +7aeef825f355d2436dc4fd47d92ca857decaa195 - optee/optee_os/core/kernel/spin_lock_debug.c +9323261c4542f4f78ce0668852a81df361a9953e - optee/optee_os/core/kernel/initcall.c +7d0ada42e3e9e9fd9e14c60a53e62fc5c0a5a023 - optee/optee_os/core/kernel/ldelf_syscalls.c +94e2c0c379ce289434664a0320006df2fbae034b - optee/optee_os/core/kernel/msg_param.c +0a7dbadbb9b02d2767cbb75fdaaa8f36c95853a5 - optee/optee_os/core/kernel/tee_ta_manager.c +95db84ed2db1edad93dd163e910a57e8a493e1af - optee/optee_os/core/kernel/ubsan.c +ad3214582c294d2157bf0094e356be8877650aa9 - optee/optee_os/core/kernel/console.c +103d74f02824b46e307830b5f0b2a5e0685c68d6 - optee/optee_os/core/kernel/dt_driver.c +5507bde30082bac9d1a101094c3f7cde4e04e1ff - optee/optee_os/core/kernel/wait_queue.c +59ff0a3736635fe8ceca714aa629bcfc9cd518f0 - optee/optee_os/core/kernel/dt.c +1beba0db1ff1f826641fd640ce1927e68758f838 - optee/optee_os/core/kernel/early_ta.c +3fc5e9e411b1ae45c0e4cae4b8a6bb864f0af29a - optee/optee_os/core/kernel/mutex.c +e935ef062cf6f49e0a970956b28f70243e48b06d - optee/optee_os/core/kernel/trace_ext.c +1790af643118a654c31b61378ea1bf4510484835 - optee/optee_os/core/kernel/embedded_ts.c +af2e20cbb543df6547a140deb039888cf8560fe4 - optee/optee_os/core/kernel/asan.c +4be3395d930addfce9c97be3cee349556b9b9b6e - optee/optee_os/core/kernel/ree_fs_ta.c +9975d02cd73795987cd451389809dfce9a902e9b - optee/optee_os/core/kernel/user_mode_ctx.c +93b8d5e48af159d7ca5fa174b79d935f05dbaa8b - optee/optee_os/core/kernel/tee_time_ree.c +4931d22ebf9d5389b6bb8c59af1c129a4940e031 - optee/optee_os/core/kernel/interrupt.c +601f8df7890b8b38b123509a94b8f05bb40105ca - optee/optee_os/core/kernel/scall.c +02448f355229caa2a32a4411c3198eb084395320 - optee/optee_os/core/kernel/lockdep.c +3e9c3ee98dbe0f91714a5f2df5f1d5efc3e8d831 - optee/optee_os/core/kernel/notif.c +f854d339faf497fd0d027dac4594eb6c84548129 - optee/optee_os/core/kernel/user_ta.c +34c3fe34974039ae46f116dd60ce4b21a9fc901b - optee/optee_os/core/kernel/tee_time.c +7be1928ee7e34f7f47f52b99bce43e0024f06a44 - optee/optee_os/core/kernel/assert.c +907f7e88942ef24b0c59476c762dfeb7b3b2375e - optee/optee_os/core/kernel/tpm.c +221e610e4adbc3cd9e97867d9d1ae548a818fdfd - optee/optee_os/core/kernel/ts_manager.c +2a6a7890436dd84f6d5cd90ba647014156d06967 - optee/optee_os/core/kernel/thread.c +c5144935485fc83d941a9c80668ace38c73633fc - optee/optee_os/core/kernel/huk_subkey.c +f5d7654e570bb5bec7e4a93e3e08a88601cdb56c - optee/optee_os/core/kernel/user_access.c +f4b199a80f0476f43f34060f72493f81a289748e - optee/optee_os/core/kernel/otp_stubs.c +a1ef5afe68f55b5660aae6406acd31080c5af73a - optee/optee_os/core/kernel/tee_misc.c +813e8ed14c578b5b735b29cae3bbb42af9f03a58 - optee/optee_os/core/kernel/handle.c +3f891a5b83a8c9f2a82a468d79ea21efb2399b10 - optee/optee_os/core/kernel/panic.c +8abe5fcfb8a632e1c77c0e0f92bbc0414f1e2857 - optee/optee_os/core/kernel/mutex_lockdep.c +6ba41c747462a65ec025b7f099e70c4f0fb04cc1 - optee/optee_os/core/kernel/ldelf_loader.c +1962b8040874d00636c9541f532f3ee5b2ef4f16 - optee/optee_os/core/kernel/scattered_array.c +21449d26573f5cefed595f37780b901b7b937304 - optee/optee_os/core/kernel/mutex_lockdep.h +484e911f8c30e048b696a55ca84ec1b45d0a6839 - optee/optee_os/core/kernel/pseudo_ta.c +de1675480ef4043349e0bc3875749598f8092a54 - optee/optee_os/core/kernel/show_conf.c +e0f7be46eb2d862733bba0c834997c6d4203d425 - optee/optee_os/core/kernel/pm.c +54e613f652bc14d6ba8684814fe8dae398c800b9 - optee/optee_os/core/kernel/delay.c +e3cfba43bda2276f238dec15e574a1d5b70bc7e2 - optee/optee_os/core/kernel/dt_driver_test.c +309c59c03e9e9577dff0819b23e420d73280278b - optee/optee_os/core/kernel/refcount.c +c017d6ad6fee751242776e60c631fe9d1ffbb42f - optee/optee_os/core/kernel/secstor_ta.c +a45b57d0b4aadf1d209b8ab2ef53b359fef4a276 - optee/optee_os/core/include/gen-asm-defines.h +fe35bcb23450f547f7b098c1dc83a86e94884a96 - optee/optee_os/core/include/rng_support.h +5130acc35038686b8e096d0af60300156bb1fd91 - optee/optee_os/core/include/initcall.h +418f28494fe899852d688a2c61470ea0b87ea139 - optee/optee_os/core/include/console.h +0fe00321b7624b03757e3175805922dd46ccb50a - optee/optee_os/core/include/keep.h +c41e2bca18dd7445ca83d477da79e00e5b1f6046 - optee/optee_os/core/include/io.h +129133eb0ba4e4b73eaf1d84710e580b22e10009 - optee/optee_os/core/include/spi.h +76a3a307fcae8ca4315d47c57222dfdbf7db3af7 - optee/optee_os/core/include/bench.h +8caab014052baad250b6a2fdfd50f4b5b4020264 - optee/optee_os/core/include/signed_hdr.h +a368caa21683937ca27d5854e743a1d5359cd46d - optee/optee_os/core/include/ta_pub_key.h +6cd050c7ddd4d5c1022f00bf74e621a0a04818df - optee/optee_os/core/include/scattered_array.h +fa6b95e58563f8332731f989e0d1bca1fffbbac4 - optee/optee_os/core/include/optee_rpc_cmd.h +5748d7d2f9ad14c08033135fa29ea471cf6fd1e4 - optee/optee_os/core/include/gpio.h +4baa40de63545ddbcfb6dc86b9cedfcd4359a44c - optee/optee_os/core/include/optee_msg.h +c97a01f7bba80935fcbf2dafe9e946d43c247e1b - optee/optee_os/core/include/mm/sp_mem.h +30b8bfeb037aa430b36a9d62a9d906834dcf8903 - optee/optee_os/core/include/mm/fobj.h +33fa0dc8e82a82e1ef188ba26a539792cfe3767c - optee/optee_os/core/include/mm/mobj.h +985a54afd09d327768ec4d1e05e94e7bfa7355ca - optee/optee_os/core/include/mm/tee_mmu_types.h +a6c2241b6f11dd5ebe72620c9997e5783bada425 - optee/optee_os/core/include/mm/pgt_cache.h +3813eb3d7bca8b05bf4d8df687119a55c902d925 - optee/optee_os/core/include/mm/tee_mm.h +2657238352e3ca4c25aedc808f05e904ff697330 - optee/optee_os/core/include/mm/tee_pager.h +493b72f34c04bd89c57c5ead3a53240b0d6ba642 - optee/optee_os/core/include/mm/vm.h +1af89b4c6e2cc87501b23b0f12e2365c613a6996 - optee/optee_os/core/include/mm/core_memprot.h +80ac097aa1c99ae9da69fca47169085d49b572a2 - optee/optee_os/core/include/mm/core_mmu.h +3ab7ecf667fa906a144379998f686f44c83c2394 - optee/optee_os/core/include/mm/file.h +ccc329ed438598e8306a1a164a17d28a7b30ca79 - optee/optee_os/core/include/dt-bindings/clock/at91.h +c82fd3d48caa51f67f6bb71f5637c491c8869afb - optee/optee_os/core/include/dt-bindings/clock/stm32mp1-clks.h +700be76cdd56cf4beca99964e8bef7679ca119a4 - optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clksrc.h +6ee67bde9c0ae2dd9f7b6db105f90afd017ac1dc - optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h +1e7ab5294d740390ffb703e0912f612c043e1ce3 - optee/optee_os/core/include/dt-bindings/dma/at91.h +23149233a025ca8a0b84821b398694bbf0bfdf4e - optee/optee_os/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h +b07457cf8179a2129c3e2cbdf8afc8cfd94f6875 - optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h +51c769451ca1c189b2b01b45473d6fb93157a4f2 - optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h +19bb520476cff77efd84b0106f690c4dd972bd63 - optee/optee_os/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h +75e3b85cfb7663af28a4aeabd71f5d9171713d1b - optee/optee_os/core/include/dt-bindings/reset/stm32mp13-resets.h +6f7d303afc4981c5aaf8ae4eedae611976aa5b7e - optee/optee_os/core/include/dt-bindings/reset/stm32mp1-resets.h +dcd9135e8790bfdbf7e925e8e5c9d421b5e89041 - optee/optee_os/core/include/dt-bindings/pinctrl/stm32-pinfunc.h +736b382bd5ae6f63e95b0ec473a146ffe182294e - optee/optee_os/core/include/dt-bindings/gpio/atmel,piobu.h +f0ee73ec026d62a1125c4410ba4a0a72b924d09f - optee/optee_os/core/include/dt-bindings/gpio/gpio.h +8bbae85d2c9ec2416cc28a15f3d8e79d19c9847c - optee/optee_os/core/include/dt-bindings/interrupt-controller/arm-gic.h +c09a35772e7498a4ece6515946754488ec651860 - optee/optee_os/core/include/dt-bindings/interrupt-controller/irq.h +3d11a04568b27618db9569d34ed229c92f24f7cc - optee/optee_os/core/include/dt-bindings/mfd/st,stpmic1.h +dd5621d99484ecb0900f61801adab7e10d37f0f1 - optee/optee_os/core/include/dt-bindings/mfd/atmel-flexcom.h +bb5104c1046fab4b7b59c7c5a4b7bcc11bc975d1 - optee/optee_os/core/include/crypto/sm2-kdf.h +fb2b7a8d8b1e4d72673e7746b2209b7ce0705ab6 - optee/optee_os/core/include/crypto/crypto_se.h +eef0ead7045789d8587d0a0a470491a3138a9c3b - optee/optee_os/core/include/crypto/internal_aes-gcm.h +3c37642b6f4bfefdcae5a1697faef8aa2b82b756 - optee/optee_os/core/include/crypto/crypto_accel.h +a725d527edaf0a1dc858a9c5ba4740dde46a647a - optee/optee_os/core/include/crypto/crypto_impl.h +868a62eff03e1a25a10d061392adece3469e1cf5 - optee/optee_os/core/include/crypto/crypto.h +573aef790439e7f8668bf6d5be663c9504f9273a - optee/optee_os/core/include/drivers/tzc380.h +4bee46ff90df0433979e547ff28194293739570b - optee/optee_os/core/include/drivers/stih_asc.h +ba280c416a5feaf1576cfdb84a7f4c6c10f95bd1 - optee/optee_os/core/include/drivers/imx_wdog.h +631cc4ec89ffe0c7e2eb61ef0c441a265c1cff11 - optee/optee_os/core/include/drivers/versal_pm.h +209a9de5a95c149ed87d06209a00416aca6bdf59 - optee/optee_os/core/include/drivers/versal_puf.h +04f9993ffd5c2f798953978835626f7d91793c27 - optee/optee_os/core/include/drivers/zynqmp_pm.h +d9e6e80aa5d27c1fcf9c1edc4895e62394b0d4d4 - optee/optee_os/core/include/drivers/versal_nvm.h +6d429cc510e8a7657953b5312b459f26e03494d8 - optee/optee_os/core/include/drivers/imx_snvs.h +a30ec174c1201d5297ef6ee8356cea3f0fbcf512 - optee/optee_os/core/include/drivers/rstctrl.h +9c339b4eecb10745f1cd1a5edb6c60a9d5854b19 - optee/optee_os/core/include/drivers/sp805_wdt.h +cca1719ab46702da66faa45ee2e674cbf56e0936 - optee/optee_os/core/include/drivers/zynqmp_csu_puf.h +8b6ce4ad485b93603cb3a306654cd097e40508f9 - optee/optee_os/core/include/drivers/wdt.h +648ece0e1c404051cf7840a3caa294b090ac0947 - optee/optee_os/core/include/drivers/pl061_gpio.h +0eaea95f747c036c18d965a634e304c3819d6a00 - optee/optee_os/core/include/drivers/atmel_rstc.h +96e732bccb33868cd127943ce6fb12f5c9f68487 - optee/optee_os/core/include/drivers/ns16550.h +807fef6f8992f0fea2edc92c55deb829eb8e8be4 - optee/optee_os/core/include/drivers/versal_gpio.h +6267fd81bf3990311590c922d90fc4cecd83ea5b - optee/optee_os/core/include/drivers/hi16xx_uart.h +82d4883130bac9ae57b009986c8a8cf82f34f53b - optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h +90f5cecf44f1353954b9f509e72380c23dae5481 - optee/optee_os/core/include/drivers/zynqmp_csu_aes.h +3eab3b939280e8984b98283ca0325b82ae90fa88 - optee/optee_os/core/include/drivers/serial8250_uart.h +2e3c9c2926bbbc02de43b280cb53d39b021200df - optee/optee_os/core/include/drivers/clk_dt.h +0858c735ecd0b0f69511c80da83b88cb428ae108 - optee/optee_os/core/include/drivers/versal_sha3_384.h +9fecf61927af88057778f180eaa3f37588e42a69 - optee/optee_os/core/include/drivers/serial.h +a989968154cdc25bcf61e8bf07f8586a30eb61a4 - optee/optee_os/core/include/drivers/stm32_i2c.h +fae1d97a03ad4920ce240b22f5fe477866b1ce74 - optee/optee_os/core/include/drivers/stm32_uart.h +f6c06a7e3d38d67183bbde4814b1b4fc68226fda - optee/optee_os/core/include/drivers/stm32_shared_io.h +fa33f522c3cb38d765763701719a079010068a81 - optee/optee_os/core/include/drivers/atmel_uart.h +d5dfc765162bdef02e9e02dd12d30d08eeadb409 - optee/optee_os/core/include/drivers/hfic.h +d4025e0f4dc505c8928a4b46ce1d39a18d4b7786 - optee/optee_os/core/include/drivers/atmel_saic.h +21f16be3e12698442b37c7fbd4b2cf9b5e1eb2da - optee/optee_os/core/include/drivers/mvebu_uart.h +d2608b476c0a3e6772cbc28ea1b2b555091784fc - optee/optee_os/core/include/drivers/atmel_rtc.h +17e4e2d1b983087461bfcc4bbfbd70e8b3ae1dac - optee/optee_os/core/include/drivers/ls_sfp.h +850d68c54c252aaad1b085a02dd9755cdafbf8d1 - optee/optee_os/core/include/drivers/pl011.h +5a5250f891c8e3fd01fe97da71d746ab170d70f8 - optee/optee_os/core/include/drivers/zynqmp_efuse.h +f79ce31669141d007d3d46c0510c83271a074888 - optee/optee_os/core/include/drivers/zynqmp_huk.h +967a082f3664b603f92282dc6fbeab8b6b48a5fe - optee/optee_os/core/include/drivers/stm32_bsec.h +7ec39bbfed1d291fab370eb45582e3387233babd - optee/optee_os/core/include/drivers/rtc.h +f4a11c9f29e893a7d4398704cf87f9025181fafc - optee/optee_os/core/include/drivers/lpc_uart.h +d3f5bdbf1140a7acc6783fb34bf37bb7bf908822 - optee/optee_os/core/include/drivers/stm32_gpio.h +6f702cd255c663f52ccc829b19c4b0922c5a424a - optee/optee_os/core/include/drivers/scmi-msg.h +7f3ef46e25244f20b8ad05b4953dc9bdc01db532 - optee/optee_os/core/include/drivers/stm32mp13_rcc.h +ed0702ba8e49ca5d2b8fde5b754911bdd2120b71 - optee/optee_os/core/include/drivers/imx_i2c.h +c17bb19360d4833803c17e03dcbeeb35f1ea9db4 - optee/optee_os/core/include/drivers/bcm_sotp.h +d6e344ad9b81930944052a2aa7439fea4f98e7a3 - optee/optee_os/core/include/drivers/imx_sc_api.h +bc7cd62a50be3ff1fe02b16ac03930cd0dfcd250 - optee/optee_os/core/include/drivers/i2c.h +e6b7e53a5566ba0e35f80a7ef10778c3e94a322c - optee/optee_os/core/include/drivers/stm32_etzpc.h +91b6d3c752a3d89e785356b8589c47726ff68d98 - optee/optee_os/core/include/drivers/zynqmp_csudma.h +270363e25fe0225609b0ffe1465e58e30181cd29 - optee/optee_os/core/include/drivers/amlogic_uart.h +e2313ad621f3429650c5a66e403ac36467a63d00 - optee/optee_os/core/include/drivers/scif.h +85176c6d326f482d19d97007de5c3ec8d04b620b - optee/optee_os/core/include/drivers/gic.h +fdec23a82da4b29851ee791c9f774fbcd9a3ef53 - optee/optee_os/core/include/drivers/stpmic1.h +6110fa3ecbd1bb7185abcee753303ad1090d1aca - optee/optee_os/core/include/drivers/ls_i2c.h +6c1691ca8fd41135a8d571021414095918e1ddae - optee/optee_os/core/include/drivers/stpmic1_regulator.h +b0bd034bd589dd4037f5d2c08c927680967378fe - optee/optee_os/core/include/drivers/bcm_hwrng.h +03e62f840c1787e03eeef8e2651241d857e9db43 - optee/optee_os/core/include/drivers/bcm_gpio.h +58ddebbef8bd6c594d871fb476d88a5f9831153d - optee/optee_os/core/include/drivers/ls_sec_mon.h +ccf8b37d1e3c2b88218a2f4a5527a5351e578154 - optee/optee_os/core/include/drivers/stm32_iwdg.h +13f6bae233237743e412afcd68f284c9ed5dbaa0 - optee/optee_os/core/include/drivers/clk.h +15c9e1f1141527fddac70ab4b2c014fc7d6bc9fe - optee/optee_os/core/include/drivers/sprd_uart.h +0052e6343728b9d0478a53e48d52e63fdf849444 - optee/optee_os/core/include/drivers/pl022_spi.h +ffdb782c56f2fad968e061ada29b9f9fbf53b964 - optee/optee_os/core/include/drivers/caam_extension.h +5ff0b0a51178c901092daedd19fb97ba89033676 - optee/optee_os/core/include/drivers/imx_uart.h +0d14069df1c50f642343da9b04da98feaaa60fed - optee/optee_os/core/include/drivers/cbmem_console.h +aa9e92efc98f9e0aa945c7a89dbc24edeccf22a8 - optee/optee_os/core/include/drivers/cdns_uart.h +b1d5544ff4f3ab0503a7b7403cafc67a0893bc29 - optee/optee_os/core/include/drivers/tzc400.h +6afdb461835883d1f14f1359a5c3400225542c53 - optee/optee_os/core/include/drivers/ls_gpio.h +406ff8e0cfe26a1e6e63621ffa9ac1176426c376 - optee/optee_os/core/include/drivers/tegra_combined_uart.h +d23e095f310bc590363cdcd5017e718a87f5d987 - optee/optee_os/core/include/drivers/imx_ocotp.h +abea729d88bd897be58ed6c9534b6d37cf914d57 - optee/optee_os/core/include/drivers/zynqmp_csu.h +b86965bb5304387c459eeff497e0bd9b83c5ddf4 - optee/optee_os/core/include/drivers/ls_dspi.h +20aa80be5a165588b6d87d778ae56cb924f4f8dd - optee/optee_os/core/include/drivers/scmi.h +54f6572933ae458e1115bd8d43337c0955900239 - optee/optee_os/core/include/drivers/atmel_shdwc.h +bbd9f402bd751cfe638fb2585b52d940de3cd704 - optee/optee_os/core/include/drivers/stm32_tamp.h +01e3e3b8a4910f25dfdfdd865b70e885b8eb5151 - optee/optee_os/core/include/drivers/versal_mbox.h +5a4750980a258bf284a226cd8646a4d9a4f20486 - optee/optee_os/core/include/drivers/imx_mu.h +70c182404c24a9fa1b059962400b894e241bb626 - optee/optee_os/core/include/drivers/stm32mp1_rcc.h +f15cc62ed1de06587145c0fb453cb291930709a5 - optee/optee_os/core/include/drivers/bcm/bnxt.h +ab510c035d99dbaa743189d33aad9ea7118657ee - optee/optee_os/core/include/drivers/imx/dcp.h +33ea27d3d7b5742a187f56005a3c9ef39258ca2a - optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h +6d6fe341171b0aff38656211fbd1e2080b8784a0 - optee/optee_os/core/include/drivers/tegra/tegra_fuse.h +9caf071db678be64cccc5729f716abe5d1b44353 - optee/optee_os/core/include/drivers/tegra/tegra_se_kdf.h +4a198e834d4cbdca4a981db0189327d923feca02 - optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h +85b2be535e1d7a67ad7dcc13cbef547e8a1fdc22 - optee/optee_os/core/include/drivers/tegra/tegra_se_aes.h +c43a36c90b5dc3d59157a90b64bc67387c6eeb80 - optee/optee_os/core/include/drivers/tegra/tegra_se_rng.h +077a260e86e358ef193c8be4014a2e153f873680 - optee/optee_os/core/include/drivers/sam/at91_ddr.h +b08482914acc95186b72c3958214552a60f2cecf - optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h +56b607a2dea23df516e984c6fc8fcd88f15d5d40 - optee/optee_os/core/include/tee/cache.h +442eb415369cd5a3b0ce0122ade4dad47a62e645 - optee/optee_os/core/include/tee/svc_cache.h +6251efcc663e5b7b2d2e3909adaabba03fb68f05 - optee/optee_os/core/include/tee/tee_fs_key_manager.h +657ef3fdd6eee0127813cbbc0b30f96b020ddad7 - optee/optee_os/core/include/tee/fs_htree.h +ae129424808a418e6bac7c413d61d8e68b77f1a5 - optee/optee_os/core/include/tee/tee_fs_rpc.h +abea67617b2ab0ac70350ff3fe67b738eaa3645d - optee/optee_os/core/include/tee/uuid.h +261ffac302a6e4dfc609d264ab8a2f5c8f611cd6 - optee/optee_os/core/include/tee/entry_std.h +985b521fdf5c6b861009db340a64b69916629c81 - optee/optee_os/core/include/tee/tee_obj.h +9c9452532e8c96703b27a5fa32a17686296b03aa - optee/optee_os/core/include/tee/tee_cryp_utl.h +c3d0c51429849d97786fb4e47f9a1903d00f27f3 - optee/optee_os/core/include/tee/tee_ta_enc_manager.h +75b991d9820ed21b0e6aaae7716292815e436105 - optee/optee_os/core/include/tee/fs_dirfile.h +83624d48c6657bc88f152412c4b188cb45c321c4 - optee/optee_os/core/include/tee/tee_svc.h +fd483467f8bbbd73a4715c099b3cef4143fd9fa2 - optee/optee_os/core/include/tee/tee_svc_storage.h +49a43384e80403de5b68e7c51b49d0ab2cb72c20 - optee/optee_os/core/include/tee/tadb.h +4d806cb789bea5d77548fff5db9fd2efaba6e6c1 - optee/optee_os/core/include/tee/tee_cryp_concat_kdf.h +751b511848af0dffbda5a13f33e56b5edce71560 - optee/optee_os/core/include/tee/tee_cryp_pbkdf2.h +904e71454435133456b0c322cf904d5c59bdf624 - optee/optee_os/core/include/tee/tee_cryp_hkdf.h +282d054a700343402b5ffbf55003e16a0e40d567 - optee/optee_os/core/include/tee/tee_fs.h +736098ff42612ea5b4b62eb75748c077b386bad0 - optee/optee_os/core/include/tee/tee_svc_cryp.h +5d5bc9425b1ee3986b607bda1c87fe7358ac446e - optee/optee_os/core/include/tee/tee_pobj.h +13d33b2eec5bee8db2ab00fdf9d382e998437f6e - optee/optee_os/core/include/kernel/tee_common_otp.h +a3920a6899bce55bcd3fa5d64f5bb7ca1e8b76e4 - optee/optee_os/core/include/kernel/time_source.h +7de5f721ad13121bcf2d0de7f6a9ea4143dd9f86 - optee/optee_os/core/include/kernel/user_ta.h +c39885dc2548b8d6723071bcc766bb513e3ef78b - optee/optee_os/core/include/kernel/user_mode_ctx.h +079022f97400edf9b24bc33342d83d5a29904660 - optee/optee_os/core/include/kernel/pm.h +343ecd6ccd2cab4352a674c9ab3a15b1c1ba21c0 - optee/optee_os/core/include/kernel/misc.h +6a70452c8b44c8e2c5cd9b2882d9b5b2523e6d6f - optee/optee_os/core/include/kernel/ts_store.h +0e119d6c1c012d0e897cd92f4d1e69edb103d332 - optee/optee_os/core/include/kernel/trace_ta.h +c1f5708a89345bd1d1e59c0998656cb1b410984d - optee/optee_os/core/include/kernel/cache_helpers.h +f8c3e09feb3eb6829317622723491376e16ad403 - optee/optee_os/core/include/kernel/ldelf_loader.h +4b118e15613afc9762f5fffac4cf75718a1e2365 - optee/optee_os/core/include/kernel/embedded_ts.h +5981e9060b7c5809d07b6470818fbc8106b6ba1c - optee/optee_os/core/include/kernel/timer.h +03869d1183dcc5a128c46283d613b819c265b46f - optee/optee_os/core/include/kernel/user_access.h +156f0676f16613690d53954d8970a207696ad998 - optee/optee_os/core/include/kernel/boot.h +08718b75d19035055180740c78363d96b950f76f - optee/optee_os/core/include/kernel/scall.h +43d7208ecc74a9e5dae1a0f3a0952edbd3f50444 - optee/optee_os/core/include/kernel/dt_driver.h +1f01922d333b66cb291425b1df13da258ce3c63a - optee/optee_os/core/include/kernel/ldelf_syscalls.h +590c3ba3b3785bd1b70f32788080caa459b55454 - optee/optee_os/core/include/kernel/tpm.h +50ad6b5029b19a50602abf8eb47e8e9899f1c5b6 - optee/optee_os/core/include/kernel/mutex.h +ea06c194fd6a73003ffa0e05277da5d7e959ad86 - optee/optee_os/core/include/kernel/dt.h +3c866070d82642a38f13295e6f77062550edf5ad - optee/optee_os/core/include/kernel/msg_param.h +bd8e3321c7ecc34efa571fc5e86b54d71cb6528c - optee/optee_os/core/include/kernel/thread.h +ad2a242f3d2159af1fbab6dd61510bffc9c4ab5b - optee/optee_os/core/include/kernel/wait_queue.h +625040376d7bc280e4dffbe23e77e046dbf40e2d - optee/optee_os/core/include/kernel/asan.h +e4719588b0cc670eee34fbf59d8d50f39cdbdc45 - optee/optee_os/core/include/kernel/thread_private.h +20b6809c10b27e0f3f68a37fb3e63acdbb2ed77c - optee/optee_os/core/include/kernel/early_ta.h +c2ecc11bbd7e8f0f5790187e95cf6e75d3de949f - optee/optee_os/core/include/kernel/delay.h +dec752b6f205f5aaebb155fc59b0b0dfb271fb92 - optee/optee_os/core/include/kernel/ts_manager.h +008387623d8bffb1af193f51ceef6a0e1ee50d27 - optee/optee_os/core/include/kernel/huk_subkey.h +2557d4fe44597586a3ba561a107751dcc6371950 - optee/optee_os/core/include/kernel/user_mode_ctx_struct.h +7beb0d03bbf670fec4501a0f47399d2688f320ea - optee/optee_os/core/include/kernel/tee_common.h +7a061ef229094709080ea9495ad8bc590c005d4d - optee/optee_os/core/include/kernel/tee_ta_manager.h +583639447d8f7259b6621ac01705f412b6077543 - optee/optee_os/core/include/kernel/tee_misc.h +9580dfe1f16580758041e227e65811d04ca384b6 - optee/optee_os/core/include/kernel/lockdep.h +0f7eb297ee9d4dbf0e98871bec56c6dc261ba775 - optee/optee_os/core/include/kernel/abort.h +794f29e2701b79021aa45108e202b7dd5b569624 - optee/optee_os/core/include/kernel/chip_services.h +475dea2eb1f1a4e0e1d015e9237c945140be9040 - optee/optee_os/core/include/kernel/virtualization.h +c7f3799e8db3911f324d4cb4892e433edaab0059 - optee/optee_os/core/include/kernel/unwind.h +9edd15d57bd1a295e7318d5910137712e72bf085 - optee/optee_os/core/include/kernel/linker.h +4b1ffaeb0730cb0bfc64e8e63c6bf3191816c516 - optee/optee_os/core/include/kernel/rpc_io_i2c.h +67fe768ec9472c46198b28bd25d0ba5672840d37 - optee/optee_os/core/include/kernel/tee_time.h +224aab4a1ea0d969da205086d9438a0975c6c8bd - optee/optee_os/core/include/kernel/interrupt.h +42bbd277b0848f680a125342d00ce386bd6eb605 - optee/optee_os/core/include/kernel/spinlock.h +340dc639cdcc2c5510554711d03b760103b790d5 - optee/optee_os/core/include/kernel/handle.h +f2ab69b044d5bcce9b58ca8ccb79b83d50b5fb70 - optee/optee_os/core/include/kernel/notif.h +3e8149ef20283bc5089ca8714a3a698349e96d37 - optee/optee_os/core/include/kernel/pseudo_ta.h +ff1ad215df335bbc1bf5a8365c96c64746e4388d - optee/optee_os/core/include/kernel/refcount.h +843ea779e8ef15af5a338c3845356280d56bbff2 - optee/optee_os/core/include/kernel/panic.h +ed2772a8c2274cf02551a2a21cfbc33a7d81c2dd - optee/optee_os/core/lib/libfdt/fdt_rw.c +a6759c569917866b44961c88629ae4f3f07ea686 - optee/optee_os/core/lib/libfdt/README.license +966e9a4b174cc33c3ba6126614b919ca0bfd09e4 - optee/optee_os/core/lib/libfdt/fdt_overlay.c +78de4be67ce92f5b90ff1ab89c2ba46a1a34da7d - optee/optee_os/core/lib/libfdt/fdt_ro.c +5ac5dba57124ad85911a67c10cf941f08ae861bd - optee/optee_os/core/lib/libfdt/libfdt_internal.h +0da7a6ee0118d32ca78e772cbf5a81f0cd62af9a - optee/optee_os/core/lib/libfdt/fdt.c +1c8f13cf72490970da6d19a7a3d3c06f18770f07 - optee/optee_os/core/lib/libfdt/fdt_wip.c +e01b7a0052b837a4650f2c9ac75ad38c40edc583 - optee/optee_os/core/lib/libfdt/fdt_empty_tree.c +e5657b776e8466d0d7c9578591d9c2ef45ef2799 - optee/optee_os/core/lib/libfdt/fdt_strerror.c +55fc5d2ffcba07e29948822d0b12e4bf5546b8b8 - optee/optee_os/core/lib/libfdt/fdt_addresses.c +fd3af5baadbf42cca01d1a438cc826ae85a21f97 - optee/optee_os/core/lib/libfdt/fdt_sw.c +c90d25bb7b217171ad9437ee0bc8d4e0c5c7f4d3 - optee/optee_os/core/lib/libfdt/include/libfdt_env.h +7cf2619336867b335fe8f3c919607242477ccfa0 - optee/optee_os/core/lib/libfdt/include/libfdt.h +265155048eb725a03c49a45a27f322ca6f3dfe6b - optee/optee_os/core/lib/libfdt/include/fdt.h +edf93d4bfb11950ac75aade2faf0bf05d0aaff47 - optee/optee_os/core/lib/zlib/zutil.h +8770ab43c9050b824c646f6e6cee8b3c0628cbda - optee/optee_os/core/lib/zlib/inffixed.h +47e5da9b88163c7194af9b7b6a17fb46ca08b009 - optee/optee_os/core/lib/zlib/inflate.h +36c4f51e48f8320621c5739dd2ee69ef0d973a21 - optee/optee_os/core/lib/zlib/gzguts.h +00b226f75f6beab393031f6893b2868c707d0d0c - optee/optee_os/core/lib/zlib/inftrees.c +8139ab5dd86e53ccbde7ba4e78200db4cd79f9a9 - optee/optee_os/core/lib/zlib/inftrees.h +1e0b1438feffed910661d48b2b793a5f7c308f06 - optee/optee_os/core/lib/zlib/zutil.c +eb37e780cdfe0dbafb29c0fa8629125c6e19bd6a - optee/optee_os/core/lib/zlib/adler32.c +206b2054814df6c3f42f29c045d584c6a25c462f - optee/optee_os/core/lib/zlib/inflate.c +5121bcf9ae9f1eb58b39c4debbc5931e5be16434 - optee/optee_os/core/lib/zlib/inffast.c +341003df806d2bcfcbd194fc3f9da99919b918a9 - optee/optee_os/core/lib/zlib/inffast.h +4192c931405d13fabed42ec8725255502d35fbcc - optee/optee_os/core/lib/zlib/zlib.h +ce569e81ab26f5eb8d922b18be6561af7876c4e8 - optee/optee_os/core/lib/zlib/zconf.h +79b1451ee0197c749cd4f07450ed2d374f1c3cee - optee/optee_os/core/lib/scmi-server/scmi_server.c +619aa8e61beb89b2df060ca24485432e8269b5fd - optee/optee_os/core/lib/scmi-server/include/optee_scmi.h +36ca35680a4370d4f993961371d80d2e7b777458 - optee/optee_os/core/lib/libtomcrypt/acipher_helpers.h +ef50fbda210143489722c5c073b049220aee69ce - optee/optee_os/core/lib/libtomcrypt/cbc.c +2449139582c992c16e854441a9adf477c7b7cbd9 - optee/optee_os/core/lib/libtomcrypt/gcm.c +518d56bb8519843ed52fc2ba83bc4fb568576c65 - optee/optee_os/core/lib/libtomcrypt/ecc.c +a001afe7f955e43839c5e0d73be3db5db77d94d3 - optee/optee_os/core/lib/libtomcrypt/ecb.c +9197499a951acd6f4952270e28672de2d04696ca - optee/optee_os/core/lib/libtomcrypt/ctr.c +bd085d21425692efa0737d43fe957bf83da73e8c - optee/optee_os/core/lib/libtomcrypt/des2_key.h +3ff597cbe112f20a809342d56622442a8a427ef0 - optee/optee_os/core/lib/libtomcrypt/rsa.c +bc5761862d3f2bdc223bbd894e1edffc89db0614 - optee/optee_os/core/lib/libtomcrypt/aes.c +ac9a9648fe065d77e8a07c0f153c16784b90b675 - optee/optee_os/core/lib/libtomcrypt/cmac.c +a53dd03d8ef444dc1ee628dd000ca066984be89d - optee/optee_os/core/lib/libtomcrypt/sha256_accel.c +b1d9c45ed1f78bc67c1bf788fd2478f835b86f80 - optee/optee_os/core/lib/libtomcrypt/aes_accel.c +d406e89a395c613f397920c807ff31640f85073c - optee/optee_os/core/lib/libtomcrypt/x25519.c +466eb4dd083c77261b455c56dfb3036243b0992e - optee/optee_os/core/lib/libtomcrypt/sha1_accel.c +f2db1584836afadf8108bc4068ada599727f3a85 - optee/optee_os/core/lib/libtomcrypt/sm2-pke.c +2fc6c08d346f75feec7f1c1633ccf1ddc1ac7736 - optee/optee_os/core/lib/libtomcrypt/hmac.c +1f8c0a64e4cf8b1399017599666898c92a705a3f - optee/optee_os/core/lib/libtomcrypt/dh.c +181064609b067d38f551f69dcacc2d7a6ee4c249 - optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c +a2ecdde9b88869f00656b532502bf2e1c9c778bf - optee/optee_os/core/lib/libtomcrypt/shake.c +6d7a529ebaf23ae4f3fb74ea1d5774041d190880 - optee/optee_os/core/lib/libtomcrypt/dsa.c +72b382fc200ec2a39395f48c821d263bb827cd3c - optee/optee_os/core/lib/libtomcrypt/sha512_accel.c +bf7cfd733029fd500704f55382b02cd8fba1b84e - optee/optee_os/core/lib/libtomcrypt/hash.c +627ba519b1c58c51f6ba86d4c3efcf948e497db9 - optee/optee_os/core/lib/libtomcrypt/sm2-kep.c +4c84ceade0de9502fa8805960179c1dddbff19f6 - optee/optee_os/core/lib/libtomcrypt/tomcrypt.c +422469b123ee31fdd517259a2ff73fe03da28d95 - optee/optee_os/core/lib/libtomcrypt/ed25519.c +d71f169898b1d8fda6a85945b52a67c6499afaa3 - optee/optee_os/core/lib/libtomcrypt/mpi_desc.c +191319cf67c91dac0437c501694f9973ada49045 - optee/optee_os/core/lib/libtomcrypt/xts.c +f38de7925c7043b9c008b228fe88f291f90fe671 - optee/optee_os/core/lib/libtomcrypt/sha3_accel.c +99aa558ed75d6462b266bdab24faa189c03b4563 - optee/optee_os/core/lib/libtomcrypt/ccm.c +999e42770e9ee014be2004a0f9ce41d08a2002ac - optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_mp.h +5c28c3c8b5fdb83a197148d44816e8b005affa3e - optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_init.h +c991e82af32c3fd33d4ca7f63a43c46aaa3a8af5 - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd320.c +bbb1244d51ea6efa2a0d6fd5ff5d1a6b507eb3cb - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd128.c +c4e009d4708e3b97b2d83467411f582076ec374b - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha1.c +699622196fe40d368c4aa87afa335085d2d7cbd8 - optee/optee_os/core/lib/libtomcrypt/src/hashes/md2.c +a24770ddff20aa047ca6e50ed3b40f67fb229213 - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd256.c +3c19181cce8bd461cc6a736ec3f3940ec737bcdd - optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd160.c +82aa1b04a2ce5276fd516e96169dc1b0c2432bb6 - optee/optee_os/core/lib/libtomcrypt/src/hashes/md5.c +f0e38b2df179903a5c62a5d1223c27d9468f2b55 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3_test.c +f7476e6db75e35d781ab4d7ac8fbbb76133f2158 - optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c +17750b4d62fad12b1ae16ef01a8ffa2cac05fe1a - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3.c +1767c79b4e8637fd2636ed3e5d54dcd37cebae04 - optee/optee_os/core/lib/libtomcrypt/src/hashes/tiger.c +50f0d32cf7879499990c4ec792546db1e812dfaf - optee/optee_os/core/lib/libtomcrypt/src/hashes/md4.c +436cc2c14c7f7f513d234253ebce325da3441faf - optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2b.c +d4fe8714b77fd3ad07260899bc8b5307e2d44e68 - optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c +5c4268acde331fa5dfc75643f9edc2c04189e29c - optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirl.c +63de08d2a37229f4bc2e4138db49d71e7f5786d0 - optee/optee_os/core/lib/libtomcrypt/src/hashes/chc/chc.c +3b7138b66d581516a8dd7568842636ce576e8f33 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c +18123fb06342b70d7c8af10d2c72fd07b75e1d2c - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha384.c +91834258fd0a291b0c2e8b5a43b6bd8f7278bca6 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c +3d396867f33dd56b9cb7f66e66c902badeee4bfc - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha224.c +3ff874c5735dc5e5d895621a56ed2a379f35f3fa - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512.c +f25a1dad013d500b85f3eef3b3570f30a88b8937 - optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha256.c +123f4981edadc5f102d34b0ba1b5a187c185bba8 - optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_file.c +0143b2df7c00d23cf21ee3f0a263e80cfb42788e - optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c +01fc3d71a3f1525612e644839c7a707c1e5a1af5 - optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c +06ac2272160baaf80405c2bc2d9ef9a5295548b4 - optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c +b1696e891350ceb540ac60bc6d4fc5601ae109b1 - optee/optee_os/core/lib/libtomcrypt/src/prngs/chacha20.c +91b049316fd473eb33d4807d7b5aaa9a00844a82 - optee/optee_os/core/lib/libtomcrypt/src/prngs/rc4.c +9931d364f7feeae167aaad25aabc387977444f87 - optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c +94ca15102c5937a658d63a00e39be8d7ce0a25fe - optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c +e618ce5c3d8409cf47b68ba9621e64262846a123 - optee/optee_os/core/lib/libtomcrypt/src/prngs/sprng.c +65bdd642447c1d4dfc26f0f35958f0e1f9dbf51b - optee/optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c +4b6959d31d2cd9d600c17adca9edd2b7fbb70bb8 - optee/optee_os/core/lib/libtomcrypt/src/prngs/fortuna.c +0175635dc4f43317153da8fa639515156755da5c - optee/optee_os/core/lib/libtomcrypt/src/prngs/sober128.c +51e23c33fc2f379b97fdbb9128414859204e00a4 - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c +cc60780ba62cc198b8657fb2994150ebdbd9aabd - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c +15c26663221b68b94b5e2f66b93c1b4468d6b956 - optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c +43f7927b89b648f1b642bbe96a30329482a96706 - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c +e554ce2b664e1b21e037000eab5b05a464e2f913 - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c +0370402bb2b440618f27fff3e9a7d3e2219a348e - optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c +7c4f40cf2659b91a59b92ee79867fc47b44affe1 - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128tab.c +ff214c34d15c197a91a236c37775d89e959c1bec - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c +18ce9329f7f80ff15e4e96615479074600a7ec87 - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream_memory.c +d6981e9defa0ed7bd29fdde4dff9567394bf672e - optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream.c +421494432d61682c13c00cb14769af324f4694e7 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_done.c +0ecad8f59cf056ac38226599bdef384c2e52c733 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_setup.c +a1c69b888c2662b3db2c4343318cfed05ce1a262 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c +2f7b628448c81541c1e80e9cd8cd61e1489736f8 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.c +408fed5f27e4bb531ec7c18c4ea4b85e1b3e25b4 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.c +95e2d29cf4201f1cc469997b0aef539883229f02 - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c +76550dd06cbcff27a2d8ac4d8f8ef0428da2a4ba - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c +19529a1c91610536d1f56e09d8f7f0c1c44ed1fb - optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c +1e3ea925d7df004fe7994bcedc4d5e0d9551c09d - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c +d7ddc63403a0836fcb998d8a80e1d253aad3fac4 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c +51497c0e6a261a2ebe26056565149049e7154e05 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c +c086c739c64705448b06feec7107cd47dedf997e - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_memory.c +bfa49e2602c5cdee29bb880f6558844a31175fc9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_test.c +a4f8195e9e117c1053f0272b7b26bc835bdc5337 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c +5d403e317c9deb62133d017412250702a48683d9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c +b8a013b428ced9671422b507d6833d25312bd823 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.c +e8f1fb8eb2b962abfef86027594a70a50023e9d9 - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c +c1487e9b5be5b8d3a2662a6e37a477cf5c86bb8f - optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c +21ad37425084eb46c5dd6d7917ce29b0758fe98e - optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit.c +4aca9bfe042afdad9b57f2241c99597911fcb7a8 - optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit_memory.c +41b01b20223d2bb66ac8f419cf6f8435c9867f86 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c +2e8ea32ff629fd7635676de6611f85ef9285eee6 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c +f9f61c74b98bf0afefdd73ff10efad3fafc465b2 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c +cf8ba7e0b9c7428652d258729d7790277015c181 - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_start.c +ad7cdbcaef35b7db424ce95e64bf87baf2f4164a - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c +06cbb137bfc9d209674f552805083aeb3ae1516e - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c +2140195d11a6c4c204d39ed215e9600018bd23cf - optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_done.c +85a32e2be465b69f7a4132892ad684cbcd8ea293 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_test.c +3dea7eb14320987637e14b812e161c7efa873b76 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c +336fd44e027effb81725392b176eb6fe5112e371 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_done.c +769fbede217b0ef928a9b5939e849a6efd2d0e01 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_init.c +75a66324c9304c63a62bc2a97fbc8ea51df97255 - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c +a2a2185a5cbe8319ecd9e65dbb720317d63814ad - optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c +4a3b1b9453c09f7842de157e91770af0c0ed7415 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c +e6d6ea2e6d96293a8daf46f6c0748936ccc3527b - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c +747a817bfdd38ce834a9198f1e176c1fe227b3bd - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c +f07be7c3adc027be7917e3d412fe07dcd829fb1e - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c +f3d6327ce4ffdabcd4e94091f0c4d616198e8f04 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c +9e461ccf05f3b82c258302f4a3eb873038978a89 - optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c +4ec1b143f43bb9aac8d870e9bad201ea008c17c3 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c +eb172f92954aa6843672b7d7bc9707f7448bc1c4 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c +6cb5287688b6eee249f4ccc152104c13fc0579f1 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c +2301f47f63701715e30b0a1d5a7bcf2ff97644ff - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c +207351014a29ed0dce3fcaa0898b5c563262e0e1 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c +f5dfcba990f115b494ccd95e958582ca983bfb31 - optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c +3a750d0cc44888f039a609e54a400af43310abcd - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c +7d9c7698b787a53e3bd28940cdd444746994860b - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c +56f1ea6d8684edf6bbfc6e96fec03f21f3ec7879 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c +a5a54f70612eca541d03a7a560aba8cdff0b4df3 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c +d6eb82ef3d2185e358f7226af8bb34ffff297694 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c +ca7bed22fee4c69c65394f0811f17e8a4a3b3ea9 - optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c +2997b2353ddb192f89b3ec278ad91cdc8d7f2b62 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c +ee5c9c1fd94d09694078522a5a470058f1aa78ea - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c +c9abd410a11d44eb94910ab6d95bafc4e75fcbe7 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c +0303400a05e16078ca1944029c36280472d79869 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c +cf2740b0fb974b94f1cc08890920c5e95f703310 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c +265e8429da2df62461fd0b313a0120c58034bd0b - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c +b03f3351e97f9628fb7921eda85ae3f0b0534156 - optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c +6186f3e377626cce35518099044023ede1954ee7 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c +7cbf93842dddca33e61a035f80d15e15d1e0c609 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c +89d10d95e8d542d75a69d8f580d6ba6448096006 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c +ad10e437f618657cf5b5e3ffc20fb6c5219a6db8 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c +6343e513ad46501c7b3c7dc039c8b246ea927590 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c +89b75f314fad2f247f3c02a8d043c69822182beb - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c +6166a8f10c3d96dd48d974f0c420288c79faaeed - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c +3e8b2b92ce4faeef2ac7282bb0e58253ed01bc41 - optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c +2f93fc0a9e1afdf93c263f75675e15d9aae63cf6 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c +4a0d52f29c5da69ba1248de543b53f80f00f0358 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c +a1361518be72e5f0a2c22cf2e99afc5155c64421 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c +a0941ac3c7a39107c7f3049a9ce6b7cc3d120c58 - optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c +7b1c5747593a58fdf9669888bd86df7718579054 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c +cf505805e8a15d2a7e342491371d6f38a799f8e3 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c +f162118759bca19c0f87c3807df85b6373ae5644 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c +d071d7e805d688ccaaf2b3f8c3b7bc5d68bbba1e - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c +60ead8187339abc082c6fb5cfa8ca4a07d5bd3d1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c +3f6fff56e90836bbb49e7e0f2ea08ef20a25dcc7 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c +792b2c41264e5daf5d14ec67d327f8bfd079d994 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c +38d9de8caef78490c170d9f138c49db6374e6a02 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c +9dd030615b3a2c6b70c7e24dc125673f88550909 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c +6799d4d2d91f4e12e8d866fd920ae847eb66d5e6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c +19aceaaa2254b78b3210d81efdb82d2909a5edbe - optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c +650667de1f0e3d2308872cf4537ae49498239261 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c +9b663e83c3004ebe1725ad851bde5f946c0e6150 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c +4dd6870aa2c7606e90a94d802fa383dd8515b825 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c +487cb958837ebcf06f92ef604fb17b4a495bbd64 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c +7d45e3754a326d8386f2e536d6baa81554378581 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c +7c091098e78cd1fb572b8b2e843ac04d30099719 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c +ce658863c830e150ad4cc3c3bf741b91dfa68c6c - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c +5f19a3d36e36aa4d6fd83ace3219f06916e307a9 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_done.c +946301da12005f65f7f0a5d5cd79114186db81e7 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_init.c +df0f2138b4cb5a037739e226490a0d08bd268048 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c +5de251abffe4c5d5eea6c9deb2b5a3dd7c128147 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c +d3aff516bc303de0bedf794c42305bb770b41629 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c +5fd053c692f154fa517d1a66afac3bf88a666dc1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c +83f9d3b22b6bd8960fde8524bcd094d2fd1bad6b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c +4c0669699a2b11b52aacda4fd2c617d5695da4c1 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c +069dc6544fea4923f5ffc9ed6cb508d1e3be4b16 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c +fb2baeda2808e719b2543a5bf4e92e86c5a8475f - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c +87188dae93ef2263dd1baa4207faf5551bf57bff - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c +93e89b145ff46fcae1c653ee70c2061ac539e737 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c +16d4c4b33c5e68749766312b86e074433514c453 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c +af7e5ec699439a45de3f29a72e6779709ebce7ac - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c +727b4d190bb993d395c276fdc4b6772e7507af6f - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c +9874e24493855b4ccab70b0ff538125c23e3515b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c +a1a4e685352d4984fd5d49522bcd50c4492ea66c - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c +2d89b89d0738d4db5b761d40f9cd02510f413933 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c +0af7bc735a8720e5b936a261204b1aa73a0943f5 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c +5cc80740578579a16d394fdd144d7d71daabfa35 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c +559a51a7d6a1d21918f5908f788bb294acf88bee - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c +00df47ac677f1c073e872b02d89d034defae3198 - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c +9de6e2171df8c3c6a974888bfde2f9333e56e12a - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c +55555aa0f46d7b4575242255f0729e9da8593aff - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c +268ca7b0eb4a15158fd3f58ae75ddaa90a8f7eaa - optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c +3199f0f705460b9182e1e9b543e800f7d26b305b - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c +cf42e3ab0129e2962618a2b9b261e9ea20e0bcf2 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c +8f82752538241e4f3c3f48ccdb5bf6fd41d7e889 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c +f60e6c18f07779e8b066581926c51522a92069d6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_done.c +782a71b6b10b0305491529ce9963ace0c26a38f6 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_test.c +c5f08bda970ba7d30ff7bee44fda96f5e6515caf - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_init.c +633dfd755ba58507be81b2d70c2d483d28ca9597 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c +30473a74f19214129f69b8b067d6d2d5a87a7364 - optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c +f8f818328098018b9bc6836915dbfc34bafbf574 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.c +d4dca139aea0166092d5665e29064ddda8901842 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_process.c +a91a5e3eaa7bcde10bc135c0f63feaf78724d5ca - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c +9eb480ccdf51a957a9391e17f2740e53048dd90a - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c +e045e646861478e232fea83658bd42d37547f4fb - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.c +62851dedaffe4829a9e1d62149db76a1986abd9b - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c +f8665c5b620a773ad0a216d19c5abc141e016573 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_init.c +9a94ec21fc09797428df52cdd5e9fd31d0692885 - optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c +ff2dcdde770c5904024d8bd59763632a301e9790 - optee/optee_os/core/lib/libtomcrypt/src/misc/burn_stack.c +746776871c1d225104237b1021e530a23d5c1fd0 - optee/optee_os/core/lib/libtomcrypt/src/misc/compare_testvector.c +ad0c66e6a4431f567b49915d01f026888538f63e - optee/optee_os/core/lib/libtomcrypt/src/misc/error_to_string.c +6adfd2c5e4b416a65be0e9e7d0b6a24c1a3589d1 - optee/optee_os/core/lib/libtomcrypt/src/misc/adler32.c +5c187006ec54c463347d528d5671b8e92f9b762b - optee/optee_os/core/lib/libtomcrypt/src/misc/copy_or_zeromem.c +f4059601bb534681d08bbf29b543f5bc37d29267 - optee/optee_os/core/lib/libtomcrypt/src/misc/zeromem.c +90dd180fc585755ec6db549d5d69653fe83ed6ab - optee/optee_os/core/lib/libtomcrypt/src/misc/mem_neq.c +c129c049a7b7b18cdb44284f93430835d0001761 - optee/optee_os/core/lib/libtomcrypt/src/misc/crc32.c +4b83b978826b5dc7e68898bde8d396e51a73583e - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c +c2fe66c77a5e4ba8a09979753ec8fa3b1c9530ae - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c +d0feb5c364be991806af64380cd3a6e5d7062ab3 - optee/optee_os/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c +1d1ff4347844de6a3d1d111125194a55c55cf30e - optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_pad.c +3c3c7ed1c6223f40663fab3cc95afff608de638c - optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_depad.c +e0622cab6f654c9d78768c0037a71e91c7c904d8 - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes2.c +5e2328959d1d9fa3dfe651bc8390f56e97cfeeb9 - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes.c +8ea5fa890004eae1957192d67e017a2f68ad820f - optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes1.c +779555900035522f3dacfa9d8dcb18c310e78d2e - optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf.c +78d7c916e74e8dba0076ccd8a784ef784d2a3473 - optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf_test.c +abb752921991a5264ecf76f92d09589c9477d1d6 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c +63d0675dee46f130dd505b9ef11305f66b51d5ef - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c +81f55ffa10b11eb901eb4a3e44acce81c2582f84 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c +a98c18ecdba584f662232ca582bb88b502daee55 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c +d92b5cc31e60e6581ee77b6e9780353b967e8321 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt.c +0090a8c4b12094134c7e3fcdd6c82cd26327c271 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c +233015470408b5b2e38773c5b1127762f545a856 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c +5c81f4d8d18f6544665cf9385fabb100324f2323 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c +96342e249d7c747d11849bf1a4a2cfa99139134f - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c +c261fdd28c1198d33aeccd35a7728d324671e3b1 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c +dd27864633e7f1746e256cc07e47437bbbb4bc97 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c +1221efc9a518048e34fe881a93fe5c765524f34e - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c +26a169c33ea38516c1421f536f7bbeeb2983f01c - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c +c22b0f36bb603c5a4cc0e043d1fc84ed5615c82a - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c +6809767adc93fcb15bd91fdd9e99a6264937a6ef - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c +18b723be741bf36e94966af24f7f0da9fa256f26 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c +23eb56683e5cb3b2a6203532f2261e1146584ee2 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c +9e47537140b5988fba0847120d3e311f83085ac8 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c +34b218af0b0d226b125bb51da3c2016bcde2eb62 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c +70ff3cb0ee05909a347b56392e40b79171d1d3ce - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c +07ad1815506e2a82911ec0c3fbb9dbe66466efde - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c +f1821b4e1d8e159fc9eebb3c49abfe0f6eef8da9 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c +d15ddf5b26ce2f13c726a540479ac62355bc4ab3 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c +80d8a64decdaeb241abf260380e42f406eb7e132 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c +d4220e04397554fa19428f3ff33ebc5b80d93d7d - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c +28e1308aa1d2f79105cf6aedb36a9ea1664e3567 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c +082f0d654b13f0b93cbe1d28f01726941f0bac78 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c +994a86f2bda5d048c5755b0e7819184195f24ce9 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c +474440e2037216fed3c26f124fd92a96e2bf51d8 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c +209b907a121df459daa08c8ab473adaedc01f56b - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c +20925129239360b39ed195a0d8b6b99d59b890f2 - optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c +4a0a598b182902b1813bb584ef6dd3ae446d0c70 - optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c +6b7496efa00caecdbe62a0a85ac0ac8b7a637d57 - optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c +1a73cc544c8c9a3bb0d77497a5a92900c5acef58 - optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_encode.c +e6d0978d88f10edcb4164e550bac09364d5a72e2 - optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_decode.c +2e8f9163643ed6d0b41b646077f77fa7c179ffcc - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c +4f6812ba75aa737fd7f24b4148cdf1b3a99e59e4 - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c +11a7db8b0e76dc35b70e854992156d2f75f98688 - optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c +f5d1d5c1f347ba72d7eecf6995812bd9b0443efc - optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_decode.c +c2fa3c8655b71dc36a48c5aa409c9ed586f9c8d0 - optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_encode.c +b4f980accf155a8df885c69266a8b2154992181a - optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_decode.c +eb9ee827d87cbf5ee6013ea99a318a0e5c477a57 - optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_encode.c +9d2d04084cdc6c4c56cec3479af1ccb74619fe42 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc5.c +819970a30ad279c10add699d9bb08c1023039bbc - optee/optee_os/core/lib/libtomcrypt/src/ciphers/anubis.c +60505e6a888a893c8edf9d6065362453230d0d78 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/des.c +9748ebff9d560f59b42bb6c8c1dedc71dccbc225 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc2.c +02474538dadafba33694c8ecab5fc2e6d00a7281 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/khazad.c +06e4fcdd40cc84f756e818ffb70a63da8066c7a1 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/kasumi.c +b0f8a843a280133fbab3d261ce7a7486c5f20bb2 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/cast5.c +48cdd948011ecd3e9298f56dce531d60ede7608d - optee/optee_os/core/lib/libtomcrypt/src/ciphers/idea.c +398a2df01e72511a00c4fd56ef10ba61c9e08ae4 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/kseed.c +e28e47ef72883f05ef629df3d495fddfda0372f9 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/skipjack.c +cfc7412e0fbe23e14536db6836f3da2102c02e06 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/xtea.c +c870397dc946312c9c0304e8f132b1fe87eb18c3 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/tea.c +461cbf82c045454db297fe16c3c478c4cde8fadd - optee/optee_os/core/lib/libtomcrypt/src/ciphers/noekeon.c +840013cf542fd64a45cdea8afb965f8aa0e51df8 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/multi2.c +4e35739fffcd60f1f9971113810a08c7c7fb114e - optee/optee_os/core/lib/libtomcrypt/src/ciphers/camellia.c +0e87ea79442a67dec4fad902f2df7a827f1c233f - optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc6.c +783f175a7e6e630e954aa409e43cc67a854e2921 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/blowfish.c +d48e4087de75284fb9aa215069515ac90849dd5f - optee/optee_os/core/lib/libtomcrypt/src/ciphers/serpent.c +4d6e2810b820eb2b29529f2bb429d35841b3bdd5 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes.c +48a4a60cd68d5143a1998139b830ee8fa7e56faf - optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c +f7eb0744775bb897d006417c91c5f5b4aac5dd92 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer.c +31702a5acb225e761e0a4cd0e4b4e0e31c5206e3 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer_tab.c +5f2865f98ba1100f2d497f84b78a20571393885b - optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/saferp.c +b6e57c2661c58975ca885c612932e68bfeb45d9e - optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c +4a6bb1fb9b2eed818cf6aebf8d6fc78f108db521 - optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c +49b2782b96dbf7d798398be0b39ba922e5a21bf1 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_math.h +4cdf5186a0f57233bdeac68a7db9e2e488806fd7 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h +ed9c10d0285b377accb1e2494f6286e154bed777 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h +23b6ced88dc0c3124f432f3017aba8b385df4866 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h +6e3431e86381584751e3fe17d1f783454fad2f52 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h +6603ac9ecc182ac6407d2a5bdd90f3baa4552f58 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_private.h +4e5b33b2454acbfaa9b2ab42a0a03fcabc598d30 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt.h +44976f48c4f37ff61e8b03ca839b1a65f273117f - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h +47a31bfd38f96720df80f298c98d96cb435b3ad3 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h +660c8803aeecea2223f2075be243bfdf24187599 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h +2e713c6c463faaebb4e01472732e51d74aa5b185 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h +941fea915f92af82307b36234f5ce179c0fd3025 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h +d86162251e3b48c30f090b3d893a17106c1b59d3 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h +b024a3e54d8b78ef88bc56740995d089836bfc81 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h +c4d8079f35569279e5f30da5d4666d1a145c29e1 - optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h +406b6b0422373c9c2a3c3f85df960bd5fd4134d8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c +131a94c18f4c6d67111f71772ce64e30b214b7c6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c +bbaf6a67e160f4064a99efb50a56e264bcd9722d - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c +344a33caba6182cfa38c93b69be392fdb85ac4c9 - optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c +7e7beaf2f29e72101e3ff7ff9cde8d32af8b6305 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c +9765d9c7ad353767665e26aa27114aed5064b9d5 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c +f97b4369ca4a6cee89a277cd05e60345fcc88377 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c +7a444c752e2d4df2d1384ce8f9a56dff42a02347 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c +357e06818540426a6b09b30b6265482454ba9342 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c +2d5bca5df73d8684673df1d6ab38bae6f25cd304 - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c +7bb1feddfc1ba6fcb69cb4ef537c5a0dfafb8d1e - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c +f804f75c30cacbad97b14cac9f9603f27f4ee67f - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c +fa6b0f40cef3e152cec36c4ccd8d895e10dc60ca - optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c +67055fc35186b6aa83df93e46da7bcbbe92b1f5c - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_set.c +41df11b40913dcd9ec153132f10f527896611190 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c +94fb2295b17b0d88234119fb717d678ec352c9d1 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_get_size.c +47347830be6ee382ced26f00e0be055570804c49 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c +9a424e42fb17d230990378f002faa44cd171738f - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c +87a49a80c12d41e8594da7524050eba34e5f96f0 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c +9f43d136949b104d186b32b4e272ab71212d140b - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c +a47196953806fe0b060f66e17a9f5c26db46a788 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c +38f5811d94e0c86e4215591ed40917dbde19a7f8 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c +01b964e18bfa23b2d17ae36580bb114f096fb07c - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c +979846f85b72946ff810edf5eafeca166d4283fd - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c +9701778bd557f9eb30009b82a995c5e31167eff1 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c +071f6f93d133ca61acdffd03ca03180bd812032b - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c +32efc4a6c51bd46b2e5123cff17d55cc8560d582 - optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c +3c7f07f8405b9f895d89a3ea2090632df8c19cc8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c +e428a8a7e8121639e668ea708f09f5a768e4d12e - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c +26547d5e1492512ed28376c853daeed24108f559 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c +7fa48553c905b29d4a54176091d6fce2114399d4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_verify.c +3e1ac45da9df45134fb091ec1709d5464f79d2ef - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_sign.c +bca50dcf7601a449f350e48f0db458f6e0377f15 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c +8d59b1b306078e34f08e267a5aa226debdf7551d - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c +d06add7d54e686364cb1d56bc5c23a69c71597c3 - optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.c +82232e2e87681ab9ba1ecb3a51e964671eeb710a - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_make_key.c +d32c3211c9738e6edeec863035ebddca34d496fe - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_check_pubkey.c +952b34bccc6c1b05ad9de3bcddb1cca3b46b4e58 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c +ec26e921ae1e3e3d36d45dc1e9485f2ce7793529 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set.c +e304ed0a492309f8b0055a4e147f87970fdf38bc - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export.c +fb90bf4aa59ee4d6f4371b1ed062a7efdf83462e - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c +3f0628db016f76777bae6ec89728511a7cb6cfa5 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh.c +9c29bb5f9a40d49dc22a8b7c3f62c2fb6930eec9 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_shared_secret.c +2517e59c7961fc7b73ed472569df670355137213 - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export_key.c +af78940c2ff22884837509d7ba94f767ac3af81e - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_import.c +a1886213cc203cfe7e6ef49271838e7d967f53bd - optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_free.c +3b82a4885c17b3d11eae9d1f870da34e6cae9f0f - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c +4b2dbab5e2aa90bd324218ea5674fef8777f8473 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c +fa3c683b57ff8087a2fd90fb5c6accf72d63ffd8 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c +272952cb667172cf8fba5e852b5b8147d03f3534 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c +f547d958caecd824b0b17b1355530bcc788c20ca - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c +a55666907f63f401c00cfa793eac033bc2226339 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c +5dc0463320e60a8062e4bb3b76301bfbb72227a5 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c +0803f50e230a9797701852fd02cdc9821544fa74 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c +b2e238370d7a369638a2b76d7c64b726f3eb53eb - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c +2893671ff36eba57509da1721ac9e5cf8567b6db - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c +b6d3f3a6c24debd170f1ec62a74d682113250cff - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c +b0a3bbbaf6fb172cc402a25cfd4114abb554850c - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c +bb5f98cabbead6be93d785dcc286f45498d5c0c9 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c +7da5513cb4e6ebca0d19c35d74509deb172ebac6 - optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c +0287f0fa69106c0067f42dcf123ce01e29d98031 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c +42aa854ffcb3552db4fb57796569ea830db3d9e1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c +6b5a515a99122e80c6c6b9aa06a86e21ee73b3fa - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c +bc4963f87689adb59ace0786a7b43d6a677b8512 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c +280c3e6ecb5e86ef00f694afb173a251ce58babc - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c +cf05860092837c42f574e893b097a13b3374da04 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c +a5205a7b0f315b2ebe0a2ced975772f8a1057571 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c +b482130a4f79e28597bcb38ab42cff07c19787a6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c +8149696ce9b92edc4b72e701857542c66a19265d - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc.c +5b57ce74997f89ba8f1107d442aca33bb2dc01e4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c +4703d1e4bec1f70e5e1b17f15db6ee3a4046b47c - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c +b1285aa85f707bd46b815f2a877d32bd8573987d - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c +1303993f215f0d4001ad7ac1dac13696058b33aa - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c +fe473b8190607030112719eb24493f1941c3e619 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export_openssl.c +1860b05d1e6d84e49e6bde6665be70d81cc9c8a1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c +450bf440ad3be5053c0d9c6d7926d5cdcd9714be - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c +bf20409e528c89116d228521a61e12ec29b6b8e5 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c +b51764d8bd42b7561f41b8a977e021f720d461f6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c +c5c1644f8bcfb94a1e9dc96faf3657ba2ebb4266 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c +b818e0a65fbcb65e56211555e7979eb98ece81a0 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c +1931064b040780af5b1dfe453878c4cffbec7c7d - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c +c3b19e86b94901366e718206c46cd3cc4432b417 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c +c8932926feb1db7458a4121747277fbf302deca4 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c +966e686fb8e1225167a2e3a7c6df50b0540fa9c6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c +f03fb73a557258c6ea41d3193cd6bd750a62245e - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c +257ac82c33135561dfe7b5c7edecb5a2d0cdf7e1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c +1fb03ce919d517f2cdd83c378d731a39ff656df8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c +450616e20f9d56c11a1adb892a3645a93741b105 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c +015e8b1e8df2b67df5666581c49ed3b443a17ebd - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c +3e64593819f63544e4b0a5e7d7aca57eb34eade6 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c +fbe398aee3a10e7dcb094e86282410752aa1a8b7 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c +1c00b1e26aaf1253c27c4f23b98535e45a041610 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c +4204640f642d5ddb2df36d5eb318b13aed778172 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c +d8f5cf749289d6a9c685c94b34909b764e1d7689 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c +96db40ce102160544ab24dfd2a14926461815e18 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c +f527339cc3a30c2b3135771f132f79c94331a0d8 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c +df15dd31ef7691042508e5eb5a7963483113cfc1 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c +1a11b95c51b4280fc073baaebd5f749bf0b623c0 - optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c +8c6f5460141c1ee2b6fe1887243f5ee6ab21da0e - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c +a9ba477ca5b2713fbf6217fa2b25888a448773dc - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_shared_secret.c +cbc194b08bb465a7b3cea249824712fda8857789 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c +9e8045a9b7b85a4fd345a8606dda5a4529102a84 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c +812929f4e13a575e58aeceea8cd3c5db95ab2189 - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_export.c +0672fb6756a04c5eec2b963d2b2e9798f5d94c5b - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_make_key.c +f2e15ff205094f5a30ffd289282806adf3bfa02c - optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.c +ea6f9fec8d29d2a40e34eca954bf19601646c1fb - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c +aafed90e2fb679630e5f4234ead1dbcc220b5ca8 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c +c9b6246d4dfd821f49c4cfb15b0b6bc3414d69bd - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c +ad22ad01c3f0cfb81fcc6eb155f0e48df5223102 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c +bdfcc0fc58006df5d8906f179fb339eeece8a99d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c +cdc82def06cef9eb373fb549f277544af32d2d40 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c +ca628b8ab6300f40be2d696eb9c06cec680f4e87 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c +1292bcd4021db8959c6d5042550705be1b170daf - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c +28a82e82ca20ba6d4ef0d5d0da2afd9994aea550 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c +3fc70309a59d43216aa49ab5477df50823a97232 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c +ddc24ebe07f30aff933f0dcacceca877f7a8c912 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c +3ca43288d74863f2acf8e0553554f4110d572e56 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c +c66a829d9f1a1a0e936357a82b563385c99b38f3 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c +3547f3191ec66412dcb8347be374eca128c03c11 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c +16be383d4118fcac43cee6cf8550a7b4027ace1e - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c +aedf07da8f7d1b98991abe3e3e74d0760c207630 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c +c5977a968d09b999595cf145d3429a62599ca661 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c +36b1d4df09d77914a9621e323848927e19b9e482 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c +ca146db1227ca30261685565e96aad77b75b5577 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c +a7b792db24f08ecaf3dc061773572acce6754633 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c +e597c83e6003b94ef2d3664d81d39ef668416724 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c +6dc60f80f7af76c0a1b5992f03ddea0435b439ec - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c +cdbe2378f68d5da22b7a94428334cb11343dd5ff - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c +8eedec47a421b47090137b1e2da8eb203fdef911 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c +8412b0b3c04480ca5f376fefe953156f97d32d51 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c +769cca541575ba36865f25e1673640cad524581b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c +8a688cc8917314414fb10e6bf7557ac9b22f42d6 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c +24de714f216931c3f599fc8d1e2deb86c21b847d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c +2da5ad73ec9c0ef261a7a06266369434fbeddc4f - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c +9a3485d1bfab9d30eaf363de36eddaec1464396b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c +291e2e946e23e0e29c802af28ecfb68aa74a3179 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c +df1aa22c0a11a444fa3e307b084eb35b6d651a88 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c +f65972e7e1e35ea9bf3c750f6d2fbd3c22de8df1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c +b85ec531d4f44b87eb3be27290a2aaddc246d62b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c +2c41e8e870f523500c8fb60f9d88b90dd079c9ab - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c +715c09b19bbef0a9d89511be2ba47db3eb184457 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c +b64eaf809c7884f4963eabf55cbae2037d4aeb1f - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c +424afeec6f07fd7906055c91c9951d455c69033c - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c +f3830f9b7b3e4c414480974538e07a107e11eb09 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c +6040a83b18f15c48008263edc7586ab2682a2650 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c +e45dcd69212ceaa620d3a68584c8cc3d8d7d7abc - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c +2e24598b6fabfaad933446c87bd5a064a275e144 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c +d82b04231f128724960a64f0099c8af38548d2d7 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c +61c080828e48973c7e450aca6d6e998b893001fa - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c +7a3773c30383a7999306b37627b17630b85eddf1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c +5ae066c005e04dc7f013a783713675e77547f565 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c +e9d1241660244c310419ea1378b9ae323a7ac61d - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c +18ca4c581baeb6b0fc04572980c8ff2c540588f1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c +6d28b44c01e719209cf6726c110c6b0601e3ba50 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c +9d6bf8a3d490c881c022ec153b9dfd96d4798be1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c +13994ec081d65c83c2a411ecce60211f79aa7f8a - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c +5c2277093dc1c4f2d6b877f924200805c950e697 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c +4ab4dd3b5bbbb87afcfc52966eb024bb4d0c8234 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c +e50711035dcfcaa4d0c1fc32f433be0aa8d98689 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c +52132cd7a799e297b872a524bda661601b33e5a3 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c +be4a439c97860d7aaf286c7ff16597491596101f - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c +3ed9c426a6a4649858e87dfe5a61277fc5aab712 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c +f387f820036c9bddff6210310aafe78d14e6c4f6 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c +5cff49720c80fe773da512a51dbaaac7ef7a8eb8 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c +0fcf9b8d13534b36c44fbab36118578551653494 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c +2e7715416f0b9b81765354e9b71ac389bc674bdb - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c +fde5cba0f1fbdcfa0af606a17b90c2ece77fdfee - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c +efb086030db7d8223ec9f72497920413fe5b9cb1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c +d6404b3d1b805e9236eb4d91f784191692cb4f3b - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c +65c73948627beeb228b285cceb082340770d5dd1 - optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c +daee17f76d3539a02d8567dc943b2b3217098786 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_file.c +7314b670b2c1a382ba1017ccd3b3806fe451aad6 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c +5e2fa3a8a8b8c0d38d74aa0bab4d4cc206166453 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory.c +2588957db97d4b727a20206702de592edae7afb9 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_init.c +3657dea6098b394ec68f7c996eb8c2525646dafb - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_done.c +a081274e2f9dcc2ed96ec2a4db00ededed0ec9e8 - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_test.c +5a792633cf4c62bb31894bcce5bb07e78763b88e - optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_process.c +7ec5d863f61666d818632fd057c4fe9bc1a879f0 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_done.c +de921bd15503ba513e2979be7113493b8c679ac9 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_init.c +78be422e4801b343c32f4a4574075488109af2e0 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c +8fa264dc57c925de0f8f36ad8848c8b278694d5a - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_test.c +683da90e66dec7dfc447bac38e35dbee802d3b57 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_file.c +5c61eca352761007c4111cf83cabf66f712cb67c - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_process.c +9b028196ee6d1b9299d41bc2c6d66cacd1011ed3 - optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory.c +fd77eaabb5a5ffddd12e2f91920bd8e657aaff2f - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c +21ade96dad372a77d13f421cc9c1f8d2290e239c - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c +74a84dcfca09518e42ab725a717c8aedc0fb9f84 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c +1336042d04c7dd5b0ee965be9d037bf654049339 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c +0e00b9ac2e143fc27c3122a3f3d9bc87d8282076 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c +539c06612340597abac186f272ceeec032082a08 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c +eb8f24748a3fbff1fabe0be3ce91f76ace71528b - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c +0371334e645562a86984c83f6257967f26cf1464 - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c +4a8d8ec6fb7faf70d806473ae0d8a3d1c9d3cc5d - optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c +86f1332253c798f3fdfa01762ed1c64949a69794 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.c +6f1f256d9e8a6ee6660406b43866a0dd79fbd255 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c +31e9ff14eef67741c7e79e9b1a4e478222f794b9 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_file.c +f9cbe3b6dd912225eefc54f7dee30754e366cf62 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305.c +5300bb1eab429d1a602a848c46b9dbed916d1860 - optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory.c +224913f37550084d0b6a11c46a674e2560b9f6de - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c +9bccb9e3b0ce1b901cd5e52d30d7b54b1e8c5674 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c +c2f957e54093361abef389519c1a79136dfb5124 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c +278c6feea087176001778da10154df788711b864 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c +149949542f34fe4521472a0d3740f4ac64b23050 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c +b27bb0657c7accb0df147f4bf193b12933a9d970 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c +c987048ee653d7b9e528924cd4ea2041d81ffbd3 - optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c +93f44519ebb2341e9ca27ec077a77a455641dba9 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c +13a4a399570926073872b210027dc5539d30d44e - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c +420e593df278e8c4bce349965dc185a1654e27b7 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c +9bf71a86a4483d4e404521f696f591017b261b9e - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c +208bbe5ced04c13eb0e1d3b24e76f5c81345cd04 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c +7ef84ee8949eea9fb48ef217f1c8ff24f6adf1d7 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c +196fd89dd21f7f943fca9702ed9616a27edc7221 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c +e853e7da65047812f5c09f5ed42bc85f5b2256db - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_file.c +e29b12ee69c044ee575a389f95878c7498a62af9 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c +361ba0aee5e365c0c0cb186cb4aefdac17289943 - optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c +114da72cefd715009a772baebd50f69a3237da72 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c +8151c66fd55cb82b2e4252f211a7d14de20599e1 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c +b8c88d3152a2d9384baf86c1ec61ebb26f13660f - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c +f86f622ff3761a9086d7779d77559eddf2774ece - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c +a3529bef5d5ca05f194021b998a1d7ba5fdec700 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c +ac3fb83b5d619e067782a032452e215cc2ccc3b4 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c +bbf18f6d75557cfdbb5aec0cb00e3df605536d68 - optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c +bfdb58bcc629f18e9ee0daf89aaccb205454e950 - optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_memory.c +40dc7c58ad7c36c78900489dd9043971310b0824 - optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_test.c +23f68588e1e7259db12eff911680272b1742519d - optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican.c +9974963705cf2ee6ede4a5f04102ba8237fe707e - optee/optee_os/core/lib/libtomcrypt/src/math/tfm_desc.c +0519f4dfb1ed6bcad6119da63132e2cb99a1ed77 - optee/optee_os/core/lib/libtomcrypt/src/math/ltm_desc.c +829f687603d1caba9543ddddb56af948b6a6369e - optee/optee_os/core/lib/libtomcrypt/src/math/multi.c +6eb1e1c16c036e2717dc3ab41e98acde07da53a8 - optee/optee_os/core/lib/libtomcrypt/src/math/rand_bn.c +2ca00d67d4090191db790a545cd86d609c5678eb - optee/optee_os/core/lib/libtomcrypt/src/math/gmp_desc.c +4107a71b931755873657a1db5c1d361d3baad0e5 - optee/optee_os/core/lib/libtomcrypt/src/math/radix_to_bin.c +64535e883ae11fec86629844a95e9c1d7f02a486 - optee/optee_os/core/lib/libtomcrypt/src/math/rand_prime.c +5a3aef9006609eab6327112f5508e2991e7a678e - optee/optee_os/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c +8eb767695e5573271863a44feebb74683f2f7ff6 - optee/optee_os/core/pta/benchmark.c +6284c967a1103f26724ff4dfe45af409bfbbf948 - optee/optee_os/core/pta/secstor_ta_mgmt.c +35fdbb1aef5536f3741a6fd8413c617d3fc6ac1f - optee/optee_os/core/pta/scmi.c +1a3dee6c0209f34eb5cc01113ffa6b544f5cebf8 - optee/optee_os/core/pta/attestation.c +4e1b614df9067b7a1f2158f1d5111c1925483f9b - optee/optee_os/core/pta/apdu.c +5464c3291d0ccd05a1742d955c828fb6bff76cf7 - optee/optee_os/core/pta/system.c +4b7b26064a5527653817507ced6b5d36e09d75dd - optee/optee_os/core/pta/rtc.c +3ea15c610f4ecba8788d1055a06e13c3b6aeea5f - optee/optee_os/core/pta/scp03.c +14015171ba8ab23dce63f6011ecd0899f08137c1 - optee/optee_os/core/pta/hwrng.c +8217fd671d72116cf6419307db3308a18014e422 - optee/optee_os/core/pta/stats.c +6a748b8c571c2b207c9db79b56b491192bf22379 - optee/optee_os/core/pta/gprof.c +45844fe0a6df40bac193ad48ae86eef7eecbeb4a - optee/optee_os/core/pta/device.c +92265a3a661a4862d09043e5c3ed8787895b4d23 - optee/optee_os/core/pta/bcm/bnxt.c +5d347d3376095cbc05c1ae47cb6d4ac6f74ef5b5 - optee/optee_os/core/pta/bcm/sotp.c +9548805f4cdf2d64fe66f30a4518b5738878b0b9 - optee/optee_os/core/pta/bcm/gpio.c +1d96880636f5a98568edf08f68e5e4b38291da17 - optee/optee_os/core/pta/bcm/wdt.c +c53ce6db2d7519d9bd08c02472fe525fbb768a6c - optee/optee_os/core/pta/bcm/elog.c +8accf96a33e318180c18fd79729c3476c4e4a567 - optee/optee_os/core/pta/bcm/hwrng.c +f76d93f72808e78fe854329128254e40a8ae64ef - optee/optee_os/core/pta/imx/digprog.c +0b56b4c47bf29b408b9832b6a57ca5277c05a16e - optee/optee_os/core/pta/imx/manufacturing_protection.c +1141e0df408fb0977880fbd63e8a1575a2a81e8d - optee/optee_os/core/pta/imx/ocotp.c +1828d31f10e6236e1f4f6c98f71f34b61827f092 - optee/optee_os/core/pta/tests/misc.c +773d0fc2245c86d75271917a6eef93910cd5a5f2 - optee/optee_os/core/pta/tests/misc.h +598beefd2c0b1d1ed3caf79b7ee3f6fd4315b410 - optee/optee_os/core/pta/tests/mutex.c +a27586aab31e93cb9ce669c13e202c989d6f3e00 - optee/optee_os/core/pta/tests/lockdep.c +64e6434dfd3be13b965104477ee440eec10fbaa2 - optee/optee_os/core/pta/tests/fs_htree.c +9d5f604852b526c4c03348962f3d622ead341452 - optee/optee_os/core/pta/tests/invoke.c +5334d9f03de114b60edb9b9b5e7037b10eea8c69 - optee/optee_os/core/pta/tests/aes_perf.c +5b825d9894d2ed56396b487aaa3d994d6860b837 - optee/optee_os/core/pta/k3/otp.c +9f086ff5817b522588e0b043af390b20bc659347 - optee/optee_os/core/pta/tegra/jetson_t234_decrypt_cpubl_payload.c +169bda07f69b89df46b79e7a085d3fc44595d2ec - optee/optee_os/core/pta/tegra/jetson_decrypt_cpubl_payload.h +2cbe5352d0e151803629138882b8b410cd377bef - optee/optee_os/core/pta/tegra/jetson_user_key_pta.c +186b949fc854bc97be7883a0f85300a6113bce2c - optee/optee_os/core/pta/tegra/jetson_t194_decrypt_cpubl_payload.c +83d3b7f9616db0d5e42b621f55691ec5d505b4dc - optee/optee_os/core/pta/stm32mp/bsec_pta.c +be4c6a3071f47d6d836b24e210bc1d446aa9afcc - optee/optee_os/lib/libdl/dlfcn.c +902b546a61d836961ed0f5fe348b564b0583755a - optee/optee_os/lib/libdl/include/dlfcn.h +2ece28422760c949f999a648997f0e4f232ccf24 - optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md +69a1029c5445fbf82397087777714675c6aed1e5 - optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog +34cd5767e5498e0e9fbc3ea30953dbb7a30cc6f6 - optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md +e2ad0770f50a3b483b020e4015860e4802e3b9ab - optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md +9c4135419c10fb8160ed25ba74f2e655dd524114 - optee/optee_os/lib/libmbedtls/mbedtls/README.md +2b8b815229aa8a61e483fb4ba0588b8b6c491890 - optee/optee_os/lib/libmbedtls/mbedtls/LICENSE +acf6955c96e7b062fb476682cca44221182ce556 - optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md +c5c0de3138dcf3adf8478d316468a72d544a833b - optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h +83fcbb151b339ff236e86dce0b26c7f4a24f4ca3 - optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c +f48433f7b983f2e4bc0dd945c94ad7da76d5f4df - optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c +1e1202a1a70b33fc56dfc5e187c17011edb30e3d - optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c +f8f18a16efdfd7aaa581fc625d16b1c3e55ce4c1 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c +315ee16fbc23682b7e4d5757716b16f5cd02bc4c - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c +1b8905fce80fe974d94b8c622fe8f1c9ffac330d - optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c +559b9e2bea2960c9394c7f3d6c3ce853a86da592 - optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c +bdedcce806f7e967428c250acae28d2acefae2a0 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_srv.c +29af5c956f2a788693c3f61103071b8bed4ec090 - optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c +322993cbc8151f3520b8022f9f95ff9a3c20a182 - optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c +21c1eb3144519a4d6b901bc7c4710d2e46ead2e5 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c +f5b2d834025f50f1f657e75b119ffb5eca0ce04d - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c +63f97dee98c3e121f09f1a92ce5a4db660b69055 - optee/optee_os/lib/libmbedtls/mbedtls/library/arc4.c +8c4d1ea180d89beaf123ffa211485ec970338882 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c +27337042477fbc35ca34acdb6ed9d142ac8fad20 - optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c +e2802f6140845c3bf4498eaf768e5f76af606817 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c +c518169e89e4a6a9741c048118a20187a9b5c9d5 - optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c +efe4b23e8a0c98b570563531ddb3284914370a94 - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_invasive.h +e4f22fee91436d0c50a565246c300a07adda1ed7 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c +260858d5b01b92f1a8f1bcbd987cd005e93a120f - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c +a89fcca6031d01abe7a86696de3b42bb4a839986 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c +efc6fd614fa60d6706cc4d36d961646d92edc8e1 - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c +271f6cfabb363b38f50d995deedbe2a97ee17223 - optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c +4935912b62ab72b3f50e5eaf29df7d5ce2b9e01b - optee/optee_os/lib/libmbedtls/mbedtls/library/md2.c +fac77be2fd3e8b7fe8fbc68b56e8107eb47cab72 - optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c +453e24f27239b9150880e9edbafc1096ef2df104 - optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c +c274b5a7e841aa574404844167c3f0c3d14c4397 - optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c +71b284a0544487e2958b45a953b397c5d5edd41b - optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c +3ba0ae44b8c9142c37d6b3eec1bb283353c29b1f - optee/optee_os/lib/libmbedtls/mbedtls/library/des.c +9413a59ef6b7123ce68204057686900330e067b2 - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c +b6f08f5eec4486713b955968cd08783799e79c70 - optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c +6c8836c3ee0092aa55203d6b340e2a88ab1ad9bd - optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c +9ca35438a2848ad8bdbf3810fe6b660abc0b6cb9 - optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c +38089efff8e763ca84f68899aa27a12aee37d52e - optee/optee_os/lib/libmbedtls/mbedtls/library/version.c +eef47ec15328369abecebd4a9c3bf1d7d5a061d7 - optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c +622cef7a11f54b42f48a8a2acbe628943e1f037b - optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c +91bf49b8e21a175232f8f9ac0a27e7e29344e351 - optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c +61082dbe6e7a14d79f82c525f5bb500235b37448 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c +a4fd9926ce0bf5211b4b61e2e83574f522a10eec - optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c +fc5fa6471e433ad425b79bfbdd938becb5cbe10b - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c +9ddeb707be554648d86dbf8b3bd105cebf911eb6 - optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c +adcbba8a5604dfc87c5fe2315b816fa96c5f7d7e - optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c +f85c4897537e66e26f7b00502beb5f1b8b98460b - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c +b255f5117b8d7c51edf2e480ea74bf97759e7a08 - optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_internal.c +b12c4de77452103680a51e14ebc8262beaaa1945 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c +6f78ed043b58503736206088d7114d6640a7e699 - optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c +18c9db10ef79e7521984a3ca7f367808e1ec1694 - optee/optee_os/lib/libmbedtls/mbedtls/library/md.c +c31f931b210d449cd6e0418ee3f64599bbf66148 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c +fa87c2cb698c3f1d4814e062984c0e3a18dc3389 - optee/optee_os/lib/libmbedtls/mbedtls/library/common.h +c52c9609c2c6a156b85487c6c29dd205aca6489c - optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c +f23224aa8aa469d56af749fea346db46e7f42400 - optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c +2c0509b66770248ba1f87c8701d23ebafb826fef - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h +ff2f47eab3d90d25a4a3feca4c9c97d29e5b8837 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c +5cb4e9ad752529bb18f635e12f2e7a4653ceae0b - optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c +2a5883a66ffb4f0bf72035d66cd93a1da1212a50 - optee/optee_os/lib/libmbedtls/mbedtls/library/xtea.c +6ccacdbcb3d6683215a378812ac9c07a95d15b52 - optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c +eff5827f73dc11e94f0cdb521b69c886b6d977bf - optee/optee_os/lib/libmbedtls/mbedtls/library/havege.c +6bc1bb1090d17c6661707282b09e6eb1a829b41c - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c +ddc711088ca1bbfb07baefe70610dba57b3ed987 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c +5d28c38c58ee292a7fad605958ca7bb50a68e7a4 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h +fa172fc71f540bbfc7442d35fc4e6bb8d66c32a0 - optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c +a852ceb607571260156072fa6312d959950c6d85 - optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c +1b7eea33bb1515eb89b6cdd0a39214ca1233187e - optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c +b1e5a79d68a7a1ec7f0275df720f96ef736ab374 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c +a6b69690f3cd334d2902f9ee2bf9cf96549e0c89 - optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c +96e03b56195a5d547890a933bf2586653d4bbfdc - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c +da2586312dc78f3baed16f9321ff36678be19a73 - optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h +d2fb6454dfe04574a6194efbeff38a1b67b3d0f0 - optee/optee_os/lib/libmbedtls/mbedtls/library/md4.c +fc8e38cb560a03ad03584ddd456fd0b0402e3b07 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cli.c +1ec5e59dd3a1462a5fd643e8bb24f38deaf554a4 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c +2def7447401b608adce999138281423a3102b8af - optee/optee_os/lib/libmbedtls/mbedtls/library/error.c +75f272323fdb02057934dffc82b676c20a1a34e9 - optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c +8fed6dfadaaf2677ddc9e6da823396b060bcca16 - optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c +142ac144081804afe7d4e8fc50cff380303e0b02 - optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs11.c +bc1b782ddea9e8c505bac2d0674df882749dd9b0 - optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c +9947e648b9c9cd3133a8d7a283afe20fc0142362 - optee/optee_os/lib/libmbedtls/mbedtls/library/certs.c +8cc3416707d175080cb571ca699249b993481ee0 - optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c +581c1aabeaadfff8296d06359503afeea30bb8fa - optee/optee_os/lib/libmbedtls/mbedtls/library/base64.c +0e792d29724a824da680ae05d8fcfffb924ea6ef - optee/optee_os/lib/libmbedtls/mbedtls/library/blowfish.c +39ec52f39c7a19416093db88d93a2d0850b6471a - optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c +132e8598402370bf01ad8f97a2fd020c89e3649e - optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c +9033f80cc2775bdf8642698f000b1f14c17c2531 - optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c +8e110f23ff047d8ad91cf150b21dda15a8c51fd8 - optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c +ebc9d7694d77dc95c9a26e172b1778334df73a71 - optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c +e246ca77d621222a8aa12f52a8984410aea9785b - optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c +b908bc4417b8167c769fda2487b88a62b987ed0f - optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c +f7f70eab033df0e2aa8f73f3e56e4ecf01967b46 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h +7a8fd1f6b729f3ad210ea034763ec05999fc1499 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h +c5fc28af127a0a2ec0b26b5a10db2916e8f46537 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h +2297980e8e469ca536cb0d8f6953f27288d83afd - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h +c3786d1c03cc2779e4b50925d85b988380615922 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h +fdab353d59e781049e2839fe8c0bd9fe5c7376f9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h +da3320bde8f57af08bff72700a80d8f95d96b6c6 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h +73e972973c69f84a622ac147a84ea7b15f4a526f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h +ba12324cbba3f3db8cc8241a119702ff0abe8026 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h +35916f94391efa0b5cbebe9b8e50842832671015 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h +82385e900e1d154fbde1b7048606ab6d682b07ea - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h +3cd46cd245df5c87b55bb5efc77dc6f5142657f0 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h +24d59951a54278751304dc0abc30bc19d34a04f8 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h +88ed65ff99b7a98bdc81116adf4b3cf3b93c3698 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config.h +0a7d606dfa4d654a551d1b0a2ca188e7b08c17be - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h +aaf629ff227c300525b34bfb14b4169d1e0da989 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md4.h +3ff671bde0767ebc75fe6252c3fec712c4c70332 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h +d876bd7b141720bb5c553f5c74e806e65ed34068 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h +f68ba04bf10e7ae5460af4cd3a0a0aeef75e1b1c - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h +86fd1279228501f3a8124e575516862cae64f274 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h +2f556b5bb16c79df9985b5515f4efd98b8e9d36e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h +e510c5c9d18bb20e5a0db4b7feafd16978ea97e7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h +1fd549849be8d4b4e5f2df80e9e0521b3f77af66 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h +fd9c07978180a4ddaf4dc878c64425b6fff60d58 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h +3421e523a4eb7a40b760ae0fef477c206fe1c0a1 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/havege.h +05e40045faab7912fe526f549ed02e8e728accc9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h +2e912771a4bb2c76b64a5e33e8e4cf959bda360a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h +988814b4760d2244e329efc2f5a695a90b06b98a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h +0050c84a3902d0103eef8e3790304a672ad80651 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h +81184c66cf49b3a5fddf6f414045dacbba683c94 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h +d112a7ee17bef0546621b7cb32492e267fe14e62 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h +382613af5b38ad8b21776442aa78c648f076ef3d - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h +61ef986ba7df9eb5e9af42d4350290efd2c6cc20 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h +6946d05f02bae8db69c2d8fe537bf1fd4e93c6c7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h +86ee6f8982ebee49fcbb54593bcfc4608ea03022 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h +f02f5e69a9c8edafcaccd9257271628e5d451069 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h +42ef4ce799699bc086a6cecaee5e5f1248b52b89 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h +695db14013c2730f69e207f528656845bc4d98fb - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md2.h +3c23e8d56fc0fc5ca288a6b23d7d1e72689fce30 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h +a182f69d5e8305d19faf1b88f3c6443f0c998d38 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h +7105549c051d678722d5b3c4b5a6eab6664ffe39 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h +bf8042d59b2ba674077ef56511948fb2057bcb92 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h +9559b189986fa0cc09ddf64b2af4cb427195b47b - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h +3d4c418e2a25efd04b957f4a184e17a1173175d9 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h +87dbe26bb03c986fcbb4adb6484e23669e3e8fe4 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h +ef6dc18a06fe96400c6fc925e0eb3805631ff930 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h +879fc92ce266212bd186509f7c9639b64b914388 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h +6dcc94a51079bacc8ac9dd2f8cc2d886baaa5e53 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h +b4b7b0fd5cb9db5e05afea5ace2811809ecd17ff - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h +97a63ba6760938a6a84ce283a36ba5e193958bf7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h +d1d0f5c6aab7d5cbd9ea97e6e9b6dad1ab961341 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h +3be0e79f3eccb1145cadb7d9d57fdb2bd6b5056f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h +7ba60fe8dbf1a8014980df4d02edd15edf1d8376 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h +7c1598cb9035f535cb60545302c735df638672ef - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h +e8934d06b86a0d71bb8e3a8e061b2aa7ddc811d5 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h +f1bf57f612067bf2e4df95ff7a4135368a8fda50 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h +8391f7564988437ecbcbe07aa53684b8f883f4fe - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h +5d75d5424716ad4ad724d932ad1e2a0f4816d19b - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h +b5bd802a71034f41daaa5d0f3cbad9840adaddb8 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h +8e7f7f04a47bd1833a9b06fada69ab68beb1f29e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/certs.h +587c56d3cde1593fd3344eaaa7a85ad96468054f - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h +ffcc5d17de9dc2b0f1abf9dd48f99cc8597c8d01 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h +6a23d17bd6e89b823200ec15a2e1aa1a6eeb75ee - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h +831d497ea55442be6258d188b7106ae6b407275d - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h +58d14a3da288383e17a50162b7ee8676aa39e30b - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h +8e69d040c9f7f246f2ed05821a0c12b8b479fba2 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h +2ea32a77038f43ab89a11a66e8ebe28467d2aef7 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h +33753b5d5cad4c1743fd00279037e092bb447b06 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h +4cbcf3ca5862d0d701a55325388bc7dc46e97011 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h +b29c34b6cc5f246b5f4770f0ff8e740a3ba995da - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h +64fba94be26b0bc251bdc4dbbc123b9c6d47ba27 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h +303d2fa577d2570f5862b2f24ed080db63839e3d - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h +5499103f9e51faf154bddc54e08336587fcd23e8 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h +b9adc12e4a406da08cf6736975a560b5a2cf63ca - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h +25a8519a8e435600c9e9f0e4fb73628e8c26308c - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net.h +8f5a31b8baa24df22d43316bd594a9ee90d9b485 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h +3516e070c31eabeb823c760af684046cfbc8ca57 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h +bab8fdc0f1df4dad69f3ec9e718c9a40081c486e - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h +83b0ba9cd31fa8443be607606a5ed2ae11f69b1a - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h +f9dc451695e690dbe1efad8f404eec60095d44e8 - optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h +0ce5c274e6c19b4f0b153fa0ab9c55ea8622d82a - optee/optee_os/lib/libmbedtls/core/bignum.c +c5faad859e41c84415cee53c68129957632a203e - optee/optee_os/lib/libmbedtls/core/mbed_helpers.h +17b0020bb8d91bb229a17505c5830912086d7dcc - optee/optee_os/lib/libmbedtls/core/ecc.c +98b5b0189cbb8c50b0e303790d23dbf9681647cc - optee/optee_os/lib/libmbedtls/core/sm2-dsa.h +b68da531ca86368d8d211961616d067dca104cf2 - optee/optee_os/lib/libmbedtls/core/aes_cbc.c +9eac1bef00d42cb5d29355da4ff216ab65029708 - optee/optee_os/lib/libmbedtls/core/des3_ecb.c +201268ac06f2c70661d14ec18b1290902998eb64 - optee/optee_os/lib/libmbedtls/core/rsa.c +e9ad5e77639fed16cb29a614b7ded9aafd47232f - optee/optee_os/lib/libmbedtls/core/aes.c +44c09d4b791e9fc7eb12c3090186b990a05f4484 - optee/optee_os/lib/libmbedtls/core/cmac.c +4be86702d2f54b1d3c9fa62c47c1c16e8f9a5210 - optee/optee_os/lib/libmbedtls/core/sm2-pke.h +a86c6c8bf63ea21ef2492f49cbc071f2f23a1d35 - optee/optee_os/lib/libmbedtls/core/mbed_helpers.c +3a1838593a7cbf67a1966456b9e4e441e14368ea - optee/optee_os/lib/libmbedtls/core/aes_ecb.c +3eb60b38bd9b87944a242c659ad68d8aaa8e220f - optee/optee_os/lib/libmbedtls/core/aes_ctr.c +bc4a14352a35d7f28ca65fda6e4625eaad768ef2 - optee/optee_os/lib/libmbedtls/core/sm2-pke.c +bc890bd3de1fadc56b5b900e0d3f378f35e60250 - optee/optee_os/lib/libmbedtls/core/hmac.c +9f8f69d3262f16988e954e72c755c3e4706bde9d - optee/optee_os/lib/libmbedtls/core/dh.c +1e3080bd5db0189b057a3f4fa1d45dae9ce59c72 - optee/optee_os/lib/libmbedtls/core/des_ecb.c +95257f1b9669bd55e715296a5db0520dfef94dfa - optee/optee_os/lib/libmbedtls/core/des3_cbc.c +89b5b1b09c6141ce6cae83b42b24106dbf5d19d7 - optee/optee_os/lib/libmbedtls/core/sm2-dsa.c +4a3549fe50b6596fa95703bdad942578f79ff095 - optee/optee_os/lib/libmbedtls/core/des_cbc.c +314159d576fa3458bb67bf9f6ab24f9852fcc617 - optee/optee_os/lib/libmbedtls/core/hash.c +7cf5fb5fdbffcf6f9ad1ffefde20cb30eb66d58f - optee/optee_os/lib/libmbedtls/core/sm2-kep.c +27d0d017d652207089357343fefde8822d574a56 - optee/optee_os/lib/libmbedtls/core/tomcrypt.c +af0ca4eb18666ddc7ea8c06659fc1253a3d96416 - optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h +82d195f6948af776b75bb8bcc34cb945ab8eb1fe - optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h +61a92d97bc038e1636f35968f5a75f708383e065 - optee/optee_os/lib/libmbedtls/include/aes_alt.h +51ba88c458d47c0829585e30ed93e07a7f5ee183 - optee/optee_os/lib/libutils/ext/mempool.c +47c2201804ad35107c694730f37c017ee288ee01 - optee/optee_os/lib/libutils/ext/fault_mitigation.c +8d6b22214c57ad89d47fbf50c9d2a28ec11c2951 - optee/optee_os/lib/libutils/ext/snprintk.c +9fd93f109631c93c98f7d21f4b2bc03867d03097 - optee/optee_os/lib/libutils/ext/trace.c +ce50432f4d5515d5ce9fb398b5098b9c0ec12c38 - optee/optee_os/lib/libutils/ext/pthread_stubs.c +53a0650d0e1a37aefbb511bb3f422ca162180c36 - optee/optee_os/lib/libutils/ext/strlcpy.c +ffad6974fa755ea998a6801173ebf69647d8e204 - optee/optee_os/lib/libutils/ext/memzero_explicit.c +7a501727fe2d0e89ac822ec9ecfc06ac9387eb69 - optee/optee_os/lib/libutils/ext/strlcat.c +89ebb1873af1f851bc8fc67e813f81eb6a676a2c - optee/optee_os/lib/libutils/ext/consttime_memcmp.c +eeaf7cbef43d983ce60db9ac8731767dc6bbf22b - optee/optee_os/lib/libutils/ext/nex_strdup.c +ece984c44b615c403bcea03f8d97fec4569856f1 - optee/optee_os/lib/libutils/ext/arch/riscv/atomic_rv.S +527c3d07f4d854cb770425c1d1bb43d87d25a622 - optee/optee_os/lib/libutils/ext/arch/arm/aeabi_unwind.c +7249fff01b1ca0cec36cca67bec4a1395ee4224f - optee/optee_os/lib/libutils/ext/arch/arm/atomic_a32.S +ff0eea4f25438d8836034710afb20c6ff62d9805 - optee/optee_os/lib/libutils/ext/arch/arm/atomic_a64.S +3c9419abbdb07dffd661757f2b8acbc0c49e971b - optee/optee_os/lib/libutils/ext/arch/arm/memtag.c +c76559d831152142d5a0612b9a2ba8988ead0414 - optee/optee_os/lib/libutils/ext/arch/arm/auxval.c +adf6c7b011707e03c48439a6a7de0b07e91d5e59 - optee/optee_os/lib/libutils/ext/arch/arm/mcount_a64.S +fcd9b20bfb493ed1ef33987681cef3c072605105 - optee/optee_os/lib/libutils/ext/arch/arm/mcount_a32.S +0e9c096815b105d29d59a8cfadaaeb5e7a3b7998 - optee/optee_os/lib/libutils/ext/include/arm64_bti.S +296cc431c36cb1c06ef0965e569bb8f0028aaa86 - optee/optee_os/lib/libutils/ext/include/bitstring.h +0c4e420d80821bc2e9d1c85cb5488cdba9b2dfb0 - optee/optee_os/lib/libutils/ext/include/config.h +dd93b7320673f243262308cadb21031730b3eb4d - optee/optee_os/lib/libutils/ext/include/asm.S +e0f599207b28b33bf06b5e1c02b650d0e1a2d7c5 - optee/optee_os/lib/libutils/ext/include/trace_levels.h +603efb52be462838f3f8f8f5ddb20258ac30f353 - optee/optee_os/lib/libutils/ext/include/types_ext.h +82c8f1ff88d4550ef30a6295467a3c9a89a49f64 - optee/optee_os/lib/libutils/ext/include/fault_mitigation.h +d4f08bbbde731d1464ddd75a103de8d6d5cdf013 - optee/optee_os/lib/libutils/ext/include/util.h +70ac170a6c79b30435a4b8fef9cf7e98ea61e9a9 - optee/optee_os/lib/libutils/ext/include/printk.h +af2b6927c92cd80ffae87a12bf87645f43748dd8 - optee/optee_os/lib/libutils/ext/include/atomic.h +d0fd7d83680885f9a71f56435b92b078f79e14df - optee/optee_os/lib/libutils/ext/include/mempool.h +80947d734f9aa0143f5cc2a9565cfe10081f306c - optee/optee_os/lib/libutils/ext/include/trace.h +ce8e8d219a06d536dfb044bd004db98fd595d438 - optee/optee_os/lib/libutils/ext/include/stdlib_ext.h +183abaee8b69b529765cdd0e2523118f88c563a2 - optee/optee_os/lib/libutils/ext/include/compiler.h +6d52c01d26b5f87893d70ca173d1fd712d53f4a5 - optee/optee_os/lib/libutils/ext/include/confine_array_index.h +5d1943eba944ecd7ffb277b76460ab47a379f73f - optee/optee_os/lib/libutils/ext/include/memtag.h +93a77e57894a180ceb9cbf485c96b316b0223286 - optee/optee_os/lib/libutils/ext/include/string_ext.h +b5e7d766670b001150bb9d2fb65a689a8c9f3ca0 - optee/optee_os/lib/libutils/ext/include/speculation_barrier.h +86bb497d1cf2b492514391182b51ce9f223003c1 - optee/optee_os/lib/libutils/ext/ftrace/ftrace.c +d252604ab38468dc215d8fff7e20420e53adb60d - optee/optee_os/lib/libutils/ext/ftrace/ftrace.h +fd0766e5127d24a75662d988de4c18f5686b3020 - optee/optee_os/lib/libutils/isoc/isalnum.c +f3a4dd8bf719bba595428ad39e580b4bdb83c0f2 - optee/optee_os/lib/libutils/isoc/isprint.c +69389cffd2f2392d520b42fb8a877d88184eb7ce - optee/optee_os/lib/libutils/isoc/fputc.c +78241abd2dfcf669e50f78ed7af96d4ab11eee84 - optee/optee_os/lib/libutils/isoc/bget_malloc.c +3849e364a583d8e2a6b06c73b88cbff340651414 - optee/optee_os/lib/libutils/isoc/isdigit.c +07859d16a6f156a7b7d53976c3ea35d8c181c050 - optee/optee_os/lib/libutils/isoc/strdup.c +15d9b02b2f680e631dc3cb4acb612c5051534577 - optee/optee_os/lib/libutils/isoc/snprintf.c +44884a714f6031d8c9899eda446ab6bd902d63bc - optee/optee_os/lib/libutils/isoc/bget.doc +afbd6bbf47f8aceef9ce91f60a65246aa8579e52 - optee/optee_os/lib/libutils/isoc/write.c +adf5b4c7851eccb3ab23eaa51e2c67aaea646dba - optee/optee_os/lib/libutils/isoc/ispunct.c +3c0076665f570bb3894f7975c7af19546b24b949 - optee/optee_os/lib/libutils/isoc/stack_check.c +cc419cf9b3049ca5a067f8efc8b87fb21d16cc17 - optee/optee_os/lib/libutils/isoc/bget.h +aae0aea5aeb4c700916f3a0cb796958a066f2033 - optee/optee_os/lib/libutils/isoc/islower.c +9bef02b228d5d11a675a74e974644af7f91dc6ec - optee/optee_os/lib/libutils/isoc/iscntrl.c +465dccda5f6216b5156acdf8d97692de7a6bc618 - optee/optee_os/lib/libutils/isoc/tolower.c +3871de5c02c34257cb8c03aea71c406eca1389eb - optee/optee_os/lib/libutils/isoc/isupper.c +bd92a4e902b8f071cb08e11be594c2cc03b13e0b - optee/optee_os/lib/libutils/isoc/qsort.c +3072e334c9965c360ee485346541f37b1cade0ce - optee/optee_os/lib/libutils/isoc/strndup.c +d7303541082db306fa6b0447bd5aca62f4cb8169 - optee/optee_os/lib/libutils/isoc/bget.c +66446d12deb5b2f6768b0037c5cd7f6bda49c01a - optee/optee_os/lib/libutils/isoc/fwrite.c +bdba22e240af00ccb765dec28ab938c5e3619bd3 - optee/optee_os/lib/libutils/isoc/isalpha.c +29a7857f6999a06d58d700ca9bd712c157595adc - optee/optee_os/lib/libutils/isoc/isxdigit.c +e50bee77ddab437d58aec0c7d06ad8e70066d752 - optee/optee_os/lib/libutils/isoc/isgraph.c +b2a87efad81c7fc35f3f17a1507b650945a64089 - optee/optee_os/lib/libutils/isoc/fputs.c +486e4ec67949ba32eb52d521355b28c032ea31d4 - optee/optee_os/lib/libutils/isoc/fp.c +08ed68e1c3fcaca243143f636c99d7b1c7c325bf - optee/optee_os/lib/libutils/isoc/sprintf.c +fbbd10cc345ddfe50e1ca5ec8a2e936b5cfe396a - optee/optee_os/lib/libutils/isoc/toupper.c +a426f426e3093d41ca84adcdf9eefd3d37354379 - optee/optee_os/lib/libutils/isoc/isspace.c +6054fbc2e1ca96c1f5291cab671fc90d7ce00fa5 - optee/optee_os/lib/libutils/isoc/newlib/memchr.c +2424e0252f73a9e6fea420e9f7f2967538d56444 - optee/optee_os/lib/libutils/isoc/newlib/_ansi.h +4536b43b4035e668869db96685c3e398be901a40 - optee/optee_os/lib/libutils/isoc/newlib/strtoul.c +c62c5a7633896186fdfc21ab5992c569d0b93d28 - optee/optee_os/lib/libutils/isoc/newlib/strnlen.c +afd073d96ce316d15f065f34576779bf31b11b4a - optee/optee_os/lib/libutils/isoc/newlib/strtok_r.c +5a9624425bf1040b1f7f44f5391b07f0f54eb969 - optee/optee_os/lib/libutils/isoc/newlib/strstr.c +3eaef3643d7bc2740a34226b2b66dca0fd662558 - optee/optee_os/lib/libutils/isoc/newlib/strrchr.c +f4be3b2ac744128b112751c273f2850ec6277a45 - optee/optee_os/lib/libutils/isoc/newlib/abs.c +0800e9eb716a2e65ba7a95b2fbd873749abb41ec - optee/optee_os/lib/libutils/isoc/newlib/strcmp.c +ffc219c3a21638f7e62d3b658ee6c4a3dad8e628 - optee/optee_os/lib/libutils/isoc/newlib/strncmp.c +5c1c0c4053502cfc23acb11a61aef64e6a9f7383 - optee/optee_os/lib/libutils/isoc/newlib/strcpy.c +ca1b181d9d51ccd041f7a54adb83afacde6591b7 - optee/optee_os/lib/libutils/isoc/newlib/bcmp.c +108514868e87a312a98be4104fdfa5f0b689a956 - optee/optee_os/lib/libutils/isoc/newlib/memcmp.c +5f94025cb7d772e0b69eb04008405feb9ef86a0c - optee/optee_os/lib/libutils/isoc/newlib/strlen.c +811f31f56bd454989b15ad39bd9201411a4971f2 - optee/optee_os/lib/libutils/isoc/newlib/memset.c +5604c3647615806cbfd5068d684f1127272226c0 - optee/optee_os/lib/libutils/isoc/newlib/str-two-way.h +b1d845daf20cc5443488f37fac3559c721bcfb45 - optee/optee_os/lib/libutils/isoc/newlib/memcpy.c +e0298efe1346c7206253a9f0f174acc71479f134 - optee/optee_os/lib/libutils/isoc/newlib/strchr.c +ad3617f14072481d06acd4c17903f9eaf3301223 - optee/optee_os/lib/libutils/isoc/newlib/memmove.c +f78df3e9bb90074ab9ac143f5e62bed8c2557796 - optee/optee_os/lib/libutils/isoc/newlib/strncpy.c +646239269fb199ffdc49b9001bd8beeded3a1e32 - optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S +24bfedc4ffd1c78df045ab1c725bd811b0531bee - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S +0f25fedd6c6f397a39b1254cce305242fe230e0b - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c +99b85b897d6a461c3fa3c1f9bd54fb771c45ae5c - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c +4d6df8e998067ae07c67580b5f7f261238c7cdb6 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S +30211cfa366caf873a7801a7ac8e5828d0518b42 - optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S +6a325e1881f32b8ca7c74367132e75f9318aff08 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c +dbc715c45b8998c5276e4a7f3dfc71bd81a03947 - optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a64.S +c9a1019f6ff1967d8aa48f5b5e7fc42a42660937 - optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c +eea63204ff2fd371e116939e14a504bd9d17de4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.html +0ef83486a7270a31dab5ced482dfaec14b9a5b4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64.c +920cf94c441178943a1442a168fb4649cfe755d2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128Sig.c +c841c237414b6697fc42f3a261082257cec7dbec - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c +1843081e5eaa9f77ccd80c3cba04e650ceee756b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c +ea9e18329087b88e680a9b0e1dc3f73d78ffc97b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF128SigM.c +5bd19e6fff94dd11976e8f78f6ef8b9af01d33d2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c +e14e58254cc0fe0ce4710d073c7a4c41961df960 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c +49a30ac92f2823400a43a7b0789def54eac5d67e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c +25ad3859febf3093e91de0392cb0d7c98d3e9dcd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32.c +89e1c8f8d93bed98125ee2c0e27f4ad4b87f5f9e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64.c +3e4e1cde87c7d37013c4665489e22a5e653b9e75 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c +60cccf04237a9a059b26075b3bc4742662905190 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c +f3c0c6bf5032a3f329e5637aa49336a98dc365f1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c +eed7248a2360c629c3dc0b39a7b019c718c1f8f8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c +9c753ee79b20998c7b9c420d50cd9ca84b18a3f4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c +2e201e03147cc253f93e31812b6cc1fa19c54acc - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c +f7e21606f0f60046e7ed31a99520969bf3cff7c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c +6772aca13808c91d5fbc62b23e65a9aba99df8ef - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c +6b7125daba8bb60ca3e2db6c38bf5cbc5df906ea - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c +b28464c7ae4ca7eb7416555259cf21f36e3906ba - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c +c32eb171afa353fe6d96c9fcc1b6bc9116ba3237 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c +136777686e7e2c7b3decdc75d9cb9e0f802b4dec - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c +440066ddfc6cb2460e07a86d2552d5aa6978ca47 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c +6ab2cbbff35bbae58c14a90419c2dd153b667063 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c +3f17bb81a05b30c928c6f3dcbd9d6c33f6dd808b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c +9cd0d76126fdd8add379caa20c766668256efb6e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c +ef40011bbd21ac40df712f0f16dc844ee06aa453 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_add.c +e6ad1063b924e4b96a1801d49b960b3d8534342e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c +a5d1d8aa31fb5646e96d1f889729bd9eb7867e9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c +188a513a8b2102d97b435bddcaa70a13422fd36b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c +c9372c8b60f9e67962d30179a0595294d74953a2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c +809dcde66eb6eff4e7af6a71ab240cdae5c11097 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c +c62a95ceba02a10b8f43ebf0b1621e6a814f07ad - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c +f79c163815f902511ac25f8f5a391149043a846b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c +68c9d3e3654c5107bd58185d3632d6e8c4b04687 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c +1d4036336aa49d6961f510e234caf45cba50d995 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c +5d1495da9f0d75aa3f5fa75b43c5edbc95dc1ae9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f64.c +fab91920cf859d0f22562a98eea05a843806e70e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c +f1663c2acfcb26909b23e18b18c43a4aecee1908 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80.c +ed1a42257f7a11ddfb2896bb3db8fa6b6b799910 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c +3e0d54c15411c2c997b29fa7132f305ba0986d0c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c +47e7b19a3c969e8c6acf899992a2b3dc02ee894f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRight128.c +a56defbdfcb63c086c83b3754d2848c2d67b561c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c +fd6492962962b16aeabef92ff9542da4aae05f26 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c +bf60482d7a8c7573451dd9d358a4f59882b4ecd8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c +23659a34fd66f6a163767159d9191aece60e9833 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c +c8fa83b76113c38831b0a21b4b6359fe6976b133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c +7749e3a634b0f7cb154a734be194e52d612310c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c +60a64ea74aeaa87b706af4f0c880e551d68ee8f6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c +0db18e1a005858944af9123bb29580ebac102bac - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c +14119b8fcb0828e0621f0d1c0b3130721abcf3a8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c +b4f539877d9b40f21099ed92d2e18a9f57f28566 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c +cddf72a19a53f1cc1e2077dbf7e9269f0ba5cf16 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c +cc614514257c6b0a721ebfbf2f2eb22e764e75e4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c +60f8ae03f26507e95f988d859c2a779d957c4efa - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c +8c11bd928370bc41568ae3c44ed648224268134b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToExtF80M.c +ddf3732777273f55557aa33c85aaea98c3017a0d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c +cc9936a7e89313dabf987a759166c6b627c5697f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128M.c +fb78669ac8ebe25845bdac20fd3007ac6ed6e254 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c +74978af5148ccce4ca51465a934e52d8ff03fb9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c +e550bcef98e4bc5091eac085dd5972d58c2bab09 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c +6eb4a2a36946f25f5528e564a0391b709127224b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c +5adc627cc2a4ed39719943fac8c29517f3d39bbe - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c +03ee79d8d396bc6778c8bd477647f5e7b2035214 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c +7bed7a39e5684ce23986346806ce19c0a2d198a4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c +d2e10d43888a0af127c80ebb29261c8c424b217e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c +3d89aeb6e7880b1152564ff98fac17e80a4beab4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c +3088c598cdb456e47e280fd0bc369fb0d5e6d2f9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c +e4be027468e7ee598e8835dfe5c58692978be102 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c +672608ed7c1150531f5d4e2b3aa274de76f24f44 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80.c +260bca4ccf486c140c36950f988253e30be3f9e2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c +27897b3a3e2b0f5cfd67ca737c35af7cc360c3cf - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64.c +32ee0bb66ee86e9f4d4f49c23487905e3e09715e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c +3314b591c37fbe10125dd1047b564db3968c7246 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c +6f034e453e9efaa8477ac48fed5ff48d6320f99a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c +20cc97dd02d91a85b8d58ab1373f550058a5a4ce - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c +e0f5d8c33a9db5f50d0fc16b09808a48a8b052b5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c +25066beb2f05f436d718c8073ec11ad550f53ef1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF64.c +345b454a7bf01265db26b15ff80f98692e81fc5f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c +644f4fb69b6d67725a586cb47755d4472694dc54 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c +3c7d728ab8fa5d0e345c67d53f5335d672d8fd5a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c +ff0afa5079cd15008d3d3386ac73d3b62a0c4d79 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c +9a156cc904d7427a794de20f093bdff4a44cc12f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c +d7dec92efc7a7503386861fc8a67b770c78d50fd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c +467dcd8f83fcddef3d3402ebcc2c08822c68621e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c +5e4ff4edf1d3a006c61ca3098f1919088d42dd66 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c +2355160c0a3526eb32abd1d54fb01083a1fbe18a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c +6ba3f71a3a306c79f58d469163b33f810aa8faa8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c +623ab3fb8b679ac1b86f7c366eb192d128358f16 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128.c +c3d4d8448c3e622688342aa49d892b84716125a5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c +8a4a364a4b4f144bc47fb5e28144cfe82dd3b585 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalExtF80Sig.c +c7030401c4589ebe4ca9df47cdf4473be706e9c8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c +7edbff34e15aeda6b14e5e01fa34a2e4ec230d88 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c +757e08593f768490c92840e212583a4ec63dbbf9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF64.c +3166b1b25c791f37186ac5ace33c6369720cd72d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c +39e684d513bd8e1bc18146fe5b6b41ca6abfb889 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c +a4bba6333e9a92cef62ff68ef528240c29173398 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c +d724729fe9aff2647d82d44cf7c98ef024550f4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c +28ed562132fa508b794485f84e37ffebf0f45c03 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c +5547439bc882d6cb17257578b63ed5dea9e85ad3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c +4cc44bf1f32b533112fceaf74f2116052c251f45 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c +d11f89d0268036c5e2190b2001b08b46df5a1496 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c +0ac05f3c78dd89e1084687237ede90311fc758d6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF64Sig.c +a8cd508101d5d02ae58933c2b91b0638fe9ce308 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c +d5a7b42551a9289e11b502dcd611101098d47502 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c +02501e2df1729d1c331ab6288158859f5302a791 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32.c +f06279e2d0e5d4a308a35ce0eae73d18ff2b0ad1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c +f394231a827adbe842d2249d968ff138ad99c20b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c +7fbcbd3346af638125a977564bb94e3a4112db4c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c +a6ea63bd09a37c67ab0db5c7378603bc343f7c4a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c +4cc27ddd980713ad95fd12a90c077df01999893f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c +06c8f4bcf358da5b2930df117ecc0f2324a59b3f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c +35820af43505df9a372d4e74e3f0550a3af9a249 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c +321d4491ee122d9ff20f50a5fd4708eec3a9bbc4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c +e5c280ffda9fadc7cf51f4e49ba880138473c188 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c +2a8c469188ac72f1647a4e23121d6baab2f46881 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c +64b0e4b0e7bb5d8073e937068421026aa213bb57 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c +04b228218122ee8f024959ef831393289d417e7e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c +67a5f98ae9f74d18b7c83f145618185127a93260 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c +b971ed0265436f05a8f8f5eb8653de23e49747f1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c +9fb6f1767a51f28d28e6af39ffaedc9883363298 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c +2fc25c51a836eb30d5a0215659d5fd8b4dbda2e8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c +359da64e36a5f411cf383e3fd0f83a248a1dd066 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f64.c +9fbd0b33c76b78481c512902dc4d9a0d67f4f210 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c +3fef81240caee61991a4a7c3ffa8e6d6e2e8066b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c +2211257786a567ae6daea47fa4ddd31c0339d328 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c +3155ae7f402b23659c4ff5e89bd77c5599ee23e0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.c +1e172d64c3dbd60e0e9ffcbcc7a0225702f04848 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c +0020d431a9fe3314ba42c1dafe946fbd2ef7e606 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c +2679177fa989374186316764ed9a90c42e38edd7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c +6504b9481457cfd6e39a69e7066fe09ffbbdb258 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c +a091e47127bd1311d2cd2b78353ee99ddfc54100 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c +6a29d35180197bb865f52b54695f07430e3e06db - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c +a44f15f379846d39821c025d6b7afe2f94cb4411 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sqrt.c +4dbe7ada2eae098c62ec673be2cb2452390c0a78 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c +c50d86d027171a9f2481e8f7c1cb4308f1cf1d3a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64.c +fc451ef01165565a1d593b0e2572eb8e37aa72a3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c +83db5e18b844bed794c0f1690aa2aa28ed93e4dd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64.c +f5755b53bfa3d4ada8ed3be7b2e264ca31c83e9b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c +58782db3382eb567580f7105c6c8d88dd1a6fc67 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64.c +ea2befd81aa697654bc1baf2a7da10508ae8b9ce - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c +61fb9da8313a688f608a43d8aa36ac9861c74c75 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c +b6e5c30069ee1bfdeb29301eb988d9b5ef1e6fd7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_remStepMBy32.c +57500b9bade8439c0c3f06cbb999f6ba13952ad9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c +b37dddeca4634f2e81fadc1fe8c9ec9f9643c56c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c +e0d12d5167bae0c40dc2ee4e8eb79ccb7d7f8709 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c +1d30d31c5765c77e617b9969b778019b60c4b1bd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64.c +bbb2e442ce63abe6d694eab84ce821e2ec210522 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c +c425d403c3b3dfaed940888bca06384b967e8e5e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c +e6b71c319835a3d037818d3ca0d1468b2dd3c325 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64.c +9611fba0e534169527d66900db62b107e96b8e2a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c +625d048386528b1c63a19813ace77ab7484e1876 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c +61342ccf516ad5891a6f2eb1980d37329501ea4e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c +62e6926f729011d5c3aa3af610ce0b916b919eb4 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c +df4f91f5c1ef40d1eaec328ca6b879bf095951a7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c +2d988cd65efb881d8f5103b71c9f6b121121ef6d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c +4042678da076368eb21bb4ded888e17dd2109b55 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c +6e91b9e38753aa8aa2094b6b40b596796bd11b3d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c +01cd4ad4fff8805cc5bf43533b1576d7e170925b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c +bbe0db256dda63763f1a09d9af66cfbfa51c69f6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c +a91c926882ae26c3a59dc8885fabc6e86ce9465e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c +0fb28e0101aaab0bd33ae51a05e4b522cea887b3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64.c +c87f6f4eb78569c01e3fd0c6caed99232b37a378 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c +fb72828cc90ce8ac0bb436552fbd39bee0f11d35 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c +c42aa8ca5eb2a847874b705199b3033ae8fc00ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c +0529a095355f150e35063942c7aec7276033842d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c +80f53f88a6f924eaf40e9f79955bdfff87f72d14 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64.c +5728e535d2903cca9e9558dddf7a571e606a385e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c +8fd3330c1a032cc7c4a7ad995996169ac7f0805d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c +39eaa261c0332f55f617941b8bf51f30dfa288bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c +6ee82c2c62f3442cc1c0b2e9ef6b0b85da32cf3c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c +876085f70200480ee30305fa6463d7c6504e7e77 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c +019af317356453e7119ac20be4c98c0a1c83f8af - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c +e5f8702f5072f781a5b4ef72c7ec4db154d75965 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c +84791d4f50e8187197aeca69dbef6a333d167fc1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c +29d181916bd52d0effa525808e4e4564f56b5ed3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c +2cbd145a4e3465e12bfd47dc4a52fd75c4e0b427 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c +7aeebb299243e2d857eef25300233d709662a1be - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c +7db7c6e3e7ed45f7c7ed16ea6935cc7fdba73da3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c +6c279773b785568a5567bfe33f5a6082265b9efb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c +9e7235e0ad3872a7b6f005a0203e63508f11eaab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c +622a359dab67eedd5448775dc3204d4f48039034 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64.c +1fb366479cad4034726000f4f22cdbcdcb95a4c0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c +dd1f8b3669ce1b87360bd05963ce288acfd9f386 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c +a05a89d48fe8216f0fa0babd342a60249c72cef2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c +73622cf9aea053c968f1922c8a206030cab025a9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c +9cdcb1720d52c0b09ac2ab14aab047bfe940304a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c +63a8a8dcae334e46b7fbc7ebc687e8d6c011fb7a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c +b8189771723e965a9e94712bfa8135b04f844af1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c +12d0070692fad1189770f55c41aab025bee462a7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c +e33d236ac36ab3726429718fa699498e908afb21 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c +f81c603cb90e956ee8dde34149ac6bd684d4c70a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c +2af1a8917871bcc8c0560e709aa28418d004c97e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c +9783f22f581b7feca4f86660b538b214dd32b129 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c +faf4056d360eb6faeccac416f54caa2a1a8bae9a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64.c +0fa1c7015b7c39efbe07d739a03f2a83b85745b8 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c +d0375fd187a2ec8138e6a29c04afb951176c31bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c +6de7ad17814ec3532d2cc20927580d8cb52c44de - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c +5f3d886dc9c8533c8093c13f3b4242c66ba17e5a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c +3ad627bba48b5bb63c11c5e86c0081d283f4a13c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c +28af646437af4de6033b2176542a5d805636323e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c +04822aab5f0c58ebdfca756670ddbddf4524258b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_add.c +97a45958e5ea33d1fed598272e527b7f72a9d8ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c +71874d6de8e801c14005d5b1f68170c3c6c6baba - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c +bc52a98da5add09bb146c15a8cc1e524e1e36989 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c +9b35552cd723623625c63511e14b0e559d678f4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c +4e4a329eebd8c7675a57c1b06f75ff4ac326b2e1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c +327934b641bc5a6a891fd19aab7b9f0363952a0c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c +1a1af8af29ddb0214656df304b31583e97bbe044 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c +acd11d468d7a20b0e4381a8b7168e186b7d49d4b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c +5cd984d2fe4bfa79945c464d200d7b17d205b475 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToExtF80M.c +1aff280581ce3e0a033ebdb2257a5095804f4a18 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c +993bf55183ee975278a5e4c34e658f6f7bd3702e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c +7233f7a2c75705b0b4173168df45777f969cae96 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c +bb4b86c5d78b77f1babf89d73c262ab3e47b6832 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c +0f29c869a8f46f705f24531b2826deabe579032f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c +97688d5996165455b0ead5c1973e36b6d096c21f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c +71d3ef74fe02e7fe6891e4db41241c5b2e615643 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c +db04e48a5c823e4f060cc56187b01cbb89ee1afc - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c +039cc691a2609fb90724786e7ed7be17b006803f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c +dda54df5d890a969ba663a54ceae83c6492d7866 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c +f02ad3fb3c3e82d60532e677d475a578ecdf6a1d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c +a473fd92baf36ab51a725b665f964a7a082f4eb3 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c +de37f2fef538ee89236273ac956585b2d58a15ab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c +70a0a4dddf509479def6ff905d493e6a50c1bacd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c +4802d692dda23c6bdb15e682f8895eaa2e02a824 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c +a8129c9fa34f996b39adef2e0620dd63b5ab655e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c +495735b890e1bebb53e4e2cef50ffda57a242662 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c +add3de1ad7693fb4a2a5453483938b93b287e275 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c +c5fd85ea4a5cf0a00edfc6cb66cf20b3e7100062 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c +890504face9da670bb9338c6587d893fd632819b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c +e9570bb5907e357489fdf310d629201fb63fe691 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c +d5160582645bf346bf920e38f896596319da591b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c +bf81966f25644611be0129d9ef8aaf0f5c6da21e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c +dd00b7472e373b2a72b05389fd8c595c9e688831 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c +20b550200dc22a4995a52f7bb20f8177c851d08b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c +1a5d352e9bacfa36ecd8ef231155053713acece0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c +ebd71c72d17dd55dc010988fcc223aeb9679ee6f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c +c0e3f7568f5ce015eb6724ca13dcdebf3846138f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c +23a84b7f28ce5a2345b3d037ccc8f2707163d262 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c +d586657c54173f413fa72807b84027e1beeb6234 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c +d64953149b1077f8e6d0848e2fd5506136e6f2d6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_add.c +54fed28ecc0bb163f71b7d5f47c960063b16f0f0 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c +62cbafb0d4719707254e3021383d31fd007b3971 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c +082138b2e89a050296984be3e3d195746735edfa - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c +33dedf42e83eb53f8ce20395143a01a73b412457 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c +3c754eb220ded3a7e9c82cb01c7ed8adc2144452 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c +a04e210c7ba96d0c982f31acdc218a4a63b5326d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c +c04c45b92e29225e1d2e3decc3dfc108ae63b093 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c +641b01960569783533397d0ed1cdbb00695a3578 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c +d594421c568958d475a5939b2bc14c195493768f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c +f815fd87ebd1c160aa9ddb1c232c1de58da01072 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32.c +badda43bf474995d00db78fe6ae6b40268e9f90f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c +5aa2d29c4f2ecefdd83adab4927c2dba794a0a43 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c +d688f7a888e0e7b33a166af94044edc80100754e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c +5158c6ca5efcc7ee5067415f6df5988c4b3645ed - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c +73f1f3cdf7a70d4d02ddd5d73f8198482d373296 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128M.c +d3cdaf7ed2016c9f9764a514ec05b2dd6f86fc85 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64Extra.c +0d9fe463bfee7b28f85650d68588f7fb47358282 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c +b390f4671e459aa98a5e6eba67989a524df502c6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c +7c39994169fccf5700f2fe944d8b94d912a07723 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c +289aeaf52ea847d12eab9ab91e1b080ae5cc4774 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c +684615f62d1f460768c6b9cf951bbe7d82b7aa4e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c +5bddd155904f96e1af61acc11b87973856d66810 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c +5d919ea71a15f028ff7b85cd73d9543cbe322b06 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c +4189613b8730aaff62a01f6254b071b9fd3c8cb6 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c +7a1740bacdd6fbf37b3e9ad6b304b772722041c2 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c +513a918766d59060a56eb14f936404c5a807d54d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f64.c +b33f24777a60c2b658a6463c17c19f932c67cefe - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add128.c +b48f6bd306c3509038d6c4d283bc189d517d3b4f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c +0f3d7b35ae34828864a226e8b123484e88b8cd13 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c +016a9e65ca19c7f5d3561d54a3fcbddfb6a310ee - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft64To96M.c +73e3351f07e2c7c7d591555895c25042a56c82fd - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c +302b57e7a9ad056c7936806892309cb4de6ffc96 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c +868cee0046c6b1426f45136804fd662b030f263e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c +52fee0fd73c94d2e2f5a21a55f082e1963b1569b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c +67e0a5407af29f70e8a1cd10563b7aaec9ccbcdb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c +7c65ad2301cc6e79aa3392bdb9010a7ce81b0c38 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c +94e7fa32804e73cff91d5bfa140aebbbb55fe6cb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c +f58e104619733d72884d1de3ce89eedacb671595 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h +b6b8b672735a45d7c495bf8af1fa94d1c8e6556c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c +52bc24f91ee7846596274fb2b29654539fd3fa00 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c +35b37030a4086b22b7974082589b33ca07ccc8bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c +7d5189099e205be2e0420013770668fb8b96e133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c +7e3b18d1139373153529a43d88c469da845d393b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c +74a3e6c966c47167bebd7abdfb17797124ee9279 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c +1c390c99fc7405c9a44b4117383cce7de291c13e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c +4a66a4eaba41707a706d22a724ff5853260d070c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c +2c9f36c79b5d80fe13893b8c9b9f9c94273c1c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c +70de120b27bf3bf6917bf2a9536aad6fe8536358 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c +784083a6783d1d5de48e4b5a95ccb43b8103bfff - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c +8c5a81c2b54db7d09ea4a08a43171c7f9ed3cbe7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c +b0822433062f48471e106e268f79f079d1a1cd55 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c +d8fc85a2746e3c31e70de675027af01735ba105f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c +7dc9295fddc66cd74761fa03a90c65985b964c08 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c +cc1a5d99c9f6833e79108373c21162c7fb65a742 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c +868cee0046c6b1426f45136804fd662b030f263e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c +52fee0fd73c94d2e2f5a21a55f082e1963b1569b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c +67e0a5407af29f70e8a1cd10563b7aaec9ccbcdb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c +7c65ad2301cc6e79aa3392bdb9010a7ce81b0c38 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c +94e7fa32804e73cff91d5bfa140aebbbb55fe6cb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c +ade8c323e356c3e70af2424ed9e2ca0ccabc68c5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h +b6b8b672735a45d7c495bf8af1fa94d1c8e6556c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c +52bc24f91ee7846596274fb2b29654539fd3fa00 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c +35b37030a4086b22b7974082589b33ca07ccc8bb - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c +7d5189099e205be2e0420013770668fb8b96e133 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c +7e3b18d1139373153529a43d88c469da845d393b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c +5e2ab65ab8c5b830b547afdfac8b72c1a7b193f5 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c +1c390c99fc7405c9a44b4117383cce7de291c13e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c +4a66a4eaba41707a706d22a724ff5853260d070c - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c +2c9f36c79b5d80fe13893b8c9b9f9c94273c1c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c +70de120b27bf3bf6917bf2a9536aad6fe8536358 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c +93bd291166335a88ca0721d5beaebd9599a2475e - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c +8c5a81c2b54db7d09ea4a08a43171c7f9ed3cbe7 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c +3b12a5a00c5ee315f9665165cc0160e7e4e7b946 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c +d8fc85a2746e3c31e70de675027af01735ba105f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c +7dc9295fddc66cd74761fa03a90c65985b964c08 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c +1afdc66c33767a868d162893776bf6d3ba9f1247 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.h +8450fc5ca89f94b128b1d1d4608903ffd0de498b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h +5ab0e0aaf3ae2f7637cf1c42709cdad267a20850 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat.h +0d0858bee5e0636c53a6f5b4a484f08b979495a9 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitives.h +3b6c666fa3fd1fcdb96504690f34db6740d85b2f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h +2b66ebd06a1b0c7e7626aceab2192011d72a70ab - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/Makefile +39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/platform.h +6be19d4409b8a6cafc0be14b9b5ffdf052c7b25b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/Makefile +39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/platform.h +6cbdecb56028446ec09651ef96ade55402b23a2d - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/Makefile +39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/platform.h +fc40163df60fca883cf8105128b0e2044b4e5c95 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/Makefile +18484ed24a14a759985a39574bf4d1c56cfe1939 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/platform.h +19237050b884871548365d61622e85253f30ffd1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/Makefile +18484ed24a14a759985a39574bf4d1c56cfe1939 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/platform.h +140c840a66dc59f8b8460c7e18349faba5989be1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/Makefile +39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/platform.h +140c840a66dc59f8b8460c7e18349faba5989be1 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/Makefile +39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/platform.h +6be19d4409b8a6cafc0be14b9b5ffdf052c7b25b - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/Makefile +39cb04a350a785c8fb1feeb91759b428750191ae - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/platform.h +90d2bc9a9afc3396f0a2271c1d79a76287c2516a - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.html +75e9aa350d3aae45b151a9bbe2f6e70ccad11c7f - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html +9170d3167dcd72c685ebc6ca6250eee2eefd0c45 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-source.html +cbaa68e47415bdb2b68ad13c2037e03cd231fd60 - optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/arm32_include/platform.h +f1ba2ffbb8b80c3d2c8baf5ad09f2d1883ccc95e - optee/optee_os/lib/libutils/isoc/include/wchar.h +eb700f736fea47a51c03069d099ff492d566f45b - optee/optee_os/lib/libutils/isoc/include/time.h +15ec9c6af06bd04877ce230bac8bfa3ce26a23e9 - optee/optee_os/lib/libutils/isoc/include/unistd.h +9edc066dbedabb03c6479c2dfc962125c09207b5 - optee/optee_os/lib/libutils/isoc/include/memory.h +b704c2144f4058cc83eff91c732a965487af7f2f - optee/optee_os/lib/libutils/isoc/include/signal.h +9978646994c635cccfd0082f5e183aa8817ee114 - optee/optee_os/lib/libutils/isoc/include/setjmp.h +d107150611ad4db054a4c134a03cb4072e5b978f - optee/optee_os/lib/libutils/isoc/include/strings.h +5fbd70f4fe7a023e3b9c3c6997b0cc042bec58d8 - optee/optee_os/lib/libutils/isoc/include/inttypes.h +7146a287e1507a73b42aa6ae46d72881a5b318a8 - optee/optee_os/lib/libutils/isoc/include/stdlib.h +1b5da4e5962171c39a2b4762a169e12e50dd6641 - optee/optee_os/lib/libutils/isoc/include/stdio.h +0e27c8f74b3f066a60b8b79fe1951ecc76c12fb3 - optee/optee_os/lib/libutils/isoc/include/malloc.h +353c7b2a8c73f6458ed0e92d380fe01ff4dea900 - optee/optee_os/lib/libutils/isoc/include/assert.h +e7fdba9acf2bc6ddc6d25cd852eeff72855d143d - optee/optee_os/lib/libutils/isoc/include/limits.h +e83da5f07c33bc84bb291affe6480214bb4e6f9a - optee/optee_os/lib/libutils/isoc/include/ctype.h +44f78c63d935ad93ce68039331f214dcc699f6e1 - optee/optee_os/lib/libutils/isoc/include/stdint.h +8629e94b3bc7a9b628d559492f6859405e065233 - optee/optee_os/lib/libutils/isoc/include/string.h +ea09b9213223627399f059ff48bc083ac9652a96 - optee/optee_os/lib/libutils/isoc/include/sys/queue.h +f39fd14f91c4f1b1a6c2636a7abfaa0cad378a37 - optee/optee_os/lib/libutils/isoc/include/sys/types.h +e646420d5133d287b223a251d711caef5077d8aa - optee/optee_os/lib/libutils/isoc/include/sys/cdefs.h +cd3c2b81c2fa7237a975213bafcf7ac4e67ff177 - optee/optee_os/lib/libutee/tee_socket_private.h +6a2bd30d6d4442e50515c09a081afd22562e62a8 - optee/optee_os/lib/libutee/base64.h +2a8949363bf9be408cbddf09c072982132988ffc - optee/optee_os/lib/libutee/abort.c +4a67c07665addfbe2d7f5a4405dc1cb2b8a44f45 - optee/optee_os/lib/libutee/tee_api_arith_mpi.c +55c2020c1066f0e0ccee7396effb27bc63af0b5e - optee/optee_os/lib/libutee/tee_api_operations.c +8fa85961841aca5f32b051d7c2137dce6048c90a - optee/optee_os/lib/libutee/trace_ext.c +9389ec3691da465689f9ef3c7e4a843bdad07389 - optee/optee_os/lib/libutee/tee_tcpudp_socket.c +b692cdf8031f1a5f56a40e3a331b86bf6ad0c81f - optee/optee_os/lib/libutee/tee_api.c +3cd93276aee5c3e854a28469d4249e285836e0cc - optee/optee_os/lib/libutee/tee_api_property.c +077681c818e3003b52065a80dbacbd498dff6b29 - optee/optee_os/lib/libutee/tee_api_private.h +61ba39ae5f3db7e446666d29227a87474f4a6117 - optee/optee_os/lib/libutee/tee_socket_pta.c +756eb32d34c8adc8518381acb1da0e71abfc07c9 - optee/optee_os/lib/libutee/assert.c +b1398a9a37ee47f2718169316310a4a16c61166c - optee/optee_os/lib/libutee/tee_uuid_from_str.c +dc820097b9daaecdbebb44d2745b59ab6c868b3c - optee/optee_os/lib/libutee/user_ta_entry_compat.c +bc9153018927868009fb5a5e6df2a409ecb13f4c - optee/optee_os/lib/libutee/tee_system_pta.c +45c1ba4438be0ecfb4d4bca51534640836b8c995 - optee/optee_os/lib/libutee/tee_api_panic.c +505da116e55bfaee3c94a6db710ef70a860f9bf1 - optee/optee_os/lib/libutee/tcb.c +b4d75c22cea319de57b7d095ce76316fa38d1506 - optee/optee_os/lib/libutee/base64.c +8b5165f5a04ab8a7602713559fe272670f5b5aab - optee/optee_os/lib/libutee/user_ta_entry.c +de26a71b90cb412c9efc752727836f54fb1d95b9 - optee/optee_os/lib/libutee/tee_api_objects.c +b2ceb3db7e2bb09feef1e3551cfe2f2000b8bc66 - optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S +137080dcbc697e48f567709fe3fda2528f5d40fa - optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S +b1ff8027d8f72d6043aefff12c169937335d77c2 - optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a32.S +a2170433362124e5401cea1cf6f4dafaca653856 - optee/optee_os/lib/libutee/arch/arm/gprof/gmon.h +2e2b03efa22c915b6ab0a59c54793e918ae83560 - optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.h +16e0dc83cf08600fd769832ff1d21611782da066 - optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.c +1a3e524ad810227480d10b0d8426c780c85328bb - optee/optee_os/lib/libutee/arch/arm/gprof/gprof.c +be6fc3000484b65889ef0ddf1e7a926e364575a8 - optee/optee_os/lib/libutee/arch/arm/gprof/gmon_out.h +80eb8b37eb87886d40dc390c74bfae90f83ea208 - optee/optee_os/lib/libutee/include/pta_socket.h +a990d751d99ca55773e11d46acf4794e93181cf6 - optee/optee_os/lib/libutee/include/pta_benchmark.h +1ee95d67db99aa4b7dab212672290e1dcf51e1e6 - optee/optee_os/lib/libutee/include/tee_api_types.h +7812d9a6cf27c9c8cb718a2a8824323576ccaf38 - optee/optee_os/lib/libutee/include/tee_api_compat.h +0311b7bfd98a444eeef7c7c89d4e942a84ea6787 - optee/optee_os/lib/libutee/include/tee_ta_api.h +ce4bc2d3ed7f6c3ecb68a1f98a7f368f7369a286 - optee/optee_os/lib/libutee/include/utee_syscalls_asm.S +398b00b2fdfc1d0dd1987e95722a21a6de7413bc - optee/optee_os/lib/libutee/include/pta_device.h +f5d83909e5071e2affc98fc56ac4b941e00ef03a - optee/optee_os/lib/libutee/include/pta_apdu.h +d6494aea8b2d08af66c5b03901a962d4c23afa5c - optee/optee_os/lib/libutee/include/pta_secstor_ta_mgmt.h +f4adab9015698b3a5ad156216c44340a86567794 - optee/optee_os/lib/libutee/include/link.h +dfe89d4404a213f5751887db149a30135cd07f9a - optee/optee_os/lib/libutee/include/pta_scp03.h +793d80272b98715200cd83435c35de534049b96e - optee/optee_os/lib/libutee/include/__tee_isocket_defines.h +bc735eb7fc5fe9fa8e31ddfe2f98dca62b95ec9e - optee/optee_os/lib/libutee/include/tee_arith_internal.h +d6461788cfe9c7fa1812938fccf00428981ca21f - optee/optee_os/lib/libutee/include/pta_rtc.h +0914ffb8eea917ca32ddfd5e9d1e07b08242a132 - optee/optee_os/lib/libutee/include/elf64.h +5e23b121b492913159ac492c975bc689fe4fe9d5 - optee/optee_os/lib/libutee/include/utee_syscalls.h +47e7cf8af6ad09392aa45b94e88e4cc07e54520e - optee/optee_os/lib/libutee/include/tee_syscall_numbers.h +aff5768a908441b37ad3a28350e0b0f6bf0007b0 - optee/optee_os/lib/libutee/include/tee_api_defines.h +aa09af74960113ccd4fb8827d07e4b9140aacf8f - optee/optee_os/lib/libutee/include/arm_user_sysreg.h +1cb2546168ca45afe3e8ee0cd818c13e6019c425 - optee/optee_os/lib/libutee/include/elf_common.h +62fdcf80906b4877ba0a4d22e69a0c75e98e8b9b - optee/optee_os/lib/libutee/include/pta_imx_manufacturing_protection.h +34686e9ef3d016d68cb94ca12b860c89349b5eca - optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines_extensions.h +9c2c1f4769d19646dfe1493dfaa1007b8c538af0 - optee/optee_os/lib/libutee/include/rng_pta_client.h +5d2f8542dbd85a819207cf9201d5c104d1f45799 - optee/optee_os/lib/libutee/include/arm64_user_sysreg.h +989a3f3ba297d8913c040b838c9cab1a5103308f - optee/optee_os/lib/libutee/include/pta_attestation.h +41b79406ff05bc4d3528fca688813e7f88e7d135 - optee/optee_os/lib/libutee/include/tee_isocket.h +ebea83d32048f9808bd31f5e2dabc5c0314057bb - optee/optee_os/lib/libutee/include/__tee_ipsocket.h +376f36da862c7024aec13565c1d6af9518cf3f01 - optee/optee_os/lib/libutee/include/pta_jetson_user_key.h +8572ff4140b947a4e4a4b5752d8265fe1ea5b348 - optee/optee_os/lib/libutee/include/pta_scmi_client.h +d1eb626d04bb19cbf07f7e9b1a69eaf8593b16ce - optee/optee_os/lib/libutee/include/utee_defines.h +083e406c1b8993f6c0226bf312fcd140b1bc2cc4 - optee/optee_os/lib/libutee/include/pta_imx_digprog.h +5a4c5c4386df019b937e53bdfca5e05bf5f10921 - optee/optee_os/lib/libutee/include/pta_invoke_tests.h +faeceac8862bbe02c984a8839b1e1cae06319dba - optee/optee_os/lib/libutee/include/pta_rng.h +8981169f89ce2d195a17112b676bb8552d21ad4c - optee/optee_os/lib/libutee/include/tee_api.h +f6b88edde49c7f79eebc0c3f861b6f19ff685fd1 - optee/optee_os/lib/libutee/include/tee_udpsocket.h +5ca4833e2188ae7c12e8b39f0448c7f3627571c7 - optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines.h +bfd21882753009a9bff306c49ea3d6ba0a27715d - optee/optee_os/lib/libutee/include/pta_stm32mp_bsec.h +0f06e417dc0b4434790db823616a67697a157404 - optee/optee_os/lib/libutee/include/__tee_udpsocket_defines.h +ed871d9884b5e4c5c7801d8dfc5f77f30d79d4ec - optee/optee_os/lib/libutee/include/tee_tcpsocket.h +8ddaf3ec29e785a63a8b8ba266c13abdce68c125 - optee/optee_os/lib/libutee/include/elf32.h +c603b51b2bfba8baa7cb2c4dfbaaa421d9461207 - optee/optee_os/lib/libutee/include/tee_api_defines_extensions.h +6cf7866d8d5f2388b28df78b419553de615ec055 - optee/optee_os/lib/libutee/include/user_ta_header.h +591d4ed947e32e0c72a95a7a2514221f1cf9490d - optee/optee_os/lib/libutee/include/pta_gprof.h +e3514bd732b3d0be323aae77cdfcbfb736b42fdb - optee/optee_os/lib/libutee/include/tee_internal_api.h +c4e212610ccdc55f55421917a843a5b8ddb567c2 - optee/optee_os/lib/libutee/include/pta_imx_ocotp.h +9155ede1378206e1762eb2696d1589cb2b620ee6 - optee/optee_os/lib/libutee/include/utee_types.h +aa7d01574e3506e0ee2f42cdb251145908b75381 - optee/optee_os/lib/libutee/include/elf.h +5e08d24c95ed9a2dbbcf69ef3896898ad97abc8a - optee/optee_os/lib/libutee/include/tee_internal_api_extensions.h +24acf5f9664ccd81af1147a5e2f875e5a303d97a - optee/optee_os/lib/libutee/include/pta_system.h +d84b15deba3ac3edfa192902098d7b012e19893c - optee/optee_os/lib/libutee/include/k3/otp_keywriting_ta.h +739a223e693f30815eb57c7b1bdae6bc5e2c8028 - optee/optee_os/lib/libunw/unwind_arm32.c +a7b80ca6cb33642237a2a0ecfdc7ad3827cef4c7 - optee/optee_os/lib/libunw/unwind_arm64.c +62096636f7a228af8aad98afd445a8ce4e9ba81a - optee/optee_os/lib/libunw/include/unw/unwind.h +d3c54bb6b126358f60fecee23a0d6064d3ad12e0 - optee/optee_os/prebuilt/t234/libcommon_crypto.a +4ec1a9b7d2f64d94ccdaa889afe2cba025e5b33b - optee/optee_os/keys/default_ta.pem +91c83678702ef358777559205b8c2c775789c87a - optee/optee_os/ta/user_ta_header.c +32f326f4c0f102b4ee4c9ba88d7d1760b803237c - optee/optee_os/ta/pkcs11/Makefile +a6e947a9f3f7337320b8940c40d8441cb477073a - optee/optee_os/ta/pkcs11/scripts/verify-helpers.sh +e766a0c478f5e52ce2ea56f842f8e012f68427af - optee/optee_os/ta/pkcs11/scripts/dump_ec_curve_params.sh +5329b77d3056c08cdeb14ecdea7b81110262fc24 - optee/optee_os/ta/pkcs11/include/pkcs11_ta.h +b10094c63a4f11d5d590d53e1c73d6f587d0dfdb - optee/optee_os/ta/pkcs11/src/attributes.c +b44775c01d993d49402ab222d398850976d8bbc9 - optee/optee_os/ta/pkcs11/src/object.c +4b7dbda490ed1c5ac55d3357b440a8f012c647d5 - optee/optee_os/ta/pkcs11/src/persistent_token.c +5f8de729864d1ad926d2f9ec4ef37e8ff38ceb70 - optee/optee_os/ta/pkcs11/src/serializer.c +eb55922796647a3afae81a788f1ce67eaaaba09d - optee/optee_os/ta/pkcs11/src/sanitize_object.c +9ba0514e3a2e9581cf9564462df013a0494f745d - optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c +aee16d7bf1c5d2a0c39c6a5112cec71f528421b3 - optee/optee_os/ta/pkcs11/src/user_ta_header_defines.h +0e3dca0597af48781c952400ea4ecad857110eef - optee/optee_os/ta/pkcs11/src/serializer.h +9e799d40bc5157fad91180105d091bf81c2695ab - optee/optee_os/ta/pkcs11/src/processing_digest.c +26dc92427964930f69b616be7c77b90da4bcb8df - optee/optee_os/ta/pkcs11/src/object.h +2a2615470b5e9f0946dbf9e32ee11fe0b4dff621 - optee/optee_os/ta/pkcs11/src/pkcs11_token.c +fb13a7d2381ef0bc40438bc32f4406ee2690d914 - optee/optee_os/ta/pkcs11/src/processing_aes.c +0aa2868227123053da7d9368bc3640a839d4e682 - optee/optee_os/ta/pkcs11/src/processing_rsa.c +aaff008a064e973b8f57ec40853d5935a7fd36cd - optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h +a199684d2e257ba2568ad8c8d6788b9e4e8abcab - optee/optee_os/ta/pkcs11/src/token_capabilities.h +c1bc93345d7db093a5ac9ce255a1f1b9b04f9b41 - optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h +8d8b0a84e056fa008bf4be504cddf4b5f059389a - optee/optee_os/ta/pkcs11/src/handle.c +f5f2eae047cb155a42ed528fb8b2f574970fe2a2 - optee/optee_os/ta/pkcs11/src/processing_symm.c +5cf92c8affd431f709ff970b2f42fab1b0a96ad2 - optee/optee_os/ta/pkcs11/src/processing_ec.c +deec6a53392a9c38fca095c61a072b80ec426224 - optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c +0ffa60c477bc8ee08f506cf0302096d0982314b1 - optee/optee_os/ta/pkcs11/src/pkcs11_token.h +03111d59e4b6c3a54517680ae126d3498a8d2b9e - optee/optee_os/ta/pkcs11/src/processing.c +406de9608e4061b2c61b5af8605bcd7f389e4bf3 - optee/optee_os/ta/pkcs11/src/handle.h +8a63bd474856b01d14303d306048e3981ddf19c4 - optee/optee_os/ta/pkcs11/src/entry.c +4ad6fb1144fae7c02fd7ef269c1a4af2c25ca38c - optee/optee_os/ta/pkcs11/src/token_capabilities.c +f96d820c677acbc73e09670a4747a0c925f319d2 - optee/optee_os/ta/pkcs11/src/processing_asymm.c +84b21a00a4d1908760573381497ecc1584892ee3 - optee/optee_os/ta/pkcs11/src/processing.h +894d688c805cbbca2bde46ae5dfcf38092d7e8dd - optee/optee_os/ta/pkcs11/src/attributes.h +9d7de06484bf080c9fb9d2922ea6a4d808edce81 - optee/optee_os/ta/pkcs11/src/sanitize_object.h +353da6ac448fb9756cfa1b97c162df13d0174fac - optee/optee_os/ta/arch/riscv/ta.ld.S +44f007aca97998b425d27b7af67779c039d4d8d7 - optee/optee_os/ta/arch/arm/ta_entry_a32.S +a5b56b622eb2fde139565fba51a74c5de3806afe - optee/optee_os/ta/arch/arm/ta.ld.S +78100b9031d82bc62fe38e0650f780d2c18f2f5b - optee/optee_os/ta/avb/user_ta_header_defines.h +cc0a07d6f59b29a9ec0e01f5ca6a378b3d445248 - optee/optee_os/ta/avb/Makefile +49328831e03037ff1c84c1721fb97905781904e0 - optee/optee_os/ta/avb/entry.c +04d61d12d0b618ec98f1f36f7aac7e7f6a0bada7 - optee/optee_os/ta/avb/include/ta_avb.h +b28af208dabadef396024e4007f36154699e975b - optee/optee_os/ta/trusted_keys/user_ta_header_defines.h +50fac4ba9aede25524155ad8cd8cdd905f195a87 - optee/optee_os/ta/trusted_keys/entry.c +8ff25744520aea7259967d34911798667d2cf6fd - optee/optee_os/ta/trusted_keys/include/trusted_keys.h +bf52776d687b57bc5e886b2f4e7a0f7ece62b0b7 - optee/samples/Makefile +b2def2faca96323618fae5d302c50260bccb869e - optee/samples/LICENSE +22d6ec718c65f0f1fab50d6a32d64857f975eb83 - optee/samples/hwkey-agent/Makefile +d641b8218d5f3af3869eb24210d632d9accc789e - optee/samples/hwkey-agent/README +b2def2faca96323618fae5d302c50260bccb869e - optee/samples/hwkey-agent/LICENSE +d8d2851c68cdbcc9138bf2542d445f73ab2ebe44 - optee/samples/hwkey-agent/host/Makefile +59f6594fdd5e77aaf03788a08a39999ffd8b86e5 - optee/samples/hwkey-agent/host/hwkey_agent_ca.c +3e73868f9048110e8fce23a71343f5d0db256281 - optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh +04735615008d1c575afd724156b78c21d77766ea - optee/samples/hwkey-agent/host/tool/gen_ekb/README +e000cd877e89200d16afabb3f5778d4ce0bc072b - optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py +65d0125074f02769fd68a3b9db5c1f440a076ec6 - optee/samples/hwkey-agent/ta/hwkey_agent_ta.c +01a5ebf5ecbf58a06002ad10b902e18d78d452d8 - optee/samples/hwkey-agent/ta/user_ta_header_defines.h +5054796c29272096d67dbf4fa7453f9bfa3ad280 - optee/samples/hwkey-agent/ta/Makefile +f1652fd24c49bf7be742b2e2081280bcd33d2ddd - optee/samples/hwkey-agent/ta/include/hwkey_agent_ta.h +85cb555a484a3191da2b234f4c2121addebc83a5 - optee/samples/luks-srv/Makefile +6fb1ad386475e975804bd789938f171a0e634bf9 - optee/samples/luks-srv/README +b2def2faca96323618fae5d302c50260bccb869e - optee/samples/luks-srv/LICENSE +ba0f3f4839fe17b652aa8a9e18d0f5fe602f4662 - optee/samples/luks-srv/host/Makefile +8577e960a7ba6fea952165100b467fd6b4fb1902 - optee/samples/luks-srv/host/luks_srv_ca.c +6d3ac3cebb74c4f088accfac2d48654ea788769b - optee/samples/luks-srv/host/tool/gen_luks_passphrase/example.sh +42761539497633e52d70529a0c963678c1e2b9e8 - optee/samples/luks-srv/host/tool/gen_luks_passphrase/README +ea3aeef7e946314ca0a3dc1f6b2c64099963b8e8 - optee/samples/luks-srv/host/tool/gen_luks_passphrase/gen_luks_passphrase.py +9198ad9d0108d1f0c5411e43cfcdbbb011dc6ddd - optee/samples/luks-srv/ta/user_ta_header_defines.h +7dcf0c69657674d5c8d84f037993856ccdabf784 - optee/samples/luks-srv/ta/luks_srv_ta.c +fa3f0583c33f15560475d2899643217e9b8bdedd - optee/samples/luks-srv/ta/Makefile +80db8ae67e3a08227b8feeb7c71d80c97e620988 - optee/samples/luks-srv/ta/include/luks_srv_ta.h +21ee084c6b208974935df6b5626f27e4cbb8e053 - optee/optee_client/Makefile +1be3a93bb56c46ee4d4693b47ddd7c4c5487ffd3 - optee/optee_client/README.md +a7d910ff308216f427e9a4776d72cfe84e2915ad - optee/optee_client/LICENSE +c9b3bb5ab0a3d0252ed93cfc3578e3991ee2b994 - optee/optee_client/typedefs.checkpatch +c9c46f6d84c395db9e62599d15980f06cf993db7 - optee/optee_client/libckteec/Makefile +f25fe667d7155f39694414e63dac8d54adb5e264 - optee/optee_client/libckteec/include/pkcs11_ta.h +7d66a5a9955374f577b36eda3684c254841edbda - optee/optee_client/libckteec/include/ck_debug.h +cbd1cf1d939303ee17050057c176ddb7498b1598 - optee/optee_client/libckteec/include/pkcs11.h +53de33af06e51fb21fe2f24c2c0665a45baeb3b8 - optee/optee_client/libckteec/src/ck_helpers.h +a4b2b6fc00af2b337386db3fc110f54709a248bb - optee/optee_client/libckteec/src/serializer.c +28f837a80c95ceb3f72437386993f46469f861e9 - optee/optee_client/libckteec/src/serialize_ck.h +4a7c34adbc6006ef9230bb1919ca520891b9823a - optee/optee_client/libckteec/src/invoke_ta.c +e640a280681f076f112beee518ea1adff965c818 - optee/optee_client/libckteec/src/local_utils.h +0db1379449cb2cdae53a7b480a402e8c43457431 - optee/optee_client/libckteec/src/serializer.h +a36127385f3d497598291e167cfc4147e48861ed - optee/optee_client/libckteec/src/pkcs11_processing.h +af95d0df955aaa2ab03f767ed5368a2d461eb337 - optee/optee_client/libckteec/src/pkcs11_token.c +48b8562a4200b00fe6382797789d8e694186c620 - optee/optee_client/libckteec/src/invoke_ta.h +04e59fc9b03985ed9c71fb751bcf60dc050aa517 - optee/optee_client/libckteec/src/ck_helpers.c +f88324eb36dec1f8579a56f5e446475ced59b52d - optee/optee_client/libckteec/src/ck_debug.c +ff70441ef0fe6caa58fb618ff6343691f6a5440f - optee/optee_client/libckteec/src/serialize_ck.c +178b53aac43cdfc719b04be256672168226a3e4e - optee/optee_client/libckteec/src/pkcs11_processing.c +3d1d16bc8a998c7382d0e5deb177e421613cbdb9 - optee/optee_client/libckteec/src/pkcs11_token.h +145e33a2859354e90473957df5bdd430b63f437c - optee/optee_client/libckteec/src/pkcs11_api.c +d6e6c51b13d0f6f61ae51ff3da8b8f51b3ac433e - optee/optee_client/scripts/checkpatch_inc.sh +668dfffd684890e7dd9bedbfd635db0df9af35d8 - optee/optee_client/public/teec_trace.h +5009e68a037662f4c9aa73a569a2ffa76983dd05 - optee/optee_client/public/tee_client_api.h +43da45835976c93e70ec5ad1ed02b891a0dbe000 - optee/optee_client/public/tee_plugin_method.h +08cc148a2aa7668b539ec815dcfcd4ba6ee64ca1 - optee/optee_client/public/tee_bench.h +c6e011ef6751f07449bffe9fd19006a15b8624b5 - optee/optee_client/public/tee_client_api_extensions.h +c2eeeb99eea300a1748db00f9803a548f2282c49 - optee/optee_client/libteeacl/Makefile +ee867d9d7bddd079e18e86b614ddb0951d3a79ce - optee/optee_client/libteeacl/include/teeacl.h +d44856b3c2e641d34dc08c44aa14df8111f0f2a0 - optee/optee_client/libteeacl/src/tee_uuid.c +3842833a20a863d971c8d33f5e101ccc77e88c62 - optee/optee_client/libteeacl/src/group.c +0ddc947d4bafad6f4a3d62517c539706e25b6cd0 - optee/optee_client/libteec/Makefile +65b3d16f29fb30f1241ad61acff018a0dc2e6f88 - optee/optee_client/libteec/libteec.pc.in +6f319e289afeaa66b6058c8f2397e66d4bd79b70 - optee/optee_client/libteec/include/teec_benchmark.h +15278a332dd772f0c91e486e562d10ba1b9cb6df - optee/optee_client/libteec/include/linux/tee.h +67f6aec80cb155ca0bb850b4b38b6cf0042917c8 - optee/optee_client/libteec/src/teec_benchmark.c +d842563e16728b8e4b8e70f1fd7522598235d843 - optee/optee_client/libteec/src/teec_trace.c +72b02b7343819ffef928481f93f3d02afeb55b88 - optee/optee_client/libteec/src/tee_client_api.c +162069bdee10a33e7ff8e9680386d51bd7eaffff - optee/optee_client/libseteec/Makefile +2219ff4dd85f1c6a0ee11024a1834c7d17124a79 - optee/optee_client/libseteec/include/se_tee.h +f5d83909e5071e2affc98fc56ac4b941e00ef03a - optee/optee_client/libseteec/src/pta_apdu.h +dfe89d4404a213f5751887db149a30135cd07f9a - optee/optee_client/libseteec/src/pta_scp03.h +eb52a5aa690916e1cdb6e9d58fd746762ac03bbc - optee/optee_client/libseteec/src/se.c +874f552974cb3d5f17a63dd2ba50582a28e2d28e - optee/optee_client/ci/Dockerfile.ubuntu +2a0b9b82ad279a7127d4fb8fa2c4c4bb0bbfb62e - optee/optee_client/ci/Dockerfile.debian +02f2418592552d63eb73b6480b2b59962b800f2a - optee/optee_client/tee-supplicant/Makefile +8fbfe192d68bdb1e126598cb730e7c11f511960d - optee/optee_client/tee-supplicant/src/hmac_sha2.h +f24b5d7b4681f11f33d735e96c6193f040d61420 - optee/optee_client/tee-supplicant/src/rpmb.c +120c38c9db67c7f01f10865b26742c3d2ae3aabe - optee/optee_client/tee-supplicant/src/teec_ta_load.h +f5b0fdcf3343c38ff2495f438044546952d538e2 - optee/optee_client/tee-supplicant/src/tee_supp_fs.c +5387e1fcf4e95d497b72ee814d729c4c90adb740 - optee/optee_client/tee-supplicant/src/plugin.h +07af4053379b51e5d33dda8ac2eda2181ae23a02 - optee/optee_client/tee-supplicant/src/nvme_rpmb.c +eb428488f05ca6049614557e2a89abbe531b1e24 - optee/optee_client/tee-supplicant/src/sha2.c +2b4e00ad1b9e0f3a5e7c2efbef6591de41a0e409 - optee/optee_client/tee-supplicant/src/sha2.h +ad3a9ab261d5a20d083f5cefdfb13c93c3222cd9 - optee/optee_client/tee-supplicant/src/teec_ta_load.c +a80eb6caf9c8732d74f0fc4c329a4222995ec6c8 - optee/optee_client/tee-supplicant/src/__tee_isocket_defines.h +f04b1790f669de1573516dc81fe3f4eefcb59c1f - optee/optee_client/tee-supplicant/src/rpmb.h +f17cf7d08bb300eb71cf0b2ca503f505c269e761 - optee/optee_client/tee-supplicant/src/tee_socket.h +da6b261a72fe9cce7fef5e8d85d300790dd5b158 - optee/optee_client/tee-supplicant/src/tee_supplicant.c +efbb5dce35c8d8f138142500a0d6ca7df0a01dd4 - optee/optee_client/tee-supplicant/src/tee_supplicant.h +ea069507eb088c8be58fd316e1182d94fdcfffb6 - optee/optee_client/tee-supplicant/src/optee_msg_supplicant.h +593518d07f2abcdc15942f188796aaa0bb12d4c6 - optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h +946a1750a3bd2cb7ee8a0934d7df7849d1649aee - optee/optee_client/tee-supplicant/src/__tee_ipsocket.h +1f145b8b2fe3882017290f627f46dfc328a7c144 - optee/optee_client/tee-supplicant/src/handle.c +4a38f4ea1eea116c78d27b03a2cbfb92f8ea3a97 - optee/optee_client/tee-supplicant/src/tee_supp_fs.h +721aca20ceeacd1648d0f7204c85f69b282fe101 - optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines.h +945a945fa92b85f4b7003123e4ef27a588bdc2bd - optee/optee_client/tee-supplicant/src/hmac_sha2.c +b81a505561be6982f3eea681e266827c8236583c - optee/optee_client/tee-supplicant/src/__tee_udpsocket_defines.h +9763ee4354d75e34559e80fe8dda7bb158c4c5d0 - optee/optee_client/tee-supplicant/src/handle.h +f1107acfa97784e2a91a1a393dd6198fc4a4a222 - optee/optee_client/tee-supplicant/src/prof.h +2eeff0bb8ad1aaf5594e87a9faa9b9bffa63ee8f - optee/optee_client/tee-supplicant/src/plugin.c +a5f3a0cb9e4309400c0c22dc574de3c8eef67a65 - optee/optee_client/tee-supplicant/src/nvme_rpmb.h +a16a80d873293f74d73baf53721eb5019ded25cf - optee/optee_client/tee-supplicant/src/tee_socket.c +bed7d31fece3711cc20a9418d51d24ef7fe3391b - optee/optee_client/tee-supplicant/src/prof.c +1764bfc2b32f604e3b3b7d735ce13aebfbd84d74 - optee/optee_test/Makefile +30a64b524a40d63d6e6f97698875a98100706c59 - optee/optee_test/LICENSE.md +1677c508f843daf45fcf3a1e8c23dacf24f2f222 - optee/optee_test/README.md +9f9d1e370fe395412ffa6a5bc7d21a13586d1551 - optee/optee_test/typedefs.checkpatch +d178f675a81f53b7e725d270b25fadc6b064d6f8 - optee/optee_test/scripts/checkpatch.sh +5d1d72def657b4edb305b87edbff271b1a4e0c81 - optee/optee_test/scripts/rsp_to_gcm_test.py +72d26f74f4c2afb8675278b599c37c055eeeee59 - optee/optee_test/scripts/file_to_c.py +c035f30f1e5286ab496634f87b76fca573244cec - optee/optee_test/host/supp_plugin/test_supp_plugin.c +c6f2d858387614cd7e1ba883db5977638bbcfd55 - optee/optee_test/host/supp_plugin/Makefile +fa35e416cf42119ff66e1a064a4d5db8c785118e - optee/optee_test/host/supp_plugin/include/test_supp_plugin.h +2ede51c8890d3520381c8cbef3b37e41fba5ae38 - optee/optee_test/host/openssl/include/openssl/ecdsa.h +0b02b031e6e3e70e62bf1b49e9c2e1cecfcfc53e - optee/optee_test/host/openssl/include/openssl/rsa.h +d957c5aee3bd2927a6600aa410806835df0afa64 - optee/optee_test/host/openssl/include/openssl/pqueue.h +4b807b363eb139b490d51878492a987b9f0fbadf - optee/optee_test/host/openssl/include/openssl/pkcs12.h +09b47f0d80884577cc93c8a315e2f257f866f71e - optee/optee_test/host/openssl/include/openssl/whrlpool.h +b31cf4d26ccbefd0c519bd475ea515f8cad8be06 - optee/optee_test/host/openssl/include/openssl/comp.h +36fbc7d4b2c4a903cce70e18132610a96a7f605f - optee/optee_test/host/openssl/include/openssl/krb5_asn.h +521646326a376805c0087b4ac4e587e312e48a86 - optee/optee_test/host/openssl/include/openssl/rc2.h +6e2539151422b3aa13de79253cd6ca1c9a51ee0f - optee/optee_test/host/openssl/include/openssl/md4.h +aeca6068019b931b7d13625ebd103d216bca02dd - optee/optee_test/host/openssl/include/openssl/asn1_mac.h +f67566f6be946527f9fd7377f6d0497fe8b46311 - optee/optee_test/host/openssl/include/openssl/lhash.h +007afd8fc88d891a1e00f03bc5a8d4a91d1efb30 - optee/optee_test/host/openssl/include/openssl/dh.h +2b2d1d499c5edf35ef3f9ac62bececf383d41ac8 - optee/optee_test/host/openssl/include/openssl/ebcdic.h +7a76095422e2ee1f5fb153ba7c0c2ef9433ea6b8 - optee/optee_test/host/openssl/include/openssl/rc4.h +8f83d8e48dcc303c8728abdc98037de8201324cd - optee/optee_test/host/openssl/include/openssl/hmac.h +0aa379746d3f24d0b687810aaaf0713ac8d86cac - optee/optee_test/host/openssl/include/openssl/cast.h +2048939555964c40f69cdefc57dcea55871b5e21 - optee/optee_test/host/openssl/include/openssl/mdc2.h +5dbab49158bcb4a23e2a0bf815685b7af61f2deb - optee/optee_test/host/openssl/include/openssl/aes.h +d71fa389c798ef55aeb8e8b585fc1162e31bdcc2 - optee/optee_test/host/openssl/include/openssl/opensslv.h +b57a6862b5e685a8307d9223bb7503a7d455beed - optee/optee_test/host/openssl/include/openssl/e_os2.h +833548d5315aae6cb83981ec70013ca82d8ba523 - optee/optee_test/host/openssl/include/openssl/stack.h +f2d2c1d8957a3a90515fad312be14bd33b7457ae - optee/optee_test/host/openssl/include/openssl/ocsp.h +3990fba87a08e52c857f2d84c339515db4d5961b - optee/optee_test/host/openssl/include/openssl/ossl_typ.h +4617f3f1b34e51a83332ce79f96b7d21ee8850b8 - optee/optee_test/host/openssl/include/openssl/rand.h +1ac129425f344b32376a91e54598a3dfa0f5fd5e - optee/optee_test/host/openssl/include/openssl/pkcs7.h +81b3cbbc6aec76fe305933bb36fbe6cccc40060a - optee/optee_test/host/openssl/include/openssl/asn1.h +37a6ce9452aba6d49d2187b0b511cdc7fbc74f79 - optee/optee_test/host/openssl/include/openssl/des.h +b363b25219a1c9eacee176d89341d73f1c48fc2c - optee/optee_test/host/openssl/include/openssl/bn.h +2ace7c1f67fc524df92ae2ae2664d1c801133683 - optee/optee_test/host/openssl/include/openssl/symhacks.h +fb15a076c1eb0858fe09e6810ad86e3a8991a9ce - optee/optee_test/host/openssl/include/openssl/x509v3.h +9f1ac5a09d7973c8cd30e0298ac1d1be1a0d6886 - optee/optee_test/host/openssl/include/openssl/blowfish.h +4b7d9942149c0c6118f6cfd9c003f90d588296b3 - optee/optee_test/host/openssl/include/openssl/conf.h +d18c728f023f12638001d15986c50433e663a09c - optee/optee_test/host/openssl/include/openssl/pem2.h +7eeea32830643e2f0f4d15395206df2be5df49c4 - optee/optee_test/host/openssl/include/openssl/ecdh.h +dcfb707bab9b356d55f13464fd8d7e11a3bdea22 - optee/optee_test/host/openssl/include/openssl/md5.h +84e95faa34c5a831ee71a5f5dcbb646201b3ebb9 - optee/optee_test/host/openssl/include/openssl/des_old.h +b6b3c01be13efb980c8906da0393538b4c3719c7 - optee/optee_test/host/openssl/include/openssl/seed.h +7244a5772f23284c8bd43229143a1593bb09f056 - optee/optee_test/host/openssl/include/openssl/sha.h +91b236bcae76db131199e0e286ac95943640a75c - optee/optee_test/host/openssl/include/openssl/bio.h +eae391c729397d3c5ad18e6910ce855e200507bb - optee/optee_test/host/openssl/include/openssl/opensslconf.h +eac535357ab50226b3107ae08f15db1a440545b7 - optee/optee_test/host/openssl/include/openssl/srtp.h +7a4605500282f7f93bf6a9d81906d951840f0b02 - optee/optee_test/host/openssl/include/openssl/ui.h +f23cbec4815cddcfe918ef1922900963069b9e41 - optee/optee_test/host/openssl/include/openssl/cms.h +e9da708e470b8d2252e9b09393e5c4580b1f4bb6 - optee/optee_test/host/openssl/include/openssl/ripemd.h +91fd336279423d8e0ccfcd3fe23df9b480034889 - optee/optee_test/host/openssl/include/openssl/x509_vfy.h +54dd565d744fbcfa3e38942843caa0ecc019a910 - optee/optee_test/host/openssl/include/openssl/ssl2.h +3871fe3539f575999166622f5f3295fb9b9ae673 - optee/optee_test/host/openssl/include/openssl/buffer.h +e2ba178670ae93680fb28a3b57fff7f6917355e1 - optee/optee_test/host/openssl/include/openssl/kssl.h +2c6c8cda8629b0d3dda1efc8f1a5ebd445e91955 - optee/optee_test/host/openssl/include/openssl/engine.h +f2463bfe32222c40ede22c3029699bf0a72ebcc5 - optee/optee_test/host/openssl/include/openssl/ec.h +2f638be4aded9c65a4b26ba81b30866b9dd161de - optee/optee_test/host/openssl/include/openssl/pem.h +8950cfbc3480ab12e4820970075260196620fe62 - optee/optee_test/host/openssl/include/openssl/ssl.h +6d1f831d4539dda2a411e59d8a6b796f3182de46 - optee/optee_test/host/openssl/include/openssl/modes.h +5e329424d948cbb1c0d9dd3ebb4186628f2187a8 - optee/optee_test/host/openssl/include/openssl/ts.h +348d7310a404d8ea1ebb6643a5ce6f0825ab9cdd - optee/optee_test/host/openssl/include/openssl/conf_api.h +3983b476f0abceec9b60bb53eebdfe56fad3a5fa - optee/optee_test/host/openssl/include/openssl/idea.h +c8c527ee5e92b3a1ecffcec43a430403632a3add - optee/optee_test/host/openssl/include/openssl/camellia.h +fa9bfab1d6d9e91f5277755673e3cb5b03705e91 - optee/optee_test/host/openssl/include/openssl/dtls1.h +9e6782cd54849b4c6bbdac9bac3bac212a8cec90 - optee/optee_test/host/openssl/include/openssl/obj_mac.h +5ae3cd2824e759e5db6b4db2e8c1822522106ede - optee/optee_test/host/openssl/include/openssl/ssl23.h +23ea4c0c2a08169c3b483dbfc029ad2ca6ffef06 - optee/optee_test/host/openssl/include/openssl/ssl3.h +44533c0a69f2f7b36d3cb7f4b5988f6cdde1ddf1 - optee/optee_test/host/openssl/include/openssl/x509.h +91d7ca042ccce5880c8e269596f308ae0b9ea926 - optee/optee_test/host/openssl/include/openssl/evp.h +b41be35897beb8a5a5e4335933691bb60a0866ea - optee/optee_test/host/openssl/include/openssl/srp.h +71d0dc5dcf2d6f948006266274599e59df948640 - optee/optee_test/host/openssl/include/openssl/cmac.h +a5f237896f32dc70faa6ee3dc24759a9db5aff2c - optee/optee_test/host/openssl/include/openssl/crypto.h +c60c090361a630efae68bdd14760bb2e6562fe41 - optee/optee_test/host/openssl/include/openssl/ui_compat.h +6d98c86e1e6c3cda9df339540539b819f9ee038f - optee/optee_test/host/openssl/include/openssl/tls1.h +ead277c7cf2b9d4210347bbe980c0ea419cd8ad5 - optee/optee_test/host/openssl/include/openssl/txt_db.h +1afa8c4dffa42c03657b47d7d6a317c0d09fafc6 - optee/optee_test/host/openssl/include/openssl/dsa.h +3a84c50fc7a71ea781a04dcd3d1915a83c0193c6 - optee/optee_test/host/openssl/include/openssl/safestack.h +95a13ac793b2a71b4ae39c72da0f18012db54268 - optee/optee_test/host/openssl/include/openssl/dso.h +385087b8e5f37ef32cbbf8af02de4f24acab85df - optee/optee_test/host/openssl/include/openssl/asn1t.h +8a674b7fa0641dff8c2b55e565149cdb3d208fb8 - optee/optee_test/host/openssl/include/openssl/objects.h +dc45fa098993e12071562269ab765bf9160fa670 - optee/optee_test/host/openssl/include/openssl/err.h +386831d0bd03bc34d096121a9412f212a82507e7 - optee/optee_test/host/openssl/lib/aarch64/libcrypto.a +2f90ea6f809369b37a3d482750a9616ae008aa5c - optee/optee_test/host/openssl/lib/arm/libcrypto.a +d9f2461c2a9d755472e666b2c5b60fe21ae7f431 - optee/optee_test/host/xtest/regression_8100.c +4e533d0531c352071ee236302dab1c2fed2068d6 - optee/optee_test/host/xtest/install_ta.h +80a9b9f4795682feb072795a92f15c630eefa57d - optee/optee_test/host/xtest/sdp_basic.h +4ed1b27140db56a58e598a1d47e2eee729363f6c - optee/optee_test/host/xtest/xtest_test.c +032a232dd66725d849cb168cfb5ed48cc19a2023 - optee/optee_test/host/xtest/xtest_test.h +01ce700dbb77213e51c372e4e6dc61082d7da4fe - optee/optee_test/host/xtest/regression_8000.c +12ca0aa8361d1e3bdbf54e11e288ca087745ce14 - optee/optee_test/host/xtest/benchmark_1000.c +3203c2511c56b80cf0757ce40aff2627e1589f54 - optee/optee_test/host/xtest/regression_5000.c +e1fb4f35907beabaf3b0dbe646b45d64d4aa5d03 - optee/optee_test/host/xtest/stats.h +47d40cdaa11a5c163ebe1b3f530bc7706b43fefd - optee/optee_test/host/xtest/hash_perf.c +4f006a99a3d317def8f48cbcd1450ab4132eda31 - optee/optee_test/host/xtest/regression_1000.c +1c0d518167dbd004a55feb971308505c53869a40 - optee/optee_test/host/xtest/sock_server.h +68d3a5e5deb31ba074b1848cf8e1ab7b3ee6606a - optee/optee_test/host/xtest/regression_4100.c +d300a7ef8b1675a42dbf548bc666f0a25b52f241 - optee/optee_test/host/xtest/regression_4000.c +34252d1d1af13adc2316a7646dd79af124e5f2c0 - optee/optee_test/host/xtest/Makefile +6c62f544374fa83651ea1885eee47d0811ed10a9 - optee/optee_test/host/xtest/sdp_basic.c +6074430df45012584a40484c4ed72373bcbbe599 - optee/optee_test/host/xtest/benchmark_2000.c +175414663dc68fd21ab80cf3420337256d7570c4 - optee/optee_test/host/xtest/xtest_uuid_helpers.c +fcc29faa1a7c09980dd59d6d420b3c4c944fa09d - optee/optee_test/host/xtest/xtest_main.c +ee2eb88f341b89c3f0408931d30d5bbf17dd5b1b - optee/optee_test/host/xtest/ffa_spmc_1000.c +14686c51c1e1fc99b03e351c11aed2874aee799d - optee/optee_test/host/xtest/install_ta.c +4cc77b90af91e615a64ae04893fdffa7939db84c - optee/optee_test/host/xtest/LICENSE +5943cfc12866b99e42e14fd92203ed1767ab893a - optee/optee_test/host/xtest/stats.c +4b76e6786bed1ae8da806d21ac567198a5bebdd8 - optee/optee_test/host/xtest/rand_stream.h +aba50362fcc1ac3ba6d33e204435ca7a84cfb20e - optee/optee_test/host/xtest/regression_4000_data.h +f3517bebcb21463533c4004d029833eaf5cde12f - optee/optee_test/host/xtest/xtest_uuid_helpers.h +16276b9d01ba73bf3bb21cb41ff264f3d0126d20 - optee/optee_test/host/xtest/sock_server.c +a611cff7cdaf3b04d87eef15c299048990ec3ea1 - optee/optee_test/host/xtest/xtest_helpers.h +2396216346fc9cde6fa94372e0bb7a14d0bc4fc1 - optee/optee_test/host/xtest/pkcs11_1000.c +9f00cd47e998059a38459f0c6eb06c7b4662bf83 - optee/optee_test/host/xtest/regression_6000.c +d5fc61a73a10975c5945aa67296797824b64b8b4 - optee/optee_test/host/xtest/rand_stream.c +52b11c0af213c40771048607e3da5eb5943e0d98 - optee/optee_test/host/xtest/regression_2000.c +9f2e5d4fab27dc73f38eb0289cd64269900bf3e7 - optee/optee_test/host/xtest/aes_perf.c +d4e67633393e1eafbf02639e218f430a71cb978d - optee/optee_test/host/xtest/xtest_helpers.c +bb316ac26e30020622adeecd07ddf9139e9202c2 - optee/optee_test/host/xtest/crypto_common.h +e6ac80b711f1a44d2eb77e1c618fe7f3270205be - optee/optee_test/host/xtest/nist/186-2ecdsatestvectors.h +a8012c439058a9ab645990d2efcd10447bc34324 - optee/optee_test/host/xtest/nist/ecccdhtestvectors.h +99f104f79f66a659ea913d475077f7503b8a1c51 - optee/optee_test/host/xtest/nist/186-3dsatestvectors.h +dd01f2d86e9e0e0a15aab712c3828f76e4c6e2fc - optee/optee_test/host/xtest/adbg/include/adbg.h +cf415448a59978f2a427eddeb129a7080f5b5dbf - optee/optee_test/host/xtest/adbg/src/adbg_expect.c +f465eee2e09e054182205ae7c53f7253604401b9 - optee/optee_test/host/xtest/adbg/src/adbg_run.c +fd1a3702bdc602b4b70535b00d38b9443e275607 - optee/optee_test/host/xtest/adbg/src/adbg_int.h +bef73e2c136bf2a04bc8cf33b2052afac83535c1 - optee/optee_test/host/xtest/adbg/src/adbg_case.c +e62cdf03f6bf82c09ca10f285a951c1018bbe70d - optee/optee_test/host/xtest/adbg/src/adbg_log.c +877fc553d7b1b08364cb1189bf4cdc3b6cf3c0e6 - optee/optee_test/host/xtest/adbg/src/security_utils_hex.c +4f57fda84526a6b64ecc3eccc008e18b97fc3523 - optee/optee_test/host/xtest/adbg/src/security_utils_hex.h +825ea0288d353fbf26dd5cb0e56be8db4e7bf245 - optee/optee_test/host/xtest/adbg/src/adbg_enum.c +35ce411007e4e624913b8da87f51325be763d65d - optee/optee_test/host/xtest/gp/prepare_suite.sh +78e225e2b8581d7bd917bf1c007f4fee5b1d088b - optee/optee_test/host/xtest/gp/TEE_Crypto_API.xsl +488980fe7c4d8999c8466da403ef5b2811727e7d - optee/optee_test/host/xtest/gp/TEE_TimeArithm_API.xsl +d00562756b00f6607632030c58bbd3576f7c13aa - optee/optee_test/host/xtest/gp/TEE_Internal_API.xsl +39dbed853b87d4a916b95de14d5e23a8f434bfb2 - optee/optee_test/host/xtest/gp/TEE.xsl +baf0c6e02b9300a37bd4409628cea730d71faa5f - optee/optee_test/host/xtest/gp/TEE_DataStorage_API.xsl +c6196ca75d7d48f6e14cc561eefaa9f320adc598 - optee/optee_test/host/xtest/gp/include/xml_datastorage_api.h +93a968118f5345200d7a4d9d78443ada60e64227 - optee/optee_test/host/xtest/gp/include/xml_crypto_api.h +438135b73e49aaad9e34b6863f5bc922f1013b64 - optee/optee_test/host/xtest/gp/include/xml_common_api.h +9d3445c797b4be4516d15baa3e11c682dd8b4918 - optee/optee_test/host/xtest/gp/include/xml_internal_api.h +1af3df59426284098690de7d43586a5e4fd37db9 - optee/optee_test/host/xtest/gp/include/xml_timearithm_api.h +7b0cf45da16221e265fbd01221f541b851cb9e21 - optee/optee_test/host/xtest/gp/include/xml_client_api.h +5bdbfb7c09b73b8ee3f012bb4c05c5655a2e426c - optee/optee_test/host/xtest/gp/patches/0012-TTA_TCF-remove-TEE_MemMove-from-CmdTEEGetPropertyAsX.patch +146a6228e298272ab7e73778962df356d9198311 - optee/optee_test/host/xtest/gp/patches/0010-TEE_DataStorage_API.xml.patch +496f8635c2c0110849cb7e095423e036dae754ec - optee/optee_test/host/xtest/gp/patches/0014-Pass-upper-32-bits-of-TEE_PropSetHandle-in-value.b.patch +705d65243c1e46af9f9642bb84f45b2daeff957f - optee/optee_test/host/xtest/gp/patches/0008-TEE.xml.patch +4f9aca322840391a171d320f3e9d5976b257fa41 - optee/optee_test/host/xtest/gp/patches/0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch +0c86f63bc803a23617fb13ba1479108edaf5dac5 - optee/optee_test/host/xtest/gp/patches/0009-TEE_Internal_API.xml.patch +cbc872e82c403faa84376db8efc78150338e2693 - optee/optee_test/host/xtest/gp/patches/0004-TTA_Arithmetical-patch.patch +c834f47f97dd115566b874fa7e4a6d40d064d939 - optee/optee_test/host/xtest/gp/patches/0013-Disable-Invoke_GetTAPersistentTimeNotSet_and_SetTAPe.patch +163d266dd45cad8536da0f2e1f5c625fc45e2e52 - optee/optee_test/host/xtest/gp/patches/0005-GP_defs.h-enable-debug-prints.patch +f0098e4814dc81f9ecae74036f354210e6c33a50 - optee/optee_test/host/xtest/gp/patches/0003-TTA_TCF-patch.patch +4436ae2a8726be665c4adbc30899d7dbcf721afd - optee/optee_test/host/xtest/gp/patches/0002-TTAs-add-files-needed-to-compile.patch +34223b3e49b6b18b8bf88abf784fac10a0648a10 - optee/optee_test/host/xtest/gp/patches/0015-Enable-compatibility-with-TEE-Internal-Core-API-v1.1.patch +93fe519236e63a82aec4fa2e267aa9c10a9cf3e2 - optee/optee_test/host/xtest/gp/patches/0007-TTAs-revert-to-v1.1-types.patch +cc1ccad0b05569188be42a4e6fad9069b9b44d05 - optee/optee_test/host/xtest/gp/patches/0011-TEE_Crypto_API.xml.patch +aa6291df45558c38403e3272c86920d0441aace1 - optee/optee_test/host/xtest/include/uapi/linux/arm_ffa_user.h +ca513a618e76b7425f4f1350e90c7b74d4778eac - optee/optee_test/cert/my.crt +4c8bd2753f58de91b618d71902216b93834e1b18 - optee/optee_test/cert/ca.key +1f75eacaea5baa5f8ecd35d3c8df7e746c3f73a9 - optee/optee_test/cert/mid.srl +5870a0a431a6e7fd1fb251ada8f25d58c79a762a - optee/optee_test/cert/mid.csr +f11ba7468488761597018fef555faaa8dcf0049f - optee/optee_test/cert/ca.crt +cf7626a2e6fdd3e5cd2455117e6ff59e38cc3a99 - optee/optee_test/cert/mid.key +c858311b53e86391299c5bc0c30a39801b3893a3 - optee/optee_test/cert/mid.ext +6f108292e83a3a3555b56add6fba6bfc75bb1d03 - optee/optee_test/cert/my.key +89bb7582daae987e60e094aebfd5b2b073e9ac62 - optee/optee_test/cert/my.conf +93503a34df30013f6f47e50cde65662d3e5d3a8c - optee/optee_test/cert/mid.conf +6b932b1ab7b3565ddb4557b31b13ff823577f997 - optee/optee_test/cert/my.csr +9162a5682d5d26b3df6021cc646498709aadc3e9 - optee/optee_test/cert/ca.srl +c1c1370410a6251da1f2a65d4bb6799b6695ae46 - optee/optee_test/cert/mid.crt +d9a4193c1df764fc72c7e49efeeb550f84c6dcb0 - optee/optee_test/ta/identity_subkey2.bin +8890459880f4ef0eb20f8a28b727540e789f07a3 - optee/optee_test/ta/identity_subkey2.pem +5d45a78f116ff6a6a5ce6227b1dd705d86a1a640 - optee/optee_test/ta/mid_level_subkey.pem +787a4239906f6e69dc5f12f7eb194950ab92fbdd - optee/optee_test/ta/Makefile +2f0deec19c000366d2fd6d627f9b4363213eef7a - optee/optee_test/ta/mid_level_subkey.bin +494d296fe7e6b7bc0f500a343c6a33cf9f0b05a3 - optee/optee_test/ta/top_level_subkey.bin +525fc4d0105b2261ed118a2d96d2cbf71cba2432 - optee/optee_test/ta/top_level_subkey.pem +c16239ae81d65b85bdbf88f1ec1695ce06a10c24 - optee/optee_test/ta/aes_perf/ta_entry.c +571347fdcd744e2ab03261542891ebb469e61c85 - optee/optee_test/ta/aes_perf/Makefile +7fbb1b605782db00da42f6acd94c45b8535df785 - optee/optee_test/ta/aes_perf/ta_aes_perf.c +837e306e61195565be0391ea2ee9c24557c82908 - optee/optee_test/ta/aes_perf/include/user_ta_header_defines.h +3367296a9f889d9d13d77d03830ca17f9c6786db - optee/optee_test/ta/aes_perf/include/ta_aes_perf_priv.h +24d404e8f61876d1768f09f4d5f698c2fba3fddd - optee/optee_test/ta/aes_perf/include/ta_aes_perf.h +dfa325b63f0b17c8ef3c8e1e055e4f8dc2135812 - optee/optee_test/ta/storage_benchmark/benchmark.c +126f0a0f43f2045ed64ac151420ff2750039cae6 - optee/optee_test/ta/storage_benchmark/ta_entry.c +a7891e77ba72a13303bee70e3469d5b66c4dd0ff - optee/optee_test/ta/storage_benchmark/Makefile +350b57d8d13e85db59890347995fb8b25902941d - optee/optee_test/ta/storage_benchmark/include/storage_benchmark.h +e69f771764df6d0ccfead0a6b563545f3f43b159 - optee/optee_test/ta/storage_benchmark/include/user_ta_header_defines.h +44317f3ee1e0f27bc5889d02e634bcddc250334a - optee/optee_test/ta/storage_benchmark/include/ta_storage_benchmark.h +63727dbe77411a56de4384f2647ac604df1bb77e - optee/optee_test/ta/sims_keepalive/ta_entry.c +3e93b929b783566f5933da6daf3bf178b60f0ac9 - optee/optee_test/ta/sims_keepalive/Makefile +17584ab846d09d2e11a0c62ee9c12f7eb00a89f2 - optee/optee_test/ta/sims_keepalive/ta_sims_keepalive.c +8b0caca8445e731ff595dca61af1768b26fc70df - optee/optee_test/ta/sims_keepalive/include/user_ta_header_defines.h +1b55cdb55165cb46dd80757553d9aab34a61dcd3 - optee/optee_test/ta/sims_keepalive/include/ta_sims_keepalive_test.h +3762c8d8188b6fd5c0e0216aa0dfbc1a81c33bd4 - optee/optee_test/ta/sdp_basic/Makefile +03a7ec19dd525347d073d1ef9887d1c32e2ec843 - optee/optee_test/ta/sdp_basic/ta_sdp_basic.c +a0178fe3ab1e1cd9204c5868dfb36eed00a7d800 - optee/optee_test/ta/sdp_basic/include/ta_sdp_basic.h +9123b67fb31c5aa32dc2d54b9a1d2dcff27b3996 - optee/optee_test/ta/sdp_basic/include/user_ta_header_defines.h +b33588442f2691e00ae34677fee3503279ec4251 - optee/optee_test/ta/concurrent/ta_entry.c +403faf3efbd2a187981acd30a58067dcb43d4d2f - optee/optee_test/ta/concurrent/Makefile +b203b24b6fb092d32555949aece3d104a945d314 - optee/optee_test/ta/concurrent/include/user_ta_header_defines.h +81d9fc2603da64f6aca629d4c1f6152ce40f4299 - optee/optee_test/ta/concurrent/include/ta_concurrent.h +3231e66bc961e72de9759c2d801cf7e081611183 - optee/optee_test/ta/large/ta_entry.c +5558acac0905fc8f55ec7451c6cafff4654c532c - optee/optee_test/ta/large/Makefile +78c0f90194587f8ec4696ed9937eab82bd2d6102 - optee/optee_test/ta/large/include/ta_large.h +04b692b46b7c145c2fe975bb20250626d9e5680e - optee/optee_test/ta/large/include/user_ta_header_defines.h +b0992bc9d242a926b54b8162b36f7f219c278624 - optee/optee_test/ta/os_test_lib/os_test_lib.c +192ebe9f6d76a6b9d3938a69c72663ef7b627fff - optee/optee_test/ta/os_test_lib/Makefile +e0089857c48d5c57869ad4d411a71a2a3ba33f80 - optee/optee_test/ta/os_test_lib/os_test_lib_cxx.cpp +e868bceb0a3e38d9c81f3fece9efc1ced6e9b1b9 - optee/optee_test/ta/os_test_lib/include/os_test_lib.h +fd20f8c7b48682f3cb154209d193c38ef5fa8afa - optee/optee_test/ta/storage2/ta_entry.c +3777dde2c0aee5f993ddf5f6e2899d578554736d - optee/optee_test/ta/storage2/Makefile +b5ccb3b112baffad3e3afb89d72d7cc8a922ce1c - optee/optee_test/ta/storage2/storage.c +1c8f590037f4f9235325a760a6e10589ac820492 - optee/optee_test/ta/storage2/include/user_ta_header_defines.h +8ace73b1298eb7b4679a5f6a93533d147c6165f0 - optee/optee_test/ta/storage2/include/storage.h +739bf20897d248851d4e26908cc4a58f70ff9e98 - optee/optee_test/ta/os_test/ta_entry.c +c845f1bef062d33dd7e59d0647155b05ef5ed6ac - optee/optee_test/ta/os_test/attestation.c +a4ae385c460bad98c3f1bb74e4cd6d78a3d1c569 - optee/optee_test/ta/os_test/cxx_tests.cpp +0821f97bb6d0e672f229f163d91a44db3b3cfc21 - optee/optee_test/ta/os_test/pauth_a64.S +0455da7d426f2d9c91e8d1f0ceedcbcdc25b7e63 - optee/optee_test/ta/os_test/cxx_tests.h +efba276afd39d7103c04a55a36060b6da949183b - optee/optee_test/ta/os_test/os_test.c +81b48e32f421e3809c799370e7d5a84be82e4007 - optee/optee_test/ta/os_test/test_float_subj.c +e00637d3dc4e177f4693a591711c655a84f82c6e - optee/optee_test/ta/os_test/Makefile +30c95077d893a72f6dd6f25698b9e3c4c90c7173 - optee/optee_test/ta/os_test/ta_arm_pauth.c +f99ecd7a7d1466b6ae095553f19b144a3b5e05a6 - optee/optee_test/ta/os_test/cxx_tests_c.c +4b24fec7bb0779f54df830b2accd4589c58ee714 - optee/optee_test/ta/os_test/test_float_subj.h +7c34f62620b2c3cf1e435dc2f06b5bc695a0ffca - optee/optee_test/ta/os_test/init.c +9f19100db2cc1610f815fafd087f583d78880d0d - optee/optee_test/ta/os_test/include/ta_os_test.h +c250edae8e50b81ddc7f2d82b74533be8ce36484 - optee/optee_test/ta/os_test/include/user_ta_header_defines.h +9a31e7f47747984b55fcfd8f87f8c3eda3903943 - optee/optee_test/ta/os_test/include/tb_asserts.h +263c19c932534cb04ff5681cf3331201d72711ec - optee/optee_test/ta/os_test/include/tb_macros.h +ef669e3a5af86a9d7433680efe47e7475ebae840 - optee/optee_test/ta/os_test/include/testframework.h +dfa926eae1baeaa723c73c36a5a87108a941f0a8 - optee/optee_test/ta/os_test/include/os_test.h +c0f2b4917d2e7e2c64767ce20c51277d030da95e - optee/optee_test/ta/os_test/include/init.h +615513981a90fabad2bd36d67b4ece7b3e63bfe6 - optee/optee_test/ta/supp_plugin/ta_entry.c +e3deb7bd3c13099679c0218b2daabc17547fb2aa - optee/optee_test/ta/supp_plugin/Makefile +97d8481ac3b8dd32d148d69acc3da07308fb759a - optee/optee_test/ta/supp_plugin/include/user_ta_header_defines.h +a6d7b87593d95249d1adf41e1ed2855be8557092 - optee/optee_test/ta/supp_plugin/include/ta_supp_plugin.h +f041af378514b0adb83e13683c439bdfda633a38 - optee/optee_test/ta/tpm_log_test/ta_entry.c +159ab9161f614e0e78c7ed8ad589b1da7dc49313 - optee/optee_test/ta/tpm_log_test/Makefile +05d9586c179dfa463023108f57186c397f67b168 - optee/optee_test/ta/tpm_log_test/include/ta_tpm_log.h +15979122b263375291e30ed248816c707e51aa9d - optee/optee_test/ta/tpm_log_test/include/user_ta_header_defines.h +071de3ab826aea3082b54036a436e42d20e5e829 - optee/optee_test/ta/tpm_log_test/include/ta_tpm_log_test.h +63727dbe77411a56de4384f2647ac604df1bb77e - optee/optee_test/ta/miss/ta_entry.c +6902d41cad5e1a7fdd792070ee6fe09543fd0a36 - optee/optee_test/ta/miss/Makefile +17584ab846d09d2e11a0c62ee9c12f7eb00a89f2 - optee/optee_test/ta/miss/ta_miss.c +7577f16d52d892d26d2aba97100c391696f1b4e0 - optee/optee_test/ta/miss/include/user_ta_header_defines.h +e8cc80687d4a1d454c124c0288798e280142a723 - optee/optee_test/ta/miss/include/ta_miss_test.h +246ca7646c82ccb61f14a0b439ec943d8850f0dd - optee/optee_test/ta/storage/ta_entry.c +a29dec4b78281324f1e479a7648b636feef1d163 - optee/optee_test/ta/storage/Makefile +9fdefd261cbb4dfe3fcdfb05749fd3acaa8383bb - optee/optee_test/ta/storage/storage.c +cbcf995c4fce7f48869248f9f3bf912195d4873e - optee/optee_test/ta/storage/include/user_ta_header_defines.h +b958d8b7c770808b61bfb420a9d39473b275e4c4 - optee/optee_test/ta/storage/include/storage.h +96b12ede29af7df11c0b54a3d3924599f9ad0de4 - optee/optee_test/ta/enc_fs/include/enc_fs_key_manager_test.h +e1b35b65fffd182965ab59d513da17f3bc2cb637 - optee/optee_test/ta/socket/ta_entry.c +dfc1e1eb35732695271ed55f42d20a4f3d65dd85 - optee/optee_test/ta/socket/Makefile +7caf8e51e601aad92bfa2080fd1d462af34a690f - optee/optee_test/ta/socket/include/user_ta_header_defines.h +60c71c4fd9746b52eff3180768cadfb42246ad63 - optee/optee_test/ta/socket/include/ta_socket.h +a2d1207a964e7c839176e0c9beb333de1aa5114d - optee/optee_test/ta/sims/ta_entry.c +b27b844ff53c4ce9ea4b37becfc73759661121c9 - optee/optee_test/ta/sims/ta_sims.c +62093428f73279ad6337e6b83de79cdc9638aa07 - optee/optee_test/ta/sims/Makefile +d89af8095b36e083626767c864548995a05f5be0 - optee/optee_test/ta/sims/include/user_ta_header_defines.h +11789923a6ea66b45d579f62db7b637f475896b5 - optee/optee_test/ta/sims/include/ta_sims_test.h +3c47004c9fc79085a49889e5e0a2f74eb9672619 - optee/optee_test/ta/sims/include/ta_sims.h +3a18196418d2722e402a8427f7c603fbb0001208 - optee/optee_test/ta/hash_perf/ta_entry.c +c55f5d16d5adcee00938fe1809a49f80f8b4466c - optee/optee_test/ta/hash_perf/Makefile +fe7cfa7b09ca126fe985f184990efd82c5364016 - optee/optee_test/ta/hash_perf/ta_hash_perf.c +9e4cddd8c6ca6c49ccf2a9c071940659a8404666 - optee/optee_test/ta/hash_perf/include/user_ta_header_defines.h +30630325b3b69827882db59d7c22880109f1aed7 - optee/optee_test/ta/hash_perf/include/ta_hash_perf.h +3ab83f366683236b9a32ce8c776846709795c9fd - optee/optee_test/ta/hash_perf/include/ta_hash_perf_priv.h +0205269ec12a07945fa15e1f01beacd396129c02 - optee/optee_test/ta/crypt/ta_entry.c +a35bf9387750436613dd75a04109a0ac26abb4ad - optee/optee_test/ta/crypt/mbedtls_taf.c +2f8d16642c23418d96eae0799cdbb319adae9bd2 - optee/optee_test/ta/crypt/aes_taf.c +6d536756fbdc5623379b5c8c68b3383c6c3c7535 - optee/optee_test/ta/crypt/aes_impl.c +707f95e800674bd769a22f4b05b0f86bde9bdda0 - optee/optee_test/ta/crypt/Makefile +f22bc5e3e7d42fae8b515ed89e6d52e14853097d - optee/optee_test/ta/crypt/arith_taf.c +cda695cd368148125b67d4b5049b4b5e44f19d4d - optee/optee_test/ta/crypt/sha2_taf.c +71541fecba370d8d5d888ff889cc55a649e0f6e3 - optee/optee_test/ta/crypt/handle.c +0f5728bb87da64faea76a4d60859ffc6ee7cfb0e - optee/optee_test/ta/crypt/seed_rng_taf.c +62f575dd691dc4df07cd85b6aaf381bb1fa129df - optee/optee_test/ta/crypt/handle.h +ae237aa24606ab8442252be914264ebc32acb3f1 - optee/optee_test/ta/crypt/derive_key_taf.c +89299c5c290be38d0509309892bd9bf67946a552 - optee/optee_test/ta/crypt/sha2_impl.c +08792d69cd8404668362c47a42015e3ed15a03e2 - optee/optee_test/ta/crypt/cryp_taf.c +98b131e0650e8848c202b367de6afd9713234b23 - optee/optee_test/ta/crypt/include/cryp_taf.h +81c28b5d39b57c60583003aa3b19d4e9355be3e8 - optee/optee_test/ta/crypt/include/aes_taf.h +65726ede28ff3980980f0786f73da00bf00f7adf - optee/optee_test/ta/crypt/include/aes_impl.h +e39b6697e3f099db9e9210630f403279d821b01d - optee/optee_test/ta/crypt/include/user_ta_header_defines.h +f922975017d8e69cf55d924ad3475f48207c778c - optee/optee_test/ta/crypt/include/sha2_taf.h +dedb18c14d2c13ecb2666beff2d43a1c6f2b1f4c - optee/optee_test/ta/crypt/include/derive_key_taf.h +bece95c11da1deff583de5cccb73aeb047b13bb3 - optee/optee_test/ta/crypt/include/seed_rng_taf.h +971b7e4384dfd449056d2d98600938baaa13b45c - optee/optee_test/ta/crypt/include/arith_taf.h +751a9eda488bdee96dd4666819f86792eb94e63c - optee/optee_test/ta/crypt/include/mbedtls_taf.h +59bb92661052957ededa8bf444418db0f792e5df - optee/optee_test/ta/crypt/include/sha2_impl.h +d6094f43aff3a5e99b1b4916e6f0616f4b506c4e - optee/optee_test/ta/crypt/include/ta_crypt.h +34655a75cdbf9b1cf1a0f475a835630aa77d76ad - optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl.c +0b8f95e1cc815a73f1913f8b1cd1199b86afd777 - optee/optee_test/ta/os_test_lib_dl/Makefile +9d8c78ff226d9cd3e8f8be315142adc0bdc791d5 - optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl_cxx.cpp +36e93c9c976420202d3962d3af744a06481e4bda - optee/optee_test/ta/os_test_lib_dl/include/os_test_lib_dl.h +28e50e4d884a51351b0454dcf8971ea8619becb2 - optee/optee_test/ta/rpc_test/ta_entry.c +db39d7c16208c8b18547c18b524c4d4d8d8533a6 - optee/optee_test/ta/rpc_test/Makefile +515cd2121fffeb7e284eb41a47cd39f68e8caee3 - optee/optee_test/ta/rpc_test/ta_rpc.c +bb5b31def49e12cb5ca13946631064fdab7f3ce1 - optee/optee_test/ta/rpc_test/include/user_ta_header_defines.h +daf6f0380173f9c72cb5ab411c7e145635102403 - optee/optee_test/ta/rpc_test/include/ta_rpc.h +5a06508a48d77c9bc4d4483f2c1064bc11547f17 - optee/optee_test/ta/rpc_test/include/ta_rpc_test.h +729fae7d04cb0ca43a757f92763e4accc4b12b47 - optee/optee_test/ta/include/ta_storage.h +e98d28dd7d955c5f1430b86d1f9fa9a293f2c6a5 - optee/optee_test/ta/subkey1/ta_entry.c +ab190ed1cbd92987955bd1b18cf1125760e00235 - optee/optee_test/ta/subkey1/Makefile +fccce5046748bb0a2c4bf866d2ee4099789327e9 - optee/optee_test/ta/subkey1/include/ta_subkey1.h +3ef18fee5ed3f12595bcae5cd670e9b614bddccb - optee/optee_test/ta/subkey1/include/user_ta_header_defines.h +327bcd861d17179ed6eec837ae40d93f6d4d5171 - optee/optee_test/ta/create_fail_test/ta_entry.c +969daad84d451c2beaaeb0205d361045b135c899 - optee/optee_test/ta/create_fail_test/Makefile +28f22d74fc72b507d9530a7788812714f4ccd2be - optee/optee_test/ta/create_fail_test/include/user_ta_header_defines.h +f8ff5608bd441c5bb14ba4e0d1ac825036c0be26 - optee/optee_test/ta/create_fail_test/include/ta_create_fail_test.h +c5741796e6b99090e6fd99dc03a6bbcfe6871028 - optee/optee_test/ta/concurrent_large/ta_entry.c +305e7a10ae0489f83dfe773f06b47ad314bb9771 - optee/optee_test/ta/concurrent_large/Makefile +51f374f9df753de95e0ee8a082c29395bed8625a - optee/optee_test/ta/concurrent_large/include/ta_concurrent_large.h +6fc98a616100591a9ba17fe01d8cd7f30c449420 - optee/optee_test/ta/concurrent_large/include/user_ta_header_defines.h +3484bf8a9bd48d0fd2c66b682574dcbd80ae59e7 - optee/optee_test/ta/subkey2/ta_entry.c +56e682b335cbdbb4b053f31838a28d596ea0dbf5 - optee/optee_test/ta/subkey2/Makefile +d1217850bdabdc5c5f402556a4dd76a32af19d03 - optee/optee_test/ta/subkey2/include/user_ta_header_defines.h +786d2761de772f9af4885b058126e8596a16e194 - optee/optee_test/ta/subkey2/include/ta_subkey2.h +9752d870fbaca8ae7c1554096be6f228b5a0efaf - optee/optee_test/ta/bti_test/ta_entry.c +19e490a77411c75a67b54eb0684edc9dc35f7192 - optee/optee_test/ta/bti_test/Makefile +02a75c4818fde432ee44ba7d161b5c27851a796b - optee/optee_test/ta/bti_test/bti_stubs_a64.S +a59733e35df2f166b33f45d74ffcad1404144624 - optee/optee_test/ta/bti_test/ta_arm_bti.c +7f829607eda29dcb8ef45bfba360ed98db860871 - optee/optee_test/ta/bti_test/include/ta_arm_bti_priv.h +3d48258f0e002fce82e638e430b603a76c11d113 - optee/optee_test/ta/bti_test/include/user_ta_header_defines.h +a6569f27e231e4466e5b7f08f63a13626cf26810 - optee/optee_test/ta/bti_test/include/ta_arm_bti.h diff --git a/nvcommon_build.sh b/nvcommon_build.sh new file mode 100755 index 0000000..5b47065 --- /dev/null +++ b/nvcommon_build.sh @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: Copyright (c) 2019-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: LicenseRef-NvidiaProprietary +# +# NVIDIA CORPORATION, its affiliates and licensors retain all intellectual +# property and proprietary rights in and to this material, related +# documentation and any modifications thereto. Any use, reproduction, +# disclosure or distribution of this material and related documentation +# without an express license agreement from NVIDIA CORPORATION or +# its affiliates is strictly prohibited. + +# shellcheck disable=SC2148 + +# Function to check if variable is defined. +function check_vars { + # shellcheck disable=SC2124 + variables=${@} + for variable in ${variables} ; do + if [ -z "${!variable}" ]; then + echo "Error: Env variable ${variable} is not set!!" + exit 1 + fi + done +} + +# Function to check build environment +function check_env_common { + if [ "${IS_CROSS_COMPILATION}" -eq 1 ]; then + check_vars "CROSS_COMPILE_AARCH64_PATH" + CROSS_COMPILE_AARCH64="${CROSS_COMPILE_AARCH64:-${CROSS_COMPILE_AARCH64_PATH}/bin/aarch64-buildroot-linux-gnu-}" + if [ ! -f "${CROSS_COMPILE_AARCH64}gcc" ]; then + echo "Error: Path ${CROSS_COMPILE_AARCH64}gcc does not exist." + exit 1 + fi + fi + # shellcheck disable=SC2046,SC2235 + if [ "${MAKE_BIN}" != "make" ] && \ + ( [ ! -f "${MAKE_BIN}" ] || \ + [ ! -f $(basename "${MAKE_BIN}") ] ); then + echo "Error: ${MAKE_BIN} does not exist !!" + # shellcheck disable=SC2140 + echo "Set MAKE_BIN env variable to "make" binary" + exit 1 + fi +} + + +# shellcheck disable=SC2034 +NPROC=$(nproc) +MAKE_BIN="${MAKE_BIN:-make}" +BUILD_DIR="${BUILD_DIR:-$(pwd)/build_nv_sources}" + +MACHINE=$(uname -m) + +IS_CROSS_COMPILATION=0 +if [[ "${MACHINE}" =~ "x86" ]]; then + IS_CROSS_COMPILATION=1 +fi +check_env_common diff --git a/optee/atf_and_optee_README.txt b/optee/atf_and_optee_README.txt new file mode 100644 index 0000000..a9e76c7 --- /dev/null +++ b/optee/atf_and_optee_README.txt @@ -0,0 +1,139 @@ +********************************************************************** +NVIDIA Jetson Linux (L4T) OP-TEE Package +********************************************************************** + +---------------------------------------------------------------------- +Introduction +---------------------------------------------------------------------- +This package contains the necessary files and instructions to build a +trusted OS image based on ATF and OP-TEE for these Jetson devices: +- Jetson Xavier NX +- Jetson AGX Xavier series +- Jetson AGX Orin series + +---------------------------------------------------------------------- +Prerequisites +---------------------------------------------------------------------- +Please refer to the link below to install build prerequisites, e.g. +python3-pycryptodome and python3-pyelftools, in your build machine. + +https://optee.readthedocs.io/en/latest/building/prerequisites.html + +---------------------------------------------------------------------- +The python cryptography issue +---------------------------------------------------------------------- +When building OP-TEE sources, you may see a python error in sign_encrypt.py like: +"TypeError: public_key() missing 1 required positional argument: 'backend'" + +This is because the "cryptography" python package in your build system is too old. +Running the following commands can fix the issue: + +sudo apt remove python3-cryptography +pip3 install cryptography + +---------------------------------------------------------------------- +Placeholders used in this document +---------------------------------------------------------------------- +This document uses a placeholder, "", to indicate Jetson platforms. +Its possible values are: +- 194 +- 234 +Choose the platform value according to your Jetson board to build different +trusted OS images and DTBs. + +---------------------------------------------------------------------- +Toolchain +---------------------------------------------------------------------- +Download the toolchain from Jetson release page according to your L4T version: + +https://developer.nvidia.com/embedded/jetson-linux-archive + +Set environment variable CROSS_COMPILE_AARCH64_PATH to point to the aarch64 +toolchain. For example, if the aarch64 toolchain directory is +/toolchain/aarch64--glibc--stable-2022.03-1/, then set +the CROSS_COMPILE_AARCH64_PATH with the command below. + +export CROSS_COMPILE_AARCH64_PATH=/toolchain/aarch64--glibc--stable-2022.03-1 + +Then set environment variable CROSS_COMPILE_AARCH64 with the command +below. + +export CROSS_COMPILE_AARCH64=/toolchain/aarch64--glibc--stable-2022.03-1/bin/aarch64-buildroot-linux-gnu- + +---------------------------------------------------------------------- +UEFI StMM image +---------------------------------------------------------------------- +A UEFI StMM image is required when building OP-TEE. The image is usually at: + +For the Jetson AGX Xavier series and the Jetson Xavier NX: +/bootloader/standalonemm_optee_t194.bin + +For the Jetson AGX Orin series: +/bootloader/standalonemm_optee_t234.bin + +Set the environment variable "UEFI_STMM_PATH" to let the OP-TEE build script +know where the image is: + +export UEFI_STMM_PATH= + +---------------------------------------------------------------------- +Building the OP-TEE source code +---------------------------------------------------------------------- +Execute this command to build the OP-TEE source package: + +./optee_src_build.sh -p t + +---------------------------------------------------------------------- +Building the OP-TEE dtb +---------------------------------------------------------------------- +Execute this command to build OP-TEE dtb: + +dtc -I dts -O dtb -o ./optee/tegra-optee.dtb ./optee/tegra-optee.dts + +---------------------------------------------------------------------- +Building the ATF source code with OP-TEE SPD +---------------------------------------------------------------------- +1. Extract the ATF source package. + mkdir atf_build + tar -I lbzip2 -C atf_build -xpf atf_src.tbz2 + +2. Build the ATF source code: + cd atf_build/arm-trusted-firmware + make BUILD_BASE=./build \ + CROSS_COMPILE="${CROSS_COMPILE_AARCH64}" \ + DEBUG=0 LOG_LEVEL=20 PLAT=tegra SPD=opteed TARGET_SOC=t V=0 + cd ../.. + +---------------------------------------------------------------------- +Generating the tos.img with ATF and OP-TEE images +---------------------------------------------------------------------- +1. Get gen_tos_part_img.py. It's usually in the directory + /nv_tegra/tos-scripts/ of BSP package. + +2. Generate the tos.img with the commands: + ./gen_tos_part_img.py \ + --monitor ./atf_build/arm-trusted-firmware/build/tegra/t/release/bl31.bin \ + --os ./optee/build/t/core/tee-raw.bin \ + --dtb ./optee/tegra-optee.dtb \ + --tostype optee \ + ./tos.img + +---------------------------------------------------------------------- +Verifying the Image +---------------------------------------------------------------------- +To verify the image: +1. Replace the default TOS image file with the newly generated TOS + image. The default TOS image file is located at: + /bootloader/tos-optee_t.img + +2. Perform either of these tasks: + - Flash the system as normal. + This is useful for flashing a new system or replacing the + entire operating system. + - Re-flash the TOS image using these partition flash commands: + sudo ./flash.sh -k mmcblk0p1 + ex: + sudo ./flash.sh -k secure-os jetson-xavier-nx-devkit mmcblk0p1 + sudo ./flash.sh -k A_secure-os jetson-agx-orin-devkit mmcblk0p1 + +3. Copy all the files under ./optee/install/t to the target. diff --git a/optee/optee_client/.github/workflows/ci.yml b/optee/optee_client/.github/workflows/ci.yml new file mode 100644 index 0000000..1297791 --- /dev/null +++ b/optee/optee_client/.github/workflows/ci.yml @@ -0,0 +1,51 @@ +name: CI +on: [push, pull_request] +permissions: + contents: read # to fetch code (actions/checkout) +jobs: + debian: + name: build (Debian) + runs-on: ubuntu-latest + container: jforissier/optee_client_ci_debian + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: arm64 with make + run: make -j O=out-make-aarch64 CROSS_COMPILE=aarch64-linux-gnu- + - name: armhf with make + run: make -j O=out-make-armhf CROSS_COMPILE=arm-linux-gnueabihf- + - name: arm64 with cmake + run: | + set -e -v + mkdir out-cmake-aarch64 && cd out-cmake-aarch64 + PKG_CONFIG=aarch64-linux-gnu-pkg-config cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc + make -j + - name: armhf with cmake + run: | + set -e -v + mkdir out-cmake-armhf && cd out-cmake-armhf + PKG_CONFIG=arm-linux-gnueabihf-pkg-config cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc + make -j + ubuntu: + name: build (Ubuntu) + runs-on: ubuntu-latest + container: jforissier/optee_client_ci_ubuntu + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: arm64 with make + run: make -j O=out-make-aarch64 CROSS_COMPILE=aarch64-linux-gnu- + - name: armhf with make + run: make -j O=out-make-armhf CROSS_COMPILE=arm-linux-gnueabihf- + - name: arm64 with cmake + run: | + set -e -v + mkdir out-cmake-aarch64 && cd out-cmake-aarch64 + PKG_CONFIG=aarch64-linux-gnu-pkg-config cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc + make -j + - name: armhf with cmake + run: | + set -e -v + mkdir out-cmake-armhf && cd out-cmake-armhf + PKG_CONFIG=arm-linux-gnueabihf-pkg-config cmake .. -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc + make -j diff --git a/optee/optee_client/.github/workflows/stales.yml b/optee/optee_client/.github/workflows/stales.yml new file mode 100644 index 0000000..e0d47f3 --- /dev/null +++ b/optee/optee_client/.github/workflows/stales.yml @@ -0,0 +1,27 @@ +name: 'Close stale issues and pull requests with no recent activity' +on: + schedule: + - cron: "15 00 * * *" + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4.1.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue has been marked as a stale issue because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this issue will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.' + stale-pr-message: 'This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.' + stale-issue-label: Stale + stale-pr-label: Stale + exempt-issue-labels: bug,enhancement + exempt-pr-labels: bug,enhancement + days-before-stale: 30 + days-before-close: 5 + remove-stale-when-updated: true + remove-issue-stale-when-updated: true + remove-pr-stale-when-updated: true diff --git a/optee/optee_client/Android.mk b/optee/optee_client/Android.mk new file mode 100644 index 0000000..ca08a80 --- /dev/null +++ b/optee/optee_client/Android.mk @@ -0,0 +1,107 @@ +################################################################################ +# Android optee-client, libckteec and optee-supplicant makefile # +################################################################################ +LOCAL_PATH := $(call my-dir) + +# 3 (debug) is too noisy +CFG_TEE_CLIENT_LOG_LEVEL ?= 2 +CFG_TEE_SUPP_LOG_LEVEL ?= 2 + +# Define Android-specific configuration before including config.mk +CFG_TEE_CLIENT_LOAD_PATH ?= /vendor/lib +TEEC_TEST_LOAD_PATH ?= /data/vendor/tee +CFG_TEE_FS_PARENT_PATH ?= /data/vendor/tee +CFG_TEE_SUPP_PLUGINS ?= y +ifneq ($(strip $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)),) +CFG_TEE_PLUGIN_LOAD_PATH ?= /vendor/lib64/tee-supplicant/plugins/ +else +CFG_TEE_PLUGIN_LOAD_PATH ?= /vendor/lib/tee-supplicant/plugins/ +endif + +$(info CFG_TEE_PLUGIN_LOAD_PATH = ${CFG_TEE_PLUGIN_LOAD_PATH}) + + +################################################################################ +# Include optee-client common config and flags # +################################################################################ +include $(LOCAL_PATH)/config.mk +include $(LOCAL_PATH)/android_flags.mk + +optee_CFLAGS = $(CFLAGS) + +################################################################################ +# Build libteec.so - TEE (Trusted Execution Environment) shared library # +################################################################################ +include $(CLEAR_VARS) +LOCAL_CFLAGS += $(optee_CFLAGS) + +ifneq ($(CFG_TEE_CLIENT_LOG_FILE),) +LOCAL_CFLAGS += -DTEEC_LOG_FILE=\"$(CFG_TEE_CLIENT_LOG_FILE)\" +endif + +LOCAL_CFLAGS += -DDEBUGLEVEL_$(CFG_TEE_CLIENT_LOG_LEVEL) +LOCAL_CFLAGS += -DBINARY_PREFIX=\"TEEC\" + +LOCAL_SRC_FILES := libteec/src/tee_client_api.c \ + libteec/src/teec_trace.c +ifeq ($(CFG_TEE_BENCHMARK),y) +LOCAL_CFLAGS += -DCFG_TEE_BENCHMARK +LOCAL_SRC_FILES += teec_benchmark.c +endif + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/public \ + $(LOCAL_PATH)/libteec/include \ + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libteec + +LOCAL_MODULE_TAGS := optional +LOCAL_VENDOR_MODULE := true + +# Build the 32-bit and 64-bit versions. +LOCAL_MULTILIB := both +LOCAL_MODULE_TARGET_ARCH := arm arm64 + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/public + +include $(BUILD_SHARED_LIBRARY) + +################################################################################ +# Build libckteec.so # +################################################################################ +include $(CLEAR_VARS) + +LOCAL_CFLAGS += $(optee_CFLAGS) + +LOCAL_SRC_FILES := libckteec/src/pkcs11_api.c \ + libckteec/src/ck_debug.c \ + libckteec/src/ck_helpers.c \ + libckteec/src/invoke_ta.c \ + libckteec/src/pkcs11_processing.c \ + libckteec/src/pkcs11_token.c \ + libckteec/src/serializer.c \ + libckteec/src/serialize_ck.c + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/public \ + $(LOCAL_PATH)/libckteec/include + +LOCAL_SHARED_LIBRARIES := libteec + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libckteec + +LOCAL_MODULE_TAGS := optional +LOCAL_VENDOR_MODULE := true + +# Build the 32-bit and 64-bit versions. +LOCAL_MULTILIB := both +LOCAL_MODULE_TARGET_ARCH := arm arm64 + +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/libckteec/include + +include $(BUILD_SHARED_LIBRARY) + +################################################################################ +# Build TEE Supplicant # +################################################################################ +include $(LOCAL_PATH)/tee-supplicant/tee_supplicant_android.mk diff --git a/optee/optee_client/CMakeLists.txt b/optee/optee_client/CMakeLists.txt new file mode 100644 index 0000000..a31fa4b --- /dev/null +++ b/optee/optee_client/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required (VERSION 3.4) +project (optee_client C) + +# https://cmake.org/Wiki/CMake_Useful_Variables +set (CMAKE_TOOLCHAIN_FILE CMakeToolchain.txt) + +option (CFG_WERROR "Build with -Werror" TRUE) +option (WITH_TEEACL "Build libteeacl" TRUE) + +include(GNUInstallDirs) + +################################################################################ +# Compiler flags: +# We want to use the same flags in the entire optee_client git +################################################################################ +add_compile_options ( + -Wall -Wbad-function-cast -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 -fPIC +) +if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + add_compile_options( + -Wunsafe-loop-optimizations + ) +endif() +if(CFG_WERROR) + add_compile_options(-Werror) +endif(CFG_WERROR) + +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) +endif(CCACHE_FOUND) + +add_subdirectory (libteec) +add_subdirectory (tee-supplicant) +add_subdirectory (public) +add_subdirectory (libckteec) +if(WITH_TEEACL) + find_package (PkgConfig REQUIRED) + pkg_check_modules(uuid REQUIRED IMPORTED_TARGET uuid) + add_subdirectory (libteeacl) +endif(WITH_TEEACL) +add_subdirectory (libseteec) diff --git a/optee/optee_client/CMakeToolchain.txt b/optee/optee_client/CMakeToolchain.txt new file mode 100644 index 0000000..71eb52f --- /dev/null +++ b/optee/optee_client/CMakeToolchain.txt @@ -0,0 +1,3 @@ +set (CMAKE_SYSTEM_NAME Linux) + +set (CMAKE_SYSTEM_PROCESSOR arm) diff --git a/optee/optee_client/LICENSE b/optee/optee_client/LICENSE new file mode 100644 index 0000000..76c5d00 --- /dev/null +++ b/optee/optee_client/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) 2015, 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. diff --git a/optee/optee_client/Makefile b/optee/optee_client/Makefile new file mode 100644 index 0000000..de1e14f --- /dev/null +++ b/optee/optee_client/Makefile @@ -0,0 +1,173 @@ +# Public variables are stored in config.mk +include ./config.mk + +######################################################################### +# Set Internal Variables # +# May be modified to match your setup # +######################################################################### +ifneq ($(V),1) +VPREFIX := @ +endif +export VPREFIX + +EXPORT_DIR ?= $(O)/export +DESTDIR ?= $(EXPORT_DIR) +SBINDIR ?= /usr/sbin +LIBDIR ?= /usr/lib +INCLUDEDIR ?= /usr/include +sbindir ?= $(SBINDIR) +libdir ?= $(LIBDIR) +includedir ?= $(INCLUDEDIR) + +WITH_TEEACL ?= 1 + +.PHONY: all build build-libteec build-libckteec build-libseteec \ + build-libteeacl install copy_export clean cscope \ + clean-cscope \ + checkpatch-pre-req checkpatch-modified-patch checkpatch-modified-file \ + checkpatch-last-commit-patch checkpatch-last-commit-file \ + checkpatch-base-commit-patch checkpatch-base-commit-file \ + checkpatch-all-files distclean + +all: build install + +build-libteec: + @echo "Building libteec.so" + @$(MAKE) --directory=libteec --no-print-directory --no-builtin-variables \ + CFG_TEE_BENCHMARK=$(CFG_TEE_BENCHMARK) CFG_TEE_CLIENT_LOG_LEVEL=$(CFG_TEE_CLIENT_LOG_LEVEL) + +build-tee-supplicant: build-libteec + @echo "Building tee-supplicant" + $(MAKE) --directory=tee-supplicant --no-print-directory --no-builtin-variables CFG_TEE_SUPP_LOG_LEVEL=$(CFG_TEE_SUPP_LOG_LEVEL) + +build: build-libteec build-tee-supplicant build-libckteec build-libseteec \ +# Disable libteeacl: +# build-libteeacl + +build-libckteec: build-libteec + @echo "Building libckteec.so" + @$(MAKE) --directory=libckteec --no-print-directory --no-builtin-variables + +build-libseteec: build-libteec + @echo "Building libseteec.so" + @$(MAKE) --directory=libseteec --no-print-directory --no-builtin-variables + +build-libteeacl: + @echo "Building libteeacl.so" + @$(MAKE) --directory=libteeacl --no-print-directory --no-builtin-variables + +install: copy_export + +clean: clean-libteec clean-tee-supplicant clean-cscope clean-libckteec \ + clean-libseteec \ +# Disable libteeacl: +# clean-libteeacl + +clean-libteec: + @$(MAKE) --directory=libteec --no-print-directory clean + +clean-tee-supplicant: + @$(MAKE) --directory=tee-supplicant --no-print-directory clean + +clean-libckteec: + @$(MAKE) --directory=libckteec --no-print-directory clean + +clean-libseteec: + @$(MAKE) --directory=libseteec --no-print-directory clean + +clean-libteeacl: + @$(MAKE) --directory=libteeacl --no-print-directory clean + +cscope: + @echo " CSCOPE" + ${VPREFIX}find ${CURDIR} -name "*.[chsS]" > cscope.files + ${VPREFIX}cscope -b -q -k + +clean-cscope: + ${VPREFIX}rm -f cscope.* + +# Various checkpatch targets. The ones ending with "patch" only considers the +# patch, whilst the ones ending with "file" checks the complete file. +# +-------------------------------+------------+----------------------------+ +# | Target commit | File/Patch | Comment | +# +-------------------------------+------------+----------------------------+ +# | checkpatch-modified-patch | Patch | Check local modifications | +# +-------------------------------+------------+----------------------------+ +# | checkpatch-modified-file | File | Check Local modifications | +# +-------------------------------+------------+----------------------------+ +# | checkpatch-last-commit-patch | Patch | Check against HEAD^ | +# +-------------------------------+------------+----------------------------+ +# | checkpatch-last-commit-file | File | Check against HEAD^ | +# +-------------------------------+------------+----------------------------+ +# | checkpatch-base-commit-patch | Patch | Against specic commit | +# +-------------------------------+------------+----------------------------+ +# | checkpatch-base-commit-file | File | Against specic commit | +# +-------------------------------+------------+----------------------------+ +# | checkpatch-all-files | File | Check all tracked files | +# +-------------------------------+------------+----------------------------+ +CHECKPATCH_IGNORE ?= --ignore NEW_TYPEDEFS --no-signoff +CHECKPATCH_STRICT ?= --strict +CHECKPATCH_ARGS ?= $(CHECKPATCH_IGNORE) $(CHECKPATCH_STRICT) --no-tree --terse +CHECKPATCH_PATCH_ARGS := $(CHECKPATCH_ARGS) --patch +CHECKPATCH_FILE_ARGS := $(CHECKPATCH_ARGS) --file --no-patch + +checkpatch-pre-req: + @echo " CHECKPATCH" +ifndef CHECKPATCH + $(error "Environment variable CHECKPATCH must point to Linux kernels checkpatch script") +else +ifeq (,$(wildcard ${CHECKPATCH})) + $(error "CHECKPATCH points to the incorrect file") +endif +endif + +checkpatch-modified-patch: checkpatch-pre-req + ${VPREFIX}git diff | ${CHECKPATCH} $(CHECKPATCH_PATCH_ARGS) - || true + +checkpatch-modified-file: checkpatch-pre-req + ${VPREFIX}${CHECKPATCH} $(CHECKPATCH_FILE_ARGS) $(shell git diff --name-only) + + +checkpatch-last-commit-patch: checkpatch-pre-req + ${VPREFIX}git diff HEAD^ | ${CHECKPATCH} $(CHECKPATCH_PATCH_ARGS) - || true + +checkpatch-last-commit-file: checkpatch-pre-req + ${VPREFIX}${CHECKPATCH} $(CHECKPATCH_FILE_ARGS) $(shell git diff --name-only HEAD^) + + +checkpatch-base-commit-patch: checkpatch-pre-req +ifndef BASE_COMMIT + $(error "Environment variable BASE_COMMIT must contain a valid commit") +endif + ${VPREFIX}git diff $(BASE_COMMIT) | ${CHECKPATCH} $(CHECKPATCH_PATCH_ARGS) - || true + +checkpatch-base-commit-file: checkpatch-pre-req +ifndef BASE_COMMIT + $(error "Environment variable BASE_COMMIT must contain a valid commit") +endif + ${VPREFIX}${CHECKPATCH} $(CHECKPATCH_FILE_ARGS) $(shell git diff --name-only ${BASE_COMMIT}) + +checkpatch-all-files: checkpatch-pre-req + ${VPREFIX}${CHECKPATCH} $(CHECKPATCH_FILE_ARGS) $(shell git ls-files) + +distclean: clean + +copy_export: build + mkdir -p $(DESTDIR)$(sbindir) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) + cp config.mk $(DESTDIR)/$(includedir)/optee_client_config.mk + cp -d ${O}/libteec/libteec.so* $(DESTDIR)$(libdir) + cp -d ${O}/libteec/libteec.a $(DESTDIR)$(libdir) + cp ${O}/tee-supplicant/tee-supplicant $(DESTDIR)$(sbindir) + cp public/*.h $(DESTDIR)$(includedir) + cp libckteec/include/*.h $(DESTDIR)$(includedir) + cp -d ${O}/libckteec/libckteec.so* $(DESTDIR)$(libdir) + cp -d ${O}/libckteec/libckteec.a $(DESTDIR)$(libdir) +ifeq ($(WITH_TEEACL),1) +# Disable libteeacl: +# cp libteeacl/include/*.h $(DESTDIR)$(includedir) +# cp -d ${O}/libteeacl/libteeacl.so* $(DESTDIR)$(libdir) +# cp -d ${O}/libteeacl/libteeacl.a $(DESTDIR)$(libdir) +endif + cp libseteec/include/*.h $(DESTDIR)$(includedir) + cp -d ${O}/libseteec/libseteec.so* $(DESTDIR)$(libdir) + cp -d ${O}/libseteec/libseteec.a $(DESTDIR)$(libdir) diff --git a/optee/optee_client/README.md b/optee/optee_client/README.md new file mode 100644 index 0000000..045dbfd --- /dev/null +++ b/optee/optee_client/README.md @@ -0,0 +1,10 @@ +# OP-TEE Client API +This git contains source code for the non-secure side implementation of the +OP-TEE project making up the client library and tee-supplicant. + +All official OP-TEE documentation has moved to http://optee.readthedocs.io. The +information that used to be here in this git can be found under [optee_client]. + +// OP-TEE core maintainers + +[optee_client]: https://optee.readthedocs.io/en/latest/building/gits/optee_client.html diff --git a/optee/optee_client/android_flags.mk b/optee/optee_client/android_flags.mk new file mode 100644 index 0000000..17c57fe --- /dev/null +++ b/optee/optee_client/android_flags.mk @@ -0,0 +1,27 @@ +######################################################################### +# COMMON COMPILATION FLAGS # +######################################################################### +CFLAGS := -Wall -Wbad-function-cast -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 +ifeq ($(CFG_WERROR),y) +CFLAGS += -Werror +endif +CFLAGS += -c -fPIC + +DEBUG ?= 0 +ifeq ($(DEBUG), 1) +CFLAGS += -DDEBUG -O0 -g +endif + +RM := rm -rf + +define rmdir +if [ -d "$(1)" ] ; then rmdir --ignore-fail-on-non-empty $(1) ; fi +endef diff --git a/optee/optee_client/ci/Dockerfile.debian b/optee/optee_client/ci/Dockerfile.debian new file mode 100644 index 0000000..875f113 --- /dev/null +++ b/optee/optee_client/ci/Dockerfile.debian @@ -0,0 +1,21 @@ +# Dockerfile for CI image used in ../.github/workflows/ci.yml + +FROM debian:bullseye-slim +MAINTAINER Jerome Forissier + +ENV LANG=C.UTF-8 + +RUN dpkg --add-architecture armhf +RUN dpkg --add-architecture arm64 + +RUN apt update +RUN apt upgrade -y +RUN apt install -y \ + cmake \ + dpkg-dev \ + gcc-aarch64-linux-gnu \ + gcc-arm-linux-gnueabihf \ + make \ + pkg-config \ + uuid-dev:armhf \ + uuid-dev:arm64 diff --git a/optee/optee_client/ci/Dockerfile.ubuntu b/optee/optee_client/ci/Dockerfile.ubuntu new file mode 100644 index 0000000..9a4f8a5 --- /dev/null +++ b/optee/optee_client/ci/Dockerfile.ubuntu @@ -0,0 +1,30 @@ +# Dockerfile for CI image used in ../.github/workflows/ci.yml + +FROM ubuntu:22.04 +MAINTAINER Jerome Forissier + +ENV LANG=C.UTF-8 + +RUN dpkg --add-architecture armhf +RUN dpkg --add-architecture arm64 + +RUN echo 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse' > /etc/apt/sources.list +RUN echo 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe multiverse' >> /etc/apt/sources.list +RUN echo 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse' >> /etc/apt/sources.list +RUN echo 'deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse' >> /etc/apt/sources.list +RUN echo 'deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe multiverse' >> /etc/apt/sources.list +RUN echo 'deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe multiverse' >> /etc/apt/sources.list +RUN echo 'deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted universe multiverse' >> /etc/apt/sources.list +RUN echo 'deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse' >> /etc/apt/sources.list + +RUN apt update +RUN apt upgrade -y +RUN apt install -y \ + cmake \ + dpkg-dev \ + gcc-aarch64-linux-gnu \ + gcc-arm-linux-gnueabihf \ + make \ + pkg-config \ + uuid-dev:armhf \ + uuid-dev:arm64 diff --git a/optee/optee_client/config.mk b/optee/optee_client/config.mk new file mode 100644 index 0000000..24904af --- /dev/null +++ b/optee/optee_client/config.mk @@ -0,0 +1,79 @@ +######################################################################### +# Public variables # +# Developers may override these values when calling the makefile, # +# as for example # +# CFG_TEE_CLIENT_LOG_LEVEL=1 make # +# Note: # +# Please do not use export to declare the variables, so that to avoid # +# compiling problem for android platform # +######################################################################### + +# CFG_TEE_CLIENT_LOG_LEVEL +# Client (User Non Secure) log level +# Supported values: 0 (no traces) to 4 (all traces) +CFG_TEE_CLIENT_LOG_LEVEL?=1 + +# CFG_TEE_SUPP_LOG_LEVEL +# Supplicant log level +# Supported values: 0 (no traces) to 4 (all traces) +CFG_TEE_SUPP_LOG_LEVEL?=1 + +# CFG_TEE_FS_PARENT_PATH +# Path to folder that will contain TEE filesystem. +# This folder can be created with the required permission in an init +# script during boot, else it will be created by the tee-supplicant on +# first REE FS access. +CFG_TEE_FS_PARENT_PATH ?= /data/tee + +# CFG_TEE_CLIENT_LOG_FILE +# The location of the client log file when logging to file is enabled. +CFG_TEE_CLIENT_LOG_FILE ?= $(CFG_TEE_FS_PARENT_PATH)/teec.log + +# CFG_TEE_CLIENT_LOAD_PATH +# Colon-separated list of paths where tee-supplicant loads TAs from. +# For example: CFG_TEE_CLIENT_LOAD_PATH ?= /lib:/vendor/lib +# Note that the TA files are typically in a sub-directory (see the +# --ta-dir option). +CFG_TEE_CLIENT_LOAD_PATH ?= /lib + +# CFG_TEE_SUPP_PLUGINS +# Enable (y) or disable (n) TEE supplicant plugin support +CFG_TEE_SUPP_PLUGINS ?= y + +# CFG_TEE_PLUGIN_LOAD_PATH +# The location of the user plugins +CFG_TEE_PLUGIN_LOAD_PATH ?= /usr/lib/tee-supplicant/plugins/ + +# CFG_TA_TEST_PATH +# Enable the tee test path. When enabled, the supplicant will try +# loading from a debug path before the regular path. This allows test +# such as 1008.5 that test loading of corrupt TAs. +CFG_TA_TEST_PATH ?= n + +# CFG_GP_SOCKETS +# Enable Global Platform Sockets support +CFG_GP_SOCKETS ?= y + +# CFG_TA_GPROF_SUPPORT +# Enable dumping gprof data, not used unless secure world decides +# to dump something +CFG_TA_GPROF_SUPPORT ?= y + +# CFG_FTRACE_SUPPORT +# Enable dumping ftrace data, not used unless secure world decides +# to dump something +CFG_FTRACE_SUPPORT ?= y + +# Default output directory. +# May be absolute, or relative to the optee_client source directory. +O ?= out + +# To be used instead of $(O) in sub-directories +OO := $(if $(filter /%,$(O)),$(O),$(CURDIR)/../$(O)) + +######################################################################### +# Private Values # +######################################################################### + +# Check that settings are coherent. + diff --git a/optee/optee_client/flags.mk b/optee/optee_client/flags.mk new file mode 100644 index 0000000..be4088c --- /dev/null +++ b/optee/optee_client/flags.mk @@ -0,0 +1,37 @@ +######################################################################### +# COMMON COMPILATION FLAGS # +######################################################################### + +CROSS_COMPILE ?= arm-linux-gnueabihf- +CC ?= $(CROSS_COMPILE)gcc +AR ?= $(CROSS_COMPILE)ar +PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config + +C_COMPILER=$(shell readlink -f $$(which $(CC))) + +override CFLAGS += -Wall -Wbad-function-cast -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 -D_FILE_OFFSET_BITS=64 +ifneq (,$(findstring gcc,$(C_COMPILER))) +override CFLAGS += -Wunsafe-loop-optimizations +endif +ifeq ($(CFG_WERROR),y) +override CFLAGS += -Werror +endif +override CFLAGS += -c -fPIC + +DEBUG ?= 0 +ifeq ($(DEBUG), 1) +override CFLAGS += -DDEBUG -O0 -g +endif + +RM := rm -f + +define rmdir +if [ -d "$(1)" ] ; then rmdir --ignore-fail-on-non-empty $(1) ; fi +endef diff --git a/optee/optee_client/libckteec/CMakeLists.txt b/optee/optee_client/libckteec/CMakeLists.txt new file mode 100644 index 0000000..26c050e --- /dev/null +++ b/optee/optee_client/libckteec/CMakeLists.txt @@ -0,0 +1,77 @@ +project(ckteec + VERSION 0.1.0 + LANGUAGES C) + +################################################################################ +# Packages +################################################################################ +find_package(Threads REQUIRED) +if(NOT THREADS_FOUND) + message(FATAL_ERROR "Threads not found") +endif() + +include(GNUInstallDirs) + +################################################################################ +# Source files +################################################################################ +set (SRC + src/pkcs11_api.c + src/ck_debug.c + src/ck_helpers.c + src/invoke_ta.c + src/pkcs11_processing.c + src/pkcs11_token.c + src/serializer.c + src/serialize_ck.c +) + +################################################################################ +# Built library +################################################################################ +add_library (ckteec ${SRC}) + +set_target_properties (ckteec PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) + +################################################################################ +# Flags always set +################################################################################ +target_compile_definitions (ckteec + PRIVATE -D_GNU_SOURCE + PRIVATE -DBINARY_PREFIX="LT" +) + +################################################################################ +# Optional flags +################################################################################ + +################################################################################ +# Public and private header and library dependencies +################################################################################ +target_include_directories(ckteec + PUBLIC $ + $ + PRIVATE src +) + +target_include_directories(teec + PUBLIC include +) + +target_link_libraries (ckteec + PRIVATE pthread + PRIVATE teec + PRIVATE m +) + +################################################################################ +# Install targets +################################################################################ +install (TARGETS ckteec + DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +add_subdirectory(include) diff --git a/optee/optee_client/libckteec/Makefile b/optee/optee_client/libckteec/Makefile new file mode 100644 index 0000000..859ce3c --- /dev/null +++ b/optee/optee_client/libckteec/Makefile @@ -0,0 +1,78 @@ +include ../flags.mk +include ../config.mk + +OUT_DIR := $(OO)/libckteec + +.PHONY: all libckteec clean + +all: libckteec +install: libckteec + +LIB_NAME := libckteec +MAJOR_VERSION := 0 +MINOR_VERSION := 1 +PATCH_VERSION := 0 + +LIB_MAJOR := $(LIB_NAME).so.$(MAJOR_VERSION) +LIB_MAJ_MIN := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION) +LIB_MAJ_MIN_PAT := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) +LIBCKTEEC_SO_LIBRARY := $(LIB_MAJ_MIN_PAT) +LIBCKTEEC_AR_LIBRARY := $(LIB_NAME).a + +LIBCKTEEC_SRC_DIR := src + +LIBCKTEEC_SRCS = pkcs11_api.c +LIBCKTEEC_SRCS += ck_debug.c +LIBCKTEEC_SRCS += ck_helpers.c +LIBCKTEEC_SRCS += invoke_ta.c +LIBCKTEEC_SRCS += pkcs11_processing.c +LIBCKTEEC_SRCS += pkcs11_token.c +LIBCKTEEC_SRCS += serializer.c +LIBCKTEEC_SRCS += serialize_ck.c + +LIBCKTEEC_INCLUDES = ${CURDIR}/include +LIBCKTEEC_INCLUDES += ${CURDIR}/../public + +LIBCKTEEC_CFLAGS := $(addprefix -I, $(LIBCKTEEC_INCLUDES)) \ + $(CFLAGS) -D_GNU_SOURCE -fPIC + +LIBCKTEEC_LFLAGS := $(LDFLAGS) -L$(OUT_DIR)/../libteec -lteec + +LIBCKTEEC_OBJ_DIR := $(OUT_DIR) +LIBCKTEEC_OBJS := $(patsubst %.c,$(LIBCKTEEC_OBJ_DIR)/%.o, $(LIBCKTEEC_SRCS)) + +$(LIBCKTEEC_OBJ_DIR)/%.o: ${LIBCKTEEC_SRC_DIR}/%.c + $(VPREFIX)mkdir -p $(LIBCKTEEC_OBJ_DIR) + @echo " CC $<" + $(VPREFIX)$(CC) $(LIBCKTEEC_CFLAGS) -c $< -o $@ + +libckteec: $(OUT_DIR)/$(LIBCKTEEC_SO_LIBRARY) + +$(OUT_DIR)/$(LIBCKTEEC_SO_LIBRARY): $(LIBCKTEEC_OBJS) + @echo " LINK $@" + $(VPREFIX)$(CC) -shared -Wl,-soname,$(LIB_MAJOR) -o $@ $+ $(LIBCKTEEC_LFLAGS) + @echo "" + +libckteec: $(OUT_DIR)/$(LIBCKTEEC_AR_LIBRARY) + +$(OUT_DIR)/$(LIBCKTEEC_AR_LIBRARY): $(LIBCKTEEC_OBJS) + @echo " AR $@" + $(VPREFIX)$(AR) rcs $@ $+ + +libckteec: + $(VPREFIX)ln -sf $(LIB_MAJ_MIN_PAT) $(OUT_DIR)/$(LIB_MAJ_MIN) + $(VPREFIX)ln -sf $(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_MAJOR) + $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME).so + +################################################################################ +# Cleaning up configuration +################################################################################ +clean: + $(RM) $(LIBCKTEEC_OBJS) + $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN_PAT) + $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN) + $(RM) $(OUT_DIR)/$(LIB_MAJOR) + $(RM) $(OUT_DIR)/$(LIBCKTEEC_SO_LIBRARY) + $(RM) $(OUT_DIR)/$(LIBCKTEEC_AR_LIBRARY) + $(call rmdir,$(OUT_DIR)) + diff --git a/optee/optee_client/libckteec/include/CMakeLists.txt b/optee/optee_client/libckteec/include/CMakeLists.txt new file mode 100644 index 0000000..826bb48 --- /dev/null +++ b/optee/optee_client/libckteec/include/CMakeLists.txt @@ -0,0 +1,12 @@ +project (libckteec-headers C) + +FILE(GLOB INSTALL_HEADERS "*.h") + +add_library(${PROJECT_NAME} INTERFACE) +target_include_directories( + ${PROJECT_NAME} + INTERFACE $ + $ +) + +install (FILES ${INSTALL_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/optee/optee_client/libckteec/include/ck_debug.h b/optee/optee_client/libckteec/include/ck_debug.h new file mode 100644 index 0000000..3e7e210 --- /dev/null +++ b/optee/optee_client/libckteec/include/ck_debug.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#ifndef LIBCKTEEC_CK_DEBUG_H +#define LIBCKTEEC_CK_DEBUG_H + +#include + +/* Return a pointer to a string buffer of "CKR_xxx\0" return value ID */ +const char *ckr2str(CK_RV id); + +/* ckm2str - Return string buffer of "CKM_xxx\0" for a mechanism ID */ +const char *ckm2str(CK_MECHANISM_TYPE id); + +/* slot_ckf2str - Return string buffer of "CKF_xxx\0" for a slot flag */ +const char *slot_ckf2str(CK_ULONG flag); + +/* token_ckf2str - Return string buffer "CKF_xxx\0" for a token flag */ +const char *token_ckf2str(CK_ULONG flag); + +/* mecha_ckf2str - Return string buffer "CKF_xxx\0" for a mechanism flag */ +const char *mecha_ckf2str(CK_ULONG flag); + +/* session_ckf2str - Return string buffer "CKF_xxx\0" for a session flag */ +const char *session_ckf2str(CK_ULONG flag); + +/* session_cks2str - Return string buffer "CKS_xxx\0" for a session state */ +const char *session_cks2str(CK_ULONG flag); + +/* Return a pointer to a string buffer of "CKA_xxx\0" attribute ID */ +const char *cka2str(CK_ATTRIBUTE_TYPE id); + +/* Return a pointer to a string buffer of "CKO_xxx\0" object class ID */ +const char *cko2str(CK_OBJECT_CLASS id); + +/* Return a pointer to a string buffer of "CKK_xxx\0" key type ID */ +const char *ckk2str(CK_KEY_TYPE id); + +#endif /*LIBCKTEEC_CK_DEBUG_H*/ diff --git a/optee/optee_client/libckteec/include/pkcs11.h b/optee/optee_client/libckteec/include/pkcs11.h new file mode 100644 index 0000000..6d7a0f7 --- /dev/null +++ b/optee/optee_client/libckteec/include/pkcs11.h @@ -0,0 +1,1248 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#ifndef PKCS11_H +#define PKCS11_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * PKCS#11 Cryptoki API v2.40-errata01, See specification from: + * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/errata01/os/pkcs11-base-v2.40-errata01-os-complete.html + */ +#define CK_PKCS11_VERSION_MAJOR 2 +#define CK_PKCS11_VERSION_MINOR 40 +#define CK_PKCS11_VERSION_PATCH 1 + +typedef unsigned char CK_BYTE; +typedef unsigned long CK_ULONG; +typedef long CK_LONG; + +typedef CK_BYTE CK_CHAR; +typedef CK_BYTE CK_UTF8CHAR; + +typedef CK_BYTE *CK_BYTE_PTR; + +typedef CK_ULONG *CK_ULONG_PTR; + +typedef CK_CHAR *CK_CHAR_PTR; +typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; + +typedef void *CK_VOID_PTR; +typedef CK_VOID_PTR *CK_VOID_PTR_PTR; + +typedef CK_BYTE CK_BBOOL; + +#define CK_TRUE 1 +#define CK_FALSE 0 + +typedef CK_ULONG CK_FLAGS; + +#define CK_UNAVAILABLE_INFORMATION (~0UL) +#define CK_EFFECTIVELY_INFINITE 0UL + +typedef CK_ULONG CK_SESSION_HANDLE; +typedef CK_SESSION_HANDLE *CK_SESSION_HANDLE_PTR; + +typedef CK_ULONG CK_OBJECT_HANDLE; +typedef CK_OBJECT_HANDLE *CK_OBJECT_HANDLE_PTR; + +#define CK_INVALID_HANDLE 0 + +typedef CK_ULONG CK_SLOT_ID; +typedef CK_SLOT_ID *CK_SLOT_ID_PTR; + +typedef struct CK_VERSION CK_VERSION; +typedef struct CK_VERSION *CK_VERSION_PTR; + +struct CK_VERSION { + CK_BYTE major; + CK_BYTE minor; +}; + +typedef struct CK_DATE CK_DATE; +typedef struct CK_DATE *CK_DATE_PTR; + +struct CK_DATE { + CK_CHAR year[4]; + CK_CHAR month[2]; + CK_CHAR day[2]; +}; + +/* + * PKCS#11 Objects attributes + */ + +typedef CK_ULONG CK_ATTRIBUTE_TYPE; + +typedef struct CK_ATTRIBUTE CK_ATTRIBUTE; +typedef struct CK_ATTRIBUTE *CK_ATTRIBUTE_PTR; + +struct CK_ATTRIBUTE { + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; +}; + +/* + * Values for CK_ATTRIBUTE_TYPE + * + * This does not cover the full PKCS#11 IDs. + */ +#define CKF_ARRAY_ATTRIBUTE (1U << 30) +#define CKA_VENDOR_DEFINED (1U << 31) +#define CKA_CLASS 0x0000 +#define CKA_TOKEN 0x0001 +#define CKA_PRIVATE 0x0002 +#define CKA_LABEL 0x0003 +#define CKA_APPLICATION 0x0010 +#define CKA_VALUE 0x0011 +#define CKA_OBJECT_ID 0x0012 +#define CKA_CERTIFICATE_TYPE 0x0080 +#define CKA_ISSUER 0x0081 +#define CKA_SERIAL_NUMBER 0x0082 +#define CKA_AC_ISSUER 0x0083 +#define CKA_OWNER 0x0084 +#define CKA_ATTR_TYPES 0x0085 +#define CKA_TRUSTED 0x0086 +#define CKA_CERTIFICATE_CATEGORY 0x0087 +#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x0088 +#define CKA_URL 0x0089 +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x008a +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x008b +#define CKA_NAME_HASH_ALGORITHM 0x008c +#define CKA_CHECK_VALUE 0x0090 +#define CKA_KEY_TYPE 0x0100 +#define CKA_SUBJECT 0x0101 +#define CKA_ID 0x0102 +#define CKA_SENSITIVE 0x0103 +#define CKA_ENCRYPT 0x0104 +#define CKA_DECRYPT 0x0105 +#define CKA_WRAP 0x0106 +#define CKA_UNWRAP 0x0107 +#define CKA_SIGN 0x0108 +#define CKA_SIGN_RECOVER 0x0109 +#define CKA_VERIFY 0x010a +#define CKA_VERIFY_RECOVER 0x010b +#define CKA_DERIVE 0x010c +#define CKA_START_DATE 0x0110 +#define CKA_END_DATE 0x0111 +#define CKA_MODULUS 0x0120 +#define CKA_MODULUS_BITS 0x0121 +#define CKA_PUBLIC_EXPONENT 0x0122 +#define CKA_PRIVATE_EXPONENT 0x0123 +#define CKA_PRIME_1 0x0124 +#define CKA_PRIME_2 0x0125 +#define CKA_EXPONENT_1 0x0126 +#define CKA_EXPONENT_2 0x0127 +#define CKA_COEFFICIENT 0x0128 +#define CKA_PUBLIC_KEY_INFO 0x0129 +#define CKA_PRIME 0x0130 +#define CKA_SUBPRIME 0x0131 +#define CKA_BASE 0x0132 +#define CKA_PRIME_BITS 0x0133 +#define CKA_SUBPRIME_BITS 0x0134 +#define CKA_VALUE_BITS 0x0160 +#define CKA_VALUE_LEN 0x0161 +#define CKA_EXTRACTABLE 0x0162 +#define CKA_LOCAL 0x0163 +#define CKA_NEVER_EXTRACTABLE 0x0164 +#define CKA_ALWAYS_SENSITIVE 0x0165 +#define CKA_KEY_GEN_MECHANISM 0x0166 +#define CKA_MODIFIABLE 0x0170 +#define CKA_COPYABLE 0x0171 +#define CKA_DESTROYABLE 0x0172 +#define CKA_EC_PARAMS 0x0180 +#define CKA_EC_POINT 0x0181 +#define CKA_ALWAYS_AUTHENTICATE 0x0202 +#define CKA_WRAP_WITH_TRUSTED 0x0210 +#define CKA_WRAP_TEMPLATE (0x0211 | CKF_ARRAY_ATTRIBUTE) +#define CKA_UNWRAP_TEMPLATE (0x0212 | CKF_ARRAY_ATTRIBUTE) +#define CKA_DERIVE_TEMPLATE (0x0213 | CKF_ARRAY_ATTRIBUTE) +#define CKA_OTP_FORMAT 0x0220 +#define CKA_OTP_LENGTH 0x0221 +#define CKA_OTP_TIME_INTERVAL 0x0222 +#define CKA_OTP_USER_FRIENDLY_MODE 0x0223 +#define CKA_OTP_CHALLENGE_REQUIREMENT 0x0224 +#define CKA_OTP_TIME_REQUIREMENT 0x0225 +#define CKA_OTP_COUNTER_REQUIREMENT 0x0226 +#define CKA_OTP_PIN_REQUIREMENT 0x0227 +#define CKA_OTP_COUNTER 0x022e +#define CKA_OTP_TIME 0x022f +#define CKA_OTP_USER_IDENTIFIER 0x022a +#define CKA_OTP_SERVICE_IDENTIFIER 0x022b +#define CKA_OTP_SERVICE_LOGO 0x022c +#define CKA_OTP_SERVICE_LOGO_TYPE 0x022d +#define CKA_GOSTR3410_PARAMS 0x0250 +#define CKA_GOSTR3411_PARAMS 0x0251 +#define CKA_GOST28147_PARAMS 0x0252 +#define CKA_HW_FEATURE_TYPE 0x0300 +#define CKA_RESET_ON_INIT 0x0301 +#define CKA_HAS_RESET 0x0302 +#define CKA_PIXEL_X 0x0400 +#define CKA_PIXEL_Y 0x0401 +#define CKA_RESOLUTION 0x0402 +#define CKA_CHAR_ROWS 0x0403 +#define CKA_CHAR_COLUMNS 0x0404 +#define CKA_COLOR 0x0405 +#define CKA_BITS_PER_PIXEL 0x0406 +#define CKA_CHAR_SETS 0x0480 +#define CKA_ENCODING_METHODS 0x0481 +#define CKA_MIME_TYPES 0x0482 +#define CKA_MECHANISM_TYPE 0x0500 +#define CKA_REQUIRED_CMS_ATTRIBUTES 0x0501 +#define CKA_DEFAULT_CMS_ATTRIBUTES 0x0502 +#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x0503 +#define CKA_ALLOWED_MECHANISMS (0x0600 | CKF_ARRAY_ATTRIBUTE) + +/* Attribute CKA_CLASS refers to a CK_OBJECT_CLASS typed value */ +typedef CK_ULONG CK_OBJECT_CLASS; +typedef CK_OBJECT_CLASS *CK_OBJECT_CLASS_PTR; + +/* Values for type CK_OBJECT_CLASS */ +#define CKO_VENDOR_DEFINED (1U << 31) +#define CKO_DATA 0x0 +#define CKO_CERTIFICATE 0x1 +#define CKO_PUBLIC_KEY 0x2 +#define CKO_PRIVATE_KEY 0x3 +#define CKO_SECRET_KEY 0x4 +#define CKO_HW_FEATURE 0x5 +#define CKO_DOMAIN_PARAMETERS 0x6 +#define CKO_MECHANISM 0x7 +#define CKO_OTP_KEY 0x8 + +/* Attribute CKA_KEY_TYPE refers to a CK_KEY_TYPE typed value */ +typedef CK_ULONG CK_KEY_TYPE; +typedef CK_KEY_TYPE *CK_KEY_TYPE_PTR; + +/* + * Values for type CK_KEY_TYPE + * + * This does not cover the full PKCS#11 IDs. + */ +#define CKK_VENDOR_DEFINED (1U << 31) +#define CKK_RSA 0x000 +#define CKK_DSA 0x001 +#define CKK_DH 0x002 +#define CKK_ECDSA 0x003 +#define CKK_EC 0x003 +#define CKK_GENERIC_SECRET 0x010 +#define CKK_DES3 0x015 +#define CKK_AES 0x01f +#define CKK_HOTP 0x023 +#define CKK_MD5_HMAC 0x027 +#define CKK_SHA_1_HMAC 0x028 +#define CKK_SHA256_HMAC 0x02b +#define CKK_SHA384_HMAC 0x02c +#define CKK_SHA512_HMAC 0x02d +#define CKK_SHA224_HMAC 0x02e +#define CKK_EC_EDWARDS 0x040 /* PKCS#11 v3.1-cs01 */ + +/* + * Certificates + */ +typedef CK_ULONG CK_CERTIFICATE_TYPE; +typedef CK_ULONG CK_CERTIFICATE_CATEGORY; + +/* + * Valid values for attribute CKA_CERTIFICATE_TYPE + */ +#define CKC_X_509 0x00000000UL +#define CKC_X_509_ATTR_CERT 0x00000001UL +#define CKC_WTLS 0x00000002UL + +/* + * Valid values for attribute CKA_CERTIFICATE_CATEGORY + */ +#define CK_CERTIFICATE_CATEGORY_UNSPECIFIED 0UL +#define CK_CERTIFICATE_CATEGORY_TOKEN_USER 1UL +#define CK_CERTIFICATE_CATEGORY_AUTHORITY 2UL +#define CK_CERTIFICATE_CATEGORY_OTHER_ENTITY 3UL + +/* + * Mechanisms + * + * Note: a mechanism can be referenced as object reference in some PKCS#11 API + * functions. In such case, the object hold attribute CKA_MECHANISM_TYPE which + * refers to a CK_MECHANISM_TYPE typed value that defines the target mechanism. + */ + +typedef CK_ULONG CK_MECHANISM_TYPE; +typedef CK_MECHANISM_TYPE *CK_MECHANISM_TYPE_PTR; + +/* + * Values for type CK_MECHANISM_TYPE + * + * This does not cover the full PKCS#11 IDs. + */ +#define CKM_VENDOR_DEFINED (1U << 31) +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000 +#define CKM_RSA_PKCS 0x00001 +#define CKM_RSA_9796 0x00002 +#define CKM_RSA_X_509 0x00003 +#define CKM_MD5_RSA_PKCS 0x00005 +#define CKM_SHA1_RSA_PKCS 0x00006 +#define CKM_RSA_PKCS_OAEP 0x00009 +#define CKM_RSA_PKCS_PSS 0x0000d +#define CKM_SHA1_RSA_PKCS_PSS 0x0000e +#define CKM_SHA256_RSA_PKCS 0x00040 +#define CKM_SHA384_RSA_PKCS 0x00041 +#define CKM_SHA512_RSA_PKCS 0x00042 +#define CKM_SHA256_RSA_PKCS_PSS 0x00043 +#define CKM_SHA384_RSA_PKCS_PSS 0x00044 +#define CKM_SHA512_RSA_PKCS_PSS 0x00045 +#define CKM_SHA224_RSA_PKCS 0x00046 +#define CKM_SHA224_RSA_PKCS_PSS 0x00047 +#define CKM_SHA512_224 0x00048 +#define CKM_SHA512_224_HMAC 0x00049 +#define CKM_SHA512_224_HMAC_GENERAL 0x0004a +#define CKM_SHA512_224_KEY_DERIVATION 0x0004b +#define CKM_SHA512_256 0x0004c +#define CKM_SHA512_256_HMAC 0x0004d +#define CKM_SHA512_256_HMAC_GENERAL 0x0004e +#define CKM_SHA512_256_KEY_DERIVATION 0x0004f +#define CKM_DES3_ECB 0x00132 +#define CKM_DES3_CBC 0x00133 +#define CKM_DES3_MAC 0x00134 +#define CKM_DES3_MAC_GENERAL 0x00135 +#define CKM_DES3_CBC_PAD 0x00136 +#define CKM_DES3_CMAC_GENERAL 0x00137 +#define CKM_DES3_CMAC 0x00138 +#define CKM_MD5 0x00210 +#define CKM_MD5_HMAC 0x00211 +#define CKM_MD5_HMAC_GENERAL 0x00212 +#define CKM_SHA_1 0x00220 +#define CKM_SHA_1_HMAC 0x00221 +#define CKM_SHA_1_HMAC_GENERAL 0x00222 +#define CKM_SHA256 0x00250 +#define CKM_SHA256_HMAC 0x00251 +#define CKM_SHA256_HMAC_GENERAL 0x00252 +#define CKM_SHA224 0x00255 +#define CKM_SHA224_HMAC 0x00256 +#define CKM_SHA224_HMAC_GENERAL 0x00257 +#define CKM_SHA384 0x00260 +#define CKM_SHA384_HMAC 0x00261 +#define CKM_SHA384_HMAC_GENERAL 0x00262 +#define CKM_SHA512 0x00270 +#define CKM_SHA512_HMAC 0x00271 +#define CKM_SHA512_HMAC_GENERAL 0x00272 +#define CKM_HOTP_KEY_GEN 0x00290 +#define CKM_HOTP 0x00291 +#define CKM_GENERIC_SECRET_KEY_GEN 0x00350 +#define CKM_MD5_KEY_DERIVATION 0x00390 +#define CKM_MD2_KEY_DERIVATION 0x00391 +#define CKM_SHA1_KEY_DERIVATION 0x00392 +#define CKM_SHA256_KEY_DERIVATION 0x00393 +#define CKM_SHA384_KEY_DERIVATION 0x00394 +#define CKM_SHA512_KEY_DERIVATION 0x00395 +#define CKM_SHA224_KEY_DERIVATION 0x00396 +#define CKM_EC_KEY_PAIR_GEN 0x01040 +#define CKM_ECDSA 0x01041 +#define CKM_ECDSA_SHA1 0x01042 +#define CKM_ECDSA_SHA224 0x01043 +#define CKM_ECDSA_SHA256 0x01044 +#define CKM_ECDSA_SHA384 0x01045 +#define CKM_ECDSA_SHA512 0x01046 +#define CKM_ECDH1_DERIVE 0x01050 +#define CKM_ECDH1_COFACTOR_DERIVE 0x01051 +#define CKM_ECMQV_DERIVE 0x01052 +#define CKM_ECDH_AES_KEY_WRAP 0x01053 +#define CKM_RSA_AES_KEY_WRAP 0x01054 +#define CKM_EC_EDWARDS_KEY_PAIR_GEN 0x01055 +#define CKM_EDDSA 0x01057 +#define CKM_AES_KEY_GEN 0x01080 +#define CKM_AES_ECB 0x01081 +#define CKM_AES_CBC 0x01082 +#define CKM_AES_MAC 0x01083 +#define CKM_AES_MAC_GENERAL 0x01084 +#define CKM_AES_CBC_PAD 0x01085 +#define CKM_AES_CTR 0x01086 +#define CKM_AES_GCM 0x01087 +#define CKM_AES_CCM 0x01088 +#define CKM_AES_CTS 0x01089 +#define CKM_AES_CMAC 0x0108a +#define CKM_AES_CMAC_GENERAL 0x0108b +#define CKM_AES_XCBC_MAC 0x0108c +#define CKM_AES_XCBC_MAC_96 0x0108d +#define CKM_AES_GMAC 0x0108e +#define CKM_DES3_ECB_ENCRYPT_DATA 0x01102 +#define CKM_DES3_CBC_ENCRYPT_DATA 0x01103 +#define CKM_AES_ECB_ENCRYPT_DATA 0x01104 +#define CKM_AES_CBC_ENCRYPT_DATA 0x01105 +#define CKM_AES_KEY_WRAP 0x02109 +#define CKM_AES_KEY_WRAP_PAD 0x0210a + +typedef struct CK_MECHANISM_INFO CK_MECHANISM_INFO; +typedef struct CK_MECHANISM_INFO *CK_MECHANISM_INFO_PTR; + +struct CK_MECHANISM_INFO { + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; +}; + +/* Flags for field flags of struct ck_mechanism_info */ +#define CKF_HW (1U << 0) +#define CKF_ENCRYPT (1U << 8) +#define CKF_DECRYPT (1U << 9) +#define CKF_DIGEST (1U << 10) +#define CKF_SIGN (1U << 11) +#define CKF_SIGN_RECOVER (1U << 12) +#define CKF_VERIFY (1U << 13) +#define CKF_VERIFY_RECOVER (1U << 14) +#define CKF_GENERATE (1U << 15) +#define CKF_GENERATE_KEY_PAIR (1U << 16) +#define CKF_WRAP (1U << 17) +#define CKF_UNWRAP (1U << 18) +#define CKF_DERIVE (1U << 19) +#define CKF_EC_F_P (1U << 20) +#define CKF_EC_F_2M (1U << 21) +#define CKF_EC_ECPARAMETERS (1U << 22) +#define CKF_EC_NAMEDCURVE (1U << 23) +#define CKF_EC_UNCOMPRESS (1U << 24) +#define CKF_EC_COMPRESS (1U << 25) +#define CKF_EXTENSION (1U << 31) + +/* + * Mechanism parameter structures + * + * This does not cover the whole mechanism parameter structures defined by + * the PKCS#11. To be updated when needed. + */ + +typedef struct CK_MECHANISM CK_MECHANISM; +typedef struct CK_MECHANISM *CK_MECHANISM_PTR; + +struct CK_MECHANISM { + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + CK_ULONG ulParameterLen; +}; + +typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; + +/* Values for type CK_RSA_PKCS_MGF_TYPE */ +#define CKG_MGF1_SHA1 0x0001UL +#define CKG_MGF1_SHA224 0x0005UL +#define CKG_MGF1_SHA256 0x0002UL +#define CKG_MGF1_SHA384 0x0003UL +#define CKG_MGF1_SHA512 0x0004UL + +typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; + +/* Values for type CK_RSA_PKCS_OAEP_SOURCE_TYPE */ +#define CKZ_DATA_SPECIFIED 0x0001UL + +/* MAC General parameters */ +typedef CK_ULONG CK_MAC_GENERAL_PARAMS; +typedef CK_MAC_GENERAL_PARAMS *CK_MAC_GENERAL_PARAMS_PTR; + +/* + * CK_EC_KDF_TYPE is used to indicate the Key Derivation Function (KDF) applied + * to derive keying data from a shared secret. + */ +typedef CK_ULONG CK_EC_KDF_TYPE; + +/* + * Elliptic curve Diffie-Hellman key derivation + * Elliptic curve Diffie-Hellman cofactor key derivation parameters + */ +typedef struct CK_ECDH1_DERIVE_PARAMS CK_ECDH1_DERIVE_PARAMS; +typedef struct CK_ECDH1_DERIVE_PARAMS *CK_ECDH1_DERIVE_PARAMS_PTR; + +struct CK_ECDH1_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +}; + +/* AES CBC encryption parameters */ +typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_AES_CBC_ENCRYPT_DATA_PARAMS; +typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS + *CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +}; + +/* AES CTR parameters */ +typedef struct CK_AES_CTR_PARAMS CK_AES_CTR_PARAMS; +typedef struct CK_AES_CTR_PARAMS *CK_AES_CTR_PARAMS_PTR; + +struct CK_AES_CTR_PARAMS { + CK_ULONG ulCounterBits; + CK_BYTE cb[16]; +}; + +/* AES GCM parameters */ +typedef struct CK_GCM_PARAMS CK_GCM_PARAMS; +typedef struct CK_GCM_PARAMS *CK_GCM_PARAMS_PTR; + +struct CK_GCM_PARAMS { + CK_BYTE_PTR pIv; + CK_ULONG ulIvLen; + CK_ULONG ulIvBits; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; + CK_ULONG ulTagBits; +}; + +/* EdDSA (RFC 8032) */ +typedef struct CK_EDDSA_PARAMS { + CK_BYTE phFlag; + CK_ULONG ulContextDataLen; + CK_BYTE_PTR pContextData; +} CK_EDDSA_PARAMS; + +typedef CK_EDDSA_PARAMS *CK_EDDSA_PARAMS_PTR; + +/* AES CCM parameters */ +typedef struct CK_CCM_PARAMS CK_CCM_PARAMS; +typedef struct CK_CCM_PARAMS *CK_CCM_PARAMS_PTR; + +struct CK_CCM_PARAMS { + CK_ULONG ulDataLen; + CK_BYTE_PTR pNonce; + CK_ULONG ulNonceLen; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; + CK_ULONG ulMACLen; +}; + +typedef struct CK_KEY_DERIVATION_STRING_DATA CK_KEY_DERIVATION_STRING_DATA; +typedef struct CK_KEY_DERIVATION_STRING_DATA + *CK_KEY_DERIVATION_STRING_DATA_PTR; + +struct CK_KEY_DERIVATION_STRING_DATA { + CK_BYTE_PTR pData; + CK_ULONG ulLen; +}; + +/* Parameters for CKM_RSA_PKCS_PSS */ +typedef struct CK_RSA_PKCS_PSS_PARAMS CK_RSA_PKCS_PSS_PARAMS; +typedef struct CK_RSA_PKCS_PSS_PARAMS *CK_RSA_PKCS_PSS_PARAMS_PTR; + +struct CK_RSA_PKCS_PSS_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_ULONG sLen; +}; + +/* Parameters for CKM_RSA_PKCS_OAEP */ +typedef struct CK_RSA_PKCS_OAEP_PARAMS CK_RSA_PKCS_OAEP_PARAMS; +typedef struct CK_RSA_PKCS_OAEP_PARAMS *CK_RSA_PKCS_OAEP_PARAMS_PTR; + +struct CK_RSA_PKCS_OAEP_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; +}; + +typedef struct CK_RSA_AES_KEY_WRAP_PARAMS { + CK_ULONG ulAESKeyBits; + CK_RSA_PKCS_OAEP_PARAMS_PTR pOAEPParams; +} CK_RSA_AES_KEY_WRAP_PARAMS; + +typedef CK_RSA_AES_KEY_WRAP_PARAMS *CK_RSA_AES_KEY_WRAP_PARAMS_PTR; + +/* + * PKCS#11 return values + */ +typedef CK_ULONG CK_RV; + +/* Values for type CK_RV */ +#define CKR_VENDOR_DEFINED (1U << 31) +#define CKR_OK 0x0000 +#define CKR_CANCEL 0x0001 +#define CKR_HOST_MEMORY 0x0002 +#define CKR_SLOT_ID_INVALID 0x0003 +#define CKR_GENERAL_ERROR 0x0005 +#define CKR_FUNCTION_FAILED 0x0006 +#define CKR_ARGUMENTS_BAD 0x0007 +#define CKR_NO_EVENT 0x0008 +#define CKR_NEED_TO_CREATE_THREADS 0x0009 +#define CKR_CANT_LOCK 0x000a +#define CKR_ATTRIBUTE_READ_ONLY 0x0010 +#define CKR_ATTRIBUTE_SENSITIVE 0x0011 +#define CKR_ATTRIBUTE_TYPE_INVALID 0x0012 +#define CKR_ATTRIBUTE_VALUE_INVALID 0x0013 +#define CKR_ACTION_PROHIBITED 0x001b +#define CKR_DATA_INVALID 0x0020 +#define CKR_DATA_LEN_RANGE 0x0021 +#define CKR_DEVICE_ERROR 0x0030 +#define CKR_DEVICE_MEMORY 0x0031 +#define CKR_DEVICE_REMOVED 0x0032 +#define CKR_ENCRYPTED_DATA_INVALID 0x0040 +#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x0041 +#define CKR_FUNCTION_CANCELED 0x0050 +#define CKR_FUNCTION_NOT_PARALLEL 0x0051 +#define CKR_FUNCTION_NOT_SUPPORTED 0x0054 +#define CKR_KEY_HANDLE_INVALID 0x0060 +#define CKR_KEY_SIZE_RANGE 0x0062 +#define CKR_KEY_TYPE_INCONSISTENT 0x0063 +#define CKR_KEY_NOT_NEEDED 0x0064 +#define CKR_KEY_CHANGED 0x0065 +#define CKR_KEY_NEEDED 0x0066 +#define CKR_KEY_INDIGESTIBLE 0x0067 +#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x0068 +#define CKR_KEY_NOT_WRAPPABLE 0x0069 +#define CKR_KEY_UNEXTRACTABLE 0x006a +#define CKR_MECHANISM_INVALID 0x0070 +#define CKR_MECHANISM_PARAM_INVALID 0x0071 +#define CKR_OBJECT_HANDLE_INVALID 0x0082 +#define CKR_OPERATION_ACTIVE 0x0090 +#define CKR_OPERATION_NOT_INITIALIZED 0x0091 +#define CKR_PIN_INCORRECT 0x00a0 +#define CKR_PIN_INVALID 0x00a1 +#define CKR_PIN_LEN_RANGE 0x00a2 +#define CKR_PIN_EXPIRED 0x00a3 +#define CKR_PIN_LOCKED 0x00a4 +#define CKR_SESSION_CLOSED 0x00b0 +#define CKR_SESSION_COUNT 0x00b1 +#define CKR_SESSION_HANDLE_INVALID 0x00b3 +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x00b4 +#define CKR_SESSION_READ_ONLY 0x00b5 +#define CKR_SESSION_EXISTS 0x00b6 +#define CKR_SESSION_READ_ONLY_EXISTS 0x00b7 +#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x00b8 +#define CKR_SIGNATURE_INVALID 0x00c0 +#define CKR_SIGNATURE_LEN_RANGE 0x00c1 +#define CKR_TEMPLATE_INCOMPLETE 0x00d0 +#define CKR_TEMPLATE_INCONSISTENT 0x00d1 +#define CKR_TOKEN_NOT_PRESENT 0x00e0 +#define CKR_TOKEN_NOT_RECOGNIZED 0x00e1 +#define CKR_TOKEN_WRITE_PROTECTED 0x00e2 +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x00f0 +#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x00f1 +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x00f2 +#define CKR_USER_ALREADY_LOGGED_IN 0x0100 +#define CKR_USER_NOT_LOGGED_IN 0x0101 +#define CKR_USER_PIN_NOT_INITIALIZED 0x0102 +#define CKR_USER_TYPE_INVALID 0x0103 +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x0104 +#define CKR_USER_TOO_MANY_TYPES 0x0105 +#define CKR_WRAPPED_KEY_INVALID 0x0110 +#define CKR_WRAPPED_KEY_LEN_RANGE 0x0112 +#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x0113 +#define CKR_WRAPPING_KEY_SIZE_RANGE 0x0114 +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x0115 +#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x0120 +#define CKR_RANDOM_NO_RNG 0x0121 +#define CKR_DOMAIN_PARAMS_INVALID 0x0130 +#define CKR_CURVE_NOT_SUPPORTED 0x0140 +#define CKR_BUFFER_TOO_SMALL 0x0150 +#define CKR_SAVED_STATE_INVALID 0x0160 +#define CKR_INFORMATION_SENSITIVE 0x0170 +#define CKR_STATE_UNSAVEABLE 0x0180 +#define CKR_CRYPTOKI_NOT_INITIALIZED 0x0190 +#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x0191 +#define CKR_MUTEX_BAD 0x01a0 +#define CKR_MUTEX_NOT_LOCKED 0x01a1 +#define CKR_NEW_PIN_MODE 0x01b0 +#define CKR_NEXT_OTP 0x01b1 +#define CKR_EXCEEDED_MAX_ITERATIONS 0x01b5 +#define CKR_FIPS_SELF_TEST_FAILED 0x01b6 +#define CKR_LIBRARY_LOAD_FAILED 0x01b7 +#define CKR_PIN_TOO_WEAK 0x01b8 +#define CKR_PUBLIC_KEY_INVALID 0x01b9 +#define CKR_FUNCTION_REJECTED 0x0200 + +/* + * PKCS#11 API functions + */ + +/* Argument for C_GetInfo */ +typedef struct CK_INFO CK_INFO; +typedef struct CK_INFO *CK_INFO_PTR; + +struct CK_INFO { + CK_VERSION cryptokiVersion; + CK_UTF8CHAR manufacturerID[32]; + CK_FLAGS flags; + CK_UTF8CHAR libraryDescription[32]; + CK_VERSION libraryVersion; +}; + +/* Argument for C_GetSlotInfo */ +typedef struct CK_SLOT_INFO CK_SLOT_INFO; +typedef struct CK_SLOT_INFO *CK_SLOT_INFO_PTR; + +struct CK_SLOT_INFO { + CK_UTF8CHAR slotDescription[64]; + CK_UTF8CHAR manufacturerID[32]; + CK_FLAGS flags; + CK_VERSION hardwareVersion; + CK_VERSION firmwareVersion; +}; + +/* Values for field flags of struct ck_slot_info */ +#define CKF_TOKEN_PRESENT (1U << 0) +#define CKF_REMOVABLE_DEVICE (1U << 1) +#define CKF_HW_SLOT (1U << 2) + +/* Argument for C_GetTokenInfo */ +typedef struct CK_TOKEN_INFO CK_TOKEN_INFO; +typedef struct CK_TOKEN_INFO *CK_TOKEN_INFO_PTR; + +struct CK_TOKEN_INFO { + CK_UTF8CHAR label[32]; + CK_UTF8CHAR manufacturerID[32]; + CK_UTF8CHAR model[16]; + CK_CHAR serialNumber[16]; + CK_FLAGS flags; + CK_ULONG ulMaxSessionCount; + CK_ULONG ulSessionCount; + CK_ULONG ulMaxRwSessionCount; + CK_ULONG ulRwSessionCount; + CK_ULONG ulMaxPinLen; + CK_ULONG ulMinPinLen; + CK_ULONG ulTotalPublicMemory; + CK_ULONG ulFreePublicMemory; + CK_ULONG ulTotalPrivateMemory; + CK_ULONG ulFreePrivateMemory; + CK_VERSION hardwareVersion; + CK_VERSION firmwareVersion; + CK_CHAR utcTime[16]; +}; + +/* Values for field flags of struct ck_token_info */ +#define CKF_RNG (1U << 0) +#define CKF_WRITE_PROTECTED (1U << 1) +#define CKF_LOGIN_REQUIRED (1U << 2) +#define CKF_USER_PIN_INITIALIZED (1U << 3) +#define CKF_RESTORE_KEY_NOT_NEEDED (1U << 5) +#define CKF_CLOCK_ON_TOKEN (1U << 6) +#define CKF_PROTECTED_AUTHENTICATION_PATH (1U << 8) +#define CKF_DUAL_CRYPTO_OPERATIONS (1U << 9) +#define CKF_TOKEN_INITIALIZED (1U << 10) +#define CKF_SECONDARY_AUTHENTICATION (1U << 11) +#define CKF_USER_PIN_COUNT_LOW (1U << 16) +#define CKF_USER_PIN_FINAL_TRY (1U << 17) +#define CKF_USER_PIN_LOCKED (1U << 18) +#define CKF_USER_PIN_TO_BE_CHANGED (1U << 19) +#define CKF_SO_PIN_COUNT_LOW (1U << 20) +#define CKF_SO_PIN_FINAL_TRY (1U << 21) +#define CKF_SO_PIN_LOCKED (1U << 22) +#define CKF_SO_PIN_TO_BE_CHANGED (1U << 23) +#define CKF_ERROR_STATE (1U << 24) + +/* Argument for C_GetSessionInfo */ +typedef struct CK_SESSION_INFO CK_SESSION_INFO; +typedef struct CK_SESSION_INFO *CK_SESSION_INFO_PTR; + +typedef CK_ULONG CK_STATE; + +/* Values for CK_STATE */ +#define CKS_RO_PUBLIC_SESSION 0 +#define CKS_RO_USER_FUNCTIONS 1 +#define CKS_RW_PUBLIC_SESSION 2 +#define CKS_RW_USER_FUNCTIONS 3 +#define CKS_RW_SO_FUNCTIONS 4 + +struct CK_SESSION_INFO { + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; + CK_ULONG ulDeviceError; +}; + +/* Values for field flags of struct ck_session_info */ +#define CKF_RW_SESSION (1U << 1) +#define CKF_SERIAL_SESSION (1U << 2) + +/* Argument for C_Login */ +typedef CK_ULONG CK_USER_TYPE; + +/* Values for CK_USER_TYPE */ +#define CKU_SO 0 +#define CKU_USER 1 +#define CKU_CONTEXT_SPECIFIC 2 + +/* Values for argument flags of C_WaitForSlotEvent */ +#define CKF_DONT_BLOCK 1 + +/* Argument for CK_NOTIFY typed callback function */ +typedef CK_ULONG CK_NOTIFICATION; + +/* Values for CK_NOTIFICATION */ +#define CKN_SURRENDER 0 +#define CKN_OTP_CHANGED 1 + +/* Callback handler types */ +typedef CK_RV (*CK_NOTIFY) (CK_SESSION_HANDLE hSession, CK_NOTIFICATION event, + CK_VOID_PTR pApplication); +typedef CK_RV (*CK_CREATEMUTEX) (CK_VOID_PTR_PTR ppMutex); +typedef CK_RV (*CK_DESTROYMUTEX) (CK_VOID_PTR pMutex); +typedef CK_RV (*CK_LOCKMUTEX) (CK_VOID_PTR pMutex); +typedef CK_RV (*CK_UNLOCKMUTEX) (CK_VOID_PTR pMutex); + +/* Argument for C_GetFunctionList */ +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; +typedef struct CK_FUNCTION_LIST *CK_FUNCTION_LIST_PTR; +typedef struct CK_FUNCTION_LIST **CK_FUNCTION_LIST_PTR_PTR; + +struct CK_FUNCTION_LIST { + CK_VERSION version; + CK_RV (*C_Initialize)(CK_VOID_PTR pInitArgs); + CK_RV (*C_Finalize)(CK_VOID_PTR pReserved); + CK_RV (*C_GetInfo)(CK_INFO_PTR pInfo); + CK_RV (*C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + CK_RV (*C_GetSlotList)(CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount); + CK_RV (*C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); + CK_RV (*C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); + CK_RV (*C_GetMechanismList)(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount); + CK_RV (*C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo); + CK_RV (*C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel); + CK_RV (*C_InitPIN)(CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); + CK_RV (*C_SetPIN)(CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, + CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen); + CK_RV (*C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, + CK_VOID_PTR pApplication, CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession); + CK_RV (*C_CloseSession)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CloseAllSessions)(CK_SLOT_ID slotID); + CK_RV (*C_GetSessionInfo)(CK_SESSION_HANDLE hSession, + CK_SESSION_INFO_PTR pInfo); + CK_RV (*C_GetOperationState)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG_PTR pulOperationStateLen); + CK_RV (*C_SetOperationState)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG ulOperationStateLen, + CK_OBJECT_HANDLE hEncryptionKey, + CK_OBJECT_HANDLE hAuthenticationKey); + CK_RV (*C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); + CK_RV (*C_Logout)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CreateObject)(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject); + CK_RV (*C_CopyObject)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject); + CK_RV (*C_DestroyObject)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject); + CK_RV (*C_GetObjectSize)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG_PTR pulSize); + CK_RV (*C_GetAttributeValue)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount); + CK_RV (*C_SetAttributeValue)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount); + CK_RV (*C_FindObjectsInit)(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount); + CK_RV (*C_FindObjects)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount); + CK_RV (*C_FindObjectsFinal)(CK_SESSION_HANDLE hSession); + CK_RV (*C_EncryptInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_Encrypt)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen); + CK_RV (*C_EncryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen); + CK_RV (*C_EncryptFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, + CK_ULONG_PTR pulLastEncryptedPartLen); + CK_RV (*C_DecryptInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_Decrypt)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); + CK_RV (*C_DecryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); + CK_RV (*C_DecryptFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastPart, + CK_ULONG_PTR pulLastPartLen); + CK_RV (*C_DigestInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism); + CK_RV (*C_Digest)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen); + CK_RV (*C_DigestUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen); + CK_RV (*C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); + CK_RV (*C_DigestFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen); + CK_RV (*C_SignInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_Sign)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_SignUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen); + CK_RV (*C_SignFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_SignRecoverInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_SignRecover)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_VerifyInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_Verify)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen); + CK_RV (*C_VerifyUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen); + CK_RV (*C_VerifyFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen); + CK_RV (*C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_VerifyRecover)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); + CK_RV (*C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + CK_RV (*C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen); + CK_RV (*C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + CK_RV (*C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen); + CK_RV (*C_GenerateKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_GenerateKeyPair)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey); + CK_RV (*C_WrapKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hWrappingKey, + CK_OBJECT_HANDLE hKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG_PTR pulWrappedKeyLen); + CK_RV (*C_UnwrapKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_DeriveKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_SeedRandom)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen); + CK_RV (*C_GenerateRandom)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pRandomData, + CK_ULONG ulRandomLen); + CK_RV (*C_GetFunctionStatus)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CancelFunction)(CK_SESSION_HANDLE hSession); + CK_RV (*C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR slotID, + CK_VOID_PTR pReserved); +}; + +/* Optional init_args structure for C_Initialize */ +typedef struct CK_C_INITIALIZE_ARGS CK_C_INITIALIZE_ARGS; +typedef struct CK_C_INITIALIZE_ARGS *CK_C_INITIALIZE_ARGS_PTR; + +struct CK_C_INITIALIZE_ARGS { + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR reserved; +}; + +/* Flags for field flags of struct ck_c_initialize_args */ +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1U << 0) +#define CKF_OS_LOCKING_OK (1U << 1) + +CK_RV C_Initialize(CK_VOID_PTR pInitArgs); + +CK_RV C_Finalize(CK_VOID_PTR pReserved); + +CK_RV C_GetInfo(CK_INFO_PTR pInfo); + +CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + +CK_RV C_GetSlotList(CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount); + +CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); + +CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); + +CK_RV C_GetMechanismList(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount); + +CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo); + +CK_RV C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel); + +CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); + +CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, + CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen); + +CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, + CK_VOID_PTR pApplication, CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession); + +CK_RV C_CloseSession(CK_SESSION_HANDLE hSession); + +CK_RV C_CloseAllSessions(CK_SLOT_ID slotID); + +CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo); + +CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG_PTR pulOperationStateLen); + +CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG ulOperationStateLen, + CK_OBJECT_HANDLE hEncryptionKey, + CK_OBJECT_HANDLE hAuthenticationKey); + +CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); + +CK_RV C_Logout(CK_SESSION_HANDLE hSession); + +CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject); + +CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject); + +CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject); + +CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, + CK_ULONG_PTR pulSize); + +CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + +CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + +CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + +CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount); + +CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession); + +CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen); + +CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen); + +CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, + CK_ULONG_PTR pulLastEncryptedPartLen); + +CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); + +CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); + +CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen); + +CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism); + +CK_RV C_Digest(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen); + +CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen); + +CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); + +CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen); + +CK_RV C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); + +CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen); + +CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); + +CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen); + +CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV C_Verify(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen); + +CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen); + +CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen); + +CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + +CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); + +CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + +CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); + +CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + +CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); + +CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + +CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey); + +CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, + CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen); + +CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + +CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + +CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen); + +CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen); + +CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession); + +CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession); + +CK_RV C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR slotID, + CK_VOID_PTR pReserved); + +#ifdef __cplusplus +} +#endif + +#endif /*PKCS11_H*/ diff --git a/optee/optee_client/libckteec/include/pkcs11_ta.h b/optee/optee_client/libckteec/include/pkcs11_ta.h new file mode 100644 index 0000000..063198b --- /dev/null +++ b/optee/optee_client/libckteec/include/pkcs11_ta.h @@ -0,0 +1,1332 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#ifndef PKCS11_TA_H +#define PKCS11_TA_H + +#include +#include + +#define PKCS11_TA_UUID { 0xfd02c9da, 0x306c, 0x48c7, \ + { 0xa4, 0x9c, 0xbb, 0xd8, 0x27, 0xae, 0x86, 0xee } } + +/* PKCS11 trusted application version information */ +#define PKCS11_TA_VERSION_MAJOR 0 +#define PKCS11_TA_VERSION_MINOR 1 +#define PKCS11_TA_VERSION_PATCH 0 + +/* Attribute specific values */ +#define PKCS11_CK_UNAVAILABLE_INFORMATION UINT32_C(0xFFFFFFFF) +#define PKCS11_UNDEFINED_ID UINT32_C(0xFFFFFFFF) +#define PKCS11_FALSE false +#define PKCS11_TRUE true + +/* + * Note on PKCS#11 TA commands ABI + * + * For evolution of the TA API and to not mess with the GPD TEE 4 parameters + * constraint, all the PKCS11 TA invocation commands use a subset of available + * the GPD TEE invocation parameter types. + * + * Param#0 is used for the so-called control arguments of the invoked command + * and for providing a PKCS#11 compliant status code for the request command. + * Param#0 is an in/out memory reference (aka memref[0]). The input buffer + * stores serialized arguments for the command. The output buffer store the + * 32bit TA return code for the command. As a consequence, param#0 shall + * always be an input/output memory reference of at least 32bit, more if + * the command expects more input arguments. + * + * When the TA returns with TEE_SUCCESS result, client shall always get the + * 32bit value stored in param#0 output buffer and use the value as TA + * return code for the invoked command. + * + * Param#1 can be used for input data arguments of the invoked command. + * It is unused or is an input memory reference, aka memref[1]. + * Evolution of the API may use memref[1] for output data as well. + * + * Param#2 is mostly used for output data arguments of the invoked command + * and for output handles generated from invoked commands. + * Few commands uses it for a secondary input data buffer argument. + * It is unused or is an input/output/in-out memory reference, aka memref[2]. + * + * Param#3 is currently unused and reserved for evolution of the API. + */ + +enum pkcs11_ta_cmd { + /* + * PKCS11_CMD_PING Ack TA presence and return version info + * + * [in] memref[0] = 32bit, unused, must be 0 + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = [ + * 32bit version major value, + * 32bit version minor value + * 32bit version patch value + * ] + */ + PKCS11_CMD_PING = 0, + + /* + * PKCS11_CMD_SLOT_LIST - Get the table of the valid slot IDs + * + * [in] memref[0] = 32bit, unused, must be 0 + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit array slot_ids[slot counts] + * + * The TA instance may represent several PKCS#11 slots and + * associated tokens. This commadn reports the IDs of embedded tokens. + * This command relates the PKCS#11 API function C_GetSlotList(). + */ + PKCS11_CMD_SLOT_LIST = 1, + + /* + * PKCS11_CMD_SLOT_INFO - Get cryptoki structured slot information + * + * [in] memref[0] = 32bit slot ID + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_slot_info)info + * + * The TA instance may represent several PKCS#11 slots/tokens. + * This command relates the PKCS#11 API function C_GetSlotInfo(). + */ + PKCS11_CMD_SLOT_INFO = 2, + + /* + * PKCS11_CMD_TOKEN_INFO - Get cryptoki structured token information + * + * [in] memref[0] = 32bit slot ID + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_token_info)info + * + * The TA instance may represent several PKCS#11 slots/tokens. + * This command relates the PKCS#11 API function C_GetTokenInfo(). + */ + PKCS11_CMD_TOKEN_INFO = 3, + + /* + * PKCS11_CMD_MECHANISM_IDS - Get list of the supported mechanisms + * + * [in] memref[0] = 32bit slot ID + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit array mechanism IDs + * + * This command relates to the PKCS#11 API function + * C_GetMechanismList(). + */ + PKCS11_CMD_MECHANISM_IDS = 4, + + /* + * PKCS11_CMD_MECHANISM_INFO - Get information on a specific mechanism + * + * [in] memref[0] = [ + * 32bit slot ID, + * 32bit mechanism ID (PKCS11_CKM_*) + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_mechanism_info)info + * + * This command relates to the PKCS#11 API function + * C_GetMechanismInfo(). + */ + PKCS11_CMD_MECHANISM_INFO = 5, + + /* + * PKCS11_CMD_OPEN_SESSION - Open a session + * + * [in] memref[0] = [ + * 32bit slot ID, + * 32bit session flags, + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit session handle + * + * This command relates to the PKCS#11 API function C_OpenSession(). + */ + PKCS11_CMD_OPEN_SESSION = 6, + + /* + * PKCS11_CMD_CLOSE_SESSION - Close an opened session + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_CloseSession(). + */ + PKCS11_CMD_CLOSE_SESSION = 7, + + /* + * PKCS11_CMD_CLOSE_ALL_SESSIONS - Close all client sessions on token + * + * [in] memref[0] = 32bit slot ID + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function + * C_CloseAllSessions(). + */ + PKCS11_CMD_CLOSE_ALL_SESSIONS = 8, + + /* + * PKCS11_CMD_SESSION_INFO - Get Cryptoki information on a session + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_session_info)info + * + * This command relates to the PKCS#11 API function C_GetSessionInfo(). + */ + PKCS11_CMD_SESSION_INFO = 9, + + /* + * PKCS11_CMD_INIT_TOKEN - Initialize PKCS#11 token + * + * [in] memref[0] = [ + * 32bit slot ID, + * 32bit PIN length, + * byte array label[32] + * byte array PIN[PIN length], + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_InitToken(). + */ + PKCS11_CMD_INIT_TOKEN = 10, + + /* + * PKCS11_CMD_INIT_PIN - Initialize user PIN + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit PIN byte size, + * byte array: PIN data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_InitPIN(). + */ + PKCS11_CMD_INIT_PIN = 11, + + /* + * PKCS11_CMD_SET_PIN - Change user PIN + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit old PIN byte size, + * 32bit new PIN byte size, + * byte array: PIN data, + * byte array: new PIN data, + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_SetPIN(). + */ + PKCS11_CMD_SET_PIN = 12, + + /* + * PKCS11_CMD_LOGIN - Initialize user PIN + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit user identifier, enum pkcs11_user_type + * 32bit PIN byte size, + * byte array: PIN data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_Login(). + */ + PKCS11_CMD_LOGIN = 13, + + /* + * PKCS11_CMD_LOGOUT - Log out from token + * + * [in] memref[0] = [ + * 32bit session handle, + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_Logout(). + */ + PKCS11_CMD_LOGOUT = 14, + + /* + * PKCS11_CMD_CREATE_OBJECT - Create a raw client assembled object in + * the session or token + * + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_CreateObject(). + */ + PKCS11_CMD_CREATE_OBJECT = 15, + + /* + * PKCS11_CMD_DESTROY_OBJECT - Destroy an object + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_DestroyObject(). + */ + PKCS11_CMD_DESTROY_OBJECT = 16, + + /* + * PKCS11_CMD_ENCRYPT_INIT - Initialize encryption processing + * PKCS11_CMD_DECRYPT_INIT - Initialize decryption processing + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle of the key, + * (struct pkcs11_attribute_head)mechanism + mecha params + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * These commands relate to the PKCS#11 API functions + * C_EncryptInit() and C_DecryptInit(). + */ + PKCS11_CMD_ENCRYPT_INIT = 17, + PKCS11_CMD_DECRYPT_INIT = 18, + + /* + * PKCS11_CMD_ENCRYPT_UPDATE - Update encryption processing + * PKCS11_CMD_DECRYPT_UPDATE - Update decryption processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [out] memref[2] = output processed data + * + * These commands relate to the PKCS#11 API functions + * C_EncryptUpdate() and C_DecryptUpdate(). + */ + PKCS11_CMD_ENCRYPT_UPDATE = 19, + PKCS11_CMD_DECRYPT_UPDATE = 20, + + /* + * PKCS11_CMD_ENCRYPT_FINAL - Finalize encryption processing + * PKCS11_CMD_DECRYPT_FINAL - Finalize decryption processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = output processed data + * + * These commands relate to the PKCS#11 API functions + * C_EncryptFinal() and C_DecryptFinal(). + */ + PKCS11_CMD_ENCRYPT_FINAL = 21, + PKCS11_CMD_DECRYPT_FINAL = 22, + + /* + * PKCS11_CMD_ENCRYPT_ONESHOT - Update and finalize encryption + * processing + * PKCS11_CMD_DECRYPT_ONESHOT - Update and finalize decryption + * processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [out] memref[2] = output processed data + * + * These commands relate to the PKCS#11 API functions C_Encrypt and + * C_Decrypt. + */ + PKCS11_CMD_ENCRYPT_ONESHOT = 23, + PKCS11_CMD_DECRYPT_ONESHOT = 24, + + /* + * PKCS11_CMD_SIGN_INIT - Initialize a signature computation + * processing + * PKCS11_CMD_VERIFY_INIT - Initialize a signature verification + * processing + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit key handle, + * (struct pkcs11_attribute_head)mechanism + + * mechanism params, + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * These commands relate to the PKCS#11 API functions C_SignInit() and + * C_VerifyInit(). + */ + PKCS11_CMD_SIGN_INIT = 25, + PKCS11_CMD_VERIFY_INIT = 26, + + /* + * PKCS11_CMD_SIGN_UPDATE - Update a signature computation processing + * PKCS11_CMD_VERIFY_UPDATE - Update a signature verification processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * + * These commands relate to the PKCS#11 API functions C_SignUpdate() and + * C_VerifyUpdate(). + */ + PKCS11_CMD_SIGN_UPDATE = 27, + PKCS11_CMD_VERIFY_UPDATE = 28, + + /* + * PKCS11_CMD_SIGN_FINAL - Finalize a signature computation processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = output signature + * + * This command relates to the PKCS#11 API functions C_SignFinal(). + */ + PKCS11_CMD_SIGN_FINAL = 29, + + /* + * PKCS11_CMD_VERIFY_FINAL - Finalize a signature verification + * processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[2] = input signature to be processed + * + * This command relates to the PKCS#11 API functions C_VerifyFinal(). + */ + PKCS11_CMD_VERIFY_FINAL = 30, + + /* + * PKCS11_CMD_SIGN_ONESHOT - Compute a signature + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [out] memref[2] = byte array: generated signature + * + * This command relates to the PKCS#11 API function C_Sign(). + */ + PKCS11_CMD_SIGN_ONESHOT = 31, + + /* + * PKCS11_CMD_VERIFY_ONESHOT - Compute and compare a signature + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [in] memref[2] = input signature to be processed + * + * This command relates to the PKCS#11 API function C_Verify(). + */ + PKCS11_CMD_VERIFY_ONESHOT = 32, + + /* + * PKCS11_CMD_GENERATE_KEY - Generate a symmetric key or domain + * parameters + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_attribute_head)mechanism + mecha params, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_GenerateKey(). + */ + PKCS11_CMD_GENERATE_KEY = 33, + + /* + * PKCS11_CMD_FIND_OBJECTS_INIT - Initialize an object search + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_FindOjectsInit(). + */ + PKCS11_CMD_FIND_OBJECTS_INIT = 34, + + /* + * PKCS11_CMD_FIND_OBJECTS - Get handles of matching objects + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit array object_handle_array[N] + * + * This command relates to the PKCS#11 API function C_FindOjects(). + * The size of object_handle_array depends on the size of the output + * buffer provided by the client. + */ + PKCS11_CMD_FIND_OBJECTS = 35, + + /* + * PKCS11_CMD_FIND_OBJECTS_FINAL - Finalize current objects search + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_FindOjectsFinal(). + */ + PKCS11_CMD_FIND_OBJECTS_FINAL = 36, + + /* + * PKCS11_CMD_GET_OBJECT_SIZE - Get byte size used by object in the TEE + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object_byte_size + * + * This command relates to the PKCS#11 API function C_GetObjectSize(). + */ + PKCS11_CMD_GET_OBJECT_SIZE = 37, + + /* + * PKCS11_CMD_GET_ATTRIBUTE_VALUE - Get the value of object attribute(s) + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_object_head)attribs + attributes + * data + * + * This command relates to the PKCS#11 API function C_GetAttributeValue. + * Caller provides an attribute template as 3rd argument in memref[0] + * (referred here as attribs + attributes data). Upon successful + * completion, the TA returns the provided template filled with expected + * data through output argument memref[2] (referred here again as + * attribs + attributes data). + */ + PKCS11_CMD_GET_ATTRIBUTE_VALUE = 38, + + /* + * PKCS11_CMD_SET_ATTRIBUTE_VALUE - Set the value of object attribute(s) + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_SetAttributeValue. + * Caller provides an attribute template as 3rd argument in memref[0] + * (referred here as attribs + attributes data). + */ + PKCS11_CMD_SET_ATTRIBUTE_VALUE = 39, + + /* + * PKCS11_CMD_COPY_OBJECT - Copies an object, creating a new object for + * the copy. + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_CopyObject(). + * Caller provides an attribute template as 3rd argument in memref[0] + * (referred here as attribs + attributes data). + */ + PKCS11_CMD_COPY_OBJECT = 40, + + /* + * PKCS11_CMD_SEED_RANDOM - Seed random data generator + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = byte array: seed material to feed into the RNG + * + * This command relates to the PKCS#11 API function C_SeedRandom(). + */ + PKCS11_CMD_SEED_RANDOM = 41, + + /* + * PKCS11_CMD_GENERATE_RANDOM - Generate random data + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = byte array: generated random + * + * This command relates to the PKCS#11 API function C_GenerateRandom(). + */ + PKCS11_CMD_GENERATE_RANDOM = 42, + + /* + * PKCS11_CMD_DERIVE_KEY - Derive a key from a parent key. + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit parent key handle, + * (struct pkcs11_attribute_head)mechanism + mecha params, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_DeriveKey(). + */ + PKCS11_CMD_DERIVE_KEY = 43, + + /* + * PKCS11_CMD_RELEASE_ACTIVE_PROCESSING - Release active processing + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit enum pkcs11_ta_cmd + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command is used to release active processing in case of + * Cryptoki API invocation error is detected in user space processing. + * Function derived from pkcs11_ta_cmd is used to verify that active + * processing matches. + */ + PKCS11_CMD_RELEASE_ACTIVE_PROCESSING = 44, + + /* + * PKCS11_CMD_DIGEST_INIT - Initialize a digest computation processing + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_attribute_head)mechanism + mecha params + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_DigestInit(). + */ + PKCS11_CMD_DIGEST_INIT = 45, + + /* + * PKCS11_CMD_DIGEST_KEY - Update digest with a key + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit key handle + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_DigestKey(). + */ + PKCS11_CMD_DIGEST_KEY = 46, + + /* + * PKCS11_CMD_DIGEST_UPDATE - Update digest with data + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * + * This command relates to the PKCS#11 API function C_DigestUpdate(). + */ + PKCS11_CMD_DIGEST_UPDATE = 47, + + /* + * PKCS11_CMD_DIGEST_FINAL - Finalize a digest computation processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = output digest + * + * This command relates to the PKCS#11 API function C_DigestFinal(). + */ + PKCS11_CMD_DIGEST_FINAL = 48, + + /* + * PKCS11_CMD_DIGEST_ONESHOT - Compute a digest + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [out] memref[2] = byte array: generated digest + * + * This command relates to the PKCS#11 API function C_Digest(). + */ + PKCS11_CMD_DIGEST_ONESHOT = 49, + + /* + * PKCS11_CMD_GENERATE_KEY_PAIR - Generate an asymmetric key pair + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_attribute_head)mechanism + mecha params, + * (struct pkcs11_object_head)public key attribs + + * attributes data, + * (struct pkcs11_object_head)private key attribs + + * attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = [ + * 32bit public key object handle, + * 32bit private key object handle + * ] + * + * This command relates to the PKCS#11 API function + * C_GenerateKeyPair(). + */ + PKCS11_CMD_GENERATE_KEY_PAIR = 50, + + /* + * PKCS11_CMD_WRAP_KEY - Wraps a private or secret key. + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit wrapping key handle, + * 32bit key handle, + * (struct pkcs11_attribute_head)mechanism + mecha params + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = wrapped key + * + * This command relates to the PKCS#11 API function C_WrapKey(). + */ + PKCS11_CMD_WRAP_KEY = 51, + + /* + * PKCS11_CMD_UNWRAP_KEY - Unwraps a wrapped key, creating a new + * private or secret key object. + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit unwrapping key handle, + * (struct pkcs11_attribute_head)mechanism + mecha params, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = wrapped key + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_UnwrapKey(). + */ + PKCS11_CMD_UNWRAP_KEY = 52, +}; + +/* + * Command return codes + * PKCS11_ relates CryptoKi client API CKR_ + */ +enum pkcs11_rc { + PKCS11_CKR_OK = 0, + PKCS11_CKR_CANCEL = 0x0001, + PKCS11_CKR_SLOT_ID_INVALID = 0x0003, + PKCS11_CKR_GENERAL_ERROR = 0x0005, + PKCS11_CKR_FUNCTION_FAILED = 0x0006, + PKCS11_CKR_ARGUMENTS_BAD = 0x0007, + PKCS11_CKR_ATTRIBUTE_READ_ONLY = 0x0010, + PKCS11_CKR_ATTRIBUTE_SENSITIVE = 0x0011, + PKCS11_CKR_ATTRIBUTE_TYPE_INVALID = 0x0012, + PKCS11_CKR_ATTRIBUTE_VALUE_INVALID = 0x0013, + PKCS11_CKR_ACTION_PROHIBITED = 0x001b, + PKCS11_CKR_DATA_INVALID = 0x0020, + PKCS11_CKR_DATA_LEN_RANGE = 0x0021, + PKCS11_CKR_DEVICE_ERROR = 0x0030, + PKCS11_CKR_DEVICE_MEMORY = 0x0031, + PKCS11_CKR_DEVICE_REMOVED = 0x0032, + PKCS11_CKR_ENCRYPTED_DATA_INVALID = 0x0040, + PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE = 0x0041, + PKCS11_CKR_KEY_HANDLE_INVALID = 0x0060, + PKCS11_CKR_KEY_SIZE_RANGE = 0x0062, + PKCS11_CKR_KEY_TYPE_INCONSISTENT = 0x0063, + PKCS11_CKR_KEY_INDIGESTIBLE = 0x0067, + PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED = 0x0068, + PKCS11_CKR_KEY_NOT_WRAPPABLE = 0x0069, + PKCS11_CKR_KEY_UNEXTRACTABLE = 0x006a, + PKCS11_CKR_MECHANISM_INVALID = 0x0070, + PKCS11_CKR_MECHANISM_PARAM_INVALID = 0x0071, + PKCS11_CKR_OBJECT_HANDLE_INVALID = 0x0082, + PKCS11_CKR_OPERATION_ACTIVE = 0x0090, + PKCS11_CKR_OPERATION_NOT_INITIALIZED = 0x0091, + PKCS11_CKR_PIN_INCORRECT = 0x00a0, + PKCS11_CKR_PIN_INVALID = 0x00a1, + PKCS11_CKR_PIN_LEN_RANGE = 0x00a2, + PKCS11_CKR_PIN_EXPIRED = 0x00a3, + PKCS11_CKR_PIN_LOCKED = 0x00a4, + PKCS11_CKR_SESSION_CLOSED = 0x00b0, + PKCS11_CKR_SESSION_COUNT = 0x00b1, + PKCS11_CKR_SESSION_HANDLE_INVALID = 0x00b3, + PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED = 0x00b4, + PKCS11_CKR_SESSION_READ_ONLY = 0x00b5, + PKCS11_CKR_SESSION_EXISTS = 0x00b6, + PKCS11_CKR_SESSION_READ_ONLY_EXISTS = 0x00b7, + PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS = 0x00b8, + PKCS11_CKR_SIGNATURE_INVALID = 0x00c0, + PKCS11_CKR_SIGNATURE_LEN_RANGE = 0x00c1, + PKCS11_CKR_TEMPLATE_INCOMPLETE = 0x00d0, + PKCS11_CKR_TEMPLATE_INCONSISTENT = 0x00d1, + PKCS11_CKR_TOKEN_NOT_PRESENT = 0x00e0, + PKCS11_CKR_TOKEN_NOT_RECOGNIZED = 0x00e1, + PKCS11_CKR_TOKEN_WRITE_PROTECTED = 0x00e2, + PKCS11_CKR_UNWRAPPING_KEY_HANDLE_INVALID = 0x00f0, + PKCS11_CKR_UNWRAPPING_KEY_SIZE_RANGE = 0x00f1, + PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT = 0x00f2, + PKCS11_CKR_USER_ALREADY_LOGGED_IN = 0x0100, + PKCS11_CKR_USER_NOT_LOGGED_IN = 0x0101, + PKCS11_CKR_USER_PIN_NOT_INITIALIZED = 0x0102, + PKCS11_CKR_USER_TYPE_INVALID = 0x0103, + PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN = 0x0104, + PKCS11_CKR_USER_TOO_MANY_TYPES = 0x0105, + PKCS11_CKR_WRAPPED_KEY_INVALID = 0x0110, + PKCS11_CKR_WRAPPED_KEY_LEN_RANGE = 0x0112, + PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID = 0x0113, + PKCS11_CKR_WRAPPING_KEY_SIZE_RANGE = 0x0114, + PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT = 0x0115, + PKCS11_CKR_RANDOM_SEED_NOT_SUPPORTED = 0x0120, + PKCS11_CKR_RANDOM_NO_RNG = 0x0121, + PKCS11_CKR_DOMAIN_PARAMS_INVALID = 0x0130, + PKCS11_CKR_CURVE_NOT_SUPPORTED = 0x0140, + PKCS11_CKR_BUFFER_TOO_SMALL = 0x0150, + PKCS11_CKR_SAVED_STATE_INVALID = 0x0160, + PKCS11_CKR_INFORMATION_SENSITIVE = 0x0170, + PKCS11_CKR_STATE_UNSAVEABLE = 0x0180, + PKCS11_CKR_PIN_TOO_WEAK = 0x01b8, + PKCS11_CKR_PUBLIC_KEY_INVALID = 0x01b9, + PKCS11_CKR_FUNCTION_REJECTED = 0x0200, + /* Vendor specific IDs not returned to client */ + PKCS11_RV_NOT_FOUND = 0x80000000, + PKCS11_RV_NOT_IMPLEMENTED = 0x80000001, +}; + +/* + * Arguments for PKCS11_CMD_SLOT_INFO + */ +#define PKCS11_SLOT_DESC_SIZE 64 +#define PKCS11_SLOT_MANUFACTURER_SIZE 32 +#define PKCS11_SLOT_VERSION_SIZE 2 + +struct pkcs11_slot_info { + uint8_t slot_description[PKCS11_SLOT_DESC_SIZE]; + uint8_t manufacturer_id[PKCS11_SLOT_MANUFACTURER_SIZE]; + uint32_t flags; + uint8_t hardware_version[PKCS11_SLOT_VERSION_SIZE]; + uint8_t firmware_version[PKCS11_SLOT_VERSION_SIZE]; +}; + +/* + * Values for pkcs11_slot_info::flags. + * PKCS11_CKFS_ reflects CryptoKi client API slot flags CKF_. + */ +#define PKCS11_CKFS_TOKEN_PRESENT (1U << 0) +#define PKCS11_CKFS_REMOVABLE_DEVICE (1U << 1) +#define PKCS11_CKFS_HW_SLOT (1U << 2) + +/* + * Arguments for PKCS11_CMD_TOKEN_INFO + */ +#define PKCS11_TOKEN_LABEL_SIZE 32 +#define PKCS11_TOKEN_MANUFACTURER_SIZE 32 +#define PKCS11_TOKEN_MODEL_SIZE 16 +#define PKCS11_TOKEN_SERIALNUM_SIZE 16 + +struct pkcs11_token_info { + uint8_t label[PKCS11_TOKEN_LABEL_SIZE]; + uint8_t manufacturer_id[PKCS11_TOKEN_MANUFACTURER_SIZE]; + uint8_t model[PKCS11_TOKEN_MODEL_SIZE]; + uint8_t serial_number[PKCS11_TOKEN_SERIALNUM_SIZE]; + uint32_t flags; + uint32_t max_session_count; + uint32_t session_count; + uint32_t max_rw_session_count; + uint32_t rw_session_count; + uint32_t max_pin_len; + uint32_t min_pin_len; + uint32_t total_public_memory; + uint32_t free_public_memory; + uint32_t total_private_memory; + uint32_t free_private_memory; + uint8_t hardware_version[2]; + uint8_t firmware_version[2]; + uint8_t utc_time[16]; +}; + +/* + * Values for pkcs11_token_info::flags. + * PKCS11_CKFT_ reflects CryptoKi client API token flags CKF_. + */ +#define PKCS11_CKFT_RNG (1U << 0) +#define PKCS11_CKFT_WRITE_PROTECTED (1U << 1) +#define PKCS11_CKFT_LOGIN_REQUIRED (1U << 2) +#define PKCS11_CKFT_USER_PIN_INITIALIZED (1U << 3) +#define PKCS11_CKFT_RESTORE_KEY_NOT_NEEDED (1U << 5) +#define PKCS11_CKFT_CLOCK_ON_TOKEN (1U << 6) +#define PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH (1U << 8) +#define PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS (1U << 9) +#define PKCS11_CKFT_TOKEN_INITIALIZED (1U << 10) +#define PKCS11_CKFT_SECONDARY_AUTHENTICATION (1U << 11) +#define PKCS11_CKFT_USER_PIN_COUNT_LOW (1U << 16) +#define PKCS11_CKFT_USER_PIN_FINAL_TRY (1U << 17) +#define PKCS11_CKFT_USER_PIN_LOCKED (1U << 18) +#define PKCS11_CKFT_USER_PIN_TO_BE_CHANGED (1U << 19) +#define PKCS11_CKFT_SO_PIN_COUNT_LOW (1U << 20) +#define PKCS11_CKFT_SO_PIN_FINAL_TRY (1U << 21) +#define PKCS11_CKFT_SO_PIN_LOCKED (1U << 22) +#define PKCS11_CKFT_SO_PIN_TO_BE_CHANGED (1U << 23) +#define PKCS11_CKFT_ERROR_STATE (1U << 24) + +/* Values for user identity */ +enum pkcs11_user_type { + PKCS11_CKU_SO = 0x000, + PKCS11_CKU_USER = 0x001, + PKCS11_CKU_CONTEXT_SPECIFIC = 0x002, +}; + +/* + * TEE Identity based authentication for tokens + * + * When configuration CFG_PKCS11_TA_AUTH_TEE_IDENTITY is enabled TEE Identity + * based authentication scheme is enabled. + * + * Feature enablement per token basis is controlled by token flag: + * pkcs11_token_info->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH + * + * When calling C_InitToken() mode is determined based on SO PIN value. + * - If the PIN is empty (or NULL_PTR) then active client TEE Identity will be + * used as SO TEE Identity + * - If the PIN is given then normal PIN behavior is used + * + * Once TEE Identity based authentication is activated following operational + * changes happen: + * - PIN failure counters are disabled to prevent token authentication lockups + * - Switching to different authentication mode needs C_InitToken() + * - When C_Login() or so is performed actual PIN value is ignored and active + * client TEE Identity will be used + * + * Different types of TEE Identity authentication methods can be configured: + * - Configured with C_InitToken(), C_InitPIN() or by C_SetPIN() + * - PIN value follows below PIN syntax + * + * TEE Identity based authenticate PIN syntax: + * - PIN value: NULL_PTR or empty + * - Use active client TEE Identity + * - PIN value: public + * - TEE public login + * - PIN value: user: + * - TEE user login with client UUID matching user credentials + * - PIN value: group: + * - TEE group login with client UUID matching group credentials + */ + +/* Keywords for protected authenticated path PIN parser */ +#define PKCS11_AUTH_TEE_IDENTITY_PUBLIC "public" +#define PKCS11_AUTH_TEE_IDENTITY_USER "user:" +#define PKCS11_AUTH_TEE_IDENTITY_GROUP "group:" + +/* + * Values for 32bit session flags argument to PKCS11_CMD_OPEN_SESSION + * and pkcs11_session_info::flags. + * PKCS11_CKFSS_ reflects CryptoKi client API session flags CKF_. + */ +#define PKCS11_CKFSS_RW_SESSION (1U << 1) +#define PKCS11_CKFSS_SERIAL_SESSION (1U << 2) + +/* + * Arguments for PKCS11_CMD_SESSION_INFO + */ + +struct pkcs11_session_info { + uint32_t slot_id; + uint32_t state; + uint32_t flags; + uint32_t device_error; +}; + +/* Valid values for pkcs11_session_info::state */ +enum pkcs11_session_state { + PKCS11_CKS_RO_PUBLIC_SESSION = 0, + PKCS11_CKS_RO_USER_FUNCTIONS = 1, + PKCS11_CKS_RW_PUBLIC_SESSION = 2, + PKCS11_CKS_RW_USER_FUNCTIONS = 3, + PKCS11_CKS_RW_SO_FUNCTIONS = 4, +}; + +/* + * Arguments for PKCS11_CMD_MECHANISM_INFO + */ + +struct pkcs11_mechanism_info { + uint32_t min_key_size; + uint32_t max_key_size; + uint32_t flags; +}; + +/* + * Values for pkcs11_mechanism_info::flags. + * PKCS11_CKFM_ reflects CryptoKi client API mechanism flags CKF_. + */ +#define PKCS11_CKFM_HW (1U << 0) +#define PKCS11_CKFM_ENCRYPT (1U << 8) +#define PKCS11_CKFM_DECRYPT (1U << 9) +#define PKCS11_CKFM_DIGEST (1U << 10) +#define PKCS11_CKFM_SIGN (1U << 11) +#define PKCS11_CKFM_SIGN_RECOVER (1U << 12) +#define PKCS11_CKFM_VERIFY (1U << 13) +#define PKCS11_CKFM_VERIFY_RECOVER (1U << 14) +#define PKCS11_CKFM_GENERATE (1U << 15) +#define PKCS11_CKFM_GENERATE_KEY_PAIR (1U << 16) +#define PKCS11_CKFM_WRAP (1U << 17) +#define PKCS11_CKFM_UNWRAP (1U << 18) +#define PKCS11_CKFM_DERIVE (1U << 19) +#define PKCS11_CKFM_EC_F_P (1U << 20) +#define PKCS11_CKFM_EC_F_2M (1U << 21) +#define PKCS11_CKFM_EC_ECPARAMETERS (1U << 22) +#define PKCS11_CKFM_EC_NAMEDCURVE (1U << 23) +#define PKCS11_CKFM_EC_UNCOMPRESS (1U << 24) +#define PKCS11_CKFM_EC_COMPRESS (1U << 25) + +/* + * pkcs11_object_head - Header of object whose data are serialized in memory + * + * An object is made of several attributes. Attributes are stored one next to + * the other with byte alignment as a serialized byte array. The byte array + * of serialized attributes is prepended with the size of the attrs[] array + * in bytes and the number of attributes in the array, yielding the struct + * pkcs11_object_head. + * + * @attrs_size - byte size of whole byte array attrs[] + * @attrs_count - number of attribute items stored in attrs[] + * @attrs - then starts the attributes data + */ +struct pkcs11_object_head { + uint32_t attrs_size; + uint32_t attrs_count; + uint8_t attrs[]; +}; + +/* + * Attribute reference in the TA ABI. Each attribute starts with a header + * structure followed by the attribute value. The attribute byte size is + * defined in the attribute header. + * + * @id - the 32bit identifier of the attribute, see PKCS11_CKA_ + * @size - the 32bit value attribute byte size + * @data - then starts the attribute value + */ +struct pkcs11_attribute_head { + uint32_t id; + uint32_t size; + uint8_t data[]; +}; + +/* + * Attribute identification IDs as of v2.40 excluding deprecated IDs. + * Valid values for struct pkcs11_attribute_head::id + * PKCS11_CKA_ reflects CryptoKi client API attribute IDs CKA_. + */ +enum pkcs11_attr_id { + PKCS11_CKA_CLASS = 0x0000, + PKCS11_CKA_TOKEN = 0x0001, + PKCS11_CKA_PRIVATE = 0x0002, + PKCS11_CKA_LABEL = 0x0003, + PKCS11_CKA_APPLICATION = 0x0010, + PKCS11_CKA_VALUE = 0x0011, + PKCS11_CKA_OBJECT_ID = 0x0012, + PKCS11_CKA_CERTIFICATE_TYPE = 0x0080, + PKCS11_CKA_ISSUER = 0x0081, + PKCS11_CKA_SERIAL_NUMBER = 0x0082, + PKCS11_CKA_AC_ISSUER = 0x0083, + PKCS11_CKA_OWNER = 0x0084, + PKCS11_CKA_ATTR_TYPES = 0x0085, + PKCS11_CKA_TRUSTED = 0x0086, + PKCS11_CKA_CERTIFICATE_CATEGORY = 0x0087, + PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN = 0x0088, + PKCS11_CKA_URL = 0x0089, + PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY = 0x008a, + PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY = 0x008b, + PKCS11_CKA_NAME_HASH_ALGORITHM = 0x008c, + PKCS11_CKA_CHECK_VALUE = 0x0090, + PKCS11_CKA_KEY_TYPE = 0x0100, + PKCS11_CKA_SUBJECT = 0x0101, + PKCS11_CKA_ID = 0x0102, + PKCS11_CKA_SENSITIVE = 0x0103, + PKCS11_CKA_ENCRYPT = 0x0104, + PKCS11_CKA_DECRYPT = 0x0105, + PKCS11_CKA_WRAP = 0x0106, + PKCS11_CKA_UNWRAP = 0x0107, + PKCS11_CKA_SIGN = 0x0108, + PKCS11_CKA_SIGN_RECOVER = 0x0109, + PKCS11_CKA_VERIFY = 0x010a, + PKCS11_CKA_VERIFY_RECOVER = 0x010b, + PKCS11_CKA_DERIVE = 0x010c, + PKCS11_CKA_START_DATE = 0x0110, + PKCS11_CKA_END_DATE = 0x0111, + PKCS11_CKA_MODULUS = 0x0120, + PKCS11_CKA_MODULUS_BITS = 0x0121, + PKCS11_CKA_PUBLIC_EXPONENT = 0x0122, + PKCS11_CKA_PRIVATE_EXPONENT = 0x0123, + PKCS11_CKA_PRIME_1 = 0x0124, + PKCS11_CKA_PRIME_2 = 0x0125, + PKCS11_CKA_EXPONENT_1 = 0x0126, + PKCS11_CKA_EXPONENT_2 = 0x0127, + PKCS11_CKA_COEFFICIENT = 0x0128, + PKCS11_CKA_PUBLIC_KEY_INFO = 0x0129, + PKCS11_CKA_PRIME = 0x0130, + PKCS11_CKA_SUBPRIME = 0x0131, + PKCS11_CKA_BASE = 0x0132, + PKCS11_CKA_PRIME_BITS = 0x0133, + PKCS11_CKA_SUBPRIME_BITS = 0x0134, + PKCS11_CKA_VALUE_BITS = 0x0160, + PKCS11_CKA_VALUE_LEN = 0x0161, + PKCS11_CKA_EXTRACTABLE = 0x0162, + PKCS11_CKA_LOCAL = 0x0163, + PKCS11_CKA_NEVER_EXTRACTABLE = 0x0164, + PKCS11_CKA_ALWAYS_SENSITIVE = 0x0165, + PKCS11_CKA_KEY_GEN_MECHANISM = 0x0166, + PKCS11_CKA_MODIFIABLE = 0x0170, + PKCS11_CKA_COPYABLE = 0x0171, + PKCS11_CKA_DESTROYABLE = 0x0172, + PKCS11_CKA_EC_PARAMS = 0x0180, + PKCS11_CKA_EC_POINT = 0x0181, + PKCS11_CKA_ALWAYS_AUTHENTICATE = 0x0202, + PKCS11_CKA_WRAP_WITH_TRUSTED = 0x0210, + /* + * The leading 4 comes from the PKCS#11 spec or:ing with + * CKF_ARRAY_ATTRIBUTE = 0x40000000. + */ + PKCS11_CKA_WRAP_TEMPLATE = 0x40000211, + PKCS11_CKA_UNWRAP_TEMPLATE = 0x40000212, + PKCS11_CKA_DERIVE_TEMPLATE = 0x40000213, + PKCS11_CKA_OTP_FORMAT = 0x0220, + PKCS11_CKA_OTP_LENGTH = 0x0221, + PKCS11_CKA_OTP_TIME_INTERVAL = 0x0222, + PKCS11_CKA_OTP_USER_FRIENDLY_MODE = 0x0223, + PKCS11_CKA_OTP_CHALLENGE_REQUIREMENT = 0x0224, + PKCS11_CKA_OTP_TIME_REQUIREMENT = 0x0225, + PKCS11_CKA_OTP_COUNTER_REQUIREMENT = 0x0226, + PKCS11_CKA_OTP_PIN_REQUIREMENT = 0x0227, + PKCS11_CKA_OTP_COUNTER = 0x022e, + PKCS11_CKA_OTP_TIME = 0x022f, + PKCS11_CKA_OTP_USER_IDENTIFIER = 0x022a, + PKCS11_CKA_OTP_SERVICE_IDENTIFIER = 0x022b, + PKCS11_CKA_OTP_SERVICE_LOGO = 0x022c, + PKCS11_CKA_OTP_SERVICE_LOGO_TYPE = 0x022d, + PKCS11_CKA_GOSTR3410_PARAMS = 0x0250, + PKCS11_CKA_GOSTR3411_PARAMS = 0x0251, + PKCS11_CKA_GOST28147_PARAMS = 0x0252, + PKCS11_CKA_HW_FEATURE_TYPE = 0x0300, + PKCS11_CKA_RESET_ON_INIT = 0x0301, + PKCS11_CKA_HAS_RESET = 0x0302, + PKCS11_CKA_PIXEL_X = 0x0400, + PKCS11_CKA_PIXEL_Y = 0x0401, + PKCS11_CKA_RESOLUTION = 0x0402, + PKCS11_CKA_CHAR_ROWS = 0x0403, + PKCS11_CKA_CHAR_COLUMNS = 0x0404, + PKCS11_CKA_COLOR = 0x0405, + PKCS11_CKA_BITS_PER_PIXEL = 0x0406, + PKCS11_CKA_CHAR_SETS = 0x0480, + PKCS11_CKA_ENCODING_METHODS = 0x0481, + PKCS11_CKA_MIME_TYPES = 0x0482, + PKCS11_CKA_MECHANISM_TYPE = 0x0500, + PKCS11_CKA_REQUIRED_CMS_ATTRIBUTES = 0x0501, + PKCS11_CKA_DEFAULT_CMS_ATTRIBUTES = 0x0502, + PKCS11_CKA_SUPPORTED_CMS_ATTRIBUTES = 0x0503, + /* + * The leading 4 comes from the PKCS#11 spec or:ing with + * CKF_ARRAY_ATTRIBUTE = 0x40000000. + */ + PKCS11_CKA_ALLOWED_MECHANISMS = 0x40000600, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKA_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for attribute PKCS11_CKA_CLASS + * PKCS11_CKO_ reflects CryptoKi client API object class IDs CKO_. + */ +enum pkcs11_class_id { + PKCS11_CKO_DATA = 0x000, + PKCS11_CKO_CERTIFICATE = 0x001, + PKCS11_CKO_PUBLIC_KEY = 0x002, + PKCS11_CKO_PRIVATE_KEY = 0x003, + PKCS11_CKO_SECRET_KEY = 0x004, + PKCS11_CKO_HW_FEATURE = 0x005, + PKCS11_CKO_DOMAIN_PARAMETERS = 0x006, + PKCS11_CKO_MECHANISM = 0x007, + PKCS11_CKO_OTP_KEY = 0x008, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKO_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for attribute PKCS11_CKA_KEY_TYPE + * PKCS11_CKK_ reflects CryptoKi client API key type IDs CKK_. + * Note that this is only a subset of the PKCS#11 specification. + */ +enum pkcs11_key_type { + PKCS11_CKK_RSA = 0x000, + PKCS11_CKK_DSA = 0x001, + PKCS11_CKK_DH = 0x002, + PKCS11_CKK_EC = 0x003, + PKCS11_CKK_GENERIC_SECRET = 0x010, + PKCS11_CKK_AES = 0x01f, + PKCS11_CKK_MD5_HMAC = 0x027, + PKCS11_CKK_SHA_1_HMAC = 0x028, + PKCS11_CKK_SHA256_HMAC = 0x02b, + PKCS11_CKK_SHA384_HMAC = 0x02c, + PKCS11_CKK_SHA512_HMAC = 0x02d, + PKCS11_CKK_SHA224_HMAC = 0x02e, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKK_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for attribute PKCS11_CKA_CERTIFICATE_TYPE + */ +enum pkcs11_certificate_type { + PKCS11_CKC_X_509 = 0x00000000UL, + PKCS11_CKC_X_509_ATTR_CERT = 0x00000001UL, + PKCS11_CKC_WTLS = 0x00000002UL, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKC_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for attribute PKCS11_CKA_CERTIFICATE_CATEGORY + */ +enum pkcs11_certificate_category { + PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0UL, + PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1UL, + PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY = 2UL, + PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 3UL, +}; + +/* + * Valid values for mechanism IDs + * PKCS11_CKM_ reflects CryptoKi client API mechanism IDs CKM_. + */ +enum pkcs11_mechanism_id { + PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000, + PKCS11_CKM_RSA_PKCS = 0x00001, + PKCS11_CKM_RSA_9796 = 0x00002, + PKCS11_CKM_RSA_X_509 = 0x00003, + PKCS11_CKM_MD5_RSA_PKCS = 0x00005, + PKCS11_CKM_SHA1_RSA_PKCS = 0x00006, + PKCS11_CKM_RSA_PKCS_OAEP = 0x00009, + PKCS11_CKM_RSA_PKCS_PSS = 0x0000d, + PKCS11_CKM_SHA1_RSA_PKCS_PSS = 0x0000e, + PKCS11_CKM_SHA256_RSA_PKCS = 0x00040, + PKCS11_CKM_SHA384_RSA_PKCS = 0x00041, + PKCS11_CKM_SHA512_RSA_PKCS = 0x00042, + PKCS11_CKM_SHA256_RSA_PKCS_PSS = 0x00043, + PKCS11_CKM_SHA384_RSA_PKCS_PSS = 0x00044, + PKCS11_CKM_SHA512_RSA_PKCS_PSS = 0x00045, + PKCS11_CKM_SHA224_RSA_PKCS = 0x00046, + PKCS11_CKM_SHA224_RSA_PKCS_PSS = 0x00047, + PKCS11_CKM_SHA512_224 = 0x00048, + PKCS11_CKM_SHA512_224_HMAC = 0x00049, + PKCS11_CKM_SHA512_224_HMAC_GENERAL = 0x0004a, + PKCS11_CKM_SHA512_224_KEY_DERIVATION = 0x0004b, + PKCS11_CKM_SHA512_256 = 0x0004c, + PKCS11_CKM_SHA512_256_HMAC = 0x0004d, + PKCS11_CKM_SHA512_256_HMAC_GENERAL = 0x0004e, + PKCS11_CKM_SHA512_256_KEY_DERIVATION = 0x0004f, + PKCS11_CKM_DES3_ECB = 0x00132, + PKCS11_CKM_DES3_CBC = 0x00133, + PKCS11_CKM_DES3_MAC = 0x00134, + PKCS11_CKM_DES3_MAC_GENERAL = 0x00135, + PKCS11_CKM_DES3_CBC_PAD = 0x00136, + PKCS11_CKM_DES3_CMAC_GENERAL = 0x00137, + PKCS11_CKM_DES3_CMAC = 0x00138, + PKCS11_CKM_MD5 = 0x00210, + PKCS11_CKM_MD5_HMAC = 0x00211, + PKCS11_CKM_MD5_HMAC_GENERAL = 0x00212, + PKCS11_CKM_SHA_1 = 0x00220, + PKCS11_CKM_SHA_1_HMAC = 0x00221, + PKCS11_CKM_SHA_1_HMAC_GENERAL = 0x00222, + PKCS11_CKM_SHA256 = 0x00250, + PKCS11_CKM_SHA256_HMAC = 0x00251, + PKCS11_CKM_SHA256_HMAC_GENERAL = 0x00252, + PKCS11_CKM_SHA224 = 0x00255, + PKCS11_CKM_SHA224_HMAC = 0x00256, + PKCS11_CKM_SHA224_HMAC_GENERAL = 0x00257, + PKCS11_CKM_SHA384 = 0x00260, + PKCS11_CKM_SHA384_HMAC = 0x00261, + PKCS11_CKM_SHA384_HMAC_GENERAL = 0x00262, + PKCS11_CKM_SHA512 = 0x00270, + PKCS11_CKM_SHA512_HMAC = 0x00271, + PKCS11_CKM_SHA512_HMAC_GENERAL = 0x00272, + PKCS11_CKM_HOTP_KEY_GEN = 0x00290, + PKCS11_CKM_HOTP = 0x00291, + PKCS11_CKM_GENERIC_SECRET_KEY_GEN = 0x00350, + PKCS11_CKM_MD5_KEY_DERIVATION = 0x00390, + PKCS11_CKM_MD2_KEY_DERIVATION = 0x00391, + PKCS11_CKM_SHA1_KEY_DERIVATION = 0x00392, + PKCS11_CKM_SHA256_KEY_DERIVATION = 0x00393, + PKCS11_CKM_SHA384_KEY_DERIVATION = 0x00394, + PKCS11_CKM_SHA512_KEY_DERIVATION = 0x00395, + PKCS11_CKM_SHA224_KEY_DERIVATION = 0x00396, + PKCS11_CKM_EC_KEY_PAIR_GEN = 0x01040, + PKCS11_CKM_ECDSA = 0x01041, + PKCS11_CKM_ECDSA_SHA1 = 0x01042, + PKCS11_CKM_ECDSA_SHA224 = 0x01043, + PKCS11_CKM_ECDSA_SHA256 = 0x01044, + PKCS11_CKM_ECDSA_SHA384 = 0x01045, + PKCS11_CKM_ECDSA_SHA512 = 0x01046, + PKCS11_CKM_ECDH1_DERIVE = 0x01050, + PKCS11_CKM_ECDH1_COFACTOR_DERIVE = 0x01051, + PKCS11_CKM_ECMQV_DERIVE = 0x01052, + PKCS11_CKM_ECDH_AES_KEY_WRAP = 0x01053, + PKCS11_CKM_RSA_AES_KEY_WRAP = 0x01054, + PKCS11_CKM_EDDSA = 0x01057, + PKCS11_CKM_AES_KEY_GEN = 0x01080, + PKCS11_CKM_AES_ECB = 0x01081, + PKCS11_CKM_AES_CBC = 0x01082, + PKCS11_CKM_AES_MAC = 0x01083, + PKCS11_CKM_AES_MAC_GENERAL = 0x01084, + PKCS11_CKM_AES_CBC_PAD = 0x01085, + PKCS11_CKM_AES_CTR = 0x01086, + PKCS11_CKM_AES_GCM = 0x01087, + PKCS11_CKM_AES_CCM = 0x01088, + PKCS11_CKM_AES_CTS = 0x01089, + PKCS11_CKM_AES_CMAC = 0x0108a, + PKCS11_CKM_AES_CMAC_GENERAL = 0x0108b, + PKCS11_CKM_AES_XCBC_MAC = 0x0108c, + PKCS11_CKM_AES_XCBC_MAC_96 = 0x0108d, + PKCS11_CKM_AES_GMAC = 0x0108e, + PKCS11_CKM_DES3_ECB_ENCRYPT_DATA = 0x01102, + PKCS11_CKM_DES3_CBC_ENCRYPT_DATA = 0x01103, + PKCS11_CKM_AES_ECB_ENCRYPT_DATA = 0x01104, + PKCS11_CKM_AES_CBC_ENCRYPT_DATA = 0x01105, + PKCS11_CKM_AES_KEY_WRAP = 0x02109, + PKCS11_CKM_AES_KEY_WRAP_PAD = 0x0210a, + /* + * Vendor extensions below. + * PKCS11 added IDs for operation not related to a CK mechanism ID + */ + PKCS11_PROCESSING_IMPORT = 0x80000000, + PKCS11_CKM_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values MG function identifiers + * PKCS11_CKG_ reflects CryptoKi client API MG function IDs CKG_. + */ +enum pkcs11_mgf_id { + PKCS11_CKG_MGF1_SHA1 = 0x0001, + PKCS11_CKG_MGF1_SHA224 = 0x0005, + PKCS11_CKG_MGF1_SHA256 = 0x0002, + PKCS11_CKG_MGF1_SHA384 = 0x0003, + PKCS11_CKG_MGF1_SHA512 = 0x0004, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKG_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for RSA PKCS/OAEP source type identifier + * PKCS11_CKZ_ reflects CryptoKi client API source type IDs CKZ_. + */ +#define PKCS11_CKZ_DATA_SPECIFIED 0x0001 + +#endif /*PKCS11_TA_H*/ diff --git a/optee/optee_client/libckteec/src/ck_debug.c b/optee/optee_client/libckteec/src/ck_debug.c new file mode 100644 index 0000000..49a5015 --- /dev/null +++ b/optee/optee_client/libckteec/src/ck_debug.c @@ -0,0 +1,460 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "local_utils.h" + +#define CK2STR_ENTRY(id) case id: return #id + +const char *ckr2str(CK_RV id) +{ + switch (id) { + CK2STR_ENTRY(CKR_OK); + CK2STR_ENTRY(CKR_CANCEL); + CK2STR_ENTRY(CKR_HOST_MEMORY); + CK2STR_ENTRY(CKR_SLOT_ID_INVALID); + CK2STR_ENTRY(CKR_GENERAL_ERROR); + CK2STR_ENTRY(CKR_FUNCTION_FAILED); + CK2STR_ENTRY(CKR_ARGUMENTS_BAD); + CK2STR_ENTRY(CKR_NO_EVENT); + CK2STR_ENTRY(CKR_NEED_TO_CREATE_THREADS); + CK2STR_ENTRY(CKR_CANT_LOCK); + CK2STR_ENTRY(CKR_ATTRIBUTE_READ_ONLY); + CK2STR_ENTRY(CKR_ATTRIBUTE_SENSITIVE); + CK2STR_ENTRY(CKR_ATTRIBUTE_TYPE_INVALID); + CK2STR_ENTRY(CKR_ATTRIBUTE_VALUE_INVALID); + CK2STR_ENTRY(CKR_ACTION_PROHIBITED); + CK2STR_ENTRY(CKR_DATA_INVALID); + CK2STR_ENTRY(CKR_DATA_LEN_RANGE); + CK2STR_ENTRY(CKR_DEVICE_ERROR); + CK2STR_ENTRY(CKR_DEVICE_MEMORY); + CK2STR_ENTRY(CKR_DEVICE_REMOVED); + CK2STR_ENTRY(CKR_ENCRYPTED_DATA_INVALID); + CK2STR_ENTRY(CKR_ENCRYPTED_DATA_LEN_RANGE); + CK2STR_ENTRY(CKR_FUNCTION_CANCELED); + CK2STR_ENTRY(CKR_FUNCTION_NOT_PARALLEL); + CK2STR_ENTRY(CKR_FUNCTION_NOT_SUPPORTED); + CK2STR_ENTRY(CKR_KEY_HANDLE_INVALID); + CK2STR_ENTRY(CKR_KEY_SIZE_RANGE); + CK2STR_ENTRY(CKR_KEY_TYPE_INCONSISTENT); + CK2STR_ENTRY(CKR_KEY_NOT_NEEDED); + CK2STR_ENTRY(CKR_KEY_CHANGED); + CK2STR_ENTRY(CKR_KEY_NEEDED); + CK2STR_ENTRY(CKR_KEY_INDIGESTIBLE); + CK2STR_ENTRY(CKR_KEY_FUNCTION_NOT_PERMITTED); + CK2STR_ENTRY(CKR_KEY_NOT_WRAPPABLE); + CK2STR_ENTRY(CKR_KEY_UNEXTRACTABLE); + CK2STR_ENTRY(CKR_MECHANISM_INVALID); + CK2STR_ENTRY(CKR_MECHANISM_PARAM_INVALID); + CK2STR_ENTRY(CKR_OBJECT_HANDLE_INVALID); + CK2STR_ENTRY(CKR_OPERATION_ACTIVE); + CK2STR_ENTRY(CKR_OPERATION_NOT_INITIALIZED); + CK2STR_ENTRY(CKR_PIN_INCORRECT); + CK2STR_ENTRY(CKR_PIN_INVALID); + CK2STR_ENTRY(CKR_PIN_LEN_RANGE); + CK2STR_ENTRY(CKR_PIN_EXPIRED); + CK2STR_ENTRY(CKR_PIN_LOCKED); + CK2STR_ENTRY(CKR_SESSION_CLOSED); + CK2STR_ENTRY(CKR_SESSION_COUNT); + CK2STR_ENTRY(CKR_SESSION_HANDLE_INVALID); + CK2STR_ENTRY(CKR_SESSION_PARALLEL_NOT_SUPPORTED); + CK2STR_ENTRY(CKR_SESSION_READ_ONLY); + CK2STR_ENTRY(CKR_SESSION_EXISTS); + CK2STR_ENTRY(CKR_SESSION_READ_ONLY_EXISTS); + CK2STR_ENTRY(CKR_SESSION_READ_WRITE_SO_EXISTS); + CK2STR_ENTRY(CKR_SIGNATURE_INVALID); + CK2STR_ENTRY(CKR_SIGNATURE_LEN_RANGE); + CK2STR_ENTRY(CKR_TEMPLATE_INCOMPLETE); + CK2STR_ENTRY(CKR_TEMPLATE_INCONSISTENT); + CK2STR_ENTRY(CKR_TOKEN_NOT_PRESENT); + CK2STR_ENTRY(CKR_TOKEN_NOT_RECOGNIZED); + CK2STR_ENTRY(CKR_TOKEN_WRITE_PROTECTED); + CK2STR_ENTRY(CKR_UNWRAPPING_KEY_HANDLE_INVALID); + CK2STR_ENTRY(CKR_UNWRAPPING_KEY_SIZE_RANGE); + CK2STR_ENTRY(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT); + CK2STR_ENTRY(CKR_USER_ALREADY_LOGGED_IN); + CK2STR_ENTRY(CKR_USER_NOT_LOGGED_IN); + CK2STR_ENTRY(CKR_USER_PIN_NOT_INITIALIZED); + CK2STR_ENTRY(CKR_USER_TYPE_INVALID); + CK2STR_ENTRY(CKR_USER_ANOTHER_ALREADY_LOGGED_IN); + CK2STR_ENTRY(CKR_USER_TOO_MANY_TYPES); + CK2STR_ENTRY(CKR_WRAPPED_KEY_INVALID); + CK2STR_ENTRY(CKR_WRAPPED_KEY_LEN_RANGE); + CK2STR_ENTRY(CKR_WRAPPING_KEY_HANDLE_INVALID); + CK2STR_ENTRY(CKR_WRAPPING_KEY_SIZE_RANGE); + CK2STR_ENTRY(CKR_WRAPPING_KEY_TYPE_INCONSISTENT); + CK2STR_ENTRY(CKR_RANDOM_SEED_NOT_SUPPORTED); + CK2STR_ENTRY(CKR_RANDOM_NO_RNG); + CK2STR_ENTRY(CKR_DOMAIN_PARAMS_INVALID); + CK2STR_ENTRY(CKR_CURVE_NOT_SUPPORTED); + CK2STR_ENTRY(CKR_BUFFER_TOO_SMALL); + CK2STR_ENTRY(CKR_SAVED_STATE_INVALID); + CK2STR_ENTRY(CKR_INFORMATION_SENSITIVE); + CK2STR_ENTRY(CKR_STATE_UNSAVEABLE); + CK2STR_ENTRY(CKR_CRYPTOKI_NOT_INITIALIZED); + CK2STR_ENTRY(CKR_CRYPTOKI_ALREADY_INITIALIZED); + CK2STR_ENTRY(CKR_MUTEX_BAD); + CK2STR_ENTRY(CKR_MUTEX_NOT_LOCKED); + CK2STR_ENTRY(CKR_NEW_PIN_MODE); + CK2STR_ENTRY(CKR_NEXT_OTP); + CK2STR_ENTRY(CKR_EXCEEDED_MAX_ITERATIONS); + CK2STR_ENTRY(CKR_FIPS_SELF_TEST_FAILED); + CK2STR_ENTRY(CKR_LIBRARY_LOAD_FAILED); + CK2STR_ENTRY(CKR_PIN_TOO_WEAK); + CK2STR_ENTRY(CKR_PUBLIC_KEY_INVALID); + CK2STR_ENTRY(CKR_FUNCTION_REJECTED); + default: + if (id & CKR_VENDOR_DEFINED) + return "Vendor defined"; + else + return "Unknown ID"; + } +} + +const char *ckm2str(CK_MECHANISM_TYPE id) +{ + switch (id) { + CK2STR_ENTRY(CKM_RSA_PKCS_KEY_PAIR_GEN); + CK2STR_ENTRY(CKM_RSA_PKCS); + CK2STR_ENTRY(CKM_RSA_9796); + CK2STR_ENTRY(CKM_RSA_X_509); + CK2STR_ENTRY(CKM_MD5_RSA_PKCS); + CK2STR_ENTRY(CKM_SHA1_RSA_PKCS); + CK2STR_ENTRY(CKM_RSA_PKCS_OAEP); + CK2STR_ENTRY(CKM_RSA_PKCS_PSS); + CK2STR_ENTRY(CKM_SHA1_RSA_PKCS_PSS); + CK2STR_ENTRY(CKM_SHA256_RSA_PKCS); + CK2STR_ENTRY(CKM_SHA384_RSA_PKCS); + CK2STR_ENTRY(CKM_SHA512_RSA_PKCS); + CK2STR_ENTRY(CKM_SHA256_RSA_PKCS_PSS); + CK2STR_ENTRY(CKM_SHA384_RSA_PKCS_PSS); + CK2STR_ENTRY(CKM_SHA512_RSA_PKCS_PSS); + CK2STR_ENTRY(CKM_SHA224_RSA_PKCS); + CK2STR_ENTRY(CKM_SHA224_RSA_PKCS_PSS); + CK2STR_ENTRY(CKM_SHA512_224); + CK2STR_ENTRY(CKM_SHA512_224_HMAC); + CK2STR_ENTRY(CKM_SHA512_224_HMAC_GENERAL); + CK2STR_ENTRY(CKM_SHA512_224_KEY_DERIVATION); + CK2STR_ENTRY(CKM_SHA512_256); + CK2STR_ENTRY(CKM_SHA512_256_HMAC); + CK2STR_ENTRY(CKM_SHA512_256_HMAC_GENERAL); + CK2STR_ENTRY(CKM_SHA512_256_KEY_DERIVATION); + CK2STR_ENTRY(CKM_MD5); + CK2STR_ENTRY(CKM_MD5_HMAC); + CK2STR_ENTRY(CKM_MD5_HMAC_GENERAL); + CK2STR_ENTRY(CKM_SHA_1); + CK2STR_ENTRY(CKM_SHA_1_HMAC); + CK2STR_ENTRY(CKM_SHA_1_HMAC_GENERAL); + CK2STR_ENTRY(CKM_SHA256); + CK2STR_ENTRY(CKM_SHA256_HMAC); + CK2STR_ENTRY(CKM_SHA256_HMAC_GENERAL); + CK2STR_ENTRY(CKM_SHA224); + CK2STR_ENTRY(CKM_SHA224_HMAC); + CK2STR_ENTRY(CKM_SHA224_HMAC_GENERAL); + CK2STR_ENTRY(CKM_SHA384); + CK2STR_ENTRY(CKM_SHA384_HMAC); + CK2STR_ENTRY(CKM_SHA384_HMAC_GENERAL); + CK2STR_ENTRY(CKM_SHA512); + CK2STR_ENTRY(CKM_SHA512_HMAC); + CK2STR_ENTRY(CKM_SHA512_HMAC_GENERAL); + CK2STR_ENTRY(CKM_HOTP_KEY_GEN); + CK2STR_ENTRY(CKM_HOTP); + CK2STR_ENTRY(CKM_GENERIC_SECRET_KEY_GEN); + CK2STR_ENTRY(CKM_SHA1_KEY_DERIVATION); + CK2STR_ENTRY(CKM_SHA256_KEY_DERIVATION); + CK2STR_ENTRY(CKM_SHA384_KEY_DERIVATION); + CK2STR_ENTRY(CKM_SHA512_KEY_DERIVATION); + CK2STR_ENTRY(CKM_SHA224_KEY_DERIVATION); + CK2STR_ENTRY(CKM_EC_KEY_PAIR_GEN); + CK2STR_ENTRY(CKM_ECDSA); + CK2STR_ENTRY(CKM_ECDSA_SHA1); + CK2STR_ENTRY(CKM_ECDSA_SHA224); + CK2STR_ENTRY(CKM_ECDSA_SHA256); + CK2STR_ENTRY(CKM_ECDSA_SHA384); + CK2STR_ENTRY(CKM_ECDSA_SHA512); + CK2STR_ENTRY(CKM_ECDH1_DERIVE); + CK2STR_ENTRY(CKM_ECDH1_COFACTOR_DERIVE); + CK2STR_ENTRY(CKM_ECMQV_DERIVE); + CK2STR_ENTRY(CKM_ECDH_AES_KEY_WRAP); + CK2STR_ENTRY(CKM_RSA_AES_KEY_WRAP); + CK2STR_ENTRY(CKM_AES_KEY_GEN); + CK2STR_ENTRY(CKM_AES_ECB); + CK2STR_ENTRY(CKM_AES_CBC); + CK2STR_ENTRY(CKM_AES_MAC); + CK2STR_ENTRY(CKM_AES_MAC_GENERAL); + CK2STR_ENTRY(CKM_AES_CBC_PAD); + CK2STR_ENTRY(CKM_AES_CTR); + CK2STR_ENTRY(CKM_AES_GCM); + CK2STR_ENTRY(CKM_AES_CCM); + CK2STR_ENTRY(CKM_AES_CTS); + CK2STR_ENTRY(CKM_AES_CMAC); + CK2STR_ENTRY(CKM_AES_CMAC_GENERAL); + CK2STR_ENTRY(CKM_AES_XCBC_MAC); + CK2STR_ENTRY(CKM_AES_XCBC_MAC_96); + CK2STR_ENTRY(CKM_AES_GMAC); + CK2STR_ENTRY(CKM_DES3_ECB_ENCRYPT_DATA); + CK2STR_ENTRY(CKM_DES3_CBC_ENCRYPT_DATA); + CK2STR_ENTRY(CKM_AES_ECB_ENCRYPT_DATA); + CK2STR_ENTRY(CKM_AES_CBC_ENCRYPT_DATA); + CK2STR_ENTRY(CKM_AES_KEY_WRAP); + CK2STR_ENTRY(CKM_AES_KEY_WRAP_PAD); + default: + if (id & CKM_VENDOR_DEFINED) + return "Vendor defined"; + else + return "Unknown ID"; + } +} + +const char *slot_ckf2str(CK_ULONG flag) +{ + switch (flag) { + CK2STR_ENTRY(CKF_TOKEN_PRESENT); + CK2STR_ENTRY(CKF_REMOVABLE_DEVICE); + CK2STR_ENTRY(CKF_HW_SLOT); + default: + return "Unknown flag"; + } +} + +const char *token_ckf2str(CK_ULONG flag) +{ + switch (flag) { + CK2STR_ENTRY(CKF_RNG); + CK2STR_ENTRY(CKF_WRITE_PROTECTED); + CK2STR_ENTRY(CKF_LOGIN_REQUIRED); + CK2STR_ENTRY(CKF_USER_PIN_INITIALIZED); + CK2STR_ENTRY(CKF_RESTORE_KEY_NOT_NEEDED); + CK2STR_ENTRY(CKF_CLOCK_ON_TOKEN); + CK2STR_ENTRY(CKF_PROTECTED_AUTHENTICATION_PATH); + CK2STR_ENTRY(CKF_DUAL_CRYPTO_OPERATIONS); + CK2STR_ENTRY(CKF_TOKEN_INITIALIZED); + CK2STR_ENTRY(CKF_SECONDARY_AUTHENTICATION); + CK2STR_ENTRY(CKF_USER_PIN_COUNT_LOW); + CK2STR_ENTRY(CKF_USER_PIN_FINAL_TRY); + CK2STR_ENTRY(CKF_USER_PIN_LOCKED); + CK2STR_ENTRY(CKF_USER_PIN_TO_BE_CHANGED); + CK2STR_ENTRY(CKF_SO_PIN_COUNT_LOW); + CK2STR_ENTRY(CKF_SO_PIN_FINAL_TRY); + CK2STR_ENTRY(CKF_SO_PIN_LOCKED); + CK2STR_ENTRY(CKF_SO_PIN_TO_BE_CHANGED); + CK2STR_ENTRY(CKF_ERROR_STATE); + default: + return "Unknown flag"; + } +} + +const char *mecha_ckf2str(CK_ULONG flag) +{ + switch (flag) { + CK2STR_ENTRY(CKF_HW); + CK2STR_ENTRY(CKF_ENCRYPT); + CK2STR_ENTRY(CKF_DECRYPT); + CK2STR_ENTRY(CKF_DIGEST); + CK2STR_ENTRY(CKF_SIGN); + CK2STR_ENTRY(CKF_SIGN_RECOVER); + CK2STR_ENTRY(CKF_VERIFY); + CK2STR_ENTRY(CKF_VERIFY_RECOVER); + CK2STR_ENTRY(CKF_GENERATE); + CK2STR_ENTRY(CKF_GENERATE_KEY_PAIR); + CK2STR_ENTRY(CKF_WRAP); + CK2STR_ENTRY(CKF_UNWRAP); + CK2STR_ENTRY(CKF_DERIVE); + CK2STR_ENTRY(CKF_EC_F_P); + CK2STR_ENTRY(CKF_EC_F_2M); + CK2STR_ENTRY(CKF_EC_ECPARAMETERS); + CK2STR_ENTRY(CKF_EC_NAMEDCURVE); + CK2STR_ENTRY(CKF_EC_UNCOMPRESS); + CK2STR_ENTRY(CKF_EC_COMPRESS); + CK2STR_ENTRY(CKF_EXTENSION); + default: + return "Unknown flag"; + } +} + +const char *session_ckf2str(CK_ULONG flag) +{ + switch (flag) { + CK2STR_ENTRY(CKF_RW_SESSION); + CK2STR_ENTRY(CKF_SERIAL_SESSION); + default: + return "Unknown flag"; + } +} + +const char *session_cks2str(CK_ULONG flag) +{ + switch (flag) { + CK2STR_ENTRY(CKS_RO_PUBLIC_SESSION); + CK2STR_ENTRY(CKS_RO_USER_FUNCTIONS); + CK2STR_ENTRY(CKS_RW_PUBLIC_SESSION); + CK2STR_ENTRY(CKS_RW_USER_FUNCTIONS); + CK2STR_ENTRY(CKS_RW_SO_FUNCTIONS); + default: + return "Unknown flag"; + } +} + +const char *cka2str(CK_ATTRIBUTE_TYPE id) +{ + switch (id) { + /* Standard CK attributes */ + CK2STR_ENTRY(CKA_CLASS); + CK2STR_ENTRY(CKA_TOKEN); + CK2STR_ENTRY(CKA_PRIVATE); + CK2STR_ENTRY(CKA_LABEL); + CK2STR_ENTRY(CKA_APPLICATION); + CK2STR_ENTRY(CKA_VALUE); + CK2STR_ENTRY(CKA_OBJECT_ID); + CK2STR_ENTRY(CKA_CERTIFICATE_TYPE); + CK2STR_ENTRY(CKA_ISSUER); + CK2STR_ENTRY(CKA_SERIAL_NUMBER); + CK2STR_ENTRY(CKA_AC_ISSUER); + CK2STR_ENTRY(CKA_OWNER); + CK2STR_ENTRY(CKA_ATTR_TYPES); + CK2STR_ENTRY(CKA_TRUSTED); + CK2STR_ENTRY(CKA_CERTIFICATE_CATEGORY); + CK2STR_ENTRY(CKA_JAVA_MIDP_SECURITY_DOMAIN); + CK2STR_ENTRY(CKA_URL); + CK2STR_ENTRY(CKA_HASH_OF_SUBJECT_PUBLIC_KEY); + CK2STR_ENTRY(CKA_HASH_OF_ISSUER_PUBLIC_KEY); + CK2STR_ENTRY(CKA_NAME_HASH_ALGORITHM); + CK2STR_ENTRY(CKA_CHECK_VALUE); + CK2STR_ENTRY(CKA_KEY_TYPE); + CK2STR_ENTRY(CKA_SUBJECT); + CK2STR_ENTRY(CKA_ID); + CK2STR_ENTRY(CKA_SENSITIVE); + CK2STR_ENTRY(CKA_ENCRYPT); + CK2STR_ENTRY(CKA_DECRYPT); + CK2STR_ENTRY(CKA_WRAP); + CK2STR_ENTRY(CKA_UNWRAP); + CK2STR_ENTRY(CKA_SIGN); + CK2STR_ENTRY(CKA_SIGN_RECOVER); + CK2STR_ENTRY(CKA_VERIFY); + CK2STR_ENTRY(CKA_VERIFY_RECOVER); + CK2STR_ENTRY(CKA_DERIVE); + CK2STR_ENTRY(CKA_START_DATE); + CK2STR_ENTRY(CKA_END_DATE); + CK2STR_ENTRY(CKA_MODULUS); + CK2STR_ENTRY(CKA_MODULUS_BITS); + CK2STR_ENTRY(CKA_PUBLIC_EXPONENT); + CK2STR_ENTRY(CKA_PRIVATE_EXPONENT); + CK2STR_ENTRY(CKA_PRIME_1); + CK2STR_ENTRY(CKA_PRIME_2); + CK2STR_ENTRY(CKA_EXPONENT_1); + CK2STR_ENTRY(CKA_EXPONENT_2); + CK2STR_ENTRY(CKA_COEFFICIENT); + CK2STR_ENTRY(CKA_PUBLIC_KEY_INFO); + CK2STR_ENTRY(CKA_PRIME); + CK2STR_ENTRY(CKA_SUBPRIME); + CK2STR_ENTRY(CKA_BASE); + CK2STR_ENTRY(CKA_PRIME_BITS); + CK2STR_ENTRY(CKA_SUBPRIME_BITS); + CK2STR_ENTRY(CKA_VALUE_BITS); + CK2STR_ENTRY(CKA_VALUE_LEN); + CK2STR_ENTRY(CKA_EXTRACTABLE); + CK2STR_ENTRY(CKA_LOCAL); + CK2STR_ENTRY(CKA_NEVER_EXTRACTABLE); + CK2STR_ENTRY(CKA_ALWAYS_SENSITIVE); + CK2STR_ENTRY(CKA_KEY_GEN_MECHANISM); + CK2STR_ENTRY(CKA_MODIFIABLE); + CK2STR_ENTRY(CKA_COPYABLE); + CK2STR_ENTRY(CKA_DESTROYABLE); + CK2STR_ENTRY(CKA_EC_PARAMS); + CK2STR_ENTRY(CKA_EC_POINT); + CK2STR_ENTRY(CKA_ALWAYS_AUTHENTICATE); + CK2STR_ENTRY(CKA_WRAP_WITH_TRUSTED); + CK2STR_ENTRY(CKA_WRAP_TEMPLATE); + CK2STR_ENTRY(CKA_UNWRAP_TEMPLATE); + CK2STR_ENTRY(CKA_DERIVE_TEMPLATE); + CK2STR_ENTRY(CKA_OTP_FORMAT); + CK2STR_ENTRY(CKA_OTP_LENGTH); + CK2STR_ENTRY(CKA_OTP_TIME_INTERVAL); + CK2STR_ENTRY(CKA_OTP_USER_FRIENDLY_MODE); + CK2STR_ENTRY(CKA_OTP_CHALLENGE_REQUIREMENT); + CK2STR_ENTRY(CKA_OTP_TIME_REQUIREMENT); + CK2STR_ENTRY(CKA_OTP_COUNTER_REQUIREMENT); + CK2STR_ENTRY(CKA_OTP_PIN_REQUIREMENT); + CK2STR_ENTRY(CKA_OTP_COUNTER); + CK2STR_ENTRY(CKA_OTP_TIME); + CK2STR_ENTRY(CKA_OTP_USER_IDENTIFIER); + CK2STR_ENTRY(CKA_OTP_SERVICE_IDENTIFIER); + CK2STR_ENTRY(CKA_OTP_SERVICE_LOGO); + CK2STR_ENTRY(CKA_OTP_SERVICE_LOGO_TYPE); + CK2STR_ENTRY(CKA_GOSTR3410_PARAMS); + CK2STR_ENTRY(CKA_GOSTR3411_PARAMS); + CK2STR_ENTRY(CKA_GOST28147_PARAMS); + CK2STR_ENTRY(CKA_HW_FEATURE_TYPE); + CK2STR_ENTRY(CKA_RESET_ON_INIT); + CK2STR_ENTRY(CKA_HAS_RESET); + CK2STR_ENTRY(CKA_PIXEL_X); + CK2STR_ENTRY(CKA_PIXEL_Y); + CK2STR_ENTRY(CKA_RESOLUTION); + CK2STR_ENTRY(CKA_CHAR_ROWS); + CK2STR_ENTRY(CKA_CHAR_COLUMNS); + CK2STR_ENTRY(CKA_COLOR); + CK2STR_ENTRY(CKA_BITS_PER_PIXEL); + CK2STR_ENTRY(CKA_CHAR_SETS); + CK2STR_ENTRY(CKA_ENCODING_METHODS); + CK2STR_ENTRY(CKA_MIME_TYPES); + CK2STR_ENTRY(CKA_MECHANISM_TYPE); + CK2STR_ENTRY(CKA_REQUIRED_CMS_ATTRIBUTES); + CK2STR_ENTRY(CKA_DEFAULT_CMS_ATTRIBUTES); + CK2STR_ENTRY(CKA_SUPPORTED_CMS_ATTRIBUTES); + CK2STR_ENTRY(CKA_ALLOWED_MECHANISMS); + CK2STR_ENTRY(CKA_VENDOR_DEFINED); + default: + if (id & CKA_VENDOR_DEFINED) + return "Vendor defined"; + else + return "Unknown ID"; + } +} + +const char *cko2str(CK_OBJECT_CLASS id) +{ + switch (id) { + CK2STR_ENTRY(CKO_DATA); + CK2STR_ENTRY(CKO_CERTIFICATE); + CK2STR_ENTRY(CKO_PUBLIC_KEY); + CK2STR_ENTRY(CKO_PRIVATE_KEY); + CK2STR_ENTRY(CKO_SECRET_KEY); + CK2STR_ENTRY(CKO_HW_FEATURE); + CK2STR_ENTRY(CKO_DOMAIN_PARAMETERS); + CK2STR_ENTRY(CKO_MECHANISM); + CK2STR_ENTRY(CKO_OTP_KEY); + CK2STR_ENTRY(CKO_VENDOR_DEFINED); + default: + return "Unknown"; + } +} + +const char *ckk2str(CK_KEY_TYPE id) +{ + switch (id) { + CK2STR_ENTRY(CKK_RSA); + CK2STR_ENTRY(CKK_DSA); + CK2STR_ENTRY(CKK_DH); + CK2STR_ENTRY(CKK_ECDSA); + CK2STR_ENTRY(CKK_GENERIC_SECRET); + CK2STR_ENTRY(CKK_DES3); + CK2STR_ENTRY(CKK_AES); + CK2STR_ENTRY(CKK_HOTP); + CK2STR_ENTRY(CKK_MD5_HMAC); + CK2STR_ENTRY(CKK_SHA_1_HMAC); + CK2STR_ENTRY(CKK_SHA256_HMAC); + CK2STR_ENTRY(CKK_SHA384_HMAC); + CK2STR_ENTRY(CKK_SHA512_HMAC); + CK2STR_ENTRY(CKK_SHA224_HMAC); + CK2STR_ENTRY(CKK_VENDOR_DEFINED); + default: + return "Unknown"; + } +} diff --git a/optee/optee_client/libckteec/src/ck_helpers.c b/optee/optee_client/libckteec/src/ck_helpers.c new file mode 100644 index 0000000..776c115 --- /dev/null +++ b/optee/optee_client/libckteec/src/ck_helpers.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "ck_helpers.h" + +#ifdef DEBUG +void ckteec_assert_expected_rv(const char *function, CK_RV rv, + const CK_RV *expected_rv, size_t expected_count) +{ + size_t n = 0; + + for (n = 0; n < expected_count; n++) + if (rv == expected_rv[n]) + return; + + fprintf(stderr, "libckteec: %s: unexpected return value 0x%lx (%s)\n", + function, rv, ckr2str(rv)); + + assert(0); +} +#endif diff --git a/optee/optee_client/libckteec/src/ck_helpers.h b/optee/optee_client/libckteec/src/ck_helpers.h new file mode 100644 index 0000000..e00a798 --- /dev/null +++ b/optee/optee_client/libckteec/src/ck_helpers.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef LIBCKTEEC_CK_HELPERS_H +#define LIBCKTEEC_CK_HELPERS_H + +#include +#include + +#include "local_utils.h" + +#ifdef DEBUG +#define ASSERT_CK_RV(_rv, ...) \ + do { \ + const CK_RV ref[] = { __VA_ARGS__ }; \ + size_t count = ARRAY_SIZE(ref); \ + \ + ckteec_assert_expected_rv(__func__, (_rv), ref, count); \ + } while (0) + +void ckteec_assert_expected_rv(const char *function, CK_RV rv, + const CK_RV *expected_rv, size_t expected_count); +#else +#define ASSERT_CK_RV(_rv, ...) (void)0 +#endif /*DEBUG*/ + +#endif /*LIBCKTEEC_CK_HELPERS_H*/ diff --git a/optee/optee_client/libckteec/src/invoke_ta.c b/optee/optee_client/libckteec/src/invoke_ta.c new file mode 100644 index 0000000..07b110e --- /dev/null +++ b/optee/optee_client/libckteec/src/invoke_ta.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +/* BINARY_PREFIX is expected by teec_trace.h */ +#ifndef BINARY_PREFIX +#define BINARY_PREFIX "ckteec" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ck_helpers.h" +#include "invoke_ta.h" +#include "local_utils.h" + +struct ta_context { + pthread_mutex_t init_mutex; + bool initiated; + TEEC_Context context; + TEEC_Session session; +}; + +static struct ta_context ta_ctx = { + .init_mutex = PTHREAD_MUTEX_INITIALIZER, +}; + +bool ckteec_invoke_initiated(void) +{ + return ta_ctx.initiated; +} + +TEEC_SharedMemory *ckteec_alloc_shm(size_t size, enum ckteec_shm_dir dir) +{ + TEEC_SharedMemory *shm = NULL; + + switch (dir) { + case CKTEEC_SHM_IN: + case CKTEEC_SHM_OUT: + case CKTEEC_SHM_INOUT: + break; + default: + return NULL; + } + + shm = calloc(1, sizeof(TEEC_SharedMemory)); + if (!shm) + return NULL; + + shm->size = size; + + if (dir == CKTEEC_SHM_IN || dir == CKTEEC_SHM_INOUT) + shm->flags |= TEEC_MEM_INPUT; + if (dir == CKTEEC_SHM_OUT || dir == CKTEEC_SHM_INOUT) + shm->flags |= TEEC_MEM_OUTPUT; + + if (TEEC_AllocateSharedMemory(&ta_ctx.context, shm)) { + free(shm); + return NULL; + } + + return shm; +} + +TEEC_SharedMemory *ckteec_register_shm(void *buffer, size_t size, + enum ckteec_shm_dir dir) +{ + TEEC_SharedMemory *shm = NULL; + + switch (dir) { + case CKTEEC_SHM_IN: + case CKTEEC_SHM_OUT: + case CKTEEC_SHM_INOUT: + break; + default: + return NULL; + } + + shm = calloc(1, sizeof(TEEC_SharedMemory)); + if (!shm) + return NULL; + + shm->buffer = buffer; + shm->size = size; + + if (dir == CKTEEC_SHM_IN || dir == CKTEEC_SHM_INOUT) + shm->flags |= TEEC_MEM_INPUT; + if (dir == CKTEEC_SHM_OUT || dir == CKTEEC_SHM_INOUT) + shm->flags |= TEEC_MEM_OUTPUT; + + if (TEEC_RegisterSharedMemory(&ta_ctx.context, shm)) { + free(shm); + return NULL; + } + + return shm; +} + +void ckteec_free_shm(TEEC_SharedMemory *shm) +{ + TEEC_ReleaseSharedMemory(shm); + free(shm); +} + +static bool is_output_shm(TEEC_SharedMemory *shm) +{ + return shm && (shm->flags & TEEC_MEM_OUTPUT); +} + +CK_RV ckteec_invoke_ta(unsigned long cmd, TEEC_SharedMemory *ctrl, + TEEC_SharedMemory *io1, + TEEC_SharedMemory *io2, size_t *out2_size, + TEEC_SharedMemory *io3, size_t *out3_size) +{ + uint32_t command = (uint32_t)cmd; + TEEC_Operation op; + uint32_t origin = 0; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ta_rc = PKCS11_CKR_GENERAL_ERROR; + + if ((is_output_shm(io2) && !out2_size) || + (is_output_shm(io3) && !out3_size)) + return CKR_ARGUMENTS_BAD; + + memset(&op, 0, sizeof(op)); + + if (ctrl && !(ctrl->flags & TEEC_MEM_INPUT && + ctrl->flags & TEEC_MEM_OUTPUT)) + return CKR_ARGUMENTS_BAD; + + if (ctrl) { + op.paramTypes |= TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, 0, 0, 0); + op.params[0].memref.parent = ctrl; + } else { + /* TA mandates param#0 as in/out memref for output status */ + op.paramTypes |= TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, + 0, 0, 0); + op.params[0].tmpref.buffer = &ta_rc; + op.params[0].tmpref.size = sizeof(ta_rc); + } + + if (io1) { + op.paramTypes |= TEEC_PARAM_TYPES(0, TEEC_MEMREF_WHOLE, 0, 0); + op.params[1].memref.parent = io1; + } + + if (io2) { + op.paramTypes |= TEEC_PARAM_TYPES(0, 0, TEEC_MEMREF_WHOLE, 0); + op.params[2].memref.parent = io2; + } + + if (io3) { + op.paramTypes |= TEEC_PARAM_TYPES(0, 0, 0, TEEC_MEMREF_WHOLE); + op.params[3].memref.parent = io3; + } + + res = TEEC_InvokeCommand(&ta_ctx.session, command, &op, &origin); + switch (res) { + case TEEC_SUCCESS: + /* Get PKCS11 TA return value from ctrl buffer */ + if (ctrl) { + if (op.params[0].memref.size == sizeof(ta_rc)) + memcpy(&ta_rc, ctrl->buffer, sizeof(ta_rc)); + } else { + if (op.params[0].tmpref.size != sizeof(ta_rc)) + ta_rc = PKCS11_CKR_GENERAL_ERROR; + } + break; + case TEEC_ERROR_SHORT_BUFFER: + ta_rc = CKR_BUFFER_TOO_SMALL; + break; + case TEEC_ERROR_OUT_OF_MEMORY: + return CKR_DEVICE_MEMORY; + default: + return CKR_GENERAL_ERROR; + } + + if (ta_rc == CKR_OK || ta_rc == CKR_BUFFER_TOO_SMALL) { + if (is_output_shm(io2)) + *out2_size = op.params[2].memref.size; + if (is_output_shm(io3)) + *out3_size = op.params[3].memref.size; + } + + return ta_rc; +} + +static CK_RV ping_ta(void) +{ + TEEC_Operation op = { 0 }; + uint32_t origin = 0; + TEEC_Result res = TEEC_SUCCESS; + uint32_t ta_version[3] = { 0 }; + uint32_t status = 0; + + memset(&op, 0, sizeof(op)); + op.params[0].tmpref.buffer = &status; + op.params[0].tmpref.size = sizeof(status); + op.params[2].tmpref.buffer = ta_version; + op.params[2].tmpref.size = sizeof(ta_version); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, TEEC_NONE, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(&ta_ctx.session, PKCS11_CMD_PING, &op, + &origin); + + if (res != TEEC_SUCCESS || + origin != TEEC_ORIGIN_TRUSTED_APP || + op.params[0].tmpref.size != sizeof(status) || + status != PKCS11_CKR_OK) + return CKR_DEVICE_ERROR; + + if (ta_version[0] != PKCS11_TA_VERSION_MAJOR && + ta_version[1] > PKCS11_TA_VERSION_MINOR) { + EMSG("PKCS11 TA version mismatch: %"PRIu32".%"PRIu32".%"PRIu32, + ta_version[0], ta_version[1], ta_version[2]); + + return CKR_DEVICE_ERROR; + } + + DMSG("PKCS11 TA version %"PRIu32".%"PRIu32".%"PRIu32, + ta_version[0], ta_version[1], ta_version[2]); + + return CKR_OK; +} + +CK_RV ckteec_invoke_init(void) +{ + TEEC_UUID uuid = PKCS11_TA_UUID; + uint32_t origin = 0; + TEEC_Result res = TEEC_SUCCESS; + CK_RV rv = CKR_CRYPTOKI_ALREADY_INITIALIZED; + const char *login_type_env = NULL; + const char *login_gid_env = NULL; + uint32_t login_method = TEEC_LOGIN_PUBLIC; + void *login_data = NULL; + gid_t login_gid = 0; + unsigned long tmpconv = 0; + char *endp = NULL; + int e = 0; + + login_type_env = getenv("CKTEEC_LOGIN_TYPE"); + + if (login_type_env) { + if (strcmp(login_type_env, "public") == 0) { + login_method = TEEC_LOGIN_PUBLIC; + } else if (strcmp(login_type_env, "user") == 0) { + login_method = TEEC_LOGIN_USER; + } else if (strcmp(login_type_env, "group") == 0) { + login_gid_env = getenv("CKTEEC_LOGIN_GID"); + if (!login_gid_env || !strlen(login_gid_env)) { + EMSG("missing CKTEEC_LOGIN_GID"); + rv = CKR_ARGUMENTS_BAD; + goto out; + } + + login_method = TEEC_LOGIN_GROUP; + tmpconv = strtoul(login_gid_env, &endp, 10); + if (errno == ERANGE || tmpconv > (gid_t)-1 || + (login_gid_env + strlen(login_gid_env) != endp)) { + EMSG("failed to convert CKTEEC_LOGIN_GID"); + rv = CKR_ARGUMENTS_BAD; + goto out; + } + + login_gid = (gid_t)tmpconv; + login_data = &login_gid; + } else { + EMSG("invalid value for CKTEEC_LOGIN_TYPE"); + rv = CKR_ARGUMENTS_BAD; + goto out; + } + } + + e = pthread_mutex_lock(&ta_ctx.init_mutex); + if (e) + return CKR_CANT_LOCK; + + if (ta_ctx.initiated) { + rv = CKR_CRYPTOKI_ALREADY_INITIALIZED; + goto out; + } + + res = TEEC_InitializeContext(NULL, &ta_ctx.context); + if (res != TEEC_SUCCESS) { + EMSG("TEEC init context failed\n"); + rv = CKR_DEVICE_ERROR; + goto out; + } + + res = TEEC_OpenSession(&ta_ctx.context, &ta_ctx.session, &uuid, + login_method, login_data, NULL, &origin); + if (res != TEEC_SUCCESS) { + EMSG("TEEC open session failed %x from %d\n", res, origin); + TEEC_FinalizeContext(&ta_ctx.context); + rv = CKR_DEVICE_ERROR; + goto out; + } + + rv = ping_ta(); + + if (rv == CKR_OK) { + ta_ctx.initiated = true; + } else { + TEEC_CloseSession(&ta_ctx.session); + TEEC_FinalizeContext(&ta_ctx.context); + } + +out: + e = pthread_mutex_unlock(&ta_ctx.init_mutex); + if (e) { + EMSG("pthread_mutex_unlock: %s", strerror(e)); + EMSG("terminating..."); + exit(EXIT_FAILURE); + } + + return rv; +} + +CK_RV ckteec_invoke_terminate(void) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + int e = 0; + + e = pthread_mutex_lock(&ta_ctx.init_mutex); + if (e) { + EMSG("pthread_mutex_lock: %s", strerror(e)); + EMSG("terminating..."); + exit(EXIT_FAILURE); + } + + if (!ta_ctx.initiated) + goto out; + + ta_ctx.initiated = false; + TEEC_CloseSession(&ta_ctx.session); + TEEC_FinalizeContext(&ta_ctx.context); + + rv = CKR_OK; + +out: + e = pthread_mutex_unlock(&ta_ctx.init_mutex); + if (e) { + EMSG("pthread_mutex_unlock: %s", strerror(e)); + EMSG("terminating..."); + exit(EXIT_FAILURE); + } + + return rv; +} diff --git a/optee/optee_client/libckteec/src/invoke_ta.h b/optee/optee_client/libckteec/src/invoke_ta.h new file mode 100644 index 0000000..b54f319 --- /dev/null +++ b/optee/optee_client/libckteec/src/invoke_ta.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 20187-2020, Linaro Limited + */ + +#ifndef LIBCKTEEC_INVOKE_TA_H +#define LIBCKTEEC_INVOKE_TA_H + +#include +#include + +enum ckteec_shm_dir { + CKTEEC_SHM_IN, + CKTEEC_SHM_OUT, + CKTEEC_SHM_INOUT, +}; + +/** + * ckteec_alloc_shm - Allocate memory in the TEE SHM (in, out or in/out) + * + * @size - Allocated size in byte + * @dir - Data direction used for the shared memory + * + * Return a shm reference or NULL on failure. + */ +TEEC_SharedMemory *ckteec_alloc_shm(size_t size, enum ckteec_shm_dir dir); + +/** + * ckteec_register_shm - Register memory as shared in the TEE SHM + * + * @buffer - Base address of buffer to register + * @size - Allocated size in byte + * @dir - Data direction used for the shared memory + * + * Return a shm reference or NULL on failure. + */ +TEEC_SharedMemory *ckteec_register_shm(void *buffer, size_t size, + enum ckteec_shm_dir dir); + +/** + * ckteec_free_shm - Release allocated or registered emory in the TEE SHM + * + * @shm - memory reference + */ +void ckteec_free_shm(TEEC_SharedMemory *shm); + +/** + * ckteec_invoke_ta - Invoke PKCS11 TA for a target request through the TEE + * + * @cmd - PKCS11 TA command ID + * @ctrl - shared memory with serialized request input arguments or NULL + * @io1 - In memory buffer argument #1 for the command or NULL + * @io2 - In and/or out memory buffer argument #2 for the command or NULL + * @out2_size - Reference to @io2 output buffer size or NULL if not applicable + * @io3 - In and/or out memory buffer argument #3 for the command or NULL + * @out3_size - Reference to @io3 output buffer size or NULL if not applicable + * + * Return a CR_RV compliant return value + */ +CK_RV ckteec_invoke_ta(unsigned long cmd, TEEC_SharedMemory *ctrl, + TEEC_SharedMemory *io1, + TEEC_SharedMemory *io2, size_t *out2_size, + TEEC_SharedMemory *io3, size_t *out3_size); + +static inline CK_RV ckteec_invoke_ctrl(unsigned long cmd, + TEEC_SharedMemory *ctrl) +{ + return ckteec_invoke_ta(cmd, ctrl, NULL, NULL, NULL, NULL, NULL); +} + +static inline CK_RV ckteec_invoke_ctrl_in(unsigned long cmd, + TEEC_SharedMemory *ctrl, + TEEC_SharedMemory *io1) +{ + return ckteec_invoke_ta(cmd, ctrl, io1, NULL, NULL, NULL, NULL); +} + +static inline CK_RV ckteec_invoke_ctrl_out(unsigned long cmd, + TEEC_SharedMemory *ctrl, + TEEC_SharedMemory *io2, + size_t *out_sz) +{ + return ckteec_invoke_ta(cmd, ctrl, NULL, io2, out_sz, NULL, NULL); +} + +/* + * ckteec_invoke_init - Initialize TEE session with the PKCS11 TA + * + * Return a CR_RV compliant return value + */ +CK_RV ckteec_invoke_init(void); + +/* + * ckteec_invoke_terminate - Release all allocated invocation resources + * + * Return a CR_RV compliant return value + */ +CK_RV ckteec_invoke_terminate(void); + +/* Return true if and only if the PKCS11 TA invocation context is initiated */ +bool ckteec_invoke_initiated(void); + +#endif /*LIBCKTEEC_INVOKE_TA_H*/ diff --git a/optee/optee_client/libckteec/src/local_utils.h b/optee/optee_client/libckteec/src/local_utils.h new file mode 100644 index 0000000..57e46fd --- /dev/null +++ b/optee/optee_client/libckteec/src/local_utils.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef LIBCKTEEC_LOCAL_UTILS_H +#define LIBCKTEEC_LOCAL_UTILS_H + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +#define COMPILE_TIME_ASSERT(x) \ + do { \ + switch (0) { case 0: case ((x) ? 1: 0) : default : break; } \ + } while (0) + +#endif /*LIBCKTEEC_LOCAL_UTILS_H*/ diff --git a/optee/optee_client/libckteec/src/pkcs11_api.c b/optee/optee_client/libckteec/src/pkcs11_api.c new file mode 100644 index 0000000..9b83454 --- /dev/null +++ b/optee/optee_client/libckteec/src/pkcs11_api.c @@ -0,0 +1,1473 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include + +#include "ck_helpers.h" +#include "invoke_ta.h" +#include "pkcs11_processing.h" +#include "pkcs11_token.h" + +static const CK_FUNCTION_LIST libckteec_function_list = { + .version = { + .major = CK_PKCS11_VERSION_MAJOR, + .minor = CK_PKCS11_VERSION_MINOR, + }, + .C_Initialize = C_Initialize, + .C_Finalize = C_Finalize, + .C_GetInfo = C_GetInfo, + .C_GetFunctionList = C_GetFunctionList, + .C_GetSlotList = C_GetSlotList, + .C_GetSlotInfo = C_GetSlotInfo, + .C_GetTokenInfo = C_GetTokenInfo, + .C_GetMechanismList = C_GetMechanismList, + .C_GetMechanismInfo = C_GetMechanismInfo, + .C_InitToken = C_InitToken, + .C_InitPIN = C_InitPIN, + .C_SetPIN = C_SetPIN, + .C_OpenSession = C_OpenSession, + .C_CloseSession = C_CloseSession, + .C_CloseAllSessions = C_CloseAllSessions, + .C_GetSessionInfo = C_GetSessionInfo, + .C_GetOperationState = C_GetOperationState, + .C_SetOperationState = C_SetOperationState, + .C_Login = C_Login, + .C_Logout = C_Logout, + .C_CreateObject = C_CreateObject, + .C_CopyObject = C_CopyObject, + .C_DestroyObject = C_DestroyObject, + .C_GetObjectSize = C_GetObjectSize, + .C_GetAttributeValue = C_GetAttributeValue, + .C_SetAttributeValue = C_SetAttributeValue, + .C_FindObjectsInit = C_FindObjectsInit, + .C_FindObjects = C_FindObjects, + .C_FindObjectsFinal = C_FindObjectsFinal, + .C_EncryptInit = C_EncryptInit, + .C_Encrypt = C_Encrypt, + .C_EncryptUpdate = C_EncryptUpdate, + .C_EncryptFinal = C_EncryptFinal, + .C_DecryptInit = C_DecryptInit, + .C_Decrypt = C_Decrypt, + .C_DecryptUpdate = C_DecryptUpdate, + .C_DecryptFinal = C_DecryptFinal, + .C_DigestInit = C_DigestInit, + .C_Digest = C_Digest, + .C_DigestUpdate = C_DigestUpdate, + .C_DigestKey = C_DigestKey, + .C_DigestFinal = C_DigestFinal, + .C_SignInit = C_SignInit, + .C_Sign = C_Sign, + .C_SignUpdate = C_SignUpdate, + .C_SignFinal = C_SignFinal, + .C_SignRecoverInit = C_SignRecoverInit, + .C_SignRecover = C_SignRecover, + .C_VerifyInit = C_VerifyInit, + .C_Verify = C_Verify, + .C_VerifyUpdate = C_VerifyUpdate, + .C_VerifyFinal = C_VerifyFinal, + .C_VerifyRecoverInit = C_VerifyRecoverInit, + .C_VerifyRecover = C_VerifyRecover, + .C_DigestEncryptUpdate = C_DigestEncryptUpdate, + .C_DecryptDigestUpdate = C_DecryptDigestUpdate, + .C_SignEncryptUpdate = C_SignEncryptUpdate, + .C_DecryptVerifyUpdate = C_DecryptVerifyUpdate, + .C_GenerateKey = C_GenerateKey, + .C_GenerateKeyPair = C_GenerateKeyPair, + .C_WrapKey = C_WrapKey, + .C_UnwrapKey = C_UnwrapKey, + .C_DeriveKey = C_DeriveKey, + .C_SeedRandom = C_SeedRandom, + .C_GenerateRandom = C_GenerateRandom, + .C_GetFunctionStatus = C_GetFunctionStatus, + .C_CancelFunction = C_CancelFunction, + .C_WaitForSlotEvent = C_WaitForSlotEvent, +}; + +static bool lib_initiated(void) +{ + return ckteec_invoke_initiated(); +} + +CK_RV C_Initialize(CK_VOID_PTR pInitArgs) +{ + CK_C_INITIALIZE_ARGS_PTR args = NULL; + CK_RV rv = 0; + + if (pInitArgs) { + args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs; + + /* Reserved must be set to NULL in this version of PKCS#11 */ + if (args->reserved) + return CKR_ARGUMENTS_BAD; + } + + rv = ckteec_invoke_init(); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CANT_LOCK, + CKR_CRYPTOKI_ALREADY_INITIALIZED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_NEED_TO_CREATE_THREADS, CKR_OK, + CKR_MUTEX_BAD); + + return rv; +} + +CK_RV C_Finalize(CK_VOID_PTR pReserved) +{ + CK_RV rv = 0; + + /* Reserved must be set to NULL in this version of PKCS#11 */ + if (pReserved) + return CKR_ARGUMENTS_BAD; + + rv = ckteec_invoke_terminate(); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK); + + return rv; +} + +CK_RV C_GetInfo(CK_INFO_PTR pInfo) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_get_info(pInfo); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK); + + return rv; +} + +CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) +{ + if (!ppFunctionList) + return CKR_ARGUMENTS_BAD; + + /* Discard the const attribute when exporting the list address */ + *ppFunctionList = (void *)&libckteec_function_list; + + return CKR_OK; +} + +CK_RV C_GetSlotList(CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, + CK_ULONG_PTR pulCount) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_slot_get_list(tokenPresent, pSlotList, pulCount); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK); + + return rv; +} + +CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, + CK_SLOT_INFO_PTR pInfo) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_slot_get_info(slotID, pInfo); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, + CKR_HOST_MEMORY, CKR_OK, CKR_SLOT_ID_INVALID); + + return rv; +} + +CK_RV C_InitToken(CK_SLOT_ID slotID, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, + CK_UTF8CHAR_PTR pLabel) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_init_token(slotID, pPin, ulPinLen, pLabel); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_PIN_INCORRECT, CKR_PIN_LOCKED, CKR_SESSION_EXISTS, + CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, + CKR_TOKEN_NOT_RECOGNIZED, CKR_TOKEN_WRITE_PROTECTED); + + return rv; +} + +CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, + CK_TOKEN_INFO_PTR pInfo) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_token_get_info(slotID, pInfo); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, + CKR_TOKEN_NOT_RECOGNIZED, CKR_ARGUMENTS_BAD); + + return rv; +} + +CK_RV C_GetMechanismList(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_token_mechanism_ids(slotID, pMechanismList, pulCount); + + ASSERT_CK_RV(rv, CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, + CKR_TOKEN_NOT_RECOGNIZED, CKR_ARGUMENTS_BAD); + + return rv; +} + +CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_token_mechanism_info(slotID, type, pInfo); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, + CKR_OK, CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT, + CKR_TOKEN_NOT_RECOGNIZED, CKR_ARGUMENTS_BAD); + + return rv; +} + +CK_RV C_OpenSession(CK_SLOT_ID slotID, + CK_FLAGS flags, + CK_VOID_PTR pApplication, + CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_open_session(slotID, flags, pApplication, Notify, + phSession); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_SESSION_COUNT, CKR_SESSION_PARALLEL_NOT_SUPPORTED, + CKR_SESSION_READ_WRITE_SO_EXISTS, CKR_SLOT_ID_INVALID, + CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_NOT_RECOGNIZED, + CKR_TOKEN_WRITE_PROTECTED, CKR_ARGUMENTS_BAD); + + return rv; +} + +CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_close_session(hSession); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_close_all_sessions(slotID); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_SLOT_ID_INVALID, CKR_TOKEN_NOT_PRESENT); + + return rv; +} + +CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, + CK_SESSION_INFO_PTR pInfo) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_get_session_info(hSession, pInfo); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_ARGUMENTS_BAD); + + return rv; +} + +CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_init_pin(hSession, pPin, ulPinLen); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_PIN_INVALID, CKR_PIN_LEN_RANGE, CKR_SESSION_CLOSED, + CKR_SESSION_READ_ONLY, CKR_SESSION_HANDLE_INVALID, + CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN, + CKR_ARGUMENTS_BAD); + + return rv; +} + +CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, + CK_UTF8CHAR_PTR pOldPin, + CK_ULONG ulOldLen, + CK_UTF8CHAR_PTR pNewPin, + CK_ULONG ulNewLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_set_pin(hSession, pOldPin, ulOldLen, pNewPin, ulNewLen); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_PIN_INCORRECT, CKR_PIN_INVALID, + CKR_PIN_LEN_RANGE, CKR_PIN_LOCKED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, + CKR_TOKEN_WRITE_PROTECTED, CKR_ARGUMENTS_BAD); + + return rv; +} + +CK_RV C_Login(CK_SESSION_HANDLE hSession, + CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen) + +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_login(hSession, userType, pPin, ulPinLen); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_PIN_INCORRECT, + CKR_PIN_LOCKED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY_EXISTS, + CKR_USER_ALREADY_LOGGED_IN, + CKR_USER_ANOTHER_ALREADY_LOGGED_IN, + CKR_USER_PIN_NOT_INITIALIZED, CKR_USER_TOO_MANY_TYPES, + CKR_USER_TYPE_INVALID); + + return rv; +} + +CK_RV C_Logout(CK_SESSION_HANDLE hSession) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_logout(hSession); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG_PTR pulOperationStateLen) +{ + (void)hSession; + (void)pOperationState; + (void)pulOperationStateLen; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG ulOperationStateLen, + CK_OBJECT_HANDLE hEncryptionKey, + CK_OBJECT_HANDLE hAuthenticationKey) +{ + (void)hSession; + (void)pOperationState; + (void)ulOperationStateLen; + (void)hEncryptionKey; + (void)hAuthenticationKey; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_create_object(hSession, pTemplate, ulCount, phObject); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, + CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, + CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, + CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_copy_object(hSession, hObject, pTemplate, ulCount, + phNewObject); + + ASSERT_CK_RV(rv, CKR_ACTION_PROHIBITED, CKR_ARGUMENTS_BAD, + CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, + CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_PIN_EXPIRED, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCONSISTENT, + CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_destroy_object(hSession, hObject); + + ASSERT_CK_RV(rv, CKR_ACTION_PROHIBITED, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_PIN_EXPIRED, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_SESSION_READ_ONLY, CKR_TOKEN_WRITE_PROTECTED); + + return rv; +} + +CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG_PTR pulSize) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_get_object_size(hSession, hObject, pulSize); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_INFORMATION_SENSITIVE, CKR_OBJECT_HANDLE_INVALID, + CKR_OK, CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_get_attribute_value(hSession, hObject, pTemplate, ulCount); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_SENSITIVE, + CKR_ATTRIBUTE_TYPE_INVALID, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_set_attribute_value(hSession, hObject, pTemplate, ulCount); + + ASSERT_CK_RV(rv, CKR_ACTION_PROHIBITED, CKR_ARGUMENTS_BAD, + CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_TYPE_INVALID, + CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OBJECT_HANDLE_INVALID, CKR_OK, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, + CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, + CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_find_objects_init(hSession, pTemplate, ulCount); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_TYPE_INVALID, + CKR_ATTRIBUTE_VALUE_INVALID, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount) + +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_find_objects(hSession, phObject, + ulMaxObjectCount, pulObjectCount); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_find_objects_final(hSession); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_encdecrypt_init(hSession, pMechanism, hKey, CK_FALSE); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, + CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, + CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, + CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_encdecrypt_oneshot(hSession, pData, ulDataLen, + pEncryptedData, pulEncryptedDataLen, + CK_FALSE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_encdecrypt_update(hSession, pPart, ulPartLen, + pEncryptedData, + pulEncryptedDataLen, CK_FALSE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, + CK_ULONG_PTR pulLastEncryptedPartLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_encdecrypt_final(hSession, pLastEncryptedPart, + pulLastEncryptedPartLen, CK_FALSE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_encdecrypt_init(hSession, pMechanism, hKey, CK_TRUE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, + CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, + CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, + CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_encdecrypt_oneshot(hSession, pEncryptedData, + ulEncryptedDataLen, + pData, pulDataLen, CK_TRUE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_encdecrypt_update(hSession, pEncryptedPart, + ulEncryptedPartLen, + pPart, pulPartLen, CK_TRUE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastPart, + CK_ULONG_PTR pulLastPartLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_encdecrypt_final(hSession, pLastPart, pulLastPartLen, + CK_TRUE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_digest_init(hSession, pMechanism); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, + CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, + CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_Digest(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_digest_oneshot(hSession, pData, ulDataLen, pDigest, + pulDigestLen); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_digest_update(hSession, pPart, ulPartLen); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_digest_key(hSession, hKey); + + ASSERT_CK_RV(rv, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_KEY_HANDLE_INVALID, CKR_KEY_INDIGESTIBLE, + CKR_KEY_SIZE_RANGE, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_digest_final(hSession, pDigest, pulDigestLen); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_SignInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_signverify_init(hSession, pMechanism, hKey, CK_TRUE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, + CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, + CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, + CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_Sign(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_signverify_oneshot(hSession, pData, ulDataLen, + pSignature, pulSignatureLen, + CK_TRUE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_INVALID, + CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, + CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN, + CKR_FUNCTION_REJECTED); + + return rv; +} + +CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_signverify_update(hSession, pPart, ulPartLen, CK_TRUE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, + CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_signverify_final(hSession, pSignature, pulSignatureLen, + CK_TRUE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DATA_LEN_RANGE, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN, + CKR_FUNCTION_REJECTED); + + return rv; +} + +CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + (void)hSession; + (void)pMechanism; + (void)hKey; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + (void)hSession; + (void)pData; + (void)ulDataLen; + (void)pSignature; + (void)pulSignatureLen; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_signverify_init(hSession, pMechanism, hKey, CK_FALSE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_KEY_FUNCTION_NOT_PERMITTED, CKR_KEY_HANDLE_INVALID, + CKR_KEY_SIZE_RANGE, CKR_KEY_TYPE_INCONSISTENT, + CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, + CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_Verify(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + CK_ULONG out_size = ulSignatureLen; + + if (lib_initiated()) + rv = ck_signverify_oneshot(hSession, pData, ulDataLen, + pSignature, &out_size, + CK_FALSE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DATA_INVALID, CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SIGNATURE_INVALID, + CKR_SIGNATURE_LEN_RANGE); + + return rv; +} + +CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_signverify_update(hSession, pPart, ulPartLen, CK_FALSE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, + CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID); + + return rv; +} + +CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_signverify_final(hSession, pSignature, &ulSignatureLen, + CK_FALSE); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DATA_LEN_RANGE, CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, + CKR_DEVICE_REMOVED, CKR_FUNCTION_CANCELED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_OK, CKR_OPERATION_NOT_INITIALIZED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SIGNATURE_INVALID, + CKR_SIGNATURE_LEN_RANGE); + + return rv; +} + +CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + (void)hSession; + (void)pMechanism; + (void)hKey; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen, + CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen) +{ + (void)hSession; + (void)pSignature; + (void)ulSignatureLen; + (void)pData; + (void)pulDataLen; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen) +{ + (void)hSession; + (void)pPart; + (void)ulPartLen; + (void)pEncryptedPart; + (void)pulEncryptedPartLen; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen) +{ + (void)hSession; + (void)pEncryptedPart; + (void)ulEncryptedPartLen; + (void)pPart; + (void)pulPartLen; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen) +{ + (void)hSession; + (void)pPart; + (void)ulPartLen; + (void)pEncryptedPart; + (void)pulEncryptedPartLen; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen) +{ + (void)hSession; + (void)pEncryptedPart; + (void)ulEncryptedPartLen; + (void)pPart; + (void)pulPartLen; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_generate_key(hSession, pMechanism, pTemplate, ulCount, + phKey); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, + CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MECHANISM_INVALID, + CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, + CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, + CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, + CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_generate_key_pair(hSession, pMechanism, + pPublicKeyTemplate, + ulPublicKeyAttributeCount, + pPrivateKeyTemplate, + ulPrivateKeyAttributeCount, + phPublicKey, phPrivateKey); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, + CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, + CKR_OK, CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_SESSION_READ_ONLY, CKR_TEMPLATE_INCOMPLETE, + CKR_TEMPLATE_INCONSISTENT, CKR_TOKEN_WRITE_PROTECTED, + CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hWrappingKey, + CK_OBJECT_HANDLE hKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG_PTR pulWrappedKeyLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_wrap_key(hSession, pMechanism, hWrappingKey, hKey, + pWrappedKey, pulWrappedKeyLen); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_BUFFER_TOO_SMALL, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_KEY_HANDLE_INVALID, + CKR_KEY_NOT_WRAPPABLE, CKR_KEY_SIZE_RANGE, + CKR_KEY_UNEXTRACTABLE, CKR_MECHANISM_INVALID, + CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, + CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN, + CKR_WRAPPING_KEY_HANDLE_INVALID, + CKR_WRAPPING_KEY_SIZE_RANGE, + CKR_WRAPPING_KEY_TYPE_INCONSISTENT); + + return rv; +} + +CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_unwrap_key(hSession, pMechanism, hUnwrappingKey, + pWrappedKey, ulWrappedKeyLen, pTemplate, + ulCount, phKey); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, + CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, + CKR_BUFFER_TOO_SMALL, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_CURVE_NOT_SUPPORTED, CKR_DEVICE_ERROR, + CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, CKR_OK, + CKR_OPERATION_ACTIVE, CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, + CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, + CKR_TOKEN_WRITE_PROTECTED, + CKR_UNWRAPPING_KEY_HANDLE_INVALID, + CKR_UNWRAPPING_KEY_SIZE_RANGE, + CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, + CKR_USER_NOT_LOGGED_IN, CKR_WRAPPED_KEY_INVALID, + CKR_WRAPPED_KEY_LEN_RANGE); + + return rv; +} + +CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_derive_key(hSession, pMechanism, hBaseKey, pTemplate, + ulCount, phKey); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_ATTRIBUTE_READ_ONLY, + CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_VALUE_INVALID, + CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CURVE_NOT_SUPPORTED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_DOMAIN_PARAMS_INVALID, CKR_FUNCTION_CANCELED, + CKR_FUNCTION_FAILED, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, + CKR_KEY_HANDLE_INVALID, CKR_KEY_SIZE_RANGE, + CKR_KEY_TYPE_INCONSISTENT, CKR_MECHANISM_INVALID, + CKR_MECHANISM_PARAM_INVALID, CKR_OK, CKR_OPERATION_ACTIVE, + CKR_PIN_EXPIRED, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_SESSION_READ_ONLY, + CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, + CKR_TOKEN_WRITE_PROTECTED, CKR_USER_NOT_LOGGED_IN, + CKR_DATA_LEN_RANGE); + + return rv; +} + +CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSeed, + CK_ULONG ulSeedLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_seed_random(hSession, pSeed, ulSeedLen); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_ACTIVE, CKR_RANDOM_SEED_NOT_SUPPORTED, + CKR_RANDOM_NO_RNG, CKR_SESSION_CLOSED, + CKR_SESSION_HANDLE_INVALID, CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pRandomData, + CK_ULONG ulRandomLen) +{ + CK_RV rv = CKR_CRYPTOKI_NOT_INITIALIZED; + + if (lib_initiated()) + rv = ck_generate_random(hSession, pRandomData, ulRandomLen); + + ASSERT_CK_RV(rv, CKR_ARGUMENTS_BAD, CKR_CRYPTOKI_NOT_INITIALIZED, + CKR_DEVICE_ERROR, CKR_DEVICE_MEMORY, CKR_DEVICE_REMOVED, + CKR_FUNCTION_CANCELED, CKR_FUNCTION_FAILED, + CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_OK, + CKR_OPERATION_ACTIVE, CKR_RANDOM_NO_RNG, + CKR_SESSION_CLOSED, CKR_SESSION_HANDLE_INVALID, + CKR_USER_NOT_LOGGED_IN); + + return rv; +} + +CK_RV C_GetFunctionStatus(CK_SESSION_HANDLE hSession) +{ + (void)hSession; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_PARALLEL; +} + +CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession) +{ + (void)hSession; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_PARALLEL; +} + +CK_RV C_WaitForSlotEvent(CK_FLAGS flags, + CK_SLOT_ID_PTR slotID, + CK_VOID_PTR pReserved) +{ + (void)flags; + (void)slotID; + (void)pReserved; + + if (!lib_initiated()) + return CKR_CRYPTOKI_NOT_INITIALIZED; + + return CKR_FUNCTION_NOT_SUPPORTED; +} diff --git a/optee/optee_client/libckteec/src/pkcs11_processing.c b/optee/optee_client/libckteec/src/pkcs11_processing.c new file mode 100644 index 0000000..bb26c1f --- /dev/null +++ b/optee/optee_client/libckteec/src/pkcs11_processing.c @@ -0,0 +1,1705 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "pkcs11_processing.h" +#include "invoke_ta.h" +#include "serializer.h" +#include "serialize_ck.h" + +CK_RV ck_create_object(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) +{ + CK_RV rv = CKR_GENERAL_ERROR; + struct serializer obj = { 0 }; + size_t ctrl_size = 0; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + uint32_t session_handle = session; + uint32_t key_handle = 0; + char *buf = NULL; + size_t out_size = 0; + + if (!handle || !attribs || !count) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_attributes(&obj, attribs, count); + if (rv) + goto out; + + /* Shm io0: (i/o) [session-handle][serialized-attributes] / [status] */ + ctrl_size = sizeof(session_handle) + obj.size; + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, obj.buffer, obj.size); + + /* Shm io2: (out) [object handle] */ + out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_CREATE_OBJECT, + ctrl, out_shm, &out_size); + + if (rv != CKR_OK || out_size != out_shm->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto out; + } + + memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); + *handle = key_handle; + +out: + release_serial_object(&obj); + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + size_t ctrl_size = 0; + char *buf = NULL; + uint32_t session_handle = session; + uint32_t obj_id = obj; + + /* Shm io0: (i/o) ctrl = [session-handle][object-handle] / [status] */ + ctrl_size = sizeof(session_handle) + sizeof(obj_id); + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &obj_id, sizeof(obj_id)); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_DESTROY_OBJECT, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_encdecrypt_init(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key, + int decrypt) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + struct serializer obj = { 0 }; + uint32_t session_handle = session; + uint32_t key_handle = key; + size_t ctrl_size = 0; + char *buf = NULL; + + if (!mechanism) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_mecha_params(&obj, mechanism); + if (rv) + return rv; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][key-handle][serialized-mechanism-blob] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + sizeof(key_handle) + obj.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &key_handle, sizeof(key_handle)); + buf += sizeof(key_handle); + + memcpy(buf, obj.buffer, obj.size); + + rv = ckteec_invoke_ctrl(decrypt ? PKCS11_CMD_DECRYPT_INIT : + PKCS11_CMD_ENCRYPT_INIT, ctrl); + +bail: + ckteec_free_shm(ctrl); + release_serial_object(&obj); + + return rv; +} + +CK_RV ck_encdecrypt_update(CK_SESSION_HANDLE session, + CK_BYTE_PTR in, + CK_ULONG in_len, + CK_BYTE_PTR out, + CK_ULONG_PTR out_len, + int decrypt) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *in_shm = NULL; + TEEC_SharedMemory *out_shm = NULL; + uint32_t session_handle = session; + size_t out_size = 0; + + if (!out_len || (in_len && !in)) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io1: input data buffer if any */ + if (in_len) { + in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); + if (!in_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + } + + /* Shm io2: output data buffer */ + if (out && out_len && *out_len) { + out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); + } else { + /* Query output data size */ + out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); + } + + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + /* Invoke */ + rv = ckteec_invoke_ta(decrypt ? PKCS11_CMD_DECRYPT_UPDATE : + PKCS11_CMD_ENCRYPT_UPDATE, ctrl, + in_shm, out_shm, &out_size, NULL, NULL); + + if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) + *out_len = out_size; + + if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) + rv = CKR_OK; + + goto bail_invoked; + +bail: + ck_release_active_processing(session, decrypt ? + PKCS11_CMD_DECRYPT_UPDATE : + PKCS11_CMD_ENCRYPT_UPDATE); +bail_invoked: + ckteec_free_shm(out_shm); + ckteec_free_shm(in_shm); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_encdecrypt_oneshot(CK_SESSION_HANDLE session, + CK_BYTE_PTR in, + CK_ULONG in_len, + CK_BYTE_PTR out, + CK_ULONG_PTR out_len, + int decrypt) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *in_shm = NULL; + TEEC_SharedMemory *out_shm = NULL; + uint32_t session_handle = session; + size_t out_size = 0; + + if (!out_len || (in_len && !in)) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io1: input data buffer */ + in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); + if (!in_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + /* Shm io2: output data buffer */ + if (out && out_len && *out_len) { + out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); + } else { + /* Query output data size */ + out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); + } + + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ta(decrypt ? PKCS11_CMD_DECRYPT_ONESHOT : + PKCS11_CMD_ENCRYPT_ONESHOT, ctrl, + in_shm, out_shm, &out_size, NULL, NULL); + + if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) + *out_len = out_size; + + if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) + rv = CKR_OK; + + goto bail_invoked; + +bail: + ck_release_active_processing(session, decrypt ? + PKCS11_CMD_DECRYPT_ONESHOT : + PKCS11_CMD_ENCRYPT_ONESHOT); +bail_invoked: + ckteec_free_shm(out_shm); + ckteec_free_shm(in_shm); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_encdecrypt_final(CK_SESSION_HANDLE session, + CK_BYTE_PTR out, + CK_ULONG_PTR out_len, + int decrypt) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + uint32_t session_handle = session; + size_t out_size = 0; + + if (!out_len) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io2: output buffer reference */ + if (out && out_len && *out_len) { + out_shm = ckteec_register_shm(out, *out_len, CKTEEC_SHM_OUT); + } else { + /* Query output data size */ + out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); + } + + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(decrypt ? PKCS11_CMD_DECRYPT_FINAL : + PKCS11_CMD_ENCRYPT_FINAL, + ctrl, out_shm, &out_size); + + if (out_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) + *out_len = out_size; + + if (rv == CKR_BUFFER_TOO_SMALL && out_size && !out) + rv = CKR_OK; + + goto bail_invoked; + +bail: + ck_release_active_processing(session, decrypt ? + PKCS11_CMD_DECRYPT_FINAL : + PKCS11_CMD_ENCRYPT_FINAL); +bail_invoked: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_digest_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + struct serializer obj = { 0 }; + uint32_t session_handle = session; + size_t ctrl_size = 0; + uint8_t *buf = NULL; + + if (!mechanism) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_mecha_params(&obj, mechanism); + if (rv) + return rv; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][serialized-mechanism-blob] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + obj.size; + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, obj.buffer, obj.size); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_DIGEST_INIT, ctrl); + +bail: + ckteec_free_shm(ctrl); + release_serial_object(&obj); + + return rv; +} + +CK_RV ck_digest_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t session_handle = session; + uint32_t key_handle = key; + size_t ctrl_size = 0; + uint8_t *buf = NULL; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][key-handle] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + sizeof(key_handle); + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &key_handle, sizeof(key_handle)); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_DIGEST_KEY, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_digest_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, + CK_ULONG in_len) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *io1 = NULL; + uint32_t session_handle = session; + uint8_t *buf = NULL; + + if (!in && in_len) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* + * Shm io0: (in/out) ctrl = [session-handle] / [status] + */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + + /* Shm io1: input payload */ + if (in_len && in) { + io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); + if (!io1) { + rv = CKR_HOST_MEMORY; + goto bail; + } + } + + rv = ckteec_invoke_ctrl_in(PKCS11_CMD_DIGEST_UPDATE, ctrl, io1); + + goto bail_invoked; + +bail: + ck_release_active_processing(session, PKCS11_CMD_DIGEST_UPDATE); +bail_invoked: + ckteec_free_shm(io1); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_digest_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, + CK_ULONG in_len, CK_BYTE_PTR digest_ref, + CK_ULONG_PTR digest_len) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *io1 = NULL; + TEEC_SharedMemory *io2 = NULL; + uint32_t session_handle = session; + size_t out_size = 0; + uint8_t *buf = NULL; + + if ((!in && in_len) || !digest_len) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* + * Shm io0: (in/out) ctrl = [session-handle] / [status] + */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + + /* Shm io1: input payload */ + if (in_len && in) { + io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); + if (!io1) { + rv = CKR_HOST_MEMORY; + goto bail; + } + } + + /* Shm io2: output digest or null sized shm */ + if (digest_ref) { + io2 = ckteec_register_shm(digest_ref, *digest_len, + CKTEEC_SHM_OUT); + } else { + /* Query size if output signature */ + io2 = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); + } + + if (!io2) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ta(PKCS11_CMD_DIGEST_ONESHOT, ctrl, + io1, io2, &out_size, NULL, NULL); + + if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) + *digest_len = out_size; + + if (rv == CKR_BUFFER_TOO_SMALL && out_size && !digest_ref) + rv = CKR_OK; + + goto bail_invoked; + +bail: + ck_release_active_processing(session, PKCS11_CMD_DIGEST_ONESHOT); +bail_invoked: + ckteec_free_shm(io1); + ckteec_free_shm(io2); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_digest_final(CK_SESSION_HANDLE session, CK_BYTE_PTR digest_ref, + CK_ULONG_PTR digest_len) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *io2 = NULL; + uint32_t session_handle = session; + size_t io2_size = 0; + uint8_t *buf = NULL; + + /* + * - If digest_ref == NULL AND digest_len == NULL -> need to call TA to + * terminate session. + * - If digest_len == NULL -> need to call to TA to terminate session. + * - If digest_ref == NULL BUT digest_len != NULL just operate normally + * to get size of the required buffer + */ + if (!digest_len) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* + * Shm io0: (in/out) ctrl = [session-handle] / [status] + */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + + /* Shm io2: output digest or null sized shm */ + if (digest_ref) + io2 = ckteec_register_shm(digest_ref, *digest_len, + CKTEEC_SHM_OUT); + else + io2 = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); + + if (!io2) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ta(PKCS11_CMD_DIGEST_FINAL, ctrl, NULL, io2, + &io2_size, NULL, NULL); + + if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) + *digest_len = io2_size; + + if (rv == CKR_BUFFER_TOO_SMALL && io2_size && !digest_ref) + rv = CKR_OK; + + goto bail_invoked; + +bail: + ck_release_active_processing(session, PKCS11_CMD_DIGEST_FINAL); +bail_invoked: + ckteec_free_shm(io2); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_signverify_init(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key, + int sign) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + struct serializer obj = { 0 }; + uint32_t session_handle = session; + uint32_t key_handle = key; + size_t ctrl_size = 0; + char *buf = NULL; + + if (!mechanism) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_mecha_params(&obj, mechanism); + if (rv) + return rv; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][key-handle][serialized-mechanism-blob] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + sizeof(key_handle) + obj.size; + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &key_handle, sizeof(key_handle)); + buf += sizeof(key_handle); + + memcpy(buf, obj.buffer, obj.size); + + rv = ckteec_invoke_ctrl(sign ? PKCS11_CMD_SIGN_INIT : + PKCS11_CMD_VERIFY_INIT, ctrl); + +bail: + ckteec_free_shm(ctrl); + release_serial_object(&obj); + + return rv; +} + +CK_RV ck_signverify_update(CK_SESSION_HANDLE session, + CK_BYTE_PTR in, + CK_ULONG in_len, + int sign) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *in_shm = NULL; + uint32_t session_handle = session; + + if (!in && in_len) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io1: input data */ + in_shm = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); + if (!in_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_in(sign ? PKCS11_CMD_SIGN_UPDATE : + PKCS11_CMD_VERIFY_UPDATE, ctrl, in_shm); + + goto bail_invoked; + +bail: + ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_UPDATE : + PKCS11_CMD_VERIFY_UPDATE); +bail_invoked: + ckteec_free_shm(in_shm); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_signverify_oneshot(CK_SESSION_HANDLE session, + CK_BYTE_PTR in, + CK_ULONG in_len, + CK_BYTE_PTR sign_ref, + CK_ULONG_PTR sign_len, + int sign) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *io1 = NULL; + TEEC_SharedMemory *io2 = NULL; + uint32_t session_handle = session; + size_t out_size = 0; + + if ((in_len && !in) || (!sign && sign_len && *sign_len && !sign_ref) || + (sign && !sign_len)) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io1: input payload */ + if (in_len) { + io1 = ckteec_register_shm(in, in_len, CKTEEC_SHM_IN); + if (!io1) { + rv = CKR_HOST_MEMORY; + goto bail; + } + } + + /* + * Shm io2: input signature (if verifying) or null sized shm + * or + * Shm io2: output signature (if signing) or null sized shm + */ + if (sign_ref && sign_len && *sign_len) { + io2 = ckteec_register_shm(sign_ref, *sign_len, + sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); + } else { + /* Query size if output signature */ + io2 = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); + } + + if (!io2) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_ONESHOT : + PKCS11_CMD_VERIFY_ONESHOT, ctrl, + io1, io2, &out_size, NULL, NULL); + + if (sign && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) + *sign_len = out_size; + + if (rv == CKR_BUFFER_TOO_SMALL && out_size && !sign_ref) + rv = CKR_OK; + + goto bail_invoked; + +bail: + ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_ONESHOT : + PKCS11_CMD_VERIFY_ONESHOT); +bail_invoked: + ckteec_free_shm(io1); + ckteec_free_shm(io2); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_signverify_final(CK_SESSION_HANDLE session, + CK_BYTE_PTR sign_ref, + CK_ULONG_PTR sign_len, + int sign) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *io = NULL; + uint32_t session_handle = session; + size_t io_size = 0; + + if ((!sign && sign_len && *sign_len && !sign_ref) || + (sign && !sign_len)) { + rv = CKR_ARGUMENTS_BAD; + goto bail; + } + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* + * Shm io1: input signature (if verifying) or null sized shm + * or + * Shm io1: output signature (if signing) or null sized shm + */ + if (sign_ref && sign_len && *sign_len) + io = ckteec_register_shm(sign_ref, *sign_len, + sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); + else + io = ckteec_alloc_shm(0, sign ? CKTEEC_SHM_OUT : CKTEEC_SHM_IN); + + if (!io) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ta(sign ? PKCS11_CMD_SIGN_FINAL : + PKCS11_CMD_VERIFY_FINAL, ctrl, NULL, io, + &io_size, NULL, NULL); + + if (sign && sign_len && (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)) + *sign_len = io_size; + + if (rv == CKR_BUFFER_TOO_SMALL && io_size && !sign_ref) + rv = CKR_OK; + + goto bail_invoked; + +bail: + ck_release_active_processing(session, sign ? PKCS11_CMD_SIGN_FINAL : + PKCS11_CMD_VERIFY_FINAL); +bail_invoked: + ckteec_free_shm(io); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_generate_key(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR handle) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + struct serializer smecha = { 0 }; + struct serializer sattr = { 0 }; + uint32_t session_handle = session; + size_t ctrl_size = 0; + uint32_t key_handle = 0; + char *buf = NULL; + size_t out_size = 0; + + if (!handle || !mechanism || (count && !attribs)) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_mecha_params(&smecha, mechanism); + if (rv) + return rv; + + rv = serialize_ck_attributes(&sattr, attribs, count); + if (rv) + goto bail; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][serialized-mecha][serialized-attributes] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + smecha.size + sattr.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, smecha.buffer, smecha.size); + buf += smecha.size; + + memcpy(buf, sattr.buffer, sattr.size); + + /* Shm io2: (out) [object handle] */ + out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_KEY, + ctrl, out_shm, &out_size); + + if (rv != CKR_OK || out_size != out_shm->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto bail; + } + + memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); + *handle = key_handle; + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + release_serial_object(&sattr); + release_serial_object(&smecha); + + return rv; +} + +CK_RV ck_find_objects_init(CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t session_handle = session; + struct serializer obj = { 0 }; + size_t ctrl_size = 0; + char *buf = NULL; + + if (count && !attribs) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_attributes(&obj, attribs, count); + if (rv) + return rv; + + /* Shm io0: (in/out) ctrl + * (in) [session-handle][headed-serialized-attributes] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + obj.size; + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, obj.buffer, obj.size); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_FIND_OBJECTS_INIT, ctrl); + +bail: + ckteec_free_shm(ctrl); + release_serial_object(&obj); + + return rv; +} + +CK_RV ck_find_objects(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE_PTR obj, + CK_ULONG max_count, + CK_ULONG_PTR count) + +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + uint32_t session_handle = session; + uint32_t *handles = NULL; + size_t handles_size = max_count * sizeof(uint32_t); + CK_ULONG n = 0; + CK_ULONG last = 0; + size_t out_size = 0; + + if (!count || (max_count && !obj)) + return CKR_ARGUMENTS_BAD; + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io2: (out) [object handle list] */ + out_shm = ckteec_alloc_shm(handles_size, CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_FIND_OBJECTS, + ctrl, out_shm, &out_size); + + if (rv || out_size > out_shm->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto bail; + } + + handles = out_shm->buffer; + last = out_size / sizeof(uint32_t); + *count = last; + + for (n = 0; n < last; n++) + obj[n] = handles[n]; + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_find_objects_final(CK_SESSION_HANDLE session) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t session_handle = session; + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_FIND_OBJECTS_FINAL, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_get_object_size(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE obj, + CK_ULONG_PTR p_size) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + size_t ctrl_size = 0; + uint32_t session_handle = session; + uint32_t obj_handle = obj; + char *buf = NULL; + size_t out_size = 0; + uint32_t u32_sz = 0; + + if (!p_size) + return CKR_ARGUMENTS_BAD; + + /* Shm io0: (in/out) [session][obj-handle] / [status] */ + ctrl_size = sizeof(session_handle) + sizeof(obj_handle); + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &obj_handle, sizeof(obj_handle)); + + /* Shm io2: (out) [object size] */ + out_shm = ckteec_alloc_shm(sizeof(uint32_t), CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GET_OBJECT_SIZE, + ctrl, out_shm, &out_size); + if (rv) + goto bail; + + if (out_shm->size != sizeof(uint32_t)) { + rv = CKR_DEVICE_ERROR; + goto bail; + } + + memcpy(&u32_sz, out_shm->buffer, out_shm->size); + *p_size = u32_sz; + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_get_attribute_value(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE obj, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_RV rv2 = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + struct serializer sattr = { 0 }; + size_t ctrl_size = 0; + uint32_t session_handle = session; + uint32_t obj_handle = obj; + char *buf = NULL; + size_t out_size = 0; + + if (count && !attribs) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_attributes(&sattr, attribs, count); + if (rv) + goto bail; + + /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ + ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &obj_handle, sizeof(obj_handle)); + buf += sizeof(obj_handle); + + memcpy(buf, sattr.buffer, sattr.size); + + /* Shm io2: (out) [attributes] */ + out_shm = ckteec_alloc_shm(sattr.size, CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GET_ATTRIBUTE_VALUE, + ctrl, out_shm, &out_size); + + if (rv == CKR_OK || rv == CKR_ATTRIBUTE_SENSITIVE || + rv == CKR_ATTRIBUTE_TYPE_INVALID || rv == CKR_BUFFER_TOO_SMALL) { + rv2 = deserialize_ck_attributes(out_shm->buffer, attribs, + count); + if (rv2) + rv = CKR_GENERAL_ERROR; + } + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + release_serial_object(&sattr); + + return rv; +} + +CK_RV ck_set_attribute_value(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE obj, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + struct serializer sattr = { 0 }; + size_t ctrl_size = 0; + uint32_t session_handle = session; + uint32_t obj_handle = obj; + char *buf = NULL; + + if (count && !attribs) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_attributes(&sattr, attribs, count); + if (rv) + goto bail; + + /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ + ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &obj_handle, sizeof(obj_handle)); + buf += sizeof(obj_handle); + + memcpy(buf, sattr.buffer, sattr.size); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_SET_ATTRIBUTE_VALUE, ctrl); + +bail: + ckteec_free_shm(ctrl); + release_serial_object(&sattr); + + return rv; +} + +CK_RV ck_copy_object(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE obj, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR handle) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + struct serializer sattr = { 0 }; + size_t ctrl_size = 0; + uint32_t session_handle = session; + uint32_t obj_handle = obj; + uint32_t key_handle = 0; + char *buf = NULL; + size_t out_size = 0; + + if (!handle || (count && !attribs)) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_attributes(&sattr, attribs, count); + if (rv) + goto bail; + + /* Shm io0: (in/out) [session][obj-handle][attributes] / [status] */ + ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + sattr.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &obj_handle, sizeof(obj_handle)); + buf += sizeof(obj_handle); + + memcpy(buf, sattr.buffer, sattr.size); + + /* Shm io2: (out) [object handle] */ + out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_COPY_OBJECT, + ctrl, out_shm, &out_size); + if (rv != CKR_OK || out_size != out_shm->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto bail; + } + + memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); + *handle = key_handle; + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + release_serial_object(&sattr); + + return rv; +} + +CK_RV ck_derive_key(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE parent_key, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR handle) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + struct serializer smecha = { 0 }; + struct serializer sattr = { 0 }; + uint32_t session_handle = session; + uint32_t obj_handle = parent_key; + size_t ctrl_size = 0; + uint32_t key_handle = 0; + char *buf = NULL; + size_t out_size = 0; + + if (!handle || !mechanism || (count && !attribs)) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_mecha_params(&smecha, mechanism); + if (rv) + return rv; + + rv = serialize_ck_attributes(&sattr, attribs, count); + if (rv) + goto bail; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][obj-handle][serialized-mecha][serialized-attributes] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + sizeof(obj_handle) + smecha.size + + sattr.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &obj_handle, sizeof(obj_handle)); + buf += sizeof(obj_handle); + + memcpy(buf, smecha.buffer, smecha.size); + buf += smecha.size; + + memcpy(buf, sattr.buffer, sattr.size); + + /* Shm io2: (out) [object handle] */ + out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_DERIVE_KEY, + ctrl, out_shm, &out_size); + + if (rv != CKR_OK || out_size != out_shm->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto bail; + } + + memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); + *handle = key_handle; + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + release_serial_object(&sattr); + release_serial_object(&smecha); + + return rv; +} + +CK_RV ck_release_active_processing(CK_SESSION_HANDLE session, + enum pkcs11_ta_cmd command) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t session_handle = session; + uint32_t cmd = command; + size_t ctrl_size = 0; + char *buf = NULL; + + /* Shm io0: (in/out) ctrl = [session-handle][command] / [status] */ + ctrl_size = sizeof(session_handle) + sizeof(cmd); + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &cmd, sizeof(cmd)); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_RELEASE_ACTIVE_PROCESSING, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_generate_key_pair(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR pub_attribs, + CK_ULONG pub_count, + CK_ATTRIBUTE_PTR priv_attribs, + CK_ULONG priv_count, + CK_OBJECT_HANDLE_PTR pub_key, + CK_OBJECT_HANDLE_PTR priv_key) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + struct serializer smecha = { 0 }; + struct serializer pub_sattr = { 0 }; + struct serializer priv_sattr = { 0 }; + uint32_t session_handle = session; + size_t ctrl_size = 0; + uint32_t *key_handle = NULL; + size_t key_handle_size = 2 * sizeof(*key_handle); + char *buf = NULL; + size_t out_size = 0; + + if (!(mechanism && pub_attribs && priv_attribs && pub_key && priv_key)) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_mecha_params(&smecha, mechanism); + if (rv) + return rv; + + rv = serialize_ck_attributes(&pub_sattr, pub_attribs, pub_count); + if (rv) + goto bail; + + rv = serialize_ck_attributes(&priv_sattr, priv_attribs, priv_count); + if (rv) + goto bail; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][serialized-mecha][serialized-pub_attribs] + * [serialized-priv_attribs] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + smecha.size + pub_sattr.size + + priv_sattr.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, smecha.buffer, smecha.size); + buf += smecha.size; + + memcpy(buf, pub_sattr.buffer, pub_sattr.size); + buf += pub_sattr.size; + + memcpy(buf, priv_sattr.buffer, priv_sattr.size); + + /* + * Shm io2: (out) public key object handle][private key object handle] + */ + out_shm = ckteec_alloc_shm(key_handle_size, CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_KEY_PAIR, + ctrl, out_shm, &out_size); + + if (rv != CKR_OK || out_size != out_shm->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto bail; + } + + key_handle = out_shm->buffer; + *pub_key = key_handle[0]; + *priv_key = key_handle[1]; + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + release_serial_object(&priv_sattr); + release_serial_object(&pub_sattr); + release_serial_object(&smecha); + + return rv; +} + +CK_RV ck_wrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, + CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + struct serializer smecha = { 0 }; + uint32_t session_handle = session; + uint32_t wrp_key_handle = wrapping_key; + uint32_t key_handle = key; + size_t ctrl_size = 0; + size_t out_size = 0; + char *buf = NULL; + + if (!mechanism || !wrapped_key_len) + return CKR_ARGUMENTS_BAD; + + rv = serialize_ck_mecha_params(&smecha, mechanism); + if (rv) + return rv; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][wrapping-key-handle][key-handle] + * [serialized-mecha] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + sizeof(wrp_key_handle) + + sizeof(key_handle) + smecha.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &wrp_key_handle, sizeof(wrp_key_handle)); + buf += sizeof(wrp_key_handle); + + memcpy(buf, &key_handle, sizeof(key_handle)); + buf += sizeof(key_handle); + + memcpy(buf, smecha.buffer, smecha.size); + + /* Shm io2: output buffer reference - wrapped key */ + if (wrapped_key && *wrapped_key_len) + out_shm = ckteec_register_shm(wrapped_key, *wrapped_key_len, + CKTEEC_SHM_OUT); + else + /* Query output data size */ + out_shm = ckteec_alloc_shm(0, CKTEEC_SHM_OUT); + + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_WRAP_KEY, ctrl, out_shm, + &out_size); + + if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) + *wrapped_key_len = out_size; + + if (rv == CKR_BUFFER_TOO_SMALL && out_size && !wrapped_key) + rv = CKR_OK; + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + release_serial_object(&smecha); + + return rv; +} + +CK_RV ck_unwrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, + CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, CK_OBJECT_HANDLE_PTR handle) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *in_shm = NULL; + TEEC_SharedMemory *out_shm = NULL; + struct serializer smecha = { 0 }; + struct serializer sattr = { 0 }; + uint32_t session_handle = session; + uint32_t unwrapping_key_handle = unwrapping_key; + size_t ctrl_size = 0; + uint32_t key_handle = 0; + char *buf = NULL; + size_t out_size = 0; + + if (!handle || !mechanism || (count && !attribs) || + (wrapped_key_len && !wrapped_key)) + return CKR_ARGUMENTS_BAD; + + if (!unwrapping_key) + return CKR_UNWRAPPING_KEY_HANDLE_INVALID; + + rv = serialize_ck_mecha_params(&smecha, mechanism); + if (rv) + return rv; + + rv = serialize_ck_attributes(&sattr, attribs, count); + if (rv) + goto bail; + + /* + * Shm io0: (in/out) ctrl + * (in) [session-handle][unwrapping-key-handle][serialized-mecha] + * [serialized-attributes] + * (out) [status] + */ + ctrl_size = sizeof(session_handle) + sizeof(unwrapping_key_handle) + + smecha.size + sattr.size; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + buf = ctrl->buffer; + + memcpy(buf, &session_handle, sizeof(session_handle)); + buf += sizeof(session_handle); + + memcpy(buf, &unwrapping_key_handle, sizeof(unwrapping_key_handle)); + buf += sizeof(unwrapping_key_handle); + + memcpy(buf, smecha.buffer, smecha.size); + buf += smecha.size; + + memcpy(buf, sattr.buffer, sattr.size); + + /* Shm io1: input - wrapped key buffer */ + in_shm = ckteec_register_shm(wrapped_key, wrapped_key_len, + CKTEEC_SHM_IN); + if (!in_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + /* Shm io2: (out) [object handle] */ + out_shm = ckteec_alloc_shm(sizeof(key_handle), CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = ckteec_invoke_ta(PKCS11_CMD_UNWRAP_KEY, ctrl, in_shm, out_shm, + &out_size, NULL, NULL); + + if (rv != CKR_OK || out_size != out_shm->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto bail; + } + + memcpy(&key_handle, out_shm->buffer, sizeof(key_handle)); + *handle = key_handle; + +bail: + ckteec_free_shm(out_shm); + ckteec_free_shm(in_shm); + ckteec_free_shm(ctrl); + release_serial_object(&sattr); + release_serial_object(&smecha); + + return rv; +} diff --git a/optee/optee_client/libckteec/src/pkcs11_processing.h b/optee/optee_client/libckteec/src/pkcs11_processing.h new file mode 100644 index 0000000..aee8fb2 --- /dev/null +++ b/optee/optee_client/libckteec/src/pkcs11_processing.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2018, Linaro Limited + */ + +#ifndef LIBCKTEEC_PKCS11_PROCESSING_H +#define LIBCKTEEC_PKCS11_PROCESSING_H + +#include +#include + +CK_RV ck_create_object(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, CK_OBJECT_HANDLE_PTR phObject); + +CK_RV ck_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj); + +CK_RV ck_encdecrypt_init(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key, + int decrypt); + +CK_RV ck_encdecrypt_update(CK_SESSION_HANDLE session, + CK_BYTE_PTR in, + CK_ULONG in_len, + CK_BYTE_PTR out, + CK_ULONG_PTR out_len, + int decrypt); + +CK_RV ck_encdecrypt_oneshot(CK_SESSION_HANDLE session, + CK_BYTE_PTR in, + CK_ULONG in_len, + CK_BYTE_PTR out, + CK_ULONG_PTR out_len, + int decrypt); + +CK_RV ck_encdecrypt_final(CK_SESSION_HANDLE session, + CK_BYTE_PTR out, + CK_ULONG_PTR out_len, + int decrypt); + +CK_RV ck_digest_init(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism); + +CK_RV ck_digest_key(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key); + +CK_RV ck_digest_update(CK_SESSION_HANDLE session, CK_BYTE_PTR in, + CK_ULONG in_len); + +CK_RV ck_digest_oneshot(CK_SESSION_HANDLE session, CK_BYTE_PTR in, + CK_ULONG in_len, CK_BYTE_PTR out, + CK_ULONG_PTR out_len); + +CK_RV ck_digest_final(CK_SESSION_HANDLE session, CK_BYTE_PTR out, + CK_ULONG_PTR out_len); + +CK_RV ck_signverify_init(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key, + int sign); + +CK_RV ck_signverify_update(CK_SESSION_HANDLE session, + CK_BYTE_PTR in, + CK_ULONG in_len, + int sign); + +CK_RV ck_signverify_oneshot(CK_SESSION_HANDLE session, + CK_BYTE_PTR in, + CK_ULONG in_len, + CK_BYTE_PTR out, + CK_ULONG_PTR out_len, + int sign); + +CK_RV ck_signverify_final(CK_SESSION_HANDLE session, + CK_BYTE_PTR out, + CK_ULONG_PTR out_len, + int sign); + +CK_RV ck_generate_key(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR handle); + +CK_RV ck_find_objects_init(CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count); + +CK_RV ck_find_objects(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE_PTR obj, + CK_ULONG max_count, + CK_ULONG_PTR count); + +CK_RV ck_find_objects_final(CK_SESSION_HANDLE session); + +CK_RV ck_get_object_size(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE obj, + CK_ULONG_PTR p_size); + +CK_RV ck_get_attribute_value(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE obj, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count); + +CK_RV ck_set_attribute_value(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE obj, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count); + +CK_RV ck_copy_object(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE obj, + CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR handle); + +CK_RV ck_derive_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, CK_OBJECT_HANDLE_PTR handle); + +CK_RV ck_release_active_processing(CK_SESSION_HANDLE session, + enum pkcs11_ta_cmd command); + +CK_RV ck_generate_key_pair(CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR pub_attribs, + CK_ULONG pub_count, + CK_ATTRIBUTE_PTR priv_attribs, + CK_ULONG priv_count, + CK_OBJECT_HANDLE_PTR pub_key, + CK_OBJECT_HANDLE_PTR priv_key); + +CK_RV ck_wrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE wrapping_key, CK_OBJECT_HANDLE key, + CK_BYTE_PTR wrapped_key, CK_ULONG_PTR wrapped_key_len); + +CK_RV ck_unwrap_key(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE unwrapping_key, CK_BYTE_PTR wrapped_key, + CK_ULONG wrapped_key_len, CK_ATTRIBUTE_PTR attribs, + CK_ULONG count, CK_OBJECT_HANDLE_PTR handle); + +#endif /*LIBCKTEEC_PKCS11_PROCESSING_H*/ diff --git a/optee/optee_client/libckteec/src/pkcs11_token.c b/optee/optee_client/libckteec/src/pkcs11_token.c new file mode 100644 index 0000000..670162e --- /dev/null +++ b/optee/optee_client/libckteec/src/pkcs11_token.c @@ -0,0 +1,841 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "ck_helpers.h" +#include "invoke_ta.h" +#include "local_utils.h" +#include "pkcs11_token.h" + +#define PKCS11_LIB_MANUFACTURER "Linaro" +#define PKCS11_LIB_DESCRIPTION "OP-TEE PKCS11 Cryptoki library" + +/** + * ck_get_info - Get local information for C_GetInfo + */ +CK_RV ck_get_info(CK_INFO_PTR info) +{ + const CK_INFO lib_info = { + .cryptokiVersion = { + CK_PKCS11_VERSION_MAJOR, + CK_PKCS11_VERSION_MINOR, + }, + .manufacturerID = PKCS11_LIB_MANUFACTURER, + .flags = 0, /* must be zero per the PKCS#11 2.40 */ + .libraryDescription = PKCS11_LIB_DESCRIPTION, + .libraryVersion = { + PKCS11_TA_VERSION_MAJOR, + PKCS11_TA_VERSION_MINOR + }, + }; + int n = 0; + + if (!info) + return CKR_ARGUMENTS_BAD; + + *info = lib_info; + + /* Pad strings with blank characters */ + n = strnlen((char *)info->manufacturerID, + sizeof(info->manufacturerID)); + memset(&info->manufacturerID[n], ' ', + sizeof(info->manufacturerID) - n); + + n = strnlen((char *)info->libraryDescription, + sizeof(info->libraryDescription)); + memset(&info->libraryDescription[n], ' ', + sizeof(info->libraryDescription) - n); + + return CKR_OK; +} + +/** + * ck_slot_get_list - Wrap C_GetSlotList into PKCS11_CMD_SLOT_LIST + */ +CK_RV ck_slot_get_list(CK_BBOOL present, + CK_SLOT_ID_PTR slots, CK_ULONG_PTR count) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *shm = NULL; + uint32_t *slot_ids = NULL; + size_t client_count = 0; + size_t size = 0; + size_t n = 0; + + /* Discard @present: all slots reported by TA are present */ + (void)present; + + if (!count) + return CKR_ARGUMENTS_BAD; + + /* + * As per spec, if @slots is NULL, "The contents of *pulCount on + * entry to C_GetSlotList has no meaning in this case (...)" + */ + if (slots) + client_count = *count; + + size = client_count * sizeof(*slot_ids); + + shm = ckteec_alloc_shm(size, CKTEEC_SHM_OUT); + if (!shm) + return CKR_HOST_MEMORY; + + rv = ckteec_invoke_ta(PKCS11_CMD_SLOT_LIST, NULL, + NULL, shm, &size, NULL, NULL); + + if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) + *count = size / sizeof(*slot_ids); + + if (!slots && rv == CKR_BUFFER_TOO_SMALL) + rv = CKR_OK; + if (!slots || rv) + goto out; + + slot_ids = shm->buffer; + for (n = 0; n < *count; n++) + slots[n] = slot_ids[n]; + +out: + ckteec_free_shm(shm); + + return rv; +} + +/** + * ck_slot_get_info - Wrap C_GetSlotInfo into PKCS11_CMD_SLOT_INFO + */ +CK_RV ck_slot_get_info(CK_SLOT_ID slot, CK_SLOT_INFO_PTR info) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out = NULL; + uint32_t slot_id = slot; + struct pkcs11_slot_info *ta_info = NULL; + size_t out_size = 0; + + if (!info) + return CKR_ARGUMENTS_BAD; + + ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); + + out = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); + if (!out) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_SLOT_INFO, ctrl, out, &out_size); + if (rv != CKR_OK || out_size != out->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto out; + } + + ta_info = out->buffer; + + COMPILE_TIME_ASSERT(sizeof(info->slotDescription) == + sizeof(ta_info->slot_description)); + memcpy(info->slotDescription, ta_info->slot_description, + sizeof(info->slotDescription)); + + COMPILE_TIME_ASSERT(sizeof(info->manufacturerID) == + sizeof(ta_info->manufacturer_id)); + memcpy(info->manufacturerID, ta_info->manufacturer_id, + sizeof(info->manufacturerID)); + + info->flags = ta_info->flags; + + COMPILE_TIME_ASSERT(sizeof(info->hardwareVersion) == + sizeof(ta_info->hardware_version)); + memcpy(&info->hardwareVersion, ta_info->hardware_version, + sizeof(info->hardwareVersion)); + + COMPILE_TIME_ASSERT(sizeof(info->firmwareVersion) == + sizeof(ta_info->firmware_version)); + memcpy(&info->firmwareVersion, ta_info->firmware_version, + sizeof(info->firmwareVersion)); + +out: + ckteec_free_shm(ctrl); + ckteec_free_shm(out); + + return rv; +} + +/** + * ck_token_get_info - Wrap C_GetTokenInfo into PKCS11_CMD_TOKEN_INFO + */ +CK_RV ck_token_get_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + uint32_t slot_id = slot; + struct pkcs11_token_info *ta_info = NULL; + size_t out_size = 0; + + if (!info) + return CKR_ARGUMENTS_BAD; + + ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); + + out_shm = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_TOKEN_INFO, ctrl, + out_shm, &out_size); + if (rv) + goto out; + + if (out_size != out_shm->size) { + rv = CKR_DEVICE_ERROR; + goto out; + } + + ta_info = out_shm->buffer; + + COMPILE_TIME_ASSERT(sizeof(info->label) == sizeof(ta_info->label)); + memcpy(info->label, ta_info->label, sizeof(info->label)); + + COMPILE_TIME_ASSERT(sizeof(info->manufacturerID) == + sizeof(ta_info->manufacturer_id)); + memcpy(info->manufacturerID, ta_info->manufacturer_id, + sizeof(info->manufacturerID)); + + COMPILE_TIME_ASSERT(sizeof(info->model) == sizeof(ta_info->model)); + memcpy(info->model, ta_info->model, sizeof(info->model)); + + COMPILE_TIME_ASSERT(sizeof(info->serialNumber) == + sizeof(ta_info->serial_number)); + memcpy(info->serialNumber, ta_info->serial_number, + sizeof(info->serialNumber)); + + info->flags = ta_info->flags; + info->ulMaxSessionCount = ta_info->max_session_count; + info->ulSessionCount = ta_info->session_count; + info->ulMaxRwSessionCount = ta_info->max_rw_session_count; + info->ulRwSessionCount = ta_info->rw_session_count; + info->ulMaxPinLen = ta_info->max_pin_len; + info->ulMinPinLen = ta_info->min_pin_len; + info->ulTotalPublicMemory = ta_info->total_public_memory; + info->ulFreePublicMemory = ta_info->free_public_memory; + info->ulTotalPrivateMemory = ta_info->total_private_memory; + info->ulFreePrivateMemory = ta_info->free_private_memory; + + COMPILE_TIME_ASSERT(sizeof(info->hardwareVersion) == + sizeof(ta_info->hardware_version)); + memcpy(&info->hardwareVersion, ta_info->hardware_version, + sizeof(info->hardwareVersion)); + + COMPILE_TIME_ASSERT(sizeof(info->firmwareVersion) == + sizeof(ta_info->firmware_version)); + memcpy(&info->firmwareVersion, ta_info->firmware_version, + sizeof(info->firmwareVersion)); + + COMPILE_TIME_ASSERT(sizeof(info->utcTime) == sizeof(ta_info->utc_time)); + memcpy(&info->utcTime, ta_info->utc_time, sizeof(info->utcTime)); + +out: + ckteec_free_shm(ctrl); + ckteec_free_shm(out_shm); + + return rv; +} + +/** + * ck_token_mechanism_ids - Wrap C_GetMechanismList + */ +CK_RV ck_token_mechanism_ids(CK_SLOT_ID slot, + CK_MECHANISM_TYPE_PTR mechanisms, + CK_ULONG_PTR count) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out = NULL; + uint32_t slot_id = slot; + uint32_t *mecha_ids = NULL; + size_t out_size = 0; + size_t n = 0; + + if (!count) + return CKR_ARGUMENTS_BAD; + + /* + * As per spec, if @mechanism is NULL, "The contents of *pulCount on + * entry to C_GetMechanismList has no meaning in this case (...)" + */ + if (mechanisms) + out_size = *count * sizeof(*mecha_ids); + + ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); + + out = ckteec_alloc_shm(out_size, CKTEEC_SHM_OUT); + if (!out) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_MECHANISM_IDS, + ctrl, out, &out_size); + + if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) + *count = out_size / sizeof(*mecha_ids); + + if (!mechanisms && rv == CKR_BUFFER_TOO_SMALL) + rv = CKR_OK; + if (!mechanisms || rv) + goto out; + + mecha_ids = out->buffer; + for (n = 0; n < *count; n++) + mechanisms[n] = mecha_ids[n]; + +out: + ckteec_free_shm(ctrl); + ckteec_free_shm(out); + + return rv; +} + +/** + * ck_token_mechanism_info - Wrap C_GetMechanismInfo into command MECHANISM_INFO + */ +CK_RV ck_token_mechanism_info(CK_SLOT_ID slot, CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR info) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out = NULL; + uint32_t slot_id = slot; + uint32_t mecha_type = type; + struct pkcs11_mechanism_info *ta_info = NULL; + char *buf = NULL; + size_t out_size = 0; + + if (!info) + return CKR_ARGUMENTS_BAD; + + ctrl = ckteec_alloc_shm(sizeof(slot_id) + sizeof(mecha_type), + CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + + buf = ctrl->buffer; + + memcpy(buf, &slot_id, sizeof(slot_id)); + buf += sizeof(slot_id); + + memcpy(buf, &mecha_type, sizeof(mecha_type)); + + out = ckteec_alloc_shm(sizeof(*ta_info), CKTEEC_SHM_OUT); + if (!out) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_MECHANISM_INFO, + ctrl, out, &out_size); + + if (rv != CKR_OK || out_size != out->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto out; + } + + ta_info = out->buffer; + + info->ulMinKeySize = ta_info->min_key_size; + info->ulMaxKeySize = ta_info->max_key_size; + info->flags = ta_info->flags; + +out: + ckteec_free_shm(ctrl); + ckteec_free_shm(out); + + return rv; +} + +/** + * ck_open_session - Wrap C_OpenSession into PKCS11_CMD_OPEN_{RW|RO}_SESSION + * + * Note: cookie and callback are not utilized by libckteec and are silently + * sinked in to have better out-of-box compatibility with 3rd party libraries + * and applications which provides the callback. + */ +CK_RV ck_open_session(CK_SLOT_ID slot, CK_FLAGS flags, CK_VOID_PTR cookie, + CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out = NULL; + uint32_t slot_id = slot; + uint32_t u32_flags = flags; + uint32_t handle = 0; + size_t out_size = 0; + uint8_t *buf; + + /* Ignore notify callback */ + (void)cookie; + (void)callback; + + if ((flags & ~(CKF_RW_SESSION | CKF_SERIAL_SESSION)) || !session) + return CKR_ARGUMENTS_BAD; + + /* Shm io0: (in/out) ctrl = [slot-id][flags] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(slot_id) + sizeof(u32_flags), + CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + buf = (uint8_t *)ctrl->buffer; + memcpy(buf, &slot_id, sizeof(slot_id)); + buf += sizeof(slot_id); + memcpy(buf, &u32_flags, sizeof(u32_flags)); + + /* Shm io2: (out) [session handle] */ + out = ckteec_alloc_shm(sizeof(handle), CKTEEC_SHM_OUT); + if (!out) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_OPEN_SESSION, + ctrl, out, &out_size); + if (rv != CKR_OK || out_size != out->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto out; + } + + memcpy(&handle, out->buffer, sizeof(handle)); + *session = handle; + +out: + ckteec_free_shm(ctrl); + ckteec_free_shm(out); + + return rv; +} + +/** + * ck_open_session - Wrap C_OpenSession into PKCS11_CMD_CLOSE_SESSION + */ +CK_RV ck_close_session(CK_SESSION_HANDLE session) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t session_handle = session; + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_CLOSE_SESSION, ctrl); + +out: + ckteec_free_shm(ctrl); + + return rv; +} + +/** + * ck_close_all_sessions - Wrap C_CloseAllSessions into TA command + */ +CK_RV ck_close_all_sessions(CK_SLOT_ID slot) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t slot_id = slot; + + /* Shm io0: (in/out) ctrl = [slot-id] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(slot_id), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + memcpy(ctrl->buffer, &slot_id, sizeof(slot_id)); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_CLOSE_ALL_SESSIONS, ctrl); + +out: + ckteec_free_shm(ctrl); + + return rv; +} + +/** + * ck_get_session_info - Wrap C_GetSessionInfo into PKCS11_CMD_SESSION_INFO + */ +CK_RV ck_get_session_info(CK_SESSION_HANDLE session, + CK_SESSION_INFO_PTR info) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out = NULL; + uint32_t session_handle = session; + struct pkcs11_session_info *ta_info = NULL; + size_t out_size = 0; + + if (!info) + return CKR_ARGUMENTS_BAD; + + /* Shm io0: (in/out) ctrl = [session-handle] / [status] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) { + rv = CKR_HOST_MEMORY; + goto out; + } + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io2: (out) [session info] */ + out = ckteec_alloc_shm(sizeof(struct pkcs11_session_info), + CKTEEC_SHM_OUT); + if (!out) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_SESSION_INFO, + ctrl, out, &out_size); + + if (rv != CKR_OK || out_size != out->size) { + if (rv == CKR_OK) + rv = CKR_DEVICE_ERROR; + goto out; + } + + ta_info = (struct pkcs11_session_info *)out->buffer; + info->slotID = ta_info->slot_id; + info->state = ta_info->state; + info->flags = ta_info->flags; + info->ulDeviceError = ta_info->device_error; + +out: + ckteec_free_shm(ctrl); + ckteec_free_shm(out); + + return rv; +} + +/** + * ck_init_token - Wrap C_InitToken into PKCS11_CMD_INIT_TOKEN + */ +CK_RV ck_init_token(CK_SLOT_ID slot, CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len, CK_UTF8CHAR_PTR label) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t slot_id = slot; + uint32_t pkcs11_pin_len = pin_len; + size_t ctrl_size = 0; + char *buf = NULL; + + if (!pin && pin_len) + return CKR_ARGUMENTS_BAD; + + if (!label) + return CKR_ARGUMENTS_BAD; + + /* Shm io0: (in/out) ctrl = [slot-id][pin_len][label][pin] / [status] */ + ctrl_size = sizeof(slot_id) + sizeof(pkcs11_pin_len) + + 32 * sizeof(uint8_t) + pkcs11_pin_len; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + buf = ctrl->buffer; + + memcpy(buf, &slot_id, sizeof(slot_id)); + buf += sizeof(slot_id); + + memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); + buf += sizeof(pkcs11_pin_len); + + memcpy(buf, label, 32 * sizeof(uint8_t)); + buf += 32 * sizeof(uint8_t); + + memcpy(buf, pin, pkcs11_pin_len); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_INIT_TOKEN, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +/** + * ck_init_pin - Wrap C_InitPIN into PKCS11_CMD_INIT_PIN + */ +CK_RV ck_init_pin(CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t pkcs11_session = session; + uint32_t pkcs11_pin_len = pin_len; + size_t ctrl_size = 0; + char *buf = NULL; + + if (!pin && pin_len) + return CKR_ARGUMENTS_BAD; + + /* Shm io0: (in/out) ctrl = [session][pin_len][pin] / [status] */ + ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_pin_len) + + pkcs11_pin_len; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + buf = ctrl->buffer; + + memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); + buf += sizeof(pkcs11_session); + + memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); + buf += sizeof(pkcs11_pin_len); + + memcpy(buf, pin, pkcs11_pin_len); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_INIT_PIN, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +/** + * ck_set_pin - Wrap C_SetPIN into PKCS11_CMD_SET_PIN + */ +CK_RV ck_set_pin(CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR old, CK_ULONG old_len, + CK_UTF8CHAR_PTR new, CK_ULONG new_len) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t pkcs11_session = session; + uint32_t pkcs11_old_len = old_len; + uint32_t pkcs11_new_len = new_len; + size_t ctrl_size = 0; + char *buf; + + if ((!old && old_len) || (!new && new_len)) + return CKR_ARGUMENTS_BAD; + + /* + * Shm io0: (in/out) ctrl + * (in) [session][old_pin_len][new_pin_len][old pin][new pin] + * (out) [status] + */ + ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_old_len) + + sizeof(pkcs11_new_len) + pkcs11_old_len + pkcs11_new_len; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + buf = ctrl->buffer; + + memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); + buf += sizeof(pkcs11_session); + + memcpy(buf, &pkcs11_old_len, sizeof(pkcs11_old_len)); + buf += sizeof(pkcs11_old_len); + + memcpy(buf, &pkcs11_new_len, sizeof(pkcs11_new_len)); + buf += sizeof(pkcs11_new_len); + + memcpy(buf, old, pkcs11_old_len); + buf += pkcs11_old_len; + + memcpy(buf, new, pkcs11_new_len); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_SET_PIN, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +/** + * ck_login - Wrap C_Login into PKCS11_CMD_LOGIN + */ +CK_RV ck_login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type, + CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) + +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t pkcs11_session = session; + uint32_t pkcs11_user = user_type; + uint32_t pkcs11_pin_len = pin_len; + size_t ctrl_size = 0; + char *buf = NULL; + + if (!pin && pin_len) + return CKR_ARGUMENTS_BAD; + + /* Shm io0: (i/o) ctrl = [session][user][pin length][pin] / [status] */ + ctrl_size = sizeof(pkcs11_session) + sizeof(pkcs11_user) + + sizeof(pkcs11_pin_len) + pkcs11_pin_len; + + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + buf = ctrl->buffer; + + memcpy(buf, &pkcs11_session, sizeof(pkcs11_session)); + buf += sizeof(pkcs11_session); + + memcpy(buf, &pkcs11_user, sizeof(pkcs11_user)); + buf += sizeof(pkcs11_user); + + memcpy(buf, &pkcs11_pin_len, sizeof(pkcs11_pin_len)); + buf += sizeof(pkcs11_pin_len); + + memcpy(buf, pin, pkcs11_pin_len); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_LOGIN, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +/** + * ck_logout - Wrap C_Logout into PKCS11_CMD_LOGOUT + */ +CK_RV ck_logout(CK_SESSION_HANDLE session) +{ + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_SharedMemory *ctrl = NULL; + uint32_t session_handle = session; + + /* io0 = [session-handle] */ + ctrl = ckteec_alloc_shm(sizeof(session_handle), CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + rv = ckteec_invoke_ctrl(PKCS11_CMD_LOGOUT, ctrl); + + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_seed_random(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, + CK_ULONG length) +{ + CK_RV rv = CKR_GENERAL_ERROR; + size_t ctrl_size = 0; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *in_shm = NULL; + uint32_t session_handle = session; + + if (!seed && length) + return CKR_ARGUMENTS_BAD; + + if (!seed) + return CKR_OK; + + /* Shm io0: (i/o) [session-handle] / [status] */ + ctrl_size = sizeof(session_handle); + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io1: (in) [seed data] */ + in_shm = ckteec_register_shm(seed, length, CKTEEC_SHM_IN); + if (!in_shm) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_in(PKCS11_CMD_SEED_RANDOM, ctrl, in_shm); + +out: + ckteec_free_shm(in_shm); + ckteec_free_shm(ctrl); + + return rv; +} + +CK_RV ck_generate_random(CK_SESSION_HANDLE session, CK_BYTE_PTR data, + CK_ULONG length) +{ + CK_RV rv = CKR_GENERAL_ERROR; + size_t ctrl_size = 0; + TEEC_SharedMemory *ctrl = NULL; + TEEC_SharedMemory *out_shm = NULL; + uint32_t session_handle = session; + size_t out_size = 0; + + if (!data && length) + return CKR_ARGUMENTS_BAD; + + if (!data) + return CKR_OK; + + /* Shm io0: (i/o) [session-handle] / [status] */ + ctrl_size = sizeof(session_handle); + ctrl = ckteec_alloc_shm(ctrl_size, CKTEEC_SHM_INOUT); + if (!ctrl) + return CKR_HOST_MEMORY; + + memcpy(ctrl->buffer, &session_handle, sizeof(session_handle)); + + /* Shm io2: (out) [generated random] */ + out_shm = ckteec_register_shm(data, length, CKTEEC_SHM_OUT); + if (!out_shm) { + rv = CKR_HOST_MEMORY; + goto out; + } + + rv = ckteec_invoke_ctrl_out(PKCS11_CMD_GENERATE_RANDOM, ctrl, out_shm, + &out_size); + +out: + ckteec_free_shm(out_shm); + ckteec_free_shm(ctrl); + + return rv; +} diff --git a/optee/optee_client/libckteec/src/pkcs11_token.h b/optee/optee_client/libckteec/src/pkcs11_token.h new file mode 100644 index 0000000..7c3e9bb --- /dev/null +++ b/optee/optee_client/libckteec/src/pkcs11_token.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef LIBCKTEEC_PKCS11_TOKEN_H +#define LIBCKTEEC_PKCS11_TOKEN_H + +#include + +#include "invoke_ta.h" + +CK_RV ck_get_info(CK_INFO_PTR info); + +CK_RV ck_slot_get_list(CK_BBOOL present, + CK_SLOT_ID_PTR slots, CK_ULONG_PTR count); + +CK_RV ck_slot_get_info(CK_SLOT_ID slot, CK_SLOT_INFO_PTR info); + +CK_RV ck_token_get_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info); + +CK_RV ck_token_mechanism_ids(CK_SLOT_ID slot, + CK_MECHANISM_TYPE_PTR mechanisms, + CK_ULONG_PTR count); + +CK_RV ck_token_mechanism_info(CK_SLOT_ID slot, CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR info); + +CK_RV ck_open_session(CK_SLOT_ID slot, CK_FLAGS flags, CK_VOID_PTR cookie, + CK_NOTIFY callback, CK_SESSION_HANDLE_PTR session); + +CK_RV ck_close_session(CK_SESSION_HANDLE session); + +CK_RV ck_close_all_sessions(CK_SLOT_ID slot); + +CK_RV ck_get_session_info(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info); + +CK_RV ck_init_token(CK_SLOT_ID slot, CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len, CK_UTF8CHAR_PTR label); + +CK_RV ck_init_pin(CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR pin, CK_ULONG pin_len); + +CK_RV ck_set_pin(CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR old, CK_ULONG old_len, + CK_UTF8CHAR_PTR new, CK_ULONG new_len); + +CK_RV ck_login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type, + CK_UTF8CHAR_PTR pin, CK_ULONG pin_len); + +CK_RV ck_logout(CK_SESSION_HANDLE session); + +CK_RV ck_seed_random(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, + CK_ULONG length); + +CK_RV ck_generate_random(CK_SESSION_HANDLE session, CK_BYTE_PTR data, + CK_ULONG length); + +#endif /*LIBCKTEEC_PKCS11_TOKEN_H*/ diff --git a/optee/optee_client/libckteec/src/serialize_ck.c b/optee/optee_client/libckteec/src/serialize_ck.c new file mode 100644 index 0000000..6fe9d10 --- /dev/null +++ b/optee/optee_client/libckteec/src/serialize_ck.c @@ -0,0 +1,791 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "ck_helpers.h" +#include "local_utils.h" +#include "serializer.h" +#include "serialize_ck.h" + +/* + * Serialization and de-serialization logic + * + * Cryptoki API works in a way that user application uses memory references + * in object attributes description. TA can be invoked with only a small set + * of possible references to caller memory. Thus a Cryptoki object, made of + * data and pointers to data, is reassembled into a byte array where each + * attribute info (ID, value size, value) is appended with byte alignment. This + * so-called serialized object can be passed through the TA API. + * + * Initial entry to PKCS11 TA uses serialize_ck_attributes(). When TA + * returns with updated serialized data to be passed back to caller, we call + * deserialize_ck_attributes(). + * + * Special handling is performed for CK_ULONG passing which may be either 32 + * bits or 64 bits depending on target device architecture. In TA interface + * this is handled as unsigned 32 bit data type. + * + * When user application is querying attributes in example with + * C_GetAttributeValue() user may allocate larger value buffers. During entry + * to TA shared buffer is allocated in serialize_ck_attributes() based on + * caller's arguments. For each attribute TA verifies if value fits in + * the buffer and if it does, value is returned. Value size in buffer is + * updated to indicate real size of the value. When call is returned back to + * REE deserialize_ck_attributes() is invoked and then both input arguments and + * serialization buffer are used to return values to caller. Provided input + * arguments from caller are used to determine serialization buffer structure + * and then actual values and value sizes are then decoded from serialization + * buffer and returned to caller in caller's allocated memory. + */ + +/* + * Generic way of serializing CK keys, certificates, mechanism parameters, ... + * In cryptoki 2.40 parameters are almost all packaged as structure below: + */ +struct ck_ref { + CK_ULONG id; + CK_BYTE_PTR ptr; + CK_ULONG len; +}; + +/* + * This is for attributes that contains data memory indirections. + * In other words, an attributes that defines a list of attributes. + * They are identified from the attribute type CKA_... + * + * @obj - ref used to track the serial object being created + * @attribute - pointer to a structure aligned of the CK_ATTRIBUTE struct + */ +static CK_RV serialize_indirect_attribute(struct serializer *obj, + CK_ATTRIBUTE_PTR attribute) +{ + CK_ATTRIBUTE_PTR attr = NULL; + CK_ULONG count = 0; + CK_RV rv = CKR_GENERAL_ERROR; + struct serializer obj2 = { 0 }; + + switch (attribute->type) { + /* These are serialized each separately */ + case CKA_DERIVE_TEMPLATE: + case CKA_WRAP_TEMPLATE: + case CKA_UNWRAP_TEMPLATE: + count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE); + attr = (CK_ATTRIBUTE_PTR)attribute->pValue; + break; + default: + return CKR_NO_EVENT; + } + + /* Create a serialized object for the content */ + rv = serialize_ck_attributes(&obj2, attr, count); + if (rv) + return rv; + + /* + * Append the created serialized object into target object: + * [attrib-id][byte-size][attributes-data] + */ + rv = serialize_32b(obj, attribute->type); + if (rv) + return rv; + + rv = serialize_32b(obj, obj2.size); + if (rv) + return rv; + + rv = serialize_buffer(obj, obj2.buffer, obj2.size); + if (rv) + return rv; + + obj->item_count++; + + return rv; +} + +static CK_RV deserialize_indirect_attribute(struct pkcs11_attribute_head *obj, + CK_ATTRIBUTE_PTR attribute) +{ + CK_ULONG count = 0; + CK_ATTRIBUTE_PTR attr = NULL; + + switch (attribute->type) { + /* These are serialized each separately */ + case CKA_DERIVE_TEMPLATE: + case CKA_WRAP_TEMPLATE: + case CKA_UNWRAP_TEMPLATE: + count = attribute->ulValueLen / sizeof(CK_ATTRIBUTE); + attr = (CK_ATTRIBUTE_PTR)attribute->pValue; + break; + default: + return CKR_GENERAL_ERROR; + } + + return deserialize_ck_attributes(obj->data, attr, count); +} + +static int ck_attr_is_ulong(CK_ATTRIBUTE_TYPE attribute_id) +{ + switch (attribute_id) { + case CKA_CLASS: + case CKA_CERTIFICATE_TYPE: + case CKA_CERTIFICATE_CATEGORY: + case CKA_NAME_HASH_ALGORITHM: + case CKA_KEY_TYPE: + case CKA_HW_FEATURE_TYPE: + case CKA_MECHANISM_TYPE: + case CKA_KEY_GEN_MECHANISM: + case CKA_VALUE_LEN: + case CKA_MODULUS_BITS: + return true; + default: + return false; + } +} + +static CK_RV serialize_ck_attribute(struct serializer *obj, CK_ATTRIBUTE *attr) +{ + CK_MECHANISM_TYPE *type = NULL; + uint32_t pkcs11_size = 0; + uint32_t pkcs11_data32 = 0; + void *pkcs11_pdata = NULL; + uint32_t *mech_buf = NULL; + CK_RV rv = CKR_GENERAL_ERROR; + unsigned int n = 0; + unsigned int m = 0; + + if (attr->type == PKCS11_UNDEFINED_ID) + return CKR_ATTRIBUTE_TYPE_INVALID; + + switch (attr->type) { + case CKA_DERIVE_TEMPLATE: + case CKA_WRAP_TEMPLATE: + case CKA_UNWRAP_TEMPLATE: + return serialize_indirect_attribute(obj, attr); + case CKA_ALLOWED_MECHANISMS: + n = attr->ulValueLen / sizeof(CK_ULONG); + pkcs11_size = n * sizeof(uint32_t); + mech_buf = malloc(pkcs11_size); + if (!mech_buf) + return CKR_HOST_MEMORY; + + type = attr->pValue; + for (m = 0; m < n; m++) { + mech_buf[m] = type[m]; + if (mech_buf[m] == PKCS11_UNDEFINED_ID) { + rv = CKR_MECHANISM_INVALID; + goto out; + } + } + pkcs11_pdata = mech_buf; + break; + /* Attributes which data value do not need conversion (aside ulong) */ + default: + pkcs11_pdata = attr->pValue; + if (!attr->pValue) { + pkcs11_size = 0; + } else if (ck_attr_is_ulong(attr->type)) { + CK_ULONG ck_ulong = 0; + + if (attr->ulValueLen < sizeof(CK_ULONG)) + return CKR_ATTRIBUTE_VALUE_INVALID; + + memcpy(&ck_ulong, attr->pValue, sizeof(ck_ulong)); + pkcs11_data32 = ck_ulong; + pkcs11_pdata = &pkcs11_data32; + pkcs11_size = sizeof(uint32_t); + } else { + pkcs11_size = attr->ulValueLen; + } + break; + } + + rv = serialize_32b(obj, attr->type); + if (rv) + goto out; + + rv = serialize_32b(obj, pkcs11_size); + if (rv) + goto out; + + rv = serialize_buffer(obj, pkcs11_pdata, pkcs11_size); + if (rv) + goto out; + + obj->item_count++; +out: + free(mech_buf); + + return rv; +} + +/* CK attribute reference arguments are list of attribute item */ +CK_RV serialize_ck_attributes(struct serializer *obj, + CK_ATTRIBUTE_PTR attributes, CK_ULONG count) +{ + CK_ULONG n = 0; + CK_RV rv = CKR_OK; + + rv = init_serial_object(obj); + if (rv) + return rv; + + for (n = 0; n < count; n++) { + rv = serialize_ck_attribute(obj, attributes + n); + if (rv) + break; + } + + if (rv) + release_serial_object(obj); + else + finalize_serial_object(obj); + + return rv; +} + +static CK_RV deserialize_mecha_list(CK_MECHANISM_TYPE *dst, void *src, + size_t count) +{ + char *ta_src = src; + size_t n = 0; + uint32_t mecha_id = 0; + + for (n = 0; n < count; n++) { + memcpy(&mecha_id, ta_src + n * sizeof(mecha_id), + sizeof(mecha_id)); + dst[n] = mecha_id; + } + + return CKR_OK; +} + +static CK_RV deserialize_ck_attribute(struct pkcs11_attribute_head *in, + uint8_t *data, CK_ATTRIBUTE_PTR out) +{ + CK_ULONG ck_ulong = 0; + uint32_t pkcs11_data32 = 0; + CK_RV rv = CKR_OK; + + out->type = in->id; + + if (in->size == PKCS11_CK_UNAVAILABLE_INFORMATION) { + out->ulValueLen = CK_UNAVAILABLE_INFORMATION; + return CKR_OK; + } + + if (!out->pValue && ck_attr_is_ulong(out->type)) { + out->ulValueLen = sizeof(CK_ULONG); + return CKR_OK; + } + + if (out->ulValueLen < in->size) { + out->ulValueLen = in->size; + return CKR_OK; + } + + if (!out->pValue) + return CKR_OK; + + /* Specific ulong encoded as 32bit in PKCS11 TA API */ + if (ck_attr_is_ulong(out->type)) { + if (out->ulValueLen < sizeof(CK_ULONG)) + return CKR_ATTRIBUTE_VALUE_INVALID; + + memcpy(&pkcs11_data32, data, sizeof(uint32_t)); + if (out->type == CKA_KEY_GEN_MECHANISM && + pkcs11_data32 == PKCS11_CK_UNAVAILABLE_INFORMATION) + ck_ulong = CK_UNAVAILABLE_INFORMATION; + else + ck_ulong = pkcs11_data32; + + memcpy(out->pValue, &ck_ulong, sizeof(CK_ULONG)); + out->ulValueLen = sizeof(CK_ULONG); + return CKR_OK; + } + + switch (out->type) { + case CKA_DERIVE_TEMPLATE: + case CKA_WRAP_TEMPLATE: + case CKA_UNWRAP_TEMPLATE: + rv = deserialize_indirect_attribute(in, out->pValue); + break; + case CKA_ALLOWED_MECHANISMS: + rv = deserialize_mecha_list(out->pValue, data, + in->size / sizeof(uint32_t)); + out->ulValueLen = in->size / sizeof(uint32_t) * + sizeof(CK_ULONG); + break; + /* Attributes which data value do not need conversion (aside ulong) */ + default: + memcpy(out->pValue, data, in->size); + out->ulValueLen = in->size; + break; + } + + return rv; +} + +CK_RV deserialize_ck_attributes(uint8_t *in, CK_ATTRIBUTE_PTR attributes, + CK_ULONG count) +{ + CK_ATTRIBUTE_PTR cur_attr = attributes; + CK_ULONG n = 0; + CK_RV rv = CKR_OK; + uint8_t *curr_head = in; + size_t len = 0; + + curr_head += sizeof(struct pkcs11_object_head); + + for (n = count; n > 0; n--, cur_attr++, curr_head += len) { + struct pkcs11_attribute_head *cli_ref = (void *)curr_head; + struct pkcs11_attribute_head cli_head = { 0 }; + void *data_ptr = NULL; + + /* Make copy if header so that is aligned properly. */ + memcpy(&cli_head, cli_ref, sizeof(cli_head)); + + /* Get real data pointer from template data */ + data_ptr = cli_ref->data; + + len = sizeof(cli_head); + + /* Advance by size provisioned in input serialized buffer */ + if (cur_attr->pValue) { + if (ck_attr_is_ulong(cur_attr->type)) + len += sizeof(uint32_t); + else + len += cur_attr->ulValueLen; + } + + rv = deserialize_ck_attribute(&cli_head, data_ptr, cur_attr); + if (rv) + return rv; + } + + return rv; +} + +/* + * Serialization of CK mechanism parameters + * + * Most mechanism have no parameters. + * Some mechanism have a single 32bit parameter. + * Some mechanism have a specific parameter structure which may contain + * indirected data (data referred by a buffer pointer). + * + * Below are each structure specific mechanisms parameters. + */ + +static CK_RV serialize_mecha_aes_ctr(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_AES_CTR_PARAMS_PTR param = mecha->pParameter; + CK_RV rv = CKR_GENERAL_ERROR; + uint32_t size = 0; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + size = sizeof(uint32_t) + sizeof(param->cb); + rv = serialize_32b(obj, size); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, param->ulCounterBits); + if (rv) + return rv; + + rv = serialize_buffer(obj, param->cb, sizeof(param->cb)); + if (rv) + return rv; + + return rv; +} + +static CK_RV serialize_mecha_aes_iv(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + uint32_t iv_size = mecha->ulParameterLen; + CK_RV rv = CKR_GENERAL_ERROR; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + rv = serialize_32b(obj, iv_size); + if (rv) + return rv; + + return serialize_buffer(obj, mecha->pParameter, mecha->ulParameterLen); +} + +static CK_RV serialize_mecha_key_deriv_str(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_KEY_DERIVATION_STRING_DATA_PTR param = mecha->pParameter; + CK_RV rv = CKR_GENERAL_ERROR; + uint32_t size = 0; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + size = sizeof(uint32_t) + param->ulLen; + rv = serialize_32b(obj, size); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, param->ulLen); + if (rv) + return rv; + + return serialize_buffer(obj, param->pData, param->ulLen); +} + +static CK_RV serialize_mecha_ecdh1_derive_param(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_ECDH1_DERIVE_PARAMS *params = mecha->pParameter; + CK_RV rv = CKR_GENERAL_ERROR; + size_t params_size = 3 * sizeof(uint32_t) + params->ulSharedDataLen + + params->ulPublicDataLen; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + rv = serialize_32b(obj, params_size); + if (rv) + return rv; + + rv = serialize_32b(obj, params->kdf); + if (rv) + return rv; + + rv = serialize_32b(obj, params->ulSharedDataLen); + if (rv) + return rv; + + rv = serialize_buffer(obj, params->pSharedData, + params->ulSharedDataLen); + if (rv) + return rv; + + rv = serialize_32b(obj, params->ulPublicDataLen); + if (rv) + return rv; + + return serialize_buffer(obj, params->pPublicData, + params->ulPublicDataLen); +} + +static CK_RV serialize_mecha_aes_cbc_encrypt_data(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR param = mecha->pParameter; + CK_RV rv = CKR_GENERAL_ERROR; + uint32_t size = 0; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + size = sizeof(param->iv) + sizeof(uint32_t) + param->length; + rv = serialize_32b(obj, size); + if (rv) + return rv; + + rv = serialize_buffer(obj, param->iv, sizeof(param->iv)); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, param->length); + if (rv) + return rv; + + return serialize_buffer(obj, param->pData, param->length); +} + +static CK_RV serialize_mecha_rsa_pss_param(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_RSA_PKCS_PSS_PARAMS *params = mecha->pParameter; + CK_RV rv = CKR_GENERAL_ERROR; + uint32_t params_size = 3 * sizeof(uint32_t); + + if (mecha->ulParameterLen != sizeof(*params)) + return CKR_ARGUMENTS_BAD; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + rv = serialize_32b(obj, params_size); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, params->hashAlg); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, params->mgf); + if (rv) + return rv; + + return serialize_ck_ulong(obj, params->sLen); +} + +static CK_RV serialize_mecha_rsa_oaep_param(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_RSA_PKCS_OAEP_PARAMS *params = mecha->pParameter; + CK_RV rv = CKR_GENERAL_ERROR; + size_t params_size = 4 * sizeof(uint32_t) + params->ulSourceDataLen; + + if (mecha->ulParameterLen != sizeof(*params)) + return CKR_ARGUMENTS_BAD; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + rv = serialize_32b(obj, params_size); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, params->hashAlg); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, params->mgf); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, params->source); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, params->ulSourceDataLen); + if (rv) + return rv; + + return serialize_buffer(obj, params->pSourceData, + params->ulSourceDataLen); +} + +static CK_RV serialize_mecha_rsa_aes_key_wrap(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_RSA_AES_KEY_WRAP_PARAMS *params = mecha->pParameter; + CK_RSA_PKCS_OAEP_PARAMS *aes_params = params->pOAEPParams; + CK_RV rv = CKR_GENERAL_ERROR; + size_t params_size = 5 * sizeof(uint32_t) + aes_params->ulSourceDataLen; + + if (mecha->ulParameterLen != sizeof(*params)) + return CKR_ARGUMENTS_BAD; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + rv = serialize_32b(obj, params_size); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, params->ulAESKeyBits); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, aes_params->hashAlg); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, aes_params->mgf); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, aes_params->source); + if (rv) + return rv; + + rv = serialize_ck_ulong(obj, aes_params->ulSourceDataLen); + if (rv) + return rv; + + return serialize_buffer(obj, aes_params->pSourceData, + aes_params->ulSourceDataLen); +} + +static CK_RV serialize_mecha_eddsa(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_EDDSA_PARAMS *params = mecha->pParameter; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + rv = serialize_32b(obj, 2 * sizeof(uint32_t) + params->ulContextDataLen); + if (rv) + return rv; + + rv = serialize_32b(obj, params->phFlag); + if (rv) + return rv; + + rv = serialize_32b(obj, params->ulContextDataLen); + if (rv) + return rv; + + return serialize_buffer(obj, params->pContextData, params->ulContextDataLen); +} + +static CK_RV serialize_mecha_mac_general_param(struct serializer *obj, + CK_MECHANISM_PTR mecha) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_ULONG ck_data = 0; + + if (mecha->ulParameterLen != sizeof(ck_data)) + return CKR_ARGUMENTS_BAD; + + memcpy(&ck_data, mecha->pParameter, mecha->ulParameterLen); + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + rv = serialize_32b(obj, sizeof(uint32_t)); + if (rv) + return rv; + + return serialize_ck_ulong(obj, ck_data); +} + +/** + * serialize_ck_mecha_params - serialize a mechanism type & params + * + * @obj - serializer used to track the serialization + * @mechanism - pointer of the in structure aligned CK_MECHANISM. + * + * Serialized content: + * [mechanism-type][mechanism-param-blob] + * + * [mechanism-param-blob] depends on mechanism type ID, see + * serialize_mecha_XXX(). + */ +CK_RV serialize_ck_mecha_params(struct serializer *obj, + CK_MECHANISM_PTR mechanism) +{ + CK_MECHANISM mecha = { 0 }; + CK_RV rv = CKR_GENERAL_ERROR; + + memset(obj, 0, sizeof(*obj)); + + obj->object = PKCS11_CKO_MECHANISM; + + mecha = *mechanism; + obj->type = mecha.mechanism; + if (obj->type == PKCS11_UNDEFINED_ID) + return CKR_MECHANISM_INVALID; + + switch (mecha.mechanism) { + case CKM_GENERIC_SECRET_KEY_GEN: + case CKM_AES_KEY_GEN: + case CKM_AES_ECB: + case CKM_AES_CMAC: + case CKM_MD5: + case CKM_SHA_1: + case CKM_SHA224: + case CKM_SHA256: + case CKM_SHA384: + case CKM_SHA512: + case CKM_MD5_HMAC: + case CKM_SHA_1_HMAC: + case CKM_SHA224_HMAC: + case CKM_SHA256_HMAC: + case CKM_SHA384_HMAC: + case CKM_SHA512_HMAC: + case CKM_EC_KEY_PAIR_GEN: + case CKM_EC_EDWARDS_KEY_PAIR_GEN: + case CKM_ECDSA: + case CKM_ECDSA_SHA1: + case CKM_ECDSA_SHA224: + case CKM_ECDSA_SHA256: + case CKM_ECDSA_SHA384: + case CKM_ECDSA_SHA512: + case CKM_RSA_PKCS_KEY_PAIR_GEN: + case CKM_RSA_PKCS: + case CKM_MD5_RSA_PKCS: + case CKM_SHA1_RSA_PKCS: + case CKM_SHA224_RSA_PKCS: + case CKM_SHA256_RSA_PKCS: + case CKM_SHA384_RSA_PKCS: + case CKM_SHA512_RSA_PKCS: + /* No parameter expected, size shall be 0 */ + if (mechanism->ulParameterLen) + return CKR_MECHANISM_PARAM_INVALID; + + rv = serialize_32b(obj, obj->type); + if (rv) + return rv; + + return serialize_32b(obj, 0); + + case CKM_EDDSA: + return serialize_mecha_eddsa(obj, &mecha); + + case CKM_AES_CBC: + case CKM_AES_CBC_PAD: + case CKM_AES_CTS: + return serialize_mecha_aes_iv(obj, &mecha); + + case CKM_AES_CTR: + return serialize_mecha_aes_ctr(obj, &mecha); + + case CKM_AES_ECB_ENCRYPT_DATA: + return serialize_mecha_key_deriv_str(obj, &mecha); + + case CKM_AES_CBC_ENCRYPT_DATA: + return serialize_mecha_aes_cbc_encrypt_data(obj, &mecha); + + case CKM_ECDH1_DERIVE: + case CKM_ECDH1_COFACTOR_DERIVE: + return serialize_mecha_ecdh1_derive_param(obj, &mecha); + + case CKM_RSA_PKCS_PSS: + case CKM_SHA1_RSA_PKCS_PSS: + case CKM_SHA256_RSA_PKCS_PSS: + case CKM_SHA384_RSA_PKCS_PSS: + case CKM_SHA512_RSA_PKCS_PSS: + case CKM_SHA224_RSA_PKCS_PSS: + return serialize_mecha_rsa_pss_param(obj, &mecha); + + case CKM_RSA_PKCS_OAEP: + return serialize_mecha_rsa_oaep_param(obj, &mecha); + + case CKM_AES_CMAC_GENERAL: + case CKM_MD5_HMAC_GENERAL: + case CKM_SHA_1_HMAC_GENERAL: + case CKM_SHA224_HMAC_GENERAL: + case CKM_SHA256_HMAC_GENERAL: + case CKM_SHA384_HMAC_GENERAL: + case CKM_SHA512_HMAC_GENERAL: + return serialize_mecha_mac_general_param(obj, &mecha); + case CKM_RSA_AES_KEY_WRAP: + return serialize_mecha_rsa_aes_key_wrap(obj, &mecha); + + default: + return CKR_MECHANISM_INVALID; + } +} diff --git a/optee/optee_client/libckteec/src/serialize_ck.h b/optee/optee_client/libckteec/src/serialize_ck.h new file mode 100644 index 0000000..f7a205a --- /dev/null +++ b/optee/optee_client/libckteec/src/serialize_ck.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ +#ifndef LIBCKTEEC_SERIALIZE_CK_H +#define LIBCKTEEC_SERIALIZE_CK_H + +#include + +#include "serializer.h" + +/* Create (and allocate) a serial object for CK_ATTRIBUTE array */ +CK_RV serialize_ck_attributes(struct serializer *obj, + CK_ATTRIBUTE_PTR attributes, CK_ULONG count); + +/* Convert PKCS11 TA attributes back to CK_ATTRIBUTE array */ +CK_RV deserialize_ck_attributes(uint8_t *in, + CK_ATTRIBUTE_PTR attributes, CK_ULONG count); + +/* Create (and allocate) a serial object for CK_MECHANISM array */ +CK_RV serialize_ck_mecha_params(struct serializer *obj, + CK_MECHANISM_PTR mechanisms); +#endif /*LIBCKTEEC_SERIALIZE_CK_H*/ diff --git a/optee/optee_client/libckteec/src/serializer.c b/optee/optee_client/libckteec/src/serializer.c new file mode 100644 index 0000000..d94932b --- /dev/null +++ b/optee/optee_client/libckteec/src/serializer.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include + +#include "ck_helpers.h" +#include "local_utils.h" +#include "serializer.h" + +CK_RV init_serial_object(struct serializer *obj) +{ + struct pkcs11_object_head head = { 0 }; + + memset(obj, 0, sizeof(*obj)); + + return serialize_buffer(obj, &head, sizeof(head)); +} + +void finalize_serial_object(struct serializer *obj) +{ + struct pkcs11_object_head head = { 0 }; + + head.attrs_size = obj->size - sizeof(head); + head.attrs_count = obj->item_count; + memcpy(obj->buffer, &head, sizeof(head)); +} + +void release_serial_object(struct serializer *obj) +{ + free(obj->buffer); + obj->buffer = NULL; +} + +/** + * serialize - append data in a serialized buffer + * + * Serialize data in provided buffer. + * Ensure 64byte alignment of appended data in the buffer. + */ +static CK_RV serialize(char **bstart, size_t *blen, void *data, size_t len) +{ + size_t nlen = *blen + len; + char *buf = realloc(*bstart, nlen); + + if (!buf) + return CKR_HOST_MEMORY; + + memcpy(buf + *blen, data, len); + + *blen = nlen; + *bstart = buf; + + return CKR_OK; +} + +CK_RV serialize_buffer(struct serializer *obj, void *data, size_t size) +{ + return serialize(&obj->buffer, &obj->size, data, size); +} + +CK_RV serialize_32b(struct serializer *obj, uint32_t data) +{ + return serialize_buffer(obj, &data, sizeof(data)); +} + +CK_RV serialize_ck_ulong(struct serializer *obj, CK_ULONG data) +{ + uint32_t data32 = data; + + return serialize_buffer(obj, &data32, sizeof(data32)); +} diff --git a/optee/optee_client/libckteec/src/serializer.h b/optee/optee_client/libckteec/src/serializer.h new file mode 100644 index 0000000..0c9264a --- /dev/null +++ b/optee/optee_client/libckteec/src/serializer.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ +#ifndef LIBCKTEEC_SERIALIZER_H +#define LIBCKTEEC_SERIALIZER_H + +#include +#include +#include +#include + +/* + * Struct used to create the buffer storing the serialized data. + * Contains some fields to help parsing content (type/boolprops). + */ +struct serializer { + char *buffer; /* serial buffer base address */ + size_t size; /* serial buffer current byte size */ + size_t item_count; /* number of items in entry table */ + uint32_t object; + uint32_t type; +}; + +/* Init/finalize/release a serializer object */ +CK_RV init_serial_object(struct serializer *obj); +void finalize_serial_object(struct serializer *obj); +void release_serial_object(struct serializer *obj); + +CK_RV serialize_buffer(struct serializer *obj, void *data, size_t size); +CK_RV serialize_32b(struct serializer *obj, uint32_t data); +CK_RV serialize_ck_ulong(struct serializer *obj, CK_ULONG data); + +#endif /*LIBCKTEEC_SERIALIZER_H*/ diff --git a/optee/optee_client/libseteec/CMakeLists.txt b/optee/optee_client/libseteec/CMakeLists.txt new file mode 100644 index 0000000..5080231 --- /dev/null +++ b/optee/optee_client/libseteec/CMakeLists.txt @@ -0,0 +1,65 @@ +project(seteec + VERSION 0.1.0 + LANGUAGES C) + +################################################################################ +# Packages +################################################################################ +find_package(Threads REQUIRED) +if(NOT THREADS_FOUND) + message(FATAL_ERROR "Threads not found") +endif() + +include(GNUInstallDirs) + +################################################################################ +# Source files +################################################################################ +set (SRC + src/se.c +) + +################################################################################ +# Built library +################################################################################ +add_library (seteec ${SRC}) + +set_target_properties (seteec PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) + +################################################################################ +# Flags always set +################################################################################ +target_compile_definitions (seteec + PRIVATE -D_GNU_SOURCE + PRIVATE -DBINARY_PREFIX="LT" +) + +################################################################################ +# Optional flags +################################################################################ + +################################################################################ +# Public and private header and library dependencies +################################################################################ +target_include_directories(seteec + PUBLIC $ + $ + PRIVATE src +) + +target_link_libraries (seteec + PRIVATE pthread + PRIVATE teec +) + +################################################################################ +# Install targets +################################################################################ +install (TARGETS seteec + DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +add_subdirectory(include) diff --git a/optee/optee_client/libseteec/Makefile b/optee/optee_client/libseteec/Makefile new file mode 100644 index 0000000..8384d5b --- /dev/null +++ b/optee/optee_client/libseteec/Makefile @@ -0,0 +1,71 @@ +include ../flags.mk +include ../config.mk + +OUT_DIR := $(OO)/libseteec + +.PHONY: all libseteec clean + +all: libseteec +install: libseteec + +LIB_NAME := libseteec +MAJOR_VERSION := 0 +MINOR_VERSION := 1 +PATCH_VERSION := 0 + +LIB_MAJOR := $(LIB_NAME).so.$(MAJOR_VERSION) +LIB_MAJ_MIN := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION) +LIB_MAJ_MIN_PAT := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) +LIBSETEEC_SO_LIBRARY := $(LIB_MAJ_MIN_PAT) +LIBSETEEC_AR_LIBRARY := $(LIB_NAME).a + +LIBSETEEC_SRC_DIR := src + +LIBSETEEC_SRCS = se.c + +LIBSETEEC_INCLUDES = ${CURDIR}/include +LIBSETEEC_INCLUDES += ${CURDIR}/../public + +LIBSETEEC_CFLAGS := $(addprefix -I, $(LIBSETEEC_INCLUDES)) \ + $(CFLAGS) -D_GNU_SOURCE -fPIC + +LIBSETEEC_LFLAGS := $(LDFLAGS) -L$(OUT_DIR)/../libteec -lteec -lpthread + +LIBSETEEC_OBJ_DIR := $(OUT_DIR) +LIBSETEEC_OBJS := $(patsubst %.c,$(LIBSETEEC_OBJ_DIR)/%.o, $(LIBSETEEC_SRCS)) + +$(LIBSETEEC_OBJ_DIR)/%.o: ${LIBSETEEC_SRC_DIR}/%.c + $(VPREFIX)mkdir -p $(LIBSETEEC_OBJ_DIR) + @echo " CC $<" + $(VPREFIX)$(CC) $(LIBSETEEC_CFLAGS) -c $< -o $@ + +libseteec: $(OUT_DIR)/$(LIBSETEEC_SO_LIBRARY) + +$(OUT_DIR)/$(LIBSETEEC_SO_LIBRARY): $(LIBSETEEC_OBJS) + @echo " LINK $@" + $(VPREFIX)$(CC) -shared -Wl,-soname,$(LIB_MAJOR) -o $@ $+ $(LIBSETEEC_LFLAGS) + @echo "" + +libseteec: $(OUT_DIR)/$(LIBSETEEC_AR_LIBRARY) + +$(OUT_DIR)/$(LIBSETEEC_AR_LIBRARY): $(LIBSETEEC_OBJS) + @echo " AR $@" + $(VPREFIX)$(AR) rcs $@ $+ + +libseteec: + $(VPREFIX)ln -sf $(LIB_MAJ_MIN_PAT) $(OUT_DIR)/$(LIB_MAJ_MIN) + $(VPREFIX)ln -sf $(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_MAJOR) + $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME).so + +################################################################################ +# Cleaning up configuration +################################################################################ +clean: + $(RM) $(LIBSETEEC_OBJS) + $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN_PAT) + $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN) + $(RM) $(OUT_DIR)/$(LIB_MAJOR) + $(RM) $(OUT_DIR)/$(LIBSETEEC_SO_LIBRARY) + $(RM) $(OUT_DIR)/$(LIBSETEEC_AR_LIBRARY) + $(call rmdir,$(OUT_DIR)) + diff --git a/optee/optee_client/libseteec/include/CMakeLists.txt b/optee/optee_client/libseteec/include/CMakeLists.txt new file mode 100644 index 0000000..9241574 --- /dev/null +++ b/optee/optee_client/libseteec/include/CMakeLists.txt @@ -0,0 +1,7 @@ +project (libseteec-headers C) + +FILE(GLOB INSTALL_HEADERS "*.h") + +add_library(${PROJECT_NAME} INTERFACE) + +install (FILES ${INSTALL_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/optee/optee_client/libseteec/include/se_tee.h b/optee/optee_client/libseteec/include/se_tee.h new file mode 100644 index 0000000..4da2342 --- /dev/null +++ b/optee/optee_client/libseteec/include/se_tee.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Foundries.io + * Jorge Ramirez-Ortiz + */ + +#ifndef SE_TEE_H +#define SE_TEE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long SE_ULONG; +typedef SE_ULONG SE_RV; + +/* Values for type SR_RV */ +#define SER_OK 0x0000 +#define SER_CANT_OPEN_SESSION 0x0001 +#define SER_ERROR_GENERIC 0x0002 + +/* + * Type identifier for the APDU message as described by Smart Card Standard ISO7816-4 + * about ADPU message bodies decoding convention: + * + * https://cardwerk.com/smart-card-standard-iso7816-4-section-5-basic-organizations/#chap5_3_2 + */ +enum se_apdu_type { + SE_APDU_NO_HINT, + SE_APDU_CASE_1, + SE_APDU_CASE_2, + SE_APDU_CASE_2E, + SE_APDU_CASE_3, + SE_APDU_CASE_3E, + SE_APDU_CASE_4, + SE_APDU_CASE_4E, +}; + +/** + * se_apdu_request() - Send an APDU message and get response. + * + * @param type Type of the APDU command. + * @param hdr Pointer to APDU message header. + * @param hdr_len Byte length of message header @hdr. + * @param src Pointer to APDU message payload. + * @param src_len Byte length of message payload @src. + * @param dst Pointer to APDU message reponse buffer. + * @param dst_len Byte length of reponse buffer @dst. + * + * @return SER_CANT_OPEN_SESSION Error opening the TEE session. + * @return SER_ERROR_GENERIC Error unspecified. + * @return SER_OK On success. + */ +SE_RV se_apdu_request(enum se_apdu_type type, + unsigned char *hdr, size_t hdr_len, + unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len); + +/** + * se_scp03_enable() - Enable the SCP03 protocol using the keys active in the + * Secure Element. + * + * Enables the SCP03 session with the Secure Element. + * + * @return SER_CANT_OPEN_SESSION Error opening the TEE session. + * @return SER_ERROR_GENERIC Error unspecified. + * @return SER_OK On success. + */ +SE_RV se_scp03_enable(void); + +/** + * se_scp03_rotate_keys_and_enable() - Attempt to replace the active SCP03 keys + * and enable the SCP03 session. + * + * Generates secure keys for the board and writes them in the Secure Element non + * volatile memory. Then re-enables the session. + * + * @return SER_CANT_OPEN_SESSION Error opening the TEE session. + * @return SER_ERROR_GENERIC Error unspecified. + * @return SER_OK On success. + */ +SE_RV se_scp03_rotate_keys_and_enable(void); + +#ifdef __cplusplus +} +#endif + +#endif /*SE_TEE_H*/ diff --git a/optee/optee_client/libseteec/src/pta_apdu.h b/optee/optee_client/libseteec/src/pta_apdu.h new file mode 100644 index 0000000..8fed78f --- /dev/null +++ b/optee/optee_client/libseteec/src/pta_apdu.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (C) 2021, Foundries Limited + * Author: Jorge Ramirez + */ + +#ifndef __PTA_APDU_H +#define __PTA_APDU_H + +#define PTA_APDU_UUID { 0x3f3eb880, 0x3639, 0x11ec, \ + { 0x9b, 0x9d, 0x0f, 0x3f, 0xc9, 0x46, 0x8f, 0x50 } } + +/* + * ADPU based communication with the Secure Element + * + * [in] value[0].a Use APDU TXRX hints: PTA_APDU_TXRX_CASE_* + * [in] memref[1].buffer APDU header. + * [in] memref[1].size APDU header length. + * [in] memref[2].buffer request (APDU raw frame). + * [in] memref[2].size request length. + * [out] memref[3].buffer response (APDU raw frame). + * [out] memref[3].size response length. + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_NOT_IMPLEMENTED - Invoke command not implemented + * TEE_ERROR_GENERIC - Invoke command failure + */ +#define PTA_CMD_TXRX_APDU_RAW_FRAME 0 + +/* + * Type identifier for the APDU message as described by Smart Card Standard + * ISO7816-4 about ADPU message bodies decoding convention: + * + * https://cardwerk.com/smart-card-standard-iso7816-4-section-5-basic-organizations/#chap5_3_2 + */ +#define PTA_APDU_TXRX_CASE_NO_HINT 0 +#define PTA_APDU_TXRX_CASE_1 1 +#define PTA_APDU_TXRX_CASE_2 2 +#define PTA_APDU_TXRX_CASE_2E 3 +#define PTA_APDU_TXRX_CASE_3 4 +#define PTA_APDU_TXRX_CASE_3E 5 +#define PTA_APDU_TXRX_CASE_4 6 +#define PTA_APDU_TXRX_CASE_4E 7 + +#endif /* __PTA_APDU_H */ diff --git a/optee/optee_client/libseteec/src/pta_scp03.h b/optee/optee_client/libseteec/src/pta_scp03.h new file mode 100644 index 0000000..393ca56 --- /dev/null +++ b/optee/optee_client/libseteec/src/pta_scp03.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (C) 2020, Foundries Limited + */ + +#ifndef __PTA_SCP03_H +#define __PTA_SCP03_H + +#define PTA_SCP03_UUID { 0xbe0e5821, 0xe718, 0x4f77, \ + { 0xab, 0x3e, 0x8e, 0x6c, 0x73, 0xa9, 0xc7, 0x35 } } + +/* + * Enable SCP03 support on the SE + * + * [in] value[0].a Use session keys PTA_SCP03_SESSION_* + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_NOT_IMPLEMENTED - Invoke command not implemented + * TEE_ERROR_GENERIC - Invoke command failure + */ +#define PTA_CMD_ENABLE_SCP03 0 + +/* Enable the session using the current keys in the Secure Element */ +#define PTA_SCP03_SESSION_CURRENT_KEYS 0 + +/* Enable the session after replacing the current keys in the Secure Element */ +#define PTA_SCP03_SESSION_ROTATE_KEYS 1 + +#endif /* __PTA_SCP03_H */ diff --git a/optee/optee_client/libseteec/src/se.c b/optee/optee_client/libseteec/src/se.c new file mode 100644 index 0000000..4f6be5a --- /dev/null +++ b/optee/optee_client/libseteec/src/se.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Foundries.io Ltd + */ + +#ifndef BINARY_PREFIX +#define BINARY_PREFIX "seteec" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pta_apdu.h" +#include "pta_scp03.h" + +struct ta_context { + pthread_mutex_t lock; + TEEC_Context context; + TEEC_Session session; + TEEC_UUID uuid; + bool open; +}; + +static struct ta_context apdu_ta_ctx = { + .lock = PTHREAD_MUTEX_INITIALIZER, + .uuid = PTA_APDU_UUID, +}; + +static struct ta_context scp03_ta_ctx = { + .lock = PTHREAD_MUTEX_INITIALIZER, + .uuid = PTA_SCP03_UUID, +}; + +static bool open_session(struct ta_context *ctx) +{ + TEEC_Result res = TEEC_SUCCESS; + + if (pthread_mutex_lock(&ctx->lock)) + return false; + + if (!ctx->open) { + res = TEEC_InitializeContext(NULL, &ctx->context); + if (!res) { + res = TEEC_OpenSession(&ctx->context, &ctx->session, + &ctx->uuid, TEEC_LOGIN_PUBLIC, + NULL, NULL, NULL); + if (!res) + ctx->open = true; + } + } + + return !pthread_mutex_unlock(&ctx->lock) && !res; +} + +static SE_RV do_scp03(uint32_t cmd) +{ + TEEC_Operation op = { 0 }; + + if (!open_session(&scp03_ta_ctx)) + return SER_CANT_OPEN_SESSION; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, 0, 0, 0); + op.params[0].value.a = cmd; + + if (TEEC_InvokeCommand(&scp03_ta_ctx.session, + PTA_CMD_ENABLE_SCP03, &op, NULL)) + return SER_ERROR_GENERIC; + + return SER_OK; +} + +SE_RV se_scp03_enable(void) +{ + return do_scp03(PTA_SCP03_SESSION_CURRENT_KEYS); +} + +SE_RV se_scp03_rotate_keys_and_enable(void) +{ + return do_scp03(PTA_SCP03_SESSION_ROTATE_KEYS); +} + +SE_RV se_apdu_request(enum se_apdu_type apdu_type, + unsigned char *hdr, size_t hdr_len, + unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len) +{ + uint32_t type = PTA_APDU_TXRX_CASE_NO_HINT; + TEEC_Operation op = { 0 }; + + switch (apdu_type) { + case SE_APDU_NO_HINT: + type = PTA_APDU_TXRX_CASE_NO_HINT; + break; + case SE_APDU_CASE_1: + type = PTA_APDU_TXRX_CASE_1; + break; + case SE_APDU_CASE_2: + type = PTA_APDU_TXRX_CASE_2; + break; + case SE_APDU_CASE_2E: + type = PTA_APDU_TXRX_CASE_2E; + break; + case SE_APDU_CASE_3: + type = PTA_APDU_TXRX_CASE_3; + break; + case SE_APDU_CASE_3E: + type = PTA_APDU_TXRX_CASE_3E; + break; + case SE_APDU_CASE_4: + type = PTA_APDU_TXRX_CASE_4; + break; + case SE_APDU_CASE_4E: + type = PTA_APDU_TXRX_CASE_4E; + break; + default: + return SER_ERROR_GENERIC; + } + + if (!open_session(&apdu_ta_ctx)) + return SER_CANT_OPEN_SESSION; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT); + op.params[0].value.a = type; + op.params[1].tmpref.buffer = hdr; + op.params[1].tmpref.size = hdr_len; + op.params[2].tmpref.buffer = src; + op.params[2].tmpref.size = src_len; + op.params[3].tmpref.buffer = dst; + op.params[3].tmpref.size = *dst_len; + + if (TEEC_InvokeCommand(&apdu_ta_ctx.session, + PTA_CMD_TXRX_APDU_RAW_FRAME, &op, NULL)) + return SER_ERROR_GENERIC; + + *dst_len = op.params[3].tmpref.size; + + return SER_OK; +} diff --git a/optee/optee_client/libteeacl/CMakeLists.txt b/optee/optee_client/libteeacl/CMakeLists.txt new file mode 100644 index 0000000..ce78058 --- /dev/null +++ b/optee/optee_client/libteeacl/CMakeLists.txt @@ -0,0 +1,53 @@ +project(teeacl + VERSION 0.1.0 + LANGUAGES C +) + +include(GNUInstallDirs) + +################################################################################ +# Source files +################################################################################ +set(SRC + src/group.c + src/tee_uuid.c +) + +################################################################################ +# Built library +################################################################################ +add_library(teeacl ${SRC}) + +set_target_properties(teeacl PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) + +################################################################################ +# Flags always set +################################################################################ +target_compile_definitions(teeacl + PRIVATE -D_GNU_SOURCE + PRIVATE -DBINARY_PREFIX="LT" +) + +################################################################################ +# Public and private header and library dependencies +################################################################################ +target_include_directories(teeacl PUBLIC + $ + $ +) + +target_link_libraries(teeacl + PUBLIC PkgConfig::uuid +) + +################################################################################ +# Install targets +################################################################################ +install(TARGETS teeacl + DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") diff --git a/optee/optee_client/libteeacl/Makefile b/optee/optee_client/libteeacl/Makefile new file mode 100644 index 0000000..fe50c51 --- /dev/null +++ b/optee/optee_client/libteeacl/Makefile @@ -0,0 +1,77 @@ +include ../flags.mk +include ../config.mk + +OUT_DIR := $(OO)/libteeacl + +.PHONY: all libteeacl check-libuuid clean + +all: libteeacl +install: libteeacl + +LIB_NAME := libteeacl +MAJOR_VERSION := 0 +MINOR_VERSION := 1 +PATCH_VERSION := 0 + +LIB_MAJOR := $(LIB_NAME).so.$(MAJOR_VERSION) +LIB_MAJ_MIN := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION) +LIB_MAJ_MIN_PAT := $(LIB_NAME).so.$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) +LIBTEEACL_SO_LIBRARY := $(LIB_MAJ_MIN_PAT) +LIBTEEACL_AR_LIBRARY := $(LIB_NAME).a + +LIBTEEACL_SRC_DIR := src + +LIBTEEACL_SRCS = group.c +LIBTEEACL_SRCS += tee_uuid.c + +LIBTEEACL_INCLUDES = ${CURDIR}/include + +LIBTEEACL_CFLAGS := $(addprefix -I, $(LIBTEEACL_INCLUDES)) \ + $(shell $(PKG_CONFIG) --cflags uuid) \ + $(CFLAGS) -D_GNU_SOURCE -fPIC + +LIBTEEACL_LFLAGS := $(LDFLAGS) $(shell $(PKG_CONFIG) --libs uuid) + +LIBTEEACL_OBJ_DIR := $(OUT_DIR) +LIBTEEACL_OBJS := $(patsubst %.c,$(LIBTEEACL_OBJ_DIR)/%.o, $(LIBTEEACL_SRCS)) + +$(LIBTEEACL_OBJ_DIR)/%.o: ${LIBTEEACL_SRC_DIR}/%.c + $(VPREFIX)mkdir -p $(LIBTEEACL_OBJ_DIR) + @echo " CC $<" + $(VPREFIX)$(CC) $(LIBTEEACL_CFLAGS) -c $< -o $@ + +libteeacl: check-libuuid + +check-libuuid: + @echo " Finding uuid.pc" + $(VPREFIX)$(PKG_CONFIG) --atleast-version=2.34 uuid + +libteeacl: $(OUT_DIR)/$(LIBTEEACL_SO_LIBRARY) + +$(OUT_DIR)/$(LIBTEEACL_SO_LIBRARY): $(LIBTEEACL_OBJS) + @echo " LINK $@" + $(VPREFIX)$(CC) -shared -Wl,-soname,$(LIBTEEACL_SO_LIBRARY) -o $@ $+ $(LIBTEEACL_LFLAGS) + @echo "" + +libteeacl: $(OUT_DIR)/$(LIBTEEACL_AR_LIBRARY) + +$(OUT_DIR)/$(LIBTEEACL_AR_LIBRARY): $(LIBTEEACL_OBJS) + @echo " AR $@" + $(VPREFIX)$(AR) rcs $@ $+ + +libteeacl: + $(VPREFIX)ln -sf $(LIB_MAJ_MIN_PAT) $(OUT_DIR)/$(LIB_MAJ_MIN) + $(VPREFIX)ln -sf $(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_MAJOR) + $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME).so + +################################################################################ +# Cleaning up configuration +################################################################################ +clean: + $(RM) $(LIBTEEACL_OBJS) + $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN_PAT) + $(RM) $(OUT_DIR)/$(LIB_MAJ_MIN) + $(RM) $(OUT_DIR)/$(LIB_MAJOR) + $(RM) $(OUT_DIR)/$(LIBTEEACL_SO_LIBRARY) + $(RM) $(OUT_DIR)/$(LIBTEEACL_AR_LIBRARY) + $(call rmdir,$(OUT_DIR)) diff --git a/optee/optee_client/libteeacl/include/teeacl.h b/optee/optee_client/libteeacl/include/teeacl.h new file mode 100644 index 0000000..1d7a5ee --- /dev/null +++ b/optee/optee_client/libteeacl/include/teeacl.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Vaisala Oyj. + */ + +/* + * Definitions for configuring and using Access Control List (ACL) + * based login methods. + */ + +#ifndef TEEACL_H +#define TEEACL_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// TEE Client UUID name space identifier (UUIDv4) +// same as `tee_client_uuid_ns` in linux kernel drivers/tee/tee_core.c +#define KERNEL_NAMESPACE "58ac9ca0-2086-4683-a1b8-ec4bc08e01b6" + +/* + * len UUID = 36 characters + * + * Prefixes: + * public + * user: + * group: + * + * + '\0' character totals 43, roundup. + */ + +/** + * Required length for UUID char buffers + */ +#define TEEACL_L_UUID 48 + +/** + * teeacl_gid_from_name - Try to resolve gid_t for a given `group_name`. + * + * If a matching group is found, zero is returned and `gid_out` will be set to + * the found value. + * If no group is found, -ENOENT is returned. + * If memory allocation fails, -ENOMEM is returned. + * For other failures, errno is returned. + * + * @param gid_out Ptr to gid result. Will be set to group id if a matching + * group is found. + * @param group_name Name of group to resolve. + * @return 0 if a matching group is found, see detailed description for other + * cases. + */ +int teeacl_gid_from_name(gid_t *gid_out, const char *group_name); + +/** + * teeacl_group_acl_uuid() - Encode a group login ACL string to the + * provided uuid_buf + * + * @param uuid_buf A buffer of length TEEACL_L_UUID. + * @param group Group id to encode for login. + * @return 0 on success, otherwise a negative number is returned in case of failure. + */ +int teeacl_group_acl_uuid(char uuid_buf[TEEACL_L_UUID], gid_t group); +/** + * The possible return values of the *_user_is_member_of functions. + */ +enum rv_groupmember { + NOT_MEMBER, + IS_MEMBER, + E_MEMORY, /**< Failed to allocate memory. */ + E_GROUPLIST /**< Failed to read group listing. */ +}; + +/** + * teeacl_current_user_is_member_of() - Check if the effective user ID of + * the process is a member in `group`. + * + * @param group Group id to check membership of. + * @return enum rv_groupmember form result. + */ +enum rv_groupmember teeacl_current_user_is_member_of(gid_t group); + +/** + * teeacl_user_is_member_of() - Check if `user` is a member in `group`. + * + * @param user Username string. + * @param group Group id to check membership of. + * @return enum rv_groupmember form result. + */ +enum rv_groupmember teeacl_user_is_member_of(const char *user, gid_t group); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* TEEACL_H */ diff --git a/optee/optee_client/libteeacl/src/group.c b/optee/optee_client/libteeacl/src/group.c new file mode 100644 index 0000000..bd165a1 --- /dev/null +++ b/optee/optee_client/libteeacl/src/group.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Vaisala Oyj. + */ + +#include + +#include +#include +#include +#include +#include +#include + +static long teeacl_getgr_r_size_max(void) +{ + long s = sysconf(_SC_GETGR_R_SIZE_MAX); + + if (s == -1) + return 1024; + return s; +}; + +int teeacl_gid_from_name(gid_t *gid_out, const char *group_name) +{ + struct group grp = { 0 }; + char *buffer = NULL; + struct group *result = NULL; + size_t b_size = 0; + int rv = 0; + + b_size = teeacl_getgr_r_size_max(); + buffer = calloc(1, b_size); + if (!buffer) + return -ENOMEM; + + rv = getgrnam_r(group_name, &grp, buffer, b_size, &result); + + free(buffer); + if (!result) { + if (rv == 0) + return -ENOENT; + else + return rv; + } else { + *gid_out = grp.gr_gid; + return 0; + } +} + +enum rv_groupmember teeacl_current_user_is_member_of(gid_t group) +{ + char username[L_cuserid] = { 0 }; + + cuserid(username); + return teeacl_user_is_member_of(username, group); +} + +enum rv_groupmember teeacl_user_is_member_of(const char *user, gid_t group) +{ + enum rv_groupmember result = E_MEMORY; + int ret = 0; + int i = 0; + int grouplistsize = 8; /* initial guess */ + gid_t *p_groups = NULL; + gid_t *groups = calloc(grouplistsize, sizeof(gid_t)); + + if (!groups) + return E_MEMORY; + ret = getgrouplist(user, group, groups, &grouplistsize); + + if (ret == -1) { + p_groups = groups; + + /* we use realloc, since uClibc does not implement reallocarray */ + groups = realloc(groups, grouplistsize * sizeof(gid_t)); + if (!groups) { + free(p_groups); + return E_MEMORY; + } + ret = getgrouplist(user, group, groups, &grouplistsize); + if (ret == -1) { + result = E_GROUPLIST; + goto out; + } + } + + for (i = 0; i < grouplistsize; ++i) { + if (group == groups[i]) { + result = IS_MEMBER; + goto out; + } + } + result = NOT_MEMBER; +out: + free(groups); + return result; +} diff --git a/optee/optee_client/libteeacl/src/tee_uuid.c b/optee/optee_client/libteeacl/src/tee_uuid.c new file mode 100644 index 0000000..8c727e2 --- /dev/null +++ b/optee/optee_client/libteeacl/src/tee_uuid.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Vaisala Oyj. + */ + +#include +#include +#include +#include + +int teeacl_group_acl_uuid(char uuid_buf[TEEACL_L_UUID], gid_t group) +{ + uuid_t g_uuid = { 0 }; + uuid_t k_uuid = { 0 }; + char gid_buf[TEEACL_L_UUID] = { 0 }; + size_t gid_buf_len = 0; + uint gstr_len = 6; + int rv = snprintf(gid_buf, TEEACL_L_UUID, "gid=%x", group); + + if (rv < 0) + return rv; + if (rv >= TEEACL_L_UUID) + return -1; + rv = uuid_parse(KERNEL_NAMESPACE, k_uuid); + if (rv < 0) + return rv; + + gid_buf_len = strnlen(gid_buf, TEEACL_L_UUID); + + uuid_generate_sha1(g_uuid, k_uuid, gid_buf, gid_buf_len); + + memcpy(uuid_buf, "group:", gstr_len); + uuid_unparse(g_uuid, uuid_buf + gstr_len); + return 0; +} diff --git a/optee/optee_client/libteec/CMakeLists.txt b/optee/optee_client/libteec/CMakeLists.txt new file mode 100644 index 0000000..b546e50 --- /dev/null +++ b/optee/optee_client/libteec/CMakeLists.txt @@ -0,0 +1,78 @@ +project(libteec + VERSION 1.0.0 + LANGUAGES C) + +################################################################################ +# Packages +################################################################################ +find_package(Threads REQUIRED) +if(NOT THREADS_FOUND) + message(FATAL_ERROR "Threads not found") +endif() + +################################################################################ +# Configuration flags always included +################################################################################ +option (CFG_TEE_BENCHMARK "Build with benchmark support" OFF) + +set (CFG_TEE_CLIENT_LOG_LEVEL "1" CACHE STRING "libteec log level") +set (CFG_TEE_CLIENT_LOG_FILE "/data/tee/teec.log" CACHE STRING "Location of libteec log") + +################################################################################ +# Source files +################################################################################ +set (SRC + src/tee_client_api.c + src/teec_trace.c +) + +if (CFG_TEE_BENCHMARK) + set (SRC ${SRC} src/teec_benchmark.c) +endif() + +################################################################################ +# Built library +################################################################################ +add_library (teec ${SRC}) + +set(libteectgt teec) +configure_file(libteec.pc.in libteec.pc @ONLY) + +set_target_properties (teec PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) + +################################################################################ +# Flags always set +################################################################################ +target_compile_definitions (teec + PRIVATE -D_GNU_SOURCE + PRIVATE -DDEBUGLEVEL_${CFG_TEE_CLIENT_LOG_LEVEL} + PRIVATE -DTEEC_LOG_FILE="${CFG_TEE_CLIENT_LOG_FILE}" + PRIVATE -DBINARY_PREFIX="LT" +) + +################################################################################ +# Optional flags +################################################################################ +if (CFG_TEE_BENCHMARK) + target_compile_definitions (teec PRIVATE -DCFG_TEE_BENCHMARK) +endif() + +################################################################################ +# Public and private header and library dependencies +################################################################################ +target_include_directories(teec PUBLIC include) + +target_link_libraries (teec + PUBLIC ${CMAKE_THREAD_LIBS_INIT} # this is pthreads + PRIVATE optee-client-headers) + +################################################################################ +# Install targets +################################################################################ +# FIXME: This should in someway harmonize with CFG_TEE_CLIENT_LOAD_PATH +# FIXME: Should we change this to /usr/local/lib? +install (TARGETS teec LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") diff --git a/optee/optee_client/libteec/Makefile b/optee/optee_client/libteec/Makefile new file mode 100644 index 0000000..3b279ab --- /dev/null +++ b/optee/optee_client/libteec/Makefile @@ -0,0 +1,70 @@ +include ../flags.mk +include ../config.mk + +OUT_DIR := $(OO)/libteec + +.PHONY: all libteec clean + +all: libteec +################################################################################ +# Teec configuration +################################################################################ +MAJOR_VERSION := 1 +MINOR_VERSION := 0 +PATCH_VERSION := 0 +LIB_NAME := libteec.so +LIB_MAJOR := $(LIB_NAME).$(MAJOR_VERSION) +LIB_MAJ_MIN := $(LIB_NAME).$(MAJOR_VERSION).$(MINOR_VERSION) +LIB_MAJ_MIN_P := $(LIB_NAME).$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION) + +TEEC_SRCS := tee_client_api.c \ + teec_trace.c +ifeq ($(CFG_TEE_BENCHMARK),y) +TEEC_SRCS += teec_benchmark.c +endif + +TEEC_SRC_DIR := src +TEEC_OBJ_DIR := $(OUT_DIR) +TEEC_OBJS := $(patsubst %.c,$(TEEC_OBJ_DIR)/%.o, $(TEEC_SRCS)) +TEEC_INCLUDES := \ + ${CURDIR}/include \ + ${CURDIR}/../public \ + +TEEC_CFLAGS := $(addprefix -I, $(TEEC_INCLUDES)) $(CFLAGS) -D_GNU_SOURCE \ + -DDEBUGLEVEL_$(CFG_TEE_CLIENT_LOG_LEVEL) \ + -DBINARY_PREFIX=\"TEEC\" + +ifeq ($(CFG_TEE_BENCHMARK),y) +TEEC_CFLAGS += -DCFG_TEE_BENCHMARK +endif + +TEEC_LFLAGS := $(LDFLAGS) -lpthread +TEEC_LIBRARY := $(OUT_DIR)/$(LIB_MAJ_MIN_P) + +libteec: $(TEEC_LIBRARY) $(OUT_DIR)/libteec.a + $(VPREFIX)ln -sf $(LIB_MAJ_MIN_P) $(OUT_DIR)/$(LIB_MAJOR) + $(VPREFIX)ln -sf $(LIB_MAJ_MIN_P) $(OUT_DIR)/$(LIB_MAJ_MIN) + $(VPREFIX)ln -sf $(LIB_MAJOR) $(OUT_DIR)/$(LIB_NAME) + +$(TEEC_LIBRARY): $(TEEC_OBJS) + @echo " LINK $@" + $(VPREFIX)$(CC) -shared -Wl,-soname,$(LIB_MAJOR) -o $@ $+ $(TEEC_LFLAGS) + @echo "" + +$(OUT_DIR)/libteec.a: $(TEEC_OBJS) + @echo " AR $@" + $(VPREFIX)$(AR) rcs $@ $+ + +$(TEEC_OBJ_DIR)/%.o: ${TEEC_SRC_DIR}/%.c + $(VPREFIX)mkdir -p $(TEEC_OBJ_DIR) + @echo " CC $<" + $(VPREFIX)$(CC) $(TEEC_CFLAGS) -c $< -o $@ + +################################################################################ +# Cleaning up configuration +################################################################################ +clean: + $(RM) $(TEEC_OBJS) $(TEEC_LIBRARY) $(OUT_DIR)/$(LIB_MAJOR) \ + $(OUT_DIR)/$(LIB_MAJ_MIN) $(OUT_DIR)/$(LIB_NAME) + $(RM) $(OUT_DIR)/libteec.a + $(call rmdir,$(OUT_DIR)) diff --git a/optee/optee_client/libteec/include/linux/tee.h b/optee/optee_client/libteec/include/linux/tee.h new file mode 100644 index 0000000..f883ebc --- /dev/null +++ b/optee/optee_client/libteec/include/linux/tee.h @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2015-2016, 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 __TEE_H +#define __TEE_H + +#include +#include + +/* + * This file describes the API provided by a TEE driver to user space. + * + * Each TEE driver defines a TEE specific protocol which is used for the + * data passed back and forth using TEE_IOC_CMD. + */ + +/* Helpers to make the ioctl defines */ +#define TEE_IOC_MAGIC 0xa4 +#define TEE_IOC_BASE 0 + +/* Flags relating to shared memory */ +#define TEE_IOCTL_SHM_MAPPED 0x1 /* memory mapped in normal world */ +#define TEE_IOCTL_SHM_DMA_BUF 0x2 /* dma-buf handle on shared memory */ + +#define TEE_MAX_ARG_SIZE 1024 + +#define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */ +#define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ +#define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */ +#define TEE_GEN_CAP_MEMREF_NULL (1 << 3) /* Support NULL MemRef */ + +#define TEE_MEMREF_NULL ((__u64)-1) /* NULL MemRef Buffer */ + +/* + * TEE Implementation ID + */ +#define TEE_IMPL_ID_OPTEE 1 +#define TEE_IMPL_ID_AMDTEE 2 + +/* + * OP-TEE specific capabilities + */ +#define TEE_OPTEE_CAP_TZ (1 << 0) + +/** + * struct tee_ioctl_version_data - TEE version + * @impl_id: [out] TEE implementation id + * @impl_caps: [out] Implementation specific capabilities + * @gen_caps: [out] Generic capabilities, defined by TEE_GEN_CAPS_* above + * + * Identifies the TEE implementation, @impl_id is one of TEE_IMPL_ID_* above. + * @impl_caps is implementation specific, for example TEE_OPTEE_CAP_* + * is valid when @impl_id == TEE_IMPL_ID_OPTEE. + */ +struct tee_ioctl_version_data { + __u32 impl_id; + __u32 impl_caps; + __u32 gen_caps; +}; + +/** + * TEE_IOC_VERSION - query version of TEE + * + * Takes a tee_ioctl_version_data struct and returns with the TEE version + * data filled in. + */ +#define TEE_IOC_VERSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 0, \ + struct tee_ioctl_version_data) + +/** + * struct tee_ioctl_shm_alloc_data - Shared memory allocate argument + * @size: [in/out] Size of shared memory to allocate + * @flags: [in/out] Flags to/from allocation. + * @id: [out] Identifier of the shared memory + * + * The flags field should currently be zero as input. Updated by the call + * with actual flags as defined by TEE_IOCTL_SHM_* above. + * This structure is used as argument for TEE_IOC_SHM_ALLOC below. + */ +struct tee_ioctl_shm_alloc_data { + __u64 size; + __u32 flags; + __s32 id; +}; + +/** + * TEE_IOC_SHM_ALLOC - allocate shared memory + * + * Allocates shared memory between the user space process and secure OS. + * + * Returns a file descriptor on success or < 0 on failure + * + * The returned file descriptor is used to map the shared memory into user + * space. The shared memory is freed when the descriptor is closed and the + * memory is unmapped. + */ +#define TEE_IOC_SHM_ALLOC _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \ + struct tee_ioctl_shm_alloc_data) + +/** + * struct tee_ioctl_shm_register_fd_data - Shared memory registering argument + * @fd: [in] file descriptor identifying the shared memory + * @size: [out] Size of shared memory to allocate + * @flags: [in] Flags to/from allocation. + * @id: [out] Identifier of the shared memory + * + * The flags field should currently be zero as input. Updated by the call + * with actual flags as defined by TEE_IOCTL_SHM_* above. + * This structure is used as argument for TEE_IOC_SHM_ALLOC below. + */ +struct tee_ioctl_shm_register_fd_data { + __s64 fd; + __u64 size; + __u32 flags; + __s32 id; +} __aligned(8); + +/* + * Attributes for struct tee_ioctl_param, selects field in the union + */ +#define TEE_IOCTL_PARAM_ATTR_TYPE_NONE 0 /* parameter not used */ + +/* + * These defines value parameters (struct tee_ioctl_param_value) + */ +#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT 1 +#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT 2 +#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT 3 /* input and output */ + +/* + * These defines shared memory reference parameters (struct + * tee_ioctl_param_memref) + */ +#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT 5 +#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT 6 +#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT 7 /* input and output */ + +/* + * Mask for the type part of the attribute, leaves room for more types + */ +#define TEE_IOCTL_PARAM_ATTR_TYPE_MASK 0xff + +/* Meta parameter carrying extra information about the message. */ +#define TEE_IOCTL_PARAM_ATTR_META 0x100 + +/* Mask of all known attr bits */ +#define TEE_IOCTL_PARAM_ATTR_MASK \ + (TEE_IOCTL_PARAM_ATTR_TYPE_MASK | TEE_IOCTL_PARAM_ATTR_META) + +/* + * Matches TEEC_LOGIN_* in GP TEE Client API + * Are only defined for GP compliant TEEs + */ +#define TEE_IOCTL_LOGIN_PUBLIC 0 +#define TEE_IOCTL_LOGIN_USER 1 +#define TEE_IOCTL_LOGIN_GROUP 2 +#define TEE_IOCTL_LOGIN_APPLICATION 4 +#define TEE_IOCTL_LOGIN_USER_APPLICATION 5 +#define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6 + +/** + * struct tee_ioctl_param - parameter + * @attr: attributes + * @a: if a memref, offset into the shared memory object, else a value parameter + * @b: if a memref, size of the buffer, else a value parameter + * @c: if a memref, shared memory identifier, else a value parameter + * + * @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref or value is used in + * the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value and + * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref. TEE_PARAM_ATTR_TYPE_NONE + * indicates that none of the members are used. + * + * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an + * identifier representing the shared memory object. A memref can reference + * a part of a shared memory by specifying an offset (@a) and size (@b) of + * the object. To supply the entire shared memory object set the offset + * (@a) to 0 and size (@b) to the previously returned size of the object. + */ +struct tee_ioctl_param { + __u64 attr; + __u64 a; + __u64 b; + __u64 c; +}; + +#define TEE_IOCTL_UUID_LEN 16 + +/** + * struct tee_ioctl_open_session_arg - Open session argument + * @uuid: [in] UUID of the Trusted Application + * @clnt_uuid: [in] UUID of client + * @clnt_login: [in] Login class of client, TEE_IOCTL_LOGIN_* above + * @cancel_id: [in] Cancellation id, a unique value to identify this request + * @session: [out] Session id + * @ret: [out] return value + * @ret_origin [out] origin of the return value + * @num_params [in] number of parameters following this struct + */ +struct tee_ioctl_open_session_arg { + __u8 uuid[TEE_IOCTL_UUID_LEN]; + __u8 clnt_uuid[TEE_IOCTL_UUID_LEN]; + __u32 clnt_login; + __u32 cancel_id; + __u32 session; + __u32 ret; + __u32 ret_origin; + __u32 num_params; + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + +/** + * TEE_IOC_OPEN_SESSION - opens a session to a Trusted Application + * + * Takes a struct tee_ioctl_buf_data which contains a struct + * tee_ioctl_open_session_arg followed by any array of struct + * tee_ioctl_param + */ +#define TEE_IOC_OPEN_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 2, \ + struct tee_ioctl_buf_data) + +/** + * struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted + * Application + * @func: [in] Trusted Application function, specific to the TA + * @session: [in] Session id + * @cancel_id: [in] Cancellation id, a unique value to identify this request + * @ret: [out] return value + * @ret_origin [out] origin of the return value + * @num_params [in] number of parameters following this struct + */ +struct tee_ioctl_invoke_arg { + __u32 func; + __u32 session; + __u32 cancel_id; + __u32 ret; + __u32 ret_origin; + __u32 num_params; + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + +/** + * TEE_IOC_INVOKE - Invokes a function in a Trusted Application + * + * Takes a struct tee_ioctl_buf_data which contains a struct + * tee_invoke_func_arg followed by any array of struct tee_param + */ +#define TEE_IOC_INVOKE _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 3, \ + struct tee_ioctl_buf_data) + +/** + * struct tee_ioctl_cancel_arg - Cancels an open session or invoke ioctl + * @cancel_id: [in] Cancellation id, a unique value to identify this request + * @session: [in] Session id, if the session is opened, else set to 0 + */ +struct tee_ioctl_cancel_arg { + __u32 cancel_id; + __u32 session; +}; + +/** + * TEE_IOC_CANCEL - Cancels an open session or invoke + */ +#define TEE_IOC_CANCEL _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 4, \ + struct tee_ioctl_cancel_arg) + +/** + * struct tee_ioctl_close_session_arg - Closes an open session + * @session: [in] Session id + */ +struct tee_ioctl_close_session_arg { + __u32 session; +}; + +/** + * TEE_IOC_CLOSE_SESSION - Closes a session + */ +#define TEE_IOC_CLOSE_SESSION _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 5, \ + struct tee_ioctl_close_session_arg) + +/** + * struct tee_iocl_supp_recv_arg - Receive a request for a supplicant function + * @func: [in] supplicant function + * @num_params [in/out] number of parameters following this struct + * + * @num_params is the number of params that tee-supplicant has room to + * receive when input, @num_params is the number of actual params + * tee-supplicant receives when output. + */ +struct tee_iocl_supp_recv_arg { + __u32 func; + __u32 num_params; + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + +/** + * TEE_IOC_SUPPL_RECV - Receive a request for a supplicant function + * + * Takes a struct tee_ioctl_buf_data which contains a struct + * tee_iocl_supp_recv_arg followed by any array of struct tee_param + */ +#define TEE_IOC_SUPPL_RECV _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 6, \ + struct tee_ioctl_buf_data) + +/** + * struct tee_iocl_supp_send_arg - Send a response to a received request + * @ret: [out] return value + * @num_params [in] number of parameters following this struct + */ +struct tee_iocl_supp_send_arg { + __u32 ret; + __u32 num_params; + /* num_params tells the actual number of element in params */ + struct tee_ioctl_param params[]; +}; + +/** + * TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function + * + * Takes a struct tee_ioctl_buf_data which contains a struct + * tee_iocl_supp_send_arg followed by any array of struct tee_param + */ +#define TEE_IOC_SUPPL_SEND _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \ + struct tee_ioctl_buf_data) + +/** + * struct tee_ioctl_shm_register_data - Shared memory register argument + * @addr: [in] Start address of shared memory to register + * @length: [in/out] Length of shared memory to register + * @flags: [in/out] Flags to/from registration. + * @id: [out] Identifier of the shared memory + * + * The flags field should currently be zero as input. Updated by the call + * with actual flags as defined by TEE_IOCTL_SHM_* above. + * This structure is used as argument for TEE_IOC_SHM_REGISTER below. + */ +struct tee_ioctl_shm_register_data { + __u64 addr; + __u64 length; + __u32 flags; + __s32 id; +}; + +/** + * TEE_IOC_SHM_REGISTER_FD - register a shared memory from a file descriptor + * + * Returns a file descriptor on success or < 0 on failure + * + * The returned file descriptor refers to the shared memory object in kernel + * land. The shared memory is freed when the descriptor is closed. + */ +#define TEE_IOC_SHM_REGISTER_FD _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 8, \ + struct tee_ioctl_shm_register_fd_data) + +/** + * struct tee_ioctl_buf_data - Variable sized buffer + * @buf_ptr: [in] A __user pointer to a buffer + * @buf_len: [in] Length of the buffer above + * + * Used as argument for TEE_IOC_OPEN_SESSION, TEE_IOC_INVOKE, + * TEE_IOC_SUPPL_RECV, and TEE_IOC_SUPPL_SEND below. + */ +struct tee_ioctl_buf_data { + __u64 buf_ptr; + __u64 buf_len; +}; + +/** + * TEE_IOC_SHM_REGISTER - Register shared memory argument + * + * Registers shared memory between the user space process and secure OS. + * + * Returns a file descriptor on success or < 0 on failure + * + * The shared memory is unregisterred when the descriptor is closed. + */ +#define TEE_IOC_SHM_REGISTER _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 9, \ + struct tee_ioctl_shm_register_data) +/* + * Five syscalls are used when communicating with the TEE driver. + * open(): opens the device associated with the driver + * ioctl(): as described above operating on the file descriptor from open() + * close(): two cases + * - closes the device file descriptor + * - closes a file descriptor connected to allocated shared memory + * mmap(): maps shared memory into user space using information from struct + * tee_ioctl_shm_alloc_data + * munmap(): unmaps previously shared memory + */ + +#endif /*__TEE_H*/ diff --git a/optee/optee_client/libteec/include/teec_benchmark.h b/optee/optee_client/libteec/include/teec_benchmark.h new file mode 100644 index 0000000..17d99ac --- /dev/null +++ b/optee/optee_client/libteec/include/teec_benchmark.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017, 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 __TEEC_BENCHMARK_H +#define __TEEC_BENCHMARK_H + +#ifdef CFG_TEE_BENCHMARK +void bm_timestamp(void); +#else +static inline void bm_timestamp(void) {} +#endif + +#endif /* __TEEC_BENCHMARK_H */ diff --git a/optee/optee_client/libteec/libteec.pc.in b/optee/optee_client/libteec/libteec.pc.in new file mode 100644 index 0000000..f6fc530 --- /dev/null +++ b/optee/optee_client/libteec/libteec.pc.in @@ -0,0 +1,21 @@ +# this template is filled-in by CMake `configure_file(... @ONLY)` +# the `@....@` are filled in by CMake configure_file(), +# from variables set in your CMakeLists.txt or by CMake itself +# +# Good tutoral for understanding .pc files: +# https://people.freedesktop.org/~dbn/pkg-config-guide.html + +prefix="@CMAKE_INSTALL_PREFIX@" +exec_prefix="${prefix}" +libdir="${prefix}/lib" +includedir="${prefix}/include" + +Name: @PROJECT_NAME@ +Description: @CMAKE_PROJECT_DESCRIPTION@ +URL: @CMAKE_PROJECT_HOMEPAGE_URL@ +Version: @PROJECT_VERSION@ +Requires: @pc_req_public@ +Requires.private: @pc_req_private@ +Cflags: -I"${includedir}" +Libs: -L"${libdir}" -l@libteectgt@ +Libs.private: -L"${libdir}" -l@libteectgt@ @pc_libs_private@ diff --git a/optee/optee_client/libteec/src/tee_client_api.c b/optee/optee_client/libteec/src/tee_client_api.c new file mode 100644 index 0000000..d8cc4b5 --- /dev/null +++ b/optee/optee_client/libteec/src/tee_client_api.c @@ -0,0 +1,958 @@ +/* + * Copyright (c) 2015-2016, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif +#include + +#include "teec_benchmark.h" + +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) + +/* How many device sequence numbers will be tried before giving up */ +#define TEEC_MAX_DEV_SEQ 10 + +/* Helpers to access memref parts of a struct tee_ioctl_param */ +#define MEMREF_SHM_ID(p) ((p)->c) +#define MEMREF_SHM_OFFS(p) ((p)->a) +#define MEMREF_SIZE(p) ((p)->b) + +/* + * Internal flags of TEEC_SharedMemory::internal.flags + */ +#define SHM_FLAG_BUFFER_ALLOCED (1u << 0) +#define SHM_FLAG_SHADOW_BUFFER_ALLOCED (1u << 1) + +static pthread_mutex_t teec_mutex = PTHREAD_MUTEX_INITIALIZER; + +static void teec_mutex_lock(pthread_mutex_t *mu) +{ + pthread_mutex_lock(mu); +} + +static void teec_mutex_unlock(pthread_mutex_t *mu) +{ + pthread_mutex_unlock(mu); +} + +static void *teec_paged_aligned_alloc(size_t sz) +{ + void *p = NULL; + + if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz)) + return p; + + return NULL; +} + +static int teec_open_dev(const char *devname, const char *capabilities, + uint32_t *gen_caps) +{ + int fd = 0; + struct tee_ioctl_version_data vers; + + memset(&vers, 0, sizeof(vers)); + + fd = open(devname, O_RDWR); + if (fd < 0) + return -1; + + if (ioctl(fd, TEE_IOC_VERSION, &vers)) { + EMSG("TEE_IOC_VERSION failed"); + goto err; + } + + /* We can only handle GP TEEs */ + if (!(vers.gen_caps & TEE_GEN_CAP_GP)) + goto err; + + if (capabilities) { + if (strcmp(capabilities, "optee-tz") == 0) { + if (vers.impl_id != TEE_IMPL_ID_OPTEE) + goto err; + if (!(vers.impl_caps & TEE_OPTEE_CAP_TZ)) + goto err; + } else { + /* Unrecognized capability requested */ + goto err; + } + } + + *gen_caps = vers.gen_caps; + return fd; +err: + close(fd); + return -1; +} + +static int teec_shm_alloc(int fd, size_t size, int *id) +{ + int shm_fd = 0; + struct tee_ioctl_shm_alloc_data data; + + memset(&data, 0, sizeof(data)); + + data.size = size; + shm_fd = ioctl(fd, TEE_IOC_SHM_ALLOC, &data); + if (shm_fd < 0) + return -1; + *id = data.id; + return shm_fd; +} + +static int teec_shm_register(int fd, void *buf, size_t size, int *id) +{ + int shm_fd = 0; + struct tee_ioctl_shm_register_data data; + + memset(&data, 0, sizeof(data)); + + data.addr = (uintptr_t)buf; + data.length = size; + shm_fd = ioctl(fd, TEE_IOC_SHM_REGISTER, &data); + if (shm_fd < 0) + return -1; + *id = data.id; + return shm_fd; +} + +TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *ctx) +{ + char devname[PATH_MAX] = { 0 }; + int fd = 0; + size_t n = 0; + + if (!ctx) + return TEEC_ERROR_BAD_PARAMETERS; + + for (n = 0; n < TEEC_MAX_DEV_SEQ; n++) { + uint32_t gen_caps = 0; + + snprintf(devname, sizeof(devname), "/dev/tee%zu", n); + fd = teec_open_dev(devname, name, &gen_caps); + if (fd >= 0) { + ctx->fd = fd; + ctx->reg_mem = gen_caps & TEE_GEN_CAP_REG_MEM; + ctx->memref_null = gen_caps & TEE_GEN_CAP_MEMREF_NULL; + return TEEC_SUCCESS; + } + } + + return TEEC_ERROR_ITEM_NOT_FOUND; +} + +void TEEC_FinalizeContext(TEEC_Context *ctx) +{ + if (ctx) + close(ctx->fd); +} + + +static TEEC_Result teec_pre_process_tmpref(TEEC_Context *ctx, + uint32_t param_type, TEEC_TempMemoryReference *tmpref, + struct tee_ioctl_param *param, + TEEC_SharedMemory *shm) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + + switch (param_type) { + case TEEC_MEMREF_TEMP_INPUT: + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + shm->flags = TEEC_MEM_INPUT; + break; + case TEEC_MEMREF_TEMP_OUTPUT: + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; + shm->flags = TEEC_MEM_OUTPUT; + break; + case TEEC_MEMREF_TEMP_INOUT: + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; + shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + break; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + shm->size = tmpref->size; + + if (!tmpref->buffer) { + if (tmpref->size) + return TEEC_ERROR_BAD_PARAMETERS; + + if (ctx->memref_null) { + /* Null pointer, indicate no shared memory attached */ + MEMREF_SHM_ID(param) = TEE_MEMREF_NULL; + shm->id = -1; + } else { + res = TEEC_AllocateSharedMemory(ctx, shm); + if (res != TEEC_SUCCESS) + return res; + MEMREF_SHM_ID(param) = shm->id; + } + } else { + shm->buffer = tmpref->buffer; + res = TEEC_RegisterSharedMemory(ctx, shm); + if (res != TEEC_SUCCESS) + return res; + + if (shm->shadow_buffer) + memcpy(shm->shadow_buffer, tmpref->buffer, + tmpref->size); + + MEMREF_SHM_ID(param) = shm->id; + } + + MEMREF_SIZE(param) = tmpref->size; + + return TEEC_SUCCESS; +} + +static TEEC_Result teec_pre_process_whole( + TEEC_RegisteredMemoryReference *memref, + struct tee_ioctl_param *param) +{ + const uint32_t inout = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + uint32_t flags = memref->parent->flags & inout; + TEEC_SharedMemory *shm = NULL; + + if (flags == inout) + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; + else if (flags & TEEC_MEM_INPUT) + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + else if (flags & TEEC_MEM_OUTPUT) + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; + else + return TEEC_ERROR_BAD_PARAMETERS; + + shm = memref->parent; + /* + * We're using a shadow buffer in this reference, copy the real buffer + * into the shadow buffer if needed. We'll copy it back once we've + * returned from the call to secure world. + */ + if (shm->shadow_buffer && (flags & TEEC_MEM_INPUT)) + memcpy(shm->shadow_buffer, shm->buffer, shm->size); + + MEMREF_SHM_ID(param) = shm->id; + MEMREF_SIZE(param) = shm->size; + + return TEEC_SUCCESS; +} + +static TEEC_Result teec_pre_process_partial(uint32_t param_type, + TEEC_RegisteredMemoryReference *memref, + struct tee_ioctl_param *param) +{ + uint32_t req_shm_flags = 0; + TEEC_SharedMemory *shm = NULL; + + switch (param_type) { + case TEEC_MEMREF_PARTIAL_INPUT: + req_shm_flags = TEEC_MEM_INPUT; + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + break; + case TEEC_MEMREF_PARTIAL_OUTPUT: + req_shm_flags = TEEC_MEM_OUTPUT; + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; + break; + case TEEC_MEMREF_PARTIAL_INOUT: + req_shm_flags = TEEC_MEM_OUTPUT | TEEC_MEM_INPUT; + param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT; + break; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + + shm = memref->parent; + + if ((shm->flags & req_shm_flags) != req_shm_flags) + return TEEC_ERROR_BAD_PARAMETERS; + + if ((memref->offset + memref->size < memref->offset) || + (memref->offset + memref->size > shm->size)) + return TEEC_ERROR_BAD_PARAMETERS; + + /* + * We're using a shadow buffer in this reference, copy the real buffer + * into the shadow buffer if needed. We'll copy it back once we've + * returned from the call to secure world. + */ + if (shm->shadow_buffer && param_type != TEEC_MEMREF_PARTIAL_OUTPUT) + memcpy((char *)shm->shadow_buffer + memref->offset, + (char *)shm->buffer + memref->offset, memref->size); + + MEMREF_SHM_ID(param) = shm->id; + MEMREF_SHM_OFFS(param) = memref->offset; + MEMREF_SIZE(param) = memref->size; + + return TEEC_SUCCESS; +} + +static TEEC_Result teec_pre_process_operation(TEEC_Context *ctx, + TEEC_Operation *operation, + struct tee_ioctl_param *params, + TEEC_SharedMemory *shms) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + size_t n = 0; + + memset(shms, 0, sizeof(TEEC_SharedMemory) * + TEEC_CONFIG_PAYLOAD_REF_COUNT); + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) + shms[n].id = -1; + + if (!operation) { + memset(params, 0, sizeof(struct tee_ioctl_param) * + TEEC_CONFIG_PAYLOAD_REF_COUNT); + return TEEC_SUCCESS; + } + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + uint32_t param_type = 0; + + param_type = TEEC_PARAM_TYPE_GET(operation->paramTypes, n); + switch (param_type) { + case TEEC_NONE: + params[n].attr = param_type; + break; + case TEEC_VALUE_INPUT: + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + params[n].attr = param_type; + params[n].a = operation->params[n].value.a; + params[n].b = operation->params[n].value.b; + break; + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + res = teec_pre_process_tmpref(ctx, param_type, + &operation->params[n].tmpref, params + n, + shms + n); + if (res != TEEC_SUCCESS) + return res; + break; + case TEEC_MEMREF_WHOLE: + res = teec_pre_process_whole( + &operation->params[n].memref, + params + n); + if (res != TEEC_SUCCESS) + return res; + break; + case TEEC_MEMREF_PARTIAL_INPUT: + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + res = teec_pre_process_partial(param_type, + &operation->params[n].memref, params + n); + if (res != TEEC_SUCCESS) + return res; + break; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + } + + return TEEC_SUCCESS; +} + +static void teec_post_process_tmpref(uint32_t param_type, + TEEC_TempMemoryReference *tmpref, + struct tee_ioctl_param *param, + TEEC_SharedMemory *shm) +{ + if (param_type != TEEC_MEMREF_TEMP_INPUT) { + if (tmpref->buffer && shm->shadow_buffer) + memcpy(tmpref->buffer, shm->shadow_buffer, + MIN(MEMREF_SIZE(param), tmpref->size)); + + tmpref->size = MEMREF_SIZE(param); + } +} + +static void teec_post_process_whole(TEEC_RegisteredMemoryReference *memref, + struct tee_ioctl_param *param) +{ + TEEC_SharedMemory *shm = memref->parent; + + if (shm->flags & TEEC_MEM_OUTPUT) { + + /* + * We're using a shadow buffer in this reference, copy back + * the shadow buffer into the real buffer now that we've + * returned from secure world. + */ + if (shm->shadow_buffer && MEMREF_SIZE(param) <= shm->size) + memcpy(shm->buffer, shm->shadow_buffer, + MEMREF_SIZE(param)); + + memref->size = MEMREF_SIZE(param); + } +} + +static void teec_post_process_partial(uint32_t param_type, + TEEC_RegisteredMemoryReference *memref, + struct tee_ioctl_param *param) +{ + if (param_type != TEEC_MEMREF_PARTIAL_INPUT) { + TEEC_SharedMemory *shm = memref->parent; + + /* + * We're using a shadow buffer in this reference, copy back + * the shadow buffer into the real buffer now that we've + * returned from secure world. + */ + if (shm->shadow_buffer && MEMREF_SIZE(param) <= memref->size) + memcpy((char *)shm->buffer + memref->offset, + (char *)shm->shadow_buffer + memref->offset, + MEMREF_SIZE(param)); + + memref->size = MEMREF_SIZE(param); + } +} + +static void teec_post_process_operation(TEEC_Operation *operation, + struct tee_ioctl_param *params, + TEEC_SharedMemory *shms) +{ + size_t n = 0; + + if (!operation) + return; + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + uint32_t param_type = 0; + + param_type = TEEC_PARAM_TYPE_GET(operation->paramTypes, n); + switch (param_type) { + case TEEC_VALUE_INPUT: + break; + case TEEC_VALUE_OUTPUT: + case TEEC_VALUE_INOUT: + operation->params[n].value.a = params[n].a; + operation->params[n].value.b = params[n].b; + break; + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + teec_post_process_tmpref(param_type, + &operation->params[n].tmpref, params + n, + shms + n); + break; + case TEEC_MEMREF_WHOLE: + teec_post_process_whole(&operation->params[n].memref, + params + n); + break; + case TEEC_MEMREF_PARTIAL_INPUT: + case TEEC_MEMREF_PARTIAL_OUTPUT: + case TEEC_MEMREF_PARTIAL_INOUT: + teec_post_process_partial(param_type, + &operation->params[n].memref, params + n); + default: + break; + } + } +} + +static void teec_free_temp_refs(TEEC_Operation *operation, + TEEC_SharedMemory *shms) +{ + size_t n = 0; + + if (!operation) + return; + + for (n = 0; n < TEEC_CONFIG_PAYLOAD_REF_COUNT; n++) { + switch (TEEC_PARAM_TYPE_GET(operation->paramTypes, n)) { + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_TEMP_INOUT: + TEEC_ReleaseSharedMemory(shms + n); + break; + default: + break; + } + } +} + +static TEEC_Result ioctl_errno_to_res(int err) +{ + switch (err) { + case ENOMEM: + return TEEC_ERROR_OUT_OF_MEMORY; + case EINVAL: + return TEEC_ERROR_BAD_PARAMETERS; + default: + return TEEC_ERROR_GENERIC; + } +} + +static void uuid_to_octets(uint8_t d[TEE_IOCTL_UUID_LEN], const TEEC_UUID *s) +{ + d[0] = s->timeLow >> 24; + d[1] = s->timeLow >> 16; + d[2] = s->timeLow >> 8; + d[3] = s->timeLow; + d[4] = s->timeMid >> 8; + d[5] = s->timeMid; + d[6] = s->timeHiAndVersion >> 8; + d[7] = s->timeHiAndVersion; + memcpy(d + 8, s->clockSeqAndNode, sizeof(s->clockSeqAndNode)); +} + +static void setup_client_data(struct tee_ioctl_open_session_arg *arg, + uint32_t connection_method, + const void *connection_data) +{ + arg->clnt_login = connection_method; + + switch (connection_method) { + case TEE_IOCTL_LOGIN_PUBLIC: + /* No connection data to pass */ + break; + case TEE_IOCTL_LOGIN_USER: + /* Kernel auto-fills UID and forms client UUID */ + break; + case TEE_IOCTL_LOGIN_GROUP: + /* + * Connection data for group login is uint32_t and rest of + * clnt_uuid is set as zero. + * + * Kernel verifies group membership and then forms client UUID. + */ + memcpy(arg->clnt_uuid, connection_data, sizeof(gid_t)); + break; + case TEE_IOCTL_LOGIN_APPLICATION: + /* + * Kernel auto-fills application identifier and forms client + * UUID. + */ + break; + case TEE_IOCTL_LOGIN_USER_APPLICATION: + /* + * Kernel auto-fills application identifier, UID and forms + * client UUID. + */ + break; + case TEE_IOCTL_LOGIN_GROUP_APPLICATION: + /* + * Connection data for group login is uint32_t rest of + * clnt_uuid is set as zero. + * + * Kernel verifies group membership, auto-fills application + * identifier and then forms client UUID. + */ + memcpy(arg->clnt_uuid, connection_data, sizeof(gid_t)); + break; + default: + /* + * Unknown login method, don't pass any connection data as we + * don't know size. + */ + break; + } +} + +TEEC_Result TEEC_OpenSession(TEEC_Context *ctx, TEEC_Session *session, + const TEEC_UUID *destination, + uint32_t connection_method, const void *connection_data, + TEEC_Operation *operation, uint32_t *ret_origin) +{ + struct tee_ioctl_open_session_arg *arg = NULL; + struct tee_ioctl_param *params = NULL; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t eorig = 0; + int rc = 0; + const size_t arg_size = sizeof(struct tee_ioctl_open_session_arg) + + TEEC_CONFIG_PAYLOAD_REF_COUNT * + sizeof(struct tee_ioctl_param); + union { + struct tee_ioctl_open_session_arg arg; + uint8_t data[arg_size]; + } buf; + struct tee_ioctl_buf_data buf_data; + TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; + + memset(&buf, 0, sizeof(buf)); + memset(&shm, 0, sizeof(shm)); + memset(&buf_data, 0, sizeof(buf_data)); + + if (!ctx || !session) { + eorig = TEEC_ORIGIN_API; + res = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + + buf_data.buf_ptr = (uintptr_t)&buf; + buf_data.buf_len = sizeof(buf); + + arg = &buf.arg; + arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; + params = (struct tee_ioctl_param *)(arg + 1); + + uuid_to_octets(arg->uuid, destination); + + setup_client_data(arg, connection_method, connection_data); + + res = teec_pre_process_operation(ctx, operation, params, shm); + if (res != TEEC_SUCCESS) { + eorig = TEEC_ORIGIN_API; + goto out_free_temp_refs; + } + + rc = ioctl(ctx->fd, TEE_IOC_OPEN_SESSION, &buf_data); + if (rc) { + EMSG("TEE_IOC_OPEN_SESSION failed"); + eorig = TEEC_ORIGIN_COMMS; + res = ioctl_errno_to_res(errno); + goto out_free_temp_refs; + } + res = arg->ret; + eorig = arg->ret_origin; + if (res == TEEC_SUCCESS) { + session->ctx = ctx; + session->session_id = arg->session; + } + teec_post_process_operation(operation, params, shm); + +out_free_temp_refs: + teec_free_temp_refs(operation, shm); +out: + if (ret_origin) + *ret_origin = eorig; + return res; +} + +void TEEC_CloseSession(TEEC_Session *session) +{ + struct tee_ioctl_close_session_arg arg; + + memset(&arg, 0, sizeof(arg)); + + if (!session) + return; + + arg.session = session->session_id; + if (ioctl(session->ctx->fd, TEE_IOC_CLOSE_SESSION, &arg)) + EMSG("Failed to close session 0x%x", session->session_id); +} + +TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t cmd_id, + TEEC_Operation *operation, uint32_t *error_origin) +{ + struct tee_ioctl_invoke_arg *arg = NULL; + struct tee_ioctl_param *params = NULL; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t eorig = 0; + int rc = 0; + const size_t arg_size = sizeof(struct tee_ioctl_invoke_arg) + + TEEC_CONFIG_PAYLOAD_REF_COUNT * + sizeof(struct tee_ioctl_param); + union { + struct tee_ioctl_invoke_arg arg; + uint8_t data[arg_size]; + } buf; + struct tee_ioctl_buf_data buf_data; + TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; + + memset(&buf, 0, sizeof(buf)); + memset(&buf_data, 0, sizeof(buf_data)); + memset(&shm, 0, sizeof(shm)); + + if (!session) { + eorig = TEEC_ORIGIN_API; + res = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + + bm_timestamp(); + + buf_data.buf_ptr = (uintptr_t)&buf; + buf_data.buf_len = sizeof(buf); + + arg = &buf.arg; + arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; + params = (struct tee_ioctl_param *)(arg + 1); + + arg->session = session->session_id; + arg->func = cmd_id; + + if (operation) { + teec_mutex_lock(&teec_mutex); + operation->session = session; + teec_mutex_unlock(&teec_mutex); + } + + res = teec_pre_process_operation(session->ctx, operation, params, shm); + if (res != TEEC_SUCCESS) { + eorig = TEEC_ORIGIN_API; + goto out_free_temp_refs; + } + + rc = ioctl(session->ctx->fd, TEE_IOC_INVOKE, &buf_data); + if (rc) { + EMSG("TEE_IOC_INVOKE failed"); + eorig = TEEC_ORIGIN_COMMS; + res = ioctl_errno_to_res(errno); + goto out_free_temp_refs; + } + + res = arg->ret; + eorig = arg->ret_origin; + teec_post_process_operation(operation, params, shm); + + bm_timestamp(); + +out_free_temp_refs: + teec_free_temp_refs(operation, shm); +out: + if (error_origin) + *error_origin = eorig; + return res; +} + +void TEEC_RequestCancellation(TEEC_Operation *operation) +{ + TEEC_Session *session = NULL; + struct tee_ioctl_cancel_arg arg; + + memset(&arg, 0, sizeof(arg)); + + if (!operation) + return; + + teec_mutex_lock(&teec_mutex); + session = operation->session; + teec_mutex_unlock(&teec_mutex); + + if (!session) + return; + + arg.session = session->session_id; + arg.cancel_id = 0; + + if (ioctl(session->ctx->fd, TEE_IOC_CANCEL, &arg)) + EMSG("TEE_IOC_CANCEL: %s", strerror(errno)); +} + +TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm) +{ + TEEC_Result res = TEEC_SUCCESS; + int fd = 0; + size_t s = 0; + + if (!ctx || !shm) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!shm->buffer) + return TEEC_ERROR_BAD_PARAMETERS; + + s = shm->size; + if (!s) + s = 8; + if (ctx->reg_mem) { + fd = teec_shm_register(ctx->fd, shm->buffer, s, &shm->id); + if (fd >= 0) { + shm->registered_fd = fd; + shm->shadow_buffer = NULL; + shm->internal.flags = 0; + goto out; + } + + /* + * If we're here TEE_IOC_SHM_REGISTER failed, probably + * because some read-only memory was supplied and the Linux + * kernel doesn't like that at the moment. + * + * The error could also have some other origin. In any case + * we're not making matters worse by trying to allocate and + * register a shadow buffer before giving up. + */ + shm->shadow_buffer = teec_paged_aligned_alloc(s); + if (!shm->shadow_buffer) + return TEEC_ERROR_OUT_OF_MEMORY; + fd = teec_shm_register(ctx->fd, shm->shadow_buffer, s, + &shm->id); + if (fd >= 0) { + shm->registered_fd = fd; + shm->internal.flags = SHM_FLAG_SHADOW_BUFFER_ALLOCED; + goto out; + } + + if (errno == ENOMEM) + res = TEEC_ERROR_OUT_OF_MEMORY; + else + res = TEEC_ERROR_GENERIC; + free(shm->shadow_buffer); + shm->shadow_buffer = NULL; + return res; + } else { + fd = teec_shm_alloc(ctx->fd, s, &shm->id); + if (fd < 0) + return TEEC_ERROR_OUT_OF_MEMORY; + + shm->shadow_buffer = mmap(NULL, s, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + close(fd); + if (shm->shadow_buffer == (void *)MAP_FAILED) { + shm->id = -1; + return TEEC_ERROR_OUT_OF_MEMORY; + } + shm->registered_fd = -1; + shm->internal.flags = 0; + } + +out: + shm->alloced_size = s; + return TEEC_SUCCESS; +} + +TEEC_Result TEEC_RegisterSharedMemoryFileDescriptor(TEEC_Context *ctx, + TEEC_SharedMemory *shm, + int fd) +{ + int rfd = 0; + struct tee_ioctl_shm_register_fd_data data; + + memset(&data, 0, sizeof(data)); + + if (!ctx || !shm || fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) + return TEEC_ERROR_BAD_PARAMETERS; + + data.fd = fd; + rfd = ioctl(ctx->fd, TEE_IOC_SHM_REGISTER_FD, &data); + if (rfd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + shm->buffer = NULL; + shm->shadow_buffer = NULL; + shm->registered_fd = rfd; + shm->id = data.id; + shm->size = data.size; + return TEEC_SUCCESS; +} + +TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm) +{ + int fd = 0; + size_t s = 0; + + if (!ctx || !shm) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!shm->flags || (shm->flags & ~(TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) + return TEEC_ERROR_BAD_PARAMETERS; + + s = shm->size; + if (!s) + s = 8; + + if (ctx->reg_mem) { + shm->buffer = teec_paged_aligned_alloc(s); + if (!shm->buffer) + return TEEC_ERROR_OUT_OF_MEMORY; + + fd = teec_shm_register(ctx->fd, shm->buffer, s, &shm->id); + if (fd < 0) { + free(shm->buffer); + shm->buffer = NULL; + return TEEC_ERROR_OUT_OF_MEMORY; + } + shm->registered_fd = fd; + } else { + fd = teec_shm_alloc(ctx->fd, s, &shm->id); + if (fd < 0) + return TEEC_ERROR_OUT_OF_MEMORY; + + shm->buffer = mmap(NULL, s, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + close(fd); + if (shm->buffer == (void *)MAP_FAILED) { + shm->id = -1; + return TEEC_ERROR_OUT_OF_MEMORY; + } + shm->registered_fd = -1; + } + + shm->shadow_buffer = NULL; + shm->alloced_size = s; + shm->internal.flags = SHM_FLAG_BUFFER_ALLOCED; + return TEEC_SUCCESS; +} + +void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shm) +{ + if (!shm || shm->id == -1) + return; + + if (shm->shadow_buffer) { + if (shm->registered_fd >= 0) { + if (shm->internal.flags & + SHM_FLAG_SHADOW_BUFFER_ALLOCED) + free(shm->shadow_buffer); + close(shm->registered_fd); + } else { + munmap(shm->shadow_buffer, shm->alloced_size); + } + } else if (shm->buffer) { + if (shm->registered_fd >= 0) { + if (shm->internal.flags & SHM_FLAG_BUFFER_ALLOCED) + free(shm->buffer); + close(shm->registered_fd); + } else { + munmap(shm->buffer, shm->alloced_size); + } + } else if (shm->registered_fd >= 0) { + close(shm->registered_fd); + } + + shm->id = -1; + shm->shadow_buffer = NULL; + shm->buffer = NULL; + shm->registered_fd = -1; + shm->internal.flags = 0; +} diff --git a/optee/optee_client/libteec/src/teec_benchmark.c b/optee/optee_client/libteec/src/teec_benchmark.c new file mode 100644 index 0000000..0d04c19 --- /dev/null +++ b/optee/optee_client/libteec/src/teec_benchmark.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2017, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "teec_benchmark.h" + +struct tee_ts_global *bench_ts_global; +static const TEEC_UUID pta_benchmark_uuid = PTA_BENCHMARK_UUID; + +static TEEC_Context bench_ctx; +static TEEC_Session bench_sess; + +static pthread_mutex_t teec_bench_mu = PTHREAD_MUTEX_INITIALIZER; + +/* Cycle counter */ +static inline uint64_t read_ccounter(void) +{ + uint64_t ccounter = 0; +#ifdef __aarch64__ + asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(ccounter)); +#else + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(ccounter)); +#endif + return ccounter * TEE_BENCH_DIVIDER; +} + +static TEEC_Result benchmark_pta_open(void) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_orig = 0; + + res = TEEC_InitializeContext(NULL, &bench_ctx); + if (res != TEEC_SUCCESS) + return res; + + res = TEEC_OpenSession(&bench_ctx, &bench_sess, + &pta_benchmark_uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &ret_orig); + if (res != TEEC_SUCCESS) { + TEEC_FinalizeContext(&bench_ctx); + return res; + } + + return res; +} + +static void benchmark_pta_close(void) +{ + TEEC_CloseSession(&bench_sess); + TEEC_FinalizeContext(&bench_ctx); +} + +static TEEC_Result benchmark_get_bench_buf_paddr(uint64_t *paddr_ts_buf, + uint64_t *size) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_orig = 0; + TEEC_Operation op; + + memset(&op, 0, sizeof(op)); + + res = benchmark_pta_open(); + if (res != TEEC_SUCCESS) + return res; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(&bench_sess, BENCHMARK_CMD_GET_MEMREF, + &op, &ret_orig); + if (res != TEEC_SUCCESS) + return res; + + *paddr_ts_buf = op.params[0].value.a; + *size = op.params[0].value.b; + + benchmark_pta_close(); + + return res; +} + +static void *mmap_paddr(intptr_t paddr, uint64_t size) +{ + int devmem = 0; + off_t offset = 0; + off_t page_addr = 0; + intptr_t *hw_addr = NULL; + + devmem = open("/dev/mem", O_RDWR); + if (!devmem) + return NULL; + + offset = (off_t)paddr % getpagesize(); + page_addr = (off_t)(paddr - offset); + + hw_addr = (intptr_t *)mmap(0, size + offset, PROT_READ|PROT_WRITE, + MAP_SHARED, devmem, page_addr); + if (hw_addr == MAP_FAILED) { + close(devmem); + return NULL; + } + + close(devmem); + return (hw_addr + offset); +} + +/* check if we are in benchmark mode */ +static bool benchmark_check_mode(void) +{ + uint64_t ts_buf_raw = 0; + uint64_t ts_buf_size = 0; + bool res = true; + + if (!bench_ts_global) { + /* receive buffer from Benchmark PTA and register it */ + benchmark_get_bench_buf_paddr(&ts_buf_raw, &ts_buf_size); + if (ts_buf_raw && ts_buf_size) { + bench_ts_global = mmap_paddr(ts_buf_raw, ts_buf_size); + res = (bench_ts_global) ? true : false; + } else { + res = false; + } + } + + return res; +} + +/* Adding timestamp to buffer */ +void bm_timestamp(void) +{ + struct tee_ts_cpu_buf *cpu_buf = NULL; + uint64_t ts_i = 0; + void *ret_addr = NULL; + uint32_t cur_cpu = 0; + int ret = 0; + cpu_set_t cpu_set_old; + cpu_set_t cpu_set_tmp; + struct tee_time_st ts_data; + + memset(&cpu_set_old, 0, sizeof(cpu_set_old)); + memset(&cpu_set_tmp, 0, sizeof(cpu_set_tmp)); + memset(&ts_data, 0, sizeof(ts_data)); + + if (pthread_mutex_trylock(&teec_bench_mu)) + return; + + if (!benchmark_check_mode()) + goto error; + + CPU_ZERO(&cpu_set_old); + ret = sched_getaffinity(0, sizeof(cpu_set_old), &cpu_set_old); + if (ret) + goto error; + + /* stick to the same core while putting timestamp */ + cur_cpu = sched_getcpu(); + CPU_ZERO(&cpu_set_tmp); + CPU_SET(cur_cpu, &cpu_set_tmp); + ret = sched_setaffinity(0, sizeof(cpu_set_tmp), &cpu_set_tmp); + if (ret) + goto error; + + /* fill timestamp data */ + if (cur_cpu >= bench_ts_global->cores) { + ret = sched_setaffinity(0, sizeof(cpu_set_old), &cpu_set_old); + goto error; + } + + ret_addr = __builtin_return_address(0); + + cpu_buf = &bench_ts_global->cpu_buf[cur_cpu]; + ts_i = __sync_fetch_and_add(&cpu_buf->head, 1); + ts_data.cnt = read_ccounter(); + ts_data.addr = (uintptr_t)ret_addr; + ts_data.src = TEE_BENCH_CLIENT; + cpu_buf->stamps[ts_i & TEE_BENCH_MAX_MASK] = ts_data; + + /* set back affinity mask */ + sched_setaffinity(0, sizeof(cpu_set_old), &cpu_set_old); + +error: + pthread_mutex_unlock(&teec_bench_mu); +} + diff --git a/optee/optee_client/libteec/src/teec_trace.c b/optee/optee_client/libteec/src/teec_trace.c new file mode 100644 index 0000000..7194c8c --- /dev/null +++ b/optee/optee_client/libteec/src/teec_trace.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 + +#include "teec_trace.h" + +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) + +/* + * The length of the prefix is 37, for example it looks like this: + * P = Prefix + * M = Message + * F = Function name + * L = Line number + * PPPP: MMMMM [FFFFFFFFFFFFFFF : LLLLL] + */ +#define MAX_PRINT_SIZE 256 + +#ifdef TEEC_LOG_FILE +static void log_to_file(const char *buffer) +{ + FILE *log_file = fopen(TEEC_LOG_FILE, "a"); + + if (log_file != NULL) { + fprintf(log_file, "%s", buffer); + fclose(log_file); + log_file = NULL; + } +} +#else +#define log_to_file(buffer) +#endif + +static const char * const trace_level_strings[] = { + "", "ERR", "INF", "DBG", "FLW" +}; + +void _dprintf(const char *function, int line, int level, const char *prefix, + const char *fmt, ...) +{ + char msg[MAX_PRINT_SIZE]; + int n = 0; + va_list ap; + + if (function) { + int thread_id = syscall(SYS_gettid); + + n = snprintf(msg, sizeof(msg), "%s [%d] %s:%s:%d: ", + trace_level_strings[level], thread_id, prefix, + function, line); + if (n < 0) + return; + } + + if ((size_t)n < sizeof(msg)) { + va_start(ap, fmt); + n = vsnprintf(msg + n, sizeof(msg) - n, fmt, ap); + va_end(ap); + if (n < 0) + return; + } + + fprintf(stdout, "%s", msg); + log_to_file(msg); +} + +#if (defined(DEBUGLEVEL_3) || defined(DEBUGLEVEL_true) || defined(DEBUGLEVEL_4)) +void dump_buffer(const char *bname, const uint8_t *buffer, size_t blen) +{ + fprintf(stderr, "#### %s\n", bname); + + while (blen > 0) { + size_t n = 0; + + for (n = 0; n < 16; n++) { + if (n < blen) + fprintf(stderr, "%02x ", (int)buffer[n]); + else + fprintf(stderr, " "); + + if (n == 7) + fprintf(stderr, " "); + } + + fprintf(stderr, " |"); + + for (n = 0; n < 16; n++) { + if (n < blen) { + if (isprint(buffer[n])) + fprintf(stderr, "%c", (int)buffer[n]); + else + fprintf(stderr, "."); + } + } + + fprintf(stderr, "|\n"); + + blen -= MIN(blen, 16); + buffer += 16; + } +} +#else +void dump_buffer(const char *bname, const uint8_t *buffer, size_t blen) +{ + (void)bname; + (void)buffer; + (void)blen; +} +#endif diff --git a/optee/optee_client/public/CMakeLists.txt b/optee/optee_client/public/CMakeLists.txt new file mode 100644 index 0000000..72b078a --- /dev/null +++ b/optee/optee_client/public/CMakeLists.txt @@ -0,0 +1,25 @@ +project (optee-client-headers C) + +################################################################################ +# Header files to be exported +################################################################################ +FILE(GLOB INSTALL_HEADERS "*.h") + +################################################################################ +# Built library +################################################################################ +add_library(${PROJECT_NAME} INTERFACE) + +################################################################################ +# Public and private header and library dependencies +################################################################################ +target_include_directories( + teec + PUBLIC $ + $ +) + +################################################################################ +# Install targets +################################################################################ +install (FILES ${INSTALL_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/optee/optee_client/public/tee_bench.h b/optee/optee_client/public/tee_bench.h new file mode 100644 index 0000000..600407f --- /dev/null +++ b/optee/optee_client/public/tee_bench.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, 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 TEE_BENCH_H +#define TEE_BENCH_H + +#include + +#define PTA_BENCHMARK_UUID \ + { 0x0b9a63b0, 0xb4c6, 0x4c85, \ + { 0xa2, 0x84, 0xa2, 0x28, 0xef, 0x54, 0x7b, 0x4e } } + +#define BENCHMARK_CMD(id) (0xFA190000 | ((id) & 0xFFFF)) +#define BENCHMARK_CMD_REGISTER_MEMREF BENCHMARK_CMD(1) +#define BENCHMARK_CMD_GET_MEMREF BENCHMARK_CMD(2) +#define BENCHMARK_CMD_UNREGISTER BENCHMARK_CMD(3) + +/* + * Cycle count divider is enabled (in PMCR), + * CCNT value is incremented every 64th clock cycle + */ +#define TEE_BENCH_DIVIDER 64 +/* max amount of timestamps per buffer */ +#define TEE_BENCH_MAX_STAMPS 32 +#define TEE_BENCH_MAX_MASK (TEE_BENCH_MAX_STAMPS - 1) + +/* OP-TEE susbsystems ids */ +#define TEE_BENCH_CLIENT 0x10000000 +#define TEE_BENCH_KMOD 0x20000000 +#define TEE_BENCH_CORE 0x30000000 +#define TEE_BENCH_UTEE 0x40000000 +#define TEE_BENCH_DUMB_TA 0xF0000001 + +/* storing timestamp */ +struct tee_time_st { + uint64_t cnt; /* stores value from CNTPCT register */ + uint64_t addr; /* stores value from program counter register */ + uint64_t src; /* OP-TEE subsystem id */ +}; + +/* per-cpu circular buffer for timestamps */ +struct tee_ts_cpu_buf { + uint64_t head; + uint64_t tail; + struct tee_time_st stamps[TEE_BENCH_MAX_STAMPS]; +}; + +/* memory layout for shared memory, where timestamps will be stored */ +struct tee_ts_global { + uint64_t cores; + struct tee_ts_cpu_buf cpu_buf[]; +}; +#endif /* TEE_BENCH_H */ diff --git a/optee/optee_client/public/tee_client_api.h b/optee/optee_client/public/tee_client_api.h new file mode 100644 index 0000000..1693998 --- /dev/null +++ b/optee/optee_client/public/tee_client_api.h @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * Copyright (c) 2015, 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 TEE_CLIENT_API_H +#define TEE_CLIENT_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +/* + * Defines the number of available memory references in an open session or + * invoke command operation payload. + */ +#define TEEC_CONFIG_PAYLOAD_REF_COUNT 4 + +/** + * Defines the maximum size of a single shared memory block, in bytes, of both + * API allocated and API registered memory. There is no good value to put here + * (limits depend on specific config used), so this define does not provide any + * restriction in this implementation. + */ +#define TEEC_CONFIG_SHAREDMEM_MAX_SIZE ULONG_MAX + +/** + * Flag constants indicating the type of parameters encoded inside the + * operation payload (TEEC_Operation), Type is uint32_t. + * + * TEEC_NONE The Parameter is not used + * + * TEEC_VALUE_INPUT The Parameter is a TEEC_Value tagged as input. + * + * TEEC_VALUE_OUTPUT The Parameter is a TEEC_Value tagged as output. + * + * TEEC_VALUE_INOUT The Parameter is a TEEC_Value tagged as both as + * input and output, i.e., for which both the + * behaviors of TEEC_VALUE_INPUT and + * TEEC_VALUE_OUTPUT apply. + * + * TEEC_MEMREF_TEMP_INPUT The Parameter is a TEEC_TempMemoryReference + * describing a region of memory which needs to be + * temporarily registered for the duration of the + * Operation and is tagged as input. + * + * TEEC_MEMREF_TEMP_OUTPUT Same as TEEC_MEMREF_TEMP_INPUT, but the Memory + * Reference is tagged as output. The + * Implementation may update the size field to + * reflect the required output size in some use + * cases. + * + * TEEC_MEMREF_TEMP_INOUT A Temporary Memory Reference tagged as both + * input and output, i.e., for which both the + * behaviors of TEEC_MEMREF_TEMP_INPUT and + * TEEC_MEMREF_TEMP_OUTPUT apply. + * + * TEEC_MEMREF_WHOLE The Parameter is a Registered Memory Reference + * that refers to the entirety of its parent Shared + * Memory block. The parameter structure is a + * TEEC_MemoryReference. In this structure, the + * Implementation MUST read only the parent field + * and MAY update the size field when the operation + * completes. + * + * TEEC_MEMREF_PARTIAL_INPUT A Registered Memory Reference structure that + * refers to a partial region of its parent Shared + * Memory block and is tagged as input. + * + * TEEC_MEMREF_PARTIAL_OUTPUT Registered Memory Reference structure that + * refers to a partial region of its parent Shared + * Memory block and is tagged as output. + * + * TEEC_MEMREF_PARTIAL_INOUT The Registered Memory Reference structure that + * refers to a partial region of its parent Shared + * Memory block and is tagged as both input and + * output, i.e., for which both the behaviors of + * TEEC_MEMREF_PARTIAL_INPUT and + * TEEC_MEMREF_PARTIAL_OUTPUT apply. + */ +#define TEEC_NONE 0x00000000 +#define TEEC_VALUE_INPUT 0x00000001 +#define TEEC_VALUE_OUTPUT 0x00000002 +#define TEEC_VALUE_INOUT 0x00000003 +#define TEEC_MEMREF_TEMP_INPUT 0x00000005 +#define TEEC_MEMREF_TEMP_OUTPUT 0x00000006 +#define TEEC_MEMREF_TEMP_INOUT 0x00000007 +#define TEEC_MEMREF_WHOLE 0x0000000C +#define TEEC_MEMREF_PARTIAL_INPUT 0x0000000D +#define TEEC_MEMREF_PARTIAL_OUTPUT 0x0000000E +#define TEEC_MEMREF_PARTIAL_INOUT 0x0000000F + +/** + * Flag constants indicating the data transfer direction of memory in + * TEEC_Parameter. TEEC_MEM_INPUT signifies data transfer direction from the + * client application to the TEE. TEEC_MEM_OUTPUT signifies data transfer + * direction from the TEE to the client application. Type is uint32_t. + * + * TEEC_MEM_INPUT The Shared Memory can carry data from the client + * application to the Trusted Application. + * TEEC_MEM_OUTPUT The Shared Memory can carry data from the Trusted + * Application to the client application. + */ +#define TEEC_MEM_INPUT 0x00000001 +#define TEEC_MEM_OUTPUT 0x00000002 + +/** + * Return values. Type is TEEC_Result + * + * TEEC_SUCCESS The operation was successful. + * TEEC_ERROR_GENERIC Non-specific cause. + * TEEC_ERROR_ACCESS_DENIED Access privileges are not sufficient. + * TEEC_ERROR_CANCEL The operation was canceled. + * TEEC_ERROR_ACCESS_CONFLICT Concurrent accesses caused conflict. + * TEEC_ERROR_EXCESS_DATA Too much data for the requested operation was + * passed. + * TEEC_ERROR_BAD_FORMAT Input data was of invalid format. + * TEEC_ERROR_BAD_PARAMETERS Input parameters were invalid. + * TEEC_ERROR_BAD_STATE Operation is not valid in the current state. + * TEEC_ERROR_ITEM_NOT_FOUND The requested data item is not found. + * TEEC_ERROR_NOT_IMPLEMENTED The requested operation should exist but is not + * yet implemented. + * TEEC_ERROR_NOT_SUPPORTED The requested operation is valid but is not + * supported in this implementation. + * TEEC_ERROR_NO_DATA Expected data was missing. + * TEEC_ERROR_OUT_OF_MEMORY System ran out of resources. + * TEEC_ERROR_BUSY The system is busy working on something else. + * TEEC_ERROR_COMMUNICATION Communication with a remote party failed. + * TEEC_ERROR_SECURITY A security fault was detected. + * TEEC_ERROR_SHORT_BUFFER The supplied buffer is too short for the + * generated output. + * TEEC_ERROR_TARGET_DEAD Trusted Application has panicked + * during the operation. + */ + +/** + * Standard defined error codes. + */ +#define TEEC_SUCCESS 0x00000000 +#define TEEC_ERROR_STORAGE_NOT_AVAILABLE 0xF0100003 +#define TEEC_ERROR_GENERIC 0xFFFF0000 +#define TEEC_ERROR_ACCESS_DENIED 0xFFFF0001 +#define TEEC_ERROR_CANCEL 0xFFFF0002 +#define TEEC_ERROR_ACCESS_CONFLICT 0xFFFF0003 +#define TEEC_ERROR_EXCESS_DATA 0xFFFF0004 +#define TEEC_ERROR_BAD_FORMAT 0xFFFF0005 +#define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 +#define TEEC_ERROR_BAD_STATE 0xFFFF0007 +#define TEEC_ERROR_ITEM_NOT_FOUND 0xFFFF0008 +#define TEEC_ERROR_NOT_IMPLEMENTED 0xFFFF0009 +#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A +#define TEEC_ERROR_NO_DATA 0xFFFF000B +#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C +#define TEEC_ERROR_BUSY 0xFFFF000D +#define TEEC_ERROR_COMMUNICATION 0xFFFF000E +#define TEEC_ERROR_SECURITY 0xFFFF000F +#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010 +#define TEEC_ERROR_EXTERNAL_CANCEL 0xFFFF0011 +#define TEEC_ERROR_TARGET_DEAD 0xFFFF3024 +#define TEEC_ERROR_STORAGE_NO_SPACE 0xFFFF3041 + +/** + * Function error origins, of type TEEC_ErrorOrigin. These indicate where in + * the software stack a particular return value originates from. + * + * TEEC_ORIGIN_API The error originated within the TEE Client API + * implementation. + * TEEC_ORIGIN_COMMS The error originated within the underlying + * communications stack linking the rich OS with + * the TEE. + * TEEC_ORIGIN_TEE The error originated within the common TEE code. + * TEEC_ORIGIN_TRUSTED_APP The error originated within the Trusted Application + * code. + */ +#define TEEC_ORIGIN_API 0x00000001 +#define TEEC_ORIGIN_COMMS 0x00000002 +#define TEEC_ORIGIN_TEE 0x00000003 +#define TEEC_ORIGIN_TRUSTED_APP 0x00000004 + +/** + * Session login methods, for use in TEEC_OpenSession() as parameter + * connectionMethod. Type is uint32_t. + * + * TEEC_LOGIN_PUBLIC No login data is provided. + * TEEC_LOGIN_USER Login data about the user running the Client + * Application process is provided. + * TEEC_LOGIN_GROUP Login data about the group running the Client + * Application process is provided. + * TEEC_LOGIN_APPLICATION Login data about the running Client Application + * itself is provided. + * TEEC_LOGIN_USER_APPLICATION Login data about the user and the running + * Client Application itself is provided. + * TEEC_LOGIN_GROUP_APPLICATION Login data about the group and the running + * Client Application itself is provided. + */ +#define TEEC_LOGIN_PUBLIC 0x00000000 +#define TEEC_LOGIN_USER 0x00000001 +#define TEEC_LOGIN_GROUP 0x00000002 +#define TEEC_LOGIN_APPLICATION 0x00000004 +#define TEEC_LOGIN_USER_APPLICATION 0x00000005 +#define TEEC_LOGIN_GROUP_APPLICATION 0x00000006 + +/** + * Encode the paramTypes according to the supplied types. + * + * @param p0 The first param type. + * @param p1 The second param type. + * @param p2 The third param type. + * @param p3 The fourth param type. + */ +#define TEEC_PARAM_TYPES(p0, p1, p2, p3) \ + ((p0) | ((p1) << 4) | ((p2) << 8) | ((p3) << 12)) + +/** + * Get the i_th param type from the paramType. + * + * @param p The paramType. + * @param i The i-th parameter to get the type for. + */ +#define TEEC_PARAM_TYPE_GET(p, i) (((p) >> (i * 4)) & 0xF) + +typedef uint32_t TEEC_Result; + +/** + * struct TEEC_Context - Represents a connection between a client application + * and a TEE. + */ +typedef struct { + /* Implementation defined */ + int fd; + bool reg_mem; + bool memref_null; +} TEEC_Context; + +/** + * This type contains a Universally Unique Resource Identifier (UUID) type as + * defined in RFC4122. These UUID values are used to identify Trusted + * Applications. + */ +typedef struct { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint8_t clockSeqAndNode[8]; +} TEEC_UUID; + +/** + * struct TEEC_SharedMemory - Memory to transfer data between a client + * application and trusted code. + * + * @param buffer The memory buffer which is to be, or has been, shared + * with the TEE. + * @param size The size, in bytes, of the memory buffer. + * @param flags Bit-vector which holds properties of buffer. + * The bit-vector can contain either or both of the + * TEEC_MEM_INPUT and TEEC_MEM_OUTPUT flags. + * + * A shared memory block is a region of memory allocated in the context of the + * client application memory space that can be used to transfer data between + * that client application and a trusted application. The user of this struct + * is responsible to populate the buffer pointer. + */ +typedef struct { + void *buffer; + size_t size; + uint32_t flags; + /* + * Implementation-Defined + */ + int id; + size_t alloced_size; + void *shadow_buffer; + int registered_fd; + union { + bool dummy; + uint8_t flags; + } internal; +} TEEC_SharedMemory; + +/** + * struct TEEC_TempMemoryReference - Temporary memory to transfer data between + * a client application and trusted code, only used for the duration of the + * operation. + * + * @param buffer The memory buffer which is to be, or has been shared with + * the TEE. + * @param size The size, in bytes, of the memory buffer. + * + * A memory buffer that is registered temporarily for the duration of the + * operation to be called. + */ +typedef struct { + void *buffer; + size_t size; +} TEEC_TempMemoryReference; + +/** + * struct TEEC_RegisteredMemoryReference - use a pre-registered or + * pre-allocated shared memory block of memory to transfer data between + * a client application and trusted code. + * + * @param parent Points to a shared memory structure. The memory reference + * may utilize the whole shared memory or only a part of it. + * Must not be NULL + * + * @param size The size, in bytes, of the memory buffer. + * + * @param offset The offset, in bytes, of the referenced memory region from + * the start of the shared memory block. + * + */ +typedef struct { + TEEC_SharedMemory *parent; + size_t size; + size_t offset; +} TEEC_RegisteredMemoryReference; + +/** + * struct TEEC_Value - Small raw data container + * + * Instead of allocating a shared memory buffer this structure can be used + * to pass small raw data between a client application and trusted code. + * + * @param a The first integer value. + * + * @param b The second value. + */ +typedef struct { + uint32_t a; + uint32_t b; +} TEEC_Value; + +/** + * union TEEC_Parameter - Memory container to be used when passing data between + * client application and trusted code. + * + * Either the client uses a shared memory reference, parts of it or a small raw + * data container. + * + * @param tmpref A temporary memory reference only valid for the duration + * of the operation. + * + * @param memref The entire shared memory or parts of it. + * + * @param value The small raw data container to use + */ +typedef union { + TEEC_TempMemoryReference tmpref; + TEEC_RegisteredMemoryReference memref; + TEEC_Value value; +} TEEC_Parameter; + +/** + * struct TEEC_Session - Represents a connection between a client application + * and a trusted application. + */ +typedef struct { + /* Implementation defined */ + TEEC_Context *ctx; + uint32_t session_id; +} TEEC_Session; + +/** + * struct TEEC_Operation - Holds information and memory references used in + * TEEC_InvokeCommand(). + * + * @param started Client must initialize to zero if it needs to cancel + * an operation about to be performed. + * @param paramTypes Type of data passed. Use TEEC_PARAM_TYPES macro to + * create the correct flags. + * 0 means TEEC_NONE is passed for all params. + * @param params Array of parameters of type TEEC_Parameter. + * @param session Internal pointer to the last session used by + * TEEC_InvokeCommand with this operation. + * + */ +typedef struct { + uint32_t started; + uint32_t paramTypes; + TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; + /* Implementation-Defined */ + TEEC_Session *session; +} TEEC_Operation; + +/** + * TEEC_InitializeContext() - Initializes a context holding connection + * information on the specific TEE, designated by the name string. + + * @param name A zero-terminated string identifying the TEE to connect to. + * If name is set to NULL, the default TEE is connected to. NULL + * is the only supported value in this version of the API + * implementation. + * + * @param context The context structure which is to be initialized. + * + * @return TEEC_SUCCESS The initialization was successful. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context); + +/** + * TEEC_FinalizeContext() - Destroys a context holding connection information + * on the specific TEE. + * + * This function destroys an initialized TEE context, closing the connection + * between the client application and the TEE. This function must only be + * called when all sessions related to this TEE context have been closed and + * all shared memory blocks have been released. + * + * @param context The context to be destroyed. + */ +void TEEC_FinalizeContext(TEEC_Context *context); + +/** + * TEEC_OpenSession() - Opens a new session with the specified trusted + * application. + * + * @param context The initialized TEE context structure in which + * scope to open the session. + * @param session The session to initialize. + * @param destination A structure identifying the trusted application + * with which to open a session. + * + * @param connectionMethod The connection method to use. + * @param connectionData Any data necessary to connect with the chosen + * connection method. Not supported, should be set to + * NULL. + * @param operation An operation structure to use in the session. May + * be set to NULL to signify no operation structure + * needed. + * + * @param returnOrigin A parameter which will hold the error origin if + * this function returns any value other than + * TEEC_SUCCESS. + * + * @return TEEC_SUCCESS OpenSession successfully opened a new session. + * @return TEEC_Result Something failed. + * + */ +TEEC_Result TEEC_OpenSession(TEEC_Context *context, + TEEC_Session *session, + const TEEC_UUID *destination, + uint32_t connectionMethod, + const void *connectionData, + TEEC_Operation *operation, + uint32_t *returnOrigin); + +/** + * TEEC_CloseSession() - Closes the session which has been opened with the + * specific trusted application. + * + * @param session The opened session to close. + */ +void TEEC_CloseSession(TEEC_Session *session); + +/** + * TEEC_InvokeCommand() - Executes a command in the specified trusted + * application. + * + * @param session A handle to an open connection to the trusted + * application. + * @param commandID Identifier of the command in the trusted application + * to invoke. + * @param operation An operation structure to use in the invoke command. + * May be set to NULL to signify no operation structure + * needed. + * @param returnOrigin A parameter which will hold the error origin if this + * function returns any value other than TEEC_SUCCESS. + * + * @return TEEC_SUCCESS OpenSession successfully opened a new session. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, + uint32_t commandID, + TEEC_Operation *operation, + uint32_t *returnOrigin); + +/** + * TEEC_RegisterSharedMemory() - Register a block of existing memory as a + * shared block within the scope of the specified context. + * + * @param context The initialized TEE context structure in which scope to + * open the session. + * @param sharedMem pointer to the shared memory structure to register. + * + * @return TEEC_SUCCESS The registration was successful. + * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, + TEEC_SharedMemory *sharedMem); + +/** + * TEEC_AllocateSharedMemory() - Allocate shared memory for TEE. + * + * @param context The initialized TEE context structure in which scope to + * open the session. + * @param sharedMem Pointer to the allocated shared memory. + * + * @return TEEC_SUCCESS The registration was successful. + * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, + TEEC_SharedMemory *sharedMem); + +/** + * TEEC_ReleaseSharedMemory() - Free or deregister the shared memory. + * + * @param sharedMem Pointer to the shared memory to be freed. + */ +void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *sharedMemory); + +/** + * TEEC_RequestCancellation() - Request the cancellation of a pending open + * session or command invocation. + * + * @param operation Pointer to an operation previously passed to open session + * or invoke. + */ +void TEEC_RequestCancellation(TEEC_Operation *operation); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_client/public/tee_client_api_extensions.h b/optee/optee_client/public/tee_client_api_extensions.h new file mode 100644 index 0000000..85298aa --- /dev/null +++ b/optee/optee_client/public/tee_client_api_extensions.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016, 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 TEE_CLIENT_API_EXTENSIONS_H +#define TEE_CLIENT_API_EXTENSIONS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * TEEC_RegisterMemoryFileDescriptor() - Register a block of existing memory as + * a shared block within the scope of the specified context. + * + * @param context The initialized TEE context structure in which scope to + * open the session. + * @param sharedMem pointer to the shared memory structure to register. + * @param fd file descriptor of the target memory. + * + * @return TEEC_SUCCESS The registration was successful. + * @return TEEC_ERROR_OUT_OF_MEMORY Memory exhaustion. + * @return TEEC_Result Something failed. + */ +TEEC_Result TEEC_RegisterSharedMemoryFileDescriptor(TEEC_Context *context, + TEEC_SharedMemory *sharedMem, + int fd); + +#ifdef __cplusplus +} +#endif + +#endif /* TEE_CLIENT_API_EXTENSIONS_H */ diff --git a/optee/optee_client/public/tee_plugin_method.h b/optee/optee_client/public/tee_plugin_method.h new file mode 100644 index 0000000..c08dc12 --- /dev/null +++ b/optee/optee_client/public/tee_plugin_method.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#ifndef TEE_PLUGIN_METHOD_H +#define TEE_PLUGIN_METHOD_H + +#include +#include + +struct plugin_method { + const char *name; /* short friendly name of the plugin */ + TEEC_UUID uuid; + TEEC_Result (*init)(void); + TEEC_Result (*invoke)(unsigned int cmd, unsigned int sub_cmd, + void *data, size_t in_len, size_t *out_len); +}; + +#endif /* TEE_PLUGIN_METHOD_H */ diff --git a/optee/optee_client/public/teec_trace.h b/optee/optee_client/public/teec_trace.h new file mode 100644 index 0000000..f75358f --- /dev/null +++ b/optee/optee_client/public/teec_trace.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 TEEC_TRACE_H +#define TEEC_TRACE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#ifndef BINARY_PREFIX +#error "BINARY_PREFIX not defined" +#endif + +/* + * Trace levels. + * + * 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_ERROR 1 +#define TRACE_INFO 2 +#define TRACE_DEBUG 3 +#define TRACE_FLOW 4 + +#if defined(DEBUGLEVEL_0) && !defined(DEBUGLEVEL) +#define DEBUGLEVEL TRACE_ERROR +#endif + +#if defined(DEBUGLEVEL_1) && !defined(DEBUGLEVEL) +#define DEBUGLEVEL TRACE_ERROR +#endif + +#if defined(DEBUGLEVEL_2) && !defined(DEBUGLEVEL) +#define DEBUGLEVEL TRACE_INFO +#endif + +#if defined(DEBUGLEVEL_3) && !defined(DEBUGLEVEL) +#define DEBUGLEVEL TRACE_DEBUG +#endif + +#if defined(DEBUGLEVEL_4) && !defined(DEBUGLEVEL) +#define DEBUGLEVEL TRACE_FLOW +#endif + +#ifndef DEBUGLEVEL +/* Default debug level. */ +#define DEBUGLEVEL TRACE_INFO +#endif + +/* + * 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))) + +void _dprintf(const char *function, int line, int level, const char *prefix, + const char *fmt, ...) __PRINTFLIKE(5, 6); + +#define dprintf(level, x...) do { \ + if ((level) <= DEBUGLEVEL) { \ + _dprintf(__func__, __LINE__, level, \ + BINARY_PREFIX, x); \ + } \ + } while (0) + +#define EMSG(fmt, ...) dprintf(TRACE_ERROR, fmt "\n", ##__VA_ARGS__) +#define IMSG(fmt, ...) dprintf(TRACE_INFO, fmt "\n", ##__VA_ARGS__) +#define DMSG(fmt, ...) dprintf(TRACE_DEBUG, fmt "\n", ##__VA_ARGS__) +#define FMSG(fmt, ...) dprintf(TRACE_FLOW, fmt "\n", ##__VA_ARGS__) + +#define INMSG(fmt, ...) FMSG("> " fmt, ##__VA_ARGS__) +#define OUTMSG(fmt, ...) FMSG("< " fmt, ##__VA_ARGS__) +#define OUTRMSG(r) \ + do { \ + if (r) \ + EMSG("Function returns with [%d]", r); \ + OUTMSG("r=[%d]", r); \ + return r; \ + } while (0) + +#define dprintf_raw(level, x...) do { \ + if ((level) <= DEBUGLEVEL) \ + _dprintf(0, 0, (level), BINARY_PREFIX, x); \ + } while (0) + +#define EMSG_RAW(fmt, ...) dprintf_raw(TRACE_ERROR, fmt, ##__VA_ARGS__) +#define IMSG_RAW(fmt, ...) dprintf_raw(TRACE_INFO, fmt, ##__VA_ARGS__) +#define DMSG_RAW(fmt, ...) dprintf_raw(TRACE_DEBUG, fmt, ##__VA_ARGS__) +#define FMSG_RAW(fmt, ...) dprintf_raw(TRACE_FLOW, fmt, ##__VA_ARGS__) + +/* + * This function will hex and ascii dump a buffer. + * + * Note that this function will only print if debug flag + * DEBUGLEVEL is INFO or FLOOD. + * + * @param bname Information string describing the buffer. + * @param buffer Pointer to the buffer. + * @param blen Length of the buffer. + * + * @return void + */ +void dump_buffer(const char *bname, const uint8_t *buffer, size_t blen); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_client/scripts/checkpatch_inc.sh b/optee/optee_client/scripts/checkpatch_inc.sh new file mode 100644 index 0000000..23a503c --- /dev/null +++ b/optee/optee_client/scripts/checkpatch_inc.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-2-Clause + +CHECKPATCH="${CHECKPATCH:-checkpatch.pl}" +# checkpatch.pl will ignore the following paths +CHECKPATCH_IGNORE=$(echo ) +_CP_EXCL=$(for p in $CHECKPATCH_IGNORE; do echo ":(exclude)$p" ; done) + +function _checkpatch() { + # Use --typedefsfile if supported by the checkpatch tool + typedefs_opt="--typedefsfile typedefs.checkpatch" + $CHECKPATCH --help 2>&1 | grep -q -- --typedefsfile || \ + typedefs_opt=""; + # Ignore NOT_UNIFIED_DIFF in case patch has no diff + # (e.g., all paths filtered out) + $CHECKPATCH --quiet --ignore FILE_PATH_CHANGES \ + --ignore GERRIT_CHANGE_ID \ + --ignore NOT_UNIFIED_DIFF \ + --ignore CAMELCASE \ + --ignore PREFER_KERNEL_TYPES \ + --ignore CONCATENATED_STRING \ + --no-tree \ + --strict \ + $typedefs_opt \ + - +} + +function checkpatch() { + git show --oneline --no-patch $1 + # The first git 'format-patch' shows the commit message + # The second one produces the diff (might be empty if _CP_EXCL + # filters out all diffs) + (git format-patch $1^..$1 --stdout | sed -n '/^diff --git/q;p'; \ + git format-patch $1^..$1 --stdout -- $_CP_EXCL . | \ + sed -n '/^diff --git/,$p') | _checkpatch +} + +function checkstaging() { + git diff --cached -- . $_CP_EXCL | _checkpatch +} + +function checkworking() { + git diff -- . $_CP_EXCL | _checkpatch +} + +function checkdiff() { + git diff $1...$2 -- . $_CP_EXCL | _checkpatch +} + diff --git a/optee/optee_client/tee-supplicant/CMakeLists.txt b/optee/optee_client/tee-supplicant/CMakeLists.txt new file mode 100644 index 0000000..39f797c --- /dev/null +++ b/optee/optee_client/tee-supplicant/CMakeLists.txt @@ -0,0 +1,119 @@ +project (tee-supplicant C) + +################################################################################ +# Configuration flags always included +################################################################################ +option (CFG_TA_TEST_PATH "Enable tee-supplicant to load from test/debug path" OFF) +option (RPMB_EMU "Enable tee-supplicant to emulate RPMB" ON) +option (CFG_TA_GPROF_SUPPORT "Enable tee-supplicant support for TAs instrumented with gprof" ON) +option (CFG_FTRACE_SUPPORT "Enable tee-supplicant support for TAs instrumented with ftrace" ON) +option (CFG_TEE_SUPP_PLUGINS "Enable tee-supplicant plugin support" ON) + +set (CFG_TEE_SUPP_LOG_LEVEL "1" CACHE STRING "tee-supplicant log level") +# FIXME: Question is, is this really needed? Should just use defaults from # GNUInstallDirs? +set (CFG_TEE_CLIENT_LOAD_PATH "/lib" CACHE STRING "Colon-separated list of paths where to look for TAs (see also --ta-dir)") +set (CFG_TEE_FS_PARENT_PATH "/data/tee" CACHE STRING "Location of TEE filesystem (secure storage)") +# FIXME: Why do we have if defined(CFG_GP_SOCKETS) && CFG_GP_SOCKETS == 1 in the c-file? +set (CFG_GP_SOCKETS "1" CACHE STRING "Enable GlobalPlatform Socket API support") +set (CFG_TEE_PLUGIN_LOAD_PATH "/usr/lib/tee-supplicant/plugins/" CACHE STRING "tee-supplicant's plugins path") + +if (CFG_TEE_SUPP_PLUGINS) + set (CMAKE_INSTALL_RPATH "${CFG_TEE_PLUGIN_LOAD_PATH}") +endif() + +################################################################################ +# Source files +################################################################################ +set (SRC + src/handle.c + src/hmac_sha2.c + src/rpmb.c + src/nvme_rpmb.c + src/sha2.c + src/tee_supp_fs.c + src/tee_supplicant.c + src/teec_ta_load.c +) + +if (CFG_GP_SOCKETS) + set (SRC ${SRC} src/tee_socket.c) +endif() + +if (CFG_TA_GPROF_SUPPORT OR CFG_FTRACE_SUPPORT) + set (SRC ${SRC} src/prof.c) +endif() + +if (CFG_TEE_SUPP_PLUGINS) + set (SRC ${SRC} src/plugin.c) +endif() + +################################################################################ +# Built binary +################################################################################ +add_executable (${PROJECT_NAME} ${SRC}) + +################################################################################ +# Flags always set +################################################################################ +target_compile_definitions (${PROJECT_NAME} + PRIVATE -DDEBUGLEVEL_${CFG_TEE_SUPP_LOG_LEVEL} + PRIVATE -DTEEC_LOAD_PATH="${CFG_TEE_CLIENT_LOAD_PATH}" + PRIVATE -DTEE_FS_PARENT_PATH="${CFG_TEE_FS_PARENT_PATH}" + PRIVATE -DBINARY_PREFIX="TSUP" +) + +################################################################################ +# Optional flags +################################################################################ +if (CFG_GP_SOCKETS) + target_compile_definitions (${PROJECT_NAME} + PRIVATE -DCFG_GP_SOCKETS=${CFG_GP_SOCKETS}) +endif() + +if (CFG_TA_TEST_PATH) + target_compile_definitions (${PROJECT_NAME} + PRIVATE -DCFG_TA_TEST_PATH=${CFG_TA_TEST_PATH}) +endif() + +if (RPMB_EMU) + target_compile_definitions (${PROJECT_NAME} + PRIVATE -DRPMB_EMU=1) +endif() + +if (CFG_TA_GPROF_SUPPORT) + target_compile_definitions (${PROJECT_NAME} + PRIVATE -DCFG_TA_GPROF_SUPPORT) +endif() + +if (CFG_FTRACE_SUPPORT) + target_compile_definitions (${PROJECT_NAME} + PRIVATE -DCFG_FTRACE_SUPPORT) +endif() + +if (CFG_TEE_SUPP_PLUGINS) + target_compile_definitions (${PROJECT_NAME} + PRIVATE -DTEE_SUPP_PLUGINS + PRIVATE -DTEE_PLUGIN_LOAD_PATH="${CFG_TEE_PLUGIN_LOAD_PATH}" + ) +endif() + +################################################################################ +# Public and private header and library dependencies +################################################################################ +target_include_directories(${PROJECT_NAME} PRIVATE src) + +target_link_libraries (${PROJECT_NAME} + PRIVATE teec + PRIVATE optee-client-headers +) + +if (CFG_TEE_SUPP_PLUGINS) + target_link_libraries (${PROJECT_NAME} + PRIVATE dl + ) +endif() + +################################################################################ +# Install targets +################################################################################ +install (TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}) diff --git a/optee/optee_client/tee-supplicant/Makefile b/optee/optee_client/tee-supplicant/Makefile new file mode 100644 index 0000000..2252613 --- /dev/null +++ b/optee/optee_client/tee-supplicant/Makefile @@ -0,0 +1,107 @@ +include ../flags.mk +include ../config.mk + +OUT_DIR := $(OO)/tee-supplicant + +# Emulate RPMB ioctl's by default +RPMB_EMU ?= 1 + +.PHONY: all tee-supplicant clean + +all: tee-supplicant +################################################################################ +# Teec configuration +################################################################################ +PACKAGE_NAME := tee-supplicant + +TEES_SRCS := tee_supplicant.c \ + teec_ta_load.c \ + tee_supp_fs.c \ + rpmb.c \ + nvme_rpmb.c \ + handle.c + +ifeq ($(CFG_GP_SOCKETS),y) +TEES_SRCS += tee_socket.c +endif + +ifeq ($(RPMB_EMU),1) +TEES_SRCS += sha2.c hmac_sha2.c +endif +ifneq (,$(filter y,$(CFG_TA_GPROF_SUPPORT) $(CFG_FTRACE_SUPPORT))) +TEES_SRCS += prof.c +endif + +ifeq ($(CFG_TEE_SUPP_PLUGINS),y) +TEES_SRCS += plugin.c +endif + +TEES_SRC_DIR := src +TEES_OBJ_DIR := $(OUT_DIR) +TEES_OBJS := $(patsubst %.c,$(TEES_OBJ_DIR)/%.o, $(TEES_SRCS)) +TEES_INCLUDES := ${CURDIR}/../libteec/include \ + ${CURDIR}/src \ + ${CURDIR}/../public \ + +TEES_CFLAGS := $(addprefix -I, $(TEES_INCLUDES)) $(CFLAGS) \ + -DDEBUGLEVEL_$(CFG_TEE_SUPP_LOG_LEVEL) \ + -DBINARY_PREFIX=\"TEES\" \ + -DTEE_FS_PARENT_PATH=\"$(CFG_TEE_FS_PARENT_PATH)\" \ + -DTEEC_LOAD_PATH=\"$(CFG_TEE_CLIENT_LOAD_PATH)\" \ + +ifeq ($(CFG_GP_SOCKETS),y) +TEES_CFLAGS += -DCFG_GP_SOCKETS=1 +endif +ifeq ($(RPMB_EMU),1) +TEES_CFLAGS += -DRPMB_EMU=1 +endif +ifeq ($(CFG_TA_TEST_PATH),y) +TEES_CFLAGS += -DCFG_TA_TEST_PATH=1 +endif +TEES_FILE := $(OUT_DIR)/$(PACKAGE_NAME) +TEES_LFLAGS := $(LDFLAGS) -L$(OUT_DIR)/../libteec -lteec + +ifeq ($(CFG_TA_GPROF_SUPPORT),y) +TEES_CFLAGS += -DCFG_TA_GPROF_SUPPORT +endif + +ifeq ($(CFG_FTRACE_SUPPORT),y) +TEES_CFLAGS += -DCFG_FTRACE_SUPPORT +endif + +TEES_CFLAGS += -fstack-protector-strong + +ifeq ($(CFG_TEE_SUPP_PLUGINS),y) +TEES_CFLAGS += -DTEE_SUPP_PLUGINS \ + -DTEE_PLUGIN_LOAD_PATH=\"$(CFG_TEE_PLUGIN_LOAD_PATH)\" +endif + +TEES_LFLAGS += -lpthread +# Needed to get clock_gettime() for for glibc versions before 2.17 +TEES_LFLAGS += -lrt + +ifeq ($(CFG_TEE_SUPP_PLUGINS),y) +# Needed to dynamically load user plugins +TEES_LFLAGS += -ldl +# Needed for dlopen() +TEES_LFLAGS += -Wl,-rpath=$(CFG_TEE_PLUGIN_LOAD_PATH) +endif + +tee-supplicant: $(TEES_FILE) + +$(TEES_FILE): $(TEES_OBJS) + @echo " LINK $@" + $(VPREFIX)$(CC) -o $@ $+ $(TEES_LFLAGS) + @echo "" + +$(TEES_OBJ_DIR)/%.o: $(TEES_SRC_DIR)/%.c + $(VPREFIX)mkdir -p $(dir $@) + @echo " CC $<" + $(VPREFIX)$(CC) $(TEES_CFLAGS) $(TEES_CFLAGS_$(notdir $<)) -c $< -o $@ + +################################################################################ +# Cleaning up configuration +################################################################################ +clean: + $(RM) $(TEES_OBJS) $(TEES_FILE) + $(call rmdir,$(OUT_DIR)) diff --git a/optee/optee_client/tee-supplicant/src/__tee_ipsocket.h b/optee/optee_client/tee-supplicant/src/__tee_ipsocket.h new file mode 100644 index 0000000..7c33666 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/__tee_ipsocket.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016-2017, 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 ____TEE_IPSOCKET_H +#define ____TEE_IPSOCKET_H + +typedef enum TEE_ipSocket_ipVersion_e { + TEE_IP_VERSION_DC = 0, /* don’t care */ + TEE_IP_VERSION_4 = 1, + TEE_IP_VERSION_6 = 2 +} TEE_ipSocket_ipVersion; + +#endif /*____TEE_IPSOCKET_H*/ diff --git a/optee/optee_client/tee-supplicant/src/__tee_isocket_defines.h b/optee/optee_client/tee-supplicant/src/__tee_isocket_defines.h new file mode 100644 index 0000000..b38457a --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/__tee_isocket_defines.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016-2017, 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 ____TEE_ISOCKET_DEFINES_H +#define ____TEE_ISOCKET_DEFINES_H + +#define TEE_ISOCKET_VERSION 0x01000000 + +#define TEE_ISOCKET_ERROR_PROTOCOL 0xF1007001 +#define TEE_ISOCKET_ERROR_REMOTE_CLOSED 0xF1007002 +#define TEE_ISOCKET_ERROR_TIMEOUT 0xF1007003 +#define TEE_ISOCKET_ERROR_OUT_OF_RESOURCES 0xF1007004 +#define TEE_ISOCKET_ERROR_LARGE_BUFFER 0xF1007005 +#define TEE_ISOCKET_WARNING_PROTOCOL 0xF1007006 +#define TEE_ISOCKET_ERROR_HOSTNAME 0xF1007007 + +#endif /*____TEE_ISOCKET_DEFINES_H*/ diff --git a/optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines.h b/optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines.h new file mode 100644 index 0000000..21853e0 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016-2017, 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 ____TEE_TCPSOCKET_DEFINES_H +#define ____TEE_TCPSOCKET_DEFINES_H + +/* Protocol identifier */ +#define TEE_ISOCKET_PROTOCOLID_TCP 0x65 + +/* Instance specific errors */ +#define TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND 0xF1010002 + +#endif /*____TEE_TCPSOCKET_DEFINES_H*/ diff --git a/optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h b/optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h new file mode 100644 index 0000000..3a03a2c --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/__tee_tcpsocket_defines_extensions.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016-2017, 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 ____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H +#define ____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H + +/* Instance and implementation specific ioctl functions */ +#define TEE_TCP_SET_RECVBUF 0x65f00000 +#define TEE_TCP_SET_SENDBUF 0x65f00001 + +#endif /*____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H*/ diff --git a/optee/optee_client/tee-supplicant/src/__tee_udpsocket_defines.h b/optee/optee_client/tee-supplicant/src/__tee_udpsocket_defines.h new file mode 100644 index 0000000..64ec09c --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/__tee_udpsocket_defines.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016-2017, 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 ____TEE_UDPSOCKET_DEFINES_H +#define ____TEE_UDPSOCKET_DEFINES_H + +/* Protocol identifier */ +#define TEE_ISOCKET_PROTOCOLID_UDP 0x66 + +/* Instance specific errors */ +#define TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND 0xF1020002 + +/* Instance specific ioctl functions */ +#define TEE_UDP_CHANGEADDR 0x66000001 +#define TEE_UDP_CHANGEPORT 0x66000002 + +#endif /*____TEE_UDPSOCKET_DEFINES_H*/ diff --git a/optee/optee_client/tee-supplicant/src/handle.c b/optee/optee_client/tee-supplicant/src/handle.c new file mode 100644 index 0000000..58254bd --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/handle.c @@ -0,0 +1,175 @@ +/* + * 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 +#include "handle.h" + +/* + * Define the initial capacity of the database. It should be a low number + * multiple of 2 since some databases a likely to only use a few handles. + * Since the algorithm is to doubles up when growing it shouldn't cause a + * noticable overhead on large databases. + */ +#define HANDLE_DB_INITIAL_MAX_PTRS 4 + +static void mutex_lock(struct handle_db *db) +{ + if (db->mu) + pthread_mutex_lock(db->mu); +} + +static void mutex_unlock(struct handle_db *db) +{ + if (db->mu) + pthread_mutex_unlock(db->mu); +} + + +void handle_db_set_mutex(struct handle_db *db, pthread_mutex_t *mu) +{ + db->mu = mu; +} + +void handle_db_destroy(struct handle_db *db) +{ + if (db) { + mutex_lock(db); + free(db->ptrs); + db->ptrs = NULL; + db->max_ptrs = 0; + mutex_unlock(db); + } +} + +int handle_get(struct handle_db *db, void *ptr) +{ + size_t n = 0; + void *p = NULL; + size_t new_max_ptrs = 0; + int ret = 0; + + if (!db || !ptr) + return -1; + + mutex_lock(db); + + /* Try to find an empty location */ + for (n = 0; n < db->max_ptrs; n++) { + if (!db->ptrs[n]) { + db->ptrs[n] = ptr; + ret = n; + goto out; + } + } + + /* No location available, grow the ptrs array */ + if (db->max_ptrs) + new_max_ptrs = db->max_ptrs * 2; + else + new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; + p = realloc(db->ptrs, new_max_ptrs * sizeof(void *)); + if (!p) { + ret = -1; + goto out; + } + db->ptrs = p; + memset(db->ptrs + db->max_ptrs, 0, + (new_max_ptrs - db->max_ptrs) * sizeof(void *)); + db->max_ptrs = new_max_ptrs; + + /* Since n stopped at db->max_ptrs there is an empty location there */ + db->ptrs[n] = ptr; + ret = n; + +out: + mutex_unlock(db); + return ret; +} + +void *handle_put(struct handle_db *db, int handle) +{ + void *p = NULL; + + if (!db || handle < 0) + return NULL; + + mutex_lock(db); + + if ((size_t)handle >= db->max_ptrs) { + p = NULL; + goto out; + } + + p = db->ptrs[handle]; + db->ptrs[handle] = NULL; + +out: + mutex_unlock(db); + return p; +} + +void *handle_lookup(struct handle_db *db, int handle) +{ + void *p = NULL; + + if (!db || handle < 0) + return NULL; + + mutex_lock(db); + + if ((size_t)handle >= db->max_ptrs) { + p = NULL; + goto out; + } + + p = db->ptrs[handle]; + +out: + mutex_unlock(db); + return p; +} + +void handle_foreach_put(struct handle_db *db, + void (*cb)(int handle, void *ptr, void *arg), + void *arg) +{ + size_t n = 0; + + if (!db || !cb) + return; + + mutex_lock(db); + + for (n = 0; n < db->max_ptrs; n++) { + if (db->ptrs[n]) { + cb(n, db->ptrs[n], arg); + db->ptrs[n] = NULL; + } + } + + mutex_unlock(db); +} diff --git a/optee/optee_client/tee-supplicant/src/handle.h b/optee/optee_client/tee-supplicant/src/handle.h new file mode 100644 index 0000000..5be5461 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/handle.h @@ -0,0 +1,82 @@ +/* + * 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 HANDLE_H +#define HANDLE_H + +#include +#include + +struct handle_db { + void **ptrs; + size_t max_ptrs; + pthread_mutex_t *mu; +}; + +#define HANDLE_DB_INITIALIZER { NULL, 0, NULL } +#define HANDLE_DB_INITIALIZER_WITH_MUTEX(mu) { NULL, 0, (mu) } + +/* + * Assigns a mutex for the database. If mu != NULL the mutex will be + * acquired before each access to the database and released when + * the operation is done. + */ +void handle_db_set_mutex(struct handle_db *db, pthread_mutex_t *mu); + +/* + * Frees all internal data structures of the database, but does not free + * the db pointer. The database is safe to reuse after it's destroyed, it + * just be empty again. The assigned mutex is also preserved. + */ +void handle_db_destroy(struct handle_db *db); + +/* + * Allocates a new handle and assigns the supplied pointer to it, + * ptr must not be NULL. + * The function returns + * >= 0 on success and + * -1 on failure + */ +int handle_get(struct handle_db *db, void *ptr); + +/* + * Deallocates a handle. Returns the assiciated pointer of the handle + * the the handle was valid or NULL if it's invalid. + */ +void *handle_put(struct handle_db *db, int handle); + +/* + * Returns the assiciated pointer of the handle if the handle is a valid + * handle. + * Returns NULL on failure. + */ +void *handle_lookup(struct handle_db *db, int handle); + +void handle_foreach_put(struct handle_db *db, + void (*cb)(int handle, void *ptr, void *arg), + void *arg); + +#endif /*HANDLE_H*/ diff --git a/optee/optee_client/tee-supplicant/src/hmac_sha2.c b/optee/optee_client/tee-supplicant/src/hmac_sha2.c new file mode 100644 index 0000000..20e994a --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/hmac_sha2.c @@ -0,0 +1,126 @@ +/* + * HMAC-SHA-224/256/384/512 implementation + * Last update: 06/15/2005 + * Issue date: 06/15/2005 + * + * Copyright (C) 2005 Olivier Gay + * All rights reserved. + * + * Copyright (c) 2016, 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. + * 3. Neither the name of the project 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 PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 "hmac_sha2.h" + +/* HMAC-SHA-256 functions */ + +void hmac_sha256_init(hmac_sha256_ctx *ctx, const unsigned char *key, + unsigned int key_size) +{ + unsigned int fill = 0; + unsigned int num = 0; + const unsigned char *key_used = NULL; + unsigned char key_temp[SHA256_DIGEST_SIZE] = { 0 }; + int i = 0; + + if (key_size == SHA256_BLOCK_SIZE) { + key_used = key; + num = SHA256_BLOCK_SIZE; + } else { + if (key_size > SHA256_BLOCK_SIZE){ + num = SHA256_DIGEST_SIZE; + sha256(key, key_size, key_temp); + key_used = key_temp; + } else { /* key_size > SHA256_BLOCK_SIZE */ + key_used = key; + num = key_size; + } + fill = SHA256_BLOCK_SIZE - num; + + memset(ctx->block_ipad + num, 0x36, fill); + memset(ctx->block_opad + num, 0x5c, fill); + } + + for (i = 0; i < (int) num; i++) { + ctx->block_ipad[i] = key_used[i] ^ 0x36; + ctx->block_opad[i] = key_used[i] ^ 0x5c; + } + + sha256_init(&ctx->ctx_inside); + sha256_update(&ctx->ctx_inside, ctx->block_ipad, SHA256_BLOCK_SIZE); + + sha256_init(&ctx->ctx_outside); + sha256_update(&ctx->ctx_outside, ctx->block_opad, + SHA256_BLOCK_SIZE); + + /* for hmac_reinit */ + memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside, + sizeof(sha256_ctx)); + memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside, + sizeof(sha256_ctx)); +} + +void hmac_sha256_reinit(hmac_sha256_ctx *ctx) +{ + memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit, + sizeof(sha256_ctx)); + memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit, + sizeof(sha256_ctx)); +} + +void hmac_sha256_update(hmac_sha256_ctx *ctx, const unsigned char *message, + unsigned int message_len) +{ + sha256_update(&ctx->ctx_inside, message, message_len); +} + +void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac, + unsigned int mac_size) +{ + unsigned char digest_inside[SHA256_DIGEST_SIZE] = { 0 }; + unsigned char mac_temp[SHA256_DIGEST_SIZE] = { 0 }; + + sha256_final(&ctx->ctx_inside, digest_inside); + sha256_update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_SIZE); + sha256_final(&ctx->ctx_outside, mac_temp); + memcpy(mac, mac_temp, mac_size); +} + +void hmac_sha256(const unsigned char *key, unsigned int key_size, + const unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size) +{ + hmac_sha256_ctx ctx; + + memset(&ctx, 0, sizeof(ctx)); + + hmac_sha256_init(&ctx, key, key_size); + hmac_sha256_update(&ctx, message, message_len); + hmac_sha256_final(&ctx, mac, mac_size); +} diff --git a/optee/optee_client/tee-supplicant/src/hmac_sha2.h b/optee/optee_client/tee-supplicant/src/hmac_sha2.h new file mode 100644 index 0000000..1044524 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/hmac_sha2.h @@ -0,0 +1,74 @@ +/* + * HMAC-SHA-224/256/384/512 implementation + * Last update: 06/15/2005 + * Issue date: 06/15/2005 + * + * Copyright (C) 2005 Olivier Gay + * All rights reserved. + * + * Copyright (c) 2016, 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. + * 3. Neither the name of the project 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 PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 HMAC_SHA2_H +#define HMAC_SHA2_H + +#include "sha2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + sha256_ctx ctx_inside; + sha256_ctx ctx_outside; + + /* for hmac_reinit */ + sha256_ctx ctx_inside_reinit; + sha256_ctx ctx_outside_reinit; + + unsigned char block_ipad[SHA256_BLOCK_SIZE]; + unsigned char block_opad[SHA256_BLOCK_SIZE]; +} hmac_sha256_ctx; + +void hmac_sha256_init(hmac_sha256_ctx *ctx, const unsigned char *key, + unsigned int key_size); +void hmac_sha256_reinit(hmac_sha256_ctx *ctx); +void hmac_sha256_update(hmac_sha256_ctx *ctx, const unsigned char *message, + unsigned int message_len); +void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac, + unsigned int mac_size); +void hmac_sha256(const unsigned char *key, unsigned int key_size, + const unsigned char *message, unsigned int message_len, + unsigned char *mac, unsigned mac_size); + +#ifdef __cplusplus +} +#endif + +#endif /* !HMAC_SHA2_H */ + diff --git a/optee/optee_client/tee-supplicant/src/nvme_rpmb.c b/optee/optee_client/tee-supplicant/src/nvme_rpmb.c new file mode 100644 index 0000000..e8e270f --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/nvme_rpmb.c @@ -0,0 +1,596 @@ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +struct nvme_psd_31{ + uint16_t mp; + uint8_t rsvd2; + uint8_t flags; + uint32_t enlat; + uint32_t exlat; + uint8_t rrt; + uint8_t rrl; + uint8_t rwt; + uint8_t rwl; + uint16_t idlp; + uint8_t ips; + uint8_t rsvd19; + uint16_t actp; + uint8_t apws; + uint8_t rsvd23[9]; +}; + +struct nvme_identify_controller { + uint16_t vid; + uint16_t ssvid; + char sn[20]; + char mn[40]; + char fr[8]; + uint8_t rab; + uint8_t ieee[3]; + uint8_t cmic; + uint8_t mdts; + uint16_t cntlid; + uint32_t ver; + uint32_t rtd3r; + uint32_t rtd3e; + uint32_t oaes; + uint32_t ctratt; + uint16_t rrls; + uint8_t rsvd102[9]; + uint8_t cntrltype; + uint8_t fguid[16]; + uint16_t crdt1; + uint16_t crdt2; + uint16_t crdt3; + uint8_t rsvd134[119]; + uint8_t nvmsr; + uint8_t vwci; + uint8_t mec; + uint16_t oacs; + uint8_t acl; + uint8_t aerl; + uint8_t frmw; + uint8_t lpa; + uint8_t elpe; + uint8_t npss; + uint8_t avscc; + uint8_t apsta; + uint16_t wctemp; + uint16_t cctemp; + uint16_t mtfa; + uint32_t hmpre; + uint32_t hmmin; + uint8_t tnvmcap[16]; + uint8_t unvmcap[16]; + uint32_t rpmbs; + uint16_t edstt; + uint8_t dsto; + uint8_t fwug; + uint16_t kas; + uint16_t hctma; + uint16_t mntmt; + uint16_t mxtmt; + uint32_t sanicap; + uint32_t hmminds; + uint16_t hmmaxd; + uint16_t nsetidmax; + uint16_t endgidmax; + uint8_t anatt; + uint8_t anacap; + uint32_t anagrpmax; + uint32_t nanagrpid; + uint32_t pels; + uint16_t domainid; + uint8_t rsvd358[10]; + uint8_t megcap[16]; + uint8_t rsvd384[128]; + uint8_t sqes; + uint8_t cqes; + uint16_t maxcmd; + uint32_t nn; + uint16_t oncs; + uint16_t fuses; + uint8_t fna; + uint8_t vwc; + uint16_t awun; + uint16_t awupf; + uint8_t icsvscc; + uint8_t nwpc; + uint16_t acwu; + uint16_t ocfs; + uint32_t sgls; + uint32_t mnan; + uint8_t maxdna[16]; + uint32_t maxcna; + uint8_t rsvd564[204]; + char subnqn[256]; + uint8_t rsvd1024[768]; + uint32_t ioccsz; + uint32_t iorcsz; + uint16_t icdoff; + uint8_t fcatt; + uint8_t msdbd; + uint16_t ofcs; + uint8_t dctype; + uint8_t rsvd1807[241]; + struct nvme_psd_31 psd[32]; + uint8_t vs[1024]; +}; + +/* identify command */ +#define NVME_IDENTIFY_CDW10_CNTID_SHIFT 16 +#define NVME_IDENTIFY_CDW10_CNS_SHIFT 0 +#define NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT 0 +#define NVME_IDENTIFY_CDW11_CSI_SHIFT 24 +#define NVME_IDENTIFY_CDW14_UUID_SHIFT 0 +#define NVME_IDENTIFY_CDW10_CNTID_MASK 0xffff +#define NVME_IDENTIFY_CDW10_CNS_MASK 0xff +#define NVME_IDENTIFY_CDW11_CNSSPECID_MASK 0xffff +#define NVME_IDENTIFY_CDW11_CSI_MASK 0xff +#define NVME_IDENTIFY_CDW14_UUID_MASK 0x7f + +#define NVME_IDENTIFY_CNS_CTRL 0x01 +#define NVME_CSI_NVM 0x0 +#define NVME_NSID_NONE 0x0 +#define NVME_CNTLID_NONE 0x0 +#define NVME_CNSSPECID_NONE 0x0 +#define NVME_UUID_NONE 0x0 + +#define NVME_DEV_SN_LENGTH 20 + +/* security comamnd */ +#define NVME_SECURITY_NSSF_SHIFT 0 +#define NVME_SECURITY_SPSP0_SHIFT 8 +#define NVME_SECURITY_SPSP1_SHIFT 16 +#define NVME_SECURITY_SECP_SHIFT 24 +#define NVME_SECURITY_NSSF_MASK 0xff +#define NVME_SECURITY_SPSP0_MASK 0xff +#define NVME_SECURITY_SPSP1_MASK 0xff +#define NVME_SECURITY_SECP_MASK 0xff + +#define NVME_RPMB_SECP 0xEA +#define NVME_RPMB_SPSP0 0x01 +#define NVME_RPMB_SPSP1 0x00 + +/* NVMe admin opcodes */ +#define NVME_ADMIN_IDENTIFY 0x06 +#define NVME_ADMIN_SECURITY_SEND 0x81 +#define NVME_ADMIN_SECURITY_RECV 0x82 + +#define NVME_IDENTIFY_DATA_SIZE 4096 + +/* default timeout */ +#define NVME_DEFAULT_IOCTL_TIMEOUT 0 + +/* Request */ +struct nvme_rpmb_req { + uint16_t cmd; +#define NVME_RPMB_CMD_DATA_REQ 0x00 +#define NVME_RPMB_CMD_GET_RPMBS_INFO 0x01 + uint16_t dev_id; + /* Optional data frames (rpmb_data_frame) follow */ +}; +#define NVME_RPMB_REQ_DATA(req) ((void *)((struct nvme_rpmb_req *)(req) + 1)) + +/* + * This structure is shared with OP-TEE and the NVMe ioctl layer. + * It is the "data frame for RPMB access" defined by NVMe spec, + * minus the start and stop bits. + */ +struct nvme_rpmb_data_frame { + uint8_t stuff_bytes[191]; + uint8_t key_mac[32]; + uint8_t target; + uint8_t nonce[16]; + uint32_t write_counter; + uint32_t address; + uint32_t block_count; + uint16_t op_result; +#define NVME_RPMB_RESULT_OK 0x00 +#define NVME_RPMB_RESULT_GENERAL_FAILURE 0x01 +#define NVME_RPMB_RESULT_AUTH_FAILURE 0x02 +#define NVME_RPMB_RESULT_COUNTER_FAILURE 0x03 +#define NVME_RPMB_RESULT_ADDRESS_FAILURE 0x04 +#define NVME_RPMB_RESULT_WRITE_FAILURE 0x05 +#define NVME_RPMB_RESULT_READ_FAILURE 0x06 +#define NVME_RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED 0x07 +#define NVME_RPMB_RESULT_INVALID_DEV_CONFIG_BLOCK 0x08 +#define NVME_RPMB_RESULT_MASK 0x3F +#define NVME_RPMB_RESULT_WR_CNT_EXPIRED 0x80 + uint16_t msg_type; +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM 0x0001 +#define NVME_RPMB_MSG_TYPE_REQ_WRITE_COUNTER_READ 0x0002 +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE 0x0003 +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_READ 0x0004 +#define NVME_RPMB_MSG_TYPE_REQ_RESULT_READ 0x0005 +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_DCB_WRITE 0x0006 +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_DCB_READ 0x0007 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM 0x0100 +#define NVME_RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ 0x0200 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE 0x0300 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_DATA_READ 0x0400 +#define NVME_RPMB_MSG_TYPE_RESP_RESULT_READ 0x0500 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_DCB_WRITE 0x0600 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_DCB_READ 0x0700 + uint8_t data[0]; +}; + +/* + * ioctl() interface + * Comes from: uapi/linux/nvme_ioctl.h + */ +struct nvme_passthru_cmd { + __u8 opcode; + __u8 flags; + __u16 rsvd1; + __u32 nsid; + __u32 cdw2; + __u32 cdw3; + __u64 metadata; + __u64 addr; + __u32 metadata_len; + __u32 data_len; + __u32 cdw10; + __u32 cdw11; + __u32 cdw12; + __u32 cdw13; + __u32 cdw14; + __u32 cdw15; + __u32 timeout_ms; + __u32 result; +}; + +#define nvme_admin_cmd nvme_passthru_cmd + +#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_admin_cmd) + +static pthread_mutex_t nvme_rpmb_mutex = PTHREAD_MUTEX_INITIALIZER; + +struct nvme_dev_info { + unsigned int rpmbs; + char sn[NVME_DEV_SN_LENGTH + 1]; +}; + +static TEEC_Result nvme_identify_command(int fd, struct nvme_identify_controller *id) +{ + uint32_t cdw10 = (((NVME_CNTLID_NONE << NVME_IDENTIFY_CDW10_CNTID_SHIFT)) + & NVME_IDENTIFY_CDW10_CNTID_MASK) + | (((NVME_IDENTIFY_CNS_CTRL << NVME_IDENTIFY_CDW10_CNS_SHIFT)) + & NVME_IDENTIFY_CDW10_CNS_MASK); + uint32_t cdw11 = (((NVME_CNSSPECID_NONE << NVME_IDENTIFY_CDW11_CNSSPECID_SHIFT)) + & NVME_IDENTIFY_CDW11_CNSSPECID_MASK) + | (((NVME_CSI_NVM << NVME_IDENTIFY_CDW11_CSI_SHIFT)) + & NVME_IDENTIFY_CDW11_CSI_MASK); + uint32_t cdw14 = (NVME_UUID_NONE << NVME_IDENTIFY_CDW14_UUID_SHIFT) + & NVME_IDENTIFY_CDW14_UUID_MASK; + + struct nvme_passthru_cmd cmd = { + .opcode = NVME_ADMIN_IDENTIFY, + .nsid = NVME_NSID_NONE, + .addr = (uint64_t)(uintptr_t)id, + .data_len = NVME_IDENTIFY_DATA_SIZE, + .cdw10 = cdw10, + .cdw11 = cdw11, + .cdw14 = cdw14, + .timeout_ms = NVME_DEFAULT_IOCTL_TIMEOUT, + }; + + int err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, cmd); + if (err != 0) { + EMSG("Failed to get get nvme rpmb support info\n"); + return TEEC_ERROR_GENERIC; + } + + return TEEC_SUCCESS; +} + +static TEEC_Result nvme_security_command(int fd, uint8_t opcode, uint32_t nsid, + uint32_t cdw10, uint32_t cdw11, void *data, uint32_t data_len) { + struct nvme_passthru_cmd cmd = { + .opcode = opcode, + .nsid = nsid, + .cdw10 = cdw10, + .cdw11 = cdw11, + .data_len = data_len, + .addr = (uint64_t)(uintptr_t)data, + .timeout_ms = NVME_DEFAULT_IOCTL_TIMEOUT, + }; + + int err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, cmd); + if (err != 0) { + EMSG("Failed to send nvme security command with err = %d\n", err); + return TEEC_ERROR_GENERIC; + } + + return TEEC_SUCCESS; +} + +static TEEC_Result nvme_security_send(int fd, uint32_t nsid, + uint32_t cdw10, uint32_t cdw11, void *data, uint32_t data_len) +{ + return nvme_security_command(fd, NVME_ADMIN_SECURITY_SEND, + nsid, cdw10, cdw11, data, data_len); +} + +static TEEC_Result nvme_security_receive(int fd, uint32_t nsid, + uint32_t cdw10, uint32_t cdw11, void *data, uint32_t data_len) +{ + return nvme_security_command(fd, NVME_ADMIN_SECURITY_RECV, + nsid, cdw10, cdw11, data, data_len); +} + +static TEEC_Result rpmb_read_request(int fd, + struct nvme_rpmb_data_frame *req, size_t req_size, + struct nvme_rpmb_data_frame *rsp, size_t rsp_size) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint8_t nssf = req->target; + uint8_t spsp0 = NVME_RPMB_SPSP0; + uint8_t spsp1 = NVME_RPMB_SPSP1; + uint8_t secp = NVME_RPMB_SECP; + uint32_t cdw10; + uint32_t cdw11; + + cdw10 = (((nssf & NVME_SECURITY_NSSF_MASK) << NVME_SECURITY_NSSF_SHIFT) + | ((spsp0 & NVME_SECURITY_SPSP0_MASK) << NVME_SECURITY_SPSP0_SHIFT) + | ((spsp1 & NVME_SECURITY_SPSP1_MASK) << NVME_SECURITY_SPSP1_SHIFT) + | ((secp & NVME_SECURITY_SECP_MASK) << NVME_SECURITY_SECP_SHIFT)); + cdw11 = req_size; + + res = nvme_security_send(fd, 0, cdw10, cdw11, (void *)req, (uint32_t)req_size); + if (res) { + EMSG("Send security cmd error with res = 0x%08x\n", res); + goto error_out; + } + + cdw11 = rsp_size; + res = nvme_security_receive(fd, 0, cdw10, cdw11, (void *)rsp, (uint32_t)rsp_size); + if (res) { + EMSG("Receive security cmd error with res = 0x%08x\n", res); + goto error_out; + } + +error_out: + return res; +} + +static TEEC_Result rpmb_write_request(int fd, + struct nvme_rpmb_data_frame *req, size_t req_size, + struct nvme_rpmb_data_frame *rsp, size_t rsp_size) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint8_t nssf = req->target; + uint8_t spsp0 = NVME_RPMB_SPSP0; + uint8_t spsp1 = NVME_RPMB_SPSP1; + uint8_t secp = NVME_RPMB_SECP; + uint32_t cdw10; + uint32_t cdw11; + + cdw10 = (((nssf & NVME_SECURITY_NSSF_MASK) << NVME_SECURITY_NSSF_SHIFT) + | ((spsp0 & NVME_SECURITY_SPSP0_MASK) << NVME_SECURITY_SPSP0_SHIFT) + | ((spsp1 & NVME_SECURITY_SPSP1_MASK) << NVME_SECURITY_SPSP1_SHIFT) + | ((secp & NVME_SECURITY_SECP_MASK) << NVME_SECURITY_SECP_SHIFT)); + cdw11 = req_size; + + res = nvme_security_send(fd, 0, cdw10, cdw11, (void *)req, (uint32_t)req_size); + if (res) { + EMSG("send security cmd error with res = 0x%08x\n", res); + goto error_out; + } + + memset(rsp, 0, sizeof(struct nvme_rpmb_data_frame)); + rsp->target = req->target; + rsp->msg_type = NVME_RPMB_MSG_TYPE_REQ_RESULT_READ; + cdw11 = rsp_size; + res = nvme_security_send(fd, 0, cdw10, cdw11, (void *)rsp, (uint32_t)rsp_size); + if (res) { + EMSG("send security cmd error with res = 0x%08x\n", res); + goto error_out; + } + + memset(rsp, 0, rsp_size); + res = nvme_security_receive(fd, 0, cdw10, cdw11, (void *)rsp, (uint32_t)rsp_size); + if (res || rsp->op_result != 0) { + EMSG("receive security cmd error with res = 0x%08x\n", res); + goto error_out; + } + +error_out: + return res; +} + +/* Open and/or return file descriptor to RPMB partition of device dev_id */ +static int open_nvme_rpmb_fd(uint16_t dev_id) +{ + static int id; + static int fd = -1; + char path[PATH_MAX] = { 0 }; + + DMSG("dev_id = %u", dev_id); + if (fd < 0) { + snprintf(path, sizeof(path), "/dev/nvme%u", dev_id); + fd = open(path, O_RDWR); + if (fd < 0) { + EMSG("Could not open %s (%s)", path, strerror(errno)); + return -1; + } + id = dev_id; + } + if (id != dev_id) { + EMSG("Only one NVMe device is supported"); + return -1; + } + return fd; +} + +/* Open NVMe device dev_id */ +static int nvme_fd(uint16_t dev_id) +{ + int fd = 0; + char path[PATH_MAX] = { 0 }; + + IMSG("NVMe dev_id = %u", dev_id); + snprintf(path, sizeof(path), "/dev/nvme%u", dev_id); + fd = open(path, O_RDONLY); + if (fd < 0) + EMSG("Could not open %s\n", path); + + return fd; +} + +static void close_nvme_fd(int fd) +{ + close(fd); +} + +static TEEC_Result nvme_rpmb_get_rpmbs_info(uint16_t dev_id, struct nvme_dev_info *info) +{ + int fd = 0; + TEEC_Result res = TEEC_ERROR_GENERIC; + struct nvme_identify_controller id; + + memset(info, 0, sizeof(struct nvme_dev_info)); + + fd = nvme_fd(dev_id); + if (fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + res = nvme_identify_command(fd, &id); + if (res != TEEC_SUCCESS) + goto out; + + memcpy(info->sn, id.sn, NVME_DEV_SN_LENGTH); + info->rpmbs = id.rpmbs; + +out: + close_nvme_fd(fd); + return res; +} + +static TEEC_Result nvme_rpmb_data_req(int fd, + struct nvme_rpmb_data_frame *req, size_t req_size, + struct nvme_rpmb_data_frame *rsp, size_t rsp_size) +{ + TEEC_Result res; + + switch (req->msg_type) { + case NVME_RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM: + case NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: + case NVME_RPMB_MSG_TYPE_REQ_AUTH_DCB_WRITE: + res = rpmb_write_request(fd, req, req_size, rsp, rsp_size); + break; + case NVME_RPMB_MSG_TYPE_REQ_WRITE_COUNTER_READ: + case NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: + case NVME_RPMB_MSG_TYPE_REQ_AUTH_DCB_READ: + res = rpmb_read_request(fd, req, req_size, rsp, rsp_size); + break; + default: + EMSG("command 0x%08x not support\n", req->msg_type); + res = TEEC_ERROR_BAD_PARAMETERS; + break; + } + + return res; +} + +/* + * req is one struct rpmb_req followed by one struct nvme_rpmb_data_frame + * rsp is either one struct nvme_dev_info or one nvme_rpmb_data_frame + */ +static TEEC_Result nvme_rpmb_process_request_unlocked( + void *req, size_t req_size, + void *rsp, size_t rsp_size) +{ + uint32_t res = TEEC_ERROR_GENERIC; + struct nvme_rpmb_req *sreq = req; + int fd = 0; + + if (req_size < sizeof(struct nvme_rpmb_req)) + return TEEC_ERROR_BAD_PARAMETERS; + + switch (sreq->cmd) { + case NVME_RPMB_CMD_DATA_REQ: + /* + * To ensure only one device can be used, we will not close the device + * after it is opened. + */ + fd = open_nvme_rpmb_fd(sreq->dev_id); + if (fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + res = nvme_rpmb_data_req(fd, NVME_RPMB_REQ_DATA(req), + req_size - sizeof(struct nvme_rpmb_req), rsp, rsp_size); + break; + + case NVME_RPMB_CMD_GET_RPMBS_INFO: + if (req_size != sizeof(struct nvme_rpmb_req) || + rsp_size != sizeof(struct nvme_dev_info)) { + EMSG("Invalid req/rsp size"); + return TEEC_ERROR_BAD_PARAMETERS; + } + res = nvme_rpmb_get_rpmbs_info(sreq->dev_id, (struct nvme_dev_info *)rsp); + break; + + default: + EMSG("Unsupported RPMB command: %d", sreq->cmd); + res = TEEC_ERROR_BAD_PARAMETERS; + break; + } + + return res; +} + + +TEEC_Result nvme_rpmb_process_request(void *req, size_t req_size, + void *rsp, size_t rsp_size) +{ + uint32_t res = 0; + + tee_supp_mutex_lock(&nvme_rpmb_mutex); + res = nvme_rpmb_process_request_unlocked(req, req_size, rsp, rsp_size); + tee_supp_mutex_unlock(&nvme_rpmb_mutex); + + return res; +} diff --git a/optee/optee_client/tee-supplicant/src/nvme_rpmb.h b/optee/optee_client/tee-supplicant/src/nvme_rpmb.h new file mode 100644 index 0000000..cf65f16 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/nvme_rpmb.h @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + + +#ifndef NVME_RPMB_H +#define NVME_RPMB_H + +#include +#include + +uint32_t nvme_rpmb_process_request(void *req, size_t req_size, void *rsp, + size_t rsp_size); + +#endif /* NVME_RPMB_H */ diff --git a/optee/optee_client/tee-supplicant/src/optee_msg_supplicant.h b/optee/optee_client/tee-supplicant/src/optee_msg_supplicant.h new file mode 100644 index 0000000..ab94abe --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/optee_msg_supplicant.h @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2016-2017, Linaro Limited + * All rights reserved. + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 __OPTEE_MSG_SUPPLICANT_H +#define __OPTEE_MSG_SUPPLICANT_H + +/* + * Load a TA into memory + */ +#define OPTEE_MSG_RPC_CMD_LOAD_TA 0 + +/* + * Replay Protected Memory Block access + */ +#define OPTEE_MSG_RPC_CMD_RPMB 1 + +/* + * File system access + */ +#define OPTEE_MSG_RPC_CMD_FS 2 + +/* + * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_FS and first + * parameter has the attribute OPTEE_MSG_ATTR_TYPE_VALUE_INPUT. + */ + +/* + * Open a file + * + * [in] param[0].u.value.a OPTEE_MRF_OPEN + * [in] param[1].u.tmem a string holding the file name + * [out] param[2].u.value.a file descriptor of open file + */ +#define OPTEE_MRF_OPEN 0 + +/* + * Create a file + * + * [in] param[0].u.value.a OPTEE_MRF_CREATE + * [in] param[1].u.tmem a string holding the file name + * [out] param[2].u.value.a file descriptor of open file + */ +#define OPTEE_MRF_CREATE 1 + +/* + * Close a file + * + * [in] param[0].u.value.a OPTEE_MRF_CLOSE + * [in] param[0].u.value.b file descriptor of open file. + */ +#define OPTEE_MRF_CLOSE 2 + +/* + * Read from a file + * + * [in] param[0].u.value.a OPTEE_MRF_READ + * [in] param[0].u.value.b file descriptor of open file + * [in] param[0].u.value.c offset into file + * [out] param[1].u.tmem buffer to hold returned data + */ +#define OPTEE_MRF_READ 3 + +/* + * Write to a file + * + * [in] param[0].u.value.a OPTEE_MRF_WRITE + * [in] param[0].u.value.b file descriptor of open file + * [in] param[0].u.value.c offset into file + * [in] param[1].u.tmem buffer holding data to be written + */ +#define OPTEE_MRF_WRITE 4 + +/* + * Truncate a file + * + * [in] param[0].u.value.a OPTEE_MRF_TRUNCATE + * [in] param[0].u.value.b file descriptor of open file + * [in] param[0].u.value.c length of file. + */ +#define OPTEE_MRF_TRUNCATE 5 + +/* + * Remove a file + * + * [in] param[0].u.value.a OPTEE_MRF_REMOVE + * [in] param[1].u.tmem a string holding the file name + */ +#define OPTEE_MRF_REMOVE 6 + +/* + * Rename a file + * + * [in] param[0].u.value.a OPTEE_MRF_RENAME + * [in] param[0].u.value.b true if existing target should be removed + * [in] param[1].u.tmem a string holding the old file name + * [in] param[2].u.tmem a string holding the new file name + */ +#define OPTEE_MRF_RENAME 7 + +/* + * Opens a directory for file listing + * + * [in] param[0].u.value.a OPTEE_MRF_OPENDIR + * [in] param[1].u.tmem a string holding the name of the directory + * [out] param[2].u.value.a handle to open directory + */ +#define OPTEE_MRF_OPENDIR 8 + +/* + * Closes a directory handle + * + * [in] param[0].u.value.a OPTEE_MRF_CLOSEDIR + * [in] param[0].u.value.b handle to open directory + */ +#define OPTEE_MRF_CLOSEDIR 9 + +/* + * Read next file name of directory + * + * + * [in] param[0].u.value.a OPTEE_MRF_READDIR + * [in] param[0].u.value.b handle to open directory + * [out] param[1].u.tmem a string holding the file name + */ +#define OPTEE_MRF_READDIR 10 + +/* + * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_FS + */ + +/* + * Command Ids 3, 4 and 5 of OPTEE_MSG_RPC_CMD_xxx macros are reserved for use + * by the kernel driver. + */ + +/* + * Shared memory allocation + */ +#define OPTEE_MSG_RPC_CMD_SHM_ALLOC 6 +#define OPTEE_MSG_RPC_CMD_SHM_FREE 7 + +/* + * Was OPTEE_MSG_RPC_CMD_SQL_FS, which isn't supported any longer + */ +#define OPTEE_MSG_RPC_CMD_SQL_FS_RESERVED 8 + +/* + * GPROF support management commands + */ +#define OPTEE_MSG_RPC_CMD_GPROF 9 + +/* + * Socket commands + */ +#define OPTEE_MSG_RPC_CMD_SOCKET 10 + +/* + * Function tracing support management commands + */ +#define OPTEE_MSG_RPC_CMD_FTRACE 11 + +/* + * Plugin commands + */ +#define OPTEE_MSG_RPC_CMD_PLUGIN 12 + +/* + * NVMe Replay Protected Memory Block access + */ +#define OPTEE_MSG_RPC_CMD_NVME_RPMB 13 + +/* + * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET + */ + +#define OPTEE_MRC_SOCKET_TIMEOUT_NONBLOCKING 0 +#define OPTEE_MRC_SOCKET_TIMEOUT_BLOCKING 0xffffffff + +/* + * Open socket + * + * [in] param[0].u.value.a OPTEE_MRC_SOCKET_OPEN + * [in] param[0].u.value.b TA instance id + * [in] param[1].u.value.a server port number + * [in] param[1].u.value.b protocol, TEE_ISOCKET_PROTOCOLID_* + * [in] param[1].u.value.c ip version TEE_IP_VERSION_* from tee_ipsocket.h + * [in] param[2].u.tmem server address + * [out] param[3].u.value.a socket handle (32-bit) + */ +#define OPTEE_MRC_SOCKET_OPEN 0 + +/* + * Close socket + * + * [in] param[0].u.value.a OPTEE_MRC_SOCKET_CLOSE + * [in] param[0].u.value.b TA instance id + * [in] param[0].u.value.c socket handle + */ +#define OPTEE_MRC_SOCKET_CLOSE 1 + +/* + * Close all sockets + * + * [in] param[0].u.value.a OPTEE_MRC_SOCKET_CLOSE_ALL + * [in] param[0].u.value.b TA instance id + */ +#define OPTEE_MRC_SOCKET_CLOSE_ALL 2 + +/* + * Send data on socket + * + * [in] param[0].u.value.a OPTEE_MRC_SOCKET_SEND + * [in] param[0].u.value.b TA instance id + * [in] param[0].u.value.c socket handle + * [in] param[1].u.tmem buffer to transmit + * [in] param[2].u.value.a timeout ms or OPTEE_MRC_SOCKET_TIMEOUT_* + * [out] param[2].u.value.b number of transmitted bytes + */ +#define OPTEE_MRC_SOCKET_SEND 3 + +/* + * Receive data on socket + * + * [in] param[0].u.value.a OPTEE_MRC_SOCKET_RECV + * [in] param[0].u.value.b TA instance id + * [in] param[0].u.value.c socket handle + * [out] param[1].u.tmem buffer to receive + * [in] param[2].u.value.a timeout ms or OPTEE_MRC_SOCKET_TIMEOUT_* + */ +#define OPTEE_MRC_SOCKET_RECV 4 + +/* + * Perform IOCTL on socket + * + * [in] param[0].u.value.a OPTEE_MRC_SOCKET_IOCTL + * [in] param[0].u.value.b TA instance id + * [in] param[0].u.value.c socket handle + * [in/out] param[1].u.tmem buffer + * [in] param[2].u.value.a ioctl command + */ +#define OPTEE_MRC_SOCKET_IOCTL 5 + +/* + * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_SOCKET + */ + +/* + * Define protocol for messages with .cmd == OPTEE_MSG_RPC_CMD_PLUGIN + */ + +/* + * Invoke a tee-supplicant plugin. + * + * [in] param[0].u.value.a OPTEE_INVOKE_PLUGIN + * [in] param[0].u.value.b uuid.d1 + * [in] param[0].u.value.c uuid.d2 + * [in] param[1].u.value.a uuid.d3 + * [in] param[1].u.value.b uuid.d4 + * [in] param[1].u.value.c cmd for plugin + * [in] param[2].u.value.a sub_cmd for plugin + * [out] param[2].u.value.b length of the outbuf (param[3]), + * if out is needed. + * [in/out] param[3].u.tmem buffer holding data for plugin + * + * UUID serialized into octets: + * b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 + * d1 | d2 | d3 | d4 + * + * The endianness of words d1, d2, d3 and d4 from SWd is little-endian. + * d1 word contains [b3 b2 b1 b0] + * d2 word contains [b7 b6 b5 b4] + * d3 word contains [b11 b10 b9 b8] + * d4 word contains [b15 b14 b13 b12] + */ +#define OPTEE_INVOKE_PLUGIN 0 + +/* + * End of definitions for messages with .cmd == OPTEE_MSG_RPC_CMD_PLUGIN + */ + +#endif /*__OPTEE_MSG_SUPPLICANT_H*/ diff --git a/optee/optee_client/tee-supplicant/src/plugin.c b/optee/optee_client/tee-supplicant/src/plugin.c new file mode 100644 index 0000000..cca22a1 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/plugin.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "optee_msg_supplicant.h" + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif +#include + +/* internal possible returned values */ +enum plugin_err { + PLUGIN_OK = 0, + PLUGIN_DL_OPEN_ERR = -1, + PLUGIN_DL_SYM_ERR = -2, +}; + +static struct plugin *plugin_list_head; + +/* returns 0, if u1 and u2 are equal */ +static int uuid_cmp(TEEC_UUID *u1, TEEC_UUID *u2) +{ + if (!memcmp(u1, u2, sizeof(TEEC_UUID))) + return 0; + + return 1; +} + +static void uuid_from_octets(TEEC_UUID *d, const uint8_t s[TEE_IOCTL_UUID_LEN]) +{ + d->timeLow = ((uint32_t)s[0] << 24) | ((uint32_t)s[1] << 16) | + ((uint32_t)s[2] << 8) | s[3]; + d->timeMid = ((uint32_t)s[4] << 8) | s[5]; + d->timeHiAndVersion = ((uint32_t)s[6] << 8) | s[7]; + memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode)); +} + +static void push_plugin(struct plugin *p) +{ + p->next = plugin_list_head; + plugin_list_head = p; +} + +static struct plugin *find_plugin(TEEC_UUID *u) +{ + struct plugin *p = plugin_list_head; + + while (p) { + if (!uuid_cmp(&p->method->uuid, u)) + return p; + + p = p->next; + } + + return NULL; +} + +static enum plugin_err load_plugin(const char *name, struct plugin *p) +{ + void *handle = NULL; + struct plugin_method *m = NULL; + + handle = dlopen(name, RTLD_LAZY); + if (!handle) + return PLUGIN_DL_OPEN_ERR; + + m = (struct plugin_method *)dlsym(handle, "plugin_method"); + if (!m || !m->name || !m->invoke) { + dlclose(handle); + return PLUGIN_DL_SYM_ERR; + } + + p->handle = handle; + p->method = m; + + return PLUGIN_OK; +} + +static TEEC_Result plugin_invoke(TEEC_UUID *u, unsigned int cmd, + unsigned int sub_cmd, void *data, + size_t in_len, size_t *out_len) +{ + struct plugin *p = NULL; + + p = find_plugin(u); + if (!p) + return TEEC_ERROR_ITEM_NOT_FOUND; + + assert(p->method->invoke); + + return p->method->invoke(cmd, sub_cmd, data, in_len, out_len); +} + +TEEC_Result plugin_load_all(void) +{ + DIR *dir = NULL; + enum plugin_err res = PLUGIN_OK; + TEEC_Result teec_res = TEEC_SUCCESS; + struct dirent *entry = NULL; + char path[PATH_MAX] = { 0 }; + + dir = opendir(supplicant_params.plugin_load_path); + + if (!dir) { + IMSG("could not open directory %s", supplicant_params.plugin_load_path); + + /* don't generate error if there is no the dir */ + return TEEC_SUCCESS; + } + + while ((entry = readdir(dir))) { + struct plugin *p; + int r; + + if (!strcmp(entry->d_name, "..") || !strcmp(entry->d_name, ".")) + continue; + + p = calloc(1, sizeof(struct plugin)); + if (!p) { + EMSG("allocate mem for plugin <%s> failed", + entry->d_name); + closedir(dir); + return TEEC_ERROR_OUT_OF_MEMORY; + } + r = snprintf(path, sizeof(path), "%s/%s", + supplicant_params.plugin_load_path, entry->d_name); + if (r < 0 || r >= (int)sizeof(path)) { + EMSG("assemble of full path for plugin <%s> failed", + entry->d_name); + closedir(dir); + return TEEC_ERROR_GENERIC ; + } + res = load_plugin(path, p); + switch (res) { + case PLUGIN_DL_OPEN_ERR: + EMSG("open plugin <%s> failed: %s", + entry->d_name, dlerror()); + free(p); + continue; + case PLUGIN_DL_SYM_ERR: + EMSG("find 'plugin_method' sym in <%s> failed: %s", + entry->d_name, dlerror()); + free(p); + continue; + default: + DMSG("loading the <%s> plugin were successful", + p->method->name); + break; + } + + /* Init the plugin */ + if (p->method->init) { + teec_res = p->method->init(); + if (teec_res) { + EMSG("init the <%s> plugin failed with 0x%x", + p->method->name, teec_res); + free(p); + continue; + } + } + + push_plugin(p); + } + + closedir(dir); + return TEEC_SUCCESS; +} + +TEEC_Result plugin_process(size_t num_params, struct tee_ioctl_param *params) +{ + unsigned int cmd = 0; + unsigned int sub_cmd = 0; + void *data = NULL; + uint32_t data_len = 0; + TEEC_UUID uuid = { }; + uint32_t uuid_words[4] = { }; + size_t outlen = 0; + TEEC_Result res = TEEC_ERROR_NOT_SUPPORTED; + + if (num_params != 4 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT || + (params[3].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT) + return TEEC_ERROR_BAD_PARAMETERS; + + uuid_words[0] = params[0].b; + uuid_words[1] = params[0].c; + uuid_words[2] = params[1].a; + uuid_words[3] = params[1].b; + + uuid_from_octets(&uuid, (const uint8_t *)uuid_words); + + cmd = params[1].c; + sub_cmd = params[2].a; + + data = tee_supp_param_to_va(params + 3); + data_len = MEMREF_SIZE(params + 3); + + if (data_len && !data) + return TEEC_ERROR_BAD_PARAMETERS; + + switch (params[0].a) { + case OPTEE_INVOKE_PLUGIN: + res = plugin_invoke(&uuid, cmd, sub_cmd, data, data_len, + &outlen); + params[2].b = outlen; + default: + break; + } + + return res; +} diff --git a/optee/optee_client/tee-supplicant/src/plugin.h b/optee/optee_client/tee-supplicant/src/plugin.h new file mode 100644 index 0000000..f0ee829 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/plugin.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#ifndef PLUGIN_H +#define PLUGIN_H + +#include +#include +#include + +struct tee_ioctl_param; + +/* This structure describes one plugin for the supplicant */ +struct plugin { + void *handle; + struct plugin_method *method; /* Implemented in the plugin */ + struct plugin *next; +}; + +#ifdef TEE_SUPP_PLUGINS +/* + * Loads all shared objects from 'CFG_TEE_PLUGIN_LOAD_PATH' + * and binds all functions. + * + * @return 'TEEC_SUCCESS' if all plugins were successfully loaded. + */ +TEEC_Result plugin_load_all(void); + +/* Plugin RPC handler */ +TEEC_Result plugin_process(size_t num_params, struct tee_ioctl_param *params); +#else +static inline TEEC_Result plugin_load_all(void) +{ + return TEEC_SUCCESS; +} + +static inline TEEC_Result plugin_process(size_t num_params, + struct tee_ioctl_param *params) +{ + (void)num_params; + (void)params; + + return TEEC_ERROR_NOT_SUPPORTED; +} +#endif /*TEE_SUPP_PLUGINS*/ + +#endif /* PLUGIN_H */ + diff --git a/optee/optee_client/tee-supplicant/src/prof.c b/optee/optee_client/tee-supplicant/src/prof.c new file mode 100644 index 0000000..3a3056e --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/prof.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016, 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 +#include +#include +#include +#include +#include +#include +#include +#include "prof.h" + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif +#include + +TEEC_Result prof_process(size_t num_params, struct tee_ioctl_param *params, + const char *prefix) +{ + char vers[5] = ""; + char path[255] = { 0 }; + size_t bufsize = 0; + TEEC_UUID *u = NULL; + int fd = -1; + void *buf = NULL; + int flags = 0; + int id = 0; + int st = 0; + int n = 0; + + if (num_params != 3 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || + (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + id = params[0].a; + + if (MEMREF_SIZE(params + 1) != sizeof(TEEC_UUID)) + return TEEC_ERROR_BAD_PARAMETERS; + + u = tee_supp_param_to_va(params + 1); + if (!u) + return TEEC_ERROR_BAD_PARAMETERS; + + buf = tee_supp_param_to_va(params + 2); + if (!buf) + return TEEC_ERROR_BAD_PARAMETERS; + + bufsize = MEMREF_SIZE(params + 2); + + if (id < 0 || id > 100) + return TEEC_ERROR_BAD_PARAMETERS; + + flags = O_APPEND | O_WRONLY; + if (!id) { + /* id == 0 means create file */ + flags |= O_CREAT | O_EXCL; + id = 1; + } + + for (;;) { + if (id > 1) { + /* + * id == 1 is file 0 (no suffix), id == 2 is file .1 + * etc. + */ + if (id > 100) + id = 100; /* Avoid GCC truncation warning */ + snprintf(vers, sizeof(vers), ".%d", id - 1); + } + n = snprintf(path, sizeof(path), + "/tmp/%s" + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" + "%s.out", + prefix, + u->timeLow, u->timeMid, u->timeHiAndVersion, + u->clockSeqAndNode[0], u->clockSeqAndNode[1], + u->clockSeqAndNode[2], u->clockSeqAndNode[3], + u->clockSeqAndNode[4], u->clockSeqAndNode[5], + u->clockSeqAndNode[6], u->clockSeqAndNode[7], + vers); + if ((n < 0) || (n >= (int)sizeof(path))) + break; + fd = open(path, flags, 0644); + if (fd >= 0) { + do { + st = write(fd, buf, bufsize); + } while (st < 0 && errno == EINTR); + close(fd); + if (st < 0 || st != (int)bufsize) + break; + params[0].a = id; + goto success; + } + if (errno != EEXIST) + break; + if (id++ == 100) + break; + } + + /* An error occurred */ + return TEEC_ERROR_GENERIC; + +success: + return TEEC_SUCCESS; +} diff --git a/optee/optee_client/tee-supplicant/src/prof.h b/optee/optee_client/tee-supplicant/src/prof.h new file mode 100644 index 0000000..48c8993 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/prof.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, 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 PROF_H +#define PROF_H + +#include + +struct tee_ioctl_param; + +#if defined(CFG_TA_GPROF_SUPPORT) || defined(CFG_FTRACE_SUPPORT) + +TEEC_Result prof_process(size_t num_params, struct tee_ioctl_param *params, + const char *prefix); + +#else + +static inline TEEC_Result prof_process(size_t num_params, + struct tee_ioctl_param *params, + const char *prefix) +{ + (void)num_params; + (void)params; + (void)prefix; + + return TEEC_ERROR_NOT_SUPPORTED; +} + +#endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */ +#endif /* PROF_H */ diff --git a/optee/optee_client/tee-supplicant/src/rpmb.c b/optee/optee_client/tee-supplicant/src/rpmb.c new file mode 100644 index 0000000..7643ed6 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/rpmb.c @@ -0,0 +1,989 @@ +/* + * Copyright (c) 2016, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RPMB_EMU +#include +#include "hmac_sha2.h" +#else +#include +#endif + +/* + * Request and response definitions must be in sync with the secure side + */ + +/* Request */ +struct rpmb_req { + uint16_t cmd; +#define RPMB_CMD_DATA_REQ 0x00 +#define RPMB_CMD_GET_DEV_INFO 0x01 + uint16_t dev_id; + uint16_t block_count; + /* Optional data frames (rpmb_data_frame) follow */ +}; +#define RPMB_REQ_DATA(req) ((void *)((struct rpmb_req *)(req) + 1)) + +#define RPMB_CID_SZ 16 + +/* Response to device info request */ +struct rpmb_dev_info { + uint8_t cid[RPMB_CID_SZ]; + uint8_t rpmb_size_mult; /* EXT CSD-slice 168: RPMB Size */ + uint8_t rel_wr_sec_c; /* EXT CSD-slice 222: Reliable Write Sector */ + /* Count */ + uint8_t ret_code; +#define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00 +#define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01 +}; + +/* + * This structure is shared with OP-TEE and the MMC ioctl layer. + * It is the "data frame for RPMB access" defined by JEDEC, minus the + * start and stop bits. + */ +struct rpmb_data_frame { + uint8_t stuff_bytes[196]; + uint8_t key_mac[32]; + uint8_t data[256]; + uint8_t nonce[16]; + uint32_t write_counter; + uint16_t address; + uint16_t block_count; + uint16_t op_result; +#define RPMB_RESULT_OK 0x00 +#define RPMB_RESULT_GENERAL_FAILURE 0x01 +#define RPMB_RESULT_AUTH_FAILURE 0x02 +#define RPMB_RESULT_ADDRESS_FAILURE 0x04 +#define RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED 0x07 + uint16_t msg_type; +#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 +}; + + +static pthread_mutex_t rpmb_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* + * ioctl() interface + * Comes from: uapi/linux/major.h, linux/mmc/core.h + */ + +#define MMC_BLOCK_MAJOR 179 + +/* mmc_ioc_cmd.opcode */ +#define MMC_READ_MULTIPLE_BLOCK 18 +#define MMC_WRITE_MULTIPLE_BLOCK 25 + +/* mmc_ioc_cmd.flags */ +#define MMC_RSP_PRESENT (1 << 0) +#define MMC_RSP_136 (1 << 1) /* 136 bit response */ +#define MMC_RSP_CRC (1 << 2) /* Expect valid CRC */ +#define MMC_RSP_OPCODE (1 << 4) /* Response contains opcode */ + +#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE) + +#define MMC_CMD_ADTC (1 << 5) /* Addressed data transfer command */ + +/* mmc_ioc_cmd.write_flag */ +#define MMC_CMD23_ARG_REL_WR (1 << 31) /* CMD23 reliable write */ + +/* Maximum number of commands used in a multiple ioc command request */ +#define RPMB_MAX_IOC_MULTI_CMDS 3 + +#ifndef RPMB_EMU + +#define IOCTL(fd, request, ...) \ + ({ \ + int ret; \ + ret = ioctl((fd), (request), ##__VA_ARGS__); \ + if (ret < 0) \ + EMSG("ioctl ret=%d errno=%d", ret, errno); \ + ret; \ + }) + + +/* Open and/or return file descriptor to RPMB partition of device dev_id */ +static int mmc_rpmb_fd(uint16_t dev_id) +{ + static int id; + static int fd = -1; + char path[PATH_MAX] = { 0 }; + + DMSG("dev_id = %u", dev_id); + if (fd < 0) { +#ifdef __ANDROID__ + snprintf(path, sizeof(path), "/dev/mmcblk%urpmb", dev_id); +#else + snprintf(path, sizeof(path), "/dev/mmcblk%urpmb", dev_id); +#endif + fd = open(path, O_RDWR); + if (fd < 0) { + EMSG("Could not open %s (%s)", path, strerror(errno)); + return -1; + } + id = dev_id; + } + if (id != dev_id) { + EMSG("Only one MMC device is supported"); + return -1; + } + return fd; +} + +/* + * Read @n bytes from @fd, takes care of short reads and EINTR. + * Adapted from “Advanced Programming In the UNIX Environment†by W. Richard + * Stevens and Stephen A. Rago, 2013, 3rd Edition, Addison-Wesley + * (EINTR handling was added) + */ +static ssize_t readn(int fd, void *ptr, size_t n) +{ + size_t nleft = n; + ssize_t nread = 0; + uint8_t *p = ptr; + + while (nleft > 0) { + if ((nread = read(fd, p, nleft)) < 0) { + if (errno == EINTR) + continue; + if (nleft == n) + return -1; /* error, nothing read, return -1 */ + else + break; /* error, return amount read so far */ + } else if (nread == 0) { + break; /* EOF */ + } + nleft -= nread; + p += nread; + } + return n - nleft; /* return >= 0 */ +} + +/* Size of CID printed in hexadecimal */ +#define CID_STR_SZ (2 * RPMB_CID_SZ) + +static TEEC_Result read_cid_str(uint16_t dev_id, char cid[CID_STR_SZ + 1]) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + char path[48] = { 0 }; + int fd = 0; + int st = 0; + + snprintf(path, sizeof(path), + "/sys/class/mmc_host/mmc%u/mmc%u:0001/cid", dev_id, dev_id); + fd = open(path, O_RDONLY); + if (fd < 0) + return TEEC_ERROR_ITEM_NOT_FOUND; + st = readn(fd, cid, CID_STR_SZ); + if (st != CID_STR_SZ) { + EMSG("Read CID error"); + if (errno) + EMSG("%s", strerror(errno)); + res = TEEC_ERROR_NO_DATA; + goto out; + } + res = TEEC_SUCCESS; +out: + close(fd); + return res; +} + +static int hexchar2int(char 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; + return -1; +} + +static int hexbyte2int(char *hex) +{ + int v1 = hexchar2int(hex[0]); + int v2 = hexchar2int(hex[1]); + + if (v1 < 0 || v2 < 0) + return -1; + return 16 * v1 + v2; +} + +/* Device Identification (CID) register is 16 bytes. It is read from sysfs. */ +static TEEC_Result read_cid(uint16_t dev_id, uint8_t *cid) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + char cid_str[CID_STR_SZ + 1] = { }; + int i = 0; + int v = 0; + + res = read_cid_str(dev_id, cid_str); + if (res) + return res; + + for (i = 0; i < RPMB_CID_SZ; i++) { + v = hexbyte2int(cid_str + 2 * i); + if (v < 0) { + EMSG("Invalid CID string: %s", cid_str); + return TEEC_ERROR_NO_DATA; + } + cid[i] = v; + } + return TEEC_SUCCESS; +} + +static TEEC_Result read_mmc_sysfs_hex(uint16_t dev_id, const char *file, uint8_t *value) +{ + TEEC_Result status = TEEC_SUCCESS; + char path[255] = { 0 }; + char buf[255] = { 0 }; + char *endp = buf; + int fd = 0; + int ret = 0; + + snprintf(path, sizeof(path), "/sys/class/mmc_host/mmc%u/mmc%u:0001/%s", + dev_id, dev_id, file); + + fd = open(path, O_RDONLY); + if (fd < 0) { + EMSG("Could not open %s (%s)", path, strerror(errno)); + return TEEC_ERROR_ITEM_NOT_FOUND; + } + + ret = readn(fd, buf, sizeof(buf)); + if (ret < 0) { + EMSG("Read error (%s)", strerror(errno)); + status = TEEC_ERROR_NO_DATA; + goto out; + } + + errno = 0; + *value = strtol(buf, &endp, 16); + if (errno || endp == buf) + status = TEEC_ERROR_GENERIC; + +out: + close(fd); + return status; +} + +static TEEC_Result read_size_mult(uint16_t dev_id, uint8_t *value) +{ + return read_mmc_sysfs_hex(dev_id, "raw_rpmb_size_mult", value); +} + +static TEEC_Result read_rel_wr_sec_c(uint16_t dev_id, uint8_t *value) +{ + return read_mmc_sysfs_hex(dev_id, "rel_sectors", value); +} + +/* + * - If --rpmb-cid is given, find the eMMC RPMB device number with the specified + * CID, cache the number, copy it to @ndev_id and return true. If not found + * return false. + * - If --rpmb-cid is not given, copy @dev_id to @ndev_id and return true. + */ +static bool remap_rpmb_dev_id(uint16_t dev_id, uint16_t *ndev_id) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + static bool found = false; + static bool err = false; + static uint16_t id = 0; + char cid[CID_STR_SZ + 1] = { }; + struct dirent *dent = NULL; + DIR *dir = NULL; + int num = 0; + + if (err || found) + goto out; + + if (!supplicant_params.rpmb_cid) { + id = dev_id; + found = true; + goto out; + } + + dir = opendir("/sys/class/mmc_host"); + if (!dir) { + EMSG("Could not open /sys/class/mmc_host (%s)", + strerror(errno)); + err = true; + goto out; + } + + while ((dent = readdir(dir))) { + if (sscanf(dent->d_name, "%*[^0123456789]%d", &num) != 1) + continue; + if (num > UINT16_MAX) { + EMSG("Too many MMC devices"); + err = true; + break; + } + id = (uint16_t)num; + res = read_cid_str(id, cid); + if (res) + continue; + if (strcmp(cid, supplicant_params.rpmb_cid)) + continue; + IMSG("RPMB device %s is at /dev/mmcblk%urpmb\n", cid, id); + found = true; + break; + } + + closedir(dir); + + if (!found) + err = true; +out: + if (found) + *ndev_id = id; + return found; +} + +#else /* RPMB_EMU */ + +#define IOCTL(fd, request, ...) ioctl_emu((fd), (request), ##__VA_ARGS__) + +/* Emulated rel_wr_sec_c value (reliable write size, *256 bytes) */ +#define EMU_RPMB_REL_WR_SEC_C 1 +/* Emulated rpmb_size_mult value (RPMB size, *128 kB) */ +#define EMU_RPMB_SIZE_MULT 2 + +#define EMU_RPMB_SIZE_BYTES (EMU_RPMB_SIZE_MULT * 128 * 1024) + +/* Emulated eMMC device state */ +struct rpmb_emu { + uint8_t buf[EMU_RPMB_SIZE_BYTES]; + size_t size; + uint8_t key[32]; + bool key_set; + uint8_t nonce[16]; + uint32_t write_counter; + struct { + uint16_t msg_type; + uint16_t op_result; + uint16_t address; + } last_op; +}; +static struct rpmb_emu rpmb_emu = { + .size = EMU_RPMB_SIZE_BYTES +}; + +static struct rpmb_emu *mem_for_fd(int fd) +{ + static int sfd = -1; + + if (sfd == -1) + sfd = fd; + if (sfd != fd) { + EMSG("Emulating more than 1 RPMB partition is not supported"); + return NULL; + } + + return &rpmb_emu; +} + +#if (DEBUGLEVEL >= TRACE_FLOW) +static void dump_blocks(size_t startblk, size_t numblk, uint8_t *ptr, + bool to_mmc) +{ + char msg[100] = { 0 }; + size_t i = 0; + + for (i = 0; i < numblk; i++) { + snprintf(msg, sizeof(msg), "%s MMC block %zu", + to_mmc ? "Write" : "Read", startblk + i); + dump_buffer(msg, ptr, 256); + ptr += 256; + } +} +#else +static void dump_blocks(size_t startblk, size_t numblk, uint8_t *ptr, + bool to_mmc) +{ + (void)startblk; + (void)numblk; + (void)ptr; + (void)to_mmc; +} +#endif + +#define CUC(x) ((const unsigned char *)(x)) +static void hmac_update_frm(hmac_sha256_ctx *ctx, struct rpmb_data_frame *frm) +{ + hmac_sha256_update(ctx, CUC(frm->data), 256); + hmac_sha256_update(ctx, CUC(frm->nonce), 16); + hmac_sha256_update(ctx, CUC(&frm->write_counter), 4); + hmac_sha256_update(ctx, CUC(&frm->address), 2); + hmac_sha256_update(ctx, CUC(&frm->block_count), 2); + hmac_sha256_update(ctx, CUC(&frm->op_result), 2); + hmac_sha256_update(ctx, CUC(&frm->msg_type), 2); +} + +static bool is_hmac_valid(struct rpmb_emu *mem, struct rpmb_data_frame *frm, + size_t nfrm) +{ + uint8_t mac[32] = { 0 }; + size_t i = 0; + hmac_sha256_ctx ctx; + + memset(&ctx, 0, sizeof(ctx)); + + if (!mem->key_set) { + EMSG("Cannot check MAC (key not set)"); + return false; + } + + hmac_sha256_init(&ctx, mem->key, sizeof(mem->key)); + for (i = 0; i < nfrm; i++, frm++) + hmac_update_frm(&ctx, frm); + frm--; + hmac_sha256_final(&ctx, mac, 32); + + if (memcmp(mac, frm->key_mac, 32)) { + EMSG("Invalid MAC"); + return false; + } + return true; +} + +static uint16_t gen_msb1st_result(uint8_t byte) +{ + return (uint16_t)byte << 8; +} + +static uint16_t compute_hmac(struct rpmb_emu *mem, struct rpmb_data_frame *frm, + size_t nfrm) +{ + size_t i = 0; + hmac_sha256_ctx ctx; + + memset(&ctx, 0, sizeof(ctx)); + + if (!mem->key_set) { + EMSG("Cannot compute MAC (key not set)"); + return gen_msb1st_result(RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED); + } + + hmac_sha256_init(&ctx, mem->key, sizeof(mem->key)); + for (i = 0; i < nfrm; i++, frm++) + hmac_update_frm(&ctx, frm); + frm--; + hmac_sha256_final(&ctx, frm->key_mac, 32); + + return gen_msb1st_result(RPMB_RESULT_OK); +} + +static uint16_t ioctl_emu_mem_transfer(struct rpmb_emu *mem, + struct rpmb_data_frame *frm, + size_t nfrm, int to_mmc) +{ + size_t start = mem->last_op.address * 256; + size_t size = nfrm * 256; + size_t i = 0; + uint8_t *memptr = NULL; + + if (start > mem->size || start + size > mem->size) { + EMSG("Transfer bounds exceeed emulated memory"); + return gen_msb1st_result(RPMB_RESULT_ADDRESS_FAILURE); + } + if (to_mmc && !is_hmac_valid(mem, frm, nfrm)) + return gen_msb1st_result(RPMB_RESULT_AUTH_FAILURE); + + DMSG("Transferring %zu 256-byte data block%s %s MMC (block offset=%zu)", + nfrm, (nfrm > 1) ? "s" : "", to_mmc ? "to" : "from", start / 256); + for (i = 0; i < nfrm; i++) { + memptr = mem->buf + start + i * 256; + if (to_mmc) { + memcpy(memptr, frm[i].data, 256); + mem->write_counter++; + frm[i].write_counter = htonl(mem->write_counter); + frm[i].msg_type = + htons(RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE); + } else { + memcpy(frm[i].data, memptr, 256); + frm[i].msg_type = + htons(RPMB_MSG_TYPE_RESP_AUTH_DATA_READ); + frm[i].address = htons(mem->last_op.address); + frm[i].block_count = nfrm; + memcpy(frm[i].nonce, mem->nonce, 16); + } + frm[i].op_result = gen_msb1st_result(RPMB_RESULT_OK); + } + dump_blocks(mem->last_op.address, nfrm, mem->buf + start, to_mmc); + + if (!to_mmc) + compute_hmac(mem, frm, nfrm); + + return gen_msb1st_result(RPMB_RESULT_OK); +} + +static void ioctl_emu_get_write_result(struct rpmb_emu *mem, + struct rpmb_data_frame *frm) +{ + frm->msg_type = htons(RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE); + frm->op_result = mem->last_op.op_result; + frm->address = htons(mem->last_op.address); + frm->write_counter = htonl(mem->write_counter); + compute_hmac(mem, frm, 1); +} + +static uint16_t ioctl_emu_setkey(struct rpmb_emu *mem, + struct rpmb_data_frame *frm) +{ + if (mem->key_set) { + EMSG("Key already set"); + return gen_msb1st_result(RPMB_RESULT_GENERAL_FAILURE); + } + dump_buffer("Setting key", frm->key_mac, 32); + memcpy(mem->key, frm->key_mac, 32); + mem->key_set = true; + + return gen_msb1st_result(RPMB_RESULT_OK); +} + +static void ioctl_emu_get_keyprog_result(struct rpmb_emu *mem, + struct rpmb_data_frame *frm) +{ + frm->msg_type = + htons(RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM); + frm->op_result = mem->last_op.op_result; +} + +static void ioctl_emu_read_ctr(struct rpmb_emu *mem, + struct rpmb_data_frame *frm) +{ + DMSG("Reading counter"); + frm->msg_type = htons(RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ); + frm->write_counter = htonl(mem->write_counter); + memcpy(frm->nonce, mem->nonce, 16); + frm->op_result = compute_hmac(mem, frm, 1); +} + +static uint32_t read_cid(uint16_t dev_id, uint8_t *cid) +{ + /* Taken from an actual eMMC chip */ + static const uint8_t test_cid[] = { + /* MID (Manufacturer ID): Micron */ + 0xfe, + /* CBX (Device/BGA): BGA */ + 0x01, + /* OID (OEM/Application ID) */ + 0x4e, + /* PNM (Product name) "MMC04G" */ + 0x4d, 0x4d, 0x43, 0x30, 0x34, 0x47, + /* PRV (Product revision): 4.2 */ + 0x42, + /* PSN (Product serial number) */ + 0xc8, 0xf6, 0x55, 0x2a, + /* + * MDT (Manufacturing date): + * June, 2014 + */ + 0x61, + /* (CRC7 (0xA) << 1) | 0x1 */ + 0x15 + }; + + (void)dev_id; + memcpy(cid, test_cid, sizeof(test_cid)); + + return TEEC_SUCCESS; +} + +/* A crude emulation of the MMC ioc commands we need for RPMB */ +static int ioctl_emu_cmd(int fd, struct mmc_ioc_cmd *cmd) +{ + struct rpmb_data_frame *frm = NULL; + uint16_t msg_type = 0; + struct rpmb_emu *mem = mem_for_fd(fd); + + if (!mem) + return -1; + + switch (cmd->opcode) { + case MMC_WRITE_MULTIPLE_BLOCK: + frm = (struct rpmb_data_frame *)(uintptr_t)cmd->data_ptr; + msg_type = ntohs(frm->msg_type); + + switch (msg_type) { + case RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM: + mem->last_op.msg_type = msg_type; + mem->last_op.op_result = ioctl_emu_setkey(mem, frm); + break; + + case RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: + mem->last_op.msg_type = msg_type; + mem->last_op.address = ntohs(frm->address); + mem->last_op.op_result = + ioctl_emu_mem_transfer(mem, frm, + cmd->blocks, 1); + break; + + case RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ: + case RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: + memcpy(mem->nonce, frm->nonce, 16); + mem->last_op.msg_type = msg_type; + mem->last_op.address = ntohs(frm->address); + break; + default: + break; + } + break; + + case MMC_READ_MULTIPLE_BLOCK: + frm = (struct rpmb_data_frame *)(uintptr_t)cmd->data_ptr; + msg_type = ntohs(frm->msg_type); + + switch (mem->last_op.msg_type) { + case RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM: + ioctl_emu_get_keyprog_result(mem, frm); + break; + + case RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: + ioctl_emu_get_write_result(mem, frm); + break; + + case RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ: + ioctl_emu_read_ctr(mem, frm); + break; + + case RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: + ioctl_emu_mem_transfer(mem, frm, cmd->blocks, 0); + break; + + default: + EMSG("Unexpected"); + break; + } + break; + + default: + EMSG("Unsupported ioctl opcode 0x%08x", cmd->opcode); + return -1; + } + + return 0; +} + +static int ioctl_emu(int fd, unsigned long request, ...) +{ + struct mmc_ioc_multi_cmd *mcmd = NULL; + struct mmc_ioc_cmd *cmd = NULL; + size_t i = 0; + int res = 0; + va_list ap; + + if (request == MMC_IOC_CMD) { + va_start(ap, request); + cmd = va_arg(ap, struct mmc_ioc_cmd *); + va_end(ap); + + res = ioctl_emu_cmd(fd, cmd); + } else if (request == MMC_IOC_MULTI_CMD) { + va_start(ap, request); + mcmd = va_arg(ap, struct mmc_ioc_multi_cmd *); + va_end(ap); + + for (i = 0; i < mcmd->num_of_cmds; i++) { + res = ioctl_emu_cmd(fd, &mcmd->cmds[i]); + if (res) + return res; + } + } else { + EMSG("Unsupported ioctl: 0x%lx", request); + return -1; + } + + return res; +} + +static int mmc_rpmb_fd(uint16_t dev_id) +{ + (void)dev_id; + + /* Any value != -1 will do in test mode */ + return 0; +} + +static TEEC_Result read_size_mult(uint16_t dev_id, uint8_t *value) +{ + (void)dev_id; + + *value = EMU_RPMB_SIZE_MULT; + return TEEC_SUCCESS; +} + +static TEEC_Result read_rel_wr_sec_c(uint16_t dev_id, uint8_t *value) +{ + (void)dev_id; + + *value = EMU_RPMB_REL_WR_SEC_C; + return TEEC_SUCCESS; +} + +static bool remap_rpmb_dev_id(uint16_t dev_id, uint16_t *ndev_id) +{ + *ndev_id = dev_id; + return true; +} + +#endif /* RPMB_EMU */ + +static inline void set_mmc_io_cmd(struct mmc_ioc_cmd *cmd, unsigned int blocks, + __u32 opcode, int write_flag) +{ + cmd->blksz = 512; + cmd->blocks = blocks; + cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC; + cmd->opcode = opcode; + cmd->write_flag = write_flag; +} + +static uint32_t rpmb_data_req(int fd, struct rpmb_data_frame *req_frm, + size_t req_nfrm, struct rpmb_data_frame *rsp_frm, + size_t rsp_nfrm) +{ + TEEC_Result res = TEEC_SUCCESS; + int st = 0; + size_t i = 0; + uint16_t msg_type = ntohs(req_frm->msg_type); + struct mmc_ioc_multi_cmd *mcmd = NULL; + struct mmc_ioc_cmd *cmd = NULL; + + for (i = 1; i < req_nfrm; i++) { + if (req_frm[i].msg_type != msg_type) { + EMSG("All request frames shall be of the same type"); + return TEEC_ERROR_BAD_PARAMETERS; + } + } + + DMSG("Req: %zu frame(s) of type 0x%04x", req_nfrm, msg_type); + DMSG("Rsp: %zu frame(s)", rsp_nfrm); + + mcmd = (struct mmc_ioc_multi_cmd *) + calloc(1, sizeof(struct mmc_ioc_multi_cmd) + + RPMB_MAX_IOC_MULTI_CMDS * sizeof(struct mmc_ioc_cmd)); + if (!mcmd) + return TEEC_ERROR_OUT_OF_MEMORY; + + switch(msg_type) { + case RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM: + case RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE: + if (rsp_nfrm != 1) { + EMSG("Expected only one response frame"); + res = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + + mcmd->num_of_cmds = 3; + + /* Send write request frame(s) */ + cmd = &mcmd->cmds[0]; + set_mmc_io_cmd(cmd, req_nfrm, MMC_WRITE_MULTIPLE_BLOCK, + 1 | MMC_CMD23_ARG_REL_WR); + /* + * Black magic: tested on a HiKey board with a HardKernel eMMC + * module. When postsleep values are zero, the kernel logs + * random errors: "mmc_blk_ioctl_cmd: Card Status=0x00000E00" + * and ioctl() fails. + */ + cmd->postsleep_min_us = 20000; + cmd->postsleep_max_us = 50000; + mmc_ioc_cmd_set_data((*cmd), (uintptr_t)req_frm); + + /* Send result request frame */ + cmd = &mcmd->cmds[1]; + set_mmc_io_cmd(cmd, req_nfrm, MMC_WRITE_MULTIPLE_BLOCK, 1); + memset(rsp_frm, 0, 1); + rsp_frm->msg_type = htons(RPMB_MSG_TYPE_REQ_RESULT_READ); + mmc_ioc_cmd_set_data((*cmd), (uintptr_t)rsp_frm); + + /* Read response frame */ + cmd = &mcmd->cmds[2]; + set_mmc_io_cmd(cmd, rsp_nfrm, MMC_READ_MULTIPLE_BLOCK, 0); + mmc_ioc_cmd_set_data((*cmd), (uintptr_t)rsp_frm); + break; + + case RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ: + if (rsp_nfrm != 1) { + EMSG("Expected only one response frame"); + res = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } +#if __GNUC__ > 6 + __attribute__((fallthrough)); +#endif + + case RPMB_MSG_TYPE_REQ_AUTH_DATA_READ: + if (req_nfrm != 1) { + EMSG("Expected only one request frame"); + res = TEEC_ERROR_BAD_PARAMETERS; + goto out; + } + + mcmd->num_of_cmds = 2; + + /* Send request frame */ + cmd = &mcmd->cmds[0]; + set_mmc_io_cmd(cmd, req_nfrm, MMC_WRITE_MULTIPLE_BLOCK, 1); + mmc_ioc_cmd_set_data((*cmd), (uintptr_t)req_frm); + + /* Read response frames */ + cmd = &mcmd->cmds[1]; + set_mmc_io_cmd(cmd, rsp_nfrm, MMC_READ_MULTIPLE_BLOCK, 0); + mmc_ioc_cmd_set_data((*cmd), (uintptr_t)rsp_frm); + break; + + default: + EMSG("Unsupported message type: %d", msg_type); + res = TEEC_ERROR_GENERIC; + goto out; + } + + st = IOCTL(fd, MMC_IOC_MULTI_CMD, mcmd); + if (st < 0) + res = TEEC_ERROR_GENERIC; + +out: + free(mcmd); + + return res; +} + +static uint32_t rpmb_get_dev_info(uint16_t dev_id, struct rpmb_dev_info *info) +{ + TEEC_Result res = TEEC_SUCCESS; + uint8_t rpmb_size_mult = 0; + uint8_t rel_wr_sec_c = 0; + + res = read_cid(dev_id, info->cid); + if (res != TEEC_SUCCESS) + return res; + + res = read_size_mult(dev_id, &rpmb_size_mult); + if (res != TEEC_SUCCESS) + return res; + info->rpmb_size_mult = rpmb_size_mult; + + res = read_rel_wr_sec_c(dev_id, &rel_wr_sec_c); + if (res != TEEC_SUCCESS) + return res; + info->rel_wr_sec_c = rel_wr_sec_c; + + info->ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK; + + return res; +} + + +/* + * req is one struct rpmb_req followed by one or more struct rpmb_data_frame + * rsp is either one struct rpmb_dev_info or one or more struct rpmb_data_frame + */ +static uint32_t rpmb_process_request_unlocked(void *req, size_t req_size, + void *rsp, size_t rsp_size) +{ + struct rpmb_req *sreq = req; + size_t req_nfrm = 0; + size_t rsp_nfrm = 0; + uint16_t dev_id = 0; + uint32_t res = 0; + int fd = 0; + + if (req_size < sizeof(*sreq)) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!remap_rpmb_dev_id(sreq->dev_id, &dev_id)) + return TEEC_ERROR_ITEM_NOT_FOUND; + + switch (sreq->cmd) { + case RPMB_CMD_DATA_REQ: + req_nfrm = (req_size - sizeof(struct rpmb_req)) / 512; + rsp_nfrm = rsp_size / 512; + fd = mmc_rpmb_fd(dev_id); + if (fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + res = rpmb_data_req(fd, RPMB_REQ_DATA(req), req_nfrm, rsp, + rsp_nfrm); + break; + + case RPMB_CMD_GET_DEV_INFO: + if (req_size != sizeof(struct rpmb_req) || + rsp_size != sizeof(struct rpmb_dev_info)) { + EMSG("Invalid req/rsp size"); + return TEEC_ERROR_BAD_PARAMETERS; + } + res = rpmb_get_dev_info(dev_id, (struct rpmb_dev_info *)rsp); + break; + + default: + EMSG("Unsupported RPMB command: %d", sreq->cmd); + res = TEEC_ERROR_BAD_PARAMETERS; + break; + } + + return res; +} + + +uint32_t rpmb_process_request(void *req, size_t req_size, void *rsp, + size_t rsp_size) +{ + uint32_t res = 0; + + tee_supp_mutex_lock(&rpmb_mutex); + res = rpmb_process_request_unlocked(req, req_size, rsp, rsp_size); + tee_supp_mutex_unlock(&rpmb_mutex); + + return res; +} diff --git a/optee/optee_client/tee-supplicant/src/rpmb.h b/optee/optee_client/tee-supplicant/src/rpmb.h new file mode 100644 index 0000000..feeed5b --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/rpmb.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 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 RPMB_H +#define RPMB_H + +#include +#include + +uint32_t rpmb_process_request(void *req, size_t req_size, void *rsp, + size_t rsp_size); + +#endif /* RPMB_H */ diff --git a/optee/optee_client/tee-supplicant/src/sha2.c b/optee/optee_client/tee-supplicant/src/sha2.c new file mode 100644 index 0000000..b884033 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/sha2.c @@ -0,0 +1,249 @@ +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Copyright (c) 2016, 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. + * 3. Neither the name of the project 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 PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 "sha2.h" + +#define SHFR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) +#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) +#define CH(x, y, z) ((x & y) ^ (~x & z)) +#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) + +#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) +#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) + +#define UNPACK32(x, str) \ +{ \ + *((str) + 3) = (uint8) ((x) ); \ + *((str) + 2) = (uint8) ((x) >> 8); \ + *((str) + 1) = (uint8) ((x) >> 16); \ + *((str) + 0) = (uint8) ((x) >> 24); \ +} + +#define PACK32(str, x) \ +{ \ + *(x) = ((uint32) *((str) + 3) ) \ + | ((uint32) *((str) + 2) << 8) \ + | ((uint32) *((str) + 1) << 16) \ + | ((uint32) *((str) + 0) << 24); \ +} + +#define UNPACK64(x, str) \ +{ \ + *((str) + 7) = (uint8) ((x) ); \ + *((str) + 6) = (uint8) ((x) >> 8); \ + *((str) + 5) = (uint8) ((x) >> 16); \ + *((str) + 4) = (uint8) ((x) >> 24); \ + *((str) + 3) = (uint8) ((x) >> 32); \ + *((str) + 2) = (uint8) ((x) >> 40); \ + *((str) + 1) = (uint8) ((x) >> 48); \ + *((str) + 0) = (uint8) ((x) >> 56); \ +} + +#define PACK64(str, x) \ +{ \ + *(x) = ((uint64) *((str) + 7) ) \ + | ((uint64) *((str) + 6) << 8) \ + | ((uint64) *((str) + 5) << 16) \ + | ((uint64) *((str) + 4) << 24) \ + | ((uint64) *((str) + 3) << 32) \ + | ((uint64) *((str) + 2) << 40) \ + | ((uint64) *((str) + 1) << 48) \ + | ((uint64) *((str) + 0) << 56); \ +} + +#define SHA256_SCR(i) \ +{ \ + w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \ + + SHA256_F3(w[i - 15]) + w[i - 16]; \ +} + +uint32 sha256_h0[8] = + {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + +uint32 sha256_k[64] = + {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; + +/* SHA-256 functions */ + +static void sha256_transf(sha256_ctx *ctx, const unsigned char *message, + unsigned int block_nb) +{ + uint32 w[64] = { 0 }; + uint32 wv[8] = { 0 }; + uint32 t1 = 0; + uint32 t2 = 0; + const unsigned char *sub_block = NULL; + int i = 0; + int j = 0; + + for (i = 0; i < (int) block_nb; i++) { + sub_block = message + (i << 6); + + for (j = 0; j < 16; j++) { + PACK32(&sub_block[j << 2], &w[j]); + } + + for (j = 16; j < 64; j++) { + SHA256_SCR(j); + } + + for (j = 0; j < 8; j++) { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 64; j++) { + t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + + sha256_k[j] + w[j]; + t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) { + ctx->h[j] += wv[j]; + } + } +} + +void sha256(const unsigned char *message, unsigned int len, + unsigned char *digest) +{ + sha256_ctx ctx; + + memset(&ctx, 0, sizeof(ctx)); + + sha256_init(&ctx); + sha256_update(&ctx, message, len); + sha256_final(&ctx, digest); +} + +void sha256_init(sha256_ctx *ctx) +{ + int i = 0; + + for (i = 0; i < 8; i++) { + ctx->h[i] = sha256_h0[i]; + } + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha256_update(sha256_ctx *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb = 0; + unsigned int new_len = 0; + unsigned int rem_len = 0; + unsigned int tmp_len = 0; + const unsigned char *shifted_message = NULL; + + tmp_len = SHA256_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA256_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA256_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha256_transf(ctx, ctx->block, 1); + sha256_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA256_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 6], + rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void sha256_final(sha256_ctx *ctx, unsigned char *digest) +{ + unsigned int block_nb = 0; + unsigned int pm_len = 0; + unsigned int len_b = 0; + int i = 0; + + block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) + < (ctx->len % SHA256_BLOCK_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha256_transf(ctx, ctx->block, block_nb); + + for (i = 0 ; i < 8; i++) { + UNPACK32(ctx->h[i], &digest[i << 2]); + } +} diff --git a/optee/optee_client/tee-supplicant/src/sha2.h b/optee/optee_client/tee-supplicant/src/sha2.h new file mode 100644 index 0000000..3a17fae --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/sha2.h @@ -0,0 +1,75 @@ +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Copyright (c) 2016, 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. + * 3. Neither the name of the project 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 PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 SHA2_H +#define SHA2_H + +#define SHA256_DIGEST_SIZE ( 256 / 8) +#define SHA256_BLOCK_SIZE ( 512 / 8) + +#ifndef SHA2_TYPES +#define SHA2_TYPES +typedef unsigned char uint8; +typedef unsigned int uint32; +typedef unsigned long long uint64; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned int tot_len; + unsigned int len; + unsigned char block[2 * SHA256_BLOCK_SIZE]; + uint32 h[8]; +} sha256_ctx; + +typedef sha256_ctx sha224_ctx; + +void sha256_init(sha256_ctx * ctx); +void sha256_update(sha256_ctx *ctx, const unsigned char *message, + unsigned int len); +void sha256_final(sha256_ctx *ctx, unsigned char *digest); +void sha256(const unsigned char *message, unsigned int len, + unsigned char *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* !SHA2_H */ + diff --git a/optee/optee_client/tee-supplicant/src/tee_socket.c b/optee/optee_client/tee-supplicant/src/tee_socket.c new file mode 100644 index 0000000..b9ae613 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/tee_socket.c @@ -0,0 +1,848 @@ +/* + * Copyright (c) 2016-2017, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "handle.h" +#include "__tee_isocket_defines.h" +#include "__tee_ipsocket.h" +#include "__tee_tcpsocket_defines.h" +#include "__tee_tcpsocket_defines_extensions.h" +#include "__tee_udpsocket_defines.h" + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif +#include + +/* + * Used when checking how much data we have queued. + * + * For SOCK_DGRAM we try to be accurate up to 4096 bytes as + * that's our arbitrary chosen sensible upper size (with + * some margin). Larger size doesn't make much sense since + * anything larger than the MTU is bound to cause trouble + * on a congested network. + * + * For SOCK_STREAM we chose the same upper limit for + * simplicity. It doesn't matter if there's more queued, + * no data will be lost. + */ +#define SUPP_MAX_PEEK_LEN 4096 + +struct sock_instance { + uint32_t id; + struct handle_db db; + TAILQ_ENTRY(sock_instance) link; +}; + +static pthread_mutex_t sock_mutex = PTHREAD_MUTEX_INITIALIZER; +TAILQ_HEAD(, sock_instance) sock_instances = + TAILQ_HEAD_INITIALIZER(sock_instances); + +static void sock_lock(void) +{ + pthread_mutex_lock(&sock_mutex); +} + +static void sock_unlock(void) +{ + pthread_mutex_unlock(&sock_mutex); +} + +static struct sock_instance *sock_instance_find(uint32_t instance_id) +{ + struct sock_instance *si = NULL; + + TAILQ_FOREACH(si, &sock_instances, link) { + if (si->id == instance_id) + return si; + } + return NULL; +} + +static void *fd_to_handle_ptr(int fd) +{ + uintptr_t ptr = 0; + + assert(fd >= 0); + ptr = fd + 1; + return (void *)ptr; +} + +static int handle_ptr_to_fd(void *ptr) +{ + assert(ptr); + return (uintptr_t)ptr - 1; +} + +static int sock_handle_get(uint32_t instance_id, int fd) +{ + int handle = -1; + struct sock_instance *si = NULL; + + sock_lock(); + + si = sock_instance_find(instance_id); + if (!si) { + si = calloc(1, sizeof(*si)); + if (!si) + goto out; + si->id = instance_id; + TAILQ_INSERT_TAIL(&sock_instances, si, link); + } + + handle = handle_get(&si->db, fd_to_handle_ptr(fd)); +out: + sock_unlock(); + return handle; +} + +static int sock_handle_to_fd(uint32_t instance_id, uint32_t handle) +{ + int fd = -1; + struct sock_instance *si = NULL; + + sock_lock(); + si = sock_instance_find(instance_id); + if (si) + fd = handle_ptr_to_fd(handle_lookup(&si->db, handle)); + sock_unlock(); + return fd; +} + +static void sock_handle_put(uint32_t instance_id, uint32_t handle) +{ + struct sock_instance *si = NULL; + + sock_lock(); + si = sock_instance_find(instance_id); + if (si) + handle_put(&si->db, handle); + sock_unlock(); +} + +static bool chk_pt(struct tee_ioctl_param *param, uint32_t type) +{ + return (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) == type; +} + +static int fd_flags_add(int fd, int flags) +{ + int val = 0; + + val = fcntl(fd, F_GETFD, 0); + if (val == -1) + return -1; + + val |= flags; + + return fcntl(fd, F_SETFL, val); +} + +static TEEC_Result sock_connect(uint32_t ip_vers, unsigned int protocol, + const char *server, uint16_t port, int *ret_fd) +{ + TEEC_Result r = TEEC_ERROR_GENERIC; + struct addrinfo *res0 = NULL; + struct addrinfo *res = NULL; + int fd = -1; + char port_name[10] = { 0 }; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + + snprintf(port_name, sizeof(port_name), "%" PRIu16, port); + + switch (ip_vers) { + case TEE_IP_VERSION_DC: + hints.ai_family = AF_UNSPEC; + break; + case TEE_IP_VERSION_4: + hints.ai_family = AF_INET; + break; + case TEE_IP_VERSION_6: + hints.ai_family = AF_INET6; + break; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } + + if (protocol == TEE_ISOCKET_PROTOCOLID_TCP) + hints.ai_socktype = SOCK_STREAM; + else if (protocol == TEE_ISOCKET_PROTOCOLID_UDP) + hints.ai_socktype = SOCK_DGRAM; + else + return TEEC_ERROR_BAD_PARAMETERS; + + if (getaddrinfo(server, port_name, &hints, &res0)) + return TEE_ISOCKET_ERROR_HOSTNAME; + + for (res = res0; res; res = res->ai_next) { + fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (fd == -1) { + if (errno == ENOMEM || errno == ENOBUFS) + r = TEE_ISOCKET_ERROR_OUT_OF_RESOURCES; + else + r = TEEC_ERROR_GENERIC; + continue; + } + + if (connect(fd, res->ai_addr, res->ai_addrlen)) { + if (errno == ETIMEDOUT) + r = TEE_ISOCKET_ERROR_TIMEOUT; + else + r = TEEC_ERROR_COMMUNICATION; + + close(fd); + fd = -1; + continue; + } + + if (fd_flags_add(fd, O_NONBLOCK)) { + close(fd); + fd = -1; + r = TEEC_ERROR_GENERIC; + break; + } + + r = TEEC_SUCCESS; + break; + } + + freeaddrinfo(res0); + *ret_fd = fd; + return r; +} + +static TEEC_Result tee_socket_open(size_t num_params, + struct tee_ioctl_param *params) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + int handle = 0; + int fd = 0; + uint32_t instance_id = 0; + char *server = NULL; + uint32_t ip_vers = 0; + uint16_t port = 0; + uint32_t protocol = 0; + + if (num_params != 4 || + !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || + !chk_pt(params + 1, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || + !chk_pt(params + 2, TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) || + !chk_pt(params + 3, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT)) + return TEEC_ERROR_BAD_PARAMETERS; + + instance_id = params[0].b; + port = params[1].a; + protocol = params[1].b; + ip_vers = params[1].c; + + server = tee_supp_param_to_va(params + 2); + if (!server || server[MEMREF_SIZE(params + 2) - 1] != '\0') + return TEE_ISOCKET_ERROR_HOSTNAME; + + res = sock_connect(ip_vers, protocol, server, port, &fd); + if (res != TEEC_SUCCESS) + return res; + + handle = sock_handle_get(instance_id, fd); + if (handle < 0) { + close(fd); + return TEEC_ERROR_OUT_OF_MEMORY; + } + + params[3].a = handle; + return TEEC_SUCCESS; +} + +static TEEC_Result tee_socket_close(size_t num_params, + struct tee_ioctl_param *params) +{ + int handle = 0; + uint32_t instance_id = 0; + int fd = 0; + + if (num_params != 1 || + !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)) + return TEEC_ERROR_BAD_PARAMETERS; + + instance_id = params[0].b; + handle = params[0].c; + fd = sock_handle_to_fd(instance_id, handle); + if (fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + sock_handle_put(instance_id, handle); + if (close(fd)) { + EMSG("tee_socket_close: close(%d): %s", fd, strerror(errno)); + return TEEC_ERROR_GENERIC; + } + return TEEC_SUCCESS; +} + +static void sock_close_cb(int handle, void *ptr, void *arg) +{ + struct sock_instance *si = arg; + int fd = handle_ptr_to_fd(ptr); + + if (close(fd)) + EMSG("sock_close_cb instance_id %d handle %d fd %d: %s", + si->id, handle, fd, strerror(errno)); +} + +static TEEC_Result tee_socket_close_all(size_t num_params, + struct tee_ioctl_param *params) +{ + uint32_t instance_id = 0; + struct sock_instance *si = NULL; + + if (num_params != 1 || + !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)) + return TEEC_ERROR_BAD_PARAMETERS; + + instance_id = params[0].b; + sock_lock(); + si = sock_instance_find(instance_id); + if (si) + handle_foreach_put(&si->db, sock_close_cb, si); + sock_unlock(); + + return TEEC_SUCCESS; +} + +#define TS_NSEC_PER_SEC 1000000000 + +static void ts_add(const struct timespec *a, const struct timespec *b, + struct timespec *res) +{ + res->tv_sec = a->tv_sec + b->tv_sec; + res->tv_nsec = a->tv_nsec + b->tv_nsec; + if (res->tv_nsec >= TS_NSEC_PER_SEC) { + res->tv_sec++; + res->tv_nsec -= TS_NSEC_PER_SEC; + } +} + +static int ts_diff_to_polltimeout(const struct timespec *a, + const struct timespec *b) +{ + struct timespec diff; + + memset(&diff, 0, sizeof(diff)); + + diff.tv_sec = a->tv_sec - b->tv_sec; + diff.tv_nsec = a->tv_nsec - b->tv_nsec; + if (a->tv_nsec < b->tv_nsec) { + diff.tv_nsec += TS_NSEC_PER_SEC; + diff.tv_sec--; + } + + if ((diff.tv_sec - 1) > (INT_MAX / 1000)) + return INT_MAX; + return diff.tv_sec * 1000 + diff.tv_nsec / (TS_NSEC_PER_SEC / 1000); +} + +static void ts_delay_from_millis(uint32_t millis, struct timespec *res) +{ + res->tv_sec = millis / 1000; + res->tv_nsec = (millis % 1000) * (TS_NSEC_PER_SEC / 1000); +} + +static TEEC_Result poll_with_timeout(struct pollfd *pfd, nfds_t nfds, + uint32_t timeout) +{ + int to = 0; + int r = 0; + struct timespec now; + struct timespec until; + + memset(&now, 0, sizeof(now)); + memset(&until, 0, sizeof(until)); + + if (timeout == OPTEE_MRC_SOCKET_TIMEOUT_BLOCKING) { + to = -1; + } else { + struct timespec delay; + + memset(&delay, 0, sizeof(delay)); + + ts_delay_from_millis(timeout, &delay); + + if (clock_gettime(CLOCK_REALTIME, &now)) + return TEEC_ERROR_GENERIC; + + ts_add(&now, &delay, &until); + } + + while (true) { + if (to != -1) + to = ts_diff_to_polltimeout(&until, &now); + + r = poll(pfd, nfds, to); + if (!r) + return TEE_ISOCKET_ERROR_TIMEOUT; + if (r == -1) { + /* + * If we're interrupted by a signal treat + * recalculate the timeout (if needed) and wait + * again. + */ + if (errno == EINTR) { + if (to != -1 && + clock_gettime(CLOCK_REALTIME, &now)) + return TEEC_ERROR_GENERIC; + continue; + } + return TEEC_ERROR_BAD_PARAMETERS; + } + return TEEC_SUCCESS; + } +} + +static TEEC_Result write_with_timeout(int fd, const void *buf, size_t *blen, + uint32_t timeout) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + struct pollfd pfd = { .fd = fd, .events = POLLOUT }; + ssize_t r = 0; + + res = poll_with_timeout(&pfd, 1, timeout); + if (res != TEEC_SUCCESS) + return res; + + r = write(fd, buf, *blen); + if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + return TEE_ISOCKET_ERROR_TIMEOUT; + return TEEC_ERROR_BAD_PARAMETERS; + } + *blen = r; + return TEEC_SUCCESS; +} + +static TEEC_Result tee_socket_send(size_t num_params, + struct tee_ioctl_param *params) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + int handle = 0; + int fd = 0; + uint32_t instance_id = 0; + void *buf = NULL; + size_t bytes = 0; + + if (num_params != 3 || + !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || + !chk_pt(params + 1, TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) || + !chk_pt(params + 2, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT)) + return TEEC_ERROR_BAD_PARAMETERS; + + instance_id = params[0].b; + handle = params[0].c; + fd = sock_handle_to_fd(instance_id, handle); + if (fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + buf = tee_supp_param_to_va(params + 1); + bytes = MEMREF_SIZE(params + 1); + res = write_with_timeout(fd, buf, &bytes, params[2].a); + if (res == TEEC_SUCCESS) + params[2].b = bytes; + return res; +} + +static ssize_t recv_with_out_flags(int fd, void *buf, size_t len, int inflags, + int *out_flags) +{ + ssize_t r = 0; + + while (true) { + struct iovec iov = { .iov_base = buf, .iov_len = len, }; + struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, }; + + r = recvmsg(fd, &msg, inflags); + if (r < 0) { + /* + * If the syscall was just interrupted by a signal + * delivery, try again. + */ + if (errno == EINTR) + continue; + return r; + } + + *out_flags = msg.msg_flags; + return r; + } +} + +static TEEC_Result read_with_timeout(int fd, void *buf, size_t *blen, + uint32_t timeout) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + struct pollfd pfd = { .fd = fd, .events = POLLIN }; + int socktype = 0; + socklen_t l = sizeof(socktype); + size_t peek_len = 0; + int out_flags = 0; + ssize_t r = 0; + int e = 0; + + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &l)) + return TEEC_ERROR_BAD_PARAMETERS; + + if (*blen) { + /* If *blen == 0, the timeout parameter has no effect. */ + res = poll_with_timeout(&pfd, 1, timeout); + if (res != TEEC_SUCCESS) + return res; + } + + if ((socktype == SOCK_DGRAM && *blen < SUPP_MAX_PEEK_LEN) || !*blen) { + /* Check how much data we have queued. */ + void *b = malloc(SUPP_MAX_PEEK_LEN); + + if (!b) + return TEEC_ERROR_OUT_OF_MEMORY; + r = recv_with_out_flags(fd, b, SUPP_MAX_PEEK_LEN, + MSG_PEEK | MSG_DONTWAIT, &out_flags); + e = errno; + free(b); + if (r < 0) + goto err; + + /* + * If the message was truncated we know that it's at least + * one byte larger. + */ + if (out_flags & MSG_TRUNC) + r++; + + if (!*blen) { + *blen = r; + return TEEC_SUCCESS; + } + + peek_len = r; + } + + r = recv_with_out_flags(fd, buf, *blen, MSG_DONTWAIT, &out_flags); + if (r == -1) { + e = errno; + goto err; + } + if (socktype == SOCK_DGRAM && (out_flags & MSG_TRUNC)) { + /* + * The datagram has been truncated, return the best length + * we have to indicate that. + */ + if (peek_len > (size_t)r) + *blen = peek_len; + else + *blen = r + 1; + } else { + *blen = r; + } + return TEEC_SUCCESS; + +err: + if (e == EAGAIN || e == EWOULDBLOCK) { + /* + * If *blen is supplied as 0 then we're not supposed wait + * for data so the call to poll has been skipped. In case + * there is no data available recvmsg() will return an + * error with errno set to EAGAIN or EWOULDBLOCK. + */ + if (!*blen) + return TEEC_SUCCESS; + return TEE_ISOCKET_ERROR_TIMEOUT; + } + return TEEC_ERROR_BAD_PARAMETERS; +} + +static TEEC_Result tee_socket_recv(size_t num_params, + struct tee_ioctl_param *params) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + int handle = 0; + int fd = 0; + uint32_t instance_id = 0; + void *buf = NULL; + size_t bytes = 0; + + if (num_params != 3 || + !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || + !chk_pt(params + 1, TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) || + !chk_pt(params + 2, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)) + return TEEC_ERROR_BAD_PARAMETERS; + + instance_id = params[0].b; + handle = params[0].c; + fd = sock_handle_to_fd(instance_id, handle); + if (fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + buf = tee_supp_param_to_va(params + 1); + + bytes = MEMREF_SIZE(params + 1); + res = read_with_timeout(fd, buf, &bytes, params[2].a); + if (res == TEEC_SUCCESS) + MEMREF_SIZE(params + 1) = bytes; + + return res; +} + +static TEEC_Result tee_socket_ioctl_tcp(int fd, uint32_t command, + void *buf, size_t *blen) +{ + switch (command) { + case TEE_TCP_SET_RECVBUF: + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, buf, *blen)) + return TEEC_ERROR_BAD_PARAMETERS; + return TEEC_SUCCESS; + case TEE_TCP_SET_SENDBUF: + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, buf, *blen)) + return TEEC_ERROR_BAD_PARAMETERS; + return TEEC_SUCCESS; + default: + return TEEC_ERROR_NOT_SUPPORTED; + } +} + +static TEEC_Result sa_set_port(struct sockaddr *sa, socklen_t slen, + uint16_t port) +{ + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sain = (void *)sa; + + if (slen < (socklen_t)sizeof(*sain)) + return TEEC_ERROR_BAD_PARAMETERS; + sain->sin_port = htons(port); + + return TEEC_SUCCESS; + } + + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sain6 = (void *)sa; + + if (slen < (socklen_t)sizeof(*sain6)) + return TEEC_ERROR_BAD_PARAMETERS; + sain6->sin6_port = htons(port); + + return TEEC_SUCCESS; + } + + return TEEC_ERROR_BAD_PARAMETERS; +} + +static TEEC_Result sa_get_port(struct sockaddr *sa, socklen_t slen, + uint16_t *port) +{ + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sain = (void *)sa; + + if (slen < (socklen_t)sizeof(*sain)) + return TEEC_ERROR_BAD_PARAMETERS; + *port = ntohs(sain->sin_port); + + return TEEC_SUCCESS; + } + + if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sain6 = (void *)sa; + + if (slen < (socklen_t)sizeof(*sain6)) + return TEEC_ERROR_BAD_PARAMETERS; + *port = ntohs(sain6->sin6_port); + + return TEEC_SUCCESS; + } + + return TEEC_ERROR_BAD_PARAMETERS; +} + +static TEEC_Result udp_changeaddr(int fd, int family, const char *server, + uint16_t port) +{ + TEEC_Result r = TEE_ISOCKET_ERROR_HOSTNAME; + struct addrinfo *res0 = NULL; + struct addrinfo *res = NULL; + char port_name[10] = { 0 }; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + + snprintf(port_name, sizeof(port_name), "%" PRIu16, port); + + hints.ai_family = family; + hints.ai_socktype = SOCK_DGRAM; + if (getaddrinfo(server, port_name, &hints, &res0)) + return TEE_ISOCKET_ERROR_HOSTNAME; + for (res = res0; res; res = res->ai_next) { + if (connect(fd, res->ai_addr, res->ai_addrlen)) { + if (errno == ETIMEDOUT) + r = TEE_ISOCKET_ERROR_TIMEOUT; + else + r = TEEC_ERROR_COMMUNICATION; + continue; + } + r = TEEC_SUCCESS; + break; + } + freeaddrinfo(res0); + + return r; +} + +static TEEC_Result tee_socket_ioctl_udp(int fd, uint32_t command, + void *buf, size_t *blen) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint16_t port = 0; + struct sockaddr_storage sass; + struct sockaddr *sa = (struct sockaddr *)&sass; + socklen_t len = sizeof(sass); + + memset(&sass, 0, sizeof(sass)); + + if (getpeername(fd, sa, &len)) + return TEEC_ERROR_BAD_PARAMETERS; + + switch (command) { + case TEE_UDP_CHANGEADDR: + res = sa_get_port(sa, len, &port); + if (res != TEEC_SUCCESS) + return res; + + if (!blen || *((char *)buf + *blen - 1) != '\0') + return TEE_ISOCKET_ERROR_HOSTNAME; + + return udp_changeaddr(fd, sa->sa_family, buf, port); + case TEE_UDP_CHANGEPORT: + if (*blen != sizeof(port)) + return TEEC_ERROR_BAD_PARAMETERS; + memcpy(&port, buf, sizeof(port)); + res = sa_set_port(sa, len, port); + if (res != TEEC_SUCCESS) + return res; + if (connect(fd, sa, len)) + return TEEC_ERROR_GENERIC; + return TEEC_SUCCESS; + default: + return TEEC_ERROR_NOT_SUPPORTED; + } +} + +static TEEC_Result tee_socket_ioctl(size_t num_params, + struct tee_ioctl_param *params) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + int handle = 0; + int fd = 0; + uint32_t instance_id = 0; + uint32_t command = 0; + void *buf = NULL; + int socktype = 0; + socklen_t l = 0; + size_t sz = 0; + + if (num_params != 3 || + !chk_pt(params + 0, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) || + !chk_pt(params + 1, TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT) || + !chk_pt(params + 2, TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT)) + return TEEC_ERROR_BAD_PARAMETERS; + + instance_id = params[0].b; + handle = params[0].c; + command = params[2].a; + fd = sock_handle_to_fd(instance_id, handle); + if (fd < 0) + return TEEC_ERROR_BAD_PARAMETERS; + + l = sizeof(socktype); + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &l)) + return TEEC_ERROR_BAD_PARAMETERS; + + buf = tee_supp_param_to_va(params + 1); + + switch (socktype) { + case SOCK_STREAM: + sz = MEMREF_SIZE(params + 1); + res = tee_socket_ioctl_tcp(fd, command, buf, &sz); + MEMREF_SIZE(params + 1) = sz; + return res; + case SOCK_DGRAM: + sz = MEMREF_SIZE(params + 1); + res = tee_socket_ioctl_udp(fd, command, buf, &sz); + MEMREF_SIZE(params + 1) = sz; + return res; + default: + return TEEC_ERROR_BAD_PARAMETERS; + } +} + +TEEC_Result tee_socket_process(size_t num_params, + struct tee_ioctl_param *params) +{ + if (!num_params || !tee_supp_param_is_value(params)) + return TEEC_ERROR_BAD_PARAMETERS; + + switch (params->a) { + case OPTEE_MRC_SOCKET_OPEN: + return tee_socket_open(num_params, params); + case OPTEE_MRC_SOCKET_CLOSE: + return tee_socket_close(num_params, params); + case OPTEE_MRC_SOCKET_CLOSE_ALL: + return tee_socket_close_all(num_params, params); + case OPTEE_MRC_SOCKET_SEND: + return tee_socket_send(num_params, params); + case OPTEE_MRC_SOCKET_RECV: + return tee_socket_recv(num_params, params); + case OPTEE_MRC_SOCKET_IOCTL: + return tee_socket_ioctl(num_params, params); + default: + return TEEC_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_client/tee-supplicant/src/tee_socket.h b/optee/optee_client/tee-supplicant/src/tee_socket.h new file mode 100644 index 0000000..800c27c --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/tee_socket.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016-2017, 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 __TEE_SOCKET_H +#define __TEE_SOCKET_H + +#include + +struct tee_ioctl_param; + +#if defined(CFG_GP_SOCKETS) && CFG_GP_SOCKETS == 1 +TEEC_Result tee_socket_process(size_t num_params, + struct tee_ioctl_param *params); +#else +static inline TEEC_Result tee_socket_process(size_t num_params, + struct tee_ioctl_param *params) +{ + (void)num_params; + (void)params; + + return TEEC_ERROR_NOT_SUPPORTED; +} +#endif + +#endif /*__SOCKET_H*/ diff --git a/optee/optee_client/tee-supplicant/src/tee_supp_fs.c b/optee/optee_client/tee-supplicant/src/tee_supp_fs.c new file mode 100644 index 0000000..cc4120f --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/tee_supp_fs.c @@ -0,0 +1,681 @@ +/* + * 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 + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif +#include + +#ifndef PATH_MAX +#define PATH_MAX 255 +#endif + +/* Path to all secure storage files. */ +static char tee_fs_root[PATH_MAX]; + +#define TEE_FS_FILENAME_MAX_LENGTH 150 + +static pthread_mutex_t dir_handle_db_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct handle_db dir_handle_db = + HANDLE_DB_INITIALIZER_WITH_MUTEX(&dir_handle_db_mutex); + +static TEEC_Result errno_to_teec(int err) +{ + switch (err) { + case ENOSPC: + return TEEC_ERROR_STORAGE_NO_SPACE; + case ENOENT: + return TEEC_ERROR_ITEM_NOT_FOUND; + default: + break; + } + return TEEC_ERROR_GENERIC; +} + +static size_t tee_fs_get_absolute_filename(char *file, char *out, + size_t out_size) +{ + int s = 0; + + if (!file || !out || (out_size <= strlen(tee_fs_root) + 1)) + return 0; + + s = snprintf(out, out_size, "%s%s", tee_fs_root, file); + if (s < 0 || (size_t)s >= out_size) + return 0; + + /* Safe to cast since we have checked that sizes are OK */ + return (size_t)s; +} + +static void fs_fsync(void) +{ + int fd = 0; + + fd = open(tee_fs_root, O_RDONLY | O_DIRECTORY); + if (fd > 0) { + fsync(fd); + close(fd); + } +} + +static int do_mkdir(const char *path, mode_t mode) +{ + struct stat st; + + memset(&st, 0, sizeof(st)); + + if (mkdir(path, mode) != 0 && errno != EEXIST) + return -1; + + if (stat(path, &st) != 0 && !S_ISDIR(st.st_mode)) + return -1; + + fs_fsync(); + return 0; +} + +static int mkpath(const char *path, mode_t mode) +{ + int status = 0; + char *subpath = strdup(path); + char *prev = subpath; + char *curr = NULL; + + while (status == 0 && (curr = strchr(prev, '/')) != 0) { + /* + * Check for root or double slash + */ + if (curr != prev) { + *curr = '\0'; + status = do_mkdir(subpath, mode); + *curr = '/'; + } + prev = curr + 1; + } + if (status == 0) + status = do_mkdir(path, mode); + + free(subpath); + return status; +} + +static int tee_supp_fs_init(void) +{ + size_t n = 0; + mode_t mode = 0700; + + n = snprintf(tee_fs_root, sizeof(tee_fs_root), "%s/", supplicant_params.fs_parent_path); + + if (n >= sizeof(tee_fs_root)) + return -1; + + if (mkpath(tee_fs_root, mode) != 0) + return -1; + + return 0; +} + +static int open_wrapper(const char *fname, int flags) +{ + int fd = 0; + + while (true) { + fd = open(fname, flags | O_SYNC, 0600); + if (fd >= 0 || errno != EINTR) + return fd; + } +} + +static TEEC_Result ree_fs_new_open(size_t num_params, + struct tee_ioctl_param *params) +{ + char abs_filename[PATH_MAX] = { 0 }; + char *fname = NULL; + int fd = 0; + + if (num_params != 3 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || + (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + fname = tee_supp_param_to_va(params + 1); + if (!fname) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!tee_fs_get_absolute_filename(fname, abs_filename, + sizeof(abs_filename))) + return TEEC_ERROR_BAD_PARAMETERS; + + fd = open_wrapper(abs_filename, O_RDWR); + if (fd < 0) { + /* + * In case the problem is the filesystem is RO, retry with the + * open flags restricted to RO. + */ + fd = open_wrapper(abs_filename, O_RDONLY); + if (fd < 0) + return TEEC_ERROR_ITEM_NOT_FOUND; + } + + params[2].a = fd; + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_create(size_t num_params, + struct tee_ioctl_param *params) +{ + char abs_filename[PATH_MAX] = { 0 }; + char abs_dir[PATH_MAX] = { 0 }; + char *fname = NULL; + char *d = NULL; + int fd = 0; + const int flags = O_RDWR | O_CREAT | O_TRUNC; + + if (num_params != 3 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || + (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + fname = tee_supp_param_to_va(params + 1); + if (!fname) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!tee_fs_get_absolute_filename(fname, abs_filename, + sizeof(abs_filename))) + return TEEC_ERROR_BAD_PARAMETERS; + + fd = open_wrapper(abs_filename, flags); + if (fd >= 0) + goto out; + if (errno != ENOENT) + return errno_to_teec(errno); + + /* Directory for file missing, try make to it */ + strncpy(abs_dir, abs_filename, sizeof(abs_dir)); + abs_dir[sizeof(abs_dir) - 1] = '\0'; + d = dirname(abs_dir); + if (!mkdir(d, 0700)) { + int err = 0; + + fd = open_wrapper(abs_filename, flags); + if (fd >= 0) + goto out; + /* + * The directory was made but the file could still not be + * created. + */ + err = errno; + rmdir(d); + return errno_to_teec(err); + } + if (errno != ENOENT) + return errno_to_teec(errno); + + /* Parent directory for file missing, try to make it */ + d = dirname(d); + if (mkdir(d, 0700)) + return errno_to_teec(errno); + + /* Try to make directory for file again */ + strncpy(abs_dir, abs_filename, sizeof(abs_dir)); + abs_dir[sizeof(abs_dir) - 1] = '\0'; + d = dirname(abs_dir); + if (mkdir(d, 0700)) { + int err = errno; + + d = dirname(d); + rmdir(d); + return errno_to_teec(err); + } + + fd = open_wrapper(abs_filename, flags); + if (fd < 0) { + int err = errno; + + rmdir(d); + d = dirname(d); + rmdir(d); + return errno_to_teec(err); + } + +out: + fs_fsync(); + params[2].a = fd; + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_close(size_t num_params, + struct tee_ioctl_param *params) +{ + int fd = 0; + + if (num_params != 1 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + fd = params[0].b; + while (close(fd)) { + if (errno != EINTR) + return errno_to_teec(errno); + } + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_read(size_t num_params, + struct tee_ioctl_param *params) +{ + uint8_t *buf = NULL; + size_t len = 0; + off_t offs = 0; + int fd = 0; + ssize_t r = 0; + size_t s = 0; + + if (num_params != 2 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + fd = params[0].b; + offs = params[0].c; + + buf = tee_supp_param_to_va(params + 1); + if (!buf) + return TEEC_ERROR_BAD_PARAMETERS; + len = MEMREF_SIZE(params + 1); + + s = 0; + r = -1; + while (r && len) { + r = pread(fd, buf, len, offs); + if (r < 0) { + if (errno == EINTR) + continue; + return errno_to_teec(errno); + } + assert((size_t)r <= len); + buf += r; + len -= r; + offs += r; + s += r; + } + + MEMREF_SIZE(params + 1) = s; + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_write(size_t num_params, + struct tee_ioctl_param *params) +{ + uint8_t *buf = NULL; + size_t len = 0; + off_t offs = 0; + int fd = 0; + ssize_t r = 0; + + if (num_params != 2 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + fd = params[0].b; + offs = params[0].c; + + buf = tee_supp_param_to_va(params + 1); + if (!buf) + return TEEC_ERROR_BAD_PARAMETERS; + len = MEMREF_SIZE(params + 1); + + while (len) { + r = pwrite(fd, buf, len, offs); + if (r < 0) { + if (errno == EINTR) + continue; + return errno_to_teec(errno); + } + assert((size_t)r <= len); + buf += r; + len -= r; + offs += r; + } + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_truncate(size_t num_params, + struct tee_ioctl_param *params) +{ + size_t len = 0; + int fd = 0; + + if (num_params != 1 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + fd = params[0].b; + len = params[0].c; + + while (ftruncate(fd, len)) { + if (errno != EINTR) + return errno_to_teec(errno); + } + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_remove(size_t num_params, + struct tee_ioctl_param *params) +{ + char abs_filename[PATH_MAX] = { 0 }; + char *fname = NULL; + char *d = NULL; + + if (num_params != 2 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + fname = tee_supp_param_to_va(params + 1); + if (!fname) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!tee_fs_get_absolute_filename(fname, abs_filename, + sizeof(abs_filename))) + return TEEC_ERROR_BAD_PARAMETERS; + + if (unlink(abs_filename)) + return errno_to_teec(errno); + + /* If a file is removed, maybe the directory can be removed to? */ + d = dirname(abs_filename); + if (!rmdir(d)) { + /* + * If the directory was removed, maybe the parent directory + * can be removed too? + */ + d = dirname(d); + rmdir(d); + } + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_rename(size_t num_params, + struct tee_ioctl_param *params) +{ + char old_abs_filename[PATH_MAX] = { 0 }; + char new_abs_filename[PATH_MAX] = { 0 }; + char *old_fname = NULL; + char *new_fname = NULL; + bool overwrite = false; + + if (num_params != 3 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || + (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + overwrite = !!params[0].b; + + old_fname = tee_supp_param_to_va(params + 1); + if (!old_fname) + return TEEC_ERROR_BAD_PARAMETERS; + + new_fname = tee_supp_param_to_va(params + 2); + if (!new_fname) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!tee_fs_get_absolute_filename(old_fname, old_abs_filename, + sizeof(old_abs_filename))) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!tee_fs_get_absolute_filename(new_fname, new_abs_filename, + sizeof(new_abs_filename))) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!overwrite) { + struct stat st; + + if (!stat(new_abs_filename, &st)) + return TEEC_ERROR_ACCESS_CONFLICT; + } + if (rename(old_abs_filename, new_abs_filename)) { + if (errno == ENOENT) + return TEEC_ERROR_ITEM_NOT_FOUND; + } + + fs_fsync(); + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_opendir(size_t num_params, + struct tee_ioctl_param *params) +{ + char abs_filename[PATH_MAX] = { 0 }; + char *fname = NULL; + DIR *dir = NULL; + int handle = 0; + struct dirent *dent = NULL; + bool empty = true; + + if (num_params != 3 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT || + (params[2].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + fname = tee_supp_param_to_va(params + 1); + if (!fname) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!tee_fs_get_absolute_filename(fname, abs_filename, + sizeof(abs_filename))) + return TEEC_ERROR_BAD_PARAMETERS; + + dir = opendir(abs_filename); + if (!dir) + return TEEC_ERROR_ITEM_NOT_FOUND; + + /* + * Ignore empty directories. Works around an issue when the + * data path is mounted over NFS. Due to the way OP-TEE implements + * TEE_CloseAndDeletePersistentObject1() currently, tee-supplicant + * still has a file descriptor open to the file when it's removed in + * ree_fs_new_remove(). In this case the NFS server may create a + * temporary reference called .nfs????, and the rmdir() call fails + * so that the TA directory is left over. Checking this special case + * here avoids that TEE_StartPersistentObjectEnumerator() returns + * TEE_SUCCESS when it should return TEEC_ERROR_ITEM_NOT_FOUND. + * Test case: "xtest 6009 6010". + */ + while ((dent = readdir(dir))) { + if (dent->d_name[0] == '.') + continue; + empty = false; + break; + } + if (empty) { + closedir(dir); + return TEEC_ERROR_ITEM_NOT_FOUND; + } + rewinddir(dir); + + handle = handle_get(&dir_handle_db, dir); + if (handle < 0) { + closedir(dir); + return TEEC_ERROR_OUT_OF_MEMORY; + } + + params[2].a = handle; + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_closedir(size_t num_params, + struct tee_ioctl_param *params) +{ + DIR *dir = NULL; + + if (num_params != 1 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + dir = handle_put(&dir_handle_db, params[0].b); + if (!dir) + return TEEC_ERROR_BAD_PARAMETERS; + + closedir(dir); + + return TEEC_SUCCESS; +} + +static TEEC_Result ree_fs_new_readdir(size_t num_params, + struct tee_ioctl_param *params) +{ + DIR *dir = NULL; + struct dirent *dirent = NULL; + char *buf = NULL; + size_t len = 0; + size_t fname_len = 0; + + if (num_params != 2 || + (params[0].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT || + (params[1].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) != + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT) + return TEEC_ERROR_BAD_PARAMETERS; + + + buf = tee_supp_param_to_va(params + 1); + if (!buf) + return TEEC_ERROR_BAD_PARAMETERS; + len = MEMREF_SIZE(params + 1); + + dir = handle_lookup(&dir_handle_db, params[0].b); + if (!dir) + return TEEC_ERROR_BAD_PARAMETERS; + + while (true) { + dirent = readdir(dir); + if (!dirent) + return TEEC_ERROR_ITEM_NOT_FOUND; + if (dirent->d_name[0] != '.') + break; + } + + fname_len = strlen(dirent->d_name) + 1; + MEMREF_SIZE(params + 1) = fname_len; + if (fname_len > len) + return TEEC_ERROR_SHORT_BUFFER; + + memcpy(buf, dirent->d_name, fname_len); + + return TEEC_SUCCESS; +} + +TEEC_Result tee_supp_fs_process(size_t num_params, + struct tee_ioctl_param *params) +{ + if (!num_params || !tee_supp_param_is_value(params)) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!tee_fs_root[0]) { + if (tee_supp_fs_init() != 0) { + EMSG("error tee_supp_fs_init: failed to create %s/", + tee_fs_root); + memset(tee_fs_root, 0, sizeof(tee_fs_root)); + return TEEC_ERROR_STORAGE_NOT_AVAILABLE; + } + } + + switch (params->a) { + case OPTEE_MRF_OPEN: + return ree_fs_new_open(num_params, params); + case OPTEE_MRF_CREATE: + return ree_fs_new_create(num_params, params); + case OPTEE_MRF_CLOSE: + return ree_fs_new_close(num_params, params); + case OPTEE_MRF_READ: + return ree_fs_new_read(num_params, params); + case OPTEE_MRF_WRITE: + return ree_fs_new_write(num_params, params); + case OPTEE_MRF_TRUNCATE: + return ree_fs_new_truncate(num_params, params); + case OPTEE_MRF_REMOVE: + return ree_fs_new_remove(num_params, params); + case OPTEE_MRF_RENAME: + return ree_fs_new_rename(num_params, params); + case OPTEE_MRF_OPENDIR: + return ree_fs_new_opendir(num_params, params); + case OPTEE_MRF_CLOSEDIR: + return ree_fs_new_closedir(num_params, params); + case OPTEE_MRF_READDIR: + return ree_fs_new_readdir(num_params, params); + default: + return TEEC_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_client/tee-supplicant/src/tee_supp_fs.h b/optee/optee_client/tee-supplicant/src/tee_supp_fs.h new file mode 100644 index 0000000..43e13fe --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/tee_supp_fs.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_SUPP_FS_H +#define TEE_SUPP_FS_H + +#include + +struct tee_ioctl_param; + +TEEC_Result tee_supp_fs_process(size_t num_params, + struct tee_ioctl_param *params); + +#endif diff --git a/optee/optee_client/tee-supplicant/src/tee_supplicant.c b/optee/optee_client/tee-supplicant/src/tee_supplicant.c new file mode 100644 index 0000000..97d2bf4 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/tee_supplicant.c @@ -0,0 +1,995 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 +#include +#include + +#include "optee_msg_supplicant.h" + +#ifndef __aligned +#define __aligned(x) __attribute__((__aligned__(x))) +#endif +#include + +#define RPC_NUM_PARAMS 5 + +#define RPC_BUF_SIZE (sizeof(struct tee_iocl_supp_send_arg) + \ + RPC_NUM_PARAMS * sizeof(struct tee_ioctl_param)) + +char **ta_path; +char *ta_path_str; + +union tee_rpc_invoke { + uint64_t buf[(RPC_BUF_SIZE - 1) / sizeof(uint64_t) + 1]; + struct tee_iocl_supp_recv_arg recv; + struct tee_iocl_supp_send_arg send; +}; + +struct tee_shm { + int id; + void *p; + size_t size; + bool registered; + int fd; + struct tee_shm *next; +}; + +struct thread_arg { + int fd; + uint32_t gen_caps; + bool abort; + size_t num_waiters; + pthread_mutex_t mutex; +}; + +struct param_value { + uint64_t a; + uint64_t b; + uint64_t c; +}; + +static pthread_mutex_t shm_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct tee_shm *shm_head; + +struct tee_supplicant_params supplicant_params = { + .ta_dir = "optee_armtz", +#ifdef TEE_PLUGIN_LOAD_PATH + .plugin_load_path = TEE_PLUGIN_LOAD_PATH, +#endif + .fs_parent_path = TEE_FS_PARENT_PATH, +}; + +static void *thread_main(void *a); + +static size_t num_waiters_inc(struct thread_arg *arg) +{ + size_t ret = 0; + + tee_supp_mutex_lock(&arg->mutex); + arg->num_waiters++; + assert(arg->num_waiters); + ret = arg->num_waiters; + tee_supp_mutex_unlock(&arg->mutex); + + return ret; +} + +static size_t num_waiters_dec(struct thread_arg *arg) +{ + size_t ret = 0; + + tee_supp_mutex_lock(&arg->mutex); + assert(arg->num_waiters); + arg->num_waiters--; + ret = arg->num_waiters; + tee_supp_mutex_unlock(&arg->mutex); + + return ret; +} + +static void *paged_aligned_alloc(size_t sz) +{ + void *p = NULL; + + if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz)) + return p; + + return NULL; +} + +static int get_value(size_t num_params, struct tee_ioctl_param *params, + const uint32_t idx, struct param_value **value) +{ + if (idx >= num_params) + return -1; + + switch (params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + *value = (void *)¶ms[idx].a; + return 0; + default: + return -1; + } +} + +static struct tee_shm *find_tshm(int id) +{ + struct tee_shm *tshm = NULL; + + tee_supp_mutex_lock(&shm_mutex); + + tshm = shm_head; + while (tshm && tshm->id != id) + tshm = tshm->next; + + tee_supp_mutex_unlock(&shm_mutex); + + return tshm; +} + +static struct tee_shm *pop_tshm(int id) +{ + struct tee_shm *tshm = NULL; + struct tee_shm *prev = NULL; + + tee_supp_mutex_lock(&shm_mutex); + + tshm = shm_head; + if (!tshm) + goto out; + + if (tshm->id == id) { + shm_head = tshm->next; + goto out; + } + + do { + prev = tshm; + tshm = tshm->next; + if (!tshm) + goto out; + } while (tshm->id != id); + prev->next = tshm->next; + +out: + tee_supp_mutex_unlock(&shm_mutex); + + return tshm; +} + +static void push_tshm(struct tee_shm *tshm) +{ + tee_supp_mutex_lock(&shm_mutex); + + tshm->next = shm_head; + shm_head = tshm; + + tee_supp_mutex_unlock(&shm_mutex); +} + +/* Get parameter allocated by secure world */ +static int get_param(size_t num_params, struct tee_ioctl_param *params, + const uint32_t idx, TEEC_SharedMemory *shm) +{ + struct tee_shm *tshm = NULL; + size_t offs = 0; + size_t sz = 0; + + if (idx >= num_params) + return -1; + + switch (params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + break; + default: + return -1; + } + + memset(shm, 0, sizeof(*shm)); + + tshm = find_tshm(MEMREF_SHM_ID(params + idx)); + if (!tshm) { + /* + * It doesn't make sense to query required size of an + * input buffer. + */ + if ((params[idx].attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) == + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT) + return -1; + + /* + * Buffer isn't found, the caller is querying required size + * of the buffer. + */ + return 0; + } + + sz = MEMREF_SIZE(params + idx); + offs = MEMREF_SHM_OFFS(params + idx); + if ((sz + offs) < sz) + return -1; + if ((sz + offs) > tshm->size) + return -1; + + shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + shm->size = sz; + shm->id = MEMREF_SHM_ID(params + idx); + shm->buffer = (uint8_t *)tshm->p + offs; + + return 0; +} + +static void uuid_from_octets(TEEC_UUID *d, const uint8_t s[TEE_IOCTL_UUID_LEN]) +{ + d->timeLow = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; + d->timeMid = (s[4] << 8) | s[5]; + d->timeHiAndVersion = (s[6] << 8) | s[7]; + memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode)); +} + +static uint32_t load_ta(size_t num_params, struct tee_ioctl_param *params) +{ + int ta_found = 0; + size_t size = 0; + struct param_value *val_cmd = NULL; + TEEC_UUID uuid; + TEEC_SharedMemory shm_ta; + + memset(&uuid, 0, sizeof(uuid)); + memset(&shm_ta, 0, sizeof(shm_ta)); + + if (num_params != 2 || get_value(num_params, params, 0, &val_cmd) || + get_param(num_params, params, 1, &shm_ta)) + return TEEC_ERROR_BAD_PARAMETERS; + + uuid_from_octets(&uuid, (void *)val_cmd); + + size = shm_ta.size; + ta_found = TEECI_LoadSecureModule(supplicant_params.ta_dir, &uuid, shm_ta.buffer, &size); + if (ta_found != TA_BINARY_FOUND) { + EMSG(" TA not found"); + return TEEC_ERROR_ITEM_NOT_FOUND; + } + + MEMREF_SIZE(params + 1) = size; + + /* + * If a buffer wasn't provided, just tell which size it should be. + * If it was provided but isn't big enough, report an error. + */ + if (shm_ta.buffer && size > shm_ta.size) + return TEEC_ERROR_SHORT_BUFFER; + + return TEEC_SUCCESS; +} + +static struct tee_shm *alloc_shm(int fd, size_t size) +{ + struct tee_shm *shm = NULL; + struct tee_ioctl_shm_alloc_data data; + + memset(&data, 0, sizeof(data)); + + shm = calloc(1, sizeof(*shm)); + if (!shm) + return NULL; + + data.size = size; + shm->fd = ioctl(fd, TEE_IOC_SHM_ALLOC, &data); + if (shm->fd < 0) { + free(shm); + return NULL; + } + + shm->p = mmap(NULL, data.size, PROT_READ | PROT_WRITE, MAP_SHARED, + shm->fd, 0); + if (shm->p == (void *)MAP_FAILED) { + close(shm->fd); + free(shm); + return NULL; + } + + shm->id = data.id; + shm->registered = false; + return shm; +} + +static struct tee_shm *register_local_shm(int fd, size_t size) +{ + struct tee_shm *shm = NULL; + void *buf = NULL; + struct tee_ioctl_shm_register_data data; + + memset(&data, 0, sizeof(data)); + + buf = paged_aligned_alloc(size); + if (!buf) + return NULL; + + shm = calloc(1, sizeof(*shm)); + if (!shm) { + free(buf); + return NULL; + } + + data.addr = (uintptr_t)buf; + data.length = size; + + shm->fd = ioctl(fd, TEE_IOC_SHM_REGISTER, &data); + if (shm->fd < 0) { + free(shm); + free(buf); + return NULL; + } + + shm->p = buf; + shm->registered = true; + shm->id = data.id; + + return shm; +} + +static uint32_t process_alloc(struct thread_arg *arg, size_t num_params, + struct tee_ioctl_param *params) +{ + struct param_value *val = NULL; + struct tee_shm *shm = NULL; + + if (num_params != 1 || get_value(num_params, params, 0, &val)) + return TEEC_ERROR_BAD_PARAMETERS; + + if (arg->gen_caps & TEE_GEN_CAP_REG_MEM) + shm = register_local_shm(arg->fd, val->b); + else + shm = alloc_shm(arg->fd, val->b); + + if (!shm) + return TEEC_ERROR_OUT_OF_MEMORY; + + shm->size = val->b; + val->c = shm->id; + push_tshm(shm); + + return TEEC_SUCCESS; +} + +static uint32_t process_free(size_t num_params, struct tee_ioctl_param *params) +{ + struct param_value *val = NULL; + struct tee_shm *shm = NULL; + int id = 0; + + if (num_params != 1 || get_value(num_params, params, 0, &val)) + return TEEC_ERROR_BAD_PARAMETERS; + + id = val->b; + + shm = pop_tshm(id); + if (!shm) + return TEEC_ERROR_BAD_PARAMETERS; + + close(shm->fd); + if (shm->registered) { + free(shm->p); + } else { + if (munmap(shm->p, shm->size) != 0) { + EMSG("munmap(%p, %zu) failed - Error = %s", + shm->p, shm->size, strerror(errno)); + free(shm); + return TEEC_ERROR_BAD_PARAMETERS; + } + } + + free(shm); + return TEEC_SUCCESS; +} + + + +/* How many device sequence numbers will be tried before giving up */ +#define MAX_DEV_SEQ 10 + +static int open_dev(const char *devname, uint32_t *gen_caps) +{ + int fd = 0; + struct tee_ioctl_version_data vers; + + memset(&vers, 0, sizeof(vers)); + + fd = open(devname, O_RDWR); + if (fd < 0) + return -1; + + if (ioctl(fd, TEE_IOC_VERSION, &vers)) + goto err; + + /* Only OP-TEE supported */ + if (vers.impl_id != TEE_IMPL_ID_OPTEE) + goto err; + + if (gen_caps) + *gen_caps = vers.gen_caps; + + DMSG("using device \"%s\"", devname); + return fd; +err: + close(fd); + return -1; +} + +static int get_dev_fd(uint32_t *gen_caps) +{ + int fd = 0; + char name[PATH_MAX] = { 0 }; + size_t n = 0; + + for (n = 0; n < MAX_DEV_SEQ; n++) { + snprintf(name, sizeof(name), "/dev/teepriv%zu", n); + fd = open_dev(name, gen_caps); + if (fd >= 0) + return fd; + } + return -1; +} + +static int usage(int status) +{ + fprintf(stderr, "Usage: tee-supplicant [options] []\n"); + fprintf(stderr, "\t-h, --help: this help\n"); + fprintf(stderr, "\t-d, --daemonize: run as a daemon (fork and return " + "after child has opened the TEE device or on error)\n"); + fprintf(stderr, "\t-f, --fs-parent-path: secure fs parent path [%s]\n", + supplicant_params.fs_parent_path); + fprintf(stderr, "\t-t, --ta-dir: TAs dirname under %s [%s]\n", TEEC_LOAD_PATH, + supplicant_params.ta_dir); + fprintf(stderr, "\t-p, --plugin-path: plugin load path [%s]\n", + supplicant_params.plugin_load_path); + fprintf(stderr, "\t-r, --rpmb-cid: RPMB device identification register " + "(CID) in hexadecimal\n"); + return status; +} + +static uint32_t process_rpmb(size_t num_params, struct tee_ioctl_param *params) +{ + TEEC_SharedMemory req; + TEEC_SharedMemory rsp; + + memset(&req, 0, sizeof(req)); + memset(&rsp, 0, sizeof(rsp)); + + if (get_param(num_params, params, 0, &req) || + get_param(num_params, params, 1, &rsp)) + return TEEC_ERROR_BAD_PARAMETERS; + + return rpmb_process_request(req.buffer, req.size, rsp.buffer, rsp.size); +} + +static uint32_t process_nvme_rpmb(size_t num_params, struct tee_ioctl_param *params) +{ + TEEC_SharedMemory req; + TEEC_SharedMemory rsp; + + memset(&req, 0, sizeof(req)); + memset(&rsp, 0, sizeof(rsp)); + + if (get_param(num_params, params, 0, &req) || + get_param(num_params, params, 1, &rsp)) + return TEEC_ERROR_BAD_PARAMETERS; + + return nvme_rpmb_process_request(req.buffer, req.size, rsp.buffer, rsp.size); +} + +static bool read_request(int fd, union tee_rpc_invoke *request) +{ + struct tee_ioctl_buf_data data; + + memset(&data, 0, sizeof(data)); + + data.buf_ptr = (uintptr_t)request; + data.buf_len = sizeof(*request); + if (ioctl(fd, TEE_IOC_SUPPL_RECV, &data)) { + EMSG("TEE_IOC_SUPPL_RECV: %s", strerror(errno)); + return false; + } + return true; +} + +static bool write_response(int fd, union tee_rpc_invoke *request) +{ + struct tee_ioctl_buf_data data; + + memset(&data, 0, sizeof(data)); + + data.buf_ptr = (uintptr_t)&request->send; + data.buf_len = sizeof(struct tee_iocl_supp_send_arg) + + sizeof(struct tee_ioctl_param) * + (__u64)request->send.num_params; + if (ioctl(fd, TEE_IOC_SUPPL_SEND, &data)) { + EMSG("TEE_IOC_SUPPL_SEND: %s", strerror(errno)); + return false; + } + return true; +} + +static bool find_params(union tee_rpc_invoke *request, uint32_t *func, + size_t *num_params, struct tee_ioctl_param **params, + size_t *num_meta) +{ + struct tee_ioctl_param *p = NULL; + size_t n = 0; + + p = (struct tee_ioctl_param *)(&request->recv + 1); + + /* Skip meta parameters in the front */ + for (n = 0; n < request->recv.num_params; n++) + if (!(p[n].attr & TEE_IOCTL_PARAM_ATTR_META)) + break; + + *func = request->recv.func; + *num_params = request->recv.num_params - n; + *params = p + n; + *num_meta = n; + + /* Make sure that no meta parameters follows a non-meta parameter */ + for (; n < request->recv.num_params; n++) { + if (p[n].attr & TEE_IOCTL_PARAM_ATTR_META) { + EMSG("Unexpected meta parameter"); + return false; + } + } + + return true; +} + +static bool spawn_thread(struct thread_arg *arg) +{ + int e = 0; + pthread_t tid; + + memset(&tid, 0, sizeof(tid)); + + DMSG("Spawning a new thread"); + + /* + * Increase number of waiters now to avoid starting another thread + * before this thread has been scheduled. + */ + num_waiters_inc(arg); + + e = pthread_create(&tid, NULL, thread_main, arg); + if (e) { + EMSG("pthread_create: %s", strerror(e)); + num_waiters_dec(arg); + return false; + } + + e = pthread_detach(tid); + if (e) + EMSG("pthread_detach: %s", strerror(e)); + + return true; +} + +static bool process_one_request(struct thread_arg *arg) +{ + size_t num_params = 0; + size_t num_meta = 0; + struct tee_ioctl_param *params = NULL; + uint32_t func = 0; + uint32_t ret = 0; + union tee_rpc_invoke request; + + memset(&request, 0, sizeof(request)); + + DMSG("looping"); + request.recv.num_params = RPC_NUM_PARAMS; + + /* Let it be known that we can deal with meta parameters */ + params = (struct tee_ioctl_param *)(&request.send + 1); + params->attr = TEE_IOCTL_PARAM_ATTR_META; + + num_waiters_inc(arg); + + if (!read_request(arg->fd, &request)) + return false; + + if (!find_params(&request, &func, &num_params, ¶ms, &num_meta)) + return false; + + if (num_meta && !num_waiters_dec(arg) && !spawn_thread(arg)) + return false; + + switch (func) { + case OPTEE_MSG_RPC_CMD_LOAD_TA: + ret = load_ta(num_params, params); + break; + case OPTEE_MSG_RPC_CMD_FS: + ret = tee_supp_fs_process(num_params, params); + break; + case OPTEE_MSG_RPC_CMD_RPMB: + ret = process_rpmb(num_params, params); + break; + case OPTEE_MSG_RPC_CMD_SHM_ALLOC: + ret = process_alloc(arg, num_params, params); + break; + case OPTEE_MSG_RPC_CMD_SHM_FREE: + ret = process_free(num_params, params); + break; + case OPTEE_MSG_RPC_CMD_GPROF: + ret = prof_process(num_params, params, "gmon-"); + break; + case OPTEE_MSG_RPC_CMD_SOCKET: + ret = tee_socket_process(num_params, params); + break; + case OPTEE_MSG_RPC_CMD_FTRACE: + ret = prof_process(num_params, params, "ftrace-"); + break; + case OPTEE_MSG_RPC_CMD_PLUGIN: + ret = plugin_process(num_params, params); + break; + case OPTEE_MSG_RPC_CMD_NVME_RPMB: + ret = process_nvme_rpmb(num_params, params); + break; + default: + EMSG("Cmd [0x%" PRIx32 "] not supported", func); + /* Not supported. */ + ret = TEEC_ERROR_NOT_SUPPORTED; + break; + } + + request.send.ret = ret; + return write_response(arg->fd, &request); +} + +static void *thread_main(void *a) +{ + struct thread_arg *arg = a; + + /* + * Now that this thread has been scheduled, compensate for the + * initial increase in spawn_thread() before. + */ + num_waiters_dec(arg); + + while (!arg->abort) { + if (!process_one_request(arg)) + arg->abort = true; + } + + return NULL; +} + +#define TEEC_TEST_LOAD_PATH "/foo:/bar::/baz" + +static void set_ta_path(void) +{ + char *p = NULL; + char *saveptr = NULL; + const char *path = (char *) +#ifdef TEEC_TEST_LOAD_PATH + TEEC_TEST_LOAD_PATH ":" +#endif + TEEC_LOAD_PATH; + size_t n = 0; + + ta_path_str = strdup(path); + if (!ta_path_str) + goto err; + + p = ta_path_str; + while (strtok_r(p, ":", &saveptr)) { + p = NULL; + n++; + } + n++; /* NULL terminator */ + + ta_path = malloc(n * sizeof(char *)); + if (!ta_path) + goto err; + + n = 0; + strcpy(ta_path_str, path); + p = ta_path_str; + while ((ta_path[n++] = strtok_r(p, ":", &saveptr))) + p = NULL; + + return; +err: + EMSG("out of memory"); + exit(EXIT_FAILURE); +} + +/* + * Similar to the standard libc function daemon(0, 0) but the parent process + * issues a blocking read on pipefd[0] before exiting. + * Returns 0 on success, <0 on error. + */ +static int make_daemon(int pipefd[2]) +{ + int fd = 0; + char c = 0; + int n = 0; + + switch (fork()) { + case -1: + return -1; + case 0: + /* In child */ + close(pipefd[0]); + break; + default: + /* In parent */ + close(pipefd[1]); + n = read(pipefd[0], &c, 1); + close(pipefd[0]); + if (!n) { + /* + * Nothing has been read: child has closed without + * writing (either exited on error or crashed) + */ + return -1; + } + /* Child is done with the opening of the TEE device */ + _exit(EXIT_SUCCESS); + } + + if (setsid() < 0) + return -2; + + if (chdir("/") < 0) + return -3; + + fd = open("/dev/null", O_RDWR); + if (fd < 0) + return -4; + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + + return 0; +} + +int main(int argc, char *argv[]) +{ + struct thread_arg arg = { .fd = -1 }; + int pipefd[2] = { 0, }; + bool daemonize = false; + char *dev = NULL; + int e = 0; + int long_index = 0; + int opt = 0; + + e = pthread_mutex_init(&arg.mutex, NULL); + if (e) { + EMSG("pthread_mutex_init: %s", strerror(e)); + EMSG("terminating..."); + exit(EXIT_FAILURE); + } + + static struct option long_options[] = { + /* long name | has argument | flag | short value */ + { "help", no_argument, 0, 'h' }, + { "daemonize", no_argument, 0, 'd' }, + { "fs-parent-path", required_argument, 0, 'f' }, + { "ta-dir", required_argument, 0, 't' }, + { "plugin-path", required_argument, 0, 'p' }, + { "rpmb-cid", required_argument, 0, 'r' }, + { 0, 0, 0, 0 } + }; + + while ((opt = getopt_long(argc, argv, "hdf:t:p:r:", + long_options, &long_index )) != -1) { + switch (opt) { + case 'h' : + return usage(EXIT_SUCCESS); + break; + case 'd': + daemonize = true; + break; + case 'f': + supplicant_params.fs_parent_path = optarg; + break; + case 't': + supplicant_params.ta_dir = optarg; + break; + case 'p': + supplicant_params.plugin_load_path = optarg; + break; + case 'r': + supplicant_params.rpmb_cid = optarg; + break; + default: + return usage(EXIT_FAILURE); + } + } + /* check for non option argument, which is device name */ + if (argv[optind]) { + fprintf(stderr, "Using device %s.\n", argv[optind]); + dev = argv[optind]; + /* check that we do not have too many arguments */ + if (argv[optind + 1]) { + fprintf(stderr, "Too many arguments passed: extra argument: %s.\n", + argv[optind+1]); + return usage(EXIT_FAILURE); + } + } + + + set_ta_path(); + + if (plugin_load_all() != 0) { + EMSG("failed to load plugins"); + exit(EXIT_FAILURE); + } + + if (daemonize) { + if (pipe(pipefd) < 0) { + EMSG("pipe(): %s", strerror(errno)); + exit(EXIT_FAILURE); + } + e = make_daemon(pipefd); + if (e < 0) { + EMSG("make_daemon(): %d", e); + exit(EXIT_FAILURE); + } + } + + if (dev) { + arg.fd = open_dev(dev, &arg.gen_caps); + if (arg.fd < 0) { + EMSG("failed to open \"%s\"", argv[1]); + exit(EXIT_FAILURE); + } + } else { + arg.fd = get_dev_fd(&arg.gen_caps); + if (arg.fd < 0) { + EMSG("failed to find an OP-TEE supplicant device"); + exit(EXIT_FAILURE); + } + } + + if (daemonize) { + /* Release parent */ + if (write(pipefd[1], "", 1) != 1) { + EMSG("write(): %s", strerror(errno)); + exit(EXIT_FAILURE); + } + close(pipefd[1]); + } + + while (!arg.abort) { + if (!process_one_request(&arg)) + arg.abort = true; + } + + close(arg.fd); + + return EXIT_FAILURE; +} + +bool tee_supp_param_is_memref(struct tee_ioctl_param *param) +{ + switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + return true; + default: + return false; + } +} + +bool tee_supp_param_is_value(struct tee_ioctl_param *param) +{ + switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT: + return true; + default: + return false; + } +} + +void *tee_supp_param_to_va(struct tee_ioctl_param *param) +{ + struct tee_shm *tshm = NULL; + size_t end_offs = 0; + + if (!tee_supp_param_is_memref(param)) + return NULL; + + end_offs = MEMREF_SIZE(param) + MEMREF_SHM_OFFS(param); + if (end_offs < MEMREF_SIZE(param) || end_offs < MEMREF_SHM_OFFS(param)) + return NULL; + + tshm = find_tshm(MEMREF_SHM_ID(param)); + if (!tshm) + return NULL; + + if (end_offs > tshm->size) + return NULL; + + return (uint8_t *)tshm->p + MEMREF_SHM_OFFS(param); +} + +void tee_supp_mutex_lock(pthread_mutex_t *mu) +{ + int e = pthread_mutex_lock(mu); + + if (e) { + EMSG("pthread_mutex_lock: %s", strerror(e)); + EMSG("terminating..."); + exit(EXIT_FAILURE); + } +} + +void tee_supp_mutex_unlock(pthread_mutex_t *mu) +{ + int e = pthread_mutex_unlock(mu); + + if (e) { + EMSG("pthread_mutex_unlock: %s", strerror(e)); + EMSG("terminating..."); + exit(EXIT_FAILURE); + } +} diff --git a/optee/optee_client/tee-supplicant/src/tee_supplicant.h b/optee/optee_client/tee-supplicant/src/tee_supplicant.h new file mode 100644 index 0000000..cf98ac8 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/tee_supplicant.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016, Linaro Limited + * 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_SUPPLICANT_H +#define TEE_SUPPLICANT_H + +#include +#include + +/* Helpers to access memref parts of a struct tee_ioctl_param */ +#define MEMREF_SHM_ID(p) ((p)->c) +#define MEMREF_SHM_OFFS(p) ((p)->a) +#define MEMREF_SIZE(p) ((p)->b) + +struct tee_ioctl_param; + +/* Global tee-supplicant parameters */ +struct tee_supplicant_params { + const char *ta_dir; + const char *plugin_load_path; + const char *fs_parent_path; + const char *rpmb_cid; +}; + +extern struct tee_supplicant_params supplicant_params; + +bool tee_supp_param_is_memref(struct tee_ioctl_param *param); +bool tee_supp_param_is_value(struct tee_ioctl_param *param); +void *tee_supp_param_to_va(struct tee_ioctl_param *param); + +void tee_supp_mutex_lock(pthread_mutex_t *mu); +void tee_supp_mutex_unlock(pthread_mutex_t *mu); + +#endif /*TEE_SUPPLICANT_H*/ diff --git a/optee/optee_client/tee-supplicant/src/teec_ta_load.c b/optee/optee_client/tee-supplicant/src/teec_ta_load.c new file mode 100644 index 0000000..2cb5e98 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/teec_ta_load.c @@ -0,0 +1,192 @@ +/* + * 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 + +/* + * Attempt to first load TAs from a writable directory. This is + * intended for testing (xtest 1008, load_corrupt_ta specifically), + * and should not be enabled in a production system, as it would + * greatly facilitate loading rogue TA code. + */ +#ifdef CFG_TA_TEST_PATH +# ifndef TEEC_TEST_LOAD_PATH +# ifdef __ANDROID__ +# define TEEC_TEST_LOAD_PATH "/data/vendor/tee" +# else +# define TEEC_TEST_LOAD_PATH "/tmp" +# endif +# endif +#endif + +#ifndef PATH_MAX +#define PATH_MAX 255 +#endif + +struct tee_rpc_cmd { + void *buffer; + uint32_t size; + uint32_t type; + int fd; +}; + +/* + * Based on the uuid this function will try to find a TA-binary on the + * filesystem and return it back to the caller in the parameter ta. + * + * @param: prefix Prefix for TA load path + * @param: dev_path Where to load the TA from. The full path to the TA + * binary is @prefix/@dev_path/@destination.ta. + * @param: destination The uuid of the TA we are searching for. + * @param: ta A pointer which this function will allocate and copy + * the TA from the filesystem to the pointer itself. It is + * the callers responsibility to free the pointer. + * @param: ta_size The size of the TA found on file system. It will be 0 + * if no TA was not found. + * + * @return 0 if TA was found, otherwise -1. + */ +static int try_load_secure_module(const char* prefix, + const char* dev_path, + const TEEC_UUID *destination, void *ta, + size_t *ta_size) +{ + char fname[PATH_MAX] = { 0 }; + FILE *file = NULL; + bool first_try = true; + size_t s = 0; + long l = 0; + int n = 0; + + if (!ta_size || !destination) { + DMSG("wrong inparameter to TEECI_LoadSecureModule"); + return TA_BINARY_NOT_FOUND; + } + + /* + * We expect the TA binary to be named after the UUID as per RFC4122, + * that is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ta + * If the file cannot be open, try the deprecated format: + * xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx.ta + */ +again: + n = snprintf(fname, PATH_MAX, + "%s/%s/%08x-%04x-%04x-%02x%02x%s%02x%02x%02x%02x%02x%02x.ta", + prefix, dev_path, + destination->timeLow, + destination->timeMid, + destination->timeHiAndVersion, + destination->clockSeqAndNode[0], + destination->clockSeqAndNode[1], + first_try ? "-" : "", + destination->clockSeqAndNode[2], + destination->clockSeqAndNode[3], + destination->clockSeqAndNode[4], + destination->clockSeqAndNode[5], + destination->clockSeqAndNode[6], + destination->clockSeqAndNode[7]); + + DMSG("Attempt to load %s", fname); + + if ((n < 0) || (n >= PATH_MAX)) { + EMSG("wrong TA path [%s]", fname); + return TA_BINARY_NOT_FOUND; + } + + file = fopen(fname, "r"); + if (file == NULL) { + DMSG("failed to open the ta %s TA-file", fname); + if (first_try) { + first_try = false; + goto again; + } + return TA_BINARY_NOT_FOUND; + } + + if (fseek(file, 0, SEEK_END) != 0) { + fclose(file); + return TA_BINARY_NOT_FOUND; + } + + l = ftell(file); + if (l < 0) { + DMSG("failed to ftell the ta %s TA-file", fname); + fclose(file); + return TA_BINARY_NOT_FOUND; + } + + s = l; + if (s > *ta_size || !ta) { + /* + * Buffer isn't large enough, return the required size to + * let the caller increase the size of the buffer and try + * again. + */ + goto out; + } + + if (fseek(file, 0, SEEK_SET) != 0) { + fclose(file); + return TA_BINARY_NOT_FOUND; + } + + if (s != fread(ta, 1, s, file)) { + DMSG("failed to fread the ta %s TA-file", fname); + fclose(file); + return TA_BINARY_NOT_FOUND; + } + +out: + *ta_size = s; + fclose(file); + return TA_BINARY_FOUND; +} + +int TEECI_LoadSecureModule(const char* dev_path, + const TEEC_UUID *destination, void *ta, + size_t *ta_size) +{ + int res = TA_BINARY_NOT_FOUND; + char **path = NULL; + + for (path = ta_path; *path; path++) { + res = try_load_secure_module(*path, dev_path, destination, ta, + ta_size); + if (res == TA_BINARY_FOUND) + break; + } + return res; +} diff --git a/optee/optee_client/tee-supplicant/src/teec_ta_load.h b/optee/optee_client/tee-supplicant/src/teec_ta_load.h new file mode 100644 index 0000000..c89f4a0 --- /dev/null +++ b/optee/optee_client/tee-supplicant/src/teec_ta_load.h @@ -0,0 +1,55 @@ +/* + * 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 _TEEC_TA_LOAD_H +#define _TEEC_TA_LOAD_H +#include + +#define TA_BINARY_FOUND 0 +#define TA_BINARY_NOT_FOUND -1 + +/* Heap copy of TA load paths, separated by '\0' (access via ta_path) */ +extern char *ta_path_str; +/* NULL-terminated list of paths (pointers into ta_path_str) */ +extern char **ta_path; + +/** + * Based on the uuid this function will try to find a TA-binary on the + * filesystem and return it back to the caller in the parameter ta. + * + * @param: destination The uuid of the TA we are searching for. + * @param: ta A pointer which this function will copy + * the TA from the filesystem to if *@ta_size i large + * enough. + * @param: ta_size The size of the TA found on file system. It will be 0 + * if no TA was not found. + * + * @return 0 if TA was found, otherwise -1. + */ +int TEECI_LoadSecureModule(const char *name, + const TEEC_UUID *destination, void *ta, + size_t *ta_size); +#endif diff --git a/optee/optee_client/tee-supplicant/tee_supplicant_android.mk b/optee/optee_client/tee-supplicant/tee_supplicant_android.mk new file mode 100644 index 0000000..49bc388 --- /dev/null +++ b/optee/optee_client/tee-supplicant/tee_supplicant_android.mk @@ -0,0 +1,74 @@ +################################################################################ +# Build tee supplicant # +################################################################################ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_CFLAGS += $(optee_CFLAGS) + +LOCAL_CFLAGS += -DDEBUGLEVEL_$(CFG_TEE_SUPP_LOG_LEVEL) \ + -DBINARY_PREFIX=\"TEES\" \ + -DTEE_FS_PARENT_PATH=\"$(CFG_TEE_FS_PARENT_PATH)\" \ + -DTEEC_LOAD_PATH=\"$(CFG_TEE_CLIENT_LOAD_PATH)\" + +ifneq ($(TEEC_TEST_LOAD_PATH),) +LOCAL_CFLAGS += -DTEEC_TEST_LOAD_PATH=\"$(TEEC_TEST_LOAD_PATH)\" +endif + +ifeq ($(CFG_TA_TEST_PATH),y) +LOCAL_CFLAGS += -DCFG_TA_TEST_PATH=1 +endif + +LOCAL_SRC_FILES += src/tee_supplicant.c \ + src/teec_ta_load.c \ + src/tee_supp_fs.c \ + src/rpmb.c \ + src/handle.c + +ifeq ($(CFG_GP_SOCKETS),y) +LOCAL_SRC_FILES += src/tee_socket.c +LOCAL_CFLAGS += -DCFG_GP_SOCKETS=1 +endif + +RPMB_EMU ?= 1 +ifeq ($(RPMB_EMU),1) +LOCAL_SRC_FILES += src/sha2.c src/hmac_sha2.c +LOCAL_CFLAGS += -DRPMB_EMU=1 +endif + +ifneq (,$(filter y,$(CFG_TA_GPROF_SUPPORT) $(CFG_FTRACE_SUPPORT))) +LOCAL_SRC_FILES += src/prof.c +endif + +ifeq ($(CFG_TA_GPROF_SUPPORT),y) +LOCAL_CFLAGS += -DCFG_TA_GPROF_SUPPORT +endif + +ifeq ($(CFG_TEE_SUPP_PLUGINS),y) +LOCAL_SRC_FILES += src/plugin.c + +LOCAL_CFLAGS += -DTEE_SUPP_PLUGINS \ + -DTEE_PLUGIN_LOAD_PATH=\"$(CFG_TEE_PLUGIN_LOAD_PATH)\" + +# Needed to dynamically load user plugins +LOCAL_LDFLAGS += -ldl +# Needed for dlopen() +LOCAL_LDFLAGS += -Wl,-rpath=$(CFG_TEE_PLUGIN_LOAD_PATH) +endif + +LOCAL_CFLAGS += -pthread + +ifeq ($(CFG_FTRACE_SUPPORT),y) +LOCAL_CFLAGS += -DCFG_FTRACE_SUPPORT +endif + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../public \ + $(LOCAL_PATH)/../libteec/include \ + $(LOCAL_PATH)/src + +LOCAL_SHARED_LIBRARIES := libteec + +LOCAL_MODULE := tee-supplicant +LOCAL_MODULE_TAGS := optional +LOCAL_VENDOR_MODULE := true +include $(BUILD_EXECUTABLE) diff --git a/optee/optee_client/typedefs.checkpatch b/optee/optee_client/typedefs.checkpatch new file mode 100644 index 0000000..84d846e --- /dev/null +++ b/optee/optee_client/typedefs.checkpatch @@ -0,0 +1,80 @@ +# Note: please keep the entries in this file sorted in reverse alphabetical +# order (sort -r) +TEEC_Result +TEEC_Context +TEEC_UUID +TEEC_SharedMemory +TEEC_TempMemoryReference +TEEC_RegisteredMemoryReference +TEEC_Value +TEEC_Parameter +TEEC_Session +TEEC_Operation +CK_VOID_PTR_PTR +CK_VOID_PTR +CK_VERSION_PTR +CK_VERSION +CK_UTF8CHAR_PTR +CK_UTF8CHAR +CK_USER_TYPE +CK_UNLOCKMUTEX +CK_ULONG_PTR +CK_ULONG +CK_TOKEN_INFO_PTR +CK_TOKEN_INFO +CK_STATE +CK_SLOT_INFO_PTR +CK_SLOT_INFO +CK_SLOT_ID_PTR +CK_SLOT_ID +CK_SESSION_INFO_PTR +CK_SESSION_INFO +CK_SESSION_HANDLE_PTR +CK_SESSION_HANDLE +CK_RV +CK_OBJECT_HANDLE_PTR +CK_OBJECT_HANDLE +CK_OBJECT_CLASS_PTR +CK_OBJECT_CLASS +CK_NOTIFY +CK_NOTIFICATION +CK_MECHANISM_TYPE_PTR +CK_MECHANISM_TYPE +CK_MECHANISM_PTR +CK_MECHANISM_INFO_PTR +CK_MECHANISM_INFO +CK_MECHANISM +CK_MAC_GENERAL_PARAMS_PTR +CK_MAC_GENERAL_PARAMS +CK_LONG +CK_LOCKMUTEX +CK_KEY_TYPE_PTR +CK_KEY_TYPE +CK_INFO_PTR +CK_INFO +CK_GCM_PARAMS_PTR +CK_GCM_PARAMS +CK_FUNCTION_LIST_PTR_PTR +CK_FUNCTION_LIST_PTR +CK_FUNCTION_LIST +CK_FLAGS +CK_DESTROYMUTEX +CK_DATE_PTR +CK_DATE +CK_CREATEMUTEX +CK_C_INITIALIZE_ARGS_PTR +CK_C_INITIALIZE_ARGS +CK_CHAR_PTR +CK_CHAR +CK_CCM_PARAMS_PTR +CK_CCM_PARAMS +CK_BYTE_PTR +CK_BYTE +CK_BBOOL +CK_ATTRIBUTE_TYPE +CK_ATTRIBUTE_PTR +CK_ATTRIBUTE +CK_AES_CTR_PARAMS_PTR +CK_AES_CTR_PARAMS +CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR +CK_AES_CBC_ENCRYPT_DATA_PARAMS diff --git a/optee/optee_os/.checkpatch.conf b/optee/optee_os/.checkpatch.conf new file mode 100644 index 0000000..8d1e1d9 --- /dev/null +++ b/optee/optee_os/.checkpatch.conf @@ -0,0 +1,13 @@ +--codespell +--no-tree +--quiet +--strict +--max-line-length=80 +--ignore=CAMELCASE +--ignore=CONCATENATED_STRING +--ignore=FILE_PATH_CHANGES +--ignore=GERRIT_CHANGE_ID +--ignore=NOT_UNIFIED_DIFF +--ignore=PREFER_KERNEL_TYPES +--ignore=USLEEP_RANGE +--kconfig-prefix=CFG_ diff --git a/optee/optee_os/.github/issue_template.md b/optee/optee_os/.github/issue_template.md new file mode 100644 index 0000000..0b6f432 --- /dev/null +++ b/optee/optee_os/.github/issue_template.md @@ -0,0 +1,21 @@ + diff --git a/optee/optee_os/.github/pull_request_template.md b/optee/optee_os/.github/pull_request_template.md new file mode 100644 index 0000000..03cb067 --- /dev/null +++ b/optee/optee_os/.github/pull_request_template.md @@ -0,0 +1,19 @@ + diff --git a/optee/optee_os/.github/workflows/ci-cancel.yml b/optee/optee_os/.github/workflows/ci-cancel.yml new file mode 100644 index 0000000..19119f5 --- /dev/null +++ b/optee/optee_os/.github/workflows/ci-cancel.yml @@ -0,0 +1,22 @@ +# Cancel previous CI workflows that are still running when a new one is +# requested with the same ID. Happens when a branch is pushed to, +# including when a PR is updated. It would be wasteful to leave CI +# running on obsolete content. +# See https://github.com/marketplace/actions/cancel-workflow-action#advanced-pull-requests-from-forks +name: Cancel obsolete CI +on: + workflow_run: + workflows: [CI] + types: [requested] + branches-ignore: [master] +permissions: {} +jobs: + cancel: + permissions: + actions: write # to cancel/stop running workflows (styfle/cancel-workflow-action) + name: Cancel obsolete CI workflows + runs-on: ubuntu-latest + steps: + - uses: styfle/cancel-workflow-action@0.10.0 + with: + workflow_id: ${{ github.event.workflow.id }} diff --git a/optee/optee_os/.github/workflows/ci.yml b/optee/optee_os/.github/workflows/ci.yml new file mode 100644 index 0000000..48c1b10 --- /dev/null +++ b/optee/optee_os/.github/workflows/ci.yml @@ -0,0 +1,387 @@ +name: CI +on: [push, pull_request] +permissions: + contents: read # to fetch code (actions/checkout) +jobs: + code_style: + name: Code style + runs-on: ubuntu-latest + container: jforissier/optee_os_ci + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 # full history so checkpatch can check commit IDs in commit messages + - name: Update Git config + run: git config --global --add safe.directory ${GITHUB_WORKSPACE} + - name: Run checkpatch + shell: bash + run: | + # checkpatch task + set -e + git config --global --add safe.directory /__w/optee_os/optee_os + pushd . >/dev/null + mkdir -p /tmp/linux/scripts + cd /tmp/linux/scripts + wget --quiet https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/plain/scripts/checkpatch.pl + chmod +x checkpatch.pl + wget --quiet https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/plain/scripts/spelling.txt + echo "invalid.struct.name" >const_structs.checkpatch + export PATH=/tmp/linux/scripts:$PATH + popd >/dev/null + source scripts/checkpatch_inc.sh + function _do() { echo '>>' $*; $*; } + # Run checkpatch.pl: + # - on the tip of the branch only if we're not in a pull request + # - otherwise: + # * on each commit in the development branch that is not in the target (merge to) branch + # * on the global diff if the PR contains more than one commit (useful to check if fixup + # commits do solve previous checkpatch errors) + if [ "${GITHUB_EVENT_NAME}" = "push" ]; then \ + _do checkpatch HEAD || failed=1; \ + else \ + for c in $(git rev-list HEAD^1..HEAD^2); do \ + _do checkpatch $c || failed=1; \ + done; \ + if [ "$(git rev-list --count HEAD^1..HEAD^2)" -gt 1 ]; then \ + _do checkdiff $(git rev-parse HEAD^1) $(git rev-parse HEAD^2) || failed=1; \ + fi; \ + fi + [ -z "$failed" ] + - name: Run pycodestyle + if: success() || failure() + run: | + # pycodestyle task + sudo -E bash -c "apt update -qq -y && apt install -qq -y pycodestyle" + pycodestyle scripts/*.py core/arch/arm/plat-stm32mp1/scripts/stm32image.py + builds: + name: make (multi-platform) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci + steps: + - name: Restore build cache + uses: actions/cache@v3 + with: + path: /github/home/.cache/ccache + key: builds-cache-${{ github.sha }} + restore-keys: | + builds-cache- + - name: Checkout + uses: actions/checkout@v3 + - shell: bash + run: | + # build task + set -e -v + export LC_ALL=C + export PATH=/usr/local/bin:$PATH # clang + export CROSS_COMPILE32="ccache arm-linux-gnueabihf-" + export CROSS_COMPILE64="ccache aarch64-linux-gnu-" + export CFG_DEBUG_INFO=n + export CFG_WERROR=y + + function _make() { make -j$(nproc) -s O=out $*; } + function download_plug_and_trust() { mkdir -p $HOME/se050 && git clone --single-branch -b v0.4.2 https://github.com/foundriesio/plug-and-trust $HOME/se050/plug-and-trust || (rm -rf $HOME/se050 ; echo Nervermind); } + function download_scp_firmware() { git clone --single-branch https://github.com/ARM-software/SCP-firmware.git $HOME/scp-firmware || echo Nervermind; } + + ccache -s -v + download_plug_and_trust + download_scp_firmware + + _make + _make COMPILER=clang + _make CFG_TEE_CORE_LOG_LEVEL=4 CFG_TEE_CORE_DEBUG=y CFG_TEE_TA_LOG_LEVEL=4 CFG_CC_OPT_LEVEL=0 CFG_DEBUG_INFO=y + _make CFG_TEE_CORE_LOG_LEVEL=0 CFG_TEE_CORE_DEBUG=n CFG_TEE_TA_LOG_LEVEL=0 CFG_DEBUG_INFO=n CFG_ENABLE_EMBEDDED_TESTS=n + _make CFG_TEE_CORE_MALLOC_DEBUG=y CFG_CORE_DEBUG_CHECK_STACKS=y + _make CFG_CORE_SANITIZE_KADDRESS=y + _make CFG_LOCKDEP=y + _make CFG_CRYPTO=n + _make CFG_CRYPTO_{AES,DES}=n + _make CFG_CRYPTO_{DSA,RSA,DH}=n + _make CFG_CRYPTO_{DSA,RSA,DH,ECC}=n + _make CFG_CRYPTO_{H,C,CBC_}MAC=n + _make CFG_CRYPTO_{G,C}CM=n + _make CFG_CRYPTO_{MD5,SHA{1,224,256,384,512,512_256}}=n + _make CFG_WITH_PAGER=y out/core/tee{,-pager,-pageable}.bin + _make CFG_WITH_PAGER=y CFG_CRYPTOLIB_NAME=mbedtls CFG_CRYPTOLIB_DIR=lib/libmbedtls + _make CFG_WITH_PAGER=y CFG_WITH_LPAE=y + _make CFG_WITH_LPAE=y + _make CFG_CORE_PREALLOC_EL0_TBLS=y + _make CFG_RPMB_FS=y + _make CFG_RPMB_FS=y CFG_RPMB_TESTKEY=y + _make CFG_REE_FS=n CFG_RPMB_FS=y + _make CFG_WITH_PAGER=y CFG_WITH_LPAE=y CFG_RPMB_FS=y CFG_DT=y CFG_TEE_CORE_LOG_LEVEL=1 CFG_TEE_CORE_DEBUG=y CFG_CC_OPT_LEVEL=0 CFG_DEBUG_INFO=y + _make CFG_WITH_PAGER=y CFG_WITH_LPAE=y CFG_RPMB_FS=y CFG_DT=y CFG_TEE_CORE_LOG_LEVEL=0 CFG_TEE_CORE_DEBUG=n DEBUG=0 + _make CFG_BUILT_IN_ARGS=y CFG_PAGEABLE_ADDR=0 CFG_NS_ENTRY_ADDR=0 CFG_DT_ADDR=0 CFG_DT=y + _make CFG_FTRACE_SUPPORT=y CFG_ULIBS_MCOUNT=y CFG_ULIBS_SHARED=y + _make CFG_TA_GPROF_SUPPORT=y CFG_FTRACE_SUPPORT=y CFG_SYSCALL_FTRACE=y CFG_ULIBS_MCOUNT=y + _make CFG_SECURE_DATA_PATH=y + _make CFG_REE_FS_TA_BUFFERED=y + _make CFG_WITH_USER_TA=n + _make CFG_{ATTESTATION,DEVICE_ENUM,RTC,SCMI,SECSTOR_TA_MGT}_PTA=y CFG_WITH_STATS=y CFG_TA_STATS=y + _make PLATFORM=vexpress-qemu_armv8a + _make PLATFORM=vexpress-qemu_armv8a COMPILER=clang + _make PLATFORM=vexpress-qemu_armv8a CFG_TEE_CORE_LOG_LEVEL=0 CFG_TEE_CORE_DEBUG=n CFG_TEE_TA_LOG_LEVEL=0 CFG_DEBUG_INFO=n + _make PLATFORM=vexpress-qemu_armv8a CFG_TEE_CORE_LOG_LEVEL=4 CFG_TEE_CORE_DEBUG=y CFG_TEE_TA_LOG_LEVEL=4 CFG_CC_OPT_LEVEL=0 CFG_DEBUG_INFO=y + _make PLATFORM=vexpress-qemu_armv8a CFG_WITH_PAGER=y + _make PLATFORM=vexpress-qemu_armv8a CFG_FTRACE_SUPPORT=y CFG_ULIBS_MCOUNT=y CFG_ULIBS_SHARED=y + _make PLATFORM=vexpress-qemu_armv8a CFG_TA_GPROF_SUPPORT=y CFG_FTRACE_SUPPORT=y CFG_SYSCALL_FTRACE=y CFG_ULIBS_MCOUNT=y + _make PLATFORM=vexpress-qemu_armv8a CFG_NS_VIRTUALIZATION=y + _make PLATFORM=vexpress-qemu_armv8a CFG_CORE_PREALLOC_EL0_TBLS=y + _make PLATFORM=vexpress-qemu_armv8a CFG_CORE_SEL1_SPMC=y + _make PLATFORM=vexpress-qemu_armv8a CFG_CORE_SEL2_SPMC=y CFG_CORE_PHYS_RELOCATABLE=y CFG_TZDRAM_START=0x0d304000 CFG_TZDRAM_SIZE=0x00cfc000 + _make PLATFORM=vexpress-qemu_armv8a CFG_{ATTESTATION,DEVICE_ENUM,RTC,SCMI,SECSTOR_TA_MGT}_PTA=y CFG_WITH_STATS=y CFG_TA_STATS=y + dd if=/dev/urandom of=BL32_AP_MM.fd bs=2621440 count=1 && _make PLATFORM=vexpress-qemu_armv8a CFG_STMM_PATH=BL32_AP_MM.fd CFG_RPMB_FS=y CFG_CORE_HEAP_SIZE=524288 CFG_TEE_RAM_VA_SIZE=0x00400000 + if [ -d $HOME/scp-firmware ]; then _make PLATFORM=vexpress-qemu_armv8a CFG_SCMI_SCPFW=y CFG_SCP_FIRMWARE=$HOME/scp-firmware; fi + _make PLATFORM=stm-b2260 + _make PLATFORM=stm-cannes + _make PLATFORM=stm32mp1 + _make PLATFORM=stm32mp1-135F_DK + if [ -d $HOME/scp-firmware ]; then _make PLATFORM=stm32mp1-157C_DK2 CFG_SCMI_SCPFW=y CFG_SCP_FIRMWARE=$HOME/scp-firmware; fi + _make PLATFORM=vexpress-fvp + _make PLATFORM=vexpress-fvp CFG_ARM64_core=y + _make PLATFORM=vexpress-fvp CFG_ARM64_core=y CFG_CORE_SEL1_SPMC=y CFG_SECURE_PARTITION=y + if [ -d $HOME/scp-firmware ]; then _make PLATFORM=vexpress-fvp CFG_SCMI_SCPFW=y CFG_SCP_FIRMWARE=$HOME/scp-firmware; fi + _make PLATFORM=vexpress-juno + _make PLATFORM=vexpress-juno CFG_ARM64_core=y + _make PLATFORM=hikey + _make PLATFORM=hikey CFG_ARM64_core=y + _make PLATFORM=mediatek-mt8173 + _make PLATFORM=mediatek-mt8175 + _make PLATFORM=mediatek-mt8183 + _make PLATFORM=mediatek-mt8516 + _make PLATFORM=imx-mx6ulevk + _make PLATFORM=imx-mx6ulevk CFG_NXP_CAAM=y CFG_CRYPTO_DRIVER=y + _make PLATFORM=imx-mx6ul9x9evk + _make PLATFORM=imx-mx6ullevk CFG_WITH_SOFTWARE_PRNG=n CFG_IMX_RNGB=y + if [ -d $HOME/se050/plug-and-trust ]; then _make PLATFORM=imx-mx6ullevk CFG_NXP_SE05X=y CFG_IMX_I2C=y CFG_STACK_{THREAD,TMP}_EXTRA=8192 CFG_CRYPTO_DRV_{CIPHER,ACIPHER}=y CFG_WITH_SOFTWARE_PRNG=n CFG_NXP_SE05X_{DIEID,RNG,RSA,ECC,CTR}_DRV=y CFG_NXP_SE05X_RSA_DRV_FALLBACK=y CFG_NXP_SE05X_ECC_DRV_FALLBACK=y CFG_NXP_SE05X_PLUG_AND_TRUST=$HOME/se050/plug-and-trust ; fi + _make PLATFORM=imx-mx6ulzevk + _make PLATFORM=imx-mx6slevk + _make PLATFORM=imx-mx6sllevk + _make PLATFORM=imx-mx6sxsabreauto + _make PLATFORM=imx-mx6sxsabresd + _make PLATFORM=imx-mx6sxsabresd CFG_NXP_CAAM=y CFG_CRYPTO_DRIVER=y + _make PLATFORM=imx-mx6solosabresd + _make PLATFORM=imx-mx6solosabreauto + _make PLATFORM=imx-mx6sxsabreauto + _make PLATFORM=imx-mx6qsabrelite + _make PLATFORM=imx-mx6qsabresd + _make PLATFORM=imx-mx6qsabresd CFG_RPMB_FS=y + _make PLATFORM=imx-mx6qsabreauto + _make PLATFORM=imx-mx6qsabreauto CFG_NXP_CAAM=y CFG_CRYPTO_DRIVER=y + _make PLATFORM=imx-mx6qpsabreauto + _make PLATFORM=imx-mx6qpsabresd + _make PLATFORM=imx-mx6dlsabresd + _make PLATFORM=imx-mx6dlsabreauto + _make PLATFORM=imx-mx6dapalis + _make PLATFORM=imx-mx6qapalis + _make PLATFORM=imx-mx7dsabresd + _make PLATFORM=imx-mx7dsabresd CFG_NXP_CAAM=y CFG_CRYPTO_DRIVER=y + _make PLATFORM=imx-mx7ulpevk + _make PLATFORM=imx-mx8mmevk + _make PLATFORM=imx-mx8mmevk CFG_NXP_CAAM=y CFG_CRYPTO_DRIVER=y + if [ -d $HOME/se050/plug-and-trust ]; then _make PLATFORM=imx-mx8mmevk CFG_NXP_CAAM=y CFG_NXP_CAAM_RNG_DRV=y CFG_NXP_SE05X=y CFG_IMX_I2C=y CFG_STACK_{THREAD,TMP}_EXTRA=8192 CFG_CRYPTO_DRV_{CIPHER,ACIPHER}=y CFG_NXP_SE05X_RNG_DRV=n CFG_WITH_SOFTWARE_PRNG=n CFG_NXP_SE05X_{DIEID,RSA,ECC,CTR}_DRV=y CFG_NXP_SE05X_RSA_DRV_FALLBACK=y CFG_NXP_SE05X_ECC_DRV_FALLBACK=y CFG_NXP_SE05X_PLUG_AND_TRUST=$HOME/se050/plug-and-trust ; fi + _make PLATFORM=imx-mx8mnevk + _make PLATFORM=imx-mx8mqevk + _make PLATFORM=imx-mx8mpevk + _make PLATFORM=imx-mx8qxpmek + _make PLATFORM=imx-mx8qmmek + _make PLATFORM=imx-mx8dxlevk + _make PLATFORM=imx-mx8ulpevk + _make PLATFORM=imx-mx8ulpevk CFG_NXP_CAAM=y CFG_CRYPTO_DRIVER=y + _make PLATFORM=imx-mx93evk + _make PLATFORM=k3-j721e + _make PLATFORM=k3-j721e CFG_ARM64_core=y + _make PLATFORM=k3-j784s4 + _make PLATFORM=k3-j784s4 CFG_ARM64_core=y + _make PLATFORM=k3-am65x + _make PLATFORM=k3-am65x CFG_ARM64_core=y + _make PLATFORM=k3-am64x + _make PLATFORM=k3-am64x CFG_ARM64_core=y + _make PLATFORM=k3-am62x + _make PLATFORM=k3-am62x CFG_ARM64_core=y + _make PLATFORM=ti-dra7xx out/core/tee{,-pager,-pageable}.bin + _make PLATFORM=ti-am57xx + _make PLATFORM=ti-am43xx + _make PLATFORM=sprd-sc9860 + _make PLATFORM=sprd-sc9860 CFG_ARM64_core=y + _make PLATFORM=ls-ls1043ardb + _make PLATFORM=ls-ls1046ardb + _make PLATFORM=ls-ls1012ardb + _make PLATFORM=ls-ls1028ardb + _make PLATFORM=ls-ls1088ardb + _make PLATFORM=ls-ls2088ardb + _make PLATFORM=ls-lx2160ardb + _make PLATFORM=ls-lx2160aqds + _make PLATFORM=zynq7k-zc702 + _make PLATFORM=zynqmp-zcu102 + _make PLATFORM=zynqmp-zcu102 CFG_ARM64_core=y + _make PLATFORM=zynqmp-zcu102 CFG_ARM64_core=y CFG_WITH_SOFTWARE_PRNG=n CFG_XIPHERA_TRNG=y CFG_ZYNQMP_HUK=y + _make PLATFORM=d02 + _make PLATFORM=d02 CFG_ARM64_core=y + _make PLATFORM=rcar + _make PLATFORM=rzg + _make PLATFORM=rzg CFG_ARM64_core=y + _make PLATFORM=rpi3 + _make PLATFORM=rpi3 CFG_ARM64_core=y + _make PLATFORM=hikey-hikey960 + _make PLATFORM=hikey-hikey960 COMPILER=clang + _make PLATFORM=hikey-hikey960 CFG_ARM64_core=y + _make PLATFORM=hikey-hikey960 CFG_ARM64_core=y COMPILER=clang + _make PLATFORM=hikey-hikey960 CFG_SECURE_DATA_PATH=n + _make PLATFORM=poplar + _make PLATFORM=poplar CFG_ARM64_core=y + _make PLATFORM=rockchip-rk322x + _make PLATFORM=rockchip-rk3399 + _make PLATFORM=sam + _make PLATFORM=sam-sama5d27_wlsom1_ek + _make PLATFORM=marvell-armada7k8k + _make PLATFORM=marvell-armada3700 + _make PLATFORM=marvell-otx2t96 + _make PLATFORM=marvell-otx2f95 + _make PLATFORM=marvell-otx2t98 + _make PLATFORM=synquacer + _make PLATFORM=sunxi-bpi_zero + _make PLATFORM=sunxi-sun50i_a64 + _make PLATFORM=bcm-ns3 CFG_ARM64_core=y + _make PLATFORM=hisilicon-hi3519av100_demo + _make PLATFORM=amlogic + _make PLATFORM=rzn1 + _make PLATFORM=versal CFG_VERSAL_FPGA_DDR_ADDR=0x40000000 + _make PLATFORM=corstone1000 + + QEMUv8_check: + name: make check (QEMUv8) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemuv8_check2 + steps: + - name: Restore build cache + uses: actions/cache@v3 + with: + path: /github/home/.cache/ccache + key: qemuv8_check-cache-${{ github.sha }} + restore-keys: | + qemuv8_check-cache- + - name: Checkout + uses: actions/checkout@v3 + - shell: bash + run: | + # make check task + set -e -v + export LC_ALL=C + export BR2_CCACHE_DIR=/github/home/.cache/ccache + export CFG_TEE_CORE_LOG_LEVEL=0 + WD=$(pwd) + cd .. + TOP=$(pwd)/optee_repo_qemu_v8 + /root/get_optee_qemuv8.sh ${TOP} + mv ${TOP}/optee_os ${TOP}/optee_os_old + ln -s ${WD} ${TOP}/optee_os + cd ${TOP}/build + + make -j$(nproc) check + make -j$(nproc) check CFG_CRYPTO_WITH_CE82=y + make -j$(nproc) check CFG_FTRACE_SUPPORT=y CFG_SYSCALL_FTRACE=y XTEST_ARGS=regression_1001 + + QEMUv8_Xen_check: + name: make check (QEMUv8, Xen) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemuv8_check2 + steps: + - name: Restore build cache + uses: actions/cache@v3 + with: + path: /github/home/.cache/ccache + key: qemuv8_xen_check-cache-${{ github.sha }} + restore-keys: | + qemuv8_xen_check-cache- + - name: Checkout + uses: actions/checkout@v3 + - shell: bash + run: | + # make check task + set -e -v + export LC_ALL=C + export CFG_TEE_CORE_LOG_LEVEL=0 + export BR2_CCACHE_DIR=/github/home/.cache/ccache + WD=$(pwd) + cd .. + TOP=$(pwd)/optee_repo_qemu_v8 + /root/get_optee_qemuv8.sh ${TOP} + mv ${TOP}/optee_os ${TOP}/optee_os_old + ln -s ${WD} ${TOP}/optee_os + cd ${TOP}/build + + make -j$(nproc) check XEN_BOOT=y + + QEMUv8_check_BTI_MTE_PAC: + name: make check (QEMUv8, BTI+MTE+PAC) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemuv8_check2 + steps: + - name: Restore build cache + uses: actions/cache@v3 + with: + path: /github/home/.cache/ccache + key: qemuv8_check_bti_mte_pac-cache-${{ github.sha }} + restore-keys: | + qemuv8_check_bti_mte_pac-cache- + - name: Checkout + uses: actions/checkout@v3 + - shell: bash + run: | + # make check task + set -e -v + export LC_ALL=C + # The BTI-enabled toolchain is aarch64-unknown-linux-uclibc-gcc in /usr/local/bin + export PATH=/usr/local/bin:$PATH + export AARCH64_CROSS_COMPILE=aarch64-unknown-linux-uclibc- + export BR2_CCACHE_DIR=/github/home/.cache/ccache + export CFG_TEE_CORE_LOG_LEVEL=0 + export CFG_USER_TA_TARGETS=ta_arm64 + WD=$(pwd) + cd .. + TOP=$(pwd)/optee_repo_qemu_v8 + # TF-A v2.6 fails to build with the above toolchain so override it + export TF_A_EXPORTS="CROSS_COMPILE=${TOP}/toolchains/aarch64/bin/aarch64-linux-gnu-" + /root/get_optee_qemuv8.sh ${TOP} + # QEMU v7.2.0 has an issue with MTE + # https://github.com/OP-TEE/optee_os/issues/5759#issuecomment-1380590951 + cd ${TOP}/qemu && git fetch github && git checkout 13356edb87 + mv ${TOP}/optee_os ${TOP}/optee_os_old + ln -s ${WD} ${TOP}/optee_os + cd ${TOP}/build + + # xtest 1031 is excluded because 1031.4 (C++ exception from shared library) fails with this cross-compiler + make -j$(nproc) CFG_CORE_BTI=y CFG_TA_BTI=y MEMTAG=y PAUTH=y XTEST_ARGS="-x 1031" check + + QEMUv8_check_rust: + name: make check-rust (QEMUv8) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemuv8_check2 + steps: + - name: Restore build cache + uses: actions/cache@v3 + with: + path: /github/home/.cache/ccache + key: qemuv8_check_rust-cache-${{ github.sha }} + restore-keys: | + qemuv8_check_rust-cache- + - name: Checkout + uses: actions/checkout@v3 + - shell: bash + run: | + # make check-rust task + set -e -v + export LC_ALL=C + export BR2_CCACHE_DIR=/github/home/.cache/ccache + WD=$(pwd) + cd .. + TOP=$(pwd)/optee_repo_qemu_v8 + /root/get_optee_qemuv8.sh ${TOP} + mv ${TOP}/optee_os ${TOP}/optee_os_old + ln -s ${WD} ${TOP}/optee_os + cd ${TOP}/build + + # Without this line, the following one fails with "ld: cannot find -lteec" when building acipher-rs + make -j$(nproc) + make -j$(nproc) OPTEE_RUST_ENABLE=y check-rust diff --git a/optee/optee_os/.github/workflows/stales.yml b/optee/optee_os/.github/workflows/stales.yml new file mode 100644 index 0000000..e0d47f3 --- /dev/null +++ b/optee/optee_os/.github/workflows/stales.yml @@ -0,0 +1,27 @@ +name: 'Close stale issues and pull requests with no recent activity' +on: + schedule: + - cron: "15 00 * * *" + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4.1.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue has been marked as a stale issue because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this issue will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.' + stale-pr-message: 'This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.' + stale-issue-label: Stale + stale-pr-label: Stale + exempt-issue-labels: bug,enhancement + exempt-pr-labels: bug,enhancement + days-before-stale: 30 + days-before-close: 5 + remove-stale-when-updated: true + remove-issue-stale-when-updated: true + remove-pr-stale-when-updated: true diff --git a/optee/optee_os/CHANGELOG.md b/optee/optee_os/CHANGELOG.md new file mode 100644 index 0000000..1ff17d3 --- /dev/null +++ b/optee/optee_os/CHANGELOG.md @@ -0,0 +1,1675 @@ +# OP-TEE - version 3.21.0 (2023-04-14) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_21], [commits][OP_TEE_optee_os_commits_3_21] and [pull requests][OP_TEE_optee_os_pr_3_21] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_21], [commits][OP_TEE_optee_client_commits_3_21] and [pull requests][OP_TEE_optee_client_pr_3_21] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_21], [commits][OP_TEE_optee_test_commits_3_21] and [pull requests][OP_TEE_optee_test_pr_3_21] + - OP-TEE/build: [release page][OP_TEE_build_release_3_21], [commits][OP_TEE_build_commits_3_21] and [pull requests][OP_TEE_build_pr_3_21] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_21], [commits][linaro_swg_optee_examples_commits_3_21] and [pull requests][linaro_swg_optee_examples_pr_3_21] + + +[OP_TEE_optee_os_release_3_21]: https://github.com/OP-TEE/optee_os/releases/tag/3.21.0 +[OP_TEE_optee_os_commits_3_21]: https://github.com/OP-TEE/optee_os/compare/3.20.0...3.21.0 +[OP_TEE_optee_os_pr_3_21]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 + +[OP_TEE_optee_client_release_3_21]: https://github.com/OP-TEE/optee_client/releases/tag/3.21.0 +[OP_TEE_optee_client_commits_3_21]: https://github.com/OP-TEE/optee_client/compare/3.20.0...3.21.0 +[OP_TEE_optee_client_pr_3_21]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 + +[OP_TEE_optee_test_release_3_21]: https://github.com/OP-TEE/optee_test/releases/tag/3.21.0 +[OP_TEE_optee_test_commits_3_21]: https://github.com/OP-TEE/optee_test/compare/3.20.0...3.21.0 +[OP_TEE_optee_test_pr_3_21]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 + +[OP_TEE_build_release_3_21]: https://github.com/OP-TEE/build/releases/tag/3.21.0 +[OP_TEE_build_commits_3_21]: https://github.com/OP-TEE/build/compare/3.20.0...3.21.0 +[OP_TEE_build_pr_3_21]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 + +[linaro_swg_optee_examples_release_3_21]: https://github.com/linaro-swg/optee_examples/releases/tag/3.21.0 +[linaro_swg_optee_examples_commits_3_21]: https://github.com/linaro-swg/optee_examples/compare/3.20.0...3.21.0 +[linaro_swg_optee_examples_pr_3_21]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 + +# OP-TEE - version 3.20.0 (2023-01-20) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_20], [commits][OP_TEE_optee_os_commits_3_20] and [pull requests][OP_TEE_optee_os_pr_3_20] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_20], [commits][OP_TEE_optee_client_commits_3_20] and [pull requests][OP_TEE_optee_client_pr_3_20] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_20], [commits][OP_TEE_optee_test_commits_3_20] and [pull requests][OP_TEE_optee_test_pr_3_20] + - OP-TEE/build: [release page][OP_TEE_build_release_3_20], [commits][OP_TEE_build_commits_3_20] and [pull requests][OP_TEE_build_pr_3_20] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_20], [commits][linaro_swg_optee_examples_commits_3_20] and [pull requests][linaro_swg_optee_examples_pr_3_20] + + +[OP_TEE_optee_os_release_3_20]: https://github.com/OP-TEE/optee_os/releases/tag/3.20.0 +[OP_TEE_optee_os_commits_3_20]: https://github.com/OP-TEE/optee_os/compare/3.19.0...3.20.0 +[OP_TEE_optee_os_pr_3_20]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 + +[OP_TEE_optee_client_release_3_20]: https://github.com/OP-TEE/optee_client/releases/tag/3.20.0 +[OP_TEE_optee_client_commits_3_20]: https://github.com/OP-TEE/optee_client/compare/3.19.0...3.20.0 +[OP_TEE_optee_client_pr_3_20]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 + +[OP_TEE_optee_test_release_3_20]: https://github.com/OP-TEE/optee_test/releases/tag/3.20.0 +[OP_TEE_optee_test_commits_3_20]: https://github.com/OP-TEE/optee_test/compare/3.19.0...3.20.0 +[OP_TEE_optee_test_pr_3_20]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 + +[OP_TEE_build_release_3_20]: https://github.com/OP-TEE/build/releases/tag/3.20.0 +[OP_TEE_build_commits_3_20]: https://github.com/OP-TEE/build/compare/3.19.0...3.20.0 +[OP_TEE_build_pr_3_20]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 + +[linaro_swg_optee_examples_release_3_20]: https://github.com/linaro-swg/optee_examples/releases/tag/3.20.0 +[linaro_swg_optee_examples_commits_3_20]: https://github.com/linaro-swg/optee_examples/compare/3.19.0...3.20.0 +[linaro_swg_optee_examples_pr_3_20]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 + +# OP-TEE - version 3.19.0 (2022-10-14) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_19], [commits][OP_TEE_optee_os_commits_3_19] and [ +pull requests][OP_TEE_optee_os_pr_3_19] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_19], [commits][OP_TEE_optee_client_commits_3_19] and [pull requests][OP_TEE_optee_client_pr_3_19] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_19], [commits][OP_TEE_optee_test_commits_3_19] and [pull requests][OP_TEE_optee_test_pr_3_19] + - OP-TEE/build: [release page][OP_TEE_build_release_3_19], [commits][OP_TEE_build_commits_3_19] and [pull requests][OP_TEE_build_pr_3_19] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_19], [commits][linaro_swg_optee_examples_commits_3_19] and [pull requests][linaro_swg_optee_examples_pr_3_19] + + +[OP_TEE_optee_os_release_3_19]: https://github.com/OP-TEE/optee_os/releases/tag/3.19.0 +[OP_TEE_optee_os_commits_3_19]: https://github.com/OP-TEE/optee_os/compare/3.18.0...3.19.0 +[OP_TEE_optee_os_pr_3_19]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 + +[OP_TEE_optee_client_release_3_19]: https://github.com/OP-TEE/optee_client/releases/tag/3.19.0 +[OP_TEE_optee_client_commits_3_19]: https://github.com/OP-TEE/optee_client/compare/3.18.0...3.19.0 +[OP_TEE_optee_client_pr_3_19]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 + +[OP_TEE_optee_test_release_3_19]: https://github.com/OP-TEE/optee_test/releases/tag/3.19.0 +[OP_TEE_optee_test_commits_3_19]: https://github.com/OP-TEE/optee_test/compare/3.18.0...3.19.0 +[OP_TEE_optee_test_pr_3_19]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 + +[OP_TEE_build_release_3_19]: https://github.com/OP-TEE/build/releases/tag/3.19.0 +[OP_TEE_build_commits_3_19]: https://github.com/OP-TEE/build/compare/3.18.0...3.19.0 +[OP_TEE_build_pr_3_19]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 + +[linaro_swg_optee_examples_release_3_19]: https://github.com/linaro-swg/optee_examples/releases/tag/3.19.0 +[linaro_swg_optee_examples_commits_3_19]: https://github.com/linaro-swg/optee_examples/compare/3.18.0...3.19.0 +[linaro_swg_optee_examples_pr_3_19]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 + +# OP-TEE - version 3.18.0 (2022-07-15) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_18_0], [commits][OP_TEE_optee_os_commits_3_18_0] and [pull requests][OP_TEE_optee_os_pr_3_18_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_18_0], [commits][OP_TEE_optee_client_commits_3_18_0] and [pull requests][OP_TEE_optee_client_pr_3_18_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_18_0], [commits][OP_TEE_optee_test_commits_3_18_0] and [pull requests][OP_TEE_optee_test_pr_3_18_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_18_0], [commits][OP_TEE_build_commits_3_18_0] and [pull requests][OP_TEE_build_pr_3_18_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_18_0], [commits][linaro_swg_optee_examples_commits_3_18_0] and [pull requests][linaro_swg_optee_examples_pr_3_18_0] + + +[OP_TEE_optee_os_release_3_18_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.18.0 +[OP_TEE_optee_os_commits_3_18_0]: https://github.com/OP-TEE/optee_os/compare/3.17.0...3.18.0 +[OP_TEE_optee_os_pr_3_18_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 + +[OP_TEE_optee_client_release_3_18_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.18.0 +[OP_TEE_optee_client_commits_3_18_0]: https://github.com/OP-TEE/optee_client/compare/3.17.0...3.18.0 +[OP_TEE_optee_client_pr_3_18_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 + +[OP_TEE_optee_test_release_3_18_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.18.0 +[OP_TEE_optee_test_commits_3_18_0]: https://github.com/OP-TEE/optee_test/compare/3.17.0...3.18.0 +[OP_TEE_optee_test_pr_3_18_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 + +[OP_TEE_build_release_3_18_0]: https://github.com/OP-TEE/build/releases/tag/3.18.0 +[OP_TEE_build_commits_3_18_0]: https://github.com/OP-TEE/build/compare/3.17.0...3.18.0 +[OP_TEE_build_pr_3_18_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 + +[linaro_swg_optee_examples_release_3_18_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.18.0 +[linaro_swg_optee_examples_commits_3_18_0]: https://github.com/linaro-swg/optee_examples/compare/3.17.0...3.18.0 +[linaro_swg_optee_examples_pr_3_18_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 + +# OP-TEE - version 3.17.0 (2022-04-15) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_17_0], [commits][OP_TEE_optee_os_commits_3_17_0] and [pull requests][OP_TEE_optee_os_pr_3_17_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_17_0], [commits][OP_TEE_optee_client_commits_3_17_0] and [pull requests][OP_TEE_optee_client_pr_3_17_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_17_0], [commits][OP_TEE_optee_test_commits_3_17_0] and [pull requests][OP_TEE_optee_test_pr_3_17_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_17_0], [commits][OP_TEE_build_commits_3_17_0] and [pull requests][OP_TEE_build_pr_3_17_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_17_0], [commits][linaro_swg_optee_examples_commits_3_17_0] and [pull requests][linaro_swg_optee_examples_pr_3_17_0] + + +[OP_TEE_optee_os_release_3_17_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.17.0 +[OP_TEE_optee_os_commits_3_17_0]: https://github.com/OP-TEE/optee_os/compare/3.16.0...3.17.0 +[OP_TEE_optee_os_pr_3_17_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-28..2022-04-15 + +[OP_TEE_optee_client_release_3_17_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.17.0 +[OP_TEE_optee_client_commits_3_17_0]: https://github.com/OP-TEE/optee_client/compare/3.16.0...3.17.0 +[OP_TEE_optee_client_pr_3_17_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-01-28..2022-04-15 + +[OP_TEE_optee_test_release_3_17_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.17.0 +[OP_TEE_optee_test_commits_3_17_0]: https://github.com/OP-TEE/optee_test/compare/3.16.0...3.17.0 +[OP_TEE_optee_test_pr_3_17_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-01-28..2022-04-15 + +[OP_TEE_build_release_3_17_0]: https://github.com/OP-TEE/build/releases/tag/3.17.0 +[OP_TEE_build_commits_3_17_0]: https://github.com/OP-TEE/build/compare/3.16.0...3.17.0 +[OP_TEE_build_pr_3_17_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-28..2022-04-15 + +[linaro_swg_optee_examples_release_3_17_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.17.0 +[linaro_swg_optee_examples_commits_3_17_0]: https://github.com/linaro-swg/optee_examples/compare/3.16.0...3.17.0 +[linaro_swg_optee_examples_pr_3_17_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-01-28..2022-04-15 + +# OP-TEE - version 3.16.0 (2022-01-28) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_16_0], [commits][OP_TEE_optee_os_commits_3_16_0] and [pull requests][OP_TEE_optee_os_pr_3_16_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_16_0], [commits][OP_TEE_optee_client_commits_3_16_0] and [pull requests][OP_TEE_optee_client_pr_3_16_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_16_0], [commits][OP_TEE_optee_test_commits_3_16_0] and [pull requests][OP_TEE_optee_test_pr_3_16_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_16_0], [commits][OP_TEE_build_commits_3_16_0] and [pull requests][OP_TEE_build_pr_3_16_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_16_0], [commits][linaro_swg_optee_examples_commits_3_16_0] and [pull requests][linaro_swg_optee_examples_pr_3_16_0] + + +[OP_TEE_optee_os_release_3_16_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.16.0 +[OP_TEE_optee_os_commits_3_16_0]: https://github.com/OP-TEE/optee_os/compare/3.15.0...3.16.0 +[OP_TEE_optee_os_pr_3_16_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 + +[OP_TEE_optee_client_release_3_16_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.16.0 +[OP_TEE_optee_client_commits_3_16_0]: https://github.com/OP-TEE/optee_client/compare/3.15.0...3.16.0 +[OP_TEE_optee_client_pr_3_16_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 + +[OP_TEE_optee_test_release_3_16_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.16.0 +[OP_TEE_optee_test_commits_3_16_0]: https://github.com/OP-TEE/optee_test/compare/3.15.0...3.16.0 +[OP_TEE_optee_test_pr_3_16_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 + +[OP_TEE_build_release_3_16_0]: https://github.com/OP-TEE/build/releases/tag/3.16.0 +[OP_TEE_build_commits_3_16_0]: https://github.com/OP-TEE/build/compare/3.15.0...3.16.0 +[OP_TEE_build_pr_3_16_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 + +[linaro_swg_optee_examples_release_3_16_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.16.0 +[linaro_swg_optee_examples_commits_3_16_0]: https://github.com/linaro-swg/optee_examples/compare/3.15.0...3.16.0 +[linaro_swg_optee_examples_pr_3_16_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 + +# OP-TEE - version 3.15.0 (2021-10-18) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_15_0], [commits][OP_TEE_optee_os_commits_3_15_0] and [pull requests][OP_TEE_optee_os_pr_3_15_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_15_0], [commits][OP_TEE_optee_client_commits_3_15_0] and [pull requests][OP_TEE_optee_client_pr_3_15_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_15_0], [commits][OP_TEE_optee_test_commits_3_15_0] and [pull requests][OP_TEE_optee_test_pr_3_15_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_15_0], [commits][OP_TEE_build_commits_3_15_0] and [pull requests][OP_TEE_build_pr_3_15_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_15_0], [commits][linaro_swg_optee_examples_commits_3_15_0] and [pull requests][linaro_swg_optee_examples_pr_3_15_0] + + +[OP_TEE_optee_os_release_3_15_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.15.0 +[OP_TEE_optee_os_commits_3_15_0]: https://github.com/OP-TEE/optee_os/compare/3.14.0...3.15.0 +[OP_TEE_optee_os_pr_3_15_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 + +[OP_TEE_optee_client_release_3_15_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.15.0 +[OP_TEE_optee_client_commits_3_15_0]: https://github.com/OP-TEE/optee_client/compare/3.14.0...3.15.0 +[OP_TEE_optee_client_pr_3_15_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 + +[OP_TEE_optee_test_release_3_15_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.15.0 +[OP_TEE_optee_test_commits_3_15_0]: https://github.com/OP-TEE/optee_test/compare/3.14.0...3.15.0 +[OP_TEE_optee_test_pr_3_15_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 + +[OP_TEE_build_release_3_15_0]: https://github.com/OP-TEE/build/releases/tag/3.15.0 +[OP_TEE_build_commits_3_15_0]: https://github.com/OP-TEE/build/compare/3.14.0...3.15.0 +[OP_TEE_build_pr_3_15_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 + +[linaro_swg_optee_examples_release_3_15_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.15.0 +[linaro_swg_optee_examples_commits_3_15_0]: https://github.com/linaro-swg/optee_examples/compare/3.14.0...3.15.0 +[linaro_swg_optee_examples_pr_3_15_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 + +# OP-TEE - version 3.14.0 (target date: 2021-07-16) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_14_0], [commits][OP_TEE_optee_os_commits_3_14_0] and [pull requests][OP_TEE_optee_os_pr_3_14_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_14_0], [commits][OP_TEE_optee_client_commits_3_14_0] and [pull requests][OP_TEE_optee_client_pr_3_14_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_14_0], [commits][OP_TEE_optee_test_commits_3_14_0] and [pull requests][OP_TEE_optee_test_pr_3_14_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_14_0], [commits][OP_TEE_build_commits_3_14_0] and [pull requests][OP_TEE_build_pr_3_14_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_14_0], [commits][linaro_swg_optee_examples_commits_3_14_0] and [pull requests][linaro_swg_optee_examples_pr_3_14_0] + + +[OP_TEE_optee_os_release_3_14_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.14.0 +[OP_TEE_optee_os_commits_3_14_0]: https://github.com/OP-TEE/optee_os/compare/3.13.0...3.14.0 +[OP_TEE_optee_os_pr_3_14_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01..2021-07-16 + +[OP_TEE_optee_client_release_3_14_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.14.0 +[OP_TEE_optee_client_commits_3_14_0]: https://github.com/OP-TEE/optee_client/compare/3.13.0...3.14.0 +[OP_TEE_optee_client_pr_3_14_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01-..2021-07-16 + +[OP_TEE_optee_test_release_3_14_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.14.0 +[OP_TEE_optee_test_commits_3_14_0]: https://github.com/OP-TEE/optee_test/compare/3.13.0...3.14.0 +[OP_TEE_optee_test_pr_3_14_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01..2021-07-16 + +[OP_TEE_build_release_3_14_0]: https://github.com/OP-TEE/build/releases/tag/3.14.0 +[OP_TEE_build_commits_3_14_0]: https://github.com/OP-TEE/build/compare/3.13.0...3.14.0 +[OP_TEE_build_pr_3_14_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01..2021-07-16 + +[linaro_swg_optee_examples_release_3_14_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.14.0 +[linaro_swg_optee_examples_commits_3_14_0]: https://github.com/linaro-swg/optee_examples/compare/3.13.0...3.14.0 +[linaro_swg_optee_examples_pr_3_14_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01..2021-07-16 + +# OP-TEE - version 3.13.0 (2021-04-30) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_13_0], [commits][OP_TEE_optee_os_commits_3_13_0] and [pull requests][OP_TEE_optee_os_pr_3_13_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_13_0], [commits][OP_TEE_optee_client_commits_3_13_0] and [pull requests][OP_TEE_optee_client_pr_3_13_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_13_0], [commits][OP_TEE_optee_test_commits_3_13_0] and [pull requests][OP_TEE_optee_test_pr_3_13_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_13_0], [commits][OP_TEE_build_commits_3_13_0] and [pull requests][OP_TEE_build_pr_3_13_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_13_0], [commits][linaro_swg_optee_examples_commits_3_13_0] and [pull requests][linaro_swg_optee_examples_pr_3_13_0] + + +[OP_TEE_optee_os_release_3_13_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.13.0 +[OP_TEE_optee_os_commits_3_13_0]: https://github.com/OP-TEE/optee_os/compare/3.12.0...3.13.0 +[OP_TEE_optee_os_pr_3_13_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 + +[OP_TEE_optee_client_release_3_13_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.13.0 +[OP_TEE_optee_client_commits_3_13_0]: https://github.com/OP-TEE/optee_client/compare/3.12.0...3.13.0 +[OP_TEE_optee_client_pr_3_13_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 + +[OP_TEE_optee_test_release_3_13_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.13.0 +[OP_TEE_optee_test_commits_3_13_0]: https://github.com/OP-TEE/optee_test/compare/3.12.0...3.13.0 +[OP_TEE_optee_test_pr_3_13_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 + +[OP_TEE_build_release_3_13_0]: https://github.com/OP-TEE/build/releases/tag/3.13.0 +[OP_TEE_build_commits_3_13_0]: https://github.com/OP-TEE/build/compare/3.12.0...3.13.0 +[OP_TEE_build_pr_3_13_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 + +[linaro_swg_optee_examples_release_3_13_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.13.0 +[linaro_swg_optee_examples_commits_3_13_0]: https://github.com/linaro-swg/optee_examples/compare/3.12.0...3.13.0 +[linaro_swg_optee_examples_pr_3_13_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 + +# OP-TEE - version 3.12.0 (2021-01-20) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_12_0], [commits][OP_TEE_optee_os_commits_3_12_0] and [pull requests][OP_TEE_optee_os_pr_3_12_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_12_0], [commits][OP_TEE_optee_client_commits_3_12_0] and [pull requests][OP_TEE_optee_client_pr_3_12_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_12_0], [commits][OP_TEE_optee_test_commits_3_12_0] and [pull requests][OP_TEE_optee_test_pr_3_12_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_12_0], [commits][OP_TEE_build_commits_3_12_0] and [pull requests][OP_TEE_build_pr_3_12_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_12_0], [commits][linaro_swg_optee_examples_commits_3_12_0] and [pull requests][linaro_swg_optee_examples_pr_3_12_0] + + +[OP_TEE_optee_os_release_3_12_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.12.0 +[OP_TEE_optee_os_commits_3_12_0]: https://github.com/OP-TEE/optee_os/compare/3.11.0...3.12.0 +[OP_TEE_optee_os_pr_3_12_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 + +[OP_TEE_optee_client_release_3_12_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.12.0 +[OP_TEE_optee_client_commits_3_12_0]: https://github.com/OP-TEE/optee_client/compare/3.11.0...3.12.0 +[OP_TEE_optee_client_pr_3_12_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 + +[OP_TEE_optee_test_release_3_12_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.12.0 +[OP_TEE_optee_test_commits_3_12_0]: https://github.com/OP-TEE/optee_test/compare/3.11.0...3.12.0 +[OP_TEE_optee_test_pr_3_12_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 + +[OP_TEE_build_release_3_12_0]: https://github.com/OP-TEE/build/releases/tag/3.12.0 +[OP_TEE_build_commits_3_12_0]: https://github.com/OP-TEE/build/compare/3.11.0...3.12.0 +[OP_TEE_build_pr_3_12_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 + +[linaro_swg_optee_examples_release_3_12_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.12.0 +[linaro_swg_optee_examples_commits_3_12_0]: https://github.com/linaro-swg/optee_examples/compare/3.11.0...3.12.0 +[linaro_swg_optee_examples_pr_3_12_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 + +# OP-TEE - version 3.11.0 (2020-10-16) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_11_0], [commits][OP_TEE_optee_os_commits_3_11_0] and [pull requests][OP_TEE_optee_os_pr_3_11_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_11_0], [commits][OP_TEE_optee_client_commits_3_11_0] and [pull requests][OP_TEE_optee_client_pr_3_11_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_11_0], [commits][OP_TEE_optee_test_commits_3_11_0] and [pull requests][OP_TEE_optee_test_pr_3_11_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_11_0], [commits][OP_TEE_build_commits_3_11_0] and [pull requests][OP_TEE_build_pr_3_11_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_11_0], [commits][linaro_swg_optee_examples_commits_3_11_0] and [pull requests][linaro_swg_optee_examples_pr_3_11_0] + + +[OP_TEE_optee_os_release_3_11_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.11.0 +[OP_TEE_optee_os_commits_3_11_0]: https://github.com/OP-TEE/optee_os/compare/3.10.0...3.11.0 +[OP_TEE_optee_os_pr_3_11_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 + +[OP_TEE_optee_client_release_3_11_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.11.0 +[OP_TEE_optee_client_commits_3_11_0]: https://github.com/OP-TEE/optee_client/compare/3.10.0...3.11.0 +[OP_TEE_optee_client_pr_3_11_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 + +[OP_TEE_optee_test_release_3_11_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.11.0 +[OP_TEE_optee_test_commits_3_11_0]: https://github.com/OP-TEE/optee_test/compare/3.10.0...3.11.0 +[OP_TEE_optee_test_pr_3_11_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 + +[OP_TEE_build_release_3_11_0]: https://github.com/OP-TEE/build/releases/tag/3.11.0 +[OP_TEE_build_commits_3_11_0]: https://github.com/OP-TEE/build/compare/3.10.0...3.11.0 +[OP_TEE_build_pr_3_11_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 + +[linaro_swg_optee_examples_release_3_11_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.11.0 +[linaro_swg_optee_examples_commits_3_11_0]: https://github.com/linaro-swg/optee_examples/compare/3.10.0...3.11.0 +[linaro_swg_optee_examples_pr_3_11_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 + +# OP-TEE - version 3.10.0 (2020-08-21) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_10_0], [commits][OP_TEE_optee_os_commits_3_10_0] and [pull requests][OP_TEE_optee_os_pr_3_10_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_10_0], [commits][OP_TEE_optee_client_commits_3_10_0] and [pull requests][OP_TEE_optee_client_pr_3_10_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_10_0], [commits][OP_TEE_optee_test_commits_3_10_0] and [pull requests][OP_TEE_optee_test_pr_3_10_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_10_0], [commits][OP_TEE_build_commits_3_10_0] and [pull requests][OP_TEE_build_pr_3_10_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_10_0], [commits][linaro_swg_optee_examples_commits_3_10_0] and [pull requests][linaro_swg_optee_examples_pr_3_10_0] + + +[OP_TEE_optee_os_release_3_10_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.10.0 +[OP_TEE_optee_os_commits_3_10_0]: https://github.com/OP-TEE/optee_os/compare/3.9.0...3.10.0 +[OP_TEE_optee_os_pr_3_10_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 + +[OP_TEE_optee_client_release_3_10_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.10.0 +[OP_TEE_optee_client_commits_3_10_0]: https://github.com/OP-TEE/optee_client/compare/3.9.0...3.10.0 +[OP_TEE_optee_client_pr_3_10_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 + +[OP_TEE_optee_test_release_3_10_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.10.0 +[OP_TEE_optee_test_commits_3_10_0]: https://github.com/OP-TEE/optee_test/compare/3.9.0...3.10.0 +[OP_TEE_optee_test_pr_3_10_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 + +[OP_TEE_build_release_3_10_0]: https://github.com/OP-TEE/build/releases/tag/3.10.0 +[OP_TEE_build_commits_3_10_0]: https://github.com/OP-TEE/build/compare/3.9.0...3.10.0 +[OP_TEE_build_pr_3_10_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 + +[linaro_swg_optee_examples_release_3_10_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.10.0 +[linaro_swg_optee_examples_commits_3_10_0]: https://github.com/linaro-swg/optee_examples/compare/3.9.0...3.10.0 +[linaro_swg_optee_examples_pr_3_10_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 + +# OP-TEE - version 3.9.0 (2020-04-22) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_9_0], [commits][OP_TEE_optee_os_commits_3_9_0] and [pull requests][OP_TEE_optee_os_pr_3_9_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_9_0], [commits][OP_TEE_optee_client_commits_3_9_0] and [pull requests][OP_TEE_optee_client_pr_3_9_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_9_0], [commits][OP_TEE_optee_test_commits_3_9_0] and [pull requests][OP_TEE_optee_test_pr_3_9_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_9_0], [commits][OP_TEE_build_commits_3_9_0] and [pull requests][OP_TEE_build_pr_3_9_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_9_0], [commits][linaro_swg_optee_examples_commits_3_9_0] and [pull requests][linaro_swg_optee_examples_pr_3_9_0] + + +[OP_TEE_optee_os_release_3_9_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.9.0 +[OP_TEE_optee_os_commits_3_9_0]: https://github.com/OP-TEE/optee_os/compare/3.8.0...3.9.0 +[OP_TEE_optee_os_pr_3_9_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 + +[OP_TEE_optee_client_release_3_9_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.9.0 +[OP_TEE_optee_client_commits_3_9_0]: https://github.com/OP-TEE/optee_client/compare/3.8.0...3.9.0 +[OP_TEE_optee_client_pr_3_9_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 + +[OP_TEE_optee_test_release_3_9_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.9.0 +[OP_TEE_optee_test_commits_3_9_0]: https://github.com/OP-TEE/optee_test/compare/3.8.0...3.9.0 +[OP_TEE_optee_test_pr_3_9_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 + +[OP_TEE_build_release_3_9_0]: https://github.com/OP-TEE/build/releases/tag/3.9.0 +[OP_TEE_build_commits_3_9_0]: https://github.com/OP-TEE/build/compare/3.8.0...3.9.0 +[OP_TEE_build_pr_3_9_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 + +[linaro_swg_optee_examples_release_3_9_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.9.0 +[linaro_swg_optee_examples_commits_3_9_0]: https://github.com/linaro-swg/optee_examples/compare/3.8.0...3.9.0 +[linaro_swg_optee_examples_pr_3_9_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 + +# OP-TEE - version 3.8.0 (2020-01-24) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_8_0], [commits][OP_TEE_optee_os_commits_3_8_0] and [pull requests][OP_TEE_optee_os_pr_3_8_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_8_0], [commits][OP_TEE_optee_client_commits_3_8_0] and [pull requests][OP_TEE_optee_client_pr_3_8_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_8_0], [commits][OP_TEE_optee_test_commits_3_8_0] and [pull requests][OP_TEE_optee_test_pr_3_8_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_8_0], [commits][OP_TEE_build_commits_3_8_0] and [pull requests][OP_TEE_build_pr_3_8_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_8_0], [commits][linaro_swg_optee_examples_commits_3_8_0] and [pull requests][linaro_swg_optee_examples_pr_3_8_0] + + +[OP_TEE_optee_os_release_3_8_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.8.0 +[OP_TEE_optee_os_commits_3_8_0]: https://github.com/OP-TEE/optee_os/compare/3.7.0...3.8.0 +[OP_TEE_optee_os_pr_3_8_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-01-24 + +[OP_TEE_optee_client_release_3_8_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.8.0 +[OP_TEE_optee_client_commits_3_8_0]: https://github.com/OP-TEE/optee_client/compare/3.7.0...3.8.0 +[OP_TEE_optee_client_pr_3_8_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2020-01-24 + +[OP_TEE_optee_test_release_3_8_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.8.0 +[OP_TEE_optee_test_commits_3_8_0]: https://github.com/OP-TEE/optee_test/compare/3.7.0...3.8.0 +[OP_TEE_optee_test_pr_3_8_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2020-01-24 + +[OP_TEE_build_release_3_8_0]: https://github.com/OP-TEE/build/releases/tag/3.8.0 +[OP_TEE_build_commits_3_8_0]: https://github.com/OP-TEE/build/compare/3.7.0...3.8.0 +[OP_TEE_build_pr_3_8_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2020-01-24 + +[linaro_swg_optee_examples_release_3_8_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.8.0 +[linaro_swg_optee_examples_commits_3_8_0]: https://github.com/linaro-swg/optee_examples/compare/3.7.0...3.8.0 +[linaro_swg_optee_examples_pr_3_8_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2020-01-24 + +# OP-TEE - version 3.7.0 (2019-10-18) + +- Links to the release pages, commits and pull requests merged into this release for: + - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_7_0], [commits][OP_TEE_optee_os_commits_3_7_0] and [pull requests][OP_TEE_optee_os_pr_3_7_0] + - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_7_0], [commits][OP_TEE_optee_client_commits_3_7_0] and [pull requests][OP_TEE_optee_client_pr_3_7_0] + - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_7_0], [commits][OP_TEE_optee_test_commits_3_7_0] and [pull requests][OP_TEE_optee_test_pr_3_7_0] + - OP-TEE/build: [release page][OP_TEE_build_release_3_7_0], [commits][OP_TEE_build_commits_3_7_0] and [pull requests][OP_TEE_build_pr_3_7_0] + - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_7_0], [commits][linaro_swg_optee_examples_commits_3_7_0] and [pull requests][linaro_swg_optee_examples_pr_3_7_0] + + +[OP_TEE_optee_os_release_3_7_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.7.0 +[OP_TEE_optee_os_commits_3_7_0]: https://github.com/OP-TEE/optee_os/compare/3.6.0...3.7.0 +[OP_TEE_optee_os_pr_3_7_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 + +[OP_TEE_optee_client_release_3_7_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.7.0 +[OP_TEE_optee_client_commits_3_7_0]: https://github.com/OP-TEE/optee_client/compare/3.6.0...3.7.0 +[OP_TEE_optee_client_pr_3_7_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 + +[OP_TEE_optee_test_release_3_7_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.7.0 +[OP_TEE_optee_test_commits_3_7_0]: https://github.com/OP-TEE/optee_test/compare/3.6.0...3.7.0 +[OP_TEE_optee_test_pr_3_7_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 + +[OP_TEE_build_release_3_7_0]: https://github.com/OP-TEE/build/releases/tag/3.7.0 +[OP_TEE_build_commits_3_7_0]: https://github.com/OP-TEE/build/compare/3.6.0...3.7.0 +[OP_TEE_build_pr_3_7_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 + +[linaro_swg_optee_examples_release_3_7_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.7.0 +[linaro_swg_optee_examples_commits_3_7_0]: https://github.com/linaro-swg/optee_examples/compare/3.6.0...3.7.0 +[linaro_swg_optee_examples_pr_3_7_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 + +# OP-TEE - version 3.6.0 (2019-07-05) + +- Link to the GitHub [release page][github_release_3_6_0]. +- Links to the [commits][github_commits_3_6_0] and +[pull requests][github_pr_3_6_0] merged into this release. + +[github_release_3_6_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.6.0 +[github_commits_3_6_0]: https://github.com/OP-TEE/optee_os/compare/3.5.0...3.6.0 +[github_pr_3_6_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-04-26..2019-07-05 + +# OP-TEE - version 3.5.0 (2019-04-26) + +- Link to the GitHub [release page][github_release_3_5_0]. +- Links to the [commits][github_commits_3_5_0] and +[pull requests][github_pr_3_5_0] merged into this release. + +[github_release_3_5_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.5.0 +[github_commits_3_5_0]: https://github.com/OP-TEE/optee_os/compare/3.4.0...3.5.0 +[github_pr_3_5_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-01-26..2019-04-26 + +# OP-TEE - version 3.4.0 (2019-01-25) + +- Link to the GitHub [release page][github_release_3_4_0]. +- Links to the [commits][github_commits_3_4_0] and +[pull requests][github_pr_3_4_0] merged into this release. + +[github_release_3_4_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.4.0 +[github_commits_3_4_0]: https://github.com/OP-TEE/optee_os/compare/3.3.0...3.4.0 +[github_pr_3_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2018-10-12..2019-01-25 + +# OP-TEE - version 3.3.0 (2018-10-12) + +- Link to the GitHub [release page][github_release_3_3_0]. +- Links to the [commits][github_commits_3_3_0] and +[pull requests][github_pr_3_3_0] merged into this release. + +[github_release_3_3_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.3.0 +[github_commits_3_3_0]: https://github.com/OP-TEE/optee_os/compare/3.2.0...3.3.0 +[github_pr_3_3_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2018-07-04..2018-10-12 + +# OP-TEE - version 3.2.0 (2018-07-04) + +- Link to the GitHub [release page][github_release_3_2_0]. +- Links to the [commits][github_commits_3_2_0] and +[pull requests][github_pr_3_2_0] merged into this release. + +## Known issues + +* HiKey960: assertion in bget create_free_block() \[memalign() self-test\] ([#2414]) +* D02: assertion '!have_spinlock()' ([#2437]) + +[github_commits_3_2_0]: https://github.com/OP-TEE/optee_os/compare/3.1.0...3.2.0 +[github_pr_3_2_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2018-04-13..2018-07-04 +[github_release_3_2_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.2.0 +[#2414]: https://github.com/OP-TEE/optee_os/issues/2414 +[#2437]: https://github.com/OP-TEE/optee_os/issues/2437 + +# OP-TEE - version 3.1.0 (2018-04-13) + +- Link to the GitHub [release page][github_release_3_1_0]. +- Links to the [commits][github_commits_3_1_0] and +[pull requests][github_pr_3_1_0] merged into this release. + +[github_commits_3_1_0]: https://github.com/OP-TEE/optee_os/compare/3.0.0...3.1.0 +[github_pr_3_1_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2018-01-26..2018-04-13 +[github_release_3_1_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.1.0 + +# OP-TEE - version 3.0.0 (2018-01-26) + +[Link][github_commits_3_0_0] to a list of all commits between this release and +the previous one (2.6.0). + +About backwards compatibility: Trusted Applications built with OP-TEE 2.5.0 or +earlier will not run properly with a *debug* build of this release due +to commit [0e1c6e8e][commit_0e1c6e8e] ("Dump call stack on TA panic"). +Non-debug builds are not affected. + +## New features + +* New supported platforms: Armada 3700 ([#1946]), Poplar ([#1999]), 64-bit + support for FSL ls1012ardb ([#1941]), i.MX6SX Sabreauto ([#1974]). +* arm32: sm: init CNTVOFF ([#2052]) +* Debug/info/error traces: make output more compact ([#2011]) +* tzc380: implement new functions ([#1994]) +* Secure Data Path: add pseudo-TA to convert VA to PA (#1993]) +* Pager: use NEON AES GCM implementation ([#1959]) +* Crypto: add optimized AES GCM implementation using NEON ([#1949]) +* Add support for using secure storage for TA anti-rollback ([#1928]) +* Crypto: replace struct crypto_ops with function interface ([#1923], + [#1931]) +* aosp_optee.mk: define OPTEE_BIN ([#1922]) +* Add build option to allow concurrent execution of single-instance TAs + ([#1915]) +* Pager: support for address sanitizer ([#1856]) +* Pager: make memory between CFG_TEE_RAM_START and TEE load address usable by + pager ([#1826]) + +## Bug fixes + +* Fix crash in tee_mmu_final() on TA loading error ([#2092]) +* LibTomCrypt: fix issue causing invalid output when using AES CTR with +hardware acceleration (CFG_CRYPTO_WITH_CE) ([#2086]) +* pl310: fix cache sync ([#2035]) +* tzc380: do not write reserved bits ([#1994]) +* Fix potential double free in ta_open() ([#1970]) +* libfdt: fix undefined behaviour in fdt_offset_ptr() ([#1969]) +* imx_wdog: fix register access ([#1966]) +* Secure storage: fix potential memory leak after early return ([#1961]) +* LibTomCrypt: fix double free in dsa_import() ([#1963]) +* RPMB: fix TA independance issue in secure storage ([#1921]) +* RPMB: return TEE_ERROR_ACCESS_CONFLICT instead of panicking when a TA + attempts to create an existing persistent object without the overwrite flag + ([#1919]) +* PSCI: pass non-secure context to psci_system_suspend() ([#1916]) +* Fix "Argument list too long" during "make clean" ([#1897]) + +## Security fixes + +* Mitigations and hardening against the Spectre and Meltdown vulnerabilities + (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754). + +## Known issues + +* Secure storage (REE FS): storage size not updated after +TEE_TruncateObjectData() ([#2094]) +* Possible deadlock with CFG_WITH_PAGER=y when loading a TA and not enough +page tables are available in pgt_cache ([#2080]) + +## Tested on + +The release was tested successfully on the platforms listed below. + + +* d02 +* hikey +* hikey-hikey960 +* imx-mx6ulevk +* imx-mx7dsabresd +* marvell-armada7k8k +* marvell-armada3700 +* mediatek-mt8173 +* rcar-salvator_m3 +* rockchip-rk322x +* rpi3 +* sam +* ti +* vexpress-juno +* vexpress-qemu_armv8a +* vexpress-qemu_virt + +[commit_0e1c6e8e]: https://github.com/OP-TEE/optee_os/commit/0e1c6e8e +[github_commits_3_0_0]: https://github.com/OP-TEE/optee_os/compare/2.6.0...3.0.0 +[#2092]: https://github.com/OP-TEE/optee_os/pull/2092 +[#2086]: https://github.com/OP-TEE/optee_os/pull/2086 +[#2094]: https://github.com/OP-TEE/optee_os/issues/2094 +[#2080]: https://github.com/OP-TEE/optee_os/issues/2080 +[#2052]: https://github.com/OP-TEE/optee_os/pull/2052 +[#2035]: https://github.com/OP-TEE/optee_os/pull/2035 +[#2011]: https://github.com/OP-TEE/optee_os/pull/2011 +[#1999]: https://github.com/OP-TEE/optee_os/pull/1999 +[#1994]: https://github.com/OP-TEE/optee_os/pull/1994 +[#1993]: https://github.com/OP-TEE/optee_os/pull/1993 +[#1974]: https://github.com/OP-TEE/optee_os/pull/1974 +[#1970]: https://github.com/OP-TEE/optee_os/pull/1970 +[#1969]: https://github.com/OP-TEE/optee_os/pull/1969 +[#1966]: https://github.com/OP-TEE/optee_os/pull/1966 +[#1963]: https://github.com/OP-TEE/optee_os/pull/1963 +[#1961]: https://github.com/OP-TEE/optee_os/pull/1961 +[#1959]: https://github.com/OP-TEE/optee_os/pull/1959 +[#1949]: https://github.com/OP-TEE/optee_os/pull/1949 +[#1946]: https://github.com/OP-TEE/optee_os/pull/1946 +[#1941]: https://github.com/OP-TEE/optee_os/pull/1941 +[#1931]: https://github.com/OP-TEE/optee_os/pull/1931 +[#1928]: https://github.com/OP-TEE/optee_os/pull/1928 +[#1923]: https://github.com/OP-TEE/optee_os/pull/1923 +[#1922]: https://github.com/OP-TEE/optee_os/pull/1922 +[#1921]: https://github.com/OP-TEE/optee_os/pull/1921 +[#1919]: https://github.com/OP-TEE/optee_os/pull/1919 +[#1916]: https://github.com/OP-TEE/optee_os/pull/1916 +[#1915]: https://github.com/OP-TEE/optee_os/pull/1915 +[#1897]: https://github.com/OP-TEE/optee_os/pull/1897 +[#1856]: https://github.com/OP-TEE/optee_os/pull/1856 +[#1826]: https://github.com/OP-TEE/optee_os/pull/1826 + +# OP-TEE - version 2.6.0 + +[Link][github_commits_2_6_0] to a list of all commits between this release and +the previous one (2.5.0). + +## New features + +* New supported platforms: Atmel SAMA5 ([#1714]), HiSilicon HiKey960 ([#1684]), + Rockchip RK322X ([#1666]), NXP LS1043A-RDB/LS1046A-RDB ([#1787]), Marvell + Armada 70x0/80x0 ([#1807]). +* Dynamic shared memory (non-contiguous, non-secure memory can be mapped into + Trusted Applications VA space) ([#1631]) +* Dump TA call stack on panic ([#1858]) +* i.MX: PSCI reset ([#1849]) +* plat-ti: AM43xx: suspend/resume support ([#1822]) +* QEMU SMP support ([#1820]) +* plat-ti: AM43xx: disable TRNG ([#1816]) +* plat-ti: enable Secure Data Path by default ([#1815]) +* Improve symbolize.py ([#1778], [#1767], [#1766]) +* Early TAs (TAs linked in tee.bin) ([#1733]) +* Suspend/resume framework for arm32 and imx7d support ([#1729]) +* RK322X PSCI version, features and suspend support ([#1720]) +* arm32: handle aborts in system mode ([#1703]) +* i.MX: add SNVS SRTC support ([#1700]) +* GCC7 support ([#1693]) +* Improve detection of programming errors in locking code ([#1671], [#1670]) +* Support TEE RAM size larger than page directory size ([#1669]) + +## Removed features + +* Remove TUI code ([#1842]) + +## Bug fixes + +* Add missing synchronization barrier in core_mmu_map_pages() ([#1827]) +* Secure storage: REE FS: fix bug in error path ([#1801]) +* ASAN bug fixes ([#1799]) +* Fix race in core_mmu_user_mapping_is_active() ([#1785]) +* libutee: printf() and puts() fixes, add putchar() ([#1759], [#1754]) +* arm32: GICv3: fix FIQ masking in IRQ/ABT/SVC/UND handlers ([#1748]) +* arm32: preserve r12 in native_intr_handler() ([#1682]) +* arm64: fix print_kernel_stack() ([#1664]) +* benchmark: fix core data-abort ([#1658]) + +## Security fixes or enhancements + +* crypto: fix software PRNG weaknesses + ([OP-TEE-2017-0001][OP-TEE-2017-0001]) ([#1843]) + +## Tested on + +The release was tested successfully on the platforms listed below. +If a platform is not listed, it means the release was not tested on this +platform. + + +* d02 +* hikey +* hikey-hikey960 +* imx-mx6ulevk +* imx-mx7dsabresd +* ls-ls1021a??? (single core) +* ls-ls1043ardb +* ls-ls1046ardb +* mediatek-mt8173 +* rcar +* rockchip-rk322x +* rpi3 +* sam +* stm-b2260 +* stm-cannes +* ti-??? +* vexpress-fvp +* vexpress-juno +* vexpress-qemu_armv8a +* vexpress-qemu_virt + +[github_commits_2_6_0]: https://github.com/OP-TEE/optee_os/compare/2.5.0...2.6.0 +[#1858]: https://github.com/OP-TEE/optee_os/issues/1858 +[#1849]: https://github.com/OP-TEE/optee_os/issues/1849 +[#1843]: https://github.com/OP-TEE/optee_os/issues/1843 +[#1842]: https://github.com/OP-TEE/optee_os/issues/1842 +[#1827]: https://github.com/OP-TEE/optee_os/issues/1827 +[#1822]: https://github.com/OP-TEE/optee_os/issues/1822 +[#1820]: https://github.com/OP-TEE/optee_os/issues/1820 +[#1816]: https://github.com/OP-TEE/optee_os/issues/1816 +[#1815]: https://github.com/OP-TEE/optee_os/issues/1815 +[#1807]: https://github.com/OP-TEE/optee_os/issues/1807 +[#1801]: https://github.com/OP-TEE/optee_os/issues/1801 +[#1799]: https://github.com/OP-TEE/optee_os/issues/1799 +[#1787]: https://github.com/OP-TEE/optee_os/issues/1787 +[#1785]: https://github.com/OP-TEE/optee_os/issues/1785 +[#1778]: https://github.com/OP-TEE/optee_os/issues/1778 +[#1767]: https://github.com/OP-TEE/optee_os/issues/1767 +[#1766]: https://github.com/OP-TEE/optee_os/issues/1766 +[#1759]: https://github.com/OP-TEE/optee_os/issues/1759 +[#1754]: https://github.com/OP-TEE/optee_os/issues/1754 +[#1748]: https://github.com/OP-TEE/optee_os/issues/1748 +[#1733]: https://github.com/OP-TEE/optee_os/issues/1733 +[#1729]: https://github.com/OP-TEE/optee_os/issues/1729 +[#1720]: https://github.com/OP-TEE/optee_os/issues/1720 +[#1714]: https://github.com/OP-TEE/optee_os/issues/1714 +[#1703]: https://github.com/OP-TEE/optee_os/issues/1703 +[#1700]: https://github.com/OP-TEE/optee_os/issues/1700 +[#1693]: https://github.com/OP-TEE/optee_os/issues/1693 +[#1684]: https://github.com/OP-TEE/optee_os/issues/1684 +[#1682]: https://github.com/OP-TEE/optee_os/issues/1682 +[#1671]: https://github.com/OP-TEE/optee_os/issues/1671 +[#1670]: https://github.com/OP-TEE/optee_os/issues/1670 +[#1669]: https://github.com/OP-TEE/optee_os/issues/1669 +[#1666]: https://github.com/OP-TEE/optee_os/issues/1666 +[#1664]: https://github.com/OP-TEE/optee_os/issues/1664 +[#1658]: https://github.com/OP-TEE/optee_os/issues/1658 +[#1631]: https://github.com/OP-TEE/optee_os/issues/1631 +[OP-TEE-2017-0001]: https://www.op-tee.org/security-advisories/ + +# OP-TEE - version 2.5.0 + +[Link][github_commits_2_5_0] to a list of all commits between this release and +the previous one (2.4.0). + +## New features + +* New supported platform: i.MX7D ([#1639]) +* Secure storage: anti-rollback protection for REE FS using RPMB FS ([#1630]) +* Assign non-secure DDR configuration from DT if CFG_DT=y ([#1623]) +* Add new image format: split image into three separate binaries suitable for + upcoming ARM Trusted Firmware ([#1589]). +* Make alignment check configurable ([#1586]) +* drivers: add TZC380 driver ([#1578]) +* plat-imx: PSCI CPU off ([#1577]) +* 64-bit paging on QEMU v8 and HiKey ([#1575], [#1592]) +* Benchmark framework ([#1365]) +* Dump call stack of user TAs on abort ([#1552]) +* plat-hikey: enable Secure Data Path ([#1440]) +* Add interface to load and decrypt/authenticate user TAs ([#1513]) +* plat-ti: add secure paging support ([#1493]) +* plat-ti: add OTP hardware key support ([#1492]) +* Support ARM GICv3 ([#1465]) + +## Removed features + +* stm-orly2 is not supported anymore ([#1650]) +* Remove secure storage based on SQL FS (`CFG_SQL_FS=y`) ([#1490]) +* Remove support for mapping user TAs with 1 MiB or 2 MiB granularity + (`CFG_SMALL_PAGE_USER_TA=n`) ([#1559]). TAs are always mapped using small + pages. + +## Bug fixes + +* Reduce size of non-pageable code ([#1621]) +* Ignore `TA_FLAG_MULTI_SESSION` and `TA_FLAG_INSTANCE_KEEP_ALIVE` when + `TA_FLAG_SINGLE_INSTANCE` is not set ([#1574]) +* libutee: remove buffering for AES GCM (PR#1573) and AES CTR ([#1580]) +* Fix ROUNDUP()/ROUNDDOWN() macros ([#1519]) +* Do not touch other bits in GICD_CTLR ([#1508]) +* Fix build issue with `DEBUG=y` and `CFG_TEE_CORE_LOG_LEVEL=0` ([#1502]) +* crypto: do not restrict hash size when algorithm is ECDSA ([#1497]) + +## Security fixes or enhancements + +- crypto: fix RSA key leakage after fault injection attack + ([OP-TEE-2016-0003][OP-TEE-2016-0003]) ([#1610]) +* crypto: fix RSA key leakage after side channel attack + ([OP-TEE-2016-0002][OP-TEE-2016-0002]) ([#1610]) +* Make pager aliased pages not always writable ([#1551]) +* Support for no-exec RO and RW data ([#1459], [#1550]) + +## New issues + +* armv7: some platform-specific code (`plat_cpu_reset_early()`) overwrites +SCTLR bits configured by generic code. This affects alignment checks (`SCTLR.A`) +and write-implies-no-exec (`SCTLR.WXN`, `SCTLR.UWXN`), which can therefore not +be configured via the compile-time `CFG_` variables. +* armv7: plat-imx: Cortex-A9 cores should enable branch prediction (`SCLTR.Z`) +for improved performance. +* [#1656] qemu_armv8a: init hangs when secure data path and pager are both + enabled. + +## Tested on + +In the list below, _standard_ means that the `xtest` program passed with +its default configuration, while _extended_ means it was run successfully +with the additional GlobalPlatformâ„¢ TEE Initial Configuration Test Suite +v1.1.0.4. + +If a platform is not listed, it means the release was not tested on this +platform. + + +* d02: extended +* hikey: extended +* imx-mx6ulevk: standard +* imx-mx6ullevk: standard +* imx-mx7dsabresd: standard +* ls-ls1021atwr: standard +* mediatek-mt8173: standard +* rcar-h3: standard +* rpi3: standard +* stm-b2260: extended +* stm-cannes: extended +* ti-am43xx: standard +* ti-am57xx: standard +* ti-dra7xx: standard +* vexpress-fvp: standard +* vexpress-juno: standard +* vexpress-qemu_armv8a: standard +* vexpress-qemu_virt: standard + +[github_commits_2_5_0]: https://github.com/OP-TEE/optee_os/compare/2.4.0...2.5.0-rc1 +[#1656]: https://github.com/OP-TEE/optee_os/issues/1656 +[#1650]: https://github.com/OP-TEE/optee_os/pull/1650 +[#1639]: https://github.com/OP-TEE/optee_os/pull/1639 +[#1630]: https://github.com/OP-TEE/optee_os/pull/1630 +[#1623]: https://github.com/OP-TEE/optee_os/pull/1623 +[#1621]: https://github.com/OP-TEE/optee_os/pull/1621 +[#1610]: https://github.com/OP-TEE/optee_os/pull/1610 +[#1592]: https://github.com/OP-TEE/optee_os/pull/1592 +[#1589]: https://github.com/OP-TEE/optee_os/pull/1589 +[#1586]: https://github.com/OP-TEE/optee_os/pull/1586 +[#1580]: https://github.com/OP-TEE/optee_os/pull/1580 +[#1578]: https://github.com/OP-TEE/optee_os/pull/1578 +[#1577]: https://github.com/OP-TEE/optee_os/pull/1577 +[#1574]: https://github.com/OP-TEE/optee_os/pull/1574 +[#1559]: https://github.com/OP-TEE/optee_os/pull/1559 +[#1551]: https://github.com/OP-TEE/optee_os/pull/1551 +[#1550]: https://github.com/OP-TEE/optee_os/pull/1550 +[#1519]: https://github.com/OP-TEE/optee_os/pull/1519 +[#1502]: https://github.com/OP-TEE/optee_os/pull/1502 +[#1365]: https://github.com/OP-TEE/optee_os/pull/1365 +[#1552]: https://github.com/OP-TEE/optee_os/pull/1552 +[#1513]: https://github.com/OP-TEE/optee_os/pull/1513 +[#1508]: https://github.com/OP-TEE/optee_os/pull/1508 +[#1493]: https://github.com/OP-TEE/optee_os/pull/1493 +[#1497]: https://github.com/OP-TEE/optee_os/pull/1497 +[#1492]: https://github.com/OP-TEE/optee_os/pull/1492 +[#1490]: https://github.com/OP-TEE/optee_os/pull/1490 +[#1465]: https://github.com/OP-TEE/optee_os/pull/1465 +[#1459]: https://github.com/OP-TEE/optee_os/pull/1459 +[#1440]: https://github.com/OP-TEE/optee_os/pull/1440 +[OP-TEE-2016-0003]: https://www.op-tee.org/security-advisories/ +[OP-TEE-2016-0002]: https://www.op-tee.org/security-advisories/ + +# OP-TEE - version 2.4.0 + +[Link][github_commits_2_4_0] to a list of all commits between this release and +the previous one (2.3.0). + +Please note: this release is API-compatible with the previous one, but the +Secure Storage internal format for the REE and SQL FS is not compatible due to +commits [a238b74][commit_a238b74] ("core: REE FS: use the new hash tree +interface") and [44e900e][commit_44e900e] ("core: SQL FS: use the new hash tree +interface"). + +## New features + +* Add porting guidelines + +* Add support for Secure Data Path which allows Client and Trusted Applications + to share references to secure memory + +* New supported platform: Texas Instruments AM57xx (`PLATFORM=ti-am57xx`) + +* ARMv7-A: add support for platform services in secure monitor and add these + services for the DRA7xx platform + +* SPI framework and PL022 driver cleanup and improvements + +* Use CNTPCT (when available) to add entropy to the software PRNG + +* Add GlobalPlatform Socket API for UDP and TCP (IPv4 and IPv6) + +* DRA7: add TRNG driver, enable GICv2 driver + +* Support load address larger than 4G + +* libutee: preserve error code when calling TEE_Panic() for easier + troubleshooting + +* Support TA profiling with gprof (-pg compiler switch) + +* Optimize the ELF loader for TAs when pager is enabled + +* Update documentation + +* Add paged secure shared memory that can be transferred between TAs as + needed + +* Introduce MOBJ abstraction + +* i.MX6: add PSCI "on" function + +* arm32: introduce PSCI framework + +## Bug fixes + +* Secure storage: improve integrity checking of the REE and SQL filesystems by + adding a hash tree on the internal data structures. Any external modification + is detected, except full rollback. Fixes [#1188][issue1188]. + +* The linux driver will set the 'privileged' flag (TEE_GEN_CAP_PRIVILEGED) on + the device intended for use by tee-supplicant. Fixes [#1199][issue1199]. + +* RPMB: don't try to program the RPMB key by default + +* Fix "make clean" error cases + +* Fix issue when resetting persistent storage enumerator [#1332][issue1332] + +* Fix TA panic when doing AES CTS with specific buffer sizes + [#1203][issue1203]. + +## Known issues + +* On RPi3 xtest sometimes stall (rcu_sched self-detected stall on CPU) [#1353][issue1353] +* For multi-core PSCI support is to be added for ls1021atwr in OP-TEE. +* USB keyboard cannot be used to stop the u-boot timeout ([build issue131]). +* Travis service (build.git) seems unstable from time to time. + +## Tested on + +In the list below, _standard_ means that the `xtest` program passed with +its default configuration, while _extended_ means it was run successfully +with the additional GlobalPlatformâ„¢ TEE Initial Configuration Test Suite +v1.1.0.4. + +If a platform is not listed, it means the release was not tested on this +platform. + + +* d02: extended +* hikey: extended +* imx-mx6ulevk: standard +* ls-ls1021atwr: standard (single core) +* mediatek-mt8173: standard +* rcar-h3: standard +* rpi3: standard +* stm-b2260: extended +* ti-dra7xx: standard +* vexpress-fvp: standard +* vexpress-juno: standard +* vexpress-qemu_armv8a: standard +* vexpress-qemu_virt: standard +* zynqmp-zc1751_dc1: standard +* zynqmp-zc1751_dc2: standard +* zynqmp-zcu102: standard + +[github_commits_2_4_0]: https://github.com/OP-TEE/optee_os/compare/2.3.0...2.4.0 +[issue1332]: https://github.com/OP-TEE/optee_os/issues/1332 +[issue1353]: https://github.com/OP-TEE/optee_os/issues/1353 +[build issue131]: https://github.com/OP-TEE/build/issues/131 +[commit_a238b74]: https://github.com/OP-TEE/optee_os/commit/a238b744b1b3 +[commit_44e900e]: https://github.com/OP-TEE/optee_os/commit/44e900eabfc1 + +# OP-TEE - version 2.3.0 + +[Link][github_commits_2_3_0] to a list of all commits between this release and +the previous one (2.2.0). + +Please note: this release is API-compatible with the previous one, but the +Secure Storage internal format for the REE FS is not compatible due to commit +[361fb3e][commit_361fb3e] ("core: REE FS: use a single file per object"). + +[commit_361fb3e]: https://github.com/OP-TEE/optee_os/commit/361fb3e + +## New features + +* New supported platform: Xilinx Zynq 7000 ZC702 (`PLATFORM=zynq7k-zc702`) + +* Add debug assertions to spinlocks and mutexes + +* Add more CP15 register access macros for Cortex-A9 + +* ARMv7-A: redesign secure monitor to make it easier to register services + +* ARMv7-A: cleanup boot arguments + +* libutee: extend `TEE_CheckMemoryAccessRights()` with + `TEE_MEMORY_ACCESS_SECURE` and `TEE_MEMORY_ACCESS_NONSECURE` + +* plat-hikey: enable SPI by default and add sample test code + +* Consider `CFLAGS_ta_arm64` and `CFLAGS_ta_arm32` when building TAs + +* Secure storage refactoring + - Simplify interface with tee-supplicant. Minimize round trips with normal + world, especially by adding a cache for FS RPC payload data. + - REE FS: use a single file per object, remove block cache. + +* Print call stack in panic() + +## Bug fixes + +* Fix UUID encoding when communicating with normal world (use big endian + mode instead of native endianness). Related to this, the string format + for UUIDs has changed in tee-supplicant, so that TA file names now follow + the format defined in RFC4122 (a missing hyphen was added). The old format + is still supported, but deprecated, and will likely be removed with the + next major release. + +* Drop write permission to non-writable ELF segments after TA loading is + complete. + +* mm: fix confusing memory mapping debug traces + +* plat-ti: fix issues with MMU mapping + +* crypto: fix clearing of big numbers + +* build: allow spaces and double quotes in CFG_ variables + +* mm: use paddr_t to support both 32- and 64-bit architectures properly. + Resolves 32-bit truncation error when pool is at top of 32 bit address + space on 64-bit architecture. + +* plat-stm: support pager. Fix pager on ARMv7-A SMP boards. + +* Fix debug output of Trusted Applications (remove "ERROR: TEE-CORE:" prefix) + +* Do not consider TA memref parameters as TA private memory + +* crypto: fix `cipher_final()` which would not call `cbc_done()` for CBC_MAC + algorithms + +* fix for 16-way PL310 + +* arm32: fix call stack unwinding (`print_stack()`) + +* arm32: fix spinlock assembly code + +* plat-stm, plat-imx: fix SCR initalization + +* Fix user L1 MMU entries calculation (non-LPAE), allowing TTBCR.N values + other than 7. + +* mtk-mt8173: fix panic caused by incorrect size of SHMEM + +* plat-stm: fix RNG driver (non-flat mapping) + +## Known issues + +* New issues open on GitHub + * [#1203][issue1203] AES-CTS mode will fail when inlen=0x100, in_incr=0x80 + * [#1199][issue1199] Both tee and teepriv reported GlobalPlatform compliant + * [#1188][issue1188] Secure storage (SQL FS and REE FS): blocks not tied to + current meta header + * [#1172][issue1172] paddr_t should be larger than 32 bits when + CFG_WITH_LPAE is enabled + +## Tested on + +In the list below, _standard_ means that the `xtest` program passed with +its default configuration, while _extended_ means it was run successfully +with the additional GlobalPlatformâ„¢ TEE Initial Configuration Test Suite +v1.1.0.4. + +If a platform is not listed, it means the release was not tested on this +platform. + + +* d02: extended +* hikey: extended +* imx-mx6ulevk: standard +* ls-ls1021atwr: standard +* mediatek-mt8173: standard +* rcar-h3: standard +* rpi3: standard +* stm-b2260: extended +* stm-cannes: extended +* ti-dra7xx: standard +* vexpress-fvp: standard +* vexpress-juno: standard +* vexpress-qemu_armv8a: standard +* vexpress-qemu_virt: extended +* zynqmp-zcu102: standard + +[github_commits_2_3_0]: https://github.com/OP-TEE/optee_os/compare/2.2.0...2.3.0 +[issue1172]: https://github.com/OP-TEE/optee_os/issues/1172 +[issue1188]: https://github.com/OP-TEE/optee_os/issues/1188 +[issue1199]: https://github.com/OP-TEE/optee_os/issues/1199 +[issue1203]: https://github.com/OP-TEE/optee_os/issues/1203 + +# OP-TEE - version 2.2.0 + +[Link][github_commits_2_2_0] to a list of all commits between this release and +the previous one (2.1.0). + +Please note: this release is API-compatible with the previous one, but the +Secure Storage internal format is not compatible due to commit +[fde4a75][commit_fde4a75] ("storage: encrypt the FEK with a TA-specific key"). + +[commit_fde4a75]: https://github.com/OP-TEE/optee_os/commit/fde4a75 + +## New features + +* New supported platforms: + * Freescale i.MX6 Quad SABRE Lite & SD + * HiSilicon D02 + * Raspberry Pi3 + * Renesas RCAR H3 + * STMicroelectronics b2260 - h410 + +* Pager: Support paging of read/write pages by encrypting them with AES-GCM. + Support paging of user TAs. Add global setting for TZSRAM size + (CFG_CORE_TZSRAM_EMUL_SIZE), defaults to 300K. + +* Support for more than 8 CPU cores + +* Added SPI framework and PL022 driver + +* GPIO: framework supports multiple instances, PL061 driver now has get/set + interrupt and mode control functions + +* Secure storage: Encrypt the File Encryption Key with a TA-specific key for + better TA isolation. Add build-time and run-time support for multiple storage + backends. Add SQLite backend. + +* Trusted User Interface: some code is introduced to support the implementation + of TUI. This includes: a generic framebuffer driver, display and serial + abstractions, and drivers for PL111 (LCD) / PL050 (KMI) / TZC400 and PS2 + mouse. + +* AES acceleration using ARMv8-A Cryptographic Extensions instructions is + now supported in AArch32 mode + +* Add support for GCC flags: -fsanitize=undefined and -fsanitize=kernel-address + +* Use a global setting for core heap size (CFG_CORE_HEAP_SIZE), 64K by default. + +* Add macros to unwind and print the call stack of TEE core + +* Libtomcrypt: sync with the latest `develop` branch. + +* The Trusted Application SDK (ta_dev_kit.mk) can produce libraries (.a) + +* Rework assertions and TEE core panics and properly honor NDEBUG + +## Bug fixes + +* Fix incorrect algorithm passed to cipher.final() + +* scripts: support Python 2.x and 3.x + +* Secure storage: Add proper locking to support concurrent access. Fix sign + extension bug with offset parameter of syscall storage_obj_seek which could + cause errors in Aarch32 mode. Fix reading beyond end of file. + +* Aarch64: mask all maskable exceptions before doing a normal return from call. + +* Device Tree: add no-map property to OP-TEE node in reserved-memory. + +* LibTomcrypt: fix CVE-2016-6129 + +## Known issues + +* New issues open on GitHub + * [#1093][issue1093] rcar-h3: xtest 6010 hangs + * [#1092][issue1092] rcar-h3: xtest 4010 fails + * [#1081][issue1081] Bad mapping of TA secure memref parameters + * [#1071][issue1071] __data_end may not correctly represent text start position when using CFG_WITH_PAGER + * [#1069][issue1069] armv7/Aarch32: crash in stack unwind (DPRINT_STACK()) + +## Tested on + +In the list below, _standard_ means that the `xtest` program passed with +its default configuration, while _extended_ means it was run successfully +with the additional GlobalPlatformâ„¢ TEE Initial Configuration Test Suite +v1.1.0.4. + +If a platform is not listed, it means the release was not tested on this +platform. + + +* d02: extended +* hikey: extended +* imx-mx6qsabrelite: standard +* imx-mx6qsabresd: standard +* rcar-h3: standard, pass except issues [#1092][issue1092] and [#1093][issue1093] +* rpi3: standard +* stm-b2260: standard +* stm-cannes: standard +* ti-dra7xx: standard +* vexpress-fvp: standard +* vexpress-juno: standard +* vexpress-qemu_armv8a: standard +* vexpress-qemu_virt: extended +* zynqmp-zcu102: standard + +[github_commits_2_2_0]: https://github.com/OP-TEE/optee_os/compare/2.1.0...2.2.0 +[issue1081]: https://github.com/OP-TEE/optee_os/issues/1081 +[issue1071]: https://github.com/OP-TEE/optee_os/issues/1071 +[issue1069]: https://github.com/OP-TEE/optee_os/issues/1069 +[issue1092]: https://github.com/OP-TEE/optee_os/issues/1092 +[issue1093]: https://github.com/OP-TEE/optee_os/issues/1093 + +# OP-TEE - version 2.1.0 + +## New features + +* New supported platforms: + * Xilinx Zynq UltraScale+ MPSOC + * Spreadtrum SC9860 + +* GCC5 support + +* Non Linear Mapping support: In OP-TEE kernel mode, the physical to virtual + addresses was linear until this release, meaning the virtual addresses + were equal to the physical addresses. This is no more the case in this + release. + +* Font rendering routines have been introduced in order to ease an + implementation of Trusted UI. + +* File Storage: Possibility to use the normal world filesystem and the RPMB + implementations simultaneously. + +* AOSP: There is a [local manifest][aosp_local_manifest] to build OP-TEE into an AOSP build, running on HiKey. + Please refer to the README in that repo for instructions. + +* OpenEmbedded: In addition to the makefile-based build described in the optee_os README, there is an + [OpenEmbedded-based build][oe_build] that supports Qemu (32-bit), FVP (64-bit), and HiKey (64-bit). + Please refer to the README in that repo for instructions. + +* [Link][github_commits_2_1_0] to a list of all commits between this and + previous release. + + +## Tested on +Definitions: + +| Type | Meaning | +| ---- | ------- | +| Standard tests | The [optee_test][optee_test] project. | +| Extended tests | optee_test with tests from the GlobalPlatformâ„¢ TEE Initial Configuration Test Suite v1.1.0.4. | + +* ARM Juno Board (vexpress-juno), standard. +* Foundation Models (vexpress-fvp), standard tests + extended tests, + using FVP ARM V8 Foundation Platformr0p0 (platform build 10.0.37) +* FSL i.MX6 UltraLite EVK (imx), standard. +* FSL ls1021a (ls-ls1021atwr), standard tests. +* HiKey (hikey), standard + extended tests. +* QEMU (vexpress-qemu), standard + extended tests. +* Xilinx Zynq UltraScale+ MPSOC, standard tests + +Note that the following platform has not been tested: +* MTK8173-EVB (mediatek-mt8173) + + +## Known issues +* Issue(s) open on GitHub + * [#868][pr868]: python-wand font generation sometimes times out + * [#863][pr863]: "double free or corruption" error when building optee_os + * [#858][pr858]: UUIDs in binary format have wrong endinanness + * [#857][pr857]: Formatting of UUIDs is incorrect + * [#847][pr847]: optee_os panic(TEE-CORE: Assertion) + * [#838][pr838]: TUI font rendering is _very_ slow + * [#814][pr814]: Persistent objects : save informations after close + * [#665][pr665]: xtest 1013 stalled on HiKey when log levels are 4 and optee_os is on its own UART + * [#506][pr506]: tee-supplicant panic & ta panic + +[github_commits_2_1_0]: https://github.com/OP-TEE/optee_os/compare/2.0.0...2.1.0 +[pr868]: https://github.com/OP-TEE/optee_os/issues/868 +[pr863]: https://github.com/OP-TEE/optee_os/issues/863 +[pr858]: https://github.com/OP-TEE/optee_os/issues/858 +[pr857]: https://github.com/OP-TEE/optee_os/issues/857 +[pr847]: https://github.com/OP-TEE/optee_os/issues/847 +[pr838]: https://github.com/OP-TEE/optee_os/issues/838 +[pr814]: https://github.com/OP-TEE/optee_os/issues/814 +[pr665]: https://github.com/OP-TEE/optee_os/issues/665 +[aosp_local_manifest]: https://github.com/linaro-swg/optee_android_manifest +[oe_build]: https://github.com/linaro-swg/oe-optee + +# OP-TEE - version 2.0.0 + +## New features + +* Generic driver: A new generic TEE driver is in the process of being + [upstreamed][gendrv_v9]. + In this release, [OP-TEE/optee_linuxdriver][optee_linuxdriver] is no more used. + Instead, linux v4.5 is being patched using the proposed Generic TEE Driver, + as it can be found in [https://github.com/linaro-swg/linux/tree/optee][linux_optee] + +* RPMB support: Secure Storage can now use Replay Protected Memory Block (RPMB) partition + of an eMMC device. Check the [full documentation][rpmb_doc] + +* Hard-float ABI is now available. + +* [Link][github_commits_2_0_0] to a list of all commits between this and + previous release. + + +## Tested on +Definitions: + +| Type | Meaning | +| ---- | ------- | +| Standard tests | The [optee_test][optee_test] project. | +| Extended tests | optee_test with tests from the GlobalPlatformâ„¢ TEE Initial Configuration Test Suite v1.1.0.4. | + +* ARM Juno Board (vexpress-juno), standard. +* Foundation Models (vexpress-fvp), standard tests + extended tests, + using FVP ARM V8 Foundation Platformr0p0 (platform build 9.5.40) +* FSL ls1021a (ls-ls1021atwr), standard. +* HiKey (hikey), standard. +* MTK8173-EVB (mediatek-mt8173), standard. +* QEMU (vexpress-qemu), standard + extended tests. +* STM Cannes (stm-cannes), standard + extended tests. + +## Known issues +* Issue(s) open on GitHub + * [#40][prld40] BUG_ON() when re-using RPC buffer to tee-supplicant + * [#506][pr506]: tee-supplicant panic & ta panic + +[github_commits_2_0_0]: https://github.com/OP-TEE/optee_os/compare/1.1.0...2.0.0 +[rpmb_doc]: https://github.com/OP-TEE/optee_os/blob/master/documentation/secure_storage_rpmb.md +[optee_linuxdriver]: https://github.com/OP-TEE/optee_linuxdriver +[gendrv_v9]: https://lkml.org/lkml/2016/4/1/205 +[linux_optee]: https://github.com/linaro-swg/linux/tree/optee + + +# OP-TEE - version 1.1.0 + + +## New features + +* Softfloat library: floating point support is now available in 32bits TA. + +* Support running 64-bits TA: on ARMv8-A platform, TA can be compiled in + AArch32 and/or in AArch64 in case the core is compiled in AArch64. + An example can be found in HiKey configuration file. Using the following + excerpt code, the user TA libraries are compiled in both AArch32 and + AArch64, and can be found in `out/arm-plat-hikey/export-ta_arm32` and + `out/arm-plat-hikey/export-ta_arm64` + +``` + ta-targets = ta_arm32 + ta-targets += ta_arm64 +``` + +* Concurrent TA support: multiple TA can run in parallel on + several cores. + +* New tests added in xtest test suite: concurrent TA (xtest 1013), + floating point tests (xtest 1006 and os_test TA) and corruption + file storage (xtest 20000) + +* [Link][github_commits_1_1_0] to a list of all commits between this and + previous release. + + +## Tested on +Definitions: + +| Type | Meaning | +| ---- | ------- | +| Standard tests | The [optee_test][optee_test] project. | +| Extended tests | optee_test with tests from the GlobalPlatformâ„¢ TEE Initial Configuration Test Suite v1.1.0.4. | +| Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | + +* Foundation Models (vexpress-fvp), standard tests + extended tests, + using FVP ARM V8 Foundation Platformr0p0 (platform build 9.5.40) +* HiKey (hikey), standard + extended tests. +* MT8173 (mediatek), standard tests. +* QEMU (vexpress-qemu), standard + extended tests. +* STM Cannes (stm-cannes), standard + extended tests. + +## Known issues +* Secure Storage is implemented, but note that anti-rollback protection + is not implemented yet. + +* Issue(s) open on GitHub + * [#40][prld40] BUG_ON() when re-using RPC buffer to tee-supplicant + * [#296][pr296]: Connecting RPMB to the storage APIs. + * [#493][pr493]: setup_juno_optee: unable to find pre-built binaries + * [#506][pr506]: tee-supplicant panic & ta panic + +[prld40]: https://github.com/OP-TEE/optee_linuxdriver/issues/40 +[pr506]: https://github.com/OP-TEE/optee_os/issues/506 +[github_commits_1_1_0]: https://github.com/OP-TEE/optee_os/compare/1.0.1...1.1.0 + + + +# OP-TEE - version 1.0.0 + +OP-TEE is now maintained by Linaro. Contributors do not need to +sign a CLA anymore, but must follow the rules of the [DCO][DCO] +(Developer Certificate of Origin) instead. + + +## New features + +* Add hardware support for Texas Instruments DRA7xx, ARMv7 (plat-ti) + +* GlobalPlatformâ„¢ TEE Internal Core API Specification v1.1, + including ECC algorithms. + +* Secure Storage: Files stored by the REE are now encrypted. Operations + are made atomic in order to prevent inconsistencies in case of errors + during the storage operations. [Slides][LCStorage] describing the + Secure Storage have been presented at the Linaro Connect SFO15. + +* Change of format of the Trusted Applications: they follow a + [signed ELF format][elf] + +* Rework thread [synchronization][synchro] in optee_os. + +* Use of ARMv8 native cryptographic support. + +* [OP-TEE/optee_test][optee_test] test suite is released. + +* Introduce [OP-TEE/manifest][manifest] and [OP-TEE/build][build] + to setup and build QEMU, FVP, HiKey and Mediatek platforms. Setup scripts + that used to be in optee_os have been removed, except for Juno board. + +* [Link][github_commits_1_0_0] to a list of all commits between this and + previous release. + + +## Tested on +Definitions: + +| Type | Meaning | +| ---- | ------- | +| Standard tests | The [optee_test][optee_test] project. | +| Extended tests | optee_test with tests from the GlobalPlatformâ„¢ TEE Initial Configuration Test Suite v1.1.0.4. | +| Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | + +* ARM Juno Board (vexpress-juno), standard + extended tests. +* Foundation Models (vexpress-fvp), standard tests. +* HiKey (hikey), standard + extended tests. +* MT8173 (mediatek), standard tests. +* QEMU (vexpress-qemu), standard + extended tests. +* STM Cannes (stm-cannes), standard + extended tests. + +## Known issues +* Secure Storage is implemented, but note that anti-rollback protection + is not implemented yet. + +* Issue(s) open on GitHub + * [#210][pr210]: libteec.so 32-bit does not communicate well + with 64-bit kernel module + * [#296][pr296]: Connecting RPMB to the storage APIs. + * [#493][pr493]: setup_juno_optee: unable to find pre-built binaries + * [#494][pr494]: HiKey: xtest 7671 fails (1.0.0-rc2) + +[pr210]: https://github.com/OP-TEE/optee_os/issues/210 +[pr296]: https://github.com/OP-TEE/optee_os/issues/296 +[pr493]: https://github.com/OP-TEE/optee_os/issues/493 +[pr494]: https://github.com/OP-TEE/optee_os/issues/494 +[github_commits_1_0_0]: https://github.com/OP-TEE/optee_os/compare/0.3.0...1.0.0 +[DCO]: https://github.com/OP-TEE/optee_os/blob/master/Notice.md#contributions +[LCStorage]: http://www.slideshare.net/linaroorg/sfo15503-secure-storage-in-optee +[synchro]: https://github.com/OP-TEE/optee_os/blob/master/documentation/optee_design.md#4-thread-handling +[elf]: https://github.com/OP-TEE/optee_os/blob/master/documentation/optee_design.md#format +[optee_test]: https://github.com/OP-TEE/optee_test +[manifest]: https://github.com/OP-TEE/manifest +[build]: https://github.com/OP-TEE/build + + + +# OP-TEE - version 0.3.0 + +## New features + +* Add hardware support for + * Mediatek MT8173 Board, ARMv8-A (plat-mediatek) + * Hisilicon HiKey Board, ARMv8-A (plat-hikey) +* AArch64 build of optee_os is now possible through the configuration `CFG_ARM64_core=y` +* Secure Storage: Data can be encrypted prior to their storage in the non-secure. + Build is configured using `CFG_ENC_FS=y` +* A generic boot scheme can be used. Boot configuration is commonalized. This helps + new board support. It is applied on plat-hikey, plat-vexpress, plat-mediatek, plat-stm + and plat-vexpress. + +## Tested on +Definitions: + +| Type | Meaning | +| ---- | ------- | +| Standard tests | The optee_test project. | +| Extended tests | optee_test with tests from the GlobalPlatformâ„¢ TEE Initial Configuration Test Suite v1.1.0.4. | +| Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | + +* ARM Juno Board (vexpress-juno), standard tests. +* Foundation Models (vexpress-fvp), standard tests. +* HiKey (hikey), standard tests. +* MT8173 (mediatek), standard tests. +* QEMU (vexpress-qemu), standard + extended tests. +* STM Cannes (stm-cannes), standard + extended tests. + +------------------------------------------- + +# OP-TEE - version 0.2.0 + +## New features + +### Linux Driver Refactoring + +Linux Driver has been refactored. It is now split in two parts: +* optee.ko, the generic Linux driver. It contains all functionality + common to all backends. +* optee_armtz.ko, a specific backend dedicated to the TrustZone optee. + It depends on optee.ko. + +Loading the TrustZone optee linux driver module is now performed using + + modprobe optee_armtz + +Thanks to the dependency between the generic and the backend modules, optee.ko is then automatically loaded. + +### Misc new features +* support PL310 lock down at TEE boot +* add 64bits support (division / print) + +## Tested on +Definitions: + +| Type | Meaning | +| ---- | ------- | +| Standard tests | The optee_test project. | +| Extended tests | optee_test with tests from the GlobalPlatformâ„¢ TEE Initial Configuration Test Suite v1.1.0.4. | +| Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | + +* ARM Juno Board (vexpress-juno), standard tests + extended tests. + +* Foundation Models (vexpress-fvp), standard + extended tests. + +* QEMU (vexpress-qemu), standard + extended tests. + +* STM Cannes (stm-cannes), standard + extended tests. + + +## Issues resolved since last release +* Fix user TA trace issue, in order each TA is able to select its own trace level + + +------------------------------------------- +# OP-TEE - version 0.1.0 + +## New features +Below is a summary of the most important features added, but at the end you will +find a link that present you all commits between the current and previous +release tag. + +* GlobalPlatform Client API v1.0 support. + +* GlobalPlatform Internal API v1.0 support. + +* GlobalPlatform Secure Elements v1.0 support. + +* Add hardware support for + + * Allwinner A80, ARMv7-A. + + * ARM Juno Board, ARMv8-A. + + * Foundation Models, ARMv8-A. + + * Fast Models, ARMv8-A. + + * QEMU, ARMv7-A. + + * STM Cannes, ARMv7-A. + + * STM Orly2, ARMv7-A. + +* Add LibTomCrypt as the default software cryptographic library. + +* Add cryptographic abstraction layer in on secure side to ease the use of + other cryptographic software libraries or adding support for hardware + acceleration. + +* Extended cryptographic API with support for HKDF, Concat KDF and PBKDF2. + +* SHA-1 and SHA-256 ARMv8-A crypto extension implementation. + +* Enabled paging support in OP-TEE OS. + +* Add support for xtest (both standard and extended) in QEMU and FVP setup + scripts. + +* Add documentation for the OS design, cryptographic abstraction layer, secure + elements design, the build system, GitHub usage, key derivation extensions, + ARM-Trusted Firmware usage within OP-TEE and GlobalPlatform usage within + OP-TEE. + +* Integrate support for Travis CI. + +* [Link][github_commits_0_1_0] to a list of all commits between this and + previous release. + + +## Tested on +Definitions: + +| Type | Meaning | +| ---- | ------- | +| Standard tests | The optee_test project. | +| Extended tests | optee_test with tests from the GlobalPlatformâ„¢ TEE Initial Configuration Test Suite v1.0.0. | +| Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | + +* Allwinner A80 (plat-sunxi), hello world test. + +* ARM Juno Board (vexpress-juno), standard tests. + +* Foundation Models (plat-vexpress-fvp), standard + extended tests + +* QEMU (plat-vexpress-qemu), standard + extended tests (and Secure Elements + tested separately). + +* STM Cannes (plat-stm-cannes), standard + extended tests. + + +## Issues resolved since last release +N/A since this is the first release tag on OP-TEE. + + +## Known issues +* Storage is implemented, but not "Secure storage", meaning that a client + needs to do encrypt files on their own before storing the files. + +* Issue(s) open on GitHub + * [#95][pr95]: An error about building the test code of libtomcrypt. + + * [#149][pr149]: when testing optee os with arm trusted firmware (I + utilized optee os tee.bin as bl32 image) on juno platform, I got an + error. + + * [#161][pr161]: tee_svc_cryp.c lacks accessibility checks on + user-supplied TEE_Attributes. + +[hello_world]: https://github.com/jenswi-linaro/lcu14_optee_hello_world +[github_commits_0_1_0]: https://github.com/OP-TEE/optee_os/compare/b01047730e77127c23a36591643eeb8bb0487d68...999e4a6c0f64d3177fd3d0db234107b6fb860884 +[pr95]: https://github.com/OP-TEE/optee_os/issues/95 +[pr149]: https://github.com/OP-TEE/optee_os/issues/149 +[pr161]: https://github.com/OP-TEE/optee_os/issues/161 + +* Global Platform Device Internal Core API v1.1 + * [#230][pr230]: Persistent object corruption support (TEE_ERROR_CORRUPT_OBJECT/_2) + * [#230][pr230]: Persistent object access support (TEE_ERROR_STORAGE_NOT_AVAILABLE/_2) diff --git a/optee/optee_os/LICENSE b/optee/optee_os/LICENSE new file mode 100644 index 0000000..689c2b3 --- /dev/null +++ b/optee/optee_os/LICENSE @@ -0,0 +1,45 @@ +Unless it has its own copyright/license embedded in its body, each file +is subject to the following license terms: + +Copyright (c) 2015, 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. + + +The following terms apply to this list of files: +1. core/drivers/tegra/t234/include/tegra_se_ccc.h +2. prebuilt/t234/libcommon_crypto.a + +These items are under the following terms: + +* NVIDIA License terms * +SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: LicenseRef-NvidiaProprietary + +NVIDIA CORPORATION, its affiliates and licensors retain all intellectual +property and proprietary rights in and to this material, related +documentation and any modifications thereto. Any use, reproduction, +disclosure or distribution of this material and related documentation +without an express license agreement from NVIDIA CORPORATION or +its affiliates is strictly prohibited. diff --git a/optee/optee_os/LICENSE.NVIDIA b/optee/optee_os/LICENSE.NVIDIA new file mode 100644 index 0000000..41d838f --- /dev/null +++ b/optee/optee_os/LICENSE.NVIDIA @@ -0,0 +1,141 @@ +The below listed files are provided under the following terms: + +core/drivers/tegra/t234/include/tegra_se_ccc.h +core/drivers/tegra/t234/include/tegra_se_ccc_errno.h +prebuilt/t234/libcommon_crypto.a + +Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + + License For Customer Use of NVIDIA Software + + +IMPORTANT NOTICE -- READ CAREFULLY: This License For Customer Use of +NVIDIA Software ("LICENSE") is the agreement which governs use of +the software of NVIDIA Corporation and its subsidiaries ("NVIDIA") +downloadable herefrom, including computer software and associated +printed materials ("SOFTWARE"). By downloading, installing, copying, +or otherwise using the SOFTWARE, you agree to be bound by the terms +of this LICENSE. If you do not agree to the terms of this LICENSE, +do not download the SOFTWARE. + +RECITALS + +Use of NVIDIA's products requires three elements: the SOFTWARE, the +hardware on a graphics controller board, and a personal computer. The +SOFTWARE is protected by copyright laws and international copyright +treaties, as well as other intellectual property laws and treaties. +The SOFTWARE is not sold, and instead is only licensed for use, +strictly in accordance with this document. The hardware is protected +by various patents, and is sold, but this agreement does not cover +that sale, since it may not necessarily be sold as a package with +the SOFTWARE. This agreement sets forth the terms and conditions +of the SOFTWARE LICENSE only. + +1. DEFINITIONS + +1.1 Customer. Customer means the entity or individual that +downloads the SOFTWARE. + +2. GRANT OF LICENSE + +2.1 Rights and Limitations of Grant. NVIDIA hereby grants Customer +the following non-exclusive, non-transferable right to use the +SOFTWARE, with the following limitations: + +2.1.1 Rights. Customer may install and use multiple copies of the +SOFTWARE on a shared computer or concurrently on different computers, +and make multiple back-up copies of the SOFTWARE, solely for Customer's +use within Customer's Enterprise. "Enterprise" shall mean individual use +by Customer or any legal entity (such as a corporation or university) +and the subsidiaries it owns by more than fifty percent (50%). + +2.1.2 Linux/FreeBSD Exception. Notwithstanding the foregoing terms +of Section 2.1.1, SOFTWARE designed exclusively for use on the Linux or +FreeBSD operating systems, or other operating systems derived from the +source code to these operating systems, may be copied and redistributed, +provided that the binary files thereof are not modified in any way +(except for unzipping of compressed files). + +2.1.3 Limitations. + +No Reverse Engineering. Customer may not reverse engineer, +decompile, or disassemble the SOFTWARE, nor attempt in any other +manner to obtain the source code. + +No Separation of Components. The SOFTWARE is licensed as a +single product. Its component parts may not be separated for use +on more than one computer, nor otherwise used separately from the +other parts. + +No Rental. Customer may not rent or lease the SOFTWARE to someone +else. + +3. TERMINATION + +This LICENSE will automatically terminate if Customer fails to +comply with any of the terms and conditions hereof. In such event, +Customer must destroy all copies of the SOFTWARE and all of its +component parts. + +Defensive Suspension. If Customer commences or participates in any legal +proceeding against NVIDIA, then NVIDIA may, in its sole discretion, +suspend or terminate all license grants and any other rights provided +under this LICENSE during the pendency of such legal proceedings. + +4. COPYRIGHT + +All title and copyrights in and to the SOFTWARE (including but +not limited to all images, photographs, animations, video, audio, +music, text, and other information incorporated into the SOFTWARE), +the accompanying printed materials, and any copies of the SOFTWARE, +are owned by NVIDIA, or its suppliers. The SOFTWARE is protected +by copyright laws and international treaty provisions. Accordingly, +Customer is required to treat the SOFTWARE like any other copyrighted +material, except as otherwise allowed pursuant to this LICENSE +and that it may make one copy of the SOFTWARE solely for backup or +archive purposes. + +5. APPLICABLE LAW + +This agreement shall be deemed to have been made in, and shall be +construed pursuant to, the laws of the State of California. + +6. DISCLAIMER OF WARRANTIES AND LIMITATION ON LIABILITY + +6.1 No Warranties. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE +LAW, THE SOFTWARE IS PROVIDED "AS IS" AND NVIDIA AND ITS SUPPLIERS +DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. + +6.2 No Liability for Consequential Damages. TO THE MAXIMUM +EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL NVIDIA OR +ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, +DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS +OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT +OF THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF NVIDIA HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +6.3 Specific Use. SOFTWARE is licensed only for use with NVIDIA products. +Customer's use of NVIDIA products with any other firmware is at its own +risk and may cause an NVIDIA product to become non-compliant with certain +of its certification markings. + +7. MISCELLANEOUS + +The United Nations Convention on Contracts for the International +Sale of Goods is specifically disclaimed. If any provision of this +LICENSE is inconsistent with, or cannot be fully enforced under, +the law, such provision will be construed as limited to the extent +necessary to be consistent with and fully enforceable under the law. +This agreement is the final, complete and exclusive agreement between +the parties relating to the subject matter hereof, and supersedes +all prior or contemporaneous understandings and agreements relating +to such subject matter, whether oral or written. Customer agrees +that it will not ship, transfer or export the SOFTWARE into any +country, or use the SOFTWARE in any manner, prohibited by the +United States Bureau of Export Administration or any export laws, +restrictions or regulations. This LICENSE may only be modified in +writing signed by an authorized officer of NVIDIA. + diff --git a/optee/optee_os/MAINTAINERS b/optee/optee_os/MAINTAINERS new file mode 100644 index 0000000..a941d11 --- /dev/null +++ b/optee/optee_os/MAINTAINERS @@ -0,0 +1,310 @@ + Maintainers in the OP-TEE project + +Linaro as such maintains OP-TEE, but for individual devices which might not be +available to Linaro and/or in public in general we have assigned +sub-maintainers for these platforms. + +Please keep this list in alphabetical order, and refer to the Linux kernel's +MAINTAINER file for the description of section entries [1]. + +Note that OP-TEE development mainly occurs on GitHub [2] so this file should be +used a bit differently compared to the Linux MAINTAINERS file: + +1. GitHub accounts may be given in square brackets, starting with an @ sign. +For example, [@jbech-linaro]. + +2. Patches should generally be submitted as GitHub pull requests (more details +in documentation/github.md). Therefore, please do NOT send patches to the +e-mail addresses below. Maintainers normally are subscribed to GitHub +notifications, so they should see your pull requests. If you need to 'ping' +some maintainer, just mention his/her GitHub account in a comment in the pull +request. + +2. Bug reports and questions should be posted to the GitHub project as well +(use the "Issues" tab). + +3. The last entry ("THE REST") lists the overall maintainers (M:) and the +members of the Linaro Security Working Group who provide reviews on a regular +basis (R:). + +[1] https://www.kernel.org/doc/linux/MAINTAINERS +[2] https://github.com/OP-TEE/optee_os + +---------- + +ARM Foundation FVP +R: Jens Wiklander [@jenswi-linaro] +S: Maintained +F: core/arch/arm/plat-vexpress/ + +ARM Juno +R: Jens Wiklander [@jenswi-linaro] +S: Maintained +F: core/arch/arm/plat-vexpress/ + +ARM Corstone1000 +R: Vishnu Banavath [@vishnu-banavath] +S: Maintained +F: core/arch/arm/plat-corstone1000/ + +AllWinner sun8i H2+ +R: Ying-Chun Liu (PaulLiu) [@grandpaul] +S: Maintained +F: core/arch/arm/plat-sunxi/ + +AllWinner sun50i A64 +R: Amit Singh Tomar [@Amit-Radur] +S: Maintained +F: core/arch/arm/plat-sunxi/ + +AmLogic AXG (A113D) +R: Carlo Caione [@carlocaione] +S: Maintained +F: core/arch/arm/plat-amlogic/ + +Atmel ATSAMA5D2-XULT +R: Akshay Bhat [@nodeax] +S: Maintained +F: core/arch/arm/plat-sam/ + +Broadcom ns3 +L: Broadcom +S: Orphan +F: core/arch/arm/plat-bcm/ + +Core Drivers I2C +R: Jorge Ramirez [@ldts] +S: Maintained +F: core/drivers/imx_i2c.c + +Core Drivers RNGB +R: Jorge Ramirez [@ldts] +S: Maintained +F: core/drivers/imx_rngb.c + +Core Drivers SE050 +R: Jorge Ramirez [@ldts] +S: Maintained +F: core/drivers/crypto/se050 + +Core Drivers Versal ACAP +R: Jorge Ramirez [@ldts] +S: Maintained +F: core/drivers/crypto/versal/authenc.c +F: core/drivers/crypto/versal/ecc.c +F: core/drivers/crypto/versal/ipi.c +F: core/drivers/crypto/versal/rsa.c +F: core/drivers/versal_gpio.c +F: core/drivers/versal_huk.c +F: core/drivers/versal_mbox.c +F: core/drivers/versal_nvm.c +F: core/drivers/versal_pm.c +F: core/drivers/versal_puf.c +F: core/drivers/versal_sha3_384.c +F: core/drivers/versal_trng.c + +Core Drivers ZYNQMP +R: Jorge Ramirez [@ldts] +S: Maintained +F: core/drivers/zynqmp_csu_aes.c +F: core/drivers/zynqmp_csu_puf.c +F: core/drivers/zynqmp_csudma.c +F: core/drivers/zynqmp_huk.c +F: core/drivers/zynqmp_pm.c + +Function Graph Tracer (ftrace) support +R: Sumit Garg [@b49020] +S: Maintained +F: ldelf/ftrace.c +F: lib/libutils/ext/ftrace/ + +HiSilicon D02 +S: Orphan +F: core/arch/arm/plat-d02/ + +HiSilicon D06 +R: Xiaoxu Zeng [@xiaoxuZeng] +S: Maintained +F: core/arch/arm/plat-d06/ + +HiSilicon HiKey (Kirin 620), HiKey960 (Kirin 960) +R: Jerome Forissier [@jforissier] +S: Maintained +F: core/arch/arm/plat-hikey/ + +HiSilicon Poplar (Hi3798C V200) +R: Igor Opaniuk [@igoropaniuk] +S: Maintained +F: core/arch/arm/plat-poplar/ + +Hisilicon Hi3519AV100 family +R: Jerome Forissier [@jforissier] +S: Maintained +F: core/arch/arm/plat-hisilicon + +Marvell Armada 70x0, Armada 80x0, Armada 3700, OcteonTX2 CN96XX, OcteonTX2 CFN95XX, OcteonTX2 CN98XX +R: Tao Lu [@taovcu] +S: Maintained +F: core/arch/arm/plat-marvell/ + +MediaTek MT8173 EVB +S: Orphan +F: core/arch/arm/plat-mediatek/ + +NXP LS1021A, LS1043A-RDB, LS1046A-RDB, LS1012A-RDB, LS1012A-FRWY, LS1028A-RDB, LS1088A-RDB, LS2088A-RDB, LX2160A-RDB, LX2160A-QDS +R: Pankaj Gupta [@pangupta] +R: Sahil Malhotra [@sahilnxp] +S: Maintained +F: core/arch/arm/plat-ls/ + +Core Drivers I2C +R: Sahil Malhotra [@sahilnxp] +S: Maintained +F: core/drivers/ls_i2c.c + +LS Core Drivers GPIO +R: Sahil Malhotra [@sahilnxp] +S: Maintained +F: core/drivers/ls_gpio.c + +LS Core Drivers DSPI +R: Sahil Malhotra [@sahilnxp] +S: Maintained +F: core/drivers/ls_dspi.c + +NXP (Freescale) i.MX family +R: Peng Fan [@MrVan] +R: Cedric Neveux [@cneveux] +R: Silvano Di Ninno [@sdininno] +R: Clement Faure [@clementfaure] +S: Maintained +F: core/arch/arm/plat-imx/ +F: core/arch/arm/plat-imx/registers +F: core/drivers/crypto/caam/ + +Clock driver framework +R: Clement Leger [@clementleger] +S: Maintained +F: core/drivers/clk/ + +Crypto driver interface +R: Cedric Neveux [@cneveux] +R: Silvano Di Ninno [@sdininno] +R: Clement Faure [@clementfaure] +S: Maintained +F: core/drivers/crypto/ + +NXP (Freescale) i.MX7 WaRP7 +R: Peng Fan [@MrVan] +R: Bryan O'Donoghue [@bryanodonoghue] +S: Maintained +F: core/arch/arm/plat-imx/conf.mk + +PKCS#11 TA +R: Etienne Carriere [@etienne-lms] +R: Ruchika Gupta [@ruchi393] +R: Vesa Jääskeläinen [@vesajaaskelainen] +S: Maintained +F: ta/pkcs11 + +QEMU (32 and 64 bits) +R: Jens Wiklander [@jenswi-linaro] +S: Maintained +F: core/arch/arm/plat-vexpress/ + +Raspberry Pi3 +R: Joakim Bech [@jbech-linaro] +S: Maintained +F: core/arch/arm/plat-rpi3/ + +Renesas RCAR +R: Volodymyr Babchuk [@lorc] +S: Maintained +F: core/arch/arm/plat-rcar/ + +Renesas RZ/G2 +R: Lad Prabhakar [@prabhakarlad] +R: Biju Das [@bijucdas] +S: Maintained +F: core/arch/arm/plat-rzg/ + +Renesas RZ/N1 +R: Sumit Garg [@b49020] +S: Maintained +F: core/arch/arm/plat-rzn1/ + +Rockchip RK322X +R: Rockchip +S: Maintained +F: core/arch/arm/plat-rockchip/ + +Socionext DeveloperBox (Synquacer SC2A11) +R: Sumit Garg [@b49020] +S: Maintained +F: core/arch/arm/plat-synquacer/ + +Socionext UniPhier +R: Kunihiko Hayashi +R: [@96boards-akebi96/optee] +S: Maintained +F: core/arch/arm/plat-uniphier/ + +Spreadtrum SC9860 +S: Orphan +F: core/arch/arm/plat-sprd/ + +STMicroelectronics b2260-h410, b2120-h310/h410 +R: Etienne Carriere [@etienne-lms] +S: Maintained +F: core/arch/arm/plat-stm/ + +STMicroelectronics stm32mp1 +R: Etienne Carriere [@etienne-lms] +S: Maintained +F: core/arch/arm/plat-stm32mp1/ +F: core/drivers/stm32_* +F: core/drivers/stm32mp15_huk.c +F: core/drivers/stpmic1.c + +Texas Instruments AM43xx, AM57xx, DRA7xx, AM65x, J721E, J784S4, AM64x, AM62x +R: Andrew Davis [@glneo] +S: Maintained +F: core/arch/arm/plat-ti/ +F: core/arch/arm/plat-k3/ + +Xilinx Zynq 7000 ZC702 Board +R: Yan Yan +R: Feng Yu +S: Maintained +F: core/arch/arm/plat-zynq7k/ + +Xilinx Zynq UltraScale+ MPSOC +R: Ricardo Salveti [@ricardosalveti] +S: Maintained +F: core/arch/arm/plat-zynqmp/ + +Xilinx Versal ACAP +R: Jorge Ramirez-Ortiz [@ldts] +S: Maintained +F: core/arch/arm/plat-versal/ + +Virtualization support +R: Volodymyr Babchuk [@lorc] +S: Maintained +F: core/arch/arm/kernel/virtualization.c + +Aspeed AST2600 +R: Chia-Wei Wang [@ChiaweiW] +R: Neal Liu [@Neal-liu] +S: Maintained +F: core/arch/arm/plat-aspeed/ + +THE REST +M: Joakim Bech [@jbech-linaro] +M: Jens Wiklander [@jenswi-linaro] +M: Jerome Forissier [@jforissier] +R: Etienne Carriere [@etienne-lms] +L: op-tee@lists.trustedfirmware.org +S: Maintained +F: * +F: */ diff --git a/optee/optee_os/Makefile b/optee/optee_os/Makefile new file mode 100644 index 0000000..25d7689 --- /dev/null +++ b/optee/optee_os/Makefile @@ -0,0 +1,127 @@ +SHELL = bash + +# It can happen that a makefile calls us, which contains an 'export' directive +# or the '.EXPORT_ALL_VARIABLES:' special target. In this case, all the make +# variables are added to the environment for each line of the recipes, so that +# any sub-makefile can use them. +# We have observed this can cause issues such as 'Argument list too long' +# errors as the shell runs out of memory. +# Since this Makefile won't call any sub-makefiles, and since the commands do +# not expect to implicitely obtain any make variable from the environment, we +# can safely cancel this export mechanism. Unfortunately, it can't be done +# globally, only by name. Let's unexport MAKEFILE_LIST which is by far the +# biggest one due to our way of tracking dependencies and compile flags +# (we include many *.cmd and *.d files). +unexport MAKEFILE_LIST + +# Automatically delete corrupt targets (file updated but recipe exits with a +# nonzero status). Useful since a few recipes use shell redirection. +.DELETE_ON_ERROR: + +include mk/checkconf.mk + +.PHONY: all +all: + +.PHONY: mem_usage +mem_usage: + +# log and load eventual tee config file +# path is absolute or relative to current source root directory. +ifdef CFG_OPTEE_CONFIG +$(info Loading OPTEE configuration file $(CFG_OPTEE_CONFIG)) +include $(CFG_OPTEE_CONFIG) +endif + +# If $(PLATFORM) is defined and contains a hyphen, parse it as +# $(PLATFORM)-$(PLATFORM_FLAVOR) for convenience +ifneq (,$(findstring -,$(PLATFORM))) +ops := $(join PLATFORM PLATFORM_FLAVOR,$(addprefix =,$(subst -, ,$(PLATFORM)))) +$(foreach op,$(ops),$(eval override $(op))) +endif + +# Make these default for now +ARCH ?= arm +PLATFORM ?= vexpress +# Default value for PLATFORM_FLAVOR is set in plat-$(PLATFORM)/conf.mk +ifeq ($O,) +O := out +out-dir := $(O)/$(ARCH)-plat-$(PLATFORM) +else +out-dir := $(O) +endif + +arch_$(ARCH) := y + +ifneq ($V,1) +q := @ +cmd-echo := true +cmd-echo-silent := echo +else +q := +cmd-echo := echo +cmd-echo-silent := true +endif + +ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4 +ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),) +cmd-echo-silent := true +endif +else # make-3.8x +ifneq ($(findstring s, $(MAKEFLAGS)),) +cmd-echo-silent := true +endif +endif + +SCRIPTS_DIR := scripts + +include core/core.mk + +# Platform/arch config is supposed to assign the targets +ta-targets ?= invalid +default-user-ta-target ?= $(firstword $(ta-targets)) + +ifeq ($(CFG_WITH_USER_TA),y) +include ldelf/ldelf.mk +define build-ta-target +ta-target := $(1) +include ta/ta.mk +endef +$(foreach t, $(ta-targets), $(eval $(call build-ta-target, $(t)))) + +# Build user TAs included in this git +ifeq ($(CFG_BUILD_IN_TREE_TA),y) +define build-user-ta +ta-mk-file := $(1) +include ta/mk/build-user-ta.mk +endef +$(foreach t, $(sort $(wildcard ta/*/user_ta.mk)), $(eval $(call build-user-ta,$(t)))) +endif +endif + +include mk/cleandirs.mk + +.PHONY: clean +clean: + @$(cmd-echo-silent) ' CLEAN $(out-dir)' + $(call do-rm-f, $(cleanfiles)) + ${q}dirs="$(call cleandirs-for-rmdir)"; if [ "$$dirs" ]; then $(RMDIR) $$dirs; fi + @if [ "$(out-dir)" != "$(O)" ]; then $(cmd-echo-silent) ' CLEAN $(O)'; fi + ${q}if [ -d "$(O)" ]; then $(RMDIR) $(O); fi + +.PHONY: cscope +cscope: + @echo ' CSCOPE .' + ${q}rm -f cscope.* + ${q}find $(PWD) -name "*.[chSs]" | grep -v export-ta_ | \ + grep -v -F _init.ld.S | grep -v -F _unpaged.ld.S > cscope.files + ${q}cscope -b -q -k + +.PHONY: checkpatch checkpatch-staging checkpatch-working +checkpatch: checkpatch-staging checkpatch-working + +checkpatch-working: + ${q}./scripts/checkpatch.sh + +checkpatch-staging: + ${q}./scripts/checkpatch.sh --cached diff --git a/optee/optee_os/README.md b/optee/optee_os/README.md new file mode 100644 index 0000000..328078e --- /dev/null +++ b/optee/optee_os/README.md @@ -0,0 +1,7 @@ +# OP-TEE Trusted OS +This git contains source code for the secure side implementation of OP-TEE +project. + +All official OP-TEE documentation has moved to http://optee.readthedocs.io. + +// OP-TEE core maintainers diff --git a/optee/optee_os/core/arch/arm/arm.mk b/optee/optee_os/core/arch/arm/arm.mk new file mode 100644 index 0000000..19f558e --- /dev/null +++ b/optee/optee_os/core/arch/arm/arm.mk @@ -0,0 +1,445 @@ +# Setup compiler for the core module +ifeq ($(CFG_ARM64_core),y) +arch-bits-core := 64 +else +arch-bits-core := 32 +endif +CROSS_COMPILE_core := $(CROSS_COMPILE$(arch-bits-core)) +COMPILER_core := $(COMPILER) +include mk/$(COMPILER_core).mk + +# Defines the cc-option macro using the compiler set for the core module +include mk/cc-option.mk + +# Size of emulated TrustZone protected SRAM, 448 kB. +# Only applicable when paging is enabled. +CFG_CORE_TZSRAM_EMUL_SIZE ?= 458752 + +ifneq ($(CFG_LPAE_ADDR_SPACE_SIZE),) +$(warning Error: CFG_LPAE_ADDR_SPACE_SIZE is not supported any longer) +$(error Error: Please use CFG_LPAE_ADDR_SPACE_BITS instead) +endif + +CFG_LPAE_ADDR_SPACE_BITS ?= 32 + +CFG_MMAP_REGIONS ?= 13 +CFG_RESERVED_VASPACE_SIZE ?= (1024 * 1024 * 10) + +ifeq ($(CFG_ARM64_core),y) +ifeq ($(CFG_ARM32_core),y) +$(error CFG_ARM64_core and CFG_ARM32_core cannot be both 'y') +endif +CFG_KERN_LINKER_FORMAT ?= elf64-littleaarch64 +CFG_KERN_LINKER_ARCH ?= aarch64 +# TCR_EL1.IPS needs to be initialized according to the largest physical +# address that we need to map. +# Physical address size +# 32 bits, 4GB. +# 36 bits, 64GB. +# (etc.) +CFG_CORE_ARM64_PA_BITS ?= 32 +$(call force,CFG_WITH_LPAE,y) +else +$(call force,CFG_ARM32_core,y) +CFG_KERN_LINKER_FORMAT ?= elf32-littlearm +CFG_KERN_LINKER_ARCH ?= arm +endif + +ifeq ($(CFG_TA_FLOAT_SUPPORT),y) +# Use hard-float for floating point support in user TAs instead of +# soft-float +CFG_WITH_VFP ?= y +ifeq ($(CFG_ARM64_core),y) +# AArch64 has no fallback to soft-float +$(call force,CFG_WITH_VFP,y) +endif +ifeq ($(CFG_WITH_VFP),y) +arm64-platform-hard-float-enabled := y +ifneq ($(CFG_TA_ARM32_NO_HARD_FLOAT_SUPPORT),y) +arm32-platform-hard-float-enabled := y +endif +endif +endif + +# Adds protection against CVE-2017-5715 also know as Spectre +# (https://spectreattack.com) +# See also https://developer.arm.com/-/media/Files/pdf/Cache_Speculation_Side-channels.pdf +# Variant 2 +CFG_CORE_WORKAROUND_SPECTRE_BP ?= y +# Same as CFG_CORE_WORKAROUND_SPECTRE_BP but targeting exceptions from +# secure EL0 instead of non-secure world, including mitigation for +# CVE-2022-23960. +CFG_CORE_WORKAROUND_SPECTRE_BP_SEC ?= $(CFG_CORE_WORKAROUND_SPECTRE_BP) + +# Adds protection against a tool like Cachegrab +# (https://github.com/nccgroup/cachegrab), which uses non-secure interrupts +# to prime and later analyze the L1D, L1I and BTB caches to gain +# information from secure world execution. +CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME ?= y +ifeq ($(CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME),y) +$(call force,CFG_CORE_WORKAROUND_SPECTRE_BP,y,Required by CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME) +endif + +# Adds workarounds against if ARM core is configured with Non-maskable FIQ +# (NMFI) support. This is indicated by SCTLR.NMFI being true. NMFI cannot be +# disabled by software and as it affects atomic context end result will be +# prohibiting FIQ signal usage in OP-TEE and applying some tweaks to make sure +# FIQ is enabled in critical places. +CFG_CORE_WORKAROUND_ARM_NMFI ?= n + +CFG_CORE_RWDATA_NOEXEC ?= y +CFG_CORE_RODATA_NOEXEC ?= n +ifeq ($(CFG_CORE_RODATA_NOEXEC),y) +$(call force,CFG_CORE_RWDATA_NOEXEC,y) +endif +# 'y' to set the Alignment Check Enable bit in SCTLR/SCTLR_EL1, 'n' to clear it +CFG_SCTLR_ALIGNMENT_CHECK ?= n + +ifeq ($(CFG_CORE_LARGE_PHYS_ADDR),y) +$(call force,CFG_WITH_LPAE,y) +endif + +# SPMC configuration "S-EL1 SPMC" where SPM Core is implemented at S-EL1, +# that is, OP-TEE. +ifeq ($(CFG_CORE_SEL1_SPMC),y) +$(call force,CFG_CORE_FFA,y) +$(call force,CFG_CORE_SEL2_SPMC,n) +$(call force,CFG_CORE_EL3_SPMC,n) +endif +# SPMC configuration "S-EL2 SPMC" where SPM Core is implemented at S-EL2, +# that is, the hypervisor sandboxing OP-TEE +ifeq ($(CFG_CORE_SEL2_SPMC),y) +$(call force,CFG_CORE_FFA,y) +$(call force,CFG_CORE_SEL1_SPMC,n) +$(call force,CFG_CORE_EL3_SPMC,n) +CFG_CORE_HAFNIUM_INTC ?= y +# Enable support in OP-TEE to relocate itself to allow it to run from a +# physical address that differs from the link address +CFG_CORE_PHYS_RELOCATABLE ?= y +endif +# SPMC configuration "EL3 SPMC" where SPM Core is implemented at EL3, that +# is, in TF-A +ifeq ($(CFG_CORE_EL3_SPMC),y) +$(call force,CFG_CORE_FFA,y) +$(call force,CFG_CORE_SEL2_SPMC,n) +$(call force,CFG_CORE_SEL1_SPMC,n) +endif + +ifeq ($(CFG_CORE_PHYS_RELOCATABLE)-$(CFG_WITH_PAGER),y-y) +$(error CFG_CORE_PHYS_RELOCATABLE and CFG_WITH_PAGER are not compatible) +endif + +ifeq ($(CFG_CORE_FFA)-$(CFG_WITH_PAGER),y-y) +$(error CFG_CORE_FFA and CFG_WITH_PAGER are not compatible) +endif +ifeq ($(CFG_GIC),y) +ifeq ($(CFG_ARM_GICV3),y) +$(call force,CFG_CORE_IRQ_IS_NATIVE_INTR,y) +else +$(call force,CFG_CORE_IRQ_IS_NATIVE_INTR,n) +endif +endif + +CFG_CORE_HAFNIUM_INTC ?= n +ifeq ($(CFG_CORE_HAFNIUM_INTC),y) +$(call force,CFG_CORE_IRQ_IS_NATIVE_INTR,y) +endif + +# Selects if IRQ is used to signal native interrupt +# if CFG_CORE_IRQ_IS_NATIVE_INTR == y: +# IRQ signals a native interrupt pending +# FIQ signals a foreign non-secure interrupt or a managed exit pending +# else: (vice versa) +# IRQ signals a foreign non-secure interrupt or a managed exit pending +# FIQ signals a native interrupt pending +CFG_CORE_IRQ_IS_NATIVE_INTR ?= n + +# Unmaps all kernel mode code except the code needed to take exceptions +# from user space and restore kernel mode mapping again. This gives more +# strict control over what is accessible while in user mode. +# Addresses CVE-2017-5715 (aka Meltdown) known to affect Arm Cortex-A75 +CFG_CORE_UNMAP_CORE_AT_EL0 ?= y + +# Initialize PMCR.DP to 1 to prohibit cycle counting in secure state, and +# save/restore PMCR during world switch. +CFG_SM_NO_CYCLE_COUNTING ?= y + + +# CFG_CORE_ASYNC_NOTIF_GIC_INTID is defined by the platform to some free +# interrupt. Setting it to a non-zero number enables support for using an +# Arm-GIC to notify normal world. This config variable should use a value +# larger the 32 to make it of the type SPI. +# Note that asynchronous notifactions must be enabled with +# CFG_CORE_ASYNC_NOTIF=y for this variable to be used. +CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 0 + +ifeq ($(CFG_ARM32_core),y) +# Configration directive related to ARMv7 optee boot arguments. +# CFG_PAGEABLE_ADDR: if defined, forces pageable data physical address. +# CFG_NS_ENTRY_ADDR: if defined, forces NS World physical entry address. +# CFG_DT_ADDR: if defined, forces Device Tree data physical address. +endif + +# CFG_MAX_CACHE_LINE_SHIFT is used to define platform specific maximum cache +# line size in address lines. This must cover all inner and outer cache levels. +# When data is aligned with this and cache operations are performed then those +# only affect correct data. +# +# Default value (6 lines or 64 bytes) should cover most architectures, override +# this in platform config if different. +CFG_MAX_CACHE_LINE_SHIFT ?= 6 + +core-platform-cppflags += -I$(arch-dir)/include +core-platform-subdirs += \ + $(addprefix $(arch-dir)/, kernel crypto mm tee) $(platform-dir) + +ifneq ($(CFG_WITH_ARM_TRUSTED_FW),y) +core-platform-subdirs += $(arch-dir)/sm +endif + +arm64-platform-cppflags += -DARM64=1 -D__LP64__=1 +arm32-platform-cppflags += -DARM32=1 -D__ILP32__=1 + +platform-cflags-generic ?= -ffunction-sections -fdata-sections -pipe +platform-aflags-generic ?= -pipe + +arm32-platform-aflags += -marm + +arm32-platform-cflags-no-hard-float ?= -mfloat-abi=soft +arm32-platform-cflags-hard-float ?= -mfloat-abi=hard -funsafe-math-optimizations +arm32-platform-cflags-generic-thumb ?= -mthumb \ + -fno-short-enums -fno-common -mno-unaligned-access +arm32-platform-cflags-generic-arm ?= -marm -fno-omit-frame-pointer -mapcs \ + -fno-short-enums -fno-common -mno-unaligned-access +arm32-platform-aflags-no-hard-float ?= + +arm64-platform-cflags-no-hard-float ?= -mgeneral-regs-only +arm64-platform-cflags-hard-float ?= +arm64-platform-cflags-generic := -mstrict-align $(call cc-option,-mno-outline-atomics,) + +ifeq ($(CFG_MEMTAG),y) +arm64-platform-cflags += -march=armv8.5-a+memtag +arm64-platform-aflags += -march=armv8.5-a+memtag +endif + +platform-cflags-optimization ?= -O$(CFG_CC_OPT_LEVEL) + +ifeq ($(CFG_DEBUG_INFO),y) +platform-cflags-debug-info ?= -g3 +platform-aflags-debug-info ?= -g +endif + +core-platform-cflags += $(platform-cflags-optimization) +core-platform-cflags += $(platform-cflags-generic) +core-platform-cflags += $(platform-cflags-debug-info) + +core-platform-aflags += $(platform-aflags-generic) +core-platform-aflags += $(platform-aflags-debug-info) + +ifeq ($(call cfg-one-enabled, CFG_CORE_ASLR CFG_CORE_PHYS_RELOCATABLE),y) +core-platform-cflags += -fpie +endif + +ifeq ($(CFG_CORE_PAUTH),y) +bp-core-opt := $(call cc-option,-mbranch-protection=pac-ret+leaf) +endif + +ifeq ($(CFG_CORE_BTI),y) +bp-core-opt := $(call cc-option,-mbranch-protection=bti) +endif + +ifeq (y-y,$(CFG_CORE_PAUTH)-$(CFG_CORE_BTI)) +bp-core-opt := $(call cc-option,-mbranch-protection=pac-ret+leaf+bti) +endif + +ifeq (y,$(filter $(CFG_CORE_BTI) $(CFG_CORE_PAUTH),y)) +ifeq (,$(bp-core-opt)) +$(error -mbranch-protection not supported) +endif +core-platform-cflags += $(bp-core-opt) +endif + +ifeq ($(CFG_ARM64_core),y) +core-platform-cppflags += $(arm64-platform-cppflags) +core-platform-cflags += $(arm64-platform-cflags) +core-platform-cflags += $(arm64-platform-cflags-generic) +core-platform-cflags += $(arm64-platform-cflags-no-hard-float) +core-platform-aflags += $(arm64-platform-aflags) +else +core-platform-cppflags += $(arm32-platform-cppflags) +core-platform-cflags += $(arm32-platform-cflags) +core-platform-cflags += $(arm32-platform-cflags-no-hard-float) +ifeq ($(CFG_UNWIND),y) +core-platform-cflags += -funwind-tables +endif +ifeq ($(CFG_SYSCALL_FTRACE),y) +core-platform-cflags += $(arm32-platform-cflags-generic-arm) +else +core-platform-cflags += $(arm32-platform-cflags-generic-thumb) +endif +core-platform-aflags += $(core_arm32-platform-aflags) +core-platform-aflags += $(arm32-platform-aflags) +endif + +# Provide default supported-ta-targets if not set by the platform config +ifeq (,$(supported-ta-targets)) +supported-ta-targets = ta_arm32 +ifeq ($(CFG_ARM64_core),y) +supported-ta-targets += ta_arm64 +endif +endif + +ta-targets := $(if $(CFG_USER_TA_TARGETS),$(filter $(supported-ta-targets),$(CFG_USER_TA_TARGETS)),$(supported-ta-targets)) +unsup-targets := $(filter-out $(ta-targets),$(CFG_USER_TA_TARGETS)) +ifneq (,$(unsup-targets)) +$(error CFG_USER_TA_TARGETS contains unsupported value(s): $(unsup-targets). Valid values: $(supported-ta-targets)) +endif + +ifneq ($(filter ta_arm32,$(ta-targets)),) +# Variables for ta-target/sm "ta_arm32" +CFG_ARM32_ta_arm32 := y +arch-bits-ta_arm32 := 32 +ta_arm32-platform-cppflags += $(arm32-platform-cppflags) +ta_arm32-platform-cflags += $(arm32-platform-cflags) +ta_arm32-platform-cflags += $(platform-cflags-optimization) +ta_arm32-platform-cflags += $(platform-cflags-debug-info) +ta_arm32-platform-cflags += -fpic + +# Thumb mode doesn't support function graph tracing due to missing +# frame pointer support required to trace function call chain. So +# rather compile in ARM mode if function tracing is enabled. +ifeq ($(CFG_FTRACE_SUPPORT),y) +ta_arm32-platform-cflags += $(arm32-platform-cflags-generic-arm) +else +ta_arm32-platform-cflags += $(arm32-platform-cflags-generic-thumb) +endif + +ifeq ($(arm32-platform-hard-float-enabled),y) +ta_arm32-platform-cflags += $(arm32-platform-cflags-hard-float) +else +ta_arm32-platform-cflags += $(arm32-platform-cflags-no-hard-float) +endif +ifeq ($(CFG_UNWIND),y) +ta_arm32-platform-cflags += -funwind-tables +endif +ta_arm32-platform-aflags += $(platform-aflags-generic) +ta_arm32-platform-aflags += $(platform-aflags-debug-info) +ta_arm32-platform-aflags += $(arm32-platform-aflags) + +ta_arm32-platform-cxxflags += -fpic +ta_arm32-platform-cxxflags += $(arm32-platform-cxxflags) +ta_arm32-platform-cxxflags += $(platform-cflags-optimization) +ta_arm32-platform-cxxflags += $(platform-cflags-debug-info) + +ifeq ($(arm32-platform-hard-float-enabled),y) +ta_arm32-platform-cxxflags += $(arm32-platform-cflags-hard-float) +else +ta_arm32-platform-cxxflags += $(arm32-platform-cflags-no-hard-float) +endif + +ta-mk-file-export-vars-ta_arm32 += CFG_ARM32_ta_arm32 +ta-mk-file-export-vars-ta_arm32 += ta_arm32-platform-cppflags +ta-mk-file-export-vars-ta_arm32 += ta_arm32-platform-cflags +ta-mk-file-export-vars-ta_arm32 += ta_arm32-platform-aflags +ta-mk-file-export-vars-ta_arm32 += ta_arm32-platform-cxxflags + +ta-mk-file-export-add-ta_arm32 += CROSS_COMPILE ?= arm-linux-gnueabihf-_nl_ +ta-mk-file-export-add-ta_arm32 += CROSS_COMPILE32 ?= $$(CROSS_COMPILE)_nl_ +ta-mk-file-export-add-ta_arm32 += CROSS_COMPILE_ta_arm32 ?= $$(CROSS_COMPILE32)_nl_ +ta-mk-file-export-add-ta_arm32 += COMPILER ?= gcc_nl_ +ta-mk-file-export-add-ta_arm32 += COMPILER_ta_arm32 ?= $$(COMPILER)_nl_ +ta-mk-file-export-add-ta_arm32 += PYTHON3 ?= python3_nl_ +endif + +ifneq ($(filter ta_arm64,$(ta-targets)),) +# Variables for ta-target/sm "ta_arm64" +CFG_ARM64_ta_arm64 := y +arch-bits-ta_arm64 := 64 +ta_arm64-platform-cppflags += $(arm64-platform-cppflags) +ta_arm64-platform-cflags += $(arm64-platform-cflags) +ta_arm64-platform-cflags += $(platform-cflags-optimization) +ta_arm64-platform-cflags += $(platform-cflags-debug-info) +ta_arm64-platform-cflags += -fpic +ta_arm64-platform-cflags += $(arm64-platform-cflags-generic) +ifeq ($(arm64-platform-hard-float-enabled),y) +ta_arm64-platform-cflags += $(arm64-platform-cflags-hard-float) +else +ta_arm64-platform-cflags += $(arm64-platform-cflags-no-hard-float) +endif +ta_arm64-platform-aflags += $(platform-aflags-generic) +ta_arm64-platform-aflags += $(platform-aflags-debug-info) +ta_arm64-platform-aflags += $(arm64-platform-aflags) + +ta_arm64-platform-cxxflags += -fpic +ta_arm64-platform-cxxflags += $(platform-cflags-optimization) +ta_arm64-platform-cxxflags += $(platform-cflags-debug-info) + +ifeq ($(CFG_TA_PAUTH),y) +bp-ta-opt := $(call cc-option,-mbranch-protection=pac-ret+leaf) +endif + +ifeq ($(CFG_TA_BTI),y) +bp-ta-opt := $(call cc-option,-mbranch-protection=bti) +endif + +ifeq (y-y,$(CFG_TA_PAUTH)-$(CFG_TA_BTI)) +bp-ta-opt := $(call cc-option,-mbranch-protection=pac-ret+leaf+bti) +endif + +ifeq (y,$(filter $(CFG_TA_BTI) $(CFG_TA_PAUTH),y)) +ifeq (,$(bp-ta-opt)) +$(error -mbranch-protection not supported) +endif +ta_arm64-platform-cflags += $(bp-ta-opt) +endif + +ta-mk-file-export-vars-ta_arm64 += CFG_ARM64_ta_arm64 +ta-mk-file-export-vars-ta_arm64 += ta_arm64-platform-cppflags +ta-mk-file-export-vars-ta_arm64 += ta_arm64-platform-cflags +ta-mk-file-export-vars-ta_arm64 += ta_arm64-platform-aflags +ta-mk-file-export-vars-ta_arm64 += ta_arm64-platform-cxxflags + +ta-mk-file-export-add-ta_arm64 += CROSS_COMPILE64 ?= $$(CROSS_COMPILE)_nl_ +ta-mk-file-export-add-ta_arm64 += CROSS_COMPILE_ta_arm64 ?= $$(CROSS_COMPILE64)_nl_ +ta-mk-file-export-add-ta_arm64 += COMPILER ?= gcc_nl_ +ta-mk-file-export-add-ta_arm64 += COMPILER_ta_arm64 ?= $$(COMPILER)_nl_ +ta-mk-file-export-add-ta_arm64 += PYTHON3 ?= python3_nl_ +endif + +# Set cross compiler prefix for each TA target +$(foreach sm, $(ta-targets), $(eval CROSS_COMPILE_$(sm) ?= $(CROSS_COMPILE$(arch-bits-$(sm))))) + +arm32-sysreg-txt = core/arch/arm/kernel/arm32_sysreg.txt +arm32-sysregs-$(arm32-sysreg-txt)-h := arm32_sysreg.h +arm32-sysregs-$(arm32-sysreg-txt)-s := arm32_sysreg.S +arm32-sysregs += $(arm32-sysreg-txt) + +ifeq ($(CFG_ARM_GICV3),y) +arm32-gicv3-sysreg-txt = core/arch/arm/kernel/arm32_gicv3_sysreg.txt +arm32-sysregs-$(arm32-gicv3-sysreg-txt)-h := arm32_gicv3_sysreg.h +arm32-sysregs-$(arm32-gicv3-sysreg-txt)-s := arm32_gicv3_sysreg.S +arm32-sysregs += $(arm32-gicv3-sysreg-txt) +endif + +arm32-sysregs-out := $(out-dir)/$(sm)/include/generated + +define process-arm32-sysreg +FORCE-GENSRC$(sm): $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-h) +cleanfiles := $$(cleanfiles) $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-h) + +$$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-h): $(1) scripts/arm32_sysreg.py + @$(cmd-echo-silent) ' GEN $$@' + $(q)mkdir -p $$(dir $$@) + $(q)scripts/arm32_sysreg.py --guard __$$(arm32-sysregs-$(1)-h) \ + < $$< > $$@ + +FORCE-GENSRC$(sm): $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-s) +cleanfiles := $$(cleanfiles) $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-s) + +$$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-s): $(1) scripts/arm32_sysreg.py + @$(cmd-echo-silent) ' GEN $$@' + $(q)mkdir -p $$(dir $$@) + $(q)scripts/arm32_sysreg.py --s_file < $$< > $$@ +endef #process-arm32-sysreg + +$(foreach sr, $(arm32-sysregs), $(eval $(call process-arm32-sysreg,$(sr)))) diff --git a/optee/optee_os/core/arch/arm/cpu/cortex-a15.mk b/optee/optee_os/core/arch/arm/cpu/cortex-a15.mk new file mode 100644 index 0000000..b01014e --- /dev/null +++ b/optee/optee_os/core/arch/arm/cpu/cortex-a15.mk @@ -0,0 +1,10 @@ +$(call force,CFG_ARM32_core,y) +$(call force,CFG_ARM64_core,n) +$(call force,CFG_HWSUPP_MEM_PERM_WXN,y) +$(call force,CFG_HWSUPP_MEM_PERM_PXN,y) +arm32-platform-cpuarch := cortex-a15 +arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) +# Program flow prediction may need manual enablement +CFG_ENABLE_SCTLR_Z ?= y diff --git a/optee/optee_os/core/arch/arm/cpu/cortex-a5.mk b/optee/optee_os/core/arch/arm/cpu/cortex-a5.mk new file mode 100644 index 0000000..11714dd --- /dev/null +++ b/optee/optee_os/core/arch/arm/cpu/cortex-a5.mk @@ -0,0 +1,10 @@ +$(call force,CFG_ARM32_core,y) +$(call force,CFG_ARM64_core,n) +$(call force,CFG_WITH_LPAE,n) +$(call force,CFG_HWSUPP_MEM_PERM_WXN,n) +$(call force,CFG_HWSUPP_MEM_PERM_PXN,n) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,n) +arm32-platform-cpuarch := cortex-a5 +arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) diff --git a/optee/optee_os/core/arch/arm/cpu/cortex-a7.mk b/optee/optee_os/core/arch/arm/cpu/cortex-a7.mk new file mode 100644 index 0000000..46d4d1a --- /dev/null +++ b/optee/optee_os/core/arch/arm/cpu/cortex-a7.mk @@ -0,0 +1,9 @@ +$(call force,CFG_ARM32_core,y) +$(call force,CFG_ARM64_core,n) +$(call force,CFG_HWSUPP_MEM_PERM_WXN,y) +$(call force,CFG_HWSUPP_MEM_PERM_PXN,y) +$(call force,CFG_ENABLE_SCTLR_Z,n) +arm32-platform-cpuarch := cortex-a7 +arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) diff --git a/optee/optee_os/core/arch/arm/cpu/cortex-a9.mk b/optee/optee_os/core/arch/arm/cpu/cortex-a9.mk new file mode 100644 index 0000000..6da50be --- /dev/null +++ b/optee/optee_os/core/arch/arm/cpu/cortex-a9.mk @@ -0,0 +1,12 @@ +$(call force,CFG_ARM32_core,y) +$(call force,CFG_ARM64_core,n) +$(call force,CFG_WITH_LPAE,n) +$(call force,CFG_HWSUPP_MEM_PERM_WXN,n) +$(call force,CFG_HWSUPP_MEM_PERM_PXN,n) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,n) +arm32-platform-cpuarch := cortex-a9 +arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) +# Program flow prediction may need manual enablement +CFG_ENABLE_SCTLR_Z ?= y diff --git a/optee/optee_os/core/arch/arm/cpu/cortex-armv8-0.mk b/optee/optee_os/core/arch/arm/cpu/cortex-armv8-0.mk new file mode 100644 index 0000000..624b7cf --- /dev/null +++ b/optee/optee_os/core/arch/arm/cpu/cortex-armv8-0.mk @@ -0,0 +1,10 @@ +$(call force,CFG_HWSUPP_MEM_PERM_WXN,y) +$(call force,CFG_HWSUPP_MEM_PERM_PXN,y) +$(call force,CFG_ENABLE_SCTLR_RR,n) +$(call force,CFG_ENABLE_SCTLR_Z,n) +# cortex-a53 and cortex-a57 complies on arm32 architectures +arm32-platform-cpuarch := cortex-a53 +arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) +arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) +platform-flavor-armv8 := 1 diff --git a/optee/optee_os/core/arch/arm/crypto/aes-gcm-ce.c b/optee/optee_os/core/arch/arm/crypto/aes-gcm-ce.c new file mode 100644 index 0000000..054dda3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/aes-gcm-ce.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aes_armv8a_ce.h" + +static void get_be_block(void *dst, const void *src) +{ + uint64_t *d = dst; + + d[1] = get_be64(src); + d[0] = get_be64((const uint8_t *)src + 8); +} + +static void put_be_block(void *dst, const void *src) +{ + const uint64_t *s = src; + + put_be64(dst, s[1]); + put_be64((uint8_t *)dst + 8, s[0]); +} + +static void ghash_reflect(uint64_t h[2], const uint64_t k[2]) +{ + uint64_t b = get_be64(k); + uint64_t a = get_be64(k + 1); + + h[0] = (a << 1) | (b >> 63); + h[1] = (b << 1) | (a >> 63); + if (b >> 63) + h[1] ^= 0xc200000000000000UL; +} + +void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *enc_key) +{ + uint64_t k[2] = { 0 }; + uint64_t h[2] = { 0 }; + + crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data), + enc_key->rounds, state->ctr, k); + + ghash_reflect(state->ghash_key.h, k); + + internal_aes_gcm_gfmul(k, k, h); + ghash_reflect(state->ghash_key.h2, h); + + internal_aes_gcm_gfmul(k, h, h); + ghash_reflect(state->ghash_key.h3, h); + + internal_aes_gcm_gfmul(k, h, h); + ghash_reflect(state->ghash_key.h4, h); +} + +static void pmull_ghash_update(int num_blocks, uint64_t dg[2], + const uint8_t *src, + const struct internal_ghash_key *ghash_key, + const uint8_t *head) +{ +#ifdef CFG_HWSUPP_PMULT_64 + pmull_ghash_update_p64(num_blocks, dg, src, ghash_key, head); +#else + pmull_ghash_update_p8(num_blocks, dg, src, ghash_key, head); +#endif +} + +void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state, + const void *head, const void *data, + size_t num_blocks) +{ + uint32_t vfp_state; + uint64_t dg[2]; + + get_be_block(dg, state->hash_state); + + vfp_state = thread_kernel_enable_vfp(); + + pmull_ghash_update(num_blocks, dg, data, &state->ghash_key, head); + + thread_kernel_disable_vfp(vfp_state); + + put_be_block(state->hash_state, dg); +} + +static void encrypt_pl(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, uint64_t dg[2], + const uint8_t *src, size_t num_blocks, uint8_t *dst) +{ + void *buf_cryp = state->buf_cryp; + + while (num_blocks) { + ce_aes_xor_block(buf_cryp, buf_cryp, src); + + pmull_ghash_update(1, dg, buf_cryp, &state->ghash_key, NULL); + memcpy(dst, buf_cryp, TEE_AES_BLOCK_SIZE); + + ce_aes_ecb_encrypt(buf_cryp, (const uint8_t *)state->ctr, + (const uint8_t *)ek->data, ek->rounds, + 1, 1); + internal_aes_gcm_inc_ctr(state); + + src += TEE_AES_BLOCK_SIZE; + dst += TEE_AES_BLOCK_SIZE; + num_blocks--; + } +} + +static void decrypt_pl(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, uint64_t dg[2], + const uint8_t *src, size_t num_blocks, uint8_t *dst) +{ + while (num_blocks) { + ce_aes_ctr_encrypt(dst, src, (const uint8_t *)ek->data, + ek->rounds, 1, (uint8_t *)state->ctr, 1); + pmull_ghash_update(1, dg, src, &state->ghash_key, NULL); + + src += TEE_AES_BLOCK_SIZE; + dst += TEE_AES_BLOCK_SIZE; + num_blocks--; + } +} + +#ifdef ARM64 +static void update_payload_2block(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + uint64_t dg[2], TEE_OperationMode mode, + const void *src, size_t num_blocks, void *dst) +{ + assert(num_blocks && !(num_blocks % 2)); + + if (mode == TEE_MODE_ENCRYPT) { + uint8_t ks[sizeof(state->buf_cryp) * 2] = { 0 }; + + /* + * ks holds the encrypted counters of the next two blocks. + * pmull_gcm_encrypt() uses this to encrypt the first two + * blocks. When pmull_gcm_encrypt() returns is ks updated + * with the encrypted counters of the next two blocks. As + * we're only keeping one of these blocks we throw away + * block number two consequently decreases the counter by + * one. + */ + memcpy(ks, state->buf_cryp, sizeof(state->buf_cryp)); + + pmull_gcm_load_round_keys(ek->data, ek->rounds); + pmull_gcm_encrypt_block(ks + sizeof(state->buf_cryp), + (uint8_t *)state->ctr, ek->rounds); + internal_aes_gcm_inc_ctr(state); + pmull_gcm_encrypt(num_blocks, dg, dst, src, &state->ghash_key, + state->ctr, NULL, ek->rounds, ks); + memcpy(state->buf_cryp, ks, TEE_AES_BLOCK_SIZE); + internal_aes_gcm_dec_ctr(state); + } else { + pmull_gcm_decrypt(num_blocks, dg, dst, src, &state->ghash_key, + state->ctr, ek->data, ek->rounds); + } +} + +/* Overriding the __weak function */ +void +internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + TEE_OperationMode mode, const void *src, + size_t num_blocks, void *dst) +{ + size_t nb = ROUNDDOWN(num_blocks, 2); + uint32_t vfp_state = 0; + uint64_t dg[2] = { 0 }; + + get_be_block(dg, state->hash_state); + vfp_state = thread_kernel_enable_vfp(); + + /* + * pmull_gcm_encrypt() and pmull_gcm_decrypt() can only handle + * blocks in multiples of two. + */ + if (nb) + update_payload_2block(state, ek, dg, mode, src, nb, dst); + + if (nb != num_blocks) { + /* There's a final block */ + const void *s = (const uint8_t *)src + nb * TEE_AES_BLOCK_SIZE; + void *d = (uint8_t *)dst + nb * TEE_AES_BLOCK_SIZE; + + if (mode == TEE_MODE_ENCRYPT) + encrypt_pl(state, ek, dg, s, 1, d); + else + decrypt_pl(state, ek, dg, s, 1, d); + } + + thread_kernel_disable_vfp(vfp_state); + put_be_block(state->hash_state, dg); +} +#endif /*ARM64*/ + +#ifdef ARM32 +/* Overriding the __weak function */ +void +internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + TEE_OperationMode mode, const void *src, + size_t num_blocks, void *dst) +{ + uint64_t dg[2] = { 0 }; + uint32_t vfp_state = 0; + + assert(!state->buf_pos && num_blocks); + get_be_block(dg, state->hash_state); + vfp_state = thread_kernel_enable_vfp(); + + if (mode == TEE_MODE_ENCRYPT) + encrypt_pl(state, ek, dg, src, num_blocks, dst); + else + decrypt_pl(state, ek, dg, src, num_blocks, dst); + + thread_kernel_disable_vfp(vfp_state); + put_be_block(state->hash_state, dg); +} +#endif diff --git a/optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.c b/optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.c new file mode 100644 index 0000000..725eacb --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, 2020 Linaro Limited + * Copyright (C) 2013 Linaro Ltd + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 cipher for ARMv8 with Crypto Extensions + */ + +#include +#include +#include +#include +#include +#include + +#include "aes_armv8a_ce.h" + +struct aes_block { + uint8_t b[TEE_AES_BLOCK_SIZE]; +}; + +static uint32_t ror32(uint32_t val, unsigned int shift) +{ + return (val >> shift) | (val << (32 - shift)); +} + +static void expand_enc_key(uint32_t *enc_key, size_t key_len) +{ + /* The AES key schedule round constants */ + static uint8_t const rcon[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, + }; + unsigned int kwords = key_len / sizeof(uint32_t); + unsigned int i = 0; + + for (i = 0; i < sizeof(rcon); i++) { + uint32_t *rki = enc_key + i * kwords; + uint32_t *rko = rki + kwords; + + rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8) ^ + rcon[i] ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + + if (key_len == 24) { + if (i >= 7) + break; + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + } else if (key_len == 32) { + if (i >= 6) + break; + rko[4] = ce_aes_sub(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; + } + } +} + +static void make_dec_key(unsigned int round_count, + const struct aes_block *key_enc, + struct aes_block *key_dec) +{ + unsigned int i = 0; + unsigned int j = round_count; + + /* + * Generate the decryption keys for the Equivalent Inverse Cipher. + * This involves reversing the order of the round keys, and applying + * the Inverse Mix Columns transformation on all but the first and + * the last ones. + */ + j = round_count; + + key_dec[0] = key_enc[j]; + for (i = 1, j--; j > 0; i++, j--) + ce_aes_invert(key_dec + i, key_enc + j); + key_dec[i] = key_enc[0]; +} + +TEE_Result crypto_accel_aes_expand_keys(const void *key, size_t key_len, + void *enc_key, void *dec_key, + size_t expanded_key_len, + unsigned int *round_count) +{ + unsigned int num_rounds = 0; + uint32_t vfp_state = 0; + + if (!key || !enc_key) + return TEE_ERROR_BAD_PARAMETERS; + if (key_len != 16 && key_len != 24 && key_len != 32) + return TEE_ERROR_BAD_PARAMETERS; + if (!IS_ALIGNED_WITH_TYPE(enc_key, struct aes_block) || + !IS_ALIGNED_WITH_TYPE(dec_key, struct aes_block)) + return TEE_ERROR_BAD_PARAMETERS; + + num_rounds = 10 + ((key_len / 8) - 2) * 2; + + if (expanded_key_len < (num_rounds + 1) * sizeof(struct aes_block)) + return TEE_ERROR_BAD_PARAMETERS; + + *round_count = num_rounds; + memset(enc_key, 0, expanded_key_len); + memcpy(enc_key, key, key_len); + + vfp_state = thread_kernel_enable_vfp(); + + expand_enc_key(enc_key, key_len); + if (dec_key) + make_dec_key(num_rounds, enc_key, dec_key); + + thread_kernel_disable_vfp(vfp_state); + + return TEE_SUCCESS; +} + +void crypto_accel_aes_ecb_enc(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count) +{ + uint32_t vfp_state = 0; + + assert(out && in && key); + + vfp_state = thread_kernel_enable_vfp(); + ce_aes_ecb_encrypt(out, in, key, round_count, block_count, 1); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_aes_ecb_dec(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count) +{ + uint32_t vfp_state = 0; + + assert(out && in && key); + + vfp_state = thread_kernel_enable_vfp(); + ce_aes_ecb_decrypt(out, in, key, round_count, block_count, 1); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_aes_cbc_enc(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && iv); + + vfp_state = thread_kernel_enable_vfp(); + ce_aes_cbc_encrypt(out, in, key, round_count, block_count, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_aes_cbc_dec(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && iv); + + vfp_state = thread_kernel_enable_vfp(); + ce_aes_cbc_decrypt(out, in, key, round_count, block_count, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_aes_ctr_be_enc(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && iv); + + vfp_state = thread_kernel_enable_vfp(); + ce_aes_ctr_encrypt(out, in, key, round_count, block_count, iv, 1); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_aes_xts_enc(void *out, const void *in, const void *key1, + unsigned int round_count, + unsigned int block_count, const void *key2, + void *tweak) +{ + uint32_t vfp_state = 0; + + assert(out && in && key1 && key2 && tweak); + + vfp_state = thread_kernel_enable_vfp(); + ce_aes_xts_encrypt(out, in, key1, round_count, block_count, key2, + tweak); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_aes_xts_dec(void *out, const void *in, const void *key1, + unsigned int round_count, + unsigned int block_count, const void *key2, + void *tweak) +{ + uint32_t vfp_state = 0; + + assert(out && in && key1 && key2 && tweak); + + vfp_state = thread_kernel_enable_vfp(); + ce_aes_xts_decrypt(out, in, key1, round_count, block_count, key2, + tweak); + thread_kernel_disable_vfp(vfp_state); +} diff --git a/optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.h b/optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.h new file mode 100644 index 0000000..fccc27c --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/aes_armv8a_ce.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020 Linaro Limited + */ + +#ifndef __AES_ARMV8_CE_H +#define __AES_ARMV8_CE_H + +#include + +/* Prototypes for assembly functions */ +uint32_t ce_aes_sub(uint32_t in); +void ce_aes_invert(void *dst, const void *src); +void ce_aes_ecb_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + int rounds, int blocks, int first); +void ce_aes_ecb_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + int rounds, int blocks, int first); +void ce_aes_cbc_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + int rounds, int blocks, uint8_t iv[]); +void ce_aes_cbc_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + int rounds, int blocks, uint8_t iv[]); +void ce_aes_ctr_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + int rounds, int blocks, uint8_t ctr[], int first); +void ce_aes_xts_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], + int rounds, int blocks, uint8_t const rk2[], + uint8_t iv[]); +void ce_aes_xts_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], + int rounds, int blocks, uint8_t const rk2[], + uint8_t iv[]); +void ce_aes_xor_block(uint8_t out[], uint8_t const op1[], uint8_t const op2[]); + +#endif /*__AES_ARMV8_CE_H*/ diff --git a/optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S b/optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S new file mode 100644 index 0000000..30a431a --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S @@ -0,0 +1,531 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, 2020 Linaro Limited + * Copyright (C) 2015 Linaro Ltd + * + * aes-ce-core.S - AES in CBC/CTR/XTS mode using ARMv8 Crypto Extensions + */ + +#include + + .fpu crypto-neon-fp-armv8 + + .macro enc_round, state, key + aese.8 \state, \key + aesmc.8 \state, \state + .endm + + .macro dec_round, state, key + aesd.8 \state, \key + aesimc.8 \state, \state + .endm + + .macro enc_dround, key1, key2 + enc_round q0, \key1 + enc_round q0, \key2 + .endm + + .macro dec_dround, key1, key2 + dec_round q0, \key1 + dec_round q0, \key2 + .endm + + .macro enc_fround, key1, key2, key3 + enc_round q0, \key1 + aese.8 q0, \key2 + veor q0, q0, \key3 + .endm + + .macro dec_fround, key1, key2, key3 + dec_round q0, \key1 + aesd.8 q0, \key2 + veor q0, q0, \key3 + .endm + + .macro enc_dround_3x, key1, key2 + enc_round q0, \key1 + enc_round q1, \key1 + enc_round q2, \key1 + enc_round q0, \key2 + enc_round q1, \key2 + enc_round q2, \key2 + .endm + + .macro dec_dround_3x, key1, key2 + dec_round q0, \key1 + dec_round q1, \key1 + dec_round q2, \key1 + dec_round q0, \key2 + dec_round q1, \key2 + dec_round q2, \key2 + .endm + + .macro enc_fround_3x, key1, key2, key3 + enc_round q0, \key1 + enc_round q1, \key1 + enc_round q2, \key1 + aese.8 q0, \key2 + aese.8 q1, \key2 + aese.8 q2, \key2 + veor q0, q0, \key3 + veor q1, q1, \key3 + veor q2, q2, \key3 + .endm + + .macro dec_fround_3x, key1, key2, key3 + dec_round q0, \key1 + dec_round q1, \key1 + dec_round q2, \key1 + aesd.8 q0, \key2 + aesd.8 q1, \key2 + aesd.8 q2, \key2 + veor q0, q0, \key3 + veor q1, q1, \key3 + veor q2, q2, \key3 + .endm + + .macro do_block, dround, fround + cmp r3, #12 @ which key size? + vld1.8 {q10-q11}, [ip]! + \dround q8, q9 + vld1.8 {q12-q13}, [ip]! + \dround q10, q11 + vld1.8 {q10-q11}, [ip]! + \dround q12, q13 + vld1.8 {q12-q13}, [ip]! + \dround q10, q11 + blo 0f @ AES-128: 10 rounds + vld1.8 {q10-q11}, [ip]! + \dround q12, q13 + beq 1f @ AES-192: 12 rounds + vld1.8 {q12-q13}, [ip] + \dround q10, q11 +0: \fround q12, q13, q14 + bx lr + +1: \fround q10, q11, q14 + bx lr + .endm + + /* + * Internal, non-AAPCS compliant functions that implement the core + * AES transforms. These should preserve all registers except q0 - + * q2 and ip. + * Arguments: + * q0 : first in/output block + * q1 : second in/output block (_3x version only) + * q2 : third in/output block (_3x version only) + * q8 : first round key + * q9 : secound round key + * q14 : final round key + * r2 : address of round key array + * r3 : number of rounds + */ + .section .text.ce_aes_helpers + .align 6 +aes_encrypt: + add ip, r2, #32 @ 3rd round key +.Laes_encrypt_tweak: + do_block enc_dround, enc_fround + + .align 6 +aes_decrypt: + add ip, r2, #32 @ 3rd round key + do_block dec_dround, dec_fround + + .align 6 +aes_encrypt_3x: + add ip, r2, #32 @ 3rd round key + do_block enc_dround_3x, enc_fround_3x + + .align 6 +aes_decrypt_3x: + add ip, r2, #32 @ 3rd round key + do_block dec_dround_3x, dec_fround_3x + + .macro prepare_key, rk, rounds + add ip, \rk, \rounds, lsl #4 + vld1.8 {q8-q9}, [\rk] @ load first 2 round keys + vld1.8 {q14}, [ip] @ load last round key + .endm + + /* + * void ce_aes_ecb_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], int rounds, int blocks, + * int first) + */ +FUNC ce_aes_ecb_encrypt , : + push {r4, lr} + ldr r4, [sp, #8] + prepare_key r2, r3 +.Lecbencloop3x: + subs r4, r4, #3 + bmi .Lecbenc1x + vld1.8 {q0-q1}, [r1]! + vld1.8 {q2}, [r1]! + bl aes_encrypt_3x + vst1.8 {q0-q1}, [r0]! + vst1.8 {q2}, [r0]! + b .Lecbencloop3x +.Lecbenc1x: + adds r4, r4, #3 + beq .Lecbencout +.Lecbencloop: + vld1.8 {q0}, [r1]! + bl aes_encrypt + vst1.8 {q0}, [r0]! + subs r4, r4, #1 + bne .Lecbencloop +.Lecbencout: + pop {r4, pc} +END_FUNC ce_aes_ecb_encrypt + + /* + * void ce_aes_ecb_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], int rounds, int blocks, + * int first) + */ +FUNC ce_aes_ecb_decrypt , : + push {r4, lr} + ldr r4, [sp, #8] + prepare_key r2, r3 +.Lecbdecloop3x: + subs r4, r4, #3 + bmi .Lecbdec1x + vld1.8 {q0-q1}, [r1]! + vld1.8 {q2}, [r1]! + bl aes_decrypt_3x + vst1.8 {q0-q1}, [r0]! + vst1.8 {q2}, [r0]! + b .Lecbdecloop3x +.Lecbdec1x: + adds r4, r4, #3 + beq .Lecbdecout +.Lecbdecloop: + vld1.8 {q0}, [r1]! + bl aes_decrypt + vst1.8 {q0}, [r0]! + subs r4, r4, #1 + bne .Lecbdecloop +.Lecbdecout: + pop {r4, pc} +END_FUNC ce_aes_ecb_decrypt + + /* + * void ce_aes_cbc_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], int rounds, int blocks, + * uint8_t iv[]) + */ +FUNC ce_aes_cbc_encrypt , : + push {r4-r6, lr} + ldrd r4, r5, [sp, #16] + vld1.8 {q0}, [r5] + prepare_key r2, r3 +.Lcbcencloop: + vld1.8 {q1}, [r1]! @ get next pt block + veor q0, q0, q1 @ ..and xor with iv + bl aes_encrypt + vst1.8 {q0}, [r0]! + subs r4, r4, #1 + bne .Lcbcencloop + vst1.8 {q0}, [r5] + pop {r4-r6, pc} +END_FUNC ce_aes_cbc_encrypt + + /* + * void ce_aes_cbc_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], int rounds, int blocks, + * uint8_t iv[]) + */ +FUNC ce_aes_cbc_decrypt , : + push {r4-r6, lr} + ldrd r4, r5, [sp, #16] + vld1.8 {q6}, [r5] @ keep iv in q6 + prepare_key r2, r3 +.Lcbcdecloop3x: + subs r4, r4, #3 + bmi .Lcbcdec1x + vld1.8 {q0-q1}, [r1]! + vld1.8 {q2}, [r1]! + vmov q3, q0 + vmov q4, q1 + vmov q5, q2 + bl aes_decrypt_3x + veor q0, q0, q6 + veor q1, q1, q3 + veor q2, q2, q4 + vmov q6, q5 + vst1.8 {q0-q1}, [r0]! + vst1.8 {q2}, [r0]! + b .Lcbcdecloop3x +.Lcbcdec1x: + adds r4, r4, #3 + beq .Lcbcdecout + vmov q15, q14 @ preserve last round key +.Lcbcdecloop: + vld1.8 {q0}, [r1]! @ get next ct block + veor q14, q15, q6 @ combine prev ct with last key + vmov q6, q0 + bl aes_decrypt + vst1.8 {q0}, [r0]! + subs r4, r4, #1 + bne .Lcbcdecloop +.Lcbcdecout: + vst1.8 {q6}, [r5] @ keep iv in q6 + pop {r4-r6, pc} +END_FUNC ce_aes_cbc_decrypt + + /* + * void ce_aes_ctr_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], int rounds, int blocks, + * uint8_t ctr[], int first) + */ +FUNC ce_aes_ctr_encrypt , : + push {r4-r6, lr} + ldrd r4, r5, [sp, #16] + vld1.8 {q6}, [r5] @ load ctr + prepare_key r2, r3 + vmov r6, s27 @ keep swabbed ctr in r6 + rev r6, r6 + cmn r6, r4 @ 32 bit overflow? + bcs .Lctrloop +.Lctrloop3x: + subs r4, r4, #3 + bmi .Lctr1x + add r6, r6, #1 + vmov q0, q6 + vmov q1, q6 + rev ip, r6 + add r6, r6, #1 + vmov q2, q6 + vmov s7, ip + rev ip, r6 + add r6, r6, #1 + vmov s11, ip + vld1.8 {q3-q4}, [r1]! + vld1.8 {q5}, [r1]! + bl aes_encrypt_3x + veor q0, q0, q3 + veor q1, q1, q4 + veor q2, q2, q5 + rev ip, r6 + vst1.8 {q0-q1}, [r0]! + vst1.8 {q2}, [r0]! + vmov s27, ip + b .Lctrloop3x +.Lctr1x: + adds r4, r4, #3 + beq .Lctrout +.Lctrloop: + vmov q0, q6 + bl aes_encrypt + subs r4, r4, #1 + bmi .Lctrtailblock @ blocks < 0 means tail block + vld1.8 {q3}, [r1]! + veor q3, q0, q3 + vst1.8 {q3}, [r0]! + + adds r6, r6, #1 @ increment BE ctr + rev ip, r6 + vmov s27, ip + bcs .Lctrcarry + teq r4, #0 + bne .Lctrloop +.Lctrout: + vst1.8 {q6}, [r5] + pop {r4-r6, pc} + +.Lctrtailblock: + vst1.8 {q0}, [r0, :64] @ return just the key stream + pop {r4-r6, pc} + +.Lctrcarry: + .irp sreg, s26, s25, s24 + vmov ip, \sreg @ load next word of ctr + rev ip, ip @ ... to handle the carry + adds ip, ip, #1 + rev ip, ip + vmov \sreg, ip + bcc 0f + .endr +0: teq r4, #0 + beq .Lctrout + b .Lctrloop +END_FUNC ce_aes_ctr_encrypt + + /* + * void ce_aes_xts_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk1[], int rounds, int blocks, + * uint8_t const rk2[], uint8_t iv[]) + * void ce_aes_xts_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk1[], int rounds, int blocks, + * uint8_t const rk2[], uint8_t iv[]); + */ + + .macro next_tweak, out, in, const, tmp + vshr.s64 \tmp, \in, #63 + vand \tmp, \tmp, \const + vadd.u64 \out, \in, \in + vext.8 \tmp, \tmp, \tmp, #8 + veor \out, \out, \tmp + .endm + +LOCAL_FUNC ce_aes_xts_init , : + vldr d14, .Lxts_mul_x + vldr d15, .Lxts_mul_x + 8 + + ldr r4, [sp, #16] @ load args + ldr r5, [sp, #24] + vld1.8 {q0}, [r5] @ load iv + + @ Encrypt the IV in q0 with the second AES key. This should only + @ be done at the start of a block. + ldr r6, [sp, #20] @ load AES key 2 + prepare_key r6, r3 + add ip, r6, #32 @ 3rd round key of key 2 + b .Laes_encrypt_tweak @ tail call + + .align 3 +.Lxts_mul_x: + .quad 1, 0x87 +END_FUNC ce_aes_xts_init + +FUNC ce_aes_xts_encrypt , : + push {r4-r6, lr} + + bl ce_aes_xts_init @ run shared prologue + prepare_key r2, r3 + vmov q3, q0 + + teq r6, #0 @ start of a block? + bne .Lxtsenc3x + +.Lxtsencloop3x: + next_tweak q3, q3, q7, q6 +.Lxtsenc3x: + subs r4, r4, #3 + bmi .Lxtsenc1x + vld1.8 {q0-q1}, [r1]! @ get 3 pt blocks + vld1.8 {q2}, [r1]! + next_tweak q4, q3, q7, q6 + veor q0, q0, q3 + next_tweak q5, q4, q7, q6 + veor q1, q1, q4 + veor q2, q2, q5 + bl aes_encrypt_3x + veor q0, q0, q3 + veor q1, q1, q4 + veor q2, q2, q5 + vst1.8 {q0-q1}, [r0]! @ write 3 ct blocks + vst1.8 {q2}, [r0]! + vmov q3, q5 + teq r4, #0 + beq .Lxtsencout + b .Lxtsencloop3x +.Lxtsenc1x: + adds r4, r4, #3 + beq .Lxtsencout +.Lxtsencloop: + vld1.8 {q0}, [r1]! + veor q0, q0, q3 + bl aes_encrypt + veor q0, q0, q3 + vst1.8 {q0}, [r0]! + subs r4, r4, #1 + beq .Lxtsencout + next_tweak q3, q3, q7, q6 + b .Lxtsencloop +.Lxtsencout: + next_tweak q3, q3, q7, q6 + vst1.8 {q3}, [r5] + pop {r4-r6, pc} +END_FUNC ce_aes_xts_encrypt + +FUNC ce_aes_xts_decrypt , : + push {r4-r6, lr} + + bl ce_aes_xts_init @ run shared prologue + prepare_key r2, r3 + vmov q3, q0 + + teq r6, #0 @ start of a block? + bne .Lxtsdec3x + +.Lxtsdecloop3x: + next_tweak q3, q3, q7, q6 +.Lxtsdec3x: + subs r4, r4, #3 + bmi .Lxtsdec1x + vld1.8 {q0-q1}, [r1]! @ get 3 ct blocks + vld1.8 {q2}, [r1]! + next_tweak q4, q3, q7, q6 + veor q0, q0, q3 + next_tweak q5, q4, q7, q6 + veor q1, q1, q4 + veor q2, q2, q5 + bl aes_decrypt_3x + veor q0, q0, q3 + veor q1, q1, q4 + veor q2, q2, q5 + vst1.8 {q0-q1}, [r0]! @ write 3 pt blocks + vst1.8 {q2}, [r0]! + vmov q3, q5 + teq r4, #0 + beq .Lxtsdecout + b .Lxtsdecloop3x +.Lxtsdec1x: + adds r4, r4, #3 + beq .Lxtsdecout +.Lxtsdecloop: + vld1.8 {q0}, [r1]! + veor q0, q0, q3 + add ip, r2, #32 @ 3rd round key + bl aes_decrypt + veor q0, q0, q3 + vst1.8 {q0}, [r0]! + subs r4, r4, #1 + beq .Lxtsdecout + next_tweak q3, q3, q7, q6 + b .Lxtsdecloop +.Lxtsdecout: + next_tweak q3, q3, q7, q6 + vst1.8 {q3}, [r5] + pop {r4-r6, pc} +END_FUNC ce_aes_xts_decrypt + + /* + * u32 ce_aes_sub(u32 input) - use the aese instruction to perform the + * AES sbox substitution on each byte in + * 'input' + */ +FUNC ce_aes_sub , : + vdup.32 q1, r0 + veor q0, q0, q0 + aese.8 q0, q1 + vmov r0, s0 + bx lr +END_FUNC ce_aes_sub + + /* + * void ce_aes_invert(void *dst, const void *src) + * + * perform the Inverse MixColumns operation on round key in + */ +FUNC ce_aes_invert , : + vld1.8 {q0}, [r1] + aesimc.8 q0, q0 + vst1.8 {q0}, [r0] + bx lr +END_FUNC ce_aes_invert + + /* + * void ce_aes_xor_block(uint8_t out[], uint8_t const op1[], + * uint8_t const op2[]); + */ +FUNC ce_aes_xor_block , : + vld1.8 {q0}, [r1] + vld1.8 {q1}, [r2] + veor q0, q0, q1 + vst1.8 {q0}, [r0] + bx lr +END_FUNC ce_aes_xor_block diff --git a/optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S b/optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S new file mode 100644 index 0000000..72dfea7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S @@ -0,0 +1,664 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, 2020 Linaro Limited + * Copyright (C) 2013 Linaro Ltd + * + * - AES cipher for ARMv8 with Crypto Extensions + * - Chaining mode wrappers for AES + */ + +#include + + .arch armv8-a+crypto + + /* Preload all round keys */ + .macro load_round_keys, rounds, rk + cmp \rounds, #12 + blo 2222f /* 128 bits */ + beq 1111f /* 192 bits */ + ld1 {v17.16b-v18.16b}, [\rk], #32 +1111: ld1 {v19.16b-v20.16b}, [\rk], #32 +2222: ld1 {v21.16b-v24.16b}, [\rk], #64 + ld1 {v25.16b-v28.16b}, [\rk], #64 + ld1 {v29.16b-v31.16b}, [\rk] + .endm + + /* Prepare for encryption with key in rk[] */ + .macro enc_prepare, rounds, rk, ignore + load_round_keys \rounds, \rk + .endm + + /* Prepare for encryption (again) but with new key in rk[] */ + .macro enc_switch_key, rounds, rk, ignore + load_round_keys \rounds, \rk + .endm + + /* Prepare for decryption with key in rk[] */ + .macro dec_prepare, rounds, rk, ignore + load_round_keys \rounds, \rk + .endm + + .macro do_enc_Nx, de, mc, k, i0, i1, i2, i3 + aes\de \i0\().16b, \k\().16b + aes\mc \i0\().16b, \i0\().16b + .ifnb \i1 + aes\de \i1\().16b, \k\().16b + aes\mc \i1\().16b, \i1\().16b + .ifnb \i3 + aes\de \i2\().16b, \k\().16b + aes\mc \i2\().16b, \i2\().16b + aes\de \i3\().16b, \k\().16b + aes\mc \i3\().16b, \i3\().16b + .endif + .endif + .endm + + /* Up to 4 interleaved encryption rounds with the same round key */ + .macro round_Nx, enc, k, i0, i1, i2, i3 + .ifc \enc, e + do_enc_Nx e, mc, \k, \i0, \i1, \i2, \i3 + .else + do_enc_Nx d, imc, \k, \i0, \i1, \i2, \i3 + .endif + .endm + + /* Up to 4 interleaved final rounds */ + .macro fin_round_Nx, de, k, k2, i0, i1, i2, i3 + aes\de \i0\().16b, \k\().16b + .ifnb \i1 + aes\de \i1\().16b, \k\().16b + .ifnb \i3 + aes\de \i2\().16b, \k\().16b + aes\de \i3\().16b, \k\().16b + .endif + .endif + eor \i0\().16b, \i0\().16b, \k2\().16b + .ifnb \i1 + eor \i1\().16b, \i1\().16b, \k2\().16b + .ifnb \i3 + eor \i2\().16b, \i2\().16b, \k2\().16b + eor \i3\().16b, \i3\().16b, \k2\().16b + .endif + .endif + .endm + + /* Up to 4 interleaved blocks */ + .macro do_block_Nx, enc, rounds, i0, i1, i2, i3 + cmp \rounds, #12 + blo 2222f /* 128 bits */ + beq 1111f /* 192 bits */ + round_Nx \enc, v17, \i0, \i1, \i2, \i3 + round_Nx \enc, v18, \i0, \i1, \i2, \i3 +1111: round_Nx \enc, v19, \i0, \i1, \i2, \i3 + round_Nx \enc, v20, \i0, \i1, \i2, \i3 +2222: .irp key, v21, v22, v23, v24, v25, v26, v27, v28, v29 + round_Nx \enc, \key, \i0, \i1, \i2, \i3 + .endr + fin_round_Nx \enc, v30, v31, \i0, \i1, \i2, \i3 + .endm + + .macro encrypt_block, in, rounds, t0, t1, t2 + do_block_Nx e, \rounds, \in + .endm + + .macro encrypt_block2x, i0, i1, rounds, t0, t1, t2 + do_block_Nx e, \rounds, \i0, \i1 + .endm + + .macro encrypt_block4x, i0, i1, i2, i3, rounds, t0, t1, t2 + do_block_Nx e, \rounds, \i0, \i1, \i2, \i3 + .endm + + .macro decrypt_block, in, rounds, t0, t1, t2 + do_block_Nx d, \rounds, \in + .endm + + .macro decrypt_block2x, i0, i1, rounds, t0, t1, t2 + do_block_Nx d, \rounds, \i0, \i1 + .endm + + .macro decrypt_block4x, i0, i1, i2, i3, rounds, t0, t1, t2 + do_block_Nx d, \rounds, \i0, \i1, \i2, \i3 + .endm + + +/* + * There are several ways to instantiate this code: + * - no interleave, all inline + * - 2-way interleave, 2x calls out of line (-DINTERLEAVE=2) + * - 2-way interleave, all inline (-DINTERLEAVE=2 -DINTERLEAVE_INLINE) + * - 4-way interleave, 4x calls out of line (-DINTERLEAVE=4) + * - 4-way interleave, all inline (-DINTERLEAVE=4 -DINTERLEAVE_INLINE) + * + * Macros imported by this code: + * - enc_prepare - setup NEON registers for encryption + * - dec_prepare - setup NEON registers for decryption + * - enc_switch_key - change to new key after having prepared for encryption + * - encrypt_block - encrypt a single block + * - decrypt block - decrypt a single block + * - encrypt_block2x - encrypt 2 blocks in parallel (if INTERLEAVE == 2) + * - decrypt_block2x - decrypt 2 blocks in parallel (if INTERLEAVE == 2) + * - encrypt_block4x - encrypt 4 blocks in parallel (if INTERLEAVE == 4) + * - decrypt_block4x - decrypt 4 blocks in parallel (if INTERLEAVE == 4) + */ + +#if defined(INTERLEAVE) && !defined(INTERLEAVE_INLINE) +#define FRAME_PUSH stp x29, x30, [sp,#-16]! ; mov x29, sp +#define FRAME_POP ldp x29, x30, [sp],#16 + +#if INTERLEAVE == 2 + +LOCAL_FUNC aes_encrypt_block2x , : + encrypt_block2x v0, v1, w3, x2, x6, w7 + ret +END_FUNC aes_encrypt_block2x + +LOCAL_FUNC aes_decrypt_block2x , : + decrypt_block2x v0, v1, w3, x2, x6, w7 + ret +END_FUNC aes_decrypt_block2x + +#elif INTERLEAVE == 4 + +LOCAL_FUNC aes_encrypt_block4x , : + encrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 + ret +END_FUNC aes_encrypt_block4x + +LOCAL_FUNC aes_decrypt_block4x , : + decrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 + ret +END_FUNC aes_decrypt_block4x + +#else +#error INTERLEAVE should equal 2 or 4 +#endif + + .macro do_encrypt_block2x + bl aes_encrypt_block2x + .endm + + .macro do_decrypt_block2x + bl aes_decrypt_block2x + .endm + + .macro do_encrypt_block4x + bl aes_encrypt_block4x + .endm + + .macro do_decrypt_block4x + bl aes_decrypt_block4x + .endm + +#else +#define FRAME_PUSH +#define FRAME_POP + + .macro do_encrypt_block2x + encrypt_block2x v0, v1, w3, x2, x6, w7 + .endm + + .macro do_decrypt_block2x + decrypt_block2x v0, v1, w3, x2, x6, w7 + .endm + + .macro do_encrypt_block4x + encrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 + .endm + + .macro do_decrypt_block4x + decrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 + .endm + +#endif + + /* + * uint32_t ce_aes_sub(uint32_t in) - use the aese instruction to + * perform the AES sbox substitution on each byte in 'input' + */ +FUNC ce_aes_sub , : + dup v1.4s, w0 + movi v0.16b, #0 + aese v0.16b, v1.16b + umov w0, v0.s[0] + ret +END_FUNC ce_aes_sub + + /* + * void ce_aes_invert(void *dst, const void *src); + */ +FUNC ce_aes_invert , : + ld1 {v0.16b}, [x1] + aesimc v1.16b, v0.16b + st1 {v1.16b}, [x0] + ret +END_FUNC ce_aes_invert + + /* + * ce_aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], + * int rounds, int blocks, int first) + */ +FUNC ce_aes_ecb_encrypt , : + FRAME_PUSH + cbz w5, .LecbencloopNx + + enc_prepare w3, x2, x5 + +.LecbencloopNx: +#if INTERLEAVE >= 2 + subs w4, w4, #INTERLEAVE + bmi .Lecbenc1x +#if INTERLEAVE == 2 + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 pt blocks */ + do_encrypt_block2x + st1 {v0.16b-v1.16b}, [x0], #32 +#else + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ + do_encrypt_block4x + st1 {v0.16b-v3.16b}, [x0], #64 +#endif + b .LecbencloopNx +.Lecbenc1x: + adds w4, w4, #INTERLEAVE + beq .Lecbencout +#endif +.Lecbencloop: + ld1 {v0.16b}, [x1], #16 /* get next pt block */ + encrypt_block v0, w3, x2, x5, w6 + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 + bne .Lecbencloop +.Lecbencout: + FRAME_POP + ret +END_FUNC ce_aes_ecb_encrypt + + /* + * ce_aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], + * int rounds, int blocks, int first) + */ +FUNC ce_aes_ecb_decrypt , : + FRAME_PUSH + cbz w5, .LecbdecloopNx + + dec_prepare w3, x2, x5 + +.LecbdecloopNx: +#if INTERLEAVE >= 2 + subs w4, w4, #INTERLEAVE + bmi .Lecbdec1x +#if INTERLEAVE == 2 + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */ + do_decrypt_block2x + st1 {v0.16b-v1.16b}, [x0], #32 +#else + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ + do_decrypt_block4x + st1 {v0.16b-v3.16b}, [x0], #64 +#endif + b .LecbdecloopNx +.Lecbdec1x: + adds w4, w4, #INTERLEAVE + beq .Lecbdecout +#endif +.Lecbdecloop: + ld1 {v0.16b}, [x1], #16 /* get next ct block */ + decrypt_block v0, w3, x2, x5, w6 + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 + bne .Lecbdecloop +.Lecbdecout: + FRAME_POP + ret +END_FUNC ce_aes_ecb_decrypt + + /* + * void ce_aes_cbc_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], int rounds, int blocks, + * uint8_t iv[]) + */ +FUNC ce_aes_cbc_encrypt , : + ld1 {v4.16b}, [x5] /* get iv */ + enc_prepare w3, x2, x6 + +.Lcbcencloop4x: + subs w4, w4, #4 + bmi .Lcbcenc1x + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ + eor v0.16b, v0.16b, v4.16b /* ..and xor with iv */ + encrypt_block v0, w3, x2, x6, w7 + eor v1.16b, v1.16b, v0.16b + encrypt_block v1, w3, x2, x6, w7 + eor v2.16b, v2.16b, v1.16b + encrypt_block v2, w3, x2, x6, w7 + eor v3.16b, v3.16b, v2.16b + encrypt_block v3, w3, x2, x6, w7 + st1 {v0.16b-v3.16b}, [x0], #64 + mov v4.16b, v3.16b + b .Lcbcencloop4x +.Lcbcenc1x: + adds w4, w4, #4 + beq .Lcbcencout +.Lcbcencloop: + ld1 {v0.16b}, [x1], #16 /* get next pt block */ + eor v4.16b, v4.16b, v0.16b /* ..and xor with iv */ + encrypt_block v4, w3, x2, x6, w7 + st1 {v4.16b}, [x0], #16 + subs w4, w4, #1 + bne .Lcbcencloop +.Lcbcencout: + st1 {v4.16b}, [x5] /* return iv */ + ret +END_FUNC ce_aes_cbc_encrypt + + /* + * void ce_aes_cbc_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], int rounds, int blocks, + * uint8_t iv[]) + */ +FUNC ce_aes_cbc_decrypt , : + stp x29, x30, [sp, #-16]! + mov x29, sp + + ld1 {v7.16b}, [x5] /* get iv */ + dec_prepare w3, x2, x6 + +.LcbcdecloopNx: + subs w4, w4, #4 + bmi .Lcbcdec1x + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ + mov v4.16b, v0.16b + mov v5.16b, v1.16b + mov v6.16b, v2.16b + bl aes_decrypt_block4x + sub x1, x1, #16 + eor v0.16b, v0.16b, v7.16b + eor v1.16b, v1.16b, v4.16b + ld1 {v7.16b}, [x1], #16 /* reload 1 ct block */ + eor v2.16b, v2.16b, v5.16b + eor v3.16b, v3.16b, v6.16b + st1 {v0.16b-v3.16b}, [x0], #64 + b .LcbcdecloopNx +.Lcbcdec1x: + adds w4, w4, #4 + beq .Lcbcdecout +.Lcbcdecloop: + ld1 {v1.16b}, [x1], #16 /* get next ct block */ + mov v0.16b, v1.16b /* ...and copy to v0 */ + decrypt_block v0, w3, x2, x6, w7 + eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */ + mov v7.16b, v1.16b /* ct is next iv */ + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 + bne .Lcbcdecloop +.Lcbcdecout: + st1 {v7.16b}, [x5] /* return iv */ + ldp x29, x30, [sp], #16 + ret +END_FUNC ce_aes_cbc_decrypt + + + /* + * void ce_aes_ctr_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], int rounds, int blocks, + * uint8_t ctr[], int first) + */ +FUNC ce_aes_ctr_encrypt , : + stp x29, x30, [sp, #-16]! + mov x29, sp + + enc_prepare w3, x2, x6 + ld1 {v4.16b}, [x5] + + umov x6, v4.d[1] /* keep swabbed ctr in reg */ + rev x6, x6 + cmn w6, w4 /* 32 bit overflow? */ + bcs .Lctrloop +.LctrloopNx: + subs w4, w4, #4 + bmi .Lctr1x + add w7, w6, #1 + mov v0.16b, v4.16b + add w8, w6, #2 + mov v1.16b, v4.16b + add w9, w6, #3 + mov v2.16b, v4.16b + rev w7, w7 + mov v3.16b, v4.16b + rev w8, w8 + mov v1.s[3], w7 + rev w9, w9 + mov v2.s[3], w8 + mov v3.s[3], w9 + ld1 {v5.16b-v7.16b}, [x1], #48 /* get 3 input blocks */ + bl aes_encrypt_block4x + eor v0.16b, v5.16b, v0.16b + ld1 {v5.16b}, [x1], #16 /* get 1 input block */ + eor v1.16b, v6.16b, v1.16b + eor v2.16b, v7.16b, v2.16b + eor v3.16b, v5.16b, v3.16b + st1 {v0.16b-v3.16b}, [x0], #64 + add x6, x6, #4 + rev x7, x6 + ins v4.d[1], x7 + cbz w4, .Lctrout + b .LctrloopNx +.Lctr1x: + adds w4, w4, #4 + beq .Lctrout +.Lctrloop: + mov v0.16b, v4.16b + encrypt_block v0, w3, x2, x8, w7 + + adds x6, x6, #1 /* increment BE ctr */ + rev x7, x6 + ins v4.d[1], x7 + bcs .Lctrcarry /* overflow? */ + +.Lctrcarrydone: + subs w4, w4, #1 + bmi .Lctrtailblock /* blocks <0 means tail block */ + ld1 {v3.16b}, [x1], #16 + eor v3.16b, v0.16b, v3.16b + st1 {v3.16b}, [x0], #16 + bne .Lctrloop + +.Lctrout: + st1 {v4.16b}, [x5] /* return next CTR value */ + ldp x29, x30, [sp], #16 + ret + +.Lctrtailblock: + st1 {v0.16b}, [x0] + ldp x29, x30, [sp], #16 + ret + +.Lctrcarry: + umov x7, v4.d[0] /* load upper word of ctr */ + rev x7, x7 /* ... to handle the carry */ + add x7, x7, #1 + rev x7, x7 + ins v4.d[0], x7 + b .Lctrcarrydone +END_FUNC ce_aes_ctr_encrypt + + + .macro next_tweak, out, in, const, tmp + sshr \tmp\().2d, \in\().2d, #63 + and \tmp\().16b, \tmp\().16b, \const\().16b + add \out\().2d, \in\().2d, \in\().2d + ext \tmp\().16b, \tmp\().16b, \tmp\().16b, #8 + eor \out\().16b, \out\().16b, \tmp\().16b + .endm + + /* + * void ce_aes_xts_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk1[], int rounds, int blocks, + * uint8_t const rk2[], uint8_t iv[]) + */ +FUNC ce_aes_xts_encrypt , : + FRAME_PUSH + + ld1 {v4.16b}, [x6] + enc_prepare w3, x5, x6 + encrypt_block v4, w3, x5, x6, w7 /* first tweak */ + enc_switch_key w3, x2, x6 + ldr q7, .Lxts_mul_x + b .LxtsencNx + +.LxtsencloopNx: + ldr q7, .Lxts_mul_x + next_tweak v4, v4, v7, v8 +.LxtsencNx: +#if INTERLEAVE >= 2 + subs w4, w4, #INTERLEAVE + bmi .Lxtsenc1x +#if INTERLEAVE == 2 + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 pt blocks */ + next_tweak v5, v4, v7, v8 + eor v0.16b, v0.16b, v4.16b + eor v1.16b, v1.16b, v5.16b + do_encrypt_block2x + eor v0.16b, v0.16b, v4.16b + eor v1.16b, v1.16b, v5.16b + st1 {v0.16b-v1.16b}, [x0], #32 + cbz w4, .LxtsencoutNx + next_tweak v4, v5, v7, v8 + b .LxtsencNx +.LxtsencoutNx: + mov v4.16b, v5.16b + b .Lxtsencout +#else + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ + next_tweak v5, v4, v7, v8 + eor v0.16b, v0.16b, v4.16b + next_tweak v6, v5, v7, v8 + eor v1.16b, v1.16b, v5.16b + eor v2.16b, v2.16b, v6.16b + next_tweak v7, v6, v7, v8 + eor v3.16b, v3.16b, v7.16b + do_encrypt_block4x + eor v3.16b, v3.16b, v7.16b + eor v0.16b, v0.16b, v4.16b + eor v1.16b, v1.16b, v5.16b + eor v2.16b, v2.16b, v6.16b + st1 {v0.16b-v3.16b}, [x0], #64 + mov v4.16b, v7.16b + cbz w4, .Lxtsencout + b .LxtsencloopNx +#endif +.Lxtsenc1x: + adds w4, w4, #INTERLEAVE + beq .Lxtsencout +#endif +.Lxtsencloop: + ld1 {v1.16b}, [x1], #16 + eor v0.16b, v1.16b, v4.16b + encrypt_block v0, w3, x2, x6, w7 + eor v0.16b, v0.16b, v4.16b + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 + beq .Lxtsencout + next_tweak v4, v4, v7, v8 + b .Lxtsencloop +.Lxtsencout: + next_tweak v4, v4, v7, v8 + st1 {v4.16b}, [x6], #16 + FRAME_POP + ret + + .align 4 +.Lxts_mul_x: + .word 1, 0, 0x87, 0 +END_FUNC ce_aes_xts_encrypt + + /* + * void ce_aes_xts_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk1[], int rounds, int blocks, + * uint8_t const rk2[], uint8_t iv[]) + */ +FUNC ce_aes_xts_decrypt , : + FRAME_PUSH + + ld1 {v4.16b}, [x6] + enc_prepare w3, x5, x6 + encrypt_block v4, w3, x5, x6, w7 /* first tweak */ + dec_prepare w3, x2, x6 + ldr q7, .Lxts_mul_x + b .LxtsdecNx + +.LxtsdecloopNx: + ldr q7, .Lxts_mul_x + next_tweak v4, v4, v7, v8 +.LxtsdecNx: +#if INTERLEAVE >= 2 + subs w4, w4, #INTERLEAVE + bmi .Lxtsdec1x +#if INTERLEAVE == 2 + ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */ + next_tweak v5, v4, v7, v8 + eor v0.16b, v0.16b, v4.16b + eor v1.16b, v1.16b, v5.16b + do_decrypt_block2x + eor v0.16b, v0.16b, v4.16b + eor v1.16b, v1.16b, v5.16b + st1 {v0.16b-v1.16b}, [x0], #32 + cbz w4, .LxtsdecoutNx + next_tweak v4, v5, v7, v8 + b .LxtsdecNx +.LxtsdecoutNx: + mov v4.16b, v5.16b + b .Lxtsdecout +#else + ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ + next_tweak v5, v4, v7, v8 + eor v0.16b, v0.16b, v4.16b + next_tweak v6, v5, v7, v8 + eor v1.16b, v1.16b, v5.16b + eor v2.16b, v2.16b, v6.16b + next_tweak v7, v6, v7, v8 + eor v3.16b, v3.16b, v7.16b + do_decrypt_block4x + eor v3.16b, v3.16b, v7.16b + eor v0.16b, v0.16b, v4.16b + eor v1.16b, v1.16b, v5.16b + eor v2.16b, v2.16b, v6.16b + st1 {v0.16b-v3.16b}, [x0], #64 + mov v4.16b, v7.16b + cbz w4, .Lxtsdecout + b .LxtsdecloopNx +#endif +.Lxtsdec1x: + adds w4, w4, #INTERLEAVE + beq .Lxtsdecout +#endif +.Lxtsdecloop: + ld1 {v1.16b}, [x1], #16 + eor v0.16b, v1.16b, v4.16b + decrypt_block v0, w3, x2, x6, w7 + eor v0.16b, v0.16b, v4.16b + st1 {v0.16b}, [x0], #16 + subs w4, w4, #1 + beq .Lxtsdecout + next_tweak v4, v4, v7, v8 + b .Lxtsdecloop +.Lxtsdecout: + FRAME_POP + next_tweak v4, v4, v7, v8 + st1 {v4.16b}, [x6], #16 + ret +END_FUNC ce_aes_xts_decrypt + + /* + * void ce_aes_xor_block(uint8_t out[], uint8_t const op1[], + * uint8_t const op2[]); + */ +FUNC ce_aes_xor_block , : + ld1 {v0.16b}, [x1] + ld1 {v1.16b}, [x2] + eor v0.16b, v0.16b, v1.16b + st1 {v0.16b}, [x0] + ret +END_FUNC ce_aes_xor_block + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a32.S b/optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a32.S new file mode 100644 index 0000000..08d4665 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a32.S @@ -0,0 +1,241 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Accelerated GHASH implementation with ARMv8 PMULL instructions. + * + * Copyright (C) 2014 - 2017 Linaro Ltd. + */ + +#include +#include + +#define CPU_LE(x...) x + + SHASH .req q0 + T1 .req q1 + XL .req q2 + XM .req q3 + XH .req q4 + IN1 .req q4 + + SHASH_L .req d0 + SHASH_H .req d1 + T1_L .req d2 + T1_H .req d3 + XL_L .req d4 + XL_H .req d5 + XM_L .req d6 + XM_H .req d7 + XH_L .req d8 + + t0l .req d10 + t0h .req d11 + t1l .req d12 + t1h .req d13 + t2l .req d14 + t2h .req d15 + t3l .req d16 + t3h .req d17 + t4l .req d18 + t4h .req d19 + + t0q .req q5 + t1q .req q6 + t2q .req q7 + t3q .req q8 + t4q .req q9 + T2 .req q9 + + s1l .req d20 + s1h .req d21 + s2l .req d22 + s2h .req d23 + s3l .req d24 + s3h .req d25 + s4l .req d26 + s4h .req d27 + + MASK .req d28 + SHASH2_p8 .req d28 + + k16 .req d29 + k32 .req d30 + k48 .req d31 + SHASH2_p64 .req d31 + + .text + .fpu crypto-neon-fp-armv8 + + .macro __pmull_p64, rd, rn, rm, b1, b2, b3, b4 + vmull.p64 \rd, \rn, \rm + .endm + + /* + * This implementation of 64x64 -> 128 bit polynomial multiplication + * using vmull.p8 instructions (8x8 -> 16) is taken from the paper + * "Fast Software Polynomial Multiplication on ARM Processors Using + * the NEON Engine" by Danilo Camara, Conrado Gouvea, Julio Lopez and + * Ricardo Dahab (https://hal.inria.fr/hal-01506572) + * + * It has been slightly tweaked for in-order performance, and to allow + * 'rq' to overlap with 'ad' or 'bd'. + */ + .macro __pmull_p8, rq, ad, bd, b1=t4l, b2=t3l, b3=t4l, b4=t3l + vext.8 t0l, \ad, \ad, #1 @ A1 + .ifc \b1, t4l + vext.8 t4l, \bd, \bd, #1 @ B1 + .endif + vmull.p8 t0q, t0l, \bd @ F = A1*B + vext.8 t1l, \ad, \ad, #2 @ A2 + vmull.p8 t4q, \ad, \b1 @ E = A*B1 + .ifc \b2, t3l + vext.8 t3l, \bd, \bd, #2 @ B2 + .endif + vmull.p8 t1q, t1l, \bd @ H = A2*B + vext.8 t2l, \ad, \ad, #3 @ A3 + vmull.p8 t3q, \ad, \b2 @ G = A*B2 + veor t0q, t0q, t4q @ L = E + F + .ifc \b3, t4l + vext.8 t4l, \bd, \bd, #3 @ B3 + .endif + vmull.p8 t2q, t2l, \bd @ J = A3*B + veor t0l, t0l, t0h @ t0 = (L) (P0 + P1) << 8 + veor t1q, t1q, t3q @ M = G + H + .ifc \b4, t3l + vext.8 t3l, \bd, \bd, #4 @ B4 + .endif + vmull.p8 t4q, \ad, \b3 @ I = A*B3 + veor t1l, t1l, t1h @ t1 = (M) (P2 + P3) << 16 + vmull.p8 t3q, \ad, \b4 @ K = A*B4 + vand t0h, t0h, k48 + vand t1h, t1h, k32 + veor t2q, t2q, t4q @ N = I + J + veor t0l, t0l, t0h + veor t1l, t1l, t1h + veor t2l, t2l, t2h @ t2 = (N) (P4 + P5) << 24 + vand t2h, t2h, k16 + veor t3l, t3l, t3h @ t3 = (K) (P6 + P7) << 32 + vmov.i64 t3h, #0 + vext.8 t0q, t0q, t0q, #15 + veor t2l, t2l, t2h + vext.8 t1q, t1q, t1q, #14 + vmull.p8 \rq, \ad, \bd @ D = A*B + vext.8 t2q, t2q, t2q, #13 + vext.8 t3q, t3q, t3q, #12 + veor t0q, t0q, t1q + veor t2q, t2q, t3q + veor \rq, \rq, t0q + veor \rq, \rq, t2q + .endm + + // + // PMULL (64x64->128) based reduction for CPUs that can do + // it in a single instruction. + // + .macro __pmull_reduce_p64 + vmull.p64 T1, XL_L, MASK + + veor XH_L, XH_L, XM_H + vext.8 T1, T1, T1, #8 + veor XL_H, XL_H, XM_L + veor T1, T1, XL + + vmull.p64 XL, T1_H, MASK + .endm + + // + // Alternative reduction for CPUs that lack support for the + // 64x64->128 PMULL instruction + // + .macro __pmull_reduce_p8 + veor XL_H, XL_H, XM_L + veor XH_L, XH_L, XM_H + + vshl.i64 T1, XL, #57 + vshl.i64 T2, XL, #62 + veor T1, T1, T2 + vshl.i64 T2, XL, #63 + veor T1, T1, T2 + veor XL_H, XL_H, T1_L + veor XH_L, XH_L, T1_H + + vshr.u64 T1, XL, #1 + veor XH, XH, XL + veor XL, XL, T1 + vshr.u64 T1, T1, #6 + vshr.u64 XL, XL, #1 + .endm + + .macro ghash_update, pn + vld1.64 {XL}, [r1] + + /* do the head block first, if supplied */ + ldr ip, [sp] + teq ip, #0 + beq 0f + vld1.8 {T1}, [ip] + teq r0, #0 + b 1f + +0: vld1.8 {T1}, [r2]! + subs r0, r0, #1 + +1: /* multiply XL by SHASH in GF(2^128) */ +#ifndef CONFIG_CPU_BIG_ENDIAN + vrev64.8 T1, T1 +#endif + vext.8 IN1, T1, T1, #8 + veor T1_L, T1_L, XL_H + veor XL, XL, IN1 + + __pmull_\pn XH, XL_H, SHASH_H, s1h, s2h, s3h, s4h @ a1 * b1 + veor T1, T1, XL + __pmull_\pn XL, XL_L, SHASH_L, s1l, s2l, s3l, s4l @ a0 * b0 + __pmull_\pn XM, T1_L, SHASH2_\pn @ (a1+a0)(b1+b0) + + veor T1, XL, XH + veor XM, XM, T1 + + __pmull_reduce_\pn + + veor T1, T1, XH + veor XL, XL, T1 + + bne 0b + + vst1.64 {XL}, [r1] + bx lr + .endm + + /* + * void pmull_ghash_update(int blocks, u64 dg[], const char *src, + * struct ghash_key const *k, const char *head) + */ +FUNC pmull_ghash_update_p64 , : + vld1.64 {SHASH}, [r3] + veor SHASH2_p64, SHASH_L, SHASH_H + + vmov.i8 MASK, #0xe1 + vshl.u64 MASK, MASK, #57 + + ghash_update p64 +END_FUNC pmull_ghash_update_p64 + +FUNC pmull_ghash_update_p8 , : + vld1.64 {SHASH}, [r3] + veor SHASH2_p8, SHASH_L, SHASH_H + + vext.8 s1l, SHASH_L, SHASH_L, #1 + vext.8 s2l, SHASH_L, SHASH_L, #2 + vext.8 s3l, SHASH_L, SHASH_L, #3 + vext.8 s4l, SHASH_L, SHASH_L, #4 + vext.8 s1h, SHASH_H, SHASH_H, #1 + vext.8 s2h, SHASH_H, SHASH_H, #2 + vext.8 s3h, SHASH_H, SHASH_H, #3 + vext.8 s4h, SHASH_H, SHASH_H, #4 + + vmov.i64 k16, #0xffff + vmov.i64 k32, #0xffffffff + vmov.i64 k48, #0xffffffffffff + + ghash_update p8 +END_FUNC pmull_ghash_update_p8 diff --git a/optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S b/optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S new file mode 100644 index 0000000..dc86132 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/ghash-ce-core_a64.S @@ -0,0 +1,650 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020 Linaro Limited + * Copyright (C) 2014 - 2017 Linaro Ltd. + * + * Accelerated GHASH implementation with ARMv8 PMULL instructions. + */ + +#include +#include +#define CPU_LE(x...) x + +/* + * If the lower half of CTR is initialized with zeroes or a low value we + * can expect that the upper half will remain unchanged. As an optimization + * make the code to increase the upper half optional. + */ +#define INC_HALF_CTR 0 + + SHASH .req v0 + SHASH2 .req v1 + T1 .req v2 + T2 .req v3 + MASK .req v4 + XL .req v5 + XM .req v6 + XH .req v7 + IN1 .req v7 + + k00_16 .req v8 + k32_48 .req v9 + + t3 .req v10 + t4 .req v11 + t5 .req v12 + t6 .req v13 + t7 .req v14 + t8 .req v15 + t9 .req v16 + + perm1 .req v17 + perm2 .req v18 + perm3 .req v19 + + sh1 .req v20 + sh2 .req v21 + sh3 .req v22 + sh4 .req v23 + + ss1 .req v24 + ss2 .req v25 + ss3 .req v26 + ss4 .req v27 + + XL2 .req v8 + XM2 .req v9 + XH2 .req v10 + XL3 .req v11 + XM3 .req v12 + XH3 .req v13 + TT3 .req v14 + TT4 .req v15 + HH .req v16 + HH3 .req v17 + HH4 .req v18 + HH34 .req v19 + + .arch armv8-a+crypto + + .macro __pmull_p64, rd, rn, rm + pmull \rd\().1q, \rn\().1d, \rm\().1d + .endm + + .macro __pmull2_p64, rd, rn, rm + pmull2 \rd\().1q, \rn\().2d, \rm\().2d + .endm + + .macro __pmull_p8, rq, ad, bd + ext t3.8b, \ad\().8b, \ad\().8b, #1 // A1 + ext t5.8b, \ad\().8b, \ad\().8b, #2 // A2 + ext t7.8b, \ad\().8b, \ad\().8b, #3 // A3 + + __pmull_p8_\bd \rq, \ad + .endm + + .macro __pmull2_p8, rq, ad, bd + tbl t3.16b, {\ad\().16b}, perm1.16b // A1 + tbl t5.16b, {\ad\().16b}, perm2.16b // A2 + tbl t7.16b, {\ad\().16b}, perm3.16b // A3 + + __pmull2_p8_\bd \rq, \ad + .endm + + .macro __pmull_p8_SHASH, rq, ad + __pmull_p8_tail \rq, \ad\().8b, SHASH.8b, 8b,, sh1, sh2, sh3, sh4 + .endm + + .macro __pmull_p8_SHASH2, rq, ad + __pmull_p8_tail \rq, \ad\().8b, SHASH2.8b, 8b,, ss1, ss2, ss3, ss4 + .endm + + .macro __pmull2_p8_SHASH, rq, ad + __pmull_p8_tail \rq, \ad\().16b, SHASH.16b, 16b, 2, sh1, sh2, sh3, sh4 + .endm + + .macro __pmull_p8_tail, rq, ad, bd, nb, t, b1, b2, b3, b4 + pmull\t t3.8h, t3.\nb, \bd // F = A1*B + pmull\t t4.8h, \ad, \b1\().\nb // E = A*B1 + pmull\t t5.8h, t5.\nb, \bd // H = A2*B + pmull\t t6.8h, \ad, \b2\().\nb // G = A*B2 + pmull\t t7.8h, t7.\nb, \bd // J = A3*B + pmull\t t8.8h, \ad, \b3\().\nb // I = A*B3 + pmull\t t9.8h, \ad, \b4\().\nb // K = A*B4 + pmull\t \rq\().8h, \ad, \bd // D = A*B + + eor t3.16b, t3.16b, t4.16b // L = E + F + eor t5.16b, t5.16b, t6.16b // M = G + H + eor t7.16b, t7.16b, t8.16b // N = I + J + + uzp1 t4.2d, t3.2d, t5.2d + uzp2 t3.2d, t3.2d, t5.2d + uzp1 t6.2d, t7.2d, t9.2d + uzp2 t7.2d, t7.2d, t9.2d + + // t3 = (L) (P0 + P1) << 8 + // t5 = (M) (P2 + P3) << 16 + eor t4.16b, t4.16b, t3.16b + and t3.16b, t3.16b, k32_48.16b + + // t7 = (N) (P4 + P5) << 24 + // t9 = (K) (P6 + P7) << 32 + eor t6.16b, t6.16b, t7.16b + and t7.16b, t7.16b, k00_16.16b + + eor t4.16b, t4.16b, t3.16b + eor t6.16b, t6.16b, t7.16b + + zip2 t5.2d, t4.2d, t3.2d + zip1 t3.2d, t4.2d, t3.2d + zip2 t9.2d, t6.2d, t7.2d + zip1 t7.2d, t6.2d, t7.2d + + ext t3.16b, t3.16b, t3.16b, #15 + ext t5.16b, t5.16b, t5.16b, #14 + ext t7.16b, t7.16b, t7.16b, #13 + ext t9.16b, t9.16b, t9.16b, #12 + + eor t3.16b, t3.16b, t5.16b + eor t7.16b, t7.16b, t9.16b + eor \rq\().16b, \rq\().16b, t3.16b + eor \rq\().16b, \rq\().16b, t7.16b + .endm + + .macro __pmull_pre_p64 + add x8, x3, #16 + ld1 {HH.2d-HH4.2d}, [x8] + + trn1 SHASH2.2d, SHASH.2d, HH.2d + trn2 T1.2d, SHASH.2d, HH.2d + eor SHASH2.16b, SHASH2.16b, T1.16b + + trn1 HH34.2d, HH3.2d, HH4.2d + trn2 T1.2d, HH3.2d, HH4.2d + eor HH34.16b, HH34.16b, T1.16b + + movi MASK.16b, #0xe1 + shl MASK.2d, MASK.2d, #57 + .endm + + .macro __pmull_pre_p8 + ext SHASH2.16b, SHASH.16b, SHASH.16b, #8 + eor SHASH2.16b, SHASH2.16b, SHASH.16b + + // k00_16 := 0x0000000000000000_000000000000ffff + // k32_48 := 0x00000000ffffffff_0000ffffffffffff + movi k32_48.2d, #0xffffffff + mov k32_48.h[2], k32_48.h[0] + ushr k00_16.2d, k32_48.2d, #32 + + // prepare the permutation vectors + mov_imm x5, 0x080f0e0d0c0b0a09 + movi T1.8b, #8 + dup perm1.2d, x5 + eor perm1.16b, perm1.16b, T1.16b + ushr perm2.2d, perm1.2d, #8 + ushr perm3.2d, perm1.2d, #16 + ushr T1.2d, perm1.2d, #24 + sli perm2.2d, perm1.2d, #56 + sli perm3.2d, perm1.2d, #48 + sli T1.2d, perm1.2d, #40 + + // precompute loop invariants + tbl sh1.16b, {SHASH.16b}, perm1.16b + tbl sh2.16b, {SHASH.16b}, perm2.16b + tbl sh3.16b, {SHASH.16b}, perm3.16b + tbl sh4.16b, {SHASH.16b}, T1.16b + ext ss1.8b, SHASH2.8b, SHASH2.8b, #1 + ext ss2.8b, SHASH2.8b, SHASH2.8b, #2 + ext ss3.8b, SHASH2.8b, SHASH2.8b, #3 + ext ss4.8b, SHASH2.8b, SHASH2.8b, #4 + .endm + + // + // PMULL (64x64->128) based reduction for CPUs that can do + // it in a single instruction. + // + .macro __pmull_reduce_p64 + pmull T2.1q, XL.1d, MASK.1d + eor XM.16b, XM.16b, T1.16b + + mov XH.d[0], XM.d[1] + mov XM.d[1], XL.d[0] + + eor XL.16b, XM.16b, T2.16b + ext T2.16b, XL.16b, XL.16b, #8 + pmull XL.1q, XL.1d, MASK.1d + .endm + + // + // Alternative reduction for CPUs that lack support for the + // 64x64->128 PMULL instruction + // + .macro __pmull_reduce_p8 + eor XM.16b, XM.16b, T1.16b + + mov XL.d[1], XM.d[0] + mov XH.d[0], XM.d[1] + + shl T1.2d, XL.2d, #57 + shl T2.2d, XL.2d, #62 + eor T2.16b, T2.16b, T1.16b + shl T1.2d, XL.2d, #63 + eor T2.16b, T2.16b, T1.16b + ext T1.16b, XL.16b, XH.16b, #8 + eor T2.16b, T2.16b, T1.16b + + mov XL.d[1], T2.d[0] + mov XH.d[0], T2.d[1] + + ushr T2.2d, XL.2d, #1 + eor XH.16b, XH.16b, XL.16b + eor XL.16b, XL.16b, T2.16b + ushr T2.2d, T2.2d, #6 + ushr XL.2d, XL.2d, #1 + .endm + + .macro __pmull_ghash, pn + ld1 {SHASH.2d}, [x3] + ld1 {XL.2d}, [x1] + + __pmull_pre_\pn + + /* do the head block first, if supplied */ + cbz x4, 0f + ld1 {T1.16b}, [x4] + mov x4, xzr + b 3f + +0: .ifc \pn, p64 + tbnz w0, #0, 2f // skip until #blocks is a + tbnz w0, #1, 2f // round multiple of 4 + +1: ld1 {XM3.16b-TT4.16b}, [x2], #64 + + sub w0, w0, #4 + + rev64 T1.16b, XM3.16b + rev64 T2.16b, XH3.16b + rev64 TT4.16b, TT4.16b + rev64 TT3.16b, TT3.16b + + ext IN1.16b, TT4.16b, TT4.16b, #8 + ext XL3.16b, TT3.16b, TT3.16b, #8 + + eor TT4.16b, TT4.16b, IN1.16b + pmull2 XH2.1q, SHASH.2d, IN1.2d // a1 * b1 + pmull XL2.1q, SHASH.1d, IN1.1d // a0 * b0 + pmull XM2.1q, SHASH2.1d, TT4.1d // (a1 + a0)(b1 + b0) + + eor TT3.16b, TT3.16b, XL3.16b + pmull2 XH3.1q, HH.2d, XL3.2d // a1 * b1 + pmull XL3.1q, HH.1d, XL3.1d // a0 * b0 + pmull2 XM3.1q, SHASH2.2d, TT3.2d // (a1 + a0)(b1 + b0) + + ext IN1.16b, T2.16b, T2.16b, #8 + eor XL2.16b, XL2.16b, XL3.16b + eor XH2.16b, XH2.16b, XH3.16b + eor XM2.16b, XM2.16b, XM3.16b + + eor T2.16b, T2.16b, IN1.16b + pmull2 XH3.1q, HH3.2d, IN1.2d // a1 * b1 + pmull XL3.1q, HH3.1d, IN1.1d // a0 * b0 + pmull XM3.1q, HH34.1d, T2.1d // (a1 + a0)(b1 + b0) + + eor XL2.16b, XL2.16b, XL3.16b + eor XH2.16b, XH2.16b, XH3.16b + eor XM2.16b, XM2.16b, XM3.16b + + ext IN1.16b, T1.16b, T1.16b, #8 + ext TT3.16b, XL.16b, XL.16b, #8 + eor XL.16b, XL.16b, IN1.16b + eor T1.16b, T1.16b, TT3.16b + + pmull2 XH.1q, HH4.2d, XL.2d // a1 * b1 + eor T1.16b, T1.16b, XL.16b + pmull XL.1q, HH4.1d, XL.1d // a0 * b0 + pmull2 XM.1q, HH34.2d, T1.2d // (a1 + a0)(b1 + b0) + + eor XL.16b, XL.16b, XL2.16b + eor XH.16b, XH.16b, XH2.16b + eor XM.16b, XM.16b, XM2.16b + + eor T2.16b, XL.16b, XH.16b + ext T1.16b, XL.16b, XH.16b, #8 + eor XM.16b, XM.16b, T2.16b + + __pmull_reduce_p64 + + eor T2.16b, T2.16b, XH.16b + eor XL.16b, XL.16b, T2.16b + + cbz w0, 5f + b 1b + .endif + +2: ld1 {T1.16b}, [x2], #16 + sub w0, w0, #1 + +3: /* multiply XL by SHASH in GF(2^128) */ +CPU_LE( rev64 T1.16b, T1.16b ) + + ext T2.16b, XL.16b, XL.16b, #8 + ext IN1.16b, T1.16b, T1.16b, #8 + eor T1.16b, T1.16b, T2.16b + eor XL.16b, XL.16b, IN1.16b + + __pmull2_\pn XH, XL, SHASH // a1 * b1 + eor T1.16b, T1.16b, XL.16b + __pmull_\pn XL, XL, SHASH // a0 * b0 + __pmull_\pn XM, T1, SHASH2 // (a1 + a0)(b1 + b0) + +4: eor T2.16b, XL.16b, XH.16b + ext T1.16b, XL.16b, XH.16b, #8 + eor XM.16b, XM.16b, T2.16b + + __pmull_reduce_\pn + + eor T2.16b, T2.16b, XH.16b + eor XL.16b, XL.16b, T2.16b + + cbnz w0, 0b + +5: st1 {XL.2d}, [x1] + ret + .endm + +/* + * void pmull_ghash_update_p64(int blocks, uint64_t dg[2], const uint8_t *src, + * const struct internal_ghash_key *ghash_key, + * const uint8_t *head); + */ +FUNC pmull_ghash_update_p64 , : + __pmull_ghash p64 +END_FUNC pmull_ghash_update_p64 + +/* + * void pmull_ghash_update_p8(int blocks, uint64_t dg[2], const uint8_t *src, + * const struct internal_ghash_key *ghash_key, + * const uint8_t *head); + */ +FUNC pmull_ghash_update_p8 , : + __pmull_ghash p8 +END_FUNC pmull_ghash_update_p8 + + KS0 .req v12 + KS1 .req v13 + INP0 .req v14 + INP1 .req v15 + + .macro load_round_keys, rounds, rk + cmp \rounds, #12 + blo 2222f /* 128 bits */ + beq 1111f /* 192 bits */ + ld1 {v17.4s-v18.4s}, [\rk], #32 +1111: ld1 {v19.4s-v20.4s}, [\rk], #32 +2222: ld1 {v21.4s-v24.4s}, [\rk], #64 + ld1 {v25.4s-v28.4s}, [\rk], #64 + ld1 {v29.4s-v31.4s}, [\rk] + .endm + + .macro enc_round, state, key + aese \state\().16b, \key\().16b + aesmc \state\().16b, \state\().16b + .endm + + .macro enc_block, state, rounds + cmp \rounds, #12 + b.lo 2222f /* 128 bits */ + b.eq 1111f /* 192 bits */ + enc_round \state, v17 + enc_round \state, v18 +1111: enc_round \state, v19 + enc_round \state, v20 +2222: .irp key, v21, v22, v23, v24, v25, v26, v27, v28, v29 + enc_round \state, \key + .endr + aese \state\().16b, v30.16b + eor \state\().16b, \state\().16b, v31.16b + .endm + + .macro pmull_gcm_do_crypt, enc + ld1 {SHASH.2d}, [x4], #16 + ld1 {HH.2d}, [x4] + ld1 {XL.2d}, [x1] +#if INC_HALF_CTR + ldr x8, [x5, #8] // load lower counter +#else + ldp x9, x8, [x5] // load counter +#endif + + movi MASK.16b, #0xe1 + trn1 SHASH2.2d, SHASH.2d, HH.2d + trn2 T1.2d, SHASH.2d, HH.2d +CPU_LE( rev x8, x8 ) +#if !INC_HALF_CTR +CPU_LE( rev x9, x9 ) +#endif + shl MASK.2d, MASK.2d, #57 + eor SHASH2.16b, SHASH2.16b, T1.16b + + .if \enc == 1 + ldr x10, [sp] + ld1 {KS0.16b-KS1.16b}, [x10] + .endif + + cbnz x6, 4f + +0: ld1 {INP0.16b-INP1.16b}, [x3], #32 + +#if INC_HALF_CTR + rev x9, x8 + add x11, x8, #1 + add x8, x8, #2 +#endif + + .if \enc == 1 + eor INP0.16b, INP0.16b, KS0.16b // encrypt input + eor INP1.16b, INP1.16b, KS1.16b + .endif + + sub w0, w0, #2 + +#if INC_HALF_CTR + ld1 {KS0.8b}, [x5] // load upper counter + rev x11, x11 + mov KS1.8b, KS0.8b + ins KS0.d[1], x9 // set lower counter + ins KS1.d[1], x11 +#else + ins KS0.d[1], x8 + ins KS0.d[0], x9 + rev64 KS0.16b, KS0.16b + + add x8, x8, #1 + cbnz x8, 10f + add x9, x9, #1 +10: + ins KS1.d[1], x8 + ins KS1.d[0], x9 + rev64 KS1.16b, KS1.16b + + add x8, x8, #1 + cbnz x8, 11f + add x9, x9, #1 +11: +#endif + + rev64 T1.16b, INP1.16b + + cmp w7, #12 + b.ge 2f // AES-192/256? + +1: enc_round KS0, v21 + ext IN1.16b, T1.16b, T1.16b, #8 + + enc_round KS1, v21 + pmull2 XH2.1q, SHASH.2d, IN1.2d // a1 * b1 + + enc_round KS0, v22 + eor T1.16b, T1.16b, IN1.16b + + enc_round KS1, v22 + pmull XL2.1q, SHASH.1d, IN1.1d // a0 * b0 + + enc_round KS0, v23 + pmull XM2.1q, SHASH2.1d, T1.1d // (a1 + a0)(b1 + b0) + + enc_round KS1, v23 + rev64 T1.16b, INP0.16b + ext T2.16b, XL.16b, XL.16b, #8 + + enc_round KS0, v24 + ext IN1.16b, T1.16b, T1.16b, #8 + eor T1.16b, T1.16b, T2.16b + + enc_round KS1, v24 + eor XL.16b, XL.16b, IN1.16b + + enc_round KS0, v25 + eor T1.16b, T1.16b, XL.16b + + enc_round KS1, v25 + pmull2 XH.1q, HH.2d, XL.2d // a1 * b1 + + enc_round KS0, v26 + pmull XL.1q, HH.1d, XL.1d // a0 * b0 + + enc_round KS1, v26 + pmull2 XM.1q, SHASH2.2d, T1.2d // (a1 + a0)(b1 + b0) + + enc_round KS0, v27 + eor XL.16b, XL.16b, XL2.16b + eor XH.16b, XH.16b, XH2.16b + + enc_round KS1, v27 + eor XM.16b, XM.16b, XM2.16b + ext T1.16b, XL.16b, XH.16b, #8 + + enc_round KS0, v28 + eor T2.16b, XL.16b, XH.16b + eor XM.16b, XM.16b, T1.16b + + enc_round KS1, v28 + eor XM.16b, XM.16b, T2.16b + + enc_round KS0, v29 + pmull T2.1q, XL.1d, MASK.1d + + enc_round KS1, v29 + mov XH.d[0], XM.d[1] + mov XM.d[1], XL.d[0] + + aese KS0.16b, v30.16b + eor XL.16b, XM.16b, T2.16b + + aese KS1.16b, v30.16b + ext T2.16b, XL.16b, XL.16b, #8 + + eor KS0.16b, KS0.16b, v31.16b + pmull XL.1q, XL.1d, MASK.1d + eor T2.16b, T2.16b, XH.16b + + eor KS1.16b, KS1.16b, v31.16b + eor XL.16b, XL.16b, T2.16b + + .if \enc == 0 + eor INP0.16b, INP0.16b, KS0.16b + eor INP1.16b, INP1.16b, KS1.16b + .endif + + st1 {INP0.16b-INP1.16b}, [x2], #32 + + cbnz w0, 0b + +CPU_LE( rev x8, x8 ) +#if !INC_HALF_CTR +CPU_LE( rev x9, x9 ) +#endif + st1 {XL.2d}, [x1] +#if INC_HALF_CTR + str x8, [x5, #8] // store lower counter +#else + stp x9, x8, [x5] // store counter +#endif + + .if \enc == 1 + st1 {KS0.16b-KS1.16b}, [x10] + .endif + + ret + +2: b.eq 3f // AES-192? + enc_round KS0, v17 + enc_round KS1, v17 + enc_round KS0, v18 + enc_round KS1, v18 +3: enc_round KS0, v19 + enc_round KS1, v19 + enc_round KS0, v20 + enc_round KS1, v20 + b 1b + +4: load_round_keys w7, x6 + b 0b + .endm + +/* + * void pmull_gcm_encrypt(int blocks, uint64_t dg[2], uint8_t dst[], + * const uint8_t src[], + * const struct internal_ghash_key *ghash_key, + * uint64_t ctr[], const uint64_t rk[], int rounds, + * uint8_t ks[]); + */ +FUNC pmull_gcm_encrypt , : + pmull_gcm_do_crypt 1 +END_FUNC pmull_gcm_encrypt + +/* + * void pmull_gcm_decrypt(int blocks, uint64_t dg[2], uint8_t dst[], + * const uint8_t src[], + * const struct internal_ghash_key *ghash_key, + * uint64_t ctr[], const uint64_t rk[], int rounds); + */ +FUNC pmull_gcm_decrypt , : + pmull_gcm_do_crypt 0 +END_FUNC pmull_gcm_decrypt + +/* + * void pmull_gcm_encrypt_block(uint8_t dst[], const uint8_t src[], int rounds) + */ +FUNC pmull_gcm_encrypt_block , : + ld1 {v0.16b}, [x1] + enc_block v0, w2 + st1 {v0.16b}, [x0] + ret +END_FUNC pmull_gcm_encrypt_block + +/* + * void pmull_gcm_load_round_keys(const uint64_t rk[30], int rounds) + */ +FUNC pmull_gcm_load_round_keys , : + load_round_keys w1, x0 + ret +END_FUNC pmull_gcm_load_round_keys + +/* + * uint32_t pmull_gcm_aes_sub(uint32_t input) + * + * use the aese instruction to perform the AES sbox substitution + * on each byte in 'input' + */ +FUNC pmull_gcm_aes_sub , : + dup v1.4s, w0 + movi v0.16b, #0 + aese v0.16b, v1.16b + umov w0, v0.s[0] + ret +END_FUNC pmull_gcm_aes_sub + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce.c b/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce.c new file mode 100644 index 0000000..4689ce0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include + +/* Prototype for assembly function */ +void sha1_ce_transform(uint32_t state[5], const void *src, + unsigned int block_count); + +void crypto_accel_sha1_compress(uint32_t state[5], const void *src, + unsigned int block_count) +{ + uint32_t vfp_state = 0; + + vfp_state = thread_kernel_enable_vfp(); + sha1_ce_transform(state, src, block_count); + thread_kernel_disable_vfp(vfp_state); +} diff --git a/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a32.S b/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a32.S new file mode 100644 index 0000000..0c75821 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a32.S @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2020, Linaro Limited + */ + +/* SHA-1 secure hash using ARMv8 Crypto Extensions */ + +#include + + .fpu crypto-neon-fp-armv8 + + k0 .req q0 + k1 .req q1 + k2 .req q2 + k3 .req q3 + + ta0 .req q4 + ta1 .req q5 + tb0 .req q5 + tb1 .req q4 + + dga .req q6 + dgb .req q7 + dgbs .req s28 + + dg0 .req q12 + + dg1a0 .req q13 + dg1a1 .req q14 + dg1b0 .req q14 + dg1b1 .req q13 + + .macro add_only, op, ev, rc, s0, dg1 + .ifnb \s0 + vadd.u32 tb\ev, q\s0, \rc + .endif + sha1h.32 dg1b\ev, dg0 + .ifb \dg1 + sha1\op\().32 dg0, dg1a\ev, ta\ev + .else + sha1\op\().32 dg0, \dg1, ta\ev + .endif + .endm + + .macro add_update, op, ev, rc, s0, s1, s2, s3, dg1 + sha1su0.32 q\s0, q\s1, q\s2 + add_only \op, \ev, \rc, \s1, \dg1 + sha1su1.32 q\s0, q\s3 + .endm + + +FUNC sha1_ce_transform , : + /* load round constants */ + adr r3, .Lsha1_rcon + vld1.32 {k0-k1}, [r3]! + vld1.32 {k2-k3}, [r3] + + /* load state */ + vld1.32 {dga}, [r0] + vldr dgbs, [r0, #16] + +0: /* load input */ + vld1.8 {q8-q9}, [r1]! + vrev32.8 q8, q8 + vrev32.8 q9, q9 + vld1.8 {q10-q11}, [r1]! + vrev32.8 q10, q10 + vrev32.8 q11, q11 + subs r2, r2, #1 + + vadd.u32 ta0, q8, k0 + vmov dg0, dga + + add_update c, 0, k0, 8, 9, 10, 11, dgb + add_update c, 1, k0, 9, 10, 11, 8 + add_update c, 0, k0, 10, 11, 8, 9 + add_update c, 1, k0, 11, 8, 9, 10 + add_update c, 0, k1, 8, 9, 10, 11 + + add_update p, 1, k1, 9, 10, 11, 8 + add_update p, 0, k1, 10, 11, 8, 9 + add_update p, 1, k1, 11, 8, 9, 10 + add_update p, 0, k1, 8, 9, 10, 11 + add_update p, 1, k2, 9, 10, 11, 8 + + add_update m, 0, k2, 10, 11, 8, 9 + add_update m, 1, k2, 11, 8, 9, 10 + add_update m, 0, k2, 8, 9, 10, 11 + add_update m, 1, k2, 9, 10, 11, 8 + add_update m, 0, k3, 10, 11, 8, 9 + + add_update p, 1, k3, 11, 8, 9, 10 + add_only p, 0, k3, 9 + add_only p, 1, k3, 10 + add_only p, 0, k3, 11 + add_only p, 1 + + /* update state */ + vadd.u32 dga, dga, dg0 + vadd.u32 dgb, dgb, dg1a0 + bne 0b + + /* store new state */ + vst1.32 {dga}, [r0] + vstr dgbs, [r0, #16] + bx lr + + .align 4 +.Lsha1_rcon: + .word 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999 + .word 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1 + .word 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc + .word 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6 +END_FUNC sha1_ce_transform diff --git a/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a64.S b/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a64.S new file mode 100644 index 0000000..b8ed17f --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha1_armv8a_ce_a64.S @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2020, Linaro Limited + * Copyright (C) 2014 Linaro Ltd + */ + + /* SHA-1 secure hash using ARMv8 Crypto Extensions */ + +#include + + .arch armv8-a+crypto + + k0 .req v0 + k1 .req v1 + k2 .req v2 + k3 .req v3 + + t0 .req v4 + t1 .req v5 + + dga .req q6 + dgav .req v6 + dgb .req s7 + dgbv .req v7 + + dg0q .req q12 + dg0s .req s12 + dg0v .req v12 + dg1s .req s13 + dg1v .req v13 + dg2s .req s14 + + .macro add_only, op, ev, rc, s0, dg1 + .ifc \ev, ev + add t1.4s, v\s0\().4s, \rc\().4s + sha1h dg2s, dg0s + .ifnb \dg1 + sha1\op dg0q, \dg1, t0.4s + .else + sha1\op dg0q, dg1s, t0.4s + .endif + .else + .ifnb \s0 + add t0.4s, v\s0\().4s, \rc\().4s + .endif + sha1h dg1s, dg0s + sha1\op dg0q, dg2s, t1.4s + .endif + .endm + + .macro add_update, op, ev, rc, s0, s1, s2, s3, dg1 + sha1su0 v\s0\().4s, v\s1\().4s, v\s2\().4s + add_only \op, \ev, \rc, \s1, \dg1 + sha1su1 v\s0\().4s, v\s3\().4s + .endm + + /* + * void sha1_ce_transform(u32 state[5], u8 const *src, int blocks) + */ +FUNC sha1_ce_transform , : + /* load round constants */ + adr x6, .Lsha1_rcon + ld1r {k0.4s}, [x6], #4 + ld1r {k1.4s}, [x6], #4 + ld1r {k2.4s}, [x6], #4 + ld1r {k3.4s}, [x6] + + /* load state */ + ld1 {dgav.4s}, [x0] + ldr dgb, [x0, #16] + + /* load input */ +0: ld1 {v8.16b-v11.16b}, [x1], #64 + sub w2, w2, #1 + + rev32 v8.16b, v8.16b + rev32 v9.16b, v9.16b + rev32 v10.16b, v10.16b + rev32 v11.16b, v11.16b + +1: add t0.4s, v8.4s, k0.4s + mov dg0v.16b, dgav.16b + + add_update c, ev, k0, 8, 9, 10, 11, dgb + add_update c, od, k0, 9, 10, 11, 8 + add_update c, ev, k0, 10, 11, 8, 9 + add_update c, od, k0, 11, 8, 9, 10 + add_update c, ev, k1, 8, 9, 10, 11 + + add_update p, od, k1, 9, 10, 11, 8 + add_update p, ev, k1, 10, 11, 8, 9 + add_update p, od, k1, 11, 8, 9, 10 + add_update p, ev, k1, 8, 9, 10, 11 + add_update p, od, k2, 9, 10, 11, 8 + + add_update m, ev, k2, 10, 11, 8, 9 + add_update m, od, k2, 11, 8, 9, 10 + add_update m, ev, k2, 8, 9, 10, 11 + add_update m, od, k2, 9, 10, 11, 8 + add_update m, ev, k3, 10, 11, 8, 9 + + add_update p, od, k3, 11, 8, 9, 10 + add_only p, ev, k3, 9 + add_only p, od, k3, 10 + add_only p, ev, k3, 11 + add_only p, od + + /* update state */ + add dgbv.2s, dgbv.2s, dg1v.2s + add dgav.4s, dgav.4s, dg0v.4s + + cbnz w2, 0b + + /* store new state */ +3: st1 {dgav.4s}, [x0] + str dgb, [x0, #16] + ret + + /* The SHA1 round constants */ + .align 4 +.Lsha1_rcon: + .word 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 +END_FUNC sha1_ce_transform + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce.c b/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce.c new file mode 100644 index 0000000..6114d85 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include + +/* Prototype for assembly function */ +void sha256_ce_transform(uint32_t state[8], const void *src, + unsigned int block_count); + +void crypto_accel_sha256_compress(uint32_t state[8], const void *src, + unsigned int block_count) +{ + uint32_t vfp_state = 0; + + vfp_state = thread_kernel_enable_vfp(); + sha256_ce_transform(state, src, block_count); + thread_kernel_disable_vfp(vfp_state); +} diff --git a/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a32.S b/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a32.S new file mode 100644 index 0000000..ccad7a9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a32.S @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2020, Linaro Limited + */ + +/* SHA-256 secure hash using ARMv8 Crypto Extensions */ + +#include + + .fpu crypto-neon-fp-armv8 + + k0 .req q7 + k1 .req q8 + + ta0 .req q9 + ta1 .req q10 + tb0 .req q10 + tb1 .req q9 + + dga .req q11 + dgb .req q12 + + dg0 .req q13 + dg1 .req q14 + dg2 .req q15 + + .macro add_only, ev, s0 + vmov dg2, dg0 + .ifnb \s0 + vld1.32 {k\ev}, [r3]! + .endif + sha256h.32 dg0, dg1, tb\ev + sha256h2.32 dg1, dg2, tb\ev + .ifnb \s0 + vadd.u32 ta\ev, q\s0, k\ev + .endif + .endm + + .macro add_update, ev, s0, s1, s2, s3 + sha256su0.32 q\s0, q\s1 + add_only \ev, \s1 + sha256su1.32 q\s0, q\s2, q\s3 + .endm + + +FUNC sha256_ce_transform , : + /* load state */ + vld1.8 {dga-dgb}, [r0] + + /* load input */ +0: vld1.8 {q0-q1}, [r1]! + vrev32.8 q0, q0 + vrev32.8 q1, q1 + vld1.8 {q2-q3}, [r1]! + vrev32.8 q2, q2 + vrev32.8 q3, q3 + subs r2, r2, #1 + + /* load round constants */ + adr r3, .Lsha256_rcon + vld1.32 {k0}, [r3]! + + vadd.u32 ta0, q0, k0 + vmov dg0, dga + vmov dg1, dgb + + add_update 1, 0, 1, 2, 3 + add_update 0, 1, 2, 3, 0 + add_update 1, 2, 3, 0, 1 + add_update 0, 3, 0, 1, 2 + add_update 1, 0, 1, 2, 3 + add_update 0, 1, 2, 3, 0 + add_update 1, 2, 3, 0, 1 + add_update 0, 3, 0, 1, 2 + add_update 1, 0, 1, 2, 3 + add_update 0, 1, 2, 3, 0 + add_update 1, 2, 3, 0, 1 + add_update 0, 3, 0, 1, 2 + + add_only 1, 1 + add_only 0, 2 + add_only 1, 3 + add_only 0 + + /* update state */ + vadd.u32 dga, dga, dg0 + vadd.u32 dgb, dgb, dg1 + bne 0b + + /* store new state */ + vst1.8 {dga-dgb}, [r0] + bx lr + + .align 6 +.Lsha256_rcon: + .word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 + .word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 + .word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 + .word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 + .word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc + .word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da + .word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 + .word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 + .word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 + .word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 + .word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 + .word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 + .word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 + .word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 + .word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 + .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +END_FUNC sha256_ce_transform diff --git a/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a64.S b/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a64.S new file mode 100644 index 0000000..5fcfc65 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha256_armv8a_ce_a64.S @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2020, Linaro Limited + * Copyright (C) 2014 Linaro Ltd + */ + +/* Core SHA-224/SHA-256 transform using v8 Crypto Extensions */ + +#include + + .arch armv8-a+crypto + + dga .req q20 + dgav .req v20 + dgb .req q21 + dgbv .req v21 + + t0 .req v22 + t1 .req v23 + + dg0q .req q24 + dg0v .req v24 + dg1q .req q25 + dg1v .req v25 + dg2q .req q26 + dg2v .req v26 + + .macro add_only, ev, rc, s0 + mov dg2v.16b, dg0v.16b + .ifeq \ev + add t1.4s, v\s0\().4s, \rc\().4s + sha256h dg0q, dg1q, t0.4s + sha256h2 dg1q, dg2q, t0.4s + .else + .ifnb \s0 + add t0.4s, v\s0\().4s, \rc\().4s + .endif + sha256h dg0q, dg1q, t1.4s + sha256h2 dg1q, dg2q, t1.4s + .endif + .endm + + .macro add_update, ev, rc, s0, s1, s2, s3 + sha256su0 v\s0\().4s, v\s1\().4s + add_only \ev, \rc, \s1 + sha256su1 v\s0\().4s, v\s2\().4s, v\s3\().4s + .endm + + + /* + * void sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src, + * int blocks) + */ +FUNC sha256_ce_transform , : + /* load round constants */ + adr x8, .Lsha2_rcon + ld1 { v0.4s- v3.4s}, [x8], #64 + ld1 { v4.4s- v7.4s}, [x8], #64 + ld1 { v8.4s-v11.4s}, [x8], #64 + ld1 {v12.4s-v15.4s}, [x8] + + /* load state */ + mov x9, x0 + ld1 {dgav.4s}, [x9], #16 + ld1 {dgbv.4s}, [x9] + + /* load input */ +0: ld1 {v16.16b-v19.16b}, [x1], #64 + sub w2, w2, #1 + + rev32 v16.16b, v16.16b + rev32 v17.16b, v17.16b + rev32 v18.16b, v18.16b + rev32 v19.16b, v19.16b + +1: add t0.4s, v16.4s, v0.4s + mov dg0v.16b, dgav.16b + mov dg1v.16b, dgbv.16b + + add_update 0, v1, 16, 17, 18, 19 + add_update 1, v2, 17, 18, 19, 16 + add_update 0, v3, 18, 19, 16, 17 + add_update 1, v4, 19, 16, 17, 18 + + add_update 0, v5, 16, 17, 18, 19 + add_update 1, v6, 17, 18, 19, 16 + add_update 0, v7, 18, 19, 16, 17 + add_update 1, v8, 19, 16, 17, 18 + + add_update 0, v9, 16, 17, 18, 19 + add_update 1, v10, 17, 18, 19, 16 + add_update 0, v11, 18, 19, 16, 17 + add_update 1, v12, 19, 16, 17, 18 + + add_only 0, v13, 17 + add_only 1, v14, 18 + add_only 0, v15, 19 + add_only 1 + + /* update state */ + add dgav.4s, dgav.4s, dg0v.4s + add dgbv.4s, dgbv.4s, dg1v.4s + + /* handled all input blocks? */ + cbnz w2, 0b + + /* store new state */ +3: mov x9, x0 + st1 {dgav.16b}, [x9], #16 + st1 {dgbv.16b}, [x9] + ret + + /* + * The SHA-256 round constants + */ + .align 4 +.Lsha2_rcon: + .word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 + .word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 + .word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 + .word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 + .word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc + .word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da + .word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 + .word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 + .word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 + .word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 + .word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 + .word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 + .word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 + .word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 + .word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 + .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +END_FUNC sha256_ce_transform + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce.c b/optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce.c new file mode 100644 index 0000000..ad9152d --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Linaro Limited + */ + +#include +#include + +/* Prototype for assembly function */ +int sha3_ce_transform(uint64_t state[25], const void *src, + unsigned int block_count, unsigned int digest_size); + +void crypto_accel_sha3_compress(uint64_t state[25], const void *src, + unsigned int block_count, + unsigned int digest_size) +{ + uint32_t vfp_state = 0; + int res = 0; + + vfp_state = thread_kernel_enable_vfp(); + res = sha3_ce_transform(state, src, block_count, digest_size); + thread_kernel_disable_vfp(vfp_state); + assert(!res); +} + diff --git a/optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce_a64.S b/optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce_a64.S new file mode 100644 index 0000000..a468998 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha3_armv8a_ce_a64.S @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2018 Linaro Ltd + * Copyright (c) 2023 Linaro Limited + */ + +/* Core SHA-3 transform using v8 Crypto Extensions */ + +#include +#include + + .irp b,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,26,27,28,29,30,31 + .set .Lv\b\().2d, \b + .set .Lv\b\().16b, \b + .endr + + /* + * ARMv8.2 Crypto Extensions instructions + */ + .macro eor3, rd, rn, rm, ra + .inst 0xce000000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | \ + (.L\rm << 16) + .endm + + .macro rax1, rd, rn, rm + .inst 0xce608c00 | .L\rd | (.L\rn << 5) | (.L\rm << 16) + .endm + + .macro bcax, rd, rn, rm, ra + .inst 0xce200000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | \ + (.L\rm << 16) + .endm + + .macro xar, rd, rn, rm, imm6 + .inst 0xce800000 | .L\rd | (.L\rn << 5) | ((\imm6) << 10) | \ + (.L\rm << 16) + .endm + + /* + * int sha3_ce_transform(u64 *st, const u8 *data, int blocks, + * int dg_size) + */ + .text +FUNC sha3_ce_transform , : + /* load state */ + add x8, x0, #32 + ld1 { v0.1d- v3.1d}, [x0] + ld1 { v4.1d- v7.1d}, [x8], #32 + ld1 { v8.1d-v11.1d}, [x8], #32 + ld1 {v12.1d-v15.1d}, [x8], #32 + ld1 {v16.1d-v19.1d}, [x8], #32 + ld1 {v20.1d-v23.1d}, [x8], #32 + ld1 {v24.1d}, [x8] + +0: sub w2, w2, #1 + mov w8, #24 + adr_l x9, .Lsha3_rcon + + /* load input */ + ld1 {v25.8b-v28.8b}, [x1], #32 + ld1 {v29.8b-v31.8b}, [x1], #24 + eor v0.8b, v0.8b, v25.8b + eor v1.8b, v1.8b, v26.8b + eor v2.8b, v2.8b, v27.8b + eor v3.8b, v3.8b, v28.8b + eor v4.8b, v4.8b, v29.8b + eor v5.8b, v5.8b, v30.8b + eor v6.8b, v6.8b, v31.8b + + /* Bit 6 set? -> SHA3-512 */ + tbnz x3, #6, 3f + + /* SHA3-384, SHA3-256, SHA3-224 or SHA3-128 */ + ld1 {v25.8b-v28.8b}, [x1], #32 + ld1 {v29.8b-v30.8b}, [x1], #16 + eor v7.8b, v7.8b, v25.8b + eor v8.8b, v8.8b, v26.8b + eor v9.8b, v9.8b, v27.8b + eor v10.8b, v10.8b, v28.8b + eor v11.8b, v11.8b, v29.8b + eor v12.8b, v12.8b, v30.8b + + /* bit 4 set? -> SHA3-384, SHA3-224 or SHA3-128 */ + tbnz x3, #4, 1f + + /* SHA3-256: digest size 32 bytes, block size 136 bytes */ + ld1 {v25.8b-v28.8b}, [x1], #32 + eor v13.8b, v13.8b, v25.8b + eor v14.8b, v14.8b, v26.8b + eor v15.8b, v15.8b, v27.8b + eor v16.8b, v16.8b, v28.8b + b 4f + + /* bit 5 set? -> SHA-384 */ +1: tbnz x3, #5, 4f + + /* SHA3-224 or SHA3-128 */ + ld1 {v25.8b-v28.8b}, [x1], #32 + eor v13.8b, v13.8b, v25.8b + eor v14.8b, v14.8b, v26.8b + eor v15.8b, v15.8b, v27.8b + eor v16.8b, v16.8b, v28.8b + + /* bit 2 set? -> SHA-224 */ + tbnz x3, #2, 2f + + /* SHA3-128: digest size 16 bytes, block size 168 bytes */ + ld1 {v25.8b-v28.8b}, [x1], #32 + eor v17.8b, v17.8b, v25.8b + eor v18.8b, v18.8b, v26.8b + eor v19.8b, v19.8b, v27.8b + eor v20.8b, v20.8b, v28.8b + b 4f + + /* SHA3-224: digest size 28 bytes, block size 144 bytes */ +2: ld1 {v25.8b-v26.8b}, [x1], #16 + eor v17.8b, v17.8b, v25.8b + eor v18.8b, v18.8b, v26.8b + b 4f + + /* SHA3-512: digest size 64 bytes , block size 72 bytes */ +3: ld1 {v25.8b-v26.8b}, [x1], #16 + eor v7.8b, v7.8b, v25.8b + eor v8.8b, v8.8b, v26.8b + +4: sub w8, w8, #1 + + eor3 v29.16b, v4.16b, v9.16b, v14.16b + eor3 v26.16b, v1.16b, v6.16b, v11.16b + eor3 v28.16b, v3.16b, v8.16b, v13.16b + eor3 v25.16b, v0.16b, v5.16b, v10.16b + eor3 v27.16b, v2.16b, v7.16b, v12.16b + eor3 v29.16b, v29.16b, v19.16b, v24.16b + eor3 v26.16b, v26.16b, v16.16b, v21.16b + eor3 v28.16b, v28.16b, v18.16b, v23.16b + eor3 v25.16b, v25.16b, v15.16b, v20.16b + eor3 v27.16b, v27.16b, v17.16b, v22.16b + + rax1 v30.2d, v29.2d, v26.2d // bc[0] + rax1 v26.2d, v26.2d, v28.2d // bc[2] + rax1 v28.2d, v28.2d, v25.2d // bc[4] + rax1 v25.2d, v25.2d, v27.2d // bc[1] + rax1 v27.2d, v27.2d, v29.2d // bc[3] + + eor v0.16b, v0.16b, v30.16b + xar v29.2d, v1.2d, v25.2d, (64 - 1) + xar v1.2d, v6.2d, v25.2d, (64 - 44) + xar v6.2d, v9.2d, v28.2d, (64 - 20) + xar v9.2d, v22.2d, v26.2d, (64 - 61) + xar v22.2d, v14.2d, v28.2d, (64 - 39) + xar v14.2d, v20.2d, v30.2d, (64 - 18) + xar v31.2d, v2.2d, v26.2d, (64 - 62) + xar v2.2d, v12.2d, v26.2d, (64 - 43) + xar v12.2d, v13.2d, v27.2d, (64 - 25) + xar v13.2d, v19.2d, v28.2d, (64 - 8) + xar v19.2d, v23.2d, v27.2d, (64 - 56) + xar v23.2d, v15.2d, v30.2d, (64 - 41) + xar v15.2d, v4.2d, v28.2d, (64 - 27) + xar v28.2d, v24.2d, v28.2d, (64 - 14) + xar v24.2d, v21.2d, v25.2d, (64 - 2) + xar v8.2d, v8.2d, v27.2d, (64 - 55) + xar v4.2d, v16.2d, v25.2d, (64 - 45) + xar v16.2d, v5.2d, v30.2d, (64 - 36) + xar v5.2d, v3.2d, v27.2d, (64 - 28) + xar v27.2d, v18.2d, v27.2d, (64 - 21) + xar v3.2d, v17.2d, v26.2d, (64 - 15) + xar v25.2d, v11.2d, v25.2d, (64 - 10) + xar v26.2d, v7.2d, v26.2d, (64 - 6) + xar v30.2d, v10.2d, v30.2d, (64 - 3) + + bcax v20.16b, v31.16b, v22.16b, v8.16b + bcax v21.16b, v8.16b, v23.16b, v22.16b + bcax v22.16b, v22.16b, v24.16b, v23.16b + bcax v23.16b, v23.16b, v31.16b, v24.16b + bcax v24.16b, v24.16b, v8.16b, v31.16b + + ld1r {v31.2d}, [x9], #8 + + bcax v17.16b, v25.16b, v19.16b, v3.16b + bcax v18.16b, v3.16b, v15.16b, v19.16b + bcax v19.16b, v19.16b, v16.16b, v15.16b + bcax v15.16b, v15.16b, v25.16b, v16.16b + bcax v16.16b, v16.16b, v3.16b, v25.16b + + bcax v10.16b, v29.16b, v12.16b, v26.16b + bcax v11.16b, v26.16b, v13.16b, v12.16b + bcax v12.16b, v12.16b, v14.16b, v13.16b + bcax v13.16b, v13.16b, v29.16b, v14.16b + bcax v14.16b, v14.16b, v26.16b, v29.16b + + bcax v7.16b, v30.16b, v9.16b, v4.16b + bcax v8.16b, v4.16b, v5.16b, v9.16b + bcax v9.16b, v9.16b, v6.16b, v5.16b + bcax v5.16b, v5.16b, v30.16b, v6.16b + bcax v6.16b, v6.16b, v4.16b, v30.16b + + bcax v3.16b, v27.16b, v0.16b, v28.16b + bcax v4.16b, v28.16b, v1.16b, v0.16b + bcax v0.16b, v0.16b, v2.16b, v1.16b + bcax v1.16b, v1.16b, v27.16b, v2.16b + bcax v2.16b, v2.16b, v28.16b, v27.16b + + eor v0.16b, v0.16b, v31.16b + + cbnz w8, 4b + cbnz w2, 0b + + /* save state */ + st1 { v0.1d- v3.1d}, [x0], #32 + st1 { v4.1d- v7.1d}, [x0], #32 + st1 { v8.1d-v11.1d}, [x0], #32 + st1 {v12.1d-v15.1d}, [x0], #32 + st1 {v16.1d-v19.1d}, [x0], #32 + st1 {v20.1d-v23.1d}, [x0], #32 + st1 {v24.1d}, [x0] + mov w0, w2 + ret +END_FUNC sha3_ce_transform + + .section ".rodata", "a" + .align 8 +LOCAL_DATA .Lsha3_rcon , : + .quad 0x0000000000000001, 0x0000000000008082, 0x800000000000808a + .quad 0x8000000080008000, 0x000000000000808b, 0x0000000080000001 + .quad 0x8000000080008081, 0x8000000000008009, 0x000000000000008a + .quad 0x0000000000000088, 0x0000000080008009, 0x000000008000000a + .quad 0x000000008000808b, 0x800000000000008b, 0x8000000000008089 + .quad 0x8000000000008003, 0x8000000000008002, 0x8000000000000080 + .quad 0x000000000000800a, 0x800000008000000a, 0x8000000080008081 + .quad 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce.c b/optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce.c new file mode 100644 index 0000000..165e718 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include + +/* Prototype for assembly function */ +void sha512_ce_transform(uint64_t state[8], const void *src, + unsigned int block_count); + +void crypto_accel_sha512_compress(uint64_t state[8], const void *src, + unsigned int block_count) +{ + uint32_t vfp_state = 0; + + vfp_state = thread_kernel_enable_vfp(); + sha512_ce_transform(state, src, block_count); + thread_kernel_disable_vfp(vfp_state); +} diff --git a/optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce_a64.S b/optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce_a64.S new file mode 100644 index 0000000..d6a83fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sha512_armv8a_ce_a64.S @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + * Copyright (C) 2018 Linaro Ltd + */ + +/* Core SHA-384/SHA-512 transform using v8 Crypto Extensions */ + +#include +#include + + .irp b,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 + .set .Lq\b, \b + .set .Lv\b\().2d, \b + .endr + + .macro sha512h, rd, rn, rm + .inst 0xce608000 | .L\rd | (.L\rn << 5) | (.L\rm << 16) + .endm + + .macro sha512h2, rd, rn, rm + .inst 0xce608400 | .L\rd | (.L\rn << 5) | (.L\rm << 16) + .endm + + .macro sha512su0, rd, rn + .inst 0xcec08000 | .L\rd | (.L\rn << 5) + .endm + + .macro sha512su1, rd, rn, rm + .inst 0xce608800 | .L\rd | (.L\rn << 5) | (.L\rm << 16) + .endm + + /* + * The SHA-512 round constants + */ + .section ".rodata", "a" + .align 4 +LOCAL_DATA .Lsha512_rcon , : + .quad 0x428a2f98d728ae22, 0x7137449123ef65cd + .quad 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc + .quad 0x3956c25bf348b538, 0x59f111f1b605d019 + .quad 0x923f82a4af194f9b, 0xab1c5ed5da6d8118 + .quad 0xd807aa98a3030242, 0x12835b0145706fbe + .quad 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2 + .quad 0x72be5d74f27b896f, 0x80deb1fe3b1696b1 + .quad 0x9bdc06a725c71235, 0xc19bf174cf692694 + .quad 0xe49b69c19ef14ad2, 0xefbe4786384f25e3 + .quad 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65 + .quad 0x2de92c6f592b0275, 0x4a7484aa6ea6e483 + .quad 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5 + .quad 0x983e5152ee66dfab, 0xa831c66d2db43210 + .quad 0xb00327c898fb213f, 0xbf597fc7beef0ee4 + .quad 0xc6e00bf33da88fc2, 0xd5a79147930aa725 + .quad 0x06ca6351e003826f, 0x142929670a0e6e70 + .quad 0x27b70a8546d22ffc, 0x2e1b21385c26c926 + .quad 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df + .quad 0x650a73548baf63de, 0x766a0abb3c77b2a8 + .quad 0x81c2c92e47edaee6, 0x92722c851482353b + .quad 0xa2bfe8a14cf10364, 0xa81a664bbc423001 + .quad 0xc24b8b70d0f89791, 0xc76c51a30654be30 + .quad 0xd192e819d6ef5218, 0xd69906245565a910 + .quad 0xf40e35855771202a, 0x106aa07032bbd1b8 + .quad 0x19a4c116b8d2d0c8, 0x1e376c085141ab53 + .quad 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8 + .quad 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb + .quad 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3 + .quad 0x748f82ee5defb2fc, 0x78a5636f43172f60 + .quad 0x84c87814a1f0ab72, 0x8cc702081a6439ec + .quad 0x90befffa23631e28, 0xa4506cebde82bde9 + .quad 0xbef9a3f7b2c67915, 0xc67178f2e372532b + .quad 0xca273eceea26619c, 0xd186b8c721c0c207 + .quad 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178 + .quad 0x06f067aa72176fba, 0x0a637dc5a2c898a6 + .quad 0x113f9804bef90dae, 0x1b710b35131c471b + .quad 0x28db77f523047d84, 0x32caab7b40c72493 + .quad 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c + .quad 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a + .quad 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 +END_DATA .Lsha512_rcon + + .macro dround, i0, i1, i2, i3, i4, rc0, rc1, in0, in1, in2, in3, in4 + .ifnb \rc1 + ld1 {v\rc1\().2d}, [x4], #16 + .endif + add v5.2d, v\rc0\().2d, v\in0\().2d + ext v6.16b, v\i2\().16b, v\i3\().16b, #8 + ext v5.16b, v5.16b, v5.16b, #8 + ext v7.16b, v\i1\().16b, v\i2\().16b, #8 + add v\i3\().2d, v\i3\().2d, v5.2d + .ifnb \in1 + ext v5.16b, v\in3\().16b, v\in4\().16b, #8 + sha512su0 v\in0\().2d, v\in1\().2d + .endif + sha512h q\i3, q6, v7.2d + .ifnb \in1 + sha512su1 v\in0\().2d, v\in2\().2d, v5.2d + .endif + add v\i4\().2d, v\i1\().2d, v\i3\().2d + sha512h2 q\i3, q\i1, v\i0\().2d + .endm + + /* + * void sha512_ce_transform(struct sha512_state *sst, u8 const *src, + * int blocks) + */ +FUNC sha512_ce_transform , : + /* load state */ + ld1 {v8.2d-v11.2d}, [x0] + + /* load first 4 round constants */ + adr_l x3, .Lsha512_rcon + ld1 {v20.2d-v23.2d}, [x3], #64 + + /* load input */ +0: ld1 {v12.2d-v15.2d}, [x1], #64 + ld1 {v16.2d-v19.2d}, [x1], #64 + sub w2, w2, #1 + + rev64 v12.16b, v12.16b + rev64 v13.16b, v13.16b + rev64 v14.16b, v14.16b + rev64 v15.16b, v15.16b + rev64 v16.16b, v16.16b + rev64 v17.16b, v17.16b + rev64 v18.16b, v18.16b + rev64 v19.16b, v19.16b + + mov x4, x3 // rc pointer + + mov v0.16b, v8.16b + mov v1.16b, v9.16b + mov v2.16b, v10.16b + mov v3.16b, v11.16b + + // v0 ab cd -- ef gh ab + // v1 cd -- ef gh ab cd + // v2 ef gh ab cd -- ef + // v3 gh ab cd -- ef gh + // v4 -- ef gh ab cd -- + + dround 0, 1, 2, 3, 4, 20, 24, 12, 13, 19, 16, 17 + dround 3, 0, 4, 2, 1, 21, 25, 13, 14, 12, 17, 18 + dround 2, 3, 1, 4, 0, 22, 26, 14, 15, 13, 18, 19 + dround 4, 2, 0, 1, 3, 23, 27, 15, 16, 14, 19, 12 + dround 1, 4, 3, 0, 2, 24, 28, 16, 17, 15, 12, 13 + + dround 0, 1, 2, 3, 4, 25, 29, 17, 18, 16, 13, 14 + dround 3, 0, 4, 2, 1, 26, 30, 18, 19, 17, 14, 15 + dround 2, 3, 1, 4, 0, 27, 31, 19, 12, 18, 15, 16 + dround 4, 2, 0, 1, 3, 28, 24, 12, 13, 19, 16, 17 + dround 1, 4, 3, 0, 2, 29, 25, 13, 14, 12, 17, 18 + + dround 0, 1, 2, 3, 4, 30, 26, 14, 15, 13, 18, 19 + dround 3, 0, 4, 2, 1, 31, 27, 15, 16, 14, 19, 12 + dround 2, 3, 1, 4, 0, 24, 28, 16, 17, 15, 12, 13 + dround 4, 2, 0, 1, 3, 25, 29, 17, 18, 16, 13, 14 + dround 1, 4, 3, 0, 2, 26, 30, 18, 19, 17, 14, 15 + + dround 0, 1, 2, 3, 4, 27, 31, 19, 12, 18, 15, 16 + dround 3, 0, 4, 2, 1, 28, 24, 12, 13, 19, 16, 17 + dround 2, 3, 1, 4, 0, 29, 25, 13, 14, 12, 17, 18 + dround 4, 2, 0, 1, 3, 30, 26, 14, 15, 13, 18, 19 + dround 1, 4, 3, 0, 2, 31, 27, 15, 16, 14, 19, 12 + + dround 0, 1, 2, 3, 4, 24, 28, 16, 17, 15, 12, 13 + dround 3, 0, 4, 2, 1, 25, 29, 17, 18, 16, 13, 14 + dround 2, 3, 1, 4, 0, 26, 30, 18, 19, 17, 14, 15 + dround 4, 2, 0, 1, 3, 27, 31, 19, 12, 18, 15, 16 + dround 1, 4, 3, 0, 2, 28, 24, 12, 13, 19, 16, 17 + + dround 0, 1, 2, 3, 4, 29, 25, 13, 14, 12, 17, 18 + dround 3, 0, 4, 2, 1, 30, 26, 14, 15, 13, 18, 19 + dround 2, 3, 1, 4, 0, 31, 27, 15, 16, 14, 19, 12 + dround 4, 2, 0, 1, 3, 24, 28, 16, 17, 15, 12, 13 + dround 1, 4, 3, 0, 2, 25, 29, 17, 18, 16, 13, 14 + + dround 0, 1, 2, 3, 4, 26, 30, 18, 19, 17, 14, 15 + dround 3, 0, 4, 2, 1, 27, 31, 19, 12, 18, 15, 16 + dround 2, 3, 1, 4, 0, 28, 24, 12 + dround 4, 2, 0, 1, 3, 29, 25, 13 + dround 1, 4, 3, 0, 2, 30, 26, 14 + + dround 0, 1, 2, 3, 4, 31, 27, 15 + dround 3, 0, 4, 2, 1, 24, , 16 + dround 2, 3, 1, 4, 0, 25, , 17 + dround 4, 2, 0, 1, 3, 26, , 18 + dround 1, 4, 3, 0, 2, 27, , 19 + + /* update state */ + add v8.2d, v8.2d, v0.2d + add v9.2d, v9.2d, v1.2d + add v10.2d, v10.2d, v2.2d + add v11.2d, v11.2d, v3.2d + + /* handled all input blocks? */ + cbnz w2, 0b + + /* store new state */ +3: st1 {v8.2d-v11.2d}, [x0] + mov w0, w2 + ret +END_FUNC sha512_ce_transform + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce.c b/optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce.c new file mode 100644 index 0000000..2646849 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022 Linaro Limited + */ + +#include +#include + +/* Prototype for assembly function */ +void sm3_ce_transform(uint32_t state[8], const void *src, + unsigned int block_count); + +void crypto_accel_sm3_compress(uint32_t state[8], const void *src, + unsigned int block_count) +{ + uint32_t vfp_state = 0; + + vfp_state = thread_kernel_enable_vfp(); + sm3_ce_transform(state, src, block_count); + thread_kernel_disable_vfp(vfp_state); +} + diff --git a/optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce_a64.S b/optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce_a64.S new file mode 100644 index 0000000..13ed507 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sm3_armv8a_ce_a64.S @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022 Linaro Limited + * Copyright (C) 2018 Linaro Ltd + */ + +/* Core SM3 secure hash using ARMv8.2 Crypto Extensions */ + +#include +#include + + .irp b, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 + .set .Lv\b\().4s, \b + .endr + + .macro sm3partw1, rd, rn, rm + .inst 0xce60c000 | .L\rd | (.L\rn << 5) | (.L\rm << 16) + .endm + + .macro sm3partw2, rd, rn, rm + .inst 0xce60c400 | .L\rd | (.L\rn << 5) | (.L\rm << 16) + .endm + + .macro sm3ss1, rd, rn, rm, ra + .inst 0xce400000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | (.L\rm << 16) + .endm + + .macro sm3tt1a, rd, rn, rm, imm2 + .inst 0xce408000 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) + .endm + + .macro sm3tt1b, rd, rn, rm, imm2 + .inst 0xce408400 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) + .endm + + .macro sm3tt2a, rd, rn, rm, imm2 + .inst 0xce408800 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) + .endm + + .macro sm3tt2b, rd, rn, rm, imm2 + .inst 0xce408c00 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) + .endm + + .macro round, ab, s0, t0, t1, i + sm3ss1 v5.4s, v8.4s, \t0\().4s, v9.4s + shl \t1\().4s, \t0\().4s, #1 + sri \t1\().4s, \t0\().4s, #31 + sm3tt1\ab v8.4s, v5.4s, v10.4s, \i + sm3tt2\ab v9.4s, v5.4s, \s0\().4s, \i + .endm + + .macro qround, ab, s0, s1, s2, s3, s4 + .ifnb \s4 + ext \s4\().16b, \s1\().16b, \s2\().16b, #12 + ext v6.16b, \s0\().16b, \s1\().16b, #12 + ext v7.16b, \s2\().16b, \s3\().16b, #8 + sm3partw1 \s4\().4s, \s0\().4s, \s3\().4s + .endif + + eor v10.16b, \s0\().16b, \s1\().16b + + round \ab, \s0, v11, v12, 0 + round \ab, \s0, v12, v11, 1 + round \ab, \s0, v11, v12, 2 + round \ab, \s0, v12, v11, 3 + + .ifnb \s4 + sm3partw2 \s4\().4s, v7.4s, v6.4s + .endif + .endm + + /* + * void sm3_ce_transform(struct sm3_state *sst, u8 const *src, + * int blocks) + */ +FUNC sm3_ce_transform , : + /* load state */ + ld1 {v8.4s-v9.4s}, [x0] + rev64 v8.4s, v8.4s + rev64 v9.4s, v9.4s + ext v8.16b, v8.16b, v8.16b, #8 + ext v9.16b, v9.16b, v9.16b, #8 + + adr_l x8, .Lt + ldp s13, s14, [x8] + + /* load input */ +0: ld1 {v0.16b-v3.16b}, [x1], #64 + sub w2, w2, #1 + + mov v15.16b, v8.16b + mov v16.16b, v9.16b + + rev32 v0.16b, v0.16b + rev32 v1.16b, v1.16b + rev32 v2.16b, v2.16b + rev32 v3.16b, v3.16b + + ext v11.16b, v13.16b, v13.16b, #4 + + qround a, v0, v1, v2, v3, v4 + qround a, v1, v2, v3, v4, v0 + qround a, v2, v3, v4, v0, v1 + qround a, v3, v4, v0, v1, v2 + + ext v11.16b, v14.16b, v14.16b, #4 + + qround b, v4, v0, v1, v2, v3 + qround b, v0, v1, v2, v3, v4 + qround b, v1, v2, v3, v4, v0 + qround b, v2, v3, v4, v0, v1 + qround b, v3, v4, v0, v1, v2 + qround b, v4, v0, v1, v2, v3 + qround b, v0, v1, v2, v3, v4 + qround b, v1, v2, v3, v4, v0 + qround b, v2, v3, v4, v0, v1 + qround b, v3, v4 + qround b, v4, v0 + qround b, v0, v1 + + eor v8.16b, v8.16b, v15.16b + eor v9.16b, v9.16b, v16.16b + + /* handled all input blocks? */ + cbnz w2, 0b + + /* save state */ + rev64 v8.4s, v8.4s + rev64 v9.4s, v9.4s + ext v8.16b, v8.16b, v8.16b, #8 + ext v9.16b, v9.16b, v9.16b, #8 + st1 {v8.4s-v9.4s}, [x0] + ret +END_FUNC sm3_ce_transform + + .section ".rodata", "a" + .align 3 +LOCAL_DATA .Lt , : + .word 0x79cc4519, 0x9d8a7a87 +END_DATA .Lt + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_aese_a64.S b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_aese_a64.S new file mode 100644 index 0000000..ca51956 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_aese_a64.S @@ -0,0 +1,1122 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. + * Copyright (C) 2022, Alibaba Group. + * Copyright (C) 2022 Tianjia Zhang + * + * SM4 optimization for ARMv8 by NEON and AES HW instruction, which is an + * optional Cryptographic Extension for ARMv8-A. + * + * The NEON implementation refers to Linux kernel (sm4-neon-core.S contributed + * by Tianjia Zhang ). + * + * The AES trick refers to sm4ni (https://github.com/mjosaarinen/sm4ni). The + * constants used in load_sbox_matrix are from this blog (https://www.cnblogs. + * com/kentle/p/15826075.html). We've done some further optimizations so the + * constants don't look the same. + */ + +#include + +.arch armv8-a+crypto + +#define m0 w9 +#define m1 w10 +#define m2 w11 +#define m3 w12 +#define tw0l x7 +#define tw0h x8 +#define tw1l x9 +#define tw1h x10 +#define tw2l x11 +#define tw2h x12 +#define tw3l x13 +#define tw3h x14 +#define tw4l x15 +#define tw4h x16 +#define tw5l x17 +#define tw5h x18 +#define tw6l x19 +#define tw6h x20 +#define tw7l x21 +#define tw7h x22 +#define tmpw0 w23 +#define tmpx0 x23 +#define tmpw1 w24 +#define tmpx1 x24 +#define tmpw2 w25 + +/* round keys: v0-v7 */ +#define RK0 v0 +#define RK1 v1 +#define RK2 v2 +#define RK3 v3 +#define RK4 v4 +#define RK5 v5 +#define RK6 v6 +#define RK7 v7 + +/* plain blocks: v8-v15 */ +#define BLK0 v8 +#define BLK1 v9 +#define BLK2 v10 +#define BLK3 v11 +#define BLK4 v12 +#define BLK5 v13 +#define BLK6 v14 +#define BLK7 v15 + +#define TMP0 v16 +#define TMP1 v17 +#define TMP2 v18 +#define TMP3 v19 +#define TMP4 v20 +#define TMP5 v21 +#define TMP6 v22 +#define TMP7 v23 +#define TMP8 v24 +#define IV v25 +#define ANDMASKV v26 +#define ANDMASKQ q26 +#define ATALMaskV v27 +#define ATALMaskQ q27 +#define ATAHMaskV v28 +#define ATAHMaskQ q28 +#define TALMaskV v29 +#define TALMaskQ q29 +#define TAHMaskV v30 +#define TAHMaskQ q30 +#define MASKV v31 +#define MASKQ q31 + +.macro frame_push + stp x15, x16, [sp, #-0x10]! + stp x17, x18, [sp, #-0x10]! + stp x19, x20, [sp, #-0x10]! + stp x21, x22, [sp, #-0x10]! + stp x23, x24, [sp, #-0x10]! + stp x25, x26, [sp, #-0x10]! + stp x27, x28, [sp, #-0x10]! + stp x29, x30, [sp, #-0x10]! + stp d8, d9, [sp, #-0x10]! + stp d10, d11, [sp, #-0x10]! + stp d12, d13, [sp, #-0x10]! + stp d14, d15, [sp, #-0x10]! +.endm + +.macro frame_pop + ldp d14, d15, [sp], #0x10 + ldp d12, d13, [sp], #0x10 + ldp d10, d11, [sp], #0x10 + ldp d8, d9, [sp], #0x10 + ldp x29, x30, [sp], #0x10 + ldp x27, x28, [sp], #0x10 + ldp x25, x26, [sp], #0x10 + ldp x23, x24, [sp], #0x10 + ldp x21, x22, [sp], #0x10 + ldp x19, x20, [sp], #0x10 + ldp x17, x18, [sp], #0x10 + ldp x15, x16, [sp], #0x10 +.endm + +.macro load_sbox_matrix + ldr MASKQ, .Lsbox_magic + ldr TAHMaskQ, .Lsbox_magic+16 + ldr TALMaskQ, .Lsbox_magic+32 + ldr ATAHMaskQ, .Lsbox_magic+48 + ldr ATALMaskQ, .Lsbox_magic+64 + ldr ANDMASKQ, .Lsbox_magic+80 +.endm + +.macro multi_matrix, x, high, low, tmp + ushr \tmp\().16b, \x\().16b, 4 + and \x\().16b, \x\().16b, ANDMASKV.16b + tbl \x\().16b, {\low\().16b}, \x\().16b + tbl \tmp\().16b, {\high\().16b}, \tmp\().16b + eor \x\().16b, \x\().16b, \tmp\().16b +.endm + +.macro sbox, des, src, tmp1, tmp2 + tbl \des\().16b, {\src\().16b}, MASKV.16b + multi_matrix \des, TAHMaskV, TALMaskV, \tmp2 + eor \tmp1\().16b, \tmp1\().16b, \tmp1\().16b + aese \des\().16b, \tmp1\().16b + multi_matrix \des, ATAHMaskV, ATALMaskV, \tmp2 +.endm + +.macro sbox_double, des0, src0, des1, src1, tmp1, tmp2 + tbl \des0\().16b, {\src0\().16b}, MASKV.16b + tbl \des1\().16b, {\src1\().16b}, MASKV.16b + multi_matrix \des0, TAHMaskV, TALMaskV, \tmp2 + multi_matrix \des1, TAHMaskV, TALMaskV, \tmp2 + eor \tmp1\().16b, \tmp1\().16b, \tmp1\().16b + aese \des0\().16b, \tmp1\().16b + multi_matrix \des0, ATAHMaskV, ATALMaskV, \tmp2 + aese \des1\().16b, \tmp1\().16b + multi_matrix \des1, ATAHMaskV, ATALMaskV, \tmp2 +.endm + +.macro round, c0, c1, c2, c3, k + mov tmpw0, \k + eor tmpw1, \c1, \c2 + eor tmpw0, \c3, tmpw0 + eor tmpw2, tmpw1, tmpw0 + mov TMP0.s[0], tmpw2 + /* nonlinear transformation */ + sbox TMP1, TMP0, TMP2, TMP3 + /* linear transformation */ + mov tmpw2, TMP1.s[0] + ror tmpw0, tmpw2, #(32-10) + eor tmpw0, tmpw0, tmpw2, ror #(32-2) + ror tmpw1, tmpw2, #(32-24) + eor tmpw1, tmpw1, tmpw2, ror #(32-18) + eor tmpw0, tmpw0, tmpw1 + eor tmpw2, tmpw0, tmpw2 + eor \c0, \c0, tmpw2 +.endm + +.macro round4_enc, k + round m0, m1, m2, m3, \k\().s[0] + round m1, m2, m3, m0, \k\().s[1] + round m2, m3, m0, m1, \k\().s[2] + round m3, m0, m1, m2, \k\().s[3] +.endm + +.macro round4_dec, k + round m0, m1, m2, m3, \k\().s[3] + round m1, m2, m3, m0, \k\().s[2] + round m2, m3, m0, m1, \k\().s[1] + round m3, m0, m1, m2, \k\().s[0] +.endm + +.macro encrypt_block_no_rev, in + mov m0, \in\().s[0] + mov m1, \in\().s[1] + mov m2, \in\().s[2] + mov m3, \in\().s[3] + round4_enc RK0 + round4_enc RK1 + round4_enc RK2 + round4_enc RK3 + round4_enc RK4 + round4_enc RK5 + round4_enc RK6 + round4_enc RK7 + mov \in\().s[0], m3 + mov \in\().s[1], m2 + mov \in\().s[2], m1 + mov \in\().s[3], m0 +.endm + +.macro encrypt_block, in + rev32 \in\().16b, \in\().16b + encrypt_block_no_rev \in + rev32 \in\().16b, \in\().16b +.endm + +.macro decrypt_block_no_rev, in + mov m0, \in\().s[0] + mov m1, \in\().s[1] + mov m2, \in\().s[2] + mov m3, \in\().s[3] + round4_dec RK7 + round4_dec RK6 + round4_dec RK5 + round4_dec RK4 + round4_dec RK3 + round4_dec RK2 + round4_dec RK1 + round4_dec RK0 + mov \in\().s[0], m3 + mov \in\().s[1], m2 + mov \in\().s[2], m1 + mov \in\().s[3], m0 +.endm + +.macro decrypt_block, in + rev32 \in\().16b, \in\().16b + decrypt_block_no_rev \in + rev32 \in\().16b, \in\().16b +.endm + +LOCAL_FUNC sm4_encrypt_block1x , : + encrypt_block BLK0 + ret +END_FUNC sm4_encrypt_block1x + +LOCAL_FUNC sm4_decrypt_block1x , : + decrypt_block BLK0 + ret +END_FUNC sm4_decrypt_block1x + +.macro transpose_4x4, s0, s1, s2, s3 + zip1 TMP0.4s, \s0\().4s, \s1\().4s + zip1 TMP1.4s, \s2\().4s, \s3\().4s + zip2 TMP2.4s, \s0\().4s, \s1\().4s + zip2 TMP3.4s, \s2\().4s, \s3\().4s + zip1 \s0\().2d, TMP0.2d, TMP1.2d + zip2 \s1\().2d, TMP0.2d, TMP1.2d + zip1 \s2\().2d, TMP2.2d, TMP3.2d + zip2 \s3\().2d, TMP2.2d, TMP3.2d +.endm + +.macro rotate_clockwise_90, s0, s1, s2, s3 + zip1 TMP0.4s, \s1\().4s, \s0\().4s + zip2 TMP1.4s, \s1\().4s, \s0\().4s + zip1 TMP2.4s, \s3\().4s, \s2\().4s + zip2 TMP3.4s, \s3\().4s, \s2\().4s + zip1 \s0\().2d, TMP2.2d, TMP0.2d + zip2 \s1\().2d, TMP2.2d, TMP0.2d + zip1 \s2\().2d, TMP3.2d, TMP1.2d + zip2 \s3\().2d, TMP3.2d, TMP1.2d +.endm + + +.macro round_4x, s0, s1, s2, s3, k + dup TMP8.4s, \k + eor TMP1.16b, \s2\().16b, \s3\().16b + eor TMP8.16b, TMP8.16b, \s1\().16b + eor TMP8.16b, TMP8.16b, TMP1.16b + + /* nonlinear transformation */ + sbox TMP0, TMP8, TMP2, TMP3 + + /* linear transformation */ + shl TMP1.4s, TMP0.4s, #2 + shl TMP2.4s, TMP0.4s, #10 + shl TMP3.4s, TMP0.4s, #18 + shl TMP4.4s, TMP0.4s, #24 + sri TMP1.4s, TMP0.4s, #(32-2) + sri TMP2.4s, TMP0.4s, #(32-10) + sri TMP3.4s, TMP0.4s, #(32-18) + sri TMP4.4s, TMP0.4s, #(32-24) + eor TMP0.16b, TMP0.16b, TMP1.16b + eor TMP2.16b, TMP2.16b, TMP3.16b + eor TMP4.16b, TMP4.16b, \s0\().16b + eor TMP0.16b, TMP0.16b, TMP2.16b + eor \s0\().16b, TMP0.16b, TMP4.16b +.endm + +.macro round4_4x, k + round_4x BLK0, BLK1, BLK2, BLK3, \k\().s[0] + round_4x BLK1, BLK2, BLK3, BLK0, \k\().s[1] + round_4x BLK2, BLK3, BLK0, BLK1, \k\().s[2] + round_4x BLK3, BLK0, BLK1, BLK2, \k\().s[3] +.endm + +LOCAL_FUNC sm4_encrypt_block4x , : + rev32 BLK0.16b, BLK0.16b + rev32 BLK1.16b, BLK1.16b + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + + transpose_4x4 BLK0, BLK1, BLK2, BLK3 + + round4_4x RK0 + round4_4x RK1 + round4_4x RK2 + round4_4x RK3 + round4_4x RK4 + round4_4x RK5 + round4_4x RK6 + round4_4x RK7 + + rotate_clockwise_90 BLK0, BLK1, BLK2, BLK3 + rev32 BLK0.16b, BLK0.16b + rev32 BLK1.16b, BLK1.16b + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + ret +END_FUNC sm4_encrypt_block4x + +.macro round_8x, s0, s1, s2, s3, t0, t1, t2, t3, k + dup TMP8.4s, \k + eor TMP0.16b, \s2\().16b, \s3\().16b + mov TMP7.16b, TMP8.16b + eor TMP1.16b, \t2\().16b, \t3\().16b + eor TMP8.16b, TMP8.16b, \s1\().16b + eor TMP7.16b, TMP7.16b, \t1\().16b + eor TMP8.16b, TMP8.16b, TMP0.16b + eor TMP7.16b, TMP7.16b, TMP1.16b + + /* nonlinear transformation */ + sbox_double TMP0, TMP8, TMP1, TMP7, TMP2, TMP3 + + /* linear transformation */ + shl TMP6.4s, TMP0.4s, #2 + shl TMP8.4s, TMP1.4s, #2 + shl TMP2.4s, TMP0.4s, #10 + shl TMP5.4s, TMP1.4s, #10 + shl TMP3.4s, TMP0.4s, #18 + shl TMP4.4s, TMP0.4s, #24 + sri TMP6.4s, TMP0.4s, #(32-2) + sri TMP2.4s, TMP0.4s, #(32-10) + sri TMP3.4s, TMP0.4s, #(32-18) + sri TMP4.4s, TMP0.4s, #(32-24) + eor TMP0.16b, TMP0.16b, TMP6.16b + eor TMP2.16b, TMP2.16b, TMP3.16b + shl TMP6.4s, TMP1.4s, #18 + shl TMP7.4s, TMP1.4s, #24 + sri TMP8.4s, TMP1.4s, #(32-2) + sri TMP5.4s, TMP1.4s, #(32-10) + sri TMP6.4s, TMP1.4s, #(32-18) + sri TMP7.4s, TMP1.4s, #(32-24) + eor TMP4.16b, TMP4.16b, \s0\().16b + eor TMP1.16b, TMP1.16b, TMP8.16b + eor \s0\().16b, TMP0.16b, TMP2.16b + eor \s0\().16b, \s0\().16b, TMP4.16b + eor TMP5.16b, TMP5.16b, TMP6.16b + eor TMP7.16b, TMP7.16b, \t0\().16b + eor TMP1.16b, TMP1.16b, TMP5.16b + eor \t0\().16b, TMP1.16b, TMP7.16b +.endm + +.macro round4_8x, k + round_8x BLK0, BLK1, BLK2, BLK3, BLK4, BLK5, BLK6, BLK7, \k\().s[0] + round_8x BLK1, BLK2, BLK3, BLK0, BLK5, BLK6, BLK7, BLK4, \k\().s[1] + round_8x BLK2, BLK3, BLK0, BLK1, BLK6, BLK7, BLK4, BLK5, \k\().s[2] + round_8x BLK3, BLK0, BLK1, BLK2, BLK7, BLK4, BLK5, BLK6, \k\().s[3] +.endm + +LOCAL_FUNC sm4_encrypt_block8x , : + rev32 BLK0.16b, BLK0.16b + rev32 BLK1.16b, BLK1.16b + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + rev32 BLK4.16b, BLK4.16b + rev32 BLK5.16b, BLK5.16b + rev32 BLK6.16b, BLK6.16b + rev32 BLK7.16b, BLK7.16b + + transpose_4x4 BLK0, BLK1, BLK2, BLK3 + transpose_4x4 BLK4, BLK5, BLK6, BLK7 + + round4_8x RK0 + round4_8x RK1 + round4_8x RK2 + round4_8x RK3 + round4_8x RK4 + round4_8x RK5 + round4_8x RK6 + round4_8x RK7 + + rotate_clockwise_90 BLK0, BLK1, BLK2, BLK3 + rotate_clockwise_90 BLK4, BLK5, BLK6, BLK7 + + rev32 BLK0.16b, BLK0.16b + rev32 BLK1.16b, BLK1.16b + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + rev32 BLK4.16b, BLK4.16b + rev32 BLK5.16b, BLK5.16b + rev32 BLK6.16b, BLK6.16b + rev32 BLK7.16b, BLK7.16b + ret +END_FUNC sm4_encrypt_block8x + +.macro inc_le128, vctr, low, high + mov \vctr\().d[1], \high + mov \vctr\().d[0], \low + adds \high, \high, #1 + adc \low, \low, xzr + rev64 \vctr\().16b, \vctr\().16b +.endm + +.macro mov_reg_to_vec, desv, src0, src1 + mov \desv\().d[0], \src0 + mov \desv\().d[1], \src1 +.endm + +.macro next_tweak, des0, des1, src0, src1 + mov tmpw2, 0x87 + extr tmpx0, \src1, \src1, #32 + extr \des1, \src1, \src0, #63 + and tmpw1, tmpw2, tmpw0, asr#31 + eor \des0, tmpx1, \src0, lsl#1 +.endm + +.macro next_tweak_vec, desv, srcv + mov tw0l, \srcv\().d[0] + mov tw0h, \srcv\().d[1] + next_tweak tw1l, tw1h, tw0l, tw0h + mov \desv\().d[0], tw1l + mov \desv\().d[1], tw1h +.endm + +LOCAL_DATA .Lck , : + .long 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269 + .long 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9 + .long 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249 + .long 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9 + .long 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229 + .long 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299 + .long 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209 + .long 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 +END_DATA .Lck + +LOCAL_DATA .Lfk , : + .long 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc +END_DATA .Lfk + +LOCAL_DATA .Lshuffles , : + .long 0x07060504, 0x0B0A0908, 0x0F0E0D0C, 0x03020100 +END_DATA .Lshuffles + +LOCAL_DATA .Lsbox_magic , : + .dword 0x0b0e0104070a0d00, 0x0306090c0f020508 + .dword 0x62185a2042387a00, 0x22581a6002783a40 + .dword 0x15df62a89e54e923, 0xc10bb67c4a803df7 + .dword 0xb9aa6b78c1d21300, 0x1407c6d56c7fbead + .dword 0x6404462679195b3b, 0xe383c1a1fe9edcbc + .dword 0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f +END_DATA .Lsbox_magic + +.macro sm4_setkey + ld1 {v5.4s}, [x1] + load_sbox_matrix + rev32 v5.16b, v5.16b + adr x5, .Lfk + ld1 {v6.4s}, [x5] + eor v5.16b, v5.16b, v6.16b + mov x6, #32 + adr x5, .Lck +1: + mov w7, v5.s[1] + ldr w8, [x5], #4 + eor w8, w8, w7 + mov w7, v5.s[2] + eor w8, w8, w7 + mov w7, v5.s[3] + eor w8, w8, w7 + + /* optimize sbox using AESE instruction */ + mov TMP0.s[0], w8 + sbox TMP1, TMP0, TMP2, TMP3 + mov w7, TMP1.s[0] + + /* linear transformation */ + eor w8, w7, w7, ror #19 + eor w8, w8, w7, ror #9 + mov w7, v5.s[0] + eor w8, w8, w7 + mov v5.s[0], w8 + ext v5.16b, v5.16b, v5.16b, 4 + subs x6, x6, #1 +.endm + +/* + * void neon_sm4_setkey_enc(uint32_t sk[32], uint8_t const key[16]); + * x0: round key + * x1: user key + */ +FUNC neon_sm4_setkey_enc , : + sm4_setkey + str w8, [x0], #4 + b.ne 1b + ret +END_FUNC neon_sm4_setkey_enc + +/* + * void neon_sm4_setkey_dec(uint32_t sk[32], uint8_t const key[16]); + * x0: round key + * x1: user key + */ +FUNC neon_sm4_setkey_dec , : + add x0, x0, 124 + sm4_setkey + str w8, [x0], #-4 + b.ne 1b + ret +END_FUNC neon_sm4_setkey_dec + +/* + * void neon_sm4_ecb_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], size_t len); + * x0: output + * x1: input + * x2: round key + * w3: length + */ +FUNC neon_sm4_ecb_encrypt , : + frame_push + load_sbox_matrix + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + lsr w3, w3, 4 + +.Lecbloop8x: + cmp w3, 8 + b.lt .Lecb4x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 + bl sm4_encrypt_block8x + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 + subs w3, w3, #8 + b.gt .Lecbloop8x + +.Lecb4x: + cmp w3, 1 + b.lt .Lecbout + cmp w3, 2 + b.lt .Lecb1x + cmp w3, 3 + b.lt .Lecb2x + cmp w3, 4 + b.lt .Lecb3x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + bl sm4_encrypt_block4x + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + sub w3, w3, #4 + b .Lecb4x + +.Lecb3x: + ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 + bl sm4_encrypt_block4x + st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 + subs w3, w3, #3 + b.le .Lecbout + +.Lecb2x: + ld1 {BLK0.16b, BLK1.16b}, [x1], #32 + bl sm4_encrypt_block4x + st1 {BLK0.16b, BLK1.16b}, [x0], #32 + subs w3, w3, #2 + b.le .Lecbout + +.Lecb1x: + ld1 {BLK0.16b}, [x1], #16 + bl sm4_encrypt_block1x + st1 {BLK0.16b}, [x0], #16 + +.Lecbout: + frame_pop + ret + +END_FUNC neon_sm4_ecb_encrypt + +/* + * void neon_sm4_cbc_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], size_t len, + * uint8_t iv[]); + * x0: output + * x1: input + * x2: round key + * w3: length + * x4: iv + */ +FUNC neon_sm4_cbc_encrypt , : + frame_push + load_sbox_matrix + + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + lsr w3, w3, 4 + ld1 {IV.16b}, [x4] + +.Lcbcencloop4x: + cmp w3, 4 + b.lt .Lcbcenc1x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + eor BLK0.16b, BLK0.16b, IV.16b + rev32 BLK0.16b, BLK0.16b + rev32 BLK1.16b, BLK1.16b + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + encrypt_block_no_rev BLK0 + eor BLK1.16b, BLK1.16b, BLK0.16b + encrypt_block_no_rev BLK1 + rev32 BLK0.16b, BLK0.16b + eor BLK2.16b, BLK2.16b, BLK1.16b + encrypt_block_no_rev BLK2 + rev32 BLK1.16b, BLK1.16b + eor BLK3.16b, BLK3.16b, BLK2.16b + encrypt_block_no_rev BLK3 + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + mov IV.16b, BLK3.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + subs w3, w3, #4 + b .Lcbcencloop4x +.Lcbcenc1x: + cmp w3, 1 + b.lt .Lcbcencout +.Lcbcencloop: + ld1 {BLK0.16b}, [x1], #16 + eor BLK0.16b, BLK0.16b, IV.16b + bl sm4_encrypt_block1x + mov IV.16b, BLK0.16b + st1 {BLK0.16b}, [x0], #16 + subs w3, w3, #1 + bne .Lcbcencloop +.Lcbcencout: + st1 {IV.16b}, [x4] + frame_pop + ret +END_FUNC neon_sm4_cbc_encrypt + +/* + * void neon_sm4_cbc_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], size_t len, + * uint8_t iv[]); + * x0: output + * x1: input + * x2: round key + * w3: length + * x4: iv + */ +FUNC neon_sm4_cbc_decrypt , : + frame_push + load_sbox_matrix + + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + lsr w3, w3, 4 + ld1 {IV.16b}, [x4] + +.Lcbcdecloop8x: + cmp w3, 8 + b.lt .Lcbcdec4x + + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 + bl sm4_encrypt_block8x + sub x5, x1, #128 + eor BLK0.16b, BLK0.16b, IV.16b + ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x5], #64 + eor BLK1.16b, BLK1.16b, TMP0.16b + eor BLK2.16b, BLK2.16b, TMP1.16b + eor BLK3.16b, BLK3.16b, TMP2.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + ld1 {TMP4.16b, TMP5.16b, TMP6.16b, TMP7.16b}, [x5], #64 + eor BLK4.16b, BLK4.16b, TMP3.16b + eor BLK5.16b, BLK5.16b, TMP4.16b + mov IV.16b, TMP7.16b + eor BLK6.16b, BLK6.16b, TMP5.16b + eor BLK7.16b, BLK7.16b, TMP6.16b + st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 + subs w3, w3, #8 + b.gt .Lcbcdecloop8x + +.Lcbcdec4x: + cmp w3, 1 + b.lt .Lcbcdecout + cmp w3, 2 + b.lt .Lcbcdec1x + cmp w3, 3 + b.lt .Lcbcdec2x + cmp w3, 4 + b.lt .Lcbcdec3x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + bl sm4_encrypt_block4x + sub x5, x1, 64 + ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x5], #64 + eor BLK0.16b, BLK0.16b, IV.16b + eor BLK1.16b, BLK1.16b, TMP0.16b + eor BLK2.16b, BLK2.16b, TMP1.16b + eor BLK3.16b, BLK3.16b, TMP2.16b + mov IV.16b, TMP3.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + sub w3, w3, #4 + b .Lcbcdec4x + +.Lcbcdec3x: + ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 + bl sm4_encrypt_block4x + sub x5, x1, 48 + ld1 {TMP0.16b, TMP1.16b, TMP2.16b}, [x5], #48 + eor BLK0.16b, BLK0.16b, IV.16b + eor BLK1.16b, BLK1.16b, TMP0.16b + eor BLK2.16b, BLK2.16b, TMP1.16b + mov IV.16b, TMP2.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 + subs w3, w3, #3 + b.le .Lcbcdecout + +.Lcbcdec2x: + ld1 {BLK0.16b, BLK1.16b}, [x1], #32 + bl sm4_encrypt_block4x + sub x5, x1, 32 + ld1 {TMP0.16b, TMP1.16b}, [x5], #32 + eor BLK0.16b, BLK0.16b, IV.16b + eor BLK1.16b, BLK1.16b, TMP0.16b + mov IV.16b, TMP1.16b + st1 {BLK0.16b, BLK1.16b}, [x0], #32 + subs w3, w3, #2 + b.le .Lcbcdecout + +.Lcbcdec1x: + ld1 {BLK0.16b}, [x1], #16 + bl sm4_encrypt_block1x + sub x5, x1, 16 + ld1 {TMP0.16b}, [x5], #16 + eor BLK0.16b, BLK0.16b, IV.16b + mov IV.16b, TMP0.16b + st1 {BLK0.16b}, [x0], #16 + +.Lcbcdecout: + st1 {IV.16b}, [x4] + frame_pop + ret +END_FUNC neon_sm4_cbc_decrypt + +/* + * void neon_sm4_ctr_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], size_t len, + * uint8_t iv[]); + * x0: output + * x1: input + * x2: round key + * w3: length + * x4: iv + */ +FUNC neon_sm4_ctr_encrypt , : + frame_push + load_sbox_matrix + + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + lsr w3, w3, 4 + ldp x7, x8, [x4] + rev x7, x7 + rev x8, x8 + +.Lctrloop8x: + cmp w3, 8 + b.lt .Lctr4x + + /* construct CTRs */ + inc_le128 BLK0, x7, x8 + inc_le128 BLK1, x7, x8 + inc_le128 BLK2, x7, x8 + inc_le128 BLK3, x7, x8 + inc_le128 BLK4, x7, x8 + inc_le128 BLK5, x7, x8 + inc_le128 BLK6, x7, x8 + inc_le128 BLK7, x7, x8 + bl sm4_encrypt_block8x + ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x1], #64 + ld1 {TMP4.16b, TMP5.16b, TMP6.16b, TMP7.16b}, [x1], #64 + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + eor BLK3.16b, BLK3.16b, TMP3.16b + eor BLK4.16b, BLK4.16b, TMP4.16b + eor BLK5.16b, BLK5.16b, TMP5.16b + eor BLK6.16b, BLK6.16b, TMP6.16b + eor BLK7.16b, BLK7.16b, TMP7.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 + subs w3, w3, #8 + b.gt .Lctrloop8x + +.Lctr4x: + cmp w3, 1 + b.lt .Lctrout + cmp w3, 2 + b.lt .Lctr1x + cmp w3, 3 + b.lt .Lctr2x + cmp w3, 4 + b.lt .Lctr3x + inc_le128 BLK0, x7, x8 + inc_le128 BLK1, x7, x8 + inc_le128 BLK2, x7, x8 + inc_le128 BLK3, x7, x8 + bl sm4_encrypt_block4x + ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x1], #64 + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + eor BLK3.16b, BLK3.16b, TMP3.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + sub w3, w3, #4 + b .Lctr4x + +.Lctr3x: + inc_le128 BLK0, x7, x8 + inc_le128 BLK1, x7, x8 + inc_le128 BLK2, x7, x8 + bl sm4_encrypt_block4x + ld1 {TMP0.16b, TMP1.16b, TMP2.16b}, [x1], #48 + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 + subs w3, w3, #3 + b.le .Lctrout + +.Lctr2x: + inc_le128 BLK0, x7, x8 + inc_le128 BLK1, x7, x8 + bl sm4_encrypt_block4x + ld1 {TMP0.16b, TMP1.16b}, [x1], #32 + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + st1 {BLK0.16b, BLK1.16b}, [x0], #32 + subs w3, w3, #2 + b.le .Lctrout + +.Lctr1x: + inc_le128 BLK0, x7, x8 + bl sm4_encrypt_block1x + ld1 {TMP0.16b}, [x1], #16 + eor BLK0.16b, BLK0.16b, TMP0.16b + st1 {BLK0.16b}, [x0], #16 + +.Lctrout: + rev x7, x7 + rev x8, x8 + stp x7, x8, [x4] + frame_pop + ret +END_FUNC neon_sm4_ctr_encrypt + +/* + * x0: output + * x1: input + * x2: round key1 + * x3: round key2 + * w4: blocks + * x26: enc/dec + */ +LOCAL_FUNC xts_do_cipher , : + stp x29, x30, [sp, #-16]! + mov x29, sp + load_sbox_matrix + ld1 {IV.16b}, [x5] + /* load round key2 for first tweak */ + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x3], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x3], #64 + encrypt_block IV + /* load round key1 for block cipher */ + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + /* w6: remain */ + and w6, w4, #0x0F + /* w4: blocks */ + lsr w4, w4, 4 + /* blocks == 0: ret */ + cmp w4, #1 + b.lt .Lxtsout + cmp w6, 0 + b.eq .Lxtsblks + subs w4, w4, #1 + b.eq .Lxtstail +.Lxtsblks: + mov tw0l, IV.d[0] + mov tw0h, IV.d[1] + next_tweak tw1l, tw1h, tw0l, tw0h + next_tweak tw2l, tw2h, tw1l, tw1h + next_tweak tw3l, tw3h, tw2l, tw2h + next_tweak tw4l, tw4h, tw3l, tw3h + next_tweak tw5l, tw5h, tw4l, tw4h + next_tweak tw6l, tw6h, tw5l, tw5h + next_tweak tw7l, tw7h, tw6l, tw6h +.Lxtsloop8x: + cmp w4, 8 + b.lt .Lxts4x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + mov_reg_to_vec TMP0, tw0l, tw0h + mov_reg_to_vec TMP1, tw1l, tw1h + mov_reg_to_vec TMP2, tw2l, tw2h + mov_reg_to_vec TMP3, tw3l, tw3h + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + eor BLK3.16b, BLK3.16b, TMP3.16b + ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 + mov_reg_to_vec TMP4, tw4l, tw4h + mov_reg_to_vec TMP5, tw5l, tw5h + mov_reg_to_vec TMP6, tw6l, tw6h + mov_reg_to_vec IV, tw7l, tw7h + eor BLK4.16b, BLK4.16b, TMP4.16b + eor BLK5.16b, BLK5.16b, TMP5.16b + eor BLK6.16b, BLK6.16b, TMP6.16b + eor BLK7.16b, BLK7.16b, IV.16b + + bl sm4_encrypt_block8x + + mov_reg_to_vec TMP0, tw0l, tw0h + next_tweak tw0l, tw0h, tw7l, tw7h + mov_reg_to_vec TMP1, tw1l, tw1h + next_tweak tw1l, tw1h, tw0l, tw0h + mov_reg_to_vec TMP2, tw2l, tw2h + next_tweak tw2l, tw2h, tw1l, tw1h + mov_reg_to_vec TMP3, tw3l, tw3h + next_tweak tw3l, tw3h, tw2l, tw2h + mov_reg_to_vec TMP4, tw4l, tw4h + next_tweak tw4l, tw4h, tw3l, tw3h + mov_reg_to_vec TMP5, tw5l, tw5h + next_tweak tw5l, tw5h, tw4l, tw4h + mov_reg_to_vec TMP6, tw6l, tw6h + next_tweak tw6l, tw6h, tw5l, tw5h + mov_reg_to_vec IV, tw7l, tw7h + next_tweak tw7l, tw7h, tw6l, tw6h + + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + eor BLK3.16b, BLK3.16b, TMP3.16b + eor BLK4.16b, BLK4.16b, TMP4.16b + eor BLK5.16b, BLK5.16b, TMP5.16b + eor BLK6.16b, BLK6.16b, TMP6.16b + eor BLK7.16b, BLK7.16b, IV.16b + + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 + subs w4, w4, #8 + b.gt .Lxtsloop8x + +.Lxts4x: + cmp w4, 1 + b.lt .Lxtsblksout + cmp w4, 2 + b.lt .Lxts1x + cmp w4, 3 + b.lt .Lxts2x + cmp w4, 4 + b.lt .Lxts3x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + mov_reg_to_vec BLK4, tw0l, tw0h + mov_reg_to_vec BLK5, tw1l, tw1h + mov_reg_to_vec BLK6, tw2l, tw2h + mov_reg_to_vec IV, tw3l, tw3h + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, BLK5.16b + eor BLK2.16b, BLK2.16b, BLK6.16b + eor BLK3.16b, BLK3.16b, IV.16b + bl sm4_encrypt_block4x + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, BLK5.16b + eor BLK2.16b, BLK2.16b, BLK6.16b + eor BLK3.16b, BLK3.16b, IV.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + sub w4, w4, #4 + + mov tw0l, tw4l + mov tw0h, tw4h + mov tw1l, tw5l + mov tw1h, tw5h + mov tw2l, tw6l + mov tw2h, tw6h + b .Lxts4x + +.Lxts3x: + ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 + mov_reg_to_vec BLK4, tw0l, tw0h + mov_reg_to_vec BLK5, tw1l, tw1h + mov_reg_to_vec IV, tw2l, tw2h + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, BLK5.16b + eor BLK2.16b, BLK2.16b, IV.16b + bl sm4_encrypt_block4x + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, BLK5.16b + eor BLK2.16b, BLK2.16b, IV.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 + subs w4, w4, #3 + b.le .Lxtsblksout + +.Lxts2x: + ld1 {BLK0.16b, BLK1.16b}, [x1], #32 + mov_reg_to_vec BLK4, tw0l, tw0h + mov_reg_to_vec IV, tw1l, tw1h + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, IV.16b + bl sm4_encrypt_block4x + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, IV.16b + st1 {BLK0.16b, BLK1.16b}, [x0], #32 + subs w4, w4, #2 + b.le .Lxtsblksout + +.Lxts1x: + ld1 {BLK0.16b}, [x1], #16 + mov_reg_to_vec IV, tw0l, tw0h + eor BLK0.16b, BLK0.16b, IV.16b + bl sm4_encrypt_block1x + eor BLK0.16b, BLK0.16b, IV.16b + st1 {BLK0.16b}, [x0], #16 +.Lxtsblksout: + cmp w6, 0 + /* if encrypt some blocks with a partial block */ + next_tweak_vec IV, IV + b.eq .Lxtsout +.Lxtstail: + next_tweak_vec TMP7, IV + cmp x26, 1 + b.eq 1f + /* The last two tweaks IV, TMP7 need to be swapped for decryption */ + mov TMP8.16b, IV.16b + mov IV.16b, TMP7.16b + mov TMP7.16b, TMP8.16b + 1: + ld1 {BLK0.16b}, [x1], #16 + eor BLK0.16b, BLK0.16b, IV.16b + bl sm4_encrypt_block1x + eor BLK0.16b, BLK0.16b, IV.16b + st1 {BLK0.16b}, [x0], #16 + sub x7, x0, 16 + 10: + subs x6, x6, 1 + ldrb tmpw0, [x7, x6] + strb tmpw0, [x0, x6] + ldrb tmpw0, [x1, x6] + strb tmpw0, [x7, x6] + b.gt 10b + ld1 {BLK0.16b}, [x7] + eor BLK0.16b, BLK0.16b, TMP7.16b + bl sm4_encrypt_block1x + eor BLK0.16b, BLK0.16b, TMP7.16b + st1 {BLK0.16b}, [x7] + +.Lxtsout: + /* load round key2 for last tweak */ + sub x3, x3, #128 + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x3], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x3], #64 + /* decrypt last tweak for next update */ + decrypt_block IV + st1 {IV.16b}, [x5] + ldp x29, x30, [sp], #16 + ret +END_FUNC xts_do_cipher + +/* + * void neon_sm4_xts_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk1[], uint8_t const rk2[], + * size_t len, uint8_t iv[]) + * x0: output + * x1: input + * x2: round key1 + * x3: round key2 + * w4: len + * x5: iv + */ +FUNC neon_sm4_xts_encrypt , : + frame_push + mov x26, 1 + bl xts_do_cipher + frame_pop + ret +END_FUNC neon_sm4_xts_encrypt + +/* + * void neon_sm4_xts_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk1[], uint8_t const rk2[], + * size_t len, uint8_t iv[]) + * x0: output + * x1: input + * x2: round key1 + * x3: round key2 + * w4: len + * x5: iv + */ +FUNC neon_sm4_xts_decrypt , : + frame_push + mov x26, 0 + bl xts_do_cipher + frame_pop + ret +END_FUNC neon_sm4_xts_decrypt diff --git a/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.c b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.c new file mode 100644 index 0000000..cd8f35b --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. + * + * SM4 optimization for ARMv8 by SM4 HW instruction, which is an optional + * Cryptographic Extension for ARMv8.2-A. + */ +#include +#include + +#include "sm4_armv8a_ce.h" + +void crypto_accel_sm4_setkey_enc(uint32_t sk[32], const uint8_t key[16]) +{ + uint32_t vfp_state = 0; + + assert(sk && key); + + vfp_state = thread_kernel_enable_vfp(); + ce_sm4_setkey_enc(sk, key); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_setkey_dec(uint32_t sk[32], const uint8_t key[16]) +{ + uint32_t vfp_state = 0; + + assert(sk && key); + + vfp_state = thread_kernel_enable_vfp(); + ce_sm4_setkey_dec(sk, key); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_ecb_enc(void *out, const void *in, const void *key, + unsigned int len) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && !(len % 16)); + + vfp_state = thread_kernel_enable_vfp(); + ce_sm4_ecb_encrypt(out, in, key, len); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_cbc_enc(void *out, const void *in, const void *key, + unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && !(len % 16)); + + vfp_state = thread_kernel_enable_vfp(); + ce_sm4_cbc_encrypt(out, in, key, len, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_cbc_dec(void *out, const void *in, const void *key, + unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && !(len % 16)); + + vfp_state = thread_kernel_enable_vfp(); + ce_sm4_cbc_decrypt(out, in, key, len, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_ctr_enc(void *out, const void *in, const void *key, + unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && !(len % 16)); + + vfp_state = thread_kernel_enable_vfp(); + ce_sm4_ctr_encrypt(out, in, key, len, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_xts_enc(void *out, const void *in, const void *key1, + const void *key2, unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key1 && key2 && (len >= 16)); + + vfp_state = thread_kernel_enable_vfp(); + ce_sm4_xts_encrypt(out, in, key1, key2, len, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_xts_dec(void *out, const void *in, const void *key1, + const void *key2, unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key1 && key2 && (len >= 16)); + + vfp_state = thread_kernel_enable_vfp(); + ce_sm4_xts_decrypt(out, in, key1, key2, len, iv); + thread_kernel_disable_vfp(vfp_state); +} diff --git a/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.h b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.h new file mode 100644 index 0000000..5e1c2ed --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. + */ + +#ifndef __SM4_ARMV8_CE_H +#define __SM4_ARMV8_CE_H + +#include + +/* Prototypes for assembly functions */ +void ce_sm4_setkey_enc(uint32_t sk[32], uint8_t const key[16]); +void ce_sm4_setkey_dec(uint32_t sk[32], uint8_t const key[16]); +void ce_sm4_ecb_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + size_t len); +void ce_sm4_cbc_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + size_t len, uint8_t iv[]); +void ce_sm4_cbc_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + size_t len, uint8_t iv[]); +void ce_sm4_ctr_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + size_t len, uint8_t iv[]); +void ce_sm4_xts_encrypt(uint8_t out[], uint8_t const in[], + uint8_t const rk1[], uint8_t const rk2[], size_t len, + uint8_t iv[]); +void ce_sm4_xts_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], + uint8_t const rk2[], size_t len, uint8_t iv[]); + +#endif /*__SM4_ARMV8_CE_H*/ diff --git a/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce_a64.S b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce_a64.S new file mode 100644 index 0000000..1f96bbf --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_ce_a64.S @@ -0,0 +1,1030 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. + * Copyright (C) 2022, Alibaba Group. + * Copyright (C) 2022 Tianjia Zhang + * + * SM4 optimization for ARMv8 by SM4 HW instruction, which is an optional + * Cryptographic Extension for ARMv8.2-A. + * + * The CE implementation refers to Linux kernel (sm4-ce-core.S contributed + * by Tianjia Zhang ). + */ + +#include + +.arch armv8.2-a+crypto+sm4 + +#define tw0l x7 +#define tw0h x8 +#define tw1l x9 +#define tw1h x10 +#define tw2l x11 +#define tw2h x12 +#define tw3l x13 +#define tw3h x14 +#define tw4l x15 +#define tw4h x16 +#define tw5l x17 +#define tw5h x18 +#define tw6l x19 +#define tw6h x20 +#define tw7l x21 +#define tw7h x22 +#define tmpw0 w23 +#define tmpx0 x23 +#define tmpw1 w24 +#define tmpx1 x24 +#define tmpw2 w25 + +/* round keys: v0-v7 */ +#define RK0 v0 +#define RK1 v1 +#define RK2 v2 +#define RK3 v3 +#define RK4 v4 +#define RK5 v5 +#define RK6 v6 +#define RK7 v7 + +/* plain blocks: v8-v15 */ +#define BLK0 v8 +#define BLK1 v9 +#define BLK2 v10 +#define BLK3 v11 +#define BLK4 v12 +#define BLK5 v13 +#define BLK6 v14 +#define BLK7 v15 + +#define TMP0 v16 +#define TMP1 v17 +#define TMP2 v18 +#define TMP3 v19 +#define TMP4 v20 +#define TMP5 v21 +#define TMP6 v22 +#define TMP7 v23 +#define TMP8 v24 +#define IV v25 + +.macro frame_push + stp x15, x16, [sp, #-0x10]! + stp x17, x18, [sp, #-0x10]! + stp x19, x20, [sp, #-0x10]! + stp x21, x22, [sp, #-0x10]! + stp x23, x24, [sp, #-0x10]! + stp x25, x26, [sp, #-0x10]! + stp x27, x28, [sp, #-0x10]! + stp x29, x30, [sp, #-0x10]! + stp d8, d9, [sp, #-0x10]! + stp d10, d11, [sp, #-0x10]! + stp d12, d13, [sp, #-0x10]! + stp d14, d15, [sp, #-0x10]! +.endm + +.macro frame_pop + ldp d14, d15, [sp], #0x10 + ldp d12, d13, [sp], #0x10 + ldp d10, d11, [sp], #0x10 + ldp d8, d9, [sp], #0x10 + ldp x29, x30, [sp], #0x10 + ldp x27, x28, [sp], #0x10 + ldp x25, x26, [sp], #0x10 + ldp x23, x24, [sp], #0x10 + ldp x21, x22, [sp], #0x10 + ldp x19, x20, [sp], #0x10 + ldp x17, x18, [sp], #0x10 + ldp x15, x16, [sp], #0x10 +.endm + +.macro encrypt_block_no_rev, in + sm4e \in\().4s, RK0.4s + sm4e \in\().4s, RK1.4s + sm4e \in\().4s, RK2.4s + sm4e \in\().4s, RK3.4s + sm4e \in\().4s, RK4.4s + sm4e \in\().4s, RK5.4s + sm4e \in\().4s, RK6.4s + sm4e \in\().4s, RK7.4s + rev64 \in\().4s, \in\().4s + ext \in\().16b, \in\().16b, \in\().16b, #8 +.endm + +.macro encrypt_block, in + rev32 \in\().16b, \in\().16b + sm4e \in\().4s, RK0.4s + sm4e \in\().4s, RK1.4s + sm4e \in\().4s, RK2.4s + sm4e \in\().4s, RK3.4s + sm4e \in\().4s, RK4.4s + sm4e \in\().4s, RK5.4s + sm4e \in\().4s, RK6.4s + sm4e \in\().4s, RK7.4s + rev64 \in\().16b, \in\().16b + ext \in\().16b, \in\().16b, \in\().16b, #8 +.endm + +.macro decrypt_block, in + rev32 \in\().16b, \in\().16b + rev64 RK7.4s, RK7.4s; + rev64 RK6.4s, RK6.4s; + rev64 RK5.4s, RK5.4s; + rev64 RK4.4s, RK4.4s; + ext RK7.16b, RK7.16b, RK7.16b, #8; + ext RK6.16b, RK6.16b, RK6.16b, #8; + ext RK5.16b, RK5.16b, RK5.16b, #8; + ext RK4.16b, RK4.16b, RK4.16b, #8; + sm4e \in\().4s, RK7.4s + sm4e \in\().4s, RK6.4s + sm4e \in\().4s, RK5.4s + sm4e \in\().4s, RK4.4s + rev64 RK3.4s, RK3.4s; + rev64 RK2.4s, RK2.4s; + rev64 RK1.4s, RK1.4s; + rev64 RK0.4s, RK0.4s; + ext RK3.16b, RK3.16b, RK3.16b, #8; + ext RK2.16b, RK2.16b, RK2.16b, #8; + ext RK1.16b, RK1.16b, RK1.16b, #8; + ext RK0.16b, RK0.16b, RK0.16b, #8; + sm4e \in\().4s, RK3.4s + sm4e \in\().4s, RK2.4s + sm4e \in\().4s, RK1.4s + sm4e \in\().4s, RK0.4s + rev64 \in\().16b, \in\().16b + ext \in\().16b, \in\().16b, \in\().16b, #8 +.endm + +LOCAL_FUNC sm4_encrypt_block1x , : + encrypt_block BLK0 + ret +END_FUNC sm4_encrypt_block1x + +LOCAL_FUNC sm4_decrypt_block1x , : + decrypt_block BLK0 + ret +END_FUNC sm4_decrypt_block1x + +LOCAL_FUNC sm4_encrypt_block4x , : + rev32 BLK0.16b, BLK0.16b + rev32 BLK1.16b, BLK1.16b + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + + sm4e BLK0.4s, RK0.4s + sm4e BLK1.4s, RK0.4s + sm4e BLK2.4s, RK0.4s + sm4e BLK3.4s, RK0.4s + + sm4e BLK0.4s, RK1.4s + sm4e BLK1.4s, RK1.4s + sm4e BLK2.4s, RK1.4s + sm4e BLK3.4s, RK1.4s + + sm4e BLK0.4s, RK2.4s + sm4e BLK1.4s, RK2.4s + sm4e BLK2.4s, RK2.4s + sm4e BLK3.4s, RK2.4s + + sm4e BLK0.4s, RK3.4s + sm4e BLK1.4s, RK3.4s + sm4e BLK2.4s, RK3.4s + sm4e BLK3.4s, RK3.4s + + sm4e BLK0.4s, RK4.4s + sm4e BLK1.4s, RK4.4s + sm4e BLK2.4s, RK4.4s + sm4e BLK3.4s, RK4.4s + + sm4e BLK0.4s, RK5.4s + sm4e BLK1.4s, RK5.4s + sm4e BLK2.4s, RK5.4s + sm4e BLK3.4s, RK5.4s + + sm4e BLK0.4s, RK6.4s + sm4e BLK1.4s, RK6.4s + sm4e BLK2.4s, RK6.4s + sm4e BLK3.4s, RK6.4s + + sm4e BLK0.4s, RK7.4s + sm4e BLK1.4s, RK7.4s + sm4e BLK2.4s, RK7.4s + sm4e BLK3.4s, RK7.4s + + rev64 BLK0.16b, BLK0.16b + rev64 BLK1.16b, BLK1.16b + rev64 BLK2.16b, BLK2.16b + rev64 BLK3.16b, BLK3.16b + + ext BLK0.16b, BLK0.16b, BLK0.16b, #8 + ext BLK1.16b, BLK1.16b, BLK1.16b, #8 + ext BLK2.16b, BLK2.16b, BLK2.16b, #8 + ext BLK3.16b, BLK3.16b, BLK3.16b, #8 + ret +END_FUNC sm4_encrypt_block4x + +LOCAL_FUNC sm4_encrypt_block8x , : + rev32 BLK0.16b, BLK0.16b + rev32 BLK1.16b, BLK1.16b + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + rev32 BLK4.16b, BLK4.16b + rev32 BLK5.16b, BLK5.16b + rev32 BLK6.16b, BLK6.16b + rev32 BLK7.16b, BLK7.16b + + sm4e BLK0.4s, RK0.4s + sm4e BLK1.4s, RK0.4s + sm4e BLK2.4s, RK0.4s + sm4e BLK3.4s, RK0.4s + sm4e BLK4.4s, RK0.4s + sm4e BLK5.4s, RK0.4s + sm4e BLK6.4s, RK0.4s + sm4e BLK7.4s, RK0.4s + + sm4e BLK0.4s, RK1.4s + sm4e BLK1.4s, RK1.4s + sm4e BLK2.4s, RK1.4s + sm4e BLK3.4s, RK1.4s + sm4e BLK4.4s, RK1.4s + sm4e BLK5.4s, RK1.4s + sm4e BLK6.4s, RK1.4s + sm4e BLK7.4s, RK1.4s + + sm4e BLK0.4s, RK2.4s + sm4e BLK1.4s, RK2.4s + sm4e BLK2.4s, RK2.4s + sm4e BLK3.4s, RK2.4s + sm4e BLK4.4s, RK2.4s + sm4e BLK5.4s, RK2.4s + sm4e BLK6.4s, RK2.4s + sm4e BLK7.4s, RK2.4s + + sm4e BLK0.4s, RK3.4s + sm4e BLK1.4s, RK3.4s + sm4e BLK2.4s, RK3.4s + sm4e BLK3.4s, RK3.4s + sm4e BLK4.4s, RK3.4s + sm4e BLK5.4s, RK3.4s + sm4e BLK6.4s, RK3.4s + sm4e BLK7.4s, RK3.4s + + sm4e BLK0.4s, RK4.4s + sm4e BLK1.4s, RK4.4s + sm4e BLK2.4s, RK4.4s + sm4e BLK3.4s, RK4.4s + sm4e BLK4.4s, RK4.4s + sm4e BLK5.4s, RK4.4s + sm4e BLK6.4s, RK4.4s + sm4e BLK7.4s, RK4.4s + + sm4e BLK0.4s, RK5.4s + sm4e BLK1.4s, RK5.4s + sm4e BLK2.4s, RK5.4s + sm4e BLK3.4s, RK5.4s + sm4e BLK4.4s, RK5.4s + sm4e BLK5.4s, RK5.4s + sm4e BLK6.4s, RK5.4s + sm4e BLK7.4s, RK5.4s + + sm4e BLK0.4s, RK6.4s + sm4e BLK1.4s, RK6.4s + sm4e BLK2.4s, RK6.4s + sm4e BLK3.4s, RK6.4s + sm4e BLK4.4s, RK6.4s + sm4e BLK5.4s, RK6.4s + sm4e BLK6.4s, RK6.4s + sm4e BLK7.4s, RK6.4s + + sm4e BLK0.4s, RK7.4s + sm4e BLK1.4s, RK7.4s + sm4e BLK2.4s, RK7.4s + sm4e BLK3.4s, RK7.4s + sm4e BLK4.4s, RK7.4s + sm4e BLK5.4s, RK7.4s + sm4e BLK6.4s, RK7.4s + sm4e BLK7.4s, RK7.4s + + rev64 BLK0.16b, BLK0.16b + rev64 BLK1.16b, BLK1.16b + rev64 BLK2.16b, BLK2.16b + rev64 BLK3.16b, BLK3.16b + rev64 BLK4.16b, BLK4.16b + rev64 BLK5.16b, BLK5.16b + rev64 BLK6.16b, BLK6.16b + rev64 BLK7.16b, BLK7.16b + + ext BLK0.16b, BLK0.16b, BLK0.16b, #8 + ext BLK1.16b, BLK1.16b, BLK1.16b, #8 + ext BLK2.16b, BLK2.16b, BLK2.16b, #8 + ext BLK3.16b, BLK3.16b, BLK3.16b, #8 + ext BLK4.16b, BLK4.16b, BLK4.16b, #8 + ext BLK5.16b, BLK5.16b, BLK5.16b, #8 + ext BLK6.16b, BLK6.16b, BLK6.16b, #8 + ext BLK7.16b, BLK7.16b, BLK7.16b, #8 + ret +END_FUNC sm4_encrypt_block8x + +.macro inc_le128, vctr, low, high + mov \vctr\().d[1], \high + mov \vctr\().d[0], \low + adds \high, \high, #1 + adc \low, \low, xzr + rev64 \vctr\().16b, \vctr\().16b +.endm + +.macro mov_reg_to_vec, desv, src0, src1 + mov \desv\().d[0], \src0 + mov \desv\().d[1], \src1 +.endm + +.macro next_tweak, des0, des1, src0, src1 + mov tmpw2, 0x87 + extr tmpx0, \src1, \src1, #32 + extr \des1, \src1, \src0, #63 + and tmpw1, tmpw2, tmpw0, asr#31 + eor \des0, tmpx1, \src0, lsl#1 +.endm + +.macro next_tweak_vec, desv, srcv + mov tw0l, \srcv\().d[0] + mov tw0h, \srcv\().d[1] + next_tweak tw1l, tw1h, tw0l, tw0h + mov \desv\().d[0], tw1l + mov \desv\().d[1], tw1h +.endm + +LOCAL_DATA .Lck , : + .long 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269 + .long 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9 + .long 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249 + .long 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9 + .long 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229 + .long 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299 + .long 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209 + .long 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 +END_DATA .Lck + +LOCAL_DATA .Lfk , : + .long 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc +END_DATA .Lfk + +/* + * void ce_sm4_setkey_enc(uint32_t sk[32], uint8_t const key[16]); + * x0: round key + * x1: user key + */ +FUNC ce_sm4_setkey_enc , : + ld1 {RK0.4s}, [x1] + adr x2, .Lfk + ld1 {TMP8.4s}, [x2] + adr x2, .Lck + ld1 {TMP0.4s, TMP1.4s, TMP2.4s, TMP3.4s}, [x2], 64 + rev32 RK0.16b, RK0.16b + ld1 {TMP4.4s, TMP5.4s, TMP6.4s, TMP7.4s}, [x2] + eor RK0.16b, RK0.16b, TMP8.16b + sm4ekey RK0.4s, RK0.4s, TMP0.4s + sm4ekey RK1.4s, RK0.4s, TMP1.4s + sm4ekey RK2.4s, RK1.4s, TMP2.4s + sm4ekey RK3.4s, RK2.4s, TMP3.4s + sm4ekey RK4.4s, RK3.4s, TMP4.4s + st1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x0], 64 + sm4ekey RK5.4s, RK4.4s, TMP5.4s + sm4ekey RK6.4s, RK5.4s, TMP6.4s + sm4ekey RK7.4s, RK6.4s, TMP7.4s + st1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x0] + ret +END_FUNC ce_sm4_setkey_enc + +/* + * void ce_sm4_setkey_dec(uint32_t sk[32], uint8_t const key[16]); + * x0: round key + * x1: user key + */ +FUNC ce_sm4_setkey_dec , : + ld1 {RK7.4s}, [x1] + adr x2, .Lfk + ld1 {TMP8.4s}, [x2] + adr x2, .Lck + ld1 {TMP0.4s, TMP1.4s, TMP2.4s, TMP3.4s}, [x2], 64 + rev32 RK7.16b, RK7.16b + ld1 {TMP4.4s, TMP5.4s, TMP6.4s, TMP7.4s}, [x2] + eor RK7.16b, RK7.16b, TMP8.16b; + sm4ekey RK7.4s, RK7.4s, TMP0.4s + sm4ekey RK6.4s, RK7.4s, TMP1.4s + sm4ekey RK5.4s, RK6.4s, TMP2.4s + rev64 RK7.4s, RK7.4s + rev64 RK6.4s, RK6.4s + ext RK7.16b, RK7.16b, RK7.16b, #8 + ext RK6.16b, RK6.16b, RK6.16b, #8 + sm4ekey RK4.4s, RK5.4s, TMP3.4s + sm4ekey RK3.4s, RK4.4s, TMP4.4s + rev64 RK5.4s, RK5.4s + rev64 RK4.4s, RK4.4s + ext RK5.16b, RK5.16b, RK5.16b, #8 + ext RK4.16b, RK4.16b, RK4.16b, #8 + sm4ekey RK2.4s, RK3.4s, TMP5.4s + sm4ekey RK1.4s, RK2.4s, TMP6.4s + rev64 RK3.4s, RK3.4s + rev64 RK2.4s, RK2.4s + ext RK3.16b, RK3.16b, RK3.16b, #8 + ext RK2.16b, RK2.16b, RK2.16b, #8 + sm4ekey RK0.4s, RK1.4s, TMP7.4s + rev64 RK1.4s, RK1.4s + rev64 RK0.4s, RK0.4s + ext RK1.16b, RK1.16b, RK1.16b, #8 + ext RK0.16b, RK0.16b, RK0.16b, #8 + st1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x0], 64 + st1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x0] + ret +END_FUNC ce_sm4_setkey_dec + +/* + * void ce_sm4_ecb_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], size_t len); + * x0: output + * x1: input + * x2: round key + * w3: length + */ +FUNC ce_sm4_ecb_encrypt , : + frame_push + + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + lsr w3, w3, 4 + +.Lecbloop8x: + cmp w3, 8 + b.lt .Lecb4x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 + bl sm4_encrypt_block8x + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 + subs w3, w3, #8 + b.gt .Lecbloop8x + +.Lecb4x: + cmp w3, 1 + b.lt .Lecbout + cmp w3, 2 + b.lt .Lecb1x + cmp w3, 3 + b.lt .Lecb2x + cmp w3, 4 + b.lt .Lecb3x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + bl sm4_encrypt_block4x + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + sub w3, w3, #4 + b .Lecb4x + +.Lecb3x: + ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 + bl sm4_encrypt_block4x + st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 + subs w3, w3, #3 + b.le .Lecbout + +.Lecb2x: + ld1 {BLK0.16b, BLK1.16b}, [x1], #32 + bl sm4_encrypt_block4x + st1 {BLK0.16b, BLK1.16b}, [x0], #32 + subs w3, w3, #2 + b.le .Lecbout + +.Lecb1x: + ld1 {BLK0.16b}, [x1], #16 + bl sm4_encrypt_block1x + st1 {BLK0.16b}, [x0], #16 + +.Lecbout: + frame_pop + ret + +END_FUNC ce_sm4_ecb_encrypt + +/* + * void ce_sm4_cbc_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], size_t len, + * uint8_t iv[]); + * x0: output + * x1: input + * x2: round key + * w3: length + * x4: iv + */ +FUNC ce_sm4_cbc_encrypt , : + frame_push + + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + lsr w3, w3, 4 + ld1 {IV.16b}, [x4] + +.Lcbcencloop4x: + cmp w3, 4 + b.lt .Lcbcenc1x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + eor BLK0.16b, BLK0.16b, IV.16b + rev32 BLK0.16b, BLK0.16b + rev32 BLK1.16b, BLK1.16b + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + encrypt_block_no_rev BLK0 + eor BLK1.16b, BLK1.16b, BLK0.16b + encrypt_block_no_rev BLK1 + rev32 BLK0.16b, BLK0.16b + eor BLK2.16b, BLK2.16b, BLK1.16b + encrypt_block_no_rev BLK2 + rev32 BLK1.16b, BLK1.16b + eor BLK3.16b, BLK3.16b, BLK2.16b + encrypt_block_no_rev BLK3 + rev32 BLK2.16b, BLK2.16b + rev32 BLK3.16b, BLK3.16b + mov IV.16b, BLK3.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + subs w3, w3, #4 + b .Lcbcencloop4x +.Lcbcenc1x: + cmp w3, 1 + b.lt .Lcbcencout +.Lcbcencloop: + ld1 {BLK0.16b}, [x1], #16 + eor BLK0.16b, BLK0.16b, IV.16b + bl sm4_encrypt_block1x + mov IV.16b, BLK0.16b + st1 {BLK0.16b}, [x0], #16 + subs w3, w3, #1 + bne .Lcbcencloop +.Lcbcencout: + st1 {IV.16b}, [x4] + frame_pop + ret +END_FUNC ce_sm4_cbc_encrypt + +/* + * void ce_sm4_cbc_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], size_t len, + * uint8_t iv[]); + * x0: output + * x1: input + * x2: round key + * w3: length + * x4: iv + */ +FUNC ce_sm4_cbc_decrypt , : + frame_push + + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + lsr w3, w3, 4 + ld1 {IV.16b}, [x4] + +.Lcbcdecloop8x: + cmp w3, 8 + b.lt .Lcbcdec4x + + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 + bl sm4_encrypt_block8x + sub x5, x1, #128 + eor BLK0.16b, BLK0.16b, IV.16b + ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x5], #64 + eor BLK1.16b, BLK1.16b, TMP0.16b + eor BLK2.16b, BLK2.16b, TMP1.16b + eor BLK3.16b, BLK3.16b, TMP2.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + ld1 {TMP4.16b, TMP5.16b, TMP6.16b, TMP7.16b}, [x5], #64 + eor BLK4.16b, BLK4.16b, TMP3.16b + eor BLK5.16b, BLK5.16b, TMP4.16b + mov IV.16b, TMP7.16b + eor BLK6.16b, BLK6.16b, TMP5.16b + eor BLK7.16b, BLK7.16b, TMP6.16b + st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 + subs w3, w3, #8 + b.gt .Lcbcdecloop8x + +.Lcbcdec4x: + cmp w3, 1 + b.lt .Lcbcdecout + cmp w3, 2 + b.lt .Lcbcdec1x + cmp w3, 3 + b.lt .Lcbcdec2x + cmp w3, 4 + b.lt .Lcbcdec3x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + bl sm4_encrypt_block4x + sub x5, x1, 64 + ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x5], #64 + eor BLK0.16b, BLK0.16b, IV.16b + eor BLK1.16b, BLK1.16b, TMP0.16b + eor BLK2.16b, BLK2.16b, TMP1.16b + eor BLK3.16b, BLK3.16b, TMP2.16b + mov IV.16b, TMP3.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + sub w3, w3, #4 + b .Lcbcdec4x + +.Lcbcdec3x: + ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 + bl sm4_encrypt_block4x + sub x5, x1, 48 + ld1 {TMP0.16b, TMP1.16b, TMP2.16b}, [x5], #48 + eor BLK0.16b, BLK0.16b, IV.16b + eor BLK1.16b, BLK1.16b, TMP0.16b + eor BLK2.16b, BLK2.16b, TMP1.16b + mov IV.16b, TMP2.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 + subs w3, w3, #3 + b.le .Lcbcdecout + +.Lcbcdec2x: + ld1 {BLK0.16b, BLK1.16b}, [x1], #32 + bl sm4_encrypt_block4x + sub x5, x1, 32 + ld1 {TMP0.16b, TMP1.16b}, [x5], #32 + eor BLK0.16b, BLK0.16b, IV.16b + eor BLK1.16b, BLK1.16b, TMP0.16b + mov IV.16b, TMP1.16b + st1 {BLK0.16b, BLK1.16b}, [x0], #32 + subs w3, w3, #2 + b.le .Lcbcdecout + +.Lcbcdec1x: + ld1 {BLK0.16b}, [x1], #16 + bl sm4_encrypt_block1x + sub x5, x1, 16 + ld1 {TMP0.16b}, [x5], #16 + eor BLK0.16b, BLK0.16b, IV.16b + mov IV.16b, TMP0.16b + st1 {BLK0.16b}, [x0], #16 + +.Lcbcdecout: + st1 {IV.16b}, [x4] + frame_pop + ret +END_FUNC ce_sm4_cbc_decrypt + +/* + * void ce_sm4_ctr_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk[], size_t len, + * uint8_t iv[]); + * x0: output + * x1: input + * x2: round key + * w3: length + * x4: iv + */ +FUNC ce_sm4_ctr_encrypt , : + frame_push + + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + lsr w3, w3, 4 + ldp x7, x8, [x4] + rev x7, x7 + rev x8, x8 + +.Lctrloop8x: + cmp w3, 8 + b.lt .Lctr4x + + /* construct CTRs */ + inc_le128 BLK0, x7, x8 + inc_le128 BLK1, x7, x8 + inc_le128 BLK2, x7, x8 + inc_le128 BLK3, x7, x8 + inc_le128 BLK4, x7, x8 + inc_le128 BLK5, x7, x8 + inc_le128 BLK6, x7, x8 + inc_le128 BLK7, x7, x8 + bl sm4_encrypt_block8x + ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x1], #64 + ld1 {TMP4.16b, TMP5.16b, TMP6.16b, TMP7.16b}, [x1], #64 + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + eor BLK3.16b, BLK3.16b, TMP3.16b + eor BLK4.16b, BLK4.16b, TMP4.16b + eor BLK5.16b, BLK5.16b, TMP5.16b + eor BLK6.16b, BLK6.16b, TMP6.16b + eor BLK7.16b, BLK7.16b, TMP7.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 + subs w3, w3, #8 + b.gt .Lctrloop8x + +.Lctr4x: + cmp w3, 1 + b.lt .Lctrout + cmp w3, 2 + b.lt .Lctr1x + cmp w3, 3 + b.lt .Lctr2x + cmp w3, 4 + b.lt .Lctr3x + inc_le128 BLK0, x7, x8 + inc_le128 BLK1, x7, x8 + inc_le128 BLK2, x7, x8 + inc_le128 BLK3, x7, x8 + bl sm4_encrypt_block4x + ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x1], #64 + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + eor BLK3.16b, BLK3.16b, TMP3.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + sub w3, w3, #4 + b .Lctr4x + +.Lctr3x: + inc_le128 BLK0, x7, x8 + inc_le128 BLK1, x7, x8 + inc_le128 BLK2, x7, x8 + bl sm4_encrypt_block4x + ld1 {TMP0.16b, TMP1.16b, TMP2.16b}, [x1], #48 + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 + subs w3, w3, #3 + b.le .Lctrout + +.Lctr2x: + inc_le128 BLK0, x7, x8 + inc_le128 BLK1, x7, x8 + bl sm4_encrypt_block4x + ld1 {TMP0.16b, TMP1.16b}, [x1], #32 + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + st1 {BLK0.16b, BLK1.16b}, [x0], #32 + subs w3, w3, #2 + b.le .Lctrout + +.Lctr1x: + inc_le128 BLK0, x7, x8 + bl sm4_encrypt_block1x + ld1 {TMP0.16b}, [x1], #16 + eor BLK0.16b, BLK0.16b, TMP0.16b + st1 {BLK0.16b}, [x0], #16 + +.Lctrout: + rev x7, x7 + rev x8, x8 + stp x7, x8, [x4] + frame_pop + ret +END_FUNC ce_sm4_ctr_encrypt + +/* + * x0: output + * x1: input + * x2: round key1 + * x3: round key2 + * w4: blocks + * x26: enc/dec + */ +LOCAL_FUNC xts_do_cipher , : + stp x29, x30, [sp, #-16]! + mov x29, sp + + ld1 {IV.16b}, [x5] + /* load round key2 for first tweak */ + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x3], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x3], #64 + encrypt_block IV + /* load round key1 for block cipher */ + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 + /* w6: remain */ + and w6, w4, #0x0F + /* w4: blocks */ + lsr w4, w4, 4 + /* blocks == 0: ret */ + cmp w4, #1 + b.lt .Lxtsout + cmp w6, 0 + b.eq .Lxtsblks + subs w4, w4, #1 + b.eq .Lxtstail +.Lxtsblks: + mov tw0l, IV.d[0] + mov tw0h, IV.d[1] + next_tweak tw1l, tw1h, tw0l, tw0h + next_tweak tw2l, tw2h, tw1l, tw1h + next_tweak tw3l, tw3h, tw2l, tw2h + next_tweak tw4l, tw4h, tw3l, tw3h + next_tweak tw5l, tw5h, tw4l, tw4h + next_tweak tw6l, tw6h, tw5l, tw5h + next_tweak tw7l, tw7h, tw6l, tw6h +.Lxtsloop8x: + cmp w4, 8 + b.lt .Lxts4x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + mov_reg_to_vec TMP0, tw0l, tw0h + mov_reg_to_vec TMP1, tw1l, tw1h + mov_reg_to_vec TMP2, tw2l, tw2h + mov_reg_to_vec TMP3, tw3l, tw3h + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + eor BLK3.16b, BLK3.16b, TMP3.16b + ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 + mov_reg_to_vec TMP4, tw4l, tw4h + mov_reg_to_vec TMP5, tw5l, tw5h + mov_reg_to_vec TMP6, tw6l, tw6h + mov_reg_to_vec IV, tw7l, tw7h + eor BLK4.16b, BLK4.16b, TMP4.16b + eor BLK5.16b, BLK5.16b, TMP5.16b + eor BLK6.16b, BLK6.16b, TMP6.16b + eor BLK7.16b, BLK7.16b, IV.16b + + bl sm4_encrypt_block8x + + mov_reg_to_vec TMP0, tw0l, tw0h + next_tweak tw0l, tw0h, tw7l, tw7h + mov_reg_to_vec TMP1, tw1l, tw1h + next_tweak tw1l, tw1h, tw0l, tw0h + mov_reg_to_vec TMP2, tw2l, tw2h + next_tweak tw2l, tw2h, tw1l, tw1h + mov_reg_to_vec TMP3, tw3l, tw3h + next_tweak tw3l, tw3h, tw2l, tw2h + mov_reg_to_vec TMP4, tw4l, tw4h + next_tweak tw4l, tw4h, tw3l, tw3h + mov_reg_to_vec TMP5, tw5l, tw5h + next_tweak tw5l, tw5h, tw4l, tw4h + mov_reg_to_vec TMP6, tw6l, tw6h + next_tweak tw6l, tw6h, tw5l, tw5h + mov_reg_to_vec IV, tw7l, tw7h + next_tweak tw7l, tw7h, tw6l, tw6h + + eor BLK0.16b, BLK0.16b, TMP0.16b + eor BLK1.16b, BLK1.16b, TMP1.16b + eor BLK2.16b, BLK2.16b, TMP2.16b + eor BLK3.16b, BLK3.16b, TMP3.16b + eor BLK4.16b, BLK4.16b, TMP4.16b + eor BLK5.16b, BLK5.16b, TMP5.16b + eor BLK6.16b, BLK6.16b, TMP6.16b + eor BLK7.16b, BLK7.16b, IV.16b + + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 + subs w4, w4, #8 + b.gt .Lxtsloop8x + +.Lxts4x: + cmp w4, 1 + b.lt .Lxtsblksout + cmp w4, 2 + b.lt .Lxts1x + cmp w4, 3 + b.lt .Lxts2x + cmp w4, 4 + b.lt .Lxts3x + ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 + mov_reg_to_vec BLK4, tw0l, tw0h + mov_reg_to_vec BLK5, tw1l, tw1h + mov_reg_to_vec BLK6, tw2l, tw2h + mov_reg_to_vec IV, tw3l, tw3h + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, BLK5.16b + eor BLK2.16b, BLK2.16b, BLK6.16b + eor BLK3.16b, BLK3.16b, IV.16b + bl sm4_encrypt_block4x + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, BLK5.16b + eor BLK2.16b, BLK2.16b, BLK6.16b + eor BLK3.16b, BLK3.16b, IV.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 + sub w4, w4, #4 + + mov tw0l, tw4l + mov tw0h, tw4h + mov tw1l, tw5l + mov tw1h, tw5h + mov tw2l, tw6l + mov tw2h, tw6h + b .Lxts4x + +.Lxts3x: + ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 + mov_reg_to_vec BLK4, tw0l, tw0h + mov_reg_to_vec BLK5, tw1l, tw1h + mov_reg_to_vec IV, tw2l, tw2h + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, BLK5.16b + eor BLK2.16b, BLK2.16b, IV.16b + bl sm4_encrypt_block4x + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, BLK5.16b + eor BLK2.16b, BLK2.16b, IV.16b + st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 + subs w4, w4, #3 + b.le .Lxtsblksout + +.Lxts2x: + ld1 {BLK0.16b, BLK1.16b}, [x1], #32 + mov_reg_to_vec BLK4, tw0l, tw0h + mov_reg_to_vec IV, tw1l, tw1h + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, IV.16b + bl sm4_encrypt_block4x + eor BLK0.16b, BLK0.16b, BLK4.16b + eor BLK1.16b, BLK1.16b, IV.16b + st1 {BLK0.16b, BLK1.16b}, [x0], #32 + subs w4, w4, #2 + b.le .Lxtsblksout + +.Lxts1x: + ld1 {BLK0.16b}, [x1], #16 + mov_reg_to_vec IV, tw0l, tw0h + eor BLK0.16b, BLK0.16b, IV.16b + bl sm4_encrypt_block1x + eor BLK0.16b, BLK0.16b, IV.16b + st1 {BLK0.16b}, [x0], #16 +.Lxtsblksout: + cmp w6, 0 + /* if encrypt some blocks with a partial block */ + next_tweak_vec IV, IV + b.eq .Lxtsout +.Lxtstail: + next_tweak_vec TMP7, IV + cmp x26, 1 + b.eq 1f + /* The last two tweaks IV, TMP7 need to be swapped for decryption */ + mov TMP8.16b, IV.16b + mov IV.16b, TMP7.16b + mov TMP7.16b, TMP8.16b + 1: + ld1 {BLK0.16b}, [x1], #16 + eor BLK0.16b, BLK0.16b, IV.16b + bl sm4_encrypt_block1x + eor BLK0.16b, BLK0.16b, IV.16b + st1 {BLK0.16b}, [x0], #16 + sub x7, x0, 16 + 10: + subs x6, x6, 1 + ldrb tmpw0, [x7, x6] + strb tmpw0, [x0, x6] + ldrb tmpw0, [x1, x6] + strb tmpw0, [x7, x6] + b.gt 10b + ld1 {BLK0.16b}, [x7] + eor BLK0.16b, BLK0.16b, TMP7.16b + bl sm4_encrypt_block1x + eor BLK0.16b, BLK0.16b, TMP7.16b + st1 {BLK0.16b}, [x7] + +.Lxtsout: + /* load round key2 for last tweak */ + sub x3, x3, #128 + ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x3], #64 + ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x3], #64 + /* decrypt last tweak for next update */ + decrypt_block IV + st1 {IV.16b}, [x5] + ldp x29, x30, [sp], #16 + ret +END_FUNC xts_do_cipher + +/* + * void ce_sm4_xts_encrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk1[], uint8_t const rk2[], + * size_t len, uint8_t iv[]) + * x0: output + * x1: input + * x2: round key1 + * x3: round key2 + * w4: len + * x5: iv + */ +FUNC ce_sm4_xts_encrypt , : + frame_push + mov x26, 1 + bl xts_do_cipher + frame_pop + ret + +END_FUNC ce_sm4_xts_encrypt + +/* + * void ce_sm4_xts_decrypt(uint8_t out[], uint8_t const in[], + * uint8_t const rk1[], uint8_t const rk2[], + * size_t len, uint8_t iv[]) + * x0: output + * x1: input + * x2: round key1 + * x3: round key2 + * w4: len + * x5: iv + */ +FUNC ce_sm4_xts_decrypt , : + frame_push + mov x26, 0 + bl xts_do_cipher + frame_pop + ret +END_FUNC ce_sm4_xts_decrypt diff --git a/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.c b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.c new file mode 100644 index 0000000..6d1f759 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. + * + * SM4 optimization for ARMv8 by NEON and AES HW instruction, which is an + * optional Cryptographic Extension for ARMv8-A. + */ +#include +#include + +#include "sm4_armv8a_neon.h" + +void crypto_accel_sm4_setkey_enc(uint32_t sk[32], const uint8_t key[16]) +{ + uint32_t vfp_state = 0; + + assert(sk && key); + + vfp_state = thread_kernel_enable_vfp(); + neon_sm4_setkey_enc(sk, key); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_setkey_dec(uint32_t sk[32], const uint8_t key[16]) +{ + uint32_t vfp_state = 0; + + assert(sk && key); + + vfp_state = thread_kernel_enable_vfp(); + neon_sm4_setkey_dec(sk, key); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_ecb_enc(void *out, const void *in, const void *key, + unsigned int len) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && !(len % 16)); + + vfp_state = thread_kernel_enable_vfp(); + neon_sm4_ecb_encrypt(out, in, key, len); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_cbc_enc(void *out, const void *in, const void *key, + unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && !(len % 16)); + + vfp_state = thread_kernel_enable_vfp(); + neon_sm4_cbc_encrypt(out, in, key, len, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_cbc_dec(void *out, const void *in, const void *key, + unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && !(len % 16)); + + vfp_state = thread_kernel_enable_vfp(); + neon_sm4_cbc_decrypt(out, in, key, len, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_ctr_enc(void *out, const void *in, const void *key, + unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key && !(len % 16)); + + vfp_state = thread_kernel_enable_vfp(); + neon_sm4_ctr_encrypt(out, in, key, len, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_xts_enc(void *out, const void *in, const void *key1, + const void *key2, unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key1 && key2 && (len >= 16)); + + vfp_state = thread_kernel_enable_vfp(); + neon_sm4_xts_encrypt(out, in, key1, key2, len, iv); + thread_kernel_disable_vfp(vfp_state); +} + +void crypto_accel_sm4_xts_dec(void *out, const void *in, const void *key1, + const void *key2, unsigned int len, void *iv) +{ + uint32_t vfp_state = 0; + + assert(out && in && key1 && key2 && (len >= 16)); + + vfp_state = thread_kernel_enable_vfp(); + neon_sm4_xts_decrypt(out, in, key1, key2, len, iv); + thread_kernel_disable_vfp(vfp_state); +} diff --git a/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.h b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.h new file mode 100644 index 0000000..addf9d3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sm4_armv8a_neon.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. + */ + +#ifndef __SM4_ARMV8_NEON_H +#define __SM4_ARMV8_NEON_H + +#include + +/* Prototypes for assembly functions */ +void neon_sm4_setkey_enc(uint32_t sk[32], uint8_t const key[16]); +void neon_sm4_setkey_dec(uint32_t sk[32], uint8_t const key[16]); +void neon_sm4_ecb_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + size_t len); +void neon_sm4_cbc_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + size_t len, uint8_t iv[]); +void neon_sm4_cbc_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + size_t len, uint8_t iv[]); +void neon_sm4_ctr_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], + size_t len, uint8_t iv[]); +void neon_sm4_xts_encrypt(uint8_t out[], uint8_t const in[], + uint8_t const rk1[], uint8_t const rk2[], size_t len, + uint8_t iv[]); +void neon_sm4_xts_decrypt(uint8_t out[], uint8_t const in[], + uint8_t const rk1[], uint8_t const rk2[], size_t len, + uint8_t iv[]); + +#endif /*__SM4_ARMV8_NEON_H*/ diff --git a/optee/optee_os/core/arch/arm/crypto/sub.mk b/optee/optee_os/core/arch/arm/crypto/sub.mk new file mode 100644 index 0000000..9179916 --- /dev/null +++ b/optee/optee_os/core/arch/arm/crypto/sub.mk @@ -0,0 +1,47 @@ +ifeq ($(CFG_CRYPTO_WITH_CE),y) +srcs-$(CFG_ARM64_core) += ghash-ce-core_a64.S +srcs-$(CFG_ARM32_core) += ghash-ce-core_a32.S +srcs-y += aes-gcm-ce.c +endif + +ifeq ($(CFG_CRYPTO_AES_ARM_CE),y) +srcs-y += aes_armv8a_ce.c +srcs-$(CFG_ARM64_core) += aes_modes_armv8a_ce_a64.S +aflags-aes_modes_armv8a_ce_a64.S-y += -DINTERLEAVE=4 +srcs-$(CFG_ARM32_core) += aes_modes_armv8a_ce_a32.S +endif + +ifeq ($(CFG_CRYPTO_SHA1_ARM_CE),y) +srcs-y += sha1_armv8a_ce.c +srcs-$(CFG_ARM64_core) += sha1_armv8a_ce_a64.S +srcs-$(CFG_ARM32_core) += sha1_armv8a_ce_a32.S +endif + +ifeq ($(CFG_CRYPTO_SHA256_ARM_CE),y) +srcs-y += sha256_armv8a_ce.c +srcs-$(CFG_ARM64_core) += sha256_armv8a_ce_a64.S +srcs-$(CFG_ARM32_core) += sha256_armv8a_ce_a32.S +endif + +ifeq ($(CFG_CRYPTO_SHA512_ARM_CE),y) +srcs-y += sha512_armv8a_ce.c +srcs-$(CFG_ARM64_core) += sha512_armv8a_ce_a64.S +endif + +ifeq ($(CFG_CRYPTO_SHA3_ARM_CE),y) +srcs-y += sha3_armv8a_ce.c +srcs-$(CFG_ARM64_core) += sha3_armv8a_ce_a64.S +endif + +ifeq ($(CFG_CRYPTO_SM3_ARM_CE),y) +srcs-y += sm3_armv8a_ce.c +srcs-$(CFG_ARM64_core) += sm3_armv8a_ce_a64.S +endif + +ifeq ($(CFG_CRYPTO_SM4_ARM_CE),y) +srcs-$(CFG_ARM64_core) += sm4_armv8a_ce.c +srcs-$(CFG_ARM64_core) += sm4_armv8a_ce_a64.S +else ifeq ($(CFG_CRYPTO_SM4_ARM_AESE),y) +srcs-$(CFG_ARM64_core) += sm4_armv8a_neon.c +srcs-$(CFG_ARM64_core) += sm4_armv8a_aese_a64.S +endif diff --git a/optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1.dtsi b/optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1.dtsi new file mode 100644 index 0000000..efd725a --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1.dtsi @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * at91-sama5d27_som1.dtsi - Device Tree file for SAMA5D27 SoM1 board + * + * Copyright (c) 2017, Microchip Technology Inc. + * 2017 Cristian Birsan + * 2017 Claudiu Beznea + */ +#include "sama5d2.dtsi" +#include "sama5d2-pinfunc.h" + +/ { + model = "Atmel SAMA5D27 SoM1"; + compatible = "atmel,sama5d27-som1", "atmel,sama5d27", "atmel,sama5d2", "atmel,sama5"; + + aliases { + i2c0 = &i2c0; + }; + + clocks { + slow_xtal { + clock-frequency = <32768>; + }; + + main_xtal { + clock-frequency = <24000000>; + }; + }; + + ahb { + sdmmc0: sdio-host@a0000000 { + microchip,sdcal-inverted; + }; + + apb { + qspi1: spi@f0024000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi1_default>; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <80000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + m25p,fast-read; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x00000000 0x00040000>; + }; + + bootloader@40000 { + label = "bootloader"; + reg = <0x00040000 0x000c0000>; + }; + + bootloaderenvred@100000 { + label = "bootloader env redundant"; + reg = <0x00100000 0x00040000>; + }; + + bootloaderenv@140000 { + label = "bootloader env"; + reg = <0x00140000 0x00040000>; + }; + + dtb@180000 { + label = "device tree"; + reg = <0x00180000 0x00080000>; + }; + + kernel@200000 { + label = "kernel"; + reg = <0x00200000 0x00600000>; + }; + }; + }; + + macb0: ethernet@f8008000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb0_default>; + phy-mode = "rmii"; + + ethernet-phy@7 { + reg = <0x7>; + interrupt-parent = <&pioA>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb0_phy_irq>; + }; + }; + + i2c0: i2c@f8028000 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0_default>; + status = "okay"; + + at24@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <8>; + }; + }; + + pinctrl@fc039000 { + pinctrl_i2c0_default: i2c0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_qspi1_default: qspi1_default { + sck_cs { + pinmux = , + ; + bias-disable; + }; + + data { + pinmux = , + , + , + ; + bias-pull-up; + }; + }; + + pinctrl_macb0_default: macb0_default { + pinmux = , + , + , + , + , + , + , + , + , + ; + bias-disable; + }; + + pinctrl_macb0_phy_irq: macb0_phy_irq { + pinmux = ; + bias-disable; + }; + }; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1_ek.dts b/optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1_ek.dts new file mode 100644 index 0000000..461934b --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/at91-sama5d27_som1_ek.dts @@ -0,0 +1,527 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * at91-sama5d27_som1_ek.dts - Device Tree file for SAMA5D27-SOM1-EK board + * + * Copyright (c) 2017, Microchip Technology Inc. + * 2016 Nicolas Ferre + * 2017 Cristian Birsan + * 2017 Claudiu Beznea + */ +/dts-v1/; +#include "at91-sama5d27_som1.dtsi" +#include +#include + +/ { + model = "Atmel SAMA5D27 SOM1 EK"; + compatible = "atmel,sama5d27-som1-ek", "atmel,sama5d27-som1", "atmel,sama5d27", "atmel,sama5d2", "atmel,sama5"; + + aliases { + serial0 = &uart1; /* DBGU */ + serial1 = &uart4; /* mikro BUS 1 */ + serial2 = &uart2; /* mikro BUS 2 */ + i2c1 = &i2c1; + i2c2 = &i2c3; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + ahb { + usb0: gadget@300000 { + atmel,vbus-gpio = <&pioA PIN_PD20 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usba_vbus>; + status = "okay"; + }; + + usb1: ohci@400000 { + num-ports = <3>; + atmel,vbus-gpio = <0 /* &pioA PIN_PD20 GPIO_ACTIVE_HIGH */ + &pioA PIN_PA27 GPIO_ACTIVE_HIGH + 0 + >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_default>; + status = "okay"; + }; + + usb2: ehci@500000 { + status = "okay"; + }; + + sdmmc0: sdio-host@a0000000 { + bus-width = <8>; + mmc-ddr-3_3v; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdmmc0_default>; + status = "okay"; + }; + + sdmmc1: sdio-host@b0000000 { + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdmmc1_default>; + status = "okay"; + }; + + apb { + isc: isc@f0008000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_isc_base &pinctrl_isc_data_8bit &pinctrl_isc_data_9_10 &pinctrl_isc_data_11_12>; + status = "okay"; + }; + + qspi1: spi@f0024000 { + status = "okay"; + }; + + spi0: spi@f8000000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0_default>; + status = "okay"; + }; + + macb0: ethernet@f8008000 { + status = "okay"; + }; + + tcb0: timer@f800c000 { + timer0: timer@0 { + compatible = "atmel,tcb-timer"; + reg = <0>; + }; + + timer1: timer@1 { + compatible = "atmel,tcb-timer"; + reg = <1>; + }; + }; + + uart1: serial@f8020000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1_default>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "okay"; + }; + + uart2: serial@f8024000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mikrobus2_uart>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "okay"; + }; + + pwm0: pwm@f802c000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mikrobus1_pwm &pinctrl_mikrobus2_pwm>; + status = "disabled"; /* Conflict with leds. */ + }; + + flx1: flexcom@f8038000 { + atmel,flexcom-mode = ; + status = "okay"; + + i2c3: i2c@600 { + dmas = <0>, <0>; + i2c-analog-filter; + i2c-digital-filter; + i2c-digital-filter-width-ns = <35>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mikrobus_i2c>; + status = "okay"; + }; + }; + + shdwc@f8048010 { + debounce-delay-us = <976>; + atmel,wakeup-rtc-timer; + + input@0 { + reg = <0>; + }; + }; + + uart3: serial@fc008000 { + atmel,use-dma-rx; + atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3_default>; + status = "disabled"; /* Conflict with isc. */ + }; + + uart4: serial@fc00c000 { + atmel,use-dma-rx; + atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mikrobus1_uart>; + status = "okay"; + }; + + flx3: flexcom@fc014000 { + atmel,flexcom-mode = ; + status = "disabled"; + + uart8: serial@200 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx3_default>; + status = "disabled"; /* Conflict with isc. */ + }; + + spi5: spi@400 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx3_default>; + status = "disabled"; /* Conflict with isc. */ + }; + }; + + flx4: flexcom@fc018000 { + atmel,flexcom-mode = ; + status = "okay"; + + uart9: serial@200 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx4_default>; + status = "disabled"; /* Conflict with spi6 and i2c6. */ + }; + + spi6: spi@400 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mikrobus_spi &pinctrl_mikrobus1_spi_cs &pinctrl_mikrobus2_spi_cs>; + status = "okay"; /* Conflict with uart5 and i2c6. */ + }; + + i2c6: i2c@600 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx4_default>; + status = "disabled"; /* Conflict with uart5 and spi6. */ + }; + }; + + i2c1: i2c@fc028000 { + dmas = <0>, <0>; + i2c-analog-filter; + i2c-digital-filter; + i2c-digital-filter-width-ns = <35>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1_default>; + status = "okay"; + }; + + adc: adc@fc030000 { + vddana-supply = <&vddana>; + vref-supply = <&advref>; + + status = "disabled"; + }; + + pinctrl@fc039000 { + + pinctrl_can1_default: can1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_flx3_default: flx3_default { + pinmux = , + , + , + , + ; + bias-disable; + }; + + pinctrl_i2c1_default: i2c1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_isc_base: isc_base { + pinmux = , + , + , + ; + bias-disable; + }; + + pinctrl_isc_data_8bit: isc_data_8bit { + pinmux = , + , + , + , + , + , + , + ; + bias-disable; + }; + + pinctrl_isc_data_9_10: isc_data_9_10 { + pinmux = , + ; + bias-disable; + }; + + pinctrl_isc_data_11_12: isc_data_11_12 { + pinmux = , + ; + bias-disable; + }; + + pinctrl_key_gpio_default: key_gpio_default { + pinmux = ; + bias-pull-up; + }; + + pinctrl_led_gpio_default: led_gpio_default { + pinmux = , + , + ; + bias-pull-up; + }; + + pinctrl_sdmmc0_default: sdmmc0_default { + cmd_data { + pinmux = , + , + , + , + , + , + , + , + ; + bias-disable; + }; + + ck_cd_vddsel { + pinmux = , + , + ; + bias-disable; + }; + }; + + pinctrl_sdmmc1_default: sdmmc1_default { + cmd_data { + pinmux = , + , + , + , + ; + bias-disable; + }; + + conf-ck_cd { + pinmux = , + ; + bias-disable; + }; + }; + + pinctrl_spi0_default: spi0_default { + pinmux = , + , + , + ; + bias-disable; + }; + + pinctrl_uart1_default: uart1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_uart3_default: uart3_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_usb_default: usb_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_usba_vbus: usba_vbus { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus1_an: mikrobus1_an { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus2_an: mikrobus2_an { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus1_rst: mikrobus1_rst { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus2_rst: mikrobus2_rst { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus1_spi_cs: mikrobus1_spi_cs { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus2_spi_cs: mikrobus2_spi_cs { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus_spi: mikrobus_spi { + pinmux = , + , + ; + bias-disable; + }; + + pinctrl_mikrobus1_pwm: mikrobus1_pwm { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus2_pwm: mikrobus2_pwm { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus1_int: mikrobus1_int { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus2_int: mikrobus2_int { + pinmux = ; + bias-disable; + }; + + pinctrl_mikrobus1_uart: mikrobus1_uart { + pinmux = , + ; + bias-disable; + }; + + pinctrl_mikrobus2_uart: mikrobus2_uart { + pinmux = , + ; + bias-disable; + }; + + pinctrl_mikrobus_i2c: mikrobus1_i2c { + pinmux = , + ; + bias-disable; + }; + + pinctrl_flx4_default: flx4_uart_default { + pinmux = , + , + , + , + ; + bias-disable; + }; + }; + + can1: can@fc050000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can1_default>; + status = "okay"; + }; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_key_gpio_default>; + + pb4 { + label = "USER"; + gpios = <&pioA PIN_PA29 GPIO_ACTIVE_LOW>; + /* linux,code = ; BSD license issue */ + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_led_gpio_default>; + status = "okay"; /* Conflict with pwm0. */ + + red { + label = "red"; + gpios = <&pioA PIN_PA10 GPIO_ACTIVE_HIGH>; + }; + + green { + label = "green"; + gpios = <&pioA PIN_PB1 GPIO_ACTIVE_HIGH>; + }; + + blue { + label = "blue"; + gpios = <&pioA PIN_PA31 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + vddin_3v3: fixed-regulator-vddin_3v3 { + compatible = "regulator-fixed"; + + regulator-name = "VDDIN_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + status = "okay"; + }; + + vddana: fixed-regulator-vddana { + compatible = "regulator-fixed"; + + regulator-name = "VDDANA"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vddin_3v3>; + status = "okay"; + }; + + advref: fixed-regulator-advref { + compatible = "regulator-fixed"; + + regulator-name = "advref"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vddana>; + status = "okay"; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi b/optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi new file mode 100644 index 0000000..f177c46 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * at91-sama5d27_wlsom1.dtsi - Device Tree file for SAMA5D27 WLSOM1 + * + * Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries + * + * Author: Nicolas Ferre + * Author: Eugen Hristev + */ +#include "sama5d2.dtsi" +#include "sama5d2-pinfunc.h" +#include +#include + +/ { + model = "Microchip SAMA5D27 WLSOM1"; + compatible = "microchip,sama5d27-wlsom1", "atmel,sama5d27", "atmel,sama5d2", "atmel,sama5"; + + aliases { + i2c0 = &i2c0; + }; + + clocks { + slow_xtal { + clock-frequency = <32768>; + }; + + main_xtal { + clock-frequency = <24000000>; + }; + }; +}; + +&flx1 { + atmel,flexcom-mode = ; + + uart6: serial@200 { + pinctrl-0 = <&pinctrl_flx1_default>; + pinctrl-names = "default"; + }; +}; + +&i2c0 { + pinctrl-0 = <&pinctrl_i2c0_default>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + pinctrl-names = "default", "gpio"; + sda-gpios = <&pioA PIN_PD21 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; +}; + +&i2c1 { + dmas = <0>, <0>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1_default>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + sda-gpios = <&pioA PIN_PD19 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "disable"; + secure-status = "okay"; + + mcp16502@5b { + compatible = "microchip,mcp16502"; + reg = <0x5b>; + status = "okay"; + lpm-gpios = <&pioBU 0 GPIO_ACTIVE_LOW>; + + regulators { + vdd_3v3: VDD_IO { + regulator-name = "VDD_IO"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3700000>; + regulator-initial-mode = <2>; + regulator-allowed-modes = <2>, <4>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + regulator-mode = <4>; + }; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-mode = <4>; + }; + }; + + vddio_ddr: VDD_DDR { + regulator-name = "VDD_DDR"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1850000>; + regulator-initial-mode = <2>; + regulator-allowed-modes = <2>, <4>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1200000>; + regulator-changeable-in-suspend; + regulator-mode = <4>; + }; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1200000>; + regulator-changeable-in-suspend; + regulator-mode = <4>; + }; + }; + + vdd_core: VDD_CORE { + regulator-name = "VDD_CORE"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1850000>; + regulator-initial-mode = <2>; + regulator-allowed-modes = <2>, <4>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + regulator-mode = <4>; + }; + + regulator-state-mem { + regulator-off-in-suspend; + regulator-mode = <4>; + }; + }; + + vdd_ddr: VDD_OTHER { + regulator-name = "VDD_OTHER"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-initial-mode = <2>; + regulator-allowed-modes = <2>, <4>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + regulator-changeable-in-suspend; + regulator-mode = <4>; + }; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + regulator-changeable-in-suspend; + regulator-mode = <4>; + }; + }; + + LDO1 { + regulator-name = "LDO1"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3700000>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + }; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + LDO2 { + regulator-name = "LDO2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <3700000>; + regulator-always-on; + + regulator-state-standby { + regulator-on-in-suspend; + }; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; +}; + +&macb0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb0_default>; + phy-mode = "rmii"; + + ethernet-phy@0 { + reg = <0x0>; + interrupt-parent = <&pioA>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb0_phy_irq>; + }; +}; + +&pmc { + atmel,osc-bypass; +}; + +&qspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi1_default>; + status = "disabled"; + + qspi1_flash: spi_flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <80000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <4>; + m25p,fast-read; + status = "disabled"; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x0 0x40000>; + }; + + bootloader@40000 { + label = "bootloader"; + reg = <0x40000 0xc0000>; + }; + + bootloaderenvred@100000 { + label = "bootloader env redundant"; + reg = <0x100000 0x40000>; + }; + + bootloaderenv@140000 { + label = "bootloader env"; + reg = <0x140000 0x40000>; + }; + + dtb@180000 { + label = "device tree"; + reg = <0x180000 0x80000>; + }; + + kernel@200000 { + label = "kernel"; + reg = <0x200000 0x600000>; + }; + }; +}; + +&pioA { + pinctrl_flx1_default: flx1_usart_default { + pinmux = , + , + , + ; + bias-disable; + }; + + pinctrl_i2c0_default: i2c0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c0_gpio: i2c0_gpio { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c1_default: i2c1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c1_gpio: i2c1_gpio { + pinmux = , + ; + bias-disable; + }; + + pinctrl_macb0_default: macb0_default { + pinmux = , + , + , + , + , + , + , + , + , + ; + bias-disable; + }; + + pinctrl_macb0_phy_irq: macb0_phy_irq { + pinmux = ; + bias-disable; + }; + + pinctrl_qspi1_default: qspi1_default { + pinmux = , + , + , + , + , + ; + bias-pull-up; + }; +}; + diff --git a/optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts b/optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts new file mode 100644 index 0000000..c6c3fc8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * at91-sama5d27_wlsom1_ek.dts - Device Tree file for SAMA5D27 WLSOM1 EK + * + * Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries + * + * Author: Nicolas Ferre + */ +/dts-v1/; +#include "at91-sama5d27_wlsom1.dtsi" + +/ { + model = "Microchip SAMA5D27 WLSOM1 EK"; + compatible = "microchip,sama5d27-wlsom1-ek", "microchip,sama5d27-wlsom1", "atmel,sama5d27", "atmel,sama5d2", "atmel,sama5"; + + aliases { + serial0 = &uart0; /* DBGU */ + serial1 = &uart6; /* BT */ + serial2 = &uart5; /* mikro BUS 2 */ + serial3 = &uart3; /* mikro BUS 1 */ + i2c1 = &i2c1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_led_gpio_default>; + status = "okay"; + + red { + label = "red"; + gpios = <&pioA PIN_PA6 GPIO_ACTIVE_HIGH>; + }; + + green { + label = "green"; + gpios = <&pioA PIN_PA7 GPIO_ACTIVE_HIGH>; + }; + + blue { + label = "blue"; + gpios = <&pioA PIN_PA8 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; +}; + +&adc { + vddana-supply = <&vdd_3v3>; + vref-supply = <&vdd_3v3>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc_default>; + status = "okay"; +}; + +&flx0 { + atmel,flexcom-mode = ; + status = "okay"; + + uart5: serial@200 { + pinctrl-0 = <&pinctrl_flx0_default>; + pinctrl-names = "default"; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "okay"; + }; +}; + +&flx1 { + status = "okay"; + + uart6: serial@200 { + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "okay"; + }; +}; + +&macb0 { + status = "okay"; +}; + +&pioA { + /* + * There is no real pinmux for ADC, if the pin + * is not requested by another peripheral then + * the muxing is done when channel is enabled. + * Requesting pins for ADC is GPIO is + * encouraged to prevent conflicts and to + * disable bias in order to be in the same + * state when the pin is not muxed to the adc. + */ + pinctrl_adc_default: adc_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_flx0_default: flx0_usart_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_key_gpio_default: key_gpio_default { + pinmux = ; + bias-pull-up; + }; + + pinctrl_led_gpio_default: led_gpio_default { + pinmux = , + , + ; + bias-pull-down; + }; + + pinctrl_sdmmc0_default: sdmmc0_default { + cmd_data { + pinmux = , + , + , + , + ; + bias-disable; + }; + + ck_cd_vddsel { + pinmux = , + , + , + ; + bias-disable; + }; + }; + + pinctrl_uart0_default: uart0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_uart3_default: uart3_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_pwm0_default: pwm0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_usb_default: usb_default { + pinmux = ; + bias-disable; + }; + + pinctrl_usba_vbus: usba_vbus { + pinmux = ; + bias-disable; + }; +}; + +&pwm0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0_default>; + status = "okay"; +}; + +&qspi1 { + status = "okay"; + + qspi1_flash: spi_flash@0 { + status = "okay"; + }; +}; + +&sdmmc0 { + bus-width = <4>; + mmc-ddr-3_3v; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdmmc0_default>; + status = "okay"; +}; + +&shutdown_controller { + atmel,shdwc-debouncer = <976>; + atmel,wakeup-rtc-timer; + + input@0 { + reg = <0>; + }; +}; + +&tcb0 { + timer0: timer@0 { + compatible = "atmel,tcb-timer"; + reg = <0>; + }; + + timer1: timer@1 { + compatible = "atmel,tcb-timer"; + reg = <1>; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0_default>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3_default>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "okay"; +}; + +&usb0 { + atmel,vbus-gpio = <&pioA PIN_PA16 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usba_vbus>; + status = "okay"; +}; + +&usb1 { + num-ports = <3>; + atmel,vbus-gpio = <0 + &pioA PIN_PA10 GPIO_ACTIVE_HIGH + 0 + >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_default>; + status = "okay"; +}; + +&usb2 { + phy_type = "hsic"; + status = "okay"; +}; + diff --git a/optee/optee_os/core/arch/arm/dts/at91-sama5d2_xplained.dts b/optee/optee_os/core/arch/arm/dts/at91-sama5d2_xplained.dts new file mode 100644 index 0000000..1909b7f --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/at91-sama5d2_xplained.dts @@ -0,0 +1,739 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * at91-sama5d2_xplained.dts - Device Tree file for SAMA5D2 Xplained board + * + * Copyright (C) 2015 Atmel, + * 2015 Nicolas Ferre + */ +/dts-v1/; +#include "sama5d2.dtsi" +#include "sama5d2-pinfunc.h" +#include +#include +#include + +/ { + model = "Atmel SAMA5D2 Xplained"; + compatible = "atmel,sama5d2-xplained", "atmel,sama5d2", "atmel,sama5"; + + aliases { + serial0 = &uart1; /* DBGU */ + i2c0 = &i2c0; + i2c1 = &i2c1; + i2c2 = &i2c2; /* XPRO EXT2 */ + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clocks { + slow_xtal { + clock-frequency = <32768>; + }; + + main_xtal { + clock-frequency = <12000000>; + }; + }; + + ahb { + usb0: gadget@300000 { + atmel,vbus-gpio = <&pioA PIN_PA31 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usba_vbus>; + status = "okay"; + }; + + usb1: ohci@400000 { + num-ports = <3>; + atmel,vbus-gpio = <0 /* &pioA PIN_PB9 GPIO_ACTIVE_HIGH */ + &pioA PIN_PB10 GPIO_ACTIVE_HIGH + 0 + >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_default>; + status = "okay"; + }; + + usb2: ehci@500000 { + status = "okay"; + }; + + sdmmc0: sdio-host@a0000000 { + bus-width = <8>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdmmc0_default>; + non-removable; + mmc-ddr-1_8v; + status = "okay"; + }; + + sdmmc1: sdio-host@b0000000 { + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdmmc1_default>; + status = "okay"; /* conflict with qspi0 */ + vqmmc-supply = <&vdd_3v3_reg>; + vmmc-supply = <&vdd_3v3_reg>; + }; + + apb { + qspi0: spi@f0020000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi0_default>; + status = "disabled"; /* conflict with sdmmc1 */ + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <80000000>; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + m25p,fast-read; + + at91bootstrap@0 { + label = "at91bootstrap"; + reg = <0x00000000 0x00040000>; + }; + + bootloader@40000 { + label = "bootloader"; + reg = <0x00040000 0x000c0000>; + }; + + bootloaderenvred@100000 { + label = "bootloader env redundant"; + reg = <0x00100000 0x00040000>; + }; + + bootloaderenv@140000 { + label = "bootloader env"; + reg = <0x00140000 0x00040000>; + }; + + dtb@180000 { + label = "device tree"; + reg = <0x00180000 0x00080000>; + }; + + kernel@200000 { + label = "kernel"; + reg = <0x00200000 0x00600000>; + }; + + misc@800000 { + label = "misc"; + reg = <0x00800000 0x00000000>; + }; + }; + }; + + spi0: spi@f8000000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi0_default>; + status = "okay"; + + m25p80@0 { + compatible = "atmel,at25df321a"; + reg = <0>; + spi-max-frequency = <50000000>; + }; + }; + + macb0: ethernet@f8008000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_macb0_default &pinctrl_macb0_phy_irq>; + phy-mode = "rmii"; + status = "okay"; + + ethernet-phy@1 { + reg = <0x1>; + interrupt-parent = <&pioA>; + interrupts = ; + }; + }; + + tcb0: timer@f800c000 { + timer0: timer@0 { + compatible = "atmel,tcb-timer"; + reg = <0>; + }; + + timer1: timer@1 { + compatible = "atmel,tcb-timer"; + reg = <1>; + }; + }; + + uart1: serial@f8020000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1_default>; + atmel,use-dma-rx; + atmel,use-dma-tx; + status = "okay"; + }; + + i2c0: i2c@f8028000 { + dmas = <0>, <0>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c0_default>; + pinctrl-1 = <&pinctrl_i2c0_gpio>; + sda-gpios = <&pioA PIN_PD21 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-sda-hold-time-ns = <350>; + status = "okay"; + + pmic@5b { + compatible = "active-semi,act8945a"; + reg = <0x5b>; + active-semi,vsel-high; + status = "okay"; + + regulators { + vdd_1v35_reg: REG_DCDC1 { + regulator-name = "VDD_1V35"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + regulator-always-on; + + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-min-microvolt=<1400000>; + regulator-suspend-max-microvolt=<1400000>; + regulator-changeable-in-suspend; + regulator-mode=; + }; + }; + + vdd_1v2_reg: REG_DCDC2 { + regulator-name = "VDD_1V2"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1300000>; + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + regulator-always-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_3v3_reg: REG_DCDC3 { + regulator-name = "VDD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + regulator-always-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_fuse_reg: REG_LDO1 { + regulator-name = "VDD_FUSE"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + regulator-always-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_3v3_lp_reg: REG_LDO2 { + regulator-name = "VDD_3V3_LP"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + regulator-always-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_led_reg: REG_LDO3 { + regulator-name = "VDD_LED"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + regulator-always-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_sdhc_1v8_reg: REG_LDO4 { + regulator-name = "VDD_SDHC_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-allowed-modes = , + ; + regulator-initial-mode = ; + regulator-always-on; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + + charger { + compatible = "active-semi,act8945a-charger"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_charger_chglev &pinctrl_charger_lbo &pinctrl_charger_irq>; + interrupt-parent = <&pioA>; + interrupts = ; + + active-semi,chglev-gpios = <&pioA PIN_PA12 GPIO_ACTIVE_HIGH>; + active-semi,lbo-gpios = <&pioA PIN_PC8 GPIO_ACTIVE_LOW>; + active-semi,input-voltage-threshold-microvolt = <6600>; + active-semi,precondition-timeout = <40>; + active-semi,total-timeout = <3>; + status = "okay"; + }; + }; + }; + + pwm0: pwm@f802c000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm0_pwm2_default>; + status = "disabled"; /* conflict with leds */ + }; + + flx0: flexcom@f8034000 { + atmel,flexcom-mode = ; + status = "disabled"; /* conflict with ISC_D2 & ISC_D3 data pins */ + + uart5: serial@200 { + dmas = <0>, <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flx0_default>; + status = "okay"; + }; + + i2c2: i2c@600 { + dmas = <0>, <0>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_flx0_default>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + sda-gpios = <&pioA PIN_PB28 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PB29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-sda-hold-time-ns = <350>; + i2c-analog-filter; + i2c-digital-filter; + i2c-digital-filter-width-ns = <35>; + status = "disabled"; /* conflict with ISC_D2 & ISC_D3 data pins */ + }; + }; + + shdwc@f8048010 { + debounce-delay-us = <976>; + atmel,wakeup-rtc-timer; + + input@0 { + reg = <0>; + }; + }; + + i2s0: i2s@f8050000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s0_default>; + status = "disabled"; /* conflict with can0 */ + }; + + can0: can@f8054000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can0_default>; + status = "okay"; + }; + + uart3: serial@fc008000 { + atmel,use-dma-rx; + atmel,use-dma-tx; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3_default>; + status = "okay"; + }; + + flx4: flexcom@fc018000 { + atmel,flexcom-mode = ; + status = "okay"; + + i2c6: i2c@600 { + dmas = <0>, <0>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_flx4_default>; + pinctrl-1 = <&pinctrl_flx4_gpio>; + sda-gpios = <&pioA PIN_PD12 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + i2c-analog-filter; + i2c-digital-filter; + i2c-digital-filter-width-ns = <35>; + status = "okay"; + }; + }; + + i2c1: i2c@fc028000 { + dmas = <0>, <0>; + pinctrl-names = "default", "gpio"; + pinctrl-0 = <&pinctrl_i2c1_default>; + i2c-analog-filter; + i2c-digital-filter; + i2c-digital-filter-width-ns = <35>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + sda-gpios = <&pioA PIN_PD4 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA PIN_PD5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + status = "okay"; + + at24@54 { + compatible = "atmel,24c02"; + reg = <0x54>; + pagesize = <16>; + }; + }; + + adc: adc@fc030000 { + vddana-supply = <&vdd_3v3_lp_reg>; + vref-supply = <&vdd_3v3_lp_reg>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>; + status = "okay"; + }; + + pinctrl@fc039000 { + /* + * There is no real pinmux for ADC, if the pin + * is not requested by another peripheral then + * the muxing is done when channel is enabled. + * Requesting pins for ADC is GPIO is + * encouraged to prevent conflicts and to + * disable bias in order to be in the same + * state when the pin is not muxed to the adc. + */ + pinctrl_adc_default: adc_default { + pinmux = ; + bias-disable; + }; + + pinctrl_can0_default: can0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_can1_default: can1_default { + pinmux = , + ; + bias-disable; + }; + + /* + * The ADTRG pin can work on any edge type. + * In here it's being pulled up, so need to + * connect it to ground to get an edge e.g. + * Trigger can be configured on falling, rise + * or any edge, and the pull-up can be changed + * to pull-down or left floating according to + * needs. + */ + pinctrl_adtrg_default: adtrg_default { + pinmux = ; + bias-pull-up; + }; + + pinctrl_charger_chglev: charger_chglev { + pinmux = ; + bias-disable; + }; + + pinctrl_charger_irq: charger_irq { + pinmux = ; + bias-disable; + }; + + pinctrl_charger_lbo: charger_lbo { + pinmux = ; + bias-pull-up; + }; + + pinctrl_classd_default_pfets: classd_default_pfets { + pinmux = , + ; + bias-pull-up; + }; + + pinctrl_classd_default_nfets: classd_default_nfets { + pinmux = , + ; + bias-pull-down; + }; + + pinctrl_flx0_default: flx0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_flx4_default: flx4_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_flx4_gpio: flx4_gpio { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c0_default: i2c0_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c0_gpio: i2c0_gpio { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c1_default: i2c1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c1_gpio: i2c1_gpio { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2c2_gpio: i2c2_gpio { + pinmux = , + ; + bias-disable; + }; + + pinctrl_i2s0_default: i2s0_default { + pinmux = , + , + , + , + ; + bias-disable; + }; + + pinctrl_i2s1_default: i2s1_default { + pinmux = , + , + , + , + ; + bias-disable; + }; + + pinctrl_key_gpio_default: key_gpio_default { + pinmux = ; + bias-pull-up; + }; + + pinctrl_led_gpio_default: led_gpio_default { + pinmux = , + , + ; + bias-pull-up; + }; + + pinctrl_macb0_default: macb0_default { + pinmux = , + , + , + , + , + , + , + , + , + ; + bias-disable; + }; + + pinctrl_macb0_phy_irq: macb0_phy_irq { + pinmux = ; + bias-disable; + }; + + pinctrl_qspi0_default: qspi0_default { + sck_cs { + pinmux = , + ; + bias-disable; + }; + + data { + pinmux = , + , + , + ; + bias-pull-up; + }; + }; + + pinctrl_sdmmc0_default: sdmmc0_default { + cmd_data { + pinmux = , + , + , + , + , + , + , + , + ; + bias-disable; + }; + + ck_cd_rstn_vddsel { + pinmux = , + , + , + ; + bias-disable; + }; + }; + + pinctrl_sdmmc1_default: sdmmc1_default { + cmd_data { + pinmux = , + , + , + , + ; + bias-disable; + }; + + conf-ck_cd { + pinmux = , + ; + bias-disable; + }; + }; + + pinctrl_spi0_default: spi0_default { + pinmux = , + , + , + ; + bias-disable; + }; + + pinctrl_uart1_default: uart1_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_uart3_default: uart3_default { + pinmux = , + ; + bias-disable; + }; + + pinctrl_usb_default: usb_default { + pinmux = ; + bias-disable; + }; + + pinctrl_usba_vbus: usba_vbus { + pinmux = ; + bias-disable; + }; + + pinctrl_pwm0_pwm2_default: pwm0_pwm2_default { + pinmux = , + ; + bias-pull-up; + }; + }; + + classd: classd@fc048000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_classd_default_pfets &pinctrl_classd_default_nfets>; + atmel,pwm-type = "diff"; + atmel,non-overlap-time = <10>; + status = "okay"; + }; + + i2s1: i2s@fc04c000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s1_default>; + status = "disabled"; /* conflict with spi0, sdmmc1 */ + }; + + can1: can@fc050000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can1_default>; + status = "okay"; + }; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_key_gpio_default>; + + bp1 { + label = "PB_USER"; + gpios = <&pioA PIN_PB9 GPIO_ACTIVE_LOW>; + /* linux,code = ; BSD license issue */ + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_led_gpio_default>; + status = "okay"; /* conflict with pwm0 */ + + red { + label = "red"; + gpios = <&pioA PIN_PB6 GPIO_ACTIVE_LOW>; + }; + + + green { + label = "green"; + gpios = <&pioA PIN_PB5 GPIO_ACTIVE_LOW>; + }; + + blue { + label = "blue"; + gpios = <&pioA PIN_PB0 GPIO_ACTIVE_LOW>; + linux,default-trigger = "heartbeat"; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi b/optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi new file mode 100644 index 0000000..9bef755 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/dt_driver_test.dtsi @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +/ { + /* + * Device dt-test-consumer consumes resource, it is expected + * to defer its probe until resources are ready. + */ + dt-test-consumer { + compatible = "linaro,dt-test-consumer"; + clocks = <&dt_test_provider 3>, <&dt_test_provider 7>; + clock-names = "clk0", "clk1"; + resets = <&dt_test_provider 35>, <&dt_test_provider 5>; + reset-names = "rst0", "rst1"; + }; + + /* + * Resource device are discovered from subnode added to probe + * list by related drivers (here all simple-bus). + */ + dt-test-bus-b0 { + compatible = "simple-bus"; + + dt-test-bus-b1 { + compatible = "simple-bus"; + + dt-test-bus-b2 { + compatible = "simple-bus"; + + dt-test-bus-b3 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + dt_test_provider: dt-test-provider@0 { + compatible = "linaro,dt-test-provider"; + reg = <0>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + }; + }; + }; + }; + + dt-test-crypt-consumer { + compatible = "linaro,dt-test-crypt-consumer"; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/embedded_dtb_test.dts b/optee/optee_os/core/arch/arm/dts/embedded_dtb_test.dts new file mode 100644 index 0000000..48e2d0d --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/embedded_dtb_test.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ +/dts-v1/; + +#include "dt_driver_test.dtsi" + +/ { + model = "Embedded device tree for OP-TEE/Qemu platform test purpose"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/fsl-lx2160a-qds.dts b/optee/optee_os/core/arch/arm/dts/fsl-lx2160a-qds.dts new file mode 100644 index 0000000..0cf72cb --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/fsl-lx2160a-qds.dts @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Device Tree file for LX2160AQDS +// +// Copyright 2018-2020 NXP + +/dts-v1/; + +#include "fsl-lx2160a.dtsi" + +/ { + model = "NXP Layerscape LX2160AQDS"; + compatible = "fsl,lx2160a-qds", "fsl,lx2160a"; + + aliases { + crypto = &crypto; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + sb_3v3: regulator-sb3v3 { + compatible = "regulator-fixed"; + regulator-name = "MC34717-3.3VSB"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + mdio-mux-1 { + compatible = "mdio-mux-multiplexer"; + mux-controls = <&mux 0>; + mdio-parent-bus = <&emdio1>; + #address-cells=<1>; + #size-cells = <0>; + + mdio@0 { /* On-board PHY #1 RGMI1*/ + reg = <0x00>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@8 { /* On-board PHY #2 RGMI2*/ + reg = <0x8>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@18 { /* Slot #1 */ + reg = <0x18>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@19 { /* Slot #2 */ + reg = <0x19>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@1a { /* Slot #3 */ + reg = <0x1a>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@1b { /* Slot #4 */ + reg = <0x1b>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@1c { /* Slot #5 */ + reg = <0x1c>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@1d { /* Slot #6 */ + reg = <0x1d>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@1e { /* Slot #7 */ + reg = <0x1e>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@1f { /* Slot #8 */ + reg = <0x1f>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + mdio-mux-2 { + compatible = "mdio-mux-multiplexer"; + mux-controls = <&mux 1>; + mdio-parent-bus = <&emdio2>; + #address-cells=<1>; + #size-cells = <0>; + + mdio@0 { /* Slot #1 (secondary EMI) */ + reg = <0x00>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@1 { /* Slot #2 (secondary EMI) */ + reg = <0x01>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@2 { /* Slot #3 (secondary EMI) */ + reg = <0x02>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@3 { /* Slot #4 (secondary EMI) */ + reg = <0x03>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@4 { /* Slot #5 (secondary EMI) */ + reg = <0x04>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@5 { /* Slot #6 (secondary EMI) */ + reg = <0x05>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@6 { /* Slot #7 (secondary EMI) */ + reg = <0x06>; + #address-cells = <1>; + #size-cells = <0>; + }; + + mdio@7 { /* Slot #8 (secondary EMI) */ + reg = <0x07>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; +}; + +&can0 { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&crypto { + status = "okay"; +}; + +&dspi0 { + status = "okay"; + + dflash0: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +&dspi1 { + status = "okay"; + + dflash1: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +&dspi2 { + status = "okay"; + + dflash2: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +&emdio1 { + status = "okay"; +}; + +&emdio2 { + status = "okay"; +}; + +&esdhc0 { + status = "okay"; +}; + +&esdhc1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + + fpga@66 { + compatible = "fsl,lx2160aqds-fpga", "fsl,fpga-qixis-i2c", + "simple-mfd"; + reg = <0x66>; + + mux: mux-controller { + compatible = "reg-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x54 0xf8>, /* 0: reg 0x54, bits 7:3 */ + <0x54 0x07>; /* 1: reg 0x54, bit 2:0 */ + }; + }; + + i2c-mux@77 { + compatible = "nxp,pca9547"; + reg = <0x77>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + + power-monitor@40 { + compatible = "ti,ina220"; + reg = <0x40>; + shunt-resistor = <500>; + }; + + power-monitor@41 { + compatible = "ti,ina220"; + reg = <0x41>; + shunt-resistor = <1000>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + + temperature-sensor@4c { + compatible = "nxp,sa56004"; + reg = <0x4c>; + vcc-supply = <&sb_3v3>; + }; + + temperature-sensor@4d { + compatible = "nxp,sa56004"; + reg = <0x4d>; + vcc-supply = <&sb_3v3>; + }; + + rtc@51 { + compatible = "nxp,pcf2129"; + reg = <0x51>; + }; + }; + }; +}; + +&sata0 { + status = "okay"; +}; + +&sata1 { + status = "okay"; +}; + +&sata2 { + status = "okay"; +}; + +&sata3 { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; + +&sata0 { + status = "okay"; +}; + +&sata1 { + status = "okay"; +}; + +&sata2 { + status = "okay"; +}; + +&sata3 { + status = "okay"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/fsl-lx2160a-rdb.dts b/optee/optee_os/core/arch/arm/dts/fsl-lx2160a-rdb.dts new file mode 100644 index 0000000..c2817b7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/fsl-lx2160a-rdb.dts @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Device Tree file for LX2160ARDB +// +// Copyright 2018 NXP + +/dts-v1/; + +#include "fsl-lx2160a.dtsi" + +/ { + model = "NXP Layerscape LX2160ARDB"; + compatible = "fsl,lx2160a-rdb", "fsl,lx2160a"; + + aliases { + crypto = &crypto; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + sb_3v3: regulator-sb3v3 { + compatible = "regulator-fixed"; + regulator-name = "MC34717-3.3VSB"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; +}; + +&crypto { + status = "okay"; +}; + +&esdhc0 { + sd-uhs-sdr104; + sd-uhs-sdr50; + sd-uhs-sdr25; + sd-uhs-sdr12; + status = "okay"; +}; + +&esdhc1 { + mmc-hs200-1_8v; + mmc-hs400-1_8v; + bus-width = <8>; + status = "okay"; +}; + +&fspi { + status = "okay"; + + mt35xu512aba0: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,m25p80"; + m25p,fast-read; + spi-max-frequency = <50000000>; + reg = <0>; + spi-rx-bus-width = <8>; + spi-tx-bus-width = <8>; + }; + + mt35xu512aba1: flash@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,m25p80"; + m25p,fast-read; + spi-max-frequency = <50000000>; + reg = <1>; + spi-rx-bus-width = <8>; + spi-tx-bus-width = <8>; + }; +}; + +&i2c0 { + status = "okay"; + + i2c-mux@77 { + compatible = "nxp,pca9547"; + reg = <0x77>; + #address-cells = <1>; + #size-cells = <0>; + + i2c@2 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x2>; + + power-monitor@40 { + compatible = "ti,ina220"; + reg = <0x40>; + shunt-resistor = <1000>; + }; + }; + + i2c@3 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3>; + + temperature-sensor@4c { + compatible = "nxp,sa56004"; + reg = <0x4c>; + vcc-supply = <&sb_3v3>; + }; + + temperature-sensor@4d { + compatible = "nxp,sa56004"; + reg = <0x4d>; + vcc-supply = <&sb_3v3>; + }; + }; + }; +}; + +&i2c4 { + status = "okay"; + + rtc@51 { + compatible = "nxp,pcf2129"; + reg = <0x51>; + // IRQ10_B + interrupts = <0 150 0x4>; + }; +}; + +&sata0 { + status = "okay"; +}; + +&sata1 { + status = "okay"; +}; + +&sata2 { + status = "okay"; +}; + +&sata3 { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&uart1 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi b/optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi new file mode 100644 index 0000000..c5bdfc8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/fsl-lx2160a.dtsi @@ -0,0 +1,1385 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +// +// Device Tree Include file for Layerscape-LX2160A family SoC. +// +// Copyright 2018-2020 NXP + +#include +#include + +/memreserve/ 0x80000000 0x00010000; + +/ { + compatible = "fsl,lx2160a"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + rtc1 = &ftm_alarm0; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + // 8 clusters having 2 Cortex-A72 cores each + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x0>; + clocks = <&clockgen 1 0>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster0_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x1>; + clocks = <&clockgen 1 0>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster0_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu100: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x100>; + clocks = <&clockgen 1 1>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster1_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu101: cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x101>; + clocks = <&clockgen 1 1>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster1_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu200: cpu@200 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x200>; + clocks = <&clockgen 1 2>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster2_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu201: cpu@201 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x201>; + clocks = <&clockgen 1 2>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster2_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu300: cpu@300 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x300>; + clocks = <&clockgen 1 3>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster3_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu301: cpu@301 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x301>; + clocks = <&clockgen 1 3>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster3_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu400: cpu@400 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x400>; + clocks = <&clockgen 1 4>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster4_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu401: cpu@401 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x401>; + clocks = <&clockgen 1 4>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster4_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu500: cpu@500 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x500>; + clocks = <&clockgen 1 5>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster5_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu501: cpu@501 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x501>; + clocks = <&clockgen 1 5>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster5_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu600: cpu@600 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x600>; + clocks = <&clockgen 1 6>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster6_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu601: cpu@601 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x601>; + clocks = <&clockgen 1 6>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster6_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu700: cpu@700 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x700>; + clocks = <&clockgen 1 7>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster7_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cpu701: cpu@701 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + enable-method = "psci"; + reg = <0x701>; + clocks = <&clockgen 1 7>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + i-cache-size = <0xC000>; + i-cache-line-size = <64>; + i-cache-sets = <192>; + next-level-cache = <&cluster7_l2>; + cpu-idle-states = <&cpu_pw15>; + #cooling-cells = <2>; + }; + + cluster0_l2: l2-cache0 { + compatible = "cache"; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + cache-level = <2>; + }; + + cluster1_l2: l2-cache1 { + compatible = "cache"; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + cache-level = <2>; + }; + + cluster2_l2: l2-cache2 { + compatible = "cache"; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + cache-level = <2>; + }; + + cluster3_l2: l2-cache3 { + compatible = "cache"; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + cache-level = <2>; + }; + + cluster4_l2: l2-cache4 { + compatible = "cache"; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + cache-level = <2>; + }; + + cluster5_l2: l2-cache5 { + compatible = "cache"; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + cache-level = <2>; + }; + + cluster6_l2: l2-cache6 { + compatible = "cache"; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + cache-level = <2>; + }; + + cluster7_l2: l2-cache7 { + compatible = "cache"; + cache-size = <0x100000>; + cache-line-size = <64>; + cache-sets = <1024>; + cache-level = <2>; + }; + + cpu_pw15: cpu-pw15 { + compatible = "arm,idle-state"; + idle-state-name = "PW15"; + arm,psci-suspend-param = <0x0>; + entry-latency-us = <2000>; + exit-latency-us = <2000>; + min-residency-us = <6000>; + }; + }; + + gic: interrupt-controller@6000000 { + compatible = "arm,gic-v3"; + reg = <0x0 0x06000000 0 0x10000>, // GIC Dist + <0x0 0x06200000 0 0x200000>, // GICR (RD_base + + // SGI_base) + <0x0 0x0c0c0000 0 0x2000>, // GICC + <0x0 0x0c0d0000 0 0x1000>, // GICH + <0x0 0x0c0e0000 0 0x20000>; // GICV + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + interrupts = ; + + its: gic-its@6020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x6020000 0 0x20000>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + pmu { + compatible = "arm,cortex-a72-pmu"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + memory@80000000 { + // DRAM space - 1, size : 2 GB DRAM + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x80000000>; + }; + + ddr1: memory-controller@1080000 { + compatible = "fsl,qoriq-memory-controller"; + reg = <0x0 0x1080000 0x0 0x1000>; + interrupts = ; + little-endian; + }; + + ddr2: memory-controller@1090000 { + compatible = "fsl,qoriq-memory-controller"; + reg = <0x0 0x1090000 0x0 0x1000>; + interrupts = ; + little-endian; + }; + + // One clock unit-sysclk node which bootloader require during DT fix-up + sysclk: sysclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; // fixed up by bootloader + clock-output-names = "sysclk"; + }; + + thermal-zones { + core_thermal1: core-thermal1 { + polling-delay-passive = <1000>; + polling-delay = <5000>; + thermal-sensors = <&tmu 0>; + + trips { + core_cluster_alert: core-cluster-alert { + temperature = <85000>; + hysteresis = <2000>; + type = "passive"; + }; + + core_cluster_crit: core-cluster-crit { + temperature = <95000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + dma-ranges = <0x0 0x0 0x0 0x0 0x10000 0x00000000>; + + crypto: crypto@8000000 { + compatible = "fsl,sec-v5.0", "fsl,sec-v4.0"; + fsl,sec-era = <10>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x00 0x8000000 0x100000>; + reg = <0x00 0x8000000 0x0 0x100000>; + interrupts = ; + dma-coherent; + status = "disabled"; + + sec_jr0: jr@10000 { + compatible = "fsl,sec-v5.0-job-ring", + "fsl,sec-v4.0-job-ring"; + reg = <0x10000 0x10000>; + interrupts = ; + status = "okay"; secure-status = "disabled"; /* NS-only */ + }; + + sec_jr1: jr@20000 { + compatible = "fsl,sec-v5.0-job-ring", + "fsl,sec-v4.0-job-ring"; + reg = <0x20000 0x10000>; + interrupts = ; + status = "okay"; secure-status = "disabled"; /* NS-only */ + }; + + sec_jr2: jr@30000 { + compatible = "fsl,sec-v5.0-job-ring", + "fsl,sec-v4.0-job-ring"; + reg = <0x30000 0x10000>; + interrupts = ; + status = "disabled"; secure-status = "okay"; /* S-only */ + }; + + sec_jr3: jr@40000 { + compatible = "fsl,sec-v5.0-job-ring", + "fsl,sec-v4.0-job-ring"; + reg = <0x40000 0x10000>; + interrupts = ; + status = "okay"; secure-status = "disabled"; /* workaround for ATF */ + }; + }; + + clockgen: clock-controller@1300000 { + compatible = "fsl,lx2160a-clockgen"; + reg = <0 0x1300000 0 0xa0000>; + #clock-cells = <2>; + clocks = <&sysclk>; + }; + + dcfg: syscon@1e00000 { + compatible = "fsl,lx2160a-dcfg", "syscon"; + reg = <0x0 0x1e00000 0x0 0x10000>; + little-endian; + }; + + sfp: sfp@1e80000 { + compatible = "fsl,lx2160a-sfp"; + reg = <0x0 0x1e80000 0x0 0x1000>; + }; + + sec_mon: sec-mon@1e90000 { + compatible = "fsl,lx2160a-sec-mon"; + reg = <0x0 0x1e90000 0x0 0x1000>; + status = "disabled"; + secure-status = "okay"; + }; + + /* WRIOP0: 0x8b8_0000, E-MDIO1: 0x1_6000 */ + emdio1: mdio@8b96000 { + compatible = "fsl,fman-memac-mdio"; + reg = <0x0 0x8b96000 0x0 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + little-endian; /* force the driver in LE mode */ + status = "disabled"; + }; + + /* WRIOP0: 0x8b8_0000, E-MDIO2: 0x1_7000 */ + emdio2: mdio@8b97000 { + compatible = "fsl,fman-memac-mdio"; + reg = <0x0 0x8b97000 0x0 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + little-endian; /* force the driver in LE mode */ + status = "disabled"; + }; + + i2c0: i2c@2000000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2000000 0x0 0x10000>; + interrupts = ; + clock-names = "i2c"; + clocks = <&clockgen 4 15>; + scl-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>; + status = "disabled"; + }; + + i2c1: i2c@2010000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2010000 0x0 0x10000>; + interrupts = ; + clock-names = "i2c"; + clocks = <&clockgen 4 15>; + status = "disabled"; + }; + + i2c2: i2c@2020000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2020000 0x0 0x10000>; + interrupts = ; + clock-names = "i2c"; + clocks = <&clockgen 4 15>; + status = "disabled"; + }; + + i2c3: i2c@2030000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2030000 0x0 0x10000>; + interrupts = ; + clock-names = "i2c"; + clocks = <&clockgen 4 15>; + status = "disabled"; + }; + + i2c4: i2c@2040000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2040000 0x0 0x10000>; + interrupts = ; + clock-names = "i2c"; + clocks = <&clockgen 4 15>; + scl-gpios = <&gpio2 16 GPIO_ACTIVE_HIGH>; + status = "disabled"; + }; + + i2c5: i2c@2050000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2050000 0x0 0x10000>; + interrupts = ; + clock-names = "i2c"; + clocks = <&clockgen 4 15>; + status = "disabled"; + }; + + i2c6: i2c@2060000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2060000 0x0 0x10000>; + interrupts = ; + clock-names = "i2c"; + clocks = <&clockgen 4 15>; + status = "disabled"; + }; + + i2c7: i2c@2070000 { + compatible = "fsl,vf610-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2070000 0x0 0x10000>; + interrupts = ; + clock-names = "i2c"; + clocks = <&clockgen 4 15>; + status = "disabled"; + }; + + fspi: spi@20c0000 { + compatible = "nxp,lx2160a-fspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x20c0000 0x0 0x10000>, + <0x0 0x20000000 0x0 0x10000000>; + reg-names = "fspi_base", "fspi_mmap"; + interrupts = ; + clocks = <&clockgen 4 3>, <&clockgen 4 3>; + clock-names = "fspi_en", "fspi"; + status = "disabled"; + }; + + dspi0: spi@2100000 { + compatible = "fsl,lx2160a-dspi", "fsl,ls2085a-dspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2100000 0x0 0x10000>; + interrupts = ; + clocks = <&clockgen 4 7>; + clock-names = "dspi"; + spi-num-chipselects = <5>; + bus-num = <0>; + status = "disabled"; + }; + + dspi1: spi@2110000 { + compatible = "fsl,lx2160a-dspi", "fsl,ls2085a-dspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2110000 0x0 0x10000>; + interrupts = ; + clocks = <&clockgen 4 7>; + clock-names = "dspi"; + spi-num-chipselects = <5>; + bus-num = <1>; + status = "disabled"; + }; + + dspi2: spi@2120000 { + compatible = "fsl,lx2160a-dspi", "fsl,ls2085a-dspi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x2120000 0x0 0x10000>; + interrupts = ; + clocks = <&clockgen 4 7>; + clock-names = "dspi"; + spi-num-chipselects = <5>; + bus-num = <2>; + status = "disabled"; + }; + + esdhc0: esdhc@2140000 { + compatible = "fsl,esdhc"; + reg = <0x0 0x2140000 0x0 0x10000>; + interrupts = <0 28 0x4>; /* Level high type */ + clocks = <&clockgen 4 1>; + voltage-ranges = <1800 1800 3300 3300>; + sdhci,auto-cmd12; + little-endian; + bus-width = <4>; + status = "disabled"; + }; + + esdhc1: esdhc@2150000 { + compatible = "fsl,esdhc"; + reg = <0x0 0x2150000 0x0 0x10000>; + interrupts = <0 63 0x4>; /* Level high type */ + clocks = <&clockgen 4 1>; + voltage-ranges = <1800 1800 3300 3300>; + sdhci,auto-cmd12; + broken-cd; + little-endian; + bus-width = <4>; + status = "disabled"; + }; + + can0: can@2180000 { + compatible = "fsl,lx2160ar1-flexcan"; + reg = <0x0 0x2180000 0x0 0x10000>; + interrupts = ; + clocks = <&sysclk>, <&clockgen 4 7>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + can1: can@2190000 { + compatible = "fsl,lx2160ar1-flexcan"; + reg = <0x0 0x2190000 0x0 0x10000>; + interrupts = ; + clocks = <&sysclk>, <&clockgen 4 7>; + clock-names = "ipg", "per"; + status = "disabled"; + }; + + tmu: tmu@1f80000 { + compatible = "fsl,qoriq-tmu"; + reg = <0x0 0x1f80000 0x0 0x10000>; + interrupts = <0 23 0x4>; + fsl,tmu-range = <0x800000E6 0x8001017D>; + fsl,tmu-calibration = + /* Calibration data group 1 */ + <0x00000000 0x00000035 + /* Calibration data group 2 */ + 0x00010001 0x00000154>; + little-endian; + #thermal-sensor-cells = <1>; + }; + + uart0: serial@21c0000 { + compatible = "arm,sbsa-uart","arm,pl011"; + reg = <0x0 0x21c0000 0x0 0x1000>; + interrupts = ; + current-speed = <115200>; + status = "disabled"; + }; + + uart1: serial@21d0000 { + compatible = "arm,sbsa-uart","arm,pl011"; + reg = <0x0 0x21d0000 0x0 0x1000>; + interrupts = ; + current-speed = <115200>; + status = "disabled"; + }; + + uart2: serial@21e0000 { + compatible = "arm,sbsa-uart","arm,pl011"; + reg = <0x0 0x21e0000 0x0 0x1000>; + interrupts = ; + current-speed = <115200>; + status = "disabled"; + }; + + uart3: serial@21f0000 { + compatible = "arm,sbsa-uart","arm,pl011"; + reg = <0x0 0x21f0000 0x0 0x1000>; + interrupts = ; + current-speed = <115200>; + status = "disabled"; + }; + + gpio0: gpio@2300000 { + compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2300000 0x0 0x10000>; + interrupts = ; + gpio-controller; + little-endian; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio1: gpio@2310000 { + compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2310000 0x0 0x10000>; + interrupts = ; + gpio-controller; + little-endian; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio@2320000 { + compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2320000 0x0 0x10000>; + interrupts = ; + gpio-controller; + little-endian; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio@2330000 { + compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2330000 0x0 0x10000>; + interrupts = ; + gpio-controller; + little-endian; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + watchdog@23a0000 { + compatible = "arm,sbsa-gwdt"; + reg = <0x0 0x23a0000 0 0x1000>, + <0x0 0x2390000 0 0x1000>; + interrupts = ; + timeout-sec = <30>; + }; + + rcpm: rcpm@1e34040 { + compatible = "fsl,lx2160a-rcpm", "fsl,qoriq-rcpm-2.1+"; + reg = <0x0 0x1e34040 0x0 0x1c>; + #fsl,rcpm-wakeup-cells = <7>; + little-endian; + }; + + ftm_alarm0: timer@2800000 { + compatible = "fsl,lx2160a-ftm-alarm"; + reg = <0x0 0x2800000 0x0 0x10000>; + fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0 0x0>; + interrupts = <0 44 4>; + }; + + usb0: usb@3100000 { + compatible = "fsl,lx2160a-dwc3", "snps,dwc3"; + reg = <0x0 0x3100000 0x0 0x10000>; + interrupts = ; + dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; + usb3-lpm-capable; + snps,dis-u1u2-when-u3-quirk; + snps,dis_rxdet_inp3_quirk; + snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>; + snps,host-vbus-glitches; + dma-coherent; + status = "disabled"; + }; + + usb1: usb@3110000 { + compatible = "fsl,lx2160a-dwc3", "snps,dwc3"; + reg = <0x0 0x3110000 0x0 0x10000>; + interrupts = ; + dr_mode = "host"; + snps,quirk-frame-length-adjustment = <0x20>; + usb3-lpm-capable; + snps,dis-u1u2-when-u3-quirk; + snps,dis_rxdet_inp3_quirk; + snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>; + snps,host-vbus-glitches; + status = "disabled"; + }; + + sata0: sata@3200000 { + compatible = "fsl,lx2160a-ahci"; + reg = <0x0 0x3200000 0x0 0x10000>, + <0x7 0x100520 0x0 0x4>; + reg-names = "ahci", "sata-ecc"; + interrupts = ; + clocks = <&clockgen 4 3>; + dma-coherent; + status = "disabled"; + }; + + sata1: sata@3210000 { + compatible = "fsl,lx2160a-ahci"; + reg = <0x0 0x3210000 0x0 0x10000>, + <0x7 0x100520 0x0 0x4>; + reg-names = "ahci", "sata-ecc"; + interrupts = ; + clocks = <&clockgen 4 3>; + dma-coherent; + status = "disabled"; + }; + + sata2: sata@3220000 { + compatible = "fsl,lx2160a-ahci"; + reg = <0x0 0x3220000 0x0 0x10000>, + <0x7 0x100520 0x0 0x4>; + reg-names = "ahci", "sata-ecc"; + interrupts = ; + clocks = <&clockgen 4 3>; + dma-coherent; + status = "disabled"; + }; + + sata3: sata@3230000 { + compatible = "fsl,lx2160a-ahci"; + reg = <0x0 0x3230000 0x0 0x10000>, + <0x7 0x100520 0x0 0x4>; + reg-names = "ahci", "sata-ecc"; + interrupts = ; + clocks = <&clockgen 4 3>; + dma-coherent; + status = "disabled"; + }; + + pcie@3400000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */ + 0x80 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie_ep@3400000 { + compatible = "fsl,lx2160a-pcie-ep"; + reg = <0x00 0x03400000 0x0 0x00100000 + 0x80 0x00000000 0x8 0x00000000>; + reg-names = "regs", "addr_space"; + num-ob-windows = <256>; + status = "disabled"; + }; + + pcie@3500000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */ + 0x88 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie_ep@3500000 { + compatible = "fsl,lx2160a-pcie-ep"; + reg = <0x00 0x03500000 0x0 0x00100000 + 0x88 0x00000000 0x8 0x00000000>; + reg-names = "regs", "addr_space"; + num-ob-windows = <256>; + status = "disabled"; + }; + + pcie@3600000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */ + 0x90 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie_ep@3600000 { + compatible = "fsl,lx2160a-pcie-ep"; + reg = <0x00 0x03600000 0x0 0x00100000 + 0x90 0x00000000 0x8 0x00000000>; + reg-names = "regs", "addr_space"; + num-ob-windows = <256>; + max-functions = <2>; + status = "disabled"; + }; + + pcie@3700000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03700000 0x0 0x00100000 /* controller registers */ + 0x98 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie_ep@3700000 { + compatible = "fsl,lx2160a-pcie-ep"; + reg = <0x00 0x03700000 0x0 0x00100000 + 0x98 0x00000000 0x8 0x00000000>; + reg-names = "regs", "addr_space"; + num-ob-windows = <256>; + status = "disabled"; + }; + + pcie@3800000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03800000 0x0 0x00100000 /* controller registers */ + 0xa0 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie_ep@3800000 { + compatible = "fsl,lx2160a-pcie-ep"; + reg = <0x00 0x03800000 0x0 0x00100000 + 0xa0 0x00000000 0x8 0x00000000>; + reg-names = "regs", "addr_space"; + num-ob-windows = <256>; + max-functions = <2>; + status = "disabled"; + }; + + pcie@3900000 { + compatible = "fsl,lx2160a-pcie"; + reg = <0x00 0x03900000 0x0 0x00100000 /* controller registers */ + 0xa8 0x00000000 0x0 0x00001000>; /* configuration space */ + reg-names = "csr_axi_slave", "config_axi_slave"; + interrupts = , /* AER interrupt */ + , /* PME interrupt */ + ; /* controller interrupt */ + interrupt-names = "aer", "pme", "intr"; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + dma-coherent; + apio-wins = <8>; + ppio-wins = <8>; + bus-range = <0x0 0xff>; + ranges = <0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ + msi-parent = <&its>; + iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 2 &gic 0 0 GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 3 &gic 0 0 GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, + <0000 0 0 4 &gic 0 0 GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + pcie_ep@3900000 { + compatible = "fsl,lx2160a-pcie-ep"; + reg = <0x00 0x03900000 0x0 0x00100000 + 0xa8 0x00000000 0x8 0x00000000>; + reg-names = "regs", "addr_space"; + num-ob-windows = <256>; + status = "disabled"; + }; + + smmu: iommu@5000000 { + compatible = "arm,mmu-500"; + reg = <0 0x5000000 0 0x800000>; + #iommu-cells = <1>; + #global-interrupts = <14>; + // global secure fault + interrupts = , + // combined secure + , + // global non-secure fault + , + // combined non-secure + , + // performance counter interrupts 0-9 + , + , + , + , + , + , + , + , + , + , + // per context interrupt, 64 interrupts + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + dma-coherent; + }; + + console@8340020 { + compatible = "fsl,dpaa2-console"; + reg = <0x00000000 0x08340020 0 0x2>; + }; + + ptp-timer@8b95000 { + compatible = "fsl,dpaa2-ptp"; + reg = <0x0 0x8b95000 0x0 0x100>; + clocks = <&clockgen 4 1>; + little-endian; + fsl,extts-fifo; + }; + + fsl_mc: fsl-mc@80c000000 { + compatible = "fsl,qoriq-mc"; + reg = <0x00000008 0x0c000000 0 0x40>, + <0x00000000 0x08340000 0 0x40000>; + msi-parent = <&its>; + /* iommu-map property is fixed up by u-boot */ + iommu-map = <0 &smmu 0 0>; + dma-coherent; + #address-cells = <3>; + #size-cells = <1>; + + /* + * Region type 0x0 - MC portals + * Region type 0x1 - QBMAN portals + */ + ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000 + 0x1 0x0 0x0 0x8 0x18000000 0x8000000>; + + /* + * Define the maximum number of MACs present on the SoC. + */ + dpmacs { + #address-cells = <1>; + #size-cells = <0>; + + dpmac1: dpmac@1 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x1>; + }; + + dpmac2: dpmac@2 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x2>; + }; + + dpmac3: dpmac@3 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x3>; + }; + + dpmac4: dpmac@4 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x4>; + }; + + dpmac5: dpmac@5 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x5>; + }; + + dpmac6: dpmac@6 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x6>; + }; + + dpmac7: dpmac@7 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x7>; + }; + + dpmac8: dpmac@8 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x8>; + }; + + dpmac9: dpmac@9 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x9>; + }; + + dpmac10: dpmac@a { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xa>; + }; + + dpmac11: dpmac@b { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xb>; + }; + + dpmac12: dpmac@c { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xc>; + }; + + dpmac13: dpmac@d { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xd>; + }; + + dpmac14: dpmac@e { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xe>; + }; + + dpmac15: dpmac@f { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0xf>; + }; + + dpmac16: dpmac@10 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x10>; + }; + + dpmac17: dpmac@11 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x11>; + }; + + dpmac18: dpmac@12 { + compatible = "fsl,qoriq-mc-dpmac"; + reg = <0x12>; + }; + }; + }; + }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/hikey.dts b/optee/optee_os/core/arch/arm/dts/hikey.dts new file mode 100644 index 0000000..0ac794b --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/hikey.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <0>; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + + sdp@3e800000 { + compatible = "linaro,secure-heap"; + no-map; + reg = <0x3E800000 0x00400000>; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/sama5d2-pinfunc.h b/optee/optee_os/core/arch/arm/dts/sama5d2-pinfunc.h new file mode 100644 index 0000000..25d64d7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/sama5d2-pinfunc.h @@ -0,0 +1,885 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) 2021 Microchip + */ + +#define PINMUX_PIN(no, func, ioset) \ +(((no) & 0xffff) | (((func) & 0xf) << 16) | (((ioset) & 0xff) << 20)) + +#define PIN_PA0 0 +#define PIN_PA0__GPIO PINMUX_PIN(PIN_PA0, 0, 0) +#define PIN_PA0__SDMMC0_CK PINMUX_PIN(PIN_PA0, 1, 1) +#define PIN_PA0__QSPI0_SCK PINMUX_PIN(PIN_PA0, 2, 1) +#define PIN_PA0__D0 PINMUX_PIN(PIN_PA0, 6, 2) +#define PIN_PA1 1 +#define PIN_PA1__GPIO PINMUX_PIN(PIN_PA1, 0, 0) +#define PIN_PA1__SDMMC0_CMD PINMUX_PIN(PIN_PA1, 1, 1) +#define PIN_PA1__QSPI0_CS PINMUX_PIN(PIN_PA1, 2, 1) +#define PIN_PA1__D1 PINMUX_PIN(PIN_PA1, 6, 2) +#define PIN_PA2 2 +#define PIN_PA2__GPIO PINMUX_PIN(PIN_PA2, 0, 0) +#define PIN_PA2__SDMMC0_DAT0 PINMUX_PIN(PIN_PA2, 1, 1) +#define PIN_PA2__QSPI0_IO0 PINMUX_PIN(PIN_PA2, 2, 1) +#define PIN_PA2__D2 PINMUX_PIN(PIN_PA2, 6, 2) +#define PIN_PA3 3 +#define PIN_PA3__GPIO PINMUX_PIN(PIN_PA3, 0, 0) +#define PIN_PA3__SDMMC0_DAT1 PINMUX_PIN(PIN_PA3, 1, 1) +#define PIN_PA3__QSPI0_IO1 PINMUX_PIN(PIN_PA3, 2, 1) +#define PIN_PA3__D3 PINMUX_PIN(PIN_PA3, 6, 2) +#define PIN_PA4 4 +#define PIN_PA4__GPIO PINMUX_PIN(PIN_PA4, 0, 0) +#define PIN_PA4__SDMMC0_DAT2 PINMUX_PIN(PIN_PA4, 1, 1) +#define PIN_PA4__QSPI0_IO2 PINMUX_PIN(PIN_PA4, 2, 1) +#define PIN_PA4__D4 PINMUX_PIN(PIN_PA4, 6, 2) +#define PIN_PA5 5 +#define PIN_PA5__GPIO PINMUX_PIN(PIN_PA5, 0, 0) +#define PIN_PA5__SDMMC0_DAT3 PINMUX_PIN(PIN_PA5, 1, 1) +#define PIN_PA5__QSPI0_IO3 PINMUX_PIN(PIN_PA5, 2, 1) +#define PIN_PA5__D5 PINMUX_PIN(PIN_PA5, 6, 2) +#define PIN_PA6 6 +#define PIN_PA6__GPIO PINMUX_PIN(PIN_PA6, 0, 0) +#define PIN_PA6__SDMMC0_DAT4 PINMUX_PIN(PIN_PA6, 1, 1) +#define PIN_PA6__QSPI1_SCK PINMUX_PIN(PIN_PA6, 2, 1) +#define PIN_PA6__TIOA5 PINMUX_PIN(PIN_PA6, 4, 1) +#define PIN_PA6__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA6, 5, 1) +#define PIN_PA6__D6 PINMUX_PIN(PIN_PA6, 6, 2) +#define PIN_PA7 7 +#define PIN_PA7__GPIO PINMUX_PIN(PIN_PA7, 0, 0) +#define PIN_PA7__SDMMC0_DAT5 PINMUX_PIN(PIN_PA7, 1, 1) +#define PIN_PA7__QSPI1_IO0 PINMUX_PIN(PIN_PA7, 2, 1) +#define PIN_PA7__TIOB5 PINMUX_PIN(PIN_PA7, 4, 1) +#define PIN_PA7__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA7, 5, 1) +#define PIN_PA7__D7 PINMUX_PIN(PIN_PA7, 6, 2) +#define PIN_PA8 8 +#define PIN_PA8__GPIO PINMUX_PIN(PIN_PA8, 0, 0) +#define PIN_PA8__SDMMC0_DAT6 PINMUX_PIN(PIN_PA8, 1, 1) +#define PIN_PA8__QSPI1_IO1 PINMUX_PIN(PIN_PA8, 2, 1) +#define PIN_PA8__TCLK5 PINMUX_PIN(PIN_PA8, 4, 1) +#define PIN_PA8__FLEXCOM2_IO2 PINMUX_PIN(PIN_PA8, 5, 1) +#define PIN_PA8__NWE_NANDWE PINMUX_PIN(PIN_PA8, 6, 2) +#define PIN_PA9 9 +#define PIN_PA9__GPIO PINMUX_PIN(PIN_PA9, 0, 0) +#define PIN_PA9__SDMMC0_DAT7 PINMUX_PIN(PIN_PA9, 1, 1) +#define PIN_PA9__QSPI1_IO2 PINMUX_PIN(PIN_PA9, 2, 1) +#define PIN_PA9__TIOA4 PINMUX_PIN(PIN_PA9, 4, 1) +#define PIN_PA9__FLEXCOM2_IO3 PINMUX_PIN(PIN_PA9, 5, 1) +#define PIN_PA9__NCS3 PINMUX_PIN(PIN_PA9, 6, 2) +#define PIN_PA10 10 +#define PIN_PA10__GPIO PINMUX_PIN(PIN_PA10, 0, 0) +#define PIN_PA10__SDMMC0_RSTN PINMUX_PIN(PIN_PA10, 1, 1) +#define PIN_PA10__QSPI1_IO3 PINMUX_PIN(PIN_PA10, 2, 1) +#define PIN_PA10__TIOB4 PINMUX_PIN(PIN_PA10, 4, 1) +#define PIN_PA10__FLEXCOM2_IO4 PINMUX_PIN(PIN_PA10, 5, 1) +#define PIN_PA10__A21_NANDALE PINMUX_PIN(PIN_PA10, 6, 2) +#define PIN_PA11 11 +#define PIN_PA11__GPIO PINMUX_PIN(PIN_PA11, 0, 0) +#define PIN_PA11__SDMMC0_VDDSEL PINMUX_PIN(PIN_PA11, 1, 1) +#define PIN_PA11__QSPI1_CS PINMUX_PIN(PIN_PA11, 2, 1) +#define PIN_PA11__TCLK4 PINMUX_PIN(PIN_PA11, 4, 1) +#define PIN_PA11__A22_NANDCLE PINMUX_PIN(PIN_PA11, 6, 2) +#define PIN_PA12 12 +#define PIN_PA12__GPIO PINMUX_PIN(PIN_PA12, 0, 0) +#define PIN_PA12__SDMMC0_WP PINMUX_PIN(PIN_PA12, 1, 1) +#define PIN_PA12__IRQ PINMUX_PIN(PIN_PA12, 2, 1) +#define PIN_PA12__NRD_NANDOE PINMUX_PIN(PIN_PA12, 6, 2) +#define PIN_PA13 13 +#define PIN_PA13__GPIO PINMUX_PIN(PIN_PA13, 0, 0) +#define PIN_PA13__SDMMC0_CD PINMUX_PIN(PIN_PA13, 1, 1) +#define PIN_PA13__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA13, 5, 1) +#define PIN_PA13__D8 PINMUX_PIN(PIN_PA13, 6, 2) +#define PIN_PA14 14 +#define PIN_PA14__GPIO PINMUX_PIN(PIN_PA14, 0, 0) +#define PIN_PA14__SPI0_SPCK PINMUX_PIN(PIN_PA14, 1, 1) +#define PIN_PA14__TK1 PINMUX_PIN(PIN_PA14, 2, 1) +#define PIN_PA14__QSPI0_SCK PINMUX_PIN(PIN_PA14, 3, 2) +#define PIN_PA14__I2SC1_MCK PINMUX_PIN(PIN_PA14, 4, 2) +#define PIN_PA14__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA14, 5, 1) +#define PIN_PA14__D9 PINMUX_PIN(PIN_PA14, 6, 2) +#define PIN_PA15 15 +#define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0) +#define PIN_PA15__SPI0_MOSI PINMUX_PIN(PIN_PA15, 1, 1) +#define PIN_PA15__TF1 PINMUX_PIN(PIN_PA15, 2, 1) +#define PIN_PA15__QSPI0_CS PINMUX_PIN(PIN_PA15, 3, 2) +#define PIN_PA15__I2SC1_CK PINMUX_PIN(PIN_PA15, 4, 2) +#define PIN_PA15__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA15, 5, 1) +#define PIN_PA15__D10 PINMUX_PIN(PIN_PA15, 6, 2) +#define PIN_PA16 16 +#define PIN_PA16__GPIO PINMUX_PIN(PIN_PA16, 0, 0) +#define PIN_PA16__SPI0_MISO PINMUX_PIN(PIN_PA16, 1, 1) +#define PIN_PA16__TD1 PINMUX_PIN(PIN_PA16, 2, 1) +#define PIN_PA16__QSPI0_IO0 PINMUX_PIN(PIN_PA16, 3, 2) +#define PIN_PA16__I2SC1_WS PINMUX_PIN(PIN_PA16, 4, 2) +#define PIN_PA16__FLEXCOM3_IO3 PINMUX_PIN(PIN_PA16, 5, 1) +#define PIN_PA16__D11 PINMUX_PIN(PIN_PA16, 6, 2) +#define PIN_PA17 17 +#define PIN_PA17__GPIO PINMUX_PIN(PIN_PA17, 0, 0) +#define PIN_PA17__SPI0_NPCS0 PINMUX_PIN(PIN_PA17, 1, 1) +#define PIN_PA17__RD1 PINMUX_PIN(PIN_PA17, 2, 1) +#define PIN_PA17__QSPI0_IO1 PINMUX_PIN(PIN_PA17, 3, 2) +#define PIN_PA17__I2SC1_DI0 PINMUX_PIN(PIN_PA17, 4, 2) +#define PIN_PA17__FLEXCOM3_IO4 PINMUX_PIN(PIN_PA17, 5, 1) +#define PIN_PA17__D12 PINMUX_PIN(PIN_PA17, 6, 2) +#define PIN_PA18 18 +#define PIN_PA18__GPIO PINMUX_PIN(PIN_PA18, 0, 0) +#define PIN_PA18__SPI0_NPCS1 PINMUX_PIN(PIN_PA18, 1, 1) +#define PIN_PA18__RK1 PINMUX_PIN(PIN_PA18, 2, 1) +#define PIN_PA18__QSPI0_IO2 PINMUX_PIN(PIN_PA18, 3, 2) +#define PIN_PA18__I2SC1_DO0 PINMUX_PIN(PIN_PA18, 4, 2) +#define PIN_PA18__SDMMC1_DAT0 PINMUX_PIN(PIN_PA18, 5, 1) +#define PIN_PA18__D13 PINMUX_PIN(PIN_PA18, 6, 2) +#define PIN_PA19 19 +#define PIN_PA19__GPIO PINMUX_PIN(PIN_PA19, 0, 0) +#define PIN_PA19__SPI0_NPCS2 PINMUX_PIN(PIN_PA19, 1, 1) +#define PIN_PA19__RF1 PINMUX_PIN(PIN_PA19, 2, 1) +#define PIN_PA19__QSPI0_IO3 PINMUX_PIN(PIN_PA19, 3, 2) +#define PIN_PA19__TIOA0 PINMUX_PIN(PIN_PA19, 4, 1) +#define PIN_PA19__SDMMC1_DAT1 PINMUX_PIN(PIN_PA19, 5, 1) +#define PIN_PA19__D14 PINMUX_PIN(PIN_PA19, 6, 2) +#define PIN_PA20 20 +#define PIN_PA20__GPIO PINMUX_PIN(PIN_PA20, 0, 0) +#define PIN_PA20__SPI0_NPCS3 PINMUX_PIN(PIN_PA20, 1, 1) +#define PIN_PA20__TIOB0 PINMUX_PIN(PIN_PA20, 4, 1) +#define PIN_PA20__SDMMC1_DAT2 PINMUX_PIN(PIN_PA20, 5, 1) +#define PIN_PA20__D15 PINMUX_PIN(PIN_PA20, 6, 2) +#define PIN_PA21 21 +#define PIN_PA21__GPIO PINMUX_PIN(PIN_PA21, 0, 0) +#define PIN_PA21__IRQ PINMUX_PIN(PIN_PA21, 1, 2) +#define PIN_PA21__PCK2 PINMUX_PIN(PIN_PA21, 2, 3) +#define PIN_PA21__TCLK0 PINMUX_PIN(PIN_PA21, 4, 1) +#define PIN_PA21__SDMMC1_DAT3 PINMUX_PIN(PIN_PA21, 5, 1) +#define PIN_PA21__NANDRDY PINMUX_PIN(PIN_PA21, 6, 2) +#define PIN_PA22 22 +#define PIN_PA22__GPIO PINMUX_PIN(PIN_PA22, 0, 0) +#define PIN_PA22__FLEXCOM1_IO2 PINMUX_PIN(PIN_PA22, 1, 1) +#define PIN_PA22__D0 PINMUX_PIN(PIN_PA22, 2, 1) +#define PIN_PA22__TCK PINMUX_PIN(PIN_PA22, 3, 4) +#define PIN_PA22__SPI1_SPCK PINMUX_PIN(PIN_PA22, 4, 2) +#define PIN_PA22__SDMMC1_CK PINMUX_PIN(PIN_PA22, 5, 1) +#define PIN_PA22__QSPI0_SCK PINMUX_PIN(PIN_PA22, 6, 3) +#define PIN_PA23 23 +#define PIN_PA23__GPIO PINMUX_PIN(PIN_PA23, 0, 0) +#define PIN_PA23__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA23, 1, 1) +#define PIN_PA23__D1 PINMUX_PIN(PIN_PA23, 2, 1) +#define PIN_PA23__TDI PINMUX_PIN(PIN_PA23, 3, 4) +#define PIN_PA23__SPI1_MOSI PINMUX_PIN(PIN_PA23, 4, 2) +#define PIN_PA23__QSPI0_CS PINMUX_PIN(PIN_PA23, 6, 3) +#define PIN_PA24 24 +#define PIN_PA24__GPIO PINMUX_PIN(PIN_PA24, 0, 0) +#define PIN_PA24__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA24, 1, 1) +#define PIN_PA24__D2 PINMUX_PIN(PIN_PA24, 2, 1) +#define PIN_PA24__TDO PINMUX_PIN(PIN_PA24, 3, 4) +#define PIN_PA24__SPI1_MISO PINMUX_PIN(PIN_PA24, 4, 2) +#define PIN_PA24__QSPI0_IO0 PINMUX_PIN(PIN_PA24, 6, 3) +#define PIN_PA25 25 +#define PIN_PA25__GPIO PINMUX_PIN(PIN_PA25, 0, 0) +#define PIN_PA25__FLEXCOM1_IO3 PINMUX_PIN(PIN_PA25, 1, 1) +#define PIN_PA25__D3 PINMUX_PIN(PIN_PA25, 2, 1) +#define PIN_PA25__TMS PINMUX_PIN(PIN_PA25, 3, 4) +#define PIN_PA25__SPI1_NPCS0 PINMUX_PIN(PIN_PA25, 4, 2) +#define PIN_PA25__QSPI0_IO1 PINMUX_PIN(PIN_PA25, 6, 3) +#define PIN_PA26 26 +#define PIN_PA26__GPIO PINMUX_PIN(PIN_PA26, 0, 0) +#define PIN_PA26__FLEXCOM1_IO4 PINMUX_PIN(PIN_PA26, 1, 1) +#define PIN_PA26__D4 PINMUX_PIN(PIN_PA26, 2, 1) +#define PIN_PA26__NTRST PINMUX_PIN(PIN_PA26, 3, 4) +#define PIN_PA26__SPI1_NPCS1 PINMUX_PIN(PIN_PA26, 4, 2) +#define PIN_PA26__QSPI0_IO2 PINMUX_PIN(PIN_PA26, 6, 3) +#define PIN_PA27 27 +#define PIN_PA27__GPIO PINMUX_PIN(PIN_PA27, 0, 0) +#define PIN_PA27__TIOA1 PINMUX_PIN(PIN_PA27, 1, 2) +#define PIN_PA27__D5 PINMUX_PIN(PIN_PA27, 2, 1) +#define PIN_PA27__SPI0_NPCS2 PINMUX_PIN(PIN_PA27, 3, 2) +#define PIN_PA27__SPI1_NPCS2 PINMUX_PIN(PIN_PA27, 4, 2) +#define PIN_PA27__SDMMC1_RSTN PINMUX_PIN(PIN_PA27, 5, 1) +#define PIN_PA27__QSPI0_IO3 PINMUX_PIN(PIN_PA27, 6, 3) +#define PIN_PA28 28 +#define PIN_PA28__GPIO PINMUX_PIN(PIN_PA28, 0, 0) +#define PIN_PA28__TIOB1 PINMUX_PIN(PIN_PA28, 1, 2) +#define PIN_PA28__D6 PINMUX_PIN(PIN_PA28, 2, 1) +#define PIN_PA28__SPI0_NPCS3 PINMUX_PIN(PIN_PA28, 3, 2) +#define PIN_PA28__SPI1_NPCS3 PINMUX_PIN(PIN_PA28, 4, 2) +#define PIN_PA28__SDMMC1_CMD PINMUX_PIN(PIN_PA28, 5, 1) +#define PIN_PA28__CLASSD_L0 PINMUX_PIN(PIN_PA28, 6, 1) +#define PIN_PA29 29 +#define PIN_PA29__GPIO PINMUX_PIN(PIN_PA29, 0, 0) +#define PIN_PA29__TCLK1 PINMUX_PIN(PIN_PA29, 1, 2) +#define PIN_PA29__D7 PINMUX_PIN(PIN_PA29, 2, 1) +#define PIN_PA29__SPI0_NPCS1 PINMUX_PIN(PIN_PA29, 3, 2) +#define PIN_PA29__SDMMC1_WP PINMUX_PIN(PIN_PA29, 5, 1) +#define PIN_PA29__CLASSD_L1 PINMUX_PIN(PIN_PA29, 6, 1) +#define PIN_PA30 30 +#define PIN_PA30__GPIO PINMUX_PIN(PIN_PA30, 0, 0) +#define PIN_PA30__NWE_NANDWE PINMUX_PIN(PIN_PA30, 2, 1) +#define PIN_PA30__SPI0_NPCS0 PINMUX_PIN(PIN_PA30, 3, 2) +#define PIN_PA30__PWMH0 PINMUX_PIN(PIN_PA30, 4, 1) +#define PIN_PA30__SDMMC1_CD PINMUX_PIN(PIN_PA30, 5, 1) +#define PIN_PA30__CLASSD_L2 PINMUX_PIN(PIN_PA30, 6, 1) +#define PIN_PA31 31 +#define PIN_PA31__GPIO PINMUX_PIN(PIN_PA31, 0, 0) +#define PIN_PA31__NCS3 PINMUX_PIN(PIN_PA31, 2, 1) +#define PIN_PA31__SPI0_MISO PINMUX_PIN(PIN_PA31, 3, 2) +#define PIN_PA31__PWML0 PINMUX_PIN(PIN_PA31, 4, 1) +#define PIN_PA31__CLASSD_L3 PINMUX_PIN(PIN_PA31, 6, 1) +#define PIN_PB0 32 +#define PIN_PB0__GPIO PINMUX_PIN(PIN_PB0, 0, 0) +#define PIN_PB0__A21_NANDALE PINMUX_PIN(PIN_PB0, 2, 1) +#define PIN_PB0__SPI0_MOSI PINMUX_PIN(PIN_PB0, 3, 2) +#define PIN_PB0__PWMH1 PINMUX_PIN(PIN_PB0, 4, 1) +#define PIN_PB1 33 +#define PIN_PB1__GPIO PINMUX_PIN(PIN_PB1, 0, 0) +#define PIN_PB1__A22_NANDCLE PINMUX_PIN(PIN_PB1, 2, 1) +#define PIN_PB1__SPI0_SPCK PINMUX_PIN(PIN_PB1, 3, 2) +#define PIN_PB1__PWML1 PINMUX_PIN(PIN_PB1, 4, 1) +#define PIN_PB1__CLASSD_R0 PINMUX_PIN(PIN_PB1, 6, 1) +#define PIN_PB2 34 +#define PIN_PB2__GPIO PINMUX_PIN(PIN_PB2, 0, 0) +#define PIN_PB2__NRD_NANDOE PINMUX_PIN(PIN_PB2, 2, 1) +#define PIN_PB2__PWMFI0 PINMUX_PIN(PIN_PB2, 4, 1) +#define PIN_PB2__CLASSD_R1 PINMUX_PIN(PIN_PB2, 6, 1) +#define PIN_PB3 35 +#define PIN_PB3__GPIO PINMUX_PIN(PIN_PB3, 0, 0) +#define PIN_PB3__URXD4 PINMUX_PIN(PIN_PB3, 1, 1) +#define PIN_PB3__D8 PINMUX_PIN(PIN_PB3, 2, 1) +#define PIN_PB3__IRQ PINMUX_PIN(PIN_PB3, 3, 3) +#define PIN_PB3__PWMEXTRG0 PINMUX_PIN(PIN_PB3, 4, 1) +#define PIN_PB3__CLASSD_R2 PINMUX_PIN(PIN_PB3, 6, 1) +#define PIN_PB4 36 +#define PIN_PB4__GPIO PINMUX_PIN(PIN_PB4, 0, 0) +#define PIN_PB4__UTXD4 PINMUX_PIN(PIN_PB4, 1, 1) +#define PIN_PB4__D9 PINMUX_PIN(PIN_PB4, 2, 1) +#define PIN_PB4__FIQ PINMUX_PIN(PIN_PB4, 3, 4) +#define PIN_PB4__CLASSD_R3 PINMUX_PIN(PIN_PB4, 6, 1) +#define PIN_PB5 37 +#define PIN_PB5__GPIO PINMUX_PIN(PIN_PB5, 0, 0) +#define PIN_PB5__TCLK2 PINMUX_PIN(PIN_PB5, 1, 1) +#define PIN_PB5__D10 PINMUX_PIN(PIN_PB5, 2, 1) +#define PIN_PB5__PWMH2 PINMUX_PIN(PIN_PB5, 3, 1) +#define PIN_PB5__QSPI1_SCK PINMUX_PIN(PIN_PB5, 4, 2) +#define PIN_PB5__GTSUCOMP PINMUX_PIN(PIN_PB5, 6, 3) +#define PIN_PB6 38 +#define PIN_PB6__GPIO PINMUX_PIN(PIN_PB6, 0, 0) +#define PIN_PB6__TIOA2 PINMUX_PIN(PIN_PB6, 1, 1) +#define PIN_PB6__D11 PINMUX_PIN(PIN_PB6, 2, 1) +#define PIN_PB6__PWML2 PINMUX_PIN(PIN_PB6, 3, 1) +#define PIN_PB6__QSPI1_CS PINMUX_PIN(PIN_PB6, 4, 2) +#define PIN_PB6__GTXER PINMUX_PIN(PIN_PB6, 6, 3) +#define PIN_PB7 39 +#define PIN_PB7__GPIO PINMUX_PIN(PIN_PB7, 0, 0) +#define PIN_PB7__TIOB2 PINMUX_PIN(PIN_PB7, 1, 1) +#define PIN_PB7__D12 PINMUX_PIN(PIN_PB7, 2, 1) +#define PIN_PB7__PWMH3 PINMUX_PIN(PIN_PB7, 3, 1) +#define PIN_PB7__QSPI1_IO0 PINMUX_PIN(PIN_PB7, 4, 2) +#define PIN_PB7__GRXCK PINMUX_PIN(PIN_PB7, 6, 3) +#define PIN_PB8 40 +#define PIN_PB8__GPIO PINMUX_PIN(PIN_PB8, 0, 0) +#define PIN_PB8__TCLK3 PINMUX_PIN(PIN_PB8, 1, 1) +#define PIN_PB8__D13 PINMUX_PIN(PIN_PB8, 2, 1) +#define PIN_PB8__PWML3 PINMUX_PIN(PIN_PB8, 3, 1) +#define PIN_PB8__QSPI1_IO1 PINMUX_PIN(PIN_PB8, 4, 2) +#define PIN_PB8__GCRS PINMUX_PIN(PIN_PB8, 6, 3) +#define PIN_PB9 41 +#define PIN_PB9__GPIO PINMUX_PIN(PIN_PB9, 0, 0) +#define PIN_PB9__TIOA3 PINMUX_PIN(PIN_PB9, 1, 1) +#define PIN_PB9__D14 PINMUX_PIN(PIN_PB9, 2, 1) +#define PIN_PB9__PWMFI1 PINMUX_PIN(PIN_PB9, 3, 1) +#define PIN_PB9__QSPI1_IO2 PINMUX_PIN(PIN_PB9, 4, 2) +#define PIN_PB9__GCOL PINMUX_PIN(PIN_PB9, 6, 3) +#define PIN_PB10 42 +#define PIN_PB10__GPIO PINMUX_PIN(PIN_PB10, 0, 0) +#define PIN_PB10__TIOB3 PINMUX_PIN(PIN_PB10, 1, 1) +#define PIN_PB10__D15 PINMUX_PIN(PIN_PB10, 2, 1) +#define PIN_PB10__PWMEXTRG1 PINMUX_PIN(PIN_PB10, 3, 1) +#define PIN_PB10__QSPI1_IO3 PINMUX_PIN(PIN_PB10, 4, 2) +#define PIN_PB10__GRX2 PINMUX_PIN(PIN_PB10, 6, 3) +#define PIN_PB11 43 +#define PIN_PB11__GPIO PINMUX_PIN(PIN_PB11, 0, 0) +#define PIN_PB11__LCDDAT0 PINMUX_PIN(PIN_PB11, 1, 1) +#define PIN_PB11__A0_NBS0 PINMUX_PIN(PIN_PB11, 2, 1) +#define PIN_PB11__URXD3 PINMUX_PIN(PIN_PB11, 3, 3) +#define PIN_PB11__PDMIC_DAT PINMUX_PIN(PIN_PB11, 4, 2) +#define PIN_PB11__GRX3 PINMUX_PIN(PIN_PB11, 6, 3) +#define PIN_PB12 44 +#define PIN_PB12__GPIO PINMUX_PIN(PIN_PB12, 0, 0) +#define PIN_PB12__LCDDAT1 PINMUX_PIN(PIN_PB12, 1, 1) +#define PIN_PB12__A1 PINMUX_PIN(PIN_PB12, 2, 1) +#define PIN_PB12__UTXD3 PINMUX_PIN(PIN_PB12, 3, 3) +#define PIN_PB12__PDMIC_CLK PINMUX_PIN(PIN_PB12, 4, 2) +#define PIN_PB12__GTX2 PINMUX_PIN(PIN_PB12, 6, 3) +#define PIN_PB13 45 +#define PIN_PB13__GPIO PINMUX_PIN(PIN_PB13, 0, 0) +#define PIN_PB13__LCDDAT2 PINMUX_PIN(PIN_PB13, 1, 1) +#define PIN_PB13__A2 PINMUX_PIN(PIN_PB13, 2, 1) +#define PIN_PB13__PCK1 PINMUX_PIN(PIN_PB13, 3, 3) +#define PIN_PB13__GTX3 PINMUX_PIN(PIN_PB13, 6, 3) +#define PIN_PB14 46 +#define PIN_PB14__GPIO PINMUX_PIN(PIN_PB14, 0, 0) +#define PIN_PB14__LCDDAT3 PINMUX_PIN(PIN_PB14, 1, 1) +#define PIN_PB14__A3 PINMUX_PIN(PIN_PB14, 2, 1) +#define PIN_PB14__TK1 PINMUX_PIN(PIN_PB14, 3, 2) +#define PIN_PB14__I2SC1_MCK PINMUX_PIN(PIN_PB14, 4, 1) +#define PIN_PB14__QSPI1_SCK PINMUX_PIN(PIN_PB14, 5, 3) +#define PIN_PB14__GTXCK PINMUX_PIN(PIN_PB14, 6, 3) +#define PIN_PB15 47 +#define PIN_PB15__GPIO PINMUX_PIN(PIN_PB15, 0, 0) +#define PIN_PB15__LCDDAT4 PINMUX_PIN(PIN_PB15, 1, 1) +#define PIN_PB15__A4 PINMUX_PIN(PIN_PB15, 2, 1) +#define PIN_PB15__TF1 PINMUX_PIN(PIN_PB15, 3, 2) +#define PIN_PB15__I2SC1_CK PINMUX_PIN(PIN_PB15, 4, 1) +#define PIN_PB15__QSPI1_CS PINMUX_PIN(PIN_PB15, 5, 3) +#define PIN_PB15__GTXEN PINMUX_PIN(PIN_PB15, 6, 3) +#define PIN_PB16 48 +#define PIN_PB16__GPIO PINMUX_PIN(PIN_PB16, 0, 0) +#define PIN_PB16__LCDDAT5 PINMUX_PIN(PIN_PB16, 1, 1) +#define PIN_PB16__A5 PINMUX_PIN(PIN_PB16, 2, 1) +#define PIN_PB16__TD1 PINMUX_PIN(PIN_PB16, 3, 2) +#define PIN_PB16__I2SC1_WS PINMUX_PIN(PIN_PB16, 4, 1) +#define PIN_PB16__QSPI1_IO0 PINMUX_PIN(PIN_PB16, 5, 3) +#define PIN_PB16__GRXDV PINMUX_PIN(PIN_PB16, 6, 3) +#define PIN_PB17 49 +#define PIN_PB17__GPIO PINMUX_PIN(PIN_PB17, 0, 0) +#define PIN_PB17__LCDDAT6 PINMUX_PIN(PIN_PB17, 1, 1) +#define PIN_PB17__A6 PINMUX_PIN(PIN_PB17, 2, 1) +#define PIN_PB17__RD1 PINMUX_PIN(PIN_PB17, 3, 2) +#define PIN_PB17__I2SC1_DI0 PINMUX_PIN(PIN_PB17, 4, 1) +#define PIN_PB17__QSPI1_IO1 PINMUX_PIN(PIN_PB17, 5, 3) +#define PIN_PB17__GRXER PINMUX_PIN(PIN_PB17, 6, 3) +#define PIN_PB18 50 +#define PIN_PB18__GPIO PINMUX_PIN(PIN_PB18, 0, 0) +#define PIN_PB18__LCDDAT7 PINMUX_PIN(PIN_PB18, 1, 1) +#define PIN_PB18__A7 PINMUX_PIN(PIN_PB18, 2, 1) +#define PIN_PB18__RK1 PINMUX_PIN(PIN_PB18, 3, 2) +#define PIN_PB18__I2SC1_DO0 PINMUX_PIN(PIN_PB18, 4, 1) +#define PIN_PB18__QSPI1_IO2 PINMUX_PIN(PIN_PB18, 5, 3) +#define PIN_PB18__GRX0 PINMUX_PIN(PIN_PB18, 6, 3) +#define PIN_PB19 51 +#define PIN_PB19__GPIO PINMUX_PIN(PIN_PB19, 0, 0) +#define PIN_PB19__LCDDAT8 PINMUX_PIN(PIN_PB19, 1, 1) +#define PIN_PB19__A8 PINMUX_PIN(PIN_PB19, 2, 1) +#define PIN_PB19__RF1 PINMUX_PIN(PIN_PB19, 3, 2) +#define PIN_PB19__TIOA3 PINMUX_PIN(PIN_PB19, 4, 2) +#define PIN_PB19__QSPI1_IO3 PINMUX_PIN(PIN_PB19, 5, 3) +#define PIN_PB19__GRX1 PINMUX_PIN(PIN_PB19, 6, 3) +#define PIN_PB20 52 +#define PIN_PB20__GPIO PINMUX_PIN(PIN_PB20, 0, 0) +#define PIN_PB20__LCDDAT9 PINMUX_PIN(PIN_PB20, 1, 1) +#define PIN_PB20__A9 PINMUX_PIN(PIN_PB20, 2, 1) +#define PIN_PB20__TK0 PINMUX_PIN(PIN_PB20, 3, 1) +#define PIN_PB20__TIOB3 PINMUX_PIN(PIN_PB20, 4, 2) +#define PIN_PB20__PCK1 PINMUX_PIN(PIN_PB20, 5, 4) +#define PIN_PB20__GTX0 PINMUX_PIN(PIN_PB20, 6, 3) +#define PIN_PB21 53 +#define PIN_PB21__GPIO PINMUX_PIN(PIN_PB21, 0, 0) +#define PIN_PB21__LCDDAT10 PINMUX_PIN(PIN_PB21, 1, 1) +#define PIN_PB21__A10 PINMUX_PIN(PIN_PB21, 2, 1) +#define PIN_PB21__TF0 PINMUX_PIN(PIN_PB21, 3, 1) +#define PIN_PB21__TCLK3 PINMUX_PIN(PIN_PB21, 4, 2) +#define PIN_PB21__FLEXCOM3_IO2 PINMUX_PIN(PIN_PB21, 5, 3) +#define PIN_PB21__GTX1 PINMUX_PIN(PIN_PB21, 6, 3) +#define PIN_PB22 54 +#define PIN_PB22__GPIO PINMUX_PIN(PIN_PB22, 0, 0) +#define PIN_PB22__LCDDAT11 PINMUX_PIN(PIN_PB22, 1, 1) +#define PIN_PB22__A11 PINMUX_PIN(PIN_PB22, 2, 1) +#define PIN_PB22__TD0 PINMUX_PIN(PIN_PB22, 3, 1) +#define PIN_PB22__TIOA2 PINMUX_PIN(PIN_PB22, 4, 2) +#define PIN_PB22__FLEXCOM3_IO1 PINMUX_PIN(PIN_PB22, 5, 3) +#define PIN_PB22__GMDC PINMUX_PIN(PIN_PB22, 6, 3) +#define PIN_PB23 55 +#define PIN_PB23__GPIO PINMUX_PIN(PIN_PB23, 0, 0) +#define PIN_PB23__LCDDAT12 PINMUX_PIN(PIN_PB23, 1, 1) +#define PIN_PB23__A12 PINMUX_PIN(PIN_PB23, 2, 1) +#define PIN_PB23__RD0 PINMUX_PIN(PIN_PB23, 3, 1) +#define PIN_PB23__TIOB2 PINMUX_PIN(PIN_PB23, 4, 2) +#define PIN_PB23__FLEXCOM3_IO0 PINMUX_PIN(PIN_PB23, 5, 3) +#define PIN_PB23__GMDIO PINMUX_PIN(PIN_PB23, 6, 3) +#define PIN_PB24 56 +#define PIN_PB24__GPIO PINMUX_PIN(PIN_PB24, 0, 0) +#define PIN_PB24__LCDDAT13 PINMUX_PIN(PIN_PB24, 1, 1) +#define PIN_PB24__A13 PINMUX_PIN(PIN_PB24, 2, 1) +#define PIN_PB24__RK0 PINMUX_PIN(PIN_PB24, 3, 1) +#define PIN_PB24__TCLK2 PINMUX_PIN(PIN_PB24, 4, 2) +#define PIN_PB24__FLEXCOM3_IO3 PINMUX_PIN(PIN_PB24, 5, 3) +#define PIN_PB24__ISC_D10 PINMUX_PIN(PIN_PB24, 6, 3) +#define PIN_PB25 57 +#define PIN_PB25__GPIO PINMUX_PIN(PIN_PB25, 0, 0) +#define PIN_PB25__LCDDAT14 PINMUX_PIN(PIN_PB25, 1, 1) +#define PIN_PB25__A14 PINMUX_PIN(PIN_PB25, 2, 1) +#define PIN_PB25__RF0 PINMUX_PIN(PIN_PB25, 3, 1) +#define PIN_PB25__FLEXCOM3_IO4 PINMUX_PIN(PIN_PB25, 5, 3) +#define PIN_PB25__ISC_D11 PINMUX_PIN(PIN_PB25, 6, 3) +#define PIN_PB26 58 +#define PIN_PB26__GPIO PINMUX_PIN(PIN_PB26, 0, 0) +#define PIN_PB26__LCDDAT15 PINMUX_PIN(PIN_PB26, 1, 1) +#define PIN_PB26__A15 PINMUX_PIN(PIN_PB26, 2, 1) +#define PIN_PB26__URXD0 PINMUX_PIN(PIN_PB26, 3, 1) +#define PIN_PB26__PDMIC_DAT PINMUX_PIN(PIN_PB26, 4, 1) +#define PIN_PB26__ISC_D0 PINMUX_PIN(PIN_PB26, 6, 3) +#define PIN_PB27 59 +#define PIN_PB27__GPIO PINMUX_PIN(PIN_PB27, 0, 0) +#define PIN_PB27__LCDDAT16 PINMUX_PIN(PIN_PB27, 1, 1) +#define PIN_PB27__A16 PINMUX_PIN(PIN_PB27, 2, 1) +#define PIN_PB27__UTXD0 PINMUX_PIN(PIN_PB27, 3, 1) +#define PIN_PB27__PDMIC_CLK PINMUX_PIN(PIN_PB27, 4, 1) +#define PIN_PB27__ISC_D1 PINMUX_PIN(PIN_PB27, 6, 3) +#define PIN_PB28 60 +#define PIN_PB28__GPIO PINMUX_PIN(PIN_PB28, 0, 0) +#define PIN_PB28__LCDDAT17 PINMUX_PIN(PIN_PB28, 1, 1) +#define PIN_PB28__A17 PINMUX_PIN(PIN_PB28, 2, 1) +#define PIN_PB28__FLEXCOM0_IO0 PINMUX_PIN(PIN_PB28, 3, 1) +#define PIN_PB28__TIOA5 PINMUX_PIN(PIN_PB28, 4, 2) +#define PIN_PB28__ISC_D2 PINMUX_PIN(PIN_PB28, 6, 3) +#define PIN_PB29 61 +#define PIN_PB29__GPIO PINMUX_PIN(PIN_PB29, 0, 0) +#define PIN_PB29__LCDDAT18 PINMUX_PIN(PIN_PB29, 1, 1) +#define PIN_PB29__A18 PINMUX_PIN(PIN_PB29, 2, 1) +#define PIN_PB29__FLEXCOM0_IO1 PINMUX_PIN(PIN_PB29, 3, 1) +#define PIN_PB29__TIOB5 PINMUX_PIN(PIN_PB29, 4, 2) +#define PIN_PB29__ISC_D3 PINMUX_PIN(PIN_PB29, 7, 3) +#define PIN_PB30 62 +#define PIN_PB30__GPIO PINMUX_PIN(PIN_PB30, 0, 0) +#define PIN_PB30__LCDDAT19 PINMUX_PIN(PIN_PB30, 1, 1) +#define PIN_PB30__A19 PINMUX_PIN(PIN_PB30, 2, 1) +#define PIN_PB30__FLEXCOM0_IO2 PINMUX_PIN(PIN_PB30, 3, 1) +#define PIN_PB30__TCLK5 PINMUX_PIN(PIN_PB30, 4, 2) +#define PIN_PB30__ISC_D4 PINMUX_PIN(PIN_PB30, 6, 3) +#define PIN_PB31 63 +#define PIN_PB31__GPIO PINMUX_PIN(PIN_PB31, 0, 0) +#define PIN_PB31__LCDDAT20 PINMUX_PIN(PIN_PB31, 1, 1) +#define PIN_PB31__A20 PINMUX_PIN(PIN_PB31, 2, 1) +#define PIN_PB31__FLEXCOM0_IO3 PINMUX_PIN(PIN_PB31, 3, 1) +#define PIN_PB31__TWD0 PINMUX_PIN(PIN_PB31, 4, 1) +#define PIN_PB31__ISC_D5 PINMUX_PIN(PIN_PB31, 6, 3) +#define PIN_PC0 64 +#define PIN_PC0__GPIO PINMUX_PIN(PIN_PC0, 0, 0) +#define PIN_PC0__LCDDAT21 PINMUX_PIN(PIN_PC0, 1, 1) +#define PIN_PC0__A23 PINMUX_PIN(PIN_PC0, 2, 1) +#define PIN_PC0__FLEXCOM0_IO4 PINMUX_PIN(PIN_PC0, 3, 1) +#define PIN_PC0__TWCK0 PINMUX_PIN(PIN_PC0, 4, 1) +#define PIN_PC0__ISC_D6 PINMUX_PIN(PIN_PC0, 6, 3) +#define PIN_PC1 65 +#define PIN_PC1__GPIO PINMUX_PIN(PIN_PC1, 0, 0) +#define PIN_PC1__LCDDAT22 PINMUX_PIN(PIN_PC1, 1, 1) +#define PIN_PC1__A24 PINMUX_PIN(PIN_PC1, 2, 1) +#define PIN_PC1__CANTX0 PINMUX_PIN(PIN_PC1, 3, 1) +#define PIN_PC1__SPI1_SPCK PINMUX_PIN(PIN_PC1, 4, 1) +#define PIN_PC1__I2SC0_CK PINMUX_PIN(PIN_PC1, 5, 1) +#define PIN_PC1__ISC_D7 PINMUX_PIN(PIN_PC1, 6, 3) +#define PIN_PC2 66 +#define PIN_PC2__GPIO PINMUX_PIN(PIN_PC2, 0, 0) +#define PIN_PC2__LCDDAT23 PINMUX_PIN(PIN_PC2, 1, 1) +#define PIN_PC2__A25 PINMUX_PIN(PIN_PC2, 2, 1) +#define PIN_PC2__CANRX0 PINMUX_PIN(PIN_PC2, 3, 1) +#define PIN_PC2__SPI1_MOSI PINMUX_PIN(PIN_PC2, 4, 1) +#define PIN_PC2__I2SC0_MCK PINMUX_PIN(PIN_PC2, 5, 1) +#define PIN_PC2__ISC_D8 PINMUX_PIN(PIN_PC2, 6, 3) +#define PIN_PC3 67 +#define PIN_PC3__GPIO PINMUX_PIN(PIN_PC3, 0, 0) +#define PIN_PC3__LCDPWM PINMUX_PIN(PIN_PC3, 1, 1) +#define PIN_PC3__NWAIT PINMUX_PIN(PIN_PC3, 2, 1) +#define PIN_PC3__TIOA1 PINMUX_PIN(PIN_PC3, 3, 1) +#define PIN_PC3__SPI1_MISO PINMUX_PIN(PIN_PC3, 4, 1) +#define PIN_PC3__I2SC0_WS PINMUX_PIN(PIN_PC3, 5, 1) +#define PIN_PC3__ISC_D9 PINMUX_PIN(PIN_PC3, 6, 3) +#define PIN_PC4 68 +#define PIN_PC4__GPIO PINMUX_PIN(PIN_PC4, 0, 0) +#define PIN_PC4__LCDDISP PINMUX_PIN(PIN_PC4, 1, 1) +#define PIN_PC4__NWR1_NBS1 PINMUX_PIN(PIN_PC4, 2, 1) +#define PIN_PC4__TIOB1 PINMUX_PIN(PIN_PC4, 3, 1) +#define PIN_PC4__SPI1_NPCS0 PINMUX_PIN(PIN_PC4, 4, 1) +#define PIN_PC4__I2SC0_DI0 PINMUX_PIN(PIN_PC4, 5, 1) +#define PIN_PC4__ISC_PCK PINMUX_PIN(PIN_PC4, 6, 3) +#define PIN_PC5 69 +#define PIN_PC5__GPIO PINMUX_PIN(PIN_PC5, 0, 0) +#define PIN_PC5__LCDVSYNC PINMUX_PIN(PIN_PC5, 1, 1) +#define PIN_PC5__NCS0 PINMUX_PIN(PIN_PC5, 2, 1) +#define PIN_PC5__TCLK1 PINMUX_PIN(PIN_PC5, 3, 1) +#define PIN_PC5__SPI1_NPCS1 PINMUX_PIN(PIN_PC5, 4, 1) +#define PIN_PC5__I2SC0_DO0 PINMUX_PIN(PIN_PC5, 5, 1) +#define PIN_PC5__ISC_VSYNC PINMUX_PIN(PIN_PC5, 6, 3) +#define PIN_PC6 70 +#define PIN_PC6__GPIO PINMUX_PIN(PIN_PC6, 0, 0) +#define PIN_PC6__LCDHSYNC PINMUX_PIN(PIN_PC6, 1, 1) +#define PIN_PC6__NCS1 PINMUX_PIN(PIN_PC6, 2, 1) +#define PIN_PC6__TWD1 PINMUX_PIN(PIN_PC6, 3, 1) +#define PIN_PC6__SPI1_NPCS2 PINMUX_PIN(PIN_PC6, 4, 1) +#define PIN_PC6__ISC_HSYNC PINMUX_PIN(PIN_PC6, 6, 3) +#define PIN_PC7 71 +#define PIN_PC7__GPIO PINMUX_PIN(PIN_PC7, 0, 0) +#define PIN_PC7__LCDPCK PINMUX_PIN(PIN_PC7, 1, 1) +#define PIN_PC7__NCS2 PINMUX_PIN(PIN_PC7, 2, 1) +#define PIN_PC7__TWCK1 PINMUX_PIN(PIN_PC7, 3, 1) +#define PIN_PC7__SPI1_NPCS3 PINMUX_PIN(PIN_PC7, 4, 1) +#define PIN_PC7__URXD1 PINMUX_PIN(PIN_PC7, 5, 2) +#define PIN_PC7__ISC_MCK PINMUX_PIN(PIN_PC7, 6, 3) +#define PIN_PC8 72 +#define PIN_PC8__GPIO PINMUX_PIN(PIN_PC8, 0, 0) +#define PIN_PC8__LCDDEN PINMUX_PIN(PIN_PC8, 1, 1) +#define PIN_PC8__NANDRDY PINMUX_PIN(PIN_PC8, 2, 1) +#define PIN_PC8__FIQ PINMUX_PIN(PIN_PC8, 3, 1) +#define PIN_PC8__PCK0 PINMUX_PIN(PIN_PC8, 4, 3) +#define PIN_PC8__UTXD1 PINMUX_PIN(PIN_PC8, 5, 2) +#define PIN_PC8__ISC_FIELD PINMUX_PIN(PIN_PC8, 6, 3) +#define PIN_PC9 73 +#define PIN_PC9__GPIO PINMUX_PIN(PIN_PC9, 0, 0) +#define PIN_PC9__FIQ PINMUX_PIN(PIN_PC9, 1, 3) +#define PIN_PC9__GTSUCOMP PINMUX_PIN(PIN_PC9, 2, 1) +#define PIN_PC9__ISC_D0 PINMUX_PIN(PIN_PC9, 3, 1) +#define PIN_PC9__TIOA4 PINMUX_PIN(PIN_PC9, 4, 2) +#define PIN_PC10 74 +#define PIN_PC10__GPIO PINMUX_PIN(PIN_PC10, 0, 0) +#define PIN_PC10__LCDDAT2 PINMUX_PIN(PIN_PC10, 1, 2) +#define PIN_PC10__GTXCK PINMUX_PIN(PIN_PC10, 2, 1) +#define PIN_PC10__ISC_D1 PINMUX_PIN(PIN_PC10, 3, 1) +#define PIN_PC10__TIOB4 PINMUX_PIN(PIN_PC10, 4, 2) +#define PIN_PC10__CANTX0 PINMUX_PIN(PIN_PC10, 5, 2) +#define PIN_PC11 75 +#define PIN_PC11__GPIO PINMUX_PIN(PIN_PC11, 0, 0) +#define PIN_PC11__LCDDAT3 PINMUX_PIN(PIN_PC11, 1, 2) +#define PIN_PC11__GTXEN PINMUX_PIN(PIN_PC11, 2, 1) +#define PIN_PC11__ISC_D2 PINMUX_PIN(PIN_PC11, 3, 1) +#define PIN_PC11__TCLK4 PINMUX_PIN(PIN_PC11, 4, 2) +#define PIN_PC11__CANRX0 PINMUX_PIN(PIN_PC11, 5, 2) +#define PIN_PC11__A0_NBS0 PINMUX_PIN(PIN_PC11, 6, 2) +#define PIN_PC12 76 +#define PIN_PC12__GPIO PINMUX_PIN(PIN_PC12, 0, 0) +#define PIN_PC12__LCDDAT4 PINMUX_PIN(PIN_PC12, 1, 2) +#define PIN_PC12__GRXDV PINMUX_PIN(PIN_PC12, 2, 1) +#define PIN_PC12__ISC_D3 PINMUX_PIN(PIN_PC12, 3, 1) +#define PIN_PC12__URXD3 PINMUX_PIN(PIN_PC12, 4, 1) +#define PIN_PC12__TK0 PINMUX_PIN(PIN_PC12, 5, 2) +#define PIN_PC12__A1 PINMUX_PIN(PIN_PC12, 6, 2) +#define PIN_PC13 77 +#define PIN_PC13__GPIO PINMUX_PIN(PIN_PC13, 0, 0) +#define PIN_PC13__LCDDAT5 PINMUX_PIN(PIN_PC13, 1, 2) +#define PIN_PC13__GRXER PINMUX_PIN(PIN_PC13, 2, 1) +#define PIN_PC13__ISC_D4 PINMUX_PIN(PIN_PC13, 3, 1) +#define PIN_PC13__UTXD3 PINMUX_PIN(PIN_PC13, 4, 1) +#define PIN_PC13__TF0 PINMUX_PIN(PIN_PC13, 5, 2) +#define PIN_PC13__A2 PINMUX_PIN(PIN_PC13, 6, 2) +#define PIN_PC14 78 +#define PIN_PC14__GPIO PINMUX_PIN(PIN_PC14, 0, 0) +#define PIN_PC14__LCDDAT6 PINMUX_PIN(PIN_PC14, 1, 2) +#define PIN_PC14__GRX0 PINMUX_PIN(PIN_PC14, 2, 1) +#define PIN_PC14__ISC_D5 PINMUX_PIN(PIN_PC14, 3, 1) +#define PIN_PC14__TD0 PINMUX_PIN(PIN_PC14, 5, 2) +#define PIN_PC14__A3 PINMUX_PIN(PIN_PC14, 6, 2) +#define PIN_PC15 79 +#define PIN_PC15__GPIO PINMUX_PIN(PIN_PC15, 0, 0) +#define PIN_PC15__LCDDAT7 PINMUX_PIN(PIN_PC15, 1, 2) +#define PIN_PC15__GRX1 PINMUX_PIN(PIN_PC15, 2, 1) +#define PIN_PC15__ISC_D6 PINMUX_PIN(PIN_PC15, 3, 1) +#define PIN_PC15__RD0 PINMUX_PIN(PIN_PC15, 5, 2) +#define PIN_PC15__A4 PINMUX_PIN(PIN_PC15, 6, 2) +#define PIN_PC16 80 +#define PIN_PC16__GPIO PINMUX_PIN(PIN_PC16, 0, 0) +#define PIN_PC16__LCDDAT10 PINMUX_PIN(PIN_PC16, 1, 2) +#define PIN_PC16__GTX0 PINMUX_PIN(PIN_PC16, 2, 1) +#define PIN_PC16__ISC_D7 PINMUX_PIN(PIN_PC16, 3, 1) +#define PIN_PC16__RK0 PINMUX_PIN(PIN_PC16, 5, 2) +#define PIN_PC16__A5 PINMUX_PIN(PIN_PC16, 6, 2) +#define PIN_PC17 81 +#define PIN_PC17__GPIO PINMUX_PIN(PIN_PC17, 0, 0) +#define PIN_PC17__LCDDAT11 PINMUX_PIN(PIN_PC17, 1, 2) +#define PIN_PC17__GTX1 PINMUX_PIN(PIN_PC17, 2, 1) +#define PIN_PC17__ISC_D8 PINMUX_PIN(PIN_PC17, 3, 1) +#define PIN_PC17__RF0 PINMUX_PIN(PIN_PC17, 5, 2) +#define PIN_PC17__A6 PINMUX_PIN(PIN_PC17, 6, 2) +#define PIN_PC18 82 +#define PIN_PC18__GPIO PINMUX_PIN(PIN_PC18, 0, 0) +#define PIN_PC18__LCDDAT12 PINMUX_PIN(PIN_PC18, 1, 2) +#define PIN_PC18__GMDC PINMUX_PIN(PIN_PC18, 2, 1) +#define PIN_PC18__ISC_D9 PINMUX_PIN(PIN_PC18, 3, 1) +#define PIN_PC18__FLEXCOM3_IO2 PINMUX_PIN(PIN_PC18, 5, 2) +#define PIN_PC18__A7 PINMUX_PIN(PIN_PC18, 6, 2) +#define PIN_PC19 83 +#define PIN_PC19__GPIO PINMUX_PIN(PIN_PC19, 0, 0) +#define PIN_PC19__LCDDAT13 PINMUX_PIN(PIN_PC19, 1, 2) +#define PIN_PC19__GMDIO PINMUX_PIN(PIN_PC19, 2, 1) +#define PIN_PC19__ISC_D10 PINMUX_PIN(PIN_PC19, 3, 1) +#define PIN_PC19__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC19, 5, 2) +#define PIN_PC19__A8 PINMUX_PIN(PIN_PC19, 6, 2) +#define PIN_PC20 84 +#define PIN_PC20__GPIO PINMUX_PIN(PIN_PC20, 0, 0) +#define PIN_PC20__LCDDAT14 PINMUX_PIN(PIN_PC20, 1, 2) +#define PIN_PC20__GRXCK PINMUX_PIN(PIN_PC20, 2, 1) +#define PIN_PC20__ISC_D11 PINMUX_PIN(PIN_PC20, 3, 1) +#define PIN_PC20__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC20, 5, 2) +#define PIN_PC20__A9 PINMUX_PIN(PIN_PC20, 6, 2) +#define PIN_PC21 85 +#define PIN_PC21__GPIO PINMUX_PIN(PIN_PC21, 0, 0) +#define PIN_PC21__LCDDAT15 PINMUX_PIN(PIN_PC21, 1, 2) +#define PIN_PC21__GTXER PINMUX_PIN(PIN_PC21, 2, 1) +#define PIN_PC21__ISC_PCK PINMUX_PIN(PIN_PC21, 3, 1) +#define PIN_PC21__FLEXCOM3_IO3 PINMUX_PIN(PIN_PC21, 5, 2) +#define PIN_PC21__A10 PINMUX_PIN(PIN_PC21, 6, 2) +#define PIN_PC22 86 +#define PIN_PC22__GPIO PINMUX_PIN(PIN_PC22, 0, 0) +#define PIN_PC22__LCDDAT18 PINMUX_PIN(PIN_PC22, 1, 2) +#define PIN_PC22__GCRS PINMUX_PIN(PIN_PC22, 2, 1) +#define PIN_PC22__ISC_VSYNC PINMUX_PIN(PIN_PC22, 3, 1) +#define PIN_PC22__FLEXCOM3_IO4 PINMUX_PIN(PIN_PC22, 5, 2) +#define PIN_PC22__A11 PINMUX_PIN(PIN_PC22, 6, 2) +#define PIN_PC23 87 +#define PIN_PC23__GPIO PINMUX_PIN(PIN_PC23, 0, 0) +#define PIN_PC23__LCDDAT19 PINMUX_PIN(PIN_PC23, 1, 2) +#define PIN_PC23__GCOL PINMUX_PIN(PIN_PC23, 2, 1) +#define PIN_PC23__ISC_HSYNC PINMUX_PIN(PIN_PC23, 3, 1) +#define PIN_PC23__A12 PINMUX_PIN(PIN_PC23, 6, 2) +#define PIN_PC24 88 +#define PIN_PC24__GPIO PINMUX_PIN(PIN_PC24, 0, 0) +#define PIN_PC24__LCDDAT20 PINMUX_PIN(PIN_PC24, 1, 2) +#define PIN_PC24__GRX2 PINMUX_PIN(PIN_PC24, 2, 1) +#define PIN_PC24__ISC_MCK PINMUX_PIN(PIN_PC24, 3, 1) +#define PIN_PC24__A13 PINMUX_PIN(PIN_PC24, 6, 2) +#define PIN_PC25 89 +#define PIN_PC25__GPIO PINMUX_PIN(PIN_PC25, 0, 0) +#define PIN_PC25__LCDDAT21 PINMUX_PIN(PIN_PC25, 1, 2) +#define PIN_PC25__GRX3 PINMUX_PIN(PIN_PC25, 2, 1) +#define PIN_PC25__ISC_FIELD PINMUX_PIN(PIN_PC25, 3, 1) +#define PIN_PC25__A14 PINMUX_PIN(PIN_PC25, 6, 2) +#define PIN_PC26 90 +#define PIN_PC26__GPIO PINMUX_PIN(PIN_PC26, 0, 0) +#define PIN_PC26__LCDDAT22 PINMUX_PIN(PIN_PC26, 1, 2) +#define PIN_PC26__GTX2 PINMUX_PIN(PIN_PC26, 2, 1) +#define PIN_PC26__CANTX1 PINMUX_PIN(PIN_PC26, 4, 1) +#define PIN_PC26__A15 PINMUX_PIN(PIN_PC26, 6, 2) +#define PIN_PC27 91 +#define PIN_PC27__GPIO PINMUX_PIN(PIN_PC27, 0, 0) +#define PIN_PC27__LCDDAT23 PINMUX_PIN(PIN_PC27, 1, 2) +#define PIN_PC27__GTX3 PINMUX_PIN(PIN_PC27, 2, 1) +#define PIN_PC27__PCK1 PINMUX_PIN(PIN_PC27, 3, 2) +#define PIN_PC27__CANRX1 PINMUX_PIN(PIN_PC27, 4, 1) +#define PIN_PC27__TWD0 PINMUX_PIN(PIN_PC27, 5, 2) +#define PIN_PC27__A16 PINMUX_PIN(PIN_PC27, 6, 2) +#define PIN_PC28 92 +#define PIN_PC28__GPIO PINMUX_PIN(PIN_PC28, 0, 0) +#define PIN_PC28__LCDPWM PINMUX_PIN(PIN_PC28, 1, 2) +#define PIN_PC28__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC28, 2, 1) +#define PIN_PC28__PCK2 PINMUX_PIN(PIN_PC28, 3, 2) +#define PIN_PC28__TWCK0 PINMUX_PIN(PIN_PC28, 5, 2) +#define PIN_PC28__A17 PINMUX_PIN(PIN_PC28, 6, 2) +#define PIN_PC29 93 +#define PIN_PC29__GPIO PINMUX_PIN(PIN_PC29, 0, 0) +#define PIN_PC29__LCDDISP PINMUX_PIN(PIN_PC29, 1, 2) +#define PIN_PC29__FLEXCOM4_IO1 PINMUX_PIN(PIN_PC29, 2, 1) +#define PIN_PC29__A18 PINMUX_PIN(PIN_PC29, 6, 2) +#define PIN_PC30 94 +#define PIN_PC30__GPIO PINMUX_PIN(PIN_PC30, 0, 0) +#define PIN_PC30__LCDVSYNC PINMUX_PIN(PIN_PC30, 1, 2) +#define PIN_PC30__FLEXCOM4_IO2 PINMUX_PIN(PIN_PC30, 2, 1) +#define PIN_PC30__A19 PINMUX_PIN(PIN_PC30, 6, 2) +#define PIN_PC31 95 +#define PIN_PC31__GPIO PINMUX_PIN(PIN_PC31, 0, 0) +#define PIN_PC31__LCDHSYNC PINMUX_PIN(PIN_PC31, 1, 2) +#define PIN_PC31__FLEXCOM4_IO3 PINMUX_PIN(PIN_PC31, 2, 1) +#define PIN_PC31__URXD3 PINMUX_PIN(PIN_PC31, 3, 2) +#define PIN_PC31__A20 PINMUX_PIN(PIN_PC31, 6, 2) +#define PIN_PD0 96 +#define PIN_PD0__GPIO PINMUX_PIN(PIN_PD0, 0, 0) +#define PIN_PD0__LCDPCK PINMUX_PIN(PIN_PD0, 1, 2) +#define PIN_PD0__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD0, 2, 1) +#define PIN_PD0__UTXD3 PINMUX_PIN(PIN_PD0, 3, 2) +#define PIN_PD0__GTSUCOMP PINMUX_PIN(PIN_PD0, 4, 2) +#define PIN_PD0__A23 PINMUX_PIN(PIN_PD0, 6, 2) +#define PIN_PD1 97 +#define PIN_PD1__GPIO PINMUX_PIN(PIN_PD1, 0, 0) +#define PIN_PD1__LCDDEN PINMUX_PIN(PIN_PD1, 1, 2) +#define PIN_PD1__GRXCK PINMUX_PIN(PIN_PD1, 4, 2) +#define PIN_PD1__A24 PINMUX_PIN(PIN_PD1, 6, 2) +#define PIN_PD2 98 +#define PIN_PD2__GPIO PINMUX_PIN(PIN_PD2, 0, 0) +#define PIN_PD2__URXD1 PINMUX_PIN(PIN_PD2, 1, 1) +#define PIN_PD2__GTXER PINMUX_PIN(PIN_PD2, 4, 2) +#define PIN_PD2__ISC_MCK PINMUX_PIN(PIN_PD2, 5, 2) +#define PIN_PD2__A25 PINMUX_PIN(PIN_PD2, 6, 2) +#define PIN_PD3 99 +#define PIN_PD3__GPIO PINMUX_PIN(PIN_PD3, 0, 0) +#define PIN_PD3__UTXD1 PINMUX_PIN(PIN_PD3, 1, 1) +#define PIN_PD3__FIQ PINMUX_PIN(PIN_PD3, 2, 2) +#define PIN_PD3__GCRS PINMUX_PIN(PIN_PD3, 4, 2) +#define PIN_PD3__ISC_D11 PINMUX_PIN(PIN_PD3, 5, 2) +#define PIN_PD3__NWAIT PINMUX_PIN(PIN_PD3, 6, 2) +#define PIN_PD4 100 +#define PIN_PD4__GPIO PINMUX_PIN(PIN_PD4, 0, 0) +#define PIN_PD4__TWD1 PINMUX_PIN(PIN_PD4, 1, 2) +#define PIN_PD4__URXD2 PINMUX_PIN(PIN_PD4, 2, 1) +#define PIN_PD4__GCOL PINMUX_PIN(PIN_PD4, 4, 2) +#define PIN_PD4__ISC_D10 PINMUX_PIN(PIN_PD4, 5, 2) +#define PIN_PD4__NCS0 PINMUX_PIN(PIN_PD4, 6, 2) +#define PIN_PD5 101 +#define PIN_PD5__GPIO PINMUX_PIN(PIN_PD5, 0, 0) +#define PIN_PD5__TWCK1 PINMUX_PIN(PIN_PD5, 1, 2) +#define PIN_PD5__UTXD2 PINMUX_PIN(PIN_PD5, 2, 1) +#define PIN_PD5__GRX2 PINMUX_PIN(PIN_PD5, 4, 2) +#define PIN_PD5__ISC_D9 PINMUX_PIN(PIN_PD5, 5, 2) +#define PIN_PD5__NCS1 PINMUX_PIN(PIN_PD5, 6, 2) +#define PIN_PD6 102 +#define PIN_PD6__GPIO PINMUX_PIN(PIN_PD6, 0, 0) +#define PIN_PD6__TCK PINMUX_PIN(PIN_PD6, 1, 2) +#define PIN_PD6__PCK1 PINMUX_PIN(PIN_PD6, 2, 1) +#define PIN_PD6__GRX3 PINMUX_PIN(PIN_PD6, 4, 2) +#define PIN_PD6__ISC_D8 PINMUX_PIN(PIN_PD6, 5, 2) +#define PIN_PD6__NCS2 PINMUX_PIN(PIN_PD6, 6, 2) +#define PIN_PD7 103 +#define PIN_PD7__GPIO PINMUX_PIN(PIN_PD7, 0, 0) +#define PIN_PD7__TDI PINMUX_PIN(PIN_PD7, 1, 2) +#define PIN_PD7__UTMI_RXVAL PINMUX_PIN(PIN_PD7, 3, 1) +#define PIN_PD7__GTX2 PINMUX_PIN(PIN_PD7, 4, 2) +#define PIN_PD7__ISC_D0 PINMUX_PIN(PIN_PD7, 5, 2) +#define PIN_PD7__NWR1_NBS1 PINMUX_PIN(PIN_PD7, 6, 2) +#define PIN_PD8 104 +#define PIN_PD8__GPIO PINMUX_PIN(PIN_PD8, 0, 0) +#define PIN_PD8__TDO PINMUX_PIN(PIN_PD8, 1, 2) +#define PIN_PD8__UTMI_RXERR PINMUX_PIN(PIN_PD8, 3, 1) +#define PIN_PD8__GTX3 PINMUX_PIN(PIN_PD8, 4, 2) +#define PIN_PD8__ISC_D1 PINMUX_PIN(PIN_PD8, 5, 2) +#define PIN_PD8__NANDRDY PINMUX_PIN(PIN_PD8, 6, 2) +#define PIN_PD9 105 +#define PIN_PD9__GPIO PINMUX_PIN(PIN_PD9, 0, 0) +#define PIN_PD9__TMS PINMUX_PIN(PIN_PD9, 1, 2) +#define PIN_PD9__UTMI_RXACT PINMUX_PIN(PIN_PD9, 3, 1) +#define PIN_PD9__GTXCK PINMUX_PIN(PIN_PD9, 4, 2) +#define PIN_PD9__ISC_D2 PINMUX_PIN(PIN_PD9, 5, 2) +#define PIN_PD10 106 +#define PIN_PD10__GPIO PINMUX_PIN(PIN_PD10, 0, 0) +#define PIN_PD10__NTRST PINMUX_PIN(PIN_PD10, 1, 2) +#define PIN_PD10__UTMI_HDIS PINMUX_PIN(PIN_PD10, 3, 1) +#define PIN_PD10__GTXEN PINMUX_PIN(PIN_PD10, 4, 2) +#define PIN_PD10__ISC_D3 PINMUX_PIN(PIN_PD10, 5, 2) +#define PIN_PD11 107 +#define PIN_PD11__GPIO PINMUX_PIN(PIN_PD11, 0, 0) +#define PIN_PD11__TIOA1 PINMUX_PIN(PIN_PD11, 1, 3) +#define PIN_PD11__PCK2 PINMUX_PIN(PIN_PD11, 2, 2) +#define PIN_PD11__UTMI_LS0 PINMUX_PIN(PIN_PD11, 3, 1) +#define PIN_PD11__GRXDV PINMUX_PIN(PIN_PD11, 4, 2) +#define PIN_PD11__ISC_D4 PINMUX_PIN(PIN_PD11, 5, 2) +#define PIN_PD11__ISC_MCK PINMUX_PIN(PIN_PD11, 7, 4) +#define PIN_PD12 108 +#define PIN_PD12__GPIO PINMUX_PIN(PIN_PD12, 0, 0) +#define PIN_PD12__TIOB1 PINMUX_PIN(PIN_PD12, 1, 3) +#define PIN_PD12__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD12, 2, 2) +#define PIN_PD12__UTMI_LS1 PINMUX_PIN(PIN_PD12, 3, 1) +#define PIN_PD12__GRXER PINMUX_PIN(PIN_PD12, 4, 2) +#define PIN_PD12__ISC_D5 PINMUX_PIN(PIN_PD12, 5, 2) +#define PIN_PD12__ISC_D4 PINMUX_PIN(PIN_PD12, 6, 4) +#define PIN_PD13 109 +#define PIN_PD13__GPIO PINMUX_PIN(PIN_PD13, 0, 0) +#define PIN_PD13__TCLK1 PINMUX_PIN(PIN_PD13, 1, 3) +#define PIN_PD13__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD13, 2, 2) +#define PIN_PD13__UTMI_CDRPCSEL0 PINMUX_PIN(PIN_PD13, 3, 1) +#define PIN_PD13__GRX0 PINMUX_PIN(PIN_PD13, 4, 2) +#define PIN_PD13__ISC_D6 PINMUX_PIN(PIN_PD13, 5, 2) +#define PIN_PD13__ISC_D5 PINMUX_PIN(PIN_PD13, 6, 4) +#define PIN_PD14 110 +#define PIN_PD14__GPIO PINMUX_PIN(PIN_PD14, 0, 0) +#define PIN_PD14__TCK PINMUX_PIN(PIN_PD14, 1, 1) +#define PIN_PD14__FLEXCOM4_IO2 PINMUX_PIN(PIN_PD14, 2, 2) +#define PIN_PD14__UTMI_CDRPCSEL1 PINMUX_PIN(PIN_PD14, 3, 1) +#define PIN_PD14__GRX1 PINMUX_PIN(PIN_PD14, 4, 2) +#define PIN_PD14__ISC_D7 PINMUX_PIN(PIN_PD14, 5, 2) +#define PIN_PD14__ISC_D6 PINMUX_PIN(PIN_PD14, 6, 4) +#define PIN_PD15 111 +#define PIN_PD15__GPIO PINMUX_PIN(PIN_PD15, 0, 0) +#define PIN_PD15__TDI PINMUX_PIN(PIN_PD15, 1, 1) +#define PIN_PD15__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD15, 2, 2) +#define PIN_PD15__UTMI_CDRCPDIVEN PINMUX_PIN(PIN_PD15, 3, 1) +#define PIN_PD15__GTX0 PINMUX_PIN(PIN_PD15, 4, 2) +#define PIN_PD15__ISC_PCK PINMUX_PIN(PIN_PD15, 5, 2) +#define PIN_PD15__ISC_D7 PINMUX_PIN(PIN_PD15, 6, 4) +#define PIN_PD16 112 +#define PIN_PD16__GPIO PINMUX_PIN(PIN_PD16, 0, 0) +#define PIN_PD16__TDO PINMUX_PIN(PIN_PD16, 1, 1) +#define PIN_PD16__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD16, 2, 2) +#define PIN_PD16__UTMI_CDRBISTEN PINMUX_PIN(PIN_PD16, 3, 1) +#define PIN_PD16__GTX1 PINMUX_PIN(PIN_PD16, 4, 2) +#define PIN_PD16__ISC_VSYNC PINMUX_PIN(PIN_PD16, 5, 2) +#define PIN_PD16__ISC_D8 PINMUX_PIN(PIN_PD16, 6, 4) +#define PIN_PD17 113 +#define PIN_PD17__GPIO PINMUX_PIN(PIN_PD17, 0, 0) +#define PIN_PD17__TMS PINMUX_PIN(PIN_PD17, 1, 1) +#define PIN_PD17__UTMI_CDRCPSELDIV PINMUX_PIN(PIN_PD17, 3, 1) +#define PIN_PD17__GMDC PINMUX_PIN(PIN_PD17, 4, 2) +#define PIN_PD17__ISC_HSYNC PINMUX_PIN(PIN_PD17, 5, 2) +#define PIN_PD17__ISC_D9 PINMUX_PIN(PIN_PD17, 6, 4) +#define PIN_PD18 114 +#define PIN_PD18__GPIO PINMUX_PIN(PIN_PD18, 0, 0) +#define PIN_PD18__NTRST PINMUX_PIN(PIN_PD18, 1, 1) +#define PIN_PD18__GMDIO PINMUX_PIN(PIN_PD18, 4, 2) +#define PIN_PD18__ISC_FIELD PINMUX_PIN(PIN_PD18, 5, 2) +#define PIN_PD18__ISC_D10 PINMUX_PIN(PIN_PD18, 6, 4) +#define PIN_PD19 115 +#define PIN_PD19__GPIO PINMUX_PIN(PIN_PD19, 0, 0) +#define PIN_PD19__PCK0 PINMUX_PIN(PIN_PD19, 1, 1) +#define PIN_PD19__TWD1 PINMUX_PIN(PIN_PD19, 2, 3) +#define PIN_PD19__URXD2 PINMUX_PIN(PIN_PD19, 3, 3) +#define PIN_PD19__I2SC0_CK PINMUX_PIN(PIN_PD19, 5, 2) +#define PIN_PD19__ISC_D11 PINMUX_PIN(PIN_PD19, 6, 4) +#define PIN_PD20 116 +#define PIN_PD20__GPIO PINMUX_PIN(PIN_PD20, 0, 0) +#define PIN_PD20__TIOA2 PINMUX_PIN(PIN_PD20, 1, 3) +#define PIN_PD20__TWCK1 PINMUX_PIN(PIN_PD20, 2, 3) +#define PIN_PD20__UTXD2 PINMUX_PIN(PIN_PD20, 3, 3) +#define PIN_PD20__I2SC0_MCK PINMUX_PIN(PIN_PD20, 5, 2) +#define PIN_PD20__ISC_PCK PINMUX_PIN(PIN_PD20, 6, 4) +#define PIN_PD21 117 +#define PIN_PD21__GPIO PINMUX_PIN(PIN_PD21, 0, 0) +#define PIN_PD21__TIOB2 PINMUX_PIN(PIN_PD21, 1, 3) +#define PIN_PD21__TWD0 PINMUX_PIN(PIN_PD21, 2, 4) +#define PIN_PD21__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD21, 3, 3) +#define PIN_PD21__I2SC0_WS PINMUX_PIN(PIN_PD21, 5, 2) +#define PIN_PD21__ISC_VSYNC PINMUX_PIN(PIN_PD21, 6, 4) +#define PIN_PD22 118 +#define PIN_PD22__GPIO PINMUX_PIN(PIN_PD22, 0, 0) +#define PIN_PD22__TCLK2 PINMUX_PIN(PIN_PD22, 1, 3) +#define PIN_PD22__TWCK0 PINMUX_PIN(PIN_PD22, 2, 4) +#define PIN_PD22__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD22, 3, 3) +#define PIN_PD22__I2SC0_DI0 PINMUX_PIN(PIN_PD22, 5, 2) +#define PIN_PD22__ISC_HSYNC PINMUX_PIN(PIN_PD22, 6, 4) +#define PIN_PD23 119 +#define PIN_PD23__GPIO PINMUX_PIN(PIN_PD23, 0, 0) +#define PIN_PD23__URXD2 PINMUX_PIN(PIN_PD23, 1, 2) +#define PIN_PD23__FLEXCOM4_IO2 PINMUX_PIN(PIN_PD23, 3, 3) +#define PIN_PD23__I2SC0_DO0 PINMUX_PIN(PIN_PD23, 5, 2) +#define PIN_PD23__ISC_FIELD PINMUX_PIN(PIN_PD23, 6, 4) +#define PIN_PD24 120 +#define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0) +#define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD24, 1, 2) +#define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD24, 3, 3) +#define PIN_PD25 121 +#define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0) +#define PIN_PD25__SPI1_SPCK PINMUX_PIN(PIN_PD25, 1, 3) +#define PIN_PD25__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD25, 3, 3) +#define PIN_PD26 122 +#define PIN_PD26__GPIO PINMUX_PIN(PIN_PD26, 0, 0) +#define PIN_PD26__SPI1_MOSI PINMUX_PIN(PIN_PD26, 1, 3) +#define PIN_PD26__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD26, 3, 2) +#define PIN_PD27 123 +#define PIN_PD27__GPIO PINMUX_PIN(PIN_PD27, 0, 0) +#define PIN_PD27__SPI1_MISO PINMUX_PIN(PIN_PD27, 1, 3) +#define PIN_PD27__TCK PINMUX_PIN(PIN_PD27, 2, 3) +#define PIN_PD27__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD27, 3, 2) +#define PIN_PD28 124 +#define PIN_PD28__GPIO PINMUX_PIN(PIN_PD28, 0, 0) +#define PIN_PD28__SPI1_NPCS0 PINMUX_PIN(PIN_PD28, 1, 3) +#define PIN_PD28__TCI PINMUX_PIN(PIN_PD28, 2, 3) +#define PIN_PD28__FLEXCOM2_IO2 PINMUX_PIN(PIN_PD28, 3, 2) +#define PIN_PD29 125 +#define PIN_PD29__GPIO PINMUX_PIN(PIN_PD29, 0, 0) +#define PIN_PD29__SPI1_NPCS1 PINMUX_PIN(PIN_PD29, 1, 3) +#define PIN_PD29__TDO PINMUX_PIN(PIN_PD29, 2, 3) +#define PIN_PD29__FLEXCOM2_IO3 PINMUX_PIN(PIN_PD29, 3, 2) +#define PIN_PD29__TIOA3 PINMUX_PIN(PIN_PD29, 4, 3) +#define PIN_PD29__TWD0 PINMUX_PIN(PIN_PD29, 5, 3) +#define PIN_PD30 126 +#define PIN_PD30__GPIO PINMUX_PIN(PIN_PD30, 0, 0) +#define PIN_PD30__SPI1_NPCS2 PINMUX_PIN(PIN_PD30, 1, 3) +#define PIN_PD30__TMS PINMUX_PIN(PIN_PD30, 2, 3) +#define PIN_PD30__FLEXCOM2_IO4 PINMUX_PIN(PIN_PD30, 3, 2) +#define PIN_PD30__TIOB3 PINMUX_PIN(PIN_PD30, 4, 3) +#define PIN_PD30__TWCK0 PINMUX_PIN(PIN_PD30, 5, 3) +#define PIN_PD31 127 +#define PIN_PD31__GPIO PINMUX_PIN(PIN_PD31, 0, 0) +#define PIN_PD31__ADTRG PINMUX_PIN(PIN_PD31, 1, 1) +#define PIN_PD31__NTRST PINMUX_PIN(PIN_PD31, 2, 3) +#define PIN_PD31__IRQ PINMUX_PIN(PIN_PD31, 3, 4) +#define PIN_PD31__TCLK3 PINMUX_PIN(PIN_PD31, 4, 3) +#define PIN_PD31__PCK0 PINMUX_PIN(PIN_PD31, 5, 2) diff --git a/optee/optee_os/core/arch/arm/dts/sama5d2.dtsi b/optee/optee_os/core/arch/arm/dts/sama5d2.dtsi new file mode 100644 index 0000000..993a505 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/sama5d2.dtsi @@ -0,0 +1,1205 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * sama5d2.dtsi - Device Tree Include file for SAMA5D2 family SoC + * + * Copyright (C) 2015 Atmel, + * 2015 Ludovic Desroches + */ + +#include +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "Atmel SAMA5D2 family SoC"; + compatible = "atmel,sama5d2"; + interrupt-parent = <&aic>; + + aliases { + serial0 = &uart1; + serial1 = &uart3; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <0>; + next-level-cache = <&L2>; + clocks = <&pmc PMC_TYPE_CORE PMC_MCK_PRES>; + clock-names = "cpu"; + }; + }; + + pmu { + compatible = "arm,cortex-a5-pmu"; + interrupts = <2 IRQ_TYPE_LEVEL_HIGH 0>; + }; + + etb@740000 { + compatible = "arm,coresight-etb10", "arm,primecell"; + reg = <0x740000 0x1000>; + + clocks = <&pmc PMC_TYPE_CORE PMC_MCK>; + clock-names = "apb_pclk"; + + in-ports { + port { + etb_in: endpoint { + remote-endpoint = <&etm_out>; + }; + }; + }; + }; + + etm@73c000 { + compatible = "arm,coresight-etm3x", "arm,primecell"; + reg = <0x73c000 0x1000>; + + clocks = <&pmc PMC_TYPE_CORE PMC_MCK>; + clock-names = "apb_pclk"; + + out-ports { + port { + etm_out: endpoint { + remote-endpoint = <&etb_in>; + }; + }; + }; + }; + + memory@20000000 { + device_type = "memory"; + reg = <0x20000000 0x20000000>; + }; + + clocks { + slow_xtal: slow_xtal { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + main_xtal: main_xtal { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + }; + + ns_sram: sram@200000 { + compatible = "atmel,sama5d2-sram", "mmio-sram"; + reg = <0x00200000 0x20000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x00200000 0x20000>; + status = "disabled"; + secure-status = "okay"; + }; + + ahb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + nfc_sram: sram@100000 { + compatible = "mmio-sram"; + no-memory-wc; + reg = <0x00100000 0x2400>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x00100000 0x2400>; + + }; + + usb0: gadget@300000 { + compatible = "atmel,sama5d3-udc"; + reg = <0x00300000 0x100000 + 0xfc02c000 0x400>; + interrupts = <42 IRQ_TYPE_LEVEL_HIGH 2>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 42>, <&pmc PMC_TYPE_CORE PMC_UTMI>; + clock-names = "pclk", "hclk"; + assigned-clocks = <&pmc PMC_TYPE_CORE PMC_USBCK>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; + assigned-clock-rates = <48000000>; + status = "disabled"; + }; + + usb1: ohci@400000 { + compatible = "atmel,at91rm9200-ohci", "usb-ohci"; + reg = <0x00400000 0x100000>; + interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 41>, <&pmc PMC_TYPE_PERIPHERAL 41>, <&pmc PMC_TYPE_SYSTEM 6>; + clock-names = "ohci_clk", "hclk", "uhpck"; + assigned-clocks = <&pmc PMC_TYPE_CORE PMC_USBCK>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; + assigned-clock-rates = <48000000>; + status = "disabled"; + }; + + usb2: ehci@500000 { + compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; + reg = <0x00500000 0x100000>; + interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>; + clocks = <&pmc PMC_TYPE_CORE PMC_UTMI>, <&pmc PMC_TYPE_PERIPHERAL 41>; + clock-names = "usb_clk", "ehci_clk"; + assigned-clocks = <&pmc PMC_TYPE_CORE PMC_USBCK>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; + assigned-clock-rates = <48000000>; + status = "disabled"; + }; + + L2: cache-controller@a00000 { + compatible = "arm,pl310-cache"; + reg = <0x00a00000 0x1000>; + interrupts = <63 IRQ_TYPE_LEVEL_HIGH 4>; + cache-unified; + cache-level = <2>; + }; + + ebi: ebi@10000000 { + compatible = "atmel,sama5d3-ebi"; + #address-cells = <2>; + #size-cells = <1>; + atmel,smc = <&hsmc>; + reg = <0x10000000 0x10000000 + 0x60000000 0x30000000>; + ranges = <0x0 0x0 0x10000000 0x10000000 + 0x1 0x0 0x60000000 0x10000000 + 0x2 0x0 0x70000000 0x10000000 + 0x3 0x0 0x80000000 0x10000000>; + clocks = <&pmc PMC_TYPE_CORE PMC_MCK2>; + status = "disabled"; + + nand_controller: nand-controller { + compatible = "atmel,sama5d3-nand-controller"; + atmel,nfc-sram = <&nfc_sram>; + atmel,nfc-io = <&nfc_io>; + ecc-engine = <&pmecc>; + #address-cells = <2>; + #size-cells = <1>; + ranges; + status = "disabled"; + }; + }; + + sdmmc0: sdio-host@a0000000 { + compatible = "atmel,sama5d2-sdhci"; + reg = <0xa0000000 0x300>; + interrupts = <31 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 31>, <&pmc PMC_TYPE_GCK 31>, <&pmc PMC_TYPE_CORE PMC_MAIN>; + clock-names = "hclock", "multclk", "baseclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 31>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; + assigned-clock-rates = <480000000>; + status = "disabled"; + }; + + sdmmc1: sdio-host@b0000000 { + compatible = "atmel,sama5d2-sdhci"; + reg = <0xb0000000 0x300>; + interrupts = <32 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 32>, <&pmc PMC_TYPE_GCK 32>, <&pmc PMC_TYPE_CORE PMC_MAIN>; + clock-names = "hclock", "multclk", "baseclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 32>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; + assigned-clock-rates = <480000000>; + status = "disabled"; + }; + + nfc_io: nfc-io@c0000000 { + compatible = "atmel,sama5d3-nfc-io", "syscon"; + reg = <0xc0000000 0x8000000>; + }; + + apb { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + hlcdc: hlcdc@f0000000 { + compatible = "atmel,sama5d2-hlcdc"; + reg = <0xf0000000 0x2000>; + interrupts = <45 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 45>, <&pmc PMC_TYPE_SYSTEM 3>, <&clk32k>; + clock-names = "periph_clk","sys_clk", "slow_clk"; + status = "disabled"; + + hlcdc-display-controller { + compatible = "atmel,hlcdc-display-controller"; + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + }; + + hlcdc_pwm: hlcdc-pwm { + compatible = "atmel,hlcdc-pwm"; + #pwm-cells = <3>; + }; + }; + + isc: isc@f0008000 { + compatible = "atmel,sama5d2-isc"; + reg = <0xf0008000 0x4000>; + interrupts = <46 IRQ_TYPE_LEVEL_HIGH 5>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 46>, <&pmc PMC_TYPE_SYSTEM 18>, <&pmc PMC_TYPE_GCK 46>; + clock-names = "hclock", "iscck", "gck"; + #clock-cells = <0>; + clock-output-names = "isc-mck"; + status = "disabled"; + }; + + ramc0: ramc@f000c000 { + compatible = "atmel,sama5d3-ddramc"; + reg = <0xf000c000 0x200>; + clocks = <&pmc PMC_TYPE_SYSTEM 2>, <&pmc PMC_TYPE_PERIPHERAL 13>; + clock-names = "ddrck", "mpddr"; + }; + + dma0: dma-controller@f0010000 { + compatible = "atmel,sama5d4-dma"; + reg = <0xf0010000 0x1000>; + interrupts = <6 IRQ_TYPE_LEVEL_HIGH 0>; + #dma-cells = <1>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 6>; + clock-names = "dma_clk"; + }; + + /* Place dma1 here despite its address */ + dma1: dma-controller@f0004000 { + compatible = "atmel,sama5d4-dma"; + reg = <0xf0004000 0x1000>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH 0>; + #dma-cells = <1>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 7>; + clock-names = "dma_clk"; + }; + + pmc: pmc@f0014000 { + compatible = "atmel,sama5d2-pmc", "syscon"; + reg = <0xf0014000 0x160>; + interrupts = <74 IRQ_TYPE_LEVEL_HIGH 7>; + #clock-cells = <2>; + clocks = <&clk32k>, <&main_xtal>; + clock-names = "slow_clk", "main_xtal"; + status = "disabled"; + secure-status = "okay"; + }; + + qspi0: spi@f0020000 { + compatible = "atmel,sama5d2-qspi"; + reg = <0xf0020000 0x100>, <0xd0000000 0x08000000>; + reg-names = "qspi_base", "qspi_mmap"; + interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 52>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + qspi1: spi@f0024000 { + compatible = "atmel,sama5d2-qspi"; + reg = <0xf0024000 0x100>, <0xd8000000 0x08000000>; + reg-names = "qspi_base", "qspi_mmap"; + interrupts = <53 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 53>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + sha@f0028000 { + compatible = "atmel,at91sam9g46-sha"; + reg = <0xf0028000 0x100>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(30))>; + dma-names = "tx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 12>; + clock-names = "sha_clk"; + status = "okay"; + }; + + aes@f002c000 { + compatible = "atmel,at91sam9g46-aes"; + reg = <0xf002c000 0x100>; + interrupts = <9 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(26))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(27))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 9>; + clock-names = "aes_clk"; + status = "okay"; + }; + + spi0: spi@f8000000 { + compatible = "atmel,at91rm9200-spi"; + reg = <0xf8000000 0x100>; + interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(6))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(7))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 33>; + clock-names = "spi_clk"; + atmel,fifo-size = <16>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + ssc0: ssc@f8004000 { + compatible = "atmel,at91sam9g45-ssc"; + reg = <0xf8004000 0x4000>; + interrupts = <43 IRQ_TYPE_LEVEL_HIGH 4>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(21))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(22))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 43>; + clock-names = "pclk"; + status = "disabled"; + }; + + macb0: ethernet@f8008000 { + compatible = "atmel,sama5d2-gem"; + reg = <0xf8008000 0x1000>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH 3 /* Queue 0 */ + 66 IRQ_TYPE_LEVEL_HIGH 3 /* Queue 1 */ + 67 IRQ_TYPE_LEVEL_HIGH 3>; /* Queue 2 */ + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 5>, <&pmc PMC_TYPE_PERIPHERAL 5>; + clock-names = "hclk", "pclk"; + status = "disabled"; + }; + + tcb0: timer@f800c000 { + compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xf800c000 0x100>; + interrupts = <35 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 35>, <&pmc PMC_TYPE_GCK 35>, <&clk32k>; + clock-names = "t0_clk", "gclk", "slow_clk"; + }; + + tcb1: timer@f8010000 { + compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xf8010000 0x100>; + interrupts = <36 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 36>, <&pmc PMC_TYPE_GCK 36>, <&clk32k>; + clock-names = "t0_clk", "gclk", "slow_clk"; + status = "disabled"; + secure-status = "okay"; + }; + + hsmc: hsmc@f8014000 { + compatible = "atmel,sama5d2-smc", "syscon", "simple-mfd"; + reg = <0xf8014000 0x1000>; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH 6>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 17>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + pmecc: ecc-engine@f8014070 { + compatible = "atmel,sama5d2-pmecc"; + reg = <0xf8014070 0x490>, + <0xf8014500 0x100>; + }; + }; + + pdmic: pdmic@f8018000 { + compatible = "atmel,sama5d2-pdmic"; + reg = <0xf8018000 0x124>; + interrupts = <48 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) + | AT91_XDMAC_DT_PERID(50))>; + dma-names = "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 48>, <&pmc PMC_TYPE_GCK 48>; + clock-names = "pclk", "gclk"; + status = "disabled"; + }; + + uart0: serial@f801c000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xf801c000 0x100>; + interrupts = <24 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(35))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(36))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 24>; + clock-names = "usart"; + status = "disabled"; + }; + + uart1: serial@f8020000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xf8020000 0x100>; + interrupts = <25 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(37))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(38))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 25>; + clock-names = "usart"; + status = "disabled"; + }; + + uart2: serial@f8024000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xf8024000 0x100>; + interrupts = <26 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(39))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(40))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 26>; + clock-names = "usart"; + status = "disabled"; + }; + + i2c0: i2c@f8028000 { + compatible = "atmel,sama5d2-i2c"; + reg = <0xf8028000 0x100>; + interrupts = <29 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(0))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(1))>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 29>; + atmel,fifo-size = <16>; + status = "disabled"; + }; + + pwm0: pwm@f802c000 { + compatible = "atmel,sama5d2-pwm"; + reg = <0xf802c000 0x4000>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH 7>; + #pwm-cells = <3>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 38>; + status = "disabled"; + }; + + sfr: sfr@f8030000 { + compatible = "atmel,sama5d2-sfr", "syscon"; + reg = <0xf8030000 0x98>; + status = "disabled"; + secure-status = "okay"; + }; + + flx0: flexcom@f8034000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xf8034000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xf8034000 0x800>; + status = "disabled"; + + uart5: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; + clock-names = "usart"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(11))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(12))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <32>; + status = "disabled"; + }; + + spi2: spi@400 { + compatible = "atmel,at91rm9200-spi"; + reg = <0x400 0x200>; + interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; + clock-names = "spi_clk"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(11))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(12))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + + i2c2: i2c@600 { + compatible = "atmel,sama5d2-i2c"; + reg = <0x600 0x200>; + interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(11))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(12))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + }; + + flx1: flexcom@f8038000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xf8038000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 20>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xf8038000 0x800>; + status = "disabled"; + + uart6: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 20>; + clock-names = "usart"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(13))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(14))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <32>; + status = "disabled"; + }; + + spi3: spi@400 { + compatible = "atmel,at91rm9200-spi"; + reg = <0x400 0x200>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 20>; + clock-names = "spi_clk"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(13))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(14))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + + i2c3: i2c@600 { + compatible = "atmel,sama5d2-i2c"; + reg = <0x600 0x200>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 20>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(13))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(14))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + }; + + securam: sram@f8044000 { + compatible = "atmel,sama5d2-securam", "mmio-sram"; + reg = <0xf8044000 0x1420>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 51>; + #address-cells = <1>; + #size-cells = <1>; + no-memory-wc; + ranges = <0 0xf8044000 0x1420>; + status = "disabled"; + secure-status = "okay"; + }; + + reset_controller: rstc@f8048000 { + compatible = "atmel,sama5d3-rstc"; + reg = <0xf8048000 0x10>; + clocks = <&clk32k>; + status = "disabled"; + secure-status = "okay"; + }; + + shutdown_controller: shdwc@f8048010 { + compatible = "atmel,sama5d2-shdwc"; + reg = <0xf8048010 0x10>; + clocks = <&clk32k>; + #address-cells = <1>; + #size-cells = <0>; + atmel,wakeup-rtc-timer; + status = "disabled"; + secure-status = "okay"; + }; + + pit: timer@f8048030 { + compatible = "atmel,at91sam9260-pit"; + reg = <0xf8048030 0x10>; + interrupts = <3 IRQ_TYPE_LEVEL_HIGH 5>; + clocks = <&pmc PMC_TYPE_CORE PMC_MCK2>; + }; + + watchdog: watchdog@f8048040 { + compatible = "atmel,sama5d4-wdt"; + reg = <0xf8048040 0x10>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&clk32k>; + status = "disabled"; + secure-status = "okay"; + }; + + clk32k: sckc@f8048050 { + compatible = "atmel,sama5d4-sckc"; + reg = <0xf8048050 0x4>; + + clocks = <&slow_xtal>; + #clock-cells = <0>; + status = "disabled"; + secure-status = "okay"; + }; + + rtc: rtc@f80480b0 { + compatible = "atmel,sama5d2-rtc"; + reg = <0xf80480b0 0x30>; + interrupts = <74 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&clk32k>; + status = "disabled"; + secure-status = "okay"; + }; + + i2s0: i2s@f8050000 { + compatible = "atmel,sama5d2-i2s"; + reg = <0xf8050000 0x100>; + interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(31))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(32))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 54>, <&pmc PMC_TYPE_GCK 54>; + clock-names = "pclk", "gclk"; + assigned-clocks = <&pmc PMC_TYPE_CORE PMC_I2S0_MUX>; + assigned-clock-parents = <&pmc PMC_TYPE_GCK 54>; + status = "disabled"; + }; + + can0: can@f8054000 { + compatible = "bosch,m_can"; + reg = <0xf8054000 0x4000>, <0x210000 0x1c00>; + reg-names = "m_can", "message_ram"; + interrupts = <56 IRQ_TYPE_LEVEL_HIGH 7>, + <64 IRQ_TYPE_LEVEL_HIGH 7>; + interrupt-names = "int0", "int1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 56>, <&pmc PMC_TYPE_GCK 56>; + clock-names = "hclk", "cclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 56>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; + assigned-clock-rates = <40000000>; + bosch,mram-cfg = <0x0 0 0 64 0 0 32 32>; + status = "disabled"; + }; + + spi1: spi@fc000000 { + compatible = "atmel,at91rm9200-spi"; + reg = <0xfc000000 0x100>; + interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(8))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(9))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 34>; + clock-names = "spi_clk"; + atmel,fifo-size = <16>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + uart3: serial@fc008000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfc008000 0x100>; + interrupts = <27 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma1 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(41))>, + <&dma1 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(42))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 27>; + clock-names = "usart"; + status = "disabled"; + }; + + uart4: serial@fc00c000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xfc00c000 0x100>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(43))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(44))>; + dma-names = "tx", "rx"; + interrupts = <28 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 28>; + clock-names = "usart"; + status = "disabled"; + }; + + flx2: flexcom@fc010000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xfc010000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xfc010000 0x800>; + status = "disabled"; + + uart7: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = <21 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; + clock-names = "usart"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(15))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(16))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <32>; + status = "disabled"; + }; + + spi4: spi@400 { + compatible = "atmel,at91rm9200-spi"; + reg = <0x400 0x200>; + interrupts = <21 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; + clock-names = "spi_clk"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(15))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(16))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + + i2c4: i2c@600 { + compatible = "atmel,sama5d2-i2c"; + reg = <0x600 0x200>; + interrupts = <21 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(15))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(16))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + }; + + flx3: flexcom@fc014000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xfc014000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xfc014000 0x800>; + status = "disabled"; + + uart8: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; + clock-names = "usart"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(17))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(18))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <32>; + status = "disabled"; + }; + + spi5: spi@400 { + compatible = "atmel,at91rm9200-spi"; + reg = <0x400 0x200>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; + clock-names = "spi_clk"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(17))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(18))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + + i2c5: i2c@600 { + compatible = "atmel,sama5d2-i2c"; + reg = <0x600 0x200>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(17))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(18))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + + }; + + flx4: flexcom@fc018000 { + compatible = "atmel,sama5d2-flexcom"; + reg = <0xfc018000 0x200>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0xfc018000 0x800>; + status = "disabled"; + + uart9: serial@200 { + compatible = "atmel,at91sam9260-usart"; + reg = <0x200 0x200>; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; + clock-names = "usart"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(19))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(20))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <32>; + status = "disabled"; + }; + + spi6: spi@400 { + compatible = "atmel,at91rm9200-spi"; + reg = <0x400 0x200>; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; + clock-names = "spi_clk"; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(19))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(20))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + + i2c6: i2c@600 { + compatible = "atmel,sama5d2-i2c"; + reg = <0x600 0x200>; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH 7>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(19))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | + AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(20))>; + dma-names = "tx", "rx"; + atmel,fifo-size = <16>; + status = "disabled"; + }; + }; + + trng@fc01c000 { + compatible = "atmel,at91sam9g45-trng"; + reg = <0xfc01c000 0x100>; + interrupts = <47 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 47>; + status = "disabled"; + secure-status = "okay"; + }; + + aic: interrupt-controller@fc020000 { + #interrupt-cells = <3>; + compatible = "atmel,sama5d2-aic"; + interrupt-controller; + reg = <0xfc020000 0x200>; + atmel,external-irqs = <49>; + }; + + saic: interrupt-controller@f803c000 { + #interrupt-cells = <3>; + compatible = "atmel,sama5d2-saic"; + interrupt-controller; + reg = <0xf803c000 0x200>; + atmel,external-irqs = <49>; + status = "disabled"; + secure-status = "okay"; + }; + + i2c1: i2c@fc028000 { + compatible = "atmel,sama5d2-i2c"; + reg = <0xfc028000 0x100>; + interrupts = <30 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(2))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(3))>; + dma-names = "tx", "rx"; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 30>; + atmel,fifo-size = <16>; + status = "disabled"; + }; + + adc: adc@fc030000 { + compatible = "atmel,sama5d2-adc"; + reg = <0xfc030000 0x100>; + interrupts = <40 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 40>; + clock-names = "adc_clk"; + dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(25))>; + dma-names = "rx"; + atmel,min-sample-rate-hz = <200000>; + atmel,max-sample-rate-hz = <20000000>; + atmel,startup-time-ms = <4>; + atmel,trigger-edge-type = ; + #io-channel-cells = <1>; + status = "disabled"; + }; + + resistive_touch: resistive-touch { + compatible = "resistive-adc-touch"; + io-channels = <&adc AT91_SAMA5D2_ADC_X_CHANNEL>, + <&adc AT91_SAMA5D2_ADC_Y_CHANNEL>, + <&adc AT91_SAMA5D2_ADC_P_CHANNEL>; + io-channel-names = "x", "y", "pressure"; + touchscreen-min-pressure = <50000>; + status = "disabled"; + }; + + pioA: pinctrl@fc039000 { + compatible = "atmel,sama5d2-pinctrl"; + reg = <0xfc039000 0x600>; + interrupts = <18 IRQ_TYPE_LEVEL_HIGH 7>, + <68 IRQ_TYPE_LEVEL_HIGH 7>, + <69 IRQ_TYPE_LEVEL_HIGH 7>, + <70 IRQ_TYPE_LEVEL_HIGH 7>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 18>; + }; + + pioBU: secumod@fc040000 { + compatible = "atmel,sama5d2-secumod", "syscon"; + reg = <0xfc040000 0x100>; + + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + secure-status = "okay"; + }; + + tdes@fc044000 { + compatible = "atmel,at91sam9g46-tdes"; + reg = <0xfc044000 0x100>; + interrupts = <11 IRQ_TYPE_LEVEL_HIGH 0>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(28))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(29))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 11>; + clock-names = "tdes_clk"; + status = "okay"; + }; + + classd: classd@fc048000 { + compatible = "atmel,sama5d2-classd"; + reg = <0xfc048000 0x100>; + interrupts = <59 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(47))>; + dma-names = "tx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 59>, <&pmc PMC_TYPE_GCK 59>; + clock-names = "pclk", "gclk"; + status = "disabled"; + }; + + i2s1: i2s@fc04c000 { + compatible = "atmel,sama5d2-i2s"; + reg = <0xfc04c000 0x100>; + interrupts = <55 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(33))>, + <&dma0 + (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(34))>; + dma-names = "tx", "rx"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 55>, <&pmc PMC_TYPE_GCK 55>; + clock-names = "pclk", "gclk"; + assigned-clocks = <&pmc PMC_TYPE_CORE PMC_I2S1_MUX>; + assigned-parrents = <&pmc PMC_TYPE_GCK 55>; + status = "disabled"; + }; + + can1: can@fc050000 { + compatible = "bosch,m_can"; + reg = <0xfc050000 0x4000>, <0x210000 0x3800>; + reg-names = "m_can", "message_ram"; + interrupts = <57 IRQ_TYPE_LEVEL_HIGH 7>, + <65 IRQ_TYPE_LEVEL_HIGH 7>; + interrupt-names = "int0", "int1"; + clocks = <&pmc PMC_TYPE_PERIPHERAL 57>, <&pmc PMC_TYPE_GCK 57>; + clock-names = "hclk", "cclk"; + assigned-clocks = <&pmc PMC_TYPE_GCK 57>; + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; + assigned-clock-rates = <40000000>; + bosch,mram-cfg = <0x1c00 0 0 64 0 0 32 32>; + status = "disabled"; + }; + + sfrbu: sfr@fc05c000 { + compatible = "atmel,sama5d2-sfrbu", "syscon"; + reg = <0xfc05c000 0x20>; + }; + + chipid@fc069000 { + compatible = "atmel,sama5d2-chipid"; + reg = <0xfc069000 0x8>; + }; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi new file mode 100644 index 0000000..50bf308 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp13-pinctrl.dtsi @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019-2022 - All Rights Reserved + * Author: Alexandre Torgue + */ +#include + +&pinctrl { + i2c4_pins_a: i2c4-0 { + pins { + pinmux = , /* I2C4_SCL */ + ; /* I2C4_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + uart4_pins_a: uart4-0 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + usart1_pins_a: usart1-0 { + pins1 { + pinmux = , /* USART1_TX */ + ; /* USART1_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART1_RX */ + ; /* USART1_CTS_NSS */ + bias-pull-up; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi new file mode 100644 index 0000000..5255bec --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp131.dtsi @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <0>; + }; + }; + + intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, + <0xa0022000 0x2000>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + + clk_i2sin: clk-i2sin { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <19000000>; + }; + + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges; + + usart3: serial@4000f000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000f000 0x400>; + interrupts = ; + status = "disabled"; + }; + + uart4: serial@40010000 { + compatible = "st,stm32h7-uart"; + reg = <0x40010000 0x400>; + interrupts = ; + clocks = <&rcc UART4_K>; + status = "disabled"; + }; + + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; + interrupts = ; + status = "disabled"; + }; + + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; + interrupts = ; + status = "disabled"; + }; + + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; + interrupts = ; + status = "disabled"; + }; + + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; + interrupts = ; + status = "disabled"; + }; + + usart1: serial@4c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x4c000000 0x400>; + interrupts = ; + status = "disabled"; + }; + + usart2: serial@4c001000 { + compatible = "st,stm32h7-uart"; + reg = <0x4c001000 0x400>; + interrupts = ; + status = "disabled"; + }; + + i2c3: i2c@4c004000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c004000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x4>; + i2c-analog-filter; + status = "disabled"; + }; + + i2c4: i2c@4c005000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c005000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x8>; + i2c-analog-filter; + status = "disabled"; + }; + + i2c5: i2c@4c006000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c006000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x10>; + i2c-analog-filter; + status = "disabled"; + }; + + rcc: rcc@50000000 { + compatible = "st,stm32mp13-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <1>; + #reset-cells = <1>; + clocks = <&clk_hse>, <&clk_hsi>, <&clk_lse>, <&clk_lsi>, <&clk_csi>, <&clk_i2sin>; + clock-names = "clk-hse", "clk-hsi", "clk-lse", "clk-lsi", "clk-csi", "clk-i2sin"; + interrupts = ; + secure-interrupts = ; + secure-interrupt-names = "wakeup"; + }; + + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + }; + + rng: rng@54004000 { + compatible = "st,stm32mp13-rng"; + reg = <0x54004000 0x400>; + clocks = <&rcc RNG1_K>; + status = "disabled"; + }; + + bsec: efuse@5c005000 { + compatible = "st,stm32mp13-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + + cfg0_otp: cfg0_otp@0 { + reg = <0x0 0x2>; + }; + part_number_otp: part_number_otp@4 { + reg = <0x4 0x2>; + }; + monotonic_otp: monotonic_otp@10 { + reg = <0x10 0x4>; + }; + nand_otp: cfg9_otp@24 { + reg = <0x24 0x4>; + }; + uid_otp: uid_otp@34 { + reg = <0x34 0xc>; + }; + hw2_otp: hw2_otp@48 { + reg = <0x48 0x4>; + }; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; + pkh_otp: pkh_otp@60 { + reg = <0x60 0x20>; + }; + ethernet_mac1_address: mac1@e4 { + reg = <0xe4 0xc>; + st,non-secure-otp; + }; + oem_enc_key: oem_enc_key@170 { + reg = <0x170 0x10>; + }; + }; + + tzc400: tzc@5c006000 { + compatible = "st,stm32mp1-tzc"; + reg = <0x5c006000 0x1000>; + interrupts = ; + st,mem-map = <0xc0000000 0x40000000>; + clocks = <&rcc TZC>; + }; + + etzpc: etzpc@5c007000 { + compatible = "st,stm32-etzpc"; + reg = <0x5C007000 0x400>; + }; + + stgen: stgen@5c008000 { + compatible = "st,stm32-stgen"; + reg = <0x5C008000 0x1000>; + }; + + pinctrl: pin-controller@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp135-pinctrl"; + ranges = <0 0x50002000 0x8400>; + pins-are-numbered; + + gpioa: gpio@50002000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOA>; + reg = <0x0 0x400>; + st,bank-name = "GPIOA"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOB>; + reg = <0x1000 0x400>; + st,bank-name = "GPIOB"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOC>; + reg = <0x2000 0x400>; + st,bank-name = "GPIOC"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOD>; + reg = <0x3000 0x400>; + st,bank-name = "GPIOD"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOE>; + reg = <0x4000 0x400>; + st,bank-name = "GPIOE"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOF>; + reg = <0x5000 0x400>; + st,bank-name = "GPIOF"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOG>; + reg = <0x6000 0x400>; + st,bank-name = "GPIOG"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOH>; + reg = <0x7000 0x400>; + st,bank-name = "GPIOH"; + ngpios = <15>; + gpio-ranges = <&pinctrl 0 112 15>; + }; + + gpioi: gpio@5000a000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&rcc GPIOI>; + reg = <0x8000 0x400>; + st,bank-name = "GPIOI"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 128 8>; + }; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp133.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp133.dtsi new file mode 100644 index 0000000..d69614e --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp133.dtsi @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp131.dtsi" diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi new file mode 100644 index 0000000..6f456f4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp135.dtsi @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp133.dtsi" diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts b/optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts new file mode 100644 index 0000000..88b5742 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp135f-dk.dts @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include +#include "stm32mp135.dtsi" +#include "stm32mp13xf.dtsi" +#include "stm32mp13-pinctrl.dtsi" + +/ { + model = "STMicroelectronics STM32MP135F-DK Discovery Board"; + compatible = "st,stm32mp135f-dk", "st,stm32mp135"; + + aliases { + serial0 = &uart4; + serial1 = &usart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + optee_framebuffer: optee-framebuffer@dd000000 { + /* Secure framebuffer memory */ + reg = <0xdd000000 0x1000000>; + no-map; + }; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + v3v3_ao: v3v3_ao { + compatible = "regulator-fixed"; + regulator-name = "v3v3_ao"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; +}; + +&bsec { + board_id: board_id@f0 { + reg = <0xf0 0x4>; + st,non-secure-otp; + }; +}; + +&oem_enc_key { + st,non-secure-otp-provisioning; +}; + +&rcc { + compatible = "st,stm32mp13-rcc", "syscon"; + + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MLAHBS_PLL3 + CLK_RTC_LSE + CLK_MCO1_HSE + CLK_MCO2_DISABLED + CLK_CKPER_HSE + CLK_ETH1_PLL4P + CLK_ETH2_PLL4P + CLK_SDMMC1_PLL4P + CLK_SDMMC2_PLL4P + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_I2C4_HSI + CLK_USBO_USBPHY + CLK_ADC2_CKPER + CLK_I2C12_HSI + CLK_UART1_HSI + CLK_UART2_HSI + CLK_UART35_HSI + CLK_UART4_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SAES_AXI + CLK_DCMIPP_PLL2Q + CLK_LPTIM3_PCLK3 + CLK_RNG1_PLL4R + >; + + st,clkdiv = < + DIV(DIV_MPU, 1) + DIV(DIV_AXI, 0) + DIV(DIV_MLAHB, 0) + DIV(DIV_APB1, 1) + DIV(DIV_APB2, 1) + DIV(DIV_APB3, 1) + DIV(DIV_APB4, 1) + DIV(DIV_APB5, 2) + DIV(DIV_APB6, 1) + DIV(DIV_RTC, 0) + DIV(DIV_MCO1, 0) + DIV(DIV_MCO2, 0) + >; + + st,pll_vco { + pll1_vco_2000Mhz: pll1-vco-2000Mhz { + src = < CLK_PLL12_HSE >; + divmn = < 1 82 >; + frac = < 0xAAA >; + }; + + pll1_vco_1300Mhz: pll1-vco-1300Mhz { + src = < CLK_PLL12_HSE >; + divmn = < 2 80 >; + frac = < 0x800 >; + }; + + pll2_vco_1066Mhz: pll2-vco-1066Mhz { + src = < CLK_PLL12_HSE >; + divmn = < 2 65 >; + frac = < 0x1400 >; + }; + + pll3_vco_417_8Mhz: pll3-vco-417_8Mhz { + src = < CLK_PLL3_HSE >; + divmn = < 1 33 >; + frac = < 0x1a04 >; + }; + + pll4_vco_600Mhz: pll4-vco-600Mhz { + src = < CLK_PLL4_HSE >; + divmn = < 1 49 >; + }; + }; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + + st,pll = < &pll1_cfg1 >; + + pll1_cfg1: pll1_cfg1 { + st,pll_vco = < &pll1_vco_1300Mhz >; + st,pll_div_pqr = < 0 1 1 >; + }; + + pll1_cfg2: pll1_cfg2 { + st,pll_vco = < &pll1_vco_2000Mhz >; + st,pll_div_pqr = < 0 1 1 >; + }; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 266, R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + + st,pll = < &pll2_cfg1 >; + + pll2_cfg1: pll2_cfg1 { + st,pll_vco = < &pll2_vco_1066Mhz >; + st,pll_div_pqr = < 1 1 0 >; + }; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + + st,pll = < &pll3_cfg1 >; + + pll3_cfg1: pll3_cfg1 { + st,pll_vco = < &pll3_vco_417_8Mhz >; + st,pll_div_pqr = < 1 16 36 >; + }; + }; + + /* VCO = 600.0 MHz => P = 50, Q = 10, R = 50 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + st,pll = < &pll4_cfg1 >; + + pll4_cfg1: pll4_cfg1 { + st,pll_vco = < &pll4_vco_600Mhz >; + st,pll_div_pqr = < 11 59 11 >; + }; + }; + + st,clk_opp { + /* CK_MPU clock config for MP13 */ + st,ck_mpu { + + cfg_1 { + hz = < 1000000000 >; + st,clksrc = < CLK_MPU_PLL1P >; + st,pll = < &pll1_cfg2 >; + }; + + cfg_2 { + hz = < 650000000 >; + st,clksrc = < CLK_MPU_PLL1P >; + st,pll = < &pll1_cfg1 >; + }; + }; + }; +}; + +&rng { + status = "okay"; + clock-error-detect; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; + +&usart1 { + pinctrl-names = "default"; + pinctrl-0 = <&usart1_pins_a>; + uart-has-rtscts; + status = "disabled"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi new file mode 100644 index 0000000..23ff3d5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp13xc.dtsi @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { + soc { + cryp: cryp@54002000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54002000 0x400>; + interrupts = ; + status = "disabled"; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi new file mode 100644 index 0000000..23ff3d5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp13xf.dtsi @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { + soc { + cryp: cryp@54002000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54002000 0x400>; + interrupts = ; + status = "disabled"; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15-pinctrl.dtsi new file mode 100644 index 0000000..6052243 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15-pinctrl.dtsi @@ -0,0 +1,2279 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +#include + +&pinctrl { + adc1_in6_pins_a: adc1-in6-0 { + pins { + pinmux = ; + }; + }; + + adc12_ain_pins_a: adc12-ain-0 { + pins { + pinmux = , /* ADC1 in13 */ + , /* ADC1 in6 */ + , /* ADC2 in2 */ + ; /* ADC2 in6 */ + }; + }; + + adc12_ain_pins_b: adc12-ain-1 { + pins { + pinmux = , /* ADC1 in6 */ + ; /* ADC2 in2 */ + }; + }; + + adc12_usb_cc_pins_a: adc12-usb-cc-pins-0 { + pins { + pinmux = , /* ADC12 in18 */ + ; /* ADC12 in19 */ + }; + }; + + cec_pins_a: cec-0 { + pins { + pinmux = ; + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + cec_sleep_pins_a: cec-sleep-0 { + pins { + pinmux = ; /* HDMI_CEC */ + }; + }; + + cec_pins_b: cec-1 { + pins { + pinmux = ; + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + cec_sleep_pins_b: cec-sleep-1 { + pins { + pinmux = ; /* HDMI_CEC */ + }; + }; + + dac_ch1_pins_a: dac-ch1-0 { + pins { + pinmux = ; + }; + }; + + dac_ch2_pins_a: dac-ch2-0 { + pins { + pinmux = ; + }; + }; + + dcmi_pins_a: dcmi-0 { + pins { + pinmux = ,/* DCMI_HSYNC */ + ,/* DCMI_VSYNC */ + ,/* DCMI_PIXCLK */ + ,/* DCMI_D0 */ + ,/* DCMI_D1 */ + ,/* DCMI_D2 */ + ,/* DCMI_D3 */ + ,/* DCMI_D4 */ + ,/* DCMI_D5 */ + ,/* DCMI_D6 */ + ,/* DCMI_D7 */ + ,/* DCMI_D8 */ + ,/* DCMI_D9 */ + ,/* DCMI_D10 */ + ;/* DCMI_D11 */ + bias-disable; + }; + }; + + dcmi_sleep_pins_a: dcmi-sleep-0 { + pins { + pinmux = ,/* DCMI_HSYNC */ + ,/* DCMI_VSYNC */ + ,/* DCMI_PIXCLK */ + ,/* DCMI_D0 */ + ,/* DCMI_D1 */ + ,/* DCMI_D2 */ + ,/* DCMI_D3 */ + ,/* DCMI_D4 */ + ,/* DCMI_D5 */ + ,/* DCMI_D6 */ + ,/* DCMI_D7 */ + ,/* DCMI_D8 */ + ,/* DCMI_D9 */ + ,/* DCMI_D10 */ + ;/* DCMI_D11 */ + }; + }; + + dcmi_pins_b: dcmi-1 { + pins { + pinmux = ,/* DCMI_HSYNC */ + ,/* DCMI_VSYNC */ + ,/* DCMI_PIXCLK */ + ,/* DCMI_D0 */ + ,/* DCMI_D1 */ + ,/* DCMI_D2 */ + ,/* DCMI_D3 */ + ,/* DCMI_D4 */ + ,/* DCMI_D5 */ + ,/* DCMI_D6 */ + ;/* DCMI_D7 */ + bias-disable; + }; + }; + + dcmi_sleep_pins_b: dcmi-sleep-1 { + pins { + pinmux = ,/* DCMI_HSYNC */ + ,/* DCMI_VSYNC */ + ,/* DCMI_PIXCLK */ + ,/* DCMI_D0 */ + ,/* DCMI_D1 */ + ,/* DCMI_D2 */ + ,/* DCMI_D3 */ + ,/* DCMI_D4 */ + ,/* DCMI_D5 */ + ,/* DCMI_D6 */ + ;/* DCMI_D7 */ + }; + }; + + ethernet0_rgmii_pins_a: rgmii-0 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ + , /* ETH_RGMII_TXD0 */ + , /* ETH_RGMII_TXD1 */ + , /* ETH_RGMII_TXD2 */ + , /* ETH_RGMII_TXD3 */ + , /* ETH_RGMII_TX_CTL */ + ; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = ; /* ETH_MDIO */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = , /* ETH_RGMII_RXD0 */ + , /* ETH_RGMII_RXD1 */ + , /* ETH_RGMII_RXD2 */ + , /* ETH_RGMII_RXD3 */ + , /* ETH_RGMII_RX_CLK */ + ; /* ETH_RGMII_RX_CTL */ + bias-disable; + }; + }; + + ethernet0_rgmii_sleep_pins_a: rgmii-sleep-0 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ + , /* ETH_RGMII_TXD0 */ + , /* ETH_RGMII_TXD1 */ + , /* ETH_RGMII_TXD2 */ + , /* ETH_RGMII_TXD3 */ + , /* ETH_RGMII_TX_CTL */ + , /* ETH_MDIO */ + , /* ETH_MDC */ + , /* ETH_RGMII_RXD0 */ + , /* ETH_RGMII_RXD1 */ + , /* ETH_RGMII_RXD2 */ + , /* ETH_RGMII_RXD3 */ + , /* ETH_RGMII_RX_CLK */ + ; /* ETH_RGMII_RX_CTL */ + }; + }; + + ethernet0_rgmii_pins_b: rgmii-1 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ + , /* ETH_RGMII_TXD0 */ + , /* ETH_RGMII_TXD1 */ + , /* ETH_RGMII_TXD2 */ + , /* ETH_RGMII_TXD3 */ + , /* ETH_RGMII_TX_CTL */ + ; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = ; /* ETH_MDIO */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = , /* ETH_RGMII_RXD0 */ + , /* ETH_RGMII_RXD1 */ + , /* ETH_RGMII_RXD2 */ + , /* ETH_RGMII_RXD3 */ + , /* ETH_RGMII_RX_CLK */ + ; /* ETH_RGMII_RX_CTL */ + bias-disable; + }; + }; + + ethernet0_rgmii_sleep_pins_b: rgmii-sleep-1 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ + , /* ETH_RGMII_TXD0 */ + , /* ETH_RGMII_TXD1 */ + , /* ETH_RGMII_TXD2 */ + , /* ETH_RGMII_TXD3 */ + , /* ETH_RGMII_TX_CTL */ + , /* ETH_MDC */ + , /* ETH_MDIO */ + , /* ETH_RGMII_RXD0 */ + , /* ETH_RGMII_RXD1 */ + , /* ETH_RGMII_RXD2 */ + , /* ETH_RGMII_RXD3 */ + , /* ETH_RGMII_RX_CLK */ + ; /* ETH_RGMII_RX_CTL */ + }; + }; + + ethernet0_rgmii_pins_c: rgmii-2 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ + , /* ETH_RGMII_TXD0 */ + , /* ETH_RGMII_TXD1 */ + , /* ETH_RGMII_TXD2 */ + , /* ETH_RGMII_TXD3 */ + , /* ETH_RGMII_TX_CTL */ + ; /* ETH_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = ; /* ETH_MDIO */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = , /* ETH_RGMII_RXD0 */ + , /* ETH_RGMII_RXD1 */ + , /* ETH_RGMII_RXD2 */ + , /* ETH_RGMII_RXD3 */ + , /* ETH_RGMII_RX_CLK */ + ; /* ETH_RGMII_RX_CTL */ + bias-disable; + }; + }; + + ethernet0_rgmii_sleep_pins_c: rgmii-sleep-2 { + pins1 { + pinmux = , /* ETH_RGMII_CLK125 */ + , /* ETH_RGMII_GTX_CLK */ + , /* ETH_RGMII_TXD0 */ + , /* ETH_RGMII_TXD1 */ + , /* ETH_RGMII_TXD2 */ + , /* ETH_RGMII_TXD3 */ + , /* ETH_RGMII_TX_CTL */ + , /* ETH_MDIO */ + , /* ETH_MDC */ + , /* ETH_RGMII_RXD0 */ + , /* ETH_RGMII_RXD1 */ + , /* ETH_RGMII_RXD2 */ + , /* ETH_RGMII_RXD3 */ + , /* ETH_RGMII_RX_CLK */ + ; /* ETH_RGMII_RX_CTL */ + }; + }; + + ethernet0_rmii_pins_a: rmii-0 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ + , /* ETH1_RMII_TX_EN */ + , /* ETH1_RMII_REF_CLK */ + , /* ETH1_MDIO */ + ; /* ETH1_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = , /* ETH1_RMII_RXD0 */ + , /* ETH1_RMII_RXD1 */ + ; /* ETH1_RMII_CRS_DV */ + bias-disable; + }; + }; + + ethernet0_rmii_sleep_pins_a: rmii-sleep-0 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ + , /* ETH1_RMII_TX_EN */ + , /* ETH1_MDIO */ + , /* ETH1_MDC */ + , /* ETH1_RMII_RXD0 */ + , /* ETH1_RMII_RXD1 */ + , /* ETH1_RMII_REF_CLK */ + ; /* ETH1_RMII_CRS_DV */ + }; + }; + + ethernet0_rmii_pins_b: rmii-1 { + pins1 { + pinmux = , /* ETH1_CLK */ + , /* ETH1_MDC */ + , /* ETH1_TXD0 */ + ; /* ETH1_TXD1 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* ETH1_MDIO */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = , /* ETH1_CRS_DV */ + , /* ETH1_RXD0 */ + ; /* ETH1_RXD1 */ + bias-disable; + }; + pins4 { + pinmux = ; /* ETH1_TX_EN */ + }; + }; + + ethernet0_rmii_sleep_pins_b: rmii-sleep-1 { + pins1 { + pinmux = , /* ETH1_MDIO */ + , /* ETH1_CRS_DV */ + , /* ETH1_CLK */ + , /* ETH1_TX_EN */ + , /* ETH1_MDC */ + , /* ETH1_RXD0 */ + , /* ETH1_RXD1 */ + , /* ETH1_TXD0 */ + ; /* ETH1_TXD1 */ + }; + }; + + ethernet0_rmii_pins_c: rmii-2 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ + , /* ETH1_RMII_TX_EN */ + , /* ETH1_RMII_REF_CLK */ + , /* ETH1_MDIO */ + ; /* ETH1_MDC */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + pins2 { + pinmux = , /* ETH1_RMII_RXD0 */ + , /* ETH1_RMII_RXD1 */ + ; /* ETH1_RMII_CRS_DV */ + bias-disable; + }; + }; + + ethernet0_rmii_sleep_pins_c: rmii-sleep-2 { + pins1 { + pinmux = , /* ETH1_RMII_TXD0 */ + , /* ETH1_RMII_TXD1 */ + , /* ETH1_RMII_TX_EN */ + , /* ETH1_MDIO */ + , /* ETH1_MDC */ + , /* ETH1_RMII_RXD0 */ + , /* ETH1_RMII_RXD1 */ + , /* ETH1_RMII_REF_CLK */ + ; /* ETH1_RMII_CRS_DV */ + }; + }; + + fmc_pins_a: fmc-0 { + pins1 { + pinmux = , /* FMC_NOE */ + , /* FMC_NWE */ + , /* FMC_A16_FMC_CLE */ + , /* FMC_A17_FMC_ALE */ + , /* FMC_D0 */ + , /* FMC_D1 */ + , /* FMC_D2 */ + , /* FMC_D3 */ + , /* FMC_D4 */ + , /* FMC_D5 */ + , /* FMC_D6 */ + , /* FMC_D7 */ + ; /* FMC_NE2_FMC_NCE */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* FMC_NWAIT */ + bias-pull-up; + }; + }; + + fmc_sleep_pins_a: fmc-sleep-0 { + pins { + pinmux = , /* FMC_NOE */ + , /* FMC_NWE */ + , /* FMC_A16_FMC_CLE */ + , /* FMC_A17_FMC_ALE */ + , /* FMC_D0 */ + , /* FMC_D1 */ + , /* FMC_D2 */ + , /* FMC_D3 */ + , /* FMC_D4 */ + , /* FMC_D5 */ + , /* FMC_D6 */ + , /* FMC_D7 */ + , /* FMC_NWAIT */ + ; /* FMC_NE2_FMC_NCE */ + }; + }; + + fmc_pins_b: fmc-1 { + pins { + pinmux = , /* FMC_NOE */ + , /* FMC_NWE */ + , /* FMC_NL */ + , /* FMC_D0 */ + , /* FMC_D1 */ + , /* FMC_D2 */ + , /* FMC_D3 */ + , /* FMC_D4 */ + , /* FMC_D5 */ + , /* FMC_D6 */ + , /* FMC_D7 */ + , /* FMC_D8 */ + , /* FMC_D9 */ + , /* FMC_D10 */ + , /* FMC_D11 */ + , /* FMC_D12 */ + , /* FMC_D13 */ + , /* FMC_D14 */ + , /* FMC_D15 */ + , /* FMC_NE2_FMC_NCE */ + ; /* FMC_NE4 */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + }; + + fmc_sleep_pins_b: fmc-sleep-1 { + pins { + pinmux = , /* FMC_NOE */ + , /* FMC_NWE */ + , /* FMC_NL */ + , /* FMC_D0 */ + , /* FMC_D1 */ + , /* FMC_D2 */ + , /* FMC_D3 */ + , /* FMC_D4 */ + , /* FMC_D5 */ + , /* FMC_D6 */ + , /* FMC_D7 */ + , /* FMC_D8 */ + , /* FMC_D9 */ + , /* FMC_D10 */ + , /* FMC_D11 */ + , /* FMC_D12 */ + , /* FMC_D13 */ + , /* FMC_D14 */ + , /* FMC_D15 */ + , /* FMC_NE2_FMC_NCE */ + ; /* FMC_NE4 */ + }; + }; + + i2c1_pins_a: i2c1-0 { + pins { + pinmux = , /* I2C1_SCL */ + ; /* I2C1_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c1_sleep_pins_a: i2c1-sleep-0 { + pins { + pinmux = , /* I2C1_SCL */ + ; /* I2C1_SDA */ + }; + }; + + i2c1_pins_b: i2c1-1 { + pins { + pinmux = , /* I2C1_SCL */ + ; /* I2C1_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c1_sleep_pins_b: i2c1-sleep-1 { + pins { + pinmux = , /* I2C1_SCL */ + ; /* I2C1_SDA */ + }; + }; + + i2c2_pins_a: i2c2-0 { + pins { + pinmux = , /* I2C2_SCL */ + ; /* I2C2_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c2_sleep_pins_a: i2c2-sleep-0 { + pins { + pinmux = , /* I2C2_SCL */ + ; /* I2C2_SDA */ + }; + }; + + i2c2_pins_b1: i2c2-1 { + pins { + pinmux = ; /* I2C2_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c2_sleep_pins_b1: i2c2-sleep-1 { + pins { + pinmux = ; /* I2C2_SDA */ + }; + }; + + i2c2_pins_c: i2c2-2 { + pins { + pinmux = , /* I2C2_SCL */ + ; /* I2C2_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c2_pins_sleep_c: i2c2-sleep-2 { + pins { + pinmux = , /* I2C2_SCL */ + ; /* I2C2_SDA */ + }; + }; + + i2c5_pins_a: i2c5-0 { + pins { + pinmux = , /* I2C5_SCL */ + ; /* I2C5_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c5_sleep_pins_a: i2c5-sleep-0 { + pins { + pinmux = , /* I2C5_SCL */ + ; /* I2C5_SDA */ + + }; + }; + + i2c5_pins_b: i2c5-1 { + pins { + pinmux = , /* I2C5_SCL */ + ; /* I2C5_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c5_sleep_pins_b: i2c5-sleep-1 { + pins { + pinmux = , /* I2C5_SCL */ + ; /* I2C5_SDA */ + }; + }; + + i2s2_pins_a: i2s2-0 { + pins { + pinmux = , /* I2S2_SDO */ + , /* I2S2_WS */ + ; /* I2S2_CK */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + }; + + i2s2_sleep_pins_a: i2s2-sleep-0 { + pins { + pinmux = , /* I2S2_SDO */ + , /* I2S2_WS */ + ; /* I2S2_CK */ + }; + }; + + ltdc_pins_a: ltdc-0 { + pins { + pinmux = , /* LCD_CLK */ + , /* LCD_HSYNC */ + , /* LCD_VSYNC */ + , /* LCD_DE */ + , /* LCD_R0 */ + , /* LCD_R1 */ + , /* LCD_R2 */ + , /* LCD_R3 */ + , /* LCD_R4 */ + , /* LCD_R5 */ + , /* LCD_R6 */ + , /* LCD_R7 */ + , /* LCD_G0 */ + , /* LCD_G1 */ + , /* LCD_G2 */ + , /* LCD_G3 */ + , /* LCD_G4 */ + , /* LCD_G5 */ + , /* LCD_G6 */ + , /* LCD_G7 */ + , /* LCD_B0 */ + , /* LCD_B1 */ + , /* LCD_B2 */ + , /* LCD_B3 */ + , /* LCD_B4 */ + , /* LCD_B5 */ + , /* LCD_B6 */ + ; /* LCD_B7 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + }; + + ltdc_sleep_pins_a: ltdc-sleep-0 { + pins { + pinmux = , /* LCD_CLK */ + , /* LCD_HSYNC */ + , /* LCD_VSYNC */ + , /* LCD_DE */ + , /* LCD_R0 */ + , /* LCD_R1 */ + , /* LCD_R2 */ + , /* LCD_R3 */ + , /* LCD_R4 */ + , /* LCD_R5 */ + , /* LCD_R6 */ + , /* LCD_R7 */ + , /* LCD_G0 */ + , /* LCD_G1 */ + , /* LCD_G2 */ + , /* LCD_G3 */ + , /* LCD_G4 */ + , /* LCD_G5 */ + , /* LCD_G6 */ + , /* LCD_G7 */ + , /* LCD_B0 */ + , /* LCD_B1 */ + , /* LCD_B2 */ + , /* LCD_B3 */ + , /* LCD_B4 */ + , /* LCD_B5 */ + , /* LCD_B6 */ + ; /* LCD_B7 */ + }; + }; + + ltdc_pins_b: ltdc-1 { + pins { + pinmux = , /* LCD_CLK */ + , /* LCD_HSYNC */ + , /* LCD_VSYNC */ + , /* LCD_DE */ + , /* LCD_R0 */ + , /* LCD_R1 */ + , /* LCD_R2 */ + , /* LCD_R3 */ + , /* LCD_R4 */ + , /* LCD_R5 */ + , /* LCD_R6 */ + , /* LCD_R7 */ + , /* LCD_G0 */ + , /* LCD_G1 */ + , /* LCD_G2 */ + , /* LCD_G3 */ + , /* LCD_G4 */ + , /* LCD_G5 */ + , /* LCD_G6 */ + , /* LCD_G7 */ + , /* LCD_B0 */ + , /* LCD_B1 */ + , /* LCD_B2 */ + , /* LCD_B3 */ + , /* LCD_B4 */ + , /* LCD_B5 */ + , /* LCD_B6 */ + ; /* LCD_B7 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + }; + + ltdc_sleep_pins_b: ltdc-sleep-1 { + pins { + pinmux = , /* LCD_CLK */ + , /* LCD_HSYNC */ + , /* LCD_VSYNC */ + , /* LCD_DE */ + , /* LCD_R0 */ + , /* LCD_R1 */ + , /* LCD_R2 */ + , /* LCD_R3 */ + , /* LCD_R4 */ + , /* LCD_R5 */ + , /* LCD_R6 */ + , /* LCD_R7 */ + , /* LCD_G0 */ + , /* LCD_G1 */ + , /* LCD_G2 */ + , /* LCD_G3 */ + , /* LCD_G4 */ + , /* LCD_G5 */ + , /* LCD_G6 */ + , /* LCD_G7 */ + , /* LCD_B0 */ + , /* LCD_B1 */ + , /* LCD_B2 */ + , /* LCD_B3 */ + , /* LCD_B4 */ + , /* LCD_B5 */ + , /* LCD_B6 */ + ; /* LCD_B7 */ + }; + }; + + ltdc_pins_c: ltdc-2 { + pins1 { + pinmux = , /* LTDC_R6 */ + , /* LTDC_B7 */ + , /* LTDC_R5 */ + , /* LTDC_G7 */ + , /* LTDC_B2 */ + , /* LTDC_B3 */ + , /* LTDC_G3 */ + , /* LTDC_B4 */ + , /* LTDC_DE */ + , /* LTDC_R7 */ + , /* LTDC_G5 */ + , /* LTDC_R2 */ + , /* LTDC_R3 */ + , /* LTDC_R4 */ + , /* LTDC_G2 */ + , /* LTDC_G4 */ + , /* LTDC_G6 */ + , /* LTDC_B5 */ + , /* LTDC_B6 */ + , /* LTDC_VSYNC */ + ; /* LTDC_HSYNC */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* LTDC_CLK */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + }; + + ltdc_sleep_pins_c: ltdc-sleep-2 { + pins1 { + pinmux = , /* LTDC_R6 */ + , /* LTDC_B7 */ + , /* LTDC_R5 */ + , /* LTDC_G7 */ + , /* LTDC_B2 */ + , /* LTDC_B3 */ + , /* LTDC_G3 */ + , /* LTDC_B4 */ + , /* LTDC_DE */ + , /* LTDC_R7 */ + , /* LTDC_G5 */ + , /* LTDC_R2 */ + , /* LTDC_R3 */ + , /* LTDC_R4 */ + , /* LTDC_G2 */ + , /* LTDC_G4 */ + , /* LTDC_G6 */ + , /* LTDC_B5 */ + , /* LTDC_B6 */ + , /* LTDC_VSYNC */ + , /* LTDC_HSYNC */ + ; /* LTDC_CLK */ + }; + }; + + ltdc_pins_d: ltdc-3 { + pins1 { + pinmux = ; /* LCD_CLK */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + pins2 { + pinmux = , /* LCD_HSYNC */ + , /* LCD_VSYNC */ + , /* LCD_DE */ + , /* LCD_R0 */ + , /* LCD_R1 */ + , /* LCD_R2 */ + , /* LCD_R3 */ + , /* LCD_R4 */ + , /* LCD_R5 */ + , /* LCD_R6 */ + , /* LCD_R7 */ + , /* LCD_G0 */ + , /* LCD_G1 */ + , /* LCD_G2 */ + , /* LCD_G3 */ + , /* LCD_G4 */ + , /* LCD_G5 */ + , /* LCD_G6 */ + , /* LCD_G7 */ + , /* LCD_B0 */ + , /* LCD_B1 */ + , /* LCD_B2 */ + , /* LCD_B3 */ + , /* LCD_B4 */ + , /* LCD_B5 */ + , /* LCD_B6 */ + ; /* LCD_B7 */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + }; + + ltdc_sleep_pins_d: ltdc-sleep-3 { + pins { + pinmux = , /* LCD_CLK */ + , /* LCD_HSYNC */ + , /* LCD_VSYNC */ + , /* LCD_DE */ + , /* LCD_R0 */ + , /* LCD_R1 */ + , /* LCD_R2 */ + , /* LCD_R3 */ + , /* LCD_R4 */ + , /* LCD_R5 */ + , /* LCD_R6 */ + , /* LCD_R7 */ + , /* LCD_G0 */ + , /* LCD_G1 */ + , /* LCD_G2 */ + , /* LCD_G3 */ + , /* LCD_G4 */ + , /* LCD_G5 */ + , /* LCD_G6 */ + , /* LCD_G7 */ + , /* LCD_B0 */ + , /* LCD_B1 */ + , /* LCD_B2 */ + , /* LCD_B3 */ + , /* LCD_B4 */ + , /* LCD_B5 */ + , /* LCD_B6 */ + ; /* LCD_B7 */ + }; + }; + + mco2_pins_a: mco2-0 { + pins { + pinmux = ; /* MCO2 */ + bias-disable; + drive-push-pull; + slew-rate = <2>; + }; + }; + + mco2_sleep_pins_a: mco2-sleep-0 { + pins { + pinmux = ; /* MCO2 */ + }; + }; + + m_can1_pins_a: m-can1-0 { + pins1 { + pinmux = ; /* CAN1_TX */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* CAN1_RX */ + bias-disable; + }; + }; + + m_can1_sleep_pins_a: m_can1-sleep-0 { + pins { + pinmux = , /* CAN1_TX */ + ; /* CAN1_RX */ + }; + }; + + m_can1_pins_b: m-can1-1 { + pins1 { + pinmux = ; /* CAN1_TX */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* CAN1_RX */ + bias-disable; + }; + }; + + m_can1_sleep_pins_b: m_can1-sleep-1 { + pins { + pinmux = , /* CAN1_TX */ + ; /* CAN1_RX */ + }; + }; + + m_can2_pins_a: m-can2-0 { + pins1 { + pinmux = ; /* CAN2_TX */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* CAN2_RX */ + bias-disable; + }; + }; + + m_can2_sleep_pins_a: m_can2-sleep-0 { + pins { + pinmux = , /* CAN2_TX */ + ; /* CAN2_RX */ + }; + }; + + pwm1_pins_a: pwm1-0 { + pins { + pinmux = , /* TIM1_CH1 */ + , /* TIM1_CH2 */ + ; /* TIM1_CH4 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm1_sleep_pins_a: pwm1-sleep-0 { + pins { + pinmux = , /* TIM1_CH1 */ + , /* TIM1_CH2 */ + ; /* TIM1_CH4 */ + }; + }; + + pwm1_pins_b: pwm1-1 { + pins { + pinmux = ; /* TIM1_CH1 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm1_sleep_pins_b: pwm1-sleep-1 { + pins { + pinmux = ; /* TIM1_CH1 */ + }; + }; + + pwm2_pins_a: pwm2-0 { + pins { + pinmux = ; /* TIM2_CH4 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm2_sleep_pins_a: pwm2-sleep-0 { + pins { + pinmux = ; /* TIM2_CH4 */ + }; + }; + + pwm3_pins_a: pwm3-0 { + pins { + pinmux = ; /* TIM3_CH2 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm3_sleep_pins_a: pwm3-sleep-0 { + pins { + pinmux = ; /* TIM3_CH2 */ + }; + }; + + pwm3_pins_b: pwm3-1 { + pins { + pinmux = ; /* TIM3_CH2 */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm3_sleep_pins_b: pwm3-sleep-1 { + pins { + pinmux = ; /* TIM3_CH2 */ + }; + }; + + pwm4_pins_a: pwm4-0 { + pins { + pinmux = , /* TIM4_CH3 */ + ; /* TIM4_CH4 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm4_sleep_pins_a: pwm4-sleep-0 { + pins { + pinmux = , /* TIM4_CH3 */ + ; /* TIM4_CH4 */ + }; + }; + + pwm4_pins_b: pwm4-1 { + pins { + pinmux = ; /* TIM4_CH2 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm4_sleep_pins_b: pwm4-sleep-1 { + pins { + pinmux = ; /* TIM4_CH2 */ + }; + }; + + pwm5_pins_a: pwm5-0 { + pins { + pinmux = ; /* TIM5_CH2 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm5_sleep_pins_a: pwm5-sleep-0 { + pins { + pinmux = ; /* TIM5_CH2 */ + }; + }; + + pwm5_pins_b: pwm5-1 { + pins { + pinmux = , /* TIM5_CH2 */ + , /* TIM5_CH3 */ + ; /* TIM5_CH4 */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm5_sleep_pins_b: pwm5-sleep-1 { + pins { + pinmux = , /* TIM5_CH2 */ + , /* TIM5_CH3 */ + ; /* TIM5_CH4 */ + }; + }; + + pwm8_pins_a: pwm8-0 { + pins { + pinmux = ; /* TIM8_CH4 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm8_sleep_pins_a: pwm8-sleep-0 { + pins { + pinmux = ; /* TIM8_CH4 */ + }; + }; + + pwm12_pins_a: pwm12-0 { + pins { + pinmux = ; /* TIM12_CH1 */ + bias-pull-down; + drive-push-pull; + slew-rate = <0>; + }; + }; + + pwm12_sleep_pins_a: pwm12-sleep-0 { + pins { + pinmux = ; /* TIM12_CH1 */ + }; + }; + + qspi_clk_pins_a: qspi-clk-0 { + pins { + pinmux = ; /* QSPI_CLK */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + }; + + qspi_clk_sleep_pins_a: qspi-clk-sleep-0 { + pins { + pinmux = ; /* QSPI_CLK */ + }; + }; + + qspi_bk1_pins_a: qspi-bk1-0 { + pins1 { + pinmux = , /* QSPI_BK1_IO0 */ + , /* QSPI_BK1_IO1 */ + , /* QSPI_BK1_IO2 */ + ; /* QSPI_BK1_IO3 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* QSPI_BK1_NCS */ + bias-pull-up; + drive-push-pull; + slew-rate = <1>; + }; + }; + + qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 { + pins { + pinmux = , /* QSPI_BK1_IO0 */ + , /* QSPI_BK1_IO1 */ + , /* QSPI_BK1_IO2 */ + , /* QSPI_BK1_IO3 */ + ; /* QSPI_BK1_NCS */ + }; + }; + + qspi_bk2_pins_a: qspi-bk2-0 { + pins1 { + pinmux = , /* QSPI_BK2_IO0 */ + , /* QSPI_BK2_IO1 */ + , /* QSPI_BK2_IO2 */ + ; /* QSPI_BK2_IO3 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* QSPI_BK2_NCS */ + bias-pull-up; + drive-push-pull; + slew-rate = <1>; + }; + }; + + qspi_bk2_sleep_pins_a: qspi-bk2-sleep-0 { + pins { + pinmux = , /* QSPI_BK2_IO0 */ + , /* QSPI_BK2_IO1 */ + , /* QSPI_BK2_IO2 */ + , /* QSPI_BK2_IO3 */ + ; /* QSPI_BK2_NCS */ + }; + }; + + sai2a_pins_a: sai2a-0 { + pins { + pinmux = , /* SAI2_SCK_A */ + , /* SAI2_SD_A */ + , /* SAI2_FS_A */ + ; /* SAI2_MCLK_A */ + slew-rate = <0>; + drive-push-pull; + bias-disable; + }; + }; + + sai2a_sleep_pins_a: sai2a-sleep-0 { + pins { + pinmux = , /* SAI2_SCK_A */ + , /* SAI2_SD_A */ + , /* SAI2_FS_A */ + ; /* SAI2_MCLK_A */ + }; + }; + + sai2a_pins_b: sai2a-1 { + pins1 { + pinmux = , /* SAI2_SD_A */ + , /* SAI2_FS_A */ + ; /* SAI2_SCK_A */ + slew-rate = <0>; + drive-push-pull; + bias-disable; + }; + }; + + sai2a_sleep_pins_b: sai2a-sleep-1 { + pins { + pinmux = , /* SAI2_SD_A */ + , /* SAI2_FS_A */ + ; /* SAI2_SCK_A */ + }; + }; + + sai2a_pins_c: sai2a-2 { + pins { + pinmux = , /* SAI2_SCK_A */ + , /* SAI2_SD_A */ + ; /* SAI2_FS_A */ + slew-rate = <0>; + drive-push-pull; + bias-disable; + }; + }; + + sai2a_sleep_pins_c: sai2a-sleep-2 { + pins { + pinmux = , /* SAI2_SCK_A */ + , /* SAI2_SD_A */ + ; /* SAI2_FS_A */ + }; + }; + + sai2b_pins_a: sai2b-0 { + pins1 { + pinmux = , /* SAI2_SCK_B */ + , /* SAI2_FS_B */ + ; /* SAI2_MCLK_B */ + slew-rate = <0>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SAI2_SD_B */ + bias-disable; + }; + }; + + sai2b_sleep_pins_a: sai2b-sleep-0 { + pins { + pinmux = , /* SAI2_SD_B */ + , /* SAI2_SCK_B */ + , /* SAI2_FS_B */ + ; /* SAI2_MCLK_B */ + }; + }; + + sai2b_pins_b: sai2b-1 { + pins { + pinmux = ; /* SAI2_SD_B */ + bias-disable; + }; + }; + + sai2b_sleep_pins_b: sai2b-sleep-1 { + pins { + pinmux = ; /* SAI2_SD_B */ + }; + }; + + sai2b_pins_c: sai2b-2 { + pins1 { + pinmux = ; /* SAI2_SD_B */ + bias-disable; + }; + }; + + sai2b_sleep_pins_c: sai2b-sleep-2 { + pins { + pinmux = ; /* SAI2_SD_B */ + }; + }; + + sai4a_pins_a: sai4a-0 { + pins { + pinmux = ; /* SAI4_SD_A */ + slew-rate = <0>; + drive-push-pull; + bias-disable; + }; + }; + + sai4a_sleep_pins_a: sai4a-sleep-0 { + pins { + pinmux = ; /* SAI4_SD_A */ + }; + }; + + sdmmc1_b4_pins_a: sdmmc1-b4-0 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + , /* SDMMC1_D3 */ + ; /* SDMMC1_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + ; /* SDMMC1_D3 */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + pins3 { + pinmux = ; /* SDMMC1_CMD */ + slew-rate = <1>; + drive-open-drain; + bias-disable; + }; + }; + + sdmmc1_b4_init_pins_a: sdmmc1-b4-init-0 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + ; /* SDMMC1_D3 */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 { + pins { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + , /* SDMMC1_D3 */ + , /* SDMMC1_CK */ + ; /* SDMMC1_CMD */ + }; + }; + + sdmmc1_dir_pins_a: sdmmc1-dir-0 { + pins1 { + pinmux = , /* SDMMC1_D0DIR */ + , /* SDMMC1_D123DIR */ + ; /* SDMMC1_CDIR */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2{ + pinmux = ; /* SDMMC1_CKIN */ + bias-pull-up; + }; + }; + + sdmmc1_dir_init_pins_a: sdmmc1-dir-init-0 { + pins1 { + pinmux = , /* SDMMC1_D0DIR */ + , /* SDMMC1_D123DIR */ + ; /* SDMMC1_CDIR */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 { + pins { + pinmux = , /* SDMMC1_D0DIR */ + , /* SDMMC1_D123DIR */ + , /* SDMMC1_CDIR */ + ; /* SDMMC1_CKIN */ + }; + }; + + sdmmc1_dir_pins_b: sdmmc1-dir-1 { + pins1 { + pinmux = , /* SDMMC1_D0DIR */ + , /* SDMMC1_D123DIR */ + ; /* SDMMC1_CDIR */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2{ + pinmux = ; /* SDMMC1_CKIN */ + bias-pull-up; + }; + }; + + sdmmc1_dir_sleep_pins_b: sdmmc1-dir-sleep-1 { + pins { + pinmux = , /* SDMMC1_D0DIR */ + , /* SDMMC1_D123DIR */ + , /* SDMMC1_CDIR */ + ; /* SDMMC1_CKIN */ + }; + }; + + sdmmc2_b4_pins_a: sdmmc2-b4-0 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + ; /* SDMMC2_D3 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + pins3 { + pinmux = ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-open-drain; + bias-pull-up; + }; + }; + + sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 { + pins { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + , /* SDMMC2_CK */ + ; /* SDMMC2_CMD */ + }; + }; + + sdmmc2_b4_pins_b: sdmmc2-b4-1 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + ; /* SDMMC2_D3 */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + pins3 { + pinmux = ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-open-drain; + bias-disable; + }; + }; + + sdmmc2_d47_pins_a: sdmmc2-d47-0 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + }; + }; + + sdmmc2_d47_pins_b: sdmmc2-d47-1 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc2_d47_sleep_pins_b: sdmmc2-d47-sleep-1 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + }; + }; + + sdmmc2_d47_pins_c: sdmmc2-d47-2 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc2_d47_sleep_pins_c: sdmmc2-d47-sleep-2 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + }; + }; + + sdmmc2_d47_pins_d: sdmmc2-d47-3 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + }; + }; + + sdmmc2_d47_sleep_pins_d: sdmmc2-d47-sleep-3 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + }; + }; + + sdmmc3_b4_pins_a: sdmmc3-b4-0 { + pins1 { + pinmux = , /* SDMMC3_D0 */ + , /* SDMMC3_D1 */ + , /* SDMMC3_D2 */ + , /* SDMMC3_D3 */ + ; /* SDMMC3_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC3_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc3_b4_od_pins_a: sdmmc3-b4-od-0 { + pins1 { + pinmux = , /* SDMMC3_D0 */ + , /* SDMMC3_D1 */ + , /* SDMMC3_D2 */ + ; /* SDMMC3_D3 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC3_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + pins3 { + pinmux = ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-open-drain; + bias-pull-up; + }; + }; + + sdmmc3_b4_sleep_pins_a: sdmmc3-b4-sleep-0 { + pins { + pinmux = , /* SDMMC3_D0 */ + , /* SDMMC3_D1 */ + , /* SDMMC3_D2 */ + , /* SDMMC3_D3 */ + , /* SDMMC3_CK */ + ; /* SDMMC3_CMD */ + }; + }; + + sdmmc3_b4_pins_b: sdmmc3-b4-1 { + pins1 { + pinmux = , /* SDMMC3_D0 */ + , /* SDMMC3_D1 */ + , /* SDMMC3_D2 */ + , /* SDMMC3_D3 */ + ; /* SDMMC3_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC3_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc3_b4_od_pins_b: sdmmc3-b4-od-1 { + pins1 { + pinmux = , /* SDMMC3_D0 */ + , /* SDMMC3_D1 */ + , /* SDMMC3_D2 */ + ; /* SDMMC3_D3 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC3_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + pins3 { + pinmux = ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-open-drain; + bias-pull-up; + }; + }; + + sdmmc3_b4_sleep_pins_b: sdmmc3-b4-sleep-1 { + pins { + pinmux = , /* SDMMC3_D0 */ + , /* SDMMC3_D1 */ + , /* SDMMC3_D2 */ + , /* SDMMC3_D3 */ + , /* SDMMC3_CK */ + ; /* SDMMC3_CMD */ + }; + }; + + spdifrx_pins_a: spdifrx-0 { + pins { + pinmux = ; /* SPDIF_IN1 */ + bias-disable; + }; + }; + + spdifrx_sleep_pins_a: spdifrx-sleep-0 { + pins { + pinmux = ; /* SPDIF_IN1 */ + }; + }; + + spi2_pins_a: spi2-0 { + pins1 { + pinmux = , /* SPI1_SCK */ + ; /* SPI1_MOSI */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + + pins2 { + pinmux = ; /* SPI1_MISO */ + bias-disable; + }; + }; + + spi4_pins_a: spi4-0 { + pins { + pinmux = , /* SPI4_SCK */ + ; /* SPI4_MOSI */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* SPI4_MISO */ + bias-disable; + }; + }; + + stusb1600_pins_a: stusb1600-0 { + pins { + pinmux = ; + bias-pull-up; + }; + }; + + uart4_pins_a: uart4-0 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + uart4_idle_pins_a: uart4-idle-0 { + pins1 { + pinmux = ; /* UART4_TX */ + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + uart4_sleep_pins_a: uart4-sleep-0 { + pins { + pinmux = , /* UART4_TX */ + ; /* UART4_RX */ + }; + }; + + uart4_pins_b: uart4-1 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + uart4_pins_c: uart4-2 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + uart7_pins_a: uart7-0 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* UART7_RX */ + , /* UART7_CTS */ + ; /* UART7_RTS */ + bias-disable; + }; + }; + + uart7_pins_b: uart7-1 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART7_RX */ + bias-disable; + }; + }; + + uart7_pins_c: uart7-2 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART7_RX */ + bias-pull-up; + }; + }; + + uart7_idle_pins_c: uart7-idle-2 { + pins1 { + pinmux = ; /* UART7_TX */ + }; + pins2 { + pinmux = ; /* UART7_RX */ + bias-pull-up; + }; + }; + + uart7_sleep_pins_c: uart7-sleep-2 { + pins { + pinmux = , /* UART7_TX */ + ; /* UART7_RX */ + }; + }; + + uart8_pins_a: uart8-0 { + pins1 { + pinmux = ; /* UART8_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART8_RX */ + bias-disable; + }; + }; + + uart8_rtscts_pins_a: uart8rtscts-0 { + pins { + pinmux = , /* UART8_RTS */ + ; /* UART8_CTS */ + bias-disable; + }; + }; + + usart2_pins_a: usart2-0 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart2_sleep_pins_a: usart2-sleep-0 { + pins { + pinmux = , /* USART2_TX */ + , /* USART2_RTS */ + , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + }; + }; + + usart2_pins_b: usart2-1 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart2_sleep_pins_b: usart2-sleep-1 { + pins { + pinmux = , /* USART2_TX */ + , /* USART2_RTS */ + , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + }; + }; + + usart2_pins_c: usart2-2 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart2_idle_pins_c: usart2-idle-2 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_CTS_NSS */ + }; + pins2 { + pinmux = ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + pins3 { + pinmux = ; /* USART2_RX */ + bias-disable; + }; + }; + + usart2_sleep_pins_c: usart2-sleep-2 { + pins { + pinmux = , /* USART2_TX */ + , /* USART2_RTS */ + , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + }; + }; + + usart3_pins_a: usart3-0 { + pins1 { + pinmux = ; /* USART3_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART3_RX */ + bias-disable; + }; + }; + + usart3_pins_b: usart3-1 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-pull-up; + }; + }; + + usart3_idle_pins_b: usart3-idle-1 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_CTS_NSS */ + }; + pins2 { + pinmux = ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = ; /* USART3_RX */ + bias-pull-up; + }; + }; + + usart3_sleep_pins_b: usart3-sleep-1 { + pins { + pinmux = , /* USART3_TX */ + , /* USART3_RTS */ + , /* USART3_CTS_NSS */ + ; /* USART3_RX */ + }; + }; + + usart3_pins_c: usart3-2 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-pull-up; + }; + }; + + usart3_idle_pins_c: usart3-idle-2 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_CTS_NSS */ + }; + pins2 { + pinmux = ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins3 { + pinmux = ; /* USART3_RX */ + bias-pull-up; + }; + }; + + usart3_sleep_pins_c: usart3-sleep-2 { + pins { + pinmux = , /* USART3_TX */ + , /* USART3_RTS */ + , /* USART3_CTS_NSS */ + ; /* USART3_RX */ + }; + }; + + usart3_pins_d: usart3-3 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; + + usart3_idle_pins_d: usart3-idle-3 { + pins1 { + pinmux = , /* USART3_TX */ + , /* USART3_RTS */ + ; /* USART3_CTS_NSS */ + }; + pins2 { + pinmux = ; /* USART3_RX */ + bias-disable; + }; + }; + + usart3_sleep_pins_d: usart3-sleep-3 { + pins { + pinmux = , /* USART3_TX */ + , /* USART3_RTS */ + , /* USART3_CTS_NSS */ + ; /* USART3_RX */ + }; + }; + + usbotg_hs_pins_a: usbotg-hs-0 { + pins { + pinmux = ; /* OTG_ID */ + }; + }; + + usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { + pins { + pinmux = , /* OTG_FS_DM */ + ; /* OTG_FS_DP */ + }; + }; +}; + +&pinctrl_z { + i2c2_pins_b2: i2c2-0 { + pins { + pinmux = ; /* I2C2_SCL */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c2_sleep_pins_b2: i2c2-sleep-0 { + pins { + pinmux = ; /* I2C2_SCL */ + }; + }; + + i2c4_pins_a: i2c4-0 { + pins { + pinmux = , /* I2C4_SCL */ + ; /* I2C4_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c4_sleep_pins_a: i2c4-sleep-0 { + pins { + pinmux = , /* I2C4_SCL */ + ; /* I2C4_SDA */ + }; + }; + + i2c6_pins_a: i2c6-0 { + pins { + pinmux = , /* I2C6_SCL */ + ; /* I2C6_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + i2c6_sleep_pins_a: i2c6-sleep-0 { + pins { + pinmux = , /* I2C6_SCL */ + ; /* I2C6_SDA */ + }; + }; + + spi1_pins_a: spi1-0 { + pins1 { + pinmux = , /* SPI1_SCK */ + ; /* SPI1_MOSI */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + + pins2 { + pinmux = ; /* SPI1_MISO */ + bias-disable; + }; + }; + + spi1_pins_b: spi1-1 { + pins1 { + pinmux = , /* SPI1_SCK */ + ; /* SPI1_MOSI */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + + pins2 { + pinmux = ; /* SPI1_MISO */ + bias-disable; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp151.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp151.dtsi new file mode 100644 index 0000000..dce4095 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp151.dtsi @@ -0,0 +1,1851 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a7"; + clock-frequency = <650000000>; + device_type = "cpu"; + reg = <0>; + }; + }; + + arm-pmu { + compatible = "arm,cortex-a7-pmu"; + interrupts = ; + interrupt-affinity = <&cpu0>; + interrupt-parent = <&intc>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, + <0xa0022000 0x2000>; + }; + + timer { + compatible = "arm,armv7-timer"; + interrupts = , + , + , + ; + interrupt-parent = <&intc>; + }; + + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&dts>; + + trips { + cpu_alert1: cpu-alert1 { + temperature = <85000>; + hysteresis = <0>; + type = "passive"; + }; + + cpu-crit { + temperature = <120000>; + hysteresis = <0>; + type = "critical"; + }; + }; + + cooling-maps { + }; + }; + }; + + booster: regulator-booster { + compatible = "st,stm32mp1-booster"; + st,syscfg = <&syscfg>; + status = "disabled"; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges; + + timers2: timer@40000000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40000000 0x400>; + clocks = <&rcc TIM2_K>; + clock-names = "int"; + dmas = <&dmamux1 18 0x400 0x1>, + <&dmamux1 19 0x400 0x1>, + <&dmamux1 20 0x400 0x1>, + <&dmamux1 21 0x400 0x1>, + <&dmamux1 22 0x400 0x1>; + dma-names = "ch1", "ch2", "ch3", "ch4", "up"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@1 { + compatible = "st,stm32h7-timer-trigger"; + reg = <1>; + status = "disabled"; + }; + + counter { + compatible = "st,stm32-timer-counter"; + status = "disabled"; + }; + }; + + timers3: timer@40001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40001000 0x400>; + clocks = <&rcc TIM3_K>; + clock-names = "int"; + dmas = <&dmamux1 23 0x400 0x1>, + <&dmamux1 24 0x400 0x1>, + <&dmamux1 25 0x400 0x1>, + <&dmamux1 26 0x400 0x1>, + <&dmamux1 27 0x400 0x1>, + <&dmamux1 28 0x400 0x1>; + dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@2 { + compatible = "st,stm32h7-timer-trigger"; + reg = <2>; + status = "disabled"; + }; + + counter { + compatible = "st,stm32-timer-counter"; + status = "disabled"; + }; + }; + + timers4: timer@40002000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40002000 0x400>; + clocks = <&rcc TIM4_K>; + clock-names = "int"; + dmas = <&dmamux1 29 0x400 0x1>, + <&dmamux1 30 0x400 0x1>, + <&dmamux1 31 0x400 0x1>, + <&dmamux1 32 0x400 0x1>; + dma-names = "ch1", "ch2", "ch3", "ch4"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@3 { + compatible = "st,stm32h7-timer-trigger"; + reg = <3>; + status = "disabled"; + }; + + counter { + compatible = "st,stm32-timer-counter"; + status = "disabled"; + }; + }; + + timers5: timer@40003000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40003000 0x400>; + clocks = <&rcc TIM5_K>; + clock-names = "int"; + dmas = <&dmamux1 55 0x400 0x1>, + <&dmamux1 56 0x400 0x1>, + <&dmamux1 57 0x400 0x1>, + <&dmamux1 58 0x400 0x1>, + <&dmamux1 59 0x400 0x1>, + <&dmamux1 60 0x400 0x1>; + dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@4 { + compatible = "st,stm32h7-timer-trigger"; + reg = <4>; + status = "disabled"; + }; + + counter { + compatible = "st,stm32-timer-counter"; + status = "disabled"; + }; + }; + + timers6: timer@40004000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40004000 0x400>; + clocks = <&rcc TIM6_K>; + clock-names = "int"; + dmas = <&dmamux1 69 0x400 0x1>; + dma-names = "up"; + status = "disabled"; + + timer@5 { + compatible = "st,stm32h7-timer-trigger"; + reg = <5>; + status = "disabled"; + }; + }; + + timers7: timer@40005000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40005000 0x400>; + clocks = <&rcc TIM7_K>; + clock-names = "int"; + dmas = <&dmamux1 70 0x400 0x1>; + dma-names = "up"; + status = "disabled"; + + timer@6 { + compatible = "st,stm32h7-timer-trigger"; + reg = <6>; + status = "disabled"; + }; + }; + + timers12: timer@40006000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40006000 0x400>; + clocks = <&rcc TIM12_K>; + clock-names = "int"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@11 { + compatible = "st,stm32h7-timer-trigger"; + reg = <11>; + status = "disabled"; + }; + }; + + timers13: timer@40007000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40007000 0x400>; + clocks = <&rcc TIM13_K>; + clock-names = "int"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@12 { + compatible = "st,stm32h7-timer-trigger"; + reg = <12>; + status = "disabled"; + }; + }; + + timers14: timer@40008000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40008000 0x400>; + clocks = <&rcc TIM14_K>; + clock-names = "int"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@13 { + compatible = "st,stm32h7-timer-trigger"; + reg = <13>; + status = "disabled"; + }; + }; + + lptimer1: timer@40009000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-lptimer"; + reg = <0x40009000 0x400>; + interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM1_K>; + clock-names = "mux"; + wakeup-source; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm-lp"; + #pwm-cells = <3>; + status = "disabled"; + }; + + trigger@0 { + compatible = "st,stm32-lptimer-trigger"; + reg = <0>; + status = "disabled"; + }; + + counter { + compatible = "st,stm32-lptimer-counter"; + status = "disabled"; + }; + }; + + spi2: spi@4000b000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x4000b000 0x400>; + interrupts = ; + clocks = <&rcc SPI2_K>; + resets = <&rcc SPI2_R>; + dmas = <&dmamux1 39 0x400 0x05>, + <&dmamux1 40 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + i2s2: audio-controller@4000b000 { + compatible = "st,stm32h7-i2s"; + #sound-dai-cells = <0>; + reg = <0x4000b000 0x400>; + interrupts = ; + dmas = <&dmamux1 39 0x400 0x01>, + <&dmamux1 40 0x400 0x01>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + spi3: spi@4000c000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x4000c000 0x400>; + interrupts = ; + clocks = <&rcc SPI3_K>; + resets = <&rcc SPI3_R>; + dmas = <&dmamux1 61 0x400 0x05>, + <&dmamux1 62 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + i2s3: audio-controller@4000c000 { + compatible = "st,stm32h7-i2s"; + #sound-dai-cells = <0>; + reg = <0x4000c000 0x400>; + interrupts = ; + dmas = <&dmamux1 61 0x400 0x01>, + <&dmamux1 62 0x400 0x01>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + spdifrx: audio-controller@4000d000 { + compatible = "st,stm32h7-spdifrx"; + #sound-dai-cells = <0>; + reg = <0x4000d000 0x400>; + clocks = <&rcc SPDIF_K>; + clock-names = "kclk"; + interrupts = ; + dmas = <&dmamux1 93 0x400 0x01>, + <&dmamux1 94 0x400 0x01>; + dma-names = "rx", "rx-ctrl"; + status = "disabled"; + }; + + usart2: serial@4000e000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000e000 0x400>; + interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART2_K>; + wakeup-source; + dmas = <&dmamux1 43 0x400 0x15>, + <&dmamux1 44 0x400 0x11>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + usart3: serial@4000f000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000f000 0x400>; + interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART3_K>; + wakeup-source; + dmas = <&dmamux1 45 0x400 0x15>, + <&dmamux1 46 0x400 0x11>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart4: serial@40010000 { + compatible = "st,stm32h7-uart"; + reg = <0x40010000 0x400>; + interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART4_K>; + wakeup-source; + dmas = <&dmamux1 63 0x400 0x15>, + <&dmamux1 64 0x400 0x11>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; + interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART5_K>; + wakeup-source; + dmas = <&dmamux1 65 0x400 0x15>, + <&dmamux1 66 0x400 0x11>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + i2c1: i2c@40012000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x40012000 0x400>; + interrupt-names = "event", "error"; + interrupts = , + ; + clocks = <&rcc I2C1_K>; + resets = <&rcc I2C1_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x1>; + wakeup-source; + i2c-analog-filter; + status = "disabled"; + }; + + i2c2: i2c@40013000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x40013000 0x400>; + interrupt-names = "event", "error"; + interrupts = , + ; + clocks = <&rcc I2C2_K>; + resets = <&rcc I2C2_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x2>; + wakeup-source; + i2c-analog-filter; + status = "disabled"; + }; + + i2c3: i2c@40014000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x40014000 0x400>; + interrupt-names = "event", "error"; + interrupts = , + ; + clocks = <&rcc I2C3_K>; + resets = <&rcc I2C3_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x4>; + wakeup-source; + i2c-analog-filter; + status = "disabled"; + }; + + i2c5: i2c@40015000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x40015000 0x400>; + interrupt-names = "event", "error"; + interrupts = , + ; + clocks = <&rcc I2C5_K>; + resets = <&rcc I2C5_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x10>; + wakeup-source; + i2c-analog-filter; + status = "disabled"; + }; + + cec: cec@40016000 { + compatible = "st,stm32-cec"; + reg = <0x40016000 0x400>; + interrupts = ; + clocks = <&rcc CEC_K>, <&rcc CEC>; + clock-names = "cec", "hdmi-cec"; + status = "disabled"; + }; + + dac: dac@40017000 { + compatible = "st,stm32h7-dac-core"; + reg = <0x40017000 0x400>; + clocks = <&rcc DAC12>; + clock-names = "pclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + dac1: dac@1 { + compatible = "st,stm32-dac"; + #io-channel-cells = <1>; + reg = <1>; + status = "disabled"; + }; + + dac2: dac@2 { + compatible = "st,stm32-dac"; + #io-channel-cells = <1>; + reg = <2>; + status = "disabled"; + }; + }; + + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; + interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART7_K>; + wakeup-source; + dmas = <&dmamux1 79 0x400 0x15>, + <&dmamux1 80 0x400 0x11>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; + interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART8_K>; + wakeup-source; + dmas = <&dmamux1 81 0x400 0x15>, + <&dmamux1 82 0x400 0x11>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + timers1: timer@44000000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x44000000 0x400>; + clocks = <&rcc TIM1_K>; + clock-names = "int"; + dmas = <&dmamux1 11 0x400 0x1>, + <&dmamux1 12 0x400 0x1>, + <&dmamux1 13 0x400 0x1>, + <&dmamux1 14 0x400 0x1>, + <&dmamux1 15 0x400 0x1>, + <&dmamux1 16 0x400 0x1>, + <&dmamux1 17 0x400 0x1>; + dma-names = "ch1", "ch2", "ch3", "ch4", + "up", "trig", "com"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@0 { + compatible = "st,stm32h7-timer-trigger"; + reg = <0>; + status = "disabled"; + }; + + counter { + compatible = "st,stm32-timer-counter"; + status = "disabled"; + }; + }; + + timers8: timer@44001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x44001000 0x400>; + clocks = <&rcc TIM8_K>; + clock-names = "int"; + dmas = <&dmamux1 47 0x400 0x1>, + <&dmamux1 48 0x400 0x1>, + <&dmamux1 49 0x400 0x1>, + <&dmamux1 50 0x400 0x1>, + <&dmamux1 51 0x400 0x1>, + <&dmamux1 52 0x400 0x1>, + <&dmamux1 53 0x400 0x1>; + dma-names = "ch1", "ch2", "ch3", "ch4", + "up", "trig", "com"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@7 { + compatible = "st,stm32h7-timer-trigger"; + reg = <7>; + status = "disabled"; + }; + + counter { + compatible = "st,stm32-timer-counter"; + status = "disabled"; + }; + }; + + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; + interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART6_K>; + wakeup-source; + dmas = <&dmamux1 71 0x400 0x15>, + <&dmamux1 72 0x400 0x11>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + spi1: spi@44004000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x44004000 0x400>; + interrupts = ; + clocks = <&rcc SPI1_K>; + resets = <&rcc SPI1_R>; + dmas = <&dmamux1 37 0x400 0x05>, + <&dmamux1 38 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + i2s1: audio-controller@44004000 { + compatible = "st,stm32h7-i2s"; + #sound-dai-cells = <0>; + reg = <0x44004000 0x400>; + interrupts = ; + dmas = <&dmamux1 37 0x400 0x01>, + <&dmamux1 38 0x400 0x01>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + spi4: spi@44005000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x44005000 0x400>; + interrupts = ; + clocks = <&rcc SPI4_K>; + resets = <&rcc SPI4_R>; + dmas = <&dmamux1 83 0x400 0x05>, + <&dmamux1 84 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + timers15: timer@44006000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x44006000 0x400>; + clocks = <&rcc TIM15_K>; + clock-names = "int"; + dmas = <&dmamux1 105 0x400 0x1>, + <&dmamux1 106 0x400 0x1>, + <&dmamux1 107 0x400 0x1>, + <&dmamux1 108 0x400 0x1>; + dma-names = "ch1", "up", "trig", "com"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@14 { + compatible = "st,stm32h7-timer-trigger"; + reg = <14>; + status = "disabled"; + }; + }; + + timers16: timer@44007000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x44007000 0x400>; + clocks = <&rcc TIM16_K>; + clock-names = "int"; + dmas = <&dmamux1 109 0x400 0x1>, + <&dmamux1 110 0x400 0x1>; + dma-names = "ch1", "up"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + timer@15 { + compatible = "st,stm32h7-timer-trigger"; + reg = <15>; + status = "disabled"; + }; + }; + + timers17: timer@44008000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x44008000 0x400>; + clocks = <&rcc TIM17_K>; + clock-names = "int"; + dmas = <&dmamux1 111 0x400 0x1>, + <&dmamux1 112 0x400 0x1>; + dma-names = "ch1", "up"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + + timer@16 { + compatible = "st,stm32h7-timer-trigger"; + reg = <16>; + status = "disabled"; + }; + }; + + spi5: spi@44009000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x44009000 0x400>; + interrupts = ; + clocks = <&rcc SPI5_K>; + resets = <&rcc SPI5_R>; + dmas = <&dmamux1 85 0x400 0x05>, + <&dmamux1 86 0x400 0x05>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + sai1: sai@4400a000 { + compatible = "st,stm32h7-sai"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x4400a000 0x400>; + reg = <0x4400a000 0x4>, <0x4400a3f0 0x10>; + interrupts = ; + resets = <&rcc SAI1_R>; + status = "disabled"; + + sai1a: audio-controller@4400a004 { + #sound-dai-cells = <0>; + + compatible = "st,stm32-sai-sub-a"; + reg = <0x4 0x20>; + clocks = <&rcc SAI1_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 87 0x400 0x01>; + status = "disabled"; + }; + + sai1b: audio-controller@4400a024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; + reg = <0x24 0x20>; + clocks = <&rcc SAI1_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 88 0x400 0x01>; + status = "disabled"; + }; + }; + + sai2: sai@4400b000 { + compatible = "st,stm32h7-sai"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x4400b000 0x400>; + reg = <0x4400b000 0x4>, <0x4400b3f0 0x10>; + interrupts = ; + resets = <&rcc SAI2_R>; + status = "disabled"; + + sai2a: audio-controller@4400b004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; + reg = <0x4 0x20>; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 89 0x400 0x01>; + status = "disabled"; + }; + + sai2b: audio-controller@4400b024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; + reg = <0x24 0x20>; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 90 0x400 0x01>; + status = "disabled"; + }; + }; + + sai3: sai@4400c000 { + compatible = "st,stm32h7-sai"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x4400c000 0x400>; + reg = <0x4400c000 0x4>, <0x4400c3f0 0x10>; + interrupts = ; + resets = <&rcc SAI3_R>; + status = "disabled"; + + sai3a: audio-controller@4400c004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; + reg = <0x04 0x20>; + clocks = <&rcc SAI3_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 113 0x400 0x01>; + status = "disabled"; + }; + + sai3b: audio-controller@4400c024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; + reg = <0x24 0x20>; + clocks = <&rcc SAI3_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 114 0x400 0x01>; + status = "disabled"; + }; + }; + + dfsdm: dfsdm@4400d000 { + compatible = "st,stm32mp1-dfsdm"; + reg = <0x4400d000 0x800>; + clocks = <&rcc DFSDM_K>; + clock-names = "dfsdm"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + dfsdm0: filter@0 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <0>; + interrupts = ; + dmas = <&dmamux1 101 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm1: filter@1 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <1>; + interrupts = ; + dmas = <&dmamux1 102 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm2: filter@2 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <2>; + interrupts = ; + dmas = <&dmamux1 103 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm3: filter@3 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <3>; + interrupts = ; + dmas = <&dmamux1 104 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm4: filter@4 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <4>; + interrupts = ; + dmas = <&dmamux1 91 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + dfsdm5: filter@5 { + compatible = "st,stm32-dfsdm-adc"; + #io-channel-cells = <1>; + reg = <5>; + interrupts = ; + dmas = <&dmamux1 92 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + }; + + dma1: dma-controller@48000000 { + compatible = "st,stm32-dma"; + reg = <0x48000000 0x400>; + interrupts = , + , + , + , + , + , + , + ; + clocks = <&rcc DMA1>; + resets = <&rcc DMA1_R>; + #dma-cells = <4>; + st,mem2mem; + dma-requests = <8>; + }; + + dma2: dma-controller@48001000 { + compatible = "st,stm32-dma"; + reg = <0x48001000 0x400>; + interrupts = , + , + , + , + , + , + , + ; + clocks = <&rcc DMA2>; + resets = <&rcc DMA2_R>; + #dma-cells = <4>; + st,mem2mem; + dma-requests = <8>; + }; + + dmamux1: dma-router@48002000 { + compatible = "st,stm32h7-dmamux"; + reg = <0x48002000 0x40>; + #dma-cells = <3>; + dma-requests = <128>; + dma-masters = <&dma1 &dma2>; + dma-channels = <16>; + clocks = <&rcc DMAMUX>; + resets = <&rcc DMAMUX_R>; + }; + + adc: adc@48003000 { + compatible = "st,stm32mp1-adc-core"; + reg = <0x48003000 0x400>; + interrupts = , + ; + clocks = <&rcc ADC12>, <&rcc ADC12_K>; + clock-names = "bus", "adc"; + interrupt-controller; + st,syscfg = <&syscfg>; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + adc1: adc@0 { + compatible = "st,stm32mp1-adc"; + #io-channel-cells = <1>; + reg = <0x0>; + interrupt-parent = <&adc>; + interrupts = <0>; + dmas = <&dmamux1 9 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + + adc2: adc@100 { + compatible = "st,stm32mp1-adc"; + #io-channel-cells = <1>; + reg = <0x100>; + interrupt-parent = <&adc>; + interrupts = <1>; + dmas = <&dmamux1 10 0x400 0x01>; + dma-names = "rx"; + status = "disabled"; + }; + }; + + sdmmc3: mmc@48004000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; + reg = <0x48004000 0x400>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC3_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC3_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + usbotg_hs: usb-otg@49000000 { + compatible = "st,stm32mp15-hsotg", "snps,dwc2"; + reg = <0x49000000 0x10000>; + clocks = <&rcc USBO_K>; + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; + interrupts = ; + g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <32>; + g-tx-fifo-size = <256 16 16 16 16 16 16 16>; + dr_mode = "otg"; + otg-rev = <0x200>; + usb33d-supply = <&usb33>; + status = "disabled"; + }; + + ipcc: mailbox@4c001000 { + compatible = "st,stm32mp1-ipcc"; + #mbox-cells = <1>; + reg = <0x4c001000 0x400>; + st,proc-id = <0>; + interrupts-extended = + <&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, + <&exti 61 1>; + interrupt-names = "rx", "tx", "wakeup"; + clocks = <&rcc IPCC>; + wakeup-source; + status = "disabled"; + }; + + dcmi: dcmi@4c006000 { + compatible = "st,stm32-dcmi"; + reg = <0x4c006000 0x400>; + interrupts = ; + resets = <&rcc CAMITF_R>; + clocks = <&rcc DCMI>; + clock-names = "mclk"; + dmas = <&dmamux1 75 0x400 0x01>; + dma-names = "tx"; + status = "disabled"; + }; + + rcc: rcc@50000000 { + compatible = "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + pwr_regulators: pwr@50001000 { + compatible = "st,stm32mp1,pwr-reg"; + reg = <0x50001000 0x10>; + + reg11: reg11 { + regulator-name = "reg11"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + reg18: reg18 { + regulator-name = "reg18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + usb33: usb33 { + regulator-name = "usb33"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + + pwr_mcu: pwr_mcu@50001014 { + compatible = "st,stm32mp151-pwr-mcu", "syscon"; + reg = <0x50001014 0x4>; + }; + + exti: interrupt-controller@5000d000 { + compatible = "st,stm32mp1-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000d000 0x400>; + }; + + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + clocks = <&rcc SYSCFG>; + }; + + lptimer2: timer@50021000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-lptimer"; + reg = <0x50021000 0x400>; + interrupts-extended = <&exti 48 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM2_K>; + clock-names = "mux"; + wakeup-source; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm-lp"; + #pwm-cells = <3>; + status = "disabled"; + }; + + trigger@1 { + compatible = "st,stm32-lptimer-trigger"; + reg = <1>; + status = "disabled"; + }; + + counter { + compatible = "st,stm32-lptimer-counter"; + status = "disabled"; + }; + }; + + lptimer3: timer@50022000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-lptimer"; + reg = <0x50022000 0x400>; + interrupts-extended = <&exti 50 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM3_K>; + clock-names = "mux"; + wakeup-source; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm-lp"; + #pwm-cells = <3>; + status = "disabled"; + }; + + trigger@2 { + compatible = "st,stm32-lptimer-trigger"; + reg = <2>; + status = "disabled"; + }; + }; + + lptimer4: timer@50023000 { + compatible = "st,stm32-lptimer"; + reg = <0x50023000 0x400>; + interrupts-extended = <&exti 52 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM4_K>; + clock-names = "mux"; + wakeup-source; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm-lp"; + #pwm-cells = <3>; + status = "disabled"; + }; + }; + + lptimer5: timer@50024000 { + compatible = "st,stm32-lptimer"; + reg = <0x50024000 0x400>; + interrupts-extended = <&exti 53 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc LPTIM5_K>; + clock-names = "mux"; + wakeup-source; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm-lp"; + #pwm-cells = <3>; + status = "disabled"; + }; + }; + + vrefbuf: vrefbuf@50025000 { + compatible = "st,stm32-vrefbuf"; + reg = <0x50025000 0x8>; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <2500000>; + clocks = <&rcc VREF>; + status = "disabled"; + }; + + sai4: sai@50027000 { + compatible = "st,stm32h7-sai"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x50027000 0x400>; + reg = <0x50027000 0x4>, <0x500273f0 0x10>; + interrupts = ; + resets = <&rcc SAI4_R>; + status = "disabled"; + + sai4a: audio-controller@50027004 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-a"; + reg = <0x04 0x20>; + clocks = <&rcc SAI4_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 99 0x400 0x01>; + status = "disabled"; + }; + + sai4b: audio-controller@50027024 { + #sound-dai-cells = <0>; + compatible = "st,stm32-sai-sub-b"; + reg = <0x24 0x20>; + clocks = <&rcc SAI4_K>; + clock-names = "sai_ck"; + dmas = <&dmamux1 100 0x400 0x01>; + status = "disabled"; + }; + }; + + dts: thermal@50028000 { + compatible = "st,stm32-thermal"; + reg = <0x50028000 0x100>; + interrupts = ; + clocks = <&rcc TMPSENS>; + clock-names = "pclk"; + #thermal-sensor-cells = <0>; + status = "disabled"; + }; + + hash1: hash@54002000 { + compatible = "st,stm32f756-hash"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; + dmas = <&mdma1 31 0x2 0x1000A02 0x0 0x0>; + dma-names = "in"; + dma-maxburst = <2>; + status = "disabled"; + }; + + rng1: rng@54003000 { + compatible = "st,stm32-rng"; + reg = <0x54003000 0x400>; + clocks = <&rcc RNG1_K>; + resets = <&rcc RNG1_R>; + status = "disabled"; + }; + + mdma1: dma-controller@58000000 { + compatible = "st,stm32h7-mdma"; + reg = <0x58000000 0x1000>; + interrupts = ; + clocks = <&rcc MDMA>; + resets = <&rcc MDMA_R>; + #dma-cells = <5>; + dma-channels = <32>; + dma-requests = <48>; + }; + + fmc: memory-controller@58002000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "st,stm32mp1-fmc2-ebi"; + reg = <0x58002000 0x1000>; + clocks = <&rcc FMC_K>; + resets = <&rcc FMC_R>; + status = "disabled"; + + ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ + <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ + <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ + <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ + <4 0 0x80000000 0x10000000>; /* NAND */ + + nand-controller@4,0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32mp1-fmc2-nfc"; + reg = <4 0x00000000 0x1000>, + <4 0x08010000 0x1000>, + <4 0x08020000 0x1000>, + <4 0x01000000 0x1000>, + <4 0x09010000 0x1000>, + <4 0x09020000 0x1000>; + interrupts = ; + dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>, + <&mdma1 20 0x2 0x12000a08 0x0 0x0>, + <&mdma1 21 0x2 0x12000a0a 0x0 0x0>; + dma-names = "tx", "rx", "ecc"; + status = "disabled"; + }; + }; + + qspi: spi@58003000 { + compatible = "st,stm32f469-qspi"; + reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; + interrupts = ; + dmas = <&mdma1 22 0x2 0x10100002 0x0 0x0>, + <&mdma1 22 0x2 0x10100008 0x0 0x0>; + dma-names = "tx", "rx"; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + sdmmc1: mmc@58005000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; + reg = <0x58005000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC1_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC1_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + sdmmc2: mmc@58007000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; + reg = <0x58007000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC2_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC2_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + crc1: crc@58009000 { + compatible = "st,stm32f7-crc"; + reg = <0x58009000 0x400>; + clocks = <&rcc CRC1>; + status = "disabled"; + }; + + ethernet0: ethernet@5800a000 { + compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; + reg = <0x5800a000 0x2000>; + reg-names = "stmmaceth"; + interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq"; + clock-names = "stmmaceth", + "mac-clk-tx", + "mac-clk-rx", + "eth-ck", + "ptp_ref", + "ethstp"; + clocks = <&rcc ETHMAC>, + <&rcc ETHTX>, + <&rcc ETHRX>, + <&rcc ETHCK_K>, + <&rcc ETHPTP_K>, + <&rcc ETHSTP>; + st,syscon = <&syscfg 0x4>; + snps,mixed-burst; + snps,pbl = <2>; + snps,en-tx-lpi-clockgating; + snps,axi-config = <&stmmac_axi_config_0>; + snps,tso; + status = "disabled"; + + stmmac_axi_config_0: stmmac-axi-config { + snps,wr_osr_lmt = <0x7>; + snps,rd_osr_lmt = <0x7>; + snps,blen = <0 0 0 0 16 8 4>; + }; + }; + + usbh_ohci: usb@5800c000 { + compatible = "generic-ohci"; + reg = <0x5800c000 0x1000>; + clocks = <&usbphyc>, <&rcc USBH>; + resets = <&rcc USBH_R>; + interrupts = ; + status = "disabled"; + }; + + usbh_ehci: usb@5800d000 { + compatible = "generic-ehci"; + reg = <0x5800d000 0x1000>; + clocks = <&usbphyc>, <&rcc USBH>; + resets = <&rcc USBH_R>; + interrupts = ; + companion = <&usbh_ohci>; + status = "disabled"; + }; + + ltdc: display-controller@5a001000 { + compatible = "st,stm32-ltdc"; + reg = <0x5a001000 0x400>; + interrupts = , + ; + clocks = <&rcc LTDC_PX>; + clock-names = "lcd"; + resets = <&rcc LTDC_R>; + status = "disabled"; + + port { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; + interrupts = ; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + usbphyc: usbphyc@5a006000 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "st,stm32mp1-usbphyc"; + reg = <0x5a006000 0x1000>; + clocks = <&rcc USBPHY_K>; + resets = <&rcc USBPHY_R>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; + status = "disabled"; + + usbphyc_port0: usb-phy@0 { + #phy-cells = <0>; + reg = <0>; + }; + + usbphyc_port1: usb-phy@1 { + #phy-cells = <1>; + reg = <1>; + }; + }; + + usart1: serial@5c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x5c000000 0x400>; + interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART1_K>; + wakeup-source; + status = "disabled"; + }; + + spi6: spi@5c001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x5c001000 0x400>; + interrupts = ; + clocks = <&rcc SPI6_K>; + resets = <&rcc SPI6_R>; + dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>, + <&mdma1 35 0x0 0x40002 0x0 0x0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + i2c4: i2c@5c002000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x5c002000 0x400>; + interrupt-names = "event", "error"; + interrupts = , + ; + clocks = <&rcc I2C4_K>; + resets = <&rcc I2C4_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x8>; + wakeup-source; + i2c-analog-filter; + status = "disabled"; + }; + + iwdg1: watchdog@5c003000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5C003000 0x400>; + interrupts = ; + clocks = <&rcc IWDG1>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + rtc: rtc@5c004000 { + compatible = "st,stm32mp1-rtc"; + reg = <0x5c004000 0x400>; + clocks = <&rcc RTCAPB>, <&rcc RTC>; + clock-names = "pclk", "rtc_ck"; + interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + bsec: efuse@5c005000 { + compatible = "st,stm32mp15-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + + cfg0_otp: cfg0_otp@0 { + reg = <0x0 0x1>; + }; + part_number_otp: part_number_otp@4 { + reg = <0x4 0x1>; + }; + monotonic_otp: monotonic_otp@10 { + reg = <0x10 0x4>; + }; + nand_otp: nand_otp@24 { + reg = <0x24 0x4>; + }; + uid_otp: uid_otp@34 { + reg = <0x34 0xc>; + }; + package_otp: package_otp@40 { + reg = <0x40 0x4>; + }; + hw2_otp: hw2_otp@48 { + reg = <0x48 0x4>; + }; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; + pkh_otp: pkh_otp@60 { + reg = <0x60 0x20>; + }; + ethernet_mac_address: mac@e4 { + reg = <0xe4 0x8>; + st,non-secure-otp; + }; + }; + + etzpc: etzpc@5c007000 { + compatible = "st,stm32-etzpc"; + reg = <0x5C007000 0x400>; + clocks = <&rcc TZPC>; + status = "disabled"; + secure-status = "okay"; + }; + + i2c6: i2c@5c009000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x5c009000 0x400>; + interrupt-names = "event", "error"; + interrupts = , + ; + clocks = <&rcc I2C6_K>; + resets = <&rcc I2C6_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x20>; + wakeup-source; + i2c-analog-filter; + status = "disabled"; + }; + + tamp: tamp@5c00a000 { + compatible = "st,stm32-tamp", "syscon", "simple-mfd"; + reg = <0x5c00a000 0x400>; + clocks = <&rcc RTCAPB>; + }; + + /* + * Break node order to solve dependency probe issue between + * pinctrl and exti. + */ + pinctrl: pinctrl@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-pinctrl"; + ranges = <0 0x50002000 0xa400>; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; + pins-are-numbered; + + gpioa: gpio@50002000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x0 0x400>; + clocks = <&rcc GPIOA>; + st,bank-name = "GPIOA"; + status = "disabled"; + }; + + gpiob: gpio@50003000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x1000 0x400>; + clocks = <&rcc GPIOB>; + st,bank-name = "GPIOB"; + status = "disabled"; + }; + + gpioc: gpio@50004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x2000 0x400>; + clocks = <&rcc GPIOC>; + st,bank-name = "GPIOC"; + status = "disabled"; + }; + + gpiod: gpio@50005000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x3000 0x400>; + clocks = <&rcc GPIOD>; + st,bank-name = "GPIOD"; + status = "disabled"; + }; + + gpioe: gpio@50006000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x4000 0x400>; + clocks = <&rcc GPIOE>; + st,bank-name = "GPIOE"; + status = "disabled"; + }; + + gpiof: gpio@50007000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000 0x400>; + clocks = <&rcc GPIOF>; + st,bank-name = "GPIOF"; + status = "disabled"; + }; + + gpiog: gpio@50008000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x6000 0x400>; + clocks = <&rcc GPIOG>; + st,bank-name = "GPIOG"; + status = "disabled"; + }; + + gpioh: gpio@50009000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x7000 0x400>; + clocks = <&rcc GPIOH>; + st,bank-name = "GPIOH"; + status = "disabled"; + }; + + gpioi: gpio@5000a000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x8000 0x400>; + clocks = <&rcc GPIOI>; + st,bank-name = "GPIOI"; + status = "disabled"; + }; + + gpioj: gpio@5000b000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x9000 0x400>; + clocks = <&rcc GPIOJ>; + st,bank-name = "GPIOJ"; + status = "disabled"; + }; + + gpiok: gpio@5000c000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0xa000 0x400>; + clocks = <&rcc GPIOK>; + st,bank-name = "GPIOK"; + status = "disabled"; + }; + }; + + pinctrl_z: pinctrl@54004000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-z-pinctrl"; + ranges = <0 0x54004000 0x400>; + pins-are-numbered; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; + + gpioz: gpio@54004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0 0x400>; + clocks = <&rcc GPIOZ>; + st,bank-name = "GPIOZ"; + st,bank-ioport = <11>; + status = "disabled"; + }; + }; + }; + + mlahb: ahb { + compatible = "st,mlahb", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + dma-ranges = <0x00000000 0x38000000 0x10000>, + <0x10000000 0x10000000 0x60000>, + <0x30000000 0x30000000 0x60000>; + + m4_rproc: m4@10000000 { + compatible = "st,stm32mp1-m4"; + reg = <0x10000000 0x40000>, + <0x30000000 0x40000>, + <0x38000000 0x10000>; + resets = <&rcc MCU_R>; + st,syscfg-holdboot = <&rcc 0x10C 0x1>; + st,syscfg-tz = <&rcc 0x000 0x1>; + st,syscfg-pdds = <&pwr_mcu 0x0 0x1>; + st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; + st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>; + status = "disabled"; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp153.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp153.dtsi new file mode 100644 index 0000000..486084e --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp153.dtsi @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp151.dtsi" + +/ { + cpus { + cpu1: cpu@1 { + compatible = "arm,cortex-a7"; + clock-frequency = <650000000>; + device_type = "cpu"; + reg = <1>; + }; + }; + + arm-pmu { + interrupts = , + ; + interrupt-affinity = <&cpu0>, <&cpu1>; + }; + + timer { + interrupts = , + , + , + ; + }; + + soc { + m_can1: can@4400e000 { + compatible = "bosch,m_can"; + reg = <0x4400e000 0x400>, <0x44011000 0x1400>; + reg-names = "m_can", "message_ram"; + interrupts = , + ; + interrupt-names = "int0", "int1"; + clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; + clock-names = "hclk", "cclk"; + bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; + status = "disabled"; + }; + + m_can2: can@4400f000 { + compatible = "bosch,m_can"; + reg = <0x4400f000 0x400>, <0x44011000 0x2800>; + reg-names = "m_can", "message_ram"; + interrupts = , + ; + interrupt-names = "int0", "int1"; + clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; + clock-names = "hclk", "cclk"; + bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; + status = "disabled"; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp157.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp157.dtsi new file mode 100644 index 0000000..54e73cc --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157.dtsi @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp153.dtsi" + +/ { + soc { + gpu: gpu@59000000 { + compatible = "vivante,gc"; + reg = <0x59000000 0x800>; + interrupts = ; + clocks = <&rcc GPU>, <&rcc GPU_K>; + clock-names = "bus" ,"core"; + resets = <&rcc GPU_R>; + }; + + dsi: dsi@5a000000 { + compatible = "st,stm32-dsi"; + reg = <0x5a000000 0x800>; + clocks = <&rcc DSI_K>, <&clk_hse>, <&rcc DSI_PX>; + clock-names = "pclk", "ref", "px_clk"; + resets = <&rcc DSI_R>; + reset-names = "apb"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts new file mode 100644 index 0000000..2e3c9fb --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* + * Copyright (C) Linaro Ltd 2019 - All Rights Reserved + * Author: Manivannan Sadhasivam + * Copyright (C) 2020 Marek Vasut + * + * DHCOR STM32MP1 variant: + * DHCR-STM32MP157A-C065-R102-V18-SPI-C-01LG + * DHCOR PCB number: 586-100 or newer + * Avenger96 PCB number: 588-200 or newer + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15xx-dhcor-som.dtsi" +#include "stm32mp15xx-dhcor-avenger96.dtsi" + +/ { + model = "Arrow Electronics STM32MP157A Avenger96 board"; + compatible = "arrow,stm32mp157a-avenger96", "dh,stm32mp157a-dhcor-som", + "st,stm32mp157"; +}; + +&m_can1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&m_can1_pins_b>; + pinctrl-1 = <&m_can1_sleep_pins_b>; + status = "disabled"; +}; + +&m_can2 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&m_can2_pins_a>; + pinctrl-1 = <&m_can2_sleep_pins_a>; + status = "disabled"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts new file mode 100644 index 0000000..7ba971e --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157a-dk1.dts @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include "stm32mp15xx-dkx.dtsi" + +/ { + model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; + compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; + + aliases { + ethernet0 = ðernet0; + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; + huk_otp: huk-otp@f0 { + reg = <0xf0 0x10>; + }; +}; + +&rcc { + status = "okay"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts new file mode 100644 index 0000000..a2e8e56 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2019-2020 Marek Vasut + * Copyright (C) 2022 DH electronics GmbH + * + * DHCOM STM32MP1 variant: + * DHCM-STM32MP157C-C065-R102-F0819-SPI-E2-CAN2-SDR104-RTC-WBT-T-DSI-I-01D2 + * DHCOM PCB number: 587-200 or newer + * PDK2 PCB number: 516-400 or newer + */ +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15xx-dhcom-som.dtsi" +#include "stm32mp15xx-dhcom-pdk2.dtsi" + +/ { + model = "DH electronics STM32MP157C DHCOM Premium Developer Kit (2)"; + compatible = "dh,stm32mp157c-dhcom-pdk2", "dh,stm32mp157c-dhcom-som", + "st,stm32mp157"; +}; + +&m_can1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&m_can1_pins_a>; + pinctrl-1 = <&m_can1_sleep_pins_a>; + status = "okay"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts new file mode 100644 index 0000000..b82730c --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-dk2.dts @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include "stm32mp15xx-dkx.dtsi" + +/ { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + + aliases { + ethernet0 = ðernet0; + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; + serial3 = &usart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; + huk_otp: huk-otp@f0 { + reg = <0xf0 0x10>; + }; +}; + +&dsi { + status = "disabled"; + phy-dsi-supply = <®18>; + + ports { + port@0 { + reg = <0>; + dsi_in: endpoint { + remote-endpoint = <<dc_ep1_out>; + }; + }; + + port@1 { + reg = <1>; + dsi_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; + + panel@0 { + compatible = "orisetech,otm8009a"; + reg = <0>; + reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; + power-supply = <&v3v3>; + status = "okay"; + + port { + panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; +}; + +&i2c1 { + touchscreen@38 { + compatible = "focaltech,ft6236"; + reg = <0x38>; + interrupts = <2 2>; + interrupt-parent = <&gpiof>; + interrupt-controller; + touchscreen-size-x = <480>; + touchscreen-size-y = <800>; + status = "okay"; + }; +}; + +<dc { + status = "disabled"; + + port { + ltdc_ep1_out: endpoint@1 { + reg = <1>; + remote-endpoint = <&dsi_in>; + }; + }; +}; + +&rcc { + status = "okay"; +}; + +&usart2 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&usart2_pins_c>; + pinctrl-1 = <&usart2_sleep_pins_c>; + pinctrl-2 = <&usart2_idle_pins_c>; + status = "disabled"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts new file mode 100644 index 0000000..1c5ab2d --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ed1.dts @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include +#include + +/ { + model = "STMicroelectronics STM32MP157C eval daughter"; + compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xC0000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + + gpu_reserved: gpu@e8000000 { + reg = <0xe8000000 0x8000000>; + no-map; + }; + }; + + aliases { + serial0 = &uart4; + }; + + sd_switch: regulator-sd_switch { + compatible = "regulator-gpio"; + regulator-name = "sd_switch"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2900000>; + regulator-type = "voltage"; + regulator-always-on; + + gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; + gpios-states = <0>; + states = <1800000 0x1>, + <2900000 0x0>; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; + +&adc { + /* ANA0, ANA1 are dedicated pins and don't need pinctrl: only in6. */ + pinctrl-0 = <&adc1_in6_pins_a>; + pinctrl-names = "default"; + vdd-supply = <&vdd>; + vdda-supply = <&vdda>; + vref-supply = <&vdda>; + status = "disabled"; + adc1: adc@0 { + st,adc-channels = <0 1 6>; + /* 16.5 ck_cycles sampling time */ + st,min-sample-time-nsecs = <400>; + status = "okay"; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; + huk_otp: huk-otp@f0 { + reg = <0xf0 0x10>; + }; +}; + +&crc1 { + status = "disabled"; +}; + +&dac { + pinctrl-names = "default"; + pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; + vref-supply = <&vdda>; + status = "disabled"; + dac1: dac@1 { + status = "okay"; + }; + dac2: dac@2 { + status = "okay"; + }; +}; + +&dts { + status = "disabled"; +}; + +&gpu { + contiguous-area = <&gpu_reserved>; +}; + +&hash1 { + status = "disabled"; +}; + +&i2c4 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c4_pins_a>; + pinctrl-1 = <&i2c4_sleep_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "okay"; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo4-supply = <&vin>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + vref_ddr-supply = <&vin>; + boost-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + interrupts = ; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + interrupts = ; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + regulator-boot-on; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + interrupts = ; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + interrupts = ; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + interrupts = ; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + interrupts = ; + regulator-active-discharge = <1>; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + interrupts = , ; + interrupt-names = "onkey-falling", "onkey-rising"; + power-off-time-sec = <10>; + status = "disabled"; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&ipcc { + status = "disabled"; +}; + +&iwdg1 { + timeout-sec = <32>; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "disabled"; +}; + +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>; + mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>; + mbox-names = "vq0", "vq1", "shutdown", "detach"; + interrupt-parent = <&exti>; + interrupts = <68 1>; + status = "disabled"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + status = "okay"; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "disabled"; +}; + +&sdmmc1 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; + pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; + pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; + cd-gpios = <&gpiog 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + disable-wp; + st,sig-dir; + st,neg-edge; + st,use-ckin; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + vqmmc-supply = <&sd_switch>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-ddr50; + status = "disabled"; +}; + +&sdmmc2 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; + pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; + pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; + non-removable; + no-sd; + no-sdio; + st,neg-edge; + bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&vdd>; + mmc-ddr-3_3v; + status = "disabled"; +}; + +&timers6 { + status = "disabled"; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + timer@5 { + status = "okay"; + }; +}; + +&uart4 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&uart4_pins_a>; + pinctrl-1 = <&uart4_sleep_pins_a>; + pinctrl-2 = <&uart4_idle_pins_a>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +&usbotg_hs { + vbus-supply = <&vbus_otg>; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1.dts b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1.dts new file mode 100644 index 0000000..a973a2d --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp157c-ev1.dts @@ -0,0 +1,393 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +/dts-v1/; + +#include "stm32mp157c-ed1.dts" +#include + +/ { + model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; + compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial0 = &uart4; + serial1 = &usart3; + ethernet0 = ðernet0; + }; + + clocks { + clk_ext_camera: clk-ext-camera { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + }; + + joystick { + compatible = "gpio-keys"; + pinctrl-0 = <&joystick_pins>; + pinctrl-names = "default"; + button-0 { + label = "JoySel"; + interrupt-parent = <&stmfx_pinctrl>; + interrupts = <0 IRQ_TYPE_EDGE_RISING>; + }; + button-1 { + label = "JoyDown"; + interrupt-parent = <&stmfx_pinctrl>; + interrupts = <1 IRQ_TYPE_EDGE_RISING>; + }; + button-2 { + label = "JoyLeft"; + interrupt-parent = <&stmfx_pinctrl>; + interrupts = <2 IRQ_TYPE_EDGE_RISING>; + }; + button-3 { + label = "JoyRight"; + interrupt-parent = <&stmfx_pinctrl>; + interrupts = <3 IRQ_TYPE_EDGE_RISING>; + }; + button-4 { + label = "JoyUp"; + interrupt-parent = <&stmfx_pinctrl>; + interrupts = <4 IRQ_TYPE_EDGE_RISING>; + }; + }; + + panel_backlight: panel-backlight { + compatible = "gpio-backlight"; + gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; + default-on; + status = "okay"; + }; +}; + +&cec { + pinctrl-names = "default"; + pinctrl-0 = <&cec_pins_a>; + status = "disabled"; +}; + +&dcmi { + status = "disabled"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&dcmi_pins_a>; + pinctrl-1 = <&dcmi_sleep_pins_a>; + + port { + dcmi_0: endpoint { + remote-endpoint = <&ov5640_0>; + bus-type = <5>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + pclk-sample = <1>; + }; + }; +}; + +&dsi { + phy-dsi-supply = <®18>; + status = "disabled"; + + ports { + port@0 { + reg = <0>; + dsi_in: endpoint { + remote-endpoint = <<dc_ep0_out>; + }; + }; + + port@1 { + reg = <1>; + dsi_out: endpoint { + remote-endpoint = <&dsi_panel_in>; + }; + }; + }; + + panel-dsi@0 { + compatible = "raydium,rm68200"; + reg = <0>; + reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; + backlight = <&panel_backlight>; + power-supply = <&v3v3>; + status = "okay"; + + port { + dsi_panel_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; +}; + +ðernet0 { + status = "disabled"; + pinctrl-0 = <ðernet0_rgmii_pins_a>; + pinctrl-1 = <ðernet0_rgmii_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + phy-mode = "rgmii-id"; + max-speed = <1000>; + phy-handle = <&phy0>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + +&fmc { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&fmc_pins_a>; + pinctrl-1 = <&fmc_sleep_pins_a>; + status = "disabled"; + + nand-controller@4,0 { + status = "okay"; + + nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; + #size-cells = <1>; + }; + }; +}; + +&i2c2 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c2_pins_a>; + pinctrl-1 = <&i2c2_sleep_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "disabled"; + + ov5640: camera@3c { + compatible = "ovti,ov5640"; + reg = <0x3c>; + clocks = <&clk_ext_camera>; + clock-names = "xclk"; + DOVDD-supply = <&v2v8>; + powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; + reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; + rotation = <180>; + status = "okay"; + + port { + ov5640_0: endpoint { + remote-endpoint = <&dcmi_0>; + bus-width = <8>; + data-shift = <2>; /* lines 9:2 are used */ + hsync-active = <0>; + vsync-active = <0>; + pclk-sample = <1>; + }; + }; + }; + + stmfx: stmfx@42 { + compatible = "st,stmfx-0300"; + reg = <0x42>; + interrupts = <8 IRQ_TYPE_EDGE_RISING>; + interrupt-parent = <&gpioi>; + vdd-supply = <&v3v3>; + + stmfx_pinctrl: pinctrl { + compatible = "st,stmfx-0300-pinctrl"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-ranges = <&stmfx_pinctrl 0 0 24>; + + joystick_pins: joystick-pins { + pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; + bias-pull-down; + }; + }; + }; +}; + +&i2c5 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c5_pins_a>; + pinctrl-1 = <&i2c5_sleep_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "disabled"; +}; + +<dc { + status = "disabled"; + + port { + ltdc_ep0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&dsi_in>; + }; + }; +}; + +&m_can1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&m_can1_pins_a>; + pinctrl-1 = <&m_can1_sleep_pins_a>; + status = "disabled"; +}; + +&qspi { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; + pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; + reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + flash0: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + flash1: flash@1 { + compatible = "jedec,spi-nor"; + reg = <1>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&sdmmc3 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc3_b4_pins_a>; + pinctrl-1 = <&sdmmc3_b4_od_pins_a>; + pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; + broken-cd; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "disabled"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins_a>; + status = "disabled"; +}; + +&timers2 { + /* spare dmas for other usage (un-delete to enable pwm capture) */ + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + pwm { + pinctrl-0 = <&pwm2_pins_a>; + pinctrl-1 = <&pwm2_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; + timer@1 { + status = "okay"; + }; +}; + +&timers8 { + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + pwm { + pinctrl-0 = <&pwm8_pins_a>; + pinctrl-1 = <&pwm8_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; + timer@7 { + status = "okay"; + }; +}; + +&timers12 { + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + pwm { + pinctrl-0 = <&pwm12_pins_a>; + pinctrl-1 = <&pwm12_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; + timer@11 { + status = "okay"; + }; +}; + +&usart3 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&usart3_pins_b>; + pinctrl-1 = <&usart3_sleep_pins_b>; + pinctrl-2 = <&usart3_idle_pins_b>; + /* + * HW flow control USART3_RTS is optional, and isn't default wired to + * the connector. SB23 needs to be soldered in order to use it, and R77 + * (ETH_CLK) should be removed. + */ + uart-has-rtscts; + status = "disabled"; +}; + +&usbh_ehci { + phys = <&usbphyc_port0>; + status = "disabled"; +}; + +&usbotg_hs { + pinctrl-0 = <&usbotg_hs_pins_a>; + pinctrl-names = "default"; + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + status = "disabled"; +}; + +&usbphyc { + status = "disabled"; +}; + +&usbphyc_port0 { + st,tune-hs-dc-level = <2>; + st,enable-fs-rftime-tuning; + st,enable-hs-rftime-reduction; + st,trim-hs-current = <15>; + st,trim-hs-impedance = <1>; + st,tune-squelch-level = <3>; + st,tune-hs-rx-offset = <2>; + st,no-lsfs-sc; +}; + +&usbphyc_port1 { + st,tune-hs-dc-level = <2>; + st,enable-fs-rftime-tuning; + st,enable-hs-rftime-reduction; + st,trim-hs-current = <15>; + st,trim-hs-impedance = <1>; + st,tune-squelch-level = <3>; + st,tune-hs-rx-offset = <2>; + st,no-lsfs-sc; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xc.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xc.dtsi new file mode 100644 index 0000000..b06a55a --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xc.dtsi @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { + soc { + cryp1: cryp@54001000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54001000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi new file mode 100644 index 0000000..f1ff04f --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2019-2020 Marek Vasut + * Copyright (C) 2022 DH electronics GmbH + */ + +/ { + aliases { + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart8; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + clk_ext_audio_codec: clock-codec { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + }; + + display_bl: display-bl { + compatible = "pwm-backlight"; + pwms = <&pwm2 3 500000 1>; + brightness-levels = <0 16 22 30 40 55 75 102 138 188 255>; + default-brightness-level = <8>; + enable-gpios = <&gpioi 0 GPIO_ACTIVE_HIGH>; + power-supply = <®_panel_bl>; + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + /* + * The EXTi IRQ line 3 is shared with ethernet, + * so mark this as polled GPIO key. + */ + button-0 { + label = "TA1-GPIO-A"; + gpios = <&gpiof 3 GPIO_ACTIVE_LOW>; + }; + + /* + * The EXTi IRQ line 6 is shared with touchscreen, + * so mark this as polled GPIO key. + */ + button-1 { + label = "TA2-GPIO-B"; + gpios = <&gpiod 6 GPIO_ACTIVE_LOW>; + }; + + /* + * The EXTi IRQ line 0 is shared with PMIC, + * so mark this as polled GPIO key. + */ + button-2 { + label = "TA3-GPIO-C"; + gpios = <&gpiog 0 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + button-3 { + label = "TA4-GPIO-D"; + gpios = <&gpiod 12 GPIO_ACTIVE_LOW>; + wakeup-source; + }; + }; + + led { + compatible = "gpio-leds"; + + led-0 { + label = "green:led5"; + gpios = <&gpioc 6 GPIO_ACTIVE_HIGH>; + default-state = "off"; + status = "disabled"; + }; + + led-1 { + label = "green:led6"; + gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-2 { + label = "green:led7"; + gpios = <&gpioi 2 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + led-3 { + label = "green:led8"; + gpios = <&gpioi 3 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + }; + + panel { + compatible = "edt,etm0700g0edh6"; + backlight = <&display_bl>; + power-supply = <®_panel_bl>; + + port { + lcd_panel_in: endpoint { + remote-endpoint = <&lcd_display_out>; + }; + }; + }; + + reg_panel_bl: regulator-panel-bl { + compatible = "regulator-fixed"; + regulator-name = "panel_backlight"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <®_panel_supply>; + }; + + reg_panel_supply: regulator-panel-supply { + compatible = "regulator-fixed"; + regulator-name = "panel_supply"; + regulator-min-microvolt = <24000000>; + regulator-max-microvolt = <24000000>; + }; + + sound { + compatible = "audio-graph-card"; + routing = + "MIC_IN", "Capture", + "Capture", "Mic Bias", + "Playback", "HP_OUT"; + dais = <&sai2a_port &sai2b_port>; + status = "okay"; + }; +}; + +&cec { + pinctrl-names = "default"; + pinctrl-0 = <&cec_pins_a>; + status = "okay"; +}; + +&i2c2 { /* Header X22 */ + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; +}; + +&i2c5 { /* Header X21 */ + pinctrl-names = "default"; + pinctrl-0 = <&i2c5_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + + sgtl5000: codec@a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + #sound-dai-cells = <0>; + clocks = <&clk_ext_audio_codec>; + VDDA-supply = <&v3v3>; + VDDIO-supply = <&vdd>; + + sgtl5000_port: port { + #address-cells = <1>; + #size-cells = <0>; + + sgtl5000_tx_endpoint: endpoint@0 { + reg = <0>; + remote-endpoint = <&sai2a_endpoint>; + frame-master = <&sgtl5000_tx_endpoint>; + bitclock-master = <&sgtl5000_tx_endpoint>; + }; + + sgtl5000_rx_endpoint: endpoint@1 { + reg = <1>; + remote-endpoint = <&sai2b_endpoint>; + frame-master = <&sgtl5000_rx_endpoint>; + bitclock-master = <&sgtl5000_rx_endpoint>; + }; + }; + + }; + + touchscreen@38 { + compatible = "edt,edt-ft5406"; + reg = <0x38>; + interrupt-parent = <&gpioc>; + interrupts = <6 IRQ_TYPE_EDGE_FALLING>; /* GPIO E */ + }; +}; + +<dc { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <<dc_pins_b>; + pinctrl-1 = <<dc_sleep_pins_b>; + status = "okay"; + + port { + lcd_display_out: endpoint { + remote-endpoint = <&lcd_panel_in>; + }; + }; +}; + +&sai2 { + clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; + clock-names = "pclk", "x8k", "x11k"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sai2a_pins_b &sai2b_pins_b>; + pinctrl-1 = <&sai2a_sleep_pins_b &sai2b_sleep_pins_b>; + status = "okay"; + + sai2a: audio-controller@4400b004 { + #clock-cells = <0>; + dma-names = "tx"; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + status = "okay"; + + sai2a_port: port { + sai2a_endpoint: endpoint { + remote-endpoint = <&sgtl5000_tx_endpoint>; + format = "i2s"; + mclk-fs = <512>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + }; + }; + + sai2b: audio-controller@4400b024 { + dma-names = "rx"; + st,sync = <&sai2a 2>; + clocks = <&rcc SAI2_K>, <&sai2a>; + clock-names = "sai_ck", "MCLK"; + status = "okay"; + + sai2b_port: port { + sai2b_endpoint: endpoint { + remote-endpoint = <&sgtl5000_rx_endpoint>; + format = "i2s"; + mclk-fs = <512>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <16>; + }; + }; + }; +}; + +&timers2 { + /* spare dmas for other usage (un-delete to enable pwm capture) */ + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; + pwm2: pwm { + pinctrl-0 = <&pwm2_pins_a>; + pinctrl-names = "default"; + status = "okay"; + }; + timer@1 { + status = "okay"; + }; +}; + +&usart3 { + pinctrl-names = "default"; + pinctrl-0 = <&usart3_pins_a>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +&uart8 { + pinctrl-names = "default"; + pinctrl-0 = <&uart8_pins_a &uart8_rtscts_pins_a>; + uart-has-rtscts; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +&usbh_ehci { + phys = <&usbphyc_port0>; + status = "okay"; +}; + +&usbotg_hs { + dr_mode = "otg"; + pinctrl-0 = <&usbotg_hs_pins_a>; + pinctrl-names = "default"; + phy-names = "usb2-phy"; + phys = <&usbphyc_port1 0>; + vbus-supply = <&vbus_otg>; + status = "okay"; +}; + +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi new file mode 100644 index 0000000..b4fc6da --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi @@ -0,0 +1,544 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) 2019-2020 Marek Vasut + * Copyright (C) 2022 DH electronics GmbH + */ + +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include +#include + +/ { + aliases { + ethernet0 = ðernet0; + ethernet1 = &ksz8851; + rtc0 = &hwrtc; + rtc1 = &rtc; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xC0000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + }; + + ethernet_vio: vioregulator { + compatible = "regulator-fixed"; + regulator-name = "vio"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpiog 3 GPIO_ACTIVE_LOW>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vdd>; + }; +}; + +&adc { + vdd-supply = <&vdd>; + vdda-supply = <&vdda>; + vref-supply = <&vdda>; + status = "okay"; + + adc1: adc@0 { + st,min-sample-time-nsecs = <5000>; + st,adc-channels = <0>; + status = "okay"; + }; + + adc2: adc@100 { + st,adc-channels = <1>; + st,min-sample-time-nsecs = <5000>; + status = "okay"; + }; +}; + +&crc1 { + status = "okay"; +}; + +&dac { + pinctrl-names = "default"; + pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; + vref-supply = <&vdda>; + status = "okay"; + + dac1: dac@1 { + status = "okay"; + }; + dac2: dac@2 { + status = "okay"; + }; +}; + +&dts { + status = "okay"; +}; + +ðernet0 { + status = "okay"; + pinctrl-0 = <ðernet0_rmii_pins_c &mco2_pins_a>; + pinctrl-1 = <ðernet0_rmii_sleep_pins_c &mco2_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + phy-mode = "rmii"; + max-speed = <100>; + phy-handle = <&phy0>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + + phy0: ethernet-phy@1 { + reg = <1>; + /* LAN8710Ai */ + compatible = "ethernet-phy-id0007.c0f0", + "ethernet-phy-ieee802.3-c22"; + clocks = <&rcc CK_MCO2>; + reset-gpios = <&gpioh 3 GPIO_ACTIVE_LOW>; + reset-assert-us = <500>; + reset-deassert-us = <500>; + smsc,disable-energy-detect; + interrupt-parent = <&gpioi>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + }; + }; +}; + +&fmc { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&fmc_pins_b>; + pinctrl-1 = <&fmc_sleep_pins_b>; + status = "okay"; + + ksz8851: ethernet@1,0 { + compatible = "micrel,ks8851-mll"; + reg = <1 0x0 0x2>, <1 0x2 0x20000>; + interrupt-parent = <&gpioc>; + interrupts = <3 IRQ_TYPE_LEVEL_LOW>; + bank-width = <2>; + + /* Timing values are in nS */ + st,fmc2-ebi-cs-mux-enable; + st,fmc2-ebi-cs-transaction-type = <4>; + st,fmc2-ebi-cs-buswidth = <16>; + st,fmc2-ebi-cs-address-setup-ns = <5>; + st,fmc2-ebi-cs-address-hold-ns = <5>; + st,fmc2-ebi-cs-bus-turnaround-ns = <5>; + st,fmc2-ebi-cs-data-setup-ns = <45>; + st,fmc2-ebi-cs-data-hold-ns = <1>; + st,fmc2-ebi-cs-write-address-setup-ns = <5>; + st,fmc2-ebi-cs-write-address-hold-ns = <5>; + st,fmc2-ebi-cs-write-bus-turnaround-ns = <5>; + st,fmc2-ebi-cs-write-data-setup-ns = <45>; + st,fmc2-ebi-cs-write-data-hold-ns = <1>; + }; +}; + +&gpioa { + gpio-line-names = "", "", "", "", + "", "", "DHCOM-K", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpiob { + gpio-line-names = "", "", "", "", + "", "", "", "", + "DHCOM-Q", "", "", "", + "", "", "", ""; +}; + +&gpioc { + gpio-line-names = "", "", "", "", + "", "", "DHCOM-E", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpiod { + gpio-line-names = "", "", "", "", + "", "", "DHCOM-B", "", + "", "", "", "DHCOM-F", + "DHCOM-D", "", "", ""; +}; + +&gpioe { + gpio-line-names = "", "", "", "", + "", "", "DHCOM-P", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpiof { + gpio-line-names = "", "", "", "DHCOM-A", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpiog { + gpio-line-names = "DHCOM-C", "", "", "", + "", "", "", "", + "DHCOM-L", "", "", "", + "", "", "", ""; +}; + +&gpioh { + gpio-line-names = "", "", "", "", + "", "", "", "DHCOM-N", + "DHCOM-J", "DHCOM-W", "DHCOM-V", "DHCOM-U", + "DHCOM-T", "", "DHCOM-S", ""; +}; + +&gpioi { + gpio-line-names = "DHCOM-G", "DHCOM-O", "DHCOM-H", "DHCOM-I", + "DHCOM-R", "DHCOM-M", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + + hwrtc: rtc@32 { + compatible = "microcrystal,rv8803"; + reg = <0x32>; + }; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-always-on; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + interrupts = ; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + interrupts = ; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + regulator-boot-on; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + interrupts = ; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + interrupts = ; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + interrupts = ; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + interrupts = ; + regulator-active-discharge = <1>; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + interrupts = , ; + interrupt-names = "onkey-falling", "onkey-rising"; + power-off-time-sec = <10>; + status = "okay"; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; + + touchscreen@49 { + compatible = "ti,tsc2004"; + reg = <0x49>; + vio-supply = <&v3v3>; + interrupts-extended = <&gpioh 15 IRQ_TYPE_EDGE_FALLING>; + }; + + eeprom@50 { + compatible = "atmel,24c02"; + reg = <0x50>; + pagesize = <16>; + }; +}; + +&ipcc { + status = "okay"; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "disabled"; +}; + +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>; + mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; + mbox-names = "vq0", "vq1", "shutdown"; + interrupt-parent = <&exti>; + interrupts = <68 1>; + status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&qspi { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>; + pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>; + reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash0: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&rcc { + /* Connect MCO2 output to ETH_RX_CLK input via pad-pad connection */ + /* clocks = <&rcc CK_MCO2>; Not supported in OP-TEE OS */ + /* clock-names = "ETH_RX_CLK/ETH_REF_CLK"; Not supported */ + + /* + * Set PLL4P output to 100 MHz to supply SDMMC with faster clock, + * set MCO2 output to 50 MHz to supply ETHRX clock with PLL4P/2, + * so that MCO2 behaves as a divider for the ETHRX clock here. + */ + /* assigned-clocks = <&rcc CK_MCO2>, <&rcc PLL4_P>; Not supported */ + /* assigned-clock-parents = <&rcc PLL4_P>; Not supported */ + /* assigned-clock-rates = <50000000>, <100000000>; Not supported */ + + status = "okay"; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default", "opendrain", "sleep", "init"; + pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; + pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; + pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; + pinctrl-3 = <&sdmmc1_b4_init_pins_a &sdmmc1_dir_init_pins_a>; + cd-gpios = <&gpiog 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + disable-wp; + st,sig-dir; + st,neg-edge; + st,use-ckin; + st,cmd-gpios = <&gpiod 2 0>; + st,ck-gpios = <&gpioc 12 0>; + st,ckin-gpios = <&gpioe 4 0>; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + status = "okay"; +}; + +&sdmmc1_b4_pins_a { + /* + * SD bus pull-up resistors: + * - optional on SoMs with SD voltage translator + * - mandatory on SoMs without SD voltage translator + */ + pins1 { + bias-pull-up; + }; + pins2 { + bias-pull-up; + }; +}; + +&sdmmc2 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; + pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; + pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; + non-removable; + no-sd; + no-sdio; + st,neg-edge; + bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&v3v3>; + mmc-ddr-3_3v; + status = "okay"; +}; + +&sdmmc3 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc3_b4_pins_a>; + pinctrl-1 = <&sdmmc3_b4_od_pins_a>; + pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; + broken-cd; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&v3v3>; + mmc-ddr-3_3v; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi new file mode 100644 index 0000000..76c54b0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* + * Copyright (C) Linaro Ltd 2019 - All Rights Reserved + * Author: Manivannan Sadhasivam + * Copyright (C) 2020 Marek Vasut + */ + +/* Avenger96 uses DHCOR SoM configured for 1V8 IO operation */ +#include "stm32mp15xx-dhcor-io1v8.dtsi" + +/ { + aliases { + ethernet0 = ðernet0; + mmc0 = &sdmmc1; + serial0 = &uart4; + serial1 = &uart7; + serial2 = &usart2; + spi0 = &qspi; + }; + + /* XTal Q1 */ + cec_clock: clk-cec-fixed { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <&adv7513_out>; + }; + }; + }; + + led { + compatible = "gpio-leds"; + led1 { + label = "green:user0"; + gpios = <&gpioz 7 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + }; + + led2 { + label = "green:user1"; + gpios = <&gpiof 3 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc0"; + default-state = "off"; + }; + + led3 { + label = "green:user2"; + gpios = <&gpiog 0 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "mmc1"; + default-state = "off"; + }; + + led4 { + label = "green:user3"; + gpios = <&gpiog 1 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "none"; + default-state = "off"; + panic-indicator; + }; + }; + + sd_switch: regulator-sd_switch { + compatible = "regulator-gpio"; + regulator-name = "sd_switch"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <2900000>; + regulator-type = "voltage"; + regulator-always-on; + + gpios = <&gpioi 5 GPIO_ACTIVE_HIGH>; + gpios-states = <0>; + states = <1800000 0x1>, + <2900000 0x0>; + }; + + sound { + compatible = "audio-graph-card"; + label = "STM32MP1-AV96-HDMI"; + dais = <&sai2a_port>; + status = "okay"; + }; + + wlan_pwr: regulator-wlan { + compatible = "regulator-fixed"; + + regulator-name = "wl-reg"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpioz 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; +}; + +&adc { + pinctrl-names = "default"; + pinctrl-0 = <&adc12_ain_pins_b>; + vdd-supply = <&vdd>; + vdda-supply = <&vdda>; + vref-supply = <&vdda>; + status = "okay"; + + adc1: adc@0 { + st,adc-channels = <0 1 6>; + st,min-sample-time-nsecs = <5000>; + status = "okay"; + }; + + adc2: adc@100 { + st,adc-channels = <0 1 2>; + st,min-sample-time-nsecs = <5000>; + status = "okay"; + }; +}; + +ðernet0 { + status = "okay"; + pinctrl-0 = <ðernet0_rgmii_pins_c>; + pinctrl-1 = <ðernet0_rgmii_sleep_pins_c>; + pinctrl-names = "default", "sleep"; + phy-mode = "rgmii"; + max-speed = <1000>; + phy-handle = <&phy0>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + reset-gpios = <&gpioz 2 GPIO_ACTIVE_LOW>; + reset-delay-us = <1000>; + reset-post-delay-us = <1000>; + + phy0: ethernet-phy@7 { + reg = <7>; + + rxc-skew-ps = <1500>; + rxdv-skew-ps = <540>; + rxd0-skew-ps = <420>; + rxd1-skew-ps = <420>; + rxd2-skew-ps = <420>; + rxd3-skew-ps = <420>; + + txc-skew-ps = <1440>; + txen-skew-ps = <540>; + txd0-skew-ps = <420>; + txd1-skew-ps = <420>; + txd2-skew-ps = <420>; + txd3-skew-ps = <420>; + }; + }; +}; + +&gpioa { + gpio-line-names = "", "", "", "", + "", "", "", "", + "", "", "", "AV96-K", + "AV96-I", "", "AV96-A", ""; +}; + +&gpiob { + gpio-line-names = "", "", "", "", + "", "AV96-J", "", "", + "", "", "", "AV96-B", + "", "AV96-L", "", ""; +}; + +&gpioc { + gpio-line-names = "", "", "", "AV96-C", + "", "", "", "", + "", "", "", "", + "", "", "", ""; +}; + +&gpiod { + gpio-line-names = "", "", "", "", + "", "", "", "", + "AV96-D", "", "", "", + "", "", "AV96-E", "AV96-F"; +}; + +&gpiof { + gpio-line-names = "", "", "", "", + "", "", "", "", + "", "", "", "", + "AV96-G", "AV96-H", "", ""; +}; + +&i2c1 { /* X6 I2C1 */ + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins_b>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /delete-property/dmas; + /delete-property/dma-names; +}; + +&i2c2 { /* X6 I2C2 */ + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_c>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /delete-property/dmas; + /delete-property/dma-names; +}; + +&i2c4 { + hdmi-transmitter@3d { + compatible = "adi,adv7513"; + reg = <0x3d>, <0x4d>, <0x2d>, <0x5d>; + reg-names = "main", "edid", "cec", "packet"; + clocks = <&cec_clock>; + clock-names = "cec"; + + avdd-supply = <&v3v3>; + dvdd-supply = <&v3v3>; + pvdd-supply = <&v3v3>; + dvdd-3v-supply = <&v3v3>; + bgvdd-supply = <&v3v3>; + + interrupts = <9 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpiog>; + + status = "okay"; + + adi,input-depth = <8>; + adi,input-colorspace = "rgb"; + adi,input-clock = "1x"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + adv7513_in: endpoint { + remote-endpoint = <<dc_ep0_out>; + }; + }; + + port@1 { + reg = <1>; + adv7513_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + + port@2 { + reg = <2>; + adv7513_i2s0: endpoint { + remote-endpoint = <&sai2a_endpoint>; + }; + }; + }; + }; +}; + +<dc { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <<dc_pins_d>; + pinctrl-1 = <<dc_sleep_pins_d>; + status = "okay"; + + port { + #address-cells = <1>; + #size-cells = <0>; + + ltdc_ep0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&adv7513_in>; + }; + }; +}; + +&sai2 { + clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sai2a_pins_c>; + pinctrl-1 = <&sai2a_sleep_pins_c>; + clock-names = "pclk", "x8k", "x11k"; + status = "okay"; + + sai2a: audio-controller@4400b004 { + #clock-cells = <0>; + dma-names = "tx"; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + status = "okay"; + + sai2a_port: port { + sai2a_endpoint: endpoint { + remote-endpoint = <&adv7513_i2s0>; + format = "i2s"; + mclk-fs = <256>; + }; + }; + }; +}; + +&sdmmc1 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_b>; + pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_b>; + pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_b>; + cd-gpios = <&gpioi 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + disable-wp; + st,sig-dir; + st,neg-edge; + st,use-ckin; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + vqmmc-supply = <&sd_switch>; + status = "okay"; +}; + +&sdmmc2 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_c>; + pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_c>; + pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_c>; + bus-width = <8>; + mmc-ddr-1_8v; + no-sd; + no-sdio; + non-removable; + st,neg-edge; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&vdd_io>; + status = "okay"; +}; + +&sdmmc3 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc3_b4_pins_b>; + pinctrl-1 = <&sdmmc3_b4_od_pins_b>; + pinctrl-2 = <&sdmmc3_b4_sleep_pins_b>; + broken-cd; + non-removable; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&wlan_pwr>; + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm4329-fmac"; + }; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&spi2_pins_a>; + cs-gpios = <&gpioi 0 0>; + status = "disabled"; + /delete-property/dmas; + /delete-property/dma-names; +}; + +&uart4 { + /* On Low speed expansion header */ + label = "LS-UART1"; + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_b>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +&uart7 { + /* On Low speed expansion header */ + label = "LS-UART0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + uart-has-rtscts; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +/* Bluetooth */ +&usart2 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&usart2_pins_a>; + pinctrl-1 = <&usart2_sleep_pins_a>; + st,hw-flow-ctrl; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <3000000>; + shutdown-gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>; + }; +}; + +&usbh_ehci { + phys = <&usbphyc_port0>; + phy-names = "usb"; + status = "okay"; +}; + +&usbotg_hs { + pinctrl-0 = <&usbotg_hs_pins_a>; + pinctrl-names = "default"; + phy-names = "usb2-phy"; + phys = <&usbphyc_port1 0>; + status = "okay"; + vbus-supply = <&vbus_otg>; +}; + +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi new file mode 100644 index 0000000..7517231 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* + * Copyright (C) Linaro Ltd 2019 - All Rights Reserved + * Author: Manivannan Sadhasivam + * Copyright (C) 2020 Marek Vasut + */ + +/ { + /* Enpirion EP3A8LQI U2 on the DHCOR */ + vdd_io: regulator-buck-io { + compatible = "regulator-fixed"; + regulator-name = "buck-io"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vdd>; + }; +}; + +&pwr_regulators { + vdd-supply = <&vdd_io>; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi new file mode 100644 index 0000000..312f387 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* + * Copyright (C) Linaro Ltd 2019 - All Rights Reserved + * Author: Manivannan Sadhasivam + * Copyright (C) 2020 Marek Vasut + * Copyright (C) 2022 DH electronics GmbH + */ + +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include +#include + +/ { + aliases { + spi0 = &qspi; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + }; +}; + +&crc1 { + status = "okay"; +}; + +&dts { + status = "okay"; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + /delete-property/dmas; + /delete-property/dma-names; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + interrupts = ; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + interrupts = ; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + regulator-boot-on; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + interrupts = ; + regulator-enable-ramp-delay = <300000>; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + interrupts = ; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + interrupts = ; + regulator-active-discharge = <1>; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + interrupts = ; + regulator-active-discharge = <1>; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + interrupts = , ; + interrupt-names = "onkey-falling", "onkey-rising"; + status = "okay"; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; + + eeprom@53 { + compatible = "atmel,24c02"; + reg = <0x53>; + pagesize = <16>; + }; +}; + +&ipcc { + status = "okay"; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "disabled"; +}; + +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>; + mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; + mbox-names = "vq0", "vq1", "shutdown"; + interrupt-parent = <&exti>; + interrupts = <68 1>; + status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&qspi { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>; + pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>; + reg = <0x58003000 0x1000>, <0x70000000 0x200000>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash0: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <50000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&rcc { + status = "okay"; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi new file mode 100644 index 0000000..cb4b6ac --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xx-dkx.dtsi @@ -0,0 +1,734 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include +#include + +/ { + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + mcuram2: mcuram2@10000000 { + compatible = "shared-dma-pool"; + reg = <0x10000000 0x40000>; + no-map; + }; + + vdev0vring0: vdev0vring0@10040000 { + compatible = "shared-dma-pool"; + reg = <0x10040000 0x1000>; + no-map; + }; + + vdev0vring1: vdev0vring1@10041000 { + compatible = "shared-dma-pool"; + reg = <0x10041000 0x1000>; + no-map; + }; + + vdev0buffer: vdev0buffer@10042000 { + compatible = "shared-dma-pool"; + reg = <0x10042000 0x4000>; + no-map; + }; + + mcuram: mcuram@30000000 { + compatible = "shared-dma-pool"; + reg = <0x30000000 0x40000>; + no-map; + }; + + retram: retram@38000000 { + compatible = "shared-dma-pool"; + reg = <0x38000000 0x10000>; + no-map; + }; + + gpu_reserved: gpu@d4000000 { + reg = <0xd4000000 0x4000000>; + no-map; + }; + }; + + led { + compatible = "gpio-leds"; + led-blue { + label = "heartbeat"; + gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + default-state = "off"; + status = "disabled"; + }; + }; + + sound { + compatible = "audio-graph-card"; + label = "STM32MP1-DK"; + routing = + "Playback" , "MCLK", + "Capture" , "MCLK", + "MICL" , "Mic Bias"; + dais = <&sai2a_port &sai2b_port &i2s2_port>; + status = "disabled"; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; + +&adc { + pinctrl-names = "default"; + pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; + vdd-supply = <&vdd>; + vdda-supply = <&vdd>; + vref-supply = <&vrefbuf>; + status = "disabled"; + adc1: adc@0 { + /* + * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19. + * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: + * 5 * (56 + 47kOhms) * 5pF => 2.5us. + * Use arbitrary margin here (e.g. 5us). + */ + st,min-sample-time-nsecs = <5000>; + /* AIN connector, USB Type-C CC1 & CC2 */ + st,adc-channels = <0 1 6 13 18 19>; + status = "okay"; + }; + adc2: adc@100 { + /* AIN connector, USB Type-C CC1 & CC2 */ + st,adc-channels = <0 1 2 6 18 19>; + st,min-sample-time-nsecs = <5000>; + status = "okay"; + }; +}; + +&cec { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cec_pins_b>; + pinctrl-1 = <&cec_sleep_pins_b>; + status = "disabled"; +}; + +&crc1 { + status = "disabled"; +}; + +&dts { + status = "disabled"; +}; + +ðernet0 { + status = "disabled"; + pinctrl-0 = <ðernet0_rgmii_pins_a>; + pinctrl-1 = <ðernet0_rgmii_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + phy-mode = "rgmii-id"; + max-speed = <1000>; + phy-handle = <&phy0>; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; +}; + +&gpu { + contiguous-area = <&gpu_reserved>; +}; + +&hash1 { + status = "disabled"; +}; + +&i2c1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c1_pins_a>; + pinctrl-1 = <&i2c1_sleep_pins_a>; + i2c-scl-rising-time-ns = <100>; + i2c-scl-falling-time-ns = <7>; + status = "disabled"; + /delete-property/dmas; + /delete-property/dma-names; + + hdmi-transmitter@39 { + compatible = "sil,sii9022"; + reg = <0x39>; + iovcc-supply = <&v3v3_hdmi>; + cvcc12-supply = <&v1v2_hdmi>; + reset-gpios = <&gpioa 10 GPIO_ACTIVE_LOW>; + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpiog>; + #sound-dai-cells = <0>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + sii9022_in: endpoint { + remote-endpoint = <<dc_ep0_out>; + }; + }; + + port@3 { + reg = <3>; + sii9022_tx_endpoint: endpoint { + remote-endpoint = <&i2s2_endpoint>; + }; + }; + }; + }; + + cs42l51: cs42l51@4a { + compatible = "cirrus,cs42l51"; + reg = <0x4a>; + #sound-dai-cells = <0>; + VL-supply = <&v3v3>; + VD-supply = <&v1v8_audio>; + VA-supply = <&v1v8_audio>; + VAHP-supply = <&v1v8_audio>; + reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; + clocks = <&sai2a>; + clock-names = "MCLK"; + status = "okay"; + + cs42l51_port: port { + #address-cells = <1>; + #size-cells = <0>; + + cs42l51_tx_endpoint: endpoint@0 { + reg = <0>; + remote-endpoint = <&sai2a_endpoint>; + frame-master = <&cs42l51_tx_endpoint>; + bitclock-master = <&cs42l51_tx_endpoint>; + }; + + cs42l51_rx_endpoint: endpoint@1 { + reg = <1>; + remote-endpoint = <&sai2b_endpoint>; + frame-master = <&cs42l51_rx_endpoint>; + bitclock-master = <&cs42l51_rx_endpoint>; + }; + }; + }; +}; + +&i2c4 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c4_pins_a>; + pinctrl-1 = <&i2c4_sleep_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "okay"; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + + stusb1600@28 { + compatible = "st,stusb1600"; + reg = <0x28>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + interrupt-parent = <&gpioi>; + pinctrl-names = "default"; + pinctrl-0 = <&stusb1600_pins_a>; + status = "okay"; + vdd-supply = <&vin>; + + connector { + compatible = "usb-c-connector"; + label = "USB-C"; + power-role = "dual"; + typec-power-opmode = "default"; + + port { + con_usbotg_hs_ep: endpoint { + remote-endpoint = <&usbotg_hs_ep>; + }; + }; + }; + }; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&v3v3>; + ldo2-supply = <&vin>; + ldo3-supply = <&vdd_ddr>; + ldo4-supply = <&vin>; + ldo5-supply = <&vin>; + ldo6-supply = <&v3v3>; + vref_ddr-supply = <&vin>; + boost-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + interrupts = ; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + interrupts = ; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + interrupts = ; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + interrupts = ; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + interrupts = ; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + interrupts = ; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + interrupts = ; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + interrupts = ; + regulator-active-discharge = <1>; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + interrupts = , ; + interrupt-names = "onkey-falling", "onkey-rising"; + power-off-time-sec = <10>; + status = "okay"; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&i2c5 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c5_pins_a>; + pinctrl-1 = <&i2c5_sleep_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; +}; + +&i2s2 { + clocks = <&rcc SPI2>, <&rcc SPI2_K>, <&rcc PLL3_Q>, <&rcc PLL3_R>; + clock-names = "pclk", "i2sclk", "x8k", "x11k"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2s2_pins_a>; + pinctrl-1 = <&i2s2_sleep_pins_a>; + status = "disabled"; + + i2s2_port: port { + i2s2_endpoint: endpoint { + remote-endpoint = <&sii9022_tx_endpoint>; + format = "i2s"; + mclk-fs = <256>; + }; + }; +}; + +&ipcc { + status = "disabled"; +}; + +&iwdg1 { + timeout-sec = <32>; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "disabled"; +}; + +<dc { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <<dc_pins_a>; + pinctrl-1 = <<dc_sleep_pins_a>; + status = "disabled"; + + port { + ltdc_ep0_out: endpoint@0 { + reg = <0>; + remote-endpoint = <&sii9022_in>; + }; + }; +}; + +&m4_rproc { + memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, + <&vdev0vring1>, <&vdev0buffer>; + mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>; + mbox-names = "vq0", "vq1", "shutdown", "detach"; + interrupt-parent = <&exti>; + interrupts = <68 1>; + status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sai2 { + clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; + clock-names = "pclk", "x8k", "x11k"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>; + pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>; + status = "disabled"; + + sai2a: audio-controller@4400b004 { + #clock-cells = <0>; + dma-names = "tx"; + clocks = <&rcc SAI2_K>; + clock-names = "sai_ck"; + status = "okay"; + + sai2a_port: port { + sai2a_endpoint: endpoint { + remote-endpoint = <&cs42l51_tx_endpoint>; + format = "i2s"; + mclk-fs = <256>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; + }; + }; + + sai2b: audio-controller@4400b024 { + dma-names = "rx"; + st,sync = <&sai2a 2>; + clocks = <&rcc SAI2_K>, <&sai2a>; + clock-names = "sai_ck", "MCLK"; + status = "okay"; + + sai2b_port: port { + sai2b_endpoint: endpoint { + remote-endpoint = <&cs42l51_rx_endpoint>; + format = "i2s"; + mclk-fs = <256>; + dai-tdm-slot-num = <2>; + dai-tdm-slot-width = <32>; + }; + }; + }; +}; + +&sdmmc1 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + pinctrl-1 = <&sdmmc1_b4_od_pins_a>; + pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>; + cd-gpios = <&gpiob 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "disabled"; +}; + +&sdmmc3 { + pinctrl-names = "default", "opendrain", "sleep"; + pinctrl-0 = <&sdmmc3_b4_pins_a>; + pinctrl-1 = <&sdmmc3_b4_od_pins_a>; + pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; + broken-cd; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "disabled"; +}; + +&timers1 { + /* spare dmas for other usage */ + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + pwm { + pinctrl-0 = <&pwm1_pins_a>; + pinctrl-1 = <&pwm1_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; + timer@0 { + status = "okay"; + }; +}; + +&timers3 { + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + pwm { + pinctrl-0 = <&pwm3_pins_a>; + pinctrl-1 = <&pwm3_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; + timer@2 { + status = "okay"; + }; +}; + +&timers4 { + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + pwm { + pinctrl-0 = <&pwm4_pins_a &pwm4_pins_b>; + pinctrl-1 = <&pwm4_sleep_pins_a &pwm4_sleep_pins_b>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; + timer@3 { + status = "okay"; + }; +}; + +&timers5 { + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + pwm { + pinctrl-0 = <&pwm5_pins_a>; + pinctrl-1 = <&pwm5_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; + timer@4 { + status = "okay"; + }; +}; + +&timers6 { + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + timer@5 { + status = "okay"; + }; +}; + +&timers12 { + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; + pwm { + pinctrl-0 = <&pwm12_pins_a>; + pinctrl-1 = <&pwm12_sleep_pins_a>; + pinctrl-names = "default", "sleep"; + status = "okay"; + }; + timer@11 { + status = "okay"; + }; +}; + +&uart4 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&uart4_pins_a>; + pinctrl-1 = <&uart4_sleep_pins_a>; + pinctrl-2 = <&uart4_idle_pins_a>; + /delete-property/dmas; + /delete-property/dma-names; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&uart7_pins_c>; + pinctrl-1 = <&uart7_sleep_pins_c>; + pinctrl-2 = <&uart7_idle_pins_c>; + /delete-property/dmas; + /delete-property/dma-names; + status = "disabled"; +}; + +&usart3 { + pinctrl-names = "default", "sleep", "idle"; + pinctrl-0 = <&usart3_pins_c>; + pinctrl-1 = <&usart3_sleep_pins_c>; + pinctrl-2 = <&usart3_idle_pins_c>; + uart-has-rtscts; + status = "disabled"; +}; + +&usbh_ehci { + phys = <&usbphyc_port0>; + status = "disabled"; +}; + +&usbotg_hs { + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + usb-role-switch; + status = "disabled"; + + port { + usbotg_hs_ep: endpoint { + remote-endpoint = <&con_usbotg_hs_ep>; + }; + }; +}; + +&usbphyc { + status = "disabled"; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; + st,tune-hs-dc-level = <2>; + st,enable-fs-rftime-tuning; + st,enable-hs-rftime-reduction; + st,trim-hs-current = <15>; + st,trim-hs-impedance = <1>; + st,tune-squelch-level = <3>; + st,tune-hs-rx-offset = <2>; + st,no-lsfs-sc; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; + st,tune-hs-dc-level = <2>; + st,enable-fs-rftime-tuning; + st,enable-hs-rftime-reduction; + st,trim-hs-current = <15>; + st,trim-hs-impedance = <1>; + st,tune-squelch-level = <3>; + st,tune-hs-rx-offset = <2>; + st,no-lsfs-sc; +}; + +&vrefbuf { + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + vdda-supply = <&vdd>; + status = "okay"; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi new file mode 100644 index 0000000..04f7a43 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 112 16>; + }; + + gpioi: gpio@5000a000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 128 16>; + }; + + gpioj: gpio@5000b000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 144 16>; + }; + + gpiok: gpio@5000c000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 160 8>; + }; +}; + +&pinctrl_z { + st,package = ; + + gpioz: gpio@54004000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl_z 0 400 8>; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi new file mode 100644 index 0000000..328dad1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <6>; + gpio-ranges = <&pinctrl 6 86 6>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl 6 102 10>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <2>; + gpio-ranges = <&pinctrl 0 112 2>; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi new file mode 100644 index 0000000..7eaa245 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 112 16>; + }; + + gpioi: gpio@5000a000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + st,package = ; + + gpioz: gpio@54004000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl_z 0 400 8>; + }; +}; diff --git a/optee/optee_os/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi b/optee/optee_os/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi new file mode 100644 index 0000000..b63e207 --- /dev/null +++ b/optee/optee_os/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <6>; + gpio-ranges = <&pinctrl 6 86 6>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl 6 102 10>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <2>; + gpio-ranges = <&pinctrl 0 112 2>; + }; +}; diff --git a/optee/optee_os/core/arch/arm/include/arm.h b/optee/optee_os/core/arch/arm/include/arm.h new file mode 100644 index 0000000..3ca2afa --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2019-2023, Arm Limited. All rights reserved. + */ +#ifndef ARM_H +#define ARM_H + +#include +#include +#include + +/* MIDR definitions */ +#define MIDR_PRIMARY_PART_NUM_SHIFT U(4) +#define MIDR_PRIMARY_PART_NUM_WIDTH U(12) +#define MIDR_PRIMARY_PART_NUM_MASK (BIT(MIDR_PRIMARY_PART_NUM_WIDTH) - 1) + +#define MIDR_IMPLEMENTER_SHIFT U(24) +#define MIDR_IMPLEMENTER_WIDTH U(8) +#define MIDR_IMPLEMENTER_MASK (BIT(MIDR_IMPLEMENTER_WIDTH) - 1) +#define MIDR_IMPLEMENTER_ARM U(0x41) + +#define MIDR_VARIANT_SHIFT U(20) +#define MIDR_VARIANT_WIDTH U(4) +#define MIDR_VARIANT_MASK (BIT(MIDR_VARIANT_WIDTH) - 1) + +#define MIDR_REVISION_SHIFT U(0) +#define MIDR_REVISION_WIDTH U(4) +#define MIDR_REVISION_MASK (BIT(MIDR_REVISION_WIDTH) - 1) + +#define CORTEX_A5_PART_NUM U(0xC05) +#define CORTEX_A7_PART_NUM U(0xC07) +#define CORTEX_A8_PART_NUM U(0xC08) +#define CORTEX_A9_PART_NUM U(0xC09) +#define CORTEX_A15_PART_NUM U(0xC0F) +#define CORTEX_A17_PART_NUM U(0xC0E) +#define CORTEX_A57_PART_NUM U(0xD07) +#define CORTEX_A72_PART_NUM U(0xD08) +#define CORTEX_A73_PART_NUM U(0xD09) +#define CORTEX_A75_PART_NUM U(0xD0A) +#define CORTEX_A65_PART_NUM U(0xD06) +#define CORTEX_A65AE_PART_NUM U(0xD43) +#define CORTEX_A76_PART_NUM U(0xD0B) +#define CORTEX_A76AE_PART_NUM U(0xD0E) +#define CORTEX_A77_PART_NUM U(0xD0D) +#define CORTEX_A78_PART_NUM U(0xD41) +#define CORTEX_A78AE_PART_NUM U(0xD42) +#define CORTEX_A78C_PART_NUM U(0xD4B) +#define CORTEX_A710_PART_NUM U(0xD47) +#define CORTEX_X1_PART_NUM U(0xD44) +#define CORTEX_X2_PART_NUM U(0xD48) +#define NEOVERSE_E1_PART_NUM U(0xD4A) +#define NEOVERSE_N1_PART_NUM U(0xD0C) +#define NEOVERSE_N2_PART_NUM U(0xD49) +#define NEOVERSE_V1_PART_NUM U(0xD40) + +/* MPIDR definitions */ +#define MPIDR_AFFINITY_BITS U(8) +#define MPIDR_AFFLVL_MASK U(0xff) +#define MPIDR_AFF0_SHIFT U(0) +#define MPIDR_AFF0_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT) +#define MPIDR_AFF1_SHIFT U(8) +#define MPIDR_AFF1_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) +#define MPIDR_AFF2_SHIFT U(16) +#define MPIDR_AFF2_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT) + +#define MPIDR_MT_SHIFT U(24) +#define MPIDR_MT_MASK BIT(MPIDR_MT_SHIFT) + +#define MPIDR_CPU_MASK MPIDR_AFF0_MASK +#define MPIDR_CLUSTER_SHIFT MPIDR_AFF1_SHIFT +#define MPIDR_CLUSTER_MASK MPIDR_AFF1_MASK + +#define MPIDR_AARCH32_AFF_MASK (MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | \ + MPIDR_AFF2_MASK) + +/* CLIDR definitions */ +#define CLIDR_LOUIS_SHIFT U(21) +#define CLIDR_LOC_SHIFT U(24) +#define CLIDR_FIELD_WIDTH U(3) + +/* CSSELR definitions */ +#define CSSELR_LEVEL_SHIFT U(1) + +/* CTR definitions */ +#define CTR_CWG_SHIFT U(24) +#define CTR_CWG_MASK U(0xf) +#define CTR_ERG_SHIFT U(20) +#define CTR_ERG_MASK U(0xf) +#define CTR_DMINLINE_SHIFT U(16) +#define CTR_DMINLINE_WIDTH U(4) +#define CTR_DMINLINE_MASK (BIT(4) - 1) +#define CTR_L1IP_SHIFT U(14) +#define CTR_L1IP_MASK U(0x3) +#define CTR_IMINLINE_SHIFT U(0) +#define CTR_IMINLINE_MASK U(0xf) +#define CTR_WORD_SIZE U(4) + +#define ARM32_CPSR_MODE_MASK U(0x1f) +#define ARM32_CPSR_MODE_USR U(0x10) +#define ARM32_CPSR_MODE_FIQ U(0x11) +#define ARM32_CPSR_MODE_IRQ U(0x12) +#define ARM32_CPSR_MODE_SVC U(0x13) +#define ARM32_CPSR_MODE_MON U(0x16) +#define ARM32_CPSR_MODE_ABT U(0x17) +#define ARM32_CPSR_MODE_UND U(0x1b) +#define ARM32_CPSR_MODE_SYS U(0x1f) + +#define ARM32_CPSR_T BIT(5) +#define ARM32_CPSR_F_SHIFT U(6) +#define ARM32_CPSR_F BIT(6) +#define ARM32_CPSR_I BIT(7) +#define ARM32_CPSR_A BIT(8) +#define ARM32_CPSR_E BIT(9) +#define ARM32_CPSR_FIA (ARM32_CPSR_F | ARM32_CPSR_I | ARM32_CPSR_A) +#define ARM32_CPSR_IT_MASK (ARM32_CPSR_IT_MASK1 | ARM32_CPSR_IT_MASK2) +#define ARM32_CPSR_IT_MASK1 U(0x06000000) +#define ARM32_CPSR_IT_MASK2 U(0x0000fc00) + +/* ARM Generic timer definitions */ +#define CNTKCTL_PL0PCTEN BIT(0) /* physical counter el0 access enable */ +#define CNTKCTL_PL0VCTEN BIT(1) /* virtual counter el0 access enable */ + +#ifdef ARM32 +#include +#endif + +#ifdef ARM64 +#include +#endif + +#ifndef __ASSEMBLER__ +static inline __noprof uint64_t barrier_read_counter_timer(void) +{ + isb(); +#ifdef CFG_CORE_SEL2_SPMC + return read_cntvct(); +#else + return read_cntpct(); +#endif +} + +static inline bool feat_bti_is_implemented(void) +{ +#ifdef ARM32 + return false; +#else + return ((read_id_aa64pfr1_el1() & ID_AA64PFR1_EL1_BT_MASK) == + FEAT_BTI_IMPLEMENTED); +#endif +} + +static inline unsigned int feat_mte_implemented(void) +{ +#ifdef ARM32 + return 0; +#else + return (read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) & + ID_AA64PFR1_EL1_MTE_MASK; +#endif +} + +static inline bool feat_crc32_implemented(void) +{ +#ifdef ARM32 + return false; +#else + return ((read_id_aa64isar0_el1() >> ID_AA64ISAR0_EL1_CRC32_SHIFT) & + ID_AA64ISAR0_EL1_CRC32_MASK) == FEAT_CRC32_IMPLEMENTED; +#endif +} + +static inline bool feat_pauth_is_implemented(void) +{ +#ifdef ARM32 + return false; +#else + uint64_t mask = + SHIFT_U64(ID_AA64ISAR1_GPI_MASK, ID_AA64ISAR1_GPI_SHIFT) | + SHIFT_U64(ID_AA64ISAR1_GPA_MASK, ID_AA64ISAR1_GPA_SHIFT) | + SHIFT_U64(ID_AA64ISAR1_API_MASK, ID_AA64ISAR1_API_SHIFT) | + SHIFT_U64(ID_AA64ISAR1_APA_MASK, ID_AA64ISAR1_APA_SHIFT); + + /* If any of the fields is not zero, PAuth is implemented by arch */ + return (read_id_aa64isar1_el1() & mask) != 0U; +#endif +} + +#endif + +#endif /*ARM_H*/ diff --git a/optee/optee_os/core/arch/arm/include/arm32.h b/optee/optee_os/core/arch/arm/include/arm32.h new file mode 100644 index 0000000..253b197 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm32.h @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef ARM32_H +#define ARM32_H + +#include +#include +#include +#include + +#define CPSR_MODE_MASK ARM32_CPSR_MODE_MASK +#define CPSR_MODE_USR ARM32_CPSR_MODE_USR +#define CPSR_MODE_FIQ ARM32_CPSR_MODE_FIQ +#define CPSR_MODE_IRQ ARM32_CPSR_MODE_IRQ +#define CPSR_MODE_SVC ARM32_CPSR_MODE_SVC +#define CPSR_MODE_MON ARM32_CPSR_MODE_MON +#define CPSR_MODE_ABT ARM32_CPSR_MODE_ABT +#define CPSR_MODE_UND ARM32_CPSR_MODE_UND +#define CPSR_MODE_SYS ARM32_CPSR_MODE_SYS + +#define CPSR_T ARM32_CPSR_T +#define CPSR_F_SHIFT ARM32_CPSR_F_SHIFT +#define CPSR_F ARM32_CPSR_F +#define CPSR_I ARM32_CPSR_I +#define CPSR_A ARM32_CPSR_A +#define CPSR_FIA ARM32_CPSR_FIA +#define CPSR_IT_MASK ARM32_CPSR_IT_MASK +#define CPSR_IT_MASK1 ARM32_CPSR_IT_MASK1 +#define CPSR_IT_MASK2 ARM32_CPSR_IT_MASK2 + +#define PMCR_DP BIT32(5) + +#define SCR_NS BIT32(0) +#define SCR_IRQ BIT32(1) +#define SCR_FIQ BIT32(2) +#define SCR_EA BIT32(3) +#define SCR_FW BIT32(4) +#define SCR_AW BIT32(5) +#define SCR_NET BIT32(6) +#define SCR_SCD BIT32(7) +#define SCR_HCE BIT32(8) +#define SCR_SIF BIT32(9) + +#define SCTLR_M BIT32(0) +#define SCTLR_A BIT32(1) +#define SCTLR_C BIT32(2) +#define SCTLR_CP15BEN BIT32(5) +#define SCTLR_SW BIT32(10) +#define SCTLR_Z BIT32(11) +#define SCTLR_I BIT32(12) +#define SCTLR_V BIT32(13) +#define SCTLR_RR BIT32(14) +#define SCTLR_HA BIT32(17) +#define SCTLR_WXN BIT32(19) +#define SCTLR_UWXN BIT32(20) +#define SCTLR_FI BIT32(21) +#define SCTLR_SPAN BIT32(23) +#define SCTLR_VE BIT32(24) +#define SCTLR_EE BIT32(25) +#define SCTLR_NMFI BIT32(27) +#define SCTLR_TRE BIT32(28) +#define SCTLR_AFE BIT32(29) +#define SCTLR_TE BIT32(30) + +/* Only valid for Cortex-A15 */ +#define ACTLR_CA15_ENABLE_INVALIDATE_BTB BIT(0) +/* Only valid for Cortex-A8 */ +#define ACTLR_CA8_ENABLE_INVALIDATE_BTB BIT(6) +/* Only valid for Cortex-A9 */ +#define ACTLR_CA9_WFLZ BIT(3) + +#define ACTLR_SMP BIT32(6) + +#define NSACR_CP10 BIT32(10) +#define NSACR_CP11 BIT32(11) +#define NSACR_NSD32DIS BIT32(14) +#define NSACR_NSASEDIS BIT32(15) +#define NSACR_NS_L2ERR BIT32(17) +#define NSACR_NS_SMP BIT32(18) + +#define CPACR_ASEDIS BIT32(31) +#define CPACR_D32DIS BIT32(30) +#define CPACR_CP(co_proc, access) SHIFT_U32((access), ((co_proc) * 2)) +#define CPACR_CP_ACCESS_DENIED U(0x0) +#define CPACR_CP_ACCESS_PL1_ONLY U(0x1) +#define CPACR_CP_ACCESS_FULL U(0x3) + + +#define DACR_DOMAIN(num, perm) SHIFT_U32((perm), ((num) * 2)) +#define DACR_DOMAIN_PERM_NO_ACCESS U(0x0) +#define DACR_DOMAIN_PERM_CLIENT U(0x1) +#define DACR_DOMAIN_PERM_MANAGER U(0x3) + +#define PAR_F BIT32(0) +#define PAR_SS BIT32(1) +#define PAR_LPAE BIT32(11) +#define PAR_PA_SHIFT U(12) +#define PAR32_PA_MASK (BIT32(20) - 1) +#define PAR64_PA_MASK (BIT64(28) - 1) + +/* + * TTBCR has different register layout if LPAE is enabled or not. + * TTBCR.EAE == 0 => LPAE is not enabled + * TTBCR.EAE == 1 => LPAE is enabled + */ +#define TTBCR_EAE BIT32(31) + +/* When TTBCR.EAE == 0 */ +#define TTBCR_PD0 BIT32(4) +#define TTBCR_PD1 BIT32(5) + +/* When TTBCR.EAE == 1 */ +#define TTBCR_T0SZ_SHIFT U(0) +#define TTBCR_EPD0 BIT32(7) +#define TTBCR_IRGN0_SHIFT U(8) +#define TTBCR_ORGN0_SHIFT U(10) +#define TTBCR_SH0_SHIFT U(12) +#define TTBCR_T1SZ_SHIFT U(16) +#define TTBCR_A1 BIT32(22) +#define TTBCR_EPD1 BIT32(23) +#define TTBCR_IRGN1_SHIFT U(24) +#define TTBCR_ORGN1_SHIFT U(26) +#define TTBCR_SH1_SHIFT U(28) + +/* Normal memory, Inner/Outer Non-cacheable */ +#define TTBCR_XRGNX_NC U(0x0) +/* Normal memory, Inner/Outer Write-Back Write-Allocate Cacheable */ +#define TTBCR_XRGNX_WB U(0x1) +/* Normal memory, Inner/Outer Write-Through Cacheable */ +#define TTBCR_XRGNX_WT U(0x2) +/* Normal memory, Inner/Outer Write-Back no Write-Allocate Cacheable */ +#define TTBCR_XRGNX_WBWA U(0x3) + +/* Non-shareable */ +#define TTBCR_SHX_NSH U(0x0) +/* Outer Shareable */ +#define TTBCR_SHX_OSH U(0x2) +/* Inner Shareable */ +#define TTBCR_SHX_ISH U(0x3) + +#define TTBR_ASID_MASK U(0xff) +#define TTBR_ASID_SHIFT U(48) + +#define TLBI_MVA_SHIFT U(12) +#define TLBI_ASID_MASK U(0xff) + +#define FSR_LPAE BIT32(9) +#define FSR_WNR BIT32(11) + +/* Valid if FSR.LPAE is 1 */ +#define FSR_STATUS_MASK (BIT32(6) - 1) + +/* Valid if FSR.LPAE is 0 */ +#define FSR_FS_MASK (BIT32(10) | (BIT32(4) - 1)) + +/* ID_PFR1 bit fields */ +#define IDPFR1_VIRT_SHIFT U(12) +#define IDPFR1_VIRT_MASK SHIFT_U32(0xF, IDPFR1_VIRT_SHIFT) +#define IDPFR1_GENTIMER_SHIFT U(16) +#define IDPFR1_GENTIMER_MASK SHIFT_U32(0xF, IDPFR1_GENTIMER_SHIFT) + +#ifndef __ASSEMBLER__ +#include +#ifdef CFG_ARM_GICV3 +#include +#endif + +static inline __noprof void isb(void) +{ + asm volatile ("isb" : : : "memory"); +} + +static inline __noprof void dsb(void) +{ + asm volatile ("dsb" : : : "memory"); +} + +static inline __noprof void dsb_ish(void) +{ + asm volatile ("dsb ish" : : : "memory"); +} + +static inline __noprof void dsb_ishst(void) +{ + asm volatile ("dsb ishst" : : : "memory"); +} + +static inline __noprof void dmb(void) +{ + asm volatile ("dmb" : : : "memory"); +} + +static inline __noprof void sev(void) +{ + asm volatile ("sev" : : : "memory"); +} + +static inline __noprof void wfe(void) +{ + asm volatile ("wfe" : : : "memory"); +} + +static inline __noprof uint32_t read_cpsr(void) +{ + uint32_t cpsr; + + asm volatile ("mrs %[cpsr], cpsr" + : [cpsr] "=r" (cpsr) + ); + return cpsr; +} + +static inline __noprof void write_cpsr(uint32_t cpsr) +{ + asm volatile ("msr cpsr_fsxc, %[cpsr]" + : : [cpsr] "r" (cpsr) + ); +} + +static inline __noprof uint32_t read_spsr(void) +{ + uint32_t spsr; + + asm volatile ("mrs %[spsr], spsr" + : [spsr] "=r" (spsr) + ); + return spsr; +} + +static inline __noprof void wfi(void) +{ + asm volatile("wfi" : : : "memory"); +} + +static __always_inline __noprof uint32_t read_pc(void) +{ + uint32_t val; + + asm volatile ("adr %0, ." : "=r" (val)); + return val; +} + +static __always_inline __noprof uint32_t read_sp(void) +{ + uint32_t val; + + asm volatile ("mov %0, sp" : "=r" (val)); + return val; +} + +static __always_inline __noprof uint32_t read_lr(void) +{ + uint32_t val; + + asm volatile ("mov %0, lr" : "=r" (val)); + return val; +} + +static __always_inline __noprof uint32_t read_fp(void) +{ + uint32_t val; + + asm volatile ("mov %0, fp" : "=r" (val)); + return val; +} + +static __always_inline __noprof uint32_t read_r7(void) +{ + uint32_t val; + + asm volatile ("mov %0, r7" : "=r" (val)); + return val; +} + +#endif /*__ASSEMBLER__*/ + +#endif /*ARM32_H*/ diff --git a/optee/optee_os/core/arch/arm/include/arm32_macros.S b/optee/optee_os/core/arch/arm/include/arm32_macros.S new file mode 100644 index 0000000..95077a0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm32_macros.S @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#ifdef CFG_ARM_GICV3 +#include +#endif + + .macro mov_imm reg, val + .if ((\val) & 0xffff0000) == 0 + movw \reg, #(\val) + .else + movw \reg, #((\val) & 0xffff) + movt \reg, #((\val) >> 16) + .endif + .endm + + .macro panic_at_smc_return +#if defined(CFG_TEE_CORE_DEBUG) + bl __panic_at_smc_return +#else + b . +#endif + .endm diff --git a/optee/optee_os/core/arch/arm/include/arm32_macros_cortex_a9.S b/optee/optee_os/core/arch/arm/include/arm32_macros_cortex_a9.S new file mode 100644 index 0000000..4960e9f --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm32_macros_cortex_a9.S @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Peng Fan + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 write_pcr reg + mcr p15, 0, \reg, c15, c0, 0 + .endm + + .macro read_pcr reg + mrc p15, 0, \reg, c15, c0, 0 + .endm + + .macro write_diag reg + mcr p15, 0, \reg, c15, c0, 1 + .endm + + .macro read_diag reg + mrc p15, 0, \reg, c15, c0, 1 + .endm diff --git a/optee/optee_os/core/arch/arm/include/arm64.h b/optee/optee_os/core/arch/arm/include/arm64.h new file mode 100644 index 0000000..2655c17 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm64.h @@ -0,0 +1,466 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2023, Arm Limited + */ +#ifndef ARM64_H +#define ARM64_H + +#include +#include +#include +#include + +#define SCTLR_M BIT64(0) +#define SCTLR_A BIT64(1) +#define SCTLR_C BIT64(2) +#define SCTLR_SA BIT64(3) +#define SCTLR_I BIT64(12) +#define SCTLR_ENDB BIT64(13) +#define SCTLR_WXN BIT64(19) +#define SCTLR_SPAN BIT64(23) +#define SCTLR_ENDA BIT64(27) +#define SCTLR_ENIB BIT64(30) +#define SCTLR_ENIA BIT64(31) +#define SCTLR_BT0 BIT64(35) +#define SCTLR_BT1 BIT64(36) +#define SCTLR_ITFSB BIT64(37) + +#define SCTLR_TCF_MASK SHIFT_U64(0x3, 40) +#define SCTLR_TCF_NONE SHIFT_U64(0x0, 40) +#define SCTLR_TCF_SYNC SHIFT_U64(0x1, 40) +#define SCTLR_TCF_ASYNC SHIFT_U64(0x2, 40) +#define SCTLR_TCF_ASYMM SHIFT_U64(0x3, 40) + +#define SCTLR_TCF0_MASK SHIFT_U64(0x3, 38) +#define SCTLR_TCF0_NONE SHIFT_U64(0x0, 38) +#define SCTLR_TCF0_SYNC SHIFT_U64(0x1, 38) +#define SCTLR_TCF0_ASYNC SHIFT_U64(0x2, 38) +#define SCTLR_TCF0_ASYMM SHIFT_U64(0x3, 38) + +#define SCTLR_ATA0 BIT64(42) +#define SCTLR_ATA BIT64(43) + +#define TTBR_ASID_MASK U(0xff) +#define TTBR_ASID_SHIFT U(48) + +#define CLIDR_LOUIS_SHIFT U(21) +#define CLIDR_LOC_SHIFT U(24) +#define CLIDR_FIELD_WIDTH U(3) + +#define CSSELR_LEVEL_SHIFT U(1) + +#define DAIFBIT_FIQ BIT32(0) +#define DAIFBIT_IRQ BIT32(1) +#define DAIFBIT_ABT BIT32(2) +#define DAIFBIT_DBG BIT32(3) +#define DAIFBIT_ALL (DAIFBIT_FIQ | DAIFBIT_IRQ | \ + DAIFBIT_ABT | DAIFBIT_DBG) + +#define DAIF_F_SHIFT U(6) +#define DAIF_F BIT32(6) +#define DAIF_I BIT32(7) +#define DAIF_A BIT32(8) +#define DAIF_D BIT32(9) +#define DAIF_AIF (DAIF_A | DAIF_I | DAIF_F) + +#define SPSR_MODE_RW_SHIFT U(4) +#define SPSR_MODE_RW_MASK U(0x1) +#define SPSR_MODE_RW_64 U(0x0) +#define SPSR_MODE_RW_32 U(0x1) + +#define SPSR_64_MODE_SP_SHIFT U(0) +#define SPSR_64_MODE_SP_MASK U(0x1) +#define SPSR_64_MODE_SP_EL0 U(0x0) +#define SPSR_64_MODE_SP_ELX U(0x1) + +#define SPSR_64_MODE_EL_SHIFT U(2) +#define SPSR_64_MODE_EL_MASK U(0x3) +#define SPSR_64_MODE_EL1 U(0x1) +#define SPSR_64_MODE_EL0 U(0x0) + +#define SPSR_64_DAIF_SHIFT U(6) +#define SPSR_64_DAIF_MASK U(0xf) + +#define SPSR_32_AIF_SHIFT U(6) +#define SPSR_32_AIF_MASK U(0x7) + +#define SPSR_32_E_SHIFT U(9) +#define SPSR_32_E_MASK U(0x1) +#define SPSR_32_E_LITTLE U(0x0) +#define SPSR_32_E_BIG U(0x1) + +#define SPSR_32_T_SHIFT U(5) +#define SPSR_32_T_MASK U(0x1) +#define SPSR_32_T_ARM U(0x0) +#define SPSR_32_T_THUMB U(0x1) + +#define SPSR_32_MODE_SHIFT U(0) +#define SPSR_32_MODE_MASK U(0xf) +#define SPSR_32_MODE_USR U(0x0) + + +#define SPSR_64(el, sp, daif) \ + (SPSR_MODE_RW_64 << SPSR_MODE_RW_SHIFT | \ + ((el) & SPSR_64_MODE_EL_MASK) << SPSR_64_MODE_EL_SHIFT | \ + ((sp) & SPSR_64_MODE_SP_MASK) << SPSR_64_MODE_SP_SHIFT | \ + ((daif) & SPSR_64_DAIF_MASK) << SPSR_64_DAIF_SHIFT) + +#define SPSR_32(mode, isa, aif) \ + (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT | \ + SPSR_32_E_LITTLE << SPSR_32_E_SHIFT | \ + ((mode) & SPSR_32_MODE_MASK) << SPSR_32_MODE_SHIFT | \ + ((isa) & SPSR_32_T_MASK) << SPSR_32_T_SHIFT | \ + ((aif) & SPSR_32_AIF_MASK) << SPSR_32_AIF_SHIFT) + + +#define TCR_T0SZ_SHIFT U(0) +#define TCR_EPD0 BIT64(7) +#define TCR_IRGN0_SHIFT U(8) +#define TCR_ORGN0_SHIFT U(10) +#define TCR_SH0_SHIFT U(12) +#define TCR_T1SZ_SHIFT U(16) +#define TCR_A1 BIT64(22) +#define TCR_EPD1 BIT64(23) +#define TCR_IRGN1_SHIFT U(24) +#define TCR_ORGN1_SHIFT U(26) +#define TCR_SH1_SHIFT U(28) +#define TCR_EL1_IPS_SHIFT U(32) +#define TCR_EL1_IPS_MASK UINT64_C(0x7) +#define TCR_TG1_4KB SHIFT_U64(2, 30) +#define TCR_RES1 BIT64(31) +#define TCR_TBI0 BIT64(37) +#define TCR_TBI1 BIT64(38) +#define TCR_TCMA0 BIT64(57) +#define TCR_TCMA1 BIT64(58) + + +/* Normal memory, Inner/Outer Non-cacheable */ +#define TCR_XRGNX_NC U(0x0) +/* Normal memory, Inner/Outer Write-Back Write-Allocate Cacheable */ +#define TCR_XRGNX_WB U(0x1) +/* Normal memory, Inner/Outer Write-Through Cacheable */ +#define TCR_XRGNX_WT U(0x2) +/* Normal memory, Inner/Outer Write-Back no Write-Allocate Cacheable */ +#define TCR_XRGNX_WBWA U(0x3) + +/* Non-shareable */ +#define TCR_SHX_NSH U(0x0) +/* Outer Shareable */ +#define TCR_SHX_OSH U(0x2) +/* Inner Shareable */ +#define TCR_SHX_ISH U(0x3) + +#define ESR_EC_SHIFT U(26) +#define ESR_EC_MASK U(0x3f) + +#define ESR_EC_UNKNOWN U(0x00) +#define ESR_EC_WFI U(0x01) +#define ESR_EC_AARCH32_CP15_32 U(0x03) +#define ESR_EC_AARCH32_CP15_64 U(0x04) +#define ESR_EC_AARCH32_CP14_MR U(0x05) +#define ESR_EC_AARCH32_CP14_LS U(0x06) +#define ESR_EC_FP_ASIMD U(0x07) +#define ESR_EC_AARCH32_CP10_ID U(0x08) +#define ESR_EC_PAUTH U(0x09) +#define ESR_EC_AARCH32_CP14_64 U(0x0c) +#define ESR_EC_BTI U(0x0d) +#define ESR_EC_ILLEGAL U(0x0e) +#define ESR_EC_AARCH32_SVC U(0x11) +#define ESR_EC_AARCH64_SVC U(0x15) +#define ESR_EC_AARCH64_SYS U(0x18) +#define ESR_EC_ERET U(0x1a) +#define ESR_EC_FPAC U(0x1c) +#define ESR_EC_IABT_EL0 U(0x20) +#define ESR_EC_IABT_EL1 U(0x21) +#define ESR_EC_PC_ALIGN U(0x22) +#define ESR_EC_DABT_EL0 U(0x24) +#define ESR_EC_DABT_EL1 U(0x25) +#define ESR_EC_SP_ALIGN U(0x26) +#define ESR_EC_AARCH32_FP U(0x28) +#define ESR_EC_AARCH64_FP U(0x2c) +#define ESR_EC_SERROR U(0x2f) +#define ESR_EC_BREAKPT_EL0 U(0x30) +#define ESR_EC_BREAKPT_EL1 U(0x31) +#define ESR_EC_SOFTSTP_EL0 U(0x32) +#define ESR_EC_SOFTSTP_EL1 U(0x33) +#define ESR_EC_WATCHPT_EL0 U(0x34) +#define ESR_EC_WATCHPT_EL1 U(0x35) +#define ESR_EC_AARCH32_BKPT U(0x38) +#define ESR_EC_AARCH64_BRK U(0x3c) + +/* Combined defines for DFSC and IFSC */ +#define ESR_FSC_MASK U(0x3f) +#define ESR_FSC_SIZE_L0 U(0x00) +#define ESR_FSC_SIZE_L1 U(0x01) +#define ESR_FSC_SIZE_L2 U(0x02) +#define ESR_FSC_SIZE_L3 U(0x03) +#define ESR_FSC_TRANS_L0 U(0x04) +#define ESR_FSC_TRANS_L1 U(0x05) +#define ESR_FSC_TRANS_L2 U(0x06) +#define ESR_FSC_TRANS_L3 U(0x07) +#define ESR_FSC_ACCF_L1 U(0x09) +#define ESR_FSC_ACCF_L2 U(0x0a) +#define ESR_FSC_ACCF_L3 U(0x0b) +#define ESR_FSC_PERMF_L1 U(0x0d) +#define ESR_FSC_PERMF_L2 U(0x0e) +#define ESR_FSC_PERMF_L3 U(0x0f) +#define ESR_FSC_TAG_CHECK U(0x11) +#define ESR_FSC_ALIGN U(0x21) + +/* WnR for DABT and RES0 for IABT */ +#define ESR_ABT_WNR BIT32(6) + +#define CPACR_EL1_FPEN_SHIFT U(20) +#define CPACR_EL1_FPEN_MASK U(0x3) +#define CPACR_EL1_FPEN_NONE U(0x0) +#define CPACR_EL1_FPEN_EL1 U(0x1) +#define CPACR_EL1_FPEN_EL0EL1 U(0x3) +#define CPACR_EL1_FPEN(x) ((x) >> CPACR_EL1_FPEN_SHIFT \ + & CPACR_EL1_FPEN_MASK) + + +#define PAR_F BIT32(0) +#define PAR_PA_SHIFT U(12) +#define PAR_PA_MASK (BIT64(36) - 1) + +#define TLBI_MVA_SHIFT U(12) +#define TLBI_ASID_SHIFT U(48) +#define TLBI_ASID_MASK U(0xff) + +#define ID_AA64PFR1_EL1_BT_MASK ULL(0xf) +#define FEAT_BTI_IMPLEMENTED ULL(0x1) + +#define ID_AA64PFR1_EL1_MTE_MASK UL(0xf) +#define ID_AA64PFR1_EL1_MTE_SHIFT U(8) +#define FEAT_MTE_NOT_IMPLEMENTED U(0x0) +#define FEAT_MTE_IMPLEMENTED U(0x1) +#define FEAT_MTE2_IMPLEMENTED U(0x2) +#define FEAT_MTE3_IMPLEMENTED U(0x3) + +#define ID_AA64ISAR0_EL1_CRC32_MASK UL(0xf) +#define ID_AA64ISAR0_EL1_CRC32_SHIFT U(16) +#define FEAT_CRC32_NOT_IMPLEMENTED U(0x0) +#define FEAT_CRC32_IMPLEMENTED U(0x1) + +#define ID_AA64ISAR1_GPI_SHIFT U(28) +#define ID_AA64ISAR1_GPI_MASK U(0xf) +#define ID_AA64ISAR1_GPI_NI U(0x0) +#define ID_AA64ISAR1_GPI_IMP_DEF U(0x1) + +#define ID_AA64ISAR1_GPA_SHIFT U(24) +#define ID_AA64ISAR1_GPA_MASK U(0xf) +#define ID_AA64ISAR1_GPA_NI U(0x0) +#define ID_AA64ISAR1_GPA_ARCHITECTED U(0x1) + +#define ID_AA64ISAR1_API_SHIFT U(8) +#define ID_AA64ISAR1_API_MASK U(0xf) +#define ID_AA64ISAR1_API_NI U(0x0) +#define ID_AA64ISAR1_API_IMP_DEF U(0x1) +#define ID_AA64ISAR1_API_IMP_DEF_EPAC U(0x2) +#define ID_AA64ISAR1_API_IMP_DEF_EPAC2 U(0x3) +#define ID_AA64ISAR1_API_IMP_DEF_EPAC2_FPAC U(0x4) +#define ID_AA64ISAR1_API_IMP_DEF_EPAC2_FPAC_CMB U(0x5) + +#define ID_AA64ISAR1_APA_SHIFT U(4) +#define ID_AA64ISAR1_APA_MASK U(0xf) +#define ID_AA64ISAR1_APA_NI U(0x0) +#define ID_AA64ISAR1_APA_ARCHITECTED U(0x1) +#define ID_AA64ISAR1_APA_ARCH_EPAC U(0x2) +#define ID_AA64ISAR1_APA_ARCH_EPAC2 U(0x3) +#define ID_AA64ISAR1_APA_ARCH_EPAC2_FPAC U(0x4) +#define ID_AA64ISAR1_APA_ARCH_EPAC2_FPAC_CMB U(0x5) + +#define GCR_EL1_RRND BIT64(16) + +#ifndef __ASSEMBLER__ +static inline __noprof void isb(void) +{ + asm volatile ("isb" : : : "memory"); +} + +static inline __noprof void dsb(void) +{ + asm volatile ("dsb sy" : : : "memory"); +} + +static inline __noprof void dsb_ish(void) +{ + asm volatile ("dsb ish" : : : "memory"); +} + +static inline __noprof void dsb_ishst(void) +{ + asm volatile ("dsb ishst" : : : "memory"); +} + +static inline __noprof void sev(void) +{ + asm volatile ("sev" : : : "memory"); +} + +static inline __noprof void wfe(void) +{ + asm volatile ("wfe" : : : "memory"); +} + +static inline __noprof void wfi(void) +{ + asm volatile ("wfi" : : : "memory"); +} + +static inline __noprof void write_at_s1e1r(uint64_t va) +{ + asm volatile ("at S1E1R, %0" : : "r" (va)); +} + +static __always_inline __noprof uint64_t read_pc(void) +{ + uint64_t val; + + asm volatile ("adr %0, ." : "=r" (val)); + return val; +} + +static __always_inline __noprof uint64_t read_fp(void) +{ + uint64_t val; + + asm volatile ("mov %0, x29" : "=r" (val)); + return val; +} + +static inline __noprof uint64_t read_pmu_ccnt(void) +{ + uint64_t val; + + asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(val)); + return val; +} + +static inline __noprof void tlbi_vaae1is(uint64_t mva) +{ + asm volatile ("tlbi vaae1is, %0" : : "r" (mva)); +} + +static inline __noprof void tlbi_vale1is(uint64_t mva) +{ + asm volatile ("tlbi vale1is, %0" : : "r" (mva)); +} + +/* + * Templates for register read/write functions based on mrs/msr + */ + +#define DEFINE_REG_READ_FUNC_(reg, type, asmreg) \ +static inline __noprof type read_##reg(void) \ +{ \ + uint64_t val64 = 0; \ + \ + asm volatile("mrs %0, " #asmreg : "=r" (val64)); \ + return val64; \ +} + +#define DEFINE_REG_WRITE_FUNC_(reg, type, asmreg) \ +static inline __noprof void write_##reg(type val) \ +{ \ + uint64_t val64 = val; \ + \ + asm volatile("msr " #asmreg ", %0" : : "r" (val64)); \ +} + +#define DEFINE_U32_REG_READ_FUNC(reg) \ + DEFINE_REG_READ_FUNC_(reg, uint32_t, reg) + +#define DEFINE_U32_REG_WRITE_FUNC(reg) \ + DEFINE_REG_WRITE_FUNC_(reg, uint32_t, reg) + +#define DEFINE_U32_REG_READWRITE_FUNCS(reg) \ + DEFINE_U32_REG_READ_FUNC(reg) \ + DEFINE_U32_REG_WRITE_FUNC(reg) + +#define DEFINE_U64_REG_READ_FUNC(reg) \ + DEFINE_REG_READ_FUNC_(reg, uint64_t, reg) + +#define DEFINE_U64_REG_WRITE_FUNC(reg) \ + DEFINE_REG_WRITE_FUNC_(reg, uint64_t, reg) + +#define DEFINE_U64_REG_READWRITE_FUNCS(reg) \ + DEFINE_U64_REG_READ_FUNC(reg) \ + DEFINE_U64_REG_WRITE_FUNC(reg) + +/* + * Define register access functions + */ + +DEFINE_U32_REG_READWRITE_FUNCS(cpacr_el1) +DEFINE_U32_REG_READWRITE_FUNCS(daif) +DEFINE_U32_REG_READWRITE_FUNCS(fpcr) +DEFINE_U32_REG_READWRITE_FUNCS(fpsr) + +DEFINE_U32_REG_READ_FUNC(ctr_el0) +#define read_ctr() read_ctr_el0() +DEFINE_U32_REG_READ_FUNC(contextidr_el1) +DEFINE_U64_REG_READ_FUNC(sctlr_el1) + +/* ARM Generic timer functions */ +DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0) +DEFINE_REG_READ_FUNC_(cntvct, uint64_t, cntvct_el0) +DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0) +DEFINE_REG_READ_FUNC_(cntkctl, uint32_t, cntkctl_el1) +DEFINE_REG_WRITE_FUNC_(cntkctl, uint32_t, cntkctl_el1) +DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1) +DEFINE_REG_WRITE_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1) +DEFINE_REG_READ_FUNC_(cntps_tval, uint32_t, cntps_tval_el1) +DEFINE_REG_WRITE_FUNC_(cntps_tval, uint32_t, cntps_tval_el1) + +DEFINE_REG_READ_FUNC_(pmccntr, uint64_t, pmccntr_el0) + +DEFINE_U64_REG_READWRITE_FUNCS(ttbr0_el1) +DEFINE_U64_REG_READWRITE_FUNCS(ttbr1_el1) +DEFINE_U64_REG_READWRITE_FUNCS(tcr_el1) + +DEFINE_U64_REG_READ_FUNC(esr_el1) +DEFINE_U64_REG_READ_FUNC(far_el1) +DEFINE_U64_REG_READ_FUNC(mpidr_el1) +/* Alias for reading this register to avoid ifdefs in code */ +#define read_mpidr() read_mpidr_el1() +DEFINE_U64_REG_READ_FUNC(midr_el1) +/* Alias for reading this register to avoid ifdefs in code */ +#define read_midr() read_midr_el1() +DEFINE_U64_REG_READ_FUNC(par_el1) + +DEFINE_U64_REG_WRITE_FUNC(mair_el1) + +DEFINE_U64_REG_READ_FUNC(id_aa64pfr1_el1) +DEFINE_U64_REG_READ_FUNC(id_aa64isar0_el1) +DEFINE_U64_REG_READ_FUNC(id_aa64isar1_el1) +DEFINE_REG_READ_FUNC_(apiakeylo, uint64_t, S3_0_c2_c1_0) +DEFINE_REG_READ_FUNC_(apiakeyhi, uint64_t, S3_0_c2_c1_1) + +DEFINE_REG_WRITE_FUNC_(apibkeylo, uint64_t, S3_0_c2_c1_2) +DEFINE_REG_WRITE_FUNC_(apibkeyhi, uint64_t, S3_0_c2_c1_3) + +DEFINE_REG_READ_FUNC_(apdakeylo, uint64_t, S3_0_c2_c2_0) +DEFINE_REG_READ_FUNC_(apdakeyhi, uint64_t, S3_0_c2_c2_1) + +DEFINE_REG_WRITE_FUNC_(apdbkeylo, uint64_t, S3_0_c2_c2_2) +DEFINE_REG_WRITE_FUNC_(apdbkeyhi, uint64_t, S3_0_c2_c2_3) + +DEFINE_REG_WRITE_FUNC_(apgakeylo, uint64_t, S3_0_c2_c3_0) +DEFINE_REG_WRITE_FUNC_(apgakeyhi, uint64_t, S3_0_c2_c3_1) + +/* Register read/write functions for GICC registers by using system interface */ +DEFINE_REG_READ_FUNC_(icc_ctlr, uint32_t, S3_0_C12_C12_4) +DEFINE_REG_WRITE_FUNC_(icc_ctlr, uint32_t, S3_0_C12_C12_4) +DEFINE_REG_WRITE_FUNC_(icc_pmr, uint32_t, S3_0_C4_C6_0) +DEFINE_REG_READ_FUNC_(icc_iar0, uint32_t, S3_0_c12_c8_0) +DEFINE_REG_READ_FUNC_(icc_iar1, uint32_t, S3_0_c12_c12_0) +DEFINE_REG_WRITE_FUNC_(icc_eoir0, uint32_t, S3_0_c12_c8_1) +DEFINE_REG_WRITE_FUNC_(icc_eoir1, uint32_t, S3_0_c12_c12_1) +DEFINE_REG_WRITE_FUNC_(icc_igrpen0, uint32_t, S3_0_C12_C12_6) +DEFINE_REG_WRITE_FUNC_(icc_igrpen1, uint32_t, S3_0_C12_C12_7) +#endif /*__ASSEMBLER__*/ + +#endif /*ARM64_H*/ + diff --git a/optee/optee_os/core/arch/arm/include/arm64_macros.S b/optee/optee_os/core/arch/arm/include/arm64_macros.S new file mode 100644 index 0000000..aced8f0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/arm64_macros.S @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + + .altmacro + + /* + * This helper macro concatenates instr_prefix, instr_suffix, to + * create a ldp/stp instruction. It also selects register name x/w + * based on reg_bytes. + */ + .macro __do_dregs instr_prefix, instr_suffix, reg_bytes, base_reg, \ + base_offs, reg0, reg1 + .if \reg_bytes == 8 + \instr_prefix\instr_suffix \ + x\reg0, x\reg1, [\base_reg, #\base_offs] + .else + \instr_prefix\instr_suffix \ + w\reg0, w\reg1, [\base_reg, #\base_offs] + .endif + .endm + + /* + * This helper macro concatenates instr_prefix, instr_suffix, to + * create a ldr/str instruction. It also selects register name x/w + * based on reg_bytes. + */ + .macro __do_reg instr_prefix, instr_suffix, reg_bytes, base_reg, \ + base_offs, reg + .if \reg_bytes == 8 + \instr_prefix\instr_suffix \ + x\reg, [\base_reg, #\base_offs] + .else + \instr_prefix\instr_suffix \ + w\reg, [\base_reg, #\base_offs] + .endif + .endm + + /* + * This helper macro uses recursion to create a loop which will + * start with generating instructions for register pairs and if + * it's an odd number of registers end with a single load/store. + */ + .macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \ + from_regnum, to_regnum + .if (\to_regnum - \from_regnum + 1) >= 2 + __do_dregs \instr_prefix, p, \reg_bytes, \base_reg, \ + \base_offs, \from_regnum, %(\from_regnum + 1) + .else + __do_reg \instr_prefix, r, \reg_bytes, \base_reg, \ + \base_offs, \from_regnum + .endif + .if (\to_regnum - \from_regnum + 1) > 2 + _do_regs \instr_prefix, \reg_bytes, \base_reg, \ + %(\base_offs + 2 * \reg_bytes), \ + %(\from_regnum + 2), \to_regnum + .endif + .endm + + /* + * Stores registers x[from_regnum]..x[to_regnum] at + * [base_reg, #base_offs] + */ + .macro store_xregs base_reg, base_offs, from_regnum, to_regnum + _do_regs st 8 \base_reg, \base_offs, \from_regnum, \to_regnum + .endm + + /* + * Stores registers w[from_regnum]..w[to_regnum] at + * [base_reg, #base_offs] + */ + .macro store_wregs base_reg, base_offs, from_regnum, to_regnum + _do_regs st 4 \base_reg, \base_offs, \from_regnum, \to_regnum + .endm + + /* + * Loads registers x[from_regnum]..x[to_regnum] at + * [base_reg, #base_offs] + */ + .macro load_xregs base_reg, base_offs, from_regnum, to_regnum + _do_regs ld 8 \base_reg, \base_offs, \from_regnum, \to_regnum + .endm + + /* + * Loads registers w[from_regnum]..w[to_regnum] at + * [base_reg, #base_offs] + */ + .macro load_wregs base_reg, base_offs, from_regnum, to_regnum + _do_regs ld 4 \base_reg, \base_offs, \from_regnum, \to_regnum + .endm + + + /* Push register pair on stack */ + .macro push, r1, r2 + stp \r1, \r2, [sp, #-16]! + .endm + + /* Pop register pair from stack */ + .macro pop, r1, r2 + ldp \r1, \r2, [sp], #16 + .endm + + .macro mov_imm _reg, _val + .if (((\_val) >> 31) == 0 || ((\_val) >> 31) == 0x1ffffffff) + movz \_reg, :abs_g1_s:\_val + .else + .if (((\_val) >> 47) == 0 || ((\_val) >> 47) == 0x1ffff) + movz \_reg, :abs_g2_s:\_val + .else + movz \_reg, :abs_g3:\_val + movk \_reg, :abs_g2_nc:\_val + .endif + movk \_reg, :abs_g1_nc:\_val + .endif + movk \_reg, :abs_g0_nc:\_val + .endm + + /* + * Load address of into , being in the range + * +/- 4GB of the PC (note that 'adr reg, sym' is limited to +/- 1MB). + */ + .macro adr_l reg, sym + adrp \reg, \sym + add \reg, \reg, :lo12:\sym + .endm + + .macro panic_at_smc_return +#if defined(CFG_TEE_CORE_DEBUG) + bl __panic_at_smc_return +#else + b . +#endif + .endm + + .macro read_apiakeylo reg + mrs \reg, S3_0_c2_c1_0 + .endm + + .macro read_apiakeyhi reg + mrs \reg, S3_0_c2_c1_1 + .endm + + .macro write_apiakeylo reg + msr S3_0_c2_c1_0, \reg + .endm + + .macro write_apiakeyhi reg + msr S3_0_c2_c1_1, \reg + .endm diff --git a/optee/optee_os/core/arch/arm/include/crypto/ghash-ce-core.h b/optee/optee_os/core/arch/arm/include/crypto/ghash-ce-core.h new file mode 100644 index 0000000..b0f9f54 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/crypto/ghash-ce-core.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#ifndef __GHASH_CE_CORE_H +#define __GHASH_CE_CORE_H + +#include + +struct internal_ghash_key { + uint64_t h[2]; + uint64_t h2[2]; + uint64_t h3[2]; + uint64_t h4[2]; +}; + +void pmull_ghash_update_p64(int blocks, uint64_t dg[2], const uint8_t *src, + const struct internal_ghash_key *ghash_key, + const uint8_t *head); +void pmull_ghash_update_p8(int blocks, uint64_t dg[2], const uint8_t *src, + const struct internal_ghash_key *ghash_key, + const uint8_t *head); + +void pmull_gcm_load_round_keys(const uint64_t rk[30], int rounds); + +void pmull_gcm_encrypt(int blocks, uint64_t dg[2], uint8_t dst[], + const uint8_t src[], + const struct internal_ghash_key *ghash_key, + uint64_t ctr[], const uint64_t rk[], int rounds, + uint8_t ks[]); + + +void pmull_gcm_decrypt(int blocks, uint64_t dg[2], uint8_t dst[], + const uint8_t src[], + const struct internal_ghash_key *ghash_key, + uint64_t ctr[], const uint64_t rk[], int rounds); + +uint32_t pmull_gcm_aes_sub(uint32_t input); + +void pmull_gcm_encrypt_block(uint8_t dst[], const uint8_t src[], int rounds); + +#endif /*__GHASH_CE_CORE_H*/ diff --git a/optee/optee_os/core/arch/arm/include/ffa.h b/optee/optee_os/core/arch/arm/include/ffa.h new file mode 100644 index 0000000..f71cd85 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/ffa.h @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2020, Linaro Limited + * Copyright (c) 2018-2022, Arm Limited. All rights reserved. + */ + +#ifndef __FFA_H +#define __FFA_H + +/* This is based on the FF-A 1.0 EAC specification */ + +#include +#include +#include + +/* Error codes */ +#define FFA_OK 0 +#define FFA_NOT_SUPPORTED -1 +#define FFA_INVALID_PARAMETERS -2 +#define FFA_NO_MEMORY -3 +#define FFA_BUSY -4 +#define FFA_INTERRUPTED -5 +#define FFA_DENIED -6 +#define FFA_RETRY -7 +#define FFA_ABORTED -8 + +/* FFA_VERSION helpers */ +#define FFA_VERSION_MAJOR U(1) +#define FFA_VERSION_MAJOR_SHIFT U(16) +#define FFA_VERSION_MAJOR_MASK U(0x7FFF) +#define FFA_VERSION_MINOR U(0) +#define FFA_VERSION_MINOR_SHIFT U(0) +#define FFA_VERSION_MINOR_MASK U(0xFFFF) +#define MAKE_FFA_VERSION(major, minor) \ + ((((major) & FFA_VERSION_MAJOR_MASK) << FFA_VERSION_MAJOR_SHIFT) | \ + ((minor) & FFA_VERSION_MINOR_MASK)) + +/* Function IDs */ +#define FFA_ERROR U(0x84000060) +#define FFA_SUCCESS_32 U(0x84000061) +#define FFA_SUCCESS_64 U(0xC4000061) +#define FFA_INTERRUPT U(0x84000062) +#define FFA_VERSION U(0x84000063) +#define FFA_FEATURES U(0x84000064) +#define FFA_RX_RELEASE U(0x84000065) +#define FFA_RXTX_MAP_32 U(0x84000066) +#define FFA_RXTX_MAP_64 U(0xC4000066) +#define FFA_RXTX_UNMAP U(0x84000067) +#define FFA_PARTITION_INFO_GET U(0x84000068) +#define FFA_ID_GET U(0x84000069) +#define FFA_MSG_WAIT U(0x8400006B) +#define FFA_MSG_YIELD U(0x8400006C) +#define FFA_MSG_RUN U(0x8400006D) +#define FFA_MSG_SEND U(0x8400006E) +#define FFA_MSG_SEND_DIRECT_REQ_32 U(0x8400006F) +#define FFA_MSG_SEND_DIRECT_REQ_64 U(0xC400006F) +#define FFA_MSG_SEND_DIRECT_RESP_32 U(0x84000070) +#define FFA_MSG_SEND_DIRECT_RESP_64 U(0xC4000070) +#define FFA_MSG_POLL U(0x8400006A) +#define FFA_MEM_DONATE_32 U(0x84000071) +#define FFA_MEM_DONATE_64 U(0xC4000071) +#define FFA_MEM_LEND_32 U(0x84000072) +#define FFA_MEM_LEND_64 U(0xC4000072) +#define FFA_MEM_SHARE_32 U(0x84000073) +#define FFA_MEM_SHARE_64 U(0xC4000073) +#define FFA_MEM_RETRIEVE_REQ_32 U(0x84000074) +#define FFA_MEM_RETRIEVE_REQ_64 U(0xC4000074) +#define FFA_MEM_RETRIEVE_RESP U(0x84000075) +#define FFA_MEM_RELINQUISH U(0x84000076) +#define FFA_MEM_RECLAIM U(0x84000077) +#define FFA_MEM_FRAG_RX U(0x8400007A) +#define FFA_MEM_FRAG_TX U(0x8400007B) +#define FFA_SECONDARY_EP_REGISTER_64 U(0xC4000087) +#define FFA_MEM_PERM_GET_32 U(0x84000088) +#define FFA_MEM_PERM_GET_64 U(0xC4000088) +#define FFA_MEM_PERM_SET_32 U(0x84000089) +#define FFA_MEM_PERM_SET_64 U(0xC4000089) + +/* Special value for traffic targeted to the Hypervisor or SPM */ +#define FFA_TARGET_INFO_MBZ U(0x0) + +/* Memory attributes: Normal memory, Write-Back cacheable, Inner shareable */ +#define FFA_NORMAL_MEM_REG_ATTR U(0x2f) + +/* Memory access permissions: Read-write */ +#define FFA_MEM_ACC_RW BIT(1) + +/* Memory access permissions: executable */ +#define FFA_MEM_ACC_EXE BIT(3) + +/* Memory access permissions mask */ +#define FFA_MEM_ACC_MASK 0xf + +/* Clear memory before mapping in receiver */ +#define FFA_MEMORY_REGION_FLAG_CLEAR BIT(0) +/* Relayer may time slice this operation */ +#define FFA_MEMORY_REGION_FLAG_TIME_SLICE BIT(1) +/* Clear memory after receiver relinquishes it */ +#define FFA_MEMORY_REGION_FLAG_CLEAR_RELINQUISH BIT(2) + +/* Share memory transaction */ +#define FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE SHIFT_U32(1, 3) +/* Relayer must choose the alignment boundary */ +#define FFA_MEMORY_REGION_FLAG_ANY_ALIGNMENT 0 + +#define FFA_MEM_PERM_DATA_PERM GENMASK_32(1, 0) +#define FFA_MEM_PERM_RW U(0x1) +#define FFA_MEM_PERM_RO U(0x3) + +#define FFA_MEM_PERM_INSTRUCTION_PERM BIT(2) +#define FFA_MEM_PERM_NX BIT(2) +#define FFA_MEM_PERM_X U(0) + +#define FFA_MEM_PERM_RESERVED GENMASK_32(31, 3) + +/* Special value for MBZ parameters */ +#define FFA_PARAM_MBZ U(0x0) + +/* + * Flags used for the FFA_PARTITION_INFO_GET return message: + * BIT(0): Supports receipt of direct requests + * BIT(1): Can send direct requests + * BIT(2): Cannot send and receive indirect messages + * BIT(3): Does not support receipt of notifications + * BIT(4-5): Partition ID is a PE endpoint ID + */ +#define FFA_PARTITION_DIRECT_REQ_RECV_SUPPORT BIT(0) +#define FFA_PARTITION_DIRECT_REQ_SEND_SUPPORT BIT(1) + +#define FFA_MEMORY_HANDLE_SECURE_BIT BIT64(45) +#define FFA_MEMORY_HANDLE_NONE_SECURE_BIT BIT64(44) + +#define FFA_BOOT_INFO_NAME_LEN U(16) + +/* Boot Info descriptors type */ +#define FFA_BOOT_INFO_TYPE_IMDEF BIT(7) +#define FFA_BOOT_INFO_TYPE_ID_MASK GENMASK_32(6, 0) +#define FFA_BOOT_INFO_TYPE_ID_FDT U(0) +#define FFA_BOOT_INFO_TYPE_ID_HOB U(1) + +/* Boot Info descriptors flags */ +#define FFA_BOOT_INFO_FLAG_NAME_FORMAT_MASK GENMASK_32(1, 0) +#define FFA_BOOT_INFO_FLAG_NAME_FORMAT_STRING U(0) +#define FFA_BOOT_INFO_FLAG_NAME_FORMAT_UUID U(1) + +/** Bits [3:2] encode the format of the content field in ffa_boot_info_desc. */ +#define FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_SHIFT U(2) +#define FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_MASK GENMASK_32(3, 2) +#define FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_VALUE U(1) +#define FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR U(0) + +#define FFA_BOOT_INFO_SIGNATURE U(0xFFA) +#define FFA_BOOT_INFO_VERSION U(0x10001) + +#ifndef __ASSEMBLER__ +/* Constituent memory region descriptor */ +struct ffa_address_range { + uint64_t address; + uint32_t page_count; + uint32_t reserved; +}; + +/* Composite memory region descriptor */ +struct ffa_mem_region { + uint32_t total_page_count; + uint32_t address_range_count; + uint64_t reserved; + struct ffa_address_range address_range_array[]; +}; + +/* Memory access permissions descriptor */ +struct ffa_mem_access_perm { + uint16_t endpoint_id; + uint8_t perm; + uint8_t flags; +}; + +/* Endpoint memory access descriptor */ +struct ffa_mem_access { + struct ffa_mem_access_perm access_perm; + uint32_t region_offs; + uint64_t reserved; +}; + +/* Lend, donate or share memory transaction descriptor */ +struct ffa_mem_transaction { + uint16_t sender_id; + uint8_t mem_reg_attr; + uint8_t reserved0; + uint32_t flags; + uint64_t global_handle; + uint64_t tag; + uint32_t reserved1; + uint32_t mem_access_count; + struct ffa_mem_access mem_access_array[]; +}; + +/* Partition information descriptor */ +struct ffa_partition_info { + uint16_t id; + uint16_t execution_context; + uint32_t partition_properties; +}; + +/* Descriptor to relinquish a memory region (FFA_MEM_RELINQUISH) */ +struct ffa_mem_relinquish { + uint64_t handle; + uint32_t flags; + uint32_t endpoint_count; + uint16_t endpoint_id_array[]; +}; + +/* FF-A v1.1 boot information descriptor */ +struct ffa_boot_info { + char name[FFA_BOOT_INFO_NAME_LEN]; + uint8_t type; + uint8_t reserved; + uint16_t flags; + uint32_t size; + uint64_t contents; +}; + +/* FF-A v1.1 boot information header */ +struct ffa_boot_info_header { + uint32_t signature; + uint32_t version; + uint32_t blob_size; + uint32_t desc_size; + uint32_t desc_count; + uint32_t desc_offset; + uint64_t reserved; +}; + +#endif /*__ASSEMBLER__*/ +#endif /* __FFA_H */ diff --git a/optee/optee_os/core/arch/arm/include/hafnium.h b/optee/optee_os/core/arch/arm/include/hafnium.h new file mode 100644 index 0000000..542ae8f --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/hafnium.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright 2018 The Hafnium Authors. + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef __HAFNIUM_H +#define __HAFNIUM_H + +/* + * This is based on inc/vmapi/hf/abi.h and inc/vmapi/hf/types.h from the + * Hafnium source tree. + */ + +/* + * Enables a given interrupt ID, returns 0 on success or -1 if the + * interrupt ID is invalid. + */ +#define HF_INTERRUPT_ENABLE 0xff03 + +/* + * Returns the ID of the next pending interrupt, and acknowledges it (i.e. + * marks it as no longer pending). Returns HF_INVALID_INTID if there are no + * pending interrupts. + */ +#define HF_INTERRUPT_GET 0xff04 + +/* + * Drops the current interrupt priority and deactivate the given interrupt + * ID. + */ +#define HF_INTERRUPT_DEACTIVATE 0xff08 + +/* Interrupt ID returned when there is no interrupt pending. */ +#define HF_INVALID_INTID 0xffffffff + +/* The virtual interrupt ID used for managed exit. */ +#define HF_MANAGED_EXIT_INTID 4 + +#define HF_INTERRUPT_TYPE_IRQ 0 +#define HF_INTERRUPT_TYPE_FIQ 1 +#define HF_ENABLE 1 +#define HF_DISABLE 0 + +#endif /*__HAFNIUM_H*/ diff --git a/optee/optee_os/core/arch/arm/include/kernel/arch_scall.h b/optee/optee_os/core/arch/arm/include/kernel/arch_scall.h new file mode 100644 index 0000000..cff6cc2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/arch_scall.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2022, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ +#ifndef __KERNEL_ARCH_SCALL_H +#define __KERNEL_ARCH_SCALL_H + +#include +#include +#include + +static inline void scall_get_max_args(struct thread_scall_regs *regs, + size_t *scn, size_t *max_args) +{ +#ifdef ARM32 + *scn = regs->r7; + *max_args = regs->r6; +#endif +#ifdef ARM64 + if (((regs->spsr >> SPSR_MODE_RW_SHIFT) & SPSR_MODE_RW_MASK) == + SPSR_MODE_RW_32) { + *scn = regs->x7; + *max_args = regs->x6; + } else { + *scn = regs->x8; + *max_args = 0; + } +#endif +} + +static inline void scall_set_retval(struct thread_scall_regs *regs, + uint32_t ret_val) +{ +#ifdef ARM32 + regs->r0 = ret_val; +#endif +#ifdef ARM64 + regs->x0 = ret_val; +#endif +} + +static inline void scall_set_sys_return_regs(struct thread_scall_regs *regs, + bool panic, uint32_t panic_code) +{ +#ifdef ARM32 + regs->r1 = panic; + regs->r2 = panic_code; +#endif +#ifdef ARM64 + regs->x1 = panic; + regs->x2 = panic_code; +#endif +} +#endif /*__KERNEL_ARCH_SCALL_H*/ + diff --git a/optee/optee_os/core/arch/arm/include/kernel/cache_helpers_arch.h b/optee/optee_os/core/arch/arm/include/kernel/cache_helpers_arch.h new file mode 100644 index 0000000..aa136fe --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/cache_helpers_arch.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __KERNEL_CACHE_HELPERS_ARCH_H +#define __KERNEL_CACHE_HELPERS_ARCH_H + +#ifndef __ASSEMBLER__ +#include +#include +#endif + +#ifndef __ASSEMBLER__ + +static inline unsigned int dcache_get_line_size(void) +{ + uint32_t value = read_ctr(); + + return CTR_WORD_SIZE << + ((value >> CTR_DMINLINE_SHIFT) & CTR_DMINLINE_MASK); +} + +#endif /*!__ASSEMBLER__*/ + +#endif /*__KERNEL_CACHE_HELPERS_ARCH_H*/ diff --git a/optee/optee_os/core/arch/arm/include/kernel/delay_arch.h b/optee/optee_os/core/arch/arm/include/kernel/delay_arch.h new file mode 100644 index 0000000..12a2080 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/delay_arch.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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_DELAY_ARCH_H +#define __KERNEL_DELAY_ARCH_H + +#include +#include +#include + +static inline uint64_t arm_cnt_us2cnt(uint32_t us) +{ + return ((uint64_t)us * (uint64_t)read_cntfrq()) / 1000000ULL; +} + +static inline uint64_t timeout_init_us(uint32_t us) +{ + return barrier_read_counter_timer() + arm_cnt_us2cnt(us); +} + +static inline bool timeout_elapsed(uint64_t expire) +{ + return barrier_read_counter_timer() > expire; +} + +#endif diff --git a/optee/optee_os/core/arch/arm/include/kernel/misc_arch.h b/optee/optee_os/core/arch/arm/include/kernel/misc_arch.h new file mode 100644 index 0000000..0653119 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/misc_arch.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef KERNEL_MISC_ARCH_H +#define KERNEL_MISC_ARCH_H + +#include +#include +#include + +size_t get_core_pos_mpidr(uint32_t mpidr); + +uint32_t read_mode_sp(int cpu_mode); +uint32_t read_mode_lr(int cpu_mode); + +void wait_cycles(unsigned long cycles); + +#endif /*KERNEL_MISC_ARCH_H*/ diff --git a/optee/optee_os/core/arch/arm/include/kernel/secure_partition.h b/optee/optee_os/core/arch/arm/include/kernel/secure_partition.h new file mode 100644 index 0000000..2907509 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/secure_partition.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020-2023, Arm Limited. + */ +#ifndef __KERNEL_SECURE_PARTITION_H +#define __KERNEL_SECURE_PARTITION_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TAILQ_HEAD(sp_sessions_head, sp_session); + +struct sp_name_value_pair { + uint32_t name[4]; + uint64_t value; + uint64_t size; +}; + +/* SP entry arguments passed to SP image: see ABI in FF-A specification */ +struct sp_ffa_init_info { + uint32_t magic; /* FF-A */ + uint32_t count; /* Count of name value size pairs */ + struct sp_name_value_pair nvp[]; /* Array of name value size pairs */ +}; + +enum sp_status { sp_idle, sp_busy, sp_preempted, sp_dead }; + +struct sp_session { + struct ffa_rxtx rxtx; + enum sp_status state; + uint16_t endpoint_id; + uint16_t caller_id; + struct ts_session ts_sess; + struct sp_ffa_init_info *info; + unsigned int spinlock; + const void *fdt; + bool is_initialized; + TEE_UUID ffa_uuid; + TAILQ_ENTRY(sp_session) link; +}; + +struct sp_ctx { + struct thread_ctx_regs sp_regs; + struct sp_session *open_session; + struct user_mode_ctx uctx; + struct ts_ctx ts_ctx; +}; + +struct sp_image { + struct embedded_ts image; + const void *fdt; +}; + +#ifdef CFG_SECURE_PARTITION +bool is_sp_ctx(struct ts_ctx *ctx); +#else +static inline bool is_sp_ctx(struct ts_ctx *ctx __unused) +{ + return false; +} +#endif + +static inline struct sp_session *__noprof +to_sp_session(struct ts_session *sess) +{ + assert(is_sp_ctx(sess->ctx)); + return container_of(sess, struct sp_session, ts_sess); +} + +static inline struct sp_ctx *to_sp_ctx(struct ts_ctx *ctx) +{ + assert(is_sp_ctx(ctx)); + return container_of(ctx, struct sp_ctx, ts_ctx); +} + +struct sp_session *sp_get_session(uint32_t session_id); +TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp); +TEE_Result sp_partition_info_get(struct ffa_partition_info *fpi, + const TEE_UUID *ffa_uuid, size_t *elem_count); + +bool sp_has_exclusive_access(struct sp_mem_map_region *mem, + struct user_mode_ctx *uctx); +TEE_Result sp_map_shared(struct sp_session *s, + struct sp_mem_receiver *receiver, + struct sp_mem *mem, + uint64_t *va); +TEE_Result sp_unmap_ffa_regions(struct sp_session *s, struct sp_mem *smem); + +#define for_each_secure_partition(_sp) \ + SCATTERED_ARRAY_FOREACH(_sp, sp_images, struct sp_image) + +struct fip_sp { + struct sp_image sp_img; + STAILQ_ENTRY(fip_sp) link; +}; + +STAILQ_HEAD(fip_sp_head, fip_sp); +extern struct fip_sp_head fip_sp_list; + +#define for_each_fip_sp(_sp) \ + STAILQ_FOREACH(_sp, &fip_sp_list, link) + +#endif /* __KERNEL_SECURE_PARTITION_H */ diff --git a/optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h b/optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h new file mode 100644 index 0000000..f5bda7b --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/spmc_sp_handler.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Arm Limited. + */ +#ifndef __KERNEL_SPMC_SP_HANDLER_H +#define __KERNEL_SPMC_SP_HANDLER_H + +#include +#include +#include +#include +#include + +#define FFA_DST(x) ((x) & UINT16_MAX) +#define FFA_SRC(x) (((x) >> 16) & UINT16_MAX) + +void spmc_sp_thread_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3); +void spmc_sp_msg_handler(struct thread_smc_args *args, + struct sp_session *caller_sp); +bool ffa_mem_reclaim(struct thread_smc_args *args, + struct sp_session *caller_sp); + +#ifdef CFG_SECURE_PARTITION +void spmc_sp_start_thread(struct thread_smc_args *args); +int spmc_sp_add_share(struct ffa_rxtx *rxtx, + size_t blen, uint64_t *global_handle, + struct sp_session *owner_sp); +#else +static inline void spmc_sp_start_thread(struct thread_smc_args *args __unused) +{ +} + +static inline int spmc_sp_add_share(struct ffa_rxtx *rxtx __unused, + size_t blen __unused, + uint64_t *global_handle __unused, + struct sp_session *owner_sp __unused) +{ + return FFA_NOT_SUPPORTED; +} +#endif + +#endif /* __KERNEL_SPMC_SP_HANDLER_H */ diff --git a/optee/optee_os/core/arch/arm/include/kernel/stmm_sp.h b/optee/optee_os/core/arch/arm/include/kernel/stmm_sp.h new file mode 100644 index 0000000..aee6bd6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/stmm_sp.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2020, Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ + +#ifndef __KERNEL_STMM_SP_H +#define __KERNEL_STMM_SP_H + +#include +#include +#include +#include +#include +#include +#include + +#define STMM_RET_SUCCESS 0 +#define STMM_RET_NOT_SUPPORTED -1 +#define STMM_RET_INVALID_PARAM -2 +#define STMM_RET_DENIED -3 +#define STMM_RET_NO_MEM -5 + +#define STMM_MEM_ATTR_ACCESS_MASK U(0x3) +#define STMM_MEM_ATTR_ACCESS_NONE U(0) +#define STMM_MEM_ATTR_ACCESS_RW U(1) +#define STMM_MEM_ATTR_ACCESS_RO U(3) +#define STMM_MEM_ATTR_EXEC_NEVER BIT(2) +#define STMM_MEM_ATTR_EXEC U(0) +#define STMM_MEM_ATTR_ALL (STMM_MEM_ATTR_ACCESS_RW | \ + STMM_MEM_ATTR_ACCESS_RO | \ + STMM_MEM_ATTR_EXEC_NEVER) + +/* + * Used for EDK2 StMM communication. Since StMM can be launched on an arbitrary + * address it uses these 2 syscalls to define the memory attributes for the + * data and code segments after dispatching the binaries. + * + * FFA_SVC_MEMORY_ATTRIBUTES_SET_64/FFA_SVC_MEMORY_ATTRIBUTES_SET_32: + * - x4: base address + * - x5: number of pages + * - x6: attributes of the remapping (described above) + * + * FFA_SVC_MEMORY_ATTRIBUTES_GET_32/FFA_SVC_MEMORY_ATTRIBUTES_GET_64: + * - x4: base address, currently only a single page is requested. + */ +#define FFA_SVC_MEMORY_ATTRIBUTES_GET_64 UINT32_C(0xC4000064) +#define FFA_SVC_MEMORY_ATTRIBUTES_SET_64 UINT32_C(0xC4000065) + +#define FFA_SVC_MEMORY_ATTRIBUTES_GET_32 UINT32_C(0x84000064) +#define FFA_SVC_MEMORY_ATTRIBUTES_SET_32 UINT32_C(0x84000065) + +/* + * We need to define the RPMB IDs formally, since the plan is + * for them to be included in the FFA spec (for SP-to-SP future communication). + * This is fine for now as it represents the internal contract between the + * EDK2 RPMB driver and Secure Partition + * + * FFA_SVC_RPMB_WRITE/FFA_SVC_RPMB_WRITE_32: + * - x4: virtual address of the buffer to write in the device + * - x5: buffer byte length + * - x6: byte offset in the device + * FFA_SVC_RPMB_READ/FFA_SVC_RPMB_READ_32: + * - x4: virtual address of the buffer were RPMB contents are copied + * - x5: buffer byte length to read + * - x6: byte offset in the device + */ +#define FFA_SVC_RPMB_READ UINT32_C(0xC4000066) +#define FFA_SVC_RPMB_WRITE UINT32_C(0xC4000067) + +#define FFA_SVC_RPMB_READ_32 UINT32_C(0x84000066) +#define FFA_SVC_RPMB_WRITE_32 UINT32_C(0x84000067) + +/* Param header types */ +#define STMM_PARAM_EP UINT8_C(0x01) +#define STMM_PARAM_IMAGE_BINARY UINT8_C(0x02) +#define STMM_PARAM_BL31 UINT8_C(0x03) +#define STMM_PARAM_BL_LOAD_INFO UINT8_C(0x04) +#define STMM_PARAM_BL_PARAMS UINT8_C(0x05) +#define STMM_PARAM_PSCI_LIB_ARGS UINT8_C(0x06) +#define STMM_PARAM_SP_IMAGE_BOOT_INFO UINT8_C(0x07) + +/* Param header version */ +#define STMM_PARAM_VERSION_1 UINT8_C(0x01) +#define STMM_PARAM_VERSION_2 UINT8_C(0x02) + +/* + * This structure provides information on format used to describe + * secure partition invocation parameters. + */ +struct stmm_param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ +}; + +/* + * Flags used by the stmm_mp_info structure to describe the + * characteristics of a cpu. Only a single flag is defined at the moment to + * indicate the primary cpu. + */ +#define MP_INFO_FLAG_PRIMARY_CPU UINT32_C(0x00000001) + +#define DEVICE_REGION_NAME_LEN 32 +/* + * The maximum device regions that can be defined in DT + */ +#define MAX_DEVICE_REGIONS 10 + +/* + * This structure is used to provide information required to initialise a S-EL0 + * partition. + */ +struct stmm_mp_info { + uint64_t mpidr; + uint32_t linear_id; + uint32_t flags; +}; + +struct device_region { + char name[DEVICE_REGION_NAME_LEN]; + vaddr_t va; + size_t size; +}; + +struct device_region_dt { + char name[DEVICE_REGION_NAME_LEN]; + paddr_t pa; + uint32_t page_count; + uint32_t prot; +}; + +struct stmm_boot_info { + struct stmm_param_header h; + uint64_t sp_mem_base; + uint64_t sp_mem_limit; + uint64_t sp_image_base; + uint64_t sp_stack_base; + uint64_t sp_heap_base; + uint64_t sp_ns_comm_buf_base; + uint64_t sp_shared_buf_base; + uint64_t sp_image_size; + uint64_t sp_pcpu_stack_size; + uint64_t sp_heap_size; + uint64_t sp_ns_comm_buf_size; + uint64_t sp_shared_buf_size; + uint32_t num_sp_mem_regions; + uint32_t num_cpus; + struct stmm_mp_info *mp_info; + struct device_region device_regions[MAX_DEVICE_REGIONS]; + uint32_t device_regions_len; +}; + +struct stmm_ctx { + struct user_mode_ctx uctx; + struct tee_ta_ctx ta_ctx; + struct thread_ctx_regs regs; + vaddr_t ns_comm_buf_addr; + unsigned int ns_comm_buf_size; + bool is_initializing; +}; + +extern const struct ts_ops stmm_sp_ops; + +static inline bool is_stmm_ctx(struct ts_ctx *ctx __maybe_unused) +{ + return IS_ENABLED(CFG_WITH_STMM_SP) && ctx && ctx->ops == &stmm_sp_ops; +} + +static inline struct stmm_ctx *to_stmm_ctx(struct ts_ctx *ctx) +{ + assert(is_stmm_ctx(ctx)); + return container_of(ctx, struct stmm_ctx, ta_ctx.ts_ctx); +} + +#ifdef CFG_WITH_STMM_SP +TEE_Result stmm_init_session(const TEE_UUID *uuid, + struct tee_ta_session *s); +#else +static inline TEE_Result +stmm_init_session(const TEE_UUID *uuid __unused, + struct tee_ta_session *s __unused) +{ + return TEE_ERROR_ITEM_NOT_FOUND; +} +#endif + +#ifdef CFG_WITH_STMM_SP +const TEE_UUID *stmm_get_uuid(void); +#else +static inline const TEE_UUID *stmm_get_uuid(void) { return NULL; } +#endif + +bool stmm_is_device_mem_inside(paddr_t pa, size_t len); + +#endif /*__KERNEL_STMM_SP_H*/ diff --git a/optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h b/optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h new file mode 100644 index 0000000..1011fce --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/tee_l2cc_mutex.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef TEE_L2CC_MUTEX_H +#define TEE_L2CC_MUTEX_H +#include +#include +#include +#include + +#if defined(CFG_PL310) +TEE_Result tee_enable_l2cc_mutex(void); +TEE_Result tee_disable_l2cc_mutex(void); +TEE_Result tee_get_l2cc_mutex(paddr_t *mutex); +TEE_Result tee_set_l2cc_mutex(paddr_t *mutex); +void tee_l2cc_mutex_lock(void); +void tee_l2cc_mutex_unlock(void); + +/* + * Store the pa of a mutex used for l2cc + * It is allocated from the boot + */ +void tee_l2cc_store_mutex_boot_pa(uint32_t pa); + +#else +static TEE_Result tee_enable_l2cc_mutex(void); +static TEE_Result tee_disable_l2cc_mutex(void); +static TEE_Result tee_get_l2cc_mutex(paddr_t *mutex); +static TEE_Result tee_set_l2cc_mutex(paddr_t *mutex); + +static inline TEE_Result tee_enable_l2cc_mutex(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +static inline TEE_Result tee_disable_l2cc_mutex(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +static inline TEE_Result tee_get_l2cc_mutex(paddr_t *mutex __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +static inline TEE_Result tee_set_l2cc_mutex(paddr_t *mutex __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +#endif /* TEE_L2CC_MUTEX_H */ diff --git a/optee/optee_os/core/arch/arm/include/kernel/thread_arch.h b/optee/optee_os/core/arch/arm/include/kernel/thread_arch.h new file mode 100644 index 0000000..2beadf4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/thread_arch.h @@ -0,0 +1,458 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2016-2022, Linaro Limited + * Copyright (c) 2020-2021, Arm Limited + */ + +#ifndef __KERNEL_THREAD_ARCH_H +#define __KERNEL_THREAD_ARCH_H + +#ifndef __ASSEMBLER__ +#include +#include +#include +#include +#endif + +#ifndef __ASSEMBLER__ + +#ifdef ARM64 +/* + * struct thread_core_local needs to have alignment suitable for a stack + * pointer since SP_EL1 points to this + */ +#define THREAD_CORE_LOCAL_ALIGNED __aligned(16) +#else +#define THREAD_CORE_LOCAL_ALIGNED __aligned(8) +#endif + +struct mobj; + +/* + * Storage of keys used for pointer authentication. FEAT_PAuth supports a + * number of keys of which only the APIA key is currently used, depending on + * configuration. + */ +struct thread_pauth_keys { + uint64_t apia_hi; + uint64_t apia_lo; +}; + +struct thread_core_local { +#ifdef ARM32 + uint32_t r[2]; + paddr_t sm_pm_ctx_phys; +#endif +#ifdef ARM64 + uint64_t x[4]; +#endif +#ifdef CFG_CORE_PAUTH + struct thread_pauth_keys keys; +#endif + vaddr_t tmp_stack_va_end; + long kcode_offset; + short int curr_thread; + uint32_t flags; + vaddr_t abt_stack_va_end; +#ifdef CFG_TEE_CORE_DEBUG + unsigned int locked_count; /* Number of spinlocks held */ +#endif +#if defined(ARM64) && defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) + uint8_t bhb_loop_count; +#endif +#ifdef CFG_CORE_DEBUG_CHECK_STACKS + bool stackcheck_recursion; +#endif +} THREAD_CORE_LOCAL_ALIGNED; + +struct thread_vector_table { + uint32_t std_smc_entry; + uint32_t fast_smc_entry; + uint32_t cpu_on_entry; + uint32_t cpu_off_entry; + uint32_t cpu_resume_entry; + uint32_t cpu_suspend_entry; + uint32_t fiq_entry; + uint32_t system_off_entry; + uint32_t system_reset_entry; +}; + +extern struct thread_vector_table thread_vector_table; + +struct thread_user_vfp_state { + struct vfp_state vfp; + bool lazy_saved; + bool saved; +}; + +#ifdef ARM32 +struct thread_smc_args { + uint32_t a0; /* SMC function ID */ + uint32_t a1; /* Parameter */ + uint32_t a2; /* Parameter */ + uint32_t a3; /* Thread ID when returning from RPC */ + uint32_t a4; /* Not used */ + uint32_t a5; /* Not used */ + uint32_t a6; /* Not used */ + uint32_t a7; /* Hypervisor Client ID */ +}; +#endif /*ARM32*/ +#ifdef ARM64 +struct thread_smc_args { + uint64_t a0; /* SMC function ID */ + uint64_t a1; /* Parameter */ + uint64_t a2; /* Parameter */ + uint64_t a3; /* Thread ID when returning from RPC */ + uint64_t a4; /* Not used */ + uint64_t a5; /* Not used */ + uint64_t a6; /* Not used */ + uint64_t a7; /* Hypervisor Client ID */ +}; +#endif /*ARM64*/ + +#ifdef ARM32 +struct thread_abort_regs { + uint32_t usr_sp; + uint32_t usr_lr; + uint32_t pad; + uint32_t spsr; + uint32_t elr; + 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 ip; +}; +#endif /*ARM32*/ +#ifdef ARM64 +struct thread_abort_regs { + uint64_t x0; /* r0_usr */ + uint64_t x1; /* r1_usr */ + uint64_t x2; /* r2_usr */ + uint64_t x3; /* r3_usr */ + uint64_t x4; /* r4_usr */ + uint64_t x5; /* r5_usr */ + uint64_t x6; /* r6_usr */ + uint64_t x7; /* r7_usr */ + uint64_t x8; /* r8_usr */ + uint64_t x9; /* r9_usr */ + uint64_t x10; /* r10_usr */ + uint64_t x11; /* r11_usr */ + uint64_t x12; /* r12_usr */ + uint64_t x13; /* r13/sp_usr */ + uint64_t x14; /* r14/lr_usr */ + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; + uint64_t x30; + uint64_t elr; + uint64_t spsr; + uint64_t sp_el0; +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + uint64_t apiakey_hi; + uint64_t apiakey_lo; +#endif +}; +#endif /*ARM64*/ + +#ifdef ARM32 +struct thread_scall_regs { + uint32_t spsr; + 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 lr; +}; +#endif /*ARM32*/ +#ifdef ARM64 +struct thread_scall_regs { + uint64_t elr; + uint64_t spsr; + uint64_t x0; /* r0_usr */ + uint64_t x1; /* r1_usr */ + uint64_t x2; /* r2_usr */ + uint64_t x3; /* r3_usr */ + uint64_t x4; /* r4_usr */ + uint64_t x5; /* r5_usr */ + uint64_t x6; /* r6_usr */ + uint64_t x7; /* r7_usr */ + uint64_t x8; /* r8_usr */ + uint64_t x9; /* r9_usr */ + uint64_t x10; /* r10_usr */ + uint64_t x11; /* r11_usr */ + uint64_t x12; /* r12_usr */ + uint64_t x13; /* r13/sp_usr */ + uint64_t x14; /* r14/lr_usr */ + uint64_t x30; + uint64_t sp_el0; +#ifdef CFG_SECURE_PARTITION + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; +#endif +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + uint64_t apiakey_hi; + uint64_t apiakey_lo; +#endif + uint64_t pad; +} __aligned(16); +#endif /*ARM64*/ + +#ifdef ARM32 +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_sp; + uint32_t usr_lr; + uint32_t svc_spsr; + uint32_t svc_sp; + uint32_t svc_lr; + uint32_t pc; + uint32_t cpsr; +}; +#endif /*ARM32*/ + +#ifdef ARM64 +struct thread_ctx_regs { + uint64_t sp; + uint64_t pc; + uint64_t cpsr; + uint64_t x[31]; + uint64_t tpidr_el0; +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + uint64_t apiakey_hi; + uint64_t apiakey_lo; +#endif +}; +#endif /*ARM64*/ + +struct user_mode_ctx; + +#ifdef CFG_WITH_ARM_TRUSTED_FW +/* + * These five functions have a __weak default implementation which does + * nothing. Platforms are expected to override them if needed. + */ +unsigned long thread_cpu_off_handler(unsigned long a0, unsigned long a1); +unsigned long thread_cpu_suspend_handler(unsigned long a0, unsigned long a1); +unsigned long thread_cpu_resume_handler(unsigned long a0, unsigned long a1); +unsigned long thread_system_off_handler(unsigned long a0, unsigned long a1); +unsigned long thread_system_reset_handler(unsigned long a0, unsigned long a1); +#endif /*CFG_WITH_ARM_TRUSTED_FW*/ + +/* + * Defines the bits for the exception mask used by the + * thread_*_exceptions() functions below. + * These definitions are compatible with both ARM32 and ARM64. + */ +#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) +#define THREAD_EXCP_FOREIGN_INTR (ARM32_CPSR_F >> ARM32_CPSR_F_SHIFT) +#define THREAD_EXCP_NATIVE_INTR (ARM32_CPSR_I >> ARM32_CPSR_F_SHIFT) +#else +#define THREAD_EXCP_FOREIGN_INTR (ARM32_CPSR_I >> ARM32_CPSR_F_SHIFT) +#define THREAD_EXCP_NATIVE_INTR (ARM32_CPSR_F >> ARM32_CPSR_F_SHIFT) +#endif +#define THREAD_EXCP_ALL (THREAD_EXCP_FOREIGN_INTR \ + | THREAD_EXCP_NATIVE_INTR \ + | (ARM32_CPSR_A >> ARM32_CPSR_F_SHIFT)) + +#ifdef CFG_WITH_VFP +/* + * thread_kernel_enable_vfp() - Temporarily enables usage of VFP + * + * Foreign interrupts are masked while VFP is enabled. User space must not be + * entered before thread_kernel_disable_vfp() has been called to disable VFP + * and restore the foreign interrupt status. + * + * This function may only be called from an active thread context and may + * not be called again before thread_kernel_disable_vfp() has been called. + * + * VFP state is saved as needed. + * + * Returns a state variable that should be passed to + * thread_kernel_disable_vfp(). + */ +uint32_t thread_kernel_enable_vfp(void); + +/* + * thread_kernel_disable_vfp() - Disables usage of VFP + * @state: state variable returned by thread_kernel_enable_vfp() + * + * Disables usage of VFP and restores foreign interrupt status after a call to + * thread_kernel_enable_vfp(). + * + * This function may only be called after a call to + * thread_kernel_enable_vfp(). + */ +void thread_kernel_disable_vfp(uint32_t state); + +/* + * thread_kernel_save_vfp() - Saves kernel vfp state if enabled + */ +void thread_kernel_save_vfp(void); + +/* + * thread_kernel_save_vfp() - Restores kernel vfp state + */ +void thread_kernel_restore_vfp(void); + +/* + * thread_user_enable_vfp() - Enables vfp for user mode usage + * @uvfp: pointer to where to save the vfp state if needed + */ +void thread_user_enable_vfp(struct thread_user_vfp_state *uvfp); +#else /*CFG_WITH_VFP*/ +static inline void thread_kernel_save_vfp(void) +{ +} + +static inline void thread_kernel_restore_vfp(void) +{ +} +#endif /*CFG_WITH_VFP*/ + +/* + * thread_user_save_vfp() - Saves the user vfp state if enabled + */ +#ifdef CFG_WITH_VFP +void thread_user_save_vfp(void); +#else +static inline void thread_user_save_vfp(void) +{ +} +#endif + +/* + * thread_user_clear_vfp() - Clears the vfp state + * @uctx: pointer to user mode context containing the saved state to clear + */ +#ifdef CFG_WITH_VFP +void thread_user_clear_vfp(struct user_mode_ctx *uctx); +#else +static inline void thread_user_clear_vfp(struct user_mode_ctx *uctx __unused) +{ +} +#endif + +#ifdef ARM64 +/* + * thread_get_saved_thread_sp() - Returns the saved sp of current thread + * + * When switching from the thread stack pointer the value is stored + * separately in the current thread context. This function returns this + * saved value. + * + * @returns stack pointer + */ +vaddr_t thread_get_saved_thread_sp(void); +#endif /*ARM64*/ + +/* + * Provides addresses and size of kernel code that must be mapped while in + * user mode. + */ +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 +void thread_get_user_kcode(struct mobj **mobj, size_t *offset, + vaddr_t *va, size_t *sz); +#else +static inline void thread_get_user_kcode(struct mobj **mobj, size_t *offset, + vaddr_t *va, size_t *sz) +{ + *mobj = NULL; + *offset = 0; + *va = 0; + *sz = 0; +} +#endif + +/* + * Provides addresses and size of kernel (rw) data that must be mapped + * while in user mode. + */ +#if defined(CFG_CORE_UNMAP_CORE_AT_EL0) && \ + defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64) +void thread_get_user_kdata(struct mobj **mobj, size_t *offset, + vaddr_t *va, size_t *sz); +#else +static inline void thread_get_user_kdata(struct mobj **mobj, size_t *offset, + vaddr_t *va, size_t *sz) +{ + *mobj = NULL; + *offset = 0; + *va = 0; + *sz = 0; +} +#endif + +/* + * Disables and empties the prealloc RPC cache one reference at a time. If + * all threads are idle this function returns true and a cookie of one shm + * object which was removed from the cache. When the cache is empty *cookie + * is set to 0 and the cache is disabled else a valid cookie value. If one + * thread isn't idle this function returns false. + */ +bool thread_disable_prealloc_rpc_cache(uint64_t *cookie); + +/* + * Enabled the prealloc RPC cache. If all threads are idle the cache is + * enabled and this function returns true. If one thread isn't idle this + * function return false. + */ +bool thread_enable_prealloc_rpc_cache(void); + +unsigned long thread_hvc(unsigned long func_id, unsigned long a1, + unsigned long a2, unsigned long a3); +unsigned long thread_smc(unsigned long func_id, unsigned long a1, + unsigned long a2, unsigned long a3); +void thread_smccc(struct thread_smc_args *arg_res); +#endif /*__ASSEMBLER__*/ +#endif /*__KERNEL_THREAD_ARCH_H*/ diff --git a/optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h b/optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h new file mode 100644 index 0000000..450d417 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/thread_private_arch.h @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef __KERNEL_THREAD_PRIVATE_ARCH_H +#define __KERNEL_THREAD_PRIVATE_ARCH_H + +#ifndef __ASSEMBLER__ + +#include +#include +#include + +#ifdef CFG_WITH_ARM_TRUSTED_FW +#define STACK_TMP_OFFS 0 +#else +#define STACK_TMP_OFFS SM_STACK_TMP_RESERVE_SIZE +#endif + +#ifdef ARM32 +#ifdef CFG_CORE_SANITIZE_KADDRESS +#define STACK_TMP_SIZE (3072 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) +#else +#define STACK_TMP_SIZE (2048 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) +#endif +#define STACK_THREAD_SIZE (8192 + CFG_STACK_THREAD_EXTRA) + +#if defined(CFG_CORE_SANITIZE_KADDRESS) || defined(__clang__) || \ + !defined(CFG_CRYPTO_WITH_CE) +#define STACK_ABT_SIZE 3072 +#else +#define STACK_ABT_SIZE 2048 +#endif + +#endif /*ARM32*/ + +#ifdef ARM64 +#if defined(__clang__) && !defined(__OPTIMIZE_SIZE__) +#define STACK_TMP_SIZE (4096 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) +#else +#define STACK_TMP_SIZE (2048 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) +#endif +#define STACK_THREAD_SIZE (8192 + CFG_STACK_THREAD_EXTRA) + +#if TRACE_LEVEL > 0 +#define STACK_ABT_SIZE 3072 +#else +#define STACK_ABT_SIZE 1024 +#endif +#endif /*ARM64*/ + +#ifdef CFG_CORE_DEBUG_CHECK_STACKS +/* + * Extra space added to each stack in order to reliably detect and dump stack + * overflows. Should cover the maximum expected overflow size caused by any C + * function (say, 512 bytes; no function should have that much local variables), + * plus the maximum stack space needed by __cyg_profile_func_exit(): about 1 KB, + * a large part of which is used to print the call stack. Total: 1.5 KB. + */ +#define STACK_CHECK_EXTRA 1536 +#else +#define STACK_CHECK_EXTRA 0 +#endif + +#ifdef ARM64 +struct thread_user_mode_rec { + uint64_t ctx_regs_ptr; + uint64_t exit_status0_ptr; + uint64_t exit_status1_ptr; + uint64_t pad; + uint64_t x[31 - 19]; /* x19..x30 */ +}; +#endif /*ARM64*/ + +#ifdef CFG_WITH_VFP +struct thread_vfp_state { + bool ns_saved; + bool sec_saved; + bool sec_lazy_saved; + struct vfp_state ns; + struct vfp_state sec; + struct thread_user_vfp_state *uvfp; +}; + +#endif /*CFG_WITH_VFP*/ +#endif /*__ASSEMBLER__*/ + +#ifdef ARM64 +#ifdef CFG_WITH_VFP +#define THREAD_VFP_STATE_SIZE \ + (16 + (16 * 32 + 16) * 2 + 16) +#else +#define THREAD_VFP_STATE_SIZE 0 +#endif +#endif /*ARM64*/ + +#ifndef __ASSEMBLER__ + +/* + * During boot note the part of code and data that needs to be mapped while + * in user mode. The provided address and size have to be page aligned. + * Note that the code and data will be mapped at the lowest possible + * addresses available for user space (see core_mmu_get_user_va_range()). + */ +extern long thread_user_kcode_offset; + +/* + * Initializes VBAR for current CPU (called by thread_init_per_cpu() + */ +void thread_init_vbar(vaddr_t addr); + +void thread_excp_vect(void); +void thread_excp_vect_wa_spectre_v2(void); +void thread_excp_vect_wa_a15_spectre_v2(void); +void thread_excp_vect_wa_spectre_bhb(void); +void thread_excp_vect_end(void); + +/* + * Assembly function as the first function in a thread. Handles a stdcall, + * a0-a3 holds the parameters. Hands over to __thread_std_smc_entry() when + * everything is set up and does some post processing once + * __thread_std_smc_entry() returns. + */ +void thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5); +uint32_t __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5); + +void thread_sp_alloc_and_run(struct thread_smc_args *args); + +/* + * 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); + +uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, + uint32_t *exit_status0, + uint32_t *exit_status1); + +/* + * Private functions made available for thread_asm.S + */ + +/* Returns the temp stack for current CPU */ +void *thread_get_tmp_sp(void); + +/* + * 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, vaddr_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); + +#ifdef ARM32 +/* Sets sp for abort mode */ +void thread_set_abt_sp(vaddr_t sp); + +/* Sets sp for undefined mode */ +void thread_set_und_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); + +/* Read usr_sp banked CPU register */ +uint32_t thread_get_usr_sp(void); +uint32_t thread_get_usr_lr(void); +void thread_set_usr_lr(uint32_t usr_lr); +#endif /*ARM32*/ + +void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5); +void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3); + +/* + * 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 4 +#ifdef CFG_CORE_FFA +struct thread_rpc_arg { + union { + struct { + uint32_t w1; + uint32_t w4; + uint32_t w5; + uint32_t w6; + } call; + struct { + uint32_t w4; + uint32_t w5; + uint32_t w6; + } ret; + uint32_t pad[THREAD_RPC_NUM_ARGS]; + }; +}; + +void thread_rpc(struct thread_rpc_arg *rpc_arg); +#else +void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); +#endif + +/* + * Called from assembly only, vector_fast_smc_entry(). Handles a fast SMC + * by dispatching it to the registered fast SMC handler. + */ +void thread_handle_fast_smc(struct thread_smc_args *args); + +/* + * Called from assembly only, vector_std_smc_entry(). Handles a std SMC by + * dispatching it to the registered std SMC handler. + */ +uint32_t thread_handle_std_smc(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6, uint32_t a7); + +/* Called from assembly only. Handles a SVC from user mode. */ +void thread_scall_handler(struct thread_scall_regs *regs); + +void thread_spmc_register_secondary_ep(vaddr_t ep); +#endif /*__ASSEMBLER__*/ +#endif /*__KERNEL_THREAD_PRIVATE_ARCH_H*/ diff --git a/optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h b/optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h new file mode 100644 index 0000000..2d43c50 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/thread_spmc.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Arm Limited. + */ +#ifndef __KERNEL_THREAD_SPMC_H +#define __KERNEL_THREAD_SPMC_H + +#include +#include + +/* FF-A endpoint base ID when OP-TEE is used as a S-EL1 endpoint */ +#define SPMC_ENDPOINT_ID 0x8001 + +struct ffa_rxtx { + void *rx; + void *tx; + unsigned int size; + unsigned int spinlock; + bool tx_is_mine; +}; + +void spmc_handle_rxtx_map(struct thread_smc_args *args, struct ffa_rxtx *buf); +void spmc_handle_rxtx_unmap(struct thread_smc_args *args, struct ffa_rxtx *buf); +void spmc_handle_rx_release(struct thread_smc_args *args, struct ffa_rxtx *buf); +void spmc_handle_version(struct thread_smc_args *args); + +void spmc_set_args(struct thread_smc_args *args, uint32_t fid, uint32_t src_dst, + uint32_t w2, uint32_t w3, uint32_t w4, uint32_t w5); +void spmc_handle_partition_info_get(struct thread_smc_args *args, + struct ffa_rxtx *rxtx); +void spmc_fill_partition_entry(struct ffa_partition_info *fpi, + uint16_t endpoint_id, + uint16_t execution_context); +#if !defined(CFG_CORE_SEL1_SPMC) +struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie); +void thread_spmc_relinquish(uint64_t memory_region_handle); +#endif + +#endif /* __KERNEL_THREAD_SPMC_H */ diff --git a/optee/optee_os/core/arch/arm/include/kernel/tlb_helpers.h b/optee/optee_os/core/arch/arm/include/kernel/tlb_helpers.h new file mode 100644 index 0000000..2dbcbcf --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/tlb_helpers.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef TLB_HELPERS_H +#define TLB_HELPERS_H + +#include + +#ifndef __ASSEMBLER__ +#include + +void tlbi_all(void); +void tlbi_asid(unsigned long asid); +void tlbi_mva_allasid(unsigned long addr); + +static inline void tlbi_mva_allasid_nosync(vaddr_t va) +{ +#ifdef ARM64 + tlbi_vaae1is(va >> TLBI_MVA_SHIFT); +#else + write_tlbimvaais(va); +#endif +} + +static inline void tlbi_mva_asid_nosync(vaddr_t va, uint32_t asid) +{ + uint32_t a = asid & TLBI_ASID_MASK; + +#ifdef ARM64 + tlbi_vale1is((va >> TLBI_MVA_SHIFT) | SHIFT_U64(a, TLBI_ASID_SHIFT)); + tlbi_vale1is((va >> TLBI_MVA_SHIFT) | + SHIFT_U64(a | 1, TLBI_ASID_SHIFT)); +#else + write_tlbimvais((va & ~(BIT32(TLBI_MVA_SHIFT) - 1)) | a); + write_tlbimvais((va & ~(BIT32(TLBI_MVA_SHIFT) - 1)) | a | 1); +#endif +} + +static inline void tlbi_mva_asid(vaddr_t va, uint32_t asid) +{ + dsb_ishst(); + tlbi_mva_asid_nosync(va, asid); + dsb_ish(); + isb(); +} +#endif /*!__ASSEMBLER__*/ + +#endif /* TLB_HELPERS_H */ diff --git a/optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h b/optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h new file mode 100644 index 0000000..6e9097d --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/tz_proc_def.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include + +/* + * General constants + */ + +/* + * CP15 Multiprocessor Affinity register (MPIDR) + */ +#define CP15_CONFIG_CPU_ID_MASK U(0x00000003) +#define CPU_ID0 U(0x00000000) +#define CPU_ID1 U(0x00000001) + +/* + * CP15 Secure configuration register + */ +#define CP15_CONFIG_NS_MASK U(0x00000001) +#define CP15_CONFIG_IRQ_MASK U(0x00000002) +#define CP15_CONFIG_FIQ_MASK U(0x00000004) +#define CP15_CONFIG_EA_MASK U(0x00000008) +#define CP15_CONFIG_FW_MASK U(0x00000010) +#define CP15_CONFIG_AW_MASK U(0x00000020) +#define CP15_CONFIG_nET_MASK U(0x00000040) + +/* + * CP15 Control register + */ +#define CP15_CONTROL_M_MASK U(0x00000001) +#define CP15_CONTROL_C_MASK U(0x00000004) +#define CP15_CONTROL_Z_MASK U(0x00000800) +#define CP15_CONTROL_I_MASK U(0x00001000) +#define CP15_CONTROL_V_MASK U(0x00002000) +#define CP15_CONTROL_HA_MASK U(0x00020000) +#define CP15_CONTROL_EE_MASK U(0x02000000) +#define CP15_CONTROL_NMFI_MASK U(0x08000000) +#define CP15_CONTROL_TRE_MASK U(0x10000000) +#define CP15_CONTROL_AFE_MASK U(0x20000000) +#define CP15_CONTROL_TE_MASK U(0x40000000) + +/* + * CP15 Auxiliary Control register + */ +#define CP15_CONTROL_SMP_MASK U(0x00000040) +#define CP15_CONTROL_EXCL_MASK U(0x00000080) + +/* + * CP15 Non secure access control register + */ +#define CP15_NSAC_TL_MASK U(0x10000) +#define CP15_NSAC_CL_MASK U(0x20000) +#define CP15_NSAC_CPN_MASK U(0x3FFF) + +/* + * CP15 Cache register + */ +#define CP15_CACHE_ADDR_R_BIT U(12) +#define CP15_CACHE_ADDR_L_BIT (U(32) - CP15_CACHE_ADDR_R_BIT) +#define CP15_CACHE_RESULT_MASK U(0x00000001) + +/* + * CP15 TCM register + * + * ITCM configuration (4kbytes, @0x20100000, enabled) + * DTCM configuration (4kbytes, @0x20101000, enabled) + */ +#define CP15_TCM_ENABLE_MASK U(0x00000001) +#define CP15_TCM_INSTR_TCM U(0x2010000C) +#define CP15_TCM_DATA_TCM U(0x2010100C) + +/* + * CP15 cache lockdown register + * + * ITCM configuration (4kbytes, @0x20100000, enabled) + * DTCM configuration (4kbytes, @0x20101000, enabled) + */ +#define CP15_CACHE_LOCK_ALLWAYS_MASK U(0x0000000F) + +/* + * CP15 cache cleaning constant definition + */ +/* start of line number field offset in way/index format */ +#define LINE_FIELD_OFFSET U(5) +/* Warning: this assumes a 256 lines/way cache (32kB cache) */ +#define LINE_FIELD_OVERFLOW U(13) +/* start of way number field offset in way/index format */ +#define WAY_FIELD_OFFSET U(30) diff --git a/optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_def.h b/optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_def.h new file mode 100644 index 0000000..25215b5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_def.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef TZ_SSVCE_DEF_H +#define TZ_SSVCE_DEF_H + +#include +#include + +/* + * ARMv7 Secure Services library + */ + +#define CPSR_OFFSET U(0x00) +#define STACK_INT_USAGE U(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 U(4) +#define SSAPI_RET_FROM_RPC_SERV U(5) + +/* + * TEE monitor: status returned by the routine that checks the entry + * reason (valid Service ID / secure context). + */ +#define SEC_INVALID_ENTRY U(0) +#define SEC_PRE_INIT_ENTRY U(1) +#define SEC_RET_FROM_INT_ENTRY U(2) +#define SEC_RET_FROM_RPC_ENTRY U(3) +#define SEC_NORMAL_ENTRY U(4) + +/* + * teecore exit reason. + * Set by Secure in R4 before SMC to request a switch to NSec. + */ +#define SEC_EXIT_NORMAL U(1) +#define SEC_EXIT_START_EXT_CODE U(2) +#define SEC_EXIT_INT U(3) +#define SEC_EXIT_RPC_CALL U(4) +#define SEC_EXIT_FIRST U(5) +#define SEC_EXIT_DEEP_SLEEP U(6) + +/* misc */ + +#define SEC_UNDEF_STACK_OFFSET U(4) +#define SEC_ABORT_STACK_OFFSET U(12) + +#define SEC_ENTRY_STATUS_NOK U(0) +#define SEC_ENTRY_STATUS_OK U(1) + +/* + * Outer cache iomem + */ +#define PL310_LINE_SIZE U(32) +#define PL310_8_WAYS U(8) + +#define PL310_CACHE_ID 0x0 +/* reg1 */ +#define PL310_CTRL U(0x100) +#define PL310_AUX_CTRL U(0x104) +#define PL310_TAG_RAM_CTRL U(0x108) +#define PL310_DATA_RAM_CTRL U(0x10C) +/* reg7 */ +#define PL310_SYNC U(0x730) +#define PL310_INV_BY_WAY U(0x77C) +#define PL310_CLEAN_BY_WAY U(0x7BC) +#define PL310_FLUSH_BY_WAY U(0x7FC) +#define PL310_INV_BY_PA U(0x770) +#define PL310_CLEAN_BY_PA U(0x7B0) +#define PL310_FLUSH_BY_PA U(0x7F0) +#define PL310_FLUSH_BY_INDEXWAY U(0x7F8) +/* reg9 */ +#define PL310_DCACHE_LOCKDOWN_BASE U(0x900) +#define PL310_ICACHE_LOCKDOWN_BASE U(0x904) +/* reg12 */ +#define PL310_ADDR_FILT_START U(0xC00) +#define PL310_ADDR_FILT_END U(0xC04) +/* reg15 */ +#define PL310_DEBUG_CTRL U(0xF40) +#define PL310_PREFETCH_CTRL U(0xF60) +#define PL310_POWER_CTRL U(0xF80) + +#define PL310_CTRL_ENABLE_BIT BIT32(0) +#define PL310_AUX_16WAY_BIT BIT32(16) + +#define PL310_CACHE_ID_PART_MASK GENMASK_32(9, 6) +#define PL310_CACHE_ID_PART_L310 0xC0 +#define PL310_CACHE_ID_RTL_MASK GENMASK_32(5, 0) +#define PL310_CACHE_ID_RTL_R3P2 0x8 + +/* + * SCU iomem + */ +#define SCU_CTRL U(0x00) +#define SCU_CONFIG U(0x04) +#define SCU_POWER U(0x08) +#define SCU_INV_SEC U(0x0C) +#define SCU_FILT_SA U(0x40) +#define SCU_FILT_EA U(0x44) +#define SCU_SAC U(0x50) +#define SCU_NSAC U(0x54) +#define SCU_SIZE U(0x58) +#define SCU_ERRATA744369 U(0x30) + +#define SCU_ACCESS_CONTROL_CPU0 BIT32(0) +#define SCU_ACCESS_CONTROL_CPU1 BIT32(1) +#define SCU_ACCESS_CONTROL_CPU2 BIT32(2) +#define SCU_ACCESS_CONTROL_CPU3 BIT32(3) +#define SCU_NSAC_SCU_SHIFT U(0) +#define SCU_NSAC_PTIMER_SHIFT U(4) +#define SCU_NSAC_GTIMER_SHIFT U(8) + +/* + * GIC iomem + */ +#define GIC_DIST_ISR0 U(0x080) +#define GIC_DIST_ISR1 U(0x084) +#define GIC_DIST_IPRIO U(0x400) + +/* + * CPU iomem + */ +#define CORE_ICC_ICCPMR U(0x0004) + +#endif /* TZ_SSVCE_DEF_H */ diff --git a/optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h b/optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h new file mode 100644 index 0000000..2bcd26e --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/tz_ssvce_pl310.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TZ_SSVCE_PL310_H +#define TZ_SSVCE_PL310_H + +#include +#include +#include + +vaddr_t pl310_base(void); +/* + * End address is included in the range (last address in range) + */ +void arm_cl2_cleaninvbyway(vaddr_t pl310_base); +void arm_cl2_invbyway(vaddr_t pl310_base); +void arm_cl2_cleanbyway(vaddr_t pl310_base); +void arm_cl2_cleanbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); +void arm_cl2_invbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); +void arm_cl2_cleaninvbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); + +#endif /* TZ_SSVCE_PL310_H */ diff --git a/optee/optee_os/core/arch/arm/include/kernel/vfp.h b/optee/optee_os/core/arch/arm/include/kernel/vfp.h new file mode 100644 index 0000000..49c0d73 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/kernel/vfp.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef KERNEL_VFP_H +#define KERNEL_VFP_H + +#include +#include + +#ifdef ARM32 +/* + * Advanced SIMD/floating point state on ARMv7-A or ARMv8-A AArch32 has: + * - 32 64-bit data registers + * - FPSCR (32 bits) + * - FPEXC (32 bits) + */ + +#define VFP_NUM_REGS U(32) + +struct vfp_reg { + uint64_t v; +}; + +struct vfp_state { + uint32_t fpexc; + uint32_t fpscr; + struct vfp_reg reg[VFP_NUM_REGS]; +}; +#endif + +#ifdef ARM64 +/* + * Advanced SIMD/floating point state on ARMv8-A AArch64 has: + * - 32 128-bit data registers + * - FPSR (32 bits) + * - FPCR (32 bits) + * - CPACR_EL1.FPEN (2 bits) + */ + +#define VFP_NUM_REGS U(32) + +struct vfp_reg { + uint8_t v[16]; +} __aligned(16); + +struct vfp_state { + struct vfp_reg reg[VFP_NUM_REGS]; + uint32_t fpsr; + uint32_t fpcr; + uint32_t cpacr_el1; +}; +#endif + +#ifdef CFG_WITH_VFP +/* vfp_is_enabled() - Returns true if VFP is enabled */ +bool vfp_is_enabled(void); + +/* vfp_enable() - Enables vfp */ +void vfp_enable(void); + +/* vfp_disable() - Disables vfp */ +void vfp_disable(void); +#else +static inline bool vfp_is_enabled(void) +{ + return false; +} + +static inline void vfp_enable(void) +{ +} + +static inline void vfp_disable(void) +{ +} +#endif + +/* + * vfp_lazy_save_state_init() - Saves VFP enable status and disables VFP + * @state: VFP state structure to initialize + */ +void vfp_lazy_save_state_init(struct vfp_state *state); + +/* + * vfp_lazy_save_state_final() - Saves rest of VFP state + * @state: VFP state to save to + * @force_save: Forces saving of state regardless of previous state if true. + * + * If VFP was enabled when vfp_lazy_save_state_init() was called or + * @force_save is true: save rest of state and disable VFP. Otherwise, do + * nothing. + */ +void vfp_lazy_save_state_final(struct vfp_state *state, bool force_save); + +/* + * vfp_lazy_restore_state() - Lazy restore VFP state + * @state: VFP state to restore + * + * Restores VFP enable status and also restores rest of VFP state if + * vfp_lazy_save_state_final() was called on this state. + */ +void vfp_lazy_restore_state(struct vfp_state *state, bool full_state); + +#endif /*KERNEL_VFP_H*/ diff --git a/optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h b/optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h new file mode 100644 index 0000000..498f9ae --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/mm/core_mmu_arch.h @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __CORE_MMU_ARCH_H +#define __CORE_MMU_ARCH_H + +#ifndef __ASSEMBLER__ +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include + +/* + * Platforms can define TRUSTED_{S,D}RAM_* or TZ{S,D}RAM_*. We're helping + * here with the transition to TRUSTED_{S,D}RAM_* by defining these if + * missing based on the legacy defines. + */ +#ifdef TZSRAM_BASE +#ifdef TRUSTED_SRAM_BASE +#error TRUSTED_SRAM_BASE is already defined +#endif +#define TRUSTED_SRAM_BASE TZSRAM_BASE +#define TRUSTED_SRAM_SIZE TZSRAM_SIZE +#endif + +#ifdef TZDRAM_BASE +#ifdef TRUSTED_DRAM_BASE +#error TRUSTED_DRAM_BASE is already defined +#endif +#define TRUSTED_DRAM_BASE TZDRAM_BASE +#define TRUSTED_DRAM_SIZE TZDRAM_SIZE +#endif + +#define SMALL_PAGE_SHIFT U(12) + +#ifdef CFG_WITH_LPAE +#define CORE_MMU_PGDIR_SHIFT U(21) +#define CORE_MMU_PGDIR_LEVEL U(3) +#else +#define CORE_MMU_PGDIR_SHIFT U(20) +#define CORE_MMU_PGDIR_LEVEL U(2) +#endif + +#define CORE_MMU_USER_CODE_SHIFT SMALL_PAGE_SHIFT + +#define CORE_MMU_USER_PARAM_SHIFT SMALL_PAGE_SHIFT + +/* + * Level of base table (i.e. first level of page table), + * depending on address space + */ +#if !defined(CFG_WITH_LPAE) || (CFG_LPAE_ADDR_SPACE_BITS < 40) +#define CORE_MMU_BASE_TABLE_SHIFT U(30) +#define CORE_MMU_BASE_TABLE_LEVEL U(1) +#elif (CFG_LPAE_ADDR_SPACE_BITS <= 48) +#define CORE_MMU_BASE_TABLE_SHIFT U(39) +#define CORE_MMU_BASE_TABLE_LEVEL U(0) +#else /* (CFG_LPAE_ADDR_SPACE_BITS > 48) */ +#error "CFG_WITH_LPAE with CFG_LPAE_ADDR_SPACE_BITS > 48 isn't supported!" +#endif + +#ifdef CFG_WITH_LPAE +/* + * CORE_MMU_BASE_TABLE_OFFSET is used when switching to/from reduced kernel + * mapping. The actual value depends on internals in core_mmu_lpae.c which + * we rather not expose here. There's a compile time assertion to check + * that these magic numbers are correct. + */ +#define CORE_MMU_BASE_TABLE_OFFSET \ + (CFG_TEE_CORE_NB_CORE * \ + BIT(CFG_LPAE_ADDR_SPACE_BITS - CORE_MMU_BASE_TABLE_SHIFT) * \ + U(8)) +#define CORE_MMU_BASE_TABLE_OFFSET_HIGH (CORE_MMU_BASE_TABLE_OFFSET >> 12) +#define CORE_MMU_BASE_TABLE_OFFSET_LOW (CORE_MMU_BASE_TABLE_OFFSET & 0xFFF) +#endif + +#ifndef __ASSEMBLER__ + +/* + * Assembly code in enable_mmu() depends on the layout of this struct. + */ +struct core_mmu_config { +#if defined(ARM64) + uint64_t tcr_el1; + uint64_t mair_el1; + uint64_t ttbr0_el1_base; + uint64_t ttbr0_core_offset; + uint64_t map_offset; +#elif defined(CFG_WITH_LPAE) + uint32_t ttbcr; + uint32_t mair0; + uint32_t ttbr0_base; + uint32_t ttbr0_core_offset; + uint32_t map_offset; +#else + uint32_t prrr; + uint32_t nmrr; + uint32_t dacr; + uint32_t ttbcr; + uint32_t ttbr; + uint32_t map_offset; +#endif +}; + +#ifdef CFG_WITH_LPAE +/* + * struct core_mmu_user_map - current user mapping register state + * @user_map: physical address of user map translation table + * @asid: ASID for the user map + * + * Note that this struct should be treated as an opaque struct since + * the content depends on descriptor table format. + */ +struct core_mmu_user_map { + uint64_t user_map; + uint32_t asid; +}; +#else +/* + * struct core_mmu_user_map - current user mapping register state + * @ttbr0: content of ttbr0 + * @ctxid: content of contextidr + * + * Note that this struct should be treated as an opaque struct since + * the content depends on descriptor table format. + */ +struct core_mmu_user_map { + uint32_t ttbr0; + uint32_t ctxid; +}; +#endif + +#ifdef CFG_WITH_LPAE +bool core_mmu_user_va_range_is_defined(void); +#else +static inline bool __noprof core_mmu_user_va_range_is_defined(void) +{ + return true; +} +#endif + +/* Cache maintenance operation type */ +enum cache_op { + DCACHE_CLEAN, + DCACHE_AREA_CLEAN, + DCACHE_INVALIDATE, + DCACHE_AREA_INVALIDATE, + ICACHE_INVALIDATE, + ICACHE_AREA_INVALIDATE, + DCACHE_CLEAN_INV, + DCACHE_AREA_CLEAN_INV, +}; + +/* L1/L2 cache maintenance */ +TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len); +#ifdef CFG_PL310 +TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len); +#else +static inline TEE_Result cache_op_outer(enum cache_op op __unused, + paddr_t pa __unused, + size_t len __unused) +{ + /* Nothing to do about L2 Cache Maintenance when no PL310 */ + return TEE_SUCCESS; +} +#endif + +/* Do section mapping, not support on LPAE */ +void map_memarea_sections(const struct tee_mmap_region *mm, uint32_t *ttb); + +static inline bool core_mmu_check_max_pa(paddr_t pa __maybe_unused) +{ +#if defined(ARM64) + return pa <= (BIT64(CFG_CORE_ARM64_PA_BITS) - 1); +#elif defined(CFG_CORE_LARGE_PHYS_ADDR) + return pa <= (BIT64(40) - 1); +#else + COMPILE_TIME_ASSERT(sizeof(paddr_t) == sizeof(uint32_t)); + return true; +#endif +} + +/* + * Special barrier to make sure all the changes to translation tables are + * visible before returning. + */ +static inline void core_mmu_table_write_barrier(void) +{ + dsb_ishst(); +} + +static inline bool core_mmu_entry_have_security_bit(uint32_t attr) +{ + return !(attr & TEE_MATTR_TABLE) || !IS_ENABLED(CFG_WITH_LPAE); +} + +static inline unsigned int core_mmu_get_va_width(void) +{ + if (IS_ENABLED(ARM64)) { + COMPILE_TIME_ASSERT(CFG_LPAE_ADDR_SPACE_BITS >= 32); + COMPILE_TIME_ASSERT(CFG_LPAE_ADDR_SPACE_BITS <= 48); + return CFG_LPAE_ADDR_SPACE_BITS; + } + return 32; +} +#endif /*__ASSEMBLER__*/ + +#endif /* CORE_MMU_H */ diff --git a/optee/optee_os/core/arch/arm/include/mm/generic_ram_layout.h b/optee/optee_os/core/arch/arm/include/mm/generic_ram_layout.h new file mode 100644 index 0000000..b3e0ac3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/mm/generic_ram_layout.h @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef __MM_GENERIC_RAM_LAYOUT_H +#define __MM_GENERIC_RAM_LAYOUT_H + +#include + +/* + * Generic RAM layout configuration directives + * + * Mandatory directives: + * CFG_TZDRAM_START + * CFG_TZDRAM_SIZE + * CFG_SHMEM_START + * CFG_SHMEM_SIZE + * + * Optional directives: + * CFG_TEE_LOAD_ADDR If defined sets TEE_LOAD_ADDR. If not, TEE_LOAD_ADDR + * is set by the platform or defaults to TEE_RAM_START. + * CFG_TEE_RAM_VA_SIZE Some platforms may have specific needs + * + * Optional directives when pager is enabled: + * CFG_TZSRAM_START If no set, emulated at CFG_TZDRAM_START + * CFG_TZSRAM_SIZE Default to CFG_CORE_TZSRAM_EMUL_SIZE + * + * Optional directive when CFG_SECURE_DATA_PATH is enabled: + * CFG_TEE_SDP_MEM_SIZE If CFG_TEE_SDP_MEM_BASE is not defined, SDP test + * memory byte size can be set by CFG_TEE_SDP_MEM_SIZE. + * + * This header file produces the following generic macros upon the mandatory + * and optional configuration directives listed above: + * + * TEE_RAM_START TEE core RAM physical base address + * TEE_RAM_VA_SIZE TEE core virtual memory address range size + * TEE_RAM_PH_SIZE TEE core physical RAM byte size + * TA_RAM_START TA contexts/pagestore RAM physical base address + * TA_RAM_SIZE TA contexts/pagestore RAM byte size + * TEE_SHMEM_START Non-secure static shared memory physical base address + * TEE_SHMEM_SIZE Non-secure static shared memory byte size + * + * TZDRAM_BASE Main/external secure RAM base address + * TZDRAM_SIZE Main/external secure RAM byte size + * TZSRAM_BASE On-chip secure RAM base address, required by pager. + * TZSRAM_SIZE On-chip secure RAM byte size, required by pager. + * + * TEE_LOAD_ADDR Only defined here if CFG_TEE_LOAD_ADDR is defined. + * Otherwise we expect the platform_config.h to define it + * unless which LEE_LOAD_ADDR defaults to TEE_RAM_START. + * + * TEE_RAM_VA_SIZE Set to CFG_TEE_RAM_VA_SIZE or defaults to + * CORE_MMU_PGDIR_SIZE. + * + * TEE_SDP_TEST_MEM_BASE Define if a SDP memory pool is required and none set. + * Always defined in the inner top (high addresses) + * of CFG_TZDRAM_START/_SIZE. + * TEE_SDP_TEST_MEM_SIZE Set to CFG_TEE_SDP_MEM_SIZE or a default size. + * + * ---------------------------------------------------------------------------- + * TEE RAM layout without CFG_WITH_PAGER + *_ + * +----------------------------------+ <-- CFG_TZDRAM_START + * | TEE core secure RAM (TEE_RAM) | + * +----------------------------------+ + * | Trusted Application RAM (TA_RAM) | + * +----------------------------------+ + * | SDP test memory (optional) | + * +----------------------------------+ <-- CFG_TZDRAM_START + CFG_TZDRAM_SIZE + * + * +----------------------------------+ <-- CFG_SHMEM_START + * | Non-secure static SHM | + * +----------------------------------+ <-- CFG_SHMEM_START + CFG_SHMEM_SIZE + * + * ---------------------------------------------------------------------------- + * TEE RAM layout with CFG_WITH_PAGER=y and undefined CFG_TZSRAM_START/_SIZE + * + * +----------------------------------+ <-- CFG_TZDRAM_START + * | TEE core secure RAM (TEE_RAM) | | | CFG_CORE_TZSRAM_EMUL_SIZE + * +----------------------------------+ --|-' + * | reserved (for kasan) | | TEE_RAM_VA_SIZE + * +----------------------------------+ --' + * | TA RAM / Pagestore (TA_RAM) | + * +----------------------------------+ <---- align with CORE_MMU_PGDIR_SIZE + * +----------------------------------+ <-- + * | SDP test memory (optional) | | CFG_TEE_SDP_MEM_SIZE + * +----------------------------------+ <-+ CFG_TZDRAM_START + CFG_TZDRAM_SIZE + * + * +----------------------------------+ <-- CFG_SHMEM_START + * | Non-secure static SHM | | + * +----------------------------------+ v CFG_SHMEM_SIZE + * + * ---------------------------------------------------------------------------- + * TEE RAM layout with CFG_WITH_PAGER=y and define CFG_TZSRAM_START/_SIZE + * + * +----------------------------------+ <-- CFG_TZSRAM_START + * | TEE core secure RAM (TEE_RAM) | | CFG_TZSRAM_SIZE + * +----------------------------------+ --' + * + * +----------------------------------+ <- CFG_TZDRAM_START + * | TA RAM / Pagestore (TA_RAM) | + * |----------------------------------+ <---- align with CORE_MMU_PGDIR_SIZE + * |----------------------------------+ <-- + * | SDP test memory (optional) | | CFG_TEE_SDP_MEM_SIZE + * +----------------------------------+ <-+ CFG_TZDRAM_START + CFG_TZDRAM_SIZE + * + * +----------------------------------+ <-- CFG_SHMEM_START + * | Non-secure static SHM | | + * +----------------------------------+ v CFG_SHMEM_SIZE + */ + +#ifdef CFG_TEE_LOAD_ADDR +#define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR +#else +/* Platform specific platform_config.h may set TEE_LOAD_ADDR */ +#endif + +#ifdef CFG_TEE_RAM_VA_SIZE +#define TEE_RAM_VA_SIZE CFG_TEE_RAM_VA_SIZE +#else +#define TEE_RAM_VA_SIZE CORE_MMU_PGDIR_SIZE +#endif + +#ifdef CFG_SHMEM_SIZE +#define TEE_SHMEM_SIZE CFG_SHMEM_SIZE +#endif + +#ifdef CFG_SHMEM_START +#define TEE_SHMEM_START CFG_SHMEM_START +#ifndef CFG_SHMEM_SIZE +#error CFG_SHMEM_START mandates CFG_SHMEM_SIZE +#endif +#endif + +#if defined(CFG_TZSRAM_START) +#define TZSRAM_BASE CFG_TZSRAM_START +#define TZSRAM_SIZE CFG_TZSRAM_SIZE +#endif + +#ifdef CFG_TZDRAM_START +#if !defined(CFG_WITH_PAGER) || defined(CFG_TZSRAM_START) +#define TZDRAM_BASE CFG_TZDRAM_START +#define TZDRAM_SIZE CFG_TZDRAM_SIZE +#else +#define TZSRAM_BASE CFG_TZDRAM_START +#define TZSRAM_SIZE CFG_CORE_TZSRAM_EMUL_SIZE +#define TZDRAM_BASE ROUNDUP(TZSRAM_BASE + TZSRAM_SIZE, \ + TEE_RAM_VA_SIZE) +#define TZDRAM_SIZE (CFG_TZDRAM_START + (CFG_TZDRAM_SIZE - \ + TZDRAM_BASE)) +#endif + +#ifdef CFG_WITH_PAGER +#define TEE_RAM_START TZSRAM_BASE +#define TEE_RAM_PH_SIZE TZSRAM_SIZE +#else +#define TEE_RAM_START TZDRAM_BASE +#define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE +#endif /*CFG_WITH_PAGER*/ +#endif /*CFG_TZDRAM_START*/ + +/* + * Secure data path test memory pool + * - If SDP is disabled, no SDP test memory needed. + * - If SDP is enabled, if CFG_TEE_SDP_MEM_BASE, SDP test pool is not needed. + * - If SDP is enabled and CFG_TEE_SDP_MEM_BASE not defined, a SDP test pool + * is defined at the end of the secure RAM. CFG_TEE_SDP_MEM_SIZE can set + * its size otherwise it defaults to 4MB. + */ +#if !defined(CFG_SECURE_DATA_PATH) || defined(CFG_TEE_SDP_MEM_BASE) +#define TEE_SDP_TEST_MEM_SIZE 0 +#else +#ifdef CFG_TEE_SDP_MEM_SIZE +#define TEE_SDP_TEST_MEM_SIZE CFG_TEE_SDP_MEM_SIZE +#else +#define TEE_SDP_TEST_MEM_SIZE SIZE_4M +#endif +#define TEE_SDP_TEST_MEM_BASE (CFG_TZDRAM_START + (CFG_TZDRAM_SIZE - \ + TEE_SDP_TEST_MEM_SIZE)) +#endif + +#endif /*__MM_GENERIC_RAM_LAYOUT_H*/ + diff --git a/optee/optee_os/core/arch/arm/include/optee_ffa.h b/optee/optee_os/core/arch/arm/include/optee_ffa.h new file mode 100644 index 0000000..f3d6b20 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/optee_ffa.h @@ -0,0 +1,164 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2021, Linaro Limited + */ + +/* + * This file is exported by OP-TEE and is kept in sync between secure world + * and normal world drivers. We're using ARM FF-A 1.0 specification. + */ + +#ifndef __OPTEE_FFA_H +#define __OPTEE_FFA_H + +#include + +/* + * Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and + * responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal + * messages. + * + * All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP + * are using the AArch32 SMC calling convention with register usage as + * defined in FF-A specification: + * w0: Function ID (0x8400006F or 0x84000070) + * w1: Source/Destination IDs + * w2: Reserved (MBZ) + * w3-w7: Implementation defined, free to be used below + */ + +#define OPTEE_FFA_VERSION_MAJOR UINT32_C(1) +#define OPTEE_FFA_VERSION_MINOR UINT32_C(0) + +#define OPTEE_FFA_BLOCKING_CALL(id) UINT32_C(id) +#define OPTEE_FFA_YIELDING_CALL_BIT U(31) +#define OPTEE_FFA_YIELDING_CALL(id) (UINT32_C(id) | \ + BIT32(OPTEE_FFA_YIELDING_CALL_BIT)) + +/* + * Returns the API version implemented, currently follows the FF-A version. + * Call register usage: + * w3: Service ID, OPTEE_FFA_GET_API_VERSION + * w4-w7: Not used (MBZ) + * + * Return register usage: + * w3: OPTEE_FFA_VERSION_MAJOR + * w4: OPTEE_FFA_VERSION_MINOR + * w5-w7: Not used (MBZ) + */ +#define OPTEE_FFA_GET_API_VERSION OPTEE_FFA_BLOCKING_CALL(0) + +/* + * Returns the revision of OP-TEE. + * + * 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. + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_GET_OS_VERSION + * w4-w7: Unused (MBZ) + * + * Return register usage: + * w3: CFG_OPTEE_REVISION_MAJOR + * w4: CFG_OPTEE_REVISION_MINOR + * w5: TEE_IMPL_GIT_SHA1 (or zero if not supported) + */ +#define OPTEE_FFA_GET_OS_VERSION OPTEE_FFA_BLOCKING_CALL(1) + +/* + * Exchange capabilities between normal world and secure world. + * + * Currently there are no defined capabilities. When features are added new + * capabilities may be added. + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES + * w4-w7: Note used (MBZ) + * + * Return register usage: + * w3: Error code, 0 on success + * w4: Bit[7:0]: Number of parameters needed for RPC to be supplied + * as the second MSG arg struct for + * OPTEE_FFA_YIELDING_CALL_WITH_ARG. + * Bit[31:8]: Reserved (MBZ) + * w5: Bitfield of secure world capabilities OPTEE_FFA_SEC_CAP_* below, + * unused bits MBZ. + * w6-w7: Not used (MBZ) + */ +/* + * Secure world supports using an offset into the argument shared memory + * object, see also OPTEE_FFA_YIELDING_CALL_WITH_ARG + */ +#define OPTEE_FFA_SEC_CAP_ARG_OFFSET BIT(0) + +#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2) + +/* + * Unregister shared memory + * + * Call register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM + * w4: Shared memory handle, lower bits + * w5: Shared memory handle, higher bits + * w6-w7: Not used (MBZ) + * + * Return register usage: + * w3: Error code, 0 on success + * w4-w7: Note used (MBZ) + */ +#define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3) + +/* + * Call with struct optee_msg_arg as argument in the supplied shared memory + * with a zero internal offset and normal cached memory attributes. + * Register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG + * w4: Lower 32 bits of a 64-bit Shared memory handle + * w5: Upper 32 bits of a 64-bit Shared memory handle + * w6: Offset into shared memory pointing to a struct optee_msg_arg + * right after the parameters of this struct (at offset + * OPTEE_MSG_GET_ARG_SIZE(num_params) follows a struct optee_msg_arg + * for RPC, this struct has reserved space for the number of RPC + * parameters as returned by OPTEE_FFA_EXCHANGE_CAPABILITIES. + * MBZ unless the bit OPTEE_FFA_SEC_CAP_ARG_OFFSET is received with + * OPTEE_FFA_EXCHANGE_CAPABILITIES. + * w7: Not used (MBZ) + * Resume from RPC. Register usage: + * w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME + * w4-w6: Not used (MBZ) + * w7: Resume info + * + * Normal return (yielding call is completed). Register usage: + * w3: Error code, 0 on success + * w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE + * w5-w7: Not used (MBZ) + * + * RPC interrupt return (RPC from secure world). Register usage: + * w3: Error code == 0 + * w4: Any defined RPC code but OPTEE_FFA_YIELDING_CALL_RETURN_DONE + * w5-w6: Not used (MBZ) + * w7: Resume info + * + * Possible error codes in register w3: + * 0: Success + * FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START + * OPTEE_FFA_YIELDING_CALL_RESUME + * + * Possible error codes for OPTEE_FFA_YIELDING_CALL_START, + * FFA_BUSY: Number of OP-TEE OS threads exceeded, + * try again later + * FFA_DENIED: RPC shared memory object not found + * FFA_INVALID_PARAMETER: Bad shared memory handle or offset into the memory + * + * Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME + * FFA_INVALID_PARAMETER: Bad resume info + */ +#define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0) +#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(1) + +#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE U(0) +#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD U(1) +#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT U(2) + +#endif /*__OPTEE_FFA_H*/ diff --git a/optee/optee_os/core/arch/arm/include/pta_stmm.h b/optee/optee_os/core/arch/arm/include/pta_stmm.h new file mode 100644 index 0000000..891647a --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/pta_stmm.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018-2020, Linaro Limited + */ +#ifndef __PTA_STMM_H +#define __PTA_STMM_H + +/* + * Interface to the pseudo TA, which provides a communication channel with + * the Standalone MM SP (StMM) running at S-EL0. + */ + +#define PTA_STMM_UUID { 0xed32d533, 0x99e6, 0x4209, {\ + 0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 } } + +/* + * Pass a buffer to Standalone MM SP + * + * [in/out] memref[0]: EFI Communication buffer + * [out] value[1].a: EFI return code + */ +#define PTA_STMM_CMD_COMMUNICATE 0 + +#endif /* __PTA_STMM_H */ + diff --git a/optee/optee_os/core/arch/arm/include/scmi/scmi_server.h b/optee/optee_os/core/arch/arm/include/scmi/scmi_server.h new file mode 100644 index 0000000..a28fd66 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/scmi/scmi_server.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2022, Linaro Limited + */ +#ifndef SCMI_SERVER_H +#define SCMI_SERVER_H + +#include +#include + +#ifdef CFG_SCMI_SCPFW +/* + * Request processing of an incoming event in the SCMI server for a target + * MHU/SMT mailbox. + * + * @channel_id: SCMI channel handler + */ +TEE_Result scmi_server_smt_process_thread(unsigned int channel_id); + +/* + * Request processing of an incoming event in the SCMI server for a target + * MHU/MSG mailbox. + * + * @id: SCMI channel handler + * @in_buf: Input message MSG buffer + * @in_size: Input message MSG buffer size + * @out_buf: Output message MSG buffer + * @out_size: Reference to output message MSG buffer size + */ +TEE_Result scmi_server_msg_process_thread(unsigned int channel_id, void *in_buf, + size_t in_size, void *out_buf, + size_t *out_size); + +/* + * Get SCP-firmware channel device ID from the client channel ID. + * + * @channel_id: SCMI channel handler + * @handle: Output SCP-firmware device ID for the target SCMI mailbox + */ +TEE_Result scmi_server_get_channel(unsigned int channel_id, int *handle); + +/* Get number of channels supported by the SCMI platform/server */ +int scmi_server_get_channels_count(void); + +#else /* CFG_SCMI_SCPFW */ +static inline +TEE_Result scmi_server_smt_process_thread(unsigned int channel_id __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline +TEE_Result scmi_server_msg_process_thread(unsigned int channel_id __unused, + void *in_buf __unused, + size_t in_size __unused, + void *out_buf __unused, + size_t *out_size __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result scmi_server_get_channel(unsigned int id __unused, + int *handle __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline int scmi_server_get_channels_count(void) +{ + return 0; +} +#endif /* CFG_SCMI_SCPFW */ +#endif /* SCMI_SERVER_H */ diff --git a/optee/optee_os/core/arch/arm/include/sm/optee_smc.h b/optee/optee_os/core/arch/arm/include/sm/optee_smc.h new file mode 100644 index 0000000..04a3839 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/optee_smc.h @@ -0,0 +1,708 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2021, Linaro Limited + */ +#ifndef OPTEE_SMC_H +#define OPTEE_SMC_H + +#include + +/* + * This file is exported by OP-TEE and is in kept in sync between secure + * world and normal world kernel driver. We're following ARM SMC Calling + * Convention as specified in + * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + * + * This file depends on optee_msg.h being included to expand the SMC id + * macros below. + */ + +#define OPTEE_SMC_32 U(0) +#define OPTEE_SMC_64 U(0x40000000) +#define OPTEE_SMC_FAST_CALL U(0x80000000) +#define OPTEE_SMC_STD_CALL U(0) + +#define OPTEE_SMC_OWNER_MASK U(0x3F) +#define OPTEE_SMC_OWNER_SHIFT U(24) + +#define OPTEE_SMC_FUNC_MASK U(0xFFFF) + +#define OPTEE_SMC_IS_FAST_CALL(smc_val) ((smc_val) & OPTEE_SMC_FAST_CALL) +#define OPTEE_SMC_IS_64(smc_val) ((smc_val) & OPTEE_SMC_64) +#define OPTEE_SMC_FUNC_NUM(smc_val) ((smc_val) & OPTEE_SMC_FUNC_MASK) +#define OPTEE_SMC_OWNER_NUM(smc_val) \ + (((smc_val) >> OPTEE_SMC_OWNER_SHIFT) & OPTEE_SMC_OWNER_MASK) + +#define OPTEE_SMC_CALL_VAL(type, calling_convention, owner, func_num) \ + ((type) | (calling_convention) | \ + (((owner) & OPTEE_SMC_OWNER_MASK) << \ + OPTEE_SMC_OWNER_SHIFT) |\ + ((func_num) & OPTEE_SMC_FUNC_MASK)) + +#define OPTEE_SMC_STD_CALL_VAL(func_num) \ + OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_STD_CALL, \ + OPTEE_SMC_OWNER_TRUSTED_OS, (func_num)) +#define OPTEE_SMC_FAST_CALL_VAL(func_num) \ + OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ + OPTEE_SMC_OWNER_TRUSTED_OS, (func_num)) + +#define OPTEE_SMC_OWNER_ARCH U(0) +#define OPTEE_SMC_OWNER_CPU U(1) +#define OPTEE_SMC_OWNER_SIP U(2) +#define OPTEE_SMC_OWNER_OEM U(3) +#define OPTEE_SMC_OWNER_STANDARD U(4) +#define OPTEE_SMC_OWNER_TRUSTED_APP U(48) +#define OPTEE_SMC_OWNER_TRUSTED_OS U(50) + +#define OPTEE_SMC_OWNER_TRUSTED_OS_OPTEED U(62) +#define OPTEE_SMC_OWNER_TRUSTED_OS_API U(63) + +/* + * Function specified by SMC Calling convention. + */ +#define OPTEE_SMC_FUNCID_CALLS_COUNT U(0xFF00) +#define OPTEE_SMC_CALLS_COUNT \ + OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ + OPTEE_SMC_OWNER_TRUSTED_OS_API, \ + OPTEE_SMC_FUNCID_CALLS_COUNT) + +/* + * Normal cached memory (write-back), shareable for SMP systems and not + * shareable for UP systems. + */ +#define OPTEE_SMC_SHM_CACHED U(1) + +/* + * a0..a7 is used as register names in the descriptions below, on arm32 + * that translates to r0..r7 and on arm64 to w0..w7. In both cases it's + * 32-bit registers. + */ + +/* + * Function specified by SMC Calling convention + * + * Return the following UID if using API specified in this file + * without further extensions: + * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. + * see also OPTEE_MSG_UID_* in optee_msg.h + */ +#define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID +#define OPTEE_SMC_CALLS_UID \ + OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ + OPTEE_SMC_OWNER_TRUSTED_OS_API, \ + OPTEE_SMC_FUNCID_CALLS_UID) + +/* + * Function specified by SMC Calling convention + * + * Returns 2.0 if using API specified in this file without further extensions. + * see also OPTEE_MSG_REVISION_* in optee_msg.h + */ +#define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION +#define OPTEE_SMC_CALLS_REVISION \ + OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ + OPTEE_SMC_OWNER_TRUSTED_OS_API, \ + OPTEE_SMC_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 a0-4 in the same way as OPTEE_SMC_CALLS_UID + * described above. + */ +#define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID +#define OPTEE_SMC_CALL_GET_OS_UUID \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_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 a0-1 in the same way as OPTEE_SMC_CALLS_REVISION + * described above. May optionally return a 32-bit build identifier in a2, + * with zero meaning unspecified. + */ +#define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION +#define OPTEE_SMC_CALL_GET_OS_REVISION \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION) + +/* + * Call with struct optee_msg_arg as argument + * + * When called with OPTEE_SMC_CALL_WITH_RPC_ARG or + * OPTEE_SMC_CALL_WITH_REGD_ARG in a0 there is one RPC struct optee_msg_arg + * following after the first struct optee_msg_arg. The RPC struct + * optee_msg_arg has reserved space for the number of RPC parameters as + * returned by OPTEE_SMC_EXCHANGE_CAPABILITIES. + * + * When calling these functions normal world has a few responsibilities: + * 1. It must be able to handle eventual RPCs + * 2. Non-secure interrupts should not be masked + * 3. If asynchronous notifications has been negotiated successfully, then + * the interrupt for asynchronous notifications should be unmasked + * during this call. + * + * Call register usage, OPTEE_SMC_CALL_WITH_ARG and + * OPTEE_SMC_CALL_WITH_RPC_ARG: + * a0 SMC Function ID, OPTEE_SMC_CALL_WITH_ARG or OPTEE_SMC_CALL_WITH_RPC_ARG + * a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg + * a2 Lower 32 bits of a 64-bit physical pointer to a struct optee_msg_arg + * a3 Cache settings, not used if physical pointer is in a predefined shared + * memory area else per OPTEE_SMC_SHM_* + * a4-6 Not used + * a7 Hypervisor Client ID register + * + * Call register usage, OPTEE_SMC_CALL_WITH_REGD_ARG: + * a0 SMC Function ID, OPTEE_SMC_CALL_WITH_REGD_ARG + * a1 Upper 32 bits of a 64-bit shared memory cookie + * a2 Lower 32 bits of a 64-bit shared memory cookie + * a3 Offset of the struct optee_msg_arg in the shared memory with the + * supplied cookie + * a4-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 Return value, OPTEE_SMC_RETURN_* + * a1-3 Not used + * a4-7 Preserved + * + * OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage: + * a0 Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT + * a1-3 Preserved + * a4-7 Preserved + * + * RPC return register usage: + * a0 Return value, OPTEE_SMC_RETURN_IS_RPC(val) + * a1-2 RPC parameters + * a3-7 Resume information, must be preserved + * + * Possible return values: + * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this + * function. + * OPTEE_SMC_RETURN_OK Call completed, result updated in + * the previously supplied struct + * optee_msg_arg. + * OPTEE_SMC_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded, + * try again later. + * OPTEE_SMC_RETURN_EBADADDR Bad physical pointer to struct + * optee_msg_arg. + * OPTEE_SMC_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg + * OPTEE_SMC_RETURN_IS_RPC() Call suspended by RPC call to normal + * world. + */ +#define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG +#define OPTEE_SMC_CALL_WITH_ARG \ + OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG) +#define OPTEE_SMC_CALL_WITH_RPC_ARG \ + OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_RPC_ARG) +#define OPTEE_SMC_CALL_WITH_REGD_ARG \ + OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG) + +/* + * Get Shared Memory Config + * + * Returns the Secure/Non-secure shared memory config. + * + * Call register usage: + * a0 SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Have config return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 Physical address of start of SHM + * a2 Size of of SHM + * a3 Cache settings of memory, as defined by the + * OPTEE_SMC_SHM_* values above + * a4-7 Preserved + * + * Not available register usage: + * a0 OPTEE_SMC_RETURN_ENOTAVAIL + * a1-3 Not used + * a4-7 Preserved + */ +#define OPTEE_SMC_FUNCID_GET_SHM_CONFIG 7 +#define OPTEE_SMC_GET_SHM_CONFIG \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG) + +/* + * Configures L2CC mutex + * + * Disables, enables usage of L2CC mutex. Returns or sets physical address + * of L2CC mutex. + * + * Call register usage: + * a0 SMC Function ID, OPTEE_SMC_L2CC_MUTEX + * a1 OPTEE_SMC_L2CC_MUTEX_GET_ADDR Get physical address of mutex + * OPTEE_SMC_L2CC_MUTEX_SET_ADDR Set physical address of mutex + * OPTEE_SMC_L2CC_MUTEX_ENABLE Enable usage of mutex + * OPTEE_SMC_L2CC_MUTEX_DISABLE Disable usage of mutex + * a2 if a1 == OPTEE_SMC_L2CC_MUTEX_SET_ADDR, upper 32bit of a 64bit + * physical address of mutex + * a3 if a1 == OPTEE_SMC_L2CC_MUTEX_SET_ADDR, lower 32bit of a 64bit + * physical address of mutex + * a3-6 Not used + * a7 Hypervisor Client ID register + * + * Have config return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 Preserved + * a2 if a1 == OPTEE_SMC_L2CC_MUTEX_GET_ADDR, upper 32bit of a 64bit + * physical address of mutex + * a3 if a1 == OPTEE_SMC_L2CC_MUTEX_GET_ADDR, lower 32bit of a 64bit + * physical address of mutex + * a3-7 Preserved + * + * Error return register usage: + * a0 OPTEE_SMC_RETURN_ENOTAVAIL Physical address not available + * OPTEE_SMC_RETURN_EBADADDR Bad supplied physical address + * OPTEE_SMC_RETURN_EBADCMD Unsupported value in a1 + * a1-7 Preserved + */ +#define OPTEE_SMC_L2CC_MUTEX_GET_ADDR U(0) +#define OPTEE_SMC_L2CC_MUTEX_SET_ADDR U(1) +#define OPTEE_SMC_L2CC_MUTEX_ENABLE U(2) +#define OPTEE_SMC_L2CC_MUTEX_DISABLE U(3) +#define OPTEE_SMC_FUNCID_L2CC_MUTEX U(8) +#define OPTEE_SMC_L2CC_MUTEX \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_L2CC_MUTEX) + +/* + * Exchanges capabilities between normal world and secure world + * + * Call register usage: + * a0 SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES + * a1 bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_* + * a2-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_* + * a2 The maximum secure world notification number + * a3 Bit[7:0]: Number of parameters needed for RPC to be supplied + * as the second MSG arg struct for + * OPTEE_SMC_CALL_WITH_ARG + * Bit[31:8]: Reserved (MBZ) + * a3-7 Preserved + * + * Error return register usage: + * a0 OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world + * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_* + * a2-7 Preserved + */ +/* Normal world works as a uniprocessor system */ +#define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR BIT(0) +/* Secure world has reserved shared memory for normal world to use */ +#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM BIT(0) +/* Secure world can communicate via previously unregistered shared memory */ +#define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM BIT(1) +/* + * Secure world supports commands "register/unregister shared memory", + * secure world accepts command buffers located in any parts of non-secure RAM + */ +#define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2) +/* Secure world is built with virtualization support */ +#define OPTEE_SMC_SEC_CAP_VIRTUALIZATION BIT(3) +/* Secure world supports Shared Memory with a NULL reference */ +#define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4) +/* Secure world supports asynchronous notification of normal world */ +#define OPTEE_SMC_SEC_CAP_ASYNC_NOTIF BIT(5) +/* Secure world supports pre-allocating RPC arg struct */ +#define OPTEE_SMC_SEC_CAP_RPC_ARG BIT(6) + +#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES U(9) +#define OPTEE_SMC_EXCHANGE_CAPABILITIES \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES) + +/* + * Disable and empties cache of shared memory objects + * + * Secure world can cache frequently used shared memory objects, for + * example objects used as RPC arguments. When secure world is idle this + * function returns one shared memory reference to free. To disable the + * cache and free all cached objects this function has to be called until + * it returns OPTEE_SMC_RETURN_ENOTAVAIL. + * + * Call register usage: + * a0 SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 Upper 32 bits of a 64-bit Shared memory cookie + * a2 Lower 32 bits of a 64-bit Shared memory cookie + * a3-7 Preserved + * + * Cache empty return register usage: + * a0 OPTEE_SMC_RETURN_ENOTAVAIL + * a1-7 Preserved + * + * Not idle return register usage: + * a0 OPTEE_SMC_RETURN_EBUSY + * a1-7 Preserved + */ +#define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE U(10) +#define OPTEE_SMC_DISABLE_SHM_CACHE \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE) + +/* + * Enable cache of shared memory objects + * + * Secure world can cache frequently used shared memory objects, for + * example objects used as RPC arguments. When secure world is idle this + * function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If + * secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned. + * + * Call register usage: + * a0 SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1-7 Preserved + * + * Not idle return register usage: + * a0 OPTEE_SMC_RETURN_EBUSY + * a1-7 Preserved + */ +#define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE U(11) +#define OPTEE_SMC_ENABLE_SHM_CACHE \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE) + +/* + * Release of secondary cores + * + * OP-TEE in secure world is in charge of the release process of secondary + * cores. The Rich OS issue the this request to ask OP-TEE to boot up the + * secondary cores, go through the OP-TEE per-core initialization, and then + * switch to the Non-seCure world with the Rich OS provided entry address. + * The secondary cores enter Non-Secure world in SVC mode, with Thumb, FIQ, + * IRQ and Abort bits disabled. + * + * Call register usage: + * a0 SMC Function ID, OPTEE_SMC_BOOT_SECONDARY + * a1 Index of secondary core to boot + * a2 Upper 32 bits of a 64-bit Non-Secure world entry physical address + * a3 Lower 32 bits of a 64-bit Non-Secure world entry physical address + * a4-7 Not used + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1-7 Preserved + * + * Error return: + * a0 OPTEE_SMC_RETURN_EBADCMD Core index out of range + * a1-7 Preserved + * + * Not idle return register usage: + * a0 OPTEE_SMC_RETURN_EBUSY + * a1-7 Preserved + */ +#define OPTEE_SMC_FUNCID_BOOT_SECONDARY U(12) +#define OPTEE_SMC_BOOT_SECONDARY \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_BOOT_SECONDARY) + +/* + * Inform OP-TEE about a new virtual machine + * + * Hypervisor issues this call during virtual machine (guest) creation. + * OP-TEE records client id of new virtual machine and prepares + * to receive requests from it. This call is available only if OP-TEE + * was built with virtualization support. + * + * Call requests usage: + * a0 SMC Function ID, OPTEE_SMC_VM_CREATED + * a1 Hypervisor Client ID of newly created virtual machine + * a2-6 Not used + * a7 Hypervisor Client ID register. Must be 0, because only hypervisor + * can issue this call + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1-7 Preserved + * + * Error return: + * a0 OPTEE_SMC_RETURN_ENOTAVAIL OP-TEE have no resources for + * another VM + * a1-7 Preserved + * + */ +#define OPTEE_SMC_FUNCID_VM_CREATED U(13) +#define OPTEE_SMC_VM_CREATED \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_VM_CREATED) + +/* + * Inform OP-TEE about shutdown of a virtual machine + * + * Hypervisor issues this call during virtual machine (guest) destruction. + * OP-TEE will clean up all resources associated with this VM. This call is + * available only if OP-TEE was built with virtualization support. + * + * Call requests usage: + * a0 SMC Function ID, OPTEE_SMC_VM_DESTROYED + * a1 Hypervisor Client ID of virtual machine being shut down + * a2-6 Not used + * a7 Hypervisor Client ID register. Must be 0, because only hypervisor + * can issue this call + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1-7 Preserved + * + */ +#define OPTEE_SMC_FUNCID_VM_DESTROYED U(14) +#define OPTEE_SMC_VM_DESTROYED \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_VM_DESTROYED) + +/* + * Query OP-TEE about number of supported threads + * + * Normal World OS or Hypervisor issues this call to find out how many + * threads OP-TEE supports. That is how many standard calls can be issued + * in parallel before OP-TEE will return OPTEE_SMC_RETURN_ETHREAD_LIMIT. + * + * Call requests usage: + * a0 SMC Function ID, OPTEE_SMC_GET_THREAD_COUNT + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 Number of threads + * a2-7 Preserved + * + * Error return: + * a0 OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Requested call is not implemented + * a1-7 Preserved + */ +#define OPTEE_SMC_FUNCID_GET_THREAD_COUNT U(15) +#define OPTEE_SMC_GET_THREAD_COUNT \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_THREAD_COUNT) + +/* + * Inform OP-TEE that normal world is able to receive asynchronous + * notifications. + * + * Call requests usage: + * a0 SMC Function ID, OPTEE_SMC_ENABLE_ASYNC_NOTIF + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1-7 Preserved + * + * Not supported return register usage: + * a0 OPTEE_SMC_RETURN_ENOTAVAIL + * a1-7 Preserved + */ +#define OPTEE_SMC_FUNCID_ENABLE_ASYNC_NOTIF 16 +#define OPTEE_SMC_ENABLE_ASYNC_NOTIF \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_ASYNC_NOTIF) + +/* + * Retrieve a value of notifications pending since the last call of this + * function. + * + * OP-TEE keeps a record of all posted values. When an interrupt is + * received which indicates that there are posted values this function + * should be called until all pended values have been retrieved. When a + * value is retrieved, it's cleared from the record in secure world. + * + * It is expected that this function is called from an interrupt handler + * in normal world. + * + * Call requests usage: + * a0 SMC Function ID, OPTEE_SMC_GET_ASYNC_NOTIF_VALUE + * a1-6 Not used + * a7 Hypervisor Client ID register + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 value + * a2 Bit[0]: OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID if the value in a1 is + * valid, else 0 if no values were pending + * a2 Bit[1]: OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING if another value is + * pending, else 0. + * Bit[31:2]: MBZ + * a3-7 Preserved + * + * Not supported return register usage: + * a0 OPTEE_SMC_RETURN_ENOTAVAIL + * a1-7 Preserved + */ +#define OPTEE_SMC_ASYNC_NOTIF_VALID BIT(0) +#define OPTEE_SMC_ASYNC_NOTIF_PENDING BIT(1) + +/* + * Notification that OP-TEE expects a yielding call to do some bottom half + * work in a driver. + */ +#define OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF 0 + +#define OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE 17 +#define OPTEE_SMC_GET_ASYNC_NOTIF_VALUE \ + OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE) + +/* See OPTEE_SMC_CALL_WITH_RPC_ARG above */ +#define OPTEE_SMC_FUNCID_CALL_WITH_RPC_ARG U(18) + +/* See OPTEE_SMC_CALL_WITH_REGD_ARG above */ +#define OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG U(19) + +/* + * Resume from RPC (for example after processing a foreign interrupt) + * + * Call register usage: + * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC + * a1-3 Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned + * OPTEE_SMC_RETURN_RPC in a0 + * + * Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above. + * + * Possible return values + * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this + * function. + * OPTEE_SMC_RETURN_OK Original call completed, result + * updated in the previously supplied. + * struct optee_msg_arg + * OPTEE_SMC_RETURN_RPC Call suspended by RPC call to normal + * world. + * OPTEE_SMC_RETURN_ERESUME Resume failed, the opaque resume + * information was corrupt. + */ +#define OPTEE_SMC_FUNCID_RETURN_FROM_RPC U(3) +#define OPTEE_SMC_CALL_RETURN_FROM_RPC \ + OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC) + +#define OPTEE_SMC_RETURN_RPC_PREFIX_MASK U(0xFFFF0000) +#define OPTEE_SMC_RETURN_RPC_PREFIX U(0xFFFF0000) +#define OPTEE_SMC_RETURN_RPC_FUNC_MASK U(0x0000FFFF) + +#define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) \ + ((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK) + +#define OPTEE_SMC_RPC_VAL(func) ((func) | OPTEE_SMC_RETURN_RPC_PREFIX) + +/* + * Allocate memory for RPC parameter passing. The memory is used to hold a + * struct optee_msg_arg. + * + * "Call" register usage: + * a0 This value, OPTEE_SMC_RETURN_RPC_ALLOC + * a1 Size in bytes of required argument memory + * a2 Not used + * a3 Resume information, must be preserved + * a4-5 Not used + * a6-7 Resume information, must be preserved + * + * "Return" register usage: + * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. + * a1 Upper 32 bits of 64-bit physical pointer to allocated + * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't + * be allocated. + * a2 Lower 32 bits of 64-bit physical pointer to allocated + * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't + * be allocated + * a3 Preserved + * a4 Upper 32 bits of 64-bit Shared memory cookie used when freeing + * the memory or doing an RPC + * a5 Lower 32 bits of 64-bit Shared memory cookie used when freeing + * the memory or doing an RPC + * a6-7 Preserved + */ +#define OPTEE_SMC_RPC_FUNC_ALLOC U(0) +#define OPTEE_SMC_RETURN_RPC_ALLOC \ + OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC) + +/* + * Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC + * + * "Call" register usage: + * a0 This value, OPTEE_SMC_RETURN_RPC_FREE + * a1 Upper 32 bits of 64-bit shared memory cookie belonging to this + * argument memory + * a2 Lower 32 bits of 64-bit shared memory cookie belonging to this + * argument memory + * a3-7 Resume information, must be preserved + * + * "Return" register usage: + * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. + * a1-2 Not used + * a3-7 Preserved + */ +#define OPTEE_SMC_RPC_FUNC_FREE U(2) +#define OPTEE_SMC_RETURN_RPC_FREE \ + OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE) + +/* + * Deliver a foreign interrupt in normal world. + * + * "Call" register usage: + * a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR + * a1-7 Resume information, must be preserved + * + * "Return" register usage: + * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. + * a1-7 Preserved + */ +#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR U(4) +#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \ + OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR) + +/* + * Do an RPC request. The supplied struct optee_msg_arg tells which + * request to do and the parameters 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: + * a0 OPTEE_SMC_RETURN_RPC_CMD + * a1 Upper 32 bits of a 64-bit Shared memory cookie holding a + * struct optee_msg_arg, must be preserved, only the data should + * be updated + * a2 Lower 32 bits of a 64-bit Shared memory cookie holding a + * struct optee_msg_arg, must be preserved, only the data should + * be updated + * a3-7 Resume information, must be preserved + * + * "Return" register usage: + * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. + * a1-2 Not used + * a3-7 Preserved + */ +#define OPTEE_SMC_RPC_FUNC_CMD U(5) +#define OPTEE_SMC_RETURN_RPC_CMD \ + OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD) + +/* Returned in a0 */ +#define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION U(0xFFFFFFFF) + +/* Returned in a0 only from Trusted OS functions */ +#define OPTEE_SMC_RETURN_OK U(0x0) +#define OPTEE_SMC_RETURN_ETHREAD_LIMIT U(0x1) +#define OPTEE_SMC_RETURN_EBUSY U(0x2) +#define OPTEE_SMC_RETURN_ERESUME U(0x3) +#define OPTEE_SMC_RETURN_EBADADDR U(0x4) +#define OPTEE_SMC_RETURN_EBADCMD U(0x5) +#define OPTEE_SMC_RETURN_ENOMEM U(0x6) +#define OPTEE_SMC_RETURN_ENOTAVAIL U(0x7) +#define OPTEE_SMC_RETURN_IS_RPC(ret) \ + (((ret) != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION) && \ + ((((ret) & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) == \ + OPTEE_SMC_RETURN_RPC_PREFIX))) + +#endif /* OPTEE_SMC_H */ diff --git a/optee/optee_os/core/arch/arm/include/sm/pm.h b/optee/optee_os/core/arch/arm/include/sm/pm.h new file mode 100644 index 0000000..939f966 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/pm.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017 NXP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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_PM_H +#define SM_PM_H +#include +#include + +struct sm_pm_ctx { + uint32_t sp; + paddr_t cpu_resume_addr; + uint32_t suspend_regs[16]; +}; + +/* suspend/resume core functions */ +void sm_pm_cpu_suspend_save(struct sm_pm_ctx *ptr, uint32_t sp); +void sm_pm_cpu_do_suspend(uint32_t *ptr); +void sm_pm_cpu_do_resume(void); + +/* + * Exported to platform suspend, arg will be passed to fn as r0 + * Return value: 0 - cpu resumed from suspended state. + * -1 - cpu not suspended. + */ +int sm_pm_cpu_suspend(uint32_t arg, int (*fn)(uint32_t)); +#endif diff --git a/optee/optee_os/core/arch/arm/include/sm/psci.h b/optee/optee_os/core/arch/arm/include/sm/psci.h new file mode 100644 index 0000000..b992e60 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/psci.h @@ -0,0 +1,81 @@ +#include +#include +#include + +#define PSCI_VERSION_0_2 U(0x00000002) +#define PSCI_VERSION_1_0 U(0x00010000) +#define PSCI_VERSION_1_1 U(0x00010001) +#define PSCI_VERSION U(0x84000000) +#define PSCI_CPU_SUSPEND U(0x84000001) +#define PSCI_CPU_OFF U(0x84000002) +#define PSCI_CPU_ON U(0x84000003) +#define PSCI_CPU_ON_SMC64 (PSCI_CPU_ON | U(0x40000000)) +#define PSCI_AFFINITY_INFO U(0x84000004) +#define PSCI_MIGRATE U(0x84000005) +#define PSCI_MIGRATE_INFO_TYPE U(0x84000006) +#define PSCI_MIGRATE_INFO_UP_CPU U(0x84000007) +#define PSCI_SYSTEM_OFF U(0x84000008) +#define PSCI_SYSTEM_RESET U(0x84000009) +#define PSCI_PSCI_FEATURES U(0x8400000a) +#define PSCI_CPU_FREEZE U(0x8400000b) +#define PSCI_CPU_DEFAULT_SUSPEND U(0x8400000c) +#define PSCI_NODE_HW_STATE U(0x8400000d) +#define PSCI_SYSTEM_SUSPEND U(0x8400000e) +#define PSCI_PSCI_SET_SUSPEND_MODE U(0x8400000f) +#define PSCI_FN_STAT_RESIDENCY U(0x84000010) +#define PSCI_FN_STAT_COUNT U(0x84000011) +#define PSCI_SYSTEM_RESET2 U(0x84000012) +#define PSCI_MEM_PROTECT U(0x84000013) +#define PSCI_MEM_PROTECT_CHECK_RANGE U(0x84000014) + +#define PSCI_NUM_CALLS U(21) + +#define PSCI_AFFINITY_LEVEL_ON U(0) +#define PSCI_AFFINITY_LEVEL_OFF U(1) +#define PSCI_AFFINITY_LEVEL_ON_PENDING U(2) + +#define PSCI_POWER_STATE_ID_MASK U(0xffff) +#define PSCI_POWER_STATE_ID_SHIFT U(0) +#define PSCI_POWER_STATE_TYPE_SHIFT U(16) +#define PSCI_POWER_STATE_TYPE_MASK BIT32(PSCI_POWER_STATE_TYPE_SHIFT) +#define PSCI_POWER_STATE_AFFL_SHIFT U(24) +#define PSCI_POWER_STATE_AFFL_MASK SHIFT_U32(0x3, \ + PSCI_POWER_STATE_AFFL_SHIFT) + +#define PSCI_POWER_STATE_TYPE_STANDBY U(0) +#define PSCI_POWER_STATE_TYPE_POWER_DOWN U(1) + +#define PSCI_RET_SUCCESS (0) +#define PSCI_RET_NOT_SUPPORTED (-1) +#define PSCI_RET_INVALID_PARAMETERS (-2) +#define PSCI_RET_DENIED (-3) +#define PSCI_RET_ALREADY_ON (-4) +#define PSCI_RET_ON_PENDING (-5) +#define PSCI_RET_INTERNAL_FAILURE (-6) +#define PSCI_RET_NOT_PRESENT (-7) +#define PSCI_RET_DISABLED (-8) +#define PSCI_RET_INVALID_ADDRESS (-9) + +uint32_t psci_version(void); +int psci_cpu_suspend(uint32_t power_state, uintptr_t entry, + uint32_t context_id, struct sm_nsec_ctx *nsec); +int psci_cpu_off(void); +int psci_cpu_on(uint32_t cpu_id, uint32_t entry, uint32_t context_id); +int psci_affinity_info(uint32_t affinity, uint32_t lowest_affnity_level); +int psci_migrate(uint32_t cpu_id); +int psci_migrate_info_type(void); +int psci_migrate_info_up_cpu(void); +void psci_system_off(void); +void psci_system_reset(void); +int psci_features(uint32_t psci_fid); +int psci_system_reset2(uint32_t reset_type, uint32_t cookie); +int psci_mem_protect(uint32_t enable); +int psci_mem_chk_range(paddr_t base, size_t length); +int psci_node_hw_state(uint32_t cpu_id, uint32_t power_level); +int psci_system_suspend(uintptr_t entry, uint32_t context_id, + struct sm_nsec_ctx *nsec); +int psci_stat_residency(uint32_t cpu_id, uint32_t power_state); +int psci_stat_count(uint32_t cpu_id, uint32_t power_state); +void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec); + +void psci_armv7_cpu_off(void); diff --git a/optee/optee_os/core/arch/arm/include/sm/sm.h b/optee/optee_os/core/arch/arm/include/sm/sm.h new file mode 100644 index 0000000..d33c5fc --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/sm.h @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef SM_SM_H +#define SM_SM_H + +#ifndef __ASSEMBLER__ + +#include +#include + +struct sm_unbanked_regs { + uint32_t usr_sp; + uint32_t usr_lr; + uint32_t irq_spsr; + uint32_t irq_sp; + uint32_t irq_lr; + uint32_t fiq_spsr; + uint32_t fiq_sp; + uint32_t fiq_lr; + /* + * Note that fiq_r{8-12} are not saved here. Instead thread_fiq_handler + * preserves r{8-12}. + */ + 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; +#ifdef CFG_SM_NO_CYCLE_COUNTING + uint32_t pmcr; +#endif +#ifdef CFG_FTRACE_SUPPORT + uint32_t cntkctl; + uint32_t pad; +#endif +}; + +struct sm_nsec_ctx { + struct sm_unbanked_regs ub_regs; + + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + + /* return state */ + uint32_t mon_lr; + uint32_t mon_spsr; +}; + +struct sm_sec_ctx { + struct sm_unbanked_regs ub_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; + + /* return state */ + uint32_t mon_lr; + uint32_t mon_spsr; +}; + +struct sm_ctx { +#ifndef CFG_SM_NO_CYCLE_COUNTING + uint32_t pad; +#endif + struct sm_sec_ctx sec; +#ifdef CFG_SM_NO_CYCLE_COUNTING + uint32_t pad; +#endif + struct sm_nsec_ctx nsec; +}; + +/* + * The secure monitor reserves space at top of stack_tmp to hold struct + * sm_ctx. + */ +#define SM_STACK_TMP_RESERVE_SIZE sizeof(struct sm_ctx) + +/* Returns storage location of non-secure context for current CPU */ +struct sm_nsec_ctx *sm_get_nsec_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); + +enum sm_handler_ret { + SM_HANDLER_SMC_HANDLED = 0, + SM_HANDLER_PENDING_SMC, +}; + +/* + * Returns whether SMC was handled from platform handler in secure monitor + * or if it shall reach OP-TEE core . + */ +enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx); + +void sm_save_unbanked_regs(struct sm_unbanked_regs *regs); +void sm_restore_unbanked_regs(struct sm_unbanked_regs *regs); + +/* + * These function return to secure monitor by SMC instead of a normal + * function return. + */ +void vector_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7); +void vector_fast_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7); +void vector_fiq_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7); + +#endif /*!__ASSEMBLER__*/ + +/* 32 bit return value for sm_from_nsec() */ +#define SM_EXIT_TO_NON_SECURE 0 +#define SM_EXIT_TO_SECURE 1 + +#endif /*SM_SM_H*/ diff --git a/optee/optee_os/core/arch/arm/include/sm/std_smc.h b/optee/optee_os/core/arch/arm/include/sm/std_smc.h new file mode 100644 index 0000000..ce8606d --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/std_smc.h @@ -0,0 +1,39 @@ +#ifndef __STD_SMC_H__ +#define __STD_SMC_H__ + +#include + +/* SMC function IDs for Standard Service queries */ + +#define ARM_STD_SVC_CALL_COUNT 0x8400ff00 +#define ARM_STD_SVC_UID 0x8400ff01 +/* 0x8400ff02 is reserved */ +#define ARM_STD_SVC_VERSION 0x8400ff03 + +#define ARM_SMCCC_VERSION 0x80000000 +#define ARM_SMCCC_ARCH_FEATURES 0x80000001 +#define ARM_SMCCC_ARCH_SOC_ID 0x80000002 +#define ARM_SMCCC_ARCH_WORKAROUND_1 0x80008000 +#define ARM_SMCCC_ARCH_WORKAROUND_2 0x80007fff + +#define ARM_SMCCC_RET_SUCCESS 0 +#define ARM_SMCCC_RET_NOT_SUPPORTED 0xffffffff +#define ARM_SMCCC_RET_NOT_REQUIRED 0xfffffffe +#define ARM_SMCCC_RET_INVALID_PARAMETER 0xfffffffd + +#define SMCCC_V_1_0 0x10000 +#define SMCCC_V_1_1 0x10001 +#define SMCCC_V_1_2 0x10002 + +/* ARM Standard Service Calls version numbers */ +#define STD_SVC_VERSION_MAJOR 0x0 +#define STD_SVC_VERSION_MINOR 0x1 + +/* The macros below are used to identify PSCI calls from the SMC function ID */ +#define PSCI_FID_MASK 0xffe0u +#define PSCI_FID_VALUE 0u +#define is_psci_fid(_fid) \ + (((_fid) & PSCI_FID_MASK) == PSCI_FID_VALUE) + +void smc_std_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec); +#endif diff --git a/optee/optee_os/core/arch/arm/include/sm/teesmc_opteed.h b/optee/optee_os/core/arch/arm/include/sm/teesmc_opteed.h new file mode 100644 index 0000000..41e7204 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/teesmc_opteed.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef TEESMC_OPTEED_H +#define TEESMC_OPTEED_H + +/* + * This file specify SMC function IDs used when returning from TEE to the + * secure monitor. + * + * All SMC Function IDs indicates SMC32 Calling Convention but will carry + * full 64 bit values in the argument registers if invoked from Aarch64 + * mode. This violates the SMC Calling Convention, but since this + * convention only coveres API towards Normwal World it's something that + * only concerns the OP-TEE Dispatcher in ARM Trusted Firmware and OP-TEE + * OS at Secure EL1. + */ + +/* + * Issued when returning from initial entry. + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ENTRY_DONE + * r1/x1 Pointer to entry vector + */ +#define TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE 0 +#define TEESMC_OPTEED_RETURN_ENTRY_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE) + + + +/* + * Issued when returning from "cpu_on" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ON_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_ON_DONE 1 +#define TEESMC_OPTEED_RETURN_ON_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ON_DONE) + +/* + * Issued when returning from "cpu_off" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_OFF_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE 2 +#define TEESMC_OPTEED_RETURN_OFF_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE) + +/* + * Issued when returning from "cpu_suspend" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SUSPEND_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE 3 +#define TEESMC_OPTEED_RETURN_SUSPEND_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE) + +/* + * Issued when returning from "cpu_resume" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_RESUME_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE 4 +#define TEESMC_OPTEED_RETURN_RESUME_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE) + +/* + * Issued when returning from "std_smc" or "fast_smc" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_CALL_DONE + * r1-4/x1-4 Return value 0-3 which will passed to normal world in + * r0-3/x0-3 + */ +#define TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE 5 +#define TEESMC_OPTEED_RETURN_CALL_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE) + +/* + * Issued when returning from "fiq" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_FIQ_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE 6 +#define TEESMC_OPTEED_RETURN_FIQ_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE) + +/* + * Issued when returning from "system_off" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE 7 +#define TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE) + +/* + * Issued when returning from "system_reset" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE 8 +#define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) + +#endif /*TEESMC_OPTEED_H*/ diff --git a/optee/optee_os/core/arch/arm/include/sm/teesmc_opteed_macros.h b/optee/optee_os/core/arch/arm/include/sm/teesmc_opteed_macros.h new file mode 100644 index 0000000..fcc84b7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/sm/teesmc_opteed_macros.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef TEESMC_OPTEED_MACROS_H +#define TEESMC_OPTEED_MACROS_H + +#define TEESMC_OPTEED_RV(func_num) \ + OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ + OPTEE_SMC_OWNER_TRUSTED_OS_OPTEED, (func_num)) + +#endif /*TEESMC_OPTEED_MACROS_H*/ diff --git a/optee/optee_os/core/arch/arm/include/smccc.h b/optee/optee_os/core/arch/arm/include/smccc.h new file mode 100644 index 0000000..8146cbe --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/smccc.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef __SMCCC_H +#define __SMCCC_H + +/* + * Describes features of SMC Calling Convention from v1.1 + * See also https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf + */ + +/* + * Retrieve the implemented version of the SMC Calling Convention + * Mandatory from SMCCC v1.1 + * Optional in SMCCC v1.0 + */ +#define SMCCC_VERSION 0x80000000 + +/* + * Determine the availability and capability of Arm Architecture Service + * functions. + * Mandatory from SMCCC v1.1 + * Optional for SMCCC v1.0 + */ +#define SMCCC_ARCH_FEATURES 0x80000001 + +/* + * Execute the mitigation for CVE-2017-5715 on the calling PE + * Optional from SMCCC v1.1 + * Not supported in SMCCC v1.0 + */ +#define SMCCC_ARCH_WORKAROUND_1 0x80008000 + +#endif /*__SMCCC_H*/ diff --git a/optee/optee_os/core/arch/arm/include/tee/entry_fast.h b/optee/optee_os/core/arch/arm/include/tee/entry_fast.h new file mode 100644 index 0000000..0f6fef8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/include/tee/entry_fast.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TEE_ENTRY_FAST_H +#define TEE_ENTRY_FAST_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); + +/* + * Fast call entry, __weak, overridable. If overridden should call + * __tee_entry_fast() at the end in order to handle the standard functions. + */ +void tee_entry_fast(struct thread_smc_args *args); +void __tee_entry_fast(struct thread_smc_args *args); + +#endif /* TEE_ENTRY_FAST_H */ diff --git a/optee/optee_os/core/arch/arm/kernel/abort.c b/optee/optee_os/core/arch/arm/kernel/abort.c new file mode 100644 index 0000000..9972cc1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/abort.c @@ -0,0 +1,581 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum fault_type { + FAULT_TYPE_USER_MODE_PANIC, + FAULT_TYPE_USER_MODE_VFP, + FAULT_TYPE_PAGEABLE, + FAULT_TYPE_IGNORE, +}; + +#ifdef CFG_UNWIND + +#ifdef ARM32 +/* + * Kernel or user mode unwind (32-bit execution state). + */ +static void __print_stack_unwind(struct abort_info *ai) +{ + struct unwind_state_arm32 state = { }; + uint32_t mode = ai->regs->spsr & CPSR_MODE_MASK; + uint32_t sp = 0; + uint32_t lr = 0; + + assert(!abort_is_user_exception(ai)); + + if (mode == CPSR_MODE_SYS) { + sp = ai->regs->usr_sp; + lr = ai->regs->usr_lr; + } else { + sp = read_mode_sp(mode); + lr = read_mode_lr(mode); + } + + memset(&state, 0, sizeof(state)); + state.registers[0] = ai->regs->r0; + state.registers[1] = ai->regs->r1; + state.registers[2] = ai->regs->r2; + state.registers[3] = ai->regs->r3; + state.registers[4] = ai->regs->r4; + state.registers[5] = ai->regs->r5; + state.registers[6] = ai->regs->r6; + state.registers[7] = ai->regs->r7; + state.registers[8] = ai->regs->r8; + state.registers[9] = ai->regs->r9; + state.registers[10] = ai->regs->r10; + state.registers[11] = ai->regs->r11; + state.registers[13] = sp; + state.registers[14] = lr; + state.registers[15] = ai->pc; + + print_stack_arm32(&state, thread_stack_start(), thread_stack_size()); +} +#endif /* ARM32 */ + +#ifdef ARM64 +/* Kernel mode unwind (64-bit execution state) */ +static void __print_stack_unwind(struct abort_info *ai) +{ + struct unwind_state_arm64 state = { + .pc = ai->regs->elr, + .fp = ai->regs->x29, + }; + + print_stack_arm64(&state, thread_stack_start(), thread_stack_size()); +} +#endif /*ARM64*/ + +#else /* CFG_UNWIND */ +static void __print_stack_unwind(struct abort_info *ai __unused) +{ +} +#endif /* CFG_UNWIND */ + +static __maybe_unused const char *abort_type_to_str(uint32_t abort_type) +{ + if (abort_type == ABORT_TYPE_DATA) + return "data"; + if (abort_type == ABORT_TYPE_PREFETCH) + return "prefetch"; + return "undef"; +} + +static __maybe_unused const char *fault_to_str(uint32_t abort_type, + uint32_t fault_descr) +{ + /* fault_descr is only valid for data or prefetch abort */ + if (abort_type != ABORT_TYPE_DATA && abort_type != ABORT_TYPE_PREFETCH) + return ""; + + switch (core_mmu_get_fault_type(fault_descr)) { + case CORE_MMU_FAULT_ALIGNMENT: + return " (alignment fault)"; + case CORE_MMU_FAULT_TRANSLATION: + return " (translation fault)"; + case CORE_MMU_FAULT_READ_PERMISSION: + return " (read permission fault)"; + case CORE_MMU_FAULT_WRITE_PERMISSION: + return " (write permission fault)"; + case CORE_MMU_FAULT_TAG_CHECK: + return " (tag check fault)"; + default: + return ""; + } +} + +static __maybe_unused void +__print_abort_info(struct abort_info *ai __maybe_unused, + const char *ctx __maybe_unused) +{ + __maybe_unused size_t core_pos = 0; +#ifdef ARM32 + uint32_t mode = ai->regs->spsr & CPSR_MODE_MASK; + __maybe_unused uint32_t sp = 0; + __maybe_unused uint32_t lr = 0; + + if (mode == CPSR_MODE_USR || mode == CPSR_MODE_SYS) { + sp = ai->regs->usr_sp; + lr = ai->regs->usr_lr; + core_pos = thread_get_tsd()->abort_core; + } else { + sp = read_mode_sp(mode); + lr = read_mode_lr(mode); + core_pos = get_core_pos(); + } +#endif /*ARM32*/ +#ifdef ARM64 + if (abort_is_user_exception(ai)) + core_pos = thread_get_tsd()->abort_core; + else + core_pos = get_core_pos(); +#endif /*ARM64*/ + + EMSG_RAW(""); + EMSG_RAW("%s %s-abort at address 0x%" PRIxVA "%s", + ctx, abort_type_to_str(ai->abort_type), ai->va, + fault_to_str(ai->abort_type, ai->fault_descr)); +#ifdef ARM32 + EMSG_RAW(" fsr 0x%08x ttbr0 0x%08x ttbr1 0x%08x cidr 0x%X", + ai->fault_descr, read_ttbr0(), read_ttbr1(), + read_contextidr()); + EMSG_RAW(" cpu #%zu cpsr 0x%08x", + core_pos, ai->regs->spsr); + EMSG_RAW(" r0 0x%08x r4 0x%08x r8 0x%08x r12 0x%08x", + ai->regs->r0, ai->regs->r4, ai->regs->r8, ai->regs->ip); + EMSG_RAW(" r1 0x%08x r5 0x%08x r9 0x%08x sp 0x%08x", + ai->regs->r1, ai->regs->r5, ai->regs->r9, sp); + EMSG_RAW(" r2 0x%08x r6 0x%08x r10 0x%08x lr 0x%08x", + ai->regs->r2, ai->regs->r6, ai->regs->r10, lr); + EMSG_RAW(" r3 0x%08x r7 0x%08x r11 0x%08x pc 0x%08x", + ai->regs->r3, ai->regs->r7, ai->regs->r11, ai->pc); +#endif /*ARM32*/ +#ifdef ARM64 + EMSG_RAW(" esr 0x%08x ttbr0 0x%08" PRIx64 " ttbr1 0x%08" PRIx64 + " cidr 0x%X", ai->fault_descr, read_ttbr0_el1(), + read_ttbr1_el1(), read_contextidr_el1()); + EMSG_RAW(" cpu #%zu cpsr 0x%08x", + core_pos, (uint32_t)ai->regs->spsr); + EMSG_RAW(" x0 %016" PRIx64 " x1 %016" PRIx64, + ai->regs->x0, ai->regs->x1); + EMSG_RAW(" x2 %016" PRIx64 " x3 %016" PRIx64, + ai->regs->x2, ai->regs->x3); + EMSG_RAW(" x4 %016" PRIx64 " x5 %016" PRIx64, + ai->regs->x4, ai->regs->x5); + EMSG_RAW(" x6 %016" PRIx64 " x7 %016" PRIx64, + ai->regs->x6, ai->regs->x7); + EMSG_RAW(" x8 %016" PRIx64 " x9 %016" PRIx64, + ai->regs->x8, ai->regs->x9); + EMSG_RAW(" x10 %016" PRIx64 " x11 %016" PRIx64, + ai->regs->x10, ai->regs->x11); + EMSG_RAW(" x12 %016" PRIx64 " x13 %016" PRIx64, + ai->regs->x12, ai->regs->x13); + EMSG_RAW(" x14 %016" PRIx64 " x15 %016" PRIx64, + ai->regs->x14, ai->regs->x15); + EMSG_RAW(" x16 %016" PRIx64 " x17 %016" PRIx64, + ai->regs->x16, ai->regs->x17); + EMSG_RAW(" x18 %016" PRIx64 " x19 %016" PRIx64, + ai->regs->x18, ai->regs->x19); + EMSG_RAW(" x20 %016" PRIx64 " x21 %016" PRIx64, + ai->regs->x20, ai->regs->x21); + EMSG_RAW(" x22 %016" PRIx64 " x23 %016" PRIx64, + ai->regs->x22, ai->regs->x23); + EMSG_RAW(" x24 %016" PRIx64 " x25 %016" PRIx64, + ai->regs->x24, ai->regs->x25); + EMSG_RAW(" x26 %016" PRIx64 " x27 %016" PRIx64, + ai->regs->x26, ai->regs->x27); + EMSG_RAW(" x28 %016" PRIx64 " x29 %016" PRIx64, + ai->regs->x28, ai->regs->x29); + EMSG_RAW(" x30 %016" PRIx64 " elr %016" PRIx64, + ai->regs->x30, ai->regs->elr); + EMSG_RAW(" sp_el0 %016" PRIx64, ai->regs->sp_el0); +#endif /*ARM64*/ +} + +/* + * Print abort info and (optionally) stack dump to the console + * @ai kernel-mode abort info. + * @stack_dump true to show a stack trace + */ +static void __abort_print(struct abort_info *ai, bool stack_dump) +{ + assert(!abort_is_user_exception(ai)); + + __print_abort_info(ai, "Core"); + + if (stack_dump) { + trace_printf_helper_raw(TRACE_ERROR, true, + "TEE load address @ %#"PRIxVA, + VCORE_START_VA); + __print_stack_unwind(ai); + } +} + +void abort_print(struct abort_info *ai) +{ + __abort_print(ai, false); +} + +void abort_print_error(struct abort_info *ai) +{ + __abort_print(ai, true); +} + +/* This function must be called from a normal thread */ +void abort_print_current_ts(void) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + struct abort_info ai = { }; + struct ts_session *s = ts_get_current_session(); + + ai.abort_type = tsd->abort_type; + ai.fault_descr = tsd->abort_descr; + ai.va = tsd->abort_va; + ai.pc = tsd->abort_regs.elr; + ai.regs = &tsd->abort_regs; + + if (ai.abort_type != ABORT_TYPE_USER_MODE_PANIC) + __print_abort_info(&ai, "User mode"); + + s->ctx->ops->dump_state(s->ctx); + +#if defined(CFG_FTRACE_SUPPORT) + if (s->ctx->ops->dump_ftrace) { + s->fbuf = NULL; + s->ctx->ops->dump_ftrace(s->ctx); + } +#endif +} + +static void save_abort_info_in_tsd(struct abort_info *ai) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + + tsd->abort_type = ai->abort_type; + tsd->abort_descr = ai->fault_descr; + tsd->abort_va = ai->va; + tsd->abort_regs = *ai->regs; + tsd->abort_core = get_core_pos(); +} + +#ifdef ARM32 +static void set_abort_info(uint32_t abort_type, struct thread_abort_regs *regs, + struct abort_info *ai) +{ + switch (abort_type) { + case ABORT_TYPE_DATA: + ai->fault_descr = read_dfsr(); + ai->va = read_dfar(); + break; + case ABORT_TYPE_PREFETCH: + ai->fault_descr = read_ifsr(); + ai->va = read_ifar(); + break; + default: + ai->fault_descr = 0; + ai->va = regs->elr; + break; + } + ai->abort_type = abort_type; + ai->pc = regs->elr; + ai->regs = regs; +} +#endif /*ARM32*/ + +#ifdef ARM64 +static void set_abort_info(uint32_t abort_type __unused, + struct thread_abort_regs *regs, struct abort_info *ai) +{ + ai->fault_descr = read_esr_el1(); + switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) { + case ESR_EC_IABT_EL0: + case ESR_EC_IABT_EL1: + ai->abort_type = ABORT_TYPE_PREFETCH; + ai->va = read_far_el1(); + break; + case ESR_EC_DABT_EL0: + case ESR_EC_DABT_EL1: + case ESR_EC_SP_ALIGN: + ai->abort_type = ABORT_TYPE_DATA; + ai->va = read_far_el1(); + break; + default: + ai->abort_type = ABORT_TYPE_UNDEF; + ai->va = regs->elr; + } + ai->pc = regs->elr; + ai->regs = regs; +} +#endif /*ARM64*/ + +#ifdef ARM32 +static void handle_user_mode_panic(struct abort_info *ai) +{ + /* + * It was a user exception, stop user execution and return + * to TEE Core. + */ + ai->regs->r0 = TEE_ERROR_TARGET_DEAD; + ai->regs->r1 = true; + ai->regs->r2 = 0xdeadbeef; + ai->regs->elr = (uint32_t)thread_unwind_user_mode; + ai->regs->spsr &= CPSR_FIA; + ai->regs->spsr &= ~CPSR_MODE_MASK; + ai->regs->spsr |= CPSR_MODE_SVC; + /* Select Thumb or ARM mode */ + if (ai->regs->elr & 1) + ai->regs->spsr |= CPSR_T; + else + ai->regs->spsr &= ~CPSR_T; +} +#endif /*ARM32*/ + +#ifdef ARM64 +static void handle_user_mode_panic(struct abort_info *ai) +{ + struct thread_ctx *tc __maybe_unused = NULL; + uint32_t daif = 0; + + /* + * It was a user exception, stop user execution and return + * to TEE Core. + */ + ai->regs->x0 = TEE_ERROR_TARGET_DEAD; + ai->regs->x1 = true; + ai->regs->x2 = 0xdeadbeef; + ai->regs->elr = (vaddr_t)thread_unwind_user_mode; + ai->regs->sp_el0 = thread_get_saved_thread_sp(); + +#if defined(CFG_CORE_PAUTH) + /* + * We're going to return to the privileged core thread, update the + * APIA key to match the key used by the thread. + */ + tc = threads + thread_get_id(); + ai->regs->apiakey_hi = tc->keys.apia_hi; + ai->regs->apiakey_lo = tc->keys.apia_lo; +#endif + + daif = (ai->regs->spsr >> SPSR_32_AIF_SHIFT) & SPSR_32_AIF_MASK; + /* XXX what about DAIF_D? */ + ai->regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, daif); +} +#endif /*ARM64*/ + +#ifdef CFG_WITH_VFP +static void handle_user_mode_vfp(void) +{ + struct ts_session *s = ts_get_current_session(); + + thread_user_enable_vfp(&to_user_mode_ctx(s->ctx)->vfp); +} +#endif /*CFG_WITH_VFP*/ + +#ifdef CFG_WITH_USER_TA +#ifdef ARM32 +/* Returns true if the exception originated from user mode */ +bool abort_is_user_exception(struct abort_info *ai) +{ + return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_USR; +} +#endif /*ARM32*/ + +#ifdef ARM64 +/* Returns true if the exception originated from user mode */ +bool abort_is_user_exception(struct abort_info *ai) +{ + uint32_t spsr = ai->regs->spsr; + + if (spsr & (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT)) + return true; + if (((spsr >> SPSR_64_MODE_EL_SHIFT) & SPSR_64_MODE_EL_MASK) == + SPSR_64_MODE_EL0) + return true; + return false; +} +#endif /*ARM64*/ +#else /*CFG_WITH_USER_TA*/ +bool abort_is_user_exception(struct abort_info *ai __unused) +{ + return false; +} +#endif /*CFG_WITH_USER_TA*/ + +#if defined(CFG_WITH_VFP) && defined(CFG_WITH_USER_TA) +#ifdef ARM32 +static bool is_vfp_fault(struct abort_info *ai) +{ + if ((ai->abort_type != ABORT_TYPE_UNDEF) || vfp_is_enabled()) + return false; + + /* + * Not entirely accurate, but if it's a truly undefined instruction + * we'll end up in this function again, except this time + * vfp_is_enabled() so we'll return false. + */ + return true; +} +#endif /*ARM32*/ + +#ifdef ARM64 +static bool is_vfp_fault(struct abort_info *ai) +{ + switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) { + case ESR_EC_FP_ASIMD: + case ESR_EC_AARCH32_FP: + case ESR_EC_AARCH64_FP: + return true; + default: + return false; + } +} +#endif /*ARM64*/ +#else /*CFG_WITH_VFP && CFG_WITH_USER_TA*/ +static bool is_vfp_fault(struct abort_info *ai __unused) +{ + return false; +} +#endif /*CFG_WITH_VFP && CFG_WITH_USER_TA*/ + +bool abort_is_write_fault(struct abort_info *ai) +{ +#ifdef ARM32 + unsigned int write_not_read = 11; +#endif +#ifdef ARM64 + unsigned int write_not_read = 6; +#endif + + return ai->abort_type == ABORT_TYPE_DATA && + (ai->fault_descr & BIT(write_not_read)); +} + +static enum fault_type get_fault_type(struct abort_info *ai) +{ + if (abort_is_user_exception(ai)) { + if (is_vfp_fault(ai)) + return FAULT_TYPE_USER_MODE_VFP; +#ifndef CFG_WITH_PAGER + return FAULT_TYPE_USER_MODE_PANIC; +#endif + } + + if (thread_is_from_abort_mode()) { + abort_print_error(ai); + panic("[abort] abort in abort handler (trap CPU)"); + } + + if (ai->abort_type == ABORT_TYPE_UNDEF) { + if (abort_is_user_exception(ai)) + return FAULT_TYPE_USER_MODE_PANIC; + abort_print_error(ai); + panic("[abort] undefined abort (trap CPU)"); + } + + switch (core_mmu_get_fault_type(ai->fault_descr)) { + case CORE_MMU_FAULT_ALIGNMENT: + if (abort_is_user_exception(ai)) + return FAULT_TYPE_USER_MODE_PANIC; + abort_print_error(ai); + panic("[abort] alignement fault! (trap CPU)"); + break; + + case CORE_MMU_FAULT_ACCESS_BIT: + if (abort_is_user_exception(ai)) + return FAULT_TYPE_USER_MODE_PANIC; + abort_print_error(ai); + panic("[abort] access bit fault! (trap CPU)"); + break; + + case CORE_MMU_FAULT_DEBUG_EVENT: + if (!abort_is_user_exception(ai)) + abort_print(ai); + DMSG("[abort] Ignoring debug event!"); + return FAULT_TYPE_IGNORE; + + case CORE_MMU_FAULT_TRANSLATION: + case CORE_MMU_FAULT_WRITE_PERMISSION: + case CORE_MMU_FAULT_READ_PERMISSION: + return FAULT_TYPE_PAGEABLE; + + case CORE_MMU_FAULT_ASYNC_EXTERNAL: + if (!abort_is_user_exception(ai)) + abort_print(ai); + DMSG("[abort] Ignoring async external abort!"); + return FAULT_TYPE_IGNORE; + + case CORE_MMU_FAULT_TAG_CHECK: + if (abort_is_user_exception(ai)) + return FAULT_TYPE_USER_MODE_PANIC; + abort_print_error(ai); + panic("[abort] Tag check fault! (trap CPU)"); + break; + + case CORE_MMU_FAULT_OTHER: + default: + if (!abort_is_user_exception(ai)) + abort_print(ai); + DMSG("[abort] Unhandled fault!"); + return FAULT_TYPE_IGNORE; + } +} + +void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs) +{ + struct abort_info ai; + bool handled; + + set_abort_info(abort_type, regs, &ai); + + switch (get_fault_type(&ai)) { + case FAULT_TYPE_IGNORE: + break; + case FAULT_TYPE_USER_MODE_PANIC: + DMSG("[abort] abort in User mode (TA will panic)"); + save_abort_info_in_tsd(&ai); + vfp_disable(); + handle_user_mode_panic(&ai); + break; +#ifdef CFG_WITH_VFP + case FAULT_TYPE_USER_MODE_VFP: + handle_user_mode_vfp(); + break; +#endif + case FAULT_TYPE_PAGEABLE: + default: + if (thread_get_id_may_fail() < 0) { + abort_print_error(&ai); + panic("abort outside thread context"); + } + thread_kernel_save_vfp(); + handled = tee_pager_handle_fault(&ai); + thread_kernel_restore_vfp(); + if (!handled) { + if (!abort_is_user_exception(&ai)) { + abort_print_error(&ai); + panic("unhandled pageable abort"); + } + DMSG("[abort] abort in User mode (TA will panic)"); + save_abort_info_in_tsd(&ai); + vfp_disable(); + handle_user_mode_panic(&ai); + } + break; + } +} diff --git a/optee/optee_os/core/arch/arm/kernel/arch_scall.c b/optee/optee_os/core/arch/arm/kernel/arch_scall.c new file mode 100644 index 0000000..a56c921 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/arch_scall.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2022, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#define TA32_CONTEXT_MAX_SIZE (14 * sizeof(uint32_t)) +#define TA64_CONTEXT_MAX_SIZE (2 * sizeof(uint64_t)) + +#ifdef CFG_UNWIND +#ifdef ARM32 +/* Get register values pushed onto the stack by _utee_panic() */ +static void save_panic_regs_a32_ta(struct thread_specific_data *tsd, + uint32_t *pushed) +{ + tsd->abort_regs = (struct thread_abort_regs){ + .elr = pushed[0], + .r0 = pushed[1], + .r1 = pushed[2], + .r2 = pushed[3], + .r3 = pushed[4], + .r4 = pushed[5], + .r5 = pushed[6], + .r6 = pushed[7], + .r7 = pushed[8], + .r8 = pushed[9], + .r9 = pushed[10], + .r10 = pushed[11], + .r11 = pushed[12], + .usr_sp = (uint32_t)pushed, + .usr_lr = pushed[13], + .spsr = read_spsr(), + }; +} + +void scall_save_panic_stack(struct thread_scall_regs *regs) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + struct ts_session *s = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); + + tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; + tsd->abort_descr = 0; + tsd->abort_va = 0; + + if (vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE, + (uaddr_t)regs->r1, TA32_CONTEXT_MAX_SIZE)) { + TAMSG_RAW(""); + TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, + (uaddr_t)regs->r1); + return; + } + + save_panic_regs_a32_ta(tsd, (uint32_t *)regs->r1); +} +#endif /*ARM32*/ + +#ifdef ARM64 +/* Get register values pushed onto the stack by _utee_panic() (32-bit TA) */ +static void save_panic_regs_a32_ta(struct thread_specific_data *tsd, + uint32_t *pushed) +{ + tsd->abort_regs = (struct thread_abort_regs){ + .elr = pushed[0], + .x0 = pushed[1], + .x1 = pushed[2], + .x2 = pushed[3], + .x3 = pushed[4], + .x4 = pushed[5], + .x5 = pushed[6], + .x6 = pushed[7], + .x7 = pushed[8], + .x8 = pushed[9], + .x9 = pushed[10], + .x10 = pushed[11], + .x11 = pushed[12], + .x13 = (uint64_t)pushed, + .x14 = pushed[13], + .spsr = (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT), + }; +} + +/* Get register values pushed onto the stack by _utee_panic() (64-bit TA) */ +static void save_panic_regs_a64_ta(struct thread_specific_data *tsd, + uint64_t *pushed) +{ + tsd->abort_regs = (struct thread_abort_regs){ + .x29 = pushed[0], + .elr = pushed[1], + .spsr = (SPSR_64_MODE_EL0 << SPSR_64_MODE_EL_SHIFT), + }; +} + +void scall_save_panic_stack(struct thread_scall_regs *regs) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + struct ts_session *s = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); + + if (vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE, + (uaddr_t)regs->x1, + utc->uctx.is_32bit ? + TA32_CONTEXT_MAX_SIZE : + TA64_CONTEXT_MAX_SIZE)) { + TAMSG_RAW(""); + TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, + (uaddr_t)regs->x1); + return; + } + + tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; + tsd->abort_descr = 0; + tsd->abort_va = 0; + + if (utc->uctx.is_32bit) + save_panic_regs_a32_ta(tsd, (uint32_t *)regs->x1); + else + save_panic_regs_a64_ta(tsd, (uint64_t *)regs->x1); +} +#endif /*ARM64*/ + +#else /* CFG_UNWIND */ +void scall_save_panic_stack(struct thread_scall_regs *regs __unused) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + + tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; +} +#endif /* CFG_UNWIND */ diff --git a/optee/optee_os/core/arch/arm/kernel/arch_scall_a32.S b/optee/optee_os/core/arch/arm/kernel/arch_scall_a32.S new file mode 100644 index 0000000..2b572e2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/arch_scall_a32.S @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include "tee_syscall_numbers.h" +#include "trace_levels.h" +#include +#include +#include +#include +#include + +/* + * uint32_t scall_do_call(struct thread_scall_regs *regs, syscall_t func); + * + * Called from scall_handle_user_ta() + */ +FUNC scall_do_call , : +UNWIND( .cantunwind) + push {r5-r9, lr} + mov r7, sp + mov r8, r0 + mov r9, r1 + ldr r5, [r8, #THREAD_SCALL_REG_R5] + ldr r6, [r8, #THREAD_SCALL_REG_R6] + + /* + * Copy eventual arguments passed on the user stack. + * + * r5 holds the address of the first word + * r6 holds the number of words + * + * scall_handle_user_ta() who calls this function has already checked + * that we don't copy too much data. + */ + cmp r6, #0 + beq .Lno_args + sub sp, sp, r6, lsl #2 + bic sp, sp, #7 /* make sure it's a multiple of 8 */ + mov r0, sp + mov r1, r5 + mov r2, r6, lsl #2 + ldr lr, =copy_from_user + blx lr + + /* If copy failed return the error */ + cmp r0, #0 + bne .Lret + +.Lno_args: + /* Load arguments to function */ + add lr, r8, #THREAD_SCALL_REG_R0 + ldm lr, {r0-r3} + blx r9 +.Lret: + mov sp, r7 + pop {r5-r9, pc} +END_FUNC scall_do_call + +/* + * syscall_sys_return() and syscall_panic() are two special cases for syscalls + * in the way that they do not return to the TA, instead execution is resumed + * as if __thread_enter_user_mode() had returned to thread_enter_user_mode(). + * + * In order to do this the functions need a way to get hold of a pointer to + * the struct thread_scall_regs provided by storing relevant registers on the + * stack in thread_scall_handler() and later load them into registers again + * when thread_scall_handler() is returning. + * + * scall_do_call() is supplied the pointer to struct thread_scall_regs in + * r0. This pointer can later be retrieved from r8. + */ + +/* + * User space sees this function as: + * void syscall_sys_return(uint32_t ret) __noreturn; + * + * But internally the function depends on being called from + * scall_do_call() with pointer to the struct thread_scall_regs saved by + * thread_scall_handler() in r8. + * + * The argument ret is already in r0 so we don't touch that and let it + * propagate as return value of the called scall_sys_return_helper(). + */ +FUNC syscall_sys_return , : + mov r1, #0 /* panic = false */ + mov r2, #0 /* panic_code = 0 */ + mov r3, r8 /* pointer to struct thread_scall_regs */ + b scall_sys_return_helper +END_FUNC syscall_sys_return + +/* + * User space sees this function as: + * void syscall_panic(uint32_t code) __noreturn; + * + * But internally the function depends on being called from + * scall_do_call() with pointer to the struct thread_scall_regs saved by + * thread_scall_handler() in r8. + */ +FUNC syscall_panic , : + mov r1, #1 /* panic = true */ + mov r2, r0 /* panic_code = 0 */ + mov r3, r8 /* pointer to struct thread_scall_regs */ + ldr r0, =TEE_ERROR_TARGET_DEAD + b scall_sys_return_helper +END_FUNC syscall_panic diff --git a/optee/optee_os/core/arch/arm/kernel/arch_scall_a64.S b/optee/optee_os/core/arch/arm/kernel/arch_scall_a64.S new file mode 100644 index 0000000..03a96f6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/arch_scall_a64.S @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#include "tee_syscall_numbers.h" +#include "trace_levels.h" +#include +#include +#include +#include +#include +#include + +#if 0 +struct sc_rec { + uint64_t x0; + uint64_t x1; + uint64_t x19; + uint64_t x30; +} +#endif +#define SC_REC_X0 (8 * 0) +#define SC_REC_X1 (8 * 1) +#define SC_REC_X19 (8 * 2) +#define SC_REC_X30 (8 * 3) +#define SC_REC_SIZE (SC_REC_X30 + 8) + +/* + * uint32_t scall_do_call(struct thread_scall_regs *regs, syscall_t func); + * + * Called from scall_handle_user_ta() + */ +FUNC scall_do_call , : + sub sp, sp, #SC_REC_SIZE + stp x0, x1, [sp, #SC_REC_X0] + stp x19, x30, [sp, #SC_REC_X19] + mov x19, sp + + ldr x2, [x0, #THREAD_SCALL_REG_SPSR] + tst x2, #(SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT) + b.eq .Lcall_a64 + + ldp x5, x6, [x0, #THREAD_SCALL_REG_X5] + cmp x6, #0 + b.eq .Lno_args_a32 + + /* + * Calculate required space on stack to copy Aarch32 arguments + * and to transform them into Aarch64 arguments. + * x6 = nargs_on_stack + * n64 = (nargs_on_stack - 4) * 8 + * n32 = nargs_on_stack * 4 + * sp -= ROUNDUP(MAX(n32, n64), 16) + * + */ + /* n64 = (nargs_on_stack - 4) * 8 */ + sub x1, x6, #0x4 + lsl x1, x1, #3 + /* n32 = nargs_on_stack * 4 */ + lsl x0, x6, #2 + /* sp -= ROUNDUP(MAX(n32, n64), 16) */ + cmp x1, x0 + csel x0, x1, x0, ge + add x0, x0, #0xf + and x0, x0, #0xfffffffffffffff0 + sub sp, sp, x0 + + /* + * Find location on stack where to copy the Aarch32 arguments + * and do the copy. + * copy_from_user(sp, x5, nargs_on_stack * 4) + */ + mov x0, sp + mov x1, x5 + add x2, xzr, x6, lsl #2 + bl copy_from_user + /* If copy failed return the error */ + cmp x0, #0 + bne .Lret + + /* + * Load arguments into w4..w7, we're loading junk into unused + * registers, but it's quicker than trying to figure out how + * many registers to load into. + */ + /* x0 = nargs_on_stack */ + ldr x0, [x19, #SC_REC_X0] + ldr x0, [x0, #THREAD_SCALL_REG_X6] + load_wregs sp, 0, 4, 7 + + /* + * Convert remaining Aarch32 parameters passed on stack as Aarch64 + * parameters on stack. + * + * nargs_on_stack is initialized in x0 above + * n64 = (nargs_on_stack - 4) * 8 + * if n64 < 0 goro .Lno_args + * x0 = x2 = x19 - n64 + * x1 points to next argument + * while (x2 != x19) { + * w3 = *x1 + * x1 += 4 + * *x2 = x3 + * x2 += 8 + * } + * sp = x0 + */ + /* n64 = (nargs_on_stack - 4) * 8 */ + subs x2, x0, #0x4 + b.le .Lno_args_a32 + lsl x2, x2, #3 + mov x0, x2 + +.Lcpy_to_stack: + ldr w3, [x1], #4 + str x3, [x2], #8 + cmp x2, x19 + b.ne .Lcpy_to_stack + mov sp, x0 + + +.Lno_args_a32: /* Load the first 4 arguments to function */ + ldr x9, [x19, #SC_REC_X0] + load_xregs x9, THREAD_SCALL_REG_X0, 0, 3 + mov w0, w0 + mov w1, w1 + mov w2, w2 + mov w3, w3 + + /* Call the syscall function */ + ldr x16, [x19, #SC_REC_X1] + blr x16 + b .Lret + +.Lcall_a64: /* Load the first 8 arguments to function */ + ldr x9, [x19, #SC_REC_X0] + load_xregs x9, THREAD_SCALL_REG_X0, 0, 8 + + /* Call the syscall function */ + ldr x16, [x19, #SC_REC_X1] + blr x16 + +.Lret: + mov sp, x19 + ldp x19, x30, [sp, #SC_REC_X19] + add sp, sp, #SC_REC_SIZE + ret +END_FUNC scall_do_call + +/* + * syscall_sys_return() and syscall_panic() are two special cases for syscalls + * in the way that they do not return to the TA, instead execution is resumed + * as if __thread_enter_user_mode() had returned to thread_enter_user_mode(). + * + * In order to do this the functions need a way to get hold of a pointer to + * the struct thread_scall_regs provided by storing relevant registers on the + * stack in el0_svc() and later load them into registers again when el0_svc() + * is returning. + * + * scall_do_call() is supplied the pointer to struct thread_scall_regs in + * x0. This pointer can later be retrieved by chasing x19. + */ + +/* + * User space sees this function as: + * void syscall_sys_return(uint32_t ret) __noreturn; + * + * But internally the function depends on being called from + * scall_do_call() to be able to chase x19 in order to get hold of a + * pointer to struct thread_scall_regs. + * + * The argument ret is already in x0 so we don't touch that and let it + * propagate as return value of the called scall_sys_return_helper(). + */ +FUNC syscall_sys_return , : + mov x1, #0 /* panic = false */ + mov x2, #0 /* panic_code = 0 */ + ldr x3, [x19, #SC_REC_X0] /* pointer to struct thread_scall_regs */ + b scall_sys_return_helper +END_FUNC syscall_sys_return + +/* + * User space sees this function as: + * void syscall_panic(uint32_t code) __noreturn; + * + * But internally the function depends on being called from + * scall_do_call() to be able to chase x19 in order to get hold of a + * pointer to struct thread_scall_regs. + */ +FUNC syscall_panic , : + mov x1, #1 /* panic = true */ + mov x2, x0 /* code */ + ldr w0, =TEE_ERROR_TARGET_DEAD + ldr x3, [x19, #SC_REC_X0] /* pointer to struct thread_scall_regs */ + b scall_sys_return_helper +END_FUNC syscall_panic + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/arm32_gicv3_sysreg.txt b/optee/optee_os/core/arch/arm/kernel/arm32_gicv3_sysreg.txt new file mode 100644 index 0000000..dd379e6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/arm32_gicv3_sysreg.txt @@ -0,0 +1,40 @@ +# Format of file +# +# lines beginning with '@' will be printed as additional comments + +@ Based on register description in +@ ARM Generic Interrupt Controller +@ Architecture Specification +@ GIC architecture version 3.0 and version 4.0 + +@ Table 8-7 Mapping of MCR and MRC to physical and virtual CPU interface registers, AArch32 state +ICC_AP0R0 c12 0 c8 4 RW +ICC_AP0R1 c12 0 c8 5 RW +ICC_AP0R2 c12 0 c8 6 RW +ICC_AP0R3 c12 0 c8 7 RW +ICC_AP1R0 c12 0 c9 0 RW +ICC_AP1R1 c12 0 c9 1 RW +ICC_AP1R2 c12 0 c9 2 RW +ICC_AP1R3 c12 0 c9 3 RW +ICC_ASGI1R - 1 c12 - WO +ICC_BPR0 c12 0 c8 3 RW +ICC_BPR1 c12 0 c12 3 RW +ICC_CTLR c12 0 c12 4 RW +ICC_DIR c12 0 c11 1 WO +ICC_EOIR0 c12 0 c8 1 WO +ICC_EOIR1 c12 0 c12 1 WO +ICC_HPPIR0 c12 0 c8 2 RO +ICC_HPPIR1 c12 0 c12 2 RO +ICC_HSRE c12 4 c9 5 RW +ICC_IAR0 c12 0 c8 0 RO +ICC_IAR1 c12 0 c12 0 RO +ICC_IGRPEN0 c12 0 c12 6 RW +ICC_IGRPEN1 c12 0 c12 7 RW +ICC_MCTLR c12 6 c12 4 RW +ICC_MGRPEN1 c12 6 c12 7 RW +ICC_MSRE c12 6 c12 5 RW +ICC_PMR c4 0 c6 0 RW +ICC_RPR c12 0 c11 3 RO +ICC_SGI0R - 2 c12 - WO +ICC_SGI1R - 0 c12 - WO +ICC_SRE c12 0 c12 5 RW diff --git a/optee/optee_os/core/arch/arm/kernel/arm32_sysreg.txt b/optee/optee_os/core/arch/arm/kernel/arm32_sysreg.txt new file mode 100644 index 0000000..b69ebcb --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/arm32_sysreg.txt @@ -0,0 +1,146 @@ +# Format of file +# +# lines beginning with '@' will be printed as additional comments + +@ Based on register description in +@ ARM Architecture Reference Manual +@ ARMv7-A and ARMv7-R edition +@ Issue C.c +@ + +@ B3.18.1 Identification registers, functional group +AIDR c0 1 c0 7 RO IMPLEMENTATION DEFINED Auxiliary ID Register +CCSIDR c0 1 c0 0 RO Cache Size ID Registers +CLIDR c0 1 c0 1 RO Cache Level ID Register +CSSELR c0 2 c0 0 RW Cache Size Selection Register +CTR c0 0 c0 1 RO Cache Type Register +ID_AFR0 c0 0 c1 3 RO Auxiliary Feature Register 0 +ID_DFR0 c0 0 c1 2 RO Debug Feature Register 0 +ID_ISAR0 c0 0 c2 0 RO Instruction Set Attribute Register 0 +ID_ISAR1 c0 0 c2 1 RO Instruction Set Attribute Register 1 +ID_ISAR2 c0 0 c2 2 RO Instruction Set Attribute Register 2 +ID_ISAR3 c0 0 c2 3 RO Instruction Set Attribute Register 3 +ID_ISAR4 c0 0 c2 4 RO Instruction Set Attribute Register 4 +ID_ISAR5 c0 0 c2 5 RO Instruction Set Attribute Register 5 +ID_MMFR0 c0 0 c1 4 RO Memory Model Feature Register 0 +ID_MMFR1 c0 0 c1 5 RO Memory Model Feature Register 1 +ID_MMFR2 c0 0 c1 6 RO Memory Model Feature Register 2 +ID_MMFR3 c0 0 c1 7 RO Memory Model Feature Register 3 +ID_PFR0 c0 0 c1 0 RO Processor Feature Register 0 +ID_PFR1 c0 0 c1 1 RO Processor Feature Register 1 +MIDR c0 0 c0 0 RO Main ID Register +MPIDR c0 0 c0 5 RO Multiprocessor Affinity Register +REVIDR c0 0 c0 6 RO Revision ID Register +TCMTR c0 0 c0 2 RO TCM Type Register +TLBTR c0 0 c0 3 RO TLB Type Register + +@ B3.18.2 Virtual memory control registers, functional group +AMAIR0 c10 0 c3 0 RW Auxiliary Memory Attribute Indirection Register 0 +AMAIR1 c10 0 c3 1 RW Auxiliary Memory Attribute Indirection Register 1 +CONTEXTIDR c13 0 c0 1 RW Context ID Register +DACR c3 0 c0 0 RW Domain Access Control Register +MAIR0 c10 0 c2 0 RW Memory Attribute Indirection Register 0 +MAIR1 c10 0 c2 1 RW Memory Attribute Indirection Register 1 +NMRR c10 0 c2 1 RW Normal Memory Remap Register +PRRR c10 0 c2 0 RW Primary Region Remap Register +SCTLR c1 0 c0 0 RW System Control Register +TTBCR c2 0 c0 2 RW Translation Table Base Control Register +TTBR0 c2 0 c0 0 RW Translation Table Base Register 0 +TTBR0_64bit - 0 c2 - RW Translation Table Base Register 0 +TTBR1 c2 0 c0 1 RW Translation Table Base Register 1 +TTBR1_64bit - 1 c2 - RW Translation Table Base Register 1 + +@ B3.18.3 PL1 Fault handling registers, functional group +ADFSR c5 0 c1 0 RW Auxiliary Data Fault Status Register +AIFSR c5 0 c1 1 RW Auxiliary Instruction Fault Status Register +DFAR c6 0 c0 0 RW Data Fault Address Register +DFSR c5 0 c0 0 RW Data Fault Status Register +IFAR c6 0 c0 2 RW Instruction Fault Address Register +IFSR c5 0 c0 1 RW Instruction Fault Status Register + +@ B3.18.4 Other system control registers, functional group +ACTLR c1 0 c0 1 RW IMPLEMENTATION DEFINED Auxiliary Control Register +CPACR c1 0 c0 2 RW Coprocessor Access Control Register +FCSEIDR c13 0 c0 0 RW FCSE Process ID Register + +@ B3.18.6 Cache maintenance operations, functional group, VMSA +BPIALL c7 0 c5 6 WOD Branch predictor invalidate all +BPIALLIS c7 0 c1 6 WOD Branch predictor invalidate all IS +BPIMVA c7 0 c5 7 WO Branch predictor invalidate by MVA +DCCIMVAC c7 0 c14 1 WO Data cache clean and invalidate by MVA PoC +DCCISW c7 0 c14 2 WO Data cache clean and invalidate by set/way +DCCMVAC c7 0 c10 1 WO Data cache clean by MVA PoC +DCCMVAU c7 0 c11 1 WO Data cache clean by MVA PoU +DCCSW c7 0 c10 2 WO Data cache clean by set/way +DCIMVAC c7 0 c6 1 WO Data cache invalidate by MVA PoC +DCISW c7 0 c6 2 WO Data cache invalidate by set/way +ICIALLU c7 0 c5 0 WOD Instruction cache invalidate all PoU +ICIALLUIS c7 0 c1 0 WOD Instruction cache invalidate all PoU, IS +ICIMVAU c7 0 c5 1 WO Instruction cache invalidate by MVA PoU + +@ B3.18.7 TLB maintenance operations, functional group +TLBIALL c8 0 c7 0 WOD Invalidate entire unified TLB +TLBIALLIS c8 0 c3 0 WOD Invalidate entire unified TLB IS +TLBIASID c8 0 c7 2 WO Invalidate unified TLB by ASID +TLBIASIDIS c8 0 c3 2 WO Invalidate unified TLB by ASID IS +TLBIMVAA c8 0 c7 3 WO Invalidate unified TLB by MVA, all ASID +TLBIMVAAIS c8 0 c3 3 WO Invalidate unified TLB by MVA, all ASID IS +TLBIMVA c8 0 c7 1 WO Invalidate unified TLB by MVA +TLBIMVAIS c8 0 c3 1 WO Invalidate unified TLB by MVA IS + +@ B3.18.8 Address translation operations, functional group +ATS12NSOPR c7 0 c8 4 WO Stages 1 and 2 Non-secure only PL1 read +ATS12NSOPW c7 0 c8 5 WO Stages 1 and 2 Non-secure only PL1 write +ATS12NSOUR c7 0 c8 6 WO Stages 1 and 2 Non-secure only unprivileged read +ATS12NSOUW c7 0 c8 7 WO Stages 1 and 2 Non-secure only unprivileged write +ATS1CPR c7 0 c8 0 WO Stage 1 Current state PL1 read +ATS1CPW c7 0 c8 1 WO Stage 1 Current state PL1 write +ATS1CUR c7 0 c8 2 WO Stage 1 Current state unprivileged read +ATS1CUW c7 0 c8 3 WO Stage 1 Current state unprivileged write +ATS1HR c7 4 c8 0 WO Stage 1 Hyp mode read +ATS1HW c7 4 c8 1 WO Stage 1 Hyp mode write +PAR32 c7 0 c4 0 RW Physical Address Register +PAR64 - 0 c7 - RW Physical Address Register + +@ B3.18.9 Miscellaneous operations, functional group +TPIDRPRW c13 0 c0 4 RW PL1 only Thread ID Register +TPIDRURO c13 0 c0 3 RW PL0 User Read-Only Thread ID Register +TPIDRURW c13 0 c0 2 RW PL0 User Read/Write Thread ID Register + +@ B3.18.11 Security Extensions registers, functional group +ISR c12 0 c1 0 RO Interrupt Status Register +MVBAR c12 0 c0 1 RW Monitor Vector Base Address Register +NSACR c1 0 c1 2 RW Non-Secure Access Control Register +SCR c1 0 c1 0 RW Secure Configuration Register +SDER c1 0 c1 1 RW Secure Debug Enable Register +VBAR c12 0 c0 0 RW Vector Base Address Register + +@ B8.2 Generic Timer registers summary +CNTFRQ c14 0 c0 0 RW Counter Frequency register +CNTPCT - 0 c14 - RO Physical Count register +CNTKCTL c14 0 c1 0 RW Timer PL1 Control register +CNTP_TVAL c14 0 c2 0 RW PL1 Physical TimerValue register +CNTP_CTL c14 0 c2 1 RW PL1 Physical Timer Control register +CNTV_TVAL c14 0 c3 0 RW Virtual TimerValue register +CNTV_CTL c14 0 c3 1 RW Virtual Timer Control register +CNTVCT - 1 c14 - RO Virtual Count register +CNTP_CVAL - 2 c14 - RW PL1 Physical Timer CompareValue register +CNTV_CVAL - 3 c14 - RW Virtual Timer CompareValue register +CNTVOFF - 4 c14 - RW Virtual Offset register + +@ Table C12-7 Performance Monitors register summary +PMCR c9 0 c12 0 RW Performance Monitors Control Register +PMCNTENSET c9 0 c12 1 RW Performance Monitors Count Enable Set register +PMCNTENCLR c9 0 c12 2 RW Performance Monitors Count Enable Clear register +PMOVSR c9 0 c12 3 RW Performance Monitors Overflow Flag Status Register +PMSWINC c9 0 c12 4 WO Performance Monitors Software Increment register +PMSELR c9 0 c12 5 RW Performance Monitors Event Counter Selection Register +PMCEID0 c9 0 c12 6 RO Performance Monitors Common Event Identification reg 0 +PMCEID1 c9 0 c12 7 RO Performance Monitors Common Event Identification reg 1 +PMCCNTR c9 0 c13 0 RW Performance Monitors Cycle Count Register +PMXEVTYPER c9 0 c13 1 RW Performance Monitors Event Type Select Register +PMXEVCNTR c9 0 c13 2 RW Performance Monitors Event Count Register +PMUSERENR c9 0 c14 0 RW Performance Monitors User Enable Register +PMINTENSET c9 0 c14 1 RW Performance Monitors Interrupt Enable Set register +PMINTENCLR c9 0 c14 2 RW Performance Monitors Interrupt Enable Clear register +PMOVSSET c9 0 c14 3 RW Performance Monitors Overflow Flag Status Set register diff --git a/optee/optee_os/core/arch/arm/kernel/asm-defines.c b/optee/optee_os/core/arch/arm/kernel/asm-defines.c new file mode 100644 index 0000000..64e5b13 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/asm-defines.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +DEFINES +{ +#ifdef ARM32 + DEFINE(SM_NSEC_CTX_R0, offsetof(struct sm_nsec_ctx, r0)); + DEFINE(SM_NSEC_CTX_R8, offsetof(struct sm_nsec_ctx, r8)); + DEFINE(SM_SEC_CTX_R0, offsetof(struct sm_sec_ctx, r0)); + DEFINE(SM_SEC_CTX_MON_LR, offsetof(struct sm_sec_ctx, mon_lr)); + DEFINE(SM_CTX_SEC_SIZE, sizeof(struct sm_sec_ctx)); + DEFINE(SM_CTX_SIZE, sizeof(struct sm_ctx)); + DEFINE(SM_CTX_NSEC, offsetof(struct sm_ctx, nsec)); + DEFINE(SM_CTX_SEC, offsetof(struct sm_ctx, sec)); + + DEFINE(THREAD_SCALL_REG_R0, offsetof(struct thread_scall_regs, r0)); + DEFINE(THREAD_SCALL_REG_R5, offsetof(struct thread_scall_regs, r5)); + DEFINE(THREAD_SCALL_REG_R6, offsetof(struct thread_scall_regs, r6)); + + /* struct thread_ctx */ + DEFINE(THREAD_CTX_STACK_VA_END, offsetof(struct thread_ctx, + stack_va_end)); + + /* struct thread_ctx_regs */ + DEFINE(THREAD_CTX_REGS_USR_SP, + offsetof(struct thread_ctx_regs, usr_sp)); + DEFINE(THREAD_CTX_REGS_PC, offsetof(struct thread_ctx_regs, pc)); + DEFINE(THREAD_CTX_REGS_CPSR, offsetof(struct thread_ctx_regs, cpsr)); + + /* struct thread_core_local */ + DEFINE(THREAD_CORE_LOCAL_R0, offsetof(struct thread_core_local, r[0])); + DEFINE(THREAD_CORE_LOCAL_SM_PM_CTX_PHYS, + offsetof(struct thread_core_local, sm_pm_ctx_phys)); + DEFINE(THREAD_CORE_LOCAL_SIZE, sizeof(struct thread_core_local)); + + DEFINE(SM_PM_CTX_SIZE, sizeof(struct sm_pm_ctx)); +#endif /*ARM32*/ + +#ifdef ARM64 + DEFINE(THREAD_SMC_ARGS_X0, offsetof(struct thread_smc_args, a0)); + DEFINE(THREAD_SMC_ARGS_SIZE, sizeof(struct thread_smc_args)); + + DEFINE(THREAD_SCALL_REG_X0, offsetof(struct thread_scall_regs, x0)); + DEFINE(THREAD_SCALL_REG_X2, offsetof(struct thread_scall_regs, x2)); + DEFINE(THREAD_SCALL_REG_X5, offsetof(struct thread_scall_regs, x5)); + DEFINE(THREAD_SCALL_REG_X6, offsetof(struct thread_scall_regs, x6)); + DEFINE(THREAD_SCALL_REG_X30, offsetof(struct thread_scall_regs, x30)); + DEFINE(THREAD_SCALL_REG_ELR, offsetof(struct thread_scall_regs, elr)); + DEFINE(THREAD_SCALL_REG_SPSR, offsetof(struct thread_scall_regs, spsr)); + DEFINE(THREAD_SCALL_REG_SP_EL0, offsetof(struct thread_scall_regs, + sp_el0)); +#ifdef CFG_TA_PAUTH + DEFINE(THREAD_SCALL_REG_APIAKEY_HI, offsetof(struct thread_scall_regs, + apiakey_hi)); +#endif + DEFINE(THREAD_SCALL_REG_SIZE, sizeof(struct thread_scall_regs)); + + /* struct thread_abort_regs */ + DEFINE(THREAD_ABT_REG_X0, offsetof(struct thread_abort_regs, x0)); + DEFINE(THREAD_ABT_REG_X2, offsetof(struct thread_abort_regs, x2)); + DEFINE(THREAD_ABT_REG_X30, offsetof(struct thread_abort_regs, x30)); + DEFINE(THREAD_ABT_REG_SPSR, offsetof(struct thread_abort_regs, spsr)); + DEFINE(THREAD_ABT_REGS_SIZE, sizeof(struct thread_abort_regs)); +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + DEFINE(THREAD_ABT_REGS_APIAKEY_HI, offsetof(struct thread_abort_regs, + apiakey_hi)); +#endif + + /* struct thread_ctx */ + DEFINE(THREAD_CTX_KERN_SP, offsetof(struct thread_ctx, kern_sp)); + DEFINE(THREAD_CTX_STACK_VA_END, offsetof(struct thread_ctx, + stack_va_end)); +#if defined(CFG_CORE_PAUTH) + DEFINE(THREAD_CTX_KEYS, offsetof(struct thread_ctx, keys)); +#endif + + /* struct thread_ctx_regs */ + DEFINE(THREAD_CTX_REGS_SP, offsetof(struct thread_ctx_regs, sp)); + DEFINE(THREAD_CTX_REGS_X0, offsetof(struct thread_ctx_regs, x[0])); + DEFINE(THREAD_CTX_REGS_X1, offsetof(struct thread_ctx_regs, x[1])); + DEFINE(THREAD_CTX_REGS_X2, offsetof(struct thread_ctx_regs, x[2])); + DEFINE(THREAD_CTX_REGS_X4, offsetof(struct thread_ctx_regs, x[4])); + DEFINE(THREAD_CTX_REGS_X19, offsetof(struct thread_ctx_regs, x[19])); + DEFINE(THREAD_CTX_REGS_TPIDR_EL0, offsetof(struct thread_ctx_regs, + tpidr_el0)); +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + DEFINE(THREAD_CTX_REGS_APIAKEY_HI, offsetof(struct thread_ctx_regs, + apiakey_hi)); +#endif + + /* struct thread_user_mode_rec */ + DEFINE(THREAD_USER_MODE_REC_CTX_REGS_PTR, + offsetof(struct thread_user_mode_rec, ctx_regs_ptr)); + DEFINE(THREAD_USER_MODE_REC_EXIT_STATUS0_PTR, + offsetof(struct thread_user_mode_rec, exit_status0_ptr)); + DEFINE(THREAD_USER_MODE_REC_X19, + offsetof(struct thread_user_mode_rec, x[0])); + DEFINE(THREAD_USER_MODE_REC_SIZE, sizeof(struct thread_user_mode_rec)); + + /* struct thread_core_local */ + DEFINE(THREAD_CORE_LOCAL_X0, offsetof(struct thread_core_local, x[0])); + DEFINE(THREAD_CORE_LOCAL_X2, offsetof(struct thread_core_local, x[2])); + DEFINE(THREAD_CORE_LOCAL_KCODE_OFFSET, + offsetof(struct thread_core_local, kcode_offset)); +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC + DEFINE(THREAD_CORE_LOCAL_BHB_LOOP_COUNT, + offsetof(struct thread_core_local, bhb_loop_count)); +#endif +#if defined(CFG_CORE_PAUTH) + DEFINE(THREAD_CORE_LOCAL_KEYS, + offsetof(struct thread_core_local, keys)); +#endif +#endif /*ARM64*/ + + /* struct thread_ctx */ + DEFINE(THREAD_CTX_SIZE, sizeof(struct thread_ctx)); +#ifdef CFG_CORE_FFA + DEFINE(THREAD_CTX_TSD_RPC_TARGET_INFO, + offsetof(struct thread_ctx, tsd.rpc_target_info)) +#endif + + /* struct thread_core_local */ + DEFINE(THREAD_CORE_LOCAL_TMP_STACK_VA_END, + offsetof(struct thread_core_local, tmp_stack_va_end)); + DEFINE(THREAD_CORE_LOCAL_CURR_THREAD, + offsetof(struct thread_core_local, curr_thread)); + DEFINE(THREAD_CORE_LOCAL_FLAGS, + offsetof(struct thread_core_local, flags)); + DEFINE(THREAD_CORE_LOCAL_ABT_STACK_VA_END, + offsetof(struct thread_core_local, abt_stack_va_end)); + + DEFINE(STACK_TMP_GUARD, STACK_CANARY_SIZE / 2 + STACK_TMP_OFFS); + + /* struct core_mmu_config */ + DEFINE(CORE_MMU_CONFIG_SIZE, sizeof(struct core_mmu_config)); + DEFINE(CORE_MMU_CONFIG_MAP_OFFSET, + offsetof(struct core_mmu_config, map_offset)); + + /* struct boot_embdata */ + DEFINE(BOOT_EMBDATA_HASHES_OFFSET, + offsetof(struct boot_embdata, hashes_offset)); + DEFINE(BOOT_EMBDATA_HASHES_LEN, + offsetof(struct boot_embdata, hashes_len)); + DEFINE(BOOT_EMBDATA_RELOC_OFFSET, + offsetof(struct boot_embdata, reloc_offset)); + DEFINE(BOOT_EMBDATA_RELOC_LEN, + offsetof(struct boot_embdata, reloc_len)); +} diff --git a/optee/optee_os/core/arch/arm/kernel/boot.c b/optee/optee_os/core/arch/arm/kernel/boot.c new file mode 100644 index 0000000..32dd417 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/boot.c @@ -0,0 +1,1724 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2023, Linaro Limited + * Copyright (c) 2023, Arm Limited + */ + +#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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if !defined(CFG_WITH_ARM_TRUSTED_FW) +#include +#endif + +#if defined(CFG_WITH_VFP) +#include +#endif + +/* + * In this file we're using unsigned long to represent physical pointers as + * they are received in a single register when OP-TEE is initially entered. + * This limits 32-bit systems to only use make use of the lower 32 bits + * of a physical address for initial parameters. + * + * 64-bit systems on the other hand can use full 64-bit physical pointers. + */ +#define PADDR_INVALID ULONG_MAX + +#if defined(CFG_BOOT_SECONDARY_REQUEST) +struct ns_entry_context { + uintptr_t entry_point; + uintptr_t context_id; +}; +struct ns_entry_context ns_entry_contexts[CFG_TEE_CORE_NB_CORE]; +static uint32_t spin_table[CFG_TEE_CORE_NB_CORE]; +#endif + +#ifdef CFG_BOOT_SYNC_CPU +/* + * Array used when booting, to synchronize cpu. + * When 0, the cpu has not started. + * When 1, it has started + */ +uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE]; +DECLARE_KEEP_PAGER(sem_cpu_sync); +#endif + +#ifdef CFG_DT +struct dt_descriptor { + void *blob; +#ifdef _CFG_USE_DTB_OVERLAY + int frag_id; +#endif +}; + +static struct dt_descriptor external_dt __nex_bss; +#ifdef CFG_CORE_SEL1_SPMC +static struct dt_descriptor tos_fw_config_dt __nex_bss; +#endif +#endif + +#ifdef CFG_SECONDARY_INIT_CNTFRQ +static uint32_t cntfrq; +#endif + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void plat_primary_init_early(void) +{ +} +DECLARE_KEEP_PAGER(plat_primary_init_early); + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void main_init_gic(void) +{ +} + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void main_secondary_init_gic(void) +{ +} + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak unsigned long plat_get_aslr_seed(void) +{ + DMSG("Warning: no ASLR seed"); + + return 0; +} + +#if defined(_CFG_CORE_STACK_PROTECTOR) +/* Generate random stack canary value on boot up */ +__weak uintptr_t plat_get_random_stack_canary(void) +{ + uintptr_t canary = 0xbaaaad00; + TEE_Result ret = TEE_ERROR_GENERIC; + + /* + * With virtualization the RNG is not initialized in Nexus core. + * Need to override with platform specific implementation. + */ + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + IMSG("WARNING: Using fixed value for stack canary"); + return canary; + } + + ret = crypto_rng_read(&canary, sizeof(canary)); + if (ret != TEE_SUCCESS) + panic("Failed to generate random stack canary"); + + /* Leave null byte in canary to prevent string base exploit */ + return canary & ~0xffUL; +} +#endif /*_CFG_CORE_STACK_PROTECTOR*/ + +/* + * This function is called as a guard after each smc call which is not + * supposed to return. + */ +void __panic_at_smc_return(void) +{ + panic(); +} + +#if defined(CFG_WITH_ARM_TRUSTED_FW) +void init_sec_mon(unsigned long nsec_entry __maybe_unused) +{ + assert(nsec_entry == PADDR_INVALID); + /* Do nothing as we don't have a secure monitor */ +} +#else +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void init_sec_mon(unsigned long nsec_entry) +{ + struct sm_nsec_ctx *nsec_ctx; + + assert(nsec_entry != PADDR_INVALID); + + /* Initialize secure monitor */ + nsec_ctx = sm_get_nsec_ctx(); + nsec_ctx->mon_lr = nsec_entry; + nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I; + if (nsec_entry & 1) + nsec_ctx->mon_spsr |= CPSR_T; +} +#endif + +#if defined(CFG_WITH_ARM_TRUSTED_FW) +static void init_vfp_nsec(void) +{ +} +#else +static void init_vfp_nsec(void) +{ + /* Normal world can use CP10 and CP11 (SIMD/VFP) */ + write_nsacr(read_nsacr() | NSACR_CP10 | NSACR_CP11); +} +#endif + +#if defined(CFG_WITH_VFP) + +#ifdef ARM32 +static void init_vfp_sec(void) +{ + uint32_t cpacr = read_cpacr(); + + /* + * Enable Advanced SIMD functionality. + * Enable use of D16-D31 of the Floating-point Extension register + * file. + */ + cpacr &= ~(CPACR_ASEDIS | CPACR_D32DIS); + /* + * Enable usage of CP10 and CP11 (SIMD/VFP) (both kernel and user + * mode. + */ + cpacr |= CPACR_CP(10, CPACR_CP_ACCESS_FULL); + cpacr |= CPACR_CP(11, CPACR_CP_ACCESS_FULL); + write_cpacr(cpacr); +} +#endif /* ARM32 */ + +#ifdef ARM64 +static void init_vfp_sec(void) +{ + /* Not using VFP until thread_kernel_enable_vfp() */ + vfp_disable(); +} +#endif /* ARM64 */ + +#else /* CFG_WITH_VFP */ + +static void init_vfp_sec(void) +{ + /* Not using VFP */ +} +#endif + +#ifdef CFG_SECONDARY_INIT_CNTFRQ +static void primary_save_cntfrq(void) +{ + assert(cntfrq == 0); + + /* + * CNTFRQ should be initialized on the primary CPU by a + * previous boot stage + */ + cntfrq = read_cntfrq(); +} + +static void secondary_init_cntfrq(void) +{ + assert(cntfrq != 0); + write_cntfrq(cntfrq); +} +#else /* CFG_SECONDARY_INIT_CNTFRQ */ +static void primary_save_cntfrq(void) +{ +} + +static void secondary_init_cntfrq(void) +{ +} +#endif + +#ifdef CFG_CORE_SANITIZE_KADDRESS +static void init_run_constructors(void) +{ + const vaddr_t *ctor; + + for (ctor = &__ctor_list; ctor < &__ctor_end; ctor++) + ((void (*)(void))(*ctor))(); +} + +static void init_asan(void) +{ + + /* + * CFG_ASAN_SHADOW_OFFSET is also supplied as + * -fasan-shadow-offset=$(CFG_ASAN_SHADOW_OFFSET) to the compiler. + * Since all the needed values to calculate the value of + * CFG_ASAN_SHADOW_OFFSET isn't available in to make we need to + * calculate it in advance and hard code it into the platform + * conf.mk. Here where we have all the needed values we double + * check that the compiler is supplied the correct value. + */ + +#define __ASAN_SHADOW_START \ + ROUNDUP(TEE_RAM_START + (TEE_RAM_VA_SIZE * 8) / 9 - 8, 8) + assert(__ASAN_SHADOW_START == (vaddr_t)&__asan_shadow_start); +#define __CFG_ASAN_SHADOW_OFFSET \ + (__ASAN_SHADOW_START - (TEE_RAM_START / 8)) + COMPILE_TIME_ASSERT(CFG_ASAN_SHADOW_OFFSET == __CFG_ASAN_SHADOW_OFFSET); +#undef __ASAN_SHADOW_START +#undef __CFG_ASAN_SHADOW_OFFSET + + /* + * Assign area covered by the shadow area, everything from start up + * to the beginning of the shadow area. + */ + asan_set_shadowed((void *)TEE_LOAD_ADDR, &__asan_shadow_start); + + /* + * Add access to areas that aren't opened automatically by a + * constructor. + */ + asan_tag_access(&__ctor_list, &__ctor_end); + asan_tag_access(__rodata_start, __rodata_end); +#ifdef CFG_WITH_PAGER + asan_tag_access(__pageable_start, __pageable_end); +#endif /*CFG_WITH_PAGER*/ + asan_tag_access(__nozi_start, __nozi_end); + asan_tag_access(__exidx_start, __exidx_end); + asan_tag_access(__extab_start, __extab_end); + + init_run_constructors(); + + /* Everything is tagged correctly, let's start address sanitizing. */ + asan_start(); +} +#else /*CFG_CORE_SANITIZE_KADDRESS*/ +static void init_asan(void) +{ +} +#endif /*CFG_CORE_SANITIZE_KADDRESS*/ + +#if defined(CFG_MEMTAG) +/* Called from entry_a64.S only when MEMTAG is configured */ +void boot_init_memtag(void) +{ + paddr_t base = 0; + paddr_size_t size = 0; + + memtag_init_ops(feat_mte_implemented()); + core_mmu_get_secure_memory(&base, &size); + memtag_set_tags((void *)(vaddr_t)base, size, 0); +} +#endif + +#ifdef CFG_WITH_PAGER + +#ifdef CFG_CORE_SANITIZE_KADDRESS +static void carve_out_asan_mem(tee_mm_pool_t *pool) +{ + const size_t s = pool->hi - pool->lo; + tee_mm_entry_t *mm; + paddr_t apa = ASAN_MAP_PA; + size_t asz = ASAN_MAP_SZ; + + if (core_is_buffer_outside(apa, asz, pool->lo, s)) + return; + + /* Reserve the shadow area */ + if (!core_is_buffer_inside(apa, asz, pool->lo, s)) { + if (apa < pool->lo) { + /* + * ASAN buffer is overlapping with the beginning of + * the pool. + */ + asz -= pool->lo - apa; + apa = pool->lo; + } else { + /* + * ASAN buffer is overlapping with the end of the + * pool. + */ + asz = pool->hi - apa; + } + } + mm = tee_mm_alloc2(pool, apa, asz); + assert(mm); +} +#else +static void carve_out_asan_mem(tee_mm_pool_t *pool __unused) +{ +} +#endif + +static void print_pager_pool_size(void) +{ + struct tee_pager_stats __maybe_unused stats; + + tee_pager_get_stats(&stats); + IMSG("Pager pool size: %zukB", + stats.npages_all * SMALL_PAGE_SIZE / 1024); +} + +static void init_vcore(tee_mm_pool_t *mm_vcore) +{ + const vaddr_t begin = VCORE_START_VA; + size_t size = TEE_RAM_VA_SIZE; + +#ifdef CFG_CORE_SANITIZE_KADDRESS + /* Carve out asan memory, flat maped after core memory */ + if (begin + size > ASAN_SHADOW_PA) + size = ASAN_MAP_PA - begin; +#endif + + if (!tee_mm_init(mm_vcore, begin, size, SMALL_PAGE_SHIFT, + TEE_MM_POOL_NO_FLAGS)) + panic("tee_mm_vcore init failed"); +} + +/* + * With CFG_CORE_ASLR=y the init part is relocated very early during boot. + * The init part is also paged just as the rest of the normal paged code, with + * the difference that it's preloaded during boot. When the backing store + * is configured the entire paged binary is copied in place and then also + * the init part. Since the init part has been relocated (references to + * addresses updated to compensate for the new load address) this has to be + * undone for the hashes of those pages to match with the original binary. + * + * If CFG_CORE_ASLR=n, nothing needs to be done as the code/ro pages are + * unchanged. + */ +static void undo_init_relocation(uint8_t *paged_store __maybe_unused) +{ +#ifdef CFG_CORE_ASLR + unsigned long *ptr = NULL; + const uint32_t *reloc = NULL; + const uint32_t *reloc_end = NULL; + unsigned long offs = boot_mmu_config.map_offset; + const struct boot_embdata *embdata = (const void *)__init_end; + vaddr_t addr_end = (vaddr_t)__init_end - offs - TEE_LOAD_ADDR; + vaddr_t addr_start = (vaddr_t)__init_start - offs - TEE_LOAD_ADDR; + + reloc = (const void *)((vaddr_t)embdata + embdata->reloc_offset); + reloc_end = reloc + embdata->reloc_len / sizeof(*reloc); + + for (; reloc < reloc_end; reloc++) { + if (*reloc < addr_start) + continue; + if (*reloc >= addr_end) + break; + ptr = (void *)(paged_store + *reloc - addr_start); + *ptr -= offs; + } +#endif +} + +static struct fobj *ro_paged_alloc(tee_mm_entry_t *mm, void *hashes, + void *store) +{ + const unsigned int num_pages = tee_mm_get_bytes(mm) / SMALL_PAGE_SIZE; +#ifdef CFG_CORE_ASLR + unsigned int reloc_offs = (vaddr_t)__pageable_start - VCORE_START_VA; + const struct boot_embdata *embdata = (const void *)__init_end; + const void *reloc = __init_end + embdata->reloc_offset; + + return fobj_ro_reloc_paged_alloc(num_pages, hashes, reloc_offs, + reloc, embdata->reloc_len, store); +#else + return fobj_ro_paged_alloc(num_pages, hashes, store); +#endif +} + +static void init_runtime(unsigned long pageable_part) +{ + size_t n; + size_t init_size = (size_t)(__init_end - __init_start); + size_t pageable_start = (size_t)__pageable_start; + size_t pageable_end = (size_t)__pageable_end; + size_t pageable_size = pageable_end - pageable_start; + vaddr_t tzsram_end = TZSRAM_BASE + TZSRAM_SIZE - TEE_LOAD_ADDR + + VCORE_START_VA; + size_t hash_size = (pageable_size / SMALL_PAGE_SIZE) * + TEE_SHA256_HASH_SIZE; + const struct boot_embdata *embdata = (const void *)__init_end; + const void *tmp_hashes = NULL; + tee_mm_entry_t *mm = NULL; + struct fobj *fobj = NULL; + uint8_t *paged_store = NULL; + uint8_t *hashes = NULL; + + assert(pageable_size % SMALL_PAGE_SIZE == 0); + assert(embdata->total_len >= embdata->hashes_offset + + embdata->hashes_len); + assert(hash_size == embdata->hashes_len); + + tmp_hashes = __init_end + embdata->hashes_offset; + + init_asan(); + + /* Add heap2 first as heap1 may be too small as initial bget pool */ + malloc_add_pool(__heap2_start, __heap2_end - __heap2_start); + malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); + + /* + * This needs to be initialized early to support address lookup + * in MEM_AREA_TEE_RAM + */ + tee_pager_early_init(); + + hashes = malloc(hash_size); + IMSG_RAW("\n"); + IMSG("Pager is enabled. Hashes: %zu bytes", hash_size); + assert(hashes); + asan_memcpy_unchecked(hashes, tmp_hashes, hash_size); + + /* + * Need tee_mm_sec_ddr initialized to be able to allocate secure + * DDR below. + */ + core_mmu_init_ta_ram(); + + carve_out_asan_mem(&tee_mm_sec_ddr); + + mm = tee_mm_alloc(&tee_mm_sec_ddr, pageable_size); + assert(mm); + paged_store = phys_to_virt(tee_mm_get_smem(mm), MEM_AREA_TA_RAM, + pageable_size); + /* + * Load pageable part in the dedicated allocated area: + * - Move pageable non-init part into pageable area. Note bootloader + * may have loaded it anywhere in TA RAM hence use memmove(). + * - Copy pageable init part from current location into pageable area. + */ + memmove(paged_store + init_size, + phys_to_virt(pageable_part, + core_mmu_get_type_by_pa(pageable_part), + __pageable_part_end - __pageable_part_start), + __pageable_part_end - __pageable_part_start); + asan_memcpy_unchecked(paged_store, __init_start, init_size); + /* + * Undo eventual relocation for the init part so the hash checks + * can pass. + */ + undo_init_relocation(paged_store); + + /* Check that hashes of what's in pageable area is OK */ + DMSG("Checking hashes of pageable area"); + for (n = 0; (n * SMALL_PAGE_SIZE) < pageable_size; n++) { + const uint8_t *hash = hashes + n * TEE_SHA256_HASH_SIZE; + const uint8_t *page = paged_store + n * SMALL_PAGE_SIZE; + TEE_Result res; + + DMSG("hash pg_idx %zu hash %p page %p", n, hash, page); + res = hash_sha256_check(hash, page, SMALL_PAGE_SIZE); + if (res != TEE_SUCCESS) { + EMSG("Hash failed for page %zu at %p: res 0x%x", + n, (void *)page, res); + panic(); + } + } + + /* + * Assert prepaged init sections are page aligned so that nothing + * trails uninited at the end of the premapped init area. + */ + assert(!(init_size & SMALL_PAGE_MASK)); + + /* + * Initialize the virtual memory pool used for main_mmu_l2_ttb which + * is supplied to tee_pager_init() below. + */ + init_vcore(&tee_mm_vcore); + + /* + * Assign alias area for pager end of the small page block the rest + * of the binary is loaded into. We're taking more than needed, but + * we're guaranteed to not need more than the physical amount of + * TZSRAM. + */ + mm = tee_mm_alloc2(&tee_mm_vcore, + (vaddr_t)tee_mm_vcore.lo + + tee_mm_vcore.size - TZSRAM_SIZE, + TZSRAM_SIZE); + assert(mm); + tee_pager_set_alias_area(mm); + + /* + * Claim virtual memory which isn't paged. + * Linear memory (flat map core memory) ends there. + */ + mm = tee_mm_alloc2(&tee_mm_vcore, VCORE_UNPG_RX_PA, + (vaddr_t)(__pageable_start - VCORE_UNPG_RX_PA)); + assert(mm); + + /* + * Allocate virtual memory for the pageable area and let the pager + * take charge of all the pages already assigned to that memory. + */ + mm = tee_mm_alloc2(&tee_mm_vcore, (vaddr_t)__pageable_start, + pageable_size); + assert(mm); + fobj = ro_paged_alloc(mm, hashes, paged_store); + assert(fobj); + tee_pager_add_core_region(tee_mm_get_smem(mm), PAGED_REGION_TYPE_RO, + fobj); + fobj_put(fobj); + + tee_pager_add_pages(pageable_start, init_size / SMALL_PAGE_SIZE, false); + tee_pager_add_pages(pageable_start + init_size, + (pageable_size - init_size) / SMALL_PAGE_SIZE, + true); + if (pageable_end < tzsram_end) + tee_pager_add_pages(pageable_end, (tzsram_end - pageable_end) / + SMALL_PAGE_SIZE, true); + + /* + * There may be physical pages in TZSRAM before the core load address. + * These pages can be added to the physical pages pool of the pager. + * This setup may happen when a the secure bootloader runs in TZRAM + * and its memory can be reused by OP-TEE once boot stages complete. + */ + tee_pager_add_pages(tee_mm_vcore.lo, + (VCORE_UNPG_RX_PA - tee_mm_vcore.lo) / SMALL_PAGE_SIZE, + true); + + print_pager_pool_size(); +} +#else + +static void init_runtime(unsigned long pageable_part __unused) +{ + init_asan(); + + /* + * By default whole OP-TEE uses malloc, so we need to initialize + * it early. But, when virtualization is enabled, malloc is used + * only by TEE runtime, so malloc should be initialized later, for + * every virtual partition separately. Core code uses nex_malloc + * instead. + */ +#ifdef CFG_NS_VIRTUALIZATION + nex_malloc_add_pool(__nex_heap_start, __nex_heap_end - + __nex_heap_start); +#else + malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); +#endif + + IMSG_RAW("\n"); +} +#endif + +void *get_dt(void) +{ + void *fdt = get_embedded_dt(); + + if (!fdt) + fdt = get_external_dt(); + + return fdt; +} + +void *get_secure_dt(void) +{ + void *fdt = get_embedded_dt(); + + if (!fdt && IS_ENABLED(CFG_MAP_EXT_DT_SECURE)) + fdt = get_external_dt(); + + return fdt; +} + +#if defined(CFG_EMBED_DTB) +void *get_embedded_dt(void) +{ + static bool checked; + + assert(cpu_mmu_enabled()); + + if (!checked) { + IMSG("Embedded DTB found"); + + if (fdt_check_header(embedded_secure_dtb)) + panic("Invalid embedded DTB"); + + checked = true; + } + + return embedded_secure_dtb; +} +#else +void *get_embedded_dt(void) +{ + return NULL; +} +#endif /*CFG_EMBED_DTB*/ + +#if defined(CFG_DT) +void *get_external_dt(void) +{ + if (!IS_ENABLED(CFG_EXTERNAL_DT)) + return NULL; + + assert(cpu_mmu_enabled()); + return external_dt.blob; +} + +static TEE_Result release_external_dt(void) +{ + int ret = 0; + + if (!IS_ENABLED(CFG_EXTERNAL_DT)) + return TEE_SUCCESS; + + if (!external_dt.blob) + return TEE_SUCCESS; + + ret = fdt_pack(external_dt.blob); + if (ret < 0) { + EMSG("Failed to pack Device Tree at 0x%" PRIxPA ": error %d", + virt_to_phys(external_dt.blob), ret); + panic(); + } + + if (core_mmu_remove_mapping(MEM_AREA_EXT_DT, external_dt.blob, + CFG_DTB_MAX_SIZE)) + panic("Failed to remove temporary Device Tree mapping"); + + /* External DTB no more reached, reset pointer to invalid */ + external_dt.blob = NULL; + + return TEE_SUCCESS; +} +boot_final(release_external_dt); + +#ifdef _CFG_USE_DTB_OVERLAY +static int add_dt_overlay_fragment(struct dt_descriptor *dt, int ioffs) +{ + char frag[32]; + int offs; + int ret; + + snprintf(frag, sizeof(frag), "fragment@%d", dt->frag_id); + offs = fdt_add_subnode(dt->blob, ioffs, frag); + if (offs < 0) + return offs; + + dt->frag_id += 1; + + ret = fdt_setprop_string(dt->blob, offs, "target-path", "/"); + if (ret < 0) + return -1; + + return fdt_add_subnode(dt->blob, offs, "__overlay__"); +} + +static int init_dt_overlay(struct dt_descriptor *dt, int __maybe_unused dt_size) +{ + int fragment; + + if (IS_ENABLED(CFG_EXTERNAL_DTB_OVERLAY)) { + if (!fdt_check_header(dt->blob)) { + fdt_for_each_subnode(fragment, dt->blob, 0) + dt->frag_id += 1; + return 0; + } + } + + return fdt_create_empty_tree(dt->blob, dt_size); +} +#else +static int add_dt_overlay_fragment(struct dt_descriptor *dt __unused, int offs) +{ + return offs; +} + +static int init_dt_overlay(struct dt_descriptor *dt __unused, + int dt_size __unused) +{ + return 0; +} +#endif /* _CFG_USE_DTB_OVERLAY */ + +static int add_dt_path_subnode(struct dt_descriptor *dt, const char *path, + const char *subnode) +{ + int offs; + + offs = fdt_path_offset(dt->blob, path); + if (offs < 0) + return -1; + offs = add_dt_overlay_fragment(dt, offs); + if (offs < 0) + return -1; + offs = fdt_add_subnode(dt->blob, offs, subnode); + if (offs < 0) + return -1; + return offs; +} + +static int add_optee_dt_node(struct dt_descriptor *dt) +{ + int offs; + int ret; + + if (fdt_path_offset(dt->blob, "/firmware/optee") >= 0) { + DMSG("OP-TEE Device Tree node already exists!"); + return 0; + } + + offs = fdt_path_offset(dt->blob, "/firmware"); + if (offs < 0) { + offs = add_dt_path_subnode(dt, "/", "firmware"); + if (offs < 0) + return -1; + } + + offs = fdt_add_subnode(dt->blob, offs, "optee"); + if (offs < 0) + return -1; + + ret = fdt_setprop_string(dt->blob, offs, "compatible", + "linaro,optee-tz"); + if (ret < 0) + return -1; + ret = fdt_setprop_string(dt->blob, offs, "method", "smc"); + if (ret < 0) + return -1; + + if (CFG_CORE_ASYNC_NOTIF_GIC_INTID) { + /* + * The format of the interrupt property is defined by the + * binding of the interrupt domain root. In this case it's + * one Arm GIC v1, v2 or v3 so we must be compatible with + * these. + * + * An SPI type of interrupt is indicated with a 0 in the + * first cell. A PPI type is indicated with value 1. + * + * The interrupt number goes in the second cell where + * SPIs ranges from 0 to 987 and PPI ranges from 0 to 15. + * + * Flags are passed in the third cells. + */ + uint32_t itr_trigger = 0; + uint32_t itr_type = 0; + uint32_t itr_id = 0; + uint32_t val[3] = { }; + + /* PPI are visible only in current CPU cluster */ + static_assert(!CFG_CORE_ASYNC_NOTIF_GIC_INTID || + (CFG_CORE_ASYNC_NOTIF_GIC_INTID >= + GIC_SPI_BASE) || + ((CFG_TEE_CORE_NB_CORE <= 8) && + (CFG_CORE_ASYNC_NOTIF_GIC_INTID >= + GIC_PPI_BASE))); + + if (CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_SPI_BASE) { + itr_type = GIC_SPI; + itr_id = CFG_CORE_ASYNC_NOTIF_GIC_INTID - GIC_SPI_BASE; + itr_trigger = IRQ_TYPE_EDGE_RISING; + } else { + itr_type = GIC_PPI; + itr_id = CFG_CORE_ASYNC_NOTIF_GIC_INTID - GIC_PPI_BASE; + itr_trigger = IRQ_TYPE_EDGE_RISING | + GIC_CPU_MASK_SIMPLE(CFG_TEE_CORE_NB_CORE); + } + + val[0] = TEE_U32_TO_BIG_ENDIAN(itr_type); + val[1] = TEE_U32_TO_BIG_ENDIAN(itr_id); + val[2] = TEE_U32_TO_BIG_ENDIAN(itr_trigger); + + ret = fdt_setprop(dt->blob, offs, "interrupts", val, + sizeof(val)); + if (ret < 0) + return -1; + } + return 0; +} + +#ifdef CFG_PSCI_ARM32 +static int append_psci_compatible(void *fdt, int offs, const char *str) +{ + return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1); +} + +static int dt_add_psci_node(struct dt_descriptor *dt) +{ + int offs; + + if (fdt_path_offset(dt->blob, "/psci") >= 0) { + DMSG("PSCI Device Tree node already exists!"); + return 0; + } + + offs = add_dt_path_subnode(dt, "/", "psci"); + if (offs < 0) + return -1; + if (append_psci_compatible(dt->blob, offs, "arm,psci-1.0")) + return -1; + if (append_psci_compatible(dt->blob, offs, "arm,psci-0.2")) + return -1; + if (append_psci_compatible(dt->blob, offs, "arm,psci")) + return -1; + if (fdt_setprop_string(dt->blob, offs, "method", "smc")) + return -1; + if (fdt_setprop_u32(dt->blob, offs, "cpu_suspend", PSCI_CPU_SUSPEND)) + return -1; + if (fdt_setprop_u32(dt->blob, offs, "cpu_off", PSCI_CPU_OFF)) + return -1; + if (fdt_setprop_u32(dt->blob, offs, "cpu_on", PSCI_CPU_ON)) + return -1; + if (fdt_setprop_u32(dt->blob, offs, "sys_poweroff", PSCI_SYSTEM_OFF)) + return -1; + if (fdt_setprop_u32(dt->blob, offs, "sys_reset", PSCI_SYSTEM_RESET)) + return -1; + return 0; +} + +static int check_node_compat_prefix(struct dt_descriptor *dt, int offs, + const char *prefix) +{ + const size_t prefix_len = strlen(prefix); + size_t l; + int plen; + const char *prop; + + prop = fdt_getprop(dt->blob, offs, "compatible", &plen); + if (!prop) + return -1; + + while (plen > 0) { + if (memcmp(prop, prefix, prefix_len) == 0) + return 0; /* match */ + + l = strlen(prop) + 1; + prop += l; + plen -= l; + } + + return -1; +} + +static int dt_add_psci_cpu_enable_methods(struct dt_descriptor *dt) +{ + int offs = 0; + + while (1) { + offs = fdt_next_node(dt->blob, offs, NULL); + if (offs < 0) + break; + if (fdt_getprop(dt->blob, offs, "enable-method", NULL)) + continue; /* already set */ + if (check_node_compat_prefix(dt, offs, "arm,cortex-a")) + continue; /* no compatible */ + if (fdt_setprop_string(dt->blob, offs, "enable-method", "psci")) + return -1; + /* Need to restart scanning as offsets may have changed */ + offs = 0; + } + return 0; +} + +static int config_psci(struct dt_descriptor *dt) +{ + if (dt_add_psci_node(dt)) + return -1; + return dt_add_psci_cpu_enable_methods(dt); +} +#else +static int config_psci(struct dt_descriptor *dt __unused) +{ + return 0; +} +#endif /*CFG_PSCI_ARM32*/ + +static void set_dt_val(void *data, uint32_t cell_size, uint64_t val) +{ + if (cell_size == 1) { + fdt32_t v = cpu_to_fdt32((uint32_t)val); + + memcpy(data, &v, sizeof(v)); + } else { + fdt64_t v = cpu_to_fdt64(val); + + memcpy(data, &v, sizeof(v)); + } +} + +static int add_res_mem_dt_node(struct dt_descriptor *dt, const char *name, + paddr_t pa, size_t size) +{ + int offs = 0; + int ret = 0; + int addr_size = -1; + int len_size = -1; + bool found = true; + char subnode_name[80] = { 0 }; + + offs = fdt_path_offset(dt->blob, "/reserved-memory"); + + if (offs < 0) { + found = false; + offs = 0; + } + + if (IS_ENABLED2(_CFG_USE_DTB_OVERLAY)) { + len_size = sizeof(paddr_t) / sizeof(uint32_t); + addr_size = sizeof(paddr_t) / sizeof(uint32_t); + } else { + len_size = fdt_size_cells(dt->blob, offs); + if (len_size < 0) + return -1; + addr_size = fdt_address_cells(dt->blob, offs); + if (addr_size < 0) + return -1; + } + + if (!found) { + offs = add_dt_path_subnode(dt, "/", "reserved-memory"); + if (offs < 0) + return -1; + ret = fdt_setprop_cell(dt->blob, offs, "#address-cells", + addr_size); + if (ret < 0) + return -1; + ret = fdt_setprop_cell(dt->blob, offs, "#size-cells", len_size); + if (ret < 0) + return -1; + ret = fdt_setprop(dt->blob, offs, "ranges", NULL, 0); + if (ret < 0) + return -1; + } + + ret = snprintf(subnode_name, sizeof(subnode_name), + "%s@%" PRIxPA, name, pa); + if (ret < 0 || ret >= (int)sizeof(subnode_name)) + DMSG("truncated node \"%s@%" PRIxPA"\"", name, pa); + offs = fdt_add_subnode(dt->blob, offs, subnode_name); + if (offs >= 0) { + uint32_t data[FDT_MAX_NCELLS * 2]; + + set_dt_val(data, addr_size, pa); + set_dt_val(data + addr_size, len_size, size); + ret = fdt_setprop(dt->blob, offs, "reg", data, + sizeof(uint32_t) * (addr_size + len_size)); + if (ret < 0) + return -1; + ret = fdt_setprop(dt->blob, offs, "no-map", NULL, 0); + if (ret < 0) + return -1; + } else { + return -1; + } + return 0; +} + +#ifdef CFG_CORE_DYN_SHM +static uint64_t get_dt_val_and_advance(const void *data, size_t *offs, + uint32_t cell_size) +{ + uint64_t rv = 0; + + if (cell_size == 1) { + uint32_t v; + + memcpy(&v, (const uint8_t *)data + *offs, sizeof(v)); + *offs += sizeof(v); + rv = fdt32_to_cpu(v); + } else { + uint64_t v; + + memcpy(&v, (const uint8_t *)data + *offs, sizeof(v)); + *offs += sizeof(v); + rv = fdt64_to_cpu(v); + } + + return rv; +} + +/* + * Find all non-secure memory from DT. Memory marked inaccessible by Secure + * World is ignored since it could not be mapped to be used as dynamic shared + * memory. + */ +static int get_nsec_memory_helper(void *fdt, struct core_mmu_phys_mem *mem) +{ + const uint8_t *prop = NULL; + uint64_t a = 0; + uint64_t l = 0; + size_t prop_offs = 0; + size_t prop_len = 0; + int elems_total = 0; + int addr_size = 0; + int len_size = 0; + int offs = 0; + size_t n = 0; + int len = 0; + + addr_size = fdt_address_cells(fdt, 0); + if (addr_size < 0) + return 0; + + len_size = fdt_size_cells(fdt, 0); + if (len_size < 0) + return 0; + + while (true) { + offs = fdt_node_offset_by_prop_value(fdt, offs, "device_type", + "memory", + sizeof("memory")); + if (offs < 0) + break; + + if (fdt_get_status(fdt, offs) != (DT_STATUS_OK_NSEC | + DT_STATUS_OK_SEC)) + continue; + + prop = fdt_getprop(fdt, offs, "reg", &len); + if (!prop) + continue; + + prop_len = len; + for (n = 0, prop_offs = 0; prop_offs < prop_len; n++) { + a = get_dt_val_and_advance(prop, &prop_offs, addr_size); + if (prop_offs >= prop_len) { + n--; + break; + } + + l = get_dt_val_and_advance(prop, &prop_offs, len_size); + if (mem) { + mem->type = MEM_AREA_DDR_OVERALL; + mem->addr = a; + mem->size = l; + mem++; + } + } + + elems_total += n; + } + + return elems_total; +} + +static struct core_mmu_phys_mem *get_nsec_memory(void *fdt, size_t *nelems) +{ + struct core_mmu_phys_mem *mem = NULL; + int elems_total = 0; + + elems_total = get_nsec_memory_helper(fdt, NULL); + if (elems_total <= 0) + return NULL; + + mem = nex_calloc(elems_total, sizeof(*mem)); + if (!mem) + panic(); + + elems_total = get_nsec_memory_helper(fdt, mem); + assert(elems_total > 0); + + *nelems = elems_total; + + return mem; +} +#endif /*CFG_CORE_DYN_SHM*/ + +#ifdef CFG_CORE_RESERVED_SHM +static int mark_static_shm_as_reserved(struct dt_descriptor *dt) +{ + vaddr_t shm_start; + vaddr_t shm_end; + + core_mmu_get_mem_by_type(MEM_AREA_NSEC_SHM, &shm_start, &shm_end); + if (shm_start != shm_end) + return add_res_mem_dt_node(dt, "optee_shm", + virt_to_phys((void *)shm_start), + shm_end - shm_start); + + DMSG("No SHM configured"); + return -1; +} +#endif /*CFG_CORE_RESERVED_SHM*/ + +static void init_external_dt(unsigned long phys_dt) +{ + struct dt_descriptor *dt = &external_dt; + void *fdt; + int ret; + + if (!IS_ENABLED(CFG_EXTERNAL_DT)) + return; + + if (!phys_dt) { + /* + * No need to panic as we're not using the DT in OP-TEE + * yet, we're only adding some nodes for normal world use. + * This makes the switch to using DT easier as we can boot + * a newer OP-TEE with older boot loaders. Once we start to + * initialize devices based on DT we'll likely panic + * instead of returning here. + */ + IMSG("No non-secure external DT"); + return; + } + + fdt = core_mmu_add_mapping(MEM_AREA_EXT_DT, phys_dt, CFG_DTB_MAX_SIZE); + if (!fdt) + panic("Failed to map external DTB"); + + dt->blob = fdt; + + ret = init_dt_overlay(dt, CFG_DTB_MAX_SIZE); + if (ret < 0) { + EMSG("Device Tree Overlay init fail @ %#lx: error %d", phys_dt, + ret); + panic(); + } + + ret = fdt_open_into(fdt, fdt, CFG_DTB_MAX_SIZE); + if (ret < 0) { + EMSG("Invalid Device Tree at %#lx: error %d", phys_dt, ret); + panic(); + } + + IMSG("Non-secure external DT found"); +} + +static int mark_tzdram_as_reserved(struct dt_descriptor *dt) +{ + return add_res_mem_dt_node(dt, "optee_core", CFG_TZDRAM_START, + CFG_TZDRAM_SIZE); +} + +static void update_external_dt(void) +{ + struct dt_descriptor *dt = &external_dt; + + if (!IS_ENABLED(CFG_EXTERNAL_DT)) + return; + + if (!dt->blob) + return; + + if (!IS_ENABLED(CFG_CORE_FFA) && add_optee_dt_node(dt)) + panic("Failed to add OP-TEE Device Tree node"); + + if (config_psci(dt)) + panic("Failed to config PSCI"); + +#ifdef CFG_CORE_RESERVED_SHM + if (mark_static_shm_as_reserved(dt)) + panic("Failed to config non-secure memory"); +#endif + + if (mark_tzdram_as_reserved(dt)) + panic("Failed to config secure memory"); +} +#else /*CFG_DT*/ +void *get_external_dt(void) +{ + return NULL; +} + +static void init_external_dt(unsigned long phys_dt __unused) +{ +} + +static void update_external_dt(void) +{ +} + +#ifdef CFG_CORE_DYN_SHM +static struct core_mmu_phys_mem *get_nsec_memory(void *fdt __unused, + size_t *nelems __unused) +{ + return NULL; +} +#endif /*CFG_CORE_DYN_SHM*/ +#endif /*!CFG_DT*/ + +#if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_DT) +void *get_tos_fw_config_dt(void) +{ + if (!IS_ENABLED(CFG_MAP_EXT_DT_SECURE)) + return NULL; + + assert(cpu_mmu_enabled()); + + return tos_fw_config_dt.blob; +} + +static void init_tos_fw_config_dt(unsigned long pa) +{ + struct dt_descriptor *dt = &tos_fw_config_dt; + void *fdt = NULL; + int ret = 0; + + if (!IS_ENABLED(CFG_MAP_EXT_DT_SECURE)) + return; + + if (!pa) + panic("No TOS_FW_CONFIG DT found"); + + fdt = core_mmu_add_mapping(MEM_AREA_EXT_DT, pa, CFG_DTB_MAX_SIZE); + if (!fdt) + panic("Failed to map TOS_FW_CONFIG DT"); + + dt->blob = fdt; + + ret = fdt_open_into(fdt, fdt, CFG_DTB_MAX_SIZE); + if (ret < 0) { + EMSG("Invalid Device Tree at %#lx: error %d", pa, ret); + panic(); + } + + IMSG("TOS_FW_CONFIG DT found"); +} +#else +void *get_tos_fw_config_dt(void) +{ + return NULL; +} + +static void init_tos_fw_config_dt(unsigned long pa __unused) +{ +} +#endif /*CFG_CORE_SEL1_SPMC && CFG_DT*/ + +#ifdef CFG_CORE_DYN_SHM +static void discover_nsec_memory(void) +{ + struct core_mmu_phys_mem *mem; + const struct core_mmu_phys_mem *mem_begin = NULL; + const struct core_mmu_phys_mem *mem_end = NULL; + size_t nelems; + void *fdt = get_external_dt(); + + if (fdt) { + mem = get_nsec_memory(fdt, &nelems); + if (mem) { + core_mmu_set_discovered_nsec_ddr(mem, nelems); + return; + } + + DMSG("No non-secure memory found in FDT"); + } + + mem_begin = phys_ddr_overall_begin; + mem_end = phys_ddr_overall_end; + nelems = mem_end - mem_begin; + if (nelems) { + /* + * Platform cannot use both register_ddr() and the now + * deprecated register_dynamic_shm(). + */ + assert(phys_ddr_overall_compat_begin == + phys_ddr_overall_compat_end); + } else { + mem_begin = phys_ddr_overall_compat_begin; + mem_end = phys_ddr_overall_compat_end; + nelems = mem_end - mem_begin; + if (!nelems) + return; + DMSG("Warning register_dynamic_shm() is deprecated, please use register_ddr() instead"); + } + + mem = nex_calloc(nelems, sizeof(*mem)); + if (!mem) + panic(); + + memcpy(mem, phys_ddr_overall_begin, sizeof(*mem) * nelems); + core_mmu_set_discovered_nsec_ddr(mem, nelems); +} +#else /*CFG_CORE_DYN_SHM*/ +static void discover_nsec_memory(void) +{ +} +#endif /*!CFG_CORE_DYN_SHM*/ + +#ifdef CFG_NS_VIRTUALIZATION +static TEE_Result virt_init_heap(void) +{ + /* We need to initialize pool for every virtual guest partition */ + malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); + + return TEE_SUCCESS; +} +preinit_early(virt_init_heap); +#endif + +void init_tee_runtime(void) +{ +#ifndef CFG_WITH_PAGER + /* Pager initializes TA RAM early */ + core_mmu_init_ta_ram(); +#endif + /* + * With virtualization we call this function when creating the + * OP-TEE partition instead. + */ + if (!IS_ENABLED(CFG_NS_VIRTUALIZATION)) + call_preinitcalls(); + call_initcalls(); + + /* + * These two functions uses crypto_rng_read() to initialize the + * pauth keys. Once call_initcalls() returns we're guaranteed that + * crypto_rng_read() is ready to be used. + */ + thread_init_core_local_pauth_keys(); + thread_init_thread_pauth_keys(); +} + +static void init_primary(unsigned long pageable_part, unsigned long nsec_entry) +{ + thread_init_core_local_stacks(); + /* + * Mask asynchronous exceptions before switch to the thread vector + * as the thread handler requires those to be masked while + * executing with the temporary stack. The thread subsystem also + * asserts that the foreign interrupts are blocked when using most of + * its functions. + */ + thread_set_exceptions(THREAD_EXCP_ALL); + primary_save_cntfrq(); + init_vfp_sec(); + /* + * Pager: init_runtime() calls thread_kernel_enable_vfp() so we must + * set a current thread right now to avoid a chicken-and-egg problem + * (thread_init_boot_thread() sets the current thread but needs + * things set by init_runtime()). + */ + thread_get_core_local()->curr_thread = 0; + init_runtime(pageable_part); + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + /* + * Virtualization: We can't initialize threads right now because + * threads belong to "tee" part and will be initialized + * separately per each new virtual guest. So, we'll clear + * "curr_thread" and call it done. + */ + thread_get_core_local()->curr_thread = -1; + } else { + thread_init_boot_thread(); + } + thread_init_primary(); + thread_init_per_cpu(); + init_sec_mon(nsec_entry); +} + +static bool cpu_nmfi_enabled(void) +{ +#if defined(ARM32) + return read_sctlr() & SCTLR_NMFI; +#else + /* Note: ARM64 does not feature non-maskable FIQ support. */ + return false; +#endif +} + +/* + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area. + */ +void __weak boot_init_primary_late(unsigned long fdt, + unsigned long tos_fw_config) +{ + init_external_dt(fdt); + init_tos_fw_config_dt(tos_fw_config); +#ifdef CFG_CORE_SEL1_SPMC + tpm_map_log_area(get_tos_fw_config_dt()); +#else + tpm_map_log_area(get_external_dt()); +#endif + discover_nsec_memory(); + update_external_dt(); + configure_console_from_dt(); + + IMSG("OP-TEE version: %s", core_v_str); + if (IS_ENABLED(CFG_WARN_INSECURE)) { + IMSG("WARNING: This OP-TEE configuration might be insecure!"); + IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html"); + } + IMSG("Primary CPU initializing"); +#ifdef CFG_CORE_ASLR + DMSG("Executing at offset %#lx with virtual load address %#"PRIxVA, + (unsigned long)boot_mmu_config.map_offset, VCORE_START_VA); +#endif + if (IS_ENABLED(CFG_MEMTAG)) + DMSG("Memory tagging %s", + memtag_is_enabled() ? "enabled" : "disabled"); + + /* Check if platform needs NMFI workaround */ + if (cpu_nmfi_enabled()) { + if (!IS_ENABLED(CFG_CORE_WORKAROUND_ARM_NMFI)) + IMSG("WARNING: This ARM core has NMFI enabled, please apply workaround!"); + } else { + if (IS_ENABLED(CFG_CORE_WORKAROUND_ARM_NMFI)) + IMSG("WARNING: This ARM core does not have NMFI enabled, no need for workaround"); + } + + main_init_gic(); + init_vfp_nsec(); + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + IMSG("Initializing virtualization support"); + core_mmu_init_virtualization(); + } else { + init_tee_runtime(); + } + call_finalcalls(); + IMSG("Primary CPU switching to normal world boot"); +} + +static void init_secondary_helper(unsigned long nsec_entry) +{ + IMSG("Secondary CPU %zu initializing", get_core_pos()); + + /* + * Mask asynchronous exceptions before switch to the thread vector + * as the thread handler requires those to be masked while + * executing with the temporary stack. The thread subsystem also + * asserts that the foreign interrupts are blocked when using most of + * its functions. + */ + thread_set_exceptions(THREAD_EXCP_ALL); + + secondary_init_cntfrq(); + thread_init_per_cpu(); + init_sec_mon(nsec_entry); + main_secondary_init_gic(); + init_vfp_sec(); + init_vfp_nsec(); + + IMSG("Secondary CPU %zu switching to normal world boot", get_core_pos()); +} + +/* + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area so that it lies in the init area. + */ +void __weak boot_init_primary_early(unsigned long pageable_part, + unsigned long nsec_entry __maybe_unused) +{ + unsigned long e = PADDR_INVALID; + +#if !defined(CFG_WITH_ARM_TRUSTED_FW) + e = nsec_entry; +#endif + + init_primary(pageable_part, e); +} + +#if defined(CFG_WITH_ARM_TRUSTED_FW) +unsigned long boot_cpu_on_handler(unsigned long a0 __maybe_unused, + unsigned long a1 __unused) +{ + init_secondary_helper(PADDR_INVALID); + return 0; +} +#else +void boot_init_secondary(unsigned long nsec_entry) +{ + init_secondary_helper(nsec_entry); +} +#endif + +#if defined(CFG_BOOT_SECONDARY_REQUEST) +void boot_set_core_ns_entry(size_t core_idx, uintptr_t entry, + uintptr_t context_id) +{ + ns_entry_contexts[core_idx].entry_point = entry; + ns_entry_contexts[core_idx].context_id = context_id; + dsb_ishst(); +} + +int boot_core_release(size_t core_idx, paddr_t entry) +{ + if (!core_idx || core_idx >= CFG_TEE_CORE_NB_CORE) + return -1; + + ns_entry_contexts[core_idx].entry_point = entry; + dmb(); + spin_table[core_idx] = 1; + dsb(); + sev(); + + return 0; +} + +/* + * spin until secondary boot request, then returns with + * the secondary core entry address. + */ +struct ns_entry_context *boot_core_hpen(void) +{ +#ifdef CFG_PSCI_ARM32 + return &ns_entry_contexts[get_core_pos()]; +#else + do { + wfe(); + } while (!spin_table[get_core_pos()]); + dmb(); + return &ns_entry_contexts[get_core_pos()]; +#endif +} +#endif + +#if defined(CFG_CORE_ASLR) +#if defined(CFG_DT) +unsigned long __weak get_aslr_seed(void *fdt) +{ + int rc = 0; + const uint64_t *seed = NULL; + int offs = 0; + int len = 0; + + if (!fdt) { + DMSG("No fdt"); + goto err; + } + + rc = fdt_check_header(fdt); + if (rc) { + DMSG("Bad fdt: %d", rc); + goto err; + } + + offs = fdt_path_offset(fdt, "/secure-chosen"); + if (offs < 0) { + DMSG("Cannot find /secure-chosen"); + goto err; + } + seed = fdt_getprop(fdt, offs, "kaslr-seed", &len); + if (!seed || len != sizeof(*seed)) { + DMSG("Cannot find valid kaslr-seed"); + goto err; + } + + return fdt64_to_cpu(*seed); + +err: + /* Try platform implementation */ + return plat_get_aslr_seed(); +} +#else /*!CFG_DT*/ +unsigned long __weak get_aslr_seed(void *fdt __unused) +{ + /* Try platform implementation */ + return plat_get_aslr_seed(); +} +#endif /*!CFG_DT*/ +#endif /*CFG_CORE_ASLR*/ + +#if defined(CFG_CORE_SEL2_SPMC) && defined(CFG_CORE_PHYS_RELOCATABLE) +static void *get_fdt_from_boot_info(struct ffa_boot_info_header *hdr) +{ + struct ffa_boot_info *desc = NULL; + uint8_t content_fmt = 0; + uint8_t name_fmt = 0; + void *fdt = NULL; + int ret = 0; + + if (hdr->signature != FFA_BOOT_INFO_SIGNATURE) { + EMSG("Bad boot info signature %#"PRIx32, hdr->signature); + panic(); + } + if (hdr->version != FFA_BOOT_INFO_VERSION) { + EMSG("Bad boot info version %#"PRIx32, hdr->version); + panic(); + } + if (hdr->desc_count != 1) { + EMSG("Bad boot info descriptor count %#"PRIx32, + hdr->desc_count); + panic(); + } + desc = (void *)((vaddr_t)hdr + hdr->desc_offset); + name_fmt = desc->flags & FFA_BOOT_INFO_FLAG_NAME_FORMAT_MASK; + if (name_fmt == FFA_BOOT_INFO_FLAG_NAME_FORMAT_STRING) + DMSG("Boot info descriptor name \"%16s\"", desc->name); + else if (name_fmt == FFA_BOOT_INFO_FLAG_NAME_FORMAT_UUID) + DMSG("Boot info descriptor UUID %pUl", (void *)desc->name); + else + DMSG("Boot info descriptor: unknown name format %"PRIu8, + name_fmt); + + content_fmt = (desc->flags & FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_MASK) >> + FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_SHIFT; + if (content_fmt != FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR) { + EMSG("Bad boot info content format %"PRIu8", expected %u (address)", + content_fmt, FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR); + panic(); + } + + fdt = (void *)(vaddr_t)desc->contents; + ret = fdt_check_full(fdt, desc->size); + if (ret < 0) { + EMSG("Invalid Device Tree at %p: error %d", fdt, ret); + panic(); + } + return fdt; +} + +static void get_sec_mem_from_manifest(void *fdt, paddr_t *base, size_t *size) +{ + int ret = 0; + uint64_t num = 0; + + ret = fdt_node_check_compatible(fdt, 0, "arm,ffa-manifest-1.0"); + if (ret < 0) { + EMSG("Invalid FF-A manifest at %p: error %d", fdt, ret); + panic(); + } + ret = dt_getprop_as_number(fdt, 0, "load-address", &num); + if (ret < 0) { + EMSG("Can't read \"load-address\" from FF-A manifest at %p: error %d", + fdt, ret); + panic(); + } + *base = num; + /* "mem-size" is currently an undocumented extension to the spec. */ + ret = dt_getprop_as_number(fdt, 0, "mem-size", &num); + if (ret < 0) { + EMSG("Can't read \"mem-size\" from FF-A manifest at %p: error %d", + fdt, ret); + panic(); + } + *size = num; +} + +void __weak boot_save_boot_info(void *boot_info) +{ + void *fdt = NULL; + paddr_t base = 0; + size_t size = 0; + + fdt = get_fdt_from_boot_info(boot_info); + get_sec_mem_from_manifest(fdt, &base, &size); + core_mmu_set_secure_memory(base, size); +} +#endif /*CFG_CORE_SEL2_SPMC && CFG_CORE_PHYS_RELOCATABLE*/ + +#if ! defined(CFG_CORE_SEL2_SPMC) && defined(CFG_CORE_PHYS_RELOCATABLE) +void __weak boot_set_fixed_secmem_range(paddr_t base) +{ + core_mmu_set_secure_memory(base, CFG_TZDRAM_SIZE); +} +#endif diff --git a/optee/optee_os/core/arch/arm/kernel/cache_helpers_a32.S b/optee/optee_os/core/arch/arm/kernel/cache_helpers_a32.S new file mode 100644 index 0000000..50180dc --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/cache_helpers_a32.S @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2017, Linaro Limited. All rights reserved. + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/* + * Cache line size helpers + */ +.macro dcache_line_size reg, tmp + read_ctr \tmp + ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH + mov \reg, #CTR_WORD_SIZE + lsl \reg, \reg, \tmp +.endm + +.macro icache_line_size reg, tmp + read_ctr \tmp + and \tmp, \tmp, #CTR_IMINLINE_MASK + mov \reg, #CTR_WORD_SIZE + lsl \reg, \reg, \tmp +.endm + +/* + * This macro can be used for implementing various data cache operations `op` + */ +.macro do_dcache_maintenance_by_mva reg + dcache_line_size r2, r3 + add r1, r0, r1 + sub r3, r2, #1 + bic r0, r0, r3 +loop_\reg: + write_\reg r0 + add r0, r0, r2 + cmp r0, r1 + blo loop_\reg + dsb sy + bx lr +.endm + + /* ------------------------------------------ + * Clean+Invalidate from base address till + * size. 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +FUNC dcache_cleaninv_range , : + do_dcache_maintenance_by_mva dccimvac +END_FUNC dcache_cleaninv_range + + /* ------------------------------------------ + * Clean from base address till size. + * 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +FUNC dcache_clean_range , : + do_dcache_maintenance_by_mva dccmvac +END_FUNC dcache_clean_range + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +FUNC dcache_inv_range , : + do_dcache_maintenance_by_mva dcimvac +END_FUNC dcache_inv_range + + + /* ------------------------------------------ + * Clean from base address till size to point of unification + * 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +FUNC dcache_clean_range_pou , : + do_dcache_maintenance_by_mva dccmvau +END_FUNC dcache_clean_range_pou + + /* ---------------------------------------------------------------- + * Data cache operations by set/way to the level specified + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, + * DCACHE_OP_CLEAN), as defined in cache_helpers.h + * r1: The cache level to begin operation from + * r2: clidr_el1 + * r3: The last cache level to operate on + * and will carry out the operation on each data cache from level 0 + * to the level in r3 in sequence + * + * The dcsw_op macro sets up the r2 and r3 parameters based on + * clidr_el1 cache information before invoking the main function + * ---------------------------------------------------------------- + */ + + .macro dcsw_op shift, fw, ls + read_clidr r2 + ubfx r3, r2, \shift, \fw + lsl r3, r3, \ls + mov r1, #0 + b do_dcsw_op + .endm + +LOCAL_FUNC do_dcsw_op , : + push {r4-r12,lr} + adr r11, dcsw_loop_table // compute cache op based on the operation type + add r6, r11, r0, lsl #3 // cache op is 2x32-bit instructions +loop1: + add r10, r1, r1, LSR #1 // Work out 3x current cache level + mov r12, r2, LSR r10 // extract cache type bits from clidr + and r12, r12, #7 // mask the bits for current cache only + cmp r12, #2 // see what cache we have at this level + blo level_done // no cache or only instruction cache at this level + + write_csselr r1 // select current cache level in csselr + isb // isb to sych the new cssr&csidr + read_ccsidr r12 // read the new ccsidr + and r10, r12, #7 // extract the length of the cache lines + add r10, r10, #4 // add 4 (r10 = line length offset) + ubfx r4, r12, #3, #10 // r4 = maximum way number (right aligned) + clz r5, r4 // r5 = the bit position of the way size increment + mov r9, r4 // r9 working copy of the aligned max way number + +loop2: + ubfx r7, r12, #13, #15 // r7 = max set number (right aligned) + +loop3: + orr r0, r1, r9, LSL r5 // factor in the way number and cache level into r0 + orr r0, r0, r7, LSL r10 // factor in the set number + + blx r6 + subs r7, r7, #1 // decrement the set number + bhs loop3 + subs r9, r9, #1 // decrement the way number + bhs loop2 +level_done: + add r1, r1, #2 // increment the cache number + cmp r3, r1 + dsb sy // ensure completion of previous cache maintenance instruction + bhi loop1 + + mov r6, #0 + write_csselr r6 //select cache level 0 in csselr + dsb sy + isb + pop {r4-r12,pc} + +dcsw_loop_table: + write_dcisw r0 + bx lr + write_dccisw r0 + bx lr + write_dccsw r0 + bx lr +END_FUNC do_dcsw_op + + /* --------------------------------------------------------------- + * Data cache operations by set/way till PoU. + * + * The function requires : + * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, + * DCACHE_OP_CLEAN), as defined in cache_helpers.h + * --------------------------------------------------------------- + */ +FUNC dcache_op_louis , : + dcsw_op #CLIDR_LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #CSSELR_LEVEL_SHIFT +END_FUNC dcache_op_louis + + /* --------------------------------------------------------------- + * Data cache operations by set/way till PoC. + * + * The function requires : + * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, + * DCACHE_OP_CLEAN), as defined in cache_helpers.h + * --------------------------------------------------------------- + */ +FUNC dcache_op_all , : + dcsw_op #CLIDR_LOC_SHIFT, #CLIDR_FIELD_WIDTH, #CSSELR_LEVEL_SHIFT +END_FUNC dcache_op_all + + + /* --------------------------------------------------------------- + * Helper macro for data cache operations by set/way for the + * level specified + * --------------------------------------------------------------- + */ + .macro dcsw_op_level level + read_clidr r2 + mov r3, \level + sub r1, r3, #2 + b do_dcsw_op + .endm + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 1 cache + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, + * DCACHE_OP_CLEAN), as defined in cache_helpers.h + * --------------------------------------------------------------- + */ +FUNC dcache_op_level1 , : + dcsw_op_level #(1 << CSSELR_LEVEL_SHIFT) +END_FUNC dcache_op_level1 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 2 cache + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, + * DCACHE_OP_CLEAN), as defined in cache_helpers.h + * --------------------------------------------------------------- + */ +FUNC dcache_op_level2 , : + dcsw_op_level #(2 << CSSELR_LEVEL_SHIFT) +END_FUNC dcache_op_level2 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 3 cache + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, + * DCACHE_OP_CLEAN), as defined in cache_helpers.h + * --------------------------------------------------------------- + */ +FUNC dcache_op_level3 , : + dcsw_op_level #(3 << CSSELR_LEVEL_SHIFT) +END_FUNC dcache_op_level3 + +FUNC icache_inv_all , : + /* Invalidate Entire Instruction Cache (and branch predictors) */ + write_icialluis + + dsb ishst /* ensure that maintenance operations are seen */ + isb /* by the instructions rigth after the isb */ + + bx lr +END_FUNC icache_inv_all + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +FUNC icache_inv_range , : + icache_line_size r2, r3 + add r1, r0, r1 + sub r3, r2, #1 + bic r0, r0, r3 +loop_ic_inv: + write_icimvau r0 + add r0, r0, r2 + cmp r0, r1 + blo loop_ic_inv + + /* Invalidate entire branch predictor array inner shareable */ + write_bpiallis + + dsb ishst + isb + + bx lr +END_FUNC icache_inv_range diff --git a/optee/optee_os/core/arch/arm/kernel/cache_helpers_a64.S b/optee/optee_os/core/arch/arm/kernel/cache_helpers_a64.S new file mode 100644 index 0000000..ee5a429 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/cache_helpers_a64.S @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2017, Linaro Limited. All rights reserved. + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +.macro dcache_line_size reg, tmp + mrs \tmp, ctr_el0 + ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH + mov \reg, #CTR_WORD_SIZE + lsl \reg, \reg, \tmp +.endm + +.macro icache_line_size reg, tmp + mrs \tmp, ctr_el0 + and \tmp, \tmp, #CTR_IMINLINE_MASK + mov \reg, #CTR_WORD_SIZE + lsl \reg, \reg, \tmp +.endm + +/* + * This macro can be used for implementing various data cache operations `op` + */ +.macro do_dcache_maintenance_by_mva op + dcache_line_size x2, x3 + add x1, x0, x1 + sub x3, x2, #1 + bic x0, x0, x3 +loop_\op: + dc \op, x0 + add x0, x0, x2 + cmp x0, x1 + b.lo loop_\op + dsb sy + ret +.endm + /* ------------------------------------------ + * Clean+Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +FUNC dcache_cleaninv_range , : + do_dcache_maintenance_by_mva civac +END_FUNC dcache_cleaninv_range + + /* ------------------------------------------ + * Clean from base address till size. + * 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +FUNC dcache_clean_range , : + do_dcache_maintenance_by_mva cvac +END_FUNC dcache_clean_range + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +FUNC dcache_inv_range , : + do_dcache_maintenance_by_mva ivac +END_FUNC dcache_inv_range + + /* ------------------------------------------ + * Clean from base address till size to point of unification + * 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +FUNC dcache_clean_range_pou , : + do_dcache_maintenance_by_mva cvau +END_FUNC dcache_clean_range_pou + + /* --------------------------------------------------------------- + * Data cache operations by set/way to the level specified + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in cache_helpers.h + * x3: The last cache level to operate on + * x9: clidr_el1 + * x10: The cache level to begin operation from + * and will carry out the operation on each data cache from level 0 + * to the level in x3 in sequence + * + * The dcsw_op macro sets up the x3 and x9 parameters based on + * clidr_el1 cache information before invoking the main function + * --------------------------------------------------------------- + */ + + .macro dcsw_op shift, fw, ls + mrs x9, clidr_el1 + ubfx x3, x9, \shift, \fw + lsl x3, x3, \ls + mov x10, xzr + b do_dcsw_op + .endm + +LOCAL_FUNC do_dcsw_op , : + cbz x3, exit + adr x14, dcsw_loop_table // compute inner loop address + add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions +BTI( add x14, x14, x0, lsl #2) // inner loop is + "bti j" instruction + mov x0, x9 + mov w8, #1 +loop1: + add x2, x10, x10, lsr #1 // work out 3x current cache level + lsr x1, x0, x2 // extract cache type bits from clidr + and x1, x1, #7 // mask the bits for current cache only + cmp x1, #2 // see what cache we have at this level + b.lo level_done // nothing to do if no cache or icache + + msr csselr_el1, x10 // select current cache level in csselr + isb // isb to sych the new cssr&csidr + mrs x1, ccsidr_el1 // read the new ccsidr + and x2, x1, #7 // extract the length of the cache lines + add x2, x2, #4 // add 4 (line length offset) + ubfx x4, x1, #3, #10 // maximum way number + clz w5, w4 // bit position of way size increment + lsl w9, w4, w5 // w9 = aligned max way number + lsl w16, w8, w5 // w16 = way number loop decrement + orr w9, w10, w9 // w9 = combine way and cache number + ubfx w6, w1, #13, #15 // w6 = max set number + lsl w17, w8, w2 // w17 = set number loop decrement + dsb sy // barrier before we start this level + br x14 // jump to DC operation specific loop + + .macro dcsw_loop _op +BTI( bti j) +loop2_\_op: + lsl w7, w6, w2 // w7 = aligned max set number + +loop3_\_op: + orr w11, w9, w7 // combine cache, way and set number + dc \_op, x11 + subs w7, w7, w17 // decrement set number + b.hs loop3_\_op + + subs x9, x9, x16 // decrement way number + b.hs loop2_\_op + + b level_done + .endm + +level_done: + add x10, x10, #2 // increment cache number + cmp x3, x10 + b.hi loop1 + msr csselr_el1, xzr // select cache level 0 in csselr + dsb sy // barrier to complete final cache operation + isb +exit: + ret + +dcsw_loop_table: + dcsw_loop isw + dcsw_loop cisw + dcsw_loop csw +END_FUNC do_dcsw_op + +FUNC dcache_op_louis , : + dcsw_op #CLIDR_LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #CSSELR_LEVEL_SHIFT +END_FUNC dcache_op_louis + +FUNC dcache_op_all , : + dcsw_op #CLIDR_LOC_SHIFT, #CLIDR_FIELD_WIDTH, #CSSELR_LEVEL_SHIFT +END_FUNC dcache_op_all + + /* --------------------------------------------------------------- + * Helper macro for data cache operations by set/way for the + * level specified + * --------------------------------------------------------------- + */ + .macro dcsw_op_level level + mrs x9, clidr_el1 + mov x3, \level + sub x10, x3, #2 + b do_dcsw_op + .endm + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 1 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in cache_helpers.h + * --------------------------------------------------------------- + */ +FUNC dcache_op_level1 , : + dcsw_op_level #(1 << CSSELR_LEVEL_SHIFT) +END_FUNC dcache_op_level1 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 2 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in cache_helpers.h + * --------------------------------------------------------------- + */ +FUNC dcache_op_level2 , : + dcsw_op_level #(2 << CSSELR_LEVEL_SHIFT) +END_FUNC dcache_op_level2 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 3 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in cache_helpers.h + * --------------------------------------------------------------- + */ +FUNC dcache_op_level3 , : + dcsw_op_level #(3 << CSSELR_LEVEL_SHIFT) +END_FUNC dcache_op_level3 + +FUNC icache_inv_all , : + /* Invalidate Entire Instruction Cache */ + ic ialluis + + dsb ish /* ensure that maintenance operations are seen */ + isb /* by the instructions rigth after the isb */ + + ret +END_FUNC icache_inv_all + +FUNC icache_inv_range , : + icache_line_size x2, x3 + add x1, x0, x1 + sub x3, x2, #1 + bic x0, x0, x3 +loop_ic_inv: + ic ivau, x0 + add x0, x0, x2 + cmp x0, x1 + b.lo loop_ic_inv + dsb ish + ret + +END_FUNC icache_inv_range + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/entry_a32.S b/optee/optee_os/core/arch/arm/kernel/entry_a32.S new file mode 100644 index 0000000..9f6a793 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/entry_a32.S @@ -0,0 +1,925 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + * Copyright (c) 2021-2023, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +.arch_extension sec + +.section .data +.balign 4 + +#ifdef CFG_BOOT_SYNC_CPU +.equ SEM_CPU_READY, 1 +#endif + +#ifdef CFG_PL310 +.section .rodata.init +panic_boot_file: + .asciz __FILE__ + +/* + * void assert_flat_mapped_range(uint32_t vaddr, uint32_t line) + */ +LOCAL_FUNC __assert_flat_mapped_range , : +UNWIND( .cantunwind) + push { r4-r6, lr } + mov r4, r0 + mov r5, r1 + bl cpu_mmu_enabled + cmp r0, #0 + beq 1f + mov r0, r4 + bl virt_to_phys + cmp r0, r4 + beq 1f + /* + * this must be compliant with the panic generic routine: + * __do_panic(__FILE__, __LINE__, __func__, str) + */ + ldr r0, =panic_boot_file + mov r1, r5 + mov r2, #0 + mov r3, #0 + bl __do_panic + b . /* should NOT return */ +1: pop { r4-r6, pc } +END_FUNC __assert_flat_mapped_range + + /* panic if mmu is enable and vaddr != paddr (scratch lr) */ + .macro assert_flat_mapped_range va, line + ldr r0, \va + ldr r1, =\line + bl __assert_flat_mapped_range + .endm +#endif /* CFG_PL310 */ + +WEAK_FUNC plat_cpu_reset_early , : + bx lr +END_FUNC plat_cpu_reset_early +DECLARE_KEEP_PAGER plat_cpu_reset_early + + .section .identity_map, "ax" + .align 5 +LOCAL_FUNC reset_vect_table , : , .identity_map + b . + b . /* Undef */ + b . /* Syscall */ + b . /* Prefetch abort */ + b . /* Data abort */ + b . /* Reserved */ + b . /* IRQ */ + b . /* FIQ */ +END_FUNC reset_vect_table + + .macro cpu_is_ready +#ifdef CFG_BOOT_SYNC_CPU + bl __get_core_pos + lsl r0, r0, #2 + ldr r1,=sem_cpu_sync + ldr r2, =SEM_CPU_READY + str r2, [r1, r0] + dsb + sev +#endif + .endm + + .macro wait_primary +#ifdef CFG_BOOT_SYNC_CPU + ldr r0, =sem_cpu_sync + mov r2, #SEM_CPU_READY + sev +1: + ldr r1, [r0] + cmp r1, r2 + wfene + bne 1b +#endif + .endm + + .macro wait_secondary +#ifdef CFG_BOOT_SYNC_CPU + ldr r0, =sem_cpu_sync + mov r3, #CFG_TEE_CORE_NB_CORE + mov r2, #SEM_CPU_READY + sev +1: + subs r3, r3, #1 + beq 3f + add r0, r0, #4 +2: + ldr r1, [r0] + cmp r1, r2 + wfene + bne 2b + b 1b +3: +#endif + .endm + + /* + * set_sctlr : Setup some core configuration in CP15 SCTLR + * + * Setup required by current implementation of the OP-TEE core: + * - Disable data and instruction cache. + * - MMU is expected off and exceptions trapped in ARM mode. + * - Enable or disable alignment checks upon platform configuration. + * - Optionally enable write-implies-execute-never. + * - Optionally enable round robin strategy for cache replacement. + * + * Clobbers r0. + */ + .macro set_sctlr + read_sctlr r0 + bic r0, r0, #(SCTLR_M | SCTLR_C) + bic r0, r0, #SCTLR_I + bic r0, r0, #SCTLR_TE + orr r0, r0, #SCTLR_SPAN +#if defined(CFG_SCTLR_ALIGNMENT_CHECK) + orr r0, r0, #SCTLR_A +#else + bic r0, r0, #SCTLR_A +#endif +#if defined(CFG_HWSUPP_MEM_PERM_WXN) && defined(CFG_CORE_RWDATA_NOEXEC) + orr r0, r0, #(SCTLR_WXN | SCTLR_UWXN) +#endif +#if defined(CFG_ENABLE_SCTLR_RR) + orr r0, r0, #SCTLR_RR +#endif + write_sctlr r0 + .endm + +#if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_WITH_ARM_TRUSTED_FW) + /* + * With OP-TEE as SPMC at S-EL1 the SPMD (SPD_spmd) in TF-A passes + * the DTB in r0, pagable part in r1, and the rest of the registers + * are unused + * + * Save boot arguments passed + * entry r0, saved r6: device tree address + * entry r1, saved r4: pagestore + * saved r5, r7: Zero + */ + .macro bootargs_entry + mov r6, r0 + mov r4, r1 + mov r5, #0 + mov r7, #0 + .endm +#else + /* + * Save boot arguments + * entry r0, saved r4: pagestore + * entry r1, saved r7: (ARMv7 standard bootarg #1) + * entry r2, saved r6: device tree address, (ARMv7 standard bootarg #2) + * entry lr, saved r5: non-secure entry address (ARMv7 bootarg #0) + */ + .macro bootargs_entry +#if defined(CFG_NS_ENTRY_ADDR) + ldr r5, =CFG_NS_ENTRY_ADDR +#else + mov r5, lr +#endif +#if defined(CFG_PAGEABLE_ADDR) + ldr r4, =CFG_PAGEABLE_ADDR +#else + mov r4, r0 +#endif +#if defined(CFG_DT_ADDR) + ldr r6, =CFG_DT_ADDR +#else + mov r6, r2 +#endif + mov r7, r1 + .endm +#endif + + .macro maybe_init_spectre_workaround +#if !defined(CFG_WITH_ARM_TRUSTED_FW) && \ + (defined(CFG_CORE_WORKAROUND_SPECTRE_BP) || \ + defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC)) + read_midr r0 + ubfx r1, r0, #MIDR_IMPLEMENTER_SHIFT, #MIDR_IMPLEMENTER_WIDTH + cmp r1, #MIDR_IMPLEMENTER_ARM + bne 1f + ubfx r1, r0, #MIDR_PRIMARY_PART_NUM_SHIFT, \ + #MIDR_PRIMARY_PART_NUM_WIDTH + + movw r2, #CORTEX_A8_PART_NUM + cmp r1, r2 + moveq r2, #ACTLR_CA8_ENABLE_INVALIDATE_BTB + beq 2f + + movw r2, #CORTEX_A15_PART_NUM + cmp r1, r2 + moveq r2, #ACTLR_CA15_ENABLE_INVALIDATE_BTB + bne 1f /* Skip it for all other CPUs */ +2: + read_actlr r0 + orr r0, r0, r2 + write_actlr r0 + isb +1: +#endif + .endm + +FUNC _start , : +UNWIND( .cantunwind) + + bootargs_entry + + /* + * 32bit entry is expected to execute Supervisor mode, + * some bootloader may enter in Supervisor or Monitor + */ + cps #CPSR_MODE_SVC + + /* Early ARM secure MP specific configuration */ + bl plat_cpu_reset_early + maybe_init_spectre_workaround + + set_sctlr + isb + + ldr r0, =reset_vect_table + write_vbar r0 + +#if defined(CFG_WITH_ARM_TRUSTED_FW) + b reset_primary +#else + bl __get_core_pos + cmp r0, #0 + beq reset_primary + b reset_secondary +#endif +END_FUNC _start +DECLARE_KEEP_INIT _start + + /* + * Setup sp to point to the top of the tmp stack for the current CPU: + * sp is assigned: + * stack_tmp + (cpu_id + 1) * stack_tmp_stride - STACK_TMP_GUARD + */ + .macro set_sp + bl __get_core_pos + cmp r0, #CFG_TEE_CORE_NB_CORE + /* Unsupported CPU, park it before it breaks something */ + bge unhandled_cpu + add r0, r0, #1 + + /* r2 = stack_tmp - STACK_TMP_GUARD */ + adr r3, stack_tmp_rel + ldr r2, [r3] + add r2, r2, r3 + + /* + * stack_tmp_stride and stack_tmp_stride_rel are the + * equivalent of: + * extern const u32 stack_tmp_stride; + * u32 stack_tmp_stride_rel = (u32)&stack_tmp_stride - + * (u32)&stack_tmp_stride_rel + * + * To load the value of stack_tmp_stride we do the equivalent + * of: + * *(u32 *)(stack_tmp_stride + (u32)&stack_tmp_stride_rel) + */ + adr r3, stack_tmp_stride_rel + ldr r1, [r3] + ldr r1, [r1, r3] + + /* + * r0 is core pos + 1 + * r1 is value of stack_tmp_stride + * r2 is value of stack_tmp + guard + */ + mul r1, r0, r1 + add sp, r1, r2 + .endm + + /* + * Cache maintenance during entry: handle outer cache. + * End address is exclusive: first byte not to be changed. + * Note however arm_clX_inv/cleanbyva operate on full cache lines. + * + * Use ANSI #define to trap source file line number for PL310 assertion + */ + .macro __inval_cache_vrange vbase, vend, line +#if defined(CFG_PL310) && !defined(CFG_PL310_SIP_PROTOCOL) + assert_flat_mapped_range (\vbase), (\line) + bl pl310_base + ldr r1, \vbase + ldr r2, \vend + bl arm_cl2_invbypa +#endif + ldr r0, \vbase + ldr r1, \vend + sub r1, r1, r0 + bl dcache_inv_range + .endm + + .macro __flush_cache_vrange vbase, vend, line +#if defined(CFG_PL310) && !defined(CFG_PL310_SIP_PROTOCOL) + assert_flat_mapped_range (\vbase), (\line) + ldr r0, \vbase + ldr r1, \vend + sub r1, r1, r0 + bl dcache_clean_range + bl pl310_base + ldr r1, \vbase + ldr r2, \vend + bl arm_cl2_cleaninvbypa +#endif + ldr r0, \vbase + ldr r1, \vend + sub r1, r1, r0 + bl dcache_cleaninv_range + .endm + +#define inval_cache_vrange(vbase, vend) \ + __inval_cache_vrange vbase, vend, __LINE__ + +#define flush_cache_vrange(vbase, vend) \ + __flush_cache_vrange vbase, vend, __LINE__ + +#ifdef CFG_BOOT_SYNC_CPU +#define flush_cpu_semaphores \ + flush_cache_vrange(sem_cpu_sync_start, sem_cpu_sync_end) +#else +#define flush_cpu_semaphores +#endif + +LOCAL_FUNC reset_primary , : , .identity_map +UNWIND( .cantunwind) + + /* preserve r4-r7: bootargs */ + +#ifdef CFG_WITH_PAGER + /* + * Move init code into correct location and move hashes to a + * temporary safe location until the heap is initialized. + * + * The binary is built as: + * [Pager code, rodata and data] : In correct location + * [Init code and rodata] : Should be copied to __init_start + * [struct boot_embdata + data] : Should be saved before + * initializing pager, first uint32_t tells the length of the data + */ + ldr r0, =__init_start /* dst */ + ldr r1, =__data_end /* src */ + ldr r2, =__init_end + sub r2, r2, r0 /* init len */ + ldr r12, [r1, r2] /* length of hashes etc */ + add r2, r2, r12 /* length of init and hashes etc */ + /* Copy backwards (as memmove) in case we're overlapping */ + add r0, r0, r2 /* __init_start + len */ + add r1, r1, r2 /* __data_end + len */ + str r0, cached_mem_end + ldr r2, =__init_start +copy_init: + ldmdb r1!, {r3, r8-r12} + stmdb r0!, {r3, r8-r12} + cmp r0, r2 + bgt copy_init +#else + /* + * The binary is built as: + * [Core, rodata and data] : In correct location + * [struct boot_embdata + data] : Should be moved to __end, first + * uint32_t tells the length of the struct + data + */ + ldr r0, =__end /* dst */ + ldr r1, =__data_end /* src */ + ldr r2, [r1] /* struct boot_embdata::total_len */ + /* Copy backwards (as memmove) in case we're overlapping */ + add r0, r0, r2 + add r1, r1, r2 + str r0, cached_mem_end + ldr r2, =__end + +copy_init: + ldmdb r1!, {r3, r8-r12} + stmdb r0!, {r3, r8-r12} + cmp r0, r2 + bgt copy_init +#endif + + /* + * Clear .bss, this code obviously depends on the linker keeping + * start/end of .bss at least 8 byte aligned. + */ + ldr r0, =__bss_start + ldr r1, =__bss_end + mov r2, #0 + mov r3, #0 +clear_bss: + stmia r0!, {r2, r3} + cmp r0, r1 + bls clear_bss + +#ifdef CFG_NS_VIRTUALIZATION + /* + * Clear .nex_bss, this code obviously depends on the linker keeping + * start/end of .bss at least 8 byte aligned. + */ + ldr r0, =__nex_bss_start + ldr r1, =__nex_bss_end + mov r2, #0 + mov r3, #0 +clear_nex_bss: + stmia r0!, {r2, r3} + cmp r0, r1 + bls clear_nex_bss +#endif + +#ifdef CFG_CORE_SANITIZE_KADDRESS + /* First initialize the entire shadow area with no access */ + ldr r0, =__asan_shadow_start /* start */ + ldr r1, =__asan_shadow_end /* limit */ + mov r2, #ASAN_DATA_RED_ZONE +shadow_no_access: + str r2, [r0], #4 + cmp r0, r1 + bls shadow_no_access + + /* Mark the entire stack area as OK */ + ldr r2, =CFG_ASAN_SHADOW_OFFSET + ldr r0, =__nozi_stack_start /* start */ + lsr r0, r0, #ASAN_BLOCK_SHIFT + add r0, r0, r2 + ldr r1, =__nozi_stack_end /* limit */ + lsr r1, r1, #ASAN_BLOCK_SHIFT + add r1, r1, r2 + mov r2, #0 +shadow_stack_access_ok: + strb r2, [r0], #1 + cmp r0, r1 + bls shadow_stack_access_ok +#endif + + set_sp + + bl thread_init_thread_core_local + + /* complete ARM secure MP common configuration */ + bl plat_primary_init_early + + /* Enable Console */ + bl console_init + +#ifdef CFG_PL310 + bl pl310_base + bl arm_cl2_config +#endif + + /* + * Invalidate dcache for all memory used during initialization to + * avoid nasty surprices when the cache is turned on. We must not + * invalidate memory not used by OP-TEE since we may invalidate + * entries used by for instance ARM Trusted Firmware. + */ + inval_cache_vrange(cached_mem_start, cached_mem_end) + +#if defined(CFG_PL310) && !defined(CFG_PL310_SIP_PROTOCOL) + /* Enable PL310 if not yet enabled */ + bl pl310_base + bl arm_cl2_enable +#endif + +#ifdef CFG_CORE_ASLR + mov r0, r6 + bl get_aslr_seed +#else + mov r0, #0 +#endif + + ldr r1, =boot_mmu_config + bl core_init_mmu_map + +#ifdef CFG_CORE_ASLR + /* + * Process relocation information for updating with the virtual map + * offset. We're doing this now before MMU is enabled as some of + * the memory will become write protected. + */ + ldr r0, =boot_mmu_config + ldr r0, [r0, #CORE_MMU_CONFIG_MAP_OFFSET] + /* + * Update cached_mem_end address with load offset since it was + * calculated before relocation. + */ + ldr r2, cached_mem_end + add r2, r2, r0 + str r2, cached_mem_end + + bl relocate +#endif + + bl __get_core_pos + bl enable_mmu +#ifdef CFG_CORE_ASLR + /* + * Reinitialize console, since register_serial_console() has + * previously registered a PA and with ASLR the VA is different + * from the PA. + */ + bl console_init +#endif + +#ifdef CFG_NS_VIRTUALIZATION + /* + * Initialize partition tables for each partition to + * default_partition which has been relocated now to a different VA + */ + bl core_mmu_set_default_prtn_tbl +#endif + + mov r0, r4 /* pageable part address */ + mov r1, r5 /* ns-entry address */ + bl boot_init_primary_early +#ifndef CFG_NS_VIRTUALIZATION + mov r9, sp + ldr r0, =threads + ldr r0, [r0, #THREAD_CTX_STACK_VA_END] + mov sp, r0 + bl thread_get_core_local + mov r8, r0 + mov r0, #0 + str r0, [r8, #THREAD_CORE_LOCAL_FLAGS] +#endif + mov r0, r6 /* DT address */ + mov r1, #0 /* unused */ + bl boot_init_primary_late +#ifndef CFG_NS_VIRTUALIZATION + mov r0, #THREAD_CLF_TMP + str r0, [r8, #THREAD_CORE_LOCAL_FLAGS] + mov sp, r9 +#endif + +#ifdef _CFG_CORE_STACK_PROTECTOR + /* Update stack canary value */ + bl plat_get_random_stack_canary + ldr r1, =__stack_chk_guard + str r0, [r1] +#endif + + /* + * In case we've touched memory that secondary CPUs will use before + * they have turned on their D-cache, clean and invalidate the + * D-cache before exiting to normal world. + */ + flush_cache_vrange(cached_mem_start, cached_mem_end) + + /* release secondary boot cores and sync with them */ + cpu_is_ready + flush_cpu_semaphores + wait_secondary + +#ifdef CFG_PL310_LOCKED +#ifdef CFG_PL310_SIP_PROTOCOL +#error "CFG_PL310_LOCKED must not be defined when CFG_PL310_SIP_PROTOCOL=y" +#endif + /* lock/invalidate all lines: pl310 behaves as if disable */ + bl pl310_base + bl arm_cl2_lockallways + bl pl310_base + bl arm_cl2_cleaninvbyway +#endif + + /* + * Clear current thread id now to allow the thread to be reused on + * next entry. Matches the thread_init_boot_thread() in + * boot.c. + */ +#ifndef CFG_NS_VIRTUALIZATION + bl thread_clr_boot_thread +#endif + +#ifdef CFG_CORE_FFA + ldr r0, =cpu_on_handler + /* + * Compensate for the virtual map offset since cpu_on_handler() is + * called with MMU off. + */ + ldr r1, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET + sub r0, r0, r1 + bl thread_spmc_register_secondary_ep + b thread_ffa_msg_wait +#else /* CFG_CORE_FFA */ + +#if defined(CFG_WITH_ARM_TRUSTED_FW) + ldr r0, =boot_mmu_config + ldr r0, [r0, #CORE_MMU_CONFIG_MAP_OFFSET] + ldr r1, =thread_vector_table + /* Pass the vector address returned from main_init */ + sub r1, r1, r0 +#else + /* realy standard bootarg #1 and #2 to non secure entry */ + mov r4, #0 + mov r3, r6 /* std bootarg #2 for register R2 */ + mov r2, r7 /* std bootarg #1 for register R1 */ + mov r1, #0 +#endif /* CFG_WITH_ARM_TRUSTED_FW */ + + mov r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +#endif /* CFG_CORE_FFA */ +END_FUNC reset_primary + +#ifdef CFG_BOOT_SYNC_CPU +LOCAL_DATA sem_cpu_sync_start , : + .word sem_cpu_sync +END_DATA sem_cpu_sync_start + +LOCAL_DATA sem_cpu_sync_end , : + .word sem_cpu_sync + (CFG_TEE_CORE_NB_CORE << 2) +END_DATA sem_cpu_sync_end +#endif + +LOCAL_DATA cached_mem_start , : + .word __text_start +END_DATA cached_mem_start + +LOCAL_DATA cached_mem_end , : + .skip 4 +END_DATA cached_mem_end + +LOCAL_FUNC unhandled_cpu , : + wfi + b unhandled_cpu +END_FUNC unhandled_cpu + +#ifdef CFG_CORE_ASLR +LOCAL_FUNC relocate , : + push {r4-r5} + /* r0 holds load offset */ +#ifdef CFG_WITH_PAGER + ldr r12, =__init_end +#else + ldr r12, =__end +#endif + ldr r2, [r12, #BOOT_EMBDATA_RELOC_OFFSET] + ldr r3, [r12, #BOOT_EMBDATA_RELOC_LEN] + + mov_imm r1, TEE_LOAD_ADDR + add r2, r2, r12 /* start of relocations */ + add r3, r3, r2 /* end of relocations */ + + /* + * Relocations are not formatted as Rel32, instead they are in a + * compressed format created by get_reloc_bin() in + * scripts/gen_tee_bin.py + * + * All the R_ARM_RELATIVE relocations are translated into a list of + * 32-bit offsets from TEE_LOAD_ADDR. At each address a 32-bit + * value pointed out which increased with the load offset. + */ + +#ifdef CFG_WITH_PAGER + /* + * With pager enabled we can only relocate the pager and init + * parts, the rest has to be done when a page is populated. + */ + sub r12, r12, r1 +#endif + + b 2f + /* Loop over the relocation addresses and process all entries */ +1: ldr r4, [r2], #4 +#ifdef CFG_WITH_PAGER + /* Skip too large addresses */ + cmp r4, r12 + bge 2f +#endif + ldr r5, [r4, r1] + add r5, r5, r0 + str r5, [r4, r1] + +2: cmp r2, r3 + bne 1b + + pop {r4-r5} + bx lr +END_FUNC relocate +#endif + +/* + * void enable_mmu(unsigned long core_pos); + * + * This function depends on being mapped with in the identity map where + * physical address and virtual address is the same. After MMU has been + * enabled the instruction pointer will be updated to execute as the new + * offset instead. Stack pointers and the return address are updated. + */ +LOCAL_FUNC enable_mmu , : , .identity_map + /* r0 = core pos */ + adr r1, boot_mmu_config + +#ifdef CFG_WITH_LPAE + ldm r1!, {r2, r3} + /* + * r2 = ttbcr + * r3 = mair0 + */ + write_ttbcr r2 + write_mair0 r3 + + ldm r1!, {r2, r3} + /* + * r2 = ttbr0_base + * r3 = ttbr0_core_offset + */ + + /* + * ttbr0_el1 = ttbr0_base + ttbr0_core_offset * core_pos + */ + mla r12, r0, r3, r2 + mov r0, #0 + write_ttbr0_64bit r12, r0 + write_ttbr1_64bit r0, r0 +#else + ldm r1!, {r2, r3} + /* + * r2 = prrr + * r3 = nmrr + */ + write_prrr r2 + write_nmrr r3 + + ldm r1!, {r2, r3} + /* + * r2 = dacr + * r3 = ttbcr + */ + write_dacr r2 + write_ttbcr r3 + + ldm r1!, {r2} + /* r2 = ttbr */ + write_ttbr0 r2 + write_ttbr1 r2 + + mov r2, #0 + write_contextidr r2 +#endif + ldm r1!, {r2} + /* r2 = load_offset (always 0 if CFG_CORE_ASLR=n) */ + isb + + /* Invalidate TLB */ + write_tlbiall + + /* + * Make sure translation table writes have drained into memory and + * the TLB invalidation is complete. + */ + dsb sy + isb + + read_sctlr r0 + orr r0, r0, #SCTLR_M +#ifndef CFG_WITH_LPAE + /* Enable Access flag (simplified access permissions) and TEX remap */ + orr r0, r0, #(SCTLR_AFE | SCTLR_TRE) +#endif + write_sctlr r0 + isb + + /* Update vbar */ + read_vbar r1 + add r1, r1, r2 + write_vbar r1 + isb + + /* Invalidate instruction cache and branch predictor */ + write_iciallu + write_bpiall + isb + + read_sctlr r0 + /* Enable I and D cache */ + orr r0, r0, #SCTLR_I + orr r0, r0, #SCTLR_C +#if defined(CFG_ENABLE_SCTLR_Z) + /* + * This is only needed on ARMv7 architecture and hence conditionned + * by configuration directive CFG_ENABLE_SCTLR_Z. For recent + * architectures, the program flow prediction is automatically + * enabled upon MMU enablement. + */ + orr r0, r0, #SCTLR_Z +#endif + write_sctlr r0 + isb + + /* Adjust stack pointer and return address */ + add sp, sp, r2 + add lr, lr, r2 + + bx lr +END_FUNC enable_mmu + +LOCAL_DATA stack_tmp_rel , : + .word stack_tmp - stack_tmp_rel - STACK_TMP_GUARD +END_DATA stack_tmp_rel + +LOCAL_DATA stack_tmp_stride_rel , : + .word stack_tmp_stride - stack_tmp_stride_rel +END_DATA stack_tmp_stride_rel + +DATA boot_mmu_config , : /* struct core_mmu_config */ + .skip CORE_MMU_CONFIG_SIZE +END_DATA boot_mmu_config + +#if defined(CFG_WITH_ARM_TRUSTED_FW) +FUNC cpu_on_handler , : , .identity_map +UNWIND( .cantunwind) + mov r4, r0 + mov r5, r1 + mov r6, lr + + set_sctlr + isb + + adr r0, reset_vect_table + write_vbar r0 + + mov r4, lr + + bl __get_core_pos + bl enable_mmu + + set_sp + + mov r0, r4 + mov r1, r5 + bl boot_cpu_on_handler +#ifdef CFG_CORE_FFA + b thread_ffa_msg_wait +#else + bx r6 +#endif +END_FUNC cpu_on_handler +DECLARE_KEEP_PAGER cpu_on_handler + +#else /* defined(CFG_WITH_ARM_TRUSTED_FW) */ + +LOCAL_FUNC reset_secondary , : , .identity_map +UNWIND( .cantunwind) + adr r0, reset_vect_table + write_vbar r0 + + wait_primary + + set_sp + +#if defined (CFG_BOOT_SECONDARY_REQUEST) + /* if L1 is not invalidated before, do it here */ + mov r0, #DCACHE_OP_INV + bl dcache_op_level1 +#endif + + bl __get_core_pos + bl enable_mmu + + cpu_is_ready + +#if defined (CFG_BOOT_SECONDARY_REQUEST) + /* + * boot_core_hpen() return value (r0) is address of + * ns entry context structure + */ + bl boot_core_hpen + ldm r0, {r0, r6} +#else + mov r0, r5 /* ns-entry address */ + mov r6, #0 +#endif + bl boot_init_secondary + + mov r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE + mov r1, r6 + mov r2, #0 + mov r3, #0 + mov r4, #0 + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC reset_secondary +DECLARE_KEEP_PAGER reset_secondary +#endif /* defined(CFG_WITH_ARM_TRUSTED_FW) */ diff --git a/optee/optee_os/core/arch/arm/kernel/entry_a64.S b/optee/optee_os/core/arch/arm/kernel/entry_a64.S new file mode 100644 index 0000000..c4e4943 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/entry_a64.S @@ -0,0 +1,756 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2022, Linaro Limited + * Copyright (c) 2021-2023, Arm Limited + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + /* + * Setup SP_EL0 and SPEL1, SP will be set to SP_EL0. + * SP_EL0 is assigned: + * stack_tmp + (cpu_id + 1) * stack_tmp_stride - STACK_TMP_GUARD + * SP_EL1 is assigned thread_core_local[cpu_id] + */ + .macro set_sp + bl __get_core_pos + cmp x0, #CFG_TEE_CORE_NB_CORE + /* Unsupported CPU, park it before it breaks something */ + bge unhandled_cpu + add x0, x0, #1 + adr_l x1, stack_tmp_stride + ldr w1, [x1] + mul x1, x0, x1 + + /* x0 = stack_tmp - STACK_TMP_GUARD */ + adr_l x2, stack_tmp_rel + ldr w0, [x2] + add x0, x0, x2 + + msr spsel, #0 + add sp, x1, x0 + bl thread_get_core_local + msr spsel, #1 + mov sp, x0 + msr spsel, #0 + .endm + + .macro read_feat_mte reg + mrs \reg, id_aa64pfr1_el1 + ubfx \reg, \reg, #ID_AA64PFR1_EL1_MTE_SHIFT, #4 + .endm + + .macro set_sctlr_el1 + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_I + orr x0, x0, #SCTLR_SA + orr x0, x0, #SCTLR_SPAN +#if defined(CFG_CORE_RWDATA_NOEXEC) + orr x0, x0, #SCTLR_WXN +#endif +#if defined(CFG_SCTLR_ALIGNMENT_CHECK) + orr x0, x0, #SCTLR_A +#else + bic x0, x0, #SCTLR_A +#endif +#ifdef CFG_MEMTAG + read_feat_mte x1 + cmp w1, #1 + b.ls 111f + orr x0, x0, #(SCTLR_ATA | SCTLR_ATA0) + bic x0, x0, #SCTLR_TCF_MASK + bic x0, x0, #SCTLR_TCF0_MASK +111: +#endif +#if defined(CFG_TA_PAUTH) && defined(CFG_TA_BTI) + orr x0, x0, #SCTLR_BT0 +#endif +#if defined(CFG_CORE_PAUTH) && defined(CFG_CORE_BTI) + orr x0, x0, #SCTLR_BT1 +#endif + msr sctlr_el1, x0 + .endm + + .macro init_memtag_per_cpu + read_feat_mte x0 + cmp w0, #1 + b.ls 11f + +#ifdef CFG_TEE_CORE_DEBUG + /* + * This together with GCR_EL1.RRND = 0 will make the tags + * acquired with the irg instruction deterministic. + */ + mov_imm x0, 0xcafe00 + msr rgsr_el1, x0 + /* Avoid tag = 0x0 and 0xf */ + mov x0, #0 +#else + /* + * Still avoid tag = 0x0 and 0xf as we use that tag for + * everything which isn't explicitly tagged. Setting + * GCR_EL1.RRND = 1 to allow an implementation specific + * method of generating the tags. + */ + mov x0, #GCR_EL1_RRND +#endif + orr x0, x0, #1 + orr x0, x0, #(1 << 15) + msr gcr_el1, x0 + + /* + * Enable the tag checks on the current CPU. + * + * Depends on boot_init_memtag() having cleared tags for + * TEE core memory. Well, not really, addresses with the + * tag value 0b0000 will use unchecked access due to + * TCR_TCMA0. + */ + mrs x0, tcr_el1 + orr x0, x0, #TCR_TBI0 + orr x0, x0, #TCR_TCMA0 + msr tcr_el1, x0 + + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_TCF_SYNC + orr x0, x0, #SCTLR_TCF0_SYNC + msr sctlr_el1, x0 + + isb +11: + .endm + + .macro init_pauth_per_cpu + msr spsel, #1 + ldp x0, x1, [sp, #THREAD_CORE_LOCAL_KEYS] + msr spsel, #0 + write_apiakeyhi x0 + write_apiakeylo x1 + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_ENIA + msr sctlr_el1, x0 + isb + .endm + +FUNC _start , : + /* + * Register use: + * x0 - CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=n: + * if non-NULL holds the TOS FW config [1] address + * - CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=y: + * address of FF-A Boot Information Blob + * - CFG_CORE_FFA=n: + * if non-NULL holds the pagable part address + * x2 - CFG_CORE_SEL2_SPMC=n: + * if non-NULL holds the system DTB address + * + * x19 - saved x0 + * x20 - saved x2 + * + * [1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware + * configuration file. Used by Trusted OS (BL32), that is, OP-TEE + * here. + */ + mov x19, x0 +#if defined(CFG_DT_ADDR) + ldr x20, =CFG_DT_ADDR +#else + mov x20, x2 /* Save DT address */ +#endif + + adr x0, reset_vect_table + msr vbar_el1, x0 + isb + + set_sctlr_el1 + isb + +#ifdef CFG_WITH_PAGER + /* + * Move init code into correct location and move hashes to a + * temporary safe location until the heap is initialized. + * + * The binary is built as: + * [Pager code, rodata and data] : In correct location + * [Init code and rodata] : Should be copied to __init_start + * [struct boot_embdata + data] : Should be saved before + * initializing pager, first uint32_t tells the length of the data + */ + adr x0, __init_start /* dst */ + adr x1, __data_end /* src */ + adr x2, __init_end + sub x2, x2, x0 /* init len */ + ldr w4, [x1, x2] /* length of hashes etc */ + add x2, x2, x4 /* length of init and hashes etc */ + /* Copy backwards (as memmove) in case we're overlapping */ + add x0, x0, x2 /* __init_start + len */ + add x1, x1, x2 /* __data_end + len */ + adr x3, cached_mem_end + str x0, [x3] + adr x2, __init_start +copy_init: + ldp x3, x4, [x1, #-16]! + stp x3, x4, [x0, #-16]! + cmp x0, x2 + b.gt copy_init +#else + /* + * The binary is built as: + * [Core, rodata and data] : In correct location + * [struct boot_embdata + data] : Should be moved to __end, first + * uint32_t tells the length of the struct + data + */ + adr_l x0, __end /* dst */ + adr_l x1, __data_end /* src */ + ldr w2, [x1] /* struct boot_embdata::total_len */ + /* Copy backwards (as memmove) in case we're overlapping */ + add x0, x0, x2 + add x1, x1, x2 + adr x3, cached_mem_end + str x0, [x3] + adr_l x2, __end + +copy_init: + ldp x3, x4, [x1, #-16]! + stp x3, x4, [x0, #-16]! + cmp x0, x2 + b.gt copy_init +#endif + + /* + * Clear .bss, this code obviously depends on the linker keeping + * start/end of .bss at least 8 byte aligned. + */ + adr_l x0, __bss_start + adr_l x1, __bss_end +clear_bss: + str xzr, [x0], #8 + cmp x0, x1 + b.lt clear_bss + +#ifdef CFG_NS_VIRTUALIZATION + /* + * Clear .nex_bss, this code obviously depends on the linker keeping + * start/end of .bss at least 8 byte aligned. + */ + adr x0, __nex_bss_start + adr x1, __nex_bss_end +clear_nex_bss: + str xzr, [x0], #8 + cmp x0, x1 + b.lt clear_nex_bss +#endif + + +#if defined(CFG_CORE_PHYS_RELOCATABLE) + /* + * Save the base physical address, it will not change after this + * point. + */ + adr_l x2, core_mmu_tee_load_pa + adr x1, _start /* Load address */ + str x1, [x2] + + mov_imm x0, TEE_LOAD_ADDR /* Compiled load address */ + sub x0, x1, x0 /* Relocatation offset */ + + cbz x0, 1f + bl relocate +1: +#endif + + /* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */ + set_sp + + bl thread_init_thread_core_local + + /* Enable aborts now that we can receive exceptions */ + msr daifclr, #DAIFBIT_ABT + + /* + * Invalidate dcache for all memory used during initialization to + * avoid nasty surprices when the cache is turned on. We must not + * invalidate memory not used by OP-TEE since we may invalidate + * entries used by for instance ARM Trusted Firmware. + */ + adr_l x0, __text_start + ldr x1, cached_mem_end + sub x1, x1, x0 + bl dcache_cleaninv_range + + /* Enable Console */ + bl console_init + +#if ! defined(CFG_CORE_SEL2_SPMC) && defined(CFG_CORE_PHYS_RELOCATABLE) + adr x0, _start /* Load address */ + bl boot_set_fixed_secmem_range +#endif + +#if defined(CFG_CORE_SEL2_SPMC) && defined(CFG_CORE_PHYS_RELOCATABLE) + mov x0, x19 /* boot info */ + bl boot_save_boot_info +#endif + +#ifdef CFG_MEMTAG + /* + * If FEAT_MTE2 is available, initializes the memtag callbacks. + * Tags for OP-TEE core memory are then cleared to make it safe to + * enable MEMTAG below. + */ + bl boot_init_memtag +#endif + +#ifdef CFG_CORE_ASLR + mov x0, x20 /* DT address */ + bl get_aslr_seed +#else + mov x0, #0 +#endif + + adr x1, boot_mmu_config + bl core_init_mmu_map + +#ifdef CFG_CORE_ASLR + /* + * Process relocation information again updating for the virtual + * map offset. We're doing this now before MMU is enabled as some + * of the memory will become write protected. + */ + ldr x0, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET + cbz x0, 1f + /* + * Update cached_mem_end address with load offset since it was + * calculated before relocation. + */ + adr x5, cached_mem_end + ldr x6, [x5] + add x6, x6, x0 + str x6, [x5] + adr x1, _start /* Load address */ + bl relocate +1: +#endif + + bl __get_core_pos + bl enable_mmu +#ifdef CFG_CORE_ASLR + /* + * Reinitialize console, since register_serial_console() has + * previously registered a PA and with ASLR the VA is different + * from the PA. + */ + bl console_init +#endif + +#ifdef CFG_NS_VIRTUALIZATION + /* + * Initialize partition tables for each partition to + * default_partition which has been relocated now to a different VA + */ + bl core_mmu_set_default_prtn_tbl +#endif + +#ifdef CFG_CORE_SEL1_SPMC + mov x0, xzr /* pager not used */ +#else + mov x0, x19 /* pagable part address */ +#endif + mov x1, #-1 + bl boot_init_primary_early + +#ifdef CFG_MEMTAG + init_memtag_per_cpu +#endif + +#ifndef CFG_NS_VIRTUALIZATION + mov x21, sp + adr_l x0, threads + ldr x0, [x0, #THREAD_CTX_STACK_VA_END] + mov sp, x0 + bl thread_get_core_local + mov x22, x0 + str wzr, [x22, #THREAD_CORE_LOCAL_FLAGS] +#endif + mov x0, x20 /* DT address also known as HW_CONFIG */ +#ifdef CFG_CORE_SEL1_SPMC + mov x1, x19 /* TOS_FW_CONFIG DT address */ +#else + mov x1, xzr /* unused */ +#endif + bl boot_init_primary_late +#ifdef CFG_CORE_PAUTH + init_pauth_per_cpu +#endif + +#ifndef CFG_NS_VIRTUALIZATION + mov x0, #THREAD_CLF_TMP + str w0, [x22, #THREAD_CORE_LOCAL_FLAGS] + mov sp, x21 +#endif + +#ifdef _CFG_CORE_STACK_PROTECTOR + /* Update stack canary value */ + bl plat_get_random_stack_canary + adr_l x5, __stack_chk_guard + str x0, [x5] +#endif + + /* + * In case we've touched memory that secondary CPUs will use before + * they have turned on their D-cache, clean and invalidate the + * D-cache before exiting to normal world. + */ + adr_l x0, __text_start + ldr x1, cached_mem_end + sub x1, x1, x0 + bl dcache_cleaninv_range + + + /* + * Clear current thread id now to allow the thread to be reused on + * next entry. Matches the thread_init_boot_thread in + * boot.c. + */ +#ifndef CFG_NS_VIRTUALIZATION + bl thread_clr_boot_thread +#endif + +#ifdef CFG_CORE_FFA + adr x0, cpu_on_handler + /* + * Compensate for the virtual map offset since cpu_on_handler() is + * called with MMU off. + */ + ldr x1, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET + sub x0, x0, x1 + bl thread_spmc_register_secondary_ep + b thread_ffa_msg_wait +#else + /* + * Pass the vector address returned from main_init Compensate for + * the virtual map offset since cpu_on_handler() is called with MMU + * off. + */ + ldr x0, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET + adr x1, thread_vector_table + sub x1, x1, x0 + mov x0, #TEESMC_OPTEED_RETURN_ENTRY_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +#endif +END_FUNC _start +DECLARE_KEEP_INIT _start + + .section .identity_map.data + .balign 8 +LOCAL_DATA cached_mem_end , : + .skip 8 +END_DATA cached_mem_end + +#if defined(CFG_CORE_ASLR) || defined(CFG_CORE_PHYS_RELOCATABLE) +LOCAL_FUNC relocate , : + /* + * x0 holds relocate offset + * x1 holds load address + */ +#ifdef CFG_WITH_PAGER + adr_l x6, __init_end +#else + adr_l x6, __end +#endif + ldp w2, w3, [x6, #BOOT_EMBDATA_RELOC_OFFSET] + + add x2, x2, x6 /* start of relocations */ + add x3, x3, x2 /* end of relocations */ + + /* + * Relocations are not formatted as Rela64, instead they are in a + * compressed format created by get_reloc_bin() in + * scripts/gen_tee_bin.py + * + * All the R_AARCH64_RELATIVE relocations are translated into a + * list of 32-bit offsets from TEE_LOAD_ADDR. At each address a + * 64-bit value pointed out which increased with the load offset. + */ + +#ifdef CFG_WITH_PAGER + /* + * With pager enabled we can only relocate the pager and init + * parts, the rest has to be done when a page is populated. + */ + sub x6, x6, x1 +#endif + + b 2f + /* Loop over the relocation addresses and process all entries */ +1: ldr w4, [x2], #4 +#ifdef CFG_WITH_PAGER + /* Skip too large addresses */ + cmp x4, x6 + b.ge 2f +#endif + add x4, x4, x1 + ldr x5, [x4] + add x5, x5, x0 + str x5, [x4] + +2: cmp x2, x3 + b.ne 1b + + ret +END_FUNC relocate +#endif + +/* + * void enable_mmu(unsigned long core_pos); + * + * This function depends on being mapped with in the identity map where + * physical address and virtual address is the same. After MMU has been + * enabled the instruction pointer will be updated to execute as the new + * offset instead. Stack pointers and the return address are updated. + */ +LOCAL_FUNC enable_mmu , : , .identity_map + adr x1, boot_mmu_config + load_xregs x1, 0, 2, 6 + /* + * x0 = core_pos + * x2 = tcr_el1 + * x3 = mair_el1 + * x4 = ttbr0_el1_base + * x5 = ttbr0_core_offset + * x6 = load_offset + */ + msr tcr_el1, x2 + msr mair_el1, x3 + + /* + * ttbr0_el1 = ttbr0_el1_base + ttbr0_core_offset * core_pos + */ + madd x1, x5, x0, x4 + msr ttbr0_el1, x1 + msr ttbr1_el1, xzr + isb + + /* Invalidate TLB */ + tlbi vmalle1 + + /* + * Make sure translation table writes have drained into memory and + * the TLB invalidation is complete. + */ + dsb sy + isb + + /* Enable the MMU */ + mrs x1, sctlr_el1 + orr x1, x1, #SCTLR_M + msr sctlr_el1, x1 + isb + + /* Update vbar */ + mrs x1, vbar_el1 + add x1, x1, x6 + msr vbar_el1, x1 + isb + + /* Invalidate instruction cache and branch predictor */ + ic iallu + isb + + /* Enable I and D cache */ + mrs x1, sctlr_el1 + orr x1, x1, #SCTLR_I + orr x1, x1, #SCTLR_C + msr sctlr_el1, x1 + isb + + /* Adjust stack pointers and return address */ + msr spsel, #1 + add sp, sp, x6 + msr spsel, #0 + add sp, sp, x6 + add x30, x30, x6 + + ret +END_FUNC enable_mmu + + .section .identity_map.data + .balign 8 +DATA boot_mmu_config , : /* struct core_mmu_config */ + .skip CORE_MMU_CONFIG_SIZE +END_DATA boot_mmu_config + +FUNC cpu_on_handler , : + mov x19, x0 + mov x20, x1 + mov x21, x30 + + adr x0, reset_vect_table + msr vbar_el1, x0 + isb + + set_sctlr_el1 + isb + + /* Enable aborts now that we can receive exceptions */ + msr daifclr, #DAIFBIT_ABT + + bl __get_core_pos + bl enable_mmu + + /* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */ + set_sp + +#ifdef CFG_MEMTAG + init_memtag_per_cpu +#endif +#ifdef CFG_CORE_PAUTH + init_pauth_per_cpu +#endif + + mov x0, x19 + mov x1, x20 +#ifdef CFG_CORE_FFA + bl boot_cpu_on_handler + b thread_ffa_msg_wait +#else + mov x30, x21 + b boot_cpu_on_handler +#endif +END_FUNC cpu_on_handler +DECLARE_KEEP_PAGER cpu_on_handler + +LOCAL_FUNC unhandled_cpu , : + wfi + b unhandled_cpu +END_FUNC unhandled_cpu + +LOCAL_DATA stack_tmp_rel , : + .word stack_tmp - stack_tmp_rel - STACK_TMP_GUARD +END_DATA stack_tmp_rel + + /* + * This macro verifies that the a given vector doesn't exceed the + * architectural limit of 32 instructions. This is meant to be placed + * immedately after the last instruction in the vector. It takes the + * vector entry as the parameter + */ + .macro check_vector_size since + .if (. - \since) > (32 * 4) + .error "Vector exceeds 32 instructions" + .endif + .endm + + .section .identity_map, "ax", %progbits + .align 11 +LOCAL_FUNC reset_vect_table , :, .identity_map, , nobti + /* ----------------------------------------------------- + * Current EL with SP0 : 0x0 - 0x180 + * ----------------------------------------------------- + */ +SynchronousExceptionSP0: + b SynchronousExceptionSP0 + check_vector_size SynchronousExceptionSP0 + + .align 7 +IrqSP0: + b IrqSP0 + check_vector_size IrqSP0 + + .align 7 +FiqSP0: + b FiqSP0 + check_vector_size FiqSP0 + + .align 7 +SErrorSP0: + b SErrorSP0 + check_vector_size SErrorSP0 + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x380 + * ----------------------------------------------------- + */ + .align 7 +SynchronousExceptionSPx: + b SynchronousExceptionSPx + check_vector_size SynchronousExceptionSPx + + .align 7 +IrqSPx: + b IrqSPx + check_vector_size IrqSPx + + .align 7 +FiqSPx: + b FiqSPx + check_vector_size FiqSPx + + .align 7 +SErrorSPx: + b SErrorSPx + check_vector_size SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x580 + * ----------------------------------------------------- + */ + .align 7 +SynchronousExceptionA64: + b SynchronousExceptionA64 + check_vector_size SynchronousExceptionA64 + + .align 7 +IrqA64: + b IrqA64 + check_vector_size IrqA64 + + .align 7 +FiqA64: + b FiqA64 + check_vector_size FiqA64 + + .align 7 +SErrorA64: + b SErrorA64 + check_vector_size SErrorA64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x0 - 0x180 + * ----------------------------------------------------- + */ + .align 7 +SynchronousExceptionA32: + b SynchronousExceptionA32 + check_vector_size SynchronousExceptionA32 + + .align 7 +IrqA32: + b IrqA32 + check_vector_size IrqA32 + + .align 7 +FiqA32: + b FiqA32 + check_vector_size FiqA32 + + .align 7 +SErrorA32: + b SErrorA32 + check_vector_size SErrorA32 + +END_FUNC reset_vect_table + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/idle.c b/optee/optee_os/core/arch/arm/kernel/idle.c new file mode 100644 index 0000000..c2824fc --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/idle.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Huawei Technology Co., Ltd + */ + +#include +#include + +void cpu_idle(void) +{ + dsb(); + wfi(); +} diff --git a/optee/optee_os/core/arch/arm/kernel/kern.ld.S b/optee/optee_os/core/arch/arm/kernel/kern.ld.S new file mode 100644 index 0000000..500c2d2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/kern.ld.S @@ -0,0 +1,499 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND MIT) */ +/* + * 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. + */ + +/* + * Copyright (c) 2008-2010 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +/* + * Note: + * Clang 11 (ld.lld) generates non-relocatable reference when using ROUNDDOWN() + * from , which does not work with ASLR. + */ +#define LD_ROUNDDOWN(x, y) ((x) - ((x) % (y))) + +OUTPUT_FORMAT(CFG_KERN_LINKER_FORMAT) +OUTPUT_ARCH(CFG_KERN_LINKER_ARCH) + +ENTRY(_start) +SECTIONS +{ + . = TEE_LOAD_ADDR; + ASSERT(!(TEE_LOAD_ADDR & (SMALL_PAGE_SIZE - 1)), + "text start should be page aligned") + __text_start = .; + + /* + * Memory between TEE_LOAD_ADDR and page aligned rounded down + * value will be mapped with unpaged "text" section attributes: + * likely to be read-only/executable. + */ + __flatmap_unpg_rx_start = LD_ROUNDDOWN(__text_start, SMALL_PAGE_SIZE); + + .text : { + KEEP(*(.text._start)) + __identity_map_init_start = .; + __text_data_start = .; + *(.identity_map.data) + __text_data_end = .; + *(.identity_map .identity_map.* \ + /* + * The one below is needed because it's a weak + * symbol that may be overridden by platform + * specific code. + */ + .text.get_core_pos_mpidr) + __identity_map_init_end = .; + KEEP(*(.text.init .text.plat_cpu_reset_early \ + .text.reset .text.reset_primary .text.unhandled_cpu \ + .text.__assert_flat_mapped_range)) + +#ifdef CFG_WITH_PAGER + *(.text) +/* Include list of sections needed for paging */ +#include +#else + *(.text .text.*) +#endif + *(.sram.text.glue_7* .gnu.linkonce.t.*) + . = ALIGN(8); + } + __text_end = .; + +#ifdef CFG_CORE_RODATA_NOEXEC + . = ALIGN(SMALL_PAGE_SIZE); +#endif + __flatmap_unpg_rx_size = . - __flatmap_unpg_rx_start; + __flatmap_unpg_ro_start = .; + + .rodata : ALIGN(8) { + __rodata_start = .; + *(.gnu.linkonce.r.*) +#ifdef CFG_WITH_PAGER + *(.rodata .rodata.__unpaged .rodata.__unpaged.*) +#include +#else + *(.rodata .rodata.*) +#ifndef CFG_CORE_ASLR + . = ALIGN(8); + KEEP(*(SORT(.scattered_array*))); +#endif +#endif + . = ALIGN(8); + __rodata_end = .; + } + +#if defined(CFG_CORE_ASLR) + .data.rel.ro : { +#if !defined(CFG_WITH_PAGER) + . = ALIGN(8); + KEEP(*(SORT(.scattered_array*))); +#endif + *(.data.rel.ro.__unpaged .data.rel.ro.__unpaged.*) + } +#endif + + .got : { *(.got.plt) *(.got) } + .note.gnu.property : { *(.note.gnu.property) } + .plt : { *(.plt) } + + .ctors : ALIGN(8) { + __ctor_list = .; + KEEP(*(.ctors .ctors.* .init_array .init_array.*)) + __ctor_end = .; + } + .dtors : ALIGN(8) { + __dtor_list = .; + KEEP(*(.dtors .dtors.* .fini_array .fini_array.*)) + __dtor_end = .; + } + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } + + .ARM.extab : { + __extab_start = .; + *(.ARM.extab*) + __extab_end = .; + } + + /* Start page aligned read-write memory */ +#ifdef CFG_CORE_RWDATA_NOEXEC + . = ALIGN(SMALL_PAGE_SIZE); +#endif + __flatmap_unpg_ro_size = . - __flatmap_unpg_ro_start; + +#ifdef CFG_NS_VIRTUALIZATION + __flatmap_nex_rw_start = . ; + .nex_data : ALIGN(8) { + *(.nex_data .nex_data.*) + } + + .nex_bss : ALIGN(8) { + __nex_bss_start = .; + *(.nex_bss .nex_bss.*) + __nex_bss_end = .; + } + + /* + * We want to keep all nexus memory in one place, because + * it should be always mapped and it is easier to map one + * memory region than two. + * Next section are NOLOAD ones, but they are followed + * by sections with data. Thus, this NOLOAD section will + * be included in the resulting binary, filled with zeroes + */ + .nex_stack (NOLOAD) : { + __nozi_stack_start = .; + KEEP(*(.nozi_stack.stack_tmp .nozi_stack.stack_abt)) + . = ALIGN(8); + __nozi_stack_end = .; + } + + .nex_heap (NOLOAD) : { + __nex_heap_start = .; + . += CFG_CORE_NEX_HEAP_SIZE; + . = ALIGN(16 * 1024); + __nex_heap_end = .; + } + .nex_nozi (NOLOAD) : { + ASSERT(!(ABSOLUTE(.) & (16 * 1024 - 1)), "align nozi to 16kB"); + KEEP(*(.nozi.mmu.base_table .nozi.mmu.l2)) + } + + . = ALIGN(SMALL_PAGE_SIZE); + + __flatmap_nex_rw_size = . - __flatmap_nex_rw_start; + __flatmap_nex_rw_end = .; +#endif + + __flatmap_unpg_rw_start = .; + + .data : ALIGN(8) { + /* writable data */ + __data_start_rom = .; + /* in one segment binaries, the rom data address is on top + of the ram data address */ + __data_start = .; + *(.data .data.* .gnu.linkonce.d.*) + . = ALIGN(8); + } + + /* unintialized data */ + .bss : { + __data_end = .; + __bss_start = .; + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + __bss_end = .; + } + + .heap1 (NOLOAD) : { + /* + * We're keeping track of the padding added before the + * .nozi section so we can do something useful with + * this otherwise wasted memory. + */ + __heap1_start = .; +#ifndef CFG_WITH_PAGER + . += CFG_CORE_HEAP_SIZE; +#endif +#ifdef CFG_WITH_LPAE + . = ALIGN(4 * 1024); +#else + . = ALIGN(16 * 1024); +#endif + __heap1_end = .; + } + /* + * Uninitialized data that shouldn't be zero initialized at + * runtime. + * + * L1 mmu table requires 16 KiB alignment + */ + .nozi (NOLOAD) : { + __nozi_start = .; + KEEP(*(.nozi .nozi.*)) + . = ALIGN(16); + __nozi_end = .; + /* + * If virtualization is enabled, abt and tmp stacks will placed + * at above .nex_stack section and thread stacks will go there + */ + __nozi_stack_start = .; + KEEP(*(.nozi_stack .nozi_stack.*)) + . = ALIGN(8); + __nozi_stack_end = .; + } + +#ifdef CFG_WITH_PAGER + .heap2 (NOLOAD) : { + __heap2_start = .; + /* + * Reserve additional memory for heap, the total should be + * at least CFG_CORE_HEAP_SIZE, but count what has already + * been reserved in .heap1 + */ + . += CFG_CORE_HEAP_SIZE - (__heap1_end - __heap1_start); + . = ALIGN(SMALL_PAGE_SIZE); + __heap2_end = .; + } + + /* Start page aligned read-only memory */ + __flatmap_unpg_rw_size = . - __flatmap_unpg_rw_start; + + __init_start = .; + __flatmap_init_rx_start = .; + + ASSERT(!(__flatmap_init_rx_start & (SMALL_PAGE_SIZE - 1)), + "read-write memory is not paged aligned") + + .text_init : { + __text_init_start = .; +/* + * Include list of sections needed for boot initialization, this list + * overlaps with unpaged.ld.S but since unpaged.ld.S is first all those + * sections will go into the unpaged area. + */ +#include + KEEP(*(.text.startup.*)); + /* Make sure constructor functions are available during init */ + KEEP(*(.text._GLOBAL__sub_*)); + . = ALIGN(8); + __text_init_end = .; + } + +#ifdef CFG_CORE_RODATA_NOEXEC + . = ALIGN(SMALL_PAGE_SIZE); +#endif + __flatmap_init_rx_size = . - __flatmap_init_rx_start; + __flatmap_init_ro_start = .; + + .rodata_init : { + __rodata_init_start = .; +#include +#ifndef CFG_CORE_ASLR + . = ALIGN(8); + KEEP(*(SORT(.scattered_array*))); +#endif + __rodata_init_end = .; + } +#ifdef CFG_CORE_ASLR + .data.rel.ro_init : ALIGN(8) { + KEEP(*(SORT(.scattered_array*))); + } +#endif + . = ALIGN(8); + __ro_and_relro_data_init_end = .; + + __init_end = ALIGN(__ro_and_relro_data_init_end, SMALL_PAGE_SIZE); + __get_tee_init_end = __init_end; + __init_size = __init_end - __init_start; + + /* vcore flat map stops here. No need to page align, rodata follows. */ + __flatmap_init_ro_size = __init_end - __flatmap_init_ro_start; + + .rodata_pageable : ALIGN(8) { + __rodata_pageable_start = .; + *(.rodata*) + __rodata_pageable_end = .; + } + +#ifdef CFG_CORE_RODATA_NOEXEC + . = ALIGN(SMALL_PAGE_SIZE); +#endif + + .text_pageable : ALIGN(8) { + __text_pageable_start = .; + *(.text*) + . = ALIGN(SMALL_PAGE_SIZE); + __text_pageable_end = .; + } + + __pageable_part_end = .; + __pageable_part_start = __init_end; + __pageable_start = __init_start; + __pageable_end = __pageable_part_end; + + ASSERT(TEE_LOAD_ADDR >= TEE_RAM_START, + "Load address before start of physical memory") + ASSERT(TEE_LOAD_ADDR < (TEE_RAM_START + TEE_RAM_PH_SIZE), + "Load address after end of physical memory") + ASSERT((TEE_RAM_START + TEE_RAM_PH_SIZE - __init_end) > + SMALL_PAGE_SIZE, "Too few free pages to initialize paging") + + +#endif /*CFG_WITH_PAGER*/ + +#ifdef CFG_CORE_SANITIZE_KADDRESS + . = TEE_RAM_START + (TEE_RAM_VA_SIZE * 8) / 9 - 8; + . = ALIGN(8); + .asan_shadow : { + __asan_shadow_start = .; + . += TEE_RAM_VA_SIZE / 9; + __asan_shadow_end = .; + __asan_shadow_size = __asan_shadow_end - __asan_shadow_start; + } +#endif /*CFG_CORE_SANITIZE_KADDRESS*/ + + __end = .; + +#ifndef CFG_WITH_PAGER + __init_size = __data_end - TEE_LOAD_ADDR; +#endif + /* + * Guard against moving the location counter backwards in the assignment + * below. + */ + ASSERT(. <= (TEE_RAM_START + TEE_RAM_VA_SIZE), + "TEE_RAM_VA_SIZE is too small") + . = TEE_RAM_START + TEE_RAM_VA_SIZE; + + _end_of_ram = .; + +#ifndef CFG_WITH_PAGER + __flatmap_unpg_rw_size = _end_of_ram - __flatmap_unpg_rw_start; + __get_tee_init_end = .; +#endif + + /* + * These regions will not become a normal part of the dumped + * binary, instead some are interpreted by the dump script and + * converted into suitable format for OP-TEE itself to use. + */ + .dynamic : { *(.dynamic) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + + .rel : { + *(.rel.*) + } + .rela : { + *(.rela.*) + } +#if !defined(CFG_CORE_ASLR) && !defined(CFG_CORE_PHYS_RELOCATABLE) + ASSERT(SIZEOF(.rel) == 0, "Relocation entries not expected") + ASSERT(SIZEOF(.rela) == 0, "Relocation entries not expected") +#endif + + /DISCARD/ : { + /* Strip unnecessary stuff */ + *(.comment .note .eh_frame .interp) + /* Strip meta variables */ + *(__keep_meta_vars*) + } + +} + +/* Unpaged read-only memories */ +__vcore_unpg_rx_start = __flatmap_unpg_rx_start; +__vcore_unpg_ro_start = __flatmap_unpg_ro_start; +#ifdef CFG_CORE_RODATA_NOEXEC +__vcore_unpg_rx_size = __flatmap_unpg_rx_size; +__vcore_unpg_ro_size = __flatmap_unpg_ro_size; +#else +__vcore_unpg_rx_size = __flatmap_unpg_rx_size + __flatmap_unpg_ro_size; +__vcore_unpg_ro_size = 0; +#endif +__vcore_unpg_rx_end = __vcore_unpg_rx_start + __vcore_unpg_rx_size; +__vcore_unpg_ro_end = __vcore_unpg_ro_start + __vcore_unpg_ro_size; + +/* Unpaged read-write memory */ +__vcore_unpg_rw_start = __flatmap_unpg_rw_start; +__vcore_unpg_rw_size = __flatmap_unpg_rw_size; +__vcore_unpg_rw_end = __vcore_unpg_rw_start + __vcore_unpg_rw_size; + +#ifdef CFG_NS_VIRTUALIZATION +/* Nexus read-write memory */ +__vcore_nex_rw_start = __flatmap_nex_rw_start; +__vcore_nex_rw_size = __flatmap_nex_rw_size; +__vcore_nex_rw_end = __vcore_nex_rw_start + __vcore_nex_rw_size; +#endif + +#ifdef CFG_WITH_PAGER +/* + * Core init mapping shall cover up to end of the physical RAM. + * This is required since the hash table is appended to the + * binary data after the firmware build sequence. + */ +#define __FLATMAP_PAGER_TRAILING_SPACE \ + (TEE_RAM_START + TEE_RAM_PH_SIZE - \ + (__flatmap_init_ro_start + __flatmap_init_ro_size)) + +/* Paged/init read-only memories */ +__vcore_init_rx_start = __flatmap_init_rx_start; +__vcore_init_ro_start = __flatmap_init_ro_start; +#ifdef CFG_CORE_RODATA_NOEXEC +__vcore_init_rx_size = __flatmap_init_rx_size; +__vcore_init_ro_size = __flatmap_init_ro_size + __FLATMAP_PAGER_TRAILING_SPACE; +#else +__vcore_init_rx_size = __flatmap_init_rx_size + __flatmap_init_ro_size + + __FLATMAP_PAGER_TRAILING_SPACE; +__vcore_init_ro_size = 0; +#endif /* CFG_CORE_RODATA_NOEXEC */ +__vcore_init_rx_end = __vcore_init_rx_start + __vcore_init_rx_size; +__vcore_init_ro_end = __vcore_init_ro_start + __vcore_init_ro_size; +#endif /* CFG_WITH_PAGER */ + +#ifdef CFG_CORE_SANITIZE_KADDRESS +__asan_map_start = (__asan_shadow_start / SMALL_PAGE_SIZE) * + SMALL_PAGE_SIZE; +__asan_map_end = ((__asan_shadow_end - 1) / SMALL_PAGE_SIZE) * + SMALL_PAGE_SIZE + SMALL_PAGE_SIZE; +__asan_map_size = __asan_map_end - __asan_map_start; +#endif /*CFG_CORE_SANITIZE_KADDRESS*/ diff --git a/optee/optee_os/core/arch/arm/kernel/link.mk b/optee/optee_os/core/arch/arm/kernel/link.mk new file mode 100644 index 0000000..49e9f4f --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/link.mk @@ -0,0 +1,263 @@ +link-out-dir = $(out-dir)/core + +link-script-dummy = $(arch-dir)/kernel/link_dummy.ld +link-script = $(if $(wildcard $(platform-dir)/kern.ld.S), \ + $(platform-dir)/kern.ld.S, \ + $(arch-dir)/kernel/kern.ld.S) +link-script-pp = $(link-out-dir)/kern.ld +link-script-dep = $(link-out-dir)/.kern.ld.d + +AWK = awk + +link-ldflags-common += $(call ld-option,--no-warn-rwx-segments) +ifeq ($(CFG_ARM32_core),y) +link-ldflags-common += $(call ld-option,--no-warn-execstack) +endif + +link-ldflags = $(LDFLAGS) +ifeq ($(call cfg-one-enabled, CFG_CORE_ASLR CFG_CORE_PHYS_RELOCATABLE),y) +link-ldflags += -pie -Bsymbolic -z norelro $(ldflag-apply-dynamic-relocs) +ifeq ($(CFG_ARM64_core),y) +link-ldflags += -z text +else +# Suppression of relocations in read-only segments has not been done yet +link-ldflags += -z notext +endif +endif +ifeq ($(CFG_CORE_BTI),y) +# force-bti tells the linker to warn if some object files lack the .note.gnu.property +# section with the BTI flag, and to turn on the BTI flag in the output anyway. The +# resulting executable would likely fail at runtime so we use this flag along +# with the --fatal-warnings below to check and prevent this situation (with useful +# diagnostics). +link-ldflags += $(call ld-option,-z force-bti) --fatal-warnings +endif +link-ldflags += -T $(link-script-pp) -Map=$(link-out-dir)/tee.map +link-ldflags += --sort-section=alignment +link-ldflags += --fatal-warnings +link-ldflags += --gc-sections +link-ldflags += $(link-ldflags-common) + +link-ldadd = $(LDADD) +link-ldadd += $(ldflags-external) +link-ldadd += $(libdeps) +link-objs := $(filter-out \ + $(out-dir)/$(platform-dir)/link_dummies_paged.o \ + $(out-dir)/$(platform-dir)/link_dummies_init.o \ + $(out-dir)/$(arch-dir)/kernel/link_dummies_paged.o \ + $(out-dir)/$(arch-dir)/kernel/link_dummies_init.o, \ + $(objs)) +link-objs-init := $(filter-out \ + $(out-dir)/$(platform-dir)/link_dummies_init.o \ + $(out-dir)/$(arch-dir)/kernel/link_dummies_init.o, \ + $(objs)) +ldargs-tee.elf := $(link-ldflags) $(link-objs) $(link-out-dir)/version.o \ + $(link-ldadd) $(libgcccore) + +link-script-cppflags := \ + $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \ + $(nostdinccore) $(CPPFLAGS) \ + $(addprefix -I,$(incdirscore) $(link-out-dir)) \ + $(cppflagscore)) + +ldargs-all_objs := -T $(link-script-dummy) --no-check-sections \ + $(link-ldflags-common) \ + $(link-objs) $(link-ldadd) $(libgcccore) +cleanfiles += $(link-out-dir)/all_objs.o +$(link-out-dir)/all_objs.o: $(objs) $(libdeps) $(MAKEFILE_LIST) + @$(cmd-echo-silent) ' LD $@' + $(q)$(LDcore) $(ldargs-all_objs) -o $@ + +cleanfiles += $(link-out-dir)/unpaged_entries.txt +$(link-out-dir)/unpaged_entries.txt: $(link-out-dir)/all_objs.o + @$(cmd-echo-silent) ' GEN $@' + $(q)$(NMcore) $< | \ + $(AWK) '/ ____keep_pager/ { printf "-u%s ", $$3 }' > $@ + +unpaged-ldargs := -T $(link-script-dummy) --no-check-sections --gc-sections \ + $(link-ldflags-common) +unpaged-ldadd := $(objs) $(link-ldadd) $(libgcccore) +cleanfiles += $(link-out-dir)/unpaged.o +$(link-out-dir)/unpaged.o: $(link-out-dir)/unpaged_entries.txt + @$(cmd-echo-silent) ' LD $@' + $(q)$(LDcore) $(unpaged-ldargs) \ + `cat $(link-out-dir)/unpaged_entries.txt` \ + $(unpaged-ldadd) -o $@ + +cleanfiles += $(link-out-dir)/text_unpaged.ld.S +$(link-out-dir)/text_unpaged.ld.S: $(link-out-dir)/unpaged.o + @$(cmd-echo-silent) ' GEN $@' + $(q)$(READELFcore) -S -W $< | \ + $(PYTHON3) ./scripts/gen_ld_sects.py .text. > $@ + +cleanfiles += $(link-out-dir)/rodata_unpaged.ld.S +$(link-out-dir)/rodata_unpaged.ld.S: $(link-out-dir)/unpaged.o + @$(cmd-echo-silent) ' GEN $@' + $(q)$(READELFcore) -S -W $< | \ + $(PYTHON3) ./scripts/gen_ld_sects.py .rodata. > $@ + + +cleanfiles += $(link-out-dir)/init_entries.txt +$(link-out-dir)/init_entries.txt: $(link-out-dir)/all_objs.o + @$(cmd-echo-silent) ' GEN $@' + $(q)$(NMcore) $< | \ + $(AWK) '/ ____keep_init/ { printf "-u%s ", $$3 }' > $@ + +init-ldargs := -T $(link-script-dummy) --no-check-sections --gc-sections \ + $(link-ldflags-common) +init-ldadd := $(link-objs-init) $(link-out-dir)/version.o $(link-ldadd) \ + $(libgcccore) +cleanfiles += $(link-out-dir)/init.o +$(link-out-dir)/init.o: $(link-out-dir)/init_entries.txt + $(call gen-version-o) + @$(cmd-echo-silent) ' LD $@' + $(q)$(LDcore) $(init-ldargs) \ + `cat $(link-out-dir)/init_entries.txt` \ + $(init-ldadd) -o $@ + +cleanfiles += $(link-out-dir)/text_init.ld.S +$(link-out-dir)/text_init.ld.S: $(link-out-dir)/init.o + @$(cmd-echo-silent) ' GEN $@' + $(q)$(READELFcore) -S -W $< | \ + $(PYTHON3) ./scripts/gen_ld_sects.py .text. > $@ + +cleanfiles += $(link-out-dir)/rodata_init.ld.S +$(link-out-dir)/rodata_init.ld.S: $(link-out-dir)/init.o + @$(cmd-echo-silent) ' GEN $@' + $(q)$(READELFcore) -S -W $< | $(PYTHON3) ./scripts/gen_ld_sects.py .rodata. > $@ + +-include $(link-script-dep) + +link-script-extra-deps += $(link-out-dir)/text_unpaged.ld.S +link-script-extra-deps += $(link-out-dir)/rodata_unpaged.ld.S +link-script-extra-deps += $(link-out-dir)/text_init.ld.S +link-script-extra-deps += $(link-out-dir)/rodata_init.ld.S +link-script-extra-deps += $(conf-file) +cleanfiles += $(link-script-pp) $(link-script-dep) +$(link-script-pp): $(link-script) $(link-script-extra-deps) + @$(cmd-echo-silent) ' CPP $@' + @mkdir -p $(dir $@) + $(q)$(CPPcore) -P -MT $@ -MD -MF $(link-script-dep) \ + $(link-script-cppflags) $< -o $@ + +define update-buildcount + @$(cmd-echo-silent) ' UPD $(1)' + $(q)if [ ! -f $(1) ]; then \ + mkdir -p $(dir $(1)); \ + echo 1 >$(1); \ + else \ + expr 0`cat $(1)` + 1 >$(1); \ + fi +endef + +# filter-out to workaround objdump warning +version-o-cflags = $(filter-out -g3,$(core-platform-cflags) \ + $(platform-cflags) $(cflagscore)) +# SOURCE_DATE_EPOCH defined for reproducible builds +ifneq ($(SOURCE_DATE_EPOCH),) +date-opts = -d @$(SOURCE_DATE_EPOCH) +endif +DATE_STR = `LC_ALL=C date -u $(date-opts)` +BUILD_COUNT_STR = `cat $(link-out-dir)/.buildcount` +CORE_CC_VERSION = `$(CCcore) -v 2>&1 | grep "version " | sed 's/ *$$//'` +define gen-version-o + $(call update-buildcount,$(link-out-dir)/.buildcount) + @$(cmd-echo-silent) ' GEN $(link-out-dir)/version.o' + $(q)echo -e "const char core_v_str[] =" \ + "\"$(TEE_IMPL_VERSION) \"" \ + "\"($(CORE_CC_VERSION)) \"" \ + "\"#$(BUILD_COUNT_STR) \"" \ + "\"$(DATE_STR) \"" \ + "\"$(CFG_KERN_LINKER_ARCH)\";\n" \ + | $(CCcore) $(version-o-cflags) \ + -xc - -c -o $(link-out-dir)/version.o +endef +$(link-out-dir)/version.o: + $(call gen-version-o) + +-include $(link-out-dir)/.tee.elf.cmd +define check-link-objs +$(if $(strip $(filter-out $(link-objs), $(old-link-objs)) + $(filter-out $(old-link-objs), $(link-objs))), FORCE_LINK := FORCE) +endef +$(eval $(call check-link-objs)) + +all: $(link-out-dir)/tee.elf +cleanfiles += $(link-out-dir)/tee.elf $(link-out-dir)/tee.map +cleanfiles += $(link-out-dir)/version.o +cleanfiles += $(link-out-dir)/.buildcount +cleanfiles += $(link-out-dir)/.tee.elf.cmd +$(link-out-dir)/tee.elf: $(link-objs) $(libdeps) $(link-script-pp) $(FORCE_LINK) + @echo "old-link-objs := $(link-objs)" >$(link-out-dir)/.tee.elf.cmd + @$(cmd-echo-silent) ' LD $@' + $(q)$(LDcore) $(ldargs-tee.elf) -o $@ + +all: $(link-out-dir)/tee.dmp +cleanfiles += $(link-out-dir)/tee.dmp +$(link-out-dir)/tee.dmp: $(link-out-dir)/tee.elf + @$(cmd-echo-silent) ' OBJDUMP $@' + $(q)$(OBJDUMPcore) -l -x -d $< > $@ + +cleanfiles += $(link-out-dir)/tee-pager.bin +$(link-out-dir)/tee-pager.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py + @echo Warning: $@ is deprecated + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_tee_pager_bin $@ + +cleanfiles += $(link-out-dir)/tee-pageable.bin +$(link-out-dir)/tee-pageable.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py + @echo Warning: $@ is deprecated + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_tee_pageable_bin $@ + +all: $(link-out-dir)/tee.bin +cleanfiles += $(link-out-dir)/tee.bin +$(link-out-dir)/tee.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_tee_bin $@ + +all: $(link-out-dir)/tee-header_v2.bin +cleanfiles += $(link-out-dir)/tee-header_v2.bin +$(link-out-dir)/tee-header_v2.bin: $(link-out-dir)/tee.elf \ + scripts/gen_tee_bin.py + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_header_v2 $@ + +all: $(link-out-dir)/tee-pager_v2.bin +cleanfiles += $(link-out-dir)/tee-pager_v2.bin +$(link-out-dir)/tee-pager_v2.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_pager_v2 $@ + +all: $(link-out-dir)/tee-pageable_v2.bin +cleanfiles += $(link-out-dir)/tee-pageable_v2.bin +$(link-out-dir)/tee-pageable_v2.bin: $(link-out-dir)/tee.elf \ + scripts/gen_tee_bin.py + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_pageable_v2 $@ + +all: $(link-out-dir)/tee.symb_sizes +cleanfiles += $(link-out-dir)/tee.symb_sizes +$(link-out-dir)/tee.symb_sizes: $(link-out-dir)/tee.elf + @$(cmd-echo-silent) ' GEN $@' + $(q)$(NMcore) --print-size --reverse-sort --size-sort $< > $@ + +cleanfiles += $(link-out-dir)/tee.mem_usage +ifneq ($(filter mem_usage,$(MAKECMDGOALS)),) +mem_usage: $(link-out-dir)/tee.mem_usage + +$(link-out-dir)/tee.mem_usage: $(link-out-dir)/tee.elf + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) ./scripts/mem_usage.py $< > $@ +endif + +all: $(link-out-dir)/tee-raw.bin +cleanfiles += $(link-out-dir)/tee-raw.bin +$(link-out-dir)/tee-raw.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py + @$(cmd-echo-silent) ' GEN $@' + $(q)scripts/gen_tee_bin.py --input $< --out_tee_raw_bin $@ + +cleanfiles += $(link-out-dir)/tee.srec +$(link-out-dir)/tee.srec: $(link-out-dir)/tee-raw.bin + @$(cmd-echo-silent) ' SREC $@' + $(q)$(OBJCOPYcore) -I binary -O srec $(SRECFLAGS) $< $@ diff --git a/optee/optee_os/core/arch/arm/kernel/link_dummies_init.c b/optee/optee_os/core/arch/arm/kernel/link_dummies_init.c new file mode 100644 index 0000000..5c90271 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/link_dummies_init.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + */ +#include +#include +#include + +void __section(".text.dummy.boot_save_boot_info") +boot_save_boot_info(void *boot_info __unused) +{ +} + +unsigned long __section(".text.dummy.get_aslr_seed") +get_aslr_seed(void *fdt __unused) +{ + return 0; +} + +void __section(".text.dummy.core_init_mmu_map") +core_init_mmu_map(unsigned long seed __unused, + struct core_mmu_config *cfg __unused) +{ +} + +void __section(".text.dummy.boot_init_primary_early") +boot_init_primary_early(unsigned long pageable_part __unused, + unsigned long nsec_entry __unused) +{ +} diff --git a/optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c b/optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c new file mode 100644 index 0000000..023a5f3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/link_dummies_paged.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2021, Linaro Limited + * Copyright (c) 2023, Arm Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void __section(".text.dummy.call_preinitcalls") call_preinitcalls(void) +{ +} + +void __section(".text.dummy.call_initcalls") call_initcalls(void) +{ +} + +void __section(".text.dummy.call_finalcalls") call_finalcalls(void) +{ +} + +void __section(".text.dummy.boot_init_primary_late") +boot_init_primary_late(unsigned long fdt __unused, + unsigned long tos_fw_config __unused) +{ +} + +uint32_t __section(".text.dummy.__thread_std_smc_entry") +__thread_std_smc_entry(uint32_t a0 __unused, uint32_t a1 __unused, + uint32_t a2 __unused, uint32_t a3 __unused, + uint32_t a4 __unused, uint32_t a5 __unused) +{ + return 0; +} + +const struct mobj_ops mobj_reg_shm_ops __rodata_dummy; +const struct mobj_ops mobj_phys_ops __rodata_dummy; +const struct mobj_ops mobj_virt_ops __rodata_dummy; +const struct mobj_ops mobj_mm_ops __rodata_dummy; +const struct mobj_ops mobj_shm_ops __rodata_dummy; +const struct mobj_ops mobj_seccpy_shm_ops __rodata_dummy; +const struct mobj_ops mobj_with_fobj_ops __rodata_dummy; +const struct fobj_ops ops_rwp_paged_iv __rodata_dummy; +const struct fobj_ops ops_rwp_unpaged_iv __rodata_dummy; +const struct fobj_ops ops_ro_paged __rodata_dummy; +const struct fobj_ops ops_ro_reloc_paged __rodata_dummy; +const struct fobj_ops ops_locked_paged __rodata_dummy; +const struct fobj_ops ops_sec_mem __rodata_dummy; +const struct ts_ops user_ta_ops __rodata_dummy; +const struct ts_ops stmm_sp_ops __rodata_dummy; diff --git a/optee/optee_os/core/arch/arm/kernel/link_dummy.ld b/optee/optee_os/core/arch/arm/kernel/link_dummy.ld new file mode 100644 index 0000000..1393088 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/link_dummy.ld @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +SECTIONS +{ + /* + * This seems to make the ARMv7 linker happy with regards to glue_7 + * sections etc. + */ + ..dummy : { } +} + +__asan_map_end = .; +__asan_map_size = .; +__asan_map_start = .; +__asan_shadow_end = .; +__asan_shadow_size = .; +__asan_shadow_start = .; +__bss_end = .; +__bss_start = .; +__ctor_end = .; +__ctor_list = .; +__data_end = .; +__data_start = .; +__end = .; +__end_phys_ddr_overall_section = .; +__end_phys_mem_map_section = .; +__end_phys_nsec_ddr_section = .; +__end_phys_sdp_mem_section = .; +__exidx_end = .; +__exidx_start = .; +__extab_end = .; +__extab_start = .; +__heap1_end = .; +__heap1_start = .; +__heap2_end = .; +__heap2_start = .; +__identity_map_init_end = .; +__identity_map_init_start = .; +__initcall_end = .; +__initcall_start = .; +__init_end = .; +__init_size = .; +__init_start = .; +__nex_bss_end = .; +__nex_bss_start = .; +__nex_heap_end = .; +__nex_heap_start = .; +__nozi_end = .; +__nozi_stack_end = .; +__nozi_stack_start = .; +__nozi_start = .; +__pageable_end = .; +__pageable_part_end = .; +__pageable_part_start = .; +__pageable_start = .; +__rela_end = .; +__rela_start = .; +__rel_end = .; +__rel_start = .; +__ro_and_relro_data_init_end = .; +__rodata_early_ta_end = .; +__rodata_early_ta_start = .; +__rodata_end = .; +__rodata_init_end = .; +__rodata_init_start = .; +__rodata_pageable_end = .; +__rodata_pageable_start = .; +__rodata_start = .; +__start_phys_ddr_overall_section = .; +__start_phys_nsec_ddr_section = .; +__text_init_end = .; +__text_init_start = .; +__text_pageable_end = .; +__text_pageable_start = .; +__text_start = .; +__text_data_start = .; +__text_data_end = .; +__text_end = .; +__tmp_hashes_end = .; +__tmp_hashes_size = .; +__tmp_hashes_start = .; +__vcore_init_ro_end = .; +__vcore_init_ro_size = .; +__vcore_init_ro_start = .; +__vcore_init_rx_end = .; +__vcore_init_rx_size = .; +__vcore_init_rx_start = .; +__vcore_nex_rw_end = .; +__vcore_nex_rw_size = .; +__vcore_nex_rw_start = .; +__vcore_unpg_ro_end = .; +__vcore_unpg_ro_size = .; +__vcore_unpg_ro_start = .; +__vcore_unpg_rw_end = .; +__vcore_unpg_rw_size = .; +__vcore_unpg_rw_start = .; +__vcore_unpg_rx_end = .; +__vcore_unpg_rx_size = .; +__vcore_unpg_rx_start = .; +PROVIDE(core_v_str = 0); +PROVIDE(tee_entry_std = 0); +PROVIDE(init_teecore = 0); diff --git a/optee/optee_os/core/arch/arm/kernel/misc_a32.S b/optee/optee_os/core/arch/arm/kernel/misc_a32.S new file mode 100644 index 0000000..13983da --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/misc_a32.S @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2019, Arm Limited. All rights reserved. + */ + +#include +#include +#include +#include + + +/* size_t __get_core_pos(void); */ +FUNC __get_core_pos , : , .identity_map + read_mpidr r0 + b get_core_pos_mpidr +END_FUNC __get_core_pos + +/* size_t get_core_pos_mpidr(uint32_t mpidr); */ +/* Let platforms override this if needed */ +WEAK_FUNC get_core_pos_mpidr , : + mov r3, r0 + + /* + * Shift MPIDR value if it's not already shifted. + * Using logical shift ensures AFF0 to be filled with zeroes. + * This part is necessary even if CFG_CORE_THREAD_SHIFT is 0 because + * MT bit can be set on single threaded systems where all the AFF0 + * values are zeroes. + */ + tst r0, #MPIDR_MT_MASK + lsleq r3, r0, #MPIDR_AFFINITY_BITS + + /* + * At this point the MPIDR layout is always shifted so it looks + * as follows AFF2 -> cluster, AFF1 -> core, AFF0 -> thread + */ +#if CFG_CORE_THREAD_SHIFT == 0 + /* Calculate CorePos = (ClusterId * (cores/cluster)) + CoreId */ + ubfx r0, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + add r0, r0, r1, LSL #(CFG_CORE_CLUSTER_SHIFT) +#else + /* + * Calculate CorePos = + * ((ClusterId * (cores/cluster)) + CoreId) * (threads/core) + ThreadId + */ + ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + add r1, r1, r2, LSL #(CFG_CORE_CLUSTER_SHIFT) + add r0, r0, r1, LSL #(CFG_CORE_THREAD_SHIFT) +#endif + + bx lr +END_FUNC get_core_pos_mpidr + +/* + * uint32_t temp_set_mode(int cpu_mode) + * returns cpsr to be set + */ +LOCAL_FUNC temp_set_mode , : + mov r1, r0 + cmp r1, #CPSR_MODE_USR /* update mode: usr -> sys */ + moveq r1, #CPSR_MODE_SYS + cpsid aif /* disable interrupts */ + mrs r0, cpsr /* get cpsr with disabled its*/ + bic r0, #CPSR_MODE_MASK /* clear mode */ + orr r0, r1 /* set expected mode */ + bx lr +END_FUNC temp_set_mode + +/* uint32_t read_mode_sp(int cpu_mode) */ +FUNC read_mode_sp , : + push {r4, lr} +UNWIND( .save {r4, lr}) + mrs r4, cpsr /* save cpsr */ + bl temp_set_mode + msr cpsr, r0 /* set the new mode */ + mov r0, sp /* get the function result */ + msr cpsr, r4 /* back to the old mode */ + pop {r4, pc} +END_FUNC read_mode_sp + +/* uint32_t read_mode_lr(int cpu_mode) */ +FUNC read_mode_lr , : + push {r4, lr} +UNWIND( .save {r4, lr}) + mrs r4, cpsr /* save cpsr */ + bl temp_set_mode + msr cpsr, r0 /* set the new mode */ + mov r0, lr /* get the function result */ + msr cpsr, r4 /* back to the old mode */ + pop {r4, pc} +END_FUNC read_mode_lr + +/* void wait_cycles(unsigned long cycles) */ +FUNC wait_cycles , : + /* Divide by 4 since each loop will take 4 cycles to complete */ + lsrs r0, r0, #2 + bxeq lr +loop: + subs r0, r0, #1 + nop + bne loop + + bx lr +END_FUNC wait_cycles diff --git a/optee/optee_os/core/arch/arm/kernel/misc_a64.S b/optee/optee_os/core/arch/arm/kernel/misc_a64.S new file mode 100644 index 0000000..3e70a0d --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/misc_a64.S @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2019, Arm Limited. All rights reserved. + */ + +#include +#include +#include + +/* size_t __get_core_pos(void); */ +FUNC __get_core_pos , : , .identity_map + mrs x0, mpidr_el1 + b get_core_pos_mpidr +END_FUNC __get_core_pos + +/* size_t get_core_pos_mpidr(uint32_t mpidr); */ +/* Let platforms override this if needed */ +WEAK_FUNC get_core_pos_mpidr , : + /* + * Shift MPIDR value if it's not already shifted. + * Using logical shift ensures AFF0 to be filled with zeroes. + * This part is necessary even if CFG_CORE_THREAD_SHIFT is 0 because + * MT bit can be set on single threaded systems where all the AFF0 + * values are zeroes. + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* + * At this point the MPIDR layout is always shifted so it looks + * as follows AFF2 -> cluster, AFF1 -> core, AFF0 -> thread + */ +#if CFG_CORE_THREAD_SHIFT == 0 + /* Calculate CorePos = (ClusterId * (cores/cluster)) + CoreId */ + ubfx x0, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + add x0, x0, x1, LSL #(CFG_CORE_CLUSTER_SHIFT) +#else + /* + * Calculate CorePos = + * ((ClusterId * (cores/cluster)) + CoreId) * (threads/core) + ThreadId + */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + add x1, x1, x2, LSL #(CFG_CORE_CLUSTER_SHIFT) + add x0, x0, x1, LSL #(CFG_CORE_THREAD_SHIFT) +#endif + + ret +END_FUNC get_core_pos_mpidr + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/rpc_io_i2c.c b/optee/optee_os/core/arch/arm/kernel/rpc_io_i2c.c new file mode 100644 index 0000000..439ab9a --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/rpc_io_i2c.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020 Foundries Ltd + */ +#include +#include +#include +#include + +/* + * @brief: I2C master transfer request to an I2C slave device. + * It is the responsibility of the caller to validate the number of bytes + * processed by the REE. + * + * @param req: the secure world I2C master request + * @param len: the number of bytes processed by REE + * @returns: TEE_SUCCESS on success, TEE_ERROR_XXX on error. + */ +TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *req, size_t *len) +{ + struct thread_param p[4] = { }; + TEE_Result res = TEE_SUCCESS; + struct mobj *mobj = NULL; + uint8_t *va = NULL; + + assert(req); + + if (!len) + return TEE_ERROR_BAD_PARAMETERS; + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_I2C, + THREAD_SHM_TYPE_KERNEL_PRIVATE, + req->buffer_len, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + if (req->mode == RPC_I2C_MODE_WRITE) + memcpy(va, req->buffer, req->buffer_len); + + p[0] = THREAD_PARAM_VALUE(IN, req->mode, req->bus, req->chip); + p[1] = THREAD_PARAM_VALUE(IN, req->flags, 0, 0); + p[2] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, req->buffer_len); + p[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_I2C_TRANSFER, ARRAY_SIZE(p), p); + if (res != TEE_SUCCESS) + return res; + + /* + * Reporting more bytes than supplied or requested from the I2C chip is + * an REE error + */ + if (p[3].u.value.a > req->buffer_len) + return TEE_ERROR_EXCESS_DATA; + + *len = p[3].u.value.a; + + if (req->mode == RPC_I2C_MODE_READ) + memcpy(req->buffer, va, *len); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/arch/arm/kernel/secure_partition.c b/optee/optee_os/core/arch/arm/kernel/secure_partition.c new file mode 100644 index 0000000..85ad2d0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/secure_partition.c @@ -0,0 +1,1648 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020-2023, Arm Limited. + */ +#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 +#include +#include +#include + +#define SP_MANIFEST_ATTR_READ BIT(0) +#define SP_MANIFEST_ATTR_WRITE BIT(1) +#define SP_MANIFEST_ATTR_EXEC BIT(2) +#define SP_MANIFEST_ATTR_NSEC BIT(3) + +#define SP_MANIFEST_ATTR_RO (SP_MANIFEST_ATTR_READ) +#define SP_MANIFEST_ATTR_RW (SP_MANIFEST_ATTR_READ | \ + SP_MANIFEST_ATTR_WRITE) +#define SP_MANIFEST_ATTR_RX (SP_MANIFEST_ATTR_READ | \ + SP_MANIFEST_ATTR_EXEC) +#define SP_MANIFEST_ATTR_RWX (SP_MANIFEST_ATTR_READ | \ + SP_MANIFEST_ATTR_WRITE | \ + SP_MANIFEST_ATTR_EXEC) + +#define SP_MANIFEST_FLAG_NOBITS BIT(0) + +#define SP_PKG_HEADER_MAGIC (0x474b5053) +#define SP_PKG_HEADER_VERSION_V1 (0x1) +#define SP_PKG_HEADER_VERSION_V2 (0x2) + +struct sp_pkg_header { + uint32_t magic; + uint32_t version; + uint32_t pm_offset; + uint32_t pm_size; + uint32_t img_offset; + uint32_t img_size; +}; + +struct fip_sp_head fip_sp_list = STAILQ_HEAD_INITIALIZER(fip_sp_list); + +static const struct ts_ops sp_ops; + +/* List that holds all of the loaded SP's */ +static struct sp_sessions_head open_sp_sessions = + TAILQ_HEAD_INITIALIZER(open_sp_sessions); + +static const struct embedded_ts *find_secure_partition(const TEE_UUID *uuid) +{ + const struct sp_image *sp = NULL; + const struct fip_sp *fip_sp = NULL; + + for_each_secure_partition(sp) { + if (!memcmp(&sp->image.uuid, uuid, sizeof(*uuid))) + return &sp->image; + } + + for_each_fip_sp(fip_sp) { + if (!memcmp(&fip_sp->sp_img.image.uuid, uuid, sizeof(*uuid))) + return &fip_sp->sp_img.image; + } + + return NULL; +} + +bool is_sp_ctx(struct ts_ctx *ctx) +{ + return ctx && (ctx->ops == &sp_ops); +} + +static void set_sp_ctx_ops(struct ts_ctx *ctx) +{ + ctx->ops = &sp_ops; +} + +struct sp_session *sp_get_session(uint32_t session_id) +{ + struct sp_session *s = NULL; + + TAILQ_FOREACH(s, &open_sp_sessions, link) { + if (s->endpoint_id == session_id) + return s; + } + + return NULL; +} + +TEE_Result sp_partition_info_get(struct ffa_partition_info *fpi, + const TEE_UUID *ffa_uuid, size_t *elem_count) +{ + size_t in_count = *elem_count; + struct sp_session *s = NULL; + size_t count = 0; + + TAILQ_FOREACH(s, &open_sp_sessions, link) { + if (ffa_uuid && + memcmp(&s->ffa_uuid, ffa_uuid, sizeof(*ffa_uuid))) + continue; + + if (s->state == sp_dead) + continue; + if (count < in_count) { + spmc_fill_partition_entry(fpi, s->endpoint_id, 1); + fpi++; + } + count++; + } + + *elem_count = count; + if (count > in_count) + return TEE_ERROR_SHORT_BUFFER; + + return TEE_SUCCESS; +} + +bool sp_has_exclusive_access(struct sp_mem_map_region *mem, + struct user_mode_ctx *uctx) +{ + /* + * Check that we have access to the region if it is supposed to be + * mapped to the current context. + */ + if (uctx) { + struct vm_region *region = NULL; + + /* Make sure that each mobj belongs to the SP */ + TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { + if (region->mobj == mem->mobj) + break; + } + + if (!region) + return false; + } + + /* Check that it is not shared with another SP */ + return !sp_mem_is_shared(mem); +} + +static uint16_t new_session_id(struct sp_sessions_head *open_sessions) +{ + struct sp_session *last = NULL; + uint16_t id = SPMC_ENDPOINT_ID + 1; + + last = TAILQ_LAST(open_sessions, sp_sessions_head); + if (last) + id = last->endpoint_id + 1; + + assert(id > SPMC_ENDPOINT_ID); + return id; +} + +static TEE_Result sp_create_ctx(const TEE_UUID *bin_uuid, struct sp_session *s) +{ + TEE_Result res = TEE_SUCCESS; + struct sp_ctx *spc = NULL; + + /* Register context */ + spc = calloc(1, sizeof(struct sp_ctx)); + if (!spc) + return TEE_ERROR_OUT_OF_MEMORY; + + spc->open_session = s; + s->ts_sess.ctx = &spc->ts_ctx; + spc->ts_ctx.uuid = *bin_uuid; + + res = vm_info_init(&spc->uctx, &spc->ts_ctx); + if (res) + goto err; + + set_sp_ctx_ops(&spc->ts_ctx); + + return TEE_SUCCESS; + +err: + free(spc); + return res; +} + +static TEE_Result sp_create_session(struct sp_sessions_head *open_sessions, + const TEE_UUID *bin_uuid, + struct sp_session **sess) +{ + TEE_Result res = TEE_SUCCESS; + struct sp_session *s = calloc(1, sizeof(struct sp_session)); + + if (!s) + return TEE_ERROR_OUT_OF_MEMORY; + + s->endpoint_id = new_session_id(open_sessions); + if (!s->endpoint_id) { + res = TEE_ERROR_OVERFLOW; + goto err; + } + + DMSG("Loading Secure Partition %pUl", (void *)bin_uuid); + res = sp_create_ctx(bin_uuid, s); + if (res) + goto err; + + TAILQ_INSERT_TAIL(open_sessions, s, link); + *sess = s; + return TEE_SUCCESS; + +err: + free(s); + return res; +} + +static TEE_Result sp_init_set_registers(struct sp_ctx *ctx) +{ + struct thread_ctx_regs *sp_regs = &ctx->sp_regs; + + memset(sp_regs, 0, sizeof(*sp_regs)); + sp_regs->sp = ctx->uctx.stack_ptr; + sp_regs->pc = ctx->uctx.entry_func; + + return TEE_SUCCESS; +} + +TEE_Result sp_map_shared(struct sp_session *s, + struct sp_mem_receiver *receiver, + struct sp_mem *smem, + uint64_t *va) +{ + TEE_Result res = TEE_SUCCESS; + struct sp_ctx *ctx = NULL; + uint32_t perm = TEE_MATTR_UR; + struct sp_mem_map_region *reg = NULL; + + ctx = to_sp_ctx(s->ts_sess.ctx); + + /* Get the permission */ + if (receiver->perm.perm & FFA_MEM_ACC_EXE) + perm |= TEE_MATTR_UX; + + if (receiver->perm.perm & FFA_MEM_ACC_RW) { + if (receiver->perm.perm & FFA_MEM_ACC_EXE) + return TEE_ERROR_ACCESS_CONFLICT; + + perm |= TEE_MATTR_UW; + } + /* + * Currently we don't support passing a va. We can't guarantee that the + * full region will be mapped in a contiguous region. A smem->region can + * have multiple mobj for one share. Currently there doesn't seem to be + * an option to guarantee that these will be mapped in a contiguous va + * space. + */ + if (*va) + return TEE_ERROR_NOT_SUPPORTED; + + SLIST_FOREACH(reg, &smem->regions, link) { + res = vm_map(&ctx->uctx, va, reg->page_count * SMALL_PAGE_SIZE, + perm, 0, reg->mobj, reg->page_offset); + + if (res != TEE_SUCCESS) { + EMSG("Failed to map memory region %#"PRIx32, res); + return res; + } + } + return TEE_SUCCESS; +} + +TEE_Result sp_unmap_ffa_regions(struct sp_session *s, struct sp_mem *smem) +{ + TEE_Result res = TEE_SUCCESS; + vaddr_t vaddr = 0; + size_t len = 0; + struct sp_ctx *ctx = to_sp_ctx(s->ts_sess.ctx); + struct sp_mem_map_region *reg = NULL; + + SLIST_FOREACH(reg, &smem->regions, link) { + vaddr = (vaddr_t)sp_mem_get_va(&ctx->uctx, reg->page_offset, + reg->mobj); + len = reg->page_count * SMALL_PAGE_SIZE; + + res = vm_unmap(&ctx->uctx, vaddr, len); + if (res != TEE_SUCCESS) + return res; + } + + return TEE_SUCCESS; +} + +static TEE_Result sp_dt_get_u64(const void *fdt, int node, const char *property, + uint64_t *value) +{ + const fdt64_t *p = NULL; + int len = 0; + + p = fdt_getprop(fdt, node, property, &len); + if (!p) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (len != sizeof(*p)) + return TEE_ERROR_BAD_FORMAT; + + *value = fdt64_ld(p); + + return TEE_SUCCESS; +} + +static TEE_Result sp_dt_get_u32(const void *fdt, int node, const char *property, + uint32_t *value) +{ + const fdt32_t *p = NULL; + int len = 0; + + p = fdt_getprop(fdt, node, property, &len); + if (!p) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (len != sizeof(*p)) + return TEE_ERROR_BAD_FORMAT; + + *value = fdt32_to_cpu(*p); + + return TEE_SUCCESS; +} + +static TEE_Result sp_dt_get_uuid(const void *fdt, int node, + const char *property, TEE_UUID *uuid) +{ + uint32_t uuid_array[4] = { 0 }; + const fdt32_t *p = NULL; + int len = 0; + int i = 0; + + p = fdt_getprop(fdt, node, property, &len); + if (!p) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (len != sizeof(TEE_UUID)) + return TEE_ERROR_BAD_FORMAT; + + for (i = 0; i < 4; i++) + uuid_array[i] = fdt32_to_cpu(p[i]); + + tee_uuid_from_octets(uuid, (uint8_t *)uuid_array); + + return TEE_SUCCESS; +} + +static TEE_Result sp_is_elf_format(const void *fdt, int sp_node, + bool *is_elf_format) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t elf_format = 0; + + res = sp_dt_get_u32(fdt, sp_node, "elf-format", &elf_format); + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) + return res; + + *is_elf_format = (elf_format != 0); + + return TEE_SUCCESS; +} + +static TEE_Result sp_binary_open(const TEE_UUID *uuid, + const struct ts_store_ops **ops, + struct ts_store_handle **handle) +{ + TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; + + SCATTERED_ARRAY_FOREACH(*ops, sp_stores, struct ts_store_ops) { + res = (*ops)->open(uuid, handle); + if (res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + break; + } + + return res; +} + +static TEE_Result load_binary_sp(struct ts_session *s, + struct user_mode_ctx *uctx) +{ + size_t bin_size = 0, bin_size_rounded = 0, bin_page_count = 0; + const struct ts_store_ops *store_ops = NULL; + struct ts_store_handle *handle = NULL; + TEE_Result res = TEE_SUCCESS; + tee_mm_entry_t *mm = NULL; + struct mobj *mobj = NULL; + uaddr_t base_addr = 0; + uint32_t vm_flags = 0; + unsigned int idx = 0; + vaddr_t va = 0; + + if (!s || !uctx) + return TEE_ERROR_BAD_PARAMETERS; + + DMSG("Loading raw binary format SP %pUl", &uctx->ts_ctx->uuid); + + vm_set_ctx(uctx->ts_ctx); + + /* Find TS store and open SP binary */ + res = sp_binary_open(&uctx->ts_ctx->uuid, &store_ops, &handle); + if (res != TEE_SUCCESS) { + EMSG("Failed to open SP binary"); + return res; + } + + /* Query binary size and calculate page count */ + res = store_ops->get_size(handle, &bin_size); + if (res != TEE_SUCCESS) + goto err; + + if (ROUNDUP_OVERFLOW(bin_size, SMALL_PAGE_SIZE, &bin_size_rounded)) { + res = TEE_ERROR_OVERFLOW; + goto err; + } + + bin_page_count = bin_size_rounded / SMALL_PAGE_SIZE; + + /* Allocate memory */ + mm = tee_mm_alloc(&tee_mm_sec_ddr, bin_size_rounded); + if (!mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + base_addr = tee_mm_get_smem(mm); + + /* Create mobj */ + mobj = sp_mem_new_mobj(bin_page_count, TEE_MATTR_MEM_TYPE_CACHED, true); + if (!mobj) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err_free_tee_mm; + } + + res = sp_mem_add_pages(mobj, &idx, base_addr, bin_page_count); + if (res) + goto err_free_mobj; + + /* Map memory area for the SP binary */ + res = vm_map(uctx, &va, bin_size_rounded, TEE_MATTR_URWX, + vm_flags, mobj, 0); + if (res) + goto err_free_mobj; + + /* Read SP binary into the previously mapped memory area */ + res = store_ops->read(handle, (void *)va, bin_size); + if (res) + goto err_unmap; + + /* Set memory protection to allow execution */ + res = vm_set_prot(uctx, va, bin_size_rounded, TEE_MATTR_UX); + if (res) + goto err_unmap; + + mobj_put(mobj); + store_ops->close(handle); + + /* The entry point must be at the beginning of the SP binary. */ + uctx->entry_func = va; + uctx->load_addr = va; + uctx->is_32bit = false; + + s->handle_scall = s->ctx->ops->handle_scall; + + return TEE_SUCCESS; + +err_unmap: + vm_unmap(uctx, va, bin_size_rounded); + +err_free_mobj: + mobj_put(mobj); + +err_free_tee_mm: + tee_mm_free(mm); + +err: + store_ops->close(handle); + + return res; +} + +static TEE_Result sp_open_session(struct sp_session **sess, + struct sp_sessions_head *open_sessions, + const TEE_UUID *ffa_uuid, + const TEE_UUID *bin_uuid, + const void *fdt) +{ + TEE_Result res = TEE_SUCCESS; + struct sp_session *s = NULL; + struct sp_ctx *ctx = NULL; + bool is_elf_format = false; + + if (!find_secure_partition(bin_uuid)) + return TEE_ERROR_ITEM_NOT_FOUND; + + res = sp_create_session(open_sessions, bin_uuid, &s); + if (res != TEE_SUCCESS) { + DMSG("sp_create_session failed %#"PRIx32, res); + return res; + } + + ctx = to_sp_ctx(s->ts_sess.ctx); + assert(ctx); + if (!ctx) + return TEE_ERROR_TARGET_DEAD; + *sess = s; + + ts_push_current_session(&s->ts_sess); + + res = sp_is_elf_format(fdt, 0, &is_elf_format); + if (res == TEE_SUCCESS) { + if (is_elf_format) { + /* Load the SP using ldelf. */ + ldelf_load_ldelf(&ctx->uctx); + res = ldelf_init_with_ldelf(&s->ts_sess, &ctx->uctx); + } else { + /* Raw binary format SP */ + res = load_binary_sp(&s->ts_sess, &ctx->uctx); + } + } else { + EMSG("Failed to detect SP format"); + } + + if (res != TEE_SUCCESS) { + EMSG("Failed loading SP %#"PRIx32, res); + ts_pop_current_session(); + return TEE_ERROR_TARGET_DEAD; + } + + /* Make the SP ready for its first run */ + s->state = sp_idle; + s->caller_id = 0; + sp_init_set_registers(ctx); + memcpy(&s->ffa_uuid, ffa_uuid, sizeof(*ffa_uuid)); + ts_pop_current_session(); + + return TEE_SUCCESS; +} + +static TEE_Result fdt_get_uuid(const void * const fdt, TEE_UUID *uuid) +{ + const struct fdt_property *description = NULL; + int description_name_len = 0; + + if (fdt_node_check_compatible(fdt, 0, "arm,ffa-manifest-1.0")) { + EMSG("Failed loading SP, manifest not found"); + return TEE_ERROR_BAD_PARAMETERS; + } + + description = fdt_get_property(fdt, 0, "description", + &description_name_len); + if (description) + DMSG("Loading SP: %s", description->data); + + if (sp_dt_get_uuid(fdt, 0, "uuid", uuid)) { + EMSG("Missing or invalid UUID in SP manifest"); + return TEE_ERROR_BAD_FORMAT; + } + + return TEE_SUCCESS; +} + +/* + * sp_init_info allocates and maps the sp_ffa_init_info for the SP. It will copy + * the fdt into the allocated page(s) and return a pointer to the new location + * of the fdt. This pointer can be used to update data inside the fdt. + */ +static TEE_Result sp_init_info(struct sp_ctx *ctx, struct thread_smc_args *args, + const void * const input_fdt, vaddr_t *va, + size_t *num_pgs, void **fdt_copy) +{ + struct sp_ffa_init_info *info = NULL; + int nvp_count = 1; + size_t total_size = ROUNDUP(CFG_SP_INIT_INFO_MAX_SIZE, SMALL_PAGE_SIZE); + size_t nvp_size = sizeof(struct sp_name_value_pair) * nvp_count; + size_t info_size = sizeof(*info) + nvp_size; + size_t fdt_size = total_size - info_size; + TEE_Result res = TEE_SUCCESS; + uint32_t perm = TEE_MATTR_URW | TEE_MATTR_PRW; + struct fobj *f = NULL; + struct mobj *m = NULL; + static const char fdt_name[16] = "TYPE_DT\0\0\0\0\0\0\0\0"; + + *num_pgs = total_size / SMALL_PAGE_SIZE; + + f = fobj_sec_mem_alloc(*num_pgs); + m = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); + + fobj_put(f); + if (!m) + return TEE_ERROR_OUT_OF_MEMORY; + + res = vm_map(&ctx->uctx, va, total_size, perm, 0, m, 0); + mobj_put(m); + if (res) + return res; + + info = (struct sp_ffa_init_info *)*va; + + /* magic field is 4 bytes, we don't copy /0 byte. */ + memcpy(&info->magic, "FF-A", 4); + info->count = nvp_count; + args->a0 = (vaddr_t)info; + + /* + * Store the fdt after the boot_info and store the pointer in the + * first element. + */ + COMPILE_TIME_ASSERT(sizeof(info->nvp[0].name) == sizeof(fdt_name)); + memcpy(info->nvp[0].name, fdt_name, sizeof(fdt_name)); + info->nvp[0].value = *va + info_size; + info->nvp[0].size = fdt_size; + *fdt_copy = (void *)info->nvp[0].value; + + if (fdt_open_into(input_fdt, *fdt_copy, fdt_size)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result handle_fdt_load_relative_mem_regions(struct sp_ctx *ctx, + const void *fdt) +{ + int node = 0; + int subnode = 0; + tee_mm_entry_t *mm = NULL; + TEE_Result res = TEE_SUCCESS; + + /* + * Memory regions are optional in the SP manifest, it's not an error if + * we don't find any. + */ + node = fdt_node_offset_by_compatible(fdt, 0, + "arm,ffa-manifest-memory-regions"); + if (node < 0) + return TEE_SUCCESS; + + fdt_for_each_subnode(subnode, fdt, node) { + uint64_t load_rel_offset = 0; + uint32_t attributes = 0; + uint64_t base_addr = 0; + uint32_t pages_cnt = 0; + uint32_t flags = 0; + uint32_t perm = 0; + size_t size = 0; + vaddr_t va = 0; + + mm = NULL; + + /* Load address relative offset of a memory region */ + if (!sp_dt_get_u64(fdt, subnode, "load-address-relative-offset", + &load_rel_offset)) { + va = ctx->uctx.load_addr + load_rel_offset; + } else { + /* Skip non load address relative memory regions */ + continue; + } + + if (!sp_dt_get_u64(fdt, subnode, "base-address", &base_addr)) { + EMSG("Both base-address and load-address-relative-offset fields are set"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Size of memory region as count of 4K pages */ + if (sp_dt_get_u32(fdt, subnode, "pages-count", &pages_cnt)) { + EMSG("Mandatory field is missing: pages-count"); + return TEE_ERROR_BAD_FORMAT; + } + + if (MUL_OVERFLOW(pages_cnt, SMALL_PAGE_SIZE, &size)) + return TEE_ERROR_OVERFLOW; + + /* Memory region attributes */ + if (sp_dt_get_u32(fdt, subnode, "attributes", &attributes)) { + EMSG("Mandatory field is missing: attributes"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Check instruction and data access permissions */ + switch (attributes & SP_MANIFEST_ATTR_RWX) { + case SP_MANIFEST_ATTR_RO: + perm = TEE_MATTR_UR; + break; + case SP_MANIFEST_ATTR_RW: + perm = TEE_MATTR_URW; + break; + case SP_MANIFEST_ATTR_RX: + perm = TEE_MATTR_URX; + break; + default: + EMSG("Invalid memory access permissions"); + return TEE_ERROR_BAD_FORMAT; + } + + res = sp_dt_get_u32(fdt, subnode, "load-flags", &flags); + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) { + EMSG("Optional field with invalid value: flags"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Load relative regions must be secure */ + if (attributes & SP_MANIFEST_ATTR_NSEC) { + EMSG("Invalid memory security attribute"); + return TEE_ERROR_BAD_FORMAT; + } + + if (flags & SP_MANIFEST_FLAG_NOBITS) { + /* + * NOBITS flag is set, which means that loaded binary + * doesn't contain this area, so it's need to be + * allocated. + */ + struct mobj *m = NULL; + unsigned int idx = 0; + + mm = tee_mm_alloc(&tee_mm_sec_ddr, size); + if (!mm) + return TEE_ERROR_OUT_OF_MEMORY; + + base_addr = tee_mm_get_smem(mm); + + m = sp_mem_new_mobj(pages_cnt, + TEE_MATTR_MEM_TYPE_CACHED, true); + if (!m) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err_mm_free; + } + + res = sp_mem_add_pages(m, &idx, base_addr, pages_cnt); + if (res) { + mobj_put(m); + goto err_mm_free; + } + + res = vm_map(&ctx->uctx, &va, size, perm, 0, m, 0); + mobj_put(m); + if (res) + goto err_mm_free; + } else { + /* + * If NOBITS is not present the memory area is already + * mapped and only need to set the correct permissions. + */ + res = vm_set_prot(&ctx->uctx, va, size, perm); + if (res) + return res; + } + } + + return TEE_SUCCESS; + +err_mm_free: + tee_mm_free(mm); + return res; +} + +static TEE_Result handle_fdt_dev_regions(struct sp_ctx *ctx, void *fdt) +{ + int node = 0; + int subnode = 0; + TEE_Result res = TEE_SUCCESS; + const char *dt_device_match_table = { + "arm,ffa-manifest-device-regions", + }; + + /* + * Device regions are optional in the SP manifest, it's not an error if + * we don't find any + */ + node = fdt_node_offset_by_compatible(fdt, 0, dt_device_match_table); + if (node < 0) + return TEE_SUCCESS; + + fdt_for_each_subnode(subnode, fdt, node) { + uint64_t base_addr = 0; + uint32_t pages_cnt = 0; + uint32_t attributes = 0; + struct mobj *m = NULL; + bool is_secure = true; + uint32_t perm = 0; + vaddr_t va = 0; + unsigned int idx = 0; + + /* + * Physical base address of a device MMIO region. + * Currently only physically contiguous region is supported. + */ + if (sp_dt_get_u64(fdt, subnode, "base-address", &base_addr)) { + EMSG("Mandatory field is missing: base-address"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Total size of MMIO region as count of 4K pages */ + if (sp_dt_get_u32(fdt, subnode, "pages-count", &pages_cnt)) { + EMSG("Mandatory field is missing: pages-count"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Data access, instruction access and security attributes */ + if (sp_dt_get_u32(fdt, subnode, "attributes", &attributes)) { + EMSG("Mandatory field is missing: attributes"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Check instruction and data access permissions */ + switch (attributes & SP_MANIFEST_ATTR_RWX) { + case SP_MANIFEST_ATTR_RO: + perm = TEE_MATTR_UR; + break; + case SP_MANIFEST_ATTR_RW: + perm = TEE_MATTR_URW; + break; + default: + EMSG("Invalid memory access permissions"); + return TEE_ERROR_BAD_FORMAT; + } + + /* + * The SP is a secure endpoint, security attribute can be + * secure or non-secure + */ + if (attributes & SP_MANIFEST_ATTR_NSEC) + is_secure = false; + + /* Memory attributes must be Device-nGnRnE */ + m = sp_mem_new_mobj(pages_cnt, TEE_MATTR_MEM_TYPE_STRONGLY_O, + is_secure); + if (!m) + return TEE_ERROR_OUT_OF_MEMORY; + + res = sp_mem_add_pages(m, &idx, (paddr_t)base_addr, pages_cnt); + if (res) { + mobj_put(m); + return res; + } + + res = vm_map(&ctx->uctx, &va, pages_cnt * SMALL_PAGE_SIZE, + perm, 0, m, 0); + mobj_put(m); + if (res) + return res; + + /* + * Overwrite the device region's PA in the fdt with the VA. This + * fdt will be passed to the SP. + */ + res = fdt_setprop_u64(fdt, subnode, "base-address", va); + + /* + * Unmap the region if the overwrite failed since the SP won't + * be able to access it without knowing the VA. + */ + if (res) { + vm_unmap(&ctx->uctx, va, pages_cnt * SMALL_PAGE_SIZE); + return res; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result swap_sp_endpoints(uint32_t endpoint_id, + uint32_t new_endpoint_id) +{ + struct sp_session *session = sp_get_session(endpoint_id); + uint32_t manifest_endpoint_id = 0; + + /* + * We don't know in which order the SPs are loaded. The endpoint ID + * defined in the manifest could already be generated by + * new_session_id() and used by another SP. If this is the case, we swap + * the ID's of the two SPs. We also have to make sure that the ID's are + * not defined twice in the manifest. + */ + + /* The endpoint ID was not assigned yet */ + if (!session) + return TEE_SUCCESS; + + /* + * Read the manifest file from the SP who originally had the endpoint. + * We can safely swap the endpoint ID's if the manifest file doesn't + * have an endpoint ID defined. + */ + if (!sp_dt_get_u32(session->fdt, 0, "id", &manifest_endpoint_id)) { + assert(manifest_endpoint_id == endpoint_id); + EMSG("SP: Found duplicated endpoint ID %#"PRIx32, endpoint_id); + return TEE_ERROR_ACCESS_CONFLICT; + } + + session->endpoint_id = new_endpoint_id; + + return TEE_SUCCESS; +} + +static TEE_Result read_manifest_endpoint_id(struct sp_session *s) +{ + uint32_t endpoint_id = 0; + + /* + * The endpoint ID can be optionally defined in the manifest file. We + * have to map the ID inside the manifest to the SP if it's defined. + * If not, the endpoint ID generated inside new_session_id() will be + * used. + */ + if (!sp_dt_get_u32(s->fdt, 0, "id", &endpoint_id)) { + TEE_Result res = TEE_ERROR_GENERIC; + + if (endpoint_id <= SPMC_ENDPOINT_ID) + return TEE_ERROR_BAD_FORMAT; + + res = swap_sp_endpoints(endpoint_id, s->endpoint_id); + if (res) + return res; + + DMSG("SP: endpoint ID (0x%"PRIx32") found in manifest", + endpoint_id); + /* Assign the endpoint ID to the current SP */ + s->endpoint_id = endpoint_id; + } + return TEE_SUCCESS; +} + +static TEE_Result handle_fdt_mem_regions(struct sp_ctx *ctx, void *fdt) +{ + int node = 0; + int subnode = 0; + tee_mm_entry_t *mm = NULL; + TEE_Result res = TEE_SUCCESS; + + /* + * Memory regions are optional in the SP manifest, it's not an error if + * we don't find any. + */ + node = fdt_node_offset_by_compatible(fdt, 0, + "arm,ffa-manifest-memory-regions"); + if (node < 0) + return TEE_SUCCESS; + + fdt_for_each_subnode(subnode, fdt, node) { + uint64_t load_rel_offset = 0; + bool alloc_needed = false; + uint32_t attributes = 0; + uint64_t base_addr = 0; + uint32_t pages_cnt = 0; + bool is_secure = true; + struct mobj *m = NULL; + unsigned int idx = 0; + uint32_t perm = 0; + size_t size = 0; + vaddr_t va = 0; + + mm = NULL; + + /* Load address relative offset of a memory region */ + if (!sp_dt_get_u64(fdt, subnode, "load-address-relative-offset", + &load_rel_offset)) { + /* + * At this point the memory region is already mapped by + * handle_fdt_load_relative_mem_regions. + * Only need to set the base-address in the manifest and + * then skip the rest of the mapping process. + */ + va = ctx->uctx.load_addr + load_rel_offset; + res = fdt_setprop_u64(fdt, subnode, "base-address", va); + if (res) + return res; + + continue; + } + + /* + * Base address of a memory region. + * If not present, we have to allocate the specified memory. + * If present, this field could specify a PA or VA. Currently + * only a PA is supported. + */ + if (sp_dt_get_u64(fdt, subnode, "base-address", &base_addr)) + alloc_needed = true; + + /* Size of memory region as count of 4K pages */ + if (sp_dt_get_u32(fdt, subnode, "pages-count", &pages_cnt)) { + EMSG("Mandatory field is missing: pages-count"); + return TEE_ERROR_BAD_FORMAT; + } + + if (MUL_OVERFLOW(pages_cnt, SMALL_PAGE_SIZE, &size)) + return TEE_ERROR_OVERFLOW; + + /* + * Memory region attributes: + * - Instruction/data access permissions + * - Cacheability/shareability attributes + * - Security attributes + * + * Cacheability/shareability attributes can be ignored for now. + * OP-TEE only supports a single type for normal cached memory + * and currently there is no use case that would require to + * change this. + */ + if (sp_dt_get_u32(fdt, subnode, "attributes", &attributes)) { + EMSG("Mandatory field is missing: attributes"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Check instruction and data access permissions */ + switch (attributes & SP_MANIFEST_ATTR_RWX) { + case SP_MANIFEST_ATTR_RO: + perm = TEE_MATTR_UR; + break; + case SP_MANIFEST_ATTR_RW: + perm = TEE_MATTR_URW; + break; + case SP_MANIFEST_ATTR_RX: + perm = TEE_MATTR_URX; + break; + default: + EMSG("Invalid memory access permissions"); + return TEE_ERROR_BAD_FORMAT; + } + + /* + * The SP is a secure endpoint, security attribute can be + * secure or non-secure. + * The SPMC cannot allocate non-secure memory, i.e. if the base + * address is missing this attribute must be secure. + */ + if (attributes & SP_MANIFEST_ATTR_NSEC) { + if (alloc_needed) { + EMSG("Invalid memory security attribute"); + return TEE_ERROR_BAD_FORMAT; + } + is_secure = false; + } + + if (alloc_needed) { + /* Base address is missing, we have to allocate */ + mm = tee_mm_alloc(&tee_mm_sec_ddr, size); + if (!mm) + return TEE_ERROR_OUT_OF_MEMORY; + + base_addr = tee_mm_get_smem(mm); + } + + m = sp_mem_new_mobj(pages_cnt, TEE_MATTR_MEM_TYPE_CACHED, + is_secure); + if (!m) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err_mm_free; + } + + res = sp_mem_add_pages(m, &idx, base_addr, pages_cnt); + if (res) { + mobj_put(m); + goto err_mm_free; + } + + res = vm_map(&ctx->uctx, &va, size, perm, 0, m, 0); + mobj_put(m); + if (res) + goto err_mm_free; + + /* + * Overwrite the memory region's base address in the fdt with + * the VA. This fdt will be passed to the SP. + * If the base-address field was not present in the original + * fdt, this function will create it. This doesn't cause issues + * since the necessary extra space has been allocated when + * opening the fdt. + */ + res = fdt_setprop_u64(fdt, subnode, "base-address", va); + + /* + * Unmap the region if the overwrite failed since the SP won't + * be able to access it without knowing the VA. + */ + if (res) { + vm_unmap(&ctx->uctx, va, size); + goto err_mm_free; + } + } + + return TEE_SUCCESS; + +err_mm_free: + tee_mm_free(mm); + return res; +} + +static TEE_Result handle_tpm_event_log(struct sp_ctx *ctx, void *fdt) +{ + uint32_t perm = TEE_MATTR_URW | TEE_MATTR_PRW; + uint32_t dummy_size __maybe_unused = 0; + TEE_Result res = TEE_SUCCESS; + size_t page_count = 0; + struct fobj *f = NULL; + struct mobj *m = NULL; + vaddr_t log_addr = 0; + size_t log_size = 0; + int node = 0; + + node = fdt_node_offset_by_compatible(fdt, 0, "arm,tpm_event_log"); + if (node < 0) + return TEE_SUCCESS; + + /* Checking the existence and size of the event log properties */ + if (sp_dt_get_u64(fdt, node, "tpm_event_log_addr", &log_addr)) { + EMSG("tpm_event_log_addr not found or has invalid size"); + return TEE_ERROR_BAD_FORMAT; + } + + if (sp_dt_get_u32(fdt, node, "tpm_event_log_size", &dummy_size)) { + EMSG("tpm_event_log_size not found or has invalid size"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Validating event log */ + res = tpm_get_event_log_size(&log_size); + if (res) + return res; + + if (!log_size) { + EMSG("Empty TPM event log was provided"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + /* Allocating memory area for the event log to share with the SP */ + page_count = ROUNDUP_DIV(log_size, SMALL_PAGE_SIZE); + + f = fobj_sec_mem_alloc(page_count); + m = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); + fobj_put(f); + if (!m) + return TEE_ERROR_OUT_OF_MEMORY; + + res = vm_map(&ctx->uctx, &log_addr, log_size, perm, 0, m, 0); + mobj_put(m); + if (res) + return res; + + /* Copy event log */ + res = tpm_get_event_log((void *)log_addr, &log_size); + if (res) + goto err_unmap; + + /* Setting event log details in the manifest */ + res = fdt_setprop_u64(fdt, node, "tpm_event_log_addr", log_addr); + if (res) + goto err_unmap; + + res = fdt_setprop_u32(fdt, node, "tpm_event_log_size", log_size); + if (res) + goto err_unmap; + + return TEE_SUCCESS; + +err_unmap: + vm_unmap(&ctx->uctx, log_addr, log_size); + + return res; +} + +/* + * Note: this function is called only on the primary CPU. It assumes that the + * features present on the primary CPU are available on all of the secondary + * CPUs as well. + */ +static TEE_Result handle_hw_features(void *fdt) +{ + uint32_t val __maybe_unused = 0; + TEE_Result res = TEE_SUCCESS; + int node = 0; + + /* + * HW feature descriptions are optional in the SP manifest, it's not an + * error if we don't find any. + */ + node = fdt_node_offset_by_compatible(fdt, 0, "arm,hw-features"); + if (node < 0) + return TEE_SUCCESS; + + /* Modify the crc32 property only if it's already present */ + if (!sp_dt_get_u32(fdt, node, "crc32", &val)) { + res = fdt_setprop_u32(fdt, node, "crc32", + feat_crc32_implemented()); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt) +{ + TEE_Result res = TEE_SUCCESS; + struct sp_session *sess = NULL; + TEE_UUID ffa_uuid = {}; + + res = fdt_get_uuid(fdt, &ffa_uuid); + if (res) + return res; + + res = sp_open_session(&sess, + &open_sp_sessions, + &ffa_uuid, bin_uuid, fdt); + if (res) + return res; + + sess->fdt = fdt; + res = read_manifest_endpoint_id(sess); + if (res) + return res; + DMSG("endpoint is 0x%"PRIx16, sess->endpoint_id); + + return TEE_SUCCESS; +} + +static TEE_Result sp_first_run(struct sp_session *sess) +{ + TEE_Result res = TEE_SUCCESS; + struct thread_smc_args args = { }; + vaddr_t va = 0; + size_t num_pgs = 0; + struct sp_ctx *ctx = NULL; + void *fdt_copy = NULL; + + ctx = to_sp_ctx(sess->ts_sess.ctx); + ts_push_current_session(&sess->ts_sess); + + /* + * Load relative memory regions must be handled before doing any other + * mapping to prevent conflicts in the VA space. + */ + res = handle_fdt_load_relative_mem_regions(ctx, sess->fdt); + if (res) { + ts_pop_current_session(); + return res; + } + + res = sp_init_info(ctx, &args, sess->fdt, &va, &num_pgs, &fdt_copy); + if (res) + goto out; + + res = handle_fdt_dev_regions(ctx, fdt_copy); + if (res) + goto out; + + res = handle_fdt_mem_regions(ctx, fdt_copy); + if (res) + goto out; + + if (IS_ENABLED(CFG_CORE_TPM_EVENT_LOG)) { + res = handle_tpm_event_log(ctx, fdt_copy); + if (res) + goto out; + } + + res = handle_hw_features(fdt_copy); + if (res) + goto out; + + ts_pop_current_session(); + + sess->is_initialized = false; + if (sp_enter(&args, sess)) { + vm_unmap(&ctx->uctx, va, num_pgs); + return FFA_ABORTED; + } + + spmc_sp_msg_handler(&args, sess); + + sess->is_initialized = true; + + ts_push_current_session(&sess->ts_sess); +out: + /* Free the boot info page from the SP memory */ + vm_unmap(&ctx->uctx, va, num_pgs); + ts_pop_current_session(); + + return res; +} + +TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp) +{ + TEE_Result res = FFA_OK; + struct sp_ctx *ctx = to_sp_ctx(sp->ts_sess.ctx); + + ctx->sp_regs.x[0] = args->a0; + ctx->sp_regs.x[1] = args->a1; + ctx->sp_regs.x[2] = args->a2; + ctx->sp_regs.x[3] = args->a3; + ctx->sp_regs.x[4] = args->a4; + ctx->sp_regs.x[5] = args->a5; + ctx->sp_regs.x[6] = args->a6; + ctx->sp_regs.x[7] = args->a7; + + res = sp->ts_sess.ctx->ops->enter_invoke_cmd(&sp->ts_sess, 0); + + args->a0 = ctx->sp_regs.x[0]; + args->a1 = ctx->sp_regs.x[1]; + args->a2 = ctx->sp_regs.x[2]; + args->a3 = ctx->sp_regs.x[3]; + args->a4 = ctx->sp_regs.x[4]; + args->a5 = ctx->sp_regs.x[5]; + args->a6 = ctx->sp_regs.x[6]; + args->a7 = ctx->sp_regs.x[7]; + + return res; +} + +static TEE_Result sp_enter_invoke_cmd(struct ts_session *s, + uint32_t cmd __unused) +{ + struct sp_ctx *ctx = to_sp_ctx(s->ctx); + TEE_Result res = TEE_SUCCESS; + uint32_t exceptions = 0; + uint64_t cpsr = 0; + struct sp_session *sp_s = to_sp_session(s); + struct ts_session *sess = NULL; + struct thread_ctx_regs *sp_regs = NULL; + uint32_t panicked = false; + uint32_t panic_code = 0; + + bm_timestamp(); + + sp_regs = &ctx->sp_regs; + ts_push_current_session(s); + + cpsr = sp_regs->cpsr; + sp_regs->cpsr = read_daif() & (SPSR_64_DAIF_MASK << SPSR_64_DAIF_SHIFT); + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + __thread_enter_user_mode(sp_regs, &panicked, &panic_code); + sp_regs->cpsr = cpsr; + thread_unmask_exceptions(exceptions); + + thread_user_clear_vfp(&ctx->uctx); + + if (panicked) { + DMSG("SP panicked with code %#"PRIx32, panic_code); + abort_print_current_ts(); + + sess = ts_pop_current_session(); + cpu_spin_lock(&sp_s->spinlock); + sp_s->state = sp_dead; + cpu_spin_unlock(&sp_s->spinlock); + + return TEE_ERROR_TARGET_DEAD; + } + + sess = ts_pop_current_session(); + assert(sess == s); + + bm_timestamp(); + + return res; +} + +/* We currently don't support 32 bits */ +#ifdef ARM64 +static void sp_svc_store_registers(struct thread_scall_regs *regs, + struct thread_ctx_regs *sp_regs) +{ + COMPILE_TIME_ASSERT(sizeof(sp_regs->x[0]) == sizeof(regs->x0)); + memcpy(sp_regs->x, ®s->x0, 31 * sizeof(regs->x0)); + sp_regs->pc = regs->elr; + sp_regs->sp = regs->sp_el0; +} +#endif + +static bool sp_handle_scall(struct thread_scall_regs *regs) +{ + struct ts_session *ts = ts_get_current_session(); + struct sp_ctx *uctx = to_sp_ctx(ts->ctx); + struct sp_session *s = uctx->open_session; + + assert(s); + + sp_svc_store_registers(regs, &uctx->sp_regs); + + regs->x0 = 0; + regs->x1 = 0; /* panic */ + regs->x2 = 0; /* panic code */ + + /* + * All the registers of the SP are saved in the SP session by the SVC + * handler. + * We always return to S-El1 after handling the SVC. We will continue + * in sp_enter_invoke_cmd() (return from __thread_enter_user_mode). + * The sp_enter() function copies the FF-A parameters (a0-a7) from the + * saved registers to the thread_smc_args. The thread_smc_args object is + * afterward used by the spmc_sp_msg_handler() to handle the + * FF-A message send by the SP. + */ + return false; +} + +static void sp_dump_state(struct ts_ctx *ctx) +{ + struct sp_ctx *utc = to_sp_ctx(ctx); + + if (utc->uctx.dump_entry_func) { + TEE_Result res = ldelf_dump_state(&utc->uctx); + + if (!res || res == TEE_ERROR_TARGET_DEAD) + return; + } + + user_mode_ctx_print_mappings(&utc->uctx); +} + +static const struct ts_ops sp_ops = { + .enter_invoke_cmd = sp_enter_invoke_cmd, + .handle_scall = sp_handle_scall, + .dump_state = sp_dump_state, +}; + +static TEE_Result process_sp_pkg(uint64_t sp_pkg_pa, TEE_UUID *sp_uuid) +{ + enum teecore_memtypes mtype = MEM_AREA_TA_RAM; + struct sp_pkg_header *sp_pkg_hdr = NULL; + struct fip_sp *sp = NULL; + uint64_t sp_fdt_end = 0; + size_t sp_pkg_size = 0; + vaddr_t sp_pkg_va = 0; + + /* Process the first page which contains the SP package header */ + sp_pkg_va = (vaddr_t)phys_to_virt(sp_pkg_pa, mtype, SMALL_PAGE_SIZE); + if (!sp_pkg_va) { + EMSG("Cannot find mapping for PA %#" PRIxPA, sp_pkg_pa); + return TEE_ERROR_GENERIC; + } + + sp_pkg_hdr = (struct sp_pkg_header *)sp_pkg_va; + + if (sp_pkg_hdr->magic != SP_PKG_HEADER_MAGIC) { + EMSG("Invalid SP package magic"); + return TEE_ERROR_BAD_FORMAT; + } + + if (sp_pkg_hdr->version != SP_PKG_HEADER_VERSION_V1 && + sp_pkg_hdr->version != SP_PKG_HEADER_VERSION_V2) { + EMSG("Invalid SP header version"); + return TEE_ERROR_BAD_FORMAT; + } + + if (ADD_OVERFLOW(sp_pkg_hdr->img_offset, sp_pkg_hdr->img_size, + &sp_pkg_size)) { + EMSG("Invalid SP package size"); + return TEE_ERROR_BAD_FORMAT; + } + + if (ADD_OVERFLOW(sp_pkg_hdr->pm_offset, sp_pkg_hdr->pm_size, + &sp_fdt_end) || sp_fdt_end > sp_pkg_hdr->img_offset) { + EMSG("Invalid SP manifest size"); + return TEE_ERROR_BAD_FORMAT; + } + + /* Process the whole SP package now that the size is known */ + sp_pkg_va = (vaddr_t)phys_to_virt(sp_pkg_pa, mtype, sp_pkg_size); + if (!sp_pkg_va) { + EMSG("Cannot find mapping for PA %#" PRIxPA, sp_pkg_pa); + return TEE_ERROR_GENERIC; + } + + sp_pkg_hdr = (struct sp_pkg_header *)sp_pkg_va; + + sp = calloc(1, sizeof(struct fip_sp)); + if (!sp) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(&sp->sp_img.image.uuid, sp_uuid, sizeof(*sp_uuid)); + sp->sp_img.image.ts = (uint8_t *)(sp_pkg_va + sp_pkg_hdr->img_offset); + sp->sp_img.image.size = sp_pkg_hdr->img_size; + sp->sp_img.image.flags = 0; + sp->sp_img.fdt = (uint8_t *)(sp_pkg_va + sp_pkg_hdr->pm_offset); + + STAILQ_INSERT_TAIL(&fip_sp_list, sp, link); + + return TEE_SUCCESS; +} + +static TEE_Result fip_sp_init_all(void) +{ + TEE_Result res = TEE_SUCCESS; + uint64_t sp_pkg_addr = 0; + const void *fdt = NULL; + TEE_UUID sp_uuid = { }; + int sp_pkgs_node = 0; + int subnode = 0; + int root = 0; + + fdt = get_tos_fw_config_dt(); + if (!fdt) { + EMSG("No SPMC manifest found"); + return TEE_ERROR_GENERIC; + } + + root = fdt_path_offset(fdt, "/"); + if (root < 0) + return TEE_ERROR_BAD_FORMAT; + + if (fdt_node_check_compatible(fdt, root, "arm,ffa-core-manifest-1.0")) + return TEE_ERROR_BAD_FORMAT; + + /* SP packages are optional, it's not an error if we don't find any */ + sp_pkgs_node = fdt_node_offset_by_compatible(fdt, root, "arm,sp_pkg"); + if (sp_pkgs_node < 0) + return TEE_SUCCESS; + + fdt_for_each_subnode(subnode, fdt, sp_pkgs_node) { + res = sp_dt_get_u64(fdt, subnode, "load-address", &sp_pkg_addr); + if (res) { + EMSG("Invalid FIP SP load address"); + return res; + } + + res = sp_dt_get_uuid(fdt, subnode, "uuid", &sp_uuid); + if (res) { + EMSG("Invalid FIP SP uuid"); + return res; + } + + res = process_sp_pkg(sp_pkg_addr, &sp_uuid); + if (res) { + EMSG("Invalid FIP SP package"); + return res; + } + } + + return TEE_SUCCESS; +} + +static void fip_sp_deinit_all(void) +{ + while (!STAILQ_EMPTY(&fip_sp_list)) { + struct fip_sp *sp = STAILQ_FIRST(&fip_sp_list); + + STAILQ_REMOVE_HEAD(&fip_sp_list, link); + free(sp); + } +} + +static TEE_Result sp_init_all(void) +{ + TEE_Result res = TEE_SUCCESS; + const struct sp_image *sp = NULL; + const struct fip_sp *fip_sp = NULL; + char __maybe_unused msg[60] = { '\0', }; + struct sp_session *s = NULL; + + for_each_secure_partition(sp) { + if (sp->image.uncompressed_size) + snprintf(msg, sizeof(msg), + " (compressed, uncompressed %u)", + sp->image.uncompressed_size); + else + msg[0] = '\0'; + DMSG("SP %pUl size %u%s", (void *)&sp->image.uuid, + sp->image.size, msg); + + res = sp_init_uuid(&sp->image.uuid, sp->fdt); + + if (res != TEE_SUCCESS) { + EMSG("Failed initializing SP(%pUl) err:%#"PRIx32, + &sp->image.uuid, res); + if (!IS_ENABLED(CFG_SP_SKIP_FAILED)) + panic(); + } + } + + res = fip_sp_init_all(); + if (res) + panic("Failed initializing FIP SPs"); + + for_each_fip_sp(fip_sp) { + sp = &fip_sp->sp_img; + + DMSG("SP %pUl size %u", (void *)&sp->image.uuid, + sp->image.size); + + res = sp_init_uuid(&sp->image.uuid, sp->fdt); + + if (res != TEE_SUCCESS) { + EMSG("Failed initializing SP(%pUl) err:%#"PRIx32, + &sp->image.uuid, res); + if (!IS_ENABLED(CFG_SP_SKIP_FAILED)) + panic(); + } + } + + /* + * At this point all FIP SPs are loaded by ldelf or by the raw binary SP + * loader, so the original images (loaded by BL2) are not needed anymore + */ + fip_sp_deinit_all(); + + /* Continue the initialization and run the SP */ + TAILQ_FOREACH(s, &open_sp_sessions, link) { + res = sp_first_run(s); + if (res != TEE_SUCCESS) { + EMSG("Failed starting SP(0x%"PRIx16") err:%#"PRIx32, + s->endpoint_id, res); + if (!IS_ENABLED(CFG_SP_SKIP_FAILED)) + panic(); + } + } + + return TEE_SUCCESS; +} + +boot_final(sp_init_all); + +static TEE_Result secure_partition_open(const TEE_UUID *uuid, + struct ts_store_handle **h) +{ + return emb_ts_open(uuid, h, find_secure_partition); +} + +REGISTER_SP_STORE(2) = { + .description = "SP store", + .open = secure_partition_open, + .get_size = emb_ts_get_size, + .get_tag = emb_ts_get_tag, + .read = emb_ts_read, + .close = emb_ts_close, +}; diff --git a/optee/optee_os/core/arch/arm/kernel/spin_lock_a32.S b/optee/optee_os/core/arch/arm/kernel/spin_lock_a32.S new file mode 100644 index 0000000..ab9c41b --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/spin_lock_a32.S @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * 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. + * + * Neither the name of ARM 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. + */ + +#include +#include + +/* void __cpu_spin_lock(unsigned int *lock) */ +FUNC __cpu_spin_lock , : + mov r2, #SPINLOCK_LOCK +1: + ldrex r1, [r0] + cmp r1, #SPINLOCK_UNLOCK + wfene + strexeq r1, r2, [r0] + cmpeq r1, #0 + bne 1b + dmb + bx lr +END_FUNC __cpu_spin_lock + +/* int __cpu_spin_trylock(unsigned int *lock) - return 0 on success */ +FUNC __cpu_spin_trylock , : + mov r2, #SPINLOCK_LOCK + mov r1, r0 +1: + ldrex r0, [r1] + cmp r0, #0 + bne 1f + strex r0, r2, [r1] + cmp r0, #0 + bne 1b + dmb + bx lr +1: + clrex + dmb + bx lr +END_FUNC __cpu_spin_trylock + +/* void __cpu_spin_unlock(unsigned int *lock) */ +FUNC __cpu_spin_unlock , : + dmb + mov r1, #SPINLOCK_UNLOCK + str r1, [r0] + dsb + sev + bx lr +END_FUNC __cpu_spin_unlock diff --git a/optee/optee_os/core/arch/arm/kernel/spin_lock_a64.S b/optee/optee_os/core/arch/arm/kernel/spin_lock_a64.S new file mode 100644 index 0000000..10561fe --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/spin_lock_a64.S @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) */ +/* + * Copyright (c) 2015, 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. + */ + +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM 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. + */ + +#include +#include + +/* void __cpu_spin_lock(unsigned int *lock); */ +FUNC __cpu_spin_lock , : + mov w2, #SPINLOCK_LOCK + sevl +l1: wfe +l2: ldaxr w1, [x0] + cbnz w1, l1 + stxr w1, w2, [x0] + cbnz w1, l2 + ret +END_FUNC __cpu_spin_lock + +/* unsigned int __cpu_spin_trylock(unsigned int *lock); */ +FUNC __cpu_spin_trylock , : + mov x1, x0 + mov w2, #SPINLOCK_LOCK +.loop: ldaxr w0, [x1] + cbnz w0, .cpu_spin_trylock_out + stxr w0, w2, [x1] + cbnz w0, .loop +.cpu_spin_trylock_out: + ret +END_FUNC __cpu_spin_trylock + +/* void __cpu_spin_unlock(unsigned int *lock); */ +FUNC __cpu_spin_unlock , : + stlr wzr, [x0] + ret +END_FUNC __cpu_spin_unlock + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c b/optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c new file mode 100644 index 0000000..46a1564 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/spmc_sp_handler.c @@ -0,0 +1,1142 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2022, Arm Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int mem_ref_lock = SPINLOCK_UNLOCK; + +void spmc_sp_start_thread(struct thread_smc_args *args) +{ + thread_sp_alloc_and_run(args); +} + +static void ffa_set_error(struct thread_smc_args *args, uint32_t error) +{ + args->a0 = FFA_ERROR; + args->a2 = error; +} + +static void ffa_success(struct thread_smc_args *args) +{ + args->a0 = FFA_SUCCESS_32; +} + +static TEE_Result ffa_get_dst(struct thread_smc_args *args, + struct sp_session *caller, + struct sp_session **dst) +{ + struct sp_session *s = NULL; + + if (args->a2 != FFA_PARAM_MBZ) + return FFA_INVALID_PARAMETERS; + + s = sp_get_session(FFA_DST(args->a1)); + + /* Message came from the NW */ + if (!caller) { + if (!s) { + EMSG("Neither destination nor source is a SP"); + return FFA_INVALID_PARAMETERS; + } + } else { + /* Check if the source matches the endpoint we came from */ + if (FFA_SRC(args->a1) != caller->endpoint_id) { + EMSG("Source address doesn't match the endpoint id"); + return FFA_INVALID_PARAMETERS; + } + } + + *dst = s; + + return FFA_OK; +} + +static struct sp_mem_receiver *find_sp_mem_receiver(struct sp_session *s, + struct sp_mem *smem) +{ + struct sp_mem_receiver *receiver = NULL; + + /* + * FF-A Spec 8.10.2: + * Each Handle identifies a single unique composite memory region + * description that is, there is a 1:1 mapping between the two. + * + * Each memory share has an unique handle. We can only have each SP + * once as a receiver in the memory share. For each receiver of a + * memory share, we have one sp_mem_access_descr object. + * This means that there can only be one SP linked to a specific + * struct sp_mem_access_descr. + */ + SLIST_FOREACH(receiver, &smem->receivers, link) { + if (receiver->perm.endpoint_id == s->endpoint_id) + break; + } + return receiver; +} + +static int add_mem_region_to_sp(struct ffa_mem_access *mem_acc, + struct sp_mem *smem) +{ + struct ffa_mem_access_perm *access_perm = &mem_acc->access_perm; + struct sp_session *s = NULL; + struct sp_mem_receiver *receiver = NULL; + uint8_t perm = READ_ONCE(access_perm->perm); + uint16_t endpoint_id = READ_ONCE(access_perm->endpoint_id); + + s = sp_get_session(endpoint_id); + + /* Only add memory shares of loaded SPs */ + if (!s) + return FFA_DENIED; + + /* Only allow each endpoint once */ + if (find_sp_mem_receiver(s, smem)) + return FFA_DENIED; + + if (perm & ~FFA_MEM_ACC_MASK) + return FFA_DENIED; + + receiver = calloc(1, sizeof(struct sp_mem_receiver)); + if (!receiver) + return FFA_NO_MEMORY; + + receiver->smem = smem; + + receiver->perm.endpoint_id = endpoint_id; + receiver->perm.perm = perm; + receiver->perm.flags = READ_ONCE(access_perm->flags); + + SLIST_INSERT_HEAD(&smem->receivers, receiver, link); + + return FFA_OK; +} + +static void spmc_sp_handle_mem_share(struct thread_smc_args *args, + struct ffa_rxtx *rxtx, + struct sp_session *owner_sp) +{ + uint64_t global_handle = 0; + int res = FFA_OK; + uint32_t ret_w2 = 0; + uint32_t ret_w3 = 0; + + cpu_spin_lock(&rxtx->spinlock); + + res = spmc_sp_add_share(rxtx, args->a1, &global_handle, owner_sp); + if (!res) { + reg_pair_from_64(global_handle, &ret_w3, &ret_w2); + args->a3 = ret_w3; + args->a2 = ret_w2; + args->a1 = FFA_PARAM_MBZ; + args->a0 = FFA_SUCCESS_32; + } else { + ffa_set_error(args, res); + } + + cpu_spin_unlock(&rxtx->spinlock); +} + +static int spmc_sp_add_sp_region(struct sp_mem *smem, + struct ffa_address_range *mem_reg, + struct sp_session *owner_sp, + uint8_t highest_permission) +{ + struct sp_ctx *sp_ctx = NULL; + uint64_t va = READ_ONCE(mem_reg->address); + int res = FFA_OK; + uint64_t region_len = READ_ONCE(mem_reg->page_count) * SMALL_PAGE_SIZE; + struct mobj *mobj = NULL; + + sp_ctx = to_sp_ctx(owner_sp->ts_sess.ctx); + + /* + * The memory region we try to share might not be linked to just one + * mobj. Create a new region for each mobj. + */ + while (region_len) { + size_t len = region_len; + struct sp_mem_map_region *region = NULL; + uint16_t prot = 0; + size_t offs = 0; + + /* + * There is already a mobj for each address that is in the SPs + * address range. + */ + mobj = vm_get_mobj(&sp_ctx->uctx, va, &len, &prot, &offs); + if (!mobj) + return FFA_DENIED; + + /* + * If we share memory from a SP, check if we are not sharing + * with a higher permission than the memory was originally + * mapped. + */ + if ((highest_permission & FFA_MEM_ACC_RW) && + !(prot & TEE_MATTR_UW)) { + res = FFA_DENIED; + goto err; + } + + if ((highest_permission & FFA_MEM_ACC_EXE) && + !(prot & TEE_MATTR_UX)) { + res = FFA_DENIED; + goto err; + } + + region = calloc(1, sizeof(*region)); + region->mobj = mobj; + region->page_offset = offs; + region->page_count = len / SMALL_PAGE_SIZE; + + if (!sp_has_exclusive_access(region, &sp_ctx->uctx)) { + free(region); + res = FFA_DENIED; + goto err; + } + + va += len; + region_len -= len; + SLIST_INSERT_HEAD(&smem->regions, region, link); + } + + return FFA_OK; +err: + mobj_put(mobj); + + return res; +} + +static int spmc_sp_add_nw_region(struct sp_mem *smem, + struct ffa_mem_region *mem_reg) +{ + uint64_t page_count = READ_ONCE(mem_reg->total_page_count); + struct sp_mem_map_region *region = NULL; + struct mobj *m = sp_mem_new_mobj(page_count, TEE_MATTR_MEM_TYPE_CACHED, + false); + unsigned int i = 0; + unsigned int idx = 0; + int res = FFA_OK; + uint64_t address_count = READ_ONCE(mem_reg->address_range_count); + + if (!m) + return FFA_NO_MEMORY; + + for (i = 0; i < address_count; i++) { + struct ffa_address_range *addr_range = NULL; + + addr_range = &mem_reg->address_range_array[i]; + if (sp_mem_add_pages(m, &idx, + READ_ONCE(addr_range->address), + READ_ONCE(addr_range->page_count))) { + res = FFA_DENIED; + goto clean_up; + } + } + + region = calloc(1, sizeof(*region)); + if (!region) { + res = FFA_NO_MEMORY; + goto clean_up; + } + + region->mobj = m; + region->page_count = page_count; + + if (!sp_has_exclusive_access(region, NULL)) { + free(region); + res = FFA_DENIED; + goto clean_up; + } + + SLIST_INSERT_HEAD(&smem->regions, region, link); + return FFA_OK; +clean_up: + mobj_put(m); + return res; +} + +int spmc_sp_add_share(struct ffa_rxtx *rxtx, + size_t blen, uint64_t *global_handle, + struct sp_session *owner_sp) +{ + int res = FFA_INVALID_PARAMETERS; + unsigned int num_mem_accs = 0; + unsigned int i = 0; + struct ffa_mem_access *mem_acc = NULL; + size_t needed_size = 0; + size_t addr_range_offs = 0; + struct ffa_mem_region *mem_reg = NULL; + uint8_t highest_permission = 0; + struct sp_mem *smem = sp_mem_new(); + struct ffa_mem_transaction *input_descr = rxtx->rx; + uint16_t sender_id = READ_ONCE(input_descr->sender_id); + + if (!smem) + return FFA_NO_MEMORY; + + if ((owner_sp && owner_sp->endpoint_id != sender_id) || + (!owner_sp && sp_get_session(sender_id))) { + res = FFA_DENIED; + goto cleanup; + } + + num_mem_accs = READ_ONCE(input_descr->mem_access_count); + mem_acc = input_descr->mem_access_array; + + if (!num_mem_accs) { + res = FFA_DENIED; + goto cleanup; + } + + /* Store the ffa_mem_transaction */ + smem->sender_id = sender_id; + smem->mem_reg_attr = READ_ONCE(input_descr->mem_reg_attr); + smem->flags = READ_ONCE(input_descr->flags); + smem->tag = READ_ONCE(input_descr->tag); + + if (MUL_OVERFLOW(num_mem_accs, sizeof(*mem_acc), &needed_size) || + ADD_OVERFLOW(needed_size, sizeof(*input_descr), &needed_size) || + needed_size > blen) { + res = FFA_NO_MEMORY; + goto cleanup; + } + + for (i = 0; i < num_mem_accs; i++) + highest_permission |= READ_ONCE(mem_acc[i].access_perm.perm); + + addr_range_offs = READ_ONCE(mem_acc[0].region_offs); + mem_reg = (void *)((char *)input_descr + addr_range_offs); + + /* Iterate over all the addresses */ + if (owner_sp) { + size_t address_range = READ_ONCE(mem_reg->address_range_count); + + for (i = 0; i < address_range; i++) { + struct ffa_address_range *addr_range = NULL; + + addr_range = &mem_reg->address_range_array[i]; + + if (!core_is_buffer_inside((vaddr_t)addr_range, + sizeof(*addr_range), + (vaddr_t)rxtx->rx, + rxtx->size)) { + res = FFA_NO_MEMORY; + goto cleanup; + } + res = spmc_sp_add_sp_region(smem, addr_range, + owner_sp, + highest_permission); + if (res) + goto cleanup; + } + } else { + res = spmc_sp_add_nw_region(smem, mem_reg); + if (res) + goto cleanup; + } + + /* Add the memory address to the SP */ + for (i = 0; i < num_mem_accs; i++) { + res = add_mem_region_to_sp(&mem_acc[i], smem); + if (res) + goto cleanup; + } + *global_handle = smem->global_handle; + sp_mem_add(smem); + + return FFA_OK; + +cleanup: + sp_mem_remove(smem); + return res; +} + +static bool check_rxtx(struct ffa_rxtx *rxtx) +{ + return rxtx && rxtx->rx && rxtx->tx && rxtx->size > 0; +} + +static TEE_Result check_retrieve_request(struct sp_mem_receiver *receiver, + struct ffa_mem_transaction *retr_dsc, + struct sp_mem *smem, int64_t tx_len) +{ + struct ffa_mem_access *retr_access = NULL; + uint8_t share_perm = receiver->perm.perm; + uint32_t retr_perm = 0; + uint32_t retr_flags = READ_ONCE(retr_dsc->flags); + uint64_t retr_tag = READ_ONCE(retr_dsc->tag); + struct sp_mem_map_region *reg = NULL; + + /* + * The request came from the endpoint. It should only have one + * ffa_mem_access element + */ + if (READ_ONCE(retr_dsc->mem_access_count) != 1) + return TEE_ERROR_BAD_PARAMETERS; + + retr_access = retr_dsc->mem_access_array; + retr_perm = READ_ONCE(retr_access->access_perm.perm); + + /* Check if tag is correct */ + if (receiver->smem->tag != retr_tag) { + EMSG("Incorrect tag %#"PRIx64" %#"PRIx64, receiver->smem->tag, + retr_tag); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Check permissions and flags */ + if ((retr_perm & FFA_MEM_ACC_RW) && + !(share_perm & FFA_MEM_ACC_RW)) { + DMSG("Incorrect memshare permission set"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if ((retr_perm & FFA_MEM_ACC_EXE) && + !(share_perm & FFA_MEM_ACC_EXE)) { + DMSG("Incorrect memshare permission set"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (retr_flags & FFA_MEMORY_REGION_FLAG_CLEAR_RELINQUISH) { + DMSG("CLEAR_RELINQUISH is not allowed for FFA_SHARE"); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* + * Check if there is enough space in the tx buffer to send the respons. + */ + tx_len -= sizeof(struct ffa_mem_transaction) + + sizeof(struct ffa_mem_access) + + sizeof(struct ffa_mem_region); + + if (tx_len < 0) + return FFA_NO_MEMORY; + + SLIST_FOREACH(reg, &smem->regions, link) { + tx_len -= sizeof(struct ffa_address_range); + if (tx_len < 0) + return FFA_NO_MEMORY; + } + + return TEE_SUCCESS; +} + +static void create_retrieve_response(void *dst_buffer, + struct sp_mem_receiver *receiver, + struct sp_mem *smem, struct sp_session *s) +{ + size_t off = 0; + struct ffa_mem_region *dst_region = NULL; + struct ffa_mem_transaction *d_ds = dst_buffer; + struct ffa_address_range *addr_dst = NULL; + struct sp_mem_map_region *reg = NULL; + + /* + * We respond with a FFA_MEM_RETRIEVE_RESP which defines the + * following data in the rx buffer of the SP. + * struct mem_transaction_descr + * struct mem_access_descr (always 1 Element) + * struct mem_region_descr + */ + /* Copy the mem_transaction_descr */ + d_ds->sender_id = receiver->smem->sender_id; + d_ds->mem_reg_attr = receiver->smem->mem_reg_attr; + d_ds->flags = receiver->smem->flags; + d_ds->tag = receiver->smem->tag; + + off = sizeof(struct ffa_mem_transaction) + + sizeof(struct ffa_mem_access); + + d_ds->mem_access_count = 1; + + /* Copy the mem_accsess_descr */ + d_ds->mem_access_array[0].region_offs = off; + memcpy(&d_ds->mem_access_array[0].access_perm, + &receiver->perm, sizeof(struct ffa_mem_access_perm)); + + /* Copy the mem_region_descr */ + dst_region = (struct ffa_mem_region *)((vaddr_t)d_ds + off); + + dst_region->address_range_count = 0; + dst_region->total_page_count = 0; + + addr_dst = dst_region->address_range_array; + + SLIST_FOREACH(reg, &smem->regions, link) { + uint32_t offset = reg->page_offset; + struct sp_ctx *ctx = to_sp_ctx(s->ts_sess.ctx); + + addr_dst->address = (uint64_t)sp_mem_get_va(&ctx->uctx, + offset, + reg->mobj); + addr_dst->page_count = reg->page_count; + dst_region->address_range_count++; + + dst_region->total_page_count += addr_dst->page_count; + } +} + +static void ffa_mem_retrieve(struct thread_smc_args *args, + struct sp_session *caller_sp, + struct ffa_rxtx *rxtx) +{ + int ret = FFA_OK; + size_t tx_len = 0; + struct ffa_mem_transaction *retr_dsc = NULL; + struct ffa_mem_region *mem_region = NULL; + uint64_t va = 0; + struct sp_mem *smem = NULL; + struct sp_mem_receiver *receiver = NULL; + uint32_t exceptions = 0; + uint32_t address_offset = 0; + size_t needed_size = 0; + + if (!check_rxtx(rxtx) || !rxtx->tx_is_mine) { + ret = FFA_DENIED; + goto err; + } + + tx_len = rxtx->size; + retr_dsc = rxtx->rx; + + smem = sp_mem_get(retr_dsc->global_handle); + if (!smem) { + DMSG("Incorrect handle"); + ret = FFA_DENIED; + goto err; + } + + receiver = sp_mem_get_receiver(caller_sp->endpoint_id, smem); + + address_offset = READ_ONCE(retr_dsc->mem_access_array[0].region_offs); + + if (ADD_OVERFLOW(address_offset, sizeof(struct ffa_mem_region), + &needed_size) || needed_size > tx_len) { + ret = FFA_INVALID_PARAMETERS; + goto err; + } + + if (check_retrieve_request(receiver, retr_dsc, smem, tx_len) != + TEE_SUCCESS) { + ret = FFA_INVALID_PARAMETERS; + goto err; + } + + exceptions = cpu_spin_lock_xsave(&mem_ref_lock); + + if (receiver->ref_count == UINT8_MAX) { + ret = FFA_DENIED; + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + goto err; + } + + receiver->ref_count++; + + /* We only need to map the region the first time we request it. */ + if (receiver->ref_count == 1) { + TEE_Result ret_map = TEE_SUCCESS; + + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + + /* + * Try to map the memory linked to the handle in + * sp_mem_access_descr. + */ + mem_region = (struct ffa_mem_region *)((vaddr_t)retr_dsc + + address_offset); + + va = READ_ONCE(mem_region->address_range_array[0].address); + ret_map = sp_map_shared(caller_sp, receiver, smem, &va); + + if (ret_map) { + EMSG("Could not map memory region: %#"PRIx32, ret_map); + exceptions = cpu_spin_lock_xsave(&mem_ref_lock); + receiver->ref_count--; + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + ret = FFA_DENIED; + goto err; + } + } else { + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + } + + create_retrieve_response(rxtx->tx, receiver, smem, caller_sp); + + args->a0 = FFA_MEM_RETRIEVE_RESP; + args->a1 = tx_len; + args->a2 = tx_len; + + rxtx->tx_is_mine = false; + + return; +err: + ffa_set_error(args, ret); +} + +static void ffa_mem_relinquish(struct thread_smc_args *args, + struct sp_session *caller_sp, + struct ffa_rxtx *rxtx) +{ + struct sp_mem *smem = NULL; + struct ffa_mem_relinquish *mem = rxtx->rx; + struct sp_mem_receiver *receiver = NULL; + int err = FFA_NOT_SUPPORTED; + uint32_t exceptions = 0; + + if (!check_rxtx(rxtx)) { + ffa_set_error(args, FFA_DENIED); + return; + } + + exceptions = cpu_spin_lock_xsave(&rxtx->spinlock); + smem = sp_mem_get(READ_ONCE(mem->handle)); + + if (!smem) { + DMSG("Incorrect handle"); + err = FFA_DENIED; + goto err_unlock_rxtwx; + } + + if (READ_ONCE(mem->endpoint_count) != 1) { + DMSG("Incorrect endpoint count"); + err = FFA_INVALID_PARAMETERS; + goto err_unlock_rxtwx; + } + + if (READ_ONCE(mem->endpoint_id_array[0]) != caller_sp->endpoint_id) { + DMSG("Incorrect endpoint id"); + err = FFA_DENIED; + goto err_unlock_rxtwx; + } + + cpu_spin_unlock_xrestore(&rxtx->spinlock, exceptions); + + receiver = sp_mem_get_receiver(caller_sp->endpoint_id, smem); + + exceptions = cpu_spin_lock_xsave(&mem_ref_lock); + if (!receiver->ref_count) { + DMSG("To many relinquish requests"); + err = FFA_DENIED; + goto err_unlock_memref; + } + + receiver->ref_count--; + if (!receiver->ref_count) { + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + if (sp_unmap_ffa_regions(caller_sp, smem) != TEE_SUCCESS) { + DMSG("Failed to unmap region"); + ffa_set_error(args, FFA_DENIED); + return; + } + } else { + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + } + + ffa_success(args); + return; + +err_unlock_rxtwx: + cpu_spin_unlock_xrestore(&rxtx->spinlock, exceptions); + ffa_set_error(args, err); + return; +err_unlock_memref: + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + ffa_set_error(args, err); +} + +static void zero_mem_region(struct sp_mem *smem, struct sp_session *s) +{ + void *addr = NULL; + struct sp_ctx *ctx = to_sp_ctx(s->ts_sess.ctx); + struct sp_mem_map_region *reg = NULL; + + ts_push_current_session(&s->ts_sess); + SLIST_FOREACH(reg, &smem->regions, link) { + size_t sz = reg->page_count * SMALL_PAGE_SIZE; + + addr = sp_mem_get_va(&ctx->uctx, reg->page_offset, reg->mobj); + + assert(addr); + memset(addr, 0, sz); + } + ts_pop_current_session(); +} + +/* + * ffa_mem_reclaim returns false if it couldn't process the reclaim message. + * This happens when the memory regions was shared with the OP-TEE endpoint. + * After this thread_spmc calls handle_mem_reclaim() to make sure that the + * region is reclaimed from the OP-TEE endpoint. + */ +bool ffa_mem_reclaim(struct thread_smc_args *args, + struct sp_session *caller_sp) +{ + uint64_t handle = reg_pair_to_64(args->a2, args->a1); + uint32_t flags = args->a3; + uint32_t endpoint = 0; + struct sp_mem *smem = NULL; + struct sp_mem_receiver *receiver = NULL; + uint32_t exceptions = 0; + + smem = sp_mem_get(handle); + if (!smem) + return false; + + if (caller_sp) + endpoint = caller_sp->endpoint_id; + + /* Make sure that the caller is the owner of the share */ + if (smem->sender_id != endpoint) { + ffa_set_error(args, FFA_DENIED); + return true; + } + + exceptions = cpu_spin_lock_xsave(&mem_ref_lock); + + /* Make sure that all shares where relinquished */ + SLIST_FOREACH(receiver, &smem->receivers, link) { + if (receiver->ref_count != 0) { + ffa_set_error(args, FFA_DENIED); + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + return true; + } + } + + if (flags & FFA_MEMORY_REGION_FLAG_CLEAR) { + if (caller_sp) { + zero_mem_region(smem, caller_sp); + } else { + /* + * Currently we don't support zeroing Normal World + * memory. To do this we would have to map the memory + * again, zero it and unmap it. + */ + ffa_set_error(args, FFA_DENIED); + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + return true; + } + } + + sp_mem_remove(smem); + cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); + + ffa_success(args); + return true; +} + +static struct sp_session * +ffa_handle_sp_direct_req(struct thread_smc_args *args, + struct sp_session *caller_sp) +{ + struct sp_session *dst = NULL; + TEE_Result res = FFA_OK; + + if (args->a2 != FFA_PARAM_MBZ) { + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return NULL; + } + + res = ffa_get_dst(args, caller_sp, &dst); + if (res) { + /* Tried to send message to an incorrect endpoint */ + ffa_set_error(args, res); + return caller_sp; + } + if (!dst) { + EMSG("Request to normal world not supported"); + ffa_set_error(args, FFA_NOT_SUPPORTED); + return NULL; + } + + cpu_spin_lock(&dst->spinlock); + if (dst->state != sp_idle) { + DMSG("SP is busy"); + ffa_set_error(args, FFA_BUSY); + cpu_spin_unlock(&dst->spinlock); + return caller_sp; + } + + dst->state = sp_busy; + cpu_spin_unlock(&dst->spinlock); + + /* + * Store the calling endpoint id. This will make it possible to check + * if the response is sent back to the correct endpoint. + */ + dst->caller_id = FFA_SRC(args->a1); + + /* Forward the message to the destination SP */ + res = sp_enter(args, dst); + if (res) { + /* The SP Panicked */ + ffa_set_error(args, FFA_ABORTED); + /* Return error to calling SP */ + return caller_sp; + } + + return dst; +} + +static struct sp_session * +ffa_handle_sp_direct_resp(struct thread_smc_args *args, + struct sp_session *caller_sp) +{ + struct sp_session *dst = NULL; + TEE_Result res = FFA_OK; + + if (!caller_sp) { + EMSG("Response from normal world not supported"); + ffa_set_error(args, FFA_NOT_SUPPORTED); + return NULL; + } + + res = ffa_get_dst(args, caller_sp, &dst); + if (res) { + /* Tried to send response to an incorrect endpoint */ + ffa_set_error(args, res); + return caller_sp; + } + + if (caller_sp->state != sp_busy) { + EMSG("SP is not waiting for a request"); + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + if (caller_sp->caller_id != FFA_DST(args->a1)) { + EMSG("FFA_MSG_SEND_DIRECT_RESP to incorrect SP"); + ffa_set_error(args, FFA_INVALID_PARAMETERS); + return caller_sp; + } + + caller_sp->caller_id = 0; + + cpu_spin_lock(&caller_sp->spinlock); + caller_sp->state = sp_idle; + cpu_spin_unlock(&caller_sp->spinlock); + + if (!dst) { + /* Send message back to the NW */ + return NULL; + } + + /* Forward the message to the destination SP */ + res = sp_enter(args, dst); + if (res) { + /* The SP Panicked */ + ffa_set_error(args, FFA_ABORTED); + /* Return error to calling SP */ + return caller_sp; + } + return dst; +} + +static struct sp_session * +ffa_handle_sp_error(struct thread_smc_args *args, + struct sp_session *caller_sp) +{ + struct sp_session *dst = NULL; + + dst = sp_get_session(FFA_DST(args->a1)); + + /* FFA_ERROR Came from Noral World */ + if (caller_sp) + caller_sp->state = sp_idle; + + /* If dst == NULL send message to Normal World */ + if (dst && sp_enter(args, dst)) { + /* + * We can not return the error. Unwind the call chain with one + * link. Set the state of the SP to dead. + */ + dst->state = sp_dead; + /* Create error. */ + ffa_set_error(args, FFA_DENIED); + return sp_get_session(dst->caller_id); + } + + return dst; +} + +static void handle_features(struct thread_smc_args *args) +{ + uint32_t ret_fid = 0; + uint32_t ret_w2 = FFA_PARAM_MBZ; + + switch (args->a1) { +#ifdef ARM64 + case FFA_RXTX_MAP_64: +#endif + case FFA_RXTX_MAP_32: + ret_fid = FFA_SUCCESS_32; + ret_w2 = 0; /* 4kB Minimum buffer size and alignment boundary */ + break; + case FFA_ERROR: + case FFA_VERSION: + case FFA_SUCCESS_32: +#ifdef ARM64 + case FFA_SUCCESS_64: +#endif + default: + ret_fid = FFA_ERROR; + ret_w2 = FFA_NOT_SUPPORTED; + break; + } + + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_w2, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +static void handle_mem_perm_get(struct thread_smc_args *args, + struct sp_session *sp_s) +{ + struct sp_ctx *sp_ctx = NULL; + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + uint16_t attrs = 0; + uint32_t ret_fid = FFA_ERROR; + uint32_t ret_val = FFA_INVALID_PARAMETERS; + + /* + * The FFA_MEM_PERM_GET interface is only allowed during initialization + */ + if (sp_s->is_initialized) { + ret_val = FFA_DENIED; + goto out; + } + + sp_ctx = to_sp_ctx(sp_s->ts_sess.ctx); + if (!sp_ctx) + goto out; + + /* Query memory attributes */ + ts_push_current_session(&sp_s->ts_sess); + res = vm_get_prot(&sp_ctx->uctx, args->a1, SMALL_PAGE_SIZE, &attrs); + ts_pop_current_session(); + if (res) + goto out; + + /* Build response value */ + ret_fid = FFA_SUCCESS_32; + ret_val = 0; + if ((attrs & TEE_MATTR_URW) == TEE_MATTR_URW) + ret_val |= FFA_MEM_PERM_RW; + else if (attrs & TEE_MATTR_UR) + ret_val |= FFA_MEM_PERM_RO; + + if ((attrs & TEE_MATTR_UX) == 0) + ret_val |= FFA_MEM_PERM_NX; + +out: + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_val, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +static void handle_mem_perm_set(struct thread_smc_args *args, + struct sp_session *sp_s) +{ + struct sp_ctx *sp_ctx = NULL; + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + size_t region_size = 0; + uint32_t data_perm = 0; + uint32_t instruction_perm = 0; + uint16_t attrs = 0; + uint32_t ret_fid = FFA_ERROR; + uint32_t ret_val = FFA_INVALID_PARAMETERS; + + /* + * The FFA_MEM_PERM_GET interface is only allowed during initialization + */ + if (sp_s->is_initialized) { + ret_val = FFA_DENIED; + goto out; + } + + sp_ctx = to_sp_ctx(sp_s->ts_sess.ctx); + if (!sp_ctx) + goto out; + + if (MUL_OVERFLOW(args->a2, SMALL_PAGE_SIZE, ®ion_size)) + goto out; + + if (args->a3 & FFA_MEM_PERM_RESERVED) { + /* Non-zero reserved bits */ + goto out; + } + + data_perm = args->a3 & FFA_MEM_PERM_DATA_PERM; + instruction_perm = args->a3 & FFA_MEM_PERM_INSTRUCTION_PERM; + + /* RWX access right configuration is not permitted */ + if (data_perm == FFA_MEM_PERM_RW && instruction_perm == FFA_MEM_PERM_X) + goto out; + + switch (data_perm) { + case FFA_MEM_PERM_RO: + attrs = TEE_MATTR_UR; + break; + case FFA_MEM_PERM_RW: + attrs = TEE_MATTR_URW; + break; + default: + /* Invalid permission value */ + goto out; + } + + if (instruction_perm == FFA_MEM_PERM_X) + attrs |= TEE_MATTR_UX; + + /* Set access rights */ + ts_push_current_session(&sp_s->ts_sess); + res = vm_set_prot(&sp_ctx->uctx, args->a1, region_size, attrs); + ts_pop_current_session(); + if (res != TEE_SUCCESS) + goto out; + + ret_fid = FFA_SUCCESS_32; + ret_val = FFA_PARAM_MBZ; + +out: + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_val, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +/* + * FF-A messages handler for SP. Every messages for or from a SP is handled + * here. This is the entry of the sp_spmc kernel thread. The caller_sp is set + * to NULL when it is the Normal World. + */ +void spmc_sp_msg_handler(struct thread_smc_args *args, + struct sp_session *caller_sp) +{ + thread_check_canaries(); + do { + switch (args->a0) { +#ifdef ARM64 + case FFA_MSG_SEND_DIRECT_REQ_64: +#endif + case FFA_MSG_SEND_DIRECT_REQ_32: + caller_sp = ffa_handle_sp_direct_req(args, caller_sp); + break; +#ifdef ARM64 + case FFA_MSG_SEND_DIRECT_RESP_64: +#endif + case FFA_MSG_SEND_DIRECT_RESP_32: + caller_sp = ffa_handle_sp_direct_resp(args, caller_sp); + break; + case FFA_ERROR: + caller_sp = ffa_handle_sp_error(args, caller_sp); + break; + case FFA_MSG_WAIT: + /* FFA_WAIT gives control back to NW */ + cpu_spin_lock(&caller_sp->spinlock); + caller_sp->state = sp_idle; + cpu_spin_unlock(&caller_sp->spinlock); + caller_sp = NULL; + break; +#ifdef ARM64 + case FFA_RXTX_MAP_64: +#endif + case FFA_RXTX_MAP_32: + ts_push_current_session(&caller_sp->ts_sess); + spmc_handle_rxtx_map(args, &caller_sp->rxtx); + ts_pop_current_session(); + sp_enter(args, caller_sp); + break; + case FFA_RXTX_UNMAP: + ts_push_current_session(&caller_sp->ts_sess); + spmc_handle_rxtx_unmap(args, &caller_sp->rxtx); + ts_pop_current_session(); + sp_enter(args, caller_sp); + break; + case FFA_RX_RELEASE: + ts_push_current_session(&caller_sp->ts_sess); + spmc_handle_rx_release(args, &caller_sp->rxtx); + ts_pop_current_session(); + sp_enter(args, caller_sp); + break; + case FFA_ID_GET: + args->a0 = FFA_SUCCESS_32; + args->a2 = caller_sp->endpoint_id; + sp_enter(args, caller_sp); + break; + case FFA_VERSION: + spmc_handle_version(args); + sp_enter(args, caller_sp); + break; + case FFA_FEATURES: + handle_features(args); + sp_enter(args, caller_sp); + break; + case FFA_PARTITION_INFO_GET: + ts_push_current_session(&caller_sp->ts_sess); + spmc_handle_partition_info_get(args, &caller_sp->rxtx); + ts_pop_current_session(); + sp_enter(args, caller_sp); + break; +#ifdef ARM64 + case FFA_MEM_SHARE_64: +#endif + case FFA_MEM_SHARE_32: + ts_push_current_session(&caller_sp->ts_sess); + spmc_sp_handle_mem_share(args, &caller_sp->rxtx, + caller_sp); + ts_pop_current_session(); + sp_enter(args, caller_sp); + break; +#ifdef ARM64 + case FFA_MEM_RETRIEVE_REQ_64: +#endif + case FFA_MEM_RETRIEVE_REQ_32: + ts_push_current_session(&caller_sp->ts_sess); + ffa_mem_retrieve(args, caller_sp, &caller_sp->rxtx); + ts_pop_current_session(); + sp_enter(args, caller_sp); + break; + case FFA_MEM_RELINQUISH: + ts_push_current_session(&caller_sp->ts_sess); + ffa_mem_relinquish(args, caller_sp, &caller_sp->rxtx); + ts_pop_current_session(); + sp_enter(args, caller_sp); + break; + case FFA_MEM_RECLAIM: + ffa_mem_reclaim(args, caller_sp); + sp_enter(args, caller_sp); + break; +#ifdef ARM64 + case FFA_MEM_PERM_GET_64: +#endif + case FFA_MEM_PERM_GET_32: + handle_mem_perm_get(args, caller_sp); + sp_enter(args, caller_sp); + break; + +#ifdef ARM64 + case FFA_MEM_PERM_SET_64: +#endif + case FFA_MEM_PERM_SET_32: + handle_mem_perm_set(args, caller_sp); + sp_enter(args, caller_sp); + break; + default: + EMSG("Unhandled FFA function ID %#"PRIx32, + (uint32_t)args->a0); + ffa_set_error(args, FFA_INVALID_PARAMETERS); + sp_enter(args, caller_sp); + } + } while (caller_sp); +} diff --git a/optee/optee_os/core/arch/arm/kernel/stmm_sp.c b/optee/optee_os/core/arch/arm/kernel/stmm_sp.c new file mode 100644 index 0000000..3190e4f --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/stmm_sp.c @@ -0,0 +1,1132 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef ARM64 +#define SVC_REGS_A0(_regs) ((_regs)->x0) +#define SVC_REGS_A1(_regs) ((_regs)->x1) +#define SVC_REGS_A2(_regs) ((_regs)->x2) +#define SVC_REGS_A3(_regs) ((_regs)->x3) +#define SVC_REGS_A4(_regs) ((_regs)->x4) +#define SVC_REGS_A5(_regs) ((_regs)->x5) +#define SVC_REGS_A6(_regs) ((_regs)->x6) +#define SVC_REGS_A7(_regs) ((_regs)->x7) +#define __FFA_SVC_RPMB_READ FFA_SVC_RPMB_READ +#define __FFA_SVC_RPMB_WRITE FFA_SVC_RPMB_WRITE +#define __FFA_SVC_MEMORY_ATTRIBUTES_GET FFA_SVC_MEMORY_ATTRIBUTES_GET_64 +#define __FFA_SVC_MEMORY_ATTRIBUTES_SET FFA_SVC_MEMORY_ATTRIBUTES_SET_64 +#define __FFA_MSG_SEND_DIRECT_RESP FFA_MSG_SEND_DIRECT_RESP_64 +#define __FFA_MSG_SEND_DIRECT_REQ FFA_MSG_SEND_DIRECT_REQ_64 +#endif +#ifdef ARM32 +#define SVC_REGS_A0(_regs) ((_regs)->r0) +#define SVC_REGS_A1(_regs) ((_regs)->r1) +#define SVC_REGS_A2(_regs) ((_regs)->r2) +#define SVC_REGS_A3(_regs) ((_regs)->r3) +#define SVC_REGS_A4(_regs) ((_regs)->r4) +#define SVC_REGS_A5(_regs) ((_regs)->r5) +#define SVC_REGS_A6(_regs) ((_regs)->r6) +#define SVC_REGS_A7(_regs) ((_regs)->r7) +#define __FFA_SVC_RPMB_READ FFA_SVC_RPMB_READ_32 +#define __FFA_SVC_RPMB_WRITE FFA_SVC_RPMB_WRITE_32 +#define __FFA_SVC_MEMORY_ATTRIBUTES_GET FFA_SVC_MEMORY_ATTRIBUTES_GET_32 +#define __FFA_SVC_MEMORY_ATTRIBUTES_SET FFA_SVC_MEMORY_ATTRIBUTES_SET_32 +#define __FFA_MSG_SEND_DIRECT_RESP FFA_MSG_SEND_DIRECT_RESP_32 +#define __FFA_MSG_SEND_DIRECT_REQ FFA_MSG_SEND_DIRECT_REQ_32 +#endif + +#define MEM_READ_ACCESS BIT(0) +#define MEM_WRITE_ACCESS BIT(1) +#define MEM_EXECUTABLE_ACCESS BIT(2) +#define MEM_NS_ACCESS BIT(3) + +static const TEE_UUID stmm_uuid = PTA_STMM_UUID; + +/* + * Once a complete FFA spec is added, these will become discoverable. + * Until then these are considered part of the internal ABI between + * OP-TEE and StMM. + */ +static const uint16_t stmm_id = 1U; +static const uint16_t stmm_pta_id = 2U; +static const uint16_t mem_mgr_id = 3U; +static const uint16_t ffa_storage_id = 4U; + +static const unsigned int stmm_stack_size = 4 * SMALL_PAGE_SIZE; +static const unsigned int stmm_heap_size = 750 * SMALL_PAGE_SIZE; +static const unsigned int stmm_sec_buf_size = 21 * SMALL_PAGE_SIZE; +static const unsigned int stmm_ns_comm_buf_size = 21 * SMALL_PAGE_SIZE; + +extern unsigned char stmm_image[]; +extern const unsigned int stmm_image_size; +extern const unsigned int stmm_image_uncompressed_size; + +static struct device_region_dt stmm_dt_device_regions[MAX_DEVICE_REGIONS]; +static uint32_t stmm_dt_device_regions_len = 0; + +const TEE_UUID *stmm_get_uuid(void) +{ + return &stmm_uuid; +} + +static struct stmm_ctx *stmm_alloc_ctx(const TEE_UUID *uuid) +{ + TEE_Result res = TEE_SUCCESS; + struct stmm_ctx *spc = NULL; + + spc = calloc(1, sizeof(*spc)); + if (!spc) + return NULL; + + spc->ta_ctx.ts_ctx.ops = &stmm_sp_ops; + spc->ta_ctx.ts_ctx.uuid = *uuid; + spc->ta_ctx.flags = TA_FLAG_SINGLE_INSTANCE | + TA_FLAG_INSTANCE_KEEP_ALIVE; + + res = vm_info_init(&spc->uctx, &spc->ta_ctx.ts_ctx); + if (res) { + free(spc); + return NULL; + } + + spc->ta_ctx.ref_count = 1; + condvar_init(&spc->ta_ctx.busy_cv); + + return spc; +} + +static TEE_Result stmm_enter_user_mode(struct stmm_ctx *spc) +{ + uint32_t exceptions = 0; + uint32_t panic_code = 0; + uint32_t panicked = 0; + uint64_t cntkctl = 0; + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + cntkctl = read_cntkctl(); + write_cntkctl(cntkctl | CNTKCTL_PL0PCTEN); + +#ifdef ARM32 + /* Handle usr_lr in place of __thread_enter_user_mode() */ + thread_set_usr_lr(spc->regs.usr_lr); +#endif + + __thread_enter_user_mode(&spc->regs, &panicked, &panic_code); + +#ifdef ARM32 + spc->regs.usr_lr = thread_get_usr_lr(); +#endif + + write_cntkctl(cntkctl); + thread_unmask_exceptions(exceptions); + + thread_user_clear_vfp(&spc->uctx); + + if (panicked) { + abort_print_current_ts(); + DMSG("stmm panicked with code %#"PRIx32, panic_code); + return TEE_ERROR_TARGET_DEAD; + } + + return TEE_SUCCESS; +} + +#ifdef ARM64 +static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0, + unsigned long a1, unsigned long sp, unsigned long pc) +{ + spc->regs.x[0] = a0; + spc->regs.x[1] = a1; + spc->regs.sp = sp; + spc->regs.pc = pc; +} +#endif + +#ifdef ARM32 +static uint32_t __maybe_unused get_spsr(void) +{ + uint32_t s = 0; + + s = read_cpsr(); + s &= ~(CPSR_MODE_MASK | CPSR_T | ARM32_CPSR_IT_MASK); + s |= CPSR_MODE_USR; + + return s; +} + +static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0, + unsigned long a1, unsigned long sp, unsigned long pc) +{ + spc->regs.r0 = a0; + spc->regs.r1 = a1; + spc->regs.usr_sp = sp; + spc->regs.cpsr = get_spsr(); + spc->regs.pc = pc; +} +#endif + +static TEE_Result alloc_and_map_sp_fobj(struct stmm_ctx *spc, size_t sz, + uint32_t prot, vaddr_t *va) +{ + size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; + struct fobj *fobj = fobj_ta_mem_alloc(num_pgs); + TEE_Result res = TEE_SUCCESS; + struct mobj *mobj = NULL; + + mobj = mobj_with_fobj_alloc(fobj, NULL, TEE_MATTR_MEM_TYPE_TAGGED); + fobj_put(fobj); + if (!mobj) + return TEE_ERROR_OUT_OF_MEMORY; + + res = vm_map(&spc->uctx, va, num_pgs * SMALL_PAGE_SIZE, + prot, 0, mobj, 0); + if (res) + mobj_put(mobj); + + return TEE_SUCCESS; +} + +static void *zalloc(void *opaque __unused, unsigned int items, + unsigned int size) +{ + return mempool_alloc(mempool_default, items * size); +} + +static void zfree(void *opaque __unused, void *address) +{ + mempool_free(mempool_default, address); +} + +static void uncompress_image(void *dst, size_t dst_size, void *src, + size_t src_size) +{ + z_stream strm = { + .next_in = src, + .avail_in = src_size, + .next_out = dst, + .avail_out = dst_size, + .zalloc = zalloc, + .zfree = zfree, + }; + + if (inflateInit(&strm) != Z_OK) + panic("inflateInit"); + + if (inflate(&strm, Z_SYNC_FLUSH) != Z_STREAM_END) + panic("inflate"); + + if (inflateEnd(&strm) != Z_OK) + panic("inflateEnd"); +} + +static TEE_Result map_region(struct stmm_ctx *ctx, uint64_t pa, + size_t num_pgs, uint32_t prot, vaddr_t *va) +{ + struct mobj *mobj = NULL; + TEE_Result res = TEE_SUCCESS; + + mobj = mobj_phys_alloc(pa, num_pgs * SMALL_PAGE_SIZE, + TEE_MATTR_MEM_TYPE_DEV, CORE_MEM_DEVICE); + if (mobj == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + res = vm_map(&ctx->uctx, va, num_pgs * SMALL_PAGE_SIZE, prot, + VM_FLAG_EPHEMERAL, mobj, 0); + if (res) + mobj_put(mobj); + + return res; +} + +static TEE_Result stmm_sp_map_device_regions(struct stmm_ctx *ctx, + struct stmm_boot_info *boot_info) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t i = 0; + struct device_region *dr = NULL; + struct device_region_dt *drd = NULL; + vaddr_t va; + + boot_info->device_regions_len = 0; + for (i = 0; i < stmm_dt_device_regions_len; i++) { + dr = &boot_info->device_regions[i]; + drd = &stmm_dt_device_regions[i]; + + memset(dr->name, 0, DEVICE_REGION_NAME_LEN); + memcpy(dr->name, drd->name, strlen(drd->name)); + dr->size = drd->page_count * SMALL_PAGE_SIZE; + + va = 0; + ret = map_region(ctx, drd->pa, drd->page_count, drd->prot, &va); + if (ret != TEE_SUCCESS) { + EMSG("Map device: %s, pa: 0x%lx, sz: 0x%x, prot: 0x%x failed: 0x%x", + dr->name, drd->pa, drd->page_count, drd->prot, ret); + break; + } + dr->va = va; + + DMSG("Mapped device: %s, pa: 0x%lx, " + "sz: 0x%x, prot: 0x%x to 0x%lx", + dr->name, drd->pa, drd->page_count, drd->prot, (uint64_t)va); + boot_info->device_regions_len++; + } + + return ret; +} + +static TEE_Result load_stmm(struct stmm_ctx *spc) +{ + struct stmm_boot_info *boot_info = NULL; + struct stmm_mp_info *mp_info = NULL; + TEE_Result res = TEE_SUCCESS; + vaddr_t sp_addr = 0; + vaddr_t image_addr = 0; + vaddr_t heap_addr = 0; + vaddr_t stack_addr = 0; + vaddr_t sec_buf_addr = 0; + vaddr_t comm_buf_addr = 0; + unsigned int sp_size = 0; + unsigned int uncompressed_size_roundup = 0; + + uncompressed_size_roundup = ROUNDUP(stmm_image_uncompressed_size, + SMALL_PAGE_SIZE); + sp_size = uncompressed_size_roundup + stmm_stack_size + + stmm_heap_size + stmm_sec_buf_size; + res = alloc_and_map_sp_fobj(spc, sp_size, + TEE_MATTR_PRW, &sp_addr); + if (res) + return res; + + res = alloc_and_map_sp_fobj(spc, stmm_ns_comm_buf_size, + TEE_MATTR_URW | TEE_MATTR_PRW, + &comm_buf_addr); + /* + * We don't need to free the previous instance here, they'll all be + * handled during the destruction call (stmm_ctx_destroy()) + */ + if (res) + return res; + + image_addr = sp_addr; + heap_addr = image_addr + uncompressed_size_roundup; + stack_addr = heap_addr + stmm_heap_size; + sec_buf_addr = stack_addr + stmm_stack_size; + + vm_set_ctx(&spc->ta_ctx.ts_ctx); + uncompress_image((void *)image_addr, stmm_image_uncompressed_size, + stmm_image, stmm_image_size); + + res = vm_set_prot(&spc->uctx, image_addr, uncompressed_size_roundup, + TEE_MATTR_URX | TEE_MATTR_PR); + if (res) + return res; + + res = vm_set_prot(&spc->uctx, heap_addr, stmm_heap_size, + TEE_MATTR_URW | TEE_MATTR_PRW); + if (res) + return res; + + res = vm_set_prot(&spc->uctx, stack_addr, stmm_stack_size, + TEE_MATTR_URW | TEE_MATTR_PRW); + if (res) + return res; + + res = vm_set_prot(&spc->uctx, sec_buf_addr, stmm_sec_buf_size, + TEE_MATTR_URW | TEE_MATTR_PRW); + if (res) + return res; + + DMSG("stmm load address %#"PRIxVA, image_addr); + + boot_info = (struct stmm_boot_info *)sec_buf_addr; + mp_info = (struct stmm_mp_info *)(boot_info + 1); + *boot_info = (struct stmm_boot_info){ + .h.type = STMM_PARAM_SP_IMAGE_BOOT_INFO, + .h.version = STMM_PARAM_VERSION_1, + .h.size = sizeof(struct stmm_boot_info), + .h.attr = 0, + .sp_mem_base = sp_addr, + .sp_mem_limit = sp_addr + sp_size, + .sp_image_base = image_addr, + .sp_stack_base = stack_addr, + .sp_heap_base = heap_addr, + .sp_ns_comm_buf_base = comm_buf_addr, + .sp_shared_buf_base = sec_buf_addr, + .sp_image_size = stmm_image_size, + .sp_pcpu_stack_size = stmm_stack_size, + .sp_heap_size = stmm_heap_size, + .sp_ns_comm_buf_size = stmm_ns_comm_buf_size, + .sp_shared_buf_size = stmm_sec_buf_size, + .num_sp_mem_regions = 6, + .num_cpus = 1, + .mp_info = mp_info, + }; + mp_info->mpidr = read_mpidr(); + mp_info->linear_id = 0; + mp_info->flags = MP_INFO_FLAG_PRIMARY_CPU; + spc->ns_comm_buf_addr = comm_buf_addr; + spc->ns_comm_buf_size = stmm_ns_comm_buf_size; + + res = stmm_sp_map_device_regions(spc, boot_info); + if (res != TEE_SUCCESS) + return res; + + init_stmm_regs(spc, sec_buf_addr, + (vaddr_t)(mp_info + 1) - sec_buf_addr, + stack_addr + stmm_stack_size, image_addr); + + return stmm_enter_user_mode(spc); +} + +TEE_Result stmm_init_session(const TEE_UUID *uuid, struct tee_ta_session *sess) +{ + struct stmm_ctx *spc = NULL; + TEE_Result res = TEE_SUCCESS; + + if (memcmp(uuid, &stmm_uuid, sizeof(*uuid))) + return TEE_ERROR_ITEM_NOT_FOUND; + + spc = stmm_alloc_ctx(uuid); + if (!spc) + return TEE_ERROR_OUT_OF_MEMORY; + + spc->is_initializing = true; + + mutex_lock(&tee_ta_mutex); + sess->ts_sess.ctx = &spc->ta_ctx.ts_ctx; + sess->ts_sess.handle_scall = sess->ts_sess.ctx->ops->handle_scall; + mutex_unlock(&tee_ta_mutex); + + ts_push_current_session(&sess->ts_sess); + res = load_stmm(spc); + ts_pop_current_session(); + vm_set_ctx(NULL); + if (res) { + sess->ts_sess.ctx = NULL; + spc->ta_ctx.ts_ctx.ops->destroy(&spc->ta_ctx.ts_ctx); + + return res; + } + + mutex_lock(&tee_ta_mutex); + spc->is_initializing = false; + TAILQ_INSERT_TAIL(&tee_ctxes, &spc->ta_ctx, link); + mutex_unlock(&tee_ta_mutex); + + return TEE_SUCCESS; +} + +static TEE_Result stmm_enter_open_session(struct ts_session *s) +{ + struct stmm_ctx *spc = to_stmm_ctx(s->ctx); + struct tee_ta_session *ta_sess = to_ta_session(s); + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (ta_sess->param->types != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (spc->is_initializing) { + /* StMM is initialized in stmm_init_session() */ + ta_sess->err_origin = TEE_ORIGIN_TEE; + return TEE_ERROR_BAD_STATE; + } + + return TEE_SUCCESS; +} + +static TEE_Result stmm_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) +{ + struct stmm_ctx *spc = to_stmm_ctx(s->ctx); + struct tee_ta_session *ta_sess = to_ta_session(s); + TEE_Result res = TEE_SUCCESS; + TEE_Result __maybe_unused tmp_res = TEE_SUCCESS; + unsigned int ns_buf_size = 0; + struct param_mem *mem = NULL; + void *va = NULL; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (cmd != PTA_STMM_CMD_COMMUNICATE) + return TEE_ERROR_BAD_PARAMETERS; + + if (ta_sess->param->types != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + mem = &ta_sess->param->u[0].mem; + ns_buf_size = mem->size; + if (ns_buf_size > spc->ns_comm_buf_size) { + mem->size = spc->ns_comm_buf_size; + return TEE_ERROR_EXCESS_DATA; + } + + res = mobj_inc_map(mem->mobj); + if (res) + return res; + + va = mobj_get_va(mem->mobj, mem->offs, mem->size); + if (!va) { + EMSG("Can't get a valid VA for NS buffer"); + res = TEE_ERROR_BAD_PARAMETERS; + goto out_va; + } + +#ifdef ARM64 + spc->regs.x[0] = __FFA_MSG_SEND_DIRECT_REQ; + spc->regs.x[1] = (stmm_pta_id << 16) | stmm_id; + spc->regs.x[2] = FFA_PARAM_MBZ; + spc->regs.x[3] = spc->ns_comm_buf_addr; + spc->regs.x[4] = ns_buf_size; + spc->regs.x[5] = 0; + spc->regs.x[6] = 0; + spc->regs.x[7] = 0; +#endif +#ifdef ARM32 + spc->regs.r0 = __FFA_MSG_SEND_DIRECT_REQ; + spc->regs.r1 = (stmm_pta_id << 16) | stmm_id; + spc->regs.r2 = FFA_PARAM_MBZ; + spc->regs.r3 = spc->ns_comm_buf_addr; + spc->regs.r4 = ns_buf_size; + spc->regs.r5 = 0; + spc->regs.r6 = 0; + spc->regs.r7 = 0; +#endif + + ts_push_current_session(s); + + memcpy((void *)spc->ns_comm_buf_addr, va, ns_buf_size); + + res = stmm_enter_user_mode(spc); + if (res) + goto out_session; + /* + * Copy the SPM response from secure partition back to the non-secure + * buffer of the client that called us. + */ +#ifdef ARM64 + ta_sess->param->u[1].val.a = spc->regs.x[4]; +#endif +#ifdef ARM32 + ta_sess->param->u[1].val.a = spc->regs.r4; +#endif + + memcpy(va, (void *)spc->ns_comm_buf_addr, ns_buf_size); + +out_session: + ts_pop_current_session(); +out_va: + tmp_res = mobj_dec_map(mem->mobj); + assert(!tmp_res); + + return res; +} + +static void stmm_enter_close_session(struct ts_session *s __unused) +{ +} + +static void stmm_dump_state(struct ts_ctx *ctx) +{ + user_mode_ctx_print_mappings(to_user_mode_ctx(ctx)); +} +DECLARE_KEEP_PAGER(stmm_dump_state); + +static uint32_t stmm_get_instance_id(struct ts_ctx *ctx) +{ + return to_stmm_ctx(ctx)->uctx.vm_info.asid; +} + +static void stmm_ctx_destroy(struct ts_ctx *ctx) +{ + struct stmm_ctx *spc = to_stmm_ctx(ctx); + + vm_info_final(&spc->uctx); + free(spc); +} + +static uint32_t sp_svc_get_mem_attr(vaddr_t va) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + struct ts_session *sess = NULL; + struct stmm_ctx *spc = NULL; + uint16_t attrs = 0; + uint16_t perm = 0; + + if (!va) + goto err; + + sess = ts_get_current_session(); + spc = to_stmm_ctx(sess->ctx); + + res = vm_get_prot(&spc->uctx, va, SMALL_PAGE_SIZE, &attrs); + if (res) + goto err; + + if (attrs & TEE_MATTR_UR) + perm |= STMM_MEM_ATTR_ACCESS_RO; + else if (attrs & TEE_MATTR_UW) + perm |= STMM_MEM_ATTR_ACCESS_RW; + + if (attrs & TEE_MATTR_UX) + perm |= STMM_MEM_ATTR_EXEC; + + return perm; +err: + return STMM_RET_DENIED; +} + +static int sp_svc_set_mem_attr(vaddr_t va, unsigned int nr_pages, uint32_t perm) +{ + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + struct ts_session *sess = NULL; + struct stmm_ctx *spc = NULL; + size_t sz = 0; + uint32_t prot = 0; + + if (!va || !nr_pages || MUL_OVERFLOW(nr_pages, SMALL_PAGE_SIZE, &sz)) + return STMM_RET_INVALID_PARAM; + + if (perm & ~STMM_MEM_ATTR_ALL) + return STMM_RET_INVALID_PARAM; + + sess = ts_get_current_session(); + spc = to_stmm_ctx(sess->ctx); + + if ((perm & STMM_MEM_ATTR_ACCESS_MASK) == STMM_MEM_ATTR_ACCESS_RO) + prot |= TEE_MATTR_UR; + else if ((perm & STMM_MEM_ATTR_ACCESS_MASK) == STMM_MEM_ATTR_ACCESS_RW) + prot |= TEE_MATTR_URW; + + if ((perm & STMM_MEM_ATTR_EXEC_NEVER) == STMM_MEM_ATTR_EXEC) + prot |= TEE_MATTR_UX; + + res = vm_set_prot(&spc->uctx, va, sz, prot); + if (res) + return STMM_RET_DENIED; + + return STMM_RET_SUCCESS; +} + +#ifdef ARM64 +static void save_sp_ctx(struct stmm_ctx *spc, + struct thread_scall_regs *regs) +{ + size_t n = 0; + + /* Save the return values from StMM */ + for (n = 0; n <= 7; n++) + spc->regs.x[n] = *(®s->x0 + n); + + spc->regs.sp = regs->sp_el0; + spc->regs.pc = regs->elr; + spc->regs.cpsr = regs->spsr; +} +#endif + +#ifdef ARM32 +static void save_sp_ctx(struct stmm_ctx *spc, + struct thread_scall_regs *regs) +{ + spc->regs.r0 = regs->r0; + spc->regs.r1 = regs->r1; + spc->regs.r2 = regs->r2; + spc->regs.r3 = regs->r3; + spc->regs.r4 = regs->r4; + spc->regs.r5 = regs->r5; + spc->regs.r6 = regs->r6; + spc->regs.r7 = regs->r7; + spc->regs.pc = regs->lr; + spc->regs.cpsr = regs->spsr; + spc->regs.usr_sp = thread_get_usr_sp(); +} +#endif + +static void return_from_sp_helper(bool panic, uint32_t panic_code, + struct thread_scall_regs *regs) +{ + struct ts_session *sess = ts_get_current_session(); + struct stmm_ctx *spc = to_stmm_ctx(sess->ctx); + + if (panic) + spc->ta_ctx.panicked = true; + else + save_sp_ctx(spc, regs); + + SVC_REGS_A0(regs) = 0; + SVC_REGS_A1(regs) = panic; + SVC_REGS_A2(regs) = panic_code; +} + +static void service_compose_direct_resp(struct thread_scall_regs *regs, + uint32_t ret_val) +{ + uint16_t src_id = 0; + uint16_t dst_id = 0; + + /* extract from request */ + src_id = (SVC_REGS_A1(regs) >> 16) & UINT16_MAX; + dst_id = SVC_REGS_A1(regs) & UINT16_MAX; + + /* compose message */ + SVC_REGS_A0(regs) = __FFA_MSG_SEND_DIRECT_RESP; + /* swap endpoint ids */ + SVC_REGS_A1(regs) = SHIFT_U32(dst_id, 16) | src_id; + SVC_REGS_A2(regs) = FFA_PARAM_MBZ; + SVC_REGS_A3(regs) = ret_val; + SVC_REGS_A4(regs) = 0; + SVC_REGS_A5(regs) = 0; + SVC_REGS_A6(regs) = 0; + SVC_REGS_A7(regs) = 0; +} + +/* + * Combined read from secure partition, this will open, read and + * close the file object. + */ +static TEE_Result sec_storage_obj_read(unsigned long storage_id, char *obj_id, + unsigned long obj_id_len, void *data, + unsigned long len, unsigned long offset, + unsigned long flags) +{ + const struct tee_file_operations *fops = NULL; + TEE_Result res = TEE_ERROR_BAD_STATE; + struct ts_session *sess = NULL; + struct tee_file_handle *fh = NULL; + struct stmm_ctx *spc = NULL; + struct tee_pobj *po = NULL; + size_t file_size = 0; + size_t read_len = 0; + + fops = tee_svc_storage_file_ops(storage_id); + if (!fops) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + sess = ts_get_current_session(); + spc = to_stmm_ctx(sess->ctx); + res = vm_check_access_rights(&spc->uctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)data, len); + if (res != TEE_SUCCESS) + return res; + + res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, + false, fops, &po); + if (res != TEE_SUCCESS) + return res; + + res = po->fops->open(po, &file_size, &fh); + if (res != TEE_SUCCESS) + goto out; + + read_len = len; + res = po->fops->read(fh, offset, data, &read_len); + if (res == TEE_ERROR_CORRUPT_OBJECT) { + EMSG("Object corrupt"); + po->fops->remove(po); + } else if (res == TEE_SUCCESS && len != read_len) { + res = TEE_ERROR_CORRUPT_OBJECT; + } + + po->fops->close(&fh); + +out: + tee_pobj_release(po); + + return res; +} + +/* + * Combined write from secure partition, this will create/open, write and + * close the file object. + */ +static TEE_Result sec_storage_obj_write(unsigned long storage_id, char *obj_id, + unsigned long obj_id_len, void *data, + unsigned long len, unsigned long offset, + unsigned long flags) + +{ + const struct tee_file_operations *fops = NULL; + struct ts_session *sess = NULL; + struct tee_file_handle *fh = NULL; + struct stmm_ctx *spc = NULL; + TEE_Result res = TEE_SUCCESS; + struct tee_pobj *po = NULL; + + fops = tee_svc_storage_file_ops(storage_id); + if (!fops) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + sess = ts_get_current_session(); + spc = to_stmm_ctx(sess->ctx); + res = vm_check_access_rights(&spc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)data, len); + if (res != TEE_SUCCESS) + return res; + + res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, + false, fops, &po); + if (res != TEE_SUCCESS) + return res; + + res = po->fops->open(po, NULL, &fh); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = po->fops->create(po, false, NULL, 0, NULL, 0, NULL, 0, + &fh); + if (res == TEE_SUCCESS) { + res = po->fops->write(fh, offset, data, len); + po->fops->close(&fh); + } + + tee_pobj_release(po); + + return res; +} + +static void stmm_handle_mem_mgr_service(struct thread_scall_regs *regs) +{ + uint32_t action = SVC_REGS_A3(regs); + uintptr_t va = SVC_REGS_A4(regs); + uint32_t nr_pages = SVC_REGS_A5(regs); + uint32_t perm = SVC_REGS_A6(regs); + + switch (action) { + case __FFA_SVC_MEMORY_ATTRIBUTES_GET: + service_compose_direct_resp(regs, sp_svc_get_mem_attr(va)); + break; + case __FFA_SVC_MEMORY_ATTRIBUTES_SET: + service_compose_direct_resp(regs, + sp_svc_set_mem_attr(va, nr_pages, + perm)); + break; + default: + EMSG("Undefined service id %#"PRIx32, action); + service_compose_direct_resp(regs, STMM_RET_INVALID_PARAM); + break; + } +} + +static uint32_t tee2stmm_ret_val(TEE_Result res) +{ + switch (res) { + case TEE_SUCCESS: + return STMM_RET_SUCCESS; + case TEE_ERROR_NOT_SUPPORTED: + return STMM_RET_NOT_SUPPORTED; + case TEE_ERROR_ACCESS_DENIED: + return STMM_RET_DENIED; + case TEE_ERROR_OUT_OF_MEMORY: + return STMM_RET_NO_MEM; + case TEE_ERROR_BAD_PARAMETERS: + default: + return STMM_RET_INVALID_PARAM; + } +} + +#define FILENAME "EFI_VARS" +static void stmm_handle_storage_service(struct thread_scall_regs *regs) +{ + uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE; + uint32_t action = SVC_REGS_A3(regs); + void *va = (void *)SVC_REGS_A4(regs); + unsigned long len = SVC_REGS_A5(regs); + unsigned long offset = SVC_REGS_A6(regs); + char obj_id[] = FILENAME; + size_t obj_id_len = strlen(obj_id); + TEE_Result res = TEE_SUCCESS; + uint32_t stmm_rc = STMM_RET_INVALID_PARAM; + + switch (action) { + case __FFA_SVC_RPMB_READ: + DMSG("RPMB read"); + res = sec_storage_obj_read(TEE_STORAGE_PRIVATE_RPMB, obj_id, + obj_id_len, va, len, offset, flags); + stmm_rc = tee2stmm_ret_val(res); + break; + case __FFA_SVC_RPMB_WRITE: + DMSG("RPMB write"); + res = sec_storage_obj_write(TEE_STORAGE_PRIVATE_RPMB, obj_id, + obj_id_len, va, len, offset, flags); + stmm_rc = tee2stmm_ret_val(res); + break; + default: + EMSG("Undefined service id %#"PRIx32, action); + break; + } + + service_compose_direct_resp(regs, stmm_rc); +} + +static void spm_eret_error(int32_t error_code, struct thread_scall_regs *regs) +{ + SVC_REGS_A0(regs) = FFA_ERROR; + SVC_REGS_A1(regs) = FFA_PARAM_MBZ; + SVC_REGS_A2(regs) = error_code; + SVC_REGS_A3(regs) = FFA_PARAM_MBZ; + SVC_REGS_A4(regs) = FFA_PARAM_MBZ; + SVC_REGS_A5(regs) = FFA_PARAM_MBZ; + SVC_REGS_A6(regs) = FFA_PARAM_MBZ; + SVC_REGS_A7(regs) = FFA_PARAM_MBZ; +} + +static void spm_handle_direct_req(struct thread_scall_regs *regs) +{ + uint16_t dst_id = SVC_REGS_A1(regs) & UINT16_MAX; + + if (dst_id == mem_mgr_id) { + stmm_handle_mem_mgr_service(regs); + } else if (dst_id == ffa_storage_id) { + stmm_handle_storage_service(regs); + } else { + EMSG("Undefined endpoint id %#"PRIx16, dst_id); + spm_eret_error(STMM_RET_INVALID_PARAM, regs); + } +} + +/* Return true if returning to SP, false if returning to caller */ +static bool spm_handle_scall(struct thread_scall_regs *regs) +{ +#ifdef ARM64 + uint64_t *a0 = ®s->x0; +#endif +#ifdef ARM32 + uint32_t *a0 = ®s->r0; +#endif + + switch (*a0) { + case FFA_VERSION: + DMSG("Received FFA version"); + *a0 = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR); + return true; + case __FFA_MSG_SEND_DIRECT_RESP: + DMSG("Received FFA direct response"); + return_from_sp_helper(false, 0, regs); + return false; + case __FFA_MSG_SEND_DIRECT_REQ: + DMSG("Received FFA direct request"); + spm_handle_direct_req(regs); + return true; + default: + EMSG("Undefined syscall %#"PRIx32, (uint32_t)*a0); + return_from_sp_helper(true /*panic*/, 0xabcd, regs); + return false; + } +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct ts_ops stmm_sp_ops __weak __relrodata_unpaged("stmm_sp_ops") = { + .enter_open_session = stmm_enter_open_session, + .enter_invoke_cmd = stmm_enter_invoke_cmd, + .enter_close_session = stmm_enter_close_session, + .dump_state = stmm_dump_state, + .destroy = stmm_ctx_destroy, + .get_instance_id = stmm_get_instance_id, + .handle_scall = spm_handle_scall, +}; + +static TEE_Result sp_dt_get_u64(void *fdt, int node, const char *property, + uint64_t *value) +{ + int len = 0; + const fdt32_t *cuint = NULL; + + cuint = fdt_getprop(fdt, node, property, &len); + if (!cuint || len != sizeof(uint64_t)) + return TEE_ERROR_ITEM_NOT_FOUND; + + *value = ((uint64_t)fdt32_to_cpu(cuint[0])) << 32 | + fdt32_to_cpu(cuint[1]); + return TEE_SUCCESS; +} + +static TEE_Result sp_dt_get_u32(void *fdt, int node, const char *property, + uint32_t *value) +{ + int len = 0; + const fdt32_t *cuint32 = NULL; + + cuint32 = fdt_getprop(fdt, node, property, &len); + if (!cuint32 || len != sizeof(*cuint32)) + return TEE_ERROR_ITEM_NOT_FOUND; + + *value = fdt32_to_cpu(*cuint32); + return TEE_SUCCESS; +} + +static TEE_Result stmm_sp_save_dt_device_regions(void *fdt, int off) +{ + int sp_node = 0; + int count = 0; + + if (!fdt) + return TEE_ERROR_ITEM_NOT_FOUND; + + off = fdt_subnode_offset(fdt, off, "device-regions"); + fdt_for_each_subnode(sp_node, fdt, off) { + uint64_t pa = 0; + uint32_t page_count = 0; + uint32_t attributes = 0; + uint32_t prot = 0; + const char *region_name = NULL; + struct device_region_dt *drd = NULL; + int name_len = 0; + + if (count > MAX_DEVICE_REGIONS) { + EMSG("Too many device regions in DT."); + return TEE_ERROR_OUT_OF_MEMORY; + } + + if (sp_dt_get_u64(fdt, sp_node, "base-address", &pa)) { + EMSG("No device region base-address defined, skip."); + continue; + } + + if (sp_dt_get_u32(fdt, sp_node, "pages-count", &page_count)) { + EMSG("No device region pages-count defined, skip."); + continue; + } + + if (sp_dt_get_u32(fdt, sp_node, "attributes", &attributes)) { + EMSG("No device region attributes defined, skip."); + continue; + } + + if (attributes & MEM_READ_ACCESS) + prot |= TEE_MATTR_UR; + + if (attributes & MEM_WRITE_ACCESS) + prot |= TEE_MATTR_UW; + + /* Device memory should not be executable */ + if (attributes & MEM_EXECUTABLE_ACCESS) { + EMSG("Device region mapped with executable, skip."); + continue; + } + + /* Enable secure memory when NS memory bit is not set */ + if (!(attributes & MEM_NS_ACCESS)) { + prot |= TEE_MATTR_SECURE; + } else { + EMSG("Device region mapped with NS access, skip."); + continue; + } + + prot |= TEE_MATTR_DEVICE; + prot |= TEE_MATTR_MEM_TYPE_DEV << TEE_MATTR_MEM_TYPE_SHIFT; + + region_name = fdt_get_name(fdt, sp_node, &name_len); + if (!region_name || name_len >= DEVICE_REGION_NAME_LEN) { + EMSG("Invalid device region name, skip."); + continue; + } + + drd = &stmm_dt_device_regions[count]; + memset(drd->name, 0, DEVICE_REGION_NAME_LEN); + memcpy(drd->name, region_name, name_len); + drd->pa = pa; + drd->page_count = page_count; + drd->prot = prot; + + DMSG("stmm_sp: parsed a device region: %s, pa: 0x%lx, page_count: %u, " + "prot: 0x%x", drd->name, drd->pa, drd->page_count, drd->prot); + count++; + } + + stmm_dt_device_regions_len = count; + return TEE_SUCCESS; +} + +bool stmm_is_device_mem_inside(paddr_t pa, size_t len) +{ + uint32_t i = 0; + bool ret = false; + + for (i = 0; i < stmm_dt_device_regions_len; i++) { + struct device_region_dt *drd = &stmm_dt_device_regions[i]; + if (core_is_buffer_inside(pa, len, drd->pa, + drd->page_count * SMALL_PAGE_SIZE)) { + ret = true; + break; + } + } + + return ret; +} + +static TEE_Result stmm_sp_parse_dt(void) +{ + void *fdt = NULL; + int sp_node = 0; + int node = 0; + const fdt32_t *cuint32 = NULL; + int len = 0; + + fdt = get_dt(); + if (!fdt) + return TEE_ERROR_ITEM_NOT_FOUND; + + node = fdt_path_offset(fdt, "/"); + fdt_for_each_subnode(sp_node, fdt, node) { + cuint32 = fdt_getprop(fdt, sp_node, "uuid", &len); + if (len != sizeof(TEE_UUID)) + continue; + + if (cuint32) { + TEE_UUID dt_uuid = {}; + tee_uuid_from_uint32_t(&dt_uuid, + fdt32_to_cpu(cuint32[0]), + fdt32_to_cpu(cuint32[1]), + fdt32_to_cpu(cuint32[2]), + fdt32_to_cpu(cuint32[3])); + if (memcmp(&dt_uuid, &stmm_uuid, sizeof(stmm_uuid))) + continue; + + return stmm_sp_save_dt_device_regions(fdt, sp_node); + } + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} +service_init(stmm_sp_parse_dt); diff --git a/optee/optee_os/core/arch/arm/kernel/sub.mk b/optee/optee_os/core/arch/arm/kernel/sub.mk new file mode 100644 index 0000000..49c5927 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/sub.mk @@ -0,0 +1,83 @@ +srcs-y += rpc_io_i2c.c +srcs-y += idle.c + +srcs-$(CFG_SECURE_TIME_SOURCE_CNTPCT) += tee_time_arm_cntpct.c +srcs-$(CFG_ARM64_core) += timer_a64.c + +srcs-$(CFG_ARM32_core) += spin_lock_a32.S +srcs-$(CFG_ARM64_core) += spin_lock_a64.S +srcs-$(CFG_ARM32_core) += tlb_helpers_a32.S +srcs-$(CFG_ARM64_core) += tlb_helpers_a64.S +srcs-$(CFG_ARM64_core) += cache_helpers_a64.S +srcs-$(CFG_ARM32_core) += cache_helpers_a32.S +srcs-$(CFG_PL310) += tz_ssvce_pl310_a32.S +srcs-$(CFG_PL310) += tee_l2cc_mutex.c + +srcs-$(CFG_ARM32_core) += thread_a32.S +srcs-$(CFG_ARM64_core) += thread_a64.S +srcs-y += thread.c +ifeq ($(CFG_WITH_USER_TA),y) +srcs-y += arch_scall.c +srcs-$(CFG_ARM32_core) += arch_scall_a32.S +srcs-$(CFG_ARM64_core) += arch_scall_a64.S +endif +ifeq ($(CFG_CORE_FFA),y) +srcs-y += thread_spmc.c +cppflags-thread_spmc.c-y += -DTEE_IMPL_GIT_SHA1=$(TEE_IMPL_GIT_SHA1) +srcs-$(CFG_ARM32_core) += thread_spmc_a32.S +srcs-$(CFG_ARM64_core) += thread_spmc_a64.S +else +srcs-y += thread_optee_smc.c +srcs-$(CFG_ARM32_core) += thread_optee_smc_a32.S +srcs-$(CFG_ARM64_core) += thread_optee_smc_a64.S +endif +srcs-y += abort.c +srcs-$(CFG_WITH_VFP) += vfp.c +ifeq ($(CFG_WITH_VFP),y) +srcs-$(CFG_ARM32_core) += vfp_a32.S +srcs-$(CFG_ARM64_core) += vfp_a64.S +endif +srcs-$(CFG_ARM32_core) += misc_a32.S +srcs-$(CFG_ARM64_core) += misc_a64.S +srcs-$(CFG_WITH_STMM_SP) += stmm_sp.c +srcs-$(CFG_SECURE_PARTITION) += secure_partition.c +srcs-$(CFG_SECURE_PARTITION) += spmc_sp_handler.c + +srcs-y += boot.c +srcs-$(CFG_ARM32_core) += entry_a32.S +srcs-$(CFG_ARM64_core) += entry_a64.S + +ifeq ($(CFG_UNWIND),y) +srcs-$(CFG_ARM32_core) += unwind_arm32.c +srcs-$(CFG_ARM64_core) += unwind_arm64.c +endif + +srcs-$(CFG_NS_VIRTUALIZATION) += virtualization.c + +srcs-y += link_dummies_paged.c +srcs-y += link_dummies_init.c + +asm-defines-y += asm-defines.c +# Reflect the following dependencies: +# asm-defines.c includes +# includes +# includes +# and (optional) +asm-defines-asm-defines.c-deps += $(out-dir)/core/include/generated/arm32_sysreg.h +ifeq ($(CFG_ARM_GICV3),y) +asm-defines-asm-defines.c-deps += $(out-dir)/core/include/generated/arm32_gicv3_sysreg.h +endif + +ifeq ($(CFG_SYSCALL_FTRACE),y) +# We would not like to profile thread.c file as it provide common APIs +# that are needed for ftrace framework to trace syscalls. So profiling +# this file could create an incorrect cyclic behaviour. +cflags-remove-thread.c-y += -pg +# Tracing abort dump files corrupts the stack trace. So exclude them +# from profiling. +cflags-remove-abort.c-y += -pg +ifeq ($(CFG_UNWIND),y) +cflags-remove-unwind_arm32.c-y += -pg +cflags-remove-unwind_arm64.c-$(CFG_ARM64_core) += -pg +endif +endif diff --git a/optee/optee_os/core/arch/arm/kernel/tee_l2cc_mutex.c b/optee/optee_os/core/arch/arm/kernel/tee_l2cc_mutex.c new file mode 100644 index 0000000..38e8f81 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/tee_l2cc_mutex.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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. + */ +#define MUTEX_SZ sizeof(uint32_t) + +static uint32_t *l2cc_mutex_va; +static uint32_t l2cc_mutex_pa; +static uint32_t l2cc_mutex_boot_pa; +static unsigned int *l2cc_mutex; + +void tee_l2cc_store_mutex_boot_pa(uint32_t pa) +{ + l2cc_mutex_boot_pa = pa; +} + +/* + * Allocate public RAM to get a L2CC mutex to shared with NSec. + * Return 0 on success. + */ +static int l2cc_mutex_alloc(void) +{ + void *va; + + if (l2cc_mutex_va != NULL) + return -1; + + l2cc_mutex_pa = l2cc_mutex_boot_pa; + + va = phys_to_virt(l2cc_mutex_pa, MEM_AREA_NSEC_SHM, MUTEX_SZ); + if (!va) + return -1; + + *(uint32_t *)va = 0; + l2cc_mutex_va = va; + return 0; +} + +static void l2cc_mutex_set(void *mutex) +{ + l2cc_mutex = (unsigned int *)mutex; +} + +/* + * tee_xxx_l2cc_mutex(): 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. + * + * 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. + */ +TEE_Result tee_enable_l2cc_mutex(void) +{ + int ret; + + if (!l2cc_mutex_va) { + ret = l2cc_mutex_alloc(); + if (ret) + return TEE_ERROR_GENERIC; + } + l2cc_mutex_set(l2cc_mutex_va); + return TEE_SUCCESS; +} + +TEE_Result tee_disable_l2cc_mutex(void) +{ + l2cc_mutex_va = NULL; + l2cc_mutex_set(NULL); + return TEE_SUCCESS; +} + +TEE_Result tee_get_l2cc_mutex(paddr_t *mutex) +{ + int ret; + + if (!l2cc_mutex_va) { + ret = l2cc_mutex_alloc(); + if (ret) + return TEE_ERROR_GENERIC; + } + *mutex = l2cc_mutex_pa; + return TEE_SUCCESS; +} + +TEE_Result tee_set_l2cc_mutex(paddr_t *mutex) +{ + uint32_t addr; + void *va; + + if (l2cc_mutex_va != NULL) + return TEE_ERROR_BAD_PARAMETERS; + addr = *mutex; + va = phys_to_virt(addr, MEM_AREA_NSEC_SHM, MUTEX_SZ); + if (!va) + return TEE_ERROR_BAD_PARAMETERS; + l2cc_mutex_pa = addr; + l2cc_mutex_va = va; + return TEE_SUCCESS; +} + +void tee_l2cc_mutex_lock(void) +{ + if (l2cc_mutex) + cpu_spin_lock(l2cc_mutex); +} + +void tee_l2cc_mutex_unlock(void) +{ + if (l2cc_mutex) + cpu_spin_unlock(l2cc_mutex); +} diff --git a/optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c b/optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c new file mode 100644 index 0000000..112dfc3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, 2015 Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result arm_cntpct_get_sys_time(TEE_Time *time) +{ + uint64_t cntpct = barrier_read_counter_timer(); + uint32_t cntfrq = read_cntfrq(); + + time->seconds = cntpct / cntfrq; + time->millis = (cntpct % cntfrq) / (cntfrq / TEE_TIME_MILLIS_BASE); + + return TEE_SUCCESS; +} + +static const struct time_source arm_cntpct_time_source = { + .name = "arm cntpct", + .protection_level = 1000, + .get_sys_time = arm_cntpct_get_sys_time, +}; + +REGISTER_TIME_SOURCE(arm_cntpct_time_source) + +/* + * We collect jitter using cntpct in 32- or 64-bit mode that is typically + * clocked at around 1MHz. + * + * The first time we are called, we add low 16 bits of the counter as entropy. + * + * Subsequently, accumulate 2 low bits each time by: + * + * - rotating the accumumlator by 2 bits + * - XORing it in 2-bit chunks with the whole CNTPCT contents + * + * and adding one byte of entropy when we reach 8 rotated bits. + */ + +void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, unsigned int *pnum) +{ + uint64_t tsc = barrier_read_counter_timer(); + int bytes = 0, n; + static uint8_t first, bits; + static uint16_t acc; + + if (!first) { + acc = tsc; + bytes = 2; + first = 1; + } else { + acc = (acc << 2) | ((acc >> 6) & 3); + for (n = 0; n < 64; n += 2) + acc ^= (tsc >> n) & 3; + bits += 2; + if (bits >= 8) { + bits = 0; + bytes = 1; + } + } + if (bytes) { + FMSG("0x%02X", (int)acc & ((1 << (bytes * 8)) - 1)); + crypto_rng_add_event(sid, pnum, (uint8_t *)&acc, bytes); + } +} diff --git a/optee/optee_os/core/arch/arm/kernel/thread.c b/optee/optee_os/core/arch/arm/kernel/thread.c new file mode 100644 index 0000000..22ef932 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread.c @@ -0,0 +1,1175 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2022, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020-2021, Arm Limited + */ + +#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 +#include +#include + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 +static vaddr_t thread_user_kcode_va __nex_bss; +long thread_user_kcode_offset __nex_bss; +static size_t thread_user_kcode_size __nex_bss; +#endif + +#if defined(CFG_CORE_UNMAP_CORE_AT_EL0) && \ + defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64) +long thread_user_kdata_sp_offset __nex_bss; +static uint8_t thread_user_kdata_page[ + ROUNDUP(sizeof(struct thread_core_local) * CFG_TEE_CORE_NB_CORE, + SMALL_PAGE_SIZE)] + __aligned(SMALL_PAGE_SIZE) +#ifndef CFG_NS_VIRTUALIZATION + __section(".nozi.kdata_page"); +#else + __section(".nex_nozi.kdata_page"); +#endif +#endif + +#ifdef ARM32 +uint32_t __nostackcheck thread_get_exceptions(void) +{ + uint32_t cpsr = read_cpsr(); + + return (cpsr >> CPSR_F_SHIFT) & THREAD_EXCP_ALL; +} + +void __nostackcheck thread_set_exceptions(uint32_t exceptions) +{ + uint32_t cpsr = read_cpsr(); + + /* Foreign interrupts must not be unmasked while holding a spinlock */ + if (!(exceptions & THREAD_EXCP_FOREIGN_INTR)) + assert_have_no_spinlock(); + + cpsr &= ~(THREAD_EXCP_ALL << CPSR_F_SHIFT); + cpsr |= ((exceptions & THREAD_EXCP_ALL) << CPSR_F_SHIFT); + + barrier(); + write_cpsr(cpsr); + barrier(); +} +#endif /*ARM32*/ + +#ifdef ARM64 +uint32_t __nostackcheck thread_get_exceptions(void) +{ + uint32_t daif = read_daif(); + + return (daif >> DAIF_F_SHIFT) & THREAD_EXCP_ALL; +} + +void __nostackcheck thread_set_exceptions(uint32_t exceptions) +{ + uint32_t daif = read_daif(); + + /* Foreign interrupts must not be unmasked while holding a spinlock */ + if (!(exceptions & THREAD_EXCP_FOREIGN_INTR)) + assert_have_no_spinlock(); + + daif &= ~(THREAD_EXCP_ALL << DAIF_F_SHIFT); + daif |= ((exceptions & THREAD_EXCP_ALL) << DAIF_F_SHIFT); + + barrier(); + write_daif(daif); + barrier(); +} +#endif /*ARM64*/ + +uint32_t __nostackcheck thread_mask_exceptions(uint32_t exceptions) +{ + uint32_t state = thread_get_exceptions(); + + thread_set_exceptions(state | (exceptions & THREAD_EXCP_ALL)); + return state; +} + +void __nostackcheck thread_unmask_exceptions(uint32_t state) +{ + thread_set_exceptions(state & THREAD_EXCP_ALL); +} + +static void thread_lazy_save_ns_vfp(void) +{ +#ifdef CFG_WITH_VFP + struct thread_ctx *thr = threads + thread_get_id(); + + thr->vfp_state.ns_saved = false; + vfp_lazy_save_state_init(&thr->vfp_state.ns); +#endif /*CFG_WITH_VFP*/ +} + +static void thread_lazy_restore_ns_vfp(void) +{ +#ifdef CFG_WITH_VFP + struct thread_ctx *thr = threads + thread_get_id(); + struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp; + + assert(!thr->vfp_state.sec_lazy_saved && !thr->vfp_state.sec_saved); + + if (tuv && tuv->lazy_saved && !tuv->saved) { + vfp_lazy_save_state_final(&tuv->vfp, false /*!force_save*/); + tuv->saved = true; + } + + vfp_lazy_restore_state(&thr->vfp_state.ns, thr->vfp_state.ns_saved); + thr->vfp_state.ns_saved = false; +#endif /*CFG_WITH_VFP*/ +} + +#ifdef ARM32 +static void init_regs(struct thread_ctx *thread, uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6, uint32_t a7, void *pc) +{ + thread->regs.pc = (uint32_t)pc; + + /* + * Stdcalls starts in SVC mode with masked foreign interrupts, masked + * Asynchronous abort and unmasked native interrupts. + */ + thread->regs.cpsr = read_cpsr() & ARM32_CPSR_E; + thread->regs.cpsr |= CPSR_MODE_SVC | CPSR_A | + (THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT); + /* Enable thumb mode if it's a thumb instruction */ + if (thread->regs.pc & 1) + thread->regs.cpsr |= CPSR_T; + /* Reinitialize stack pointer */ + thread->regs.svc_sp = thread->stack_va_end; + + /* + * Copy arguments into context. This will make the + * arguments appear in r0-r7 when thread is started. + */ + thread->regs.r0 = a0; + thread->regs.r1 = a1; + thread->regs.r2 = a2; + thread->regs.r3 = a3; + thread->regs.r4 = a4; + thread->regs.r5 = a5; + thread->regs.r6 = a6; + thread->regs.r7 = a7; +} +#endif /*ARM32*/ + +#ifdef ARM64 +static void init_regs(struct thread_ctx *thread, uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6, uint32_t a7, void *pc) +{ + thread->regs.pc = (uint64_t)pc; + + /* + * Stdcalls starts in SVC mode with masked foreign interrupts, masked + * Asynchronous abort and unmasked native interrupts. + */ + thread->regs.cpsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, + THREAD_EXCP_FOREIGN_INTR | DAIFBIT_ABT); + /* Reinitialize stack pointer */ + thread->regs.sp = thread->stack_va_end; + + /* + * Copy arguments into context. This will make the + * arguments appear in x0-x7 when thread is started. + */ + thread->regs.x[0] = a0; + thread->regs.x[1] = a1; + thread->regs.x[2] = a2; + thread->regs.x[3] = a3; + thread->regs.x[4] = a4; + thread->regs.x[5] = a5; + thread->regs.x[6] = a6; + thread->regs.x[7] = a7; + + /* Set up frame pointer as per the Aarch64 AAPCS */ + thread->regs.x[29] = 0; +} +#endif /*ARM64*/ + +static void __thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6, uint32_t a7, + void *pc) +{ + struct thread_core_local *l = thread_get_core_local(); + bool found_thread = false; + size_t n = 0; + + assert(l->curr_thread == THREAD_ID_INVALID); + + thread_lock_global(); + + for (n = 0; n < CFG_NUM_THREADS; n++) { + if (threads[n].state == THREAD_STATE_FREE) { + threads[n].state = THREAD_STATE_ACTIVE; + found_thread = true; + break; + } + } + + thread_unlock_global(); + + if (!found_thread) + return; + + l->curr_thread = n; + + threads[n].flags = 0; + init_regs(threads + n, a0, a1, a2, a3, a4, a5, a6, a7, pc); +#ifdef CFG_CORE_PAUTH + /* + * Copy the APIA key into the registers to be restored with + * thread_resume(). + */ + threads[n].regs.apiakey_hi = threads[n].keys.apia_hi; + threads[n].regs.apiakey_lo = threads[n].keys.apia_lo; +#endif + + thread_lazy_save_ns_vfp(); + + l->flags &= ~THREAD_CLF_TMP; + thread_resume(&threads[n].regs); + /*NOTREACHED*/ + panic(); +} + +void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5) +{ + __thread_alloc_and_run(a0, a1, a2, a3, a4, a5, 0, 0, + thread_std_smc_entry); +} + +#ifdef CFG_SECURE_PARTITION +void thread_sp_alloc_and_run(struct thread_smc_args *args __maybe_unused) +{ + __thread_alloc_and_run(args->a0, args->a1, args->a2, args->a3, args->a4, + args->a5, args->a6, args->a7, + spmc_sp_thread_entry); +} +#endif + +#ifdef ARM32 +static void copy_a0_to_a3(struct thread_ctx_regs *regs, uint32_t a0, + uint32_t a1, uint32_t a2, uint32_t a3) +{ + /* + * Update returned values from RPC, values will appear in + * r0-r3 when thread is resumed. + */ + regs->r0 = a0; + regs->r1 = a1; + regs->r2 = a2; + regs->r3 = a3; +} +#endif /*ARM32*/ + +#ifdef ARM64 +static void copy_a0_to_a3(struct thread_ctx_regs *regs, uint32_t a0, + uint32_t a1, uint32_t a2, uint32_t a3) +{ + /* + * Update returned values from RPC, values will appear in + * x0-x3 when thread is resumed. + */ + regs->x[0] = a0; + regs->x[1] = a1; + regs->x[2] = a2; + regs->x[3] = a3; +} +#endif /*ARM64*/ + +#ifdef ARM32 +static bool is_from_user(uint32_t cpsr) +{ + return (cpsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_USR; +} +#endif + +#ifdef ARM64 +static bool is_from_user(uint32_t cpsr) +{ + if (cpsr & (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT)) + return true; + if (((cpsr >> SPSR_64_MODE_EL_SHIFT) & SPSR_64_MODE_EL_MASK) == + SPSR_64_MODE_EL0) + return true; + return false; +} +#endif + +#ifdef CFG_SYSCALL_FTRACE +static void __noprof ftrace_suspend(void) +{ + struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); + + if (s && s->fbuf) + s->fbuf->syscall_trace_suspended = true; +} + +static void __noprof ftrace_resume(void) +{ + struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); + + if (s && s->fbuf) + s->fbuf->syscall_trace_suspended = false; +} +#else +static void __noprof ftrace_suspend(void) +{ +} + +static void __noprof ftrace_resume(void) +{ +} +#endif + +static bool is_user_mode(struct thread_ctx_regs *regs) +{ + return is_from_user((uint32_t)regs->cpsr); +} + +void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) +{ + size_t n = thread_id; + struct thread_core_local *l = thread_get_core_local(); + bool found_thread = false; + + assert(l->curr_thread == THREAD_ID_INVALID); + + thread_lock_global(); + + if (n < CFG_NUM_THREADS && threads[n].state == THREAD_STATE_SUSPENDED) { + threads[n].state = THREAD_STATE_ACTIVE; + found_thread = true; + } + + thread_unlock_global(); + + if (!found_thread) + return; + + l->curr_thread = n; + + if (threads[n].have_user_map) { + core_mmu_set_user_map(&threads[n].user_map); + if (threads[n].flags & THREAD_FLAGS_EXIT_ON_FOREIGN_INTR) + tee_ta_ftrace_update_times_resume(); + } + + if (is_user_mode(&threads[n].regs)) + tee_ta_update_session_utime_resume(); + + /* + * Return from RPC to request service of a foreign interrupt must not + * get parameters from non-secure world. + */ + if (threads[n].flags & THREAD_FLAGS_COPY_ARGS_ON_RETURN) { + copy_a0_to_a3(&threads[n].regs, a0, a1, a2, a3); + threads[n].flags &= ~THREAD_FLAGS_COPY_ARGS_ON_RETURN; + } + + thread_lazy_save_ns_vfp(); + + if (threads[n].have_user_map) + ftrace_resume(); + + l->flags &= ~THREAD_CLF_TMP; + thread_resume(&threads[n].regs); + /*NOTREACHED*/ + panic(); +} + +#ifdef ARM64 +vaddr_t thread_get_saved_thread_sp(void) +{ + struct thread_core_local *l = thread_get_core_local(); + int ct = l->curr_thread; + + assert(ct != THREAD_ID_INVALID); + return threads[ct].kern_sp; +} +#endif /*ARM64*/ + +#ifdef ARM32 +bool thread_is_in_normal_mode(void) +{ + return (read_cpsr() & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_SVC; +} +#endif + +void thread_state_free(void) +{ + struct thread_core_local *l = thread_get_core_local(); + int ct = l->curr_thread; + + assert(ct != THREAD_ID_INVALID); + + thread_lazy_restore_ns_vfp(); + tee_pager_release_phys( + (void *)(threads[ct].stack_va_end - STACK_THREAD_SIZE), + STACK_THREAD_SIZE); + + thread_lock_global(); + + assert(threads[ct].state == THREAD_STATE_ACTIVE); + threads[ct].state = THREAD_STATE_FREE; + threads[ct].flags = 0; + l->curr_thread = THREAD_ID_INVALID; + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + virt_unset_guest(); + thread_unlock_global(); +} + +#ifdef CFG_WITH_PAGER +static void release_unused_kernel_stack(struct thread_ctx *thr, + uint32_t cpsr __maybe_unused) +{ +#ifdef ARM64 + /* + * If we're from user mode then thr->regs.sp is the saved user + * stack pointer and thr->kern_sp holds the last kernel stack + * pointer. But if we're from kernel mode then thr->kern_sp isn't + * up to date so we need to read from thr->regs.sp instead. + */ + vaddr_t sp = is_from_user(cpsr) ? thr->kern_sp : thr->regs.sp; +#else + vaddr_t sp = thr->regs.svc_sp; +#endif + vaddr_t base = thr->stack_va_end - STACK_THREAD_SIZE; + size_t len = sp - base; + + tee_pager_release_phys((void *)base, len); +} +#else +static void release_unused_kernel_stack(struct thread_ctx *thr __unused, + uint32_t cpsr __unused) +{ +} +#endif + +int thread_state_suspend(uint32_t flags, uint32_t cpsr, vaddr_t pc) +{ + struct thread_core_local *l = thread_get_core_local(); + int ct = l->curr_thread; + + assert(ct != THREAD_ID_INVALID); + + if (core_mmu_user_mapping_is_active()) + ftrace_suspend(); + + thread_check_canaries(); + + release_unused_kernel_stack(threads + ct, cpsr); + + if (is_from_user(cpsr)) { + thread_user_save_vfp(); + tee_ta_update_session_utime_suspend(); + tee_ta_gprof_sample_pc(pc); + } + thread_lazy_restore_ns_vfp(); + + thread_lock_global(); + + assert(threads[ct].state == THREAD_STATE_ACTIVE); + threads[ct].flags |= flags; + threads[ct].regs.cpsr = cpsr; + threads[ct].regs.pc = pc; + threads[ct].state = THREAD_STATE_SUSPENDED; + + threads[ct].have_user_map = core_mmu_user_mapping_is_active(); + if (threads[ct].have_user_map) { + if (threads[ct].flags & THREAD_FLAGS_EXIT_ON_FOREIGN_INTR) + tee_ta_ftrace_update_times_suspend(); + core_mmu_get_user_map(&threads[ct].user_map); + core_mmu_set_user_map(NULL); + } + + l->curr_thread = THREAD_ID_INVALID; + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + virt_unset_guest(); + + thread_unlock_global(); + + return ct; +} + +bool thread_init_stack(uint32_t thread_id, vaddr_t sp) +{ + if (thread_id >= CFG_NUM_THREADS) + return false; + threads[thread_id].stack_va_end = sp; + return true; +} + +static void __maybe_unused +set_core_local_kcode_offset(struct thread_core_local *cls, long offset) +{ + size_t n = 0; + + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) + cls[n].kcode_offset = offset; +} + +static void init_user_kcode(void) +{ +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + vaddr_t v = (vaddr_t)thread_excp_vect; + vaddr_t ve = (vaddr_t)thread_excp_vect_end; + + thread_user_kcode_va = ROUNDDOWN(v, CORE_MMU_USER_CODE_SIZE); + ve = ROUNDUP(ve, CORE_MMU_USER_CODE_SIZE); + thread_user_kcode_size = ve - thread_user_kcode_va; + + core_mmu_get_user_va_range(&v, NULL); + thread_user_kcode_offset = thread_user_kcode_va - v; + + set_core_local_kcode_offset(thread_core_local, + thread_user_kcode_offset); +#if defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64) + set_core_local_kcode_offset((void *)thread_user_kdata_page, + thread_user_kcode_offset); + /* + * When transitioning to EL0 subtract SP with this much to point to + * this special kdata page instead. SP is restored by add this much + * while transitioning back to EL1. + */ + v += thread_user_kcode_size; + thread_user_kdata_sp_offset = (vaddr_t)thread_core_local - v; +#endif +#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ +} + +void thread_init_primary(void) +{ + /* Initialize canaries around the stacks */ + thread_init_canaries(); + + init_user_kcode(); +} + +static uint32_t __maybe_unused get_midr_implementer(uint32_t midr) +{ + return (midr >> MIDR_IMPLEMENTER_SHIFT) & MIDR_IMPLEMENTER_MASK; +} + +static uint32_t __maybe_unused get_midr_primary_part(uint32_t midr) +{ + return (midr >> MIDR_PRIMARY_PART_NUM_SHIFT) & + MIDR_PRIMARY_PART_NUM_MASK; +} + +static uint32_t __maybe_unused get_midr_variant(uint32_t midr) +{ + return (midr >> MIDR_VARIANT_SHIFT) & MIDR_VARIANT_MASK; +} + +static uint32_t __maybe_unused get_midr_revision(uint32_t midr) +{ + return (midr >> MIDR_REVISION_SHIFT) & MIDR_REVISION_MASK; +} + +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC +#ifdef ARM64 +static bool probe_workaround_available(uint32_t wa_id) +{ + int32_t r; + + r = thread_smc(SMCCC_VERSION, 0, 0, 0); + if (r < 0) + return false; + if (r < 0x10001) /* compare with version 1.1 */ + return false; + + /* Version >= 1.1, so SMCCC_ARCH_FEATURES is available */ + r = thread_smc(SMCCC_ARCH_FEATURES, wa_id, 0, 0); + return r >= 0; +} + +static vaddr_t __maybe_unused select_vector_wa_spectre_v2(void) +{ + if (probe_workaround_available(SMCCC_ARCH_WORKAROUND_1)) { + DMSG("SMCCC_ARCH_WORKAROUND_1 (%#08" PRIx32 ") available", + SMCCC_ARCH_WORKAROUND_1); + DMSG("SMC Workaround for CVE-2017-5715 used"); + return (vaddr_t)thread_excp_vect_wa_spectre_v2; + } + + DMSG("SMCCC_ARCH_WORKAROUND_1 (%#08" PRIx32 ") unavailable", + SMCCC_ARCH_WORKAROUND_1); + DMSG("SMC Workaround for CVE-2017-5715 not needed (if ARM-TF is up to date)"); + return (vaddr_t)thread_excp_vect; +} +#else +static vaddr_t __maybe_unused select_vector_wa_spectre_v2(void) +{ + return (vaddr_t)thread_excp_vect_wa_spectre_v2; +} +#endif +#endif + +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC +static vaddr_t select_vector_wa_spectre_bhb(uint8_t loop_count __maybe_unused) +{ + /* + * Spectre-BHB has only been analyzed for AArch64 so far. For + * AArch32 fall back to the Spectre-V2 workaround which is likely + * to work even if perhaps a bit more expensive than a more + * optimized workaround. + */ +#ifdef ARM64 +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + struct thread_core_local *cl = (void *)thread_user_kdata_page; + + cl[get_core_pos()].bhb_loop_count = loop_count; +#endif + thread_get_core_local()->bhb_loop_count = loop_count; + + DMSG("Spectre-BHB CVE-2022-23960 workaround enabled with \"K\" = %u", + loop_count); + + return (vaddr_t)thread_excp_vect_wa_spectre_bhb; +#else + return select_vector_wa_spectre_v2(); +#endif +} +#endif + +static vaddr_t get_excp_vect(void) +{ +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC + uint32_t midr = read_midr(); + uint8_t vers = 0; + + if (get_midr_implementer(midr) != MIDR_IMPLEMENTER_ARM) + return (vaddr_t)thread_excp_vect; + /* + * Variant rx, Revision py, for instance + * Variant 2 Revision 0 = r2p0 = 0x20 + */ + vers = (get_midr_variant(midr) << 4) | get_midr_revision(midr); + + /* + * Spectre-V2 (CVE-2017-5715) software workarounds covers what's + * needed for Spectre-BHB (CVE-2022-23960) too. The workaround for + * Spectre-V2 is more expensive than the one for Spectre-BHB so if + * possible select the workaround for Spectre-BHB. + */ + switch (get_midr_primary_part(midr)) { +#ifdef ARM32 + /* Spectre-V2 */ + case CORTEX_A8_PART_NUM: + case CORTEX_A9_PART_NUM: + case CORTEX_A17_PART_NUM: +#endif + /* Spectre-V2 */ + case CORTEX_A57_PART_NUM: + case CORTEX_A73_PART_NUM: + case CORTEX_A75_PART_NUM: + return select_vector_wa_spectre_v2(); +#ifdef ARM32 + /* Spectre-V2 */ + case CORTEX_A15_PART_NUM: + return (vaddr_t)thread_excp_vect_wa_a15_spectre_v2; +#endif + /* + * Spectre-V2 for vers < r1p0 + * Spectre-BHB for vers >= r1p0 + */ + case CORTEX_A72_PART_NUM: + if (vers < 0x10) + return select_vector_wa_spectre_v2(); + return select_vector_wa_spectre_bhb(8); + + /* + * Doing the more safe but expensive Spectre-V2 workaround for CPUs + * still being researched on the best mitigation sequence. + */ + case CORTEX_A65_PART_NUM: + case CORTEX_A65AE_PART_NUM: + case NEOVERSE_E1_PART_NUM: + return select_vector_wa_spectre_v2(); + + /* Spectre-BHB */ + case CORTEX_A76_PART_NUM: + case CORTEX_A76AE_PART_NUM: + case CORTEX_A77_PART_NUM: + return select_vector_wa_spectre_bhb(24); + case CORTEX_A78_PART_NUM: + case CORTEX_A78AE_PART_NUM: + case CORTEX_A78C_PART_NUM: + case CORTEX_A710_PART_NUM: + case CORTEX_X1_PART_NUM: + case CORTEX_X2_PART_NUM: + return select_vector_wa_spectre_bhb(32); + case NEOVERSE_N1_PART_NUM: + return select_vector_wa_spectre_bhb(24); + case NEOVERSE_N2_PART_NUM: + case NEOVERSE_V1_PART_NUM: + return select_vector_wa_spectre_bhb(32); + + default: + return (vaddr_t)thread_excp_vect; + } +#endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/ + + return (vaddr_t)thread_excp_vect; +} + +void thread_init_per_cpu(void) +{ +#ifdef ARM32 + struct thread_core_local *l = thread_get_core_local(); + +#if !defined(CFG_WITH_ARM_TRUSTED_FW) + /* Initialize secure monitor */ + sm_init(l->tmp_stack_va_end + STACK_TMP_OFFS); +#endif + thread_set_irq_sp(l->tmp_stack_va_end); + thread_set_fiq_sp(l->tmp_stack_va_end); + thread_set_abt_sp((vaddr_t)l); + thread_set_und_sp((vaddr_t)l); +#endif + + thread_init_vbar(get_excp_vect()); + +#ifdef CFG_FTRACE_SUPPORT + /* + * Enable accesses to frequency register and physical counter + * register in EL0/PL0 required for timestamping during + * function tracing. + */ + write_cntkctl(read_cntkctl() | CNTKCTL_PL0PCTEN); +#endif +} + +#ifdef CFG_WITH_VFP +uint32_t thread_kernel_enable_vfp(void) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + struct thread_ctx *thr = threads + thread_get_id(); + struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp; + + assert(!vfp_is_enabled()); + + if (!thr->vfp_state.ns_saved) { + vfp_lazy_save_state_final(&thr->vfp_state.ns, + true /*force_save*/); + thr->vfp_state.ns_saved = true; + } else if (thr->vfp_state.sec_lazy_saved && + !thr->vfp_state.sec_saved) { + /* + * This happens when we're handling an abort while the + * thread was using the VFP state. + */ + vfp_lazy_save_state_final(&thr->vfp_state.sec, + false /*!force_save*/); + thr->vfp_state.sec_saved = true; + } else if (tuv && tuv->lazy_saved && !tuv->saved) { + /* + * This can happen either during syscall or abort + * processing (while processing a syscall). + */ + vfp_lazy_save_state_final(&tuv->vfp, false /*!force_save*/); + tuv->saved = true; + } + + vfp_enable(); + return exceptions; +} + +void thread_kernel_disable_vfp(uint32_t state) +{ + uint32_t exceptions; + + assert(vfp_is_enabled()); + + vfp_disable(); + exceptions = thread_get_exceptions(); + assert(exceptions & THREAD_EXCP_FOREIGN_INTR); + exceptions &= ~THREAD_EXCP_FOREIGN_INTR; + exceptions |= state & THREAD_EXCP_FOREIGN_INTR; + thread_set_exceptions(exceptions); +} + +void thread_kernel_save_vfp(void) +{ + struct thread_ctx *thr = threads + thread_get_id(); + + assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); + if (vfp_is_enabled()) { + vfp_lazy_save_state_init(&thr->vfp_state.sec); + thr->vfp_state.sec_lazy_saved = true; + } +} + +void thread_kernel_restore_vfp(void) +{ + struct thread_ctx *thr = threads + thread_get_id(); + + assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); + assert(!vfp_is_enabled()); + if (thr->vfp_state.sec_lazy_saved) { + vfp_lazy_restore_state(&thr->vfp_state.sec, + thr->vfp_state.sec_saved); + thr->vfp_state.sec_saved = false; + thr->vfp_state.sec_lazy_saved = false; + } +} + +void thread_user_enable_vfp(struct thread_user_vfp_state *uvfp) +{ + struct thread_ctx *thr = threads + thread_get_id(); + struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp; + + assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); + assert(!vfp_is_enabled()); + + if (!thr->vfp_state.ns_saved) { + vfp_lazy_save_state_final(&thr->vfp_state.ns, + true /*force_save*/); + thr->vfp_state.ns_saved = true; + } else if (tuv && uvfp != tuv) { + if (tuv->lazy_saved && !tuv->saved) { + vfp_lazy_save_state_final(&tuv->vfp, + false /*!force_save*/); + tuv->saved = true; + } + } + + if (uvfp->lazy_saved) + vfp_lazy_restore_state(&uvfp->vfp, uvfp->saved); + uvfp->lazy_saved = false; + uvfp->saved = false; + + thr->vfp_state.uvfp = uvfp; + vfp_enable(); +} + +void thread_user_save_vfp(void) +{ + struct thread_ctx *thr = threads + thread_get_id(); + struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp; + + assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); + if (!vfp_is_enabled()) + return; + + assert(tuv && !tuv->lazy_saved && !tuv->saved); + vfp_lazy_save_state_init(&tuv->vfp); + tuv->lazy_saved = true; +} + +void thread_user_clear_vfp(struct user_mode_ctx *uctx) +{ + struct thread_user_vfp_state *uvfp = &uctx->vfp; + struct thread_ctx *thr = threads + thread_get_id(); + + if (uvfp == thr->vfp_state.uvfp) + thr->vfp_state.uvfp = NULL; + uvfp->lazy_saved = false; + uvfp->saved = false; +} +#endif /*CFG_WITH_VFP*/ + +#ifdef ARM32 +static bool get_spsr(bool is_32bit, unsigned long entry_func, uint32_t *spsr) +{ + uint32_t s; + + if (!is_32bit) + return false; + + s = read_cpsr(); + s &= ~(CPSR_MODE_MASK | CPSR_T | CPSR_IT_MASK1 | CPSR_IT_MASK2); + s |= CPSR_MODE_USR; + if (entry_func & 1) + s |= CPSR_T; + *spsr = s; + return true; +} +#endif + +#ifdef ARM64 +static bool get_spsr(bool is_32bit, unsigned long entry_func, uint32_t *spsr) +{ + uint32_t s; + + if (is_32bit) { + s = read_daif() & (SPSR_32_AIF_MASK << SPSR_32_AIF_SHIFT); + s |= SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT; + s |= (entry_func & SPSR_32_T_MASK) << SPSR_32_T_SHIFT; + } else { + s = read_daif() & (SPSR_64_DAIF_MASK << SPSR_64_DAIF_SHIFT); + } + + *spsr = s; + return true; +} +#endif + +static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0, + unsigned long a1, unsigned long a2, unsigned long a3, + unsigned long user_sp, unsigned long entry_func, + uint32_t spsr, + struct thread_pauth_keys *keys __maybe_unused) +{ + /* + * First clear all registers to avoid leaking information from + * other TAs or even the Core itself. + */ + *regs = (struct thread_ctx_regs){ }; +#ifdef ARM32 + regs->r0 = a0; + regs->r1 = a1; + regs->r2 = a2; + regs->r3 = a3; + regs->usr_sp = user_sp; + regs->pc = entry_func; + regs->cpsr = spsr; +#endif +#ifdef ARM64 + regs->x[0] = a0; + regs->x[1] = a1; + regs->x[2] = a2; + regs->x[3] = a3; + regs->sp = user_sp; + regs->pc = entry_func; + regs->cpsr = spsr; + regs->x[13] = user_sp; /* Used when running TA in Aarch32 */ + regs->sp = user_sp; /* Used when running TA in Aarch64 */ +#ifdef CFG_TA_PAUTH + assert(keys); + regs->apiakey_hi = keys->apia_hi; + regs->apiakey_lo = keys->apia_lo; +#endif + /* Set frame pointer (user stack can't be unwound past this point) */ + regs->x[29] = 0; +#endif +} + +static struct thread_pauth_keys *thread_get_pauth_keys(void) +{ +#if defined(CFG_TA_PAUTH) + struct ts_session *s = ts_get_current_session(); + /* Only user TA's support the PAUTH keys */ + struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); + + return &utc->uctx.keys; +#else + return NULL; +#endif +} + +uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, unsigned long user_sp, + unsigned long entry_func, bool is_32bit, + uint32_t *exit_status0, uint32_t *exit_status1) +{ + uint32_t spsr = 0; + uint32_t exceptions = 0; + uint32_t rc = 0; + struct thread_ctx_regs *regs = NULL; + struct thread_pauth_keys *keys = NULL; + + tee_ta_update_session_utime_resume(); + + keys = thread_get_pauth_keys(); + + /* Derive SPSR from current CPSR/PSTATE readout. */ + if (!get_spsr(is_32bit, entry_func, &spsr)) { + *exit_status0 = 1; /* panic */ + *exit_status1 = 0xbadbadba; + return 0; + } + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + /* + * We're using the per thread location of saved context registers + * for temporary storage. Now that exceptions are masked they will + * not be used for any thing else until they are eventually + * unmasked when user mode has been entered. + */ + regs = thread_get_ctx_regs(); + set_ctx_regs(regs, a0, a1, a2, a3, user_sp, entry_func, spsr, keys); + rc = __thread_enter_user_mode(regs, exit_status0, exit_status1); + thread_unmask_exceptions(exceptions); + return rc; +} + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 +void thread_get_user_kcode(struct mobj **mobj, size_t *offset, + vaddr_t *va, size_t *sz) +{ + core_mmu_get_user_va_range(va, NULL); + *mobj = mobj_tee_ram_rx; + *sz = thread_user_kcode_size; + *offset = thread_user_kcode_va - (vaddr_t)mobj_get_va(*mobj, 0, *sz); +} +#endif + +#if defined(CFG_CORE_UNMAP_CORE_AT_EL0) && \ + defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64) +void thread_get_user_kdata(struct mobj **mobj, size_t *offset, + vaddr_t *va, size_t *sz) +{ + vaddr_t v; + + core_mmu_get_user_va_range(&v, NULL); + *va = v + thread_user_kcode_size; + *mobj = mobj_tee_ram_rw; + *sz = sizeof(thread_user_kdata_page); + *offset = (vaddr_t)thread_user_kdata_page - + (vaddr_t)mobj_get_va(*mobj, 0, *sz); +} +#endif + +static void setup_unwind_user_mode(struct thread_scall_regs *regs) +{ +#ifdef ARM32 + regs->lr = (uintptr_t)thread_unwind_user_mode; + regs->spsr = read_cpsr(); +#endif +#ifdef ARM64 + regs->elr = (uintptr_t)thread_unwind_user_mode; + regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, 0); + regs->spsr |= read_daif(); + /* + * Regs is the value of stack pointer before calling the SVC + * handler. By the addition matches for the reserved space at the + * beginning of el0_sync_svc(). This prepares the stack when + * returning to thread_unwind_user_mode instead of a normal + * exception return. + */ + regs->sp_el0 = (uint64_t)(regs + 1); +#endif +} + +static void gprof_set_status(struct ts_session *s __maybe_unused, + enum ts_gprof_status status __maybe_unused) +{ +#ifdef CFG_TA_GPROF_SUPPORT + if (s->ctx->ops->gprof_set_status) + s->ctx->ops->gprof_set_status(status); +#endif +} + +/* + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area. + */ +void __weak thread_scall_handler(struct thread_scall_regs *regs) +{ + struct ts_session *sess = NULL; + uint32_t state = 0; + + /* Enable native interrupts */ + state = thread_get_exceptions(); + thread_unmask_exceptions(state & ~THREAD_EXCP_NATIVE_INTR); + + thread_user_save_vfp(); + + sess = ts_get_current_session(); + /* + * User mode service has just entered kernel mode, suspend gprof + * collection until we're about to switch back again. + */ + gprof_set_status(sess, TS_GPROF_SUSPEND); + + /* Restore foreign interrupts which are disabled on exception entry */ + thread_restore_foreign_intr(); + + assert(sess && sess->handle_scall); + if (sess->handle_scall(regs)) { + /* We're about to switch back to user mode */ + gprof_set_status(sess, TS_GPROF_RESUME); + } else { + /* We're returning from __thread_enter_user_mode() */ + setup_unwind_user_mode(regs); + } +} + +#ifdef CFG_WITH_ARM_TRUSTED_FW +/* + * These five functions are __weak to allow platforms to override them if + * needed. + */ +unsigned long __weak thread_cpu_off_handler(unsigned long a0 __unused, + unsigned long a1 __unused) +{ + return 0; +} +DECLARE_KEEP_PAGER(thread_cpu_off_handler); + +unsigned long __weak thread_cpu_suspend_handler(unsigned long a0 __unused, + unsigned long a1 __unused) +{ + return 0; +} +DECLARE_KEEP_PAGER(thread_cpu_suspend_handler); + +unsigned long __weak thread_cpu_resume_handler(unsigned long a0 __unused, + unsigned long a1 __unused) +{ + return 0; +} +DECLARE_KEEP_PAGER(thread_cpu_resume_handler); + +unsigned long __weak thread_system_off_handler(unsigned long a0 __unused, + unsigned long a1 __unused) +{ + return 0; +} +DECLARE_KEEP_PAGER(thread_system_off_handler); + +unsigned long __weak thread_system_reset_handler(unsigned long a0 __unused, + unsigned long a1 __unused) +{ + return 0; +} +DECLARE_KEEP_PAGER(thread_system_reset_handler); +#endif /*CFG_WITH_ARM_TRUSTED_FW*/ + +#ifdef CFG_CORE_WORKAROUND_ARM_NMFI +void __noreturn itr_core_handler(void) +{ + /* + * Note: overrides the default implementation of this function so that + * if there would be another handler defined there would be duplicate + * symbol error during linking. + */ + panic("Secure interrupt received but it is not supported"); +} +#endif diff --git a/optee/optee_os/core/arch/arm/kernel/thread_a32.S b/optee/optee_os/core/arch/arm/kernel/thread_a32.S new file mode 100644 index 0000000..23e31f1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_a32.S @@ -0,0 +1,990 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2020, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .syntax unified + .arch_extension sec + + .macro cmp_spsr_user_mode reg:req + /* + * We're only testing the lower 4 bits as bit 5 (0x10) + * always is set. + */ + tst \reg, #0x0f + .endm + +FUNC thread_set_abt_sp , : +UNWIND( .cantunwind) + mrs r1, cpsr + cps #CPSR_MODE_ABT + mov sp, r0 + msr cpsr, r1 + bx lr +END_FUNC thread_set_abt_sp + +FUNC thread_set_und_sp , : +UNWIND( .cantunwind) + mrs r1, cpsr + cps #CPSR_MODE_UND + mov sp, r0 + msr cpsr, r1 + bx lr +END_FUNC thread_set_und_sp + +FUNC thread_set_irq_sp , : +UNWIND( .cantunwind) + 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 , : +UNWIND( .cantunwind) + mrs r1, cpsr + cps #CPSR_MODE_FIQ + mov sp, r0 + msr cpsr, r1 + bx lr +END_FUNC thread_set_fiq_sp + +FUNC thread_get_usr_sp , : + mrs r1, cpsr + cpsid aif + cps #CPSR_MODE_SYS + mov r0, sp + msr cpsr, r1 + bx lr +END_FUNC thread_get_usr_sp + +FUNC thread_get_usr_lr , : + mrs r1, cpsr + cpsid aif + cps #CPSR_MODE_SYS + mov r0, lr + msr cpsr, r1 + bx lr +END_FUNC thread_get_usr_lr + +FUNC thread_set_usr_lr , : + mrs r1, cpsr + cpsid aif + cps #CPSR_MODE_SYS + mov lr, r0 + msr cpsr, r1 + bx lr +END_FUNC thread_set_usr_lr + +/* void thread_resume(struct thread_ctx_regs *regs) */ +FUNC thread_resume , : +UNWIND( .cantunwind) + add r12, r0, #(13 * 4) /* Restore registers r0-r12 later */ + + cps #CPSR_MODE_SYS + ldr sp, [r12], #4 + ldr lr, [r12], #4 + + cps #CPSR_MODE_SVC + ldr r1, [r12], #4 + ldr sp, [r12], #4 + ldr lr, [r12], #4 + msr spsr_fsxc, r1 + + ldm r12, {r1, r2} + + /* + * Switching to some other mode than SVC as we need to set spsr in + * order to return into the old state properly and it may be SVC + * mode we're returning to. + */ + cps #CPSR_MODE_ABT + cmp_spsr_user_mode r2 + mov lr, r1 + msr spsr_fsxc, r2 + ldm r0, {r0-r12} + movsne pc, lr + b eret_to_user_mode +END_FUNC thread_resume + +/* + * Disables IRQ and FIQ and saves state of thread in fiq mode which has + * the banked r8-r12 registers, returns original CPSR. + */ +LOCAL_FUNC thread_save_state_fiq , : +UNWIND( .cantunwind) + mov r9, lr + + /* + * Uses stack for temporary storage, while storing needed + * context in the thread context struct. + */ + + mrs r8, cpsr + + cpsid aif /* Disable Async abort, IRQ and FIQ */ + + push {r4-r7} + push {r0-r3} + + 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} + + cps #CPSR_MODE_SYS + stm r0!, {r8-r12} + str sp, [r0], #4 + str lr, [r0], #4 + + cps #CPSR_MODE_SVC + mrs r1, spsr + str r1, [r0], #4 + str sp, [r0], #4 + str lr, [r0], #4 + + /* back to fiq mode */ + orr r6, r6, #ARM32_CPSR_FIA /* Disable Async abort, IRQ and FIQ */ + msr cpsr, r6 /* Restore mode */ + + mov r0, r8 /* Return original CPSR */ + bx r9 +END_FUNC thread_save_state_fiq + +/* + * Disables IRQ and FIQ and saves state of thread, returns original + * CPSR. + */ +FUNC thread_save_state , : +UNWIND( .cantunwind) + push {r12, lr} + /* + * Uses stack for temporary storage, while storing needed + * context in the thread context struct. + */ + + mrs r12, cpsr + + cpsid aif /* Disable Async abort, 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 + str sp, [r0], #4 + str lr, [r0], #4 + + cps #CPSR_MODE_SVC + mrs r1, spsr + str r1, [r0], #4 + str sp, [r0], #4 + str lr, [r0], #4 + + orr r6, r6, #ARM32_CPSR_FIA /* Disable Async abort, IRQ and FIQ */ + msr cpsr, r6 /* Restore mode */ + + mov r0, r5 /* Return original CPSR */ + bx lr +END_FUNC thread_save_state + +#ifdef CFG_CORE_SEL2_SPMC +/* + * unsigned long thread_hvc(unsigned long func_id, unsigned long a1, + * unsigned long a2, unsigned long a3) + */ +FUNC thread_hvc , : + push {r4-r7} +UNWIND( .save {r4-r7}) + hvc #0 + pop {r4-r7} + bx lr +END_FUNC thread_hvc +#endif /*CFG_CORE_SEL2_SPMC*/ + +/* + * unsigned long thread_smc(unsigned long func_id, unsigned long a1, + * unsigned long a2, unsigned long a3) + */ +FUNC thread_smc , : + push {r4-r7} +UNWIND( .save {r4-r7}) + smc #0 + pop {r4-r7} + bx lr +END_FUNC thread_smc + +/* void thread_smccc(struct thread_smc_args *arg_res) */ +FUNC thread_smccc , : + push {r4-r7} + push {r0, lr} + ldm r0, {r0-r7} +#ifdef CFG_CORE_SEL2_SPMC + hvc #0 +#else + smc #0 +#endif + pop {r12, lr} + stm r12, {r0-r7} + pop {r4-r7} + bx lr +END_FUNC thread_smccc + +FUNC thread_init_vbar , : + /* Set vector (VBAR) */ + write_vbar r0 + bx lr +END_FUNC thread_init_vbar +DECLARE_KEEP_PAGER thread_init_vbar + +/* + * Below are low level routines handling entry and return from user mode. + * + * thread_enter_user_mode() saves all that registers user mode can change + * so kernel mode can restore needed registers when resuming execution + * after the call to thread_enter_user_mode() has returned. + * thread_enter_user_mode() doesn't return directly since it enters user + * mode instead, it's thread_unwind_user_mode() that does the + * returning by restoring the registers saved by thread_enter_user_mode(). + * + * There's three ways for thread_enter_user_mode() to return to caller, + * user TA calls _utee_return, user TA calls _utee_panic or through an abort. + * + * Calls to _utee_return or _utee_panic are handled as: + * __thread_svc_handler() -> thread_scall_handler() -> scall_do_call() which + * calls syscall_return() or syscall_panic(). + * + * These function calls returns normally except thread_scall_handler() which + * which is an exception handling routine so it reads return address and + * SPSR to restore from the stack. syscall_return() and syscall_panic() + * changes return address and SPSR used by thread_scall_handler() to instead of + * returning into user mode as with other syscalls it returns into + * thread_unwind_user_mode() in kernel mode instead. When + * thread_scall_handler() returns the stack pointer at the point where + * thread_enter_user_mode() left it so this is where + * thread_unwind_user_mode() can operate. + * + * Aborts are handled in a similar way but by thread_abort_handler() + * instead, when the pager sees that it's an abort from user mode that + * can't be handled it updates SPSR and return address used by + * thread_abort_handler() to return into thread_unwind_user_mode() + * instead. + */ + +/* + * uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, + * uint32_t *exit_status0, + * uint32_t *exit_status1); + * + * This function depends on being called with exceptions masked. + */ +FUNC __thread_enter_user_mode , : +UNWIND( .cantunwind) + /* + * Save all registers to allow syscall_return() to resume execution + * as if this function would have returned. This is also used in + * syscall_panic(). + * + * If stack usage of this function is changed + * thread_unwind_user_mode() has to be updated. + */ + push {r4-r12,lr} + + /* + * Save old user sp and set new user sp. + */ + cps #CPSR_MODE_SYS + mov r4, sp + ldr sp, [r0, #THREAD_CTX_REGS_USR_SP] + cps #CPSR_MODE_SVC + + push {r1, r2, r4, r5} + + /* Prepare user mode entry via eret_to_user_mode */ + ldr lr, [r0, #THREAD_CTX_REGS_PC] + ldr r4, [r0, #THREAD_CTX_REGS_CPSR] + msr spsr_fsxc, r4 + + ldm r0, {r0-r12} + + b eret_to_user_mode +END_FUNC __thread_enter_user_mode + +/* + * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, + * uint32_t exit_status1); + * See description in thread.h + */ +FUNC thread_unwind_user_mode , : +UNWIND( .cantunwind) + /* Match push {r1, r2, r4, r5} in thread_enter_user_mode() */ + pop {r4-r7} + str r1, [r4] + str r2, [r5] + + /* Restore old user sp */ + cps #CPSR_MODE_SYS + mov sp, r6 + cps #CPSR_MODE_SVC + + /* Match push {r4-r12,lr} in thread_enter_user_mode() */ + pop {r4-r12,pc} +END_FUNC thread_unwind_user_mode + + .macro maybe_restore_mapping + /* + * This macro is a bit hard to read due to all the ifdefs, + * we're testing for two different configs which makes four + * different combinations. + * + * - With LPAE, and then some extra code if with + * CFG_CORE_UNMAP_CORE_AT_EL0 + * - Without LPAE, and then some extra code if with + * CFG_CORE_UNMAP_CORE_AT_EL0 + */ + + /* + * At this point we can't rely on any memory being writable + * yet, so we're using TPIDRPRW to store r0, and if with + * LPAE TPIDRURO to store r1 too. + */ + write_tpidrprw r0 +#if defined(CFG_CORE_UNMAP_CORE_AT_EL0) || defined(CFG_WITH_LPAE) + write_tpidruro r1 +#endif + +#ifdef CFG_WITH_LPAE + read_ttbr0_64bit r0, r1 + tst r1, #BIT(TTBR_ASID_SHIFT - 32) + beq 11f + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + /* + * Update the mapping to use the full kernel mode mapping. + * Since the translation table could reside above 4GB we'll + * have to use 64-bit arithmetics. + */ + subs r0, r0, #CORE_MMU_BASE_TABLE_OFFSET + sbc r1, r1, #0 +#endif + bic r1, r1, #BIT(TTBR_ASID_SHIFT - 32) + write_ttbr0_64bit r0, r1 + isb + +#else /*!CFG_WITH_LPAE*/ + read_contextidr r0 + tst r0, #1 + beq 11f + + /* Update the mapping to use the full kernel mode mapping. */ + bic r0, r0, #1 + write_contextidr r0 + isb +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + read_ttbcr r0 + bic r0, r0, #TTBCR_PD1 + write_ttbcr r0 + isb +#endif + +#endif /*!CFG_WITH_LPAE*/ + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + ldr r0, =thread_user_kcode_offset + ldr r0, [r0] + read_vbar r1 + add r1, r1, r0 + write_vbar r1 + isb + + 11: /* + * The PC is adjusted unconditionally to guard against the + * case there was an FIQ just before we did the "cpsid aif". + */ + ldr r0, =22f + bx r0 + 22: +#else + 11: +#endif + read_tpidrprw r0 +#if defined(CFG_CORE_UNMAP_CORE_AT_EL0) || defined(CFG_WITH_LPAE) + read_tpidruro r1 +#endif + .endm + +/* The handler of native interrupt. */ +.macro native_intr_handler mode:req + cpsid aif + maybe_restore_mapping + + /* + * FIQ and IRQ have a +4 offset for lr compared to preferred return + * address + */ + sub lr, lr, #4 + + /* + * We're always saving {r0-r3}. In IRQ mode we're saving r12 also. + * In FIQ mode we're saving the banked fiq registers {r8-r12} FIQ + * because the secure monitor doesn't save those. The treatment of + * the banked fiq registers is somewhat analogous to the lazy save + * of VFP registers. + */ + .ifc \mode\(),fiq + push {r0-r3, r8-r12, lr} + .else + push {r0-r3, r12, lr} + .endif + + bl thread_check_canaries + bl itr_core_handler + + mrs r0, spsr + cmp_spsr_user_mode r0 + + .ifc \mode\(),fiq + pop {r0-r3, r8-r12, lr} + .else + pop {r0-r3, r12, lr} + .endif + + movsne pc, lr + b eret_to_user_mode +.endm + +/* The handler of foreign interrupt. */ +.macro foreign_intr_handler mode:req + cpsid aif + maybe_restore_mapping + + sub lr, lr, #4 + push {r12} + + .ifc \mode\(),fiq + /* + * If a foreign (non-secure) interrupt is received as a FIQ we need + * to check that we're in a saveable state or if we need to mask + * the interrupt to be handled later. + * + * The window when this is needed is quite narrow, it's between + * entering the exception vector and until the "cpsid" instruction + * of the handler has been executed. + * + * Currently we can save the state properly if the FIQ is received + * while in user or svc (kernel) mode. + * + * If we're returning to abort, undef or irq mode we're returning + * with the mapping restored. This is OK since before the handler + * we're returning to eventually returns to user mode the reduced + * mapping will be restored. + */ + mrs r12, spsr + and r12, r12, #ARM32_CPSR_MODE_MASK + cmp r12, #ARM32_CPSR_MODE_USR + cmpne r12, #ARM32_CPSR_MODE_SVC + beq 1f + mrs r12, spsr + orr r12, r12, #ARM32_CPSR_F + msr spsr_fsxc, r12 + pop {r12} + movs pc, lr +1: + .endif + + push {lr} + + .ifc \mode\(),fiq + bl thread_save_state_fiq + .else + bl thread_save_state + .endif + +#ifdef CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME + /* + * Prevent leaking information about which entries has been used in + * cache. We're relying on the secure monitor/dispatcher to take + * care of the BTB. + */ + mov r0, #DCACHE_OP_CLEAN_INV + bl dcache_op_louis + write_iciallu +#endif + + /* + * Use SP_abt to update core local flags. + * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_TMP; + */ + cps #CPSR_MODE_ABT + ldr r1, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsl r1, r1, #THREAD_CLF_SAVED_SHIFT + orr r1, r1, #THREAD_CLF_TMP + str r1, [sp, #THREAD_CORE_LOCAL_FLAGS] + .ifc \mode\(),fiq + cps #CPSR_MODE_FIQ + .else + cps #CPSR_MODE_IRQ + .endif + + mov r0, #THREAD_FLAGS_EXIT_ON_FOREIGN_INTR + mrs r1, spsr + pop {r2} + pop {r12} + blx thread_state_suspend + + /* + * Switch to SVC mode and copy current stack pointer as it already + * is the tmp stack. + */ + mov r1, sp + cps #CPSR_MODE_SVC + mov sp, r1 + + /* Passing thread index in r0 */ + b thread_foreign_intr_exit +.endm + +FUNC thread_excp_vect , :, align=32 +UNWIND( .cantunwind) + 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 */ +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC + .macro vector_prologue_spectre + /* + * This depends on SP being 8 byte aligned, that is, the + * lowest three bits in SP are zero. + * + * To avoid unexpected speculation we need to invalidate + * the branch predictor before we do the first branch. It + * doesn't matter if it's a conditional or an unconditional + * branch speculation can still occur. + * + * The idea is to form a specific bit pattern in the lowest + * three bits of SP depending on which entry in the vector + * we enter via. This is done by adding 1 to SP in each + * entry but the last. + */ + add sp, sp, #1 /* 7:111 Reset */ + add sp, sp, #1 /* 6:110 Undefined instruction */ + add sp, sp, #1 /* 5:101 Secure monitor call */ + add sp, sp, #1 /* 4:100 Prefetch abort */ + add sp, sp, #1 /* 3:011 Data abort */ + add sp, sp, #1 /* 2:010 Reserved */ + add sp, sp, #1 /* 1:001 IRQ */ + cpsid aif /* 0:000 FIQ */ + .endm + + .balign 32 + .global thread_excp_vect_wa_a15_spectre_v2 +thread_excp_vect_wa_a15_spectre_v2: + vector_prologue_spectre + write_tpidrprw r0 + mrs r0, spsr + cmp_spsr_user_mode r0 + bne 1f + /* + * Invalidate the branch predictor for the current processor. + * For Cortex-A8 ACTLR[6] has to be set to 1 for BPIALL to be + * effective. + * Note that the BPIALL instruction is not effective in + * invalidating the branch predictor on Cortex-A15. For that CPU, + * set ACTLR[0] to 1 during early processor initialisation, and + * invalidate the branch predictor by performing an ICIALLU + * instruction. See also: + * https://github.com/ARM-software/arm-trusted-firmware/wiki/Arm-Trusted-Firmware-Security-Advisory-TFV-6#variant-2-cve-2017-5715 + */ + write_iciallu + isb + b 1f + + .balign 32 + .global thread_excp_vect_wa_spectre_v2 +thread_excp_vect_wa_spectre_v2: + vector_prologue_spectre + write_tpidrprw r0 + mrs r0, spsr + cmp_spsr_user_mode r0 + bne 1f + /* Invalidate the branch predictor for the current processor. */ + write_bpiall + isb + +1: and r0, sp, #(BIT(0) | BIT(1) | BIT(2)) + bic sp, sp, #(BIT(0) | BIT(1) | BIT(2)) + add pc, pc, r0, LSL #3 + nop + + read_tpidrprw r0 + b __thread_fiq_handler /* FIQ */ + read_tpidrprw r0 + b __thread_irq_handler /* IRQ */ + read_tpidrprw r0 + b . /* Reserved */ + read_tpidrprw r0 + b __thread_dabort_handler /* Data abort */ + read_tpidrprw r0 + b __thread_pabort_handler /* Prefetch abort */ + read_tpidrprw r0 + b __thread_svc_handler /* System call */ + read_tpidrprw r0 + b __thread_und_handler /* Undefined instruction */ + read_tpidrprw r0 + b . /* Reset */ +#endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/ + +__thread_und_handler: + cpsid aif + maybe_restore_mapping + strd r0, r1, [sp, #THREAD_CORE_LOCAL_R0] + mrs r1, spsr + tst r1, #CPSR_T + subne lr, lr, #2 + subeq lr, lr, #4 + mov r0, #ABORT_TYPE_UNDEF + b __thread_abort_common + +__thread_dabort_handler: + cpsid aif + maybe_restore_mapping + strd r0, r1, [sp, #THREAD_CORE_LOCAL_R0] + sub lr, lr, #8 + mov r0, #ABORT_TYPE_DATA + b __thread_abort_common + +__thread_pabort_handler: + cpsid aif + maybe_restore_mapping + strd r0, r1, [sp, #THREAD_CORE_LOCAL_R0] + sub lr, lr, #4 + mov r0, #ABORT_TYPE_PREFETCH + +__thread_abort_common: + /* + * At this label: + * cpsr is in mode undef or abort + * sp is still pointing to struct thread_core_local belonging to + * this core. + * {r0, r1} are saved in struct thread_core_local pointed to by sp + * {r2-r11, ip} are untouched. + * r0 holds the first argument for abort_handler() + */ + + /* + * Update core local flags. + * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_ABORT; + */ + ldr r1, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsl r1, r1, #THREAD_CLF_SAVED_SHIFT + orr r1, r1, #THREAD_CLF_ABORT + + /* + * Select stack and update flags accordingly + * + * Normal case: + * If the abort stack is unused select that. + * + * Fatal error handling: + * If we're already using the abort stack as noted by bit + * (THREAD_CLF_SAVED_SHIFT + THREAD_CLF_ABORT_SHIFT) in the flags + * field we're selecting the temporary stack instead to be able to + * make a stack trace of the abort in abort mode. + * + * r1 is initialized as a temporary stack pointer until we've + * switched to system mode. + */ + tst r1, #(THREAD_CLF_ABORT << THREAD_CLF_SAVED_SHIFT) + orrne r1, r1, #THREAD_CLF_TMP /* flags |= THREAD_CLF_TMP; */ + str r1, [sp, #THREAD_CORE_LOCAL_FLAGS] + ldrne r1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] + ldreq r1, [sp, #THREAD_CORE_LOCAL_ABT_STACK_VA_END] + + /* + * Store registers on stack fitting struct thread_abort_regs + * start from the end of the struct + * {r2-r11, ip} + * Load content of previously saved {r0-r1} and stores + * it up to the pad field. + * After this is only {usr_sp, usr_lr} missing in the struct + */ + stmdb r1!, {r2-r11, ip} /* Push on the selected stack */ + ldrd r2, r3, [sp, #THREAD_CORE_LOCAL_R0] + /* Push the original {r0-r1} on the selected stack */ + stmdb r1!, {r2-r3} + mrs r3, spsr + /* Push {pad, spsr, elr} on the selected stack */ + stmdb r1!, {r2, r3, lr} + + cps #CPSR_MODE_SYS + str lr, [r1, #-4]! + str sp, [r1, #-4]! + mov sp, r1 + + bl abort_handler + + mov ip, sp + ldr sp, [ip], #4 + ldr lr, [ip], #4 + + /* + * Even if we entered via CPSR_MODE_UND, we are returning via + * CPSR_MODE_ABT. It doesn't matter as lr and spsr are assigned + * here. + */ + cps #CPSR_MODE_ABT + ldm ip!, {r0, r1, lr} /* r0 is pad */ + msr spsr_fsxc, r1 + + /* Update core local flags */ + ldr r0, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsr r0, r0, #THREAD_CLF_SAVED_SHIFT + str r0, [sp, #THREAD_CORE_LOCAL_FLAGS] + + cmp_spsr_user_mode r1 + ldm ip, {r0-r11, ip} + movsne pc, lr + b eret_to_user_mode + /* end thread_abort_common */ + +__thread_svc_handler: + cpsid aif + + maybe_restore_mapping + + push {r0-r7, lr} + mrs r0, spsr + push {r0} + mov r0, sp + bl thread_scall_handler + cpsid aif /* In case something was unmasked */ + pop {r0} + msr spsr_fsxc, r0 + cmp_spsr_user_mode r0 + pop {r0-r7, lr} + movsne pc, lr + b eret_to_user_mode + /* end thread_svc_handler */ + +__thread_fiq_handler: +#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) + foreign_intr_handler fiq +#else + native_intr_handler fiq +#endif + /* end thread_fiq_handler */ + +__thread_irq_handler: +#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) + native_intr_handler irq +#else + foreign_intr_handler irq +#endif + /* end thread_irq_handler */ + + /* + * Returns to user mode. + * Expects to be jumped to with lr pointing to the user space + * address to jump to and spsr holding the desired cpsr. Async + * abort, irq and fiq should be masked. + */ +eret_to_user_mode: + write_tpidrprw r0 +#if defined(CFG_CORE_UNMAP_CORE_AT_EL0) || defined(CFG_WITH_LPAE) + write_tpidruro r1 +#endif + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + ldr r0, =thread_user_kcode_offset + ldr r0, [r0] + read_vbar r1 + sub r1, r1, r0 + write_vbar r1 + isb + + /* Jump into the reduced mapping before the full mapping is removed */ + ldr r1, =1f + sub r1, r1, r0 + bx r1 +1: +#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ + +#ifdef CFG_WITH_LPAE + read_ttbr0_64bit r0, r1 +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + add r0, r0, #CORE_MMU_BASE_TABLE_OFFSET +#endif + /* switch to user ASID */ + orr r1, r1, #BIT(TTBR_ASID_SHIFT - 32) + write_ttbr0_64bit r0, r1 + isb +#else /*!CFG_WITH_LPAE*/ +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + read_ttbcr r0 + orr r0, r0, #TTBCR_PD1 + write_ttbcr r0 + isb +#endif + read_contextidr r0 + orr r0, r0, #BIT(0) + write_contextidr r0 + isb +#endif /*!CFG_WITH_LPAE*/ + + read_tpidrprw r0 +#if defined(CFG_CORE_UNMAP_CORE_AT_EL0) || defined(CFG_WITH_LPAE) + read_tpidruro r1 +#endif + + movs pc, lr + + /* + * void icache_inv_user_range(void *addr, size_t size); + * + * This function has to execute with the user space ASID active, + * this means executing with reduced mapping and the code needs + * to be located here together with the vector. + */ + .global icache_inv_user_range + .type icache_inv_user_range , %function +icache_inv_user_range: + push {r4-r7} + + /* Mask all exceptions */ + mrs r4, cpsr /* This register must be preserved */ + cpsid aif + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + ldr r2, =thread_user_kcode_offset + ldr r2, [r2] + read_vbar r5 /* This register must be preserved */ + sub r3, r5, r2 + write_vbar r3 + isb + + /* Jump into the reduced mapping before the full mapping is removed */ + ldr r3, =1f + sub r3, r3, r2 + bx r3 +1: +#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ + +#ifdef CFG_WITH_LPAE + read_ttbr0_64bit r6, r7 /* These registers must be preseved */ + /* switch to user ASID */ + orr r3, r7, #BIT(TTBR_ASID_SHIFT - 32) +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + add r2, r6, #CORE_MMU_BASE_TABLE_OFFSET + write_ttbr0_64bit r2, r3 +#else + write_ttbr0_64bit r6, r3 +#endif + isb +#else /*!CFG_WITH_LPAE*/ +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + read_ttbcr r6 /* This register must be preserved */ + orr r2, r6, #TTBCR_PD1 + write_ttbcr r2 + isb +#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ + read_contextidr r7 /* This register must be preserved */ + orr r2, r7, #BIT(0) + write_contextidr r2 + isb +#endif /*!CFG_WITH_LPAE*/ + + /* + * Do the actual icache invalidation + */ + + /* Calculate minimum icache line size, result in r2 */ + read_ctr r3 + and r3, r3, #CTR_IMINLINE_MASK + mov r2, #CTR_WORD_SIZE + lsl r2, r2, r3 + + add r1, r0, r1 + sub r3, r2, #1 + bic r0, r0, r3 +1: + write_icimvau r0 + add r0, r0, r2 + cmp r0, r1 + blo 1b + + /* Invalidate entire branch predictor array inner shareable */ + write_bpiallis + + dsb ishst + isb + +#ifdef CFG_WITH_LPAE + write_ttbr0_64bit r6, r7 + isb +#else /*!CFG_WITH_LPAE*/ + write_contextidr r7 + isb +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + write_ttbcr r6 + isb +#endif +#endif /*!CFG_WITH_LPAE*/ + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + write_vbar r5 + isb + /* + * The PC is adjusted unconditionally to guard against the + * case there was an FIQ just before we did the "cpsid aif". + */ + ldr r0, =1f + bx r0 +1: +#endif + + msr cpsr_fsxc, r4 /* Restore exceptions */ + pop {r4-r7} + bx lr /* End of icache_inv_user_range() */ + + /* + * Make sure that literals are placed before the + * thread_excp_vect_end label. + */ + .pool + .global thread_excp_vect_end +thread_excp_vect_end: +END_FUNC thread_excp_vect diff --git a/optee/optee_os/core/arch/arm/kernel/thread_a64.S b/optee/optee_os/core/arch/arm/kernel/thread_a64.S new file mode 100644 index 0000000..8db79aa --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_a64.S @@ -0,0 +1,1339 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .macro get_thread_ctx core_local, res, tmp0, tmp1 + ldrh w\tmp0, [\core_local, \ + #THREAD_CORE_LOCAL_CURR_THREAD] + adr_l x\res, threads + mov x\tmp1, #THREAD_CTX_SIZE + madd x\res, x\tmp0, x\tmp1, x\res + .endm + + .macro return_from_exception + eret + /* Guard against speculation past ERET */ + dsb nsh + isb + .endm + + .macro b_if_spsr_is_el0 reg, label + tbnz \reg, #(SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT), \label + tst \reg, #(SPSR_64_MODE_EL_MASK << SPSR_64_MODE_EL_SHIFT) + b.eq \label + .endm + + .macro pauth_el0_to_el1 reg + /* + * If pauth is only enabled in one of core or TA (xor) we + * need to update sctlr. + */ +#if (defined(CFG_TA_PAUTH) && !defined(CFG_CORE_PAUTH)) || \ + (!defined(CFG_TA_PAUTH) && defined(CFG_CORE_PAUTH)) + mrs \reg, sctlr_el1 + /* Flip the SCTLR_ENIA bit */ + eor \reg, \reg, #SCTLR_ENIA + msr sctlr_el1, \reg +#endif + .endm + + .macro pauth_el1_to_el0 reg + /* + * If pauth is only enabled in one of core or TA (xor) we + * need to update sctlr. + */ +#if (defined(CFG_TA_PAUTH) && !defined(CFG_CORE_PAUTH)) || \ + (!defined(CFG_TA_PAUTH) && defined(CFG_CORE_PAUTH)) + mrs \reg, sctlr_el1 + /* Flip the SCTLR_ENIA bit */ + eor \reg, \reg, #SCTLR_ENIA + msr sctlr_el1, \reg +#endif + .endm + +/* void thread_resume(struct thread_ctx_regs *regs) */ +FUNC thread_resume , : + load_xregs x0, THREAD_CTX_REGS_SP, 1, 3 + load_xregs x0, THREAD_CTX_REGS_X4, 4, 30 + mov sp, x1 + msr elr_el1, x2 + msr spsr_el1, x3 + ldr x1, [x0, THREAD_CTX_REGS_TPIDR_EL0] + msr tpidr_el0, x1 + +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + load_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 + write_apiakeyhi x1 + write_apiakeylo x2 +#endif + b_if_spsr_is_el0 w3, 1f + +#if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) + /* SCTLR or the APIA key has changed */ + isb +#endif + load_xregs x0, THREAD_CTX_REGS_X1, 1, 3 + ldr x0, [x0, THREAD_CTX_REGS_X0] + return_from_exception + +1: + load_xregs x0, THREAD_CTX_REGS_X1, 1, 3 + ldr x0, [x0, THREAD_CTX_REGS_X0] + + msr spsel, #1 + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 + b eret_to_el0 +END_FUNC thread_resume + +#ifdef CFG_CORE_SEL2_SPMC +FUNC thread_hvc , : + hvc #0 + ret +END_FUNC thread_hvc +#endif + +FUNC thread_smc , : + smc #0 + ret +END_FUNC thread_smc + +/* void thread_smccc(struct thread_smc_args *arg_res) */ +FUNC thread_smccc , : + push x0, xzr + mov x8, x0 + load_xregs x8, 0, 0, 7 +#ifdef CFG_CORE_SEL2_SPMC + hvc #0 +#else + smc #0 +#endif + pop x8, xzr + store_xregs x8, 0, 0, 7 + ret +END_FUNC thread_smccc + +FUNC thread_init_vbar , : + msr vbar_el1, x0 + ret +END_FUNC thread_init_vbar +DECLARE_KEEP_PAGER thread_init_vbar + +/* + * uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, + * uint32_t *exit_status0, + * uint32_t *exit_status1); + * + * This function depends on being called with exceptions masked. + */ +FUNC __thread_enter_user_mode , : + /* + * Create the and fill in the struct thread_user_mode_rec + */ + sub sp, sp, #THREAD_USER_MODE_REC_SIZE + store_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, 0, 2 + store_xregs sp, THREAD_USER_MODE_REC_X19, 19, 30 + + /* + * Save kern sp in x19 + * Switch to SP_EL1 + */ + mov x19, sp + msr spsel, #1 + + /* + * Save the kernel stack pointer in the thread context + */ + /* get pointer to current thread context */ + get_thread_ctx sp, 21, 20, 22 + /* + * Save kernel stack pointer to ensure that el0_svc() uses + * correct stack pointer + */ + str x19, [x21, #THREAD_CTX_KERN_SP] + + /* + * Initialize SPSR, ELR_EL1, and SP_EL0 to enter user mode + */ + load_xregs x0, THREAD_CTX_REGS_SP, 1, 3 + msr sp_el0, x1 + msr elr_el1, x2 + msr spsr_el1, x3 + +#ifdef CFG_TA_PAUTH + /* Load APIAKEY */ + load_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 + write_apiakeyhi x1 + write_apiakeylo x2 +#endif + + /* + * Save the values for x0 and x1 in struct thread_core_local to be + * restored later just before the eret. + */ + load_xregs x0, THREAD_CTX_REGS_X0, 1, 2 + store_xregs sp, THREAD_CORE_LOCAL_X0, 1, 2 + + /* Load the rest of the general purpose registers */ + load_xregs x0, THREAD_CTX_REGS_X2, 2, 30 + + /* Jump into user mode */ + b eret_to_el0 +END_FUNC __thread_enter_user_mode +DECLARE_KEEP_PAGER __thread_enter_user_mode + +/* + * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, + * uint32_t exit_status1); + * See description in thread.h + */ +FUNC thread_unwind_user_mode , : + /* Store the exit status */ + load_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, 3, 5 + str w1, [x4] + str w2, [x5] + /* Save x19..x30 */ + store_xregs x3, THREAD_CTX_REGS_X19, 19, 30 + /* Restore x19..x30 */ + load_xregs sp, THREAD_USER_MODE_REC_X19, 19, 30 + add sp, sp, #THREAD_USER_MODE_REC_SIZE + /* Return from the call of thread_enter_user_mode() */ + ret +END_FUNC thread_unwind_user_mode + + /* + * This macro verifies that the a given vector doesn't exceed the + * architectural limit of 32 instructions. This is meant to be placed + * immedately after the last instruction in the vector. It takes the + * vector entry as the parameter + */ + .macro check_vector_size since + .if (. - \since) > (32 * 4) + .error "Vector exceeds 32 instructions" + .endif + .endm + + .macro restore_mapping +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + /* Temporarily save x0, x1 */ + msr tpidr_el1, x0 + msr tpidrro_el0, x1 + + /* Update the mapping to use the full kernel mapping */ + mrs x0, ttbr0_el1 + sub x0, x0, #CORE_MMU_BASE_TABLE_OFFSET_HIGH, LSL #12 + sub x0, x0, #CORE_MMU_BASE_TABLE_OFFSET_LOW + /* switch to kernel mode ASID */ + bic x0, x0, #BIT(TTBR_ASID_SHIFT) + msr ttbr0_el1, x0 + isb + + /* Jump into the full mapping and continue execution */ + adr x0, 1f + ldr x1, [sp, #THREAD_CORE_LOCAL_KCODE_OFFSET] + add x0, x0, x1 + br x0 + 1: +BTI( bti j) + /* Point to the vector into the full mapping */ + adr_l x0, thread_user_kcode_offset + ldr x0, [x0] + mrs x1, vbar_el1 + add x1, x1, x0 + msr vbar_el1, x1 + isb + +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC + /* + * Update the SP with thread_user_kdata_sp_offset as + * described in init_user_kcode(). + */ + adr_l x0, thread_user_kdata_sp_offset + ldr x0, [x0] + add sp, sp, x0 +#endif + + /* Restore x0, x1 */ + mrs x0, tpidr_el1 + mrs x1, tpidrro_el0 + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 +#else + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + mrs x0, ttbr0_el1 + /* switch to kernel mode ASID */ + bic x0, x0, #BIT(TTBR_ASID_SHIFT) + msr ttbr0_el1, x0 + isb +#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ + .endm + +#define INV_INSN 0 +FUNC thread_excp_vect , : , default, 2048, nobti + /* ----------------------------------------------------- + * EL1 with SP0 : 0x0 - 0x180 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +el1_sync_sp0: + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + b el1_sync_abort + check_vector_size el1_sync_sp0 + + .balign 128, INV_INSN +el1_irq_sp0: + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + b elx_irq + check_vector_size el1_irq_sp0 + + .balign 128, INV_INSN +el1_fiq_sp0: + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + b elx_fiq + check_vector_size el1_fiq_sp0 + + .balign 128, INV_INSN +el1_serror_sp0: + b el1_serror_sp0 + check_vector_size el1_serror_sp0 + + /* ----------------------------------------------------- + * Current EL with SP1: 0x200 - 0x380 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +el1_sync_sp1: + b el1_sync_sp1 + check_vector_size el1_sync_sp1 + + .balign 128, INV_INSN +el1_irq_sp1: + b el1_irq_sp1 + check_vector_size el1_irq_sp1 + + .balign 128, INV_INSN +el1_fiq_sp1: + b el1_fiq_sp1 + check_vector_size el1_fiq_sp1 + + .balign 128, INV_INSN +el1_serror_sp1: + b el1_serror_sp1 + check_vector_size el1_serror_sp1 + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x580 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +el0_sync_a64: + restore_mapping + /* PAuth will be disabled later else check_vector_size will fail */ + + b el0_sync_a64_finish + check_vector_size el0_sync_a64 + + .balign 128, INV_INSN +el0_irq_a64: + restore_mapping + pauth_el0_to_el1 x1 + + b elx_irq + check_vector_size el0_irq_a64 + + .balign 128, INV_INSN +el0_fiq_a64: + restore_mapping + pauth_el0_to_el1 x1 + + b elx_fiq + check_vector_size el0_fiq_a64 + + .balign 128, INV_INSN +el0_serror_a64: + b el0_serror_a64 + check_vector_size el0_serror_a64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x0 - 0x180 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +el0_sync_a32: + restore_mapping + + b el0_sync_a32_finish + check_vector_size el0_sync_a32 + + .balign 128, INV_INSN +el0_irq_a32: + restore_mapping + + b elx_irq + check_vector_size el0_irq_a32 + + .balign 128, INV_INSN +el0_fiq_a32: + restore_mapping + + b elx_fiq + check_vector_size el0_fiq_a32 + + .balign 128, INV_INSN +el0_serror_a32: + b el0_serror_a32 + check_vector_size el0_serror_a32 + +#if defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) + .macro invalidate_branch_predictor + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + mov_imm x0, SMCCC_ARCH_WORKAROUND_1 + smc #0 + load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + .endm + + .balign 2048, INV_INSN + .global thread_excp_vect_wa_spectre_v2 +thread_excp_vect_wa_spectre_v2: + /* ----------------------------------------------------- + * EL1 with SP0 : 0x0 - 0x180 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +wa_spectre_v2_el1_sync_sp0: + b el1_sync_sp0 + check_vector_size wa_spectre_v2_el1_sync_sp0 + + .balign 128, INV_INSN +wa_spectre_v2_el1_irq_sp0: + b el1_irq_sp0 + check_vector_size wa_spectre_v2_el1_irq_sp0 + + .balign 128, INV_INSN +wa_spectre_v2_el1_fiq_sp0: + b el1_fiq_sp0 + check_vector_size wa_spectre_v2_el1_fiq_sp0 + + .balign 128, INV_INSN +wa_spectre_v2_el1_serror_sp0: + b el1_serror_sp0 + check_vector_size wa_spectre_v2_el1_serror_sp0 + + /* ----------------------------------------------------- + * Current EL with SP1: 0x200 - 0x380 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +wa_spectre_v2_el1_sync_sp1: + b wa_spectre_v2_el1_sync_sp1 + check_vector_size wa_spectre_v2_el1_sync_sp1 + + .balign 128, INV_INSN +wa_spectre_v2_el1_irq_sp1: + b wa_spectre_v2_el1_irq_sp1 + check_vector_size wa_spectre_v2_el1_irq_sp1 + + .balign 128, INV_INSN +wa_spectre_v2_el1_fiq_sp1: + b wa_spectre_v2_el1_fiq_sp1 + check_vector_size wa_spectre_v2_el1_fiq_sp1 + + .balign 128, INV_INSN +wa_spectre_v2_el1_serror_sp1: + b wa_spectre_v2_el1_serror_sp1 + check_vector_size wa_spectre_v2_el1_serror_sp1 + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x580 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +wa_spectre_v2_el0_sync_a64: + invalidate_branch_predictor + b el0_sync_a64 + check_vector_size wa_spectre_v2_el0_sync_a64 + + .balign 128, INV_INSN +wa_spectre_v2_el0_irq_a64: + invalidate_branch_predictor + b el0_irq_a64 + check_vector_size wa_spectre_v2_el0_irq_a64 + + .balign 128, INV_INSN +wa_spectre_v2_el0_fiq_a64: + invalidate_branch_predictor + b el0_fiq_a64 + check_vector_size wa_spectre_v2_el0_fiq_a64 + + .balign 128, INV_INSN +wa_spectre_v2_el0_serror_a64: + b wa_spectre_v2_el0_serror_a64 + check_vector_size wa_spectre_v2_el0_serror_a64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x0 - 0x180 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +wa_spectre_v2_el0_sync_a32: + invalidate_branch_predictor + b el0_sync_a32 + check_vector_size wa_spectre_v2_el0_sync_a32 + + .balign 128, INV_INSN +wa_spectre_v2_el0_irq_a32: + invalidate_branch_predictor + b el0_irq_a32 + check_vector_size wa_spectre_v2_el0_irq_a32 + + .balign 128, INV_INSN +wa_spectre_v2_el0_fiq_a32: + invalidate_branch_predictor + b el0_fiq_a32 + check_vector_size wa_spectre_v2_el0_fiq_a32 + + .balign 128, INV_INSN +wa_spectre_v2_el0_serror_a32: + b wa_spectre_v2_el0_serror_a32 + check_vector_size wa_spectre_v2_el0_serror_a32 + + .macro discard_branch_history + str x0, [sp, #THREAD_CORE_LOCAL_X0] + ldrb w0, [sp, #THREAD_CORE_LOCAL_BHB_LOOP_COUNT] + 1: b 2f + 2: subs w0, w0, #1 + bne 1b + dsb sy + isb + ldr x0, [sp, #THREAD_CORE_LOCAL_X0] + .endm + + .balign 2048, INV_INSN + .global thread_excp_vect_wa_spectre_bhb +thread_excp_vect_wa_spectre_bhb: + /* ----------------------------------------------------- + * EL1 with SP0 : 0x0 - 0x180 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +wa_spectre_bhb_el1_sync_sp0: + b el1_sync_sp0 + check_vector_size wa_spectre_bhb_el1_sync_sp0 + + .balign 128, INV_INSN +wa_spectre_bhb_el1_irq_sp0: + b el1_irq_sp0 + check_vector_size wa_spectre_bhb_el1_irq_sp0 + + .balign 128, INV_INSN +wa_spectre_bhb_el1_fiq_sp0: + b el1_fiq_sp0 + check_vector_size wa_spectre_bhb_el1_fiq_sp0 + + .balign 128, INV_INSN +wa_spectre_bhb_el1_serror_sp0: + b el1_serror_sp0 + check_vector_size wa_spectre_bhb_el1_serror_sp0 + + /* ----------------------------------------------------- + * Current EL with SP1: 0x200 - 0x380 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +wa_spectre_bhb_el1_sync_sp1: + b wa_spectre_bhb_el1_sync_sp1 + check_vector_size wa_spectre_bhb_el1_sync_sp1 + + .balign 128, INV_INSN +wa_spectre_bhb_el1_irq_sp1: + b wa_spectre_bhb_el1_irq_sp1 + check_vector_size wa_spectre_bhb_el1_irq_sp1 + + .balign 128, INV_INSN +wa_spectre_bhb_el1_fiq_sp1: + b wa_spectre_bhb_el1_fiq_sp1 + check_vector_size wa_spectre_bhb_el1_fiq_sp1 + + .balign 128, INV_INSN +wa_spectre_bhb_el1_serror_sp1: + b wa_spectre_bhb_el1_serror_sp1 + check_vector_size wa_spectre_bhb_el1_serror_sp1 + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x580 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +wa_spectre_bhb_el0_sync_a64: + discard_branch_history + b el0_sync_a64 + check_vector_size wa_spectre_bhb_el0_sync_a64 + + .balign 128, INV_INSN +wa_spectre_bhb_el0_irq_a64: + discard_branch_history + b el0_irq_a64 + check_vector_size wa_spectre_bhb_el0_irq_a64 + + .balign 128, INV_INSN +wa_spectre_bhb_el0_fiq_a64: + discard_branch_history + b el0_fiq_a64 + check_vector_size wa_spectre_bhb_el0_fiq_a64 + + .balign 128, INV_INSN +wa_spectre_bhb_el0_serror_a64: + b wa_spectre_bhb_el0_serror_a64 + check_vector_size wa_spectre_bhb_el0_serror_a64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x0 - 0x180 + * ----------------------------------------------------- + */ + .balign 128, INV_INSN +wa_spectre_bhb_el0_sync_a32: + discard_branch_history + b el0_sync_a32 + check_vector_size wa_spectre_bhb_el0_sync_a32 + + .balign 128, INV_INSN +wa_spectre_bhb_el0_irq_a32: + discard_branch_history + b el0_irq_a32 + check_vector_size wa_spectre_bhb_el0_irq_a32 + + .balign 128, INV_INSN +wa_spectre_bhb_el0_fiq_a32: + discard_branch_history + b el0_fiq_a32 + check_vector_size wa_spectre_bhb_el0_fiq_a32 + + .balign 128, INV_INSN +wa_spectre_bhb_el0_serror_a32: + b wa_spectre_bhb_el0_serror_a32 + check_vector_size wa_spectre_bhb_el0_serror_a32 +#endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/ + +/* + * We're keeping this code in the same section as the vector to make sure + * that it's always available. + */ +eret_to_el0: + pauth_el1_to_el0 x1 + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + /* Point to the vector into the reduced mapping */ + adr_l x0, thread_user_kcode_offset + ldr x0, [x0] + mrs x1, vbar_el1 + sub x1, x1, x0 + msr vbar_el1, x1 + isb + +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC + /* Store the SP offset in tpidr_el1 to be used below to update SP */ + adr_l x1, thread_user_kdata_sp_offset + ldr x1, [x1] + msr tpidr_el1, x1 +#endif + + /* Jump into the reduced mapping and continue execution */ + adr_l x1, 1f + sub x1, x1, x0 + br x1 +1: +BTI( bti j) + load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 + msr tpidrro_el0, x0 + + /* Update the mapping to exclude the full kernel mapping */ + mrs x0, ttbr0_el1 + add x0, x0, #CORE_MMU_BASE_TABLE_OFFSET_HIGH, LSL #12 + add x0, x0, #CORE_MMU_BASE_TABLE_OFFSET_LOW + orr x0, x0, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ + msr ttbr0_el1, x0 + isb + +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC + /* + * Update the SP with thread_user_kdata_sp_offset as described in + * init_user_kcode(). + */ + mrs x0, tpidr_el1 + sub sp, sp, x0 +#endif + + mrs x0, tpidrro_el0 +#else + mrs x0, ttbr0_el1 + orr x0, x0, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ + msr ttbr0_el1, x0 + isb + load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 +#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ + + return_from_exception + +el0_sync_a64_finish: + mrs x2, esr_el1 + mrs x3, sp_el0 + lsr x2, x2, #ESR_EC_SHIFT + cmp x2, #ESR_EC_AARCH64_SVC + b.eq el0_svc + b el0_sync_abort + +el0_sync_a32_finish: + mrs x2, esr_el1 + mrs x3, sp_el0 + lsr x2, x2, #ESR_EC_SHIFT + cmp x2, #ESR_EC_AARCH32_SVC + b.eq el0_svc + b el0_sync_abort + + /* + * void icache_inv_user_range(void *addr, size_t size); + * + * This function has to execute with the user space ASID active, + * this means executing with reduced mapping and the code needs + * to be located here together with the vector. + */ + .global icache_inv_user_range + .type icache_inv_user_range , %function +icache_inv_user_range: + /* Mask all exceptions */ + mrs x6, daif /* this register must be preserved */ + msr daifset, #DAIFBIT_ALL + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + /* Point to the vector into the reduced mapping */ + adr_l x7, thread_user_kcode_offset + ldr x7, [x7] /* this register must be preserved */ + mrs x4, vbar_el1 /* this register must be preserved */ + sub x3, x4, x7 + msr vbar_el1, x3 + isb + + /* Jump into the reduced mapping and continue execution */ + adr x3, 1f + sub x3, x3, x7 + br x3 +1: +BTI( bti j) + /* Update the mapping to exclude the full kernel mapping */ + mrs x5, ttbr0_el1 /* this register must be preserved */ + add x2, x5, #CORE_MMU_BASE_TABLE_OFFSET_HIGH, LSL #12 + add x2, x5, #CORE_MMU_BASE_TABLE_OFFSET_LOW + orr x2, x2, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ + msr ttbr0_el1, x2 + isb + +#else + mrs x5, ttbr0_el1 /* this register must be preserved */ + orr x2, x5, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ + msr ttbr0_el1, x2 + isb +#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ + + /* + * Do the actual icache invalidation + */ + + /* Calculate minimum icache line size, result in x2 */ + mrs x3, ctr_el0 + and x3, x3, #CTR_IMINLINE_MASK + mov x2, #CTR_WORD_SIZE + lsl x2, x2, x3 + + add x1, x0, x1 + sub x3, x2, #1 + bic x0, x0, x3 +1: + ic ivau, x0 + add x0, x0, x2 + cmp x0, x1 + b.lo 1b + dsb ish + +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + /* Update the mapping to use the full kernel mapping and ASID */ + msr ttbr0_el1, x5 + isb + + /* Jump into the full mapping and continue execution */ + adr x0, 1f + add x0, x0, x7 + br x0 +1: +BTI( bti j) + /* Point to the vector into the full mapping */ + msr vbar_el1, x4 + isb +#else + /* switch to kernel mode ASID */ + msr ttbr0_el1, x5 + isb +#endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ + + msr daif, x6 /* restore exceptions */ + ret /* End of icache_inv_user_range() */ + + /* + * Make sure that literals are placed before the + * thread_excp_vect_end label. + */ + .pool + .global thread_excp_vect_end +thread_excp_vect_end: +END_FUNC thread_excp_vect + +LOCAL_FUNC el0_svc , : + pauth_el0_to_el1 x1 + /* get pointer to current thread context in x0 */ + get_thread_ctx sp, 0, 1, 2 + mrs x1, tpidr_el0 + str x1, [x0, #THREAD_CTX_REGS_TPIDR_EL0] + /* load saved kernel sp */ + ldr x3, [x0, #THREAD_CTX_KERN_SP] + /* Keep pointer to initial recod in x1 */ + mov x1, sp + /* Switch to SP_EL0 and restore kernel sp */ + msr spsel, #0 + mov x2, sp /* Save SP_EL0 */ + mov sp, x3 + + /* Make room for struct thread_scall_regs */ + sub sp, sp, #THREAD_SCALL_REG_SIZE + stp x30, x2, [sp, #THREAD_SCALL_REG_X30] + +#ifdef CFG_TA_PAUTH + /* Save APIAKEY */ + read_apiakeyhi x2 + read_apiakeylo x3 + stp x2, x3, [sp, #THREAD_SCALL_REG_APIAKEY_HI] +#endif + +#ifdef CFG_CORE_PAUTH + ldp x2, x3, [x0, #THREAD_CTX_KEYS] + write_apiakeyhi x2 + write_apiakeylo x3 +#endif +#if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) + /* SCTLR or the APIA key has changed */ + isb +#endif + + /* Restore x0-x3 */ + ldp x2, x3, [x1, #THREAD_CORE_LOCAL_X2] + ldp x0, x1, [x1, #THREAD_CORE_LOCAL_X0] + + /* Prepare the argument for the handler */ + store_xregs sp, THREAD_SCALL_REG_X0, 0, 14 + mrs x0, elr_el1 + mrs x1, spsr_el1 + store_xregs sp, THREAD_SCALL_REG_ELR, 0, 1 + + mov x0, sp + + /* + * Unmask native interrupts, Serror, and debug exceptions since we have + * nothing left in sp_el1. Note that the SVC handler is excepted to + * re-enable foreign interrupts by itself. + */ +#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) + msr daifclr, #(DAIFBIT_IRQ | DAIFBIT_ABT | DAIFBIT_DBG) +#else + msr daifclr, #(DAIFBIT_FIQ | DAIFBIT_ABT | DAIFBIT_DBG) +#endif + + /* Call the handler */ + bl thread_scall_handler + + /* Mask all maskable exceptions since we're switching back to sp_el1 */ + msr daifset, #DAIFBIT_ALL + + /* + * Save kernel sp we'll had at the beginning of this function. + * This is when this TA has called another TA because + * __thread_enter_user_mode() also saves the stack pointer in this + * field. + */ + msr spsel, #1 + get_thread_ctx sp, 0, 1, 2 + msr spsel, #0 + add x1, sp, #THREAD_SCALL_REG_SIZE + str x1, [x0, #THREAD_CTX_KERN_SP] + + /* Restore registers to the required state and return*/ + ldr x1, [x0, #THREAD_CTX_REGS_TPIDR_EL0] + msr tpidr_el0, x1 + load_xregs sp, THREAD_SCALL_REG_ELR, 0, 1 + msr elr_el1, x0 + msr spsr_el1, x1 + load_xregs sp, THREAD_SCALL_REG_X2, 2, 14 + mov x30, sp + ldr x0, [x30, #THREAD_SCALL_REG_SP_EL0] + mov sp, x0 + b_if_spsr_is_el0 w1, 1f + ldp x0, x1, [x30, THREAD_SCALL_REG_X0] + ldr x30, [x30, #THREAD_SCALL_REG_X30] + + return_from_exception + +1: +#ifdef CFG_TA_PAUTH + /* Restore APIAKEY */ + load_xregs x30, THREAD_SCALL_REG_APIAKEY_HI, 0, 1 + write_apiakeyhi x0 + write_apiakeylo x1 +#endif + + ldp x0, x1, [x30, THREAD_SCALL_REG_X0] + ldr x30, [x30, #THREAD_SCALL_REG_X30] + + msr spsel, #1 + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 + b eret_to_el0 +END_FUNC el0_svc + +LOCAL_FUNC el1_sync_abort , : + mov x0, sp + msr spsel, #0 + mov x3, sp /* Save original sp */ + + /* + * Update core local flags. + * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_ABORT; + */ + ldr w1, [x0, #THREAD_CORE_LOCAL_FLAGS] + lsl w1, w1, #THREAD_CLF_SAVED_SHIFT + orr w1, w1, #THREAD_CLF_ABORT + tbnz w1, #(THREAD_CLF_SAVED_SHIFT + THREAD_CLF_ABORT_SHIFT), \ + .Lsel_tmp_sp + + /* Select abort stack */ + ldr x2, [x0, #THREAD_CORE_LOCAL_ABT_STACK_VA_END] + b .Lset_sp + +.Lsel_tmp_sp: + /* We have an abort while using the abort stack, select tmp stack */ + ldr x2, [x0, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] + orr w1, w1, #THREAD_CLF_TMP /* flags |= THREAD_CLF_TMP; */ + +.Lset_sp: + mov sp, x2 + str w1, [x0, #THREAD_CORE_LOCAL_FLAGS] + + /* + * Save state on stack + */ + sub sp, sp, #THREAD_ABT_REGS_SIZE + mrs x2, spsr_el1 + /* Store spsr, sp_el0 */ + stp x2, x3, [sp, #THREAD_ABT_REG_SPSR] + /* Store original x0, x1 */ + ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X0] + stp x2, x3, [sp, #THREAD_ABT_REG_X0] + /* Store original x2, x3 and x4 to x29 */ + ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X2] + store_xregs sp, THREAD_ABT_REG_X2, 2, 29 + /* Store x30, elr_el1 */ + mrs x1, elr_el1 + stp x30, x1, [sp, #THREAD_ABT_REG_X30] + +#if defined(CFG_CORE_PAUTH) + read_apiakeyhi x2 + read_apiakeylo x3 + stp x2, x3, [sp, #THREAD_ABT_REGS_APIAKEY_HI] + ldp x2, x3, [x0, #THREAD_CORE_LOCAL_KEYS] + write_apiakeyhi x2 + write_apiakeylo x3 + isb +#endif + + /* + * Call handler + */ + mov x0, #0 + mov x1, sp + bl abort_handler + + /* + * Restore state from stack + */ + /* Load x30, elr_el1 */ + ldp x30, x0, [sp, #THREAD_ABT_REG_X30] + msr elr_el1, x0 + /* Load x0 to x29 */ + load_xregs sp, THREAD_ABT_REG_X0, 0, 29 + /* Switch to SP_EL1 */ + msr spsel, #1 + /* Save x0 to x3 in CORE_LOCAL */ + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + /* Restore spsr_el1 and sp_el0 */ + mrs x3, sp_el0 + ldp x0, x1, [x3, #THREAD_ABT_REG_SPSR] + msr spsr_el1, x0 + msr sp_el0, x1 + + /* Update core local flags */ + ldr w0, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsr w0, w0, #THREAD_CLF_SAVED_SHIFT + str w0, [sp, #THREAD_CORE_LOCAL_FLAGS] + +#if defined(CFG_CORE_PAUTH) + ldp x0, x1, [x3, #THREAD_ABT_REGS_APIAKEY_HI] + write_apiakeyhi x0 + write_apiakeylo x1 + isb +#endif + + /* Restore x0 to x3 */ + load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + + /* Return from exception */ + return_from_exception +END_FUNC el1_sync_abort + + /* sp_el0 in x3 */ +LOCAL_FUNC el0_sync_abort , : + pauth_el0_to_el1 x1 + /* + * Update core local flags + */ + ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsl w1, w1, #THREAD_CLF_SAVED_SHIFT + orr w1, w1, #THREAD_CLF_ABORT + str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + + /* + * Save state on stack + */ + + /* load abt_stack_va_end */ + ldr x1, [sp, #THREAD_CORE_LOCAL_ABT_STACK_VA_END] + /* Keep pointer to initial record in x0 */ + mov x0, sp + /* Switch to SP_EL0 */ + msr spsel, #0 + mov sp, x1 + sub sp, sp, #THREAD_ABT_REGS_SIZE + mrs x2, spsr_el1 + /* Store spsr, sp_el0 */ + stp x2, x3, [sp, #THREAD_ABT_REG_SPSR] + /* Store original x0, x1 */ + ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X0] + stp x2, x3, [sp, #THREAD_ABT_REG_X0] + /* Store original x2, x3 and x4 to x29 */ + ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X2] + store_xregs sp, THREAD_ABT_REG_X2, 2, 29 + /* Store x30, elr_el1 */ + mrs x1, elr_el1 + stp x30, x1, [sp, #THREAD_ABT_REG_X30] + +#if defined(CFG_TA_PAUTH) + read_apiakeyhi x2 + read_apiakeylo x3 + stp x2, x3, [sp, #THREAD_ABT_REGS_APIAKEY_HI] +#endif + +#if defined(CFG_CORE_PAUTH) + ldp x2, x3, [x0, #THREAD_CORE_LOCAL_KEYS] + write_apiakeyhi x2 + write_apiakeylo x3 +#endif + +#if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) + /* SCTLR or the APIA key has changed */ + isb +#endif + + /* + * Call handler + */ + mov x0, #0 + mov x1, sp + bl abort_handler + + /* + * Restore state from stack + */ + + /* Load x30, elr_el1 */ + ldp x30, x0, [sp, #THREAD_ABT_REG_X30] + msr elr_el1, x0 + /* Load x0 to x29 */ + load_xregs sp, THREAD_ABT_REG_X0, 0, 29 + /* Switch to SP_EL1 */ + msr spsel, #1 + /* Save x0 to x3 in EL1_REC */ + store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 + /* Restore spsr_el1 and sp_el0 */ + mrs x3, sp_el0 + ldp x0, x1, [x3, #THREAD_ABT_REG_SPSR] + msr spsr_el1, x0 + msr sp_el0, x1 + + /* Update core local flags */ + ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsr w1, w1, #THREAD_CLF_SAVED_SHIFT + str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + ldp x1, x2, [x3, #THREAD_ABT_REGS_APIAKEY_HI] + write_apiakeyhi x1 + write_apiakeylo x2 +#endif + + /* Restore x2 to x3 */ + load_xregs sp, THREAD_CORE_LOCAL_X2, 2, 3 + + b_if_spsr_is_el0 w0, 1f + +#if defined(CFG_CORE_PAUTH) + /* the APIA key has changed */ + isb +#endif + + /* Restore x0 to x1 */ + load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 + + /* Return from exception */ + return_from_exception +1: b eret_to_el0 +END_FUNC el0_sync_abort + +/* The handler of foreign interrupt. */ +.macro foreign_intr_handler mode:req + /* + * Update core local flags + */ + ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsl w1, w1, #THREAD_CLF_SAVED_SHIFT + orr w1, w1, #THREAD_CLF_TMP + .ifc \mode\(),fiq + orr w1, w1, #THREAD_CLF_FIQ + .else + orr w1, w1, #THREAD_CLF_IRQ + .endif + str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + + /* get pointer to current thread context in x0 */ + get_thread_ctx sp, 0, 1, 2 + /* Keep original SP_EL0 */ + mrs x2, sp_el0 + + /* Store original sp_el0 */ + str x2, [x0, #THREAD_CTX_REGS_SP] + /* Store tpidr_el0 */ + mrs x2, tpidr_el0 + str x2, [x0, #THREAD_CTX_REGS_TPIDR_EL0] + /* Store x4..x30 */ + store_xregs x0, THREAD_CTX_REGS_X4, 4, 30 + /* Load original x0..x3 into x10..x13 */ + load_xregs sp, THREAD_CORE_LOCAL_X0, 10, 13 + /* Save original x0..x3 */ + store_xregs x0, THREAD_CTX_REGS_X0, 10, 13 + +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + /* Save APIAKEY */ + read_apiakeyhi x1 + read_apiakeylo x2 + store_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 +#endif +#if defined(CFG_CORE_PAUTH) + ldp x1, x2, [sp, #THREAD_CORE_LOCAL_KEYS] + write_apiakeyhi x1 + write_apiakeylo x2 + isb +#endif + /* load tmp_stack_va_end */ + ldr x1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] + /* Switch to SP_EL0 */ + msr spsel, #0 + mov sp, x1 + +#ifdef CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME + /* + * Prevent leaking information about which entries has been used in + * cache. We're relying on the dispatcher in TF-A to take care of + * the BTB. + */ + mov x0, #DCACHE_OP_CLEAN_INV + bl dcache_op_louis + ic iallu +#endif + /* + * Mark current thread as suspended + */ + mov w0, #THREAD_FLAGS_EXIT_ON_FOREIGN_INTR + mrs x1, spsr_el1 + mrs x2, elr_el1 + bl thread_state_suspend + + /* Update core local flags */ + /* Switch to SP_EL1 */ + msr spsel, #1 + ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsr w1, w1, #THREAD_CLF_SAVED_SHIFT + orr w1, w1, #THREAD_CLF_TMP + str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + msr spsel, #0 + + /* + * Note that we're exiting with SP_EL0 selected since the entry + * functions expects to have SP_EL0 selected with the tmp stack + * set. + */ + + /* Passing thread index in w0 */ + b thread_foreign_intr_exit +.endm + +/* + * This struct is never used from C it's only here to visualize the + * layout. + * + * struct elx_nintr_rec { + * uint64_t x[19 - 4]; x4..x18 + * uint64_t lr; + * uint64_t sp_el0; + * #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + * uint64_t apiakey_hi; + * uint64_t apiakey_lo; + * #endif + * }; + */ +#define ELX_NINTR_REC_X(x) (8 * ((x) - 4)) +#define ELX_NINTR_REC_LR (8 + ELX_NINTR_REC_X(19)) +#define ELX_NINTR_REC_SP_EL0 (8 + ELX_NINTR_REC_LR) +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) +#define ELX_NINTR_REG_APIAKEY_HI (8 + ELX_NINTR_REC_SP_EL0) +#define ELX_NINTR_REG_APIAKEY_LO (8 + ELX_NINTR_REG_APIAKEY_HI) +#define ELX_NINTR_REC_SIZE (8 + ELX_NINTR_REG_APIAKEY_LO) +#else +#define ELX_NINTR_REC_SIZE (8 + ELX_NINTR_REC_SP_EL0) +#endif + + +/* The handler of native interrupt. */ +.macro native_intr_handler mode:req + /* + * Update core local flags + */ + ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsl w1, w1, #THREAD_CLF_SAVED_SHIFT + .ifc \mode\(),fiq + orr w1, w1, #THREAD_CLF_FIQ + .else + orr w1, w1, #THREAD_CLF_IRQ + .endif + orr w1, w1, #THREAD_CLF_TMP + str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] + + /* + * Save registers on the temp stack that can be corrupted by a call + * to a C function. + * + * Note that we're temporarily using x1 to access the temp stack + * until we're ready to switch to sp_el0 and update sp. + */ + /* load tmp_stack_va_end */ + ldr x1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] + /* Make room for struct elx_nintr_rec */ + sub x1, x1, #ELX_NINTR_REC_SIZE + /* Store lr and original sp_el0 */ + mrs x2, sp_el0 + stp x30, x2, [x1, #ELX_NINTR_REC_LR] + /* Store x4..x18 */ + store_xregs x1, ELX_NINTR_REC_X(4), 4, 18 + +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + read_apiakeyhi x2 + read_apiakeylo x3 + stp x2, x3, [x1, #ELX_NINTR_REG_APIAKEY_HI] +#if defined(CFG_CORE_PAUTH) + ldp x2, x3, [sp, #THREAD_CORE_LOCAL_KEYS] + write_apiakeyhi x2 + write_apiakeylo x3 +#endif + /* SCTLR or the APIA key has changed */ + isb +#endif + + /* Switch to SP_EL0 */ + msr spsel, #0 + mov sp, x1 + + bl thread_check_canaries + bl itr_core_handler + + /* + * Restore registers + */ + +#if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) + ldp x0, x1, [sp, #ELX_NINTR_REG_APIAKEY_HI] + write_apiakeyhi x0 + write_apiakeylo x1 +#endif + + /* Restore x4..x18 */ + load_xregs sp, ELX_NINTR_REC_X(4), 4, 18 + /* Load lr and original sp_el0 */ + ldp x30, x2, [sp, #ELX_NINTR_REC_LR] + /* Restore SP_El0 */ + mov sp, x2 + /* Switch back to SP_EL1 */ + msr spsel, #1 + + /* Update core local flags */ + ldr w0, [sp, #THREAD_CORE_LOCAL_FLAGS] + lsr w0, w0, #THREAD_CLF_SAVED_SHIFT + str w0, [sp, #THREAD_CORE_LOCAL_FLAGS] + + mrs x0, spsr_el1 + + /* Restore x2..x3 */ + load_xregs sp, THREAD_CORE_LOCAL_X2, 2, 3 + b_if_spsr_is_el0 w0, 1f + +#if defined(CFG_CORE_PAUTH) + /* APIA key has changed */ + isb +#endif + + /* Restore x0..x1 */ + load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 + + /* Return from exception */ + return_from_exception +1: b eret_to_el0 +.endm + +LOCAL_FUNC elx_irq , : +#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) + native_intr_handler irq +#else + foreign_intr_handler irq +#endif +END_FUNC elx_irq + +LOCAL_FUNC elx_fiq , : +#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) + foreign_intr_handler fiq +#else + native_intr_handler fiq +#endif +END_FUNC elx_fiq + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c b/optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c new file mode 100644 index 0000000..bc69d8b --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_optee_smc.c @@ -0,0 +1,715 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2021, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool thread_prealloc_rpc_cache; +static unsigned int thread_rpc_pnum; + +static_assert(NOTIF_VALUE_DO_BOTTOM_HALF == + OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF); + +void thread_handle_fast_smc(struct thread_smc_args *args) +{ + thread_check_canaries(); + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && + virt_set_guest(args->a7)) { + args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; + goto out; + } + + tee_entry_fast(args); + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + virt_unset_guest(); + +out: + /* Fast handlers must not unmask any exceptions */ + assert(thread_get_exceptions() == THREAD_EXCP_ALL); +} + +uint32_t thread_handle_std_smc(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6 __unused, uint32_t a7 __maybe_unused) +{ + uint32_t rv = OPTEE_SMC_RETURN_OK; + + thread_check_canaries(); + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(a7)) + return OPTEE_SMC_RETURN_ENOTAVAIL; + + /* + * thread_resume_from_rpc() and thread_alloc_and_run() only return + * on error. Successful return is done via thread_exit() or + * thread_rpc(). + */ + if (a0 == OPTEE_SMC_CALL_RETURN_FROM_RPC) { + thread_resume_from_rpc(a3, a1, a2, a4, a5); + rv = OPTEE_SMC_RETURN_ERESUME; + } else { + thread_alloc_and_run(a0, a1, a2, a3, 0, 0); + rv = OPTEE_SMC_RETURN_ETHREAD_LIMIT; + } + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + virt_unset_guest(); + + return rv; +} + +/** + * Free physical memory previously allocated with thread_rpc_alloc_arg() + * + * @cookie: cookie received when allocating the buffer + */ +static void thread_rpc_free_arg(uint64_t cookie) +{ + if (cookie) { + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { + OPTEE_SMC_RETURN_RPC_FREE + }; + + reg_pair_from_64(cookie, rpc_args + 1, rpc_args + 2); + thread_rpc(rpc_args); + } +} + +static uint32_t get_msg_arg(struct mobj *mobj, size_t offset, + size_t *num_params, struct optee_msg_arg **arg, + struct optee_msg_arg **rpc_arg) +{ + void *p = NULL; + size_t sz = 0; + + if (!mobj) + return OPTEE_SMC_RETURN_EBADADDR; + + p = mobj_get_va(mobj, offset, sizeof(struct optee_msg_arg)); + if (!p || !IS_ALIGNED_WITH_TYPE(p, struct optee_msg_arg)) + return OPTEE_SMC_RETURN_EBADADDR; + + *arg = p; + *num_params = READ_ONCE((*arg)->num_params); + if (*num_params > OPTEE_MSG_MAX_NUM_PARAMS) + return OPTEE_SMC_RETURN_EBADADDR; + + sz = OPTEE_MSG_GET_ARG_SIZE(*num_params); + if (!mobj_get_va(mobj, offset, sz)) + return OPTEE_SMC_RETURN_EBADADDR; + + if (rpc_arg) { + size_t rpc_sz = 0; + + rpc_sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); + p = mobj_get_va(mobj, offset + sz, rpc_sz); + if (!p) + return OPTEE_SMC_RETURN_EBADADDR; + *rpc_arg = p; + } + + return OPTEE_SMC_RETURN_OK; +} + +static void clear_prealloc_rpc_cache(struct thread_ctx *thr) +{ + thread_rpc_free_arg(mobj_get_cookie(thr->rpc_mobj)); + mobj_put(thr->rpc_mobj); + thr->rpc_arg = NULL; + thr->rpc_mobj = NULL; +} + +static uint32_t call_entry_std(struct optee_msg_arg *arg, size_t num_params, + struct optee_msg_arg *rpc_arg) +{ + struct thread_ctx *thr = threads + thread_get_id(); + uint32_t rv = 0; + + if (rpc_arg) { + /* + * In case the prealloc RPC arg cache is enabled, clear the + * cached object for this thread. + * + * Normally it doesn't make sense to have the prealloc RPC + * arg cache enabled together with a supplied RPC arg + * struct. But if it is we must use the supplied struct and + * at the same time make sure to not break anything. + */ + if (IS_ENABLED(CFG_PREALLOC_RPC_CACHE) && + thread_prealloc_rpc_cache) + clear_prealloc_rpc_cache(thr); + thr->rpc_arg = rpc_arg; + } + + if (tee_entry_std(arg, num_params)) + rv = OPTEE_SMC_RETURN_EBADCMD; + else + rv = OPTEE_SMC_RETURN_OK; + + thread_rpc_shm_cache_clear(&thr->shm_cache); + if (rpc_arg) + thr->rpc_arg = NULL; + + if (rv == OPTEE_SMC_RETURN_OK && + !(IS_ENABLED(CFG_PREALLOC_RPC_CACHE) && thread_prealloc_rpc_cache)) + clear_prealloc_rpc_cache(thr); + + return rv; +} + +static uint32_t std_entry_with_parg(paddr_t parg, bool with_rpc_arg) +{ + size_t sz = sizeof(struct optee_msg_arg); + struct optee_msg_arg *rpc_arg = NULL; + struct optee_msg_arg *arg = NULL; + struct mobj *mobj = NULL; + size_t num_params = 0; + uint32_t rv = 0; + + /* Check if this region is in static shared space */ + if (core_pbuf_is(CORE_MEM_NSEC_SHM, parg, sz)) { + if (!IS_ALIGNED_WITH_TYPE(parg, struct optee_msg_arg)) + goto bad_addr; + + arg = phys_to_virt(parg, MEM_AREA_NSEC_SHM, + sizeof(struct optee_msg_arg)); + if (!arg) + goto bad_addr; + + num_params = READ_ONCE(arg->num_params); + if (num_params > OPTEE_MSG_MAX_NUM_PARAMS) + return OPTEE_SMC_RETURN_EBADADDR; + + sz = OPTEE_MSG_GET_ARG_SIZE(num_params); + if (with_rpc_arg) { + rpc_arg = (void *)((uint8_t *)arg + sz); + sz += OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); + } + if (!core_pbuf_is(CORE_MEM_NSEC_SHM, parg, sz)) + goto bad_addr; + + return call_entry_std(arg, num_params, rpc_arg); + } else { + if (parg & SMALL_PAGE_MASK) + goto bad_addr; + /* + * mobj_mapped_shm_alloc checks if parg resides in nonsec + * ddr. + */ + mobj = mobj_mapped_shm_alloc(&parg, 1, 0, 0); + if (!mobj) + goto bad_addr; + if (with_rpc_arg) + rv = get_msg_arg(mobj, 0, &num_params, &arg, &rpc_arg); + else + rv = get_msg_arg(mobj, 0, &num_params, &arg, NULL); + if (!rv) + rv = call_entry_std(arg, num_params, rpc_arg); + mobj_put(mobj); + return rv; + } + +bad_addr: + EMSG("Bad arg address 0x%"PRIxPA, parg); + return OPTEE_SMC_RETURN_EBADADDR; +} + +static uint32_t std_entry_with_regd_arg(uint64_t cookie, size_t offset) +{ + struct optee_msg_arg *rpc_arg = NULL; + struct optee_msg_arg *arg = NULL; + size_t num_params = 0; + struct mobj *mobj = NULL; + uint32_t rv = 0; + + mobj = mobj_reg_shm_get_by_cookie(cookie); + if (!mobj) { + EMSG("Bad arg cookie 0x%"PRIx64, cookie); + return OPTEE_SMC_RETURN_EBADADDR; + } + + if (mobj_inc_map(mobj)) { + rv = OPTEE_SMC_RETURN_ENOMEM; + goto out; + } + + rv = get_msg_arg(mobj, offset, &num_params, &arg, &rpc_arg); + if (!rv) + rv = call_entry_std(arg, num_params, rpc_arg); + + mobj_dec_map(mobj); +out: + mobj_put(mobj); + + return rv; +} + +static uint32_t std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3 __unused) +{ + const bool with_rpc_arg = true; + + switch (a0) { + case OPTEE_SMC_CALL_WITH_ARG: + return std_entry_with_parg(reg_pair_to_64(a1, a2), + !with_rpc_arg); + case OPTEE_SMC_CALL_WITH_RPC_ARG: + return std_entry_with_parg(reg_pair_to_64(a1, a2), + with_rpc_arg); + case OPTEE_SMC_CALL_WITH_REGD_ARG: + return std_entry_with_regd_arg(reg_pair_to_64(a1, a2), a3); + default: + EMSG("Unknown SMC 0x%"PRIx32, a0); + return OPTEE_SMC_RETURN_EBADCMD; + } +} + +/* + * Helper routine for the assembly function thread_std_smc_entry() + * + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area. + */ +uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4 __unused, + uint32_t a5 __unused) +{ + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + virt_on_stdcall(); + + return std_smc_entry(a0, a1, a2, a3); +} + +bool thread_disable_prealloc_rpc_cache(uint64_t *cookie) +{ + bool rv = false; + size_t n = 0; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + + thread_lock_global(); + + for (n = 0; n < CFG_NUM_THREADS; n++) { + if (threads[n].state != THREAD_STATE_FREE) { + rv = false; + goto out; + } + } + + rv = true; + + if (IS_ENABLED(CFG_PREALLOC_RPC_CACHE)) { + for (n = 0; n < CFG_NUM_THREADS; n++) { + if (threads[n].rpc_arg) { + *cookie = mobj_get_cookie(threads[n].rpc_mobj); + mobj_put(threads[n].rpc_mobj); + threads[n].rpc_arg = NULL; + threads[n].rpc_mobj = NULL; + goto out; + } + } + } + + *cookie = 0; + thread_prealloc_rpc_cache = false; +out: + thread_unlock_global(); + thread_unmask_exceptions(exceptions); + return rv; +} + +bool thread_enable_prealloc_rpc_cache(void) +{ + bool rv = false; + size_t n = 0; + uint32_t exceptions = 0; + + if (!IS_ENABLED(CFG_PREALLOC_RPC_CACHE)) + return true; + + exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + thread_lock_global(); + + for (n = 0; n < CFG_NUM_THREADS; n++) { + if (threads[n].state != THREAD_STATE_FREE) { + rv = false; + goto out; + } + } + + rv = true; + thread_prealloc_rpc_cache = true; +out: + thread_unlock_global(); + thread_unmask_exceptions(exceptions); + return rv; +} + +static struct mobj *rpc_shm_mobj_alloc(paddr_t pa, size_t sz, uint64_t cookie) +{ + /* Check if this region is in static shared space */ + if (core_pbuf_is(CORE_MEM_NSEC_SHM, pa, sz)) + return mobj_shm_alloc(pa, sz, cookie); + + if (IS_ENABLED(CFG_CORE_DYN_SHM) && + !(pa & SMALL_PAGE_MASK) && sz <= SMALL_PAGE_SIZE) + return mobj_mapped_shm_alloc(&pa, 1, 0, cookie); + + return NULL; +} + +/** + * Allocates data for struct optee_msg_arg. + * + * @size: size in bytes of struct optee_msg_arg + * + * @returns mobj that describes allocated buffer or NULL on error + */ +static struct mobj *thread_rpc_alloc_arg(size_t size) +{ + paddr_t pa; + uint64_t co; + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { + OPTEE_SMC_RETURN_RPC_ALLOC, size + }; + struct mobj *mobj = NULL; + + thread_rpc(rpc_args); + + /* Registers 1 and 2 passed from normal world */ + pa = reg_pair_to_64(rpc_args[0], rpc_args[1]); + /* Registers 4 and 5 passed from normal world */ + co = reg_pair_to_64(rpc_args[2], rpc_args[3]); + + if (!IS_ALIGNED_WITH_TYPE(pa, struct optee_msg_arg)) + goto err; + + mobj = rpc_shm_mobj_alloc(pa, size, co); + if (!mobj) + goto err; + + return mobj; +err: + thread_rpc_free_arg(co); + mobj_put(mobj); + return NULL; +} + +static bool set_rmem(struct optee_msg_param *param, + struct thread_param *tpm) +{ + param->attr = tpm->attr - THREAD_PARAM_ATTR_MEMREF_IN + + OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; + param->u.rmem.offs = tpm->u.memref.offs; + param->u.rmem.size = tpm->u.memref.size; + if (tpm->u.memref.mobj) { + param->u.rmem.shm_ref = mobj_get_cookie(tpm->u.memref.mobj); + if (!param->u.rmem.shm_ref) + return false; + } else { + param->u.rmem.shm_ref = 0; + } + + return true; +} + +static bool set_tmem(struct optee_msg_param *param, + struct thread_param *tpm) +{ + paddr_t pa = 0; + uint64_t shm_ref = 0; + struct mobj *mobj = tpm->u.memref.mobj; + + param->attr = tpm->attr - THREAD_PARAM_ATTR_MEMREF_IN + + OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; + if (mobj) { + shm_ref = mobj_get_cookie(mobj); + if (!shm_ref) + return false; + if (mobj_get_pa(mobj, tpm->u.memref.offs, 0, &pa)) + return false; + } + + param->u.tmem.size = tpm->u.memref.size; + param->u.tmem.buf_ptr = pa; + param->u.tmem.shm_ref = shm_ref; + + return true; +} + +static uint32_t get_rpc_arg(uint32_t cmd, size_t num_params, + struct thread_param *params, void **arg_ret, + uint64_t *carg_ret) +{ + struct thread_ctx *thr = threads + thread_get_id(); + struct optee_msg_arg *arg = thr->rpc_arg; + size_t sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); + + if (num_params > THREAD_RPC_MAX_NUM_PARAMS) + return TEE_ERROR_BAD_PARAMETERS; + + if (!arg) { + struct mobj *mobj = thread_rpc_alloc_arg(sz); + + if (!mobj) + return TEE_ERROR_OUT_OF_MEMORY; + + arg = mobj_get_va(mobj, 0, sz); + if (!arg) { + thread_rpc_free_arg(mobj_get_cookie(mobj)); + return TEE_ERROR_OUT_OF_MEMORY; + } + + thr->rpc_arg = arg; + thr->rpc_mobj = mobj; + } + + memset(arg, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); + arg->cmd = cmd; + arg->num_params = num_params; + arg->ret = TEE_ERROR_GENERIC; /* in case value isn't updated */ + + for (size_t n = 0; n < num_params; n++) { + switch (params[n].attr) { + case THREAD_PARAM_ATTR_NONE: + arg->params[n].attr = OPTEE_MSG_ATTR_TYPE_NONE; + break; + case THREAD_PARAM_ATTR_VALUE_IN: + case THREAD_PARAM_ATTR_VALUE_OUT: + case THREAD_PARAM_ATTR_VALUE_INOUT: + arg->params[n].attr = params[n].attr - + THREAD_PARAM_ATTR_VALUE_IN + + OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + arg->params[n].u.value.a = params[n].u.value.a; + arg->params[n].u.value.b = params[n].u.value.b; + arg->params[n].u.value.c = params[n].u.value.c; + break; + case THREAD_PARAM_ATTR_MEMREF_IN: + case THREAD_PARAM_ATTR_MEMREF_OUT: + case THREAD_PARAM_ATTR_MEMREF_INOUT: + if (!params[n].u.memref.mobj || + mobj_matches(params[n].u.memref.mobj, + CORE_MEM_NSEC_SHM)) { + if (!set_tmem(arg->params + n, params + n)) + return TEE_ERROR_BAD_PARAMETERS; + } else if (mobj_matches(params[n].u.memref.mobj, + CORE_MEM_REG_SHM)) { + if (!set_rmem(arg->params + n, params + n)) + return TEE_ERROR_BAD_PARAMETERS; + } else { + return TEE_ERROR_BAD_PARAMETERS; + } + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + } + + *arg_ret = arg; + *carg_ret = mobj_get_cookie(thr->rpc_mobj); + + return TEE_SUCCESS; +} + +static uint32_t get_rpc_arg_res(struct optee_msg_arg *arg, size_t num_params, + struct thread_param *params) +{ + for (size_t n = 0; n < num_params; n++) { + switch (params[n].attr) { + case THREAD_PARAM_ATTR_VALUE_OUT: + case THREAD_PARAM_ATTR_VALUE_INOUT: + params[n].u.value.a = arg->params[n].u.value.a; + params[n].u.value.b = arg->params[n].u.value.b; + params[n].u.value.c = arg->params[n].u.value.c; + break; + case THREAD_PARAM_ATTR_MEMREF_OUT: + case THREAD_PARAM_ATTR_MEMREF_INOUT: + /* + * rmem.size and tmem.size is the same type and + * location. + */ + params[n].u.memref.size = arg->params[n].u.rmem.size; + break; + default: + break; + } + } + + return arg->ret; +} + +uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params, + struct thread_param *params) +{ + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_SMC_RETURN_RPC_CMD }; + void *arg = NULL; + uint64_t carg = 0; + uint32_t ret = 0; + + /* The source CRYPTO_RNG_SRC_JITTER_RPC is safe to use here */ + plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_RPC, + &thread_rpc_pnum); + + ret = get_rpc_arg(cmd, num_params, params, &arg, &carg); + if (ret) + return ret; + + reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); + thread_rpc(rpc_args); + + return get_rpc_arg_res(arg, num_params, params); +} + +/** + * Free physical memory previously allocated with thread_rpc_alloc() + * + * @cookie: cookie received when allocating the buffer + * @bt: must be the same as supplied when allocating + * @mobj: mobj that describes allocated buffer + * + * This function also frees corresponding mobj. + */ +static void thread_rpc_free(unsigned int bt, uint64_t cookie, struct mobj *mobj) +{ + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_SMC_RETURN_RPC_CMD }; + void *arg = NULL; + uint64_t carg = 0; + struct thread_param param = THREAD_PARAM_VALUE(IN, bt, cookie, 0); + uint32_t ret = get_rpc_arg(OPTEE_RPC_CMD_SHM_FREE, 1, ¶m, + &arg, &carg); + + mobj_put(mobj); + + if (!ret) { + reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); + thread_rpc(rpc_args); + } +} + +static struct mobj *get_rpc_alloc_res(struct optee_msg_arg *arg, + unsigned int bt, size_t size) +{ + struct mobj *mobj = NULL; + uint64_t cookie = 0; + size_t sz = 0; + paddr_t p = 0; + + if (arg->ret || arg->num_params != 1) + goto err; + + if (arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT && + arg->params[0].attr != (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | + OPTEE_MSG_ATTR_NONCONTIG)) + goto err; + + p = arg->params[0].u.tmem.buf_ptr; + sz = READ_ONCE(arg->params[0].u.tmem.size); + cookie = arg->params[0].u.tmem.shm_ref; + if (sz < size) + goto err; + + if (arg->params[0].attr == OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT) + mobj = rpc_shm_mobj_alloc(p, sz, cookie); + else + mobj = msg_param_mobj_from_noncontig(p, sz, cookie, true); + + if (!mobj) { + thread_rpc_free(bt, cookie, mobj); + goto err; + } + + assert(mobj_is_nonsec(mobj)); + return mobj; +err: + EMSG("RPC allocation failed. Non-secure world result: ret=%#" + PRIx32" ret_origin=%#"PRIx32, arg->ret, arg->ret_origin); + return NULL; +} + +/** + * Allocates shared memory buffer via RPC + * + * @size: size in bytes of shared memory buffer + * @align: required alignment of buffer + * @bt: buffer type OPTEE_RPC_SHM_TYPE_* + * + * Returns a pointer to MOBJ for the memory on success, or NULL on failure. + */ +static struct mobj *thread_rpc_alloc(size_t size, size_t align, unsigned int bt) +{ + uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_SMC_RETURN_RPC_CMD }; + void *arg = NULL; + uint64_t carg = 0; + struct thread_param param = THREAD_PARAM_VALUE(IN, bt, size, align); + uint32_t ret = get_rpc_arg(OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m, + &arg, &carg); + + if (ret) + return NULL; + + reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); + thread_rpc(rpc_args); + + return get_rpc_alloc_res(arg, bt, size); +} + +struct mobj *thread_rpc_alloc_payload(size_t size) +{ + return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_APPL); +} + +struct mobj *thread_rpc_alloc_kernel_payload(size_t size) +{ + /* + * Error out early since kernel private dynamic shared memory + * allocations don't currently use the `OPTEE_MSG_ATTR_NONCONTIG` bit + * and therefore cannot be larger than a page. + */ + if (IS_ENABLED(CFG_CORE_DYN_SHM) && size > SMALL_PAGE_SIZE) + return NULL; + + return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL); +} + +void thread_rpc_free_kernel_payload(struct mobj *mobj) +{ + thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj); +} + +void thread_rpc_free_payload(struct mobj *mobj) +{ + thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), + mobj); +} + +struct mobj *thread_rpc_alloc_global_payload(size_t size) +{ + return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_GLOBAL); +} + +void thread_rpc_free_global_payload(struct mobj *mobj) +{ + thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, mobj_get_cookie(mobj), + mobj); +} diff --git a/optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a32.S b/optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a32.S new file mode 100644 index 0000000..e48150d --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a32.S @@ -0,0 +1,255 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +.arch_extension sec + +/* + * If ASLR is configured the identity mapped code may be mapped at two + * locations, the identity location where virtual and physical address is + * the same and at the runtime selected location to which OP-TEE has been + * relocated. Code executing at a location different compared to the + * runtime selected location works OK as long as it doesn't do relative + * addressing outside the identity mapped range. To allow relative + * addressing this macro jumps to the runtime selected location. + * + * Note that the identity mapped range and the runtime selected range can + * only differ if ASLR is configured. + */ + .macro readjust_pc +#ifdef CFG_CORE_ASLR + ldr r12, =1111f + bx r12 +1111: +#endif + .endm + +FUNC vector_std_smc_entry , : , .identity_map +UNWIND( .cantunwind) + readjust_pc + push {r4-r7} + bl thread_handle_std_smc + add sp, sp, #(4 * 4) + /* + * Normally thread_handle_std_smc() should return via + * thread_exit(), thread_rpc(), but if thread_handle_std_smc() + * hasn't switched stack (error detected) it will do a normal "C" + * return. + */ + mov r1, r0 + ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_std_smc_entry + +FUNC vector_fast_smc_entry , : , .identity_map +UNWIND( .cantunwind) + readjust_pc + push {r0-r7} + mov r0, sp + bl thread_handle_fast_smc + pop {r1-r8} + ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_fast_smc_entry + +FUNC vector_fiq_entry , : , .identity_map +UNWIND( .cantunwind) + readjust_pc + /* Secure Monitor received a FIQ and passed control to us. */ + bl thread_check_canaries + bl itr_core_handler + ldr r0, =TEESMC_OPTEED_RETURN_FIQ_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_fiq_entry + +#if defined(CFG_WITH_ARM_TRUSTED_FW) +LOCAL_FUNC vector_cpu_on_entry , : , .identity_map +UNWIND( .cantunwind) + bl cpu_on_handler + /* When cpu_on_handler() returns mmu is enabled */ + mov r1, r0 + ldr r0, =TEESMC_OPTEED_RETURN_ON_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_cpu_on_entry + +LOCAL_FUNC vector_cpu_off_entry , : , .identity_map +UNWIND( .cantunwind) + readjust_pc + bl thread_cpu_off_handler + mov r1, r0 + ldr r0, =TEESMC_OPTEED_RETURN_OFF_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_cpu_off_entry + +LOCAL_FUNC vector_cpu_suspend_entry , : , .identity_map +UNWIND( .cantunwind) + readjust_pc + bl thread_cpu_suspend_handler + mov r1, r0 + ldr r0, =TEESMC_OPTEED_RETURN_SUSPEND_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_cpu_suspend_entry + +LOCAL_FUNC vector_cpu_resume_entry , : , .identity_map +UNWIND( .cantunwind) + readjust_pc + bl thread_cpu_resume_handler + mov r1, r0 + ldr r0, =TEESMC_OPTEED_RETURN_RESUME_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_cpu_resume_entry + +LOCAL_FUNC vector_system_off_entry , : , .identity_map +UNWIND( .cantunwind) + readjust_pc + bl thread_system_off_handler + mov r1, r0 + ldr r0, =TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_system_off_entry + +LOCAL_FUNC vector_system_reset_entry , : , .identity_map +UNWIND( .cantunwind) + readjust_pc + bl thread_system_reset_handler + mov r1, r0 + ldr r0, =TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_system_reset_entry + +/* + * Vector table supplied to ARM Trusted Firmware (ARM-TF) at + * initialization. Also used when compiled with the internal monitor, but + * the cpu_*_entry and system_*_entry are not used then. + * + * Note that ARM-TF depends on the layout of this vector table, any change + * in layout has to be synced with ARM-TF. + */ +FUNC thread_vector_table , : , .identity_map +UNWIND( .cantunwind) + b vector_std_smc_entry + b vector_fast_smc_entry + b vector_cpu_on_entry + b vector_cpu_off_entry + b vector_cpu_resume_entry + b vector_cpu_suspend_entry + b vector_fiq_entry + b vector_system_off_entry + b vector_system_reset_entry +END_FUNC thread_vector_table +DECLARE_KEEP_PAGER thread_vector_table +#endif /*if defined(CFG_WITH_ARM_TRUSTED_FW)*/ + +FUNC thread_std_smc_entry , : +UNWIND( .cantunwind) + push {r4, r5} /* Pass these following the arm32 calling convention */ + bl __thread_std_smc_entry + add sp, sp, #8 /* There's nothing return, just restore the sp */ + mov r4, r0 /* Save return value for later */ + + /* Disable interrupts before switching to temporary stack */ + cpsid aif + bl thread_get_tmp_sp + mov sp, r0 + + bl thread_state_free + + ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE + mov r1, r4 + mov r2, #0 + mov r3, #0 + mov r4, #0 + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC thread_std_smc_entry + +/* void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) */ +FUNC thread_rpc , : + push {r0, lr} +UNWIND( .save {r0, lr}) + + 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 r4, r0 /* Supply thread index */ + ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE + ldm r5, {r1-r3} /* Load rv[] into r0-r2 */ + smc #0 + /* SMC should not return */ + panic_at_smc_return + +.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, lr} /* Get pointer to rv[] */ + stm r12, {r0-r3} /* Store r0-r3 into rv[] */ + bx lr +END_FUNC thread_rpc +DECLARE_KEEP_PAGER thread_rpc + +/* + * void thread_foreign_intr_exit(uint32_t thread_index) + * + * This function is jumped to at the end of macro foreign_intr_handler(). + * The current thread as indicated by @thread_index has just been + * suspended. The job here is just to inform normal world the thread id to + * resume when returning. + */ +FUNC thread_foreign_intr_exit , : + mov r4, r0 + ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE + ldr r1, =OPTEE_SMC_RETURN_RPC_FOREIGN_INTR + mov r2, #0 + mov r3, #0 + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC thread_foreign_intr_exit diff --git a/optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S b/optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S new file mode 100644 index 0000000..6702b65 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_optee_smc_a64.S @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * If ASLR is configured the identity mapped code may be mapped at two + * locations, the identity location where virtual and physical address is + * the same and at the runtime selected location to which OP-TEE has been + * relocated. Code executing at a location different compared to the + * runtime selected location works OK as long as it doesn't do relative + * addressing outside the identity mapped range. To allow relative + * addressing this macro jumps to the runtime selected location. + * + * Note that the identity mapped range and the runtime selected range can + * only differ if ASLR is configured. + */ + .macro readjust_pc +#ifdef CFG_CORE_ASLR + adr x16, 1111f + ldr x17, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET + add x16, x16, x17 + br x16 +1111: +BTI( bti j) +#endif + .endm + +LOCAL_FUNC vector_std_smc_entry , : , .identity_map + readjust_pc + bl thread_handle_std_smc + /* + * Normally thread_handle_std_smc() should return via + * thread_exit(), thread_rpc(), but if thread_handle_std_smc() + * hasn't switched stack (error detected) it will do a normal "C" + * return. + */ + mov w1, w0 + ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_std_smc_entry + +LOCAL_FUNC vector_fast_smc_entry , : , .identity_map + readjust_pc + sub sp, sp, #THREAD_SMC_ARGS_SIZE + store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 + mov x0, sp + bl thread_handle_fast_smc + load_xregs sp, THREAD_SMC_ARGS_X0, 1, 8 + add sp, sp, #THREAD_SMC_ARGS_SIZE + ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_fast_smc_entry + +LOCAL_FUNC vector_fiq_entry , : , .identity_map + readjust_pc + /* Secure Monitor received a FIQ and passed control to us. */ + bl thread_check_canaries + bl itr_core_handler + ldr x0, =TEESMC_OPTEED_RETURN_FIQ_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_fiq_entry + +LOCAL_FUNC vector_cpu_on_entry , : , .identity_map + bl cpu_on_handler + mov x1, x0 + ldr x0, =TEESMC_OPTEED_RETURN_ON_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_cpu_on_entry + +LOCAL_FUNC vector_cpu_off_entry , : , .identity_map + readjust_pc + bl thread_cpu_off_handler + mov x1, x0 + ldr x0, =TEESMC_OPTEED_RETURN_OFF_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_cpu_off_entry + +LOCAL_FUNC vector_cpu_suspend_entry , : , .identity_map + readjust_pc + bl thread_cpu_suspend_handler + mov x1, x0 + ldr x0, =TEESMC_OPTEED_RETURN_SUSPEND_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_cpu_suspend_entry + +LOCAL_FUNC vector_cpu_resume_entry , : , .identity_map + readjust_pc + bl thread_cpu_resume_handler + mov x1, x0 + ldr x0, =TEESMC_OPTEED_RETURN_RESUME_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_cpu_resume_entry + +LOCAL_FUNC vector_system_off_entry , : , .identity_map + readjust_pc + bl thread_system_off_handler + mov x1, x0 + ldr x0, =TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_system_off_entry + +LOCAL_FUNC vector_system_reset_entry , : , .identity_map + readjust_pc + bl thread_system_reset_handler + mov x1, x0 + ldr x0, =TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC vector_system_reset_entry + +/* + * Vector table supplied to ARM Trusted Firmware (ARM-TF) at + * initialization. + * + * Note that ARM-TF depends on the layout of this vector table, any change + * in layout has to be synced with ARM-TF. + */ +FUNC thread_vector_table , : , .identity_map, , nobti + b vector_std_smc_entry + b vector_fast_smc_entry + b vector_cpu_on_entry + b vector_cpu_off_entry + b vector_cpu_resume_entry + b vector_cpu_suspend_entry + b vector_fiq_entry + b vector_system_off_entry + b vector_system_reset_entry +END_FUNC thread_vector_table +DECLARE_KEEP_PAGER thread_vector_table + +FUNC thread_std_smc_entry , : + bl __thread_std_smc_entry + mov w20, w0 /* Save return value for later */ + + /* Mask all maskable exceptions before switching to temporary stack */ + msr daifset, #DAIFBIT_ALL + bl thread_get_tmp_sp + mov sp, x0 + + bl thread_state_free + + ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE + mov w1, w20 + mov x2, #0 + mov x3, #0 + mov x4, #0 + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC thread_std_smc_entry + +/* void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) */ +FUNC thread_rpc , : + /* Read daif and create an SPSR */ + mrs x1, daif + orr x1, x1, #(SPSR_64_MODE_EL1 << SPSR_64_MODE_EL_SHIFT) + + /* Mask all maskable exceptions before switching to temporary stack */ + msr daifset, #DAIFBIT_ALL + push x0, xzr + push x1, x30 + bl thread_get_ctx_regs + ldr x30, [sp, #8] + store_xregs x0, THREAD_CTX_REGS_X19, 19, 30 + mov x19, x0 + +#if defined(CFG_CORE_PAUTH) + /* Save APIAKEY */ + read_apiakeyhi x1 + read_apiakeylo x2 + store_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 +#endif + + bl thread_get_tmp_sp + pop x1, xzr /* Match "push x1, x30" above */ + mov x2, sp + str x2, [x19, #THREAD_CTX_REGS_SP] + ldr x20, [sp] /* Get pointer to rv[] */ + mov sp, x0 /* Switch to tmp stack */ + /* + * We need to read rv[] early, because thread_state_suspend + * can invoke virt_unset_guest() which will unmap pages, + * where rv[] resides + */ + load_wregs x20, 0, 21, 23 /* Load rv[] into w20-w22 */ + + adr x2, .thread_rpc_return + mov w0, #THREAD_FLAGS_COPY_ARGS_ON_RETURN + bl thread_state_suspend + mov x4, x0 /* Supply thread index */ + ldr w0, =TEESMC_OPTEED_RETURN_CALL_DONE + mov x1, x21 + mov x2, x22 + mov x3, x23 + smc #0 + /* SMC should not return */ + panic_at_smc_return + +.thread_rpc_return: + /* + * At this point has the stack pointer been restored to the value + * stored in THREAD_CTX 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 x16, xzr /* Get pointer to rv[] */ + store_wregs x16, 0, 0, 3 /* Store w0-w3 into rv[] */ + ret +END_FUNC thread_rpc +DECLARE_KEEP_PAGER thread_rpc + +/* + * void thread_foreign_intr_exit(uint32_t thread_index) + * + * This function is jumped to at the end of macro foreign_intr_handler(). + * The current thread as indicated by @thread_index has just been + * suspended. The job here is just to inform normal world the thread id to + * resume when returning. + */ +FUNC thread_foreign_intr_exit , : + mov w4, w0 + ldr w0, =TEESMC_OPTEED_RETURN_CALL_DONE + ldr w1, =OPTEE_SMC_RETURN_RPC_FOREIGN_INTR + mov w2, #0 + mov w3, #0 + smc #0 + /* SMC should not return */ + panic_at_smc_return +END_FUNC thread_foreign_intr_exit + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/thread_spmc.c b/optee/optee_os/core/arch/arm/kernel/thread_spmc.c new file mode 100644 index 0000000..d9bfef8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_spmc.c @@ -0,0 +1,1526 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020-2021, Linaro Limited. + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CFG_CORE_SEL1_SPMC) +struct mem_share_state { + struct mobj_ffa *mf; + unsigned int page_count; + unsigned int region_count; + unsigned int current_page_idx; +}; + +struct mem_frag_state { + struct mem_share_state share; + tee_mm_entry_t *mm; + unsigned int frag_offset; + SLIST_ENTRY(mem_frag_state) link; +}; +#endif + +/* Initialized in spmc_init() below */ +static uint16_t my_endpoint_id; + +/* + * If struct ffa_rxtx::size is 0 RX/TX buffers are not mapped or initialized. + * + * struct ffa_rxtx::spin_lock protects the variables below from concurrent + * access this includes the use of content of struct ffa_rxtx::rx and + * @frag_state_head. + * + * struct ffa_rxtx::tx_buf_is_mine is true when we may write to struct + * ffa_rxtx::tx and false when it is owned by normal world. + * + * Note that we can't prevent normal world from updating the content of + * these buffers so we must always be careful when reading. while we hold + * the lock. + */ + +#ifdef CFG_CORE_SEL1_SPMC +static struct ffa_rxtx nw_rxtx; + +static bool is_nw_buf(struct ffa_rxtx *rxtx) +{ + return rxtx == &nw_rxtx; +} + +static SLIST_HEAD(mem_frag_state_head, mem_frag_state) frag_state_head = + SLIST_HEAD_INITIALIZER(&frag_state_head); +#else +static uint8_t __rx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE); +static uint8_t __tx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE); +static struct ffa_rxtx nw_rxtx = { .rx = __rx_buf, .tx = __tx_buf }; +#endif + +static uint32_t swap_src_dst(uint32_t src_dst) +{ + return (src_dst >> 16) | (src_dst << 16); +} + +void spmc_set_args(struct thread_smc_args *args, uint32_t fid, uint32_t src_dst, + uint32_t w2, uint32_t w3, uint32_t w4, uint32_t w5) +{ + *args = (struct thread_smc_args){ .a0 = fid, + .a1 = src_dst, + .a2 = w2, + .a3 = w3, + .a4 = w4, + .a5 = w5, }; +} + +#if defined(CFG_CORE_SEL1_SPMC) +void spmc_handle_version(struct thread_smc_args *args) +{ + /* + * We currently only support one version, 1.0 so let's keep it + * simple. + */ + spmc_set_args(args, + MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR), + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +static void handle_features(struct thread_smc_args *args) +{ + uint32_t ret_fid = 0; + uint32_t ret_w2 = FFA_PARAM_MBZ; + + switch (args->a1) { +#ifdef ARM64 + case FFA_RXTX_MAP_64: +#endif + case FFA_RXTX_MAP_32: + ret_fid = FFA_SUCCESS_32; + ret_w2 = 0; /* 4kB Minimum buffer size and alignment boundary */ + break; +#ifdef ARM64 + case FFA_MEM_SHARE_64: +#endif + case FFA_MEM_SHARE_32: + ret_fid = FFA_SUCCESS_32; + /* + * Partition manager supports transmission of a memory + * transaction descriptor in a buffer dynamically allocated + * by the endpoint. + */ + ret_w2 = BIT(0); + break; + + case FFA_ERROR: + case FFA_VERSION: + case FFA_SUCCESS_32: +#ifdef ARM64 + case FFA_SUCCESS_64: +#endif + case FFA_MEM_FRAG_TX: + case FFA_MEM_RECLAIM: + case FFA_MSG_SEND_DIRECT_REQ_32: + case FFA_INTERRUPT: + case FFA_PARTITION_INFO_GET: + case FFA_RX_RELEASE: + ret_fid = FFA_SUCCESS_32; + break; + default: + ret_fid = FFA_ERROR; + ret_w2 = FFA_NOT_SUPPORTED; + break; + } + + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_w2, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +static int map_buf(paddr_t pa, unsigned int sz, void **va_ret) +{ + tee_mm_entry_t *mm = NULL; + + if (!core_pbuf_is(CORE_MEM_NON_SEC, pa, sz)) + return FFA_INVALID_PARAMETERS; + + mm = tee_mm_alloc(&tee_mm_shm, sz); + if (!mm) + return FFA_NO_MEMORY; + + if (core_mmu_map_contiguous_pages(tee_mm_get_smem(mm), pa, + sz / SMALL_PAGE_SIZE, + MEM_AREA_NSEC_SHM)) { + tee_mm_free(mm); + return FFA_INVALID_PARAMETERS; + } + + *va_ret = (void *)tee_mm_get_smem(mm); + return 0; +} + +static void unmap_buf(void *va, size_t sz) +{ + tee_mm_entry_t *mm = tee_mm_find(&tee_mm_shm, (vaddr_t)va); + + assert(mm); + core_mmu_unmap_pages(tee_mm_get_smem(mm), sz / SMALL_PAGE_SIZE); + tee_mm_free(mm); +} + +void spmc_handle_rxtx_map(struct thread_smc_args *args, struct ffa_rxtx *rxtx) +{ + int rc = 0; + uint32_t ret_fid = FFA_ERROR; + unsigned int sz = 0; + paddr_t rx_pa = 0; + paddr_t tx_pa = 0; + void *rx = NULL; + void *tx = NULL; + + cpu_spin_lock(&rxtx->spinlock); + + if (args->a3 & GENMASK_64(63, 6)) { + rc = FFA_INVALID_PARAMETERS; + goto out; + } + + sz = args->a3 * SMALL_PAGE_SIZE; + if (!sz) { + rc = FFA_INVALID_PARAMETERS; + goto out; + } + /* TX/RX are swapped compared to the caller */ + tx_pa = args->a2; + rx_pa = args->a1; + + if (rxtx->size) { + rc = FFA_DENIED; + goto out; + } + + /* + * If the buffer comes from a SP the address is virtual and already + * mapped. + */ + if (is_nw_buf(rxtx)) { + rc = map_buf(tx_pa, sz, &tx); + if (rc) + goto out; + rc = map_buf(rx_pa, sz, &rx); + if (rc) { + unmap_buf(tx, sz); + goto out; + } + rxtx->tx = tx; + rxtx->rx = rx; + } else { + if ((tx_pa & SMALL_PAGE_MASK) || (rx_pa & SMALL_PAGE_MASK)) { + rc = FFA_INVALID_PARAMETERS; + goto out; + } + + if (!virt_to_phys((void *)tx_pa) || + !virt_to_phys((void *)rx_pa)) { + rc = FFA_INVALID_PARAMETERS; + goto out; + } + + rxtx->tx = (void *)tx_pa; + rxtx->rx = (void *)rx_pa; + } + + rxtx->size = sz; + rxtx->tx_is_mine = true; + ret_fid = FFA_SUCCESS_32; + DMSG("Mapped tx %#"PRIxPA" size %#x @ %p", tx_pa, sz, tx); + DMSG("Mapped rx %#"PRIxPA" size %#x @ %p", rx_pa, sz, rx); +out: + cpu_spin_unlock(&rxtx->spinlock); + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +void spmc_handle_rxtx_unmap(struct thread_smc_args *args, struct ffa_rxtx *rxtx) +{ + uint32_t ret_fid = FFA_ERROR; + int rc = FFA_INVALID_PARAMETERS; + + cpu_spin_lock(&rxtx->spinlock); + + if (!rxtx->size) + goto out; + + /* We don't unmap the SP memory as the SP might still use it */ + if (is_nw_buf(rxtx)) { + unmap_buf(rxtx->rx, rxtx->size); + unmap_buf(rxtx->tx, rxtx->size); + } + rxtx->size = 0; + rxtx->rx = NULL; + rxtx->tx = NULL; + ret_fid = FFA_SUCCESS_32; + rc = 0; +out: + cpu_spin_unlock(&rxtx->spinlock); + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +void spmc_handle_rx_release(struct thread_smc_args *args, struct ffa_rxtx *rxtx) +{ + uint32_t ret_fid = 0; + int rc = 0; + + cpu_spin_lock(&rxtx->spinlock); + /* The senders RX is our TX */ + if (!rxtx->size || rxtx->tx_is_mine) { + ret_fid = FFA_ERROR; + rc = FFA_DENIED; + } else { + ret_fid = FFA_SUCCESS_32; + rc = 0; + rxtx->tx_is_mine = true; + } + cpu_spin_unlock(&rxtx->spinlock); + + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +static bool is_nil_uuid(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3) +{ + return !w0 && !w1 && !w2 && !w3; +} + +static bool is_my_uuid(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3) +{ + /* + * This depends on which UUID we have been assigned. + * TODO add a generic mechanism to obtain our UUID. + * + * The test below is for the hard coded UUID + * 486178e0-e7f8-11e3-bc5e-0002a5d5c51b + */ + return w0 == 0xe0786148 && w1 == 0xe311f8e7 && + w2 == 0x02005ebc && w3 == 0x1bc5d5a5; +} + +void spmc_fill_partition_entry(struct ffa_partition_info *fpi, + uint16_t endpoint_id, uint16_t execution_context) +{ + fpi->id = endpoint_id; + /* Number of execution contexts implemented by this partition */ + fpi->execution_context = execution_context; + + fpi->partition_properties = FFA_PARTITION_DIRECT_REQ_RECV_SUPPORT | + FFA_PARTITION_DIRECT_REQ_SEND_SUPPORT; +} + +static uint32_t handle_partition_info_get_all(size_t *elem_count, + struct ffa_rxtx *rxtx) +{ + struct ffa_partition_info *fpi = rxtx->tx; + + /* Add OP-TEE SP */ + spmc_fill_partition_entry(fpi, my_endpoint_id, CFG_TEE_CORE_NB_CORE); + rxtx->tx_is_mine = false; + *elem_count = 1; + fpi++; + + if (IS_ENABLED(CFG_SECURE_PARTITION)) { + size_t count = (rxtx->size / sizeof(*fpi)) - 1; + + if (sp_partition_info_get(fpi, NULL, &count)) + return FFA_NO_MEMORY; + *elem_count += count; + } + + return FFA_OK; +} + +void spmc_handle_partition_info_get(struct thread_smc_args *args, + struct ffa_rxtx *rxtx) +{ + uint32_t ret_fid = FFA_ERROR; + uint32_t rc = 0; + uint32_t endpoint_id = my_endpoint_id; + struct ffa_partition_info *fpi = NULL; + + cpu_spin_lock(&rxtx->spinlock); + + if (!rxtx->size || !rxtx->tx_is_mine) { + if (rxtx->size) + rc = FFA_BUSY; + else + rc = FFA_DENIED; /* TX buffer not setup yet */ + goto out; + } + + fpi = rxtx->tx; + + if (rxtx->size < sizeof(*fpi)) { + ret_fid = FFA_ERROR; + rc = FFA_NO_MEMORY; + goto out; + } + + if (is_nil_uuid(args->a1, args->a2, args->a3, args->a4)) { + size_t elem_count = 0; + + ret_fid = handle_partition_info_get_all(&elem_count, rxtx); + + if (ret_fid) { + rc = ret_fid; + ret_fid = FFA_ERROR; + } else { + ret_fid = FFA_SUCCESS_32; + rc = elem_count; + } + + goto out; + } + + if (is_my_uuid(args->a1, args->a2, args->a3, args->a4)) { + spmc_fill_partition_entry(fpi, endpoint_id, + CFG_TEE_CORE_NB_CORE); + rc = 1; + } else if (IS_ENABLED(CFG_SECURE_PARTITION)) { + uint32_t uuid_array[4] = { 0 }; + TEE_UUID uuid = { }; + TEE_Result res = TEE_SUCCESS; + size_t count = (rxtx->size / sizeof(*fpi)); + + uuid_array[0] = args->a1; + uuid_array[1] = args->a2; + uuid_array[2] = args->a3; + uuid_array[3] = args->a4; + tee_uuid_from_octets(&uuid, (uint8_t *)uuid_array); + + res = sp_partition_info_get(fpi, &uuid, &count); + if (res != TEE_SUCCESS) { + ret_fid = FFA_ERROR; + rc = FFA_INVALID_PARAMETERS; + goto out; + } + rc = count; + } else { + ret_fid = FFA_ERROR; + rc = FFA_INVALID_PARAMETERS; + goto out; + } + + ret_fid = FFA_SUCCESS_32; + rxtx->tx_is_mine = false; + +out: + spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); + cpu_spin_unlock(&rxtx->spinlock); +} +#endif /*CFG_CORE_SEL1_SPMC*/ + +static void handle_yielding_call(struct thread_smc_args *args) +{ + TEE_Result res = 0; + + thread_check_canaries(); + + if (args->a3 == OPTEE_FFA_YIELDING_CALL_RESUME) { + /* Note connection to struct thread_rpc_arg::ret */ + thread_resume_from_rpc(args->a7, args->a4, args->a5, args->a6, + 0); + res = TEE_ERROR_BAD_PARAMETERS; + } else { + thread_alloc_and_run(args->a1, args->a3, args->a4, args->a5, + args->a6, args->a7); + res = TEE_ERROR_BUSY; + } + spmc_set_args(args, FFA_MSG_SEND_DIRECT_RESP_32, + swap_src_dst(args->a1), 0, res, 0, 0); +} + +static uint32_t handle_unregister_shm(uint32_t a4, uint32_t a5) +{ + uint64_t cookie = reg_pair_to_64(a5, a4); + uint32_t res = 0; + + res = mobj_ffa_unregister_by_cookie(cookie); + switch (res) { + case TEE_SUCCESS: + case TEE_ERROR_ITEM_NOT_FOUND: + return 0; + case TEE_ERROR_BUSY: + EMSG("res %#"PRIx32, res); + return FFA_BUSY; + default: + EMSG("res %#"PRIx32, res); + return FFA_INVALID_PARAMETERS; + } +} + +static void handle_blocking_call(struct thread_smc_args *args) +{ + switch (args->a3) { + case OPTEE_FFA_GET_API_VERSION: + spmc_set_args(args, FFA_MSG_SEND_DIRECT_RESP_32, + swap_src_dst(args->a1), 0, + OPTEE_FFA_VERSION_MAJOR, OPTEE_FFA_VERSION_MINOR, + 0); + break; + case OPTEE_FFA_GET_OS_VERSION: + spmc_set_args(args, FFA_MSG_SEND_DIRECT_RESP_32, + swap_src_dst(args->a1), 0, + CFG_OPTEE_REVISION_MAJOR, + CFG_OPTEE_REVISION_MINOR, TEE_IMPL_GIT_SHA1); + break; + case OPTEE_FFA_EXCHANGE_CAPABILITIES: + spmc_set_args(args, FFA_MSG_SEND_DIRECT_RESP_32, + swap_src_dst(args->a1), 0, 0, + THREAD_RPC_MAX_NUM_PARAMS, + OPTEE_FFA_SEC_CAP_ARG_OFFSET); + break; + case OPTEE_FFA_UNREGISTER_SHM: + spmc_set_args(args, FFA_MSG_SEND_DIRECT_RESP_32, + swap_src_dst(args->a1), 0, + handle_unregister_shm(args->a4, args->a5), 0, 0); + break; + default: + EMSG("Unhandled blocking service ID %#"PRIx32, + (uint32_t)args->a3); + panic(); + } +} + +#if defined(CFG_CORE_SEL1_SPMC) +static int get_acc_perms(struct ffa_mem_access *mem_acc, + unsigned int num_mem_accs, uint8_t *acc_perms, + unsigned int *region_offs) +{ + unsigned int n = 0; + + for (n = 0; n < num_mem_accs; n++) { + struct ffa_mem_access_perm *descr = &mem_acc[n].access_perm; + + if (READ_ONCE(descr->endpoint_id) == my_endpoint_id) { + *acc_perms = READ_ONCE(descr->perm); + *region_offs = READ_ONCE(mem_acc[n].region_offs); + return 0; + } + } + + return FFA_INVALID_PARAMETERS; +} + +static int mem_share_init(void *buf, size_t blen, unsigned int *page_count, + unsigned int *region_count, size_t *addr_range_offs) +{ + const uint8_t exp_mem_reg_attr = FFA_NORMAL_MEM_REG_ATTR; + const uint8_t exp_mem_acc_perm = FFA_MEM_ACC_RW; + struct ffa_mem_region *region_descr = NULL; + struct ffa_mem_transaction *descr = NULL; + unsigned int num_mem_accs = 0; + uint8_t mem_acc_perm = 0; + unsigned int region_descr_offs = 0; + size_t n = 0; + + if (!IS_ALIGNED_WITH_TYPE(buf, struct ffa_mem_transaction) || + blen < sizeof(struct ffa_mem_transaction)) + return FFA_INVALID_PARAMETERS; + + descr = buf; + + /* Check that the endpoint memory access descriptor array fits */ + num_mem_accs = READ_ONCE(descr->mem_access_count); + if (MUL_OVERFLOW(sizeof(struct ffa_mem_access), num_mem_accs, &n) || + ADD_OVERFLOW(sizeof(*descr), n, &n) || n > blen) + return FFA_INVALID_PARAMETERS; + + if (READ_ONCE(descr->mem_reg_attr) != exp_mem_reg_attr) + return FFA_INVALID_PARAMETERS; + + /* Check that the access permissions matches what's expected */ + if (get_acc_perms(descr->mem_access_array, + num_mem_accs, &mem_acc_perm, ®ion_descr_offs) || + mem_acc_perm != exp_mem_acc_perm) + return FFA_INVALID_PARAMETERS; + + /* Check that the Composite memory region descriptor fits */ + if (ADD_OVERFLOW(region_descr_offs, sizeof(*region_descr), &n) || + n > blen) + return FFA_INVALID_PARAMETERS; + + if (!IS_ALIGNED_WITH_TYPE((vaddr_t)descr + region_descr_offs, + struct ffa_mem_region)) + return FFA_INVALID_PARAMETERS; + + region_descr = (struct ffa_mem_region *)((vaddr_t)descr + + region_descr_offs); + *page_count = READ_ONCE(region_descr->total_page_count); + *region_count = READ_ONCE(region_descr->address_range_count); + *addr_range_offs = n; + return 0; +} + +static int add_mem_share_helper(struct mem_share_state *s, void *buf, + size_t flen) +{ + unsigned int region_count = flen / sizeof(struct ffa_address_range); + struct ffa_address_range *arange = NULL; + unsigned int n = 0; + + if (region_count > s->region_count) + region_count = s->region_count; + + if (!IS_ALIGNED_WITH_TYPE(buf, struct ffa_address_range)) + return FFA_INVALID_PARAMETERS; + arange = buf; + + for (n = 0; n < region_count; n++) { + unsigned int page_count = READ_ONCE(arange[n].page_count); + uint64_t addr = READ_ONCE(arange[n].address); + + if (mobj_ffa_add_pages_at(s->mf, &s->current_page_idx, + addr, page_count)) + return FFA_INVALID_PARAMETERS; + } + + s->region_count -= region_count; + if (s->region_count) + return region_count * sizeof(*arange); + + if (s->current_page_idx != s->page_count) + return FFA_INVALID_PARAMETERS; + + return 0; +} + +static int add_mem_share_frag(struct mem_frag_state *s, void *buf, size_t flen) +{ + int rc = 0; + + rc = add_mem_share_helper(&s->share, buf, flen); + if (rc >= 0) { + if (!ADD_OVERFLOW(s->frag_offset, rc, &s->frag_offset)) { + /* We're not at the end of the descriptor yet */ + if (s->share.region_count) + return s->frag_offset; + + /* We're done */ + rc = 0; + } else { + rc = FFA_INVALID_PARAMETERS; + } + } + + SLIST_REMOVE(&frag_state_head, s, mem_frag_state, link); + if (rc < 0) + mobj_ffa_sel1_spmc_delete(s->share.mf); + else + mobj_ffa_push_to_inactive(s->share.mf); + free(s); + + return rc; +} + +static bool is_sp_share(void *buf) +{ + struct ffa_mem_transaction *input_descr = NULL; + struct ffa_mem_access_perm *perm = NULL; + + if (!IS_ENABLED(CFG_SECURE_PARTITION)) + return false; + + input_descr = buf; + perm = &input_descr->mem_access_array[0].access_perm; + + /* + * perm->endpoint_id is read here only to check if the endpoint is + * OP-TEE. We do read it later on again, but there are some additional + * checks there to make sure that the data is correct. + */ + return READ_ONCE(perm->endpoint_id) != my_endpoint_id; +} + +static int add_mem_share(tee_mm_entry_t *mm, void *buf, size_t blen, + size_t flen, uint64_t *global_handle) +{ + int rc = 0; + struct mem_share_state share = { }; + size_t addr_range_offs = 0; + size_t n = 0; + + if (flen > blen) + return FFA_INVALID_PARAMETERS; + + rc = mem_share_init(buf, flen, &share.page_count, &share.region_count, + &addr_range_offs); + if (rc) + return rc; + + if (MUL_OVERFLOW(share.region_count, + sizeof(struct ffa_address_range), &n) || + ADD_OVERFLOW(n, addr_range_offs, &n) || n > blen) + return FFA_INVALID_PARAMETERS; + + share.mf = mobj_ffa_sel1_spmc_new(share.page_count); + if (!share.mf) + return FFA_NO_MEMORY; + + if (flen != blen) { + struct mem_frag_state *s = calloc(sizeof(*s), 1); + + if (!s) { + rc = FFA_NO_MEMORY; + goto err; + } + s->share = share; + s->mm = mm; + s->frag_offset = addr_range_offs; + + SLIST_INSERT_HEAD(&frag_state_head, s, link); + rc = add_mem_share_frag(s, (char *)buf + addr_range_offs, + flen - addr_range_offs); + + if (rc >= 0) + *global_handle = mobj_ffa_get_cookie(share.mf); + + return rc; + } + + rc = add_mem_share_helper(&share, (char *)buf + addr_range_offs, + flen - addr_range_offs); + if (rc) { + /* + * Number of consumed bytes may be returned instead of 0 for + * done. + */ + rc = FFA_INVALID_PARAMETERS; + goto err; + } + + *global_handle = mobj_ffa_push_to_inactive(share.mf); + + return 0; +err: + mobj_ffa_sel1_spmc_delete(share.mf); + return rc; +} + +static int handle_mem_share_tmem(paddr_t pbuf, size_t blen, size_t flen, + unsigned int page_count, + uint64_t *global_handle, struct ffa_rxtx *rxtx) +{ + int rc = 0; + size_t len = 0; + tee_mm_entry_t *mm = NULL; + vaddr_t offs = pbuf & SMALL_PAGE_MASK; + + if (MUL_OVERFLOW(page_count, SMALL_PAGE_SIZE, &len)) + return FFA_INVALID_PARAMETERS; + if (!core_pbuf_is(CORE_MEM_NON_SEC, pbuf, len)) + return FFA_INVALID_PARAMETERS; + + /* + * Check that the length reported in blen is covered by len even + * if the offset is taken into account. + */ + if (len < blen || len - offs < blen) + return FFA_INVALID_PARAMETERS; + + mm = tee_mm_alloc(&tee_mm_shm, len); + if (!mm) + return FFA_NO_MEMORY; + + if (core_mmu_map_contiguous_pages(tee_mm_get_smem(mm), pbuf, + page_count, MEM_AREA_NSEC_SHM)) { + rc = FFA_INVALID_PARAMETERS; + goto out; + } + + cpu_spin_lock(&rxtx->spinlock); + rc = add_mem_share(mm, (void *)(tee_mm_get_smem(mm) + offs), blen, flen, + global_handle); + cpu_spin_unlock(&rxtx->spinlock); + if (rc > 0) + return rc; + + core_mmu_unmap_pages(tee_mm_get_smem(mm), page_count); +out: + tee_mm_free(mm); + return rc; +} + +static int handle_mem_share_rxbuf(size_t blen, size_t flen, + uint64_t *global_handle, + struct ffa_rxtx *rxtx) +{ + int rc = FFA_DENIED; + + cpu_spin_lock(&rxtx->spinlock); + + if (rxtx->rx && flen <= rxtx->size) { + if (is_sp_share(rxtx->rx)) { + rc = spmc_sp_add_share(rxtx, blen, + global_handle, NULL); + } else { + rc = add_mem_share(NULL, rxtx->rx, blen, flen, + global_handle); + } + } + + cpu_spin_unlock(&rxtx->spinlock); + + return rc; +} + +static void handle_mem_share(struct thread_smc_args *args, + struct ffa_rxtx *rxtx) +{ + uint32_t ret_w1 = 0; + uint32_t ret_w2 = FFA_INVALID_PARAMETERS; + uint32_t ret_w3 = 0; + uint32_t ret_fid = FFA_ERROR; + uint64_t global_handle = 0; + int rc = 0; + + /* Check that the MBZs are indeed 0 */ + if (args->a5 || args->a6 || args->a7) + goto out; + + if (!args->a3) { + /* + * The memory transaction descriptor is passed via our rx + * buffer. + */ + if (args->a4) + goto out; + rc = handle_mem_share_rxbuf(args->a1, args->a2, &global_handle, + rxtx); + } else { + rc = handle_mem_share_tmem(args->a3, args->a1, args->a2, + args->a4, &global_handle, rxtx); + } + if (rc < 0) { + ret_w2 = rc; + } else if (rc > 0) { + ret_fid = FFA_MEM_FRAG_RX; + ret_w3 = rc; + reg_pair_from_64(global_handle, &ret_w2, &ret_w1); + } else { + ret_fid = FFA_SUCCESS_32; + reg_pair_from_64(global_handle, &ret_w3, &ret_w2); + } +out: + spmc_set_args(args, ret_fid, ret_w1, ret_w2, ret_w3, 0, 0); +} + +static struct mem_frag_state *get_frag_state(uint64_t global_handle) +{ + struct mem_frag_state *s = NULL; + + SLIST_FOREACH(s, &frag_state_head, link) + if (mobj_ffa_get_cookie(s->share.mf) == global_handle) + return s; + + return NULL; +} + +static void handle_mem_frag_tx(struct thread_smc_args *args, + struct ffa_rxtx *rxtx) +{ + int rc = 0; + uint64_t global_handle = reg_pair_to_64(READ_ONCE(args->a2), + READ_ONCE(args->a1)); + size_t flen = READ_ONCE(args->a3); + struct mem_frag_state *s = NULL; + tee_mm_entry_t *mm = NULL; + unsigned int page_count = 0; + void *buf = NULL; + uint32_t ret_w1 = 0; + uint32_t ret_w2 = 0; + uint32_t ret_w3 = 0; + uint32_t ret_fid = 0; + + /* + * Currently we're only doing this for fragmented FFA_MEM_SHARE_* + * requests. + */ + + cpu_spin_lock(&rxtx->spinlock); + + s = get_frag_state(global_handle); + if (!s) { + rc = FFA_INVALID_PARAMETERS; + goto out; + } + + mm = s->mm; + if (mm) { + if (flen > tee_mm_get_bytes(mm)) { + rc = FFA_INVALID_PARAMETERS; + goto out; + } + page_count = s->share.page_count; + buf = (void *)tee_mm_get_smem(mm); + } else { + if (flen > rxtx->size) { + rc = FFA_INVALID_PARAMETERS; + goto out; + } + buf = rxtx->rx; + } + + rc = add_mem_share_frag(s, buf, flen); +out: + cpu_spin_unlock(&rxtx->spinlock); + + if (rc <= 0 && mm) { + core_mmu_unmap_pages(tee_mm_get_smem(mm), page_count); + tee_mm_free(mm); + } + + if (rc < 0) { + ret_fid = FFA_ERROR; + ret_w2 = rc; + } else if (rc > 0) { + ret_fid = FFA_MEM_FRAG_RX; + ret_w3 = rc; + reg_pair_from_64(global_handle, &ret_w2, &ret_w1); + } else { + ret_fid = FFA_SUCCESS_32; + reg_pair_from_64(global_handle, &ret_w3, &ret_w2); + } + + spmc_set_args(args, ret_fid, ret_w1, ret_w2, ret_w3, 0, 0); +} + +static void handle_mem_reclaim(struct thread_smc_args *args) +{ + uint32_t ret_val = FFA_INVALID_PARAMETERS; + uint32_t ret_fid = FFA_ERROR; + uint64_t cookie = 0; + + if (args->a3 || args->a4 || args->a5 || args->a6 || args->a7) + goto out; + + cookie = reg_pair_to_64(args->a2, args->a1); + switch (mobj_ffa_sel1_spmc_reclaim(cookie)) { + case TEE_SUCCESS: + ret_fid = FFA_SUCCESS_32; + ret_val = 0; + break; + case TEE_ERROR_ITEM_NOT_FOUND: + DMSG("cookie %#"PRIx64" not found", cookie); + ret_val = FFA_INVALID_PARAMETERS; + break; + default: + DMSG("cookie %#"PRIx64" busy", cookie); + ret_val = FFA_DENIED; + break; + } +out: + spmc_set_args(args, ret_fid, ret_val, 0, 0, 0, 0); +} +#endif + +/* Only called from assembly */ +void thread_spmc_msg_recv(struct thread_smc_args *args); +void thread_spmc_msg_recv(struct thread_smc_args *args) +{ + assert((thread_get_exceptions() & THREAD_EXCP_ALL) == THREAD_EXCP_ALL); + switch (args->a0) { +#if defined(CFG_CORE_SEL1_SPMC) + case FFA_VERSION: + spmc_handle_version(args); + break; + case FFA_FEATURES: + handle_features(args); + break; +#ifdef ARM64 + case FFA_RXTX_MAP_64: +#endif + case FFA_RXTX_MAP_32: + spmc_handle_rxtx_map(args, &nw_rxtx); + break; + case FFA_RXTX_UNMAP: + spmc_handle_rxtx_unmap(args, &nw_rxtx); + break; + case FFA_RX_RELEASE: + spmc_handle_rx_release(args, &nw_rxtx); + break; + case FFA_PARTITION_INFO_GET: + spmc_handle_partition_info_get(args, &nw_rxtx); + break; +#endif /*CFG_CORE_SEL1_SPMC*/ + case FFA_INTERRUPT: + itr_core_handler(); + spmc_set_args(args, FFA_MSG_WAIT, 0, 0, 0, 0, 0); + break; +#ifdef ARM64 + case FFA_MSG_SEND_DIRECT_REQ_64: +#endif + case FFA_MSG_SEND_DIRECT_REQ_32: + if (IS_ENABLED(CFG_SECURE_PARTITION) && + FFA_DST(args->a1) != my_endpoint_id) { + spmc_sp_start_thread(args); + break; + } + + if (args->a3 & BIT32(OPTEE_FFA_YIELDING_CALL_BIT)) + handle_yielding_call(args); + else + handle_blocking_call(args); + break; +#if defined(CFG_CORE_SEL1_SPMC) +#ifdef ARM64 + case FFA_MEM_SHARE_64: +#endif + case FFA_MEM_SHARE_32: + handle_mem_share(args, &nw_rxtx); + break; + case FFA_MEM_RECLAIM: + if (!IS_ENABLED(CFG_SECURE_PARTITION) || + !ffa_mem_reclaim(args, NULL)) + handle_mem_reclaim(args); + break; + case FFA_MEM_FRAG_TX: + handle_mem_frag_tx(args, &nw_rxtx); + break; +#endif /*CFG_CORE_SEL1_SPMC*/ + default: + EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0); + spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); + } +} + +static TEE_Result yielding_call_with_arg(uint64_t cookie, uint32_t offset) +{ + size_t sz_rpc = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); + struct thread_ctx *thr = threads + thread_get_id(); + TEE_Result res = TEE_ERROR_BAD_PARAMETERS; + struct optee_msg_arg *arg = NULL; + struct mobj *mobj = NULL; + uint32_t num_params = 0; + size_t sz = 0; + + mobj = mobj_ffa_get_by_cookie(cookie, 0); + if (!mobj) { + EMSG("Can't find cookie %#"PRIx64, cookie); + return TEE_ERROR_BAD_PARAMETERS; + } + + res = mobj_inc_map(mobj); + if (res) + goto out_put_mobj; + + res = TEE_ERROR_BAD_PARAMETERS; + arg = mobj_get_va(mobj, offset, sizeof(*arg)); + if (!arg) + goto out_dec_map; + + num_params = READ_ONCE(arg->num_params); + if (num_params > OPTEE_MSG_MAX_NUM_PARAMS) + goto out_dec_map; + + sz = OPTEE_MSG_GET_ARG_SIZE(num_params); + + thr->rpc_arg = mobj_get_va(mobj, offset + sz, sz_rpc); + if (!thr->rpc_arg) + goto out_dec_map; + + res = tee_entry_std(arg, num_params); + + thread_rpc_shm_cache_clear(&thr->shm_cache); + thr->rpc_arg = NULL; + +out_dec_map: + mobj_dec_map(mobj); +out_put_mobj: + mobj_put(mobj); + return res; +} + +/* + * Helper routine for the assembly function thread_std_smc_entry() + * + * Note: this function is weak just to make link_dummies_paged.c happy. + */ +uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5 __unused) +{ + /* + * Arguments are supplied from handle_yielding_call() as: + * a0 <- w1 + * a1 <- w3 + * a2 <- w4 + * a3 <- w5 + * a4 <- w6 + * a5 <- w7 + */ + thread_get_tsd()->rpc_target_info = swap_src_dst(a0); + if (a1 == OPTEE_FFA_YIELDING_CALL_WITH_ARG) + return yielding_call_with_arg(reg_pair_to_64(a3, a2), a4); + return FFA_DENIED; +} + +static bool set_fmem(struct optee_msg_param *param, struct thread_param *tpm) +{ + uint64_t offs = tpm->u.memref.offs; + + param->attr = tpm->attr - THREAD_PARAM_ATTR_MEMREF_IN + + OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; + + param->u.fmem.offs_low = offs; + param->u.fmem.offs_high = offs >> 32; + if (param->u.fmem.offs_high != offs >> 32) + return false; + + param->u.fmem.size = tpm->u.memref.size; + if (tpm->u.memref.mobj) { + uint64_t cookie = mobj_get_cookie(tpm->u.memref.mobj); + + /* If a mobj is passed it better be one with a valid cookie. */ + if (cookie == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) + return false; + param->u.fmem.global_id = cookie; + } else { + param->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; + } + + return true; +} + +static uint32_t get_rpc_arg(uint32_t cmd, size_t num_params, + struct thread_param *params, + struct optee_msg_arg **arg_ret) +{ + size_t sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); + struct thread_ctx *thr = threads + thread_get_id(); + struct optee_msg_arg *arg = thr->rpc_arg; + + if (num_params > THREAD_RPC_MAX_NUM_PARAMS) + return TEE_ERROR_BAD_PARAMETERS; + + if (!arg) { + EMSG("rpc_arg not set"); + return TEE_ERROR_GENERIC; + } + + memset(arg, 0, sz); + arg->cmd = cmd; + arg->num_params = num_params; + arg->ret = TEE_ERROR_GENERIC; /* in case value isn't updated */ + + for (size_t n = 0; n < num_params; n++) { + switch (params[n].attr) { + case THREAD_PARAM_ATTR_NONE: + arg->params[n].attr = OPTEE_MSG_ATTR_TYPE_NONE; + break; + case THREAD_PARAM_ATTR_VALUE_IN: + case THREAD_PARAM_ATTR_VALUE_OUT: + case THREAD_PARAM_ATTR_VALUE_INOUT: + arg->params[n].attr = params[n].attr - + THREAD_PARAM_ATTR_VALUE_IN + + OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + arg->params[n].u.value.a = params[n].u.value.a; + arg->params[n].u.value.b = params[n].u.value.b; + arg->params[n].u.value.c = params[n].u.value.c; + break; + case THREAD_PARAM_ATTR_MEMREF_IN: + case THREAD_PARAM_ATTR_MEMREF_OUT: + case THREAD_PARAM_ATTR_MEMREF_INOUT: + if (!set_fmem(arg->params + n, params + n)) + return TEE_ERROR_BAD_PARAMETERS; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + } + + if (arg_ret) + *arg_ret = arg; + + return TEE_SUCCESS; +} + +static uint32_t get_rpc_arg_res(struct optee_msg_arg *arg, size_t num_params, + struct thread_param *params) +{ + for (size_t n = 0; n < num_params; n++) { + switch (params[n].attr) { + case THREAD_PARAM_ATTR_VALUE_OUT: + case THREAD_PARAM_ATTR_VALUE_INOUT: + params[n].u.value.a = arg->params[n].u.value.a; + params[n].u.value.b = arg->params[n].u.value.b; + params[n].u.value.c = arg->params[n].u.value.c; + break; + case THREAD_PARAM_ATTR_MEMREF_OUT: + case THREAD_PARAM_ATTR_MEMREF_INOUT: + params[n].u.memref.size = arg->params[n].u.fmem.size; + break; + default: + break; + } + } + + return arg->ret; +} + +uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params, + struct thread_param *params) +{ + struct thread_rpc_arg rpc_arg = { .call = { + .w1 = thread_get_tsd()->rpc_target_info, + .w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD, + }, + }; + struct optee_msg_arg *arg = NULL; + uint32_t ret = 0; + + ret = get_rpc_arg(cmd, num_params, params, &arg); + if (ret) + return ret; + + thread_rpc(&rpc_arg); + + return get_rpc_arg_res(arg, num_params, params); +} + +static void thread_rpc_free(unsigned int bt, uint64_t cookie, struct mobj *mobj) +{ + struct thread_rpc_arg rpc_arg = { .call = { + .w1 = thread_get_tsd()->rpc_target_info, + .w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD, + }, + }; + struct thread_param param = THREAD_PARAM_VALUE(IN, bt, cookie, 0); + uint32_t res2 = 0; + uint32_t res = 0; + + DMSG("freeing cookie %#"PRIx64, cookie); + + res = get_rpc_arg(OPTEE_RPC_CMD_SHM_FREE, 1, ¶m, NULL); + + mobj_put(mobj); + res2 = mobj_ffa_unregister_by_cookie(cookie); + if (res2) + DMSG("mobj_ffa_unregister_by_cookie(%#"PRIx64"): %#"PRIx32, + cookie, res2); + if (!res) + thread_rpc(&rpc_arg); +} + +static struct mobj *thread_rpc_alloc(size_t size, size_t align, unsigned int bt) +{ + struct thread_rpc_arg rpc_arg = { .call = { + .w1 = thread_get_tsd()->rpc_target_info, + .w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD, + }, + }; + struct thread_param param = THREAD_PARAM_VALUE(IN, bt, size, align); + struct optee_msg_arg *arg = NULL; + unsigned int internal_offset = 0; + struct mobj *mobj = NULL; + uint64_t cookie = 0; + + if (get_rpc_arg(OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m, &arg)) + return NULL; + + thread_rpc(&rpc_arg); + + if (arg->num_params != 1 || + arg->params->attr != OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT) + return NULL; + + internal_offset = READ_ONCE(arg->params->u.fmem.internal_offs); + cookie = READ_ONCE(arg->params->u.fmem.global_id); + mobj = mobj_ffa_get_by_cookie(cookie, internal_offset); + if (!mobj) { + DMSG("mobj_ffa_get_by_cookie(%#"PRIx64", %#x): failed", + cookie, internal_offset); + return NULL; + } + + assert(mobj_is_nonsec(mobj)); + + if (mobj->size < size) { + DMSG("Mobj %#"PRIx64": wrong size", cookie); + mobj_put(mobj); + return NULL; + } + + if (mobj_inc_map(mobj)) { + DMSG("mobj_inc_map(%#"PRIx64"): failed", cookie); + mobj_put(mobj); + return NULL; + } + + return mobj; +} + +struct mobj *thread_rpc_alloc_payload(size_t size) +{ + return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_APPL); +} + +struct mobj *thread_rpc_alloc_kernel_payload(size_t size) +{ + return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL); +} + +void thread_rpc_free_kernel_payload(struct mobj *mobj) +{ + thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj); +} + +void thread_rpc_free_payload(struct mobj *mobj) +{ + thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), + mobj); +} + +struct mobj *thread_rpc_alloc_global_payload(size_t size) +{ + return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_GLOBAL); +} + +void thread_rpc_free_global_payload(struct mobj *mobj) +{ + thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, mobj_get_cookie(mobj), + mobj); +} + +void thread_spmc_register_secondary_ep(vaddr_t ep) +{ + unsigned long ret = 0; + + /* Let the SPM know the entry point for secondary CPUs */ + ret = thread_smc(FFA_SECONDARY_EP_REGISTER_64, ep, 0, 0); + + if (ret != FFA_SUCCESS_32 && ret != FFA_SUCCESS_64) + EMSG("FFA_SECONDARY_EP_REGISTER_64 ret %#lx", ret); +} + +#if defined(CFG_CORE_SEL1_SPMC) +static TEE_Result spmc_init(void) +{ + my_endpoint_id = SPMC_ENDPOINT_ID; + DMSG("My endpoint ID %#x", my_endpoint_id); + + return TEE_SUCCESS; +} +#else /* !defined(CFG_CORE_SEL1_SPMC) */ +static bool is_ffa_success(uint32_t fid) +{ +#ifdef ARM64 + if (fid == FFA_SUCCESS_64) + return true; +#endif + return fid == FFA_SUCCESS_32; +} + +static void spmc_rxtx_map(struct ffa_rxtx *rxtx) +{ + struct thread_smc_args args = { +#ifdef ARM64 + .a0 = FFA_RXTX_MAP_64, +#else + .a0 = FFA_RXTX_MAP_32, +#endif + .a1 = virt_to_phys(rxtx->tx), + .a2 = virt_to_phys(rxtx->rx), + .a3 = 1, + }; + + thread_smccc(&args); + if (!is_ffa_success(args.a0)) { + if (args.a0 == FFA_ERROR) + EMSG("rxtx map failed with error %ld", args.a2); + else + EMSG("rxtx map failed"); + panic(); + } +} + +static uint16_t spmc_get_id(void) +{ + struct thread_smc_args args = { + .a0 = FFA_ID_GET, + }; + + thread_smccc(&args); + if (!is_ffa_success(args.a0)) { + if (args.a0 == FFA_ERROR) + EMSG("Get id failed with error %ld", args.a2); + else + EMSG("Get id failed"); + panic(); + } + + return args.a2; +} + +static struct ffa_mem_transaction *spmc_retrieve_req(uint64_t cookie) +{ + struct ffa_mem_transaction *trans_descr = nw_rxtx.tx; + struct ffa_mem_access *acc_descr_array = NULL; + struct ffa_mem_access_perm *perm_descr = NULL; + size_t size = sizeof(*trans_descr) + + 1 * sizeof(struct ffa_mem_access); + struct thread_smc_args args = { + .a0 = FFA_MEM_RETRIEVE_REQ_32, + .a1 = size, /* Total Length */ + .a2 = size, /* Frag Length == Total length */ + .a3 = 0, /* Address, Using TX -> MBZ */ + .a4 = 0, /* Using TX -> MBZ */ + }; + + memset(trans_descr, 0, size); + trans_descr->sender_id = thread_get_tsd()->rpc_target_info; + trans_descr->mem_reg_attr = FFA_NORMAL_MEM_REG_ATTR; + trans_descr->global_handle = cookie; + trans_descr->flags = FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE | + FFA_MEMORY_REGION_FLAG_ANY_ALIGNMENT; + trans_descr->mem_access_count = 1; + acc_descr_array = trans_descr->mem_access_array; + acc_descr_array->region_offs = 0; + acc_descr_array->reserved = 0; + perm_descr = &acc_descr_array->access_perm; + perm_descr->endpoint_id = my_endpoint_id; + perm_descr->perm = FFA_MEM_ACC_RW; + perm_descr->flags = 0; + + thread_smccc(&args); + if (args.a0 != FFA_MEM_RETRIEVE_RESP) { + if (args.a0 == FFA_ERROR) + EMSG("Failed to fetch cookie %#"PRIx64" error code %d", + cookie, (int)args.a2); + else + EMSG("Failed to fetch cookie %#"PRIx64" a0 %#"PRIx64, + cookie, args.a0); + return NULL; + } + + return nw_rxtx.rx; +} + +void thread_spmc_relinquish(uint64_t cookie) +{ + struct ffa_mem_relinquish *relinquish_desc = nw_rxtx.tx; + struct thread_smc_args args = { + .a0 = FFA_MEM_RELINQUISH, + }; + + memset(relinquish_desc, 0, sizeof(*relinquish_desc)); + relinquish_desc->handle = cookie; + relinquish_desc->flags = 0; + relinquish_desc->endpoint_count = 1; + relinquish_desc->endpoint_id_array[0] = my_endpoint_id; + thread_smccc(&args); + if (!is_ffa_success(args.a0)) + EMSG("Failed to relinquish cookie %#"PRIx64, cookie); +} + +static int set_pages(struct ffa_address_range *regions, + unsigned int num_regions, unsigned int num_pages, + struct mobj_ffa *mf) +{ + unsigned int n = 0; + unsigned int idx = 0; + + for (n = 0; n < num_regions; n++) { + unsigned int page_count = READ_ONCE(regions[n].page_count); + uint64_t addr = READ_ONCE(regions[n].address); + + if (mobj_ffa_add_pages_at(mf, &idx, addr, page_count)) + return FFA_INVALID_PARAMETERS; + } + + if (idx != num_pages) + return FFA_INVALID_PARAMETERS; + + return 0; +} + +struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie) +{ + struct mobj_ffa *ret = NULL; + struct ffa_mem_transaction *retrieve_desc = NULL; + struct ffa_mem_access *descr_array = NULL; + struct ffa_mem_region *descr = NULL; + struct mobj_ffa *mf = NULL; + unsigned int num_pages = 0; + unsigned int offs = 0; + struct thread_smc_args ffa_rx_release_args = { + .a0 = FFA_RX_RELEASE + }; + + /* + * OP-TEE is only supporting a single mem_region while the + * specification allows for more than one. + */ + retrieve_desc = spmc_retrieve_req(cookie); + if (!retrieve_desc) { + EMSG("Failed to retrieve cookie from rx buffer %#"PRIx64, + cookie); + return NULL; + } + + descr_array = retrieve_desc->mem_access_array; + offs = READ_ONCE(descr_array->region_offs); + descr = (struct ffa_mem_region *)((vaddr_t)retrieve_desc + offs); + + num_pages = READ_ONCE(descr->total_page_count); + mf = mobj_ffa_spmc_new(cookie, num_pages); + if (!mf) + goto out; + + if (set_pages(descr->address_range_array, + READ_ONCE(descr->address_range_count), num_pages, mf)) { + mobj_ffa_spmc_delete(mf); + goto out; + } + + ret = mf; + +out: + /* Release RX buffer after the mem retrieve request. */ + thread_smccc(&ffa_rx_release_args); + + return ret; +} + +static TEE_Result spmc_init(void) +{ + spmc_rxtx_map(&nw_rxtx); + my_endpoint_id = spmc_get_id(); + DMSG("My endpoint ID %#x", my_endpoint_id); + + return TEE_SUCCESS; +} +#endif /* !defined(CFG_CORE_SEL1_SPMC) */ + +service_init(spmc_init); diff --git a/optee/optee_os/core/arch/arm/kernel/thread_spmc_a32.S b/optee/optee_os/core/arch/arm/kernel/thread_spmc_a32.S new file mode 100644 index 0000000..7a8d9da --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_spmc_a32.S @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Linaro Limited + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +FUNC thread_ffa_msg_wait , : + mov_imm r0, FFA_MSG_WAIT /* FID */ + mov r1, #FFA_TARGET_INFO_MBZ /* Target info MBZ */ + mov r2, #FFA_PARAM_MBZ /* Param MBZ */ + mov r3, #FFA_PARAM_MBZ /* Param MBZ */ + mov r4, #FFA_PARAM_MBZ /* Param MBZ */ + mov r5, #FFA_PARAM_MBZ /* Param MBZ */ + mov r6, #FFA_PARAM_MBZ /* Param MBZ */ + mov r7, #FFA_PARAM_MBZ /* Param MBZ */ + b .ffa_msg_loop +END_FUNC thread_ffa_msg_wait + + /* Caller provides r1, r3-r7 params */ +LOCAL_FUNC ffa_msg_send_direct_resp , : + ldr r0, =FFA_MSG_SEND_DIRECT_RESP_32 /* FID */ + mov r2, #FFA_PARAM_MBZ /* RES MBZ */ + +.ffa_msg_loop: + /* Invoke SMC with caller provided parameters */ + smc #0 + + /* Store the parameters as struct thread_smc_args on stack */ + push {r0-r7} + mov r0, sp + + /* parse and handle message */ + bl thread_spmc_msg_recv + + /* Load struct thread_smc_args into registers */ + pop {r0-r7} + b .ffa_msg_loop +END_FUNC ffa_msg_send_direct_resp + +FUNC thread_std_smc_entry , : +UNWIND( .cantunwind) + + push {r4, r5} /* Pass these following the arm32 calling convention */ + ror r4, r0, #16 /* Save target info with src and dst swapped */ + bl __thread_std_smc_entry + add sp, sp, #8 /* There's nothing return, just restore the sp */ + mov r5, r0 /* Save return value */ + + /* Mask all maskable exceptions before switching to temporary stack */ + cpsid aif + bl thread_get_tmp_sp + mov sp, r0 + + bl thread_state_free + + mov r1, r4 /* Target info */ + mov r3, r5 /* Return value */ + mov r4, #FFA_PARAM_MBZ /* Unused parameter */ + mov r5, #FFA_PARAM_MBZ /* Unused parameter */ + mov r6, #FFA_PARAM_MBZ /* Unused parameter */ + mov r7, #FFA_PARAM_MBZ /* Unused parameter */ + b ffa_msg_send_direct_resp +END_FUNC thread_std_smc_entry + +/* void thread_rpc(struct thread_rpc_arg *rpc_arg) */ +FUNC thread_rpc , : + push {r0, lr} +UNWIND( .save {r0, lr}) + + 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 r8, [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 r7, r0 /* Supply thread index */ + ldr r0, =FFA_MSG_SEND_DIRECT_RESP_32 + mov r2, #FFA_PARAM_MBZ + mov r3, #0 /* Error code = 0 */ + ldm r8, {r1, r4-r6} /* Load rv[] into r1,r4-r6 */ + b ffa_msg_send_direct_resp + +.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, lr} /* Get pointer to rv[] */ + stm r12, {r0-r3} /* Store r0-r3 into rv[] */ + bx lr +END_FUNC thread_rpc + +/* + * void thread_foreign_intr_exit(uint32_t thread_index) + * + * This function is jumped to at the end of macro foreign_intr_handler(). + * The current thread as indicated by @thread_index has just been + * suspended. The job here is just to inform normal world the thread id to + * resume when returning. + */ +FUNC thread_foreign_intr_exit , : + /* load threads[r0].tsd.rpc_target_info into r1 */ + mov r1, #THREAD_CTX_SIZE + ldr r2, =threads + mla r1, r1, r0, r2 + ldr r1, [r1, #THREAD_CTX_TSD_RPC_TARGET_INFO] + mov r2, #FFA_PARAM_MBZ + mov r3, #FFA_PARAM_MBZ + mov r4, #OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT + mov r5, #FFA_PARAM_MBZ + mov r6, #FFA_PARAM_MBZ + mov r7, r0 + b ffa_msg_send_direct_resp +END_FUNC thread_foreign_intr_exit diff --git a/optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S b/optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S new file mode 100644 index 0000000..21cb625 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/thread_spmc_a64.S @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Linaro Limited + * Copyright (c) 2019-2021, Arm Limited + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +FUNC thread_ffa_msg_wait , : + mov_imm x0, FFA_MSG_WAIT /* FID */ + mov x1, #FFA_TARGET_INFO_MBZ /* Target info MBZ */ + mov x2, #FFA_PARAM_MBZ /* Param MBZ */ + mov x3, #FFA_PARAM_MBZ /* Param MBZ */ + mov x4, #FFA_PARAM_MBZ /* Param MBZ */ + mov x5, #FFA_PARAM_MBZ /* Param MBZ */ + mov x6, #FFA_PARAM_MBZ /* Param MBZ */ + mov x7, #FFA_PARAM_MBZ /* Param MBZ */ + b .ffa_msg_loop +END_FUNC thread_ffa_msg_wait + + /* Caller provides x1, x3-x7 params */ +LOCAL_FUNC ffa_msg_send_direct_resp , : + mov_imm x0, FFA_MSG_SEND_DIRECT_RESP_32 /* FID */ + mov x2, #FFA_PARAM_MBZ /* RES MBZ */ + +.ffa_msg_loop: + /* Invoke SMC with caller provided parameters */ + smc #0 + + /* Store the parameters as struct thread_smc_args on stack */ + sub sp, sp, #THREAD_SMC_ARGS_SIZE + store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 + mov x0, sp + + /* parse and handle message */ + bl thread_spmc_msg_recv + + /* Load struct thread_smc_args into registers */ + load_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 + add sp, sp, #THREAD_SMC_ARGS_SIZE + b .ffa_msg_loop +END_FUNC ffa_msg_send_direct_resp + +FUNC thread_std_smc_entry , : + ror w19, w0, #16 /* Save target info with src and dst swapped */ + bl __thread_std_smc_entry + mov w20, w0 /* Save return value */ + + /* Mask all maskable exceptions before switching to temporary stack */ + msr daifset, #DAIFBIT_ALL + bl thread_get_tmp_sp + mov sp, x0 + + bl thread_state_free + + mov w1, w19 /* Target info */ + mov w3, w20 /* Return value */ + mov x4, #FFA_PARAM_MBZ /* Unused parameter */ + mov x5, #FFA_PARAM_MBZ /* Unused parameter */ + mov x6, #FFA_PARAM_MBZ /* Unused parameter */ + mov x7, #FFA_PARAM_MBZ /* Unused parameter */ + b ffa_msg_send_direct_resp +END_FUNC thread_std_smc_entry + +#ifdef CFG_SECURE_PARTITION +/* void spmc_sp_thread_entry(args) */ +FUNC spmc_sp_thread_entry , : + /* Store the parameters as struct thread_smc_args on stack */ + sub sp, sp, #THREAD_SMC_ARGS_SIZE + store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 + mov x0, sp + mov x1, #0 /* Pass NULL pointer for caller_sp, coming from NW */ + bl spmc_sp_msg_handler + load_xregs sp, THREAD_SMC_ARGS_X0, 20, 27 + + /* Mask all maskable exceptions before switching to temporary stack */ + msr daifset, #DAIFBIT_ALL + bl thread_get_tmp_sp + mov sp, x0 + + bl thread_state_free + + /* Restore the FF-A arguments before the SMC instruction. */ + mov w0, w20 + mov w1, w21 + mov w2, w22 + mov w3, w23 + mov w4, w24 + mov w5, w25 + mov w6, w26 + mov w7, w27 + b .ffa_msg_loop +END_FUNC spmc_sp_thread_entry +#endif + +/* void thread_rpc(struct thread_rpc_arg *rpc_arg) */ +FUNC thread_rpc , : + /* Read daif and create an SPSR */ + mrs x1, daif + orr x1, x1, #(SPSR_64_MODE_EL1 << SPSR_64_MODE_EL_SHIFT) + + /* Mask all maskable exceptions before switching to temporary stack */ + msr daifset, #DAIFBIT_ALL + push x0, xzr + push x1, x30 + bl thread_get_ctx_regs + ldr x30, [sp, #8] + store_xregs x0, THREAD_CTX_REGS_X19, 19, 30 + mov x19, x0 + +#if defined(CFG_CORE_PAUTH) + /* Save APIAKEY */ + read_apiakeyhi x1 + read_apiakeylo x2 + store_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 +#endif + + bl thread_get_tmp_sp + pop x1, xzr /* Match "push x1, x30" above */ + mov x2, sp + str x2, [x19, #THREAD_CTX_REGS_SP] + ldr x20, [sp] /* Get pointer to rpc_arg[] */ + mov sp, x0 /* Switch to tmp stack */ + /* + * We need to read rpc_arg[] early, because thread_state_suspend + * can invoke virt_unset_guest() which will unmap pages, + * where rpc_arg[] resides + */ + load_wregs x20, 0, 21, 24 /* Load rpc_arg[] into w21-w24 */ + + adr x2, .thread_rpc_return + mov w0, #THREAD_FLAGS_COPY_ARGS_ON_RETURN + bl thread_state_suspend + mov w7, w0 /* Supply thread index */ + ldr w0, =FFA_MSG_SEND_DIRECT_RESP_32 + mov w1, w21 + mov w2, #FFA_PARAM_MBZ + mov w3, #0 /* Error code = 0 */ + mov w4, w22 + mov w5, w23 + mov w6, w24 + b ffa_msg_send_direct_resp + +.thread_rpc_return: + /* + * At this point has the stack pointer been restored to the value + * stored in THREAD_CTX 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. w0-w3 holds the values supplied + * to thread_resume_from_rpc() in a0-a3. + */ + pop x16, xzr /* Get pointer to rv[] */ + store_wregs x16, 0, 0, 3 /* Store w0-w3 into rv[] */ + ret +END_FUNC thread_rpc + +/* + * void thread_foreign_intr_exit(uint32_t thread_index) + * + * This function is jumped to at the end of macro foreign_intr_handler(). + * The current thread as indicated by @thread_index has just been + * suspended. The job here is just to inform normal world the thread id to + * resume when returning. + */ +FUNC thread_foreign_intr_exit , : + /* load threads[w0].tsd.rpc_target_info into w1 */ + mov x1, #THREAD_CTX_SIZE + adr_l x2, threads + madd x1, x1, x0, x2 + ldr w1, [x1, #THREAD_CTX_TSD_RPC_TARGET_INFO] + mov x2, #FFA_PARAM_MBZ + mov w3, #FFA_PARAM_MBZ + mov w4, #OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT + mov x5, #FFA_PARAM_MBZ + mov w6, #FFA_PARAM_MBZ + mov w7, w0 + b ffa_msg_send_direct_resp +END_FUNC thread_foreign_intr_exit + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/timer_a64.c b/optee/optee_os/core/arch/arm/kernel/timer_a64.c new file mode 100644 index 0000000..d64a997 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/timer_a64.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include + +static unsigned int timer_lock = SPINLOCK_UNLOCK; +static bool timer_running; + +void generic_timer_start(uint32_t time_ms) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + uint32_t timer_ticks; + + cpu_spin_lock(&timer_lock); + + if (timer_running == true) + goto exit; + + /* The timer will fire time_ms from now */ + timer_ticks = (read_cntfrq() * time_ms) / 1000; + write_cntps_tval(timer_ticks); + + /* Enable the secure physical timer */ + write_cntps_ctl(1); + + timer_running = true; + +exit: + cpu_spin_unlock(&timer_lock); + thread_set_exceptions(exceptions); +} + +void generic_timer_stop(void) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + cpu_spin_lock(&timer_lock); + + /* Disable the timer */ + write_cntps_ctl(0); + + timer_running = false; + + cpu_spin_unlock(&timer_lock); + thread_set_exceptions(exceptions); +} + +void generic_timer_handler(uint32_t time_ms) +{ + uint32_t timer_ticks; + + /* Ensure that the timer did assert the interrupt */ + assert((read_cntps_ctl() >> 2)); + + /* Disable the timer */ + write_cntps_ctl(0); + + /* Reconfigure timer to fire time_ms from now */ + timer_ticks = (read_cntfrq() * time_ms) / 1000; + write_cntps_tval(timer_ticks); + + /* Enable the secure physical timer */ + write_cntps_ctl(1); +} diff --git a/optee/optee_os/core/arch/arm/kernel/tlb_helpers_a32.S b/optee/optee_os/core/arch/arm/kernel/tlb_helpers_a32.S new file mode 100644 index 0000000..e65384c --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/tlb_helpers_a32.S @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include + +/* void tlbi_all(void); */ +FUNC tlbi_all , : + dsb ishst /* Sync with table update */ + write_tlbiallis /* Invalidate TLBs */ + dsb ish /* Sync with tlb invalidation completion */ + isb /* Sync execution on tlb update */ + bx lr +END_FUNC tlbi_all + +/* void tlbi_mva_allasid(vaddr_t mva); */ +FUNC tlbi_mva_allasid , : + dsb ishst /* Sync with table update */ + write_tlbimvaais r0 /* Inval TLB by MVA all ASID Inner Sharable */ + dsb ish /* Sync with tlb invalidation completion */ + isb /* Sync execution on tlb update */ + bx lr +END_FUNC tlbi_mva_allasid + +/* void tlbi_asid(unsigned long asid); */ +FUNC tlbi_asid , : + dsb ishst /* Sync with table update */ + write_tlbiasidis r0 /* Inval unified TLB by ASID Inner Sharable */ + orr r0, r0, #1 /* Select the kernel ASID */ + write_tlbiasidis r0 /* Inval unified TLB by ASID Inner Sharable */ + dsb ish /* Sync with tlb invalidation completion */ + isb /* Sync execution on tlb update */ + bx lr +END_FUNC tlbi_asid diff --git a/optee/optee_os/core/arch/arm/kernel/tlb_helpers_a64.S b/optee/optee_os/core/arch/arm/kernel/tlb_helpers_a64.S new file mode 100644 index 0000000..9be1e68 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/tlb_helpers_a64.S @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2017, Linaro Limited + */ + +#include +#include +#include + +/* void tlbi_all(void); */ +FUNC tlbi_all , : + dsb ishst /* Sync with table update */ + tlbi vmalle1is /* All tlb in inner shareable */ + dsb ish /* Sync with tlb invalidation completion */ + isb /* Sync execution on tlb update */ + ret +END_FUNC tlbi_all + +/* void tlbi_mva_allasid(vaddr_t mva); */ +FUNC tlbi_mva_allasid , : + lsr x0, x0, #TLBI_MVA_SHIFT + dsb ishst /* Sync with table update */ + tlbi vaae1is, x0 /* Invalidate tlb by mva in inner shareable */ + dsb ish /* Sync with tlb invalidation completion */ + isb /* Sync execution on tlb update */ + ret +END_FUNC tlbi_mva_allasid + +/* void tlbi_asid(unsigned int asid); */ +FUNC tlbi_asid , : + lsl x0, x0, #TLBI_ASID_SHIFT + dsb ishst /* Sync with table update */ + tlbi aside1is, x0 /* Invalidate tlb by asid in inner shareable */ + orr x0, x0, #BIT(TLBI_ASID_SHIFT) /* Select the kernel ASID */ + tlbi aside1is, x0 /* Invalidate tlb by asid in inner shareable */ + dsb ish /* Sync with tlb invalidation completion */ + isb /* Sync execution on tlb update */ + ret +END_FUNC tlbi_asid + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S b/optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S new file mode 100644 index 0000000..b3f85cc --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/tz_ssvce_pl310_a32.S @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include + +#define PL310_LOCKDOWN_NBREGS 8 +#define PL310_LOCKDOWN_SZREG 4 + +#define PL310_8WAYS_MASK 0x00FF +#define PL310_16WAYS_UPPERMASK 0xFF00 + +/* + * void arm_cl2_lockallways(vaddr_t base) + * + * lock all L2 caches ways for data and instruction + */ +FUNC arm_cl2_lockallways , : + add r1, r0, #PL310_DCACHE_LOCKDOWN_BASE + ldr r2, [r0, #PL310_AUX_CTRL] + tst r2, #PL310_AUX_16WAY_BIT + mov r2, #PL310_8WAYS_MASK + orrne r2, #PL310_16WAYS_UPPERMASK + mov r0, #PL310_LOCKDOWN_NBREGS +1: /* lock Dcache and Icache */ + str r2, [r1], #PL310_LOCKDOWN_SZREG + str r2, [r1], #PL310_LOCKDOWN_SZREG + subs r0, r0, #1 + bne 1b + + mov pc, lr +END_FUNC arm_cl2_lockallways + +/* + * Set sync operation mask according to ways associativity. + * Preserve r0 = pl310 iomem base address + */ +.macro syncbyway_set_mask reg + ldr \reg, [r0, #PL310_AUX_CTRL] + tst \reg, #PL310_AUX_16WAY_BIT + mov \reg, #PL310_8WAYS_MASK + orrne \reg, \reg, #PL310_16WAYS_UPPERMASK +.endm + +/* + * void arm_cl2_cleaninvbyway(vaddr_t base) + * clean & invalidate the whole L2 cache. + */ +FUNC arm_cl2_cleaninvbyway , : + + syncbyway_set_mask r1 + str r1, [r0, #PL310_FLUSH_BY_WAY] + + /* Wait for all cache ways to be cleaned and invalidated */ +loop_cli_way_done: + ldr r2, [r0, #PL310_FLUSH_BY_WAY] + and r2, r2, r1 + cmp r2, #0 + bne loop_cli_way_done + + /* Cache Sync */ + + /* + * Wait for writing cache sync + * To PL310, Cache sync is atomic opertion, no need to check + * the status. For PL220, this check is needed. Keeping the loop + * for PL310 is no harm for PL310. + */ +loop_cli_sync: + ldr r1, [r0, #PL310_SYNC] + cmp r1, #0 + bne loop_cli_sync + + mov r1, #0 + str r1, [r0, #PL310_SYNC] + +loop_cli_sync_done: + ldr r1, [r0, #PL310_SYNC] + cmp r1, #0 + bne loop_cli_sync_done + + mov pc, lr +END_FUNC arm_cl2_cleaninvbyway + +/* void arm_cl2_invbyway(vaddr_t base) */ +FUNC arm_cl2_invbyway , : + + syncbyway_set_mask r1 + str r1, [r0, #PL310_INV_BY_WAY] + +loop_inv_way_done: + ldr r2, [r0, #PL310_INV_BY_WAY] + and r2, r2, r1 + cmp r2, #0 + bne loop_inv_way_done + +loop_inv_way_sync: + ldr r1, [r0, #PL310_SYNC] + cmp r1, #0 + bne loop_inv_way_sync + + mov r1, #0 + str r1, [r0, #PL310_SYNC] + +loop_inv_way_sync_done: + ldr r1, [r0, #PL310_SYNC] + cmp r1, #0 + bne loop_inv_way_sync_done + + mov pc, lr +END_FUNC arm_cl2_invbyway + +/* void arm_cl2_cleanbyway(vaddr_t base) */ +FUNC arm_cl2_cleanbyway , : + + syncbyway_set_mask r1 + str r1, [r0, #PL310_CLEAN_BY_WAY] + +loop_cl_way_done: + ldr r2, [r0, #PL310_CLEAN_BY_WAY] + and r2, r2, r1 + cmp r2, #0 + bne loop_cl_way_done + +loop_cl_way_sync: + ldr r1, [r0, #PL310_SYNC] + cmp r1, #0 + bne loop_cl_way_sync + + mov r1, #0 + str r1, [r0, #PL310_SYNC] + +loop_cl_way_sync_done: + ldr r1, [r0, #PL310_SYNC] + cmp r1, #0 + bne loop_cl_way_sync_done + + mov pc, lr +END_FUNC arm_cl2_cleanbyway + +/* + * void _arm_cl2_xxxbypa(vaddr_t pl310_base, paddr_t start, paddr_t end, + * int pl310value); + * pl310value is one of PL310_CLEAN_BY_PA, PL310_INV_BY_PA or PL310_FLUSH_BY_PA + */ +LOCAL_FUNC _arm_cl2_xxxbypa , : + /* Align start address on PL310 line size */ + and r1, #(~(PL310_LINE_SIZE - 1)) +#ifdef SCU_BASE + /* + * ARM ERRATA #764369 + * Undocummented SCU Diagnostic Control Register + */ + /* + * NOTE: + * We're assuming that if mmu is enabled PL310_BASE and SCU_BASE + * still have the same relative offsets from each other. + */ + sub r0, r0, #(PL310_BASE - SCU_BASE) + mov r12, #1 + str r12, [r0, #SCU_ERRATA744369] + dsb + add r0, r0, #(PL310_BASE - SCU_BASE) +#endif +loop_cl2_xxxbypa: + str r1, [r0, r3] + +loop_xxx_pa_done: + ldr r12, [r0, r3] + and r12, r12, r1 + cmp r12, #0 + bne loop_xxx_pa_done + + add r1, r1, #PL310_LINE_SIZE + cmp r2, r1 + bpl loop_cl2_xxxbypa + +loop_xxx_pa_sync: + ldr r12, [r0, #PL310_SYNC] + cmp r12, #0 + bne loop_xxx_pa_sync + + mov r12, #0 + str r12, [r0, #PL310_SYNC] + +loop_xxx_pa_sync_done: + ldr r12, [r0, #PL310_SYNC] + cmp r12, #0 + bne loop_xxx_pa_sync_done + + mov pc, lr +END_FUNC _arm_cl2_xxxbypa + +/* + * void _arm_cl2_cleanbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); + * clean L2 cache by physical address range. + */ +FUNC arm_cl2_cleanbypa , : + mov r3, #PL310_CLEAN_BY_PA + b _arm_cl2_xxxbypa +END_FUNC arm_cl2_cleanbypa + +/* + * void arm_cl2_invbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); + * invalidate L2 cache by physical address range. + */ +FUNC arm_cl2_invbypa , : + mov r3, #PL310_INV_BY_PA + b _arm_cl2_xxxbypa +END_FUNC arm_cl2_invbypa + +/* + * void arm_cl2_cleaninvbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); + * clean and invalidate L2 cache by physical address range. + */ +FUNC arm_cl2_cleaninvbypa , : + mov r3, #PL310_FLUSH_BY_PA + b _arm_cl2_xxxbypa +END_FUNC arm_cl2_cleaninvbypa + diff --git a/optee/optee_os/core/arch/arm/kernel/unwind_arm32.c b/optee/optee_os/core/arch/arm/kernel/unwind_arm32.c new file mode 100644 index 0000000..6dcdb6e --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/unwind_arm32.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2015 Linaro Limited + * Copyright 2013-2014 Andrew Turner. + * Copyright 2013-2014 Ian Lepore. + * Copyright 2013-2014 Rui Paulo. + * Copyright 2013 Eitan Adler. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 "unwind_private.h" + +/* The register names */ +#define FP 11 +#define SP 13 +#define LR 14 +#define PC 15 + +bool find_exidx(vaddr_t addr __unused, vaddr_t *idx_start, vaddr_t *idx_end) +{ + *idx_start = (vaddr_t)__exidx_start; + *idx_end = (vaddr_t)__exidx_end; + return true; +} + +vaddr_t *unw_get_kernel_stack(void) +{ + size_t n = 0; + size_t size = 0; + size_t exidx_sz = 0; + vaddr_t *tmp = NULL; + vaddr_t *addr = NULL; + struct unwind_state_arm32 state = { }; + vaddr_t stack = thread_stack_start(); + size_t stack_size = thread_stack_size(); + + if (SUB_OVERFLOW((vaddr_t)__exidx_end, (vaddr_t)__exidx_start, + &exidx_sz)) + return NULL; + + /* r7: Thumb-style frame pointer */ + state.registers[7] = read_r7(); + /* r11: ARM-style frame pointer */ + state.registers[FP] = read_fp(); + state.registers[SP] = read_sp(); + state.registers[LR] = read_lr(); + + /* + * Add 4 to make sure that we have an address well inside this function. + * This is needed because we're subtracting 2 from PC when calling + * find_index() above. See a comment there for more details. + */ + state.registers[PC] = (uint32_t)unw_get_kernel_stack + 4; + + while (unwind_stack_arm32(&state, stack, stack_size)) { + tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t)); + if (!tmp) + goto err; + addr = tmp; + addr[n] = state.registers[PC]; + n++; + } + + if (addr) { + tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t)); + if (!tmp) + goto err; + addr = tmp; + addr[n] = 0; + } + + return addr; +err: + EMSG("Out of memory"); + return NULL; +} + +#if (TRACE_LEVEL > 0) +void print_kernel_stack(void) +{ + struct unwind_state_arm32 state = { }; + vaddr_t stack_start = 0; + vaddr_t stack_end = 0; + + /* r7: Thumb-style frame pointer */ + state.registers[7] = read_r7(); + /* r11: ARM-style frame pointer */ + state.registers[FP] = read_fp(); + state.registers[SP] = read_sp(); + state.registers[LR] = read_lr(); + + /* + * Add 4 to make sure that we have an address well inside this function. + * This is needed because we're subtracting 2 from PC when calling + * find_index() above. See a comment there for more details. + */ + state.registers[PC] = (uint32_t)print_kernel_stack + 4; + + trace_printf_helper_raw(TRACE_ERROR, true, + "TEE load address @ %#"PRIxVA, VCORE_START_VA); + get_stack_hard_limits(&stack_start, &stack_end); + print_stack_arm32(&state, stack_start, stack_end - stack_start); +} +#endif diff --git a/optee/optee_os/core/arch/arm/kernel/unwind_arm64.c b/optee/optee_os/core/arch/arm/kernel/unwind_arm64.c new file mode 100644 index 0000000..7d994d7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/unwind_arm64.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-2-Clause +/*- + * Copyright (c) 2015 Linaro Limited + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under + * the sponsorship of the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 "unwind_private.h" + +#if defined(CFG_CORE_PAUTH) +void pauth_strip_pac(uint64_t *lr) +{ + const uint64_t va_mask = GENMASK_64(CFG_LPAE_ADDR_SPACE_BITS - 1, 0); + + *lr = *lr & va_mask; +} +#endif + +vaddr_t *unw_get_kernel_stack(void) +{ + size_t n = 0; + size_t size = 0; + vaddr_t *tmp = NULL; + vaddr_t *addr = NULL; + uaddr_t stack = thread_stack_start(); + size_t stack_size = thread_stack_size(); + struct unwind_state_arm64 state = { + .pc = read_pc(), + .fp = read_fp() + }; + + while (unwind_stack_arm64(&state, stack, stack_size)) { + tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t)); + if (!tmp) + goto err; + addr = tmp; + addr[n] = state.pc; + n++; + } + + if (addr) { + tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t)); + if (!tmp) + goto err; + addr = tmp; + addr[n] = 0; + } + + return addr; +err: + EMSG("Out of memory"); + free(addr); + return NULL; +} + +#if defined(CFG_UNWIND) && (TRACE_LEVEL > 0) +void print_kernel_stack(void) +{ + struct unwind_state_arm64 state = { }; + vaddr_t stack_start = 0; + vaddr_t stack_end = 0; + + state.pc = read_pc(); + state.fp = read_fp(); + + trace_printf_helper_raw(TRACE_ERROR, true, + "TEE load address @ %#"PRIxVA, VCORE_START_VA); + get_stack_hard_limits(&stack_start, &stack_end); + print_stack_arm64(&state, stack_start, stack_end - stack_start); +} +#endif diff --git a/optee/optee_os/core/arch/arm/kernel/unwind_private.h b/optee/optee_os/core/arch/arm/kernel/unwind_private.h new file mode 100644 index 0000000..df6f2ff --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/unwind_private.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ +#include +#include +#include + +static inline void *unw_grow(void *p, size_t *cur_size, size_t new_size) +{ + size_t rounded_size = 0; + void *tmp = NULL; + + if (*cur_size >= new_size) + return p; + + rounded_size = ROUNDUP(new_size, 16 * sizeof(vaddr_t)); + tmp = realloc(p, rounded_size); + + if (tmp) + *cur_size = rounded_size; + return tmp; +} diff --git a/optee/optee_os/core/arch/arm/kernel/vfp.c b/optee/optee_os/core/arch/arm/kernel/vfp.c new file mode 100644 index 0000000..8e945bf --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/vfp.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include +#include "vfp_private.h" + +#ifdef ARM32 +bool vfp_is_enabled(void) +{ + return !!(vfp_read_fpexc() & FPEXC_EN); +} + +void vfp_enable(void) +{ + vfp_write_fpexc(vfp_read_fpexc() | FPEXC_EN); +} + +void vfp_disable(void) +{ + vfp_write_fpexc(vfp_read_fpexc() & ~FPEXC_EN); +} + +void vfp_lazy_save_state_init(struct vfp_state *state) +{ + uint32_t fpexc = vfp_read_fpexc(); + + state->fpexc = fpexc; + vfp_write_fpexc(fpexc & ~FPEXC_EN); +} + +void vfp_lazy_save_state_final(struct vfp_state *state, bool force_save) +{ + if ((state->fpexc & FPEXC_EN) || force_save) { + uint32_t fpexc = vfp_read_fpexc(); + + assert(!(fpexc & FPEXC_EN)); + vfp_write_fpexc(fpexc | FPEXC_EN); + state->fpscr = vfp_read_fpscr(); + vfp_save_extension_regs(state->reg); + vfp_write_fpexc(fpexc); + } +} + +void vfp_lazy_restore_state(struct vfp_state *state, bool full_state) +{ + + if (full_state) { + /* + * Only restore VFP registers if they have been touched as they + * otherwise are intact. + */ + + /* FPEXC is restored to what's in state->fpexc below */ + vfp_write_fpexc(vfp_read_fpexc() | FPEXC_EN); + + vfp_write_fpscr(state->fpscr); + vfp_restore_extension_regs(state->reg); + } + vfp_write_fpexc(state->fpexc); +} +#endif /* ARM32 */ + +#ifdef ARM64 +bool vfp_is_enabled(void) +{ + return (CPACR_EL1_FPEN(read_cpacr_el1()) & CPACR_EL1_FPEN_EL0EL1); +} + +void vfp_enable(void) +{ + uint32_t val = read_cpacr_el1(); + + val |= (CPACR_EL1_FPEN_EL0EL1 << CPACR_EL1_FPEN_SHIFT); + write_cpacr_el1(val); + isb(); +} + +void vfp_disable(void) +{ + uint32_t val = read_cpacr_el1(); + + val &= ~(CPACR_EL1_FPEN_MASK << CPACR_EL1_FPEN_SHIFT); + write_cpacr_el1(val); + isb(); +} + +void vfp_lazy_save_state_init(struct vfp_state *state) +{ + state->cpacr_el1 = read_cpacr_el1(); + vfp_disable(); +} + +void vfp_lazy_save_state_final(struct vfp_state *state, bool force_save) +{ + if ((CPACR_EL1_FPEN(state->cpacr_el1) & CPACR_EL1_FPEN_EL0EL1) || + force_save) { + assert(!vfp_is_enabled()); + vfp_enable(); + state->fpcr = read_fpcr(); + state->fpsr = read_fpsr(); + vfp_save_extension_regs(state->reg); + vfp_disable(); + } +} + +void vfp_lazy_restore_state(struct vfp_state *state, bool full_state) +{ + if (full_state) { + /* + * Only restore VFP registers if they have been touched as they + * otherwise are intact. + */ + + /* CPACR_EL1 is restored to what's in state->cpacr_el1 below */ + vfp_enable(); + write_fpcr(state->fpcr); + write_fpsr(state->fpsr); + vfp_restore_extension_regs(state->reg); + } + write_cpacr_el1(state->cpacr_el1); + isb(); +} +#endif /* ARM64 */ diff --git a/optee/optee_os/core/arch/arm/kernel/vfp_a32.S b/optee/optee_os/core/arch/arm/kernel/vfp_a32.S new file mode 100644 index 0000000..c435de1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/vfp_a32.S @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2016, Linaro Limited + */ + +#include +#include +#include + + .fpu neon + +/* void vfp_save_extension_regs(uint64_t regs[VFP_NUM_REGS]); */ +FUNC vfp_save_extension_regs , : + vstm r0!, {d0-d15} + read_cpacr r1 + tst r1, #CPACR_D32DIS + bxne lr + vstm r0, {d16-d31} + bx lr +END_FUNC vfp_save_extension_regs + +/* void vfp_restore_extension_regs(uint64_t regs[VFP_NUM_REGS]); */ +FUNC vfp_restore_extension_regs , : + vldm r0!, {d0-d15} + read_cpacr r1 + tst r1, #CPACR_D32DIS + bxne lr + vldm r0, {d16-d31} + bx lr +END_FUNC vfp_restore_extension_regs + +/* void vfp_write_fpexc(uint32_t fpexc) */ +FUNC vfp_write_fpexc , : + vmsr fpexc, r0 + bx lr +END_FUNC vfp_write_fpexc + +/* uint32_t vfp_read_fpexc(void) */ +FUNC vfp_read_fpexc , : + vmrs r0, fpexc + bx lr +END_FUNC vfp_read_fpexc + +/* void vfp_write_fpscr(uint32_t fpscr) */ +FUNC vfp_write_fpscr , : + vmsr fpscr, r0 + bx lr +END_FUNC vfp_write_fpscr + +/* uint32_t vfp_read_fpscr(void) */ +FUNC vfp_read_fpscr , : + vmrs r0, fpscr + bx lr +END_FUNC vfp_read_fpscr diff --git a/optee/optee_os/core/arch/arm/kernel/vfp_a64.S b/optee/optee_os/core/arch/arm/kernel/vfp_a64.S new file mode 100644 index 0000000..a7322cc --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/vfp_a64.S @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include + +/* void vfp_save_extension_regs(struct vfp_reg regs[VFP_NUM_REGS]); */ +FUNC vfp_save_extension_regs , : + stp q0, q1, [x0, #16 * 0] + stp q2, q3, [x0, #16 * 2] + stp q4, q5, [x0, #16 * 4] + stp q6, q7, [x0, #16 * 6] + stp q8, q9, [x0, #16 * 8] + stp q10, q11, [x0, #16 * 10] + stp q12, q13, [x0, #16 * 12] + stp q14, q15, [x0, #16 * 14] + stp q16, q17, [x0, #16 * 16] + stp q18, q19, [x0, #16 * 18] + stp q20, q21, [x0, #16 * 20] + stp q22, q23, [x0, #16 * 22] + stp q24, q25, [x0, #16 * 24] + stp q26, q27, [x0, #16 * 26] + stp q28, q29, [x0, #16 * 28] + stp q30, q31, [x0, #16 * 30] + ret +END_FUNC vfp_save_extension_regs + +/* void vfp_restore_extension_regs(struct vfp_reg regs[VFP_NUM_REGS]); */ +FUNC vfp_restore_extension_regs , : + ldp q0, q1, [x0, #16 * 0] + ldp q2, q3, [x0, #16 * 2] + ldp q4, q5, [x0, #16 * 4] + ldp q6, q7, [x0, #16 * 6] + ldp q8, q9, [x0, #16 * 8] + ldp q10, q11, [x0, #16 * 10] + ldp q12, q13, [x0, #16 * 12] + ldp q14, q15, [x0, #16 * 14] + ldp q16, q17, [x0, #16 * 16] + ldp q18, q19, [x0, #16 * 18] + ldp q20, q21, [x0, #16 * 20] + ldp q22, q23, [x0, #16 * 22] + ldp q24, q25, [x0, #16 * 24] + ldp q26, q27, [x0, #16 * 26] + ldp q28, q29, [x0, #16 * 28] + ldp q30, q31, [x0, #16 * 30] + ret +END_FUNC vfp_restore_extension_regs + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/core/arch/arm/kernel/vfp_private.h b/optee/optee_os/core/arch/arm/kernel/vfp_private.h new file mode 100644 index 0000000..6fac336 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/vfp_private.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef VFP_PRIVATE +#define VFP_PRIVATE + +#include + +void vfp_save_extension_regs(struct vfp_reg regs[VFP_NUM_REGS]); +void vfp_restore_extension_regs(struct vfp_reg regs[VFP_NUM_REGS]); +void vfp_clear_extension_regs(void); + +#ifdef ARM32 + +#define FPEXC_EN (1 << 30) + +/* + * These functions can't be implemented in inline assembly when compiling + * for thumb mode, to make it easy always implement then in ARM assembly as + * ordinary functions. + */ +void vfp_write_fpexc(uint32_t fpexc); +uint32_t vfp_read_fpexc(void); +void vfp_write_fpscr(uint32_t fpscr); +uint32_t vfp_read_fpscr(void); + +#endif /* ARM32 */ + +#endif /*VFP_PRIVATE*/ diff --git a/optee/optee_os/core/arch/arm/kernel/virtualization.c b/optee/optee_os/core/arch/arm/kernel/virtualization.c new file mode 100644 index 0000000..da7fdc6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/kernel/virtualization.c @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* Copyright (c) 2018, EPAM Systems. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int prtn_list_lock __nex_data = SPINLOCK_UNLOCK; + +static LIST_HEAD(prtn_list_head, guest_partition) prtn_list __nex_data = + LIST_HEAD_INITIALIZER(prtn_list_head); + +/* Free pages used for guest partitions */ +tee_mm_pool_t virt_mapper_pool __nex_bss; + +/* Memory used by OP-TEE core */ +struct tee_mmap_region *kmemory_map __nex_bss; + +struct guest_partition { + LIST_ENTRY(guest_partition) link; + struct mmu_partition *mmu_prtn; + struct tee_mmap_region *memory_map; + struct mutex mutex; + void *tables_va; + tee_mm_entry_t *tee_ram; + tee_mm_entry_t *ta_ram; + tee_mm_entry_t *tables; + bool runtime_initialized; + uint16_t id; + struct refcount refc; +}; + +struct guest_partition *current_partition[CFG_TEE_CORE_NB_CORE] __nex_bss; + +static struct guest_partition *get_current_prtn(void) +{ + struct guest_partition *ret; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + + ret = current_partition[get_core_pos()]; + + thread_unmask_exceptions(exceptions); + + return ret; +} + +static void set_current_prtn(struct guest_partition *prtn) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + + current_partition[get_core_pos()] = prtn; + + thread_unmask_exceptions(exceptions); +} + +static size_t get_ta_ram_size(void) +{ + size_t ta_size = 0; + + core_mmu_get_ta_range(NULL, &ta_size); + return ROUNDDOWN(ta_size / CFG_VIRT_GUEST_COUNT - VCORE_UNPG_RW_SZ - + core_mmu_get_total_pages_size(), SMALL_PAGE_SIZE); +} + +static struct tee_mmap_region *prepare_memory_map(paddr_t tee_data, + paddr_t ta_ram) +{ + int i, entries; + vaddr_t max_va = 0; + struct tee_mmap_region *map; + /* + * This function assumes that at time of operation, + * kmemory_map (aka static_memory_map from core_mmu.c) + * will not be altered. This is true, because all + * changes to static_memory_map are done during + * OP-TEE initialization, while this function will + * called when hypervisor creates a guest. + */ + + /* Count number of entries in nexus memory map */ + for (map = kmemory_map, entries = 1; map->type != MEM_AREA_END; + map++, entries++) + ; + + /* Allocate entries for virtual guest map */ + map = nex_calloc(entries + 1, sizeof(struct tee_mmap_region)); + if (!map) + return NULL; + + memcpy(map, kmemory_map, sizeof(*map) * entries); + + /* Map TEE .data and .bss sections */ + for (i = 0; i < entries; i++) { + if (map[i].va == (vaddr_t)(VCORE_UNPG_RW_PA)) { + map[i].type = MEM_AREA_TEE_RAM_RW; + map[i].attr = core_mmu_type_to_attr(map[i].type); + map[i].pa = tee_data; + } + if (map[i].va + map[i].size > max_va) + max_va = map[i].va + map[i].size; + } + + /* Map TA_RAM */ + assert(map[entries - 1].type == MEM_AREA_END); + map[entries] = map[entries - 1]; + map[entries - 1].region_size = SMALL_PAGE_SIZE; + map[entries - 1].va = ROUNDUP(max_va, map[entries - 1].region_size); + map[entries - 1].va += + (ta_ram - map[entries - 1].va) & CORE_MMU_PGDIR_MASK; + map[entries - 1].pa = ta_ram; + map[entries - 1].size = get_ta_ram_size(); + map[entries - 1].type = MEM_AREA_TA_RAM; + map[entries - 1].attr = core_mmu_type_to_attr(map[entries - 1].type); + + DMSG("New map (%08lx):", (vaddr_t)(VCORE_UNPG_RW_PA)); + + for (i = 0; i < entries; i++) + DMSG("T: %-16s rsz: %08x, pa: %08lx, va: %08lx, sz: %08lx attr: %x", + teecore_memtype_name(map[i].type), + map[i].region_size, map[i].pa, map[i].va, + map[i].size, map[i].attr); + return map; +} + +void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base, + paddr_size_t secmem0_size, paddr_t secmem1_base, + paddr_size_t secmem1_size) +{ + struct tee_mmap_region *map = NULL; + paddr_size_t size = secmem0_size; + paddr_t base = secmem0_base; + + if (secmem1_size) { + assert(secmem0_base + secmem0_size <= secmem1_base); + size = secmem1_base + secmem1_size - base; + } + + /* Init page pool that covers all secure RAM */ + if (!tee_mm_init(&virt_mapper_pool, base, size, + SMALL_PAGE_SHIFT, TEE_MM_POOL_NEX_MALLOC)) + panic("Can't create pool with free pages"); + DMSG("Created virtual mapper pool from %"PRIxPA" to %"PRIxPA, + base, base + size); + + if (secmem1_size) { + /* Carve out an eventual gap between secmem0 and secmem1 */ + base = secmem0_base + secmem0_size; + size = secmem1_base - base; + if (size) { + DMSG("Carving out gap between secmem0 and secmem1 (0x%"PRIxPA":0x%"PRIxPASZ")", + base, size); + if (!tee_mm_alloc2(&virt_mapper_pool, base, size)) + panic("Can't carve out secmem gap"); + } + } + + + /* Carve out areas that are used by OP-TEE core */ + for (map = memory_map; map->type != MEM_AREA_END; map++) { + switch (map->type) { + case MEM_AREA_TEE_RAM_RX: + case MEM_AREA_TEE_RAM_RO: + case MEM_AREA_NEX_RAM_RO: + case MEM_AREA_NEX_RAM_RW: + DMSG("Carving out area of type %d (0x%08lx-0x%08lx)", + map->type, map->pa, map->pa + map->size); + if (!tee_mm_alloc2(&virt_mapper_pool, map->pa, + map->size)) + panic("Can't carve out used area"); + break; + default: + continue; + } + } + + kmemory_map = memory_map; +} + + +static TEE_Result configure_guest_prtn_mem(struct guest_partition *prtn) +{ + TEE_Result res = TEE_SUCCESS; + paddr_t original_data_pa = 0; + + prtn->tee_ram = tee_mm_alloc(&virt_mapper_pool, VCORE_UNPG_RW_SZ); + if (!prtn->tee_ram) { + EMSG("Can't allocate memory for TEE runtime context"); + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + DMSG("TEE RAM: %08" PRIxPA, tee_mm_get_smem(prtn->tee_ram)); + + prtn->ta_ram = tee_mm_alloc(&virt_mapper_pool, get_ta_ram_size()); + if (!prtn->ta_ram) { + EMSG("Can't allocate memory for TA data"); + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + DMSG("TA RAM: %08" PRIxPA, tee_mm_get_smem(prtn->ta_ram)); + + prtn->tables = tee_mm_alloc(&virt_mapper_pool, + core_mmu_get_total_pages_size()); + if (!prtn->tables) { + EMSG("Can't allocate memory for page tables"); + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + prtn->tables_va = phys_to_virt(tee_mm_get_smem(prtn->tables), + MEM_AREA_SEC_RAM_OVERALL, + core_mmu_get_total_pages_size()); + assert(prtn->tables_va); + + prtn->mmu_prtn = core_alloc_mmu_prtn(prtn->tables_va); + if (!prtn->mmu_prtn) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + prtn->memory_map = prepare_memory_map(tee_mm_get_smem(prtn->tee_ram), + tee_mm_get_smem(prtn->ta_ram)); + if (!prtn->memory_map) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + core_init_mmu_prtn(prtn->mmu_prtn, prtn->memory_map); + + original_data_pa = virt_to_phys(__data_start); + /* Switch to guest's mappings */ + core_mmu_set_prtn(prtn->mmu_prtn); + + /* clear .bss */ + memset((void *)(VCORE_UNPG_RW_PA), 0, VCORE_UNPG_RW_SZ); + + /* copy .data section from R/O original */ + memcpy(__data_start, + phys_to_virt(original_data_pa, MEM_AREA_SEC_RAM_OVERALL, + __data_end - __data_start), + __data_end - __data_start); + + return TEE_SUCCESS; + +err: + if (prtn->tee_ram) + tee_mm_free(prtn->tee_ram); + if (prtn->ta_ram) + tee_mm_free(prtn->ta_ram); + if (prtn->tables) + tee_mm_free(prtn->tables); + nex_free(prtn->mmu_prtn); + nex_free(prtn->memory_map); + + return res; +} + +TEE_Result virt_guest_created(uint16_t guest_id) +{ + struct guest_partition *prtn = NULL; + TEE_Result res = TEE_SUCCESS; + uint32_t exceptions = 0; + + prtn = nex_calloc(1, sizeof(*prtn)); + if (!prtn) + return TEE_ERROR_OUT_OF_MEMORY; + + prtn->id = guest_id; + mutex_init(&prtn->mutex); + refcount_set(&prtn->refc, 1); + res = configure_guest_prtn_mem(prtn); + if (res) { + nex_free(prtn); + return res; + } + + set_current_prtn(prtn); + + /* Initialize threads */ + thread_init_threads(); + /* Do the preinitcalls */ + call_preinitcalls(); + + exceptions = cpu_spin_lock_xsave(&prtn_list_lock); + LIST_INSERT_HEAD(&prtn_list, prtn, link); + cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); + + IMSG("Added guest %d", guest_id); + + set_current_prtn(NULL); + core_mmu_set_default_prtn(); + + return TEE_SUCCESS; +} + +TEE_Result virt_guest_destroyed(uint16_t guest_id) +{ + struct guest_partition *prtn; + uint32_t exceptions; + + IMSG("Removing guest %d", guest_id); + + exceptions = cpu_spin_lock_xsave(&prtn_list_lock); + + LIST_FOREACH(prtn, &prtn_list, link) { + if (prtn->id == guest_id) { + LIST_REMOVE(prtn, link); + break; + } + } + cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); + + if (prtn) { + if (!refcount_dec(&prtn->refc)) { + EMSG("Guest thread(s) is still running. refc = %d", + refcount_val(&prtn->refc)); + panic(); + } + + tee_mm_free(prtn->tee_ram); + tee_mm_free(prtn->ta_ram); + tee_mm_free(prtn->tables); + core_free_mmu_prtn(prtn->mmu_prtn); + nex_free(prtn->memory_map); + nex_free(prtn); + } else + EMSG("Client with id %d is not found", guest_id); + + return TEE_SUCCESS; +} + +TEE_Result virt_set_guest(uint16_t guest_id) +{ + struct guest_partition *prtn; + uint32_t exceptions; + + prtn = get_current_prtn(); + + /* This can be true only if we return from IRQ RPC */ + if (prtn && prtn->id == guest_id) + return TEE_SUCCESS; + + if (prtn) + panic("Virtual guest partition is already set"); + + exceptions = cpu_spin_lock_xsave(&prtn_list_lock); + LIST_FOREACH(prtn, &prtn_list, link) { + if (prtn->id == guest_id) { + set_current_prtn(prtn); + core_mmu_set_prtn(prtn->mmu_prtn); + refcount_inc(&prtn->refc); + cpu_spin_unlock_xrestore(&prtn_list_lock, + exceptions); + return TEE_SUCCESS; + } + } + cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); + + if (guest_id == HYP_CLNT_ID) + return TEE_SUCCESS; + return TEE_ERROR_ITEM_NOT_FOUND; +} + +void virt_unset_guest(void) +{ + struct guest_partition *prtn = get_current_prtn(); + + if (!prtn) + return; + + set_current_prtn(NULL); + core_mmu_set_default_prtn(); + if (refcount_dec(&prtn->refc)) + panic(); +} + +void virt_on_stdcall(void) +{ + struct guest_partition *prtn = get_current_prtn(); + + /* Initialize runtime on first std call */ + if (!prtn->runtime_initialized) { + mutex_lock(&prtn->mutex); + if (!prtn->runtime_initialized) { + init_tee_runtime(); + prtn->runtime_initialized = true; + } + mutex_unlock(&prtn->mutex); + } +} + +struct tee_mmap_region *virt_get_memory_map(void) +{ + struct guest_partition *prtn; + + prtn = get_current_prtn(); + + if (!prtn) + return NULL; + + return prtn->memory_map; +} + +void virt_get_ta_ram(vaddr_t *start, vaddr_t *end) +{ + struct guest_partition *prtn = get_current_prtn(); + + *start = (vaddr_t)phys_to_virt(tee_mm_get_smem(prtn->ta_ram), + MEM_AREA_TA_RAM, + tee_mm_get_bytes(prtn->ta_ram)); + *end = *start + tee_mm_get_bytes(prtn->ta_ram); +} diff --git a/optee/optee_os/core/arch/arm/mm/core_mmu.c b/optee/optee_os/core/arch/arm/mm/core_mmu.c new file mode 100644 index 0000000..e39ed31 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/core_mmu.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Two ASIDs per context, one for kernel mode and one for user mode. ASID 0 + * and 1 are reserved and not used. This means a maximum of 126 loaded user + * mode contexts. This value can be increased but not beyond the maximum + * ASID, which is architecture dependent (max 255 for ARMv7-A and ARMv8-A + * Aarch32). This constant defines number of ASID pairs. + */ +#define MMU_NUM_ASID_PAIRS 64 + +static bitstr_t bit_decl(g_asid, MMU_NUM_ASID_PAIRS) __nex_bss; +static unsigned int g_asid_spinlock __nex_bss = SPINLOCK_UNLOCK; + +void tlbi_mva_range(vaddr_t va, size_t len, size_t granule) +{ + assert(granule == CORE_MMU_PGDIR_SIZE || granule == SMALL_PAGE_SIZE); + assert(!(va & (granule - 1)) && !(len & (granule - 1))); + + dsb_ishst(); + while (len) { + tlbi_mva_allasid_nosync(va); + len -= granule; + va += granule; + } + dsb_ish(); + isb(); +} + +void tlbi_mva_range_asid(vaddr_t va, size_t len, size_t granule, uint32_t asid) +{ + assert(granule == CORE_MMU_PGDIR_SIZE || granule == SMALL_PAGE_SIZE); + assert(!(va & (granule - 1)) && !(len & (granule - 1))); + + dsb_ishst(); + while (len) { + tlbi_mva_asid_nosync(va, asid); + len -= granule; + va += granule; + } + dsb_ish(); + isb(); +} + +TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len) +{ + switch (op) { + case DCACHE_CLEAN: + dcache_op_all(DCACHE_OP_CLEAN); + break; + case DCACHE_AREA_CLEAN: + dcache_clean_range(va, len); + break; + case DCACHE_INVALIDATE: + dcache_op_all(DCACHE_OP_INV); + break; + case DCACHE_AREA_INVALIDATE: + dcache_inv_range(va, len); + break; + case ICACHE_INVALIDATE: + icache_inv_all(); + break; + case ICACHE_AREA_INVALIDATE: + icache_inv_range(va, len); + break; + case DCACHE_CLEAN_INV: + dcache_op_all(DCACHE_OP_CLEAN_INV); + break; + case DCACHE_AREA_CLEAN_INV: + dcache_cleaninv_range(va, len); + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + return TEE_SUCCESS; +} + +#ifdef CFG_PL310 +TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + + tee_l2cc_mutex_lock(); + switch (op) { + case DCACHE_INVALIDATE: + arm_cl2_invbyway(pl310_base()); + break; + case DCACHE_AREA_INVALIDATE: + if (len) + arm_cl2_invbypa(pl310_base(), pa, pa + len - 1); + break; + case DCACHE_CLEAN: + arm_cl2_cleanbyway(pl310_base()); + break; + case DCACHE_AREA_CLEAN: + if (len) + arm_cl2_cleanbypa(pl310_base(), pa, pa + len - 1); + break; + case DCACHE_CLEAN_INV: + arm_cl2_cleaninvbyway(pl310_base()); + break; + case DCACHE_AREA_CLEAN_INV: + if (len) + arm_cl2_cleaninvbypa(pl310_base(), pa, pa + len - 1); + break; + default: + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + tee_l2cc_mutex_unlock(); + thread_set_exceptions(exceptions); + return ret; +} +#endif /*CFG_PL310*/ + +unsigned int asid_alloc(void) +{ + uint32_t exceptions = cpu_spin_lock_xsave(&g_asid_spinlock); + unsigned int r; + int i; + + bit_ffc(g_asid, MMU_NUM_ASID_PAIRS, &i); + if (i == -1) { + r = 0; + } else { + bit_set(g_asid, i); + r = (i + 1) * 2; + } + + cpu_spin_unlock_xrestore(&g_asid_spinlock, exceptions); + return r; +} + +void asid_free(unsigned int asid) +{ + uint32_t exceptions = cpu_spin_lock_xsave(&g_asid_spinlock); + + /* Only even ASIDs are supposed to be allocated */ + assert(!(asid & 1)); + + if (asid) { + int i = (asid - 1) / 2; + + assert(i < MMU_NUM_ASID_PAIRS && bit_test(g_asid, i)); + bit_clear(g_asid, i); + } + + cpu_spin_unlock_xrestore(&g_asid_spinlock, exceptions); +} + +bool arch_va2pa_helper(void *va, paddr_t *pa) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + paddr_t par = 0; + paddr_t par_pa_mask = 0; + bool ret = false; + +#ifdef ARM32 + write_ats1cpr((vaddr_t)va); + isb(); +#ifdef CFG_WITH_LPAE + par = read_par64(); + par_pa_mask = PAR64_PA_MASK; +#else + par = read_par32(); + par_pa_mask = PAR32_PA_MASK; +#endif +#endif /*ARM32*/ + +#ifdef ARM64 + write_at_s1e1r((vaddr_t)va); + isb(); + par = read_par_el1(); + par_pa_mask = PAR_PA_MASK; +#endif + if (par & PAR_F) + goto out; + *pa = (par & (par_pa_mask << PAR_PA_SHIFT)) | + ((vaddr_t)va & (BIT64(PAR_PA_SHIFT) - 1)); + + ret = true; +out: + thread_unmask_exceptions(exceptions); + return ret; +} + +bool cpu_mmu_enabled(void) +{ + uint32_t sctlr; + +#ifdef ARM32 + sctlr = read_sctlr(); +#else + sctlr = read_sctlr_el1(); +#endif + + return sctlr & SCTLR_M ? true : false; +} diff --git a/optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c b/optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c new file mode 100644 index 0000000..6a5db89 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/core_mmu_lpae.c @@ -0,0 +1,1354 @@ +// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) +/* + * Copyright (c) 2015-2016, 2022 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. + */ + +/* + * Copyright (c) 2014, 2022, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM 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. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef DEBUG_XLAT_TABLE +#define DEBUG_XLAT_TABLE 0 +#endif + +#if DEBUG_XLAT_TABLE +#define debug_print(...) DMSG_RAW(__VA_ARGS__) +#else +#define debug_print(...) ((void)0) +#endif + + +/* + * Miscellaneous MMU related constants + */ + +#define INVALID_DESC 0x0 +#define BLOCK_DESC 0x1 +#define L3_BLOCK_DESC 0x3 +#define TABLE_DESC 0x3 +#define DESC_ENTRY_TYPE_MASK 0x3 + +#define XN (1ull << 2) +#define PXN (1ull << 1) +#define CONT_HINT (1ull << 0) + +#define UPPER_ATTRS(x) (((x) & 0x7) << 52) +#define GP BIT64(50) /* Guarded Page, Aarch64 FEAT_BTI */ +#define NON_GLOBAL (1ull << 9) +#define ACCESS_FLAG (1ull << 8) +#define NSH (0x0 << 6) +#define OSH (0x2 << 6) +#define ISH (0x3 << 6) + +#define AP_RO (0x1 << 5) +#define AP_RW (0x0 << 5) +#define AP_UNPRIV (0x1 << 4) + +#define NS (0x1 << 3) +#define LOWER_ATTRS_SHIFT 2 +#define LOWER_ATTRS(x) (((x) & 0xfff) << LOWER_ATTRS_SHIFT) + +#define ATTR_DEVICE_nGnRE_INDEX 0x0 +#define ATTR_IWBWA_OWBWA_NTR_INDEX 0x1 +#define ATTR_DEVICE_nGnRnE_INDEX 0x2 +#define ATTR_TAGGED_NORMAL_MEM_INDEX 0x3 +#define ATTR_INDEX_MASK 0x7 + +#define ATTR_DEVICE_nGnRnE (0x0) +#define ATTR_DEVICE_nGnRE (0x4) +#define ATTR_IWBWA_OWBWA_NTR (0xff) +/* Same as ATTR_IWBWA_OWBWA_NTR but with memory tagging. */ +#define ATTR_TAGGED_NORMAL_MEM (0xf0) + +#define MAIR_ATTR_SET(attr, index) (((uint64_t)attr) << ((index) << 3)) + +#define OUTPUT_ADDRESS_MASK (0x0000FFFFFFFFF000ULL) + +/* (internal) physical address size bits in EL3/EL1 */ +#define TCR_PS_BITS_4GB (0x0) +#define TCR_PS_BITS_64GB (0x1) +#define TCR_PS_BITS_1TB (0x2) +#define TCR_PS_BITS_4TB (0x3) +#define TCR_PS_BITS_16TB (0x4) +#define TCR_PS_BITS_256TB (0x5) + +#define UNSET_DESC ((uint64_t)-1) + +#define FOUR_KB_SHIFT 12 +#define PAGE_SIZE_SHIFT FOUR_KB_SHIFT +#define PAGE_SIZE (1 << PAGE_SIZE_SHIFT) +#define PAGE_SIZE_MASK (PAGE_SIZE - 1) +#define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == 0) + +#define XLAT_ENTRY_SIZE_SHIFT 3 /* Each MMU table entry is 8 bytes (1 << 3) */ +#define XLAT_ENTRY_SIZE (1 << XLAT_ENTRY_SIZE_SHIFT) + +#define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT +#define XLAT_TABLE_SIZE (1 << XLAT_TABLE_SIZE_SHIFT) + +#define XLAT_TABLE_LEVEL_MAX U(3) + +/* Values for number of entries in each MMU translation table */ +#define XLAT_TABLE_ENTRIES_SHIFT (XLAT_TABLE_SIZE_SHIFT - XLAT_ENTRY_SIZE_SHIFT) +#define XLAT_TABLE_ENTRIES (1 << XLAT_TABLE_ENTRIES_SHIFT) +#define XLAT_TABLE_ENTRIES_MASK (XLAT_TABLE_ENTRIES - 1) + +/* Values to convert a memory address to an index into a translation table */ +#define L3_XLAT_ADDRESS_SHIFT PAGE_SIZE_SHIFT +#define L2_XLAT_ADDRESS_SHIFT (L3_XLAT_ADDRESS_SHIFT + \ + XLAT_TABLE_ENTRIES_SHIFT) +#define L1_XLAT_ADDRESS_SHIFT (L2_XLAT_ADDRESS_SHIFT + \ + XLAT_TABLE_ENTRIES_SHIFT) +#define L0_XLAT_ADDRESS_SHIFT (L1_XLAT_ADDRESS_SHIFT + \ + XLAT_TABLE_ENTRIES_SHIFT) +#define XLAT_ADDR_SHIFT(level) (PAGE_SIZE_SHIFT + \ + ((XLAT_TABLE_LEVEL_MAX - (level)) * \ + XLAT_TABLE_ENTRIES_SHIFT)) + +#define XLAT_BLOCK_SIZE(level) (UL(1) << XLAT_ADDR_SHIFT(level)) + +/* Base table */ +#define BASE_XLAT_ADDRESS_SHIFT XLAT_ADDR_SHIFT(CORE_MMU_BASE_TABLE_LEVEL) +#define BASE_XLAT_BLOCK_SIZE XLAT_BLOCK_SIZE(CORE_MMU_BASE_TABLE_LEVEL) + +#define NUM_BASE_LEVEL_ENTRIES \ + BIT(CFG_LPAE_ADDR_SPACE_BITS - BASE_XLAT_ADDRESS_SHIFT) + +/* + * MMU L1 table, one for each core + * + * With CFG_CORE_UNMAP_CORE_AT_EL0, each core has one table to be used + * while in kernel mode and one to be used while in user mode. + */ +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 +#define NUM_BASE_TABLES 2 +#else +#define NUM_BASE_TABLES 1 +#endif + +#ifndef MAX_XLAT_TABLES +#ifdef CFG_NS_VIRTUALIZATION +# define XLAT_TABLE_VIRTUALIZATION_EXTRA 3 +#else +# define XLAT_TABLE_VIRTUALIZATION_EXTRA 0 +#endif +#ifdef CFG_CORE_ASLR +# define XLAT_TABLE_ASLR_EXTRA 3 +#else +# define XLAT_TABLE_ASLR_EXTRA 0 +#endif +#if (CORE_MMU_BASE_TABLE_LEVEL == 0) +# define XLAT_TABLE_TEE_EXTRA 8 +# define XLAT_TABLE_USER_EXTRA (NUM_BASE_TABLES * CFG_TEE_CORE_NB_CORE) +#else +# define XLAT_TABLE_TEE_EXTRA 5 +# define XLAT_TABLE_USER_EXTRA 0 +#endif +#define MAX_XLAT_TABLES (XLAT_TABLE_TEE_EXTRA + \ + XLAT_TABLE_VIRTUALIZATION_EXTRA + \ + XLAT_TABLE_ASLR_EXTRA + \ + XLAT_TABLE_USER_EXTRA) +#endif /*!MAX_XLAT_TABLES*/ + +#if (CORE_MMU_BASE_TABLE_LEVEL == 0) +#if (MAX_XLAT_TABLES <= UINT8_MAX) +typedef uint8_t l1_idx_t; +#elif (MAX_XLAT_TABLES <= UINT16_MAX) +typedef uint16_t l1_idx_t; +#else +#error MAX_XLAT_TABLES is suspiciously large, please check +#endif +#endif + +typedef uint64_t base_xlat_tbls_t[CFG_TEE_CORE_NB_CORE][NUM_BASE_LEVEL_ENTRIES]; +typedef uint64_t xlat_tbl_t[XLAT_TABLE_ENTRIES]; + +static base_xlat_tbls_t base_xlation_table[NUM_BASE_TABLES] + __aligned(NUM_BASE_LEVEL_ENTRIES * XLAT_ENTRY_SIZE) + __section(".nozi.mmu.base_table"); + +static xlat_tbl_t xlat_tables[MAX_XLAT_TABLES] + __aligned(XLAT_TABLE_SIZE) __section(".nozi.mmu.l2"); + +#define XLAT_TABLES_SIZE (sizeof(xlat_tbl_t) * MAX_XLAT_TABLES) + +/* MMU L2 table for TAs, one for each thread */ +static xlat_tbl_t xlat_tables_ul1[CFG_NUM_THREADS] + __aligned(XLAT_TABLE_SIZE) __section(".nozi.mmu.l2"); + +/* + * TAs page table entry inside a level 1 page table. + * + * TAs mapping is expected to start from level 2. + * + * If base level is 1 then this is the index of a level 1 entry, + * that will point directly into TA mapping table. + * + * If base level is 0 then entry 0 in base table is always used, and then + * we fallback to "base level == 1" like scenario. + */ +static int user_va_idx __nex_data = -1; + +struct mmu_partition { + base_xlat_tbls_t *base_tables; + xlat_tbl_t *xlat_tables; + xlat_tbl_t *l2_ta_tables; + unsigned int xlat_tables_used; + unsigned int asid; + +#if (CORE_MMU_BASE_TABLE_LEVEL == 0) + /* + * Indexes of the L1 table from 'xlat_tables' + * that points to the user mappings. + */ + l1_idx_t user_l1_table_idx[NUM_BASE_TABLES][CFG_TEE_CORE_NB_CORE]; +#endif +}; + +static struct mmu_partition default_partition __nex_data = { + .base_tables = base_xlation_table, + .xlat_tables = xlat_tables, + .l2_ta_tables = xlat_tables_ul1, + .xlat_tables_used = 0, + .asid = 0 +}; + +#ifdef CFG_NS_VIRTUALIZATION +static struct mmu_partition *current_prtn[CFG_TEE_CORE_NB_CORE] __nex_bss; +#endif + +static struct mmu_partition *get_prtn(void) +{ +#ifdef CFG_NS_VIRTUALIZATION + struct mmu_partition *ret; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + ret = current_prtn[get_core_pos()]; + + thread_unmask_exceptions(exceptions); + return ret; +#else + return &default_partition; +#endif +} + +static uint32_t desc_to_mattr(unsigned level, uint64_t desc) +{ + uint32_t a; + + if (!(desc & 1)) + return 0; + + if (level == XLAT_TABLE_LEVEL_MAX) { + if ((desc & DESC_ENTRY_TYPE_MASK) != L3_BLOCK_DESC) + return 0; + } else { + if ((desc & DESC_ENTRY_TYPE_MASK) == TABLE_DESC) + return TEE_MATTR_TABLE; + } + + a = TEE_MATTR_VALID_BLOCK; + + if (desc & LOWER_ATTRS(ACCESS_FLAG)) + a |= TEE_MATTR_PRX | TEE_MATTR_URX; + + if (!(desc & LOWER_ATTRS(AP_RO))) + a |= TEE_MATTR_PW | TEE_MATTR_UW; + + if (!(desc & LOWER_ATTRS(AP_UNPRIV))) + a &= ~TEE_MATTR_URWX; + + if (desc & UPPER_ATTRS(XN)) + a &= ~(TEE_MATTR_PX | TEE_MATTR_UX); + + if (desc & UPPER_ATTRS(PXN)) + a &= ~TEE_MATTR_PX; + + COMPILE_TIME_ASSERT(ATTR_DEVICE_nGnRnE_INDEX == + TEE_MATTR_MEM_TYPE_STRONGLY_O); + COMPILE_TIME_ASSERT(ATTR_DEVICE_nGnRE_INDEX == TEE_MATTR_MEM_TYPE_DEV); + COMPILE_TIME_ASSERT(ATTR_IWBWA_OWBWA_NTR_INDEX == + TEE_MATTR_MEM_TYPE_CACHED); + COMPILE_TIME_ASSERT(ATTR_TAGGED_NORMAL_MEM_INDEX == + TEE_MATTR_MEM_TYPE_TAGGED); + + a |= ((desc & LOWER_ATTRS(ATTR_INDEX_MASK)) >> LOWER_ATTRS_SHIFT) << + TEE_MATTR_MEM_TYPE_SHIFT; + + if (!(desc & LOWER_ATTRS(NON_GLOBAL))) + a |= TEE_MATTR_GLOBAL; + + if (!(desc & LOWER_ATTRS(NS))) + a |= TEE_MATTR_SECURE; + + if (desc & GP) + a |= TEE_MATTR_GUARDED; + + return a; +} + +static uint64_t mattr_to_desc(unsigned level, uint32_t attr) +{ + uint64_t desc; + uint32_t a = attr; + + if (a & TEE_MATTR_TABLE) + return TABLE_DESC; + + if (!(a & TEE_MATTR_VALID_BLOCK)) + return 0; + + if (a & (TEE_MATTR_PX | TEE_MATTR_PW)) + a |= TEE_MATTR_PR; + if (a & (TEE_MATTR_UX | TEE_MATTR_UW)) + a |= TEE_MATTR_UR; + if (a & TEE_MATTR_UR) + a |= TEE_MATTR_PR; + if (a & TEE_MATTR_UW) + a |= TEE_MATTR_PW; + + if (IS_ENABLED(CFG_CORE_BTI) && (a & TEE_MATTR_PX)) + a |= TEE_MATTR_GUARDED; + + if (level == XLAT_TABLE_LEVEL_MAX) + desc = L3_BLOCK_DESC; + else + desc = BLOCK_DESC; + + if (!(a & (TEE_MATTR_PX | TEE_MATTR_UX))) + desc |= UPPER_ATTRS(XN); + if (!(a & TEE_MATTR_PX)) + desc |= UPPER_ATTRS(PXN); + + if (a & TEE_MATTR_UR) + desc |= LOWER_ATTRS(AP_UNPRIV); + + if (!(a & TEE_MATTR_PW)) + desc |= LOWER_ATTRS(AP_RO); + + if (feat_bti_is_implemented() && (a & TEE_MATTR_GUARDED)) + desc |= GP; + + /* Keep in sync with core_mmu.c:core_mmu_mattr_is_ok */ + switch ((a >> TEE_MATTR_MEM_TYPE_SHIFT) & TEE_MATTR_MEM_TYPE_MASK) { + case TEE_MATTR_MEM_TYPE_STRONGLY_O: + desc |= LOWER_ATTRS(ATTR_DEVICE_nGnRnE_INDEX | OSH); + break; + case TEE_MATTR_MEM_TYPE_DEV: + desc |= LOWER_ATTRS(ATTR_DEVICE_nGnRE_INDEX | OSH); + break; + case TEE_MATTR_MEM_TYPE_CACHED: + desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); + break; + case TEE_MATTR_MEM_TYPE_TAGGED: + desc |= LOWER_ATTRS(ATTR_TAGGED_NORMAL_MEM_INDEX | ISH); + break; + default: + /* + * "Can't happen" the attribute is supposed to be checked + * with core_mmu_mattr_is_ok() before. + */ + panic(); + } + + if (a & (TEE_MATTR_UR | TEE_MATTR_PR)) + desc |= LOWER_ATTRS(ACCESS_FLAG); + + if (!(a & TEE_MATTR_GLOBAL)) + desc |= LOWER_ATTRS(NON_GLOBAL); + + desc |= a & TEE_MATTR_SECURE ? 0 : LOWER_ATTRS(NS); + + return desc; +} + +#ifdef CFG_NS_VIRTUALIZATION +size_t core_mmu_get_total_pages_size(void) +{ + return ROUNDUP(sizeof(base_xlation_table), SMALL_PAGE_SIZE) + + sizeof(xlat_tables) + sizeof(xlat_tables_ul1); +} + +struct mmu_partition *core_alloc_mmu_prtn(void *tables) +{ + struct mmu_partition *prtn; + uint8_t *tbl = tables; + unsigned int asid = asid_alloc(); + + assert(((vaddr_t)tbl) % SMALL_PAGE_SIZE == 0); + + if (!asid) + return NULL; + + prtn = nex_malloc(sizeof(*prtn)); + if (!prtn) { + asid_free(asid); + return NULL; + } + + prtn->base_tables = (void *)tbl; + COMPILE_TIME_ASSERT(sizeof(base_xlation_table) <= SMALL_PAGE_SIZE); + memset(prtn->base_tables, 0, SMALL_PAGE_SIZE); + tbl += ROUNDUP(sizeof(base_xlation_table), SMALL_PAGE_SIZE); + + prtn->xlat_tables = (void *)tbl; + memset(prtn->xlat_tables, 0, XLAT_TABLES_SIZE); + tbl += XLAT_TABLES_SIZE; + assert(((vaddr_t)tbl) % SMALL_PAGE_SIZE == 0); + + prtn->l2_ta_tables = (void *)tbl; + prtn->xlat_tables_used = 0; + prtn->asid = asid; + + return prtn; +} + +void core_free_mmu_prtn(struct mmu_partition *prtn) +{ + asid_free(prtn->asid); + nex_free(prtn); +} + +void core_mmu_set_prtn(struct mmu_partition *prtn) +{ + uint64_t ttbr; + /* + * We are changing mappings for current CPU, + * so make sure that we will not be rescheduled + */ + assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); + + current_prtn[get_core_pos()] = prtn; + + ttbr = virt_to_phys(prtn->base_tables[0][get_core_pos()]); + + write_ttbr0_el1(ttbr | ((paddr_t)prtn->asid << TTBR_ASID_SHIFT)); + isb(); + tlbi_all(); +} + +void core_mmu_set_default_prtn(void) +{ + core_mmu_set_prtn(&default_partition); +} + +void core_mmu_set_default_prtn_tbl(void) +{ + size_t n = 0; + + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) + current_prtn[n] = &default_partition; +} +#endif + +static uint64_t *core_mmu_xlat_table_alloc(struct mmu_partition *prtn) +{ + uint64_t *new_table = NULL; + + if (prtn->xlat_tables_used >= MAX_XLAT_TABLES) { + EMSG("%u xlat tables exhausted", MAX_XLAT_TABLES); + + return NULL; + } + + new_table = prtn->xlat_tables[prtn->xlat_tables_used++]; + + DMSG("xlat tables used %u / %u", + prtn->xlat_tables_used, MAX_XLAT_TABLES); + + return new_table; +} + +/* + * Given an entry that points to a table returns the virtual address + * of the pointed table. NULL otherwise. + */ +static void *core_mmu_xlat_table_entry_pa2va(struct mmu_partition *prtn, + unsigned int level, + uint64_t entry) +{ + paddr_t pa = 0; + void *va = NULL; + + if ((entry & DESC_ENTRY_TYPE_MASK) != TABLE_DESC || + level >= XLAT_TABLE_LEVEL_MAX) + return NULL; + + pa = entry & OUTPUT_ADDRESS_MASK; + + if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) || prtn == &default_partition) + va = phys_to_virt(pa, MEM_AREA_TEE_RAM_RW_DATA, + XLAT_TABLE_SIZE); + else + va = phys_to_virt(pa, MEM_AREA_SEC_RAM_OVERALL, + XLAT_TABLE_SIZE); + + return va; +} + +/* + * For a table entry that points to a table - allocate and copy to + * a new pointed table. This is done for the requested entry, + * without going deeper into the pointed table entries. + * + * A success is returned for non-table entries, as nothing to do there. + */ +__maybe_unused +static bool core_mmu_entry_copy(struct core_mmu_table_info *tbl_info, + unsigned int idx) +{ + uint64_t *orig_table = NULL; + uint64_t *new_table = NULL; + uint64_t *entry = NULL; + struct mmu_partition *prtn = NULL; + +#ifdef CFG_NS_VIRTUALIZATION + prtn = tbl_info->prtn; +#else + prtn = &default_partition; +#endif + assert(prtn); + + if (idx >= tbl_info->num_entries) + return false; + + entry = (uint64_t *)tbl_info->table + idx; + + /* Nothing to do for non-table entries */ + if ((*entry & DESC_ENTRY_TYPE_MASK) != TABLE_DESC || + tbl_info->level >= XLAT_TABLE_LEVEL_MAX) + return true; + + new_table = core_mmu_xlat_table_alloc(prtn); + if (!new_table) + return false; + + orig_table = core_mmu_xlat_table_entry_pa2va(prtn, tbl_info->level, + *entry); + if (!orig_table) + return false; + + /* Copy original table content to new table */ + memcpy(new_table, orig_table, XLAT_TABLE_ENTRIES * XLAT_ENTRY_SIZE); + + /* Point to the new table */ + *entry = virt_to_phys(new_table) | (*entry & ~OUTPUT_ADDRESS_MASK); + + return true; +} + +static void core_init_mmu_prtn_tee(struct mmu_partition *prtn, + struct tee_mmap_region *mm) +{ + size_t n; + + assert(prtn && mm); + + for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) { + debug_print(" %010" PRIxVA " %010" PRIxPA " %10zx %x", + mm[n].va, mm[n].pa, mm[n].size, mm[n].attr); + + if (!IS_PAGE_ALIGNED(mm[n].pa) || !IS_PAGE_ALIGNED(mm[n].size)) + panic("unaligned region"); + } + + /* Clear table before use */ + memset(prtn->base_tables, 0, sizeof(base_xlation_table)); + + for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) + if (!core_mmu_is_dynamic_vaspace(mm + n)) + core_mmu_map_region(prtn, mm + n); + + /* + * Primary mapping table is ready at index `get_core_pos()` + * whose value may not be ZERO. Take this index as copy source. + */ + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { + if (n == get_core_pos()) + continue; + + memcpy(prtn->base_tables[0][n], + prtn->base_tables[0][get_core_pos()], + XLAT_ENTRY_SIZE * NUM_BASE_LEVEL_ENTRIES); + } +} + +/* + * In order to support 32-bit TAs we will have to find + * a user VA base in the region [1GB, 4GB[. + * Due to OP-TEE design limitation, TAs page table should be an entry + * inside a level 1 page table. + * + * Available options are only these: + * - base level 0 entry 0 - [0GB, 512GB[ + * - level 1 entry 0 - [0GB, 1GB[ + * - level 1 entry 1 - [1GB, 2GB[ <---- + * - level 1 entry 2 - [2GB, 3GB[ <---- + * - level 1 entry 3 - [3GB, 4GB[ <---- + * - level 1 entry 4 - [4GB, 5GB[ + * - ... + * - ... + * + * - base level 1 entry 0 - [0GB, 1GB[ + * - base level 1 entry 1 - [1GB, 2GB[ <---- + * - base level 1 entry 2 - [2GB, 3GB[ <---- + * - base level 1 entry 3 - [3GB, 4GB[ <---- + * - base level 1 entry 4 - [4GB, 5GB[ + * - ... + */ +static void set_user_va_idx(struct mmu_partition *prtn) +{ + uint64_t *tbl = NULL; + unsigned int n = 0; + + assert(prtn); + + tbl = prtn->base_tables[0][get_core_pos()]; + + /* + * If base level is 0, then we must use its entry 0. + */ + if (CORE_MMU_BASE_TABLE_LEVEL == 0) { + /* + * If base level 0 entry 0 is not used then + * it's clear that we can use level 1 entry 1 inside it. + * (will be allocated later). + */ + if ((tbl[0] & DESC_ENTRY_TYPE_MASK) == INVALID_DESC) { + user_va_idx = 1; + + return; + } + + assert((tbl[0] & DESC_ENTRY_TYPE_MASK) == TABLE_DESC); + + tbl = core_mmu_xlat_table_entry_pa2va(prtn, 0, tbl[0]); + assert(tbl); + } + + /* + * Search level 1 table (i.e. 1GB mapping per entry) for + * an empty entry in the range [1GB, 4GB[. + */ + for (n = 1; n < 4; n++) { + if ((tbl[n] & DESC_ENTRY_TYPE_MASK) == INVALID_DESC) { + user_va_idx = n; + break; + } + } + + assert(user_va_idx != -1); +} + +/* + * Setup an entry inside a core level 1 page table for TAs memory mapping + * + * If base table level is 1 - user_va_idx is already the index, + * so nothing to do. + * If base table level is 0 - we might need to allocate entry 0 of base table, + * as TAs page table is an entry inside a level 1 + * page table. + */ +static void core_init_mmu_prtn_ta_core(struct mmu_partition *prtn + __maybe_unused, + unsigned int base_idx __maybe_unused, + unsigned int core __maybe_unused) +{ +#if (CORE_MMU_BASE_TABLE_LEVEL == 0) + struct core_mmu_table_info tbl_info = { }; + uint64_t *tbl = NULL; + uintptr_t idx = 0; + + assert(user_va_idx != -1); + COMPILE_TIME_ASSERT(MAX_XLAT_TABLES < + (1 << (8 * sizeof(prtn->user_l1_table_idx[0][0])))); + + tbl = prtn->base_tables[base_idx][core]; + + /* + * If base level is 0, then user_va_idx refers to + * level 1 page table that's in base level 0 entry 0. + */ + core_mmu_set_info_table(&tbl_info, 0, 0, tbl); +#ifdef CFG_NS_VIRTUALIZATION + tbl_info.prtn = prtn; +#endif + + /* + * If this isn't the core that created the initial tables + * mappings, then the level 1 table must be copied, + * as it will hold pointer to the user mapping table + * that changes per core. + */ + if (core != get_core_pos()) { + if (!core_mmu_entry_copy(&tbl_info, 0)) + panic(); + } + + if (!core_mmu_entry_to_finer_grained(&tbl_info, 0, true)) + panic(); + + /* + * Now base level table should be ready with a table descriptor + */ + assert((tbl[0] & DESC_ENTRY_TYPE_MASK) == TABLE_DESC); + + tbl = core_mmu_xlat_table_entry_pa2va(prtn, 0, tbl[0]); + assert(tbl); + + idx = ((uintptr_t)&tbl[user_va_idx] - (uintptr_t)prtn->xlat_tables) / + sizeof(xlat_tbl_t); + assert(idx < prtn->xlat_tables_used); + + prtn->user_l1_table_idx[base_idx][core] = idx; +#endif +} + +static void core_init_mmu_prtn_ta(struct mmu_partition *prtn) +{ + unsigned int base_idx = 0; + unsigned int core = 0; + + assert(user_va_idx != -1); + + for (base_idx = 0; base_idx < NUM_BASE_TABLES; base_idx++) + for (core = 0; core < CFG_TEE_CORE_NB_CORE; core++) + core_init_mmu_prtn_ta_core(prtn, base_idx, core); +} + +void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm) +{ + core_init_mmu_prtn_tee(prtn, mm); + core_init_mmu_prtn_ta(prtn); +} + +void core_init_mmu(struct tee_mmap_region *mm) +{ + uint64_t max_va = 0; + size_t n; + + COMPILE_TIME_ASSERT(CORE_MMU_BASE_TABLE_SHIFT == + XLAT_ADDR_SHIFT(CORE_MMU_BASE_TABLE_LEVEL)); +#ifdef CFG_CORE_UNMAP_CORE_AT_EL0 + COMPILE_TIME_ASSERT(CORE_MMU_BASE_TABLE_OFFSET == + sizeof(base_xlation_table) / 2); +#endif + COMPILE_TIME_ASSERT(XLAT_TABLES_SIZE == sizeof(xlat_tables)); + + /* Initialize default pagetables */ + core_init_mmu_prtn_tee(&default_partition, mm); + + for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) { + vaddr_t va_end = mm[n].va + mm[n].size - 1; + + if (va_end > max_va) + max_va = va_end; + } + + set_user_va_idx(&default_partition); + + core_init_mmu_prtn_ta(&default_partition); + + COMPILE_TIME_ASSERT(CFG_LPAE_ADDR_SPACE_BITS > L1_XLAT_ADDRESS_SHIFT); + assert(max_va < BIT64(CFG_LPAE_ADDR_SPACE_BITS)); +} + +#ifdef CFG_WITH_PAGER +/* Prefer to consume only 1 base xlat table for the whole mapping */ +bool core_mmu_prefer_tee_ram_at_top(paddr_t paddr) +{ + size_t base_level_size = BASE_XLAT_BLOCK_SIZE; + paddr_t base_level_mask = base_level_size - 1; + + return (paddr & base_level_mask) > (base_level_size / 2); +} +#endif + +#ifdef ARM32 +void core_init_mmu_regs(struct core_mmu_config *cfg) +{ + uint32_t ttbcr = 0; + uint32_t mair = 0; + + cfg->ttbr0_base = virt_to_phys(base_xlation_table[0][0]); + cfg->ttbr0_core_offset = sizeof(base_xlation_table[0][0]); + + mair = MAIR_ATTR_SET(ATTR_DEVICE_nGnRE, ATTR_DEVICE_nGnRE_INDEX); + mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); + mair |= MAIR_ATTR_SET(ATTR_DEVICE_nGnRnE, ATTR_DEVICE_nGnRnE_INDEX); + /* + * Tagged memory isn't supported in 32-bit mode, map tagged memory + * as normal memory instead. + */ + mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, + ATTR_TAGGED_NORMAL_MEM_INDEX); + cfg->mair0 = mair; + + ttbcr = TTBCR_EAE; + ttbcr |= TTBCR_XRGNX_WBWA << TTBCR_IRGN0_SHIFT; + ttbcr |= TTBCR_XRGNX_WBWA << TTBCR_ORGN0_SHIFT; + ttbcr |= TTBCR_SHX_ISH << TTBCR_SH0_SHIFT; + ttbcr |= TTBCR_EPD1; /* Disable the use of TTBR1 */ + + /* TTBCR.A1 = 0 => ASID is stored in TTBR0 */ + cfg->ttbcr = ttbcr; +} +#endif /*ARM32*/ + +#ifdef ARM64 +static unsigned int get_physical_addr_size_bits(void) +{ + /* + * Intermediate Physical Address Size. + * 0b000 32 bits, 4GB. + * 0b001 36 bits, 64GB. + * 0b010 40 bits, 1TB. + * 0b011 42 bits, 4TB. + * 0b100 44 bits, 16TB. + * 0b101 48 bits, 256TB. + * 0b110 52 bits, 4PB (not supported) + */ + + COMPILE_TIME_ASSERT(CFG_CORE_ARM64_PA_BITS >= 32); + + if (CFG_CORE_ARM64_PA_BITS <= 32) + return TCR_PS_BITS_4GB; + + if (CFG_CORE_ARM64_PA_BITS <= 36) + return TCR_PS_BITS_64GB; + + if (CFG_CORE_ARM64_PA_BITS <= 40) + return TCR_PS_BITS_1TB; + + if (CFG_CORE_ARM64_PA_BITS <= 42) + return TCR_PS_BITS_4TB; + + if (CFG_CORE_ARM64_PA_BITS <= 44) + return TCR_PS_BITS_16TB; + + /* Physical address can't exceed 48 bits */ + COMPILE_TIME_ASSERT(CFG_CORE_ARM64_PA_BITS <= 48); + /* CFG_CORE_ARM64_PA_BITS <= 48 */ + return TCR_PS_BITS_256TB; +} + +void core_init_mmu_regs(struct core_mmu_config *cfg) +{ + uint64_t ips = get_physical_addr_size_bits(); + uint64_t mair = 0; + uint64_t tcr = 0; + + cfg->ttbr0_el1_base = virt_to_phys(base_xlation_table[0][0]); + cfg->ttbr0_core_offset = sizeof(base_xlation_table[0][0]); + + mair = MAIR_ATTR_SET(ATTR_DEVICE_nGnRE, ATTR_DEVICE_nGnRE_INDEX); + mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); + mair |= MAIR_ATTR_SET(ATTR_DEVICE_nGnRnE, ATTR_DEVICE_nGnRnE_INDEX); + /* + * If MEMTAG isn't enabled, map tagged memory as normal memory + * instead. + */ + if (memtag_is_enabled()) + mair |= MAIR_ATTR_SET(ATTR_TAGGED_NORMAL_MEM, + ATTR_TAGGED_NORMAL_MEM_INDEX); + else + mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, + ATTR_TAGGED_NORMAL_MEM_INDEX); + cfg->mair_el1 = mair; + + tcr = TCR_RES1; + tcr |= TCR_XRGNX_WBWA << TCR_IRGN0_SHIFT; + tcr |= TCR_XRGNX_WBWA << TCR_ORGN0_SHIFT; + tcr |= TCR_SHX_ISH << TCR_SH0_SHIFT; + tcr |= ips << TCR_EL1_IPS_SHIFT; + tcr |= 64 - CFG_LPAE_ADDR_SPACE_BITS; + + /* Disable the use of TTBR1 */ + tcr |= TCR_EPD1; + + /* + * TCR.A1 = 0 => ASID is stored in TTBR0 + * TCR.AS = 0 => Same ASID size as in Aarch32/ARMv7 + */ + cfg->tcr_el1 = tcr; +} +#endif /*ARM64*/ + +void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info, + unsigned level, vaddr_t va_base, void *table) +{ + tbl_info->level = level; + tbl_info->table = table; + tbl_info->va_base = va_base; + tbl_info->shift = XLAT_ADDR_SHIFT(level); + +#if (CORE_MMU_BASE_TABLE_LEVEL > 0) + assert(level >= CORE_MMU_BASE_TABLE_LEVEL); +#endif + assert(level <= XLAT_TABLE_LEVEL_MAX); + + if (level == CORE_MMU_BASE_TABLE_LEVEL) + tbl_info->num_entries = NUM_BASE_LEVEL_ENTRIES; + else + tbl_info->num_entries = XLAT_TABLE_ENTRIES; +} + +void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info) +{ + vaddr_t va_range_base; + void *tbl = get_prtn()->l2_ta_tables[thread_get_id()]; + + core_mmu_get_user_va_range(&va_range_base, NULL); + core_mmu_set_info_table(pgd_info, 2, va_range_base, tbl); +} + +void core_mmu_create_user_map(struct user_mode_ctx *uctx, + struct core_mmu_user_map *map) +{ + struct core_mmu_table_info dir_info; + + COMPILE_TIME_ASSERT(sizeof(uint64_t) * XLAT_TABLE_ENTRIES == PGT_SIZE); + + core_mmu_get_user_pgdir(&dir_info); + memset(dir_info.table, 0, PGT_SIZE); + core_mmu_populate_user_map(&dir_info, uctx); + map->user_map = virt_to_phys(dir_info.table) | TABLE_DESC; + map->asid = uctx->vm_info.asid; +} + +bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va, + unsigned max_level, + struct core_mmu_table_info *tbl_info) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + unsigned int num_entries = NUM_BASE_LEVEL_ENTRIES; + unsigned int level = CORE_MMU_BASE_TABLE_LEVEL; + vaddr_t va_base = 0; + bool ret = false; + uint64_t *tbl; + + if (!prtn) + prtn = get_prtn(); + tbl = prtn->base_tables[0][get_core_pos()]; + + while (true) { + unsigned int level_size_shift = XLAT_ADDR_SHIFT(level); + unsigned int n = (va - va_base) >> level_size_shift; + + if (n >= num_entries) + goto out; + + if (level == max_level || level == XLAT_TABLE_LEVEL_MAX || + (tbl[n] & TABLE_DESC) != TABLE_DESC) { + /* + * We've either reached max_level, a block + * mapping entry or an "invalid" mapping entry. + */ + + /* + * Base level is the CPU specific translation table. + * It doesn't make sense to return anything based + * on that unless foreign interrupts already are + * masked. + */ + if (level == CORE_MMU_BASE_TABLE_LEVEL && + !(exceptions & THREAD_EXCP_FOREIGN_INTR)) + goto out; + + tbl_info->table = tbl; + tbl_info->va_base = va_base; + tbl_info->level = level; + tbl_info->shift = level_size_shift; + tbl_info->num_entries = num_entries; +#ifdef CFG_NS_VIRTUALIZATION + tbl_info->prtn = prtn; +#endif + ret = true; + goto out; + } + + tbl = core_mmu_xlat_table_entry_pa2va(prtn, level, tbl[n]); + + if (!tbl) + goto out; + + va_base += (vaddr_t)n << level_size_shift; + level++; + num_entries = XLAT_TABLE_ENTRIES; + } +out: + thread_unmask_exceptions(exceptions); + return ret; +} + +bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info, + unsigned int idx, bool secure __unused) +{ + uint64_t *new_table; + uint64_t *entry; + int i; + paddr_t pa; + uint64_t attr; + paddr_t block_size_on_next_lvl = XLAT_BLOCK_SIZE(tbl_info->level + 1); + struct mmu_partition *prtn; + +#ifdef CFG_NS_VIRTUALIZATION + prtn = tbl_info->prtn; +#else + prtn = &default_partition; +#endif + assert(prtn); + + if (tbl_info->level >= XLAT_TABLE_LEVEL_MAX || + idx >= tbl_info->num_entries) + return false; + + entry = (uint64_t *)tbl_info->table + idx; + + if ((*entry & DESC_ENTRY_TYPE_MASK) == TABLE_DESC) + return true; + + new_table = core_mmu_xlat_table_alloc(prtn); + if (!new_table) + return false; + + if (*entry) { + pa = *entry & OUTPUT_ADDRESS_MASK; + attr = *entry & ~(OUTPUT_ADDRESS_MASK | DESC_ENTRY_TYPE_MASK); + for (i = 0; i < XLAT_TABLE_ENTRIES; i++) { + new_table[i] = pa | attr | BLOCK_DESC; + pa += block_size_on_next_lvl; + } + } else { + memset(new_table, 0, XLAT_TABLE_ENTRIES * XLAT_ENTRY_SIZE); + } + + *entry = virt_to_phys(new_table) | TABLE_DESC; + + return true; +} + +void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx, + paddr_t pa, uint32_t attr) +{ + uint64_t *tbl = table; + uint64_t desc = mattr_to_desc(level, attr); + + tbl[idx] = desc | pa; +} + +void core_mmu_get_entry_primitive(const void *table, size_t level, + size_t idx, paddr_t *pa, uint32_t *attr) +{ + const uint64_t *tbl = table; + + if (pa) + *pa = tbl[idx] & GENMASK_64(47, 12); + + if (attr) + *attr = desc_to_mattr(level, tbl[idx]); +} + +bool core_mmu_user_va_range_is_defined(void) +{ + return user_va_idx != -1; +} + +void core_mmu_get_user_va_range(vaddr_t *base, size_t *size) +{ + assert(user_va_idx != -1); + + if (base) + *base = (vaddr_t)user_va_idx << L1_XLAT_ADDRESS_SHIFT; + if (size) + *size = BIT64(L1_XLAT_ADDRESS_SHIFT); +} + +static uint64_t *core_mmu_get_user_mapping_entry(struct mmu_partition *prtn, + unsigned int base_idx) +{ +#if (CORE_MMU_BASE_TABLE_LEVEL == 0) + l1_idx_t idx = 0; + uint64_t *tbl = NULL; +#endif + + assert(user_va_idx != -1); + +#if (CORE_MMU_BASE_TABLE_LEVEL == 0) + idx = prtn->user_l1_table_idx[base_idx][get_core_pos()]; + tbl = prtn->xlat_tables[idx]; + + return &tbl[user_va_idx]; +#else + return &prtn->base_tables[base_idx][get_core_pos()][user_va_idx]; +#endif +} + +bool core_mmu_user_mapping_is_active(void) +{ + bool ret = false; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + uint64_t *entry = NULL; + + entry = core_mmu_get_user_mapping_entry(get_prtn(), 0); + ret = (*entry != 0); + + thread_unmask_exceptions(exceptions); + + return ret; +} + +#ifdef ARM32 +void core_mmu_get_user_map(struct core_mmu_user_map *map) +{ + struct mmu_partition *prtn = get_prtn(); + uint64_t *entry = NULL; + + entry = core_mmu_get_user_mapping_entry(prtn, 0); + + map->user_map = *entry; + if (map->user_map) { + map->asid = (read_ttbr0_64bit() >> TTBR_ASID_SHIFT) & + TTBR_ASID_MASK; + } else { + map->asid = 0; + } +} + +void core_mmu_set_user_map(struct core_mmu_user_map *map) +{ + uint64_t ttbr = 0; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + struct mmu_partition *prtn = get_prtn(); + uint64_t *entries[NUM_BASE_TABLES] = { }; + unsigned int i = 0; + + ttbr = read_ttbr0_64bit(); + /* Clear ASID */ + ttbr &= ~((uint64_t)TTBR_ASID_MASK << TTBR_ASID_SHIFT); + write_ttbr0_64bit(ttbr); + isb(); + + for (i = 0; i < NUM_BASE_TABLES; i++) + entries[i] = core_mmu_get_user_mapping_entry(prtn, i); + + /* Set the new map */ + if (map && map->user_map) { + for (i = 0; i < NUM_BASE_TABLES; i++) + *entries[i] = map->user_map; + + dsb(); /* Make sure the write above is visible */ + ttbr |= ((uint64_t)map->asid << TTBR_ASID_SHIFT); + write_ttbr0_64bit(ttbr); + isb(); + } else { + for (i = 0; i < NUM_BASE_TABLES; i++) + *entries[i] = INVALID_DESC; + + dsb(); /* Make sure the write above is visible */ + } + + tlbi_all(); + icache_inv_all(); + + thread_unmask_exceptions(exceptions); +} + +enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr) +{ + assert(fault_descr & FSR_LPAE); + + switch (fault_descr & FSR_STATUS_MASK) { + case 0x21: /* b100001 Alignment fault */ + return CORE_MMU_FAULT_ALIGNMENT; + case 0x11: /* b010001 Asynchronous extern abort (DFSR only) */ + return CORE_MMU_FAULT_ASYNC_EXTERNAL; + case 0x12: /* b100010 Debug event */ + return CORE_MMU_FAULT_DEBUG_EVENT; + default: + break; + } + + switch ((fault_descr & FSR_STATUS_MASK) >> 2) { + case 0x1: /* b0001LL Translation fault */ + return CORE_MMU_FAULT_TRANSLATION; + case 0x2: /* b0010LL Access flag fault */ + case 0x3: /* b0011LL Permission fault */ + if (fault_descr & FSR_WNR) + return CORE_MMU_FAULT_WRITE_PERMISSION; + else + return CORE_MMU_FAULT_READ_PERMISSION; + default: + return CORE_MMU_FAULT_OTHER; + } +} +#endif /*ARM32*/ + +#ifdef ARM64 +void core_mmu_get_user_map(struct core_mmu_user_map *map) +{ + struct mmu_partition *prtn = get_prtn(); + uint64_t *entry = NULL; + + entry = core_mmu_get_user_mapping_entry(prtn, 0); + + map->user_map = *entry; + if (map->user_map) { + map->asid = (read_ttbr0_el1() >> TTBR_ASID_SHIFT) & + TTBR_ASID_MASK; + } else { + map->asid = 0; + } +} + +void core_mmu_set_user_map(struct core_mmu_user_map *map) +{ + uint64_t ttbr = 0; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + struct mmu_partition *prtn = get_prtn(); + uint64_t *entries[NUM_BASE_TABLES] = { }; + unsigned int i = 0; + + ttbr = read_ttbr0_el1(); + /* Clear ASID */ + ttbr &= ~((uint64_t)TTBR_ASID_MASK << TTBR_ASID_SHIFT); + write_ttbr0_el1(ttbr); + isb(); + + for (i = 0; i < NUM_BASE_TABLES; i++) + entries[i] = core_mmu_get_user_mapping_entry(prtn, i); + + /* Set the new map */ + if (map && map->user_map) { + for (i = 0; i < NUM_BASE_TABLES; i++) + *entries[i] = map->user_map; + + dsb(); /* Make sure the write above is visible */ + ttbr |= ((uint64_t)map->asid << TTBR_ASID_SHIFT); + write_ttbr0_el1(ttbr); + isb(); + } else { + for (i = 0; i < NUM_BASE_TABLES; i++) + *entries[i] = INVALID_DESC; + + dsb(); /* Make sure the write above is visible */ + } + + tlbi_all(); + icache_inv_all(); + + thread_unmask_exceptions(exceptions); +} + +enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr) +{ + switch ((fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) { + case ESR_EC_SP_ALIGN: + case ESR_EC_PC_ALIGN: + return CORE_MMU_FAULT_ALIGNMENT; + case ESR_EC_IABT_EL0: + case ESR_EC_DABT_EL0: + case ESR_EC_IABT_EL1: + case ESR_EC_DABT_EL1: + switch (fault_descr & ESR_FSC_MASK) { + case ESR_FSC_SIZE_L0: + case ESR_FSC_SIZE_L1: + case ESR_FSC_SIZE_L2: + case ESR_FSC_SIZE_L3: + case ESR_FSC_TRANS_L0: + case ESR_FSC_TRANS_L1: + case ESR_FSC_TRANS_L2: + case ESR_FSC_TRANS_L3: + return CORE_MMU_FAULT_TRANSLATION; + case ESR_FSC_ACCF_L1: + case ESR_FSC_ACCF_L2: + case ESR_FSC_ACCF_L3: + case ESR_FSC_PERMF_L1: + case ESR_FSC_PERMF_L2: + case ESR_FSC_PERMF_L3: + if (fault_descr & ESR_ABT_WNR) + return CORE_MMU_FAULT_WRITE_PERMISSION; + else + return CORE_MMU_FAULT_READ_PERMISSION; + case ESR_FSC_ALIGN: + return CORE_MMU_FAULT_ALIGNMENT; + case ESR_FSC_TAG_CHECK: + return CORE_MMU_FAULT_TAG_CHECK; + default: + return CORE_MMU_FAULT_OTHER; + } + default: + return CORE_MMU_FAULT_OTHER; + } +} +#endif /*ARM64*/ diff --git a/optee/optee_os/core/arch/arm/mm/core_mmu_v7.c b/optee/optee_os/core/arch/arm/mm/core_mmu_v7.c new file mode 100644 index 0000000..58596be --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/core_mmu_v7.c @@ -0,0 +1,827 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_WITH_LPAE +#error This file is not to be used with LPAE +#endif + +#ifdef CFG_NS_VIRTUALIZATION +#error Currently V7 MMU code does not support virtualization +#endif + +#ifndef DEBUG_XLAT_TABLE +#define DEBUG_XLAT_TABLE 0 +#endif + +#if DEBUG_XLAT_TABLE +#define debug_print(...) DMSG_RAW(__VA_ARGS__) +#else +#define debug_print(...) ((void)0) +#endif + +/* + * MMU related values + */ + +/* 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) + +/* Normal memory, Outer Write-Back no Write-Allocate Cacheable */ +#define TEE_MMU_TTB_RNG_WB (3 << 3) + +#ifndef CFG_NO_SMP +#define TEE_MMU_DEFAULT_ATTRS \ + (TEE_MMU_TTB_S | TEE_MMU_TTB_NOS | \ + TEE_MMU_TTB_IRGN_WBWA | TEE_MMU_TTB_RNG_WBWA) +#else +#define TEE_MMU_DEFAULT_ATTRS (TEE_MMU_TTB_IRGN_WB | TEE_MMU_TTB_RNG_WB) +#endif + + +#define INVALID_DESC 0x0 + +#define SECTION_SHIFT 20 +#define SECTION_MASK 0x000fffff +#define SECTION_SIZE 0x00100000 + +/* 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_ACCESS_FLAG (1 << 10) +#define SECTION_UNPRIV (1 << 11) +#define SECTION_RO (1 << 15) +#define SECTION_TEXCB(texcb) ((((texcb) >> 2) << 12) | \ + ((((texcb) >> 1) & 0x1) << 3) | \ + (((texcb) & 0x1) << 2)) +#define SECTION_DEVICE SECTION_TEXCB(ATTR_DEVICE_INDEX) +#define SECTION_NORMAL SECTION_TEXCB(ATTR_DEVICE_INDEX) +#define SECTION_NORMAL_CACHED SECTION_TEXCB(ATTR_NORMAL_CACHED_INDEX) +#define SECTION_STRONG_O SECTION_TEXCB(ATTR_STRONG_O_INDEX) +#define SECTION_TAGGED_CACHED SECTION_TEXCB(ATTR_TAGGED_CACHED_INDEX) + +#define SECTION_XN (1 << 4) +#define SECTION_PXN (1 << 0) +#define SECTION_SECTION (2 << 0) + +#define SECTION_PT_NOTSECURE (1 << 3) +#define SECTION_PT_PT (1 << 0) + +#define SECTION_PT_ATTR_MASK ~((1 << 10) - 1) + +#define SMALL_PAGE_SMALL_PAGE (1 << 1) +#define SMALL_PAGE_SHARED (1 << 10) +#define SMALL_PAGE_NOTGLOBAL (1 << 11) +#define SMALL_PAGE_TEXCB(texcb) ((((texcb) >> 2) << 6) | \ + ((((texcb) >> 1) & 0x1) << 3) | \ + (((texcb) & 0x1) << 2)) +#define SMALL_PAGE_DEVICE SMALL_PAGE_TEXCB(ATTR_DEVICE_INDEX) +#define SMALL_PAGE_NORMAL SMALL_PAGE_TEXCB(ATTR_DEVICE_INDEX) +#define SMALL_PAGE_NORMAL_CACHED \ + SMALL_PAGE_TEXCB(ATTR_NORMAL_CACHED_INDEX) +#define SMALL_PAGE_STRONG_O SMALL_PAGE_TEXCB(ATTR_STRONG_O_INDEX) +#define SMALL_PAGE_TAGGED_CACHED \ + SMALL_PAGE_TEXCB(ATTR_TAGGED_CACHED_INDEX) +#define SMALL_PAGE_ACCESS_FLAG (1 << 4) +#define SMALL_PAGE_UNPRIV (1 << 5) +#define SMALL_PAGE_RO (1 << 9) +#define SMALL_PAGE_XN (1 << 0) + + +/* The TEX, C and B bits concatenated */ +#define ATTR_DEVICE_INDEX 0x0 +#define ATTR_NORMAL_CACHED_INDEX 0x1 +#define ATTR_STRONG_O_INDEX 0x2 +/* Compat with TEE_MATTR_MEM_TYPE_TAGGED */ +#define ATTR_TAGGED_CACHED_INDEX 0x3 + +#define PRRR_IDX(idx, tr, nos) (((tr) << (2 * (idx))) | \ + ((uint32_t)(nos) << ((idx) + 24))) +#define NMRR_IDX(idx, ir, or) (((ir) << (2 * (idx))) | \ + ((uint32_t)(or) << (2 * (idx) + 16))) +#define PRRR_DS0 (1 << 16) +#define PRRR_DS1 (1 << 17) +#define PRRR_NS0 (1 << 18) +#define PRRR_NS1 (1 << 19) + +#define ATTR_DEVICE_PRRR PRRR_IDX(ATTR_DEVICE_INDEX, 1, 0) +#define ATTR_DEVICE_NMRR NMRR_IDX(ATTR_DEVICE_INDEX, 0, 0) + +#define ATTR_STRONGLY_O_PRRR PRRR_IDX(ATTR_STRONG_O_INDEX, 0, 0) +#define ATTR_STRONGLY_O_NMRR NMRR_IDX(ATTR_STRONG_O_INDEX, 0, 0) + +#ifndef CFG_NO_SMP +#define ATTR_NORMAL_CACHED_PRRR PRRR_IDX(ATTR_NORMAL_CACHED_INDEX, 2, 1) +#define ATTR_NORMAL_CACHED_NMRR NMRR_IDX(ATTR_NORMAL_CACHED_INDEX, 1, 1) +#define ATTR_TAGGED_CACHED_PRRR PRRR_IDX(ATTR_TAGGED_CACHED_INDEX, 2, 1) +#define ATTR_TAGGED_CACHED_NMRR NMRR_IDX(ATTR_TAGGED_CACHED_INDEX, 1, 1) +#else +#define ATTR_NORMAL_CACHED_PRRR PRRR_IDX(ATTR_NORMAL_CACHED_INDEX, 2, 0) +#define ATTR_NORMAL_CACHED_NMRR NMRR_IDX(ATTR_NORMAL_CACHED_INDEX, 3, 3) +#define ATTR_TAGGED_CACHED_PRRR PRRR_IDX(ATTR_TAGGED_CACHED_INDEX, 2, 0) +#define ATTR_TAGGED_CACHED_NMRR NMRR_IDX(ATTR_TAGGED_CACHED_INDEX, 3, 3) +#endif + +#define NUM_L1_ENTRIES 4096 +#define NUM_L2_ENTRIES 256 + +#define L1_TBL_SIZE (NUM_L1_ENTRIES * 4) +#define L2_TBL_SIZE (NUM_L2_ENTRIES * 4) +#define L1_ALIGNMENT L1_TBL_SIZE +#define L2_ALIGNMENT L2_TBL_SIZE + +/* Defined to the smallest possible secondary L1 MMU table */ +#define TTBCR_N_VALUE 7 + +/* Number of sections in ttbr0 when user mapping activated */ +#define NUM_UL1_ENTRIES (1 << (12 - TTBCR_N_VALUE)) +#define UL1_ALIGNMENT (NUM_UL1_ENTRIES * 4) +/* TTB attributes */ + +/* TTB0 of TTBR0 (depends on TTBCR_N_VALUE) */ +#define TTB_UL1_MASK (~(UL1_ALIGNMENT - 1)) +/* TTB1 of TTBR1 */ +#define TTB_L1_MASK (~(L1_ALIGNMENT - 1)) + +#ifndef MAX_XLAT_TABLES +#ifdef CFG_CORE_ASLR +# define XLAT_TABLE_ASLR_EXTRA 2 +#else +# define XLAT_TABLE_ASLR_EXTRA 0 +#endif +#define MAX_XLAT_TABLES (4 + XLAT_TABLE_ASLR_EXTRA) +#endif /*!MAX_XLAT_TABLES*/ + +enum desc_type { + DESC_TYPE_PAGE_TABLE, + DESC_TYPE_SECTION, + DESC_TYPE_SUPER_SECTION, + DESC_TYPE_LARGE_PAGE, + DESC_TYPE_SMALL_PAGE, + DESC_TYPE_INVALID, +}; + +typedef uint32_t l1_xlat_tbl_t[NUM_L1_ENTRIES]; +typedef uint32_t l2_xlat_tbl_t[NUM_L2_ENTRIES]; +typedef uint32_t ul1_xlat_tbl_t[NUM_UL1_ENTRIES]; + +static l1_xlat_tbl_t main_mmu_l1_ttb + __aligned(L1_ALIGNMENT) __section(".nozi.mmu.l1"); + +/* L2 MMU tables */ +static l2_xlat_tbl_t main_mmu_l2_ttb[MAX_XLAT_TABLES] + __aligned(L2_ALIGNMENT) __section(".nozi.mmu.l2"); + +/* MMU L1 table for TAs, one for each thread */ +static ul1_xlat_tbl_t main_mmu_ul1_ttb[CFG_NUM_THREADS] + __aligned(UL1_ALIGNMENT) __section(".nozi.mmu.ul1"); + +struct mmu_partition { + l1_xlat_tbl_t *l1_table; + l2_xlat_tbl_t *l2_tables; + ul1_xlat_tbl_t *ul1_tables; + uint32_t tables_used; +}; + +static struct mmu_partition default_partition = { + .l1_table = &main_mmu_l1_ttb, + .l2_tables = main_mmu_l2_ttb, + .ul1_tables = main_mmu_ul1_ttb, + .tables_used = 0, +}; + +#ifdef CFG_NS_VIRTUALIZATION +static struct mmu_partition *current_prtn[CFG_TEE_CORE_NB_CORE]; + +void core_mmu_set_default_prtn_tbl(void) +{ + size_t n = 0; + + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) + current_prtn[n] = &default_partition; +} +#endif + +static struct mmu_partition *get_prtn(void) +{ +#ifdef CFG_NS_VIRTUALIZATION + return current_prtn[get_core_pos()]; +#else + return &default_partition; +#endif +} + +static vaddr_t core_mmu_get_main_ttb_va(struct mmu_partition *prtn) +{ + return (vaddr_t)prtn->l1_table; +} + +static paddr_t core_mmu_get_main_ttb_pa(struct mmu_partition *prtn) +{ + paddr_t pa = virt_to_phys((void *)core_mmu_get_main_ttb_va(prtn)); + + if (pa & ~TTB_L1_MASK) + panic("invalid core l1 table"); + return pa; +} + +static vaddr_t core_mmu_get_ul1_ttb_va(struct mmu_partition *prtn) +{ + return (vaddr_t)prtn->ul1_tables[thread_get_id()]; +} + +static paddr_t core_mmu_get_ul1_ttb_pa(struct mmu_partition *prtn) +{ + paddr_t pa = virt_to_phys((void *)core_mmu_get_ul1_ttb_va(prtn)); + + if (pa & ~TTB_UL1_MASK) + panic("invalid user l1 table"); + return pa; +} + +static void *core_mmu_alloc_l2(struct mmu_partition *prtn, size_t size) +{ + uint32_t to_alloc = ROUNDUP(size, NUM_L2_ENTRIES * SMALL_PAGE_SIZE) / + (NUM_L2_ENTRIES * SMALL_PAGE_SIZE); + + DMSG("L2 table used: %d/%d", prtn->tables_used + to_alloc, + MAX_XLAT_TABLES); + if (prtn->tables_used + to_alloc > MAX_XLAT_TABLES) + return NULL; + + memset(prtn->l2_tables[prtn->tables_used], 0, + sizeof(l2_xlat_tbl_t) * to_alloc); + prtn->tables_used += to_alloc; + return prtn->l2_tables[prtn->tables_used - to_alloc]; +} + +static enum desc_type get_desc_type(unsigned level, uint32_t desc) +{ + assert(level >= 1 && level <= 2); + + if (level == 1) { + if ((desc & 0x3) == 0x1) + return DESC_TYPE_PAGE_TABLE; + + if ((desc & 0x2) == 0x2) { + if (desc & (1 << 18)) + return DESC_TYPE_SUPER_SECTION; + return DESC_TYPE_SECTION; + } + } else { + if ((desc & 0x3) == 0x1) + return DESC_TYPE_LARGE_PAGE; + + if ((desc & 0x2) == 0x2) + return DESC_TYPE_SMALL_PAGE; + } + + return DESC_TYPE_INVALID; +} + +static uint32_t texcb_to_mattr(uint32_t texcb) +{ + COMPILE_TIME_ASSERT(ATTR_DEVICE_INDEX == TEE_MATTR_MEM_TYPE_DEV); + COMPILE_TIME_ASSERT(ATTR_NORMAL_CACHED_INDEX == + TEE_MATTR_MEM_TYPE_CACHED); + COMPILE_TIME_ASSERT(ATTR_STRONG_O_INDEX == + TEE_MATTR_MEM_TYPE_STRONGLY_O); + COMPILE_TIME_ASSERT(ATTR_TAGGED_CACHED_INDEX == + TEE_MATTR_MEM_TYPE_TAGGED); + + return texcb << TEE_MATTR_MEM_TYPE_SHIFT; +} + +static uint32_t mattr_to_texcb(uint32_t attr) +{ + /* Keep in sync with core_mmu.c:core_mmu_mattr_is_ok */ + return (attr >> TEE_MATTR_MEM_TYPE_SHIFT) & TEE_MATTR_MEM_TYPE_MASK; +} + + +static uint32_t desc_to_mattr(unsigned level, uint32_t desc) +{ + uint32_t a; + + switch (get_desc_type(level, desc)) { + case DESC_TYPE_PAGE_TABLE: + a = TEE_MATTR_TABLE; + if (!(desc & SECTION_PT_NOTSECURE)) + a |= TEE_MATTR_SECURE; + break; + case DESC_TYPE_SECTION: + a = TEE_MATTR_VALID_BLOCK; + if (desc & SECTION_ACCESS_FLAG) + a |= TEE_MATTR_PRX | TEE_MATTR_URX; + + if (!(desc & SECTION_RO)) + a |= TEE_MATTR_PW | TEE_MATTR_UW; + + if (desc & SECTION_XN) + a &= ~(TEE_MATTR_PX | TEE_MATTR_UX); + + if (desc & SECTION_PXN) + a &= ~TEE_MATTR_PX; + + a |= texcb_to_mattr(((desc >> 12) & 0x7) | ((desc >> 2) & 0x3)); + + if (!(desc & SECTION_NOTGLOBAL)) + a |= TEE_MATTR_GLOBAL; + + if (!(desc & SECTION_NOTSECURE)) + a |= TEE_MATTR_SECURE; + + break; + case DESC_TYPE_SMALL_PAGE: + a = TEE_MATTR_VALID_BLOCK; + if (desc & SMALL_PAGE_ACCESS_FLAG) + a |= TEE_MATTR_PRX | TEE_MATTR_URX; + + if (!(desc & SMALL_PAGE_RO)) + a |= TEE_MATTR_PW | TEE_MATTR_UW; + + if (desc & SMALL_PAGE_XN) + a &= ~(TEE_MATTR_PX | TEE_MATTR_UX); + + a |= texcb_to_mattr(((desc >> 6) & 0x7) | ((desc >> 2) & 0x3)); + + if (!(desc & SMALL_PAGE_NOTGLOBAL)) + a |= TEE_MATTR_GLOBAL; + break; + default: + return 0; + } + + return a; +} + +static uint32_t mattr_to_desc(unsigned level, uint32_t attr) +{ + uint32_t desc; + uint32_t a = attr; + unsigned texcb; + + if (level == 1 && (a & TEE_MATTR_TABLE)) { + desc = SECTION_PT_PT; + if (!(a & TEE_MATTR_SECURE)) + desc |= SECTION_PT_NOTSECURE; + return desc; + } + + if (!(a & TEE_MATTR_VALID_BLOCK)) + return INVALID_DESC; + + if (a & (TEE_MATTR_PX | TEE_MATTR_PW)) + a |= TEE_MATTR_PR; + if (a & (TEE_MATTR_UX | TEE_MATTR_UW)) + a |= TEE_MATTR_UR; + if (a & TEE_MATTR_UR) + a |= TEE_MATTR_PR; + if (a & TEE_MATTR_UW) + a |= TEE_MATTR_PW; + + + texcb = mattr_to_texcb(a); + + if (level == 1) { /* Section */ +#ifndef CFG_NO_SMP + desc = SECTION_SECTION | SECTION_SHARED; +#else + desc = SECTION_SECTION; +#endif + + if (!(a & (TEE_MATTR_PX | TEE_MATTR_UX))) + desc |= SECTION_XN; + +#ifdef CFG_HWSUPP_MEM_PERM_PXN + if (!(a & TEE_MATTR_PX)) + desc |= SECTION_PXN; +#endif + + if (a & TEE_MATTR_UR) + desc |= SECTION_UNPRIV; + + if (!(a & TEE_MATTR_PW)) + desc |= SECTION_RO; + + if (a & (TEE_MATTR_UR | TEE_MATTR_PR)) + desc |= SECTION_ACCESS_FLAG; + + if (!(a & TEE_MATTR_GLOBAL)) + desc |= SECTION_NOTGLOBAL; + + if (!(a & TEE_MATTR_SECURE)) + desc |= SECTION_NOTSECURE; + + desc |= SECTION_TEXCB(texcb); + } else { +#ifndef CFG_NO_SMP + desc = SMALL_PAGE_SMALL_PAGE | SMALL_PAGE_SHARED; +#else + desc = SMALL_PAGE_SMALL_PAGE; +#endif + + if (!(a & (TEE_MATTR_PX | TEE_MATTR_UX))) + desc |= SMALL_PAGE_XN; + + if (a & TEE_MATTR_UR) + desc |= SMALL_PAGE_UNPRIV; + + if (!(a & TEE_MATTR_PW)) + desc |= SMALL_PAGE_RO; + + if (a & (TEE_MATTR_UR | TEE_MATTR_PR)) + desc |= SMALL_PAGE_ACCESS_FLAG; + + if (!(a & TEE_MATTR_GLOBAL)) + desc |= SMALL_PAGE_NOTGLOBAL; + + desc |= SMALL_PAGE_TEXCB(texcb); + } + + return desc; +} + +void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info, + unsigned level, vaddr_t va_base, void *table) +{ + tbl_info->level = level; + tbl_info->table = table; + tbl_info->va_base = va_base; + assert(level <= 2); + if (level == 1) { + tbl_info->shift = SECTION_SHIFT; + tbl_info->num_entries = NUM_L1_ENTRIES; + } else { + tbl_info->shift = SMALL_PAGE_SHIFT; + tbl_info->num_entries = NUM_L2_ENTRIES; + } +} + +void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info) +{ + void *tbl = (void *)core_mmu_get_ul1_ttb_va(get_prtn()); + + core_mmu_set_info_table(pgd_info, 1, 0, tbl); + pgd_info->num_entries = NUM_UL1_ENTRIES; +} + +void core_mmu_create_user_map(struct user_mode_ctx *uctx, + struct core_mmu_user_map *map) +{ + struct core_mmu_table_info dir_info = { }; + + COMPILE_TIME_ASSERT(L2_TBL_SIZE == PGT_SIZE); + + core_mmu_get_user_pgdir(&dir_info); + memset(dir_info.table, 0, dir_info.num_entries * sizeof(uint32_t)); + core_mmu_populate_user_map(&dir_info, uctx); + map->ttbr0 = core_mmu_get_ul1_ttb_pa(get_prtn()) | + TEE_MMU_DEFAULT_ATTRS; + map->ctxid = uctx->vm_info.asid; +} + +bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va, + unsigned max_level, + struct core_mmu_table_info *tbl_info) +{ + uint32_t *tbl; + unsigned n = va >> SECTION_SHIFT; + + if (!prtn) + prtn = get_prtn(); + tbl = (uint32_t *)core_mmu_get_main_ttb_va(prtn); + + if (max_level == 1 || (tbl[n] & 0x3) != 0x1) { + core_mmu_set_info_table(tbl_info, 1, 0, tbl); + } else { + paddr_t ntbl = tbl[n] & ~((1 << 10) - 1); + void *l2tbl = phys_to_virt(ntbl, MEM_AREA_TEE_RAM_RW_DATA, + L2_TBL_SIZE); + + if (!l2tbl) + return false; + + core_mmu_set_info_table(tbl_info, 2, n << SECTION_SHIFT, l2tbl); + } + return true; +} + +void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx, + paddr_t pa, uint32_t attr) +{ + uint32_t *tbl = table; + uint32_t desc = mattr_to_desc(level, attr); + + tbl[idx] = desc | pa; +} + +static paddr_t desc_to_pa(unsigned level, uint32_t desc) +{ + unsigned shift_mask; + + switch (get_desc_type(level, desc)) { + case DESC_TYPE_PAGE_TABLE: + shift_mask = 10; + break; + case DESC_TYPE_SECTION: + shift_mask = 20; + break; + case DESC_TYPE_SUPER_SECTION: + shift_mask = 24; /* We're ignoring bits 32 and above. */ + break; + case DESC_TYPE_LARGE_PAGE: + shift_mask = 16; + break; + case DESC_TYPE_SMALL_PAGE: + shift_mask = 12; + break; + default: + /* Invalid section */ + shift_mask = 4; + } + + return desc & ~((1 << shift_mask) - 1); +} + +bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info, + unsigned int idx, bool secure) +{ + uint32_t *new_table; + uint32_t *entry; + uint32_t new_table_desc; + uint32_t attr; + uint32_t desc; + paddr_t pa; + int i; + + if (tbl_info->level != 1) + return false; + + if (idx >= NUM_L1_ENTRIES) + return false; + + entry = (uint32_t *)tbl_info->table + idx; + attr = desc_to_mattr(1, *entry); + + if (*entry && get_desc_type(1, *entry) == DESC_TYPE_PAGE_TABLE) { + /* + * If there is page table already, + * check the secure attribute fits + */ + return secure == (bool)(attr & TEE_MATTR_SECURE); + } + + /* If there is something mapped, check the secure access flag */ + if (attr && secure != (bool)(attr & TEE_MATTR_SECURE)) + return false; + + new_table = core_mmu_alloc_l2(get_prtn(), + NUM_L2_ENTRIES * SMALL_PAGE_SIZE); + + if (!new_table) + return false; + + new_table_desc = SECTION_PT_PT | virt_to_phys(new_table); + + if (!secure) + new_table_desc |= SECTION_PT_NOTSECURE; + + if (*entry) { + pa = desc_to_pa(1, *entry); + desc = mattr_to_desc(2, attr); + for (i = 0; i < NUM_L2_ENTRIES; i++, pa += SMALL_PAGE_SIZE) + new_table[i] = desc | pa; + } + + /* Update descriptor at current level */ + *entry = new_table_desc; + + return true; +} + +void core_mmu_get_entry_primitive(const void *table, size_t level, + size_t idx, paddr_t *pa, uint32_t *attr) +{ + const uint32_t *tbl = table; + + if (pa) + *pa = desc_to_pa(level, tbl[idx]); + + if (attr) + *attr = desc_to_mattr(level, tbl[idx]); +} + +void core_mmu_get_user_va_range(vaddr_t *base, size_t *size) +{ + if (base) { + /* Leaving the first entry unmapped to make NULL unmapped */ + *base = 1 << SECTION_SHIFT; + } + + if (size) + *size = (NUM_UL1_ENTRIES - 1) << SECTION_SHIFT; +} + +void core_mmu_get_user_map(struct core_mmu_user_map *map) +{ + map->ttbr0 = read_ttbr0(); + map->ctxid = read_contextidr(); +} + +void core_mmu_set_user_map(struct core_mmu_user_map *map) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + /* + * Update the reserved Context ID and TTBR0 + */ + + dsb(); /* ARM erratum 754322 */ + write_contextidr(0); + isb(); + + if (map) { + write_ttbr0(map->ttbr0); + isb(); + write_contextidr(map->ctxid); + isb(); + } else { + write_ttbr0(read_ttbr1()); + isb(); + } + + tlbi_all(); + icache_inv_all(); + + /* Restore interrupts */ + thread_unmask_exceptions(exceptions); +} + +bool core_mmu_user_mapping_is_active(void) +{ + bool ret; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + ret = read_ttbr0() != read_ttbr1(); + thread_unmask_exceptions(exceptions); + + return ret; +} + +static void print_mmap_area(const struct tee_mmap_region *mm __maybe_unused, + const char *str __maybe_unused) +{ + if (!(mm->attr & TEE_MATTR_VALID_BLOCK)) + debug_print("%s [%08" PRIxVA " %08" PRIxVA "] not mapped", + str, mm->va, mm->va + mm->size); + else + debug_print("%s [%08" PRIxVA " %08" PRIxVA "] %s-%s-%s-%s", + str, mm->va, mm->va + mm->size, + mattr_is_cached(mm->attr) ? "MEM" : "DEV", + mm->attr & TEE_MATTR_PW ? "RW" : "RO", + mm->attr & TEE_MATTR_PX ? "X" : "XN", + mm->attr & TEE_MATTR_SECURE ? "S" : "NS"); +} + +void map_memarea_sections(const struct tee_mmap_region *mm, uint32_t *ttb) +{ + uint32_t attr = mattr_to_desc(1, mm->attr); + size_t idx = mm->va >> SECTION_SHIFT; + paddr_t pa = 0; + size_t n; + + if (core_mmap_is_end_of_table(mm)) + return; + + print_mmap_area(mm, "section map"); + + attr = mattr_to_desc(1, mm->attr); + if (attr != INVALID_DESC) + pa = mm->pa; + + n = ROUNDUP(mm->size, SECTION_SIZE) >> SECTION_SHIFT; + while (n--) { + assert(!attr || !ttb[idx] || ttb[idx] == (pa | attr)); + + ttb[idx] = pa | attr; + idx++; + pa += SECTION_SIZE; + } +} + +void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm) +{ + void *ttb1 = (void *)core_mmu_get_main_ttb_va(prtn); + size_t n; + + /* reset L1 table */ + memset(ttb1, 0, L1_TBL_SIZE); + + for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) + if (!core_mmu_is_dynamic_vaspace(mm + n)) + core_mmu_map_region(prtn, mm + n); +} + +void core_init_mmu(struct tee_mmap_region *mm) +{ + /* Initialize default pagetables */ + core_init_mmu_prtn(&default_partition, mm); +} + +void core_init_mmu_regs(struct core_mmu_config *cfg) +{ + cfg->ttbr = core_mmu_get_main_ttb_pa(&default_partition) | + TEE_MMU_DEFAULT_ATTRS; + + cfg->prrr = ATTR_DEVICE_PRRR | ATTR_NORMAL_CACHED_PRRR | + ATTR_STRONGLY_O_PRRR | ATTR_TAGGED_CACHED_PRRR; + cfg->nmrr = ATTR_DEVICE_NMRR | ATTR_NORMAL_CACHED_NMRR | + ATTR_STRONGLY_O_NMRR | ATTR_TAGGED_CACHED_NMRR; + + cfg->prrr |= PRRR_NS1 | PRRR_DS1; + + /* + * Program Domain access control register with two domains: + * domain 0: teecore + * domain 1: TA + */ + cfg->dacr = DACR_DOMAIN(0, DACR_DOMAIN_PERM_CLIENT) | + DACR_DOMAIN(1, DACR_DOMAIN_PERM_CLIENT); + + /* + * Enable lookups using TTBR0 and TTBR1 with the split of addresses + * defined by TEE_MMU_TTBCR_N_VALUE. + */ + cfg->ttbcr = TTBCR_N_VALUE; +} + +enum core_mmu_fault core_mmu_get_fault_type(uint32_t fsr) +{ + assert(!(fsr & FSR_LPAE)); + + switch (fsr & FSR_FS_MASK) { + case 0x1: /* DFSR[10,3:0] 0b00001 Alignment fault (DFSR only) */ + return CORE_MMU_FAULT_ALIGNMENT; + case 0x2: /* DFSR[10,3:0] 0b00010 Debug event */ + return CORE_MMU_FAULT_DEBUG_EVENT; + case 0x4: /* DFSR[10,3:0] b00100 Fault on instr cache maintenance */ + case 0x5: /* DFSR[10,3:0] b00101 Translation fault first level */ + case 0x7: /* DFSR[10,3:0] b00111 Translation fault second level */ + return CORE_MMU_FAULT_TRANSLATION; + case 0xd: /* DFSR[10,3:0] b01101 Permission fault first level */ + case 0xf: /* DFSR[10,3:0] b01111 Permission fault second level */ + if (fsr & FSR_WNR) + return CORE_MMU_FAULT_WRITE_PERMISSION; + else + return CORE_MMU_FAULT_READ_PERMISSION; + case 0x3: /* DFSR[10,3:0] b00011 access bit fault on section */ + case 0x6: /* DFSR[10,3:0] b00110 access bit fault on page */ + return CORE_MMU_FAULT_ACCESS_BIT; + case (1 << 10) | 0x6: + /* DFSR[10,3:0] 0b10110 Async external abort (DFSR only) */ + return CORE_MMU_FAULT_ASYNC_EXTERNAL; + + default: + return CORE_MMU_FAULT_OTHER; + } +} diff --git a/optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c b/optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c new file mode 100644 index 0000000..3e2ac50 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/mobj_dyn_shm.c @@ -0,0 +1,468 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct mutex shm_mu = MUTEX_INITIALIZER; +static struct condvar shm_cv = CONDVAR_INITIALIZER; +static size_t shm_release_waiters; + +/* + * mobj_reg_shm implementation. Describes shared memory provided by normal world + */ + +struct mobj_reg_shm { + struct mobj mobj; + SLIST_ENTRY(mobj_reg_shm) next; + uint64_t cookie; + tee_mm_entry_t *mm; + paddr_t page_offset; + struct refcount mapcount; + bool guarded; + bool releasing; + bool release_frees; + paddr_t pages[]; +}; + +static size_t mobj_reg_shm_size(size_t nr_pages) +{ + size_t s = 0; + + if (MUL_OVERFLOW(sizeof(paddr_t), nr_pages, &s)) + return 0; + if (ADD_OVERFLOW(sizeof(struct mobj_reg_shm), s, &s)) + return 0; + return s; +} + +static SLIST_HEAD(reg_shm_head, mobj_reg_shm) reg_shm_list = + SLIST_HEAD_INITIALIZER(reg_shm_head); + +static unsigned int reg_shm_slist_lock = SPINLOCK_UNLOCK; +static unsigned int reg_shm_map_lock = SPINLOCK_UNLOCK; + +static struct mobj_reg_shm *to_mobj_reg_shm(struct mobj *mobj); + +static TEE_Result mobj_reg_shm_get_pa(struct mobj *mobj, size_t offst, + size_t granule, paddr_t *pa) +{ + struct mobj_reg_shm *mobj_reg_shm = to_mobj_reg_shm(mobj); + size_t full_offset = 0; + paddr_t p = 0; + + if (!pa) + return TEE_ERROR_GENERIC; + + if (offst >= mobj->size) + return TEE_ERROR_GENERIC; + + full_offset = offst + mobj_reg_shm->page_offset; + switch (granule) { + case 0: + p = mobj_reg_shm->pages[full_offset / SMALL_PAGE_SIZE] + + (full_offset & SMALL_PAGE_MASK); + break; + case SMALL_PAGE_SIZE: + p = mobj_reg_shm->pages[full_offset / SMALL_PAGE_SIZE]; + break; + default: + return TEE_ERROR_GENERIC; + } + *pa = p; + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(mobj_reg_shm_get_pa); + +static size_t mobj_reg_shm_get_phys_offs(struct mobj *mobj, + size_t granule __maybe_unused) +{ + assert(granule >= mobj->phys_granule); + return to_mobj_reg_shm(mobj)->page_offset; +} + +static void *mobj_reg_shm_get_va(struct mobj *mobj, size_t offst, size_t len) +{ + struct mobj_reg_shm *mrs = to_mobj_reg_shm(mobj); + + if (!mrs->mm || !mobj_check_offset_and_len(mobj, offst, len)) + return NULL; + + return (void *)(vaddr_t)(tee_mm_get_smem(mrs->mm) + offst + + mrs->page_offset); +} + +static void reg_shm_unmap_helper(struct mobj_reg_shm *r) +{ + assert(r->mm); + assert(r->mm->pool->shift == SMALL_PAGE_SHIFT); + core_mmu_unmap_pages(tee_mm_get_smem(r->mm), r->mm->size); + tee_mm_free(r->mm); + r->mm = NULL; +} + +static void reg_shm_free_helper(struct mobj_reg_shm *mobj_reg_shm) +{ + uint32_t exceptions = cpu_spin_lock_xsave(®_shm_map_lock); + + if (mobj_reg_shm->mm) + reg_shm_unmap_helper(mobj_reg_shm); + + cpu_spin_unlock_xrestore(®_shm_map_lock, exceptions); + + SLIST_REMOVE(®_shm_list, mobj_reg_shm, mobj_reg_shm, next); + free(mobj_reg_shm); +} + +static void mobj_reg_shm_free(struct mobj *mobj) +{ + struct mobj_reg_shm *r = to_mobj_reg_shm(mobj); + uint32_t exceptions = 0; + + if (r->guarded && !r->releasing) { + /* + * Guarded registersted shared memory can't be released + * by cookie, only by mobj_put(). However, unguarded + * registered shared memory can also be freed by mobj_put() + * unless mobj_reg_shm_release_by_cookie() is waiting for + * the mobj to be released. + */ + exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); + reg_shm_free_helper(r); + cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); + } else { + /* + * We've reached the point where an unguarded reg shm can + * be released by cookie. Notify eventual waiters. + */ + exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); + r->release_frees = true; + cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); + + mutex_lock(&shm_mu); + if (shm_release_waiters) + condvar_broadcast(&shm_cv); + mutex_unlock(&shm_mu); + } +} + +static TEE_Result mobj_reg_shm_get_mem_type(struct mobj *mobj __unused, + uint32_t *mt) +{ + if (!mt) + return TEE_ERROR_GENERIC; + + *mt = TEE_MATTR_MEM_TYPE_CACHED; + + return TEE_SUCCESS; +} + +static TEE_Result mobj_reg_shm_inc_map(struct mobj *mobj) +{ + TEE_Result res = TEE_SUCCESS; + struct mobj_reg_shm *r = to_mobj_reg_shm(mobj); + uint32_t exceptions = 0; + size_t sz = 0; + + while (true) { + if (refcount_inc(&r->mapcount)) + return TEE_SUCCESS; + + exceptions = cpu_spin_lock_xsave(®_shm_map_lock); + + if (!refcount_val(&r->mapcount)) + break; /* continue to reinitialize */ + /* + * If another thread beat us to initialize mapcount, + * restart to make sure we still increase it. + */ + cpu_spin_unlock_xrestore(®_shm_map_lock, exceptions); + } + + /* + * If we have beated another thread calling mobj_reg_shm_dec_map() + * to get the lock we need only to reinitialize mapcount to 1. + */ + if (!r->mm) { + sz = ROUNDUP(mobj->size + r->page_offset, SMALL_PAGE_SIZE); + r->mm = tee_mm_alloc(&tee_mm_shm, sz); + if (!r->mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = core_mmu_map_pages(tee_mm_get_smem(r->mm), r->pages, + sz / SMALL_PAGE_SIZE, + MEM_AREA_NSEC_SHM); + if (res) { + tee_mm_free(r->mm); + r->mm = NULL; + goto out; + } + } + + refcount_set(&r->mapcount, 1); +out: + cpu_spin_unlock_xrestore(®_shm_map_lock, exceptions); + + return res; +} + +static TEE_Result mobj_reg_shm_dec_map(struct mobj *mobj) +{ + struct mobj_reg_shm *r = to_mobj_reg_shm(mobj); + uint32_t exceptions = 0; + + if (!refcount_dec(&r->mapcount)) + return TEE_SUCCESS; + + exceptions = cpu_spin_lock_xsave(®_shm_map_lock); + + if (!refcount_val(&r->mapcount)) + reg_shm_unmap_helper(r); + + cpu_spin_unlock_xrestore(®_shm_map_lock, exceptions); + + return TEE_SUCCESS; +} + +static bool mobj_reg_shm_matches(struct mobj *mobj, enum buf_is_attr attr); + +static uint64_t mobj_reg_shm_get_cookie(struct mobj *mobj) +{ + return to_mobj_reg_shm(mobj)->cookie; +} + +/* + * When CFG_PREALLOC_RPC_CACHE is disabled, this variable is weak just + * to ease breaking its dependency chain when added to the unpaged area. + * When CFG_PREALLOC_RPC_CACHE is enabled, releasing RPC preallocated + * shm mandates these resources to be unpaged. + */ +const struct mobj_ops mobj_reg_shm_ops +__weak __relrodata_unpaged("mobj_reg_shm_ops") = { + .get_pa = mobj_reg_shm_get_pa, + .get_phys_offs = mobj_reg_shm_get_phys_offs, + .get_va = mobj_reg_shm_get_va, + .get_mem_type = mobj_reg_shm_get_mem_type, + .matches = mobj_reg_shm_matches, + .free = mobj_reg_shm_free, + .get_cookie = mobj_reg_shm_get_cookie, + .inc_map = mobj_reg_shm_inc_map, + .dec_map = mobj_reg_shm_dec_map, +}; + +#ifdef CFG_PREALLOC_RPC_CACHE +/* Releasing RPC preallocated shm mandates few resources to be unpaged */ +DECLARE_KEEP_PAGER(mobj_reg_shm_get_cookie); +DECLARE_KEEP_PAGER(mobj_reg_shm_matches); +DECLARE_KEEP_PAGER(mobj_reg_shm_free); +#endif + +static bool mobj_reg_shm_matches(struct mobj *mobj __maybe_unused, + enum buf_is_attr attr) +{ + assert(mobj->ops == &mobj_reg_shm_ops); + + return attr == CORE_MEM_NON_SEC || attr == CORE_MEM_REG_SHM; +} + +static struct mobj_reg_shm *to_mobj_reg_shm(struct mobj *mobj) +{ + assert(mobj->ops == &mobj_reg_shm_ops); + return container_of(mobj, struct mobj_reg_shm, mobj); +} + +struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages, + paddr_t page_offset, uint64_t cookie) +{ + struct mobj_reg_shm *mobj_reg_shm = NULL; + size_t i = 0; + uint32_t exceptions = 0; + size_t s = 0; + + if (!num_pages || page_offset >= SMALL_PAGE_SIZE) + return NULL; + + s = mobj_reg_shm_size(num_pages); + if (!s) + return NULL; + mobj_reg_shm = calloc(1, s); + if (!mobj_reg_shm) + return NULL; + + mobj_reg_shm->mobj.ops = &mobj_reg_shm_ops; + mobj_reg_shm->mobj.size = num_pages * SMALL_PAGE_SIZE - page_offset; + mobj_reg_shm->mobj.phys_granule = SMALL_PAGE_SIZE; + refcount_set(&mobj_reg_shm->mobj.refc, 1); + mobj_reg_shm->cookie = cookie; + mobj_reg_shm->guarded = true; + mobj_reg_shm->page_offset = page_offset; + memcpy(mobj_reg_shm->pages, pages, sizeof(*pages) * num_pages); + + /* Ensure loaded references match format and security constraints */ + for (i = 0; i < num_pages; i++) { + if (mobj_reg_shm->pages[i] & SMALL_PAGE_MASK) + goto err; + + /* Only Non-secure memory can be mapped there */ + if (!core_pbuf_is(CORE_MEM_NON_SEC, mobj_reg_shm->pages[i], + SMALL_PAGE_SIZE)) + goto err; + } + + exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); + SLIST_INSERT_HEAD(®_shm_list, mobj_reg_shm, next); + cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); + + return &mobj_reg_shm->mobj; +err: + free(mobj_reg_shm); + return NULL; +} + +void mobj_reg_shm_unguard(struct mobj *mobj) +{ + uint32_t exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); + + to_mobj_reg_shm(mobj)->guarded = false; + cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); +} + +static struct mobj_reg_shm *reg_shm_find_unlocked(uint64_t cookie) +{ + struct mobj_reg_shm *mobj_reg_shm = NULL; + + SLIST_FOREACH(mobj_reg_shm, ®_shm_list, next) + if (mobj_reg_shm->cookie == cookie) + return mobj_reg_shm; + + return NULL; +} + +struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie) +{ + uint32_t exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); + struct mobj_reg_shm *r = reg_shm_find_unlocked(cookie); + + cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); + if (!r) + return NULL; + + return mobj_get(&r->mobj); +} + +TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie) +{ + uint32_t exceptions = 0; + struct mobj_reg_shm *r = NULL; + + /* + * Try to find r and see can be released by this function, if so + * call mobj_put(). Otherwise this function is called either by + * wrong cookie and perhaps a second time, regardless return + * TEE_ERROR_BAD_PARAMETERS. + */ + exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); + r = reg_shm_find_unlocked(cookie); + if (!r || r->guarded || r->releasing) + r = NULL; + else + r->releasing = true; + + cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); + + if (!r) + return TEE_ERROR_BAD_PARAMETERS; + + mobj_put(&r->mobj); + + /* + * We've established that this function can release the cookie. + * Now we wait until mobj_reg_shm_free() is called by the last + * mobj_put() needed to free this mobj. Note that the call to + * mobj_put() above could very well be that call. + * + * Once mobj_reg_shm_free() is called it will set r->release_frees + * to true and we can free the mobj here. + */ + mutex_lock(&shm_mu); + shm_release_waiters++; + assert(shm_release_waiters); + + while (true) { + exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); + if (r->release_frees) { + reg_shm_free_helper(r); + r = NULL; + } + cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); + + if (!r) + break; + condvar_wait(&shm_cv, &shm_mu); + } + + assert(shm_release_waiters); + shm_release_waiters--; + mutex_unlock(&shm_mu); + + return TEE_SUCCESS; +} + +struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages, + paddr_t page_offset, uint64_t cookie) +{ + struct mobj *mobj = mobj_reg_shm_alloc(pages, num_pages, + page_offset, cookie); + + if (!mobj) + return NULL; + + if (mobj_inc_map(mobj)) { + mobj_put(mobj); + return NULL; + } + + return mobj; +} + +static TEE_Result mobj_mapped_shm_init(void) +{ + vaddr_t pool_start = 0; + vaddr_t pool_end = 0; + + core_mmu_get_mem_by_type(MEM_AREA_SHM_VASPACE, &pool_start, &pool_end); + if (!pool_start || !pool_end) + panic("Can't find region for shmem pool"); + + if (!tee_mm_init(&tee_mm_shm, pool_start, pool_end - pool_start, + SMALL_PAGE_SHIFT, TEE_MM_POOL_NO_FLAGS)) + panic("Could not create shmem pool"); + + DMSG("Shared memory address range: %" PRIxVA ", %" PRIxVA, + pool_start, pool_end); + return TEE_SUCCESS; +} + +preinit(mobj_mapped_shm_init); diff --git a/optee/optee_os/core/arch/arm/mm/mobj_ffa.c b/optee/optee_os/core/arch/arm/mm/mobj_ffa.c new file mode 100644 index 0000000..ffb0778 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/mobj_ffa.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mobj_ffa { + struct mobj mobj; + SLIST_ENTRY(mobj_ffa) link; + uint64_t cookie; + tee_mm_entry_t *mm; + struct refcount mapcount; + uint16_t page_offset; +#ifdef CFG_CORE_SEL1_SPMC + bool registered_by_cookie; + bool unregistered_by_cookie; +#endif + paddr_t pages[]; +}; + +SLIST_HEAD(mobj_ffa_head, mobj_ffa); + +#ifdef CFG_CORE_SEL1_SPMC +#define NUM_SHMS 64 +static bitstr_t bit_decl(shm_bits, NUM_SHMS); +#endif + +static struct mobj_ffa_head shm_head = SLIST_HEAD_INITIALIZER(shm_head); +static struct mobj_ffa_head shm_inactive_head = + SLIST_HEAD_INITIALIZER(shm_inactive_head); + +static unsigned int shm_lock = SPINLOCK_UNLOCK; + +static const struct mobj_ops mobj_ffa_ops; + +static struct mobj_ffa *to_mobj_ffa(struct mobj *mobj) +{ + assert(mobj->ops == &mobj_ffa_ops); + return container_of(mobj, struct mobj_ffa, mobj); +} + +static size_t shm_size(size_t num_pages) +{ + size_t s = 0; + + if (MUL_OVERFLOW(sizeof(paddr_t), num_pages, &s)) + return 0; + if (ADD_OVERFLOW(sizeof(struct mobj_ffa), s, &s)) + return 0; + return s; +} + +static struct mobj_ffa *ffa_new(unsigned int num_pages) +{ + struct mobj_ffa *mf = NULL; + size_t s = 0; + + if (!num_pages) + return NULL; + + s = shm_size(num_pages); + if (!s) + return NULL; + mf = calloc(1, s); + if (!mf) + return NULL; + + mf->mobj.ops = &mobj_ffa_ops; + mf->mobj.size = num_pages * SMALL_PAGE_SIZE; + mf->mobj.phys_granule = SMALL_PAGE_SIZE; + refcount_set(&mf->mobj.refc, 0); + + return mf; +} + +#ifdef CFG_CORE_SEL1_SPMC +struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages) +{ + struct mobj_ffa *mf = NULL; + uint32_t exceptions = 0; + int i = 0; + + mf = ffa_new(num_pages); + if (!mf) + return NULL; + + exceptions = cpu_spin_lock_xsave(&shm_lock); + bit_ffc(shm_bits, NUM_SHMS, &i); + if (i != -1) { + bit_set(shm_bits, i); + /* + * Setting bit 44 to use one of the upper 32 bits too for + * testing. + */ + mf->cookie = i | FFA_MEMORY_HANDLE_NONE_SECURE_BIT; + + } + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + + if (i == -1) { + free(mf); + return NULL; + } + + return mf; +} +#endif /*CFG_CORE_SEL1_SPMC*/ + +static size_t get_page_count(struct mobj_ffa *mf) +{ + return ROUNDUP(mf->mobj.size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; +} + +static bool cmp_cookie(struct mobj_ffa *mf, uint64_t cookie) +{ + return mf->cookie == cookie; +} + +static bool cmp_ptr(struct mobj_ffa *mf, uint64_t ptr) +{ + return mf == (void *)(vaddr_t)ptr; +} + +static struct mobj_ffa *pop_from_list(struct mobj_ffa_head *head, + bool (*cmp_func)(struct mobj_ffa *mf, + uint64_t val), + uint64_t val) +{ + struct mobj_ffa *mf = SLIST_FIRST(head); + struct mobj_ffa *p = NULL; + + if (!mf) + return NULL; + + if (cmp_func(mf, val)) { + SLIST_REMOVE_HEAD(head, link); + return mf; + } + + while (true) { + p = SLIST_NEXT(mf, link); + if (!p) + return NULL; + if (cmp_func(p, val)) { + SLIST_REMOVE_AFTER(mf, link); + return p; + } + mf = p; + } +} + +static struct mobj_ffa *find_in_list(struct mobj_ffa_head *head, + bool (*cmp_func)(struct mobj_ffa *mf, + uint64_t val), + uint64_t val) +{ + struct mobj_ffa *mf = NULL; + + SLIST_FOREACH(mf, head, link) + if (cmp_func(mf, val)) + return mf; + + return NULL; +} + +#if defined(CFG_CORE_SEL1_SPMC) +void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mf) +{ + int i = mf->cookie & ~BIT64(44); + uint32_t exceptions = 0; + + assert(i >= 0 && i < NUM_SHMS); + + exceptions = cpu_spin_lock_xsave(&shm_lock); + assert(bit_test(shm_bits, i)); + bit_clear(shm_bits, i); + assert(!mf->mm); + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + + free(mf); +} +#else /* !defined(CFG_CORE_SEL1_SPMC) */ +struct mobj_ffa *mobj_ffa_spmc_new(uint64_t cookie, unsigned int num_pages) +{ + struct mobj_ffa *mf = NULL; + + assert(cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID); + mf = ffa_new(num_pages); + if (mf) + mf->cookie = cookie; + return mf; +} + +void mobj_ffa_spmc_delete(struct mobj_ffa *mf) +{ + free(mf); +} +#endif /* !defined(CFG_CORE_SEL1_SPMC) */ + +TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mf, unsigned int *idx, + paddr_t pa, unsigned int num_pages) +{ + unsigned int n = 0; + size_t tot_page_count = get_page_count(mf); + + if (ADD_OVERFLOW(*idx, num_pages, &n) || n > tot_page_count) + return TEE_ERROR_BAD_PARAMETERS; + + if (!IS_ENABLED(CFG_CORE_SEL2_SPMC) && + !core_pbuf_is(CORE_MEM_NON_SEC, pa, num_pages * SMALL_PAGE_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + + for (n = 0; n < num_pages; n++) + mf->pages[n + *idx] = pa + n * SMALL_PAGE_SIZE; + + (*idx) += n; + return TEE_SUCCESS; +} + +uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mf) +{ + return mf->cookie; +} + +uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mf) +{ + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&shm_lock); + assert(!find_in_list(&shm_inactive_head, cmp_ptr, (vaddr_t)mf)); + assert(!find_in_list(&shm_inactive_head, cmp_cookie, mf->cookie)); + assert(!find_in_list(&shm_head, cmp_cookie, mf->cookie)); + SLIST_INSERT_HEAD(&shm_inactive_head, mf, link); + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + + return mf->cookie; +} + +static void unmap_helper(struct mobj_ffa *mf) +{ + if (mf->mm) { + core_mmu_unmap_pages(tee_mm_get_smem(mf->mm), + get_page_count(mf)); + tee_mm_free(mf->mm); + mf->mm = NULL; + } +} + +#ifdef CFG_CORE_SEL1_SPMC +TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie) +{ + TEE_Result res = TEE_SUCCESS; + struct mobj_ffa *mf = NULL; + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&shm_lock); + mf = find_in_list(&shm_head, cmp_cookie, cookie); + /* + * If the mobj is found here it's still active and cannot be + * reclaimed. + */ + if (mf) { + DMSG("cookie %#"PRIx64" busy refc %u", + cookie, refcount_val(&mf->mobj.refc)); + res = TEE_ERROR_BUSY; + goto out; + } + + mf = find_in_list(&shm_inactive_head, cmp_cookie, cookie); + if (!mf) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto out; + } + /* + * If the mobj has been registered via mobj_ffa_get_by_cookie() + * but not unregistered yet with mobj_ffa_unregister_by_cookie(). + */ + if (mf->registered_by_cookie && !mf->unregistered_by_cookie) { + DMSG("cookie %#"PRIx64" busy", cookie); + res = TEE_ERROR_BUSY; + goto out; + } + + if (!pop_from_list(&shm_inactive_head, cmp_ptr, (vaddr_t)mf)) + panic(); + res = TEE_SUCCESS; +out: + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + if (!res) + mobj_ffa_sel1_spmc_delete(mf); + return res; +} +#endif /*CFG_CORE_SEL1_SPMC*/ + +TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie) +{ + TEE_Result res = TEE_SUCCESS; + struct mobj_ffa *mf = NULL; + uint32_t exceptions = 0; + + assert(cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID); + exceptions = cpu_spin_lock_xsave(&shm_lock); + mf = find_in_list(&shm_head, cmp_cookie, cookie); + /* + * If the mobj is found here it's still active and cannot be + * unregistered. + */ + if (mf) { + DMSG("cookie %#"PRIx64" busy refc %u", + cookie, refcount_val(&mf->mobj.refc)); + res = TEE_ERROR_BUSY; + goto out; + } + mf = find_in_list(&shm_inactive_head, cmp_cookie, cookie); + /* + * If the mobj isn't found or if it already has been unregistered. + */ +#if defined(CFG_CORE_SEL1_SPMC) + if (!mf || mf->unregistered_by_cookie) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto out; + } + mf->unregistered_by_cookie = true; +#else + if (!mf) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto out; + } + mf = pop_from_list(&shm_inactive_head, cmp_cookie, cookie); + mobj_ffa_spmc_delete(mf); + thread_spmc_relinquish(cookie); +#endif + res = TEE_SUCCESS; + +out: + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + return res; +} + +struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, + unsigned int internal_offs) +{ + struct mobj_ffa *mf = NULL; + uint32_t exceptions = 0; + + if (internal_offs >= SMALL_PAGE_SIZE) + return NULL; + exceptions = cpu_spin_lock_xsave(&shm_lock); + mf = find_in_list(&shm_head, cmp_cookie, cookie); + if (mf) { + if (mf->page_offset == internal_offs) { + if (!refcount_inc(&mf->mobj.refc)) { + /* + * If refcount is 0 some other thread has + * called mobj_put() on this reached 0 and + * before ffa_inactivate() got the lock we + * found it. Let's reinitialize it. + */ + refcount_set(&mf->mobj.refc, 1); + } + DMSG("cookie %#"PRIx64" active: refc %d", + cookie, refcount_val(&mf->mobj.refc)); + } else { + EMSG("cookie %#"PRIx64" mismatching internal_offs got %#"PRIx16" expected %#x", + cookie, mf->page_offset, internal_offs); + mf = NULL; + } + } else { + mf = pop_from_list(&shm_inactive_head, cmp_cookie, cookie); +#if !defined(CFG_CORE_SEL1_SPMC) + /* Try to retrieve it from the SPM at S-EL2 */ + if (mf) { + DMSG("cookie %#"PRIx64" resurrecting", cookie); + } else { + EMSG("Populating mobj from rx buffer, cookie %#"PRIx64, + cookie); + mf = thread_spmc_populate_mobj_from_rx(cookie); + } +#endif + if (mf) { +#if defined(CFG_CORE_SEL1_SPMC) + mf->unregistered_by_cookie = false; + mf->registered_by_cookie = true; +#endif + assert(refcount_val(&mf->mobj.refc) == 0); + refcount_set(&mf->mobj.refc, 1); + refcount_set(&mf->mapcount, 0); + + /* + * mf->page_offset is offset into the first page. + * This offset is assigned from the internal_offs + * parameter to this function. + * + * While a mobj_ffa is active (ref_count > 0) this + * will not change, but when being pushed to the + * inactive list it can be changed again. + * + * So below we're backing out the old + * mf->page_offset and then assigning a new from + * internal_offset. + */ + mf->mobj.size += mf->page_offset; + assert(!(mf->mobj.size & SMALL_PAGE_MASK)); + mf->mobj.size -= internal_offs; + mf->page_offset = internal_offs; + + SLIST_INSERT_HEAD(&shm_head, mf, link); + } + } + + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + + if (!mf) { + EMSG("Failed to get cookie %#"PRIx64" internal_offs %#x", + cookie, internal_offs); + return NULL; + } + return &mf->mobj; +} + +static TEE_Result ffa_get_pa(struct mobj *mobj, size_t offset, + size_t granule, paddr_t *pa) +{ + struct mobj_ffa *mf = to_mobj_ffa(mobj); + size_t full_offset = 0; + paddr_t p = 0; + + if (!pa) + return TEE_ERROR_GENERIC; + + if (offset >= mobj->size) + return TEE_ERROR_GENERIC; + + full_offset = offset + mf->page_offset; + switch (granule) { + case 0: + p = mf->pages[full_offset / SMALL_PAGE_SIZE] + + (full_offset & SMALL_PAGE_MASK); + break; + case SMALL_PAGE_SIZE: + p = mf->pages[full_offset / SMALL_PAGE_SIZE]; + break; + default: + return TEE_ERROR_GENERIC; + } + *pa = p; + + return TEE_SUCCESS; +} + +static size_t ffa_get_phys_offs(struct mobj *mobj, + size_t granule __maybe_unused) +{ + assert(granule >= mobj->phys_granule); + + return to_mobj_ffa(mobj)->page_offset; +} + +static void *ffa_get_va(struct mobj *mobj, size_t offset, size_t len) +{ + struct mobj_ffa *mf = to_mobj_ffa(mobj); + + if (!mf->mm || !mobj_check_offset_and_len(mobj, offset, len)) + return NULL; + + return (void *)(tee_mm_get_smem(mf->mm) + offset + mf->page_offset); +} + +static void ffa_inactivate(struct mobj *mobj) +{ + struct mobj_ffa *mf = to_mobj_ffa(mobj); + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&shm_lock); + /* + * If refcount isn't 0 some other thread has found this mobj in + * shm_head after the mobj_put() that put us here and before we got + * the lock. + */ + if (refcount_val(&mobj->refc)) { + DMSG("cookie %#"PRIx64" was resurrected", mf->cookie); + goto out; + } + + DMSG("cookie %#"PRIx64, mf->cookie); + if (!pop_from_list(&shm_head, cmp_ptr, (vaddr_t)mf)) + panic(); + unmap_helper(mf); + SLIST_INSERT_HEAD(&shm_inactive_head, mf, link); +out: + cpu_spin_unlock_xrestore(&shm_lock, exceptions); +} + +static TEE_Result ffa_get_mem_type(struct mobj *mobj __unused, uint32_t *mt) +{ + if (!mt) + return TEE_ERROR_GENERIC; + + *mt = TEE_MATTR_MEM_TYPE_CACHED; + + return TEE_SUCCESS; +} + +static bool ffa_matches(struct mobj *mobj __maybe_unused, enum buf_is_attr attr) +{ + assert(mobj->ops == &mobj_ffa_ops); + + return attr == CORE_MEM_NON_SEC || attr == CORE_MEM_REG_SHM; +} + +static uint64_t ffa_get_cookie(struct mobj *mobj) +{ + return to_mobj_ffa(mobj)->cookie; +} + +static TEE_Result ffa_inc_map(struct mobj *mobj) +{ + TEE_Result res = TEE_SUCCESS; + struct mobj_ffa *mf = to_mobj_ffa(mobj); + uint32_t exceptions = 0; + size_t sz = 0; + + while (true) { + if (refcount_inc(&mf->mapcount)) + return TEE_SUCCESS; + + exceptions = cpu_spin_lock_xsave(&shm_lock); + + if (!refcount_val(&mf->mapcount)) + break; /* continue to reinitialize */ + /* + * If another thread beat us to initialize mapcount, + * restart to make sure we still increase it. + */ + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + } + + /* + * If we have beated another thread calling ffa_dec_map() + * to get the lock we need only to reinitialize mapcount to 1. + */ + if (!mf->mm) { + sz = ROUNDUP(mobj->size + mf->page_offset, SMALL_PAGE_SIZE); + mf->mm = tee_mm_alloc(&tee_mm_shm, sz); + if (!mf->mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = core_mmu_map_pages(tee_mm_get_smem(mf->mm), mf->pages, + sz / SMALL_PAGE_SIZE, + MEM_AREA_NSEC_SHM); + if (res) { + tee_mm_free(mf->mm); + mf->mm = NULL; + goto out; + } + } + + refcount_set(&mf->mapcount, 1); +out: + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + + return res; +} + +static TEE_Result ffa_dec_map(struct mobj *mobj) +{ + struct mobj_ffa *mf = to_mobj_ffa(mobj); + uint32_t exceptions = 0; + + if (!refcount_dec(&mf->mapcount)) + return TEE_SUCCESS; + + exceptions = cpu_spin_lock_xsave(&shm_lock); + if (!refcount_val(&mf->mapcount)) + unmap_helper(mf); + cpu_spin_unlock_xrestore(&shm_lock, exceptions); + + return TEE_SUCCESS; +} + +static TEE_Result mapped_shm_init(void) +{ + vaddr_t pool_start = 0; + vaddr_t pool_end = 0; + + core_mmu_get_mem_by_type(MEM_AREA_SHM_VASPACE, &pool_start, &pool_end); + if (!pool_start || !pool_end) + panic("Can't find region for shmem pool"); + + if (!tee_mm_init(&tee_mm_shm, pool_start, pool_end - pool_start, + SMALL_PAGE_SHIFT, + TEE_MM_POOL_NO_FLAGS)) + panic("Could not create shmem pool"); + + DMSG("Shared memory address range: %#"PRIxVA", %#"PRIxVA, + pool_start, pool_end); + return TEE_SUCCESS; +} + +static const struct mobj_ops mobj_ffa_ops = { + .get_pa = ffa_get_pa, + .get_phys_offs = ffa_get_phys_offs, + .get_va = ffa_get_va, + .get_mem_type = ffa_get_mem_type, + .matches = ffa_matches, + .free = ffa_inactivate, + .get_cookie = ffa_get_cookie, + .inc_map = ffa_inc_map, + .dec_map = ffa_dec_map, +}; + +preinit(mapped_shm_init); diff --git a/optee/optee_os/core/arch/arm/mm/pgt_cache.c b/optee/optee_os/core/arch/arm/mm/pgt_cache.c new file mode 100644 index 0000000..79553c6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/pgt_cache.c @@ -0,0 +1,873 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, 2022 Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * With pager enabled we allocate page table from the pager. + * + * For LPAE each page table is a complete page which is allocated and freed + * using the interface provided by the pager. + * + * For compat v7 page tables there's room for four page table in one page + * so we need to keep track of how much of an allocated page is used. When + * a page is completely unused it's returned to the pager. + * + * With pager disabled we have a static allocation of page tables instead. + * + * In all cases we limit the number of active page tables to + * PGT_CACHE_SIZE. This pool of page tables are shared between all + * threads. In case a thread can't allocate the needed number of pager + * tables it will release all its current tables and wait for some more to + * be freed. A threads allocated tables are freed each time a TA is + * unmapped so each thread should be able to allocate the needed tables in + * turn if needed. + */ + +#if defined(CFG_CORE_PREALLOC_EL0_TBLS) || \ + (defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE)) +struct pgt_parent { + size_t num_used; + struct pgt_cache pgt_cache; +#if defined(CFG_CORE_PREALLOC_EL0_TBLS) + tee_mm_entry_t *mm; + SLIST_ENTRY(pgt_parent) link; +#endif +}; +#endif + +#if defined(CFG_CORE_PREALLOC_EL0_TBLS) + +/* + * Pick something large enough that tee_mm_alloc() doesn't have to be + * called for each needed translation table. + */ +#define PGT_PARENT_SIZE (4 * SMALL_PAGE_SIZE) +#define PGT_PARENT_TBL_COUNT (PGT_PARENT_SIZE / PGT_SIZE) + +SLIST_HEAD(pgt_parent_list, pgt_parent); +static struct pgt_parent_list parent_list = SLIST_HEAD_INITIALIZER(parent_list); +static unsigned int parent_spinlock = SPINLOCK_UNLOCK; + +static void free_pgt(struct pgt *pgt) +{ + struct pgt_parent *parent = NULL; + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&parent_spinlock); + + assert(pgt && pgt->parent); + parent = pgt->parent; + assert(parent->num_used <= PGT_PARENT_TBL_COUNT && + parent->num_used > 0); + if (parent->num_used == PGT_PARENT_TBL_COUNT) + SLIST_INSERT_HEAD(&parent_list, parent, link); + parent->num_used--; + + if (!parent->num_used && SLIST_NEXT(SLIST_FIRST(&parent_list), link)) { + /* + * If this isn't the last pgt_parent with free entries we + * can free this. + */ + SLIST_REMOVE(&parent_list, parent, pgt_parent, link); + tee_mm_free(parent->mm); + free(parent); + } else { + SLIST_INSERT_HEAD(&parent->pgt_cache, pgt, link); + pgt->vabase = 0; + pgt->populated = false; + } + + cpu_spin_unlock_xrestore(&parent_spinlock, exceptions); +} + +static struct pgt_parent *alloc_pgt_parent(void) +{ + struct pgt_parent *parent = NULL; + struct pgt *pgt = NULL; + uint8_t *tbl = NULL; + size_t sz = 0; + size_t n = 0; + + sz = sizeof(*parent) + sizeof(*pgt) * PGT_PARENT_TBL_COUNT; + parent = calloc(1, sz); + if (!parent) + return NULL; + parent->mm = tee_mm_alloc(&tee_mm_sec_ddr, PGT_PARENT_SIZE); + if (!parent->mm) { + free(parent); + return NULL; + } + tbl = phys_to_virt(tee_mm_get_smem(parent->mm), MEM_AREA_TA_RAM, + PGT_PARENT_SIZE); + assert(tbl); /* "can't fail" */ + + SLIST_INIT(&parent->pgt_cache); + pgt = (struct pgt *)(parent + 1); + for (n = 0; n < PGT_PARENT_TBL_COUNT; n++) { + pgt[n].parent = parent; + pgt[n].tbl = tbl + n * PGT_SIZE; + SLIST_INSERT_HEAD(&parent->pgt_cache, pgt + n, link); + } + + return parent; +} + +static struct pgt *alloc_pgt(vaddr_t vabase) +{ + struct pgt_parent *parent = NULL; + uint32_t exceptions = 0; + struct pgt *pgt = NULL; + + exceptions = cpu_spin_lock_xsave(&parent_spinlock); + + parent = SLIST_FIRST(&parent_list); + if (!parent) { + parent = alloc_pgt_parent(); + if (!parent) + goto out; + + SLIST_INSERT_HEAD(&parent_list, parent, link); + } + + pgt = SLIST_FIRST(&parent->pgt_cache); + SLIST_REMOVE_HEAD(&parent->pgt_cache, link); + parent->num_used++; + assert(pgt && parent->num_used <= PGT_PARENT_TBL_COUNT); + if (parent->num_used == PGT_PARENT_TBL_COUNT) + SLIST_REMOVE_HEAD(&parent_list, link); + + pgt->vabase = vabase; +out: + cpu_spin_unlock_xrestore(&parent_spinlock, exceptions); + return pgt; +} + +static bool pgt_entry_matches(struct pgt *p, vaddr_t begin, vaddr_t last) +{ + if (!p) + return false; + if (last <= begin) + return false; + return core_is_buffer_inside(p->vabase, CORE_MMU_PGDIR_SIZE, begin, + last - begin); +} + +void pgt_flush_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t last) +{ + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + struct pgt *next_p = NULL; + struct pgt *p = NULL; + + /* + * Do the special case where the first element in the list is + * removed first. + */ + p = SLIST_FIRST(pgt_cache); + while (pgt_entry_matches(p, begin, last)) { + SLIST_REMOVE_HEAD(pgt_cache, link); + free_pgt(p); + p = SLIST_FIRST(pgt_cache); + } + + /* + * p either points to the first element in the list or it's NULL, + * if NULL the list is empty and we're done. + */ + if (!p) + return; + + /* + * Do the common case where the next element in the list is + * removed. + */ + while (true) { + next_p = SLIST_NEXT(p, link); + if (!next_p) + break; + if (pgt_entry_matches(next_p, begin, last)) { + SLIST_REMOVE_AFTER(p, link); + free_pgt(next_p); + continue; + } + + p = SLIST_NEXT(p, link); + } +} + +void pgt_flush(struct user_mode_ctx *uctx) +{ + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + struct pgt *p = NULL; + + while (true) { + p = SLIST_FIRST(pgt_cache); + if (!p) + break; + SLIST_REMOVE_HEAD(pgt_cache, link); + free_pgt(p); + } +} + +void pgt_clear_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t end) +{ + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + struct pgt *p = NULL; +#ifdef CFG_WITH_LPAE + uint64_t *tbl = NULL; +#else + uint32_t *tbl = NULL; +#endif + unsigned int idx = 0; + unsigned int n = 0; + + SLIST_FOREACH(p, pgt_cache, link) { + vaddr_t b = MAX(p->vabase, begin); + vaddr_t e = MIN(p->vabase + CORE_MMU_PGDIR_SIZE, end); + + if (b >= e) + continue; + + tbl = p->tbl; + idx = (b - p->vabase) / SMALL_PAGE_SIZE; + n = (e - b) / SMALL_PAGE_SIZE; + memset(tbl + idx, 0, n * sizeof(*tbl)); + } +} + +static struct pgt *prune_before_va(struct pgt_cache *pgt_cache, struct pgt *p, + struct pgt *pp, vaddr_t va) +{ + while (p && p->vabase < va) { + if (pp) { + assert(p == SLIST_NEXT(pp, link)); + SLIST_REMOVE_AFTER(pp, link); + free_pgt(p); + p = SLIST_NEXT(pp, link); + } else { + assert(p == SLIST_FIRST(pgt_cache)); + SLIST_REMOVE_HEAD(pgt_cache, link); + free_pgt(p); + p = SLIST_FIRST(pgt_cache); + } + } + + return p; +} + +bool pgt_check_avail(struct user_mode_ctx *uctx) +{ + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + struct vm_info *vm_info = &uctx->vm_info; + struct pgt *p = SLIST_FIRST(pgt_cache); + struct vm_region *r = NULL; + struct pgt *pp = NULL; + vaddr_t va = 0; + bool p_used = false; + + /* + * Prune unused tables. This is normally not needed since + * pgt_flush_range() does this too, but in the error path of for + * instance vm_remap() such calls may not be done. So for increased + * robustness remove all unused translation tables before we may + * allocate new ones. + */ + TAILQ_FOREACH(r, &vm_info->regions, link) { + for (va = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); + va < r->va + r->size; va += CORE_MMU_PGDIR_SIZE) { + if (!p_used) + p = prune_before_va(pgt_cache, p, pp, va); + if (!p) + goto prune_done; + + if (p->vabase < va) { + pp = p; + p = SLIST_NEXT(pp, link); + if (!p) + goto prune_done; + p_used = false; + } + + if (p->vabase == va) + p_used = true; + } + } +prune_done: + + p = SLIST_FIRST(pgt_cache); + pp = NULL; + TAILQ_FOREACH(r, &vm_info->regions, link) { + for (va = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); + va < r->va + r->size; va += CORE_MMU_PGDIR_SIZE) { + if (p && p->vabase < va) { + pp = p; + p = SLIST_NEXT(pp, link); + } + + if (p) { + if (p->vabase == va) + continue; + assert(p->vabase > va); + } + + p = alloc_pgt(va); + if (!p) + return false; + + if (pp) + SLIST_INSERT_AFTER(pp, p, link); + else + SLIST_INSERT_HEAD(pgt_cache, p, link); + } + } + + return true; +} +#else /* !CFG_CORE_PREALLOC_EL0_TBLS */ + +#if defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE) +static struct pgt_parent pgt_parents[PGT_CACHE_SIZE / PGT_NUM_PGT_PER_PAGE]; +#else + +static struct pgt_cache pgt_free_list = SLIST_HEAD_INITIALIZER(pgt_free_list); +#endif + +/* + * When a user TA context is temporarily unmapped the used struct pgt's of + * the context (page tables holding valid physical pages) are saved in this + * cache in the hope that it will remain in the cache when the context is + * mapped again. + */ +static struct pgt_cache pgt_cache_list = SLIST_HEAD_INITIALIZER(pgt_cache_list); + +static struct pgt pgt_entries[PGT_CACHE_SIZE]; + +static struct mutex pgt_mu = MUTEX_INITIALIZER; +static struct condvar pgt_cv = CONDVAR_INITIALIZER; + +#if defined(CFG_WITH_PAGER) && defined(CFG_WITH_LPAE) +/* + * Simple allocation of translation tables from pager, one translation + * table is one page. + */ +void pgt_init(void) +{ + size_t n; + + for (n = 0; n < PGT_CACHE_SIZE; n++) { + struct pgt *p = pgt_entries + n; + + p->tbl = tee_pager_alloc(PGT_SIZE); + SLIST_INSERT_HEAD(&pgt_free_list, p, link); + } +} +#elif defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE) +/* + * Four translation tables per page -> need to keep track of the page + * allocated from the pager. + */ +void pgt_init(void) +{ + size_t n; + size_t m; + + COMPILE_TIME_ASSERT(PGT_CACHE_SIZE % PGT_NUM_PGT_PER_PAGE == 0); + COMPILE_TIME_ASSERT(PGT_SIZE * PGT_NUM_PGT_PER_PAGE == SMALL_PAGE_SIZE); + + for (n = 0; n < ARRAY_SIZE(pgt_parents); n++) { + uint8_t *tbl = tee_pager_alloc(SMALL_PAGE_SIZE); + + SLIST_INIT(&pgt_parents[n].pgt_cache); + for (m = 0; m < PGT_NUM_PGT_PER_PAGE; m++) { + struct pgt *p = pgt_entries + + n * PGT_NUM_PGT_PER_PAGE + m; + + p->tbl = tbl + m * PGT_SIZE; + p->parent = &pgt_parents[n]; + SLIST_INSERT_HEAD(&pgt_parents[n].pgt_cache, p, link); + } + } +} +#else +/* Static allocation of translation tables */ +void pgt_init(void) +{ + /* + * We're putting this in .nozi.* instead of .bss because .nozi.* already + * has a large alignment, while .bss has a small alignment. The current + * link script is optimized for small alignment in .bss + */ + static uint8_t pgt_tables[PGT_CACHE_SIZE][PGT_SIZE] + __aligned(PGT_SIZE) __section(".nozi.pgt_cache"); + size_t n; + + for (n = 0; n < ARRAY_SIZE(pgt_tables); n++) { + struct pgt *p = pgt_entries + n; + + p->tbl = pgt_tables[n]; + SLIST_INSERT_HEAD(&pgt_free_list, p, link); + } +} +#endif + +#if defined(CFG_WITH_LPAE) || !defined(CFG_WITH_PAGER) +/* Simple allocation of translation tables from pager or static allocation */ +static struct pgt *pop_from_free_list(void) +{ + struct pgt *p = SLIST_FIRST(&pgt_free_list); + + if (p) { + SLIST_REMOVE_HEAD(&pgt_free_list, link); + memset(p->tbl, 0, PGT_SIZE); + p->populated = false; + } + return p; +} + +static void push_to_free_list(struct pgt *p) +{ + SLIST_INSERT_HEAD(&pgt_free_list, p, link); +#if defined(CFG_WITH_PAGER) + tee_pager_release_phys(p->tbl, PGT_SIZE); +#endif +} +#else +/* + * Four translation tables per page -> need to keep track of the page + * allocated from the pager. + */ +static struct pgt *pop_from_free_list(void) +{ + size_t n; + + for (n = 0; n < ARRAY_SIZE(pgt_parents); n++) { + struct pgt *p = SLIST_FIRST(&pgt_parents[n].pgt_cache); + + if (p) { + SLIST_REMOVE_HEAD(&pgt_parents[n].pgt_cache, link); + pgt_parents[n].num_used++; + memset(p->tbl, 0, PGT_SIZE); + p->populated = false; + return p; + } + } + return NULL; +} + +static void push_to_free_list(struct pgt *p) +{ + SLIST_INSERT_HEAD(&p->parent->pgt_cache, p, link); + assert(p->parent->num_used > 0); + p->parent->num_used--; + if (!p->parent->num_used) { + vaddr_t va = (vaddr_t)p->tbl & ~SMALL_PAGE_MASK; + + tee_pager_release_phys((void *)va, SMALL_PAGE_SIZE); + } +} +#endif + +static void push_to_cache_list(struct pgt *pgt) +{ + SLIST_INSERT_HEAD(&pgt_cache_list, pgt, link); +} + +static bool match_pgt(struct pgt *pgt, vaddr_t vabase, void *ctx) +{ + return pgt->ctx == ctx && pgt->vabase == vabase; +} + +static struct pgt *pop_from_cache_list(vaddr_t vabase, void *ctx) +{ + struct pgt *pgt; + struct pgt *p; + + pgt = SLIST_FIRST(&pgt_cache_list); + if (!pgt) + return NULL; + if (match_pgt(pgt, vabase, ctx)) { + SLIST_REMOVE_HEAD(&pgt_cache_list, link); + return pgt; + } + + while (true) { + p = SLIST_NEXT(pgt, link); + if (!p) + break; + if (match_pgt(p, vabase, ctx)) { + SLIST_REMOVE_AFTER(pgt, link); + break; + } + pgt = p; + } + return p; +} + +static uint16_t get_num_used_entries(struct pgt *pgt __maybe_unused) +{ +#ifdef CFG_PAGED_USER_TA + return pgt->num_used_entries; +#else + return 0; +#endif +} + +static struct pgt *pop_least_used_from_cache_list(void) +{ + struct pgt *pgt = NULL; + struct pgt *p_prev = NULL; + size_t least_used = 0; + size_t next_used = 0; + + pgt = SLIST_FIRST(&pgt_cache_list); + if (!pgt) + return NULL; + least_used = get_num_used_entries(pgt); + + while (true) { + if (!SLIST_NEXT(pgt, link)) + break; + next_used = get_num_used_entries(SLIST_NEXT(pgt, link)); + if (next_used <= least_used) { + p_prev = pgt; + least_used = next_used; + } + pgt = SLIST_NEXT(pgt, link); + } + + if (p_prev) { + pgt = SLIST_NEXT(p_prev, link); + SLIST_REMOVE_AFTER(p_prev, link); + } else { + pgt = SLIST_FIRST(&pgt_cache_list); + SLIST_REMOVE_HEAD(&pgt_cache_list, link); + } + return pgt; +} + +static void pgt_free_unlocked(struct pgt_cache *pgt_cache) +{ + while (!SLIST_EMPTY(pgt_cache)) { + struct pgt *p = SLIST_FIRST(pgt_cache); + + SLIST_REMOVE_HEAD(pgt_cache, link); + + /* + * With paging enabled we free all tables which doesn't + * refer to any paged pages any longer. This reduces the + * pressure the pool of physical pages. + */ + if (IS_ENABLED(CFG_PAGED_USER_TA) && !get_num_used_entries(p)) { + tee_pager_pgt_save_and_release_entries(p); + p->ctx = NULL; + p->vabase = 0; + + push_to_free_list(p); + continue; + } + + push_to_cache_list(p); + } +} + +static struct pgt *pop_from_some_list(vaddr_t vabase, void *ctx) +{ + struct pgt *p = pop_from_cache_list(vabase, ctx); + + if (p) + return p; + p = pop_from_free_list(); + if (!p) { + p = pop_least_used_from_cache_list(); + if (!p) + return NULL; + tee_pager_pgt_save_and_release_entries(p); + memset(p->tbl, 0, PGT_SIZE); + p->populated = false; + } + p->ctx = ctx; + p->vabase = vabase; + return p; +} + +void pgt_flush(struct user_mode_ctx *uctx) +{ + struct ts_ctx *ctx = uctx->ts_ctx; + struct pgt *pp = NULL; + struct pgt *p = NULL; + + mutex_lock(&pgt_mu); + + while (true) { + p = SLIST_FIRST(&pgt_cache_list); + if (!p) + goto out; + if (p->ctx != ctx) + break; + SLIST_REMOVE_HEAD(&pgt_cache_list, link); + tee_pager_pgt_save_and_release_entries(p); + p->ctx = NULL; + p->vabase = 0; + push_to_free_list(p); + } + + pp = p; + while (true) { + p = SLIST_NEXT(pp, link); + if (!p) + break; + if (p->ctx == ctx) { + SLIST_REMOVE_AFTER(pp, link); + tee_pager_pgt_save_and_release_entries(p); + p->ctx = NULL; + p->vabase = 0; + push_to_free_list(p); + } else { + pp = p; + } + } + +out: + mutex_unlock(&pgt_mu); +} + +static void flush_pgt_entry(struct pgt *p) +{ + tee_pager_pgt_save_and_release_entries(p); + p->ctx = NULL; + p->vabase = 0; +} + +static bool pgt_entry_matches(struct pgt *p, void *ctx, vaddr_t begin, + vaddr_t last) +{ + if (!p) + return false; + if (p->ctx != ctx) + return false; + if (last <= begin) + return false; + if (!core_is_buffer_inside(p->vabase, CORE_MMU_PGDIR_SIZE, begin, + last - begin)) + return false; + + return true; +} + +static void flush_ctx_range_from_list(struct pgt_cache *pgt_cache, void *ctx, + vaddr_t begin, vaddr_t last) +{ + struct pgt *p; + struct pgt *next_p; + + /* + * Do the special case where the first element in the list is + * removed first. + */ + p = SLIST_FIRST(pgt_cache); + while (pgt_entry_matches(p, ctx, begin, last)) { + flush_pgt_entry(p); + SLIST_REMOVE_HEAD(pgt_cache, link); + push_to_free_list(p); + p = SLIST_FIRST(pgt_cache); + } + + /* + * p either points to the first element in the list or it's NULL, + * if NULL the list is empty and we're done. + */ + if (!p) + return; + + /* + * Do the common case where the next element in the list is + * removed. + */ + while (true) { + next_p = SLIST_NEXT(p, link); + if (!next_p) + break; + if (pgt_entry_matches(next_p, ctx, begin, last)) { + flush_pgt_entry(next_p); + SLIST_REMOVE_AFTER(p, link); + push_to_free_list(next_p); + continue; + } + + p = SLIST_NEXT(p, link); + } +} + +void pgt_flush_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t last) +{ + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + struct ts_ctx *ctx = uctx->ts_ctx; + + mutex_lock(&pgt_mu); + + flush_ctx_range_from_list(pgt_cache, ctx, begin, last); + flush_ctx_range_from_list(&pgt_cache_list, ctx, begin, last); + + condvar_broadcast(&pgt_cv); + mutex_unlock(&pgt_mu); +} + +static void clear_ctx_range_from_list(struct pgt_cache *pgt_cache, + void *ctx, vaddr_t begin, vaddr_t end) +{ + struct pgt *p = NULL; +#ifdef CFG_WITH_LPAE + uint64_t *tbl = NULL; +#else + uint32_t *tbl = NULL; +#endif + unsigned int idx = 0; + unsigned int n = 0; + + SLIST_FOREACH(p, pgt_cache, link) { + vaddr_t b = MAX(p->vabase, begin); + vaddr_t e = MIN(p->vabase + CORE_MMU_PGDIR_SIZE, end); + + if (p->ctx != ctx) + continue; + if (b >= e) + continue; + + tbl = p->tbl; + idx = (b - p->vabase) / SMALL_PAGE_SIZE; + n = (e - b) / SMALL_PAGE_SIZE; + memset(tbl + idx, 0, n * sizeof(*tbl)); + } +} + +void pgt_clear_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t end) +{ + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + struct ts_ctx *ctx = uctx->ts_ctx; + + mutex_lock(&pgt_mu); + + clear_ctx_range_from_list(pgt_cache, ctx, begin, end); + clear_ctx_range_from_list(&pgt_cache_list, ctx, begin, end); + + mutex_unlock(&pgt_mu); +} + +static bool pgt_alloc_unlocked(struct pgt_cache *pgt_cache, struct ts_ctx *ctx, + struct vm_info *vm_info) +{ + struct vm_region *r = NULL; + struct pgt *pp = NULL; + struct pgt *p = NULL; + vaddr_t va = 0; + + TAILQ_FOREACH(r, &vm_info->regions, link) { + for (va = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); + va < r->va + r->size; va += CORE_MMU_PGDIR_SIZE) { + if (p && p->vabase == va) + continue; + p = pop_from_some_list(va, ctx); + if (!p) { + pgt_free_unlocked(pgt_cache); + return false; + } + if (pp) + SLIST_INSERT_AFTER(pp, p, link); + else + SLIST_INSERT_HEAD(pgt_cache, p, link); + pp = p; + } + } + + return true; +} + +bool pgt_check_avail(struct user_mode_ctx *uctx) +{ + struct vm_info *vm_info = &uctx->vm_info; + struct vm_region *r = NULL; + size_t tbl_count = 0; + vaddr_t last_va = 0; + vaddr_t va = 0; + + TAILQ_FOREACH(r, &vm_info->regions, link) { + for (va = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); + va < r->va + r->size; va += CORE_MMU_PGDIR_SIZE) { + if (va == last_va) + continue; + tbl_count++; + last_va = va; + } + } + + return tbl_count <= PGT_CACHE_SIZE; +} + +void pgt_get_all(struct user_mode_ctx *uctx) +{ + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + struct vm_info *vm_info = &uctx->vm_info; + + if (TAILQ_EMPTY(&vm_info->regions)) + return; + + mutex_lock(&pgt_mu); + + pgt_free_unlocked(pgt_cache); + while (!pgt_alloc_unlocked(pgt_cache, uctx->ts_ctx, vm_info)) { + assert(pgt_check_avail(uctx)); + DMSG("Waiting for page tables"); + condvar_broadcast(&pgt_cv); + condvar_wait(&pgt_cv, &pgt_mu); + } + + mutex_unlock(&pgt_mu); +} + +void pgt_put_all(struct user_mode_ctx *uctx) +{ + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + + if (SLIST_EMPTY(pgt_cache)) + return; + + mutex_lock(&pgt_mu); + + pgt_free_unlocked(pgt_cache); + + condvar_broadcast(&pgt_cv); + mutex_unlock(&pgt_mu); +} + +struct pgt *pgt_pop_from_cache_list(vaddr_t vabase, struct ts_ctx *ctx) +{ + struct pgt *pgt = NULL; + + mutex_lock(&pgt_mu); + pgt = pop_from_cache_list(vabase, ctx); + mutex_unlock(&pgt_mu); + + return pgt; +} + +void pgt_push_to_cache_list(struct pgt *pgt) +{ + mutex_lock(&pgt_mu); + push_to_cache_list(pgt); + mutex_unlock(&pgt_mu); +} + +#endif /* !CFG_CORE_PREALLOC_EL0_TBLS */ diff --git a/optee/optee_os/core/arch/arm/mm/sp_mem.c b/optee/optee_os/core/arch/arm/mm/sp_mem.c new file mode 100644 index 0000000..bdba730 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/sp_mem.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + */ +#include +#include +#include +#include +#include +#include + +#define NUM_SHARES 64 + +static bitstr_t bit_decl(share_bits, NUM_SHARES); +static unsigned int sp_mem_lock = SPINLOCK_UNLOCK; + +/* mem_shares stores all active FF-A shares. */ +SLIST_HEAD(sp_mem_head, sp_mem); +static struct sp_mem_head mem_shares = SLIST_HEAD_INITIALIZER(sp_mem_head); +static const struct mobj_ops mobj_sp_ops; + +struct mobj_sp { + struct mobj mobj; + uint32_t mem_type; + bool is_secure; + paddr_t pages[]; +}; + +static struct mobj_sp *to_mobj_sp(struct mobj *mobj) +{ + assert(mobj->ops == &mobj_sp_ops); + return container_of(mobj, struct mobj_sp, mobj); +} + +static size_t mobj_sp_size(size_t num_pages) +{ + size_t s = 0; + + if (MUL_OVERFLOW(sizeof(paddr_t), num_pages, &s)) + return 0; + if (ADD_OVERFLOW(sizeof(struct mobj_sp), s, &s)) + return 0; + return s; +} + +struct mobj *sp_mem_new_mobj(uint64_t pages, uint32_t mem_type, bool is_secure) +{ + struct mobj_sp *m = NULL; + size_t s = 0; + + s = mobj_sp_size(pages); + if (!s) + return NULL; + + m = calloc(1, s); + if (!m) + return NULL; + + m->mobj.ops = &mobj_sp_ops; + m->mobj.size = pages * SMALL_PAGE_SIZE; + m->mobj.phys_granule = SMALL_PAGE_SIZE; + + m->mem_type = mem_type; + m->is_secure = is_secure; + + refcount_set(&m->mobj.refc, 1); + return &m->mobj; +} + +static size_t get_page_count(struct mobj_sp *ms) +{ + return ROUNDUP(ms->mobj.size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; +} + +/* Add some physical pages to the mobj object. */ +int sp_mem_add_pages(struct mobj *mobj, unsigned int *idx, + paddr_t pa, unsigned int num_pages) +{ + struct mobj_sp *ms = to_mobj_sp(mobj); + unsigned int n = 0; + size_t tot_page_count = get_page_count(ms); + + if (ADD_OVERFLOW(*idx, num_pages, &n) || n > tot_page_count) + return TEE_ERROR_BAD_PARAMETERS; + + /* Don't check for device memory */ + if (ms->mem_type == TEE_MATTR_MEM_TYPE_CACHED) { + if (ms->is_secure) { + if (!tee_pbuf_is_sec(pa, num_pages * SMALL_PAGE_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + } else { + if (!tee_pbuf_is_non_sec(pa, + num_pages * SMALL_PAGE_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + } + } + + for (n = 0; n < num_pages; n++) + ms->pages[n + *idx] = pa + n * SMALL_PAGE_SIZE; + + *idx += n; + return TEE_SUCCESS; +} + +static TEE_Result get_mem_type(struct mobj *mobj, uint32_t *mt) +{ + struct mobj_sp *m = to_mobj_sp(mobj); + + *mt = m->mem_type; + + return TEE_SUCCESS; +} + +static bool mobj_sp_matches(struct mobj *mobj, enum buf_is_attr attr) +{ + struct mobj_sp *m = to_mobj_sp(mobj); + + if (m->is_secure) + return attr == CORE_MEM_SEC; + else + return attr == CORE_MEM_NON_SEC || attr == CORE_MEM_REG_SHM; +} + +static TEE_Result get_pa(struct mobj *mobj, size_t offset, + size_t granule, paddr_t *pa) +{ + struct mobj_sp *ms = to_mobj_sp(mobj); + paddr_t p = 0; + + if (!pa) + return TEE_ERROR_GENERIC; + + if (offset >= mobj->size) + return TEE_ERROR_GENERIC; + + switch (granule) { + case 0: + p = ms->pages[offset / SMALL_PAGE_SIZE] + + (offset & SMALL_PAGE_MASK); + break; + case SMALL_PAGE_SIZE: + p = ms->pages[offset / SMALL_PAGE_SIZE]; + break; + default: + return TEE_ERROR_GENERIC; + } + *pa = p; + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(get_pa); + +static size_t get_phys_offs(struct mobj *mobj __maybe_unused, + size_t granule __maybe_unused) +{ + return 0; +} + +static void inactivate(struct mobj *mobj) +{ + struct mobj_sp *ms = to_mobj_sp(mobj); + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&sp_mem_lock); + /* + * If refcount isn't 0 some other thread has found this mobj in + * shm_head after the mobj_put() that put us here and before we got + * the lock. + */ + if (!refcount_val(&mobj->refc)) + free(ms); + + cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); +} + +static const struct mobj_ops mobj_sp_ops = { + .get_pa = get_pa, + .get_phys_offs = get_phys_offs, + .get_mem_type = get_mem_type, + .matches = mobj_sp_matches, + .free = inactivate, +}; + +struct sp_mem_receiver *sp_mem_get_receiver(uint32_t s_id, struct sp_mem *smem) +{ + struct sp_mem_receiver *r = NULL; + + SLIST_FOREACH(r, &smem->receivers, link) { + if (r->perm.endpoint_id == s_id) + return r; + } + return NULL; +} + +struct sp_mem *sp_mem_get(uint64_t handle) +{ + struct sp_mem *smem = NULL; + uint32_t exceptions = cpu_spin_lock_xsave(&sp_mem_lock); + + SLIST_FOREACH(smem, &mem_shares, link) { + if (smem->global_handle == handle) + break; + } + + cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); + return smem; +} + +void *sp_mem_get_va(const struct user_mode_ctx *uctx, size_t offset, + struct mobj *mobj) +{ + struct vm_region *region = NULL; + + TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { + if (region->mobj == mobj && region->offset == offset) + return (void *)region->va; + } + return NULL; +} + +struct sp_mem *sp_mem_new(void) +{ + struct sp_mem *smem = NULL; + uint32_t exceptions = 0; + int i = 0; + + smem = calloc(sizeof(*smem), 1); + if (!smem) + return NULL; + + exceptions = cpu_spin_lock_xsave(&sp_mem_lock); + + bit_ffc(share_bits, NUM_SHARES, &i); + if (i == -1) { + cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); + free(smem); + return NULL; + } + + bit_set(share_bits, i); + /* + * OP-TEE SHAREs use bit 44 use bit 45 instead. + */ + smem->global_handle = i | FFA_MEMORY_HANDLE_SECURE_BIT; + SLIST_INIT(&smem->regions); + SLIST_INIT(&smem->receivers); + + cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); + + return smem; +} + +void sp_mem_add(struct sp_mem *smem) +{ + uint32_t exceptions = cpu_spin_lock_xsave(&sp_mem_lock); + + SLIST_INSERT_HEAD(&mem_shares, smem, link); + + cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); +} + +bool sp_mem_is_shared(struct sp_mem_map_region *new_reg) +{ + struct sp_mem *smem = NULL; + uint32_t exceptions = cpu_spin_lock_xsave(&sp_mem_lock); + uint64_t new_reg_end = new_reg->page_offset + + (new_reg->page_count * SMALL_PAGE_SIZE); + + SLIST_FOREACH(smem, &mem_shares, link) { + struct sp_mem_map_region *reg = NULL; + + SLIST_FOREACH(reg, &smem->regions, link) { + if (new_reg->mobj == reg->mobj) { + uint64_t reg_end = 0; + + reg_end = reg->page_offset + + (reg->page_count * SMALL_PAGE_SIZE); + + if (new_reg->page_offset < reg_end && + new_reg_end > reg->page_offset) { + cpu_spin_unlock_xrestore(&sp_mem_lock, + exceptions); + return true; + } + } + } + } + + cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); + return false; +} + +void sp_mem_remove(struct sp_mem *smem) +{ + uint32_t exceptions = 0; + int i = 0; + struct sp_mem *tsmem = NULL; + + if (!smem) + return; + + /* Remove all receivers */ + while (!SLIST_EMPTY(&smem->receivers)) { + struct sp_mem_receiver *receiver = NULL; + + receiver = SLIST_FIRST(&smem->receivers); + SLIST_REMOVE_HEAD(&smem->receivers, link); + free(receiver); + } + /* Remove all regions */ + while (!SLIST_EMPTY(&smem->regions)) { + struct sp_mem_map_region *region = SLIST_FIRST(&smem->regions); + + mobj_put(region->mobj); + + SLIST_REMOVE_HEAD(&smem->regions, link); + free(region); + } + + exceptions = cpu_spin_lock_xsave(&sp_mem_lock); + + i = smem->global_handle & ~FFA_MEMORY_HANDLE_SECURE_BIT; + assert(i < NUM_SHARES); + + bit_clear(share_bits, i); + + SLIST_FOREACH(tsmem, &mem_shares, link) { + if (tsmem == smem) { + SLIST_REMOVE(&mem_shares, smem, sp_mem, link); + break; + } + } + + cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); + + free(smem); +} diff --git a/optee/optee_os/core/arch/arm/mm/sub.mk b/optee/optee_os/core/arch/arm/mm/sub.mk new file mode 100644 index 0000000..1f63c8e --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/sub.mk @@ -0,0 +1,25 @@ +srcs-y += core_mmu.c +srcs-$(CFG_WITH_PAGER) += tee_pager.c +ifeq ($(CFG_WITH_LPAE),y) +srcs-y += core_mmu_lpae.c +else +srcs-y += core_mmu_v7.c +endif +srcs-y += pgt_cache.c +srcs-$(CFG_CORE_FFA) += mobj_ffa.c +srcs-$(CFG_SECURE_PARTITION) += sp_mem.c +ifneq ($(CFG_CORE_FFA),y) +srcs-$(CFG_CORE_DYN_SHM) += mobj_dyn_shm.c +endif + +ifeq ($(CFG_SYSCALL_FTRACE),y) +# We would not like to profile MMU APIs as these are used to switch TA +# context which may cause undesired behaviour as ftrace requires TA context +# to be active. Moreover profiling code uses some of MMU APIs to check +# if TA context is active or not. +ifeq ($(CFG_WITH_LPAE),y) +cflags-remove-core_mmu_lpae.c-y += -pg +else +cflags-remove-core_mmu_v7.c-y += -pg +endif +endif diff --git a/optee/optee_os/core/arch/arm/mm/tee_pager.c b/optee/optee_os/core/arch/arm/mm/tee_pager.c new file mode 100644 index 0000000..163b3a8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/mm/tee_pager.c @@ -0,0 +1,2048 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2021, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#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 + + +static struct vm_paged_region_head core_vm_regions = + TAILQ_HEAD_INITIALIZER(core_vm_regions); + +#define INVALID_PGIDX UINT_MAX +#define PMEM_FLAG_DIRTY BIT(0) +#define PMEM_FLAG_HIDDEN BIT(1) + +/* + * struct tee_pager_pmem - Represents a physical page used for paging. + * + * @flags flags defined by PMEM_FLAG_* above + * @fobj_pgidx index of the page in the @fobj + * @fobj File object of which a page is made visible. + * @va_alias Virtual address where the physical page always is aliased. + * Used during remapping of the page when the content need to + * be updated before it's available at the new location. + */ +struct tee_pager_pmem { + unsigned int flags; + unsigned int fobj_pgidx; + struct fobj *fobj; + void *va_alias; + TAILQ_ENTRY(tee_pager_pmem) link; +}; + +struct tblidx { + struct pgt *pgt; + unsigned int idx; +}; + +/* The list of physical pages. The first page in the list is the oldest */ +TAILQ_HEAD(tee_pager_pmem_head, tee_pager_pmem); + +static struct tee_pager_pmem_head tee_pager_pmem_head = + TAILQ_HEAD_INITIALIZER(tee_pager_pmem_head); + +static struct tee_pager_pmem_head tee_pager_lock_pmem_head = + TAILQ_HEAD_INITIALIZER(tee_pager_lock_pmem_head); + +/* number of pages hidden */ +#define TEE_PAGER_NHIDE (tee_pager_npages / 3) + +/* Number of registered physical pages, used hiding pages. */ +static size_t tee_pager_npages; + +/* This area covers the IVs for all fobjs with paged IVs */ +static struct vm_paged_region *pager_iv_region; +/* Used by make_iv_available(), see make_iv_available() for details. */ +static struct tee_pager_pmem *pager_spare_pmem; + +#ifdef CFG_WITH_STATS +static struct tee_pager_stats pager_stats; + +static inline void incr_ro_hits(void) +{ + pager_stats.ro_hits++; +} + +static inline void incr_rw_hits(void) +{ + pager_stats.rw_hits++; +} + +static inline void incr_hidden_hits(void) +{ + pager_stats.hidden_hits++; +} + +static inline void incr_zi_released(void) +{ + pager_stats.zi_released++; +} + +static inline void incr_npages_all(void) +{ + pager_stats.npages_all++; +} + +static inline void set_npages(void) +{ + pager_stats.npages = tee_pager_npages; +} + +void tee_pager_get_stats(struct tee_pager_stats *stats) +{ + *stats = pager_stats; + + pager_stats.hidden_hits = 0; + pager_stats.ro_hits = 0; + pager_stats.rw_hits = 0; + pager_stats.zi_released = 0; +} + +#else /* CFG_WITH_STATS */ +static inline void incr_ro_hits(void) { } +static inline void incr_rw_hits(void) { } +static inline void incr_hidden_hits(void) { } +static inline void incr_zi_released(void) { } +static inline void incr_npages_all(void) { } +static inline void set_npages(void) { } + +void tee_pager_get_stats(struct tee_pager_stats *stats) +{ + memset(stats, 0, sizeof(struct tee_pager_stats)); +} +#endif /* CFG_WITH_STATS */ + +#define TBL_NUM_ENTRIES (CORE_MMU_PGDIR_SIZE / SMALL_PAGE_SIZE) +#define TBL_LEVEL CORE_MMU_PGDIR_LEVEL +#define TBL_SHIFT SMALL_PAGE_SHIFT + +#define EFFECTIVE_VA_SIZE \ + (ROUNDUP(VCORE_START_VA + TEE_RAM_VA_SIZE, CORE_MMU_PGDIR_SIZE) - \ + ROUNDDOWN(VCORE_START_VA, CORE_MMU_PGDIR_SIZE)) + +static struct pager_table { + struct pgt pgt; + struct core_mmu_table_info tbl_info; +} *pager_tables; +static unsigned int num_pager_tables; + +static unsigned pager_spinlock = SPINLOCK_UNLOCK; + +/* Defines the range of the alias area */ +static tee_mm_entry_t *pager_alias_area; +/* + * Physical pages are added in a stack like fashion to the alias area, + * @pager_alias_next_free gives the address of next free entry if + * @pager_alias_next_free is != 0 + */ +static uintptr_t pager_alias_next_free; + +#ifdef CFG_TEE_CORE_DEBUG +#define pager_lock(ai) pager_lock_dldetect(__func__, __LINE__, ai) + +static uint32_t pager_lock_dldetect(const char *func, const int line, + struct abort_info *ai) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + unsigned int retries = 0; + unsigned int reminder = 0; + + while (!cpu_spin_trylock(&pager_spinlock)) { + retries++; + if (!retries) { + /* wrapped, time to report */ + trace_printf(func, line, TRACE_ERROR, true, + "possible spinlock deadlock reminder %u", + reminder); + if (reminder < UINT_MAX) + reminder++; + if (ai) + abort_print(ai); + } + } + + return exceptions; +} +#else +static uint32_t pager_lock(struct abort_info __unused *ai) +{ + return cpu_spin_lock_xsave(&pager_spinlock); +} +#endif + +static uint32_t pager_lock_check_stack(size_t stack_size) +{ + if (stack_size) { + int8_t buf[stack_size]; + size_t n; + + /* + * Make sure to touch all pages of the stack that we expect + * to use with this lock held. We need to take eventual + * page faults before the lock is taken or we'll deadlock + * the pager. The pages that are populated in this way will + * eventually be released at certain save transitions of + * the thread. + */ + for (n = 0; n < stack_size; n += SMALL_PAGE_SIZE) + io_write8((vaddr_t)buf + n, 1); + io_write8((vaddr_t)buf + stack_size - 1, 1); + } + + return pager_lock(NULL); +} + +static void pager_unlock(uint32_t exceptions) +{ + cpu_spin_unlock_xrestore(&pager_spinlock, exceptions); +} + +void *tee_pager_phys_to_virt(paddr_t pa, size_t len) +{ + struct core_mmu_table_info ti; + unsigned idx; + uint32_t a; + paddr_t p; + vaddr_t v; + size_t n; + + if (pa & SMALL_PAGE_MASK || len > SMALL_PAGE_SIZE) + return NULL; + + /* + * Most addresses are mapped lineary, try that first if possible. + */ + if (!tee_pager_get_table_info(pa, &ti)) + return NULL; /* impossible pa */ + idx = core_mmu_va2idx(&ti, pa); + core_mmu_get_entry(&ti, idx, &p, &a); + if ((a & TEE_MATTR_VALID_BLOCK) && p == pa) + return (void *)core_mmu_idx2va(&ti, idx); + + n = 0; + idx = core_mmu_va2idx(&pager_tables[n].tbl_info, TEE_RAM_START); + while (true) { + while (idx < TBL_NUM_ENTRIES) { + v = core_mmu_idx2va(&pager_tables[n].tbl_info, idx); + if (v >= (TEE_RAM_START + TEE_RAM_VA_SIZE)) + return NULL; + + core_mmu_get_entry(&pager_tables[n].tbl_info, + idx, &p, &a); + if ((a & TEE_MATTR_VALID_BLOCK) && p == pa) + return (void *)v; + idx++; + } + + n++; + if (n >= num_pager_tables) + return NULL; + idx = 0; + } + + return NULL; +} + +static bool pmem_is_hidden(struct tee_pager_pmem *pmem) +{ + return pmem->flags & PMEM_FLAG_HIDDEN; +} + +static bool pmem_is_dirty(struct tee_pager_pmem *pmem) +{ + return pmem->flags & PMEM_FLAG_DIRTY; +} + +static bool pmem_is_covered_by_region(struct tee_pager_pmem *pmem, + struct vm_paged_region *reg) +{ + if (pmem->fobj != reg->fobj) + return false; + if (pmem->fobj_pgidx < reg->fobj_pgoffs) + return false; + if ((pmem->fobj_pgidx - reg->fobj_pgoffs) >= + (reg->size >> SMALL_PAGE_SHIFT)) + return false; + + return true; +} + +static size_t get_pgt_count(vaddr_t base, size_t size) +{ + assert(size); + + return (base + size - 1) / CORE_MMU_PGDIR_SIZE + 1 - + base / CORE_MMU_PGDIR_SIZE; +} + +static bool region_have_pgt(struct vm_paged_region *reg, struct pgt *pgt) +{ + size_t n = 0; + + for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) + if (reg->pgt_array[n] == pgt) + return true; + + return false; +} + +static struct tblidx pmem_get_region_tblidx(struct tee_pager_pmem *pmem, + struct vm_paged_region *reg) +{ + size_t tbloffs = (reg->base & CORE_MMU_PGDIR_MASK) >> SMALL_PAGE_SHIFT; + size_t idx = pmem->fobj_pgidx - reg->fobj_pgoffs + tbloffs; + + assert(pmem->fobj && pmem->fobj_pgidx != INVALID_PGIDX); + assert(idx / TBL_NUM_ENTRIES < get_pgt_count(reg->base, reg->size)); + + return (struct tblidx){ + .idx = idx % TBL_NUM_ENTRIES, + .pgt = reg->pgt_array[idx / TBL_NUM_ENTRIES], + }; +} + +static struct pager_table *find_pager_table_may_fail(vaddr_t va) +{ + size_t n; + const vaddr_t mask = CORE_MMU_PGDIR_MASK; + + if (!pager_tables) + return NULL; + + n = ((va & ~mask) - pager_tables[0].tbl_info.va_base) >> + CORE_MMU_PGDIR_SHIFT; + if (n >= num_pager_tables) + return NULL; + + assert(va >= pager_tables[n].tbl_info.va_base && + va <= (pager_tables[n].tbl_info.va_base | mask)); + + return pager_tables + n; +} + +static struct pager_table *find_pager_table(vaddr_t va) +{ + struct pager_table *pt = find_pager_table_may_fail(va); + + assert(pt); + return pt; +} + +bool tee_pager_get_table_info(vaddr_t va, struct core_mmu_table_info *ti) +{ + struct pager_table *pt = find_pager_table_may_fail(va); + + if (!pt) + return false; + + *ti = pt->tbl_info; + return true; +} + +static struct core_mmu_table_info *find_table_info(vaddr_t va) +{ + return &find_pager_table(va)->tbl_info; +} + +static struct pgt *find_core_pgt(vaddr_t va) +{ + return &find_pager_table(va)->pgt; +} + +void tee_pager_set_alias_area(tee_mm_entry_t *mm) +{ + struct pager_table *pt; + unsigned idx; + vaddr_t smem = tee_mm_get_smem(mm); + size_t nbytes = tee_mm_get_bytes(mm); + vaddr_t v; + uint32_t a = 0; + + DMSG("0x%" PRIxVA " - 0x%" PRIxVA, smem, smem + nbytes); + + assert(!pager_alias_area); + pager_alias_area = mm; + pager_alias_next_free = smem; + + /* Clear all mapping in the alias area */ + pt = find_pager_table(smem); + idx = core_mmu_va2idx(&pt->tbl_info, smem); + while (pt <= (pager_tables + num_pager_tables - 1)) { + while (idx < TBL_NUM_ENTRIES) { + v = core_mmu_idx2va(&pt->tbl_info, idx); + if (v >= (smem + nbytes)) + goto out; + + core_mmu_get_entry(&pt->tbl_info, idx, NULL, &a); + core_mmu_set_entry(&pt->tbl_info, idx, 0, 0); + if (a & TEE_MATTR_VALID_BLOCK) + pgt_dec_used_entries(&pt->pgt); + idx++; + } + + pt++; + idx = 0; + } + +out: + tlbi_mva_range(smem, nbytes, SMALL_PAGE_SIZE); +} + +static size_t tbl_usage_count(struct core_mmu_table_info *ti) +{ + size_t n; + uint32_t a = 0; + size_t usage = 0; + + for (n = 0; n < ti->num_entries; n++) { + core_mmu_get_entry(ti, n, NULL, &a); + if (a & TEE_MATTR_VALID_BLOCK) + usage++; + } + return usage; +} + +static void tblidx_get_entry(struct tblidx tblidx, paddr_t *pa, uint32_t *attr) +{ + assert(tblidx.pgt && tblidx.idx < TBL_NUM_ENTRIES); + core_mmu_get_entry_primitive(tblidx.pgt->tbl, TBL_LEVEL, tblidx.idx, + pa, attr); +} + +static void tblidx_set_entry(struct tblidx tblidx, paddr_t pa, uint32_t attr) +{ + assert(tblidx.pgt && tblidx.idx < TBL_NUM_ENTRIES); + core_mmu_set_entry_primitive(tblidx.pgt->tbl, TBL_LEVEL, tblidx.idx, + pa, attr); +} + +static struct tblidx region_va2tblidx(struct vm_paged_region *reg, vaddr_t va) +{ + paddr_t mask = CORE_MMU_PGDIR_MASK; + size_t n = 0; + + assert(va >= reg->base && va < (reg->base + reg->size)); + n = (va - (reg->base & ~mask)) / CORE_MMU_PGDIR_SIZE; + + return (struct tblidx){ + .idx = (va & mask) / SMALL_PAGE_SIZE, + .pgt = reg->pgt_array[n], + }; +} + +static vaddr_t tblidx2va(struct tblidx tblidx) +{ + return tblidx.pgt->vabase + (tblidx.idx << SMALL_PAGE_SHIFT); +} + +static void tblidx_tlbi_entry(struct tblidx tblidx) +{ + vaddr_t va = tblidx2va(tblidx); + +#if defined(CFG_PAGED_USER_TA) + if (tblidx.pgt->ctx) { + uint32_t asid = to_user_mode_ctx(tblidx.pgt->ctx)->vm_info.asid; + + tlbi_mva_asid(va, asid); + return; + } +#endif + tlbi_mva_allasid(va); +} + +static void pmem_assign_fobj_page(struct tee_pager_pmem *pmem, + struct vm_paged_region *reg, vaddr_t va) +{ + struct tee_pager_pmem *p = NULL; + unsigned int fobj_pgidx = 0; + + assert(!pmem->fobj && pmem->fobj_pgidx == INVALID_PGIDX); + + assert(va >= reg->base && va < (reg->base + reg->size)); + fobj_pgidx = (va - reg->base) / SMALL_PAGE_SIZE + reg->fobj_pgoffs; + + TAILQ_FOREACH(p, &tee_pager_pmem_head, link) + assert(p->fobj != reg->fobj || p->fobj_pgidx != fobj_pgidx); + + pmem->fobj = reg->fobj; + pmem->fobj_pgidx = fobj_pgidx; +} + +static void pmem_clear(struct tee_pager_pmem *pmem) +{ + pmem->fobj = NULL; + pmem->fobj_pgidx = INVALID_PGIDX; + pmem->flags = 0; +} + +static void pmem_unmap(struct tee_pager_pmem *pmem, struct pgt *only_this_pgt) +{ + struct vm_paged_region *reg = NULL; + struct tblidx tblidx = { }; + uint32_t a = 0; + + TAILQ_FOREACH(reg, &pmem->fobj->regions, fobj_link) { + /* + * If only_this_pgt points to a pgt then the pgt of this + * region has to match or we'll skip over it. + */ + if (only_this_pgt && !region_have_pgt(reg, only_this_pgt)) + continue; + if (!pmem_is_covered_by_region(pmem, reg)) + continue; + tblidx = pmem_get_region_tblidx(pmem, reg); + if (!tblidx.pgt) + continue; + tblidx_get_entry(tblidx, NULL, &a); + if (a & TEE_MATTR_VALID_BLOCK) { + tblidx_set_entry(tblidx, 0, 0); + pgt_dec_used_entries(tblidx.pgt); + tblidx_tlbi_entry(tblidx); + } + } +} + +void tee_pager_early_init(void) +{ + size_t n = 0; + + num_pager_tables = EFFECTIVE_VA_SIZE / CORE_MMU_PGDIR_SIZE; + pager_tables = calloc(num_pager_tables, sizeof(*pager_tables)); + if (!pager_tables) + panic("Cannot allocate pager_tables"); + + /* + * Note that this depends on add_pager_vaspace() adding vaspace + * after end of memory. + */ + for (n = 0; n < num_pager_tables; n++) { + if (!core_mmu_find_table(NULL, VCORE_START_VA + + n * CORE_MMU_PGDIR_SIZE, UINT_MAX, + &pager_tables[n].tbl_info)) + panic("can't find mmu tables"); + + if (pager_tables[n].tbl_info.shift != TBL_SHIFT) + panic("Unsupported page size in translation table"); + assert(pager_tables[n].tbl_info.num_entries == TBL_NUM_ENTRIES); + assert(pager_tables[n].tbl_info.level == TBL_LEVEL); + + pager_tables[n].pgt.tbl = pager_tables[n].tbl_info.table; + pager_tables[n].pgt.vabase = pager_tables[n].tbl_info.va_base; + pgt_set_used_entries(&pager_tables[n].pgt, + tbl_usage_count(&pager_tables[n].tbl_info)); + } +} + +static void *pager_add_alias_page(paddr_t pa) +{ + unsigned idx; + struct core_mmu_table_info *ti; + /* Alias pages mapped without write permission: runtime will care */ + uint32_t attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_SECURE | + TEE_MATTR_PR | (TEE_MATTR_MEM_TYPE_CACHED << + TEE_MATTR_MEM_TYPE_SHIFT); + + DMSG("0x%" PRIxPA, pa); + + ti = find_table_info(pager_alias_next_free); + idx = core_mmu_va2idx(ti, pager_alias_next_free); + core_mmu_set_entry(ti, idx, pa, attr); + pgt_inc_used_entries(find_core_pgt(pager_alias_next_free)); + pager_alias_next_free += SMALL_PAGE_SIZE; + if (pager_alias_next_free >= (tee_mm_get_smem(pager_alias_area) + + tee_mm_get_bytes(pager_alias_area))) + pager_alias_next_free = 0; + return (void *)core_mmu_idx2va(ti, idx); +} + +static void region_insert(struct vm_paged_region_head *regions, + struct vm_paged_region *reg, + struct vm_paged_region *r_prev) +{ + uint32_t exceptions = pager_lock_check_stack(8); + + if (r_prev) + TAILQ_INSERT_AFTER(regions, r_prev, reg, link); + else + TAILQ_INSERT_HEAD(regions, reg, link); + TAILQ_INSERT_TAIL(®->fobj->regions, reg, fobj_link); + + pager_unlock(exceptions); +} +DECLARE_KEEP_PAGER(region_insert); + +static struct vm_paged_region *alloc_region(vaddr_t base, size_t size) +{ + struct vm_paged_region *reg = NULL; + + if ((base & SMALL_PAGE_MASK) || !size) { + EMSG("invalid pager region [%" PRIxVA " +0x%zx]", base, size); + panic(); + } + + reg = calloc(1, sizeof(*reg)); + if (!reg) + return NULL; + reg->pgt_array = calloc(get_pgt_count(base, size), + sizeof(struct pgt *)); + if (!reg->pgt_array) { + free(reg); + return NULL; + } + + reg->base = base; + reg->size = size; + return reg; +} + +void tee_pager_add_core_region(vaddr_t base, enum vm_paged_region_type type, + struct fobj *fobj) +{ + struct vm_paged_region *reg = NULL; + size_t n = 0; + + assert(fobj); + + DMSG("0x%" PRIxPTR " - 0x%" PRIxPTR " : type %d", + base, base + fobj->num_pages * SMALL_PAGE_SIZE, type); + + reg = alloc_region(base, fobj->num_pages * SMALL_PAGE_SIZE); + if (!reg) + panic("alloc_region"); + + reg->fobj = fobj_get(fobj); + reg->fobj_pgoffs = 0; + reg->type = type; + + switch (type) { + case PAGED_REGION_TYPE_RO: + reg->flags = TEE_MATTR_PRX; + break; + case PAGED_REGION_TYPE_RW: + case PAGED_REGION_TYPE_LOCK: + reg->flags = TEE_MATTR_PRW; + break; + default: + panic(); + } + + for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) + reg->pgt_array[n] = find_core_pgt(base + + n * CORE_MMU_PGDIR_SIZE); + region_insert(&core_vm_regions, reg, NULL); +} + +static struct vm_paged_region *find_region(struct vm_paged_region_head *regions, + vaddr_t va) +{ + struct vm_paged_region *reg; + + if (!regions) + return NULL; + + TAILQ_FOREACH(reg, regions, link) { + if (core_is_buffer_inside(va, 1, reg->base, reg->size)) + return reg; + } + return NULL; +} + +#ifdef CFG_PAGED_USER_TA +static struct vm_paged_region *find_uta_region(vaddr_t va) +{ + struct ts_ctx *ctx = thread_get_tsd()->ctx; + + if (!is_user_mode_ctx(ctx)) + return NULL; + return find_region(to_user_mode_ctx(ctx)->regions, va); +} +#else +static struct vm_paged_region *find_uta_region(vaddr_t va __unused) +{ + return NULL; +} +#endif /*CFG_PAGED_USER_TA*/ + + +static uint32_t get_region_mattr(uint32_t reg_flags) +{ + uint32_t attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_SECURE | + TEE_MATTR_MEM_TYPE_CACHED << TEE_MATTR_MEM_TYPE_SHIFT | + (reg_flags & (TEE_MATTR_PRWX | TEE_MATTR_URWX)); + + return attr; +} + +static paddr_t get_pmem_pa(struct tee_pager_pmem *pmem) +{ + struct core_mmu_table_info *ti; + paddr_t pa; + unsigned idx; + + ti = find_table_info((vaddr_t)pmem->va_alias); + idx = core_mmu_va2idx(ti, (vaddr_t)pmem->va_alias); + core_mmu_get_entry(ti, idx, &pa, NULL); + return pa; +} + +#ifdef CFG_PAGED_USER_TA +static void unlink_region(struct vm_paged_region_head *regions, + struct vm_paged_region *reg) +{ + uint32_t exceptions = pager_lock_check_stack(64); + + TAILQ_REMOVE(regions, reg, link); + TAILQ_REMOVE(®->fobj->regions, reg, fobj_link); + + pager_unlock(exceptions); +} +DECLARE_KEEP_PAGER(unlink_region); + +static void free_region(struct vm_paged_region *reg) +{ + fobj_put(reg->fobj); + free(reg->pgt_array); + free(reg); +} + +static TEE_Result pager_add_um_region(struct user_mode_ctx *uctx, vaddr_t base, + struct fobj *fobj, uint32_t prot) +{ + struct vm_paged_region *r_prev = NULL; + struct vm_paged_region *reg = NULL; + vaddr_t b = base; + size_t fobj_pgoffs = 0; + size_t s = fobj->num_pages * SMALL_PAGE_SIZE; + + if (!uctx->regions) { + uctx->regions = malloc(sizeof(*uctx->regions)); + if (!uctx->regions) + return TEE_ERROR_OUT_OF_MEMORY; + TAILQ_INIT(uctx->regions); + } + + reg = TAILQ_FIRST(uctx->regions); + while (reg) { + if (core_is_buffer_intersect(b, s, reg->base, reg->size)) + return TEE_ERROR_BAD_PARAMETERS; + if (b < reg->base) + break; + r_prev = reg; + reg = TAILQ_NEXT(reg, link); + } + + reg = alloc_region(b, s); + if (!reg) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Table info will be set when the context is activated. */ + reg->fobj = fobj_get(fobj); + reg->fobj_pgoffs = fobj_pgoffs; + reg->type = PAGED_REGION_TYPE_RW; + reg->flags = prot; + + region_insert(uctx->regions, reg, r_prev); + + return TEE_SUCCESS; +} + +static void map_pgts(struct vm_paged_region *reg) +{ + struct core_mmu_table_info dir_info = { NULL }; + size_t n = 0; + + core_mmu_get_user_pgdir(&dir_info); + + for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) { + struct pgt *pgt = reg->pgt_array[n]; + uint32_t attr = 0; + paddr_t pa = 0; + size_t idx = 0; + + idx = core_mmu_va2idx(&dir_info, pgt->vabase); + core_mmu_get_entry(&dir_info, idx, &pa, &attr); + + /* + * Check if the page table already is used, if it is, it's + * already registered. + */ + if (pgt->num_used_entries) { + assert(attr & TEE_MATTR_TABLE); + assert(pa == virt_to_phys(pgt->tbl)); + continue; + } + + attr = TEE_MATTR_SECURE | TEE_MATTR_TABLE; + pa = virt_to_phys(pgt->tbl); + assert(pa); + /* + * Note that the update of the table entry is guaranteed to + * be atomic. + */ + core_mmu_set_entry(&dir_info, idx, pa, attr); + } +} + +TEE_Result tee_pager_add_um_region(struct user_mode_ctx *uctx, vaddr_t base, + struct fobj *fobj, uint32_t prot) +{ + TEE_Result res = TEE_SUCCESS; + struct thread_specific_data *tsd = thread_get_tsd(); + struct vm_paged_region *reg = NULL; + + res = pager_add_um_region(uctx, base, fobj, prot); + if (res) + return res; + + if (uctx->ts_ctx == tsd->ctx) { + /* + * We're chaning the currently active utc. Assign page + * tables to the new regions and make sure that the page + * tables are registered in the upper table. + */ + tee_pager_assign_um_tables(uctx); + TAILQ_FOREACH(reg, uctx->regions, link) + map_pgts(reg); + } + + return TEE_SUCCESS; +} + +static void split_region(struct vm_paged_region *reg, + struct vm_paged_region *r2, vaddr_t va) +{ + uint32_t exceptions = pager_lock_check_stack(64); + size_t diff = va - reg->base; + size_t r2_pgt_count = 0; + size_t reg_pgt_count = 0; + size_t n0 = 0; + size_t n = 0; + + assert(r2->base == va); + assert(r2->size == reg->size - diff); + + r2->fobj = fobj_get(reg->fobj); + r2->fobj_pgoffs = reg->fobj_pgoffs + diff / SMALL_PAGE_SIZE; + r2->type = reg->type; + r2->flags = reg->flags; + + r2_pgt_count = get_pgt_count(r2->base, r2->size); + reg_pgt_count = get_pgt_count(reg->base, reg->size); + n0 = reg_pgt_count - r2_pgt_count; + for (n = n0; n < reg_pgt_count; n++) + r2->pgt_array[n - n0] = reg->pgt_array[n]; + reg->size = diff; + + TAILQ_INSERT_BEFORE(reg, r2, link); + TAILQ_INSERT_AFTER(®->fobj->regions, reg, r2, fobj_link); + + pager_unlock(exceptions); +} +DECLARE_KEEP_PAGER(split_region); + +TEE_Result tee_pager_split_um_region(struct user_mode_ctx *uctx, vaddr_t va) +{ + struct vm_paged_region *reg = NULL; + struct vm_paged_region *r2 = NULL; + + if (va & SMALL_PAGE_MASK) + return TEE_ERROR_BAD_PARAMETERS; + + TAILQ_FOREACH(reg, uctx->regions, link) { + if (va == reg->base || va == reg->base + reg->size) + return TEE_SUCCESS; + if (va > reg->base && va < reg->base + reg->size) { + size_t diff = va - reg->base; + + r2 = alloc_region(va, reg->size - diff); + if (!r2) + return TEE_ERROR_OUT_OF_MEMORY; + split_region(reg, r2, va); + return TEE_SUCCESS; + } + } + + return TEE_SUCCESS; +} + +static struct pgt ** +merge_region_with_next(struct vm_paged_region_head *regions, + struct vm_paged_region *reg, + struct vm_paged_region *r_next, struct pgt **pgt_array) +{ + uint32_t exceptions = pager_lock_check_stack(64); + struct pgt **old_pgt_array = reg->pgt_array; + + reg->pgt_array = pgt_array; + TAILQ_REMOVE(regions, r_next, link); + TAILQ_REMOVE(&r_next->fobj->regions, r_next, fobj_link); + + pager_unlock(exceptions); + return old_pgt_array; +} +DECLARE_KEEP_PAGER(merge_region_with_next); + +static struct pgt **alloc_merged_pgt_array(struct vm_paged_region *a, + struct vm_paged_region *a_next) +{ + size_t a_next_pgt_count = get_pgt_count(a_next->base, a_next->size); + size_t a_pgt_count = get_pgt_count(a->base, a->size); + size_t pgt_count = get_pgt_count(a->base, a->size + a_next->size); + struct pgt **pgt_array = NULL; + bool have_shared_pgt = false; + + have_shared_pgt = ((a->base + a->size) & ~CORE_MMU_PGDIR_MASK) == + (a_next->base & ~CORE_MMU_PGDIR_MASK); + + if (have_shared_pgt) + assert(pgt_count == a_pgt_count + a_next_pgt_count - 1); + else + assert(pgt_count == a_pgt_count + a_next_pgt_count); + + /* In case there's a shared pgt they must match */ + if (have_shared_pgt && + a->pgt_array[a_pgt_count - 1] != a_next->pgt_array[0]) + return NULL; + + pgt_array = calloc(sizeof(struct pgt *), pgt_count); + if (!pgt_array) + return NULL; + + /* + * Copy and merge the two pgt_arrays, note the special case + * where a pgt is shared. + */ + memcpy(pgt_array, a->pgt_array, a_pgt_count * sizeof(struct pgt *)); + if (have_shared_pgt) + memcpy(pgt_array + a_pgt_count, a_next->pgt_array + 1, + (a_next_pgt_count - 1) * sizeof(struct pgt *)); + else + memcpy(pgt_array + a_pgt_count, a_next->pgt_array, + a_next_pgt_count * sizeof(struct pgt *)); + + return pgt_array; +} + +void tee_pager_merge_um_region(struct user_mode_ctx *uctx, vaddr_t va, + size_t len) +{ + struct vm_paged_region *r_next = NULL; + struct vm_paged_region *reg = NULL; + struct pgt **pgt_array = NULL; + vaddr_t end_va = 0; + + if ((va | len) & SMALL_PAGE_MASK) + return; + if (ADD_OVERFLOW(va, len, &end_va)) + return; + + for (reg = TAILQ_FIRST(uctx->regions);; reg = r_next) { + r_next = TAILQ_NEXT(reg, link); + if (!r_next) + return; + + /* Try merging with the area just before va */ + if (reg->base + reg->size < va) + continue; + + /* + * If reg->base is well past our range we're done. + * Note that if it's just the page after our range we'll + * try to merge. + */ + if (reg->base > end_va) + return; + + if (reg->base + reg->size != r_next->base) + continue; + if (reg->fobj != r_next->fobj || reg->type != r_next->type || + reg->flags != r_next->flags) + continue; + if (reg->fobj_pgoffs + reg->size / SMALL_PAGE_SIZE != + r_next->fobj_pgoffs) + continue; + + pgt_array = alloc_merged_pgt_array(reg, r_next); + if (!pgt_array) + continue; + + /* + * merge_region_with_next() returns the old pgt array which + * was replaced in reg. We don't want to call free() + * directly from merge_region_with_next() that would pull + * free() and its dependencies into the unpaged area. + */ + free(merge_region_with_next(uctx->regions, reg, r_next, + pgt_array)); + free_region(r_next); + r_next = reg; + } +} + +static void rem_region(struct vm_paged_region_head *regions, + struct vm_paged_region *reg) +{ + struct tee_pager_pmem *pmem; + size_t last_pgoffs = reg->fobj_pgoffs + + (reg->size >> SMALL_PAGE_SHIFT) - 1; + uint32_t exceptions; + struct tblidx tblidx = { }; + uint32_t a = 0; + + exceptions = pager_lock_check_stack(64); + + TAILQ_REMOVE(regions, reg, link); + TAILQ_REMOVE(®->fobj->regions, reg, fobj_link); + + TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { + if (pmem->fobj != reg->fobj || + pmem->fobj_pgidx < reg->fobj_pgoffs || + pmem->fobj_pgidx > last_pgoffs) + continue; + + tblidx = pmem_get_region_tblidx(pmem, reg); + tblidx_get_entry(tblidx, NULL, &a); + if (!(a & TEE_MATTR_VALID_BLOCK)) + continue; + + tblidx_set_entry(tblidx, 0, 0); + tblidx_tlbi_entry(tblidx); + pgt_dec_used_entries(tblidx.pgt); + } + + pager_unlock(exceptions); +} +DECLARE_KEEP_PAGER(rem_region); + +void tee_pager_rem_um_region(struct user_mode_ctx *uctx, vaddr_t base, + size_t size) +{ + struct vm_paged_region *reg; + struct vm_paged_region *r_next; + size_t s = ROUNDUP(size, SMALL_PAGE_SIZE); + + TAILQ_FOREACH_SAFE(reg, uctx->regions, link, r_next) { + if (core_is_buffer_inside(reg->base, reg->size, base, s)) { + rem_region(uctx->regions, reg); + free_region(reg); + } + } + tlbi_asid(uctx->vm_info.asid); +} + +void tee_pager_rem_um_regions(struct user_mode_ctx *uctx) +{ + struct vm_paged_region *reg = NULL; + + if (!uctx->regions) + return; + + while (true) { + reg = TAILQ_FIRST(uctx->regions); + if (!reg) + break; + unlink_region(uctx->regions, reg); + free_region(reg); + } + + free(uctx->regions); +} + +static bool __maybe_unused same_context(struct tee_pager_pmem *pmem) +{ + struct vm_paged_region *reg = TAILQ_FIRST(&pmem->fobj->regions); + void *ctx = reg->pgt_array[0]->ctx; + + do { + reg = TAILQ_NEXT(reg, fobj_link); + if (!reg) + return true; + } while (reg->pgt_array[0]->ctx == ctx); + + return false; +} + +bool tee_pager_set_um_region_attr(struct user_mode_ctx *uctx, vaddr_t base, + size_t size, uint32_t flags) +{ + bool ret = false; + vaddr_t b = base; + size_t s = size; + size_t s2 = 0; + struct vm_paged_region *reg = find_region(uctx->regions, b); + uint32_t exceptions = 0; + struct tee_pager_pmem *pmem = NULL; + uint32_t a = 0; + uint32_t f = 0; + uint32_t mattr = 0; + uint32_t f2 = 0; + struct tblidx tblidx = { }; + + f = (flags & TEE_MATTR_URWX) | TEE_MATTR_UR | TEE_MATTR_PR; + if (f & TEE_MATTR_UW) + f |= TEE_MATTR_PW; + mattr = get_region_mattr(f); + + exceptions = pager_lock_check_stack(SMALL_PAGE_SIZE); + + while (s) { + if (!reg) { + ret = false; + goto out; + } + s2 = MIN(reg->size, s); + b += s2; + s -= s2; + + if (reg->flags == f) + goto next_region; + + TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { + if (!pmem_is_covered_by_region(pmem, reg)) + continue; + + tblidx = pmem_get_region_tblidx(pmem, reg); + tblidx_get_entry(tblidx, NULL, &a); + if (a == f) + continue; + tblidx_set_entry(tblidx, 0, 0); + tblidx_tlbi_entry(tblidx); + + pmem->flags &= ~PMEM_FLAG_HIDDEN; + if (pmem_is_dirty(pmem)) + f2 = mattr; + else + f2 = mattr & ~(TEE_MATTR_UW | TEE_MATTR_PW); + tblidx_set_entry(tblidx, get_pmem_pa(pmem), f2); + if (!(a & TEE_MATTR_VALID_BLOCK)) + pgt_inc_used_entries(tblidx.pgt); + /* + * Make sure the table update is visible before + * continuing. + */ + dsb_ishst(); + + /* + * Here's a problem if this page already is shared. + * We need do icache invalidate for each context + * in which it is shared. In practice this will + * never happen. + */ + if (flags & TEE_MATTR_UX) { + void *va = (void *)tblidx2va(tblidx); + + /* Assert that the pmem isn't shared. */ + assert(same_context(pmem)); + + dcache_clean_range_pou(va, SMALL_PAGE_SIZE); + icache_inv_user_range(va, SMALL_PAGE_SIZE); + } + } + + reg->flags = f; +next_region: + reg = TAILQ_NEXT(reg, link); + } + + ret = true; +out: + pager_unlock(exceptions); + return ret; +} + +DECLARE_KEEP_PAGER(tee_pager_set_um_region_attr); +#endif /*CFG_PAGED_USER_TA*/ + +void tee_pager_invalidate_fobj(struct fobj *fobj) +{ + struct tee_pager_pmem *pmem; + uint32_t exceptions; + + exceptions = pager_lock_check_stack(64); + + TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) + if (pmem->fobj == fobj) + pmem_clear(pmem); + + pager_unlock(exceptions); +} +DECLARE_KEEP_PAGER(tee_pager_invalidate_fobj); + +static struct tee_pager_pmem *pmem_find(struct vm_paged_region *reg, vaddr_t va) +{ + struct tee_pager_pmem *pmem = NULL; + size_t fobj_pgidx = 0; + + assert(va >= reg->base && va < (reg->base + reg->size)); + fobj_pgidx = (va - reg->base) / SMALL_PAGE_SIZE + reg->fobj_pgoffs; + + TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) + if (pmem->fobj == reg->fobj && pmem->fobj_pgidx == fobj_pgidx) + return pmem; + + return NULL; +} + +static bool tee_pager_unhide_page(struct vm_paged_region *reg, vaddr_t page_va) +{ + struct tblidx tblidx = region_va2tblidx(reg, page_va); + struct tee_pager_pmem *pmem = pmem_find(reg, page_va); + uint32_t a = get_region_mattr(reg->flags); + uint32_t attr = 0; + paddr_t pa = 0; + + if (!pmem) + return false; + + tblidx_get_entry(tblidx, NULL, &attr); + if (attr & TEE_MATTR_VALID_BLOCK) + return false; + + /* + * The page is hidden, or not not mapped yet. Unhide the page and + * move it to the tail. + * + * Since the page isn't mapped there doesn't exist a valid TLB entry + * for this address, so no TLB invalidation is required after setting + * the new entry. A DSB is needed though, to make the write visible. + * + * For user executable pages it's more complicated. Those pages can + * be shared between multiple TA mappings and thus populated by + * another TA. The reference manual states that: + * + * "instruction cache maintenance is required only after writing + * new data to a physical address that holds an instruction." + * + * So for hidden pages we would not need to invalidate i-cache, but + * for newly populated pages we do. Since we don't know which we + * have to assume the worst and always invalidate the i-cache. We + * don't need to clean the d-cache though, since that has already + * been done earlier. + * + * Additional bookkeeping to tell if the i-cache invalidation is + * needed or not is left as a future optimization. + */ + + /* If it's not a dirty block, then it should be read only. */ + if (!pmem_is_dirty(pmem)) + a &= ~(TEE_MATTR_PW | TEE_MATTR_UW); + + pa = get_pmem_pa(pmem); + pmem->flags &= ~PMEM_FLAG_HIDDEN; + if (reg->flags & TEE_MATTR_UX) { + void *va = (void *)tblidx2va(tblidx); + + /* Set a temporary read-only mapping */ + assert(!(a & (TEE_MATTR_UW | TEE_MATTR_PW))); + tblidx_set_entry(tblidx, pa, a & ~TEE_MATTR_UX); + dsb_ishst(); + + icache_inv_user_range(va, SMALL_PAGE_SIZE); + + /* Set the final mapping */ + tblidx_set_entry(tblidx, pa, a); + tblidx_tlbi_entry(tblidx); + } else { + tblidx_set_entry(tblidx, pa, a); + dsb_ishst(); + } + pgt_inc_used_entries(tblidx.pgt); + + TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link); + TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); + incr_hidden_hits(); + return true; +} + +static void tee_pager_hide_pages(void) +{ + struct tee_pager_pmem *pmem = NULL; + size_t n = 0; + + TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { + if (n >= TEE_PAGER_NHIDE) + break; + n++; + + /* we cannot hide pages when pmem->fobj is not defined. */ + if (!pmem->fobj) + continue; + + if (pmem_is_hidden(pmem)) + continue; + + pmem->flags |= PMEM_FLAG_HIDDEN; + pmem_unmap(pmem, NULL); + } +} + +static unsigned int __maybe_unused +num_regions_with_pmem(struct tee_pager_pmem *pmem) +{ + struct vm_paged_region *reg = NULL; + unsigned int num_matches = 0; + + TAILQ_FOREACH(reg, &pmem->fobj->regions, fobj_link) + if (pmem_is_covered_by_region(pmem, reg)) + num_matches++; + + return num_matches; +} + +/* + * Find mapped pmem, hide and move to pageble pmem. + * Return false if page was not mapped, and true if page was mapped. + */ +static bool tee_pager_release_one_phys(struct vm_paged_region *reg, + vaddr_t page_va) +{ + struct tee_pager_pmem *pmem = NULL; + struct tblidx tblidx = { }; + size_t fobj_pgidx = 0; + + assert(page_va >= reg->base && page_va < (reg->base + reg->size)); + fobj_pgidx = (page_va - reg->base) / SMALL_PAGE_SIZE + + reg->fobj_pgoffs; + + TAILQ_FOREACH(pmem, &tee_pager_lock_pmem_head, link) { + if (pmem->fobj != reg->fobj || pmem->fobj_pgidx != fobj_pgidx) + continue; + + /* + * Locked pages may not be shared. We're asserting that the + * number of regions using this pmem is one and only one as + * we're about to unmap it. + */ + assert(num_regions_with_pmem(pmem) == 1); + + tblidx = pmem_get_region_tblidx(pmem, reg); + tblidx_set_entry(tblidx, 0, 0); + pgt_dec_used_entries(tblidx.pgt); + TAILQ_REMOVE(&tee_pager_lock_pmem_head, pmem, link); + pmem_clear(pmem); + tee_pager_npages++; + set_npages(); + TAILQ_INSERT_HEAD(&tee_pager_pmem_head, pmem, link); + incr_zi_released(); + return true; + } + + return false; +} + +static void pager_deploy_page(struct tee_pager_pmem *pmem, + struct vm_paged_region *reg, vaddr_t page_va, + bool clean_user_cache, bool writable) +{ + struct tblidx tblidx = region_va2tblidx(reg, page_va); + uint32_t attr = get_region_mattr(reg->flags); + struct core_mmu_table_info *ti = NULL; + uint8_t *va_alias = pmem->va_alias; + paddr_t pa = get_pmem_pa(pmem); + unsigned int idx_alias = 0; + uint32_t attr_alias = 0; + paddr_t pa_alias = 0; + + /* Ensure we are allowed to write to aliased virtual page */ + ti = find_table_info((vaddr_t)va_alias); + idx_alias = core_mmu_va2idx(ti, (vaddr_t)va_alias); + core_mmu_get_entry(ti, idx_alias, &pa_alias, &attr_alias); + if (!(attr_alias & TEE_MATTR_PW)) { + attr_alias |= TEE_MATTR_PW; + core_mmu_set_entry(ti, idx_alias, pa_alias, attr_alias); + tlbi_mva_allasid((vaddr_t)va_alias); + } + + asan_tag_access(va_alias, va_alias + SMALL_PAGE_SIZE); + if (fobj_load_page(pmem->fobj, pmem->fobj_pgidx, va_alias)) { + EMSG("PH 0x%" PRIxVA " failed", page_va); + panic(); + } + switch (reg->type) { + case PAGED_REGION_TYPE_RO: + TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); + incr_ro_hits(); + /* Forbid write to aliases for read-only (maybe exec) pages */ + attr_alias &= ~TEE_MATTR_PW; + core_mmu_set_entry(ti, idx_alias, pa_alias, attr_alias); + tlbi_mva_allasid((vaddr_t)va_alias); + break; + case PAGED_REGION_TYPE_RW: + TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); + if (writable && (attr & (TEE_MATTR_PW | TEE_MATTR_UW))) + pmem->flags |= PMEM_FLAG_DIRTY; + incr_rw_hits(); + break; + case PAGED_REGION_TYPE_LOCK: + /* Move page to lock list */ + if (tee_pager_npages <= 0) + panic("Running out of pages"); + tee_pager_npages--; + set_npages(); + TAILQ_INSERT_TAIL(&tee_pager_lock_pmem_head, pmem, link); + break; + default: + panic(); + } + asan_tag_no_access(va_alias, va_alias + SMALL_PAGE_SIZE); + + if (!writable) + attr &= ~(TEE_MATTR_PW | TEE_MATTR_UW); + + /* + * We've updated the page using the aliased mapping and + * some cache maintenance is now needed if it's an + * executable page. + * + * Since the d-cache is a Physically-indexed, + * physically-tagged (PIPT) cache we can clean either the + * aliased address or the real virtual address. In this + * case we choose the real virtual address. + * + * The i-cache can also be PIPT, but may be something else + * too like VIPT. The current code requires the caches to + * implement the IVIPT extension, that is: + * "instruction cache maintenance is required only after + * writing new data to a physical address that holds an + * instruction." + * + * To portably invalidate the icache the page has to + * be mapped at the final virtual address but not + * executable. + */ + if (reg->flags & (TEE_MATTR_PX | TEE_MATTR_UX)) { + uint32_t mask = TEE_MATTR_PX | TEE_MATTR_UX | + TEE_MATTR_PW | TEE_MATTR_UW; + void *va = (void *)page_va; + + /* Set a temporary read-only mapping */ + tblidx_set_entry(tblidx, pa, attr & ~mask); + tblidx_tlbi_entry(tblidx); + + dcache_clean_range_pou(va, SMALL_PAGE_SIZE); + if (clean_user_cache) + icache_inv_user_range(va, SMALL_PAGE_SIZE); + else + icache_inv_range(va, SMALL_PAGE_SIZE); + + /* Set the final mapping */ + tblidx_set_entry(tblidx, pa, attr); + tblidx_tlbi_entry(tblidx); + } else { + tblidx_set_entry(tblidx, pa, attr); + /* + * No need to flush TLB for this entry, it was + * invalid. We should use a barrier though, to make + * sure that the change is visible. + */ + dsb_ishst(); + } + pgt_inc_used_entries(tblidx.pgt); + + FMSG("Mapped 0x%" PRIxVA " -> 0x%" PRIxPA, page_va, pa); +} + +static void make_dirty_page(struct tee_pager_pmem *pmem, + struct vm_paged_region *reg, struct tblidx tblidx, + paddr_t pa) +{ + assert(reg->flags & (TEE_MATTR_UW | TEE_MATTR_PW)); + assert(!(pmem->flags & PMEM_FLAG_DIRTY)); + + FMSG("Dirty %#"PRIxVA, tblidx2va(tblidx)); + pmem->flags |= PMEM_FLAG_DIRTY; + tblidx_set_entry(tblidx, pa, get_region_mattr(reg->flags)); + tblidx_tlbi_entry(tblidx); +} + +/* + * This function takes a reference to a page (@fobj + fobj_pgidx) and makes + * the corresponding IV available. + * + * In case the page needs to be saved the IV must be writable, consequently + * is the page holding the IV made dirty. If the page instead only is to + * be verified it's enough that the page holding the IV is readonly and + * thus doesn't have to be made dirty too. + * + * This function depends on pager_spare_pmem pointing to a free pmem when + * entered. In case the page holding the needed IV isn't mapped this spare + * pmem is used to map the page. If this function has used pager_spare_pmem + * and assigned it to NULL it must be reassigned with a new free pmem + * before this function can be called again. + */ +static void make_iv_available(struct fobj *fobj, unsigned int fobj_pgidx, + bool writable) +{ + struct vm_paged_region *reg = pager_iv_region; + struct tee_pager_pmem *pmem = NULL; + struct tblidx tblidx = { }; + vaddr_t page_va = 0; + uint32_t attr = 0; + paddr_t pa = 0; + + page_va = fobj_get_iv_vaddr(fobj, fobj_pgidx) & ~SMALL_PAGE_MASK; + if (!IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV) || !page_va) { + assert(!page_va); + return; + } + + assert(reg && reg->type == PAGED_REGION_TYPE_RW); + assert(pager_spare_pmem); + assert(core_is_buffer_inside(page_va, 1, reg->base, reg->size)); + + tblidx = region_va2tblidx(reg, page_va); + /* + * We don't care if tee_pager_unhide_page() succeeds or not, we're + * still checking the attributes afterwards. + */ + tee_pager_unhide_page(reg, page_va); + tblidx_get_entry(tblidx, &pa, &attr); + if (!(attr & TEE_MATTR_VALID_BLOCK)) { + /* + * We're using the spare pmem to map the IV corresponding + * to another page. + */ + pmem = pager_spare_pmem; + pager_spare_pmem = NULL; + pmem_assign_fobj_page(pmem, reg, page_va); + + if (writable) + pmem->flags |= PMEM_FLAG_DIRTY; + + pager_deploy_page(pmem, reg, page_va, + false /*!clean_user_cache*/, writable); + } else if (writable && !(attr & TEE_MATTR_PW)) { + pmem = pmem_find(reg, page_va); + /* Note that pa is valid since TEE_MATTR_VALID_BLOCK is set */ + make_dirty_page(pmem, reg, tblidx, pa); + } +} + +static void pager_get_page(struct vm_paged_region *reg, struct abort_info *ai, + bool clean_user_cache) +{ + vaddr_t page_va = ai->va & ~SMALL_PAGE_MASK; + struct tblidx tblidx = region_va2tblidx(reg, page_va); + struct tee_pager_pmem *pmem = NULL; + bool writable = false; + uint32_t attr = 0; + + /* + * Get a pmem to load code and data into, also make sure + * the corresponding IV page is available. + */ + while (true) { + pmem = TAILQ_FIRST(&tee_pager_pmem_head); + if (!pmem) { + EMSG("No pmem entries"); + abort_print(ai); + panic(); + } + + if (pmem->fobj) { + pmem_unmap(pmem, NULL); + if (pmem_is_dirty(pmem)) { + uint8_t *va = pmem->va_alias; + + make_iv_available(pmem->fobj, pmem->fobj_pgidx, + true /*writable*/); + asan_tag_access(va, va + SMALL_PAGE_SIZE); + if (fobj_save_page(pmem->fobj, pmem->fobj_pgidx, + pmem->va_alias)) + panic("fobj_save_page"); + asan_tag_no_access(va, va + SMALL_PAGE_SIZE); + + pmem_clear(pmem); + + /* + * If the spare pmem was used by + * make_iv_available() we need to replace + * it with the just freed pmem. + * + * See make_iv_available() for details. + */ + if (IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV) && + !pager_spare_pmem) { + TAILQ_REMOVE(&tee_pager_pmem_head, + pmem, link); + pager_spare_pmem = pmem; + pmem = NULL; + } + + /* + * Check if the needed virtual page was + * made available as a side effect of the + * call to make_iv_available() above. If so + * we're done. + */ + tblidx_get_entry(tblidx, NULL, &attr); + if (attr & TEE_MATTR_VALID_BLOCK) + return; + + /* + * The freed pmem was used to replace the + * consumed pager_spare_pmem above. Restart + * to find another pmem. + */ + if (!pmem) + continue; + } + } + + TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link); + pmem_clear(pmem); + + pmem_assign_fobj_page(pmem, reg, page_va); + make_iv_available(pmem->fobj, pmem->fobj_pgidx, + false /*!writable*/); + if (!IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV) || pager_spare_pmem) + break; + + /* + * The spare pmem was used by make_iv_available(). We need + * to replace it with the just freed pmem. And get another + * pmem. + * + * See make_iv_available() for details. + */ + pmem_clear(pmem); + pager_spare_pmem = pmem; + } + + /* + * PAGED_REGION_TYPE_LOCK are always writable while PAGED_REGION_TYPE_RO + * are never writable. + * + * Pages from PAGED_REGION_TYPE_RW starts read-only to be + * able to tell when they are updated and should be tagged + * as dirty. + */ + if (reg->type == PAGED_REGION_TYPE_LOCK || + (reg->type == PAGED_REGION_TYPE_RW && abort_is_write_fault(ai))) + writable = true; + else + writable = false; + + pager_deploy_page(pmem, reg, page_va, clean_user_cache, writable); +} + +static bool pager_update_permissions(struct vm_paged_region *reg, + struct abort_info *ai, bool *handled) +{ + struct tblidx tblidx = region_va2tblidx(reg, ai->va); + struct tee_pager_pmem *pmem = NULL; + uint32_t attr = 0; + paddr_t pa = 0; + + *handled = false; + + tblidx_get_entry(tblidx, &pa, &attr); + + /* Not mapped */ + if (!(attr & TEE_MATTR_VALID_BLOCK)) + return false; + + /* Not readable, should not happen */ + if (abort_is_user_exception(ai)) { + if (!(attr & TEE_MATTR_UR)) + return true; + } else { + if (!(attr & TEE_MATTR_PR)) { + abort_print_error(ai); + panic(); + } + } + + switch (core_mmu_get_fault_type(ai->fault_descr)) { + case CORE_MMU_FAULT_TRANSLATION: + case CORE_MMU_FAULT_READ_PERMISSION: + if (ai->abort_type == ABORT_TYPE_PREFETCH) { + /* Check attempting to execute from an NOX page */ + if (abort_is_user_exception(ai)) { + if (!(attr & TEE_MATTR_UX)) + return true; + } else { + if (!(attr & TEE_MATTR_PX)) { + abort_print_error(ai); + panic(); + } + } + } + /* Since the page is mapped now it's OK */ + break; + case CORE_MMU_FAULT_WRITE_PERMISSION: + /* Check attempting to write to an RO page */ + pmem = pmem_find(reg, ai->va); + if (!pmem) + panic(); + if (abort_is_user_exception(ai)) { + if (!(reg->flags & TEE_MATTR_UW)) + return true; + if (!(attr & TEE_MATTR_UW)) + make_dirty_page(pmem, reg, tblidx, pa); + } else { + if (!(reg->flags & TEE_MATTR_PW)) { + abort_print_error(ai); + panic(); + } + if (!(attr & TEE_MATTR_PW)) + make_dirty_page(pmem, reg, tblidx, pa); + } + /* Since permissions has been updated now it's OK */ + break; + default: + /* Some fault we can't deal with */ + if (abort_is_user_exception(ai)) + return true; + abort_print_error(ai); + panic(); + } + *handled = true; + return true; +} + +#ifdef CFG_TEE_CORE_DEBUG +static void stat_handle_fault(void) +{ + static size_t num_faults; + static size_t min_npages = SIZE_MAX; + static size_t total_min_npages = SIZE_MAX; + + num_faults++; + if ((num_faults % 1024) == 0 || tee_pager_npages < total_min_npages) { + DMSG("nfaults %zu npages %zu (min %zu)", + num_faults, tee_pager_npages, min_npages); + min_npages = tee_pager_npages; /* reset */ + } + if (tee_pager_npages < min_npages) + min_npages = tee_pager_npages; + if (tee_pager_npages < total_min_npages) + total_min_npages = tee_pager_npages; +} +#else +static void stat_handle_fault(void) +{ +} +#endif + +bool tee_pager_handle_fault(struct abort_info *ai) +{ + struct vm_paged_region *reg; + vaddr_t page_va = ai->va & ~SMALL_PAGE_MASK; + uint32_t exceptions; + bool ret; + bool clean_user_cache = false; + +#ifdef TEE_PAGER_DEBUG_PRINT + if (!abort_is_user_exception(ai)) + abort_print(ai); +#endif + + /* + * We're updating pages that can affect several active CPUs at a + * time below. We end up here because a thread tries to access some + * memory that isn't available. We have to be careful when making + * that memory available as other threads may succeed in accessing + * that address the moment after we've made it available. + * + * That means that we can't just map the memory and populate the + * page, instead we use the aliased mapping to populate the page + * and once everything is ready we map it. + */ + exceptions = pager_lock(ai); + + stat_handle_fault(); + + /* check if the access is valid */ + if (abort_is_user_exception(ai)) { + reg = find_uta_region(ai->va); + clean_user_cache = true; + } else { + reg = find_region(&core_vm_regions, ai->va); + if (!reg) { + reg = find_uta_region(ai->va); + clean_user_cache = true; + } + } + if (!reg || !reg->pgt_array[0]) { + ret = false; + goto out; + } + + if (tee_pager_unhide_page(reg, page_va)) + goto out_success; + + /* + * The page wasn't hidden, but some other core may have + * updated the table entry before we got here or we need + * to make a read-only page read-write (dirty). + */ + if (pager_update_permissions(reg, ai, &ret)) { + /* + * Nothing more to do with the abort. The problem + * could already have been dealt with from another + * core or if ret is false the TA will be paniced. + */ + goto out; + } + + pager_get_page(reg, ai, clean_user_cache); + +out_success: + tee_pager_hide_pages(); + ret = true; +out: + pager_unlock(exceptions); + return ret; +} + +void tee_pager_add_pages(vaddr_t vaddr, size_t npages, bool unmap) +{ + size_t n = 0; + + DMSG("0x%" PRIxVA " - 0x%" PRIxVA " : %d", + vaddr, vaddr + npages * SMALL_PAGE_SIZE, (int)unmap); + + /* setup memory */ + for (n = 0; n < npages; n++) { + struct core_mmu_table_info *ti = NULL; + struct tee_pager_pmem *pmem = NULL; + vaddr_t va = vaddr + n * SMALL_PAGE_SIZE; + struct tblidx tblidx = { }; + unsigned int pgidx = 0; + paddr_t pa = 0; + uint32_t attr = 0; + + ti = find_table_info(va); + pgidx = core_mmu_va2idx(ti, va); + /* + * Note that we can only support adding pages in the + * valid range of this table info, currently not a problem. + */ + core_mmu_get_entry(ti, pgidx, &pa, &attr); + + /* Ignore unmapped pages/blocks */ + if (!(attr & TEE_MATTR_VALID_BLOCK)) + continue; + + pmem = calloc(1, sizeof(struct tee_pager_pmem)); + if (!pmem) + panic("out of mem"); + pmem_clear(pmem); + + pmem->va_alias = pager_add_alias_page(pa); + + if (unmap) { + core_mmu_set_entry(ti, pgidx, 0, 0); + pgt_dec_used_entries(find_core_pgt(va)); + } else { + struct vm_paged_region *reg = NULL; + + /* + * The page is still mapped, let's assign the region + * and update the protection bits accordingly. + */ + reg = find_region(&core_vm_regions, va); + assert(reg); + pmem_assign_fobj_page(pmem, reg, va); + tblidx = pmem_get_region_tblidx(pmem, reg); + assert(tblidx.pgt == find_core_pgt(va)); + assert(pa == get_pmem_pa(pmem)); + tblidx_set_entry(tblidx, pa, + get_region_mattr(reg->flags)); + } + + if (unmap && IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV) && + !pager_spare_pmem) { + pager_spare_pmem = pmem; + } else { + tee_pager_npages++; + incr_npages_all(); + set_npages(); + TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); + } + } + + /* + * As this is done at inits, invalidate all TLBs once instead of + * targeting only the modified entries. + */ + tlbi_all(); +} + +#ifdef CFG_PAGED_USER_TA +static struct pgt *find_pgt(struct pgt *pgt, vaddr_t va) +{ + struct pgt *p = pgt; + + while (p && (va & ~CORE_MMU_PGDIR_MASK) != p->vabase) + p = SLIST_NEXT(p, link); + return p; +} + +void tee_pager_assign_um_tables(struct user_mode_ctx *uctx) +{ + struct vm_paged_region *reg = NULL; + struct pgt *pgt = NULL; + size_t n = 0; + + if (!uctx->regions) + return; + + pgt = SLIST_FIRST(&uctx->pgt_cache); + TAILQ_FOREACH(reg, uctx->regions, link) { + for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) { + vaddr_t va = reg->base + CORE_MMU_PGDIR_SIZE * n; + struct pgt *p __maybe_unused = find_pgt(pgt, va); + + if (!reg->pgt_array[n]) + reg->pgt_array[n] = p; + else + assert(reg->pgt_array[n] == p); + } + } +} + +void tee_pager_pgt_save_and_release_entries(struct pgt *pgt) +{ + struct tee_pager_pmem *pmem = NULL; + struct vm_paged_region *reg = NULL; + struct vm_paged_region_head *regions = NULL; + uint32_t exceptions = pager_lock_check_stack(SMALL_PAGE_SIZE); + size_t n = 0; + + if (!pgt->num_used_entries) + goto out; + + TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { + if (pmem->fobj) + pmem_unmap(pmem, pgt); + } + assert(!pgt->num_used_entries); + +out: + regions = to_user_mode_ctx(pgt->ctx)->regions; + if (regions) { + TAILQ_FOREACH(reg, regions, link) { + for (n = 0; n < get_pgt_count(reg->base, reg->size); + n++) { + if (reg->pgt_array[n] == pgt) { + reg->pgt_array[n] = NULL; + break; + } + } + } + } + + pager_unlock(exceptions); +} +DECLARE_KEEP_PAGER(tee_pager_pgt_save_and_release_entries); +#endif /*CFG_PAGED_USER_TA*/ + +void tee_pager_release_phys(void *addr, size_t size) +{ + bool unmaped = false; + vaddr_t va = (vaddr_t)addr; + vaddr_t begin = ROUNDUP(va, SMALL_PAGE_SIZE); + vaddr_t end = ROUNDDOWN(va + size, SMALL_PAGE_SIZE); + struct vm_paged_region *reg; + uint32_t exceptions; + + if (end <= begin) + return; + + exceptions = pager_lock_check_stack(128); + + for (va = begin; va < end; va += SMALL_PAGE_SIZE) { + reg = find_region(&core_vm_regions, va); + if (!reg) + panic(); + unmaped |= tee_pager_release_one_phys(reg, va); + } + + if (unmaped) + tlbi_mva_range(begin, end - begin, SMALL_PAGE_SIZE); + + pager_unlock(exceptions); +} +DECLARE_KEEP_PAGER(tee_pager_release_phys); + +void *tee_pager_alloc(size_t size) +{ + tee_mm_entry_t *mm = NULL; + uint8_t *smem = NULL; + size_t num_pages = 0; + struct fobj *fobj = NULL; + + if (!size) + return NULL; + + mm = tee_mm_alloc(&tee_mm_vcore, ROUNDUP(size, SMALL_PAGE_SIZE)); + if (!mm) + return NULL; + + smem = (uint8_t *)tee_mm_get_smem(mm); + num_pages = tee_mm_get_bytes(mm) / SMALL_PAGE_SIZE; + fobj = fobj_locked_paged_alloc(num_pages); + if (!fobj) { + tee_mm_free(mm); + return NULL; + } + + tee_pager_add_core_region((vaddr_t)smem, PAGED_REGION_TYPE_LOCK, fobj); + fobj_put(fobj); + + asan_tag_access(smem, smem + num_pages * SMALL_PAGE_SIZE); + + return smem; +} + +vaddr_t tee_pager_init_iv_region(struct fobj *fobj) +{ + tee_mm_entry_t *mm = NULL; + uint8_t *smem = NULL; + + assert(!pager_iv_region); + + mm = tee_mm_alloc(&tee_mm_vcore, fobj->num_pages * SMALL_PAGE_SIZE); + if (!mm) + panic(); + + smem = (uint8_t *)tee_mm_get_smem(mm); + tee_pager_add_core_region((vaddr_t)smem, PAGED_REGION_TYPE_RW, fobj); + fobj_put(fobj); + + asan_tag_access(smem, smem + fobj->num_pages * SMALL_PAGE_SIZE); + + pager_iv_region = find_region(&core_vm_regions, (vaddr_t)smem); + assert(pager_iv_region && pager_iv_region->fobj == fobj); + + return (vaddr_t)smem; +} diff --git a/optee/optee_os/core/arch/arm/plat-amlogic/conf.mk b/optee/optee_os/core/arch/arm/plat-amlogic/conf.mk new file mode 100644 index 0000000..a28779c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-amlogic/conf.mk @@ -0,0 +1,17 @@ +PLATFORM_FLAVOR ?= axg + +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_TEE_CORE_NB_CORE,4) + +CFG_TZDRAM_START ?= 0x05300000 +CFG_TZDRAM_SIZE ?= 0x00c00000 +CFG_SHMEM_START ?= 0x05000000 +CFG_SHMEM_SIZE ?= 0x00100000 + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_AMLOGIC_UART,y) + +$(call force,CFG_WITH_PAGER,n) +$(call force,CFG_ARM64_core,y) diff --git a/optee/optee_os/core/arch/arm/plat-amlogic/link.mk b/optee/optee_os/core/arch/arm/plat-amlogic/link.mk new file mode 100644 index 0000000..704996b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-amlogic/link.mk @@ -0,0 +1,17 @@ +include core/arch/arm/kernel/link.mk + +# Create BL32 image from the native binary images + +define aml_bin2img_cmd + @$(cmd-echo-silent) ' GEN $@' + $(q)./core/arch/arm/plat-amlogic/scripts/aml_bin2img.py +endef + +ifneq (,$(filter $(PLATFORM_FLAVOR),axg)) +all: $(link-out-dir)/bl32.img +cleanfiles += $(link-out-dir)/bl32.img +$(link-out-dir)/bl32.img: $(link-out-dir)/tee-pager_v2.bin + $(aml_bin2img_cmd) --source $< --dest $@ --entry 0x5300000 \ + --res_mem_start 0x5300000 --res_mem_size 0x1000000 \ + --sec_mem_start 0x5300000 --sec_mem_size 0xc00000 +endif diff --git a/optee/optee_os/core/arch/arm/plat-amlogic/main.c b/optee/optee_os/core/arch/arm/plat-amlogic/main.c new file mode 100644 index 0000000..fd5ede4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-amlogic/main.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020 Carlo Caione + */ + +#include +#include +#include +#include +#include + +static struct amlogic_uart_data console_data; +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); + +void console_init(void) +{ + amlogic_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-amlogic/platform_config.h b/optee/optee_os/core/arch/arm/plat-amlogic/platform_config.h new file mode 100644 index 0000000..a791e46 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-amlogic/platform_config.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020 Carlo Caione + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#define GIC_BASE 0xFFC01000 +#define GICC_OFFSET 0x2000 +#define GICD_OFFSET 0x1000 + +#define CONSOLE_UART_BASE 0xFF803000 + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py b/optee/optee_os/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py new file mode 100755 index 0000000..28a037d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020 Carlo Caione +# +# Derived from plat-stm32mp1/scripts/stm32image.py +# + +import argparse +import struct +import mmap + +header_size = 0x200 +ext_magic_number = 0x12348765 +version = 0x00002710 + + +def get_size(file): + file.seek(0, 2) # End of the file + size = file.tell() + return size + + +def aml_set_header(dest_fd, entry, res_mem_start, res_mem_size, sec_mem_start, + sec_mem_size): + dest_fd.seek(0, 0) + + dest_fd.write(struct.pack(' 0: + mmsrc = mmap.mmap(src_fd.fileno(), 0, access=mmap.ACCESS_READ) + dest_fd.write(mmsrc[:sizesrc]) + mmsrc.close() + + src_fd.close() + + aml_set_header(dest_fd, entry, res_mem_start, res_mem_size, sec_mem_start, + sec_mem_size) + + dest_fd.close() + + +def auto_int(x): + return int(x, 0) + + +def get_args(): + parser = argparse.ArgumentParser() + + parser.add_argument('--source', + required=True, + help='Source file') + + parser.add_argument('--dest', + required=True, + help='Destination file') + + parser.add_argument('--entry', + required=True, + type=auto_int, + help='Entry point') + + parser.add_argument('--res_mem_start', + required=True, + type=auto_int, + help='Reserved memory start') + + parser.add_argument('--res_mem_size', + required=True, + type=auto_int, + help='Reserved memory size') + + parser.add_argument('--sec_mem_start', + required=True, + type=auto_int, + help='Secure memory start') + + parser.add_argument('--sec_mem_size', + required=True, + type=auto_int, + help='Secure memory size') + + return parser.parse_args() + + +def main(): + args = get_args() + + source_file = args.source + destination_file = args.dest + entry_point = args.entry + res_mem_start = args.res_mem_start + res_mem_size = args.res_mem_size + sec_mem_start = args.sec_mem_start + sec_mem_size = args.sec_mem_size + + aml_create_header_file(source_file, + destination_file, + entry_point, + res_mem_start, + res_mem_size, + sec_mem_start, + sec_mem_size) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/core/arch/arm/plat-amlogic/sub.mk b/optee/optee_os/core/arch/arm/plat-amlogic/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-amlogic/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-aspeed/conf.mk b/optee/optee_os/core/arch/arm/plat-aspeed/conf.mk new file mode 100644 index 0000000..8cc7871 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/conf.mk @@ -0,0 +1,23 @@ +PLATFORM_FLAVOR ?= ast2600 + +ifeq ($(PLATFORM_FLAVOR),ast2600) +include core/arch/arm/cpu/cortex-a7.mk + +$(call force,CFG_8250_UART,y) +$(call force,CFG_ARM32_core,y) +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_GIC,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) + +CFG_NUM_THREADS ?= $(CFG_TEE_CORE_NB_CORE) + +CFG_DRAM_BASE ?= 0x80000000 +CFG_DRAM_SIZE ?= 0x40000000 + +CFG_TZDRAM_START ?= 0x88000000 +CFG_TZDRAM_SIZE ?= 0x01000000 + +CFG_CORE_RESERVED_SHM ?= n +else +$(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)") +endif diff --git a/optee/optee_os/core/arch/arm/plat-aspeed/core_pos_a32.S b/optee/optee_os/core/arch/arm/plat-aspeed/core_pos_a32.S new file mode 100644 index 0000000..35932d6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/core_pos_a32.S @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Aspeed Technology Inc. + */ + +#include +#include +#include + +FUNC get_core_pos_mpidr , : + /* + * need this to correct core0 - 0xf00, core1 - 0xf01, ... + */ + and r0, r0, #MPIDR_CPU_MASK + bx lr +END_FUNC get_core_pos_mpidr diff --git a/optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c b/optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c new file mode 100644 index 0000000..c018894 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/platform_ast2600.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Aspeed Technology Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum TZM_PERM { + TZM_PERM_VGA_CURSOR_RD, + TZM_PERM_VGA_CRT_RD, + TZM_PERM_SOC_DISPLAY_RD, + TZM_PERM_PCIE_BUS1_RW, + TZM_PERM_VIDEO_HIGH_WR, + TZM_PERM_CPU_RW, + TZM_PERM_SLI_RW, + TZM_PERM_PCIE_BUS2_RW, + TZM_PERM_USB20_HUB_EHCI1_DMA_RW, + TZM_PERM_USB20_DEV_EHCI2_DMA_RW, + TZM_PERM_USB11_UCHI_HOST_RW, + TZM_PERM_AHB_RW, + TZM_PERM_CM3_DATA_RW, + TZM_PERM_CM3_INSN_RW, + TZM_PERM_MAC0_DMA_RW, + TZM_PERM_MAC1_DMA_RW, + TZM_PERM_SDIO_DMA_RW, + TZM_PERM_PILOT_RW, + TZM_PERM_XDMA1_RW, + TZM_PERM_MCTP1_RW, + TZM_PERM_VIDEO_FLAG_RW, + TZM_PERM_VIDEO_LOW_WR, + TZM_PERM_2D_DATA_RW, + TZM_PERM_ENCRYPT_RW, + TZM_PERM_MCTP2_RW, + TZM_PERM_XDMA2_RW, + TZM_PERM_ECC_RSA_RW, +}; + +register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SMALL_PAGE_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE + GICD_OFFSET, GIC_DIST_REG_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE + GICC_OFFSET, GIC_CPU_REG_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, AHBC_BASE, SMALL_PAGE_SIZE); +register_phys_mem(MEM_AREA_IO_NSEC, SCU_BASE, SMALL_PAGE_SIZE); + +#define AHBC_REG_WR_PROT 0x204 +#define AHBC_TZP_ACCESS1 0x280 +#define AHBC_TZP_HACE BIT(20) +#define AHBC_TZM_ST(i) (0x300 + ((i) * 0x10)) +#define AHBC_TZM_ED(i) (0x304 + ((i) * 0x10)) +#define AHBC_TZM_PERM(i) (0x308 + ((i) * 0x10)) + +register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE); + +static struct serial8250_uart_data console_data; +static struct gic_data gic_data; + +void main_init_gic(void) +{ + gic_init(&gic_data, GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +void plat_primary_init_early(void) +{ + vaddr_t ahbc_virt = 0; + uint32_t tzm_perm = 0; + + ahbc_virt = core_mmu_get_va(AHBC_BASE, + MEM_AREA_IO_SEC, SMALL_PAGE_SIZE); + if (!ahbc_virt) + panic(); + + tzm_perm = BIT(TZM_PERM_CPU_RW); + if (IS_ENABLED(CFG_ASPEED_CRYPTO_DRIVER)) { + tzm_perm |= BIT(TZM_PERM_ENCRYPT_RW); + io_write32(ahbc_virt + AHBC_TZP_ACCESS1, AHBC_TZP_HACE); + } + + io_write32(ahbc_virt + AHBC_TZM_PERM(0), tzm_perm); + io_write32(ahbc_virt + AHBC_TZM_ED(0), + CFG_TZDRAM_START + CFG_TZDRAM_SIZE - 1); + io_write32(ahbc_virt + AHBC_TZM_ST(0), + CFG_TZDRAM_START | BIT(0)); + io_write32(ahbc_virt + AHBC_REG_WR_PROT, BIT(16)); +} diff --git a/optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h b/optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h new file mode 100644 index 0000000..fd58a79 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/platform_config.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Aspeed Technology Inc. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#if defined(PLATFORM_FLAVOR_ast2600) +#define GIC_BASE 0x40460000 +#define GICC_OFFSET 0x2000 +#define GICD_OFFSET 0x1000 + +#define AHBC_BASE 0x1e600000 +#define SCU_BASE 0x1e6e2000 +#define UART5_BASE 0x1e784000 + +#define CONSOLE_UART_BASE UART5_BASE +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 1846153 +#else +#error "Unknown platform flavor" +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-aspeed/sub.mk b/optee/optee_os/core/arch/arm/plat-aspeed/sub.mk new file mode 100644 index 0000000..422b3e5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-aspeed/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-$(PLATFORM_FLAVOR_ast2600) += platform_ast2600.c core_pos_a32.S diff --git a/optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.c b/optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.c new file mode 100644 index 0000000..2e5c9ad --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include + +static struct bcm_elog global_elog; + +void bcm_elog_putchar(char ch) +{ + struct bcm_elog *elog = &global_elog; + uint32_t offset = 0, len = 0; + vaddr_t base = 0; + + base = io_pa_or_va(&elog->base, elog->max_size); + + offset = io_read32(base + BCM_ELOG_OFF_OFFSET); + len = io_read32(base + BCM_ELOG_LEN_OFFSET); + io_write8(base + offset, ch); + offset++; + + /* Log buffer is now full and need to wrap around */ + if (offset >= elog->max_size) + offset = BCM_ELOG_HEADER_LEN; + + /* Only increment length when log buffer is not full */ + if (len < elog->max_size - BCM_ELOG_HEADER_LEN) + len++; + + io_write32(base + BCM_ELOG_OFF_OFFSET, offset); + io_write32(base + BCM_ELOG_LEN_OFFSET, len); +} + +void bcm_elog_init(uintptr_t pa_base, uint32_t size) +{ + struct bcm_elog *elog = &global_elog; + uint32_t val = 0; + vaddr_t base = 0; + + elog->base.pa = pa_base; + elog->max_size = size; + + base = io_pa_or_va(&elog->base, BCM_ELOG_HEADER_LEN); + + /* + * If a valid signature is found, it means logging is already + * initialized. In this case, we should not re-initialize the entry + * header in the designated memory + */ + val = io_read32(base + BCM_ELOG_SIG_OFFSET); + if (val != BCM_ELOG_SIG_VAL) { + io_write32(base + BCM_ELOG_SIG_OFFSET, BCM_ELOG_SIG_VAL); + io_write32(base + BCM_ELOG_OFF_OFFSET, BCM_ELOG_HEADER_LEN); + io_write32(base + BCM_ELOG_LEN_OFFSET, 0); + } +} diff --git a/optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.h b/optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.h new file mode 100644 index 0000000..218da37 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/bcm_elog.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef BCM_ELOG_H +#define BCM_ELOG_H + +#include + +/* Error logging signature offset and value */ +#define BCM_ELOG_SIG_OFFSET 0x0000 +#define BCM_ELOG_SIG_VAL 0x75767971 + +/* Current logging offset that points to where new logs should be added */ +#define BCM_ELOG_OFF_OFFSET 0x0004 + +/* Current logging length (excluding header) */ +#define BCM_ELOG_LEN_OFFSET 0x0008 + +#define BCM_ELOG_HEADER_LEN 12 + +/* + * @base: base address of memory where log is saved + * @max_size: max size of memory reserved for logging + */ +struct bcm_elog { + struct io_pa_va base; + uint32_t max_size; +}; + +void bcm_elog_init(uintptr_t pa_base, uint32_t size); +void bcm_elog_putchar(char ch); + +#endif /* BCM_ELOG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-bcm/conf.mk b/optee/optee_os/core/arch/arm/plat-bcm/conf.mk new file mode 100644 index 0000000..afcd0c0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/conf.mk @@ -0,0 +1,43 @@ +PLATFORM_FLAVOR ?= ns3 + +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_8250_UART,y) +$(call force,CFG_TEE_CORE_DEBUG,n) +$(call force,CFG_GIC,y) + +$(call force,CFG_WITH_LPAE,y) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +$(call force,CFG_TEE_CORE_NB_CORE,8) +CFG_TZDRAM_START ?= 0x8e000000 +CFG_TZDRAM_SIZE ?= 0x01000000 # 16MB +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) - $(CFG_SHMEM_SIZE)) +CFG_SHMEM_SIZE ?= 0x01000000 # 16MB +CFG_TEE_RAM_VA_SIZE := 0x400000 # 4MB + +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) + +ifeq ($(PLATFORM_FLAVOR),ns3) +$(call force,CFG_PL022,y) +$(call force,CFG_SP805_WDT,y) +$(call force,CFG_BCM_HWRNG,y) +$(call force,CFG_BCM_SOTP,y) +$(call force,CFG_BCM_GPIO,y) +CFG_BNXT_FW ?= y +CFG_BCM_ELOG_DUMP ?= y +endif + +CFG_BCM_ELOG_AP_UART_LOG_BASE ?= 0x8f110000 +CFG_BCM_ELOG_AP_UART_LOG_SIZE ?= 0x10000 + +CFG_BCM_ELOG_BASE ?= 0x8f120000 +CFG_BCM_ELOG_SIZE ?= 0x100000 + +ifeq ($(DEBUG),1) +platform-cflags += -gdwarf-2 +platform-aflags += -gdwarf-2 +endif + +CFG_WITH_STACK_CANARIES ?= n diff --git a/optee/optee_os/core/arch/arm/plat-bcm/crc32.c b/optee/optee_os/core/arch/arm/plat-bcm/crc32.c new file mode 100644 index 0000000..c716f37 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/crc32.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include + +static const uint32_t crc32tbl[] = { /* CRC polynomial 0xedb88320 */ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static uint32_t ucrc32(const char ch, uint32_t crc) +{ + return crc32tbl[(crc ^ ch) & 0xff] ^ (crc >> 8); +} + +uint32_t crc32i(uint32_t crc, const char *buf, size_t len) +{ + size_t l = 0; + + for (l = 0; l < len; l++) + crc = ucrc32(buf[l], crc); + + return ~crc; +} diff --git a/optee/optee_os/core/arch/arm/plat-bcm/crc32.h b/optee/optee_os/core/arch/arm/plat-bcm/crc32.h new file mode 100644 index 0000000..acfb15c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/crc32.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef CRC32_H +#define CRC32_H + +#include +#include + +#define CRC32_INIT_VAL (~0) +#define CRC32 crc32i + +uint32_t crc32i(uint32_t crc, const char *buf, size_t len); + +#endif /* CRC32_H */ diff --git a/optee/optee_os/core/arch/arm/plat-bcm/main.c b/optee/optee_os/core/arch/arm/plat-bcm/main.c new file mode 100644 index 0000000..ead5b25 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/main.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct gic_data gic_data; +struct serial8250_uart_data console_data; + +#ifdef BCM_DEVICE0_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE0_BASE, BCM_DEVICE0_SIZE); +#endif +#ifdef BCM_DEVICE1_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE1_BASE, BCM_DEVICE1_SIZE); +#endif +#ifdef BCM_DEVICE2_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE2_BASE, BCM_DEVICE2_SIZE); +#endif +#ifdef BCM_DEVICE3_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE3_BASE, BCM_DEVICE3_SIZE); +#endif +#ifdef BCM_DEVICE4_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE4_BASE, BCM_DEVICE4_SIZE); +#endif +#ifdef BCM_DEVICE5_BASE +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, BCM_DEVICE5_BASE, BCM_DEVICE5_SIZE); +#endif +#ifdef BCM_DRAM0_NS_BASE +register_dynamic_shm(BCM_DRAM0_NS_BASE, BCM_DRAM0_NS_SIZE); +#endif +#ifdef BCM_DRAM1_NS_BASE +register_dynamic_shm(BCM_DRAM1_NS_BASE, BCM_DRAM1_NS_SIZE); +#endif +#ifdef BCM_DRAM2_NS_BASE +register_dynamic_shm(BCM_DRAM2_NS_BASE, BCM_DRAM2_NS_SIZE); +#endif +#ifdef BCM_DRAM0_SEC_BASE +register_phys_mem(MEM_AREA_RAM_SEC, BCM_DRAM0_SEC_BASE, BCM_DRAM0_SEC_SIZE); +#endif +#ifdef CFG_BCM_ELOG_AP_UART_LOG_BASE +register_phys_mem(MEM_AREA_IO_NSEC, CFG_BCM_ELOG_AP_UART_LOG_BASE, + CFG_BCM_ELOG_AP_UART_LOG_SIZE); +#endif +#ifdef CFG_BCM_ELOG_BASE +register_phys_mem(MEM_AREA_RAM_NSEC, CFG_BCM_ELOG_BASE, CFG_BCM_ELOG_SIZE); +#endif + +void plat_trace_ext_puts(const char *str) +{ + const char *p; + + for (p = str; *p; p++) + bcm_elog_putchar(*p); +} + +void console_init(void) +{ + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); + + bcm_elog_init(CFG_BCM_ELOG_AP_UART_LOG_BASE, + CFG_BCM_ELOG_AP_UART_LOG_SIZE); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void main_init_gic(void) +{ + gic_init_base_addr(&gic_data, 0, GICD_BASE); + itr_init(&gic_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-bcm/platform_config.h b/optee/optee_os/core/arch/arm/plat-bcm/platform_config.h new file mode 100644 index 0000000..3d59c82 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/platform_config.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +#define STACK_ALIGNMENT 64 + +#define CONSOLE_UART_CLK_IN_HZ 25000000 +#define CONSOLE_BAUDRATE 115200 + +#define CONSOLE_UART_BASE 0x68a10000 + +#define GICD_BASE 0x63c00000 + +#define SMBUS0_BASE 0x689b0000 +#define SMBUS0_END (SMBUS0_BASE + 0xB0) + +#define SECURE_GPIO_BASE0 0x68b00000 +#define ASIU_GPIO_INTR 190 +#define GPIO_NUM_START0 0 +#define NUM_GPIOS0 151 + +#define CHIP_SECURE_GPIO_CONTROL0_BASE 0x68b60000 + +#define SPI_0_BASE 0x68a80000 +#define SPI_0_END (SPI_0_BASE + 0x1000) +#define SPI_0_CLK_HZ 175000000 +#define SPI_0_CS_MUX_PAD 0x68a40490 + +#define HWRNG_BASE 0x68b20000 +#define HWRNG_END (HWRNG_BASE + 0x28) + +#define SOTP_BASE 0x68b50000 + +/* NO ECC bits are present from ROW_0 to ROW_20, i.e Section 0 to Section 3 */ +#define SOTP_NO_ECC_ROWS 20 + +/* Secure Watch Dog */ +#define SEC_WDT_BASE 0x68B30000 +#define SEC_WDT_END (SEC_WDT_BASE + 0x1000) +#define SEC_WDT_CLK_HZ 12500000 +#define SEC_WDT_INTR 192 + +#define BNXT_BASE 0x60800000 + +#define QSPI_MEM_BASE 0x70000000 + +/* device memory ranges */ +#define BCM_DEVICE0_BASE GICD_BASE +#define BCM_DEVICE0_SIZE CORE_MMU_PGDIR_SIZE +#define BCM_DEVICE1_BASE SMBUS0_BASE +#define BCM_DEVICE1_SIZE CORE_MMU_PGDIR_SIZE +#define BCM_DEVICE4_BASE BNXT_BASE +#define BCM_DEVICE4_SIZE 0x800000 +#define BCM_DEVICE5_BASE QSPI_MEM_BASE +#define BCM_DEVICE5_SIZE 0x800000 + +/* NS DDR ranges */ +#define BCM_DRAM0_NS_BASE 0x80000000 +#define BCM_DRAM0_NS_SIZE 0xae00000 +#define BCM_DRAM1_NS_BASE 0x90000000 +#define BCM_DRAM1_NS_SIZE 0x70000000 +#define BCM_DRAM2_NS_BASE 0x880100000 +#define BCM_DRAM2_NS_SIZE 0x17ff00000 + +/* Secure DDR ranges */ +#define BCM_DRAM0_SEC_BASE 0x8ae00000 +#define BCM_DRAM0_SEC_SIZE 0x2200000 + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-bcm/sub.mk b/optee/optee_os/core/arch/arm/plat-bcm/sub.mk new file mode 100644 index 0000000..d3616b4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-bcm/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-y += crc32.c +srcs-y += bcm_elog.c diff --git a/optee/optee_os/core/arch/arm/plat-corstone1000/conf.mk b/optee/optee_os/core/arch/arm/plat-corstone1000/conf.mk new file mode 100644 index 0000000..98347b1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-corstone1000/conf.mk @@ -0,0 +1,44 @@ +PLATFORM_FLAVOR ?= mps3 + +# ARM debugger needs this +platform-cflags-debug-info = -gdwarf-2 +platform-aflags-debug-info = -gdwarf-2 + +$(call force,CFG_HWSUPP_MEM_PERM_WXN,y) +$(call force,CFG_HWSUPP_MEM_PERM_PXN,y) +$(call force,CFG_ENABLE_SCTLR_RR,n) +$(call force,CFG_ENABLE_SCTLR_Z,n) + +$(call force,CFG_WITH_LPAE,y) +$(call force,CFG_PSCI_ARM64,y) +$(call force,CFG_DT,y) +$(call force,CFG_EXTERNAL_DTB_OVERLAY,y) + +$(call force,CFG_CORE_SEL1_SPMC,y) +$(call force,CFG_CORE_FFA,y) +$(call force,CFG_SECURE_PARTITION,y) + +$(call force,CFG_GIC,y) +$(call force,CFG_PL011,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_ARM64_core,y) + +arm64-platform-cpuarch := cortex-a35 +arm64-platform-cflags += -mcpu=$(arm64-platform-cpuarch) +arm64-platform-aflags += -mcpu=$(arm64-platform-cpuarch) + +CFG_WITH_STATS ?= y +CFG_WITH_ARM_TRUSTED_FW ?= y + +CFG_TEE_CORE_NB_CORE ?= 1 +CFG_TZDRAM_START ?= 0x02002000 + +# TEE_RAM (OPTEE kernel + DATA) + TA_RAM = 3MB +CFG_TZDRAM_SIZE ?= 0x300000 +CFG_SHMEM_START ?= 0x86000000 +CFG_SHMEM_SIZE ?= 0x00200000 + +CFG_DDR_SIZE ?= 0x7f000000 +CFG_DT_ADDR ?= 0x82100000 +CFG_DTB_MAX_SIZE ?= 0x100000 +CFG_CORE_HEAP_SIZE ?= 131072 diff --git a/optee/optee_os/core/arch/arm/plat-corstone1000/main.c b/optee/optee_os/core/arch/arm/plat-corstone1000/main.c new file mode 100644 index 0000000..6986457 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-corstone1000/main.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct gic_data gic_data __nex_bss; +static struct pl011_data console_data __nex_bss; + +register_ddr(DRAM0_BASE, DRAM0_SIZE); +register_ddr(MM_COMM_BUF_BASE, MM_COMM_BUF_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE); + +void main_init_gic(void) +{ + gic_init_base_addr(&gic_data, GICC_BASE, GICD_BASE); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, + CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-corstone1000/platform_config.h b/optee/optee_os/core/arch/arm/plat-corstone1000/platform_config.h new file mode 100644 index 0000000..6653d38 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-corstone1000/platform_config.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Arm Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#define GIC_BASE 0x1c000000 + +#define UART0_BASE 0x1a510000 +#define UART1_BASE 0x1a520000 +#define CONSOLE_UART_BASE UART1_BASE + +#define DRAM0_BASE 0x80000000 +#define DRAM0_SIZE CFG_DDR_SIZE + +#define GICD_OFFSET 0x10000 +#define GICC_OFFSET 0x2F000 + +#define GICD_BASE (GIC_BASE + GICD_OFFSET) +#define GICC_BASE (GIC_BASE + GICC_OFFSET) + +#define MM_COMM_BUF_BASE 0x02000000 +#define MM_COMM_BUF_SIZE 0x1000 + +#define UART_BAUDRATE 115200 +#define CONSOLE_BAUDRATE UART_BAUDRATE + +#define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */ + +#define CONSOLE_UART_CLK_IN_HZ UL(50000000) /* 50MHz*/ + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-corstone1000/sub.mk b/optee/optee_os/core/arch/arm/plat-corstone1000/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-corstone1000/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-d02/conf.mk b/optee/optee_os/core/arch/arm/plat-d02/conf.mk new file mode 100644 index 0000000..f96895d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d02/conf.mk @@ -0,0 +1,34 @@ +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_TEE_CORE_NB_CORE,16) +CFG_NUM_THREADS ?= 16 +CFG_CRYPTO_WITH_CE ?= y +CFG_WITH_SOFTWARE_PRNG ?= n +# Overrides default in mk/config.mk with 96 kB +CFG_CORE_HEAP_SIZE ?= 98304 + +$(call force,CFG_HI16XX_UART,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) +$(call force,CFG_HI16XX_RNG,y) +endif +$(call force,CFG_WITH_LPAE,y) + +ifeq ($(CFG_ARM64_core),y) +CFG_CORE_TZSRAM_EMUL_SIZE ?= 655360 +else +CFG_CORE_TZSRAM_EMUL_SIZE ?= 524288 +endif + +# 20MB-384kB of secure RAM +ifeq ($(CFG_WITH_PAGER),y) +CFG_TEE_RAM_VA_SIZE ?= 0x00400000 +else +CFG_TEE_RAM_VA_SIZE ?= 0x00200000 +endif +CFG_TZDRAM_START ?= 0x50400000 +CFG_TZDRAM_SIZE ?= 0x013a00000 +CFG_SHMEM_START ?= 0x50000000 +CFG_SHMEM_SIZE ?= 0x00400000 + diff --git a/optee/optee_os/core/arch/arm/plat-d02/main.c b/optee/optee_os/core/arch/arm/plat-d02/main.c new file mode 100644 index 0000000..759ca3b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d02/main.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +static struct hi16xx_uart_data console_data; + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, + HI16XX_UART_REG_SIZE); + +void console_init(void) +{ + hi16xx_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-d02/platform_config.h b/optee/optee_os/core/arch/arm/plat-d02/platform_config.h new file mode 100644 index 0000000..eb91def --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d02/platform_config.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +/* UART */ +#define PERI_SUB_CTRL_ADDR 0x80000000 +#define CONSOLE_UART_BASE (PERI_SUB_CTRL_ADDR + 0x00300000) +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 200000000 + +/* ALG sub-controller */ +#define ALG_SC_BASE 0xD0000000 +#define ALG_SC_REG_SIZE 0xF010 + +/* RNG */ +#define RNG_BASE 0xD1010000 +#define RNG_REG_SIZE 0x18 + +/* + * HiSilicon D02 memory map + * + * Note: the physical address ranges below correspond to DRAM which is + * non-secure by default. Therefore, the terms TZDRAM and TZSRAM may not + * reflect the reality and only indicate areas that "would normally be" + * secure DRAM and secure SRAM in a more complete implementation. + * The memory map was defined like this for lack of better documentation. + * It is good enough for development/testing purposes. + * + * CFG_WITH_PAGER=n + * + * 0x7FC0_0000 - + * Linux/other | DRAM1 + * 0x5180_0000 - + * TA RAM: 16 MiB | + * 0x5080_0000 | TZDRAM + * TEE RAM: 4 MiB (TEE_RAM_VA_SIZE) | + * 0x5040_0000 [TZDRAM_BASE, TEE_LOAD_ADDR] - + * Shared memory: 4 MiB | SHMEM + * 0x5000_0000 - + * Linux/other | DRAM0 + * 0x0000_0000 [DRAM0_BASE] - + * + * CFG_WITH_PAGER=y + * + * 0x7FC0_0000 - + * Linux/other | DRAM1 + * 0x5180_0000 - + * TA RAM: 20096 KiB (TZDRAM_SIZE) | TZDRAM + * 0x5046_0000 - + * TEE RAM: 384 KiB (TZSRAM_SIZE) | TZSRAM + * 0x5040_0000 [TZSRAM_BASE, TEE_LOAD_ADDR] - + * Shared memory: 4 MiB | SHMEM + * 0x5000_0000 - + * Linux/other | DRAM0 + * 0x0000_0000 [DRAM0_BASE] - + */ + +#define DRAM0_BASE 0x00000000 +#define DRAM0_SIZE 0x50000000 + +#define DRAM1_BASE 0x51800000 +#define DRAM1_SIZE 0x2E400000 + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-d02/sub.mk b/optee/optee_os/core/arch/arm/plat-d02/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d02/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-d06/conf.mk b/optee/optee_os/core/arch/arm/plat-d06/conf.mk new file mode 100644 index 0000000..98a8fa0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d06/conf.mk @@ -0,0 +1,28 @@ +include core/arch/arm/cpu/cortex-armv8-0.mk + +CFG_TEE_CORE_NB_CORE ?= 128 +CFG_NUM_THREADS ?= 96 +CFG_CRYPTO_WITH_CE ?= y + +CFG_WITH_PAGER ?= n +CFG_WITH_SOFTWARE_PRNG ?= y +CFG_WITH_STATS ?= y +CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_WITH_LPAE,y) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_LPAE_ADDR_SPACE_BITS,48) +$(call force,CFG_LPC_UART,y) + +CFG_TEE_CORE_LOG_LEVEL ?= 4 + +CFG_CORE_HEAP_SIZE ?= 0x008000000 +CFG_CORE_ARM64_PA_BITS ?= 40 +CFG_TEE_RAM_VA_SIZE ?= 0x009000000 +CFG_TZDRAM_START ?= 0x20C0000000 +CFG_TZDRAM_SIZE ?= 0x32000000 +CFG_SHMEM_START ?= 0x50000000 +CFG_SHMEM_SIZE ?= 0x04000000 diff --git a/optee/optee_os/core/arch/arm/plat-d06/core_pos_a64.S b/optee/optee_os/core/arch/arm/plat-d06/core_pos_a64.S new file mode 100644 index 0000000..d744cf7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d06/core_pos_a64.S @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2019, Arm Limited. All rights reserved. + * Copyright (c) 2020, Marek Vasut + * Copyright (c) 2022, Huawei Technologies Co., Ltd + */ + +#include +#include +#include + +/* + * bit8~bit10: core index + * bit16~bit18: ccl index + * bit20~bit22: sccl index + * 96 cores: index = sccl * 24 + ccl * 4 + core + * 128 cores: index = sccl * 32 + ccl * 4 + core (now used) + */ + +FUNC get_core_pos_mpidr , : + lsr x1, x0, 8 + and x2, x1, 0x7 + + lsr x1, x0, 16 + and x3, x1, 0x7 + + lsr x1, x0, 20 + and x4, x1, 0x7 + + mov x5, x4 +#if (CFG_TEE_CORE_NB_CORE == 96) + lsl x5, x5, 1 + add x5, x5, x4 + lsl x5, x5, 1 +#elif (CFG_TEE_CORE_NB_CORE == 128) + lsl x5, x5, 3 +#else + static_assert(0); +#endif + add x5, x5, x3 + lsl x5, x5, 2 + add x5, x5, x2 + + mov x0, x5 + + ret +END_FUNC get_core_pos_mpidr diff --git a/optee/optee_os/core/arch/arm/plat-d06/main.c b/optee/optee_os/core/arch/arm/plat-d06/main.c new file mode 100644 index 0000000..7736944 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d06/main.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2022, Huawei Technologies Co., Ltd + */ +#include +#include +#include + +static struct lpc_uart_data console_data __nex_bss; + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, LPC_BASE, LPC_SIZE); + +void console_init(void) +{ + lpc_uart_init(&console_data, LPC_BASE, CONSOLE_UART_CLK_IN_HZ, + CONSOLE_BAUDRATE); + + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-d06/platform_config.h b/optee/optee_os/core/arch/arm/plat-d06/platform_config.h new file mode 100644 index 0000000..81979bd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d06/platform_config.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2022, Huawei Technologies Co., Ltd + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +/* UART */ +#define UART_BASE 0x2f8 +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 200 + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-d06/sub.mk b/optee/optee_os/core/arch/arm/plat-d06/sub.mk new file mode 100644 index 0000000..4324853 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-d06/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-y += core_pos_a64.S diff --git a/optee/optee_os/core/arch/arm/plat-hikey/conf.mk b/optee/optee_os/core/arch/arm/plat-hikey/conf.mk new file mode 100644 index 0000000..1fe28b9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hikey/conf.mk @@ -0,0 +1,64 @@ +PLATFORM_FLAVOR ?= hikey + +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_PL011,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) + +CFG_NUM_THREADS ?= 8 +CFG_CRYPTO_WITH_CE ?= y + +ifeq ($(PLATFORM_FLAVOR),hikey) +CFG_CORE_HEAP_SIZE ?= 73728 +CFG_PL061 ?= y +CFG_PL022 ?= y +CFG_SPI ?= y + +ifeq ($(CFG_SPI_TEST),y) +$(call force,CFG_SPI,y) +endif + +ifeq ($(CFG_SPI),y) +$(call force,CFG_PL061,y) +$(call force,CFG_PL022,y) +endif + +ifeq ($(CFG_PL061),y) +core-platform-cppflags += -DPLAT_PL061_MAX_GPIOS=160 +endif +endif + +CFG_CACHE_API ?= y +CFG_SECURE_DATA_PATH ?= n +CFG_TEE_SDP_MEM_BASE ?= 0x3E800000 +CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 + +ifeq ($(PLATFORM_FLAVOR),hikey) +CFG_CONSOLE_UART ?= 3 +CFG_DRAM_SIZE_GB ?= 2 +endif + +ifeq ($(PLATFORM_FLAVOR),hikey960) +CFG_CONSOLE_UART ?= 6 +CFG_DRAM_SIZE_GB ?= 3 +CFG_CORE_BGET_BESTFIT ?= y +ifeq ($(CFG_ARM32_core),y) +CFG_ASAN_SHADOW_OFFSET ?= 0x372E38E0 +endif +# Hikey960 4G/6G versions have physical addresses above 4G range +ifneq (,$(filter 4 6,$(CFG_DRAM_SIZE_GB))) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +endif +endif + +CFG_TZDRAM_START ?= 0x3F000000 +CFG_TZDRAM_SIZE ?= 0x01000000 +CFG_SHMEM_START ?= 0x3EE00000 +CFG_SHMEM_SIZE ?= 0x00200000 +CFG_TEE_RAM_VA_SIZE ?= 0x00200000 + +CFG_IN_TREE_EARLY_TAS += avb/023f8f1a-292a-432b-8fc4-de8471358067 + +CFG_EMBED_DTB_SOURCE_FILE ?= hikey.dts diff --git a/optee/optee_os/core/arch/arm/plat-hikey/hikey_peripherals.h b/optee/optee_os/core/arch/arm/plat-hikey/hikey_peripherals.h new file mode 100644 index 0000000..ee89715 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hikey/hikey_peripherals.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2016, Linaro Ltd and Contributors. All rights reserved. + * Copyright (c) 2016, Hisilicon Ltd and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM 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. + */ + +#ifndef __HIKEY_PERIPHERALS_H__ +#define __HIKEY_PERIPHERALS_H__ + +#include + +#define PMUSSI_BASE 0xF8000000 +#define PERI_BASE 0xF7030000 +#define PMX0_BASE 0xF7010000 +#define PMX1_BASE 0xF7010800 +#define GPIO6_BASE 0xF7022000 +#define SPI_BASE 0xF7106000 + +#define PMUSSI_REG_SIZE 0x1000 +#define PERI_BASE_REG_SIZE 0x2000 +#define PMX0_REG_SIZE 0x27c +#define PMX1_REG_SIZE 0x28c + +/* register offsets */ +#define PMUSSI_LDO21_REG_ADJ SHIFT_U32(0x86, 2) +#define PMUSSI_ENA_LDO17_22 SHIFT_U32(0x2F, 2) + +#define PERI_SC_PERIPH_RSTDIS3 0x334 +#define PERI_SC_PERIPH_RSTSTAT3 0x338 +#define PERI_SC_PERIPH_CLKEN3 0x230 +#define PERI_SC_PERIPH_CLKSTAT3 0x238 + +#define PMX0_IOMG104 0x1a0 +#define PMX0_IOMG105 0x1a4 +#define PMX0_IOMG106 0x1a8 +#define PMX0_IOMG107 0x1ac + +#define PMX1_IOCG104 0x1b0 +#define PMX1_IOCG105 0x1b4 +#define PMX1_IOCG106 0x1b8 +#define PMX1_IOCG107 0x1bc +/* end register offsets */ + +#define PMUSSI_LDO21_REG_VL_MASK 0x7 +#define PMUSSI_LDO21_REG_VL_1V8 0x3 +#define PMUSSI_ENA_LDO21 BIT(4) + +#define PERI_RST3_SSP BIT(9) +#define PERI_CLK3_SSP BIT(9) + +#define PINMUX_GPIO 0 +#define PINMUX_SPI 1 + +#define PINCFG_NOPULL 0 +#define PINCFG_PULLUP 1 +#define PINCFG_PULLDN 2 + +#define GPIO6_2 50 +#define SPI_CLK_HZ 150000000 /* 150mhz */ +#define SPI_500_KHZ 500000 +#define SPI_10_KHZ 10000 + +#ifdef CFG_SPI +void spi_init(void); +#ifdef CFG_SPI_TEST +void spi_test(void); +#endif /* CFG_SPI_TEST */ +#endif /* CFG_SPI */ + +#endif /* __HIKEY_PERIPHERALS_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-hikey/main.c b/optee/optee_os/core/arch/arm/plat-hikey/main.c new file mode 100644 index 0000000..9e0543a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hikey/main.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#ifdef CFG_SPI +#include +#include +#endif +#if defined(PLATFORM_FLAVOR_hikey) +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +static struct pl011_data console_data __nex_bss; + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, PL011_REG_SIZE); +#if defined(PLATFORM_FLAVOR_hikey) +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PMUSSI_BASE, PMUSSI_REG_SIZE); +#endif +#if defined(CFG_SPI) && defined(PLATFORM_FLAVOR_hikey) +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PERI_BASE, PERI_BASE_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PMX0_BASE, PMX0_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PMX1_BASE, PMX1_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, GPIO6_BASE, PL061_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, SPI_BASE, PL022_REG_SIZE); +#endif +register_dynamic_shm(DRAM0_BASE, DRAM0_SIZE_NSEC); +#ifdef DRAM1_SIZE_NSEC +register_dynamic_shm(DRAM1_BASE, DRAM1_SIZE_NSEC); +#endif +#ifdef DRAM2_SIZE_NSEC +register_dynamic_shm(DRAM2_BASE, DRAM2_SIZE_NSEC); +#endif + +void console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, + CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +#if defined(PLATFORM_FLAVOR_hikey) +#ifdef CFG_SPI +void spi_init(void) +{ + uint32_t shifted_val, read_val; + vaddr_t peri_base = core_mmu_get_va(PERI_BASE, MEM_AREA_IO_NSEC, + PERI_BASE_REG_SIZE); + vaddr_t pmx0_base = core_mmu_get_va(PMX0_BASE, MEM_AREA_IO_NSEC, + PMX0_REG_SIZE); + vaddr_t pmx1_base = core_mmu_get_va(PMX1_BASE, MEM_AREA_IO_NSEC, + PMX1_REG_SIZE); + + DMSG("take SPI0 out of reset\n"); + shifted_val = PERI_RST3_SSP; + /* + * no need to read PERI_SC_PERIPH_RSTDIS3 first + * as all the bits are processed and cleared after writing + */ + io_write32(peri_base + PERI_SC_PERIPH_RSTDIS3, shifted_val); + DMSG("PERI_SC_PERIPH_RSTDIS3: 0x%x\n", + io_read32(peri_base + PERI_SC_PERIPH_RSTDIS3)); + + /* + * wait until the requested device is out of reset + * and ready to be used + */ + do { + read_val = io_read32(peri_base + PERI_SC_PERIPH_RSTSTAT3); + } while (read_val & shifted_val); + DMSG("PERI_SC_PERIPH_RSTSTAT3: 0x%x\n", read_val); + + DMSG("enable SPI clock\n"); + /* + * no need to read PERI_SC_PERIPH_CLKEN3 first + * as all the bits are processed and cleared after writing + */ + shifted_val = PERI_CLK3_SSP; + io_write32(peri_base + PERI_SC_PERIPH_CLKEN3, shifted_val); + DMSG("PERI_SC_PERIPH_CLKEN3: 0x%x\n", + io_read32(peri_base + PERI_SC_PERIPH_CLKEN3)); + + DMSG("PERI_SC_PERIPH_CLKSTAT3: 0x%x\n", + io_read32(peri_base + PERI_SC_PERIPH_CLKSTAT3)); + + /* + * GPIO6_2 can be configured as PINMUX_GPIO, but as PINMUX_SPI, HW IP + * will control the chip select pin so we don't have to manually do it. + * The only concern is that the IP will pulse it between each packet, + * which might not work with certain clients. There seems to be no + * option to configure it to stay enabled for the total duration of the + * transfer. + * ref: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/CJACFAFG.html + */ + DMSG("configure gpio6 pins 0-3 as SPI\n"); + io_write32(pmx0_base + PMX0_IOMG104, PINMUX_SPI); + io_write32(pmx0_base + PMX0_IOMG105, PINMUX_SPI); + io_write32(pmx0_base + PMX0_IOMG106, PINMUX_SPI); + io_write32(pmx0_base + PMX0_IOMG107, PINMUX_SPI); + + DMSG("configure gpio6 pins 0-3 as nopull\n"); + io_write32(pmx1_base + PMX1_IOCG104, PINCFG_NOPULL); + io_write32(pmx1_base + PMX1_IOCG105, PINCFG_NOPULL); + io_write32(pmx1_base + PMX1_IOCG106, PINCFG_NOPULL); + io_write32(pmx1_base + PMX1_IOCG107, PINCFG_NOPULL); + +#ifdef CFG_SPI_TEST + spi_test(); +#endif +} +#endif + +static TEE_Result peripherals_init(void) +{ + vaddr_t pmussi_base = core_mmu_get_va(PMUSSI_BASE, MEM_AREA_IO_NSEC, + PMUSSI_REG_SIZE); + + DMSG("enable LD021_1V8 source (pin 35) on LS connector\n"); + /* + * Mezzanine cards usually use this to source level shifters for + * UART, GPIO, SPI, I2C, etc so if not enabled, connected + * peripherals will not work either (during bootloader stage) + * until linux is booted. + */ + io_mask8(pmussi_base + PMUSSI_LDO21_REG_ADJ, PMUSSI_LDO21_REG_VL_1V8, + PMUSSI_LDO21_REG_VL_MASK); + io_write8(pmussi_base + PMUSSI_ENA_LDO17_22, PMUSSI_ENA_LDO21); + +#ifdef CFG_SPI + spi_init(); +#endif + return TEE_SUCCESS; +} + +driver_init(peripherals_init); +#endif /* PLATFORM_FLAVOR_hikey */ diff --git a/optee/optee_os/core/arch/arm/plat-hikey/platform_config.h b/optee/optee_os/core/arch/arm/plat-hikey/platform_config.h new file mode 100644 index 0000000..35e6f3d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hikey/platform_config.h @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +/* PL011 UART */ +#if defined(PLATFORM_FLAVOR_hikey) + +#define PL011_UART0_BASE 0xF8015000 +#define PL011_UART2_BASE 0xF7112000 +#define PL011_UART3_BASE 0xF7113000 +#if (CFG_CONSOLE_UART == 3) +#define CONSOLE_UART_BASE PL011_UART3_BASE +#elif (CFG_CONSOLE_UART == 2) +#define CONSOLE_UART_BASE PL011_UART2_BASE +#elif (CFG_CONSOLE_UART == 0) +#define CONSOLE_UART_BASE PL011_UART0_BASE +#else +#error Unknown console UART +#endif + +#elif defined(PLATFORM_FLAVOR_hikey960) + +#define PL011_UART5_BASE 0xFDF05000 +#define PL011_UART6_BASE 0xFFF32000 +#if (CFG_CONSOLE_UART == 6) +#define CONSOLE_UART_BASE PL011_UART6_BASE +#elif (CFG_CONSOLE_UART == 5) +#define CONSOLE_UART_BASE PL011_UART5_BASE +#else +#error Unknown console UART +#endif + +#else /* PLATFORM_FLAVOR_hikey */ +#error Unknown HiKey PLATFORM_FLAVOR +#endif /* PLATFORM_FLAVOR_hikey */ + +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 19200000 + +/* + * HiKey and HiKey960 memory map + * + * Refer to the default configuration from conf.mk for description below. + * + * TZDRAM is secured (firewalled) by the DDR controller, see ARM-TF, but note + * that security of this type of memory is weak for two reasons: + * 1. It is prone to physical tampering since DRAM is external to the SoC + * 2. It is still somewhat prone to software attacks because the memory + * protection may be reverted by the non-secure kernel with a piece of + * code similar to the one that sets the protection in ARM-TF (we're + * missing a "lockdown" step which would prevent any change to the DDRC + * configuration until the next SoC reset). + * TZSRAM is emulated in the TZDRAM area, because the on-chip SRAM of the + * HiKey SoC is too small to run OP-TEE (72K total with 64K available, see + * "SRAM Memory Region Layout" in ARM-TF plat/hikey/include/hisi_sram_map.h), + * while the SRAM of the HiKey960 SoC is not available to the public at the + * moment. + * + * CFG_WITH_PAGER=n + * + * 0x4000_0000 - + * TA RAM: 14 MiB | + * 0x3F20_0000 | TZDRAM + * TEE RAM: 2 MiB (TEE_RAM_VA_SIZE) | + * 0x3F00_0000 [TZDRAM_BASE, BL32_LOAD_ADDR] - + * Shared memory: 2 MiB | + * 0x3EE0_0000 | DRAM0 + * Reserved by UEFI for OP-TEE, unused | + * 0x3EC0_0000 - + * Secure Data Path buffers: 4 MiB | DRAM0 (secure) + * 0x3E80_0000 [CFG_TEE_SDP_MEM_BASE] - + * Reserved by UEFI for OP-TEE, unused | + * 0x3E00_0000 | DRAM0 + * Available to Linux | + * 0x0000_0000 [DRAM0_BASE] - + * + * CFG_WITH_PAGER=y + * + * 0x4000_0000 - + * TA RAM: 14 MiB | TZDRAM + * 0x3F20_0000 - + * Unused + * 0x3F03_2000 - + * TEE RAM: 200 KiB | TZSRAM + * 0x3F00_0000 [TZSRAM_BASE, BL32_LOAD_ADDR] - + * Shared memory: 2 MiB | + * 0x3EE0_0000 | DRAM0 + * Reserved by UEFI for OP-TEE, unused | + * 0x3EC0_0000 - + * Secure Data Path buffers: 4 MiB | DRAM0 (secure) + * 0x3E80_0000 [CFG_TEE_SDP_MEM_BASE] - + * Reserved by UEFI for OP-TEE, unused | + * 0x3E00_0000 | DRAM0 + * Available to Linux | + * 0x0000_0000 [DRAM0_BASE] - + */ + +#define DRAM0_BASE 0x00000000 +#define DRAM0_SIZE 0x3F000000 +#define DRAM0_SIZE_NSEC 0x3E000000 +#define DRAM1_BASE 0x40000000 + +#if defined(PLATFORM_FLAVOR_hikey) + +#if (CFG_DRAM_SIZE_GB == 2) +#define DRAM1_SIZE_NSEC 0x40000000 +#elif (CFG_DRAM_SIZE_GB == 1) +/* do nothing */ +#else +#error Unknown DRAM size +#endif + +#elif defined(PLATFORM_FLAVOR_hikey960) + +/* + * Physical address ranges for HiKey960 RAM: + * 3G board: 0~3G + * 4G board: 0~3G 3~3.5G 8~8.5G + * 6G board: 0~3G 4~7G + */ +#if (CFG_DRAM_SIZE_GB == 3) +#define DRAM1_SIZE_NSEC 0x80000000 +#elif (CFG_DRAM_SIZE_GB == 4) +#define DRAM1_SIZE_NSEC 0xA0000000 +#define DRAM2_BASE 0x200000000 +#define DRAM2_SIZE_NSEC 0x20000000 +#elif (CFG_DRAM_SIZE_GB == 6) +#define DRAM1_SIZE_NSEC 0x80000000 +#define DRAM2_BASE 0x100000000 +#define DRAM2_SIZE_NSEC 0xC0000000 +#else +#error Unknown DRAM size +#endif + +#if (CFG_DRAM_SIZE_GB >= 4 && defined(CFG_ARM32_core) && \ + defined(CFG_CORE_DYN_SHM) && !defined(CFG_LARGE_PHYS_ADDR)) +#error 32-bit TEE with CFG_CORE_DYN_SHM and without CFG_LARGE_PHYS_ADDR \ + cannot support boards with 4G RAM or more +#endif + +#else /* PLATFORM_FLAVOR_hikey */ +#error Unknown HiKey PLATFORM_FLAVOR +#endif /* PLATFORM_FLAVOR_hikey */ + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-hikey/spi_test.c b/optee/optee_os/core/arch/arm/plat-hikey/spi_test.c new file mode 100644 index 0000000..ea7ec25 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hikey/spi_test.c @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PL022_STAT 0x00C +#define PL022_STAT_BSY SHIFT_U32(1, 4) + +static void spi_cs_callback(enum gpio_level value) +{ + static bool inited; + static struct pl061_data pd; + vaddr_t gpio6_base = core_mmu_get_va(GPIO6_BASE, MEM_AREA_IO_NSEC, + PL061_REG_SIZE); + vaddr_t spi_base = core_mmu_get_va(SPI_BASE, MEM_AREA_IO_NSEC, + PL022_REG_SIZE); + + if (!inited) { + pl061_init(&pd); + pl061_register(gpio6_base, 6); + pl061_set_mode_control(GPIO6_2, PL061_MC_SW); + pd.chip.ops->set_interrupt(NULL, GPIO6_2, + GPIO_INTERRUPT_DISABLE); + pd.chip.ops->set_direction(NULL, GPIO6_2, GPIO_DIR_OUT); + inited = true; + } + + if (io_read8(spi_base + PL022_STAT) & PL022_STAT_BSY) + DMSG("pl022 busy - do NOT set CS!"); + while (io_read8(spi_base + PL022_STAT) & PL022_STAT_BSY) + ; + DMSG("pl022 done - set CS!"); + + pd.chip.ops->set_value(NULL, GPIO6_2, value); +} + +static void spi_set_cs_mux(uint32_t val) +{ + uint32_t data; + vaddr_t pmx0_base = core_mmu_get_va(PMX0_BASE, MEM_AREA_IO_NSEC, + PMX0_REG_SIZE); + + if (val == PINMUX_SPI) { + DMSG("Configure gpio6 pin2 as SPI"); + io_write32(pmx0_base + PMX0_IOMG106, PINMUX_SPI); + } else { + DMSG("Configure gpio6 pin2 as GPIO"); + io_write32(pmx0_base + PMX0_IOMG106, PINMUX_GPIO); + } + + data = io_read32(pmx0_base + PMX0_IOMG106); + if (data) + DMSG("gpio6 pin2 is SPI"); + else + DMSG("gpio6 pin2 is GPIO"); +} + +static void spi_test_with_manual_cs_control(void) +{ + struct pl022_data pd; + vaddr_t spi_base = core_mmu_get_va(SPI_BASE, MEM_AREA_IO_NSEC, + PL022_REG_SIZE); + uint8_t tx[3] = {0x01, 0x80, 0x00}; + uint8_t rx[3] = {0}; + size_t i, j, len = 3; + enum spi_result res; + + spi_set_cs_mux(PINMUX_GPIO); + + DMSG("Set CS callback"); + pd.cs_control = PL022_CS_CTRL_MANUAL; + + DMSG("spi_base: 0x%" PRIxVA "\n", spi_base); + DMSG("Configure SPI"); + pd.base = spi_base; + pd.clk_hz = SPI_CLK_HZ; + pd.speed_hz = SPI_10_KHZ; + pd.mode = SPI_MODE0; + pd.data_size_bits = 8; + pd.loopback = true; + + pl022_init(&pd); + pd.chip.ops->configure(&pd.chip); + pd.chip.ops->start(&pd.chip); + + /* + * Pulse CS only once for the whole transmission. + * This is the scheme used by the pl022 driver. + */ + spi_cs_callback(GPIO_LEVEL_HIGH); + tee_time_busy_wait(2); + spi_cs_callback(GPIO_LEVEL_LOW); + for (j = 0; j < 10; j++) { + DMSG("SPI test loop: %zu", j); + res = pd.chip.ops->txrx8(&pd.chip, tx, rx, len); + if (res) { + EMSG("SPI transceive error %d", res); + break; + } + + for (i = 0; i < len; i++) + DMSG("rx[%zu] = 0x%x", i, rx[i]); + + tee_time_busy_wait(20); + } + spi_cs_callback(GPIO_LEVEL_HIGH); + + /* Pulse CS once per transfer */ + spi_cs_callback(GPIO_LEVEL_HIGH); + tee_time_busy_wait(2); + for (j = 10; j < 20; j++) { + DMSG("SPI test loop: %zu", j); + spi_cs_callback(GPIO_LEVEL_LOW); + res = pd.chip.ops->txrx8(&pd.chip, tx, rx, len); + if (res) { + EMSG("SPI transceive error %d", res); + break; + } + + for (i = 0; i < len; i++) + DMSG("rx[%zu] = 0x%x", i, rx[i]); + + tee_time_busy_wait(20); + spi_cs_callback(GPIO_LEVEL_HIGH); + } + + /* Pulse CS once per word/byte */ + spi_set_cs_mux(PINMUX_SPI); + tee_time_busy_wait(2); + for (j = 20; j < 30; j++) { + DMSG("SPI test loop: %zu", j); + res = pd.chip.ops->txrx8(&pd.chip, tx, rx, len); + if (res) { + EMSG("SPI transceive error %d", res); + break; + } + + for (i = 0; i < len; i++) + DMSG("rx[%zu] = 0x%x", i, rx[i]); + + tee_time_busy_wait(20); + } + + pd.chip.ops->end(&pd.chip); +} + +static void spi_test_with_registered_cs_cb(void) +{ + struct pl022_data pd; + vaddr_t spi_base = core_mmu_get_va(SPI_BASE, MEM_AREA_IO_NSEC, + PL022_REG_SIZE); + uint8_t tx[3] = {0x01, 0x80, 0x00}; + uint8_t rx[3] = {0}; + size_t i, j, len = 3; + enum spi_result res; + + spi_set_cs_mux(PINMUX_GPIO); + + DMSG("Set CS callback"); + pd.cs_data.cs_cb = spi_cs_callback; + pd.cs_control = PL022_CS_CTRL_CB; + + DMSG("spi_base: 0x%" PRIxVA "\n", spi_base); + DMSG("Configure SPI"); + pd.base = spi_base; + pd.clk_hz = SPI_CLK_HZ; + pd.speed_hz = SPI_10_KHZ; + pd.mode = SPI_MODE0; + pd.data_size_bits = 8; + pd.loopback = true; + + pl022_init(&pd); + pd.chip.ops->configure(&pd.chip); + pd.chip.ops->start(&pd.chip); + + for (j = 0; j < 20; j++) { + DMSG("SPI test loop: %zu", j); + res = pd.chip.ops->txrx8(&pd.chip, tx, rx, len); + if (res) { + EMSG("SPI transceive error %d", res); + break; + } + + for (i = 0; i < len; i++) + DMSG("rx[%zu] = 0x%x", i, rx[i]); + + tee_time_busy_wait(20); + } + + pd.chip.ops->end(&pd.chip); +} + +static void spi_test_with_builtin_cs_control(void) +{ + struct pl061_data pd061; + struct pl022_data pd022; + vaddr_t gpio6_base = core_mmu_get_va(GPIO6_BASE, MEM_AREA_IO_NSEC, + PL061_REG_SIZE); + vaddr_t spi_base = core_mmu_get_va(SPI_BASE, MEM_AREA_IO_NSEC, + PL022_REG_SIZE); + uint8_t tx[3] = {0x01, 0x80, 0x00}; + uint8_t rx[3] = {0}; + size_t i, j, len = 3; + enum spi_result res; + + spi_set_cs_mux(PINMUX_GPIO); + + DMSG("gpio6_base: 0x%" PRIxVA "\n", gpio6_base); + DMSG("Configure GPIO"); + pl061_init(&pd061); + pl061_register(gpio6_base, 6); + DMSG("Enable software mode control for chip select"); + pl061_set_mode_control(GPIO6_2, PL061_MC_SW); + + pd022.cs_data.gpio_data.chip = &pd061.chip; + pd022.cs_data.gpio_data.pin_num = GPIO6_2; + pd022.cs_control = PL022_CS_CTRL_AUTO_GPIO; + + DMSG("spi_base: 0x%" PRIxVA "\n", spi_base); + DMSG("Configure SPI"); + pd022.base = spi_base; + pd022.clk_hz = SPI_CLK_HZ; + pd022.speed_hz = SPI_10_KHZ; + pd022.mode = SPI_MODE0; + pd022.data_size_bits = 8; + pd022.loopback = true; + + pl022_init(&pd022); + pd022.chip.ops->configure(&pd022.chip); + pd022.chip.ops->start(&pd022.chip); + + for (j = 0; j < 20; j++) { + DMSG("SPI test loop: %zu", j); + res = pd022.chip.ops->txrx8(&pd022.chip, tx, rx, len); + if (res) { + EMSG("SPI transceive error %d", res); + break; + } + + for (i = 0; i < len; i++) + DMSG("rx[%zu] = 0x%x", i, rx[i]); + + tee_time_busy_wait(20); + } + + pd022.chip.ops->end(&pd022.chip); +} + +/* + * spi_init() MUST be run before calling this function! + * + * spi_test runs some loopback tests, so the SPI module will just receive + * what is transmitted, i.e. 0x01, 0x80, 0x00. + * + * In non-loopback mode, the transmitted value will elicit a readback of + * the measured value from the ADC chip on the Linksprite 96Boards + * Mezzanine card [1], which can be connected to either a sliding + * rheostat [2] or photoresistor [3]. + * + * [1] http://linksprite.com/wiki/index.php5?title=Linker_Mezzanine_card_for_96board + * [2] http://learn.linksprite.com/96-board/sliding-rheostat + * [3] http://learn.linksprite.com/96-board/photoresistor + */ +void spi_test(void) +{ + spi_test_with_builtin_cs_control(); + spi_test_with_registered_cs_cb(); + spi_test_with_manual_cs_control(); +} diff --git a/optee/optee_os/core/arch/arm/plat-hikey/sub.mk b/optee/optee_os/core/arch/arm/plat-hikey/sub.mk new file mode 100644 index 0000000..1acd560 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hikey/sub.mk @@ -0,0 +1,5 @@ +global-incdirs-y += . +srcs-y += main.c +ifeq ($(PLATFORM_FLAVOR),hikey) +srcs-$(CFG_SPI_TEST) += spi_test.c +endif diff --git a/optee/optee_os/core/arch/arm/plat-hisilicon/conf.mk b/optee/optee_os/core/arch/arm/plat-hisilicon/conf.mk new file mode 100644 index 0000000..dc118d8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hisilicon/conf.mk @@ -0,0 +1,61 @@ +PLATFORM_FLAVOR ?= hi3519av100_demo + +hi3519av100-flavorlist = hi3519av100_demo hi3519av100_tst + +ifneq (,$(filter $(PLATFORM_FLAVOR),$(hi3519av100-flavorlist))) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_HI3519AV100,y) +$(call force,CFG_TEE_CORE_NB_CORE,2) +# Hi3519av100 has got two clusters, one core per cluster +$(call force,CFG_CORE_CLUSTER_SHIFT,0) + +$(call force,CFG_PL011,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_ARM32_core,y) +$(call force,CFG_PSCI_ARM32,y) + +CFG_BOOT_SECONDARY_REQUEST ?= y +CFG_NUM_THREADS ?= 4 +CFG_CRYPTO_WITH_CE ?= y +CFG_NS_ENTRY_ADDR ?= 0x22008000 +CFG_CORE_HEAP_SIZE ?= 131072 + +# +# Hi3519av100 memory map +# +# This is a general memory map for demo board, and for your own board, +# you have to define your own memory map. +# +# 0x4000_0000 [DRAM_LIMIT] +# other (media memory zone/uboot and other) +# +# 0x3360_0000 - +# TA RAM: 12 MiB | TZDRAM +# 0x32a0_0000 - +# +# CFG_WITH_PAGER=n - +# TEE RAM: 4 MiB (TEE_RAM_VA_SIZE) | TZDRAM +# 0x3260_0000 [TZDRAM_BASE, TEE_LOAD_ADDR] - +# +# CFG_WITH_PAGER=y +# Unused +# 0x32607_0000 - +# TEE RAM: 448 KiB (TZSRAM_SIZE) | TZSRAM +# 0x3260_0000 [TZDRAM_BASE, TZSRAM_BASE, TEE_LOAD_ADDR] +# OP-TEE Future Use: 2 MiB +# 0x3240_0000 +# Shared memory: 4 MB +# 0x3200_0000 +# Linux memory: 256MB +# 0x2200_0000 +# DSP reserved memory: 32MB +# 0x2000_0000 [DRAM_BASE] +# +CFG_TZDRAM_START ?= 0x32600000 +CFG_TZDRAM_SIZE ?= 0x01000000 +CFG_TEE_RAM_VA_SIZE ?= 0x00400000 +CFG_SHMEM_START ?= 0x32000000 +CFG_SHMEM_SIZE ?= 0x00400000 +else +$(error Error: Not supported PLATFORM_FLAVOR or NULL PLATFORM_FLAVOR) +endif diff --git a/optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100.h b/optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100.h new file mode 100644 index 0000000..1d4b7ea --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. + */ + +#ifndef __HI3519AV100_H__ +#define __HI3519AV100_H__ + +#include + +/* PL011 */ +#define PL011_UART0_BASE 0x04540000 +#define PL011_BAUDRATE 115200 +#define PL011_UART0_CLK_IN_HZ 24000000 + +/* BootSRAM */ +#define BOOTSRAM_BASE 0x04200000 +#define BOOTSRAM_SIZE 0x1000 + +/* CPU Reset Control */ +#define CPU_CRG_BASE 0x04510000 +#define CPU_CRG_SIZE 0x1000 + +/* Sysctrl Register */ +#define SYS_CTRL_BASE 0x04520000 +#define SYS_CTRL_SIZE 0x1000 + +#endif /* __HI3519AV100_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S b/optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S new file mode 100644 index 0000000..bf11645 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. + */ + +/* + * Entry points for the Hi3519AV100 a53 aarch32 mode init. + * It is assumed no stack is available when these routines are called. + * It is assumed each routine is called with return address in LR + * and with ARM registers R0, R1, R2, R3 being scratched. + */ + +#include +#include +#include +#include + +#define CCI_BASE 0x04528000 +#define CPUECTLR_A53_SMPEN BIT(6) +#define ACTRL_CPUECTLR BIT(1) +#define HACTRL_CPUECTLR BIT(1) + +.section .text +.balign 4 +.code 32 + +/* + * Hi3519AV100 a53 aarch32 configuration early configuration + * + * Use scratch registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +FUNC plat_cpu_reset_early , : + /* + * Write the CPU Extended Control Register + * Set the SMPEN bit, this Cortex-A53 core's register + */ + mrrc p15, 1, r0, r1, c15 + orr r0, r0, #CPUECTLR_A53_SMPEN + mcrr p15, 1, r0, r1, c15 + + /* + * Enable Non-Secure EL1 write access to CPUECTLR + */ + mrs r1, cpsr + cps #CPSR_MODE_MON + + read_scr r0 + orr r0, r0, #SCR_NS /* Set NS bit in SCR */ + write_scr r0 + isb + + /* Write HACTLR register */ + mrc p15, 4, r2, c1, c0, 1 + orr r2, r2, #HACTRL_CPUECTLR + mcr p15, 4, r2, c1, c0, 1 + + bic r0, r0, #SCR_NS /* Clr NS bit in SCR */ + write_scr r0 + isb + + /* Write ACTLR register */ + mrc p15, 0, r2, c1, c0, 1 + orr r2, r2, #ACTRL_CPUECTLR + mcr p15, 0, r2, c1, c0, 1 + + msr cpsr, r1 + /* + * Enable cci for secondary core + */ + mov r3, lr + bl __get_core_pos + mov lr, r3 + cmp r0, #0 + beq out + ldr r0, =CCI_BASE + ldr r1, [r0] + orr r1, r1, #BIT(9) /* bit 9 set to 1 */ + str r1, [r0] +out: + bx lr +END_FUNC plat_cpu_reset_early diff --git a/optee/optee_os/core/arch/arm/plat-hisilicon/main.c b/optee/optee_os/core/arch/arm/plat-hisilicon/main.c new file mode 100644 index 0000000..4840b98 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hisilicon/main.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct pl011_data console_data; +register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, PL011_REG_SIZE); +#ifdef BOOTSRAM_BASE +register_phys_mem(MEM_AREA_IO_SEC, BOOTSRAM_BASE, BOOTSRAM_SIZE); +#endif +#ifdef CPU_CRG_BASE +register_phys_mem(MEM_AREA_IO_SEC, CPU_CRG_BASE, CPU_CRG_SIZE); +#endif +#ifdef SYS_CTRL_BASE +register_phys_mem(MEM_AREA_IO_SEC, SYS_CTRL_BASE, SYS_CTRL_SIZE); +#endif + +void console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-hisilicon/platform_config.h b/optee/optee_os/core/arch/arm/plat-hisilicon/platform_config.h new file mode 100644 index 0000000..c5dc82b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hisilicon/platform_config.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +/* PL011 UART */ +#define CONSOLE_UART_BASE PL011_UART0_BASE +#define CONSOLE_BAUDRATE PL011_BAUDRATE +#define CONSOLE_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-hisilicon/psci.c b/optee/optee_os/core/arch/arm/plat-hisilicon/psci.c new file mode 100644 index 0000000..9009e22 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hisilicon/psci.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_CPU_SUSSYS_RESET 0xcc +#define REG_CPU_START_COMMAND 0x0 +#define REG_CPU_START_ADDR 0x4 +#define REG_SYSCTRL_RESET 0x4 +#define RELEASE_CORE_MASK (BIT32(25) | BIT32(1)) + +int psci_features(uint32_t psci_fid) +{ + switch (psci_fid) { + case ARM_SMCCC_VERSION: + case PSCI_PSCI_FEATURES: + case PSCI_VERSION: + case PSCI_SYSTEM_RESET: +#ifdef CFG_BOOT_SECONDARY_REQUEST + case PSCI_CPU_ON: +#endif + return PSCI_RET_SUCCESS; + default: + return PSCI_RET_NOT_SUPPORTED; + } +} + +uint32_t psci_version(void) +{ + return PSCI_VERSION_1_0; +} + +void psci_system_reset(void) +{ + vaddr_t sysctrl = core_mmu_get_va(SYS_CTRL_BASE, MEM_AREA_IO_SEC, + SYS_CTRL_SIZE); + + if (!sysctrl) { + EMSG("no sysctrl mapping, hang here"); + panic(); + } + + io_write32(sysctrl + REG_SYSCTRL_RESET, 0xdeadbeef); +} + +#ifdef CFG_BOOT_SECONDARY_REQUEST +int psci_cpu_on(uint32_t core_idx, uint32_t entry, + uint32_t context_id) +{ + uint32_t val = 0; + size_t pos = get_core_pos_mpidr(core_idx); + vaddr_t bootsram = core_mmu_get_va(BOOTSRAM_BASE, MEM_AREA_IO_SEC, + BOOTSRAM_SIZE); + vaddr_t crg = core_mmu_get_va(CPU_CRG_BASE, MEM_AREA_IO_SEC, + CPU_CRG_SIZE); + + if (!bootsram || !crg) { + EMSG("No bootsram or crg mapping"); + return PSCI_RET_INVALID_PARAMETERS; + } + + if ((pos == 0) || (pos >= CFG_TEE_CORE_NB_CORE)) + return PSCI_RET_INVALID_PARAMETERS; + + /* set secondary core's NS entry addresses */ + boot_set_core_ns_entry(pos, entry, context_id); + + val = virt_to_phys((void *)TEE_LOAD_ADDR); + io_write32(bootsram + REG_CPU_START_ADDR, val); + io_write32(bootsram + REG_CPU_START_COMMAND, 0xe51ff004); + + /* release secondary core */ + io_clrbits32(crg + REG_CPU_SUSSYS_RESET, RELEASE_CORE_MASK); + + return PSCI_RET_SUCCESS; +} +#endif diff --git a/optee/optee_os/core/arch/arm/plat-hisilicon/sub.mk b/optee/optee_os/core/arch/arm/plat-hisilicon/sub.mk new file mode 100644 index 0000000..ed69d4c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-hisilicon/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-$(CFG_HI3519AV100) += hi3519av100_plat_init.S +srcs-$(CFG_PSCI_ARM32) += psci.c diff --git a/optee/optee_os/core/arch/arm/plat-imx/a7_plat_init.S b/optee/optee_os/core/arch/arm/plat-imx/a7_plat_init.S new file mode 100644 index 0000000..f96a18a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/a7_plat_init.S @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + * + * Peng Fan + */ + +/* + * Entry points for the A7 init. + * 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. + */ + +#include +#include +#include +#include +#include + +.section .text +.balign 4 +.code 32 + +/* + * Cortex A7 configuration early configuration + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +FUNC plat_cpu_reset_early , : + /* + * DDI: Disable dual issue [bit28=0] + * DDVM: Disable Distributed Virtual Memory transactions [bit15=0] + * L1PCTL: L1 Data prefetch control [bit14:13=2b11] + * L1RADIS: L1 Data Cache read-allocate mode disable [bit12=0] + * L2RADIS: L2 Data Cache read-allocate mode disable [bit11=0] + * DODMBS: Disable optimized data memory barrier behavior [bit10=0] + * SMP: Enables coherent requests to the processor [bit6=0] + */ + mov_imm r0, 0x00006040 + write_actlr r0 + + mov_imm r0, 0x00040C00 + write_nsacr r0 + + bx lr +END_FUNC plat_cpu_reset_early + +FUNC get_core_pos_mpidr , : + /* Drop ClusterId. There is no SoCs with more than 4 A7 Cores. */ + and r0, r0, #MPIDR_CPU_MASK + bx lr +END_FUNC get_core_pos_mpidr diff --git a/optee/optee_os/core/arch/arm/plat-imx/a9_plat_init.S b/optee/optee_os/core/arch/arm/plat-imx/a9_plat_init.S new file mode 100644 index 0000000..4050684 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/a9_plat_init.S @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * Copyright 2019 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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. + */ + +#include +#include +#include +#include +#include +#include + +.section .text +.balign 4 +.code 32 + +/* + * Cortex A9 early configuration + * + * Use registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +FUNC plat_cpu_reset_early , : + /* + * Under very rare timing circumstances, transition into streaming + * mode might create a data corruption + * Configurations affected + * This erratum affects configurations with either: + * - One processor if the ACP is present + * - Two or more processors + * This erratum can be worked round by setting bit[22] of the + * undocumented Diagnostic Control Register to 1. This + * register is encoded as CP15 c15 0 c0 1. + * The bit can be written in Secure state only, with the following + * Read/Modify/Write code sequence: + * MRC p15,0,rt,c15,c0,1 + * ORR rt,rt,#0x00400000 + * MCR p15,0,rt,c15,c0,1 + * When this bit is set, the processor is unable to switch into + * Read-Allocate (streaming) mode, which means this erratum cannot + * occur. Setting this bit could possibly result in a visible drop + * in performance for routines that perform intensive memory + * accesses, such as memset() or memcpy(). However, the workaround + * is not expected to create any significant performance degradation + * in most standard applications. + */ +#if defined(CFG_MX6QP) || defined(CFG_MX6Q) || defined(CFG_MX6D) || \ + defined(CFG_MX6DL) + read_diag r0 + orr r0, r0, #1 << 22 + write_diag r0 +#endif + /* + * Disallow NSec to mask FIQ [bit4: FW=0] + * Allow NSec to manage Imprecise Abort [bit5: AW=1] + * Imprecise Abort trapped to Abort Mode [bit3: EA=0] + * In Sec world, FIQ trapped to FIQ Mode [bit2: FIQ=0] + * IRQ always trapped to IRQ Mode [bit1: IRQ=0] + * Secure World [bit0: NS=0] + */ + mov r0, #SCR_AW + write_scr r0 + + /* + * Mandated HW config loaded + * + * SCTLR = 0x00004000 + * - Round-Robin replac. for icache, btac, i/duTLB (bit14: RoundRobin) + * + * ACTRL = 0x000000[46(i.MX6SLL),47] + * - core always in full SMP (FW bit0=[0(i.MX6SLL),1], SMP bit6=1) + * - L2 write full line of zero disabled (bit3=0) + * (keep WFLZ low. Will be set once outer L2 is ready) + * - L1 Prefetch enable (bit2=1) + * - L2 Prefetch hint enable (bit1=1) + * + * NSACR = 0x00020C00 + * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) + * - Nsec can lockdown TLB (TL bit17=1) + * - NSec cannot access PLE (PLE bit16=0) + * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) + * + * PCR + * - no change latency, enable clk gating + */ + mov_imm r0, 0x00004000 + write_sctlr r0 + +#ifdef CFG_MX6SLL + mov_imm r0, 0x00000046 +#else + mov_imm r0, 0x00000047 +#endif + write_actlr r0 + + mov_imm r0, 0x00020C00 + write_nsacr r0 + + read_pcr r0 + orr r0, r0, #0x1 + write_pcr r0 + + mov pc, lr +END_FUNC plat_cpu_reset_early diff --git a/optee/optee_os/core/arch/arm/plat-imx/conf.mk b/optee/optee_os/core/arch/arm/plat-imx/conf.mk new file mode 100644 index 0000000..61ff948 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/conf.mk @@ -0,0 +1,521 @@ +PLATFORM_FLAVOR ?= mx6ulevk + +# Get SoC associated with the PLATFORM_FLAVOR +mx6ul-flavorlist = \ + mx6ulevk \ + mx6ul9x9evk \ + mx6ulccimx6ulsbcpro \ + mx6ulccbv2 \ + +mx6ull-flavorlist = \ + mx6ullevk \ + mx6ulzevk \ + +mx6q-flavorlist = \ + mx6qsabrelite \ + mx6qsabreauto \ + mx6qsabresd \ + mx6qhmbedge \ + mx6qapalis \ + +mx6qp-flavorlist = \ + mx6qpsabreauto \ + mx6qpsabresd \ + +mx6sl-flavorlist = \ + mx6slevk + +mx6sll-flavorlist = \ + mx6sllevk + +mx6sx-flavorlist = \ + mx6sxsabreauto \ + mx6sxsabresd \ + mx6sxudooneofull \ + +mx6d-flavorlist = \ + mx6dhmbedge \ + mx6dapalis \ + +mx6dl-flavorlist = \ + mx6dlsabreauto \ + mx6dlsabresd \ + mx6dlhmbedge \ + +mx6s-flavorlist = \ + mx6shmbedge \ + mx6solosabresd \ + mx6solosabreauto \ + +mx7d-flavorlist = \ + mx7dsabresd \ + mx7dpico_mbl \ + mx7dclsom \ + +mx7s-flavorlist = \ + mx7swarp7 \ + mx7swarp7_mbl \ + +mx7ulp-flavorlist = \ + mx7ulpevk + +mx8mq-flavorlist = \ + mx8mqevk + +mx8mm-flavorlist = \ + mx8mmevk \ + mx8mm_cl_iot_gate + +mx8mn-flavorlist = \ + mx8mnevk + +mx8mp-flavorlist = \ + mx8mpevk \ + mx8mp_rsb3720_6g + +mx8qm-flavorlist = \ + mx8qmmek \ + +mx8qx-flavorlist = \ + mx8qxpmek \ + +mx8dxl-flavorlist = \ + mx8dxlevk \ + +mx8ulp-flavorlist = \ + mx8ulpevk \ + +mx93-flavorlist = \ + mx93evk \ + +ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6ul-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6UL,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_TZC380,y) +include core/arch/arm/cpu/cortex-a7.mk +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6ull-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6ULL,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_TZC380,y) +$(call force,CFG_IMX_CAAM,n) +$(call force,CFG_NXP_CAAM,n) +$(call force,CFG_IMX_DCP,y) +include core/arch/arm/cpu/cortex-a7.mk +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6q-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6Q,y) +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_TZC380,y) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6qp-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6QP,y) +$(call force,CFG_TEE_CORE_NB_CORE,4) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6d-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6D,y) +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_TZC380,y) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6dl-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6DL,y) +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_TZC380,y) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6s-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6S,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6sl-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6SL,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_IMX_CAAM,n) +$(call force,CFG_NXP_CAAM,n) +$(call force,CFG_IMX_DCP,y) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6sll-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6SLL,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_IMX_CAAM,n) +$(call force,CFG_NXP_CAAM,n) +$(call force,CFG_IMX_DCP,y) +$(call force,CFG_NO_SMP,y) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6sx-flavorlist))) +$(call force,CFG_MX6,y) +$(call force,CFG_MX6SX,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7s-flavorlist))) +$(call force,CFG_MX7,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +include core/arch/arm/cpu/cortex-a7.mk +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7d-flavorlist))) +$(call force,CFG_MX7,y) +$(call force,CFG_TEE_CORE_NB_CORE,2) +include core/arch/arm/cpu/cortex-a7.mk +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7ulp-flavorlist))) +$(call force,CFG_MX7ULP,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_TZC380,n) +$(call force,CFG_IMX_CSU,n) +include core/arch/arm/cpu/cortex-a7.mk +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mq-flavorlist))) +$(call force,CFG_MX8MQ,y) +$(call force,CFG_MX8M,y) +$(call force,CFG_ARM64_core,y) +CFG_DRAM_BASE ?= 0x40000000 +CFG_TEE_CORE_NB_CORE ?= 4 +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mm-flavorlist))) +$(call force,CFG_MX8MM,y) +$(call force,CFG_MX8M,y) +$(call force,CFG_ARM64_core,y) +CFG_DRAM_BASE ?= 0x40000000 +CFG_TEE_CORE_NB_CORE ?= 4 +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mn-flavorlist))) +$(call force,CFG_MX8MN,y) +$(call force,CFG_MX8M,y) +$(call force,CFG_ARM64_core,y) +CFG_DRAM_BASE ?= 0x40000000 +CFG_TEE_CORE_NB_CORE ?= 4 +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mp-flavorlist))) +$(call force,CFG_MX8MP,y) +$(call force,CFG_MX8M,y) +$(call force,CFG_ARM64_core,y) +CFG_DRAM_BASE ?= 0x40000000 +CFG_TEE_CORE_NB_CORE ?= 4 +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8qm-flavorlist))) +$(call force,CFG_MX8QM,y) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_IMX_SNVS,n) +CFG_IMX_LPUART ?= y +CFG_DRAM_BASE ?= 0x80000000 +CFG_TEE_CORE_NB_CORE ?= 6 +$(call force,CFG_IMX_OCOTP,n) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8qx-flavorlist))) +$(call force,CFG_MX8QX,y) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_IMX_SNVS,n) +CFG_IMX_LPUART ?= y +CFG_DRAM_BASE ?= 0x80000000 +CFG_TEE_CORE_NB_CORE ?= 4 +$(call force,CFG_IMX_OCOTP,n) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8dxl-flavorlist))) +$(call force,CFG_MX8DXL,y) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_IMX_SNVS,n) +CFG_IMX_LPUART ?= y +CFG_DRAM_BASE ?= 0x80000000 +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_IMX_OCOTP,n) +$(call force,CFG_NXP_CAAM,n) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8ulp-flavorlist))) +$(call force,CFG_MX8ULP,y) +$(call force,CFG_ARM64_core,y) +CFG_IMX_LPUART ?= y +CFG_DRAM_BASE ?= 0x80000000 +CFG_TEE_CORE_NB_CORE ?= 2 +$(call force,CFG_NXP_SNVS,n) +$(call force,CFG_IMX_OCOTP,n) +CFG_IMX_MU ?= y +CFG_IMX_ELE ?= y +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx93-flavorlist))) +$(call force,CFG_MX93,y) +$(call force,CFG_ARM64_core,y) +CFG_IMX_LPUART ?= y +CFG_DRAM_BASE ?= 0x80000000 +CFG_TEE_CORE_NB_CORE ?= 2 +$(call force,CFG_NXP_SNVS,n) +$(call force,CFG_IMX_OCOTP,n) +$(call force,CFG_TZC380,n) +$(call force,CFG_CRYPTO_DRIVER,n) +$(call force,CFG_NXP_CAAM,n) +CFG_IMX_MU ?= y +CFG_IMX_ELE ?= y +else +$(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)") +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx7dsabresd)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_NS_ENTRY_ADDR ?= 0x80800000 +CFG_IMX_WDOG_EXT_RESET ?= y +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx7dclsom)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_UART_BASE ?= UART1_BASE +CFG_IMX_WDOG_EXT_RESET ?= y +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx7dpico_mbl)) +CFG_DDR_SIZE ?= 0x20000000 +CFG_NS_ENTRY_ADDR ?= 0x87800000 +CFG_DT_ADDR ?= 0x83100000 +CFG_UART_BASE ?= UART5_BASE +CFG_BOOT_SECONDARY_REQUEST ?= n +CFG_EXTERNAL_DTB_OVERLAY ?= y +CFG_IMX_WDOG_EXT_RESET ?= y +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx7swarp7)) +CFG_DDR_SIZE ?= 0x20000000 +CFG_NS_ENTRY_ADDR ?= 0x80800000 +CFG_BOOT_SECONDARY_REQUEST ?= n +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx7swarp7_mbl)) +CFG_DDR_SIZE ?= 0x20000000 +CFG_NS_ENTRY_ADDR ?= 0x87800000 +CFG_DT_ADDR ?= 0x83100000 +CFG_BOOT_SECONDARY_REQUEST ?= n +CFG_EXTERNAL_DTB_OVERLAY = y +CFG_IMX_WDOG_EXT_RESET = y +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx7ulpevk)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_NS_ENTRY_ADDR ?= 0x60800000 +CFG_UART_BASE ?= UART4_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6qpsabresd mx6qsabresd mx6dlsabresd \ + mx6dlsabrelite mx6dhmbedge mx6dlhmbedge mx6solosabresd \ + mx6dapalis mx6qapalis)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_NS_ENTRY_ADDR ?= 0x12000000 +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6qpsabreauto mx6qsabreauto \ + mx6dlsabreauto mx6solosabreauto)) +CFG_DDR_SIZE ?= 0x80000000 +CFG_NS_ENTRY_ADDR ?= 0x12000000 +CFG_UART_BASE ?= UART4_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6qhmbedge)) +CFG_DDR_SIZE ?= 0x80000000 +CFG_UART_BASE ?= UART1_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6shmbedge)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_NS_ENTRY_ADDR ?= 0x12000000 +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6qsabrelite mx6dlsabrelite)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_NS_ENTRY_ADDR ?= 0x12000000 +CFG_UART_BASE ?= UART2_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6slevk)) +CFG_NS_ENTRY_ADDR ?= 0x80800000 +CFG_DDR_SIZE ?= 0x40000000 +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6sllevk)) +CFG_NS_ENTRY_ADDR ?= 0x80800000 +CFG_DDR_SIZE ?= 0x80000000 +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6sxsabreauto)) +CFG_DDR_SIZE ?= 0x80000000 +CFG_NS_ENTRY_ADDR ?= 0x80800000 +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6sxsabresd)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_NS_ENTRY_ADDR ?= 0x80800000 +endif + +ifeq ($(PLATFORM_FLAVOR), mx6sxudooneofull) +CFG_DDR_SIZE ?= 0x40000000 +CFG_UART_BASE ?= UART1_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6ulevk mx6ullevk mx6ulzevk)) +CFG_DDR_SIZE ?= 0x20000000 +CFG_NS_ENTRY_ADDR ?= 0x80800000 +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6ulccimx6ulsbcpro)) +CFG_DDR_SIZE ?= 0x10000000 +CFG_NS_ENTRY_ADDR ?= 0x80800000 +CFG_UART_BASE ?= UART5_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6ul9x9evk)) +CFG_DDR_SIZE ?= 0x10000000 +CFG_NS_ENTRY_ADDR ?= 0x80800000 +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx6ulccbv2)) +CFG_DDR_SIZE ?= 0x10000000 +CFG_UART_BASE ?= UART7_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mqevk)) +CFG_DDR_SIZE ?= 0xc0000000 +CFG_UART_BASE ?= UART1_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mmevk)) +CFG_DDR_SIZE ?= 0x80000000 +CFG_UART_BASE ?= UART2_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mm_cl_iot_gate)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_UART_BASE ?= UART3_BASE +CFG_NSEC_DDR_1_BASE ?= 0x80000000UL +CFG_NSEC_DDR_1_SIZE ?= 0x40000000UL +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mnevk)) +CFG_DDR_SIZE ?= 0x80000000 +CFG_UART_BASE ?= UART2_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mpevk)) +CFG_DDR_SIZE ?= UL(0x180000000) +CFG_UART_BASE ?= UART2_BASE +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mp_rsb3720_6g)) +CFG_DDR_SIZE ?= UL(0x180000000) +CFG_UART_BASE ?= UART3_BASE +CFG_TZDRAM_START ?= 0x56000000 +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8qxpmek mx8qmmek)) +CFG_DDR_SIZE ?= 0x80000000 +CFG_UART_BASE ?= UART0_BASE +CFG_NSEC_DDR_1_BASE ?= 0x880000000UL +CFG_NSEC_DDR_1_SIZE ?= 0x380000000UL +CFG_CORE_ARM64_PA_BITS ?= 40 +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8dxlevk)) +CFG_DDR_SIZE ?= 0x40000000 +CFG_UART_BASE ?= UART0_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx8ulpevk)) +CFG_DDR_SIZE ?= 0x80000000 +CFG_UART_BASE ?= UART5_BASE +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),mx93evk)) +CFG_DDR_SIZE ?= 0x80000000 +CFG_UART_BASE ?= UART1_BASE +endif + +# i.MX6 Solo/SL/SoloX/DualLite/Dual/Quad specific config +ifeq ($(filter y, $(CFG_MX6QP) $(CFG_MX6Q) $(CFG_MX6D) $(CFG_MX6DL) $(CFG_MX6S) \ + $(CFG_MX6SL) $(CFG_MX6SLL) $(CFG_MX6SX)), y) +include core/arch/arm/cpu/cortex-a9.mk + +$(call force,CFG_PL310,y) + +CFG_PL310_LOCKED ?= y +CFG_ENABLE_SCTLR_RR ?= y +CFG_IMX_SCU ?= y +endif + +ifeq ($(filter y, $(CFG_MX6QP) $(CFG_MX6Q) $(CFG_MX6D) $(CFG_MX6DL) $(CFG_MX6S)), y) +CFG_DRAM_BASE ?= 0x10000000 +endif + +ifneq (,$(filter y, $(CFG_MX6UL) $(CFG_MX6ULL) $(CFG_MX6SL) $(CFG_MX6SLL) \ + $(CFG_MX6SX))) +CFG_DRAM_BASE ?= 0x80000000 +endif + +ifeq ($(filter y, $(CFG_MX7)), y) +CFG_INIT_CNTVOFF ?= y +CFG_DRAM_BASE ?= 0x80000000 +endif + +ifeq ($(filter y, $(CFG_MX7ULP)), y) +CFG_INIT_CNTVOFF ?= y +CFG_DRAM_BASE ?= UL(0x60000000) +$(call force,CFG_IMX_LPUART,y) +$(call force,CFG_BOOT_SECONDARY_REQUEST,n) +endif + +ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX7ULP))) +$(call force,CFG_GIC,y) + +CFG_BOOT_SECONDARY_REQUEST ?= y +CFG_DT ?= y +CFG_DTB_MAX_SIZE ?= 0x20000 +CFG_PAGEABLE_ADDR ?= 0 +CFG_PSCI_ARM32 ?= y +CFG_SECURE_TIME_SOURCE_REE ?= y +CFG_UART_BASE ?= UART1_BASE +endif + +ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX8M))) +$(call force,CFG_IMX_UART,y) +CFG_IMX_SNVS ?= y +endif + +ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7))) +CFG_IMX_CSU ?= y +endif + +ifeq ($(filter y, $(CFG_PSCI_ARM32)), y) +CFG_HWSUPP_MEM_PERM_WXN = n +CFG_IMX_WDOG ?= y +endif + +ifeq ($(CFG_ARM64_core),y) +# arm-v8 platforms +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_GIC,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) + +CFG_CRYPTO_WITH_CE ?= y + +supported-ta-targets = ta_arm64 +endif + +CFG_TZDRAM_SIZE ?= 0x01e00000 +CFG_SHMEM_SIZE ?= 0x00200000 +CFG_TZDRAM_START ?= ($(CFG_DRAM_BASE) - $(CFG_TZDRAM_SIZE) - $(CFG_SHMEM_SIZE) + $(CFG_DDR_SIZE)) +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) + +CFG_CRYPTO_SIZE_OPTIMIZATION ?= n +CFG_MMAP_REGIONS ?= 24 + +# SE05X and OCOTP both implement tee_otp_get_die_id() +ifeq ($(CFG_NXP_SE05X),y) +$(call force,CFG_IMX_OCOTP,n) +endif +CFG_IMX_OCOTP ?= y +CFG_IMX_DIGPROG ?= y + +# Almost all platforms include CAAM HW Modules, except the +# ones forced to be disabled +CFG_NXP_CAAM ?= n + +ifeq ($(CFG_NXP_CAAM),y) +ifeq ($(filter y, $(CFG_MX8QM) $(CFG_MX8QX) $(CFG_MX8DXL)), y) +CFG_IMX_SC ?= y +CFG_IMX_MU ?= y +endif + +else + +ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX7ULP))) +CFG_IMX_CAAM ?= y +endif + +endif + diff --git a/optee/optee_os/core/arch/arm/plat-imx/config/imx6qdlsolo.h b/optee/optee_os/core/arch/arm/plat-imx/config/imx6qdlsolo.h new file mode 100644 index 0000000..45bbff8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/config/imx6qdlsolo.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * Copyright 2017-2019 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 CONFIG_IMX6QDLSOLO_H +#define CONFIG_IMX6QDLSOLO_H + +/* + * PL310 TAG RAM Control Register + * + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:3 - 4 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ +#ifndef PL310_TAG_RAM_CTRL_INIT +#define PL310_TAG_RAM_CTRL_INIT 0x00000132 +#endif + +/* + * PL310 DATA RAM Control Register + * + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:3 - 4 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ +#ifndef PL310_DATA_RAM_CTRL_INIT +#define PL310_DATA_RAM_CTRL_INIT 0x00000132 +#endif + +/* + * PL310 Auxiliary Control Register + */ +#ifndef PL310_AUX_CTRL_INIT +#if defined(CFG_MX6QP) || defined(CFG_MX6Q) || defined(CFG_MX6D) +/* + * Early BRESP enabled (bit30=1) + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockown cache lines (bit26=1) + * Pseudo-random replacement policy (bit25=1) + * Force write allocated (default) (bit24:23=00) + * Shared attribute internally ignored (bit22=1, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * 64kb way size (bit19:17=3b011) + * 16-way associativity (bit16=1) + * Store buffer device limitation disabled (bit11=0) + * Cacheable accesses have high prio (bit10=0) + * Full Line Zero (FLZ) enabled (bit0=1) + */ +#define PL310_AUX_CTRL_INIT 0x7E470001 +#else +/* + * Early BRESP enabled (bit30=0) + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockown cache lines (bit26=1) + * Pseudo-random replacement policy (bit25=0) + * Force write allocated (default) (bit24:23=00) + * Shared attribute internally ignored (bit22=1, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * 32kb way size (bit19:17=3b010) + * 8-way associativity (bit16=0) + * Store buffer device limitation enabled (bit11=1) + * Cacheable accesses have high prio (bit10=0) + * Full Line Zero (FLZ) disabled (bit0=0) + */ +#define PL310_AUX_CTRL_INIT 0x3C440800 +#endif +#endif + +/* + * PL310 Prefetch Control Register + * + * Double linefill enabled (bit30=1) + * I/D prefetch enabled (bit29:28=2b11) + * Prefetch drop disabled (bit24=0) + * Incr double linefill disable (bit23=0) + * Prefetch offset = 0xF (bit4:0) + */ +#define PL310_PREFETCH_CTRL_INIT 0x7000000F + +/* + * PL310 Power Register + * + * Dynamic clock gating enabled + * Standby mode enabled + */ +#define PL310_POWER_CTRL_INIT 0x00000003 +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/config/imx6sl.h b/optee/optee_os/core/arch/arm/plat-imx/config/imx6sl.h new file mode 100644 index 0000000..f781892 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/config/imx6sl.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + */ + +#ifndef _CONFIG_IMX6SL_H +#define _CONFIG_IMX6SL_H + +/* + * PL310 TAG RAM Control Register + * + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:3 - 4 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ +#ifndef PL310_TAG_RAM_CTRL_INIT +#define PL310_TAG_RAM_CTRL_INIT 0x00000132 +#endif + +/* + * PL310 DATA RAM Control Register + * + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:3 - 4 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ +#ifndef PL310_DATA_RAM_CTRL_INIT +#define PL310_DATA_RAM_CTRL_INIT 0x00000132 +#endif + +/* + * PL310 Auxiliary Control Register + * + * Early BRESP enabled (bit30=1) + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockown cache lines (bit26=1) + * Pseudo-random replacement policy (bit25=1) + * Force write allocated (default) (bit24:23=00) + * Shared attribute internally ignored (bit22=1, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * 16kb way size (bit19:17=3b001) + * 16-way associativity (bit16=1) + * Store buffer device limitation enabled (bit11=0) + * Cacheable accesses have high prio (bit10=0) + * Full Line Zero (FLZ) enabled (bit0=1) + */ +#ifndef PL310_AUX_CTRL_INIT +#define PL310_AUX_CTRL_INIT 0x7E430001 +#endif + +/* + * PL310 Prefetch Control Register + * + * Double linefill enabled (bit30=1) + * I/D prefetch enabled (bit29:28=2b11) + * Prefetch drop disabled (bit24=0) + * Incr double linefill disable (bit23=0) + * Prefetch offset = 0xF (bit4:0) + */ +#define PL310_PREFETCH_CTRL_INIT 0x7000000F + +/* + * PL310 Power Register + * + * Dynamic clock gating enabled + * Standby mode enabled + */ +#define PL310_POWER_CTRL_INIT 0x00000003 +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/config/imx6sll.h b/optee/optee_os/core/arch/arm/plat-imx/config/imx6sll.h new file mode 100644 index 0000000..048f748 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/config/imx6sll.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + */ + +#ifndef _CONFIG_IMX6SLL_H +#define _CONFIG_IMX6SLL_H + +/* + * PL310 TAG RAM Control Register + * + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:3 - 4 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ +#ifndef PL310_TAG_RAM_CTRL_INIT +#define PL310_TAG_RAM_CTRL_INIT 0x00000132 +#endif + +/* + * PL310 DATA RAM Control Register + * + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:3 - 4 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ +#ifndef PL310_DATA_RAM_CTRL_INIT +#define PL310_DATA_RAM_CTRL_INIT 0x00000132 +#endif + +/* + * PL310 Auxiliary Control Register + * + * Early BRESP enabled (bit30=1) + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockown cache lines (bit26=1) + * Pseudo-random replacement policy (bit25=1) + * Force write allocated (default) (bit24:23=00) + * Shared attribute internally ignored (bit22=1, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * 16kb way size (bit19:17=3b001) + * 16-way associativity (bit16=1) + * Store buffer device limitation enabled (bit11=0) + * Cacheable accesses have high prio (bit10=0) + * Full Line Zero (FLZ) enabled (bit0=1) + */ +#ifndef PL310_AUX_CTRL_INIT +#define PL310_AUX_CTRL_INIT 0x7E430001 +#endif + +/* + * PL310 Prefetch Control Register + * + * Double linefill enabled (bit30=1) + * I/D prefetch enabled (bit29:28=2b11) + * Prefetch drop disabled (bit24=0) + * Incr double linefill disable (bit23=0) + * Prefetch offset = 0xF (bit4:0) + */ +#define PL310_PREFETCH_CTRL_INIT 0x7000000F + +/* + * PL310 Power Register + * + * Dynamic clock gating enabled + * Standby mode enabled + */ +#define PL310_POWER_CTRL_INIT 0x00000003 +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/config/imx6sx.h b/optee/optee_os/core/arch/arm/plat-imx/config/imx6sx.h new file mode 100644 index 0000000..2636855 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/config/imx6sx.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + * + * Peng Fan + */ + +#ifndef __CONFIG_IMX6SX_H +#define __CONFIG_IMX6SX_H + +/* + * PL310 TAG RAM Control Register + * + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:3 - 4 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ +#ifndef PL310_TAG_RAM_CTRL_INIT +#define PL310_TAG_RAM_CTRL_INIT 0x00000132 +#endif + +/* + * PL310 DATA RAM Control Register + * + * bit[10:8]:1 - 2 cycle of write accesses latency + * bit[6:4]:3 - 4 cycle of read accesses latency + * bit[2:0]:2 - 3 cycle of setup latency + */ +#ifndef PL310_DATA_RAM_CTRL_INIT +#define PL310_DATA_RAM_CTRL_INIT 0x00000132 +#endif + +/* + * PL310 Auxiliary Control Register + * + * Early BRESP enabled (bit30=1) + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockown cache lines (bit26=1) + * Pseudo-random replacement policy (bit25=1) + * Force write allocated (default) (bit24:23=00) + * Shared attribute internally ignored (bit22=1, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * 16kb way size (bit19:17=3b001) + * 16-way associativity (bit16=1) + * Store buffer device limitation enabled (bit11=0) + * Cacheable accesses have high prio (bit10=0) + * Full Line Zero (FLZ) enabled (bit0=1) + */ +#ifndef PL310_AUX_CTRL_INIT +#define PL310_AUX_CTRL_INIT 0x7E430001 +#endif + +/* + * PL310 Prefetch Control Register + * + * Double linefill enabled (bit30=1) + * I/D prefetch enabled (bit29:28=2b11) + * Prefetch drop disabled (bit24=0) + * Incr double linefill disable (bit23=0) + * Prefetch offset = 0xF (bit4:0) + */ +#define PL310_PREFETCH_CTRL_INIT 0x7000000F + +/* + * PL310 Power Register + * + * Dynamic clock gating enabled + * Standby mode enabled + */ +#define PL310_POWER_CTRL_INIT 0x00000003 +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/imx-common.c b/optee/optee_os/core/arch/arm/plat-imx/imx-common.c new file mode 100644 index 0000000..7339137 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx-common.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2019, 2021 NXP + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SOC_TYPE(reg) (((reg) & (0x00FF0000)) >> 16) +#define SOC_REV_MAJOR(reg) (((reg) & (0x0000FF00)) >> 8) +#define SOC_REV_MINOR(reg) ((reg) & (0x0000000F)) +#define SOC_REV_MINOR_MX7(reg) ((reg) & (0x000000FF)) + +static uint32_t imx_digprog; + +#ifdef ANATOP_BASE +uint32_t imx_get_digprog(void) +{ + vaddr_t addr = 0; + + if (imx_digprog) + return imx_digprog; + + addr = core_mmu_get_va(ANATOP_BASE, MEM_AREA_IO_SEC, 0x1000); + if (!addr) + return 0; + + imx_digprog = io_read32(addr + DIGPROG_OFFSET); + +#ifdef CFG_MX8MQ + /* + * On the i.MX8MQ, the minor revision number must be updated to make + * the difference between B0 chip and the newer chips. + */ + addr = core_mmu_get_va(OCOTP_BASE, MEM_AREA_IO_SEC, OCOTP_SIZE); + if (!addr) + return 0; + + if (io_read32(addr + OCOTP_SW_INFO_B1) == OCOTP_SW_MAGIC_B1) + imx_digprog |= BIT32(0); +#endif /* CFG_MX8MQ */ + + return imx_digprog; +} +#else /* ANATOP_BASE */ +uint32_t imx_get_digprog(void) +{ + if (imx_digprog) + return imx_digprog; + + if (IS_ENABLED(CFG_MX7ULP)) + imx_digprog = SOC_MX7ULP << 16; + else if (IS_ENABLED(CFG_MX8QX)) + imx_digprog = SOC_MX8QX << 16; + else if (IS_ENABLED(CFG_MX8QM)) + imx_digprog = SOC_MX8QM << 16; + else if (IS_ENABLED(CFG_MX8DXL)) + imx_digprog = SOC_MX8DXL << 16; + else if (IS_ENABLED(CFG_MX8ULP)) + imx_digprog = SOC_MX8ULP << 16; + else if (IS_ENABLED(CFG_MX93)) + imx_digprog = SOC_MX93 << 16; + + return imx_digprog; +} +#endif /* ANATOP_BASE */ + +uint32_t imx_soc_rev_major(void) +{ + if (imx_digprog == 0) + imx_get_digprog(); + + return SOC_REV_MAJOR(imx_digprog); +} + +uint32_t imx_soc_rev_minor(void) +{ + if (imx_digprog == 0) + imx_get_digprog(); + + if (IS_ENABLED(CFG_MX7)) + return SOC_REV_MINOR_MX7(imx_digprog); + else + return SOC_REV_MINOR(imx_digprog); +} + +uint32_t imx_soc_type(void) +{ + if (imx_digprog == 0) + imx_get_digprog(); + + return SOC_TYPE(imx_digprog); +} + +bool soc_is_imx6sl(void) +{ + return imx_soc_type() == SOC_MX6SL; +} + +bool soc_is_imx6sll(void) +{ + return imx_soc_type() == SOC_MX6SLL; +} + +bool soc_is_imx6sx(void) +{ + return imx_soc_type() == SOC_MX6SX; +} + +bool soc_is_imx6ul(void) +{ + return imx_soc_type() == SOC_MX6UL; +} + +bool soc_is_imx6ull(void) +{ + return imx_soc_type() == SOC_MX6ULL; +} + +bool soc_is_imx6sdl(void) +{ + return imx_soc_type() == SOC_MX6DL; +} + +bool soc_is_imx6dq(void) +{ + return (imx_soc_type() == SOC_MX6Q) && (imx_soc_rev_major() == 0); +} + +bool soc_is_imx6dqp(void) +{ + return (imx_soc_type() == SOC_MX6Q) && (imx_soc_rev_major() == 1); +} + +bool soc_is_imx6(void) +{ + uint32_t soc = imx_soc_type(); + + return (soc == SOC_MX6SLL) || (soc == SOC_MX6SL) || + (soc == SOC_MX6D) || (soc == SOC_MX6SX) || + (soc == SOC_MX6UL) || (soc == SOC_MX6ULL) || + (soc == SOC_MX6DL) || (soc == SOC_MX6Q); +} + +bool soc_is_imx7ds(void) +{ + return imx_soc_type() == SOC_MX7D; +} + +bool soc_is_imx7ulp(void) +{ + return imx_soc_type() == SOC_MX7ULP; +} + +bool soc_is_imx8mq(void) +{ + return imx_soc_type() == SOC_MX8M && imx_soc_rev_major() == 0x40; +} + +bool soc_is_imx8mm(void) +{ + return imx_soc_type() == SOC_MX8M && imx_soc_rev_major() == 0x41; +} + +bool soc_is_imx8mn(void) +{ + return imx_soc_type() == SOC_MX8M && imx_soc_rev_major() == 0x42; +} + +bool soc_is_imx8mp(void) +{ + return imx_soc_type() == SOC_MX8M && imx_soc_rev_major() == 0x43; +} + +bool soc_is_imx8m(void) +{ + return soc_is_imx8mq() || soc_is_imx8mm() || soc_is_imx8mn() || + soc_is_imx8mp(); +} + +bool soc_is_imx8mq_b0_layer(void) +{ + if (soc_is_imx8mq() && imx_soc_rev_minor() == 0x0) + return true; + else + return false; +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/imx-regs.h b/optee/optee_os/core/arch/arm/plat-imx/imx-regs.h new file mode 100644 index 0000000..98c51b2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx-regs.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * Copyright 2019 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLAT_IMX_IMX_REGS_H +#define PLAT_IMX_IMX_REGS_H + +#ifdef CFG_MX6 +#include +#elif defined(CFG_MX7) +#include +#elif defined(CFG_MX7ULP) +#include +#elif defined(CFG_MX8MQ) || defined(CFG_MX8MM) || defined(CFG_MX8MN) || \ + defined(CFG_MX8MP) +#include +#elif defined(CFG_MX8QX) || defined(CFG_MX8QM) || defined(CFG_MX8DXL) +#include +#elif defined(CFG_MX8ULP) +#include +#elif defined(CFG_MX93) +#include +#else +#error "CFG_MX* not defined" +#endif + +#define IOMUXC_GPR4_OFFSET 0x10 +#define IOMUXC_GPR5_OFFSET 0x14 +#define ARM_WFI_STAT_MASK(n) BIT(n) + +#define ARM_WFI_STAT_MASK_7D(n) BIT(25 + ((n) & 1)) + +#define SRC_SCR 0x000 +#define SRC_GPR1 0x020 +#define SRC_GPR2 0x024 +#define SRC_SCR_CORE1_RST_OFFSET 14 +#define SRC_SCR_CORE1_ENABLE_OFFSET 22 +#define SRC_SCR_CPU_ENABLE_ALL SHIFT_U32(0x7, 22) + +#define SRC_GPR1_MX7 0x074 +#define SRC_A7RCR0 0x004 +#define SRC_A7RCR1 0x008 +#define SRC_A7RCR0_A7_CORE_RESET0_OFFSET 0 +#define SRC_A7RCR1_A7_CORE1_ENABLE_OFFSET 1 + +#define SNVS_LPCR_OFF 0x38 +#define SNVS_LPCR_TOP_MASK BIT(6) +#define SNVS_LPCR_DP_EN_MASK BIT(5) +#define SNVS_LPCR_SRTC_ENV_MASK 1 + +#define WCR_OFF 0 + +/* GPC V2 */ +#define GPC_PGC_C1 0x840 +#define GPC_PGC_C1_PUPSCR 0x844 + +#define GPC_PGC_PCG_MASK BIT(0) + +#define GPC_CPU_PGC_SW_PUP_REQ 0xf0 +#define GPC_PU_PGC_SW_PUP_REQ 0xf8 +#define GPC_CPU_PGC_SW_PDN_REQ 0xfc +#define GPC_PU_PGC_SW_PDN_REQ 0x104 +#define GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK BIT(1) +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/imx.h b/optee/optee_os/core/arch/arm/plat-imx/imx.h new file mode 100644 index 0000000..0d5776d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + * + * Peng Fan + */ +#ifndef PLAT_IMX_IMX_H +#define PLAT_IMX_IMX_H + +#include +#include + +#define SOC_MX6SL 0x60 +#define SOC_MX6DL 0x61 +#define SOC_MX6SX 0x62 +#define SOC_MX6Q 0x63 +#define SOC_MX6UL 0x64 +#define SOC_MX6ULL 0x65 +#define SOC_MX6SLL 0x67 +#define SOC_MX6D 0x6A +#define SOC_MX7D 0x72 +#define SOC_MX7ULP 0xE1 +#define SOC_MX8QX 0xE2 +#define SOC_MX8QM 0xE3 +#define SOC_MX8DXL 0xE4 +#define SOC_MX8M 0x82 +#define SOC_MX8ULP 0x83 +#define SOC_MX93 0xC1 + +#ifndef __ASSEMBLER__ +uint32_t imx_get_src_gpr(int cpu); +void imx_set_src_gpr(int cpu, uint32_t val); +bool soc_is_imx6(void); +bool soc_is_imx6sx(void); +bool soc_is_imx6sl(void); +bool soc_is_imx6sll(void); +bool soc_is_imx6ul(void); +bool soc_is_imx6ull(void); +bool soc_is_imx6sdl(void); +bool soc_is_imx6dq(void); +bool soc_is_imx6dqp(void); +bool soc_is_imx7ds(void); +bool soc_is_imx7ulp(void); +bool soc_is_imx8m(void); +bool soc_is_imx8mq(void); +bool soc_is_imx8mm(void); +bool soc_is_imx8mn(void); +bool soc_is_imx8mp(void); +bool soc_is_imx8mq_b0_layer(void); +uint32_t imx_soc_type(void); +uint32_t imx_soc_rev_major(void); +uint32_t imx_soc_rev_minor(void); +uint32_t imx_get_digprog(void); +void imx_gpcv2_set_core1_pdn_by_software(void); +void imx_gpcv2_set_core1_pup_by_software(void); +void imx_gpcv2_set_core_pgc(bool enable, uint32_t offset); + +#endif /* __ASSEMBLER__ */ +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c b/optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c new file mode 100644 index 0000000..202d64b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx_pl310.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imx_pl310.h" + +#define PL310_AUX_CTRL_FLZW BIT(0) +#define PL310_DEBUG_CTRL_DISABLE_WRITEBACK BIT(1) +#define PL310_DEBUG_CTRL_DISABLE_LINEFILL BIT(0) +#define PL310_PREFETCH_DOUBLE_LINEFILL BIT(30) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); + +void arm_cl2_config(vaddr_t pl310_base) +{ + uint32_t val = 0; + uint32_t id = 0; + + /* Disable PL310 */ + io_write32(pl310_base + PL310_CTRL, 0); + + io_write32(pl310_base + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT); + io_write32(pl310_base + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT); + io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); + /* + * The L2 cache controller(PL310) version on the i.MX6D/Q + * is r3p1-50rel0 + * The L2 cache controller(PL310) version on the + * i.MX6DL/SOLO/SL/SX/DQP is r3p2. + * + * According to ARM PL310 errata: 752271 + * ID: 752271: Double linefill feature can cause data corruption + * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 + * Workaround: The only workaround to this erratum is to disable the + * double linefill feature. This is the default behavior. + */ + val = PL310_PREFETCH_CTRL_INIT; + + id = io_read32(pl310_base + PL310_CACHE_ID); + + if (((id & PL310_CACHE_ID_PART_MASK) == PL310_CACHE_ID_PART_L310) && + ((id & PL310_CACHE_ID_RTL_MASK) < PL310_CACHE_ID_RTL_R3P2)) + val &= ~PL310_PREFETCH_DOUBLE_LINEFILL; + + io_write32(pl310_base + PL310_PREFETCH_CTRL, val); + + io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); + + /* invalidate all cache ways */ + arm_cl2_invbyway(pl310_base); +} + +void arm_cl2_enable(vaddr_t pl310_base) +{ + uint32_t val __maybe_unused; + + /* Enable PL310 ctrl -> only set lsb bit */ + io_write32(pl310_base + PL310_CTRL, 1); + +#ifndef CFG_PL310_SIP_PROTOCOL + /* if L2 FLZW enable, enable in L1 */ + val = io_read32(pl310_base + PL310_AUX_CTRL); + if (val & PL310_AUX_CTRL_FLZW) + write_actlr(read_actlr() | ACTLR_CA9_WFLZ); +#endif +} + +vaddr_t pl310_base(void) +{ + return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1); +} + +#ifdef CFG_PL310_SIP_PROTOCOL +uint32_t pl310_enable(void) +{ + vaddr_t base = pl310_base(); + + arm_cl2_config(base); + arm_cl2_enable(base); + return OPTEE_SMC_RETURN_OK; +} + +uint32_t pl310_disable(void) +{ + EMSG("not implemented"); + return OPTEE_SMC_RETURN_ENOTAVAIL; +} + +uint32_t pl310_enable_writeback(void) +{ + vaddr_t base = pl310_base(); + + io_write32(base + PL310_DEBUG_CTRL, 0); + return OPTEE_SMC_RETURN_OK; +} + +uint32_t pl310_disable_writeback(void) +{ + vaddr_t base = pl310_base(); + uint32_t val = PL310_DEBUG_CTRL_DISABLE_WRITEBACK | + PL310_DEBUG_CTRL_DISABLE_LINEFILL; + + io_write32(base + PL310_DEBUG_CTRL, val); + return OPTEE_SMC_RETURN_OK; +} + +uint32_t pl310_enable_wflz(void) +{ + write_actlr(read_actlr() | ACTLR_CA9_WFLZ); + return OPTEE_SMC_RETURN_OK; +} +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/imx_pl310.h b/optee/optee_os/core/arch/arm/plat-imx/imx_pl310.h new file mode 100644 index 0000000..4fef57b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx_pl310.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + */ +#ifndef __IMX_PL310_H__ +#define __IMX_PL310_H__ + +uint32_t pl310_enable(void); +uint32_t pl310_disable(void); +uint32_t pl310_enable_writeback(void); +uint32_t pl310_disable_writeback(void); +uint32_t pl310_enable_wflz(void); + +#endif /* __IMX_PL310_H__ */ + diff --git a/optee/optee_os/core/arch/arm/plat-imx/imx_pm.h b/optee/optee_os/core/arch/arm/plat-imx/imx_pm.h new file mode 100644 index 0000000..a9a65be --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx_pm.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017 NXP + */ + +#ifndef __IMX_PM_H +#define __IMX_PM_H + +#include + +#define MX7_DDRC_NUM 32 +#define MX7_DDRC_PHY_NUM 16 + +#define SUSPEND_OCRAM_SIZE 0x1000 +#define LOWPOWER_IDLE_OCRAM_SIZE 0x1000 + +#define SUSPEND_OCRAM_OFFSET 0x0 +#define LOWPOWER_IDLE_OCRAM_OFFSET 0x1000 + +#ifndef __ASSEMBLER__ +#include + +/* The structure is used for suspend and low power idle */ +struct imx7_pm_info { + uint32_t m4_reserve0; + uint32_t m4_reserve1; + uint32_t m4_reserve2; + vaddr_t va_base; /* va of pm_info */ + paddr_t pa_base; /* pa of pm_info */ + uintptr_t entry; + paddr_t tee_resume; + uint32_t ddr_type; + uint32_t pm_info_size; + paddr_t ddrc_pa_base; + vaddr_t ddrc_va_base; + paddr_t ddrc_phy_pa_base; + vaddr_t ddrc_phy_va_base; + paddr_t src_pa_base; + vaddr_t src_va_base; + paddr_t iomuxc_gpr_pa_base; + vaddr_t iomuxc_gpr_va_base; + paddr_t ccm_pa_base; + vaddr_t ccm_va_base; + paddr_t gpc_pa_base; + vaddr_t gpc_va_base; + paddr_t snvs_pa_base; + vaddr_t snvs_va_base; + paddr_t anatop_pa_base; + vaddr_t anatop_va_base; + paddr_t lpsr_pa_base; + vaddr_t lpsr_va_base; + paddr_t gic_pa_base; + vaddr_t gic_va_base; + uint32_t ttbr0; + uint32_t ttbr1; + uint32_t num_online_cpus; + uint32_t num_lpi_cpus; + uint32_t val; + uint32_t flag0; + uint32_t flag1; + uint32_t ddrc_num; + uint32_t ddrc_val[MX7_DDRC_NUM][2]; + uint32_t ddrc_phy_num; + uint32_t ddrc_phy_val[MX7_DDRC_NUM][2]; +} __aligned(8); + +struct suspend_save_regs { + uint32_t irq[3]; + uint32_t fiq[3]; + uint32_t und[3]; + uint32_t abt[3]; + uint32_t mon[3]; +} __aligned(8); + +struct imx7_pm_data { + uint32_t ddr_type; + uint32_t ddrc_num; + uint32_t (*ddrc_offset)[2]; + uint32_t ddrc_phy_num; + uint32_t (*ddrc_phy_offset)[2]; +}; + +void imx7_suspend(struct imx7_pm_info *info); +void imx7_resume(void); +void ca7_cpu_resume(void); +int imx7_suspend_init(void); +int pm_imx7_iram_tbl_init(void); +int imx7_cpu_suspend(uint32_t power_state, uintptr_t entry, + uint32_t context_id, struct sm_nsec_ctx *nsec); +int imx7d_lowpower_idle(uint32_t power_state, uintptr_t entry, + uint32_t context_id, struct sm_nsec_ctx *nsec); +void imx7d_low_power_idle(struct imx7_pm_info *info); +int imx7d_cpuidle_init(void); +void v7_cpu_resume(void); +#endif + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/imx_pm_asm_defines.c b/optee/optee_os/core/arch/arm/plat-imx/imx_pm_asm_defines.c new file mode 100644 index 0000000..76b1c6f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx_pm_asm_defines.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include "imx_pm.h" + +DEFINES +{ + DEFINE(PM_INFO_MX7_M4_RESERVE0_OFF, + offsetof(struct imx7_pm_info, m4_reserve0)); + DEFINE(PM_INFO_MX7_M4_RESERVE1_OFF, + offsetof(struct imx7_pm_info, m4_reserve1)); + DEFINE(PM_INFO_MX7_M4_RESERVE2_OFF, + offsetof(struct imx7_pm_info, m4_reserve2)); + DEFINE(PM_INFO_MX7_VBASE_OFF, offsetof(struct imx7_pm_info, va_base)); + DEFINE(PM_INFO_MX7_PBASE_OFF, offsetof(struct imx7_pm_info, pa_base)); + DEFINE(PM_INFO_MX7_ENTRY_OFF, offsetof(struct imx7_pm_info, entry)); + DEFINE(PM_INFO_MX7_RESUME_ADDR_OFF, + offsetof(struct imx7_pm_info, tee_resume)); + DEFINE(PM_INFO_MX7_DDR_TYPE_OFF, + offsetof(struct imx7_pm_info, ddr_type)); + DEFINE(PM_INFO_MX7_SIZE_OFF, + offsetof(struct imx7_pm_info, pm_info_size)); + DEFINE(PM_INFO_MX7_DDRC_P_OFF, + offsetof(struct imx7_pm_info, ddrc_pa_base)); + DEFINE(PM_INFO_MX7_DDRC_V_OFF, + offsetof(struct imx7_pm_info, ddrc_va_base)); + DEFINE(PM_INFO_MX7_DDRC_PHY_P_OFF, + offsetof(struct imx7_pm_info, ddrc_phy_pa_base)); + DEFINE(PM_INFO_MX7_DDRC_PHY_V_OFF, + offsetof(struct imx7_pm_info, ddrc_phy_va_base)); + DEFINE(PM_INFO_MX7_SRC_P_OFF, + offsetof(struct imx7_pm_info, src_pa_base)); + DEFINE(PM_INFO_MX7_SRC_V_OFF, + offsetof(struct imx7_pm_info, src_va_base)); + DEFINE(PM_INFO_MX7_IOMUXC_GPR_P_OFF, + offsetof(struct imx7_pm_info, iomuxc_gpr_pa_base)); + DEFINE(PM_INFO_MX7_IOMUXC_GPR_V_OFF, + offsetof(struct imx7_pm_info, iomuxc_gpr_va_base)); + DEFINE(PM_INFO_MX7_CCM_P_OFF, + offsetof(struct imx7_pm_info, ccm_pa_base)); + DEFINE(PM_INFO_MX7_CCM_V_OFF, + offsetof(struct imx7_pm_info, ccm_va_base)); + DEFINE(PM_INFO_MX7_GPC_P_OFF, + offsetof(struct imx7_pm_info, gpc_pa_base)); + DEFINE(PM_INFO_MX7_GPC_V_OFF, + offsetof(struct imx7_pm_info, gpc_va_base)); + DEFINE(PM_INFO_MX7_SNVS_P_OFF, + offsetof(struct imx7_pm_info, snvs_pa_base)); + DEFINE(PM_INFO_MX7_SNVS_V_OFF, + offsetof(struct imx7_pm_info, snvs_va_base)); + DEFINE(PM_INFO_MX7_ANATOP_P_OFF, + offsetof(struct imx7_pm_info, anatop_pa_base)); + DEFINE(PM_INFO_MX7_ANATOP_V_OFF, + offsetof(struct imx7_pm_info, anatop_va_base)); + DEFINE(PM_INFO_MX7_LPSR_P_OFF, + offsetof(struct imx7_pm_info, lpsr_pa_base)); + DEFINE(PM_INFO_MX7_LPSR_V_OFF, + offsetof(struct imx7_pm_info, lpsr_va_base)); + DEFINE(PM_INFO_MX7_GIC_DIST_P_OFF, + offsetof(struct imx7_pm_info, gic_pa_base)); + DEFINE(PM_INFO_MX7_GIC_DIST_V_OFF, + offsetof(struct imx7_pm_info, gic_va_base)); + DEFINE(PM_INFO_MX7_TTBR0_OFF, offsetof(struct imx7_pm_info, ttbr0)); + DEFINE(PM_INFO_MX7_TTBR1_OFF, offsetof(struct imx7_pm_info, ttbr1)); + DEFINE(PM_INFO_MX7_NUM_ONLINE_CPUS_OFF, + offsetof(struct imx7_pm_info, num_online_cpus)); + DEFINE(PM_INFO_MX7_NUM_LPI_CPUS_OFF, + offsetof(struct imx7_pm_info, num_lpi_cpus)); + DEFINE(PM_INFO_MX7_VAL_OFF, offsetof(struct imx7_pm_info, val)); + DEFINE(PM_INFO_MX7_FLAG0_OFF, offsetof(struct imx7_pm_info, flag0)); + DEFINE(PM_INFO_MX7_FLAG1_OFF, offsetof(struct imx7_pm_info, flag1)); + DEFINE(PM_INFO_MX7_DDRC_REG_NUM_OFF, + offsetof(struct imx7_pm_info, ddrc_num)); + DEFINE(PM_INFO_MX7_DDRC_REG_OFF, + offsetof(struct imx7_pm_info, ddrc_val)); + DEFINE(PM_INFO_MX7_DDRC_PHY_REG_NUM_OFF, + offsetof(struct imx7_pm_info, ddrc_phy_num)); + DEFINE(PM_INFO_MX7_DDRC_PHY_REG_OFF, + offsetof(struct imx7_pm_info, ddrc_phy_val)); +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/imx_src.c b/optee/optee_os/core/arch/arm/plat-imx/imx_src.c new file mode 100644 index 0000000..d1d5a2a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/imx_src.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 NXP + */ + +#include +#include +#include +#include + +uint32_t imx_get_src_gpr(int cpu) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, 1); + + if (soc_is_imx7ds()) + return io_read32(va + SRC_GPR1_MX7 + cpu * 8 + 4); + else + return io_read32(va + SRC_GPR1 + cpu * 8 + 4); +} + +void imx_set_src_gpr(int cpu, uint32_t val) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, 1); + + if (soc_is_imx7ds()) + io_write32(va + SRC_GPR1_MX7 + cpu * 8 + 4, val); + else + io_write32(va + SRC_GPR1 + cpu * 8 + 4, val); +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/link.mk b/optee/optee_os/core/arch/arm/plat-imx/link.mk new file mode 100644 index 0000000..c5a3673 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/link.mk @@ -0,0 +1,9 @@ +include core/arch/arm/kernel/link.mk + +.PHONY: uTee +uTee: $(link-out-dir)/uTee +cleanfiles += $(link-out-dir)/uTee +$(link-out-dir)/uTee: $(link-out-dir)/tee-raw.bin + @$(cmd-echo-silent) ' MKIMAGE $@' + $(q)ADDR=`printf 0x%x $$(($(subst UL,,$(CFG_TZDRAM_START))))`; \ + mkimage -A arm -O linux -C none -a $$ADDR -e $$ADDR -d $< $@ diff --git a/optee/optee_os/core/arch/arm/plat-imx/main.c b/optee/optee_os/core/arch/arm/plat-imx/main.c new file mode 100644 index 0000000..8788cba --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/main.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * Copyright 2019, 2023 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +static struct gic_data gic_data __nex_bss; + +static struct imx_uart_data console_data __nex_bss; + +#ifdef CONSOLE_UART_BASE +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); +#endif +#ifdef GIC_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); +#endif +#ifdef ANATOP_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, ANATOP_BASE, CORE_MMU_PGDIR_SIZE); +#endif +#ifdef GICD_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, 0x10000); +#endif +#ifdef AIPS0_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AIPS0_BASE, + ROUNDUP(AIPS0_SIZE, CORE_MMU_PGDIR_SIZE)); +#endif +#ifdef AIPS1_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AIPS1_BASE, + ROUNDUP(AIPS1_SIZE, CORE_MMU_PGDIR_SIZE)); +#endif +#ifdef AIPS2_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AIPS2_BASE, + ROUNDUP(AIPS2_SIZE, CORE_MMU_PGDIR_SIZE)); +#endif +#ifdef AIPS3_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AIPS3_BASE, + ROUNDUP(AIPS3_SIZE, CORE_MMU_PGDIR_SIZE)); +#endif +#ifdef IRAM_BASE +register_phys_mem(MEM_AREA_TEE_COHERENT, + ROUNDDOWN(IRAM_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); +#endif +#ifdef M4_AIPS_BASE +register_phys_mem(MEM_AREA_IO_SEC, M4_AIPS_BASE, M4_AIPS_SIZE); +#endif +#ifdef IRAM_S_BASE +register_phys_mem(MEM_AREA_TEE_COHERENT, + ROUNDDOWN(IRAM_S_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); +#endif + +#if defined(CFG_PL310) +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(PL310_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); +#endif + +#ifdef CFG_DRAM_BASE +register_ddr(CFG_DRAM_BASE, CFG_DDR_SIZE); +#endif +#ifdef CFG_NSEC_DDR_1_BASE +register_ddr(CFG_NSEC_DDR_1_BASE, CFG_NSEC_DDR_1_SIZE); +#endif + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ +#ifdef CONSOLE_UART_BASE + imx_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +#endif +} + +void main_init_gic(void) +{ +#ifdef GICD_BASE + gic_init(&gic_data, 0, GICD_BASE); +#else + gic_init(&gic_data, GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +#endif + itr_init(&gic_data.chip); +} + +#if CFG_TEE_CORE_NB_CORE > 1 +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/mmdc.c b/optee/optee_os/core/arch/arm/plat-imx/mmdc.c new file mode 100644 index 0000000..48de2c7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/mmdc.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2021 NXP + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int imx_get_ddr_type(void) +{ + uint32_t val = 0; + uint32_t off = 0; + bool is_mx7 = soc_is_imx7ds(); + vaddr_t mmdc_base = 0; + + if (is_mx7) + off = DDRC_MSTR; + else + off = MMDC_MDMISC; + + mmdc_base = core_mmu_get_va(MMDC_P0_BASE, MEM_AREA_IO_SEC, + off + sizeof(uint32_t)); + val = io_read32(mmdc_base + off); + + if (is_mx7) { + if (val & MSTR_DDR3) + return IMX_DDR_TYPE_DDR3; + else if (val & MSTR_LPDDR2) + return IMX_DDR_TYPE_LPDDR2; + else if (val & MSTR_LPDDR3) + return IMX_DDR_TYPE_LPDDR3; + else + return -1; + } + + return (val & MDMISC_DDR_TYPE_MASK) >> MDMISC_DDR_TYPE_SHIFT; +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/mmdc.h b/optee/optee_os/core/arch/arm/plat-imx/mmdc.h new file mode 100644 index 0000000..fd69c8b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/mmdc.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017 NXP + */ + +#ifndef __IMX_MMDC_H +#define __IMX_MMDC_H + +#define IMX_DDR_TYPE_DDR3 0 +#define IMX_DDR_TYPE_LPDDR2 1 +#define IMX_DDR_TYPE_LPDDR3 2 +/* For i.MX6SLL */ +#define IMX_MMDC_DDR_TYPE_LPDDR3 3 + +/* i.MX6 */ +#define MMDC_MDMISC 0x18 +#define MDMISC_DDR_TYPE_MASK GENMASK_32(4, 3) +#define MDMISC_DDR_TYPE_SHIFT 0x3 + +/* i.MX7 */ +#define DDRC_MSTR 0x0 +#define MSTR_DDR3 BIT(0) +#define MSTR_LPDDR2 BIT(2) +#define MSTR_LPDDR3 BIT(3) + +int imx_get_ddr_type(void); + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-imx/platform_config.h b/optee/optee_os/core/arch/arm/plat-imx/platform_config.h new file mode 100644 index 0000000..d7ebe0d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/platform_config.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * Copyright 2019 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include +#include +#include + +#ifndef CFG_DDR_SIZE +#error "CFG_DDR_SIZE not defined" +#endif + +#define STACK_ALIGNMENT 64 +#define CONSOLE_UART_BASE (CFG_UART_BASE) + +/* For i.MX6 Quad SABRE Lite and Smart Device board */ +#if defined(CFG_MX6QP) || defined(CFG_MX6Q) || defined(CFG_MX6D) || \ + defined(CFG_MX6DL) || defined(CFG_MX6S) +#include +#elif defined(CFG_MX6SX) +#include +/* For i.MX 6SL */ +#elif defined(CFG_MX6SL) +#include +/* For i.MX 6SLL */ +#elif defined(CFG_MX6SLL) +#include +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-imx/pm/cpuidle-imx7d.c b/optee/optee_os/core/arch/arm/plat-imx/pm/cpuidle-imx7d.c new file mode 100644 index 0000000..496027e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/pm/cpuidle-imx7d.c @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018 NXP + * + * Peng Fan + */ + +#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 + +int imx7d_cpuidle_init(void) +{ + uint32_t lpm_idle_ocram_base = + core_mmu_get_va(TRUSTZONE_OCRAM_START + + LOWPOWER_IDLE_OCRAM_OFFSET, + MEM_AREA_TEE_COHERENT, + sizeof(struct imx7_pm_info)); + struct imx7_pm_info *p = + (struct imx7_pm_info *)lpm_idle_ocram_base; + + pm_imx7_iram_tbl_init(); + + dcache_op_level1(DCACHE_OP_CLEAN_INV); + + p->va_base = lpm_idle_ocram_base; + p->pa_base = TRUSTZONE_OCRAM_START + LOWPOWER_IDLE_OCRAM_OFFSET; + p->tee_resume = (paddr_t)virt_to_phys((void *)(vaddr_t)v7_cpu_resume); + p->pm_info_size = sizeof(*p); + p->ddrc_va_base = core_mmu_get_va(DDRC_BASE, MEM_AREA_IO_SEC, 1); + p->ddrc_pa_base = DDRC_BASE; + p->ccm_va_base = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, 1); + p->ccm_pa_base = CCM_BASE; + p->anatop_va_base = core_mmu_get_va(ANATOP_BASE, MEM_AREA_IO_SEC, 1); + p->anatop_pa_base = ANATOP_BASE; + p->src_va_base = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, 1); + p->src_pa_base = SRC_BASE; + p->iomuxc_gpr_va_base = core_mmu_get_va(IOMUXC_GPR_BASE, + MEM_AREA_IO_SEC, 1); + p->iomuxc_gpr_pa_base = IOMUXC_GPR_BASE; + p->gpc_va_base = core_mmu_get_va(GPC_BASE, MEM_AREA_IO_SEC, 1); + p->gpc_pa_base = GPC_BASE; + p->gic_va_base = core_mmu_get_va(GIC_BASE, MEM_AREA_IO_SEC, 1); + p->gic_pa_base = GIC_BASE; + + p->num_lpi_cpus = 0; + p->num_online_cpus = -1; + + memcpy((void *)(lpm_idle_ocram_base + sizeof(*p)), + (void *)(vaddr_t)imx7d_low_power_idle, + LOWPOWER_IDLE_OCRAM_SIZE - sizeof(*p)); + + dcache_clean_range((void *)lpm_idle_ocram_base, + LOWPOWER_IDLE_OCRAM_SIZE); + /* + * Note that IRAM IOSEC map, if changed to MEM map, + * need to flush cache + */ + icache_inv_all(); + + return 0; +} + +static int lowpoweridle_init; + +static void imx_pen_lock(uint32_t cpu) +{ + uint32_t cpuidle_ocram_base; + struct imx7_pm_info *p; + + cpuidle_ocram_base = core_mmu_get_va(TRUSTZONE_OCRAM_START + + LOWPOWER_IDLE_OCRAM_OFFSET, + MEM_AREA_TEE_COHERENT, + sizeof(struct imx7_pm_info)); + p = (struct imx7_pm_info *)cpuidle_ocram_base; + + if (cpu == 0) { + atomic_store_u32(&p->flag0, 1); + dsb(); + atomic_store_u32(&p->val, cpu); + do { + dsb(); + } while (atomic_load_u32(&p->flag1) == 1 + && atomic_load_u32(&p->val) == cpu) + ; + } else { + atomic_store_u32(&p->flag1, 1); + dsb(); + atomic_store_u32(&p->val, cpu); + do { + dsb(); + } while (atomic_load_u32(&p->flag0) == 1 + && atomic_load_u32(&p->val) == cpu) + ; + } +} + +static void imx_pen_unlock(int cpu) +{ + uint32_t cpuidle_ocram_base; + struct imx7_pm_info *p; + + cpuidle_ocram_base = core_mmu_get_va(TRUSTZONE_OCRAM_START + + LOWPOWER_IDLE_OCRAM_OFFSET, + MEM_AREA_TEE_COHERENT, + sizeof(struct imx7_pm_info)); + p = (struct imx7_pm_info *)cpuidle_ocram_base; + + dsb(); + if (cpu == 0) + atomic_store_u32(&p->flag0, 0); + else + atomic_store_u32(&p->flag1, 0); +} + +static uint32_t get_online_cpus(void) +{ + vaddr_t src_a7rcr1 = core_mmu_get_va(SRC_BASE + SRC_A7RCR1, + MEM_AREA_IO_SEC, sizeof(uint32_t)); + uint32_t val = io_read32(src_a7rcr1); + + return (val & (1 << SRC_A7RCR1_A7_CORE1_ENABLE_OFFSET)) ? 2 : 1; +} + +int imx7d_lowpower_idle(uint32_t power_state __unused, + uintptr_t entry __unused, + uint32_t context_id __unused, + struct sm_nsec_ctx *nsec) +{ + struct imx7_pm_info *p; + uint32_t cpuidle_ocram_base; + static uint32_t gic_inited; + int ret; + + uint32_t cpu_id __maybe_unused = get_core_pos(); + uint32_t type = (power_state & PSCI_POWER_STATE_TYPE_MASK) >> + PSCI_POWER_STATE_TYPE_SHIFT; + uint32_t cpu = get_core_pos(); + + cpuidle_ocram_base = core_mmu_get_va(TRUSTZONE_OCRAM_START + + LOWPOWER_IDLE_OCRAM_OFFSET, + MEM_AREA_TEE_COHERENT, + sizeof(struct imx7_pm_info)); + p = (struct imx7_pm_info *)cpuidle_ocram_base; + + imx_pen_lock(cpu); + + if (!lowpoweridle_init) { + imx7d_cpuidle_init(); + lowpoweridle_init = 1; + } + + if (type != PSCI_POWER_STATE_TYPE_POWER_DOWN) + panic(); + + p->num_online_cpus = get_online_cpus(); + p->num_lpi_cpus++; + + sm_save_unbanked_regs(&nsec->ub_regs); + + ret = sm_pm_cpu_suspend((uint32_t)p, (int (*)(uint32_t)) + (cpuidle_ocram_base + sizeof(*p))); + + /* + * Sometimes cpu_suspend may not really suspended, we need to check + * it's return value to restore reg or not + */ + if (ret < 0) { + p->num_lpi_cpus--; + imx_pen_unlock(cpu); + DMSG("=== Not suspended, GPC IRQ Pending === %d\n", cpu_id); + return 0; + } + + /* + * Restore register of different mode in secure world + * When cpu powers up, after ROM init, cpu in secure SVC + * mode, we first need to restore monitor regs. + */ + sm_restore_unbanked_regs(&nsec->ub_regs); + + p->num_lpi_cpus--; + /* Back to Linux */ + nsec->mon_lr = (uint32_t)entry; + + if (gic_inited == 0) { + /* + * TODO: Call the Wakeup Late function to restore some + * HW configuration (e.g. TZASC) + */ + if (!get_core_pos()) + plat_primary_init_early(); + + main_init_gic(); + gic_inited = 1; + DMSG("=== Back from Suspended ===\n"); + } else { + main_secondary_init_gic(); + gic_inited = 0; + } + + imx_pen_unlock(cpu); + + return 0; +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/pm/gpcv2.c b/optee/optee_os/core/arch/arm/plat-imx/pm/gpcv2.c new file mode 100644 index 0000000..fa5bc36 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/pm/gpcv2.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 NXP + * + * Peng Fan + */ + +#include +#include +#include +#include +#include + +static vaddr_t gpc_base(void) +{ + return core_mmu_get_va(GPC_BASE, MEM_AREA_IO_SEC, 1); +} + +void imx_gpcv2_set_core_pgc(bool enable, uint32_t offset) +{ + uint32_t val = io_read32(gpc_base() + offset) & (~GPC_PGC_PCG_MASK); + + if (enable) + val |= GPC_PGC_PCG_MASK; + + io_write32(gpc_base() + offset, val); +} + +void imx_gpcv2_set_core1_pdn_by_software(void) +{ + uint32_t val = io_read32(gpc_base() + GPC_CPU_PGC_SW_PDN_REQ); + + imx_gpcv2_set_core_pgc(true, GPC_PGC_C1); + + val |= GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK; + + io_write32(gpc_base() + GPC_CPU_PGC_SW_PDN_REQ, val); + + while ((io_read32(gpc_base() + GPC_CPU_PGC_SW_PDN_REQ) & + GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK) != 0) + ; + + imx_gpcv2_set_core_pgc(false, GPC_PGC_C1); +} + +void imx_gpcv2_set_core1_pup_by_software(void) +{ + uint32_t val = io_read32(gpc_base() + GPC_CPU_PGC_SW_PUP_REQ); + + imx_gpcv2_set_core_pgc(true, GPC_PGC_C1); + + val |= GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK; + + io_write32(gpc_base() + GPC_CPU_PGC_SW_PUP_REQ, val); + + while ((io_read32(gpc_base() + GPC_CPU_PGC_SW_PUP_REQ) & + GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK) != 0) + ; + + imx_gpcv2_set_core_pgc(false, GPC_PGC_C1); +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/pm/imx7_suspend.c b/optee/optee_os/core/arch/arm/plat-imx/pm/imx7_suspend.c new file mode 100644 index 0000000..587164b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/pm/imx7_suspend.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 NXP + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int suspended_init; + +int imx7_cpu_suspend(uint32_t power_state __unused, uintptr_t entry, + uint32_t context_id __unused, struct sm_nsec_ctx *nsec) +{ + uint32_t suspend_ocram_base = core_mmu_get_va(TRUSTZONE_OCRAM_START + + SUSPEND_OCRAM_OFFSET, + MEM_AREA_TEE_COHERENT, + sizeof(struct + imx7_pm_info)); + + struct imx7_pm_info *p = (struct imx7_pm_info *)suspend_ocram_base; + int ret; + + if (!suspended_init) { + imx7_suspend_init(); + suspended_init = 1; + } + + sm_save_unbanked_regs(&nsec->ub_regs); + + ret = sm_pm_cpu_suspend((uint32_t)p, (int (*)(uint32_t)) + (suspend_ocram_base + sizeof(*p))); + /* + * Sometimes sm_pm_cpu_suspend may not really suspended, + * we need to check it's return value to restore reg or not + */ + if (ret < 0) { + DMSG("=== Not suspended, GPC IRQ Pending ===\n"); + return 0; + } + + if (!get_core_pos()) + plat_primary_init_early(); + + sm_restore_unbanked_regs(&nsec->ub_regs); + + /* Set entry for back to Linux */ + nsec->mon_lr = (uint32_t)entry; + + main_init_gic(); + + DMSG("=== Back from Suspended ===\n"); + + return 0; +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/pm/pm-imx7.c b/optee/optee_os/core/arch/arm/plat-imx/pm/pm-imx7.c new file mode 100644 index 0000000..3e52fb5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/pm/pm-imx7.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +paddr_t iram_tbl_phys_addr = -1UL; +void *iram_tbl_virt_addr; + +#define READ_DATA_FROM_HARDWARE 0 + +static uint32_t imx7d_ddrc_ddr3_setting[][2] = { + { 0x0, READ_DATA_FROM_HARDWARE }, + { 0x1a0, READ_DATA_FROM_HARDWARE }, + { 0x1a4, READ_DATA_FROM_HARDWARE }, + { 0x1a8, READ_DATA_FROM_HARDWARE }, + { 0x64, READ_DATA_FROM_HARDWARE }, + { 0x490, READ_DATA_FROM_HARDWARE }, + { 0xd0, READ_DATA_FROM_HARDWARE }, + { 0xd4, READ_DATA_FROM_HARDWARE }, + { 0xdc, READ_DATA_FROM_HARDWARE }, + { 0xe0, READ_DATA_FROM_HARDWARE }, + { 0xe4, READ_DATA_FROM_HARDWARE }, + { 0xf4, READ_DATA_FROM_HARDWARE }, + { 0x100, READ_DATA_FROM_HARDWARE }, + { 0x104, READ_DATA_FROM_HARDWARE }, + { 0x108, READ_DATA_FROM_HARDWARE }, + { 0x10c, READ_DATA_FROM_HARDWARE }, + { 0x110, READ_DATA_FROM_HARDWARE }, + { 0x114, READ_DATA_FROM_HARDWARE }, + { 0x120, READ_DATA_FROM_HARDWARE }, + { 0x180, READ_DATA_FROM_HARDWARE }, + { 0x190, READ_DATA_FROM_HARDWARE }, + { 0x194, READ_DATA_FROM_HARDWARE }, + { 0x200, READ_DATA_FROM_HARDWARE }, + { 0x204, READ_DATA_FROM_HARDWARE }, + { 0x214, READ_DATA_FROM_HARDWARE }, + { 0x218, READ_DATA_FROM_HARDWARE }, + { 0x240, READ_DATA_FROM_HARDWARE }, + { 0x244, READ_DATA_FROM_HARDWARE }, +}; + +static uint32_t imx7d_ddrc_phy_ddr3_setting[][2] = { + { 0x0, READ_DATA_FROM_HARDWARE }, + { 0x4, READ_DATA_FROM_HARDWARE }, + { 0x10, READ_DATA_FROM_HARDWARE }, + { 0xb0, READ_DATA_FROM_HARDWARE }, + { 0x9c, READ_DATA_FROM_HARDWARE }, + { 0x7c, READ_DATA_FROM_HARDWARE }, + { 0x80, READ_DATA_FROM_HARDWARE }, + { 0x84, READ_DATA_FROM_HARDWARE }, + { 0x88, READ_DATA_FROM_HARDWARE }, + { 0x6c, READ_DATA_FROM_HARDWARE }, + { 0x20, READ_DATA_FROM_HARDWARE }, + { 0x30, READ_DATA_FROM_HARDWARE }, + { 0x50, 0x01000010 }, + { 0x50, 0x00000010 }, + { 0xc0, 0x0e407304 }, + { 0xc0, 0x0e447304 }, + { 0xc0, 0x0e447306 }, + { 0xc0, 0x0e447304 }, + { 0xc0, 0x0e407306 }, +}; + +static struct imx7_pm_data imx7d_pm_data_ddr3 = { + .ddrc_num = ARRAY_SIZE(imx7d_ddrc_ddr3_setting), + .ddrc_offset = imx7d_ddrc_ddr3_setting, + .ddrc_phy_num = ARRAY_SIZE(imx7d_ddrc_phy_ddr3_setting), + .ddrc_phy_offset = imx7d_ddrc_phy_ddr3_setting, +}; + +paddr_t phys_addr[] = { + AIPS1_BASE, AIPS2_BASE, AIPS3_BASE +}; + +int pm_imx7_iram_tbl_init(void) +{ + uint32_t i; + struct tee_mmap_region map; + + /* iram mmu translation table already initialized */ + if (iram_tbl_phys_addr != (-1UL)) + return 0; + + iram_tbl_phys_addr = TRUSTZONE_OCRAM_START + 16 * 1024; + iram_tbl_virt_addr = phys_to_virt(iram_tbl_phys_addr, + MEM_AREA_TEE_COHERENT, + 16 * 1024); + + /* 16KB */ + memset(iram_tbl_virt_addr, 0, 16 * 1024); + + for (i = 0; i < ARRAY_SIZE(phys_addr); i++) { + map.pa = phys_addr[i]; + map.va = (vaddr_t)phys_to_virt(phys_addr[i], MEM_AREA_IO_SEC, + AIPS1_SIZE); + map.region_size = CORE_MMU_PGDIR_SIZE; + map.size = AIPS1_SIZE; /* 4M for AIPS1/2/3 */ + map.type = MEM_AREA_IO_SEC; + map.attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_PRW | + TEE_MATTR_SECURE | + (TEE_MATTR_MEM_TYPE_DEV << + TEE_MATTR_MEM_TYPE_SHIFT); + map_memarea_sections(&map, (uint32_t *)iram_tbl_virt_addr); + } + + /* Note IRAM_S_BASE is not 1M aligned, so take care */ + map.pa = ROUNDDOWN(IRAM_S_BASE, CORE_MMU_PGDIR_SIZE); + map.va = (vaddr_t)phys_to_virt(map.pa, MEM_AREA_TEE_COHERENT, + CORE_MMU_PGDIR_SIZE); + map.region_size = CORE_MMU_PGDIR_SIZE; + map.size = CORE_MMU_PGDIR_SIZE; + map.type = MEM_AREA_TEE_COHERENT; + map.attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_PRWX | TEE_MATTR_SECURE; + map_memarea_sections(&map, (uint32_t *)iram_tbl_virt_addr); + + map.pa = GIC_BASE; + map.va = (vaddr_t)phys_to_virt((paddr_t)GIC_BASE, MEM_AREA_IO_SEC, 1); + map.region_size = CORE_MMU_PGDIR_SIZE; + map.size = CORE_MMU_PGDIR_SIZE; + map.type = MEM_AREA_TEE_COHERENT; + map.attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_PRW | TEE_MATTR_SECURE; + map_memarea_sections(&map, (uint32_t *)iram_tbl_virt_addr); + + return 0; +} + +int imx7_suspend_init(void) +{ + uint32_t i; + uint32_t (*ddrc_offset_array)[2]; + uint32_t (*ddrc_phy_offset_array)[2]; + uint32_t suspend_ocram_base = + core_mmu_get_va(TRUSTZONE_OCRAM_START + SUSPEND_OCRAM_OFFSET, + MEM_AREA_TEE_COHERENT, + sizeof(struct imx7_pm_info)); + struct imx7_pm_info *p = (struct imx7_pm_info *)suspend_ocram_base; + struct imx7_pm_data *pm_data; + + pm_imx7_iram_tbl_init(); + + dcache_op_level1(DCACHE_OP_CLEAN_INV); + + p->pa_base = TRUSTZONE_OCRAM_START + SUSPEND_OCRAM_OFFSET; + p->tee_resume = virt_to_phys((void *)(vaddr_t)ca7_cpu_resume); + p->pm_info_size = sizeof(*p); + p->ccm_va_base = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, 1); + p->ccm_pa_base = CCM_BASE; + p->ddrc_va_base = core_mmu_get_va(DDRC_BASE, MEM_AREA_IO_SEC, 1); + p->ddrc_pa_base = DDRC_BASE; + p->ddrc_phy_va_base = core_mmu_get_va(DDRC_PHY_BASE, MEM_AREA_IO_SEC, + 1); + p->ddrc_phy_pa_base = DDRC_PHY_BASE; + p->src_va_base = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, 1); + p->src_pa_base = SRC_BASE; + p->iomuxc_gpr_va_base = core_mmu_get_va(IOMUXC_GPR_BASE, + MEM_AREA_IO_SEC, 1); + p->iomuxc_gpr_pa_base = IOMUXC_GPR_BASE; + p->gpc_va_base = core_mmu_get_va(GPC_BASE, MEM_AREA_IO_SEC, 1); + p->gpc_pa_base = GPC_BASE; + p->anatop_va_base = core_mmu_get_va(ANATOP_BASE, MEM_AREA_IO_SEC, 1); + p->anatop_pa_base = ANATOP_BASE; + p->snvs_va_base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 1); + p->snvs_pa_base = SNVS_BASE; + p->lpsr_va_base = core_mmu_get_va(LPSR_BASE, MEM_AREA_IO_SEC, 1); + p->lpsr_pa_base = LPSR_BASE; + p->gic_va_base = core_mmu_get_va(GIC_BASE, MEM_AREA_IO_SEC, 1); + p->gic_pa_base = GIC_BASE; + + /* TODO:lpsr disabled now */ + io_write32(p->lpsr_va_base, 0); + + p->ddr_type = imx_get_ddr_type(); + switch (p->ddr_type) { + case IMX_DDR_TYPE_DDR3: + pm_data = &imx7d_pm_data_ddr3; + break; + default: + panic("Not supported ddr type\n"); + break; + } + + p->ddrc_num = pm_data->ddrc_num; + p->ddrc_phy_num = pm_data->ddrc_phy_num; + ddrc_offset_array = pm_data->ddrc_offset; + ddrc_phy_offset_array = pm_data->ddrc_phy_offset; + + for (i = 0; i < p->ddrc_num; i++) { + p->ddrc_val[i][0] = ddrc_offset_array[i][0]; + if (ddrc_offset_array[i][1] == READ_DATA_FROM_HARDWARE) + p->ddrc_val[i][1] = io_read32(p->ddrc_va_base + + ddrc_offset_array[i][0]); + else + p->ddrc_val[i][1] = ddrc_offset_array[i][1]; + + if (p->ddrc_val[i][0] == 0xd0) + p->ddrc_val[i][1] |= 0xc0000000; + } + + /* initialize DDRC PHY settings */ + for (i = 0; i < p->ddrc_phy_num; i++) { + p->ddrc_phy_val[i][0] = ddrc_phy_offset_array[i][0]; + if (ddrc_phy_offset_array[i][1] == READ_DATA_FROM_HARDWARE) + p->ddrc_phy_val[i][1] = + io_read32(p->ddrc_phy_va_base + + ddrc_phy_offset_array[i][0]); + else + p->ddrc_phy_val[i][1] = ddrc_phy_offset_array[i][1]; + } + + memcpy((void *)(suspend_ocram_base + sizeof(*p)), + (void *)(vaddr_t)imx7_suspend, SUSPEND_OCRAM_SIZE - sizeof(*p)); + + dcache_clean_range((void *)suspend_ocram_base, SUSPEND_OCRAM_SIZE); + + /* + * Note that IRAM IOSEC map, if changed to MEM map, + * need to flush cache + */ + icache_inv_all(); + + return 0; +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/pm/psci-cpuidle-imx7.S b/optee/optee_os/core/arch/arm/plat-imx/pm/psci-cpuidle-imx7.S new file mode 100644 index 0000000..6894be3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/pm/psci-cpuidle-imx7.S @@ -0,0 +1,765 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MX7_SRC_GPR1 0x74 +#define MX7_SRC_GPR2 0x78 +#define MX7_SRC_GPR3 0x7c +#define MX7_SRC_GPR4 0x80 +#define MX7_GPC_IMR1 0x30 +#define MX7_GPC_IMR2 0x34 +#define MX7_GPC_IMR3 0x38 +#define MX7_GPC_IMR4 0x3c +#define DDRC_STAT 0x4 +#define DDRC_PWRCTL 0x30 +#define DDRC_DBG1 0x304 +#define DDRC_DBGCAM 0x308 +#define DDRC_PSTAT 0x3fc +#define DDRC_PCTRL_0 0x490 + + .section .text.psci.cpuidle + .align 3 +/* + * imx_pen_lock + * + * The reference link of Peterson's algorithm: + * http://en.wikipedia.org/wiki/Peterson's_algorithm + * + * val1 = r1 = !turn (inverted from Peterson's algorithm) + * on cpu 0: + * r2 = flag[0] (in flag0) + * r3 = flag[1] (in flag1) + * on cpu1: + * r2 = flag[1] (in flag1) + * r3 = flag[0] (in flag0) + * + */ + .macro imx_pen_lock + + mov r8, r0 + read_mpidr r5 + and r5, r5, #3 + add r6, r8, #PM_INFO_MX7_VAL_OFF + cmp r5, #0 + addeq r7, r8, #PM_INFO_MX7_FLAG0_OFF + addeq r8, r8, #PM_INFO_MX7_FLAG1_OFF + addne r7, r8, #PM_INFO_MX7_FLAG1_OFF + addne r8, r8, #PM_INFO_MX7_FLAG0_OFF + + mov r9, #1 + str r9, [r7] + dsb + str r5, [r6] +1: + dsb + ldr r9, [r8] + cmp r9, #1 + ldreq r9, [r6] + cmpeq r9, r5 + beq 1b + + .endm + + .macro imx_pen_unlock + + dsb + read_mpidr r6 + and r6, r6, #3 + cmp r6, #0 + addeq r7, r0, #PM_INFO_MX7_FLAG0_OFF + addne r7, r0, #PM_INFO_MX7_FLAG1_OFF + mov r9, #0 + str r9, [r7] + + .endm + + .macro disable_l1_dcache + + push {r0 - r12, lr} + mov r0, #DCACHE_OP_CLEAN_INV + ldr r1, =dcache_op_all + blx r1 + pop {r0 - r12, lr} + + /* disable d-cache */ + read_sctlr r7 + bic r7, r7, #SCTLR_C + write_sctlr r7 + dsb + isb + + push {r0 - r12, lr} + mov r0, #DCACHE_OP_CLEAN_INV + ldr r1, =dcache_op_all + blx r1 + pop {r0 - r12, lr} + + /* TODO: handle non-SMP kernel */ + clrex + + /* Turn off SMP bit. */ + read_actlr r8 + bic r8, r8, #ACTLR_SMP + write_actlr r8 + isb + dsb + + .endm + + .macro tlb_set_to_ocram + + /* save ttbr */ + read_ttbr1 r7 + str r7, [r0, #PM_INFO_MX7_TTBR1_OFF] + + read_ttbr0 r7 + str r7, [r0, #PM_INFO_MX7_TTBR0_OFF] + + /* + * To ensure no page table walks occur in DDR, we + * have a another page table stored in IRAM that only + * contains entries pointing to IRAM, AIPS1 and AIPS2. + * We need to set the TTBR1 to the new IRAM TLB. + * Do the following steps: + * 1. Flush the Branch Target Address Cache (BTAC) + * 2. Set TTBR1 to point to IRAM page table. + * 3. Disable page table walks in TTBR0 (PD0 = 1) + */ + + /* Disable Branch Prediction, Z bit in SCTLR. */ + read_sctlr r6 + bic r6, r6, #SCTLR_Z + write_sctlr r6 + + /* Flush the BTAC. */ + write_bpiallis + + ldr r6, =iram_tbl_phys_addr + ldr r7, [r6] + + dsb + isb + + /* Store the IRAM table in TTBR1/TTBR0 */ + write_ttbr1 r7 + write_ttbr0 r7 + + /* Read TTBCR and set PD0=1 */ + read_ttbcr r6 + orr r6, r6, #TTBCR_PD0 + write_ttbcr r6 + + dsb + isb + + /* flush the TLB */ + write_tlbiallis + isb + + .endm + + .macro tlb_back_to_ddr + + /* Read TTBCR and set PD0=0 */ + read_ttbcr r6 + bic r6, r6, #TTBCR_PD0 + write_ttbcr r6 + + dsb + isb + + /* flush the TLB */ + write_tlbiallis + + /* Enable Branch Prediction, Z bit in SCTLR. */ + read_sctlr r6 + orr r6, r6, #SCTLR_Z + write_sctlr r6 + + /* Flush the Branch Target Address Cache (BTAC) */ + write_bpiallis + + /* restore ttbr */ + ldr r7, [r0, #PM_INFO_MX7_TTBR1_OFF] + write_ttbr1 r7 + ldr r7, [r0, #PM_INFO_MX7_TTBR0_OFF] + write_ttbr0 r7 + + .endm + + /* r10 must be DDRC base address */ + .macro ddrc_enter_self_refresh + + ldr r10, [r0, #PM_INFO_MX7_DDRC_V_OFF] + + /* disable port */ + ldr r7, =0x0 + str r7, [r10, #DDRC_PCTRL_0] + + /* let DDR out of self-refresh */ + ldr r7, =0x0 + str r7, [r10, #DDRC_PWRCTL] + + /* wait rw port_busy clear */ + ldr r6, =(0x1 << 16) + orr r6, r6, #0x1 +2: + ldr r7, [r10, #DDRC_PSTAT] + ands r7, r7, r6 + bne 2b + + ldr r7, =0x1 + str r7, [r10, #DDRC_DBG1] + + ldr r6, =0x36000000 +11: + ldr r7, [r10, #DDRC_DBGCAM] + and r7, r7, r6 + cmp r7, r6 + bne 11b + + /* enter self-refresh bit 5 */ + ldr r7, =(0x1 << 5) + str r7, [r10, #DDRC_PWRCTL] + + /* wait until self-refresh mode entered */ +3: + ldr r7, [r10, #DDRC_STAT] + and r7, r7, #0x3 + cmp r7, #0x3 + bne 3b +4: + ldr r7, [r10, #DDRC_STAT] + ands r7, r7, #0x20 + beq 4b + + /* disable dram clk */ + ldr r7, [r10, #DDRC_PWRCTL] + orr r7, r7, #(1 << 3) + str r7, [r10, #DDRC_PWRCTL] + + /* + * TO1.1 adds feature of DDR pads power down, + * although TO1.0 has no such function, but it is + * NOT harmful to program GPR registers for TO1.0, + * it can avoid the logic of version check in idle + * thread. + */ + ldr r10, [r0, #PM_INFO_MX7_IOMUXC_GPR_V_OFF] + ldr r7, =0xf0000 + str r7, [r10] + + /* delay 20us, measured by gpio */ + ldr r7, =20 +12: + subs r7, r7, #0x1 + bne 12b + + .endm + + /* r10 must be DDRC base address */ + .macro ddrc_exit_self_refresh + + cmp r5, #0x1 + ldreq r10, [r0, #PM_INFO_MX7_IOMUXC_GPR_P_OFF] + ldrne r10, [r0, #PM_INFO_MX7_IOMUXC_GPR_V_OFF] + + ldr r7, =0x0 + str r7, [r10] + + ldr r7, =20 +13: + subs r7, r7, #0x1 + bne 13b + + cmp r5, #0x1 + ldreq r10, [r0, #PM_INFO_MX7_DDRC_P_OFF] + ldrne r10, [r0, #PM_INFO_MX7_DDRC_V_OFF] + + ldr r7, =0x0 + str r7, [r10, #DDRC_DBG1] + + ldr r6, =0x30000000 +14: + ldr r7, [r10, #DDRC_DBGCAM] + and r7, r7, r6 + cmp r7, r6 + bne 14b + + /* let DDR out of self-refresh */ + ldr r7, =0x0 + str r7, [r10, #DDRC_PWRCTL] + + /* wait until self-refresh mode exited */ +5: + ldr r7, [r10, #DDRC_STAT] + and r7, r7, #0x3 + cmp r7, #0x3 + beq 5b + + /* enable auto self-refresh */ + ldr r7, [r10, #DDRC_PWRCTL] + orr r7, r7, #(1 << 0) + str r7, [r10, #DDRC_PWRCTL] + + ldr r7, =0x1 + str r7, [r10, #DDRC_PCTRL_0] + + .endm + + .macro pll_do_wait_lock +6: + ldr r7, [r10, r8] + ands r7, #0x80000000 + beq 6b + + .endm + + .macro ccm_enter_idle + + ldr r10, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + + /* ungate pfd1 332m for lower axi */ + ldr r7, =0x8000 + str r7, [r10, #0xc8] + + ldr r10, [r0, #PM_INFO_MX7_CCM_V_OFF] + + /* switch ARM CLK to OSC */ + ldr r8, =0x8000 + ldr r7, [r10, r8] + bic r7, r7, #0x7000000 + str r7, [r10, r8] + + /* lower AXI clk from 24MHz to 3MHz */ + ldr r8, =0x8800 + ldr r7, [r10, r8] + orr r7, r7, #0x7 + str r7, [r10, r8] + + /* lower AHB clk from 24MHz to 3MHz */ + ldr r8, =0x9000 + ldr r7, [r10, r8] + orr r7, r7, #0x7 + str r7, [r10, r8] + + /* gate dram clk */ + ldr r8, =0x9880 + ldr r7, [r10, r8] + bic r7, r7, #0x10000000 + str r7, [r10, r8] + + ldr r10, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + + /* gate pfd1 332m */ + ldr r7, =0x8000 + str r7, [r10, #0xc4] + + /* gate system pll pfd div 1 */ + ldr r7, =0x10 + str r7, [r10, #0xb4] + /* power down ARM, 480 and DRAM PLL */ + ldr r7, =0x1000 + str r7, [r10, #0x64] + str r7, [r10, #0xb4] + ldr r7, =0x100000 + str r7, [r10, #0x74] + + .endm + + .macro ccm_exit_idle + + cmp r5, #0x1 + ldreq r10, [r0, #PM_INFO_MX7_ANATOP_P_OFF] + ldrne r10, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + + /* power up ARM, 480 and DRAM PLL */ + ldr r7, =0x1000 + str r7, [r10, #0x68] + ldr r8, =0x60 + pll_do_wait_lock + + ldr r7, =0x1000 + str r7, [r10, #0xb8] + ldr r8, =0xb0 + pll_do_wait_lock + + ldr r7, =0x100000 + str r7, [r10, #0x78] + ldr r8, =0x70 + pll_do_wait_lock + + /* ungate pfd1 332m for lower axi */ + ldr r7, =0x8000 + str r7, [r10, #0xc8] + + /* ungate system pll pfd div 1 */ + ldr r7, =0x10 + str r7, [r10, #0xb8] + + cmp r5, #0x1 + ldreq r10, [r0, #PM_INFO_MX7_CCM_P_OFF] + ldrne r10, [r0, #PM_INFO_MX7_CCM_V_OFF] + + /* switch ARM CLK to PLL */ + ldr r8, =0x8000 + ldr r7, [r10, r8] + orr r7, r7, #0x1000000 + str r7, [r10, r8] + + /* restore AXI clk from 3MHz to 24MHz */ + ldr r8, =0x8800 + ldr r7, [r10, r8] + bic r7, r7, #0x7 + str r7, [r10, r8] + + /* restore AHB clk from 3MHz to 24MHz */ + ldr r8, =0x9000 + ldr r7, [r10, r8] + bic r7, r7, #0x7 + str r7, [r10, r8] + + /* ungate dram clk */ + ldr r8, =0x9880 + ldr r7, [r10, r8] + orr r7, r7, #0x10000000 + str r7, [r10, r8] + + cmp r5, #0x1 + ldreq r10, [r0, #PM_INFO_MX7_ANATOP_P_OFF] + ldrne r10, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + + /* gate pfd1 332m for lower axi */ + ldr r7, =0x8000 + str r7, [r10, #0xc4] + + .endm + + .macro anatop_enter_idle + + ldr r10, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + + /* XTAL to RC-OSC switch */ + ldr r7, [r10] + orr r7, r7, #0x1000 + str r7, [r10] + /* power down XTAL */ + ldr r7, [r10] + orr r7, r7, #0x1 + str r7, [r10] + + /* enable weak 1P0A */ + ldr r7, [r10, #0x200] + orr r7, r7, #0x40000 + str r7, [r10, #0x200] + + /* disable LDO 1P0A */ + ldr r7, [r10, #0x200] + bic r7, r7, #0x1 + str r7, [r10, #0x200] + + /* disable LDO 1P0D */ + ldr r7, [r10, #0x210] + bic r7, r7, #0x1 + str r7, [r10, #0x210] + + /* disable LDO 1P2 */ + ldr r7, [r10, #0x220] + bic r7, r7, #0x1 + str r7, [r10, #0x220] + + /* switch to low power bandgap */ + ldr r7, [r10, #0x270] + orr r7, r7, #0x400 + str r7, [r10, #0x270] + /* power down normal bandgap */ + orr r7, r7, #0x1 + str r7, [r10, #0x270] + + .endm + + .macro anatop_exit_idle + + cmp r5, #0x1 + ldreq r10, [r0, #PM_INFO_MX7_ANATOP_P_OFF] + ldrne r10, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + + /* power on normal bandgap */ + ldr r7, [r10, #0x270] + bic r7, r7, #0x1 + str r7, [r10, #0x270] + /* switch to normal bandgap */ + bic r7, r7, #0x400 + str r7, [r10, #0x270] + + /* enable LDO 1P2 */ + ldr r7, [r10, #0x220] + orr r7, r7, #0x1 + str r7, [r10, #0x220] +7: + ldr r7, [r10, #0x220] + ands r7, #0x20000 + beq 7b + + /* enable LDO 1P0D */ + ldr r7, [r10, #0x210] + orr r7, r7, #0x1 + str r7, [r10, #0x210] +8: + ldr r7, [r10, #0x210] + ands r7, #0x20000 + beq 8b + + /* enable LDO 1P0A */ + ldr r7, [r10, #0x200] + orr r7, r7, #0x1 + str r7, [r10, #0x200] +9: + ldr r7, [r10, #0x200] + ands r7, #0x20000 + beq 9b + /* disable weak 1P0A */ + ldr r7, [r10, #0x200] + bic r7, r7, #0x40000 + str r7, [r10, #0x200] + + /* power up XTAL and wait */ + ldr r7, [r10] + bic r7, r7, #0x1 + str r7, [r10] +10: + ldr r7, [r10] + ands r7, r7, #0x4 + beq 10b + /* RC-OSC to XTAL switch */ + ldr r7, [r10] + bic r7, r7, #0x1000 + str r7, [r10] + + .endm + +.extern iram_tlb_phys_addr + +FUNC imx7d_low_power_idle, : + push {r0 - r12} + + /* get necessary info from pm_info */ + ldr r1, [r0, #PM_INFO_MX7_PBASE_OFF] + ldr r2, [r0, #PM_INFO_MX7_SIZE_OFF] + + /* + * counting the resume address in iram + * to set it in SRC register. + */ + ldr r5, =imx7d_low_power_idle + ldr r6, =wakeup + sub r6, r6, r5 + add r8, r1, r2 + add r3, r8, r6 + + /* r11 is cpu id */ + read_mpidr r11 + and r11, r11, #3 + cmp r11, #0x0 + ldreq r6, =MX7_SRC_GPR1 + ldreq r7, =MX7_SRC_GPR2 + ldrne r6, =MX7_SRC_GPR3 + ldrne r7, =MX7_SRC_GPR4 + /* store physical resume addr and pm_info address. */ + ldr r10, [r0, #PM_INFO_MX7_SRC_V_OFF] + str r3, [r10, r6] + str r1, [r10, r7] + + disable_l1_dcache + + tlb_set_to_ocram + + /* check last to sleep */ + ldr r6, [r0, #PM_INFO_MX7_NUM_ONLINE_CPUS_OFF] + ldr r7, [r0, #PM_INFO_MX7_NUM_LPI_CPUS_OFF] + cmp r6, r7 + bne lpi_enter_done + + ddrc_enter_self_refresh + ccm_enter_idle + anatop_enter_idle + + ldr r10, [r0, #PM_INFO_MX7_GIC_DIST_V_OFF] + ldr r7, =0x0 + ldr r8, =0x1000 + str r7, [r10, r8] + + ldr r10, [r0, #PM_INFO_MX7_GPC_V_OFF] + ldr r4, [r10, #MX7_GPC_IMR1] + ldr r5, [r10, #MX7_GPC_IMR2] + ldr r6, [r10, #MX7_GPC_IMR3] + ldr r7, [r10, #MX7_GPC_IMR4] + + ldr r8, =0xffffffff + str r8, [r10, #MX7_GPC_IMR1] + str r8, [r10, #MX7_GPC_IMR2] + str r8, [r10, #MX7_GPC_IMR3] + str r8, [r10, #MX7_GPC_IMR4] + + /* + * enable the RBC bypass counter here + * to hold off the interrupts. RBC counter + * = 8 (240us). With this setting, the latency + * from wakeup interrupt to ARM power up + * is ~250uS. + */ + ldr r8, [r10, #0x14] + bic r8, r8, #(0x3f << 24) + orr r8, r8, #(0x8 << 24) + str r8, [r10, #0x14] + + /* enable the counter. */ + ldr r8, [r10, #0x14] + orr r8, r8, #(0x1 << 30) + str r8, [r10, #0x14] + + /* unmask all the GPC interrupts. */ + str r4, [r10, #MX7_GPC_IMR1] + str r5, [r10, #MX7_GPC_IMR2] + str r6, [r10, #MX7_GPC_IMR3] + str r7, [r10, #MX7_GPC_IMR4] + + /* + * now delay for a short while (30usec) + * ARM is at 24MHz at this point + * so a short loop should be enough. + * this delay is required to ensure that + * the RBC counter can start counting in + * case an interrupt is already pending + * or in case an interrupt arrives just + * as ARM is about to assert DSM_request. + */ + ldr r4, =5 +rbc_loop: + subs r4, r4, #0x1 + bne rbc_loop + +lpi_enter_done: + imx_pen_unlock + + wfi + isb + + imx_pen_lock + + /* check first to wake */ + ldr r6, [r0, #PM_INFO_MX7_NUM_ONLINE_CPUS_OFF] + ldr r7, [r0, #PM_INFO_MX7_NUM_LPI_CPUS_OFF] + cmp r6, r7 + bne skip_lpi_flow + + ldr r5, =0x0 + anatop_exit_idle + ccm_exit_idle + ddrc_exit_self_refresh + + ldr r10, [r0, #PM_INFO_MX7_GIC_DIST_V_OFF] + ldr r7, =0x3 + ldr r8, =0x1000 + str r7, [r10, r8] +skip_lpi_flow: + + tlb_back_to_ddr + + /* TODO: handle non-SMP kernel */ + /* Turn on SMP bit. */ + read_actlr r7 + orr r7, r7, #ACTLR_SMP + write_actlr r7 + + isb + + /* enable d-cache */ + read_sctlr r7 + orr r7, r7, #SCTLR_C + write_sctlr r7 + dsb + isb + + /* Restore registers */ + pop {r0 - r12} + bx lr + +wakeup: + /* invalidate L1 I-cache first */ + write_iciallu + write_bpiall + /* enable the Icache and branch prediction */ + mov r1, #(SCTLR_I | SCTLR_Z) + write_sctlr r1 + isb + + /* switch monitor mode */ + cps #CPSR_MODE_MON + + imx_pen_lock + /* check first to wake */ + ldr r6, [r0, #PM_INFO_MX7_NUM_ONLINE_CPUS_OFF] + ldr r7, [r0, #PM_INFO_MX7_NUM_LPI_CPUS_OFF] + cmp r6, r7 + bne wakeup_skip_lpi_flow + + ldr r5, =0x1 + anatop_exit_idle + ccm_exit_idle + ddrc_exit_self_refresh +wakeup_skip_lpi_flow: + + /* get physical resume address from pm_info. */ + ldr lr, [r0, #PM_INFO_MX7_RESUME_ADDR_OFF] + + /* Restore registers */ + bx lr +END_FUNC imx7d_low_power_idle + +/* + * Note: OPTEE VA = PA, for TEE_RAM. + * This maybe changed in future. + */ +FUNC v7_cpu_resume, : + mov r0, #0 @ ; write the cache size selection register to be + write_csselr r0 @ ; 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 + write_dcisw r2 @ ; 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 @ ; overflow out of set field + bne _inv_nextline + add r0, r0, #1 << WAY_FIELD_OFFSET @ ; increment the way number + cmp r0, #0 @ ; overflow out of way field + bne _inv_nextway + + dsb @ ; synchronise + + /* + * no stack, scratch r0-r3 + * TODO: need to use specific configure, but not plat_xxx. + * because plat_xx maybe changed in future, we can not rely on it. + * need handle sp carefully. + */ + blx plat_cpu_reset_early + + b sm_pm_cpu_resume +END_FUNC v7_cpu_resume diff --git a/optee/optee_os/core/arch/arm/plat-imx/pm/psci-suspend-imx7.S b/optee/optee_os/core/arch/arm/plat-imx/pm/psci-suspend-imx7.S new file mode 100644 index 0000000..0691012 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/pm/psci-suspend-imx7.S @@ -0,0 +1,692 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MX7_SRC_GPR1 0x74 +#define MX7_SRC_GPR2 0x78 +#define GPC_PGC_C0 0x800 +#define GPC_PGC_FM 0xa00 +#define ANADIG_SNVS_MISC_CTRL 0x380 +#define ANADIG_SNVS_MISC_CTRL_SET 0x384 +#define ANADIG_SNVS_MISC_CTRL_CLR 0x388 +#define ANADIG_DIGPROG 0x800 +#define DDRC_STAT 0x4 +#define DDRC_PWRCTL 0x30 +#define DDRC_PSTAT 0x3fc +#define DDRC_PCTRL_0 0x490 +#define DDRC_DFIMISC 0x1b0 +#define DDRC_SWCTL 0x320 +#define DDRC_SWSTAT 0x324 +#define DDRPHY_LP_CON0 0x18 + +#define CCM_SNVS_LPCG 0x250 +#define MX7D_GPC_IMR1 0x30 +#define MX7D_GPC_IMR2 0x34 +#define MX7D_GPC_IMR3 0x38 +#define MX7D_GPC_IMR4 0x3c + +/* + * The code in this file is copied to coherent on-chip ram memory, + * without any dependency on code/data in tee memory(DDR). + */ + .section .text.psci.suspend + .align 3 + + .macro disable_l1_dcache + + /* + * flush L1 data cache before clearing SCTLR.C bit. + */ + push {r0 - r10, lr} + ldr r1, =dcache_op_all + mov r0, #DCACHE_OP_CLEAN_INV + mov lr, pc + bx r1 + pop {r0 - r10, lr} + + /* disable d-cache */ + read_sctlr r7 + bic r7, r7, #SCTLR_C + write_sctlr r7 + dsb + isb + + push {r0 - r10, lr} + ldr r1, =dcache_op_all + mov r0, #DCACHE_OP_CLEAN_INV + mov lr, pc + bx r1 + pop {r0 - r10, lr} + + .endm + + .macro store_ttbr + + /* Store TTBR1 to pm_info->ttbr1 */ + read_ttbr1 r7 + str r7, [r0, #PM_INFO_MX7_TTBR1_OFF] + + /* Store TTBR0 to pm_info->ttbr1 */ + read_ttbr0 r7 + str r7, [r0, #PM_INFO_MX7_TTBR0_OFF] + + /* Disable Branch Prediction */ + read_sctlr r6 + bic r6, r6, #SCTLR_Z + write_sctlr r6 + + /* Flush the BTAC. */ + write_bpiallis + + ldr r6, =iram_tbl_phys_addr + ldr r6, [r6] + dsb + isb + + /* Store the IRAM table in TTBR1/0 */ + write_ttbr1 r6 + write_ttbr0 r6 + + /* Read TTBCR and set PD0=1 */ + read_ttbcr r6 + orr r6, r6, #TTBCR_PD0 + write_ttbcr r6 + + dsb + isb + + /* flush the TLB */ + write_tlbiallis + isb + write_tlbiall + isb + + .endm + + .macro restore_ttbr + + /* Enable L1 data cache. */ + read_sctlr r6 + orr r6, r6, #SCTLR_C + write_sctlr r6 + + dsb + isb + + /* Restore TTBCR */ + /* Read TTBCR and set PD0=0 */ + read_ttbcr r6 + bic r6, r6, #TTBCR_PD0 + write_ttbcr r6 + dsb + isb + + /* flush the TLB */ + write_tlbiallis + + /* Enable Branch Prediction */ + read_sctlr r6 + orr r6, r6, #SCTLR_Z + write_sctlr r6 + + /* Flush the Branch Target Address Cache (BTAC) */ + write_bpiallis + + /* Restore TTBR1/0, get the origin ttbr1/0 from pm info */ + ldr r7, [r0, #PM_INFO_MX7_TTBR1_OFF] + write_ttbr1 r7 + ldr r7, [r0, #PM_INFO_MX7_TTBR0_OFF] + write_ttbr0 r7 + isb + + .endm + + .macro ddrc_enter_self_refresh + + ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFF] + + /* let DDR out of self-refresh */ + ldr r7, =0x0 + str r7, [r11, #DDRC_PWRCTL] + + /* wait rw port_busy clear */ + ldr r6, =BIT32(16) + orr r6, r6, #0x1 +1: + ldr r7, [r11, #DDRC_PSTAT] + ands r7, r7, r6 + bne 1b + + /* enter self-refresh bit 5 */ + ldr r7, =BIT32(5) + str r7, [r11, #DDRC_PWRCTL] + + /* wait until self-refresh mode entered */ +2: + ldr r7, [r11, #DDRC_STAT] + and r7, r7, #0x3 + cmp r7, #0x3 + bne 2b +3: + ldr r7, [r11, #DDRC_STAT] + ands r7, r7, #0x20 + beq 3b + + /* disable dram clk */ + ldr r7, [r11, #DDRC_PWRCTL] + orr r7, r7, #BIT32(3) + str r7, [r11, #DDRC_PWRCTL] + + .endm + + .macro ddrc_exit_self_refresh + + cmp r5, #0x0 + ldreq r11, [r0, #PM_INFO_MX7_DDRC_V_OFF] + ldrne r11, [r0, #PM_INFO_MX7_DDRC_P_OFF] + + /* let DDR out of self-refresh */ + ldr r7, =0x0 + str r7, [r11, #DDRC_PWRCTL] + + /* wait until self-refresh mode entered */ +4: + ldr r7, [r11, #DDRC_STAT] + and r7, r7, #0x3 + cmp r7, #0x3 + beq 4b + + /* enable auto self-refresh */ + ldr r7, [r11, #DDRC_PWRCTL] + orr r7, r7, #BIT32(0) + str r7, [r11, #DDRC_PWRCTL] + + .endm + + .macro wait_delay +5: + subs r6, r6, #0x1 + bne 5b + + .endm + + .macro ddr_enter_retention + + ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFF] + + /* let DDR out of self-refresh */ + ldr r7, =0x0 + str r7, [r11, #DDRC_PCTRL_0] + + /* wait rw port_busy clear */ + ldr r6, =BIT32(16) + orr r6, r6, #0x1 +6: + ldr r7, [r11, #DDRC_PSTAT] + ands r7, r7, r6 + bne 6b + + ldr r11, [r0, #PM_INFO_MX7_DDRC_V_OFF] + /* enter self-refresh bit 5 */ + ldr r7, =BIT32(5) + str r7, [r11, #DDRC_PWRCTL] + + /* wait until self-refresh mode entered */ +7: + ldr r7, [r11, #DDRC_STAT] + and r7, r7, #0x3 + cmp r7, #0x3 + bne 7b +8: + ldr r7, [r11, #DDRC_STAT] + ands r7, r7, #0x20 + beq 8b + + /* disable dram clk */ + ldr r7, =BIT32(5) + orr r7, r7, #BIT32(3) + str r7, [r11, #DDRC_PWRCTL] + + ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + ldr r7, [r11, #ANADIG_DIGPROG] + and r7, r7, #0xff + cmp r7, #0x11 + bne 10f + + /* TO 1.1 */ + ldr r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_V_OFF] + ldr r7, =0x38000000 + str r7, [r11] + + /* LPSR mode need to use TO1.0 flow as IOMUX lost power */ + ldr r10, [r0, #PM_INFO_MX7_LPSR_V_OFF] + ldr r7, [r10] + cmp r7, #0x0 + beq 11f +10: + /* reset ddr_phy */ + ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + ldr r7, =0x0 + str r7, [r11, #ANADIG_SNVS_MISC_CTRL] + + /* delay 7 us */ + ldr r6, =6000 + wait_delay + + ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFF] + ldr r6, =0x1000 + ldr r7, [r11, r6] + orr r7, r7, #0x1 + str r7, [r11, r6] +11: + /* turn off ddr power */ + ldr r11, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + ldr r7, =(0x1 << 29) + str r7, [r11, #ANADIG_SNVS_MISC_CTRL_SET] + + ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFF] + ldr r6, =0x1000 + ldr r7, [r11, r6] + orr r7, r7, #0x1 + str r7, [r11, r6] + + .endm + + .macro ddr_exit_retention + + cmp r5, #0x0 + ldreq r1, [r0, #PM_INFO_MX7_ANATOP_V_OFF] + ldrne r1, [r0, #PM_INFO_MX7_ANATOP_P_OFF] + ldreq r2, [r0, #PM_INFO_MX7_SRC_V_OFF] + ldrne r2, [r0, #PM_INFO_MX7_SRC_P_OFF] + ldreq r3, [r0, #PM_INFO_MX7_DDRC_V_OFF] + ldrne r3, [r0, #PM_INFO_MX7_DDRC_P_OFF] + ldreq r4, [r0, #PM_INFO_MX7_DDRC_PHY_V_OFF] + ldrne r4, [r0, #PM_INFO_MX7_DDRC_PHY_P_OFF] + ldreq r10, [r0, #PM_INFO_MX7_CCM_V_OFF] + ldrne r10, [r0, #PM_INFO_MX7_CCM_P_OFF] + ldreq r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_V_OFF] + ldrne r11, [r0, #PM_INFO_MX7_IOMUXC_GPR_P_OFF] + + /* turn on ddr power */ + ldr r7, =BIT32(29) + str r7, [r1, #ANADIG_SNVS_MISC_CTRL_CLR] + + ldr r6, =50 + wait_delay + + /* clear ddr_phy reset */ + ldr r6, =0x1000 + ldr r7, [r2, r6] + orr r7, r7, #0x3 + str r7, [r2, r6] + ldr r7, [r2, r6] + bic r7, r7, #0x1 + str r7, [r2, r6] +13: + ldr r6, [r0, #PM_INFO_MX7_DDRC_REG_NUM_OFF] + ldr r7, =PM_INFO_MX7_DDRC_REG_OFF + add r7, r7, r0 +14: + ldr r8, [r7], #0x4 + ldr r9, [r7], #0x4 + str r9, [r3, r8] + subs r6, r6, #0x1 + bne 14b + ldr r7, =0x20 + str r7, [r3, #DDRC_PWRCTL] + ldr r7, =0x0 + str r7, [r3, #DDRC_DFIMISC] + + /* do PHY, clear ddr_phy reset */ + ldr r6, =0x1000 + ldr r7, [r2, r6] + bic r7, r7, #0x2 + str r7, [r2, r6] + + ldr r7, [r1, #ANADIG_DIGPROG] + and r7, r7, #0xff + cmp r7, #0x11 + bne 12f + + /* + * TKT262940: + * System hang when press RST for DDR PAD is + * in retention mode, fixed on TO1.1 + */ + ldr r7, [r11] + bic r7, r7, #BIT32(27) + str r7, [r11] + ldr r7, [r11] + bic r7, r7, #BIT32(29) + str r7, [r11] +12: + ldr r7, =BIT32(30) + str r7, [r1, #ANADIG_SNVS_MISC_CTRL_SET] + + /* need to delay ~5mS */ + ldr r6, =0x100000 + wait_delay + + ldr r6, [r0, #PM_INFO_MX7_DDRC_PHY_REG_NUM_OFF] + ldr r7, =PM_INFO_MX7_DDRC_PHY_REG_OFF + add r7, r7, r0 + +15: + ldr r8, [r7], #0x4 + ldr r9, [r7], #0x4 + str r9, [r4, r8] + subs r6, r6, #0x1 + bne 15b + + ldr r7, =0x0 + add r9, r10, #0x4000 + str r7, [r9, #0x130] + + ldr r7, =0x170 + orr r7, r7, #0x8 + str r7, [r11, #0x20] + + ldr r7, =0x2 + add r9, r10, #0x4000 + str r7, [r9, #0x130] + + ldr r7, =0xf + str r7, [r4, #DDRPHY_LP_CON0] + + /* wait until self-refresh mode entered */ +16: + ldr r7, [r3, #DDRC_STAT] + and r7, r7, #0x3 + cmp r7, #0x3 + bne 16b + ldr r7, =0x0 + str r7, [r3, #DDRC_SWCTL] + ldr r7, =0x1 + str r7, [r3, #DDRC_DFIMISC] + ldr r7, =0x1 + str r7, [r3, #DDRC_SWCTL] +17: + ldr r7, [r3, #DDRC_SWSTAT] + and r7, r7, #0x1 + cmp r7, #0x1 + bne 17b +18: + ldr r7, [r3, #DDRC_STAT] + and r7, r7, #0x20 + cmp r7, #0x20 + bne 18b + + /* let DDR out of self-refresh */ + ldr r7, =0x0 + str r7, [r3, #DDRC_PWRCTL] +19: + ldr r7, [r3, #DDRC_STAT] + and r7, r7, #0x30 + cmp r7, #0x0 + bne 19b + +20: + ldr r7, [r3, #DDRC_STAT] + and r7, r7, #0x3 + cmp r7, #0x1 + bne 20b + + /* enable port */ + ldr r7, =0x1 + str r7, [r3, #DDRC_PCTRL_0] + + /* enable auto self-refresh */ + ldr r7, [r3, #DDRC_PWRCTL] + orr r7, r7, #(1 << 0) + str r7, [r3, #DDRC_PWRCTL] + + .endm + +FUNC imx7_suspend, : +UNWIND( .cantunwind) + push {r4-r12} + + /* make sure SNVS clk is enabled */ + ldr r11, [r0, #PM_INFO_MX7_CCM_V_OFF] + add r11, r11, #0x4000 + ldr r7, =0x3 + str r7, [r11, #CCM_SNVS_LPCG] + + /* check whether it is a standby mode */ + ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] + ldr r7, [r11, #GPC_PGC_C0] + cmp r7, #0 + beq ddr_only_self_refresh + + /* + * The value of r0 is mapped the same in origin table and IRAM table, + * thus no need to care r0 here. + */ + ldr r1, [r0, #PM_INFO_MX7_PBASE_OFF] + ldr r4, [r0, #PM_INFO_MX7_SIZE_OFF] + + /* + * counting the resume address in iram + * to set it in SRC register. + */ + ldr r6, =imx7_suspend + ldr r7, =resume + sub r7, r7, r6 + add r8, r1, r4 + add r9, r8, r7 + + ldr r11, [r0, #PM_INFO_MX7_SRC_V_OFF] + /* store physical resume addr and pm_info address. */ + str r9, [r11, #MX7_SRC_GPR1] + str r1, [r11, #MX7_SRC_GPR2] + + disable_l1_dcache + + store_ttbr + + ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] + ldr r7, [r11, #GPC_PGC_FM] + cmp r7, #0 + beq ddr_only_self_refresh + + ddr_enter_retention + /* enter LPSR mode if resume addr is valid */ + ldr r11, [r0, #PM_INFO_MX7_LPSR_V_OFF] + ldr r7, [r11] + cmp r7, #0x0 + beq ddr_retention_enter_out + + /* disable STOP mode before entering LPSR */ + ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] + ldr r7, [r11] + bic r7, #0xf + str r7, [r11] + + /* shut down vddsoc to enter lpsr mode */ + ldr r11, [r0, #PM_INFO_MX7_SNVS_V_OFF] + ldr r7, [r11, #0x38] + orr r7, r7, #0x60 + str r7, [r11, #0x38] + dsb +wait_shutdown: + wfi + b wait_shutdown + +ddr_only_self_refresh: + ddrc_enter_self_refresh + b wfi +ddr_retention_enter_out: + ldr r11, [r0, #PM_INFO_MX7_GIC_DIST_V_OFF] + ldr r7, =0x0 + ldr r8, =0x1000 + str r7, [r11, r8] + + ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] + ldr r4, [r11, #MX7D_GPC_IMR1] + ldr r5, [r11, #MX7D_GPC_IMR2] + ldr r6, [r11, #MX7D_GPC_IMR3] + ldr r7, [r11, #MX7D_GPC_IMR4] + + ldr r8, =0xffffffff + str r8, [r11, #MX7D_GPC_IMR1] + str r8, [r11, #MX7D_GPC_IMR2] + str r8, [r11, #MX7D_GPC_IMR3] + str r8, [r11, #MX7D_GPC_IMR4] + + /* + * enable the RBC bypass counter here + * to hold off the interrupts. RBC counter + * = 8 (240us). With this setting, the latency + * from wakeup interrupt to ARM power up + * is ~250uS. + */ + ldr r8, [r11, #0x14] + bic r8, r8, #(0x3f << 24) + orr r8, r8, #(0x8 << 24) + str r8, [r11, #0x14] + + /* enable the counter. */ + ldr r8, [r11, #0x14] + orr r8, r8, #(0x1 << 30) + str r8, [r11, #0x14] + + /* unmask all the GPC interrupts. */ + str r4, [r11, #MX7D_GPC_IMR1] + str r5, [r11, #MX7D_GPC_IMR2] + str r6, [r11, #MX7D_GPC_IMR3] + str r7, [r11, #MX7D_GPC_IMR4] + + /* + * now delay for a short while (3usec) + * ARM is at 1GHz at this point + * so a short loop should be enough. + * this delay is required to ensure that + * the RBC counter can start counting in + * case an interrupt is already pending + * or in case an interrupt arrives just + * as ARM is about to assert DSM_request. + */ + ldr r7, =2000 +rbc_loop: + subs r7, r7, #0x1 + bne rbc_loop +wfi: + dsb + /* Enter stop mode */ + wfi + + mov r5, #0x0 + + ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] + ldr r7, [r11, #GPC_PGC_FM] + cmp r7, #0 + beq wfi_ddr_self_refresh_out + + ddr_exit_retention + b wfi_ddr_retention_out +wfi_ddr_self_refresh_out: + ddrc_exit_self_refresh +wfi_ddr_retention_out: + + /* check whether it is a standby mode */ + ldr r11, [r0, #PM_INFO_MX7_GPC_V_OFF] + ldr r7, [r11, #GPC_PGC_C0] + cmp r7, #0 + beq standby_out + + ldr r11, [r0, #PM_INFO_MX7_GIC_DIST_V_OFF] + ldr r7, =0x1 + ldr r8, =0x1000 + str r7, [r11, r8] + + restore_ttbr +standby_out: + pop {r4-r12} + /* return to suspend finish */ + bx lr + +resume: + write_iciallu + write_bpiall + dsb + isb + + mov r6, #(SCTLR_I | SCTLR_Z) + write_sctlr r6 + isb + + /* + * After resume back, rom run in SVC mode, + * so we need to switch to monitor mode. + */ + cps #CPSR_MODE_MON + + /* get physical resume address from pm_info. */ + ldr lr, [r0, #PM_INFO_MX7_RESUME_ADDR_OFF] + /* clear core0's entry and parameter */ + ldr r11, [r0, #PM_INFO_MX7_SRC_P_OFF] + mov r7, #0x0 + str r7, [r11, #MX7_SRC_GPR1] + str r7, [r11, #MX7_SRC_GPR2] + + mov r5, #0x1 + + ldr r11, [r0, #PM_INFO_MX7_GPC_P_OFF] + ldr r7, [r11, #GPC_PGC_FM] + cmp r7, #0 + beq dsm_ddr_self_refresh_out + + ddr_exit_retention + b dsm_ddr_retention_out +dsm_ddr_self_refresh_out: + ddrc_exit_self_refresh +dsm_ddr_retention_out: + + bx lr +END_FUNC imx7_suspend + +FUNC ca7_cpu_resume, : +UNWIND( .cantunwind) + mov r0, #0 @ ; write the cache size selection register to be + write_csselr r0 @ ; 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 + write_dcisw r2 @ ; 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 @ ; overflow out of set field? + bne _inv_nextline + add r0, r0, #1 << WAY_FIELD_OFFSET @ ; increment the way number + cmp r0, #0 @ ; overflow out of way field? + bne _inv_nextway + + dsb @ ; synchronise + isb + + /* + * No stack, scratch r0-r3 + * TODO: Need to use specific configure, but not plat_xxx. + * Because plat_xx maybe changed in future, we can not rely on it. + * Need handle sp carefully. + */ + blx plat_cpu_reset_early + + b sm_pm_cpu_resume +END_FUNC ca7_cpu_resume diff --git a/optee/optee_os/core/arch/arm/plat-imx/pm/psci.c b/optee/optee_os/core/arch/arm/plat-imx/pm/psci.c new file mode 100644 index 0000000..6fb1777 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/pm/psci.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int psci_features(uint32_t psci_fid) +{ + switch (psci_fid) { + case ARM_SMCCC_VERSION: + case PSCI_PSCI_FEATURES: + case PSCI_VERSION: + case PSCI_CPU_SUSPEND: + case PSCI_CPU_OFF: +#ifdef CFG_BOOT_SECONDARY_REQUEST + case PSCI_CPU_ON: +#endif + case PSCI_AFFINITY_INFO: + case PSCI_SYSTEM_OFF: + case PSCI_SYSTEM_RESET: + case PSCI_SYSTEM_RESET2: + return PSCI_RET_SUCCESS; + default: + return PSCI_RET_NOT_SUPPORTED; + } +} + +uint32_t psci_version(void) +{ + return PSCI_VERSION_1_0; +} + +#ifdef CFG_BOOT_SECONDARY_REQUEST +int psci_cpu_on(uint32_t core_idx, uint32_t entry, + uint32_t context_id) +{ + uint32_t val; + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, 1); + + if (!va) + EMSG("No SRC mapping\n"); + + if ((core_idx == 0) || (core_idx >= CFG_TEE_CORE_NB_CORE)) + return PSCI_RET_INVALID_PARAMETERS; + + /* set secondary cores' NS entry addresses */ + boot_set_core_ns_entry(core_idx, entry, context_id); + + val = virt_to_phys((void *)TEE_LOAD_ADDR); + +#ifdef CFG_MX7 + io_write32(va + SRC_GPR1_MX7 + core_idx * 8, val); + + imx_gpcv2_set_core1_pup_by_software(); + + /* release secondary core */ + val = io_read32(va + SRC_A7RCR1); + val |= BIT32(SRC_A7RCR1_A7_CORE1_ENABLE_OFFSET + + (core_idx - 1)); + io_write32(va + SRC_A7RCR1, val); +#else + /* boot secondary cores from OP-TEE load address */ + io_write32(va + SRC_GPR1 + core_idx * 8, val); + + /* release secondary core */ + val = io_read32(va + SRC_SCR); + val |= BIT32(SRC_SCR_CORE1_ENABLE_OFFSET + (core_idx - 1)); + val |= BIT32(SRC_SCR_CORE1_RST_OFFSET + (core_idx - 1)); + io_write32(va + SRC_SCR, val); + + imx_set_src_gpr(core_idx, 0); +#endif /* CFG_MX7 */ + + return PSCI_RET_SUCCESS; +} + +int __noreturn psci_cpu_off(void) +{ + uint32_t core_id; + + core_id = get_core_pos(); + + DMSG("core_id: %" PRIu32, core_id); + + psci_armv7_cpu_off(); + + imx_set_src_gpr(core_id, UINT32_MAX); + + thread_mask_exceptions(THREAD_EXCP_ALL); + + while (true) + wfi(); +} + +int psci_affinity_info(uint32_t affinity, + uint32_t lowest_affnity_level __unused) +{ + vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, 1); + vaddr_t gpr5 = core_mmu_get_va(IOMUXC_BASE, MEM_AREA_IO_SEC, + IOMUXC_GPR5_OFFSET + sizeof(uint32_t)) + + IOMUXC_GPR5_OFFSET; + uint32_t cpu, val; + bool wfi; + + cpu = affinity; + + if (soc_is_imx7ds()) + wfi = true; + else + wfi = io_read32(gpr5) & ARM_WFI_STAT_MASK(cpu); + + if ((imx_get_src_gpr(cpu) == 0) || !wfi) + return PSCI_AFFINITY_LEVEL_ON; + + DMSG("cpu: %" PRIu32 "GPR: %" PRIx32, cpu, imx_get_src_gpr(cpu)); + /* + * Wait secondary cpus ready to be killed + * TODO: Change to non dead loop + */ + if (soc_is_imx7ds()) { + while (io_read32(va + SRC_GPR1_MX7 + cpu * 8 + 4) != UINT_MAX) + ; + + val = io_read32(va + SRC_A7RCR1); + val &= ~BIT32(SRC_A7RCR1_A7_CORE1_ENABLE_OFFSET + (cpu - 1)); + io_write32(va + SRC_A7RCR1, val); + } else { + while (io_read32(va + SRC_GPR1 + cpu * 8 + 4) != UINT32_MAX) + ; + + /* Kill cpu */ + val = io_read32(va + SRC_SCR); + val &= ~BIT32(SRC_SCR_CORE1_ENABLE_OFFSET + cpu - 1); + val |= BIT32(SRC_SCR_CORE1_RST_OFFSET + cpu - 1); + io_write32(va + SRC_SCR, val); + } + + /* Clean arg */ + imx_set_src_gpr(cpu, 0); + + return PSCI_AFFINITY_LEVEL_OFF; +} +#endif + +void __noreturn psci_system_off(void) +{ +#ifndef CFG_MX7ULP + vaddr_t snvs_base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, 1); + + io_write32(snvs_base + SNVS_LPCR_OFF, + SNVS_LPCR_TOP_MASK | + SNVS_LPCR_DP_EN_MASK | + SNVS_LPCR_SRTC_ENV_MASK); + dsb(); +#endif + + while (1) + ; +} + +__weak int imx7d_lowpower_idle(uint32_t power_state __unused, + uintptr_t entry __unused, + uint32_t context_id __unused, + struct sm_nsec_ctx *nsec __unused) +{ + return 0; +} + +__weak int imx7_cpu_suspend(uint32_t power_state __unused, + uintptr_t entry __unused, + uint32_t context_id __unused, + struct sm_nsec_ctx *nsec __unused) +{ + return 0; +} + +int psci_cpu_suspend(uint32_t power_state, + uintptr_t entry, uint32_t context_id __unused, + struct sm_nsec_ctx *nsec) +{ + uint32_t id, type; + int ret = PSCI_RET_INVALID_PARAMETERS; + + id = power_state & PSCI_POWER_STATE_ID_MASK; + type = (power_state & PSCI_POWER_STATE_TYPE_MASK) >> + PSCI_POWER_STATE_TYPE_SHIFT; + + if ((type != PSCI_POWER_STATE_TYPE_POWER_DOWN) && + (type != PSCI_POWER_STATE_TYPE_STANDBY)) { + DMSG("Not supported %x\n", type); + return ret; + } + + /* + * ID 0 means suspend + * ID 1 means low power idle + * TODO: follow PSCI StateID sample encoding. + */ + DMSG("ID = %d\n", id); + if (id == 1) { + if (soc_is_imx7ds()) + return imx7d_lowpower_idle(power_state, entry, + context_id, nsec); + return ret; + } else if (id == 0) { + if (soc_is_imx7ds()) { + return imx7_cpu_suspend(power_state, entry, + context_id, nsec); + } + return ret; + } + + DMSG("ID %d not supported\n", id); + + return ret; +} + +void __noreturn psci_system_reset(void) +{ + imx_wdog_restart(true); +} + +int __noreturn psci_system_reset2(uint32_t reset_type __unused, + uint32_t cookie __unused) +{ + /* force WDOG reset */ + imx_wdog_restart(false); +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/pm/sub.mk b/optee/optee_os/core/arch/arm/plat-imx/pm/sub.mk new file mode 100644 index 0000000..b6b51c9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/pm/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += . +srcs-y += psci.c +srcs-$(CFG_MX7) += pm-imx7.c psci-suspend-imx7.S imx7_suspend.c \ + cpuidle-imx7d.c psci-cpuidle-imx7.S gpcv2.c diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx6-crm.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx6-crm.h new file mode 100644 index 0000000..032058d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx6-crm.h @@ -0,0 +1,860 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + */ +#ifndef __IMX6_CRM_H__ +#define __IMX6_CRM_H__ + +#define CCM_CCR 0x0000 +#define CCM_CCDR 0x0004 +#define CCM_CSR 0x0008 +#define CCM_CCSR 0x000C +#define CCM_CACRR 0x0010 +#define CCM_CBCDR 0x0014 +#define CCM_CBCMR 0x0018 +#define CCM_CSCMR1 0x001C +#define CCM_CSCMR2 0x0020 +#define CCM_CSCDR1 0x0024 +#define CCM_CS1CDR 0x0028 +#define CCM_CS2CDR 0x002C +#define CCM_CDCDR 0x0030 +#define CCM_CHSCCDR 0x0034 +#define CCM_CSCDR2 0x0038 +#define CCM_CSCDR3 0x003C +#define CCM_CSCDR4 0x0040 +#define CCM_CWDR 0x0044 +#define CCM_CDHIPR 0x0048 +#define CCM_CDCR 0x004C +#define CCM_CTOR 0x0050 +#define CCM_CLPCR 0x0054 +#define CCM_CISR 0x0058 +#define CCM_CIMR 0x005C +#define CCM_CCOSR 0x0060 +#define CCM_CGPR 0x0064 +#define CCM_CCGR0 0x0068 +#define CCM_CCGR1 0x006C +#define CCM_CCGR2 0x0070 +#define CCM_CCGR3 0x0074 +#define CCM_CCGR4 0x0078 +#define CCM_CCGR5 0x007C +#define CCM_CCGR6 0x0080 +#define CCM_CCGR7 0x0084 +#define CCM_CMEOR 0x0088 + +#define CCM_ANALOG_PLL_SYS 0x4000 +#define CCM_ANALOG_PLL_SYS_SET 0x4004 +#define CCM_ANALOG_PLL_SYS_CLR 0x4008 +#define CCM_ANALOG_PLL_SYS_TOG 0x400C +#define CCM_ANALOG_USB1_PLL_480_CTRL 0x4010 +#define CCM_ANALOG_USB1_PLL_480_CTRL_SET 0x4014 +#define CCM_ANALOG_USB1_PLL_480_CTRL_CLR 0x4018 +#define CCM_ANALOG_USB1_PLL_480_CTRL_TOG 0x401C + +#define CCM_ANALOG_PLL_528 0x4030 +#define CCM_ANALOG_PLL_528_SET 0x4034 +#define CCM_ANALOG_PLL_528_CLR 0x4038 +#define CCM_ANALOG_PLL_528_TOG 0x403C +#define CCM_ANALOG_PLL_528_SS 0x4040 +#define CCM_ANALOG_PLL_528_NUM 0x4050 +#define CCM_ANALOG_PLL_528_DENOM 0x4060 +#define CCM_ANALOG_PLL_AUDIO 0x4070 +#define CCM_ANALOG_PLL_AUDIO_SET 0x4074 +#define CCM_ANALOG_PLL_AUDIO_CLR 0x4078 +#define CCM_ANALOG_PLL_AUDIO_TOG 0x407C +#define CCM_ANALOG_PLL_AUDIO_NUM 0x4080 +#define CCM_ANALOG_PLL_AUDIO_DENOM 0x4090 +#define CCM_ANALOG_PLL_VIDEO 0x40A0 +#define CCM_ANALOG_PLL_VIDEO_SET 0x40A4 +#define CCM_ANALOG_PLL_VIDEO_CLR 0x40A8 +#define CCM_ANALOG_PLL_VIDEO_TOG 0x40AC +#define CCM_ANALOG_PLL_VIDEO_NUM 0x40B0 +#define CCM_ANALOG_PLL_VEDIO_DENON 0x40C0 +#define CCM_ANALOG_PLL_ENET 0x40E0 +#define CCM_ANALOG_PLL_ENET_SET 0x40E4 +#define CCM_ANALOG_PLL_ENET_CLR 0x40E8 +#define CCM_ANALOG_PLL_ENET_TOG 0x40EC +#define CCM_ANALOG_PFD_480 0x40F0 +#define CCM_ANALOG_PFD_480_SET 0x40F4 +#define CCM_ANALOG_PFD_480_CLR 0x40F8 +#define CCM_ANALOG_PFD_480_TOG 0x40FC +#define CCM_ANALOG_PFD_528 0x4100 +#define CCM_ANALOG_PFD_528_SET 0x4104 +#define CCM_ANALOG_PFD_528_CLR 0x4108 +#define CCM_ANALOG_PFD_528_TOG 0x410C + +/* Define the bits in register CCR */ +#define BS_CCM_CCR_RBC_EN 27 +#define BM_CCM_CCR_RBC_EN BIT32(BS_CCM_CCR_RBC_EN) +#define BS_CCM_CCR_REG_BYPASS_COUNT 21 +#define BM_CCM_CCR_REG_BYPASS_COUNT \ + SHIFT_U32(0x3F, BS_CCM_CCR_REG_BYPASS_COUNT) +#define BS_CCM_CCR_WB_COUNT 16 +#define BM_CCM_CCR_WB_COUNT SHIFT_U32(0x7, BS_CCM_CCR_WB_COUNT) +#define BS_CCM_CCR_OSCNT 0 +#define BM_CCM_CCR_OSCNT SHIFT_U32(0xFF, BS_CCM_CCR_OSCNT) +#define CCM_CCR_COSC_EN SHIFT_U32((1 << 12), BS_CCM_CCR_OSCNT) + +/* Define the bits in register CCDR */ +#define BS_CCM_CCDR_MMDC_CH1_HS_MASK 16 +#define BM_CCM_CCDR_MMDC_CH1_HS_MASK BIT32(BS_CCM_CCDR_MMDC_CH1_HS_MASK) +#define BS_CCM_CCDR_MMDC_CH0_HS_MASK 17 +#define BM_CCM_CCDR_MMDC_CH0_HS_MASK BIT32(BS_CCM_CCDR_MMDC_CH0_HS_MASK) + +/* Define the bits in register CSR */ +#define BS_CCM_CSR_COSC_READY 5 +#define BM_CCM_CSR_COSC_READY BIT32(BS_CCM_CSR_COSC_READY) +#define BS_CCM_CSR_REF_EN_B 0 +#define BM_CCM_CSR_REF_EN_B BIT32(BS_CCM_CSR_REF_EN_B) + +/* Define the bits in register CCSR */ +#define BS_CCM_CCSR_PDF_540M_AUTO_DIS 15 +#define BM_CCM_CCSR_PDF_540M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_540M_AUTO_DIS) +#define BS_CCM_CCSR_PDF_720M_AUTO_DIS 14 +#define BM_CCM_CCSR_PDF_720M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_720M_AUTO_DIS) +#define BS_CCM_CCSR_PDF_454M_AUTO_DIS 13 +#define BM_CCM_CCSR_PDF_454M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_454M_AUTO_DIS) +#define BS_CCM_CCSR_PDF_508M_AUTO_DIS 12 +#define BM_CCM_CCSR_PDF_508M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_508M_AUTO_DIS) +#define BS_CCM_CCSR_PDF_594M_AUTO_DIS 11 +#define BM_CCM_CCSR_PDF_594M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_594M_AUTO_DIS) +#define BS_CCM_CCSR_PDF_352M_AUTO_DIS 10 +#define BM_CCM_CCSR_PDF_352M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_352M_AUTO_DIS) +#define BS_CCM_CCSR_PDF_400M_AUTO_DIS 9 +#define BM_CCM_CCSR_PDF_400M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_400M_AUTO_DIS) +#define BS_CCM_CCSR_STEP_SEL 8 +#define BM_CCM_CCSR_STEP_SEL BIT32(BS_CCM_CCSR_STEP_SEL) +#define BS_CCM_CCSR_PLL1_SW_CLK_SEL 2 +#define BM_CCM_CCSR_PLL1_SW_CLK_SEL BIT32(BS_CCM_CCSR_PLL1_SW_CLK_SEL) +#define BS_CCM_CCSR_PLL2_SW_CLK_SEL 1 +#define BM_CCM_CCSR_PLL2_SW_CLK_SEL BIT32(BS_CCM_CCSR_PLL2_SW_CLK_SEL) +#define BS_CCM_CCSR_PLL3_SW_CLK_SEL 0 +#define BM_CCM_CCSR_PLL3_SW_CLK_SEL BIT32(BS_CCM_CCSR_PLL3_SW_CLK_SEL) + +/* Define the bits in register CACRR */ +#define BS_CCM_CACRR_ARM_PODF 0 +#define BM_CCM_CACRR_ARM_PODF SHIFT_U32(0x7, BS_CCM_CACRR_ARM_PODF) + +/* Define the bits in register CBCDR */ +#define BS_CCM_CBCDR_PERIPH_CLK2_PODF 27 +#define BM_CCM_CBCDR_PERIPH_CLK2_PODF \ + SHIFT_U32(0x7, BS_CCM_CBCDR_PERIPH_CLK2_PODF) +#define BS_CCM_CBCDR_PERIPH2_CLK2_SEL 26 +#define BM_CCM_CBCDR_PERIPH2_CLK2_SEL BIT32(BS_CCM_CBCDR_PERIPH2_CLK2_SEL) +#define BS_CCM_CBCDR_PERIPH_CLK_SEL 25 +#define BM_CCM_CBCDR_PERIPH_CLK_SEL BIT32(BS_CCM_CBCDR_PERIPH_CLK_SEL) +#define BS_CCM_CBCDR_MMDC_CH0_PODF 19 +#define BM_CCM_CBCDR_MMDC_CH0_PODF \ + SHIFT_U32(0x7, BS_CCM_CBCDR_MMDC_CH0_PODF) +#define BS_CCM_CBCDR_AXI_PODF 16 +#define BM_CCM_CBCDR_AXI_PODF SHIFT_U32(0x7, BS_CCM_CBCDR_AXI_PODF) +#define BS_CCM_CBCDR_AHB_PODF 10 +#define BM_CCM_CBCDR_AHB_PODF SHIFT_U32(0x7, BS_CCM_CBCDR_AHB_PODF) +#define BS_CCM_CBCDR_IPG_PODF 8 +#define BM_CCM_CBCDR_IPG_PODF SHIFT_U32(0x3, BS_CCM_CBCDR_IPG_PODF) +#define BS_CCM_CBCDR_AXI_ALT_SEL 7 +#define BM_CCM_CBCDR_AXI_ALT_SEL BIT32(BS_CCM_CBCDR_AXI_ALT_SEL) +#define BS_CCM_CBCDR_AXI_SEL 6 +#define BM_CCM_CBCDR_AXI_SEL BIT32(BS_CCM_CBCDR_AXI_SEL) +#define BS_CCM_CBCDR_MMDC_CH1_PODF 3 +#define BM_CCM_CBCDR_MMDC_CH1_PODF \ + SHIFT_U32(0x7, BS_CCM_CBCDR_MMDC_CH1_PODF) +#define BS_CCM_CBCDR_PERIPH2_CLK2_PODF 0 +#define BM_CCM_CBCDR_PERIPH2_CLK2_PODF \ + SHIFT_U32(0x7, BS_CCM_CBCDR_PERIPH2_CLK2_PODF) + +/* Define the bits in register CBCMR */ +#define BS_CCM_CBCMR_GPU3D_SHADER_PODF 29 +#define BM_CCM_CBCMR_GPU3D_SHADER_PODF \ + SHIFT_U32(0x7, BS_CCM_CBCMR_GPU3D_SHADER_PODF) +#define BS_CCM_CBCMR_GPU3D_CORE_PODF 26 +#define BM_CCM_CBCMR_GPU3D_CORE_PODF \ + SHIFT_U32(0x7, BS_CCM_CBCMR_GPU3D_CORE_PODF) +#define BS_CCM_CBCMR_GPU2D_CORE_PODF 23 +#define BM_CCM_CBCMR_GPU2D_CORE_PODF \ + SHIFT_U32(0x7, BS_CCM_CBCMR_GPU2D_CORE_PODF) +#define BS_CCM_CBCMR_PRE_PERIPH2_CLK_SEL 21 +#define BM_CCM_CBCMR_PRE_PERIPH2_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CBCMR_PRE_PERIPH2_CLK_SEL) +#define BS_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL 20 +#define BM_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL \ + BIT32(BS_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL) +#define BS_CCM_CBCMR_PRE_PERIPH_CLK_SEL 18 +#define BM_CCM_CBCMR_PRE_PERIPH_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CBCMR_PRE_PERIPH_CLK_SEL) +#define BS_CCM_CBCMR_GPU2D_CLK_SEL 16 +#define BM_CCM_CBCMR_GPU2D_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CBCMR_GPU2D_CLK_SEL) +#define BS_CCM_CBCMR_VPU_AXI_CLK_SEL 14 +#define BM_CCM_CBCMR_VPU_AXI_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CBCMR_VPU_AXI_CLK_SEL) +#define BS_CCM_CBCMR_PERIPH_CLK2_SEL 12 +#define BM_CCM_CBCMR_PERIPH_CLK2_SEL \ + SHIFT_U32(0x3, BS_CCM_CBCMR_PERIPH_CLK2_SEL) +#define BS_CCM_CBCMR_VDOAXI_CLK_SEL 11 +#define BM_CCM_CBCMR_VDOAXI_CLK_SEL BIT32(BS_CCM_CBCMR_VDOAXI_CLK_SEL) +#define BS_CCM_CBCMR_PCIE_AXI_CLK_SEL 10 +#define BM_CCM_CBCMR_PCIE_AXI_CLK_SEL BIT32(BS_CCM_CBCMR_PCIE_AXI_CLK_SE) +#define BS_CCM_CBCMR_GPU3D_SHADER_CLK_SEL 8 +#define BM_CCM_CBCMR_GPU3D_SHADER_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CBCMR_GPU3D_SHADER_CLK_SEL) +#define BS_CCM_CBCMR_GPU3D_CORE_CLK_SEL 4 +#define BM_CCM_CBCMR_GPU3D_CORE_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CBCMR_GPU3D_CORE_CLK_SEL) +#define BS_CCM_CBCMR_GPU3D_AXI_CLK_SEL 1 +#define BM_CCM_CBCMR_GPU3D_AXI_CLK_SEL \ + BIT32(BS_CCM_CBCMR_GPU3D_AXI_CLK_SEL) +#define BS_CCM_CBCMR_GPU2D_AXI_CLK_SEL 0 +#define BM_CCM_CBCMR_GPU2D_AXI_CLK_SEL \ + BIT32(BS_CCM_CBCMR_GPU2D_AXI_CLK_SELx0) + +/* Define the bits in register CSCMR1 */ +#define BS_CCM_CSCMR1_ACLK_EMI_SLOW 29 +#define BM_CCM_CSCMR1_ACLK_EMI_SLOW \ + SHIFT_U32(0x3, BS_CCM_CSCMR1_ACLK_EMI_SLOW) +#define BS_CCM_CSCMR1_ACLK_EMI 27 +#define BM_CCM_CSCMR1_ACLK_EMI SHIFT_U32(0x3, BS_CCM_CSCMR1_ACLK_EMI) +#define BS_CCM_CSCMR1_ACLK_EMI_SLOW_PODF 23 +#define BM_CCM_CSCMR1_ACLK_EMI_SLOW_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCMR1_ACLK_EMI_SLOW_PODF) +#define BS_CCM_CSCMR1_ACLK_EMI_PODF 20 +#define BM_CCM_CSCMR1_ACLK_EMI_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCMR1_ACLK_EMI_PODF) +#define BS_CCM_CSCMR1_USDHC4_CLK_SEL 19 +#define BM_CCM_CSCMR1_USDHC4_CLK_SEL \ + BIT32(BS_CCM_CSCMR1_USDHC4_CLK_SEL) +#define BS_CCM_CSCMR1_USDHC3_CLK_SEL 18 +#define BM_CCM_CSCMR1_USDHC3_CLK_SEL \ + BIT32(BS_CCM_CSCMR1_USDHC3_CLK_SEL) +#define BS_CCM_CSCMR1_USDHC2_CLK_SEL 17 +#define BM_CCM_CSCMR1_USDHC2_CLK_SEL \ + BIT32(BS_CCM_CSCMR1_USDHC2_CLK_SEL) +#define BS_CCM_CSCMR1_USDHC1_CLK_SEL 16 +#define BM_CCM_CSCMR1_USDHC1_CLK_SEL \ + BIT32(BS_CCM_CSCMR1_USDHC1_CLK_SEL) +#define BS_CCM_CSCMR1_SSI3_CLK_SEL 14 +#define BM_CCM_CSCMR1_SSI3_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CSCMR1_SSI3_CLK_SEL) +#define BS_CCM_CSCMR1_SSI2_CLK_SEL 12 +#define BM_CCM_CSCMR1_SSI2_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CSCMR1_SSI2_CLK_SEL) +#define BS_CCM_CSCMR1_SSI1_CLK_SEL 10 +#define BM_CCM_CSCMR1_SSI1_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CSCMR1_SSI1_CLK_SEL) +#define BS_CCM_CSCMR1_PERCLK_PODF 0 +#define BM_CCM_CSCMR1_PERCLK_PODF \ + SHIFT_U32(0x3F, BS_CCM_CSCMR1_PERCLK_PODF) + +/* Define the bits in register CSCMR2 */ +#define BS_CCM_CSCMR2_ESAI_PRE_SEL 19 +#define BM_CCM_CSCMR2_ESAI_PRE_SEL \ + SHIFT_U32(0x3, BS_CCM_CSCMR2_ESAI_PRE_SEL) +#define BS_CCM_CSCMR2_LDB_DI1_IPU_DIV 11 +#define BM_CCM_CSCMR2_LDB_DI1_IPU_DIV BIT32(BS_CCM_CSCMR2_LDB_DI1_IPU_DIV) +#define BS_CCM_CSCMR2_LDB_DI0_IPU_DIV 10 +#define BM_CCM_CSCMR2_LDB_DI0_IPU_DIV BIT32(BS_CCM_CSCMR2_LDB_DI1_IPU_DIV) +#define BS_CCM_CSCMR2_CAN_CLK_SEL 2 +#define BM_CCM_CSCMR2_CAN_CLK_SEL \ + SHIFT_U32(0x3F, BS_CCM_CSCMR2_CAN_CLK_SEL) + +/* Define the bits in register CSCDR1 */ +#define BS_CCM_CSCDR1_VPU_AXI_PODF 25 +#define BM_CCM_CSCDR1_VPU_AXI_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCDR1_VPU_AXI_PODF) +#define BS_CCM_CSCDR1_USDHC4_PODF 22 +#define BM_CCM_CSCDR1_USDHC4_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCDR1_USDHC4_PODF) +#define BS_CCM_CSCDR1_USDHC3_PODF 19 +#define BM_CCM_CSCDR1_USDHC3_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCDR1_USDHC3_PODF) +#define BS_CCM_CSCDR1_USDHC2_PODF 16 +#define BM_CCM_CSCDR1_USDHC2_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCDR1_USDHC2_PODF) +#define BS_CCM_CSCDR1_USDHC1_PODF 11 +#define BM_CCM_CSCDR1_USDHC1_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCDR1_USDHC1_PODF) +#define BS_CCM_CSCDR1_USBOH3_CLK_PRED 8 +#define BM_CCM_CSCDR1_USBOH3_CLK_PRED \ + SHIFT_U32(0x7, BS_CCM_CSCDR1_USBOH3_CLK_PRED) +#define BS_CCM_CSCDR1_USBOH3_CLK_PODF 6 +#define BM_CCM_CSCDR1_USBOH3_CLK_PODF \ + SHIFT_U32(0x3, BS_CCM_CSCDR1_USBOH3_CLK_PODF) +#ifdef CONFIG_MX6SL +#define BS_CCM_CSCDR1_UART_CLK_SEL 6 +#define BM_CCM_CSCDR1_UART_CLK_SEL BIT32(BS_CCM_CSCDR1_UART_CLK_SEL) +#define BS_CCM_CSCDR1_UART_CLK_PODF 0 +#define BM_CCM_CSCDR1_UART_CLK_PODF SHIFT_U32(0x1F, BS_CCM_CSCDR1_UA) +#else +#define BS_CCM_CSCDR1_UART_CLK_PODF 0 +#define BM_CCM_CSCDR1_UART_CLK_PODF \ + SHIFT_U32(0x3F, BS_CCM_CSCDR1_UART_CLK_PODF) +#endif + +/* Define the bits in register CS1CDR */ +#define BS_CCM_CS1CDR_ESAI_CLK_PODF 25 +#define BM_CCM_CS1CDR_ESAI_CLK_PODF \ + SHIFT_U32(0x3F, BS_CCM_CS1CDR_ESAI_CLK_PODF) +#define BS_CCM_CS1CDR_SSI3_CLK_PODF 16 +#define BM_CCM_CS1CDR_SSI3_CLK_PODF SHIFT_U32(0x3F, BS_CCM_CS1CDR_SSI3) +#define BS_CCM_CS1CDR_ESAI_CLK_PRED 9 +#define BM_CCM_CS1CDR_ESAI_CLK_PRED \ + SHIFT_U32(0x3, BS_CCM_CS1CDR_ESAI_CLK_PRED) +#define BS_CCM_CS1CDR_SSI1_CLK_PRED 6 +#define BM_CCM_CS1CDR_SSI1_CLK_PRED \ + SHIFT_U32(0x7, BS_CCM_CS1CDR_SSI1_CLK_PRED) +#define BS_CCM_CS1CDR_SSI1_CLK_PODF 0 +#define BM_CCM_CS1CDR_SSI1_CLK_PODF \ + SHIFT_U32(0x3F, BS_CCM_CS1CDR_SSI1_CLK_PODF) + +/* Define the bits in register CS2CDR */ +#define BS_CCM_CS2CDR_ENFC_CLK_PODF 21 +#define BM_CCM_CS2CDR_ENFC_CLK_PODF \ + SHIFT_U32(0x3F, BS_CCM_CS2CDR_ENFC_CLK_PODF) +#define CCM_CS2CDR_ENFC_CLK_PODF(v) \ + (SHIFT_U32(v, BS_CCM_CS2CDR_ENFC_CLK_PODF) & \ + BM_CCM_CS2CDR_ENFC_CLK_PODF) +#define BS_CCM_CS2CDR_ENFC_CLK_PRED 18 +#define BM_CCM_CS2CDR_ENFC_CLK_PRED \ + SHIFT_U32(0x7, BS_CCM_CS2CDR_ENFC_CLK_PRED) +#define CCM_CS2CDR_ENFC_CLK_PRED(v) \ + (SHIFT_U32(v, BS_CCM_CS2CDR_ENFC_CLK_PRED) & \ + BM_CCM_CS2CDR_ENFC_CLK_PRED) +#define BS_CCM_CS2CDR_ENFC_CLK_SEL 16 +#define BM_CCM_CS2CDR_ENFC_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET) +#define CCM_CS2CDR_ENFC_CLK_SEL(v) \ + (SHIFT_U32(v, BS_CCM_CS2CDR_ENFC_CLK_SEL) & \ + BM_CCM_CS2CDR_ENFC_CLK_SEL) +#define BS_CCM_CS2CDR_LDB_DI1_CLK_SEL 12 +#define BM_CCM_CS2CDR_LDB_DI1_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CS2CDR_LDB_DI1_CLK_SEL) +#define BS_CCM_CS2CDR_LDB_DI0_CLK_SEL 9 +#define BM_CCM_CS2CDR_LDB_DI0_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CS2CDR_LDB_DI0_CLK_SEL) +#define BS_CCM_CS2CDR_SSI2_CLK_PRED 6 +#define BM_CCM_CS2CDR_SSI2_CLK_PRED \ + SHIFT_U32(0x7, BS_CCM_CS2CDR_SSI2_CLK_PRED) +#define BS_CCM_CS2CDR_SSI2_CLK_PODF 0 +#define BM_CCM_CS2CDR_SSI2_CLK_PODF \ + SHIFT_U32(0x3F, BS_CCM_CS2CDR_SSI2_CLK_PODF) + +/* Define the bits in register CDCDR */ +#define BS_CCM_CDCDR_HSI_TX_PODF 29 +#define BM_CCM_CDCDR_HSI_TX_PODF \ + SHIFT_U32(0x7, BS_CCM_CDCDR_HSI_TX_PODF) +#define BS_CCM_CDCDR_SPDIF0_CLK_PRED 25 +#define BM_CCM_CDCDR_SPDIF0_CLK_PRED \ + SHIFT_U32(0x7, BS_CCM_CDCDR_SPDIF0_CLK_PRED) +#define BS_CCM_CDCDR_HSI_TX_CLK_SEL 28 +#define BM_CCM_CDCDR_HSI_TX_CLK_SEL \ + BIT32(BS_CCM_CDCDR_HSI_TX_CLK_SEL) +#define BS_CCM_CDCDR_SPDIF0_CLK_PODF 19 +#define BM_CCM_CDCDR_SPDIF0_CLK_PODF \ + SHIFT_U32(0x7, BS_CCM_CDCDR_SPDIF0_CLK_PODF) +#define BS_CCM_CDCDR_SPDIF0_CLK_SEL 20 +#define BM_CCM_CDCDR_SPDIF0_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CDCDR_SPDIF0_CLK_SEL) +#define BS_CCM_CDCDR_SPDIF1_CLK_PRED 12 +#define BM_CCM_CDCDR_SPDIF1_CLK_PRED \ + SHIFT_U32(0x7, BS_CCM_CDCDR_SPDIF1_CLK_PRED) +#define BS_CCM_CDCDR_SPDIF1_CLK_PODF 9 +#define BM_CCM_CDCDR_SPDIF1_CLK_PODF \ + SHIFT_U32(0x7, BS_CCM_CDCDR_SPDIF1_CLK_PODF) +#define BS_CCM_CDCDR_SPDIF1_CLK_SEL 7 +#define BM_CCM_CDCDR_SPDIF1_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CDCDR_SPDIF1_CLK_SEL) + +/* Define the bits in register CHSCCDR */ +#define BS_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL 15 +#define BM_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL) +#define BS_CCM_CHSCCDR_IPU1_DI1_PODF 12 +#define BM_CCM_CHSCCDR_IPU1_DI1_PODF \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI1_PODF) +#define BS_CCM_CHSCCDR_IPU1_DI1_CLK_SEL 9 +#define BM_CCM_CHSCCDR_IPU1_DI1_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI1_CLK_SEL) +#define BS_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL 6 +#define BM_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL) +#define BS_CCM_CHSCCDR_IPU1_DI0_PODF 3 +#define BM_CCM_CHSCCDR_IPU1_DI0_PODF \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI0_PODF) +#define BS_CCM_CHSCCDR_IPU1_DI0_CLK_SEL 0 +#define BM_CCM_CHSCCDR_IPU1_DI0_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI0_CLK_SEL) + +#define CHSCCDR_CLK_SEL_LDB_DI0 3 +#define CHSCCDR_PODF_DIVIDE_BY_3 2 +#define CHSCCDR_IPU_PRE_CLK_540M_PFD 5 + +/* Define the bits in register CSCDR2 */ +#define BS_CCM_CSCDR2_ECSPI_CLK_PODF 19 +#define BM_CCM_CSCDR2_ECSPI_CLK_PODF \ + SHIFT_U32(0x3F, BS_CCM_CSCDR2_ECSPI_CLK_PODF) +#define BS_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL 15 +#define BM_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL) +#define BS_CCM_CHSCCDR_IPU2_DI1_PODF 12 +#define BM_CCM_CHSCCDR_IPU2_DI1_PODF \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI1_PODF) +#define BS_CCM_CHSCCDR_IPU2_DI1_CLK_SEL 9 +#define BM_CCM_CHSCCDR_IPU2_DI1_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI1_CLK_SEL) +#define BS_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL 6 +#define BM_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL) +#define BS_CCM_CHSCCDR_IPU2_DI0_PODF 3 +#define BM_CCM_CHSCCDR_IPU2_DI0_PODF \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI0_PODF) +#define BS_CCM_CHSCCDR_IPU2_DI0_CLK_SEL 0 +#define BM_CCM_CHSCCDR_IPU2_DI0_CLK_SEL \ + SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI0_CLK_SEL) + +/* Define the bits in register CSCDR3 */ +#define BS_CCM_CSCDR3_IPU2_HSP_PODF 16 +#define BM_CCM_CSCDR3_IPU2_HSP_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCDR3_IPU2_HSP_PODF) +#define BS_CCM_CSCDR3_IPU2_HSP_CLK_SEL 14 +#define BM_CCM_CSCDR3_IPU2_HSP_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CSCDR3_IPU2_HSP_CLK_SEL) +#define BS_CCM_CSCDR3_IPU1_HSP_PODF 11 +#define BM_CCM_CSCDR3_IPU1_HSP_PODF \ + SHIFT_U32(0x7, BS_CCM_CSCDR3_IPU1_HSP_PODF) +#define BS_CCM_CSCDR3_IPU1_HSP_CLK_SEL 9 +#define BM_CCM_CSCDR3_IPU1_HSP_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CSCDR3_IPU1_HSP_CLK_SEL) + +/* Define the bits in register CDHIPR */ +#define BS_CCM_CDHIPR_ARM_PODF_BUSY 16 +#define BM_CCM_CDHIPR_ARM_PODF_BUSY \ + BIT32(BS_CCM_CDHIPR_ARM_PODF_BUSY) +#define BS_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY 5 +#define BM_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY \ + BIT32(BS_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY) +#define BS_CCM_CDHIPR_MMDC_CH0_PODF_BUSY 4 +#define BM_CCM_CDHIPR_MMDC_CH0_PODF_BUSY \ + BIT32(BS_CCM_CDHIPR_MMDC_CH0_PODF_BUSY) +#define BS_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY 3 +#define BM_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY \ + BIT32(BS_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY) +#define BS_CCM_CDHIPR_MMDC_CH1_PODF_BUSY 2 +#define BM_CCM_CDHIPR_MMDC_CH1_PODF_BUSY \ + BIT32(BS_CCM_CDHIPR_MMDC_CH1_PODF_BUSY) +#define BS_CCM_CDHIPR_AHB_PODF_BUSY 1 +#define BM_CCM_CDHIPR_AHB_PODF_BUSY \ + BIT32(BS_CCM_CDHIPR_AHB_PODF_BUSY) +#define BS_CCM_CDHIPR_AXI_PODF_BUSY 0 +#define BM_CCM_CDHIPR_AXI_PODF_BUSY \ + BIT32(BS_CCM_CDHIPR_AXI_PODF_BUSY) + +/* Define the bits in register CLPCR */ +#define BS_CCM_CLPCR_MASK_L2CC_IDLE 27 +#define BM_CCM_CLPCR_MASK_L2CC_IDLE \ + BIT32(BS_CCM_CLPCR_MASK_L2CC_IDLE) +#define BS_CCM_CLPCR_MASK_SCU_IDLE 26 +#define BM_CCM_CLPCR_MASK_SCU_IDLE \ + BIT32(BS_CCM_CLPCR_MASK_SCU_IDLE) +#define BS_CCM_CLPCR_MASK_CORE3_WFI 25 +#define BM_CCM_CLPCR_MASK_CORE3_WFI \ + BIT32(BS_CCM_CLPCR_MASK_CORE3_WFI) +#define BS_CCM_CLPCR_MASK_CORE2_WFI 24 +#define BM_CCM_CLPCR_MASK_CORE2_WFI \ + BIT32(BS_CCM_CLPCR_MASK_CORE2_WFI) +#define BS_CCM_CLPCR_MASK_CORE1_WFI 23 +#define BM_CCM_CLPCR_MASK_CORE1_WFI \ + BIT32(BS_CCM_CLPCR_MASK_CORE1_WFI) +#define BS_CCM_CLPCR_MASK_CORE0_WFI 22 +#define BM_CCM_CLPCR_MASK_CORE0_WFI \ + BIT32(BS_CCM_CLPCR_MASK_CORE0_WFI) +#define BS_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS 21 +#define BM_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS \ + BIT32(BS_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS) +#define BS_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS 19 +#define BM_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS \ + BIT32(BS_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS) +#define BS_CCM_CLPCR_WB_CORE_AT_LPM 17 +#define BM_CCM_CLPCR_WB_CORE_AT_LPM \ + BIT32(BS_CCM_CLPCR_WB_CORE_AT_LPM) +#define BS_CCM_CLPCR_WB_PER_AT_LPM 16 +#define BM_CCM_CLPCR_WB_PER_AT_LPM \ + BIT32(BS_CCM_CLPCR_WB_PER_AT_LPM) +#define BS_CCM_CLPCR_COSC_PWRDOWN 11 +#define BM_CCM_CLPCR_COSC_PWRDOWN \ + BIT32(BS_CCM_CLPCR_COSC_PWRDOWN) +#define BS_CCM_CLPCR_STBY_COUNT 9 +#define BM_CCM_CLPCR_STBY_COUNT \ + SHIFT_U32(0x3, BS_CCM_CLPCR_STBY_COUNT) +#define BS_CCM_CLPCR_VSTBY 8 +#define BM_CCM_CLPCR_VSTBY \ + BIT32(BS_CCM_CLPCR_VSTBY) +#define BS_CCM_CLPCR_DIS_REF_OSC 7 +#define BM_CCM_CLPCR_DIS_REF_OSC \ + BIT32(BS_CCM_CLPCR_DIS_REF_OSC) +#define BS_CCM_CLPCR_SBYOS 6 +#define BM_CCM_CLPCR_SBYOS \ + BIT32(BS_CCM_CLPCR_SBYOS) +#define BS_CCM_CLPCR_ARM_CLK_DIS_ON_LPM 5 +#define BM_CCM_CLPCR_ARM_CLK_DIS_ON_LPM \ + BIT32(BS_CCM_CLPCR_ARM_CLK_DIS_ON_LPM) +#define BS_CCM_CLPCR_LPSR_CLK_SEL 3 +#define BM_CCM_CLPCR_LPSR_CLK_SEL \ + SHIFT_U32(0x3, BS_CCM_CLPCR_LPSR_CLK_SEL) +#define BS_CCM_CLPCR_BYPASS_PMIC_VFUNC_RDY 2 +#define BM_CCM_CLPCR_BYPASS_PMIC_VFUNC_RDY \ + BIT32(BS_CCM_CLPCR_BYPASS_PMIC_VFUNC_RDY) +#define BS_CCM_CLPCR_LPM 0 +#define BM_CCM_CLPCR_LPM \ + SHIFT_U32(0x3, BS_CCM_CLPCR_LPM) + +/* Define the bits in register CISR */ +#define BS_CCM_CISR_ARM_PODF_LOADED 26 +#define BM_CCM_CISR_ARM_PODF_LOADED \ + BIT32(BS_CCM_CISR_ARM_PODF_LOADED) +#define BS_CCM_CISR_MMDC_CH0_PODF_LOADED 23 +#define BM_CCM_CISR_MMDC_CH0_PODF_LOADED \ + BIT32(BS_CCM_CISR_MMDC_CH0_PODF_LOADED) +#define BS_CCM_CISR_PERIPH_CLK_SEL_LOADED 22 +#define BM_CCM_CISR_PERIPH_CLK_SEL_LOADED \ + BIT32(BS_CCM_CISR_PERIPH_CLK_SEL_LOADED) +#define BS_CCM_CISR_MMDC_CH1_PODF_LOADED 21 +#define BM_CCM_CISR_MMDC_CH1_PODF_LOADED \ + BIT32(BS_CCM_CISR_MMDC_CH1_PODF_LOADED) +#define BS_CCM_CISR_AHB_PODF_LOADED 20 +#define BM_CCM_CISR_AHB_PODF_LOADED \ + BIT32(BS_CCM_CISR_AHB_PODF_LOADED) +#define BS_CCM_CISR_PERIPH2_CLK_SEL_LOADED 19 +#define BM_CCM_CISR_PERIPH2_CLK_SEL_LOADED \ + BIT32(BS_CCM_CISR_PERIPH2_CLK_SEL_LOADED) +#define BS_CCM_CISR_AXI_PODF_LOADED 17 +#define BM_CCM_CISR_AXI_PODF_LOADED \ + BIT32(BS_CCM_CISR_AXI_PODF_LOADED) +#define BS_CCM_CISR_COSC_READY 6 +#define BM_CCM_CISR_COSC_READY \ + BIT32(BS_CCM_CISR_COSC_READY) +#define BS_CCM_CISR_LRF_PLL 0 +#define BM_CCM_CISR_LRF_PLL \ + BIT32(BS_CCM_CISR_LRF_PLL) + +/* Define the bits in register CIMR */ +#define BS_CCM_CIMR_MASK_ARM_PODF_LOADED 26 +#define BM_CCM_CIMR_MASK_ARM_PODF_LOADED \ + BIT32(BS_CCM_CIMR_MASK_ARM_PODF_LOADED) +#define BS_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED 23 +#define BM_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED \ + BIT32(BS_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED) +#define BS_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED 22 +#define BM_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED \ + BIT32(BS_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED) +#define BS_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED 21 +#define BM_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED \ + BIT32(BS_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED) +#define BS_CCM_CIMR_MASK_AHB_PODF_LOADED 20 +#define BM_CCM_CIMR_MASK_AHB_PODF_LOADED \ + BIT32(BS_CCM_CIMR_MASK_AHB_PODF_LOADED) +#define BS_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED 19 +#define BM_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED \ + BIT32(BS_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED) +#define BS_CCM_CIMR_MASK_AXI_PODF_LOADED 17 +#define BM_CCM_CIMR_MASK_AXI_PODF_LOADED \ + BIT32(BS_CCM_CIMR_MASK_AXI_PODF_LOADED) +#define BS_CCM_CIMR_MASK_COSC_READY 6 +#define BM_CCM_CIMR_MASK_COSC_READY \ + BIT32(BS_CCM_CIMR_MASK_COSC_READY) +#define BS_CCM_CIMR_MASK_LRF_PLL 0 +#define BM_CCM_CIMR_MASK_LRF_PLL \ + BIT32(BS_CCM_CIMR_MASK_LRF_PLL) + +/* Define the bits in register CCOSR */ +#define BS_CCM_CCOSR_CKO2_EN 24 +#define BM_CCM_CCOSR_CKO2_EN \ + BIT32(BS_CCM_CCOSR_CKO2_EN) +#define BS_CCM_CCOSR_CKO2_DIV 21 +#define BM_CCM_CCOSR_CKO2_DIV \ + SHIFT_U32(0x7, BS_CCM_CCOSR_CKO2_DIV) +#define BS_CCM_CCOSR_CKO2_SEL 16 +#define BM_CCM_CCOSR_CKO2_SEL \ + SHIFT_U32(0x1F, BS_CCM_CCOSR_CKO2_SEL) +#define BS_CCM_CCOSR_CLK_OUT_SEL 8 +#define BM_CCM_CCOSR_CLK_OUT_SEL_CKO2 \ + BIT32(BS_CCM_CCOSR_CLK_OUT_SEL) +#define BS_CCM_CCOSR_CKOL_EN 7 +#define BM_CCM_CCOSR_CKOL_EN \ + BIT32(BS_CCM_CCOSR_CKOL_EN) +#define BS_CCM_CCOSR_CKOL_DIV 4 +#define BM_CCM_CCOSR_CKOL_DIV \ + SHIFT_U32(0x7, BS_CCM_CCOSR_CKOL_DIV) +#define BS_CCM_CCOSR_CKOL_SEL 0 +#define BM_CCM_CCOSR_CKOL_SEL \ + SHIFT_U32(0xF, BS_CCM_CCOSR_CKOL_SEL) + +/* Define the bits in registers CGPR */ +#define BS_CCM_CGPR_INT_MEM_CLK_LPM 17 +#define BM_CCM_CGPR_INT_MEM_CLK_LPM \ + BIT32(BS_CCM_CGPR_INT_MEM_CLK_LPM) +#define BS_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE 4 +#define BM_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE \ + BIT32(BS_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE) +#define BS_CCM_CGPR_MMDC_EXT_CLK_DIS 2 +#define BM_CCM_CGPR_MMDC_EXT_CLK_DIS \ + BIT32(BS_CCM_CGPR_MMDC_EXT_CLK_DIS) +#define BS_CCM_CGPR_PMIC_DELAY_SCALER 0 +#define BM_CCM_CGPR_PMIC_DELAY_SCALER \ + BIT32(BS_CCM_CGPR_PMIC_DELAY_SCALER) + +/* Define the bits in registers CCGRx */ +#define BS_CCM_CCGR0_AIPS_TZ1 0 +#define BM_CCM_CCGR0_AIPS_TZ1 \ + SHIFT_U32(3, BS_CCM_CCGR0_AIPS_TZ1) +#define BS_CCM_CCGR0_AIPS_TZ2 2 +#define BM_CCM_CCGR0_AIPS_TZ2 \ + SHIFT_U32(3, BS_CCM_CCGR0_AIPS_TZ2) +#define BS_CCM_CCGR0_APBHDMA 4 +#define BM_CCM_CCGR0_APBHDMA \ + SHIFT_U32(3, BS_CCM_CCGR0_APBHDMA) +#define BS_CCM_CCGR0_ASRC 6 +#define BM_CCM_CCGR0_ASRC \ + SHIFT_U32(3, BS_CCM_CCGR0_ASRC) +#define BS_CCM_CCGR0_CAAM_SECURE_MEM 8 +#define BM_CCM_CCGR0_CAAM_SECURE_MEM \ + SHIFT_U32(3, BS_CCM_CCGR0_CAAM_SECURE_MEM) +#define BS_CCM_CCGR0_CAAM_WRAPPER_ACLK 10 +#define BM_CCM_CCGR0_CAAM_WRAPPER_ACLK \ + SHIFT_U32(3, BS_CCM_CCGR0_CAAM_WRAPPER_ACLK) +#define BS_CCM_CCGR0_CAAM_WRAPPER_IPG 12 +#define BM_CCM_CCGR0_CAAM_WRAPPER_IPG \ + SHIFT_U32(3, BS_CCM_CCGR0_CAAM_WRAPPER_IPG) +#define BS_CCM_CCGR0_CAN1 14 +#define BM_CCM_CCGR0_CAN1 SHIFT_U32(3, BS_CCM_CCGR0_CAN1) +#define BS_CCM_CCGR0_CAN1_SERIAL 16 +#define BM_CCM_CCGR0_CAN1_SERIAL \ + SHIFT_U32(3, BS_CCM_CCGR0_CAN1_SERIAL) +#define BS_CCM_CCGR0_CAN2 18 +#define BM_CCM_CCGR0_CAN2 SHIFT_U32(3, BS_CCM_CCGR0_CAN2) +#define BS_CCM_CCGR0_CAN2_SERIAL 20 +#define BM_CCM_CCGR0_CAN2_SERIAL \ + SHIFT_U32(3, BS_CCM_CCGR0_CAN2_SERIAL) +#define BS_CCM_CCGR0_CHEETAH_DBG_CLK 22 +#define BM_CCM_CCGR0_CHEETAH_DBG_CLK \ + SHIFT_U32(3, BS_CCM_CCGR0_CHEETAH_DBG_CLK) +#define BS_CCM_CCGR0_DCIC1 24 +#define BM_CCM_CCGR0_DCIC1 SHIFT_U32(3, BS_CCM_CCGR0_DCIC1) +#define BS_CCM_CCGR0_DCIC2 26 +#define BM_CCM_CCGR0_DCIC2 SHIFT_U32(3, BS_CCM_CCGR0_DCIC2) +#define BS_CCM_CCGR0_DTCP 28 +#define BM_CCM_CCGR0_DTCP SHIFT_U32(3, BS_CCM_CCGR0_DTCP) + +#define BS_CCM_CCGR1_ECSPI1S 0 +#define BM_CCM_CCGR1_ECSPI1S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI1S) +#define BS_CCM_CCGR1_ECSPI2S 2 +#define BM_CCM_CCGR1_ECSPI2S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI2S) +#define BS_CCM_CCGR1_ECSPI3S 4 +#define BM_CCM_CCGR1_ECSPI3S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI3S) +#define BS_CCM_CCGR1_ECSPI4S 6 +#define BM_CCM_CCGR1_ECSPI4S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI4S) +#define BS_CCM_CCGR1_ECSPI5S 8 +#define BM_CCM_CCGR1_ECSPI5S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI5S) +#define BS_CCM_CCGR1_ENET_CLK_ENABLE 10 +#define BM_CCM_CCGR1_ENET_CLK_ENABLE \ + (3 << BS_CCM_CCGR1_ENET_CLK_ENABLE) +#define BS_CCM_CCGR1_EPIT1S 12 +#define BM_CCM_CCGR1_EPIT1S SHIFT_U32(3, BS_CCM_CCGR1_EPIT1S) +#define BS_CCM_CCGR1_EPIT2S 14 +#define BM_CCM_CCGR1_EPIT2S SHIFT_U32(3, BS_CCM_CCGR1_EPIT2S) +#define BS_CCM_CCGR1_ESAIS 16 +#define BM_CCM_CCGR1_ESAIS SHIFT_U32(3, BS_CCM_CCGR1_ESAIS) +#define BS_CCM_CCGR1_GPT_BUS 20 +#define BM_CCM_CCGR1_GPT_BUS SHIFT_U32(3, BS_CCM_CCGR1_GPT_BUS) +#define BS_CCM_CCGR1_GPT_SERIAL 22 +#define BM_CCM_CCGR1_GPT_SERIAL SHIFT_U32(3, BS_CCM_CCGR1_GPT_SERIAL) +#define BS_CCM_CCGR1_GPU2D 24 +#define BM_CCM_CCGR1_GPU2D SHIFT_U32(3, BS_CCM_CCGR1_GPU2D) +#define BS_CCM_CCGR1_GPU3D 26 +#define BM_CCM_CCGR1_GPU3D SHIFT_U32(3, BS_CCM_CCGR1_GPU3D) + +#define BS_CCM_CCGR2_HDMI_TX_IAHBCLK 0 +#define BM_CCM_CCGR2_HDMI_TX_IAHBCLK \ + SHIFT_U32(3, BS_CCM_CCGR2_HDMI_TX_IAHBCLK) +#define BS_CCM_CCGR2_HDMI_TX_ISFRCLK 4 +#define BM_CCM_CCGR2_HDMI_TX_ISFRCLK \ + SHIFT_U32(3, BS_CCM_CCGR2_HDMI_TX_ISFRCLK) +#define BS_CCM_CCGR2_I2C1_SERIAL 6 +#define BM_CCM_CCGR2_I2C1_SERIAL SHIFT_U32(3, BS_CCM_CCGR2_I2C1_SERIAL) +#define BS_CCM_CCGR2_I2C2_SERIAL 8 +#define BM_CCM_CCGR2_I2C2_SERIAL SHIFT_U32(3, BS_CCM_CCGR2_I2C2_SERIAL) +#define BS_CCM_CCGR2_I2C3_SERIAL 10 +#define BM_CCM_CCGR2_I2C3_SERIAL SHIFT_U32(3, BS_CCM_CCGR2_I2C3_SERIAL) +#define BS_CCM_CCGR2_OCOTP_CTRL 12 +#define BM_CCM_CCGR2_OCOTP_CTRL SHIFT_U32(3, BS_CCM_CCGR2_OCOTP_CTRL) +#define BS_CCM_CCGR2_IOMUX_IPT_CLK_IO 14 +#define BM_CCM_CCGR2_IOMUX_IPT_CLK_IO \ + SHIFT_U32(3, BS_CCM_CCGR2_IOMUX_IPT_CLK_IO) +#define BS_CCM_CCGR2_IPMUX1 16 +#define BM_CCM_CCGR2_IPMUX1 SHIFT_U32(3, BS_CCM_CCGR2_IPMUX1) +#define BS_CCM_CCGR2_IPMUX2 18 +#define BM_CCM_CCGR2_IPMUX2 SHIFT_U32(3, BS_CCM_CCGR2_IPMUX2) +#define BS_CCM_CCGR2_IPMUX3 20 +#define BM_CCM_CCGR2_IPMUX3 SHIFT_U32(3, BS_CCM_CCGR2_IPMUX3) +#define BS_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS 22 +#define BM_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS \ + SHIFT_U32(3, BS_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS) +#define BS_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG 24 +#define BM_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG \ + SHIFT_U32(3, BS_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG) +#define BS_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK 26 +#define BM_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK \ + SHIFT_U32(3, BS_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK) + +#define BS_CCM_CCGR3_IPU1_IPU 0 +#define BM_CCM_CCGR3_IPU1_IPU SHIFT_U32(3, BS_CCM_CCGR3_IPU1_IPU) +#define BS_CCM_CCGR3_IPU1_IPU_DI0 2 +#define BM_CCM_CCGR3_IPU1_IPU_DI0 SHIFT_U32(3, BS_CCM_CCGR3_IPU1_IPU_DI0) +#define BS_CCM_CCGR3_IPU1_IPU_DI1 4 +#define BM_CCM_CCGR3_IPU1_IPU_DI1 SHIFT_U32(3, BS_CCM_CCGR3_IPU1_IPU_DI1) +#define BS_CCM_CCGR3_IPU2_IPU 6 +#define BM_CCM_CCGR3_IPU2_IPU SHIFT_U32(3, BS_CCM_CCGR3_IPU2_IPU) +#define BS_CCM_CCGR3_IPU2_IPU_DI0 8 +#define BM_CCM_CCGR3_IPU2_IPU_DI0 SHIFT_U32(3, BS_CCM_CCGR3_IPU2_IPU_DI0) +#define BS_CCM_CCGR3_IPU2_IPU_DI1 10 +#define BM_CCM_CCGR3_IPU2_IPU_DI1 SHIFT_U32(3, BS_CCM_CCGR3_IPU2_IPU_DI1) +#define BS_CCM_CCGR3_LDB_DI0 12 +#define BM_CCM_CCGR3_LDB_DI0 SHIFT_U32(3, BS_CCM_CCGR3_LDB_DI0) +#define BS_CCM_CCGR3_LDB_DI1 14 +#define BM_CCM_CCGR3_LDB_DI1 SHIFT_U32(3, BS_CCM_CCGR3_LDB_DI1) +#define BS_CCM_CCGR3_MIPI_CORE_CFG 16 +#define BM_CCM_CCGR3_MIPI_CORE_CFG \ + SHIFT_U32(3, BS_CCM_CCGR3_MIPI_CORE_CFG) +#define BS_CCM_CCGR3_MLB 18 +#define BM_CCM_CCGR3_MLB SHIFT_U32(3, BS_CCM_CCGR3_MLB) +#define BS_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0 20 +#define BM_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0 \ + SHIFT_U32(3, BS_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0) +#define BS_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1 22 +#define BM_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1 \ + SHIFT_U32(3, BS_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1) +#define BS_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0 24 +#define BM_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0 \ + SHIFT_U32(3, BS_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0) +#define BS_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1 26 +#define BM_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1 \ + SHIFT_U32(3, BS_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1) +#define BS_CCM_CCGR3_OCRAM 28 +#define BM_CCM_CCGR3_OCRAM SHIFT_U32(3, BS_CCM_CCGR3_OCRAM) +#define BS_CCM_CCGR3_OPENVGAXICLK 30 +#define BM_CCM_CCGR3_OPENVGAXICLK \ + SHIFT_U32(3, BS_CCM_CCGR3_OPENVGAXICLK) + +#define BS_CCM_CCGR4_PCIE 0 +#define BM_CCM_CCGR4_PCIE SHIFT_U32(3, BS_CCM_CCGR4_PCIE) +#define BS_CCM_CCGR4_PL301_MX6QFAST1_S133 8 +#define BM_CCM_CCGR4_PL301_MX6QFAST1_S133 \ + SHIFT_U32(3, BS_CCM_CCGR4_PL301_MX6QFAST1_S133) +#define BS_CCM_CCGR4_PL301_MX6QPER1_BCH 12 +#define BM_CCM_CCGR4_PL301_MX6QPER1_BCH \ + SHIFT_U32(3, BS_CCM_CCGR4_PL301_MX6QPER1_BCH) +#define BS_CCM_CCGR4_PL301_MX6QPER2_MAINCLK_ENABLE 14 +#define BM_CCM_CCGR4_PL301_MX6QPER2_MAINCLK_ENABLE \ + SHIFT_U32(3, BS_CCM_CCGR4_PL301_MX6QPER2_MAINCLK_ENABLE) +#define BS_CCM_CCGR4_PWM1 16 +#define BM_CCM_CCGR4_PWM1 \ + SHIFT_U32(3, BS_CCM_CCGR4_PWM1) +#define BS_CCM_CCGR4_PWM2 18 +#define BM_CCM_CCGR4_PWM2 \ + SHIFT_U32(3, BS_CCM_CCGR4_PWM2) +#define BS_CCM_CCGR4_PWM3 20 +#define BM_CCM_CCGR4_PWM3 \ + SHIFT_U32(3, BS_CCM_CCGR4_PWM3) +#define BS_CCM_CCGR4_PWM4 22 +#define BM_CCM_CCGR4_PWM4 \ + SHIFT_U32(3, BS_CCM_CCGR4_PWM4) +#define BS_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB 24 +#define BM_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB \ + SHIFT_U32(3, BS_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB) +#define BS_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH 26 +#define BM_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH \ + SHIFT_U32(3, BS_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH) +#define BS_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO 28 +#define BM_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO \ + SHIFT_U32(3, BS_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO) +#define BS_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB 30 +#define BM_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB \ + SHIFT_U32(3, BS_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB) + +#define BS_CCM_CCGR5_ROM 0 +#define BM_CCM_CCGR5_ROM SHIFT_U32(3, BS_CCM_CCGR5_ROM) +#define BS_CCM_CCGR5_SATA 4 +#define BM_CCM_CCGR5_SATA SHIFT_U32(3, BS_CCM_CCGR5_SATA) +#define BS_CCM_CCGR5_SDMA 6 +#define BM_CCM_CCGR5_SDMA SHIFT_U32(3, BS_CCM_CCGR5_SDMA) +#define BS_CCM_CCGR5_SPBA 12 +#define BM_CCM_CCGR5_SPBA SHIFT_U32(3, BS_CCM_CCGR5_SPBA) +#define BS_CCM_CCGR5_SPDIF 14 +#define BM_CCM_CCGR5_SPDIF SHIFT_U32(3, BS_CCM_CCGR5_SPDIF) +#define BS_CCM_CCGR5_SSI1 18 +#define BM_CCM_CCGR5_SSI1 SHIFT_U32(3, BS_CCM_CCGR5_SSI1) +#define BS_CCM_CCGR5_SSI2 20 +#define BM_CCM_CCGR5_SSI2 SHIFT_U32(3, BS_CCM_CCGR5_SSI2) +#define BS_CCM_CCGR5_SSI3 22 +#define BM_CCM_CCGR5_SSI3 SHIFT_U32(3, BS_CCM_CCGR5_SSI3) +#define BS_CCM_CCGR5_UART 24 +#define BM_CCM_CCGR5_UART SHIFT_U32(3, BS_CCM_CCGR5_UART) +#define BS_CCM_CCGR5_UART_SERIAL 26 +#define BM_CCM_CCGR5_UART_SERIAL SHIFT_U32(3, BS_CCM_CCGR5_UART_SERIAL) + +#define BS_CCM_CCGR6_USBOH3 0 +#define BM_CCM_CCGR6_USBOH3 SHIFT_U32(3, BS_CCM_CCGR6_USBOH3) +#define BS_CCM_CCGR6_USDHC1 2 +#define BM_CCM_CCGR6_USDHC1 SHIFT_U32(3, BS_CCM_CCGR6_USDHC1) +#define BS_CCM_CCGR6_USDHC2 4 +#define BM_CCM_CCGR6_USDHC2 SHIFT_U32(3, BS_CCM_CCGR6_USDHC2) +#define BS_CCM_CCGR6_USDHC3 6 +#define BM_CCM_CCGR6_USDHC3 SHIFT_U32(3, BS_CCM_CCGR6_USDHC3) +#define BS_CCM_CCGR6_USDHC4 8 +#define BM_CCM_CCGR6_USDHC4 SHIFT_U32(3, BS_CCM_CCGR6_USDHC4) +#define BS_CCM_CCGR6_EMI_SLOW 10 +#define BM_CCM_CCGR6_EMI_SLOW SHIFT_U32(3, BS_CCM_CCGR6_EMI_SLOW) +#define BS_CCM_CCGR6_VDOAXICLK 12 +#define BM_CCM_CCGR6_VDOAXICLK SHIFT_U32(3, BS_CCM_CCGR6_VDOAXICLK) +#define BS_CCM_CCGR6_I2C4_SERIAL 24 +#define BM_CCM_CCGR6_I2C4_SERIAL SHIFT_U32(3, BS_CCM_CCGR6_I2C4_SERIAL) + +/* + * Define Analog Macros and common bits + */ +#define BS_CCM_ANALOG_PLL_LOCK 31 +#define BM_CCM_ANALOG_PLL_LOCK \ + BIT32(BS_CCM_ANALOG_PLL_LOCK) +#define BS_CCM_ANALOG_PLL_BYPASS 16 +#define BM_CCM_ANALOG_PLL_BYPASS \ + BIT32(BS_CCM_ANALOG_PLL_BYPASS) +#define BS_CCM_ANALOG_PLL_BYPASS_CLK_SRC 14 +#define BM_CCM_ANALOG_PLL_BYPASS_CLK_SRC \ + SHIFT_U32(0x3, BS_CCM_ANALOG_PLL_BYPASS_CLK_SRC) +#define CCM_ANALOG_PLL_BYPASS_CLK_SRC(clk) \ + (SHIFT_U32(clk, BS_CCM_ANALOG_PLL_BYPASS_CLK_SRC) & \ + BM_CCM_ANALOG_PLL_BYPASS_CLK_SRC) +#define CCM_ANALOG_PLL_BYPASS_CLK_SRC_CLK24M 0x0 +#define CCM_ANALOG_PLL_BYPASS_CLK_SRC_CLK1 0x1 +#define CCM_ANALOG_PLL_BYPASS_CLK_SRC_CLK2 0x2 +#define CCM_ANALOG_PLL_BYPASS_CLK_SRC_XOR 0x3 + +#define BS_CCM_ANALOG_PLL_ENABLE 13 +#define BM_CCM_ANALOG_PLL_ENABLE BIT32(BS_CCM_ANALOG_PLL_ENABLE) +#define BS_CCM_ANALOG_PLL_POWERDOWN 12 +#define BM_CCM_ANALOG_PLL_POWERDOWN BIT32(BS_CCM_ANALOG_PLL_POWERDOWN) +#define BS_CCM_ANALOG_PLL_DIV_SELECT 0 + +/* + * Specific Analog bits definition + */ +#define BS_CCM_ANALOG_PLL_ARM_PLL_SEL 19 +#define BM_CCM_ANALOG_PLL_ARM_PLL_SEL BIT32(BS_CCM_ANALOG_PLL_ARM_PLL_SEL) +#define BS_CCM_ANALOG_PLL_ARM_LVDS_24MHZ_SEL 18 +#define BM_CCM_ANALOG_PLL_ARM_LVDS_24MHZ_SEL \ + BIT32(BS_CCM_ANALOG_PLL_ARM_LVDS_24MHZ_SEL) +#define BS_CCM_ANALOG_PLL_ARM_LVDS_SEL 17 +#define BM_CCM_ANALOG_PLL_ARM_LVDS_SEL \ + BIT32(BS_CCM_ANALOG_PLL_ARM_LVDS_SEL) +#define BM_CCM_ANALOG_PLL_ARM_DIV_SELECT \ + SHIFT_U32(0x7F, BS_CCM_ANALOG_PLL_DIV_SELECT) + +#endif /* __IMX6_CRM_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx6-dcp.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx6-dcp.h new file mode 100644 index 0000000..0067575 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx6-dcp.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020 NXP + */ + +#ifndef __IMX6_DCP_H__ +#define __IMX6_DCP_H__ + +/* DCP base address */ +#ifdef CFG_MX6ULL +#define DCP_BASE 0x2280000 +#endif +#if defined(CFG_MX6SL) || defined(CFG_MX6SLL) +#define DCP_BASE 0x20FC000 +#endif + +/* DCP registers address offset */ +#define DCP_CTRL 0x00 +#define DCP_CTRL_SET 0x04 +#define DCP_CTRL_CLR 0x08 +#define DCP_STAT 0x10 +#define DCP_STAT_CLR 0x18 +#define DCP_CHANNELCTRL 0x20 +#define DCP_CAPABILITY0 0x30 +#define DCP_CAPABILITY1 0x40 +#define DCP_CONTEXT 0x50 +#define DCP_KEY 0x60 +#define DCP_KEYDATA 0x70 +#define DCP_PACKET0 0x80 +#define DCP_PACKET1 0x90 +#define DCP_PACKET2 0xA0 +#define DCP_PACKET3 0xB0 +#define DCP_PACKET4 0xC0 +#define DCP_PACKET5 0xD0 +#define DCP_PACKET6 0xE0 +#define DCP_CH_N_CMDPTR(n) (0x100 + (n) * 0x40) +#define DCP_CH_N_SEMA(n) (0x110 + (n) * 0x40) +#define DCP_CH_N_STAT(n) (0x120 + (n) * 0x40) +#define DCP_CHOCMDPTR 0x100 +#define DCP_CH0SEMA 0x110 +#define DCP_CH0STAT 0x120 +#define DCP_CH1CMDPTR 0x140 +#define DCP_CH2CMDPTR 0x180 +#define DCP_CH3CMDPTR 0x1C0 + +/* DCP CHANNELCTRL register configuration */ +#define DCP_CHANNELCTRL_ENABLE_CHANNEL_MASK GENMASK_32(7, 0) +#define DCP_STAT_CLEAR GENMASK_32(31, 0) +#define DCP_CH_STAT_ERROR_MASK GENMASK_32(23, 0) + +/* DCP CTRL register configuration */ +#define DCP_CTRL_SFTRST BIT32(31) +#define DCP_CTRL_CLKGATE BIT32(30) +#define DCP_CTRL_GATHER_RESIDUAL_WRITES BIT32(23) +#define DCP_CTRL_ENABLE_CONTEXT_CACHING BIT32(22) +#define DCP_CTRL_ENABLE_CONTEXT_SWITCHING BIT32(21) +#define DCP_CTRL_CH3_INTERRUPT_ENABLE BIT32(3) +#define DCP_CTRL_CH2_INTERRUPT_ENABLE BIT32(2) +#define DCP_CTRL_CH1_INTERRUPT_ENABLE BIT32(1) +#define DCP_CTRL_CH0_INTERRUPT_ENABLE BIT32(0) + +/* DCP CAPABILITY0 register configuration */ +#define DCP_CAPABILITY0_DISABLE_UNIQUE_KEY BIT32(29) + +/* Work Packet control0 configuration */ +#define DCP_CONTROL0_OUTPUT_WORDSWAP BIT32(23) +#define DCP_CONTROL0_OUTPUT_BYTESWAP BIT32(22) +#define DCP_CONTROL0_INPUT_WORDSWAP BIT32(21) +#define DCP_CONTROL0_INPUT_BYTESWAP BIT32(20) +#define DCP_CONTROL0_KEY_WORDSWAP BIT32(19) +#define DCP_CONTROL0_KEY_BYTESWA BIT32(18) +#define DCP_CONTROL0_TEST_SEMA_IRQ BIT32(17) +#define DCP_CONTROL0_CONSTANT_FILL BIT32(16) +#define DCP_CONTROL0_HASH_OUTPUT BIT32(15) +#define DCP_CONTROL0_HASH_CHECK BIT32(14) +#define DCP_CONTROL0_HASH_TERM BIT32(13) +#define DCP_CONTROL0_HASH_INIT BIT32(12) +#define DCP_CONTROL0_PAYLOAD_KEY BIT32(11) +#define DCP_CONTROL0_OTP_KEY BIT32(10) +#define DCP_CONTROL0_CIPHER_INIT BIT32(9) +#define DCP_CONTROL0_CIPHER_ENCRYPT BIT32(8) +#define DCP_CONTROL0_ENABLE_BLIT BIT32(7) +#define DCP_CONTROL0_ENABLE_HASH BIT32(6) +#define DCP_CONTROL0_ENABLE_CIPHER BIT32(5) +#define DCP_CONTROL0_ENABLE_MEMCOPY BIT32(4) +#define DCP_CONTROL0_CHAIN_CONTINUOUS BIT32(3) +#define DCP_CONTROL0_CHAIN BIT32(2) +#define DCP_CONTROL0_DECR_SEMAPHORE BIT32(1) +#define DCP_CONTROL0_INTERRUPT_ENABLE BIT32(0) + +/* Work Packet control1 configuration */ +#define DCP_CONTROL1_HASH_SELECT_SHA256 SHIFT_U32(2, 16) +#define DCP_CONTROL1_HASH_SELECT_CRC32 BIT32(16) +#define DCP_CONTROL1_HASH_SELECT_SHA1 SHIFT_U32(0, 16) +#define DCP_CONTROL1_CIPHER_MODE_CBC BIT32(4) +#define DCP_CONTROL1_CIPHER_MODE_ECB SHIFT_U32(0, 4) +#define DCP_CONTROL1_CIPHER_SELECT_AES128 0 +#define DCP_CONTROL1_KEY_SELECT_OTP_CRYPTO SHIFT_U32(0xfe, 8) + +#endif /* __IMX6_DCP_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h new file mode 100644 index 0000000..366d408 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx6.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * Copyright 2017-2020 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 __IMX6_H__ +#define __IMX6_H__ + +#include +#include + +#define UART1_BASE 0x2020000 +#define IOMUXC_BASE 0x020E0000 +#define IOMUXC_SIZE 0x4000 +#define IOMUXC_GPR_BASE 0x020E4000 +#define SRC_BASE 0x020D8000 +#define SRC_SIZE 0x4000 +#define CCM_BASE 0x020C4000 +#define CCM_SIZE 0x4000 +#define ANATOP_BASE 0x020C8000 +#define ANATOP_SIZE 0x1000 +#define SNVS_BASE 0x020CC000 +#define SNVS_SIZE 0x4000 +#define GPC_BASE 0x020DC000 +#define GPC_SIZE 0x4000 +#define WDOG_BASE 0x020BC000 +#define CSU_BASE 0x021C0000 +#define SEMA4_BASE 0x02290000 +#define SEMA4_SIZE 0x4000 +#define MMDC_P0_BASE 0x021B0000 +#define MMDC_P0_SIZE 0x4000 +#define MMDC_P1_BASE 0x021B4000 +#define MMDC_P1_SIZE 0x4000 +#define TZASC_BASE 0x21D0000 +#define TZASC_SIZE 0x4000 +#define TZASC2_BASE 0x21D4000 +#define UART2_BASE 0x021E8000 +#define UART3_BASE 0x021EC000 +#define UART4_BASE 0x021F0000 +#define UART5_BASE 0x021F4000 +#define AIPS1_BASE 0x02000000 +#define AIPS1_SIZE 0x100000 +#define AIPS2_BASE 0x02100000 +#define AIPS2_SIZE 0x100000 +#define AIPS3_BASE 0x02200000 +#define AIPS3_SIZE 0x100000 + +#if defined(CFG_MX6ULL) +#define RNGB_BASE 0x02284000 +#elif defined(CFG_MX6SL) || defined(CFG_MX6SLL) +#define RNGB_BASE 0x021b4000 +#endif + +#define SCU_BASE 0x00A00000 +#define PL310_BASE 0x00A02000 +#define SRC_BASE 0x020D8000 +#define IRAM_BASE 0x00900000 + +#define OCOTP_BASE 0x021BC000 +#define OCOTP_SIZE 0x4000 + +#define GIC_BASE 0x00A00000 +#define GICD_OFFSET 0x1000 + +#if defined(CFG_MX6UL) || defined(CFG_MX6ULL) +#define GICC_OFFSET 0x2000 +#define UART6_BASE 0x021FC000 +#define UART7_BASE 0x02018000 +/* No CAAM on i.MX6ULL */ +#define CAAM_BASE 0x02140000 +#else +#define GICC_OFFSET 0x100 +#define CAAM_BASE 0x02100000 +#endif +#define CAAM_SIZE 0x40000 + +#define GIC_CPU_BASE (GIC_BASE + GICC_OFFSET) +#define GIC_DIST_BASE (GIC_BASE + GICD_OFFSET) + +/* Central Security Unit register values */ +#define CSU_CSL_START 0x0 +#define CSU_CSL_END 0xA0 +#define CSU_ACCESS_ALL 0x00FF00FF +#define CSU_SETTING_LOCK 0x01000100 +#define CSU_SA 0x218 + +/* Used in suspend/resume and low power idle */ +#define MX6Q_SRC_GPR1 0x20 +#define MX6Q_SRC_GPR2 0x24 +#define MX6Q_MMDC_MISC 0x18 +#define MX6Q_MMDC_MAPSR 0x404 +#define MX6Q_MMDC_MPDGCTRL0 0x83c +#define MX6Q_GPC_IMR1 0x08 +#define MX6Q_GPC_IMR2 0x0c +#define MX6Q_GPC_IMR3 0x10 +#define MX6Q_GPC_IMR4 0x14 +#define MX6Q_CCM_CCR 0x0 +#define MX6Q_ANATOP_CORE 0x140 + +#define IOMUXC_GPR9_OFFSET 0x24 +#define IOMUXC_GPR10_OFFSET 0x28 + +#define IOMUXC_GPR10_OCRAM_TZ_ADDR_OFFSET 5 +#define IOMUXC_GPR10_OCRAM_TZ_ADDR_MASK GENMASK_32(10, 5) + +#define IOMUXC_GPR10_OCRAM_TZ_EN_OFFSET 4 +#define IOMUXC_GPR10_OCRAM_TZ_EN_MASK GENMASK_32(4, 4) + +#define IOMUXC_GPR10_OCRAM_TZ_EN_LOCK_OFFSET 20 +#define IOMUXC_GPR10_OCRAM_TZ_EN_LOCK_MASK GENMASK_32(20, 20) +#define IOMUXC_GPR10_OCRAM_TZ_ADDR_LOCK_OFFSET 21 +#define IOMUXC_GPR10_OCRAM_TZ_ADDR_LOCK_MASK GENMASK_32(26, 21) + +#define IOMUXC_GPR10_OCRAM_TZ_ADDR_OFFSET_6UL 11 +#define IOMUXC_GPR10_OCRAM_TZ_ADDR_MASK_6UL GENMASK_32(15, 11) +#define IOMUXC_GPR10_OCRAM_TZ_EN_OFFSET_6UL 10 +#define IOMUXC_GPR10_OCRAM_TZ_EN_MASK_6UL GENMASK_32(10, 10) + +#define IOMUXC_GPR10_OCRAM_TZ_EN_LOCK_OFFSET_6UL 26 +#define IOMUXC_GPR10_OCRAM_TZ_EN_LOCK_MASK_6UL GENMASK_32(26, 26) +#define IOMUXC_GPR10_OCRAM_TZ_ADDR_LOCK_OFFSET_6UL (27) +#define IOMUXC_GPR10_OCRAM_TZ_ADDR_LOCK_MASK_6UL GENMASK_32(31, 27) + +#ifdef CFG_MX6SL +#define DIGPROG_OFFSET 0x280 +#else +#define DIGPROG_OFFSET 0x260 +#endif + +#if defined(CFG_MX6ULL) +#define I2C1_BASE 0x021a0000 +#define I2C2_BASE 0x021a4000 +#define I2C3_BASE 0x021a8000 +#define I2C4_BASE 0x021f8000 + +#define IOMUXC_I2C1_SCL_CFG_OFF 0x340 +#define IOMUXC_I2C1_SDA_CFG_OFF 0x344 +#define IOMUXC_I2C1_SCL_MUX_OFF 0xb4 +#define IOMUXC_I2C1_SDA_MUX_OFF 0xb8 +#define IOMUXC_I2C1_SCL_INP_OFF 0x5a4 +#define IOMUXC_I2C1_SDA_INP_OFF 0x5a8 +#endif + +#endif /* __IMX6_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx7-crm.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7-crm.h new file mode 100644 index 0000000..74a60e4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7-crm.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + */ + +#ifndef __IMX7_CRM_H__ +#define __IMX7_CRM_H__ + +/* + * GPRx Registers + */ +#define CCM_GPR0 0x0 +#define CCM_GPRx_OFFSET 0x10 +#define CCM_GPRx(idx) (((idx) * CCM_GRPx_OFFSET) + CCM_GPR0) +#define CCM_GPRx_SET(idx) (CCM_GPRx(idx) + 0x4) +#define CCM_GPRx_CLR(idx) (CCM_GPRx(idx) + 0x8) +#define CCM_GPRx_TOG(idx) (CCM_GPRx(idx) + 0xC) + +/* + * PLL_CTRLx Registers (PLL Control) + */ +#define CCM_PLL_CTRL0 0x800 +#define CCM_PLL_CTRLx_OFFSET 0x10 +#define CCM_PLL_CTRLx(idx) (((idx) * CCM_PLL_CTRLx_OFFSET) + CCM_PLL_CTRL0) +#define CCM_PLL_CTRLx_SET(idx) (CCM_PLL_CTRLx(idx) + 0x4) +#define CCM_PLL_CTRLx_CLR(idx) (CCM_PLL_CTRLx(idx) + 0x8) +#define CCM_PLL_CTRLx_TOG(idx) (CCM_PLL_CTRLx(idx) + 0xC) + +/* + * CCGRx Registers (Clock Gating) + */ +#define CCM_CCGR0 0x4000 +#define CCM_CCGRx_OFFSET 0x10 +#define CCM_CCGRx(idx) (((idx) * CCM_CCGRx_OFFSET) + CCM_CCGR0) +#define CCM_CCGRx_SET(idx) (CCM_CCGRx(idx) + 0x4) +#define CCM_CCGRx_CLR(idx) (CCM_CCGRx(idx) + 0x8) +#define CCM_CCGRx_TOG(idx) (CCM_CCGRx(idx) + 0xC) + +#define BS_CCM_CCGRx_SETTING(idx) ((idx) * 4) +#define BM_CCM_CCGRx_SETTING(idx) \ + SHIFT_U32(0x3, BS_CCM_CCGRx_SETTING(idx)) +#define CCM_CCGRx_DISABLE(idx) \ + SHIFT_U32(0, BS_CCM_CCGRx_SETTING(idx)) +#define CCM_CCGRx_RUN(idx) \ + BIT32(BS_CCM_CCGRx_SETTING(idx)) +#define CCM_CCGRx_RUN_WAIT(idx) \ + SHIFT_U32(0x2, BS_CCM_CCGRx_SETTING(idx)) +#define CCM_CCGRx_ALWAYS_ON(idx) \ + SHIFT_U32(0x3, BS_CCM_CCGRx_SETTING(idx)) + +/* + * TARGET_ROOTx Registers (Target) + */ +#define CCM_TARGET_ROOT0 0x8000 +#define CCM_TARGET_ROOTx_OFFSET 0x80 +#define CCM_TARGET_ROOTx(idx) \ + (((idx) * CCM_TARGET_ROOTx_OFFSET) + CCM_TARGET_ROOT0) +#define CCM_TARGET_ROOTx_SET(idx) (CCM_TARGET_ROOTx(idx) + 0x4) +#define CCM_TARGET_ROOTx_CLR(idx) (CCM_TARGET_ROOTx(idx) + 0x8) +#define CCM_TARGET_ROOTx_TOG(idx) (CCM_TARGET_ROOTx(idx) + 0xC) + +/* + * MISC_ROOTx Registers (Miscellaneous) + */ +#define CCM_MISC_ROOT0 0x8010 +#define CCM_MISC_ROOTx_OFFSET 0x80 +#define CCM_MISC_ROOTx(idx) \ + (((idx) * CCM_MISC_ROOTx_OFFSET) + CCM_MISC_ROOT0) +#define CCM_MISC_ROOTx_SET(idx) (CCM_MISC_ROOTx(idx) + 0x4) +#define CCM_MISC_ROOTx_CLR(idx) (CCM_MISC_ROOTx(idx) + 0x8) +#define CCM_MISC_ROOTx_TOG(idx) (CCM_MISC_ROOTx(idx) + 0xC) + +/* + * POST_ROOTx Registers (Post Divider) + */ +#define CCM_POST_ROOT0 0x8020 +#define CCM_POST_ROOTx_OFFSET 0x80 +#define CCM_POST_ROOTx(idx) \ + (((idx) * CCM_POST_ROOTx_OFFSET) + CCM_POST_ROOT0) +#define CCM_POST_ROOTx_SET(idx) (CCM_POST_ROOTx(idx) + 0x4) +#define CCM_POST_ROOTx_CLR(idx) (CCM_POST_ROOTx(idx) + 0x8) +#define CCM_POST_ROOTx_TOG(idx) (CCM_POST_ROOTx(idx) + 0xC) + +/* + * PRE_ROOTx Registers (Pre Divider) + */ +#define CCM_PRE_ROOT0 0x8030 +#define CCM_PRE_ROOTx_OFFSET 0x80 +#define CCM_PRE_ROOTx(idx) \ + (((idx) * CCM_PRE_ROOTx_OFFSET) + CCM_PRE_ROOT0) +#define CCM_PRE_ROOTx_SET(idx) (CCM_PRE_ROOTx(idx) + 0x4) +#define CCM_PRE_ROOTx_CLR(idx) (CCM_PRE_ROOTx(idx) + 0x8) +#define CCM_PRE_ROOTx_TOG(idx) (CCM_PRE_ROOTx(idx) + 0xC) + +/* + * ACCESS_CTRL_ROOTx Registers (Access Control) + */ +#define CCM_ACCESS_CTRL_ROOT0 0x8030 +#define CCM_ACCESS_CTRL_ROOTx_OFFSET 0x80 +#define CCM_ACCESS_CTRL_ROOTx(idx) \ + (((idx) * CCM_ACCESS_CTRL_ROOTx_OFFSET) + CCM_ACCESS_CTRL_ROOT0) +#define CCM_ACCESS_CTRL_ROOTx_SET(idx) (CCM_ACCESS_CTRL_ROOTx(idx) + 0x4) +#define CCM_ACCESS_CTRL_ROOTx_CLR(idx) (CCM_ACCESS_CTRL_ROOTx(idx) + 0x8) +#define CCM_ACCESS_CTRL_ROOTx_TOG(idx) (CCM_ACCESS_CTRL_ROOTx(idx) + 0xC) + +/* + * Clock Domain ID + */ +#define CCM_CLOCK_DOMAIN_OCOTP 35 +#define CCM_CLOCK_DOMAIN_CAAM 36 + +#endif /* __IMX7_CRM_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h new file mode 100644 index 0000000..0da8d35 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + */ +#ifndef __IMX7_H__ +#define __IMX7_H__ + +#include + +#define GIC_BASE 0x31000000 +#define GIC_SIZE 0x8000 +#define GICC_OFFSET 0x2000 +#define GICD_OFFSET 0x1000 + +#define CAAM_BASE 0x30900000 +#define CAAM_SIZE 0x40000 +#define UART1_BASE 0x30860000 +#define UART2_BASE 0x30890000 +#define UART3_BASE 0x30880000 +#define UART4_BASE 0x30A60000 +#define UART5_BASE 0x30A70000 + +#define AIPS1_BASE 0x30000000 +#define AIPS1_SIZE 0x400000 +#define AIPS2_BASE 0x30400000 +#define AIPS2_SIZE 0x400000 +#define AIPS3_BASE 0x30800000 +#define AIPS3_SIZE 0x400000 + +#define WDOG_BASE 0x30280000 +#define LPSR_BASE 0x30270000 +#define IOMUXC_BASE 0x30330000 +#define IOMUXC_GPR_BASE 0x30340000 +#define OCOTP_BASE 0x30350000 +#define OCOTP_SIZE 0x10000 +#define ANATOP_BASE 0x30360000 +#define SNVS_BASE 0x30370000 +#define SNVS_SIZE 0x10000 +#define CCM_BASE 0x30380000 +#define CCM_SIZE 0x10000 +#define SRC_BASE 0x30390000 +#define GPC_BASE 0x303A0000 +#define CSU_BASE 0x303E0000 +#define TZASC_BASE 0x30780000 +#define TZASC_SIZE 0x10000 +#define DDRC_PHY_BASE 0x30790000 +#define MMDC_P0_BASE 0x307A0000 +#define DDRC_BASE 0x307A0000 +#define IRAM_BASE 0x00900000 +#define IRAM_S_BASE 0x00180000 + +#define CSU_CSL_START 0x0 +#define CSU_CSL_END 0x100 +#define CSU_ACCESS_ALL 0x00FF00FF +#define CSU_SETTING_LOCK 0x01000100 +#define CSU_SA 0x218 + +#define TRUSTZONE_OCRAM_START 0x180000 + +#define IOMUXC_GPR9_OFFSET 0x24 +#define IOMUXC_GPR9_TZASC1_MUX_CONTROL_OFFSET 0 + +#define IOMUXC_GPR11_OFFSET 0x2C +#define IOMUXC_GPR11_OCRAM_S_TZ_ADDR_OFFSET 11 +#define IOMUXC_GPR11_OCRAM_S_TZ_ADDR_MASK GENMASK_32(13, 11) + +#define IOMUXC_GPR11_OCRAM_S_TZ_EN_OFFSET 10 +#define IOMUXC_GPR11_OCRAM_S_TZ_EN_MASK GENMASK_32(10, 10) + +#define IOMUXC_GPR11_OCRAM_S_TZ_EN_LOCK_OFFSET 26 +#define IOMUXC_GPR11_OCRAM_S_TZ_EN_LOCK_MASK GENMASK_32(26, 26) +#define IOMUXC_GPR11_OCRAM_S_TZ_ADDR_LOCK_OFFSET GENMASK_32(29, 27) + +#define DIGPROG_OFFSET 0x800 + +#endif /* __IMX7_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp-crm.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp-crm.h new file mode 100644 index 0000000..a14aed3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp-crm.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + */ +#ifndef __IMX7ULP_CRM_H__ +#define __IMX7ULP_CRM_H__ + +#include + +#define PCC_CGC_BIT_SHIFT 30 + +#define PCC_ENABLE_CLOCK BIT32(PCC_CGC_BIT_SHIFT) +#define PCC_DISABLE_CLOCK BIT32(0) + +#define PCC_CAAM 0x90 + +#endif /* __IMX7ULP_CRM_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp.h new file mode 100644 index 0000000..a5abc50 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx7ulp.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + */ + +#ifndef __IMX7ULP_H__ +#define __IMX7ULP_H__ + +#include + +#define GIC_BASE 0x40020000 +#define GIC_SIZE 0x8000 +#define GICC_OFFSET 0x2000 +#define GICD_OFFSET 0x1000 + +#define AIPS0_BASE 0x40000000 +#define AIPS0_SIZE 0x800000 +#define AIPS1_BASE 0x40800000 +#define AIPS1_SIZE 0x800000 +#define M4_AIPS_BASE 0x41000000 +#define M4_AIPS_SIZE 0x100000 +#define M4_AIPS0_BASE 0x41000000 +#define M4_AIPS0_SIZE 0x80000 +#define M4_AIPS1_BASE 0x41080000 +#define M4_AIPS1_SIZE 0x80000 + +#define GPIOC_BASE 0x400f0000 +#define GPIOD_BASE 0x400f0040 +#define GPIOE_BASE 0x400f0080 +#define GPIOF_BASE 0x400f00c0 +#define TPM5_BASE 0x40260000 +#define WDOG_BASE 0x403d0000 +#define WDOG_SIZE 0x10 +#define SCG1_BASE 0x403e0000 +#define PCC2_BASE 0x403f0000 +#define PMC1_BASE 0x40400000 +#define SMC1_BASE 0x40410000 +#define MMDC_BASE 0x40ab0000 +#define IOMUXC1_BASE 0x40ac0000 +#define MMDC_IO_BASE 0x40ad0000 +#define PCC3_BASE 0x40b30000 +#define OCOTP_BASE 0x410A6000 +#define OCOTP_SIZE 0x4000 +#define PMC0_BASE 0x410a1000 +#define SIM_BASE 0x410a3000 +#define OCOTP_BASE 0x410A6000 +#define OCOTP_SIZE 0x4000 + +#define CAAM_BASE 0x40240000 +#define CAAM_SIZE 0x10000 +#define UART4_BASE 0x402d0000 +#define UART5_BASE 0x402e0000 +#define UART6_BASE 0x40a60000 +#define UART7_BASE 0x40a70000 + +#define IRAM_BASE 0x1FFFC000 +#define IRAM_SIZE 0x4000 + +#define LP_OCRAM_START IRAM_BASE + +#endif /* __IMX7ULP_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx8m-crm.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8m-crm.h new file mode 100644 index 0000000..58b92b8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8m-crm.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020 Foundries Ltd + */ + +#ifndef __IMX8M_CRM_H +#define __IMX8M_CRM_H + +/* CCGRx Registers (Clock Gating) */ +#define CCM_CCGR0 0x4000 +#define CCM_CCGRx_OFFSET 0x10 +#define CCM_CCGRx(idx) (((idx) * CCM_CCGRx_OFFSET) + CCM_CCGR0) +#define CCM_CCGRx_SET(idx) (CCM_CCGRx(idx) + 0x4) +#define CCM_CCGRx_CLR(idx) (CCM_CCGRx(idx) + 0x8) +#define CCM_CCGRx_TOG(idx) (CCM_CCGRx(idx) + 0xC) + +#define BS_CCM_CCGRx_SETTING(idx) ((idx) * 4) +#define BM_CCM_CCGRx_SETTING(idx) \ + SHIFT_U32(0x3, BS_CCM_CCGRx_SETTING(idx)) +#define CCM_CCGRx_DISABLE(idx) \ + SHIFT_U32(0, BS_CCM_CCGRx_SETTING(idx)) +#define CCM_CCGRx_RUN(idx) \ + BIT32(BS_CCM_CCGRx_SETTING(idx)) +#define CCM_CCGRx_RUN_WAIT(idx) \ + SHIFT_U32(0x2, BS_CCM_CCGRx_SETTING(idx)) +#define CCM_CCGRx_ALWAYS_ON(idx) \ + SHIFT_U32(0x3, BS_CCM_CCGRx_SETTING(idx)) + +#define CCM_CCRG_I2C1 23 +#define CCM_CCRG_I2C2 24 +#define CCM_CCRG_I2C3 25 +#define CCM_CCRG_I2C4 26 +#define CCM_CCRG_OCOTP 34 + +#if defined(CFG_MX8MP) +#define CCM_CCRG_I2C5 51 +#define CCM_CCRG_I2C6 52 +#endif + +#endif /* __IMX8M_CRM_H */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h new file mode 100644 index 0000000..c087fea --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8m.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + */ + +#ifndef __IMX8M_H__ +#define __IMX8M_H__ + +#include + +#define GICD_BASE 0x38800000 +#define GICR_BASE 0x38880000 +#define UART1_BASE 0x30860000 +#define UART2_BASE 0x30890000 +#define UART3_BASE 0x30880000 +#define UART4_BASE 0x30A60000 +#define TZASC_BASE 0x32F80000 +#define TZASC_SIZE 0x10000 +#define CAAM_BASE 0x30900000 +#define CAAM_SIZE 0x40000 +#define CCM_BASE 0x30380000 +#define CCM_SIZE 0x10000 +#define ANATOP_BASE 0x30360000 +#define IOMUXC_BASE 0x30330000 +#define OCOTP_BASE 0x30350000 +#define OCOTP_SIZE 0x10000 +#define SNVS_BASE 0x30370000 +#define SNVS_SIZE 0x10000 + +#ifdef CFG_MX8MQ +#define DIGPROG_OFFSET 0x06c +#define OCOTP_SW_INFO_B1 0x40 +#define OCOTP_SW_MAGIC_B1 0xFF0055AA +#endif +#if defined(CFG_MX8MM) || defined(CFG_MX8MN) || defined(CFG_MX8MP) +#define DIGPROG_OFFSET 0x800 +#endif + +#if defined(CFG_MX8MM) || defined(CFG_MX8MQ) || defined(CFG_MX8MN) +#define I2C1_BASE 0x30a20000 +#define I2C2_BASE 0x30a30000 +#define I2C3_BASE 0x30a40000 +#define I2C4_BASE 0x30a50000 + +#define IOMUXC_I2C1_SCL_CFG_OFF 0x47C +#define IOMUXC_I2C1_SDA_CFG_OFF 0x480 +#define IOMUXC_I2C1_SCL_MUX_OFF 0x214 +#define IOMUXC_I2C1_SDA_MUX_OFF 0x218 +#endif + +#if defined(CFG_MX8MP) +#define I2C1_BASE 0x30a20000 +#define I2C2_BASE 0x30a30000 +#define I2C3_BASE 0x30a40000 +#define I2C4_BASE 0x30a50000 +#define I2C5_BASE 0x30ad0000 +#define I2C6_BASE 0x30ae0000 + +#define IOMUXC_I2C1_SCL_CFG_OFF 0x460 +#define IOMUXC_I2C1_SDA_CFG_OFF 0x464 +#define IOMUXC_I2C1_SCL_MUX_OFF 0x200 +#define IOMUXC_I2C1_SDA_MUX_OFF 0x204 +#endif + +#endif /* __IMX8M_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx8q.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8q.h new file mode 100644 index 0000000..b085e62 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8q.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + */ + +#ifndef __IMX8Q_H__ +#define __IMX8Q_H__ + +#define GICD_BASE 0x51a00000 +#define GICR_BASE 0x51b00000 +#define UART0_BASE 0x5a060000 +#define UART1_BASE 0x5a070000 +#define UART2_BASE 0x5a080000 +#define UART3_BASE 0x5a090000 +#define UART4_BASE 0x5a0a0000 +#define CAAM_BASE 0x31400000 +#define CAAM_SIZE 0x40000 +#define SC_IPC_BASE_SECURE 0x5d1b0000 +#define SC_IPC_SIZE 0x10000 + +#endif /* __IMX8Q_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp-crm.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp-crm.h new file mode 100644 index 0000000..1882b54 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp-crm.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + */ +#ifndef __IMX8ULP_CRM_H__ +#define __IMX8ULP_CRM_H__ + +#include + +#define PCC_CGC_BIT_SHIFT 30 +#define PCC_ENABLE_CLOCK BIT32(PCC_CGC_BIT_SHIFT) +#define PCC_CAAM 0xB8 + +#endif /* __IMX8ULP_CRM_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp.h new file mode 100644 index 0000000..7fe824b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx8ulp.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + */ +#ifndef __IMX8ULP_H__ +#define __IMX8ULP_H__ + +#include + +#define GICD_BASE 0x2d400000 +#define GICR_BASE 0x2d440000 +#define UART4_BASE 0x29390000 +#define UART5_BASE 0x293a0000 +#define CAAM_BASE 0x292e0000 +#define CAAM_SIZE 0x10000 +#define PCC3_BASE 0x292d0000 +#define PCC3_SIZE 0x1000 +#define AIPS3_BASE 0x29000000 +#define AIPS3_SIZE 0x400000 +#define SECMEM_BASE 0x00100000 +#define SECMEM_SIZE 0x80000 +#define MU_BASE 0x27020000 +#define MU_SIZE 0x10000 + +#endif /* __IMX8ULP_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/registers/imx93.h b/optee/optee_os/core/arch/arm/plat-imx/registers/imx93.h new file mode 100644 index 0000000..e916075 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/registers/imx93.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ +#ifndef __IMX93_H__ +#define __IMX93_H__ + +#define GICD_BASE 0x48000000 +#define GICR_BASE 0x48040000 + +#define UART1_BASE 0x44380000 +#define MU_BASE 0x47520000 +#define MU_SIZE 0x10000 + +#endif /* __IMX93_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-imx/sm_platform_handler.c b/optee/optee_os/core/arch/arm/plat-imx/sm_platform_handler.c new file mode 100644 index 0000000..0828891 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/sm_platform_handler.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + */ + +#include +#include +#include +#include +#include "imx_pl310.h" + +#define IMX_SIP_PL310_ENABLE 1 +#define IMX_SIP_PL310_DISABLE 2 +#define IMX_SIP_PL310_ENABLE_WRITEBACK 3 +#define IMX_SIP_PL310_DISABLE_WRITEBACK 4 +#define IMX_SIP_PL310_ENABLE_WFLZ 5 + +static enum sm_handler_ret imx_sip_handler(struct thread_smc_args *smc_args) +{ + uint16_t sip_func = OPTEE_SMC_FUNC_NUM(smc_args->a0); + + switch (sip_func) { +#ifdef CFG_PL310_SIP_PROTOCOL + case IMX_SIP_PL310_ENABLE: + smc_args->a0 = pl310_enable(); + break; + case IMX_SIP_PL310_DISABLE: + smc_args->a0 = pl310_disable(); + break; + case IMX_SIP_PL310_ENABLE_WRITEBACK: + smc_args->a0 = pl310_enable_writeback(); + break; + case IMX_SIP_PL310_DISABLE_WRITEBACK: + smc_args->a0 = pl310_disable_writeback(); + break; + case IMX_SIP_PL310_ENABLE_WFLZ: + smc_args->a0 = pl310_enable_wflz(); + break; +#endif + default: + EMSG("Invalid SIP function code: 0x%x", sip_func); + smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD; + break; + } + + return SM_HANDLER_SMC_HANDLED; +} + +enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) +{ + uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); + uint16_t smc_owner = OPTEE_SMC_OWNER_NUM(*nsec_r0); + + switch (smc_owner) { + case OPTEE_SMC_OWNER_SIP: + return imx_sip_handler((struct thread_smc_args *)nsec_r0); + default: + return SM_HANDLER_PENDING_SMC; + } +} diff --git a/optee/optee_os/core/arch/arm/plat-imx/sub.mk b/optee/optee_os/core/arch/arm/plat-imx/sub.mk new file mode 100644 index 0000000..77dc24e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/sub.mk @@ -0,0 +1,24 @@ +global-incdirs-y += . +srcs-y += main.c imx-common.c + +srcs-$(CFG_MX6)$(CFG_MX7) += imx_src.c mmdc.c + +srcs-$(CFG_PL310) += imx_pl310.c +ifeq ($(CFG_PSCI_ARM32),y) +$(call force,CFG_PM_ARM32,y) +asm-defines-y += imx_pm_asm_defines.c +endif + +ifneq (,$(filter y, $(CFG_MX6Q) $(CFG_MX6QP) $(CFG_MX6D) $(CFG_MX6DL) \ + $(CFG_MX6S) $(CFG_MX6SL) $(CFG_MX6SLL) $(CFG_MX6SX))) +srcs-y += a9_plat_init.S +srcs-$(CFG_SM_PLATFORM_HANDLER) += sm_platform_handler.c +endif + +ifneq (,$(filter y, $(CFG_MX7) $(CFG_MX7ULP) $(CFG_MX6UL) $(CFG_MX6ULL))) +srcs-y += a7_plat_init.S +endif + +subdirs-$(CFG_PSCI_ARM32) += pm + +srcs-$(CFG_TZC380) += tzc380.c diff --git a/optee/optee_os/core/arch/arm/plat-imx/tzc380.c b/optee/optee_os/core/arch/arm/plat-imx/tzc380.c new file mode 100644 index 0000000..ecc545b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-imx/tzc380.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Pengutronix + * All rights reserved. + * Copyright 2023 NXP + * + * Rouven Czerwinski + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * TZASC2_BASE is asserted non null when used. + * This is needed to compile the code for i.MX6UL/L + * and i.MX8MQ. + */ +#ifndef TZASC2_BASE +#define TZASC2_BASE 0 +#else +register_phys_mem(MEM_AREA_IO_SEC, TZASC2_BASE, TZASC_SIZE); +#endif + +register_phys_mem(MEM_AREA_IO_SEC, TZASC_BASE, TZASC_SIZE); + +static int imx_tzc_auto_configure(vaddr_t addr, vaddr_t rsize, uint32_t attr, + uint8_t region) +{ + vaddr_t addr_imx = 0; + + /* + * On 8mscale platforms, the TZASC controller for the DRAM protection, + * has the memory regions starting at address 0x0 instead of the DRAM + * base address (0x40000000) + */ + if (IS_ENABLED(CFG_MX8M)) + addr_imx = addr - CFG_DRAM_BASE; + else + addr_imx = addr; + + return tzc_auto_configure(addr_imx, rsize, attr, region); +} + +static TEE_Result imx_configure_tzasc(void) +{ + vaddr_t addr[2] = {0}; + int end = 1; + int i = 0; + + addr[0] = core_mmu_get_va(TZASC_BASE, MEM_AREA_IO_SEC, 1); + + if (IS_ENABLED(CFG_MX6Q) || IS_ENABLED(CFG_MX6D) || + IS_ENABLED(CFG_MX6DL)) { + assert(TZASC2_BASE != 0); + addr[1] = core_mmu_get_va(TZASC2_BASE, MEM_AREA_IO_SEC, 1); + end = 2; + } + + for (i = 0; i < end; i++) { + uint8_t region = 1; + + tzc_init(addr[i]); + + region = imx_tzc_auto_configure(CFG_DRAM_BASE, CFG_DDR_SIZE, + TZC_ATTR_SP_NS_RW, region); + region = imx_tzc_auto_configure(CFG_TZDRAM_START, + CFG_TZDRAM_SIZE, + TZC_ATTR_SP_S_RW, region); + region = imx_tzc_auto_configure(CFG_SHMEM_START, CFG_SHMEM_SIZE, + TZC_ATTR_SP_ALL, region); + + if (tzc_regions_lockdown() != TEE_SUCCESS) + panic("Region lockdown failed!"); + + tzc_dump_state(); + } + return TEE_SUCCESS; +} + +static TEE_Result +pm_enter_resume(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *pm_handle __unused) +{ + if (op == PM_OP_RESUME) + return imx_configure_tzasc(); + + return TEE_SUCCESS; +} + +static TEE_Result tzasc_init(void) +{ + register_pm_driver_cb(pm_enter_resume, NULL, "imx-tzasc"); + + return imx_configure_tzasc(); +} +driver_init(tzasc_init); diff --git a/optee/optee_os/core/arch/arm/plat-k3/conf.mk b/optee/optee_os/core/arch/arm/plat-k3/conf.mk new file mode 100644 index 0000000..eb3da41 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/conf.mk @@ -0,0 +1,34 @@ +CFG_WITH_STATS ?= y +CFG_CRYPTO_WITH_CE ?= y +CFG_CONSOLE_UART ?= 0 + +CFG_TZDRAM_START ?= 0x9e800000 +CFG_TZDRAM_SIZE ?= 0x01400000 # 20MB +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) +CFG_SHMEM_SIZE ?= 0x00400000 # 4MB + +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_8250_UART,y) +$(call force,CFG_HWSUPP_MEM_PERM_PXN,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_GIC,y) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_K3_OTP_KEYWRITING,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) + +ifneq (,$(filter ${PLATFORM_FLAVOR},am65x j721e j784s4 am64x am62x)) +CFG_WITH_SOFTWARE_PRNG ?= n +else +$(call force,CFG_WITH_SOFTWARE_PRNG,y) +endif + +ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) +$(call force,CFG_SA2UL,y) +CFG_HWRNG_QUALITY ?= 1024 +CFG_HWRNG_PTA ?= y +endif + +include core/arch/arm/cpu/cortex-armv8-0.mk diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c b/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c new file mode 100644 index 0000000..612c70b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Texas Instruments K3 SA2UL Driver + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * Andrew Davis + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sa2ul.h" + +#define SA2UL_ES 0x0008 +#define SA2UL_ES_TRNG BIT(3) +#define SA2UL_EEC 0x1000 +#define SA2UL_EEC_TRNG BIT(3) + +#define FW_ENABLE_REGION 0x0a +#define FW_BACKGROUND_REGION BIT(8) +#define FW_BIG_ARM_PRIVID 0x01 +#define FW_WILDCARD_PRIVID 0xc3 +#define FW_SECURE_ONLY GENMASK_32(8, 0) +#define FW_NON_SECURE GENMASK_32(16, 0) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SA2UL_BASE, SA2UL_REG_SIZE); + +static TEE_Result sa2ul_init(void) +{ + vaddr_t sa2ul = (vaddr_t)phys_to_virt(SA2UL_BASE, MEM_AREA_IO_SEC, + RNG_REG_SIZE); + uint16_t fwl_id = SA2UL_TI_SCI_FW_ID; + uint16_t sa2ul_region = SA2UL_TI_SCI_FW_RGN_ID; + uint16_t rng_region = RNG_TI_SCI_FW_RGN_ID; + uint8_t owner_index = OPTEE_HOST_ID; + uint8_t owner_privid = 0; + uint16_t owner_permission_bits = 0; + uint32_t control = 0; + uint32_t permissions[FWL_MAX_PRIVID_SLOTS] = { }; + uint64_t start_address = 0; + uint64_t end_address = 0; + uint32_t val = 0; + TEE_Result result = TEE_SUCCESS; + int ret = 0; + + if (SA2UL_TI_SCI_DEV_ID != -1) { + /* Power on the SA2UL device */ + ret = ti_sci_device_get(SA2UL_TI_SCI_DEV_ID); + if (ret) { + EMSG("Failed to get SA2UL device"); + return TEE_ERROR_GENERIC; + } + } + + IMSG("Activated SA2UL device"); + + /* Try to claim the SA2UL firewall for ourselves */ + ret = ti_sci_change_fwl_owner(fwl_id, sa2ul_region, owner_index, + &owner_privid, &owner_permission_bits); + if (ret) { + /* + * This is not fatal, it just means we are on an HS device + * where the DMSC already owns the SA2UL. On GP we need + * to do additional setup for access permissions below. + */ + DMSG("Could not change SA2UL firewall owner"); + } else { + IMSG("Fixing SA2UL firewall owner for GP device"); + + /* Get current SA2UL firewall configuration */ + ret = ti_sci_get_fwl_region(fwl_id, sa2ul_region, 1, + &control, permissions, + &start_address, &end_address); + if (ret) { + EMSG("Could not get firewall region information"); + return TEE_ERROR_GENERIC; + } + + /* Modify SA2UL firewall to allow all others access*/ + control = FW_BACKGROUND_REGION | FW_ENABLE_REGION; + permissions[0] = (FW_WILDCARD_PRIVID << 16) | FW_NON_SECURE; + ret = ti_sci_set_fwl_region(fwl_id, sa2ul_region, 1, + control, permissions, + 0x0, UINT32_MAX); + if (ret) { + EMSG("Could not set firewall region information"); + return TEE_ERROR_GENERIC; + } + } + + /* Claim the TRNG firewall for ourselves */ + ret = ti_sci_change_fwl_owner(fwl_id, rng_region, owner_index, + &owner_privid, &owner_permission_bits); + if (ret) { + EMSG("Could not change TRNG firewall owner"); + return TEE_ERROR_GENERIC; + } + + /* Get current TRNG firewall configuration */ + ret = ti_sci_get_fwl_region(fwl_id, rng_region, 1, + &control, permissions, + &start_address, &end_address); + if (ret) { + EMSG("Could not get firewall region information"); + return TEE_ERROR_GENERIC; + } + + /* Modify TRNG firewall to block all others access */ + control = FW_ENABLE_REGION; + permissions[0] = (FW_BIG_ARM_PRIVID << 16) | FW_SECURE_ONLY; + start_address = RNG_BASE; + end_address = RNG_BASE + RNG_REG_SIZE - 1; + ret = ti_sci_set_fwl_region(fwl_id, rng_region, 1, + control, permissions, + start_address, end_address); + if (ret) { + EMSG("Could not set firewall region information"); + return TEE_ERROR_GENERIC; + } + + IMSG("Enabled firewalls for SA2UL TRNG device"); + + /* Enable RNG engine in SA2UL if not already enabled */ + val = io_read32(sa2ul + SA2UL_ES); + if (!(val & SA2UL_ES_TRNG)) { + IMSG("Enabling SA2UL TRNG engine"); + io_setbits32(sa2ul + SA2UL_EEC, SA2UL_EEC_TRNG); + } + + /* Initialize the RNG Module */ + result = sa2ul_rng_init(); + if (result != TEE_SUCCESS) + return result; + + IMSG("SA2UL Drivers initialized"); + + return TEE_SUCCESS; +} +driver_init(sa2ul_init); diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.h b/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.h new file mode 100644 index 0000000..58a3eec --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Texas Instruments K3 SA2UL Driver + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * Andrew Davis + */ + +#ifndef __DRIVERS_SA2UL_H +#define __DRIVERS_SA2UL_H + +#include + +TEE_Result sa2ul_rng_init(void); + +#endif /* __DRIVERS_SA2UL_H */ diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c b/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c new file mode 100644 index 0000000..1684bff --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/sa2ul_rng.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Texas Instruments K3 SA2UL RNG Driver + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * Andrew Davis + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sa2ul.h" + +#define RNG_OUTPUT_0 0x00 +#define RNG_OUTPUT_1 0x04 +#define RNG_OUTPUT_2 0x08 +#define RNG_OUTPUT_3 0x0C +#define RNG_STATUS 0x10 +#define RNG_READY BIT(0) +#define SHUTDOWN_OFLO BIT(1) +#define RNG_INTACK 0x10 +#define RNG_CONTROL 0x14 +#define ENABLE_TRNG BIT(10) +#define RNG_CONFIG 0x18 +#define RNG_ALARMCNT 0x1C +#define RNG_FROENABLE 0x20 +#define RNG_FRODETUNE 0x24 +#define RNG_ALARMMASK 0x28 +#define RNG_ALARMSTOP 0x2C +#define RNG_OPTIONS 0x78 +#define RNG_EIP_REV 0x7C + +#define RNG_CONTROL_STARTUP_CYCLES_SHIFT 16 +#define RNG_CONTROL_STARTUP_CYCLES_MASK GENMASK_32(31, 16) + +#define RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT 16 +#define RNG_CONFIG_MAX_REFIL_CYCLES_MASK GENMASK_32(31, 16) +#define RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT 0 +#define RNG_CONFIG_MIN_REFIL_CYCLES_MASK GENMASK_32(7, 0) + +#define RNG_ALARMCNT_ALARM_TH_SHIFT 0 +#define RNG_ALARMCNT_ALARM_TH_MASK GENMASK_32(7, 0) +#define RNG_ALARMCNT_SHUTDOWN_TH_SHIFT 16 +#define RNG_ALARMCNT_SHUTDOWN_TH_MASK GENMASK_32(20, 16) + +#define RNG_CONTROL_STARTUP_CYCLES 0xff +#define RNG_CONFIG_MIN_REFIL_CYCLES 0x5 +#define RNG_CONFIG_MAX_REFIL_CYCLES 0x22 +#define RNG_ALARM_THRESHOLD 0xff +#define RNG_SHUTDOWN_THRESHOLD 0x4 + +#define RNG_FRO_MASK GENMASK_32(23, 0) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); + +static unsigned int rng_lock = SPINLOCK_UNLOCK; +static vaddr_t rng; + +static void sa2ul_rng_read128(uint32_t *word0, uint32_t *word1, + uint32_t *word2, uint32_t *word3) +{ + /* Is the result ready (available)? */ + while (!(io_read32(rng + RNG_STATUS) & RNG_READY)) { + /* Is the shutdown threshold reached? */ + if (io_read32(rng + RNG_STATUS) & SHUTDOWN_OFLO) { + uint32_t alarm = io_read32(rng + RNG_ALARMSTOP); + uint32_t tune = io_read32(rng + RNG_FRODETUNE); + + /* Clear the alarm events */ + io_write32(rng + RNG_ALARMMASK, 0x0); + io_write32(rng + RNG_ALARMSTOP, 0x0); + /* De-tune offending FROs */ + io_write32(rng + RNG_FRODETUNE, tune ^ alarm); + /* Re-enable the shut down FROs */ + io_write32(rng + RNG_FROENABLE, RNG_FRO_MASK); + /* Clear the shutdown overflow event */ + io_write32(rng + RNG_INTACK, SHUTDOWN_OFLO); + + DMSG("Fixed FRO shutdown"); + } + } + /* Read random value */ + *word0 = io_read32(rng + RNG_OUTPUT_0); + *word1 = io_read32(rng + RNG_OUTPUT_1); + *word2 = io_read32(rng + RNG_OUTPUT_2); + *word3 = io_read32(rng + RNG_OUTPUT_3); + /* Acknowledge read complete */ + io_write32(rng + RNG_INTACK, RNG_READY); +} + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + static union { + uint32_t val[4]; + uint8_t byte[16]; + } fifo; + static size_t fifo_pos; + uint8_t *buffer = buf; + size_t buffer_pos = 0; + + while (buffer_pos < len) { + uint32_t exceptions = cpu_spin_lock_xsave(&rng_lock); + + /* Refill our FIFO */ + if (fifo_pos == 0) + sa2ul_rng_read128(&fifo.val[0], &fifo.val[1], + &fifo.val[2], &fifo.val[3]); + + buffer[buffer_pos++] = fifo.byte[fifo_pos++]; + fifo_pos %= 16; + + cpu_spin_unlock_xrestore(&rng_lock, exceptions); + } + + return TEE_SUCCESS; +} + +TEE_Result sa2ul_rng_init(void) +{ + uint32_t val = 0; + + rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE); + + /* Ensure initial latency */ + val |= RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; + val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT; + io_write32(rng + RNG_CONFIG, val); + + /* Configure the desired FROs */ + io_write32(rng + RNG_FRODETUNE, 0x0); + + /* Enable all FROs */ + io_write32(rng + RNG_FROENABLE, 0xffffff); + + io_write32(rng + RNG_CONTROL, ENABLE_TRNG); + + IMSG("SA2UL TRNG initialized"); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.c b/optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.c new file mode 100644 index 0000000..3961d72 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Texas Instruments K3 Secure Proxy Driver + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * Manorit Chawdhry + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sec_proxy.h" + +/* SEC PROXY RT THREAD STATUS */ +#define RT_THREAD_STATUS_REG 0x0 +#define RT_THREAD_STATUS_ERROR_MASK BIT(31) +#define RT_THREAD_STATUS_CUR_CNT_MASK GENMASK_32(7, 0) + +/* SEC PROXY SCFG THREAD CTRL */ +#define SCFG_THREAD_CTRL_REG 0x1000 +#define SCFG_THREAD_CTRL_DIR_SHIFT 31 +#define SCFG_THREAD_CTRL_DIR_MASK BIT(31) + +/* SECURE PROXY GENERIC HELPERS */ +enum threads { + SEC_PROXY_TX_THREAD, + SEC_PROXY_RX_THREAD, + SEC_PROXY_MAX_THREADS +}; + +#define SEC_PROXY_THREAD(base, x) ((base) + (0x1000 * (x))) +#define SEC_PROXY_DATA_START_OFFS 0x4 +#define SEC_PROXY_DATA_END_OFFS 0x3c + +#define THREAD_DIR_TX (0) +#define THREAD_DIR_RX (1) + +/** + * struct k3_sec_proxy_thread - Description of a Secure Proxy Thread + * @id: Thread ID + * @data: Thread Data path region for target + * @scfg: Secure Config Region for Thread + * @rt: RealTime Region for Thread + */ +struct k3_sec_proxy_thread { + const char *name; + vaddr_t data; + vaddr_t scfg; + vaddr_t rt; +} spts[SEC_PROXY_MAX_THREADS]; + +/** + * k3_sec_proxy_verify_thread() - Verify thread status before + * sending/receiving data + * @dir: Direction of the thread + */ +static TEE_Result k3_sec_proxy_verify_thread(uint32_t dir) +{ + struct k3_sec_proxy_thread *spt = &spts[dir]; + uint64_t timeout = 0; + uint32_t val = 0; + unsigned int retry = 2; + + FMSG("Check for thread corruption"); + val = io_read32(spt->rt + RT_THREAD_STATUS_REG); + + /* Check for any errors already available */ + while ((val & RT_THREAD_STATUS_ERROR_MASK) && retry--) { + if (!retry) { + EMSG("Thread %s is corrupted, cannot send data.", + spt->name); + return TEE_ERROR_BAD_STATE; + } + + /* Write Bit 0 to this location */ + IMSG("Resetting proxy thread %s", spt->name); + val ^= RT_THREAD_STATUS_ERROR_MASK; + io_write32(spt->rt + RT_THREAD_STATUS_REG, val); + } + + FMSG("Check for thread direction"); + /* Make sure thread is configured for right direction */ + if ((io_read32(spt->scfg + SCFG_THREAD_CTRL_REG) & + SCFG_THREAD_CTRL_DIR_MASK) >> SCFG_THREAD_CTRL_DIR_SHIFT != dir) { + if (dir == SEC_PROXY_TX_THREAD) + EMSG("Trying to receive data on tx Thread %s", + spt->name); + else + EMSG("Trying to send data on rx Thread %s", spt->name); + return TEE_ERROR_COMMUNICATION; + } + + FMSG("Check for thread queue"); + /* Check the message queue before sending/receiving data */ + timeout = timeout_init_us(SEC_PROXY_TIMEOUT_US); + while (!(io_read32(spt->rt + RT_THREAD_STATUS_REG) & + RT_THREAD_STATUS_CUR_CNT_MASK)) { + DMSG("Waiting for thread %s to %s", spt->name, + (dir == THREAD_DIR_TX) ? "empty" : "fill"); + if (timeout_elapsed(timeout)) { + EMSG("Queue is busy"); + return TEE_ERROR_BUSY; + } + } + + FMSG("Success"); + return TEE_SUCCESS; +} + +/** + * k3_sec_proxy_send() - Send data over a Secure Proxy thread + * @msg: Pointer to k3_sec_proxy_msg + */ +TEE_Result k3_sec_proxy_send(const struct k3_sec_proxy_msg *msg) +{ + struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_TX_THREAD]; + int num_words = 0; + int trail_bytes = 0; + int i = 0; + uintptr_t data_reg = 0; + uint32_t data_word = 0; + TEE_Result ret = TEE_SUCCESS; + + FMSG("Verifying the thread"); + ret = k3_sec_proxy_verify_thread(THREAD_DIR_TX); + if (ret) { + EMSG("Thread %s verification failed. ret = %d", spt->name, ret); + return ret; + } + + /* Check the message size. */ + if (msg->len > SEC_PROXY_MAX_MSG_SIZE) { + EMSG("Thread %s message length %zu > max msg size %d", + spt->name, msg->len, SEC_PROXY_MAX_MSG_SIZE); + return TEE_ERROR_BAD_STATE; + } + + /* Send the message */ + data_reg = spt->data + SEC_PROXY_DATA_START_OFFS; + num_words = msg->len / sizeof(uint32_t); + for (i = 0; i < num_words; i++) { + memcpy(&data_word, &msg->buf[i * 4], sizeof(uint32_t)); + io_write32(data_reg, data_word); + data_reg += sizeof(uint32_t); + } + + trail_bytes = msg->len % sizeof(uint32_t); + if (trail_bytes) { + uint32_t data_trail = 0; + + i = msg->len - trail_bytes; + while (trail_bytes--) { + data_trail <<= 8; + data_trail |= msg->buf[i++]; + } + + io_write32(data_reg, data_trail); + data_reg += sizeof(uint32_t); + } + + /* + * 'data_reg' indicates next register to write. If we did not already + * write on tx complete reg(last reg), we must do so for transmit + */ + if (data_reg <= (spt->data + SEC_PROXY_DATA_END_OFFS)) + io_write32(spt->data + SEC_PROXY_DATA_END_OFFS, 0); + + return TEE_SUCCESS; +} + +/** + * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread + * @msg: Pointer to k3_sec_proxy_msg + */ +TEE_Result k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg) +{ + struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_RX_THREAD]; + int num_words = 0; + int i = 0; + int trail_bytes = 0; + uint32_t data_trail = 0; + uint32_t data_word = 0; + uintptr_t data_reg = 0; + TEE_Result ret = TEE_SUCCESS; + + FMSG("Verifying thread"); + ret = k3_sec_proxy_verify_thread(THREAD_DIR_RX); + if (ret) { + EMSG("Thread %s verification failed. ret = %d", spt->name, ret); + return ret; + } + + /* Receive the message */ + data_reg = spt->data + SEC_PROXY_DATA_START_OFFS; + num_words = msg->len / sizeof(uint32_t); + for (i = 0; i < num_words; i++) { + data_word = io_read32(data_reg); + memcpy(&msg->buf[i * 4], &data_word, sizeof(uint32_t)); + data_reg += sizeof(uint32_t); + } + + trail_bytes = msg->len % sizeof(uint32_t); + if (trail_bytes) { + data_trail = io_read32(data_reg); + data_reg += sizeof(uint32_t); + + i = msg->len - trail_bytes; + while (trail_bytes--) { + msg->buf[i] = data_trail & 0xff; + data_trail >>= 8; + } + } + + /* + * 'data_reg' indicates next register to read. If we did not already + * read on rx complete reg(last reg), we must do so for receive + */ + if (data_reg <= (spt->data + SEC_PROXY_DATA_END_OFFS)) + io_read32(spt->data + SEC_PROXY_DATA_END_OFFS); + + return TEE_SUCCESS; +} + +/** + * k3_sec_proxy_init() - Initialize the secure proxy threads + */ +TEE_Result k3_sec_proxy_init(void) +{ + struct k3_sec_proxy_thread *thread; + int rx_thread = SEC_PROXY_RESPONSE_THREAD; + int tx_thread = SEC_PROXY_REQUEST_THREAD; + uint32_t target_data = 0; + uint32_t cfg_scfg = 0; + uint32_t cfg_rt = 0; + + DMSG("tx_thread: %d, rx_thread: %d", tx_thread, rx_thread); + + /* TX_THREAD */ + target_data = SEC_PROXY_THREAD(SEC_PROXY_DATA_BASE, tx_thread); + cfg_scfg = SEC_PROXY_THREAD(SEC_PROXY_SCFG_BASE, tx_thread); + cfg_rt = SEC_PROXY_THREAD(SEC_PROXY_RT_BASE, tx_thread); + + thread = &spts[SEC_PROXY_TX_THREAD]; + thread->name = "SEC_PROXY_LOW_PRIORITY_THREAD"; + + thread->data = core_mmu_get_va(target_data, MEM_AREA_IO_SEC, + SEC_PROXY_DATA_SIZE); + if (!thread->data) + return TEE_ERROR_OUT_OF_MEMORY; + + thread->scfg = core_mmu_get_va(cfg_scfg, MEM_AREA_IO_SEC, + SEC_PROXY_SCFG_SIZE); + if (!thread->scfg) + return TEE_ERROR_OUT_OF_MEMORY; + + thread->rt = core_mmu_get_va(cfg_rt, MEM_AREA_IO_SEC, + SEC_PROXY_RT_SIZE); + if (!thread->rt) + return TEE_ERROR_OUT_OF_MEMORY; + + /* RX_THREAD */ + target_data = SEC_PROXY_THREAD(SEC_PROXY_DATA_BASE, rx_thread); + cfg_scfg = SEC_PROXY_THREAD(SEC_PROXY_SCFG_BASE, rx_thread); + cfg_rt = SEC_PROXY_THREAD(SEC_PROXY_RT_BASE, rx_thread); + + thread = &spts[SEC_PROXY_RX_THREAD]; + thread->name = "SEC_PROXY_RESPONSE_THREAD"; + + thread->data = core_mmu_get_va(target_data, MEM_AREA_IO_SEC, + SEC_PROXY_DATA_SIZE); + if (!thread->data) + return TEE_ERROR_OUT_OF_MEMORY; + + thread->scfg = core_mmu_get_va(cfg_scfg, MEM_AREA_IO_SEC, + SEC_PROXY_SCFG_SIZE); + if (!thread->scfg) + return TEE_ERROR_OUT_OF_MEMORY; + + thread->rt = core_mmu_get_va(cfg_rt, MEM_AREA_IO_SEC, + SEC_PROXY_RT_SIZE); + if (!thread->rt) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.h b/optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.h new file mode 100644 index 0000000..0fdfb65 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/sec_proxy.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Texas Instruments K3 Secure Proxy Driver + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * Manorit Chawdhry + */ + +#ifndef SEC_PROXY_H +#define SEC_PROXY_H + +#include +#include +#include + +#define SEC_PROXY_MAX_MSG_SIZE 60 + +/** + * struct k3_sec_proxy_msg - Secure proxy message structure + * @len: Length of data in the Buffer + * @buf: Buffer pointer + * + * This is the structure for data used in k3_sec_proxy_{send,recv}() + */ +struct k3_sec_proxy_msg { + size_t len; + uint8_t *buf; +}; + +/** + * k3_sec_proxy_send() - Send data over a Secure Proxy thread + * @msg: Pointer to k3_sec_proxy_msg + */ +TEE_Result k3_sec_proxy_send(const struct k3_sec_proxy_msg *msg); + +/** + * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread + * @msg: Pointer to k3_sec_proxy_msg + */ +TEE_Result k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg); + +/** + * k3_sec_proxy_init() - Initialize the secure proxy threads + */ +TEE_Result k3_sec_proxy_init(void); + +#endif /* __SEC_PROXY_H */ diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/sub.mk b/optee/optee_os/core/arch/arm/plat-k3/drivers/sub.mk new file mode 100644 index 0000000..0bcd2ba --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/sub.mk @@ -0,0 +1,4 @@ +srcs-y += sec_proxy.c +srcs-y += ti_sci.c +srcs-$(CFG_SA2UL) += sa2ul.c +srcs-$(CFG_SA2UL) += sa2ul_rng.c diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c new file mode 100644 index 0000000..943b74c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.c @@ -0,0 +1,451 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Texas Instruments System Control Interface Driver + * Based on TF-A implementation + * + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * Manorit Chawdhry + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sec_proxy.h" +#include "ti_sci.h" +#include "ti_sci_protocol.h" + +static uint8_t message_sequence; + +/** + * struct ti_sci_xfer - Structure representing a message flow + * @tx_message: Transmit message + * @rx_message: Receive message + */ +struct ti_sci_xfer { + struct k3_sec_proxy_msg tx_message; + struct k3_sec_proxy_msg rx_message; +}; + +/** + * ti_sci_setup_xfer() - Setup message transfer + * + * @msg_type: Message type + * @msg_flags: Flag to set for the message + * @tx_buf: Buffer to be sent to mailbox channel + * @tx_message_size: transmit message size + * @rx_buf: Buffer to be received from mailbox channel + * @rx_message_size: receive message size + * @xfer: Transfer message + * + * Helper function which is used by various command functions that are + * exposed to clients of this driver for allocating a message traffic event. + * + * Return: 0 if all goes well, else appropriate error message + */ +static int ti_sci_setup_xfer(uint16_t msg_type, uint32_t msg_flags, + void *tx_buf, + size_t tx_message_size, + void *rx_buf, + size_t rx_message_size, + struct ti_sci_xfer *xfer) +{ + struct ti_sci_msg_hdr *hdr = NULL; + + /* Ensure we have sane transfer sizes */ + if (rx_message_size > SEC_PROXY_MAX_MSG_SIZE || + tx_message_size > SEC_PROXY_MAX_MSG_SIZE || + rx_message_size < sizeof(*hdr) || + tx_message_size < sizeof(*hdr)) { + EMSG("Message transfer size not sane"); + return TEE_ERROR_SHORT_BUFFER; + } + + hdr = (struct ti_sci_msg_hdr *)tx_buf; + hdr->seq = ++message_sequence; + hdr->type = msg_type; + hdr->host = OPTEE_HOST_ID; + hdr->flags = msg_flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED; + + xfer->tx_message.buf = tx_buf; + xfer->tx_message.len = tx_message_size; + + xfer->rx_message.buf = rx_buf; + xfer->rx_message.len = rx_message_size; + + return 0; +} + +/** + * ti_sci_get_response() - Receive response from mailbox channel + * + * @xfer: Transfer to initiate and wait for response + * + * Return: 0 if all goes well, else appropriate error message + */ +static inline int ti_sci_get_response(struct ti_sci_xfer *xfer) +{ + struct k3_sec_proxy_msg *msg = &xfer->rx_message; + struct ti_sci_msg_hdr *hdr = NULL; + unsigned int retry = 5; + int ret = 0; + + for (; retry > 0; retry--) { + /* Receive the response */ + ret = k3_sec_proxy_recv(msg); + if (ret) { + EMSG("Message receive failed (%d)", ret); + return ret; + } + + /* msg is updated by Secure Proxy driver */ + hdr = (struct ti_sci_msg_hdr *)msg->buf; + + /* Sanity check for message response */ + if (hdr->seq == message_sequence) + break; + + IMSG("Message with sequence ID %u is not expected", hdr->seq); + } + if (!retry) { + EMSG("Timed out waiting for message"); + return TEE_ERROR_BUSY; + } + + if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK)) { + DMSG("Message not acknowledged"); + return TEE_ERROR_ACCESS_DENIED; + } + + return 0; +} + +/** + * ti_sci_do_xfer() - Do one transfer + * + * @xfer: Transfer to initiate and wait for response + * + * Return: 0 if all goes well, else appropriate error message + */ +static inline int ti_sci_do_xfer(struct ti_sci_xfer *xfer) +{ + struct k3_sec_proxy_msg *msg = &xfer->tx_message; + int ret = 0; + + /* Send the message */ + ret = k3_sec_proxy_send(msg); + if (ret) { + EMSG("Message sending failed (%d)", ret); + return ret; + } + + /* Get the response */ + ret = ti_sci_get_response(xfer); + if (ret) { + if ((TEE_Result)ret != TEE_ERROR_ACCESS_DENIED) + EMSG("Failed to get response (%d)", ret); + return ret; + } + + return 0; +} + +int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info) +{ + struct ti_sci_msg_req_version req = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_VERSION, 0x0, + &req, sizeof(req), + rev_info, sizeof(*rev_info), + &xfer); + if (ret) + return ret; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + return 0; +} + +static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state) +{ + struct ti_sci_msg_req_set_device_state req = { }; + struct ti_sci_msg_resp_set_device_state resp = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) + return ret; + + req.id = id; + req.state = state; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + return 0; +} + +int ti_sci_device_get(uint32_t id) +{ + return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON); +} + +int ti_sci_device_put(uint32_t id) +{ + return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF); +} + +int ti_sci_set_fwl_region(uint16_t fwl_id, uint16_t region, + uint32_t n_permission_regs, uint32_t control, + const uint32_t permissions[FWL_MAX_PRIVID_SLOTS], + uint64_t start_address, uint64_t end_address) +{ + struct ti_sci_msg_req_fwl_set_firewall_region req = { }; + struct ti_sci_msg_resp_fwl_set_firewall_region resp = { }; + struct ti_sci_xfer xfer = { }; + unsigned int i = 0; + int ret = 0; + + assert(n_permission_regs <= FWL_MAX_PRIVID_SLOTS); + + ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_SET, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) + return ret; + + req.fwl_id = fwl_id; + req.region = region; + req.n_permission_regs = n_permission_regs; + req.control = control; + for (i = 0; i < n_permission_regs; i++) + req.permissions[i] = permissions[i]; + req.start_address = start_address; + req.end_address = end_address; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + return 0; +} + +int ti_sci_get_fwl_region(uint16_t fwl_id, uint16_t region, + uint32_t n_permission_regs, uint32_t *control, + uint32_t permissions[FWL_MAX_PRIVID_SLOTS], + uint64_t *start_address, uint64_t *end_address) +{ + struct ti_sci_msg_req_fwl_get_firewall_region req = { }; + struct ti_sci_msg_resp_fwl_get_firewall_region resp = { }; + struct ti_sci_xfer xfer = { }; + unsigned int i = 0; + int ret = 0; + + assert(n_permission_regs <= FWL_MAX_PRIVID_SLOTS); + + ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_GET, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) + return ret; + + req.fwl_id = fwl_id; + req.region = region; + req.n_permission_regs = n_permission_regs; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + *control = resp.control; + for (i = 0; i < n_permission_regs; i++) + permissions[i] = resp.permissions[i]; + *start_address = resp.start_address; + *end_address = resp.end_address; + + return 0; +} + +int ti_sci_change_fwl_owner(uint16_t fwl_id, uint16_t region, + uint8_t owner_index, uint8_t *owner_privid, + uint16_t *owner_permission_bits) +{ + struct ti_sci_msg_req_fwl_change_owner_info req = { }; + struct ti_sci_msg_resp_fwl_change_owner_info resp = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_CHANGE_OWNER, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret) + return ret; + + req.fwl_id = fwl_id; + req.region = region; + req.owner_index = owner_index; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + *owner_privid = resp.owner_privid; + *owner_permission_bits = resp.owner_permission_bits; + + return 0; +} + +int ti_sci_get_dkek(uint8_t sa2ul_instance, + const char *context, const char *label, + uint8_t dkek[SA2UL_DKEK_KEY_LEN]) +{ + struct ti_sci_msg_req_sa2ul_get_dkek req = { }; + struct ti_sci_msg_resp_sa2ul_get_dkek resp = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_SA2UL_GET_DKEK, 0, + &req, sizeof(req), &resp, sizeof(resp), &xfer); + if (ret) + return ret; + + req.sa2ul_instance = sa2ul_instance; + req.kdf_label_len = strlen(label); + req.kdf_context_len = strlen(context); + if (req.kdf_label_len + req.kdf_context_len > + KDF_LABEL_AND_CONTEXT_LEN_MAX) { + EMSG("Context and Label too long"); + return TEE_ERROR_BAD_PARAMETERS; + } + memcpy(req.kdf_label_and_context, label, strlen(label)); + memcpy(req.kdf_label_and_context + strlen(label), context, + strlen(context)); + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + memcpy(dkek, resp.dkek, sizeof(resp.dkek)); + memzero_explicit(&resp, sizeof(resp)); + return 0; +} + +int ti_sci_read_otp_mmr(uint8_t mmr_idx, uint32_t *val) +{ + struct ti_sci_msg_req_read_otp_mmr req = { }; + struct ti_sci_msg_resp_read_otp_mmr resp = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_OTP_MMR, 0, + &req, sizeof(req), &resp, sizeof(resp), &xfer); + if (ret) + goto exit; + + req.mmr_idx = mmr_idx; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + goto exit; + + *val = resp.mmr_val; + +exit: + memzero_explicit(&resp, sizeof(resp)); + return ret; +} + +int ti_sci_write_otp_row(uint8_t row_idx, uint32_t row_val, uint32_t row_mask) +{ + struct ti_sci_msg_req_write_otp_row req = { }; + struct ti_sci_msg_resp_write_otp_row resp = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_WRITE_OTP_ROW, 0, + &req, sizeof(req), &resp, sizeof(resp), &xfer); + if (ret) + goto exit; + + req.row_idx = row_idx; + req.row_val = row_val; + req.row_mask = row_mask; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + goto exit; + + DMSG("resp.row_val: 0x%08x", resp.row_val); + + if (resp.row_val != (req.row_val & req.row_mask)) { + EMSG("Value not written correctly"); + DMSG("req.row_val : 0x%08"PRIx32, req.row_val); + DMSG("req.row_mask: 0x%08"PRIx32, req.row_mask); + ret = TEE_ERROR_BAD_STATE; + } + +exit: + memzero_explicit(&resp, sizeof(resp)); + memzero_explicit(&req, sizeof(req)); + return ret; +} + +int ti_sci_lock_otp_row(uint8_t row_idx, uint8_t hw_write_lock, + uint8_t hw_read_lock, uint8_t row_soft_lock) +{ + struct ti_sci_msg_req_lock_otp_row req = { }; + struct ti_sci_msg_resp_lock_otp_row resp = { }; + struct ti_sci_xfer xfer = { }; + int ret = 0; + + ret = ti_sci_setup_xfer(TI_SCI_MSG_LOCK_OTP_ROW, 0, + &req, sizeof(req), &resp, sizeof(resp), &xfer); + if (ret) + return ret; + + req.row_idx = row_idx; + req.hw_write_lock = hw_write_lock; + req.hw_read_lock = hw_read_lock; + req.row_soft_lock = row_soft_lock; + + ret = ti_sci_do_xfer(&xfer); + if (ret) + return ret; + + return 0; +} + +int ti_sci_init(void) +{ + struct ti_sci_msg_resp_version rev_info = { }; + int ret = 0; + + ret = ti_sci_get_revision(&rev_info); + if (ret) { + EMSG("Unable to communicate with control firmware (%d)", ret); + return ret; + } + + IMSG("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')", + rev_info.abi_major, rev_info.abi_minor, + rev_info.firmware_revision, + rev_info.firmware_description); + + return 0; +} diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h new file mode 100644 index 0000000..1a2b9ea --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci.h @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ + * Manorit Chawdhry + */ + +#ifndef TI_SCI_H +#define TI_SCI_H + +#include +#include +#include + +#include "ti_sci_protocol.h" + +/** + * ti_sci_get_revision() - Get the revision of the SCI entity + * + * Updates the SCI information in the internal data structure. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info); + +/** + * Device control operations + * + * - ti_sci_device_get - Get access to device managed by TISCI + * - ti_sci_device_put - Release access to device managed by TISCI + * + * NOTE: for all these functions, the following are generic in nature: + * @id: Device Identifier + * + * Returns 0 for successful request, else returns corresponding error message. + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + */ +int ti_sci_device_get(uint32_t id); +int ti_sci_device_put(uint32_t id); + +/** + * ti_sci_set_fwl_region() - Request for configuring a firewall region + * + * @fwl_id: Firewall ID in question. fwl_id is defined in the TRM. + * @region: Region or channel number to set config info. This field + * is unused in case of a simple firewall and must be + * initialized to zero. In case of a region based + * firewall, this field indicates the region in question + * (index starting from 0). In case of a channel based + * firewall, this field indicates the channel in question + * (index starting from 0). + * @n_permission_regs: Number of permission registers to set + * @control: Contents of the firewall CONTROL register to set + * @permissions: Contents of the firewall PERMISSION register to set + * @start_address: Contents of the firewall START_ADDRESS register to set + * @end_address: Contents of the firewall END_ADDRESS register to set + * + * Return: 0 if all went well, else returns appropriate error value. + */ +int ti_sci_set_fwl_region(uint16_t fwl_id, uint16_t region, + uint32_t n_permission_regs, uint32_t control, + const uint32_t permissions[FWL_MAX_PRIVID_SLOTS], + uint64_t start_address, uint64_t end_address); +/** + * ti_sci_cmd_get_fwl_region() - Request for getting a firewall region + * + * @fwl_id: Firewall ID in question. fwl_id is defined in the TRM. + * @region: Region or channel number to set config info. This field + * is unused in case of a simple firewall and must be + * initialized to zero. In case of a region based + * firewall, this field indicates the region in question + * (index starting from 0). In case of a channel based + * firewall, this field indicates the channel in question + * (index starting from 0). + * @n_permission_regs: Region or channel number to set config info + * @control: Contents of the firewall CONTROL register + * @permissions: Contents of the firewall PERMISSION register + * @start_address: Contents of the firewall START_ADDRESS register + * @end_address: Contents of the firewall END_ADDRESS register + * + * Return: 0 if all went well, else returns appropriate error value. + */ +int ti_sci_get_fwl_region(uint16_t fwl_id, uint16_t region, + uint32_t n_permission_regs, uint32_t *control, + uint32_t permissions[FWL_MAX_PRIVID_SLOTS], + uint64_t *start_address, uint64_t *end_address); +/** + * ti_sci_change_fwl_owner() - Request for changing a firewall owner + * + * @fwl_id: Firewall ID in question. fwl_id is defined in the TRM. + * @region: Region or channel number to set config info. This field + * is unused in case of a simple firewall and must be + * initialized to zero. In case of a region based + * firewall, this field indicates the region in question + * (index starting from 0). In case of a channel based + * firewall, this field indicates the channel in question + * (index starting from 0). + * @owner_index: New owner index to transfer ownership to + * @owner_privid: New owner priv-ID returned by DMSC. This field is + * currently initialized to zero by DMSC. + * @owner_permission_bits: New owner permission bits returned by DMSC. This + * field is currently initialized to zero by DMSC. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +int ti_sci_change_fwl_owner(uint16_t fwl_id, uint16_t region, + uint8_t owner_index, uint8_t *owner_privid, + uint16_t *owner_permission_bits); + +/** + * ti_sci_get_dkek() - Get the DKEK + * @sa2ul_instance: SA2UL instance to get key + * @context: Context string input to KDF + * @label: Label string input to KDF + * @dkek: Returns with DKEK populated + * + * Updates the DKEK the internal data structure. + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_get_dkek(uint8_t sa2ul_instance, + const char *context, const char *label, + uint8_t dkek[SA2UL_DKEK_KEY_LEN]); + +/** + * ti_sci_read_otp_mmr() - Get the Extended OTP + * @mmr_idx: 32-bit MMR index + * @val: Value of the 32-bit MMR + * + * Reads the extended OTP bits from efuse + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_read_otp_mmr(uint8_t mmr_idx, uint32_t *val); + +/** + * ti_sci_write_otp_row() - Write the extended OTP row + * @row_idx: Index of the OTP row. Zero indexing + * @row_val: Value to be written + * @row_mask: Mask bits for row_val to be written + * + * Writes a Row in the extended OTP field + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_write_otp_row(uint8_t row_idx, uint32_t row_val, uint32_t row_mask); + +/** + * ti_sci_lock_otp_row - Locking the Extended OTP row + * @row_idx: Index of the OTP row. Zero indexing + * @hw_write_lock: Hardware write lock + * @hw_read_lock: Hardware read lock + * @row_soft_lock: Software write lock + * + * Lockes a Row in the extended OTP field to prevent read/writes + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_lock_otp_row(uint8_t row_idx, uint8_t hw_write_lock, + uint8_t hw_read_lock, uint8_t row_soft_lock); + +/** + * ti_sci_init() - Basic initialization + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_init(void); + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h new file mode 100644 index 0000000..da7803c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h @@ -0,0 +1,382 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2016-2022 Texas Instruments Incorporated - https://www.ti.com/ + * Lokesh Vutla + * Manorit Chawdhry + */ + +#ifndef TI_SCI_PROTOCOL_H +#define TI_SCI_PROTOCOL_H + +#include +#include +#include + +/* Generic Messages */ +#define TI_SCI_MSG_VERSION 0x0002 + +/* Device requests */ +#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 + +/* Security Management Messages */ +#define TI_SCI_MSG_FWL_SET 0x9000 +#define TI_SCI_MSG_FWL_GET 0x9001 +#define TI_SCI_MSG_FWL_CHANGE_OWNER 0x9002 +#define TI_SCI_MSG_SA2UL_GET_DKEK 0x9029 +#define TI_SCI_MSG_READ_OTP_MMR 0x9022 +#define TI_SCI_MSG_WRITE_OTP_ROW 0x9023 +#define TI_SCI_MSG_LOCK_OTP_ROW 0x9024 + +/** + * struct ti_sci_secure_msg_hdr - Secure Message Header for All messages + * and responses + * + * @checksum: Integrity check for HS devices + * @reserved: Reserved for future uses + */ +struct ti_sci_secure_msg_hdr { + uint16_t checksum; + uint16_t reserved; +} __packed; + +/** + * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses + * @type: Type of messages: One of TI_SCI_MSG* values + * @host: Host of the message + * @seq: Message identifier indicating a transfer sequence + * @flags: Flag for the message + */ +struct ti_sci_msg_hdr { + struct ti_sci_secure_msg_hdr sec_hdr; + uint16_t type; + uint8_t host; + uint8_t seq; +#define TI_SCI_MSG_FLAG(val) BIT(val) +#define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0 +#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0) +#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1) +#define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0 +#define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1) + /* Additional Flags */ + uint32_t flags; +} __packed; + +/** + * struct ti_sci_msg_version_req - Request for firmware version information + * @hdr: Generic header + * + * Request for TI_SCI_MSG_VERSION + */ +struct ti_sci_msg_req_version { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * struct ti_sci_msg_resp_version - Response for firmware version information + * @hdr: Generic header + * @firmware_description: String describing the firmware + * @firmware_revision: Firmware revision + * @abi_major: Major version of the ABI that firmware supports + * @abi_minor: Minor version of the ABI that firmware supports + * @sub_version: Sub-version number of the firmware + * @patch_version: Patch-version number of the firmware. + * + * In general, ABI version changes follow the rule that minor version increments + * are backward compatible. Major revision changes in ABI may not be + * backward compatible. + * + * Response to request TI_SCI_MSG_VERSION + */ +struct ti_sci_msg_resp_version { + struct ti_sci_msg_hdr hdr; +#define FIRMWARE_DESCRIPTION_LENGTH 32 + char firmware_description[FIRMWARE_DESCRIPTION_LENGTH]; + uint16_t firmware_revision; + uint8_t abi_major; + uint8_t abi_minor; + uint8_t sub_version; + uint8_t patch_version; +} __packed; + +/** + * struct ti_sci_msg_req_set_device_state - Set the desired state of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @reserved: Reserved space in message, must be 0 for backward compatibility + * @state: The desired state of the device. + * + * Certain flags can also be set to alter the device state: + * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source. + * The meaning of this flag will vary slightly from device to device and from + * SoC to SoC but it generally allows the device to wake the SoC out of deep + * suspend states. + * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device. + * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed + * with STATE_RETENTION or STATE_ON, it will claim the device exclusively. + * If another host already has this device set to STATE_RETENTION or STATE_ON, + * the message will fail. Once successful, other hosts attempting to set + * STATE_RETENTION or STATE_ON will fail. + * + * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + uint32_t id; + uint32_t reserved; + +#define MSG_DEVICE_SW_STATE_AUTO_OFF 0 +#define MSG_DEVICE_SW_STATE_RETENTION 1 +#define MSG_DEVICE_SW_STATE_ON 2 + uint8_t state; +} __packed; + +/** + * struct ti_sci_msg_resp_set_device_state - Response for set device state + * @hdr: Generic header + * + * Response to request TI_SCI_MSG_SET_DEVICE_STATE + */ +struct ti_sci_msg_resp_set_device_state { + struct ti_sci_msg_hdr hdr; +} __packed; + +#define FWL_MAX_PRIVID_SLOTS 3U + +/** + * struct ti_sci_msg_req_fwl_set_firewall_region - Set firewall permissions + * @hdr: Generic Header + * @fwl_id: Firewall ID + * @region: Region or channel number to set config info. + * This field is unused in case of a simple firewall and + * must be initialized to zero. In case of a region based + * firewall, this field indicates the region (index + * starting from 0). In case of a channel based firewall, + * this field indicates the channel (index starting + * from 0). + * @n_permission_regs: Number of permission registers to set + * @control: Contents of the firewall CONTROL register to set + * @permissions: Contents of the firewall PERMISSION register to set + * @start_address: Contents of the firewall START_ADDRESS register to set + * @end_address: Contents of the firewall END_ADDRESS register to set + */ +struct ti_sci_msg_req_fwl_set_firewall_region { + struct ti_sci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint32_t n_permission_regs; + uint32_t control; + uint32_t permissions[FWL_MAX_PRIVID_SLOTS]; + uint64_t start_address; + uint64_t end_address; +} __packed; + +struct ti_sci_msg_resp_fwl_set_firewall_region { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * struct ti_sci_msg_req_fwl_get_firewall_region - Retrieve firewall permissions + * @hdr: Generic Header + * @fwl_id: Firewall ID in question + * @region: Region or channel number to set config info. + * This field is unused in case of a simple firewall and + * must be initialized to zero. In case of a region based + * firewall, this field indicates the region (index + * starting from 0). In case of a channel based firewall, + * this field indicates the channel (index starting + * from 0). + * @n_permission_regs: Number of permission registers to retrieve + */ +struct ti_sci_msg_req_fwl_get_firewall_region { + struct ti_sci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint32_t n_permission_regs; +} __packed; + +/** + * struct ti_sci_msg_resp_fwl_get_firewall_region - Response for retrieving the + * firewall permissions + * + * @hdr: Generic Header + * + * @fwl_id: Firewall ID in question + * @region: Region or channel number to set config info. + * This field is unused in case of a simple firewall and + * must be initialized to zero. In case of a region based + * firewall, this field indicates the region (index + * starting from 0). In case of a channel based firewall, + * this field indicates the channel (index starting + * from 0). + * @n_permission_regs: Number of permission registers retrieved + * @control: Contents of the firewall CONTROL register + * @permissions: Contents of the firewall PERMISSION registers + * @start_address: Contents of the firewall START_ADDRESS register + * @end_address: Contents of the firewall END_ADDRESS register + */ +struct ti_sci_msg_resp_fwl_get_firewall_region { + struct ti_sci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint32_t n_permission_regs; + uint32_t control; + uint32_t permissions[FWL_MAX_PRIVID_SLOTS]; + uint64_t start_address; + uint64_t end_address; +} __packed; + +/** + * struct ti_sci_msg_req_fwl_change_owner_info - Request change firewall owner + * + * @hdr: Generic Header + * + * @fwl_id: Firewall ID in question + * @region: Region or channel number if applicable + * @owner_index: New owner index to transfer ownership to + */ +struct ti_sci_msg_req_fwl_change_owner_info { + struct ti_sci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint8_t owner_index; +} __packed; + +/** + * struct ti_sci_msg_resp_fwl_change_owner_info - Response for change + * firewall owner + * + * @hdr: Generic Header + * + * @fwl_id: Firewall ID specified in request + * @region: Region or channel number specified in request + * @owner_index: Owner index specified in request + * @owner_privid: New owner priv-ID returned by DMSC. + * @owner_permission_bits: New owner permission bits returned by DMSC. + */ +struct ti_sci_msg_resp_fwl_change_owner_info { + struct ti_sci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint8_t owner_index; + uint8_t owner_privid; + uint16_t owner_permission_bits; +} __packed; + +/** + * struct ti_sci_msg_sa2ul_get_dkek_req - Request for DKEK value + * @hdr: Generic header + * @sa2ul_instance: SA2UL instance number - set to 0 + * @kdf_label_len: Length of "Label" input to KDF + * @kdf_context_len: Length of "Context" input to KDF + * @kdf_label_and_context: "Label" and "Context" bytes + * + * Request for TI_SCI_MSG_SA2UL_GET_DKEK + */ +struct ti_sci_msg_req_sa2ul_get_dkek { + struct ti_sci_msg_hdr hdr; + uint8_t sa2ul_instance; + uint8_t kdf_label_len; + uint8_t kdf_context_len; +#define KDF_LABEL_AND_CONTEXT_LEN_MAX 41 + uint8_t kdf_label_and_context[KDF_LABEL_AND_CONTEXT_LEN_MAX]; +} __packed; + +/** + * struct ti_sci_msg_sa2ul_get_dkek_req - Response for DKEK value + * @hdr: Generic header + * @dkek: Array containing Derived KEK + * + * Response to request TI_SCI_MSG_SA2UL_GET_DKEK + */ +struct ti_sci_msg_resp_sa2ul_get_dkek { + struct ti_sci_msg_hdr hdr; +#define SA2UL_DKEK_KEY_LEN 32 + uint8_t dkek[SA2UL_DKEK_KEY_LEN]; +} __packed; + +/** + * struct ti_sci_msg_resp_read_otp_mmr - Request for reading extended OTP + * @hdr: Generic header + * @mmr_idx: Index of 32 bit MMR + * + * Request for TI_SCI_MSG_READ_OTP_MMR + */ +struct ti_sci_msg_req_read_otp_mmr { + struct ti_sci_msg_hdr hdr; + uint8_t mmr_idx; +} __packed; + +/** + * struct ti_sci_msg_resp_read_otp_mmr - Response for reading extended OTP + * @hdr: Generic header + * @mmr_val: Value written in the OTP + * + * Response to request TI_SCI_MSG_READ_OTP_MMR + */ +struct ti_sci_msg_resp_read_otp_mmr { + struct ti_sci_msg_hdr hdr; + uint32_t mmr_val; +} __packed; + +/** + * struct ti_sci_msg_req_write_otp_row - Request for writing Extended OTP + * @hdr: Generic header + * @row_idx: Index of the OTP row. Zero indexing + * @row_val: Value to be written + * @row_mask: Mask bits for row_val to be written + * + * Request for TI_SCI_MSG_WRITE_OTP_ROW + */ +struct ti_sci_msg_req_write_otp_row { + struct ti_sci_msg_hdr hdr; + uint8_t row_idx; + uint32_t row_val; + uint32_t row_mask; +} __packed; + +/** + * struct ti_sci_msg_resp_write_otp_row - Response for writing Extended OTP + * @hdr: Generic header + * @row_val: Value that is written + * + * Response to request TI_SCI_MSG_WRITE_OTP_ROW + */ +struct ti_sci_msg_resp_write_otp_row { + struct ti_sci_msg_hdr hdr; + uint32_t row_val; +} __packed; + +/** + * struct ti_sci_msg_req_lock_otp_row - Request for Lock OTP row + * @hdr: Generic header + * @row_idx: Index of the OTP row. Zero indexing + * @hw_write_lock: 0x5A indicates row will be write protected + * @hw_read_lock: 0x5A indicates row will be read protected + * @row_soft_lock: Software write lock + * + * Request for TI_SCI_MSG_LOCK_OTP_ROW + */ +struct ti_sci_msg_req_lock_otp_row { + struct ti_sci_msg_hdr hdr; + uint8_t row_idx; + uint8_t hw_write_lock; + uint8_t hw_read_lock; + uint8_t row_soft_lock; +} __packed; + +/** + * struct ti_sci_msg_resp_lock_otp_row - Response for Lock OTP row + * @hdr: Generic header + * + * Response to request TI_SCI_MSG_LOCK_OTP_ROW + */ +struct ti_sci_msg_resp_lock_otp_row { + struct ti_sci_msg_hdr hdr; +} __packed; + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-k3/main.c b/optee/optee_os/core/arch/arm/plat-k3/main.c new file mode 100644 index 0000000..53d57b1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/main.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct gic_data gic_data; +static struct serial8250_uart_data console_data; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GICC_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GICD_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, + SERIAL8250_UART_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_DATA_BASE, + SEC_PROXY_DATA_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_SCFG_BASE, + SEC_PROXY_SCFG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE); +register_ddr(DRAM0_BASE, DRAM0_SIZE); +register_ddr(DRAM1_BASE, DRAM1_SIZE); + +void main_init_gic(void) +{ + gic_init_base_addr(&gic_data, GICC_BASE, GICD_BASE); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +static TEE_Result init_ti_sci(void) +{ + TEE_Result ret = TEE_SUCCESS; + + ret = k3_sec_proxy_init(); + if (ret != TEE_SUCCESS) + return ret; + + ret = ti_sci_init(); + if (ret) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} +service_init(init_ti_sci); + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + uint8_t dkek[SA2UL_DKEK_KEY_LEN] = { }; + int ret = 0; + + assert(SA2UL_DKEK_KEY_LEN >= HW_UNIQUE_KEY_LENGTH); + + ret = ti_sci_get_dkek(0, "OP-TEE", "DKEK", dkek); + if (ret) { + EMSG("Could not get HUK"); + return TEE_ERROR_SECURITY; + } + + memcpy(&hwkey->data[0], dkek, sizeof(hwkey->data)); + memzero_explicit(&dkek, sizeof(dkek)); + + IMSG("HUK Initialized"); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/arch/arm/plat-k3/platform_config.h b/optee/optee_os/core/arch/arm/plat-k3/platform_config.h new file mode 100644 index 0000000..cffca0a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/platform_config.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +#define UART0_BASE 0x02800000 + +#define CONSOLE_UART_BASE (UART0_BASE + CFG_CONSOLE_UART * 0x10000) +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 48000000 + +#define DRAM0_BASE 0x80000000 +#define DRAM0_SIZE 0x80000000 + +#define DRAM1_BASE 0x880000000 +#define DRAM1_SIZE 0x780000000 + +#define SCU_BASE 0x01800000 +#if defined(PLATFORM_FLAVOR_j721e) || defined(PLATFORM_FLAVOR_j784s4) +#define GICC_OFFSET 0x100000 +#define GICC_SIZE 0x100000 +#define GICD_OFFSET 0x0 +#define GICD_SIZE 0x10000 +#else +#define GICC_OFFSET 0x80000 +#define GICC_SIZE 0x90000 +#define GICD_OFFSET 0x0 +#define GICD_SIZE 0x10000 +#endif +#if defined(PLATFORM_FLAVOR_am65x) || defined(PLATFORM_FLAVOR_j721e) || \ + defined(PLATFORM_FLAVOR_j784s4) +#define SEC_PROXY_DATA_BASE 0x32c00000 +#define SEC_PROXY_DATA_SIZE 0x100000 +#define SEC_PROXY_SCFG_BASE 0x32800000 +#define SEC_PROXY_SCFG_SIZE 0x100000 +#define SEC_PROXY_RT_BASE 0x32400000 +#define SEC_PROXY_RT_SIZE 0x100000 +#define SEC_PROXY_RESPONSE_THREAD 6 +#define SEC_PROXY_REQUEST_THREAD 7 +#else +#define SEC_PROXY_DATA_BASE 0x4d000000 +#define SEC_PROXY_DATA_SIZE 0x80000 +#define SEC_PROXY_SCFG_BASE 0x4a400000 +#define SEC_PROXY_SCFG_SIZE 0x80000 +#define SEC_PROXY_RT_BASE 0x4a600000 +#define SEC_PROXY_RT_SIZE 0x80000 +#define SEC_PROXY_RESPONSE_THREAD 10 +#define SEC_PROXY_REQUEST_THREAD 11 +#endif +#define OPTEE_HOST_ID 11 +#define SEC_PROXY_TIMEOUT_US 1000000 +#define GICC_BASE (SCU_BASE + GICC_OFFSET) +#define GICD_BASE (SCU_BASE + GICD_OFFSET) + +/* SA2UL */ +#if defined(PLATFORM_FLAVOR_am65x) +#define SA2UL_BASE 0x04e00000 +#define SA2UL_TI_SCI_DEV_ID 136 +#define SA2UL_TI_SCI_FW_ID 2112 +#define SA2UL_TI_SCI_FW_RGN_ID 0 +#elif defined(PLATFORM_FLAVOR_j721e) +#define SA2UL_BASE 0x40900000 +#define SA2UL_TI_SCI_DEV_ID 265 +#define SA2UL_TI_SCI_FW_ID 1196 +#define SA2UL_TI_SCI_FW_RGN_ID 0 +#elif defined(PLATFORM_FLAVOR_j784s4) +#define SA2UL_BASE 0x40900000 +#define SA2UL_TI_SCI_DEV_ID -1 +#define SA2UL_TI_SCI_FW_ID 1196 +#define SA2UL_TI_SCI_FW_RGN_ID 0 +#elif defined(PLATFORM_FLAVOR_am64x) +#define SA2UL_BASE 0x40900000 +#define SA2UL_TI_SCI_DEV_ID 133 +#define SA2UL_TI_SCI_FW_ID 35 +#define SA2UL_TI_SCI_FW_RGN_ID 0 +#elif defined(PLATFORM_FLAVOR_am62x) +#define SA2UL_BASE 0x40900000 +#define SA2UL_TI_SCI_DEV_ID -1 +#define SA2UL_TI_SCI_FW_ID 66 +#define SA2UL_TI_SCI_FW_RGN_ID 1 +#endif +#define SA2UL_REG_SIZE 0x1000 + +/* RNG */ +#define RNG_BASE (SA2UL_BASE + 0x10000) +#define RNG_REG_SIZE 0x1000 +#if defined(PLATFORM_FLAVOR_am62x) +#define RNG_TI_SCI_FW_RGN_ID 2 +#else +#define RNG_TI_SCI_FW_RGN_ID 3 +#endif + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-k3/sub.mk b/optee/optee_os/core/arch/arm/plat-k3/sub.mk new file mode 100644 index 0000000..9dc7571 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-k3/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +srcs-y += main.c +subdirs-y += drivers diff --git a/optee/optee_os/core/arch/arm/plat-ls/conf.mk b/optee/optee_os/core/arch/arm/plat-ls/conf.mk new file mode 100644 index 0000000..558e471 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ls/conf.mk @@ -0,0 +1,126 @@ +PLATFORM_FLAVOR ?= ls1012ardb + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_GIC,y) +$(call force,CFG_16550_UART,y) +$(call force,CFG_LS,y) + +$(call force,CFG_DRAM0_BASE,0x80000000) +$(call force,CFG_TEE_OS_DRAM0_SIZE,0x4000000) + +ifeq ($(PLATFORM_FLAVOR),ls1012ardb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_DRAM0_SIZE,0x40000000) +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +CFG_NUM_THREADS ?= 2 +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),ls1043ardb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_DRAM0_SIZE,0x80000000) +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),ls1046ardb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_DRAM0_SIZE,0x80000000) +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),ls1088ardb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_DRAM0_SIZE,0x80000000) +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +$(call force,CFG_ARM_GICV3,y) +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),ls2088ardb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_DRAM0_SIZE,0x80000000) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +$(call force,CFG_ARM_GICV3,y) +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),lx2160aqds) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,16) +$(call force,CFG_DRAM0_SIZE,0x80000000) +$(call force,CFG_DRAM1_BASE,0x2080000000) +$(call force,CFG_DRAM1_SIZE,0x1F80000000) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_PL011,y) +$(call force,CFG_CORE_ARM64_PA_BITS,48) +$(call force,CFG_EMBED_DTB,y) +$(call force,CFG_EMBED_DTB_SOURCE_FILE,fsl-lx2160a-qds.dts) +CFG_LS_I2C ?= y +CFG_LS_GPIO ?= y +CFG_LS_DSPI ?= y +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),lx2160ardb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,16) +$(call force,CFG_DRAM0_SIZE,0x80000000) +$(call force,CFG_DRAM1_BASE,0x2080000000) +$(call force,CFG_DRAM1_SIZE,0x1F80000000) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_PL011,y) +$(call force,CFG_CORE_ARM64_PA_BITS,48) +$(call force,CFG_EMBED_DTB,y) +$(call force,CFG_EMBED_DTB_SOURCE_FILE,fsl-lx2160a-rdb.dts) +CFG_LS_I2C ?= y +CFG_LS_GPIO ?= y +CFG_LS_DSPI ?= y +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),ls1028ardb) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_DRAM0_SIZE,0x80000000) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +$(call force,CFG_ARM_GICV3,y) +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(platform-flavor-armv8),1) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +CFG_TZDRAM_START ?= ((CFG_DRAM0_BASE + CFG_DRAM0_SIZE) - CFG_TEE_OS_DRAM0_SIZE) +CFG_TZDRAM_SIZE ?= ( CFG_TEE_OS_DRAM0_SIZE - CFG_SHMEM_SIZE) +#CFG_SHMEM_START (Non-Secure shared memory) needs to be 2MB aligned boundary for TZASC 380 configuration. +CFG_SHMEM_START ?= ((CFG_DRAM0_BASE + CFG_DRAM0_SIZE) - CFG_SHMEM_SIZE) +$(call force,CFG_ARM64_core,y) +CFG_USER_TA_TARGETS ?= ta_arm64 +else +#In ARMv7 platform CFG_SHMEM_SIZE is different to that of ARMv8 platforms. +CFG_TZDRAM_START ?= ((CFG_DRAM0_BASE + CFG_DRAM0_SIZE) - CFG_TEE_OS_DRAM0_SIZE) +CFG_TZDRAM_SIZE ?= ( CFG_TEE_OS_DRAM0_SIZE - (2*CFG_SHMEM_SIZE)) +#CFG_SHMEM_START (Non-Secure shared memory) needs to be 2MB aligned boundary for TZASC 380 configuration. +CFG_SHMEM_START ?= ((CFG_DRAM0_BASE + CFG_DRAM0_SIZE) - (2*CFG_SHMEM_SIZE)) +endif + +#Keeping Number of TEE thread equal to number of cores on the SoC +CFG_NUM_THREADS ?= $(CFG_TEE_CORE_NB_CORE) + +ifneq ($(CFG_ARM64_core),y) +$(call force,CFG_SECONDARY_INIT_CNTFRQ,y) +endif + +CFG_CRYPTO_SIZE_OPTIMIZATION ?= n + +# NXP CAAM support is not enabled by default and can be enabled +# on the command line +CFG_NXP_CAAM ?= n diff --git a/optee/optee_os/core/arch/arm/plat-ls/main.c b/optee/optee_os/core/arch/arm/plat-ls/main.c new file mode 100644 index 0000000..caf37cc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ls/main.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018 NXP + * Copyright (C) 2015 Freescale Semiconductor, 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 +#ifdef CFG_PL011 +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct gic_data gic_data; +#ifdef CFG_PL011 +static struct pl011_data console_data; +#else +static struct ns16550_data console_data; +#endif + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); +#if !defined(PLATFORM_FLAVOR_lx2160aqds) && !defined(PLATFORM_FLAVOR_lx2160ardb) +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); +#endif + +#if defined(PLATFORM_FLAVOR_lx2160ardb) || defined(PLATFORM_FLAVOR_lx2160aqds) +register_ddr(CFG_DRAM0_BASE, (CFG_TZDRAM_START - CFG_DRAM0_BASE)); +#ifdef CFG_DRAM1_BASE +register_ddr(CFG_DRAM1_BASE, CFG_DRAM1_SIZE); +#endif +#endif +#ifdef DCFG_BASE +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, DCFG_BASE, CORE_MMU_PGDIR_SIZE); +#endif + +#ifdef CFG_ARM32_core +void plat_primary_init_early(void) +{ + vaddr_t addr; + +#if defined(CFG_BOOT_SECONDARY_REQUEST) + /* set secondary entry address */ + io_write32(DCFG_BASE + DCFG_SCRATCHRW1, + __compiler_bswap32(TEE_LOAD_ADDR)); + + /* release secondary cores */ + io_write32(DCFG_BASE + DCFG_CCSR_BRR /* cpu1 */, + __compiler_bswap32(0x1 << 1)); + dsb(); + sev(); +#endif + + /* configure CSU */ + + /* first grant all peripherals */ + for (addr = CSU_BASE + CSU_CSL_START; + addr != CSU_BASE + CSU_CSL_END; + addr += 4) + io_write32(addr, __compiler_bswap32(CSU_ACCESS_ALL)); + + /* restrict key preipherals from NS */ + io_write32(CSU_BASE + CSU_CSL30, + __compiler_bswap32(CSU_ACCESS_SEC_ONLY)); + io_write32(CSU_BASE + CSU_CSL37, + __compiler_bswap32(CSU_ACCESS_SEC_ONLY)); + + /* lock the settings */ + for (addr = CSU_BASE + CSU_CSL_START; + addr != CSU_BASE + CSU_CSL_END; + addr += 4) + io_setbits32(addr, + __compiler_bswap32(CSU_SETTING_LOCK)); +} +#endif + +void console_init(void) +{ +#ifdef CFG_PL011 + /* + * Everything for uart driver initialization is done in bootloader. + * So not reinitializing console. + */ + pl011_init(&console_data, CONSOLE_UART_BASE, 0, 0); +#else + ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U8, 0); +#endif + register_serial_console(&console_data.chip); +} + +#if defined(PLATFORM_FLAVOR_lx2160aqds) || defined(PLATFORM_FLAVOR_lx2160ardb) +static TEE_Result get_gic_base_addr_from_dt(paddr_t *gic_addr) +{ + paddr_t paddr = 0; + size_t size = 0; + + void *fdt = get_embedded_dt(); + int gic_offset = 0; + + gic_offset = fdt_path_offset(fdt, "/soc/interrupt-controller@6000000"); + + if (gic_offset < 0) + gic_offset = fdt_path_offset(fdt, + "/interrupt-controller@6000000"); + + if (gic_offset > 0) { + paddr = fdt_reg_base_address(fdt, gic_offset); + if (paddr == DT_INFO_INVALID_REG) { + EMSG("GIC: Unable to get base addr from DT"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + size = fdt_reg_size(fdt, gic_offset); + if (size == DT_INFO_INVALID_REG_SIZE) { + EMSG("GIC: Unable to get size of base addr from DT"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + } else { + EMSG("Unable to get gic offset node"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + /* make entry in page table */ + if (!core_mmu_add_mapping(MEM_AREA_IO_SEC, paddr, size)) { + EMSG("GIC controller base MMU PA mapping failure"); + return TEE_ERROR_GENERIC; + } + + *gic_addr = paddr; + return TEE_SUCCESS; +} +#endif + +#define SVR_MINOR_MASK 0xF + +static void get_gic_offset(uint32_t *offsetc, uint32_t *offsetd) +{ +#ifdef PLATFORM_FLAVOR_ls1043ardb + vaddr_t addr = 0; + uint32_t rev = 0; + + addr = (vaddr_t)phys_to_virt(DCFG_BASE + DCFG_SVR_OFFSET, + MEM_AREA_IO_NSEC, 1); + if (!addr) { + EMSG("Failed to get virtual address for SVR register"); + panic(); + } + + rev = get_be32((void *)addr); + + if ((rev & SVR_MINOR_MASK) == 1) { + *offsetc = GICC_OFFSET_REV1_1; + *offsetd = GICD_OFFSET_REV1_1; + } else { + *offsetc = GICC_OFFSET_REV1; + *offsetd = GICD_OFFSET_REV1; + } +#else + *offsetc = GICC_OFFSET; + *offsetd = GICD_OFFSET; +#endif +} + +void main_init_gic(void) +{ + paddr_t gic_base = 0; + uint32_t gicc_offset = 0; + uint32_t gicd_offset = 0; + +#if defined(PLATFORM_FLAVOR_lx2160aqds) || defined(PLATFORM_FLAVOR_lx2160ardb) + if (get_gic_base_addr_from_dt(&gic_base)) + EMSG("Failed to get GIC base addr from DT"); +#else + gic_base = GIC_BASE; +#endif + get_gic_offset(&gicc_offset, &gicd_offset); + +#if defined(CFG_WITH_ARM_TRUSTED_FW) + /* On ARMv8, GIC configuration is initialized in ARM-TF */ + gic_init_base_addr(&gic_data, gic_base + gicc_offset, + gic_base + gicd_offset); +#else + /* Initialize GIC */ + gic_init(&gic_data, gic_base + gicc_offset, gic_base + gicd_offset); +#endif + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} diff --git a/optee/optee_os/core/arch/arm/plat-ls/plat_init.S b/optee/optee_os/core/arch/arm/plat-ls/plat_init.S new file mode 100644 index 0000000..a6350b9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ls/plat_init.S @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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. + */ + +#include +#include +#include +#include + +.section .text +.balign 4 +.code 32 + +/* + * platform early configuration + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +FUNC plat_cpu_reset_early , : + /* + * Disallow NSec to mask FIQ [bit4: FW=0] + * Allow NSec to manage Imprecise Abort [bit5: AW=1] + * Imprecise Abort trapped to Abort Mode [bit3: EA=0] + * In Sec world, FIQ trapped to FIQ Mode [bit2: FIQ=0] + * IRQ always trapped to IRQ Mode [bit1: IRQ=0] + * Secure World [bit0: NS=0] + */ + mov r0, #SCR_AW + write_scr r0 /* write Secure Configuration Register */ + + /* + * Mandated HW config loaded + * + * SCTLR = 0x00000000 + * + * ACTRL = 0x00000040 + * - core NOT booted in full SMP (FW bit0=0) + * + * NSACR = 0x00000C00 + * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) + * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) + */ + mov_imm r0, 0x00000000 + write_sctlr r0 + + mov_imm r0, 0x00000040 + write_actlr r0 + + mov_imm r0, 0x00000C00 + write_nsacr r0 + + mov pc, lr +END_FUNC plat_cpu_reset_early diff --git a/optee/optee_os/core/arch/arm/plat-ls/platform_config.h b/optee/optee_os/core/arch/arm/plat-ls/platform_config.h new file mode 100644 index 0000000..3924b5b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ls/platform_config.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * All rights reserved. + * Copyright 2021 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +#define STACK_ALIGNMENT 64 + +/* console uart define */ +#define CONSOLE_UART_BASE UART0_BASE + +/* Platform specific defines */ +#if defined(PLATFORM_FLAVOR_ls1012ardb) +/* DUART 1 */ +#define UART0_BASE 0x021C0500 +#define GIC_BASE 0x01400000 +#define GICC_OFFSET 0x2000 +#define GICD_OFFSET 0x1000 +#define CAAM_BASE 0x01700000 +#define CAAM_SIZE 0x100000 +#endif + +#if defined(PLATFORM_FLAVOR_ls1043ardb) +#define UART0_BASE 0x021C0500 +#define GIC_BASE 0x01400000 +#define GICC_OFFSET_REV1 0x2000 +#define GICD_OFFSET_REV1 0x1000 +#define GICC_OFFSET_REV1_1 0x20000 +#define GICD_OFFSET_REV1_1 0x10000 +#define CAAM_BASE 0x01700000 +#define CAAM_SIZE 0x100000 +#define DCFG_BASE 0x01EE0000 +#define DCFG_SVR_OFFSET 0xA4 +#endif + +#if defined(PLATFORM_FLAVOR_ls1046ardb) +/* DUART 1 */ +#define UART0_BASE 0x021C0500 +#define GIC_BASE 0x01400000 +#define GICC_OFFSET 0x20000 +#define GICD_OFFSET 0x10000 +#define CAAM_BASE 0x01700000 +#define CAAM_SIZE 0x100000 +#endif + +#if defined(PLATFORM_FLAVOR_ls1088ardb) +/* DUART 1 */ +#define UART0_BASE 0x021C0500 +#define GIC_BASE 0x06000000 +#define GICC_OFFSET 0x0 +#define GICD_OFFSET 0x0 +#define CAAM_BASE 0x08000000 +#define CAAM_SIZE 0x100000 +#endif + +#if defined(PLATFORM_FLAVOR_ls2088ardb) +/* DUART 1 */ +#define UART0_BASE 0x021C0600 +#define GIC_BASE 0x06000000 +#define GICC_OFFSET 0x0 +#define GICD_OFFSET 0x0 +#define CAAM_BASE 0x08000000 +#define CAAM_SIZE 0x100000 +#endif + +#if defined(PLATFORM_FLAVOR_ls1028ardb) +/* DUART 1 */ +#define UART0_BASE 0x021C0500 +#define GIC_BASE 0x06000000 +#define GICC_OFFSET 0x0 +#define GICD_OFFSET 0x0 +#define CAAM_BASE 0x08000000 +#define CAAM_SIZE 0x100000 +#endif + +#if defined(PLATFORM_FLAVOR_lx2160ardb) +/* DUART 1 */ +#define UART0_BASE 0x021C0000 +#define GIC_BASE 0x06000000 +#define GICC_OFFSET 0x0 +#define GICD_OFFSET 0x0 +#define CAAM_BASE 0x08000000 +#define CAAM_SIZE 0x100000 +#endif + +#if defined(PLATFORM_FLAVOR_lx2160aqds) +/* DUART 1 */ +#define UART0_BASE 0x021C0000 +#define GIC_BASE 0x06000000 +#define GICC_OFFSET 0x0 +#define GICD_OFFSET 0x0 +#define CAAM_BASE 0x08000000 +#define CAAM_SIZE 0x100000 +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-ls/sub.mk b/optee/optee_os/core/arch/arm/plat-ls/sub.mk new file mode 100644 index 0000000..17fcf7a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ls/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-$(CFG_ARM32_core) += plat_init.S diff --git a/optee/optee_os/core/arch/arm/plat-marvell/armada3700/hal_sec_perf.c b/optee/optee_os/core/arch/arm/plat-marvell/armada3700/hal_sec_perf.c new file mode 100644 index 0000000..daecbe1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/armada3700/hal_sec_perf.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Marvell International Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PHY_2_VIR(addr) ((vaddr_t)phys_to_virt((addr), MEM_AREA_IO_SEC, 1)) + +#define MCU_BASE 0xD0000000 +#define MCU_MC_CONTROL_0_REG PHY_2_VIR(MCU_BASE + 0x044) +#define TRUSTZONE_LOCK BIT(31) + +#define MCU_TZ_RANGE_HIGH_REG(x) PHY_2_VIR(MCU_BASE + 0x84 + ((x) << 3)) +#define MCU_TZ_RANGE_LOW_REG(x) PHY_2_VIR(MCU_BASE + 0x80 + ((x) << 3)) + +#define RW_PERM 0x0 +#define RO_PERM 0x1 +#define WO_PERM 0x2 +#define ABORT_PERM 0x3 + +#define MAX_RANGE_NUM 16 +#define INVALID_SIZE_CODE 0xff + +#ifdef TEE_RES_CFG_16M +#define RSVD_SEC_MEM (SIZE_8M + SIZE_8M) +#elif defined(TEE_RES_CFG_24M) +#define RSVD_SEC_MEM (SIZE_8M + SIZE_8M + SIZE_8M) +#elif defined(TEE_RES_CFG_8M) +#define RSVD_SEC_MEM SIZE_8M +#else +#error "no reserved secure memory defined." +#endif + +#define RA_ADDR TZDRAM_BASE +#define RA_SIZE TZDRAM_SIZE +#define RA_PERM ABORT_PERM + +#define TZ_IS_VALID(data) ((data) & (0x1)) +#define TZ_SET_VALID(data) ((data) |= (0x1)) + +#define TZ_GET_PERM(data, ret) ((ret) = (((data) & (0x3 << 1)) >> 1)) +#define TZ_SET_PERM(data, val) \ + do { \ + (data) &= (~(0x3 << 1)); \ + (data) |= (((val) & 0x3) << 1); \ + } while (0) + +#define TZ_GET_RZ_EN(data, ret) ((ret) = (((data) & (0x1 << 3)) >> 3)) +#define TZ_SET_RZ_EN(data, val) \ + do { \ + (data) &= (~(0x1 << 3)); \ + (data) |= (((val) & 0x1) << 3); \ + } while (0) + +#define TZ_GET_AREA_LEN_CODE(data, ret) ((ret) = (((data) & (0x1F << 8)) >> 8)) + +#define TZ_SET_AREA_LEN_CODE(data, val) \ + do { \ + (data) &= (~(0x1F << 8)); \ + (data) |= (((val) & 0x1F) << 8); \ + } while (0) + +#define TZ_GET_START_ADDR_L(data, ret) \ + ((ret) = (((data) & 0xFFF00000))) + +#define TZ_SET_START_ADDR_L(data, val) \ + do { \ + (data) &= (~0xFFF00000); \ + (data) |= (((val) & 0xFFF00000)); \ + } while (0) + +#define TZ_GET_UR_PERM(data, val) ((ret) = (((data) & (0x3 << 4)) >> 4)) +#define TZ_SET_UR_PERM(data, val) \ + do { \ + (data) &= (~(0x3 << 4)); \ + (data) |= (((val) & 0x3) << 4); \ + } while (0) + +#define TZ_GET_UR_RZ_EN(data, val) \ + ((ret) = (((data) & (0x1 << 6)) >> 6)) + +#define TZ_SET_UR_RZ_EN(data, val) \ + do { \ + (data) &= (~(0x1 << 6)); \ + (data) |= (((val) & 0x1) << 6); \ + } while (0) + + /* armada3700 mini region size is 1M */ +#define RANGE_SIZE_TO_CODE(size, code, i) \ + do { \ + (code) = INVALID_SIZE_CODE; \ + for ((i) = 0; (i) <= 0x1d; (i)++) { \ + if (((uint32_t)0x1 << (i)) == ((size) >> 20)) { \ + (code) = (i); \ + break; \ + } \ + } \ + } while (0) + +#define TZ_LOCK_MC(x) \ + do { \ + (x) = io_read32(MCU_MC_CONTROL_0_REG); \ + (x) |= (TRUSTZONE_LOCK); \ + io_write32(MCU_MC_CONTROL_0_REG, (x)); \ + } while (0) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, MCU_BASE, CORE_MMU_PGDIR_SIZE); + +static int32_t _find_valid_range(void) +{ + uint32_t i; + uint32_t tmp; + + for (i = 0; i < MAX_RANGE_NUM; i++) { + tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i)); + if (!TZ_IS_VALID(tmp)) + return i; + } + return -1; +} + +static int32_t set_range(uint32_t addr, uint32_t size, uint32_t perm) +{ + uint32_t data; + uint32_t sizecode; + int32_t valid_range; + uint32_t i; + + if (!IS_ALIGNED(addr, SIZE_1M)) { + EMSG("region addr(0x%" PRIx32 ") is not aligned with 1M!", + addr); + return -1; + } + + if (!IS_ALIGNED(size, SIZE_1M)) { + EMSG("region size(0x%" PRIx32 ") is not aligned with 1M!", + size); + return -1; + } + + RANGE_SIZE_TO_CODE(size, sizecode, i); + if (sizecode == INVALID_SIZE_CODE) { + EMSG("not valid region size(2^n)! size:0x%" PRIx32, size); + return -1; + } + + valid_range = _find_valid_range(); + if (valid_range == -1) { + EMSG("ERR: can't find valid range!"); + return -1; + } + + data = io_read32(MCU_TZ_RANGE_LOW_REG(valid_range)); + + TZ_SET_VALID(data); + TZ_SET_PERM(data, perm); + TZ_SET_AREA_LEN_CODE(data, sizecode); + TZ_SET_START_ADDR_L(data, addr); + + if (!valid_range) { + /* Set Undefine Range RW */ + TZ_SET_UR_PERM(data, RW_PERM); + TZ_SET_UR_RZ_EN(data, 0); + } + + io_write32(MCU_TZ_RANGE_LOW_REG(valid_range), data); + + return 0; +} + +static void _dump_range(void) +{ + uint32_t i; + uint32_t tmp; + uint32_t __maybe_unused sizecode_read; + uint32_t __maybe_unused sizem; + uint32_t __maybe_unused addr_read; + uint32_t __maybe_unused perm_read; + + for (i = 0; i < MAX_RANGE_NUM; i++) { + tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i)); + + if (TZ_IS_VALID(tmp)) { + TZ_GET_PERM(tmp, perm_read); + TZ_GET_AREA_LEN_CODE(tmp, sizecode_read); + TZ_GET_START_ADDR_L(tmp, addr_read); + + DMSG("Range Num%" PRIu32 + ": Reg 0x%" PRIx64 " = 0x%" PRIx32, + i, MCU_TZ_RANGE_LOW_REG(i), tmp); + DMSG("AddrL: 0x%08" PRIx32, addr_read); + DMSG("Size: %" PRIu32 "M", (0x1 << sizecode_read)); + DMSG("Perm: %" PRIu32, perm_read); + } + } +} + +static void _set_range(uint32_t addr, uint32_t size, uint32_t perm) +{ + uint32_t rgn_addr = addr; + uint32_t rgn_size = size; + /* minimum region size is 1M and must be times of 1M */ + uint32_t p = 0x100000; + + while (1) { + if ((p * 2) > rgn_size) { + set_range(rgn_addr, p, perm); + rgn_addr += p; + rgn_size -= p; + if (rgn_size == 0) + break; + p = 0x100000; + } else + p <<= 1; + } +} + +static TEE_Result init_sec_perf(void) +{ + uint32_t tmp; + + /* Set Secure Memory Region */ + DMSG("sec-rgn size: ra = 0x%" PRIx32 ", size = 0x%" PRIx64, + RA_ADDR, RA_SIZE); + _set_range(RA_ADDR, RA_SIZE, RA_PERM); + + /* Close TZ register modification */ + TZ_LOCK_MC(tmp); + + _dump_range(); + + return TEE_SUCCESS; +} + +service_init(init_sec_perf); diff --git a/optee/optee_os/core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c b/optee/optee_os/core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c new file mode 100644 index 0000000..cbfda55 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Marvell International Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PHY_2_VIR(addr) ((vaddr_t)phys_to_virt((addr), MEM_AREA_IO_SEC, 1)) + +#define MCU_MC_CONTROL_0_REG PHY_2_VIR(MCU_BASE + 0x044) +#define TRUSTZONE_LOCK BIT(31) + +#define MCU_TZ_RANGE_HIGH_REG(x) PHY_2_VIR(MCU_BASE + 0x84 + ((x) << 3)) +#define MCU_TZ_RANGE_LOW_REG(x) PHY_2_VIR(MCU_BASE + 0x80 + ((x) << 3)) + +#define RW_PERM 0x0 +#define RO_PERM 0x1 +#define WO_PERM 0x2 +#define ABORT_PERM 0x3 + +#define MAX_RANGE_NUM 16 +#define INVALID_SIZE_CODE 0xff + +#ifdef TEE_RES_CFG_16M +#define RSVD_SEC_MEM (SIZE_8M + SIZE_8M) +#elif defined(TEE_RES_CFG_24M) +#define RSVD_SEC_MEM (SIZE_8M + SIZE_8M + SIZE_8M) +#elif defined(TEE_RES_CFG_8M) +#define RSVD_SEC_MEM SIZE_8M +#else +#error "no reserved secure memory defined." +#endif + +#define RA_ADDR TZDRAM_BASE +#define RA_SIZE TZDRAM_SIZE +#define RA_PERM ABORT_PERM + +#define TZ_IS_VALID(data) ((data) & (0x1)) +#define TZ_SET_VALID(data) ((data) |= (0x1)) + +#define TZ_GET_PERM(data, ret) ((ret) = (((data) & (0x3 << 1)) >> 1)) +#define TZ_SET_PERM(data, val) \ + do { \ + (data) &= (~(0x3 << 1)); \ + (data) |= (((val) & 0x3) << 1); \ + } while (0) + +#define TZ_GET_RZ_EN(data, ret) ((ret) = (((data) & (0x1 << 3)) >> 3)) +#define TZ_SET_RZ_EN(data, val) \ + do { \ + (data) &= (~(0x1 << 3)); \ + (data) |= (((val) & 0x1) << 3); \ + } while (0) + +#define TZ_GET_AREA_LEN_CODE(data, ret) ((ret) = (((data) & (0x1F << 7)) >> 7)) + +#define TZ_SET_AREA_LEN_CODE(data, val) \ + do { \ + (data) &= (~(0x1F << 7)); \ + (data) |= (((val) & 0x1F) << 7); \ + } while (0) + +#define TZ_GET_START_ADDR_L(data, ret) \ + ((ret) = (((data) & 0xFFFFF000))) + +#define TZ_SET_START_ADDR_L(data, val) \ + do { \ + (data) &= (~0xFFFFF000); \ + (data) |= (((val) & 0xFFFFF000)); \ + } while (0) + +#define TZ_GET_UR_PERM(data, val) ((ret) = (((data) & (0x3 << 4)) >> 4)) +#define TZ_SET_UR_PERM(data, val) \ + do { \ + (data) &= (~(0x3 << 4)); \ + (data) |= (((val) & 0x3) << 4); \ + } while (0) + +#define TZ_GET_UR_RZ_EN(data, val) \ + ((ret) = (((data) & (0x1 << 6)) >> 6)) + +#define TZ_SET_UR_RZ_EN(data, val) \ + do { \ + (data) &= (~(0x1 << 6)); \ + (data) |= (((val) & 0x1) << 6); \ + } while (0) + + /* armada mini region size is 1M */ +#define RANGE_SIZE_TO_CODE(size, code, i) \ + do { \ + (code) = INVALID_SIZE_CODE; \ + for ((i) = 8; (i) <= 0x1f; (i)++) { \ + if (((uint32_t)0x1 << (i)) == ((size) >> 12)) { \ + (code) = (i); \ + break; \ + } \ + } \ + } while (0) + +#define RANGE_CODE_TO_SIZE_K(code, sizek) ((sizek) = ((4) << (code))) + +#define TZ_LOCK_MC(x) \ + do { \ + (x) = io_read32(MCU_MC_CONTROL_0_REG); \ + (x) |= (TRUSTZONE_LOCK); \ + io_write32(MCU_MC_CONTROL_0_REG, (x)); \ + } while (0) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, MCU_BASE, CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, MC_SCR_REGISTER, CORE_MMU_PGDIR_SIZE); + +static int32_t _find_valid_range(void) +{ + uint32_t i; + uint32_t tmp; + + for (i = 0; i < MAX_RANGE_NUM; i++) { + tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i)); + if (!TZ_IS_VALID(tmp)) + return i; + } + return -1; +} + +static int32_t set_range(uint32_t addr, uint32_t size, uint32_t perm) +{ + uint32_t data; + uint32_t sizecode; + int32_t valid_range; + uint32_t i; + + if (!IS_ALIGNED(addr, SIZE_1M)) { + EMSG("region addr(0x%" PRIx32 ") is not aligned with 1M!", + addr); + return -1; + } + + if (!IS_ALIGNED(size, SIZE_1M)) { + EMSG("region size(0x%" PRIx32 ") is not aligned with 1M!", + size); + return -1; + } + + if (!IS_ALIGNED(addr, size)) { + EMSG("region size(0x%" PRIx32 + ") not align with addr(0x%" PRIx32 ")", + size, addr); + return -1; + } + + RANGE_SIZE_TO_CODE(size, sizecode, i); + if (sizecode == INVALID_SIZE_CODE) { + EMSG("not valid region size(2^n)! size:0x%" PRIx32, size); + return -1; + } + + valid_range = _find_valid_range(); + if (valid_range == -1) { + EMSG("ERR: can't find valid range!"); + return -1; + } + + data = io_read32(MCU_TZ_RANGE_LOW_REG(valid_range)); + + TZ_SET_VALID(data); + TZ_SET_PERM(data, perm); + TZ_SET_AREA_LEN_CODE(data, sizecode); + TZ_SET_START_ADDR_L(data, addr); + + if (!valid_range) { + /* Set Undefine Range RW */ + TZ_SET_UR_PERM(data, RW_PERM); + TZ_SET_UR_RZ_EN(data, 0); + } + + io_write32(MCU_TZ_RANGE_LOW_REG(valid_range), data); + + return 0; +} + +static void _dump_range(void) +{ + uint32_t i; + uint32_t tmp; + uint32_t sizek; + uint32_t sizecode_read; + uint32_t __maybe_unused sizem; + uint32_t __maybe_unused addr_read; + uint32_t __maybe_unused perm_read; + + for (i = 0; i < MAX_RANGE_NUM; i++) { + tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i)); + + if (TZ_IS_VALID(tmp)) { + TZ_GET_PERM(tmp, perm_read); + TZ_GET_AREA_LEN_CODE(tmp, sizecode_read); + TZ_GET_START_ADDR_L(tmp, addr_read); + + DMSG("Range Num%" PRIu32 + ": Reg 0x%" PRIx64 " = 0x%" PRIx32, + i, MCU_TZ_RANGE_LOW_REG(i), tmp); + DMSG("AddrL: 0x%08" PRIx32, addr_read); + RANGE_CODE_TO_SIZE_K(sizecode_read, sizek); + sizem = sizek >> 10; + DMSG("Size: %" PRIu32 "K, %" PRIu32 "M", sizek, sizem); + DMSG("Perm: %" PRIu32, perm_read); + } + } +} + +static uint32_t _find_granule(uint32_t addr, uint32_t size) +{ + /* max supported granule for armada is 8TB + * but 2GB is far enough here + */ + uint32_t max_granule = SIZE_2G; + + while (max_granule >= SIZE_4K) { /* min granule is 4kB */ + if (max_granule <= size && IS_ALIGNED(addr, max_granule)) + return max_granule; + + max_granule >>= 1; + } + + return 0; /* cannot find a valid granule */ +} + +static void _set_range(uint32_t addr, uint32_t size, uint32_t perm) +{ + uint32_t rgn_addr = addr; + uint32_t rgn_size = size; + uint32_t p; + + while (rgn_size) { + p = _find_granule(rgn_addr, rgn_size); + if (!p) + panic("cannot find a suitable granule!"); + if (set_range(rgn_addr, p, perm)) + panic("set_range failed!"); + + rgn_addr += p; + rgn_size -= p; + } +} + +static TEE_Result init_sec_perf(void) +{ + uint32_t tmp; + + /* MC_SCR config: deny NS access to MC registers */ + tmp = io_read32(PHY_2_VIR(MC_SCR_REGISTER)); + tmp |= 0x1; + io_write32(PHY_2_VIR(MC_SCR_REGISTER), tmp); + + /* Set Secure Memory Region */ + DMSG("sec-rgn size: ra = 0x%08" PRIx32 ", size = 0x%" PRIx32, + RA_ADDR, RA_SIZE); + _set_range(RA_ADDR, RA_SIZE, RA_PERM); + + /* Close TZ register modification */ + TZ_LOCK_MC(tmp); + + _dump_range(); + + return TEE_SUCCESS; +} + +service_init(init_sec_perf); diff --git a/optee/optee_os/core/arch/arm/plat-marvell/conf.mk b/optee/optee_os/core/arch/arm/plat-marvell/conf.mk new file mode 100644 index 0000000..c600138 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/conf.mk @@ -0,0 +1,101 @@ +PLATFORM_FLAVOR ?= armada7k8k + +ifeq ($(PLATFORM_FLAVOR),armada7k8k) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_TZDRAM_START,0x04400000) +$(call force,CFG_TZDRAM_SIZE,0x00C00000) +$(call force,CFG_SHMEM_START,0x05000000) +$(call force,CFG_SHMEM_SIZE,0x00400000) +$(call force,CFG_TEE_RAM_VA_SIZE,0x00400000) +# If Secure Data Path is enabled, uses the TZDRAM last 4MByte +$(call force,CFG_TEE_SDP_MEM_SIZE,0x00400000) +platform-debugger-arm := 1 +$(call force,CFG_8250_UART,y) +endif + +ifeq ($(PLATFORM_FLAVOR),armada3700) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_TZDRAM_START,0x04400000) +$(call force,CFG_TZDRAM_SIZE,0x00C00000) +$(call force,CFG_SHMEM_START,0x05000000) +$(call force,CFG_SHMEM_SIZE,0x00400000) +$(call force,CFG_TEE_RAM_VA_SIZE,0x00400000) +# If Secure Data Path is enabled, uses the TZDRAM last 4MByte +$(call force,CFG_TEE_SDP_MEM_SIZE,0x00400000) +platform-debugger-arm := 1 +$(call force,CFG_MVEBU_UART,y) +$(call force,CFG_ARM_GICV3,y) +endif + +ifeq ($(PLATFORM_FLAVOR),otx2t96) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,24) +$(call force,CFG_CLUSTERS_PER_NODE,4) +$(call force,CFG_TZDRAM_START,0x00001000) +$(call force,CFG_TZDRAM_SIZE,0x000a00000) +$(call force,CFG_SHMEM_START,0x01000000) +$(call force,CFG_SHMEM_SIZE,0x00800000) +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,48) +$(call force,CFG_LPAE_ADDR_SPACE_BITS,36) +$(call force,CFG_PL011,y) +$(call force,CFG_ARM_GICV3,y) +CFG_HW_UNQ_KEY_SUPPORT ?= y +CFG_USER_TA_TARGETS ?= ta_arm64 +CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE +CFG_CORE_HEAP_SIZE ?= 131072 +endif + +ifeq ($(PLATFORM_FLAVOR),otx2f95) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,6) +$(call force,CFG_CLUSTERS_PER_NODE,1) +$(call force,CFG_TZDRAM_START,0x00001000) +$(call force,CFG_TZDRAM_SIZE,0x000a00000) +$(call force,CFG_SHMEM_START,0x01000000) +$(call force,CFG_SHMEM_SIZE,0x00800000) +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,48) +$(call force,CFG_LPAE_ADDR_SPACE_BITS,36) +$(call force,CFG_PL011,y) +$(call force,CFG_ARM_GICV3,y) +CFG_HW_UNQ_KEY_SUPPORT ?= y +CFG_USER_TA_TARGETS ?= ta_arm64 +CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE +CFG_CORE_HEAP_SIZE ?= 131072 +endif + +ifeq ($(PLATFORM_FLAVOR),otx2t98) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,36) +$(call force,CFG_CLUSTERS_PER_NODE,6) +$(call force,CFG_TZDRAM_START,0x00001000) +$(call force,CFG_TZDRAM_SIZE,0x000a00000) +$(call force,CFG_SHMEM_START,0x01000000) +$(call force,CFG_SHMEM_SIZE,0x00800000) +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,48) +#$(call force,CFG_LPAE_ADDR_SPACE_BITS,36) +$(call force,CFG_PL011,y) +$(call force,CFG_ARM_GICV3,y) +CFG_HW_UNQ_KEY_SUPPORT ?= y +CFG_USER_TA_TARGETS ?= ta_arm64 +CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE +CFG_CORE_HEAP_SIZE ?= 131072 +endif + +ifeq ($(platform-debugger-arm),1) +# ARM debugger needs this +platform-cflags-debug-info = -gdwarf-2 +platform-aflags-debug-info = -gdwarf-2 +endif + +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_GIC,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) + +CFG_WITH_STATS ?= y diff --git a/optee/optee_os/core/arch/arm/plat-marvell/main.c b/optee/optee_os/core/arch/arm/plat-marvell/main.c new file mode 100644 index 0000000..25f1ac7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/main.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Marvell International Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 +#if defined(PLATFORM_FLAVOR_armada7k8k) +#include +#elif defined(PLATFORM_FLAVOR_armada3700) +#include +#endif +#ifdef CFG_PL011 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct gic_data gic_data; +#if defined(PLATFORM_FLAVOR_armada7k8k) +static struct serial8250_uart_data console_data; +#elif defined(PLATFORM_FLAVOR_armada3700) +static struct mvebu_uart_data console_data; +#elif CFG_PL011 +static struct pl011_data console_data; +#endif + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); +#ifdef CFG_HW_UNQ_KEY_SUPPORT +register_phys_mem(MEM_AREA_IO_SEC, PLAT_MARVELL_FUSF_FUSE_BASE, + SMALL_PAGE_SIZE); +#endif + +#ifdef GIC_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, CORE_MMU_PGDIR_SIZE); +#ifdef GICC_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, CORE_MMU_PGDIR_SIZE); +#endif + +void main_init_gic(void) +{ + paddr_t gicd_base; + paddr_t gicc_base = 0; + +#ifdef GICC_BASE + gicc_base = GIC_BASE + GICC_OFFSET; +#endif + gicd_base = GIC_BASE + GICD_OFFSET; + + gic_init_base_addr(&gic_data, gicc_base, gicd_base); + + itr_init(&gic_data.chip); +} +#endif + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ +#if defined(PLATFORM_FLAVOR_armada7k8k) + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); +#elif defined(PLATFORM_FLAVOR_armada3700) + mvebu_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); +#elif CFG_PL011 + pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, + CONSOLE_BAUDRATE); +#endif + register_serial_console(&console_data.chip); +} + +#ifdef CFG_HW_UNQ_KEY_SUPPORT +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + void *huk = phys_to_virt(PLAT_MARVELL_FUSF_FUSE_BASE + + PLAT_MARVELL_FUSF_HUK_OFFSET, + MEM_AREA_IO_SEC, sizeof(hwkey->data)); + if (!huk) { + EMSG("\nH/W Unique key is not fetched from the platform."); + return TEE_ERROR_SECURITY; + } + + memcpy(&hwkey->data[0], huk, sizeof(hwkey->data)); + return TEE_SUCCESS; +} +#endif diff --git a/optee/optee_os/core/arch/arm/plat-marvell/otx2/core_pos.S b/optee/optee_os/core/arch/arm/plat-marvell/otx2/core_pos.S new file mode 100644 index 0000000..a5a612f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/otx2/core_pos.S @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Marvell International Ltd. + */ + +#include +#include + +FUNC get_core_pos_mpidr , : + ubfx x1, x0, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + mov x2, #CFG_CLUSTERS_PER_NODE + mul x1, x1, x2 + ubfx x2, x0, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + add x0, x1, x2 + ret +END_FUNC get_core_pos_mpidr diff --git a/optee/optee_os/core/arch/arm/plat-marvell/platform_config.h b/optee/optee_os/core/arch/arm/plat-marvell/platform_config.h new file mode 100644 index 0000000..0925b82 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/platform_config.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017 Marvell International Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#ifdef ARM64 +#ifdef CFG_WITH_PAGER +#error "Pager not supported yet" +#endif +#else +#error "32 bit mode not supported yet" +#endif /*ARM64*/ + +#if defined(PLATFORM_FLAVOR_armada7k8k) +/* + * armada7k8k specifics. + */ +#define TEE_RES_CFG_8M + +#define MVEBU_REGS_BASE 0xF0000000 + +/* GICv2 */ +#define MVEBU_GICD_BASE 0x210000 +#define MVEBU_GICC_BASE 0x220000 +#define GIC_DIST_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE) +#define GIC_CPU_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE) + +#define GIC_BASE GIC_DIST_BASE + +/* UART */ +#define PLAT_MARVELL_BOOT_UART_BASE (MVEBU_REGS_BASE + 0x512000) +#define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ 200000000 +#define MARVELL_CONSOLE_BAUDRATE 115200 + +#define CONSOLE_UART_BASE PLAT_MARVELL_BOOT_UART_BASE + +#define GICC_OFFSET 0x10000 +#define GICD_OFFSET 0x0 + +#define GICD_BASE (GIC_BASE + GICD_OFFSET) +#define GICC_BASE (GIC_BASE + GICC_OFFSET) + +/* MCU */ +#define MCU_BASE 0xF0020000 +#define MCU_REG_SIZE SIZE_4K +#define MC_SCR_REGISTER 0xF06F0204 +#define MC_SCR_REG_SIZE SIZE_4K + +#elif defined(PLATFORM_FLAVOR_armada3700) +/* + * armada3700 specifics. + */ +#define TEE_RES_CFG_8M + +#define MVEBU_REGS_BASE 0xD0000000 + +/* GICv3 */ +#define MVEBU_GICD_BASE 0x1D00000 +#define MVEBU_GICR_BASE 0x1D40000 +#define MVEBU_GICC_BASE 0x1D80000 + +#define GIC_DIST_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE) +#define GIC_RDIS_BASE (MVEBU_REGS_BASE + MVEBU_GICR_BASE) +#define GIC_CPU_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE) + +#define GIC_BASE GIC_DIST_BASE +#define GICC_OFFSET (0x80000) +#define GICR_OFFSET (0x40000) +#define GICD_OFFSET (0x0) + +#define GICD_BASE (GIC_BASE + GICD_OFFSET) +#define GICC_BASE (GIC_BASE + GICC_OFFSET) + +/* UART */ +#define PLAT_MARVELL_BOOT_UART_BASE (MVEBU_REGS_BASE + 0x12000) +#define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ 25804800 +#define MARVELL_CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_BASE PLAT_MARVELL_BOOT_UART_BASE + +#elif defined(PLATFORM_FLAVOR_otx2t96) || defined(PLATFORM_FLAVOR_otx2f95) || \ + defined(PLATFORM_FLAVOR_otx2t98) +/* + * OcteonTX2(otx2) specifics. + */ + +/* GICv3 */ +#define GIC_BASE 0x801000000000ll +#define GICD_OFFSET (0x0) + +#define GICD_BASE (GIC_BASE + GICD_OFFSET) + +/* UART */ +#define PLAT_MARVELL_BOOT_UART_BASE 0x87E028000000ll +#define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ 16666656 +#define MARVELL_CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_BASE PLAT_MARVELL_BOOT_UART_BASE + +/* eFUSE */ +#define PLAT_MARVELL_FUSF_FUSE_BASE 0x87E004000000ll +#define PLAT_MARVELL_FUSF_HUK_OFFSET (0x90) + +#else +#error "Unknown platform flavor" +#endif + +#define UART_BAUDRATE MARVELL_CONSOLE_BAUDRATE +#define CONSOLE_BAUDRATE UART_BAUDRATE +#define CONSOLE_UART_CLK_IN_HZ PLAT_MARVELL_BOOT_UART_CLK_IN_HZ + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-marvell/sub.mk b/optee/optee_os/core/arch/arm/plat-marvell/sub.mk new file mode 100644 index 0000000..56cb912 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-marvell/sub.mk @@ -0,0 +1,7 @@ +global-incdirs-y += . +srcs-y += main.c +ifneq (,$(filter $(PLATFORM_FLAVOR),otx2t96 otx2f95 otx2t98)) +srcs-$(CFG_ARM64_core) += otx2/core_pos.S +endif +srcs-$(PLATFORM_FLAVOR_armada7k8k) += armada7k8k/hal_sec_perf.c +srcs-$(PLATFORM_FLAVOR_armada3700) += armada3700/hal_sec_perf.c diff --git a/optee/optee_os/core/arch/arm/plat-mediatek/conf.mk b/optee/optee_os/core/arch/arm/plat-mediatek/conf.mk new file mode 100644 index 0000000..689f1af --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-mediatek/conf.mk @@ -0,0 +1,68 @@ +PLATFORM_FLAVOR ?= mt8173 + +CFG_ARM64_core ?= y + +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_8250_UART,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) + +# default DRAM base address +CFG_DRAM_BASE ?= 0x40000000 + +# default DRAM size 1 GiB +CFG_DRAM_SIZE ?= 0x40000000 + +ifeq ($(PLATFORM_FLAVOR),mt8173) +# 2**1 = 2 cores per cluster +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +CFG_TZDRAM_START ?= 0xbe000000 +CFG_TZDRAM_SIZE ?= 0x01e00000 +CFG_SHMEM_START ?= 0xbfe00000 +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),mt8175) +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_GIC,y) +CFG_TZDRAM_START ?= 0x43200000 +CFG_TZDRAM_SIZE ?= 0x00a00000 +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),mt8516) +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +CFG_TZDRAM_START ?= 0x4fd00000 +CFG_TZDRAM_SIZE ?= 0x00300000 +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),mt8183) +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_GIC,y) +CFG_TZDRAM_START ?= 0x4fd00000 +CFG_TZDRAM_SIZE ?= 0x00300000 +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),mt8195) +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_GIC,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +CFG_TZDRAM_START ?= 0x43200000 +CFG_TZDRAM_SIZE ?= 0x00a00000 +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) +CFG_SHMEM_SIZE ?= 0x00200000 +endif diff --git a/optee/optee_os/core/arch/arm/plat-mediatek/main.c b/optee/optee_os/core/arch/arm/plat-mediatek/main.c new file mode 100644 index 0000000..c56ff15 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-mediatek/main.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, + CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE); + +static struct serial8250_uart_data console_data; + +register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE); + +#ifdef CFG_GIC +static struct gic_data gic_data; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE + GICD_OFFSET, + CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE + GICC_OFFSET, + CORE_MMU_PGDIR_SIZE); + +void main_init_gic(void) +{ + gic_init_base_addr(&gic_data, GIC_BASE + GICC_OFFSET, + GIC_BASE + GICD_OFFSET); + + itr_init(&gic_data.chip); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} +#endif + +void console_init(void) +{ + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h b/optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h new file mode 100644 index 0000000..3a01fd2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-mediatek/platform_config.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#ifdef ARM64 +#ifdef CFG_WITH_PAGER +#error "Pager not supported for ARM64" +#endif +#endif /*ARM64*/ + +#if defined(PLATFORM_FLAVOR_mt8173) + +#define GIC_BASE 0x10220000 +#define GICC_OFFSET 0x2000 +#define GICD_OFFSET 0x1000 + +#define UART0_BASE 0x11002000 +#define UART1_BASE 0x11003000 +#define UART2_BASE 0x11004000 +#define UART3_BASE 0x11005000 + +#define CONSOLE_UART_BASE UART0_BASE +#define CONSOLE_BAUDRATE 921600 +#define CONSOLE_UART_CLK_IN_HZ 26000000 + +#define DRAM0_BASE 0x40000000 +#define DRAM0_SIZE 0x80000000 + +#elif defined(PLATFORM_FLAVOR_mt8175) + +#define GIC_BASE 0x0C000000 +#define GICC_OFFSET 0x400000 +#define GICD_OFFSET 0x0 + +#define UART0_BASE 0x11002000 +#define UART1_BASE 0x11103000 +#define UART2_BASE 0x11104000 + +#define CONSOLE_UART_BASE UART0_BASE +#define CONSOLE_BAUDRATE 921600 +#define CONSOLE_UART_CLK_IN_HZ 26000000 + +#elif defined(PLATFORM_FLAVOR_mt8516) + +#define GIC_BASE 0x10310000 +#define GICC_OFFSET 0x10000 +#define GICD_OFFSET 0x00000 + +#define UART0_BASE 0x11005000 +#define UART1_BASE 0x11106000 +#define UART2_BASE 0x11107000 + +#define CONSOLE_UART_BASE UART0_BASE +#define CONSOLE_BAUDRATE 921600 +#define CONSOLE_UART_CLK_IN_HZ 26000000 + +#elif defined(PLATFORM_FLAVOR_mt8183) + +#define GIC_BASE 0x0C000000 +#define GICC_OFFSET 0x400000 +#define GICD_OFFSET 0x0 + +#define UART0_BASE 0x11002000 +#define UART1_BASE 0x11103000 +#define UART2_BASE 0x11104000 + +#define CONSOLE_UART_BASE UART0_BASE +#define CONSOLE_BAUDRATE 921600 +#define CONSOLE_UART_CLK_IN_HZ 26000000 + +#elif defined(PLATFORM_FLAVOR_mt8195) + +#define GIC_BASE 0x0C000000 +#define GICC_OFFSET 0x400000 +#define GICD_OFFSET 0x0 + +#define UART0_BASE 0x11001100 +#define UART1_BASE 0x11101200 +#define UART2_BASE 0x11101300 + +#define CONSOLE_UART_BASE UART0_BASE +#define CONSOLE_BAUDRATE 921600 +#define CONSOLE_UART_CLK_IN_HZ 26000000 + +#else +#error "Unknown platform flavor" +#endif + +#ifdef CFG_WITH_LPAE +#define MAX_XLAT_TABLES 5 +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-mediatek/sub.mk b/optee/optee_os/core/arch/arm/plat-mediatek/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-mediatek/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-poplar/conf.mk b/optee/optee_os/core/arch/arm/plat-poplar/conf.mk new file mode 100644 index 0000000..167cb40 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-poplar/conf.mk @@ -0,0 +1,29 @@ +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_TEE_CORE_NB_CORE,4) + +$(call force,CFG_PL011,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) + +ifeq ($(CFG_ARM64_core),y) +CFG_CORE_TZSRAM_EMUL_SIZE ?= 655360 +else +CFG_CORE_TZSRAM_EMUL_SIZE ?= 524288 +endif + +CFG_NUM_THREADS ?= 4 +CFG_CRYPTO_WITH_CE ?= y +# Overrides default in mk/config.mk with 96 kB +CFG_CORE_HEAP_SIZE ?= 98304 + +CFG_PL061 ?= y + +ifeq ($(CFG_PL061),y) +core-platform-cppflags += -DPLAT_PL061_MAX_GPIOS=104 +endif + +CFG_TEE_SDP_MEM_BASE ?= 0x02800000 +CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 + +CFG_DRAM_SIZE_GB ?= 2 diff --git a/optee/optee_os/core/arch/arm/plat-poplar/hi3798cv200.h b/optee/optee_os/core/arch/arm/plat-poplar/hi3798cv200.h new file mode 100644 index 0000000..1b6b61e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-poplar/hi3798cv200.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2017, Linaro Limited + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __HI3798cv200_H__ +#define __HI3798cv200_H__ + +/* PL011 */ +#define PL011_UART0_BASE (0xF8B00000) +#define PL011_BAUDRATE (115200) +#define PL011_UART0_CLK_IN_HZ (75000000) + +#endif /* __HI3798cv200_H__ */ diff --git a/optee/optee_os/core/arch/arm/plat-poplar/main.c b/optee/optee_os/core/arch/arm/plat-poplar/main.c new file mode 100644 index 0000000..ec244ce --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-poplar/main.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, Linaro Limited + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#ifdef CFG_PL061 +#include +#endif +#include +#include +#include +#include +#include + +static struct pl011_data console_data; + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, PL011_REG_SIZE); +/* for dynamic shared memory */ +register_dynamic_shm(DRAM0_BASE_NSEC, DRAM0_SIZE_NSEC); + +void console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-poplar/platform_config.h b/optee/optee_os/core/arch/arm/plat-poplar/platform_config.h new file mode 100644 index 0000000..ff60d52 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-poplar/platform_config.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017, Linaro Limited + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +/* PL011 UART */ +#define CONSOLE_UART_BASE PL011_UART0_BASE +#define CONSOLE_BAUDRATE PL011_BAUDRATE +#define CONSOLE_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ + +/* + * Poplar memory map + * + * Note: the physical address ranges below correspond to DRAM which is + * non-secure by default. Therefore, the terms TZDRAM and TZSRAM may not + * reflect the reality and only indicate areas that "would normally be" + * secure DRAM and secure SRAM in a more complete implementation. + * The memory map was defined like this for lack of better documentation. + * It is good enough for development/testing purposes. + * + * 0xFF00_0000 [DRAM2_LIMIT] + * other (devmem) + * 0xF000_0000 [DRAM2_BASE] + * + * 0x8000_0000 (0x4000_0000 for 1GB board) [DRAM0_LIMIT] + * u-boot + ree memory: 1144 MiB (144 MiB for 1GB board) + * 0x3700_0000 CONFIG_SYS_TEXT_BASE (u-boot) + * PLAT_POPLAR_NS_IMAGE_OFFSET (arm-tf) + * ramdisk: 76 MiB + * 0x3240_0000 + * fdt: 2 MiB + * 0x3220_0000 + * pxe file or script addr: 2 MiB + * 0x3200_0000 + * kernel/android: 32 MiB + * 0x3000_0000 + * ree memory: 696 MiB + * 0x0480_0000 CONFIG_SYS_LOAD_ADDR (defined in u-boot) + * other: 6 MiB + * 0x0420_0000 CONFIG_SYS_INIT_SP_ADDR (defined in u-boot) + * 0x0408_0000 KERNEL_TEXT_OFFSET (defined in u-boot) + * unused: 512 KiB + * 0x0400_0000 + * + * 0x0400_0000 - + * TA RAM: 14 MiB | TZDRAM + * 0x0320_0000 - + * + * CFG_WITH_PAGER=n - + * TEE RAM: 2 MiB (TEE_RAM_VA_SIZE) | TZDRAM + * 0x0300_0000 [TZDRAM_BASE, TEE_LOAD_ADDR] - + * + * CFG_WITH_PAGER=y + * Unused + * 0x030A_0000 - + * TEE RAM: 640 KiB (TZSRAM_SIZE) | TZSRAM + * 0x0300_0000 [TZSRAM_BASE, TEE_LOAD_ADDR] - + * + * 0x0300_0000 [TZDRAM_BASE, TZSRAM_BASE, TEE_LOAD_ADDR] + * OP-TEE Future Use: 4 MiB + * 0x02C0_0000 + * + * 0x02C0_0000 + * Secure Data Path buffers: 4 MiB + * 0x0280_0000 [CFG_TEE_SDP_MEM_BASE] + * Shared memory: 4 MiB + * 0x0240_0000 + * OP-TEE Future Use: 2 MiB + * 0x0220_0000 + * + * 0x0220_0000 + * unused: 64 KiB + * 0x021F_0000 l-loader limit (len/size set by poplar-l-loader.git) + * unused (cannot be used) + * 0x0210_0000 l-loader limit (max bootrom can accept) + * fip.bin load zone: 768 KiB + * 0x0204_0000 + * bl31: 80 KiB + * 0x0202_A000 + * bl2: 48 KiB + * 0x0201_E000 + * bl1: 64 KiB + * 0x0200_E000 + * l-loader text: 52 KiB + * 0x0200_1000 + * unused + * 0x0200_0000 + * TA virtual memory space + * 0x0000_0000 [DRAM0_BASE] + */ +#define DRAM0_BASE 0x00000000 +#if (CFG_DRAM_SIZE_GB == 2) +#define DRAM0_SIZE 0x80000000 +#elif (CFG_DRAM_SIZE_GB == 1) +#define DRAM0_SIZE 0x40000000 +#else +#error Unsupported DRAM size +#endif + +#define DRAM0_BASE_NSEC 0x04080000 +#define DRAM0_SIZE_NSEC (DRAM0_SIZE - DRAM0_BASE_NSEC) + +#define DRAM2_BASE 0xF0000000 +#define DRAM2_SIZE 0x0F000000 + +#ifdef CFG_WITH_PAGER + +#define TZSRAM_BASE 0x03000000 +#define TZSRAM_SIZE CFG_CORE_TZSRAM_EMUL_SIZE + +#define TZDRAM_BASE 0x03200000 +#define TZDRAM_SIZE (14 * 1024 * 1024) + +#define TEE_RAM_START TZSRAM_BASE +#define TEE_RAM_PH_SIZE TZSRAM_SIZE +#define TA_RAM_START ROUNDUP(TZDRAM_BASE, CORE_MMU_PGDIR_SIZE) +#define TA_RAM_SIZE ROUNDDOWN(TZDRAM_SIZE, CORE_MMU_PGDIR_SIZE) + +#else /* CFG_WITH_PAGER */ + +#define TZDRAM_BASE 0x03000000 +#define TZDRAM_SIZE (16 * 1024 * 1024) + +#define TEE_RAM_START TZDRAM_BASE +#define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE +#define TA_RAM_START ROUNDUP((TZDRAM_BASE + TEE_RAM_VA_SIZE), \ + CORE_MMU_PGDIR_SIZE) + +#define TA_RAM_SIZE ROUNDDOWN((TZDRAM_SIZE - TEE_RAM_VA_SIZE),\ + CORE_MMU_PGDIR_SIZE) + +#endif /* CFG_WITH_PAGER */ + +#define TEE_SHMEM_START 0x02400000 +#define TEE_SHMEM_SIZE (4 * 1024 * 1024) + +#define TEE_RAM_VA_SIZE (2 * 1024 * 1024) + +#define TEE_LOAD_ADDR 0x03000000 /* BL32_BASE */ + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-poplar/sub.mk b/optee/optee_os/core/arch/arm/plat-poplar/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-poplar/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-rcar/conf.mk b/optee/optee_os/core/arch/arm/plat-rcar/conf.mk new file mode 100644 index 0000000..0de4143 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/conf.mk @@ -0,0 +1,42 @@ +PLATFORM_FLAVOR ?= generic_dt + +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_SCIF,y) +$(call force,CFG_GIC,y) +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_WITH_LPAE,y) + +ifeq ($(PLATFORM_FLAVOR), spider_s4) +$(call force,CFG_RCAR_GEN4, y) +else +$(call force,CFG_RCAR_GEN3, y) +endif + +CFG_TZDRAM_START ?= 0x44100000 +CFG_TZDRAM_SIZE ?= 0x03D00000 +CFG_TEE_RAM_VA_SIZE ?= 0x100000 +supported-ta-targets = ta_arm64 + +ifeq ($(CFG_RCAR_GEN3), y) +CFG_WITH_SOFTWARE_PRNG ?= n +CFG_HWRNG_QUALITY ?= 1024 +CFG_HWRNG_PTA ?= y +CFG_DT ?= y +$(call force,CFG_RCAR_ROMAPI, y) +endif + +ifeq ($(CFG_RCAR_GEN4), y) +# 1xx - for SCIFxx +# 2xx - for HSCIFxx +CFG_RCAR_UART ?= 200 +$(call force,CFG_RCAR_ROMAPI, n) +$(call force,CFG_CORE_CLUSTER_SHIFT, 1) +$(call force,CFG_ARM_GICV3, y) +endif + diff --git a/optee/optee_os/core/arch/arm/plat-rcar/core_pos_a64.S b/optee/optee_os/core/arch/arm/plat-rcar/core_pos_a64.S new file mode 100644 index 0000000..ff25c85 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/core_pos_a64.S @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2019, Arm Limited. All rights reserved. + * Copyright (c) 2020, Marek Vasut + */ + +#include +#include +#include +#include +#include "rcar.h" + +FUNC get_core_pos_mpidr , : + /* + * Shift MPIDR value if it's not already shifted. + * Using logical shift ensures AFF0 to be filled with zeroes. + * This part is necessary even if CFG_CORE_THREAD_SHIFT is 0 because + * MT bit can be set on single threaded systems where all the AFF0 + * values are zeroes. + */ + tst x0, #MPIDR_MT_MASK + lsl x3, x0, #MPIDR_AFFINITY_BITS + csel x3, x3, x0, eq + + /* + * At this point the MPIDR layout is always shifted so it looks + * as follows AFF2 -> cluster, AFF1 -> core, AFF0 -> thread + */ + /* Calculate CorePos = (ClusterId * (cores/cluster)) + CoreId */ + ubfx x0, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS + ubfx x1, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS + + /* + * R-Car M3W/M3W+ have 6 cores, but internally cluster 0 has two + * cores (0, 1) and cluster 1 has four cores (4, 5, 6, 7). Other + * R-Car SoCs either have two full clusters (4xCA57 + 4xCA53) or + * they have one cluster. + * + * The code below normalizes the M3W/M3W+ core enumeration such + * that cluster 0 returns core IDs {0, 1} and cluster 1 returns + * core IDs {2, 3, 4, 5}. This is achieved by calculating the + * core ID as CorePos = CoreId + (ClusterId << (IsM3W ? 1 : 0)) + */ + + adr_l x2, rcar_prr_value + ldr w3, [x2] + cmp w3, wzr + bne 1f + + /* Load PRR PRODUCT into x3 */ + mov x2, #PRR_BASE + ldr w3, [x2, #PRR_OFFSET] + /* + * Cache the PRR register value. PRR value does not change at runtime. + * This function is first called with MMU disabled, so it is possible + * to read the PRR register via its physical address, but once MMU is + * enabled, this is no longer possible as the virtual address is not + * available here, so in that case, use the cached value of the PRR. + */ + adr_l x2, rcar_prr_value + str w3, [x2] + +1: mov w2, #PRR_PRODUCT_M3W + and w3, w3, #PRR_PRODUCT_MASK + cmp w2, w3 + beq 2f /* if (!IsM3W) { x1 <<= 2; } else { x1 <<= 1} */ + lsl x1, x1, #1 +2: lsl x1, x1, #1 + add x0, x0, x1 + + ret +END_FUNC get_core_pos_mpidr diff --git a/optee/optee_os/core/arch/arm/plat-rcar/hw_rng.c b/optee/optee_os/core/arch/arm/plat-rcar/hw_rng.c new file mode 100644 index 0000000..b8496e8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/hw_rng.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* Copyright (c) 2021, EPAM Systems. All rights reserved. */ + +#include +#include +#include +#include +#include +#include + +#include "romapi.h" + +#define SCRATCH_BUF_SZ 4096 + +static uint8_t scratch_buf[SCRATCH_BUF_SZ] __nex_bss + __aligned(RCAR_CACHE_LINE_SZ); +static unsigned int spin_lock __nex_data = SPINLOCK_UNLOCK; + +/* + * It is inefficient to call ROM_GetRndVector() every time we want 8 bits of + * random data, so we will cache the unused values for latter use. + */ +static uint8_t rng_cache[PLAT_RND_VECTOR_SZ] __nex_bss + __aligned(RCAR_CACHE_LINE_SZ); +static uint8_t rng_cache_pos __nex_data; + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + uint32_t exceptions; + uint8_t *buffer = buf; + size_t buffer_pos = 0; + uint8_t ret_val = 0; + + assert(rng_cache_pos < PLAT_RND_VECTOR_SZ); + + while (buffer_pos < len) { + exceptions = cpu_spin_lock_xsave(&spin_lock); + /* Refill our FIFO */ + if (rng_cache_pos == 0) { + uint32_t ret = plat_rom_getrndvector(rng_cache, + scratch_buf, + sizeof(scratch_buf)); + if (ret != 0) + panic("ROM_GetRndVector() returned error!"); + } + + buffer[buffer_pos++] = rng_cache[rng_cache_pos++]; + if (rng_cache_pos == PLAT_RND_VECTOR_SZ) + rng_cache_pos = 0; + + cpu_spin_unlock_xrestore(&spin_lock, exceptions); + } + + return ret_val; +} diff --git a/optee/optee_os/core/arch/arm/plat-rcar/link.mk b/optee/optee_os/core/arch/arm/plat-rcar/link.mk new file mode 100644 index 0000000..51fc371 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/link.mk @@ -0,0 +1,5 @@ +include core/arch/arm/kernel/link.mk + +SRECFLAGS ?= --srec-forceS3 --adjust-vma=$(CFG_TZDRAM_START) + +all: $(link-out-dir)/tee.srec diff --git a/optee/optee_os/core/arch/arm/plat-rcar/main.c b/optee/optee_os/core/arch/arm/plat-rcar/main.c new file mode 100644 index 0000000..ac8d20e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/main.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, GlobalLogic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, SCIF_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE); +#ifdef PRR_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, PRR_BASE, SMALL_PAGE_SIZE); +#endif + +/* Legacy platforms */ +#if defined(PLATFORM_FLAVOR_salvator_h3) || \ + defined(PLATFORM_FLAVOR_salvator_h3_4x2g) || \ + defined(PLATFORM_FLAVOR_salvator_m3) || \ + defined(PLATFORM_FLAVOR_salvator_m3_2x4g) || \ + defined(PLATFORM_FLAVOR_spider_s4) +register_ddr(NSEC_DDR_0_BASE, NSEC_DDR_0_SIZE); +register_ddr(NSEC_DDR_1_BASE, NSEC_DDR_1_SIZE); +#ifdef NSEC_DDR_2_BASE +register_ddr(NSEC_DDR_2_BASE, NSEC_DDR_2_SIZE); +#endif +#ifdef NSEC_DDR_3_BASE +register_ddr(NSEC_DDR_3_BASE, NSEC_DDR_3_SIZE); +#endif +#endif + +static struct scif_uart_data console_data __nex_bss; +static struct gic_data gic_data __nex_bss; + +#ifdef PRR_BASE +uint32_t rcar_prr_value __nex_bss; +#endif + +void console_init(void) +{ + scif_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +} + +#ifdef CFG_RCAR_ROMAPI +/* Should only seed from a hardware random number generator */ +static_assert(!IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)); + +unsigned long plat_get_aslr_seed(void) +{ + unsigned long seed = 0; + + /* On RCAR we can get hw random bytes on early boot stages */ + if (crypto_rng_read(&seed, sizeof(seed))) + panic(); + + return seed; +} +#endif + +void main_init_gic(void) +{ + gic_init(&gic_data, GICC_BASE, GICD_BASE); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + diff --git a/optee/optee_os/core/arch/arm/plat-rcar/platform_config.h b/optee/optee_os/core/arch/arm/plat-rcar/platform_config.h new file mode 100644 index 0000000..f9d5d71 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/platform_config.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, GlobalLogic + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +#define RCAR_CACHE_LINE_SZ 64 + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT RCAR_CACHE_LINE_SZ + +#if defined(CFG_RCAR_GEN3) + +#define GIC_BASE 0xF1000000 +#define GICC_BASE 0xF1020000 +#define GICD_BASE 0xF1010000 + +#define CONSOLE_UART_BASE 0xE6E88000 + +#define PRR_BASE 0xFFF00000 + +#elif defined(CFG_RCAR_GEN4) + +#define GICC_BASE 0xF1060000 +#define GICD_BASE 0xF1000000 + +#if CFG_RCAR_UART == 103 /* SCIF3 */ +#define CONSOLE_UART_BASE 0xE6C50000 +#elif CFG_RCAR_UART == 200 /* HSCIF0 */ +#define CONSOLE_UART_BASE 0xE6540000 +#endif + +#endif /* CFG_RCAR_GENx */ + +#if defined(PLATFORM_FLAVOR_salvator_h3) +#define NSEC_DDR_0_BASE 0x47E00000 +#define NSEC_DDR_0_SIZE 0x38200000 +#define NSEC_DDR_1_BASE 0x500000000U +#define NSEC_DDR_1_SIZE 0x40000000 +#define NSEC_DDR_2_BASE 0x600000000U +#define NSEC_DDR_2_SIZE 0x40000000 +#define NSEC_DDR_3_BASE 0x700000000U +#define NSEC_DDR_3_SIZE 0x40000000 + +#elif defined(PLATFORM_FLAVOR_salvator_h3_4x2g) +#define NSEC_DDR_0_BASE 0x47E00000 +#define NSEC_DDR_0_SIZE 0x78200000 +#define NSEC_DDR_1_BASE 0x500000000U +#define NSEC_DDR_1_SIZE 0x80000000 +#define NSEC_DDR_2_BASE 0x600000000U +#define NSEC_DDR_2_SIZE 0x80000000 +#define NSEC_DDR_3_BASE 0x700000000U +#define NSEC_DDR_3_SIZE 0x80000000 + +#elif defined(PLATFORM_FLAVOR_salvator_m3) +#define NSEC_DDR_0_BASE 0x47E00000 +#define NSEC_DDR_0_SIZE 0x78200000 +#define NSEC_DDR_1_BASE 0x600000000U +#define NSEC_DDR_1_SIZE 0x80000000 + +#elif defined(PLATFORM_FLAVOR_salvator_m3_2x4g) +#define NSEC_DDR_0_BASE 0x47E00000 +#define NSEC_DDR_0_SIZE 0x78200000 +#define NSEC_DDR_1_BASE 0x480000000U +#define NSEC_DDR_1_SIZE 0x80000000 +#define NSEC_DDR_2_BASE 0x600000000U +#define NSEC_DDR_2_SIZE 0x100000000U + +#elif defined(PLATFORM_FLAVOR_spider_s4) +#define NSEC_DDR_0_BASE 0x48000000 +#define NSEC_DDR_0_SIZE 0x78000000 +#define NSEC_DDR_1_BASE 0x480000000U +#define NSEC_DDR_1_SIZE 0x80000000U + +#else + +/* Generic DT-based platform */ + +#endif + +/* Full GlobalPlatform test suite requires TEE_SHMEM_SIZE to be at least 2MB */ +#define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) +#define TEE_SHMEM_SIZE 0x100000 + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-rcar/rcar.h b/optee/optee_os/core/arch/arm/plat-rcar/rcar.h new file mode 100644 index 0000000..a14cbf9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/rcar.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2021, EPAM Systems. All rights reserved. */ + +#ifndef PLAT_RCAR_RCAR_H +#define PLAT_RCAR_RCAR_H + +#define PRR_OFFSET 0x44 +#define PRR_PRODUCT_H3 0x4F00 +#define PRR_PRODUCT_M3W 0x5200 +#define PRR_PRODUCT_MASK 0xFF00 +#define PRR_CUT_MASK 0xFF +#define PRR_CUT_10 0x00 /* Ver 1.0 */ +#define PRR_CUT_11 0x01 /* Ver 1.1 */ +#define PRR_CUT_20 0x10 /* Ver 2.0 */ +#define PRR_CUT_30 0x20 /* Ver.3.0 */ + +#ifndef __ASSEMBLER__ +extern uint32_t rcar_prr_value; +#endif + +#endif /* PLAT_RCAR_RCAR_H */ diff --git a/optee/optee_os/core/arch/arm/plat-rcar/romapi.c b/optee/optee_os/core/arch/arm/plat-rcar/romapi.c new file mode 100644 index 0000000..ad0a0d9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/romapi.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, EPAM Systems + */ +#include +#include +#include +#include + +#include "rcar.h" +#include "romapi.h" + +static int get_api_table_index(void) +{ + /* + * Depending on SoC type and version, there are 4 possible addresses + * for each ROMAPI function + */ + static int index __nex_data = -1; + + if (index != -1) + return index; + + switch (rcar_prr_value & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: + switch (rcar_prr_value & PRR_CUT_MASK) { + case PRR_CUT_10: /* H3 ES1.0 */ + case PRR_CUT_11: /* H3 ES1.1 */ + index = 0; + break; + case PRR_CUT_20: /* H3 ES2.0 */ + index = 1; + break; + default: /* Newer H3 versions use unified table */ + index = 3; + break; + } + break; + case PRR_PRODUCT_M3W: + switch (rcar_prr_value & PRR_CUT_MASK) { + case PRR_CUT_10: /* M3 ES1.0 */ + index = 2; + break; + default: /* Newer M3 versions use unified table */ + index = 3; + break; + } + break; + default: /* All other SoCs use unified table */ + index = 3; + break; + } + + return index; +} + +/* implemented in romapi_call.S */ +extern uint32_t __plat_romapi_wrapper(paddr_t func, uint64_t arg1, + uint64_t arg2, uint64_t arg3); + +static uint32_t __plat_romapi_direct(paddr_t func, uint64_t arg1, + uint64_t arg2, uint64_t arg3) +{ + uint32_t (*fptr)(uint64_t arg1, uint64_t arg2, uint64_t arg3) = NULL; + + assert(!cpu_mmu_enabled()); + + fptr = (typeof(fptr))func; + + return fptr(arg1, arg2, arg3); +} + +static uint32_t plat_call_romapi(paddr_t func, uint64_t arg1, + uint64_t arg2, uint64_t arg3) +{ + uint32_t (*fptr)(paddr_t func, uint64_t arg1, uint64_t arg2, + uint64_t arg3) = NULL; + + /* + * If MMU is enabled, we need to use trampoline function that will + * disable MMU and switch stack pointer to physical address. On other + * hand, if MMU is disabled, we can call the ROM function directly. + */ + if (cpu_mmu_enabled()) + /* + * With ASLR enabled __plat_romapi_wrapper() function will be + * mapped at two addresses: at random address (with the rest of + * OP-TEE) and at identity address. We need to map it at + * identity address and call it at identity address because this + * function turns off MMU to perform ROM API call. But + * __plat_romapi_wrapper *symbol* will be relocated by ASLR + * code. To get identity address of the function we need to use + * virt_to_phys(). + */ + fptr = (void *)virt_to_phys(__plat_romapi_wrapper); + else + /* + * With MMU disabled we can call ROM code directly. + */ + fptr = __plat_romapi_direct; + + return fptr(func, arg1, arg2, arg3); +} + +static paddr_t va2pa(void *ptr) +{ + if (cpu_mmu_enabled()) + return virt_to_phys(ptr); + else + return (paddr_t)ptr; +} + +static const paddr_t romapi_getrndvector[] = { + 0xEB10DFC4, /* H3 1.0/1.1, needs confirmation */ + 0xEB117134, /* H3 2.0 */ + 0xEB11055C, /* M3 1.0/1.05, needs confirmation */ + 0xEB100188, /* H3 3.0, M3 1.1+, M3N, E3, D3, V3M 2.0 */ +}; + +uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ], + uint8_t *scratch, uint32_t scratch_sz) +{ + uint32_t ret = -1; + paddr_t func_addr = romapi_getrndvector[get_api_table_index()]; + paddr_t rndbuff_pa = va2pa(rndbuff); + paddr_t scratch_pa = va2pa(scratch); + + assert(scratch_sz >= 4096); + assert(rndbuff_pa % RCAR_CACHE_LINE_SZ == 0); + assert(scratch_pa % RCAR_CACHE_LINE_SZ == 0); + + ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa, scratch_sz); + + /* + * ROM code is called with MMU turned off, so any accesses to rndbuff + * are not affected by data cache. This can lead to two problems: + * + * 1. Any prior writes can be cached but may not reach memory. So staled + * values can be flushed to memory later and overwrite new data written + * by ROM code. This includes stack as well. + * + * 2. ROM code will write new data to the buffer, but we may see old, + * cached values. + * + * ROM code wrapper will issue dcache_op_all(DCACHE_OP_CLEAN). This will + * ensure that all writes reached memory. After the call we need to + * invalidate the cache to see new data. + * + * We are not accessing scratch area, so no need to do cache maintenance + * for that buffer. + */ + cache_op_inner(DCACHE_AREA_INVALIDATE, rndbuff, PLAT_RND_VECTOR_SZ); + + return ret; +} diff --git a/optee/optee_os/core/arch/arm/plat-rcar/romapi.h b/optee/optee_os/core/arch/arm/plat-rcar/romapi.h new file mode 100644 index 0000000..8efa0eb --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/romapi.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, EPAM Systems + */ + +#ifndef __ROMAPI_H +#define __ROMAPI_H + +#include + +/* + * Mask ROM provides number of facilities, including function that returns 32 + * byte random vector. + */ +#define PLAT_RND_VECTOR_SZ 32 + +/* + * Call to this function must be protected by a spinlock, because ROM code + * accesses hardware. This function requires at least 4kb scratch buffer to + * work. All parameters should be aligned to 8 bytes. + */ +uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ], + uint8_t *scratch, + uint32_t scratch_sz); + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-rcar/romapi_call.S b/optee/optee_os/core/arch/arm/plat-rcar/romapi_call.S new file mode 100644 index 0000000..975eddb --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/romapi_call.S @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, EPAM Systems + */ + +#include +#include +#include +#include +#include + +/* uint32_t __plat_romapi_wrapper(paddr_t func, uint64_t arg1, uint64_t arg2, + * uint64_t arg3) + * Call MaskROM function func(arg1, arg2, arg3). + * We need to disable MMU before calling any MaskROM API functions + */ +FUNC __plat_romapi_wrapper , : , .identity_map + + push fp, lr + push x19, x20 + push x21, x22 + push x23, x24 + + mov x19, x0 + mov x20, x1 + mov x21, x2 + mov x22, x3 + + /* Get PA of stack pointer */ + mov x0, sp +#ifdef CFG_CORE_ASLR + /* + * We are running at identity location, so we can't use bl there, + * because assembler will generate relative address to virt_to_phys(), + * which is not identity mapped. + */ + adr_l x9, virt_to_phys + ldr x10, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET + add x9, x9, x10 + blr x9 +#else + bl virt_to_phys +#endif + mov x23, x0 + + /* We about to disable MMU. Make sure that all writes reached memory */ + mov x0, #DCACHE_OP_CLEAN +#ifdef CFG_CORE_ASLR + /* See the comment above */ + adr_l x9, dcache_op_all + ldr x10, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET + add x9, x9, x10 + blr x9 +#else + bl dcache_op_all +#endif + + /* Disable MMU */ + mrs x9, sctlr_el1 + bic x9, x9, #SCTLR_M + bic x9, x9, #SCTLR_C + msr sctlr_el1, x9 + isb + /* Invalidate instruction cache and branch predictor */ + ic ialluis + dsb ish /* ensure that maintenance operations are seen */ + isb + + /* Save old SP to x24 and switch to a new stack */ + mov x24, sp + mov sp, x23 + + /* call the function */ + mov x0, x20 /* x20: uint64_t arg1 */ + mov x1, x21 /* x21: uint64_t arg2 */ + mov x2, x22 /* x22: uint64_t arg3 */ + blr x19 /* x19: paddr_t func */ + + /* restore sp */ + mov sp, x24 + + /* Enable MMU */ + mrs x9, sctlr_el1 + orr x9, x9, #SCTLR_M + orr x9, x9, #SCTLR_C + msr sctlr_el1, x9 + isb + + /* Invalidate instruction cache and branch predictor */ + ic iallu + isb + + pop x23, x24 + pop x21, x22 + pop x19, x20 + pop fp, lr + ret +END_FUNC __plat_romapi_wrapper diff --git a/optee/optee_os/core/arch/arm/plat-rcar/sub.mk b/optee/optee_os/core/arch/arm/plat-rcar/sub.mk new file mode 100644 index 0000000..2cbed17 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rcar/sub.mk @@ -0,0 +1,6 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-${CFG_RCAR_GEN3} += core_pos_a64.S +srcs-${CFG_RCAR_ROMAPI} += romapi.c +srcs-${CFG_RCAR_ROMAPI} += romapi_call.S +srcs-${CFG_RCAR_ROMAPI} += hw_rng.c diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/common.h b/optee/optee_os/core/arch/arm/plat-rockchip/common.h new file mode 100644 index 0000000..7111891 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/common.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + */ + +#ifndef PLAT_ROCKCHIP_COMMON_H +#define PLAT_ROCKCHIP_COMMON_H + +/* For SMP cpu bootup, they are common for rockchip platforms */ +#define LOCK_TAG 0xDEADBEAF +#define LOCK_ADDR_OFFSET 4 +#define BOOT_ADDR_OFFSET 8 + +/* + * Some register has write-mask bits, it means if you want to set the bits, + * you need set the write-mask bits at the same time, the write-mask bits is + * in high 16-bits. The following macro definition helps you access register + * efficiently. + */ +#define REG_MSK_SHIFT 16 +#define WMSK_BIT(nr) BIT((nr) + REG_MSK_SHIFT) +#define BIT_WITH_WMSK(nr) (BIT(nr) | WMSK_BIT(nr)) +#define BITS_WMSK(msk, shift) SHIFT_U32(msk, (shift) + REG_MSK_SHIFT) +#define BITS_WITH_WMASK(bits, msk, shift) \ + (SHIFT_U32(bits, shift) | BITS_WMSK(msk, shift)) + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/conf.mk b/optee/optee_os/core/arch/arm/plat-rockchip/conf.mk new file mode 100644 index 0000000..e8e9f4c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/conf.mk @@ -0,0 +1,63 @@ +PLATFORM_FLAVOR ?= rk322x + +$(call force,CFG_GIC,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_8250_UART,y) + +CFG_DT ?= y +CFG_WITH_STATS ?= y +CFG_NUM_THREADS ?= 4 + +ifeq ($(PLATFORM_FLAVOR),rk322x) +include ./core/arch/arm/cpu/cortex-a7.mk +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_PSCI_ARM32,y) +$(call force,CFG_BOOT_SECONDARY_REQUEST,y) + +CFG_TZDRAM_START ?= 0x68400000 +CFG_TZDRAM_SIZE ?= 0x00200000 +CFG_SHMEM_START ?= 0x68600000 +CFG_SHMEM_SIZE ?= 0x00100000 + +CFG_EARLY_CONSOLE ?= y +CFG_EARLY_CONSOLE_BASE ?= UART2_BASE +CFG_EARLY_CONSOLE_SIZE ?= UART2_SIZE +CFG_EARLY_CONSOLE_BAUDRATE ?= 1500000 +CFG_EARLY_CONSOLE_CLK_IN_HZ ?= 24000000 +endif + +ifeq ($(PLATFORM_FLAVOR),rk3399) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,6) +$(call force,CFG_ARM_GICV3,y) +CFG_CRYPTO_WITH_CE ?= y + +CFG_TZDRAM_START ?= 0x30000000 +CFG_TZDRAM_SIZE ?= 0x02000000 +CFG_SHMEM_START ?= 0x32000000 +CFG_SHMEM_SIZE ?= 0x00400000 + +CFG_EARLY_CONSOLE ?= y +CFG_EARLY_CONSOLE_BASE ?= UART2_BASE +CFG_EARLY_CONSOLE_SIZE ?= UART2_SIZE +CFG_EARLY_CONSOLE_BAUDRATE ?= 1500000 +CFG_EARLY_CONSOLE_CLK_IN_HZ ?= 24000000 +endif + +ifeq ($(PLATFORM_FLAVOR),px30) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,4) + +CFG_TZDRAM_START ?= 0x30000000 +CFG_TZDRAM_SIZE ?= 0x02000000 +CFG_SHMEM_START ?= 0x32000000 +CFG_SHMEM_SIZE ?= 0x00400000 + +CFG_EARLY_CONSOLE ?= n +endif + +ifeq ($(platform-flavor-armv8),1) +$(call force,CFG_ARM64_core,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +ta-targets = ta_arm64 +endif diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/core_pos_a32.S b/optee/optee_os/core/arch/arm/plat-rockchip/core_pos_a32.S new file mode 100644 index 0000000..5994c46 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/core_pos_a32.S @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include + +FUNC get_core_pos_mpidr , : + /* + * Because mpidr is designed mistake in hardware, ie. core0 is 0xf00, + * core1 is 0xf01..., so we need implement the function to correct this. + */ + and r0, r0, #MPIDR_CPU_MASK + bx lr +END_FUNC get_core_pos_mpidr + diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/cru.h b/optee/optee_os/core/arch/arm/plat-rockchip/cru.h new file mode 100644 index 0000000..afbf387 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/cru.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + */ + +#ifndef PLAT_ROCKCHIP_CRU_H +#define PLAT_ROCKCHIP_CRU_H + +#include +#include + +#if defined(PLATFORM_FLAVOR_rk322x) + +enum plls_id { + APLL_ID, + DPLL_ID, + CPLL_ID, + GPLL_ID, + PLL_END, +}; + +#define CRU_SOFTRST_CON(i) (0x110 + ((i) * 4)) +#define CRU_MODE_CON 0x040 +#define CRU_GLBRST_CFG_BASE 0x140 +#define CRU_FSTRST_VAL_BASE 0x1f0 +#define CRU_SNDRST_VAL_BASE 0x1f4 +#define CRU_FSTRST_VAL 0xfdb9 +#define CRU_SNDRST_VAL 0xeca8 +#define PLLS_SLOW_MODE 0x11030000 + +#define CORE_SOFT_RESET(core) SHIFT_U32(0x100010, (core)) +#define CORE_SOFT_RELEASE(core) SHIFT_U32(0x100000, (core)) +#define CORE_HELD_IN_RESET(core) SHIFT_U32(0x000010, (core)) +#define NONBOOT_CORES_SOFT_RESET 0x00e000e0 + +#define CRU_CLKGATE_CON_CNT 16 +#define CRU_CLKSEL_CON(i) (0x044 + ((i) * 4)) +#define CRU_CLKGATE_CON(i) (0x0d0 + ((i) * 4)) +#define CRU_PLL_CON0(pll) ((pll) * 0x0c + 0x0) +#define CRU_PLL_CON1(pll) ((pll) * 0x0c + 0x4) +#define CRU_PLL_CON2(pll) ((pll) * 0x0c + 0x8) + +#define PLL_LOCK BIT(10) +#define PLL_POWER_UP BITS_WITH_WMASK(0, 1, 13) +#define PLL_POWER_DOWN BITS_WITH_WMASK(1, 1, 13) + +#define PLL_MODE_BIT(pll) ((pll) * 4) +#define PLL_MODE_MSK(pll) BIT(PLL_MODE_BIT(pll)) +#define PLL_SLOW_MODE(pll) BITS_WITH_WMASK(0, 1, PLL_MODE_BIT(pll)) +#define PLL_NORM_MODE(pll) BITS_WITH_WMASK(1, 1, PLL_MODE_BIT(pll)) +#endif + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/grf.h b/optee/optee_os/core/arch/arm/plat-rockchip/grf.h new file mode 100644 index 0000000..40caae6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/grf.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + */ + +#ifndef PLAT_ROCKCHIP_GRF_H +#define PLAT_ROCKCHIP_GRF_H + +#if defined(PLATFORM_FLAVOR_rk322x) +#define GRF_CPU_STATUS1 0x524 + +#define CORE_WFE_MASK(core) SHIFT_U32(0x02, (core)) +#define CORE_WFI_MASK(core) SHIFT_U32(0x20, (core)) +#define CORE_WFE_I_MASK(core) (CORE_WFI_MASK(core) | CORE_WFE_MASK(core)) +#endif + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/main.c b/optee/optee_os/core/arch/arm/plat-rockchip/main.c new file mode 100644 index 0000000..05def50 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/main.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct gic_data gic_data; + +#if defined(CFG_EARLY_CONSOLE) +static struct serial8250_uart_data early_console_data; +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, + CFG_EARLY_CONSOLE_BASE, CFG_EARLY_CONSOLE_SIZE); +#endif + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); + +void main_init_gic(void) +{ + gic_init(&gic_data, GICC_BASE, GICD_BASE); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +void console_init(void) +{ +#if defined(CFG_EARLY_CONSOLE) + /* + * Console devices can vary a lot between devices and + * OP-TEE will switch to the DT-based real console later, + * based on DT-devices and the systems chosen node. + * So early console is only needed for early debugging. + */ + serial8250_uart_init(&early_console_data, + CFG_EARLY_CONSOLE_BASE, + CFG_EARLY_CONSOLE_CLK_IN_HZ, + CFG_EARLY_CONSOLE_BAUDRATE); + register_serial_console(&early_console_data.chip); +#endif +} diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/plat_init.S b/optee/optee_os/core/arch/arm/plat-rockchip/plat_init.S new file mode 100644 index 0000000..fb084af --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/plat_init.S @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include + +FUNC plat_cpu_reset_early , : + + /* Enable SMP bit */ + read_actlr r0 + orr r0, r0, #ACTLR_SMP + write_actlr r0 + bx lr +END_FUNC plat_cpu_reset_early + diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/platform.c b/optee/optee_os/core/arch/arm/plat-rockchip/platform.c new file mode 100644 index 0000000..96c343f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/platform.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include + +int __weak platform_secure_init(void) +{ + return 0; +} + +int __weak platform_secure_ddr_region(int rgn __maybe_unused, + paddr_t st __maybe_unused, + size_t sz __maybe_unused) +{ + MSG("Not protecting region %d: 0x%lx-0x%lx\n", rgn, st, st + sz); + + return 0; +} + +static TEE_Result platform_init(void) +{ + int ret = 0; + + platform_secure_init(); + + /* + * Rockchip SoCs can protect multiple memory regions (mostly 8). + * Region 0 is assigned for Trusted-Firmware memory, so use + * regions 1 for OP-TEE memory, which leaves on all known SoCs + * at least 6 more regions available for other purposes. + */ + ret = platform_secure_ddr_region(1, CFG_TZDRAM_START, CFG_TZDRAM_SIZE); + if (ret < 0) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +service_init(platform_init); diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/platform.h b/optee/optee_os/core/arch/arm/plat-rockchip/platform.h new file mode 100644 index 0000000..7b79b86 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/platform.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +#ifndef PLAT_ROCKCHIP_PLATFORM_H +#define PLAT_ROCKCHIP_PLATFORM_H + +int platform_secure_init(void); +int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz); + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/platform_config.h b/optee/optee_os/core/arch/arm/plat-rockchip/platform_config.h new file mode 100644 index 0000000..31439e2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/platform_config.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#define SIZE_K(n) ((n) * 1024) +#define SIZE_M(n) ((n) * 1024 * 1024) + +#if defined(PLATFORM_FLAVOR_rk322x) + +#define GIC_BASE 0x32010000 +#define GIC_SIZE SIZE_K(64) +#define GICD_BASE (GIC_BASE + 0x1000) +#define GICC_BASE (GIC_BASE + 0x2000) + +#define SGRF_BASE 0x10140000 +#define SGRF_SIZE SIZE_K(64) + +#define DDRSGRF_BASE 0x10150000 +#define DDRSGRF_SIZE SIZE_K(64) + +#define GRF_BASE 0x11000000 +#define GRF_SIZE SIZE_K(64) + +#define UART2_BASE 0x11030000 +#define UART2_SIZE SIZE_K(64) + +#define CRU_BASE 0x110e0000 +#define CRU_SIZE SIZE_K(64) + +/* Internal SRAM */ +#define ISRAM_BASE 0x10080000 +#define ISRAM_SIZE SIZE_K(8) + +#elif defined(PLATFORM_FLAVOR_rk3399) + +#define MMIO_BASE 0xF8000000 + +#define GIC_BASE (MMIO_BASE + 0x06E00000) +#define GIC_SIZE SIZE_M(2) +#define GICC_BASE (MMIO_BASE + 0x07F00000) +#define GICD_BASE GIC_BASE +#define GICR_BASE (GIC_BASE + SIZE_M(1)) + +#define UART0_BASE (MMIO_BASE + 0x07180000) +#define UART0_SIZE SIZE_K(64) + +#define UART1_BASE (MMIO_BASE + 0x07190000) +#define UART1_SIZE SIZE_K(64) + +#define UART2_BASE (MMIO_BASE + 0x071A0000) +#define UART2_SIZE SIZE_K(64) + +#define UART3_BASE (MMIO_BASE + 0x071B0000) +#define UART3_SIZE SIZE_K(64) + +#define SGRF_BASE (MMIO_BASE + 0x07330000) +#define SGRF_SIZE SIZE_K(64) + +#elif defined(PLATFORM_FLAVOR_px30) + +#define GIC_BASE 0xff130000 +#define GIC_SIZE SIZE_K(64) +#define GICD_BASE (GIC_BASE + 0x1000) +#define GICC_BASE (GIC_BASE + 0x2000) + +#define UART1_BASE 0xff158000 +#define UART1_SIZE SIZE_K(64) + +#define UART2_BASE 0xff160000 +#define UART2_SIZE SIZE_K(64) + +#define UART5_BASE 0xff178000 +#define UART5_SIZE SIZE_K(64) + +#define FIREWALL_DDR_BASE 0xff534000 +#define FIREWALL_DDR_SIZE SIZE_K(16) + +#else +#error "Unknown platform flavor" +#endif + +#ifdef CFG_WITH_LPAE +#define MAX_XLAT_TABLES 5 +#endif + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/platform_px30.c b/optee/optee_os/core/arch/arm/plat-rockchip/platform_px30.c new file mode 100644 index 0000000..8327ca9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/platform_px30.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +#include +#include +#include +#include +#include +#include + +#define FIREWALL_DDR_FW_DDR_RGN(i) ((i) * 0x4) +#define FIREWALL_DDR_FW_DDR_MST(i) (0x20 + (i) * 0x4) +#define FIREWALL_DDR_FW_DDR_CON_REG 0x40 +#define FIREWALL_DDR_FW_DDR_RGN_NUM 8 +#define FIREWALL_DDR_FW_DDR_MST_NUM 6 + +#define RG_MAP_SECURE(top, base) ((((top) - 1) << 16) | (base)) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE); + +int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz) +{ + vaddr_t fw_base = (vaddr_t)phys_to_virt_io(FIREWALL_DDR_BASE, + FIREWALL_DDR_SIZE); + paddr_t ed = st + sz; + uint32_t st_mb = st / SIZE_M(1); + uint32_t ed_mb = ed / SIZE_M(1); + + if (!fw_base) + panic(); + + assert(rgn <= 7); + assert(st < ed); + + /* Check aligned 1MB */ + assert(st % SIZE_M(1) == 0); + assert(ed % SIZE_M(1) == 0); + + DMSG("protecting region %d: 0x%lx-0x%lx\n", rgn, st, ed); + + /* Map top and base */ + io_write32(fw_base + FIREWALL_DDR_FW_DDR_RGN(rgn), + RG_MAP_SECURE(ed_mb, st_mb)); + + /* Enable secure setting */ + io_setbits32(fw_base + FIREWALL_DDR_FW_DDR_CON_REG, BIT(rgn)); + + return 0; +} diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/platform_rk322x.c b/optee/optee_os/core/arch/arm/plat-rockchip/platform_rk322x.c new file mode 100644 index 0000000..9b530b6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/platform_rk322x.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SGRF_BASE, SGRF_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, DDRSGRF_BASE, DDRSGRF_SIZE); + +#define SGRF_SOC_CON(n) ((n) * 4) +#define DDR_SGRF_DDR_CON(n) ((n) * 4) +#define DDR_RGN0_NS BIT32(30) +#define SLAVE_ALL_NS GENMASK_32(31, 16) + +int platform_secure_init(void) +{ + vaddr_t sgrf_base = (vaddr_t)phys_to_virt_io(SGRF_BASE, SGRF_SIZE); + vaddr_t ddrsgrf_base = (vaddr_t)phys_to_virt_io(DDRSGRF_BASE, + DDRSGRF_SIZE); + + /* Set rgn0 non-secure */ + io_write32(ddrsgrf_base + DDR_SGRF_DDR_CON(0), DDR_RGN0_NS); + + /* Initialize all slave non-secure */ + io_write32(sgrf_base + SGRF_SOC_CON(7), SLAVE_ALL_NS); + io_write32(sgrf_base + SGRF_SOC_CON(8), SLAVE_ALL_NS); + io_write32(sgrf_base + SGRF_SOC_CON(9), SLAVE_ALL_NS); + io_write32(sgrf_base + SGRF_SOC_CON(10), SLAVE_ALL_NS); + + return 0; +} diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/platform_rk3399.c b/optee/optee_os/core/arch/arm/plat-rockchip/platform_rk3399.c new file mode 100644 index 0000000..053f566 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/platform_rk3399.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH + */ + +#include +#include +#include +#include +#include +#include + +#define SGRF_DDRRGN_CON0_16(n) ((n) * 4) +#define SGRF_DDR_RGN_0_16_WMSK GENMASK_32(11, 0) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SGRF_BASE, SGRF_SIZE); + +int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz) +{ + vaddr_t sgrf_base = (vaddr_t)phys_to_virt_io(SGRF_BASE, SGRF_SIZE); + paddr_t ed = st + sz; + uint32_t st_mb = st / SIZE_M(1); + uint32_t ed_mb = ed / SIZE_M(1); + + if (!sgrf_base) + panic(); + + assert(rgn <= 7); + assert(st < ed); + + /* Check aligned 1MB */ + assert(st % SIZE_M(1) == 0); + assert(ed % SIZE_M(1) == 0); + + DMSG("protecting region %d: 0x%lx-0x%lx\n", rgn, st, ed); + + /* Set ddr region addr start */ + io_write32(sgrf_base + SGRF_DDRRGN_CON0_16(rgn), + BITS_WITH_WMASK(st_mb, SGRF_DDR_RGN_0_16_WMSK, 0)); + + /* Set ddr region addr end */ + io_write32(sgrf_base + SGRF_DDRRGN_CON0_16(rgn + 8), + BITS_WITH_WMASK((ed_mb - 1), SGRF_DDR_RGN_0_16_WMSK, 0)); + + io_write32(sgrf_base + SGRF_DDRRGN_CON0_16(16), + BIT_WITH_WMSK(rgn)); + + return 0; +} diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/psci_rk322x.c b/optee/optee_os/core/arch/arm/plat-rockchip/psci_rk322x.c new file mode 100644 index 0000000..07feae8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/psci_rk322x.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct dram_data { + uint32_t cru_mode_con; + uint32_t cru_clksel0; + uint32_t cru_clksel1; + uint32_t cru_clksel10; + uint32_t cru_clksel21; + uint32_t cru_clkgate[CRU_CLKGATE_CON_CNT]; +}; + +static struct dram_data dram_d; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CRU_BASE, CRU_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GRF_BASE, GRF_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, ISRAM_BASE, ISRAM_SIZE); + +static const uint32_t clks_gating_table[CRU_CLKGATE_CON_CNT] = { + /* gate: 0-3 */ + 0xefb8, + 0x0ff7, + 0xfff4, + 0x887f, + /* gate: 4-7 */ + 0x0030, + 0x00f8, + 0x07e0, + 0xc000, + /* gate: 8-11 */ + 0xff84, + 0xb047, + 0x1ca0, + 0x57ff, + /* gate: 12-15 */ + 0x0000, + 0x00ff, + 0x1cc0, + 0x000f, +}; + +static void clks_disable(void) +{ + uint32_t i; + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + for (i = 0; i < CRU_CLKGATE_CON_CNT; i++) { + dram_d.cru_clkgate[i] = io_read32(va_base + CRU_CLKGATE_CON(i)); + io_write32(va_base + CRU_CLKGATE_CON(i), + BITS_WITH_WMASK(clks_gating_table[i], 0xffff, 0)); + } +} + +static void clks_restore(void) +{ + uint32_t i; + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + for (i = 0; i < CRU_CLKGATE_CON_CNT; i++) + io_write32(va_base + CRU_CLKGATE_CON(i), + BITS_WITH_WMASK(dram_d.cru_clkgate[i], 0xffff, 0)); +} + +static void pll_power_down(uint32_t pll) +{ + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + io_write32(va_base + CRU_MODE_CON, PLL_SLOW_MODE(pll)); + io_write32(va_base + CRU_PLL_CON1(pll), PLL_POWER_DOWN); +} + +static void pll_power_up(uint32_t pll) +{ + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + io_write32(va_base + CRU_PLL_CON1(pll), PLL_POWER_UP); +} + +static void pll_wait_lock(uint32_t pll) +{ + uint32_t loop = 0; + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + while (!(io_read32(va_base + CRU_PLL_CON1(pll)) & PLL_LOCK) && + (loop < 500)) { + udelay(2); + loop++; + } + + if (!(io_read32(va_base + CRU_PLL_CON1(pll)) & PLL_LOCK)) { + EMSG("PLL can't lock, index = %" PRIu32, pll); + panic(); + } +} + +/* + * Select clock from external 24MHz OSC(slow mode) and power down plls, + * then set frequency division of relevant bus to 24MHz. + */ +static void plls_power_down(void) +{ + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + dram_d.cru_clksel0 = io_read32(va_base + CRU_CLKSEL_CON(0)); + dram_d.cru_clksel1 = io_read32(va_base + CRU_CLKSEL_CON(1)); + dram_d.cru_clksel10 = io_read32(va_base + CRU_CLKSEL_CON(10)); + dram_d.cru_clksel21 = io_read32(va_base + CRU_CLKSEL_CON(21)); + dram_d.cru_mode_con = io_read32(va_base + CRU_MODE_CON); + + pll_power_down(GPLL_ID); + pll_power_down(CPLL_ID); + pll_power_down(APLL_ID); + + /* core */ + io_write32(va_base + CRU_CLKSEL_CON(0), BITS_WITH_WMASK(0, 0x1f, 0)); + io_write32(va_base + CRU_CLKSEL_CON(1), + BITS_WITH_WMASK(0, 0xf, 0) | BITS_WITH_WMASK(0, 0x7, 4)); + + /* peri aclk, hclk, pclk */ + io_write32(va_base + CRU_CLKSEL_CON(10), + BITS_WITH_WMASK(0, 0x1f, 0) | BITS_WITH_WMASK(0, 0x3, 8) | + BITS_WITH_WMASK(0, 0x7, 12)); + + /* pdbus */ + io_write32(va_base + CRU_CLKSEL_CON(0), BITS_WITH_WMASK(0, 0x1f, 8)); + io_write32(va_base + CRU_CLKSEL_CON(1), + BITS_WITH_WMASK(0, 0x3, 8) | BITS_WITH_WMASK(0, 0x7, 12)); + + /* hdmi cec 32k */ + io_write32(va_base + CRU_CLKSEL_CON(21), + BITS_WITH_WMASK(732, 0x3fff, 0) | + BITS_WITH_WMASK(2, 0x3, 14)); +} + +static void plls_restore(void) +{ + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + /* power up plls */ + pll_power_up(APLL_ID); + pll_power_up(GPLL_ID); + pll_power_up(CPLL_ID); + + udelay(200); + + /* wait lock*/ + pll_wait_lock(APLL_ID); + pll_wait_lock(GPLL_ID); + pll_wait_lock(CPLL_ID); + + /* hdmi cec 32k */ + io_write32(va_base + CRU_CLKSEL_CON(21), + dram_d.cru_clksel21 | BITS_WMSK(0x3fff, 0) | + BITS_WMSK(0x3, 14)); + + /* pdbus */ + io_write32(va_base + CRU_CLKSEL_CON(0), + dram_d.cru_clksel0 | BITS_WMSK(0x1f, 8)); + io_write32(va_base + CRU_CLKSEL_CON(1), + dram_d.cru_clksel1 | BITS_WMSK(0x3, 8) | BITS_WMSK(0x7, 12)); + + /* peri aclk, hclk, pclk */ + io_write32(va_base + CRU_CLKSEL_CON(10), + dram_d.cru_clksel10 | BITS_WMSK(0x1f, 0) | + BITS_WMSK(0x3, 8) | BITS_WMSK(0x7, 12)); + + /* core */ + io_write32(va_base + CRU_CLKSEL_CON(0), + dram_d.cru_clksel0 | BITS_WMSK(0x1f, 0)); + io_write32(va_base + CRU_CLKSEL_CON(1), + dram_d.cru_clksel1 | BITS_WMSK(0xf, 0) | BITS_WMSK(0x7, 4)); + + /* resume plls mode */ + io_write32(va_base + CRU_MODE_CON, + dram_d.cru_mode_con | BITS_WMSK(0x1, PLL_MODE_BIT(APLL_ID))); + io_write32(va_base + CRU_MODE_CON, + dram_d.cru_mode_con | BITS_WMSK(0x1, PLL_MODE_BIT(CPLL_ID))); + io_write32(va_base + CRU_MODE_CON, + dram_d.cru_mode_con | BITS_WMSK(0x1, PLL_MODE_BIT(GPLL_ID))); +} + +static bool wait_core_wfe_i(uint32_t core) +{ + uint32_t wfei_mask, loop = 0; + vaddr_t va_base = (vaddr_t)phys_to_virt_io(GRF_BASE, GRF_SIZE); + + wfei_mask = CORE_WFE_I_MASK(core); + while (!(io_read32(va_base + GRF_CPU_STATUS1) & wfei_mask) && + loop < 500) { + udelay(2); + loop++; + } + + return io_read32(va_base + GRF_CPU_STATUS1) & wfei_mask; +} + +static bool core_held_in_reset(uint32_t core) +{ + uint32_t val; + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + val = io_read32(va_base + CRU_SOFTRST_CON(0)); + + return val & CORE_HELD_IN_RESET(core); +} + +uint32_t psci_version(void) +{ + return PSCI_VERSION_1_0; +} + +int psci_features(uint32_t psci_fid) +{ + switch (psci_fid) { + case PSCI_PSCI_FEATURES: + case PSCI_VERSION: + case PSCI_CPU_ON: + case PSCI_CPU_OFF: + case PSCI_SYSTEM_SUSPEND: + case PSCI_SYSTEM_RESET: + return PSCI_RET_SUCCESS; + default: + return PSCI_RET_NOT_SUPPORTED; + } +} + +int psci_cpu_on(uint32_t core_idx, uint32_t entry, + uint32_t context_id) +{ + bool wfei; + vaddr_t cru_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + vaddr_t isram_base = (vaddr_t)phys_to_virt_io(ISRAM_BASE, ISRAM_SIZE); + + core_idx &= MPIDR_CPU_MASK; + if ((core_idx == 0) || (core_idx >= CFG_TEE_CORE_NB_CORE)) + return PSCI_RET_INVALID_PARAMETERS; + + DMSG("core_id: %" PRIu32, core_idx); + + /* set secondary cores' NS entry addresses */ + boot_set_core_ns_entry(core_idx, entry, context_id); + + /* wait */ + if (!core_held_in_reset(core_idx)) { + wfei = wait_core_wfe_i(core_idx); + if (!wfei) { + EMSG("Can't wait cpu%" PRIu32 " wfei before softrst", + core_idx); + return PSCI_RET_DENIED; + } + } + + /* soft reset core */ + io_write32(cru_base + CRU_SOFTRST_CON(0), CORE_SOFT_RESET(core_idx)); + dsb(); + + udelay(2); + + /* soft release core */ + io_write32(cru_base + CRU_SOFTRST_CON(0), CORE_SOFT_RELEASE(core_idx)); + dsb(); + + /* wait */ + wfei = wait_core_wfe_i(core_idx); + if (!wfei) { + EMSG("Can't wait cpu%" PRIu32 " wfei after softrst", core_idx); + return PSCI_RET_DENIED; + } + + /* set secondary secure entry address and lock tag */ + io_write32(isram_base + BOOT_ADDR_OFFSET, TEE_LOAD_ADDR); + io_write32(isram_base + LOCK_ADDR_OFFSET, LOCK_TAG); + dsb(); + + sev(); + dsb(); + + return PSCI_RET_SUCCESS; +} + +int psci_cpu_off(void) +{ + uint32_t core = get_core_pos(); + + if ((core == 0) || (core >= CFG_TEE_CORE_NB_CORE)) + return PSCI_RET_INVALID_PARAMETERS; + + DMSG("core_id: %" PRIu32, core); + + psci_armv7_cpu_off(); + thread_mask_exceptions(THREAD_EXCP_ALL); + + while (1) + wfi(); + + return PSCI_RET_INTERNAL_FAILURE; +} + +int psci_affinity_info(uint32_t affinity, + uint32_t lowest_affnity_level __unused) +{ + uint32_t core_idx = affinity & MPIDR_CPU_MASK; + uint32_t wfi_mask = CORE_WFI_MASK(core_idx); + vaddr_t va_base = (vaddr_t)phys_to_virt_io(GRF_BASE, GRF_SIZE); + + DMSG("core_id: %" PRIu32 " STATUS: %" PRIx32 " MASK: %" PRIx32, + core_idx, io_read32(va_base + GRF_CPU_STATUS1), wfi_mask); + + return (io_read32(va_base + GRF_CPU_STATUS1) & wfi_mask) ? + PSCI_AFFINITY_LEVEL_OFF : PSCI_AFFINITY_LEVEL_ON; +} + +void psci_system_reset(void) +{ + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + /* PLLs enter slow mode */ + io_write32(va_base + CRU_MODE_CON, PLLS_SLOW_MODE); + dsb(); + + /* Global second reset */ + io_write32(va_base + CRU_SNDRST_VAL_BASE, CRU_SNDRST_VAL); + dsb(); +} + +int psci_system_suspend(uintptr_t entry __unused, + uint32_t context_id __unused, + struct sm_nsec_ctx *nsec __unused) +{ + DMSG("system suspend"); + + clks_disable(); + plls_power_down(); + + cache_op_inner(DCACHE_CLEAN_INV, NULL, 0); + + wfi(); + + plls_restore(); + clks_restore(); + + return PSCI_RET_SUCCESS; +} + +/* When SMP bootup, we release cores one by one */ +static TEE_Result reset_nonboot_cores(void) +{ + vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); + + io_write32(va_base + CRU_SOFTRST_CON(0), NONBOOT_CORES_SOFT_RESET); + + return TEE_SUCCESS; +} + +service_init_late(reset_nonboot_cores); diff --git a/optee/optee_os/core/arch/arm/plat-rockchip/sub.mk b/optee/optee_os/core/arch/arm/plat-rockchip/sub.mk new file mode 100644 index 0000000..74f8cf5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rockchip/sub.mk @@ -0,0 +1,12 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-y += platform.c +srcs-$(PLATFORM_FLAVOR_px30) += platform_px30.c +srcs-$(PLATFORM_FLAVOR_rk322x) += platform_rk322x.c +srcs-$(PLATFORM_FLAVOR_rk3399) += platform_rk3399.c + +ifeq ($(PLATFORM_FLAVOR),rk322x) +srcs-y += plat_init.S +srcs-y += core_pos_a32.S +srcs-$(CFG_PSCI_ARM32) += psci_rk322x.c +endif diff --git a/optee/optee_os/core/arch/arm/plat-rpi3/conf.mk b/optee/optee_os/core/arch/arm/plat-rpi3/conf.mk new file mode 100644 index 0000000..6bb5651 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rpi3/conf.mk @@ -0,0 +1,29 @@ +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_TEE_CORE_NB_CORE,4) + +CFG_SHMEM_START ?= 0x08000000 +CFG_SHMEM_SIZE ?= 0x00400000 +CFG_TZDRAM_START ?= 0x10100000 +CFG_TZDRAM_SIZE ?= 0x00F00000 +CFG_TEE_RAM_VA_SIZE ?= 0x00700000 + +$(call force,CFG_8250_UART,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) + +CFG_NUM_THREADS ?= 4 +CFG_CRYPTO_WITH_CE ?= n + +CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y +CFG_WITH_STACK_CANARIES ?= y +CFG_WITH_STATS ?= y + +arm32-platform-cflags += -Wno-error=cast-align +arm64-platform-cflags += -Wno-error=cast-align + +$(call force,CFG_CRYPTO_SHA256_ARM32_CE,n) +$(call force,CFG_CRYPTO_SHA256_ARM64_CE,n) +$(call force,CFG_CRYPTO_SHA1_ARM32_CE,n) +$(call force,CFG_CRYPTO_SHA1_ARM64_CE,n) +$(call force,CFG_CRYPTO_AES_ARM64_CE,n) diff --git a/optee/optee_os/core/arch/arm/plat-rpi3/main.c b/optee/optee_os/core/arch/arm/plat-rpi3/main.c new file mode 100644 index 0000000..3e9021d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rpi3/main.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, + CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE); + +static struct serial8250_uart_data console_data; + +void console_init(void) +{ + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-rpi3/platform_config.h b/optee/optee_os/core/arch/arm/plat-rpi3/platform_config.h new file mode 100644 index 0000000..dfb9e29 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rpi3/platform_config.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#ifdef ARM64 +#ifdef CFG_WITH_PAGER +#error "Pager not supported for ARM64" +#endif +#endif /* ARM64 */ + +/* 16550 UART */ +#define CONSOLE_UART_BASE 0x3f215040 /* UART0 */ +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 19200000 + +/* + * RPi memory map + * + * No secure memory on RPi... + * + * + * Available to Linux + * 0x0a00_0000 + * TA RAM: 16 MiB | + * 0x0842_0000 | TZDRAM + * TEE RAM: 4 MiB (TEE_RAM_VA_SIZE) | + * 0x0840_0000 [ARM Trusted Firmware ] - + * 0x0840_0000 [TZDRAM_BASE, BL32_LOAD_ADDR] - + * Shared memory: 4 MiB | + * 0x0800_0000 | DRAM0 + * Available to Linux | + * 0x0000_0000 [DRAM0_BASE] - + * + */ + +#define DRAM0_BASE 0x00000000 +#define DRAM0_SIZE 0x40000000 + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-rpi3/sub.mk b/optee/optee_os/core/arch/arm/plat-rpi3/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rpi3/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-rzg/conf.mk b/optee/optee_os/core/arch/arm/plat-rzg/conf.mk new file mode 100644 index 0000000..c001112 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzg/conf.mk @@ -0,0 +1,43 @@ +PLATFORM_FLAVOR ?= hihope_rzg2m + +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_SCIF,y) +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) + +# Disable core ASLR for two reasons: +# 1. There is no source for ALSR seed, as RZ/G2 platform +# does not provide DTB to OP-TEE. Also, there is no +# publicly available documentation on integrated +# hardware RNG, so we can't use it either. +# 2. OP-TEE crashes during boot with enabled CFG_CORE_ASLR. +$(call force,CFG_CORE_ASLR,n) + +ifeq ($(PLATFORM_FLAVOR),ek874) +$(call force,CFG_TEE_CORE_NB_CORE,2) +endif +ifeq ($(PLATFORM_FLAVOR),hihope_rzg2m) +$(call force,CFG_TEE_CORE_NB_CORE,6) +# RZ/G2M have 6 cores for 2 clusters, but the number isn't contiguous. +# One cluster has ids 0, 1, other has ids 3, 4, 5, 6. +# CFG_CORE_CLUSTER_SHIFT will process to make the right numbering. +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +endif +ifeq ($(PLATFORM_FLAVOR),hihope_rzg2n) +$(call force,CFG_TEE_CORE_NB_CORE,2) +endif +ifeq ($(PLATFORM_FLAVOR),hihope_rzg2h) +$(call force,CFG_TEE_CORE_NB_CORE,8) +endif + +CFG_TZDRAM_START ?= 0x44100000 +CFG_TZDRAM_SIZE ?= 0x03D00000 +CFG_TEE_RAM_VA_SIZE ?= 0x100000 +ifeq ($(CFG_ARM64_core),y) +supported-ta-targets = ta_arm64 +endif + +CFG_DT ?= y diff --git a/optee/optee_os/core/arch/arm/plat-rzg/link.mk b/optee/optee_os/core/arch/arm/plat-rzg/link.mk new file mode 100644 index 0000000..229c4b7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzg/link.mk @@ -0,0 +1,3 @@ +include core/arch/arm/kernel/link.mk + +all: $(link-out-dir)/tee.srec diff --git a/optee/optee_os/core/arch/arm/plat-rzg/main.c b/optee/optee_os/core/arch/arm/plat-rzg/main.c new file mode 100644 index 0000000..31dfd08 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzg/main.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, GlobalLogic + * Copyright (c) 2019-2020, Renesas Electronics Corporation + */ + +#include +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, SCIF_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_DIST_REG_SIZE); + +register_dynamic_shm(NSEC_DDR_0_BASE, NSEC_DDR_0_SIZE); +#ifdef NSEC_DDR_1_BASE +register_dynamic_shm(NSEC_DDR_1_BASE, NSEC_DDR_1_SIZE); +#endif +#ifdef NSEC_DDR_2_BASE +register_dynamic_shm(NSEC_DDR_2_BASE, NSEC_DDR_2_SIZE); +#endif +#ifdef NSEC_DDR_3_BASE +register_dynamic_shm(NSEC_DDR_3_BASE, NSEC_DDR_3_SIZE); +#endif + +static struct scif_uart_data console_data __nex_bss; + +void console_init(void) +{ + scif_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-rzg/platform_config.h b/optee/optee_os/core/arch/arm/plat-rzg/platform_config.h new file mode 100644 index 0000000..eacc5a4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzg/platform_config.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, GlobalLogic + * Copyright (c) 2020, Renesas Electronics Corporation + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#define GIC_BASE 0xF1000000 +#define GICC_BASE 0xF1020000 +#define GICD_BASE 0xF1010000 + +#define CONSOLE_UART_BASE 0xE6E88000 + +#if defined(PLATFORM_FLAVOR_ek874) +#define NSEC_DDR_0_BASE 0x47E00000U +#define NSEC_DDR_0_SIZE 0x78200000 + +#elif defined(PLATFORM_FLAVOR_hihope_rzg2h) + +#define NSEC_DDR_0_BASE 0x47E00000U +#define NSEC_DDR_0_SIZE 0x78200000 +#define NSEC_DDR_1_BASE 0x500000000U +#define NSEC_DDR_1_SIZE 0x80000000 + +#elif defined(PLATFORM_FLAVOR_hihope_rzg2m) + +#define NSEC_DDR_0_BASE 0x47E00000U +#define NSEC_DDR_0_SIZE 0x78200000 +#define NSEC_DDR_1_BASE 0x600000000U +#define NSEC_DDR_1_SIZE 0x80000000 + +#elif defined(PLATFORM_FLAVOR_hihope_rzg2n) + +#define NSEC_DDR_0_BASE 0x47E00000U +#define NSEC_DDR_0_SIZE 0x78200000 +#define NSEC_DDR_1_BASE 0x480000000U +#define NSEC_DDR_1_SIZE 0x80000000 + +#else +#error "Unknown platform flavor" +#endif + +#define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) +#define TEE_SHMEM_SIZE 0x100000 + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-rzg/sub.mk b/optee/optee_os/core/arch/arm/plat-rzg/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzg/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/a7_plat_init.S b/optee/optee_os/core/arch/arm/plat-rzn1/a7_plat_init.S new file mode 100644 index 0000000..4f3ae2c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/a7_plat_init.S @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Wind River Systems. + * Copyright (c) 2020, Linaro Limited + */ + +/* + * Entry points for the A7 init. + * + * Assumptions: + * - No stack is available when these routines are called. + * - Each routine is called with return address in LR and + * with ARM registers R0, R1, R2, R3 being scratchable. + */ + +#include +#include +#include +#include + +.section .text +.balign 4 +.code 32 + +FUNC plat_cpu_reset_early , : + /* + * SCR = 0x00000020 + * - FW: Disallow NSec to mask FIQ [bit4=0] + * - AW: Allow NSec to manage Imprecise Abort [bit5=1] + * - EA: Imprecise Abort trapped to Abort Mode [bit3=0] + * - FIQ: In Sec world, FIQ trapped to FIQ Mode [bit2=0] + * - IRQ: IRQ always trapped to IRQ Mode [bit1=0] + * - NS: Secure World [bit0=0] + */ + mov r0, #SCR_AW + write_scr r0 + + mov_imm r0, 0x00000000 + write_sctlr r0 + + /* + * ACTRL = 0x00006040 + * - DDI: Disable dual issue [bit28=0] + * - DDVM: Disable Distributed Virtual Memory transactions [bit15=0] + * - L1PCTL: L1 Data prefetch control [bit14:13=2b11] + * - L1RADIS: L1 Data Cache read-allocate mode disable [bit12=0] + * - L2RADIS: L2 Data Cache read-allocate mode disable [bit11=0] + * - DODMBS: Disable optimized data memory barrier behavior [bit10=0] + * - SMP: Enables coherent requests to the processor [bit6=0] + */ + mov_imm r0, 0x00006040 + write_actlr r0 + + /* + * NSACR = 0x00000C00 + * - NS_SMP: Non-secure mode cannot change ACTRL.SMP (bit18=0) + * - NSASEDIS/NSD32DIS/CP10/CP11: Non-secure mode can use SIMD/VFP + * (bit15:14=2b00, bit11:10=2b11) + */ + mov_imm r0, 0x00000C00 + write_nsacr r0 + + mov pc, lr +END_FUNC plat_cpu_reset_early diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/conf.mk b/optee/optee_os/core/arch/arm/plat-rzn1/conf.mk new file mode 100644 index 0000000..5dd7534 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/conf.mk @@ -0,0 +1,28 @@ +PLATFORM_FLAVOR ?= rzn1 + +include core/arch/arm/cpu/cortex-a7.mk + +$(call force,CFG_ARM32_core,y) +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_BOOT_SECONDARY_REQUEST,y) +$(call force,CFG_SECONDARY_INIT_CNTFRQ,y) +$(call force,CFG_PSCI_ARM32,y) +$(call force,CFG_16550_UART,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_PAGER,n) +$(call force,CFG_GIC,y) +$(call force,CFG_SM_PLATFORM_HANDLER,y) +$(call force,CFG_TA_FLOAT_SUPPORT,n) + +ta-targets = ta_arm32 + +CFG_TZDRAM_START ?= 0x88000000 +CFG_TZDRAM_SIZE ?= 0x00A00000 +CFG_SHMEM_START ?= 0x87C00000 +CFG_SHMEM_SIZE ?= 0x00400000 +CFG_TEE_RAM_VA_SIZE ?= 0x00200000 + +CFG_NUM_THREADS ?= 4 +CFG_NS_ENTRY_ADDR ?= 0x87A00000 + +CFG_BOOT_CM3 ?= y diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/main.c b/optee/optee_os/core/arch/arm/plat-rzn1/main.c new file mode 100644 index 0000000..4a9b717 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/main.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Schneider Electric + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SYSCTRL_PWRCTRL_CM3 (SYSCTRL_BASE + 0x174) +#define SYSCTRL_PWRSTAT_CM3 (SYSCTRL_BASE + 0x178) + +#define SYSCTRL_PWRCTRL_CM3_CLKEN_A BIT(0) +#define SYSCTRL_PWRCTRL_CM3_RSTN_A BIT(1) +#define SYSCTRL_PWRCTRL_CM3_MIREQ_A BIT(2) + +#define SYSCTRL_PWRSTAT_CM3_MIRACK_A BIT(0) + +/* Timeout waiting for Master Idle Request Acknowledge */ +#define IDLE_ACK_TIMEOUT_US 1000 + +static struct gic_data gic_data; +static struct ns16550_data console_data; + +register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); +register_phys_mem(MEM_AREA_IO_SEC, PERIPH_REG_BASE, CORE_MMU_PGDIR_SIZE); +register_ddr(DRAM_BASE, DRAM_SIZE); + +void console_init(void) +{ + ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U32, 2); + register_serial_console(&console_data.chip); +} + +void main_init_gic(void) +{ + gic_init(&gic_data, GICC_BASE, GICD_BASE); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +static TEE_Result rzn1_tz_init(void) +{ + vaddr_t tza_init_reg = 0; + vaddr_t tza_targ_reg = 0; + + tza_init_reg = core_mmu_get_va(FW_STATIC_TZA_INIT, MEM_AREA_IO_SEC, + sizeof(uint32_t)); + tza_targ_reg = core_mmu_get_va(FW_STATIC_TZA_TARG, MEM_AREA_IO_SEC, + sizeof(uint32_t)); + + /* TZ initiator ports */ + io_write32(tza_init_reg, TZ_INIT_CSA_SEC | TZ_INIT_YS_SEC | + TZ_INIT_YC_SEC | TZ_INIT_YD_SEC); + + /* TZ target ports */ + io_write32(tza_targ_reg, TZ_TARG_PC_SEC | TZ_TARG_QB_SEC | + TZ_TARG_QA_SEC | TZ_TARG_UB_SEC | + TZ_TARG_UA_SEC); + + return TEE_SUCCESS; +} + +service_init(rzn1_tz_init); + +#ifdef CFG_BOOT_CM3 +static TEE_Result rzn1_cm3_start(void) +{ + vaddr_t cm3_pwrctrl_reg = 0; + vaddr_t cm3_pwrstat_reg = 0; + uint64_t timeout_ack = timeout_init_us(IDLE_ACK_TIMEOUT_US); + + cm3_pwrctrl_reg = core_mmu_get_va(SYSCTRL_PWRCTRL_CM3, MEM_AREA_IO_SEC, + sizeof(uint32_t)); + cm3_pwrstat_reg = core_mmu_get_va(SYSCTRL_PWRSTAT_CM3, MEM_AREA_IO_SEC, + sizeof(uint32_t)); + + /* Master Idle Request to the interconnect for CM3 */ + io_clrbits32(cm3_pwrctrl_reg, SYSCTRL_PWRCTRL_CM3_MIREQ_A); + + /* Wait for Master Idle Request Acknowledge for CM3 */ + while (!timeout_elapsed(timeout_ack)) + if (!(io_read32(cm3_pwrstat_reg) & + SYSCTRL_PWRSTAT_CM3_MIRACK_A)) + break; + + if (io_read32(cm3_pwrstat_reg) & SYSCTRL_PWRSTAT_CM3_MIRACK_A) + panic(); + + /* Clock Enable for CM3_HCLK & Active low Reset to CM3 */ + io_setbits32(cm3_pwrctrl_reg, SYSCTRL_PWRCTRL_CM3_CLKEN_A); + io_setbits32(cm3_pwrctrl_reg, SYSCTRL_PWRCTRL_CM3_RSTN_A); + + return TEE_SUCCESS; +} + +service_init(rzn1_cm3_start); +#endif diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/platform_config.h b/optee/optee_os/core/arch/arm/plat-rzn1/platform_config.h new file mode 100644 index 0000000..a6340bb --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/platform_config.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Schneider Electric + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* DRAM */ +#define DRAM_BASE 0x80000000 +#define DRAM_SIZE 0x10000000 + +/* GIC */ +#define GIC_BASE 0x44100000 +#define GICD_OFFSET 0x1000 +#define GICC_OFFSET 0x2000 +#define GICD_BASE (GIC_BASE + GICD_OFFSET) +#define GICC_BASE (GIC_BASE + GICC_OFFSET) + +/* Peripheral memory map */ +#define PERIPH_REG_BASE 0x40000000 + +/* System Control */ +#define SYSCTRL_BASE 0x4000C000 + +/* UART */ +#define CONSOLE_UART_BASE 0x40060000 + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/psci.c b/optee/optee_os/core/arch/arm/plat-rzn1/psci.c new file mode 100644 index 0000000..9e5fb3c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/psci.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Schneider Electric + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SYSCTRL_REG_RSTEN (SYSCTRL_BASE + 0x120) +#define SYSCTRL_REG_RSTCTRL (SYSCTRL_BASE + 0x198) +#define SYSCTRL_BOOTADDR_REG (SYSCTRL_BASE + 0x204) + +#define SYSCTRL_REG_RSTEN_MRESET_EN BIT(0) +#define SYSCTRL_REG_RSTEN_SWRST_EN BIT(6) +#define SYSCTRL_REG_RSTCTRL_SWRST_REQ BIT(6) + +int psci_features(uint32_t psci_fid) +{ + switch (psci_fid) { + case PSCI_PSCI_FEATURES: + case PSCI_VERSION: + case PSCI_CPU_ON: + case PSCI_CPU_OFF: + case PSCI_SYSTEM_RESET: + return PSCI_RET_SUCCESS; + default: + return PSCI_RET_NOT_SUPPORTED; + } +} + +uint32_t psci_version(void) +{ + return PSCI_VERSION_1_0; +} + +int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) +{ + vaddr_t sctl_va = core_mmu_get_va(SYSCTRL_BOOTADDR_REG, + MEM_AREA_IO_SEC, + sizeof(uint32_t)); + + if (core_id == 0 || core_id >= CFG_TEE_CORE_NB_CORE) + return PSCI_RET_INVALID_PARAMETERS; + + DMSG("core_id: %" PRIu32, core_id); + + boot_set_core_ns_entry(core_id, entry, context_id); + io_write32(sctl_va, TEE_LOAD_ADDR); + + dsb(); + sev(); + + return PSCI_RET_SUCCESS; +} + +int __noreturn psci_cpu_off(void) +{ + DMSG("core_id: %" PRIu32, get_core_pos()); + + psci_armv7_cpu_off(); + + thread_mask_exceptions(THREAD_EXCP_ALL); + + while (1) + wfi(); +} + +void psci_system_reset(void) +{ + /* Enable software reset */ + io_setbits32(core_mmu_get_va(SYSCTRL_REG_RSTEN, MEM_AREA_IO_SEC, + sizeof(uint32_t)), + SYSCTRL_REG_RSTEN_SWRST_EN | SYSCTRL_REG_RSTEN_MRESET_EN); + + /* Trigger software reset */ + io_setbits32(core_mmu_get_va(SYSCTRL_REG_RSTCTRL, MEM_AREA_IO_SEC, + sizeof(uint32_t)), + SYSCTRL_REG_RSTCTRL_SWRST_REQ); + + dsb(); +} diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/rzn1_regauth.h b/optee/optee_os/core/arch/arm/plat-rzn1/rzn1_regauth.h new file mode 100644 index 0000000..a8572a1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/rzn1_regauth.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Schneider Electric + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef RZN1_REGAUTH_H +#define RZN1_REGAUTH_H + +struct regauth_t { + uint32_t paddr; + uint32_t size; + uint32_t rmask; + uint32_t wmask; +}; + +static const struct regauth_t regauth[] = { + /* OTP */ + { 0x40007000U, 0x4U, 0x0U, 0x0U }, /* OTPWCTRL */ + /* System Controller */ + { 0x4000C064U, 0x4U, 0xFFFFFFFFU, 0xFFFFFFE0U }, /* PWRCTRL_DDRC */ + { 0x4000C204U, 0x4U, 0x0U, 0x0U }, /* BOOTADDR */ + /* DDR CTRL */ + { 0x4000D16CU, 0x3FCU, 0x0U, 0x0U }, /* DDR_CTL 91-346 */ + { 0x4000E000U, 0x4U, 0xFFFFFFFFU, 0xFFFFFFFEU }, /* UNCCTRL */ + { 0x4000E004U, 0x4U, 0xFFFFFFFFU, 0xFFFFFFFEU }, /* DLLCTRL */ +}; + +#endif /* RZN1_REGAUTH_H */ diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/rzn1_tz.h b/optee/optee_os/core/arch/arm/plat-rzn1/rzn1_tz.h new file mode 100644 index 0000000..9ebc7d2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/rzn1_tz.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Schneider Electric + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef RZN1_TZ_H +#define RZN1_TZ_H + +#include + +/* TZ config registers */ +#define FW_STATIC_TZA_INIT 0x4000C0D0 +#define FW_STATIC_TZA_TARG 0x4000C0D4 + +/* TZ initiatior ports */ +#define TZ_INIT_CSB_SEC BIT(7) /* CoreSight AHB */ +#define TZ_INIT_CSA_SEC BIT(6) /* CoreSight AXI */ +#define TZ_INIT_YS_SEC BIT(5) /* Cortex-M3 System Bus interface */ +#define TZ_INIT_YC_SEC BIT(4) /* Cortex-M3 ICode interface */ +#define TZ_INIT_YD_SEC BIT(3) /* Cortex-M3 DCode interface */ +#define TZ_INIT_Z_SEC BIT(2) /* Packet Engine */ +#define TZ_INIT_I_SEC BIT(1) /* Peripheral Group */ +#define TZ_INIT_F_SEC BIT(0) /* Peripheral Group */ + +/* TZ target ports */ +#define TZ_TARG_W_SEC BIT(14) /* RTC */ +#define TZ_TARG_PC_SEC BIT(9) /* DDR2/3 Controller */ +#define TZ_TARG_RA_SEC BIT(8) /* CoreSight */ +#define TZ_TARG_QB_SEC BIT(7) /* System Control */ +#define TZ_TARG_QA_SEC BIT(6) /* PG0 */ +#define TZ_TARG_NB_SEC BIT(5) /* Packet Engine */ +#define TZ_TARG_NA_SEC BIT(4) /* Public Key Processor */ +#define TZ_TARG_K_SEC BIT(3) /* Peripheral Group */ +#define TZ_TARG_J_SEC BIT(2) /* Peripheral Group */ +#define TZ_TARG_UB_SEC BIT(1) /* 2MB SRAM */ +#define TZ_TARG_UA_SEC BIT(0) /* 2MB SRAM */ + +#endif /* RZN1_TZ_H */ diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c b/optee/optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c new file mode 100644 index 0000000..dc990f4 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/sm_platform_handler.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "rzn1_regauth.h" + +#define RZN1_OEM_CONSOLE_PUTC 0x01 +#define RZN1_OEM_SYSREG_AUTH 0x10 + +static const struct regauth_t regauth_pass = {.rmask = ~0U, .wmask = ~0U}; + +static const struct regauth_t *get_regauth(unsigned long paddr) +{ + unsigned int idx = 0; + unsigned int len = ARRAY_SIZE(regauth); + + while (idx < len) { + if (core_is_buffer_inside(paddr, sizeof(uint32_t), + regauth[idx].paddr, + regauth[idx].size)) + return ®auth[idx]; + idx++; + } + + return NULL; +} + +static uint32_t oem_sysreg(uint32_t addr, uint32_t mask, uint32_t *pvalue) +{ + vaddr_t reg = 0; + const struct regauth_t *auth = get_regauth(addr); + + /* Allow operations on registers not in the list */ + if (!auth) + auth = ®auth_pass; + + reg = core_mmu_get_va(addr, MEM_AREA_IO_SEC, sizeof(uint32_t)); + + if (mask) { + /* Write operation */ + mask &= auth->wmask; + if (!reg || !mask) + DMSG("Blocking write of 0x%"PRIx32" to register 0x%" + PRIx32" (0x%"PRIxVA")", *pvalue, addr, reg); + else if (mask == ~0UL) + io_write32(reg, *pvalue); + else + io_mask32(reg, *pvalue, mask); + } else { + /* Read operation */ + if (!reg || !auth->rmask) + DMSG("Blocking read of register 0x%"PRIx32" (0x%" + PRIxVA")", addr, reg); + else + *pvalue = io_read32(reg) & auth->rmask; + } + + return 0; +} + +static enum sm_handler_ret oem_service(struct sm_ctx *ctx __unused, + struct thread_smc_args *args) +{ + switch (OPTEE_SMC_FUNC_NUM(args->a0)) { + case RZN1_OEM_SYSREG_AUTH: + args->a0 = oem_sysreg(args->a1, args->a2, &args->a3); + args->a1 = args->a3; + break; + case RZN1_OEM_CONSOLE_PUTC: + console_putc(args->a1); + break; + default: + return SM_HANDLER_PENDING_SMC; + } + + return SM_HANDLER_SMC_HANDLED; +} + +enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) +{ + struct thread_smc_args *args = (void *)&ctx->nsec.r0; + + if (!OPTEE_SMC_IS_FAST_CALL(args->a0)) + return SM_HANDLER_PENDING_SMC; + + switch (OPTEE_SMC_OWNER_NUM(args->a0)) { + case OPTEE_SMC_OWNER_OEM: + return oem_service(ctx, args); + default: + return SM_HANDLER_PENDING_SMC; + } +} diff --git a/optee/optee_os/core/arch/arm/plat-rzn1/sub.mk b/optee/optee_os/core/arch/arm/plat-rzn1/sub.mk new file mode 100644 index 0000000..4fc96f0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-rzn1/sub.mk @@ -0,0 +1,5 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-y += psci.c +srcs-y += sm_platform_handler.c +srcs-y += a7_plat_init.S diff --git a/optee/optee_os/core/arch/arm/plat-sam/conf.mk b/optee/optee_os/core/arch/arm/plat-sam/conf.mk new file mode 100644 index 0000000..b37980c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/conf.mk @@ -0,0 +1,93 @@ +PLATFORM_FLAVOR ?= sama5d27_som1_ek + +flavor_dts_file-sama5d2xult = at91-sama5d2_xplained.dts +flavor_dts_file-sama5d2_xplained = at91-sama5d2_xplained.dts +flavor_dts_file-sama5d27_som1_ek = at91-sama5d27_som1_ek.dts +flavor_dts_file-sama5d27_wlsom1_ek = at91-sama5d27_wlsom1_ek.dts + +ifeq ($(PLATFORM_FLAVOR),sama5d2xult) +$(warning "sama5d2xult is deprecated, please use sama5d2_xplained") +endif + +ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),) +$(error Invalid platform flavor $(PLATFORM_FLAVOR)) +endif +CFG_EMBED_DTB_SOURCE_FILE ?= $(flavor_dts_file-$(PLATFORM_FLAVOR)) + +include core/arch/arm/cpu/cortex-a5.mk + +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_ATMEL_UART,y) +$(call force,CFG_ATMEL_SAIC,y) +$(call force,CFG_ATMEL_TCB,y) +$(call force,CFG_NO_SMP,y) +$(call force,CFG_PL310,y) +$(call force,CFG_PL310_LOCKED,y) +$(call force,CFG_AT91_MATRIX,y) +$(call force,CFG_DRIVERS_CLK,y) +$(call force,CFG_DRIVERS_CLK_DT,y) +$(call force,CFG_DRIVERS_CLK_FIXED,y) +$(call force,CFG_DRIVERS_SAM_CLK,y) +$(call force,CFG_DRIVERS_SAMA5D2_CLK,y) +$(call force,CFG_PSCI_ARM32,y) +$(call force,CFG_SM_PLATFORM_HANDLER,y) +$(call force,CFG_CORE_HAS_GENERIC_TIMER,n) + +# These values are forced because of matrix configuration for secure area. +# When modifying these, always update matrix settings in +# matrix_configure_slave_h64mx(). +$(call force,CFG_TZDRAM_START,0x20000000) +$(call force,CFG_TZDRAM_SIZE,0x800000) + +CFG_MMAP_REGIONS ?= 24 + +CFG_SHMEM_START ?= 0x21000000 +CFG_SHMEM_SIZE ?= 0x400000 + +CFG_TEE_RAM_VA_SIZE ?= 0x100000 + +# Device tree related configuration +CFG_DT_ADDR ?= 0x21500000 +CFG_GENERATE_DTB_OVERLAY ?= y + +CFG_WITH_SOFTWARE_PRNG ?= n +CFG_ATMEL_TRNG ?= y +ifeq ($(CFG_ATMEL_TRNG),y) +CFG_HWRNG_PTA ?= y +$(call force,CFG_HWRNG_QUALITY,1024) +endif + +CFG_ATMEL_RSTC ?= y +CFG_ATMEL_SHDWC ?= y + +CFG_ATMEL_PM ?= y + +ifeq ($(CFG_ATMEL_PM),y) +# Suspend mode to be used on PSCI suspend call +# 0 = STANDBY +# 1 = ULP0 +# 2 = ULP0 Fast +# 3 = ULP1 +# 4 = BACKUP +CFG_ATMEL_PM_SUSPEND_MODE ?= 0 + +$(call force,CFG_ATMEL_SHDWC,y) +$(call force,CFG_PM_ARM32,y) +endif + +CFG_WDT ?= y +CFG_WDT_SM_HANDLER ?= y +ifeq ($(CFG_WDT_SM_HANDLER),y) +CFG_WDT_SM_HANDLER_ID := 0x2000500 +endif +CFG_ATMEL_WDT ?= y + +CFG_DRIVERS_RTC ?= y +CFG_RTC_PTA ?= y +CFG_ATMEL_RTC ?= y +CFG_ATMEL_PIOBU ?= y + +ifeq ($(PLATFORM_FLAVOR),sama5d27_wlsom1_ek) +CFG_DRIVERS_I2C ?= y +CFG_ATMEL_I2C ?= y +endif diff --git a/optee/optee_os/core/arch/arm/plat-sam/freq.c b/optee/optee_os/core/arch/arm/plat-sam/freq.c new file mode 100644 index 0000000..fe4c3d6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/freq.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + */ + +#include +#include +#include +#include +#include +#include + +static unsigned long freq; + +static TEE_Result get_freq_from_dt(void) +{ + int node; + struct clk *clk; + const void *fdt = get_embedded_dt(); + + if (!fdt) + panic(); + + node = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a5"); + if (!node) + panic(); + + if (clk_dt_get_by_name(fdt, node, "cpu", &clk)) + panic(); + + freq = clk_get_rate(clk); + + return TEE_SUCCESS; +} +early_init_late(get_freq_from_dt); + +unsigned long plat_get_freq(void) +{ + assert(freq); + + return freq; +} diff --git a/optee/optee_os/core/arch/arm/plat-sam/main.c b/optee/optee_os/core/arch/arm/plat-sam/main.c new file mode 100644 index 0000000..166bfe8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/main.c @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Timesys Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +static struct atmel_uart_data console_data; +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); + +void console_init(void) +{ + atmel_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +} + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX32, + CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX64, + CORE_MMU_PGDIR_SIZE); + +vaddr_t matrix32_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(AT91C_BASE_MATRIX32, MEM_AREA_IO_SEC, + 1); + return (vaddr_t)va; + } + return AT91C_BASE_MATRIX32; +} + +vaddr_t matrix64_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(AT91C_BASE_MATRIX64, MEM_AREA_IO_SEC, + 1); + return (vaddr_t)va; + } + return AT91C_BASE_MATRIX64; +} + +static void matrix_configure_slave_h64mx(void) +{ + unsigned int ddr_port; + unsigned int ssr_setting; + unsigned int sasplit_setting; + unsigned int srtop_setting; + + /* + * 0: Bridge from H64MX to AXIMX + * (Internal ROM, Crypto Library, PKCC RAM): Always Secured + */ + + /* 1: H64MX Peripheral Bridge: SDMMC0, SDMMC1 Non-Secure */ + srtop_setting = MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_128M) + | MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M) + | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = (MATRIX_LANSECH_NS(1) + | MATRIX_LANSECH_NS(2) + | MATRIX_RDNSECH_NS(1) + | MATRIX_RDNSECH_NS(2) + | MATRIX_WRNSECH_NS(1) + | MATRIX_WRNSECH_NS(2)); + matrix_configure_slave_security(matrix64_base(), + H64MX_SLAVE_PERI_BRIDGE, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* + * Matrix DDR configuration is hardcoded here and is difficult to + * generate at runtime. Since this configuration expect the secure + * DRAM to be at start of RAM and 8M of size, enforce it here. + */ + COMPILE_TIME_ASSERT(CFG_TZDRAM_START == AT91C_BASE_DDRCS); + COMPILE_TIME_ASSERT(CFG_TZDRAM_SIZE == 0x800000); + + /* 2 ~ 9 DDR2 Port1 ~ 7: Non-Secure, except op-tee tee/ta memory */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = (MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8M) + | MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M) + | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_128M) + | MATRIX_SASPLIT(3, MATRIX_SASPLIT_VALUE_128M)); + ssr_setting = (MATRIX_LANSECH_S(0) + | MATRIX_LANSECH_NS(1) + | MATRIX_LANSECH_NS(2) + | MATRIX_LANSECH_NS(3) + | MATRIX_RDNSECH_S(0) + | MATRIX_RDNSECH_NS(1) + | MATRIX_RDNSECH_NS(2) + | MATRIX_RDNSECH_NS(3) + | MATRIX_WRNSECH_S(0) + | MATRIX_WRNSECH_NS(1) + | MATRIX_WRNSECH_NS(2) + | MATRIX_WRNSECH_NS(3)); + /* DDR port 0 not used from NWd */ + for (ddr_port = 1; ddr_port < 8; ddr_port++) { + matrix_configure_slave_security(matrix64_base(), + (H64MX_SLAVE_DDR2_PORT_0 + ddr_port), + srtop_setting, + sasplit_setting, + ssr_setting); + } + + /* + * 10: Internal SRAM 128K: + * - First 64K are reserved for suspend code in Secure World + * - Last 64K are for Non-Secure world (used by CAN) + */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128K); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SRTOP_VALUE_64K); + ssr_setting = (MATRIX_LANSECH_S(0) | MATRIX_RDNSECH_S(0) | + MATRIX_WRNSECH_S(0)); + matrix_configure_slave_security(matrix64_base(), + H64MX_SLAVE_INTERNAL_SRAM, + srtop_setting, sasplit_setting, + ssr_setting); + + /* 11: Internal SRAM 128K (Cache L2): Default */ + + /* 12: QSPI0: Normal world */ + /* 13: QSPI1: Normal world */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = MATRIX_LANSECH_NS(0) | MATRIX_RDNSECH_NS(0) | + MATRIX_WRNSECH_NS(0); + + matrix_configure_slave_security(matrix64_base(), H64MX_SLAVE_QSPI0, + srtop_setting, sasplit_setting, + ssr_setting); + matrix_configure_slave_security(matrix64_base(), H64MX_SLAVE_QSPI1, + srtop_setting, sasplit_setting, + ssr_setting); + /* 14: AESB: Default */ +} + +static void matrix_configure_slave_h32mx(void) +{ + unsigned int ssr_setting; + unsigned int sasplit_setting; + unsigned int srtop_setting; + + /* 0: Bridge from H32MX to H64MX: Not Secured */ + /* 1: H32MX Peripheral Bridge 0: Not Secured */ + /* 2: H32MX Peripheral Bridge 1: Not Secured */ + + /* + * 3: External Bus Interface + * EBI CS0 Memory(256M) ----> Slave Region 0, 1 + * EBI CS1 Memory(256M) ----> Slave Region 2, 3 + * EBI CS2 Memory(256M) ----> Slave Region 4, 5 + * EBI CS3 Memory(128M) ----> Slave Region 6 + * NFC Command Registers(128M) -->Slave Region 7 + * NANDFlash(EBI CS3) --> Slave Region 6: Non-Secure + */ + srtop_setting = MATRIX_SRTOP(6, MATRIX_SRTOP_VALUE_128M); + srtop_setting |= MATRIX_SRTOP(7, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(6, MATRIX_SASPLIT_VALUE_128M); + sasplit_setting |= MATRIX_SASPLIT(7, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = (MATRIX_LANSECH_NS(6) + | MATRIX_RDNSECH_NS(6) + | MATRIX_WRNSECH_NS(6)); + ssr_setting |= (MATRIX_LANSECH_NS(7) + | MATRIX_RDNSECH_NS(7) + | MATRIX_WRNSECH_NS(7)); + matrix_configure_slave_security(matrix32_base(), + H32MX_EXTERNAL_EBI, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 4: NFC SRAM (4K): Non-Secure */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_8K); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8K); + ssr_setting = (MATRIX_LANSECH_NS(0) + | MATRIX_RDNSECH_NS(0) + | MATRIX_WRNSECH_NS(0)); + matrix_configure_slave_security(matrix32_base(), + H32MX_NFC_SRAM, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 5: + * USB Device High Speed Dual Port RAM (DPR): 1M + * USB Host OHCI registers: 1M + * USB Host EHCI registers: 1M + */ + srtop_setting = (MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_1M) + | MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_1M) + | MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_1M)); + sasplit_setting = (MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_1M) + | MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_1M) + | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_1M)); + ssr_setting = (MATRIX_LANSECH_NS(0) + | MATRIX_LANSECH_NS(1) + | MATRIX_LANSECH_NS(2) + | MATRIX_RDNSECH_NS(0) + | MATRIX_RDNSECH_NS(1) + | MATRIX_RDNSECH_NS(2) + | MATRIX_WRNSECH_NS(0) + | MATRIX_WRNSECH_NS(1) + | MATRIX_WRNSECH_NS(2)); + matrix_configure_slave_security(matrix32_base(), + H32MX_USB, + srtop_setting, + sasplit_setting, + ssr_setting); +} + +static unsigned int security_ps_peri_id[] = { + AT91C_ID_PMC, + AT91C_ID_ARM, + AT91C_ID_PIT, + AT91C_ID_WDT, + AT91C_ID_GMAC, + AT91C_ID_XDMAC0, + AT91C_ID_XDMAC1, + AT91C_ID_ICM, + AT91C_ID_AES, + AT91C_ID_AESB, + AT91C_ID_TDES, + AT91C_ID_SHA, + AT91C_ID_MPDDRC, + AT91C_ID_HSMC, + AT91C_ID_FLEXCOM0, + AT91C_ID_FLEXCOM1, + AT91C_ID_FLEXCOM2, + AT91C_ID_FLEXCOM3, + AT91C_ID_FLEXCOM4, + AT91C_ID_UART0, + AT91C_ID_UART1, + AT91C_ID_UART2, + AT91C_ID_UART3, + AT91C_ID_UART4, + AT91C_ID_TWI0, + AT91C_ID_TWI1, + AT91C_ID_SDMMC0, + AT91C_ID_SDMMC1, + AT91C_ID_SPI0, + AT91C_ID_SPI1, + AT91C_ID_TC0, + AT91C_ID_TC1, + AT91C_ID_PWM, + AT91C_ID_ADC, + AT91C_ID_UHPHS, + AT91C_ID_UDPHS, + AT91C_ID_SSC0, + AT91C_ID_SSC1, + AT91C_ID_LCDC, + AT91C_ID_ISI, + AT91C_ID_TRNG, + AT91C_ID_PDMIC, + AT91C_ID_SFC, + AT91C_ID_QSPI0, + AT91C_ID_QSPI1, + AT91C_ID_I2SC0, + AT91C_ID_I2SC1, + AT91C_ID_CAN0_INT0, + AT91C_ID_CAN1_INT0, + AT91C_ID_CLASSD, + AT91C_ID_SFR, + AT91C_ID_L2CC, + AT91C_ID_CAN0_INT1, + AT91C_ID_CAN1_INT1, + AT91C_ID_GMAC_Q1, + AT91C_ID_GMAC_Q2, + AT91C_ID_SDMMC0_TIMER, + AT91C_ID_SDMMC1_TIMER, + AT91C_ID_SYS, + AT91C_ID_ACC, + AT91C_ID_RXLP, + AT91C_ID_SFRBU, + AT91C_ID_CHIPID, +}; + +static int matrix_init(void) +{ + matrix_write_protect_disable(matrix64_base()); + matrix_write_protect_disable(matrix32_base()); + + matrix_configure_slave_h64mx(); + matrix_configure_slave_h32mx(); + + return matrix_configure_periph_non_secure(security_ps_peri_id, + ARRAY_SIZE(security_ps_peri_id)); +} + +void plat_primary_init_early(void) +{ + matrix_init(); +} + +void itr_core_handler(void) +{ + atmel_saic_it_handle(); +} + +void main_init_gic(void) +{ + if (atmel_saic_setup()) + panic("Failed to init interrupts\n"); +} diff --git a/optee/optee_os/core/arch/arm/plat-sam/matrix.c b/optee/optee_os/core/arch/arm/plat-sam/matrix.c new file mode 100644 index 0000000..c0a39e5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/matrix.c @@ -0,0 +1,730 @@ +// SPDX-License-Identifier: BSD-Source-Code +/* + * Copyright (c) 2013, Atmel Corporation + * Copyright (c) 2017, Timesys Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 + +#define MATRIX_AXIMX 1 +#define MATRIX_H64MX 2 +#define MATRIX_H32MX 3 + +#define SECURITY_TYPE_AS 1 +#define SECURITY_TYPE_NS 2 +#define SECURITY_TYPE_PS 3 + +#define WORLD_NON_SECURE 0 +#define WORLD_SECURE 1 + +#define MATRIX_SPSELR_COUNT 3 +#define MATRIX_SLAVE_COUNT 15 + +struct peri_security { + unsigned int peri_id; + unsigned int matrix; + unsigned int security_type; + paddr_t addr; +}; + +static const struct peri_security peri_security_array[] = { + { + .peri_id = AT91C_ID_PMC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_PMC, + }, + { + .peri_id = AT91C_ID_ARM, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PIT, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_PITC, + }, + { + .peri_id = AT91C_ID_WDT, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_WDT, + }, + { + .peri_id = AT91C_ID_GMAC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_GMAC, + }, + { + .peri_id = AT91C_ID_XDMAC0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_XDMAC0, + }, + { + .peri_id = AT91C_ID_XDMAC1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_XDMAC1, + }, + { + .peri_id = AT91C_ID_ICM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_ICM, + }, + { + .peri_id = AT91C_ID_AES, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_AES, + }, + { + .peri_id = AT91C_ID_AESB, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_AESB, + }, + { + .peri_id = AT91C_ID_TDES, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TDES, + }, + { + .peri_id = AT91C_ID_SHA, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SHA, + }, + { + .peri_id = AT91C_ID_MPDDRC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_MPDDRC, + }, + { + .peri_id = AT91C_ID_MATRIX1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_MATRIX32, + }, + { + .peri_id = AT91C_ID_MATRIX0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_MATRIX64, + }, + { + .peri_id = AT91C_ID_SECUMOD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_SECUMOD, + }, + { + .peri_id = AT91C_ID_HSMC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_HSMC, + }, + { + .peri_id = AT91C_ID_PIOA, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_PIOA, + }, + { + .peri_id = AT91C_ID_FLEXCOM0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM0, + }, + { + .peri_id = AT91C_ID_FLEXCOM1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM1, + }, + { + .peri_id = AT91C_ID_FLEXCOM2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM2, + }, + { + .peri_id = AT91C_ID_FLEXCOM3, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM3, + }, + { + .peri_id = AT91C_ID_FLEXCOM4, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_FLEXCOM4, + }, + { + .peri_id = AT91C_ID_UART0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART0, + }, + { + .peri_id = AT91C_ID_UART1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART1, + }, + { + .peri_id = AT91C_ID_UART2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART2, + }, + { + .peri_id = AT91C_ID_UART3, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART3, + }, + { + .peri_id = AT91C_ID_UART4, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UART4, + }, + { + .peri_id = AT91C_ID_TWI0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TWI0, + }, + { + .peri_id = AT91C_ID_TWI1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TWI1, + }, + { + .peri_id = AT91C_ID_SDMMC0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SDHC0, + }, + { + .peri_id = AT91C_ID_SDMMC1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SDHC1, + }, + { + .peri_id = AT91C_ID_SPI0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SPI0, + }, + { + .peri_id = AT91C_ID_SPI1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SPI1, + }, + { + .peri_id = AT91C_ID_TC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TC0, + }, + { + .peri_id = AT91C_ID_TC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TC1, + }, + { + .peri_id = AT91C_ID_PWM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_PWMC, + }, + { + .peri_id = AT91C_ID_ADC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_ADC, + }, + { + .peri_id = AT91C_ID_UHPHS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_UDPHS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_UDPHS, + }, + { + .peri_id = AT91C_ID_SSC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SSC0, + }, + { + .peri_id = AT91C_ID_SSC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SSC1, + }, + { + .peri_id = AT91C_ID_LCDC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_LCDC, + }, + { + .peri_id = AT91C_ID_ISI, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_HXISI, + }, + { + .peri_id = AT91C_ID_TRNG, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_TRNG, + }, + { + .peri_id = AT91C_ID_PDMIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_PDMIC, + }, + { + .peri_id = AT91C_ID_IRQ, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_NS, + }, + { + .peri_id = AT91C_ID_SFC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SFC, + }, + { + .peri_id = AT91C_ID_SECURAM, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_SECURAM, + }, + { + .peri_id = AT91C_ID_QSPI0, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_QSPI0, + }, + { + .peri_id = AT91C_ID_QSPI1, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_QSPI1, + }, + { + .peri_id = AT91C_ID_I2SC0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_I2SC0, + }, + { + .peri_id = AT91C_ID_I2SC1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_I2SC1, + }, + { + .peri_id = AT91C_ID_CAN0_INT0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CAN1_INT0, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CLASSD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_CLASSD, + }, + { + .peri_id = AT91C_ID_SFR, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SFR, + }, + { + .peri_id = AT91C_ID_SAIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_SAIC, + }, + { + .peri_id = AT91C_ID_AIC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_NS, + .addr = AT91C_BASE_AIC, + }, + { + .peri_id = AT91C_ID_L2CC, + .matrix = MATRIX_H64MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_L2CC, + }, + { + .peri_id = AT91C_ID_CAN0_INT1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_CAN1_INT1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_GMAC_Q1, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_GMAC_Q2, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_PIOB, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_PIOB, + }, + { + .peri_id = AT91C_ID_PIOC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_PIOC, + }, + { + .peri_id = AT91C_ID_PIOD, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_AS, + .addr = AT91C_BASE_PIOD, + }, + { + .peri_id = AT91C_ID_SDMMC0_TIMER, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SDMMC1_TIMER, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + }, + { + .peri_id = AT91C_ID_SYS, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SYSC, + }, + { + .peri_id = AT91C_ID_ACC, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_ACC, + }, + { + .peri_id = AT91C_ID_RXLP, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_RXLP, + }, + { + .peri_id = AT91C_ID_SFRBU, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_SFRBU, + }, + { + .peri_id = AT91C_ID_CHIPID, + .matrix = MATRIX_H32MX, + .security_type = SECURITY_TYPE_PS, + .addr = AT91C_BASE_CHIPID, + }, +}; + +static void matrix_write(unsigned int base, + unsigned int offset, + const unsigned int value) +{ + io_write32(offset + base, value); +} + +static unsigned int matrix_read(int base, unsigned int offset) +{ + return io_read32(offset + base); +} + +void matrix_write_protect_enable(unsigned int matrix_base) +{ + matrix_write(matrix_base, MATRIX_WPMR, + (MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE)); +} + +void matrix_write_protect_disable(unsigned int matrix_base) +{ + matrix_write(matrix_base, MATRIX_WPMR, MATRIX_WPMR_WPKEY_PASSWD); +} + +void matrix_configure_slave_security(unsigned int matrix_base, + unsigned int slave, + unsigned int srtop_setting, + unsigned int srsplit_setting, + unsigned int ssr_setting) +{ + matrix_write(matrix_base, MATRIX_SSR(slave), ssr_setting); + matrix_write(matrix_base, MATRIX_SRTSR(slave), srtop_setting); + matrix_write(matrix_base, MATRIX_SASSR(slave), srsplit_setting); +} + +static const struct peri_security *get_peri_security(unsigned int peri_id) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) { + if (peri_id == peri_security_array[i].peri_id) + return &peri_security_array[i]; + } + + return NULL; +} + +static int matrix_set_periph_world(unsigned int matrix, unsigned int peri_id, + unsigned int world) +{ + unsigned int base; + unsigned int spselr; + unsigned int idx; + unsigned int bit; + + idx = peri_id / 32; + if (idx > 3) + return -1; + + bit = (0x01 << (peri_id % 32)); + + if (matrix == MATRIX_H32MX) + base = matrix32_base(); + else if (matrix == MATRIX_H64MX) + base = matrix64_base(); + else + return -1; + + spselr = matrix_read(base, MATRIX_SPSELR(idx)); + if (world == WORLD_SECURE) + spselr &= ~bit; + else + spselr |= bit; + matrix_write(base, MATRIX_SPSELR(idx), spselr); + + return 0; +} + +TEE_Result matrix_dt_get_id(const void *fdt, int node, unsigned int *id) +{ + unsigned int i = 0; + paddr_t pbase = 0; + + pbase = fdt_reg_base_address(fdt, node); + if (pbase == DT_INFO_INVALID_REG) + return TEE_ERROR_BAD_PARAMETERS; + + for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) { + if (peri_security_array[i].addr == pbase) { + *id = peri_security_array[i].peri_id; + return TEE_SUCCESS; + } + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +int matrix_configure_periph_secure(unsigned int peri_id) +{ + const struct peri_security *psec = NULL; + + psec = get_peri_security(peri_id); + if (!psec) + return -1; + + return matrix_set_periph_world(psec->matrix, peri_id, WORLD_SECURE); +} + +int matrix_configure_periph_non_secure(unsigned int *peri_id_array, + unsigned int size) +{ + unsigned int i; + unsigned int *peri_id_p; + unsigned int matrix; + unsigned int peri_id; + const struct peri_security *peripheral_sec; + int ret; + + if (!peri_id_array || !size) + return -1; + + peri_id_p = peri_id_array; + for (i = 0; i < size; i++) { + peripheral_sec = get_peri_security(*peri_id_p); + if (!peripheral_sec) + return -1; + + if (peripheral_sec->security_type != SECURITY_TYPE_PS) + return -1; + + matrix = peripheral_sec->matrix; + peri_id = *peri_id_p; + ret = matrix_set_periph_world(matrix, peri_id, + WORLD_NON_SECURE); + if (ret) + return -1; + + peri_id_p++; + } + + return 0; +} + +#ifdef CFG_PM_ARM32 +struct matrix_state { + uint32_t spselr[MATRIX_SPSELR_COUNT]; + uint32_t ssr[MATRIX_SLAVE_COUNT]; + uint32_t srtsr[MATRIX_SLAVE_COUNT]; + uint32_t sassr[MATRIX_SLAVE_COUNT]; + uint32_t meier; + uint32_t meimr; +}; + +static struct matrix_state matrix32_state; +static struct matrix_state matrix64_state; + +static void matrix_save_regs(vaddr_t base, struct matrix_state *state) +{ + int idx = 0; + + for (idx = 0; idx < MATRIX_SPSELR_COUNT; idx++) + state->spselr[idx] = matrix_read(base, MATRIX_SPSELR(idx)); + + for (idx = 0; idx < MATRIX_SLAVE_COUNT; idx++) { + state->ssr[idx] = matrix_read(base, MATRIX_SSR(idx)); + state->srtsr[idx] = matrix_read(base, MATRIX_SRTSR(idx)); + state->sassr[idx] = matrix_read(base, MATRIX_SASSR(idx)); + } + + state->meier = matrix_read(base, MATRIX_MEIER); + state->meimr = matrix_read(base, MATRIX_MEIMR); +} + +static void matrix_suspend(void) +{ + matrix_save_regs(matrix32_base(), &matrix32_state); + matrix_save_regs(matrix64_base(), &matrix64_state); +} + +static void matrix_restore_regs(vaddr_t base, struct matrix_state *state) +{ + int idx = 0; + + matrix_write_protect_disable(base); + + for (idx = 0; idx < MATRIX_SPSELR_COUNT; idx++) + matrix_write(base, MATRIX_SPSELR(idx), state->spselr[idx]); + + for (idx = 0; idx < MATRIX_SLAVE_COUNT; idx++) { + matrix_write(base, MATRIX_SSR(idx), state->ssr[idx]); + matrix_write(base, MATRIX_SRTSR(idx), state->srtsr[idx]); + matrix_write(base, MATRIX_SASSR(idx), state->sassr[idx]); + } + + matrix_write(base, MATRIX_MEIER, state->meier); + matrix_write(base, MATRIX_MEIMR, state->meimr); +} + +static void matrix_resume(void) +{ + matrix_restore_regs(matrix32_base(), &matrix32_state); + matrix_restore_regs(matrix64_base(), &matrix64_state); +} + +static TEE_Result matrix_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *hdl __unused) +{ + switch (op) { + case PM_OP_RESUME: + matrix_resume(); + break; + case PM_OP_SUSPEND: + matrix_suspend(); + break; + default: + panic("Invalid PM operation"); + } + + return TEE_SUCCESS; +} + +static TEE_Result matrix_pm_init(void) +{ + /* + * We can't call matrix_register_pm in matrix_init since allocator is + * not ready yet so we just call it later in this driver init callback. + */ + register_pm_driver_cb(matrix_pm, NULL, "sam-matrix"); + + return TEE_SUCCESS; +} +driver_init(matrix_pm_init); + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-sam/matrix.h b/optee/optee_os/core/arch/arm/plat-sam/matrix.h new file mode 100644 index 0000000..2169057 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/matrix.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-Source-Code */ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2013, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 MATRIX_H +#define MATRIX_H + +#include + +extern void matrix_write_protect_enable(unsigned int matrix_base); +extern void matrix_write_protect_disable(unsigned int matrix_base); +extern void matrix_configure_slave_security(unsigned int matrix_base, + unsigned int slave, + unsigned int srtop_setting, + unsigned int srsplit_setting, + unsigned int ssr_setting); + +int matrix_configure_periph_non_secure(unsigned int *peri_id_array, + unsigned int size); +int matrix_configure_periph_secure(unsigned int peri_id); +TEE_Result matrix_dt_get_id(const void *fdt, int node, unsigned int *id); + +vaddr_t matrix32_base(void); +vaddr_t matrix64_base(void); + +#endif /* #ifndef MATRIX_H */ diff --git a/optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c b/optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c new file mode 100644 index 0000000..e9c3589 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static enum sm_handler_ret sam_sip_handler(struct thread_smc_args *args) +{ + switch (OPTEE_SMC_FUNC_NUM(args->a0)) { + case SAMA5_SMC_SIP_SFR_SET_USB_SUSPEND: + atmel_sfr_set_usb_suspend(args->a1); + args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS; + break; + case SAMA5_SMC_SIP_SET_SUSPEND_MODE: + return at91_pm_set_suspend_mode(args); + case SAMA5_SMC_SIP_GET_SUSPEND_MODE: + return at91_pm_get_suspend_mode(args); + default: + return SM_HANDLER_PENDING_SMC; + } + + return SM_HANDLER_SMC_HANDLED; +} + +enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) +{ + uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); + uint16_t smc_owner = OPTEE_SMC_OWNER_NUM(*nsec_r0); + + switch (smc_owner) { + case OPTEE_SMC_OWNER_SIP: + return sam_sip_handler((struct thread_smc_args *)nsec_r0); + default: + return SM_HANDLER_PENDING_SMC; + } +} + diff --git a/optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h b/optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h new file mode 100644 index 0000000..dee8e02 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/nsec-service/smc_ids.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Microchip + */ + +#ifndef SMC_IDS_H +#define SMC_IDS_H + +#define SAMA5_SMC_SIP_SFR_SET_USB_SUSPEND 0x300 + +#define SAMA5_SMC_SIP_SET_SUSPEND_MODE 0x400 +#define SAMA5_SMC_SIP_GET_SUSPEND_MODE 0x401 + +/* SAMA5 SMC return codes */ +#define SAMA5_SMC_SIP_RETURN_SUCCESS 0x0 +#define SAMA5_SMC_SIP_RETURN_EINVAL 0x1 + +#endif /* SMC_IDS_H */ diff --git a/optee/optee_os/core/arch/arm/plat-sam/nsec-service/sub.mk b/optee/optee_os/core/arch/arm/plat-sam/nsec-service/sub.mk new file mode 100644 index 0000000..3c5f232 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/nsec-service/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . + +srcs-y += sm_platform_handler.c diff --git a/optee/optee_os/core/arch/arm/plat-sam/platform_config.h b/optee/optee_os/core/arch/arm/plat-sam/platform_config.h new file mode 100644 index 0000000..9742c61 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/platform_config.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017 Timesys Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include +#include + +#define STACK_ALIGNMENT 64 + +#ifdef CFG_WITH_PAGER +#error "Pager not supported for platform sama5d2" +#endif +#ifdef CFG_WITH_LPAE +#error "LPAE not supported" +#endif + +#if defined(PLATFORM_FLAVOR_sama5d27_wlsom1_ek) +#define CONSOLE_UART_BASE AT91C_BASE_UART0 +#else +#define CONSOLE_UART_BASE AT91C_BASE_UART1 +#endif + +#define PL310_BASE (AT91C_BASE_L2CC) +#define SFR_BASE (AT91C_BASE_SFR) + +/* + * PL310 Auxiliary Control Register + * + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockdown cache lines (bit26=1) + * Round robin replacement policy (bit25=1) + * Force write allocated (default) + * Treats shared accesses (bit22=0, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * Platform flavor specific way config: + * - 16kb way size (bit19:17=3b001) + * Store buffer device limitation disabled (bit11=0) + * Cacheable accesses have high prio (bit10=0) + */ +#define PL310_AUX_CTRL_INIT 0x3E020000 + +/* + * PL310 Prefetch Control Register + * + * Double linefill enabled (bit30=1) + * I/D prefetch enabled (bit29:28=2b11) + * Prefetch drop enabled (bit24=1) + * Incr double linefill enable (bit23=1) + * Prefetch offset = 1 (bit4:0) + */ +#define PL310_PREFETCH_CTRL_INIT 0x71800001 + +/* + * PL310 Power Register + * + * Dynamic clock gating enabled + * Standby mode enabled + */ +#define PL310_POWER_CTRL_INIT 0x00000003 + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-sam/pm/psci.c b/optee/optee_os/core/arch/arm/plat-sam/pm/psci.c new file mode 100644 index 0000000..3bd2471 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/pm/psci.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int psci_system_suspend(uintptr_t entry, uint32_t context_id __unused, + struct sm_nsec_ctx *nsec) +{ + if (!atmel_pm_suspend_available()) + return PSCI_RET_NOT_SUPPORTED; + + if (atmel_pm_suspend(entry, nsec)) + return PSCI_RET_INTERNAL_FAILURE; + + return PSCI_RET_SUCCESS; +} + +int psci_cpu_suspend(uint32_t power_state, + uintptr_t entry __unused, uint32_t context_id __unused, + struct sm_nsec_ctx *nsec __unused) +{ + uint32_t type = 0; + + if (atmel_pm_suspend_available()) + return PSCI_RET_NOT_SUPPORTED; + + type = (power_state & PSCI_POWER_STATE_TYPE_MASK) >> + PSCI_POWER_STATE_TYPE_SHIFT; + + if (type != PSCI_POWER_STATE_TYPE_STANDBY) { + DMSG("Power state %x not supported", type); + return PSCI_RET_INVALID_PARAMETERS; + } + + atmel_pm_cpu_idle(); + + return PSCI_RET_SUCCESS; +} + +void __noreturn psci_system_off(void) +{ + if (!atmel_shdwc_available()) + panic(); + + atmel_shdwc_shutdown(); +} + +void __noreturn psci_system_reset(void) +{ + if (!atmel_rstc_available()) + panic(); + + atmel_rstc_reset(); +} + +int psci_features(uint32_t psci_fid) +{ + switch (psci_fid) { + case ARM_SMCCC_VERSION: + case PSCI_PSCI_FEATURES: + case PSCI_VERSION: + return PSCI_RET_SUCCESS; + case PSCI_SYSTEM_RESET: + if (atmel_rstc_available()) + return PSCI_RET_SUCCESS; + return PSCI_RET_NOT_SUPPORTED; + case PSCI_SYSTEM_OFF: + if (atmel_shdwc_available()) + return PSCI_RET_SUCCESS; + return PSCI_RET_NOT_SUPPORTED; + case PSCI_CPU_SUSPEND: + case PSCI_SYSTEM_SUSPEND: + if (atmel_pm_suspend_available()) + return PSCI_RET_SUCCESS; + return PSCI_RET_NOT_SUPPORTED; + default: + return PSCI_RET_NOT_SUPPORTED; + } +} + +uint32_t psci_version(void) +{ + return PSCI_VERSION_1_0; +} diff --git a/optee/optee_os/core/arch/arm/plat-sam/pm/sub.mk b/optee/optee_os/core/arch/arm/plat-sam/pm/sub.mk new file mode 100644 index 0000000..c8ae8f9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/pm/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_PSCI_ARM32) += psci.c diff --git a/optee/optee_os/core/arch/arm/plat-sam/sam_pl310.c b/optee/optee_os/core/arch/arm/plat-sam/sam_pl310.c new file mode 100644 index 0000000..d2cc227 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/sam_pl310.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Timesys Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); + +vaddr_t pl310_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC, 1); + return (vaddr_t)va; + } + return PL310_BASE; +} + +void arm_cl2_config(vaddr_t pl310_base) +{ + io_write32(pl310_base + PL310_CTRL, 0); + io_write32(sam_sfr_base() + AT91_SFR_L2CC_HRAMC, 0x1); + io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); + io_write32(pl310_base + PL310_PREFETCH_CTRL, PL310_PREFETCH_CTRL_INIT); + io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); + + /* invalidate all cache ways */ + arm_cl2_invbyway(pl310_base); +} + +void arm_cl2_enable(vaddr_t pl310_base) +{ + /* Enable PL310 ctrl -> only set lsb bit */ + io_write32(pl310_base + PL310_CTRL, 1); +} diff --git a/optee/optee_os/core/arch/arm/plat-sam/sam_sfr.c b/optee/optee_os/core/arch/arm/plat-sam/sam_sfr.c new file mode 100644 index 0000000..3e3523a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/sam_sfr.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Timesys Corporation. + * Copyright (C) 2021 Microchip + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SFR_BASE, CORE_MMU_PGDIR_SIZE); + +vaddr_t sam_sfr_base(void) +{ + static void *va; + + if (!cpu_mmu_enabled()) + return SFR_BASE; + + if (!va) + va = phys_to_virt(SFR_BASE, MEM_AREA_IO_SEC, 1); + + return (vaddr_t)va; +} + +void atmel_sfr_set_usb_suspend(bool set) +{ + if (set) + io_setbits32(sam_sfr_base() + AT91_SFR_OHCIICR, + AT91_OHCIICR_USB_SUSPEND); + else + io_clrbits32(sam_sfr_base() + AT91_SFR_OHCIICR, + AT91_OHCIICR_USB_SUSPEND); +} + +static TEE_Result atmel_sfr_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + if (fdt_get_status(fdt, node) == DT_STATUS_OK_SEC) + matrix_configure_periph_secure(AT91C_ID_SFR); + + return TEE_SUCCESS; +} + +static const struct dt_device_match atmel_sfr_match_table[] = { + { .compatible = "atmel,sama5d2-sfr" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_sfr_dt_driver) = { + .name = "atmel_sfr", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_sfr_match_table, + .probe = atmel_sfr_probe, +}; diff --git a/optee/optee_os/core/arch/arm/plat-sam/sam_sfr.h b/optee/optee_os/core/arch/arm/plat-sam/sam_sfr.h new file mode 100644 index 0000000..c409102 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/sam_sfr.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Bootlin + */ + +#ifndef SAM_SFR_H +#define SAM_SFR_H + +#include +#include + +/* OHCI INT Configuration Register */ +#define AT91_SFR_OHCIICR 0x10 +/* UTMI Clock Trimming Register */ +#define AT91_SFR_UTMICKTRIM 0x30 +/* Serial number 0 Register */ +#define AT91_SFR_SN0 0x4c +/* Serial number 1 Register */ +#define AT91_SFR_SN1 0x50 +/* AIC Interrupt Redirection Register */ +#define AT91_SFR_AICREDIR 0x54 +/* L2 cache RAM used as an internal SRAM */ +#define AT91_SFR_L2CC_HRAMC 0x58 +/* I2SC Register */ +#define AT91_SFR_I2SCLKSEL 0x90 + +/* Field definitions */ +#define AT91_UTMICKTRIM_FREQ GENMASK_32(1, 0) + +#define AT91_OHCIICR_USB_SUSPEND GENMASK_32(10, 8) + +#define AT91_SFR_AICREDIR_XOR_KEY 0xb6d81c4d +#define AT91_SFR_AICREDIR_KEY_MASK GENMASK_32(31, 1) + +vaddr_t sam_sfr_base(void); + +void atmel_sfr_set_usb_suspend(bool set); + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-sam/sama5d2.h b/optee/optee_os/core/arch/arm/plat-sam/sama5d2.h new file mode 100644 index 0000000..d7d1451 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/sama5d2.h @@ -0,0 +1,274 @@ +/* SPDX-License-Identifier: BSD-Source-Code */ +/* + * Copyright (c) 2015, Atmel Corporation + * Copyright (c) 2017, Timesys Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 SAMA5D2_H +#define SAMA5D2_H + +/* + * Peripheral identifiers/interrupts. + */ +#define AT91C_ID_FIQ 0 /* FIQ Interrupt ID */ +#define AT91C_ID_PMC 1 /* Power Management Controller */ +#define AT91C_ID_ARM 2 /* Performance Monitor Unit */ +#define AT91C_ID_PIT 3 /* Periodic Interval Timer Interrupt */ +#define AT91C_ID_WDT 4 /* Watchdog Timer Interrupt */ +#define AT91C_ID_GMAC 5 /* Ethernet MAC */ +#define AT91C_ID_XDMAC0 6 /* DMA Controller 0 */ +#define AT91C_ID_XDMAC1 7 /* DMA Controller 1 */ +#define AT91C_ID_ICM 8 /* Integrity Check Monitor */ +#define AT91C_ID_AES 9 /* Advanced Encryption Standard */ +#define AT91C_ID_AESB 10 /* AES bridge */ +#define AT91C_ID_TDES 11 /* Triple Data Encryption Standard */ +#define AT91C_ID_SHA 12 /* SHA Signature */ +#define AT91C_ID_MPDDRC 13 /* MPDDR Controller */ +#define AT91C_ID_MATRIX1 14 /* H32MX, 32-bit AHB Matrix */ +#define AT91C_ID_MATRIX0 15 /* H64MX, 64-bit AHB Matrix */ +#define AT91C_ID_SECUMOD 16 /* Secure Module */ +#define AT91C_ID_HSMC 17 /* Multi-bit ECC interrupt */ +#define AT91C_ID_PIOA 18 /* Parallel I/O Controller A */ +#define AT91C_ID_FLEXCOM0 19 /* FLEXCOM0 */ +#define AT91C_ID_FLEXCOM1 20 /* FLEXCOM1 */ +#define AT91C_ID_FLEXCOM2 21 /* FLEXCOM2 */ +#define AT91C_ID_FLEXCOM3 22 /* FLEXCOM3 */ +#define AT91C_ID_FLEXCOM4 23 /* FLEXCOM4 */ +#define AT91C_ID_UART0 24 /* UART0 */ +#define AT91C_ID_UART1 25 /* UART1 */ +#define AT91C_ID_UART2 26 /* UART2 */ +#define AT91C_ID_UART3 27 /* UART3 */ +#define AT91C_ID_UART4 28 /* UART4 */ +#define AT91C_ID_TWI0 29 /* Two-wire Interface 0 */ +#define AT91C_ID_TWI1 30 /* Two-wire Interface 1 */ +#define AT91C_ID_SDMMC0 31 /* SDMMC Controller 0 */ +#define AT91C_ID_SDMMC1 32 /* SDMMC Controller 1 */ +#define AT91C_ID_SPI0 33 /* Serial Peripheral Interface 0 */ +#define AT91C_ID_SPI1 34 /* Serial Peripheral Interface 1 */ +#define AT91C_ID_TC0 35 /* Timer Counter 0 (ch.0,1,2) */ +#define AT91C_ID_TC1 36 /* Timer Counter 1 (ch.3,4,5) */ +/* 37 */ +#define AT91C_ID_PWM 38 /* PWM Controller0 (ch. 0,1,2,3) */ +/* 39 */ +#define AT91C_ID_ADC 40 /* Touch Screen ADC Controller */ +#define AT91C_ID_UHPHS 41 /* USB Host High Speed */ +#define AT91C_ID_UDPHS 42 /* USB Device High Speed */ +#define AT91C_ID_SSC0 43 /* Serial Synchronous Controller 0 */ +#define AT91C_ID_SSC1 44 /* Serial Synchronous Controller 1 */ +#define AT91C_ID_LCDC 45 /* LCD Controller */ +#define AT91C_ID_ISI 46 /* Image Sensor Interface */ +#define AT91C_ID_TRNG 47 /* True Random Number Generator */ +#define AT91C_ID_PDMIC 48 /* PDM Interface Controller */ +#define AT91C_ID_IRQ 49 /* IRQ Interrupt ID */ +#define AT91C_ID_SFC 50 /* Fuse Controller */ +#define AT91C_ID_SECURAM 51 /* Secure RAM */ +#define AT91C_ID_QSPI0 52 /* QSPI0 */ +#define AT91C_ID_QSPI1 53 /* QSPI1 */ +#define AT91C_ID_I2SC0 54 /* Inter-IC Sound Controller 0 */ +#define AT91C_ID_I2SC1 55 /* Inter-IC Sound Controller 1 */ +#define AT91C_ID_CAN0_INT0 56 /* MCAN 0 Interrupt0 */ +#define AT91C_ID_CAN1_INT0 57 /* MCAN 1 Interrupt0 */ +#define AT91C_ID_PTC 58 /* Peripheral Touch Controller */ +#define AT91C_ID_CLASSD 59 /* Audio Class D Amplifier */ +#define AT91C_ID_SFR 60 /* Special Function Register */ +#define AT91C_ID_SAIC 61 /* Secured AIC */ +#define AT91C_ID_AIC 62 /* Advanced Interrupt Controller */ +#define AT91C_ID_L2CC 63 /* L2 Cache Controller */ +#define AT91C_ID_CAN0_INT1 64 /* MCAN 0 Interrupt1 */ +#define AT91C_ID_CAN1_INT1 65 /* MCAN 1 Interrupt1 */ +#define AT91C_ID_GMAC_Q1 66 /* GMAC Queue 1 Interrupt */ +#define AT91C_ID_GMAC_Q2 67 /* GMAC Queue 2 Interrupt */ +#define AT91C_ID_PIOB 68 /* Parallel I/O Controller B */ +#define AT91C_ID_PIOC 69 /* Parallel I/O Controller C */ +#define AT91C_ID_PIOD 70 /* Parallel I/O Controller D */ +#define AT91C_ID_SDMMC0_TIMER 71 /* SDMMC0 Timer */ +#define AT91C_ID_SDMMC1_TIMER 72 /* SDMMC1 Timer */ +/* 73 */ +#define AT91C_ID_SYS 74 /* System Controller Interrupt */ +#define AT91C_ID_ACC 75 /* Analog Comparator */ +#define AT91C_ID_RXLP 76 /* UART Low-Power */ +#define AT91C_ID_SFRBU 77 /* Special Function Register BackUp */ +#define AT91C_ID_CHIPID 78 /* Chip ID */ + +#define AT91C_ID_COUNTS (AT91C_ID_CHIPID + 1) + +/* + * User Peripherals physical base addresses. + */ +#define AT91C_BASE_LCDC 0xf0000000 +#define AT91C_BASE_XDMAC1 0xf0004000 +#define AT91C_BASE_HXISI 0xf0008000 +#define AT91C_BASE_MPDDRC 0xf000c000 +#define AT91C_BASE_XDMAC0 0xf0010000 +#define AT91C_BASE_PMC 0xf0014000 +#define AT91C_BASE_MATRIX64 0xf0018000 /* MATRIX0 */ +#define AT91C_BASE_AESB 0xf001c000 +#define AT91C_BASE_QSPI0 0xf0020000 +#define AT91C_BASE_QSPI1 0xf0024000 +#define AT91C_BASE_SHA 0xf0028000 +#define AT91C_BASE_AES 0xf002c000 + +#define AT91C_BASE_SPI0 0xf8000000 +#define AT91C_BASE_SSC0 0xf8004000 +#define AT91C_BASE_GMAC 0xf8008000 +#define AT91C_BASE_TC0 0xf800c000 +#define AT91C_BASE_TC1 0xf8010000 +#define AT91C_BASE_HSMC 0xf8014000 +#define AT91C_BASE_PDMIC 0xf8018000 +#define AT91C_BASE_UART0 0xf801c000 +#define AT91C_BASE_UART1 0xf8020000 +#define AT91C_BASE_UART2 0xf8024000 +#define AT91C_BASE_TWI0 0xf8028000 +#define AT91C_BASE_PWMC 0xf802c000 +#define AT91C_BASE_SFR 0xf8030000 +#define AT91C_BASE_FLEXCOM0 0xf8034000 +#define AT91C_BASE_FLEXCOM1 0xf8038000 +#define AT91C_BASE_SAIC 0xf803c000 +#define AT91C_BASE_ICM 0xf8040000 +#define AT91C_BASE_SECURAM 0xf8044000 +#define AT91C_BASE_SYSC 0xf8048000 +#define AT91C_BASE_ACC 0xf804a000 +#define AT91C_BASE_RXLP 0xf8049000 +#define AT91C_BASE_SFC 0xf804c000 +#define AT91C_BASE_I2SC0 0xf8050000 +#define AT91C_BASE_CAN0 0xf8054000 + +#define AT91C_BASE_SPI1 0xfc000000 +#define AT91C_BASE_SSC1 0xfc004000 +#define AT91C_BASE_UART3 0xfc008000 +#define AT91C_BASE_UART4 0xfc00c000 +#define AT91C_BASE_FLEXCOM2 0xfc010000 +#define AT91C_BASE_FLEXCOM3 0xfc014000 +#define AT91C_BASE_FLEXCOM4 0xfc018000 +#define AT91C_BASE_TRNG 0xfc01c000 +#define AT91C_BASE_AIC 0xfc020000 +#define AT91C_BASE_TWI1 0xfc028000 +#define AT91C_BASE_UDPHS 0xfc02c000 +#define AT91C_BASE_ADC 0xfc030000 + +#define AT91C_BASE_PIOA 0xfc038000 +#define AT91C_BASE_MATRIX32 0xfc03c000 /* MATRIX1 */ +#define AT91C_BASE_SECUMOD 0xfc040000 +#define AT91C_BASE_TDES 0xfc044000 +#define AT91C_BASE_CLASSD 0xfc048000 +#define AT91C_BASE_I2SC1 0xfc04c000 +#define AT91C_BASE_CAN1 0xfc050000 +#define AT91C_BASE_SFRBU 0xfc05c000 +#define AT91C_BASE_CHIPID 0xfc069000 + +/* + * Address Memory Space + */ +#define AT91C_BASE_INTERNAL_MEM 0x00000000 +#define AT91C_BASE_CS0 0x10000000 +#define AT91C_BASE_DDRCS 0x20000000 +#define AT91C_BASE_DDRCS_AES 0x40000000 +#define AT91C_BASE_CS1 0x60000000 +#define AT91C_BASE_CS2 0x70000000 +#define AT91C_BASE_CS3 0x80000000 +#define AT91C_BASE_QSPI0_AES_MEM 0x90000000 +#define AT91C_BASE_QSPI1_AES_MEM 0x98000000 +#define AT91C_BASE_SDHC0 0xa0000000 +#define AT91C_BASE_SDHC1 0xb0000000 +#define AT91C_BASE_NFC_CMD_REG 0xc0000000 +#define AT91C_BASE_QSPI0_MEM 0xd0000000 +#define AT91C_BASE_QSPI1_MEM 0xd8000000 +#define AT91C_BASE_PERIPH 0xf0000000 + +/* + * Internal Memories + */ +#define AT91C_BASE_ROM 0x00000000 /* ROM */ +#define AT91C_BASE_ECC_ROM 0x00060000 /* ECC ROM */ +#define AT91C_BASE_NFC_SRAM 0x00100000 /* NFC SRAM */ +#define AT91C_BASE_SRAM0 0x00200000 /* SRAM0 */ +#define AT91C_BASE_SRAM1 0x00220000 /* SRAM1 */ +#define AT91C_BASE_UDPHS_SRAM 0x00300000 /* UDPHS RAM */ +#define AT91C_BASE_UHP_OHCI 0x00400000 /* UHP OHCI */ +#define AT91C_BASE_UHP_EHCI 0x00500000 /* UHP EHCI */ +#define AT91C_BASE_AXI_MATRIX 0x00600000 /* AXI Maxtrix */ +#define AT91C_BASE_DAP 0x00700000 /* DAP */ +#define AT91C_BASE_PTC 0x00800000 /* PTC */ +#define AT91C_BASE_L2CC 0x00A00000 /* L2CC */ + +/* + * Other misc defines + */ +#define AT91C_BASE_PMECC (AT91C_BASE_HSMC + 0x70) +#define AT91C_BASE_PMERRLOC (AT91C_BASE_HSMC + 0x500) + +#define AT91_PMECC (AT91C_BASE_PMECC - AT91C_BASE_SYS) +#define AT91_PMERRLOC (AT91C_BASE_PMERRLOC - AT91C_BASE_SYS) + +#define AT91C_BASE_PIOB (AT91C_BASE_PIOA + 0x40) +#define AT91C_BASE_PIOC (AT91C_BASE_PIOB + 0x40) +#define AT91C_BASE_PIOD (AT91C_BASE_PIOC + 0x40) + +/* SYSC spawns */ +#define AT91C_BASE_RSTC AT91C_BASE_SYSC +#define AT91C_BASE_SHDC (AT91C_BASE_SYSC + 0x10) +#define AT91C_BASE_PITC (AT91C_BASE_SYSC + 0x30) +#define AT91C_BASE_WDT (AT91C_BASE_SYSC + 0x40) +#define AT91C_BASE_SCKCR (AT91C_BASE_SYSC + 0x50) +#define AT91C_BASE_RTCC (AT91C_BASE_SYSC + 0xb0) + +#define ATMEL_BASE_SMC (AT91C_BASE_HSMC + 0x700) + +#define AT91C_NUM_PIO 4 +#define AT91C_NUM_TWI 2 + +/* AICREDIR Unlock Key */ +#define AICREDIR_KEY 0xB6D81C4D + +/* + * Matrix Slaves ID + */ +/* MATRIX0(H64MX) Matrix Slaves */ +/* Bridge from H64MX to AXIMX (Internal ROM, Cryto Library, PKCC RAM) */ +#define H64MX_SLAVE_BRIDGE_TO_AXIMX 0 +#define H64MX_SLAVE_PERI_BRIDGE 1 /* H64MX Peripheral Bridge */ +#define H64MX_SLAVE_DDR2_PORT_0 2 /* DDR2 Port0-AESOTF */ +#define H64MX_SLAVE_DDR2_PORT_1 3 /* DDR2 Port1 */ +#define H64MX_SLAVE_DDR2_PORT_2 4 /* DDR2 Port2 */ +#define H64MX_SLAVE_DDR2_PORT_3 5 /* DDR2 Port3 */ +#define H64MX_SLAVE_DDR2_PORT_4 6 /* DDR2 Port4 */ +#define H64MX_SLAVE_DDR2_PORT_5 7 /* DDR2 Port5 */ +#define H64MX_SLAVE_DDR2_PORT_6 8 /* DDR2 Port6 */ +#define H64MX_SLAVE_DDR2_PORT_7 9 /* DDR2 Port7 */ +#define H64MX_SLAVE_INTERNAL_SRAM 10 /* Internal SRAM 128K */ +#define H64MX_SLAVE_CACHE_L2 11 /* Internal SRAM 128K (L2) */ +#define H64MX_SLAVE_QSPI0 12 /* QSPI0 */ +#define H64MX_SLAVE_QSPI1 13 /* QSPI1 */ +#define H64MX_SLAVE_AESB 14 /* AESB */ + +/* MATRIX1(H32MX) Matrix Slaves */ +#define H32MX_BRIDGE_TO_H64MX 0 /* Bridge from H32MX to H64MX */ +#define H32MX_PERI_BRIDGE_0 1 /* H32MX Peripheral Bridge 0 */ +#define H32MX_PERI_BRIDGE_1 2 /* H32MX Peripheral Bridge 1 */ +#define H32MX_EXTERNAL_EBI 3 /* External Bus Interface */ +#define H32MX_NFC_CMD_REG 3 /* NFC command Register */ +#define H32MX_NFC_SRAM 4 /* NFC SRAM */ +#define H32MX_USB 5 + +#endif /* #ifndef SAMA5D2_H */ diff --git a/optee/optee_os/core/arch/arm/plat-sam/sub.mk b/optee/optee_os/core/arch/arm/plat-sam/sub.mk new file mode 100644 index 0000000..9e25f8c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/sub.mk @@ -0,0 +1,6 @@ +global-incdirs-y += . +srcs-y += main.c freq.c sam_sfr.c +srcs-$(CFG_AT91_MATRIX) += matrix.c +srcs-$(CFG_PL310) += sam_pl310.c +subdirs-y += pm +subdirs-y += nsec-service diff --git a/optee/optee_os/core/arch/arm/plat-sam/tz_matrix.h b/optee/optee_os/core/arch/arm/plat-sam/tz_matrix.h new file mode 100644 index 0000000..7db2e3d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sam/tz_matrix.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: BSD-Source-Code */ +/* + * Copyright (c) 2013, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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_MATRIX_H +#define TZ_MATRIX_H + +#define MATRIX_MCFG(n) (0x0000 + (n) * 4) /* Master Configuration Register */ +#define MATRIX_SCFG(n) (0x0040 + (n) * 4) /* Slave Configuration Register */ +#define MATRIX_PRAS(n) (0x0080 + (n) * 8) /* Priority Register A for Slave */ +#define MATRIX_PRBS(n) (0x0084 + (n) * 8) /* Priority Register B for Slave */ + +#define MATRIX_MRCR 0x0100 /* Master Remap Control Register */ +#define MATRIX_MEIER 0x0150 /* Master Error Interrupt Enable Register */ +#define MATRIX_MEIDR 0x0154 /* Master Error Interrupt Disable Register */ +#define MATRIX_MEIMR 0x0158 /* Master Error Interrupt Mask Register */ +#define MATRIX_MESR 0x015c /* Master Error Status Register */ + +/* Master n Error Address Register */ +#define MATRIX_MEAR(n) (0x0160 + (n) * 4) + +#define MATRIX_WPMR 0x01E4 /* Write Protect Mode Register */ +#define MATRIX_WPSR 0x01E8 /* Write Protect Status Register */ + +/* Security Slave n Register */ +#define MATRIX_SSR(n) (0x0200 + (n) * 4) +/* Security Area Split Slave n Register */ +#define MATRIX_SASSR(n) (0x0240 + (n) * 4) +/* Security Region Top Slave n Register */ +#define MATRIX_SRTSR(n) (0x0280 + (n) * 4) + +/* Security Peripheral Select n Register */ +#define MATRIX_SPSELR(n) (0x02c0 + (n) * 4) + +/**************************************************************************/ +/* Write Protect Mode Register (MATRIX_WPMR) */ +#define MATRIX_WPMR_WPEN (1 << 0) /* Write Protect Enable */ +#define MATRIX_WPMR_WPEN_DISABLE (0 << 0) +#define MATRIX_WPMR_WPEN_ENABLE (1 << 0) +#define MATRIX_WPMR_WPKEY (PASSWD << 8) /* Write Protect KEY */ +#define MATRIX_WPMR_WPKEY_PASSWD (0x4D4154 << 8) + +/* Security Slave Registers (MATRIX_SSRx) */ +#define MATRIX_LANSECH(n, bit) ((bit) << n) +#define MATRIX_LANSECH_S(n) (0x00 << n) +#define MATRIX_LANSECH_NS(n) (0x01 << n) +#define MATRIX_RDNSECH(n, bit) ((bit) << (n + 8)) +#define MATRIX_RDNSECH_S(n) (0x00 << (n + 8)) +#define MATRIX_RDNSECH_NS(n) (0x01 << (n + 8)) +#define MATRIX_WRNSECH(n, bit) ((bit) << (n + 16)) +#define MATRIX_WRNSECH_S(n) (0x00 << (n + 16)) +#define MATRIX_WRNSECH_NS(n) (0x01 << (n + 16)) + +/* Security Areas Split Slave Registers (MATRIX_SASSRx) */ +#define MATRIX_SASPLIT(n, value) ((value) << (4 * n)) +#define MATRIX_SASPLIT_VALUE_4K 0x00 +#define MATRIX_SASPLIT_VALUE_8K 0x01 +#define MATRIX_SASPLIT_VALUE_16K 0x02 +#define MATRIX_SASPLIT_VALUE_32K 0x03 +#define MATRIX_SASPLIT_VALUE_64K 0x04 +#define MATRIX_SASPLIT_VALUE_128K 0x05 +#define MATRIX_SASPLIT_VALUE_256K 0x06 +#define MATRIX_SASPLIT_VALUE_512K 0x07 +#define MATRIX_SASPLIT_VALUE_1M 0x08 +#define MATRIX_SASPLIT_VALUE_2M 0x09 +#define MATRIX_SASPLIT_VALUE_4M 0x0a +#define MATRIX_SASPLIT_VALUE_8M 0x0b +#define MATRIX_SASPLIT_VALUE_16M 0x0c +#define MATRIX_SASPLIT_VALUE_32M 0x0d +#define MATRIX_SASPLIT_VALUE_64M 0x0e +#define MATRIX_SASPLIT_VALUE_128M 0x0f + +/* Security Region Top Slave Registers (MATRIX_SRTSRx) */ +#define MATRIX_SRTOP(n, value) ((value) << (4 * n)) +#define MATRIX_SRTOP_VALUE_4K 0x00 +#define MATRIX_SRTOP_VALUE_8K 0x01 +#define MATRIX_SRTOP_VALUE_16K 0x02 +#define MATRIX_SRTOP_VALUE_32K 0x03 +#define MATRIX_SRTOP_VALUE_64K 0x04 +#define MATRIX_SRTOP_VALUE_128K 0x05 +#define MATRIX_SRTOP_VALUE_256K 0x06 +#define MATRIX_SRTOP_VALUE_512K 0x07 +#define MATRIX_SRTOP_VALUE_1M 0x08 +#define MATRIX_SRTOP_VALUE_2M 0x09 +#define MATRIX_SRTOP_VALUE_4M 0x0a +#define MATRIX_SRTOP_VALUE_8M 0x0b +#define MATRIX_SRTOP_VALUE_16M 0x0c +#define MATRIX_SRTOP_VALUE_32M 0x0d +#define MATRIX_SRTOP_VALUE_64M 0x0e +#define MATRIX_SRTOP_VALUE_128M 0x0f + +#endif /* #ifndef TZ_MATRIX_H */ diff --git a/optee/optee_os/core/arch/arm/plat-sprd/conf.mk b/optee/optee_os/core/arch/arm/plat-sprd/conf.mk new file mode 100644 index 0000000..8faae60 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sprd/conf.mk @@ -0,0 +1,12 @@ +PLATFORM_FLAVOR ?= sc9860 + +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_TEE_CORE_NB_CORE,8) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_GIC,y) +$(call force,CFG_SPRD_UART,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) + +# Overrides default in mk/config.mk with 128 kB +CFG_CORE_HEAP_SIZE ?= 131072 diff --git a/optee/optee_os/core/arch/arm/plat-sprd/console.c b/optee/optee_os/core/arch/arm/plat-sprd/console.c new file mode 100644 index 0000000..15a4b3b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sprd/console.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Spreadtrum Communications 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +static struct sprd_uart_data console_data; + +void console_init(void) +{ + sprd_uart_init(&console_data, CONSOLE_UART_BASE); + register_serial_console(&console_data.chip); +} + +void console_putc(int ch) +{ + struct serial_chip *cons = &console_data.chip; + + cons->ops->putc(cons, ch & 0xff); +} + diff --git a/optee/optee_os/core/arch/arm/plat-sprd/main.c b/optee/optee_os/core/arch/arm/plat-sprd/main.c new file mode 100644 index 0000000..1c4a324 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sprd/main.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Spreadtrum Communications 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, + ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(GIC_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +static struct gic_data gic_data; + +void main_init_gic(void) +{ + gic_init_base_addr(&gic_data, GIC_BASE + GICC_OFFSET, + GIC_BASE + GICD_OFFSET); + + itr_init(&gic_data.chip); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} diff --git a/optee/optee_os/core/arch/arm/plat-sprd/platform_config.h b/optee/optee_os/core/arch/arm/plat-sprd/platform_config.h new file mode 100644 index 0000000..f6af23d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sprd/platform_config.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Spreadtrum Communications 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#ifdef ARM64 +#ifdef CFG_WITH_PAGER +#error "Pager not supported for ARM64" +#endif +#endif /*ARM64*/ + +#if defined(PLATFORM_FLAVOR_sc9860) + +#define GIC_BASE 0x12000000 +#define UART0_BASE 0x70000000 +#define UART1_BASE 0x70100000 +#define UART2_BASE 0x70200000 +#define UART3_BASE 0x70300000 + +#define CONSOLE_UART_BASE UART1_BASE + +#define DRAM0_BASE 0x80000000 +#define DRAM0_SIZE 0x20000000 + +#define TZDRAM_BASE 0x8f600000 +#define TZDRAM_SIZE (0x02000000 - TEE_SHMEM_SIZE) + +#define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) +#define TEE_SHMEM_SIZE 0x200000 + +#define GICC_OFFSET 0x2000 +#define GICD_OFFSET 0x1000 + +#else +#error "Unknown platform flavor" +#endif + +#define TEE_RAM_VA_SIZE (1024 * 1024) + +#ifdef CFG_TEE_LOAD_ADDR +#define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR +#else +#define TEE_LOAD_ADDR TEE_RAM_START +#endif +/* + * +------------------+ + * | | TEE_RAM | + * + TZDRAM +---------+ + * | | TA_RAM | + * +--------+---------+ + */ +#define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE +#define TEE_RAM_START TZDRAM_BASE +#define TA_RAM_START ROUNDUP((TZDRAM_BASE + TEE_RAM_VA_SIZE), \ + CORE_MMU_PGDIR_SIZE) +#define TA_RAM_SIZE ROUNDDOWN((TZDRAM_SIZE - TEE_RAM_VA_SIZE), \ + CORE_MMU_PGDIR_SIZE) + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-sprd/sub.mk b/optee/optee_os/core/arch/arm/plat-sprd/sub.mk new file mode 100644 index 0000000..3a8214b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sprd/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-y += console.c diff --git a/optee/optee_os/core/arch/arm/plat-stm/conf.mk b/optee/optee_os/core/arch/arm/plat-stm/conf.mk new file mode 100644 index 0000000..4e78f36 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm/conf.mk @@ -0,0 +1,45 @@ +PLATFORM_FLAVOR ?= b2260 + +include core/arch/arm/cpu/cortex-a9.mk + +$(call force,CFG_ARM32_core,y) +$(call force,CFG_SECURE_TIME_SOURCE_REE,y) +$(call force,CFG_PL310,y) +$(call force,CFG_CACHE_API,y) +$(call force,CFG_WITH_LPAE,n) +$(call force,CFG_GIC,y) + +CFG_WITH_PAGER ?= n +CFG_BOOT_SYNC_CPU ?= y +CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y +CFG_WITH_STATS ?= y +CFG_WITH_SOFTWARE_PRNG ?= n +CFG_STIH_UART ?= y +CFG_ENABLE_SCTLR_RR ?= y + +ifeq ($(PLATFORM_FLAVOR),b2260) +$(call force,CFG_TEE_CORE_NB_CORE,2) +CFG_DDR_START ?= 0x40000000 +CFG_DDR_SIZE ?= 0x40000000 +CFG_STM_RSV_DRAM_STARTBYTES ?= 0 +CFG_CORE_TZSRAM_EMUL_START ?= 0x7fe00000 +CFG_DDR_TEETZ_RESERVED_START ?= 0x7e000000 +CFG_DDR_TEETZ_RESERVED_SIZE ?= 0x01e00000 +CFG_PL310_LOCKED ?= y +else +$(call force,CFG_TEE_CORE_NB_CORE,2) +CFG_DDR_START ?= 0x40000000 +CFG_DDR_SIZE ?= 0x80000000 +CFG_STM_RSV_DRAM_STARTBYTES ?= 0x02000000 +CFG_CORE_TZSRAM_EMUL_START ?= 0x94a00000 +CFG_DDR_TEETZ_RESERVED_START ?= 0x93a00000 +CFG_DDR_TEETZ_RESERVED_SIZE ?= 0x01000000 +CFG_PL310_LOCKED ?= n +endif + +CFG_SHMEM_SIZE ?= 0x00200000 +CFG_TZDRAM_START ?= ($(CFG_DDR_TEETZ_RESERVED_START)) +CFG_TZDRAM_SIZE ?= ($(CFG_DDR_TEETZ_RESERVED_SIZE) - $(CFG_SHMEM_SIZE)) +CFG_TZSRAM_START ?= ($(CFG_CORE_TZSRAM_EMUL_START)) +CFG_TZSRAM_SIZE ?= ($(CFG_CORE_TZSRAM_EMUL_SIZE)) +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) diff --git a/optee/optee_os/core/arch/arm/plat-stm/main.c b/optee/optee_os/core/arch/arm/plat-stm/main.c new file mode 100644 index 0000000..9ac667e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm/main.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2016, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CPU_IOMEM_BASE, CPU_IOMEM_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, UART_CONSOLE_BASE, STIH_ASC_REG_SIZE); + +#ifdef DRAM0_BASE +register_ddr(DRAM0_BASE, DRAM0_SIZE); +#endif +#ifdef DRAM1_BASE +register_ddr(DRAM1_BASE, DRAM1_SIZE); +#endif + +static struct gic_data gic_data; +static struct stih_asc_pd console_data; + +#if defined(PLATFORM_FLAVOR_b2260) +static bool ns_resources_ready(void) +{ + return true; +} +#else +/* some nonsecure resource might not be ready (uart) */ +static int boot_is_completed; +static bool ns_resources_ready(void) +{ + return !!boot_is_completed; +} + +/* Overriding the default __weak tee_entry_std() */ +TEE_Result tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) +{ + boot_is_completed = 1; + + return __tee_entry_std(arg, num_params); +} +#endif + +void console_init(void) +{ + stih_asc_init(&console_data, UART_CONSOLE_BASE); +} + +void console_putc(int ch) +{ + + if (ns_resources_ready()) { + struct serial_chip *cons = &console_data.chip; + + if (ch == '\n') + cons->ops->putc(cons, '\r'); + cons->ops->putc(cons, ch); + } +} + +void console_flush(void) +{ + if (ns_resources_ready()) { + struct serial_chip *cons = &console_data.chip; + + if (cons->ops->flush) + cons->ops->flush(cons); + } +} + +vaddr_t pl310_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC, 1); + return (vaddr_t)va; + } + return PL310_BASE; +} + +void arm_cl2_config(vaddr_t pl310) +{ + /* pl310 off */ + io_write32(pl310 + PL310_CTRL, 0); + + /* config PL310 */ + io_write32(pl310 + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT); + io_write32(pl310 + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT); + io_write32(pl310 + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); + io_write32(pl310 + PL310_PREFETCH_CTRL, PL310_PREFETCH_CTRL_INIT); + io_write32(pl310 + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); + + /* invalidate all pl310 cache ways */ + arm_cl2_invbyway(pl310); +} + +void plat_primary_init_early(void) +{ + int i; + + assert(!cpu_mmu_enabled()); + + io_write32(SCU_BASE + SCU_SAC, SCU_SAC_INIT); + io_write32(SCU_BASE + SCU_NSAC, SCU_NSAC_INIT); + io_write32(SCU_BASE + SCU_FILT_EA, CPU_PORT_FILT_END); + io_write32(SCU_BASE + SCU_FILT_SA, CPU_PORT_FILT_START); + io_write32(SCU_BASE + SCU_CTRL, SCU_CTRL_INIT); + + io_write32(pl310_base() + PL310_ADDR_FILT_END, CPU_PORT_FILT_END); + io_write32(pl310_base() + PL310_ADDR_FILT_START, + CPU_PORT_FILT_START | PL310_CTRL_ENABLE_BIT); + + /* TODO: gic_init scan fails, pre-init all SPIs are nonsecure */ + for (i = 0; i < (31 * 4); i += 4) + io_write32(GIC_DIST_BASE + GIC_DIST_ISR1 + i, 0xFFFFFFFF); +} + +void main_init_gic(void) +{ + gic_init(&gic_data, GIC_CPU_BASE, GIC_DIST_BASE); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} diff --git a/optee/optee_os/core/arch/arm/plat-stm/platform_config.h b/optee/optee_os/core/arch/arm/plat-stm/platform_config.h new file mode 100644 index 0000000..0cf4ddc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm/platform_config.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2016, Linaro Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include +#include + +/* Below are platform/SoC settings specific to stm platform flavors */ + +#if defined(PLATFORM_FLAVOR_b2260) + +#define CPU_IOMEM_BASE 0x08760000 +#define CPU_IOMEM_SIZE 0x000a0000 +#define CPU_PORT_FILT_START 0x40000000 +#define CPU_PORT_FILT_END 0xC0000000 +#define STXHXXX_LPM_PERIPH_BASE 0x09700000 +#define RNG_BASE 0x08A89000 +#define RNG_SIZE 0x00001000 + +#define ASC_NUM 21 +#define UART_CONSOLE_BASE ST_ASC21_REGS_BASE + +#elif defined(PLATFORM_FLAVOR_cannes) + +#define CPU_IOMEM_BASE 0x08760000 +#define CPU_IOMEM_SIZE 0x000a0000 +#define CPU_PORT_FILT_START 0x40000000 +#define CPU_PORT_FILT_END 0xC0000000 +#define STXHXXX_LPM_PERIPH_BASE 0x09400000 +#define RNG_BASE 0x08A89000 +#define RNG_SIZE 0x00001000 + +#define ASC_NUM 20 +#define UART_CONSOLE_BASE ST_ASC20_REGS_BASE + +#else /* defined(PLATFORM_FLAVOR_xxx) */ + +#error "Unknown platform flavor" + +#endif /* defined(PLATFORM_FLAVOR_xxx) */ + +#define PL310_BASE (CPU_IOMEM_BASE + 0x2000) +#define GIC_DIST_BASE (CPU_IOMEM_BASE + 0x1000) +#define SCU_BASE (CPU_IOMEM_BASE + 0x0000) +#define GIC_CPU_BASE (CPU_IOMEM_BASE + 0x0100) +#define ST_ASC20_REGS_BASE (STXHXXX_LPM_PERIPH_BASE + 0x00130000) +#define ST_ASC21_REGS_BASE (STXHXXX_LPM_PERIPH_BASE + 0x00131000) + +/* Below are settings common to stm platform flavors */ + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 32 + +/* + * CP15 Secure ConTroL Register (SCTLR + * + * - Round-Robin replac. for icache, btac, i/duTLB (bit14: RoundRobin) + */ +#define CPU_SCTLR_INIT 0x00004000 + +/* + * CP15 Auxiliary ConTroL Register (ACTRL) + * + * - core always in full SMP (FW bit0=1, SMP bit6=1) + * - L2 write full line of zero disabled (bit3=0) + * (keep WFLZ low. Will be set once outer L2 is ready) + */ +#define CPU_ACTLR_INIT 0x00000041 + +/* + * CP15 NonSecure Access Control Register (NSACR) + * + * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) + * - Nsec can lockdown TLB (TL bit17=1) + * - NSec cannot access PLE (PLE bit16=0) + * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) + */ +#define CPU_NSACR_INIT 0x00020C00 + +/* + * CP15 Power Control Register (PCR) + * + * - no change latency, enable clk gating + */ +#define CPU_PCR_INIT 0x00000001 + + +/* + * SCU Secure Access Control / NonSecure Access Control + * + * SAC: Both secure CPU access SCU (bit[3:0]). + * NSAC: Both nonsec cpu access SCU (bit[3:0]), private timers (bit[7:4]) + * and global timers (bit[11:8]). + */ +#if !defined(SCU_SAC_INIT) || !defined(SCU_NSAC_INIT) +#define SCU_CPUS_MASK (SHIFT_U32(1, CFG_TEE_CORE_NB_CORE) - 1) + +#define SCU_SAC_INIT SCU_CPUS_MASK +#define SCU_NSAC_INIT (SHIFT_U32(SCU_CPUS_MASK, SCU_NSAC_SCU_SHIFT) | \ + SHIFT_U32(SCU_CPUS_MASK, SCU_NSAC_PTIMER_SHIFT) | \ + SHIFT_U32(SCU_CPUS_MASK, SCU_NSAC_GTIMER_SHIFT)) +#endif + +/* + * PL310 TAG RAM Control Register + * + * 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 + */ +#ifndef PL310_TAG_RAM_CTRL_INIT +#define PL310_TAG_RAM_CTRL_INIT 0x00000111 +#endif + +/* + * PL310 DATA RAM Control Register + * + * 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 + */ +#ifndef PL310_DATA_RAM_CTRL_INIT +#define PL310_DATA_RAM_CTRL_INIT 0x00000222 +#endif + +/* + * PL310 Auxiliary Control Register + * + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockown cache lines (bit26=1) + * Pseudo-random replacement policy (bit25=0) + * Force write allocated (default) + * Shared attribute internally ignored (bit22=1, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * Platform fmavor specific way config: + * - way size (bit19:17) + * - way associciativity (bit16) + * Store buffer device limitation enabled (bit11=1) + * Cacheable accesses have high prio (bit10=0) + * Full Line Zero (FLZ) disabled (bit0=0) + */ +#ifndef PL310_AUX_CTRL_INIT +#define PL310_AUX_CTRL_INIT 0x3C480800 +#endif + +/* + * PL310 Prefetch Control Register + * + * Double linefill disabled (bit30=0) + * I/D prefetch enabled (bit29:28=2b11) + * Prefetch drop enabled (bit24=1) + * Incr double linefill disable (bit23=0) + * Prefetch offset = 7 (bit4:0) + */ +#define PL310_PREFETCH_CTRL_INIT 0x31000007 + +/* + * PL310 Power Register + * + * Dynamic clock gating enabled + * Standby mode enabled + */ +#define PL310_POWER_CTRL_INIT 0x00000003 + +/* + * SCU Control Register : CTRL = 0x00000065 + * - ic stanby enable=1 + * - scu standby enable=1 + * - scu enable=1 + */ +#define SCU_CTRL_INIT 0x00000065 + +/* + * Register non-secure DDR chunks for dynamic shared memory: these are + * DDR ranges that do not include OP-TEE secure memory. + * Some Stm platforms may reserve beginning of the DDR for non REE memory. + */ + +#ifdef CFG_DDR_START +/* Carvout out secure RAM range (emulated SRAM is expected near DRAM) */ +#if defined(CFG_WITH_PAGER) && defined(TZSRAM_BASE) +#if TZSRAM_BASE >= CFG_DDR_START +#define STM_SECDDR_BASE MIN_UNSAFE(TZSRAM_BASE, TZDRAM_BASE) +#define STM_SECDDR_END MAX_UNSAFE(TZSRAM_BASE + TZSRAM_SIZE, \ + TZDRAM_BASE + TZDRAM_SIZE) +#endif /*TZSRAM_BASE >= CFG_DDR_START*/ +#endif /*CFG_WITH_PAGER && TZSRAM_BASE*/ + +#ifndef STM_SECDDR_BASE +#define STM_SECDDR_BASE TZDRAM_BASE +#define STM_SECDDR_END (TZDRAM_BASE + TZDRAM_SIZE) +#endif + +#define STM_SECDDR_SIZE (STM_SECDDR_END - STM_SECDDR_BASE) +/* Register the DDR chunks that do not intersect the secure DDR single area */ +#define DRAM0_BASE (CFG_DDR_START + CFG_STM_RSV_DRAM_STARTBYTES) +#define DRAM0_SIZE (STM_SECDDR_BASE - DRAM0_BASE) +#if (STM_SECDDR_END < 0x80000000ULL) +#define DRAM1_BASE STM_SECDDR_END +#define DRAM1_SIZE ((CFG_DDR_START - DRAM1_BASE) + CFG_DDR_SIZE) +#endif +#endif /*CFG_DDR_START*/ + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-stm/rng_support.c b/optee/optee_os/core/arch/arm/plat-stm/rng_support.c new file mode 100644 index 0000000..2a81b7b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm/rng_support.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2016, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include + +#include "rng_support.h" + +/* Address of the register to read in the RNG IP */ +#define RNG_VAL_OFFSET 0x24 +#define RNG_STATUS_OFFSET 0x20 + +#define RNG_STATUS_ERR0 BIT32(0) +#define RNG_STATUS_ERR1 BIT32(1) +#define RNG_STATUS_FULL BIT32(5) + +static vaddr_t rng_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_SIZE); + return (vaddr_t)va; + } + return RNG_BASE; +} + +static inline int hwrng_waithost_fifo_full(void) +{ + uint32_t status; + + do { + status = io_read32(rng_base() + RNG_STATUS_OFFSET); + } while (!(status & RNG_STATUS_FULL)); + + if (status & (RNG_STATUS_ERR0 | RNG_STATUS_ERR1)) + return 1; + + return 0; +} + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + /* + * 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; + + static int nbcall; /* debug purpose - 0 is the initial value*/ + + volatile uint32_t tmpval[_LOCAL_FIFO_SIZE/2]; + int i; + + uint8_t *buffer = buf; + size_t buffer_pos = 0; + + nbcall++; + + while (buffer_pos < len) { + /* Refill our FIFO */ + if (pos == 0) { + if (hwrng_waithost_fifo_full()) + return TEE_ERROR_GENERIC; + + /* + * Read the FIFO according to the number of + * expected elements + */ + for (i = 0; i < _LOCAL_FIFO_SIZE / 2; i++) + tmpval[i] = io_read32(rng_base() + + RNG_VAL_OFFSET) & 0xFFFF; + + /* 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; + } + + buffer[buffer_pos++] = lfifo[pos++]; + if (pos == _LOCAL_FIFO_SIZE) + pos = 0; + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/arch/arm/plat-stm/sub.mk b/optee/optee_os/core/arch/arm/plat-stm/sub.mk new file mode 100644 index 0000000..4793bfb --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm/sub.mk @@ -0,0 +1,5 @@ +global-incdirs-y += . + +srcs-y += rng_support.c +srcs-y += tz_a9init.S +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-stm/tz_a9init.S b/optee/optee_os/core/arch/arm/plat-stm/tz_a9init.S new file mode 100644 index 0000000..f6b68ba --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm/tz_a9init.S @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2016, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include + +.section .text +.balign 4 +.code 32 + +/* + * void arm_cl2_enable(vaddr_t pl310_base) - Memory Cache Level2 Enable Function + * + * If PL310 supports FZLW, enable also FZL in A9 core + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + * TODO: to be moved to PL310 code (tz_svce_pl310.S ?) + */ +FUNC arm_cl2_enable , : + /* Enable PL310 ctrl -> only set lsb bit */ + mov r1, #0x1 + str r1, [r0, #PL310_CTRL] + + /* if L2 FLZW enable, enable in L1 */ + ldr r1, [r0, #PL310_AUX_CTRL] + tst r1, #(1 << 0) /* test AUX_CTRL[FLZ] */ + read_actlr r0 + orrne r0, r0, #(1 << 3) /* enable ACTLR[FLZW] */ + write_actlr r0 + + mov pc, lr +END_FUNC 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 plat_cpu_reset_early , : + /* CPSR.A can be modified in any security state. */ + mov_imm r0, SCR_AW + write_scr r0 + + mov_imm r0, CPU_SCTLR_INIT + write_sctlr r0 + + mov_imm r0, CPU_ACTLR_INIT + write_actlr r0 + + mov_imm r0, CPU_NSACR_INIT + write_nsacr r0 + + mov_imm r0, CPU_PCR_INIT + write_pcr r0 + + mov pc, lr +END_FUNC plat_cpu_reset_early + diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/boot_api.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/boot_api.h new file mode 100644 index 0000000..62e38b5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/boot_api.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (C) 2017-2018, STMicroelectronics + */ + +#ifndef __BOOT_API_H__ +#define __BOOT_API_H__ + +/* + * Backup registers mapping + */ + +/* Backup register #4: magic to request core1 boot up */ +#define BCKR_CORE1_MAGIC_NUMBER 4 + +/* Value for BCKR_CORE1_MAGIC_NUMBER entry */ +#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xca7face1 + +/* Backup register #5: physical address of core1 entry at boot up */ +#define BCKR_CORE1_BRANCH_ADDRESS 5 + +#endif /* __BOOT_API_H__*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/conf.mk b/optee/optee_os/core/arch/arm/plat-stm32mp1/conf.mk new file mode 100644 index 0000000..a7134e1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/conf.mk @@ -0,0 +1,351 @@ +# 1GB and 512MB DDR targets do not locate secure DDR at the same place. +flavor_dts_file-157A_DHCOR_AVENGER96 = stm32mp157a-dhcor-avenger96.dts +flavor_dts_file-157A_DK1 = stm32mp157a-dk1.dts +flavor_dts_file-157C_DHCOM_PDK2 = stm32mp157c-dhcom-pdk2.dts +flavor_dts_file-157C_DK2 = stm32mp157c-dk2.dts +flavor_dts_file-157C_ED1 = stm32mp157c-ed1.dts +flavor_dts_file-157C_EV1 = stm32mp157c-ev1.dts + +flavor_dts_file-135F_DK = stm32mp135f-dk.dts + +flavorlist-cryp-512M = $(flavor_dts_file-157C_DK2) \ + $(flavor_dts_file-135F_DK) + +flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1) + +flavorlist-cryp-1G = $(flavor_dts_file-157C_DHCOM_PDK2) \ + $(flavor_dts_file-157C_ED1) \ + $(flavor_dts_file-157C_EV1) + +flavorlist-no_cryp-1G = $(flavor_dts_file-157A_DHCOR_AVENGER96) + +flavorlist-no_cryp = $(flavorlist-no_cryp-512M) \ + $(flavorlist-no_cryp-1G) + +flavorlist-512M = $(flavorlist-cryp-512M) \ + $(flavorlist-no_cryp-512M) + +flavorlist-1G = $(flavorlist-cryp-1G) \ + $(flavorlist-no_cryp-1G) + +flavorlist-MP15-HUK-DT = $(flavor_dts_file-157A_DK1) \ + $(flavor_dts_file-157C_DK2) \ + $(flavor_dts_file-157C_ED1) \ + $(flavor_dts_file-157C_EV1) + +flavorlist-MP15 = $(flavor_dts_file-157A_DHCOR_AVENGER96) \ + $(flavor_dts_file-157A_DK1) \ + $(flavor_dts_file-157C_DHCOM_PDK2) \ + $(flavor_dts_file-157C_DK2) \ + $(flavor_dts_file-157C_ED1) \ + $(flavor_dts_file-157C_EV1) + +flavorlist-MP13 = $(flavor_dts_file-135F_DK) + +ifneq ($(PLATFORM_FLAVOR),) +ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),) +$(error Invalid platform flavor $(PLATFORM_FLAVOR)) +endif +CFG_EMBED_DTB_SOURCE_FILE ?= $(flavor_dts_file-$(PLATFORM_FLAVOR)) +endif +CFG_EMBED_DTB_SOURCE_FILE ?= stm32mp157c-dk2.dts + +ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-no_cryp)),) +$(call force,CFG_STM32_CRYP,n) +endif + +ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-no_rng)),) +$(call force,CFG_HWRNG_PTA,n) +$(call force,CFG_WITH_SOFTWARE_PRNG,y) +endif + +ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP15-HUK-DT)),) +CFG_STM32MP15_HUK ?= y +CFG_STM32_HUK_FROM_DT ?= y +endif + +ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP13)),) +$(call force,CFG_STM32MP13,y) +endif + +ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP15)),) +$(call force,CFG_STM32MP15,y) +endif + +# CFG_STM32MP1x switches are exclusive. +# - CFG_STM32MP15 is enabled for STM32MP15x-* targets (default) +# - CFG_STM32MP13 is enabled for STM32MP13x-* targets +ifeq ($(CFG_STM32MP13),y) +$(call force,CFG_STM32MP15,n) +else +$(call force,CFG_STM32MP15,y) +$(call force,CFG_STM32MP13,n) +endif +ifeq ($(call cfg-one-enabled,CFG_STM32MP15 CFG_STM32MP13),n) +$(error One of CFG_STM32MP15 CFG_STM32MP13 must be enabled) +endif +ifeq ($(call cfg-all-enabled,CFG_STM32MP15 CFG_STM32MP13),y) +$(error Only one of CFG_STM32MP15 CFG_STM32MP13 must be enabled) +endif + +include core/arch/arm/cpu/cortex-a7.mk + +$(call force,CFG_DRIVERS_CLK,y) +$(call force,CFG_DRIVERS_CLK_DT,y) +$(call force,CFG_GIC,y) +$(call force,CFG_INIT_CNTVOFF,y) +$(call force,CFG_PSCI_ARM32,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_SM_PLATFORM_HANDLER,y) +$(call force,CFG_STM32_SHARED_IO,y) + +ifeq ($(CFG_STM32MP13),y) +$(call force,CFG_BOOT_SECONDARY_REQUEST,n) +$(call force,CFG_CORE_RESERVED_SHM,n) +$(call force,CFG_DRIVERS_CLK_FIXED,y) +$(call force,CFG_SECONDARY_INIT_CNTFRQ,n) +$(call force,CFG_STM32_GPIO,y) +$(call force,CFG_STM32MP_CLK_CORE,y) +$(call force,CFG_STM32MP1_SHARED_RESOURCES,n) +$(call force,CFG_STM32MP13_CLK,y) +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_WITH_NSEC_GPIOS,n) +CFG_EXTERNAL_DT ?= n +CFG_STM32MP_OPP_COUNT ?= 2 +CFG_WITH_PAGER ?= n +endif # CFG_STM32MP13 + +ifeq ($(CFG_STM32MP15),y) +$(call force,CFG_BOOT_SECONDARY_REQUEST,y) +$(call force,CFG_DRIVERS_CLK_FIXED,n) +$(call force,CFG_SECONDARY_INIT_CNTFRQ,y) +$(call force,CFG_STM32MP1_SHARED_RESOURCES,y) +$(call force,CFG_STM32MP15_CLK,y) +CFG_CORE_RESERVED_SHM ?= y +CFG_EXTERNAL_DT ?= y +CFG_STM32_BSEC_SIP ?= y +CFG_TEE_CORE_NB_CORE ?= 2 +CFG_WITH_PAGER ?= y +CFG_WITH_SOFTWARE_PRNG ?= y +endif # CFG_STM32MP15 + +ifeq ($(CFG_WITH_PAGER),y) +CFG_WITH_LPAE ?= n +endif +CFG_WITH_LPAE ?= y +CFG_MMAP_REGIONS ?= 23 +CFG_DTB_MAX_SIZE ?= (256 * 1024) +CFG_CORE_ASLR ?= n + +ifneq ($(CFG_WITH_LPAE),y) +# Without LPAE, default TEE virtual address range is 1MB, we need at least 2MB. +CFG_TEE_RAM_VA_SIZE ?= 0x00200000 +endif + +ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-512M)),) +CFG_TZDRAM_START ?= 0xde000000 +CFG_DRAM_SIZE ?= 0x20000000 +endif + +CFG_DRAM_BASE ?= 0xc0000000 +CFG_DRAM_SIZE ?= 0x40000000 +CFG_STM32MP1_SCMI_SHM_BASE ?= 0x2ffff000 +CFG_STM32MP1_SCMI_SHM_SIZE ?= 0x00001000 +ifeq ($(CFG_STM32MP15),y) +CFG_TZDRAM_START ?= 0xfe000000 +ifeq ($(CFG_CORE_RESERVED_SHM),y) +CFG_TZDRAM_SIZE ?= 0x01e00000 +else +CFG_TZDRAM_SIZE ?= 0x02000000 +endif +CFG_TZSRAM_START ?= 0x2ffc0000 +CFG_TZSRAM_SIZE ?= 0x0003f000 +ifeq ($(CFG_CORE_RESERVED_SHM),y) +CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) +CFG_SHMEM_SIZE ?= ($(CFG_DRAM_BASE) + $(CFG_DRAM_SIZE) - $(CFG_SHMEM_START)) +endif +else +CFG_TZDRAM_SIZE ?= 0x02000000 +CFG_TZDRAM_START ?= ($(CFG_DRAM_BASE) + $(CFG_DRAM_SIZE) - $(CFG_TZDRAM_SIZE)) +endif #CFG_STM32MP15 + +CFG_STM32_BSEC ?= y +CFG_STM32_CRYP ?= y +CFG_STM32_ETZPC ?= y +CFG_STM32_GPIO ?= y +CFG_STM32_I2C ?= y +CFG_STM32_IWDG ?= y +CFG_STM32_RNG ?= y +CFG_STM32_RSTCTRL ?= y +CFG_STM32_TAMP ?= y +CFG_STM32_UART ?= y +CFG_STPMIC1 ?= y +CFG_TZC400 ?= y + +CFG_WITH_SOFTWARE_PRNG ?= n +ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) +$(call force,CFG_STM32_RNG,y,Required by HW RNG when CFG_WITH_SOFTWARE_PRNG=n) +endif + +ifeq ($(CFG_STPMIC1),y) +$(call force,CFG_STM32_I2C,y) +$(call force,CFG_STM32_GPIO,y) +endif + +# if any crypto driver is enabled, enable the crypto-framework layer +ifeq ($(call cfg-one-enabled, CFG_STM32_CRYP),y) +$(call force,CFG_STM32_CRYPTO_DRIVER,y) +endif + +CFG_DRIVERS_RSTCTRL ?= $(CFG_STM32_RSTCTRL) +$(eval $(call cfg-depends-all,CFG_STM32_RSTCTRL,CFG_DRIVERS_RSTCTRL)) + +CFG_WDT ?= $(CFG_STM32_IWDG) + +# Platform specific configuration +CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION ?= y + +# Default enable scmi-msg server if SCP-firmware SCMI server is disabled +ifneq ($(CFG_SCMI_SCPFW),y) +CFG_SCMI_MSG_DRIVERS ?= y +endif + +# SiP/OEM service for non-secure world +CFG_STM32_BSEC_SIP ?= n +CFG_STM32MP1_SCMI_SIP ?= n +ifeq ($(CFG_STM32MP1_SCMI_SIP),y) +$(call force,CFG_SCMI_MSG_DRIVERS,y,Mandated by CFG_STM32MP1_SCMI_SIP) +$(call force,CFG_SCMI_MSG_SMT,y,Mandated by CFG_STM32MP1_SCMI_SIP) +$(call force,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,y,Mandated by CFG_STM32MP1_SCMI_SIP) +endif + +# Enable BSEC PTA for fuses access management +CFG_STM32_BSEC_PTA ?= y +ifeq ($(CFG_STM32_BSEC_PTA),y) +$(call force,CFG_STM32_BSEC,y,Mandated by CFG_BSEC_PTA) +endif + +# Default enable SCMI PTA support +CFG_SCMI_PTA ?= y +ifeq ($(CFG_SCMI_PTA),y) +ifneq ($(CFG_SCMI_SCPFW),y) +$(call force,CFG_SCMI_MSG_DRIVERS,y,Mandated by CFG_SCMI_PTA) +$(call force,CFG_SCMI_MSG_SMT_THREAD_ENTRY,y,Mandated by CFG_SCMI_PTA) +CFG_SCMI_MSG_SHM_MSG ?= y +CFG_SCMI_MSG_SMT ?= y +endif # !CFG_SCMI_SCPFW +endif # CFG_SCMI_PTA + +CFG_SCMI_SCPFW ?= n +ifeq ($(CFG_SCMI_SCPFW),y) +$(call force,CFG_SCMI_SCPFW_PRODUCT,optee-stm32mp1) +endif + +CFG_SCMI_MSG_DRIVERS ?= n +ifeq ($(CFG_SCMI_MSG_DRIVERS),y) +$(call force,CFG_SCMI_MSG_CLOCK,y) +$(call force,CFG_SCMI_MSG_RESET_DOMAIN,y) +CFG_SCMI_MSG_SHM_MSG ?= y +CFG_SCMI_MSG_SMT ?= y +CFG_SCMI_MSG_SMT_THREAD_ENTRY ?= y +$(call force,CFG_SCMI_MSG_VOLTAGE_DOMAIN,y) +endif + +ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) +CFG_HWRNG_PTA ?= y +endif +ifeq ($(CFG_HWRNG_PTA),y) +$(call force,CFG_STM32_RNG,y,Mandated by CFG_HWRNG_PTA) +$(call force,CFG_WITH_SOFTWARE_PRNG,n,Mandated by CFG_HWRNG_PTA) +$(call force,CFG_HWRNG_QUALITY,1024) +endif + +# Provision enough threads to pass xtest +ifneq (,$(filter y,$(CFG_SCMI_PTA) $(CFG_STM32MP1_SCMI_SIP))) +ifeq ($(CFG_WITH_PAGER),y) +CFG_NUM_THREADS ?= 3 +else +CFG_NUM_THREADS ?= 10 +endif +endif + +# Default enable some test facitilites +CFG_ENABLE_EMBEDDED_TESTS ?= y +CFG_WITH_STATS ?= y + +# Enable OTP update with BSEC driver +CFG_STM32_BSEC_WRITE ?= y + +# Default disable some support for pager memory size constraint +ifeq ($(CFG_WITH_PAGER),y) +CFG_TEE_CORE_DEBUG ?= n +CFG_UNWIND ?= n +CFG_LOCKDEP ?= n +CFG_TA_BGET_TEST ?= n +# Default disable early TA compression to support a smaller HEAP size +CFG_EARLY_TA_COMPRESS ?= n +CFG_CORE_HEAP_SIZE ?= 49152 +endif + +# Non-secure UART and GPIO/pinctrl for the output console +CFG_WITH_NSEC_GPIOS ?= y +CFG_WITH_NSEC_UARTS ?= y +# UART instance used for early console (0 disables early console) +CFG_STM32_EARLY_CONSOLE_UART ?= 4 + +# CFG_STM32MP15_HUK enables use of a HUK read from BSEC fuses. +# Disable the HUK by default as it requires a product specific configuration. +# +# Configuration must provide OTP indices where HUK is loaded. +# When CFG_STM32_HUK_FROM_DT is enabled, HUK OTP location is found in the DT. +# When CFG_STM32_HUK_FROM_DT is disabled, configuration sets each HUK location. +# Either with CFG_STM32MP15_HUK_OTP_BASE, in which case the 4 words are used, +# Or with CFG_STM32MP15_HUK_BSEC_KEY_0/1/2/3 each locating one BSEC word. +# +# Configuration must provide the HUK generation scheme. The following switches +# are exclusive and at least one must be eable when CFG_STM32MP15_HUK is enable. +# CFG_STM32MP15_HUK_BSEC_KEY makes platform HUK to be the raw fuses content. +# CFG_STM32MP15_HUK_BSEC_DERIVE_UID makes platform HUK to be the HUK fuses +# content derived with the device UID fuses content. See derivation scheme +# in stm32mp15_huk.c implementation. +CFG_STM32MP15_HUK ?= n +CFG_STM32_HUK_FROM_DT ?= n + +ifeq ($(CFG_STM32MP15_HUK),y) +ifneq ($(CFG_STM32_HUK_FROM_DT),y) +ifneq (,$(CFG_STM32MP15_HUK_OTP_BASE)) +$(call force,CFG_STM32MP15_HUK_BSEC_KEY_0,CFG_STM32MP15_HUK_OTP_BASE) +$(call force,CFG_STM32MP15_HUK_BSEC_KEY_1,(CFG_STM32MP15_HUK_OTP_BASE + 1)) +$(call force,CFG_STM32MP15_HUK_BSEC_KEY_2,(CFG_STM32MP15_HUK_OTP_BASE + 2)) +$(call force,CFG_STM32MP15_HUK_BSEC_KEY_3,(CFG_STM32MP15_HUK_OTP_BASE + 3)) +endif +ifeq (,$(CFG_STM32MP15_HUK_BSEC_KEY_0)) +$(error Missing configuration switch CFG_STM32MP15_HUK_BSEC_KEY_0) +endif +ifeq (,$(CFG_STM32MP15_HUK_BSEC_KEY_1)) +$(error Missing configuration switch CFG_STM32MP15_HUK_BSEC_KEY_1) +endif +ifeq (,$(CFG_STM32MP15_HUK_BSEC_KEY_2)) +$(error Missing configuration switch CFG_STM32MP15_HUK_BSEC_KEY_2) +endif +ifeq (,$(CFG_STM32MP15_HUK_BSEC_KEY_3)) +$(error Missing configuration switch CFG_STM32MP15_HUK_BSEC_KEY_3) +endif +endif # CFG_STM32_HUK_FROM_DT + +CFG_STM32MP15_HUK_BSEC_KEY ?= y +CFG_STM32MP15_HUK_BSEC_DERIVE_UID ?= n +ifneq (y,$(call cfg-one-enabled,CFG_STM32MP15_HUK_BSEC_KEY CFG_STM32MP15_HUK_BSEC_DERIVE_UID)) +$(error CFG_STM32MP15_HUK mandates one of CFG_STM32MP15_HUK_BSEC_KEY CFG_STM32MP15_HUK_BSEC_DERIVE_UID) +else ifeq ($(CFG_STM32MP15_HUK_BSEC_KEY)-$(CFG_STM32MP15_HUK_BSEC_DERIVE_UID),y-y) +$(error CFG_STM32MP15_HUK_BSEC_KEY and CFG_STM32MP15_HUK_BSEC_DERIVE_UID are exclusive) +endif +endif # CFG_STM32MP15_HUK + +CFG_TEE_CORE_DEBUG ?= y +CFG_STM32_DEBUG_ACCESS ?= $(CFG_TEE_CORE_DEBUG) + +# Sanity on choice config switches +ifeq ($(call cfg-all-enabled,CFG_STM32MP15 CFG_STM32MP13),y) +$(error CFG_STM32MP13_CLK and CFG_STM32MP15_CLK are exclusive) +endif diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h new file mode 100644 index 0000000..bc0b78f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) 2018-2019, STMicroelectronics + */ + +#ifndef __STM32MP1_ETZPC_H +#define __STM32MP1_ETZPC_H + +/* Define DECPROT IDs for stm32mp1 familly */ +#ifdef CFG_STM32MP15 +#define STM32MP1_ETZPC_STGENC_ID 0 +#define STM32MP1_ETZPC_BKPSRAM_ID 1 +#define STM32MP1_ETZPC_IWDG1_ID 2 +#define STM32MP1_ETZPC_USART1_ID 3 +#define STM32MP1_ETZPC_SPI6_ID 4 +#define STM32MP1_ETZPC_I2C4_ID 5 +#define STM32MP1_ETZPC_GPIOZ_ID 6 +#define STM32MP1_ETZPC_RNG1_ID 7 +#define STM32MP1_ETZPC_HASH1_ID 8 +#define STM32MP1_ETZPC_CRYP1_ID 9 +#define STM32MP1_ETZPC_DDRCTRL_ID 10 +#define STM32MP1_ETZPC_DDRPHYC_ID 11 +#define STM32MP1_ETZPC_I2C6_ID 12 +/* 13-15 Reserved */ +#define STM32MP1_ETZPC_TIM2_ID 16 +#define STM32MP1_ETZPC_TIM3_ID 17 +#define STM32MP1_ETZPC_TIM4_ID 18 +#define STM32MP1_ETZPC_TIM5_ID 19 +#define STM32MP1_ETZPC_TIM6_ID 20 +#define STM32MP1_ETZPC_TIM7_ID 21 +#define STM32MP1_ETZPC_TIM12_ID 22 +#define STM32MP1_ETZPC_TIM13_ID 23 +#define STM32MP1_ETZPC_TIM14_ID 24 +#define STM32MP1_ETZPC_LPTIM1_ID 25 +#define STM32MP1_ETZPC_WWDG1_ID 26 +#define STM32MP1_ETZPC_SPI2_ID 27 +#define STM32MP1_ETZPC_SPI3_ID 28 +#define STM32MP1_ETZPC_SPDIFRX_ID 29 +#define STM32MP1_ETZPC_USART2_ID 30 +#define STM32MP1_ETZPC_USART3_ID 31 +#define STM32MP1_ETZPC_UART4_ID 32 +#define STM32MP1_ETZPC_UART5_ID 33 +#define STM32MP1_ETZPC_I2C1_ID 34 +#define STM32MP1_ETZPC_I2C2_ID 35 +#define STM32MP1_ETZPC_I2C3_ID 36 +#define STM32MP1_ETZPC_I2C5_ID 37 +#define STM32MP1_ETZPC_CEC_ID 38 +#define STM32MP1_ETZPC_DAC_ID 39 +#define STM32MP1_ETZPC_UART7_ID 40 +#define STM32MP1_ETZPC_UART8_ID 41 +/* 42-43 Reserved */ +#define STM32MP1_ETZPC_MDIOS_ID 44 +/* 45-47 Reserved */ +#define STM32MP1_ETZPC_TIM1_ID 48 +#define STM32MP1_ETZPC_TIM8_ID 49 +/* 50 Reserved */ +#define STM32MP1_ETZPC_USART6_ID 51 +#define STM32MP1_ETZPC_SPI1_ID 52 +#define STM32MP1_ETZPC_SPI4_ID 53 +#define STM32MP1_ETZPC_TIM15_ID 54 +#define STM32MP1_ETZPC_TIM16_ID 55 +#define STM32MP1_ETZPC_TIM17_ID 56 +#define STM32MP1_ETZPC_SPI5_ID 57 +#define STM32MP1_ETZPC_SAI1_ID 58 +#define STM32MP1_ETZPC_SAI2_ID 59 +#define STM32MP1_ETZPC_SAI3_ID 60 +#define STM32MP1_ETZPC_DFSDM_ID 61 +#define STM32MP1_ETZPC_TT_FDCAN_ID 62 +/* 63 Reserved */ +#define STM32MP1_ETZPC_LPTIM2_ID 64 +#define STM32MP1_ETZPC_LPTIM3_ID 65 +#define STM32MP1_ETZPC_LPTIM4_ID 66 +#define STM32MP1_ETZPC_LPTIM5_ID 67 +#define STM32MP1_ETZPC_SAI4_ID 68 +#define STM32MP1_ETZPC_VREFBUF_ID 69 +#define STM32MP1_ETZPC_DCMI_ID 70 +#define STM32MP1_ETZPC_CRC2_ID 71 +#define STM32MP1_ETZPC_ADC_ID 72 +#define STM32MP1_ETZPC_HASH2_ID 73 +#define STM32MP1_ETZPC_RNG2_ID 74 +#define STM32MP1_ETZPC_CRYP2_ID 75 +/* 76-79 Reserved */ +#define STM32MP1_ETZPC_SRAM1_ID 80 +#define STM32MP1_ETZPC_SRAM2_ID 81 +#define STM32MP1_ETZPC_SRAM3_ID 82 +#define STM32MP1_ETZPC_SRAM4_ID 83 +#define STM32MP1_ETZPC_RETRAM_ID 84 +#define STM32MP1_ETZPC_OTG_ID 85 +#define STM32MP1_ETZPC_SDMMC3_ID 86 +#define STM32MP1_ETZPC_DLYBSD3_ID 87 +#define STM32MP1_ETZPC_DMA1_ID 88 +#define STM32MP1_ETZPC_DMA2_ID 89 +#define STM32MP1_ETZPC_DMAMUX_ID 90 +#define STM32MP1_ETZPC_FMC_ID 91 +#define STM32MP1_ETZPC_QSPI_ID 92 +#define STM32MP1_ETZPC_DLYBQ_ID 93 +#define STM32MP1_ETZPC_ETH_ID 94 +/* 95 Reserved */ +#define STM32MP1_ETZPC_MAX_ID 96 +#endif /* CFG_STM32MP15 */ + +#ifdef CFG_STM32MP13 +#define STM32MP1_ETZPC_VREFBUF_ID 0 +#define STM32MP1_ETZPC_LPTIM2_ID 1 +#define STM32MP1_ETZPC_LPTIM3_ID 2 +#define STM32MP1_ETZPC_LTDC_ID 3 +#define STM32MP1_ETZPC_DCMIPP_ID 4 +#define STM32MP1_ETZPC_USBPHYCTRL_ID 5 +#define STM32MP1_ETZPC_DDRCTRLPHY_ID 6 +/* 7-11 Reserved */ +#define STM32MP1_ETZPC_IWDG1_ID 12 +#define STM32MP1_ETZPC_STGENC_ID 13 +/* 14-15 Reserved */ +#define STM32MP1_ETZPC_USART1_ID 16 +#define STM32MP1_ETZPC_USART2_ID 17 +#define STM32MP1_ETZPC_SPI4_ID 18 +#define STM32MP1_ETZPC_SPI5_ID 19 +#define STM32MP1_ETZPC_I2C3_ID 20 +#define STM32MP1_ETZPC_I2C4_ID 21 +#define STM32MP1_ETZPC_I2C5_ID 22 +#define STM32MP1_ETZPC_TIM12_ID 23 +#define STM32MP1_ETZPC_TIM13_ID 24 +#define STM32MP1_ETZPC_TIM14_ID 25 +#define STM32MP1_ETZPC_TIM15_ID 26 +#define STM32MP1_ETZPC_TIM16_ID 27 +#define STM32MP1_ETZPC_TIM17_ID 28 +/* 29-31 Reserved */ +#define STM32MP1_ETZPC_ADC1_ID 32 +#define STM32MP1_ETZPC_ADC2_ID 33 +#define STM32MP1_ETZPC_OTG_ID 34 +/* 35-36 Reserved */ +#define STM32MP1_ETZPC_TSC_ID 37 +/* 38-39 Reserved */ +#define STM32MP1_ETZPC_RNG_ID 40 +#define STM32MP1_ETZPC_HASH_ID 41 +#define STM32MP1_ETZPC_CRYP_ID 42 +#define STM32MP1_ETZPC_SAES_ID 43 +#define STM32MP1_ETZPC_PKA_ID 44 +#define STM32MP1_ETZPC_BKPSRAM_ID 45 +/* 46-47 Reserved */ +#define STM32MP1_ETZPC_ETH1_ID 48 +#define STM32MP1_ETZPC_ETH2_ID 49 +#define STM32MP1_ETZPC_SDMMC1_ID 50 +#define STM32MP1_ETZPC_SDMMC2_ID 51 +/* 52 Reserved */ +#define STM32MP1_ETZPC_MCE_ID 53 +#define STM32MP1_ETZPC_FMC_ID 54 +#define STM32MP1_ETZPC_QSPI_ID 55 +/* 56-59 Reserved */ +#define STM32MP1_ETZPC_SRAM1_ID 60 +#define STM32MP1_ETZPC_SRAM2_ID 61 +#define STM32MP1_ETZPC_SRAM3_ID 62 +/* 63 Reserved */ +#define STM32MP1_ETZPC_MAX_ID 64 +#endif /* CFG_STM32MP13 */ +#endif /*__STM32MP1_ETZPC_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c new file mode 100644 index 0000000..8584f4a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c @@ -0,0 +1,643 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2021, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODE_STANDBY 8 + +#define PMIC_I2C_TRIALS 1 +#define PMIC_I2C_TIMEOUT_BUSY_MS 5 + +#define PMIC_REGU_SUPPLY_NAME_LEN 12 + +#define PMIC_REGU_COUNT 14 + +/* Expect a single PMIC instance */ +static struct i2c_handle_s i2c_handle; +static uint32_t pmic_i2c_addr; + +/* CPU voltage supplier if found */ +static char cpu_supply_name[PMIC_REGU_SUPPLY_NAME_LEN]; + +bool stm32mp_with_pmic(void) +{ + return i2c_handle.dt_status & DT_STATUS_OK_SEC; +} + +static int dt_get_pmic_node(void *fdt) +{ + static int node = -FDT_ERR_BADOFFSET; + + if (node == -FDT_ERR_BADOFFSET) + node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); + + return node; +} + +static int dt_pmic_status(void) +{ + void *fdt = get_embedded_dt(); + + if (fdt) { + int node = dt_get_pmic_node(fdt); + + if (node > 0) + return fdt_get_status(fdt, node); + } + + return -1; +} + +int stm32mp_dt_pmic_status(void) +{ + return dt_pmic_status(); +} + +static bool dt_pmic_is_secure(void) +{ + int status = dt_pmic_status(); + + return status == DT_STATUS_OK_SEC && + i2c_handle.dt_status == DT_STATUS_OK_SEC; +} + +/* + * struct regu_bo_config - Boot on configuration for a regulator + * @flags: Operations expected when entering a low power sequence + * @cfg: Boot-on configuration to apply during low power sequences + */ +struct regu_bo_config { + uint8_t flags; + struct stpmic1_bo_cfg cfg; +}; + +#define REGU_BO_FLAG_ENABLE_REGU BIT(0) +#define REGU_BO_FLAG_SET_VOLTAGE BIT(1) +#define REGU_BO_FLAG_PULL_DOWN BIT(2) +#define REGU_BO_FLAG_MASK_RESET BIT(3) + +static struct regu_bo_config *regu_bo_config; +static size_t regu_bo_count; + +/* boot-on mandatory? if so: caller panic() on error status */ +static void dt_get_regu_boot_on_config(void *fdt, const char *regu_name, + int regu_node) +{ + const fdt32_t *cuint = NULL; + struct regu_bo_config regu_cfg = { }; + uint16_t mv = 0; + + if ((!fdt_getprop(fdt, regu_node, "regulator-boot-on", NULL)) && + (!fdt_getprop(fdt, regu_node, "regulator-always-on", NULL))) + return; + + regu_cfg.flags |= REGU_BO_FLAG_ENABLE_REGU; + if (stpmic1_bo_enable_cfg(regu_name, ®u_cfg.cfg)) { + EMSG("PMIC regulator %s not supported", regu_name); + panic(); + } + + if (fdt_getprop(fdt, regu_node, "regulator-pull-down", NULL)) { + if (stpmic1_bo_pull_down_cfg(regu_name, ®u_cfg.cfg)) { + DMSG("No pull down mode for regu %s", regu_name); + panic(); + } + regu_cfg.flags |= REGU_BO_FLAG_PULL_DOWN; + } + + if (fdt_getprop(fdt, regu_node, "st,mask-reset", NULL)) { + if (stpmic1_bo_mask_reset_cfg(regu_name, ®u_cfg.cfg)) { + DMSG("No reset mode for regu %s", regu_name); + panic(); + } + regu_cfg.flags |= REGU_BO_FLAG_MASK_RESET; + } + + cuint = fdt_getprop(fdt, regu_node, + "regulator-min-microvolt", NULL); + if (cuint) { + /* DT uses microvolts and driver awaits millivolts */ + mv = fdt32_to_cpu(*cuint) / 1000; + + if (stpmic1_bo_voltage_cfg(regu_name, mv, ®u_cfg.cfg)) + DMSG("Ignore regulator-min-microvolt for %s", + regu_name); + else + regu_cfg.flags |= REGU_BO_FLAG_SET_VOLTAGE; + } + + /* Save config in the Boot On configuration list */ + regu_bo_count++; + regu_bo_config = realloc(regu_bo_config, + regu_bo_count * sizeof(regu_cfg)); + if (!regu_bo_config) + panic(); + + regu_bo_config[regu_bo_count - 1] = regu_cfg; +} + +void stm32mp_pmic_apply_boot_on_config(void) +{ + size_t i = 0; + + for (i = 0; i < regu_bo_count; i++) { + struct regu_bo_config *regu_cfg = ®u_bo_config[i]; + + if (regu_cfg->flags & REGU_BO_FLAG_SET_VOLTAGE) + if (stpmic1_bo_voltage_unpg(®u_cfg->cfg)) + panic(); + + if (regu_cfg->flags & REGU_BO_FLAG_ENABLE_REGU) + if (stpmic1_bo_enable_unpg(®u_cfg->cfg)) + panic(); + + if (regu_cfg->flags & REGU_BO_FLAG_PULL_DOWN) + if (stpmic1_bo_pull_down_unpg(®u_cfg->cfg)) + panic(); + + if (regu_cfg->flags & REGU_BO_FLAG_MASK_RESET) + if (stpmic1_bo_mask_reset_unpg(®u_cfg->cfg)) + panic(); + } +} + +/* + * @flags: Operations expected when entering a low power sequence + * @voltage: Target voltage to apply during low power sequences + */ +struct regu_lp_config { + uint8_t flags; + struct stpmic1_lp_cfg cfg; +}; + +#define REGU_LP_FLAG_LOAD_PWRCTRL BIT(0) +#define REGU_LP_FLAG_ON_IN_SUSPEND BIT(1) +#define REGU_LP_FLAG_OFF_IN_SUSPEND BIT(2) +#define REGU_LP_FLAG_SET_VOLTAGE BIT(3) +#define REGU_LP_FLAG_MODE_STANDBY BIT(4) + +/* + * struct regu_lp_state - Low power configuration for regulators + * @name: low power state identifier string name + * @cfg_count: number of regulator configuration instance in @cfg + * @cfg: regulator configurations for low power state @name + */ +struct regu_lp_state { + const char *name; + size_t cfg_count; + struct regu_lp_config *cfg; +}; + +enum regu_lp_state_id { + REGU_LP_STATE_DISK = 0, + REGU_LP_STATE_STANDBY, + REGU_LP_STATE_MEM, + REGU_LP_STATE_MEM_LOWVOLTAGE, + REGU_LP_STATE_COUNT +}; + +static struct regu_lp_state regu_lp_state[REGU_LP_STATE_COUNT] = { + [REGU_LP_STATE_DISK] = { .name = "standby-ddr-off", }, + [REGU_LP_STATE_STANDBY] = { .name = "standby-ddr-sr", }, + [REGU_LP_STATE_MEM] = { .name = "lp-stop", }, + [REGU_LP_STATE_MEM_LOWVOLTAGE] = { .name = "lplv-stop", }, +}; + +static unsigned int regu_lp_state2idx(const char *name) +{ + unsigned int i = 0; + + for (i = 0; i < ARRAY_SIZE(regu_lp_state); i++) + if (!strcmp(name, regu_lp_state[i].name)) + return i; + + panic(); +} + +static void dt_get_regu_low_power_config(void *fdt, const char *regu_name, + int regu_node, const char *lp_state) +{ + unsigned int state_idx = regu_lp_state2idx(lp_state); + struct regu_lp_state *state = regu_lp_state + state_idx; + const fdt32_t *cuint = NULL; + int regu_state_node = 0; + struct regu_lp_config *regu_cfg = NULL; + + state->cfg_count++; + state->cfg = realloc(state->cfg, + state->cfg_count * sizeof(*state->cfg)); + if (!state->cfg) + panic(); + + regu_cfg = &state->cfg[state->cfg_count - 1]; + + memset(regu_cfg, 0, sizeof(*regu_cfg)); + + if (stpmic1_regu_has_lp_cfg(regu_name)) { + if (stpmic1_lp_cfg(regu_name, ®u_cfg->cfg)) { + DMSG("Cannot setup low power for regu %s", regu_name); + panic(); + } + /* + * Always copy active configuration (Control register) + * to PWRCTRL Control register, even if regu_state_node + * does not exist. + */ + regu_cfg->flags |= REGU_LP_FLAG_LOAD_PWRCTRL; + } + + /* Parse regulator stte node if any */ + regu_state_node = fdt_subnode_offset(fdt, regu_node, lp_state); + if (regu_state_node <= 0) + return; + + if (fdt_getprop(fdt, regu_state_node, + "regulator-on-in-suspend", NULL)) + regu_cfg->flags |= REGU_LP_FLAG_ON_IN_SUSPEND; + + if (fdt_getprop(fdt, regu_state_node, + "regulator-off-in-suspend", NULL)) + regu_cfg->flags |= REGU_LP_FLAG_OFF_IN_SUSPEND; + + cuint = fdt_getprop(fdt, regu_state_node, + "regulator-suspend-microvolt", NULL); + if (cuint) { + uint32_t mv = fdt32_to_cpu(*cuint) / 1000U; + + if (stpmic1_lp_voltage_cfg(regu_name, mv, ®u_cfg->cfg)) { + DMSG("Cannot set voltage for %s", regu_name); + panic(); + } + regu_cfg->flags |= REGU_LP_FLAG_SET_VOLTAGE; + } + + cuint = fdt_getprop(fdt, regu_state_node, + "regulator-mode", NULL); + if (cuint && fdt32_to_cpu(*cuint) == MODE_STANDBY) + regu_cfg->flags |= REGU_LP_FLAG_MODE_STANDBY; +} + +/* + * int stm32mp_pmic_set_lp_config(char *lp_state) + * + * Load the low power configuration stored in regu_lp_state[]. + */ +void stm32mp_pmic_apply_lp_config(const char *lp_state) +{ + unsigned int state_idx = regu_lp_state2idx(lp_state); + struct regu_lp_state *state = ®u_lp_state[state_idx]; + size_t i = 0; + + if (stpmic1_powerctrl_on()) + panic(); + + for (i = 0; i < state->cfg_count; i++) { + struct stpmic1_lp_cfg *cfg = &state->cfg[i].cfg; + + if ((state->cfg[i].flags & REGU_LP_FLAG_LOAD_PWRCTRL) && + stpmic1_lp_load_unpg(cfg)) + panic(); + + if ((state->cfg[i].flags & REGU_LP_FLAG_ON_IN_SUSPEND) && + stpmic1_lp_on_off_unpg(cfg, 1)) + panic(); + + if ((state->cfg[i].flags & REGU_LP_FLAG_OFF_IN_SUSPEND) && + stpmic1_lp_on_off_unpg(cfg, 0)) + panic(); + + if ((state->cfg[i].flags & REGU_LP_FLAG_SET_VOLTAGE) && + stpmic1_lp_voltage_unpg(cfg)) + panic(); + + if ((state->cfg[i].flags & REGU_LP_FLAG_MODE_STANDBY) && + stpmic1_lp_mode_unpg(cfg, 1)) + panic(); + } +} + +/* Return a libfdt compliant status value */ +static int save_cpu_supply_name(void) +{ + void *fdt = NULL; + int node = 0; + const fdt32_t *cuint = NULL; + const char *name = NULL; + + fdt = get_embedded_dt(); + if (!fdt) + panic(); + + node = fdt_path_offset(fdt, "/cpus/cpu@0"); + if (node < 0) + return -FDT_ERR_NOTFOUND; + + cuint = fdt_getprop(fdt, node, "cpu-supply", NULL); + if (!cuint) + return -FDT_ERR_NOTFOUND; + + node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (node < 0) + return -FDT_ERR_NOTFOUND; + + name = fdt_get_name(fdt, node, NULL); + assert(strnlen(name, sizeof(cpu_supply_name)) < + sizeof(cpu_supply_name)); + + strncpy(cpu_supply_name, name, sizeof(cpu_supply_name)); + + return 0; +} + +const char *stm32mp_pmic_get_cpu_supply_name(void) +{ + return cpu_supply_name; +} + +/* Preallocate not that much regu references */ +static char *nsec_access_regu_name[PMIC_REGU_COUNT]; + +bool stm32mp_nsec_can_access_pmic_regu(const char *name) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(nsec_access_regu_name); n++) + if (nsec_access_regu_name[n] && + !strcmp(nsec_access_regu_name[n], name)) + return true; + + return false; +} + +static void register_nsec_regu(const char *name_ref) +{ + size_t n = 0; + + assert(!stm32mp_nsec_can_access_pmic_regu(name_ref)); + + for (n = 0; n < ARRAY_SIZE(nsec_access_regu_name); n++) { + if (!nsec_access_regu_name[n]) { + nsec_access_regu_name[n] = strdup(name_ref); + + if (!nsec_access_regu_name[n]) + panic(); + break; + } + } + + assert(stm32mp_nsec_can_access_pmic_regu(name_ref)); +} + +static void parse_regulator_fdt_nodes(void) +{ + int pmic_node = 0; + int regulators_node = 0; + int regu_node = 0; + void *fdt = NULL; + + /* Expected called once */ + assert(!regu_bo_config && !regu_bo_count); + + fdt = get_embedded_dt(); + if (!fdt) + panic(); + + pmic_node = dt_get_pmic_node(fdt); + if (pmic_node < 0) + panic(); + + regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); + if (regulators_node < 0) + panic(); + + fdt_for_each_subnode(regu_node, fdt, regulators_node) { + int status = fdt_get_status(fdt, regu_node); + const char *regu_name = NULL; + size_t n = 0; + + if (status == DT_STATUS_DISABLED) + continue; + + regu_name = fdt_get_name(fdt, regu_node, NULL); + + assert(stpmic1_regulator_is_valid(regu_name)); + + if (status & DT_STATUS_OK_NSEC) + register_nsec_regu(regu_name); + + dt_get_regu_boot_on_config(fdt, regu_name, regu_node); + + for (n = 0; n < ARRAY_SIZE(regu_lp_state); n++) + dt_get_regu_low_power_config(fdt, regu_name, regu_node, + regu_lp_state[n].name); + } + + if (save_cpu_supply_name()) + DMSG("No CPU supply provided"); +} + +/* + * Get PMIC and its I2C bus configuration from the device tree. + * Return 0 on success, 1 if no PMIC node found and a negative value otherwise + */ +static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, + struct stm32_pinctrl **pinctrl, + size_t *pinctrl_count, + struct stm32_i2c_init_s *init) +{ + int pmic_node = 0; + int i2c_node = 0; + void *fdt = NULL; + const fdt32_t *cuint = NULL; + + fdt = get_embedded_dt(); + if (!fdt) + return -FDT_ERR_NOTFOUND; + + pmic_node = dt_get_pmic_node(fdt); + if (pmic_node < 0) + return 1; + + cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); + if (!cuint) + return -FDT_ERR_NOTFOUND; + + pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; + if (pmic_i2c_addr > UINT16_MAX) + return -FDT_ERR_BADVALUE; + + i2c_node = fdt_parent_offset(fdt, pmic_node); + if (i2c_node < 0) + return -FDT_ERR_NOTFOUND; + + fdt_fill_device_info(fdt, i2c_info, i2c_node); + if (!i2c_info->reg) + return -FDT_ERR_NOTFOUND; + + if (stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init, + pinctrl, pinctrl_count)) + panic(); + + return 0; +} + +/* + * PMIC and resource initialization + */ + +/* Return true if PMIC is available, false if not found, panics on errors */ +static bool initialize_pmic_i2c(void) +{ + int ret = 0; + struct dt_node_info i2c_info = { }; + struct i2c_handle_s *i2c = &i2c_handle; + struct stm32_pinctrl *pinctrl = NULL; + size_t pin_count = 0; + struct stm32_i2c_init_s i2c_init = { }; + + ret = dt_pmic_i2c_config(&i2c_info, &pinctrl, &pin_count, &i2c_init); + if (ret < 0) { + EMSG("I2C configuration failed %d", ret); + panic(); + } + if (ret) + return false; + + /* Initialize PMIC I2C */ + i2c->base.pa = i2c_info.reg; + i2c->base.va = (vaddr_t)phys_to_virt(i2c->base.pa, MEM_AREA_IO_SEC, 1); + assert(i2c->base.va); + i2c->dt_status = i2c_info.status; + i2c->clock = i2c_init.clock; + i2c->i2c_state = I2C_STATE_RESET; + i2c_init.own_address1 = pmic_i2c_addr; + i2c_init.analog_filter = true; + i2c_init.digital_filter_coef = 0; + + i2c->pinctrl = pinctrl; + i2c->pinctrl_count = pin_count; + + stm32mp_get_pmic(); + + ret = stm32_i2c_init(i2c, &i2c_init); + if (ret) { + EMSG("I2C init 0x%" PRIxPA ": %d", i2c_info.reg, ret); + panic(); + } + + if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, + PMIC_I2C_TRIALS, + PMIC_I2C_TIMEOUT_BUSY_MS)) + panic(); + + stpmic1_bind_i2c(i2c, pmic_i2c_addr); + + stm32mp_put_pmic(); + + return true; +} + +/* + * Automated suspend/resume at system suspend/resume is expected + * only when the PMIC is secure. If it is non secure, only atomic + * execution context can get/put the PMIC resources. + */ +static TEE_Result pmic_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *pm_handle __unused) +{ + if (op == PM_OP_SUSPEND) + stm32_i2c_suspend(&i2c_handle); + else + stm32_i2c_resume(&i2c_handle); + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(pmic_pm); + +/* stm32mp_get/put_pmic allows secure atomic sequences to use non secure PMIC */ +void stm32mp_get_pmic(void) +{ + stm32_i2c_resume(&i2c_handle); +} + +void stm32mp_put_pmic(void) +{ + stm32_i2c_suspend(&i2c_handle); +} + +static void register_non_secure_pmic(void) +{ + size_t n = 0; + + /* Allow this function to be called when STPMIC1 not used */ + if (!i2c_handle.base.pa) + return; + + for (n = 0; n < i2c_handle.pinctrl_count; n++) + stm32mp_register_non_secure_gpio(i2c_handle.pinctrl[n].bank, + i2c_handle.pinctrl[n].pin); + + stm32mp_register_non_secure_periph_iomem(i2c_handle.base.pa); +} + +static void register_secure_pmic(void) +{ + size_t n = 0; + + for (n = 0; n < i2c_handle.pinctrl_count; n++) + stm32mp_register_secure_gpio(i2c_handle.pinctrl[n].bank, + i2c_handle.pinctrl[n].pin); + + stm32mp_register_secure_periph_iomem(i2c_handle.base.pa); + register_pm_driver_cb(pmic_pm, NULL, "stm32mp1-pmic"); +} + +static TEE_Result initialize_pmic(void) +{ + unsigned long pmic_version = 0; + + if (!initialize_pmic_i2c()) { + DMSG("No PMIC"); + register_non_secure_pmic(); + return TEE_SUCCESS; + } + + stm32mp_get_pmic(); + + if (stpmic1_get_version(&pmic_version)) + panic("Failed to access PMIC"); + + DMSG("PMIC version = 0x%02lx", pmic_version); + stpmic1_dump_regulators(); + + if (dt_pmic_is_secure()) + register_secure_pmic(); + else + register_non_secure_pmic(); + + parse_regulator_fdt_nodes(); + + stm32mp_put_pmic(); + + return TEE_SUCCESS; +} +driver_init(initialize_pmic); diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h new file mode 100644 index 0000000..4625af1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2017-2020, STMicroelectronics + */ + +#ifndef __STM32MP1_PMIC_H__ +#define __STM32MP1_PMIC_H__ + +#include + +#ifdef CFG_STPMIC1 +void stm32mp_pmic_apply_boot_on_config(void); +void stm32mp_pmic_apply_lp_config(const char *lp_state); +void stm32mp_get_pmic(void); +void stm32mp_put_pmic(void); +int stm32mp_dt_pmic_status(void); +const char *stm32mp_pmic_get_cpu_supply_name(void); +#else +static inline void stm32mp_pmic_apply_boot_on_config(void) +{ +} + +static inline void stm32mp_pmic_apply_lp_config(const char *lp_state __unused) +{ +} + +static inline void stm32mp_get_pmic(void) +{ + panic(); +} + +static inline void stm32mp_put_pmic(void) +{ + panic(); +} + +static inline int stm32mp_dt_pmic_status(void) +{ + return -1; +} + +static inline const char *stm32mp_pmic_get_cpu_supply_name(void) +{ + return NULL; +} +#endif + +#endif /*__STM32MP1_PMIC_H__*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c new file mode 100644 index 0000000..3ec0d42 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018-2019, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include + +#define PWR_CR3_USB33_EN BIT(24) +#define PWR_CR3_USB33_RDY BIT(26) +#define PWR_CR3_REG18_EN BIT(28) +#define PWR_CR3_REG18_RDY BIT(29) +#define PWR_CR3_REG11_EN BIT(30) +#define PWR_CR3_REG11_RDY BIT(31) + +struct pwr_regu_desc { + unsigned int level_mv; + uint32_t cr3_enable_mask; + uint32_t cr3_ready_mask; +}; + +static const struct pwr_regu_desc pwr_regulators[PWR_REGU_COUNT] = { + [PWR_REG11] = { + .level_mv = 1100, + .cr3_enable_mask = PWR_CR3_REG11_EN, + .cr3_ready_mask = PWR_CR3_REG11_RDY, + }, + [PWR_REG18] = { + .level_mv = 1800, + .cr3_enable_mask = PWR_CR3_REG18_EN, + .cr3_ready_mask = PWR_CR3_REG18_RDY, + }, + [PWR_USB33] = { + .level_mv = 3300, + .cr3_enable_mask = PWR_CR3_USB33_EN, + .cr3_ready_mask = PWR_CR3_USB33_RDY, + }, +}; + +vaddr_t stm32_pwr_base(void) +{ + static struct io_pa_va base = { .pa = PWR_BASE }; + + return io_pa_or_va_secure(&base, 1); +} + +unsigned int stm32mp1_pwr_regulator_mv(enum pwr_regulator id) +{ + assert(id < PWR_REGU_COUNT); + + return pwr_regulators[id].level_mv; +} + +void stm32mp1_pwr_regulator_set_state(enum pwr_regulator id, bool enable) +{ + uintptr_t cr3 = stm32_pwr_base() + PWR_CR3_OFF; + uint32_t enable_mask = pwr_regulators[id].cr3_enable_mask; + + assert(id < PWR_REGU_COUNT); + + if (enable) { + uint64_t to = timeout_init_us(10 * 1000); + uint32_t ready_mask = pwr_regulators[id].cr3_ready_mask; + + io_setbits32(cr3, enable_mask); + + while (!timeout_elapsed(to)) + if (io_read32(cr3) & ready_mask) + break; + + if (!(io_read32(cr3) & ready_mask)) + panic(); + } else { + io_clrbits32(cr3, enable_mask); + } +} + +bool stm32mp1_pwr_regulator_is_enabled(enum pwr_regulator id) +{ + assert(id < PWR_REGU_COUNT); + + return io_read32(stm32_pwr_base() + PWR_CR3_OFF) & + pwr_regulators[id].cr3_enable_mask; +} diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h new file mode 100644 index 0000000..9cedd93 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2018-2019, STMicroelectronics + */ + +#ifndef __STM32MP1_PWR_H +#define __STM32MP1_PWR_H + +#include +#include + +#define PWR_CR1_OFF 0x00 +#define PWR_CR2_OFF 0x08 +#define PWR_CR3_OFF 0x0c +#define PWR_MPUCR_OFF 0x10 +#define PWR_WKUPCR_OFF 0x20 +#define PWR_MPUWKUPENR_OFF 0x28 + +#define PWR_OFFSET_MASK 0x3fUL + +enum pwr_regulator { + PWR_REG11 = 0, + PWR_REG18, + PWR_USB33, + PWR_REGU_COUNT +}; + +vaddr_t stm32_pwr_base(void); + +unsigned int stm32mp1_pwr_regulator_mv(enum pwr_regulator id); +void stm32mp1_pwr_regulator_set_state(enum pwr_regulator id, bool enable); +bool stm32mp1_pwr_regulator_is_enabled(enum pwr_regulator id); + +#endif /*__STM32MP1_PWR_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c new file mode 100644 index 0000000..0622650 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2022, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * SYSCFG register offsets (base relative) + */ +#define SYSCFG_CMPCR 0x20U +#define SYSCFG_CMPENSETR 0x24U + +/* + * SYSCFG_CMPCR Register + */ +#define SYSCFG_CMPCR_SW_CTRL BIT(1) +#define SYSCFG_CMPCR_READY BIT(8) +#define SYSCFG_CMPCR_RANSRC GENMASK_32(19, 16) +#define SYSCFG_CMPCR_RANSRC_SHIFT 16 +#define SYSCFG_CMPCR_RAPSRC GENMASK_32(23, 20) +#define SYSCFG_CMPCR_ANSRC_SHIFT 24 + +#define SYSCFG_CMPCR_READY_TIMEOUT_US 1000U + +/* + * SYSCFG_CMPENSETR Register + */ +#define SYSCFG_CMPENSETR_MPU_EN BIT(0) + +static vaddr_t get_syscfg_base(void) +{ + struct io_pa_va base = { .pa = SYSCFG_BASE }; + + return io_pa_or_va(&base, 1); +} + +void stm32mp_syscfg_enable_io_compensation(void) +{ + vaddr_t syscfg_base = get_syscfg_base(); + uint64_t timeout_ref = 0; + + if (clk_enable(stm32mp_rcc_clock_id_to_clk(CK_CSI)) || + clk_enable(stm32mp_rcc_clock_id_to_clk(SYSCFG))) + panic(); + + io_setbits32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN); + + timeout_ref = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US); + + while (!(io_read32(syscfg_base + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY)) + if (timeout_elapsed(timeout_ref)) { + EMSG("IO compensation cell not ready"); + /* Allow an almost silent failure here */ + break; + } + + io_clrbits32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); + + DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(syscfg_base + SYSCFG_CMPCR)); +} + +void stm32mp_syscfg_disable_io_compensation(void) +{ + vaddr_t syscfg_base = get_syscfg_base(); + uint32_t value = 0; + + value = io_read32(syscfg_base + SYSCFG_CMPCR) >> + SYSCFG_CMPCR_ANSRC_SHIFT; + + io_clrbits32(syscfg_base + SYSCFG_CMPCR, + SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); + + value = io_read32(syscfg_base + SYSCFG_CMPCR) | + (value << SYSCFG_CMPCR_RANSRC_SHIFT); + + io_write32(syscfg_base + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL); + + DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(syscfg_base + SYSCFG_CMPCR)); + + io_clrbits32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN); + + clk_disable(stm32mp_rcc_clock_id_to_clk(CK_CSI)); + clk_disable(stm32mp_rcc_clock_id_to_clk(SYSCFG)); +} + +static TEE_Result stm32mp1_iocomp(void) +{ + stm32mp_syscfg_enable_io_compensation(); + + return TEE_SUCCESS; +} +driver_init(stm32mp1_iocomp); diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/sub.mk b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/sub.mk new file mode 100644 index 0000000..b07c8f9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/drivers/sub.mk @@ -0,0 +1,3 @@ +srcs-$(CFG_STPMIC1) += stm32mp1_pmic.c +srcs-y += stm32mp1_pwr.c +srcs-y += stm32mp1_syscfg.c diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/link.mk b/optee/optee_os/core/arch/arm/plat-stm32mp1/link.mk new file mode 100644 index 0000000..01a9b8e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/link.mk @@ -0,0 +1,24 @@ +include core/arch/arm/kernel/link.mk + +# Create stm32 formatted images from the native binary images + +define stm32image_cmd + @$(cmd-echo-silent) ' GEN $@' + $(q)./core/arch/arm/plat-stm32mp1/scripts/stm32image.py \ + --load 0 --entry 0 +endef + +all: $(link-out-dir)/tee-header_v2.stm32 +cleanfiles += $(link-out-dir)/tee-header_v2.stm32 +$(link-out-dir)/tee-header_v2.stm32: $(link-out-dir)/tee-header_v2.bin + $(stm32image_cmd) --source $< --dest $@ --bintype 0x20 + +all: $(link-out-dir)/tee-pager_v2.stm32 +cleanfiles += $(link-out-dir)/tee-pager_v2.stm32 +$(link-out-dir)/tee-pager_v2.stm32: $(link-out-dir)/tee-pager_v2.bin + $(stm32image_cmd) --source $< --dest $@ --bintype 0x21 + +all: $(link-out-dir)/tee-pageable_v2.stm32 +cleanfiles += $(link-out-dir)/tee-pageable_v2.stm32 +$(link-out-dir)/tee-pageable_v2.stm32: $(link-out-dir)/tee-pageable_v2.bin + $(stm32image_cmd) --source $< --dest $@ --bintype 0x22 diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/link_dummies_paged.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/link_dummies_paged.c new file mode 100644 index 0000000..989d5c2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/link_dummies_paged.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ +#include +#include +#include + +const struct clk_ops stm32mp1_clk_ops __rodata_dummy; diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/main.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/main.c new file mode 100644 index 0000000..7b1ed4e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/main.c @@ -0,0 +1,546 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2022, STMicroelectronics + * Copyright (c) 2016-2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB1_BASE, APB1_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB2_BASE, APB2_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB3_BASE, APB3_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB4_BASE, APB4_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB5_BASE, APB5_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, AHB4_BASE, AHB4_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, AHB5_BASE, AHB5_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB1_BASE, APB1_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB3_BASE, APB3_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB4_BASE, APB4_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB5_BASE, APB5_SIZE); +#ifdef CFG_STM32MP13 +register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB6_BASE, APB6_SIZE); +#endif +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB4_BASE, AHB4_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB5_BASE, AHB5_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); + +#ifdef CFG_STM32MP1_SCMI_SHM_BASE +register_phys_mem(MEM_AREA_IO_NSEC, CFG_STM32MP1_SCMI_SHM_BASE, + CFG_STM32MP1_SCMI_SHM_SIZE); +#endif + +register_ddr(DDR_BASE, CFG_DRAM_SIZE); + +#define _ID2STR(id) (#id) +#define ID2STR(id) _ID2STR(id) + +static TEE_Result platform_banner(void) +{ + IMSG("Platform stm32mp1: flavor %s - DT %s", + ID2STR(PLATFORM_FLAVOR), + ID2STR(CFG_EMBED_DTB_SOURCE_FILE)); + + return TEE_SUCCESS; +} +service_init(platform_banner); + +/* + * Console + * + * CFG_STM32_EARLY_CONSOLE_UART specifies the ID of the UART used for + * trace console. Value 0 disables the early console. + * + * We cannot use the generic serial_console support since probing + * the console requires the platform clock driver to be already + * up and ready which is done only once service_init are completed. + */ +static struct stm32_uart_pdata console_data; + +void console_init(void) +{ + /* Early console initialization before MMU setup */ + struct uart { + paddr_t pa; + bool secure; + } uarts[] = { + [0] = { .pa = 0 }, + [1] = { .pa = USART1_BASE, .secure = true, }, + [2] = { .pa = USART2_BASE, .secure = false, }, + [3] = { .pa = USART3_BASE, .secure = false, }, + [4] = { .pa = UART4_BASE, .secure = false, }, + [5] = { .pa = UART5_BASE, .secure = false, }, + [6] = { .pa = USART6_BASE, .secure = false, }, + [7] = { .pa = UART7_BASE, .secure = false, }, + [8] = { .pa = UART8_BASE, .secure = false, }, + }; + + COMPILE_TIME_ASSERT(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART); + + if (!uarts[CFG_STM32_EARLY_CONSOLE_UART].pa) + return; + + /* No clock yet bound to the UART console */ + console_data.clock = NULL; + + console_data.secure = uarts[CFG_STM32_EARLY_CONSOLE_UART].secure; + stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa); + + register_serial_console(&console_data.chip); + + IMSG("Early console on UART#%u", CFG_STM32_EARLY_CONSOLE_UART); +} + +static TEE_Result init_console_from_dt(void) +{ + struct stm32_uart_pdata *pd = NULL; + void *fdt = NULL; + int node = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + fdt = get_embedded_dt(); + res = get_console_node_from_dt(fdt, &node, NULL, NULL); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + fdt = get_external_dt(); + res = get_console_node_from_dt(fdt, &node, NULL, NULL); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return TEE_SUCCESS; + if (res != TEE_SUCCESS) + return res; + } + + pd = stm32_uart_init_from_dt_node(fdt, node); + if (!pd) { + IMSG("DTB disables console"); + register_serial_console(NULL); + return TEE_SUCCESS; + } + + /* Replace early console with the new one */ + console_flush(); + console_data = *pd; + register_serial_console(&console_data.chip); + IMSG("DTB enables console (%ssecure)", pd->secure ? "" : "non-"); + free(pd); + + return TEE_SUCCESS; +} + +/* Probe console from DT once clock inits (service init level) are completed */ +service_init_late(init_console_from_dt); + +/* + * GIC init, used also for primary/secondary boot core wake completion + */ +static struct gic_data gic_data; + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void main_init_gic(void) +{ + gic_init(&gic_data, GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); + itr_init(&gic_data.chip); + + stm32mp_register_online_cpu(); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); + + stm32mp_register_online_cpu(); +} + +#ifdef CFG_STM32MP13 +#ifdef CFG_STM32_ETZPC +/* Configure ETZPC cell and lock it when resource is secure */ +static void config_lock_decprot(uint32_t decprot_id, + enum etzpc_decprot_attributes decprot_attr) +{ + etzpc_configure_decprot(decprot_id, decprot_attr); + + if (decprot_attr == ETZPC_DECPROT_S_RW) + etzpc_lock_decprot(decprot_id); +} + +static TEE_Result set_etzpc_secure_configuration(void) +{ + config_lock_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_DDRCTRLPHY_ID, + ETZPC_DECPROT_NS_R_S_W); + + /* Configure ETZPC with peripheral registering */ + config_lock_decprot(STM32MP1_ETZPC_ADC1_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_ADC2_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_CRYP_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_DCMIPP_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_ETH1_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_ETH2_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_FMC_ID, ETZPC_DECPROT_NS_RW); + /* HASH is secure */ + config_lock_decprot(STM32MP1_ETZPC_HASH_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_I2C3_ID, ETZPC_DECPROT_NS_RW); + /* I2C4 is secure */ + config_lock_decprot(STM32MP1_ETZPC_I2C4_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_I2C5_ID, ETZPC_DECPROT_NS_RW); + /* IWDG1 is secure */ + config_lock_decprot(STM32MP1_ETZPC_IWDG1_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_LPTIM2_ID, ETZPC_DECPROT_NS_RW); + /* LPTIM3 is secure */ + config_lock_decprot(STM32MP1_ETZPC_LPTIM3_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_LTDC_ID, ETZPC_DECPROT_NS_RW); + /* MCE is secure */ + config_lock_decprot(STM32MP1_ETZPC_MCE_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_OTG_ID, ETZPC_DECPROT_NS_RW); + /* PKA is secure */ + config_lock_decprot(STM32MP1_ETZPC_PKA_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_QSPI_ID, ETZPC_DECPROT_NS_RW); + /* RNG is secure */ + config_lock_decprot(STM32MP1_ETZPC_RNG_ID, ETZPC_DECPROT_S_RW); + /* SAES is secure */ + config_lock_decprot(STM32MP1_ETZPC_SAES_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_SDMMC1_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_SDMMC2_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_SPI4_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_SPI5_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_SRAM1_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_SRAM2_ID, ETZPC_DECPROT_NS_RW); + /* SRAM3 is secure */ + config_lock_decprot(STM32MP1_ETZPC_SRAM3_ID, ETZPC_DECPROT_S_RW); + /* STGENC is secure */ + config_lock_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); + /* TIM12 is secure */ + config_lock_decprot(STM32MP1_ETZPC_TIM12_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_TIM13_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_TIM14_ID, ETZPC_DECPROT_NS_RW); + /* TIM15 is secure */ + config_lock_decprot(STM32MP1_ETZPC_TIM15_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_TIM16_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_TIM17_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_USART1_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_USART2_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_USBPHYCTRL_ID, ETZPC_DECPROT_NS_RW); + config_lock_decprot(STM32MP1_ETZPC_VREFBUF_ID, ETZPC_DECPROT_NS_RW); + + return TEE_SUCCESS; +} + +driver_init_late(set_etzpc_secure_configuration); +#endif /* CFG_STM32_ETZPC */ + +#ifdef CFG_STM32_GPIO + +#define NB_PINS_PER_BANK U(16) +#define NB_PINS_BANK_H U(14) +#define NB_PINS_BANK_I U(8) + +static TEE_Result set_all_gpios_non_secure(void) +{ + unsigned int bank = 0; + unsigned int pin = 0; + unsigned int nb_pin_bank = 0; + + for (bank = 0; bank <= GPIO_BANK_I; bank++) { + switch (bank) { + case GPIO_BANK_H: + nb_pin_bank = NB_PINS_BANK_H; + break; + case GPIO_BANK_I: + nb_pin_bank = NB_PINS_BANK_I; + break; + default: + nb_pin_bank = NB_PINS_PER_BANK; + break; + } + + for (pin = 0; pin <= nb_pin_bank; pin++) + stm32_gpio_set_secure_cfg(bank, pin, false); + } + + return TEE_SUCCESS; +} + +early_init_late(set_all_gpios_non_secure); +#endif /* CFG_STM32_GPIO */ +#endif /* CFG_STM32MP13 */ + +static TEE_Result init_stm32mp1_drivers(void) +{ + /* Secure internal memories for the platform, once ETZPC is ready */ + etzpc_configure_tzma(0, ETZPC_TZMA_ALL_SECURE); + etzpc_lock_tzma(0); + +#ifdef CFG_TZSRAM_START + COMPILE_TIME_ASSERT(((SYSRAM_BASE + SYSRAM_SIZE) <= CFG_TZSRAM_START) || + ((SYSRAM_BASE <= CFG_TZSRAM_START) && + (SYSRAM_SEC_SIZE >= CFG_TZSRAM_SIZE))); +#endif /* CFG_TZSRAM_START */ + + etzpc_configure_tzma(1, SYSRAM_SEC_SIZE >> SMALL_PAGE_SHIFT); + etzpc_lock_tzma(1); + + if (SYSRAM_SIZE > SYSRAM_SEC_SIZE) { + size_t nsec_size = SYSRAM_SIZE - SYSRAM_SEC_SIZE; + paddr_t nsec_start = SYSRAM_BASE + SYSRAM_SEC_SIZE; + uint8_t *va = phys_to_virt(nsec_start, MEM_AREA_IO_NSEC, + nsec_size); + + IMSG("Non-secure SYSRAM [%p %p]", va, va + nsec_size - 1); + + /* Clear content from the non-secure part */ + memset(va, 0, nsec_size); + } + + return TEE_SUCCESS; +} + +service_init_late(init_stm32mp1_drivers); + +static TEE_Result init_late_stm32mp1_drivers(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* Set access permission to TAM backup registers */ + if (IS_ENABLED(CFG_STM32_TAMP)) { + struct stm32_bkpregs_conf conf = { + .nb_zone1_regs = TAMP_BKP_REGISTER_ZONE1_COUNT, + .nb_zone2_regs = TAMP_BKP_REGISTER_ZONE2_COUNT, + }; + + res = stm32_tamp_set_secure_bkpregs(&conf); + if (res == TEE_ERROR_DEFER_DRIVER_INIT) { + /* TAMP driver was not probed if disabled in the DT */ + res = TEE_SUCCESS; + } + if (res) + panic(); + } + + return TEE_SUCCESS; +} + +driver_init_late(init_late_stm32mp1_drivers); + +vaddr_t stm32_rcc_base(void) +{ + static struct io_pa_va base = { .pa = RCC_BASE }; + + return io_pa_or_va_secure(&base, 1); +} + +vaddr_t get_gicd_base(void) +{ + struct io_pa_va base = { .pa = GIC_BASE + GICD_OFFSET }; + + return io_pa_or_va_secure(&base, 1); +} + +void stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg *cfg) +{ + cfg->base = BSEC_BASE; + cfg->upper_start = STM32MP1_UPPER_OTP_START; + cfg->max_id = STM32MP1_OTP_MAX_ID; +} + +bool __weak stm32mp_with_pmic(void) +{ + return false; +} + +uint32_t may_spin_lock(unsigned int *lock) +{ + if (!lock || !cpu_mmu_enabled()) + return 0; + + return cpu_spin_lock_xsave(lock); +} + +void may_spin_unlock(unsigned int *lock, uint32_t exceptions) +{ + if (!lock || !cpu_mmu_enabled()) + return; + + cpu_spin_unlock_xrestore(lock, exceptions); +} + +static vaddr_t stm32_tamp_base(void) +{ + static struct io_pa_va base = { .pa = TAMP_BASE }; + + return io_pa_or_va_secure(&base, 1); +} + +static vaddr_t bkpreg_base(void) +{ + return stm32_tamp_base() + TAMP_BKP_REGISTER_OFF; +} + +vaddr_t stm32mp_bkpreg(unsigned int idx) +{ + return bkpreg_base() + (idx * sizeof(uint32_t)); +} + +static bool __maybe_unused bank_is_valid(unsigned int bank) +{ + if (IS_ENABLED(CFG_STM32MP15)) + return bank == GPIO_BANK_Z || bank <= GPIO_BANK_K; + + if (IS_ENABLED(CFG_STM32MP13)) + return bank <= GPIO_BANK_I; + + panic(); +} + +vaddr_t stm32_get_gpio_bank_base(unsigned int bank) +{ + static struct io_pa_va base = { .pa = GPIOA_BASE }; + + static_assert(GPIO_BANK_A == 0); + assert(bank_is_valid(bank)); + + if (IS_ENABLED(CFG_STM32MP15)) { + static struct io_pa_va zbase = { .pa = GPIOZ_BASE }; + + /* Get secure mapping address for GPIOZ */ + if (bank == GPIO_BANK_Z) + return io_pa_or_va_secure(&zbase, GPIO_BANK_OFFSET); + + /* Other are mapped non-secure */ + return io_pa_or_va_nsec(&base, (bank + 1) * GPIO_BANK_OFFSET) + + (bank * GPIO_BANK_OFFSET); + } + + if (IS_ENABLED(CFG_STM32MP13)) + return io_pa_or_va_secure(&base, + (bank + 1) * GPIO_BANK_OFFSET) + + (bank * GPIO_BANK_OFFSET); + + panic(); +} + +unsigned int stm32_get_gpio_bank_offset(unsigned int bank) +{ + assert(bank_is_valid(bank)); + + if (bank == GPIO_BANK_Z) + return 0; + + return bank * GPIO_BANK_OFFSET; +} + +unsigned int stm32_get_gpio_bank_clock(unsigned int bank) +{ + assert(bank_is_valid(bank)); + +#ifdef CFG_STM32MP15 + if (bank == GPIO_BANK_Z) + return GPIOZ; +#endif + + return GPIOA + bank; +} + +struct clk *stm32_get_gpio_bank_clk(unsigned int bank) +{ + assert(bank_is_valid(bank)); + + if (!IS_ENABLED(CFG_DRIVERS_CLK)) + return NULL; + + return stm32mp_rcc_clock_id_to_clk(stm32_get_gpio_bank_clock(bank)); +} + +#ifdef CFG_STM32_IWDG +TEE_Result stm32_get_iwdg_otp_config(paddr_t pbase, + struct stm32_iwdg_otp_data *otp_data) +{ + unsigned int idx = 0; + uint32_t otp_id = 0; + size_t bit_len = 0; + uint32_t otp_value = 0; + + switch (pbase) { + case IWDG1_BASE: + idx = 0; + break; + case IWDG2_BASE: + idx = 1; + break; + default: + panic(); + } + + if (stm32_bsec_find_otp_in_nvmem_layout("hw2_otp", &otp_id, &bit_len) || + bit_len != 32) + panic(); + + if (stm32_bsec_read_otp(&otp_value, otp_id)) + panic(); + + otp_data->hw_enabled = otp_value & + BIT(idx + HW2_OTP_IWDG_HW_ENABLE_SHIFT); + otp_data->disable_on_stop = otp_value & + BIT(idx + HW2_OTP_IWDG_FZ_STOP_SHIFT); + otp_data->disable_on_standby = otp_value & + BIT(idx + HW2_OTP_IWDG_FZ_STANDBY_SHIFT); + + return TEE_SUCCESS; +} +#endif /*CFG_STM32_IWDG*/ + +#ifdef CFG_STM32_DEBUG_ACCESS +static TEE_Result init_debug(void) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t conf = stm32_bsec_read_debug_conf(); + struct clk *dbg_clk = stm32mp_rcc_clock_id_to_clk(CK_DBG); + uint32_t state = 0; + + res = stm32_bsec_get_state(&state); + if (res) + return res; + + if (state != BSEC_STATE_SEC_CLOSED && conf) { + if (IS_ENABLED(CFG_WARN_INSECURE)) + IMSG("WARNING: All debug accesses are allowed"); + + res = stm32_bsec_write_debug_conf(conf | BSEC_DEBUG_ALL); + if (res) + return res; + + /* + * Enable DBG clock as used to access coprocessor + * debug registers + */ + clk_enable(dbg_clk); + } + + return TEE_SUCCESS; +} +early_init_late(init_debug); +#endif /* CFG_STM32_DEBUG_ACCESS */ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c new file mode 100644 index 0000000..9f426de --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2016-2020, STMicroelectronics + */ + +#include +#include +#include +#include + +#include "bsec_svc.h" +#include "stm32mp1_smc.h" + +void bsec_main(struct thread_smc_args *args) +{ + TEE_Result result = TEE_ERROR_GENERIC; + uint32_t cmd = args->a1; + uint32_t otp_id = args->a2; + uint32_t in_value = args->a3; + uint32_t *out_value = &args->a1; + uint32_t tmp = 0; + + if (!stm32_bsec_nsec_can_access_otp(otp_id)) { + args->a0 = STM32_SIP_SVC_INVALID_PARAMS; + return; + } + + switch (cmd) { + case STM32_SIP_SVC_BSEC_READ_SHADOW: + FMSG("read shadow @%#"PRIx32, otp_id); + result = stm32_bsec_read_otp(out_value, otp_id); + break; + case STM32_SIP_SVC_BSEC_PROG_OTP: + FMSG("program @%#"PRIx32, otp_id); + result = stm32_bsec_program_otp(in_value, otp_id); + break; + case STM32_SIP_SVC_BSEC_WRITE_SHADOW: + FMSG("write shadow @%#"PRIx32, otp_id); + result = stm32_bsec_write_otp(in_value, otp_id); + break; + case STM32_SIP_SVC_BSEC_READ_OTP: + FMSG("read @%#"PRIx32, otp_id); + result = stm32_bsec_read_otp(&tmp, otp_id); + if (!result) + result = stm32_bsec_shadow_register(otp_id); + if (!result) + result = stm32_bsec_read_otp(out_value, otp_id); + if (!result) + result = stm32_bsec_write_otp(tmp, otp_id); + break; + case STM32_SIP_SVC_BSEC_WRLOCK_OTP: + FMSG("permanent write lock @%#"PRIx32, otp_id); + result = stm32_bsec_permanent_lock_otp(otp_id); + break; + default: + DMSG("Invalid command %#"PRIx32, cmd); + result = TEE_ERROR_BAD_PARAMETERS; + break; + } + + if (!result) + args->a0 = STM32_SIP_SVC_OK; + else if (result == TEE_ERROR_BAD_PARAMETERS) + args->a0 = STM32_SIP_SVC_INVALID_PARAMS; + else + args->a0 = STM32_SIP_SVC_FAILED; +} diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h new file mode 100644 index 0000000..5e57f50 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2016-2020, STMicroelectronics + */ + +#ifndef __STM32MP1_BSEC_SVC_H__ +#define __STM32MP1_BSEC_SVC_H__ + +#include +#include +#include + +#ifdef CFG_STM32_BSEC_SIP +void bsec_main(struct thread_smc_args *args); +#else +static inline void bsec_main(struct thread_smc_args *args) +{ + args->a0 = STM32_SIP_SVC_UNKNOWN_FUNCTION; +} +#endif +#endif /*__STM32MP1_BSEC_SVC_H__*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h new file mode 100644 index 0000000..2fbcac3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2016-2022, STMicroelectronics + * Copyright (c) 2018, Linaro Limited + */ +#ifndef __STM32MP1_SMC_H__ +#define __STM32MP1_SMC_H__ + +#include + +/* + * SIP Functions + */ +#define STM32_SIP_SVC_VERSION_MAJOR 0x0 +#define STM32_SIP_SVC_VERSION_MINOR 0x1 + +#define STM32_SIP_SVC_FUNCTION_COUNT 0x3 + +/* STM32 SIP service generic return codes */ +#define STM32_SIP_SVC_OK 0x0 +#define STM32_SIP_SVC_UNKNOWN_FUNCTION OPTEE_SMC_RETURN_UNKNOWN_FUNCTION +#define STM32_SIP_SVC_FAILED 0xfffffffeU +#define STM32_SIP_SVC_INVALID_PARAMS 0xfffffffdU + +/* + * SMC function IDs for STM32 Service queries + * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF + * like this is defined in SMC calling Convention by ARM + * for SiP (Silicon Partner) + * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + */ + +/* + * SIP function STM32_SIP_FUNC_CALL_COUNT + * + * Argument a0: (input) SMCC ID + * (output) Count of defined function IDs + */ +#define STM32_SIP_SVC_FUNC_CALL_COUNT 0xff00 + +/* + * Return the following UID if using API specified in this file without + * further extensions: + * 50aa78a7-9bf4-4a14-8a5e-264d5994c214. + * + * Represented in 4 32-bit words in STM32_SIP_UID_0, STM32_SIP_UID_1, + * STM32_SIP_UID_2, STM32_SIP_UID_3. + */ +#define STM32_SIP_SVC_UID_0 0x50aa78a7 +#define STM32_SIP_SVC_UID_1 0x9bf44a14 +#define STM32_SIP_SVC_UID_2 0x8a5e264d +#define STM32_SIP_SVC_UID_3 0x5994c214 + +/* + * SIP function STM32_SIP_SVC_FUNC_UID + * + * Argument a0: (input) SMCC ID + * (output) Lowest 32bit of the stm32mp1 SIP service UUID + * Argument a1: (output) Next 32bit of the stm32mp1 SIP service UUID + * Argument a2: (output) Next 32bit of the stm32mp1 SIP service UUID + * Argument a3: (output) Last 32bit of the stm32mp1 SIP service UUID + */ +#define STM32_SIP_SVC_FUNC_UID 0xff01 + +/* + * SIP function STM32_SIP_FUNC_VERSION + * + * Argument a0: (input) SMCC ID + * (output) STM32 SIP service major + * Argument a1: (output) STM32 SIP service minor + */ +#define STM32_SIP_SVC_FUNC_VERSION 0xff03 + +/* + * SIP functions STM32_SIP_SVC_FUNC_BSEC - Deprecated + * + * Argument a0: (input) SMCCC function ID + * (output) status return code + * Argument a1: (input) Service ID (STM32_SIP_BSEC_xxx) + * Argument a2: (input) OTP index + * (output) OTP read value, if applicable + * Argument a3: (input) OTP value if applicable + */ +#define STM32_SIP_SVC_FUNC_BSEC 0x1003 + +/* Service ID for function ID STM32_SIP_FUNC_BSEC */ +#define STM32_SIP_SVC_BSEC_READ_SHADOW 0x1 +#define STM32_SIP_SVC_BSEC_PROG_OTP 0x2 +#define STM32_SIP_SVC_BSEC_WRITE_SHADOW 0x3 +#define STM32_SIP_SVC_BSEC_READ_OTP 0x4 +/* reserved for STM32_SIP_SVC_SMC_READ_ALL 0x5 */ +/* reserved for STM32_SIP_SVC_SMC_WRITE_ALL 0x6 */ +#define STM32_SIP_SVC_BSEC_WRLOCK_OTP 0x7 + +/* + * SIP function STM32_SIP_SVC_FUNC_SCMI_AGENT0 + * SIP function STM32_SIP_SVC_FUNC_SCMI_AGENT1 + * + * Process SCMI message pending in related SCMI shared memory buffer. + * + * Argument a0: (input) SMCC ID + */ +#define STM32_SIP_SVC_FUNC_SCMI_AGENT0 0x2000 +#define STM32_SIP_SVC_FUNC_SCMI_AGENT1 0x2001 + +#endif /* __STM32MP1_SMC_H__*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c new file mode 100644 index 0000000..70d6667 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2020, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include + +#include "bsec_svc.h" +#include "stm32mp1_smc.h" + +static enum sm_handler_ret sip_service(struct sm_ctx *ctx __unused, + struct thread_smc_args *args) +{ + switch (OPTEE_SMC_FUNC_NUM(args->a0)) { + case STM32_SIP_SVC_FUNC_CALL_COUNT: + args->a0 = STM32_SIP_SVC_FUNCTION_COUNT; + break; + case STM32_SIP_SVC_FUNC_VERSION: + args->a0 = STM32_SIP_SVC_VERSION_MAJOR; + args->a1 = STM32_SIP_SVC_VERSION_MINOR; + break; + case STM32_SIP_SVC_FUNC_UID: + args->a0 = STM32_SIP_SVC_UID_0; + args->a1 = STM32_SIP_SVC_UID_1; + args->a2 = STM32_SIP_SVC_UID_2; + args->a3 = STM32_SIP_SVC_UID_3; + break; + case STM32_SIP_SVC_FUNC_SCMI_AGENT0: + if (IS_ENABLED(CFG_STM32MP1_SCMI_SIP)) { + scmi_smt_fastcall_smc_entry(0); + args->a0 = STM32_SIP_SVC_OK; + } else { + args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; + } + break; + case STM32_SIP_SVC_FUNC_SCMI_AGENT1: + if (IS_ENABLED(CFG_STM32MP1_SCMI_SIP)) { + scmi_smt_fastcall_smc_entry(1); + args->a0 = STM32_SIP_SVC_OK; + } else { + args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; + } + break; + case STM32_SIP_SVC_FUNC_BSEC: + bsec_main(args); + break; + default: + return SM_HANDLER_PENDING_SMC; + } + + return SM_HANDLER_SMC_HANDLED; +} + +enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) +{ + struct thread_smc_args *args = (void *)&ctx->nsec.r0; + + if (!OPTEE_SMC_IS_FAST_CALL(args->a0)) + return SM_HANDLER_PENDING_SMC; + + switch (OPTEE_SMC_OWNER_NUM(args->a0)) { + case OPTEE_SMC_OWNER_SIP: + return sip_service(ctx, args); + default: + return SM_HANDLER_PENDING_SMC; + } +} diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk new file mode 100644 index 0000000..6e1abcb --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += . + +srcs-y += stm32mp1_svc_setup.c +srcs-$(CFG_STM32_BSEC_SIP) += bsec_svc.c diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c new file mode 100644 index 0000000..55f6d41 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/plat_tzc400.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2020, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_STM32MP15 +#define TZC_FILTERS_MASK GENMASK_32(1, 0) +#endif +#ifdef CFG_STM32MP13 +#define TZC_FILTERS_MASK GENMASK_32(0, 0) +#endif + +static enum itr_return tzc_it_handler(struct itr_handler *handler __unused) +{ + EMSG("TZC permission failure"); + tzc_fail_dump(); + + if (IS_ENABLED(CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION)) + panic(); + else + tzc_int_clear(); + + return ITRR_HANDLED; +} + +static struct itr_handler tzc_itr_handler = { + .it = STM32MP1_IRQ_TZC, + .handler = tzc_it_handler, +}; +DECLARE_KEEP_PAGER(tzc_itr_handler); + +static bool tzc_region_is_non_secure(unsigned int i, vaddr_t base, size_t size) +{ + struct tzc_region_config region_cfg = { }; + uint32_t ns_cpu_mask = TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID); + uint32_t filters_mask = TZC_FILTERS_MASK; + + if (tzc_get_region_config(i, ®ion_cfg)) + panic(); + + return region_cfg.base == base && region_cfg.top == (base + size - 1) && + region_cfg.sec_attr == TZC_REGION_S_NONE && + (region_cfg.ns_device_access & ns_cpu_mask) == ns_cpu_mask && + region_cfg.filters == filters_mask; +} + +static bool tzc_region_is_secure(unsigned int i, vaddr_t base, size_t size) +{ + struct tzc_region_config region_cfg = { }; + uint32_t filters_mask = TZC_FILTERS_MASK; + + if (tzc_get_region_config(i, ®ion_cfg)) + panic(); + + return region_cfg.base == base && region_cfg.top == (base + size - 1) && + region_cfg.sec_attr == TZC_REGION_S_RDWR && + region_cfg.ns_device_access == 0 && + region_cfg.filters == filters_mask; +} + +static TEE_Result init_stm32mp1_tzc(void) +{ + void *base = phys_to_virt(TZC_BASE, MEM_AREA_IO_SEC, 1); + unsigned int region_index = 1; + const uint64_t dram_start = DDR_BASE; + const uint64_t dram_end = dram_start + CFG_DRAM_SIZE; + const uint64_t tzdram_start = CFG_TZDRAM_START; + const uint64_t tzdram_size = CFG_TZDRAM_SIZE; + const uint64_t tzdram_end = tzdram_start + tzdram_size; + + assert(base); + + tzc_init((vaddr_t)base); + tzc_dump_state(); + + /* + * Early boot stage is in charge of configuring memory regions + * OP-TEE hence here only check this complies with static Core + * expectations. + */ + if (dram_start < tzdram_start) { + if (!tzc_region_is_non_secure(region_index, dram_start, + tzdram_start - dram_start)) + panic("Unexpected TZC area on non-secure region"); + + region_index++; + } + + if (!tzc_region_is_secure(region_index, tzdram_start, tzdram_size)) + panic("Unexpected TZC configuration on secure region"); + + if (tzdram_end < dram_end) { + region_index++; + + if (!tzc_region_is_non_secure(region_index, tzdram_end, + dram_end - tzdram_end)) + panic("Unexpected TZC area on non-secure region"); + } + + itr_add(&tzc_itr_handler); + itr_enable(tzc_itr_handler.it); + tzc_set_action(TZC_ACTION_INT); + + return TEE_SUCCESS; +} +driver_init(init_stm32mp1_tzc); diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h new file mode 100644 index 0000000..7c23833 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/platform_config.h @@ -0,0 +1,223 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2018, STMicroelectronics + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 32 + +/* Translation table */ +#ifdef CFG_WITH_LPAE +#define MAX_XLAT_TABLES 4 +#else +#define MAX_XLAT_TABLES 8 +#endif + +/* SoC interface registers base address ranges */ +#define APB1_BASE 0x40000000 +#define APB1_SIZE 0x0001d000 +#define APB2_BASE 0x44000000 +#define APB2_SIZE 0x00014000 +#define APB3_BASE 0x50020000 +#define APB3_SIZE 0x0000b000 +#define APB4_BASE 0x5a000000 +#define APB4_SIZE 0x00008000 +#define APB5_BASE 0x5c000000 +#define APB5_SIZE 0x0000b000 +#ifdef CFG_STM32MP13 +#define APB6_BASE 0x4c000000 +#define APB6_SIZE 0x0000d000 +#endif + +#define AHB4_BASE 0x50000000 +#define AHB4_SIZE 0x00020000 +#ifdef CFG_STM32MP13 +#define AHB5_BASE 0x54000000 +#define AHB5_SIZE 0x00008000 +#endif +#ifdef CFG_STM32MP15 +#define AHB5_BASE 0x54000000 +#define AHB5_SIZE 0x00005000 +#endif + +/* SoC interface registers base address */ +#define BSEC_BASE 0x5c005000 +#define ETZPC_BASE 0x5c007000 +#define CRYP1_BASE 0x54001000 +#define DDR_BASE 0xc0000000ul +#define GIC_BASE 0xa0021000ul +#define GPIOA_BASE 0x50002000 +#define GPIOB_BASE 0x50003000 +#define GPIOC_BASE 0x50004000 +#define GPIOD_BASE 0x50005000 +#define GPIOE_BASE 0x50006000 +#define GPIOF_BASE 0x50007000 +#define GPIOG_BASE 0x50008000 +#define GPIOH_BASE 0x50009000 +#define GPIOI_BASE 0x5000a000 +#define GPIOJ_BASE 0x5000b000 +#define GPIOK_BASE 0x5000c000 +#define GPIOZ_BASE 0x54004000 +#define HASH1_BASE 0x54002000 +#define I2C4_BASE 0x5c002000 +#define I2C5_BASE 0x40015000 +#define I2C6_BASE 0x5c009000 +#define IWDG1_BASE 0x5c003000 +#define IWDG2_BASE 0x5a002000 +#define PWR_BASE 0x50001000 +#define RCC_BASE 0x50000000 +#ifdef CFG_STM32MP13 +#define RNG1_BASE 0x54004000 +#endif +#ifdef CFG_STM32MP15 +#define RNG1_BASE 0x54003000 +#endif +#define RTC_BASE 0x5c004000 +#define SPI6_BASE 0x5c001000 +#define SYSCFG_BASE 0x50020000 +#ifdef CFG_STM32MP13 +#define SYSRAM_BASE 0x2ffe0000 +#endif +#ifdef CFG_STM32MP15 +#define SYSRAM_BASE 0x2ffc0000 +#endif +#define TAMP_BASE 0x5c00a000 +#define TZC_BASE 0x5c006000 +#ifdef CFG_STM32MP13 +#define UART1_BASE 0x4c000000 +#define UART2_BASE 0x4c001000 +#endif +#ifdef CFG_STM32MP15 +#define UART1_BASE 0x5c000000 +#define UART2_BASE 0x4000e000 +#endif +#define UART3_BASE 0x4000f000 +#define UART4_BASE 0x40010000 +#define UART5_BASE 0x40011000 +#define UART6_BASE 0x44003000 +#define UART7_BASE 0x40018000 +#define UART8_BASE 0x40019000 + +/* Console configuration */ +#define STM32MP1_DEBUG_USART_BASE UART4_BASE +#define GIC_SPI_UART4 84 + +#define CONSOLE_UART_BASE STM32MP1_DEBUG_USART_BASE +#define CONSOLE_UART_SIZE 1024 + +/* BSEC OTP resources */ +#define STM32MP1_OTP_MAX_ID 0x5FU +#define STM32MP1_UPPER_OTP_START 0x20U + +#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) + +/* Bit map for BSEC word CFG0_OTP */ +#ifdef CFG_STM32MP13 +#define CFG0_OTP_CLOSED_DEVICE U(0x3F) +#endif +#ifdef CFG_STM32MP15 +#define CFG0_OTP_CLOSED_DEVICE BIT(6) +#endif + +/* Bit map for BSEC word HW2_OTP */ +#define HW2_OTP_IWDG_HW_ENABLE_SHIFT U(3) +#define HW2_OTP_IWDG_FZ_STOP_SHIFT U(5) +#define HW2_OTP_IWDG_FZ_STANDBY_SHIFT U(7) + +/* GIC resources */ +#define GIC_SIZE 0x2000 +#define GICC_OFFSET 0x1000 +#define GICD_OFFSET 0x0000 + +#define GIC_NON_SEC_SGI_0 0 +#define GIC_SEC_SGI_0 8 +#define GIC_SEC_SGI_1 9 + +#define TARGET_CPU0_GIC_MASK BIT(0) +#define TARGET_CPU1_GIC_MASK BIT(1) +#define TARGET_CPUS_GIC_MASK GENMASK_32(CFG_TEE_CORE_NB_CORE - 1, 0) + +/* + * GPIO banks: 11 non secure banks (A to K) and 1 secure bank (Z) + * Bank register's base address is computed from the bank ID listed here. + */ +#define GPIOS_NSEC_COUNT 11 +#define GPIOS_NSEC_BASE GPIOA_BASE +#define GPIOS_NSEC_SIZE (GPIOS_NSEC_COUNT * SMALL_PAGE_SIZE) + +#define STM32MP1_GPIOZ_MAX_COUNT 1 +#define STM32MP1_GPIOZ_PIN_MAX_COUNT 8 + +#define GPIO_BANK_OFFSET 0x1000U + +/* Bank IDs used in GPIO driver API */ +#define GPIO_BANK_A 0U +#define GPIO_BANK_B 1U +#define GPIO_BANK_C 2U +#define GPIO_BANK_D 3U +#define GPIO_BANK_E 4U +#define GPIO_BANK_F 5U +#define GPIO_BANK_G 6U +#define GPIO_BANK_H 7U +#define GPIO_BANK_I 8U +#define GPIO_BANK_J 9U +#define GPIO_BANK_K 10U +#define GPIO_BANK_Z 25U + +/* TAMP resources */ +#define TAMP_BKP_REGISTER_OFF 0x100 +#define TAMP_BKP_REGISTER_COUNT U(32) + +#define TAMP_BKP_REGISTER_ZONE1_COUNT U(10) +#define TAMP_BKP_REGISTER_ZONE2_COUNT U(5) +#define TAMP_BKP_REGISTER_ZONE3_COUNT U(17) + +#if (TAMP_BKP_REGISTER_ZONE1_COUNT + TAMP_BKP_REGISTER_ZONE2_COUNT + \ + TAMP_BKP_REGISTER_ZONE3_COUNT != TAMP_BKP_REGISTER_COUNT) +#error Inconsistent TAMP backup register zone definition +#endif + +/* TZC resources */ +#define STM32MP1_IRQ_TZC 36 + +#define STM32MP1_TZC_A7_ID 0 +#define STM32MP1_TZC_M4_ID 1 +#define STM32MP1_TZC_LCD_ID 3 +#define STM32MP1_TZC_GPU_ID 4 +#define STM32MP1_TZC_MDMA_ID 5 +#define STM32MP1_TZC_DMA_ID 6 +#define STM32MP1_TZC_USB_HOST_ID 7 +#define STM32MP1_TZC_USB_OTG_ID 8 +#define STM32MP1_TZC_SDMMC_ID 9 +#define STM32MP1_TZC_ETH_ID 10 +#define STM32MP1_TZC_DAP_ID 15 + +/* USART/UART resources */ +#define USART1_BASE UART1_BASE +#define USART2_BASE UART2_BASE +#define USART3_BASE UART3_BASE +#define USART6_BASE UART6_BASE + +/* SYSRAM layout */ +#ifdef CFG_STM32MP13 +#define SYSRAM_SIZE 0x20000 +#else /* Assume CFG_STM32MP15 */ +#define SYSRAM_SIZE 0x40000 +#endif +#define SYSRAM_NS_SIZE (SYSRAM_SIZE - SYSRAM_SEC_SIZE) + +/* Non-secure SYSRAM must be above (higher addresses) secure SYSRAM */ +#if (CFG_STM32MP1_SCMI_SHM_BASE >= SYSRAM_BASE) && \ + ((CFG_STM32MP1_SCMI_SHM_BASE + CFG_STM32MP1_SCMI_SHM_SIZE) <= \ + (SYSRAM_BASE + SYSRAM_SIZE)) +#define SYSRAM_SEC_SIZE (CFG_STM32MP1_SCMI_SHM_BASE - SYSRAM_BASE) +#else +#define SYSRAM_SEC_SIZE SYSRAM_SIZE +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c new file mode 100644 index 0000000..f39c032 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/pm/psci.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2022, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONSOLE_FLUSH_DELAY_MS 10 + +/* + * SMP boot support and access to the mailbox + */ + +enum core_state_id { + CORE_OFF = 0, + CORE_RET, + CORE_AWAKE, + CORE_ON, +}; + +static enum core_state_id core_state[CFG_TEE_CORE_NB_CORE]; +static unsigned int __maybe_unused state_lock = SPINLOCK_UNLOCK; + +static uint32_t __maybe_unused lock_state_access(void) +{ + return may_spin_lock(&state_lock); +} + +static void __maybe_unused unlock_state_access(uint32_t exceptions) +{ + may_spin_unlock(&state_lock, exceptions); +} + +int psci_affinity_info(uint32_t affinity, uint32_t lowest_affinity_level) +{ + unsigned int pos = get_core_pos_mpidr(affinity); + + DMSG("core %zu, state %u", pos, core_state[pos]); + + if ((pos >= CFG_TEE_CORE_NB_CORE) || + (lowest_affinity_level > PSCI_AFFINITY_LEVEL_ON)) { + return PSCI_RET_INVALID_PARAMETERS; + } + + switch (core_state[pos]) { + case CORE_OFF: + case CORE_RET: + return PSCI_AFFINITY_LEVEL_OFF; + case CORE_AWAKE: + return PSCI_AFFINITY_LEVEL_ON_PENDING; + case CORE_ON: + return PSCI_AFFINITY_LEVEL_ON; + default: + panic(); + } +} + +#if CFG_TEE_CORE_NB_CORE == 1 +/* + * Function called when a CPU is booted through the OP-TEE. + * All cores shall register when online. + */ +void stm32mp_register_online_cpu(void) +{ + assert(core_state[0] == CORE_OFF); + core_state[0] = CORE_ON; +} +#else +static void __noreturn stm32_pm_cpu_power_down_wfi(void) +{ + dcache_op_level1(DCACHE_OP_CLEAN); + + io_write32(stm32_rcc_base() + RCC_MP_GRSTCSETR, + RCC_MP_GRSTCSETR_MPUP1RST); + + dsb(); + isb(); + wfi(); + panic(); +} + +void stm32mp_register_online_cpu(void) +{ + size_t pos = get_core_pos(); + uint32_t exceptions = lock_state_access(); + + if (pos == 0) { + assert(core_state[pos] == CORE_OFF); + } else { + if (core_state[pos] != CORE_AWAKE) { + core_state[pos] = CORE_OFF; + unlock_state_access(exceptions); + stm32_pm_cpu_power_down_wfi(); + panic(); + } + clk_disable(stm32mp_rcc_clock_id_to_clk(RTCAPB)); + } + + core_state[pos] = CORE_ON; + unlock_state_access(exceptions); +} + +#define GICD_SGIR 0xF00 +static void raise_sgi0_as_secure(void) +{ + dsb_ishst(); + io_write32(get_gicd_base() + GICD_SGIR, + GIC_NON_SEC_SGI_0 | SHIFT_U32(TARGET_CPU1_GIC_MASK, 16)); +} + +static void release_secondary_early_hpen(size_t __unused pos) +{ + /* Need to send SIG#0 over Group0 after individual core 1 reset */ + raise_sgi0_as_secure(); + udelay(20); + + io_write32(stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS), + TEE_LOAD_ADDR); + io_write32(stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER), + BOOT_API_A7_CORE1_MAGIC_NUMBER); + + dsb_ishst(); + itr_raise_sgi(GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK); +} + +/* Override default psci_cpu_on() with platform specific sequence */ +int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) +{ + size_t pos = get_core_pos_mpidr(core_id); + uint32_t exceptions = 0; + int rc = 0; + + if (!pos || pos >= CFG_TEE_CORE_NB_CORE) + return PSCI_RET_INVALID_PARAMETERS; + + DMSG("core %zu, ns_entry 0x%" PRIx32 ", state %u", + pos, entry, core_state[pos]); + + exceptions = lock_state_access(); + + switch (core_state[pos]) { + case CORE_ON: + rc = PSCI_RET_ALREADY_ON; + break; + case CORE_AWAKE: + rc = PSCI_RET_ON_PENDING; + break; + case CORE_RET: + rc = PSCI_RET_DENIED; + break; + case CORE_OFF: + core_state[pos] = CORE_AWAKE; + rc = PSCI_RET_SUCCESS; + break; + default: + panic(); + } + + unlock_state_access(exceptions); + + if (rc == PSCI_RET_SUCCESS) { + boot_set_core_ns_entry(pos, entry, context_id); + release_secondary_early_hpen(pos); + } + + return rc; +} + +/* Override default psci_cpu_off() with platform specific sequence */ +int psci_cpu_off(void) +{ + unsigned int pos = get_core_pos(); + uint32_t exceptions = 0; + + if (pos == 0) { + EMSG("PSCI_CPU_OFF not supported for core #0"); + return PSCI_RET_INTERNAL_FAILURE; + } + + DMSG("core %u", pos); + + exceptions = lock_state_access(); + + assert(core_state[pos] == CORE_ON); + core_state[pos] = CORE_OFF; + + unlock_state_access(exceptions); + + /* Enable BKPREG access for the disabled CPU */ + if (clk_enable(stm32mp_rcc_clock_id_to_clk(RTCAPB))) + panic(); + + thread_mask_exceptions(THREAD_EXCP_ALL); + stm32_pm_cpu_power_down_wfi(); + panic(); +} +#endif + +/* Override default psci_system_off() with platform specific sequence */ +void __noreturn psci_system_off(void) +{ + DMSG("core %u", get_core_pos()); + + if (TRACE_LEVEL >= TRACE_DEBUG) { + console_flush(); + mdelay(CONSOLE_FLUSH_DELAY_MS); + } + + if (stm32mp_with_pmic()) { + stm32mp_get_pmic(); + stpmic1_switch_off(); + udelay(100); + } + + panic(); +} + +/* Override default psci_system_reset() with platform specific sequence */ +void __noreturn psci_system_reset(void) +{ + rstctrl_assert(stm32mp_rcc_reset_id_to_rstctrl(MPSYST_R)); + udelay(100); + panic(); +} + +/* Override default psci_cpu_on() with platform supported features */ +int psci_features(uint32_t psci_fid) +{ + switch (psci_fid) { + case ARM_SMCCC_VERSION: + case PSCI_PSCI_FEATURES: + case PSCI_SYSTEM_RESET: + case PSCI_VERSION: + return PSCI_RET_SUCCESS; + case PSCI_CPU_ON: + case PSCI_CPU_OFF: + if (CFG_TEE_CORE_NB_CORE > 1) + return PSCI_RET_SUCCESS; + return PSCI_RET_NOT_SUPPORTED; + case PSCI_SYSTEM_OFF: + if (stm32mp_with_pmic()) + return PSCI_RET_SUCCESS; + return PSCI_RET_NOT_SUPPORTED; + default: + return PSCI_RET_NOT_SUPPORTED; + } +} + +/* Override default psci_version() to enable PSCI_VERSION_1_0 API */ +uint32_t psci_version(void) +{ + return PSCI_VERSION_1_0; +} diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/pm/sub.mk b/optee/optee_os/core/arch/arm/plat-stm32mp1/pm/sub.mk new file mode 100644 index 0000000..c8ae8f9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/pm/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_PSCI_ARM32) += psci.c diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/reset.S b/optee/optee_os/core/arch/arm/plat-stm32mp1/reset.S new file mode 100644 index 0000000..8a1ab64 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/reset.S @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2018, STMicroelectronics + */ + +#include +#include +#include + +.section .text +.balign 4 +.code 32 + +#define STM32MP1_NSACR_PRESERVE_MASK (0xfff << 20) + +FUNC plat_cpu_reset_early , : + ldr r0, =SCR_SIF + write_scr r0 + + read_nsacr r0 + mov_imm r1, STM32MP1_NSACR_PRESERVE_MASK + and r0, r0, r1 + write_nsacr r0 + + isb + bx lr +END_FUNC plat_cpu_reset_early diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c new file mode 100644 index 0000000..5c9d54b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/scmi_server.c @@ -0,0 +1,967 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2022, STMicroelectronics + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMEOUT_US_1MS 1000 + +#define SCMI_CLOCK_NAME_SIZE 16 +#define SCMI_RD_NAME_SIZE 16 +#define SCMI_VOLTD_NAME_SIZE 16 + +/* + * struct stm32_scmi_clk - Data for the exposed clock + * @clock_id: Clock identifier in RCC clock driver + * @name: Clock string ID exposed to channel + * @enabled: State of the SCMI clock + */ +struct stm32_scmi_clk { + unsigned long clock_id; + struct clk *clk; + const char *name; + bool enabled; +}; + +/* + * struct stm32_scmi_rd - Data for the exposed reset controller + * @reset_id: Reset identifier in RCC reset driver + * @name: Reset string ID exposed to channel + * @rstctrl: Reset controller device + */ +struct stm32_scmi_rd { + unsigned long reset_id; + const char *name; + struct rstctrl *rstctrl; +}; + +enum voltd_device { + VOLTD_PWR, + VOLTD_PMIC, +}; + +/* + * struct stm32_scmi_voltd - Data for the exposed voltage domains + * @name: Power regulator string ID exposed to channel + * @priv_id: Internal string ID for the regulator + * @priv_dev: Internal ID for the device implementing the regulator + */ +struct stm32_scmi_voltd { + const char *name; + const char *priv_id; + enum voltd_device priv_dev; + +}; + +/* Locate all non-secure SMT message buffers in last page of SYSRAM */ +#define SMT_BUFFER_BASE CFG_STM32MP1_SCMI_SHM_BASE + +#if (SMT_BUFFER_BASE + SMT_BUF_SLOT_SIZE > \ + CFG_STM32MP1_SCMI_SHM_BASE + CFG_STM32MP1_SCMI_SHM_SIZE) +#error "SCMI shared memory mismatch" +#endif + +#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \ + [(_scmi_id)] = { \ + .clock_id = (_id), \ + .name = (_name), \ + .enabled = (_init_enabled), \ + } + +#define RESET_CELL(_scmi_id, _id, _name) \ + [(_scmi_id)] = { \ + .reset_id = (_id), \ + .name = (_name), \ + } + +#define VOLTD_CELL(_scmi_id, _dev_id, _priv_id, _name) \ + [(_scmi_id)] = { \ + .priv_id = (_priv_id), \ + .priv_dev = (_dev_id), \ + .name = (_name), \ + } + +#ifdef CFG_STM32MP13 +static struct stm32_scmi_clk stm32_scmi_clock[] = { + CLOCK_CELL(CK_SCMI_HSE, CK_HSE, "ck_hse", true), + CLOCK_CELL(CK_SCMI_HSI, CK_HSI, "ck_hsi", true), + CLOCK_CELL(CK_SCMI_CSI, CK_CSI, "ck_csi", true), + CLOCK_CELL(CK_SCMI_LSE, CK_LSE, "ck_lse", true), + CLOCK_CELL(CK_SCMI_LSI, CK_LSI, "ck_lsi", true), + CLOCK_CELL(CK_SCMI_HSE_DIV2, CK_HSE_DIV2, "clk-hse-div2", true), + CLOCK_CELL(CK_SCMI_PLL2_Q, PLL2_Q, "pll2_q", true), + CLOCK_CELL(CK_SCMI_PLL2_R, PLL2_R, "pll2_r", true), + CLOCK_CELL(CK_SCMI_PLL3_P, PLL3_P, "pll3_p", true), + CLOCK_CELL(CK_SCMI_PLL3_Q, PLL3_Q, "pll3_q", true), + CLOCK_CELL(CK_SCMI_PLL3_R, PLL3_R, "pll3_r", true), + CLOCK_CELL(CK_SCMI_PLL4_P, PLL4_P, "pll4_p", true), + CLOCK_CELL(CK_SCMI_PLL4_Q, PLL4_Q, "pll4_q", true), + CLOCK_CELL(CK_SCMI_PLL4_R, PLL4_R, "pll4_r", true), + CLOCK_CELL(CK_SCMI_MPU, CK_MPU, "ck_mpu", true), + CLOCK_CELL(CK_SCMI_AXI, CK_AXI, "ck_axi", true), + CLOCK_CELL(CK_SCMI_MLAHB, CK_MLAHB, "ck_mlahb", true), + CLOCK_CELL(CK_SCMI_CKPER, CK_PER, "ck_per", true), + CLOCK_CELL(CK_SCMI_PCLK1, PCLK1, "pclk1", true), + CLOCK_CELL(CK_SCMI_PCLK2, PCLK2, "pclk2", true), + CLOCK_CELL(CK_SCMI_PCLK3, PCLK3, "pclk3", true), + CLOCK_CELL(CK_SCMI_PCLK4, PCLK4, "pclk4", true), + CLOCK_CELL(CK_SCMI_PCLK5, PCLK5, "pclk5", true), + CLOCK_CELL(CK_SCMI_PCLK6, PCLK6, "pclk6", true), + CLOCK_CELL(CK_SCMI_CKTIMG1, CK_TIMG1, "timg1_ck", true), + CLOCK_CELL(CK_SCMI_CKTIMG2, CK_TIMG2, "timg2_ck", true), + CLOCK_CELL(CK_SCMI_CKTIMG3, CK_TIMG3, "timg3_ck", true), + CLOCK_CELL(CK_SCMI_RTC, RTC, "ck_rtc", true), + CLOCK_CELL(CK_SCMI_RTCAPB, RTCAPB, "rtcapb", true), + CLOCK_CELL(CK_SCMI_BSEC, BSEC, "bsec", true), +}; +#endif + +#ifdef CFG_STM32MP15 +static struct stm32_scmi_clk stm32_scmi_clock[] = { + CLOCK_CELL(CK_SCMI_HSE, CK_HSE, "ck_hse", true), + CLOCK_CELL(CK_SCMI_HSI, CK_HSI, "ck_hsi", true), + CLOCK_CELL(CK_SCMI_CSI, CK_CSI, "ck_csi", true), + CLOCK_CELL(CK_SCMI_LSE, CK_LSE, "ck_lse", true), + CLOCK_CELL(CK_SCMI_LSI, CK_LSI, "ck_lsi", true), + CLOCK_CELL(CK_SCMI_PLL2_Q, PLL2_Q, "pll2_q", true), + CLOCK_CELL(CK_SCMI_PLL2_R, PLL2_R, "pll2_r", true), + CLOCK_CELL(CK_SCMI_MPU, CK_MPU, "ck_mpu", true), + CLOCK_CELL(CK_SCMI_AXI, CK_AXI, "ck_axi", true), + CLOCK_CELL(CK_SCMI_BSEC, BSEC, "bsec", true), + CLOCK_CELL(CK_SCMI_CRYP1, CRYP1, "cryp1", false), + CLOCK_CELL(CK_SCMI_GPIOZ, GPIOZ, "gpioz", false), + CLOCK_CELL(CK_SCMI_HASH1, HASH1, "hash1", false), + CLOCK_CELL(CK_SCMI_I2C4, I2C4_K, "i2c4_k", false), + CLOCK_CELL(CK_SCMI_I2C6, I2C6_K, "i2c6_k", false), + CLOCK_CELL(CK_SCMI_IWDG1, IWDG1, "iwdg1", false), + CLOCK_CELL(CK_SCMI_RNG1, RNG1_K, "rng1_k", true), + CLOCK_CELL(CK_SCMI_RTC, RTC, "ck_rtc", true), + CLOCK_CELL(CK_SCMI_RTCAPB, RTCAPB, "rtcapb", true), + CLOCK_CELL(CK_SCMI_SPI6, SPI6_K, "spi6_k", false), + CLOCK_CELL(CK_SCMI_USART1, USART1_K, "usart1_k", false), +}; +#endif + +#ifdef CFG_STM32MP13 +static struct stm32_scmi_rd stm32_scmi_reset_domain[] = { + RESET_CELL(RST_SCMI_LTDC, LTDC_R, "ltdc"), + RESET_CELL(RST_SCMI_MDMA, MDMA_R, "mdma"), +}; +#endif + +#ifdef CFG_STM32MP15 +static struct stm32_scmi_rd stm32_scmi_reset_domain[] = { + RESET_CELL(RST_SCMI_SPI6, SPI6_R, "spi6"), + RESET_CELL(RST_SCMI_I2C4, I2C4_R, "i2c4"), + RESET_CELL(RST_SCMI_I2C6, I2C6_R, "i2c6"), + RESET_CELL(RST_SCMI_USART1, USART1_R, "usart1"), + RESET_CELL(RST_SCMI_STGEN, STGEN_R, "stgen"), + RESET_CELL(RST_SCMI_GPIOZ, GPIOZ_R, "gpioz"), + RESET_CELL(RST_SCMI_CRYP1, CRYP1_R, "cryp1"), + RESET_CELL(RST_SCMI_HASH1, HASH1_R, "hash1"), + RESET_CELL(RST_SCMI_RNG1, RNG1_R, "rng1"), + RESET_CELL(RST_SCMI_MDMA, MDMA_R, "mdma"), + RESET_CELL(RST_SCMI_MCU, MCU_R, "mcu"), + RESET_CELL(RST_SCMI_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"), +}; +#endif + +#define PWR_REG11_NAME_ID "0" +#define PWR_REG18_NAME_ID "1" +#define PWR_USB33_NAME_ID "2" +#define PWR_SDMMC1_IO_NAME_ID "3" +#define PWR_SDMMC2_IO_NAME_ID "4" +#define PWR_VREFBUF_NAME_ID "5" + +#ifdef CFG_STM32MP13 +struct stm32_scmi_voltd scmi_voltage_domain[] = { + VOLTD_CELL(VOLTD_SCMI_REG11, VOLTD_PWR, PWR_REG11_NAME_ID, "reg11"), + VOLTD_CELL(VOLTD_SCMI_REG18, VOLTD_PWR, PWR_REG18_NAME_ID, "reg18"), + VOLTD_CELL(VOLTD_SCMI_USB33, VOLTD_PWR, PWR_USB33_NAME_ID, "usb33"), + VOLTD_CELL(VOLTD_SCMI_SDMMC1_IO, VOLTD_PWR, PWR_SDMMC1_IO_NAME_ID, + "sdmmc1"), + VOLTD_CELL(VOLTD_SCMI_SDMMC2_IO, VOLTD_PWR, PWR_SDMMC2_IO_NAME_ID, + "sdmmc2"), + VOLTD_CELL(VOLTD_SCMI_VREFBUF, VOLTD_PWR, PWR_VREFBUF_NAME_ID, + "vrefbuf"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK1, VOLTD_PMIC, "buck1", "buck1"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK2, VOLTD_PMIC, "buck2", "buck2"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK3, VOLTD_PMIC, "buck3", "buck3"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK4, VOLTD_PMIC, "buck4", "buck4"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO1, VOLTD_PMIC, "ldo1", "ldo1"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO2, VOLTD_PMIC, "ldo2", "ldo2"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO3, VOLTD_PMIC, "ldo3", "ldo3"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO4, VOLTD_PMIC, "ldo4", "ldo4"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO5, VOLTD_PMIC, "ldo5", "ldo5"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO6, VOLTD_PMIC, "ldo6", "ldo6"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_VREFDDR, VOLTD_PMIC, "vref_ddr", + "vref_ddr"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BOOST, VOLTD_PMIC, "boost", "bst_out"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW1, VOLTD_PMIC, "pwr_sw1", + "pwr_sw1"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW2, VOLTD_PMIC, "pwr_sw2", + "pwr_sw2"), +}; +#endif + +#ifdef CFG_STM32MP15 +struct stm32_scmi_voltd scmi_voltage_domain[] = { + VOLTD_CELL(VOLTD_SCMI_REG11, VOLTD_PWR, PWR_REG11_NAME_ID, "reg11"), + VOLTD_CELL(VOLTD_SCMI_REG18, VOLTD_PWR, PWR_REG18_NAME_ID, "reg18"), + VOLTD_CELL(VOLTD_SCMI_USB33, VOLTD_PWR, PWR_USB33_NAME_ID, "usb33"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK1, VOLTD_PMIC, "buck1", "vddcore"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK2, VOLTD_PMIC, "buck2", "vdd_ddr"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK3, VOLTD_PMIC, "buck3", "vdd"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK4, VOLTD_PMIC, "buck4", "v3v3"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO1, VOLTD_PMIC, "ldo1", "v1v8_audio"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO2, VOLTD_PMIC, "ldo2", "v3v3_hdmi"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO3, VOLTD_PMIC, "ldo3", "vtt_ddr"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO4, VOLTD_PMIC, "ldo4", "vdd_usb"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO5, VOLTD_PMIC, "ldo5", "vdda"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO6, VOLTD_PMIC, "ldo6", "v1v2_hdmi"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_VREFDDR, VOLTD_PMIC, "vref_ddr", + "vref_ddr"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_BOOST, VOLTD_PMIC, "boost", "bst_out"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW1, VOLTD_PMIC, "pwr_sw1", + "vbus_otg"), + VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW2, VOLTD_PMIC, "pwr_sw2", + "vbus_sw"), +}; +#endif + +struct channel_resources { + struct scmi_msg_channel *channel; + struct stm32_scmi_clk *clock; + size_t clock_count; + struct stm32_scmi_rd *rd; + size_t rd_count; + struct stm32_scmi_voltd *voltd; + size_t voltd_count; +}; + +static const struct channel_resources scmi_channel[] = { + [0] = { + .channel = &(struct scmi_msg_channel){ + .shm_addr = { .pa = SMT_BUFFER_BASE }, + .shm_size = SMT_BUF_SLOT_SIZE, + }, + .clock = stm32_scmi_clock, + .clock_count = ARRAY_SIZE(stm32_scmi_clock), + .rd = stm32_scmi_reset_domain, + .rd_count = ARRAY_SIZE(stm32_scmi_reset_domain), + .voltd = scmi_voltage_domain, + .voltd_count = ARRAY_SIZE(scmi_voltage_domain), + }, +}; + +static const struct channel_resources *find_resource(unsigned int channel_id) +{ + assert(channel_id < ARRAY_SIZE(scmi_channel)); + + return scmi_channel + channel_id; +} + +struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id) +{ + const size_t max_id = ARRAY_SIZE(scmi_channel); + unsigned int confined_id = confine_array_index(channel_id, max_id); + + if (channel_id >= max_id) + return NULL; + + return find_resource(confined_id)->channel; +} + +static size_t __maybe_unused plat_scmi_protocol_count_paranoid(void) +{ + unsigned int n = 0; + unsigned int count = 0; + const size_t channel_count = ARRAY_SIZE(scmi_channel); + + for (n = 0; n < channel_count; n++) + if (scmi_channel[n].clock_count) + break; + if (n < channel_count) + count++; + + for (n = 0; n < channel_count; n++) + if (scmi_channel[n].rd_count) + break; + if (n < channel_count) + count++; + + for (n = 0; n < channel_count; n++) + if (scmi_channel[n].voltd_count) + break; + if (n < channel_count) + count++; + + return count; +} + +static const char vendor[] = "ST"; +static const char sub_vendor[] = ""; + +const char *plat_scmi_vendor_name(void) +{ + return vendor; +} + +const char *plat_scmi_sub_vendor_name(void) +{ + return sub_vendor; +} + +/* Currently supporting Clocks and Reset Domains */ +static const uint8_t plat_protocol_list[] = { + SCMI_PROTOCOL_ID_CLOCK, + SCMI_PROTOCOL_ID_RESET_DOMAIN, + SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, + 0 /* Null termination */ +}; + +size_t plat_scmi_protocol_count(void) +{ + const size_t count = ARRAY_SIZE(plat_protocol_list) - 1; + + assert(count == plat_scmi_protocol_count_paranoid()); + + return count; +} + +const uint8_t *plat_scmi_protocol_list(unsigned int channel_id __unused) +{ + assert(plat_scmi_protocol_count_paranoid() == + (ARRAY_SIZE(plat_protocol_list) - 1)); + + return plat_protocol_list; +} + +/* + * Platform SCMI clocks + */ +static struct stm32_scmi_clk *find_clock(unsigned int channel_id, + unsigned int scmi_id) +{ + const struct channel_resources *resource = find_resource(channel_id); + size_t n = 0; + + if (resource) { + for (n = 0; n < resource->clock_count; n++) + if (n == scmi_id) + return &resource->clock[n]; + } + + return NULL; +} + +size_t plat_scmi_clock_count(unsigned int channel_id) +{ + const struct channel_resources *resource = find_resource(channel_id); + + if (!resource) + return 0; + + return resource->clock_count; +} + +const char *plat_scmi_clock_get_name(unsigned int channel_id, + unsigned int scmi_id) +{ + struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); + + if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id)) + return NULL; + + return clock->name; +} + +int32_t plat_scmi_clock_rates_array(unsigned int channel_id, + unsigned int scmi_id, size_t start_index, + unsigned long *array, size_t *nb_elts) +{ + struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); + + if (!clock) + return SCMI_NOT_FOUND; + + if (!stm32mp_nsec_can_access_clock(clock->clock_id)) + return SCMI_DENIED; + + /* Exposed clocks are currently fixed rate clocks */ + if (start_index) + return SCMI_INVALID_PARAMETERS; + + if (!array) + *nb_elts = 1; + else if (*nb_elts == 1) + *array = clk_get_rate(clock->clk); + else + return SCMI_GENERIC_ERROR; + + return SCMI_SUCCESS; +} + +unsigned long plat_scmi_clock_get_rate(unsigned int channel_id, + unsigned int scmi_id) +{ + struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); + + if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id)) + return 0; + + return clk_get_rate(clock->clk); +} + +int32_t plat_scmi_clock_get_state(unsigned int channel_id, unsigned int scmi_id) +{ + struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); + + if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id)) + return 0; + + return (int32_t)clock->enabled; +} + +int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id, + bool enable_not_disable) +{ + struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); + + if (!clock) + return SCMI_NOT_FOUND; + + if (!stm32mp_nsec_can_access_clock(clock->clock_id)) + return SCMI_DENIED; + + if (enable_not_disable) { + if (!clock->enabled) { + DMSG("SCMI clock %u enable", scmi_id); + clk_enable(clock->clk); + clock->enabled = true; + } + } else { + if (clock->enabled) { + DMSG("SCMI clock %u disable", scmi_id); + clk_disable(clock->clk); + clock->enabled = false; + } + } + + return SCMI_SUCCESS; +} + +/* + * Platform SCMI reset domains + */ +static struct stm32_scmi_rd *find_rd(unsigned int channel_id, + unsigned int scmi_id) +{ + const struct channel_resources *resource = find_resource(channel_id); + size_t n = 0; + + if (resource) { + for (n = 0; n < resource->rd_count; n++) + if (n == scmi_id) + return &resource->rd[n]; + } + + return NULL; +} + +const char *plat_scmi_rd_get_name(unsigned int channel_id, unsigned int scmi_id) +{ + const struct stm32_scmi_rd *rd = find_rd(channel_id, scmi_id); + + if (!rd) + return NULL; + + return rd->name; +} + +size_t plat_scmi_rd_count(unsigned int channel_id) +{ + const struct channel_resources *resource = find_resource(channel_id); + + if (!resource) + return 0; + + return resource->rd_count; +} + +int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id, + uint32_t state) +{ + const struct stm32_scmi_rd *rd = find_rd(channel_id, scmi_id); + + if (!rd) + return SCMI_NOT_FOUND; + + if (!rd->rstctrl || !stm32mp_nsec_can_access_reset(rd->reset_id)) + return SCMI_DENIED; + assert(rd->rstctrl); + +#ifdef CFG_STM32MP15 + if (rd->reset_id == MCU_HOLD_BOOT_R) + return SCMI_NOT_SUPPORTED; +#endif + + /* Supports only reset with context loss */ + if (state) + return SCMI_NOT_SUPPORTED; + + DMSG("SCMI reset %u cycle", scmi_id); + + if (rstctrl_assert_to(rd->rstctrl, TIMEOUT_US_1MS)) + return SCMI_HARDWARE_ERROR; + + if (rstctrl_deassert_to(rd->rstctrl, TIMEOUT_US_1MS)) + return SCMI_HARDWARE_ERROR; + + return SCMI_SUCCESS; +} + +int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id, + bool assert_not_deassert) +{ + const struct stm32_scmi_rd *rd = find_rd(channel_id, scmi_id); + TEE_Result res = TEE_ERROR_GENERIC; + + if (!rd) + return SCMI_NOT_FOUND; + + if (!rd->rstctrl || !stm32mp_nsec_can_access_reset(rd->reset_id)) + return SCMI_DENIED; + assert(rd->rstctrl); + + if (assert_not_deassert) { + DMSG("SCMI reset %u set", scmi_id); + res = rstctrl_assert(rd->rstctrl); + } else { + DMSG("SCMI reset %u release", scmi_id); + res = rstctrl_deassert(rd->rstctrl); + } + + if (res) + return SCMI_HARDWARE_ERROR; + + return SCMI_SUCCESS; +} + +/* + * Platform SCMI voltage domains + */ +static struct stm32_scmi_voltd *find_voltd(unsigned int channel_id, + unsigned int scmi_id) +{ + const struct channel_resources *resource = find_resource(channel_id); + size_t n = 0; + + if (resource) { + for (n = 0; n < resource->voltd_count; n++) + if (n == scmi_id) + return &resource->voltd[n]; + } + + return NULL; +} + +size_t plat_scmi_voltd_count(unsigned int channel_id) +{ + const struct channel_resources *resource = find_resource(channel_id); + + if (!resource) + return 0; + + return resource->voltd_count; +} + +const char *plat_scmi_voltd_get_name(unsigned int channel_id, + unsigned int scmi_id) +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + + /* Currently non-secure is allowed to access all PWR regulators */ + if (!voltd) + return NULL; + + return voltd->name; +} + +static enum pwr_regulator pwr_scmi_to_regu_id(struct stm32_scmi_voltd *voltd) +{ + if (!strcmp(voltd->priv_id, PWR_REG11_NAME_ID)) + return PWR_REG11; + if (!strcmp(voltd->priv_id, PWR_REG18_NAME_ID)) + return PWR_REG18; + if (!strcmp(voltd->priv_id, PWR_USB33_NAME_ID)) + return PWR_USB33; + + panic(); +} + +static long pwr_get_level(struct stm32_scmi_voltd *voltd) +{ + enum pwr_regulator regu_id = pwr_scmi_to_regu_id(voltd); + + return (long)stm32mp1_pwr_regulator_mv(regu_id) * 1000; +} + +static int32_t pwr_set_level(struct stm32_scmi_voltd *voltd, long level_uv) +{ + if (level_uv != pwr_get_level(voltd)) + return SCMI_INVALID_PARAMETERS; + + return SCMI_SUCCESS; +} + +static int32_t pwr_describe_levels(struct stm32_scmi_voltd *voltd, + size_t start_index, long *microvolt, + size_t *nb_elts) +{ + if (start_index) + return SCMI_INVALID_PARAMETERS; + + if (!microvolt) { + *nb_elts = 1; + return SCMI_SUCCESS; + } + + if (*nb_elts < 1) + return SCMI_GENERIC_ERROR; + + *nb_elts = 1; + *microvolt = pwr_get_level(voltd); + + return SCMI_SUCCESS; +} + +static uint32_t pwr_get_state(struct stm32_scmi_voltd *voltd) +{ + enum pwr_regulator regu_id = pwr_scmi_to_regu_id(voltd); + + if (stm32mp1_pwr_regulator_is_enabled(regu_id)) + return SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON; + + return SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF; +} + +static void pwr_set_state(struct stm32_scmi_voltd *voltd, bool enable) +{ + enum pwr_regulator regu_id = pwr_scmi_to_regu_id(voltd); + + DMSG("%sable PWR %s (was %s)", enable ? "En" : "Dis", voltd->name, + stm32mp1_pwr_regulator_is_enabled(regu_id) ? "on" : "off"); + + stm32mp1_pwr_regulator_set_state(regu_id, enable); +} + +static int32_t pmic_describe_levels(struct stm32_scmi_voltd *voltd, + size_t start_index, long *microvolt, + size_t *nb_elts) +{ + const uint16_t *levels = NULL; + size_t full_count = 0; + size_t out_count = 0; + size_t i = 0; + + if (!stm32mp_nsec_can_access_pmic_regu(voltd->priv_id)) + return SCMI_DENIED; + + stpmic1_regulator_levels_mv(voltd->priv_id, &levels, &full_count); + + if (!microvolt) { + *nb_elts = full_count - start_index; + return SCMI_SUCCESS; + } + + if (SUB_OVERFLOW(full_count, start_index, &out_count)) + return SCMI_GENERIC_ERROR; + + out_count = MIN(out_count, *nb_elts); + + FMSG("%zu levels: start %zu requested %zu output %zu", + full_count, start_index, *nb_elts, out_count); + + for (i = 0; i < out_count; i++) + microvolt[i] = levels[start_index + i] * 1000; + + *nb_elts = out_count; + + return SCMI_SUCCESS; +} + +static long pmic_get_level(struct stm32_scmi_voltd *voltd) +{ + unsigned long level_mv = 0; + + if (!stm32mp_nsec_can_access_pmic_regu(voltd->priv_id)) + return 0; + + stm32mp_get_pmic(); + level_mv = stpmic1_regulator_voltage_get(voltd->priv_id); + stm32mp_put_pmic(); + + return (long)level_mv * 1000; +} + +static int32_t pmic_set_level(struct stm32_scmi_voltd *voltd, long level_uv) +{ + int rc = 0; + unsigned int level_mv = 0; + + if (!stm32mp_nsec_can_access_pmic_regu(voltd->priv_id)) + return SCMI_DENIED; + + if (level_uv < 0 || level_uv > (UINT16_MAX * 1000)) + return SCMI_INVALID_PARAMETERS; + + level_mv = (unsigned int)level_uv / 1000; + + DMSG("Set STPMIC1 regulator %s level to %dmV", voltd->name, level_mv); + + stm32mp_get_pmic(); + rc = stpmic1_regulator_voltage_set(voltd->priv_id, level_mv); + stm32mp_put_pmic(); + + return rc ? SCMI_GENERIC_ERROR : SCMI_SUCCESS; +} + +static uint32_t pmic_get_state(struct stm32_scmi_voltd *voltd) +{ + bool enabled = false; + + if (!stm32mp_nsec_can_access_pmic_regu(voltd->priv_id)) + return SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF; + + stm32mp_get_pmic(); + enabled = stpmic1_is_regulator_enabled(voltd->priv_id); + stm32mp_put_pmic(); + + if (enabled) + return SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON; + + return SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF; +} + +static int32_t pmic_set_state(struct stm32_scmi_voltd *voltd, bool enable) +{ + int rc = 0; + + if (!stm32mp_nsec_can_access_pmic_regu(voltd->priv_id)) + return SCMI_DENIED; + + stm32mp_get_pmic(); + + DMSG("%sable STPMIC1 %s (was %s)", enable ? "En" : "Dis", voltd->name, + stpmic1_is_regulator_enabled(voltd->priv_id) ? "on" : "off"); + + if (enable) + rc = stpmic1_regulator_enable(voltd->priv_id); + else + rc = stpmic1_regulator_disable(voltd->priv_id); + + stm32mp_put_pmic(); + + return rc ? SCMI_GENERIC_ERROR : SCMI_SUCCESS; +} + +int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, + unsigned int scmi_id, size_t start_index, + long *levels, size_t *nb_elts) + +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + + if (!voltd) + return SCMI_NOT_FOUND; + + switch (voltd->priv_dev) { + case VOLTD_PWR: + return pwr_describe_levels(voltd, start_index, levels, nb_elts); + case VOLTD_PMIC: + return pmic_describe_levels(voltd, start_index, levels, + nb_elts); + default: + return SCMI_GENERIC_ERROR; + } +} + +int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id, + long *level) +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + long voltage = 0; + + if (!voltd) + return SCMI_INVALID_PARAMETERS; + + switch (voltd->priv_dev) { + case VOLTD_PWR: + *level = pwr_get_level(voltd); + return SCMI_SUCCESS; + case VOLTD_PMIC: + voltage = pmic_get_level(voltd); + if (voltage > 0) { + *level = voltage; + return SCMI_SUCCESS; + } else { + return SCMI_GENERIC_ERROR; + } + default: + panic(); + } +} + +int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, + long level) +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + + if (!voltd) + return SCMI_NOT_FOUND; + + switch (voltd->priv_dev) { + case VOLTD_PWR: + return pwr_set_level(voltd, level); + case VOLTD_PMIC: + return pmic_set_level(voltd, level); + default: + return SCMI_GENERIC_ERROR; + } +} + +int32_t plat_scmi_voltd_get_config(unsigned int channel_id, + unsigned int scmi_id, uint32_t *config) +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + + if (!voltd) + return SCMI_NOT_FOUND; + + switch (voltd->priv_dev) { + case VOLTD_PWR: + *config = pwr_get_state(voltd); + break; + case VOLTD_PMIC: + *config = pmic_get_state(voltd); + break; + default: + return SCMI_GENERIC_ERROR; + } + + return SCMI_SUCCESS; +} + +int32_t plat_scmi_voltd_set_config(unsigned int channel_id, + unsigned int scmi_id, uint32_t config) +{ + struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); + int32_t rc = SCMI_SUCCESS; + + if (!voltd) + return SCMI_NOT_FOUND; + + switch (voltd->priv_dev) { + case VOLTD_PWR: + pwr_set_state(voltd, config); + break; + case VOLTD_PMIC: + rc = pmic_set_state(voltd, config); + break; + default: + return SCMI_GENERIC_ERROR; + } + + return rc; +} + +/* + * Initialize platform SCMI resources + */ +static TEE_Result stm32mp1_init_scmi_server(void) +{ + size_t i = 0; + size_t j = 0; + + for (i = 0; i < ARRAY_SIZE(scmi_channel); i++) { + const struct channel_resources *res = scmi_channel + i; + struct scmi_msg_channel *chan = res->channel; + + /* Enforce non-secure shm mapped as device memory */ + chan->shm_addr.va = (vaddr_t)phys_to_virt(chan->shm_addr.pa, + MEM_AREA_IO_NSEC, 1); + assert(chan->shm_addr.va); + + scmi_smt_init_agent_channel(chan); + + for (j = 0; j < res->clock_count; j++) { + struct stm32_scmi_clk *clk = &res->clock[j]; + + if (!clk->name || + strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE) + panic("SCMI clock name invalid"); + + clk->clk = stm32mp_rcc_clock_id_to_clk(clk->clock_id); + assert(clk->clk); + + /* Sync SCMI clocks with their targeted initial state */ + if (clk->enabled && + stm32mp_nsec_can_access_clock(clk->clock_id)) + clk_enable(clk->clk); + } + + for (j = 0; j < res->rd_count; j++) { + struct stm32_scmi_rd *rd = &res->rd[j]; + struct rstctrl *rstctrl = NULL; + + if (!rd->name || + strlen(rd->name) >= SCMI_RD_NAME_SIZE) + panic("SCMI reset domain name invalid"); + + if (stm32mp_nsec_can_access_clock(rd->reset_id)) + continue; + + rstctrl = stm32mp_rcc_reset_id_to_rstctrl(rd->reset_id); + assert(rstctrl); + if (rstctrl_get_exclusive(rstctrl)) + continue; + + rd->rstctrl = rstctrl; + } + + for (j = 0; j < res->voltd_count; j++) { + struct stm32_scmi_voltd *voltd = &res->voltd[j]; + + if (!voltd->name || + strlen(voltd->name) >= SCMI_VOLTD_NAME_SIZE) + panic("SCMI voltage domain name invalid"); + } + } + + return TEE_SUCCESS; +} + +driver_init_late(stm32mp1_init_scmi_server); diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/scripts/stm32image.py b/optee/optee_os/core/arch/arm/plat-stm32mp1/scripts/stm32image.py new file mode 100755 index 0000000..4067fd7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/scripts/stm32image.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2017-2018, STMicroelectronics +# +import argparse +import struct +import mmap + +header_size = 256 +hdr_magic_number = 0x324D5453 # magic ='S' 'T' 'M' 0x32 +hdr_header_ver_variant = 0 +hdr_header_ver_minor = 0 +hdr_header_ver_major = 1 +hdr_version_number = 0 +hdr_option_flags = 1 # bit0=1 no signature +hdr_edcsa_algo = 1 + + +def get_size(file): + file.seek(0, 2) # End of the file + size = file.tell() + return size + + +def stm32image_checksum(dest_fd, sizedest): + csum = 0 + if sizedest < header_size: + return 0 + dest_fd.seek(header_size, 0) + length = sizedest - header_size + while length > 0: + csum += ord(dest_fd.read(1)) + length -= 1 + return csum + + +def stm32image_set_header(dest_fd, load, entry, bintype): + sizedest = get_size(dest_fd) + + checksum = stm32image_checksum(dest_fd, sizedest) + + dest_fd.seek(0, 0) + + # Magic number + dest_fd.write(struct.pack(' 0: + mmsrc = mmap.mmap(src_fd.fileno(), 0, access=mmap.ACCESS_READ) + dest_fd.write(mmsrc[:sizesrc]) + mmsrc.close() + + src_fd.close() + + stm32image_set_header(dest_fd, load, entry, bintype) + + dest_fd.close() + + +def int_parse(str): + return int(str, 0) + + +def get_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--source', + required=True, + help='Source file') + + parser.add_argument('--dest', + required=True, + help='Destination file') + + parser.add_argument('--load', + required=True, type=int_parse, + help='Load address') + + parser.add_argument('--entry', + required=True, type=int_parse, + help='Entry point') + + parser.add_argument('--bintype', + required=True, type=int_parse, + help='Binary identification') + + return parser.parse_args() + + +def main(): + args = get_args() + source_file = args.source + destination_file = args.dest + load_address = args.load + entry_point = args.entry + binary_type = args.bintype + + stm32image_create_header_file(source_file, + destination_file, + load_address, + entry_point, + binary_type) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c b/optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c new file mode 100644 index 0000000..2c4ce9e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/shared_resources.c @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2022, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Once one starts to get the resource registering state, one cannot register + * new resources. This ensures resource state cannot change. + */ +static bool registering_locked; + +/* + * Shared peripherals and resources registration + * + * Each resource assignation is stored in a table. The state defaults + * to PERIPH_UNREGISTERED if the resource is not explicitly assigned. + * + * Resource driver that as not embedded (a.k.a their related CFG_xxx build + * directive is disabled) are assigned to the non-secure world. + * + * Each IO of the GPIOZ IO can be secure or non-secure. + * + * It is the platform responsibility the ensure resource assignation + * matches the access permission firewalls configuration. + */ +enum shres_state { + SHRES_UNREGISTERED = 0, + SHRES_SECURE, + SHRES_NON_SECURE, +}; + +/* Use a byte array to store each resource state */ +static uint8_t shres_state[STM32MP1_SHRES_COUNT] = { +#if !defined(CFG_STM32_IWDG) + [STM32MP1_SHRES_IWDG1] = SHRES_NON_SECURE, +#endif +#if !defined(CFG_STM32_UART) + [STM32MP1_SHRES_USART1] = SHRES_NON_SECURE, +#endif +#if !defined(CFG_STM32_SPI) + [STM32MP1_SHRES_SPI6] = SHRES_NON_SECURE, +#endif +#if !defined(CFG_STM32_I2C) + [STM32MP1_SHRES_I2C4] = SHRES_NON_SECURE, + [STM32MP1_SHRES_I2C6] = SHRES_NON_SECURE, +#endif +#if !defined(CFG_STM32_GPIO) + [STM32MP1_SHRES_GPIOZ(0)] = SHRES_NON_SECURE, + [STM32MP1_SHRES_GPIOZ(1)] = SHRES_NON_SECURE, + [STM32MP1_SHRES_GPIOZ(2)] = SHRES_NON_SECURE, + [STM32MP1_SHRES_GPIOZ(3)] = SHRES_NON_SECURE, + [STM32MP1_SHRES_GPIOZ(4)] = SHRES_NON_SECURE, + [STM32MP1_SHRES_GPIOZ(5)] = SHRES_NON_SECURE, + [STM32MP1_SHRES_GPIOZ(6)] = SHRES_NON_SECURE, + [STM32MP1_SHRES_GPIOZ(7)] = SHRES_NON_SECURE, +#endif +#if !defined(CFG_STM32_RNG) + [STM32MP1_SHRES_RNG1] = SHRES_NON_SECURE, +#endif +#if !defined(CFG_STM32_HASH) + [STM32MP1_SHRES_HASH1] = SHRES_NON_SECURE, +#endif +#if !defined(CFG_STM32_CRYP) + [STM32MP1_SHRES_CRYP1] = SHRES_NON_SECURE, +#endif +#if !defined(CFG_STM32_RTC) + [STM32MP1_SHRES_RTC] = SHRES_NON_SECURE, +#endif +}; + +static const char __maybe_unused *shres2str_id_tbl[STM32MP1_SHRES_COUNT] = { + [STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0", + [STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1", + [STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2", + [STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3", + [STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4", + [STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5", + [STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6", + [STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7", + [STM32MP1_SHRES_IWDG1] = "IWDG1", + [STM32MP1_SHRES_USART1] = "USART1", + [STM32MP1_SHRES_SPI6] = "SPI6", + [STM32MP1_SHRES_I2C4] = "I2C4", + [STM32MP1_SHRES_RNG1] = "RNG1", + [STM32MP1_SHRES_HASH1] = "HASH1", + [STM32MP1_SHRES_CRYP1] = "CRYP1", + [STM32MP1_SHRES_I2C6] = "I2C6", + [STM32MP1_SHRES_RTC] = "RTC", + [STM32MP1_SHRES_MCU] = "MCU", + [STM32MP1_SHRES_PLL3] = "PLL3", + [STM32MP1_SHRES_MDMA] = "MDMA", +}; + +static __maybe_unused const char *shres2str_id(enum stm32mp_shres id) +{ + return shres2str_id_tbl[id]; +} + +static const char *shres2str_state_tbl[4] __maybe_unused = { + [SHRES_UNREGISTERED] = "unregistered", + [SHRES_NON_SECURE] = "non-secure", + [SHRES_SECURE] = "secure", +}; + +static __maybe_unused const char *shres2str_state(enum shres_state id) +{ + return shres2str_state_tbl[id]; +} + +/* GPIOZ bank pin count depends on SoC variants */ +/* A light count routine for unpaged context to not depend on DTB support */ +static int gpioz_nbpin = -1; + +static unsigned int get_gpioz_nbpin(void) +{ + if (gpioz_nbpin < 0) + panic(); + + return gpioz_nbpin; +} + +static TEE_Result set_gpioz_nbpin_from_dt(void) +{ + void *fdt = get_embedded_dt(); + int node = fdt_node_offset_by_compatible(fdt, -1, + "st,stm32mp157-z-pinctrl"); + int count = stm32_get_gpio_count(fdt, node, GPIO_BANK_Z); + + if (count < 0 || count > STM32MP1_GPIOZ_PIN_MAX_COUNT) + panic(); + + gpioz_nbpin = count; + + return TEE_SUCCESS; +} +/* Get GPIOZ pin count before drivers initialization, hence service_init() */ +service_init(set_gpioz_nbpin_from_dt); + +static void register_periph(enum stm32mp_shres id, enum shres_state state) +{ + assert(id < STM32MP1_SHRES_COUNT && + (state == SHRES_SECURE || state == SHRES_NON_SECURE)); + + if (registering_locked) + panic(); + + if (shres_state[id] != SHRES_UNREGISTERED && + shres_state[id] != state) { + DMSG("Cannot change %s from %s to %s", + shres2str_id(id), + shres2str_state(shres_state[id]), + shres2str_state(state)); + panic(); + } + + if (shres_state[id] == SHRES_UNREGISTERED) + DMSG("Register %s as %s", + shres2str_id(id), shres2str_state(state)); + + switch (id) { + case STM32MP1_SHRES_GPIOZ(0): + case STM32MP1_SHRES_GPIOZ(1): + case STM32MP1_SHRES_GPIOZ(2): + case STM32MP1_SHRES_GPIOZ(3): + case STM32MP1_SHRES_GPIOZ(4): + case STM32MP1_SHRES_GPIOZ(5): + case STM32MP1_SHRES_GPIOZ(6): + case STM32MP1_SHRES_GPIOZ(7): + if ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin()) { + EMSG("Invalid GPIO %u >= %u", + id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin()); + panic(); + } + break; + default: + break; + } + + shres_state[id] = state; + + /* Explore clock tree to lock secure clock dependencies */ + if (state == SHRES_SECURE) { + switch (id) { + case STM32MP1_SHRES_GPIOZ(0): + case STM32MP1_SHRES_GPIOZ(1): + case STM32MP1_SHRES_GPIOZ(2): + case STM32MP1_SHRES_GPIOZ(3): + case STM32MP1_SHRES_GPIOZ(4): + case STM32MP1_SHRES_GPIOZ(5): + case STM32MP1_SHRES_GPIOZ(6): + case STM32MP1_SHRES_GPIOZ(7): + stm32mp_register_clock_parents_secure(GPIOZ); + break; + case STM32MP1_SHRES_IWDG1: + stm32mp_register_clock_parents_secure(IWDG1); + break; + case STM32MP1_SHRES_USART1: + stm32mp_register_clock_parents_secure(USART1_K); + break; + case STM32MP1_SHRES_SPI6: + stm32mp_register_clock_parents_secure(SPI6_K); + break; + case STM32MP1_SHRES_I2C4: + stm32mp_register_clock_parents_secure(I2C4_K); + break; + case STM32MP1_SHRES_RNG1: + stm32mp_register_clock_parents_secure(RNG1_K); + break; + case STM32MP1_SHRES_HASH1: + stm32mp_register_clock_parents_secure(HASH1); + break; + case STM32MP1_SHRES_CRYP1: + stm32mp_register_clock_parents_secure(CRYP1); + break; + case STM32MP1_SHRES_I2C6: + stm32mp_register_clock_parents_secure(I2C6_K); + break; + case STM32MP1_SHRES_RTC: + stm32mp_register_clock_parents_secure(RTC); + break; + default: + /* No expected resource dependency */ + break; + } + } +} + +/* Register resource by ID */ +void stm32mp_register_secure_periph(enum stm32mp_shres id) +{ + register_periph(id, SHRES_SECURE); +} + +void stm32mp_register_non_secure_periph(enum stm32mp_shres id) +{ + register_periph(id, SHRES_NON_SECURE); +} + +/* Register resource by IO memory base address */ +static void register_periph_iomem(vaddr_t base, enum shres_state state) +{ + enum stm32mp_shres id = STM32MP1_SHRES_COUNT; + + switch (base) { + case IWDG1_BASE: + id = STM32MP1_SHRES_IWDG1; + break; + case USART1_BASE: + id = STM32MP1_SHRES_USART1; + break; + case SPI6_BASE: + id = STM32MP1_SHRES_SPI6; + break; + case I2C4_BASE: + id = STM32MP1_SHRES_I2C4; + break; + case I2C6_BASE: + id = STM32MP1_SHRES_I2C6; + break; + case RTC_BASE: + id = STM32MP1_SHRES_RTC; + break; + case RNG1_BASE: + id = STM32MP1_SHRES_RNG1; + break; + case CRYP1_BASE: + id = STM32MP1_SHRES_CRYP1; + break; + case HASH1_BASE: + id = STM32MP1_SHRES_HASH1; + break; + + /* Always non-secure resource cases */ +#ifdef CFG_WITH_NSEC_GPIOS + case GPIOA_BASE: + case GPIOB_BASE: + case GPIOC_BASE: + case GPIOD_BASE: + case GPIOE_BASE: + case GPIOF_BASE: + case GPIOG_BASE: + case GPIOH_BASE: + case GPIOI_BASE: + case GPIOJ_BASE: + case GPIOK_BASE: + fallthrough; +#endif +#ifdef CFG_WITH_NSEC_UARTS + case USART2_BASE: + case USART3_BASE: + case UART4_BASE: + case UART5_BASE: + case USART6_BASE: + case UART7_BASE: + case UART8_BASE: + fallthrough; +#endif +#ifdef CFG_WITH_NSEC_I2CS + case I2C5_BASE: + fallthrough; +#endif + case IWDG2_BASE: + /* Allow drivers to register some non-secure resources */ + DMSG("IO for non-secure resource 0x%lx", base); + if (state != SHRES_NON_SECURE) + panic(); + + return; + + default: + panic(); + break; + } + + register_periph(id, state); +} + +void stm32mp_register_secure_periph_iomem(vaddr_t base) +{ + register_periph_iomem(base, SHRES_SECURE); +} + +void stm32mp_register_non_secure_periph_iomem(vaddr_t base) +{ + register_periph_iomem(base, SHRES_NON_SECURE); +} + +/* Register GPIO resource */ +void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin) +{ + switch (bank) { + case GPIO_BANK_Z: + assert(pin < get_gpioz_nbpin()); + register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE); + break; + default: + EMSG("GPIO bank %u cannot be secured", bank); + panic(); + } +} + +void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin) +{ + switch (bank) { + case GPIO_BANK_Z: + assert(pin < get_gpioz_nbpin()); + register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE); + break; + default: + break; + } +} + +static void lock_registering(void) +{ + registering_locked = true; +} + +bool stm32mp_periph_is_secure(enum stm32mp_shres id) +{ + lock_registering(); + + return shres_state[id] == SHRES_SECURE; +} + +bool stm32mp_gpio_bank_is_shared(unsigned int bank) +{ + unsigned int not_secure = 0; + unsigned int pin = 0; + + lock_registering(); + + if (bank != GPIO_BANK_Z) + return false; + + for (pin = 0; pin < get_gpioz_nbpin(); pin++) + if (!stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin))) + not_secure++; + + return not_secure > 0 && not_secure < get_gpioz_nbpin(); +} + +bool stm32mp_gpio_bank_is_non_secure(unsigned int bank) +{ + unsigned int not_secure = 0; + unsigned int pin = 0; + + lock_registering(); + + if (bank != GPIO_BANK_Z) + return true; + + for (pin = 0; pin < get_gpioz_nbpin(); pin++) + if (!stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin))) + not_secure++; + + return not_secure > 0 && not_secure == get_gpioz_nbpin(); +} + +bool stm32mp_gpio_bank_is_secure(unsigned int bank) +{ + unsigned int secure = 0; + unsigned int pin = 0; + + lock_registering(); + + if (bank != GPIO_BANK_Z) + return false; + + for (pin = 0; pin < get_gpioz_nbpin(); pin++) + if (stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin))) + secure++; + + return secure > 0 && secure == get_gpioz_nbpin(); +} + +bool stm32mp_nsec_can_access_clock(unsigned long clock_id) +{ + enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; + + /* Oscillators and PLLs are visible from non-secure world */ + COMPILE_TIME_ASSERT(CK_HSE == 0 && + (CK_HSE + 1) == CK_CSI && + (CK_HSE + 2) == CK_LSI && + (CK_HSE + 3) == CK_LSE && + (CK_HSE + 4) == CK_HSI && + (CK_HSE + 5) == CK_HSE_DIV2 && + (PLL1_P + 1) == PLL1_Q && + (PLL1_P + 2) == PLL1_R && + (PLL1_P + 3) == PLL2_P && + (PLL1_P + 4) == PLL2_Q && + (PLL1_P + 5) == PLL2_R && + (PLL1_P + 6) == PLL3_P && + (PLL1_P + 7) == PLL3_Q && + (PLL1_P + 8) == PLL3_R); + + if (clock_id <= CK_HSE_DIV2 || + (clock_id >= PLL1_P && clock_id <= PLL3_R)) + return true; + + switch (clock_id) { + case RTCAPB: + case CK_MPU: + case CK_AXI: + case BSEC: + return true; + case GPIOZ: + return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z); + case SPI6_K: + shres_id = STM32MP1_SHRES_SPI6; + break; + case I2C4_K: + shres_id = STM32MP1_SHRES_I2C4; + break; + case I2C6_K: + shres_id = STM32MP1_SHRES_I2C6; + break; + case USART1_K: + shres_id = STM32MP1_SHRES_USART1; + break; + case IWDG1: + shres_id = STM32MP1_SHRES_IWDG1; + break; + case CRYP1: + shres_id = STM32MP1_SHRES_CRYP1; + break; + case HASH1: + shres_id = STM32MP1_SHRES_HASH1; + break; + case RNG1_K: + shres_id = STM32MP1_SHRES_RNG1; + break; + case RTC: + shres_id = STM32MP1_SHRES_RTC; + break; + case CK_MCU: + shres_id = STM32MP1_SHRES_MCU; + break; + default: + return false; + } + + return !stm32mp_periph_is_secure(shres_id); +} + +bool stm32mp_nsec_can_access_reset(unsigned int reset_id) +{ + enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; + + switch (reset_id) { + case GPIOZ_R: + return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z); + case SPI6_R: + shres_id = STM32MP1_SHRES_SPI6; + break; + case I2C4_R: + shres_id = STM32MP1_SHRES_I2C4; + break; + case I2C6_R: + shres_id = STM32MP1_SHRES_I2C6; + break; + case USART1_R: + shres_id = STM32MP1_SHRES_USART1; + break; + case CRYP1_R: + shres_id = STM32MP1_SHRES_CRYP1; + break; + case HASH1_R: + shres_id = STM32MP1_SHRES_HASH1; + break; + case RNG1_R: + shres_id = STM32MP1_SHRES_RNG1; + break; + case MDMA_R: + shres_id = STM32MP1_SHRES_MDMA; + break; + case MCU_R: + case MCU_HOLD_BOOT_R: + shres_id = STM32MP1_SHRES_MCU; + break; + default: + return false; + } + + return !stm32mp_periph_is_secure(shres_id); +} + +static bool mckprot_resource(enum stm32mp_shres id) +{ + switch (id) { + case STM32MP1_SHRES_MCU: + case STM32MP1_SHRES_PLL3: + return true; + default: + return false; + } +} + +#ifdef CFG_STM32_ETZPC +static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id) +{ + if (!stm32mp_periph_is_secure(id)) + return ETZPC_DECPROT_NS_RW; + + if (mckprot_resource(id)) + return ETZPC_DECPROT_MCU_ISOLATION; + + return ETZPC_DECPROT_S_RW; +} + +/* Configure ETZPC cell and lock it when resource is secure */ +static void config_lock_decprot(uint32_t decprot_id, + enum etzpc_decprot_attributes decprot_attr) +{ + etzpc_configure_decprot(decprot_id, decprot_attr); + + if (decprot_attr == ETZPC_DECPROT_S_RW) + etzpc_lock_decprot(decprot_id); +} + +static void set_etzpc_secure_configuration(void) +{ + /* Some peripherals shall be secure */ + config_lock_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); + config_lock_decprot(STM32MP1_ETZPC_DDRCTRL_ID, ETZPC_DECPROT_NS_R_S_W); + config_lock_decprot(STM32MP1_ETZPC_DDRPHYC_ID, ETZPC_DECPROT_NS_R_S_W); + + /* Configure ETZPC with peripheral registering */ + config_lock_decprot(STM32MP1_ETZPC_IWDG1_ID, + shres2decprot_attr(STM32MP1_SHRES_IWDG1)); + config_lock_decprot(STM32MP1_ETZPC_USART1_ID, + shres2decprot_attr(STM32MP1_SHRES_USART1)); + config_lock_decprot(STM32MP1_ETZPC_SPI6_ID, + shres2decprot_attr(STM32MP1_SHRES_SPI6)); + config_lock_decprot(STM32MP1_ETZPC_I2C4_ID, + shres2decprot_attr(STM32MP1_SHRES_I2C4)); + config_lock_decprot(STM32MP1_ETZPC_RNG1_ID, + shres2decprot_attr(STM32MP1_SHRES_RNG1)); + config_lock_decprot(STM32MP1_ETZPC_HASH1_ID, + shres2decprot_attr(STM32MP1_SHRES_HASH1)); + config_lock_decprot(STM32MP1_ETZPC_CRYP1_ID, + shres2decprot_attr(STM32MP1_SHRES_CRYP1)); + config_lock_decprot(STM32MP1_ETZPC_I2C6_ID, + shres2decprot_attr(STM32MP1_SHRES_I2C6)); +} +#else +static void set_etzpc_secure_configuration(void) +{ + /* Nothing to do */ +} +#endif + +static void check_rcc_secure_configuration(void) +{ + bool secure = stm32_rcc_is_secure(); + bool mckprot = stm32_rcc_is_mckprot(); + enum stm32mp_shres id = STM32MP1_SHRES_COUNT; + bool have_error = false; + uint32_t state = 0; + + if (stm32_bsec_get_state(&state)) + panic(); + + if (state == BSEC_STATE_SEC_CLOSED && !secure) + panic("Closed device mandates secure RCC"); + + for (id = 0; id < STM32MP1_SHRES_COUNT; id++) { + if (shres_state[id] != SHRES_SECURE) + continue; + + if ((mckprot_resource(id) && !mckprot) || !secure) { + EMSG("RCC %s MCKPROT %s and %s (%u) secure", + secure ? "secure" : "non-secure", + mckprot ? "set" : "not set", + shres2str_id(id), id); + have_error = true; + } + } + + if (have_error) + panic(); +} + +static void set_gpio_secure_configuration(void) +{ + unsigned int pin = 0; + + for (pin = 0; pin < get_gpioz_nbpin(); pin++) { + enum stm32mp_shres shres = STM32MP1_SHRES_GPIOZ(pin); + bool secure = stm32mp_periph_is_secure(shres); + + stm32_gpio_set_secure_cfg(GPIO_BANK_Z, pin, secure); + } +} + +static TEE_Result gpioz_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *hdl __unused) +{ + if (op == PM_OP_RESUME) + set_gpio_secure_configuration(); + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(gpioz_pm); + +static TEE_Result stm32mp1_init_final_shres(void) +{ + enum stm32mp_shres id = STM32MP1_SHRES_COUNT; + + lock_registering(); + + for (id = (enum stm32mp_shres)0; id < STM32MP1_SHRES_COUNT; id++) { + uint8_t __maybe_unused *state = &shres_state[id]; + + DMSG("stm32mp %-8s (%2u): %-14s", + shres2str_id(id), id, shres2str_state(*state)); + } + + set_etzpc_secure_configuration(); + if (IS_ENABLED(CFG_STM32_GPIO)) { + set_gpio_secure_configuration(); + register_pm_driver_cb(gpioz_pm, NULL, + "stm32mp1-shared-resources"); + } + check_rcc_secure_configuration(); + + return TEE_SUCCESS; +} +/* Finalize shres after drivers initialization, hence driver_init_late() */ +driver_init_late(stm32mp1_init_final_shres); diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h b/optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h new file mode 100644 index 0000000..0b741d2 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/stm32_util.h @@ -0,0 +1,329 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2018-2022, STMicroelectronics + */ + +#ifndef __STM32_UTIL_H__ +#define __STM32_UTIL_H__ + +#include +#include +#include +#include +#include +#include + +/* Backup registers and RAM utils */ +vaddr_t stm32mp_bkpreg(unsigned int idx); + +/* + * SYSCFG IO compensation. + * These functions assume non-secure world is suspended. + */ +void stm32mp_syscfg_enable_io_compensation(void); +void stm32mp_syscfg_disable_io_compensation(void); + +/* Platform util for the RCC drivers */ +vaddr_t stm32_rcc_base(void); + +/* Platform util for the GIC */ +vaddr_t get_gicd_base(void); + +/* + * Platform util functions for the GPIO driver + * @bank: Target GPIO bank ID as per DT bindings + * + * Platform shall implement these functions to provide to stm32_gpio + * driver the resource reference for a target GPIO bank. That are + * memory mapped interface base address, interface offset (see below) + * and clock identifier. + * + * stm32_get_gpio_bank_offset() returns a bank offset that is used to + * check DT configuration matches platform implementation of the banks + * description. + */ +vaddr_t stm32_get_gpio_bank_base(unsigned int bank); +unsigned int stm32_get_gpio_bank_offset(unsigned int bank); +unsigned int stm32_get_gpio_bank_clock(unsigned int bank); +struct clk *stm32_get_gpio_bank_clk(unsigned int bank); + +/* Platform util for PMIC support */ +bool stm32mp_with_pmic(void); + +/* Power management service */ +#ifdef CFG_PSCI_ARM32 +void stm32mp_register_online_cpu(void); +#else +static inline void stm32mp_register_online_cpu(void) +{ +} +#endif + +/* + * Generic spinlock function that bypass spinlock if MMU is disabled or + * lock is NULL. + */ +uint32_t may_spin_lock(unsigned int *lock); +void may_spin_unlock(unsigned int *lock, uint32_t exceptions); + +/* Helper from platform RCC clock driver */ +struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id); + +#ifdef CFG_STM32MP1_SHARED_RESOURCES +/* Return true if @clock_id is shared by secure and non-secure worlds */ +bool stm32mp_nsec_can_access_clock(unsigned long clock_id); +#else /* CFG_STM32MP1_SHARED_RESOURCES */ +static inline bool stm32mp_nsec_can_access_clock(unsigned long clock_id + __unused) +{ + return true; +} +#endif /* CFG_STM32MP1_SHARED_RESOURCES */ + +extern const struct clk_ops stm32mp1_clk_ops; + +#if defined(CFG_STPMIC1) +/* Return true if non-secure world can manipulate regulator @pmic_regu_name */ +bool stm32mp_nsec_can_access_pmic_regu(const char *pmic_regu_name); +#else +static inline bool stm32mp_nsec_can_access_pmic_regu(const char *name __unused) +{ + return false; +} +#endif + +#ifdef CFG_STM32MP1_SHARED_RESOURCES +/* Return true if and only if @reset_id relates to a non-secure peripheral */ +bool stm32mp_nsec_can_access_reset(unsigned int reset_id); +#else /* CFG_STM32MP1_SHARED_RESOURCES */ +static inline bool stm32mp_nsec_can_access_reset(unsigned int reset_id __unused) +{ + return true; +} +#endif /* CFG_STM32MP1_SHARED_RESOURCES */ + +/* Return rstctrl instance related to RCC reset controller DT binding ID */ +struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id); + +/* + * Structure and API function for BSEC driver to get some platform data. + * + * @base: BSEC interface registers physical base address + * @upper_start: Base ID for the BSEC upper words in the platform + * @max_id: Max value for BSEC word ID for the platform + */ +struct stm32_bsec_static_cfg { + paddr_t base; + unsigned int upper_start; + unsigned int max_id; +}; + +void stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg *cfg); + +/* + * Shared reference counter: increments by 2 on secure increment + * request, decrements by 2 on secure decrement request. Bit #0 + * is set to 1 on non-secure increment request and reset to 0 on + * non-secure decrement request. These counters initialize to + * either 0, 1 or 2 upon their expect default state. + * Counters saturate to UINT_MAX / 2. + */ +#define SHREFCNT_NONSECURE_FLAG 0x1ul +#define SHREFCNT_SECURE_STEP 0x2ul +#define SHREFCNT_MAX (UINT_MAX / 2) + +/* Return 1 if refcnt increments from 0, else return 0 */ +static inline int incr_shrefcnt(unsigned int *refcnt, bool secure) +{ + int rc = !*refcnt; + + if (secure) { + if (*refcnt < SHREFCNT_MAX) { + *refcnt += SHREFCNT_SECURE_STEP; + assert(*refcnt < SHREFCNT_MAX); + } + } else { + *refcnt |= SHREFCNT_NONSECURE_FLAG; + } + + return rc; +} + +/* Return 1 if refcnt decrements to 0, else return 0 */ +static inline int decr_shrefcnt(unsigned int *refcnt, bool secure) +{ + int rc = 0; + + if (secure) { + if (*refcnt < SHREFCNT_MAX) { + if (*refcnt < SHREFCNT_SECURE_STEP) + panic(); + + *refcnt -= SHREFCNT_SECURE_STEP; + rc = !*refcnt; + } + } else { + rc = (*refcnt == SHREFCNT_NONSECURE_FLAG); + *refcnt &= ~SHREFCNT_NONSECURE_FLAG; + } + + return rc; +} + +static inline int incr_refcnt(unsigned int *refcnt) +{ + return incr_shrefcnt(refcnt, true); +} + +static inline int decr_refcnt(unsigned int *refcnt) +{ + return decr_shrefcnt(refcnt, true); +} + +/* + * Shared peripherals and resources registration + * + * Resources listed in enum stm32mp_shres assigned at run-time to the + * non-secure world, to the secure world or shared by both worlds. + * In the later case, there must exist a secure service in OP-TEE + * for the non-secure world to access the resource. + * + * Resources may be a peripheral, a bus, a clock or a memory. + * + * Shared resources driver API functions allows drivers to register the + * resource as secure, non-secure or shared and to get the resource + * assignation state. + */ +#define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + i) + +enum stm32mp_shres { + STM32MP1_SHRES_GPIOZ_0 = 0, + STM32MP1_SHRES_GPIOZ_1, + STM32MP1_SHRES_GPIOZ_2, + STM32MP1_SHRES_GPIOZ_3, + STM32MP1_SHRES_GPIOZ_4, + STM32MP1_SHRES_GPIOZ_5, + STM32MP1_SHRES_GPIOZ_6, + STM32MP1_SHRES_GPIOZ_7, + STM32MP1_SHRES_IWDG1, + STM32MP1_SHRES_USART1, + STM32MP1_SHRES_SPI6, + STM32MP1_SHRES_I2C4, + STM32MP1_SHRES_RNG1, + STM32MP1_SHRES_HASH1, + STM32MP1_SHRES_CRYP1, + STM32MP1_SHRES_I2C6, + STM32MP1_SHRES_RTC, + STM32MP1_SHRES_MCU, + STM32MP1_SHRES_PLL3, + STM32MP1_SHRES_MDMA, + + STM32MP1_SHRES_COUNT +}; + +#ifdef CFG_STM32MP1_SHARED_RESOURCES +/* Register resource @id as a secure peripheral */ +void stm32mp_register_secure_periph(enum stm32mp_shres id); + +/* Register resource @id as a non-secure peripheral */ +void stm32mp_register_non_secure_periph(enum stm32mp_shres id); + +/* + * Register resource identified by @base as a secure peripheral + * @base: IOMEM physical base address of the resource + */ +void stm32mp_register_secure_periph_iomem(vaddr_t base); + +/* + * Register resource identified by @base as a non-secure peripheral + * @base: IOMEM physical base address of the resource + */ +void stm32mp_register_non_secure_periph_iomem(vaddr_t base); + +/* + * Register GPIO resource as a secure peripheral + * @bank: Bank of the target GPIO + * @pin: Bit position of the target GPIO in the bank + */ +void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin); + +/* + * Register GPIO resource as a non-secure peripheral + * @bank: Bank of the target GPIO + * @pin: Bit position of the target GPIO in the bank + */ +void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin); + +/* Return true if and only if resource @id is registered as secure */ +bool stm32mp_periph_is_secure(enum stm32mp_shres id); + +/* Return true if and only if GPIO bank @bank is registered as secure */ +bool stm32mp_gpio_bank_is_secure(unsigned int bank); + +/* Return true if and only if GPIO bank @bank is registered as shared */ +bool stm32mp_gpio_bank_is_shared(unsigned int bank); + +/* Return true if and only if GPIO bank @bank is registered as non-secure */ +bool stm32mp_gpio_bank_is_non_secure(unsigned int bank); + +/* Register parent clocks of @clock (ID used in clock DT bindings) as secure */ +void stm32mp_register_clock_parents_secure(unsigned long clock_id); + +#else /* CFG_STM32MP1_SHARED_RESOURCES */ + +static inline void stm32mp_register_secure_periph(enum stm32mp_shres id + __unused) +{ +} + +static inline void stm32mp_register_non_secure_periph(enum stm32mp_shres id + __unused) +{ +} + +static inline void stm32mp_register_secure_periph_iomem(vaddr_t base __unused) +{ +} + +static inline void stm32mp_register_non_secure_periph_iomem(vaddr_t base + __unused) +{ +} + +static inline void stm32mp_register_secure_gpio(unsigned int bank __unused, + unsigned int pin __unused) +{ +} + +static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused, + unsigned int pin __unused) +{ +} + +static inline bool stm32mp_periph_is_secure(enum stm32mp_shres id __unused) +{ + return true; +} + +static inline bool stm32mp_gpio_bank_is_secure(unsigned int bank __unused) +{ + return true; +} + +static inline bool stm32mp_gpio_bank_is_shared(unsigned int bank __unused) +{ + return false; +} + +static inline bool stm32mp_gpio_bank_is_non_secure(unsigned int bank __unused) +{ + return false; +} + +static inline void stm32mp_register_clock_parents_secure(unsigned long clock_id + __unused) +{ +} + +#endif /* CFG_STM32MP1_SHARED_RESOURCES */ +#endif /*__STM32_UTIL_H__*/ diff --git a/optee/optee_os/core/arch/arm/plat-stm32mp1/sub.mk b/optee/optee_os/core/arch/arm/plat-stm32mp1/sub.mk new file mode 100644 index 0000000..fa6e148 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-stm32mp1/sub.mk @@ -0,0 +1,12 @@ +global-incdirs-y += . + +srcs-y += main.c +srcs-y += reset.S +srcs-$(CFG_SCMI_MSG_DRIVERS) += scmi_server.c +srcs-$(CFG_STM32MP1_SHARED_RESOURCES) += shared_resources.c +srcs-$(CFG_TZC400) += plat_tzc400.c +srcs-$(CFG_WITH_PAGER) += link_dummies_paged.c + +subdirs-y += drivers +subdirs-y += nsec-service +subdirs-y += pm diff --git a/optee/optee_os/core/arch/arm/plat-sunxi/conf.mk b/optee/optee_os/core/arch/arm/plat-sunxi/conf.mk new file mode 100644 index 0000000..5c0effc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sunxi/conf.mk @@ -0,0 +1,45 @@ +PLATFORM_FLAVOR ?= bpi_zero + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_8250_UART,y) + +ifeq ($(PLATFORM_FLAVOR),bpi_zero) +include core/arch/arm/cpu/cortex-a7.mk +$(call force,CFG_SUN8I_H2_PLUS,y) +$(call force,CFG_ARM32_core,y) +$(call force,CFG_GIC,y) +$(call force,CFG_WITH_LPAE,n) +$(call force,CFG_WITH_PAGER,n) + +CFG_CRYPTO_SIZE_OPTIMIZATION ?= n +CFG_NUM_THREADS ?= 4 +CFG_TEE_CORE_NB_CORE ?= 4 +CFG_BOOT_SECONDARY_REQUEST ?= y +CFG_PSCI_ARM32 ?= y +CFG_NS_ENTRY_ADDR ?= 0x42000000 +CFG_DT ?= y +CFG_INIT_CNTVOFF ?= y +CFG_SECONDARY_INIT_CNTFRQ ?= y +CFG_TZDRAM_START ?= 0x5c000000 +CFG_TZDRAM_SIZE ?= 0x03e00000 +CFG_SHMEM_START ?= 0x5fe00000 +CFG_SHMEM_SIZE ?= 0x00200000 +endif + +ifeq ($(PLATFORM_FLAVOR),sun50i_a64) +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_ARM64_core,y) + +CFG_TZDRAM_START ?= 0x40000000 +CFG_TZDRAM_SIZE ?= 0x2000000 +CFG_SHMEM_START ?= 0x44000000 +CFG_SHMEM_SIZE ?= 0x00400000 +CFG_TEE_CORE_NB_CORE ?= 4 +CFG_TZC380 ?= y +endif + +ifeq ($(platform-flavor-armv8),1) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +endif + +CFG_WITH_STATS ?= y diff --git a/optee/optee_os/core/arch/arm/plat-sunxi/main.c b/optee/optee_os/core/arch/arm/plat-sunxi/main.c new file mode 100644 index 0000000..6a8b0e5 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sunxi/main.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Allwinner Technology Co., Ltd. + * Copyright (c) 2018, Linaro Limited + * Copyright (c) 2018, Amit Singh Tomar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +#ifdef GIC_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); +#endif + +#ifdef CONSOLE_UART_BASE +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, + CONSOLE_UART_BASE, SUNXI_UART_REG_SIZE); +#endif + +#ifdef SUNXI_TZPC_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SUNXI_TZPC_BASE, SUNXI_TZPC_REG_SIZE); +#define REG_TZPC_SMTA_DECPORT0_STA_REG (0x0004) +#define REG_TZPC_SMTA_DECPORT0_SET_REG (0x0008) +#define REG_TZPC_SMTA_DECPORT0_CLR_REG (0x000C) +#define REG_TZPC_SMTA_DECPORT1_STA_REG (0x0010) +#define REG_TZPC_SMTA_DECPORT1_SET_REG (0x0014) +#define REG_TZPC_SMTA_DECPORT1_CLR_REG (0x0018) +#define REG_TZPC_SMTA_DECPORT2_STA_REG (0x001c) +#define REG_TZPC_SMTA_DECPORT2_SET_REG (0x0020) +#define REG_TZPC_SMTA_DECPORT2_CLR_REG (0x0024) +#endif + +#ifdef SUNXI_CPUCFG_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SUNXI_CPUCFG_BASE, + SUNXI_CPUCFG_REG_SIZE); +#endif + +#ifdef SUNXI_PRCM_BASE +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SUNXI_PRCM_BASE, SUNXI_PRCM_REG_SIZE); +#endif + +#ifdef CFG_TZC380 +vaddr_t smc_base(void); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SUNXI_SMC_BASE, TZC400_REG_SIZE); +#define SMC_MASTER_BYPASS 0x18 +#define SMC_MASTER_BYPASS_EN_MASK 0x1 +#endif + +#ifdef GIC_BASE +static struct gic_data gic_data; +#endif +#ifdef SUNXI_TZPC_BASE +static void tzpc_init(void); +#endif + +static struct serial8250_uart_data console_data; + +void console_init(void) +{ + serial8250_uart_init(&console_data, + CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, + CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +#ifdef SUNXI_TZPC_BASE +static void tzpc_init(void) +{ + vaddr_t v = (vaddr_t)phys_to_virt(SUNXI_TZPC_BASE, MEM_AREA_IO_SEC, + SUNXI_TZPC_REG_SIZE); + + DMSG("SMTA_DECPORT0=%x", io_read32(v + REG_TZPC_SMTA_DECPORT0_STA_REG)); + DMSG("SMTA_DECPORT1=%x", io_read32(v + REG_TZPC_SMTA_DECPORT1_STA_REG)); + DMSG("SMTA_DECPORT2=%x", io_read32(v + REG_TZPC_SMTA_DECPORT2_STA_REG)); + + /* Allow all peripherals for normal world */ + io_write32(v + REG_TZPC_SMTA_DECPORT0_SET_REG, 0xbe); + io_write32(v + REG_TZPC_SMTA_DECPORT1_SET_REG, 0xff); + io_write32(v + REG_TZPC_SMTA_DECPORT2_SET_REG, 0x7f); + + DMSG("SMTA_DECPORT0=%x", io_read32(v + REG_TZPC_SMTA_DECPORT0_STA_REG)); + DMSG("SMTA_DECPORT1=%x", io_read32(v + REG_TZPC_SMTA_DECPORT1_STA_REG)); + DMSG("SMTA_DECPORT2=%x", io_read32(v + REG_TZPC_SMTA_DECPORT2_STA_REG)); +} +#else +static inline void tzpc_init(void) +{ +} +#endif /* SUNXI_TZPC_BASE */ + +#ifndef CFG_WITH_ARM_TRUSTED_FW +void main_init_gic(void) +{ + gic_init(&gic_data, GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} +#endif + +#ifdef ARM32 +void plat_primary_init_early(void) +{ + assert(!cpu_mmu_enabled()); + + tzpc_init(); +} +#endif + +/* + * Allwinner's A64 has TZC380 like controller called SMC that can + * be programmed to protect parts of DRAM from non-secure world. + */ +#ifdef CFG_TZC380 +vaddr_t smc_base(void) +{ + return (vaddr_t)phys_to_virt(SUNXI_SMC_BASE, MEM_AREA_IO_SEC, + TZC400_REG_SIZE); +} + +static TEE_Result smc_init(void) +{ + vaddr_t base = smc_base(); + + if (!base) { + EMSG("smc not mapped"); + panic(); + } + + tzc_init(base); + tzc_configure_region(0, 0x0, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_1G) | + TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); + tzc_configure_region(1, 0x0, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_32M) | + TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_S_RW); + + /* SoC specific bits */ + io_clrbits32(base + SMC_MASTER_BYPASS, SMC_MASTER_BYPASS_EN_MASK); + + return TEE_SUCCESS; +} + +driver_init(smc_init); +#endif /* CFG_TZC380 */ diff --git a/optee/optee_os/core/arch/arm/plat-sunxi/plat_init.S b/optee/optee_os/core/arch/arm/plat-sunxi/plat_init.S new file mode 100644 index 0000000..0b347fc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sunxi/plat_init.S @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (C) 2018, 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 +#include + +FUNC plat_cpu_reset_early , : + /* NSACR configuration */ + read_nsacr r0 + orr r0, r0, #NSACR_CP10 + orr r0, r0, #NSACR_CP11 + orr r0, r0, #NSACR_NS_SMP + write_nsacr r0 + + /* Enable SMP bit */ + read_actlr r0 + orr r0, r0, #ACTLR_SMP + write_actlr r0 + + bx lr +END_FUNC plat_cpu_reset_early diff --git a/optee/optee_os/core/arch/arm/plat-sunxi/platform_config.h b/optee/optee_os/core/arch/arm/plat-sunxi/platform_config.h new file mode 100644 index 0000000..1c682cc --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sunxi/platform_config.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Allwinner Technology Co., Ltd. + * Copyright (c) 2018, Linaro Limited + * Copyright (c) 2018, Amit Singh Tomar + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +/* 16550 UART */ +#define CONSOLE_UART_BASE 0x01c28000 /* UART0 */ +#define CONSOLE_UART_CLK_IN_HZ 24000000 +#define CONSOLE_BAUDRATE 115200 +#define SUNXI_UART_REG_SIZE 0x400 + +#if defined(PLATFORM_FLAVOR_bpi_zero) +#define GIC_BASE 0x01c80000 +#define GICC_OFFSET 0x2000 +#define GICD_OFFSET 0x1000 +#define SUNXI_TZPC_BASE 0x01c23400 +#define SUNXI_TZPC_REG_SIZE 0x400 +#define SUNXI_CPUCFG_BASE 0x01f01c00 +#define SUNXI_CPUCFG_REG_SIZE 0x400 +#define SUNXI_PRCM_BASE 0x01f01400 +#define SUNXI_PRCM_REG_SIZE 0x400 +#define PRCM_CPU_SOFT_ENTRY_REG 0x164 +#endif + +#if defined(PLATFORM_FLAVOR_sun50i_a64) +#define SUNXI_SMC_BASE 0x01c1e000 +#endif + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-sunxi/psci.c b/optee/optee_os/core/arch/arm/plat-sunxi/psci.c new file mode 100644 index 0000000..f59f72e --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sunxi/psci.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2013, ARM Ltd + * Copyright (c) 2014, Allwinner Technology Co., Ltd. + * Copyright (c) 2018, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_CPUCFG_RES0 (0x0000) +#define REG_CPUCFG_CPU_RST(cpu) (0x0040 + (cpu) * (0x0040)) +#define REG_CPUCFG_GEN_CTRL (0x0184) +#define REG_CPUCFG_PRIV0 (0x01a4) +#define REG_CPUCFG_DBG_CTRL1 (0x01e4) +#define REG_PRCM_CPU_PWROFF (0x0100) +#define REG_PRCM_CPU_PWR_CLAMP(cpu) (0x0140 + (cpu) * (0x0004)) + +int psci_features(uint32_t psci_fid) +{ + switch (psci_fid) { +#ifdef CFG_BOOT_SECONDARY_REQUEST + case PSCI_CPU_ON: + return 0; +#endif + + default: + return PSCI_RET_NOT_SUPPORTED; + } +} + +#ifdef CFG_BOOT_SECONDARY_REQUEST +int psci_cpu_on(uint32_t core_idx, uint32_t entry, + uint32_t context_id) +{ + vaddr_t base = (vaddr_t)phys_to_virt(SUNXI_PRCM_BASE, MEM_AREA_IO_SEC, + SUNXI_PRCM_REG_SIZE); + vaddr_t cpucfg = (vaddr_t)phys_to_virt(SUNXI_CPUCFG_BASE, + MEM_AREA_IO_SEC, + SUNXI_CPUCFG_REG_SIZE); + uint32_t tmpff; + uint32_t val; + + assert(base); + assert(cpucfg); + + if ((core_idx == 0) || (core_idx >= CFG_TEE_CORE_NB_CORE)) + return PSCI_RET_INVALID_PARAMETERS; + + /* set secondary cores' NS entry addresses */ + boot_set_core_ns_entry(core_idx, entry, context_id); + + val = virt_to_phys((void *)TEE_LOAD_ADDR); + + /* set entry address */ + DMSG("set entry address for CPU %d", core_idx); + io_write32(cpucfg + REG_CPUCFG_PRIV0, val); + + /* assert reset on target CPU */ + DMSG("assert reset on target CPU %d", core_idx); + io_write32(cpucfg + REG_CPUCFG_CPU_RST(core_idx), 0); + + /* invalidate L1 cache */ + DMSG("invalidate L1 cache for CPU %d", core_idx); + io_clrbits32(cpucfg + REG_CPUCFG_GEN_CTRL, BIT32(core_idx)); + + /* lock CPU (Disable external debug access) */ + DMSG("lock CPU %d", core_idx); + io_clrbits32(cpucfg + REG_CPUCFG_DBG_CTRL1, BIT32(core_idx)); + + /* release clamp */ + DMSG("release clamp for CPU %d", core_idx); + tmpff = 0x1ff; + do { + tmpff >>= 1; + io_write32(base + REG_PRCM_CPU_PWR_CLAMP(core_idx), tmpff); + } while (tmpff); + mdelay(10); + + /* clear power gating */ + DMSG("clear power gating for CPU %d", core_idx); + io_clrbits32(base + REG_PRCM_CPU_PWROFF, BIT32(core_idx)); + udelay(1000); + + /* de-assert reset on target CPU */ + DMSG("de-assert reset on target CPU %d", core_idx); + io_write32(cpucfg + REG_CPUCFG_CPU_RST(core_idx), 0x03); + + /* unlock CPU (enable external debug access) */ + DMSG("unlock CPU %d", core_idx); + io_setbits32(cpucfg + REG_CPUCFG_DBG_CTRL1, BIT32(core_idx)); + + return PSCI_RET_SUCCESS; +} + +int __noreturn psci_cpu_off(void) +{ + uint32_t core_id; + vaddr_t base = (vaddr_t)phys_to_virt(SUNXI_PRCM_BASE, MEM_AREA_IO_SEC, + SUNXI_PRCM_REG_SIZE); + vaddr_t cpucfg = (vaddr_t)phys_to_virt(SUNXI_CPUCFG_BASE, + MEM_AREA_IO_SEC, + SUNXI_CPUCFG_REG_SIZE); + + core_id = get_core_pos(); + + DMSG("core_id: %" PRIu32, core_id); + +#ifdef CFG_PSCI_ARM32 + psci_armv7_cpu_off(); +#endif /* CFG_PSCI_ARM32 */ + + assert(base); + assert(cpucfg); + + /* set power gating */ + DMSG("set power gating for cpu %d", core_id); + io_setbits32(base + REG_PRCM_CPU_PWROFF, BIT32(core_id)); + + /* Activate power clamp */ + DMSG("Activate power clamp for cpu %d", core_id); + io_write32(base + REG_PRCM_CPU_PWR_CLAMP(core_id), 0xff); + + while (true) + wfi(); +} +#endif diff --git a/optee/optee_os/core/arch/arm/plat-sunxi/sub.mk b/optee/optee_os/core/arch/arm/plat-sunxi/sub.mk new file mode 100644 index 0000000..6fefa62 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-sunxi/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-$(CFG_ARM32_core) += plat_init.S +srcs-$(CFG_ARM32_core) += psci.c diff --git a/optee/optee_os/core/arch/arm/plat-synquacer/conf.mk b/optee/optee_os/core/arch/arm/plat-synquacer/conf.mk new file mode 100644 index 0000000..8e8aaff --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-synquacer/conf.mk @@ -0,0 +1,22 @@ +PLATFORM_FLAVOR ?= developerbox + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_GIC,y) +$(call force,CFG_PL011,y) + +include core/arch/arm/cpu/cortex-armv8-0.mk +$(call force,CFG_TEE_CORE_NB_CORE,24) +CFG_NUM_THREADS ?= 8 +CFG_TZDRAM_START ?= 0xfc000000 +CFG_TZDRAM_SIZE ?= 0x03c00000 +CFG_SHMEM_START ?= 0xffc00000 +CFG_SHMEM_SIZE ?= 0x00400000 + +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) + +$(call force,CFG_ARM64_core,y) +supported-ta-targets = ta_arm64 + +CFG_CRYPTO_SIZE_OPTIMIZATION ?= n +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) diff --git a/optee/optee_os/core/arch/arm/plat-synquacer/main.c b/optee/optee_os/core/arch/arm/plat-synquacer/main.c new file mode 100644 index 0000000..111726f --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-synquacer/main.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "synquacer_rng_pta.h" + +static struct gic_data gic_data; +static struct pl011_data console_data; + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, THERMAL_SENSOR_BASE, + CORE_MMU_PGDIR_SIZE); + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, + CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +void main_init_gic(void) +{ + /* On ARMv8-A, GIC configuration is initialized in TF-A */ + gic_init_base_addr(&gic_data, 0, GIC_BASE + GICD_OFFSET); + + itr_init(&gic_data.chip); +} + +static enum itr_return timer_itr_cb(struct itr_handler *h __unused) +{ + /* Reset timer for next FIQ */ + generic_timer_handler(TIMER_PERIOD_MS); + + /* Collect entropy on each timer FIQ */ + rng_collect_entropy(); + + return ITRR_HANDLED; +} + +static struct itr_handler timer_itr = { + .it = IT_SEC_TIMER, + .flags = ITRF_TRIGGER_LEVEL, + .handler = timer_itr_cb, +}; + +static TEE_Result init_timer_itr(void) +{ + itr_add(&timer_itr); + itr_enable(IT_SEC_TIMER); + + /* Enable timer FIQ to fetch entropy required during boot */ + generic_timer_start(TIMER_PERIOD_MS); + + return TEE_SUCCESS; +} +driver_init(init_timer_itr); diff --git a/optee/optee_os/core/arch/arm/plat-synquacer/platform_config.h b/optee/optee_os/core/arch/arm/plat-synquacer/platform_config.h new file mode 100644 index 0000000..76a3d4a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-synquacer/platform_config.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +#define STACK_ALIGNMENT 64 + +#define GIC_BASE 0x30000000 +#define GICD_OFFSET 0x0 + +/* console uart define */ +#define UART0_BASE 0x2A400000 +#define CONSOLE_UART_BASE UART0_BASE +#define CONSOLE_UART_CLK_IN_HZ 62500000 +#define CONSOLE_BAUDRATE 115200 + +#define THERMAL_SENSOR_BASE 0x54190000 +#define IT_SEC_TIMER 29 +#define TIMER_PERIOD_MS 2 + +#define DRAM0_BASE 0x80000000 + +/* Platform specific defines */ +#if defined(PLATFORM_FLAVOR_developerbox) +#define DRAM0_SIZE 0x80000000 +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.c b/optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.c new file mode 100644 index 0000000..16a1e46 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-synquacer/rng_pta.c @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018-2022, Linaro Limited + */ + +/* + * Developerbox doesn't provide a hardware based true random number + * generator. So this pseudo TA provides a good source of entropy using + * noise from 7 thermal sensors. Its suitable for entropy required + * during boot, seeding kernel entropy pool, cryptographic use etc. + * + * Assumption + * ========== + * + * We have assumed the entropy of the sensor is better than 8 bits per + * 14 sensor readings. This entropy estimate is based on our simple + * minimal entropy estimates done on 2.1G bytes of raw samples collected + * from thermal sensors. + * + * We believe our estimate to be conservative and have designed to + * health tests to trigger if a sensor does not achieve at least + * 8 bits in 16 sensor reading (we use 16 rather than 14 to prevent + * spurious failures on edge cases). + * + * Theory of operation + * =================== + * + * This routine uses secure timer interrupt to sample raw thermal sensor + * readings. As thermal sensor refresh rate is every 2ms, so interrupt + * fires every 2ms. It implements continuous health test counting rising + * and falling edges to report if sensors fail to provide entropy. + * + * It uses vetted conditioner as SHA512/256 (approved hash algorithm) + * to condense entropy. As per NIST.SP.800-90B spec, to get full entropy + * from vetted conditioner, we need to supply double of input entropy. + * According to assumption above and requirement for vetted conditioner, + * we need to supply 28 raw sensor readings to get 1 byte of full + * entropy as output. So for 32 bytes of conditioner output, we need to + * supply 896 bytes of raw sensor readings. + * + * Interfaces -> Input + * ------------------- + * + * void rng_collect_entropy(void); + * + * Called as part of secure timer interrupt handler to sample raw + * thermal sensor readings and add entropy to the pool. + * + * Interfaces -> Output + * -------------------- + * + * TEE_Result rng_get_entropy(uint32_t types, + * TEE_Param params[TEE_NUM_PARAMS]); + * + * Invoke command to expose an entropy interface to normal world. + * + * Testing + * ======= + * + * Passes FIPS 140-2 rngtest. + * + * Limitations + * =========== + * + * Output rate is limited to approx. 125 bytes per second. + * + * Our entropy estimation was not reached using any approved or + * published estimation framework such as NIST.SP.800-90B and was tested + * on a very small set of physical samples. Instead we have adopted what + * we believe to be a conservative estimate and partnered it with a + * fairly agressive health check. + * + * Generating the SHA512/256 hash takes 24uS and will be run by an + * interrupt handler that pre-empts the normal world. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "synquacer_rng_pta.h" + +#define PTA_NAME "rng.pta" + +#define THERMAL_SENSOR_BASE0 0x54190800 +#define THERMAL_SENSOR_OFFSET 0x80 +#define NUM_SENSORS 7 +#define NUM_SLOTS ((NUM_SENSORS * 2) - 1) + +#define TEMP_DATA_REG_OFFSET 0x34 + +#define ENTROPY_POOL_SIZE 4096 + +#define SENSOR_DATA_SIZE 128 +#define CONDITIONER_PAYLOAD (SENSOR_DATA_SIZE * NUM_SENSORS) + +/* + * The health test monitors each sensor's least significant bit and counts + * the number of rising and falling edges. It verifies that both counts + * lie within interval of between 12.5% and 37.5% of the samples. + * For true random data with 8 bits of entropy per byte, both counts would + * be close to 25%. + */ +#define MAX_BIT_FLIP_EDGE_COUNT ((3 * SENSOR_DATA_SIZE) / 8) +#define MIN_BIT_FLIP_EDGE_COUNT (SENSOR_DATA_SIZE / 8) + +static uint8_t entropy_pool[ENTROPY_POOL_SIZE] = {0}; +static uint32_t entropy_size; + +static uint8_t sensors_data[NUM_SLOTS][SENSOR_DATA_SIZE] = {0}; +static uint8_t sensors_data_slot_idx; +static uint8_t sensors_data_idx; + +static uint32_t health_test_fail_cnt; +static uint32_t health_test_cnt; + +static unsigned int entropy_lock = SPINLOCK_UNLOCK; + +static void pool_add_entropy(uint8_t *entropy, uint32_t size) +{ + uint32_t copy_size; + + if (entropy_size >= ENTROPY_POOL_SIZE) + return; + + if ((ENTROPY_POOL_SIZE - entropy_size) >= size) + copy_size = size; + else + copy_size = ENTROPY_POOL_SIZE - entropy_size; + + memcpy((entropy_pool + entropy_size), entropy, copy_size); + + entropy_size += copy_size; +} + +static void pool_get_entropy(uint8_t *buf, uint32_t size) +{ + uint32_t off; + + if (size > entropy_size) + return; + + off = entropy_size - size; + + memcpy(buf, &entropy_pool[off], size); + entropy_size -= size; +} + +static bool health_test(uint8_t sensor_id) +{ + uint32_t falling_edge_count = 0, rising_edge_count = 0; + uint32_t lo_edge_count, hi_edge_count; + uint32_t i; + + for (i = 0; i < (SENSOR_DATA_SIZE - 1); i++) { + if ((sensors_data[sensor_id][i] ^ + sensors_data[sensor_id][i + 1]) & 0x1) { + falling_edge_count += (sensors_data[sensor_id][i] & + 0x1); + rising_edge_count += (sensors_data[sensor_id][i + 1] & + 0x1); + } + } + + lo_edge_count = rising_edge_count < falling_edge_count ? + rising_edge_count : falling_edge_count; + hi_edge_count = rising_edge_count < falling_edge_count ? + falling_edge_count : rising_edge_count; + + return (lo_edge_count >= MIN_BIT_FLIP_EDGE_COUNT) && + (hi_edge_count <= MAX_BIT_FLIP_EDGE_COUNT); +} + +static uint8_t pool_check_add_entropy(void) +{ + uint32_t i; + uint8_t entropy_sha512_256[TEE_SHA256_HASH_SIZE]; + uint8_t pool_status = 0; + TEE_Result res; + + for (i = 0; i < NUM_SENSORS; i++) { + /* Check if particular sensor data passes health test */ + if (health_test(sensors_data_slot_idx) == true) { + sensors_data_slot_idx++; + } else { + health_test_fail_cnt++; + memmove(sensors_data[sensors_data_slot_idx], + sensors_data[sensors_data_slot_idx + 1], + (SENSOR_DATA_SIZE * (NUM_SENSORS - i - 1))); + } + } + + health_test_cnt += NUM_SENSORS; + + /* Check if sensors_data have enough pass data for conditioning */ + if (sensors_data_slot_idx >= NUM_SENSORS) { + /* + * Use vetted conditioner SHA512/256 as per + * NIST.SP.800-90B to condition raw data from entropy + * source. + */ + sensors_data_slot_idx -= NUM_SENSORS; + res = hash_sha512_256_compute(entropy_sha512_256, + sensors_data[sensors_data_slot_idx], + CONDITIONER_PAYLOAD); + if (res == TEE_SUCCESS) + pool_add_entropy(entropy_sha512_256, + TEE_SHA256_HASH_SIZE); + } + + if (entropy_size >= ENTROPY_POOL_SIZE) + pool_status = 1; + + return pool_status; +} + +void rng_collect_entropy(void) +{ + uint8_t i, pool_full = 0; + void *vaddr; + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + cpu_spin_lock(&entropy_lock); + + for (i = 0; i < NUM_SENSORS; i++) { + vaddr = phys_to_virt_io(THERMAL_SENSOR_BASE0 + + (THERMAL_SENSOR_OFFSET * i) + + TEMP_DATA_REG_OFFSET, + sizeof(uint32_t)); + sensors_data[sensors_data_slot_idx + i][sensors_data_idx] = + (uint8_t)io_read32((vaddr_t)vaddr); + } + + sensors_data_idx++; + + if (sensors_data_idx >= SENSOR_DATA_SIZE) { + pool_full = pool_check_add_entropy(); + sensors_data_idx = 0; + } + + if (pool_full) + generic_timer_stop(); + + cpu_spin_unlock(&entropy_lock); + thread_set_exceptions(exceptions); +} + +static TEE_Result rng_get_entropy(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint8_t *e = NULL; + uint32_t pool_size = 0, rq_size = 0; + uint32_t exceptions; + TEE_Result res = TEE_SUCCESS; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + EMSG("bad parameters types: 0x%" PRIx32, types); + return TEE_ERROR_BAD_PARAMETERS; + } + + rq_size = params[0].memref.size; + + if ((rq_size == 0) || (rq_size > ENTROPY_POOL_SIZE)) + return TEE_ERROR_NOT_SUPPORTED; + + e = (uint8_t *)params[0].memref.buffer; + if (!e) + return TEE_ERROR_BAD_PARAMETERS; + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + cpu_spin_lock(&entropy_lock); + + /* + * Report health test failure to normal world in case fail count + * exceeds 1% of pass count. + */ + if (health_test_fail_cnt > ((health_test_cnt + 100) / 100)) { + res = TEE_ERROR_HEALTH_TEST_FAIL; + params[0].memref.size = 0; + health_test_cnt = 0; + health_test_fail_cnt = 0; + goto exit; + } + + pool_size = entropy_size; + + if (pool_size < rq_size) { + params[0].memref.size = pool_size; + pool_get_entropy(e, pool_size); + } else { + params[0].memref.size = rq_size; + pool_get_entropy(e, rq_size); + } + +exit: + /* Enable timer FIQ to fetch entropy */ + generic_timer_start(TIMER_PERIOD_MS); + + cpu_spin_unlock(&entropy_lock); + thread_set_exceptions(exceptions); + + return res; +} + +static TEE_Result rng_get_info(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + EMSG("bad parameters types: 0x%" PRIx32, types); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Output RNG rate (per second) */ + params[0].value.a = 125; + + /* + * Quality/entropy per 1024 bit of output data. As we have used + * a vetted conditioner as per NIST.SP.800-90B to provide full + * entropy given our assumption of entropy estimate for raw sensor + * data. + */ + params[0].value.b = 1024; + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *pSessionContext __unused, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]) +{ + FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME); + + switch (nCommandID) { + case PTA_CMD_GET_ENTROPY: + return rng_get_entropy(nParamTypes, pParams); + case PTA_CMD_GET_RNG_INFO: + return rng_get_info(nParamTypes, pParams); + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_RNG_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_DEVICE_ENUM, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/arch/arm/plat-synquacer/sub.mk b/optee/optee_os/core/arch/arm/plat-synquacer/sub.mk new file mode 100644 index 0000000..571c058 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-synquacer/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-y += rng_pta.c diff --git a/optee/optee_os/core/arch/arm/plat-synquacer/synquacer_rng_pta.h b/optee/optee_os/core/arch/arm/plat-synquacer/synquacer_rng_pta.h new file mode 100644 index 0000000..4360e5d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-synquacer/synquacer_rng_pta.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2018-2022, Linaro Limited + */ + +#ifndef __SYNQUACER_RNG_PTA_H +#define __SYNQUACER_RNG_PTA_H + +void rng_collect_entropy(void); + +#endif /* __SYNQUACER_RNG_PTA_H */ diff --git a/optee/optee_os/core/arch/arm/plat-tegra/README.tegra_secure_storage b/optee/optee_os/core/arch/arm/plat-tegra/README.tegra_secure_storage new file mode 100644 index 0000000..214e6b1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/README.tegra_secure_storage @@ -0,0 +1,29 @@ +======================================================================= + README-tegra-secure-storage + Linux for Tegra +======================================================================= + +Tegra Secure Storage is based on RPMB Secure Storage[1] of OP-TEE. It +adds few customizations to be compatible with Tegra product design. + +----------------------------------------------------------------------- +Enable Tegra Secure Storage +----------------------------------------------------------------------- +On Tegra we assume the RPMB key has been provisioned during +manufacturing. To enable Tegra Secure Storage you need to make sure the +configurations in optee_os below are set: +* CFG_RPMB_FS +* CFG_RPMB_KEY_HAS_PROVISIONED +And make the configurations in optee_os below are un-set: +* CFG_RPMB_WRITE_KEY +* CFG_RPMB_TESTKEY + +Reach your Nvidia contact for how to provision RPMB key with Nvidia +utility. + +You also need to set RPMB_EMU as 0 in optee_client/tee-supplicant/Makefile +to disable RPMB ioctl emulation, so that all the RPMB operations can +really reach the hardware. + + +[1] https://optee.readthedocs.io/en/latest/architecture/secure_storage.html diff --git a/optee/optee_os/core/arch/arm/plat-tegra/conf.mk b/optee/optee_os/core/arch/arm/plat-tegra/conf.mk new file mode 100644 index 0000000..10aacff --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/conf.mk @@ -0,0 +1,129 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved. +# + +include core/arch/arm/cpu/cortex-armv8-0.mk + +# TZDRAM and SHMEM addresses and sizes +CFG_TZDRAM_START ?= 0x80000000 + +# Use dynamic shared memory and disable static shared memory because +# the NS shared memory address and size are calculated dynamically +$(call force,CFG_CORE_DYN_SHM,y) +$(call force,CFG_CORE_RESERVED_SHM,n) + +# The NS memory range may exceed 4GB so 40 bits should be used +CFG_CORE_ARM64_PA_BITS = 40 + +# Enable ARM64 core +$(call force,CFG_ARM64_core,y) + +# Default number of threads is the number of CPU cores +CFG_NUM_THREADS = $(CFG_TEE_CORE_NB_CORE) + +# Default heap size for Core, 128 kB +CFG_CORE_HEAP_SIZE ?= 131072 + +# Makes sure everything built is 64-bit, even TA targets. +supported-ta-targets = ta_arm64 + +# Enables large physical address extension, necessary if ARM64 core is initialized. +$(call force,CFG_WITH_LPAE,y) + +CFG_LPAE_ADDR_SPACE_BITS = 38 +$(call force,CFG_WITH_PAGER,n) + +# Lets platform interact with ATF +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) + +# Initialize kernel time source +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) + +CFG_DTB_MAX_SIZE = 0x10000 +$(call force,CFG_DT,y) +$(call force,CFG_CORE_TPM_EVENT_LOG,n) + +# Enable tegra combined UART driver +$(call force,CFG_TEGRA_TCU,y) + +$(call force,CFG_RPMB_FS,n) +$(call force,CFG_RPMB_KEY_HAS_PROVISIONED,n) +$(call force,CFG_RPMB_WRITE_KEY,n) +$(call force,CFG_RPMB_TESTKEY,n) + +# Enable PKCS11 tests in xtest +$(call force,CFG_PKCS11_TA,y) + +# Set the default log level to INFO +$(call force,CFG_TEE_CORE_LOG_LEVEL,2) + +# Do not halt system if an invalid EKB is detected +$(call force,CFG_JETSON_MANDATORY_EKB,n) + +# Trusted OS implementation version +# Overriding TEE_IMPL_VERSION for consistency in version reporting +TEE_IMPL_VERSION = $(CFG_OPTEE_REVISION_MAJOR).$(CFG_OPTEE_REVISION_MINOR) + +# Leverage relocatable optee feature while not enable EL2 SPMC +$(call force,CFG_CORE_SEL2_SPMC,n) +$(call force,CFG_CORE_PHYS_RELOCATABLE,y) + +$(call force,CFG_CORE_ASLR,n) + +ifeq ($(PLATFORM_FLAVOR),t194) +CFG_TZDRAM_SIZE ?= 0x00f00000 + +# T194 has 4 clusters and 2 cores per cluster +$(call force,CFG_CORE_CLUSTER_SHIFT,1) +# Secondary CPU cores. t194 platform contains 8 CPU cores +CFG_TEE_CORE_NB_CORE = 8 + +# Enable Jetson user key PTA and drivers +$(call force,CFG_JETSON_USER_KEY_PTA,y) +$(call force,CFG_TEGRA_DRIVERS,y) +$(call force,CFG_TEGRA_FUSE,y) +$(call force,CFG_TEGRA_SE,y) +$(call force,CFG_TEGRA_SE_RNG1,y) +ifeq ($(CFG_TEGRA_SE_RNG1),y) +$(call force,CFG_WITH_SOFTWARE_PRNG,n) +endif + +# Enable Early TA support +$(call force,CFG_EARLY_TA,y) +$(call force,CFG_EMBEDDED_TS,y) +endif + +ifeq ($(PLATFORM_FLAVOR),t234) +CFG_TZDRAM_SIZE ?= 0x03fc0000 + +# T234 has 3 clusters and 4 cores per cluster +$(call force,CFG_CORE_CLUSTER_SHIFT,2) +# Secondary CPU cores. t234 platform contains 12 CPU cores +CFG_TEE_CORE_NB_CORE = 12 + +# Enable Jetson user key PTA and drivers +$(call force,CFG_JETSON_USER_KEY_PTA,y) +$(call force,CFG_TEGRA_DRIVERS,y) +$(call force,CFG_TEGRA_FUSE,y) +$(call force,CFG_TEGRA_SE,y) +$(call force,CFG_TEGRA_SE_RNG1,y) +ifeq ($(CFG_TEGRA_SE_RNG1),y) +$(call force,CFG_WITH_SOFTWARE_PRNG,n) +endif + +$(call force,CFG_MAP_EXT_DT_SECURE,y) + +# Enable Early TA support +$(call force,CFG_EARLY_TA,y) +$(call force,CFG_EMBEDDED_TS,y) + +$(call force,CFG_TEGRA_SE_USE_TEST_KEYS,y) + +libdeps += $(NV_CCC_PREBUILT) +endif + +# Include platform configs from $(NV_OPTEE_DIR) +ifneq ("$(wildcard $(NV_OPTEE_DIR))","") +include $(NV_OPTEE_DIR)/$(platform-dir)/conf.mk +endif diff --git a/optee/optee_os/core/arch/arm/plat-tegra/link.mk b/optee/optee_os/core/arch/arm/plat-tegra/link.mk new file mode 100644 index 0000000..1761db7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/link.mk @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. +# + +include core/arch/arm/kernel/link.mk + +all: $(link-out-dir)/tee-raw.bin + +cleanfiles += $(link-out-dir)/tee-raw.bin +$(link-out-dir)/tee-raw.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_tee_raw_bin $@ diff --git a/optee/optee_os/core/arch/arm/plat-tegra/main.c b/optee/optee_os/core/arch/arm/plat-tegra/main.c new file mode 100644 index 0000000..8cbb20c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/main.c @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include + +#ifdef CFG_TEGRA_TCU +#include +#endif + +#ifdef CFG_TEGRA_TCU +register_phys_mem_pgdir(MEM_AREA_IO_SEC, TEGRA_COMBUART_BASE, TEGRA_COMBUART_SIZE); +static struct tegra_combined_uart_data tcud; +#endif + +#if defined(PLATFORM_FLAVOR_t194) +#define TEGRA194_QSPI0_BASE 0x3270000 +#define TEGRA194_QSPI0_SIZE 0x10000 +register_phys_mem_pgdir(MEM_AREA_IO_SEC, TEGRA194_QSPI0_BASE, TEGRA194_QSPI0_SIZE); +#endif + +#if defined(PLATFORM_FLAVOR_t234) +#define TEGRA234_QSPI0_BASE 0x3270000 +#define TEGRA234_QSPI0_SIZE 0x10000 +register_phys_mem_pgdir(MEM_AREA_IO_SEC, TEGRA234_QSPI0_BASE, TEGRA234_QSPI0_SIZE); +#endif + +void console_init(void) +{ + /* Check if there is a platform-specific console. + * If so, skip the Tegra Combined UART initialization below. + */ + if(tegra_console_init() == TEE_SUCCESS) + return; + +#ifdef CFG_TEGRA_TCU + tegra_combined_uart_init(&tcud, TEGRA_COMBUART_BASE, TEGRA_COMBUART_SIZE); + register_serial_console(&tcud.chip); +#endif +} diff --git a/optee/optee_os/core/arch/arm/plat-tegra/platform_config.h b/optee/optee_os/core/arch/arm/plat-tegra/platform_config.h new file mode 100644 index 0000000..d3b2676 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/platform_config.h @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-tegra/sub.mk b/optee/optee_os/core/arch/arm/plat-tegra/sub.mk new file mode 100644 index 0000000..6618ac0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/sub.mk @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved. +# + +global-incdirs-y += . +srcs-y += main.c + +ifneq ("$(wildcard $(NV_OPTEE_DIR))","") +subdirs_ext-y += $(NV_OPTEE_DIR)/$(platform-dir) +endif diff --git a/optee/optee_os/core/arch/arm/plat-tegra/tegra_common.h b/optee/optee_os/core/arch/arm/plat-tegra/tegra_common.h new file mode 100644 index 0000000..c089d48 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-tegra/tegra_common.h @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef __TEGRA_COMMON_H__ +#define __TEGRA_COMMON_H__ + +#ifdef CFG_TEGRA_SIMULATION_SUPPORT +TEE_Result tegra_console_init(void); +#else +static inline TEE_Result tegra_console_init(void) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /* CFG_TEGRA_SIMULATION_SUPPORT */ +#endif diff --git a/optee/optee_os/core/arch/arm/plat-ti/a9_plat_init.S b/optee/optee_os/core/arch/arm/plat-ti/a9_plat_init.S new file mode 100644 index 0000000..3c3441b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/a9_plat_init.S @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew Davis + */ + +/* + * Entry points for the A9 init. + * It is assumed no stack is available when these routines are called. + * It is assumed each routine is called with return address in LR + * and with ARM registers R0, R1, R2, R3 being scratchable. + */ + +#include +#include +#include +#include +#include + +.arch_extension sec + +.section .text +.balign 4 +.code 32 + +booted: + .word 0 + +/* + * Cortex A9 check for resume + * + * Use scratables registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +FUNC plat_cpu_reset_early , : + /* Check if we are resuming */ + ldr r3, =booted + ldr r2, [r3] + cmp r2, #0 + /* Cold boot, mark our boot flag and return to normal boot */ + moveq r2, #1 + streq r2, [r3] + bxeq lr + /* Otherwise we are resuming */ + b resume_springboard +END_FUNC plat_cpu_reset_early + +LOCAL_FUNC resume_springboard , : +UNWIND( .cantunwind) + /* Setup tmp stack */ + bl __get_core_pos + cmp r0, #CFG_TEE_CORE_NB_CORE + /* Unsupported CPU, park it before it breaks something */ +unhandled_cpu: + wfige + bge unhandled_cpu + add r0, r0, #1 + ldr r1, =stack_tmp_stride + ldr r1, [r1] + mul r1, r0, r1 + ldr r0, =stack_tmp +#if (STACK_TMP_GUARD != 0) + mov_imm r2, STACK_TMP_GUARD + sub r0, r0, r2 +#endif + add sp, r1, r0 + + /* Push our return on the stack as sm_pm_cpu_do_resume expects */ + adr lr, after_resume + push {r4 - r12, lr} + + /* Assumes suspend_regs is flat-mapped */ + ldr r0, =suspend_regs + bl sm_pm_cpu_do_resume + +after_resume: + bl thread_init_per_cpu + + /* r5 contains the non-secure entry address (ARMv7 bootarg #0) */ + mov r0, r5 + bl init_sec_mon + + bl main_init_gic + + mov r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE + mov r1, #0 + mov r2, #0 + mov r3, #0 + mov r4, #0 + smc #0 + b . /* SMC should not return */ +END_FUNC resume_springboard diff --git a/optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a15.h b/optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a15.h new file mode 100644 index 0000000..ea746a6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a15.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew Davis + */ + +#ifndef API_MONITOR_INDEX_H +#define API_MONITOR_INDEX_H + +#define API_HAL_RET_VALUE_OK 0x00000000 +#define API_HAL_RET_VALUE_SERVICE_UNKNWON 0xFFFFFFFF + +/* Base Index of APIs */ +#define API_MONITOR_BASE_INDEX 0x00000100 + +/* HyperVisor Start */ +#define API_MONITOR_HYP_STARTHYPERVISOR_INDEX (API_MONITOR_BASE_INDEX + 0x00000002) +/* Caches cleaning */ +#define API_MONITOR_CACHES_CLEAN_INDEX (API_MONITOR_BASE_INDEX + 0x00000003) +/* Write the L2 Cache Controller Auxiliary Control */ +#define API_MONITOR_L2ACTLR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000004) +/* Set the Data and Tag RAM Latency */ +#define API_MONITOR_L2CACHE_SETLATENCY_INDEX (API_MONITOR_BASE_INDEX + 0x00000005) +/* L2 Cache Prefetch Control Register */ +#define API_MONITOR_L2PFR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000006) +/* Set Auxiliary Control Register */ +#define API_MONITOR_ACTLR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000007) +/* AMBA IF mode */ +#define API_MONITOR_WUGEN_MPU_SETAMBAIF_INDEX (API_MONITOR_BASE_INDEX + 0x00000008) +/* Timer CNTFRQ register set */ +#define API_MONITOR_TIMER_SETCNTFRQ_INDEX (API_MONITOR_BASE_INDEX + 0x00000009) + +#endif /* API_MONITOR_INDEX_H */ diff --git a/optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a9.h b/optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a9.h new file mode 100644 index 0000000..53768cb --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/api_monitor_index_a9.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew Davis + */ + +#ifndef API_MONITOR_INDEX_H +#define API_MONITOR_INDEX_H + +#define API_HAL_RET_VALUE_OK 0x00000000 +#define API_HAL_RET_VALUE_SERVICE_UNKNWON 0xFFFFFFFF + +/* Base for power management related services */ +#define SECURE_SVC_PM 0x70 + +/* Carry out late actions as part of suspend sequence */ +#define SECURE_SVC_PM_LATE_SUSPEND (SECURE_SVC_PM + 1) + +/* Base Index of APIs */ +#define API_MONITOR_BASE_INDEX 0x00000100 + +/* Set the Debug control register */ +#define API_MONITOR_L2CACHE_SETDEBUG_INDEX (API_MONITOR_BASE_INDEX + 0x00000000) +/* Clean and invalidate physical address range */ +#define API_MONITOR_L2CACHE_CLEANINVBYPA_INDEX (API_MONITOR_BASE_INDEX + 0x00000001) +/* Enables/Disables the PL310 Cache */ +#define API_MONITOR_L2CACHE_SETCONTROL_INDEX (API_MONITOR_BASE_INDEX + 0x00000002) +/* Set the Auxiliary Control Register */ +#define API_MONITOR_L2CACHE_SETAUXILIARYCONTROL_INDEX (API_MONITOR_BASE_INDEX + 0x00000009) +/* Set the Data and Tag RAM Latency */ +#define API_MONITOR_L2CACHE_SETLATENCY_INDEX (API_MONITOR_BASE_INDEX + 0x00000012) +/* Set the Pre-fetch Control Register */ +#define API_MONITOR_L2CACHE_SETPREFETCHCONTROL_INDEX (API_MONITOR_BASE_INDEX + 0x00000013) + +#endif /* API_MONITOR_INDEX_H */ diff --git a/optee/optee_os/core/arch/arm/plat-ti/conf.mk b/optee/optee_os/core/arch/arm/plat-ti/conf.mk new file mode 100644 index 0000000..97a41cd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/conf.mk @@ -0,0 +1,39 @@ +PLATFORM_FLAVOR ?= dra7xx + +CFG_WITH_STATS ?= y +CFG_WITH_SOFTWARE_PRNG ?= n + +ifeq ($(PLATFORM_FLAVOR),dra7xx) +include core/arch/arm/cpu/cortex-a15.mk +$(call force,CFG_TEE_CORE_NB_CORE,2) +CFG_OTP_SUPPORT ?= y +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +endif #dra7xx + +ifeq ($(PLATFORM_FLAVOR),am57xx) +include core/arch/arm/cpu/cortex-a15.mk +$(call force,CFG_TEE_CORE_NB_CORE,2) +CFG_OTP_SUPPORT ?= y +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +endif #am57xx + +ifeq ($(PLATFORM_FLAVOR),am43xx) +include core/arch/arm/cpu/cortex-a9.mk +$(call force, CFG_TEE_CORE_NB_CORE,1) +CFG_WITH_SOFTWARE_PRNG = y +$(call force,CFG_NO_SMP,y) +$(call force,CFG_PL310,y) +$(call force,CFG_PL310_LOCKED,y) +$(call force,CFG_PM_ARM32,y) +$(call force,CFG_SECURE_TIME_SOURCE_REE,y) +endif #am43xx + +$(call force,CFG_8250_UART,y) +$(call force,CFG_ARM32_core,y) +$(call force,CFG_SM_PLATFORM_HANDLER,y) +$(call force,CFG_GIC,y) +ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) +$(call force,CFG_DRA7_RNG,y) +CFG_HWRNG_QUALITY ?= 1024 +CFG_HWRNG_PTA ?= y +endif diff --git a/optee/optee_os/core/arch/arm/plat-ti/main.c b/optee/optee_os/core/arch/arm/plat-ti/main.c new file mode 100644 index 0000000..c98c6b8 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/main.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLAT_HW_UNIQUE_KEY_LENGTH 32 + +static struct gic_data gic_data; +static struct serial8250_uart_data console_data; +static uint8_t plat_huk[PLAT_HW_UNIQUE_KEY_LENGTH]; + +register_phys_mem(MEM_AREA_RAM_SEC, TZDRAM_BASE, TEE_RAM_VA_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SECRAM_BASE, SECRAM_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GICC_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GICD_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, + SERIAL8250_UART_REG_SIZE); + +void main_init_gic(void) +{ + gic_init(&gic_data, GICC_BASE, GICD_BASE); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +struct plat_nsec_ctx { + uint32_t usr_sp; + uint32_t usr_lr; + uint32_t svc_sp; + uint32_t svc_lr; + uint32_t svc_spsr; + uint32_t abt_sp; + uint32_t abt_lr; + uint32_t abt_spsr; + uint32_t und_sp; + uint32_t und_lr; + uint32_t und_spsr; + uint32_t irq_sp; + uint32_t irq_lr; + uint32_t irq_spsr; + uint32_t fiq_sp; + uint32_t fiq_lr; + uint32_t fiq_spsr; + uint32_t fiq_rx[5]; + uint32_t mon_lr; + uint32_t mon_spsr; +}; + +struct plat_boot_args { + struct plat_nsec_ctx nsec_ctx; + uint8_t huk[PLAT_HW_UNIQUE_KEY_LENGTH]; +}; + +void init_sec_mon(unsigned long nsec_entry) +{ + struct plat_boot_args *plat_boot_args; + struct sm_nsec_ctx *nsec_ctx; + + plat_boot_args = phys_to_virt(nsec_entry, MEM_AREA_IO_SEC, 1); + if (!plat_boot_args) + panic(); + + /* Invalidate cache to fetch data from external memory */ + cache_op_inner(DCACHE_AREA_INVALIDATE, + plat_boot_args, sizeof(*plat_boot_args)); + + /* Initialize secure monitor */ + nsec_ctx = sm_get_nsec_ctx(); + + nsec_ctx->ub_regs.usr_sp = plat_boot_args->nsec_ctx.usr_sp; + nsec_ctx->ub_regs.usr_lr = plat_boot_args->nsec_ctx.usr_lr; + nsec_ctx->ub_regs.irq_spsr = plat_boot_args->nsec_ctx.irq_spsr; + nsec_ctx->ub_regs.irq_sp = plat_boot_args->nsec_ctx.irq_sp; + nsec_ctx->ub_regs.irq_lr = plat_boot_args->nsec_ctx.irq_lr; + nsec_ctx->ub_regs.svc_spsr = plat_boot_args->nsec_ctx.svc_spsr; + nsec_ctx->ub_regs.svc_sp = plat_boot_args->nsec_ctx.svc_sp; + nsec_ctx->ub_regs.svc_lr = plat_boot_args->nsec_ctx.svc_lr; + nsec_ctx->ub_regs.abt_spsr = plat_boot_args->nsec_ctx.abt_spsr; + nsec_ctx->ub_regs.abt_sp = plat_boot_args->nsec_ctx.abt_sp; + nsec_ctx->ub_regs.abt_lr = plat_boot_args->nsec_ctx.abt_lr; + nsec_ctx->ub_regs.und_spsr = plat_boot_args->nsec_ctx.und_spsr; + nsec_ctx->ub_regs.und_sp = plat_boot_args->nsec_ctx.und_sp; + nsec_ctx->ub_regs.und_lr = plat_boot_args->nsec_ctx.und_lr; + nsec_ctx->mon_lr = plat_boot_args->nsec_ctx.mon_lr; + nsec_ctx->mon_spsr = plat_boot_args->nsec_ctx.mon_spsr; + + memcpy(plat_huk, plat_boot_args->huk, sizeof(plat_boot_args->huk)); +} + +void console_init(void) +{ + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +#if defined(CFG_OTP_SUPPORT) + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + memcpy(&hwkey->data[0], &plat_huk[0], sizeof(hwkey->data)); + return TEE_SUCCESS; +} + +#endif diff --git a/optee/optee_os/core/arch/arm/plat-ti/platform_config.h b/optee/optee_os/core/arch/arm/plat-ti/platform_config.h new file mode 100644 index 0000000..73f9255 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/platform_config.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#define DRAM0_BASE 0x80000000 +#define DRAM0_SIZE 0x80000000 + +#if defined(PLATFORM_FLAVOR_dra7xx) || defined(PLATFORM_FLAVOR_am57xx) + +/* Location of protected DDR on the DRA7xx platform */ +#define TZDRAM_BASE 0xbdb00000 +#define TZDRAM_SIZE 0x01c00000 + +#ifdef CFG_WITH_PAGER +#define TZSRAM_BASE 0x40300000 +#define TZSRAM_SIZE (256 * 1024) +#endif /* CFG_WITH_PAGER */ + + +#define UART1_BASE 0x4806A000 +#define UART2_BASE 0x4806C000 +#define UART3_BASE 0x48020000 + +#if defined(PLATFORM_FLAVOR_dra7xx) +#define CONSOLE_UART_BASE UART1_BASE +#elif defined(PLATFORM_FLAVOR_am57xx) +#define CONSOLE_UART_BASE UART3_BASE +#else +#error "Unknown platform flavor" +#endif + +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 48000000 + +#define SCU_BASE 0x48210000 +#define GICC_OFFSET 0x2000 +#define GICC_SIZE 0x1000 +#define GICD_OFFSET 0x1000 +#define GICD_SIZE 0x1000 +#define GICC_BASE (SCU_BASE + GICC_OFFSET) +#define GICD_BASE (SCU_BASE + GICD_OFFSET) + +#define WUGEN_MPU_BASE 0x48281000 +#define WUGEN_MPU_SIZE 0x1000 + +#define SECRAM_BASE 0x40200000 +#define SECRAM_SIZE 0x00100000 + +/* RNG */ +#define RNG_BASE 0x48090000 + +#elif defined(PLATFORM_FLAVOR_am43xx) + +/* Location of protected DDR on the AM43xx platform */ +#define TZDRAM_BASE 0xbdb00000 +#define TZDRAM_SIZE 0x01c00000 + +#define UART0_BASE 0x44E09000 +#define UART1_BASE 0x48022000 +#define UART2_BASE 0x48024000 +#define UART3_BASE 0x481A6000 +#define UART4_BASE 0x481A8000 +#define UART5_BASE 0x481AA000 + +#define CONSOLE_UART_BASE UART0_BASE +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 48000000 + +#define SCU_BASE 0x48240000 +#define GICD_OFFSET 0x1000 +#define GICD_SIZE 0x1000 +#define GICC_OFFSET 0x0100 +#define GICC_SIZE 0x0100 +#define PL310_OFFSET 0x2000 +#define PL310_SIZE 0x1000 +#define GICD_BASE (SCU_BASE + GICD_OFFSET) +#define GICC_BASE (SCU_BASE + GICC_OFFSET) +#define PL310_BASE (SCU_BASE + PL310_OFFSET) + +#define SECRAM_BASE 0x402F0000 +#define SECRAM_SIZE 0x00100000 + +/* RNG */ +#define RNG_BASE 0x48310000 + +#else +#error "Unknown platform flavor" +#endif + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#ifdef CFG_WITH_PAGER +/* + * Use TZSRAM for TEE, page out everything else to TZDRAM. + * +--------+----------+ + * | DRAM | SHMEM | + * +--------+----------+ + * | | TA_RAM | + * | TZDRAM +----------+ + * | | PAGE_RAM | + * +--------+----------+ + * | TZSRAM | TEE_RAM | + * +--------+----------+ + */ +#define TEE_RAM_VA_SIZE (1 * 1024 * 1024) +#define TEE_RAM_PH_SIZE TZSRAM_SIZE +#define TEE_RAM_START TZSRAM_BASE +#define TEE_LOAD_ADDR (TEE_RAM_START + 0x1000) + +#else /* CFG_WITH_PAGER */ +/* + * Assumes that either TZSRAM isn't large enough or TZSRAM doesn't exist, + * everything is in TZDRAM. + * +--------+---------+ + * | DRAM | SHMEM | + * +--------+---------+ + * | | TA_RAM | + * | TZDRAM +---------+ + * | | TEE_RAM | + * +--------+---------+ + */ +#define TEE_RAM_VA_SIZE (1 * 1024 * 1024) +#define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE +#define TEE_RAM_START TZDRAM_BASE +#define TEE_LOAD_ADDR TEE_RAM_START + +#endif /* CFG_WITH_PAGER */ + +#define TA_RAM_START ROUNDUP((TZDRAM_BASE + TEE_RAM_VA_SIZE), \ + CORE_MMU_PGDIR_SIZE) + +#define TA_RAM_SIZE ROUNDDOWN((TZDRAM_SIZE - TEE_RAM_VA_SIZE), \ + CORE_MMU_PGDIR_SIZE) + +/* Full GlobalPlatform test suite requires TEE_SHMEM_SIZE to be at least 2MB */ +#define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) +#define TEE_SHMEM_SIZE (4 * 1024 * 1024) + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a15.c b/optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a15.c new file mode 100644 index 0000000..8cd2a34 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a15.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew Davis + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "api_monitor_index_a15.h" + +#define WUGEN_MPU_AMBA_IF_MODE 0x80c + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, WUGEN_MPU_BASE, WUGEN_MPU_SIZE); + +static vaddr_t wugen_mpu_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(WUGEN_MPU_BASE, MEM_AREA_IO_SEC, + WUGEN_MPU_SIZE); + return (vaddr_t)va; + } + + return WUGEN_MPU_BASE; +} + +static void write_wugen_mpu_amba_if_mode(uint32_t val) +{ + io_write32(wugen_mpu_base() + WUGEN_MPU_AMBA_IF_MODE, val); +} + +static enum sm_handler_ret ti_sip_handler(struct thread_smc_args *smc_args) +{ + uint16_t sip_func = OPTEE_SMC_FUNC_NUM(smc_args->a0); + + switch (sip_func) { + case API_MONITOR_ACTLR_SETREGISTER_INDEX: + write_actlr(smc_args->a1); + isb(); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + case API_MONITOR_TIMER_SETCNTFRQ_INDEX: + write_cntfrq(smc_args->a1); + isb(); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + case API_MONITOR_WUGEN_MPU_SETAMBAIF_INDEX: + write_wugen_mpu_amba_if_mode(smc_args->a1); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + default: + EMSG("Invalid SIP function code: 0x%04"PRIx16, sip_func); + smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD; + break; + } + + return SM_HANDLER_SMC_HANDLED; +} + +enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) +{ + uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); + uint16_t smc_owner = OPTEE_SMC_OWNER_NUM(*nsec_r0); + + switch (smc_owner) { + case OPTEE_SMC_OWNER_SIP: + return ti_sip_handler((struct thread_smc_args *)nsec_r0); + default: + return SM_HANDLER_PENDING_SMC; + } +} diff --git a/optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a9.c b/optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a9.c new file mode 100644 index 0000000..8d628d1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/sm_platform_handler_a9.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew Davis + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "api_monitor_index_a9.h" + +uint32_t suspend_regs[16]; + +static enum sm_handler_ret ti_sip_handler(struct thread_smc_args *smc_args) +{ + uint16_t sip_func = OPTEE_SMC_FUNC_NUM(smc_args->a0); + + switch (sip_func) { + case SECURE_SVC_PM_LATE_SUSPEND: + sm_pm_cpu_do_suspend(suspend_regs); + cache_op_inner(DCACHE_AREA_CLEAN, suspend_regs, + sizeof(suspend_regs)); + cache_op_outer(DCACHE_AREA_CLEAN, virt_to_phys(suspend_regs), + sizeof(suspend_regs)); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + case API_MONITOR_L2CACHE_SETDEBUG_INDEX: + io_write32(pl310_base() + PL310_DEBUG_CTRL, smc_args->a1); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + case API_MONITOR_L2CACHE_CLEANINVBYPA_INDEX: + arm_cl2_cleaninvbypa(pl310_base(), smc_args->a1, + smc_args->a1 + smc_args->a2); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + case API_MONITOR_L2CACHE_SETCONTROL_INDEX: + io_write32(pl310_base() + PL310_CTRL, smc_args->a1); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + case API_MONITOR_L2CACHE_SETAUXILIARYCONTROL_INDEX: + io_write32(pl310_base() + PL310_AUX_CTRL, smc_args->a1); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + case API_MONITOR_L2CACHE_SETLATENCY_INDEX: + io_write32(pl310_base() + PL310_TAG_RAM_CTRL, smc_args->a1); + io_write32(pl310_base() + PL310_DATA_RAM_CTRL, smc_args->a2); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + case API_MONITOR_L2CACHE_SETPREFETCHCONTROL_INDEX: + io_write32(pl310_base() + PL310_PREFETCH_CTRL, smc_args->a1); + smc_args->a0 = OPTEE_SMC_RETURN_OK; + break; + default: + EMSG("Invalid SIP function code: 0x%04"PRIx16, sip_func); + smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD; + break; + } + + return SM_HANDLER_SMC_HANDLED; +} + +enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) +{ + uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); + uint16_t smc_owner = OPTEE_SMC_OWNER_NUM(*nsec_r0); + + switch (smc_owner) { + case OPTEE_SMC_OWNER_SIP: + return ti_sip_handler((struct thread_smc_args *)nsec_r0); + default: + return SM_HANDLER_PENDING_SMC; + } +} diff --git a/optee/optee_os/core/arch/arm/plat-ti/sub.mk b/optee/optee_os/core/arch/arm/plat-ti/sub.mk new file mode 100644 index 0000000..0b4c385 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/sub.mk @@ -0,0 +1,6 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-$(CFG_PL310) += ti_pl310.c +srcs-$(PLATFORM_FLAVOR_dra7xx) += sm_platform_handler_a15.c +srcs-$(PLATFORM_FLAVOR_am57xx) += sm_platform_handler_a15.c +srcs-$(PLATFORM_FLAVOR_am43xx) += sm_platform_handler_a9.c a9_plat_init.S diff --git a/optee/optee_os/core/arch/arm/plat-ti/ti_pl310.c b/optee/optee_os/core/arch/arm/plat-ti/ti_pl310.c new file mode 100644 index 0000000..f4a3dd6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-ti/ti_pl310.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew Davis + */ + +#include +#include +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, PL310_SIZE); + +vaddr_t pl310_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC, + PL310_SIZE); + return (vaddr_t)va; + } + + return PL310_BASE; +} + +/* ROM handles initial setup for us */ +void arm_cl2_config(vaddr_t pl310_base) +{ + (void)pl310_base; +} + +/* We provide platform services that expect the cache to be disabled on boot */ +void arm_cl2_enable(vaddr_t pl310_base) +{ + (void)pl310_base; +} diff --git a/optee/optee_os/core/arch/arm/plat-totalcompute/conf.mk b/optee/optee_os/core/arch/arm/plat-totalcompute/conf.mk new file mode 100644 index 0000000..2f6c0ee --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-totalcompute/conf.mk @@ -0,0 +1,45 @@ +ifneq (,$(filter ${PLATFORM_FLAVOR},tc0 tc1 tc2)) +include core/arch/arm/cpu/cortex-armv8-0.mk +platform-debugger-arm := 1 +endif + +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_GENERIC_BOOT,y) +ifeq ($(CFG_CORE_SEL2_SPMC),y) +$(call force,CFG_GIC,n) +$(call force,CFG_ARM_GICV3,n) +else +$(call force,CFG_GIC,y) +$(call force,CFG_ARM_GICV3,y) +endif +$(call force,CFG_PL011,y) +$(call force,CFG_PM_STUBS,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_ARM64_core,y) + +ifeq ($(platform-debugger-arm),1) +# ARM debugger needs this +platform-cflags-debug-info = -gdwarf-2 +platform-aflags-debug-info = -gdwarf-2 +endif + +$(call force,CFG_CORE_ARM64_PA_BITS,40) + +ifneq (,$(filter ${PLATFORM_FLAVOR},tc0 tc1 tc2)) +CFG_TEE_CORE_NB_CORE = 8 + +ifeq ($(CFG_CORE_SEL1_SPMC),y) +CFG_TZDRAM_START ?= 0xfd000000 +CFG_TZDRAM_SIZE ?= 0x02000000 +else ifeq ($(CFG_CORE_SEL2_SPMC),y) +CFG_TZDRAM_START ?= 0xfd284000 +# TZDRAM size 0x1980000 - 0x4000 manifest size +CFG_TZDRAM_SIZE ?= 0x0197c000 +else +CFG_TZDRAM_START ?= 0xff000000 +CFG_TZDRAM_SIZE ?= 0x01000000 +endif + +CFG_SHMEM_START ?= 0xfce00000 +CFG_SHMEM_SIZE ?= 0x00200000 +endif diff --git a/optee/optee_os/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts b/optee/optee_os/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts new file mode 100644 index 0000000..9464fb1 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. + * + * This file is a Partition Manifest (PM) for OP-TEE as a Secure Partition (SP) + * + */ + +/dts-v1/; + +/ { + compatible = "arm,ffa-manifest-1.0"; + + /* Properties */ + description = "op-tee"; + ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */ + uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>; + id = <1>; + execution-ctx-count = <8>; + exception-level = <2>; /* S-EL1 */ + execution-state = <0>; /* AARCH64 */ + load-address = <0xfd280000>; + entrypoint-offset = <0x4000>; + xlat-granule = <0>; /* 4KiB */ + boot-order = <0>; + messaging-method = <0x3>; /* Direct request/response supported */ + + device-regions { + compatible = "arm,ffa-manifest-device-regions"; + ap_s_uart { + base-address = <0x00000000 0x2A410000>; + pages-count = <1>; + attributes = <0x3>; /* read-write */ + }; + }; +}; diff --git a/optee/optee_os/core/arch/arm/plat-totalcompute/main.c b/optee/optee_os/core/arch/arm/plat-totalcompute/main.c new file mode 100644 index 0000000..487a606 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-totalcompute/main.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifndef CFG_CORE_SEL2_SPMC +static struct gic_data gic_data __nex_bss; +#endif +static struct pl011_data console_data __nex_bss; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE); +#ifndef CFG_CORE_SEL2_SPMC +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); +#endif + +register_ddr(DRAM0_BASE, DRAM0_SIZE); +register_ddr(DRAM1_BASE, DRAM1_SIZE); + +#ifndef CFG_CORE_SEL2_SPMC +void main_init_gic(void) +{ + /* + * On ARMv8, GIC configuration is initialized in ARM-TF + * gicd base address is same as gicc_base. + */ + gic_init_base_addr(&gic_data, GIC_BASE + GICC_OFFSET, + GIC_BASE + GICC_OFFSET); + itr_init(&gic_data.chip); +} +#endif + +void itr_core_handler(void) +{ +#ifdef CFG_CORE_SEL2_SPMC + panic("Secure interrupt handler not defined"); +#else + gic_it_handle(&gic_data); +#endif +} + +void console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, + CONSOLE_UART_BAUDRATE); + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-totalcompute/platform_config.h b/optee/optee_os/core/arch/arm/plat-totalcompute/platform_config.h new file mode 100644 index 0000000..2b34cd0 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-totalcompute/platform_config.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#if (defined(PLATFORM_FLAVOR_tc0) || \ + defined(PLATFORM_FLAVOR_tc1) || \ + defined(PLATFORM_FLAVOR_tc2)) +#ifndef CFG_CORE_SEL2_SPMC +#define GIC_BASE 0x30000000 +#define GICD_OFFSET 0x0 +#define GICC_OFFSET 0x0 +#endif + +#define UART0_BASE 0x2A410000 +#define UART1_BASE 0x2A400000 + +#define CONSOLE_UART_BASE UART0_BASE + +#define DRAM0_BASE 0x80000000 +#define DRAM0_SIZE 0x7d000000 + +#define DRAM1_BASE 0x8080000000ULL +#define DRAM1_SIZE 0x180000000ULL + +#define TZCDRAM_BASE 0xff000000 +#define TZCDRAM_SIZE 0x01000000 + +#else +#error "Unknown platform flavor" +#endif + +#ifdef GIC_BASE +#define GICD_BASE (GIC_BASE + GICD_OFFSET) +#define GICC_BASE (GIC_BASE + GICC_OFFSET) +#endif + +#define CONSOLE_UART_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 7372800 + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-totalcompute/sub.mk b/optee/optee_os/core/arch/arm/plat-totalcompute/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-totalcompute/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-uniphier/conf.mk b/optee/optee_os/core/arch/arm/plat-uniphier/conf.mk new file mode 100644 index 0000000..59e47fb --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-uniphier/conf.mk @@ -0,0 +1,46 @@ +PLATFORM_FLAVOR ?= ld20 + +include core/arch/arm/cpu/cortex-armv8-0.mk + +ifeq ($(PLATFORM_FLAVOR),ld20) +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +CFG_DRAM0_BASE ?= 0x80000000 +CFG_DRAM0_SIZE ?= 0xc0000000 +CFG_DRAM0_RSV_SIZE ?= 0x02000000 +endif + +ifeq ($(PLATFORM_FLAVOR),ld11) +$(call force,CFG_TEE_CORE_NB_CORE,2) +CFG_DRAM0_BASE ?= 0x80000000 +CFG_DRAM0_SIZE ?= 0x40000000 +CFG_DRAM0_RSV_SIZE ?= 0x02000000 +endif + +CFG_TZDRAM_START ?= (CFG_DRAM0_BASE + 0x01080000) +CFG_TZDRAM_SIZE ?= 0x00E00000 +CFG_SHMEM_START ?= (CFG_DRAM0_BASE + 0x00E00000) +CFG_SHMEM_SIZE ?= 0x00200000 +CFG_TEE_RAM_VA_SIZE ?= 0x00100000 + +# 32-bit flags +core_arm32-platform-aflags += -mfpu=neon + +$(call force,CFG_HWSUPP_MEM_PERM_PXN,y) +$(call force,CFG_GIC,y) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_8250_UART,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_CORE_CLUSTER_SHIFT,1) + +ta-targets = ta_arm32 + +ifeq ($(CFG_ARM64_core),y) +ta-targets += ta_arm64 +else +$(call force,CFG_ARM32_core,y) +endif + +CFG_NUM_THREADS ?= 4 +CFG_CRYPTO_WITH_CE ?= y diff --git a/optee/optee_os/core/arch/arm/plat-uniphier/kern.ld.S b/optee/optee_os/core/arch/arm/plat-uniphier/kern.ld.S new file mode 100644 index 0000000..f031e62 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-uniphier/kern.ld.S @@ -0,0 +1,2 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND MIT) */ +#include "../kernel/kern.ld.S" diff --git a/optee/optee_os/core/arch/arm/plat-uniphier/main.c b/optee/optee_os/core/arch/arm/plat-uniphier/main.c new file mode 100644 index 0000000..253f933 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-uniphier/main.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2017, Socionext Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(GIC_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +#ifdef DRAM0_BASE +register_ddr(DRAM0_BASE, DRAM0_SIZE); +#endif +#ifdef DRAM1_BASE +register_ddr(DRAM1_BASE, DRAM1_SIZE); +#endif + +static struct gic_data gic_data; + +static struct serial8250_uart_data console_data; + +void main_init_gic(void) +{ + gic_init_base_addr(&gic_data, GIC_BASE + GICC_OFFSET, + GIC_BASE + GICD_OFFSET); + itr_init(&gic_data.chip); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ + /* Init UART */ + serial8250_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + + /* Register console */ + register_serial_console(&console_data.chip); +} diff --git a/optee/optee_os/core/arch/arm/plat-uniphier/platform_config.h b/optee/optee_os/core/arch/arm/plat-uniphier/platform_config.h new file mode 100644 index 0000000..10f3476 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-uniphier/platform_config.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2017, Socionext Inc. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +/* GIC */ +#define GIC_BASE 0x5FE00000 +#define GICD_OFFSET 0 +#define GICC_OFFSET 0x80000 + +/* UART */ +#define UART_CH 0 +#define UART_BASE 0x54006800 +#define CONSOLE_UART_BASE (UART_BASE + 0x100 * UART_CH) +#define CONSOLE_BAUDRATE 115200 +#define CONSOLE_UART_CLK_IN_HZ 58820000 + +/* + * UniPhier memory map + * + * 0xXXXX_XXXX + * Linux kernel and user space | DRAM#0-#x | Normal memory + * 0x8200_0000 [DRAM0_BASE] - - + * unused | | + * 0x81E8_0000 | | + * TA RAM: 13 MiB | TZDRAM | + * 0x8118_0000 | | Secure memory + * TEE RAM: 1 MiB (CFG_TEE_RAM_VA_SIZE) | | + * 0x8108_0000 [CFG_TZDRAM_START] - | + * BL31 runtime: 512 KiB | | + * 0x8100_0000 | - + * Shared memory: 2 MiB (CFG_SHMEM_SIZE) | | + * 0x80E0_0000 [CFG_SHMEM_START] | DRAM#0 | Normal memory + * reserved | | + * 0x8008_0000 | | + * BL2: 512 KiB | | + * 0x8000_0000 [CFG_DRAM0_BASE] - - + */ + +#define DRAM0_BASE (CFG_DRAM0_BASE + CFG_DRAM0_RSV_SIZE) +#define DRAM0_SIZE (CFG_DRAM0_SIZE - CFG_DRAM0_RSV_SIZE) + +#define CFG_TEE_LOAD_ADDR CFG_TZDRAM_START + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-uniphier/sub.mk b/optee/optee_os/core/arch/arm/plat-uniphier/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-uniphier/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-versal/conf.mk b/optee/optee_os/core/arch/arm/plat-versal/conf.mk new file mode 100644 index 0000000..645462d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-versal/conf.mk @@ -0,0 +1,88 @@ +PLATFORM_FLAVOR ?= generic + +include core/arch/arm/cpu/cortex-armv8-0.mk + +CFG_MMAP_REGIONS ?= 24 + +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_ARM_GICV3,y) +$(call force,CFG_PL011,y) +$(call force,CFG_GIC,y) + +# Disable core ASLR for two reasons: +# 1. There is no source for ALSR seed, as TF-a does not provide a +# DTB to OP-TEE. Hardware RNG is also not currently supported. +# 2. Xilinx's bootgen can't find the OP-TEE entry point from the TEE.elf file +# used to generate boot.bin. Enabling ASLR requires an update to TF-A. +$(call force,CFG_CORE_ASLR,n) + +CFG_CRYPTO_WITH_CE ?= y +CFG_CORE_DYN_SHM ?= y +CFG_WITH_STATS ?= y +CFG_ARM64_core ?= y + +CFG_TZDRAM_START ?= 0x60000000 +CFG_TZDRAM_SIZE ?= 0x10000000 +CFG_SHMEM_START ?= 0x70000000 +CFG_SHMEM_SIZE ?= 0x10000000 + +ifeq ($(CFG_ARM64_core),y) +$(call force,CFG_CORE_ARM64_PA_BITS,43) +else +$(call force,CFG_ARM32_core,y) +endif + +# GPIO +CFG_VERSAL_GPIO ?= y + +# Debug information +CFG_VERSAL_TRACE_MBOX ?= n +CFG_VERSAL_TRACE_PLM ?= n + +$(call force, CFG_VERSAL_MBOX,y) + +# MBOX configuration +CFG_VERSAL_MBOX_IPI_ID ?= 3 + +$(call force, CFG_VERSAL_RNG_DRV,y) +$(call force, CFG_WITH_SOFTWARE_PRNG,n) + +# TRNG configuration +CFG_VERSAL_TRNG_SEED_LIFE ?= 3 +CFG_VERSAL_TRNG_DF_MUL ?= 2 + +# eFuse and BBRAM driver +$(call force, CFG_VERSAL_NVM,y) + +# Crypto driver +CFG_VERSAL_CRYPTO_DRIVER ?= y +ifeq ($(CFG_VERSAL_CRYPTO_DRIVER),y) +# Disable Fault Mitigation: triggers false positives due to +# the driver's software fallback operations - need further work +CFG_FAULT_MITIGATION ?= n +endif + +# SHA3-384 crypto engine +CFG_VERSAL_SHA3_384 ?= y + +# PM driver +CFG_VERSAL_PM ?= y + +# Physical Unclonable Function +CFG_VERSAL_PUF ?= y + +# Enable Hardware Unique Key driver +CFG_VERSAL_HUK ?= y +# AES-GCM supported key sources for HUK: +# 6 : eFUSE USR 0 +# 7 : eFuse USR 1 +# 11 : PUF KEK +# 12 : AES User Key 0 (devel) +CFG_VERSAL_HUK_KEY ?= 12 +ifneq ($(CFG_VERSAL_HUK_KEY),$(filter 6 7 11 12,$(firstword $(CFG_VERSAL_HUK_KEY)))) +$(error Invalid value: CFG_VERSAL_HUK_KEY=$(CFG_VERSAL_HUK_KEY)) +endif + +CFG_CORE_HEAP_SIZE ?= 262144 diff --git a/optee/optee_os/core/arch/arm/plat-versal/main.c b/optee/optee_os/core/arch/arm/plat-versal/main.c new file mode 100644 index 0000000..eb66826 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-versal/main.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VERSAL_AHWROT_SECURED 0xA5A5A5A5 +#define VERSAL_SHWROT_SECURED 0x96969696 +#define VERSAL_AHWROT_REG 0x14C +#define VERSAL_SHWROT_REG 0x150 + +static struct gic_data gic_data; +static struct pl011_data console_data; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + GIC_BASE, CORE_MMU_PGDIR_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE); + +register_phys_mem(MEM_AREA_IO_SEC, PLM_RTCA, PLM_RTCA_LEN); + +register_ddr(DRAM0_BASE, DRAM0_SIZE); + +#if defined(DRAM1_BASE) +register_ddr(DRAM1_BASE, DRAM1_SIZE); +register_ddr(DRAM2_BASE, DRAM2_SIZE); +#endif + +void main_init_gic(void) +{ + /* On ARMv8, GIC configuration is initialized in ARM-TF */ + gic_init_base_addr(&gic_data, + GIC_BASE + GICC_OFFSET, + GIC_BASE + GICD_OFFSET); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +static TEE_Result platform_banner(void) +{ + vaddr_t plm_rtca = (vaddr_t)phys_to_virt(PLM_RTCA, MEM_AREA_IO_SEC, + PLM_RTCA_LEN); + const char *ahwrot_str = "OFF"; + const char *shwrot_str = "OFF"; + uint8_t version = 0; + + assert(plm_rtca); + + if (versal_soc_version(&version)) { + EMSG("Failure to retrieve SoC version"); + return TEE_ERROR_GENERIC; + } + + IMSG("Platform Versal:\tSilicon Revision v%"PRIu8, version); + + if (io_read32(plm_rtca + VERSAL_AHWROT_REG) == VERSAL_AHWROT_SECURED) + ahwrot_str = "ON"; + + if (io_read32(plm_rtca + VERSAL_SHWROT_REG) == VERSAL_SHWROT_SECURED) + shwrot_str = "ON"; + + IMSG("Hardware Root of Trust: Asymmetric[%s], Symmetric[%s]", + ahwrot_str, shwrot_str); + + return TEE_SUCCESS; +} + +#if defined(CFG_RPMB_FS) +bool plat_rpmb_key_is_ready(void) +{ + vaddr_t plm_rtca = (vaddr_t)phys_to_virt(PLM_RTCA, MEM_AREA_IO_SEC, + PLM_RTCA_LEN); + + assert(plm_rtca); + + if (io_read32(plm_rtca + VERSAL_AHWROT_REG) == VERSAL_AHWROT_SECURED) + return true; + + if (io_read32(plm_rtca + VERSAL_SHWROT_REG) == VERSAL_SHWROT_SECURED) + return true; + + return false; +} +#endif + +service_init(platform_banner); + +#if defined(CFG_VERSAL_FPGA_DDR_ADDR) +static TEE_Result program_fpga(void) +{ + return versal_write_fpga(CFG_VERSAL_FPGA_DDR_ADDR); +} + +service_init(program_fpga); +#endif diff --git a/optee/optee_os/core/arch/arm/plat-versal/platform_config.h b/optee/optee_os/core/arch/arm/plat-versal/platform_config.h new file mode 100644 index 0000000..8f9b367 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-versal/platform_config.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define CACHELINE_LEN 64 +#define STACK_ALIGNMENT CACHELINE_LEN + +#if defined(PLATFORM_FLAVOR_generic) + +#define PLM_RTCA 0xF2014000 +#define PLM_RTCA_LEN 0x1000 + +#define GIC_BASE 0xF9000000 +#define UART0_BASE 0xFF000000 +#define UART1_BASE 0xFF010000 + +#define IT_UART0 50 +#define IT_UART1 51 + +#define UART0_CLK_IN_HZ 100000000 +#define UART1_CLK_IN_HZ 100000000 +#define CONSOLE_UART_BASE UART0_BASE +#define IT_CONSOLE_UART IT_UART0 +#define CONSOLE_UART_CLK_IN_HZ UART0_CLK_IN_HZ + +#define DRAM0_BASE 0 +#define DRAM0_SIZE 0x80000000 + +#ifdef ARM64 +/* DDR High area base is only available when compiling for 64 bits */ +#define DRAM1_BASE 0x800000000 +#define DRAM1_SIZE 0x180000000 +#define DRAM2_BASE 0x50000000000 +#define DRAM2_SIZE 0x200000000 +#endif + +#define GICD_OFFSET 0 +#define GICC_OFFSET 0x40000 + +#else +#error "Unknown platform flavor" +#endif + +#ifdef CFG_TEE_LOAD_ADDR +#define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR +#else +#define TEE_LOAD_ADDR TEE_RAM_START +#endif + +#ifndef UART_BAUDRATE +#define UART_BAUDRATE 115200 +#endif +#ifndef CONSOLE_BAUDRATE +#define CONSOLE_BAUDRATE UART_BAUDRATE +#endif + +#endif /* PLATFORM_CONFIG_H */ diff --git a/optee/optee_os/core/arch/arm/plat-versal/sub.mk b/optee/optee_os/core/arch/arm/plat-versal/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-versal/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/plat-vexpress/conf.mk b/optee/optee_os/core/arch/arm/plat-vexpress/conf.mk new file mode 100644 index 0000000..e5ef10a --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/conf.mk @@ -0,0 +1,152 @@ +PLATFORM_FLAVOR ?= qemu_virt + +ifeq ($(PLATFORM_FLAVOR),qemu_virt) +include core/arch/arm/cpu/cortex-a15.mk +endif +ifeq ($(PLATFORM_FLAVOR),fvp) +include core/arch/arm/cpu/cortex-armv8-0.mk +platform-debugger-arm := 1 +endif +ifeq ($(PLATFORM_FLAVOR),juno) +include core/arch/arm/cpu/cortex-armv8-0.mk +platform-debugger-arm := 1 +# Workaround 808870: Unconditional VLDM instructions might cause an +# alignment fault even though the address is aligned +# Either hard float must be disabled for AArch32 or strict alignment checks +# must be disabled +ifeq ($(CFG_SCTLR_ALIGNMENT_CHECK),y) +$(call force,CFG_TA_ARM32_NO_HARD_FLOAT_SUPPORT,y) +else +$(call force,CFG_SCTLR_ALIGNMENT_CHECK,n) +endif +endif #juno +ifeq ($(PLATFORM_FLAVOR),qemu_armv8a) +include core/arch/arm/cpu/cortex-armv8-0.mk +CFG_ARM64_core ?= y +default-user-ta-target ?= ta_arm64 +endif + + +ifeq ($(platform-debugger-arm),1) +# ARM debugger needs this +platform-cflags-debug-info = -gdwarf-2 +platform-aflags-debug-info = -gdwarf-2 +endif + +ifeq ($(platform-flavor-armv8),1) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) +endif + +$(call force,CFG_PL011,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) + +ifeq ($(CFG_CORE_TPM_EVENT_LOG),y) +# NOTE: Below values for the TPM event log are implementation +# dependent and used mostly for debugging purposes. +# Care must be taken to properly configure them if used. +CFG_TPM_LOG_BASE_ADDR ?= 0x402c951 +CFG_TPM_MAX_LOG_SIZE ?= 0x200 +endif + +ifneq ($(CFG_ARM64_core),y) +$(call force,CFG_ARM32_core,y) +endif + +CFG_WITH_STATS ?= y +CFG_ENABLE_EMBEDDED_TESTS ?= y + +ifeq ($(CFG_CORE_SEL2_SPMC),y) +$(call force,CFG_CORE_RESERVED_SHM,n) +CFG_GIC ?= n +else +$(call force,CFG_GIC,y) +endif + +ifeq ($(PLATFORM_FLAVOR),fvp) +CFG_TEE_CORE_NB_CORE = 8 +ifeq ($(CFG_CORE_SEL2_SPMC),y) +CFG_TZDRAM_START ?= 0x06281000 +CFG_TZDRAM_SIZE ?= 0x01D80000 +else +CFG_TZDRAM_START ?= 0x06000000 +CFG_TZDRAM_SIZE ?= 0x02000000 +endif +CFG_SHMEM_START ?= 0x83000000 +CFG_SHMEM_SIZE ?= 0x00200000 +# DRAM1 is defined above 4G +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +ifeq ($(CFG_SCMI_SCPFW),y) +$(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp) +endif +endif + +ifeq ($(PLATFORM_FLAVOR),juno) +CFG_TEE_CORE_NB_CORE = 6 +CFG_TZDRAM_START ?= 0xff000000 +CFG_TZDRAM_SIZE ?= 0x00ff8000 +CFG_SHMEM_START ?= 0xfee00000 +CFG_SHMEM_SIZE ?= 0x00200000 +# DRAM1 is defined above 4G +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_CORE_ARM64_PA_BITS,36) +CFG_CRYPTO_WITH_CE ?= y +CFG_ARM_SMCCC_TRNG ?= y +CFG_WITH_SOFTWARE_PRNG ?= n +endif + +ifeq ($(PLATFORM_FLAVOR),qemu_virt) +CFG_TEE_CORE_NB_CORE = 4 +# [0e00.0000 0e0f.ffff] is reserved to early boot +CFG_TZDRAM_START ?= 0x0e100000 +CFG_TZDRAM_SIZE ?= 0x00f00000 +CFG_SHMEM_START ?= 0x7fe00000 +CFG_SHMEM_SIZE ?= 0x00200000 +# When Secure Data Path is enable, last MByte of TZDRAM is SDP test memory. +CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 +# Set VA space to 2MB for Kasan offset to match LPAE and 32bit MMU configs +CFG_TEE_RAM_VA_SIZE ?= 0x00200000 +ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y) +# CFG_ASAN_SHADOW_OFFSET is calculated as: +# (&__asan_shadow_start - (TEE_RAM_VA_START / 8) +# This is unfortunately currently not possible to do in make so we have to +# calculate it offline, there's some asserts in +# core/arch/arm/kernel/generic_boot.c to check that we got it right +CFG_ASAN_SHADOW_OFFSET = 0xc6a71c0 +endif +$(call force,CFG_BOOT_SECONDARY_REQUEST,y) +$(call force,CFG_PSCI_ARM32,y) +$(call force,CFG_DT,y) +CFG_DTB_MAX_SIZE ?= 0x100000 +CFG_CORE_ASYNC_NOTIF ?= y +CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219 +endif + +ifeq ($(PLATFORM_FLAVOR),qemu_armv8a) +CFG_TEE_CORE_NB_CORE = 4 +ifneq ($(CFG_CORE_SEL2_SPMC),y) +# [0e00.0000 0e0f.ffff] is reserved to early boot +CFG_TZDRAM_START ?= 0x0e100000 +CFG_TZDRAM_SIZE ?= 0x00f00000 +# SHM chosen arbitrary, in a way that it does not interfere +# with initial location of linux kernel, dtb and initrd. +CFG_SHMEM_START ?= 0x42000000 +CFG_SHMEM_SIZE ?= 0x00200000 +# When Secure Data Path is enable, last MByte of TZDRAM is SDP test memory. +CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 +endif +$(call force,CFG_DT,y) +CFG_DTB_MAX_SIZE ?= 0x100000 +ifeq ($(CFG_SCMI_SCPFW),y) +$(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp) +endif +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),qemu_virt qemu_armv8a)) +CFG_DT_DRIVER_EMBEDDED_TEST ?= y +ifeq ($(CFG_DT_DRIVER_EMBEDDED_TEST),y) +$(call force,CFG_EMBED_DTB_SOURCE_FILE,embedded_dtb_test.dts,Mandated for DT tests) +endif +endif + +CFG_PKCS11_TA ?= y diff --git a/optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a32.S b/optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a32.S new file mode 100644 index 0000000..2887172 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a32.S @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include + +/* For Juno number the two A57s as 4 to 5 and A53s as 0 to 3 */ +FUNC get_core_pos_mpidr , : + /* Calculate CorePos = ((ClusterId ^ 1) * 4) + CoreId */ + and r1, r0, #MPIDR_CPU_MASK + and r0, r0, #MPIDR_CLUSTER_MASK + eor r0, r0, #(1 << MPIDR_CLUSTER_SHIFT) + add r0, r1, r0, LSR #6 + bx lr +END_FUNC get_core_pos_mpidr + diff --git a/optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a64.S b/optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a64.S new file mode 100644 index 0000000..b3a2352 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/juno_core_pos_a64.S @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#include +#include + +/* For Juno number the two A57s as 4 to 5 and A53s as 0 to 3 */ +FUNC get_core_pos_mpidr , : + /* Calculate CorePos = ((ClusterId ^ 1) * 4) + CoreId */ + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + eor x0, x0, #(1 << MPIDR_CLUSTER_SHIFT) + add x0, x1, x0, LSR #6 + ret +END_FUNC get_core_pos_mpidr diff --git a/optee/optee_os/core/arch/arm/plat-vexpress/main.c b/optee/optee_os/core/arch/arm/plat-vexpress/main.c new file mode 100644 index 0000000..09932c7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/main.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2020, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct gic_data gic_data __maybe_unused __nex_bss; +static struct hfic_data hfic_data __maybe_unused __nex_bss; +static struct pl011_data console_data __nex_bss; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE); +#if defined(PLATFORM_FLAVOR_fvp) +register_phys_mem(MEM_AREA_RAM_SEC, TZCDRAM_BASE, TZCDRAM_SIZE); +#endif +#if defined(PLATFORM_FLAVOR_qemu_virt) +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SECRAM_BASE, SECRAM_COHERENT_SIZE); +#endif +#ifdef DRAM0_BASE +register_ddr(DRAM0_BASE, DRAM0_SIZE); +#endif +#ifdef DRAM1_BASE +register_ddr(DRAM1_BASE, DRAM1_SIZE); +#endif + +#ifdef CFG_GIC +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_DIST_REG_SIZE); + +void main_init_gic(void) +{ +#if defined(CFG_WITH_ARM_TRUSTED_FW) + /* On ARMv8, GIC configuration is initialized in ARM-TF */ + gic_init_base_addr(&gic_data, GIC_BASE + GICC_OFFSET, + GIC_BASE + GICD_OFFSET); +#else + gic_init(&gic_data, GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); +#endif + itr_init(&gic_data.chip); +} + +#if !defined(CFG_WITH_ARM_TRUSTED_FW) +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} +#endif + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} +#endif /*CFG_GIC*/ + +#ifdef CFG_CORE_HAFNIUM_INTC +void main_init_gic(void) +{ + hfic_init(&hfic_data); + itr_init(&hfic_data.chip); +} + +void itr_core_handler(void) +{ + hfic_it_handle(&hfic_data); +} +#endif + +void console_init(void) +{ + pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, + CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +#if (defined(CFG_GIC) || defined(CFG_CORE_HAFNIUM_INTC)) && \ + defined(IT_CONSOLE_UART) && \ + !defined(CFG_NS_VIRTUALIZATION) && \ + !(defined(CFG_WITH_ARM_TRUSTED_FW) && defined(CFG_ARM_GICV2)) +/* + * This cannot be enabled with TF-A and GICv3 because TF-A then need to + * assign the interrupt number of the UART to OP-TEE (S-EL1). Currently + * there's no way of TF-A to know which interrupts that OP-TEE will serve. + * If TF-A doesn't assign the interrupt we're enabling below to OP-TEE it + * will hang in EL3 since the interrupt will just be delivered again and + * again. + */ + +static void read_console(void) +{ + struct serial_chip *cons = &console_data.chip; + + if (!cons->ops->getchar || !cons->ops->have_rx_data) + return; + + while (cons->ops->have_rx_data(cons)) { + int ch __maybe_unused = cons->ops->getchar(cons); + + DMSG("got 0x%x", ch); + } +} + +static enum itr_return console_itr_cb(struct itr_handler *h __maybe_unused) +{ + if (notif_async_is_started()) { + /* + * Asynchronous notifications are enabled, lets read from + * uart in the bottom half instead. + */ + itr_disable(IT_CONSOLE_UART); + notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF); + } else { + read_console(); + } + return ITRR_HANDLED; +} + +static struct itr_handler console_itr = { + .it = IT_CONSOLE_UART, + .flags = ITRF_TRIGGER_LEVEL, + .handler = console_itr_cb, +}; +DECLARE_KEEP_PAGER(console_itr); + +static void atomic_console_notif(struct notif_driver *ndrv __unused, + enum notif_event ev __maybe_unused) +{ + DMSG("Asynchronous notifications started, event %d", (int)ev); +} +DECLARE_KEEP_PAGER(atomic_console_notif); + +static void yielding_console_notif(struct notif_driver *ndrv __unused, + enum notif_event ev) +{ + switch (ev) { + case NOTIF_EVENT_DO_BOTTOM_HALF: + read_console(); + itr_enable(IT_CONSOLE_UART); + break; + case NOTIF_EVENT_STOPPED: + DMSG("Asynchronous notifications stopped"); + itr_enable(IT_CONSOLE_UART); + break; + default: + EMSG("Unknown event %d", (int)ev); + } +} + +struct notif_driver console_notif = { + .atomic_cb = atomic_console_notif, + .yielding_cb = yielding_console_notif, +}; + +static TEE_Result init_console_itr(void) +{ + itr_add(&console_itr); + itr_enable(IT_CONSOLE_UART); + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) + notif_register_driver(&console_notif); + return TEE_SUCCESS; +} +driver_init(init_console_itr); +#endif + +#ifdef CFG_TZC400 +register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZC400_BASE, TZC400_REG_SIZE); + +static TEE_Result init_tzc400(void) +{ + void *va; + + DMSG("Initializing TZC400"); + + va = phys_to_virt(TZC400_BASE, MEM_AREA_IO_SEC, TZC400_REG_SIZE); + if (!va) { + EMSG("TZC400 not mapped"); + panic(); + } + + tzc_init((vaddr_t)va); + tzc_dump_state(); + + return TEE_SUCCESS; +} + +service_init(init_tzc400); +#endif /*CFG_TZC400*/ + +#if defined(PLATFORM_FLAVOR_qemu_virt) +static void release_secondary_early_hpen(size_t pos) +{ + struct mailbox { + uint64_t ep; + uint64_t hpen[]; + } *mailbox; + + if (cpu_mmu_enabled()) + mailbox = phys_to_virt(SECRAM_BASE, MEM_AREA_IO_SEC, + SECRAM_COHERENT_SIZE); + else + mailbox = (void *)SECRAM_BASE; + + if (!mailbox) + panic(); + + mailbox->ep = TEE_LOAD_ADDR; + dsb_ishst(); + mailbox->hpen[pos] = 1; + dsb_ishst(); + sev(); +} + +int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) +{ + size_t pos = get_core_pos_mpidr(core_id); + static bool core_is_released[CFG_TEE_CORE_NB_CORE]; + + if (!pos || pos >= CFG_TEE_CORE_NB_CORE) + return PSCI_RET_INVALID_PARAMETERS; + + DMSG("core pos: %zu: ns_entry %#" PRIx32, pos, entry); + + if (core_is_released[pos]) { + EMSG("core %zu already released", pos); + return PSCI_RET_DENIED; + } + core_is_released[pos] = true; + + boot_set_core_ns_entry(pos, entry, context_id); + release_secondary_early_hpen(pos); + + return PSCI_RET_SUCCESS; +} +#endif /*PLATFORM_FLAVOR_qemu_virt*/ diff --git a/optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h b/optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h new file mode 100644 index 0000000..206885c --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/platform_config.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include +#include + +/* Make stacks aligned to data cache line length */ +#define STACK_ALIGNMENT 64 + +#if defined(PLATFORM_FLAVOR_fvp) + +#define GIC_BASE 0x2c000000 +#define UART0_BASE 0x1c090000 +#define UART1_BASE 0x1c0a0000 +#define UART2_BASE 0x1c0b0000 +#define UART3_BASE 0x1c0c0000 +#define TZC400_BASE 0x2a4a0000 + +#define IT_UART1 38 + +#define CONSOLE_UART_BASE UART1_BASE +#define IT_CONSOLE_UART IT_UART1 + +#elif defined(PLATFORM_FLAVOR_juno) + +#define GIC_BASE 0x2c010000 + +/* FPGA UART0 */ +#define UART0_BASE 0x1c090000 +/* FPGA UART1 */ +#define UART1_BASE 0x1c0a0000 +/* SoC UART0 */ +#define UART2_BASE 0x7ff80000 +/* SoC UART1 */ +#define UART3_BASE 0x7ff70000 + + +#define UART0_CLK_IN_HZ 24000000 +#define UART1_CLK_IN_HZ 24000000 +#define UART2_CLK_IN_HZ 7273800 +#define UART3_CLK_IN_HZ 7273800 + + +#define IT_UART3 116 + +#define CONSOLE_UART_BASE UART3_BASE +#define IT_CONSOLE_UART IT_UART3 +#define CONSOLE_UART_CLK_IN_HZ UART3_CLK_IN_HZ + +#elif defined(PLATFORM_FLAVOR_qemu_virt) + +#define GIC_BASE 0x08000000 +#define UART0_BASE 0x09000000 +#define UART1_BASE 0x09040000 +#define PCSC_BASE 0x09100000 + +#define IT_UART1 40 +#define IT_PCSC 37 + +#define CONSOLE_UART_BASE UART1_BASE +#define IT_CONSOLE_UART IT_UART1 + +#elif defined(PLATFORM_FLAVOR_qemu_armv8a) + +#define GIC_BASE 0x08000000 +#define UART0_BASE 0x09000000 +#define UART1_BASE 0x09040000 + +#define IT_UART1 40 + +#define CONSOLE_UART_BASE UART1_BASE +#define IT_CONSOLE_UART IT_UART1 + +#else +#error "Unknown platform flavor" +#endif + +#if defined(PLATFORM_FLAVOR_fvp) +/* + * FVP specifics. + */ + +#define DRAM0_BASE 0x80000000 +#define DRAM0_SIZE 0x7f000000 + +#define DRAM1_BASE 0x880000000UL +#define DRAM1_SIZE 0x180000000UL + +#define TZCDRAM_BASE 0xff000000 +#define TZCDRAM_SIZE 0x01000000 + +#define GICC_OFFSET 0x0 +#define GICD_OFFSET 0x3000000 + +#elif defined(PLATFORM_FLAVOR_juno) +/* + * Juno specifics. + */ + +#define DRAM0_BASE 0x80000000 +#define DRAM0_SIZE 0x7F000000 + +#define DRAM1_BASE 0x880000000UL +#define DRAM1_SIZE 0x180000000UL + +#define GICC_OFFSET 0x1f000 +#define GICD_OFFSET 0 + +#elif defined(PLATFORM_FLAVOR_qemu_virt) +/* + * QEMU virt specifics. + */ + +#define SECRAM_BASE 0x0e000000 +#define SECRAM_COHERENT_SIZE 4096 + +#define GICD_OFFSET 0 +#define GICC_OFFSET 0x10000 + +#elif defined(PLATFORM_FLAVOR_qemu_armv8a) + +#define GICD_OFFSET 0 +#define GICC_OFFSET 0x10000 + +#else +#error "Unknown platform flavor" +#endif + +#ifdef GIC_BASE +#define GICD_BASE (GIC_BASE + GICD_OFFSET) +#define GICC_BASE (GIC_BASE + GICC_OFFSET) +#endif + +#ifndef UART_BAUDRATE +#define UART_BAUDRATE 115200 +#endif +#ifndef CONSOLE_BAUDRATE +#define CONSOLE_BAUDRATE UART_BAUDRATE +#endif + +/* For virtual platforms where there isn't a clock */ +#ifndef CONSOLE_UART_CLK_IN_HZ +#define CONSOLE_UART_CLK_IN_HZ 1 +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-vexpress/sub.mk b/optee/optee_os/core/arch/arm/plat-vexpress/sub.mk new file mode 100644 index 0000000..9b1dd7b --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/sub.mk @@ -0,0 +1,7 @@ +global-incdirs-y += . +srcs-y += main.c +ifeq ($(PLATFORM_FLAVOR_juno),y) +srcs-$(CFG_ARM32_core) += juno_core_pos_a32.S +srcs-$(CFG_ARM64_core) += juno_core_pos_a64.S +endif +srcs-$(CFG_WITH_USER_TA) += vendor_props.c diff --git a/optee/optee_os/core/arch/arm/plat-vexpress/vendor_props.c b/optee/optee_os/core/arch/arm/plat-vexpress/vendor_props.c new file mode 100644 index 0000000..a7061a9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-vexpress/vendor_props.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2020, Linaro Limited. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * The data to hash is 48 bytes made up of: + * - 16 bytes: the UUID of the calling TA. + * - 32 bytes: the hardware device ID + * The resulting endorsement seed is 32 bytes. + * + * The output buffer is the "binary" struct defined in + * the "prop_value" union and therefore comprises: + * - 4 bytes: the size of the binary value data (32) + * - 32 bytes: the binary value data (endorsement seed) + * + * Note that this code assumes an endorsement seed + * size == device ID size for convenience. + */ +static TEE_Result get_prop_endorsement(struct ts_session *sess, + void *buf, size_t *blen) +{ + TEE_Result res; + uint32_t ta_endorsement_seed_size = 32; + uint8_t data[sizeof(TEE_UUID) + ta_endorsement_seed_size]; + uint32_t bin[1 + ta_endorsement_seed_size / sizeof(uint32_t)]; + uint32_t *bin_len = (uint32_t *)bin; + uint8_t *bin_val = (uint8_t *)(&bin[1]); + + if (*blen < sizeof(bin)) { + *blen = sizeof(bin); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(bin); + + memcpy(data, &sess->ctx->uuid, sizeof(TEE_UUID)); + + if (tee_otp_get_die_id(&data[sizeof(TEE_UUID)], + ta_endorsement_seed_size)) + return TEE_ERROR_BAD_STATE; + + res = tee_hash_createdigest(TEE_ALG_SHA256, data, sizeof(data), + bin_val, ta_endorsement_seed_size); + if (res != TEE_SUCCESS) + return TEE_ERROR_BAD_STATE; + + *bin_len = ta_endorsement_seed_size; + + return copy_to_user(buf, bin, sizeof(bin)); +} + +static const struct tee_props vendor_propset_array_tee[] = { + { + .name = "com.microsoft.ta.endorsementSeed", + .prop_type = USER_TA_PROP_TYPE_BINARY_BLOCK, + .get_prop_func = get_prop_endorsement + }, +}; + +const struct tee_vendor_props vendor_props_tee = { + .props = vendor_propset_array_tee, + .len = ARRAY_SIZE(vendor_propset_array_tee), +}; diff --git a/optee/optee_os/core/arch/arm/plat-zynq7k/conf.mk b/optee/optee_os/core/arch/arm/plat-zynq7k/conf.mk new file mode 100644 index 0000000..30f2b4d --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynq7k/conf.mk @@ -0,0 +1,22 @@ +PLATFORM_FLAVOR ?= zc702 + +include core/arch/arm/cpu/cortex-a9.mk + +$(call force,CFG_TEE_CORE_NB_CORE,2) +$(call force,CFG_ARM32_core,y) +$(call force,CFG_GIC,y) +$(call force,CFG_CDNS_UART,y) +$(call force,CFG_WITH_SOFTWARE_PRNG,y) +$(call force,CFG_PL310,y) +$(call force,CFG_PL310_LOCKED,y) +$(call force,CFG_SECURE_TIME_SOURCE_REE,y) + +# Xilinx Zynq-7000's Cortex-A9 core has been configured with Non-maskable FIQ +# (NMFI) support. This means that FIQ interrupts cannot be used in system +# designs as atomic contexts cannot mask FIQ out. +$(call force,CFG_CORE_WORKAROUND_ARM_NMFI,y) + +CFG_BOOT_SYNC_CPU ?= y +CFG_BOOT_SECONDARY_REQUEST ?= y +CFG_CRYPTO_SIZE_OPTIMIZATION ?= n +CFG_ENABLE_SCTLR_RR ?= y diff --git a/optee/optee_os/core/arch/arm/plat-zynq7k/main.c b/optee/optee_os/core/arch/arm/plat-zynq7k/main.c new file mode 100644 index 0000000..bb628b7 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynq7k/main.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * All rights reserved. + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +static struct gic_data gic_data; +static struct cdns_uart_data console_data; + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, + CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, SLCR_BASE, CORE_MMU_PGDIR_SIZE); + +void plat_primary_init_early(void) +{ + /* primary core */ +#if defined(CFG_BOOT_SECONDARY_REQUEST) + /* set secondary entry address and release core */ + io_write32(SECONDARY_ENTRY_DROP, TEE_LOAD_ADDR); + dsb(); + sev(); +#endif + + /* SCU config */ + io_write32(SCU_BASE + SCU_INV_SEC, SCU_INV_CTRL_INIT); + io_write32(SCU_BASE + SCU_SAC, SCU_SAC_CTRL_INIT); + io_write32(SCU_BASE + SCU_NSAC, SCU_NSAC_CTRL_INIT); + + /* SCU enable */ + io_setbits32(SCU_BASE + SCU_CTRL, 0x1); + + /* NS Access control */ + io_write32(SECURITY2_SDIO0, ACCESS_BITS_ALL); + io_write32(SECURITY3_SDIO1, ACCESS_BITS_ALL); + io_write32(SECURITY4_QSPI, ACCESS_BITS_ALL); + io_write32(SECURITY6_APB_SLAVES, ACCESS_BITS_ALL); + + io_write32(SLCR_UNLOCK, SLCR_UNLOCK_MAGIC); + + io_write32(SLCR_TZ_DDR_RAM, ACCESS_BITS_ALL); + io_write32(SLCR_TZ_DMA_NS, ACCESS_BITS_ALL); + io_write32(SLCR_TZ_DMA_IRQ_NS, ACCESS_BITS_ALL); + io_write32(SLCR_TZ_DMA_PERIPH_NS, ACCESS_BITS_ALL); + io_write32(SLCR_TZ_GEM, ACCESS_BITS_ALL); + io_write32(SLCR_TZ_SDIO, ACCESS_BITS_ALL); + io_write32(SLCR_TZ_USB, ACCESS_BITS_ALL); + + io_write32(SLCR_LOCK, SLCR_LOCK_MAGIC); +} + +void console_init(void) +{ + cdns_uart_init(&console_data, CONSOLE_UART_BASE, 0, 0); + register_serial_console(&console_data.chip); +} + +vaddr_t pl310_base(void) +{ + static void *va; + + if (cpu_mmu_enabled()) { + if (!va) + va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC, 1); + return (vaddr_t)va; + } + return PL310_BASE; +} + +void arm_cl2_config(vaddr_t pl310_base) +{ + /* Disable PL310 */ + io_write32(pl310_base + PL310_CTRL, 0); + + /* + * Xilinx AR#54190 recommends setting L2C RAM in SLCR + * to 0x00020202 for proper cache operations. + */ + io_write32(SLCR_L2C_RAM, SLCR_L2C_RAM_VALUE); + + io_write32(pl310_base + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT); + io_write32(pl310_base + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT); + io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); + io_write32(pl310_base + PL310_PREFETCH_CTRL, PL310_PREFETCH_CTRL_INIT); + io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); + + /* invalidate all cache ways */ + arm_cl2_invbyway(pl310_base); +} + +void arm_cl2_enable(vaddr_t pl310_base) +{ + uint32_t val; + + /* Enable PL310 ctrl -> only set lsb bit */ + io_write32(pl310_base + PL310_CTRL, 1); + + /* if L2 FLZW enable, enable in L1 */ + val = io_read32(pl310_base + PL310_AUX_CTRL); + if (val & 1) + write_actlr(read_actlr() | (1 << 3)); +} + +void main_init_gic(void) +{ + gic_init(&gic_data, GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); + itr_init(&gic_data.chip); +} + +void main_secondary_init_gic(void) +{ + gic_cpu_init(&gic_data); +} + +static vaddr_t slcr_access_range[] = { + 0x004, 0x008, /* lock, unlock */ + 0x100, 0x1FF, /* PLL */ + 0x200, 0x2FF, /* Reset */ + 0xA00, 0xAFF /* L2C */ +}; + +static uint32_t write_slcr(uint32_t addr, uint32_t val) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(slcr_access_range); i += 2) { + if (addr >= slcr_access_range[i] && + addr <= slcr_access_range[i+1]) { + static vaddr_t va; + + if (!va) + va = (vaddr_t)phys_to_virt(SLCR_BASE, + MEM_AREA_IO_SEC, + addr + + sizeof(uint32_t)); + io_write32(va + addr, val); + return OPTEE_SMC_RETURN_OK; + } + } + return OPTEE_SMC_RETURN_EBADADDR; +} + +static uint32_t read_slcr(uint32_t addr, uint32_t *val) +{ + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(slcr_access_range); i += 2) { + if (addr >= slcr_access_range[i] && + addr <= slcr_access_range[i+1]) { + static vaddr_t va; + + if (!va) + va = (vaddr_t)phys_to_virt(SLCR_BASE, + MEM_AREA_IO_SEC, + addr + + sizeof(uint32_t)); + *val = io_read32(va + addr); + return OPTEE_SMC_RETURN_OK; + } + } + return OPTEE_SMC_RETURN_EBADADDR; +} + +/* Overriding the default __weak tee_entry_fast() */ +void tee_entry_fast(struct thread_smc_args *args) +{ + switch (args->a0) { + case ZYNQ7K_SMC_SLCR_WRITE: + args->a0 = write_slcr(args->a1, args->a2); + break; + case ZYNQ7K_SMC_SLCR_READ: + args->a0 = read_slcr(args->a1, &args->a2); + break; + default: + __tee_entry_fast(args); + break; + } +} diff --git a/optee/optee_os/core/arch/arm/plat-zynq7k/plat_init.S b/optee/optee_os/core/arch/arm/plat-zynq7k/plat_init.S new file mode 100644 index 0000000..86b35da --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynq7k/plat_init.S @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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. + */ + +#include +#include +#include +#include +#include +#include + +#define ZYNQ_SLCR_L2C_RAM 0xF8000A1C + +.section .text +.balign 4 +.code 32 + +/* + * Cortex A9 early configuration + * + * Use registers R0-R3. + * No stack usage. + * LR store return address. + * Trap CPU in case of error. + */ +FUNC plat_cpu_reset_early , : + /* + * Disallow NSec to mask FIQ [bit4: FW=0] + * Allow NSec to manage Imprecise Abort [bit5: AW=1] + * Imprecise Abort trapped to Abort Mode [bit3: EA=0] + * In Sec world, FIQ trapped to FIQ Mode [bit2: FIQ=0] + * IRQ always trapped to IRQ Mode [bit1: IRQ=0] + * Secure World [bit0: NS=0] + */ + mov r0, #SCR_AW + write_scr r0 /* write Secure Configuration Register */ + + /* + * Mandated HW config loaded + * + * SCTLR = 0x00004000 + * - Round-Robin replac. for icache, btac, i/duTLB (bit14: RoundRobin) + * + * ACTRL = 0x00000041 + * - core always in full SMP (FW bit0=1, SMP bit6=1) + * - L2 write full line of zero disabled (bit3=0) + * (keep WFLZ low. Will be set once outer L2 is ready) + * + * NSACR = 0x00020C00 + * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) + * - Nsec can lockdown TLB (TL bit17=1) + * - NSec cannot access PLE (PLE bit16=0) + * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) + * + * PCR = 0x00000001 + * - no change latency, enable clk gating + */ + mov_imm r0, 0x00004000 + write_sctlr r0 + + mov_imm r0, 0x00000041 + write_actlr r0 + + mov_imm r0, 0x00020C00 + write_nsacr r0 + + mov_imm r0, 0x00000001 + write_pcr r0 + + mov pc, lr +END_FUNC plat_cpu_reset_early diff --git a/optee/optee_os/core/arch/arm/plat-zynq7k/platform_config.h b/optee/optee_os/core/arch/arm/plat-zynq7k/platform_config.h new file mode 100644 index 0000000..41a4888 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynq7k/platform_config.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Wind River Systems. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#define STACK_ALIGNMENT 64 + +/* For Zynq7000 board */ + +#define SCU_BASE 0xF8F00000 +#define PL310_BASE 0xF8F02000 +#define GIC_BASE 0xF8F00000 +#define GICC_OFFSET 0x100 +#define GICD_OFFSET 0x1000 +#define GIC_CPU_BASE (GIC_BASE + GICC_OFFSET) +#define GIC_DIST_BASE (GIC_BASE + GICD_OFFSET) + +#define SLCR_BASE 0xF8000000 +#define SLCR_LOCK 0xF8000004 +#define SLCR_UNLOCK 0xF8000008 +#define SLCR_TZ_DDR_RAM 0xF8000430 +#define SLCR_TZ_DMA_NS 0xF8000440 +#define SLCR_TZ_DMA_IRQ_NS 0xF8000444 +#define SLCR_TZ_DMA_PERIPH_NS 0xF8000448 +#define SLCR_TZ_GEM 0xF8000450 +#define SLCR_TZ_SDIO 0xF8000454 +#define SLCR_TZ_USB 0xF8000458 +#define SLCR_L2C_RAM 0xF8000A1C + +#define SLCR_LOCK_MAGIC 0x0000767B +#define SLCR_UNLOCK_MAGIC 0x0000DF0D + +#define SECURITY2_SDIO0 0xE0200008 +#define SECURITY3_SDIO1 0xE020000C +#define SECURITY4_QSPI 0xE0200010 +#define SECURITY6_APB_SLAVES 0xE0200018 + +#define UART0_BASE 0xE0000000 +#define UART1_BASE 0xE0001000 + +#define CONSOLE_UART_BASE UART1_BASE + +#define TEE_RAM_VA_SIZE (1024 * 1024) + +/* + * PL310 TAG RAM Control Register + * + * 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 + */ +#ifndef PL310_TAG_RAM_CTRL_INIT +#define PL310_TAG_RAM_CTRL_INIT 0x00000111 +#endif + +/* + * PL310 DATA RAM Control Register + * + * 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 + */ +#ifndef PL310_DATA_RAM_CTRL_INIT +#define PL310_DATA_RAM_CTRL_INIT 0x00000222 +#endif + +/* + * PL310 Auxiliary Control Register + * + * I/Dcache prefetch enabled (bit29:28=2b11) + * NS can access interrupts (bit27=1) + * NS can lockown cache lines (bit26=1) + * Pseudo-random replacement policy (bit25=0) + * Force write allocated (default) + * Shared attribute internally ignored (bit22=1, bit13=0) + * Parity disabled (bit21=0) + * Event monitor disabled (bit20=0) + * Platform fmavor specific way config: + * - 64kb way size (bit19:17=3b011) + * - 8-way associciativity (bit16=0) + * Store buffer device limitation enabled (bit11=1) + * Cacheable accesses have high prio (bit10=0) + * Full Line Zero (FLZ) disabled (bit0=0) + */ +#ifndef PL310_AUX_CTRL_INIT +#define PL310_AUX_CTRL_INIT 0x3C460800 +#endif + +/* + * PL310 Prefetch Control Register + * + * Double linefill disabled (bit30=0) + * I/D prefetch enabled (bit29:28=2b11) + * Prefetch drop enabled (bit24=1) + * Incr double linefill disable (bit23=0) + * Prefetch offset = 7 (bit4:0) + */ +#define PL310_PREFETCH_CTRL_INIT 0x31000007 + +/* + * PL310 Power Register + * + * Dynamic clock gating enabled + * Standby mode enabled + */ +#define PL310_POWER_CTRL_INIT 0x00000003 + +/* + * SCU Invalidate Register + * + * Invalidate all registers + */ +#define SCU_INV_CTRL_INIT 0xFFFFFFFF + +/* + * SCU Access Register + * - both secure CPU access SCU + */ +#define SCU_SAC_CTRL_INIT 0x0000000F + +/* + * SCU NonSecure Access Register + * - both nonsec cpu access SCU, private and global timer + */ +#define SCU_NSAC_CTRL_INIT 0x00000FFF + +/* all bit enabled in access control register */ +#define ACCESS_BITS_ALL 0xFFFFFFFF + +/* recommended value for setting the L2C_RAM register */ +#define SLCR_L2C_RAM_VALUE 0x00020202 + +/* place in OCRAM to write secondary entry to */ +#define SECONDARY_ENTRY_DROP 0xFFFFFFF0 + +/* define the memory areas */ + +#ifdef CFG_WITH_PAGER + +/* + * TEE/TZ RAM layout: + * + * +---------------------------------------+ <- CFG_CORE_TZSRAM_EMUL_START + * | TEE private highly | TEE_RAM | ^ + * | secure memory | | | CFG_CORE_TZSRAM_EMUL_SIZE + * +---------------------------------------+ v + * + * +---------------------------------------+ <- TZDRAM_BASE + * | TEE private secure | TA_RAM | ^ + TZDRAM_SIZE + * | external memory | | v + * +---------------------------------------+ <- TEE_SHMEM_START + * | Non secure | SHM | | + * | shared memory | | | + TEE_SHMEM_SIZE + * +---------------------------------------+ v + * + * TEE_RAM : default 256kByte + * TA_RAM : all what is left in DDR TEE reserved area + * PUB_RAM : default 2MByte + */ + +/* emulated SRAM, 256K at start of secure DDR */ + +#define TZSRAM_BASE 0x3E000000 +#define TZSRAM_SIZE CFG_CORE_TZSRAM_EMUL_SIZE + +/* Location of trusted dram */ + +#define TEE_RAM_START TZSRAM_BASE +#define TEE_RAM_PH_SIZE TZSRAM_SIZE + +#define TZDRAM_BASE 0x3e100000 +#define TZDRAM_SIZE 0x01e00000 + +#define TEE_SHMEM_START 0x3ff00000 +#define TEE_SHMEM_SIZE 0x00100000 + +#define TA_RAM_START TZDRAM_BASE +#define TA_RAM_SIZE TZDRAM_SIZE + +#ifdef CFG_TEE_LOAD_ADDR +#define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR +#else +#define TEE_LOAD_ADDR TEE_RAM_START +#endif + +#else /* CFG_WITH_PAGER */ + +/* + * TEE/TZ RAM layout: + * + * +---------------------------------------+ <- TZDRAM_BASE + * | TEE private secure | TEE_RAM | ^ + * | external memory +------------------+ | + * | | TA_RAM | | + * +---------------------------------------+ | TZDRAM_SIZE + * | Non secure | SHM | | + * | shared memory | | | + * +---------------------------------------+ v + * + * TEE_RAM : 1MByte + * PUB_RAM : 1MByte + * TA_RAM : all what is left (at least 2MByte !) + */ + +#define TZDRAM_BASE 0x3E000000 +#define TZDRAM_SIZE (0x02000000 - TEE_SHMEM_SIZE) + +#define TEE_RAM_START TZDRAM_BASE +#define TEE_RAM_PH_SIZE (1 * 1024 * 1024) + +#define TA_RAM_START (TZDRAM_BASE + TEE_RAM_PH_SIZE) +#define TA_RAM_SIZE (TZDRAM_SIZE - TEE_RAM_PH_SIZE) + +#define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) +#define TEE_SHMEM_SIZE 0x00100000 + +#ifdef CFG_TEE_LOAD_ADDR +#define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR +#else +#define TEE_LOAD_ADDR TEE_RAM_START +#endif + +#endif /* CFG_WITH_PAGER */ + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-zynq7k/platform_smc.h b/optee/optee_os/core/arch/arm/plat-zynq7k/platform_smc.h new file mode 100644 index 0000000..b0b8792 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynq7k/platform_smc.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Wind River System + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_SMC_H +#define PLATFORM_SMC_H + +#include + +/* + * Read SLCR (System Level Control Register) + * + * Call register usage: + * a0 SMC Function ID, ZYNQ7K_SMC_SLCR_READ + * a1 Register offset + * a2-7 Not used + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1 Value read back + * a2-3 Not used + * a4-7 Preserved + * + * OPTEE_SMC_RETURN_EBADCMD on Invalid input offset: + * a0 OPTEE_SMC_RETURN_EBADCMD + * a1 Undefined value + * a2-3 Not used + * a4-7 Preserved + */ +#define ZYNQ7K_SMC_FUNCID_SLCR_READ 0x100 +#define ZYNQ7K_SMC_SLCR_READ \ + OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ + OPTEE_SMC_OWNER_OEM, ZYNQ7K_SMC_FUNCID_SLCR_READ) + +/* + * Write SLCR (System Level Control Register) + * + * Call register usage: + * a0 SMC Function ID, ZYNQ7K_SMC_SLCR_READ + * a1 Register offset + * a2 Value to write + * a3-7 Not used + * + * Normal return register usage: + * a0 OPTEE_SMC_RETURN_OK + * a1-3 Not used + * a4-7 Preserved + * + * OPTEE_SMC_RETURN_EBADCMD on Invalid input offset: + * a0 OPTEE_SMC_RETURN_EBADCMD + * a1-3 Not used + * a4-7 Preserved + */ +#define ZYNQ7K_SMC_FUNCID_SLCR_WRITE 0x101 +#define ZYNQ7K_SMC_SLCR_WRITE \ + OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ + OPTEE_SMC_OWNER_OEM, ZYNQ7K_SMC_FUNCID_SLCR_WRITE) + +#endif /* PLATFORM_SMC_H */ diff --git a/optee/optee_os/core/arch/arm/plat-zynq7k/sub.mk b/optee/optee_os/core/arch/arm/plat-zynq7k/sub.mk new file mode 100644 index 0000000..652c084 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynq7k/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +srcs-y += main.c +srcs-y += plat_init.S diff --git a/optee/optee_os/core/arch/arm/plat-zynqmp/conf.mk b/optee/optee_os/core/arch/arm/plat-zynqmp/conf.mk new file mode 100644 index 0000000..60ff011 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynqmp/conf.mk @@ -0,0 +1,90 @@ +PLATFORM_FLAVOR ?= zcu102 + +include core/arch/arm/cpu/cortex-armv8-0.mk + +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_CDNS_UART,y) +$(call force,CFG_GIC,y) +$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) +$(call force,CFG_WITH_ARM_TRUSTED_FW,y) + +# Disable core ASLR for two reasons: +# 1. There is no source for ALSR seed, as ATF does not provide a +# DTB to OP-TEE. Hardware RNG is also not currently supported. +# 2. OP-TEE does not boot with enabled CFG_CORE_ASLR. +$(call force,CFG_CORE_ASLR,n) + +ifeq ($(CFG_ARM64_core),y) +# ZynqMP supports up to 40 bits of physical addresses +CFG_CORE_ARM64_PA_BITS ?= 40 +else +$(call force,CFG_ARM32_core,y) +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),zcu102 zcu104 zcu106 zc1751_dc1 zc1751_dc2)) + +CFG_UART_BASE ?= UART0_BASE +CFG_UART_IT ?= IT_UART0 +CFG_UART_CLK_HZ ?= UART0_CLK_IN_HZ + +# ZCU102 features 4 GiB of DDR +ifeq ($(CFG_ARM64_core),y) +CFG_DDR_SIZE ?= 0x100000000 +else +# On 32 bit build limit to 2 GiB of RAM +CFG_DDR_SIZE ?= 0x80000000 +endif +endif + +ifneq (,$(filter $(PLATFORM_FLAVOR),ultra96)) + +CFG_UART_BASE ?= UART1_BASE +CFG_UART_IT ?= IT_UART1 +CFG_UART_CLK_HZ ?= UART1_CLK_IN_HZ + +# Ultra96 features 2 GiB of DDR +CFG_DDR_SIZE ?= 0x80000000 +endif + +# By default use DT address as specified by Xilinx +CFG_DT_ADDR ?= 0x100000 + +CFG_TZDRAM_START ?= 0x60000000 +CFG_TZDRAM_SIZE ?= 0x10000000 +CFG_SHMEM_START ?= 0x70000000 +CFG_SHMEM_SIZE ?= 0x10000000 + +CFG_WITH_STATS ?= y +CFG_CRYPTO_WITH_CE ?= y + +# Enable use of User AES eFuse as device key instead of PUF. +# This is needed when images are encrypted with AES eFuse device key (AES_KEY). +CFG_ZYNQMP_HUK_AES_EFUSE ?= n + +# Configures bitmask which user eFuses should be included in HUK generation. +# Used when (part of) user eFuses are used for HUK seed (i.e. programmed with +# good random values). +# Bit 0 means eFuse USER_0, bit 1 for eFuse USER 1 and so on. +CFG_ZYNQMP_HUK_USER_EFUSE_MASK ?= 0 + +CFG_ZYNQMP_PM ?= $(CFG_ARM64_core) + +ifeq ($(CFG_RPMB_FS),y) +$(call force,CFG_ZYNQMP_HUK,y,Mandated by CFG_RPMB_FS) +endif + +ifeq ($(CFG_ZYNQMP_HUK),y) +$(call force,CFG_ZYNQMP_CSU_AES,y,Mandated by CFG_ZYNQMP_HUK) +ifneq ($(CFG_ZYNQMP_HUK_AES_EFUSE),y) +$(call force,CFG_ZYNQMP_CSU_PUF,y,Mandated by CFG_ZYNQMP_HUK) +endif +endif + +ifeq ($(CFG_ZYNQMP_CSU_AES),y) +$(call force,CFG_ZYNQMP_CSUDMA,y,Mandated by CFG_ZYNQMP_CSU_AES) +$(call force,CFG_DT,y,Mandated by CFG_ZYNQMP_CSU_AES) +endif + +ifneq (,$(filter y, $(CFG_ZYNQMP_CSU_PUF) $(CFG_ZYNQMP_CSUDMA) $(CFG_ZYNQMP_CSU_AES))) +$(call force,CFG_ZYNQMP_CSU,y,Mandated by CFG_ZYNQMP_CSU* clients) +endif diff --git a/optee/optee_os/core/arch/arm/plat-zynqmp/main.c b/optee/optee_os/core/arch/arm/plat-zynqmp/main.c new file mode 100644 index 0000000..d727c86 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynqmp/main.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Xilinx 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +static struct gic_data gic_data __nex_bss; +static struct cdns_uart_data console_data __nex_bss; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(GIC_BASE, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, + ROUNDDOWN(GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE), + CORE_MMU_PGDIR_SIZE); +#if defined(CFG_ZYNQMP_CSU) +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CSU_BASE, CSU_SIZE); +#endif + +#if CFG_DDR_SIZE > 0x80000000 + +#ifdef CFG_ARM32_core +#error DDR size over 2 GiB is not supported in 32 bit ARM mode +#endif + +register_ddr(DRAM0_BASE, 0x80000000); +register_ddr(DRAM1_BASE, CFG_DDR_SIZE - 0x80000000); +#else +register_ddr(DRAM0_BASE, CFG_DDR_SIZE); +#endif + +void main_init_gic(void) +{ + /* On ARMv8, GIC configuration is initialized in ARM-TF */ + gic_init_base_addr(&gic_data, GIC_BASE + GICC_OFFSET, + GIC_BASE + GICD_OFFSET); + itr_init(&gic_data.chip); +} + +void itr_core_handler(void) +{ + gic_it_handle(&gic_data); +} + +void console_init(void) +{ + cdns_uart_init(&console_data, CONSOLE_UART_BASE, + CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); + register_serial_console(&console_data.chip); +} + +#if defined(CFG_RPMB_FS) +bool plat_rpmb_key_is_ready(void) +{ + vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); + struct tee_hw_unique_key hwkey = { }; + uint32_t status = 0; + + if (tee_otp_get_hw_unique_key(&hwkey)) + return false; + + /* + * For security reasons, we don't allow writing the RPMB key using the + * development HUK even though it is unique. + */ + status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET); + if (status & ZYNQMP_CSU_STATUS_AUTH) + return true; + + return false; +} +#endif diff --git a/optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h b/optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h new file mode 100644 index 0000000..ce945a6 --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynqmp/platform_config.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Xilinx 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* Make stacks aligned to data cache line length */ +#define CACHELINE_LEN 64 +#define STACK_ALIGNMENT CACHELINE_LEN + +#ifdef CFG_WITH_PAGER +#error "Pager not supported for zynqmp" +#endif + +/* DDR Low area base */ +#define DRAM0_BASE 0 + +#ifdef ARM64 +/* DDR High area base is only available when compiling for 64 bits */ +#define DRAM1_BASE 0x800000000 +#endif + +#ifdef CFG_CDNS_UART +#define CONSOLE_UART_BASE (CFG_UART_BASE) +#define IT_CONSOLE_UART (CFG_UART_IT) +#define CONSOLE_UART_CLK_IN_HZ (CFG_UART_CLK_HZ) +#endif + +#if defined(PLATFORM_FLAVOR_zc1751_dc1) || \ + defined(PLATFORM_FLAVOR_zc1751_dc2) || \ + defined(PLATFORM_FLAVOR_zcu102) || \ + defined(PLATFORM_FLAVOR_zcu104) || \ + defined(PLATFORM_FLAVOR_zcu106) + +#define GIC_BASE 0xF9010000 +#define UART0_BASE 0xFF000000 +#define UART1_BASE 0xFF010000 + +#define IT_UART0 53 +#define IT_UART1 54 + +#define UART0_CLK_IN_HZ 100000000 +#define UART1_CLK_IN_HZ 100000000 + +#define GICD_OFFSET 0 +#define GICC_OFFSET 0x10000 + +#elif defined(PLATFORM_FLAVOR_ultra96) + +#define GIC_BASE 0xF9010000 +#define UART0_BASE 0xFF000000 +#define UART1_BASE 0xFF010000 + +#define IT_UART0 53 +#define IT_UART1 54 + +#define UART0_CLK_IN_HZ 100000000 +#define UART1_CLK_IN_HZ 100000000 + +#define GICD_OFFSET 0 +#define GICC_OFFSET 0x10000 + +#else +#error "Unknown platform flavor" +#endif + +#define CSUDMA_BASE 0xFFC80000 +#define CSUDMA_SIZE 0x1000 +#define CSU_BASE 0xFFCA0000 +#define CSU_SIZE 0x5038 + +#ifdef CFG_TEE_LOAD_ADDR +#define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR +#else +#define TEE_LOAD_ADDR TEE_RAM_START +#endif + +#ifndef UART_BAUDRATE +#define UART_BAUDRATE 115200 +#endif +#ifndef CONSOLE_BAUDRATE +#define CONSOLE_BAUDRATE UART_BAUDRATE +#endif + +/* For virtual platforms where there isn't a clock */ +#ifndef CONSOLE_UART_CLK_IN_HZ +#define CONSOLE_UART_CLK_IN_HZ 1 +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/arm/plat-zynqmp/sub.mk b/optee/optee_os/core/arch/arm/plat-zynqmp/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/arm/plat-zynqmp/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/arm/sm/pm.c b/optee/optee_os/core/arch/arm/sm/pm.c new file mode 100644 index 0000000..9ce3b3c --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/pm.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017 NXP + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if CFG_TEE_CORE_NB_CORE > 4 +#error "Max support 4 cores in one cluster now" +#endif + +void sm_pm_cpu_suspend_save(struct sm_pm_ctx *ctx, uint32_t sp) +{ + struct thread_core_local *p = thread_get_core_local(); + + p->sm_pm_ctx_phys = virt_to_phys((void *)ctx); + + /* The content will be passed to sm_pm_cpu_do_resume as register sp */ + ctx->sp = sp; + ctx->cpu_resume_addr = + virt_to_phys((void *)(vaddr_t)sm_pm_cpu_do_resume); + + sm_pm_cpu_do_suspend(ctx->suspend_regs); + + dcache_op_level1(DCACHE_OP_CLEAN_INV); + +#ifdef CFG_PL310 + arm_cl2_cleanbyway(core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1)); +#endif +} diff --git a/optee/optee_os/core/arch/arm/sm/pm_a32.S b/optee/optee_os/core/arch/arm/sm/pm_a32.S new file mode 100644 index 0000000..2b824ef --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/pm_a32.S @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017 NXP + * + * Peng Fan + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +.section .text + +/* + * int sm_pm_cpu_suspend(uint32_t arg, int (*fn)(uint32_t)) + * @arg will be passed to fn as argument + * return value: 0 - cpu resumed from suspended state. + * -1 - cpu not suspended. + */ +FUNC sm_pm_cpu_suspend, : +UNWIND( .cantunwind) + push {r4 - r12, lr} + mov r5, sp + sub sp, sp, #SM_PM_CTX_SIZE + push {r0, r1} + + mov r1, r5 + add r0, sp, #8 + blx sm_pm_cpu_suspend_save + adr lr, aborted + /* Jump to arch specific suspend */ + pop {r0, pc} +aborted: + /* cpu not suspended */ + add sp, sp, #SM_PM_CTX_SIZE + /* Return -1 to the caller */ + mov r0, #(-1) +suspend_return: + pop {r4 - r12, pc} +END_FUNC sm_pm_cpu_suspend + +FUNC sm_pm_cpu_do_suspend, : +UNWIND( .cantunwind) + push {r4 - r11} + read_midr r4 + ubfx r5, r4, #4, #12 + ldr r4, =CORTEX_A5_PART_NUM + cmp r5, r4 + beq a5_a7_suspend + ldr r4, =CORTEX_A7_PART_NUM + cmp r5, r4 + beq a5_a7_suspend + ldr r4, =CORTEX_A9_PART_NUM + cmp r5, r4 + beq a9_suspend + /* cpu not supported */ + b . + /* A9 needs PCR/DIAG */ +a9_suspend: + read_pcr r4 + read_diag r5 + stmia r0!, {r4 - r5} +a5_a7_suspend: + read_fcseidr r4 + read_tpidruro r5 + stmia r0!, {r4 - r5} + read_dacr r4 +#ifdef CFG_WITH_LPAE +#error "Not supported" +#else + read_ttbr0 r5 + read_ttbr1 r6 + read_ttbcr r7 +#endif + read_sctlr r8 + read_actlr r9 + read_cpacr r10 + read_mvbar r11 + stmia r0!, {r4 - r11} + read_prrr r4 + read_nmrr r5 + read_vbar r6 + read_nsacr r7 + stmia r0, {r4 - r7} + pop {r4 - r11} + bx lr +END_FUNC sm_pm_cpu_do_suspend + +FUNC sm_pm_cpu_resume, : +UNWIND( .cantunwind) + cpsid aif + + /* Call into the runtime address of __get_core_pos */ + adr r0, _core_pos + ldr r1, [r0] + add r0, r0, r1 + blx r0 + + /* + * At this point, MMU is not enabled now. + * 1. Get the runtime physical address of _suspend_sp + * 2. Get the offset from _suspend_sp to &thread_core_local + * 3. Get the runtime physical address of thread_core_local + * Since moving towards non-linear mapping, + * `ldr r0, =thread_core_local` is not used here. + */ + adr r4, _suspend_sp + ldr r5, [r4] + add r4, r4, r5 + + mov_imm r1, THREAD_CORE_LOCAL_SIZE + mla r0, r0, r1, r4 + + ldr r0, [r0, #THREAD_CORE_LOCAL_SM_PM_CTX_PHYS] + /* Need to use r0!, because sm_pm_cpu_do_resume needs it */ + ldmia r0!, {sp, pc} +END_FUNC sm_pm_cpu_resume + +/* + * The following will be located in text section whose attribute is + * marked as readonly, but we only need to read here + * _suspend_sp stores the offset between thread_core_local to _suspend_sp. + * _core_pos stores the offset between __get_core_pos to _core_pos. + */ +.align 2 +.extern thread_core_local +_suspend_sp: + .long thread_core_local - . +.extern __get_core_pos +_core_pos: + .long __get_core_pos - . + +/* + * void sm_pm_cpu_do_resume(paddr suspend_regs) __noreturn; + * Restore the registers stored when sm_pm_cpu_do_suspend + * r0 points to the physical base address of the suspend_regs + * field of struct sm_pm_ctx. + */ +FUNC sm_pm_cpu_do_resume, : +UNWIND( .cantunwind) + read_midr r4 + ubfx r5, r4, #4, #12 + ldr r4, =CORTEX_A5_PART_NUM + cmp r5, r4 + beq a5_a7_resume + ldr r4, =CORTEX_A7_PART_NUM + cmp r5, r4 + beq a5_a7_resume + + /* + * A9 needs PCR/DIAG + */ + ldmia r0!, {r4 - r5} + write_pcr r4 + write_diag r5 + +a5_a7_resume: + /* v7 resume */ + mov ip, #0 + /* Invalidate icache to PoU */ + write_iciallu + /* set reserved context */ + write_contextidr ip + ldmia r0!, {r4 - r5} + write_fcseidr r4 + write_tpidruro r5 + ldmia r0!, {r4 - r11} + /* Invalidate entire TLB */ + write_tlbiall + write_dacr r4 +#ifdef CFG_WITH_LPAE +#error "Not supported -" +#else + write_ttbr0 r5 + write_ttbr1 r6 + write_ttbcr r7 +#endif + + ldmia r0, {r4 - r7} + write_prrr r4 + write_nmrr r5 + write_vbar r6 + write_nsacr r7 + + write_actlr r9 + write_cpacr r10 + write_mvbar r11 + write_bpiall + isb + dsb + /* MMU will be enabled here */ + write_sctlr r8 + isb + mov r0, #0 + b suspend_return +END_FUNC sm_pm_cpu_do_resume + diff --git a/optee/optee_os/core/arch/arm/sm/psci-helper.S b/optee/optee_os/core/arch/arm/sm/psci-helper.S new file mode 100644 index 0000000..feaca88 --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/psci-helper.S @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017 NXP + */ + +#include +#include +#include +#include + +FUNC psci_disable_smp, : + read_actlr r0 + bic r0, r0, #ACTLR_SMP + write_actlr r0 + isb + bx lr +END_FUNC psci_disable_smp + +FUNC psci_enable_smp, : + read_actlr r0 + orr r0, r0, #ACTLR_SMP + write_actlr r0 + isb + bx lr +END_FUNC psci_enable_smp + +FUNC psci_armv7_cpu_off, : + push {r12, lr} +UNWIND( .save {r12, lr}) + + mov r0, #DCACHE_OP_CLEAN_INV + bl dcache_op_all + + /* Disable Cache */ + read_sctlr r0 + bic r0, r0, #SCTLR_C + write_sctlr r0 + isb + dsb + + mov r0, #DCACHE_OP_CLEAN_INV + bl dcache_op_all + + clrex + + bl psci_disable_smp + + pop {r12, pc} +END_FUNC psci_armv7_cpu_off diff --git a/optee/optee_os/core/arch/arm/sm/psci.c b/optee/optee_os/core/arch/arm/sm/psci.c new file mode 100644 index 0000000..167ef14 --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/psci.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * All rights reserved. + * + * Peng Fan + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +__weak uint32_t psci_version(void) +{ + return PSCI_VERSION_1_1; +} + +__weak int psci_cpu_suspend(uint32_t power_state __unused, + uintptr_t entry __unused, + uint32_t context_id __unused, + struct sm_nsec_ctx *nsec __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_cpu_off(void) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_cpu_on(uint32_t cpu_id __unused, uint32_t entry __unused, + uint32_t context_id __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_affinity_info(uint32_t affinity __unused, + uint32_t lowest_affnity_level __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_migrate(uint32_t cpu_id __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_migrate_info_type(void) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_migrate_info_up_cpu(void) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak void psci_system_off(void) +{ +} + +__weak void psci_system_reset(void) +{ +} + +__weak int psci_features(uint32_t psci_fid __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_mem_protect(uint32_t enable __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_mem_chk_range(paddr_t base __unused, + size_t length __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_system_reset2(uint32_t reset_type __unused, + uint32_t cookie __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_node_hw_state(uint32_t cpu_id __unused, + uint32_t power_level __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_system_suspend(uintptr_t entry __unused, + uint32_t context_id __unused, + struct sm_nsec_ctx *nsec __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_stat_residency(uint32_t cpu_id __unused, + uint32_t power_state __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +__weak int psci_stat_count(uint32_t cpu_id __unused, + uint32_t power_state __unused) +{ + return PSCI_RET_NOT_SUPPORTED; +} + +void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec) +{ + uint32_t smc_fid = args->a0; + uint32_t a1 = args->a1; + uint32_t a2 = args->a2; + uint32_t a3 = args->a3; + + switch (smc_fid) { + case PSCI_VERSION: + args->a0 = psci_version(); + break; + case PSCI_CPU_SUSPEND: + args->a0 = psci_cpu_suspend(a1, a2, a3, nsec); + break; + case PSCI_CPU_OFF: + args->a0 = psci_cpu_off(); + break; + case PSCI_CPU_ON: + args->a0 = psci_cpu_on(a1, a2, a3); + break; + case PSCI_AFFINITY_INFO: + args->a0 = psci_affinity_info(a1, a2); + break; + case PSCI_MIGRATE: + args->a0 = psci_migrate(a1); + break; + case PSCI_MIGRATE_INFO_TYPE: + args->a0 = psci_migrate_info_type(); + break; + case PSCI_MIGRATE_INFO_UP_CPU: + args->a0 = psci_migrate_info_up_cpu(); + break; + case PSCI_SYSTEM_OFF: + psci_system_off(); + while (1) + ; + break; + case PSCI_SYSTEM_RESET: + psci_system_reset(); + while (1) + ; + break; + case PSCI_PSCI_FEATURES: + args->a0 = psci_features(a1); + break; + case PSCI_SYSTEM_RESET2: + args->a0 = psci_system_reset2(a1, a2); + break; + case PSCI_MEM_PROTECT: + args->a0 = psci_mem_protect(a1); + break; + case PSCI_MEM_PROTECT_CHECK_RANGE: + args->a0 = psci_mem_chk_range(a1, a2); + break; + case PSCI_NODE_HW_STATE: + args->a0 = psci_node_hw_state(a1, a2); + break; + case PSCI_SYSTEM_SUSPEND: + args->a0 = psci_system_suspend(a1, a2, nsec); + break; + default: + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; + break; + } +} diff --git a/optee/optee_os/core/arch/arm/sm/sm.c b/optee/optee_os/core/arch/arm/sm/sm.c new file mode 100644 index 0000000..905e028 --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/sm.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2020, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sm_private.h" + +enum sm_handler_ret __weak sm_platform_handler(struct sm_ctx *ctx __unused) +{ + return SM_HANDLER_PENDING_SMC; +} + +static void smc_arch_handler(struct thread_smc_args *args) +{ + uint32_t smc_fid = args->a0; + uint32_t feature_fid = args->a1; + + switch (smc_fid) { + case ARM_SMCCC_VERSION: + args->a0 = SMCCC_V_1_1; + break; + case ARM_SMCCC_ARCH_FEATURES: + switch (feature_fid) { + case ARM_SMCCC_VERSION: + case ARM_SMCCC_ARCH_SOC_ID: + args->a0 = ARM_SMCCC_RET_SUCCESS; + break; + default: + args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; + break; + } + break; + case ARM_SMCCC_ARCH_SOC_ID: + args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; + break; + case ARM_SMCCC_ARCH_WORKAROUND_1: + case ARM_SMCCC_ARCH_WORKAROUND_2: + args->a0 = ARM_SMCCC_RET_NOT_REQUIRED; + break; + default: + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; + break; + } +} + +uint32_t sm_from_nsec(struct sm_ctx *ctx) +{ + uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); + struct thread_smc_args *args = (struct thread_smc_args *)nsec_r0; + + /* + * Check that struct sm_ctx has the different parts properly + * aligned since the stack pointer will be updated to point at + * different parts of this struct. + */ + COMPILE_TIME_ASSERT(!(offsetof(struct sm_ctx, sec.r0) % 8)); + COMPILE_TIME_ASSERT(!(offsetof(struct sm_ctx, nsec.r0) % 8)); + COMPILE_TIME_ASSERT(!(sizeof(struct sm_ctx) % 8)); + + if (wdt_sm_handler(args) == SM_HANDLER_SMC_HANDLED) + return SM_EXIT_TO_NON_SECURE; + + if (IS_ENABLED(CFG_SM_PLATFORM_HANDLER) && + sm_platform_handler(ctx) == SM_HANDLER_SMC_HANDLED) + return SM_EXIT_TO_NON_SECURE; + + switch (OPTEE_SMC_OWNER_NUM(args->a0)) { + case OPTEE_SMC_OWNER_STANDARD: + if (IS_ENABLED(CFG_PSCI_ARM32)) { + smc_std_handler(args, &ctx->nsec); + return SM_EXIT_TO_NON_SECURE; + } + break; + case OPTEE_SMC_OWNER_ARCH: + smc_arch_handler(args); + return SM_EXIT_TO_NON_SECURE; + default: + break; + } + + sm_save_unbanked_regs(&ctx->nsec.ub_regs); + sm_restore_unbanked_regs(&ctx->sec.ub_regs); + + memcpy(&ctx->sec.r0, args, sizeof(*args)); + + if (IS_ENABLED(CFG_CORE_WORKAROUND_ARM_NMFI)) { + /* Make sure FIQ is masked when jumping to SMC entry. */ + ctx->sec.mon_spsr |= CPSR_F; + } + + if (OPTEE_SMC_IS_FAST_CALL(ctx->sec.r0)) + ctx->sec.mon_lr = (uint32_t)vector_fast_smc_entry; + else + ctx->sec.mon_lr = (uint32_t)vector_std_smc_entry; + + return SM_EXIT_TO_SECURE; +} diff --git a/optee/optee_os/core/arch/arm/sm/sm_a32.S b/optee/optee_os/core/arch/arm/sm/sm_a32.S new file mode 100644 index 0000000..6181ebb --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/sm_a32.S @@ -0,0 +1,424 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2020, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SM_CTX_SEC_END (SM_CTX_SEC + SM_CTX_SEC_SIZE) + + .macro save_regs mode + cps \mode + mrs r2, spsr + str r2, [r0], #4 + str sp, [r0], #4 + str lr, [r0], #4 + .endm + +FUNC sm_save_unbanked_regs , : +UNWIND( .cantunwind) + /* User mode registers has to be saved from system mode */ + cps #CPSR_MODE_SYS + str sp, [r0], #4 + str lr, [r0], #4 + + save_regs #CPSR_MODE_IRQ + save_regs #CPSR_MODE_FIQ + save_regs #CPSR_MODE_SVC + save_regs #CPSR_MODE_ABT + save_regs #CPSR_MODE_UND + +#ifdef CFG_SM_NO_CYCLE_COUNTING + read_pmcr r2 + stm r0!, {r2} +#endif + +#ifdef CFG_FTRACE_SUPPORT + read_cntkctl r2 + stm r0!, {r2} +#endif + cps #CPSR_MODE_MON + bx lr +END_FUNC sm_save_unbanked_regs + + .macro restore_regs mode + cps \mode + ldr r2, [r0], #4 + ldr sp, [r0], #4 + ldr lr, [r0], #4 + msr spsr_fsxc, r2 + .endm + +/* Restores the mode specific registers */ +FUNC sm_restore_unbanked_regs , : +UNWIND( .cantunwind) + /* User mode registers has to be saved from system mode */ + cps #CPSR_MODE_SYS + ldr sp, [r0], #4 + ldr lr, [r0], #4 + + restore_regs #CPSR_MODE_IRQ + restore_regs #CPSR_MODE_FIQ + restore_regs #CPSR_MODE_SVC + restore_regs #CPSR_MODE_ABT + restore_regs #CPSR_MODE_UND + +#ifdef CFG_SM_NO_CYCLE_COUNTING + ldm r0!, {r2} + write_pmcr r2 +#endif + +#ifdef CFG_FTRACE_SUPPORT + ldm r0!, {r2} + write_cntkctl r2 +#endif + cps #CPSR_MODE_MON + bx lr +END_FUNC sm_restore_unbanked_regs + +/* + * stack_tmp is used as stack, the top of the stack is reserved to hold + * struct sm_ctx, everything below is for normal stack usage. As several + * different CPU modes are using the same stack it's important that switch + * of CPU mode isn't done until one mode is done. This means FIQ, IRQ and + * Async abort has to be masked while using stack_tmp. + */ +LOCAL_FUNC sm_smc_entry , : +UNWIND( .cantunwind) + srsdb sp!, #CPSR_MODE_MON + push {r0-r7} + + clrex /* Clear the exclusive monitor */ + + /* Find out if we're doing an secure or non-secure entry */ + read_scr r1 + tst r1, #SCR_NS + bne .smc_from_nsec + + /* + * As we're coming from secure world (NS bit cleared) the stack + * pointer points to sm_ctx.sec.r0 at this stage. After the + * instruction below the stack pointer points to sm_ctx. + */ + sub sp, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0) + + /* Save secure context */ + add r0, sp, #SM_CTX_SEC + bl sm_save_unbanked_regs + + /* + * On FIQ exit we're restoring the non-secure context unchanged, on + * all other exits we're shifting r1-r4 from secure context into + * r0-r3 in non-secure context. + */ + add r8, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0) + ldm r8, {r0-r4} + mov_imm r9, TEESMC_OPTEED_RETURN_FIQ_DONE + cmp r0, r9 + addne r8, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) + stmne r8, {r1-r4} + + /* Restore non-secure context */ + add r0, sp, #SM_CTX_NSEC + bl sm_restore_unbanked_regs + +.sm_ret_to_nsec: + /* + * Return to non-secure world + */ + add r0, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R8) + ldm r0, {r8-r12} + +#ifdef CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME + /* + * Prevent leaking information about which code has been executed. + * This is required to be used together with + * CFG_CORE_WORKAROUND_SPECTRE_BP to protect Cortex A15 CPUs too. + * + * CFG_CORE_WORKAROUND_SPECTRE_BP also invalidates the branch + * predictor on affected CPUs. In the cases where an alternative + * vector has been installed the branch predictor is already + * invalidated so invalidating here again would be redundant, but + * testing for that is more trouble than it's worth. + */ + write_bpiall +#endif + + /* Update SCR */ + read_scr r0 + orr r0, r0, #(SCR_NS | SCR_FIQ) /* Set NS and FIQ bit in SCR */ + write_scr r0 + /* + * isb not needed since we're doing an exception return below + * without dependency to the changes in SCR before that. + */ + + add sp, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) + b .sm_exit + +.smc_from_nsec: + /* + * As we're coming from non-secure world (NS bit set) the stack + * pointer points to sm_ctx.nsec.r0 at this stage. After the + * instruction below the stack pointer points to sm_ctx. + */ + sub sp, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) + + bic r1, r1, #(SCR_NS | SCR_FIQ) /* Clear NS and FIQ bit in SCR */ + write_scr r1 + isb + + add r0, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R8) + stm r0, {r8-r12} + + mov r0, sp + bl sm_from_nsec + cmp r0, #SM_EXIT_TO_NON_SECURE + beq .sm_ret_to_nsec + + /* + * Continue into secure world + */ + add sp, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0) + +.sm_exit: + pop {r0-r7} + rfefd sp! +END_FUNC sm_smc_entry + +/* + * FIQ handling + * + * Saves CPU context in the same way as sm_smc_entry() above. The CPU + * context will later be restored by sm_smc_entry() when handling a return + * from FIQ. + */ +LOCAL_FUNC sm_fiq_entry , : +UNWIND( .cantunwind) + /* FIQ has a +4 offset for lr compared to preferred return address */ + sub lr, lr, #4 + /* sp points just past struct sm_sec_ctx */ + srsdb sp!, #CPSR_MODE_MON + push {r0-r7} + + clrex /* Clear the exclusive monitor */ + + /* + * As we're coming from non-secure world the stack pointer points + * to sm_ctx.nsec.r0 at this stage. After the instruction below the + * stack pointer points to sm_ctx. + */ + sub sp, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) + + /* Update SCR */ + read_scr r1 + bic r1, r1, #(SCR_NS | SCR_FIQ) /* Clear NS and FIQ bit in SCR */ + write_scr r1 + isb + + /* Save non-secure context */ + add r0, sp, #SM_CTX_NSEC + bl sm_save_unbanked_regs + add r0, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R8) + stm r0!, {r8-r12} + + /* Set FIQ entry */ + ldr r0, =vector_fiq_entry + str r0, [sp, #(SM_CTX_SEC + SM_SEC_CTX_MON_LR)] + + /* Restore secure context */ + add r0, sp, #SM_CTX_SEC + bl sm_restore_unbanked_regs + + add sp, sp, #(SM_CTX_SEC + SM_SEC_CTX_MON_LR) + + rfefd sp! +END_FUNC sm_fiq_entry + +LOCAL_FUNC sm_vect_table , :, align=32 +UNWIND( .cantunwind) + 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 + +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP + .macro vector_prologue_spectre + /* + * This depends on SP being 8 byte aligned, that is, the + * lowest three bits in SP are zero. + * + * The idea is to form a specific bit pattern in the lowest + * three bits of SP depending on which entry in the vector + * we enter via. This is done by adding 1 to SP in each + * entry but the last. + */ + add sp, sp, #1 /* 7:111 Reset */ + add sp, sp, #1 /* 6:110 Undefined instruction */ + add sp, sp, #1 /* 5:101 Secure monitor call */ + add sp, sp, #1 /* 4:100 Prefetch abort */ + add sp, sp, #1 /* 3:011 Data abort */ + add sp, sp, #1 /* 2:010 Reserved */ + add sp, sp, #1 /* 1:001 IRQ */ + nop /* 0:000 FIQ */ + .endm + +LOCAL_FUNC sm_vect_table_a15 , :, align=32 +UNWIND( .cantunwind) + vector_prologue_spectre + /* + * Invalidate the branch predictor for the current processor. + * For Cortex-A8 ACTLR[6] has to be set to 1 for BPIALL to be + * effective. + * Note that the BPIALL instruction is not effective in + * invalidating the branch predictor on Cortex-A15. For that CPU, + * set ACTLR[0] to 1 during early processor initialisation, and + * invalidate the branch predictor by performing an ICIALLU + * instruction. See also: + * https://github.com/ARM-software/arm-trusted-firmware/wiki/Arm-Trusted-Firmware-Security-Advisory-TFV-6#variant-2-cve-2017-5715 + */ + write_iciallu + isb + b 1f +END_FUNC sm_vect_table_a15 + + +LOCAL_FUNC sm_vect_table_bpiall , :, align=32 +UNWIND( .cantunwind) + vector_prologue_spectre + /* Invalidate the branch predictor for the current processor. */ + write_bpiall + isb + +1: + /* + * Only two exception does normally occur, smc and fiq. With all + * other exceptions it's good enough to just spinn, the lowest bits + * still tells which exception we're stuck with when attaching a + * debugger. + */ + + /* Test for FIQ, all the lowest bits of SP are supposed to be 0 */ + tst sp, #(BIT(0) | BIT(1) | BIT(2)) + beq sm_fiq_entry + + /* Test for SMC, xor the lowest bits of SP to be 0 */ + eor sp, sp, #(BIT(0) | BIT(2)) + tst sp, #(BIT(0) | BIT(1) | BIT(2)) + beq sm_smc_entry + + /* unhandled exception */ + b . +END_FUNC sm_vect_table_bpiall +#endif /*!CFG_CORE_WORKAROUND_SPECTRE_BP*/ + +/* void sm_init(vaddr_t stack_pointer); */ +FUNC sm_init , : + /* Set monitor stack */ + mrs r1, cpsr + cps #CPSR_MODE_MON + /* Point just beyond sm_ctx.sec */ + sub sp, r0, #(SM_CTX_SIZE - SM_CTX_SEC_END) + +#ifdef CFG_INIT_CNTVOFF + read_scr r0 + orr r0, r0, #SCR_NS /* Set NS bit in SCR */ + write_scr r0 + isb + + /* + * Accessing CNTVOFF: + * If the implementation includes the Virtualization Extensions + * this is a RW register, accessible from Hyp mode, and + * from Monitor mode when SCR.NS is set to 1. + * If the implementation includes the Security Extensions + * but not the Virtualization Extensions, an MCRR or MRRC to + * the CNTVOFF encoding is UNPREDICTABLE if executed in Monitor + * mode, regardless of the value of SCR.NS. + */ + read_id_pfr1 r2 + mov r3, r2 + ands r3, r3, #IDPFR1_GENTIMER_MASK + beq .no_gentimer + ands r2, r2, #IDPFR1_VIRT_MASK + beq .no_gentimer + mov r2, #0 + write_cntvoff r2, r2 + +.no_gentimer: + bic r0, r0, #SCR_NS /* Clr NS bit in SCR */ + write_scr r0 + isb +#endif +#ifdef CFG_SM_NO_CYCLE_COUNTING + read_pmcr r0 + orr r0, #PMCR_DP + write_pmcr r0 +#endif + msr cpsr, r1 + +#ifdef CFG_CORE_WORKAROUND_SPECTRE_BP + /* + * For unrecognized CPUs we fall back to the vector used for + * unaffected CPUs. Cortex A-15 has special treatment compared to + * the other affected Cortex CPUs. + */ + read_midr r1 + ubfx r2, r1, #MIDR_IMPLEMENTER_SHIFT, #MIDR_IMPLEMENTER_WIDTH + cmp r2, #MIDR_IMPLEMENTER_ARM + bne 1f + + ubfx r2, r1, #MIDR_PRIMARY_PART_NUM_SHIFT, \ + #MIDR_PRIMARY_PART_NUM_WIDTH + + movw r3, #CORTEX_A8_PART_NUM + cmp r2, r3 + movwne r3, #CORTEX_A9_PART_NUM + cmpne r2, r3 + movwne r3, #CORTEX_A17_PART_NUM + cmpne r2, r3 + ldreq r0, =sm_vect_table_bpiall + beq 2f + + movw r3, #CORTEX_A15_PART_NUM + cmp r2, r3 + ldreq r0, =sm_vect_table_a15 + beq 2f +#endif + /* Set monitor vector (MVBAR) */ +1: ldr r0, =sm_vect_table +2: write_mvbar r0 + + bx lr +END_FUNC sm_init +DECLARE_KEEP_PAGER sm_init + + +/* struct sm_nsec_ctx *sm_get_nsec_ctx(void); */ +FUNC sm_get_nsec_ctx , : + mrs r1, cpsr + cps #CPSR_MODE_MON + /* + * As we're in secure mode mon_sp points just beyond sm_ctx.sec, + * which allows us to calculate the address of sm_ctx.nsec. + */ + add r0, sp, #(SM_CTX_NSEC - SM_CTX_SEC_END) + msr cpsr, r1 + + bx lr +END_FUNC sm_get_nsec_ctx diff --git a/optee/optee_os/core/arch/arm/sm/sm_private.h b/optee/optee_os/core/arch/arm/sm/sm_private.h new file mode 100644 index 0000000..c224109 --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/sm_private.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef SM_PRIVATE_H +#define SM_PRIVATE_H + +/* Returns one of SM_EXIT_TO_* exit monitor in secure or non-secure world */ +uint32_t sm_from_nsec(struct sm_ctx *ctx); +#endif /*SM_PRIVATE_H*/ + diff --git a/optee/optee_os/core/arch/arm/sm/std_smc.c b/optee/optee_os/core/arch/arm/sm/std_smc.c new file mode 100644 index 0000000..52ed918 --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/std_smc.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * All rights reserved. + * + * Peng Fan + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 const TEE_UUID uuid = { + 0x5f8b97df, 0x2d0d, 0x4ad2, + {0x98, 0xd2, 0x74, 0xf4, 0x38, 0x27, 0x98, 0xbb}, +}; + +void smc_std_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec) +{ + uint32_t smc_fid = args->a0; + + if (is_psci_fid(smc_fid)) { + tee_psci_handler(args, nsec); + return; + } + + switch (smc_fid) { + case ARM_STD_SVC_CALL_COUNT: + /* PSCI is the only STD service implemented */ + args->a0 = PSCI_NUM_CALLS; + break; + case ARM_STD_SVC_UID: + args->a0 = uuid.timeLow; + args->a1 = (uuid.timeHiAndVersion << 16) | uuid.timeMid; + args->a2 = (uuid.clockSeqAndNode[3] << 24) | + (uuid.clockSeqAndNode[2] << 16) | + (uuid.clockSeqAndNode[1] << 8) | + uuid.clockSeqAndNode[0]; + args->a3 = (uuid.clockSeqAndNode[7] << 24) | + (uuid.clockSeqAndNode[6] << 16) | + (uuid.clockSeqAndNode[5] << 8) | + uuid.clockSeqAndNode[4]; + break; + case ARM_STD_SVC_VERSION: + args->a0 = STD_SVC_VERSION_MAJOR; + args->a1 = STD_SVC_VERSION_MINOR; + break; + default: + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; + break; + } +} diff --git a/optee/optee_os/core/arch/arm/sm/sub.mk b/optee/optee_os/core/arch/arm/sm/sub.mk new file mode 100644 index 0000000..598bdad --- /dev/null +++ b/optee/optee_os/core/arch/arm/sm/sub.mk @@ -0,0 +1,4 @@ +srcs-y += sm_a32.S +srcs-y += sm.c +srcs-$(CFG_PM_ARM32) += pm.c pm_a32.S +srcs-$(CFG_PSCI_ARM32) += std_smc.c psci.c psci-helper.S diff --git a/optee/optee_os/core/arch/arm/tee/cache.c b/optee/optee_os/core/arch/arm/tee/cache.c new file mode 100644 index 0000000..d8ef9e3 --- /dev/null +++ b/optee/optee_os/core/arch/arm/tee/cache.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include + +/* + * tee_uta_cache_operation - dynamic cache clean/inval request from a TA. + * It follows ARM recommendation: + * https://developer.arm.com/documentation/ddi0246/c/Beicdhde + * Note that this implementation assumes dsb operations are part of + * cache_op_inner(), and outer cache sync are part of cache_op_outer(). + */ +TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len) +{ + TEE_Result res; + paddr_t pa; + + pa = virt_to_phys(va); + if (!pa) + return TEE_ERROR_ACCESS_DENIED; + + switch (op) { + case TEE_CACHEFLUSH: +#ifdef CFG_PL310 /* prevent initial L1 clean in case there is no outer L2 */ + /* Clean L1, Flush L2, Flush L1 */ + res = cache_op_inner(DCACHE_AREA_CLEAN, va, len); + if (res != TEE_SUCCESS) + return res; + res = cache_op_outer(DCACHE_AREA_CLEAN_INV, pa, len); + if (res != TEE_SUCCESS) + return res; +#endif + return cache_op_inner(DCACHE_AREA_CLEAN_INV, va, len); + + case TEE_CACHECLEAN: + /* Clean L1, Clean L2 */ + res = cache_op_inner(DCACHE_AREA_CLEAN, va, len); + if (res != TEE_SUCCESS) + return res; + return cache_op_outer(DCACHE_AREA_CLEAN, pa, len); + + case TEE_CACHEINVALIDATE: + /* Inval L2, Inval L1 */ + res = cache_op_outer(DCACHE_AREA_INVALIDATE, pa, len); + if (res != TEE_SUCCESS) + return res; + return cache_op_inner(DCACHE_AREA_INVALIDATE, va, len); + + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} diff --git a/optee/optee_os/core/arch/arm/tee/entry_fast.c b/optee/optee_os/core/arch/arm/tee/entry_fast.c new file mode 100644 index 0000000..f62da8c --- /dev/null +++ b/optee/optee_os/core/arch/arm/tee/entry_fast.c @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2021, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_CORE_RESERVED_SHM +static void tee_entry_get_shm_config(struct thread_smc_args *args) +{ + args->a0 = OPTEE_SMC_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(); +} +#endif + +static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args) +{ + TEE_Result ret; +#ifdef ARM32 + paddr_t pa = 0; + + switch (args->a1) { + case OPTEE_SMC_L2CC_MUTEX_GET_ADDR: + ret = tee_get_l2cc_mutex(&pa); + reg_pair_from_64(pa, &args->a2, &args->a3); + break; + case OPTEE_SMC_L2CC_MUTEX_SET_ADDR: + pa = reg_pair_to_64(args->a2, args->a3); + ret = tee_set_l2cc_mutex(&pa); + break; + case OPTEE_SMC_L2CC_MUTEX_ENABLE: + ret = tee_enable_l2cc_mutex(); + break; + case OPTEE_SMC_L2CC_MUTEX_DISABLE: + ret = tee_disable_l2cc_mutex(); + break; + default: + args->a0 = OPTEE_SMC_RETURN_EBADCMD; + return; + } +#else + ret = TEE_ERROR_NOT_SUPPORTED; +#endif + if (ret == TEE_ERROR_NOT_SUPPORTED) + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; + else if (ret) + args->a0 = OPTEE_SMC_RETURN_EBADADDR; + else + args->a0 = OPTEE_SMC_RETURN_OK; +} + +static void tee_entry_exchange_capabilities(struct thread_smc_args *args) +{ + bool res_shm_en = IS_ENABLED(CFG_CORE_RESERVED_SHM); + bool dyn_shm_en __maybe_unused = false; + + /* + * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR. + * + * The memory mapping of shared memory is defined as normal + * shared memory for SMP systems and normal memory for UP + * systems. Currently we map all memory as shared in secure + * world. + * + * When translation tables are created with shared bit cleared for + * uniprocessor systems we'll need to check + * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR. + */ + + if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) { + /* Unknown capability. */ + args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; + return; + } + + args->a0 = OPTEE_SMC_RETURN_OK; + args->a1 = 0; + + if (res_shm_en) + args->a1 |= OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM; + IMSG("Reserved shared memory is %sabled", res_shm_en ? "en" : "dis"); + +#if defined(CFG_CORE_DYN_SHM) + dyn_shm_en = core_mmu_nsec_ddr_is_defined(); + if (dyn_shm_en) + args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM; +#endif + IMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis"); + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + args->a1 |= OPTEE_SMC_SEC_CAP_VIRTUALIZATION; + IMSG("Normal World virtualization support is %sabled", + IS_ENABLED(CFG_NS_VIRTUALIZATION) ? "en" : "dis"); + + args->a1 |= OPTEE_SMC_SEC_CAP_MEMREF_NULL; + + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { + args->a1 |= OPTEE_SMC_SEC_CAP_ASYNC_NOTIF; + args->a2 = NOTIF_VALUE_MAX; + } + IMSG("Asynchronous notifications are %sabled", + IS_ENABLED(CFG_CORE_ASYNC_NOTIF) ? "en" : "dis"); + + args->a1 |= OPTEE_SMC_SEC_CAP_RPC_ARG; + args->a3 = THREAD_RPC_MAX_NUM_PARAMS; +} + +static void tee_entry_disable_shm_cache(struct thread_smc_args *args) +{ + uint64_t cookie; + + if (!thread_disable_prealloc_rpc_cache(&cookie)) { + args->a0 = OPTEE_SMC_RETURN_EBUSY; + return; + } + + if (!cookie) { + args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; + return; + } + + args->a0 = OPTEE_SMC_RETURN_OK; + args->a1 = cookie >> 32; + args->a2 = cookie; +} + +static void tee_entry_enable_shm_cache(struct thread_smc_args *args) +{ + if (thread_enable_prealloc_rpc_cache()) + args->a0 = OPTEE_SMC_RETURN_OK; + else + args->a0 = OPTEE_SMC_RETURN_EBUSY; +} + +static void tee_entry_boot_secondary(struct thread_smc_args *args) +{ +#if defined(CFG_BOOT_SECONDARY_REQUEST) + if (!boot_core_release(args->a1, (paddr_t)(args->a3))) + args->a0 = OPTEE_SMC_RETURN_OK; + else + args->a0 = OPTEE_SMC_RETURN_EBADCMD; +#else + args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; +#endif +} + +static void tee_entry_get_thread_count(struct thread_smc_args *args) +{ + args->a0 = OPTEE_SMC_RETURN_OK; + args->a1 = CFG_NUM_THREADS; +} + +#if defined(CFG_NS_VIRTUALIZATION) +static void tee_entry_vm_created(struct thread_smc_args *args) +{ + uint16_t guest_id = args->a1; + + /* Only hypervisor can issue this request */ + if (args->a7 != HYP_CLNT_ID) { + args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; + return; + } + + if (virt_guest_created(guest_id)) + args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; + else + args->a0 = OPTEE_SMC_RETURN_OK; +} + +static void tee_entry_vm_destroyed(struct thread_smc_args *args) +{ + uint16_t guest_id = args->a1; + + /* Only hypervisor can issue this request */ + if (args->a7 != HYP_CLNT_ID) { + args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; + return; + } + + if (virt_guest_destroyed(guest_id)) + args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; + else + args->a0 = OPTEE_SMC_RETURN_OK; +} +#endif + +/* Note: this function is weak to let platforms add special handling */ +void __weak tee_entry_fast(struct thread_smc_args *args) +{ + __tee_entry_fast(args); +} + +static void get_async_notif_value(struct thread_smc_args *args) +{ + bool value_valid = false; + bool value_pending = false; + + args->a0 = OPTEE_SMC_RETURN_OK; + args->a1 = notif_get_value(&value_valid, &value_pending); + args->a2 = 0; + if (value_valid) + args->a2 |= OPTEE_SMC_ASYNC_NOTIF_VALID; + if (value_pending) + args->a2 |= OPTEE_SMC_ASYNC_NOTIF_PENDING; +} + +/* + * If tee_entry_fast() is overridden, it's still supposed to call this + * function. + */ +void __tee_entry_fast(struct thread_smc_args *args) +{ + switch (args->a0) { + + /* Generic functions */ + case OPTEE_SMC_CALLS_COUNT: + tee_entry_get_api_call_count(args); + break; + case OPTEE_SMC_CALLS_UID: + tee_entry_get_api_uuid(args); + break; + case OPTEE_SMC_CALLS_REVISION: + tee_entry_get_api_revision(args); + break; + case OPTEE_SMC_CALL_GET_OS_UUID: + tee_entry_get_os_uuid(args); + break; + case OPTEE_SMC_CALL_GET_OS_REVISION: + tee_entry_get_os_revision(args); + break; + + /* OP-TEE specific SMC functions */ +#ifdef CFG_CORE_RESERVED_SHM + case OPTEE_SMC_GET_SHM_CONFIG: + tee_entry_get_shm_config(args); + break; +#endif + case OPTEE_SMC_L2CC_MUTEX: + tee_entry_fastcall_l2cc_mutex(args); + break; + case OPTEE_SMC_EXCHANGE_CAPABILITIES: + tee_entry_exchange_capabilities(args); + break; + case OPTEE_SMC_DISABLE_SHM_CACHE: + tee_entry_disable_shm_cache(args); + break; + case OPTEE_SMC_ENABLE_SHM_CACHE: + tee_entry_enable_shm_cache(args); + break; + case OPTEE_SMC_BOOT_SECONDARY: + tee_entry_boot_secondary(args); + break; + case OPTEE_SMC_GET_THREAD_COUNT: + tee_entry_get_thread_count(args); + break; + +#if defined(CFG_NS_VIRTUALIZATION) + case OPTEE_SMC_VM_CREATED: + tee_entry_vm_created(args); + break; + case OPTEE_SMC_VM_DESTROYED: + tee_entry_vm_destroyed(args); + break; +#endif + + case OPTEE_SMC_ENABLE_ASYNC_NOTIF: + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { + notif_deliver_atomic_event(NOTIF_EVENT_STARTED); + args->a0 = OPTEE_SMC_RETURN_OK; + } else { + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; + } + break; + case OPTEE_SMC_GET_ASYNC_NOTIF_VALUE: + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) + get_async_notif_value(args); + else + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; + break; + + default: + args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; + break; + } +} + +size_t tee_entry_generic_get_api_call_count(void) +{ + /* + * All the different 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. + */ + size_t ret = 12; + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + ret += 2; + + return ret; +} + +void __weak tee_entry_get_api_call_count(struct thread_smc_args *args) +{ + args->a0 = tee_entry_generic_get_api_call_count(); +} + +void __weak tee_entry_get_api_uuid(struct thread_smc_args *args) +{ + args->a0 = OPTEE_MSG_UID_0; + args->a1 = OPTEE_MSG_UID_1; + args->a2 = OPTEE_MSG_UID_2; + args->a3 = OPTEE_MSG_UID_3; +} + +void __weak tee_entry_get_api_revision(struct thread_smc_args *args) +{ + args->a0 = OPTEE_MSG_REVISION_MAJOR; + args->a1 = OPTEE_MSG_REVISION_MINOR; +} + +void __weak tee_entry_get_os_uuid(struct thread_smc_args *args) +{ + args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0; + args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1; + args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2; + args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3; +} + +void __weak tee_entry_get_os_revision(struct thread_smc_args *args) +{ + args->a0 = CFG_OPTEE_REVISION_MAJOR; + args->a1 = CFG_OPTEE_REVISION_MINOR; + args->a2 = TEE_IMPL_GIT_SHA1; +} diff --git a/optee/optee_os/core/arch/arm/tee/sub.mk b/optee/optee_os/core/arch/arm/tee/sub.mk new file mode 100644 index 0000000..5523b3b --- /dev/null +++ b/optee/optee_os/core/arch/arm/tee/sub.mk @@ -0,0 +1,8 @@ +ifeq ($(CFG_WITH_USER_TA),y) +srcs-$(CFG_CACHE_API) += svc_cache.c +endif +ifneq ($(CFG_CORE_FFA),y) +srcs-y += entry_fast.c +cppflags-entry_fast.c-y += -DTEE_IMPL_GIT_SHA1=$(TEE_IMPL_GIT_SHA1) +endif +srcs-y += cache.c diff --git a/optee/optee_os/core/arch/arm/tee/svc_cache.c b/optee/optee_os/core/arch/arm/tee/svc_cache.c new file mode 100644 index 0000000..304c4d9 --- /dev/null +++ b/optee/optee_os/core/arch/arm/tee/svc_cache.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include +#include + +TEE_Result syscall_cache_operation(void *va, size_t len, unsigned long op) +{ + struct ts_session *s = ts_get_current_session(); + struct user_ta_ctx *utc = NULL; + TEE_Result res = TEE_SUCCESS; + + if ((to_ta_ctx(s->ctx)->flags & TA_FLAG_CACHE_MAINTENANCE) == 0) + return TEE_ERROR_NOT_SUPPORTED; + + utc = to_user_ta_ctx(s->ctx); + + /* + * TAs are allowed to operate cache maintenance on TA memref parameters + * only, not on the TA private memory. + */ + if (vm_buf_intersects_um_private(&utc->uctx, va, len)) + return TEE_ERROR_ACCESS_DENIED; + + res = vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)va, len); + if (res != TEE_SUCCESS) + return TEE_ERROR_ACCESS_DENIED; + + return cache_operation(op, va, len); +} diff --git a/optee/optee_os/core/arch/riscv/include/encoding.h b/optee/optee_os/core/arch/riscv/include/encoding.h new file mode 100644 index 0000000..5ab5c76 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/encoding.h @@ -0,0 +1,4892 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* Copyright (c) 2022 RISC-V International */ + +/* + * This file is auto-generated by running 'make' in + * https://github.com/riscv/riscv-opcodes (86edbf4) + */ + +#ifndef RISCV_CSR_ENCODING_H +#define RISCV_CSR_ENCODING_H + +#define MSTATUS_UIE 0x00000001 +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_HIE 0x00000004 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_UPIE 0x00000010 +#define MSTATUS_SPIE 0x00000020 +#define MSTATUS_UBE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP 0x00000100 +#define MSTATUS_VS 0x00000600 +#define MSTATUS_MPP 0x00001800 +#define MSTATUS_FS 0x00006000 +#define MSTATUS_XS 0x00018000 +#define MSTATUS_MPRV 0x00020000 +#define MSTATUS_SUM 0x00040000 +#define MSTATUS_MXR 0x00080000 +#define MSTATUS_TVM 0x00100000 +#define MSTATUS_TW 0x00200000 +#define MSTATUS_TSR 0x00400000 +#define MSTATUS32_SD 0x80000000 +#define MSTATUS_UXL 0x0000000300000000 +#define MSTATUS_SXL 0x0000000C00000000 +#define MSTATUS_SBE 0x0000001000000000 +#define MSTATUS_MBE 0x0000002000000000 +#define MSTATUS_GVA 0x0000004000000000 +#define MSTATUS_MPV 0x0000008000000000 +#define MSTATUS64_SD 0x8000000000000000 + +#define MSTATUSH_SBE 0x00000010 +#define MSTATUSH_MBE 0x00000020 +#define MSTATUSH_GVA 0x00000040 +#define MSTATUSH_MPV 0x00000080 + +#define SSTATUS_UIE 0x00000001 +#define SSTATUS_SIE 0x00000002 +#define SSTATUS_UPIE 0x00000010 +#define SSTATUS_SPIE 0x00000020 +#define SSTATUS_UBE 0x00000040 +#define SSTATUS_SPP 0x00000100 +#define SSTATUS_VS 0x00000600 +#define SSTATUS_FS 0x00006000 +#define SSTATUS_XS 0x00018000 +#define SSTATUS_SUM 0x00040000 +#define SSTATUS_MXR 0x00080000 +#define SSTATUS32_SD 0x80000000 +#define SSTATUS_UXL 0x0000000300000000 +#define SSTATUS64_SD 0x8000000000000000 + +#define HSTATUS_VSXL 0x300000000 +#define HSTATUS_VTSR 0x00400000 +#define HSTATUS_VTW 0x00200000 +#define HSTATUS_VTVM 0x00100000 +#define HSTATUS_VGEIN 0x0003f000 +#define HSTATUS_HU 0x00000200 +#define HSTATUS_SPVP 0x00000100 +#define HSTATUS_SPV 0x00000080 +#define HSTATUS_GVA 0x00000040 +#define HSTATUS_VSBE 0x00000020 + +#define USTATUS_UIE 0x00000001 +#define USTATUS_UPIE 0x00000010 + +#define DCSR_XDEBUGVER (3U<<30) +#define DCSR_NDRESET (1<<29) +#define DCSR_FULLRESET (1<<28) +#define DCSR_EBREAKM (1<<15) +#define DCSR_EBREAKH (1<<14) +#define DCSR_EBREAKS (1<<13) +#define DCSR_EBREAKU (1<<12) +#define DCSR_STOPCYCLE (1<<10) +#define DCSR_STOPTIME (1<<9) +#define DCSR_CAUSE (7<<6) +#define DCSR_DEBUGINT (1<<5) +#define DCSR_HALT (1<<3) +#define DCSR_STEP (1<<2) +#define DCSR_PRV (3<<0) + +#define DCSR_CAUSE_NONE 0 +#define DCSR_CAUSE_SWBP 1 +#define DCSR_CAUSE_HWBP 2 +#define DCSR_CAUSE_DEBUGINT 3 +#define DCSR_CAUSE_STEP 4 +#define DCSR_CAUSE_HALT 5 +#define DCSR_CAUSE_GROUP 6 + +#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) +#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) +#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) + +#define MCONTROL_SELECT (1<<19) +#define MCONTROL_TIMING (1<<18) +#define MCONTROL_ACTION (0x3f<<12) +#define MCONTROL_CHAIN (1<<11) +#define MCONTROL_MATCH (0xf<<7) +#define MCONTROL_M (1<<6) +#define MCONTROL_H (1<<5) +#define MCONTROL_S (1<<4) +#define MCONTROL_U (1<<3) +#define MCONTROL_EXECUTE (1<<2) +#define MCONTROL_STORE (1<<1) +#define MCONTROL_LOAD (1<<0) + +#define MCONTROL_TYPE_NONE 0 +#define MCONTROL_TYPE_MATCH 2 + +#define MCONTROL_ACTION_DEBUG_EXCEPTION 0 +#define MCONTROL_ACTION_DEBUG_MODE 1 +#define MCONTROL_ACTION_TRACE_START 2 +#define MCONTROL_ACTION_TRACE_STOP 3 +#define MCONTROL_ACTION_TRACE_EMIT 4 + +#define MCONTROL_MATCH_EQUAL 0 +#define MCONTROL_MATCH_NAPOT 1 +#define MCONTROL_MATCH_GE 2 +#define MCONTROL_MATCH_LT 3 +#define MCONTROL_MATCH_MASK_LOW 4 +#define MCONTROL_MATCH_MASK_HIGH 5 + +#define MIP_USIP (1 << IRQ_U_SOFT) +#define MIP_SSIP (1 << IRQ_S_SOFT) +#define MIP_VSSIP (1 << IRQ_VS_SOFT) +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_UTIP (1 << IRQ_U_TIMER) +#define MIP_STIP (1 << IRQ_S_TIMER) +#define MIP_VSTIP (1 << IRQ_VS_TIMER) +#define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_UEIP (1 << IRQ_U_EXT) +#define MIP_SEIP (1 << IRQ_S_EXT) +#define MIP_VSEIP (1 << IRQ_VS_EXT) +#define MIP_MEIP (1 << IRQ_M_EXT) +#define MIP_SGEIP (1 << IRQ_S_GEXT) +#define MIP_LCOFIP (1 << IRQ_LCOF) + +#define MIP_S_MASK (MIP_SSIP | MIP_STIP | MIP_SEIP) +#define MIP_VS_MASK (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP) +#define MIP_HS_MASK (MIP_VS_MASK | MIP_SGEIP) + +#define MIDELEG_FORCED_MASK MIP_HS_MASK + +#define SIP_SSIP MIP_SSIP +#define SIP_STIP MIP_STIP + +#define MENVCFG_FIOM 0x00000001 +#define MENVCFG_CBIE 0x00000030 +#define MENVCFG_CBCFE 0x00000040 +#define MENVCFG_CBZE 0x00000080 +#define MENVCFG_PBMTE 0x4000000000000000 +#define MENVCFG_STCE 0x8000000000000000 + +#define MENVCFGH_PBMTE 0x40000000 +#define MENVCFGH_STCE 0x80000000 + +#define MSTATEEN0_CS 0x00000001 +#define MSTATEEN0_FCSR 0x00000002 +#define MSTATEEN0_HCONTEXT 0x0200000000000000 +#define MSTATEEN0_HENVCFG 0x4000000000000000 +#define MSTATEEN_HSTATEEN 0x8000000000000000 + +#define MSTATEEN0H_HCONTEXT 0x02000000 +#define MSTATEEN0H_HENVCFG 0x40000000 +#define MSTATEENH_HSTATEEN 0x80000000 + +#define MHPMEVENT_VUINH 0x0400000000000000 +#define MHPMEVENT_VSINH 0x0800000000000000 +#define MHPMEVENT_UINH 0x1000000000000000 +#define MHPMEVENT_SINH 0x2000000000000000 +#define MHPMEVENT_MINH 0x4000000000000000 +#define MHPMEVENT_OF 0x8000000000000000 + +#define MHPMEVENTH_VUINH 0x04000000 +#define MHPMEVENTH_VSINH 0x08000000 +#define MHPMEVENTH_UINH 0x10000000 +#define MHPMEVENTH_SINH 0x20000000 +#define MHPMEVENTH_MINH 0x40000000 +#define MHPMEVENTH_OF 0x80000000 + +#define HENVCFG_FIOM 0x00000001 +#define HENVCFG_CBIE 0x00000030 +#define HENVCFG_CBCFE 0x00000040 +#define HENVCFG_CBZE 0x00000080 +#define HENVCFG_PBMTE 0x4000000000000000 +#define HENVCFG_STCE 0x8000000000000000 + +#define HENVCFGH_PBMTE 0x40000000 +#define HENVCFGH_STCE 0x80000000 + +#define HSTATEEN0_CS 0x00000001 +#define HSTATEEN0_FCSR 0x00000002 +#define HSTATEEN0_SCONTEXT 0x0200000000000000 +#define HSTATEEN0_SENVCFG 0x4000000000000000 +#define HSTATEEN_SSTATEEN 0x8000000000000000 + +#define HSTATEEN0H_SCONTEXT 0x02000000 +#define HSTATEEN0H_SENVCFG 0x40000000 +#define HSTATEENH_SSTATEEN 0x80000000 + +#define SENVCFG_FIOM 0x00000001 +#define SENVCFG_CBIE 0x00000030 +#define SENVCFG_CBCFE 0x00000040 +#define SENVCFG_CBZE 0x00000080 + +#define SSTATEEN0_CS 0x00000001 +#define SSTATEEN0_FCSR 0x00000002 + +#define MSECCFG_MML 0x00000001 +#define MSECCFG_MMWP 0x00000002 +#define MSECCFG_RLB 0x00000004 +#define MSECCFG_USEED 0x00000100 +#define MSECCFG_SSEED 0x00000200 + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_M 3 + +#define PRV_HS (PRV_S + 1) + +#define SATP32_MODE 0x80000000 +#define SATP32_ASID 0x7FC00000 +#define SATP32_PPN 0x003FFFFF +#define SATP64_MODE 0xF000000000000000 +#define SATP64_ASID 0x0FFFF00000000000 +#define SATP64_PPN 0x00000FFFFFFFFFFF + +#define SATP_MODE_OFF 0 +#define SATP_MODE_SV32 1 +#define SATP_MODE_SV39 8 +#define SATP_MODE_SV48 9 +#define SATP_MODE_SV57 10 +#define SATP_MODE_SV64 11 + +#define HGATP32_MODE 0x80000000 +#define HGATP32_VMID 0x1FC00000 +#define HGATP32_PPN 0x003FFFFF + +#define HGATP64_MODE 0xF000000000000000 +#define HGATP64_VMID 0x03FFF00000000000 +#define HGATP64_PPN 0x00000FFFFFFFFFFF + +#define HGATP_MODE_OFF 0 +#define HGATP_MODE_SV32X4 1 +#define HGATP_MODE_SV39X4 8 +#define HGATP_MODE_SV48X4 9 +#define HGATP_MODE_SV57X4 10 + +#define PMP_R 0x01 +#define PMP_W 0x02 +#define PMP_X 0x04 +#define PMP_A 0x18 +#define PMP_L 0x80 +#define PMP_SHIFT 2 + +#define PMP_TOR 0x08 +#define PMP_NA4 0x10 +#define PMP_NAPOT 0x18 + +#define IRQ_U_SOFT 0 +#define IRQ_S_SOFT 1 +#define IRQ_VS_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_U_TIMER 4 +#define IRQ_S_TIMER 5 +#define IRQ_VS_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_U_EXT 8 +#define IRQ_S_EXT 9 +#define IRQ_VS_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_S_GEXT 12 +#define IRQ_COP 12 +#define IRQ_LCOF 13 + +/* page table entry (PTE) fields */ +#define PTE_V 0x001 /* Valid */ +#define PTE_R 0x002 /* Read */ +#define PTE_W 0x004 /* Write */ +#define PTE_X 0x008 /* Execute */ +#define PTE_U 0x010 /* User */ +#define PTE_G 0x020 /* Global */ +#define PTE_A 0x040 /* Accessed */ +#define PTE_D 0x080 /* Dirty */ +#define PTE_SOFT 0x300 /* Reserved for Software */ +#define PTE_RSVD 0x1FC0000000000000 /* Reserved for future standard use */ +#define PTE_PBMT 0x6000000000000000 /* Svpbmt: Page-based memory types */ +#define PTE_N 0x8000000000000000 /* Svnapot: NAPOT translation contiguity */ +#define PTE_ATTR 0xFFC0000000000000 /* All attributes and reserved bits */ + +#define PTE_PPN_SHIFT 10 + +#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) + +#ifdef __riscv + +#if __riscv_xlen == 64 +# define MSTATUS_SD MSTATUS64_SD +# define SSTATUS_SD SSTATUS64_SD +# define RISCV_PGLEVEL_BITS 9 +# define SATP_MODE SATP64_MODE +#else +# define MSTATUS_SD MSTATUS32_SD +# define SSTATUS_SD SSTATUS32_SD +# define RISCV_PGLEVEL_BITS 10 +# define SATP_MODE SATP32_MODE +#endif +#define RISCV_PGSHIFT 12 +#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) + +#endif + +#endif + +/* Automatically generated by parse_opcodes. */ +#ifndef RISCV_ENCODING_H +#define RISCV_ENCODING_H +#define MATCH_ADD 0x33 +#define MASK_ADD 0xfe00707f +#define MATCH_ADD16 0x40000077 +#define MASK_ADD16 0xfe00707f +#define MATCH_ADD32 0x40002077 +#define MASK_ADD32 0xfe00707f +#define MATCH_ADD64 0xc0001077 +#define MASK_ADD64 0xfe00707f +#define MATCH_ADD8 0x48000077 +#define MASK_ADD8 0xfe00707f +#define MATCH_ADD_UW 0x800003b +#define MASK_ADD_UW 0xfe00707f +#define MATCH_ADDD 0x7b +#define MASK_ADDD 0xfe00707f +#define MATCH_ADDI 0x13 +#define MASK_ADDI 0x707f +#define MATCH_ADDID 0x5b +#define MASK_ADDID 0x707f +#define MATCH_ADDIW 0x1b +#define MASK_ADDIW 0x707f +#define MATCH_ADDW 0x3b +#define MASK_ADDW 0xfe00707f +#define MATCH_AES32DSI 0x2a000033 +#define MASK_AES32DSI 0x3e00707f +#define MATCH_AES32DSMI 0x2e000033 +#define MASK_AES32DSMI 0x3e00707f +#define MATCH_AES32ESI 0x22000033 +#define MASK_AES32ESI 0x3e00707f +#define MATCH_AES32ESMI 0x26000033 +#define MASK_AES32ESMI 0x3e00707f +#define MATCH_AES64DS 0x3a000033 +#define MASK_AES64DS 0xfe00707f +#define MATCH_AES64DSM 0x3e000033 +#define MASK_AES64DSM 0xfe00707f +#define MATCH_AES64ES 0x32000033 +#define MASK_AES64ES 0xfe00707f +#define MATCH_AES64ESM 0x36000033 +#define MASK_AES64ESM 0xfe00707f +#define MATCH_AES64IM 0x30001013 +#define MASK_AES64IM 0xfff0707f +#define MATCH_AES64KS1I 0x31001013 +#define MASK_AES64KS1I 0xff00707f +#define MATCH_AES64KS2 0x7e000033 +#define MASK_AES64KS2 0xfe00707f +#define MATCH_AMOADD_D 0x302f +#define MASK_AMOADD_D 0xf800707f +#define MATCH_AMOADD_W 0x202f +#define MASK_AMOADD_W 0xf800707f +#define MATCH_AMOAND_D 0x6000302f +#define MASK_AMOAND_D 0xf800707f +#define MATCH_AMOAND_W 0x6000202f +#define MASK_AMOAND_W 0xf800707f +#define MATCH_AMOMAX_D 0xa000302f +#define MASK_AMOMAX_D 0xf800707f +#define MATCH_AMOMAX_W 0xa000202f +#define MASK_AMOMAX_W 0xf800707f +#define MATCH_AMOMAXU_D 0xe000302f +#define MASK_AMOMAXU_D 0xf800707f +#define MATCH_AMOMAXU_W 0xe000202f +#define MASK_AMOMAXU_W 0xf800707f +#define MATCH_AMOMIN_D 0x8000302f +#define MASK_AMOMIN_D 0xf800707f +#define MATCH_AMOMIN_W 0x8000202f +#define MASK_AMOMIN_W 0xf800707f +#define MATCH_AMOMINU_D 0xc000302f +#define MASK_AMOMINU_D 0xf800707f +#define MATCH_AMOMINU_W 0xc000202f +#define MASK_AMOMINU_W 0xf800707f +#define MATCH_AMOOR_D 0x4000302f +#define MASK_AMOOR_D 0xf800707f +#define MATCH_AMOOR_W 0x4000202f +#define MASK_AMOOR_W 0xf800707f +#define MATCH_AMOSWAP_D 0x800302f +#define MASK_AMOSWAP_D 0xf800707f +#define MATCH_AMOSWAP_W 0x800202f +#define MASK_AMOSWAP_W 0xf800707f +#define MATCH_AMOXOR_D 0x2000302f +#define MASK_AMOXOR_D 0xf800707f +#define MATCH_AMOXOR_W 0x2000202f +#define MASK_AMOXOR_W 0xf800707f +#define MATCH_AND 0x7033 +#define MASK_AND 0xfe00707f +#define MATCH_ANDI 0x7013 +#define MASK_ANDI 0x707f +#define MATCH_ANDN 0x40007033 +#define MASK_ANDN 0xfe00707f +#define MATCH_AUIPC 0x17 +#define MASK_AUIPC 0x7f +#define MATCH_AVE 0xe0000077 +#define MASK_AVE 0xfe00707f +#define MATCH_BCLR 0x48001033 +#define MASK_BCLR 0xfe00707f +#define MATCH_BCLRI 0x48001013 +#define MASK_BCLRI 0xfc00707f +#define MATCH_BCOMPRESS 0x8006033 +#define MASK_BCOMPRESS 0xfe00707f +#define MATCH_BCOMPRESSW 0x800603b +#define MASK_BCOMPRESSW 0xfe00707f +#define MATCH_BDECOMPRESS 0x48006033 +#define MASK_BDECOMPRESS 0xfe00707f +#define MATCH_BDECOMPRESSW 0x4800603b +#define MASK_BDECOMPRESSW 0xfe00707f +#define MATCH_BEQ 0x63 +#define MASK_BEQ 0x707f +#define MATCH_BEXT 0x48005033 +#define MASK_BEXT 0xfe00707f +#define MATCH_BEXTI 0x48005013 +#define MASK_BEXTI 0xfc00707f +#define MATCH_BFP 0x48007033 +#define MASK_BFP 0xfe00707f +#define MATCH_BFPW 0x4800703b +#define MASK_BFPW 0xfe00707f +#define MATCH_BGE 0x5063 +#define MASK_BGE 0x707f +#define MATCH_BGEU 0x7063 +#define MASK_BGEU 0x707f +#define MATCH_BINV 0x68001033 +#define MASK_BINV 0xfe00707f +#define MATCH_BINVI 0x68001013 +#define MASK_BINVI 0xfc00707f +#define MATCH_BITREV 0xe6000077 +#define MASK_BITREV 0xfe00707f +#define MATCH_BITREVI 0xe8000077 +#define MASK_BITREVI 0xfc00707f +#define MATCH_BLT 0x4063 +#define MASK_BLT 0x707f +#define MATCH_BLTU 0x6063 +#define MASK_BLTU 0x707f +#define MATCH_BMATFLIP 0x60301013 +#define MASK_BMATFLIP 0xfff0707f +#define MATCH_BMATOR 0x8003033 +#define MASK_BMATOR 0xfe00707f +#define MATCH_BMATXOR 0x48003033 +#define MASK_BMATXOR 0xfe00707f +#define MATCH_BNE 0x1063 +#define MASK_BNE 0x707f +#define MATCH_BPICK 0x3077 +#define MASK_BPICK 0x600707f +#define MATCH_BSET 0x28001033 +#define MASK_BSET 0xfe00707f +#define MATCH_BSETI 0x28001013 +#define MASK_BSETI 0xfc00707f +#define MATCH_C_ADD 0x9002 +#define MASK_C_ADD 0xf003 +#define MATCH_C_ADDI 0x1 +#define MASK_C_ADDI 0xe003 +#define MATCH_C_ADDI16SP 0x6101 +#define MASK_C_ADDI16SP 0xef83 +#define MATCH_C_ADDI4SPN 0x0 +#define MASK_C_ADDI4SPN 0xe003 +#define MATCH_C_ADDIW 0x2001 +#define MASK_C_ADDIW 0xe003 +#define MATCH_C_ADDW 0x9c21 +#define MASK_C_ADDW 0xfc63 +#define MATCH_C_AND 0x8c61 +#define MASK_C_AND 0xfc63 +#define MATCH_C_ANDI 0x8801 +#define MASK_C_ANDI 0xec03 +#define MATCH_C_BEQZ 0xc001 +#define MASK_C_BEQZ 0xe003 +#define MATCH_C_BNEZ 0xe001 +#define MASK_C_BNEZ 0xe003 +#define MATCH_C_EBREAK 0x9002 +#define MASK_C_EBREAK 0xffff +#define MATCH_C_FLD 0x2000 +#define MASK_C_FLD 0xe003 +#define MATCH_C_FLDSP 0x2002 +#define MASK_C_FLDSP 0xe003 +#define MATCH_C_FLW 0x6000 +#define MASK_C_FLW 0xe003 +#define MATCH_C_FLWSP 0x6002 +#define MASK_C_FLWSP 0xe003 +#define MATCH_C_FSD 0xa000 +#define MASK_C_FSD 0xe003 +#define MATCH_C_FSDSP 0xa002 +#define MASK_C_FSDSP 0xe003 +#define MATCH_C_FSW 0xe000 +#define MASK_C_FSW 0xe003 +#define MATCH_C_FSWSP 0xe002 +#define MASK_C_FSWSP 0xe003 +#define MATCH_C_J 0xa001 +#define MASK_C_J 0xe003 +#define MATCH_C_JAL 0x2001 +#define MASK_C_JAL 0xe003 +#define MATCH_C_JALR 0x9002 +#define MASK_C_JALR 0xf07f +#define MATCH_C_JR 0x8002 +#define MASK_C_JR 0xf07f +#define MATCH_C_LD 0x6000 +#define MASK_C_LD 0xe003 +#define MATCH_C_LDSP 0x6002 +#define MASK_C_LDSP 0xe003 +#define MATCH_C_LI 0x4001 +#define MASK_C_LI 0xe003 +#define MATCH_C_LQ 0x2000 +#define MASK_C_LQ 0xe003 +#define MATCH_C_LQSP 0x2002 +#define MASK_C_LQSP 0xe003 +#define MATCH_C_LUI 0x6001 +#define MASK_C_LUI 0xe003 +#define MATCH_C_LW 0x4000 +#define MASK_C_LW 0xe003 +#define MATCH_C_LWSP 0x4002 +#define MASK_C_LWSP 0xe003 +#define MATCH_C_MV 0x8002 +#define MASK_C_MV 0xf003 +#define MATCH_C_NOP 0x1 +#define MASK_C_NOP 0xef83 +#define MATCH_C_OR 0x8c41 +#define MASK_C_OR 0xfc63 +#define MATCH_C_SD 0xe000 +#define MASK_C_SD 0xe003 +#define MATCH_C_SDSP 0xe002 +#define MASK_C_SDSP 0xe003 +#define MATCH_C_SLLI 0x2 +#define MASK_C_SLLI 0xe003 +#define MATCH_C_SQ 0xa000 +#define MASK_C_SQ 0xe003 +#define MATCH_C_SQSP 0xa002 +#define MASK_C_SQSP 0xe003 +#define MATCH_C_SRAI 0x8401 +#define MASK_C_SRAI 0xec03 +#define MATCH_C_SRLI 0x8001 +#define MASK_C_SRLI 0xec03 +#define MATCH_C_SUB 0x8c01 +#define MASK_C_SUB 0xfc63 +#define MATCH_C_SUBW 0x9c01 +#define MASK_C_SUBW 0xfc63 +#define MATCH_C_SW 0xc000 +#define MASK_C_SW 0xe003 +#define MATCH_C_SWSP 0xc002 +#define MASK_C_SWSP 0xe003 +#define MATCH_C_XOR 0x8c21 +#define MASK_C_XOR 0xfc63 +#define MATCH_CBO_CLEAN 0x10200f +#define MASK_CBO_CLEAN 0xfff07fff +#define MATCH_CBO_FLUSH 0x20200f +#define MASK_CBO_FLUSH 0xfff07fff +#define MATCH_CBO_INVAL 0x200f +#define MASK_CBO_INVAL 0xfff07fff +#define MATCH_CBO_ZERO 0x40200f +#define MASK_CBO_ZERO 0xfff07fff +#define MATCH_CLMUL 0xa001033 +#define MASK_CLMUL 0xfe00707f +#define MATCH_CLMULH 0xa003033 +#define MASK_CLMULH 0xfe00707f +#define MATCH_CLMULR 0xa002033 +#define MASK_CLMULR 0xfe00707f +#define MATCH_CLO16 0xaeb00077 +#define MASK_CLO16 0xfff0707f +#define MATCH_CLO32 0xafb00077 +#define MASK_CLO32 0xfff0707f +#define MATCH_CLO8 0xae300077 +#define MASK_CLO8 0xfff0707f +#define MATCH_CLRS16 0xae800077 +#define MASK_CLRS16 0xfff0707f +#define MATCH_CLRS32 0xaf800077 +#define MASK_CLRS32 0xfff0707f +#define MATCH_CLRS8 0xae000077 +#define MASK_CLRS8 0xfff0707f +#define MATCH_CLZ 0x60001013 +#define MASK_CLZ 0xfff0707f +#define MATCH_CLZ16 0xae900077 +#define MASK_CLZ16 0xfff0707f +#define MATCH_CLZ32 0xaf900077 +#define MASK_CLZ32 0xfff0707f +#define MATCH_CLZ8 0xae100077 +#define MASK_CLZ8 0xfff0707f +#define MATCH_CLZW 0x6000101b +#define MASK_CLZW 0xfff0707f +#define MATCH_CMIX 0x6001033 +#define MASK_CMIX 0x600707f +#define MATCH_CMOV 0x6005033 +#define MASK_CMOV 0x600707f +#define MATCH_CMPEQ16 0x4c000077 +#define MASK_CMPEQ16 0xfe00707f +#define MATCH_CMPEQ8 0x4e000077 +#define MASK_CMPEQ8 0xfe00707f +#define MATCH_CPOP 0x60201013 +#define MASK_CPOP 0xfff0707f +#define MATCH_CPOPW 0x6020101b +#define MASK_CPOPW 0xfff0707f +#define MATCH_CRAS16 0x44000077 +#define MASK_CRAS16 0xfe00707f +#define MATCH_CRAS32 0x44002077 +#define MASK_CRAS32 0xfe00707f +#define MATCH_CRC32_B 0x61001013 +#define MASK_CRC32_B 0xfff0707f +#define MATCH_CRC32_D 0x61301013 +#define MASK_CRC32_D 0xfff0707f +#define MATCH_CRC32_H 0x61101013 +#define MASK_CRC32_H 0xfff0707f +#define MATCH_CRC32_W 0x61201013 +#define MASK_CRC32_W 0xfff0707f +#define MATCH_CRC32C_B 0x61801013 +#define MASK_CRC32C_B 0xfff0707f +#define MATCH_CRC32C_D 0x61b01013 +#define MASK_CRC32C_D 0xfff0707f +#define MATCH_CRC32C_H 0x61901013 +#define MASK_CRC32C_H 0xfff0707f +#define MATCH_CRC32C_W 0x61a01013 +#define MASK_CRC32C_W 0xfff0707f +#define MATCH_CRSA16 0x46000077 +#define MASK_CRSA16 0xfe00707f +#define MATCH_CRSA32 0x46002077 +#define MASK_CRSA32 0xfe00707f +#define MATCH_CSRRC 0x3073 +#define MASK_CSRRC 0x707f +#define MATCH_CSRRCI 0x7073 +#define MASK_CSRRCI 0x707f +#define MATCH_CSRRS 0x2073 +#define MASK_CSRRS 0x707f +#define MATCH_CSRRSI 0x6073 +#define MASK_CSRRSI 0x707f +#define MATCH_CSRRW 0x1073 +#define MASK_CSRRW 0x707f +#define MATCH_CSRRWI 0x5073 +#define MASK_CSRRWI 0x707f +#define MATCH_CTZ 0x60101013 +#define MASK_CTZ 0xfff0707f +#define MATCH_CTZW 0x6010101b +#define MASK_CTZW 0xfff0707f +#define MATCH_DIV 0x2004033 +#define MASK_DIV 0xfe00707f +#define MATCH_DIVU 0x2005033 +#define MASK_DIVU 0xfe00707f +#define MATCH_DIVUW 0x200503b +#define MASK_DIVUW 0xfe00707f +#define MATCH_DIVW 0x200403b +#define MASK_DIVW 0xfe00707f +#define MATCH_DRET 0x7b200073 +#define MASK_DRET 0xffffffff +#define MATCH_EBREAK 0x100073 +#define MASK_EBREAK 0xffffffff +#define MATCH_ECALL 0x73 +#define MASK_ECALL 0xffffffff +#define MATCH_FADD_D 0x2000053 +#define MASK_FADD_D 0xfe00007f +#define MATCH_FADD_H 0x4000053 +#define MASK_FADD_H 0xfe00007f +#define MATCH_FADD_Q 0x6000053 +#define MASK_FADD_Q 0xfe00007f +#define MATCH_FADD_S 0x53 +#define MASK_FADD_S 0xfe00007f +#define MATCH_FCLASS_D 0xe2001053 +#define MASK_FCLASS_D 0xfff0707f +#define MATCH_FCLASS_H 0xe4001053 +#define MASK_FCLASS_H 0xfff0707f +#define MATCH_FCLASS_Q 0xe6001053 +#define MASK_FCLASS_Q 0xfff0707f +#define MATCH_FCLASS_S 0xe0001053 +#define MASK_FCLASS_S 0xfff0707f +#define MATCH_FCVT_D_H 0x42200053 +#define MASK_FCVT_D_H 0xfff0007f +#define MATCH_FCVT_D_L 0xd2200053 +#define MASK_FCVT_D_L 0xfff0007f +#define MATCH_FCVT_D_LU 0xd2300053 +#define MASK_FCVT_D_LU 0xfff0007f +#define MATCH_FCVT_D_Q 0x42300053 +#define MASK_FCVT_D_Q 0xfff0007f +#define MATCH_FCVT_D_S 0x42000053 +#define MASK_FCVT_D_S 0xfff0007f +#define MATCH_FCVT_D_W 0xd2000053 +#define MASK_FCVT_D_W 0xfff0007f +#define MATCH_FCVT_D_WU 0xd2100053 +#define MASK_FCVT_D_WU 0xfff0007f +#define MATCH_FCVT_H_D 0x44100053 +#define MASK_FCVT_H_D 0xfff0007f +#define MATCH_FCVT_H_L 0xd4200053 +#define MASK_FCVT_H_L 0xfff0007f +#define MATCH_FCVT_H_LU 0xd4300053 +#define MASK_FCVT_H_LU 0xfff0007f +#define MATCH_FCVT_H_Q 0x44300053 +#define MASK_FCVT_H_Q 0xfff0007f +#define MATCH_FCVT_H_S 0x44000053 +#define MASK_FCVT_H_S 0xfff0007f +#define MATCH_FCVT_H_W 0xd4000053 +#define MASK_FCVT_H_W 0xfff0007f +#define MATCH_FCVT_H_WU 0xd4100053 +#define MASK_FCVT_H_WU 0xfff0007f +#define MATCH_FCVT_L_D 0xc2200053 +#define MASK_FCVT_L_D 0xfff0007f +#define MATCH_FCVT_L_H 0xc4200053 +#define MASK_FCVT_L_H 0xfff0007f +#define MATCH_FCVT_L_Q 0xc6200053 +#define MASK_FCVT_L_Q 0xfff0007f +#define MATCH_FCVT_L_S 0xc0200053 +#define MASK_FCVT_L_S 0xfff0007f +#define MATCH_FCVT_LU_D 0xc2300053 +#define MASK_FCVT_LU_D 0xfff0007f +#define MATCH_FCVT_LU_H 0xc4300053 +#define MASK_FCVT_LU_H 0xfff0007f +#define MATCH_FCVT_LU_Q 0xc6300053 +#define MASK_FCVT_LU_Q 0xfff0007f +#define MATCH_FCVT_LU_S 0xc0300053 +#define MASK_FCVT_LU_S 0xfff0007f +#define MATCH_FCVT_Q_D 0x46100053 +#define MASK_FCVT_Q_D 0xfff0007f +#define MATCH_FCVT_Q_H 0x46200053 +#define MASK_FCVT_Q_H 0xfff0007f +#define MATCH_FCVT_Q_L 0xd6200053 +#define MASK_FCVT_Q_L 0xfff0007f +#define MATCH_FCVT_Q_LU 0xd6300053 +#define MASK_FCVT_Q_LU 0xfff0007f +#define MATCH_FCVT_Q_S 0x46000053 +#define MASK_FCVT_Q_S 0xfff0007f +#define MATCH_FCVT_Q_W 0xd6000053 +#define MASK_FCVT_Q_W 0xfff0007f +#define MATCH_FCVT_Q_WU 0xd6100053 +#define MASK_FCVT_Q_WU 0xfff0007f +#define MATCH_FCVT_S_D 0x40100053 +#define MASK_FCVT_S_D 0xfff0007f +#define MATCH_FCVT_S_H 0x40200053 +#define MASK_FCVT_S_H 0xfff0007f +#define MATCH_FCVT_S_L 0xd0200053 +#define MASK_FCVT_S_L 0xfff0007f +#define MATCH_FCVT_S_LU 0xd0300053 +#define MASK_FCVT_S_LU 0xfff0007f +#define MATCH_FCVT_S_Q 0x40300053 +#define MASK_FCVT_S_Q 0xfff0007f +#define MATCH_FCVT_S_W 0xd0000053 +#define MASK_FCVT_S_W 0xfff0007f +#define MATCH_FCVT_S_WU 0xd0100053 +#define MASK_FCVT_S_WU 0xfff0007f +#define MATCH_FCVT_W_D 0xc2000053 +#define MASK_FCVT_W_D 0xfff0007f +#define MATCH_FCVT_W_H 0xc4000053 +#define MASK_FCVT_W_H 0xfff0007f +#define MATCH_FCVT_W_Q 0xc6000053 +#define MASK_FCVT_W_Q 0xfff0007f +#define MATCH_FCVT_W_S 0xc0000053 +#define MASK_FCVT_W_S 0xfff0007f +#define MATCH_FCVT_WU_D 0xc2100053 +#define MASK_FCVT_WU_D 0xfff0007f +#define MATCH_FCVT_WU_H 0xc4100053 +#define MASK_FCVT_WU_H 0xfff0007f +#define MATCH_FCVT_WU_Q 0xc6100053 +#define MASK_FCVT_WU_Q 0xfff0007f +#define MATCH_FCVT_WU_S 0xc0100053 +#define MASK_FCVT_WU_S 0xfff0007f +#define MATCH_FDIV_D 0x1a000053 +#define MASK_FDIV_D 0xfe00007f +#define MATCH_FDIV_H 0x1c000053 +#define MASK_FDIV_H 0xfe00007f +#define MATCH_FDIV_Q 0x1e000053 +#define MASK_FDIV_Q 0xfe00007f +#define MATCH_FDIV_S 0x18000053 +#define MASK_FDIV_S 0xfe00007f +#define MATCH_FENCE 0xf +#define MASK_FENCE 0x707f +#define MATCH_FENCE_I 0x100f +#define MASK_FENCE_I 0x707f +#define MATCH_FEQ_D 0xa2002053 +#define MASK_FEQ_D 0xfe00707f +#define MATCH_FEQ_H 0xa4002053 +#define MASK_FEQ_H 0xfe00707f +#define MATCH_FEQ_Q 0xa6002053 +#define MASK_FEQ_Q 0xfe00707f +#define MATCH_FEQ_S 0xa0002053 +#define MASK_FEQ_S 0xfe00707f +#define MATCH_FLD 0x3007 +#define MASK_FLD 0x707f +#define MATCH_FLE_D 0xa2000053 +#define MASK_FLE_D 0xfe00707f +#define MATCH_FLE_H 0xa4000053 +#define MASK_FLE_H 0xfe00707f +#define MATCH_FLE_Q 0xa6000053 +#define MASK_FLE_Q 0xfe00707f +#define MATCH_FLE_S 0xa0000053 +#define MASK_FLE_S 0xfe00707f +#define MATCH_FLH 0x1007 +#define MASK_FLH 0x707f +#define MATCH_FLQ 0x4007 +#define MASK_FLQ 0x707f +#define MATCH_FLT_D 0xa2001053 +#define MASK_FLT_D 0xfe00707f +#define MATCH_FLT_H 0xa4001053 +#define MASK_FLT_H 0xfe00707f +#define MATCH_FLT_Q 0xa6001053 +#define MASK_FLT_Q 0xfe00707f +#define MATCH_FLT_S 0xa0001053 +#define MASK_FLT_S 0xfe00707f +#define MATCH_FLW 0x2007 +#define MASK_FLW 0x707f +#define MATCH_FMADD_D 0x2000043 +#define MASK_FMADD_D 0x600007f +#define MATCH_FMADD_H 0x4000043 +#define MASK_FMADD_H 0x600007f +#define MATCH_FMADD_Q 0x6000043 +#define MASK_FMADD_Q 0x600007f +#define MATCH_FMADD_S 0x43 +#define MASK_FMADD_S 0x600007f +#define MATCH_FMAX_D 0x2a001053 +#define MASK_FMAX_D 0xfe00707f +#define MATCH_FMAX_H 0x2c001053 +#define MASK_FMAX_H 0xfe00707f +#define MATCH_FMAX_Q 0x2e001053 +#define MASK_FMAX_Q 0xfe00707f +#define MATCH_FMAX_S 0x28001053 +#define MASK_FMAX_S 0xfe00707f +#define MATCH_FMIN_D 0x2a000053 +#define MASK_FMIN_D 0xfe00707f +#define MATCH_FMIN_H 0x2c000053 +#define MASK_FMIN_H 0xfe00707f +#define MATCH_FMIN_Q 0x2e000053 +#define MASK_FMIN_Q 0xfe00707f +#define MATCH_FMIN_S 0x28000053 +#define MASK_FMIN_S 0xfe00707f +#define MATCH_FMSUB_D 0x2000047 +#define MASK_FMSUB_D 0x600007f +#define MATCH_FMSUB_H 0x4000047 +#define MASK_FMSUB_H 0x600007f +#define MATCH_FMSUB_Q 0x6000047 +#define MASK_FMSUB_Q 0x600007f +#define MATCH_FMSUB_S 0x47 +#define MASK_FMSUB_S 0x600007f +#define MATCH_FMUL_D 0x12000053 +#define MASK_FMUL_D 0xfe00007f +#define MATCH_FMUL_H 0x14000053 +#define MASK_FMUL_H 0xfe00007f +#define MATCH_FMUL_Q 0x16000053 +#define MASK_FMUL_Q 0xfe00007f +#define MATCH_FMUL_S 0x10000053 +#define MASK_FMUL_S 0xfe00007f +#define MATCH_FMV_D_X 0xf2000053 +#define MASK_FMV_D_X 0xfff0707f +#define MATCH_FMV_H_X 0xf4000053 +#define MASK_FMV_H_X 0xfff0707f +#define MATCH_FMV_W_X 0xf0000053 +#define MASK_FMV_W_X 0xfff0707f +#define MATCH_FMV_X_D 0xe2000053 +#define MASK_FMV_X_D 0xfff0707f +#define MATCH_FMV_X_H 0xe4000053 +#define MASK_FMV_X_H 0xfff0707f +#define MATCH_FMV_X_W 0xe0000053 +#define MASK_FMV_X_W 0xfff0707f +#define MATCH_FNMADD_D 0x200004f +#define MASK_FNMADD_D 0x600007f +#define MATCH_FNMADD_H 0x400004f +#define MASK_FNMADD_H 0x600007f +#define MATCH_FNMADD_Q 0x600004f +#define MASK_FNMADD_Q 0x600007f +#define MATCH_FNMADD_S 0x4f +#define MASK_FNMADD_S 0x600007f +#define MATCH_FNMSUB_D 0x200004b +#define MASK_FNMSUB_D 0x600007f +#define MATCH_FNMSUB_H 0x400004b +#define MASK_FNMSUB_H 0x600007f +#define MATCH_FNMSUB_Q 0x600004b +#define MASK_FNMSUB_Q 0x600007f +#define MATCH_FNMSUB_S 0x4b +#define MASK_FNMSUB_S 0x600007f +#define MATCH_FSD 0x3027 +#define MASK_FSD 0x707f +#define MATCH_FSGNJ_D 0x22000053 +#define MASK_FSGNJ_D 0xfe00707f +#define MATCH_FSGNJ_H 0x24000053 +#define MASK_FSGNJ_H 0xfe00707f +#define MATCH_FSGNJ_Q 0x26000053 +#define MASK_FSGNJ_Q 0xfe00707f +#define MATCH_FSGNJ_S 0x20000053 +#define MASK_FSGNJ_S 0xfe00707f +#define MATCH_FSGNJN_D 0x22001053 +#define MASK_FSGNJN_D 0xfe00707f +#define MATCH_FSGNJN_H 0x24001053 +#define MASK_FSGNJN_H 0xfe00707f +#define MATCH_FSGNJN_Q 0x26001053 +#define MASK_FSGNJN_Q 0xfe00707f +#define MATCH_FSGNJN_S 0x20001053 +#define MASK_FSGNJN_S 0xfe00707f +#define MATCH_FSGNJX_D 0x22002053 +#define MASK_FSGNJX_D 0xfe00707f +#define MATCH_FSGNJX_H 0x24002053 +#define MASK_FSGNJX_H 0xfe00707f +#define MATCH_FSGNJX_Q 0x26002053 +#define MASK_FSGNJX_Q 0xfe00707f +#define MATCH_FSGNJX_S 0x20002053 +#define MASK_FSGNJX_S 0xfe00707f +#define MATCH_FSH 0x1027 +#define MASK_FSH 0x707f +#define MATCH_FSL 0x4001033 +#define MASK_FSL 0x600707f +#define MATCH_FSLW 0x400103b +#define MASK_FSLW 0x600707f +#define MATCH_FSQ 0x4027 +#define MASK_FSQ 0x707f +#define MATCH_FSQRT_D 0x5a000053 +#define MASK_FSQRT_D 0xfff0007f +#define MATCH_FSQRT_H 0x5c000053 +#define MASK_FSQRT_H 0xfff0007f +#define MATCH_FSQRT_Q 0x5e000053 +#define MASK_FSQRT_Q 0xfff0007f +#define MATCH_FSQRT_S 0x58000053 +#define MASK_FSQRT_S 0xfff0007f +#define MATCH_FSR 0x4005033 +#define MASK_FSR 0x600707f +#define MATCH_FSRI 0x4005013 +#define MASK_FSRI 0x400707f +#define MATCH_FSRIW 0x400501b +#define MASK_FSRIW 0x600707f +#define MATCH_FSRW 0x400503b +#define MASK_FSRW 0x600707f +#define MATCH_FSUB_D 0xa000053 +#define MASK_FSUB_D 0xfe00007f +#define MATCH_FSUB_H 0xc000053 +#define MASK_FSUB_H 0xfe00007f +#define MATCH_FSUB_Q 0xe000053 +#define MASK_FSUB_Q 0xfe00007f +#define MATCH_FSUB_S 0x8000053 +#define MASK_FSUB_S 0xfe00007f +#define MATCH_FSW 0x2027 +#define MASK_FSW 0x707f +#define MATCH_GORC 0x28005033 +#define MASK_GORC 0xfe00707f +#define MATCH_GORCI 0x28005013 +#define MASK_GORCI 0xfc00707f +#define MATCH_GORCIW 0x2800501b +#define MASK_GORCIW 0xfe00707f +#define MATCH_GORCW 0x2800503b +#define MASK_GORCW 0xfe00707f +#define MATCH_GREV 0x68005033 +#define MASK_GREV 0xfe00707f +#define MATCH_GREVI 0x68005013 +#define MASK_GREVI 0xfc00707f +#define MATCH_GREVIW 0x6800501b +#define MASK_GREVIW 0xfe00707f +#define MATCH_GREVW 0x6800503b +#define MASK_GREVW 0xfe00707f +#define MATCH_HFENCE_GVMA 0x62000073 +#define MASK_HFENCE_GVMA 0xfe007fff +#define MATCH_HFENCE_VVMA 0x22000073 +#define MASK_HFENCE_VVMA 0xfe007fff +#define MATCH_HINVAL_GVMA 0x66000073 +#define MASK_HINVAL_GVMA 0xfe007fff +#define MATCH_HINVAL_VVMA 0x26000073 +#define MASK_HINVAL_VVMA 0xfe007fff +#define MATCH_HLV_B 0x60004073 +#define MASK_HLV_B 0xfff0707f +#define MATCH_HLV_BU 0x60104073 +#define MASK_HLV_BU 0xfff0707f +#define MATCH_HLV_D 0x6c004073 +#define MASK_HLV_D 0xfff0707f +#define MATCH_HLV_H 0x64004073 +#define MASK_HLV_H 0xfff0707f +#define MATCH_HLV_HU 0x64104073 +#define MASK_HLV_HU 0xfff0707f +#define MATCH_HLV_W 0x68004073 +#define MASK_HLV_W 0xfff0707f +#define MATCH_HLV_WU 0x68104073 +#define MASK_HLV_WU 0xfff0707f +#define MATCH_HLVX_HU 0x64304073 +#define MASK_HLVX_HU 0xfff0707f +#define MATCH_HLVX_WU 0x68304073 +#define MASK_HLVX_WU 0xfff0707f +#define MATCH_HSV_B 0x62004073 +#define MASK_HSV_B 0xfe007fff +#define MATCH_HSV_D 0x6e004073 +#define MASK_HSV_D 0xfe007fff +#define MATCH_HSV_H 0x66004073 +#define MASK_HSV_H 0xfe007fff +#define MATCH_HSV_W 0x6a004073 +#define MASK_HSV_W 0xfe007fff +#define MATCH_INSB 0xac000077 +#define MASK_INSB 0xff80707f +#define MATCH_JAL 0x6f +#define MASK_JAL 0x7f +#define MATCH_JALR 0x67 +#define MASK_JALR 0x707f +#define MATCH_KABS16 0xad100077 +#define MASK_KABS16 0xfff0707f +#define MATCH_KABS32 0xad200077 +#define MASK_KABS32 0xfff0707f +#define MATCH_KABS8 0xad000077 +#define MASK_KABS8 0xfff0707f +#define MATCH_KABSW 0xad400077 +#define MASK_KABSW 0xfff0707f +#define MATCH_KADD16 0x10000077 +#define MASK_KADD16 0xfe00707f +#define MATCH_KADD32 0x10002077 +#define MASK_KADD32 0xfe00707f +#define MATCH_KADD64 0x90001077 +#define MASK_KADD64 0xfe00707f +#define MATCH_KADD8 0x18000077 +#define MASK_KADD8 0xfe00707f +#define MATCH_KADDH 0x4001077 +#define MASK_KADDH 0xfe00707f +#define MATCH_KADDW 0x1077 +#define MASK_KADDW 0xfe00707f +#define MATCH_KCRAS16 0x14000077 +#define MASK_KCRAS16 0xfe00707f +#define MATCH_KCRAS32 0x14002077 +#define MASK_KCRAS32 0xfe00707f +#define MATCH_KCRSA16 0x16000077 +#define MASK_KCRSA16 0xfe00707f +#define MATCH_KCRSA32 0x16002077 +#define MASK_KCRSA32 0xfe00707f +#define MATCH_KDMABB 0xd2001077 +#define MASK_KDMABB 0xfe00707f +#define MATCH_KDMABB16 0xd8001077 +#define MASK_KDMABB16 0xfe00707f +#define MATCH_KDMABT 0xe2001077 +#define MASK_KDMABT 0xfe00707f +#define MATCH_KDMABT16 0xe8001077 +#define MASK_KDMABT16 0xfe00707f +#define MATCH_KDMATT 0xf2001077 +#define MASK_KDMATT 0xfe00707f +#define MATCH_KDMATT16 0xf8001077 +#define MASK_KDMATT16 0xfe00707f +#define MATCH_KDMBB 0xa001077 +#define MASK_KDMBB 0xfe00707f +#define MATCH_KDMBB16 0xda001077 +#define MASK_KDMBB16 0xfe00707f +#define MATCH_KDMBT 0x1a001077 +#define MASK_KDMBT 0xfe00707f +#define MATCH_KDMBT16 0xea001077 +#define MASK_KDMBT16 0xfe00707f +#define MATCH_KDMTT 0x2a001077 +#define MASK_KDMTT 0xfe00707f +#define MATCH_KDMTT16 0xfa001077 +#define MASK_KDMTT16 0xfe00707f +#define MATCH_KHM16 0x86000077 +#define MASK_KHM16 0xfe00707f +#define MATCH_KHM8 0x8e000077 +#define MASK_KHM8 0xfe00707f +#define MATCH_KHMBB 0xc001077 +#define MASK_KHMBB 0xfe00707f +#define MATCH_KHMBB16 0xdc001077 +#define MASK_KHMBB16 0xfe00707f +#define MATCH_KHMBT 0x1c001077 +#define MASK_KHMBT 0xfe00707f +#define MATCH_KHMBT16 0xec001077 +#define MASK_KHMBT16 0xfe00707f +#define MATCH_KHMTT 0x2c001077 +#define MASK_KHMTT 0xfe00707f +#define MATCH_KHMTT16 0xfc001077 +#define MASK_KHMTT16 0xfe00707f +#define MATCH_KHMX16 0x96000077 +#define MASK_KHMX16 0xfe00707f +#define MATCH_KHMX8 0x9e000077 +#define MASK_KHMX8 0xfe00707f +#define MATCH_KMABB 0x5a001077 +#define MASK_KMABB 0xfe00707f +#define MATCH_KMABB32 0x5a002077 +#define MASK_KMABB32 0xfe00707f +#define MATCH_KMABT 0x6a001077 +#define MASK_KMABT 0xfe00707f +#define MATCH_KMABT32 0x6a002077 +#define MASK_KMABT32 0xfe00707f +#define MATCH_KMADA 0x48001077 +#define MASK_KMADA 0xfe00707f +#define MATCH_KMADRS 0x6c001077 +#define MASK_KMADRS 0xfe00707f +#define MATCH_KMADRS32 0x6c002077 +#define MASK_KMADRS32 0xfe00707f +#define MATCH_KMADS 0x5c001077 +#define MASK_KMADS 0xfe00707f +#define MATCH_KMADS32 0x5c002077 +#define MASK_KMADS32 0xfe00707f +#define MATCH_KMAR64 0x94001077 +#define MASK_KMAR64 0xfe00707f +#define MATCH_KMATT 0x7a001077 +#define MASK_KMATT 0xfe00707f +#define MATCH_KMATT32 0x7a002077 +#define MASK_KMATT32 0xfe00707f +#define MATCH_KMAXDA 0x4a001077 +#define MASK_KMAXDA 0xfe00707f +#define MATCH_KMAXDA32 0x4a002077 +#define MASK_KMAXDA32 0xfe00707f +#define MATCH_KMAXDS 0x7c001077 +#define MASK_KMAXDS 0xfe00707f +#define MATCH_KMAXDS32 0x7c002077 +#define MASK_KMAXDS32 0xfe00707f +#define MATCH_KMDA 0x38001077 +#define MASK_KMDA 0xfe00707f +#define MATCH_KMDA32 0x38002077 +#define MASK_KMDA32 0xfe00707f +#define MATCH_KMMAC 0x60001077 +#define MASK_KMMAC 0xfe00707f +#define MATCH_KMMAC_U 0x70001077 +#define MASK_KMMAC_U 0xfe00707f +#define MATCH_KMMAWB 0x46001077 +#define MASK_KMMAWB 0xfe00707f +#define MATCH_KMMAWB2 0xce001077 +#define MASK_KMMAWB2 0xfe00707f +#define MATCH_KMMAWB2_U 0xde001077 +#define MASK_KMMAWB2_U 0xfe00707f +#define MATCH_KMMAWB_U 0x56001077 +#define MASK_KMMAWB_U 0xfe00707f +#define MATCH_KMMAWT 0x66001077 +#define MASK_KMMAWT 0xfe00707f +#define MATCH_KMMAWT2 0xee001077 +#define MASK_KMMAWT2 0xfe00707f +#define MATCH_KMMAWT2_U 0xfe001077 +#define MASK_KMMAWT2_U 0xfe00707f +#define MATCH_KMMAWT_U 0x76001077 +#define MASK_KMMAWT_U 0xfe00707f +#define MATCH_KMMSB 0x42001077 +#define MASK_KMMSB 0xfe00707f +#define MATCH_KMMSB_U 0x52001077 +#define MASK_KMMSB_U 0xfe00707f +#define MATCH_KMMWB2 0x8e001077 +#define MASK_KMMWB2 0xfe00707f +#define MATCH_KMMWB2_U 0x9e001077 +#define MASK_KMMWB2_U 0xfe00707f +#define MATCH_KMMWT2 0xae001077 +#define MASK_KMMWT2 0xfe00707f +#define MATCH_KMMWT2_U 0xbe001077 +#define MASK_KMMWT2_U 0xfe00707f +#define MATCH_KMSDA 0x4c001077 +#define MASK_KMSDA 0xfe00707f +#define MATCH_KMSDA32 0x4c002077 +#define MASK_KMSDA32 0xfe00707f +#define MATCH_KMSR64 0x96001077 +#define MASK_KMSR64 0xfe00707f +#define MATCH_KMSXDA 0x4e001077 +#define MASK_KMSXDA 0xfe00707f +#define MATCH_KMSXDA32 0x4e002077 +#define MASK_KMSXDA32 0xfe00707f +#define MATCH_KMXDA 0x3a001077 +#define MASK_KMXDA 0xfe00707f +#define MATCH_KMXDA32 0x3a002077 +#define MASK_KMXDA32 0xfe00707f +#define MATCH_KSLL16 0x64000077 +#define MASK_KSLL16 0xfe00707f +#define MATCH_KSLL32 0x64002077 +#define MASK_KSLL32 0xfe00707f +#define MATCH_KSLL8 0x6c000077 +#define MASK_KSLL8 0xfe00707f +#define MATCH_KSLLI16 0x75000077 +#define MASK_KSLLI16 0xff00707f +#define MATCH_KSLLI32 0x84002077 +#define MASK_KSLLI32 0xfe00707f +#define MATCH_KSLLI8 0x7c800077 +#define MASK_KSLLI8 0xff80707f +#define MATCH_KSLLIW 0x36001077 +#define MASK_KSLLIW 0xfe00707f +#define MATCH_KSLLW 0x26001077 +#define MASK_KSLLW 0xfe00707f +#define MATCH_KSLRA16 0x56000077 +#define MASK_KSLRA16 0xfe00707f +#define MATCH_KSLRA16_U 0x66000077 +#define MASK_KSLRA16_U 0xfe00707f +#define MATCH_KSLRA32 0x56002077 +#define MASK_KSLRA32 0xfe00707f +#define MATCH_KSLRA32_U 0x66002077 +#define MASK_KSLRA32_U 0xfe00707f +#define MATCH_KSLRA8 0x5e000077 +#define MASK_KSLRA8 0xfe00707f +#define MATCH_KSLRA8_U 0x6e000077 +#define MASK_KSLRA8_U 0xfe00707f +#define MATCH_KSLRAW 0x6e001077 +#define MASK_KSLRAW 0xfe00707f +#define MATCH_KSLRAW_U 0x7e001077 +#define MASK_KSLRAW_U 0xfe00707f +#define MATCH_KSTAS16 0xc4002077 +#define MASK_KSTAS16 0xfe00707f +#define MATCH_KSTAS32 0xc0002077 +#define MASK_KSTAS32 0xfe00707f +#define MATCH_KSTSA16 0xc6002077 +#define MASK_KSTSA16 0xfe00707f +#define MATCH_KSTSA32 0xc2002077 +#define MASK_KSTSA32 0xfe00707f +#define MATCH_KSUB16 0x12000077 +#define MASK_KSUB16 0xfe00707f +#define MATCH_KSUB32 0x12002077 +#define MASK_KSUB32 0xfe00707f +#define MATCH_KSUB64 0x92001077 +#define MASK_KSUB64 0xfe00707f +#define MATCH_KSUB8 0x1a000077 +#define MASK_KSUB8 0xfe00707f +#define MATCH_KSUBH 0x6001077 +#define MASK_KSUBH 0xfe00707f +#define MATCH_KSUBW 0x2001077 +#define MASK_KSUBW 0xfe00707f +#define MATCH_KWMMUL 0x62001077 +#define MASK_KWMMUL 0xfe00707f +#define MATCH_KWMMUL_U 0x72001077 +#define MASK_KWMMUL_U 0xfe00707f +#define MATCH_LB 0x3 +#define MASK_LB 0x707f +#define MATCH_LBU 0x4003 +#define MASK_LBU 0x707f +#define MATCH_LD 0x3003 +#define MASK_LD 0x707f +#define MATCH_LDU 0x7003 +#define MASK_LDU 0x707f +#define MATCH_LH 0x1003 +#define MASK_LH 0x707f +#define MATCH_LHU 0x5003 +#define MASK_LHU 0x707f +#define MATCH_LQ 0x300f +#define MASK_LQ 0x707f +#define MATCH_LR_D 0x1000302f +#define MASK_LR_D 0xf9f0707f +#define MATCH_LR_W 0x1000202f +#define MASK_LR_W 0xf9f0707f +#define MATCH_LUI 0x37 +#define MASK_LUI 0x7f +#define MATCH_LW 0x2003 +#define MASK_LW 0x707f +#define MATCH_LWU 0x6003 +#define MASK_LWU 0x707f +#define MATCH_MADDR32 0xc4001077 +#define MASK_MADDR32 0xfe00707f +#define MATCH_MAX 0xa006033 +#define MASK_MAX 0xfe00707f +#define MATCH_MAXU 0xa007033 +#define MASK_MAXU 0xfe00707f +#define MATCH_MAXW 0xf2000077 +#define MASK_MAXW 0xfe00707f +#define MATCH_MIN 0xa004033 +#define MASK_MIN 0xfe00707f +#define MATCH_MINU 0xa005033 +#define MASK_MINU 0xfe00707f +#define MATCH_MINW 0xf0000077 +#define MASK_MINW 0xfe00707f +#define MATCH_MRET 0x30200073 +#define MASK_MRET 0xffffffff +#define MATCH_MSUBR32 0xc6001077 +#define MASK_MSUBR32 0xfe00707f +#define MATCH_MUL 0x2000033 +#define MASK_MUL 0xfe00707f +#define MATCH_MULH 0x2001033 +#define MASK_MULH 0xfe00707f +#define MATCH_MULHSU 0x2002033 +#define MASK_MULHSU 0xfe00707f +#define MATCH_MULHU 0x2003033 +#define MASK_MULHU 0xfe00707f +#define MATCH_MULR64 0xf0001077 +#define MASK_MULR64 0xfe00707f +#define MATCH_MULSR64 0xe0001077 +#define MASK_MULSR64 0xfe00707f +#define MATCH_MULW 0x200003b +#define MASK_MULW 0xfe00707f +#define MATCH_OR 0x6033 +#define MASK_OR 0xfe00707f +#define MATCH_ORI 0x6013 +#define MASK_ORI 0x707f +#define MATCH_ORN 0x40006033 +#define MASK_ORN 0xfe00707f +#define MATCH_PACK 0x8004033 +#define MASK_PACK 0xfe00707f +#define MATCH_PACKH 0x8007033 +#define MASK_PACKH 0xfe00707f +#define MATCH_PACKU 0x48004033 +#define MASK_PACKU 0xfe00707f +#define MATCH_PACKUW 0x4800403b +#define MASK_PACKUW 0xfe00707f +#define MATCH_PACKW 0x800403b +#define MASK_PACKW 0xfe00707f +#define MATCH_PAUSE 0x100000f +#define MASK_PAUSE 0xffffffff +#define MATCH_PBSAD 0xfc000077 +#define MASK_PBSAD 0xfe00707f +#define MATCH_PBSADA 0xfe000077 +#define MASK_PBSADA 0xfe00707f +#define MATCH_PKBB16 0xe001077 +#define MASK_PKBB16 0xfe00707f +#define MATCH_PKBB32 0xe002077 +#define MASK_PKBB32 0xfe00707f +#define MATCH_PKBT16 0x1e001077 +#define MASK_PKBT16 0xfe00707f +#define MATCH_PKBT32 0x1e002077 +#define MASK_PKBT32 0xfe00707f +#define MATCH_PKTB16 0x3e001077 +#define MASK_PKTB16 0xfe00707f +#define MATCH_PKTB32 0x3e002077 +#define MASK_PKTB32 0xfe00707f +#define MATCH_PKTT16 0x2e001077 +#define MASK_PKTT16 0xfe00707f +#define MATCH_PKTT32 0x2e002077 +#define MASK_PKTT32 0xfe00707f +#define MATCH_PREFETCH_I 0x6013 +#define MASK_PREFETCH_I 0x1f07fff +#define MATCH_PREFETCH_R 0x106013 +#define MASK_PREFETCH_R 0x1f07fff +#define MATCH_PREFETCH_W 0x306013 +#define MASK_PREFETCH_W 0x1f07fff +#define MATCH_RADD16 0x77 +#define MASK_RADD16 0xfe00707f +#define MATCH_RADD32 0x2077 +#define MASK_RADD32 0xfe00707f +#define MATCH_RADD64 0x80001077 +#define MASK_RADD64 0xfe00707f +#define MATCH_RADD8 0x8000077 +#define MASK_RADD8 0xfe00707f +#define MATCH_RADDW 0x20001077 +#define MASK_RADDW 0xfe00707f +#define MATCH_RCRAS16 0x4000077 +#define MASK_RCRAS16 0xfe00707f +#define MATCH_RCRAS32 0x4002077 +#define MASK_RCRAS32 0xfe00707f +#define MATCH_RCRSA16 0x6000077 +#define MASK_RCRSA16 0xfe00707f +#define MATCH_RCRSA32 0x6002077 +#define MASK_RCRSA32 0xfe00707f +#define MATCH_REM 0x2006033 +#define MASK_REM 0xfe00707f +#define MATCH_REMU 0x2007033 +#define MASK_REMU 0xfe00707f +#define MATCH_REMUW 0x200703b +#define MASK_REMUW 0xfe00707f +#define MATCH_REMW 0x200603b +#define MASK_REMW 0xfe00707f +#define MATCH_ROL 0x60001033 +#define MASK_ROL 0xfe00707f +#define MATCH_ROLW 0x6000103b +#define MASK_ROLW 0xfe00707f +#define MATCH_ROR 0x60005033 +#define MASK_ROR 0xfe00707f +#define MATCH_RORI 0x60005013 +#define MASK_RORI 0xfc00707f +#define MATCH_RORIW 0x6000501b +#define MASK_RORIW 0xfe00707f +#define MATCH_RORW 0x6000503b +#define MASK_RORW 0xfe00707f +#define MATCH_RSTAS16 0xb4002077 +#define MASK_RSTAS16 0xfe00707f +#define MATCH_RSTAS32 0xb0002077 +#define MASK_RSTAS32 0xfe00707f +#define MATCH_RSTSA16 0xb6002077 +#define MASK_RSTSA16 0xfe00707f +#define MATCH_RSTSA32 0xb2002077 +#define MASK_RSTSA32 0xfe00707f +#define MATCH_RSUB16 0x2000077 +#define MASK_RSUB16 0xfe00707f +#define MATCH_RSUB32 0x2002077 +#define MASK_RSUB32 0xfe00707f +#define MATCH_RSUB64 0x82001077 +#define MASK_RSUB64 0xfe00707f +#define MATCH_RSUB8 0xa000077 +#define MASK_RSUB8 0xfe00707f +#define MATCH_RSUBW 0x22001077 +#define MASK_RSUBW 0xfe00707f +#define MATCH_SB 0x23 +#define MASK_SB 0x707f +#define MATCH_SC_D 0x1800302f +#define MASK_SC_D 0xf800707f +#define MATCH_SC_W 0x1800202f +#define MASK_SC_W 0xf800707f +#define MATCH_SCLIP16 0x84000077 +#define MASK_SCLIP16 0xff00707f +#define MATCH_SCLIP32 0xe4000077 +#define MASK_SCLIP32 0xfe00707f +#define MATCH_SCLIP8 0x8c000077 +#define MASK_SCLIP8 0xff80707f +#define MATCH_SCMPLE16 0x1c000077 +#define MASK_SCMPLE16 0xfe00707f +#define MATCH_SCMPLE8 0x1e000077 +#define MASK_SCMPLE8 0xfe00707f +#define MATCH_SCMPLT16 0xc000077 +#define MASK_SCMPLT16 0xfe00707f +#define MATCH_SCMPLT8 0xe000077 +#define MASK_SCMPLT8 0xfe00707f +#define MATCH_SD 0x3023 +#define MASK_SD 0x707f +#define MATCH_SEXT_B 0x60401013 +#define MASK_SEXT_B 0xfff0707f +#define MATCH_SEXT_H 0x60501013 +#define MASK_SEXT_H 0xfff0707f +#define MATCH_SFENCE_INVAL_IR 0x18100073 +#define MASK_SFENCE_INVAL_IR 0xffffffff +#define MATCH_SFENCE_VMA 0x12000073 +#define MASK_SFENCE_VMA 0xfe007fff +#define MATCH_SFENCE_W_INVAL 0x18000073 +#define MASK_SFENCE_W_INVAL 0xffffffff +#define MATCH_SH 0x1023 +#define MASK_SH 0x707f +#define MATCH_SH1ADD 0x20002033 +#define MASK_SH1ADD 0xfe00707f +#define MATCH_SH1ADD_UW 0x2000203b +#define MASK_SH1ADD_UW 0xfe00707f +#define MATCH_SH2ADD 0x20004033 +#define MASK_SH2ADD 0xfe00707f +#define MATCH_SH2ADD_UW 0x2000403b +#define MASK_SH2ADD_UW 0xfe00707f +#define MATCH_SH3ADD 0x20006033 +#define MASK_SH3ADD 0xfe00707f +#define MATCH_SH3ADD_UW 0x2000603b +#define MASK_SH3ADD_UW 0xfe00707f +#define MATCH_SHA256SIG0 0x10201013 +#define MASK_SHA256SIG0 0xfff0707f +#define MATCH_SHA256SIG1 0x10301013 +#define MASK_SHA256SIG1 0xfff0707f +#define MATCH_SHA256SUM0 0x10001013 +#define MASK_SHA256SUM0 0xfff0707f +#define MATCH_SHA256SUM1 0x10101013 +#define MASK_SHA256SUM1 0xfff0707f +#define MATCH_SHA512SIG0 0x10601013 +#define MASK_SHA512SIG0 0xfff0707f +#define MATCH_SHA512SIG0H 0x5c000033 +#define MASK_SHA512SIG0H 0xfe00707f +#define MATCH_SHA512SIG0L 0x54000033 +#define MASK_SHA512SIG0L 0xfe00707f +#define MATCH_SHA512SIG1 0x10701013 +#define MASK_SHA512SIG1 0xfff0707f +#define MATCH_SHA512SIG1H 0x5e000033 +#define MASK_SHA512SIG1H 0xfe00707f +#define MATCH_SHA512SIG1L 0x56000033 +#define MASK_SHA512SIG1L 0xfe00707f +#define MATCH_SHA512SUM0 0x10401013 +#define MASK_SHA512SUM0 0xfff0707f +#define MATCH_SHA512SUM0R 0x50000033 +#define MASK_SHA512SUM0R 0xfe00707f +#define MATCH_SHA512SUM1 0x10501013 +#define MASK_SHA512SUM1 0xfff0707f +#define MATCH_SHA512SUM1R 0x52000033 +#define MASK_SHA512SUM1R 0xfe00707f +#define MATCH_SHFL 0x8001033 +#define MASK_SHFL 0xfe00707f +#define MATCH_SHFLI 0x8001013 +#define MASK_SHFLI 0xfe00707f +#define MATCH_SHFLW 0x800103b +#define MASK_SHFLW 0xfe00707f +#define MATCH_SINVAL_VMA 0x16000073 +#define MASK_SINVAL_VMA 0xfe007fff +#define MATCH_SLL 0x1033 +#define MASK_SLL 0xfe00707f +#define MATCH_SLL16 0x54000077 +#define MASK_SLL16 0xfe00707f +#define MATCH_SLL32 0x54002077 +#define MASK_SLL32 0xfe00707f +#define MATCH_SLL8 0x5c000077 +#define MASK_SLL8 0xfe00707f +#define MATCH_SLLD 0x107b +#define MASK_SLLD 0xfe00707f +#define MATCH_SLLI 0x1013 +#define MASK_SLLI 0xf800707f +#define MATCH_SLLI16 0x74000077 +#define MASK_SLLI16 0xff00707f +#define MATCH_SLLI32 0x74002077 +#define MASK_SLLI32 0xfe00707f +#define MATCH_SLLI8 0x7c000077 +#define MASK_SLLI8 0xff80707f +#define MATCH_SLLI_UW 0x800101b +#define MASK_SLLI_UW 0xfc00707f +#define MATCH_SLLID 0x105b +#define MASK_SLLID 0xfc00707f +#define MATCH_SLLIW 0x101b +#define MASK_SLLIW 0xfe00707f +#define MATCH_SLLW 0x103b +#define MASK_SLLW 0xfe00707f +#define MATCH_SLO 0x20001033 +#define MASK_SLO 0xfe00707f +#define MATCH_SLOI 0x20001013 +#define MASK_SLOI 0xfc00707f +#define MATCH_SLOIW 0x2000101b +#define MASK_SLOIW 0xfe00707f +#define MATCH_SLOW 0x2000103b +#define MASK_SLOW 0xfe00707f +#define MATCH_SLT 0x2033 +#define MASK_SLT 0xfe00707f +#define MATCH_SLTI 0x2013 +#define MASK_SLTI 0x707f +#define MATCH_SLTIU 0x3013 +#define MASK_SLTIU 0x707f +#define MATCH_SLTU 0x3033 +#define MASK_SLTU 0xfe00707f +#define MATCH_SM3P0 0x10801013 +#define MASK_SM3P0 0xfff0707f +#define MATCH_SM3P1 0x10901013 +#define MASK_SM3P1 0xfff0707f +#define MATCH_SM4ED 0x30000033 +#define MASK_SM4ED 0x3e00707f +#define MATCH_SM4KS 0x34000033 +#define MASK_SM4KS 0x3e00707f +#define MATCH_SMAL 0x5e001077 +#define MASK_SMAL 0xfe00707f +#define MATCH_SMALBB 0x88001077 +#define MASK_SMALBB 0xfe00707f +#define MATCH_SMALBT 0x98001077 +#define MASK_SMALBT 0xfe00707f +#define MATCH_SMALDA 0x8c001077 +#define MASK_SMALDA 0xfe00707f +#define MATCH_SMALDRS 0x9a001077 +#define MASK_SMALDRS 0xfe00707f +#define MATCH_SMALDS 0x8a001077 +#define MASK_SMALDS 0xfe00707f +#define MATCH_SMALTT 0xa8001077 +#define MASK_SMALTT 0xfe00707f +#define MATCH_SMALXDA 0x9c001077 +#define MASK_SMALXDA 0xfe00707f +#define MATCH_SMALXDS 0xaa001077 +#define MASK_SMALXDS 0xfe00707f +#define MATCH_SMAQA 0xc8000077 +#define MASK_SMAQA 0xfe00707f +#define MATCH_SMAQA_SU 0xca000077 +#define MASK_SMAQA_SU 0xfe00707f +#define MATCH_SMAR64 0x84001077 +#define MASK_SMAR64 0xfe00707f +#define MATCH_SMAX16 0x82000077 +#define MASK_SMAX16 0xfe00707f +#define MATCH_SMAX32 0x92002077 +#define MASK_SMAX32 0xfe00707f +#define MATCH_SMAX8 0x8a000077 +#define MASK_SMAX8 0xfe00707f +#define MATCH_SMBB16 0x8001077 +#define MASK_SMBB16 0xfe00707f +#define MATCH_SMBT16 0x18001077 +#define MASK_SMBT16 0xfe00707f +#define MATCH_SMBT32 0x18002077 +#define MASK_SMBT32 0xfe00707f +#define MATCH_SMDRS 0x68001077 +#define MASK_SMDRS 0xfe00707f +#define MATCH_SMDRS32 0x68002077 +#define MASK_SMDRS32 0xfe00707f +#define MATCH_SMDS 0x58001077 +#define MASK_SMDS 0xfe00707f +#define MATCH_SMDS32 0x58002077 +#define MASK_SMDS32 0xfe00707f +#define MATCH_SMIN16 0x80000077 +#define MASK_SMIN16 0xfe00707f +#define MATCH_SMIN32 0x90002077 +#define MASK_SMIN32 0xfe00707f +#define MATCH_SMIN8 0x88000077 +#define MASK_SMIN8 0xfe00707f +#define MATCH_SMMUL 0x40001077 +#define MASK_SMMUL 0xfe00707f +#define MATCH_SMMUL_U 0x50001077 +#define MASK_SMMUL_U 0xfe00707f +#define MATCH_SMMWB 0x44001077 +#define MASK_SMMWB 0xfe00707f +#define MATCH_SMMWB_U 0x54001077 +#define MASK_SMMWB_U 0xfe00707f +#define MATCH_SMMWT 0x64001077 +#define MASK_SMMWT 0xfe00707f +#define MATCH_SMMWT_U 0x74001077 +#define MASK_SMMWT_U 0xfe00707f +#define MATCH_SMSLDA 0xac001077 +#define MASK_SMSLDA 0xfe00707f +#define MATCH_SMSLXDA 0xbc001077 +#define MASK_SMSLXDA 0xfe00707f +#define MATCH_SMSR64 0x86001077 +#define MASK_SMSR64 0xfe00707f +#define MATCH_SMTT16 0x28001077 +#define MASK_SMTT16 0xfe00707f +#define MATCH_SMTT32 0x28002077 +#define MASK_SMTT32 0xfe00707f +#define MATCH_SMUL16 0xa0000077 +#define MASK_SMUL16 0xfe00707f +#define MATCH_SMUL8 0xa8000077 +#define MASK_SMUL8 0xfe00707f +#define MATCH_SMULX16 0xa2000077 +#define MASK_SMULX16 0xfe00707f +#define MATCH_SMULX8 0xaa000077 +#define MASK_SMULX8 0xfe00707f +#define MATCH_SMXDS 0x78001077 +#define MASK_SMXDS 0xfe00707f +#define MATCH_SMXDS32 0x78002077 +#define MASK_SMXDS32 0xfe00707f +#define MATCH_SQ 0x4023 +#define MASK_SQ 0x707f +#define MATCH_SRA 0x40005033 +#define MASK_SRA 0xfe00707f +#define MATCH_SRA16 0x50000077 +#define MASK_SRA16 0xfe00707f +#define MATCH_SRA16_U 0x60000077 +#define MASK_SRA16_U 0xfe00707f +#define MATCH_SRA32 0x50002077 +#define MASK_SRA32 0xfe00707f +#define MATCH_SRA32_U 0x60002077 +#define MASK_SRA32_U 0xfe00707f +#define MATCH_SRA8 0x58000077 +#define MASK_SRA8 0xfe00707f +#define MATCH_SRA8_U 0x68000077 +#define MASK_SRA8_U 0xfe00707f +#define MATCH_SRA_U 0x24001077 +#define MASK_SRA_U 0xfe00707f +#define MATCH_SRAD 0x4000507b +#define MASK_SRAD 0xfe00707f +#define MATCH_SRAI 0x40005013 +#define MASK_SRAI 0xf800707f +#define MATCH_SRAI16 0x70000077 +#define MASK_SRAI16 0xff00707f +#define MATCH_SRAI16_U 0x71000077 +#define MASK_SRAI16_U 0xff00707f +#define MATCH_SRAI32 0x70002077 +#define MASK_SRAI32 0xfe00707f +#define MATCH_SRAI32_U 0x80002077 +#define MASK_SRAI32_U 0xfe00707f +#define MATCH_SRAI8 0x78000077 +#define MASK_SRAI8 0xff80707f +#define MATCH_SRAI8_U 0x78800077 +#define MASK_SRAI8_U 0xff80707f +#define MATCH_SRAI_U 0xd4001077 +#define MASK_SRAI_U 0xfc00707f +#define MATCH_SRAID 0x4000505b +#define MASK_SRAID 0xfc00707f +#define MATCH_SRAIW 0x4000501b +#define MASK_SRAIW 0xfe00707f +#define MATCH_SRAIW_U 0x34001077 +#define MASK_SRAIW_U 0xfe00707f +#define MATCH_SRAW 0x4000503b +#define MASK_SRAW 0xfe00707f +#define MATCH_SRET 0x10200073 +#define MASK_SRET 0xffffffff +#define MATCH_SRL 0x5033 +#define MASK_SRL 0xfe00707f +#define MATCH_SRL16 0x52000077 +#define MASK_SRL16 0xfe00707f +#define MATCH_SRL16_U 0x62000077 +#define MASK_SRL16_U 0xfe00707f +#define MATCH_SRL32 0x52002077 +#define MASK_SRL32 0xfe00707f +#define MATCH_SRL32_U 0x62002077 +#define MASK_SRL32_U 0xfe00707f +#define MATCH_SRL8 0x5a000077 +#define MASK_SRL8 0xfe00707f +#define MATCH_SRL8_U 0x6a000077 +#define MASK_SRL8_U 0xfe00707f +#define MATCH_SRLD 0x507b +#define MASK_SRLD 0xfe00707f +#define MATCH_SRLI 0x5013 +#define MASK_SRLI 0xf800707f +#define MATCH_SRLI16 0x72000077 +#define MASK_SRLI16 0xff00707f +#define MATCH_SRLI16_U 0x73000077 +#define MASK_SRLI16_U 0xff00707f +#define MATCH_SRLI32 0x72002077 +#define MASK_SRLI32 0xfe00707f +#define MATCH_SRLI32_U 0x82002077 +#define MASK_SRLI32_U 0xfe00707f +#define MATCH_SRLI8 0x7a000077 +#define MASK_SRLI8 0xff80707f +#define MATCH_SRLI8_U 0x7a800077 +#define MASK_SRLI8_U 0xff80707f +#define MATCH_SRLID 0x505b +#define MASK_SRLID 0xfc00707f +#define MATCH_SRLIW 0x501b +#define MASK_SRLIW 0xfe00707f +#define MATCH_SRLW 0x503b +#define MASK_SRLW 0xfe00707f +#define MATCH_SRO 0x20005033 +#define MASK_SRO 0xfe00707f +#define MATCH_SROI 0x20005013 +#define MASK_SROI 0xfc00707f +#define MATCH_SROIW 0x2000501b +#define MASK_SROIW 0xfe00707f +#define MATCH_SROW 0x2000503b +#define MASK_SROW 0xfe00707f +#define MATCH_STAS16 0xf4002077 +#define MASK_STAS16 0xfe00707f +#define MATCH_STAS32 0xf0002077 +#define MASK_STAS32 0xfe00707f +#define MATCH_STSA16 0xf6002077 +#define MASK_STSA16 0xfe00707f +#define MATCH_STSA32 0xf2002077 +#define MASK_STSA32 0xfe00707f +#define MATCH_SUB 0x40000033 +#define MASK_SUB 0xfe00707f +#define MATCH_SUB16 0x42000077 +#define MASK_SUB16 0xfe00707f +#define MATCH_SUB32 0x42002077 +#define MASK_SUB32 0xfe00707f +#define MATCH_SUB64 0xc2001077 +#define MASK_SUB64 0xfe00707f +#define MATCH_SUB8 0x4a000077 +#define MASK_SUB8 0xfe00707f +#define MATCH_SUBD 0x4000007b +#define MASK_SUBD 0xfe00707f +#define MATCH_SUBW 0x4000003b +#define MASK_SUBW 0xfe00707f +#define MATCH_SUNPKD810 0xac800077 +#define MASK_SUNPKD810 0xfff0707f +#define MATCH_SUNPKD820 0xac900077 +#define MASK_SUNPKD820 0xfff0707f +#define MATCH_SUNPKD830 0xaca00077 +#define MASK_SUNPKD830 0xfff0707f +#define MATCH_SUNPKD831 0xacb00077 +#define MASK_SUNPKD831 0xfff0707f +#define MATCH_SUNPKD832 0xad300077 +#define MASK_SUNPKD832 0xfff0707f +#define MATCH_SW 0x2023 +#define MASK_SW 0x707f +#define MATCH_SWAP8 0xad800077 +#define MASK_SWAP8 0xfff0707f +#define MATCH_UCLIP16 0x85000077 +#define MASK_UCLIP16 0xff00707f +#define MATCH_UCLIP32 0xf4000077 +#define MASK_UCLIP32 0xfe00707f +#define MATCH_UCLIP8 0x8d000077 +#define MASK_UCLIP8 0xff80707f +#define MATCH_UCMPLE16 0x3c000077 +#define MASK_UCMPLE16 0xfe00707f +#define MATCH_UCMPLE8 0x3e000077 +#define MASK_UCMPLE8 0xfe00707f +#define MATCH_UCMPLT16 0x2c000077 +#define MASK_UCMPLT16 0xfe00707f +#define MATCH_UCMPLT8 0x2e000077 +#define MASK_UCMPLT8 0xfe00707f +#define MATCH_UKADD16 0x30000077 +#define MASK_UKADD16 0xfe00707f +#define MATCH_UKADD32 0x30002077 +#define MASK_UKADD32 0xfe00707f +#define MATCH_UKADD64 0xb0001077 +#define MASK_UKADD64 0xfe00707f +#define MATCH_UKADD8 0x38000077 +#define MASK_UKADD8 0xfe00707f +#define MATCH_UKADDH 0x14001077 +#define MASK_UKADDH 0xfe00707f +#define MATCH_UKADDW 0x10001077 +#define MASK_UKADDW 0xfe00707f +#define MATCH_UKCRAS16 0x34000077 +#define MASK_UKCRAS16 0xfe00707f +#define MATCH_UKCRAS32 0x34002077 +#define MASK_UKCRAS32 0xfe00707f +#define MATCH_UKCRSA16 0x36000077 +#define MASK_UKCRSA16 0xfe00707f +#define MATCH_UKCRSA32 0x36002077 +#define MASK_UKCRSA32 0xfe00707f +#define MATCH_UKMAR64 0xb4001077 +#define MASK_UKMAR64 0xfe00707f +#define MATCH_UKMSR64 0xb6001077 +#define MASK_UKMSR64 0xfe00707f +#define MATCH_UKSTAS16 0xe4002077 +#define MASK_UKSTAS16 0xfe00707f +#define MATCH_UKSTAS32 0xe0002077 +#define MASK_UKSTAS32 0xfe00707f +#define MATCH_UKSTSA16 0xe6002077 +#define MASK_UKSTSA16 0xfe00707f +#define MATCH_UKSTSA32 0xe2002077 +#define MASK_UKSTSA32 0xfe00707f +#define MATCH_UKSUB16 0x32000077 +#define MASK_UKSUB16 0xfe00707f +#define MATCH_UKSUB32 0x32002077 +#define MASK_UKSUB32 0xfe00707f +#define MATCH_UKSUB64 0xb2001077 +#define MASK_UKSUB64 0xfe00707f +#define MATCH_UKSUB8 0x3a000077 +#define MASK_UKSUB8 0xfe00707f +#define MATCH_UKSUBH 0x16001077 +#define MASK_UKSUBH 0xfe00707f +#define MATCH_UKSUBW 0x12001077 +#define MASK_UKSUBW 0xfe00707f +#define MATCH_UMAQA 0xcc000077 +#define MASK_UMAQA 0xfe00707f +#define MATCH_UMAR64 0xa4001077 +#define MASK_UMAR64 0xfe00707f +#define MATCH_UMAX16 0x92000077 +#define MASK_UMAX16 0xfe00707f +#define MATCH_UMAX32 0xa2002077 +#define MASK_UMAX32 0xfe00707f +#define MATCH_UMAX8 0x9a000077 +#define MASK_UMAX8 0xfe00707f +#define MATCH_UMIN16 0x90000077 +#define MASK_UMIN16 0xfe00707f +#define MATCH_UMIN32 0xa0002077 +#define MASK_UMIN32 0xfe00707f +#define MATCH_UMIN8 0x98000077 +#define MASK_UMIN8 0xfe00707f +#define MATCH_UMSR64 0xa6001077 +#define MASK_UMSR64 0xfe00707f +#define MATCH_UMUL16 0xb0000077 +#define MASK_UMUL16 0xfe00707f +#define MATCH_UMUL8 0xb8000077 +#define MASK_UMUL8 0xfe00707f +#define MATCH_UMULX16 0xb2000077 +#define MASK_UMULX16 0xfe00707f +#define MATCH_UMULX8 0xba000077 +#define MASK_UMULX8 0xfe00707f +#define MATCH_UNSHFL 0x8005033 +#define MASK_UNSHFL 0xfe00707f +#define MATCH_UNSHFLI 0x8005013 +#define MASK_UNSHFLI 0xfe00707f +#define MATCH_UNSHFLW 0x800503b +#define MASK_UNSHFLW 0xfe00707f +#define MATCH_URADD16 0x20000077 +#define MASK_URADD16 0xfe00707f +#define MATCH_URADD32 0x20002077 +#define MASK_URADD32 0xfe00707f +#define MATCH_URADD64 0xa0001077 +#define MASK_URADD64 0xfe00707f +#define MATCH_URADD8 0x28000077 +#define MASK_URADD8 0xfe00707f +#define MATCH_URADDW 0x30001077 +#define MASK_URADDW 0xfe00707f +#define MATCH_URCRAS16 0x24000077 +#define MASK_URCRAS16 0xfe00707f +#define MATCH_URCRAS32 0x24002077 +#define MASK_URCRAS32 0xfe00707f +#define MATCH_URCRSA16 0x26000077 +#define MASK_URCRSA16 0xfe00707f +#define MATCH_URCRSA32 0x26002077 +#define MASK_URCRSA32 0xfe00707f +#define MATCH_URSTAS16 0xd4002077 +#define MASK_URSTAS16 0xfe00707f +#define MATCH_URSTAS32 0xd0002077 +#define MASK_URSTAS32 0xfe00707f +#define MATCH_URSTSA16 0xd6002077 +#define MASK_URSTSA16 0xfe00707f +#define MATCH_URSTSA32 0xd2002077 +#define MASK_URSTSA32 0xfe00707f +#define MATCH_URSUB16 0x22000077 +#define MASK_URSUB16 0xfe00707f +#define MATCH_URSUB32 0x22002077 +#define MASK_URSUB32 0xfe00707f +#define MATCH_URSUB64 0xa2001077 +#define MASK_URSUB64 0xfe00707f +#define MATCH_URSUB8 0x2a000077 +#define MASK_URSUB8 0xfe00707f +#define MATCH_URSUBW 0x32001077 +#define MASK_URSUBW 0xfe00707f +#define MATCH_VAADD_VV 0x24002057 +#define MASK_VAADD_VV 0xfc00707f +#define MATCH_VAADD_VX 0x24006057 +#define MASK_VAADD_VX 0xfc00707f +#define MATCH_VAADDU_VV 0x20002057 +#define MASK_VAADDU_VV 0xfc00707f +#define MATCH_VAADDU_VX 0x20006057 +#define MASK_VAADDU_VX 0xfc00707f +#define MATCH_VADC_VIM 0x40003057 +#define MASK_VADC_VIM 0xfe00707f +#define MATCH_VADC_VVM 0x40000057 +#define MASK_VADC_VVM 0xfe00707f +#define MATCH_VADC_VXM 0x40004057 +#define MASK_VADC_VXM 0xfe00707f +#define MATCH_VADD_VI 0x3057 +#define MASK_VADD_VI 0xfc00707f +#define MATCH_VADD_VV 0x57 +#define MASK_VADD_VV 0xfc00707f +#define MATCH_VADD_VX 0x4057 +#define MASK_VADD_VX 0xfc00707f +#define MATCH_VAMOADDEI16_V 0x502f +#define MASK_VAMOADDEI16_V 0xf800707f +#define MATCH_VAMOADDEI32_V 0x602f +#define MASK_VAMOADDEI32_V 0xf800707f +#define MATCH_VAMOADDEI64_V 0x702f +#define MASK_VAMOADDEI64_V 0xf800707f +#define MATCH_VAMOADDEI8_V 0x2f +#define MASK_VAMOADDEI8_V 0xf800707f +#define MATCH_VAMOANDEI16_V 0x6000502f +#define MASK_VAMOANDEI16_V 0xf800707f +#define MATCH_VAMOANDEI32_V 0x6000602f +#define MASK_VAMOANDEI32_V 0xf800707f +#define MATCH_VAMOANDEI64_V 0x6000702f +#define MASK_VAMOANDEI64_V 0xf800707f +#define MATCH_VAMOANDEI8_V 0x6000002f +#define MASK_VAMOANDEI8_V 0xf800707f +#define MATCH_VAMOMAXEI16_V 0xa000502f +#define MASK_VAMOMAXEI16_V 0xf800707f +#define MATCH_VAMOMAXEI32_V 0xa000602f +#define MASK_VAMOMAXEI32_V 0xf800707f +#define MATCH_VAMOMAXEI64_V 0xa000702f +#define MASK_VAMOMAXEI64_V 0xf800707f +#define MATCH_VAMOMAXEI8_V 0xa000002f +#define MASK_VAMOMAXEI8_V 0xf800707f +#define MATCH_VAMOMAXUEI16_V 0xe000502f +#define MASK_VAMOMAXUEI16_V 0xf800707f +#define MATCH_VAMOMAXUEI32_V 0xe000602f +#define MASK_VAMOMAXUEI32_V 0xf800707f +#define MATCH_VAMOMAXUEI64_V 0xe000702f +#define MASK_VAMOMAXUEI64_V 0xf800707f +#define MATCH_VAMOMAXUEI8_V 0xe000002f +#define MASK_VAMOMAXUEI8_V 0xf800707f +#define MATCH_VAMOMINEI16_V 0x8000502f +#define MASK_VAMOMINEI16_V 0xf800707f +#define MATCH_VAMOMINEI32_V 0x8000602f +#define MASK_VAMOMINEI32_V 0xf800707f +#define MATCH_VAMOMINEI64_V 0x8000702f +#define MASK_VAMOMINEI64_V 0xf800707f +#define MATCH_VAMOMINEI8_V 0x8000002f +#define MASK_VAMOMINEI8_V 0xf800707f +#define MATCH_VAMOMINUEI16_V 0xc000502f +#define MASK_VAMOMINUEI16_V 0xf800707f +#define MATCH_VAMOMINUEI32_V 0xc000602f +#define MASK_VAMOMINUEI32_V 0xf800707f +#define MATCH_VAMOMINUEI64_V 0xc000702f +#define MASK_VAMOMINUEI64_V 0xf800707f +#define MATCH_VAMOMINUEI8_V 0xc000002f +#define MASK_VAMOMINUEI8_V 0xf800707f +#define MATCH_VAMOOREI16_V 0x4000502f +#define MASK_VAMOOREI16_V 0xf800707f +#define MATCH_VAMOOREI32_V 0x4000602f +#define MASK_VAMOOREI32_V 0xf800707f +#define MATCH_VAMOOREI64_V 0x4000702f +#define MASK_VAMOOREI64_V 0xf800707f +#define MATCH_VAMOOREI8_V 0x4000002f +#define MASK_VAMOOREI8_V 0xf800707f +#define MATCH_VAMOSWAPEI16_V 0x800502f +#define MASK_VAMOSWAPEI16_V 0xf800707f +#define MATCH_VAMOSWAPEI32_V 0x800602f +#define MASK_VAMOSWAPEI32_V 0xf800707f +#define MATCH_VAMOSWAPEI64_V 0x800702f +#define MASK_VAMOSWAPEI64_V 0xf800707f +#define MATCH_VAMOSWAPEI8_V 0x800002f +#define MASK_VAMOSWAPEI8_V 0xf800707f +#define MATCH_VAMOXOREI16_V 0x2000502f +#define MASK_VAMOXOREI16_V 0xf800707f +#define MATCH_VAMOXOREI32_V 0x2000602f +#define MASK_VAMOXOREI32_V 0xf800707f +#define MATCH_VAMOXOREI64_V 0x2000702f +#define MASK_VAMOXOREI64_V 0xf800707f +#define MATCH_VAMOXOREI8_V 0x2000002f +#define MASK_VAMOXOREI8_V 0xf800707f +#define MATCH_VAND_VI 0x24003057 +#define MASK_VAND_VI 0xfc00707f +#define MATCH_VAND_VV 0x24000057 +#define MASK_VAND_VV 0xfc00707f +#define MATCH_VAND_VX 0x24004057 +#define MASK_VAND_VX 0xfc00707f +#define MATCH_VASUB_VV 0x2c002057 +#define MASK_VASUB_VV 0xfc00707f +#define MATCH_VASUB_VX 0x2c006057 +#define MASK_VASUB_VX 0xfc00707f +#define MATCH_VASUBU_VV 0x28002057 +#define MASK_VASUBU_VV 0xfc00707f +#define MATCH_VASUBU_VX 0x28006057 +#define MASK_VASUBU_VX 0xfc00707f +#define MATCH_VCOMPRESS_VM 0x5e002057 +#define MASK_VCOMPRESS_VM 0xfe00707f +#define MATCH_VCPOP_M 0x40082057 +#define MASK_VCPOP_M 0xfc0ff07f +#define MATCH_VDIV_VV 0x84002057 +#define MASK_VDIV_VV 0xfc00707f +#define MATCH_VDIV_VX 0x84006057 +#define MASK_VDIV_VX 0xfc00707f +#define MATCH_VDIVU_VV 0x80002057 +#define MASK_VDIVU_VV 0xfc00707f +#define MATCH_VDIVU_VX 0x80006057 +#define MASK_VDIVU_VX 0xfc00707f +#define MATCH_VFADD_VF 0x5057 +#define MASK_VFADD_VF 0xfc00707f +#define MATCH_VFADD_VV 0x1057 +#define MASK_VFADD_VV 0xfc00707f +#define MATCH_VFCLASS_V 0x4c081057 +#define MASK_VFCLASS_V 0xfc0ff07f +#define MATCH_VFCVT_F_X_V 0x48019057 +#define MASK_VFCVT_F_X_V 0xfc0ff07f +#define MATCH_VFCVT_F_XU_V 0x48011057 +#define MASK_VFCVT_F_XU_V 0xfc0ff07f +#define MATCH_VFCVT_RTZ_X_F_V 0x48039057 +#define MASK_VFCVT_RTZ_X_F_V 0xfc0ff07f +#define MATCH_VFCVT_RTZ_XU_F_V 0x48031057 +#define MASK_VFCVT_RTZ_XU_F_V 0xfc0ff07f +#define MATCH_VFCVT_X_F_V 0x48009057 +#define MASK_VFCVT_X_F_V 0xfc0ff07f +#define MATCH_VFCVT_XU_F_V 0x48001057 +#define MASK_VFCVT_XU_F_V 0xfc0ff07f +#define MATCH_VFDIV_VF 0x80005057 +#define MASK_VFDIV_VF 0xfc00707f +#define MATCH_VFDIV_VV 0x80001057 +#define MASK_VFDIV_VV 0xfc00707f +#define MATCH_VFIRST_M 0x4008a057 +#define MASK_VFIRST_M 0xfc0ff07f +#define MATCH_VFMACC_VF 0xb0005057 +#define MASK_VFMACC_VF 0xfc00707f +#define MATCH_VFMACC_VV 0xb0001057 +#define MASK_VFMACC_VV 0xfc00707f +#define MATCH_VFMADD_VF 0xa0005057 +#define MASK_VFMADD_VF 0xfc00707f +#define MATCH_VFMADD_VV 0xa0001057 +#define MASK_VFMADD_VV 0xfc00707f +#define MATCH_VFMAX_VF 0x18005057 +#define MASK_VFMAX_VF 0xfc00707f +#define MATCH_VFMAX_VV 0x18001057 +#define MASK_VFMAX_VV 0xfc00707f +#define MATCH_VFMERGE_VFM 0x5c005057 +#define MASK_VFMERGE_VFM 0xfe00707f +#define MATCH_VFMIN_VF 0x10005057 +#define MASK_VFMIN_VF 0xfc00707f +#define MATCH_VFMIN_VV 0x10001057 +#define MASK_VFMIN_VV 0xfc00707f +#define MATCH_VFMSAC_VF 0xb8005057 +#define MASK_VFMSAC_VF 0xfc00707f +#define MATCH_VFMSAC_VV 0xb8001057 +#define MASK_VFMSAC_VV 0xfc00707f +#define MATCH_VFMSUB_VF 0xa8005057 +#define MASK_VFMSUB_VF 0xfc00707f +#define MATCH_VFMSUB_VV 0xa8001057 +#define MASK_VFMSUB_VV 0xfc00707f +#define MATCH_VFMUL_VF 0x90005057 +#define MASK_VFMUL_VF 0xfc00707f +#define MATCH_VFMUL_VV 0x90001057 +#define MASK_VFMUL_VV 0xfc00707f +#define MATCH_VFMV_F_S 0x42001057 +#define MASK_VFMV_F_S 0xfe0ff07f +#define MATCH_VFMV_S_F 0x42005057 +#define MASK_VFMV_S_F 0xfff0707f +#define MATCH_VFMV_V_F 0x5e005057 +#define MASK_VFMV_V_F 0xfff0707f +#define MATCH_VFNCVT_F_F_W 0x480a1057 +#define MASK_VFNCVT_F_F_W 0xfc0ff07f +#define MATCH_VFNCVT_F_X_W 0x48099057 +#define MASK_VFNCVT_F_X_W 0xfc0ff07f +#define MATCH_VFNCVT_F_XU_W 0x48091057 +#define MASK_VFNCVT_F_XU_W 0xfc0ff07f +#define MATCH_VFNCVT_ROD_F_F_W 0x480a9057 +#define MASK_VFNCVT_ROD_F_F_W 0xfc0ff07f +#define MATCH_VFNCVT_RTZ_X_F_W 0x480b9057 +#define MASK_VFNCVT_RTZ_X_F_W 0xfc0ff07f +#define MATCH_VFNCVT_RTZ_XU_F_W 0x480b1057 +#define MASK_VFNCVT_RTZ_XU_F_W 0xfc0ff07f +#define MATCH_VFNCVT_X_F_W 0x48089057 +#define MASK_VFNCVT_X_F_W 0xfc0ff07f +#define MATCH_VFNCVT_XU_F_W 0x48081057 +#define MASK_VFNCVT_XU_F_W 0xfc0ff07f +#define MATCH_VFNMACC_VF 0xb4005057 +#define MASK_VFNMACC_VF 0xfc00707f +#define MATCH_VFNMACC_VV 0xb4001057 +#define MASK_VFNMACC_VV 0xfc00707f +#define MATCH_VFNMADD_VF 0xa4005057 +#define MASK_VFNMADD_VF 0xfc00707f +#define MATCH_VFNMADD_VV 0xa4001057 +#define MASK_VFNMADD_VV 0xfc00707f +#define MATCH_VFNMSAC_VF 0xbc005057 +#define MASK_VFNMSAC_VF 0xfc00707f +#define MATCH_VFNMSAC_VV 0xbc001057 +#define MASK_VFNMSAC_VV 0xfc00707f +#define MATCH_VFNMSUB_VF 0xac005057 +#define MASK_VFNMSUB_VF 0xfc00707f +#define MATCH_VFNMSUB_VV 0xac001057 +#define MASK_VFNMSUB_VV 0xfc00707f +#define MATCH_VFRDIV_VF 0x84005057 +#define MASK_VFRDIV_VF 0xfc00707f +#define MATCH_VFREC7_V 0x4c029057 +#define MASK_VFREC7_V 0xfc0ff07f +#define MATCH_VFREDMAX_VS 0x1c001057 +#define MASK_VFREDMAX_VS 0xfc00707f +#define MATCH_VFREDMIN_VS 0x14001057 +#define MASK_VFREDMIN_VS 0xfc00707f +#define MATCH_VFREDOSUM_VS 0xc001057 +#define MASK_VFREDOSUM_VS 0xfc00707f +#define MATCH_VFREDUSUM_VS 0x4001057 +#define MASK_VFREDUSUM_VS 0xfc00707f +#define MATCH_VFRSQRT7_V 0x4c021057 +#define MASK_VFRSQRT7_V 0xfc0ff07f +#define MATCH_VFRSUB_VF 0x9c005057 +#define MASK_VFRSUB_VF 0xfc00707f +#define MATCH_VFSGNJ_VF 0x20005057 +#define MASK_VFSGNJ_VF 0xfc00707f +#define MATCH_VFSGNJ_VV 0x20001057 +#define MASK_VFSGNJ_VV 0xfc00707f +#define MATCH_VFSGNJN_VF 0x24005057 +#define MASK_VFSGNJN_VF 0xfc00707f +#define MATCH_VFSGNJN_VV 0x24001057 +#define MASK_VFSGNJN_VV 0xfc00707f +#define MATCH_VFSGNJX_VF 0x28005057 +#define MASK_VFSGNJX_VF 0xfc00707f +#define MATCH_VFSGNJX_VV 0x28001057 +#define MASK_VFSGNJX_VV 0xfc00707f +#define MATCH_VFSLIDE1DOWN_VF 0x3c005057 +#define MASK_VFSLIDE1DOWN_VF 0xfc00707f +#define MATCH_VFSLIDE1UP_VF 0x38005057 +#define MASK_VFSLIDE1UP_VF 0xfc00707f +#define MATCH_VFSQRT_V 0x4c001057 +#define MASK_VFSQRT_V 0xfc0ff07f +#define MATCH_VFSUB_VF 0x8005057 +#define MASK_VFSUB_VF 0xfc00707f +#define MATCH_VFSUB_VV 0x8001057 +#define MASK_VFSUB_VV 0xfc00707f +#define MATCH_VFWADD_VF 0xc0005057 +#define MASK_VFWADD_VF 0xfc00707f +#define MATCH_VFWADD_VV 0xc0001057 +#define MASK_VFWADD_VV 0xfc00707f +#define MATCH_VFWADD_WF 0xd0005057 +#define MASK_VFWADD_WF 0xfc00707f +#define MATCH_VFWADD_WV 0xd0001057 +#define MASK_VFWADD_WV 0xfc00707f +#define MATCH_VFWCVT_F_F_V 0x48061057 +#define MASK_VFWCVT_F_F_V 0xfc0ff07f +#define MATCH_VFWCVT_F_X_V 0x48059057 +#define MASK_VFWCVT_F_X_V 0xfc0ff07f +#define MATCH_VFWCVT_F_XU_V 0x48051057 +#define MASK_VFWCVT_F_XU_V 0xfc0ff07f +#define MATCH_VFWCVT_RTZ_X_F_V 0x48079057 +#define MASK_VFWCVT_RTZ_X_F_V 0xfc0ff07f +#define MATCH_VFWCVT_RTZ_XU_F_V 0x48071057 +#define MASK_VFWCVT_RTZ_XU_F_V 0xfc0ff07f +#define MATCH_VFWCVT_X_F_V 0x48049057 +#define MASK_VFWCVT_X_F_V 0xfc0ff07f +#define MATCH_VFWCVT_XU_F_V 0x48041057 +#define MASK_VFWCVT_XU_F_V 0xfc0ff07f +#define MATCH_VFWMACC_VF 0xf0005057 +#define MASK_VFWMACC_VF 0xfc00707f +#define MATCH_VFWMACC_VV 0xf0001057 +#define MASK_VFWMACC_VV 0xfc00707f +#define MATCH_VFWMSAC_VF 0xf8005057 +#define MASK_VFWMSAC_VF 0xfc00707f +#define MATCH_VFWMSAC_VV 0xf8001057 +#define MASK_VFWMSAC_VV 0xfc00707f +#define MATCH_VFWMUL_VF 0xe0005057 +#define MASK_VFWMUL_VF 0xfc00707f +#define MATCH_VFWMUL_VV 0xe0001057 +#define MASK_VFWMUL_VV 0xfc00707f +#define MATCH_VFWNMACC_VF 0xf4005057 +#define MASK_VFWNMACC_VF 0xfc00707f +#define MATCH_VFWNMACC_VV 0xf4001057 +#define MASK_VFWNMACC_VV 0xfc00707f +#define MATCH_VFWNMSAC_VF 0xfc005057 +#define MASK_VFWNMSAC_VF 0xfc00707f +#define MATCH_VFWNMSAC_VV 0xfc001057 +#define MASK_VFWNMSAC_VV 0xfc00707f +#define MATCH_VFWREDOSUM_VS 0xcc001057 +#define MASK_VFWREDOSUM_VS 0xfc00707f +#define MATCH_VFWREDUSUM_VS 0xc4001057 +#define MASK_VFWREDUSUM_VS 0xfc00707f +#define MATCH_VFWSUB_VF 0xc8005057 +#define MASK_VFWSUB_VF 0xfc00707f +#define MATCH_VFWSUB_VV 0xc8001057 +#define MASK_VFWSUB_VV 0xfc00707f +#define MATCH_VFWSUB_WF 0xd8005057 +#define MASK_VFWSUB_WF 0xfc00707f +#define MATCH_VFWSUB_WV 0xd8001057 +#define MASK_VFWSUB_WV 0xfc00707f +#define MATCH_VID_V 0x5008a057 +#define MASK_VID_V 0xfdfff07f +#define MATCH_VIOTA_M 0x50082057 +#define MASK_VIOTA_M 0xfc0ff07f +#define MATCH_VL1RE16_V 0x2805007 +#define MASK_VL1RE16_V 0xfff0707f +#define MATCH_VL1RE32_V 0x2806007 +#define MASK_VL1RE32_V 0xfff0707f +#define MATCH_VL1RE64_V 0x2807007 +#define MASK_VL1RE64_V 0xfff0707f +#define MATCH_VL1RE8_V 0x2800007 +#define MASK_VL1RE8_V 0xfff0707f +#define MATCH_VL2RE16_V 0x22805007 +#define MASK_VL2RE16_V 0xfff0707f +#define MATCH_VL2RE32_V 0x22806007 +#define MASK_VL2RE32_V 0xfff0707f +#define MATCH_VL2RE64_V 0x22807007 +#define MASK_VL2RE64_V 0xfff0707f +#define MATCH_VL2RE8_V 0x22800007 +#define MASK_VL2RE8_V 0xfff0707f +#define MATCH_VL4RE16_V 0x62805007 +#define MASK_VL4RE16_V 0xfff0707f +#define MATCH_VL4RE32_V 0x62806007 +#define MASK_VL4RE32_V 0xfff0707f +#define MATCH_VL4RE64_V 0x62807007 +#define MASK_VL4RE64_V 0xfff0707f +#define MATCH_VL4RE8_V 0x62800007 +#define MASK_VL4RE8_V 0xfff0707f +#define MATCH_VL8RE16_V 0xe2805007 +#define MASK_VL8RE16_V 0xfff0707f +#define MATCH_VL8RE32_V 0xe2806007 +#define MASK_VL8RE32_V 0xfff0707f +#define MATCH_VL8RE64_V 0xe2807007 +#define MASK_VL8RE64_V 0xfff0707f +#define MATCH_VL8RE8_V 0xe2800007 +#define MASK_VL8RE8_V 0xfff0707f +#define MATCH_VLE1024_V 0x10007007 +#define MASK_VLE1024_V 0x1df0707f +#define MATCH_VLE1024FF_V 0x11007007 +#define MASK_VLE1024FF_V 0x1df0707f +#define MATCH_VLE128_V 0x10000007 +#define MASK_VLE128_V 0x1df0707f +#define MATCH_VLE128FF_V 0x11000007 +#define MASK_VLE128FF_V 0x1df0707f +#define MATCH_VLE16_V 0x5007 +#define MASK_VLE16_V 0x1df0707f +#define MATCH_VLE16FF_V 0x1005007 +#define MASK_VLE16FF_V 0x1df0707f +#define MATCH_VLE256_V 0x10005007 +#define MASK_VLE256_V 0x1df0707f +#define MATCH_VLE256FF_V 0x11005007 +#define MASK_VLE256FF_V 0x1df0707f +#define MATCH_VLE32_V 0x6007 +#define MASK_VLE32_V 0x1df0707f +#define MATCH_VLE32FF_V 0x1006007 +#define MASK_VLE32FF_V 0x1df0707f +#define MATCH_VLE512_V 0x10006007 +#define MASK_VLE512_V 0x1df0707f +#define MATCH_VLE512FF_V 0x11006007 +#define MASK_VLE512FF_V 0x1df0707f +#define MATCH_VLE64_V 0x7007 +#define MASK_VLE64_V 0x1df0707f +#define MATCH_VLE64FF_V 0x1007007 +#define MASK_VLE64FF_V 0x1df0707f +#define MATCH_VLE8_V 0x7 +#define MASK_VLE8_V 0x1df0707f +#define MATCH_VLE8FF_V 0x1000007 +#define MASK_VLE8FF_V 0x1df0707f +#define MATCH_VLM_V 0x2b00007 +#define MASK_VLM_V 0xfff0707f +#define MATCH_VLOXEI1024_V 0x1c007007 +#define MASK_VLOXEI1024_V 0x1c00707f +#define MATCH_VLOXEI128_V 0x1c000007 +#define MASK_VLOXEI128_V 0x1c00707f +#define MATCH_VLOXEI16_V 0xc005007 +#define MASK_VLOXEI16_V 0x1c00707f +#define MATCH_VLOXEI256_V 0x1c005007 +#define MASK_VLOXEI256_V 0x1c00707f +#define MATCH_VLOXEI32_V 0xc006007 +#define MASK_VLOXEI32_V 0x1c00707f +#define MATCH_VLOXEI512_V 0x1c006007 +#define MASK_VLOXEI512_V 0x1c00707f +#define MATCH_VLOXEI64_V 0xc007007 +#define MASK_VLOXEI64_V 0x1c00707f +#define MATCH_VLOXEI8_V 0xc000007 +#define MASK_VLOXEI8_V 0x1c00707f +#define MATCH_VLSE1024_V 0x18007007 +#define MASK_VLSE1024_V 0x1c00707f +#define MATCH_VLSE128_V 0x18000007 +#define MASK_VLSE128_V 0x1c00707f +#define MATCH_VLSE16_V 0x8005007 +#define MASK_VLSE16_V 0x1c00707f +#define MATCH_VLSE256_V 0x18005007 +#define MASK_VLSE256_V 0x1c00707f +#define MATCH_VLSE32_V 0x8006007 +#define MASK_VLSE32_V 0x1c00707f +#define MATCH_VLSE512_V 0x18006007 +#define MASK_VLSE512_V 0x1c00707f +#define MATCH_VLSE64_V 0x8007007 +#define MASK_VLSE64_V 0x1c00707f +#define MATCH_VLSE8_V 0x8000007 +#define MASK_VLSE8_V 0x1c00707f +#define MATCH_VLUXEI1024_V 0x14007007 +#define MASK_VLUXEI1024_V 0x1c00707f +#define MATCH_VLUXEI128_V 0x14000007 +#define MASK_VLUXEI128_V 0x1c00707f +#define MATCH_VLUXEI16_V 0x4005007 +#define MASK_VLUXEI16_V 0x1c00707f +#define MATCH_VLUXEI256_V 0x14005007 +#define MASK_VLUXEI256_V 0x1c00707f +#define MATCH_VLUXEI32_V 0x4006007 +#define MASK_VLUXEI32_V 0x1c00707f +#define MATCH_VLUXEI512_V 0x14006007 +#define MASK_VLUXEI512_V 0x1c00707f +#define MATCH_VLUXEI64_V 0x4007007 +#define MASK_VLUXEI64_V 0x1c00707f +#define MATCH_VLUXEI8_V 0x4000007 +#define MASK_VLUXEI8_V 0x1c00707f +#define MATCH_VMACC_VV 0xb4002057 +#define MASK_VMACC_VV 0xfc00707f +#define MATCH_VMACC_VX 0xb4006057 +#define MASK_VMACC_VX 0xfc00707f +#define MATCH_VMADC_VI 0x46003057 +#define MASK_VMADC_VI 0xfe00707f +#define MATCH_VMADC_VIM 0x44003057 +#define MASK_VMADC_VIM 0xfe00707f +#define MATCH_VMADC_VV 0x46000057 +#define MASK_VMADC_VV 0xfe00707f +#define MATCH_VMADC_VVM 0x44000057 +#define MASK_VMADC_VVM 0xfe00707f +#define MATCH_VMADC_VX 0x46004057 +#define MASK_VMADC_VX 0xfe00707f +#define MATCH_VMADC_VXM 0x44004057 +#define MASK_VMADC_VXM 0xfe00707f +#define MATCH_VMADD_VV 0xa4002057 +#define MASK_VMADD_VV 0xfc00707f +#define MATCH_VMADD_VX 0xa4006057 +#define MASK_VMADD_VX 0xfc00707f +#define MATCH_VMAND_MM 0x64002057 +#define MASK_VMAND_MM 0xfc00707f +#define MATCH_VMANDN_MM 0x60002057 +#define MASK_VMANDN_MM 0xfc00707f +#define MATCH_VMAX_VV 0x1c000057 +#define MASK_VMAX_VV 0xfc00707f +#define MATCH_VMAX_VX 0x1c004057 +#define MASK_VMAX_VX 0xfc00707f +#define MATCH_VMAXU_VV 0x18000057 +#define MASK_VMAXU_VV 0xfc00707f +#define MATCH_VMAXU_VX 0x18004057 +#define MASK_VMAXU_VX 0xfc00707f +#define MATCH_VMERGE_VIM 0x5c003057 +#define MASK_VMERGE_VIM 0xfe00707f +#define MATCH_VMERGE_VVM 0x5c000057 +#define MASK_VMERGE_VVM 0xfe00707f +#define MATCH_VMERGE_VXM 0x5c004057 +#define MASK_VMERGE_VXM 0xfe00707f +#define MATCH_VMFEQ_VF 0x60005057 +#define MASK_VMFEQ_VF 0xfc00707f +#define MATCH_VMFEQ_VV 0x60001057 +#define MASK_VMFEQ_VV 0xfc00707f +#define MATCH_VMFGE_VF 0x7c005057 +#define MASK_VMFGE_VF 0xfc00707f +#define MATCH_VMFGT_VF 0x74005057 +#define MASK_VMFGT_VF 0xfc00707f +#define MATCH_VMFLE_VF 0x64005057 +#define MASK_VMFLE_VF 0xfc00707f +#define MATCH_VMFLE_VV 0x64001057 +#define MASK_VMFLE_VV 0xfc00707f +#define MATCH_VMFLT_VF 0x6c005057 +#define MASK_VMFLT_VF 0xfc00707f +#define MATCH_VMFLT_VV 0x6c001057 +#define MASK_VMFLT_VV 0xfc00707f +#define MATCH_VMFNE_VF 0x70005057 +#define MASK_VMFNE_VF 0xfc00707f +#define MATCH_VMFNE_VV 0x70001057 +#define MASK_VMFNE_VV 0xfc00707f +#define MATCH_VMIN_VV 0x14000057 +#define MASK_VMIN_VV 0xfc00707f +#define MATCH_VMIN_VX 0x14004057 +#define MASK_VMIN_VX 0xfc00707f +#define MATCH_VMINU_VV 0x10000057 +#define MASK_VMINU_VV 0xfc00707f +#define MATCH_VMINU_VX 0x10004057 +#define MASK_VMINU_VX 0xfc00707f +#define MATCH_VMNAND_MM 0x74002057 +#define MASK_VMNAND_MM 0xfc00707f +#define MATCH_VMNOR_MM 0x78002057 +#define MASK_VMNOR_MM 0xfc00707f +#define MATCH_VMOR_MM 0x68002057 +#define MASK_VMOR_MM 0xfc00707f +#define MATCH_VMORN_MM 0x70002057 +#define MASK_VMORN_MM 0xfc00707f +#define MATCH_VMSBC_VV 0x4e000057 +#define MASK_VMSBC_VV 0xfe00707f +#define MATCH_VMSBC_VVM 0x4c000057 +#define MASK_VMSBC_VVM 0xfe00707f +#define MATCH_VMSBC_VX 0x4e004057 +#define MASK_VMSBC_VX 0xfe00707f +#define MATCH_VMSBC_VXM 0x4c004057 +#define MASK_VMSBC_VXM 0xfe00707f +#define MATCH_VMSBF_M 0x5000a057 +#define MASK_VMSBF_M 0xfc0ff07f +#define MATCH_VMSEQ_VI 0x60003057 +#define MASK_VMSEQ_VI 0xfc00707f +#define MATCH_VMSEQ_VV 0x60000057 +#define MASK_VMSEQ_VV 0xfc00707f +#define MATCH_VMSEQ_VX 0x60004057 +#define MASK_VMSEQ_VX 0xfc00707f +#define MATCH_VMSGT_VI 0x7c003057 +#define MASK_VMSGT_VI 0xfc00707f +#define MATCH_VMSGT_VX 0x7c004057 +#define MASK_VMSGT_VX 0xfc00707f +#define MATCH_VMSGTU_VI 0x78003057 +#define MASK_VMSGTU_VI 0xfc00707f +#define MATCH_VMSGTU_VX 0x78004057 +#define MASK_VMSGTU_VX 0xfc00707f +#define MATCH_VMSIF_M 0x5001a057 +#define MASK_VMSIF_M 0xfc0ff07f +#define MATCH_VMSLE_VI 0x74003057 +#define MASK_VMSLE_VI 0xfc00707f +#define MATCH_VMSLE_VV 0x74000057 +#define MASK_VMSLE_VV 0xfc00707f +#define MATCH_VMSLE_VX 0x74004057 +#define MASK_VMSLE_VX 0xfc00707f +#define MATCH_VMSLEU_VI 0x70003057 +#define MASK_VMSLEU_VI 0xfc00707f +#define MATCH_VMSLEU_VV 0x70000057 +#define MASK_VMSLEU_VV 0xfc00707f +#define MATCH_VMSLEU_VX 0x70004057 +#define MASK_VMSLEU_VX 0xfc00707f +#define MATCH_VMSLT_VV 0x6c000057 +#define MASK_VMSLT_VV 0xfc00707f +#define MATCH_VMSLT_VX 0x6c004057 +#define MASK_VMSLT_VX 0xfc00707f +#define MATCH_VMSLTU_VV 0x68000057 +#define MASK_VMSLTU_VV 0xfc00707f +#define MATCH_VMSLTU_VX 0x68004057 +#define MASK_VMSLTU_VX 0xfc00707f +#define MATCH_VMSNE_VI 0x64003057 +#define MASK_VMSNE_VI 0xfc00707f +#define MATCH_VMSNE_VV 0x64000057 +#define MASK_VMSNE_VV 0xfc00707f +#define MATCH_VMSNE_VX 0x64004057 +#define MASK_VMSNE_VX 0xfc00707f +#define MATCH_VMSOF_M 0x50012057 +#define MASK_VMSOF_M 0xfc0ff07f +#define MATCH_VMUL_VV 0x94002057 +#define MASK_VMUL_VV 0xfc00707f +#define MATCH_VMUL_VX 0x94006057 +#define MASK_VMUL_VX 0xfc00707f +#define MATCH_VMULH_VV 0x9c002057 +#define MASK_VMULH_VV 0xfc00707f +#define MATCH_VMULH_VX 0x9c006057 +#define MASK_VMULH_VX 0xfc00707f +#define MATCH_VMULHSU_VV 0x98002057 +#define MASK_VMULHSU_VV 0xfc00707f +#define MATCH_VMULHSU_VX 0x98006057 +#define MASK_VMULHSU_VX 0xfc00707f +#define MATCH_VMULHU_VV 0x90002057 +#define MASK_VMULHU_VV 0xfc00707f +#define MATCH_VMULHU_VX 0x90006057 +#define MASK_VMULHU_VX 0xfc00707f +#define MATCH_VMV1R_V 0x9e003057 +#define MASK_VMV1R_V 0xfe0ff07f +#define MATCH_VMV2R_V 0x9e00b057 +#define MASK_VMV2R_V 0xfe0ff07f +#define MATCH_VMV4R_V 0x9e01b057 +#define MASK_VMV4R_V 0xfe0ff07f +#define MATCH_VMV8R_V 0x9e03b057 +#define MASK_VMV8R_V 0xfe0ff07f +#define MATCH_VMV_S_X 0x42006057 +#define MASK_VMV_S_X 0xfff0707f +#define MATCH_VMV_V_I 0x5e003057 +#define MASK_VMV_V_I 0xfff0707f +#define MATCH_VMV_V_V 0x5e000057 +#define MASK_VMV_V_V 0xfff0707f +#define MATCH_VMV_V_X 0x5e004057 +#define MASK_VMV_V_X 0xfff0707f +#define MATCH_VMV_X_S 0x42002057 +#define MASK_VMV_X_S 0xfe0ff07f +#define MATCH_VMXNOR_MM 0x7c002057 +#define MASK_VMXNOR_MM 0xfc00707f +#define MATCH_VMXOR_MM 0x6c002057 +#define MASK_VMXOR_MM 0xfc00707f +#define MATCH_VNCLIP_WI 0xbc003057 +#define MASK_VNCLIP_WI 0xfc00707f +#define MATCH_VNCLIP_WV 0xbc000057 +#define MASK_VNCLIP_WV 0xfc00707f +#define MATCH_VNCLIP_WX 0xbc004057 +#define MASK_VNCLIP_WX 0xfc00707f +#define MATCH_VNCLIPU_WI 0xb8003057 +#define MASK_VNCLIPU_WI 0xfc00707f +#define MATCH_VNCLIPU_WV 0xb8000057 +#define MASK_VNCLIPU_WV 0xfc00707f +#define MATCH_VNCLIPU_WX 0xb8004057 +#define MASK_VNCLIPU_WX 0xfc00707f +#define MATCH_VNMSAC_VV 0xbc002057 +#define MASK_VNMSAC_VV 0xfc00707f +#define MATCH_VNMSAC_VX 0xbc006057 +#define MASK_VNMSAC_VX 0xfc00707f +#define MATCH_VNMSUB_VV 0xac002057 +#define MASK_VNMSUB_VV 0xfc00707f +#define MATCH_VNMSUB_VX 0xac006057 +#define MASK_VNMSUB_VX 0xfc00707f +#define MATCH_VNSRA_WI 0xb4003057 +#define MASK_VNSRA_WI 0xfc00707f +#define MATCH_VNSRA_WV 0xb4000057 +#define MASK_VNSRA_WV 0xfc00707f +#define MATCH_VNSRA_WX 0xb4004057 +#define MASK_VNSRA_WX 0xfc00707f +#define MATCH_VNSRL_WI 0xb0003057 +#define MASK_VNSRL_WI 0xfc00707f +#define MATCH_VNSRL_WV 0xb0000057 +#define MASK_VNSRL_WV 0xfc00707f +#define MATCH_VNSRL_WX 0xb0004057 +#define MASK_VNSRL_WX 0xfc00707f +#define MATCH_VOR_VI 0x28003057 +#define MASK_VOR_VI 0xfc00707f +#define MATCH_VOR_VV 0x28000057 +#define MASK_VOR_VV 0xfc00707f +#define MATCH_VOR_VX 0x28004057 +#define MASK_VOR_VX 0xfc00707f +#define MATCH_VREDAND_VS 0x4002057 +#define MASK_VREDAND_VS 0xfc00707f +#define MATCH_VREDMAX_VS 0x1c002057 +#define MASK_VREDMAX_VS 0xfc00707f +#define MATCH_VREDMAXU_VS 0x18002057 +#define MASK_VREDMAXU_VS 0xfc00707f +#define MATCH_VREDMIN_VS 0x14002057 +#define MASK_VREDMIN_VS 0xfc00707f +#define MATCH_VREDMINU_VS 0x10002057 +#define MASK_VREDMINU_VS 0xfc00707f +#define MATCH_VREDOR_VS 0x8002057 +#define MASK_VREDOR_VS 0xfc00707f +#define MATCH_VREDSUM_VS 0x2057 +#define MASK_VREDSUM_VS 0xfc00707f +#define MATCH_VREDXOR_VS 0xc002057 +#define MASK_VREDXOR_VS 0xfc00707f +#define MATCH_VREM_VV 0x8c002057 +#define MASK_VREM_VV 0xfc00707f +#define MATCH_VREM_VX 0x8c006057 +#define MASK_VREM_VX 0xfc00707f +#define MATCH_VREMU_VV 0x88002057 +#define MASK_VREMU_VV 0xfc00707f +#define MATCH_VREMU_VX 0x88006057 +#define MASK_VREMU_VX 0xfc00707f +#define MATCH_VRGATHER_VI 0x30003057 +#define MASK_VRGATHER_VI 0xfc00707f +#define MATCH_VRGATHER_VV 0x30000057 +#define MASK_VRGATHER_VV 0xfc00707f +#define MATCH_VRGATHER_VX 0x30004057 +#define MASK_VRGATHER_VX 0xfc00707f +#define MATCH_VRGATHEREI16_VV 0x38000057 +#define MASK_VRGATHEREI16_VV 0xfc00707f +#define MATCH_VRSUB_VI 0xc003057 +#define MASK_VRSUB_VI 0xfc00707f +#define MATCH_VRSUB_VX 0xc004057 +#define MASK_VRSUB_VX 0xfc00707f +#define MATCH_VS1R_V 0x2800027 +#define MASK_VS1R_V 0xfff0707f +#define MATCH_VS2R_V 0x22800027 +#define MASK_VS2R_V 0xfff0707f +#define MATCH_VS4R_V 0x62800027 +#define MASK_VS4R_V 0xfff0707f +#define MATCH_VS8R_V 0xe2800027 +#define MASK_VS8R_V 0xfff0707f +#define MATCH_VSADD_VI 0x84003057 +#define MASK_VSADD_VI 0xfc00707f +#define MATCH_VSADD_VV 0x84000057 +#define MASK_VSADD_VV 0xfc00707f +#define MATCH_VSADD_VX 0x84004057 +#define MASK_VSADD_VX 0xfc00707f +#define MATCH_VSADDU_VI 0x80003057 +#define MASK_VSADDU_VI 0xfc00707f +#define MATCH_VSADDU_VV 0x80000057 +#define MASK_VSADDU_VV 0xfc00707f +#define MATCH_VSADDU_VX 0x80004057 +#define MASK_VSADDU_VX 0xfc00707f +#define MATCH_VSBC_VVM 0x48000057 +#define MASK_VSBC_VVM 0xfe00707f +#define MATCH_VSBC_VXM 0x48004057 +#define MASK_VSBC_VXM 0xfe00707f +#define MATCH_VSE1024_V 0x10007027 +#define MASK_VSE1024_V 0x1df0707f +#define MATCH_VSE128_V 0x10000027 +#define MASK_VSE128_V 0x1df0707f +#define MATCH_VSE16_V 0x5027 +#define MASK_VSE16_V 0x1df0707f +#define MATCH_VSE256_V 0x10005027 +#define MASK_VSE256_V 0x1df0707f +#define MATCH_VSE32_V 0x6027 +#define MASK_VSE32_V 0x1df0707f +#define MATCH_VSE512_V 0x10006027 +#define MASK_VSE512_V 0x1df0707f +#define MATCH_VSE64_V 0x7027 +#define MASK_VSE64_V 0x1df0707f +#define MATCH_VSE8_V 0x27 +#define MASK_VSE8_V 0x1df0707f +#define MATCH_VSETIVLI 0xc0007057 +#define MASK_VSETIVLI 0xc000707f +#define MATCH_VSETVL 0x80007057 +#define MASK_VSETVL 0xfe00707f +#define MATCH_VSETVLI 0x7057 +#define MASK_VSETVLI 0x8000707f +#define MATCH_VSEXT_VF2 0x4803a057 +#define MASK_VSEXT_VF2 0xfc0ff07f +#define MATCH_VSEXT_VF4 0x4802a057 +#define MASK_VSEXT_VF4 0xfc0ff07f +#define MATCH_VSEXT_VF8 0x4801a057 +#define MASK_VSEXT_VF8 0xfc0ff07f +#define MATCH_VSLIDE1DOWN_VX 0x3c006057 +#define MASK_VSLIDE1DOWN_VX 0xfc00707f +#define MATCH_VSLIDE1UP_VX 0x38006057 +#define MASK_VSLIDE1UP_VX 0xfc00707f +#define MATCH_VSLIDEDOWN_VI 0x3c003057 +#define MASK_VSLIDEDOWN_VI 0xfc00707f +#define MATCH_VSLIDEDOWN_VX 0x3c004057 +#define MASK_VSLIDEDOWN_VX 0xfc00707f +#define MATCH_VSLIDEUP_VI 0x38003057 +#define MASK_VSLIDEUP_VI 0xfc00707f +#define MATCH_VSLIDEUP_VX 0x38004057 +#define MASK_VSLIDEUP_VX 0xfc00707f +#define MATCH_VSLL_VI 0x94003057 +#define MASK_VSLL_VI 0xfc00707f +#define MATCH_VSLL_VV 0x94000057 +#define MASK_VSLL_VV 0xfc00707f +#define MATCH_VSLL_VX 0x94004057 +#define MASK_VSLL_VX 0xfc00707f +#define MATCH_VSM_V 0x2b00027 +#define MASK_VSM_V 0xfff0707f +#define MATCH_VSMUL_VV 0x9c000057 +#define MASK_VSMUL_VV 0xfc00707f +#define MATCH_VSMUL_VX 0x9c004057 +#define MASK_VSMUL_VX 0xfc00707f +#define MATCH_VSOXEI1024_V 0x1c007027 +#define MASK_VSOXEI1024_V 0x1c00707f +#define MATCH_VSOXEI128_V 0x1c000027 +#define MASK_VSOXEI128_V 0x1c00707f +#define MATCH_VSOXEI16_V 0xc005027 +#define MASK_VSOXEI16_V 0x1c00707f +#define MATCH_VSOXEI256_V 0x1c005027 +#define MASK_VSOXEI256_V 0x1c00707f +#define MATCH_VSOXEI32_V 0xc006027 +#define MASK_VSOXEI32_V 0x1c00707f +#define MATCH_VSOXEI512_V 0x1c006027 +#define MASK_VSOXEI512_V 0x1c00707f +#define MATCH_VSOXEI64_V 0xc007027 +#define MASK_VSOXEI64_V 0x1c00707f +#define MATCH_VSOXEI8_V 0xc000027 +#define MASK_VSOXEI8_V 0x1c00707f +#define MATCH_VSRA_VI 0xa4003057 +#define MASK_VSRA_VI 0xfc00707f +#define MATCH_VSRA_VV 0xa4000057 +#define MASK_VSRA_VV 0xfc00707f +#define MATCH_VSRA_VX 0xa4004057 +#define MASK_VSRA_VX 0xfc00707f +#define MATCH_VSRL_VI 0xa0003057 +#define MASK_VSRL_VI 0xfc00707f +#define MATCH_VSRL_VV 0xa0000057 +#define MASK_VSRL_VV 0xfc00707f +#define MATCH_VSRL_VX 0xa0004057 +#define MASK_VSRL_VX 0xfc00707f +#define MATCH_VSSE1024_V 0x18007027 +#define MASK_VSSE1024_V 0x1c00707f +#define MATCH_VSSE128_V 0x18000027 +#define MASK_VSSE128_V 0x1c00707f +#define MATCH_VSSE16_V 0x8005027 +#define MASK_VSSE16_V 0x1c00707f +#define MATCH_VSSE256_V 0x18005027 +#define MASK_VSSE256_V 0x1c00707f +#define MATCH_VSSE32_V 0x8006027 +#define MASK_VSSE32_V 0x1c00707f +#define MATCH_VSSE512_V 0x18006027 +#define MASK_VSSE512_V 0x1c00707f +#define MATCH_VSSE64_V 0x8007027 +#define MASK_VSSE64_V 0x1c00707f +#define MATCH_VSSE8_V 0x8000027 +#define MASK_VSSE8_V 0x1c00707f +#define MATCH_VSSRA_VI 0xac003057 +#define MASK_VSSRA_VI 0xfc00707f +#define MATCH_VSSRA_VV 0xac000057 +#define MASK_VSSRA_VV 0xfc00707f +#define MATCH_VSSRA_VX 0xac004057 +#define MASK_VSSRA_VX 0xfc00707f +#define MATCH_VSSRL_VI 0xa8003057 +#define MASK_VSSRL_VI 0xfc00707f +#define MATCH_VSSRL_VV 0xa8000057 +#define MASK_VSSRL_VV 0xfc00707f +#define MATCH_VSSRL_VX 0xa8004057 +#define MASK_VSSRL_VX 0xfc00707f +#define MATCH_VSSUB_VV 0x8c000057 +#define MASK_VSSUB_VV 0xfc00707f +#define MATCH_VSSUB_VX 0x8c004057 +#define MASK_VSSUB_VX 0xfc00707f +#define MATCH_VSSUBU_VV 0x88000057 +#define MASK_VSSUBU_VV 0xfc00707f +#define MATCH_VSSUBU_VX 0x88004057 +#define MASK_VSSUBU_VX 0xfc00707f +#define MATCH_VSUB_VV 0x8000057 +#define MASK_VSUB_VV 0xfc00707f +#define MATCH_VSUB_VX 0x8004057 +#define MASK_VSUB_VX 0xfc00707f +#define MATCH_VSUXEI1024_V 0x14007027 +#define MASK_VSUXEI1024_V 0x1c00707f +#define MATCH_VSUXEI128_V 0x14000027 +#define MASK_VSUXEI128_V 0x1c00707f +#define MATCH_VSUXEI16_V 0x4005027 +#define MASK_VSUXEI16_V 0x1c00707f +#define MATCH_VSUXEI256_V 0x14005027 +#define MASK_VSUXEI256_V 0x1c00707f +#define MATCH_VSUXEI32_V 0x4006027 +#define MASK_VSUXEI32_V 0x1c00707f +#define MATCH_VSUXEI512_V 0x14006027 +#define MASK_VSUXEI512_V 0x1c00707f +#define MATCH_VSUXEI64_V 0x4007027 +#define MASK_VSUXEI64_V 0x1c00707f +#define MATCH_VSUXEI8_V 0x4000027 +#define MASK_VSUXEI8_V 0x1c00707f +#define MATCH_VWADD_VV 0xc4002057 +#define MASK_VWADD_VV 0xfc00707f +#define MATCH_VWADD_VX 0xc4006057 +#define MASK_VWADD_VX 0xfc00707f +#define MATCH_VWADD_WV 0xd4002057 +#define MASK_VWADD_WV 0xfc00707f +#define MATCH_VWADD_WX 0xd4006057 +#define MASK_VWADD_WX 0xfc00707f +#define MATCH_VWADDU_VV 0xc0002057 +#define MASK_VWADDU_VV 0xfc00707f +#define MATCH_VWADDU_VX 0xc0006057 +#define MASK_VWADDU_VX 0xfc00707f +#define MATCH_VWADDU_WV 0xd0002057 +#define MASK_VWADDU_WV 0xfc00707f +#define MATCH_VWADDU_WX 0xd0006057 +#define MASK_VWADDU_WX 0xfc00707f +#define MATCH_VWMACC_VV 0xf4002057 +#define MASK_VWMACC_VV 0xfc00707f +#define MATCH_VWMACC_VX 0xf4006057 +#define MASK_VWMACC_VX 0xfc00707f +#define MATCH_VWMACCSU_VV 0xfc002057 +#define MASK_VWMACCSU_VV 0xfc00707f +#define MATCH_VWMACCSU_VX 0xfc006057 +#define MASK_VWMACCSU_VX 0xfc00707f +#define MATCH_VWMACCU_VV 0xf0002057 +#define MASK_VWMACCU_VV 0xfc00707f +#define MATCH_VWMACCU_VX 0xf0006057 +#define MASK_VWMACCU_VX 0xfc00707f +#define MATCH_VWMACCUS_VX 0xf8006057 +#define MASK_VWMACCUS_VX 0xfc00707f +#define MATCH_VWMUL_VV 0xec002057 +#define MASK_VWMUL_VV 0xfc00707f +#define MATCH_VWMUL_VX 0xec006057 +#define MASK_VWMUL_VX 0xfc00707f +#define MATCH_VWMULSU_VV 0xe8002057 +#define MASK_VWMULSU_VV 0xfc00707f +#define MATCH_VWMULSU_VX 0xe8006057 +#define MASK_VWMULSU_VX 0xfc00707f +#define MATCH_VWMULU_VV 0xe0002057 +#define MASK_VWMULU_VV 0xfc00707f +#define MATCH_VWMULU_VX 0xe0006057 +#define MASK_VWMULU_VX 0xfc00707f +#define MATCH_VWREDSUM_VS 0xc4000057 +#define MASK_VWREDSUM_VS 0xfc00707f +#define MATCH_VWREDSUMU_VS 0xc0000057 +#define MASK_VWREDSUMU_VS 0xfc00707f +#define MATCH_VWSUB_VV 0xcc002057 +#define MASK_VWSUB_VV 0xfc00707f +#define MATCH_VWSUB_VX 0xcc006057 +#define MASK_VWSUB_VX 0xfc00707f +#define MATCH_VWSUB_WV 0xdc002057 +#define MASK_VWSUB_WV 0xfc00707f +#define MATCH_VWSUB_WX 0xdc006057 +#define MASK_VWSUB_WX 0xfc00707f +#define MATCH_VWSUBU_VV 0xc8002057 +#define MASK_VWSUBU_VV 0xfc00707f +#define MATCH_VWSUBU_VX 0xc8006057 +#define MASK_VWSUBU_VX 0xfc00707f +#define MATCH_VWSUBU_WV 0xd8002057 +#define MASK_VWSUBU_WV 0xfc00707f +#define MATCH_VWSUBU_WX 0xd8006057 +#define MASK_VWSUBU_WX 0xfc00707f +#define MATCH_VXOR_VI 0x2c003057 +#define MASK_VXOR_VI 0xfc00707f +#define MATCH_VXOR_VV 0x2c000057 +#define MASK_VXOR_VV 0xfc00707f +#define MATCH_VXOR_VX 0x2c004057 +#define MASK_VXOR_VX 0xfc00707f +#define MATCH_VZEXT_VF2 0x48032057 +#define MASK_VZEXT_VF2 0xfc0ff07f +#define MATCH_VZEXT_VF4 0x48022057 +#define MASK_VZEXT_VF4 0xfc0ff07f +#define MATCH_VZEXT_VF8 0x48012057 +#define MASK_VZEXT_VF8 0xfc0ff07f +#define MATCH_WEXT 0xce000077 +#define MASK_WEXT 0xfe00707f +#define MATCH_WEXTI 0xde000077 +#define MASK_WEXTI 0xfe00707f +#define MATCH_WFI 0x10500073 +#define MASK_WFI 0xffffffff +#define MATCH_WRS_NTO 0xd00073 +#define MASK_WRS_NTO 0xffffffff +#define MATCH_WRS_STO 0x1d00073 +#define MASK_WRS_STO 0xffffffff +#define MATCH_XNOR 0x40004033 +#define MASK_XNOR 0xfe00707f +#define MATCH_XOR 0x4033 +#define MASK_XOR 0xfe00707f +#define MATCH_XORI 0x4013 +#define MASK_XORI 0x707f +#define MATCH_XPERM16 0x28006033 +#define MASK_XPERM16 0xfe00707f +#define MATCH_XPERM32 0x28000033 +#define MASK_XPERM32 0xfe00707f +#define MATCH_XPERM4 0x28002033 +#define MASK_XPERM4 0xfe00707f +#define MATCH_XPERM8 0x28004033 +#define MASK_XPERM8 0xfe00707f +#define MATCH_ZUNPKD810 0xacc00077 +#define MASK_ZUNPKD810 0xfff0707f +#define MATCH_ZUNPKD820 0xacd00077 +#define MASK_ZUNPKD820 0xfff0707f +#define MATCH_ZUNPKD830 0xace00077 +#define MASK_ZUNPKD830 0xfff0707f +#define MATCH_ZUNPKD831 0xacf00077 +#define MASK_ZUNPKD831 0xfff0707f +#define MATCH_ZUNPKD832 0xad700077 +#define MASK_ZUNPKD832 0xfff0707f + +#define CSR_FFLAGS 0x1 +#define CSR_FRM 0x2 +#define CSR_FCSR 0x3 +#define CSR_VSTART 0x8 +#define CSR_VXSAT 0x9 +#define CSR_VXRM 0xa +#define CSR_VCSR 0xf +#define CSR_SEED 0x15 +#define CSR_CYCLE 0xc00 +#define CSR_TIME 0xc01 +#define CSR_INSTRET 0xc02 +#define CSR_HPMCOUNTER3 0xc03 +#define CSR_HPMCOUNTER4 0xc04 +#define CSR_HPMCOUNTER5 0xc05 +#define CSR_HPMCOUNTER6 0xc06 +#define CSR_HPMCOUNTER7 0xc07 +#define CSR_HPMCOUNTER8 0xc08 +#define CSR_HPMCOUNTER9 0xc09 +#define CSR_HPMCOUNTER10 0xc0a +#define CSR_HPMCOUNTER11 0xc0b +#define CSR_HPMCOUNTER12 0xc0c +#define CSR_HPMCOUNTER13 0xc0d +#define CSR_HPMCOUNTER14 0xc0e +#define CSR_HPMCOUNTER15 0xc0f +#define CSR_HPMCOUNTER16 0xc10 +#define CSR_HPMCOUNTER17 0xc11 +#define CSR_HPMCOUNTER18 0xc12 +#define CSR_HPMCOUNTER19 0xc13 +#define CSR_HPMCOUNTER20 0xc14 +#define CSR_HPMCOUNTER21 0xc15 +#define CSR_HPMCOUNTER22 0xc16 +#define CSR_HPMCOUNTER23 0xc17 +#define CSR_HPMCOUNTER24 0xc18 +#define CSR_HPMCOUNTER25 0xc19 +#define CSR_HPMCOUNTER26 0xc1a +#define CSR_HPMCOUNTER27 0xc1b +#define CSR_HPMCOUNTER28 0xc1c +#define CSR_HPMCOUNTER29 0xc1d +#define CSR_HPMCOUNTER30 0xc1e +#define CSR_HPMCOUNTER31 0xc1f +#define CSR_VL 0xc20 +#define CSR_VTYPE 0xc21 +#define CSR_VLENB 0xc22 +#define CSR_SSTATUS 0x100 +#define CSR_SEDELEG 0x102 +#define CSR_SIDELEG 0x103 +#define CSR_SIE 0x104 +#define CSR_STVEC 0x105 +#define CSR_SCOUNTEREN 0x106 +#define CSR_SENVCFG 0x10a +#define CSR_SSTATEEN0 0x10c +#define CSR_SSTATEEN1 0x10d +#define CSR_SSTATEEN2 0x10e +#define CSR_SSTATEEN3 0x10f +#define CSR_SSCRATCH 0x140 +#define CSR_SEPC 0x141 +#define CSR_SCAUSE 0x142 +#define CSR_STVAL 0x143 +#define CSR_SIP 0x144 +#define CSR_STIMECMP 0x14d +#define CSR_SATP 0x180 +#define CSR_SCONTEXT 0x5a8 +#define CSR_VSSTATUS 0x200 +#define CSR_VSIE 0x204 +#define CSR_VSTVEC 0x205 +#define CSR_VSSCRATCH 0x240 +#define CSR_VSEPC 0x241 +#define CSR_VSCAUSE 0x242 +#define CSR_VSTVAL 0x243 +#define CSR_VSIP 0x244 +#define CSR_VSTIMECMP 0x24d +#define CSR_VSATP 0x280 +#define CSR_HSTATUS 0x600 +#define CSR_HEDELEG 0x602 +#define CSR_HIDELEG 0x603 +#define CSR_HIE 0x604 +#define CSR_HTIMEDELTA 0x605 +#define CSR_HCOUNTEREN 0x606 +#define CSR_HGEIE 0x607 +#define CSR_HENVCFG 0x60a +#define CSR_HSTATEEN0 0x60c +#define CSR_HSTATEEN1 0x60d +#define CSR_HSTATEEN2 0x60e +#define CSR_HSTATEEN3 0x60f +#define CSR_HTVAL 0x643 +#define CSR_HIP 0x644 +#define CSR_HVIP 0x645 +#define CSR_HTINST 0x64a +#define CSR_HGATP 0x680 +#define CSR_HCONTEXT 0x6a8 +#define CSR_HGEIP 0xe12 +#define CSR_SCOUNTOVF 0xda0 +#define CSR_UTVT 0x7 +#define CSR_UNXTI 0x45 +#define CSR_UINTSTATUS 0x46 +#define CSR_USCRATCHCSW 0x48 +#define CSR_USCRATCHCSWL 0x49 +#define CSR_STVT 0x107 +#define CSR_SNXTI 0x145 +#define CSR_SINTSTATUS 0x146 +#define CSR_SSCRATCHCSW 0x148 +#define CSR_SSCRATCHCSWL 0x149 +#define CSR_MTVT 0x307 +#define CSR_MNXTI 0x345 +#define CSR_MINTSTATUS 0x346 +#define CSR_MSCRATCHCSW 0x348 +#define CSR_MSCRATCHCSWL 0x349 +#define CSR_MSTATUS 0x300 +#define CSR_MISA 0x301 +#define CSR_MEDELEG 0x302 +#define CSR_MIDELEG 0x303 +#define CSR_MIE 0x304 +#define CSR_MTVEC 0x305 +#define CSR_MCOUNTEREN 0x306 +#define CSR_MENVCFG 0x30a +#define CSR_MSTATEEN0 0x30c +#define CSR_MSTATEEN1 0x30d +#define CSR_MSTATEEN2 0x30e +#define CSR_MSTATEEN3 0x30f +#define CSR_MCOUNTINHIBIT 0x320 +#define CSR_MSCRATCH 0x340 +#define CSR_MEPC 0x341 +#define CSR_MCAUSE 0x342 +#define CSR_MTVAL 0x343 +#define CSR_MIP 0x344 +#define CSR_MTINST 0x34a +#define CSR_MTVAL2 0x34b +#define CSR_PMPCFG0 0x3a0 +#define CSR_PMPCFG1 0x3a1 +#define CSR_PMPCFG2 0x3a2 +#define CSR_PMPCFG3 0x3a3 +#define CSR_PMPCFG4 0x3a4 +#define CSR_PMPCFG5 0x3a5 +#define CSR_PMPCFG6 0x3a6 +#define CSR_PMPCFG7 0x3a7 +#define CSR_PMPCFG8 0x3a8 +#define CSR_PMPCFG9 0x3a9 +#define CSR_PMPCFG10 0x3aa +#define CSR_PMPCFG11 0x3ab +#define CSR_PMPCFG12 0x3ac +#define CSR_PMPCFG13 0x3ad +#define CSR_PMPCFG14 0x3ae +#define CSR_PMPCFG15 0x3af +#define CSR_PMPADDR0 0x3b0 +#define CSR_PMPADDR1 0x3b1 +#define CSR_PMPADDR2 0x3b2 +#define CSR_PMPADDR3 0x3b3 +#define CSR_PMPADDR4 0x3b4 +#define CSR_PMPADDR5 0x3b5 +#define CSR_PMPADDR6 0x3b6 +#define CSR_PMPADDR7 0x3b7 +#define CSR_PMPADDR8 0x3b8 +#define CSR_PMPADDR9 0x3b9 +#define CSR_PMPADDR10 0x3ba +#define CSR_PMPADDR11 0x3bb +#define CSR_PMPADDR12 0x3bc +#define CSR_PMPADDR13 0x3bd +#define CSR_PMPADDR14 0x3be +#define CSR_PMPADDR15 0x3bf +#define CSR_PMPADDR16 0x3c0 +#define CSR_PMPADDR17 0x3c1 +#define CSR_PMPADDR18 0x3c2 +#define CSR_PMPADDR19 0x3c3 +#define CSR_PMPADDR20 0x3c4 +#define CSR_PMPADDR21 0x3c5 +#define CSR_PMPADDR22 0x3c6 +#define CSR_PMPADDR23 0x3c7 +#define CSR_PMPADDR24 0x3c8 +#define CSR_PMPADDR25 0x3c9 +#define CSR_PMPADDR26 0x3ca +#define CSR_PMPADDR27 0x3cb +#define CSR_PMPADDR28 0x3cc +#define CSR_PMPADDR29 0x3cd +#define CSR_PMPADDR30 0x3ce +#define CSR_PMPADDR31 0x3cf +#define CSR_PMPADDR32 0x3d0 +#define CSR_PMPADDR33 0x3d1 +#define CSR_PMPADDR34 0x3d2 +#define CSR_PMPADDR35 0x3d3 +#define CSR_PMPADDR36 0x3d4 +#define CSR_PMPADDR37 0x3d5 +#define CSR_PMPADDR38 0x3d6 +#define CSR_PMPADDR39 0x3d7 +#define CSR_PMPADDR40 0x3d8 +#define CSR_PMPADDR41 0x3d9 +#define CSR_PMPADDR42 0x3da +#define CSR_PMPADDR43 0x3db +#define CSR_PMPADDR44 0x3dc +#define CSR_PMPADDR45 0x3dd +#define CSR_PMPADDR46 0x3de +#define CSR_PMPADDR47 0x3df +#define CSR_PMPADDR48 0x3e0 +#define CSR_PMPADDR49 0x3e1 +#define CSR_PMPADDR50 0x3e2 +#define CSR_PMPADDR51 0x3e3 +#define CSR_PMPADDR52 0x3e4 +#define CSR_PMPADDR53 0x3e5 +#define CSR_PMPADDR54 0x3e6 +#define CSR_PMPADDR55 0x3e7 +#define CSR_PMPADDR56 0x3e8 +#define CSR_PMPADDR57 0x3e9 +#define CSR_PMPADDR58 0x3ea +#define CSR_PMPADDR59 0x3eb +#define CSR_PMPADDR60 0x3ec +#define CSR_PMPADDR61 0x3ed +#define CSR_PMPADDR62 0x3ee +#define CSR_PMPADDR63 0x3ef +#define CSR_MSECCFG 0x747 +#define CSR_TSELECT 0x7a0 +#define CSR_TDATA1 0x7a1 +#define CSR_TDATA2 0x7a2 +#define CSR_TDATA3 0x7a3 +#define CSR_TINFO 0x7a4 +#define CSR_TCONTROL 0x7a5 +#define CSR_MCONTEXT 0x7a8 +#define CSR_MSCONTEXT 0x7aa +#define CSR_DCSR 0x7b0 +#define CSR_DPC 0x7b1 +#define CSR_DSCRATCH0 0x7b2 +#define CSR_DSCRATCH1 0x7b3 +#define CSR_MCYCLE 0xb00 +#define CSR_MINSTRET 0xb02 +#define CSR_MHPMCOUNTER3 0xb03 +#define CSR_MHPMCOUNTER4 0xb04 +#define CSR_MHPMCOUNTER5 0xb05 +#define CSR_MHPMCOUNTER6 0xb06 +#define CSR_MHPMCOUNTER7 0xb07 +#define CSR_MHPMCOUNTER8 0xb08 +#define CSR_MHPMCOUNTER9 0xb09 +#define CSR_MHPMCOUNTER10 0xb0a +#define CSR_MHPMCOUNTER11 0xb0b +#define CSR_MHPMCOUNTER12 0xb0c +#define CSR_MHPMCOUNTER13 0xb0d +#define CSR_MHPMCOUNTER14 0xb0e +#define CSR_MHPMCOUNTER15 0xb0f +#define CSR_MHPMCOUNTER16 0xb10 +#define CSR_MHPMCOUNTER17 0xb11 +#define CSR_MHPMCOUNTER18 0xb12 +#define CSR_MHPMCOUNTER19 0xb13 +#define CSR_MHPMCOUNTER20 0xb14 +#define CSR_MHPMCOUNTER21 0xb15 +#define CSR_MHPMCOUNTER22 0xb16 +#define CSR_MHPMCOUNTER23 0xb17 +#define CSR_MHPMCOUNTER24 0xb18 +#define CSR_MHPMCOUNTER25 0xb19 +#define CSR_MHPMCOUNTER26 0xb1a +#define CSR_MHPMCOUNTER27 0xb1b +#define CSR_MHPMCOUNTER28 0xb1c +#define CSR_MHPMCOUNTER29 0xb1d +#define CSR_MHPMCOUNTER30 0xb1e +#define CSR_MHPMCOUNTER31 0xb1f +#define CSR_MHPMEVENT3 0x323 +#define CSR_MHPMEVENT4 0x324 +#define CSR_MHPMEVENT5 0x325 +#define CSR_MHPMEVENT6 0x326 +#define CSR_MHPMEVENT7 0x327 +#define CSR_MHPMEVENT8 0x328 +#define CSR_MHPMEVENT9 0x329 +#define CSR_MHPMEVENT10 0x32a +#define CSR_MHPMEVENT11 0x32b +#define CSR_MHPMEVENT12 0x32c +#define CSR_MHPMEVENT13 0x32d +#define CSR_MHPMEVENT14 0x32e +#define CSR_MHPMEVENT15 0x32f +#define CSR_MHPMEVENT16 0x330 +#define CSR_MHPMEVENT17 0x331 +#define CSR_MHPMEVENT18 0x332 +#define CSR_MHPMEVENT19 0x333 +#define CSR_MHPMEVENT20 0x334 +#define CSR_MHPMEVENT21 0x335 +#define CSR_MHPMEVENT22 0x336 +#define CSR_MHPMEVENT23 0x337 +#define CSR_MHPMEVENT24 0x338 +#define CSR_MHPMEVENT25 0x339 +#define CSR_MHPMEVENT26 0x33a +#define CSR_MHPMEVENT27 0x33b +#define CSR_MHPMEVENT28 0x33c +#define CSR_MHPMEVENT29 0x33d +#define CSR_MHPMEVENT30 0x33e +#define CSR_MHPMEVENT31 0x33f +#define CSR_MVENDORID 0xf11 +#define CSR_MARCHID 0xf12 +#define CSR_MIMPID 0xf13 +#define CSR_MHARTID 0xf14 +#define CSR_MCONFIGPTR 0xf15 +#define CSR_STIMECMPH 0x15d +#define CSR_VSTIMECMPH 0x25d +#define CSR_HTIMEDELTAH 0x615 +#define CSR_HENVCFGH 0x61a +#define CSR_HSTATEEN0H 0x61c +#define CSR_HSTATEEN1H 0x61d +#define CSR_HSTATEEN2H 0x61e +#define CSR_HSTATEEN3H 0x61f +#define CSR_CYCLEH 0xc80 +#define CSR_TIMEH 0xc81 +#define CSR_INSTRETH 0xc82 +#define CSR_HPMCOUNTER3H 0xc83 +#define CSR_HPMCOUNTER4H 0xc84 +#define CSR_HPMCOUNTER5H 0xc85 +#define CSR_HPMCOUNTER6H 0xc86 +#define CSR_HPMCOUNTER7H 0xc87 +#define CSR_HPMCOUNTER8H 0xc88 +#define CSR_HPMCOUNTER9H 0xc89 +#define CSR_HPMCOUNTER10H 0xc8a +#define CSR_HPMCOUNTER11H 0xc8b +#define CSR_HPMCOUNTER12H 0xc8c +#define CSR_HPMCOUNTER13H 0xc8d +#define CSR_HPMCOUNTER14H 0xc8e +#define CSR_HPMCOUNTER15H 0xc8f +#define CSR_HPMCOUNTER16H 0xc90 +#define CSR_HPMCOUNTER17H 0xc91 +#define CSR_HPMCOUNTER18H 0xc92 +#define CSR_HPMCOUNTER19H 0xc93 +#define CSR_HPMCOUNTER20H 0xc94 +#define CSR_HPMCOUNTER21H 0xc95 +#define CSR_HPMCOUNTER22H 0xc96 +#define CSR_HPMCOUNTER23H 0xc97 +#define CSR_HPMCOUNTER24H 0xc98 +#define CSR_HPMCOUNTER25H 0xc99 +#define CSR_HPMCOUNTER26H 0xc9a +#define CSR_HPMCOUNTER27H 0xc9b +#define CSR_HPMCOUNTER28H 0xc9c +#define CSR_HPMCOUNTER29H 0xc9d +#define CSR_HPMCOUNTER30H 0xc9e +#define CSR_HPMCOUNTER31H 0xc9f +#define CSR_MSTATUSH 0x310 +#define CSR_MENVCFGH 0x31a +#define CSR_MSTATEEN0H 0x31c +#define CSR_MSTATEEN1H 0x31d +#define CSR_MSTATEEN2H 0x31e +#define CSR_MSTATEEN3H 0x31f +#define CSR_MHPMEVENT3H 0x723 +#define CSR_MHPMEVENT4H 0x724 +#define CSR_MHPMEVENT5H 0x725 +#define CSR_MHPMEVENT6H 0x726 +#define CSR_MHPMEVENT7H 0x727 +#define CSR_MHPMEVENT8H 0x728 +#define CSR_MHPMEVENT9H 0x729 +#define CSR_MHPMEVENT10H 0x72a +#define CSR_MHPMEVENT11H 0x72b +#define CSR_MHPMEVENT12H 0x72c +#define CSR_MHPMEVENT13H 0x72d +#define CSR_MHPMEVENT14H 0x72e +#define CSR_MHPMEVENT15H 0x72f +#define CSR_MHPMEVENT16H 0x730 +#define CSR_MHPMEVENT17H 0x731 +#define CSR_MHPMEVENT18H 0x732 +#define CSR_MHPMEVENT19H 0x733 +#define CSR_MHPMEVENT20H 0x734 +#define CSR_MHPMEVENT21H 0x735 +#define CSR_MHPMEVENT22H 0x736 +#define CSR_MHPMEVENT23H 0x737 +#define CSR_MHPMEVENT24H 0x738 +#define CSR_MHPMEVENT25H 0x739 +#define CSR_MHPMEVENT26H 0x73a +#define CSR_MHPMEVENT27H 0x73b +#define CSR_MHPMEVENT28H 0x73c +#define CSR_MHPMEVENT29H 0x73d +#define CSR_MHPMEVENT30H 0x73e +#define CSR_MHPMEVENT31H 0x73f +#define CSR_MSECCFGH 0x757 +#define CSR_MCYCLEH 0xb80 +#define CSR_MINSTRETH 0xb82 +#define CSR_MHPMCOUNTER3H 0xb83 +#define CSR_MHPMCOUNTER4H 0xb84 +#define CSR_MHPMCOUNTER5H 0xb85 +#define CSR_MHPMCOUNTER6H 0xb86 +#define CSR_MHPMCOUNTER7H 0xb87 +#define CSR_MHPMCOUNTER8H 0xb88 +#define CSR_MHPMCOUNTER9H 0xb89 +#define CSR_MHPMCOUNTER10H 0xb8a +#define CSR_MHPMCOUNTER11H 0xb8b +#define CSR_MHPMCOUNTER12H 0xb8c +#define CSR_MHPMCOUNTER13H 0xb8d +#define CSR_MHPMCOUNTER14H 0xb8e +#define CSR_MHPMCOUNTER15H 0xb8f +#define CSR_MHPMCOUNTER16H 0xb90 +#define CSR_MHPMCOUNTER17H 0xb91 +#define CSR_MHPMCOUNTER18H 0xb92 +#define CSR_MHPMCOUNTER19H 0xb93 +#define CSR_MHPMCOUNTER20H 0xb94 +#define CSR_MHPMCOUNTER21H 0xb95 +#define CSR_MHPMCOUNTER22H 0xb96 +#define CSR_MHPMCOUNTER23H 0xb97 +#define CSR_MHPMCOUNTER24H 0xb98 +#define CSR_MHPMCOUNTER25H 0xb99 +#define CSR_MHPMCOUNTER26H 0xb9a +#define CSR_MHPMCOUNTER27H 0xb9b +#define CSR_MHPMCOUNTER28H 0xb9c +#define CSR_MHPMCOUNTER29H 0xb9d +#define CSR_MHPMCOUNTER30H 0xb9e +#define CSR_MHPMCOUNTER31H 0xb9f + +#define CAUSE_MISALIGNED_FETCH 0x0 +#define CAUSE_FETCH_ACCESS 0x1 +#define CAUSE_ILLEGAL_INSTRUCTION 0x2 +#define CAUSE_BREAKPOINT 0x3 +#define CAUSE_MISALIGNED_LOAD 0x4 +#define CAUSE_LOAD_ACCESS 0x5 +#define CAUSE_MISALIGNED_STORE 0x6 +#define CAUSE_STORE_ACCESS 0x7 +#define CAUSE_USER_ECALL 0x8 +#define CAUSE_SUPERVISOR_ECALL 0x9 +#define CAUSE_VIRTUAL_SUPERVISOR_ECALL 0xa +#define CAUSE_MACHINE_ECALL 0xb +#define CAUSE_FETCH_PAGE_FAULT 0xc +#define CAUSE_LOAD_PAGE_FAULT 0xd +#define CAUSE_STORE_PAGE_FAULT 0xf +#define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14 +#define CAUSE_LOAD_GUEST_PAGE_FAULT 0x15 +#define CAUSE_VIRTUAL_INSTRUCTION 0x16 +#define CAUSE_STORE_GUEST_PAGE_FAULT 0x17 + +#define INSN_FIELD_RD 0xf80 +#define INSN_FIELD_RT 0xf8000 +#define INSN_FIELD_RS1 0xf8000 +#define INSN_FIELD_RS2 0x1f00000 +#define INSN_FIELD_RS3 0xf8000000 +#define INSN_FIELD_AQRL 0x6000000 +#define INSN_FIELD_AQ 0x4000000 +#define INSN_FIELD_RL 0x2000000 +#define INSN_FIELD_FM 0xf0000000 +#define INSN_FIELD_PRED 0xf000000 +#define INSN_FIELD_SUCC 0xf00000 +#define INSN_FIELD_RM 0x7000 +#define INSN_FIELD_FUNCT3 0x7000 +#define INSN_FIELD_FUNCT2 0x6000000 +#define INSN_FIELD_IMM20 0xfffff000 +#define INSN_FIELD_JIMM20 0xfffff000 +#define INSN_FIELD_IMM12 0xfff00000 +#define INSN_FIELD_CSR 0xfff00000 +#define INSN_FIELD_IMM12HI 0xfe000000 +#define INSN_FIELD_BIMM12HI 0xfe000000 +#define INSN_FIELD_IMM12LO 0xf80 +#define INSN_FIELD_BIMM12LO 0xf80 +#define INSN_FIELD_ZIMM 0xf8000 +#define INSN_FIELD_SHAMT 0x7f00000 +#define INSN_FIELD_SHAMTW 0x1f00000 +#define INSN_FIELD_SHAMTW4 0xf00000 +#define INSN_FIELD_SHAMTD 0x3f00000 +#define INSN_FIELD_BS 0xc0000000 +#define INSN_FIELD_RNUM 0xf00000 +#define INSN_FIELD_RC 0x3e000000 +#define INSN_FIELD_IMM2 0x300000 +#define INSN_FIELD_IMM3 0x700000 +#define INSN_FIELD_IMM4 0xf00000 +#define INSN_FIELD_IMM5 0x1f00000 +#define INSN_FIELD_IMM6 0x3f00000 +#define INSN_FIELD_OPCODE 0x7f +#define INSN_FIELD_FUNCT7 0xfe000000 +#define INSN_FIELD_VD 0xf80 +#define INSN_FIELD_VS3 0xf80 +#define INSN_FIELD_VS1 0xf8000 +#define INSN_FIELD_VS2 0x1f00000 +#define INSN_FIELD_VM 0x2000000 +#define INSN_FIELD_WD 0x4000000 +#define INSN_FIELD_AMOOP 0xf8000000 +#define INSN_FIELD_NF 0xe0000000 +#define INSN_FIELD_SIMM5 0xf8000 +#define INSN_FIELD_ZIMM10 0x3ff00000 +#define INSN_FIELD_ZIMM11 0x7ff00000 +#define INSN_FIELD_C_NZUIMM10 0x1fe0 +#define INSN_FIELD_C_UIMM7LO 0x60 +#define INSN_FIELD_C_UIMM7HI 0x1c00 +#define INSN_FIELD_C_UIMM8LO 0x60 +#define INSN_FIELD_C_UIMM8HI 0x1c00 +#define INSN_FIELD_C_UIMM9LO 0x60 +#define INSN_FIELD_C_UIMM9HI 0x1c00 +#define INSN_FIELD_C_NZIMM6LO 0x7c +#define INSN_FIELD_C_NZIMM6HI 0x1000 +#define INSN_FIELD_C_IMM6LO 0x7c +#define INSN_FIELD_C_IMM6HI 0x1000 +#define INSN_FIELD_C_NZIMM10HI 0x1000 +#define INSN_FIELD_C_NZIMM10LO 0x7c +#define INSN_FIELD_C_NZIMM18HI 0x1000 +#define INSN_FIELD_C_NZIMM18LO 0x7c +#define INSN_FIELD_C_IMM12 0x1ffc +#define INSN_FIELD_C_BIMM9LO 0x7c +#define INSN_FIELD_C_BIMM9HI 0x1c00 +#define INSN_FIELD_C_NZUIMM5 0x7c +#define INSN_FIELD_C_NZUIMM6LO 0x7c +#define INSN_FIELD_C_NZUIMM6HI 0x1000 +#define INSN_FIELD_C_UIMM8SPLO 0x7c +#define INSN_FIELD_C_UIMM8SPHI 0x1000 +#define INSN_FIELD_C_UIMM8SP_S 0x1f80 +#define INSN_FIELD_C_UIMM10SPLO 0x7c +#define INSN_FIELD_C_UIMM10SPHI 0x1000 +#define INSN_FIELD_C_UIMM9SPLO 0x7c +#define INSN_FIELD_C_UIMM9SPHI 0x1000 +#define INSN_FIELD_C_UIMM10SP_S 0x1f80 +#define INSN_FIELD_C_UIMM9SP_S 0x1f80 +#define INSN_FIELD_RS1_P 0x380 +#define INSN_FIELD_RS2_P 0x1c +#define INSN_FIELD_RD_P 0x1c +#define INSN_FIELD_RD_RS1_N0 0xf80 +#define INSN_FIELD_RD_RS1_P 0x380 +#define INSN_FIELD_RD_RS1 0xf80 +#define INSN_FIELD_RD_N2 0xf80 +#define INSN_FIELD_RD_N0 0xf80 +#define INSN_FIELD_RS1_N0 0xf80 +#define INSN_FIELD_C_RS2_N0 0x7c +#define INSN_FIELD_C_RS1_N0 0xf80 +#define INSN_FIELD_C_RS2 0x7c +#endif +#ifdef DECLARE_INSN +DECLARE_INSN(add, MATCH_ADD, MASK_ADD) +DECLARE_INSN(add16, MATCH_ADD16, MASK_ADD16) +DECLARE_INSN(add32, MATCH_ADD32, MASK_ADD32) +DECLARE_INSN(add64, MATCH_ADD64, MASK_ADD64) +DECLARE_INSN(add8, MATCH_ADD8, MASK_ADD8) +DECLARE_INSN(add_uw, MATCH_ADD_UW, MASK_ADD_UW) +DECLARE_INSN(addd, MATCH_ADDD, MASK_ADDD) +DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) +DECLARE_INSN(addid, MATCH_ADDID, MASK_ADDID) +DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) +DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) +DECLARE_INSN(aes32dsi, MATCH_AES32DSI, MASK_AES32DSI) +DECLARE_INSN(aes32dsmi, MATCH_AES32DSMI, MASK_AES32DSMI) +DECLARE_INSN(aes32esi, MATCH_AES32ESI, MASK_AES32ESI) +DECLARE_INSN(aes32esmi, MATCH_AES32ESMI, MASK_AES32ESMI) +DECLARE_INSN(aes64ds, MATCH_AES64DS, MASK_AES64DS) +DECLARE_INSN(aes64dsm, MATCH_AES64DSM, MASK_AES64DSM) +DECLARE_INSN(aes64es, MATCH_AES64ES, MASK_AES64ES) +DECLARE_INSN(aes64esm, MATCH_AES64ESM, MASK_AES64ESM) +DECLARE_INSN(aes64im, MATCH_AES64IM, MASK_AES64IM) +DECLARE_INSN(aes64ks1i, MATCH_AES64KS1I, MASK_AES64KS1I) +DECLARE_INSN(aes64ks2, MATCH_AES64KS2, MASK_AES64KS2) +DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) +DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) +DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) +DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) +DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) +DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) +DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) +DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W) +DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D) +DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W) +DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D) +DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W) +DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D) +DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W) +DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D) +DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W) +DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D) +DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W) +DECLARE_INSN(and, MATCH_AND, MASK_AND) +DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) +DECLARE_INSN(andn, MATCH_ANDN, MASK_ANDN) +DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) +DECLARE_INSN(ave, MATCH_AVE, MASK_AVE) +DECLARE_INSN(bclr, MATCH_BCLR, MASK_BCLR) +DECLARE_INSN(bclri, MATCH_BCLRI, MASK_BCLRI) +DECLARE_INSN(bcompress, MATCH_BCOMPRESS, MASK_BCOMPRESS) +DECLARE_INSN(bcompressw, MATCH_BCOMPRESSW, MASK_BCOMPRESSW) +DECLARE_INSN(bdecompress, MATCH_BDECOMPRESS, MASK_BDECOMPRESS) +DECLARE_INSN(bdecompressw, MATCH_BDECOMPRESSW, MASK_BDECOMPRESSW) +DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) +DECLARE_INSN(bext, MATCH_BEXT, MASK_BEXT) +DECLARE_INSN(bexti, MATCH_BEXTI, MASK_BEXTI) +DECLARE_INSN(bfp, MATCH_BFP, MASK_BFP) +DECLARE_INSN(bfpw, MATCH_BFPW, MASK_BFPW) +DECLARE_INSN(bge, MATCH_BGE, MASK_BGE) +DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU) +DECLARE_INSN(binv, MATCH_BINV, MASK_BINV) +DECLARE_INSN(binvi, MATCH_BINVI, MASK_BINVI) +DECLARE_INSN(bitrev, MATCH_BITREV, MASK_BITREV) +DECLARE_INSN(bitrevi, MATCH_BITREVI, MASK_BITREVI) +DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) +DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) +DECLARE_INSN(bmatflip, MATCH_BMATFLIP, MASK_BMATFLIP) +DECLARE_INSN(bmator, MATCH_BMATOR, MASK_BMATOR) +DECLARE_INSN(bmatxor, MATCH_BMATXOR, MASK_BMATXOR) +DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) +DECLARE_INSN(bpick, MATCH_BPICK, MASK_BPICK) +DECLARE_INSN(bset, MATCH_BSET, MASK_BSET) +DECLARE_INSN(bseti, MATCH_BSETI, MASK_BSETI) +DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) +DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) +DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) +DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) +DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) +DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) +DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND) +DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI) +DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) +DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) +DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) +DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) +DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) +DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) +DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP) +DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD) +DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) +DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) +DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) +DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) +DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) +DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) +DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) +DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) +DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) +DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) +DECLARE_INSN(c_lq, MATCH_C_LQ, MASK_C_LQ) +DECLARE_INSN(c_lqsp, MATCH_C_LQSP, MASK_C_LQSP) +DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) +DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) +DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) +DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) +DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) +DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR) +DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) +DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) +DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) +DECLARE_INSN(c_sq, MATCH_C_SQ, MASK_C_SQ) +DECLARE_INSN(c_sqsp, MATCH_C_SQSP, MASK_C_SQSP) +DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI) +DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI) +DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB) +DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW) +DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) +DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) +DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR) +DECLARE_INSN(cbo_clean, MATCH_CBO_CLEAN, MASK_CBO_CLEAN) +DECLARE_INSN(cbo_flush, MATCH_CBO_FLUSH, MASK_CBO_FLUSH) +DECLARE_INSN(cbo_inval, MATCH_CBO_INVAL, MASK_CBO_INVAL) +DECLARE_INSN(cbo_zero, MATCH_CBO_ZERO, MASK_CBO_ZERO) +DECLARE_INSN(clmul, MATCH_CLMUL, MASK_CLMUL) +DECLARE_INSN(clmulh, MATCH_CLMULH, MASK_CLMULH) +DECLARE_INSN(clmulr, MATCH_CLMULR, MASK_CLMULR) +DECLARE_INSN(clo16, MATCH_CLO16, MASK_CLO16) +DECLARE_INSN(clo32, MATCH_CLO32, MASK_CLO32) +DECLARE_INSN(clo8, MATCH_CLO8, MASK_CLO8) +DECLARE_INSN(clrs16, MATCH_CLRS16, MASK_CLRS16) +DECLARE_INSN(clrs32, MATCH_CLRS32, MASK_CLRS32) +DECLARE_INSN(clrs8, MATCH_CLRS8, MASK_CLRS8) +DECLARE_INSN(clz, MATCH_CLZ, MASK_CLZ) +DECLARE_INSN(clz16, MATCH_CLZ16, MASK_CLZ16) +DECLARE_INSN(clz32, MATCH_CLZ32, MASK_CLZ32) +DECLARE_INSN(clz8, MATCH_CLZ8, MASK_CLZ8) +DECLARE_INSN(clzw, MATCH_CLZW, MASK_CLZW) +DECLARE_INSN(cmix, MATCH_CMIX, MASK_CMIX) +DECLARE_INSN(cmov, MATCH_CMOV, MASK_CMOV) +DECLARE_INSN(cmpeq16, MATCH_CMPEQ16, MASK_CMPEQ16) +DECLARE_INSN(cmpeq8, MATCH_CMPEQ8, MASK_CMPEQ8) +DECLARE_INSN(cpop, MATCH_CPOP, MASK_CPOP) +DECLARE_INSN(cpopw, MATCH_CPOPW, MASK_CPOPW) +DECLARE_INSN(cras16, MATCH_CRAS16, MASK_CRAS16) +DECLARE_INSN(cras32, MATCH_CRAS32, MASK_CRAS32) +DECLARE_INSN(crc32_b, MATCH_CRC32_B, MASK_CRC32_B) +DECLARE_INSN(crc32_d, MATCH_CRC32_D, MASK_CRC32_D) +DECLARE_INSN(crc32_h, MATCH_CRC32_H, MASK_CRC32_H) +DECLARE_INSN(crc32_w, MATCH_CRC32_W, MASK_CRC32_W) +DECLARE_INSN(crc32c_b, MATCH_CRC32C_B, MASK_CRC32C_B) +DECLARE_INSN(crc32c_d, MATCH_CRC32C_D, MASK_CRC32C_D) +DECLARE_INSN(crc32c_h, MATCH_CRC32C_H, MASK_CRC32C_H) +DECLARE_INSN(crc32c_w, MATCH_CRC32C_W, MASK_CRC32C_W) +DECLARE_INSN(crsa16, MATCH_CRSA16, MASK_CRSA16) +DECLARE_INSN(crsa32, MATCH_CRSA32, MASK_CRSA32) +DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) +DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) +DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) +DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) +DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) +DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI) +DECLARE_INSN(ctz, MATCH_CTZ, MASK_CTZ) +DECLARE_INSN(ctzw, MATCH_CTZW, MASK_CTZW) +DECLARE_INSN(div, MATCH_DIV, MASK_DIV) +DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU) +DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW) +DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW) +DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) +DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) +DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) +DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D) +DECLARE_INSN(fadd_h, MATCH_FADD_H, MASK_FADD_H) +DECLARE_INSN(fadd_q, MATCH_FADD_Q, MASK_FADD_Q) +DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S) +DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) +DECLARE_INSN(fclass_h, MATCH_FCLASS_H, MASK_FCLASS_H) +DECLARE_INSN(fclass_q, MATCH_FCLASS_Q, MASK_FCLASS_Q) +DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) +DECLARE_INSN(fcvt_d_h, MATCH_FCVT_D_H, MASK_FCVT_D_H) +DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) +DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) +DECLARE_INSN(fcvt_d_q, MATCH_FCVT_D_Q, MASK_FCVT_D_Q) +DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) +DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) +DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) +DECLARE_INSN(fcvt_h_d, MATCH_FCVT_H_D, MASK_FCVT_H_D) +DECLARE_INSN(fcvt_h_l, MATCH_FCVT_H_L, MASK_FCVT_H_L) +DECLARE_INSN(fcvt_h_lu, MATCH_FCVT_H_LU, MASK_FCVT_H_LU) +DECLARE_INSN(fcvt_h_q, MATCH_FCVT_H_Q, MASK_FCVT_H_Q) +DECLARE_INSN(fcvt_h_s, MATCH_FCVT_H_S, MASK_FCVT_H_S) +DECLARE_INSN(fcvt_h_w, MATCH_FCVT_H_W, MASK_FCVT_H_W) +DECLARE_INSN(fcvt_h_wu, MATCH_FCVT_H_WU, MASK_FCVT_H_WU) +DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) +DECLARE_INSN(fcvt_l_h, MATCH_FCVT_L_H, MASK_FCVT_L_H) +DECLARE_INSN(fcvt_l_q, MATCH_FCVT_L_Q, MASK_FCVT_L_Q) +DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) +DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) +DECLARE_INSN(fcvt_lu_h, MATCH_FCVT_LU_H, MASK_FCVT_LU_H) +DECLARE_INSN(fcvt_lu_q, MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q) +DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) +DECLARE_INSN(fcvt_q_d, MATCH_FCVT_Q_D, MASK_FCVT_Q_D) +DECLARE_INSN(fcvt_q_h, MATCH_FCVT_Q_H, MASK_FCVT_Q_H) +DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L) +DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU) +DECLARE_INSN(fcvt_q_s, MATCH_FCVT_Q_S, MASK_FCVT_Q_S) +DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W) +DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU) +DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) +DECLARE_INSN(fcvt_s_h, MATCH_FCVT_S_H, MASK_FCVT_S_H) +DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) +DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) +DECLARE_INSN(fcvt_s_q, MATCH_FCVT_S_Q, MASK_FCVT_S_Q) +DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) +DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) +DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) +DECLARE_INSN(fcvt_w_h, MATCH_FCVT_W_H, MASK_FCVT_W_H) +DECLARE_INSN(fcvt_w_q, MATCH_FCVT_W_Q, MASK_FCVT_W_Q) +DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) +DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) +DECLARE_INSN(fcvt_wu_h, MATCH_FCVT_WU_H, MASK_FCVT_WU_H) +DECLARE_INSN(fcvt_wu_q, MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q) +DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) +DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D) +DECLARE_INSN(fdiv_h, MATCH_FDIV_H, MASK_FDIV_H) +DECLARE_INSN(fdiv_q, MATCH_FDIV_Q, MASK_FDIV_Q) +DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S) +DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE) +DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I) +DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) +DECLARE_INSN(feq_h, MATCH_FEQ_H, MASK_FEQ_H) +DECLARE_INSN(feq_q, MATCH_FEQ_Q, MASK_FEQ_Q) +DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) +DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) +DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) +DECLARE_INSN(fle_h, MATCH_FLE_H, MASK_FLE_H) +DECLARE_INSN(fle_q, MATCH_FLE_Q, MASK_FLE_Q) +DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) +DECLARE_INSN(flh, MATCH_FLH, MASK_FLH) +DECLARE_INSN(flq, MATCH_FLQ, MASK_FLQ) +DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) +DECLARE_INSN(flt_h, MATCH_FLT_H, MASK_FLT_H) +DECLARE_INSN(flt_q, MATCH_FLT_Q, MASK_FLT_Q) +DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) +DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) +DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) +DECLARE_INSN(fmadd_h, MATCH_FMADD_H, MASK_FMADD_H) +DECLARE_INSN(fmadd_q, MATCH_FMADD_Q, MASK_FMADD_Q) +DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) +DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) +DECLARE_INSN(fmax_h, MATCH_FMAX_H, MASK_FMAX_H) +DECLARE_INSN(fmax_q, MATCH_FMAX_Q, MASK_FMAX_Q) +DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S) +DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D) +DECLARE_INSN(fmin_h, MATCH_FMIN_H, MASK_FMIN_H) +DECLARE_INSN(fmin_q, MATCH_FMIN_Q, MASK_FMIN_Q) +DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) +DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) +DECLARE_INSN(fmsub_h, MATCH_FMSUB_H, MASK_FMSUB_H) +DECLARE_INSN(fmsub_q, MATCH_FMSUB_Q, MASK_FMSUB_Q) +DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) +DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D) +DECLARE_INSN(fmul_h, MATCH_FMUL_H, MASK_FMUL_H) +DECLARE_INSN(fmul_q, MATCH_FMUL_Q, MASK_FMUL_Q) +DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) +DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) +DECLARE_INSN(fmv_h_x, MATCH_FMV_H_X, MASK_FMV_H_X) +DECLARE_INSN(fmv_w_x, MATCH_FMV_W_X, MASK_FMV_W_X) +DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) +DECLARE_INSN(fmv_x_h, MATCH_FMV_X_H, MASK_FMV_X_H) +DECLARE_INSN(fmv_x_w, MATCH_FMV_X_W, MASK_FMV_X_W) +DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) +DECLARE_INSN(fnmadd_h, MATCH_FNMADD_H, MASK_FNMADD_H) +DECLARE_INSN(fnmadd_q, MATCH_FNMADD_Q, MASK_FNMADD_Q) +DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S) +DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) +DECLARE_INSN(fnmsub_h, MATCH_FNMSUB_H, MASK_FNMSUB_H) +DECLARE_INSN(fnmsub_q, MATCH_FNMSUB_Q, MASK_FNMSUB_Q) +DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) +DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) +DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D) +DECLARE_INSN(fsgnj_h, MATCH_FSGNJ_H, MASK_FSGNJ_H) +DECLARE_INSN(fsgnj_q, MATCH_FSGNJ_Q, MASK_FSGNJ_Q) +DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S) +DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) +DECLARE_INSN(fsgnjn_h, MATCH_FSGNJN_H, MASK_FSGNJN_H) +DECLARE_INSN(fsgnjn_q, MATCH_FSGNJN_Q, MASK_FSGNJN_Q) +DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S) +DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D) +DECLARE_INSN(fsgnjx_h, MATCH_FSGNJX_H, MASK_FSGNJX_H) +DECLARE_INSN(fsgnjx_q, MATCH_FSGNJX_Q, MASK_FSGNJX_Q) +DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) +DECLARE_INSN(fsh, MATCH_FSH, MASK_FSH) +DECLARE_INSN(fsl, MATCH_FSL, MASK_FSL) +DECLARE_INSN(fslw, MATCH_FSLW, MASK_FSLW) +DECLARE_INSN(fsq, MATCH_FSQ, MASK_FSQ) +DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) +DECLARE_INSN(fsqrt_h, MATCH_FSQRT_H, MASK_FSQRT_H) +DECLARE_INSN(fsqrt_q, MATCH_FSQRT_Q, MASK_FSQRT_Q) +DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S) +DECLARE_INSN(fsr, MATCH_FSR, MASK_FSR) +DECLARE_INSN(fsri, MATCH_FSRI, MASK_FSRI) +DECLARE_INSN(fsriw, MATCH_FSRIW, MASK_FSRIW) +DECLARE_INSN(fsrw, MATCH_FSRW, MASK_FSRW) +DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) +DECLARE_INSN(fsub_h, MATCH_FSUB_H, MASK_FSUB_H) +DECLARE_INSN(fsub_q, MATCH_FSUB_Q, MASK_FSUB_Q) +DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S) +DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) +DECLARE_INSN(gorc, MATCH_GORC, MASK_GORC) +DECLARE_INSN(gorci, MATCH_GORCI, MASK_GORCI) +DECLARE_INSN(gorciw, MATCH_GORCIW, MASK_GORCIW) +DECLARE_INSN(gorcw, MATCH_GORCW, MASK_GORCW) +DECLARE_INSN(grev, MATCH_GREV, MASK_GREV) +DECLARE_INSN(grevi, MATCH_GREVI, MASK_GREVI) +DECLARE_INSN(greviw, MATCH_GREVIW, MASK_GREVIW) +DECLARE_INSN(grevw, MATCH_GREVW, MASK_GREVW) +DECLARE_INSN(hfence_gvma, MATCH_HFENCE_GVMA, MASK_HFENCE_GVMA) +DECLARE_INSN(hfence_vvma, MATCH_HFENCE_VVMA, MASK_HFENCE_VVMA) +DECLARE_INSN(hinval_gvma, MATCH_HINVAL_GVMA, MASK_HINVAL_GVMA) +DECLARE_INSN(hinval_vvma, MATCH_HINVAL_VVMA, MASK_HINVAL_VVMA) +DECLARE_INSN(hlv_b, MATCH_HLV_B, MASK_HLV_B) +DECLARE_INSN(hlv_bu, MATCH_HLV_BU, MASK_HLV_BU) +DECLARE_INSN(hlv_d, MATCH_HLV_D, MASK_HLV_D) +DECLARE_INSN(hlv_h, MATCH_HLV_H, MASK_HLV_H) +DECLARE_INSN(hlv_hu, MATCH_HLV_HU, MASK_HLV_HU) +DECLARE_INSN(hlv_w, MATCH_HLV_W, MASK_HLV_W) +DECLARE_INSN(hlv_wu, MATCH_HLV_WU, MASK_HLV_WU) +DECLARE_INSN(hlvx_hu, MATCH_HLVX_HU, MASK_HLVX_HU) +DECLARE_INSN(hlvx_wu, MATCH_HLVX_WU, MASK_HLVX_WU) +DECLARE_INSN(hsv_b, MATCH_HSV_B, MASK_HSV_B) +DECLARE_INSN(hsv_d, MATCH_HSV_D, MASK_HSV_D) +DECLARE_INSN(hsv_h, MATCH_HSV_H, MASK_HSV_H) +DECLARE_INSN(hsv_w, MATCH_HSV_W, MASK_HSV_W) +DECLARE_INSN(insb, MATCH_INSB, MASK_INSB) +DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) +DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) +DECLARE_INSN(kabs16, MATCH_KABS16, MASK_KABS16) +DECLARE_INSN(kabs32, MATCH_KABS32, MASK_KABS32) +DECLARE_INSN(kabs8, MATCH_KABS8, MASK_KABS8) +DECLARE_INSN(kabsw, MATCH_KABSW, MASK_KABSW) +DECLARE_INSN(kadd16, MATCH_KADD16, MASK_KADD16) +DECLARE_INSN(kadd32, MATCH_KADD32, MASK_KADD32) +DECLARE_INSN(kadd64, MATCH_KADD64, MASK_KADD64) +DECLARE_INSN(kadd8, MATCH_KADD8, MASK_KADD8) +DECLARE_INSN(kaddh, MATCH_KADDH, MASK_KADDH) +DECLARE_INSN(kaddw, MATCH_KADDW, MASK_KADDW) +DECLARE_INSN(kcras16, MATCH_KCRAS16, MASK_KCRAS16) +DECLARE_INSN(kcras32, MATCH_KCRAS32, MASK_KCRAS32) +DECLARE_INSN(kcrsa16, MATCH_KCRSA16, MASK_KCRSA16) +DECLARE_INSN(kcrsa32, MATCH_KCRSA32, MASK_KCRSA32) +DECLARE_INSN(kdmabb, MATCH_KDMABB, MASK_KDMABB) +DECLARE_INSN(kdmabb16, MATCH_KDMABB16, MASK_KDMABB16) +DECLARE_INSN(kdmabt, MATCH_KDMABT, MASK_KDMABT) +DECLARE_INSN(kdmabt16, MATCH_KDMABT16, MASK_KDMABT16) +DECLARE_INSN(kdmatt, MATCH_KDMATT, MASK_KDMATT) +DECLARE_INSN(kdmatt16, MATCH_KDMATT16, MASK_KDMATT16) +DECLARE_INSN(kdmbb, MATCH_KDMBB, MASK_KDMBB) +DECLARE_INSN(kdmbb16, MATCH_KDMBB16, MASK_KDMBB16) +DECLARE_INSN(kdmbt, MATCH_KDMBT, MASK_KDMBT) +DECLARE_INSN(kdmbt16, MATCH_KDMBT16, MASK_KDMBT16) +DECLARE_INSN(kdmtt, MATCH_KDMTT, MASK_KDMTT) +DECLARE_INSN(kdmtt16, MATCH_KDMTT16, MASK_KDMTT16) +DECLARE_INSN(khm16, MATCH_KHM16, MASK_KHM16) +DECLARE_INSN(khm8, MATCH_KHM8, MASK_KHM8) +DECLARE_INSN(khmbb, MATCH_KHMBB, MASK_KHMBB) +DECLARE_INSN(khmbb16, MATCH_KHMBB16, MASK_KHMBB16) +DECLARE_INSN(khmbt, MATCH_KHMBT, MASK_KHMBT) +DECLARE_INSN(khmbt16, MATCH_KHMBT16, MASK_KHMBT16) +DECLARE_INSN(khmtt, MATCH_KHMTT, MASK_KHMTT) +DECLARE_INSN(khmtt16, MATCH_KHMTT16, MASK_KHMTT16) +DECLARE_INSN(khmx16, MATCH_KHMX16, MASK_KHMX16) +DECLARE_INSN(khmx8, MATCH_KHMX8, MASK_KHMX8) +DECLARE_INSN(kmabb, MATCH_KMABB, MASK_KMABB) +DECLARE_INSN(kmabb32, MATCH_KMABB32, MASK_KMABB32) +DECLARE_INSN(kmabt, MATCH_KMABT, MASK_KMABT) +DECLARE_INSN(kmabt32, MATCH_KMABT32, MASK_KMABT32) +DECLARE_INSN(kmada, MATCH_KMADA, MASK_KMADA) +DECLARE_INSN(kmadrs, MATCH_KMADRS, MASK_KMADRS) +DECLARE_INSN(kmadrs32, MATCH_KMADRS32, MASK_KMADRS32) +DECLARE_INSN(kmads, MATCH_KMADS, MASK_KMADS) +DECLARE_INSN(kmads32, MATCH_KMADS32, MASK_KMADS32) +DECLARE_INSN(kmar64, MATCH_KMAR64, MASK_KMAR64) +DECLARE_INSN(kmatt, MATCH_KMATT, MASK_KMATT) +DECLARE_INSN(kmatt32, MATCH_KMATT32, MASK_KMATT32) +DECLARE_INSN(kmaxda, MATCH_KMAXDA, MASK_KMAXDA) +DECLARE_INSN(kmaxda32, MATCH_KMAXDA32, MASK_KMAXDA32) +DECLARE_INSN(kmaxds, MATCH_KMAXDS, MASK_KMAXDS) +DECLARE_INSN(kmaxds32, MATCH_KMAXDS32, MASK_KMAXDS32) +DECLARE_INSN(kmda, MATCH_KMDA, MASK_KMDA) +DECLARE_INSN(kmda32, MATCH_KMDA32, MASK_KMDA32) +DECLARE_INSN(kmmac, MATCH_KMMAC, MASK_KMMAC) +DECLARE_INSN(kmmac_u, MATCH_KMMAC_U, MASK_KMMAC_U) +DECLARE_INSN(kmmawb, MATCH_KMMAWB, MASK_KMMAWB) +DECLARE_INSN(kmmawb2, MATCH_KMMAWB2, MASK_KMMAWB2) +DECLARE_INSN(kmmawb2_u, MATCH_KMMAWB2_U, MASK_KMMAWB2_U) +DECLARE_INSN(kmmawb_u, MATCH_KMMAWB_U, MASK_KMMAWB_U) +DECLARE_INSN(kmmawt, MATCH_KMMAWT, MASK_KMMAWT) +DECLARE_INSN(kmmawt2, MATCH_KMMAWT2, MASK_KMMAWT2) +DECLARE_INSN(kmmawt2_u, MATCH_KMMAWT2_U, MASK_KMMAWT2_U) +DECLARE_INSN(kmmawt_u, MATCH_KMMAWT_U, MASK_KMMAWT_U) +DECLARE_INSN(kmmsb, MATCH_KMMSB, MASK_KMMSB) +DECLARE_INSN(kmmsb_u, MATCH_KMMSB_U, MASK_KMMSB_U) +DECLARE_INSN(kmmwb2, MATCH_KMMWB2, MASK_KMMWB2) +DECLARE_INSN(kmmwb2_u, MATCH_KMMWB2_U, MASK_KMMWB2_U) +DECLARE_INSN(kmmwt2, MATCH_KMMWT2, MASK_KMMWT2) +DECLARE_INSN(kmmwt2_u, MATCH_KMMWT2_U, MASK_KMMWT2_U) +DECLARE_INSN(kmsda, MATCH_KMSDA, MASK_KMSDA) +DECLARE_INSN(kmsda32, MATCH_KMSDA32, MASK_KMSDA32) +DECLARE_INSN(kmsr64, MATCH_KMSR64, MASK_KMSR64) +DECLARE_INSN(kmsxda, MATCH_KMSXDA, MASK_KMSXDA) +DECLARE_INSN(kmsxda32, MATCH_KMSXDA32, MASK_KMSXDA32) +DECLARE_INSN(kmxda, MATCH_KMXDA, MASK_KMXDA) +DECLARE_INSN(kmxda32, MATCH_KMXDA32, MASK_KMXDA32) +DECLARE_INSN(ksll16, MATCH_KSLL16, MASK_KSLL16) +DECLARE_INSN(ksll32, MATCH_KSLL32, MASK_KSLL32) +DECLARE_INSN(ksll8, MATCH_KSLL8, MASK_KSLL8) +DECLARE_INSN(kslli16, MATCH_KSLLI16, MASK_KSLLI16) +DECLARE_INSN(kslli32, MATCH_KSLLI32, MASK_KSLLI32) +DECLARE_INSN(kslli8, MATCH_KSLLI8, MASK_KSLLI8) +DECLARE_INSN(kslliw, MATCH_KSLLIW, MASK_KSLLIW) +DECLARE_INSN(ksllw, MATCH_KSLLW, MASK_KSLLW) +DECLARE_INSN(kslra16, MATCH_KSLRA16, MASK_KSLRA16) +DECLARE_INSN(kslra16_u, MATCH_KSLRA16_U, MASK_KSLRA16_U) +DECLARE_INSN(kslra32, MATCH_KSLRA32, MASK_KSLRA32) +DECLARE_INSN(kslra32_u, MATCH_KSLRA32_U, MASK_KSLRA32_U) +DECLARE_INSN(kslra8, MATCH_KSLRA8, MASK_KSLRA8) +DECLARE_INSN(kslra8_u, MATCH_KSLRA8_U, MASK_KSLRA8_U) +DECLARE_INSN(kslraw, MATCH_KSLRAW, MASK_KSLRAW) +DECLARE_INSN(kslraw_u, MATCH_KSLRAW_U, MASK_KSLRAW_U) +DECLARE_INSN(kstas16, MATCH_KSTAS16, MASK_KSTAS16) +DECLARE_INSN(kstas32, MATCH_KSTAS32, MASK_KSTAS32) +DECLARE_INSN(kstsa16, MATCH_KSTSA16, MASK_KSTSA16) +DECLARE_INSN(kstsa32, MATCH_KSTSA32, MASK_KSTSA32) +DECLARE_INSN(ksub16, MATCH_KSUB16, MASK_KSUB16) +DECLARE_INSN(ksub32, MATCH_KSUB32, MASK_KSUB32) +DECLARE_INSN(ksub64, MATCH_KSUB64, MASK_KSUB64) +DECLARE_INSN(ksub8, MATCH_KSUB8, MASK_KSUB8) +DECLARE_INSN(ksubh, MATCH_KSUBH, MASK_KSUBH) +DECLARE_INSN(ksubw, MATCH_KSUBW, MASK_KSUBW) +DECLARE_INSN(kwmmul, MATCH_KWMMUL, MASK_KWMMUL) +DECLARE_INSN(kwmmul_u, MATCH_KWMMUL_U, MASK_KWMMUL_U) +DECLARE_INSN(lb, MATCH_LB, MASK_LB) +DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) +DECLARE_INSN(ld, MATCH_LD, MASK_LD) +DECLARE_INSN(ldu, MATCH_LDU, MASK_LDU) +DECLARE_INSN(lh, MATCH_LH, MASK_LH) +DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU) +DECLARE_INSN(lq, MATCH_LQ, MASK_LQ) +DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D) +DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W) +DECLARE_INSN(lui, MATCH_LUI, MASK_LUI) +DECLARE_INSN(lw, MATCH_LW, MASK_LW) +DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU) +DECLARE_INSN(maddr32, MATCH_MADDR32, MASK_MADDR32) +DECLARE_INSN(max, MATCH_MAX, MASK_MAX) +DECLARE_INSN(maxu, MATCH_MAXU, MASK_MAXU) +DECLARE_INSN(maxw, MATCH_MAXW, MASK_MAXW) +DECLARE_INSN(min, MATCH_MIN, MASK_MIN) +DECLARE_INSN(minu, MATCH_MINU, MASK_MINU) +DECLARE_INSN(minw, MATCH_MINW, MASK_MINW) +DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) +DECLARE_INSN(msubr32, MATCH_MSUBR32, MASK_MSUBR32) +DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) +DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) +DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) +DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) +DECLARE_INSN(mulr64, MATCH_MULR64, MASK_MULR64) +DECLARE_INSN(mulsr64, MATCH_MULSR64, MASK_MULSR64) +DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) +DECLARE_INSN(or, MATCH_OR, MASK_OR) +DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) +DECLARE_INSN(orn, MATCH_ORN, MASK_ORN) +DECLARE_INSN(pack, MATCH_PACK, MASK_PACK) +DECLARE_INSN(packh, MATCH_PACKH, MASK_PACKH) +DECLARE_INSN(packu, MATCH_PACKU, MASK_PACKU) +DECLARE_INSN(packuw, MATCH_PACKUW, MASK_PACKUW) +DECLARE_INSN(packw, MATCH_PACKW, MASK_PACKW) +DECLARE_INSN(pause, MATCH_PAUSE, MASK_PAUSE) +DECLARE_INSN(pbsad, MATCH_PBSAD, MASK_PBSAD) +DECLARE_INSN(pbsada, MATCH_PBSADA, MASK_PBSADA) +DECLARE_INSN(pkbb16, MATCH_PKBB16, MASK_PKBB16) +DECLARE_INSN(pkbb32, MATCH_PKBB32, MASK_PKBB32) +DECLARE_INSN(pkbt16, MATCH_PKBT16, MASK_PKBT16) +DECLARE_INSN(pkbt32, MATCH_PKBT32, MASK_PKBT32) +DECLARE_INSN(pktb16, MATCH_PKTB16, MASK_PKTB16) +DECLARE_INSN(pktb32, MATCH_PKTB32, MASK_PKTB32) +DECLARE_INSN(pktt16, MATCH_PKTT16, MASK_PKTT16) +DECLARE_INSN(pktt32, MATCH_PKTT32, MASK_PKTT32) +DECLARE_INSN(prefetch_i, MATCH_PREFETCH_I, MASK_PREFETCH_I) +DECLARE_INSN(prefetch_r, MATCH_PREFETCH_R, MASK_PREFETCH_R) +DECLARE_INSN(prefetch_w, MATCH_PREFETCH_W, MASK_PREFETCH_W) +DECLARE_INSN(radd16, MATCH_RADD16, MASK_RADD16) +DECLARE_INSN(radd32, MATCH_RADD32, MASK_RADD32) +DECLARE_INSN(radd64, MATCH_RADD64, MASK_RADD64) +DECLARE_INSN(radd8, MATCH_RADD8, MASK_RADD8) +DECLARE_INSN(raddw, MATCH_RADDW, MASK_RADDW) +DECLARE_INSN(rcras16, MATCH_RCRAS16, MASK_RCRAS16) +DECLARE_INSN(rcras32, MATCH_RCRAS32, MASK_RCRAS32) +DECLARE_INSN(rcrsa16, MATCH_RCRSA16, MASK_RCRSA16) +DECLARE_INSN(rcrsa32, MATCH_RCRSA32, MASK_RCRSA32) +DECLARE_INSN(rem, MATCH_REM, MASK_REM) +DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) +DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) +DECLARE_INSN(remw, MATCH_REMW, MASK_REMW) +DECLARE_INSN(rol, MATCH_ROL, MASK_ROL) +DECLARE_INSN(rolw, MATCH_ROLW, MASK_ROLW) +DECLARE_INSN(ror, MATCH_ROR, MASK_ROR) +DECLARE_INSN(rori, MATCH_RORI, MASK_RORI) +DECLARE_INSN(roriw, MATCH_RORIW, MASK_RORIW) +DECLARE_INSN(rorw, MATCH_RORW, MASK_RORW) +DECLARE_INSN(rstas16, MATCH_RSTAS16, MASK_RSTAS16) +DECLARE_INSN(rstas32, MATCH_RSTAS32, MASK_RSTAS32) +DECLARE_INSN(rstsa16, MATCH_RSTSA16, MASK_RSTSA16) +DECLARE_INSN(rstsa32, MATCH_RSTSA32, MASK_RSTSA32) +DECLARE_INSN(rsub16, MATCH_RSUB16, MASK_RSUB16) +DECLARE_INSN(rsub32, MATCH_RSUB32, MASK_RSUB32) +DECLARE_INSN(rsub64, MATCH_RSUB64, MASK_RSUB64) +DECLARE_INSN(rsub8, MATCH_RSUB8, MASK_RSUB8) +DECLARE_INSN(rsubw, MATCH_RSUBW, MASK_RSUBW) +DECLARE_INSN(sb, MATCH_SB, MASK_SB) +DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) +DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) +DECLARE_INSN(sclip16, MATCH_SCLIP16, MASK_SCLIP16) +DECLARE_INSN(sclip32, MATCH_SCLIP32, MASK_SCLIP32) +DECLARE_INSN(sclip8, MATCH_SCLIP8, MASK_SCLIP8) +DECLARE_INSN(scmple16, MATCH_SCMPLE16, MASK_SCMPLE16) +DECLARE_INSN(scmple8, MATCH_SCMPLE8, MASK_SCMPLE8) +DECLARE_INSN(scmplt16, MATCH_SCMPLT16, MASK_SCMPLT16) +DECLARE_INSN(scmplt8, MATCH_SCMPLT8, MASK_SCMPLT8) +DECLARE_INSN(sd, MATCH_SD, MASK_SD) +DECLARE_INSN(sext_b, MATCH_SEXT_B, MASK_SEXT_B) +DECLARE_INSN(sext_h, MATCH_SEXT_H, MASK_SEXT_H) +DECLARE_INSN(sfence_inval_ir, MATCH_SFENCE_INVAL_IR, MASK_SFENCE_INVAL_IR) +DECLARE_INSN(sfence_vma, MATCH_SFENCE_VMA, MASK_SFENCE_VMA) +DECLARE_INSN(sfence_w_inval, MATCH_SFENCE_W_INVAL, MASK_SFENCE_W_INVAL) +DECLARE_INSN(sh, MATCH_SH, MASK_SH) +DECLARE_INSN(sh1add, MATCH_SH1ADD, MASK_SH1ADD) +DECLARE_INSN(sh1add_uw, MATCH_SH1ADD_UW, MASK_SH1ADD_UW) +DECLARE_INSN(sh2add, MATCH_SH2ADD, MASK_SH2ADD) +DECLARE_INSN(sh2add_uw, MATCH_SH2ADD_UW, MASK_SH2ADD_UW) +DECLARE_INSN(sh3add, MATCH_SH3ADD, MASK_SH3ADD) +DECLARE_INSN(sh3add_uw, MATCH_SH3ADD_UW, MASK_SH3ADD_UW) +DECLARE_INSN(sha256sig0, MATCH_SHA256SIG0, MASK_SHA256SIG0) +DECLARE_INSN(sha256sig1, MATCH_SHA256SIG1, MASK_SHA256SIG1) +DECLARE_INSN(sha256sum0, MATCH_SHA256SUM0, MASK_SHA256SUM0) +DECLARE_INSN(sha256sum1, MATCH_SHA256SUM1, MASK_SHA256SUM1) +DECLARE_INSN(sha512sig0, MATCH_SHA512SIG0, MASK_SHA512SIG0) +DECLARE_INSN(sha512sig0h, MATCH_SHA512SIG0H, MASK_SHA512SIG0H) +DECLARE_INSN(sha512sig0l, MATCH_SHA512SIG0L, MASK_SHA512SIG0L) +DECLARE_INSN(sha512sig1, MATCH_SHA512SIG1, MASK_SHA512SIG1) +DECLARE_INSN(sha512sig1h, MATCH_SHA512SIG1H, MASK_SHA512SIG1H) +DECLARE_INSN(sha512sig1l, MATCH_SHA512SIG1L, MASK_SHA512SIG1L) +DECLARE_INSN(sha512sum0, MATCH_SHA512SUM0, MASK_SHA512SUM0) +DECLARE_INSN(sha512sum0r, MATCH_SHA512SUM0R, MASK_SHA512SUM0R) +DECLARE_INSN(sha512sum1, MATCH_SHA512SUM1, MASK_SHA512SUM1) +DECLARE_INSN(sha512sum1r, MATCH_SHA512SUM1R, MASK_SHA512SUM1R) +DECLARE_INSN(shfl, MATCH_SHFL, MASK_SHFL) +DECLARE_INSN(shfli, MATCH_SHFLI, MASK_SHFLI) +DECLARE_INSN(shflw, MATCH_SHFLW, MASK_SHFLW) +DECLARE_INSN(sinval_vma, MATCH_SINVAL_VMA, MASK_SINVAL_VMA) +DECLARE_INSN(sll, MATCH_SLL, MASK_SLL) +DECLARE_INSN(sll16, MATCH_SLL16, MASK_SLL16) +DECLARE_INSN(sll32, MATCH_SLL32, MASK_SLL32) +DECLARE_INSN(sll8, MATCH_SLL8, MASK_SLL8) +DECLARE_INSN(slld, MATCH_SLLD, MASK_SLLD) +DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI) +DECLARE_INSN(slli16, MATCH_SLLI16, MASK_SLLI16) +DECLARE_INSN(slli32, MATCH_SLLI32, MASK_SLLI32) +DECLARE_INSN(slli8, MATCH_SLLI8, MASK_SLLI8) +DECLARE_INSN(slli_uw, MATCH_SLLI_UW, MASK_SLLI_UW) +DECLARE_INSN(sllid, MATCH_SLLID, MASK_SLLID) +DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) +DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) +DECLARE_INSN(slo, MATCH_SLO, MASK_SLO) +DECLARE_INSN(sloi, MATCH_SLOI, MASK_SLOI) +DECLARE_INSN(sloiw, MATCH_SLOIW, MASK_SLOIW) +DECLARE_INSN(slow, MATCH_SLOW, MASK_SLOW) +DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) +DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) +DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) +DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU) +DECLARE_INSN(sm3p0, MATCH_SM3P0, MASK_SM3P0) +DECLARE_INSN(sm3p1, MATCH_SM3P1, MASK_SM3P1) +DECLARE_INSN(sm4ed, MATCH_SM4ED, MASK_SM4ED) +DECLARE_INSN(sm4ks, MATCH_SM4KS, MASK_SM4KS) +DECLARE_INSN(smal, MATCH_SMAL, MASK_SMAL) +DECLARE_INSN(smalbb, MATCH_SMALBB, MASK_SMALBB) +DECLARE_INSN(smalbt, MATCH_SMALBT, MASK_SMALBT) +DECLARE_INSN(smalda, MATCH_SMALDA, MASK_SMALDA) +DECLARE_INSN(smaldrs, MATCH_SMALDRS, MASK_SMALDRS) +DECLARE_INSN(smalds, MATCH_SMALDS, MASK_SMALDS) +DECLARE_INSN(smaltt, MATCH_SMALTT, MASK_SMALTT) +DECLARE_INSN(smalxda, MATCH_SMALXDA, MASK_SMALXDA) +DECLARE_INSN(smalxds, MATCH_SMALXDS, MASK_SMALXDS) +DECLARE_INSN(smaqa, MATCH_SMAQA, MASK_SMAQA) +DECLARE_INSN(smaqa_su, MATCH_SMAQA_SU, MASK_SMAQA_SU) +DECLARE_INSN(smar64, MATCH_SMAR64, MASK_SMAR64) +DECLARE_INSN(smax16, MATCH_SMAX16, MASK_SMAX16) +DECLARE_INSN(smax32, MATCH_SMAX32, MASK_SMAX32) +DECLARE_INSN(smax8, MATCH_SMAX8, MASK_SMAX8) +DECLARE_INSN(smbb16, MATCH_SMBB16, MASK_SMBB16) +DECLARE_INSN(smbt16, MATCH_SMBT16, MASK_SMBT16) +DECLARE_INSN(smbt32, MATCH_SMBT32, MASK_SMBT32) +DECLARE_INSN(smdrs, MATCH_SMDRS, MASK_SMDRS) +DECLARE_INSN(smdrs32, MATCH_SMDRS32, MASK_SMDRS32) +DECLARE_INSN(smds, MATCH_SMDS, MASK_SMDS) +DECLARE_INSN(smds32, MATCH_SMDS32, MASK_SMDS32) +DECLARE_INSN(smin16, MATCH_SMIN16, MASK_SMIN16) +DECLARE_INSN(smin32, MATCH_SMIN32, MASK_SMIN32) +DECLARE_INSN(smin8, MATCH_SMIN8, MASK_SMIN8) +DECLARE_INSN(smmul, MATCH_SMMUL, MASK_SMMUL) +DECLARE_INSN(smmul_u, MATCH_SMMUL_U, MASK_SMMUL_U) +DECLARE_INSN(smmwb, MATCH_SMMWB, MASK_SMMWB) +DECLARE_INSN(smmwb_u, MATCH_SMMWB_U, MASK_SMMWB_U) +DECLARE_INSN(smmwt, MATCH_SMMWT, MASK_SMMWT) +DECLARE_INSN(smmwt_u, MATCH_SMMWT_U, MASK_SMMWT_U) +DECLARE_INSN(smslda, MATCH_SMSLDA, MASK_SMSLDA) +DECLARE_INSN(smslxda, MATCH_SMSLXDA, MASK_SMSLXDA) +DECLARE_INSN(smsr64, MATCH_SMSR64, MASK_SMSR64) +DECLARE_INSN(smtt16, MATCH_SMTT16, MASK_SMTT16) +DECLARE_INSN(smtt32, MATCH_SMTT32, MASK_SMTT32) +DECLARE_INSN(smul16, MATCH_SMUL16, MASK_SMUL16) +DECLARE_INSN(smul8, MATCH_SMUL8, MASK_SMUL8) +DECLARE_INSN(smulx16, MATCH_SMULX16, MASK_SMULX16) +DECLARE_INSN(smulx8, MATCH_SMULX8, MASK_SMULX8) +DECLARE_INSN(smxds, MATCH_SMXDS, MASK_SMXDS) +DECLARE_INSN(smxds32, MATCH_SMXDS32, MASK_SMXDS32) +DECLARE_INSN(sq, MATCH_SQ, MASK_SQ) +DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) +DECLARE_INSN(sra16, MATCH_SRA16, MASK_SRA16) +DECLARE_INSN(sra16_u, MATCH_SRA16_U, MASK_SRA16_U) +DECLARE_INSN(sra32, MATCH_SRA32, MASK_SRA32) +DECLARE_INSN(sra32_u, MATCH_SRA32_U, MASK_SRA32_U) +DECLARE_INSN(sra8, MATCH_SRA8, MASK_SRA8) +DECLARE_INSN(sra8_u, MATCH_SRA8_U, MASK_SRA8_U) +DECLARE_INSN(sra_u, MATCH_SRA_U, MASK_SRA_U) +DECLARE_INSN(srad, MATCH_SRAD, MASK_SRAD) +DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) +DECLARE_INSN(srai16, MATCH_SRAI16, MASK_SRAI16) +DECLARE_INSN(srai16_u, MATCH_SRAI16_U, MASK_SRAI16_U) +DECLARE_INSN(srai32, MATCH_SRAI32, MASK_SRAI32) +DECLARE_INSN(srai32_u, MATCH_SRAI32_U, MASK_SRAI32_U) +DECLARE_INSN(srai8, MATCH_SRAI8, MASK_SRAI8) +DECLARE_INSN(srai8_u, MATCH_SRAI8_U, MASK_SRAI8_U) +DECLARE_INSN(srai_u, MATCH_SRAI_U, MASK_SRAI_U) +DECLARE_INSN(sraid, MATCH_SRAID, MASK_SRAID) +DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) +DECLARE_INSN(sraiw_u, MATCH_SRAIW_U, MASK_SRAIW_U) +DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW) +DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) +DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) +DECLARE_INSN(srl16, MATCH_SRL16, MASK_SRL16) +DECLARE_INSN(srl16_u, MATCH_SRL16_U, MASK_SRL16_U) +DECLARE_INSN(srl32, MATCH_SRL32, MASK_SRL32) +DECLARE_INSN(srl32_u, MATCH_SRL32_U, MASK_SRL32_U) +DECLARE_INSN(srl8, MATCH_SRL8, MASK_SRL8) +DECLARE_INSN(srl8_u, MATCH_SRL8_U, MASK_SRL8_U) +DECLARE_INSN(srld, MATCH_SRLD, MASK_SRLD) +DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) +DECLARE_INSN(srli16, MATCH_SRLI16, MASK_SRLI16) +DECLARE_INSN(srli16_u, MATCH_SRLI16_U, MASK_SRLI16_U) +DECLARE_INSN(srli32, MATCH_SRLI32, MASK_SRLI32) +DECLARE_INSN(srli32_u, MATCH_SRLI32_U, MASK_SRLI32_U) +DECLARE_INSN(srli8, MATCH_SRLI8, MASK_SRLI8) +DECLARE_INSN(srli8_u, MATCH_SRLI8_U, MASK_SRLI8_U) +DECLARE_INSN(srlid, MATCH_SRLID, MASK_SRLID) +DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) +DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) +DECLARE_INSN(sro, MATCH_SRO, MASK_SRO) +DECLARE_INSN(sroi, MATCH_SROI, MASK_SROI) +DECLARE_INSN(sroiw, MATCH_SROIW, MASK_SROIW) +DECLARE_INSN(srow, MATCH_SROW, MASK_SROW) +DECLARE_INSN(stas16, MATCH_STAS16, MASK_STAS16) +DECLARE_INSN(stas32, MATCH_STAS32, MASK_STAS32) +DECLARE_INSN(stsa16, MATCH_STSA16, MASK_STSA16) +DECLARE_INSN(stsa32, MATCH_STSA32, MASK_STSA32) +DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) +DECLARE_INSN(sub16, MATCH_SUB16, MASK_SUB16) +DECLARE_INSN(sub32, MATCH_SUB32, MASK_SUB32) +DECLARE_INSN(sub64, MATCH_SUB64, MASK_SUB64) +DECLARE_INSN(sub8, MATCH_SUB8, MASK_SUB8) +DECLARE_INSN(subd, MATCH_SUBD, MASK_SUBD) +DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) +DECLARE_INSN(sunpkd810, MATCH_SUNPKD810, MASK_SUNPKD810) +DECLARE_INSN(sunpkd820, MATCH_SUNPKD820, MASK_SUNPKD820) +DECLARE_INSN(sunpkd830, MATCH_SUNPKD830, MASK_SUNPKD830) +DECLARE_INSN(sunpkd831, MATCH_SUNPKD831, MASK_SUNPKD831) +DECLARE_INSN(sunpkd832, MATCH_SUNPKD832, MASK_SUNPKD832) +DECLARE_INSN(sw, MATCH_SW, MASK_SW) +DECLARE_INSN(swap8, MATCH_SWAP8, MASK_SWAP8) +DECLARE_INSN(uclip16, MATCH_UCLIP16, MASK_UCLIP16) +DECLARE_INSN(uclip32, MATCH_UCLIP32, MASK_UCLIP32) +DECLARE_INSN(uclip8, MATCH_UCLIP8, MASK_UCLIP8) +DECLARE_INSN(ucmple16, MATCH_UCMPLE16, MASK_UCMPLE16) +DECLARE_INSN(ucmple8, MATCH_UCMPLE8, MASK_UCMPLE8) +DECLARE_INSN(ucmplt16, MATCH_UCMPLT16, MASK_UCMPLT16) +DECLARE_INSN(ucmplt8, MATCH_UCMPLT8, MASK_UCMPLT8) +DECLARE_INSN(ukadd16, MATCH_UKADD16, MASK_UKADD16) +DECLARE_INSN(ukadd32, MATCH_UKADD32, MASK_UKADD32) +DECLARE_INSN(ukadd64, MATCH_UKADD64, MASK_UKADD64) +DECLARE_INSN(ukadd8, MATCH_UKADD8, MASK_UKADD8) +DECLARE_INSN(ukaddh, MATCH_UKADDH, MASK_UKADDH) +DECLARE_INSN(ukaddw, MATCH_UKADDW, MASK_UKADDW) +DECLARE_INSN(ukcras16, MATCH_UKCRAS16, MASK_UKCRAS16) +DECLARE_INSN(ukcras32, MATCH_UKCRAS32, MASK_UKCRAS32) +DECLARE_INSN(ukcrsa16, MATCH_UKCRSA16, MASK_UKCRSA16) +DECLARE_INSN(ukcrsa32, MATCH_UKCRSA32, MASK_UKCRSA32) +DECLARE_INSN(ukmar64, MATCH_UKMAR64, MASK_UKMAR64) +DECLARE_INSN(ukmsr64, MATCH_UKMSR64, MASK_UKMSR64) +DECLARE_INSN(ukstas16, MATCH_UKSTAS16, MASK_UKSTAS16) +DECLARE_INSN(ukstas32, MATCH_UKSTAS32, MASK_UKSTAS32) +DECLARE_INSN(ukstsa16, MATCH_UKSTSA16, MASK_UKSTSA16) +DECLARE_INSN(ukstsa32, MATCH_UKSTSA32, MASK_UKSTSA32) +DECLARE_INSN(uksub16, MATCH_UKSUB16, MASK_UKSUB16) +DECLARE_INSN(uksub32, MATCH_UKSUB32, MASK_UKSUB32) +DECLARE_INSN(uksub64, MATCH_UKSUB64, MASK_UKSUB64) +DECLARE_INSN(uksub8, MATCH_UKSUB8, MASK_UKSUB8) +DECLARE_INSN(uksubh, MATCH_UKSUBH, MASK_UKSUBH) +DECLARE_INSN(uksubw, MATCH_UKSUBW, MASK_UKSUBW) +DECLARE_INSN(umaqa, MATCH_UMAQA, MASK_UMAQA) +DECLARE_INSN(umar64, MATCH_UMAR64, MASK_UMAR64) +DECLARE_INSN(umax16, MATCH_UMAX16, MASK_UMAX16) +DECLARE_INSN(umax32, MATCH_UMAX32, MASK_UMAX32) +DECLARE_INSN(umax8, MATCH_UMAX8, MASK_UMAX8) +DECLARE_INSN(umin16, MATCH_UMIN16, MASK_UMIN16) +DECLARE_INSN(umin32, MATCH_UMIN32, MASK_UMIN32) +DECLARE_INSN(umin8, MATCH_UMIN8, MASK_UMIN8) +DECLARE_INSN(umsr64, MATCH_UMSR64, MASK_UMSR64) +DECLARE_INSN(umul16, MATCH_UMUL16, MASK_UMUL16) +DECLARE_INSN(umul8, MATCH_UMUL8, MASK_UMUL8) +DECLARE_INSN(umulx16, MATCH_UMULX16, MASK_UMULX16) +DECLARE_INSN(umulx8, MATCH_UMULX8, MASK_UMULX8) +DECLARE_INSN(unshfl, MATCH_UNSHFL, MASK_UNSHFL) +DECLARE_INSN(unshfli, MATCH_UNSHFLI, MASK_UNSHFLI) +DECLARE_INSN(unshflw, MATCH_UNSHFLW, MASK_UNSHFLW) +DECLARE_INSN(uradd16, MATCH_URADD16, MASK_URADD16) +DECLARE_INSN(uradd32, MATCH_URADD32, MASK_URADD32) +DECLARE_INSN(uradd64, MATCH_URADD64, MASK_URADD64) +DECLARE_INSN(uradd8, MATCH_URADD8, MASK_URADD8) +DECLARE_INSN(uraddw, MATCH_URADDW, MASK_URADDW) +DECLARE_INSN(urcras16, MATCH_URCRAS16, MASK_URCRAS16) +DECLARE_INSN(urcras32, MATCH_URCRAS32, MASK_URCRAS32) +DECLARE_INSN(urcrsa16, MATCH_URCRSA16, MASK_URCRSA16) +DECLARE_INSN(urcrsa32, MATCH_URCRSA32, MASK_URCRSA32) +DECLARE_INSN(urstas16, MATCH_URSTAS16, MASK_URSTAS16) +DECLARE_INSN(urstas32, MATCH_URSTAS32, MASK_URSTAS32) +DECLARE_INSN(urstsa16, MATCH_URSTSA16, MASK_URSTSA16) +DECLARE_INSN(urstsa32, MATCH_URSTSA32, MASK_URSTSA32) +DECLARE_INSN(ursub16, MATCH_URSUB16, MASK_URSUB16) +DECLARE_INSN(ursub32, MATCH_URSUB32, MASK_URSUB32) +DECLARE_INSN(ursub64, MATCH_URSUB64, MASK_URSUB64) +DECLARE_INSN(ursub8, MATCH_URSUB8, MASK_URSUB8) +DECLARE_INSN(ursubw, MATCH_URSUBW, MASK_URSUBW) +DECLARE_INSN(vaadd_vv, MATCH_VAADD_VV, MASK_VAADD_VV) +DECLARE_INSN(vaadd_vx, MATCH_VAADD_VX, MASK_VAADD_VX) +DECLARE_INSN(vaaddu_vv, MATCH_VAADDU_VV, MASK_VAADDU_VV) +DECLARE_INSN(vaaddu_vx, MATCH_VAADDU_VX, MASK_VAADDU_VX) +DECLARE_INSN(vadc_vim, MATCH_VADC_VIM, MASK_VADC_VIM) +DECLARE_INSN(vadc_vvm, MATCH_VADC_VVM, MASK_VADC_VVM) +DECLARE_INSN(vadc_vxm, MATCH_VADC_VXM, MASK_VADC_VXM) +DECLARE_INSN(vadd_vi, MATCH_VADD_VI, MASK_VADD_VI) +DECLARE_INSN(vadd_vv, MATCH_VADD_VV, MASK_VADD_VV) +DECLARE_INSN(vadd_vx, MATCH_VADD_VX, MASK_VADD_VX) +DECLARE_INSN(vamoaddei16_v, MATCH_VAMOADDEI16_V, MASK_VAMOADDEI16_V) +DECLARE_INSN(vamoaddei32_v, MATCH_VAMOADDEI32_V, MASK_VAMOADDEI32_V) +DECLARE_INSN(vamoaddei64_v, MATCH_VAMOADDEI64_V, MASK_VAMOADDEI64_V) +DECLARE_INSN(vamoaddei8_v, MATCH_VAMOADDEI8_V, MASK_VAMOADDEI8_V) +DECLARE_INSN(vamoandei16_v, MATCH_VAMOANDEI16_V, MASK_VAMOANDEI16_V) +DECLARE_INSN(vamoandei32_v, MATCH_VAMOANDEI32_V, MASK_VAMOANDEI32_V) +DECLARE_INSN(vamoandei64_v, MATCH_VAMOANDEI64_V, MASK_VAMOANDEI64_V) +DECLARE_INSN(vamoandei8_v, MATCH_VAMOANDEI8_V, MASK_VAMOANDEI8_V) +DECLARE_INSN(vamomaxei16_v, MATCH_VAMOMAXEI16_V, MASK_VAMOMAXEI16_V) +DECLARE_INSN(vamomaxei32_v, MATCH_VAMOMAXEI32_V, MASK_VAMOMAXEI32_V) +DECLARE_INSN(vamomaxei64_v, MATCH_VAMOMAXEI64_V, MASK_VAMOMAXEI64_V) +DECLARE_INSN(vamomaxei8_v, MATCH_VAMOMAXEI8_V, MASK_VAMOMAXEI8_V) +DECLARE_INSN(vamomaxuei16_v, MATCH_VAMOMAXUEI16_V, MASK_VAMOMAXUEI16_V) +DECLARE_INSN(vamomaxuei32_v, MATCH_VAMOMAXUEI32_V, MASK_VAMOMAXUEI32_V) +DECLARE_INSN(vamomaxuei64_v, MATCH_VAMOMAXUEI64_V, MASK_VAMOMAXUEI64_V) +DECLARE_INSN(vamomaxuei8_v, MATCH_VAMOMAXUEI8_V, MASK_VAMOMAXUEI8_V) +DECLARE_INSN(vamominei16_v, MATCH_VAMOMINEI16_V, MASK_VAMOMINEI16_V) +DECLARE_INSN(vamominei32_v, MATCH_VAMOMINEI32_V, MASK_VAMOMINEI32_V) +DECLARE_INSN(vamominei64_v, MATCH_VAMOMINEI64_V, MASK_VAMOMINEI64_V) +DECLARE_INSN(vamominei8_v, MATCH_VAMOMINEI8_V, MASK_VAMOMINEI8_V) +DECLARE_INSN(vamominuei16_v, MATCH_VAMOMINUEI16_V, MASK_VAMOMINUEI16_V) +DECLARE_INSN(vamominuei32_v, MATCH_VAMOMINUEI32_V, MASK_VAMOMINUEI32_V) +DECLARE_INSN(vamominuei64_v, MATCH_VAMOMINUEI64_V, MASK_VAMOMINUEI64_V) +DECLARE_INSN(vamominuei8_v, MATCH_VAMOMINUEI8_V, MASK_VAMOMINUEI8_V) +DECLARE_INSN(vamoorei16_v, MATCH_VAMOOREI16_V, MASK_VAMOOREI16_V) +DECLARE_INSN(vamoorei32_v, MATCH_VAMOOREI32_V, MASK_VAMOOREI32_V) +DECLARE_INSN(vamoorei64_v, MATCH_VAMOOREI64_V, MASK_VAMOOREI64_V) +DECLARE_INSN(vamoorei8_v, MATCH_VAMOOREI8_V, MASK_VAMOOREI8_V) +DECLARE_INSN(vamoswapei16_v, MATCH_VAMOSWAPEI16_V, MASK_VAMOSWAPEI16_V) +DECLARE_INSN(vamoswapei32_v, MATCH_VAMOSWAPEI32_V, MASK_VAMOSWAPEI32_V) +DECLARE_INSN(vamoswapei64_v, MATCH_VAMOSWAPEI64_V, MASK_VAMOSWAPEI64_V) +DECLARE_INSN(vamoswapei8_v, MATCH_VAMOSWAPEI8_V, MASK_VAMOSWAPEI8_V) +DECLARE_INSN(vamoxorei16_v, MATCH_VAMOXOREI16_V, MASK_VAMOXOREI16_V) +DECLARE_INSN(vamoxorei32_v, MATCH_VAMOXOREI32_V, MASK_VAMOXOREI32_V) +DECLARE_INSN(vamoxorei64_v, MATCH_VAMOXOREI64_V, MASK_VAMOXOREI64_V) +DECLARE_INSN(vamoxorei8_v, MATCH_VAMOXOREI8_V, MASK_VAMOXOREI8_V) +DECLARE_INSN(vand_vi, MATCH_VAND_VI, MASK_VAND_VI) +DECLARE_INSN(vand_vv, MATCH_VAND_VV, MASK_VAND_VV) +DECLARE_INSN(vand_vx, MATCH_VAND_VX, MASK_VAND_VX) +DECLARE_INSN(vasub_vv, MATCH_VASUB_VV, MASK_VASUB_VV) +DECLARE_INSN(vasub_vx, MATCH_VASUB_VX, MASK_VASUB_VX) +DECLARE_INSN(vasubu_vv, MATCH_VASUBU_VV, MASK_VASUBU_VV) +DECLARE_INSN(vasubu_vx, MATCH_VASUBU_VX, MASK_VASUBU_VX) +DECLARE_INSN(vcompress_vm, MATCH_VCOMPRESS_VM, MASK_VCOMPRESS_VM) +DECLARE_INSN(vcpop_m, MATCH_VCPOP_M, MASK_VCPOP_M) +DECLARE_INSN(vdiv_vv, MATCH_VDIV_VV, MASK_VDIV_VV) +DECLARE_INSN(vdiv_vx, MATCH_VDIV_VX, MASK_VDIV_VX) +DECLARE_INSN(vdivu_vv, MATCH_VDIVU_VV, MASK_VDIVU_VV) +DECLARE_INSN(vdivu_vx, MATCH_VDIVU_VX, MASK_VDIVU_VX) +DECLARE_INSN(vfadd_vf, MATCH_VFADD_VF, MASK_VFADD_VF) +DECLARE_INSN(vfadd_vv, MATCH_VFADD_VV, MASK_VFADD_VV) +DECLARE_INSN(vfclass_v, MATCH_VFCLASS_V, MASK_VFCLASS_V) +DECLARE_INSN(vfcvt_f_x_v, MATCH_VFCVT_F_X_V, MASK_VFCVT_F_X_V) +DECLARE_INSN(vfcvt_f_xu_v, MATCH_VFCVT_F_XU_V, MASK_VFCVT_F_XU_V) +DECLARE_INSN(vfcvt_rtz_x_f_v, MATCH_VFCVT_RTZ_X_F_V, MASK_VFCVT_RTZ_X_F_V) +DECLARE_INSN(vfcvt_rtz_xu_f_v, MATCH_VFCVT_RTZ_XU_F_V, MASK_VFCVT_RTZ_XU_F_V) +DECLARE_INSN(vfcvt_x_f_v, MATCH_VFCVT_X_F_V, MASK_VFCVT_X_F_V) +DECLARE_INSN(vfcvt_xu_f_v, MATCH_VFCVT_XU_F_V, MASK_VFCVT_XU_F_V) +DECLARE_INSN(vfdiv_vf, MATCH_VFDIV_VF, MASK_VFDIV_VF) +DECLARE_INSN(vfdiv_vv, MATCH_VFDIV_VV, MASK_VFDIV_VV) +DECLARE_INSN(vfirst_m, MATCH_VFIRST_M, MASK_VFIRST_M) +DECLARE_INSN(vfmacc_vf, MATCH_VFMACC_VF, MASK_VFMACC_VF) +DECLARE_INSN(vfmacc_vv, MATCH_VFMACC_VV, MASK_VFMACC_VV) +DECLARE_INSN(vfmadd_vf, MATCH_VFMADD_VF, MASK_VFMADD_VF) +DECLARE_INSN(vfmadd_vv, MATCH_VFMADD_VV, MASK_VFMADD_VV) +DECLARE_INSN(vfmax_vf, MATCH_VFMAX_VF, MASK_VFMAX_VF) +DECLARE_INSN(vfmax_vv, MATCH_VFMAX_VV, MASK_VFMAX_VV) +DECLARE_INSN(vfmerge_vfm, MATCH_VFMERGE_VFM, MASK_VFMERGE_VFM) +DECLARE_INSN(vfmin_vf, MATCH_VFMIN_VF, MASK_VFMIN_VF) +DECLARE_INSN(vfmin_vv, MATCH_VFMIN_VV, MASK_VFMIN_VV) +DECLARE_INSN(vfmsac_vf, MATCH_VFMSAC_VF, MASK_VFMSAC_VF) +DECLARE_INSN(vfmsac_vv, MATCH_VFMSAC_VV, MASK_VFMSAC_VV) +DECLARE_INSN(vfmsub_vf, MATCH_VFMSUB_VF, MASK_VFMSUB_VF) +DECLARE_INSN(vfmsub_vv, MATCH_VFMSUB_VV, MASK_VFMSUB_VV) +DECLARE_INSN(vfmul_vf, MATCH_VFMUL_VF, MASK_VFMUL_VF) +DECLARE_INSN(vfmul_vv, MATCH_VFMUL_VV, MASK_VFMUL_VV) +DECLARE_INSN(vfmv_f_s, MATCH_VFMV_F_S, MASK_VFMV_F_S) +DECLARE_INSN(vfmv_s_f, MATCH_VFMV_S_F, MASK_VFMV_S_F) +DECLARE_INSN(vfmv_v_f, MATCH_VFMV_V_F, MASK_VFMV_V_F) +DECLARE_INSN(vfncvt_f_f_w, MATCH_VFNCVT_F_F_W, MASK_VFNCVT_F_F_W) +DECLARE_INSN(vfncvt_f_x_w, MATCH_VFNCVT_F_X_W, MASK_VFNCVT_F_X_W) +DECLARE_INSN(vfncvt_f_xu_w, MATCH_VFNCVT_F_XU_W, MASK_VFNCVT_F_XU_W) +DECLARE_INSN(vfncvt_rod_f_f_w, MATCH_VFNCVT_ROD_F_F_W, MASK_VFNCVT_ROD_F_F_W) +DECLARE_INSN(vfncvt_rtz_x_f_w, MATCH_VFNCVT_RTZ_X_F_W, MASK_VFNCVT_RTZ_X_F_W) +DECLARE_INSN(vfncvt_rtz_xu_f_w, MATCH_VFNCVT_RTZ_XU_F_W, MASK_VFNCVT_RTZ_XU_F_W) +DECLARE_INSN(vfncvt_x_f_w, MATCH_VFNCVT_X_F_W, MASK_VFNCVT_X_F_W) +DECLARE_INSN(vfncvt_xu_f_w, MATCH_VFNCVT_XU_F_W, MASK_VFNCVT_XU_F_W) +DECLARE_INSN(vfnmacc_vf, MATCH_VFNMACC_VF, MASK_VFNMACC_VF) +DECLARE_INSN(vfnmacc_vv, MATCH_VFNMACC_VV, MASK_VFNMACC_VV) +DECLARE_INSN(vfnmadd_vf, MATCH_VFNMADD_VF, MASK_VFNMADD_VF) +DECLARE_INSN(vfnmadd_vv, MATCH_VFNMADD_VV, MASK_VFNMADD_VV) +DECLARE_INSN(vfnmsac_vf, MATCH_VFNMSAC_VF, MASK_VFNMSAC_VF) +DECLARE_INSN(vfnmsac_vv, MATCH_VFNMSAC_VV, MASK_VFNMSAC_VV) +DECLARE_INSN(vfnmsub_vf, MATCH_VFNMSUB_VF, MASK_VFNMSUB_VF) +DECLARE_INSN(vfnmsub_vv, MATCH_VFNMSUB_VV, MASK_VFNMSUB_VV) +DECLARE_INSN(vfrdiv_vf, MATCH_VFRDIV_VF, MASK_VFRDIV_VF) +DECLARE_INSN(vfrec7_v, MATCH_VFREC7_V, MASK_VFREC7_V) +DECLARE_INSN(vfredmax_vs, MATCH_VFREDMAX_VS, MASK_VFREDMAX_VS) +DECLARE_INSN(vfredmin_vs, MATCH_VFREDMIN_VS, MASK_VFREDMIN_VS) +DECLARE_INSN(vfredosum_vs, MATCH_VFREDOSUM_VS, MASK_VFREDOSUM_VS) +DECLARE_INSN(vfredusum_vs, MATCH_VFREDUSUM_VS, MASK_VFREDUSUM_VS) +DECLARE_INSN(vfrsqrt7_v, MATCH_VFRSQRT7_V, MASK_VFRSQRT7_V) +DECLARE_INSN(vfrsub_vf, MATCH_VFRSUB_VF, MASK_VFRSUB_VF) +DECLARE_INSN(vfsgnj_vf, MATCH_VFSGNJ_VF, MASK_VFSGNJ_VF) +DECLARE_INSN(vfsgnj_vv, MATCH_VFSGNJ_VV, MASK_VFSGNJ_VV) +DECLARE_INSN(vfsgnjn_vf, MATCH_VFSGNJN_VF, MASK_VFSGNJN_VF) +DECLARE_INSN(vfsgnjn_vv, MATCH_VFSGNJN_VV, MASK_VFSGNJN_VV) +DECLARE_INSN(vfsgnjx_vf, MATCH_VFSGNJX_VF, MASK_VFSGNJX_VF) +DECLARE_INSN(vfsgnjx_vv, MATCH_VFSGNJX_VV, MASK_VFSGNJX_VV) +DECLARE_INSN(vfslide1down_vf, MATCH_VFSLIDE1DOWN_VF, MASK_VFSLIDE1DOWN_VF) +DECLARE_INSN(vfslide1up_vf, MATCH_VFSLIDE1UP_VF, MASK_VFSLIDE1UP_VF) +DECLARE_INSN(vfsqrt_v, MATCH_VFSQRT_V, MASK_VFSQRT_V) +DECLARE_INSN(vfsub_vf, MATCH_VFSUB_VF, MASK_VFSUB_VF) +DECLARE_INSN(vfsub_vv, MATCH_VFSUB_VV, MASK_VFSUB_VV) +DECLARE_INSN(vfwadd_vf, MATCH_VFWADD_VF, MASK_VFWADD_VF) +DECLARE_INSN(vfwadd_vv, MATCH_VFWADD_VV, MASK_VFWADD_VV) +DECLARE_INSN(vfwadd_wf, MATCH_VFWADD_WF, MASK_VFWADD_WF) +DECLARE_INSN(vfwadd_wv, MATCH_VFWADD_WV, MASK_VFWADD_WV) +DECLARE_INSN(vfwcvt_f_f_v, MATCH_VFWCVT_F_F_V, MASK_VFWCVT_F_F_V) +DECLARE_INSN(vfwcvt_f_x_v, MATCH_VFWCVT_F_X_V, MASK_VFWCVT_F_X_V) +DECLARE_INSN(vfwcvt_f_xu_v, MATCH_VFWCVT_F_XU_V, MASK_VFWCVT_F_XU_V) +DECLARE_INSN(vfwcvt_rtz_x_f_v, MATCH_VFWCVT_RTZ_X_F_V, MASK_VFWCVT_RTZ_X_F_V) +DECLARE_INSN(vfwcvt_rtz_xu_f_v, MATCH_VFWCVT_RTZ_XU_F_V, MASK_VFWCVT_RTZ_XU_F_V) +DECLARE_INSN(vfwcvt_x_f_v, MATCH_VFWCVT_X_F_V, MASK_VFWCVT_X_F_V) +DECLARE_INSN(vfwcvt_xu_f_v, MATCH_VFWCVT_XU_F_V, MASK_VFWCVT_XU_F_V) +DECLARE_INSN(vfwmacc_vf, MATCH_VFWMACC_VF, MASK_VFWMACC_VF) +DECLARE_INSN(vfwmacc_vv, MATCH_VFWMACC_VV, MASK_VFWMACC_VV) +DECLARE_INSN(vfwmsac_vf, MATCH_VFWMSAC_VF, MASK_VFWMSAC_VF) +DECLARE_INSN(vfwmsac_vv, MATCH_VFWMSAC_VV, MASK_VFWMSAC_VV) +DECLARE_INSN(vfwmul_vf, MATCH_VFWMUL_VF, MASK_VFWMUL_VF) +DECLARE_INSN(vfwmul_vv, MATCH_VFWMUL_VV, MASK_VFWMUL_VV) +DECLARE_INSN(vfwnmacc_vf, MATCH_VFWNMACC_VF, MASK_VFWNMACC_VF) +DECLARE_INSN(vfwnmacc_vv, MATCH_VFWNMACC_VV, MASK_VFWNMACC_VV) +DECLARE_INSN(vfwnmsac_vf, MATCH_VFWNMSAC_VF, MASK_VFWNMSAC_VF) +DECLARE_INSN(vfwnmsac_vv, MATCH_VFWNMSAC_VV, MASK_VFWNMSAC_VV) +DECLARE_INSN(vfwredosum_vs, MATCH_VFWREDOSUM_VS, MASK_VFWREDOSUM_VS) +DECLARE_INSN(vfwredusum_vs, MATCH_VFWREDUSUM_VS, MASK_VFWREDUSUM_VS) +DECLARE_INSN(vfwsub_vf, MATCH_VFWSUB_VF, MASK_VFWSUB_VF) +DECLARE_INSN(vfwsub_vv, MATCH_VFWSUB_VV, MASK_VFWSUB_VV) +DECLARE_INSN(vfwsub_wf, MATCH_VFWSUB_WF, MASK_VFWSUB_WF) +DECLARE_INSN(vfwsub_wv, MATCH_VFWSUB_WV, MASK_VFWSUB_WV) +DECLARE_INSN(vid_v, MATCH_VID_V, MASK_VID_V) +DECLARE_INSN(viota_m, MATCH_VIOTA_M, MASK_VIOTA_M) +DECLARE_INSN(vl1re16_v, MATCH_VL1RE16_V, MASK_VL1RE16_V) +DECLARE_INSN(vl1re32_v, MATCH_VL1RE32_V, MASK_VL1RE32_V) +DECLARE_INSN(vl1re64_v, MATCH_VL1RE64_V, MASK_VL1RE64_V) +DECLARE_INSN(vl1re8_v, MATCH_VL1RE8_V, MASK_VL1RE8_V) +DECLARE_INSN(vl2re16_v, MATCH_VL2RE16_V, MASK_VL2RE16_V) +DECLARE_INSN(vl2re32_v, MATCH_VL2RE32_V, MASK_VL2RE32_V) +DECLARE_INSN(vl2re64_v, MATCH_VL2RE64_V, MASK_VL2RE64_V) +DECLARE_INSN(vl2re8_v, MATCH_VL2RE8_V, MASK_VL2RE8_V) +DECLARE_INSN(vl4re16_v, MATCH_VL4RE16_V, MASK_VL4RE16_V) +DECLARE_INSN(vl4re32_v, MATCH_VL4RE32_V, MASK_VL4RE32_V) +DECLARE_INSN(vl4re64_v, MATCH_VL4RE64_V, MASK_VL4RE64_V) +DECLARE_INSN(vl4re8_v, MATCH_VL4RE8_V, MASK_VL4RE8_V) +DECLARE_INSN(vl8re16_v, MATCH_VL8RE16_V, MASK_VL8RE16_V) +DECLARE_INSN(vl8re32_v, MATCH_VL8RE32_V, MASK_VL8RE32_V) +DECLARE_INSN(vl8re64_v, MATCH_VL8RE64_V, MASK_VL8RE64_V) +DECLARE_INSN(vl8re8_v, MATCH_VL8RE8_V, MASK_VL8RE8_V) +DECLARE_INSN(vle1024_v, MATCH_VLE1024_V, MASK_VLE1024_V) +DECLARE_INSN(vle1024ff_v, MATCH_VLE1024FF_V, MASK_VLE1024FF_V) +DECLARE_INSN(vle128_v, MATCH_VLE128_V, MASK_VLE128_V) +DECLARE_INSN(vle128ff_v, MATCH_VLE128FF_V, MASK_VLE128FF_V) +DECLARE_INSN(vle16_v, MATCH_VLE16_V, MASK_VLE16_V) +DECLARE_INSN(vle16ff_v, MATCH_VLE16FF_V, MASK_VLE16FF_V) +DECLARE_INSN(vle256_v, MATCH_VLE256_V, MASK_VLE256_V) +DECLARE_INSN(vle256ff_v, MATCH_VLE256FF_V, MASK_VLE256FF_V) +DECLARE_INSN(vle32_v, MATCH_VLE32_V, MASK_VLE32_V) +DECLARE_INSN(vle32ff_v, MATCH_VLE32FF_V, MASK_VLE32FF_V) +DECLARE_INSN(vle512_v, MATCH_VLE512_V, MASK_VLE512_V) +DECLARE_INSN(vle512ff_v, MATCH_VLE512FF_V, MASK_VLE512FF_V) +DECLARE_INSN(vle64_v, MATCH_VLE64_V, MASK_VLE64_V) +DECLARE_INSN(vle64ff_v, MATCH_VLE64FF_V, MASK_VLE64FF_V) +DECLARE_INSN(vle8_v, MATCH_VLE8_V, MASK_VLE8_V) +DECLARE_INSN(vle8ff_v, MATCH_VLE8FF_V, MASK_VLE8FF_V) +DECLARE_INSN(vlm_v, MATCH_VLM_V, MASK_VLM_V) +DECLARE_INSN(vloxei1024_v, MATCH_VLOXEI1024_V, MASK_VLOXEI1024_V) +DECLARE_INSN(vloxei128_v, MATCH_VLOXEI128_V, MASK_VLOXEI128_V) +DECLARE_INSN(vloxei16_v, MATCH_VLOXEI16_V, MASK_VLOXEI16_V) +DECLARE_INSN(vloxei256_v, MATCH_VLOXEI256_V, MASK_VLOXEI256_V) +DECLARE_INSN(vloxei32_v, MATCH_VLOXEI32_V, MASK_VLOXEI32_V) +DECLARE_INSN(vloxei512_v, MATCH_VLOXEI512_V, MASK_VLOXEI512_V) +DECLARE_INSN(vloxei64_v, MATCH_VLOXEI64_V, MASK_VLOXEI64_V) +DECLARE_INSN(vloxei8_v, MATCH_VLOXEI8_V, MASK_VLOXEI8_V) +DECLARE_INSN(vlse1024_v, MATCH_VLSE1024_V, MASK_VLSE1024_V) +DECLARE_INSN(vlse128_v, MATCH_VLSE128_V, MASK_VLSE128_V) +DECLARE_INSN(vlse16_v, MATCH_VLSE16_V, MASK_VLSE16_V) +DECLARE_INSN(vlse256_v, MATCH_VLSE256_V, MASK_VLSE256_V) +DECLARE_INSN(vlse32_v, MATCH_VLSE32_V, MASK_VLSE32_V) +DECLARE_INSN(vlse512_v, MATCH_VLSE512_V, MASK_VLSE512_V) +DECLARE_INSN(vlse64_v, MATCH_VLSE64_V, MASK_VLSE64_V) +DECLARE_INSN(vlse8_v, MATCH_VLSE8_V, MASK_VLSE8_V) +DECLARE_INSN(vluxei1024_v, MATCH_VLUXEI1024_V, MASK_VLUXEI1024_V) +DECLARE_INSN(vluxei128_v, MATCH_VLUXEI128_V, MASK_VLUXEI128_V) +DECLARE_INSN(vluxei16_v, MATCH_VLUXEI16_V, MASK_VLUXEI16_V) +DECLARE_INSN(vluxei256_v, MATCH_VLUXEI256_V, MASK_VLUXEI256_V) +DECLARE_INSN(vluxei32_v, MATCH_VLUXEI32_V, MASK_VLUXEI32_V) +DECLARE_INSN(vluxei512_v, MATCH_VLUXEI512_V, MASK_VLUXEI512_V) +DECLARE_INSN(vluxei64_v, MATCH_VLUXEI64_V, MASK_VLUXEI64_V) +DECLARE_INSN(vluxei8_v, MATCH_VLUXEI8_V, MASK_VLUXEI8_V) +DECLARE_INSN(vmacc_vv, MATCH_VMACC_VV, MASK_VMACC_VV) +DECLARE_INSN(vmacc_vx, MATCH_VMACC_VX, MASK_VMACC_VX) +DECLARE_INSN(vmadc_vi, MATCH_VMADC_VI, MASK_VMADC_VI) +DECLARE_INSN(vmadc_vim, MATCH_VMADC_VIM, MASK_VMADC_VIM) +DECLARE_INSN(vmadc_vv, MATCH_VMADC_VV, MASK_VMADC_VV) +DECLARE_INSN(vmadc_vvm, MATCH_VMADC_VVM, MASK_VMADC_VVM) +DECLARE_INSN(vmadc_vx, MATCH_VMADC_VX, MASK_VMADC_VX) +DECLARE_INSN(vmadc_vxm, MATCH_VMADC_VXM, MASK_VMADC_VXM) +DECLARE_INSN(vmadd_vv, MATCH_VMADD_VV, MASK_VMADD_VV) +DECLARE_INSN(vmadd_vx, MATCH_VMADD_VX, MASK_VMADD_VX) +DECLARE_INSN(vmand_mm, MATCH_VMAND_MM, MASK_VMAND_MM) +DECLARE_INSN(vmandn_mm, MATCH_VMANDN_MM, MASK_VMANDN_MM) +DECLARE_INSN(vmax_vv, MATCH_VMAX_VV, MASK_VMAX_VV) +DECLARE_INSN(vmax_vx, MATCH_VMAX_VX, MASK_VMAX_VX) +DECLARE_INSN(vmaxu_vv, MATCH_VMAXU_VV, MASK_VMAXU_VV) +DECLARE_INSN(vmaxu_vx, MATCH_VMAXU_VX, MASK_VMAXU_VX) +DECLARE_INSN(vmerge_vim, MATCH_VMERGE_VIM, MASK_VMERGE_VIM) +DECLARE_INSN(vmerge_vvm, MATCH_VMERGE_VVM, MASK_VMERGE_VVM) +DECLARE_INSN(vmerge_vxm, MATCH_VMERGE_VXM, MASK_VMERGE_VXM) +DECLARE_INSN(vmfeq_vf, MATCH_VMFEQ_VF, MASK_VMFEQ_VF) +DECLARE_INSN(vmfeq_vv, MATCH_VMFEQ_VV, MASK_VMFEQ_VV) +DECLARE_INSN(vmfge_vf, MATCH_VMFGE_VF, MASK_VMFGE_VF) +DECLARE_INSN(vmfgt_vf, MATCH_VMFGT_VF, MASK_VMFGT_VF) +DECLARE_INSN(vmfle_vf, MATCH_VMFLE_VF, MASK_VMFLE_VF) +DECLARE_INSN(vmfle_vv, MATCH_VMFLE_VV, MASK_VMFLE_VV) +DECLARE_INSN(vmflt_vf, MATCH_VMFLT_VF, MASK_VMFLT_VF) +DECLARE_INSN(vmflt_vv, MATCH_VMFLT_VV, MASK_VMFLT_VV) +DECLARE_INSN(vmfne_vf, MATCH_VMFNE_VF, MASK_VMFNE_VF) +DECLARE_INSN(vmfne_vv, MATCH_VMFNE_VV, MASK_VMFNE_VV) +DECLARE_INSN(vmin_vv, MATCH_VMIN_VV, MASK_VMIN_VV) +DECLARE_INSN(vmin_vx, MATCH_VMIN_VX, MASK_VMIN_VX) +DECLARE_INSN(vminu_vv, MATCH_VMINU_VV, MASK_VMINU_VV) +DECLARE_INSN(vminu_vx, MATCH_VMINU_VX, MASK_VMINU_VX) +DECLARE_INSN(vmnand_mm, MATCH_VMNAND_MM, MASK_VMNAND_MM) +DECLARE_INSN(vmnor_mm, MATCH_VMNOR_MM, MASK_VMNOR_MM) +DECLARE_INSN(vmor_mm, MATCH_VMOR_MM, MASK_VMOR_MM) +DECLARE_INSN(vmorn_mm, MATCH_VMORN_MM, MASK_VMORN_MM) +DECLARE_INSN(vmsbc_vv, MATCH_VMSBC_VV, MASK_VMSBC_VV) +DECLARE_INSN(vmsbc_vvm, MATCH_VMSBC_VVM, MASK_VMSBC_VVM) +DECLARE_INSN(vmsbc_vx, MATCH_VMSBC_VX, MASK_VMSBC_VX) +DECLARE_INSN(vmsbc_vxm, MATCH_VMSBC_VXM, MASK_VMSBC_VXM) +DECLARE_INSN(vmsbf_m, MATCH_VMSBF_M, MASK_VMSBF_M) +DECLARE_INSN(vmseq_vi, MATCH_VMSEQ_VI, MASK_VMSEQ_VI) +DECLARE_INSN(vmseq_vv, MATCH_VMSEQ_VV, MASK_VMSEQ_VV) +DECLARE_INSN(vmseq_vx, MATCH_VMSEQ_VX, MASK_VMSEQ_VX) +DECLARE_INSN(vmsgt_vi, MATCH_VMSGT_VI, MASK_VMSGT_VI) +DECLARE_INSN(vmsgt_vx, MATCH_VMSGT_VX, MASK_VMSGT_VX) +DECLARE_INSN(vmsgtu_vi, MATCH_VMSGTU_VI, MASK_VMSGTU_VI) +DECLARE_INSN(vmsgtu_vx, MATCH_VMSGTU_VX, MASK_VMSGTU_VX) +DECLARE_INSN(vmsif_m, MATCH_VMSIF_M, MASK_VMSIF_M) +DECLARE_INSN(vmsle_vi, MATCH_VMSLE_VI, MASK_VMSLE_VI) +DECLARE_INSN(vmsle_vv, MATCH_VMSLE_VV, MASK_VMSLE_VV) +DECLARE_INSN(vmsle_vx, MATCH_VMSLE_VX, MASK_VMSLE_VX) +DECLARE_INSN(vmsleu_vi, MATCH_VMSLEU_VI, MASK_VMSLEU_VI) +DECLARE_INSN(vmsleu_vv, MATCH_VMSLEU_VV, MASK_VMSLEU_VV) +DECLARE_INSN(vmsleu_vx, MATCH_VMSLEU_VX, MASK_VMSLEU_VX) +DECLARE_INSN(vmslt_vv, MATCH_VMSLT_VV, MASK_VMSLT_VV) +DECLARE_INSN(vmslt_vx, MATCH_VMSLT_VX, MASK_VMSLT_VX) +DECLARE_INSN(vmsltu_vv, MATCH_VMSLTU_VV, MASK_VMSLTU_VV) +DECLARE_INSN(vmsltu_vx, MATCH_VMSLTU_VX, MASK_VMSLTU_VX) +DECLARE_INSN(vmsne_vi, MATCH_VMSNE_VI, MASK_VMSNE_VI) +DECLARE_INSN(vmsne_vv, MATCH_VMSNE_VV, MASK_VMSNE_VV) +DECLARE_INSN(vmsne_vx, MATCH_VMSNE_VX, MASK_VMSNE_VX) +DECLARE_INSN(vmsof_m, MATCH_VMSOF_M, MASK_VMSOF_M) +DECLARE_INSN(vmul_vv, MATCH_VMUL_VV, MASK_VMUL_VV) +DECLARE_INSN(vmul_vx, MATCH_VMUL_VX, MASK_VMUL_VX) +DECLARE_INSN(vmulh_vv, MATCH_VMULH_VV, MASK_VMULH_VV) +DECLARE_INSN(vmulh_vx, MATCH_VMULH_VX, MASK_VMULH_VX) +DECLARE_INSN(vmulhsu_vv, MATCH_VMULHSU_VV, MASK_VMULHSU_VV) +DECLARE_INSN(vmulhsu_vx, MATCH_VMULHSU_VX, MASK_VMULHSU_VX) +DECLARE_INSN(vmulhu_vv, MATCH_VMULHU_VV, MASK_VMULHU_VV) +DECLARE_INSN(vmulhu_vx, MATCH_VMULHU_VX, MASK_VMULHU_VX) +DECLARE_INSN(vmv1r_v, MATCH_VMV1R_V, MASK_VMV1R_V) +DECLARE_INSN(vmv2r_v, MATCH_VMV2R_V, MASK_VMV2R_V) +DECLARE_INSN(vmv4r_v, MATCH_VMV4R_V, MASK_VMV4R_V) +DECLARE_INSN(vmv8r_v, MATCH_VMV8R_V, MASK_VMV8R_V) +DECLARE_INSN(vmv_s_x, MATCH_VMV_S_X, MASK_VMV_S_X) +DECLARE_INSN(vmv_v_i, MATCH_VMV_V_I, MASK_VMV_V_I) +DECLARE_INSN(vmv_v_v, MATCH_VMV_V_V, MASK_VMV_V_V) +DECLARE_INSN(vmv_v_x, MATCH_VMV_V_X, MASK_VMV_V_X) +DECLARE_INSN(vmv_x_s, MATCH_VMV_X_S, MASK_VMV_X_S) +DECLARE_INSN(vmxnor_mm, MATCH_VMXNOR_MM, MASK_VMXNOR_MM) +DECLARE_INSN(vmxor_mm, MATCH_VMXOR_MM, MASK_VMXOR_MM) +DECLARE_INSN(vnclip_wi, MATCH_VNCLIP_WI, MASK_VNCLIP_WI) +DECLARE_INSN(vnclip_wv, MATCH_VNCLIP_WV, MASK_VNCLIP_WV) +DECLARE_INSN(vnclip_wx, MATCH_VNCLIP_WX, MASK_VNCLIP_WX) +DECLARE_INSN(vnclipu_wi, MATCH_VNCLIPU_WI, MASK_VNCLIPU_WI) +DECLARE_INSN(vnclipu_wv, MATCH_VNCLIPU_WV, MASK_VNCLIPU_WV) +DECLARE_INSN(vnclipu_wx, MATCH_VNCLIPU_WX, MASK_VNCLIPU_WX) +DECLARE_INSN(vnmsac_vv, MATCH_VNMSAC_VV, MASK_VNMSAC_VV) +DECLARE_INSN(vnmsac_vx, MATCH_VNMSAC_VX, MASK_VNMSAC_VX) +DECLARE_INSN(vnmsub_vv, MATCH_VNMSUB_VV, MASK_VNMSUB_VV) +DECLARE_INSN(vnmsub_vx, MATCH_VNMSUB_VX, MASK_VNMSUB_VX) +DECLARE_INSN(vnsra_wi, MATCH_VNSRA_WI, MASK_VNSRA_WI) +DECLARE_INSN(vnsra_wv, MATCH_VNSRA_WV, MASK_VNSRA_WV) +DECLARE_INSN(vnsra_wx, MATCH_VNSRA_WX, MASK_VNSRA_WX) +DECLARE_INSN(vnsrl_wi, MATCH_VNSRL_WI, MASK_VNSRL_WI) +DECLARE_INSN(vnsrl_wv, MATCH_VNSRL_WV, MASK_VNSRL_WV) +DECLARE_INSN(vnsrl_wx, MATCH_VNSRL_WX, MASK_VNSRL_WX) +DECLARE_INSN(vor_vi, MATCH_VOR_VI, MASK_VOR_VI) +DECLARE_INSN(vor_vv, MATCH_VOR_VV, MASK_VOR_VV) +DECLARE_INSN(vor_vx, MATCH_VOR_VX, MASK_VOR_VX) +DECLARE_INSN(vredand_vs, MATCH_VREDAND_VS, MASK_VREDAND_VS) +DECLARE_INSN(vredmax_vs, MATCH_VREDMAX_VS, MASK_VREDMAX_VS) +DECLARE_INSN(vredmaxu_vs, MATCH_VREDMAXU_VS, MASK_VREDMAXU_VS) +DECLARE_INSN(vredmin_vs, MATCH_VREDMIN_VS, MASK_VREDMIN_VS) +DECLARE_INSN(vredminu_vs, MATCH_VREDMINU_VS, MASK_VREDMINU_VS) +DECLARE_INSN(vredor_vs, MATCH_VREDOR_VS, MASK_VREDOR_VS) +DECLARE_INSN(vredsum_vs, MATCH_VREDSUM_VS, MASK_VREDSUM_VS) +DECLARE_INSN(vredxor_vs, MATCH_VREDXOR_VS, MASK_VREDXOR_VS) +DECLARE_INSN(vrem_vv, MATCH_VREM_VV, MASK_VREM_VV) +DECLARE_INSN(vrem_vx, MATCH_VREM_VX, MASK_VREM_VX) +DECLARE_INSN(vremu_vv, MATCH_VREMU_VV, MASK_VREMU_VV) +DECLARE_INSN(vremu_vx, MATCH_VREMU_VX, MASK_VREMU_VX) +DECLARE_INSN(vrgather_vi, MATCH_VRGATHER_VI, MASK_VRGATHER_VI) +DECLARE_INSN(vrgather_vv, MATCH_VRGATHER_VV, MASK_VRGATHER_VV) +DECLARE_INSN(vrgather_vx, MATCH_VRGATHER_VX, MASK_VRGATHER_VX) +DECLARE_INSN(vrgatherei16_vv, MATCH_VRGATHEREI16_VV, MASK_VRGATHEREI16_VV) +DECLARE_INSN(vrsub_vi, MATCH_VRSUB_VI, MASK_VRSUB_VI) +DECLARE_INSN(vrsub_vx, MATCH_VRSUB_VX, MASK_VRSUB_VX) +DECLARE_INSN(vs1r_v, MATCH_VS1R_V, MASK_VS1R_V) +DECLARE_INSN(vs2r_v, MATCH_VS2R_V, MASK_VS2R_V) +DECLARE_INSN(vs4r_v, MATCH_VS4R_V, MASK_VS4R_V) +DECLARE_INSN(vs8r_v, MATCH_VS8R_V, MASK_VS8R_V) +DECLARE_INSN(vsadd_vi, MATCH_VSADD_VI, MASK_VSADD_VI) +DECLARE_INSN(vsadd_vv, MATCH_VSADD_VV, MASK_VSADD_VV) +DECLARE_INSN(vsadd_vx, MATCH_VSADD_VX, MASK_VSADD_VX) +DECLARE_INSN(vsaddu_vi, MATCH_VSADDU_VI, MASK_VSADDU_VI) +DECLARE_INSN(vsaddu_vv, MATCH_VSADDU_VV, MASK_VSADDU_VV) +DECLARE_INSN(vsaddu_vx, MATCH_VSADDU_VX, MASK_VSADDU_VX) +DECLARE_INSN(vsbc_vvm, MATCH_VSBC_VVM, MASK_VSBC_VVM) +DECLARE_INSN(vsbc_vxm, MATCH_VSBC_VXM, MASK_VSBC_VXM) +DECLARE_INSN(vse1024_v, MATCH_VSE1024_V, MASK_VSE1024_V) +DECLARE_INSN(vse128_v, MATCH_VSE128_V, MASK_VSE128_V) +DECLARE_INSN(vse16_v, MATCH_VSE16_V, MASK_VSE16_V) +DECLARE_INSN(vse256_v, MATCH_VSE256_V, MASK_VSE256_V) +DECLARE_INSN(vse32_v, MATCH_VSE32_V, MASK_VSE32_V) +DECLARE_INSN(vse512_v, MATCH_VSE512_V, MASK_VSE512_V) +DECLARE_INSN(vse64_v, MATCH_VSE64_V, MASK_VSE64_V) +DECLARE_INSN(vse8_v, MATCH_VSE8_V, MASK_VSE8_V) +DECLARE_INSN(vsetivli, MATCH_VSETIVLI, MASK_VSETIVLI) +DECLARE_INSN(vsetvl, MATCH_VSETVL, MASK_VSETVL) +DECLARE_INSN(vsetvli, MATCH_VSETVLI, MASK_VSETVLI) +DECLARE_INSN(vsext_vf2, MATCH_VSEXT_VF2, MASK_VSEXT_VF2) +DECLARE_INSN(vsext_vf4, MATCH_VSEXT_VF4, MASK_VSEXT_VF4) +DECLARE_INSN(vsext_vf8, MATCH_VSEXT_VF8, MASK_VSEXT_VF8) +DECLARE_INSN(vslide1down_vx, MATCH_VSLIDE1DOWN_VX, MASK_VSLIDE1DOWN_VX) +DECLARE_INSN(vslide1up_vx, MATCH_VSLIDE1UP_VX, MASK_VSLIDE1UP_VX) +DECLARE_INSN(vslidedown_vi, MATCH_VSLIDEDOWN_VI, MASK_VSLIDEDOWN_VI) +DECLARE_INSN(vslidedown_vx, MATCH_VSLIDEDOWN_VX, MASK_VSLIDEDOWN_VX) +DECLARE_INSN(vslideup_vi, MATCH_VSLIDEUP_VI, MASK_VSLIDEUP_VI) +DECLARE_INSN(vslideup_vx, MATCH_VSLIDEUP_VX, MASK_VSLIDEUP_VX) +DECLARE_INSN(vsll_vi, MATCH_VSLL_VI, MASK_VSLL_VI) +DECLARE_INSN(vsll_vv, MATCH_VSLL_VV, MASK_VSLL_VV) +DECLARE_INSN(vsll_vx, MATCH_VSLL_VX, MASK_VSLL_VX) +DECLARE_INSN(vsm_v, MATCH_VSM_V, MASK_VSM_V) +DECLARE_INSN(vsmul_vv, MATCH_VSMUL_VV, MASK_VSMUL_VV) +DECLARE_INSN(vsmul_vx, MATCH_VSMUL_VX, MASK_VSMUL_VX) +DECLARE_INSN(vsoxei1024_v, MATCH_VSOXEI1024_V, MASK_VSOXEI1024_V) +DECLARE_INSN(vsoxei128_v, MATCH_VSOXEI128_V, MASK_VSOXEI128_V) +DECLARE_INSN(vsoxei16_v, MATCH_VSOXEI16_V, MASK_VSOXEI16_V) +DECLARE_INSN(vsoxei256_v, MATCH_VSOXEI256_V, MASK_VSOXEI256_V) +DECLARE_INSN(vsoxei32_v, MATCH_VSOXEI32_V, MASK_VSOXEI32_V) +DECLARE_INSN(vsoxei512_v, MATCH_VSOXEI512_V, MASK_VSOXEI512_V) +DECLARE_INSN(vsoxei64_v, MATCH_VSOXEI64_V, MASK_VSOXEI64_V) +DECLARE_INSN(vsoxei8_v, MATCH_VSOXEI8_V, MASK_VSOXEI8_V) +DECLARE_INSN(vsra_vi, MATCH_VSRA_VI, MASK_VSRA_VI) +DECLARE_INSN(vsra_vv, MATCH_VSRA_VV, MASK_VSRA_VV) +DECLARE_INSN(vsra_vx, MATCH_VSRA_VX, MASK_VSRA_VX) +DECLARE_INSN(vsrl_vi, MATCH_VSRL_VI, MASK_VSRL_VI) +DECLARE_INSN(vsrl_vv, MATCH_VSRL_VV, MASK_VSRL_VV) +DECLARE_INSN(vsrl_vx, MATCH_VSRL_VX, MASK_VSRL_VX) +DECLARE_INSN(vsse1024_v, MATCH_VSSE1024_V, MASK_VSSE1024_V) +DECLARE_INSN(vsse128_v, MATCH_VSSE128_V, MASK_VSSE128_V) +DECLARE_INSN(vsse16_v, MATCH_VSSE16_V, MASK_VSSE16_V) +DECLARE_INSN(vsse256_v, MATCH_VSSE256_V, MASK_VSSE256_V) +DECLARE_INSN(vsse32_v, MATCH_VSSE32_V, MASK_VSSE32_V) +DECLARE_INSN(vsse512_v, MATCH_VSSE512_V, MASK_VSSE512_V) +DECLARE_INSN(vsse64_v, MATCH_VSSE64_V, MASK_VSSE64_V) +DECLARE_INSN(vsse8_v, MATCH_VSSE8_V, MASK_VSSE8_V) +DECLARE_INSN(vssra_vi, MATCH_VSSRA_VI, MASK_VSSRA_VI) +DECLARE_INSN(vssra_vv, MATCH_VSSRA_VV, MASK_VSSRA_VV) +DECLARE_INSN(vssra_vx, MATCH_VSSRA_VX, MASK_VSSRA_VX) +DECLARE_INSN(vssrl_vi, MATCH_VSSRL_VI, MASK_VSSRL_VI) +DECLARE_INSN(vssrl_vv, MATCH_VSSRL_VV, MASK_VSSRL_VV) +DECLARE_INSN(vssrl_vx, MATCH_VSSRL_VX, MASK_VSSRL_VX) +DECLARE_INSN(vssub_vv, MATCH_VSSUB_VV, MASK_VSSUB_VV) +DECLARE_INSN(vssub_vx, MATCH_VSSUB_VX, MASK_VSSUB_VX) +DECLARE_INSN(vssubu_vv, MATCH_VSSUBU_VV, MASK_VSSUBU_VV) +DECLARE_INSN(vssubu_vx, MATCH_VSSUBU_VX, MASK_VSSUBU_VX) +DECLARE_INSN(vsub_vv, MATCH_VSUB_VV, MASK_VSUB_VV) +DECLARE_INSN(vsub_vx, MATCH_VSUB_VX, MASK_VSUB_VX) +DECLARE_INSN(vsuxei1024_v, MATCH_VSUXEI1024_V, MASK_VSUXEI1024_V) +DECLARE_INSN(vsuxei128_v, MATCH_VSUXEI128_V, MASK_VSUXEI128_V) +DECLARE_INSN(vsuxei16_v, MATCH_VSUXEI16_V, MASK_VSUXEI16_V) +DECLARE_INSN(vsuxei256_v, MATCH_VSUXEI256_V, MASK_VSUXEI256_V) +DECLARE_INSN(vsuxei32_v, MATCH_VSUXEI32_V, MASK_VSUXEI32_V) +DECLARE_INSN(vsuxei512_v, MATCH_VSUXEI512_V, MASK_VSUXEI512_V) +DECLARE_INSN(vsuxei64_v, MATCH_VSUXEI64_V, MASK_VSUXEI64_V) +DECLARE_INSN(vsuxei8_v, MATCH_VSUXEI8_V, MASK_VSUXEI8_V) +DECLARE_INSN(vwadd_vv, MATCH_VWADD_VV, MASK_VWADD_VV) +DECLARE_INSN(vwadd_vx, MATCH_VWADD_VX, MASK_VWADD_VX) +DECLARE_INSN(vwadd_wv, MATCH_VWADD_WV, MASK_VWADD_WV) +DECLARE_INSN(vwadd_wx, MATCH_VWADD_WX, MASK_VWADD_WX) +DECLARE_INSN(vwaddu_vv, MATCH_VWADDU_VV, MASK_VWADDU_VV) +DECLARE_INSN(vwaddu_vx, MATCH_VWADDU_VX, MASK_VWADDU_VX) +DECLARE_INSN(vwaddu_wv, MATCH_VWADDU_WV, MASK_VWADDU_WV) +DECLARE_INSN(vwaddu_wx, MATCH_VWADDU_WX, MASK_VWADDU_WX) +DECLARE_INSN(vwmacc_vv, MATCH_VWMACC_VV, MASK_VWMACC_VV) +DECLARE_INSN(vwmacc_vx, MATCH_VWMACC_VX, MASK_VWMACC_VX) +DECLARE_INSN(vwmaccsu_vv, MATCH_VWMACCSU_VV, MASK_VWMACCSU_VV) +DECLARE_INSN(vwmaccsu_vx, MATCH_VWMACCSU_VX, MASK_VWMACCSU_VX) +DECLARE_INSN(vwmaccu_vv, MATCH_VWMACCU_VV, MASK_VWMACCU_VV) +DECLARE_INSN(vwmaccu_vx, MATCH_VWMACCU_VX, MASK_VWMACCU_VX) +DECLARE_INSN(vwmaccus_vx, MATCH_VWMACCUS_VX, MASK_VWMACCUS_VX) +DECLARE_INSN(vwmul_vv, MATCH_VWMUL_VV, MASK_VWMUL_VV) +DECLARE_INSN(vwmul_vx, MATCH_VWMUL_VX, MASK_VWMUL_VX) +DECLARE_INSN(vwmulsu_vv, MATCH_VWMULSU_VV, MASK_VWMULSU_VV) +DECLARE_INSN(vwmulsu_vx, MATCH_VWMULSU_VX, MASK_VWMULSU_VX) +DECLARE_INSN(vwmulu_vv, MATCH_VWMULU_VV, MASK_VWMULU_VV) +DECLARE_INSN(vwmulu_vx, MATCH_VWMULU_VX, MASK_VWMULU_VX) +DECLARE_INSN(vwredsum_vs, MATCH_VWREDSUM_VS, MASK_VWREDSUM_VS) +DECLARE_INSN(vwredsumu_vs, MATCH_VWREDSUMU_VS, MASK_VWREDSUMU_VS) +DECLARE_INSN(vwsub_vv, MATCH_VWSUB_VV, MASK_VWSUB_VV) +DECLARE_INSN(vwsub_vx, MATCH_VWSUB_VX, MASK_VWSUB_VX) +DECLARE_INSN(vwsub_wv, MATCH_VWSUB_WV, MASK_VWSUB_WV) +DECLARE_INSN(vwsub_wx, MATCH_VWSUB_WX, MASK_VWSUB_WX) +DECLARE_INSN(vwsubu_vv, MATCH_VWSUBU_VV, MASK_VWSUBU_VV) +DECLARE_INSN(vwsubu_vx, MATCH_VWSUBU_VX, MASK_VWSUBU_VX) +DECLARE_INSN(vwsubu_wv, MATCH_VWSUBU_WV, MASK_VWSUBU_WV) +DECLARE_INSN(vwsubu_wx, MATCH_VWSUBU_WX, MASK_VWSUBU_WX) +DECLARE_INSN(vxor_vi, MATCH_VXOR_VI, MASK_VXOR_VI) +DECLARE_INSN(vxor_vv, MATCH_VXOR_VV, MASK_VXOR_VV) +DECLARE_INSN(vxor_vx, MATCH_VXOR_VX, MASK_VXOR_VX) +DECLARE_INSN(vzext_vf2, MATCH_VZEXT_VF2, MASK_VZEXT_VF2) +DECLARE_INSN(vzext_vf4, MATCH_VZEXT_VF4, MASK_VZEXT_VF4) +DECLARE_INSN(vzext_vf8, MATCH_VZEXT_VF8, MASK_VZEXT_VF8) +DECLARE_INSN(wext, MATCH_WEXT, MASK_WEXT) +DECLARE_INSN(wexti, MATCH_WEXTI, MASK_WEXTI) +DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) +DECLARE_INSN(wrs_nto, MATCH_WRS_NTO, MASK_WRS_NTO) +DECLARE_INSN(wrs_sto, MATCH_WRS_STO, MASK_WRS_STO) +DECLARE_INSN(xnor, MATCH_XNOR, MASK_XNOR) +DECLARE_INSN(xor, MATCH_XOR, MASK_XOR) +DECLARE_INSN(xori, MATCH_XORI, MASK_XORI) +DECLARE_INSN(xperm16, MATCH_XPERM16, MASK_XPERM16) +DECLARE_INSN(xperm32, MATCH_XPERM32, MASK_XPERM32) +DECLARE_INSN(xperm4, MATCH_XPERM4, MASK_XPERM4) +DECLARE_INSN(xperm8, MATCH_XPERM8, MASK_XPERM8) +DECLARE_INSN(zunpkd810, MATCH_ZUNPKD810, MASK_ZUNPKD810) +DECLARE_INSN(zunpkd820, MATCH_ZUNPKD820, MASK_ZUNPKD820) +DECLARE_INSN(zunpkd830, MATCH_ZUNPKD830, MASK_ZUNPKD830) +DECLARE_INSN(zunpkd831, MATCH_ZUNPKD831, MASK_ZUNPKD831) +DECLARE_INSN(zunpkd832, MATCH_ZUNPKD832, MASK_ZUNPKD832) +#endif +#ifdef DECLARE_CSR +DECLARE_CSR(fflags, CSR_FFLAGS) +DECLARE_CSR(frm, CSR_FRM) +DECLARE_CSR(fcsr, CSR_FCSR) +DECLARE_CSR(vstart, CSR_VSTART) +DECLARE_CSR(vxsat, CSR_VXSAT) +DECLARE_CSR(vxrm, CSR_VXRM) +DECLARE_CSR(vcsr, CSR_VCSR) +DECLARE_CSR(seed, CSR_SEED) +DECLARE_CSR(cycle, CSR_CYCLE) +DECLARE_CSR(time, CSR_TIME) +DECLARE_CSR(instret, CSR_INSTRET) +DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3) +DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4) +DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5) +DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6) +DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7) +DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8) +DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9) +DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10) +DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11) +DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12) +DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13) +DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14) +DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15) +DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16) +DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17) +DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18) +DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19) +DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20) +DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21) +DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22) +DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23) +DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24) +DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25) +DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26) +DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27) +DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28) +DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29) +DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30) +DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) +DECLARE_CSR(vl, CSR_VL) +DECLARE_CSR(vtype, CSR_VTYPE) +DECLARE_CSR(vlenb, CSR_VLENB) +DECLARE_CSR(sstatus, CSR_SSTATUS) +DECLARE_CSR(sedeleg, CSR_SEDELEG) +DECLARE_CSR(sideleg, CSR_SIDELEG) +DECLARE_CSR(sie, CSR_SIE) +DECLARE_CSR(stvec, CSR_STVEC) +DECLARE_CSR(scounteren, CSR_SCOUNTEREN) +DECLARE_CSR(senvcfg, CSR_SENVCFG) +DECLARE_CSR(sstateen0, CSR_SSTATEEN0) +DECLARE_CSR(sstateen1, CSR_SSTATEEN1) +DECLARE_CSR(sstateen2, CSR_SSTATEEN2) +DECLARE_CSR(sstateen3, CSR_SSTATEEN3) +DECLARE_CSR(sscratch, CSR_SSCRATCH) +DECLARE_CSR(sepc, CSR_SEPC) +DECLARE_CSR(scause, CSR_SCAUSE) +DECLARE_CSR(stval, CSR_STVAL) +DECLARE_CSR(sip, CSR_SIP) +DECLARE_CSR(stimecmp, CSR_STIMECMP) +DECLARE_CSR(satp, CSR_SATP) +DECLARE_CSR(scontext, CSR_SCONTEXT) +DECLARE_CSR(vsstatus, CSR_VSSTATUS) +DECLARE_CSR(vsie, CSR_VSIE) +DECLARE_CSR(vstvec, CSR_VSTVEC) +DECLARE_CSR(vsscratch, CSR_VSSCRATCH) +DECLARE_CSR(vsepc, CSR_VSEPC) +DECLARE_CSR(vscause, CSR_VSCAUSE) +DECLARE_CSR(vstval, CSR_VSTVAL) +DECLARE_CSR(vsip, CSR_VSIP) +DECLARE_CSR(vstimecmp, CSR_VSTIMECMP) +DECLARE_CSR(vsatp, CSR_VSATP) +DECLARE_CSR(hstatus, CSR_HSTATUS) +DECLARE_CSR(hedeleg, CSR_HEDELEG) +DECLARE_CSR(hideleg, CSR_HIDELEG) +DECLARE_CSR(hie, CSR_HIE) +DECLARE_CSR(htimedelta, CSR_HTIMEDELTA) +DECLARE_CSR(hcounteren, CSR_HCOUNTEREN) +DECLARE_CSR(hgeie, CSR_HGEIE) +DECLARE_CSR(henvcfg, CSR_HENVCFG) +DECLARE_CSR(hstateen0, CSR_HSTATEEN0) +DECLARE_CSR(hstateen1, CSR_HSTATEEN1) +DECLARE_CSR(hstateen2, CSR_HSTATEEN2) +DECLARE_CSR(hstateen3, CSR_HSTATEEN3) +DECLARE_CSR(htval, CSR_HTVAL) +DECLARE_CSR(hip, CSR_HIP) +DECLARE_CSR(hvip, CSR_HVIP) +DECLARE_CSR(htinst, CSR_HTINST) +DECLARE_CSR(hgatp, CSR_HGATP) +DECLARE_CSR(hcontext, CSR_HCONTEXT) +DECLARE_CSR(hgeip, CSR_HGEIP) +DECLARE_CSR(scountovf, CSR_SCOUNTOVF) +DECLARE_CSR(utvt, CSR_UTVT) +DECLARE_CSR(unxti, CSR_UNXTI) +DECLARE_CSR(uintstatus, CSR_UINTSTATUS) +DECLARE_CSR(uscratchcsw, CSR_USCRATCHCSW) +DECLARE_CSR(uscratchcswl, CSR_USCRATCHCSWL) +DECLARE_CSR(stvt, CSR_STVT) +DECLARE_CSR(snxti, CSR_SNXTI) +DECLARE_CSR(sintstatus, CSR_SINTSTATUS) +DECLARE_CSR(sscratchcsw, CSR_SSCRATCHCSW) +DECLARE_CSR(sscratchcswl, CSR_SSCRATCHCSWL) +DECLARE_CSR(mtvt, CSR_MTVT) +DECLARE_CSR(mnxti, CSR_MNXTI) +DECLARE_CSR(mintstatus, CSR_MINTSTATUS) +DECLARE_CSR(mscratchcsw, CSR_MSCRATCHCSW) +DECLARE_CSR(mscratchcswl, CSR_MSCRATCHCSWL) +DECLARE_CSR(mstatus, CSR_MSTATUS) +DECLARE_CSR(misa, CSR_MISA) +DECLARE_CSR(medeleg, CSR_MEDELEG) +DECLARE_CSR(mideleg, CSR_MIDELEG) +DECLARE_CSR(mie, CSR_MIE) +DECLARE_CSR(mtvec, CSR_MTVEC) +DECLARE_CSR(mcounteren, CSR_MCOUNTEREN) +DECLARE_CSR(menvcfg, CSR_MENVCFG) +DECLARE_CSR(mstateen0, CSR_MSTATEEN0) +DECLARE_CSR(mstateen1, CSR_MSTATEEN1) +DECLARE_CSR(mstateen2, CSR_MSTATEEN2) +DECLARE_CSR(mstateen3, CSR_MSTATEEN3) +DECLARE_CSR(mcountinhibit, CSR_MCOUNTINHIBIT) +DECLARE_CSR(mscratch, CSR_MSCRATCH) +DECLARE_CSR(mepc, CSR_MEPC) +DECLARE_CSR(mcause, CSR_MCAUSE) +DECLARE_CSR(mtval, CSR_MTVAL) +DECLARE_CSR(mip, CSR_MIP) +DECLARE_CSR(mtinst, CSR_MTINST) +DECLARE_CSR(mtval2, CSR_MTVAL2) +DECLARE_CSR(pmpcfg0, CSR_PMPCFG0) +DECLARE_CSR(pmpcfg1, CSR_PMPCFG1) +DECLARE_CSR(pmpcfg2, CSR_PMPCFG2) +DECLARE_CSR(pmpcfg3, CSR_PMPCFG3) +DECLARE_CSR(pmpcfg4, CSR_PMPCFG4) +DECLARE_CSR(pmpcfg5, CSR_PMPCFG5) +DECLARE_CSR(pmpcfg6, CSR_PMPCFG6) +DECLARE_CSR(pmpcfg7, CSR_PMPCFG7) +DECLARE_CSR(pmpcfg8, CSR_PMPCFG8) +DECLARE_CSR(pmpcfg9, CSR_PMPCFG9) +DECLARE_CSR(pmpcfg10, CSR_PMPCFG10) +DECLARE_CSR(pmpcfg11, CSR_PMPCFG11) +DECLARE_CSR(pmpcfg12, CSR_PMPCFG12) +DECLARE_CSR(pmpcfg13, CSR_PMPCFG13) +DECLARE_CSR(pmpcfg14, CSR_PMPCFG14) +DECLARE_CSR(pmpcfg15, CSR_PMPCFG15) +DECLARE_CSR(pmpaddr0, CSR_PMPADDR0) +DECLARE_CSR(pmpaddr1, CSR_PMPADDR1) +DECLARE_CSR(pmpaddr2, CSR_PMPADDR2) +DECLARE_CSR(pmpaddr3, CSR_PMPADDR3) +DECLARE_CSR(pmpaddr4, CSR_PMPADDR4) +DECLARE_CSR(pmpaddr5, CSR_PMPADDR5) +DECLARE_CSR(pmpaddr6, CSR_PMPADDR6) +DECLARE_CSR(pmpaddr7, CSR_PMPADDR7) +DECLARE_CSR(pmpaddr8, CSR_PMPADDR8) +DECLARE_CSR(pmpaddr9, CSR_PMPADDR9) +DECLARE_CSR(pmpaddr10, CSR_PMPADDR10) +DECLARE_CSR(pmpaddr11, CSR_PMPADDR11) +DECLARE_CSR(pmpaddr12, CSR_PMPADDR12) +DECLARE_CSR(pmpaddr13, CSR_PMPADDR13) +DECLARE_CSR(pmpaddr14, CSR_PMPADDR14) +DECLARE_CSR(pmpaddr15, CSR_PMPADDR15) +DECLARE_CSR(pmpaddr16, CSR_PMPADDR16) +DECLARE_CSR(pmpaddr17, CSR_PMPADDR17) +DECLARE_CSR(pmpaddr18, CSR_PMPADDR18) +DECLARE_CSR(pmpaddr19, CSR_PMPADDR19) +DECLARE_CSR(pmpaddr20, CSR_PMPADDR20) +DECLARE_CSR(pmpaddr21, CSR_PMPADDR21) +DECLARE_CSR(pmpaddr22, CSR_PMPADDR22) +DECLARE_CSR(pmpaddr23, CSR_PMPADDR23) +DECLARE_CSR(pmpaddr24, CSR_PMPADDR24) +DECLARE_CSR(pmpaddr25, CSR_PMPADDR25) +DECLARE_CSR(pmpaddr26, CSR_PMPADDR26) +DECLARE_CSR(pmpaddr27, CSR_PMPADDR27) +DECLARE_CSR(pmpaddr28, CSR_PMPADDR28) +DECLARE_CSR(pmpaddr29, CSR_PMPADDR29) +DECLARE_CSR(pmpaddr30, CSR_PMPADDR30) +DECLARE_CSR(pmpaddr31, CSR_PMPADDR31) +DECLARE_CSR(pmpaddr32, CSR_PMPADDR32) +DECLARE_CSR(pmpaddr33, CSR_PMPADDR33) +DECLARE_CSR(pmpaddr34, CSR_PMPADDR34) +DECLARE_CSR(pmpaddr35, CSR_PMPADDR35) +DECLARE_CSR(pmpaddr36, CSR_PMPADDR36) +DECLARE_CSR(pmpaddr37, CSR_PMPADDR37) +DECLARE_CSR(pmpaddr38, CSR_PMPADDR38) +DECLARE_CSR(pmpaddr39, CSR_PMPADDR39) +DECLARE_CSR(pmpaddr40, CSR_PMPADDR40) +DECLARE_CSR(pmpaddr41, CSR_PMPADDR41) +DECLARE_CSR(pmpaddr42, CSR_PMPADDR42) +DECLARE_CSR(pmpaddr43, CSR_PMPADDR43) +DECLARE_CSR(pmpaddr44, CSR_PMPADDR44) +DECLARE_CSR(pmpaddr45, CSR_PMPADDR45) +DECLARE_CSR(pmpaddr46, CSR_PMPADDR46) +DECLARE_CSR(pmpaddr47, CSR_PMPADDR47) +DECLARE_CSR(pmpaddr48, CSR_PMPADDR48) +DECLARE_CSR(pmpaddr49, CSR_PMPADDR49) +DECLARE_CSR(pmpaddr50, CSR_PMPADDR50) +DECLARE_CSR(pmpaddr51, CSR_PMPADDR51) +DECLARE_CSR(pmpaddr52, CSR_PMPADDR52) +DECLARE_CSR(pmpaddr53, CSR_PMPADDR53) +DECLARE_CSR(pmpaddr54, CSR_PMPADDR54) +DECLARE_CSR(pmpaddr55, CSR_PMPADDR55) +DECLARE_CSR(pmpaddr56, CSR_PMPADDR56) +DECLARE_CSR(pmpaddr57, CSR_PMPADDR57) +DECLARE_CSR(pmpaddr58, CSR_PMPADDR58) +DECLARE_CSR(pmpaddr59, CSR_PMPADDR59) +DECLARE_CSR(pmpaddr60, CSR_PMPADDR60) +DECLARE_CSR(pmpaddr61, CSR_PMPADDR61) +DECLARE_CSR(pmpaddr62, CSR_PMPADDR62) +DECLARE_CSR(pmpaddr63, CSR_PMPADDR63) +DECLARE_CSR(mseccfg, CSR_MSECCFG) +DECLARE_CSR(tselect, CSR_TSELECT) +DECLARE_CSR(tdata1, CSR_TDATA1) +DECLARE_CSR(tdata2, CSR_TDATA2) +DECLARE_CSR(tdata3, CSR_TDATA3) +DECLARE_CSR(tinfo, CSR_TINFO) +DECLARE_CSR(tcontrol, CSR_TCONTROL) +DECLARE_CSR(mcontext, CSR_MCONTEXT) +DECLARE_CSR(mscontext, CSR_MSCONTEXT) +DECLARE_CSR(dcsr, CSR_DCSR) +DECLARE_CSR(dpc, CSR_DPC) +DECLARE_CSR(dscratch0, CSR_DSCRATCH0) +DECLARE_CSR(dscratch1, CSR_DSCRATCH1) +DECLARE_CSR(mcycle, CSR_MCYCLE) +DECLARE_CSR(minstret, CSR_MINSTRET) +DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3) +DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4) +DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5) +DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6) +DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7) +DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8) +DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9) +DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10) +DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11) +DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12) +DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13) +DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14) +DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15) +DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16) +DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17) +DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18) +DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19) +DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20) +DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21) +DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22) +DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23) +DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24) +DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25) +DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26) +DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27) +DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) +DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) +DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) +DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) +DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) +DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) +DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) +DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6) +DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7) +DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8) +DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9) +DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10) +DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11) +DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12) +DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13) +DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14) +DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15) +DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16) +DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17) +DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18) +DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19) +DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20) +DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21) +DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22) +DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23) +DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24) +DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25) +DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26) +DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27) +DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28) +DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29) +DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30) +DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31) +DECLARE_CSR(mvendorid, CSR_MVENDORID) +DECLARE_CSR(marchid, CSR_MARCHID) +DECLARE_CSR(mimpid, CSR_MIMPID) +DECLARE_CSR(mhartid, CSR_MHARTID) +DECLARE_CSR(mconfigptr, CSR_MCONFIGPTR) +DECLARE_CSR(stimecmph, CSR_STIMECMPH) +DECLARE_CSR(vstimecmph, CSR_VSTIMECMPH) +DECLARE_CSR(htimedeltah, CSR_HTIMEDELTAH) +DECLARE_CSR(henvcfgh, CSR_HENVCFGH) +DECLARE_CSR(hstateen0h, CSR_HSTATEEN0H) +DECLARE_CSR(hstateen1h, CSR_HSTATEEN1H) +DECLARE_CSR(hstateen2h, CSR_HSTATEEN2H) +DECLARE_CSR(hstateen3h, CSR_HSTATEEN3H) +DECLARE_CSR(cycleh, CSR_CYCLEH) +DECLARE_CSR(timeh, CSR_TIMEH) +DECLARE_CSR(instreth, CSR_INSTRETH) +DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H) +DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H) +DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H) +DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H) +DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H) +DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H) +DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H) +DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H) +DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H) +DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H) +DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H) +DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H) +DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H) +DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H) +DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H) +DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H) +DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H) +DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H) +DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H) +DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H) +DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H) +DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H) +DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H) +DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H) +DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H) +DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H) +DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H) +DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H) +DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H) +DECLARE_CSR(mstatush, CSR_MSTATUSH) +DECLARE_CSR(menvcfgh, CSR_MENVCFGH) +DECLARE_CSR(mstateen0h, CSR_MSTATEEN0H) +DECLARE_CSR(mstateen1h, CSR_MSTATEEN1H) +DECLARE_CSR(mstateen2h, CSR_MSTATEEN2H) +DECLARE_CSR(mstateen3h, CSR_MSTATEEN3H) +DECLARE_CSR(mhpmevent3h, CSR_MHPMEVENT3H) +DECLARE_CSR(mhpmevent4h, CSR_MHPMEVENT4H) +DECLARE_CSR(mhpmevent5h, CSR_MHPMEVENT5H) +DECLARE_CSR(mhpmevent6h, CSR_MHPMEVENT6H) +DECLARE_CSR(mhpmevent7h, CSR_MHPMEVENT7H) +DECLARE_CSR(mhpmevent8h, CSR_MHPMEVENT8H) +DECLARE_CSR(mhpmevent9h, CSR_MHPMEVENT9H) +DECLARE_CSR(mhpmevent10h, CSR_MHPMEVENT10H) +DECLARE_CSR(mhpmevent11h, CSR_MHPMEVENT11H) +DECLARE_CSR(mhpmevent12h, CSR_MHPMEVENT12H) +DECLARE_CSR(mhpmevent13h, CSR_MHPMEVENT13H) +DECLARE_CSR(mhpmevent14h, CSR_MHPMEVENT14H) +DECLARE_CSR(mhpmevent15h, CSR_MHPMEVENT15H) +DECLARE_CSR(mhpmevent16h, CSR_MHPMEVENT16H) +DECLARE_CSR(mhpmevent17h, CSR_MHPMEVENT17H) +DECLARE_CSR(mhpmevent18h, CSR_MHPMEVENT18H) +DECLARE_CSR(mhpmevent19h, CSR_MHPMEVENT19H) +DECLARE_CSR(mhpmevent20h, CSR_MHPMEVENT20H) +DECLARE_CSR(mhpmevent21h, CSR_MHPMEVENT21H) +DECLARE_CSR(mhpmevent22h, CSR_MHPMEVENT22H) +DECLARE_CSR(mhpmevent23h, CSR_MHPMEVENT23H) +DECLARE_CSR(mhpmevent24h, CSR_MHPMEVENT24H) +DECLARE_CSR(mhpmevent25h, CSR_MHPMEVENT25H) +DECLARE_CSR(mhpmevent26h, CSR_MHPMEVENT26H) +DECLARE_CSR(mhpmevent27h, CSR_MHPMEVENT27H) +DECLARE_CSR(mhpmevent28h, CSR_MHPMEVENT28H) +DECLARE_CSR(mhpmevent29h, CSR_MHPMEVENT29H) +DECLARE_CSR(mhpmevent30h, CSR_MHPMEVENT30H) +DECLARE_CSR(mhpmevent31h, CSR_MHPMEVENT31H) +DECLARE_CSR(mseccfgh, CSR_MSECCFGH) +DECLARE_CSR(mcycleh, CSR_MCYCLEH) +DECLARE_CSR(minstreth, CSR_MINSTRETH) +DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H) +DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H) +DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H) +DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H) +DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H) +DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H) +DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H) +DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H) +DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H) +DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H) +DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H) +DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H) +DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H) +DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H) +DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H) +DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H) +DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H) +DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H) +DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H) +DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H) +DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H) +DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H) +DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H) +DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H) +DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H) +DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H) +DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H) +DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H) +DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) +#endif +#ifdef DECLARE_CAUSE +DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) +DECLARE_CAUSE("fetch access", CAUSE_FETCH_ACCESS) +DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) +DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) +DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) +DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS) +DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) +DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS) +DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) +DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) +DECLARE_CAUSE("virtual_supervisor_ecall", CAUSE_VIRTUAL_SUPERVISOR_ECALL) +DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) +DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT) +DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT) +DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT) +DECLARE_CAUSE("fetch guest page fault", CAUSE_FETCH_GUEST_PAGE_FAULT) +DECLARE_CAUSE("load guest page fault", CAUSE_LOAD_GUEST_PAGE_FAULT) +DECLARE_CAUSE("virtual instruction", CAUSE_VIRTUAL_INSTRUCTION) +DECLARE_CAUSE("store guest page fault", CAUSE_STORE_GUEST_PAGE_FAULT) +#endif diff --git a/optee/optee_os/core/arch/riscv/include/kernel/arch_scall.h b/optee/optee_os/core/arch/riscv/include/kernel/arch_scall.h new file mode 100644 index 0000000..8d898d5 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/arch_scall.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef __KERNEL_ARCH_SCALL_H +#define __KERNEL_ARCH_SCALL_H + +#include +#include +#include + +static inline void scall_get_max_args(struct thread_scall_regs *regs, + size_t *scn, size_t *max_args) +{ + *scn = regs->t0; + *max_args = regs->t1; +} + +static inline void scall_set_retval(struct thread_scall_regs *regs, + uint32_t ret_val) +{ + regs->a0 = ret_val; +} + +static inline void scall_set_sys_return_regs(struct thread_scall_regs *regs, + bool panic, uint32_t panic_code) +{ + regs->a1 = panic; + regs->a2 = panic_code; +} + +#endif /*__KERNEL_ARCH_SCALL_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/cache_helpers_arch.h b/optee/optee_os/core/arch/riscv/include/kernel/cache_helpers_arch.h new file mode 100644 index 0000000..5f5810f --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/cache_helpers_arch.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef __KERNEL_CACHE_HELPERS_ARCH_H +#define __KERNEL_CACHE_HELPERS_ARCH_H + +#endif /*__KERNEL_CACHE_HELPERS_ARCH_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/clint.h b/optee/optee_os/core/arch/riscv/include/kernel/clint.h new file mode 100644 index 0000000..56efa25 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/clint.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef __KERNEL_CLINT_H +#define __KERNEL_CLINT_H + +#include +#include +#include +#include + +#ifdef CFG_RISCV_M_MODE + +/* Machine software-interrupt pending register for a specific hart */ +#define CLINT_MSIP(hart) (CLINT_BASE + (4 * (hart))) +/* Register for setting mtimecmp for a specific hart */ +#define CLINT_MTIMECMP(hart)(CLINT_BASE + 0x4000 + (8 * (hart))) +/* Number of cycles counted from the RTCCLK input */ +#define CLINT_MTIME (CLINT_BASE + 0xbff8) + +static inline void clint_ipi_send(unsigned long hart) +{ + assert(hart < CFG_TEE_CORE_NB_CORE); + io_write32(CLINT_MSIP(hart), 1); +} + +static inline void clint_ipi_clear(unsigned long hart) +{ + assert(hart < CFG_TEE_CORE_NB_CORE); + io_write32(CLINT_MSIP(hart), 0); +} + +static inline void clint_set_mtimecmp(uint64_t timecmp) +{ + /* Each hart has a separate source of timer interrupts */ + io_write64(CLINT_MTIMECMP(get_core_pos()), timecmp); +} + +static inline uint64_t clint_get_mtimecmp(void) +{ + return io_read64(CLINT_MTIMECMP(get_core_pos())); +} + +static inline uint64_t clint_get_mtime(void) +{ + return io_read64(CLINT_MTIME); +} + +static inline void clint_set_mtime(uint64_t mtime) +{ + io_write64(CLINT_MTIME, mtime); +} + +#endif /* CFG_RISCV_M_MODE */ +#endif /* __KERNEL_CLINT_H */ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h b/optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h new file mode 100644 index 0000000..de4709f --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/delay_arch.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef __KERNEL_DELAY_ARCH_H +#define __KERNEL_DELAY_ARCH_H + +#include +#include +#include +#include + +static inline uint64_t timeout_init_us(uint32_t us) +{ + return read_time() + ((uint64_t)us * + CFG_RISCV_MTIME_RATE) / 1000000ULL; +} + +static inline bool timeout_elapsed(uint64_t expire) +{ + return read_time() > expire; +} + +#endif /*__KERNEL_DELAY_ARCH_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/misc_arch.h b/optee/optee_os/core/arch/riscv/include/kernel/misc_arch.h new file mode 100644 index 0000000..208e358 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/misc_arch.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef KERNEL_MISC_ARCH_H +#define KERNEL_MISC_ARCH_H + +#endif /*KERNEL_MISC_ARCH_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/secure_partition.h b/optee/optee_os/core/arch/riscv/include/kernel/secure_partition.h new file mode 100644 index 0000000..c97a31a --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/secure_partition.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef __KERNEL_SECURE_PARTITION_H +#define __KERNEL_SECURE_PARTITION_H + +#include +#include +#include +#include + +struct sp_ctx { + struct user_mode_ctx uctx; + struct ts_ctx ts_ctx; +}; + +static inline bool is_sp_ctx(struct ts_ctx *ctx __unused) +{ + return false; +} + +static inline struct sp_session *__noprof +to_sp_session(struct ts_session *sess __unused) +{ + assert(is_sp_ctx(sess->ctx)); + return NULL; +} + +static inline struct sp_ctx *to_sp_ctx(struct ts_ctx *ctx __unused) +{ + assert(is_sp_ctx(ctx)); + return NULL; +} + +#endif /* __KERNEL_SECURE_PARTITION_H */ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/stmm_sp.h b/optee/optee_os/core/arch/riscv/include/kernel/stmm_sp.h new file mode 100644 index 0000000..9b5b09d --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/stmm_sp.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef __KERNEL_STMM_SP_H +#define __KERNEL_STMM_SP_H + +#include +#include +#include +#include +#include + +struct stmm_ctx { + struct user_mode_ctx uctx; + struct tee_ta_ctx ta_ctx; +}; + +static inline bool is_stmm_ctx(struct ts_ctx *ctx __unused) +{ + return false; +} + +static inline struct stmm_ctx *to_stmm_ctx(struct ts_ctx *ctx __unused) +{ + assert(is_stmm_ctx(ctx)); + return NULL; +} + +static inline TEE_Result +stmm_init_session(const TEE_UUID *uuid __unused, + struct tee_ta_session *s __unused) +{ + return TEE_ERROR_ITEM_NOT_FOUND; +} + +static inline const TEE_UUID *stmm_get_uuid(void) { return NULL; } + +#endif /*__KERNEL_STMM_SP_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/tee_l2cc_mutex.h b/optee/optee_os/core/arch/riscv/include/kernel/tee_l2cc_mutex.h new file mode 100644 index 0000000..12b9147 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/tee_l2cc_mutex.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ +#ifndef TEE_L2CC_MUTEX_H +#define TEE_L2CC_MUTEX_H + +#endif /* TEE_L2CC_MUTEX_H */ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h b/optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h new file mode 100644 index 0000000..59f9ca2 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/thread_arch.h @@ -0,0 +1,248 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef __KERNEL_THREAD_ARCH_H +#define __KERNEL_THREAD_ARCH_H + +#ifndef __ASSEMBLER__ +#include +#include +#include +#endif + +#ifndef __ASSEMBLER__ + +#define THREAD_CORE_LOCAL_ALIGNED __aligned(16) + +struct thread_pauth_keys { +}; + +struct thread_core_local { + unsigned long x[4]; + uint32_t hart_id; + vaddr_t tmp_stack_va_end; + short int curr_thread; + uint32_t flags; + vaddr_t abt_stack_va_end; +#ifdef CFG_TEE_CORE_DEBUG + unsigned int locked_count; /* Number of spinlocks held */ +#endif +#ifdef CFG_CORE_DEBUG_CHECK_STACKS + bool stackcheck_recursion; +#endif +} THREAD_CORE_LOCAL_ALIGNED; + +struct thread_user_vfp_state { +}; + +struct thread_smc_args { + unsigned long a0; /* SBI function ID */ + unsigned long a1; /* Parameter */ + unsigned long a2; /* Parameter */ + unsigned long a3; /* Thread ID when returning from RPC */ + unsigned long a4; /* Not used */ + unsigned long a5; /* Not used */ + unsigned long a6; /* Not used */ + unsigned long a7; /* Hypervisor Client ID */ +}; + +struct thread_abort_regs { + unsigned long ra; + unsigned long sp; + unsigned long gp; + unsigned long tp; + unsigned long t0; + unsigned long t1; + unsigned long t2; + unsigned long s0; + unsigned long s1; + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long s2; + unsigned long s3; + unsigned long s4; + unsigned long s5; + unsigned long s6; + unsigned long s7; + unsigned long s8; + unsigned long s9; + unsigned long s10; + unsigned long s11; + unsigned long t3; + unsigned long t4; + unsigned long t5; + unsigned long t6; + unsigned long status; + unsigned long cause; + unsigned long epc; + unsigned long tval; + unsigned long satp; +}; + +struct thread_trap_regs { + unsigned long ra; + unsigned long sp; + unsigned long gp; + unsigned long tp; + unsigned long t0; + unsigned long t1; + unsigned long t2; + unsigned long s0; + unsigned long s1; + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long s2; + unsigned long s3; + unsigned long s4; + unsigned long s5; + unsigned long s6; + unsigned long s7; + unsigned long s8; + unsigned long s9; + unsigned long s10; + unsigned long s11; + unsigned long t3; + unsigned long t4; + unsigned long t5; + unsigned long t6; + unsigned long epc; + unsigned long status; + unsigned long satp; +} __aligned(16); + +struct thread_scall_regs { + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long t0; + unsigned long t1; + unsigned long ra; + unsigned long sp; + unsigned long status; +} __aligned(16); + +struct thread_ctx_regs { + unsigned long ra; + unsigned long sp; + unsigned long gp; + unsigned long tp; + unsigned long t0; + unsigned long t1; + unsigned long t2; + unsigned long s0; + unsigned long s1; + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long s2; + unsigned long s3; + unsigned long s4; + unsigned long s5; + unsigned long s6; + unsigned long s7; + unsigned long s8; + unsigned long s9; + unsigned long s10; + unsigned long s11; + unsigned long t3; + unsigned long t4; + unsigned long t5; + unsigned long t6; + unsigned long status; +}; + +struct user_mode_ctx; + +/* + * These flags should vary according to the privilege mode selected + * to run OP-TEE core on (M/HS/S). For now default to S-Mode. + */ + +#define CSR_XIE_SIE BIT64(IRQ_XSOFT) +#define CSR_XIE_TIE BIT64(IRQ_XTIMER) +#define CSR_XIE_EIE BIT64(IRQ_XEXT) + +#define THREAD_EXCP_FOREIGN_INTR CSR_XIE_EIE +#define THREAD_EXCP_NATIVE_INTR (CSR_XIE_SIE | CSR_XIE_TIE) +#define THREAD_EXCP_ALL (THREAD_EXCP_FOREIGN_INTR |\ + THREAD_EXCP_NATIVE_INTR) + +#ifdef CFG_WITH_VFP +uint32_t thread_kernel_enable_vfp(void); +void thread_kernel_disable_vfp(uint32_t state); +void thread_kernel_save_vfp(void); +void thread_kernel_restore_vfp(void); +void thread_user_enable_vfp(struct thread_user_vfp_state *uvfp); +#else /*CFG_WITH_VFP*/ +static inline void thread_kernel_save_vfp(void) +{ +} + +static inline void thread_kernel_restore_vfp(void) +{ +} +#endif /*CFG_WITH_VFP*/ +#ifdef CFG_WITH_VFP +void thread_user_save_vfp(void); +#else +static inline void thread_user_save_vfp(void) +{ +} +#endif +#ifdef CFG_WITH_VFP +void thread_user_clear_vfp(struct user_mode_ctx *uctx); +#else +static inline void thread_user_clear_vfp(struct user_mode_ctx *uctx __unused) +{ +} +#endif + +vaddr_t thread_get_saved_thread_sp(void); + +static inline void thread_get_user_kcode(struct mobj **mobj, size_t *offset, + vaddr_t *va, size_t *sz) +{ + *mobj = NULL; + *offset = 0; + *va = 0; + *sz = 0; +} + +static inline void thread_get_user_kdata(struct mobj **mobj, size_t *offset, + vaddr_t *va, size_t *sz) +{ + *mobj = NULL; + *offset = 0; + *va = 0; + *sz = 0; +} + +bool thread_disable_prealloc_rpc_cache(uint64_t *cookie); +bool thread_enable_prealloc_rpc_cache(void); + +#endif /*__ASSEMBLER__*/ +#endif /*__KERNEL_THREAD_ARCH_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h b/optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h new file mode 100644 index 0000000..421e70b --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/thread_private_arch.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef __KERNEL_THREAD_PRIVATE_ARCH_H +#define __KERNEL_THREAD_PRIVATE_ARCH_H + +#ifndef __ASSEMBLER__ + +#include + +#define STACK_TMP_OFFS 0 + +#if defined(__clang__) && !defined(__OPTIMIZE_SIZE__) +#define STACK_TMP_SIZE (4096 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) +#else +#define STACK_TMP_SIZE (2048 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) +#endif + +#define STACK_THREAD_SIZE (8192 + CFG_STACK_THREAD_EXTRA) + +#if TRACE_LEVEL > 0 +#define STACK_ABT_SIZE 3072 +#else +#define STACK_ABT_SIZE 1024 +#endif + +#define STACK_CHECK_EXTRA 0 + +#define THREAD_RPC_NUM_ARGS 4 + +#define TRAP_MODE_KERNEL 0 +#define TRAP_MODE_USER 1 + +struct thread_user_mode_rec { + unsigned long ctx_regs_ptr; + unsigned long exit_status0_ptr; + unsigned long exit_status1_ptr; + unsigned long pad; + /* + * x[] is used to save registers for user/kernel context-switching + * 0-3: ra-tp + * 4-6: s0-s1 + * 6-15: s2-s11 + */ + unsigned long x[16]; +}; + +extern long thread_user_kcode_offset; + +void thread_trap_handler(long cause, unsigned long epc, + struct thread_trap_regs *regs, + bool user); +/* + * Initializes TVEC for current hart. Called by thread_init_per_cpu() + */ +void thread_init_tvec(void); +void thread_trap_vect(void); +void thread_trap_vect_end(void); + +/* + * Private functions made available for thread_rv.S + */ +int thread_state_suspend(uint32_t flags, uint32_t status, vaddr_t pc); +void thread_resume(struct thread_ctx_regs *regs); +uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, + uint32_t *exit_status0, + uint32_t *exit_status1); +void *thread_get_tmp_sp(void); +void thread_state_free(void); +struct thread_ctx_regs *thread_get_ctx_regs(void); +void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5); +void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3); +void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); +void thread_scall_handler(struct thread_scall_regs *regs); +void thread_exit_user_mode(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long sp, unsigned long pc, + unsigned long status); + +#endif /*__ASSEMBLER__*/ +#endif /*__KERNEL_THREAD_PRIVATE_ARCH_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/time.h b/optee/optee_os/core/arch/riscv/include/kernel/time.h new file mode 100644 index 0000000..992ee35 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/time.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef __KERNEL_TIME_H +#define __KERNEL_TIME_H + +#include +#include + +static inline __noprof uint64_t read_time(void) +{ + uint64_t time = 0; + uint32_t hi __maybe_unused = 0; + uint32_t lo __maybe_unused = 0; + +#ifdef CFG_RISCV_M_MODE + time = clint_get_mtime(); +#endif /*CFG_RISCV_M_MODE*/ + +#ifdef CFG_RISCV_S_MODE +#ifdef RV32 + do { + hi = read_csr(timeh); + lo = read_csr(time); + } while (hi != read_csr(timeh)); + + time = SHIFT_U64(hi, 32) | lo; +#else /*RV64*/ + time = rdtime(); +#endif /*RV32*/ +#endif /*CFG_RISCV_S_MODE*/ + + return time; +} + +#endif /* __KERNEL_TIME_H */ diff --git a/optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h b/optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h new file mode 100644 index 0000000..1ba731b --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/kernel/tlb_helpers.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef TLB_HELPERS_H +#define TLB_HELPERS_H + +#ifndef __ASSEMBLER__ + +void tlbi_all(void); +void tlbi_asid(unsigned long asid); + +#endif /*!__ASSEMBLER__*/ + +#endif /* TLB_HELPERS_H */ diff --git a/optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h b/optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h new file mode 100644 index 0000000..bdc8ce6 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/mm/core_mmu_arch.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ +#ifndef __CORE_MMU_ARCH_H +#define __CORE_MMU_ARCH_H + +#ifndef __ASSEMBLER__ +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include + +#ifdef TRUSTED_DRAM_BASE +#error TRUSTED_DRAM_BASE is already defined +#endif +#define TRUSTED_DRAM_BASE TDDRAM_BASE +#define TRUSTED_DRAM_SIZE TDDRAM_SIZE + +/* MMU defines */ +#ifdef CFG_RISCV_MMU_MODE +#define RISCV_MMU_MODE CFG_RISCV_MMU_MODE +#else +#ifdef RV64 +#define RISCV_MMU_MODE U(39) +#else +#define RISCV_MMU_MODE U(32) +#endif +#endif + +#if RISCV_MMU_MODE == 48 /*Sv48*/ +#define RISCV_SATP_MODE SATP_MODE_SV48 +#define RISCV_SATP_MODE_SHIFT U(60) +#define RISCV_SATP_ASID_SHIFT U(44) +#define RISCV_SATP_ASID_SIZE U(16) +#define RISCV_SATP_ASID_MASK 0x0FFFF +#define RISCV_MMU_PA_WIDTH U(56) +#define RISCV_MMU_VA_WIDTH U(48) +#elif RISCV_MMU_MODE == 39 /*Sv39*/ +#define RISCV_SATP_MODE SATP_MODE_SV39 +#define RISCV_SATP_ASID_SHIFT U(44) +#define RISCV_SATP_ASID_SIZE U(16) +#define RISCV_SATP_ASID_MASK 0x0FFFF +#define RISCV_MMU_PA_WIDTH U(56) +#define RISCV_MMU_VA_WIDTH U(39) +#define RISCV_SATP_MODE_SHIFT 60 +#elif RISCV_MMU_MODE == 32 /*Sv32*/ +#define RISCV_SATP_MODE SATP_MODE_SV32 +#define RISCV_SATP_MODE_SHIFT U(31) +#define RISCV_SATP_ASID_SHIFT U(22) +#define RISCV_SATP_ASID_SIZE U(9) +#define RISCV_SATP_ASID_MASK 0x01FF +#define RISCV_MMU_PA_WIDTH U(32) +#define RISCV_MMU_VA_WIDTH U(32) +#else +#error unknown or unsupported mmu mode +#endif + +#define RISCV_PTES_PER_PT BIT(RISCV_PGLEVEL_BITS) +#define RISCV_PGLEVELS ((RISCV_MMU_VA_WIDTH - RISCV_PGSHIFT) / \ + RISCV_PGLEVEL_BITS) +#define RISCV_MMU_VPN_MASK (BIT(RISCV_PGLEVEL_BITS) - 1) + +#define SMALL_PAGE_SHIFT U(12) + +/* + * Level 0: shift = 12 4K pages + * Level 1: shift = 21 2M pages + * Level 2: shift = 30 1G pages + */ + +#define CORE_MMU_USER_CODE_SHIFT SMALL_PAGE_SHIFT +#define CORE_MMU_USER_PARAM_SHIFT SMALL_PAGE_SHIFT + +#define CORE_MMU_PGDIR_LEVEL U(0) +#define CORE_MMU_PGDIR_SHIFT U(12) + +#define CORE_MMU_BASE_TABLE_LEVEL 0 +#define CORE_MMU_BASE_TABLE_SHIFT (RISCV_PGLEVEL_BITS * \ + CORE_MMU_BASE_TABLE_LEVEL + \ + RISCV_PGSHIFT) + +#ifndef __ASSEMBLER__ + +struct core_mmu_config { + unsigned long satp; + uint32_t map_offset; +}; + +struct core_mmu_user_map { + uint64_t user_map; + uint32_t asid; +}; + +/* Cache maintenance operation type */ +enum cache_op { + DCACHE_CLEAN, + DCACHE_AREA_CLEAN, + DCACHE_INVALIDATE, + DCACHE_AREA_INVALIDATE, + ICACHE_INVALIDATE, + ICACHE_AREA_INVALIDATE, + DCACHE_CLEAN_INV, + DCACHE_AREA_CLEAN_INV, +}; + +static inline void core_mmu_table_write_barrier(void) +{ + /* Invoke memory barrier */ + mb(); +} + +TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len); + +static inline bool core_mmu_check_max_pa(paddr_t pa) +{ + return pa <= (BIT64(RISCV_MMU_PA_WIDTH) - 1); +} + +static inline unsigned int core_mmu_get_va_width(void) +{ + return RISCV_MMU_VA_WIDTH; +} +#endif /*__ASSEMBLER__*/ + +#endif /* __CORE_MMU_ARCH_H */ diff --git a/optee/optee_os/core/arch/riscv/include/mm/generic_ram_layout.h b/optee/optee_os/core/arch/riscv/include/mm/generic_ram_layout.h new file mode 100644 index 0000000..4903ade --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/mm/generic_ram_layout.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + * Copyright 2022 NXP + */ + +#ifndef __MM_GENERIC_RAM_LAYOUT_H +#define __MM_GENERIC_RAM_LAYOUT_H + +#include + +/* + * Generic RAM layout configuration directives + * + * Mandatory directives: + * CFG_TDDRAM_START + * CFG_TDDRAM_SIZE + * CFG_SHMEM_START + * CFG_SHMEM_SIZE + * + * Optional directives: + * CFG_TEE_LOAD_ADDR If defined sets TEE_LOAD_ADDR. If not, TEE_LOAD_ADDR + * is set by the platform or defaults to TEE_RAM_START. + * CFG_TEE_RAM_VA_SIZE Some platforms may have specific needs + * + * Optional directives when pager is enabled: + * CFG_TDSRAM_START If no set, emulated at CFG_TDDRAM_START + * CFG_TDSRAM_SIZE Default to CFG_CORE_TDSRAM_EMUL_SIZE + * + * Optional directive when CFG_SECURE_DATA_PATH is enabled: + * CFG_TEE_SDP_MEM_SIZE If CFG_TEE_SDP_MEM_BASE is not defined, SDP test + * memory byte size can be set by CFG_TEE_SDP_MEM_SIZE. + * + * This header file produces the following generic macros upon the mandatory + * and optional configuration directives listed above: + * + * TEE_RAM_START TEE core RAM physical base address + * TEE_RAM_VA_SIZE TEE core virtual memory address range size + * TEE_RAM_PH_SIZE TEE core physical RAM byte size + * TA_RAM_START TA contexts/pagestore RAM physical base address + * TA_RAM_SIZE TA contexts/pagestore RAM byte size + * TEE_SHMEM_START Non-secure static shared memory physical base address + * TEE_SHMEM_SIZE Non-secure static shared memory byte size + * + * TDDRAM_BASE Main/external secure RAM base address + * TDDRAM_SIZE Main/external secure RAM byte size + * TDSRAM_BASE On-chip secure RAM base address, required by pager. + * TDSRAM_SIZE On-chip secure RAM byte size, required by pager. + * + * TEE_LOAD_ADDR Only defined here if CFG_TEE_LOAD_ADDR is defined. + * Otherwise we expect the platform_config.h to define it + * unless which LEE_LOAD_ADDR defaults to TEE_RAM_START. + * + * TEE_RAM_VA_SIZE Set to CFG_TEE_RAM_VA_SIZE or defaults to + * CORE_MMU_PGDIR_SIZE. + * + * TEE_SDP_TEST_MEM_BASE Define if a SDP memory pool is required and none set. + * Always defined in the inner top (high addresses) + * of CFG_TDDRAM_START/_SIZE. + * TEE_SDP_TEST_MEM_SIZE Set to CFG_TEE_SDP_MEM_SIZE or a default size. + * + * ---------------------------------------------------------------------------- + * TEE RAM layout without CFG_WITH_PAGER + *_ + * +----------------------------------+ <-- CFG_TDDRAM_START + * | TEE core secure RAM (TEE_RAM) | + * +----------------------------------+ + * | Trusted Application RAM (TA_RAM) | + * +----------------------------------+ + * | SDP test memory (optional) | + * +----------------------------------+ <-- CFG_TDDRAM_START + CFG_TDDRAM_SIZE + * + * +----------------------------------+ <-- CFG_SHMEM_START + * | Non-secure static SHM | + * +----------------------------------+ <-- CFG_SHMEM_START + CFG_SHMEM_SIZE + * + * ---------------------------------------------------------------------------- + * TEE RAM layout with CFG_WITH_PAGER=y and undefined CFG_TDSRAM_START/_SIZE + * + * +----------------------------------+ <-- CFG_TDDRAM_START + * | TEE core secure RAM (TEE_RAM) | | | CFG_CORE_TDSRAM_EMUL_SIZE + * +----------------------------------+ --|-' + * | reserved (for kasan) | | TEE_RAM_VA_SIZE + * +----------------------------------+ --' + * | TA RAM / Pagestore (TA_RAM) | + * +----------------------------------+ <---- align with CORE_MMU_PGDIR_SIZE + * +----------------------------------+ <-- + * | SDP test memory (optional) | | CFG_TEE_SDP_MEM_SIZE + * +----------------------------------+ <-+ CFG_TDDRAM_START + CFG_TDDRAM_SIZE + * + * +----------------------------------+ <-- CFG_SHMEM_START + * | Non-secure static SHM | | + * +----------------------------------+ v CFG_SHMEM_SIZE + * + * ---------------------------------------------------------------------------- + * TEE RAM layout with CFG_WITH_PAGER=y and define CFG_TDSRAM_START/_SIZE + * + * +----------------------------------+ <-- CFG_TDSRAM_START + * | TEE core secure RAM (TEE_RAM) | | CFG_TDSRAM_SIZE + * +----------------------------------+ --' + * + * +----------------------------------+ <- CFG_TDDRAM_START + * | TA RAM / Pagestore (TA_RAM) | + * |----------------------------------+ <---- align with CORE_MMU_PGDIR_SIZE + * |----------------------------------+ <-- + * | SDP test memory (optional) | | CFG_TEE_SDP_MEM_SIZE + * +----------------------------------+ <-+ CFG_TDDRAM_START + CFG_TDDRAM_SIZE + * + * +----------------------------------+ <-- CFG_SHMEM_START + * | Non-secure static SHM | | + * +----------------------------------+ v CFG_SHMEM_SIZE + */ + +#ifdef CFG_TEE_LOAD_ADDR +#define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR +#else +/* Platform specific platform_config.h may set TEE_LOAD_ADDR */ +#endif + +#ifdef CFG_TEE_RAM_VA_SIZE +#define TEE_RAM_VA_SIZE CFG_TEE_RAM_VA_SIZE +#else +#define TEE_RAM_VA_SIZE CORE_MMU_PGDIR_SIZE +#endif + +#ifdef CFG_SHMEM_SIZE +#define TEE_SHMEM_SIZE CFG_SHMEM_SIZE +#endif + +#ifdef CFG_SHMEM_START +#define TEE_SHMEM_START CFG_SHMEM_START +#ifndef CFG_SHMEM_SIZE +#error CFG_SHMEM_START mandates CFG_SHMEM_SIZE +#endif +#endif + +#if defined(CFG_TDSRAM_START) +#define TDSRAM_BASE CFG_TDSRAM_START +#define TDSRAM_SIZE CFG_TDSRAM_SIZE +#endif + +#ifdef CFG_TDDRAM_START +#if !defined(CFG_WITH_PAGER) || defined(CFG_TDSRAM_START) +#define TDDRAM_BASE CFG_TDDRAM_START +#define TDDRAM_SIZE CFG_TDDRAM_SIZE +#else +#define TDSRAM_BASE CFG_TDDRAM_START +#define TDSRAM_SIZE CFG_CORE_TDSRAM_EMUL_SIZE +#define TDDRAM_BASE ROUNDUP(TDSRAM_BASE + TDSRAM_SIZE, \ + TEE_RAM_VA_SIZE) +#define TDDRAM_SIZE (CFG_TDDRAM_START + (CFG_TDDRAM_SIZE - \ + TDDRAM_BASE)) +#endif + +#ifdef CFG_WITH_PAGER +#define TEE_RAM_START TDSRAM_BASE +#define TEE_RAM_PH_SIZE TDSRAM_SIZE +#define TA_RAM_START ROUNDUP(TDDRAM_BASE, CORE_MMU_PGDIR_SIZE) +#else +#define TEE_RAM_START TDDRAM_BASE +#define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE +#define TA_RAM_START ROUNDUP(TDDRAM_BASE + TEE_RAM_VA_SIZE, \ + SMALL_PAGE_SIZE) +#endif /*CFG_WITH_PAGER*/ + +#define TA_RAM_SIZE (ROUNDDOWN(TDDRAM_BASE + (TDDRAM_SIZE - \ + TEE_SDP_TEST_MEM_SIZE), \ + SMALL_PAGE_SIZE) - TA_RAM_START) +#endif /*CFG_TDDRAM_START*/ + +/* + * Secure data path test memory pool + * - If SDP is disabled, no SDP test memory needed. + * - If SDP is enabled, if CFG_TEE_SDP_MEM_BASE, SDP test pool is not needed. + * - If SDP is enabled and CFG_TEE_SDP_MEM_BASE not defined, a SDP test pool + * is defined at the end of the secure RAM. CFG_TEE_SDP_MEM_SIZE can set + * its size otherwise it defaults to 4MB. + */ +#if !defined(CFG_SECURE_DATA_PATH) || defined(CFG_TEE_SDP_MEM_BASE) +#define TEE_SDP_TEST_MEM_SIZE 0 +#else +#ifdef CFG_TEE_SDP_MEM_SIZE +#define TEE_SDP_TEST_MEM_SIZE CFG_TEE_SDP_MEM_SIZE +#else +#define TEE_SDP_TEST_MEM_SIZE SIZE_4M +#endif +#define TEE_SDP_TEST_MEM_BASE (CFG_TDDRAM_START + (CFG_TDDRAM_SIZE - \ + TEE_SDP_TEST_MEM_SIZE)) +#endif + +#endif /*__MM_GENERIC_RAM_LAYOUT_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/riscv.h b/optee/optee_os/core/arch/riscv/include/riscv.h new file mode 100644 index 0000000..6af36dc --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/riscv.h @@ -0,0 +1,371 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#ifndef RISCV_H +#define RISCV_H + +#include +#include +#include +#include +#include + +#define RISCV_XLEN_BITS (__riscv_xlen) +#define RISCV_XLEN_BYTES (__riscv_xlen / 8) + +#define REGOFF(x) ((x) * RISCV_XLEN_BYTES) + +#if __riscv_xlen == 32 +#define STR sw +#define LDR lw +#else +#define STR sd +#define LDR ld +#endif + +/* Bind registers to their ABI names */ +#define REG_RA 1 +#define REG_SP 2 +#define REG_GP 3 +#define REG_TP 4 +#define REG_T0 5 +#define REG_T2 7 +#define REG_S0 8 +#define REG_S1 9 +#define REG_A0 10 +#define REG_A1 11 +#define REG_A2 12 +#define REG_A3 13 +#define REG_A5 15 +#define REG_A7 17 +#define REG_S2 18 +#define REG_S11 27 +#define REG_T3 28 +#define REG_T6 31 + +#if defined(CFG_RISCV_M_MODE) +#define CSR_MODE_OFFSET PRV_M +#define XRET mret +#elif defined(CFG_RISCV_S_MODE) +#define CSR_MODE_OFFSET PRV_S +#define XRET sret +#endif + +#define CSR_MODE_BITS SHIFT_U64(CSR_MODE_OFFSET, 8) + +#define CSR_XSTATUS (CSR_MODE_BITS | 0x000) +#define CSR_XIE (CSR_MODE_BITS | 0x004) +#define CSR_XTVEC (CSR_MODE_BITS | 0x005) +#define CSR_XSCRATCH (CSR_MODE_BITS | 0x040) +#define CSR_XEPC (CSR_MODE_BITS | 0x041) +#define CSR_XCAUSE (CSR_MODE_BITS | 0x042) +#define CSR_XTVAL (CSR_MODE_BITS | 0x043) +#define CSR_XIP (CSR_MODE_BITS | 0x044) + +#define IRQ_XSOFT (CSR_MODE_OFFSET + 0) +#define IRQ_XTIMER (CSR_MODE_OFFSET + 4) +#define IRQ_XEXT (CSR_MODE_OFFSET + 8) + +#define CSR_XIE_SIE BIT64(IRQ_XSOFT) +#define CSR_XIE_TIE BIT64(IRQ_XTIMER) +#define CSR_XIE_EIE BIT64(IRQ_XEXT) + +#define CSR_XSTATUS_IE BIT(CSR_MODE_OFFSET + 0) +#define CSR_XSTATUS_PIE BIT(CSR_MODE_OFFSET + 4) +#define CSR_XSTATUS_SPP BIT(8) +#define CSR_XSTATUS_SUM BIT(18) +#define CSR_XSTATUS_MXR BIT(19) + +#ifndef __ASSEMBLER__ + +#define read_csr(csr) \ + ({ \ + unsigned long __tmp; \ + asm volatile ("csrr %0, %1" : "=r"(__tmp) : "i"(csr)); \ + __tmp; \ + }) + +#define write_csr(csr, val) \ + ({ \ + asm volatile ("csrw %0, %1" : : "i"(csr), "rK"(val)); \ + }) + +#define swap_csr(csr, val) \ + ({ \ + unsigned long __tmp; \ + asm volatile ("csrrw %0, %1, %2" \ + : "=r"(__tmp) : "i"(csr), "rK"(val)); \ + __tmp; \ + }) + +#define set_csr(csr, bit) \ + ({ \ + unsigned long __tmp; \ + asm volatile ("csrrs %0, %1, %2" \ + : "=r"(__tmp) : "i"(csr), "rK"(bit)); \ + __tmp; \ + }) + +#define clear_csr(csr, bit) \ + ({ \ + unsigned long __tmp; \ + asm volatile ("csrrc %0, %1, %2" \ + : "=r"(__tmp) : "i"(csr), "rK"(bit)); \ + __tmp; \ + }) + +#define rdtime() read_csr(CSR_TIME) +#define rdcycle() read_csr(CSR_CYCLE) +#define rdinstret() read_csr(CSR_INSTRET) + +static inline __noprof void mb(void) +{ + asm volatile ("fence" : : : "memory"); +} + +static inline __noprof unsigned long read_tp(void) +{ + unsigned long tp; + + asm volatile("mv %0, tp" : "=&r"(tp)); + return tp; +} + +static inline __noprof void wfi(void) +{ + asm volatile ("wfi"); +} + +static inline __noprof void flush_tlb(void) +{ + asm volatile("sfence.vma zero, zero"); +} + +static inline __noprof void flush_tlb_entry(unsigned long va) +{ + asm volatile ("sfence.vma %0" : : "r" (va) : "memory"); +} + +/* supervisor address translation and protection */ +static inline __noprof unsigned long read_satp(void) +{ + unsigned long satp; + + asm volatile("csrr %0, satp" : "=r" (satp)); + + return satp; +} + +static inline __noprof void write_satp(unsigned long satp) +{ + asm volatile("csrw satp, %0" : : "r" (satp)); +} + +/* machine trap-vector base-address register */ +static inline __noprof unsigned long read_mtvec(void) +{ + unsigned long mtvec; + + asm volatile("csrr %0, mtvec" : "=r" (mtvec)); + + return mtvec; +} + +static inline __noprof void write_mtvec(unsigned long mtvec) +{ + asm volatile("csrw mtvec, %0" : : "r" (mtvec)); +} + +/* supervisor trap-vector base-address register */ +static inline __noprof unsigned long read_stvec(void) +{ + unsigned long stvec; + + asm volatile("csrr %0, stvec" : "=r" (stvec)); + + return stvec; +} + +static inline __noprof void write_stvec(unsigned long stvec) +{ + asm volatile("csrw stvec, %0" : : "r" (stvec)); +} + +/* machine status register */ +static inline __noprof unsigned long read_mstatus(void) +{ + unsigned long mstatus; + + asm volatile("csrr %0, mstatus" : "=r" (mstatus)); + + return mstatus; +} + +static inline __noprof void write_mstatus(unsigned long mstatus) +{ + asm volatile("csrw mstatus, %0" : : "r" (mstatus)); +} + +/* supervisor status register */ +static inline __noprof unsigned long read_sstatus(void) +{ + unsigned long sstatus; + + asm volatile("csrr %0, sstatus" : "=r" (sstatus)); + + return sstatus; +} + +static inline __noprof void write_sstatus(unsigned long sstatus) +{ + asm volatile("csrw sstatus, %0" : : "r" (sstatus)); +} + +static inline __noprof void set_sstatus(unsigned long sstatus) +{ + unsigned long x; + + asm volatile ("csrrs %0, sstatus, %1" : "=r"(x) : "rK"(sstatus)); +} + +/* machine exception delegation */ +static inline __noprof unsigned long read_medeleg(void) +{ + unsigned long medeleg; + + asm volatile("csrr %0, medeleg" : "=r" (medeleg)); + + return medeleg; +} + +static inline __noprof void write_medeleg(unsigned long medeleg) +{ + asm volatile("csrw medeleg, %0" : : "r" (medeleg)); +} + +/* machine interrupt delegation */ +static inline __noprof unsigned long read_mideleg(void) +{ + unsigned long mideleg; + + asm volatile("csrr %0, mideleg" : "=r" (mideleg)); + + return mideleg; +} + +static inline __noprof void write_mideleg(unsigned long mideleg) +{ + asm volatile("csrw mideleg, %0" : : "r" (mideleg)); +} + +/* machine interrupt-enable register */ +static inline __noprof unsigned long read_mie(void) +{ + unsigned long mie; + + asm volatile("csrr %0, mie" : "=r" (mie)); + + return mie; +} + +static inline __noprof void write_mie(unsigned long mie) +{ + asm volatile("csrw mie, %0" : : "r" (mie)); +} + +/* supervisor interrupt-enable register */ +static inline __noprof unsigned long read_sie(void) +{ + unsigned long sie; + + asm volatile("csrr %0, sie" : "=r" (sie)); + + return sie; +} + +static inline __noprof void write_sie(unsigned long sie) +{ + asm volatile("csrw sie, %0" : : "r" (sie)); +} + +/* machine exception program counter */ +static inline __noprof unsigned long read_mepc(void) +{ + unsigned long mepc; + + asm volatile("csrr %0, mepc" : "=r" (mepc)); + + return mepc; +} + +static inline __noprof void write_mepc(unsigned long mepc) +{ + asm volatile("csrw mepc, %0" : : "r" (mepc)); +} + +/* supervisor exception program counter */ +static inline __noprof unsigned long read_sepc(void) +{ + unsigned long sepc; + + asm volatile("csrr %0, sepc" : "=r" (sepc)); + + return sepc; +} + +static inline __noprof void write_sepc(unsigned long sepc) +{ + asm volatile("csrw sepc, %0" : : "r" (sepc)); +} + +/* machine scratch register */ +static inline __noprof unsigned long read_mscratch(void) +{ + unsigned long mscratch; + + asm volatile("csrr %0, mscratch" : "=r" (mscratch)); + + return mscratch; +} + +static inline __noprof void write_mscratch(unsigned long mscratch) +{ + asm volatile("csrw mscratch, %0" : : "r" (mscratch)); +} + +/* supervisor scratch register */ +static inline __noprof unsigned long read_sscratch(void) +{ + unsigned long sscratch; + + asm volatile("csrr %0, sscratch" : "=r" (sscratch)); + + return sscratch; +} + +static inline __noprof void write_sscratch(unsigned long sscratch) +{ + asm volatile("csrw sscratch, %0" : : "r" (sscratch)); +} + +/* trap-return instructions */ +static inline __noprof void mret(void) +{ + asm volatile("mret"); +} + +static inline __noprof void sret(void) +{ + asm volatile("sret"); +} + +static inline __noprof void uret(void) +{ + asm volatile("uret"); +} + +#endif /*__ASSEMBLER__*/ + +#endif /*RISCV_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/riscv_macros.S b/optee/optee_os/core/arch/riscv/include/riscv_macros.S new file mode 100644 index 0000000..3092db1 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/riscv_macros.S @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + * Copyright (c) 2015, Linaro Limited + */ + + .altmacro + + + /* + * This helper macro concatenates instr_prefix, instr_suffix, to + * create a l(w,d)/s(w,d) instruction. + */ + .macro __do_reg instr_prefix, base_reg, base_offs, reg + \instr_prefix x\reg, \base_offs(\base_reg) + .endm + + /* + * This helper macro uses recursion to create a loop with a single + * load/store. + */ + .macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \ + from_regnum, to_regnum + + .if (\to_regnum - \from_regnum + 1) > 1 + _do_regs \instr_prefix, \reg_bytes, \base_reg, \ + %(\base_offs + 1 * \reg_bytes), \ + %(\from_regnum + 1), \to_regnum + .endif + + __do_reg \instr_prefix, \base_reg, \base_offs, \from_regnum + .endm + + /* + * Stores registers x[from_regnum]..x[to_regnum] at + * [base_reg, #base_offs] + */ + .macro store_xregs base_reg, base_offs, from_regnum, to_regnum + _do_regs STR, RISCV_XLEN_BYTES, \base_reg, \base_offs, \ + \from_regnum, \to_regnum + .endm + + /* + * Loads registers x[from_regnum]..x[to_regnum] at + * [base_reg, #base_offs] + */ + .macro load_xregs base_reg, base_offs, from_regnum, to_regnum + _do_regs LDR, RISCV_XLEN_BYTES, \base_reg, \base_offs, \ + \from_regnum, \to_regnum + .endm + + /* + * Multiplication macro for RISC-V harts without M extension. + */ + .macro mult, reg_op0, reg_op1, reg_res + li \reg_res, 0 + mv a0, \reg_op0 + mv a1, \reg_op1 + mv a2, a0 + li a0, 0 + 1: + andi a3, a1, 1 + beqz a3, 2f + add a0, a0, a2 + 2: + srli a1, a1, 1 + slli a2, a2, 1 + bnez a1, 1b + add \reg_res, \reg_res, a0 + .endm diff --git a/optee/optee_os/core/arch/riscv/include/sbi.h b/optee/optee_os/core/arch/riscv/include/sbi.h new file mode 100644 index 0000000..e61e877 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/sbi.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef SBI_H +#define SBI_H + +#if defined(CFG_RISCV_SBI) + +/* SBI return error codes */ +#define SBI_SUCCESS 0 +#define SBI_ERR_FAILURE -1 +#define SBI_ERR_NOT_SUPPORTED -2 +#define SBI_ERR_INVALID_PARAM -3 +#define SBI_ERR_DENIED -4 +#define SBI_ERR_INVALID_ADDRESS -5 +#define SBI_ERR_ALREADY_AVAILABLE -6 +#define SBI_ERR_ALREADY_STARTED -7 +#define SBI_ERR_ALREADY_STOPPED -8 + +/* SBI Extension IDs */ +#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x01, 0 +#define SBI_EXT_HSM 0x48534D + +/* SBI function IDs for HSM extension */ +#define SBI_EXT_HSM_HART_START U(0) +#define SBI_EXT_HSM_HART_STOP U(1) +#define SBI_EXT_HSM_HART_GET_STATUS U(2) +#define SBI_EXT_HSM_HART_SUSPEND U(3) + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include +#include +#include + +void sbi_console_putchar(int ch); +int sbi_boot_hart(uint32_t hart_id, paddr_t start_addr, unsigned long arg); + +#endif /*__ASSEMBLER__*/ +#endif /*defined(CFG_RISCV_SBI)*/ +#endif /*SBI_H*/ diff --git a/optee/optee_os/core/arch/riscv/include/sub.mk b/optee/optee_os/core/arch/riscv/include/sub.mk new file mode 100644 index 0000000..7ec09f6 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/include/sub.mk @@ -0,0 +1 @@ +global-incdirs-y += . diff --git a/optee/optee_os/core/arch/riscv/kernel/abort.c b/optee/optee_os/core/arch/riscv/kernel/abort.c new file mode 100644 index 0000000..d91d3b9 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/abort.c @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + * Copyright (c) 2015-2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum fault_type { + FAULT_TYPE_USER_MODE_PANIC, + FAULT_TYPE_USER_MODE_VFP, + FAULT_TYPE_PAGE_FAULT, + FAULT_TYPE_IGNORE, +}; + +#ifdef CFG_UNWIND + +/* Kernel mode unwind */ +static void __print_stack_unwind(struct abort_info *ai) +{ + struct unwind_state_rv state = { + .fp = ai->regs->s0, + .sp = ai->regs->sp, + .pc = ai->regs->epc, + }; + + print_stack_rv(&state, thread_stack_start(), thread_stack_size()); +} + +#else /* CFG_UNWIND */ +static void __print_stack_unwind(struct abort_info *ai __unused) +{ +} +#endif /* CFG_UNWIND */ + +static __maybe_unused const char *abort_type_to_str(uint32_t abort_type) +{ + if (abort_type == ABORT_TYPE_DATA) + return "data"; + if (abort_type == ABORT_TYPE_PREFETCH) + return "prefetch"; + return "undef"; +} + +static __maybe_unused const char * +fault_to_str(uint32_t abort_type, uint32_t fault_descr) +{ + /* fault_descr is only valid for data or prefetch abort */ + if (abort_type != ABORT_TYPE_DATA && abort_type != ABORT_TYPE_PREFETCH) + return ""; + + switch (core_mmu_get_fault_type(fault_descr)) { + case CORE_MMU_FAULT_ALIGNMENT: + return " (alignment fault)"; + case CORE_MMU_FAULT_TRANSLATION: + return " (translation fault)"; + case CORE_MMU_FAULT_READ_PERMISSION: + return " (read permission fault)"; + case CORE_MMU_FAULT_WRITE_PERMISSION: + return " (write permission fault)"; + case CORE_MMU_FAULT_TAG_CHECK: + return " (tag check fault)"; + default: + return ""; + } +} + +static __maybe_unused void +__print_abort_info(struct abort_info *ai __maybe_unused, + const char *ctx __maybe_unused) +{ + __maybe_unused size_t core_pos = 0; + + if (abort_is_user_exception(ai)) + core_pos = thread_get_tsd()->abort_core; + else + core_pos = get_core_pos(); + + EMSG_RAW(""); + EMSG_RAW("%s %s-abort at address 0x%" PRIxVA "%s", + ctx, abort_type_to_str(ai->abort_type), ai->va, + fault_to_str(ai->abort_type, ai->fault_descr)); + EMSG_RAW("cpu\t#%zu", core_pos); + EMSG_RAW("cause\t%016" PRIxPTR " epc\t%016" PRIxPTR, + ai->regs->cause, ai->regs->epc); + EMSG_RAW("tval\t%016" PRIxPTR " status\t%016" PRIxPTR, + ai->regs->tval, ai->regs->status); + EMSG_RAW("ra\t%016" PRIxPTR " sp\t%016" PRIxPTR, + ai->regs->ra, ai->regs->sp); + EMSG_RAW("gp\t%016" PRIxPTR " tp\t%016" PRIxPTR, + ai->regs->gp, ai->regs->tp); + EMSG_RAW("t0\t%016" PRIxPTR " t1\t%016" PRIxPTR, + ai->regs->t0, ai->regs->t1); + EMSG_RAW("t2\t%016" PRIxPTR " s0\t%016" PRIxPTR, + ai->regs->t2, ai->regs->s0); + EMSG_RAW("s1\t%016" PRIxPTR " a0\t%016" PRIxPTR, + ai->regs->s1, ai->regs->a0); + EMSG_RAW("a1\t%016" PRIxPTR " a2\t%016" PRIxPTR, + ai->regs->a1, ai->regs->a2); + EMSG_RAW("a3\t%016" PRIxPTR " a4\t%016" PRIxPTR, + ai->regs->a3, ai->regs->a4); + EMSG_RAW("a5\t%016" PRIxPTR " a5\t%016" PRIxPTR, + ai->regs->a5, ai->regs->a5); + EMSG_RAW("a6\t%016" PRIxPTR " a7\t%016" PRIxPTR, + ai->regs->a6, ai->regs->a7); + EMSG_RAW("s2\t%016" PRIxPTR " s3\t%016" PRIxPTR, + ai->regs->s2, ai->regs->s3); + EMSG_RAW("s4\t%016" PRIxPTR " s5\t%016" PRIxPTR, + ai->regs->s4, ai->regs->s5); + EMSG_RAW("s6\t%016" PRIxPTR " s7\t%016" PRIxPTR, + ai->regs->s6, ai->regs->s7); + EMSG_RAW("s8\t%016" PRIxPTR " s9\t%016" PRIxPTR, + ai->regs->s8, ai->regs->s9); + EMSG_RAW("s10\t%016" PRIxPTR " s11\t%016" PRIxPTR, + ai->regs->s10, ai->regs->s11); + EMSG_RAW("t3\t%016" PRIxPTR " t4\t%016" PRIxPTR, + ai->regs->t3, ai->regs->t4); + EMSG_RAW("t5\t%016" PRIxPTR " t6\t%016" PRIxPTR, + ai->regs->t5, ai->regs->t6); +} + +/* + * Print abort info and (optionally) stack dump to the console + * @ai kernel-mode abort info. + * @stack_dump true to show a stack trace + */ +static void __abort_print(struct abort_info *ai, bool stack_dump) +{ + assert(!abort_is_user_exception(ai)); + + __print_abort_info(ai, "Core"); + + if (stack_dump) { + trace_printf_helper_raw(TRACE_ERROR, true, + "TEE load address @ %#"PRIxVA, + VCORE_START_VA); + __print_stack_unwind(ai); + } +} + +void abort_print(struct abort_info *ai) +{ + __abort_print(ai, false); +} + +void abort_print_error(struct abort_info *ai) +{ + __abort_print(ai, true); +} + +/* This function must be called from a normal thread */ +void abort_print_current_ts(void) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + struct abort_info ai = { }; + struct ts_session *s = ts_get_current_session(); + + ai.abort_type = tsd->abort_type; + ai.fault_descr = tsd->abort_descr; + ai.va = tsd->abort_va; + ai.pc = tsd->abort_regs.epc; + ai.regs = &tsd->abort_regs; + + if (ai.abort_type != ABORT_TYPE_USER_MODE_PANIC) + __print_abort_info(&ai, "User mode"); + + s->ctx->ops->dump_state(s->ctx); + +#if defined(CFG_FTRACE_SUPPORT) + if (s->ctx->ops->dump_ftrace) { + s->fbuf = NULL; + s->ctx->ops->dump_ftrace(s->ctx); + } +#endif +} + +static void save_abort_info_in_tsd(struct abort_info *ai) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + + tsd->abort_type = ai->abort_type; + tsd->abort_descr = ai->fault_descr; + tsd->abort_va = ai->va; + tsd->abort_regs = *ai->regs; + tsd->abort_core = get_core_pos(); +} + +static void set_abort_info(uint32_t abort_type __unused, + struct thread_abort_regs *regs, + struct abort_info *ai) +{ + ai->fault_descr = regs->cause; + switch (ai->fault_descr) { + case CAUSE_MISALIGNED_FETCH: + case CAUSE_FETCH_ACCESS: + case CAUSE_FETCH_PAGE_FAULT: + case CAUSE_FETCH_GUEST_PAGE_FAULT: + ai->abort_type = ABORT_TYPE_PREFETCH; + break; + case CAUSE_MISALIGNED_LOAD: + case CAUSE_LOAD_ACCESS: + case CAUSE_MISALIGNED_STORE: + case CAUSE_STORE_ACCESS: + case CAUSE_LOAD_PAGE_FAULT: + case CAUSE_STORE_PAGE_FAULT: + case CAUSE_LOAD_GUEST_PAGE_FAULT: + case CAUSE_STORE_GUEST_PAGE_FAULT: + ai->abort_type = ABORT_TYPE_DATA; + break; + default: + ai->abort_type = ABORT_TYPE_UNDEF; + } + + ai->va = regs->tval; + ai->pc = regs->epc; + ai->regs = regs; +} + +static void handle_user_mode_panic(struct abort_info *ai) +{ + /* + * It was a user exception, stop user execution and return + * to TEE Core. + */ + ai->regs->a0 = TEE_ERROR_TARGET_DEAD; + ai->regs->a1 = true; + ai->regs->a2 = 0xdeadbeef; + ai->regs->ra = (vaddr_t)thread_unwind_user_mode; + ai->regs->sp = thread_get_saved_thread_sp(); + ai->regs->status = read_csr(CSR_XSTATUS); + + thread_exit_user_mode(ai->regs->a0, ai->regs->a1, ai->regs->a2, + ai->regs->a3, ai->regs->sp, ai->regs->ra, + ai->regs->status); +} + +#ifdef CFG_WITH_VFP +static void handle_user_mode_vfp(void) +{ + struct ts_session *s = ts_get_current_session(); + + thread_user_enable_vfp(&to_user_mode_ctx(s->ctx)->vfp); +} +#endif /*CFG_WITH_VFP*/ + +#ifdef CFG_WITH_USER_TA + +/* Returns true if the exception originated from user mode */ +bool abort_is_user_exception(struct abort_info *ai) +{ + return (ai->regs->status & CSR_XSTATUS_SPP) == 0; +} + +#else /*CFG_WITH_USER_TA*/ +bool abort_is_user_exception(struct abort_info *ai __unused) +{ + return false; +} +#endif /*CFG_WITH_USER_TA*/ + +#if defined(CFG_WITH_VFP) && defined(CFG_WITH_USER_TA) +static bool is_vfp_fault(struct abort_info *ai) +{ + /* Implement */ + return false; +} +#else /*CFG_WITH_VFP && CFG_WITH_USER_TA*/ +static bool is_vfp_fault(struct abort_info *ai __unused) +{ + return false; +} +#endif /*CFG_WITH_VFP && CFG_WITH_USER_TA*/ + +static enum fault_type get_fault_type(struct abort_info *ai) +{ + if (abort_is_user_exception(ai)) { + if (is_vfp_fault(ai)) + return FAULT_TYPE_USER_MODE_VFP; + return FAULT_TYPE_USER_MODE_PANIC; + } + + if (thread_is_from_abort_mode()) { + abort_print_error(ai); + panic("[abort] abort in abort handler (trap CPU)"); + } + + if (ai->abort_type == ABORT_TYPE_UNDEF) { + if (abort_is_user_exception(ai)) + return FAULT_TYPE_USER_MODE_PANIC; + abort_print_error(ai); + panic("[abort] undefined abort (trap CPU)"); + } + + switch (core_mmu_get_fault_type(ai->fault_descr)) { + case CORE_MMU_FAULT_ALIGNMENT: + if (abort_is_user_exception(ai)) + return FAULT_TYPE_USER_MODE_PANIC; + abort_print_error(ai); + panic("[abort] alignment fault! (trap CPU)"); + break; + + case CORE_MMU_FAULT_ACCESS_BIT: + if (abort_is_user_exception(ai)) + return FAULT_TYPE_USER_MODE_PANIC; + abort_print_error(ai); + panic("[abort] access bit fault! (trap CPU)"); + break; + + case CORE_MMU_FAULT_DEBUG_EVENT: + if (!abort_is_user_exception(ai)) + abort_print(ai); + DMSG("[abort] Ignoring debug event!"); + return FAULT_TYPE_IGNORE; + + case CORE_MMU_FAULT_TRANSLATION: + case CORE_MMU_FAULT_WRITE_PERMISSION: + case CORE_MMU_FAULT_READ_PERMISSION: + return FAULT_TYPE_PAGE_FAULT; + + case CORE_MMU_FAULT_ASYNC_EXTERNAL: + if (!abort_is_user_exception(ai)) + abort_print(ai); + DMSG("[abort] Ignoring async external abort!"); + return FAULT_TYPE_IGNORE; + + case CORE_MMU_FAULT_TAG_CHECK: + if (abort_is_user_exception(ai)) + return FAULT_TYPE_USER_MODE_PANIC; + abort_print_error(ai); + panic("[abort] Tag check fault! (trap CPU)"); + break; + + case CORE_MMU_FAULT_OTHER: + default: + if (!abort_is_user_exception(ai)) + abort_print(ai); + DMSG("[abort] Unhandled fault!"); + return FAULT_TYPE_IGNORE; + } +} + +void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs) +{ + struct abort_info ai; + + set_abort_info(abort_type, regs, &ai); + + switch (get_fault_type(&ai)) { + case FAULT_TYPE_IGNORE: + break; + case FAULT_TYPE_USER_MODE_PANIC: + DMSG("[abort] abort in User mode (TA will panic)"); + save_abort_info_in_tsd(&ai); +#ifdef CFG_WITH_VFP + vfp_disable(); +#endif + handle_user_mode_panic(&ai); + break; +#ifdef CFG_WITH_VFP + case FAULT_TYPE_USER_MODE_VFP: + handle_user_mode_vfp(); + break; +#endif + case FAULT_TYPE_PAGE_FAULT: + default: + if (thread_get_id_may_fail() < 0) { + abort_print_error(&ai); + panic("abort outside thread context"); + } + + if (!abort_is_user_exception(&ai)) { + abort_print_error(&ai); + panic("unhandled page fault abort"); + } + DMSG("[abort] abort in User mode (TA will panic)"); + save_abort_info_in_tsd(&ai); +#ifdef CFG_WITH_VFP + vfp_disable(); +#endif + handle_user_mode_panic(&ai); + break; + } +} diff --git a/optee/optee_os/core/arch/riscv/kernel/arch_scall.c b/optee/optee_os/core/arch/riscv/kernel/arch_scall.c new file mode 100644 index 0000000..01bdc18 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/arch_scall.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + * Copyright (c) 2014-2022, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TA_CONTEXT_MAX_SIZE (RISCV_XLEN_BYTES * 32) + +#ifdef CFG_UNWIND + +static void save_panic_regs_rv_ta(struct thread_specific_data *tsd, + unsigned long *pushed) +{ + tsd->abort_regs = (struct thread_abort_regs){ + .ra = pushed[0], + .sp = (unsigned long)pushed, + .gp = pushed[1], + .tp = pushed[2], + .t0 = pushed[3], + .t1 = pushed[4], + .t2 = pushed[5], + .s0 = pushed[6], + .s1 = pushed[7], + .a0 = pushed[8], + .a1 = pushed[9], + .a2 = pushed[10], + .a3 = pushed[11], + .a4 = pushed[12], + .a5 = pushed[13], + .a6 = pushed[14], + .a7 = pushed[15], + .s2 = pushed[16], + .s3 = pushed[17], + .s4 = pushed[18], + .s5 = pushed[19], + .s6 = pushed[20], + .s7 = pushed[21], + .s8 = pushed[22], + .s9 = pushed[23], + .s10 = pushed[24], + .s11 = pushed[25], + .t3 = pushed[26], + .t4 = pushed[27], + .t5 = pushed[28], + .t6 = pushed[29], + .status = read_csr(CSR_XSTATUS), + }; +} + +void scall_save_panic_stack(struct thread_scall_regs *regs) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + struct ts_session *s = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); + + if (vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE, + (uaddr_t)regs->a1, + TA_CONTEXT_MAX_SIZE)) { + TAMSG_RAW(""); + TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, + (uaddr_t)regs->a1); + return; + } + + tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; + tsd->abort_descr = 0; + tsd->abort_va = 0; + + save_panic_regs_rv_ta(tsd, (unsigned long *)regs->a1); +} + +#else /* CFG_UNWIND */ +void scall_save_panic_stack(struct thread_scall_regs *regs __unused) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + + tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; +} +#endif /* CFG_UNWIND */ diff --git a/optee/optee_os/core/arch/riscv/kernel/arch_scall_rv.S b/optee/optee_os/core/arch/riscv/kernel/arch_scall_rv.S new file mode 100644 index 0000000..2ec90ae --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/arch_scall_rv.S @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ +#include "tee_syscall_numbers.h" +#include "trace_levels.h" +#include +#include +#include +#include +#include +#include + +/* + * uint32_t scall_do_call(struct thread_scall_regs *regs, syscall_t func); + * + * Called from scall_handle_user_ta() + */ +FUNC scall_do_call , : + addi sp, sp, -16 + + /* Save scall regs to t0 */ + mv t0, a0 + + /* Save func to t1 */ + mv t1, a1 + + /* Push return address to stack */ + store_xregs sp, 0, 1 + + /* Load arguments to function */ + load_xregs a0, THREAD_SCALL_REG_A0, 10, 17 + + /* Call the syscall function */ + jalr t1 + + /* Pop return address from stack */ + load_xregs sp, 0, 1 + + addi sp, sp, 16 + ret +END_FUNC scall_do_call + +/* + * void syscall_sys_return(uint32_t ret); + */ +FUNC syscall_sys_return , : + li a1, 0 /* panic = false */ + li a2, 0 /* panic_code = 0 */ + mv a3, t0 /* pointer to struct thread_scall_regs */ + j scall_sys_return_helper +END_FUNC syscall_sys_return + +/* + * void syscall_panic(uint32_t code); + */ +FUNC syscall_panic , : + li a1, 1 /* panic = true */ + mv a2, a0 /* code */ + li a0, TEE_ERROR_TARGET_DEAD + mv a3, t0 /* pointer to struct thread_scall_regs */ + j scall_sys_return_helper +END_FUNC syscall_panic diff --git a/optee/optee_os/core/arch/riscv/kernel/asm-defines.c b/optee/optee_os/core/arch/riscv/kernel/asm-defines.c new file mode 100644 index 0000000..d00f1f1 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/asm-defines.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include + +DEFINES +{ + /* struct thread_ctx */ + DEFINE(THREAD_CTX_KERN_SP, offsetof(struct thread_ctx, kern_sp)); + DEFINE(THREAD_CTX_STACK_VA_END, offsetof(struct thread_ctx, + stack_va_end)); + DEFINE(THREAD_CTX_SIZE, sizeof(struct thread_ctx)); + + /* struct thread_core_local */ + DEFINE(THREAD_CORE_LOCAL_SIZE, sizeof(struct thread_core_local)); + DEFINE(THREAD_CORE_LOCAL_HART_ID, + offsetof(struct thread_core_local, hart_id)); + DEFINE(THREAD_CORE_LOCAL_TMP_STACK_VA_END, + offsetof(struct thread_core_local, tmp_stack_va_end)); + DEFINE(THREAD_CORE_LOCAL_CURR_THREAD, + offsetof(struct thread_core_local, curr_thread)); + DEFINE(THREAD_CORE_LOCAL_FLAGS, + offsetof(struct thread_core_local, flags)); + DEFINE(THREAD_CORE_LOCAL_ABT_STACK_VA_END, + offsetof(struct thread_core_local, abt_stack_va_end)); + DEFINE(THREAD_CORE_LOCAL_X10, offsetof(struct thread_core_local, x[0])); + + DEFINE(STACK_TMP_GUARD, STACK_CANARY_SIZE / 2 + STACK_TMP_OFFS); + + /* struct thread_ctx_regs */ + DEFINE(THREAD_CTX_REG_STATUS, offsetof(struct thread_ctx_regs, status)); + DEFINE(THREAD_CTX_REG_RA, offsetof(struct thread_ctx_regs, ra)); + DEFINE(THREAD_CTX_REG_SP, offsetof(struct thread_ctx_regs, sp)); + DEFINE(THREAD_CTX_REG_T0, offsetof(struct thread_ctx_regs, t0)); + DEFINE(THREAD_CTX_REG_S0, offsetof(struct thread_ctx_regs, s0)); + DEFINE(THREAD_CTX_REG_A0, offsetof(struct thread_ctx_regs, a0)); + DEFINE(THREAD_CTX_REG_S2, offsetof(struct thread_ctx_regs, s2)); + DEFINE(THREAD_CTX_REG_T3, offsetof(struct thread_ctx_regs, t3)); + DEFINE(THREAD_CTX_REGS_SIZE, sizeof(struct thread_ctx_regs)); + + /* struct thread_user_mode_rec */ + DEFINE(THREAD_USER_MODE_REC_CTX_REGS_PTR, + offsetof(struct thread_user_mode_rec, ctx_regs_ptr)); + DEFINE(THREAD_USER_MODE_REC_X1, + offsetof(struct thread_user_mode_rec, x[0])); + DEFINE(THREAD_USER_MODE_REC_X8, + offsetof(struct thread_user_mode_rec, x[4])); + DEFINE(THREAD_USER_MODE_REC_X18, + offsetof(struct thread_user_mode_rec, x[6])); + DEFINE(THREAD_USER_MODE_REC_SIZE, sizeof(struct thread_user_mode_rec)); + + /* struct thread_trap_regs */ + DEFINE(THREAD_TRAP_REG_SP, offsetof(struct thread_trap_regs, sp)); + DEFINE(THREAD_TRAP_REG_RA, offsetof(struct thread_trap_regs, ra)); + DEFINE(THREAD_TRAP_REG_GP, offsetof(struct thread_trap_regs, gp)); + DEFINE(THREAD_TRAP_REG_TP, offsetof(struct thread_trap_regs, tp)); + DEFINE(THREAD_TRAP_REG_T0, offsetof(struct thread_trap_regs, t0)); + DEFINE(THREAD_TRAP_REG_A0, offsetof(struct thread_trap_regs, a0)); + DEFINE(THREAD_TRAP_REG_T3, offsetof(struct thread_trap_regs, t3)); + DEFINE(THREAD_TRAP_REG_EPC, offsetof(struct thread_trap_regs, epc)); + DEFINE(THREAD_TRAP_REG_STATUS, + offsetof(struct thread_trap_regs, status)); + DEFINE(THREAD_TRAP_REGS_SIZE, sizeof(struct thread_trap_regs)); + + /* struct thread_scall_regs */ + DEFINE(THREAD_SCALL_REG_STATUS, + offsetof(struct thread_scall_regs, status)); + DEFINE(THREAD_SCALL_REG_RA, offsetof(struct thread_scall_regs, ra)); + DEFINE(THREAD_SCALL_REG_SP, offsetof(struct thread_scall_regs, sp)); + DEFINE(THREAD_SCALL_REG_A0, offsetof(struct thread_scall_regs, a0)); + DEFINE(THREAD_SCALL_REGS_SIZE, sizeof(struct thread_scall_regs)); +} diff --git a/optee/optee_os/core/arch/riscv/kernel/boot.c b/optee/optee_os/core/arch/riscv/kernel/boot.c new file mode 100644 index 0000000..83fa9ea --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/boot.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PADDR_INVALID ULONG_MAX + +paddr_t start_addr; +unsigned long boot_args[4]; + +uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE]; + +void init_sec_mon(unsigned long nsec_entry __maybe_unused) +{ + assert(nsec_entry == PADDR_INVALID); + /* Do nothing as we don't have a secure monitor */ +} + +#ifdef CFG_RISCV_S_MODE +static void start_secondary_cores(void) +{ + size_t i = 0; + size_t pos = get_core_pos(); + + for (i = 0; i < CFG_TEE_CORE_NB_CORE; i++) + if (i != pos && IS_ENABLED(CFG_RISCV_SBI) && + sbi_boot_hart(i, start_addr, i)) + EMSG("Error starting secondary hart %zu", i); +} +#endif + +static void init_runtime(void) +{ + malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); + + IMSG_RAW("\n"); +} + +void init_tee_runtime(void) +{ + core_mmu_init_ta_ram(); + call_preinitcalls(); + call_initcalls(); +} + +static void init_primary(unsigned long nsec_entry) +{ + thread_init_core_local_stacks(); + + /* + * Mask asynchronous exceptions before switch to the thread vector + * as the thread handler requires those to be masked while + * executing with the temporary stack. The thread subsystem also + * asserts that the foreign interrupts are blocked when using most of + * its functions. + */ + thread_set_exceptions(THREAD_EXCP_ALL); + + init_runtime(); + thread_init_boot_thread(); + thread_init_primary(); + thread_init_per_cpu(); + init_sec_mon(nsec_entry); +} + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void plat_primary_init_early(void) +{ +} + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void main_init_plic(void) +{ +} + +/* May be overridden in plat-$(PLATFORM)/main.c */ +__weak void main_secondary_init_plic(void) +{ +} + +void boot_init_primary_early(unsigned long pageable_part __unused, + unsigned long nsec_entry __unused) +{ + unsigned long e = PADDR_INVALID; + + init_primary(e); +} + +void boot_init_primary_late(unsigned long fdt __unused, + unsigned long tos_fw_config __unused) +{ + IMSG("OP-TEE version: %s", core_v_str); + if (IS_ENABLED(CFG_WARN_INSECURE)) { + IMSG("WARNING: This OP-TEE configuration might be insecure!"); + IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html"); + } + IMSG("Primary CPU initializing"); + main_init_plic(); + init_tee_runtime(); + call_finalcalls(); + IMSG("Primary CPU initialized"); + +#ifdef CFG_RISCV_S_MODE + start_secondary_cores(); +#endif +} + +static void init_secondary_helper(unsigned long nsec_entry) +{ + size_t pos = get_core_pos(); + + IMSG("Secondary CPU %zu initializing", pos); + + /* + * Mask asynchronous exceptions before switch to the thread vector + * as the thread handler requires those to be masked while + * executing with the temporary stack. The thread subsystem also + * asserts that the foreign interrupts are blocked when using most of + * its functions. + */ + thread_set_exceptions(THREAD_EXCP_ALL); + + thread_init_per_cpu(); + init_sec_mon(nsec_entry); + main_secondary_init_plic(); + + IMSG("Secondary CPU %zu initialized", pos); +} + +void boot_init_secondary(unsigned long nsec_entry __unused) +{ + init_secondary_helper(PADDR_INVALID); +} diff --git a/optee/optee_os/core/arch/riscv/kernel/cache_helpers_rv.S b/optee/optee_os/core/arch/riscv/kernel/cache_helpers_rv.S new file mode 100644 index 0000000..ea67739 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/cache_helpers_rv.S @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#include +#include + +/* + * On the below data cache management, we rely on FENCE instruction. + * The FENCE instruction is used to order device I/O and memory accesses + * as viewed by other RISC-V harts and external devices or coprocessors. + * "fence" below is a pseudo-instruction of "fence iorw, iorw" which + * performs Fence on all memory and I/O. + */ + +/* void dcache_cleaninv_range(void *addr, size_t size); */ +FUNC dcache_cleaninv_range , : + fence + ret +END_FUNC dcache_cleaninv_range + +/* void dcache_clean_range(void *addr, size_t size); */ +FUNC dcache_clean_range , : + fence + ret +END_FUNC dcache_clean_range + +/* void dcache_inv_range(void *addr, size_t size); */ +FUNC dcache_inv_range , : + fence + ret +END_FUNC dcache_inv_range + +/* void dcache_op_all(unsigned long op_type); */ +FUNC dcache_op_all , : + fence + ret +END_FUNC dcache_op_all + +/* void icache_inv_all(void); */ +FUNC icache_inv_all , : + /* + * FENCE.I instruction provides explicit synchronization + * between writes to instruction memory and instruction + * fetches on the same hart. This implies instruction cache + * management operations as result of executing this instruction. + */ + fence.i + ret +END_FUNC icache_inv_all + +/* void icache_inv_range(void *addr, size_t size); */ +FUNC icache_inv_range , : + /* + * RISC-V does not have an instruction to flush a range + * of the I$, therefore, flush it entirely as invoking + * icache_inv_all(). + */ + fence.i + ret +END_FUNC icache_inv_range diff --git a/optee/optee_os/core/arch/riscv/kernel/entry.S b/optee/optee_os/core/arch/riscv/kernel/entry.S new file mode 100644 index 0000000..64b4307 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/entry.S @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +.section .data +.balign 4 + +#ifdef CFG_BOOT_SYNC_CPU +.equ SEM_CPU_READY, 1 +#endif + + /* + * Setup sp to point to the top of the tmp stack for the current CPU: + * sp is assigned: + * stack_tmp + (hartid + 1) * stack_tmp_stride - STACK_TMP_GUARD + */ +.macro set_sp + /* Unsupported CPU, park it before it breaks something */ + li t1, CFG_TEE_CORE_NB_CORE + csrr t0, CSR_XSCRATCH + bge t0, t1, unhandled_cpu + addi t0, t0, 1 + lw t1, stack_tmp_stride + /* + * t0 = (hartid + 1) + * t1 = value of stack_tmp_stride + * value of stack_tmp_rel = stack_tmp - stack_tmp_rel - STACK_TMP_GUARD + * sp = stack_tmp + (hartid + 1) * stack_tmp_stride - STACK_TMP_GUARD + * = stack_tmp_rel + (value of stack_tmp_rel) + (t0 * t1) + */ + mul t1, t0, t1 + la t2, stack_tmp_rel + lw t0, 0(t2) + add t0, t0, t2 + add sp, t1, t0 +.endm + +.macro cpu_is_ready +#ifdef CFG_BOOT_SYNC_CPU + csrr t0, CSR_XSCRATCH + la t1, sem_cpu_sync + slli t0, t0, 2 + add t1, t1, t0 + li t2, SEM_CPU_READY + sw t2, 0(t1) + fence +#endif +.endm + +.macro set_tp + csrr a0, CSR_XSCRATCH + li a1, THREAD_CORE_LOCAL_SIZE + la tp, thread_core_local + mul a2, a1, a0 + add tp, tp, a2 + sw a0, THREAD_CORE_LOCAL_HART_ID(tp) +.endm + +.macro set_satp + la a1, boot_mmu_config + LDR a0, CORE_MMU_CONFIG_SATP(a1) + csrw CSR_SATP, a0 + sfence.vma zero, zero +.endm + +.macro wait_primary +#ifdef CFG_BOOT_SYNC_CPU + la t0, sem_cpu_sync + li t2, SEM_CPU_READY +1: + fence w, w + lw t1, 0(t0) + bne t1, t2, 1b +#endif +.endm + +.macro wait_secondary +#ifdef CFG_BOOT_SYNC_CPU + la t0, sem_cpu_sync + li t1, CFG_TEE_CORE_NB_CORE + li t2, SEM_CPU_READY +1: + addi t1, t1, -1 + beqz t1, 3f + addi t0, t0, 4 +2: + fence + lw t1, 0(t0) + bne t1, t2, 2b + j 1b +3: +#endif +.endm + +#ifdef CFG_BOOT_SYNC_CPU +#define flush_cpu_semaphores \ + la t0, sem_cpu_sync_start + la t1, sem_cpu_sync_end + fence +#else +#define flush_cpu_semaphores +#endif + +.macro bootargs_entry + /* + * Save boot arguments + */ + la t0, boot_args + /* Save boot hart */ + STR a0, REGOFF(0)(t0) + /* Save FDT address */ + STR a1, REGOFF(1)(t0) +.endm + +FUNC _start , : +.option push +.option norelax + la gp, __global_pointer$ +.option pop +#ifdef CFG_RISCV_M_MODE + csrr a0, CSR_MHARTID +#endif + csrw CSR_XSCRATCH, a0 + bnez a0, reset_secondary + jal reset_primary + j . +END_FUNC _start + +LOCAL_FUNC reset_primary , : , .identity_map +UNWIND( .cantunwind) + + bootargs_entry + + /* + * Zero bss + */ + lla t0, __bss_start + lla t1, __bss_end + beq t0, t1, 1f +0: + STR zero, (t0) + add t0, t0, RISCV_XLEN_BYTES + bne t0, t1, 0b +1: +#ifdef CFG_RISCV_S_MODE + lla t0, _start + lla t1, start_addr + STR t0, (t1) +#endif + + csrw CSR_SATP, zero + set_sp + set_tp + + jal thread_init_thread_core_local + jal plat_primary_init_early + jal console_init + + mv a0, x0 + la a1, boot_mmu_config + jal core_init_mmu_map + + set_satp + + jal boot_init_primary_early + jal boot_init_primary_late + + cpu_is_ready + flush_cpu_semaphores + wait_secondary + + jal thread_clr_boot_thread + j mu_service +END_FUNC reset_primary + +LOCAL_FUNC reset_secondary , : , .identity_map +UNWIND( .cantunwind) + wait_primary + csrw CSR_SATP, zero + set_sp + set_tp + set_satp + cpu_is_ready + + jal boot_init_secondary + j . +END_FUNC reset_secondary + +LOCAL_FUNC unhandled_cpu , : + wfi + j unhandled_cpu +END_FUNC unhandled_cpu + +#ifdef CFG_BOOT_SYNC_CPU +LOCAL_DATA sem_cpu_sync_start , : + .word sem_cpu_sync +END_DATA sem_cpu_sync_start + +LOCAL_DATA sem_cpu_sync_end , : + .word sem_cpu_sync + (CFG_TEE_CORE_NB_CORE << 2) +END_DATA sem_cpu_sync_end +#endif + +LOCAL_DATA stack_tmp_rel , : + .word stack_tmp - stack_tmp_rel - STACK_TMP_GUARD +END_DATA stack_tmp_rel + +LOCAL_DATA stack_tmp_stride_rel , : + .word stack_tmp_stride - stack_tmp_stride_rel +END_DATA stack_tmp_stride_rel + + .balign 8 +LOCAL_DATA boot_mmu_config , : /* struct core_mmu_config */ + .skip CORE_MMU_CONFIG_SIZE +END_DATA boot_mmu_config diff --git a/optee/optee_os/core/arch/riscv/kernel/idle.c b/optee/optee_os/core/arch/riscv/kernel/idle.c new file mode 100644 index 0000000..e508372 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/idle.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ + +#include +#include + +void cpu_idle(void) +{ + /* ensure memory operations were complete */ + mb(); + /* stall the hart */ + wfi(); +} diff --git a/optee/optee_os/core/arch/riscv/kernel/kern.ld.S b/optee/optee_os/core/arch/riscv/kernel/kern.ld.S new file mode 100644 index 0000000..e429de3 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/kern.ld.S @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND MIT) */ +/* + * Copyright 2022-2023 NXP + */ + +/* + * 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. + */ + +/* + * Copyright (c) 2008-2010 Travis Geiselbrecht + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +/* + * Note: + * Clang 11 (ld.lld) generates non-relocatable reference when using ROUNDDOWN() + * from , which does not work with ASLR. + */ +#define LD_ROUNDDOWN(x, y) ((x) - ((x) % (y))) + +OUTPUT_FORMAT(CFG_KERN_LINKER_FORMAT) +OUTPUT_ARCH(CFG_KERN_LINKER_ARCH) + +ENTRY(_start) +SECTIONS +{ + . = TEE_LOAD_ADDR; + /* Ensure text section is page aligned */ + ASSERT(!(TEE_LOAD_ADDR & (SMALL_PAGE_SIZE - 1)), + "text start should align to 4Kb") + + __text_start = .; + + /* + * Memory between TEE_LOAD_ADDR and page aligned rounded down + * value will be mapped with unpaged "text" section attributes: + * likely to be read-only/executable. + */ + __flatmap_rx_start = LD_ROUNDDOWN(__text_start, SMALL_PAGE_SIZE); + + .text : { + KEEP(*(.text._start)) + __identity_map_init_start = .; + __text_data_start = .; + *(.identity_map.data) + __text_data_end = .; + *(.identity_map .identity_map.*) + __identity_map_init_end = .; + *(.text .text.*) + *(.sram.text.glue_7* .gnu.linkonce.t.*) + . = ALIGN(8); + } + __text_end = .; + +#ifdef CFG_CORE_RODATA_NOEXEC + . = ALIGN(SMALL_PAGE_SIZE); +#endif + __flatmap_rx_size = . - __flatmap_rx_start; + __flatmap_ro_start = .; + + .rodata : ALIGN(8) { + __rodata_start = .; + *(.gnu.linkonce.r.*) + *(.rodata .rodata.*) +#ifndef CFG_CORE_ASLR + . = ALIGN(8); + KEEP(*(SORT(.scattered_array*))); +#endif + . = ALIGN(8); + __rodata_end = .; + } + + .got : { *(.got.plt) *(.got) } + .note.gnu.property : { *(.note.gnu.property) } + .plt : { *(.plt) } + + .ctors : ALIGN(8) { + __ctor_list = .; + KEEP(*(.ctors .ctors.* .init_array .init_array.*)) + __ctor_end = .; + } + .dtors : ALIGN(8) { + __dtor_list = .; + KEEP(*(.dtors .dtors.* .fini_array .fini_array.*)) + __dtor_end = .; + } + + /* Start page aligned read-write memory */ +#ifdef CFG_CORE_RWDATA_NOEXEC + . = ALIGN(SMALL_PAGE_SIZE); +#endif + __flatmap_ro_size = . - __flatmap_ro_start; + __flatmap_rw_start = .; + + .data : ALIGN(8) { + /* writable data */ + __data_start_rom = .; + /* in one segment binaries, the rom data address is on top + of the ram data address */ + __data_start = .; + *(.data .data.* .gnu.linkonce.d.*) + . = ALIGN(8); + /* + * To allow the linker relax accesses to global symbols, + * those need to be within imm12 (signed 12-bit) offsets + * from __global_pointer$. + */ + PROVIDE(__global_pointer$ = . + 0x800 ); + } + + /* uninitialized data */ + .bss : { + __data_end = .; + __bss_start = .; + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + __bss_end = .; + } + + .heap1 (NOLOAD) : { + /* + * We're keeping track of the padding added before the + * .nozi section so we can do something useful with + * this otherwise wasted memory. + */ + __heap1_start = .; + . += CFG_CORE_HEAP_SIZE; + . = ALIGN(4 * 1024); + __heap1_end = .; + } + /* + * Uninitialized data that shouldn't be zero initialized at + * runtime. + */ + .nozi (NOLOAD) : { + __nozi_start = .; + KEEP(*(.nozi .nozi.*)) + . = ALIGN(16); + __nozi_end = .; + __nozi_stack_start = .; + KEEP(*(.nozi_stack .nozi_stack.*)) + . = ALIGN(8); + __nozi_stack_end = .; + } + +#ifdef CFG_CORE_SANITIZE_KADDRESS + . = TEE_RAM_START + (TEE_RAM_VA_SIZE * 8) / 9 - 8; + . = ALIGN(8); + .asan_shadow : { + __asan_shadow_start = .; + . += TEE_RAM_VA_SIZE / 9; + __asan_shadow_end = .; + __asan_shadow_size = __asan_shadow_end - __asan_shadow_start; + } +#endif /*CFG_CORE_SANITIZE_KADDRESS*/ + + __end = .; + __init_size = __data_end - TEE_LOAD_ADDR; + + /* + * Guard against moving the location counter backwards in the assignment + * below. + */ + ASSERT(. <= (TEE_RAM_START + TEE_RAM_VA_SIZE), + "TEE_RAM_VA_SIZE is too small") + . = TEE_RAM_START + TEE_RAM_VA_SIZE; + + _end_of_ram = .; + + __flatmap_rw_size = _end_of_ram - __flatmap_rw_start; + __get_tee_init_end = .; + + /* + * These regions will not become a normal part of the dumped + * binary, instead some are interpreted by the dump script and + * converted into suitable format for OP-TEE itself to use. + */ + .dynamic : { *(.dynamic) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + + .rel : { + *(.rel.*) + } + .rela : { + *(.rela.*) + } +#ifndef CFG_CORE_ASLR + ASSERT(SIZEOF(.rel) == 0, "Relocation entries not expected") + ASSERT(SIZEOF(.rela) == 0, "Relocation entries not expected") +#endif + + /DISCARD/ : { + /* Strip unnecessary stuff */ + *(.comment .note .eh_frame .interp) + /* Strip meta variables */ + *(__keep_meta_vars*) + } + +} + +/* Unpaged read-only memories */ +__vcore_unpg_rx_start = __flatmap_rx_start; +__vcore_unpg_ro_start = __flatmap_ro_start; +#ifdef CFG_CORE_RODATA_NOEXEC +__vcore_unpg_rx_size = __flatmap_rx_size; +__vcore_unpg_ro_size = __flatmap_ro_size; +#else +__vcore_unpg_rx_size = __flatmap_rx_size + __flatmap_ro_size; +__vcore_unpg_ro_size = 0; +#endif +__vcore_unpg_rx_end = __vcore_unpg_rx_start + __vcore_unpg_rx_size; +__vcore_unpg_ro_end = __vcore_unpg_ro_start + __vcore_unpg_ro_size; + +/* Unpaged read-write memory */ +__vcore_unpg_rw_start = __flatmap_rw_start; +__vcore_unpg_rw_size = __flatmap_rw_size; +__vcore_unpg_rw_end = __vcore_unpg_rw_start + __vcore_unpg_rw_size; + +#ifdef CFG_CORE_SANITIZE_KADDRESS +__asan_map_start = (__asan_shadow_start / SMALL_PAGE_SIZE) * + SMALL_PAGE_SIZE; +__asan_map_end = ((__asan_shadow_end - 1) / SMALL_PAGE_SIZE) * + SMALL_PAGE_SIZE + SMALL_PAGE_SIZE; +__asan_map_size = __asan_map_end - __asan_map_start; +#endif /*CFG_CORE_SANITIZE_KADDRESS*/ diff --git a/optee/optee_os/core/arch/riscv/kernel/link.mk b/optee/optee_os/core/arch/riscv/kernel/link.mk new file mode 100644 index 0000000..3d1000d --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/link.mk @@ -0,0 +1,143 @@ +link-out-dir = $(out-dir)/core + +link-script = $(if $(wildcard $(platform-dir)/kern.ld.S), \ + $(platform-dir)/kern.ld.S, \ + $(arch-dir)/kernel/kern.ld.S) +link-script-pp = $(link-out-dir)/kern.ld +link-script-dep = $(link-out-dir)/.kern.ld.d + +link-ldflags-common += $(call ld-option,--no-warn-rwx-segments) + +link-ldflags = $(LDFLAGS) +ifeq ($(CFG_CORE_ASLR),y) +link-ldflags += -pie -Bsymbolic -z norelro $(ldflag-apply-dynamic-relocs) +endif + +link-ldflags += -T $(link-script-pp) -Map=$(link-out-dir)/tee.map +link-ldflags += --sort-section=alignment +link-ldflags += --fatal-warnings +link-ldflags += --gc-sections +link-ldflags += $(link-ldflags-common) + +link-ldadd = $(LDADD) +link-ldadd += $(ldflags-external) +link-ldadd += $(libdeps) +link-objs := $(objs) + +ldargs-tee.elf := $(link-ldflags) $(link-objs) $(link-out-dir)/version.o \ + $(link-ldadd) $(libgcccore) + +link-script-cppflags := \ + $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \ + $(nostdinccore) $(CPPFLAGS) \ + $(addprefix -I,$(incdirscore) $(link-out-dir)) \ + $(cppflagscore)) + +ldargs-all_objs := -T $(link-script) --no-check-sections \ + $(link-ldflags-common) \ + $(link-objs) $(link-ldadd) $(libgcccore) +cleanfiles += $(link-out-dir)/all_objs.o +$(link-out-dir)/all_objs.o: $(objs) $(libdeps) $(MAKEFILE_LIST) + @$(cmd-echo-silent) ' LD $@' + $(q)$(LDcore) $(ldargs-all_objs) -o $@ + +-include $(link-script-dep) + +link-script-extra-deps += $(conf-file) +cleanfiles += $(link-script-pp) $(link-script-dep) +$(link-script-pp): $(link-script) $(link-script-extra-deps) + @$(cmd-echo-silent) ' CPP $@' + @mkdir -p $(dir $@) + $(q)$(CPPcore) -P -MT $@ -MD -MF $(link-script-dep) \ + $(link-script-cppflags) $< -o $@ + +define update-buildcount + @$(cmd-echo-silent) ' UPD $(1)' + $(q)if [ ! -f $(1) ]; then \ + mkdir -p $(dir $(1)); \ + echo 1 >$(1); \ + else \ + expr 0`cat $(1)` + 1 >$(1); \ + fi +endef + +# filter-out to workaround objdump warning +version-o-cflags = $(filter-out -g3,$(core-platform-cflags) \ + $(platform-cflags) $(cflagscore)) +# SOURCE_DATE_EPOCH defined for reproducible builds +ifneq ($(SOURCE_DATE_EPOCH),) +date-opts = -d @$(SOURCE_DATE_EPOCH) +endif +DATE_STR = `LC_ALL=C date -u $(date-opts)` +BUILD_COUNT_STR = `cat $(link-out-dir)/.buildcount` +CORE_CC_VERSION = `$(CCcore) -v 2>&1 | grep "version " | sed 's/ *$$//'` +define gen-version-o + $(call update-buildcount,$(link-out-dir)/.buildcount) + @$(cmd-echo-silent) ' GEN $(link-out-dir)/version.o' + $(q)echo -e "const char core_v_str[] =" \ + "\"$(TEE_IMPL_VERSION) \"" \ + "\"($(CORE_CC_VERSION)) \"" \ + "\"#$(BUILD_COUNT_STR) \"" \ + "\"$(DATE_STR) \"" \ + "\"$(CFG_KERN_LINKER_ARCH)\";\n" \ + | $(CCcore) $(version-o-cflags) \ + -xc - -c -o $(link-out-dir)/version.o +endef + +$(link-out-dir)/version.o: + $(call gen-version-o) + +-include $(link-out-dir)/.tee.elf.cmd +define check-link-objs +$(if $(strip $(filter-out $(link-objs), $(old-link-objs)) + $(filter-out $(old-link-objs), $(link-objs))), FORCE_LINK := FORCE) +endef +#$(eval $(call check-link-objs)) + +all: $(link-out-dir)/tee.elf +cleanfiles += $(link-out-dir)/tee.elf $(link-out-dir)/tee.map +cleanfiles += $(link-out-dir)/version.o +cleanfiles += $(link-out-dir)/.buildcount +cleanfiles += $(link-out-dir)/.tee.elf.cmd +$(link-out-dir)/tee.elf: $(link-objs) $(libdeps) $(link-script-pp) $(FORCE_LINK) + $(call gen-version-o) + @echo "old-link-objs := $(link-objs)" >$(link-out-dir)/.tee.elf.cmd + @$(cmd-echo-silent) ' LD $@' + $(q)$(LDcore) $(ldargs-tee.elf) -o $@ + +all: $(link-out-dir)/tee.dmp +cleanfiles += $(link-out-dir)/tee.dmp +$(link-out-dir)/tee.dmp: $(link-out-dir)/tee.elf + @$(cmd-echo-silent) ' OBJDUMP $@' + $(q)$(OBJDUMPcore) -l -x -d $< > $@ + +all: $(link-out-dir)/tee.bin +cleanfiles += $(link-out-dir)/tee.bin +$(link-out-dir)/tee.bin: $(link-out-dir)/tee.elf + @$(cmd-echo-silent) ' GEN $@' + $(q)$(OBJCOPYcore) -O binary $< $@ + +all: $(link-out-dir)/tee.symb_sizes +cleanfiles += $(link-out-dir)/tee.symb_sizes +$(link-out-dir)/tee.symb_sizes: $(link-out-dir)/tee.elf + @$(cmd-echo-silent) ' GEN $@' + $(q)$(NMcore) --print-size --reverse-sort --size-sort $< > $@ + +cleanfiles += $(link-out-dir)/tee.mem_usage +ifneq ($(filter mem_usage,$(MAKECMDGOALS)),) +mem_usage: $(link-out-dir)/tee.mem_usage + +$(link-out-dir)/tee.mem_usage: $(link-out-dir)/tee.elf + @$(cmd-echo-silent) ' GEN $@' + $(q)$(PYTHON3) ./scripts/mem_usage.py $< > $@ +endif + +cleanfiles += $(link-out-dir)/tee-raw.bin +$(link-out-dir)/tee-raw.bin: $(link-out-dir)/tee.elf + @$(cmd-echo-silent) ' GEN $@' + $(q)$(OBJCOPYcore) -O binary $< $@ + +cleanfiles += $(link-out-dir)/tee.srec +$(link-out-dir)/tee.srec: $(link-out-dir)/tee-raw.bin + @$(cmd-echo-silent) ' SREC $@' + $(q)$(OBJCOPYcore) -I binary -O srec $(SRECFLAGS) $< $@ diff --git a/optee/optee_os/core/arch/riscv/kernel/sbi.c b/optee/optee_os/core/arch/riscv/kernel/sbi.c new file mode 100644 index 0000000..8d82040 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/sbi.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ + +#include +#include + +struct sbiret { + long error; + long value; +}; + +#define _sbi_ecall(ext, fid, arg0, arg1, arg2, arg3, arg4, arg5, ...) ({ \ + register unsigned long a0 asm("a0") = (unsigned long)arg0; \ + register unsigned long a1 asm("a1") = (unsigned long)arg1; \ + register unsigned long a2 asm("a2") = (unsigned long)arg2; \ + register unsigned long a3 asm("a3") = (unsigned long)arg3; \ + register unsigned long a4 asm("a4") = (unsigned long)arg4; \ + register unsigned long a5 asm("a5") = (unsigned long)arg5; \ + register unsigned long a6 asm("a6") = (unsigned long)fid; \ + register unsigned long a7 asm("a7") = (unsigned long)ext; \ + asm volatile ("ecall" \ + : "+r" (a0), "+r" (a1) \ + : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r"(a6), "r"(a7) \ + : "memory"); \ + (struct sbiret){ .error = a0, .value = a1 }; \ +}) + +#define sbi_ecall(...) _sbi_ecall(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0) + +void sbi_console_putchar(int ch) +{ + sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, (unsigned long)ch); +} + +int sbi_boot_hart(uint32_t hart_id, paddr_t start_addr, unsigned long arg) +{ + struct sbiret ret; + + ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START, hart_id, start_addr, arg); + + return ret.error; +} diff --git a/optee/optee_os/core/arch/riscv/kernel/sbi_console.c b/optee/optee_os/core/arch/riscv/kernel/sbi_console.c new file mode 100644 index 0000000..18c628d --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/sbi_console.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_RISCV_SBI_CONSOLE + +struct sbi_console_data { + struct serial_chip chip; +}; + +static struct sbi_console_data console_data __nex_bss; +static unsigned int sbi_console_global_lock __nex_bss = SPINLOCK_UNLOCK; + +static void sbi_console_lock_global(void) +{ + cpu_spin_lock(&sbi_console_global_lock); +} + +static void sbi_console_unlock_global(void) +{ + cpu_spin_unlock(&sbi_console_global_lock); +} + +static void sbi_console_flush(struct serial_chip *chip __unused) +{ +} + +static void sbi_console_putc(struct serial_chip *chip __unused, + int ch) +{ + sbi_console_lock_global(); + sbi_console_putchar(ch); + sbi_console_unlock_global(); +} + +static const struct serial_ops sbi_console_ops = { + .flush = sbi_console_flush, + .putc = sbi_console_putc, +}; + +static void sbi_console_init(struct sbi_console_data *pd) +{ + pd->chip.ops = &sbi_console_ops; +} + +void console_init(void) +{ + sbi_console_init(&console_data); + register_serial_console(&console_data.chip); +} + +#endif /*CFG_RISCV_SBI_CONSOLE*/ + diff --git a/optee/optee_os/core/arch/riscv/kernel/spinlock.S b/optee/optee_os/core/arch/riscv/kernel/spinlock.S new file mode 100644 index 0000000..83aa4fd --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/spinlock.S @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ + +#include +#include +#include + +/* void __cpu_spin_lock(unsigned int *lock) */ +FUNC __cpu_spin_lock , : + addi sp, sp, -(RISCV_XLEN_BYTES * 2) + STR s0, 0(sp) + STR ra, 8(sp) + mv s0, a0 +1: + mv a0, s0 + jal __cpu_spin_trylock + addiw a0, a0, 0 + bnez a0, 1b + LDR ra, 8(sp) + LDR s0, 0(sp) + addi sp, sp, (RISCV_XLEN_BYTES * 2) + ret +END_FUNC __cpu_spin_lock + + +/* void __cpu_spin_unlock(unsigned int *lock)*/ +FUNC __cpu_spin_unlock , : + fence rw, w + amoswap.w x0, x0, 0(a0) + ret +END_FUNC __cpu_spin_unlock + +/* unsigned int __cpu_spin_trylock(unsigned int *lock) */ +FUNC __cpu_spin_trylock , : + li t0, SPINLOCK_LOCK + amoswap.w a0, t0, 0(a0) + fence r,rw + ret +END_FUNC __cpu_spin_trylock + diff --git a/optee/optee_os/core/arch/riscv/kernel/sub.mk b/optee/optee_os/core/arch/riscv/kernel/sub.mk new file mode 100644 index 0000000..79a3b3f --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/sub.mk @@ -0,0 +1,14 @@ +srcs-y += spinlock.S +srcs-y += cache_helpers_rv.S +srcs-y += idle.c +srcs-$(CFG_RISCV_TIME_SOURCE_RDTIME) += tee_time_rdtime.c +srcs-$(CFG_RISCV_SBI) += sbi.c +srcs-$(CFG_RISCV_SBI_CONSOLE) += sbi_console.c +srcs-y += boot.c +srcs-y += entry.S +srcs-y += abort.c +srcs-y += thread_rv.S +srcs-y += thread_arch.c +srcs-y += arch_scall_rv.S +srcs-y += arch_scall.c +asm-defines-y += asm-defines.c diff --git a/optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c b/optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c new file mode 100644 index 0000000..f7b382c --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/tee_time_rdtime.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#include + +static TEE_Result riscv_get_sys_time(TEE_Time *time) +{ + uint64_t tm = read_time(); + uint64_t rate = CFG_RISCV_MTIME_RATE; + + time->seconds = tm / rate; + time->millis = (tm % rate) / (rate / TEE_TIME_MILLIS_BASE); + + return TEE_SUCCESS; +} + +static const struct time_source riscv_time_source_rdtime = { + .name = "risc-v rdtime", + .protection_level = 1000, + .get_sys_time = riscv_get_sys_time, +}; + +REGISTER_TIME_SOURCE(riscv_time_source_rdtime) diff --git a/optee/optee_os/core/arch/riscv/kernel/thread_arch.c b/optee/optee_os/core/arch/riscv/kernel/thread_arch.c new file mode 100644 index 0000000..f9b63c0 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/thread_arch.c @@ -0,0 +1,613 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + * Copyright (c) 2016-2022, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020-2021, Arm Limited + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +uint32_t __nostackcheck thread_get_exceptions(void) +{ + return read_csr(CSR_XIE) & THREAD_EXCP_ALL; +} + +void __nostackcheck thread_set_exceptions(uint32_t exceptions) +{ + /* Foreign interrupts must not be unmasked while holding a spinlock */ + if (!(exceptions & THREAD_EXCP_FOREIGN_INTR)) + assert_have_no_spinlock(); + + barrier(); + write_csr(CSR_XIE, exceptions); + barrier(); +} + +uint32_t __nostackcheck thread_mask_exceptions(uint32_t exceptions) +{ + uint32_t state = thread_get_exceptions(); + + thread_set_exceptions(state | (exceptions & THREAD_EXCP_ALL)); + return state; +} + +void __nostackcheck thread_unmask_exceptions(uint32_t state) +{ + thread_set_exceptions(state & THREAD_EXCP_ALL); +} + +static void thread_lazy_save_ns_vfp(void) +{ + static_assert(!IS_ENABLED(CFG_WITH_VFP)); +} + +static void thread_lazy_restore_ns_vfp(void) +{ + static_assert(!IS_ENABLED(CFG_WITH_VFP)); +} + +static void setup_unwind_user_mode(struct thread_scall_regs *regs) +{ + regs->ra = (uintptr_t)thread_unwind_user_mode; + regs->status = read_csr(CSR_XSTATUS); + regs->sp = thread_get_saved_thread_sp(); +} + +static void thread_unhandled_trap(struct thread_trap_regs *regs __unused, + unsigned long cause __unused) +{ + DMSG("Unhandled trap xepc:0x%016lx xcause:0x%016lx xtval:0x%016lx", + read_csr(CSR_XEPC), read_csr(CSR_XCAUSE), read_csr(CSR_XTVAL)); + panic(); +} + +void thread_scall_handler(struct thread_scall_regs *regs) +{ + struct ts_session *sess = NULL; + uint32_t state = 0; + + /* Enable native interrupts */ + state = thread_get_exceptions(); + thread_unmask_exceptions(state & ~THREAD_EXCP_NATIVE_INTR); + + thread_user_save_vfp(); + + sess = ts_get_current_session(); + + /* Restore foreign interrupts which are disabled on exception entry */ + thread_restore_foreign_intr(); + + assert(sess && sess->handle_scall); + + if (!sess->handle_scall(regs)) { + setup_unwind_user_mode(regs); + thread_exit_user_mode(regs->a0, regs->a1, regs->a2, + regs->a3, regs->sp, regs->ra, + regs->status); + } +} + +static void copy_scall_to_trap(struct thread_scall_regs *scall_regs, + struct thread_trap_regs *trap_regs) +{ + trap_regs->a0 = scall_regs->a0; + trap_regs->a1 = scall_regs->a1; + trap_regs->a2 = scall_regs->a2; + trap_regs->a3 = scall_regs->a3; + trap_regs->a4 = scall_regs->a4; + trap_regs->a5 = scall_regs->a5; + trap_regs->a6 = scall_regs->a6; + trap_regs->a7 = scall_regs->a7; + trap_regs->t0 = scall_regs->t0; + trap_regs->t1 = scall_regs->t1; +} + +static void copy_trap_to_scall(struct thread_trap_regs *trap_regs, + struct thread_scall_regs *scall_regs) +{ + *scall_regs = (struct thread_scall_regs) { + .status = trap_regs->status, + .ra = trap_regs->ra, + .a0 = trap_regs->a0, + .a1 = trap_regs->a1, + .a2 = trap_regs->a2, + .a3 = trap_regs->a3, + .a4 = trap_regs->a4, + .a5 = trap_regs->a5, + .a6 = trap_regs->a6, + .a7 = trap_regs->a7, + .t0 = trap_regs->t0, + .t1 = trap_regs->t1, + }; +} + +static void thread_user_ecall_handler(struct thread_trap_regs *trap_regs) +{ + struct thread_scall_regs scall_regs; + struct thread_core_local *l = thread_get_core_local(); + int ct = l->curr_thread; + + copy_trap_to_scall(trap_regs, &scall_regs); + thread_scall_handler(&scall_regs); + copy_scall_to_trap(&scall_regs, trap_regs); + /* + * Save kernel sp we'll had at the beginning of this function. + * This is when this TA has called another TA because + * __thread_enter_user_mode() also saves the stack pointer in this + * field. + */ + threads[ct].kern_sp = (unsigned long)(trap_regs + 1); + /* + * We are returning to U-Mode, on return, the program counter + * is set to xsepc (pc=xepc), we add 4 (size of an instruction) + * to continue to next instruction. + */ + trap_regs->epc += 4; +} + +static void copy_trap_to_abort(struct thread_trap_regs *trap_regs, + struct thread_abort_regs *abort_regs) +{ + *abort_regs = (struct thread_abort_regs) { + .status = trap_regs->status, + .ra = trap_regs->ra, + .sp = trap_regs->sp, + .gp = trap_regs->gp, + .tp = trap_regs->tp, + .t0 = trap_regs->t0, + .t1 = trap_regs->t1, + .t2 = trap_regs->t2, + .s0 = trap_regs->s0, + .s1 = trap_regs->s1, + .a0 = trap_regs->a0, + .a1 = trap_regs->a1, + .a2 = trap_regs->a2, + .a3 = trap_regs->a3, + .a4 = trap_regs->a4, + .a5 = trap_regs->a5, + .a6 = trap_regs->a6, + .a7 = trap_regs->a7, + .s2 = trap_regs->s2, + .s3 = trap_regs->s3, + .s4 = trap_regs->s4, + .s5 = trap_regs->s5, + .s6 = trap_regs->s6, + .s7 = trap_regs->s7, + .s8 = trap_regs->s8, + .s9 = trap_regs->s9, + .s10 = trap_regs->s10, + .s11 = trap_regs->s11, + .t3 = trap_regs->t3, + .t4 = trap_regs->t4, + .t5 = trap_regs->t5, + .t6 = trap_regs->t6, + }; +} + +static void thread_abort_handler(struct thread_trap_regs *trap_regs, + unsigned long cause) +{ + struct thread_abort_regs abort_regs = { }; + + assert(cause == read_csr(CSR_XCAUSE)); + copy_trap_to_abort(trap_regs, &abort_regs); + abort_regs.cause = read_csr(CSR_XCAUSE); + abort_regs.epc = read_csr(CSR_XEPC); + abort_regs.tval = read_csr(CSR_XTVAL); + abort_regs.satp = read_csr(CSR_SATP); + abort_handler(cause, &abort_regs); +} + +static void thread_exception_handler(unsigned long cause, + struct thread_trap_regs *regs) +{ + switch (cause) { + case CAUSE_USER_ECALL: + thread_user_ecall_handler(regs); + break; + default: + thread_abort_handler(regs, cause); + break; + } +} + +static void thread_irq_handler(void) +{ + itr_core_handler(); +} + +static void thread_interrupt_handler(unsigned long cause, + struct thread_trap_regs *regs) +{ + switch (cause & LONG_MAX) { + case IRQ_XTIMER: + clear_csr(CSR_XIE, CSR_XIE_TIE); + break; + case IRQ_XSOFT: + thread_unhandled_trap(regs, cause); + break; + case IRQ_XEXT: + thread_irq_handler(); + break; + default: + thread_unhandled_trap(regs, cause); + } +} + +void thread_trap_handler(long cause, unsigned long epc __unused, + struct thread_trap_regs *regs, + bool user __maybe_unused) +{ + /* + * The Interrupt bit (XLEN-1) in the cause register is set + * if the trap was caused by an interrupt. + */ + if (cause < 0) + thread_interrupt_handler(cause, regs); + /* + * Otherwise, cause is never written by the implementation, + * though it may be explicitly written by software. + */ + else + thread_exception_handler(cause, regs); +} + +static void init_regs(struct thread_ctx *thread, uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6, uint32_t a7, void *pc) +{ + thread->regs.ra = (uintptr_t)pc; + + /* Set up xstatus */ + thread->regs.status = read_csr(CSR_XSTATUS); + + /* Reinitialize stack pointer */ + thread->regs.sp = thread->stack_va_end; + + /* + * Copy arguments into context. This will make the + * arguments appear in a0-a7 when thread is started. + */ + thread->regs.a0 = a0; + thread->regs.a1 = a1; + thread->regs.a2 = a2; + thread->regs.a3 = a3; + thread->regs.a4 = a4; + thread->regs.a5 = a5; + thread->regs.a6 = a6; + thread->regs.a7 = a7; +} + +static void __thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, + uint32_t a3, uint32_t a4, uint32_t a5, + uint32_t a6, uint32_t a7, + void *pc) +{ + struct thread_core_local *l = thread_get_core_local(); + bool found_thread = false; + size_t n = 0; + + assert(l->curr_thread == THREAD_ID_INVALID); + + thread_lock_global(); + + for (n = 0; n < CFG_NUM_THREADS; n++) { + if (threads[n].state == THREAD_STATE_FREE) { + threads[n].state = THREAD_STATE_ACTIVE; + found_thread = true; + break; + } + } + + thread_unlock_global(); + + if (!found_thread) + return; + + l->curr_thread = n; + + threads[n].flags = 0; + init_regs(threads + n, a0, a1, a2, a3, a4, a5, a6, a7, pc); + + thread_lazy_save_ns_vfp(); + + l->flags &= ~THREAD_CLF_TMP; + + thread_resume(&threads[n].regs); + /*NOTREACHED*/ + panic(); +} + +void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, + uint32_t a4, uint32_t a5) +{ + __thread_alloc_and_run(a0, a1, a2, a3, a4, a5, 0, 0, + thread_std_smc_entry); +} + +static void copy_a0_to_a3(struct thread_ctx_regs *regs, uint32_t a0, + uint32_t a1, uint32_t a2, uint32_t a3) +{ + regs->a0 = a0; + regs->a1 = a1; + regs->a2 = a2; + regs->a3 = a3; +} + +static bool is_from_user(unsigned long status) +{ + return status & CSR_XSTATUS_SPP; +} + +#ifdef CFG_SYSCALL_FTRACE +static void __noprof ftrace_suspend(void) +{ + struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); + + if (s && s->fbuf) + s->fbuf->syscall_trace_suspended = true; +} + +static void __noprof ftrace_resume(void) +{ + struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); + + if (s && s->fbuf) + s->fbuf->syscall_trace_suspended = false; +} +#else +static void __maybe_unused __noprof ftrace_suspend(void) +{ +} + +static void __noprof ftrace_resume(void) +{ +} +#endif + +static bool is_user_mode(struct thread_ctx_regs *regs) +{ + return is_from_user((uint32_t)regs->status); +} + +vaddr_t thread_get_saved_thread_sp(void) +{ + struct thread_core_local *l = thread_get_core_local(); + int ct = l->curr_thread; + + assert(ct != THREAD_ID_INVALID); + return threads[ct].kern_sp; +} + +void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) +{ + size_t n = thread_id; + struct thread_core_local *l = thread_get_core_local(); + bool found_thread = false; + + assert(l->curr_thread == THREAD_ID_INVALID); + + thread_lock_global(); + + if (n < CFG_NUM_THREADS && threads[n].state == THREAD_STATE_SUSPENDED) { + threads[n].state = THREAD_STATE_ACTIVE; + found_thread = true; + } + + thread_unlock_global(); + + if (!found_thread) + return; + + l->curr_thread = n; + + if (threads[n].have_user_map) { + core_mmu_set_user_map(&threads[n].user_map); + if (threads[n].flags & THREAD_FLAGS_EXIT_ON_FOREIGN_INTR) + tee_ta_ftrace_update_times_resume(); + } + + if (is_user_mode(&threads[n].regs)) + tee_ta_update_session_utime_resume(); + + /* + * Return from RPC to request service of a foreign interrupt must not + * get parameters from non-secure world. + */ + if (threads[n].flags & THREAD_FLAGS_COPY_ARGS_ON_RETURN) { + copy_a0_to_a3(&threads[n].regs, a0, a1, a2, a3); + threads[n].flags &= ~THREAD_FLAGS_COPY_ARGS_ON_RETURN; + } + + thread_lazy_save_ns_vfp(); + + if (threads[n].have_user_map) + ftrace_resume(); + + l->flags &= ~THREAD_CLF_TMP; + thread_resume(&threads[n].regs); + /*NOTREACHED*/ + panic(); +} + +void thread_state_free(void) +{ + struct thread_core_local *l = thread_get_core_local(); + int ct = l->curr_thread; + + assert(ct != THREAD_ID_INVALID); + + thread_lazy_restore_ns_vfp(); + + thread_lock_global(); + + assert(threads[ct].state == THREAD_STATE_ACTIVE); + threads[ct].state = THREAD_STATE_FREE; + threads[ct].flags = 0; + l->curr_thread = THREAD_ID_INVALID; + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + virt_unset_guest(); + thread_unlock_global(); +} + +int thread_state_suspend(uint32_t flags, uint32_t status, vaddr_t pc) +{ + struct thread_core_local *l = thread_get_core_local(); + int ct = l->curr_thread; + + assert(ct != THREAD_ID_INVALID); + + if (core_mmu_user_mapping_is_active()) + ftrace_suspend(); + + thread_check_canaries(); + + if (is_from_user(status)) { + thread_user_save_vfp(); + tee_ta_update_session_utime_suspend(); + tee_ta_gprof_sample_pc(pc); + } + thread_lazy_restore_ns_vfp(); + + thread_lock_global(); + + assert(threads[ct].state == THREAD_STATE_ACTIVE); + threads[ct].flags |= flags; + threads[ct].regs.status = status; + threads[ct].regs.ra = pc; + threads[ct].state = THREAD_STATE_SUSPENDED; + + threads[ct].have_user_map = core_mmu_user_mapping_is_active(); + if (threads[ct].have_user_map) { + if (threads[ct].flags & THREAD_FLAGS_EXIT_ON_FOREIGN_INTR) + tee_ta_ftrace_update_times_suspend(); + core_mmu_get_user_map(&threads[ct].user_map); + core_mmu_set_user_map(NULL); + } + + l->curr_thread = THREAD_ID_INVALID; + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + virt_unset_guest(); + + thread_unlock_global(); + + return ct; +} + +bool thread_init_stack(uint32_t thread_id, vaddr_t sp) +{ + if (thread_id >= CFG_NUM_THREADS) + return false; + threads[thread_id].stack_va_end = sp; + return true; +} + +static void init_user_kcode(void) +{ +} + +void thread_init_primary(void) +{ + /* Initialize canaries around the stacks */ + thread_init_canaries(); + + init_user_kcode(); +} + +static vaddr_t get_trap_vect(void) +{ + return (vaddr_t)thread_trap_vect; +} + +void thread_init_tvec(void) +{ + unsigned long tvec = (unsigned long)get_trap_vect(); + + static_assert(sizeof(struct thread_trap_regs) % 16 == 0); + write_csr(CSR_XTVEC, tvec); + assert(read_csr(CSR_XTVEC) == tvec); +} + +void thread_init_per_cpu(void) +{ + thread_init_tvec(); + /* + * We may receive traps from now, therefore, zeroize xSCRATCH such + * that thread_trap_vect() can distinguish between user traps + * and kernel traps. + */ + write_csr(CSR_XSCRATCH, 0); + /* Allow access to user pages */ + set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); +} + +static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0, + unsigned long a1, unsigned long a2, unsigned long a3, + unsigned long user_sp, unsigned long entry_func, + uint32_t status, + struct thread_pauth_keys *keys __unused) +{ + *regs = (struct thread_ctx_regs){ + .a0 = a0, + .a1 = a1, + .a2 = a2, + .a3 = a3, + .sp = user_sp, + .ra = entry_func, + .status = status + }; +} + +uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long user_sp, + unsigned long entry_func, + bool is_32bit __unused, + uint32_t *exit_status0, + uint32_t *exit_status1) +{ + uint32_t status = 0; + uint32_t exceptions = 0; + uint32_t rc = 0; + struct thread_ctx_regs *regs = NULL; + + tee_ta_update_session_utime_resume(); + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + regs = thread_get_ctx_regs(); + status = CSR_XSTATUS_SUM | CSR_XSTATUS_PIE; + set_field_u64(status, CSR_XSTATUS_SPP, PRV_U); + set_ctx_regs(regs, a0, a1, a2, a3, user_sp, entry_func, status, NULL); + rc = __thread_enter_user_mode(regs, exit_status0, exit_status1); + thread_unmask_exceptions(exceptions); + + return rc; +} diff --git a/optee/optee_os/core/arch/riscv/kernel/thread_rv.S b/optee/optee_os/core/arch/riscv/kernel/thread_rv.S new file mode 100644 index 0000000..bd368f1 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/kernel/thread_rv.S @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +.macro get_thread_ctx res, tmp0 + lw \tmp0, THREAD_CORE_LOCAL_CURR_THREAD(tp) + la \res, threads +1: + beqz \tmp0, 2f + addi \res, \res, THREAD_CTX_SIZE + addi \tmp0, \tmp0, -1 + bnez \tmp0, 1b +2: +.endm + +.macro save_regs, mode + addi sp, sp, -THREAD_TRAP_REGS_SIZE +.if \mode == TRAP_MODE_USER + + /* Save user thread pointer and load kernel thread pointer */ + store_xregs sp, THREAD_TRAP_REG_TP, REG_TP + load_xregs sp, (THREAD_TRAP_REGS_SIZE - RISCV_XLEN_BYTES), REG_TP + + store_xregs sp, THREAD_TRAP_REG_GP, REG_GP + + /* + * Set the scratch register to 0 such in case of a recursive + * exception thread_trap_vect() knows that it is emitted from kernel. + */ + csrrw gp, CSR_XSCRATCH, zero + store_xregs sp, THREAD_TRAP_REG_SP, REG_GP +.option push +.option norelax + la gp, __global_pointer$ +.option pop +.endif + store_xregs sp, THREAD_TRAP_REG_T3, REG_T3, REG_T6 + store_xregs sp, THREAD_TRAP_REG_T0, REG_T0, REG_T2 + store_xregs sp, THREAD_TRAP_REG_A0, REG_A0, REG_A7 + store_xregs sp, THREAD_TRAP_REG_RA, REG_RA + + csrr t0, CSR_XSTATUS + store_xregs sp, THREAD_TRAP_REG_STATUS, REG_T0 + + csrr a0, CSR_XCAUSE + csrr a1, CSR_XEPC + + store_xregs sp, THREAD_TRAP_REG_EPC, REG_A1 + + mv a2, sp + + /* a0 = cause + * a1 = epc + * a2 = sp + * a3 = user + * thread_trap_handler(cause, epc, sp, user) + */ +.endm + +.macro restore_regs, mode + load_xregs sp, THREAD_TRAP_REG_EPC, REG_T0 + csrw CSR_XEPC, t0 + + load_xregs sp, THREAD_TRAP_REG_STATUS, REG_T0 + csrw CSR_XSTATUS, t0 + + load_xregs sp, THREAD_TRAP_REG_RA, REG_RA + load_xregs sp, THREAD_TRAP_REG_A0, REG_A0, REG_A7 + load_xregs sp, THREAD_TRAP_REG_T0, REG_T0, REG_T2 + load_xregs sp, THREAD_TRAP_REG_T3, REG_T3, REG_T6 + +.if \mode == TRAP_MODE_USER + addi gp, sp, THREAD_TRAP_REGS_SIZE + + store_xregs gp, REGOFF(-1), REG_TP + csrw CSR_XSCRATCH, gp + + load_xregs sp, THREAD_TRAP_REG_TP, REG_TP + load_xregs sp, THREAD_TRAP_REG_GP, REG_GP + load_xregs sp, THREAD_TRAP_REG_SP, REG_SP + +.else + addi sp, sp, THREAD_TRAP_REGS_SIZE +.endif +.endm + +/* size_t __get_core_pos(void); */ +FUNC __get_core_pos , : , .identity_map + lw a0, THREAD_CORE_LOCAL_HART_ID(tp) + ret +END_FUNC __get_core_pos + +FUNC thread_trap_vect , : + csrrw sp, CSR_XSCRATCH, sp + bnez sp, 0f + csrrw sp, CSR_XSCRATCH, sp + j trap_from_kernel +0: + j trap_from_user +thread_trap_vect_end: +END_FUNC thread_trap_vect + +LOCAL_FUNC trap_from_kernel, : + save_regs TRAP_MODE_KERNEL + li a3, 0 + jal thread_trap_handler + restore_regs TRAP_MODE_KERNEL + XRET +END_FUNC trap_from_kernel + +LOCAL_FUNC trap_from_user, : + save_regs TRAP_MODE_USER + li a3, 1 + jal thread_trap_handler + restore_regs TRAP_MODE_USER + XRET +END_FUNC trap_from_user + +/* + * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, + * uint32_t exit_status1); + * See description in thread.h + */ +FUNC thread_unwind_user_mode , : + + /* Store the exit status */ + load_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, REG_A3, REG_A5 + sw a1, (a4) + sw a2, (a5) + + /* Save user callee regs */ + store_xregs a3, THREAD_CTX_REG_S0, REG_S0, REG_S1 + store_xregs a3, THREAD_CTX_REG_S2, REG_S2, REG_S11 + store_xregs a3, THREAD_CTX_REG_SP, REG_SP, REG_TP + + /* Restore kernel callee regs */ + mv a1, sp + + load_xregs a1, THREAD_USER_MODE_REC_X1, REG_RA, REG_TP + load_xregs a1, THREAD_USER_MODE_REC_X8, REG_S0, REG_S1 + load_xregs a1, THREAD_USER_MODE_REC_X18, REG_S2, REG_S11 + + add sp, sp, THREAD_USER_MODE_REC_SIZE + + /* + * Zeroize xSCRATCH to indicate to thread_trap_vect() + * that we are executing in kernel. + */ + csrw CSR_XSCRATCH, zero + + /* Return from the call of thread_enter_user_mode() */ + ret +END_FUNC thread_unwind_user_mode + +/* + * void thread_exit_user_mode(unsigned long a0, unsigned long a1, + * unsigned long a2, unsigned long a3, + * unsigned long sp, unsigned long pc, + * unsigned long status); + */ +FUNC thread_exit_user_mode , : + /* Set kernel stack pointer */ + mv sp, a4 + + /* Set xSTATUS */ + csrw CSR_XSTATUS, a6 + + /* Set return address thread_unwind_user_mode() */ + mv ra, a5 + ret +END_FUNC thread_exit_user_mode + +/* + * uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, + * uint32_t *exit_status0, + * uint32_t *exit_status1); + */ +FUNC __thread_enter_user_mode , : + /* + * Create and fill in the struct thread_user_mode_rec + */ + addi sp, sp, -THREAD_USER_MODE_REC_SIZE + store_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, REG_A0, REG_A2 + store_xregs sp, THREAD_USER_MODE_REC_X1, REG_RA, REG_TP + store_xregs sp, THREAD_USER_MODE_REC_X8, REG_S0, REG_S1 + store_xregs sp, THREAD_USER_MODE_REC_X18, REG_S2, REG_S11 + + /* + * Save the kernel stack pointer in the thread context + */ + + /* Get pointer to current thread context */ + get_thread_ctx s0, s1 + + /* + * Save kernel stack pointer to ensure that + * thread_exit_user_mode() uses correct stack pointer. + */ + + store_xregs s0, THREAD_CTX_KERN_SP, REG_SP + /* + * Save kernel stack pointer in xSCRATCH to ensure that + * thread_trap_vect() uses correct stack pointer. + */ + csrw CSR_XSCRATCH, sp + + /* + * Save kernel thread pointer below of the kernel stack pointer + * to enure that thread_trap_vect() uses correct tp when traps + * come from user. + */ + store_xregs sp, REGOFF(-1), REG_TP + + /* Set user status */ + load_xregs a0, THREAD_CTX_REG_STATUS, REG_S0 + csrw CSR_XSTATUS, s0 + + /* + * Save the values for a1 and a2 in struct thread_core_local to be + * restored later just before the xRET. + */ + store_xregs tp, THREAD_CORE_LOCAL_X10, REG_A1, REG_A2 + + /* Load the rest of the general purpose registers */ + load_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP + load_xregs a0, THREAD_CTX_REG_T0, REG_T0, REG_T2 + load_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1 + load_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11 + load_xregs a0, THREAD_CTX_REG_T3, REG_T3, REG_T6 + load_xregs a0, THREAD_CTX_REG_A0, REG_A0, REG_A7 + + /* Set exception program counter */ + csrw CSR_XEPC, ra + + /* Jump into user mode */ + XRET +END_FUNC __thread_enter_user_mode + +/* + * Implement based on the transport method used to communicate between + * untrusted domain and trusted domain. It could be an SBI/ECALL-based to + * a security monitor running in M-Mode and panic or messaging-based across + * domains where we return to a messaging callback which parses and handles + * messages. + */ +LOCAL_FUNC thread_return_from_nsec_call , : + /* Implement */ + j . +END_FUNC thread_return_from_nsec_call + + +FUNC thread_std_smc_entry , : + jal __thread_std_smc_entry + + /* Save return value */ + mv s0, a0 + + /* Disable all interrupts */ + csrc CSR_XSTATUS, CSR_XSTATUS_IE + + /* Switch to temporary stack */ + jal thread_get_tmp_sp + mv sp, a0 + + /* + * We are returning from thread_alloc_and_run() + * set thread state as free + */ + jal thread_state_free + + /* Restore __thread_std_smc_entry() return value */ + mv a1, s0 + li a2, 0 + li a3, 0 + li a4, 0 + li a0, TEESMC_OPTEED_RETURN_CALL_DONE + + /* Return to untrusted domain */ + jal thread_return_from_nsec_call +END_FUNC thread_std_smc_entry + +/* void thread_resume(struct thread_ctx_regs *regs) */ +FUNC thread_resume , : + /* + * Restore all registers assuming that GP + * and TP were not changed. + */ + load_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_SP + load_xregs a0, THREAD_CTX_REG_T0, REG_T0, REG_T2 + load_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1 + load_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11 + load_xregs a0, THREAD_CTX_REG_T3, REG_T3, REG_T6 + load_xregs a0, THREAD_CTX_REG_A0, REG_A0, REG_A7 + store_xregs tp, THREAD_CORE_LOCAL_X10, REG_A0, REG_A1 + ret +END_FUNC thread_resume + +/* void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) */ +FUNC thread_rpc , : + /* Use stack for temporary storage */ + addi sp, sp, -16 + + /* Read xSTATUS */ + csrr a1, CSR_XSTATUS + + /* Save return address xSTATUS and pointer to rv */ + STR a0, REGOFF(0)(sp) + STR a1, REGOFF(1)(sp) + STR ra, REGOFF(2)(sp) + + /* Save thread state */ + jal thread_get_ctx_regs + store_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_SP + store_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1 + store_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11 + + /* Get to tmp stack */ + jal thread_get_tmp_sp + + /* Get pointer to rv */ + LDR s0, REGOFF(0)(sp) + + /* xSTATUS to restore */ + LDR a1, REGOFF(1)(sp) + /* Switch to tmp stack */ + mv sp, a0 + + /* Early load rv[] into s1-s3 */ + lw s1, 0(s0) + lw s2, 4(s0) + lw s3, 8(s0) + + li a0, THREAD_FLAGS_COPY_ARGS_ON_RETURN + la a2, .thread_rpc_return + jal thread_state_suspend + + mv a4, a0 /* thread index */ + mv a1, s1 /* rv[0] */ + mv a2, s2 /* rv[1] */ + mv a3, s3 /* rv[2] */ + li a0, TEESMC_OPTEED_RETURN_CALL_DONE + + /* Return to untrusted domain */ + jal thread_return_from_nsec_call +.thread_rpc_return: + /* + * Jumps here from thread_resume() above when RPC has returned. + * At this point has the stack pointer been restored to the value + * stored in THREAD_CTX above. + */ + + /* Get pointer to rv[] */ + LDR a4, REGOFF(0)(sp) + + /* Store a0-a3 into rv[] */ + sw a0, 0(a4) + sw a1, 4(a4) + sw a2, 8(a4) + sw a3, 12(a4) + + /* Pop return address from stack */ + LDR ra, REGOFF(2)(sp) + + addi sp, sp, 16 + ret +END_FUNC thread_rpc diff --git a/optee/optee_os/core/arch/riscv/mm/sub.mk b/optee/optee_os/core/arch/riscv/mm/sub.mk new file mode 100644 index 0000000..b73d050 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/mm/sub.mk @@ -0,0 +1 @@ +srcs-y += tlb_helpers_rv.S diff --git a/optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S b/optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S new file mode 100644 index 0000000..aa33d86 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/mm/tlb_helpers_rv.S @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#include +#include +#include + +/* void tlbi_all(void); */ +FUNC tlbi_all , : + sfence.vma zero, zero + ret +END_FUNC tlbi_all + +/* void tlbi_mva_allasid(vaddr_t mva); */ +FUNC tlbi_mva_allasid , : + sfence.vma a0, zero + ret +END_FUNC tlbi_mva_allasid + +/* void tlbi_asid(unsigned int asid); */ +FUNC tlbi_asid , : + sfence.vma zero, a0 + ret +END_FUNC tlbi_asid diff --git a/optee/optee_os/core/arch/riscv/plat-spike/conf.mk b/optee/optee_os/core/arch/riscv/plat-spike/conf.mk new file mode 100644 index 0000000..27108ac --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/conf.mk @@ -0,0 +1,77 @@ +CFG_RV64_core ?= y +$(call force,CFG_WITH_USER_TA,n) +$(call force,CFG_WITH_SOFTWARE_PRNG,y) +$(call force,CFG_CORE_FFA,n) +$(call force,CFG_CORE_DYN_SHM,n) +$(call force,CFG_SECURE_PARTITION,n) +$(call force,CFG_PAGED_USER_TA,n) +$(call force,CFG_WITH_PAGER,n) +$(call force,CFG_TEE_TA_LOG_LEVEL,0) +$(call force,CFG_EMBEDDED_TS,n) +$(call force,CFG_CORE_ASLR,n) +$(call force,CFG_LIBUTILS_WITH_ISOC,y) +$(call force,CFG_UNWIND,n) +$(call force,CFG_DT,n) +$(call force,CFG_NS_VIRTUALIZATION,n) +$(call force,CFG_WITH_VFP,n) +$(call force,CFG_WITH_STATS,n) +$(call force,CFG_WITH_STMM_SP,n) +$(call force,CFG_WITH_STACK_CANARIES,n) +$(call force,CFG_TEE_TA_MALLOC_DEBUG,n) +$(call force,CFG_COMPAT_GP10_DES,n) +$(call force,CFG_TEE_CORE_TA_TRACE,n) +$(call force,CFG_TEE_CORE_NB_CORE,4) +$(call force,CFG_TEE_CORE_MALLOC_DEBUG,n) +$(call force,CFG_TEE_CORE_DEBUG,n) +$(call force,CFG_SYSTEM_PTA,n) +$(call force,CFG_SYSCALL_FTRACE,n) +$(call force,CFG_CORE_DEBUG_CHECK_STACKS,n) +$(call force,CFG_BOOT_SECONDARY_REQUEST,n) +$(call force,CFG_CORE_DUMP_OOM,n) +$(call force,CFG_CORE_LARGE_PHYS_ADDR,n) +$(call force,CFG_CORE_RESERVED_SHM,y) +$(call force,CFG_CORE_RODATA_NOEXEC,n) +$(call force,CFG_CORE_RWDATA_NOEXEC,y) +$(call force,CFG_CORE_SANITIZE_KADDRESS,n) +$(call force,CFG_CORE_SANITIZE_UNDEFINED,n) +$(call force,CFG_CORE_THREAD_SHIFT,0) +$(call force,CFG_CORE_TPM_EVENT_LOG,n) +$(call force,CFG_DEBUG_INFO,n) +$(call force,CFG_DEVICE_ENUM_PTA,n) +$(call force,CFG_DRIVERS_CLK,n) +$(call force,CFG_DRIVERS_CLK_DT,n) +$(call force,CFG_DRIVERS_CLK_FIXED,n) +$(call force,CFG_EARLY_TA,n) +$(call force,CFG_EARLY_TA_COMPRESS,n) +$(call force,CFG_EMBED_DTB,n) +$(call force,CFG_ENABLE_EMBEDDED_TESTS,n) +$(call force,CFG_ENABLE_SCTLR_Z,n) +$(call force,CFG_EXTERNAL_DTB_OVERLAY,n) +$(call force,CFG_FTRACE_SUPPORT,n) +$(call force,CFG_GENERATE_DTB_OVERLAY,n) +$(call force,CFG_GIC,n) +$(call force,CFG_GP_SOCKETS,n) +$(call force,CFG_LOCKDEP,n) +$(call force,CFG_TEE_CORE_EMBED_INTERNAL_TESTS,n) +$(call force,CFG_MMAP_REGIONS,13) +$(call force,CFG_NUM_THREADS,4) +$(call force,CFG_PAGED_USER_TA,n) +$(call force,CFG_REE_FS,n) +$(call force,CFG_REE_FS_ALLOW_RESET,n) +$(call force,CFG_REE_FS_TA,n) +$(call force,CFG_REE_FS_TA_BUFFERED,n) +$(call force,CFG_RPMB_FS,n) +$(call force,CFG_SCMI_PTA,n) +$(call force,CFG_SCTLR_ALIGNMENT_CHECK,n) +$(call force,CFG_SECSTOR_TA,n) +$(call force,CFG_SHOW_CONF_ON_BOOT,n) +$(call force,CFG_SYSCALL_WRAPPERS_MCOUNT,n) +$(call force,CFG_BOOT_SYNC_CPU,y) +$(call force,CFG_WARN_INSECURE,y) +$(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y) +CFG_RISCV_MTIME_RATE ?= 10000000 +CFG_TDDRAM_START ?= 0xbdb00000 +CFG_TDDRAM_SIZE ?= 0x00f00000 +CFG_SHMEM_START ?= 0x7fe00000 +CFG_SHMEM_SIZE ?= 0x00200000 +CFG_TEE_RAM_VA_SIZE ?= 0x00400000 diff --git a/optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.c b/optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.c new file mode 100644 index 0000000..c7203e5 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ + +#include +#include +#include +#include +#include + +#include "htif.h" + +static unsigned int htif_global_lock __nex_bss = SPINLOCK_UNLOCK; + +#ifdef HTIF_BASE +register_phys_mem(MEM_AREA_IO_NSEC, HTIF_BASE, + ROUNDUP(HTIF_REG_SIZE, CORE_MMU_PGDIR_SIZE)); +#endif + +void htif_lock_global(void) +{ + cpu_spin_lock(&htif_global_lock); +} + +void htif_unlock_global(void) +{ + cpu_spin_unlock(&htif_global_lock); +} + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct htif_console_data *pd = + container_of(chip, struct htif_console_data, chip); + + return io_pa_or_va(&pd->base, HTIF_REG_SIZE); +} + +static void __maybe_unused tohost_cmd(vaddr_t base, uint64_t dev, + uint64_t cmd, uint64_t data) +{ + while (io_read64(base)) + barrier(); + + io_write64(base, SHIFT_U64(dev, 56) | SHIFT_U64(cmd, 48) | data); +} + +static void htif_console_putc(struct serial_chip *chip, + int ch __maybe_unused) +{ +#ifdef RV64 + vaddr_t base = 0; + + htif_lock_global(); + base = chip_to_base(chip); + tohost_cmd(base, HTIF_DEV_CONSOLE, HTIF_CMD_WRITE, ch); + htif_unlock_global(); +#else +#warning HTIF is not supported on RV32 +#endif +} + +static void htif_console_flush(struct serial_chip *chip __unused) +{ +} + +static const struct serial_ops htif_console_ops = { + .flush = htif_console_flush, + .putc = htif_console_putc, +}; +DECLARE_KEEP_PAGER(htif_console_ops); + +void htif_console_init(struct htif_console_data *pd, paddr_t pbase) +{ + pd->base.pa = pbase; + pd->chip.ops = &htif_console_ops; +} diff --git a/optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.h b/optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.h new file mode 100644 index 0000000..83935af --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/drivers/htif.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef __DRIVERS_HTIF_H__ +#define __DRIVERS_HTIF_H__ + +#include +#include + +#define HTIF_CMD_WRITE 1 +#define HTIF_DEV_CONSOLE 1 +#define HTIF_REG_SIZE (2 * RISCV_XLEN_BYTES) + +struct htif_console_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void htif_lock_global(void); +void htif_unlock_global(void); +void htif_console_init(struct htif_console_data *pd, paddr_t pbase); + +#endif /*__DRIVERS_HTIF_H__*/ diff --git a/optee/optee_os/core/arch/riscv/plat-spike/drivers/sub.mk b/optee/optee_os/core/arch/riscv/plat-spike/drivers/sub.mk new file mode 100644 index 0000000..deb63e0 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/drivers/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_RISCV_M_MODE) += htif.c diff --git a/optee/optee_os/core/arch/riscv/plat-spike/kern.ld.S b/optee/optee_os/core/arch/riscv/plat-spike/kern.ld.S new file mode 100644 index 0000000..e437dc0 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/kern.ld.S @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: (BSD-2-Clause) */ +/* + * Copyright 2022 NXP + */ + +#include "../kernel/kern.ld.S" + +SECTIONS +{ + .htif HTIF_BASE: + { + tohost = .; + fromhost = tohost + 8; + } + +} diff --git a/optee/optee_os/core/arch/riscv/plat-spike/main.c b/optee/optee_os/core/arch/riscv/plat-spike/main.c new file mode 100644 index 0000000..40de072 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/main.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ + +#include +#include +#include +#include + +#include "drivers/htif.h" + +#ifdef CFG_RISCV_M_MODE +static struct htif_console_data console_data __nex_bss; + +void console_init(void) +{ +#ifdef HTIF_BASE + htif_console_init(&console_data, HTIF_BASE); + register_serial_console(&console_data.chip); +#endif /*HTIF_BASE*/ +} +#endif /*CFG_RISCV_M_MODE*/ + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + memset(&hwkey->data[0], 0, sizeof(hwkey->data)); + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/arch/riscv/plat-spike/platform_config.h b/optee/optee_os/core/arch/riscv/plat-spike/platform_config.h new file mode 100644 index 0000000..2bfaef7 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/platform_config.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + * + * Brief Spike platform configuration. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +#ifndef HTIF_BASE +#define HTIF_BASE 0x40008000 +#endif + +#endif diff --git a/optee/optee_os/core/arch/riscv/plat-spike/sub.mk b/optee/optee_os/core/arch/riscv/plat-spike/sub.mk new file mode 100644 index 0000000..4bec00d --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-spike/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += . +subdirs-y += drivers +srcs-y += main.c diff --git a/optee/optee_os/core/arch/riscv/plat-virt/conf.mk b/optee/optee_os/core/arch/riscv/plat-virt/conf.mk new file mode 100644 index 0000000..ca7228c --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-virt/conf.mk @@ -0,0 +1,36 @@ +$(call force,CFG_RV64_core,y) + +$(call force,CFG_CORE_LARGE_PHYS_ADDR,y) +$(call force,CFG_TEE_CORE_DEBUG,n) +$(call force,CFG_CORE_DYN_SHM,n) + +# Crypto flags +$(call force,CFG_WITH_SOFTWARE_PRNG,y) + +# Protection flags +$(call force,CFG_CORE_ASLR,n) +$(call force,CFG_WITH_STACK_CANARIES,n) +$(call force,CFG_CORE_SANITIZE_KADDRESS,n) + +# Hart-related flags +$(call force,CFG_TEE_CORE_NB_CORE,1) +$(call force,CFG_NUM_THREADS,1) +$(call force,CFG_BOOT_SYNC_CPU,y) + +# RISC-V-specific flags +$(call force,CFG_RISCV_PLIC,y) +$(call force,CFG_SBI_CONSOLE,n) +$(call force,CFG_16550_UART,y) +$(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y) +CFG_RISCV_MTIME_RATE ?= 10000000 + +# TA-related flags +supported-ta-targets = ta_rv64 + +# Memory layout flags +CFG_TDDRAM_START ?= 0x8e000000 +CFG_TDDRAM_SIZE ?= 0x00f00000 +$(call force,CFG_CORE_RESERVED_SHM,y) +CFG_SHMEM_START ?= 0x88f00000 +CFG_SHMEM_SIZE ?= 0x00200000 +CFG_TEE_RAM_VA_SIZE ?= 0x00200000 diff --git a/optee/optee_os/core/arch/riscv/plat-virt/main.c b/optee/optee_os/core/arch/riscv/plat-virt/main.c new file mode 100644 index 0000000..6b23967 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-virt/main.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ + +#include +#include +#include +#include +#include +#include + +static struct plic_data plic_data __nex_bss; +static struct ns16550_data console_data __nex_bss; + +register_ddr(DRAM_BASE, DRAM_SIZE); + +register_phys_mem_pgdir(MEM_AREA_IO_NSEC, UART0_BASE, + CORE_MMU_PGDIR_SIZE); + +#ifdef CFG_RISCV_PLIC +void main_init_plic(void) +{ + plic_init(&plic_data, PLIC_BASE); + itr_init(&plic_data.chip); +} + +void main_secondary_init_plic(void) +{ + plic_hart_init(&plic_data); +} +#endif /* CFG_RISCV_PLIC */ + +void console_init(void) +{ + ns16550_init(&console_data, UART0_BASE, IO_WIDTH_U8, 0); + register_serial_console(&console_data.chip); +} + +void itr_core_handler(void) +{ + if (IS_ENABLED(CFG_RISCV_PLIC)) + plic_it_handle(&plic_data); +} diff --git a/optee/optee_os/core/arch/riscv/plat-virt/platform_config.h b/optee/optee_os/core/arch/riscv/plat-virt/platform_config.h new file mode 100644 index 0000000..8af2a03 --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-virt/platform_config.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + * + * Brief Qemu Virt platform configuration. + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#include + +/* The stack pointer is always kept 16-byte aligned */ +#define STACK_ALIGNMENT 16 + +/* DRAM */ +#ifndef DRAM_BASE +#define DRAM_BASE 0x80000000 +#define DRAM_SIZE 0x10000000 +#endif + +/* CLINT */ +#ifndef CLINT_BASE +#define CLINT_BASE 0x02000000 +#endif + +/* PLIC */ +#ifndef PLIC_BASE +#define PLIC_BASE 0x0c000000 +#define PLIC_REG_SIZE 0x1000 +#define PLIC_NUM_SOURCES 0x7f +#endif + +/* UART */ +#ifndef UART0_BASE +#define UART0_BASE 0x10000000 +#endif +#define UART0_IRQ 0x0a + +/* RTC */ +#ifndef RTC_BASE +#define RTC_BASE 0x101000 +#endif +#define RTC_IRQ 0x0b + +/* VIRTIO MMIOs */ +#define NUM_VIRTIO_MMIOS 8 + +#ifndef VIRTIO_MMIO1 +#define VIRTIO_MMIO1 0x10001000 +#define VIRTIO_MMIO1_IRQ 0x01 +#endif + +#ifndef VIRTIO_MMIO2 +#define VIRTIO_MMIO2 0x10002000 +#define VIRTIO_MMIO2_IRQ 0x02 +#endif + +#ifndef VIRTIO_MMIO3 +#define VIRTIO_MMIO3 0x10003000 +#define VIRTIO_MMIO3_IRQ 0x03 +#endif + +#ifndef VIRTIO_MMIO4 +#define VIRTIO_MMIO4 0x10004000 +#define VIRTIO_MMIO4_IRQ 0x04 +#endif + +#ifndef VIRTIO_MMIO5 +#define VIRTIO_MMIO5 0x10005000 +#define VIRTIO_MMIO5_IRQ 0x05 +#endif + +#ifndef VIRTIO_MMIO6 +#define VIRTIO_MMIO6 0x10006000 +#define VIRTIO_MMIO6_IRQ 0x06 +#endif + +#ifndef VIRTIO_MMIO7 +#define VIRTIO_MMIO7 0x10007000 +#define VIRTIO_MMIO7_IRQ 0x07 +#endif + +#ifndef VIRTIO_MMIO8 +#define VIRTIO_MMIO8 0x10008000 +#define VIRTIO_MMIO8_IRQ 0x08 +#endif + +#ifdef CFG_RISCV_MTIME_RATE +#define RISCV_MTIME_RATE CFG_RISCV_MTIME_RATE +#else +#define RISCV_MTIME_RATE 1000000 +#endif + +#endif /*PLATFORM_CONFIG_H*/ diff --git a/optee/optee_os/core/arch/riscv/plat-virt/sub.mk b/optee/optee_os/core/arch/riscv/plat-virt/sub.mk new file mode 100644 index 0000000..8ddc2fd --- /dev/null +++ b/optee/optee_os/core/arch/riscv/plat-virt/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += . +srcs-y += main.c diff --git a/optee/optee_os/core/arch/riscv/riscv.mk b/optee/optee_os/core/arch/riscv/riscv.mk new file mode 100644 index 0000000..deac27f --- /dev/null +++ b/optee/optee_os/core/arch/riscv/riscv.mk @@ -0,0 +1,211 @@ +# Setup compiler for the core module +ifeq ($(CFG_RV64_core),y) +arch-bits-core := 64 +else +arch-bits-core := 32 +endif +CROSS_COMPILE_core := $(CROSS_COMPILE$(arch-bits-core)) +COMPILER_core := $(COMPILER) + +include mk/$(COMPILER_core).mk + +# Defines the cc-option macro using the compiler set for the core module +include mk/cc-option.mk + +CFG_MMAP_REGIONS ?= 13 +CFG_RESERVED_VASPACE_SIZE ?= (1024 * 1024 * 10) + +ifeq ($(CFG_RV64_core),y) +CFG_KERN_LINKER_FORMAT ?= elf64-littleriscv +CFG_KERN_LINKER_ARCH ?= riscv +else +ifeq ($(CFG_RV32_core),y) +CFG_KERN_LINKER_FORMAT ?= elf32-littleriscv +CFG_KERN_LINKER_ARCH ?= riscv +else +$(error Error: CFG_RV64_core or CFG_RV32_core should be defined) +endif +endif + +CFG_CORE_RWDATA_NOEXEC ?= y +CFG_CORE_RODATA_NOEXEC ?= n +ifeq ($(CFG_CORE_RODATA_NOEXEC),y) +$(call force,CFG_CORE_RWDATA_NOEXEC,y) +endif + +CFG_MAX_CACHE_LINE_SHIFT ?= 6 + +CFG_RISCV_SBI ?= n +CFG_RISCV_M_MODE ?= y +ifeq ($(CFG_RISCV_M_MODE),y) +ifeq ($(CFG_RISCV_S_MODE),y) +$(error CFG_RISCV_M_MODE and CFG_RISCV_S_MODE cannot be both 'y') +else +$(call force,CFG_RISCV_S_MODE,n) +$(call force,CFG_RISCV_SBI,n) +endif +endif +ifeq ($(CFG_RISCV_S_MODE),y) +$(call force,CFG_RISCV_M_MODE,n) +endif +ifneq (y,$(call cfg-one-enabled,CFG_RISCV_M_MODE M CFG_RISCV_S_MODE)) +$(error Either CFG_RISCV_M_MODE or CFG_RISCV_S_MODE must be 'y') +endif + +ifeq ($(CFG_RISCV_SBI_CONSOLE),y) +$(call force,CFG_RISCV_SBI,y) +endif + +# Disable unsupported and other arch-specific flags +$(call force,CFG_CORE_FFA,n) +$(call force,CFG_SECURE_PARTITION,n) +$(call force,CFG_PAGED_USER_TA,n) +$(call force,CFG_WITH_PAGER,n) +$(call force,CFG_GIC,n) +$(call force,CFG_ARM_GICV3,n) +$(call force,CFG_WITH_VFP,n) +$(call force,CFG_WITH_STMM_SP,n) +$(call force,CFG_TA_BTI,n) + +core-platform-cppflags += -I$(arch-dir)/include +core-platform-subdirs += \ + $(addprefix $(arch-dir)/, kernel mm tee) $(platform-dir) + +# more convenient to move it to platform instead +rv64-platform-cppflags += -mcmodel=medany -march=rv64imafd -mabi=lp64d +rv64-platform-cppflags += -Wno-missing-include-dirs + +rv64-platform-cppflags += -DRV64=1 -D__LP64__=1 +rv32-platform-cppflags += -DRV32=1 -D__ILP32__=1 + +platform-cflags-generic ?= -ffunction-sections -fdata-sections -pipe +platform-aflags-generic ?= -pipe + +rv64-platform-cflags-generic := -mstrict-align $(call cc-option,) + +# Optimize for size by default, usually gives good performance too +CFG_CC_OPT_LEVEL ?= 0 +platform-cflags-optimization ?= -O$(CFG_CC_OPT_LEVEL) + +CFG_DEBUG_INFO ?= y +ifeq ($(CFG_DEBUG_INFO),y) +platform-cflags-debug-info ?= -g3 +platform-aflags-debug-info ?= -g +endif + +core-platform-cflags += $(platform-cflags-optimization) +core-platform-cflags += $(platform-cflags-generic) +core-platform-cflags += $(platform-cflags-debug-info) + +core-platform-aflags += $(platform-aflags-generic) +core-platform-aflags += $(platform-aflags-debug-info) + +ifeq ($(CFG_CORE_ASLR),y) +core-platform-cflags += -fpie +endif + +ifeq ($(CFG_RV64_core),y) +core-platform-cppflags += $(rv64-platform-cppflags) +core-platform-cflags += $(rv64-platform-cflags) +core-platform-cflags += $(rv64-platform-cflags-generic) +core-platform-cflags += $(rv64-platform-cflags-no-hard-float) +core-platform-aflags += $(rv64-platform-aflags) +else +core-platform-cppflags += $(rv32-platform-cppflags) +core-platform-cflags += $(rv32-platform-cflags) +core-platform-cflags += $(rv32-platform-cflags-no-hard-float) +ifeq ($(CFG_UNWIND),y) +core-platform-cflags += -funwind-tables +endif +core-platform-aflags += $(core_rv32-platform-aflags) +core-platform-aflags += $(rv32-platform-aflags) +endif + +# Provide default supported-ta-targets if not set by the platform config +ifeq (,$(supported-ta-targets)) +supported-ta-targets = ta_rv32 +ifeq ($(CFG_RV64_core),y) +supported-ta-targets += ta_rv64 +endif +endif + +ta-targets := $(if $(CFG_USER_TA_TARGETS),$(filter $(supported-ta-targets),$(CFG_USER_TA_TARGETS)),$(supported-ta-targets)) +unsup-targets := $(filter-out $(ta-targets),$(CFG_USER_TA_TARGETS)) +ifneq (,$(unsup-targets)) +$(error CFG_USER_TA_TARGETS contains unsupported value(s): $(unsup-targets). Valid values: $(supported-ta-targets)) +endif + +ifneq ($(filter ta_rv32,$(ta-targets)),) +# Variables for ta-target/sm "ta_rv32" +CFG_RV32_ta_rv32 := y +arch-bits-ta_rv32 := 32 +ta_rv32-platform-cppflags += $(rv32-platform-cppflags) +ta_rv32-platform-cflags += $(rv32-platform-cflags) +ta_rv32-platform-cflags += $(platform-cflags-optimization) +ta_rv32-platform-cflags += $(platform-cflags-debug-info) +ta_rv32-platform-cflags += -fpic + +ifeq ($(CFG_UNWIND),y) +ta_rv32-platform-cflags += -funwind-tables +endif +ta_rv32-platform-aflags += $(platform-aflags-generic) +ta_rv32-platform-aflags += $(platform-aflags-debug-info) +ta_rv32-platform-aflags += $(rv32-platform-aflags) + +ta_rv32-platform-cxxflags += -fpic +ta_rv32-platform-cxxflags += $(rv32-platform-cxxflags) +ta_rv32-platform-cxxflags += $(platform-cflags-optimization) +ta_rv32-platform-cxxflags += $(platform-cflags-debug-info) + +ta-mk-file-export-vars-ta_rv32 += CFG_RV32_ta_rv32 +ta-mk-file-export-vars-ta_rv32 += ta_rv32-platform-cppflags +ta-mk-file-export-vars-ta_rv32 += ta_rv32-platform-cflags +ta-mk-file-export-vars-ta_rv32 += ta_rv32-platform-aflags +ta-mk-file-export-vars-ta_rv32 += ta_rv32-platform-cxxflags + +ta-mk-file-export-add-ta_rv32 += CROSS_COMPILE ?= riscv32-unknown-linux-gnu-_nl_ +ta-mk-file-export-add-ta_rv32 += CROSS_COMPILE32 ?= $$(CROSS_COMPILE)_nl_ +ta-mk-file-export-add-ta_rv32 += CROSS_COMPILE_ta_rv32 ?= $$(CROSS_COMPILE32)_nl_ +ta-mk-file-export-add-ta_rv32 += COMPILER ?= gcc_nl_ +ta-mk-file-export-add-ta_rv32 += COMPILER_ta_rv32 ?= $$(COMPILER)_nl_ +ta-mk-file-export-add-ta_rv32 += PYTHON3 ?= python3_nl_ +endif + +ifneq ($(filter ta_rv64,$(ta-targets)),) +# Variables for ta-target/sm "ta_rv64" +CFG_RV64_ta_rv64 := y +arch-bits-ta_rv64 := 64 +ta_rv64-platform-cppflags += $(rv64-platform-cppflags) +ta_rv64-platform-cflags += $(rv64-platform-cflags) +ta_rv64-platform-cflags += $(platform-cflags-optimization) +ta_rv64-platform-cflags += $(platform-cflags-debug-info) +ta_rv64-platform-cflags += -fpic +ta_rv64-platform-cflags += $(rv64-platform-cflags-generic) +ifeq ($(rv64-platform-hard-float-enabled),y) +ta_rv64-platform-cflags += $(rv64-platform-cflags-hard-float) +else +ta_rv64-platform-cflags += $(rv64-platform-cflags-no-hard-float) +endif +ta_rv64-platform-aflags += $(platform-aflags-generic) +ta_rv64-platform-aflags += $(platform-aflags-debug-info) +ta_rv64-platform-aflags += $(rv64-platform-aflags) + +ta_rv64-platform-cxxflags += -fpic +ta_rv64-platform-cxxflags += $(platform-cflags-optimization) +ta_rv64-platform-cxxflags += $(platform-cflags-debug-info) + +ta-mk-file-export-vars-ta_rv64 += CFG_RV64_ta_rv64 +ta-mk-file-export-vars-ta_rv64 += ta_rv64-platform-cppflags +ta-mk-file-export-vars-ta_rv64 += ta_rv64-platform-cflags +ta-mk-file-export-vars-ta_rv64 += ta_rv64-platform-aflags +ta-mk-file-export-vars-ta_rv64 += ta_rv64-platform-cxxflags + +ta-mk-file-export-add-ta_rv64 += CROSS_COMPILE64 ?= $$(CROSS_COMPILE)_nl_ +ta-mk-file-export-add-ta_rv64 += CROSS_COMPILE_ta_rv64 ?= $$(CROSS_COMPILE64)_nl_ +ta-mk-file-export-add-ta_rv64 += COMPILER ?= gcc_nl_ +ta-mk-file-export-add-ta_rv64 += COMPILER_ta_rv64 ?= $$(COMPILER)_nl_ +ta-mk-file-export-add-ta_rv64 += PYTHON3 ?= python3_nl_ +endif + +# Set cross compiler prefix for each TA target +$(foreach sm, $(ta-targets), $(eval CROSS_COMPILE_$(sm) ?= $(CROSS_COMPILE$(arch-bits-$(sm))))) diff --git a/optee/optee_os/core/arch/riscv/tee/sub.mk b/optee/optee_os/core/arch/riscv/tee/sub.mk new file mode 100644 index 0000000..e69de29 diff --git a/optee/optee_os/core/core.mk b/optee/optee_os/core/core.mk new file mode 100644 index 0000000..b023e46 --- /dev/null +++ b/optee/optee_os/core/core.mk @@ -0,0 +1,176 @@ +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 +include mk/config.mk +# $(ARCH).mk also sets the compiler for the core module +include core/arch/$(ARCH)/$(ARCH).mk + +PLATFORM_$(PLATFORM) := y +PLATFORM_FLAVOR_$(PLATFORM_FLAVOR) := y + +$(eval $(call cfg-depends-all,CFG_PAGED_USER_TA,CFG_WITH_PAGER CFG_WITH_USER_TA)) +include core/crypto.mk + +ifeq ($(CFG_SCMI_SCPFW),y) +include core/lib/scmi-server/conf.mk +endif + +cppflags$(sm) += -D__KERNEL__ + +cppflags$(sm) += -Icore/include +cppflags$(sm) += -include $(conf-file) +cppflags$(sm) += -I$(out-dir)/core/include +cppflags$(sm) += $(core-platform-cppflags) +cflags$(sm) += $(core-platform-cflags) + +core-stackp-cflags-$(CFG_CORE_STACK_PROTECTOR) := -fstack-protector +core-stackp-cflags-$(CFG_CORE_STACK_PROTECTOR_STRONG) := -fstack-protector-strong +core-stackp-cflags-$(CFG_CORE_STACK_PROTECTOR_ALL) := -fstack-protector-all +cflags$(sm) += $(core-stackp-cflags-y) + +ifeq ($(CFG_CORE_SANITIZE_UNDEFINED),y) +cflags$(sm) += -fsanitize=undefined +endif +ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y) +ifeq ($(CFG_ASAN_SHADOW_OFFSET),) +$(error error: CFG_CORE_SANITIZE_KADDRESS not supported by platform (flavor)) +endif +ifeq ($(COMPILER),clang) +$(error error: CFG_CORE_SANITIZE_KADDRESS not supported with Clang) +endif +cflags_kasan += -fsanitize=kernel-address \ + -fasan-shadow-offset=$(CFG_ASAN_SHADOW_OFFSET)\ + --param asan-stack=1 --param asan-globals=1 \ + --param asan-instrumentation-with-call-threshold=0 +cflags$(sm) += $(cflags_kasan) +endif +ifeq ($(CFG_CORE_DEBUG_CHECK_STACKS),y) +finstrument-functions := $(call cc-option,-finstrument-functions) +ifeq (,$(finstrument-functions)) +$(error -finstrument-functions not supported) +endif +cflags$(sm) += $(finstrument-functions) +endif +ifeq ($(CFG_SYSCALL_FTRACE),y) +cflags$(sm) += -pg +endif +aflags$(sm) += $(core-platform-aflags) + +cppflags$(sm) += -DTRACE_LEVEL=$(CFG_TEE_CORE_LOG_LEVEL) +ifeq ($(CFG_TEE_CORE_MALLOC_DEBUG),y) +cppflags$(sm) += -DENABLE_MDBG=1 +endif +ifneq ($(CFG_TEE_CORE_DEBUG),y) +cppflags$(sm) += -DNDEBUG +endif + +cppflags$(sm) += -Ildelf/include +cppflags$(sm) += -Ilib/libutee/include + +ifeq ($(filter y, $(CFG_CORE_DYN_SHM) $(CFG_CORE_RESERVED_SHM)),) +$(error error: No shared memory configured) +endif + +# Tell all libraries and sub-directories (included below) that we have a +# configuration file + +conf-file := $(out-dir)/include/generated/conf.h +conf-mk-file := $(out-dir)/conf.mk +conf-cmake-file := $(out-dir)/conf.cmake +$(conf-file): $(conf-mk-file) + +cleanfiles += $(conf-file) +cleanfiles += $(conf-mk-file) +cleanfiles += $(conf-cmake-file) + +$(conf-file): FORCE + $(call check-conf-h) + +$(conf-mk-file): FORCE + $(call check-conf-mk) + +$(conf-cmake-file): FORCE + $(call check-conf-cmake) + +# +# 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 + +# CFG_CRYPTOLIB_NAME must not be changed beyond this line +CFG_CRYPTOLIB_NAME_$(CFG_CRYPTOLIB_NAME) := y + +ifeq ($(CFG_CRYPTOLIB_NAME),tomcrypt) +# We're compiling mbedtls too, but with a limited configuration which only +# provides the MPI routines +libname = mbedtls +libdir = lib/libmbedtls +include mk/lib.mk +endif #tomcrypt + +ifeq ($(CFG_CRYPTOLIB_NAME),mbedtls) +$(call force,CFG_CRYPTO_RSASSA_NA1,n,not supported by mbedtls) +libname = tomcrypt +libdir = core/lib/libtomcrypt +base-prefix := +include mk/lib.mk +base-prefix := $(sm)- +endif + +ifeq ($(firstword $(subst /, ,$(CFG_CRYPTOLIB_DIR))),core) +# If a library can be compiled for both core and user space a base-prefix +# is needed in order to avoid conflicts in the output. However, if the +# library resides under core then it can't be compiled to user space. +base-prefix := +endif + +libname = $(CFG_CRYPTOLIB_NAME) +libdir = $(CFG_CRYPTOLIB_DIR) +include mk/lib.mk + +base-prefix := + +libname = fdt +libdir = core/lib/libfdt +include mk/lib.mk + +ifeq ($(CFG_ZLIB),y) +libname = zlib +libdir = core/lib/zlib +include mk/lib.mk +endif + +libname = unw +libdir = lib/libunw +include mk/lib.mk + +ifeq ($(CFG_SCMI_SCPFW),y) +libname = scmi-server +libdir = core/lib/scmi-server +include mk/lib.mk +endif + +# +# Do main source +# + +subdirs = $(core-platform-subdirs) core +include mk/subdir.mk + +include mk/compile.mk + +include $(if $(wildcard $(platform-dir)/link.mk), \ + $(platform-dir)/link.mk, \ + core/arch/$(ARCH)/kernel/link.mk) diff --git a/optee/optee_os/core/crypto.mk b/optee/optee_os/core/crypto.mk new file mode 100644 index 0000000..dbc305a --- /dev/null +++ b/optee/optee_os/core/crypto.mk @@ -0,0 +1,304 @@ +CFG_CRYPTO ?= y +# Select small code size in the crypto library if applicable (for instance +# LibTomCrypt has -DLTC_SMALL_CODE) +# Note: the compiler flag -Os is not set here but by CFG_CC_OPT_LEVEL +CFG_CRYPTO_SIZE_OPTIMIZATION ?= y + +ifeq (y,$(CFG_CRYPTO)) + +############################################################### +# Platform crypto-driver configuration. It has a higher priority over the +# generic crypto configuration below. +############################################################### +CRYPTO_MAKEFILES := $(sort $(wildcard core/drivers/crypto/*/crypto.mk)) +include $(CRYPTO_MAKEFILES) + +# Ciphers +CFG_CRYPTO_AES ?= y +CFG_CRYPTO_DES ?= y +CFG_CRYPTO_SM4 ?= y + +# Cipher block modes +CFG_CRYPTO_ECB ?= y +CFG_CRYPTO_CBC ?= y +CFG_CRYPTO_CTR ?= y +CFG_CRYPTO_CTS ?= y +CFG_CRYPTO_XTS ?= y + +# Message authentication codes +CFG_CRYPTO_HMAC ?= y +CFG_CRYPTO_CMAC ?= y +CFG_CRYPTO_CBC_MAC ?= y +# Instead of calling the AES CBC encryption function for each 16 byte block of +# input, bundle a maximum of N blocks when possible. A maximum of N*16 bytes of +# temporary data are allocated on the heap. +# Minimum value is 1. +CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS ?= 64 + +# Hashes +CFG_CRYPTO_MD5 ?= y +CFG_CRYPTO_SHA1 ?= y +CFG_CRYPTO_SHA224 ?= y +CFG_CRYPTO_SHA256 ?= y +CFG_CRYPTO_SHA384 ?= y +CFG_CRYPTO_SHA512 ?= y +CFG_CRYPTO_SHA512_256 ?= y +CFG_CRYPTO_SM3 ?= y +CFG_CRYPTO_SHA3_224 ?= y +CFG_CRYPTO_SHA3_256 ?= y +CFG_CRYPTO_SHA3_384 ?= y +CFG_CRYPTO_SHA3_512 ?= y + +# Extendable-Output Functions (XOF) +CFG_CRYPTO_SHAKE128 ?= y +CFG_CRYPTO_SHAKE256 ?= y + +# Asymmetric ciphers +CFG_CRYPTO_DSA ?= y +CFG_CRYPTO_RSA ?= y +CFG_CRYPTO_DH ?= y +# ECC includes ECDSA and ECDH +CFG_CRYPTO_ECC ?= y +CFG_CRYPTO_SM2_PKE ?= y +CFG_CRYPTO_SM2_DSA ?= y +CFG_CRYPTO_SM2_KEP ?= y +CFG_CRYPTO_ED25519 ?= y +CFG_CRYPTO_X25519 ?= y + +# Authenticated encryption +CFG_CRYPTO_CCM ?= y +CFG_CRYPTO_GCM ?= y +# Default uses the OP-TEE internal AES-GCM implementation +CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB ?= n + +endif + +# PRNG configuration +# If CFG_WITH_SOFTWARE_PRNG is enabled, crypto provider provided +# software PRNG implementation is used. +# Otherwise, you need to implement hw_get_random_bytes() for your platform +CFG_WITH_SOFTWARE_PRNG ?= y + +ifeq ($(CFG_WITH_PAGER),y) +ifneq ($(CFG_CRYPTO_SHA256),y) +$(warning Warning: Enabling CFG_CRYPTO_SHA256 [required by CFG_WITH_PAGER]) +CFG_CRYPTO_SHA256:=y +endif +endif + +$(eval $(call cryp-enable-all-depends,CFG_WITH_SOFTWARE_PRNG, AES ECB SHA256)) + +ifeq ($(CFG_CRYPTO_WITH_CE82),y) +$(call force,CFG_CRYPTO_WITH_CE,y,required with CFG_CRYPTO_WITH_CE82) +CFG_CRYPTO_SHA512_ARM_CE ?= $(CFG_CRYPTO_SHA512) +CFG_CORE_CRYPTO_SHA512_ACCEL ?= $(CFG_CRYPTO_SHA512_ARM_CE) +CFG_CRYPTO_SHA3_ARM_CE ?= $(call cfg-one-enabled, CFG_CRYPTO_SHA3_224 \ + CFG_CRYPTO_SHA3_256 CFG_CRYPTO_SHA3_384 \ + CFG_CRYPTO_SHA3_512 CFG_CRYPTO_SHAKE128 \ + CFG_CRYPTO_SHAKE256) +CFG_CORE_CRYPTO_SHA3_ACCEL ?= $(CFG_CRYPTO_SHA3_ARM_CE) +CFG_CRYPTO_SM3_ARM_CE ?= $(CFG_CRYPTO_SM3) +CFG_CORE_CRYPTO_SM3_ACCEL ?= $(CFG_CRYPTO_SM3_ARM_CE) + +# CFG_CRYPTO_SM4_ARM_CE defines whether we use SM4E to optimize SM4 +CFG_CRYPTO_SM4_ARM_CE ?= $(CFG_CRYPTO_SM4) +CFG_CORE_CRYPTO_SM4_ACCEL ?= $(CFG_CRYPTO_SM4_ARM_CE) +endif + +ifeq ($(CFG_CRYPTO_WITH_CE),y) + +$(call force,CFG_AES_GCM_TABLE_BASED,n,conflicts with CFG_CRYPTO_WITH_CE) + +# CFG_HWSUPP_PMULT_64 defines whether the CPU supports polynomial multiplies +# of 64-bit values (Aarch64: PMULL/PMULL2 with the 1Q specifier; Aarch32: +# VMULL.P64). These operations are part of the Cryptographic Extensions, so +# assume they are implicitly contained in CFG_CRYPTO_WITH_CE=y. +CFG_HWSUPP_PMULT_64 ?= y + +CFG_CRYPTO_SHA256_ARM_CE ?= $(CFG_CRYPTO_SHA256) +CFG_CORE_CRYPTO_SHA256_ACCEL ?= $(CFG_CRYPTO_SHA256_ARM_CE) +CFG_CRYPTO_SHA1_ARM_CE ?= $(CFG_CRYPTO_SHA1) +CFG_CORE_CRYPTO_SHA1_ACCEL ?= $(CFG_CRYPTO_SHA1_ARM_CE) +CFG_CRYPTO_AES_ARM_CE ?= $(CFG_CRYPTO_AES) +CFG_CORE_CRYPTO_AES_ACCEL ?= $(CFG_CRYPTO_AES_ARM_CE) + +# CFG_CRYPTO_SM4_ARM_AESE defines whether we use AESE to optimize SM4 +CFG_CRYPTO_SM4_ARM_AESE ?= $(CFG_CRYPTO_SM4) +CFG_CORE_CRYPTO_SM4_ACCEL ?= $(CFG_CRYPTO_SM4_ARM_AESE) +else #CFG_CRYPTO_WITH_CE + +CFG_AES_GCM_TABLE_BASED ?= y + +endif #!CFG_CRYPTO_WITH_CE + + +# Cryptographic extensions can only be used safely when OP-TEE knows how to +# preserve the VFP context +ifeq ($(CFG_CRYPTO_SHA256_ARM32_CE),y) +$(call force,CFG_WITH_VFP,y,required by CFG_CRYPTO_SHA256_ARM32_CE) +endif +ifeq ($(CFG_CRYPTO_SHA256_ARM64_CE),y) +$(call force,CFG_WITH_VFP,y,required by CFG_CRYPTO_SHA256_ARM64_CE) +endif +ifeq ($(CFG_CRYPTO_SHA1_ARM_CE),y) +$(call force,CFG_WITH_VFP,y,required by CFG_CRYPTO_SHA1_ARM_CE) +endif +ifeq ($(CFG_CRYPTO_AES_ARM_CE),y) +$(call force,CFG_WITH_VFP,y,required by CFG_CRYPTO_AES_ARM_CE) +endif +ifeq ($(CFG_CORE_CRYPTO_SM4_ACCEL),y) +$(call force,CFG_WITH_VFP,y,required by CFG_CORE_CRYPTO_SM4_ACCEL) +endif +cryp-enable-all-depends = $(call cfg-enable-all-depends,$(strip $(1)),$(foreach v,$(2),CFG_CRYPTO_$(v))) +$(eval $(call cryp-enable-all-depends,CFG_REE_FS, AES ECB CTR HMAC SHA256 GCM)) +$(eval $(call cryp-enable-all-depends,CFG_RPMB_FS, AES ECB CTR HMAC SHA256 GCM)) + +# Dependency checks: warn and disable some features if dependencies are not met + +cryp-dep-one = $(call cfg-depends-one,CFG_CRYPTO_$(strip $(1)),$(patsubst %, CFG_CRYPTO_%,$(strip $(2)))) +cryp-dep-all = $(call cfg-depends-all,CFG_CRYPTO_$(strip $(1)),$(patsubst %, CFG_CRYPTO_%,$(strip $(2)))) + +$(eval $(call cryp-dep-one, ECB, AES DES)) +$(eval $(call cryp-dep-one, CBC, AES DES)) +$(eval $(call cryp-dep-one, CTR, AES)) +# CTS is implemented with ECB and CBC +$(eval $(call cryp-dep-all, CTS, AES ECB CBC)) +$(eval $(call cryp-dep-one, XTS, AES)) +$(eval $(call cryp-dep-one, HMAC, AES DES)) +$(eval $(call cryp-dep-one, HMAC, MD5 SHA1 SHA224 SHA256 SHA384 SHA512)) +$(eval $(call cryp-dep-one, CMAC, AES)) +$(eval $(call cryp-dep-one, CBC_MAC, AES DES)) +$(eval $(call cryp-dep-one, CCM, AES)) +$(eval $(call cryp-dep-one, GCM, AES)) +# If no AES cipher mode is left, disable AES +$(eval $(call cryp-dep-one, AES, ECB CBC CTR CTS XTS)) +# If no DES cipher mode is left, disable DES +$(eval $(call cryp-dep-one, DES, ECB CBC)) +# SM2 is Elliptic Curve Cryptography, it uses some generic ECC functions +$(eval $(call cryp-dep-one, SM2_PKE, ECC)) +$(eval $(call cryp-dep-one, SM2_DSA, ECC)) +$(eval $(call cryp-dep-one, SM2_KEP, ECC)) + +############################################################### +# libtomcrypt (LTC) specifics, phase #1 +# LTC is only configured via _CFG_CORE_LTC_ prefixed variables +# +# _CFG_CORE_LTC_xxx_DESC means that LTC will only register the +# descriptor of the algorithm, not provide a +# crypt_xxx_alloc_ctx() function. +############################################################### + +# If LTC is the cryptolib, pull configuration from CFG_CRYPTO_xxx +ifeq ($(CFG_CRYPTOLIB_NAME),tomcrypt) +# dsa_make_params() needs all three SHA-2 algorithms. +# Disable DSA if any is missing. +$(eval $(call cryp-dep-all, DSA, SHA256 SHA384 SHA512)) + +# Assign _CFG_CORE_LTC_xxx based on CFG_CRYPTO_yyy +core-ltc-vars = AES DES +core-ltc-vars += ECB CBC CTR CTS XTS +core-ltc-vars += MD5 SHA1 SHA224 SHA256 SHA384 SHA512 SHA512_256 +core-ltc-vars += SHA3_224 SHA3_256 SHA3_384 SHA3_512 SHAKE128 SHAKE256 +core-ltc-vars += HMAC CMAC CBC_MAC +core-ltc-vars += CCM +ifeq ($(CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB),y) +core-ltc-vars += GCM +endif +core-ltc-vars += RSA DSA DH ECC +core-ltc-vars += SIZE_OPTIMIZATION +core-ltc-vars += SM2_PKE +core-ltc-vars += SM2_DSA +core-ltc-vars += SM2_KEP +core-ltc-vars += ED25519 X25519 +# Assigned selected CFG_CRYPTO_xxx as _CFG_CORE_LTC_xxx +$(foreach v, $(core-ltc-vars), $(eval _CFG_CORE_LTC_$(v) := $(CFG_CRYPTO_$(v)))) +_CFG_CORE_LTC_MPI := $(CFG_CORE_MBEDTLS_MPI) +_CFG_CORE_LTC_AES_ACCEL := $(CFG_CORE_CRYPTO_AES_ACCEL) +_CFG_CORE_LTC_SHA1_ACCEL := $(CFG_CORE_CRYPTO_SHA1_ACCEL) +_CFG_CORE_LTC_SHA256_ACCEL := $(CFG_CORE_CRYPTO_SHA256_ACCEL) +_CFG_CORE_LTC_SHA512_ACCEL := $(CFG_CORE_CRYPTO_SHA512_ACCEL) +_CFG_CORE_LTC_SHA3_ACCEL := $(CFG_CORE_CRYPTO_SHA3_ACCEL) +endif + +############################################################### +# mbedtls specifics +############################################################### + +ifeq ($(CFG_CRYPTOLIB_NAME),mbedtls) +# mbedtls has to be complemented with some algorithms by LTC +# Specify the algorithms here +_CFG_CORE_LTC_DSA := $(CFG_CRYPTO_DSA) +_CFG_CORE_LTC_MPI := $(CFG_CRYPTO_DSA) +_CFG_CORE_LTC_SHA256_DESC := $(CFG_CRYPTO_DSA) +_CFG_CORE_LTC_SHA384_DESC := $(CFG_CRYPTO_DSA) +_CFG_CORE_LTC_SHA512_DESC := $(CFG_CRYPTO_DSA) +_CFG_CORE_LTC_XTS := $(CFG_CRYPTO_XTS) +_CFG_CORE_LTC_CCM := $(CFG_CRYPTO_CCM) +_CFG_CORE_LTC_AES_DESC := $(call cfg-one-enabled, CFG_CRYPTO_XTS CFG_CRYPTO_CCM) +_CFG_CORE_LTC_X25519 := $(CFG_CRYPTO_X25519) +_CFG_CORE_LTC_ED25519 := $(CFG_CRYPTO_ED25519) +_CFG_CORE_LTC_SHA3_224 := $(CFG_CRYPTO_SHA3_224) +_CFG_CORE_LTC_SHA3_256 := $(CFG_CRYPTO_SHA3_256) +_CFG_CORE_LTC_SHA3_384 := $(CFG_CRYPTO_SHA3_384) +_CFG_CORE_LTC_SHA3_512 := $(CFG_CRYPTO_SHA3_512) +_CFG_CORE_LTC_SHAKE128 := $(CFG_CRYPTO_SHAKE128) +_CFG_CORE_LTC_SHAKE256 := $(CFG_CRYPTO_SHAKE256) +endif + +############################################################### +# libtomcrypt (LTC) specifics, phase #2 +############################################################### + +_CFG_CORE_LTC_SHA256_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA256_DESC \ + _CFG_CORE_LTC_SHA224 \ + _CFG_CORE_LTC_SHA256) +_CFG_CORE_LTC_SHA384_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA384_DESC \ + _CFG_CORE_LTC_SHA384) +_CFG_CORE_LTC_SHA512_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA512_DESC \ + _CFG_CORE_LTC_SHA512_256 \ + _CFG_CORE_LTC_SHA512) +_CFG_CORE_LTC_AES_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_AES_DESC \ + _CFG_CORE_LTC_AES) + +_CFG_CORE_LTC_SHA3_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA3_224 \ + _CFG_CORE_LTC_SHA3_256 _CFG_CORE_LTC_SHA3_384 \ + _CFG_CORE_LTC_SHA3_512 _CFG_CORE_LTC_SHAKE128 \ + _CFG_CORE_LTC_SHAKE256) + +# Assign system variables +_CFG_CORE_LTC_CE := $(CFG_CRYPTO_WITH_CE) +_CFG_CORE_LTC_VFP := $(CFG_WITH_VFP) +_CFG_CORE_LTC_BIGNUM_MAX_BITS := $(CFG_CORE_BIGNUM_MAX_BITS) +_CFG_CORE_LTC_PAGER := $(CFG_WITH_PAGER) +ifneq ($(CFG_NUM_THREADS),1) +_CFG_CORE_LTC_OPTEE_THREAD := y +else +_CFG_CORE_LTC_OPTEE_THREAD := n +endif +_CFG_CORE_LTC_HWSUPP_PMULL := $(CFG_HWSUPP_PMULL) + +# Assign aggregated variables +ltc-one-enabled = $(call cfg-one-enabled,$(foreach v,$(1),_CFG_CORE_LTC_$(v))) +_CFG_CORE_LTC_ACIPHER := $(call ltc-one-enabled, RSA DSA DH ECC) +_CFG_CORE_LTC_AUTHENC := $(and $(filter y,$(_CFG_CORE_LTC_AES_DESC)), \ + $(filter y,$(call ltc-one-enabled, CCM GCM))) +_CFG_CORE_LTC_CIPHER := $(call ltc-one-enabled, AES_DESC DES) +_CFG_CORE_LTC_HASH := $(call ltc-one-enabled, MD5 SHA1 SHA224 SHA256 SHA384 \ + SHA512 SHA3_224 SHA3_256 \ + SHA3_384 SHA3_512) +ifeq ($(CFG_CRYPTO_HMAC),y) +_CFG_CORE_LTC_HMAC := $(call ltc-one-enabled, MD5 SHA1 SHA224 SHA256 SHA384 \ + SHA512 SHA3_224 SHA3_256 \ + SHA3_384 SHA3_512) +endif + +_CFG_CORE_LTC_MAC := $(call ltc-one-enabled, HMAC CMAC CBC_MAC) +_CFG_CORE_LTC_CBC := $(call ltc-one-enabled, CBC CBC_MAC) +_CFG_CORE_LTC_ASN1 := $(call ltc-one-enabled, RSA DSA ECC) +_CFG_CORE_LTC_EC25519 := $(call ltc-one-enabled, ED25519 X25519) + +# Enable TEE_ALG_RSASSA_PKCS1_V1_5 algorithm for signing with PKCS#1 v1.5 EMSA +# without ASN.1 around the hash. +ifeq ($(CFG_CRYPTOLIB_NAME),tomcrypt) +CFG_CRYPTO_RSASSA_NA1 ?= y +endif diff --git a/optee/optee_os/core/crypto/aes-cts.c b/optee/optee_os/core/crypto/aes-cts.c new file mode 100644 index 0000000..44142ab --- /dev/null +++ b/optee/optee_os/core/crypto/aes-cts.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#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 cts_ctx { + struct crypto_cipher_ctx ctx; + struct crypto_cipher_ctx *ecb; + struct crypto_cipher_ctx *cbc; + TEE_OperationMode mode; +}; + +static const struct crypto_cipher_ops cts_ops; + +static struct cts_ctx *to_cts_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &cts_ops); + + return container_of(ctx, struct cts_ctx, ctx); +} + +static TEE_Result cts_init(struct crypto_cipher_ctx *ctx, + 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 = TEE_SUCCESS; + struct cts_ctx *c = to_cts_ctx(ctx); + + c->mode = mode; + + res = crypto_cipher_init(c->ecb, mode, key1, key1_len, key2, key2_len, + iv, iv_len); + if (res) + return res; + + return crypto_cipher_init(c->cbc, mode, key1, key1_len, key2, key2_len, + iv, iv_len); +} + +/* + * 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. + */ +static TEE_Result cbc_cts_update(void *cbc_ctx, void *ecb_ctx, + TEE_OperationMode mode, bool last_block, + const uint8_t *data, size_t len, uint8_t *dst) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t tmp2_block[64] = { 0 }; + uint8_t tmp_block[64] = { 0 }; + int len_last_block = 0; + int block_size = 16; + int nb_blocks = 0; + + if (!last_block) + return tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, + mode, last_block, data, len, dst); + + /* Compute the last block length and check constraints */ + 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_do_cipher_update(cbc_ctx, 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_do_cipher_update(cbc_ctx, 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_do_cipher_update(ecb_ctx, 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_do_cipher_update(cbc_ctx, + TEE_ALG_AES_CBC_NOPAD, mode, + 0, data, + (nb_blocks - 2) * + block_size, dst); + if (res != TEE_SUCCESS) + return res; + } + + res = tee_do_cipher_update(cbc_ctx, 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_do_cipher_update(cbc_ctx, 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); + } + return TEE_SUCCESS; +} + +static TEE_Result cts_update(struct crypto_cipher_ctx *ctx, bool last_block, + const uint8_t *data, size_t len, uint8_t *dst) +{ + struct cts_ctx *c = to_cts_ctx(ctx); + + return cbc_cts_update(c->cbc, c->ecb, c->mode, last_block, data, len, + dst); +} + +static void cts_final(struct crypto_cipher_ctx *ctx) +{ + struct cts_ctx *c = to_cts_ctx(ctx); + + crypto_cipher_final(c->cbc); + crypto_cipher_final(c->ecb); +} + +static void cts_free_ctx(struct crypto_cipher_ctx *ctx) +{ + struct cts_ctx *c = to_cts_ctx(ctx); + + crypto_cipher_free_ctx(c->cbc); + crypto_cipher_free_ctx(c->ecb); + free(c); +} + +static void cts_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct cts_ctx *src = to_cts_ctx(src_ctx); + struct cts_ctx *dst = to_cts_ctx(dst_ctx); + + crypto_cipher_copy_state(dst->cbc, src->cbc); + crypto_cipher_copy_state(dst->ecb, src->ecb); + dst->mode = src->mode; +} + +static const struct crypto_cipher_ops cts_ops = { + .init = cts_init, + .update = cts_update, + .final = cts_final, + .free_ctx = cts_free_ctx, + .copy_state = cts_copy_state, +}; + +TEE_Result crypto_aes_cts_alloc_ctx(struct crypto_cipher_ctx **ctx) +{ + TEE_Result res = TEE_SUCCESS; + struct cts_ctx *c = calloc(1, sizeof(*c)); + + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + res = crypto_aes_ecb_alloc_ctx(&c->ecb); + if (res) + goto err; + res = crypto_aes_cbc_alloc_ctx(&c->cbc); + if (res) + goto err; + + c->ctx.ops = &cts_ops; + *ctx = &c->ctx; + + return TEE_SUCCESS; +err: + crypto_cipher_free_ctx(c->ecb); + free(c); + + return res; +} diff --git a/optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c b/optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c new file mode 100644 index 0000000..000ab00 --- /dev/null +++ b/optee/optee_os/core/crypto/aes-gcm-ghash-tbl.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (c) 2017-2020, Linaro Limited + * + * NIST SP800-38D compliant GCM implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + * + * See also: + * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/ +gcm-revised-spec.pdf + * + * We use the algorithm described as Shoup's method with 4-bit tables in + * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. + */ + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +void internal_aes_gcm_ghash_gen_tbl(struct internal_ghash_key *ghash_key, + const struct internal_aes_gcm_key *ek) +{ + int i, j; + uint64_t vl, vh; + unsigned char h[16]; + + memset(h, 0, 16); + crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, h, h); + + vh = get_be64(h); + vl = get_be64(h + 8); + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ghash_key->HL[8] = vl; + ghash_key->HH[8] = vh; + + /* 0 corresponds to 0 in GF(2^128) */ + ghash_key->HH[0] = 0; + ghash_key->HL[0] = 0; + + for (i = 4; i > 0; i >>= 1) { + uint32_t T = (vl & 1) * 0xe1000000U; + + vl = (vh << 63) | (vl >> 1); + vh = (vh >> 1) ^ ((uint64_t)T << 32); + + ghash_key->HL[i] = vl; + ghash_key->HH[i] = vh; + } + + for (i = 2; i <= 8; i *= 2) { + uint64_t *HiL = ghash_key->HL + i; + uint64_t *HiH = ghash_key->HH + i; + + vh = *HiH; + vl = *HiL; + for (j = 1; j < i; j++) { + HiH[j] = vh ^ ghash_key->HH[j]; + HiL[j] = vl ^ ghash_key->HL[j]; + } + } +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = { + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +void internal_aes_gcm_ghash_mult_tbl(struct internal_ghash_key *ghash_key, + const unsigned char x[16], + unsigned char output[16]) +{ + int i = 0; + unsigned char lo = 0, hi = 0, rem = 0; + uint64_t zh = 0, zl = 0; + + lo = x[15] & 0xf; + + zh = ghash_key->HH[lo]; + zl = ghash_key->HL[lo]; + + for (i = 15; i >= 0; i--) { + lo = x[i] & 0xf; + hi = x[i] >> 4; + + if (i != 15) { + rem = (unsigned char)zl & 0xf; + zl = (zh << 60) | (zl >> 4); + zh = (zh >> 4); + zh ^= (uint64_t)last4[rem] << 48; + zh ^= ghash_key->HH[lo]; + zl ^= ghash_key->HL[lo]; + } + + rem = (unsigned char)zl & 0xf; + zl = (zh << 60) | (zl >> 4); + zh = (zh >> 4); + zh ^= (uint64_t)last4[rem] << 48; + zh ^= ghash_key->HH[hi]; + zl ^= ghash_key->HL[hi]; + } + + put_be64(output, zh); + put_be64(output + 8, zl); +} diff --git a/optee/optee_os/core/crypto/aes-gcm-sw.c b/optee/optee_os/core/crypto/aes-gcm-sw.c new file mode 100644 index 0000000..9b40400 --- /dev/null +++ b/optee/optee_os/core/crypto/aes-gcm-sw.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek) +{ +#ifdef CFG_AES_GCM_TABLE_BASED + internal_aes_gcm_ghash_gen_tbl(&state->ghash_key, ek); +#else + crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, + state->ctr, state->ghash_key.hash_subkey); +#endif +} + +static void ghash_update_block(struct internal_aes_gcm_state *state, + const void *data) +{ + void *y = state->hash_state; + + internal_aes_gcm_xor_block(y, data); +#ifdef CFG_AES_GCM_TABLE_BASED + internal_aes_gcm_ghash_mult_tbl(&state->ghash_key, y, y); +#else + internal_aes_gcm_gfmul(state->ghash_key.hash_subkey, y, y); +#endif +} + +void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state, + const void *head, const void *data, + size_t num_blocks) +{ + size_t n = 0; + + if (head) + ghash_update_block(state, head); + + if (data) + for (n = 0; n < num_blocks; n++) + ghash_update_block(state, + (const uint8_t *)data + + n * TEE_AES_BLOCK_SIZE); +} + +static void encrypt_block(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *enc_key, + const uint64_t src[2], uint64_t dst[2]) +{ + void *buf_cryp = state->buf_cryp; + + internal_aes_gcm_xor_block(buf_cryp, src); + internal_aes_gcm_ghash_update(state, buf_cryp, NULL, 0); + memcpy(dst, buf_cryp, sizeof(state->buf_cryp)); + + crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data), + enc_key->rounds, state->ctr, state->buf_cryp); + internal_aes_gcm_inc_ctr(state); +} + +static void encrypt_pl(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + const uint8_t *src, size_t num_blocks, uint8_t *dst) +{ + size_t n = 0; + + if (IS_ALIGNED_WITH_TYPE(src, uint64_t)) { + for (n = 0; n < num_blocks; n++) { + const void *s = src + n * TEE_AES_BLOCK_SIZE; + void *d = dst + n * TEE_AES_BLOCK_SIZE; + + encrypt_block(state, ek, s, d); + } + } else { + for (n = 0; n < num_blocks; n++) { + uint64_t tmp[2] = { 0 }; + void *d = dst + n * TEE_AES_BLOCK_SIZE; + + memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp)); + encrypt_block(state, ek, tmp, d); + } + } +} + +static void decrypt_block(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *enc_key, + const uint64_t src[2], uint64_t dst[2]) +{ + void *buf_cryp = state->buf_cryp; + + crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data), + enc_key->rounds, state->ctr, buf_cryp); + internal_aes_gcm_inc_ctr(state); + + internal_aes_gcm_xor_block(buf_cryp, src); + internal_aes_gcm_ghash_update(state, src, NULL, 0); + memcpy(dst, buf_cryp, sizeof(state->buf_cryp)); +} + +static void decrypt_pl(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + const uint8_t *src, size_t num_blocks, uint8_t *dst) +{ + size_t n = 0; + + if (IS_ALIGNED_WITH_TYPE(src, uint64_t)) { + for (n = 0; n < num_blocks; n++) { + const void *s = src + n * TEE_AES_BLOCK_SIZE; + void *d = dst + n * TEE_AES_BLOCK_SIZE; + + decrypt_block(state, ek, s, d); + } + } else { + for (n = 0; n < num_blocks; n++) { + uint64_t tmp[2] = { 0 }; + void *d = dst + n * TEE_AES_BLOCK_SIZE; + + memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp)); + decrypt_block(state, ek, tmp, d); + } + } +} + +void +internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + TEE_OperationMode m, const void *src, + size_t num_blocks, void *dst) +{ + assert(!state->buf_pos && num_blocks); + + if (m == TEE_MODE_ENCRYPT) + encrypt_pl(state, ek, src, num_blocks, dst); + else + decrypt_pl(state, ek, src, num_blocks, dst); +} diff --git a/optee/optee_os/core/crypto/aes-gcm.c b/optee/optee_os/core/crypto/aes-gcm.c new file mode 100644 index 0000000..423b6f3 --- /dev/null +++ b/optee/optee_os/core/crypto/aes-gcm.c @@ -0,0 +1,549 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void xor_buf(uint8_t *dst, const uint8_t *src, size_t len) +{ + size_t n; + + for (n = 0; n < len; n++) + dst[n] ^= src[n]; +} + + +static void ghash_update_pad_zero(struct internal_aes_gcm_state *state, + const uint8_t *data, size_t len) +{ + size_t n = len / TEE_AES_BLOCK_SIZE; + uint64_t block[2]; + + if (n) { + if (internal_aes_gcm_ptr_is_block_aligned(data)) { + internal_aes_gcm_ghash_update(state, NULL, data, n); + } else { + size_t m; + + for (m = 0; m < n; m++) { + + memcpy(block, data + m * sizeof(block), + sizeof(block)); + internal_aes_gcm_ghash_update(state, NULL, + (void *)block, 1); + } + } + } + + if (len - n * TEE_AES_BLOCK_SIZE) { + memset(block, 0, sizeof(block)); + memcpy(block, data + n * TEE_AES_BLOCK_SIZE, + len - n * TEE_AES_BLOCK_SIZE); + internal_aes_gcm_ghash_update(state, block, NULL, 0); + } +} + +static void ghash_update_lengths(struct internal_aes_gcm_state *state, + uint32_t l1, uint32_t l2) +{ + uint64_t len_fields[2] = { + TEE_U64_TO_BIG_ENDIAN(l1 * 8), + TEE_U64_TO_BIG_ENDIAN(l2 * 8) + }; + + COMPILE_TIME_ASSERT(sizeof(len_fields) == TEE_AES_BLOCK_SIZE); + internal_aes_gcm_ghash_update(state, (uint8_t *)len_fields, NULL, 0); +} + +static TEE_Result __gcm_init(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + TEE_OperationMode mode, const void *nonce, + size_t nonce_len, size_t tag_len) +{ + COMPILE_TIME_ASSERT(sizeof(state->ctr) == TEE_AES_BLOCK_SIZE); + + if (tag_len > sizeof(state->buf_tag)) + return TEE_ERROR_BAD_PARAMETERS; + + memset(state, 0, sizeof(*state)); + + state->tag_len = tag_len; + internal_aes_gcm_set_key(state, ek); + + if (nonce_len == (96 / 8)) { + memcpy(state->ctr, nonce, nonce_len); + internal_aes_gcm_inc_ctr(state); + } else { + ghash_update_pad_zero(state, nonce, nonce_len); + ghash_update_lengths(state, 0, nonce_len); + + memcpy(state->ctr, state->hash_state, sizeof(state->ctr)); + memset(state->hash_state, 0, sizeof(state->hash_state)); + } + + crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, + state->ctr, state->buf_tag); + internal_aes_gcm_inc_ctr(state); + if (mode == TEE_MODE_ENCRYPT) { + /* + * Encryption uses the pre-encrypted xor-buffer to encrypt + * while decryption encrypts the xor-buffer when needed + * instead. + * + * The reason for this is that the combined encryption and + * ghash implementation does both operations intertwined. + * In the decrypt case the xor-buffer is needed at the end + * of processing each block, while the encryption case + * needs xor-buffer before processing each block. + * + * In a pure software implementation we wouldn't have any + * use for this kind of optimization, but since this + * AES-GCM implementation is aimed at being combined with + * accelerated routines it's more convenient to always have + * this optimization activated. + */ + crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, + state->ctr, state->buf_cryp); + internal_aes_gcm_inc_ctr(state); + } + + return TEE_SUCCESS; +} + +TEE_Result internal_aes_gcm_init(struct internal_aes_gcm_ctx *ctx, + TEE_OperationMode mode, const void *key, + size_t key_len, const void *nonce, + size_t nonce_len, size_t tag_len) +{ + TEE_Result res = TEE_SUCCESS; + struct internal_aes_gcm_key *ek = &ctx->key; + + res = crypto_aes_expand_enc_key(key, key_len, ek->data, + sizeof(ek->data), &ek->rounds); + if (res) + return res; + + return __gcm_init(&ctx->state, ek, mode, nonce, nonce_len, tag_len); +} + +static TEE_Result __gcm_update_aad(struct internal_aes_gcm_state *state, + const void *data, size_t len) +{ + const uint8_t *d = data; + size_t l = len; + const uint8_t *head = NULL; + size_t n; + + if (state->payload_bytes) + return TEE_ERROR_BAD_PARAMETERS; + + state->aad_bytes += len; + + while (l) { + if (state->buf_pos || + !internal_aes_gcm_ptr_is_block_aligned(d) || + l < TEE_AES_BLOCK_SIZE) { + n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l); + memcpy(state->buf_hash + state->buf_pos, d, n); + state->buf_pos += n; + + if (state->buf_pos != TEE_AES_BLOCK_SIZE) + return TEE_SUCCESS; + + state->buf_pos = 0; + head = state->buf_hash; + d += n; + l -= n; + } + + if (internal_aes_gcm_ptr_is_block_aligned(d)) + n = l / TEE_AES_BLOCK_SIZE; + else + n = 0; + + internal_aes_gcm_ghash_update(state, head, d, n); + l -= n * TEE_AES_BLOCK_SIZE; + d += n * TEE_AES_BLOCK_SIZE; + } + + return TEE_SUCCESS; +} + +TEE_Result internal_aes_gcm_update_aad(struct internal_aes_gcm_ctx *ctx, + const void *data, size_t len) +{ + return __gcm_update_aad(&ctx->state, data, len); +} + +static TEE_Result +__gcm_update_payload(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + TEE_OperationMode mode, const void *src, + size_t len, void *dst) +{ + size_t n; + const uint8_t *s = src; + uint8_t *d = dst; + size_t l = len; + + if (!state->payload_bytes && state->buf_pos) { + /* AAD part done, finish up the last bits. */ + memset(state->buf_hash + state->buf_pos, 0, + TEE_AES_BLOCK_SIZE - state->buf_pos); + internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0); + state->buf_pos = 0; + } + + state->payload_bytes += len; + + while (l) { + if (state->buf_pos || l < TEE_AES_BLOCK_SIZE) { + n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l); + + if (!state->buf_pos && mode == TEE_MODE_DECRYPT) + crypto_aes_enc_block(ek->data, sizeof(ek->data), + ek->rounds, state->ctr, + state->buf_cryp); + + xor_buf(state->buf_cryp + state->buf_pos, s, n); + memcpy(d, state->buf_cryp + state->buf_pos, n); + if (mode == TEE_MODE_ENCRYPT) + memcpy(state->buf_hash + state->buf_pos, + state->buf_cryp + state->buf_pos, n); + else + memcpy(state->buf_hash + state->buf_pos, s, n); + + state->buf_pos += n; + + if (state->buf_pos != TEE_AES_BLOCK_SIZE) + return TEE_SUCCESS; + + internal_aes_gcm_ghash_update(state, state->buf_hash, + NULL, 0); + state->buf_pos = 0; + d += n; + s += n; + l -= n; + + if (mode == TEE_MODE_ENCRYPT) + crypto_aes_enc_block(ek->data, sizeof(ek->data), + ek->rounds, state->ctr, + state->buf_cryp); + internal_aes_gcm_inc_ctr(state); + } else { + n = l / TEE_AES_BLOCK_SIZE; + internal_aes_gcm_update_payload_blocks(state, ek, mode, + s, n, d); + s += n * TEE_AES_BLOCK_SIZE; + d += n * TEE_AES_BLOCK_SIZE; + l -= n * TEE_AES_BLOCK_SIZE; + } + } + + return TEE_SUCCESS; +} + +TEE_Result internal_aes_gcm_update_payload(struct internal_aes_gcm_ctx *ctx, + TEE_OperationMode mode, + const void *src, size_t len, + void *dst) +{ + return __gcm_update_payload(&ctx->state, &ctx->key, mode, src, len, + dst); +} + +static TEE_Result operation_final(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *enc_key, + TEE_OperationMode m, const uint8_t *src, + size_t len, uint8_t *dst) +{ + TEE_Result res; + + res = __gcm_update_payload(state, enc_key, m, src, len, dst); + if (res) + return res; + + if (state->buf_pos) { + memset(state->buf_hash + state->buf_pos, 0, + sizeof(state->buf_hash) - state->buf_pos); + internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0); + } + + ghash_update_lengths(state, state->aad_bytes, state->payload_bytes); + /* buf_tag was filled in with the first counter block aes_gcm_init() */ + xor_buf(state->buf_tag, state->hash_state, state->tag_len); + + return TEE_SUCCESS; +} + +static TEE_Result __gcm_enc_final(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *enc_key, + const void *src, size_t len, void *dst, + void *tag, size_t *tag_len) +{ + TEE_Result res; + + if (*tag_len < state->tag_len) + return TEE_ERROR_SHORT_BUFFER; + + res = operation_final(state, enc_key, TEE_MODE_ENCRYPT, src, len, dst); + if (res) + return res; + + memcpy(tag, state->buf_tag, state->tag_len); + *tag_len = state->tag_len; + + return TEE_SUCCESS; +} + +TEE_Result internal_aes_gcm_enc_final(struct internal_aes_gcm_ctx *ctx, + const void *src, size_t len, void *dst, + void *tag, size_t *tag_len) +{ + return __gcm_enc_final(&ctx->state, &ctx->key, src, len, dst, tag, + tag_len); +} + +static TEE_Result __gcm_dec_final(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *enc_key, + const void *src, size_t len, void *dst, + const void *tag, size_t tag_len) +{ + TEE_Result res; + + if (tag_len != state->tag_len) + return TEE_ERROR_MAC_INVALID; + + res = operation_final(state, enc_key, TEE_MODE_DECRYPT, src, len, dst); + if (res) + return res; + + if (consttime_memcmp(state->buf_tag, tag, tag_len)) + return TEE_ERROR_MAC_INVALID; + + return TEE_SUCCESS; +} + +TEE_Result internal_aes_gcm_dec_final(struct internal_aes_gcm_ctx *ctx, + const void *src, size_t len, void *dst, + const void *tag, size_t tag_len) +{ + return __gcm_dec_final(&ctx->state, &ctx->key, src, len, dst, tag, + tag_len); +} + +void internal_aes_gcm_inc_ctr(struct internal_aes_gcm_state *state) +{ + uint64_t c = 0; + + c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]) + 1; + state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c); + if (!c) { + c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[0]) + 1; + state->ctr[0] = TEE_U64_TO_BIG_ENDIAN(c); + } +} + +void internal_aes_gcm_dec_ctr(struct internal_aes_gcm_state *state) +{ + uint64_t c = 0; + + c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]) - 1; + state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c); + if (c == UINT64_MAX) { + c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[0]) - 1; + state->ctr[0] = TEE_U64_TO_BIG_ENDIAN(c); + } +} + +TEE_Result internal_aes_gcm_enc(const struct internal_aes_gcm_key *enc_key, + const void *nonce, size_t nonce_len, + const void *aad, size_t aad_len, + const void *src, size_t len, void *dst, + void *tag, size_t *tag_len) +{ + TEE_Result res; + struct internal_aes_gcm_state state; + + res = __gcm_init(&state, enc_key, TEE_MODE_ENCRYPT, nonce, nonce_len, + *tag_len); + if (res) + return res; + + if (aad) { + res = __gcm_update_aad(&state, aad, aad_len); + if (res) + return res; + } + + return __gcm_enc_final(&state, enc_key, src, len, dst, tag, tag_len); +} + +TEE_Result internal_aes_gcm_dec(const struct internal_aes_gcm_key *enc_key, + const void *nonce, size_t nonce_len, + const void *aad, size_t aad_len, + const void *src, size_t len, void *dst, + const void *tag, size_t tag_len) +{ + TEE_Result res; + struct internal_aes_gcm_state state; + + res = __gcm_init(&state, enc_key, TEE_MODE_DECRYPT, nonce, nonce_len, + tag_len); + if (res) + return res; + + if (aad) { + res = __gcm_update_aad(&state, aad, aad_len); + if (res) + return res; + } + + return __gcm_dec_final(&state, enc_key, src, len, dst, tag, tag_len); +} + + +#ifndef CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB +#include +#include + +struct aes_gcm_ctx { + struct crypto_authenc_ctx aec; + struct internal_aes_gcm_ctx ctx; +}; + +static const struct crypto_authenc_ops aes_gcm_ops; + +static struct aes_gcm_ctx * +to_aes_gcm_ctx(struct crypto_authenc_ctx *aec) +{ + assert(aec->ops == &aes_gcm_ops); + + return container_of(aec, struct aes_gcm_ctx, aec); +} + +TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret) +{ + struct aes_gcm_ctx *ctx = calloc(1, sizeof(*ctx)); + + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + ctx->aec.ops = &aes_gcm_ops; + + *ctx_ret = &ctx->aec; + + return TEE_SUCCESS; +} + +static void aes_gcm_free_ctx(struct crypto_authenc_ctx *aec) +{ + free(to_aes_gcm_ctx(aec)); +} + +static void aes_gcm_copy_state(struct crypto_authenc_ctx *dst_ctx, + struct crypto_authenc_ctx *src_ctx) +{ + to_aes_gcm_ctx(dst_ctx)->ctx = to_aes_gcm_ctx(src_ctx)->ctx; +} + +static TEE_Result aes_gcm_init(struct crypto_authenc_ctx *aec, + 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 __unused, + size_t payload_len __unused) +{ + return internal_aes_gcm_init(&to_aes_gcm_ctx(aec)->ctx, mode, key, + key_len, nonce, nonce_len, tag_len); +} + +static TEE_Result aes_gcm_update_aad(struct crypto_authenc_ctx *aec, + const uint8_t *data, size_t len) +{ + return internal_aes_gcm_update_aad(&to_aes_gcm_ctx(aec)->ctx, data, + len); +} + +static TEE_Result aes_gcm_update_payload(struct crypto_authenc_ctx *aec, + TEE_OperationMode m, + const uint8_t *src, size_t len, + uint8_t *dst) +{ + return internal_aes_gcm_update_payload(&to_aes_gcm_ctx(aec)->ctx, + m, src, len, dst); +} + +static TEE_Result aes_gcm_enc_final(struct crypto_authenc_ctx *aec, + const uint8_t *src, size_t len, + uint8_t *dst, uint8_t *tag, size_t *tag_len) +{ + return internal_aes_gcm_enc_final(&to_aes_gcm_ctx(aec)->ctx, src, len, + dst, tag, tag_len); +} + +static TEE_Result aes_gcm_dec_final(struct crypto_authenc_ctx *aec, + const uint8_t *src, size_t len, + uint8_t *dst, const uint8_t *tag, + size_t tag_len) +{ + return internal_aes_gcm_dec_final(&to_aes_gcm_ctx(aec)->ctx, src, len, + dst, tag, tag_len); +} + +static void aes_gcm_final(struct crypto_authenc_ctx *aec __unused) +{ +} + +static const struct crypto_authenc_ops aes_gcm_ops = { + .init = aes_gcm_init, + .update_aad = aes_gcm_update_aad, + .update_payload = aes_gcm_update_payload, + .enc_final = aes_gcm_enc_final, + .dec_final = aes_gcm_dec_final, + .final = aes_gcm_final, + .free_ctx = aes_gcm_free_ctx, + .copy_state = aes_gcm_copy_state, +}; + +/* + * internal_aes_gcm_gfmul() is based on ghash_gfmul() from + * https://github.com/openbsd/src/blob/master/sys/crypto/gmac.c + */ +void internal_aes_gcm_gfmul(const uint64_t X[2], const uint64_t Y[2], + uint64_t product[2]) +{ + uint64_t y[2] = { 0 }; + uint64_t z[2] = { 0 }; + const uint8_t *x = (const uint8_t *)X; + uint32_t mul = 0; + size_t n = 0; + + y[0] = TEE_U64_FROM_BIG_ENDIAN(Y[0]); + y[1] = TEE_U64_FROM_BIG_ENDIAN(Y[1]); + + for (n = 0; n < TEE_AES_BLOCK_SIZE * 8; n++) { + /* update Z */ + if (x[n >> 3] & (1 << (~n & 7))) + internal_aes_gcm_xor_block(z, y); + + /* update Y */ + mul = y[1] & 1; + y[1] = (y[0] << 63) | (y[1] >> 1); + y[0] = (y[0] >> 1) ^ (0xe100000000000000 * mul); + } + + product[0] = TEE_U64_TO_BIG_ENDIAN(z[0]); + product[1] = TEE_U64_TO_BIG_ENDIAN(z[1]); +} +#endif /*!CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB*/ diff --git a/optee/optee_os/core/crypto/cbc-mac.c b/optee/optee_os/core/crypto/cbc-mac.c new file mode 100644 index 0000000..c38b058 --- /dev/null +++ b/optee/optee_os/core/crypto/cbc-mac.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CBCMAC_MAX_BLOCK_LEN 16 + +struct crypto_cbc_mac_ctx { + struct crypto_mac_ctx ctx; + void *cbc_ctx; + uint32_t cbc_algo; + uint8_t block[CBCMAC_MAX_BLOCK_LEN]; + uint8_t digest[CBCMAC_MAX_BLOCK_LEN]; + unsigned char current_block_len; + unsigned char block_len; + bool is_computed; + bool pkcs5_pad; +}; + +static const struct crypto_mac_ops crypto_cbc_mac_ops; + +static struct crypto_cbc_mac_ctx *to_cbc_mac_ctx(struct crypto_mac_ctx *ctx) +{ + assert(ctx && ctx->ops == &crypto_cbc_mac_ops); + + return container_of(ctx, struct crypto_cbc_mac_ctx, ctx); +} + +static TEE_Result crypto_cbc_mac_init(struct crypto_mac_ctx *ctx, + const uint8_t *key, size_t len) +{ + struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); + + memset(mc->block, 0, sizeof(mc->block)); + memset(mc->digest, 0, sizeof(mc->digest)); + mc->current_block_len = 0; + mc->is_computed = false; + + /* IV should be zero and mc->block happens to be zero at this stage */ + return crypto_cipher_init(mc->cbc_ctx, TEE_MODE_ENCRYPT, key, len, + NULL, 0, mc->block, mc->block_len); +} + +static TEE_Result crypto_cbc_mac_update(struct crypto_mac_ctx *ctx, + const uint8_t *data, size_t len) +{ + size_t nblocks = 0; + size_t out_len = 0; + uint8_t *out_tmp = NULL; + uint8_t *out = NULL; + TEE_Result res = TEE_SUCCESS; + struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); + + if ((mc->current_block_len > 0) && + (len + mc->current_block_len >= mc->block_len)) { + size_t pad_len = mc->block_len - mc->current_block_len; + + memcpy(mc->block + mc->current_block_len, data, pad_len); + data += pad_len; + len -= pad_len; + res = crypto_cipher_update(mc->cbc_ctx, TEE_MODE_ENCRYPT, + false, mc->block, mc->block_len, + mc->digest); + if (res) + return res; + mc->is_computed = 1; + mc->current_block_len = 0; + } + + nblocks = MIN(len / mc->block_len, + (size_t)CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS); + if (nblocks > 1) + out_tmp = malloc(nblocks * mc->block_len); + + while (len >= mc->block_len) { + nblocks = MIN(len / mc->block_len, + (size_t)CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS); + + if (nblocks > 1 && out_tmp) { + out_len = nblocks * mc->block_len; + out = out_tmp; + } else { + out_len = mc->block_len; + out = mc->digest; + nblocks = 1; + } + + res = crypto_cipher_update(mc->cbc_ctx, TEE_MODE_ENCRYPT, + false, data, out_len, out); + if (res) + goto out; + mc->is_computed = 1; + data += out_len; + len -= out_len; + if (nblocks > 1 && len < mc->block_len) { + assert(out_tmp); + /* Copy last block of output */ + memcpy(mc->digest, out_tmp + out_len - mc->block_len, + mc->block_len); + } + } + + if (len > 0) { + assert(mc->current_block_len + len < mc->block_len); + memcpy(mc->block + mc->current_block_len, data, len); + mc->current_block_len += len; + } + +out: + free(out_tmp); + return res; +} + +static TEE_Result crypto_cbc_mac_final(struct crypto_mac_ctx *ctx, + uint8_t *digest, size_t digest_len) +{ + struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); + + if (mc->pkcs5_pad) { + /* + * 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 + */ + size_t pad_len = mc->block_len - mc->current_block_len; + + memset(mc->block + mc->current_block_len, pad_len, pad_len); + mc->current_block_len = 0; + if (crypto_cbc_mac_update(ctx, mc->block, mc->block_len)) + return TEE_ERROR_BAD_STATE; + } + + if (!mc->is_computed || mc->current_block_len) + return TEE_ERROR_BAD_STATE; + + memcpy(digest, mc->digest, MIN(digest_len, mc->block_len)); + crypto_cipher_final(mc->cbc_ctx); + + return TEE_SUCCESS; +} + +static void crypto_cbc_mac_free_ctx(struct crypto_mac_ctx *ctx) +{ + struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); + + crypto_cipher_free_ctx(mc->cbc_ctx); + free(mc); +} + +static void crypto_cbc_mac_copy_state(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx) +{ + struct crypto_cbc_mac_ctx *dst = to_cbc_mac_ctx(dst_ctx); + struct crypto_cbc_mac_ctx *src = to_cbc_mac_ctx(src_ctx); + + assert(dst->block_len == src->block_len); + assert(dst->pkcs5_pad == src->pkcs5_pad); + assert(dst->cbc_algo == src->cbc_algo); + + crypto_cipher_copy_state(dst->cbc_ctx, src->cbc_ctx); + memcpy(dst->block, src->block, sizeof(dst->block)); + memcpy(dst->digest, src->digest, sizeof(dst->digest)); + dst->current_block_len = src->current_block_len; + dst->is_computed = src->is_computed; +} + +static const struct crypto_mac_ops crypto_cbc_mac_ops = { + .init = crypto_cbc_mac_init, + .update = crypto_cbc_mac_update, + .final = crypto_cbc_mac_final, + .free_ctx = crypto_cbc_mac_free_ctx, + .copy_state = crypto_cbc_mac_copy_state, +}; + +static TEE_Result crypto_cbc_mac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, + uint32_t cbc_algo, bool pkcs5_pad) +{ + TEE_Result res; + void *cbc_ctx = NULL; + struct crypto_cbc_mac_ctx *ctx = NULL; + size_t block_size = 0; + + res = crypto_cipher_get_block_size(cbc_algo, &block_size); + if (res) + return res; + + res = crypto_cipher_alloc_ctx(&cbc_ctx, cbc_algo); + if (res) + return res; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) { + crypto_cipher_free_ctx(cbc_ctx); + return TEE_ERROR_OUT_OF_MEMORY; + } + + ctx->cbc_ctx = cbc_ctx; + ctx->cbc_algo = cbc_algo; + ctx->pkcs5_pad = pkcs5_pad; + ctx->block_len = block_size; + ctx->ctx.ops = &crypto_cbc_mac_ops; + *ctx_ret = &ctx->ctx; + + return TEE_SUCCESS; +} + +TEE_Result crypto_aes_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_AES_CBC_NOPAD, false); +} + +TEE_Result crypto_aes_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_AES_CBC_NOPAD, true); +} + +TEE_Result crypto_des_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES_CBC_NOPAD, false); +} + +TEE_Result crypto_des_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES_CBC_NOPAD, true); +} + +TEE_Result crypto_des3_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES3_CBC_NOPAD, false); +} + +TEE_Result crypto_des3_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES3_CBC_NOPAD, true); +} diff --git a/optee/optee_os/core/crypto/crypto.c b/optee/optee_os/core/crypto/crypto.c new file mode 100644 index 0000000..3552887 --- /dev/null +++ b/optee/optee_os/core/crypto/crypto.c @@ -0,0 +1,930 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + * Copyright 2020 NXP + * Copyright 2021, SumUp Service GmbH + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result crypto_hash_alloc_ctx(void **ctx, uint32_t algo) +{ + TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_hash_ctx *c = NULL; + + /* + * Use default cryptographic implementation if no matching + * drvcrypt device. + */ + res = drvcrypt_hash_alloc_ctx(&c, algo); + + if (res == TEE_ERROR_NOT_IMPLEMENTED) { + switch (algo) { + case TEE_ALG_MD5: + res = crypto_md5_alloc_ctx(&c); + break; + case TEE_ALG_SHA1: + res = crypto_sha1_alloc_ctx(&c); + break; + case TEE_ALG_SHA224: + res = crypto_sha224_alloc_ctx(&c); + break; + case TEE_ALG_SHA256: + res = crypto_sha256_alloc_ctx(&c); + break; + case TEE_ALG_SHA384: + res = crypto_sha384_alloc_ctx(&c); + break; + case TEE_ALG_SHA512: + res = crypto_sha512_alloc_ctx(&c); + break; + case TEE_ALG_SHA3_224: + res = crypto_sha3_224_alloc_ctx(&c); + break; + case TEE_ALG_SHA3_256: + res = crypto_sha3_256_alloc_ctx(&c); + break; + case TEE_ALG_SHA3_384: + res = crypto_sha3_384_alloc_ctx(&c); + break; + case TEE_ALG_SHA3_512: + res = crypto_sha3_512_alloc_ctx(&c); + break; + case TEE_ALG_SHAKE128: + res = crypto_shake128_alloc_ctx(&c); + break; + case TEE_ALG_SHAKE256: + res = crypto_shake256_alloc_ctx(&c); + break; + case TEE_ALG_SM3: + res = crypto_sm3_alloc_ctx(&c); + break; + default: + break; + } + } + + if (!res) + *ctx = c; + + return res; +} + +static const struct crypto_hash_ops *hash_ops(void *ctx) +{ + struct crypto_hash_ctx *c = ctx; + + assert(c && c->ops); + + return c->ops; +} + +void crypto_hash_free_ctx(void *ctx) +{ + if (ctx) + hash_ops(ctx)->free_ctx(ctx); +} + +void crypto_hash_copy_state(void *dst_ctx, void *src_ctx) +{ + hash_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); +} + +TEE_Result crypto_hash_init(void *ctx) +{ + return hash_ops(ctx)->init(ctx); +} + +TEE_Result crypto_hash_update(void *ctx, const uint8_t *data, size_t len) +{ + return hash_ops(ctx)->update(ctx, data, len); +} + +TEE_Result crypto_hash_final(void *ctx, uint8_t *digest, size_t len) +{ + return hash_ops(ctx)->final(ctx, digest, len); +} + +TEE_Result crypto_cipher_alloc_ctx(void **ctx, uint32_t algo) +{ + TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_cipher_ctx *c = NULL; + + /* + * Use default cryptographic implementation if no matching + * drvcrypt device. + */ + res = drvcrypt_cipher_alloc_ctx(&c, algo); + + if (res == TEE_ERROR_NOT_IMPLEMENTED) { + switch (algo) { + case TEE_ALG_AES_ECB_NOPAD: + res = crypto_aes_ecb_alloc_ctx(&c); + break; + case TEE_ALG_AES_CBC_NOPAD: + res = crypto_aes_cbc_alloc_ctx(&c); + break; + case TEE_ALG_AES_CTR: + res = crypto_aes_ctr_alloc_ctx(&c); + break; + case TEE_ALG_AES_CTS: + res = crypto_aes_cts_alloc_ctx(&c); + break; + case TEE_ALG_AES_XTS: + res = crypto_aes_xts_alloc_ctx(&c); + break; + case TEE_ALG_DES_ECB_NOPAD: + res = crypto_des_ecb_alloc_ctx(&c); + break; + case TEE_ALG_DES3_ECB_NOPAD: + res = crypto_des3_ecb_alloc_ctx(&c); + break; + case TEE_ALG_DES_CBC_NOPAD: + res = crypto_des_cbc_alloc_ctx(&c); + break; + case TEE_ALG_DES3_CBC_NOPAD: + res = crypto_des3_cbc_alloc_ctx(&c); + break; + case TEE_ALG_SM4_ECB_NOPAD: + res = crypto_sm4_ecb_alloc_ctx(&c); + break; + case TEE_ALG_SM4_CBC_NOPAD: + res = crypto_sm4_cbc_alloc_ctx(&c); + break; + case TEE_ALG_SM4_CTR: + res = crypto_sm4_ctr_alloc_ctx(&c); + break; + case TEE_ALG_SM4_XTS: + res = crypto_sm4_xts_alloc_ctx(&c); + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + } + + if (!res) + *ctx = c; + + return res; +} + +static const struct crypto_cipher_ops *cipher_ops(void *ctx) +{ + struct crypto_cipher_ctx *c = ctx; + + assert(c && c->ops); + + return c->ops; +} + +void crypto_cipher_free_ctx(void *ctx) +{ + if (ctx) + cipher_ops(ctx)->free_ctx(ctx); +} + +void crypto_cipher_copy_state(void *dst_ctx, void *src_ctx) +{ + cipher_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); +} + +TEE_Result crypto_cipher_init(void *ctx, 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) +{ + if (mode != TEE_MODE_DECRYPT && mode != TEE_MODE_ENCRYPT) + return TEE_ERROR_BAD_PARAMETERS; + + return cipher_ops(ctx)->init(ctx, mode, key1, key1_len, key2, key2_len, + iv, iv_len); +} + +TEE_Result crypto_cipher_update(void *ctx, TEE_OperationMode mode __unused, + bool last_block, const uint8_t *data, + size_t len, uint8_t *dst) +{ + return cipher_ops(ctx)->update(ctx, last_block, data, len, dst); +} + +void crypto_cipher_final(void *ctx) +{ + cipher_ops(ctx)->final(ctx); +} + +TEE_Result crypto_cipher_get_block_size(uint32_t algo, size_t *size) +{ + uint32_t class = TEE_ALG_GET_CLASS(algo); + + if (class != TEE_OPERATION_CIPHER && class != TEE_OPERATION_MAC && + class != TEE_OPERATION_AE) + return TEE_ERROR_BAD_PARAMETERS; + + switch (TEE_ALG_GET_MAIN_ALG(algo)) { + case TEE_MAIN_ALGO_AES: + *size = TEE_AES_BLOCK_SIZE; + return TEE_SUCCESS; + case TEE_MAIN_ALGO_DES: + case TEE_MAIN_ALGO_DES3: + *size = TEE_DES_BLOCK_SIZE; + return TEE_SUCCESS; + case TEE_MAIN_ALGO_SM4: + *size = TEE_SM4_BLOCK_SIZE; + return TEE_SUCCESS; + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} + +TEE_Result crypto_mac_alloc_ctx(void **ctx, uint32_t algo) +{ + TEE_Result res = TEE_SUCCESS; + struct crypto_mac_ctx *c = NULL; + + /* + * Use default cryptographic implementation if no matching + * drvcrypt device. + */ + res = drvcrypt_mac_alloc_ctx(&c, algo); + + if (res == TEE_ERROR_NOT_IMPLEMENTED) { + switch (algo) { + case TEE_ALG_HMAC_MD5: + res = crypto_hmac_md5_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA1: + res = crypto_hmac_sha1_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA224: + res = crypto_hmac_sha224_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA256: + res = crypto_hmac_sha256_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA384: + res = crypto_hmac_sha384_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA512: + res = crypto_hmac_sha512_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA3_224: + res = crypto_hmac_sha3_224_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA3_256: + res = crypto_hmac_sha3_256_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA3_384: + res = crypto_hmac_sha3_384_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SHA3_512: + res = crypto_hmac_sha3_512_alloc_ctx(&c); + break; + case TEE_ALG_HMAC_SM3: + res = crypto_hmac_sm3_alloc_ctx(&c); + break; + case TEE_ALG_AES_CBC_MAC_NOPAD: + res = crypto_aes_cbc_mac_nopad_alloc_ctx(&c); + break; + case TEE_ALG_AES_CBC_MAC_PKCS5: + res = crypto_aes_cbc_mac_pkcs5_alloc_ctx(&c); + break; + case TEE_ALG_DES_CBC_MAC_NOPAD: + res = crypto_des_cbc_mac_nopad_alloc_ctx(&c); + break; + case TEE_ALG_DES_CBC_MAC_PKCS5: + res = crypto_des_cbc_mac_pkcs5_alloc_ctx(&c); + break; + case TEE_ALG_DES3_CBC_MAC_NOPAD: + res = crypto_des3_cbc_mac_nopad_alloc_ctx(&c); + break; + case TEE_ALG_DES3_CBC_MAC_PKCS5: + res = crypto_des3_cbc_mac_pkcs5_alloc_ctx(&c); + break; + case TEE_ALG_DES3_CMAC: + res = crypto_des3_cmac_alloc_ctx(&c); + break; + case TEE_ALG_AES_CMAC: + res = crypto_aes_cmac_alloc_ctx(&c); + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + } + + if (!res) + *ctx = c; + + return res; +} + +static const struct crypto_mac_ops *mac_ops(void *ctx) +{ + struct crypto_mac_ctx *c = ctx; + + assert(c && c->ops); + + return c->ops; +} + +void crypto_mac_free_ctx(void *ctx) +{ + if (ctx) + mac_ops(ctx)->free_ctx(ctx); +} + +void crypto_mac_copy_state(void *dst_ctx, void *src_ctx) +{ + mac_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); +} + +TEE_Result crypto_mac_init(void *ctx, const uint8_t *key, size_t len) +{ + return mac_ops(ctx)->init(ctx, key, len); +} + +TEE_Result crypto_mac_update(void *ctx, const uint8_t *data, size_t len) +{ + if (!len) + return TEE_SUCCESS; + + return mac_ops(ctx)->update(ctx, data, len); +} + +TEE_Result crypto_mac_final(void *ctx, uint8_t *digest, size_t digest_len) +{ + return mac_ops(ctx)->final(ctx, digest, digest_len); +} + +TEE_Result crypto_authenc_alloc_ctx(void **ctx, uint32_t algo) +{ + TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_authenc_ctx *c = NULL; + + /* + * Use default authenc implementation if no matching + * drvcrypt device. + */ + res = drvcrypt_authenc_alloc_ctx(&c, algo); + + if (res == TEE_ERROR_NOT_IMPLEMENTED) { + switch (algo) { +#if defined(CFG_CRYPTO_CCM) + case TEE_ALG_AES_CCM: + res = crypto_aes_ccm_alloc_ctx(&c); + break; +#endif +#if defined(CFG_CRYPTO_GCM) + case TEE_ALG_AES_GCM: + res = crypto_aes_gcm_alloc_ctx(&c); + break; +#endif + default: + break; + } + } + + if (!res) + *ctx = c; + + return res; +} + +static const struct crypto_authenc_ops *ae_ops(void *ctx) +{ + struct crypto_authenc_ctx *c = ctx; + + assert(c && c->ops); + + return c->ops; +} + +TEE_Result crypto_authenc_init(void *ctx, 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) +{ + return ae_ops(ctx)->init(ctx, mode, key, key_len, nonce, nonce_len, + tag_len, aad_len, payload_len); +} + +TEE_Result crypto_authenc_update_aad(void *ctx, TEE_OperationMode mode __unused, + const uint8_t *data, size_t len) +{ + return ae_ops(ctx)->update_aad(ctx, data, len); +} + + +TEE_Result crypto_authenc_update_payload(void *ctx, TEE_OperationMode mode, + const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + size_t *dst_len) +{ + if (*dst_len < src_len) + return TEE_ERROR_SHORT_BUFFER; + *dst_len = src_len; + + return ae_ops(ctx)->update_payload(ctx, mode, src_data, src_len, + dst_data); +} + +TEE_Result crypto_authenc_enc_final(void *ctx, const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + size_t *dst_len, uint8_t *dst_tag, + size_t *dst_tag_len) +{ + if (*dst_len < src_len) + return TEE_ERROR_SHORT_BUFFER; + *dst_len = src_len; + + return ae_ops(ctx)->enc_final(ctx, src_data, src_len, dst_data, + dst_tag, dst_tag_len); +} + +TEE_Result crypto_authenc_dec_final(void *ctx, const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + size_t *dst_len, const uint8_t *tag, + size_t tag_len) +{ + if (*dst_len < src_len) + return TEE_ERROR_SHORT_BUFFER; + *dst_len = src_len; + + return ae_ops(ctx)->dec_final(ctx, src_data, src_len, dst_data, tag, + tag_len); +} + +void crypto_authenc_final(void *ctx) +{ + ae_ops(ctx)->final(ctx); +} + +void crypto_authenc_free_ctx(void *ctx) +{ + if (ctx) + ae_ops(ctx)->free_ctx(ctx); +} + +void crypto_authenc_copy_state(void *dst_ctx, void *src_ctx) +{ + ae_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); +} + +#if !defined(CFG_CRYPTO_RSA) && !defined(CFG_CRYPTO_DSA) && \ + !defined(CFG_CRYPTO_DH) && !defined(CFG_CRYPTO_ECC) +struct bignum *crypto_bignum_allocate(size_t size_bits __unused) +{ + return NULL; +} + +TEE_Result crypto_bignum_bin2bn(const uint8_t *from __unused, + size_t fromsize __unused, + struct bignum *to __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +size_t crypto_bignum_num_bytes(struct bignum *a __unused) +{ + return 0; +} + +size_t crypto_bignum_num_bits(struct bignum *a __unused) +{ + return 0; +} + +/* + * crypto_bignum_allocate() and crypto_bignum_bin2bn() failing should be + * enough to guarantee that the functions calling this function aren't + * called, but just in case add a panic() here to avoid unexpected + * behavoir. + */ +static void bignum_cant_happen(void) +{ + volatile bool b = true; + + /* Avoid warning about function does not return */ + if (b) + panic(); +} + +void crypto_bignum_bn2bin(const struct bignum *from __unused, + uint8_t *to __unused) +{ + bignum_cant_happen(); +} + +void crypto_bignum_copy(struct bignum *to __unused, + const struct bignum *from __unused) +{ + bignum_cant_happen(); +} + +void crypto_bignum_free(struct bignum *a) +{ + if (a) + panic(); +} + +void crypto_bignum_clear(struct bignum *a __unused) +{ + bignum_cant_happen(); +} + +/* return -1 if ab */ +int32_t crypto_bignum_compare(struct bignum *a __unused, + struct bignum *b __unused) +{ + bignum_cant_happen(); + return -1; +} +#endif + +#if !defined(CFG_CRYPTO_RSA) +TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result +crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s __unused) +{ +} + +void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s __unused) +{ +} + +TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key __unused, + size_t key_size __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key __unused, + const uint8_t *src __unused, + size_t src_len __unused, + uint8_t *dst __unused, + size_t *dst_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key __unused, + const uint8_t *src __unused, + size_t src_len __unused, + uint8_t *dst __unused, + size_t *dst_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo __unused, + struct rsa_keypair *key __unused, + const uint8_t *label __unused, + size_t label_len __unused, + const uint8_t *src __unused, + size_t src_len __unused, + uint8_t *dst __unused, + size_t *dst_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo __unused, + struct rsa_public_key *key __unused, + const uint8_t *label __unused, + size_t label_len __unused, + const uint8_t *src __unused, + size_t src_len __unused, + uint8_t *dst __unused, + size_t *dst_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_rsassa_sign(uint32_t algo __unused, + struct rsa_keypair *key __unused, + int salt_len __unused, + const uint8_t *msg __unused, + size_t msg_len __unused, + uint8_t *sig __unused, + size_t *sig_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_rsassa_verify(uint32_t algo __unused, + struct rsa_public_key *key __unused, + int salt_len __unused, + const uint8_t *msg __unused, + size_t msg_len __unused, + const uint8_t *sig __unused, + size_t sig_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /*!CFG_CRYPTO_RSA*/ + +#if !defined(CFG_CRYPTO_DSA) +TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result +crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key __unused, + size_t key_size __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_dsa_sign(uint32_t algo __unused, + struct dsa_keypair *key __unused, + const uint8_t *msg __unused, + size_t msg_len __unused, + uint8_t *sig __unused, + size_t *sig_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_dsa_verify(uint32_t algo __unused, + struct dsa_public_key *key __unused, + const uint8_t *msg __unused, + size_t msg_len __unused, + const uint8_t *sig __unused, + size_t sig_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /*!CFG_CRYPTO_DSA*/ + +#if !defined(CFG_CRYPTO_DH) +TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key __unused, + struct bignum *q __unused, + size_t xbits __unused, + size_t key_size __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result +crypto_acipher_dh_shared_secret(struct dh_keypair *private_key __unused, + struct bignum *public_key __unused, + struct bignum *secret __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /*!CFG_CRYPTO_DH*/ + +TEE_Result crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *key, + uint32_t key_type, + size_t key_size_bits) +{ + TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; + + /* + * Use default cryptographic implementation if no matching + * drvcrypt device. + */ + res = drvcrypt_asym_alloc_ecc_public_key(key, key_type, key_size_bits); + if (res == TEE_ERROR_NOT_IMPLEMENTED) + res = crypto_asym_alloc_ecc_public_key(key, key_type, + key_size_bits); + + return res; +} + +TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *key, + uint32_t key_type, + size_t key_size_bits) +{ + TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; + + /* + * Use default cryptographic implementation if no matching + * drvcrypt device. + */ + res = drvcrypt_asym_alloc_ecc_keypair(key, key_type, key_size_bits); + if (res == TEE_ERROR_NOT_IMPLEMENTED) + res = crypto_asym_alloc_ecc_keypair(key, key_type, + key_size_bits); + + return res; +} + +void crypto_acipher_free_ecc_public_key(struct ecc_public_key *key) +{ + assert(key->ops && key->ops->free); + + key->ops->free(key); +} + +TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key, + size_t key_size_bits) +{ + assert(key->ops && key->ops->generate); + + return key->ops->generate(key, key_size_bits); +} + +TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + assert(key->ops); + + if (!key->ops->sign) + return TEE_ERROR_NOT_IMPLEMENTED; + + return key->ops->sign(algo, key, msg, msg_len, sig, sig_len); +} + +TEE_Result crypto_acipher_ecc_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + assert(key->ops); + + if (!key->ops->verify) + return TEE_ERROR_NOT_IMPLEMENTED; + + return key->ops->verify(algo, key, msg, msg_len, sig, sig_len); +} + +TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, + unsigned long *secret_len) +{ + assert(private_key->ops); + + if (!private_key->ops->shared_secret) + return TEE_ERROR_NOT_IMPLEMENTED; + + return private_key->ops->shared_secret(private_key, public_key, secret, + secret_len); +} + +TEE_Result crypto_acipher_sm2_pke_decrypt(struct ecc_keypair *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + assert(key->ops); + + if (!key->ops->decrypt) + return TEE_ERROR_NOT_IMPLEMENTED; + + return key->ops->decrypt(key, src, src_len, dst, dst_len); +} + +TEE_Result crypto_acipher_sm2_pke_encrypt(struct ecc_public_key *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + assert(key->ops); + + if (!key->ops->encrypt) + return TEE_ERROR_NOT_IMPLEMENTED; + + return key->ops->encrypt(key, src, src_len, dst, dst_len); +} + +#if !defined(CFG_CRYPTO_SM2_KEP) +TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key __unused, + struct ecc_keypair *my_eph_key + __unused, + struct ecc_public_key *peer_key + __unused, + struct ecc_public_key *peer_eph_key + __unused, + struct sm2_kep_parms *p __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif + +#if !defined(CFG_CRYPTO_X25519) +TEE_Result crypto_acipher_alloc_x25519_keypair(struct x25519_keypair *key + __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_gen_x25519_key(struct x25519_keypair *key __unused, + size_t key_size __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_x25519_shared_secret(struct x25519_keypair + *private_key __unused, + void *public_key __unused, + void *secret __unused, + unsigned long + *secret_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif + +#if !defined(CFG_CRYPTO_ED25519) +TEE_Result crypto_acipher_alloc_ed25519_keypair(struct ed25519_keypair *key + __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result +crypto_acipher_alloc_ed25519_public_key(struct ed25519_public_key *key __unused, + size_t key_size __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_gen_ed25519_key(struct ed25519_keypair *key __unused, + size_t key_size __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_ed25519_sign(struct ed25519_keypair *key __unused, + const uint8_t *msg __unused, + size_t msg_len __unused, + uint8_t *sig __unused, + size_t *sig_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result +crypto_acipher_ed25519_verify(struct ed25519_public_key *key __unused, + const uint8_t *msg __unused, + size_t msg_len __unused, + const uint8_t *sig __unused, + size_t sig_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result crypto_acipher_ed25519ctx_sign(struct ed25519_keypair *key __unused, + const uint8_t *msg __unused, + size_t msg_len __unused, + uint8_t *sig __unused, + size_t *sig_len __unused, + bool ph_flag __unused, + const uint8_t *ctx __unused, + size_t ctxlen __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +TEE_Result +crypto_acipher_ed25519ctx_verify(struct ed25519_public_key *key __unused, + const uint8_t *msg __unused, + size_t msg_len __unused, + const uint8_t *sig __unused, + size_t sig_len __unused, + bool ph_flag __unused, + const uint8_t *ctx __unused, + size_t ctxlen __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif + +__weak TEE_Result crypto_storage_obj_del(struct tee_obj *obj __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} diff --git a/optee/optee_os/core/crypto/rng_fortuna.c b/optee/optee_os/core/crypto/rng_fortuna.c new file mode 100644 index 0000000..f9317b6 --- /dev/null +++ b/optee/optee_os/core/crypto/rng_fortuna.c @@ -0,0 +1,531 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* Copyright (c) 2018, Linaro Limited */ + +/* + * This is an implementation of the Fortuna cryptographic PRNG as defined in + * https://www.schneier.com/academic/paperfiles/fortuna.pdf + * There's one small exception, see comment in restart_pool() below. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_POOLS 32 +#define BLOCK_SIZE 16 +#define KEY_SIZE 32 +#define CIPHER_ALGO TEE_ALG_AES_ECB_NOPAD +#define HASH_ALGO TEE_ALG_SHA256 +#define MIN_POOL_SIZE 64 +#define MAX_EVENT_DATA_LEN 32U +#define RING_BUF_DATA_SIZE 4U + +/* + * struct fortuna_state - state of the Fortuna PRNG + * @ctx: Cipher context used to produce the random numbers + * @counter: Counter which is encrypted to produce the random numbers + * @pool0_length: Amount of data added to pool0 + * @pool_ctx: One hash context for each pool + * @reseed_ctx: Hash context used while reseeding + * @reseed_count: Number of time we've reseeded the PRNG, used to tell + * which pools should be used in the reseed process + * @next_reseed_time: If we have a secure time, the earliest next time we + * may reseed + * + * To minimize the delay in crypto_rng_add_event() there's @pool_spin_lock + * which protects everything needed by this function. + * + * @next_reseed_time is used as a rate limiter for reseeding. + */ +static struct fortuna_state { + void *ctx; + uint64_t counter[2]; + unsigned int pool0_length; + void *pool_ctx[NUM_POOLS]; + void *reseed_ctx; + uint32_t reseed_count; +#ifndef CFG_SECURE_TIME_SOURCE_REE + TEE_Time next_reseed_time; +#endif +} state; + +static struct mutex state_mu = MUTEX_INITIALIZER; + +static struct { + struct { + uint8_t snum; + uint8_t pnum; + uint8_t dlen; + uint8_t data[RING_BUF_DATA_SIZE]; + } elem[8]; + unsigned int begin; + unsigned int end; +} ring_buffer; + +unsigned int ring_buffer_spin_lock; + +static void inc_counter(uint64_t counter[2]) +{ + counter[0]++; + if (!counter[0]) + counter[1]++; +} + +static TEE_Result hash_init(void *ctx) +{ + return crypto_hash_init(ctx); +} + +static TEE_Result hash_update(void *ctx, const void *data, size_t dlen) +{ + return crypto_hash_update(ctx, data, dlen); +} + +static TEE_Result hash_final(void *ctx, uint8_t digest[KEY_SIZE]) +{ + return crypto_hash_final(ctx, digest, KEY_SIZE); +} + +static TEE_Result key_from_data(void *ctx, const void *data, size_t dlen, + uint8_t key[KEY_SIZE]) +{ + TEE_Result res; + + res = hash_init(ctx); + if (res) + return res; + res = hash_update(ctx, data, dlen); + if (res) + return res; + return hash_final(ctx, key); +} + +static TEE_Result cipher_init(void *ctx, uint8_t key[KEY_SIZE]) +{ + return crypto_cipher_init(ctx, TEE_MODE_ENCRYPT, + key, KEY_SIZE, NULL, 0, NULL, 0); +} + +static void fortuna_done(void) +{ + size_t n; + + for (n = 0; n < NUM_POOLS; n++) { + crypto_hash_free_ctx(state.pool_ctx[n]); + state.pool_ctx[n] = NULL; + } + crypto_hash_free_ctx(state.reseed_ctx); + state.reseed_ctx = NULL; + crypto_cipher_free_ctx(state.ctx); + state.ctx = NULL; +} + +TEE_Result crypto_rng_init(const void *data, size_t dlen) +{ + TEE_Result res; + uint8_t key[KEY_SIZE]; + void *ctx; + size_t n; + + COMPILE_TIME_ASSERT(sizeof(state.counter) == BLOCK_SIZE); + + if (state.ctx) + return TEE_ERROR_BAD_STATE; + + memset(&state, 0, sizeof(state)); + + for (n = 0; n < NUM_POOLS; n++) { + res = crypto_hash_alloc_ctx(&state.pool_ctx[n], HASH_ALGO); + if (res) + goto err; + res = crypto_hash_init(state.pool_ctx[n]); + if (res) + goto err; + } + + res = crypto_hash_alloc_ctx(&state.reseed_ctx, HASH_ALGO); + if (res) + goto err; + + res = key_from_data(state.reseed_ctx, data, dlen, key); + if (res) + return res; + + res = crypto_cipher_alloc_ctx(&ctx, CIPHER_ALGO); + if (res) + return res; + res = cipher_init(ctx, key); + if (res) + return res; + inc_counter(state.counter); + state.ctx = ctx; + return TEE_SUCCESS; +err: + fortuna_done(); + return res; +} + +static void push_ring_buffer(uint8_t snum, uint8_t pnum, const void *data, + size_t dlen) +{ + uint8_t dl = MIN(RING_BUF_DATA_SIZE, dlen); + unsigned int next_begin; + uint32_t old_itr_status; + + /* Spinlock to serialize writers */ + old_itr_status = cpu_spin_lock_xsave(&ring_buffer_spin_lock); + + next_begin = (ring_buffer.begin + 1) % ARRAY_SIZE(ring_buffer.elem); + if (next_begin == atomic_load_uint(&ring_buffer.end)) + goto out; /* buffer is full */ + + ring_buffer.elem[next_begin].snum = snum; + ring_buffer.elem[next_begin].pnum = pnum; + ring_buffer.elem[next_begin].dlen = dl; + memcpy(ring_buffer.elem[next_begin].data, data, dl); + + atomic_store_uint(&ring_buffer.begin, next_begin); + +out: + cpu_spin_unlock_xrestore(&ring_buffer_spin_lock, old_itr_status); +} + +static size_t pop_ring_buffer(uint8_t *snum, uint8_t *pnum, + uint8_t data[RING_BUF_DATA_SIZE]) +{ + unsigned int next_end; + size_t dlen; + + if (atomic_load_uint(&ring_buffer.begin) == ring_buffer.end) + return 0; + + next_end = (ring_buffer.end + 1) % ARRAY_SIZE(ring_buffer.elem); + + *snum = ring_buffer.elem[ring_buffer.end].snum; + *pnum = ring_buffer.elem[ring_buffer.end].pnum; + dlen = MIN(ring_buffer.elem[ring_buffer.end].dlen, RING_BUF_DATA_SIZE); + assert(ring_buffer.elem[ring_buffer.end].dlen == dlen); + memcpy(data, ring_buffer.elem[ring_buffer.end].data, dlen); + + atomic_store_uint(&ring_buffer.end, next_end); + + return dlen; +} + +static TEE_Result add_event(uint8_t snum, uint8_t pnum, + const void *data, size_t dlen) +{ + TEE_Result res; + size_t dl = MIN(MAX_EVENT_DATA_LEN, dlen); + uint8_t v[] = { snum, dl }; + + if (pnum >= NUM_POOLS) + return TEE_ERROR_BAD_PARAMETERS; + + res = hash_update(state.pool_ctx[pnum], v, sizeof(v)); + if (res) + return res; + res = hash_update(state.pool_ctx[pnum], data, dl); + if (res) + return res; + if (!pnum) { + unsigned int l; + + if (!ADD_OVERFLOW(state.pool0_length, dl, &l)) + state.pool0_length = l; + } + + return TEE_SUCCESS; +} + +static TEE_Result drain_ring_buffer(void) +{ + while (true) { + TEE_Result res; + uint8_t snum; + uint8_t pnum; + uint8_t data[RING_BUF_DATA_SIZE]; + size_t dlen; + + dlen = pop_ring_buffer(&snum, &pnum, data); + if (!dlen) + return TEE_SUCCESS; + + res = add_event(snum, pnum, data, dlen); + if (res) + return res; + } +} + +static unsigned int get_next_pnum(unsigned int *pnum) +{ + unsigned int nval; + unsigned int oval = atomic_load_uint(pnum); + + while (true) { + nval = (oval + 1) % NUM_POOLS; + + if (atomic_cas_uint(pnum, &oval, nval)) { + /* + * *pnum is normally initialized to 0 and we'd like + * to start feeding pool number 0 as that's the + * most important one. + * + * If we where to take just *pnum and increase it + * later multiple updaters could end up with the + * same number. + * + * By increasing first we get the number unique for + * next update and by subtracting one (using + * modulus) we get the number for this update. + */ + return (nval + NUM_POOLS - 1) % NUM_POOLS; + } + /* + * At this point atomic_cas_uint() has updated oval to the + * current *pnum. + */ + } +} + +void crypto_rng_add_event(enum crypto_rng_src sid, unsigned int *pnum, + const void *data, size_t dlen) +{ + unsigned int pn = get_next_pnum(pnum); + uint8_t snum = sid >> 1; + + if (CRYPTO_RNG_SRC_IS_QUICK(sid)) { + push_ring_buffer(snum, pn, data, dlen); + } else { + mutex_lock(&state_mu); + add_event(snum, pn, data, dlen); + drain_ring_buffer(); + mutex_unlock(&state_mu); + } +} + +/* GenerateBlocks */ +static TEE_Result generate_blocks(void *block, size_t nblocks) +{ + uint8_t *b = block; + size_t n; + + for (n = 0; n < nblocks; n++) { + TEE_Result res = crypto_cipher_update(state.ctx, + TEE_MODE_ENCRYPT, false, + (void *)state.counter, + BLOCK_SIZE, + b + n * BLOCK_SIZE); + + /* + * Make sure to increase the counter before returning an + * eventual errors, we must never re-use the counter with + * the same key. + */ + inc_counter(state.counter); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +/* GenerateRandomData */ +static TEE_Result generate_random_data(void *buf, size_t blen) +{ + TEE_Result res; + + res = generate_blocks(buf, blen / BLOCK_SIZE); + if (res) + return res; + if (blen % BLOCK_SIZE) { + uint8_t block[BLOCK_SIZE]; + uint8_t *b = (uint8_t *)buf + ROUNDDOWN(blen, BLOCK_SIZE); + + res = generate_blocks(block, 1); + if (res) + return res; + memcpy(b, block, blen % BLOCK_SIZE); + } + + return TEE_SUCCESS; +} + +#ifdef CFG_SECURE_TIME_SOURCE_REE +static bool reseed_rate_limiting(void) +{ + /* + * There's no point in checking REE time for reseed rate limiting, + * and also it makes it less complicated if we can avoid doing RPC + * here. + */ + return false; +} +#else +static bool reseed_rate_limiting(void) +{ + TEE_Result res; + TEE_Time time; + const TEE_Time time_100ms = { 0, 100 }; + + res = tee_time_get_sys_time(&time); + /* + * Failure to read time must result in allowing reseed or we could + * block reseeding forever. + */ + if (res) + return false; + + if (TEE_TIME_LT(time, state.next_reseed_time)) + return true; + + /* Time to reseed, calculate next time reseed is OK */ + TEE_TIME_ADD(time, time_100ms, state.next_reseed_time); + return false; +} +#endif + +static TEE_Result restart_pool(void *pool_ctx, uint8_t pool_digest[KEY_SIZE]) +{ + TEE_Result res = hash_final(pool_ctx, pool_digest); + + if (res) + return res; + + res = hash_init(pool_ctx); + if (res) + return res; + + /* + * Restart the pool with the digest of the old pool. This is an + * extension to Fortuna. In the original Fortuna all pools was + * restarted from scratch. This extension is one more defense + * against spamming of the pools with known data which could lead + * to the spammer knowing the state of the pools. + * + * This extra precaution could be useful since OP-TEE sometimes + * have very few sources of good entropy and at the same time has + * sources that could quite easily be predicted by an attacker. + */ + return hash_update(pool_ctx, pool_digest, KEY_SIZE); +} + +static bool reseed_from_pool(uint32_t reseed_count, size_t pool_num) +{ + /* + * Specification says: use pool if + * 2^pool_num is a divisor of reseed_count + * + * in order to avoid an expensive modulus operation we're + * optimizing this below. + */ + return !pool_num || !((reseed_count >> (pool_num - 1)) & 1); +} + +static TEE_Result maybe_reseed(void) +{ + TEE_Result res; + size_t n; + uint8_t pool_digest[KEY_SIZE]; + + if (state.pool0_length < MIN_POOL_SIZE) + return TEE_SUCCESS; + + if (reseed_rate_limiting()) + return TEE_SUCCESS; + + state.reseed_count++; + + res = hash_init(state.reseed_ctx); + if (res) + return res; + + for (n = 0; + n < NUM_POOLS && reseed_from_pool(state.reseed_count, n); n++) { + res = restart_pool(state.pool_ctx[n], pool_digest); + if (res) + return res; + if (!n) + state.pool0_length = 0; + + res = hash_update(state.reseed_ctx, pool_digest, KEY_SIZE); + if (res) + return res; + } + res = hash_final(state.reseed_ctx, pool_digest); + if (res) + return res; + + crypto_cipher_final(state.ctx); + res = crypto_cipher_init(state.ctx, TEE_MODE_ENCRYPT, + pool_digest, KEY_SIZE, NULL, 0, NULL, 0); + if (res) + return res; + inc_counter(state.counter); + + return TEE_SUCCESS; +} + +static TEE_Result fortuna_read(void *buf, size_t blen) +{ + TEE_Result res; + + if (!state.ctx) + return TEE_ERROR_BAD_STATE; + + mutex_lock(&state_mu); + + res = maybe_reseed(); + if (res) + goto out; + + if (blen) { + uint8_t new_key[KEY_SIZE]; + + res = generate_random_data(buf, blen); + if (res) + goto out; + + res = generate_blocks(new_key, KEY_SIZE / BLOCK_SIZE); + if (res) + goto out; + crypto_cipher_final(state.ctx); + res = cipher_init(state.ctx, new_key); + if (res) + goto out; + } + + res = drain_ring_buffer(); +out: + if (res) + fortuna_done(); + mutex_unlock(&state_mu); + + return res; +} + +TEE_Result crypto_rng_read(void *buf, size_t blen) +{ + size_t offs = 0; + + while (true) { + TEE_Result res; + size_t n; + + /* Draw at most 1 MiB of random on a single key */ + n = MIN(blen - offs, SIZE_1M); + if (!n) + return TEE_SUCCESS; + res = fortuna_read((uint8_t *)buf + offs, n); + if (res) + return res; + offs += n; + } +} diff --git a/optee/optee_os/core/crypto/rng_hw.c b/optee/optee_os/core/crypto/rng_hw.c new file mode 100644 index 0000000..4d94ea7 --- /dev/null +++ b/optee/optee_os/core/crypto/rng_hw.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* Copyright (c) 2018, Linaro Limited */ + +#include +#include +#include +#include +#include +#include + +/* This is a HW RNG, no need for seeding */ +TEE_Result crypto_rng_init(const void *data __unused, size_t dlen __unused) +{ + return TEE_SUCCESS; +} + +/* This is a HW RNG, no need to add entropy */ +void crypto_rng_add_event(enum crypto_rng_src sid __unused, + unsigned int *pnum __unused, + const void *data __unused, + size_t dlen __unused) +{ +} + +TEE_Result crypto_rng_read(void *buf, size_t blen) +{ + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + return hw_get_random_bytes(buf, blen); +} diff --git a/optee/optee_os/core/crypto/signed_hdr.c b/optee/optee_os/core/crypto/signed_hdr.c new file mode 100644 index 0000000..40c2997 --- /dev/null +++ b/optee/optee_os/core/crypto/signed_hdr.c @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size) +{ + size_t shdr_size; + struct shdr *shdr; + vaddr_t img_va = (vaddr_t)img; + vaddr_t tmp = 0; + size_t end = 0; + + if (ADD_OVERFLOW(offs, sizeof(struct shdr), &end) || end > img_size) + return NULL; + + shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs)); + if (ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size) + return NULL; + + if (ADD_OVERFLOW(img_va, shdr_size, &tmp)) + return NULL; + + shdr = malloc(shdr_size); + if (!shdr) + return NULL; + memcpy(shdr, (const uint8_t *)img + offs, shdr_size); + + /* Check that the data wasn't modified before the copy was completed */ + if (shdr_size != SHDR_GET_SIZE(shdr)) { + free(shdr); + return NULL; + } + + return shdr; +} + +static bool is_weak_hash_algo(uint32_t algo) +{ + return algo == TEE_ALG_MD5 || algo == TEE_ALG_SHA1 || + algo == TEE_ALG_MD5SHA1; +} + +TEE_Result shdr_verify_signature(const struct shdr *shdr) +{ + struct rsa_public_key key = { }; + TEE_Result res = TEE_SUCCESS; + uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); + struct ftmn ftmn = { }; + unsigned int err_incr = 2; + size_t hash_size = 0; + size_t hash_algo = 0; + + if (shdr->magic != SHDR_MAGIC) + goto err; + + if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) + goto err; + + hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); + if (is_weak_hash_algo(hash_algo)) + goto err; + + res = tee_alg_get_digest_size(hash_algo, &hash_size); + if (res) + goto err; + if (hash_size != shdr->hash_size) + goto err; + + res = crypto_acipher_alloc_rsa_public_key(&key, + ta_pub_key_modulus_size * 8); + if (res) + goto err; + + res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); + if (res) + goto err; + res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size, + key.n); + if (res) + goto err; + + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, + crypto_acipher_rsassa_verify, shdr->algo, &key, + shdr->hash_size, SHDR_GET_HASH(shdr), shdr->hash_size, + SHDR_GET_SIG(shdr), shdr->sig_size); + if (!res) { + ftmn_checkpoint(&ftmn, FTMN_INCR0); + goto out; + } + err_incr = 1; +err: + res = TEE_ERROR_SECURITY; + FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res); +out: + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res); + crypto_acipher_free_rsa_public_key(&key); + return res; +} + +static const struct shdr_subkey_attr * +find_attr(const struct shdr_subkey *subkey, uint32_t id) +{ + size_t n = 0; + + for (n = 0; n < subkey->attr_count; n++) + if (subkey->attrs[n].id == id) + return subkey->attrs + n; + + return NULL; +} + +static TEE_Result load_rsa_key(const struct shdr_subkey *subkey, + struct rsa_public_key **key_pp) +{ + const uint8_t *base = (const uint8_t *)subkey; + const struct shdr_subkey_attr *pub_exp = NULL; + const struct shdr_subkey_attr *modulus = NULL; + struct rsa_public_key *key = NULL; + TEE_Result res = TEE_SUCCESS; + + pub_exp = find_attr(subkey, TEE_ATTR_RSA_PUBLIC_EXPONENT); + if (!pub_exp) + return TEE_ERROR_SECURITY; + modulus = find_attr(subkey, TEE_ATTR_RSA_MODULUS); + if (!modulus) + return TEE_ERROR_SECURITY; + + key = calloc(1, sizeof(*key)); + if (!key) + return TEE_ERROR_OUT_OF_MEMORY; + res = crypto_acipher_alloc_rsa_public_key(key, modulus->size * 8); + if (res) + goto err_key; + + res = crypto_bignum_bin2bn(base + pub_exp->offs, pub_exp->size, key->e); + if (res) + goto err; + res = crypto_bignum_bin2bn(base + modulus->offs, modulus->size, key->n); + if (res) + goto err; + + *key_pp = key; + return TEE_SUCCESS; +err: + crypto_acipher_free_rsa_public_key(key); +err_key: + free(key); + return TEE_ERROR_SECURITY; +} + +static TEE_Result check_attrs(const struct shdr_subkey *subkey, size_t img_size) +{ + const struct shdr_subkey_attr *attrs = subkey->attrs; + size_t end = 0; + size_t n = 0; + + if (MUL_OVERFLOW(subkey->attr_count, sizeof(*attrs), &end) || + ADD_OVERFLOW(end, sizeof(*subkey), &end) || + end > img_size) + return TEE_ERROR_SECURITY; + + for (n = 0; n < subkey->attr_count; n++) + if (ADD_OVERFLOW(attrs[n].offs, attrs[n].size, &end) || + end > img_size) + return TEE_ERROR_SECURITY; + + return TEE_SUCCESS; +} + +static TEE_Result calc_next_uuid(uint8_t uuid[sizeof(TEE_UUID)], + const uint8_t my_uuid[sizeof(TEE_UUID)], + const void *ns_name, size_t name_size) +{ + TEE_Result res = TEE_ERROR_SECURITY; + void *ctx = NULL; + struct { + uint8_t digest[TEE_SHA1_HASH_SIZE]; + TEE_UUID uuid; + char name_str[]; + } *tmp = NULL; + + if (!name_size) { + memcpy(uuid, my_uuid, sizeof(TEE_UUID)); + return TEE_SUCCESS; + } + + /* + * RFC 4122 requires a SHA-1 digest for UUID v5. Use SHA-512 + * instead for better collision resistance. + */ + if (crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA512)) + return TEE_ERROR_SECURITY; + + tmp = mempool_alloc(mempool_default, sizeof(*tmp) + name_size); + if (!tmp) + goto out_ctx; + memcpy(tmp->name_str, ns_name, name_size); + + if (crypto_hash_init(ctx) || + crypto_hash_update(ctx, my_uuid, sizeof(TEE_UUID)) || + crypto_hash_update(ctx, (const void *)tmp->name_str, + strnlen(tmp->name_str, name_size)) || + crypto_hash_final(ctx, tmp->digest, sizeof(tmp->digest))) + goto out_mempool; + + tee_uuid_from_octets(&tmp->uuid, tmp->digest); + /* + * Set the four most significant bits (bits 12 through 15) of the + * time_hi_and_version field to 5. + */ + tmp->uuid.timeHiAndVersion &= ~SHIFT_U32(0xf, 12); + tmp->uuid.timeHiAndVersion |= SHIFT_U32(5, 12); + /* + * Set the two most significant bits (bits 6 and 7) of the + * clock_seq_hi_and_reserved to zero and one, respectively. + */ + tmp->uuid.clockSeqAndNode[0] &= ~BIT(6); + tmp->uuid.clockSeqAndNode[0] |= BIT(7); + + tee_uuid_to_octets(uuid, &tmp->uuid); + res = TEE_SUCCESS; + +out_mempool: + mempool_free(mempool_default, tmp); +out_ctx: + crypto_hash_free_ctx(ctx); + + return res; +} + +TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs, + const uint8_t *ns_img, size_t ns_img_size, + const uint8_t next_uuid[sizeof(TEE_UUID)], + uint32_t max_depth, struct shdr_pub_key *key) +{ + struct shdr_subkey *subkey = NULL; + TEE_Result res = TEE_SUCCESS; + void *digest = NULL; + uint8_t *img = NULL; + void *ctx = NULL; + size_t end = 0; + + if (shdr->img_type != SHDR_SUBKEY) + return TEE_ERROR_SECURITY; + + if (shdr->img_size < sizeof(*subkey)) + return TEE_ERROR_SECURITY; + + if (ADD_OVERFLOW(shdr->img_size, offs, &end) || end > ns_img_size) + return TEE_ERROR_SECURITY; + + img = mempool_alloc(mempool_default, shdr->img_size + shdr->hash_size); + if (!img) + return TEE_ERROR_OUT_OF_MEMORY; + memcpy(img + shdr->hash_size, ns_img + offs, shdr->img_size); + subkey = (void *)(img + shdr->hash_size); + digest = img; + + if (crypto_hash_alloc_ctx(&ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo))) { + res = TEE_ERROR_SECURITY; + goto out_mempool; + } + + if (crypto_hash_init(ctx) || + crypto_hash_update(ctx, (const void *)shdr, sizeof(*shdr)) || + crypto_hash_update(ctx, (const void *)subkey, shdr->img_size) || + crypto_hash_final(ctx, digest, shdr->hash_size) || + memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size)) { + res = TEE_ERROR_SECURITY; + goto out_ctx; + } + + res = check_attrs(subkey, shdr->img_size); + if (res) + goto out_ctx; + + if (subkey->max_depth >= max_depth) { + res = TEE_ERROR_SECURITY; + goto out_ctx; + } + if (next_uuid && memcmp(next_uuid, subkey->uuid, sizeof(TEE_UUID))) { + res = TEE_ERROR_SECURITY; + goto out_ctx; + } + + key->max_depth = subkey->max_depth; + key->name_size = subkey->name_size; + memcpy(key->uuid, subkey->uuid, sizeof(TEE_UUID)); + if (ADD_OVERFLOW(key->name_size, offs + shdr->img_size, &end) || + end > ns_img_size) { + res = TEE_ERROR_SECURITY; + goto out_ctx; + } + res = calc_next_uuid(key->next_uuid, key->uuid, + ns_img + offs + shdr->img_size, key->name_size); + if (res) + goto out_ctx; + + key->main_algo = TEE_ALG_GET_MAIN_ALG(subkey->algo); + switch (key->main_algo) { + case TEE_MAIN_ALGO_RSA: + res = load_rsa_key(subkey, &key->pub_key.rsa); + break; + default: + res = TEE_ERROR_SECURITY; + break; + } + +out_ctx: + crypto_hash_free_ctx(ctx); +out_mempool: + mempool_free(mempool_default, img); + return res; +} + +void shdr_free_pub_key(struct shdr_pub_key *key) +{ + if (key) { + switch (key->main_algo) { + case TEE_MAIN_ALGO_RSA: + crypto_acipher_free_rsa_public_key(key->pub_key.rsa); + free(key->pub_key.rsa); + break; + default: + panic(); + } + } +} + +TEE_Result shdr_verify_signature2(struct shdr_pub_key *key, + const struct shdr *shdr) +{ + TEE_Result res = TEE_SUCCESS; + unsigned int err_incr = 2; + struct ftmn ftmn = { }; + size_t hash_size = 0; + size_t hash_algo = 0; + + if (shdr->magic != SHDR_MAGIC) + goto err; + + if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != key->main_algo) + goto err; + + hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); + if (is_weak_hash_algo(hash_algo)) + goto err; + + if (tee_alg_get_digest_size(hash_algo, &hash_size) || + hash_size != shdr->hash_size) + goto err; + + switch (key->main_algo) { + case TEE_MAIN_ALGO_RSA: + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, + crypto_acipher_rsassa_verify, shdr->algo, + key->pub_key.rsa, shdr->hash_size, + SHDR_GET_HASH(shdr), shdr->hash_size, + SHDR_GET_SIG(shdr), shdr->sig_size); + break; + default: + panic(); + } + + if (!res) { + ftmn_checkpoint(&ftmn, FTMN_INCR0); + goto out; + } + err_incr = 1; +err: + res = TEE_ERROR_SECURITY; + FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res); +out: + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res); + return res; +} diff --git a/optee/optee_os/core/crypto/sm2-kdf.c b/optee/optee_os/core/crypto/sm2-kdf.c new file mode 100644 index 0000000..81f0f0c --- /dev/null +++ b/optee/optee_os/core/crypto/sm2-kdf.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * GM/T 0003.1‒2012 Part 4 Sections 5.4.2 and 5.4.3 + * GM/T 0003.1‒2012 Part 5 Sections 5.4.2 and 5.4.3 + * Key derivation function based on the SM3 hash function + */ +TEE_Result sm2_kdf(const uint8_t *Z, size_t Z_len, uint8_t *t, size_t tlen) +{ + TEE_Result res = TEE_SUCCESS; + size_t remain = tlen; + uint32_t count = 1; + uint32_t be_count = 0; + void *ctx = NULL; + uint8_t *out = t; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + return res; + + while (remain) { + uint8_t tmp[TEE_SM3_HASH_SIZE] = { }; + uint8_t *buf = NULL; + + if (remain >= TEE_SM3_HASH_SIZE) + buf = out; + else + buf = tmp; + + put_be32(&be_count, count); + res = crypto_hash_init(ctx); + if (res) + goto out; + res = crypto_hash_update(ctx, Z, Z_len); + if (res) + goto out; + res = crypto_hash_update(ctx, (const uint8_t *)&be_count, + sizeof(be_count)); + if (res) + goto out; + res = crypto_hash_final(ctx, buf, TEE_SM3_HASH_SIZE); + if (res) + goto out; + + if (remain < TEE_SM3_HASH_SIZE) { + memcpy(out, tmp, remain); + break; + } + + out += TEE_SM3_HASH_SIZE; + remain -= TEE_SM3_HASH_SIZE; + count++; + } +out: + crypto_hash_free_ctx(ctx); + return res; +} + diff --git a/optee/optee_os/core/crypto/sm3-hash.c b/optee/optee_os/core/crypto/sm3-hash.c new file mode 100644 index 0000000..189b08a --- /dev/null +++ b/optee/optee_os/core/crypto/sm3-hash.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + * Copyright (C) 2019 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sm3.h" + +struct sm3_hash_ctx { + struct crypto_hash_ctx hash_ctx; + struct sm3_context sm3_ctx; +}; + +static const struct crypto_hash_ops sm3_hash_ops; + +static struct sm3_hash_ctx *to_hash_ctx(struct crypto_hash_ctx *ctx) +{ + assert(ctx && ctx->ops == &sm3_hash_ops); + + return container_of(ctx, struct sm3_hash_ctx, hash_ctx); +} + +static TEE_Result op_sm3_hash_init(struct crypto_hash_ctx *ctx) +{ + sm3_init(&to_hash_ctx(ctx)->sm3_ctx); + + return TEE_SUCCESS; +} + +static TEE_Result op_sm3_hash_update(struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len) +{ + sm3_update(&to_hash_ctx(ctx)->sm3_ctx, data, len); + + return TEE_SUCCESS; +} + +static TEE_Result op_sm3_hash_final(struct crypto_hash_ctx *ctx, + uint8_t *digest, + size_t len) +{ + struct sm3_hash_ctx *hc = to_hash_ctx(ctx); + size_t hash_size = TEE_SM3_HASH_SIZE; + uint8_t block_digest[TEE_SM3_HASH_SIZE] = { 0 }; + uint8_t *tmp_digest = NULL; + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (hash_size > len) + tmp_digest = block_digest; /* use a tempory buffer */ + else + tmp_digest = digest; + + sm3_final(&hc->sm3_ctx, tmp_digest); + + if (hash_size > len) + memcpy(digest, tmp_digest, len); + + return TEE_SUCCESS; +} + +static void op_sm3_hash_free_ctx(struct crypto_hash_ctx *ctx) +{ + struct sm3_hash_ctx *hc = to_hash_ctx(ctx); + + memzero_explicit(&hc->sm3_ctx, sizeof(hc->sm3_ctx)); + free(hc); +} + +static void op_sm3_hash_copy_state(struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx) +{ + struct sm3_hash_ctx *src = to_hash_ctx(src_ctx); + struct sm3_hash_ctx *dst = to_hash_ctx(dst_ctx); + + dst->sm3_ctx = src->sm3_ctx; +} + +static const struct crypto_hash_ops sm3_hash_ops = { + .init = op_sm3_hash_init, + .update = op_sm3_hash_update, + .final = op_sm3_hash_final, + .free_ctx = op_sm3_hash_free_ctx, + .copy_state = op_sm3_hash_copy_state, +}; + +TEE_Result crypto_sm3_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + struct sm3_hash_ctx *hc = NULL; + + hc = calloc(1, sizeof(*hc)); + if (!hc) + return TEE_ERROR_OUT_OF_MEMORY; + + hc->hash_ctx.ops = &sm3_hash_ops; + + *ctx = &hc->hash_ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/crypto/sm3-hmac.c b/optee/optee_os/core/crypto/sm3-hmac.c new file mode 100644 index 0000000..abe2ac8 --- /dev/null +++ b/optee/optee_os/core/crypto/sm3-hmac.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sm3.h" + +struct sm3_hmac_ctx { + struct crypto_mac_ctx mac_ctx; + struct sm3_context sm3_ctx; +}; + +static const struct crypto_mac_ops sm3_hmac_ops; + +static struct sm3_hmac_ctx *to_hmac_ctx(struct crypto_mac_ctx *ctx) +{ + assert(ctx && ctx->ops == &sm3_hmac_ops); + + return container_of(ctx, struct sm3_hmac_ctx, mac_ctx); +} + +static TEE_Result op_sm3_hmac_init(struct crypto_mac_ctx *ctx, + const uint8_t *key, size_t len) +{ + sm3_hmac_init(&to_hmac_ctx(ctx)->sm3_ctx, key, len); + + return TEE_SUCCESS; +} + +static TEE_Result op_sm3_hmac_update(struct crypto_mac_ctx *ctx, + const uint8_t *data, size_t len) +{ + sm3_hmac_update(&to_hmac_ctx(ctx)->sm3_ctx, data, len); + + return TEE_SUCCESS; +} + +static TEE_Result op_sm3_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, + size_t len) +{ + struct sm3_hmac_ctx *c = to_hmac_ctx(ctx); + size_t hmac_size = TEE_SM3_HASH_SIZE; + uint8_t block_digest[TEE_SM3_HASH_SIZE] = { 0 }; + uint8_t *tmp_digest = NULL; + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (hmac_size > len) + tmp_digest = block_digest; /* use a tempory buffer */ + else + tmp_digest = digest; + + sm3_hmac_final(&c->sm3_ctx, tmp_digest); + + if (hmac_size > len) + memcpy(digest, tmp_digest, len); + + return TEE_SUCCESS; +} + +static void op_sm3_hmac_free_ctx(struct crypto_mac_ctx *ctx) +{ + struct sm3_hmac_ctx *c = to_hmac_ctx(ctx); + + memzero_explicit(&c->sm3_ctx, sizeof(c->sm3_ctx)); + free(c); +} + +static void op_sm3_hmac_copy_state(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx) +{ + struct sm3_hmac_ctx *src = to_hmac_ctx(src_ctx); + struct sm3_hmac_ctx *dst = to_hmac_ctx(dst_ctx); + + dst->sm3_ctx = src->sm3_ctx; +} + +static const struct crypto_mac_ops sm3_hmac_ops = { + .init = op_sm3_hmac_init, + .update = op_sm3_hmac_update, + .final = op_sm3_hmac_final, + .free_ctx = op_sm3_hmac_free_ctx, + .copy_state = op_sm3_hmac_copy_state, +}; + +TEE_Result crypto_hmac_sm3_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + struct sm3_hmac_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->mac_ctx.ops = &sm3_hmac_ops; + + *ctx = &c->mac_ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/crypto/sm3.c b/optee/optee_os/core/crypto/sm3.c new file mode 100644 index 0000000..26bba10 --- /dev/null +++ b/optee/optee_os/core/crypto/sm3.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019 Huawei Technologies Co., Ltd + */ +/* + * SM3 Hash algorithm + * thanks to Xyssl + * author:goldboar + * email:goldboar@163.com + * 2011-10-26 + */ + +#include +#include +#include +#include + +#include "sm3.h" + +#define SM3_BLOCK_SIZE 64 + +#define GET_UINT32_BE(n, b, i) \ + do { \ + (n) = ((uint32_t)(b)[(i)] << 24) | \ + ((uint32_t)(b)[(i) + 1] << 16) | \ + ((uint32_t)(b)[(i) + 2] << 8) | \ + ((uint32_t)(b)[(i) + 3]); \ + } while (0) + +#define PUT_UINT32_BE(n, b, i) \ + do { \ + (b)[(i)] = (uint8_t)((n) >> 24); \ + (b)[(i) + 1] = (uint8_t)((n) >> 16); \ + (b)[(i) + 2] = (uint8_t)((n) >> 8); \ + (b)[(i) + 3] = (uint8_t)((n)); \ + } while (0) + +void sm3_init(struct sm3_context *ctx) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x7380166F; + ctx->state[1] = 0x4914B2B9; + ctx->state[2] = 0x172442D7; + ctx->state[3] = 0xDA8A0600; + ctx->state[4] = 0xA96F30BC; + ctx->state[5] = 0x163138AA; + ctx->state[6] = 0xE38DEE4D; + ctx->state[7] = 0xB0FB0E4E; +} + +static void __maybe_unused sm3_process(struct sm3_context *ctx, + const uint8_t data[64]) +{ + uint32_t SS1, SS2, TT1, TT2, W[68], W1[64]; + uint32_t A, B, C, D, E, F, G, H; + uint32_t T[64]; + uint32_t Temp1, Temp2, Temp3, Temp4, Temp5; + int j; + + for (j = 0; j < 16; j++) + T[j] = 0x79CC4519; + for (j = 16; j < 64; j++) + T[j] = 0x7A879D8A; + + GET_UINT32_BE(W[0], data, 0); + GET_UINT32_BE(W[1], data, 4); + GET_UINT32_BE(W[2], data, 8); + GET_UINT32_BE(W[3], data, 12); + GET_UINT32_BE(W[4], data, 16); + GET_UINT32_BE(W[5], data, 20); + GET_UINT32_BE(W[6], data, 24); + GET_UINT32_BE(W[7], data, 28); + GET_UINT32_BE(W[8], data, 32); + GET_UINT32_BE(W[9], data, 36); + GET_UINT32_BE(W[10], data, 40); + GET_UINT32_BE(W[11], data, 44); + GET_UINT32_BE(W[12], data, 48); + GET_UINT32_BE(W[13], data, 52); + GET_UINT32_BE(W[14], data, 56); + GET_UINT32_BE(W[15], data, 60); + +#define FF0(x, y, z) ((x) ^ (y) ^ (z)) +#define FF1(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) + +#define GG0(x, y, z) ((x) ^ (y) ^ (z)) +#define GG1(x, y, z) (((x) & (y)) | ((~(x)) & (z))) + +#define SHL(x, n) ((x) << (n)) +#define ROTL(x, n) (SHL((x), (n) & 0x1F) | ((x) >> (32 - ((n) & 0x1F)))) + +#define P0(x) ((x) ^ ROTL((x), 9) ^ ROTL((x), 17)) +#define P1(x) ((x) ^ ROTL((x), 15) ^ ROTL((x), 23)) + + for (j = 16; j < 68; j++) { + /* + * W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15)) ^ + * ROTL(W[j - 13],7 ) ^ W[j-6]; + */ + + Temp1 = W[j - 16] ^ W[j - 9]; + Temp2 = ROTL(W[j - 3], 15); + Temp3 = Temp1 ^ Temp2; + Temp4 = P1(Temp3); + Temp5 = ROTL(W[j - 13], 7) ^ W[j - 6]; + W[j] = Temp4 ^ Temp5; + } + + for (j = 0; j < 64; j++) + W1[j] = W[j] ^ W[j + 4]; + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + + for (j = 0; j < 16; j++) { + SS1 = ROTL(ROTL(A, 12) + E + ROTL(T[j], j), 7); + SS2 = SS1 ^ ROTL(A, 12); + TT1 = FF0(A, B, C) + D + SS2 + W1[j]; + TT2 = GG0(E, F, G) + H + SS1 + W[j]; + D = C; + C = ROTL(B, 9); + B = A; + A = TT1; + H = G; + G = ROTL(F, 19); + F = E; + E = P0(TT2); + } + + for (j = 16; j < 64; j++) { + SS1 = ROTL(ROTL(A, 12) + E + ROTL(T[j], j), 7); + SS2 = SS1 ^ ROTL(A, 12); + TT1 = FF1(A, B, C) + D + SS2 + W1[j]; + TT2 = GG1(E, F, G) + H + SS1 + W[j]; + D = C; + C = ROTL(B, 9); + B = A; + A = TT1; + H = G; + G = ROTL(F, 19); + F = E; + E = P0(TT2); + } + + ctx->state[0] ^= A; + ctx->state[1] ^= B; + ctx->state[2] ^= C; + ctx->state[3] ^= D; + ctx->state[4] ^= E; + ctx->state[5] ^= F; + ctx->state[6] ^= G; + ctx->state[7] ^= H; +} + +static void sm3_process_blocks(struct sm3_context *ctx, const uint8_t *input, + unsigned int block_count) +{ +#ifdef CFG_CRYPTO_SM3_ARM_CE + if (block_count) + crypto_accel_sm3_compress(ctx->state, input, block_count); +#else + unsigned int n = 0; + + for (n = 0; n < block_count; n++) + sm3_process(ctx, input + n * SM3_BLOCK_SIZE); +#endif +} + +void sm3_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen) +{ + unsigned int block_count = 0; + size_t fill = 0; + size_t left = 0; + + if (!ilen) + return; + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += ilen; + + if (ctx->total[0] < ilen) + ctx->total[1]++; + + if (left && ilen >= fill) { + memcpy(ctx->buffer + left, input, fill); + sm3_process_blocks(ctx, ctx->buffer, 1); + input += fill; + ilen -= fill; + left = 0; + } + + block_count = ilen / SM3_BLOCK_SIZE; + sm3_process_blocks(ctx, input, block_count); + ilen -= block_count * SM3_BLOCK_SIZE; + input += block_count * SM3_BLOCK_SIZE; + + if (ilen > 0) + memcpy(ctx->buffer + left, input, ilen); +} + +static const uint8_t sm3_padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void sm3_final(struct sm3_context *ctx, uint8_t output[32]) +{ + uint32_t last, padn; + uint32_t high, low; + uint8_t msglen[8]; + + high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); + low = ctx->total[0] << 3; + + PUT_UINT32_BE(high, msglen, 0); + PUT_UINT32_BE(low, msglen, 4); + + last = ctx->total[0] & 0x3F; + padn = (last < 56) ? (56 - last) : (120 - last); + + sm3_update(ctx, sm3_padding, padn); + sm3_update(ctx, msglen, 8); + + PUT_UINT32_BE(ctx->state[0], output, 0); + PUT_UINT32_BE(ctx->state[1], output, 4); + PUT_UINT32_BE(ctx->state[2], output, 8); + PUT_UINT32_BE(ctx->state[3], output, 12); + PUT_UINT32_BE(ctx->state[4], output, 16); + PUT_UINT32_BE(ctx->state[5], output, 20); + PUT_UINT32_BE(ctx->state[6], output, 24); + PUT_UINT32_BE(ctx->state[7], output, 28); +} + +void sm3(const uint8_t *input, size_t ilen, uint8_t output[32]) +{ + struct sm3_context ctx = { }; + + sm3_init(&ctx); + sm3_update(&ctx, input, ilen); + sm3_final(&ctx, output); + + memzero_explicit(&ctx, sizeof(ctx)); +} + +void sm3_hmac_init(struct sm3_context *ctx, const uint8_t *key, size_t keylen) +{ + size_t i; + uint8_t sum[32]; + + if (keylen > 64) { + sm3(key, keylen, sum); + keylen = 32; + key = sum; + } + + memset(ctx->ipad, 0x36, 64); + memset(ctx->opad, 0x5C, 64); + + for (i = 0; i < keylen; i++) { + ctx->ipad[i] ^= key[i]; + ctx->opad[i] ^= key[i]; + } + + sm3_init(ctx); + sm3_update(ctx, ctx->ipad, 64); + + memzero_explicit(sum, sizeof(sum)); +} + +void sm3_hmac_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen) +{ + sm3_update(ctx, input, ilen); +} + +void sm3_hmac_final(struct sm3_context *ctx, uint8_t output[32]) +{ + uint8_t tmpbuf[32]; + + sm3_final(ctx, tmpbuf); + sm3_init(ctx); + sm3_update(ctx, ctx->opad, 64); + sm3_update(ctx, tmpbuf, 32); + sm3_final(ctx, output); + + memzero_explicit(tmpbuf, sizeof(tmpbuf)); +} + +void sm3_hmac(const uint8_t *key, size_t keylen, const uint8_t *input, + size_t ilen, uint8_t output[32]) +{ + struct sm3_context ctx; + + sm3_hmac_init(&ctx, key, keylen); + sm3_hmac_update(&ctx, input, ilen); + sm3_hmac_final(&ctx, output); + + memzero_explicit(&ctx, sizeof(ctx)); +} diff --git a/optee/optee_os/core/crypto/sm3.h b/optee/optee_os/core/crypto/sm3.h new file mode 100644 index 0000000..7bf9afd --- /dev/null +++ b/optee/optee_os/core/crypto/sm3.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019 Huawei Technologies Co., Ltd + */ +/** + * \file sm3.h + * thanks to Xyssl + * author:goldboar + * email:goldboar@163.com + * 2011-10-26 + */ +#ifndef CORE_CRYPTO_SM3_H +#define CORE_CRYPTO_SM3_H + +#include +#include + +struct sm3_context { + uint32_t total[2]; /* number of bytes processed */ + uint32_t state[8]; /* intermediate digest state */ + uint8_t buffer[64]; /* data block being processed */ + uint8_t ipad[64]; /* HMAC: inner padding */ + uint8_t opad[64]; /* HMAC: outer padding */ +}; + +void sm3_init(struct sm3_context *ctx); +void sm3_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen); +void sm3_final(struct sm3_context *ctx, uint8_t output[32]); +void sm3(const uint8_t *input, size_t ilen, uint8_t output[32]); + +void sm3_hmac_init(struct sm3_context *ctx, const uint8_t *key, size_t keylen); +void sm3_hmac_update(struct sm3_context *ctx, const uint8_t *input, + size_t ilen); +void sm3_hmac_final(struct sm3_context *ctx, uint8_t output[32]); +void sm3_hmac(const uint8_t *key, size_t keylen, const uint8_t *input, + size_t ilen, uint8_t output[32]); + +#endif /* CORE_CRYPTO_SM3_H */ diff --git a/optee/optee_os/core/crypto/sm4-cbc.c b/optee/optee_os/core/crypto/sm4-cbc.c new file mode 100644 index 0000000..4b96a47 --- /dev/null +++ b/optee/optee_os/core/crypto/sm4-cbc.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sm4.h" + +struct sm4_cbc_ctx { + struct crypto_cipher_ctx ctx; + struct sm4_context state; + uint8_t iv[16]; +}; + +static const struct crypto_cipher_ops sm4_cbc_ops; + +static struct sm4_cbc_ctx *to_sm4_cbc_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &sm4_cbc_ops); + + return container_of(ctx, struct sm4_cbc_ctx, ctx); +} + +static TEE_Result sm4_cbc_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv, size_t iv_len) +{ + struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); + + if (key1_len != 16 || iv_len != sizeof(c->iv)) + return TEE_ERROR_BAD_PARAMETERS; + + if (mode == TEE_MODE_ENCRYPT) + sm4_setkey_enc(&c->state, key1); + else + sm4_setkey_dec(&c->state, key1); + + memcpy(c->iv, iv, sizeof(c->iv)); + + return TEE_SUCCESS; +} + +static TEE_Result sm4_cbc_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, uint8_t *dst) +{ + struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); + + sm4_crypt_cbc(&c->state, len, c->iv, data, dst); + + return TEE_SUCCESS; +} + +static void sm4_cbc_final(struct crypto_cipher_ctx *ctx) +{ + struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); + + memzero_explicit(&c->state, sizeof(c->state)); + memzero_explicit(&c->iv, sizeof(c->iv)); +} + +static void sm4_cbc_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_sm4_cbc_ctx(ctx)); +} + +static void sm4_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct sm4_cbc_ctx *src = to_sm4_cbc_ctx(src_ctx); + struct sm4_cbc_ctx *dst = to_sm4_cbc_ctx(dst_ctx); + + dst->state = src->state; + memcpy(dst->iv, src->iv, sizeof(src->iv)); +} + +static const struct crypto_cipher_ops sm4_cbc_ops = { + .init = sm4_cbc_init, + .update = sm4_cbc_update, + .final = sm4_cbc_final, + .free_ctx = sm4_cbc_free_ctx, + .copy_state = sm4_cbc_copy_state, +}; + +TEE_Result crypto_sm4_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct sm4_cbc_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &sm4_cbc_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/crypto/sm4-ctr.c b/optee/optee_os/core/crypto/sm4-ctr.c new file mode 100644 index 0000000..0b17400 --- /dev/null +++ b/optee/optee_os/core/crypto/sm4-ctr.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sm4.h" + +struct sm4_ctr_ctx { + struct crypto_cipher_ctx ctx; + struct sm4_context state; + uint8_t ctr[16]; +}; + +static const struct crypto_cipher_ops sm4_ctr_ops; + +static struct sm4_ctr_ctx *to_sm4_ctr_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &sm4_ctr_ops); + + return container_of(ctx, struct sm4_ctr_ctx, ctx); +} + +static TEE_Result sm4_ctr_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode __unused, + const uint8_t *key1, size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv, size_t iv_len) +{ + struct sm4_ctr_ctx *c = to_sm4_ctr_ctx(ctx); + + if (key1_len != 16 || iv_len != sizeof(c->ctr)) + return TEE_ERROR_BAD_PARAMETERS; + + sm4_setkey_enc(&c->state, key1); + memcpy(c->ctr, iv, sizeof(c->ctr)); + + return TEE_SUCCESS; +} + +static TEE_Result sm4_ctr_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, uint8_t *dst) +{ + struct sm4_ctr_ctx *c = to_sm4_ctr_ctx(ctx); + + sm4_crypt_ctr(&c->state, len, c->ctr, data, dst); + + return TEE_SUCCESS; +} + +static void sm4_ctr_final(struct crypto_cipher_ctx *ctx) +{ + struct sm4_ctr_ctx *c = to_sm4_ctr_ctx(ctx); + + memzero_explicit(&c->state, sizeof(c->state)); + memzero_explicit(&c->ctr, sizeof(c->ctr)); +} + +static void sm4_ctr_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_sm4_ctr_ctx(ctx)); +} + +static void sm4_ctr_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct sm4_ctr_ctx *src = to_sm4_ctr_ctx(src_ctx); + struct sm4_ctr_ctx *dst = to_sm4_ctr_ctx(dst_ctx); + + dst->state = src->state; + memcpy(dst->ctr, src->ctr, sizeof(src->ctr)); +} + +static const struct crypto_cipher_ops sm4_ctr_ops = { + .init = sm4_ctr_init, + .update = sm4_ctr_update, + .final = sm4_ctr_final, + .free_ctx = sm4_ctr_free_ctx, + .copy_state = sm4_ctr_copy_state, +}; + +TEE_Result crypto_sm4_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct sm4_ctr_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &sm4_ctr_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/crypto/sm4-ecb.c b/optee/optee_os/core/crypto/sm4-ecb.c new file mode 100644 index 0000000..2cd394d --- /dev/null +++ b/optee/optee_os/core/crypto/sm4-ecb.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sm4.h" + +struct sm4_ecb_ctx { + struct crypto_cipher_ctx ctx; + struct sm4_context state; +}; + +static const struct crypto_cipher_ops sm4_ecb_ops; + +static struct sm4_ecb_ctx *to_sm4_ecb_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &sm4_ecb_ops); + + return container_of(ctx, struct sm4_ecb_ctx, ctx); +} + +static TEE_Result sm4_ecb_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct sm4_ecb_ctx *c = to_sm4_ecb_ctx(ctx); + + if (key1_len != 16) + return TEE_ERROR_BAD_STATE; + + if (mode == TEE_MODE_ENCRYPT) + sm4_setkey_enc(&c->state, key1); + else + sm4_setkey_dec(&c->state, key1); + + return TEE_SUCCESS; +} + +static TEE_Result sm4_ecb_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, uint8_t *dst) +{ + struct sm4_ecb_ctx *c = to_sm4_ecb_ctx(ctx); + + sm4_crypt_ecb(&c->state, len, data, dst); + + return TEE_SUCCESS; +} + +static void sm4_ecb_final(struct crypto_cipher_ctx *ctx) +{ + struct sm4_ecb_ctx *c = to_sm4_ecb_ctx(ctx); + + memzero_explicit(&c->state, sizeof(c->state)); +} + +static void sm4_ecb_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_sm4_ecb_ctx(ctx)); +} + +static void sm4_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct sm4_ecb_ctx *src = to_sm4_ecb_ctx(src_ctx); + struct sm4_ecb_ctx *dst = to_sm4_ecb_ctx(dst_ctx); + + dst->state = src->state; +} + +static const struct crypto_cipher_ops sm4_ecb_ops = { + .init = sm4_ecb_init, + .update = sm4_ecb_update, + .final = sm4_ecb_final, + .free_ctx = sm4_ecb_free_ctx, + .copy_state = sm4_ecb_copy_state, +}; + +TEE_Result crypto_sm4_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct sm4_ecb_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &sm4_ecb_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/crypto/sm4-xts.c b/optee/optee_os/core/crypto/sm4-xts.c new file mode 100644 index 0000000..a46c150 --- /dev/null +++ b/optee/optee_os/core/crypto/sm4-xts.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sm4.h" + +struct sm4_xts_ctx { + struct crypto_cipher_ctx ctx; + struct sm4_context state; + struct sm4_context state_ek; + struct sm4_context state_dk; + uint8_t iv[16]; +}; + +static const struct crypto_cipher_ops sm4_xts_ops; + +static struct sm4_xts_ctx *to_sm4_xts_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &sm4_xts_ops); + + return container_of(ctx, struct sm4_xts_ctx, ctx); +} + +static TEE_Result sm4_xts_init(struct crypto_cipher_ctx *ctx, + 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) +{ + struct sm4_xts_ctx *c = to_sm4_xts_ctx(ctx); + + if (key1_len != 16 || key2_len != 16 || iv_len != sizeof(c->iv)) + return TEE_ERROR_BAD_STATE; + + if (iv) + memcpy(c->iv, iv, sizeof(c->iv)); + + if (mode == TEE_MODE_ENCRYPT) + sm4_setkey_enc(&c->state, key1); + else + sm4_setkey_dec(&c->state, key1); + + sm4_setkey_enc(&c->state_ek, key2); + sm4_setkey_dec(&c->state_dk, key2); + + return TEE_SUCCESS; +} + +static TEE_Result sm4_xts_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, const uint8_t *data, + size_t len, uint8_t *dst) +{ + struct sm4_xts_ctx *c = to_sm4_xts_ctx(ctx); + + sm4_crypt_xts(&c->state, &c->state_ek, &c->state_dk, + len, c->iv, data, dst); + + return TEE_SUCCESS; +} + +static void sm4_xts_final(struct crypto_cipher_ctx *ctx) +{ + struct sm4_xts_ctx *c = to_sm4_xts_ctx(ctx); + + memzero_explicit(&c->state, sizeof(c->state)); + memzero_explicit(&c->state_ek, sizeof(c->state_ek)); + memzero_explicit(&c->state_dk, sizeof(c->state_dk)); + memzero_explicit(&c->iv, sizeof(c->iv)); +} + +static void sm4_xts_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_sm4_xts_ctx(ctx)); +} + +static void sm4_xts_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct sm4_xts_ctx *src = to_sm4_xts_ctx(src_ctx); + struct sm4_xts_ctx *dst = to_sm4_xts_ctx(dst_ctx); + + dst->state = src->state; + dst->state_ek = src->state_ek; + dst->state_dk = src->state_dk; + memcpy(dst->iv, src->iv, sizeof(src->iv)); +} + +static const struct crypto_cipher_ops sm4_xts_ops = { + .init = sm4_xts_init, + .update = sm4_xts_update, + .final = sm4_xts_final, + .free_ctx = sm4_xts_free_ctx, + .copy_state = sm4_xts_copy_state, +}; + +TEE_Result crypto_sm4_xts_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct sm4_xts_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &sm4_xts_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/crypto/sm4.c b/optee/optee_os/core/crypto/sm4.c new file mode 100644 index 0000000..8f1dd0d --- /dev/null +++ b/optee/optee_os/core/crypto/sm4.c @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright Copyright (c) 2019 Huawei Technologies Co., Ltd + */ +/* + * SM4 Encryption algorithm (SMS4 algorithm) + * GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/ + * thanks to Xyssl + * thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html + * author:goldboar + * email:goldboar@163.com + * 2012-4-20 + */ + +#include "sm4.h" +#include +#include + +#define GET_UINT32_BE(n, b, i) \ + do { \ + (n) = ((uint32_t)(b)[(i)] << 24) | \ + ((uint32_t)(b)[(i) + 1] << 16) | \ + ((uint32_t)(b)[(i) + 2] << 8) | \ + ((uint32_t)(b)[(i) + 3]); \ + } while (0) + +#define PUT_UINT32_BE(n, b, i) \ + do { \ + (b)[(i)] = (uint8_t)((n) >> 24); \ + (b)[(i) + 1] = (uint8_t)((n) >> 16); \ + (b)[(i) + 2] = (uint8_t)((n) >> 8); \ + (b)[(i) + 3] = (uint8_t)((n)); \ + } while (0) + +#define SHL(x, n) (((x) & 0xFFFFFFFF) << (n)) +#define ROTL(x, n) (SHL((x), (n)) | ((x) >> (32 - (n)))) + +#define SWAP(a, b) { uint32_t t = a; a = b; b = t; t = 0; } + +/* + * Expanded SM4 S-boxes + */ +static const uint8_t SboxTable[16][16] = { + {0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05}, + {0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, + 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99}, + {0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, + 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62}, + {0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, + 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6}, + {0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, + 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8}, + {0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, + 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35}, + {0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, + 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87}, + {0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, + 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e}, + {0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, + 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1}, + {0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, + 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3}, + {0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, + 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f}, + {0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, + 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51}, + {0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, + 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8}, + {0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, + 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0}, + {0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, + 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84}, + {0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, + 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48} +}; + +/* System parameter */ +static const uint32_t FK[4] = { + 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc +}; + +/* Fixed parameter */ +static const uint32_t CK[32] = { + 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, + 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, + 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, + 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, + 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, + 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, + 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, + 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 +}; + +static uint8_t sm4Sbox(uint8_t inch) +{ + uint8_t *tab = (uint8_t *)SboxTable; + + return tab[inch]; +} + +static uint32_t sm4Lt(uint32_t ka) +{ + uint32_t bb = 0; + uint8_t a[4]; + uint8_t b[4]; + + PUT_UINT32_BE(ka, a, 0); + b[0] = sm4Sbox(a[0]); + b[1] = sm4Sbox(a[1]); + b[2] = sm4Sbox(a[2]); + b[3] = sm4Sbox(a[3]); + GET_UINT32_BE(bb, b, 0); + + return bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24); +} + +static uint32_t sm4F(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, + uint32_t rk) +{ + return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk); +} + +static uint32_t sm4CalciRK(uint32_t ka) +{ + uint32_t bb = 0; + uint8_t a[4]; + uint8_t b[4]; + + PUT_UINT32_BE(ka, a, 0); + b[0] = sm4Sbox(a[0]); + b[1] = sm4Sbox(a[1]); + b[2] = sm4Sbox(a[2]); + b[3] = sm4Sbox(a[3]); + GET_UINT32_BE(bb, b, 0); + + return bb ^ ROTL(bb, 13) ^ ROTL(bb, 23); +} + +static void sm4_setkey(uint32_t SK[32], const uint8_t key[16]) +{ + uint32_t MK[4]; + uint32_t k[36]; + uint32_t i = 0; + + GET_UINT32_BE(MK[0], key, 0); + GET_UINT32_BE(MK[1], key, 4); + GET_UINT32_BE(MK[2], key, 8); + GET_UINT32_BE(MK[3], key, 12); + + k[0] = MK[0] ^ FK[0]; + k[1] = MK[1] ^ FK[1]; + k[2] = MK[2] ^ FK[2]; + k[3] = MK[3] ^ FK[3]; + + for (i = 0; i < 32; i++) { + k[i + 4] = k[i] ^ sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ + CK[i]); + SK[i] = k[i + 4]; + } +} + +static void sm4_one_round(uint32_t sk[32], const uint8_t input[16], + uint8_t output[16]) +{ + uint32_t i = 0; + uint32_t ulbuf[36]; + + memset(ulbuf, 0, sizeof(ulbuf)); + + GET_UINT32_BE(ulbuf[0], input, 0); + GET_UINT32_BE(ulbuf[1], input, 4); + GET_UINT32_BE(ulbuf[2], input, 8); + GET_UINT32_BE(ulbuf[3], input, 12); + + for (i = 0; i < 32; i++) + ulbuf[i + 4] = sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2], + ulbuf[i + 3], sk[i]); + + PUT_UINT32_BE(ulbuf[35], output, 0); + PUT_UINT32_BE(ulbuf[34], output, 4); + PUT_UINT32_BE(ulbuf[33], output, 8); + PUT_UINT32_BE(ulbuf[32], output, 12); +} + +void sm4_setkey_enc(struct sm4_context *ctx, const uint8_t key[16]) +{ + ctx->mode = SM4_ENCRYPT; + sm4_setkey(ctx->sk, key); +} + +void sm4_setkey_dec(struct sm4_context *ctx, const uint8_t key[16]) +{ + int i; + + ctx->mode = SM4_DECRYPT; + sm4_setkey(ctx->sk, key); + + for (i = 0; i < 16; i++) + SWAP(ctx->sk[i], ctx->sk[31 - i]); +} + +void sm4_crypt_ecb(struct sm4_context *ctx, size_t length, const uint8_t *input, + uint8_t *output) +{ + assert(!(length % 16)); + + while (length > 0) { + sm4_one_round(ctx->sk, input, output); + input += 16; + output += 16; + length -= 16; + } +} + +void sm4_crypt_cbc(struct sm4_context *ctx, size_t length, uint8_t iv[16], + const uint8_t *input, uint8_t *output) +{ + int i; + uint8_t temp[16]; + + assert(!(length % 16)); + + if (ctx->mode == SM4_ENCRYPT) { + while (length > 0) { + for (i = 0; i < 16; i++) + output[i] = (uint8_t)(input[i] ^ iv[i]); + sm4_one_round(ctx->sk, output, output); + memcpy(iv, output, 16); + input += 16; + output += 16; + length -= 16; + } + } else { + /* SM4_DECRYPT */ + while (length > 0) { + memcpy(temp, input, 16); + sm4_one_round(ctx->sk, input, output); + for (i = 0; i < 16; i++) + output[i] = (uint8_t)(output[i] ^ iv[i]); + memcpy(iv, temp, 16); + input += 16; + output += 16; + length -= 16; + } + } +} + +void sm4_crypt_ctr(struct sm4_context *ctx, size_t length, uint8_t ctr[16], + const uint8_t *input, uint8_t *output) +{ + int i; + uint8_t temp[16]; + + assert(!(length % 16)); + + while (length > 0) { + memcpy(temp, ctr, 16); + sm4_one_round(ctx->sk, ctr, ctr); + for (i = 0; i < 16; i++) + output[i] = (uint8_t)(input[i] ^ ctr[i]); + memcpy(ctr, temp, 16); + for (i = 16; i > 0; i--) + if (++ctr[i - 1]) + break; + input += 16; + output += 16; + length -= 16; + } +} + +static void xts_multi(unsigned char *in, unsigned char *out) +{ + uint8_t tt = 0; + uint8_t t = 0; + int i = 0; + + for (i = 0; i < 16; i++) { + tt = in[i] >> 7; + out[i] = ((in[i] << 1) | t) & 0xFF; + t = tt; + } + + out[0] ^= (0x87 & (0 - tt)); +} + +static void xor_128(const uint8_t a[16], const uint8_t b[16], uint8_t c[16]) +{ + int i = 0; + + for (i = 0; i < 16; i++) + c[i] = a[i] ^ b[i]; +} + +void sm4_crypt_xts(struct sm4_context *ctx, struct sm4_context *ctx_ek, + struct sm4_context *ctx_dk, size_t len, uint8_t *iv, + const uint8_t *input, uint8_t *output) +{ + uint8_t tweak[16] = { }; + uint8_t tweak1[16] = { }; + uint8_t ct[16] = { }; + size_t i = 0; + + assert(len >= 16); + + sm4_one_round(ctx_ek->sk, iv, tweak); + + if (ctx->mode == SM4_DECRYPT && (len % 16)) + len -= 16; + + while (len >= 16) { + xor_128(input, tweak, ct); + sm4_one_round(ctx->sk, ct, ct); + xor_128(ct, tweak, output); + + xts_multi(tweak, tweak); + len -= 16; + if (len == 0) { + sm4_one_round(ctx_dk->sk, tweak, iv); + return; + } + input += 16; + output += 16; + } + + if (ctx->mode == SM4_ENCRYPT) { + memcpy(ct, output - 16, 16); + for (i = 0; i < len; i++) { + output[i] = ct[i]; + ct[i] = input[i]; + } + + xor_128(ct, tweak, ct); + sm4_one_round(ctx->sk, ct, ct); + xor_128(ct, tweak, ct); + memcpy(output - 16, ct, 16); + } else { + xts_multi(tweak, tweak1); + xor_128(input, tweak1, ct); + sm4_one_round(ctx->sk, ct, ct); + xor_128(ct, tweak1, ct); + + for (i = 0; i < len; ++i) { + output[16 + i] = ct[i]; + ct[i] = input[16 + i]; + } + xor_128(ct, tweak, ct); + sm4_one_round(ctx->sk, ct, ct); + xor_128(ct, tweak, output); + } +} diff --git a/optee/optee_os/core/crypto/sm4.h b/optee/optee_os/core/crypto/sm4.h new file mode 100644 index 0000000..21d075a --- /dev/null +++ b/optee/optee_os/core/crypto/sm4.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019 Huawei Technologies Co., Ltd + */ +#ifndef CORE_CRYPTO_SM4_H +#define CORE_CRYPTO_SM4_H + +#include +#include + +#define SM4_ENCRYPT 1 +#define SM4_DECRYPT 0 + +struct sm4_context { + int mode; /* SM4_ENCRYPT/SM4_DECRYPT */ + uint32_t sk[32]; /* SM4 subkeys */ +}; + +void sm4_setkey_enc(struct sm4_context *ctx, const uint8_t key[16]); +void sm4_setkey_dec(struct sm4_context *ctx, const uint8_t key[16]); +void sm4_crypt_ecb(struct sm4_context *ctx, size_t length, const uint8_t *input, + uint8_t *output); +void sm4_crypt_cbc(struct sm4_context *ctx, size_t length, uint8_t iv[16], + const uint8_t *input, uint8_t *output); +void sm4_crypt_ctr(struct sm4_context *ctx, size_t length, uint8_t ctr[16], + const uint8_t *input, uint8_t *output); +void sm4_crypt_xts(struct sm4_context *ctx, struct sm4_context *ctx_ek, + struct sm4_context *ctx_dk, size_t length, uint8_t *iv, + const uint8_t *input, uint8_t *output); + +#endif /* CORE_CRYPTO_SM4_H */ diff --git a/optee/optee_os/core/crypto/sm4_accel.c b/optee/optee_os/core/crypto/sm4_accel.c new file mode 100644 index 0000000..4c3d9f7 --- /dev/null +++ b/optee/optee_os/core/crypto/sm4_accel.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. + * + * SM4 optimization for ARMv8 + */ + +#include "sm4.h" +#include +#include +#include + +void sm4_setkey_enc(struct sm4_context *ctx, const uint8_t key[16]) +{ + ctx->mode = SM4_ENCRYPT; + crypto_accel_sm4_setkey_enc(ctx->sk, key); +} + +void sm4_setkey_dec(struct sm4_context *ctx, const uint8_t key[16]) +{ + ctx->mode = SM4_DECRYPT; + crypto_accel_sm4_setkey_dec(ctx->sk, key); +} + +void sm4_crypt_ecb(struct sm4_context *ctx, size_t length, const uint8_t *input, + uint8_t *output) +{ + assert(!(length % 16)); + + crypto_accel_sm4_ecb_enc(output, input, ctx->sk, length); +} + +void sm4_crypt_cbc(struct sm4_context *ctx, size_t length, uint8_t iv[16], + const uint8_t *input, uint8_t *output) +{ + assert(!(length % 16)); + + if (ctx->mode == SM4_ENCRYPT) + crypto_accel_sm4_cbc_enc(output, input, ctx->sk, length, iv); + else + /* SM4_DECRYPT */ + crypto_accel_sm4_cbc_dec(output, input, ctx->sk, length, iv); +} + +void sm4_crypt_ctr(struct sm4_context *ctx, size_t length, uint8_t ctr[16], + const uint8_t *input, uint8_t *output) +{ + assert(!(length % 16)); + + crypto_accel_sm4_ctr_enc(output, input, ctx->sk, length, ctr); +} + +void sm4_crypt_xts(struct sm4_context *ctx, struct sm4_context *ctx_ek, + struct sm4_context *ctx_dk __unused, size_t len, uint8_t *iv, + const uint8_t *input, uint8_t *output) +{ + assert(len >= 16); + + if (ctx->mode == SM4_ENCRYPT) + crypto_accel_sm4_xts_enc(output, input, ctx->sk, ctx_ek->sk, + len, iv); + else + crypto_accel_sm4_xts_dec(output, input, ctx->sk, ctx_ek->sk, + len, iv); +} diff --git a/optee/optee_os/core/crypto/sub.mk b/optee/optee_os/core/crypto/sub.mk new file mode 100644 index 0000000..223e5d6 --- /dev/null +++ b/optee/optee_os/core/crypto/sub.mk @@ -0,0 +1,45 @@ +srcs-y += crypto.c + +ifeq (y-y,$(CFG_CRYPTO_AES)-$(CFG_CRYPTO_GCM)) +srcs-y += aes-gcm.c +ifneq ($(CFG_CRYPTO_WITH_CE),y) +srcs-y += aes-gcm-sw.c +ifeq ($(CFG_AES_GCM_TABLE_BASED),y) +srcs-y += aes-gcm-ghash-tbl.c +endif +endif +endif + +srcs-$(CFG_WITH_USER_TA) += signed_hdr.c + +ifeq ($(CFG_WITH_SOFTWARE_PRNG),y) +srcs-y += rng_fortuna.c +else +srcs-y += rng_hw.c +endif + +ifneq ($(CFG_CRYPTO_CBC_MAC_FROM_CRYPTOLIB),y) +srcs-$(CFG_CRYPTO_CBC_MAC) += cbc-mac.c +endif +ifneq ($(CFG_CRYPTO_CTS_FROM_CRYPTOLIB),y) +srcs-$(CFG_CRYPTO_CTS) += aes-cts.c +endif +ifneq (,$(filter y,$(CFG_CRYPTO_SM2_PKE) $(CFG_CRYPTO_SM2_KEP))) +srcs-y += sm2-kdf.c +endif +ifeq ($(CFG_CRYPTO_SM3),y) +srcs-y += sm3.c +srcs-y += sm3-hash.c +srcs-$(CFG_CRYPTO_HMAC) += sm3-hmac.c +endif +ifeq ($(CFG_CRYPTO_SM4),y) +ifeq ($(CFG_CORE_CRYPTO_SM4_ACCEL)-$(CFG_ARM64_core),y-y) +srcs-$(CFG_ARM64_core) += sm4_accel.c +else +srcs-y += sm4.c +endif +srcs-$(CFG_CRYPTO_ECB) += sm4-ecb.c +srcs-$(CFG_CRYPTO_CBC) += sm4-cbc.c +srcs-$(CFG_CRYPTO_CTR) += sm4-ctr.c +srcs-$(CFG_CRYPTO_XTS) += sm4-xts.c +endif diff --git a/optee/optee_os/core/drivers/amlogic_uart.c b/optee/optee_os/core/drivers/amlogic_uart.c new file mode 100644 index 0000000..70dfcf4 --- /dev/null +++ b/optee/optee_os/core/drivers/amlogic_uart.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020 Carlo Caione + */ + +#include +#include +#include +#include +#include + +/* Registers */ +#define AML_UART_WFIFO 0x0000 +#define AML_UART_RFIFO 0x0004 +#define AML_UART_CONTROL 0x0008 +#define AML_UART_STATUS 0x000C +#define AML_UART_MISC 0x0010 +#define AML_UART_SIZE 0x0014 + +/* AML_UART_STATUS bits */ +#define AML_UART_RX_EMPTY BIT(20) +#define AML_UART_TX_FULL BIT(21) +#define AML_UART_TX_EMPTY BIT(22) + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct amlogic_uart_data *pd = + container_of(chip, struct amlogic_uart_data, chip); + + return io_pa_or_va(&pd->base, AML_UART_SIZE); +} + +static void amlogic_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read32(base + AML_UART_STATUS) & AML_UART_TX_EMPTY)) + ; +} + +static int amlogic_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + if (io_read32(base + AML_UART_STATUS) & AML_UART_RX_EMPTY) + return -1; + + return io_read32(base + AML_UART_RFIFO) & 0xff; +} + +static void amlogic_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + while (io_read32(base + AML_UART_STATUS) & AML_UART_TX_FULL) + ; + + io_write32(base + AML_UART_WFIFO, ch); +} + +static const struct serial_ops amlogic_uart_ops = { + .flush = amlogic_uart_flush, + .getchar = amlogic_uart_getchar, + .putc = amlogic_uart_putc, +}; + +void amlogic_uart_init(struct amlogic_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &amlogic_uart_ops; + + /* + * Do nothing, debug uart (AO) shared with normal world, everything for + * uart initialization is done in bootloader. + */ +} diff --git a/optee/optee_os/core/drivers/atmel_piobu.c b/optee/optee_os/core/drivers/atmel_piobu.c new file mode 100644 index 0000000..fa40b0e --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_piobu.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + * + * Driver for AT91 PIOBU + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SECUMOD_MAX_PINS 8 +#define SECUMOD_PIN_MASK (BIT(SECUMOD_MAX_PINS) - 1) +#define SECUMOD_PIN_SHIFT 16 +#define SECUMOD_PIN_VAL(pin) BIT(SECUMOD_PIN_SHIFT + (pin)) + +#define DT_GPIO_CELLS 2 + +#define SECUMOD_CR 0x0 +#define SECUMOD_CR_KEY_SHIFT 16 +#define SECUMOD_CR_KEY SHIFT_U32(0x89CA, SECUMOD_CR_KEY_SHIFT) +#define SECUMOD_CR_BACKUP BIT(0) +#define SECUMOD_CR_NORMAL BIT(1) + +#define SECUMOD_SR 0x8 +#define SECUMOD_SR_JTAG BIT(3) +#define SECUMOD_SR_TST_PIN BIT(2) + +#define SECUMOD_SCR 0x10 + +#define SECUMOD_PIOBU(x) (0x18 + (x) * 0x4) +#define SECUMOD_PIOBU_AFV_MASK GENMASK_32(3, 0) +#define SECUMOD_PIOBU_RFV_SHIFT 4 +#define SECUMOD_PIOBU_OUTPUT BIT(8) +#define SECUMOD_PIOBU_SOD BIT(9) +#define SECUMOD_PIOBU_PDS BIT(10) +#define SECUMOD_PIOBU_PULLUP_SHIFT 12 +#define SECUMOD_PIOBU_SWITCH_SHIFT 15 + +#define SECUMOD_JTAGCR 0x68 +#define SECUMOD_JTAGCR_FNTRST 0x1 + +#define SECUMOD_BMPR 0x7C +#define SECUMOD_NMPR 0x80 +#define SECUMOD_NIEPR 0x84 +#define SECUMOD_NIDPR 0x88 +#define SECUMOD_NIMPR 0x8C +#define SECUMOD_WKPR 0x90 + +static vaddr_t secumod_base; +static uint32_t gpio_protected; +static struct gpio_chip secumod_chip; + +/* + * Get value from GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin from which value needs to be read + * Return target GPIO pin level. + */ +static enum gpio_level gpio_get_value(struct gpio_chip *chip __unused, + unsigned int gpio_pin) +{ + vaddr_t piobu_addr = 0; + uint32_t piobu = 0; + + assert(gpio_pin < SECUMOD_MAX_PINS && + !(gpio_protected & BIT32(gpio_pin))); + + piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); + piobu = io_read32(piobu_addr); + + if (piobu & SECUMOD_PIOBU_PDS) + return GPIO_LEVEL_HIGH; + else + return GPIO_LEVEL_LOW; +} + +/* + * Set value for GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin to which value needs to be written + * value: Level state for the target pin + */ +static void gpio_set_value(struct gpio_chip *chip __unused, + unsigned int gpio_pin, enum gpio_level value) +{ + vaddr_t piobu_addr = 0; + + assert(gpio_pin < SECUMOD_MAX_PINS && + !(gpio_protected & BIT32(gpio_pin))); + + piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); + + if (value == GPIO_LEVEL_HIGH) + io_setbits32(piobu_addr, SECUMOD_PIOBU_SOD); + else + io_clrbits32(piobu_addr, SECUMOD_PIOBU_SOD); +} + +/* + * Get direction from GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin from which direction needs to be read + */ +static enum gpio_dir gpio_get_direction(struct gpio_chip *chip __unused, + unsigned int gpio_pin) +{ + vaddr_t piobu_addr = 0; + uint32_t piobu = 0; + + assert(gpio_pin < SECUMOD_MAX_PINS && + !(gpio_protected & BIT32(gpio_pin))); + + piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); + piobu = io_read32(piobu_addr); + + if (piobu & SECUMOD_PIOBU_OUTPUT) + return GPIO_DIR_OUT; + else + return GPIO_DIR_IN; +} + +/* + * Set direction for GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin on which direction needs to be set + * direction: direction which needs to be set on pin + */ +static void gpio_set_direction(struct gpio_chip *chip __unused, + unsigned int gpio_pin, enum gpio_dir direction) +{ + vaddr_t piobu_addr = 0; + + assert(gpio_pin < SECUMOD_MAX_PINS && + !(gpio_protected & BIT32(gpio_pin))); + + piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); + + if (direction == GPIO_DIR_OUT) + io_setbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); + else + io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); +} + +/* + * Get interrupt from GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin from which interrupt value needs to be read + */ +static enum gpio_interrupt gpio_get_interrupt(struct gpio_chip *chip __unused, + unsigned int gpio_pin) +{ + vaddr_t nimpr_addr = secumod_base + SECUMOD_NIMPR; + uint32_t data = 0; + + assert(gpio_pin < SECUMOD_MAX_PINS && + !(gpio_protected & BIT32(gpio_pin))); + + data = io_read32(nimpr_addr); + + if (data & SECUMOD_PIN_VAL(gpio_pin)) + return GPIO_INTERRUPT_ENABLE; + else + return GPIO_INTERRUPT_DISABLE; +} + +/* + * Set interrupt event for GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin on which interrupt value needs to be set + * interrupt: interrupt value which needs to be set on pin + */ +static void gpio_set_interrupt(struct gpio_chip *chip __unused, + unsigned int gpio_pin, + enum gpio_interrupt interrupt) +{ + vaddr_t niepr_addr = secumod_base + SECUMOD_NIEPR; + + assert(gpio_pin < SECUMOD_MAX_PINS && + !(gpio_protected & BIT32(gpio_pin))); + + if (interrupt == GPIO_INTERRUPT_ENABLE) + io_setbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); + else + io_clrbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); +} + +static const struct gpio_ops atmel_piobu_ops = { + .get_direction = gpio_get_direction, + .set_direction = gpio_set_direction, + .get_value = gpio_get_value, + .set_value = gpio_set_value, + .get_interrupt = gpio_get_interrupt, + .set_interrupt = gpio_set_interrupt, +}; + +static enum itr_return secumod_it_handler(struct itr_handler *handler __unused) +{ + int i = 0; + struct optee_rtc_time tm = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t sr = io_read32(secumod_base + SECUMOD_SR); + + for (i = 0; i < SECUMOD_MAX_PINS; i++) { + if (sr & SECUMOD_PIN_VAL(i)) + EMSG("Detected tampering on pin %d", i); + } + + if (sr & SECUMOD_SR_JTAG) + EMSG("JTAG tampering attempt"); + + if (sr & SECUMOD_SR_TST_PIN) + EMSG("Test pin tampering attempt"); + + res = atmel_rtc_get_tamper_timestamp(&tm); + if (!res) { + EMSG("Date of tampering: %02"PRIu32"/%02"PRIu32"/%02"PRIu32"", + tm.tm_mday, tm.tm_mon, tm.tm_year); + EMSG("Time of tampering: %02"PRIu32":%02"PRIu32":%02"PRIu32"", + tm.tm_hour, tm.tm_min, tm.tm_sec); + } + + io_write32(secumod_base + SECUMOD_SCR, + SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); + + panic("Tampering detected, system halted"); + + return ITRR_HANDLED; +} + +static struct itr_handler secumod_itr_handler = { + .it = AT91C_ID_SECUMOD, + .handler = secumod_it_handler, +}; + +static void secumod_interrupt_init(void) +{ + itr_add_type_prio(&secumod_itr_handler, IRQ_TYPE_LEVEL_HIGH, 7); + itr_enable(secumod_itr_handler.it); +} + +static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config) +{ + vaddr_t piobu_addr = 0; + uint8_t afv = 0; + uint8_t rfv = 0; + uint8_t pull_mode = PIOBU_PIN_PULL_NONE; + uint8_t def_level = PIOBU_PIN_DEF_LEVEL_LOW; + + assert(gpio_pin < SECUMOD_MAX_PINS); + + piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); + + /* Set GPIO as input */ + io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); + + afv = PIOBU_PIN_AFV(config); + rfv = PIOBU_PIN_RFV(config); + pull_mode = PIOBU_PIN_PULL_MODE(config); + def_level = PIOBU_PIN_DEF_LEVEL(config); + + io_write32(piobu_addr, afv | rfv << SECUMOD_PIOBU_RFV_SHIFT | + pull_mode << SECUMOD_PIOBU_PULLUP_SHIFT | + def_level << SECUMOD_PIOBU_SWITCH_SHIFT); + + /* Enable Tampering Interrupt */ + gpio_set_interrupt(&secumod_chip, gpio_pin, GPIO_INTERRUPT_ENABLE); + + /* Enable Intrusion Detection */ + io_setbits32(secumod_base + SECUMOD_NMPR, SECUMOD_PIN_VAL(gpio_pin)); + + /* Enable Wakeup */ + if (PIOBU_PIN_WAKEUP(config)) + io_setbits32(secumod_base + SECUMOD_WKPR, + SECUMOD_PIN_VAL(gpio_pin)); + + gpio_protected |= BIT32(gpio_pin); +} + +static void secumod_hw_init(const void *fdt, int node) +{ + int i = 0; + int len = 0; + uint8_t gpio_pin = 0; + uint32_t config = 0; + const uint32_t *prop = NULL; + + /* Disable JTAG Reset and Debug */ + io_write32(secumod_base + SECUMOD_JTAGCR, SECUMOD_JTAGCR_FNTRST); + + /* Switch IOs to normal mode */ + io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | + SECUMOD_CR_NORMAL); + + /* Clear all detection intrusion in normal mode */ + io_write32(secumod_base + SECUMOD_NMPR, 0); + + /* Clear Alarms */ + io_write32(secumod_base + SECUMOD_SCR, + SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); + + /* Configure each IOs */ + prop = fdt_getprop(fdt, node, "gpios", &len); + if (!prop) + return; + + len /= sizeof(uint32_t); + for (i = 0; i < len; i += DT_GPIO_CELLS) { + gpio_pin = fdt32_to_cpu(prop[i]); + config = fdt32_to_cpu(prop[i + 1]); + + secumod_cfg_input_pio(gpio_pin, config); + } +} + +#ifdef CFG_PM_ARM32 +static TEE_Result piobu_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *hdl __unused) +{ + switch (op) { + case PM_OP_RESUME: + io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | + SECUMOD_CR_NORMAL); + break; + case PM_OP_SUSPEND: + /* Enter backup mode before suspending */ + io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | + SECUMOD_CR_BACKUP); + break; + default: + panic("Invalid PM operation"); + } + + return TEE_SUCCESS; +} + +static void piobu_register_pm(void) +{ + register_pm_driver_cb(piobu_pm, NULL, "piobu"); +} +#else +static void piobu_register_pm(void) {} +#endif + +static TEE_Result atmel_secumod_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + size_t size = 0; + + if (secumod_base) + return TEE_ERROR_GENERIC; + + if (dt_map_dev(fdt, node, &secumod_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + secumod_hw_init(fdt, node); + secumod_interrupt_init(); + + secumod_chip.ops = &atmel_piobu_ops; + + piobu_register_pm(); + + return TEE_SUCCESS; +} + +static const struct dt_device_match atmel_secumod_match_table[] = { + { .compatible = "atmel,sama5d2-secumod" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_secumod_dt_driver) = { + .name = "atmel_secumod", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_secumod_match_table, + .probe = atmel_secumod_probe, +}; diff --git a/optee/optee_os/core/drivers/atmel_rstc.c b/optee/optee_os/core/drivers/atmel_rstc.c new file mode 100644 index 0000000..5fb81d4 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_rstc.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AT91_RSTC_CR 0x0 +#define AT91_RSTC_CR_KEY SHIFT_U32(0xA5, 24) +#define AT91_RSTC_CR_PROCRST BIT32(0) +#define AT91_RSTC_CR_PERRST BIT32(2) + +static vaddr_t rstc_base; + +bool atmel_rstc_available(void) +{ + return rstc_base != 0; +} + +void __noreturn atmel_rstc_reset(void) +{ + uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST | + AT91_RSTC_CR_PERRST; + + io_write32(rstc_base + AT91_RSTC_CR, val); + + /* + * After the previous write, the CPU will reset so we will never hit + * this loop. + */ + while (true) + ; +} + +static TEE_Result atmel_rstc_probe(const void *fdt, int node, + const void *compat_data __unused) + +{ + size_t size = 0; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_BAD_PARAMETERS; + + matrix_configure_periph_secure(AT91C_ID_SYS); + + if (dt_map_dev(fdt, node, &rstc_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static const struct dt_device_match atmel_rstc_match_table[] = { + { .compatible = "atmel,sama5d3-rstc" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = { + .name = "atmel_rstc", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_rstc_match_table, + .probe = atmel_rstc_probe, +}; diff --git a/optee/optee_os/core/drivers/atmel_rtc.c b/optee/optee_os/core/drivers/atmel_rtc.c new file mode 100644 index 0000000..3f79bdf --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_rtc.c @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + * + * Driver for AT91 RTC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTC_VAL(reg, val) (((val) >> RTC_## reg ## _SHIFT) & \ + RTC_## reg ##_MASK) + +#define RTC_SET_VAL(reg, val) SHIFT_U32((val) & RTC_## reg ##_MASK, \ + RTC_## reg ## _SHIFT) + +#define RTC_CR 0x0 +#define RTC_CR_UPDCAL BIT(1) +#define RTC_CR_UPDTIM BIT(0) + +#define RTC_MR 0x4 +#define RTC_MR_HR_MODE BIT(0) +#define RTC_MR_PERSIAN BIT(1) +#define RTC_MR_UTC BIT(2) +#define RTC_MR_NEGPPM BIT(4) +#define RTC_MR_CORR_SHIFT 8 +#define RTC_MR_CORR_MASK GENMASK_32(6, 0) +#define RTC_MR_CORR(val) RTC_VAL(val, MR_CORR) +#define RTC_MR_HIGHPPM BIT(15) + +#define RTC_TIMR 0x8 +#define RTC_CALR 0xC + +#define RTC_SR 0x18 +#define RTC_SR_ACKUPD BIT(0) +#define RTC_SR_SEC BIT(2) + +#define RTC_SCCR 0x1C +#define RTC_SCCR_ACKCLR BIT(0) +#define RTC_SCCR_SECCLR BIT(2) + +#define RTC_VER 0x2C +#define RTC_VER_NVTIM BIT(0) +#define RTC_VER_NVCAL BIT(1) + +#define RTC_TSTR0 0xB0 +#define RTC_TSDR0 0xB4 + +#define RTC_TSSR0 0xB8 +#define RTC_TSSR_DET_OFFSET 16 +#define RTC_TSSR_DET_COUNT 8 +#define RTC_TSSR_TST_PIN BIT(2) +#define RTC_TSSR_JTAG BIT(3) + +/* Layout of Time registers */ +#define RTC_TIME_BACKUP BIT(31) +#define RTC_TIME_HOUR_SHIFT 16 +#define RTC_TIME_HOUR_MASK GENMASK_32(5, 0) +#define RTC_TIME_MIN_SHIFT 8 +#define RTC_TIME_MIN_MASK GENMASK_32(6, 0) +#define RTC_TIME_SEC_SHIFT 0 +#define RTC_TIME_SEC_MASK GENMASK_32(6, 0) + +/* Layout of Calendar registers */ +#define RTC_CAL_DATE_SHIFT 24 +#define RTC_CAL_DATE_MASK GENMASK_32(5, 0) +#define RTC_CAL_DAY_SHIFT 21 +#define RTC_CAL_DAY_MASK GENMASK_32(2, 0) +#define RTC_CAL_MONTH_SHIFT 16 +#define RTC_CAL_MONTH_MASK GENMASK_32(4, 0) +#define RTC_CAL_YEAR_SHIFT 8 +#define RTC_CAL_YEAR_MASK GENMASK_32(7, 0) +#define RTC_CAL_CENT_SHIFT 0 +#define RTC_CAL_CENT_MASK GENMASK_32(6, 0) + +#define ATMEL_RTC_CORR_DIVIDEND 3906000 +#define ATMEL_RTC_CORR_LOW_RATIO 20 + +static vaddr_t rtc_base; + +static uint8_t bcd_decode(uint8_t dcb_val) +{ + return (dcb_val & 0xF) + (dcb_val >> 4) * 10; +} + +static uint8_t bcd_encode(uint32_t value) +{ + return ((value / 10) << 4) + value % 10; +} + +static uint32_t atmel_rtc_read(unsigned int offset) +{ + return io_read32(rtc_base + offset); +} + +static void atmel_rtc_write(unsigned int offset, uint32_t val) +{ + return io_write32(rtc_base + offset, val); +} + +static void atmel_decode_date(unsigned int time_reg, unsigned int cal_reg, + struct optee_rtc_time *tm) +{ + uint32_t time = 0; + uint32_t date = 0; + + /* Must read twice in case it changes */ + do { + time = atmel_rtc_read(time_reg); + date = atmel_rtc_read(cal_reg); + } while ((time != atmel_rtc_read(time_reg)) || + (date != atmel_rtc_read(cal_reg))); + + tm->tm_wday = bcd_decode(RTC_VAL(CAL_DAY, date)) - 1; + tm->tm_mday = bcd_decode(RTC_VAL(CAL_DATE, date)); + tm->tm_mon = bcd_decode(RTC_VAL(CAL_MONTH, date)) - 1; + tm->tm_year = bcd_decode(RTC_VAL(CAL_CENT, date)) * 100; + tm->tm_year += bcd_decode(RTC_VAL(CAL_YEAR, date)); + + tm->tm_hour = bcd_decode(RTC_VAL(TIME_HOUR, time)); + tm->tm_min = bcd_decode(RTC_VAL(TIME_MIN, time)); + tm->tm_sec = bcd_decode(RTC_VAL(TIME_SEC, time)); +} + +static TEE_Result atmel_rtc_get_time(struct rtc *rtc __unused, + struct optee_rtc_time *tm) +{ + atmel_decode_date(RTC_TIMR, RTC_CALR, tm); + + return TEE_SUCCESS; +} + +TEE_Result atmel_rtc_get_tamper_timestamp(struct optee_rtc_time *tm) +{ + if (!rtc_base) + return TEE_ERROR_NOT_SUPPORTED; + + atmel_decode_date(RTC_TSTR0, RTC_TSDR0, tm); + + return TEE_SUCCESS; +} + +static TEE_Result atmel_rtc_set_time(struct rtc *rtc __unused, + struct optee_rtc_time *tm) +{ + uint32_t cr = 0; + uint32_t sr = 0; + uint32_t err = 0; + + /* First, wait for UPDCAL/UPDTIM to be 0 */ + do { + cr = atmel_rtc_read(RTC_CR); + } while (cr & (RTC_CR_UPDCAL | RTC_CR_UPDTIM)); + + /* Stop Time/Calendar for update */ + atmel_rtc_write(RTC_CR, cr | RTC_CR_UPDCAL | RTC_CR_UPDTIM); + + do { + sr = atmel_rtc_read(RTC_SR); + } while (!(sr & RTC_SR_ACKUPD)); + + atmel_rtc_write(RTC_SCCR, RTC_SCCR_ACKCLR); + + atmel_rtc_write(RTC_TIMR, + RTC_SET_VAL(TIME_SEC, bcd_encode(tm->tm_sec)) | + RTC_SET_VAL(TIME_MIN, bcd_encode(tm->tm_min)) | + RTC_SET_VAL(TIME_HOUR, bcd_encode(tm->tm_hour))); + + atmel_rtc_write(RTC_CALR, + RTC_SET_VAL(CAL_CENT, + bcd_encode(tm->tm_year / 100)) | + RTC_SET_VAL(CAL_YEAR, bcd_encode(tm->tm_year % 100)) | + RTC_SET_VAL(CAL_MONTH, bcd_encode(tm->tm_mon + 1)) | + RTC_SET_VAL(CAL_DAY, bcd_encode(tm->tm_wday + 1)) | + RTC_SET_VAL(CAL_DATE, bcd_encode(tm->tm_mday))); + + err = atmel_rtc_read(RTC_VER); + if (err) { + if (err & RTC_VER_NVTIM) + DMSG("Invalid time programmed"); + if (err & RTC_VER_NVCAL) + DMSG("Invalid date programmed"); + + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Restart Time/Calendar */ + atmel_rtc_write(RTC_CR, cr); + + return TEE_SUCCESS; +} + +static TEE_Result atmel_rtc_get_offset(struct rtc *rtc __unused, long *offset) +{ + uint32_t mr = atmel_rtc_read(RTC_MR); + long val = RTC_VAL(MR_CORR, mr); + + if (!val) { + *offset = 0; + return TEE_SUCCESS; + } + + val++; + + if (!(mr & RTC_MR_HIGHPPM)) + val *= ATMEL_RTC_CORR_LOW_RATIO; + + val = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, val); + + if (!(mr & RTC_MR_NEGPPM)) + val = -val; + + *offset = val; + + return TEE_SUCCESS; +} + +static TEE_Result atmel_rtc_set_offset(struct rtc *rtc __unused, long offset) +{ + long corr = 0; + uint32_t mr = 0; + + if (offset > ATMEL_RTC_CORR_DIVIDEND / 2) + return TEE_ERROR_BAD_PARAMETERS; + if (offset < -ATMEL_RTC_CORR_DIVIDEND / 2) + return TEE_ERROR_BAD_PARAMETERS; + + mr = atmel_rtc_read(RTC_MR); + mr &= ~(RTC_MR_NEGPPM | RTC_MR_CORR_MASK | RTC_MR_HIGHPPM); + + if (offset > 0) + mr |= RTC_MR_NEGPPM; + else + offset = -offset; + + /* offset less than 764 ppb, disable correction */ + if (offset < 764) { + atmel_rtc_write(RTC_MR, mr & ~RTC_MR_NEGPPM); + + return TEE_SUCCESS; + } + + /* + * 29208 ppb is the perfect cutoff between low range and high range + * low range values are never better than high range value after that. + */ + if (offset < 29208) { + corr = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, + offset * ATMEL_RTC_CORR_LOW_RATIO); + } else { + corr = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, offset); + mr |= RTC_MR_HIGHPPM; + } + + corr = MIN(corr, 128); + + mr |= ((corr - 1) & RTC_MR_CORR_MASK) << RTC_MR_CORR_SHIFT; + + atmel_rtc_write(RTC_MR, mr); + + return TEE_SUCCESS; +} + +static const struct rtc_ops atmel_rtc_ops = { + .get_time = atmel_rtc_get_time, + .set_time = atmel_rtc_set_time, + .get_offset = atmel_rtc_get_offset, + .set_offset = atmel_rtc_set_offset, +}; + +static struct rtc atmel_rtc = { + .ops = &atmel_rtc_ops, + .range_min = { 1900, 1, 1, 0, 0, 0, 0 }, + .range_max = { 2099, 12, 31, 23, 59, 59, 0 }, +}; + +static TEE_Result atmel_rtc_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + size_t size = 0; + + if (rtc_base) + return TEE_ERROR_GENERIC; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_BAD_PARAMETERS; + + matrix_configure_periph_secure(AT91C_ID_SYS); + + if (dt_map_dev(fdt, node, &rtc_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + atmel_rtc_write(RTC_CR, 0); + /* Enable 24 hours Gregorian mode (this is a clear bits operation !) */ + io_clrbits32(rtc_base + RTC_MR, RTC_MR_PERSIAN | RTC_MR_UTC | + RTC_MR_HR_MODE); + + rtc_register(&atmel_rtc); + + return TEE_SUCCESS; +} + +static const struct dt_device_match atmel_rtc_match_table[] = { + { .compatible = "atmel,sama5d2-rtc" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_rtc_dt_driver) = { + .name = "atmel_rtc", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_rtc_match_table, + .probe = atmel_rtc_probe, +}; + diff --git a/optee/optee_os/core/drivers/atmel_saic.c b/optee/optee_os/core/drivers/atmel_saic.c new file mode 100644 index 0000000..7790ac1 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_saic.c @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AT91_AIC_MAX_PRIO 8 + +#define SAMA5D2_AIC_MAX_IRQS 77 + +#define SAMA5D2_AIC_MAX_IRQS32 ((SAMA5D2_AIC_MAX_IRQS + 31) / 32) + +struct saic_data { + struct itr_chip chip; + vaddr_t base; + size_t nr_irqs; + uint32_t external[SAMA5D2_AIC_MAX_IRQS32]; +}; + +static struct saic_data saic = {0}; + +static void saic_register_pm(void); + +static void saic_write_reg(uint32_t reg, uint32_t val) +{ + io_write32(saic.base + reg, val); +} + +static uint32_t saic_read_reg(uint32_t reg) +{ + return io_read32(saic.base + reg); +} + +void atmel_saic_it_handle(void) +{ + uint32_t irqnr = saic_read_reg(AT91_AIC_IVR); + + itr_handle(irqnr); + saic_write_reg(AT91_AIC_EOICR, 0); +} + +static void saic_select_it(size_t it) +{ + assert(!(it & ~AT91_AIC_SSR_ITSEL_MASK)); + + saic_write_reg(AT91_AIC_SSR, it); +} + +static void saic_configure_it(size_t it, uint32_t src_type, uint32_t priority) +{ + saic_select_it(it); + saic_write_reg(AT91_AIC_SMR, src_type | priority); +} + +static bool is_external_it(size_t it) +{ + uint32_t it_grp = it / 32; + uint32_t it_off = it % 32; + + if (it >= saic.nr_irqs) + panic(); + + return saic.external[it_grp] & BIT32(it_off); +} + +static TEE_Result saic_get_src_type(uint32_t dt_level, size_t it, + uint32_t *src_type) +{ + switch (dt_level) { + case IRQ_TYPE_EDGE_RISING: + *src_type = AT91_AIC_SMR_POS_EDGE; + break; + case IRQ_TYPE_EDGE_FALLING: + if (!is_external_it(it)) + return TEE_ERROR_BAD_PARAMETERS; + + *src_type = AT91_AIC_SMR_NEG_EDGE; + break; + case IRQ_TYPE_LEVEL_HIGH: + *src_type = AT91_AIC_SMR_HIGH_LEVEL; + break; + case IRQ_TYPE_LEVEL_LOW: + if (!is_external_it(it)) + return TEE_ERROR_BAD_PARAMETERS; + + *src_type = AT91_AIC_SMR_LEVEL; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static void saic_add(struct itr_chip *chip __unused, size_t it, + uint32_t type, uint32_t prio) +{ + uint32_t src_type = AT91_AIC_SMR_HIGH_LEVEL; + + if (it >= saic.nr_irqs) + panic(); + + if (saic_get_src_type(type, it, &src_type)) + panic("Invalid interrupt specifier"); + + saic_configure_it(it, src_type, prio); +} + +static void saic_enable(struct itr_chip *chip __unused, size_t it) +{ + saic_select_it(it); + saic_write_reg(AT91_AIC_IECR, 1); +} + +static void saic_disable(struct itr_chip *chip __unused, size_t it) +{ + saic_select_it(it); + saic_write_reg(AT91_AIC_IDCR, 1); +} + +static void saic_raise_pi(struct itr_chip *chip __unused, size_t it __unused) +{ + panic(); +} + +static void saic_raise_sgi(struct itr_chip *chip __unused, size_t it __unused, + uint8_t cpu_mask __unused) +{ + panic(); +} + +static void saic_set_affinity(struct itr_chip *chip __unused, + size_t it __unused, uint8_t cpu_mask __unused) +{ + panic(); +} + +static const struct itr_ops saic_ops = { + .add = saic_add, + .enable = saic_enable, + .disable = saic_disable, + .raise_pi = saic_raise_pi, + .raise_sgi = saic_raise_sgi, + .set_affinity = saic_set_affinity, +}; + +static int saic_dt_get_irq(const uint32_t *properties, int len, + uint32_t *type, uint32_t *prio) +{ + int it = DT_INFO_INVALID_INTERRUPT; + uint32_t src_type = 0; + uint32_t priority = 0; + uint32_t irq_type = 0; + + len /= sizeof(uint32_t); + + if (len != 3) + return DT_INFO_INVALID_INTERRUPT; + + it = fdt32_to_cpu(properties[0]); + if (it >= (int)saic.nr_irqs) + return DT_INFO_INVALID_INTERRUPT; + + irq_type = fdt32_to_cpu(properties[1]); + if (saic_get_src_type(irq_type, it, &src_type)) + return DT_INFO_INVALID_INTERRUPT; + + priority = fdt32_to_cpu(properties[2]); + if (priority >= AT91_AIC_MAX_PRIO) + return DT_INFO_INVALID_INTERRUPT; + + if (type) + *type = irq_type; + + if (prio) + *prio = priority; + + return it; +} + +struct itr_chip saic_chip = { + .ops = &saic_ops, + .dt_get_irq = &saic_dt_get_irq, +}; + +static void saic_clear_aicredir(void) +{ + vaddr_t sfr_base = sam_sfr_base(); + uint32_t aicredir_val = 0; + + aicredir_val = io_read32(sfr_base + AT91_SFR_SN1); + aicredir_val ^= AT91_SFR_AICREDIR_XOR_KEY; + aicredir_val &= AT91_SFR_AICREDIR_KEY_MASK; + + /* + * We explicitly don't want to redirect secure interrupts to non secure + * AIC. By default, AT91Bootstrap does so on some platforms. + */ + io_write32(sfr_base + AT91_SFR_AICREDIR, aicredir_val); +} + +static void saic_init_external(const void *fdt, int node) +{ + int i = 0; + int len = 0; + int it_grp = 0; + int it_off = 0; + size_t it = 0; + const uint32_t *external = NULL; + + external = fdt_getprop(fdt, node, "atmel,external-irqs", &len); + if (!external) + return; + + len /= sizeof(uint32_t); + for (i = 0; i < len; i++) { + it = fdt32_to_cpu(external[i]); + + DMSG("IRQ %zu is external", it); + + if (it >= saic.nr_irqs) + panic(); + + it_grp = it / 32; + it_off = it % 32; + + saic.external[it_grp] |= BIT32(it_off); + } +} + +static void saic_init_hw(void) +{ + unsigned int i = 0; + + saic_clear_aicredir(); + + /* Disable write protect if any */ + saic_write_reg(AT91_AIC_WPMR, AT91_AIC_WPKEY); + + /* Pop the (potential) interrupt stack (8 priority) */ + for (i = 0; i < 8; i++) + saic_write_reg(AT91_AIC_EOICR, 0); + + /* Disable and clear all interrupts initially */ + for (i = 0; i < saic.nr_irqs; i++) { + saic_write_reg(AT91_AIC_IDCR, 1); + saic_write_reg(AT91_AIC_ICCR, 1); + /* Set interrupt vector to hold interrupt number */ + saic_select_it(i); + saic_write_reg(AT91_AIC_SVR, i); + } + + saic_write_reg(AT91_AIC_SPU, 0xffffffff); + + /* Disable AIC debugging */ + saic_write_reg(AT91_AIC_DCR, 0); +} + +TEE_Result atmel_saic_setup(void) +{ + int node = -1; + int ret = 0; + size_t size = 0; + const void *fdt = get_embedded_dt(); + + /* There is only 1 SAIC controller */ + if (saic.base) + return TEE_ERROR_GENERIC; + + node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-saic"); + if (node < 0) + return TEE_ERROR_GENERIC; + + ret = dt_map_dev(fdt, node, &saic.base, &size, DT_MAP_AUTO); + if (ret) { + EMSG("Failed to map SAIC\n"); + return TEE_ERROR_GENERIC; + } + + saic.chip.ops = &saic_ops; + saic.nr_irqs = SAMA5D2_AIC_MAX_IRQS; + + saic_init_external(fdt, node); + saic_init_hw(); + + itr_init(&saic_chip); + saic_register_pm(); + + return TEE_SUCCESS; +} + +#ifdef CFG_PM_ARM32 + +static struct { + uint8_t smr[SAMA5D2_AIC_MAX_IRQS]; +} saic_state; + +static void saic_resume(void) +{ + uint8_t it = 0; + + saic_init_hw(); + + for (it = 0; it < SAMA5D2_AIC_MAX_IRQS; it++) { + saic_select_it(it); + saic_write_reg(AT91_AIC_SMR, saic_state.smr[it]); + } +} + +static void saic_suspend(void) +{ + uint8_t it = 0; + + for (it = 0; it < SAMA5D2_AIC_MAX_IRQS; it++) { + saic_select_it(it); + saic_state.smr[it] = saic_read_reg(AT91_AIC_SMR); + } +} + +static TEE_Result saic_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *hdl __unused) +{ + switch (op) { + case PM_OP_RESUME: + saic_resume(); + break; + case PM_OP_SUSPEND: + saic_suspend(); + break; + default: + panic("Invalid PM operation"); + } + + return TEE_SUCCESS; +} + +static void saic_register_pm(void) +{ + register_pm_core_service_cb(saic_pm, NULL, "saic"); +} +#else +static void saic_register_pm(void) +{ +} +#endif diff --git a/optee/optee_os/core/drivers/atmel_shdwc.c b/optee/optee_os/core/drivers/atmel_shdwc.c new file mode 100644 index 0000000..b77f934 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_shdwc.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015 Atmel Corporation, + * Nicolas Ferre + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define SHDW_WK_PIN(reg, cfg) ((reg) & \ + AT91_SHDW_WKUPIS((cfg)->wkup_pin_input)) +#define SHDW_RTCWK(reg, cfg) (((reg) >> ((cfg)->sr_rtcwk_shift)) & 0x1) +#define SHDW_RTTWK(reg, cfg) (((reg) >> ((cfg)->sr_rttwk_shift)) & 0x1) +#define SHDW_RTCWKEN(cfg) BIT((cfg)->mr_rtcwk_shift) +#define SHDW_RTTWKEN(cfg) BIT((cfg)->mr_rttwk_shift) + +#define SLOW_CLK_FREQ 32768ULL +#define DBC_PERIOD_US(x) DIV_ROUND_UP((1000000ULL * (x)), SLOW_CLK_FREQ) + +static vaddr_t shdwc_base; +static vaddr_t mpddrc_base; + +bool atmel_shdwc_available(void) +{ + return shdwc_base != 0; +} + +void __noreturn atmel_shdwc_shutdown(void) +{ + vaddr_t pmc_base = at91_pmc_get_base(); + + /* + * Mask exception before entering assembly which does not expect to be + * interrupted. + */ + thread_mask_exceptions(THREAD_EXCP_ALL); + + __atmel_shdwc_shutdown(mpddrc_base, shdwc_base, pmc_base); + + /* We are going to shutdown the CPU so we will never hit this loop */ + while (true) + ; +} + +static const unsigned long long sdwc_dbc_period[] = { + 0, 3, 32, 512, 4096, 32768, +}; + +static uint32_t at91_shdwc_debouncer_value(uint32_t in_period_us) +{ + int i = 0; + int max_idx = ARRAY_SIZE(sdwc_dbc_period) - 1; + uint64_t period_us = 0; + uint64_t max_period_us = DBC_PERIOD_US(sdwc_dbc_period[max_idx]); + + if (in_period_us > max_period_us) { + DMSG("debouncer period %"PRIu32" too big, using %"PRIu64" us", + in_period_us, max_period_us); + return max_idx; + } + + for (i = max_idx - 1; i > 0; i--) { + period_us = DBC_PERIOD_US(sdwc_dbc_period[i]); + if (in_period_us > period_us) + break; + } + + return i + 1; +} + +static uint32_t at91_shdwc_get_wakeup_input(const void *fdt, int np) +{ + const uint32_t *prop = NULL; + uint32_t wk_input_mask = 0; + uint32_t wuir = 0; + uint32_t wk_input = 0; + int child = 0; + int len = 0; + + fdt_for_each_subnode(child, fdt, np) { + prop = fdt_getprop(fdt, child, "reg", &len); + if (!prop || len != sizeof(uint32_t)) { + DMSG("reg property is missing for node %s", + fdt_get_name(fdt, child, NULL)); + continue; + } + wk_input = fdt32_to_cpu(*prop); + wk_input_mask = BIT32(wk_input); + if (!(wk_input_mask & AT91_SHDW_WKUPEN_MASK)) { + DMSG("wake-up input %"PRId32" out of bounds ignore", + wk_input); + continue; + } + wuir |= wk_input_mask; + + if (fdt_getprop(fdt, child, "atmel,wakeup-active-high", NULL)) + wuir |= AT91_SHDW_WKUPT(wk_input); + } + + return wuir; +} + +static void at91_shdwc_dt_configure(const void *fdt, int np) +{ + const uint32_t *prop = NULL; + uint32_t mode = 0; + uint32_t tmp = 0; + uint32_t input = 0; + int len = 0; + + prop = fdt_getprop(fdt, np, "debounce-delay-us", &len); + if (prop && len == sizeof(uint32_t)) { + tmp = fdt32_to_cpu(*prop); + mode |= AT91_SHDW_WKUPDBC(at91_shdwc_debouncer_value(tmp)); + } + + if (fdt_getprop(fdt, np, "atmel,wakeup-rtc-timer", &len)) + mode |= AT91_SHDW_RTCWKEN; + + io_write32(shdwc_base + AT91_SHDW_MR, mode); + + input = at91_shdwc_get_wakeup_input(fdt, np); + io_write32(shdwc_base + AT91_SHDW_WUIR, input); +} + +static TEE_Result atmel_shdwc_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + int ddr_node = 0; + size_t size = 0; + uint32_t ddr = AT91_DDRSDRC_MD_LPDDR2; + + /* + * Assembly code relies on the fact that there is only one CPU to avoid + * any other one to invalidate TLB/I-Cache. + */ + COMPILE_TIME_ASSERT(CFG_TEE_CORE_NB_CORE == 1); + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_BAD_PARAMETERS; + + matrix_configure_periph_secure(AT91C_ID_SYS); + + if (dt_map_dev(fdt, node, &shdwc_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + ddr_node = fdt_node_offset_by_compatible(fdt, -1, + "atmel,sama5d3-ddramc"); + if (ddr_node < 0) + return TEE_ERROR_GENERIC; + + if (dt_map_dev(fdt, ddr_node, &mpddrc_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + ddr = io_read32(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD; + if (ddr != AT91_DDRSDRC_MD_LPDDR2 && ddr != AT91_DDRSDRC_MD_LPDDR3) + mpddrc_base = 0; + + at91_shdwc_dt_configure(fdt, node); + + return sama5d2_pm_init(fdt, shdwc_base); +} + +static const struct dt_device_match atmel_shdwc_match_table[] = { + { .compatible = "atmel,sama5d2-shdwc" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_shdwc_dt_driver) = { + .name = "atmel_shdwc", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_shdwc_match_table, + .probe = atmel_shdwc_probe, +}; diff --git a/optee/optee_os/core/drivers/atmel_shdwc_a32.S b/optee/optee_os/core/drivers/atmel_shdwc_a32.S new file mode 100644 index 0000000..c3ebca1 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_shdwc_a32.S @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015 Atmel Corporation, + * Nicolas Ferre + * Copyright (c) 2021, Microchip + */ + + +#include +#include +#include +#include +#include + +#include "at91_pmc.h" + +/* + * Code size of shutdown assembly must fit in a single Cortex-A5 cache + * line which is 8 words long (32 bytes) since SDRAM might be disabled and thus + * not accessible to fetch code or data from it. + */ +.macro check_fit_in_cacheline since + .if (. - \since) > 32 + .error "Shutdown assembly code exceeds cache line size" + .endif +.endm + +/** + * Shutdown the CPU + * + * This function is in assembly to be sure the code fits in a single cache line. + * We are going to power down the SDRAM and thus we can't fetch code from it + * once powered down. + * + * r0 = mpddrc_base + * r1 = shdwc_base + * r2 = pmc_base + */ +FUNC __atmel_shdwc_shutdown , : + + mov_imm r3, AT91_DDRSDRC_LPDDR2_PWOFF + mov_imm r4, (AT91_SHDW_KEY | AT91_SHDW_SHDW) + + /* + * Read values from both shutdown controller and PMC to ensure the + * translations will be in the TLB. + */ + ldr r6, [r1, #AT91_SHDW_CR] + ldr r6, [r2, #AT91_PMC_MCKR] + + /* Power down SDRAM0 if mpddrc_base is set */ + tst r0, #0 + beq 1f + +/* Align to cache line to ensure the rest of code fits in a single line */ +.balign 32 +__atmel_shdwc_shutdown_sdram_disabled: + str r3, [r0, #AT91_DDRSDRC_LPR] + + /* Switch the master clock source to slow clock. */ +1: + ldr r6, [r2, #AT91_PMC_MCKR] + bic r6, r6, #AT91_PMC_CSS + str r6, [r2, #AT91_PMC_MCKR] + + /* Wait for clock switch. */ +2: + ldr r6, [r2, #AT91_PMC_SR] + tst r6, #AT91_PMC_MCKRDY + beq 2b + + /* Shutdown CPU */ + str r4, [r1, #AT91_SHDW_CR] + + check_fit_in_cacheline __atmel_shdwc_shutdown_sdram_disabled + + /* We should never reach this since we shut down the CPU */ + b . +END_FUNC __atmel_shdwc_shutdown diff --git a/optee/optee_os/core/drivers/atmel_tcb.c b/optee/optee_os/core/drivers/atmel_tcb.c new file mode 100644 index 0000000..0e87453 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_tcb.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TCB_CHAN(chan) ((chan) * 0x40) + +#define TCB_CCR(chan) (0x0 + TCB_CHAN(chan)) +#define TCB_CCR_SWTRG 0x4 +#define TCB_CCR_CLKEN 0x1 + +#define TCB_CMR(chan) (0x4 + TCB_CHAN(chan)) +#define TCB_CMR_WAVE BIT32(15) +#define TCB_CMR_TIMER_CLOCK5 4 +#define TCB_CMR_XC1 6 +#define TCB_CMR_ACPA_SET BIT32(16) +#define TCB_CMR_ACPC_CLEAR SHIFT_U32(2, 18) + +#define TCB_CV(chan) (0x10 + TCB_CHAN(chan)) + +#define TCB_RA(chan) (0x14 + TCB_CHAN(chan)) +#define TCB_RB(chan) (0x18 + TCB_CHAN(chan)) +#define TCB_RC(chan) (0x1c + TCB_CHAN(chan)) + +#define TCB_IER(chan) (0x24 + TCB_CHAN(chan)) +#define TCB_IER_COVFS 0x1 + +#define TCB_SR(chan) (0x20 + TCB_CHAN(chan)) +#define TCB_SR_COVFS 0x1 + +#define TCB_IDR(chan) (0x28 + TCB_CHAN(chan)) + +#define TCB_BCR 0xc0 +#define TCB_BCR_SYNC 0x1 + +#define TCB_BMR 0xc4 +#define TCB_BMR_TC1XC1S_TIOA0 SHIFT_U32(2, 2) + +#define TCB_WPMR 0xe4 +#define TCB_WPMR_WAKEY 0x54494d + +static const char * const tcb_clocks[] = { "t0_clk", "gclk", "slow_clk" }; +static vaddr_t tcb_base; +static uint32_t tcb_rate; + +static TEE_Result atmel_tcb_enable_clocks(const void *fdt, int node) +{ + unsigned int i = 0; + struct clk *clk = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + for (i = 0; i < ARRAY_SIZE(tcb_clocks); i++) { + res = clk_dt_get_by_name(fdt, node, tcb_clocks[i], &clk); + if (res) + return res; + + clk_enable(clk); + } + + return TEE_SUCCESS; +} + +static TEE_Result atmel_tcb_get_sys_time(TEE_Time *time) +{ + uint64_t cv0 = 0; + uint64_t cv1 = 0; + + if (!tcb_base) + return TEE_ERROR_BAD_STATE; + + do { + cv1 = io_read32(tcb_base + TCB_CV(1)); + cv0 = io_read32(tcb_base + TCB_CV(0)); + } while (io_read32(tcb_base + TCB_CV(1)) != cv1); + + cv0 |= cv1 << 32; + + time->seconds = cv0 / tcb_rate; + time->millis = (cv0 % tcb_rate) / (tcb_rate / TEE_TIME_MILLIS_BASE); + + return TEE_SUCCESS; +} + +static const struct time_source atmel_tcb_time_source = { + .name = "atmel_tcb", + .protection_level = 1000, + .get_sys_time = atmel_tcb_get_sys_time, +}; + +REGISTER_TIME_SOURCE(atmel_tcb_time_source) + +static void atmel_tcb_configure(void) +{ + /* Disable write protection */ + io_write32(tcb_base + TCB_WPMR, TCB_WPMR_WAKEY); + + /* Disable all irqs for both channel 0 & 1 */ + io_write32(tcb_base + TCB_IDR(0), 0xff); + io_write32(tcb_base + TCB_IDR(1), 0xff); + + /* + * In order to avoid wrapping, use a 64 bit counter by chaining + * two channels. We use the slow_clk which runs at 32K and is sufficient + * for the millisecond precision, this will wrap in approximately + * 17851025 years so no worries here. + * + * Channel 0 is configured to generate a clock on TIOA0 which is cleared + * when reaching 0x80000000 and set when reaching 0. + */ + io_write32(tcb_base + TCB_CMR(0), + TCB_CMR_TIMER_CLOCK5 | TCB_CMR_WAVE | TCB_CMR_ACPA_SET | + TCB_CMR_ACPC_CLEAR); + io_write32(tcb_base + TCB_RC(0), 0x80000000); + io_write32(tcb_base + TCB_RA(0), 0x1); + io_write32(tcb_base + TCB_CCR(0), TCB_CCR_CLKEN); + + /* Channel 1 is configured to use TIOA0 as input */ + io_write32(tcb_base + TCB_CMR(1), TCB_CMR_XC1 | TCB_CMR_WAVE); + io_write32(tcb_base + TCB_CCR(1), TCB_CCR_CLKEN); + + /* Set XC1 input to be TIOA0 (ie output of Channel 0) */ + io_write32(tcb_base + TCB_BMR, TCB_BMR_TC1XC1S_TIOA0); + + /* Sync & start all timers */ + io_write32(tcb_base + TCB_BCR, TCB_BCR_SYNC); + + /* Enable write protection */ + io_write32(tcb_base + TCB_WPMR, TCB_WPMR_WAKEY | 1); +} + +static TEE_Result atmel_tcb_check(void) +{ + if (!tcb_base) + panic("Missing TCB base ! Check the device-tree"); + + return TEE_SUCCESS; +} + +boot_final(atmel_tcb_check); + +static TEE_Result atmel_tcb_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + size_t size = 0; + struct clk *clk = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int peri_id = AT91C_ID_TC0; + + /* Enable all TCB clocks */ + res = atmel_tcb_enable_clocks(fdt, node); + if (res) + return res; + + if (tcb_base) + return TEE_SUCCESS; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_SUCCESS; + + res = clk_dt_get_by_name(fdt, node, "slow_clk", &clk); + if (res) + return res; + + res = matrix_dt_get_id(fdt, node, &peri_id); + if (res) + return res; + + if (dt_map_dev(fdt, node, &tcb_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + matrix_configure_periph_secure(peri_id); + + tcb_rate = clk_get_rate(clk); + assert(tcb_rate); + + atmel_tcb_configure(); + + return TEE_SUCCESS; +} + +static const struct dt_device_match atmel_tcb_match_table[] = { + { .compatible = "atmel,sama5d2-tcb" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_tcb_dt_driver) = { + .name = "atmel_tcb", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_tcb_match_table, + .probe = atmel_tcb_probe, +}; diff --git a/optee/optee_os/core/drivers/atmel_trng.c b/optee/optee_os/core/drivers/atmel_trng.c new file mode 100644 index 0000000..0b18c30 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_trng.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define TRNG_CTRL 0x0 +#define TRNG_CTRL_WAKEY_OFFSET 8 +#define TRNG_CTRL_WAKEY_VALUE 0x524E47 + +#define TRNG_IER 0x10 +#define TRNG_ISR 0x1C +#define TRNG_ODATA 0x50 + +static unsigned int trng_lock = SPINLOCK_UNLOCK; +static vaddr_t trng_base; + +static uint32_t atmel_trng_read32(void) +{ + uint32_t exceptions = 0; + uint32_t value = 0; + + exceptions = cpu_spin_lock_xsave(&trng_lock); + + while (!io_read32(trng_base + TRNG_ISR)) + ; + + value = io_read32(trng_base + TRNG_ODATA); + + cpu_spin_unlock_xrestore(&trng_lock, exceptions); + + return value; +} + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + uint8_t *rngbuf = buf; + uint32_t val = 0; + size_t len_to_copy = 0; + + assert(trng_base); + + while (len) { + val = atmel_trng_read32(); + len_to_copy = MIN(len, sizeof(uint32_t)); + memcpy(rngbuf, &val, len_to_copy); + rngbuf += len_to_copy; + len -= len_to_copy; + } + + return TEE_SUCCESS; +} + +/* This is a true RNG, no need for seeding */ +void plat_rng_init(void) +{ +} + +static void atmel_trng_reset(void) +{ + uint32_t ctrl_val = TRNG_CTRL_WAKEY_VALUE << TRNG_CTRL_WAKEY_OFFSET; + + /* Disable TRNG */ + io_setbits32(trng_base + TRNG_CTRL, ctrl_val); + /* Enable interrupt */ + io_setbits32(trng_base + TRNG_IER, 1); + /* Enable TRNG */ + io_setbits32(trng_base + TRNG_CTRL, ctrl_val | 1); +} + +static TEE_Result trng_node_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + int status = fdt_get_status(fdt, node); + size_t size = 0; + struct clk *clk = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + if (status != DT_STATUS_OK_SEC) + return TEE_ERROR_GENERIC; + + matrix_configure_periph_secure(AT91C_ID_TRNG); + + res = clk_dt_get_by_index(fdt, node, 0, &clk); + if (res) + return res; + + if (dt_map_dev(fdt, node, &trng_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + clk_enable(clk); + + atmel_trng_reset(); + + return TEE_SUCCESS; +} + +static const struct dt_device_match atmel_trng_match_table[] = { + { .compatible = "atmel,at91sam9g45-trng" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_trng_dt_driver) = { + .name = "atmel_trng", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_trng_match_table, + .probe = trng_node_probe, +}; diff --git a/optee/optee_os/core/drivers/atmel_uart.c b/optee/optee_os/core/drivers/atmel_uart.c new file mode 100644 index 0000000..7454bdb --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_uart.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Timesys Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +/* Register definitions */ +#define ATMEL_UART_CR 0x0000 /* Control Register */ +#define ATMEL_UART_MR 0x0004 /* Mode Register */ +#define ATMEL_UART_IER 0x0008 /* Interrupt Enable Register */ +#define ATMEL_UART_IDR 0x000c /* Interrupt Disable Register */ +#define ATMEL_UART_IMR 0x0010 /* Interrupt Mask Register */ +#define ATMEL_UART_SR 0x0014 /* Status Register */ + #define ATMEL_SR_RXRDY BIT(0) /* Receiver Ready */ + #define ATMEL_SR_TXRDY BIT(1) /* Transmitter Ready */ + #define ATMEL_SR_TXEMPTY BIT(1) /* Transmitter Ready */ +#define ATMEL_UART_RHR 0x0018 /* Receive Holding Register */ +#define ATMEL_UART_THR 0x001c /* Transmit Holding Register */ +#define ATMEL_UART_BRGR 0x0020 /* Baud Rate Generator Register */ +#define ATMEL_UART_CMPR 0x0024 /* Comparison Register */ +#define ATMEL_UART_RTOR 0x0028 /* Receiver Time-out Register */ +#define ATMEL_UART_WPMR 0x00e4 /* Write Protect Mode Register */ +#define ATMEL_UART_SIZE 0x00e8 /* ATMEL_UART_WPMR + sizeof(uint32_t) */ + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct atmel_uart_data *pd = + container_of(chip, struct atmel_uart_data, chip); + + return io_pa_or_va(&pd->base, ATMEL_UART_SIZE); +} + +static void atmel_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read32(base + ATMEL_UART_SR) & ATMEL_SR_TXEMPTY)) + ; +} + +static int atmel_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (io_read32(base + ATMEL_UART_SR) & ATMEL_SR_RXRDY) + ; + + return io_read32(base + ATMEL_UART_RHR); +} + +static void atmel_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read32(base + ATMEL_UART_SR) & ATMEL_SR_TXRDY)) + ; + + io_write32(base + ATMEL_UART_THR, ch); +} + +static const struct serial_ops atmel_uart_ops = { + .flush = atmel_uart_flush, + .getchar = atmel_uart_getchar, + .putc = atmel_uart_putc, +}; + +void atmel_uart_init(struct atmel_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &atmel_uart_ops; + + /* + * Do nothing, debug uart share with normal world, + * everything for uart initialization is done in bootloader. + */ +} diff --git a/optee/optee_os/core/drivers/atmel_wdt.c b/optee/optee_os/core/drivers/atmel_wdt.c new file mode 100644 index 0000000..b2aa545 --- /dev/null +++ b/optee/optee_os/core/drivers/atmel_wdt.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WDT_CR 0x0 +#define WDT_CR_KEY SHIFT_U32(0xA5, 24) +#define WDT_CR_WDRSTT BIT(0) + +#define WDT_MR 0x4 +#define WDT_MR_WDV GENMASK_32(11, 0) +#define WDT_MR_WDV_SET(val) ((val) & WDT_MR_WDV) +#define WDT_MR_WDFIEN BIT(12) +#define WDT_MR_WDRSTEN BIT(13) +#define WDT_MR_WDDIS BIT(15) +#define WDT_MR_WDD_SHIFT 16 +#define WDT_MR_WDD_MASK GENMASK_32(11, 0) +#define WDT_MR_WDD SHIFT_U32(WDT_MR_WDD_MASK, WDT_MR_WDD_SHIFT) +#define WDT_MR_WDD_SET(val) \ + SHIFT_U32(((val) & WDT_MR_WDD_MASK), WDT_MR_WDD_SHIFT) +#define WDT_MR_WDDBGHLT BIT(28) +#define WDT_MR_WDIDLEHLT BIT(29) + +#define WDT_SR 0x8 +#define WDT_SR_DUNF BIT(0) +#define WDT_SR_DERR BIT(1) + +/* + * The watchdog is clocked by a 32768Hz clock/128 and the counter is on + * 12 bits. + */ +#define SLOW_CLOCK_FREQ (32768) +#define WDT_CLOCK_FREQ (SLOW_CLOCK_FREQ / 128) +#define WDT_MIN_TIMEOUT 1 +#define WDT_MAX_TIMEOUT (BIT(12) / WDT_CLOCK_FREQ) + +#define WDT_DEFAULT_TIMEOUT WDT_MAX_TIMEOUT + +/* + * We must wait at least 3 clocks period before accessing registers MR and CR. + * Ensure that we see at least 4 edges + */ +#define WDT_REG_ACCESS_UDELAY (1000000ULL / SLOW_CLOCK_FREQ * 4) + +#define SEC_TO_WDT(sec) (((sec) * WDT_CLOCK_FREQ) - 1) + +#define WDT_ENABLED(mr) (!((mr) & WDT_MR_WDDIS)) + +struct atmel_wdt { + struct wdt_chip chip; + vaddr_t base; + unsigned long rate; + uint32_t mr; + bool enabled; +}; + +static void atmel_wdt_write_sleep(struct atmel_wdt *wdt, uint32_t reg, + uint32_t val) +{ + udelay(WDT_REG_ACCESS_UDELAY); + + io_write32(wdt->base + reg, val); +} + +static TEE_Result atmel_wdt_settimeout(struct wdt_chip *chip, + unsigned long timeout) +{ + struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip); + + wdt->mr &= ~WDT_MR_WDV; + wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(timeout)); + + /* WDV and WDD can only be updated when the watchdog is running */ + if (WDT_ENABLED(wdt->mr)) + atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr); + + return TEE_SUCCESS; +} + +static void atmel_wdt_ping(struct wdt_chip *chip) +{ + struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip); + + atmel_wdt_write_sleep(wdt, WDT_CR, WDT_CR_KEY | WDT_CR_WDRSTT); +} + +static void atmel_wdt_start(struct atmel_wdt *wdt) +{ + wdt->mr &= ~WDT_MR_WDDIS; + atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr); +} + +static void atmel_wdt_enable(struct wdt_chip *chip) +{ + struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip); + + wdt->enabled = true; + atmel_wdt_start(wdt); +} + +static void atmel_wdt_stop(struct atmel_wdt *wdt) +{ + wdt->mr |= WDT_MR_WDDIS; + atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr); +} + +static void atmel_wdt_disable(struct wdt_chip *chip) +{ + struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip); + + wdt->enabled = false; + atmel_wdt_stop(wdt); +} + +static enum itr_return atmel_wdt_itr_cb(struct itr_handler *h) +{ + struct atmel_wdt *wdt = h->data; + uint32_t sr = io_read32(wdt->base + WDT_SR); + + if (sr & WDT_SR_DUNF) + DMSG("Watchdog Underflow !"); + if (sr & WDT_SR_DERR) + DMSG("Watchdog Error !"); + + panic("Watchdog interrupt"); + + return ITRR_HANDLED; +} + +static TEE_Result atmel_wdt_init(struct wdt_chip *chip __unused, + unsigned long *min_timeout, + unsigned long *max_timeout) +{ + *min_timeout = WDT_MIN_TIMEOUT; + *max_timeout = WDT_MAX_TIMEOUT; + + return TEE_SUCCESS; +} + +static const struct wdt_ops atmel_wdt_ops = { + .init = atmel_wdt_init, + .start = atmel_wdt_enable, + .stop = atmel_wdt_disable, + .ping = atmel_wdt_ping, + .set_timeout = atmel_wdt_settimeout, +}; + +static void atmel_wdt_init_hw(struct atmel_wdt *wdt) +{ + uint32_t mr = 0; + + /* + * If we are resuming, we disabled the watchdog on suspend but the + * bootloader might have enabled the watchdog. If so, disable it + * properly. + */ + if (!WDT_ENABLED(wdt->mr)) { + mr = io_read32(wdt->base + WDT_MR); + if (WDT_ENABLED(mr)) + io_write32(wdt->base + WDT_MR, mr | WDT_MR_WDDIS); + } + + /* Enable interrupt, and disable watchdog in debug and idle */ + wdt->mr |= WDT_MR_WDFIEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT; + /* Enable watchdog reset */ + wdt->mr |= WDT_MR_WDRSTEN; + wdt->mr |= WDT_MR_WDD_SET(SEC_TO_WDT(WDT_MAX_TIMEOUT)); + wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(WDT_DEFAULT_TIMEOUT)); + + /* + * If the watchdog was enabled, write the configuration which will ping + * the watchdog. + */ + if (WDT_ENABLED(wdt->mr)) + io_write32(wdt->base + WDT_MR, wdt->mr); +} + +#ifdef CFG_PM_ARM32 +static TEE_Result atmel_wdt_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *hdl) +{ + struct atmel_wdt *wdt = hdl->handle; + + switch (op) { + case PM_OP_RESUME: + atmel_wdt_init_hw(wdt); + if (wdt->enabled) + atmel_wdt_start(wdt); + break; + case PM_OP_SUSPEND: + if (wdt->enabled) + atmel_wdt_stop(wdt); + break; + default: + panic("Invalid PM operation"); + } + + return TEE_SUCCESS; +} + +static void atmel_wdt_register_pm(struct atmel_wdt *wdt) +{ + register_pm_driver_cb(atmel_wdt_pm, wdt, "atmel_wdt"); +} +#else +static void atmel_wdt_register_pm(struct atmel_wdt *wdt __unused) +{ +} +#endif + +static TEE_Result wdt_node_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + size_t size = 0; + struct atmel_wdt *wdt; + uint32_t irq_type = 0; + uint32_t irq_prio = 0; + int it = DT_INFO_INVALID_INTERRUPT; + struct itr_handler *it_hdlr; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_BAD_PARAMETERS; + + matrix_configure_periph_secure(AT91C_ID_WDT); + + wdt = calloc(1, sizeof(*wdt)); + if (!wdt) + return TEE_ERROR_OUT_OF_MEMORY; + + wdt->chip.ops = &atmel_wdt_ops; + + it = dt_get_irq_type_prio(fdt, node, &irq_type, &irq_prio); + if (it == DT_INFO_INVALID_INTERRUPT) + goto err_free_wdt; + + it_hdlr = itr_alloc_add_type_prio(it, &atmel_wdt_itr_cb, 0, wdt, + irq_type, irq_prio); + if (!it_hdlr) + goto err_free_wdt; + + if (dt_map_dev(fdt, node, &wdt->base, &size, DT_MAP_AUTO) < 0) + goto err_free_itr_handler; + + /* Get current state of the watchdog */ + wdt->mr = io_read32(wdt->base + WDT_MR) & WDT_MR_WDDIS; + + atmel_wdt_init_hw(wdt); + itr_enable(it); + atmel_wdt_register_pm(wdt); + + return watchdog_register(&wdt->chip); + +err_free_itr_handler: + itr_free(it_hdlr); +err_free_wdt: + free(wdt); + + return TEE_ERROR_GENERIC; +} + +static const struct dt_device_match atmel_wdt_match_table[] = { + { .compatible = "atmel,sama5d4-wdt" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_wdt_dt_driver) = { + .name = "atmel_wdt", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_wdt_match_table, + .probe = wdt_node_probe, +}; diff --git a/optee/optee_os/core/drivers/bcm_gpio.c b/optee/optee_os/core/drivers/bcm_gpio.c new file mode 100644 index 0000000..cd7d9b3 --- /dev/null +++ b/optee/optee_os/core/drivers/bcm_gpio.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ +#include +#include +#include +#include +#include +#include +#include + +#define IPROC_GPIO_DATA_IN_OFFSET 0x00 +#define IPROC_GPIO_DATA_OUT_OFFSET 0x04 +#define IPROC_GPIO_OUT_EN_OFFSET 0x08 +#define IPROC_GPIO_INT_MSK_OFFSET 0x18 + +#define GPIO_BANK_SIZE 0x200 +#define NGPIOS_PER_BANK 32 +#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK) + +#define IPROC_GPIO_REG(pin, reg) ((reg) + \ + GPIO_BANK(pin) * GPIO_BANK_SIZE) + +#define IPROC_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK) + +#define GPIO_BANK_CNT 5 +#define SEC_GPIO_SIZE 0x4 +#define IPROC_GPIO_SEC_CFG_REG(pin) \ + (((GPIO_BANK_CNT - 1) - GPIO_BANK(pin)) * SEC_GPIO_SIZE) + +static SLIST_HEAD(, bcm_gpio_chip) gclist = SLIST_HEAD_INITIALIZER(gclist); + +struct bcm_gpio_chip *bcm_gpio_pin_to_chip(unsigned int pin) +{ + struct bcm_gpio_chip *gc = NULL; + + SLIST_FOREACH(gc, &gclist, link) + if ((pin >= gc->gpio_base) && + (pin < (gc->gpio_base + gc->ngpios))) + return gc; + return NULL; +} + +static bool __maybe_unused gpio_is_range_overlap(unsigned int start, + unsigned int end) +{ + struct bcm_gpio_chip *gc = NULL; + + SLIST_FOREACH(gc, &gclist, link) + if ((start < (gc->gpio_base + gc->ngpios)) && + (end > gc->gpio_base)) + return true; + return false; +} + +static void iproc_set_bit(unsigned int reg, unsigned int gpio) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, reg); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); + + assert(gc); + io_setbits32(gc->base + offset, BIT(shift)); +} + +static void iproc_clr_bit(unsigned int reg, unsigned int gpio) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, reg); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); + + assert(gc); + io_clrbits32(gc->base + offset, BIT(shift)); +} + +static void iproc_gpio_set(struct gpio_chip *chip __unused, unsigned int gpio, + enum gpio_level val) +{ + if (val == GPIO_LEVEL_HIGH) + iproc_set_bit(IPROC_GPIO_DATA_OUT_OFFSET, gpio); + else + iproc_clr_bit(IPROC_GPIO_DATA_OUT_OFFSET, gpio); +} + +static enum gpio_level iproc_gpio_get(struct gpio_chip *chip __unused, + unsigned int gpio) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_DATA_IN_OFFSET); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); + + assert(gc); + + if (io_read32(gc->base + offset) & BIT(shift)) + return GPIO_LEVEL_HIGH; + else + return GPIO_LEVEL_LOW; +} + +static void iproc_gpio_set_dir(struct gpio_chip *chip __unused, + unsigned int gpio, enum gpio_dir dir) +{ + if (dir == GPIO_DIR_OUT) + iproc_set_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); + else + iproc_clr_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); +} + +static enum gpio_dir iproc_gpio_get_dir(struct gpio_chip *chip __unused, + unsigned int gpio) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); + + assert(gc); + + if (io_read32(gc->base + offset) & BIT(shift)) + return GPIO_DIR_OUT; + else + return GPIO_DIR_IN; +} + +static enum gpio_interrupt iproc_gpio_get_itr(struct gpio_chip *chip __unused, + unsigned int gpio) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_INT_MSK_OFFSET); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); + + assert(gc); + + if (io_read32(gc->base + offset) & BIT(shift)) + return GPIO_INTERRUPT_ENABLE; + else + return GPIO_INTERRUPT_DISABLE; +} + +static void iproc_gpio_set_itr(struct gpio_chip *chip __unused, + unsigned int gpio, enum gpio_interrupt ena_dis) +{ + if (ena_dis == GPIO_INTERRUPT_ENABLE) + iproc_set_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); + else + iproc_clr_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); +} + +static const struct gpio_ops bcm_gpio_ops = { + .get_direction = iproc_gpio_get_dir, + .set_direction = iproc_gpio_set_dir, + .get_value = iproc_gpio_get, + .set_value = iproc_gpio_set, + .get_interrupt = iproc_gpio_get_itr, + .set_interrupt = iproc_gpio_set_itr, +}; +DECLARE_KEEP_PAGER(bcm_gpio_ops); + +void iproc_gpio_set_secure(int gpiopin) +{ + vaddr_t regaddr = 0; + unsigned int shift = IPROC_GPIO_SHIFT(gpiopin); + vaddr_t baseaddr = + (vaddr_t)phys_to_virt(CHIP_SECURE_GPIO_CONTROL0_BASE, + MEM_AREA_IO_SEC, + IPROC_GPIO_SEC_CFG_REG(gpiopin) + + sizeof(uint32_t)); + + regaddr = baseaddr + IPROC_GPIO_SEC_CFG_REG(gpiopin); + + io_clrbits32(regaddr, BIT(shift)); +} + +static void iproc_gpio_init(struct bcm_gpio_chip *gc, unsigned int paddr, + unsigned int gpio_base, unsigned int ngpios) +{ + assert(!gpio_is_range_overlap(gpio_base, gpio_base + gc->ngpios)); + + gc->base = core_mmu_get_va(paddr, MEM_AREA_IO_SEC, 1); + gc->chip.ops = &bcm_gpio_ops; + gc->gpio_base = gpio_base; + gc->ngpios = ngpios; + + SLIST_INSERT_HEAD(&gclist, gc, link); + + DMSG("gpio chip for <%u - %u>", gpio_base, gpio_base + ngpios); +} + +static TEE_Result bcm_gpio_init(void) +{ + struct bcm_gpio_chip *gc = NULL; + +#ifdef SECURE_GPIO_BASE0 + gc = malloc(sizeof(*gc)); + if (gc == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + iproc_gpio_init(gc, SECURE_GPIO_BASE0, GPIO_NUM_START0, NUM_GPIOS0); +#endif +#ifdef SECURE_GPIO_BASE1 + gc = malloc(sizeof(*gc)); + if (gc == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + iproc_gpio_init(gc, SECURE_GPIO_BASE1, GPIO_NUM_START1, NUM_GPIOS1); +#endif + return TEE_SUCCESS; +} +driver_init(bcm_gpio_init); diff --git a/optee/optee_os/core/drivers/bcm_hwrng.c b/optee/optee_os/core/drivers/bcm_hwrng.c new file mode 100644 index 0000000..d9351c1 --- /dev/null +++ b/optee/optee_os/core/drivers/bcm_hwrng.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define RNG_CTRL_OFFSET 0x00 +#define RNG_CTRL_MASK 0x00001fff +#define RNG_CTRL_DISABLE 0x00000000 +#define RNG_CTRL_ENABLE 0x00000001 + +#define RNG_SOFT_RESET_OFFSET 0x04 +#define RNG_SOFT_RESET_MASK 0x00000001 + +#define RNG_FIFO_DATA_OFFSET 0x20 + +#define RNG_FIFO_COUNT_OFFSET 0x24 + +#define RNG_FIFO_COUNT_MASK 0x000000ff +#define RNG_TIMEOUT_US 10000 + +static vaddr_t bcm_hwrng_base; + +static void bcm_hwrng_reset(void) +{ + /* Disable RBG */ + io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET, + RNG_CTRL_MASK, RNG_CTRL_DISABLE); + /* Reset RNG and RBG */ + io_setbits32(bcm_hwrng_base + + RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK); + io_clrbits32(bcm_hwrng_base + + RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK); + /* Enable RBG */ + io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET, + RNG_CTRL_MASK, RNG_CTRL_ENABLE); +} + +uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read) +{ + uint32_t available_words = 0; + uint32_t num_words = 0; + uint32_t i = 0; + uint64_t timeout = timeout_init_us(RNG_TIMEOUT_US); + + assert(bcm_hwrng_base); + + do { + available_words = io_read32(bcm_hwrng_base + + RNG_FIFO_COUNT_OFFSET); + available_words = available_words & RNG_FIFO_COUNT_MASK; + } while (!available_words && !timeout_elapsed(timeout)); + + if ((available_words > 0) && (words_to_read > 0)) { + num_words = MIN(available_words, words_to_read); + for (i = 0; i < num_words; i++) + p_out[i] = io_read32(bcm_hwrng_base + + RNG_FIFO_DATA_OFFSET); + } + + return num_words; +} + +static TEE_Result bcm_hwrng_init(void) +{ + bcm_hwrng_base = (vaddr_t)phys_to_virt(HWRNG_BASE, MEM_AREA_IO_SEC, + HWRNG_END - HWRNG_BASE); + + bcm_hwrng_reset(); + + DMSG("bcm_hwrng init done\n"); + return TEE_SUCCESS; +} + +driver_init(bcm_hwrng_init); diff --git a/optee/optee_os/core/drivers/bcm_sotp.c b/optee/optee_os/core/drivers/bcm_sotp.c new file mode 100644 index 0000000..75199e4 --- /dev/null +++ b/optee/optee_os/core/drivers/bcm_sotp.c @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SOTP_PROG_CONTROL 0x00 +#define SOTP_WRDATA_0 0x04 +#define SOTP_WRDATA_1 0x08 +#define SOTP_ADDR 0x0c +#define SOTP_CTRL_0 0x10 +#define SOTP_STAT_0 0x18 +#define SOTP_STATUS_1 0x1c +#define SOTP_RDDATA_0 0x20 +#define SOTP_RDDATA_1 0x24 +#define SOTP_REGS_SOTP_CHIP_STATES 0x28 +#define SOTP_REGS_OTP_WR_LOCK 0x38 +#define SOTP_CHIP_CTRL 0x4c + +#define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN BIT(15) +#define SOTP_PROG_CONTROL__OTP_DISABLE_ECC BIT(9) +#define SOTP_ADDR__OTP_ROW_ADDR_R 6 +#define SOTP_PROG_CONTROL__OTP_ECC_WREN BIT(8) +#define SOTP_CTRL_0__START 1 +#define SOTP_STATUS_0__FDONE BIT(3) +#define SOTP_STATUS_1__CMD_DONE BIT(1) +#define SOTP_STATUS_1__ECC_DET BIT(17) + +#define SOTP_READ 0 +#define SOTP_ADDR_MASK 0x3ff +#define SOTP_TIMEOUT_US 300 + +#define SOTP_PROG_WORD 10 +#define SOTP_STATUS__PROGOK BIT(2) +#define SOTP_PROG_ENABLE 2 + +#define SOTP_ROW_DATA_MASK UINT32_MAX +#define SOTP_ECC_ERR_BITS_MASK GENMASK_64(40, 32) + +#define SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES 4 +#define SOTP_CHIP_CTRL_SW_MANU_PROG 5 +#define SOTP_CHIP_CTRL_SW_CID_PROG 6 +#define SOTP_CHIP_CTRL_SW_AB_DEVICE 8 +#define SOTP_CHIP_CTRL_SW_AB_DEV_MODE 9 +#define CHIP_STATE_UNPROGRAMMED 0x1 +#define CHIP_STATE_UNASSIGNED 0x2 +#define CHIP_STATE_DEFAULT (CHIP_STATE_UNASSIGNED | \ + CHIP_STATE_UNPROGRAMMED) + +static vaddr_t bcm_sotp_base; + +static TEE_Result otp_status_done_wait(vaddr_t addr, uint32_t bit) +{ + uint64_t timeout = timeout_init_us(SOTP_TIMEOUT_US); + + while (!(io_read32(addr) & bit)) + if (timeout_elapsed(timeout)) + return TEE_ERROR_BUSY; + return TEE_SUCCESS; +} + +TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, bool sotp_add_ecc, + uint64_t *rdata) +{ + uint64_t read_data = 0; + uint32_t reg_val = 0; + TEE_Result ret = TEE_SUCCESS; + + assert(bcm_sotp_base); + /* Check for FDONE status */ + ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0), + SOTP_STATUS_0__FDONE); + if (ret) { + EMSG("FDONE status done wait failed and returned %#"PRIx32, + ret); + return ret; + } + + /* Enable OTP access by CPU */ + io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL), + SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); + + /* ROWS does not support ECC */ + if (row_addr <= SOTP_NO_ECC_ROWS) + sotp_add_ecc = false; + + if (sotp_add_ecc) { + io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL), + SOTP_PROG_CONTROL__OTP_DISABLE_ECC); + } else { + io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL), + SOTP_PROG_CONTROL__OTP_DISABLE_ECC); + } + + /* 10 bit row address */ + reg_val = (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R; + io_write32((bcm_sotp_base + SOTP_ADDR), reg_val); + reg_val = SOTP_READ; + io_write32((bcm_sotp_base + SOTP_CTRL_0), reg_val); + + /* Start bit to tell SOTP to send command to the OTP controller */ + io_setbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START); + + /* Wait for SOTP command done to be set */ + ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0), + SOTP_STATUS_1__CMD_DONE); + if (ret) { + EMSG("FDONE cmd done wait failed and returned %#"PRIx32, ret); + return ret; + } + + DMSG("CMD Done"); + + /* Clr Start bit after command done */ + io_clrbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START); + read_data = io_read32(bcm_sotp_base + SOTP_RDDATA_1); + read_data = ((read_data & 0x1ff) << 32); + read_data |= io_read32(bcm_sotp_base + SOTP_RDDATA_0); + + reg_val = io_read32(bcm_sotp_base + SOTP_STATUS_1); + /* No ECC check till SOTP_NO_ECC_ROWS */ + if (row_addr > SOTP_NO_ECC_ROWS && + reg_val & SOTP_STATUS_1__ECC_DET) { + EMSG("SOTP ECC ERROR Detected ROW %"PRIu32, row_addr); + read_data = SOTP_ECC_ERR_DETECT; + } + + /* Command done is cleared */ + io_setbits32((bcm_sotp_base + SOTP_STATUS_1), SOTP_STATUS_1__CMD_DONE); + io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL), + SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); + DMSG("read done"); + + *rdata = read_data; + return ret; +} + +TEE_Result bcm_iproc_sotp_mem_write(uint32_t row_addr, bool sotp_add_ecc, + uint64_t wdata) +{ + uint32_t chip_state = 0; + uint32_t chip_ctrl_default = 0; + uint32_t chip_ctrl = 0; + uint32_t loop = 0; + uint8_t prog_array[4] = { 0x0F, 0x04, 0x08, 0x0D }; + TEE_Result ret = TEE_SUCCESS; + + assert(bcm_sotp_base); + + chip_state = io_read32(bcm_sotp_base + SOTP_REGS_SOTP_CHIP_STATES); + + if (chip_state & CHIP_STATE_DEFAULT) { + chip_ctrl_default = io_read32(bcm_sotp_base + SOTP_CHIP_CTRL); + DMSG("SOTP: enable special prog mode"); + + chip_ctrl = BIT(SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES) | + BIT(SOTP_CHIP_CTRL_SW_MANU_PROG) | + BIT(SOTP_CHIP_CTRL_SW_CID_PROG) | + BIT(SOTP_CHIP_CTRL_SW_AB_DEVICE); + + io_write32(bcm_sotp_base + SOTP_CHIP_CTRL, chip_ctrl); + } + + /* Check for FDONE status */ + ret = otp_status_done_wait(bcm_sotp_base + SOTP_STAT_0, + SOTP_STATUS_0__FDONE); + if (ret) { + EMSG("FDONE status done wait failed and returned %#"PRIx32, + ret); + return ret; + } + + /* Enable OTP access by CPU */ + io_setbits32(bcm_sotp_base + SOTP_PROG_CONTROL, + SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); + + if (row_addr <= SOTP_NO_ECC_ROWS) { + if (sotp_add_ecc) { + io_setbits32(bcm_sotp_base + SOTP_PROG_CONTROL, + SOTP_PROG_CONTROL__OTP_ECC_WREN); + } else { + io_clrbits32(bcm_sotp_base + SOTP_PROG_CONTROL, + SOTP_PROG_CONTROL__OTP_ECC_WREN); + } + } else { + io_clrbits32(bcm_sotp_base + SOTP_PROG_CONTROL, + SOTP_PROG_CONTROL__OTP_ECC_WREN); + } + + io_write32(bcm_sotp_base + SOTP_CTRL_0, SOTP_PROG_ENABLE << 1); + + /* + * In order to avoid unintentional writes/programming of the OTP array, + * the OTP Controller must be put into programming mode before it will + * accept program commands. This is done by writing 0xF, 0x4, 0x8, 0xD + * with program commands prior to starting the actual programming + * sequence. + */ + for (loop = 0; loop < ARRAY_SIZE(prog_array); loop++) { + io_write32(bcm_sotp_base + SOTP_WRDATA_0, prog_array[loop]); + + /* Bit to tell SOTP to send command to the OTP controller */ + io_setbits32(bcm_sotp_base + SOTP_CTRL_0, SOTP_CTRL_0__START); + + /* Wait for SOTP command done to be set */ + ret = otp_status_done_wait(bcm_sotp_base + SOTP_STATUS_1, + SOTP_STATUS_1__CMD_DONE); + if (ret) { + EMSG("FDONE cmd done wait failed and returned %"PRIx32, + ret); + return ret; + } + + /* Command done is cleared w1c */ + io_setbits32(bcm_sotp_base + SOTP_STATUS_1, + SOTP_STATUS_1__CMD_DONE); + + /* Clear Start bit after command done */ + io_clrbits32(bcm_sotp_base + SOTP_CTRL_0, SOTP_CTRL_0__START); + } + + /* Check for PROGOK */ + ret = otp_status_done_wait(bcm_sotp_base + SOTP_STAT_0, + SOTP_STATUS__PROGOK); + if (ret) { + EMSG("PROGOK cmd wait failed and returned %#"PRIx32, ret); + return ret; + } + + /* Set 10 bit row address */ + io_write32(bcm_sotp_base + SOTP_ADDR, + (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R); + + /* Set SOTP Row data */ + io_write32(bcm_sotp_base + SOTP_WRDATA_0, wdata & SOTP_ROW_DATA_MASK); + + /* Set SOTP ECC and error bits */ + io_write32(bcm_sotp_base + SOTP_WRDATA_1, + (wdata & SOTP_ECC_ERR_BITS_MASK) >> 32); + + /* Set prog_word command */ + io_write32(bcm_sotp_base + SOTP_CTRL_0, SOTP_PROG_WORD << 1); + + /* Start bit to tell SOTP to send command to the OTP controller */ + io_setbits32(bcm_sotp_base + SOTP_CTRL_0, SOTP_CTRL_0__START); + + /* Wait for SOTP command done to be set */ + ret = otp_status_done_wait(bcm_sotp_base + SOTP_STATUS_1, + SOTP_STATUS_1__CMD_DONE); + if (ret) { + EMSG("CMD DONE wait failed and returned %#"PRIx32, ret); + return ret; + } + + /* Command done is cleared w1c */ + io_setbits32(bcm_sotp_base + SOTP_STATUS_1, SOTP_STATUS_1__CMD_DONE); + + /* disable OTP access by CPU */ + io_clrbits32(bcm_sotp_base + SOTP_PROG_CONTROL, + SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); + + /* Clr Start bit after command done */ + io_clrbits32(bcm_sotp_base + SOTP_CTRL_0, SOTP_CTRL_0__START); + + if (chip_state & CHIP_STATE_DEFAULT) + io_write32(bcm_sotp_base + SOTP_CHIP_CTRL, chip_ctrl_default); + + return TEE_SUCCESS; +} + +static TEE_Result bcm_sotp_init(void) +{ + bcm_sotp_base = (vaddr_t)phys_to_virt(SOTP_BASE, MEM_AREA_IO_SEC, 1); + + DMSG("bcm_sotp init done"); + return TEE_SUCCESS; +} + +service_init(bcm_sotp_init); diff --git a/optee/optee_os/core/drivers/bnxt/bnxt.c b/optee/optee_os/core/drivers/bnxt/bnxt.c new file mode 100644 index 0000000..ae613dc --- /dev/null +++ b/optee/optee_os/core/drivers/bnxt/bnxt.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BNXT_REG_CTRL_BASE 0x3040000 +#define BNXT_REG_ECO_RESERVED 0x3042400 +#define BNXT_FLASH_ACCESS_DONE_BIT 2 +#define NIC400_BNXT_IDM_IO_CONTROL_DIRECT 0x60e00408 +#define BNXT_INDIRECT_BASE 0x60800000 +#define BNXT_INDIRECT_ADDR_MASK 0x3fffffu +#define BNXT_INDIRECT_BASE_MASK (~BNXT_INDIRECT_ADDR_MASK) +#define BNXT_INDIRECT_WINDOW_SIZE (BNXT_INDIRECT_ADDR_MASK + 1) +#define BNXT_REG_CTRL_BPE_MODE_REG 0x0 +#define BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT 2 +#define BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT 1 +#define BNXT_REG_CTRL_BPE_STAT_REG 0x4 +#define BNXT_REG_CTRL_FSTBOOT_PTR_REG 0x8 +#define BNXT_ERROR_MASK 0xf0000000 +#define BNXT_CTRL_ADDR(x) (BNXT_REG_CTRL_BASE + (x)) +#define BNXT_HANDSHAKE_TIMEOUT_MS 1000 + +#define KONG_REG_CTRL_MODE_REG 0x03900000 +#define KONG_REG_CTRL_MODE_CPUHALT_N_BIT 0 + +#define BNXT_STICKY_BYTE_POR 0x04030088 +#define BNXT_STICKY_BYTE_POR_MHB_BIT 4 + +#define BNXT_HEALTH_CHECK_REG 0x03100008 + +enum bnxt_handshake_sts { + BNXT_HANDSHAKE_SUCCESS = 0, + BNXT_HANDSHAKE_WAIT_ERROR, + BNXT_HANDSHAKE_WAIT_TIMEOUT +}; + +static vaddr_t bnxt_access_window_virt_addr; +static vaddr_t bnxt_indirect_dest_addr; + +static void bnxt_prepare_access_window(uint32_t addr) +{ + addr &= BNXT_INDIRECT_BASE_MASK; + io_write32(bnxt_access_window_virt_addr, addr); +} + +static vaddr_t bnxt_indirect_tgt_addr(uint32_t addr) +{ + addr &= BNXT_INDIRECT_ADDR_MASK; + return (vaddr_t)(bnxt_indirect_dest_addr + addr); +} + +uint32_t bnxt_write32_multiple(uintptr_t dst, + uintptr_t src, + uint32_t num_entries, + int src_4byte_increment) +{ + uint32_t i = 0; + vaddr_t target = 0; + + if (num_entries == 0) + return 0; + + /* Only write up to the next window boundary */ + if ((dst & BNXT_INDIRECT_BASE_MASK) != + ((dst + num_entries * sizeof(uint32_t)) & BNXT_INDIRECT_BASE_MASK)) + num_entries = (((dst + BNXT_INDIRECT_WINDOW_SIZE) & + BNXT_INDIRECT_BASE_MASK) - + dst) / + sizeof(uint32_t); + + bnxt_prepare_access_window(dst); + target = bnxt_indirect_tgt_addr(dst); + for (i = 0; i < num_entries; i++) { + io_write32(target, *(uint32_t *)src); + target += sizeof(uint32_t); + if (src_4byte_increment) + src += sizeof(uint32_t); + } + + return num_entries; +} + +static uint32_t bnxt_read(uint32_t addr) +{ + bnxt_prepare_access_window(addr); + return io_read32(bnxt_indirect_tgt_addr(addr)); +} + +static uint32_t bnxt_read_ctrl(uint32_t offset) +{ + return bnxt_read(BNXT_CTRL_ADDR(offset)); +} + +static void bnxt_write(uint32_t addr, uint32_t value) +{ + bnxt_prepare_access_window(addr); + io_write32(bnxt_indirect_tgt_addr(addr), value); +} + +static void bnxt_write_ctrl(uint32_t offset, uint32_t value) +{ + bnxt_write(BNXT_CTRL_ADDR(offset), value); +} + +void bnxt_handshake_clear(void) +{ + uint32_t value = bnxt_read(BNXT_REG_ECO_RESERVED); + + value = value & ~BIT(BNXT_FLASH_ACCESS_DONE_BIT); + bnxt_write(BNXT_REG_ECO_RESERVED, value); +} + +static int bnxt_handshake_done(void) +{ + uint32_t value = 0; + + value = bnxt_read(BNXT_REG_ECO_RESERVED); + value &= BIT(BNXT_FLASH_ACCESS_DONE_BIT); + + return value != 0; +} + +uint32_t bnxt_wait_handshake(uint32_t max_timeout) +{ + int ret = 0; + uint32_t status = 0; + uint32_t timeout = 0; + + /* If no timeout given we go with max timeout */ + if (max_timeout == 0) + max_timeout = BNXT_HANDSHAKE_TIMEOUT_MS; + + timeout = max_timeout; + + DMSG("Waiting for ChiMP handshake..."); + do { + if (bnxt_handshake_done()) { + ret = BNXT_HANDSHAKE_SUCCESS; + break; + } + /* No need to wait if ChiMP reported an error */ + status = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_STAT_REG); + if (status & BNXT_ERROR_MASK) { + EMSG("ChiMP error 0x%x. Wait aborted", status); + ret = BNXT_HANDSHAKE_WAIT_ERROR; + break; + } + mdelay(1); + } while (--timeout); + + if (!bnxt_handshake_done()) { + if (timeout == 0) { + ret = BNXT_HANDSHAKE_WAIT_TIMEOUT; + EMSG("Timeout waiting for ChiMP handshake"); + } + } else { + ret = BNXT_HANDSHAKE_SUCCESS; + DMSG("ChiMP handshake successful"); + } + + return ret; +} + +void bnxt_chimp_halt(void) +{ + uint32_t value = 0; + + value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG); + value |= BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT); + bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value); +} + +void bnxt_kong_halt(void) +{ + uint32_t value = 0; + + value = bnxt_read(KONG_REG_CTRL_MODE_REG); + value &= ~BIT(KONG_REG_CTRL_MODE_CPUHALT_N_BIT); + bnxt_write(KONG_REG_CTRL_MODE_REG, value); +} + +int bnxt_fastboot(uintptr_t addr) +{ + uint32_t value = 0; + + value = bnxt_read(BNXT_STICKY_BYTE_POR); + value |= BIT(BNXT_STICKY_BYTE_POR_MHB_BIT); + bnxt_write(BNXT_STICKY_BYTE_POR, value); + + /* Set the fastboot address and type */ + bnxt_write_ctrl(BNXT_REG_CTRL_FSTBOOT_PTR_REG, addr); + + /* Set fastboot mode & take BNXT CPU1 out of reset */ + value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG); + value |= BIT(BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT); + value &= ~BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT); + bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value); + + return 0; +} + +uint32_t bnxt_health_status(void) +{ + return bnxt_read(BNXT_HEALTH_CHECK_REG); +} + +static TEE_Result bnxt_init(void) +{ + bnxt_access_window_virt_addr = + (vaddr_t)phys_to_virt(NIC400_BNXT_IDM_IO_CONTROL_DIRECT, + MEM_AREA_IO_SEC, sizeof(uint32_t)); + bnxt_indirect_dest_addr = + (vaddr_t)phys_to_virt(BNXT_INDIRECT_BASE, + MEM_AREA_IO_SEC, + BNXT_INDIRECT_WINDOW_SIZE); + return TEE_SUCCESS; +} +driver_init(bnxt_init); diff --git a/optee/optee_os/core/drivers/bnxt/bnxt_fw.c b/optee/optee_os/core/drivers/bnxt/bnxt_fw.c new file mode 100644 index 0000000..d4c9bab --- /dev/null +++ b/optee/optee_os/core/drivers/bnxt/bnxt_fw.c @@ -0,0 +1,697 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * These macros are the offsets where images reside on sec mem + */ +#define BNXT_BUFFER_SEC_MEM 0x8ae00000 +#define BNXT_FW_SEC_MEM_SRC BNXT_BUFFER_SEC_MEM +#define BNXT_FW_SEC_MEM_CFG (BNXT_BUFFER_SEC_MEM + 0x100000) +#define TEMP_MEM (BNXT_BUFFER_SEC_MEM + 0x180000) + +#define BNXT_CRASH_SEC_MEM 0x8b000000 +#define BNXT_CRASH_LEN 0x2000000 + +#define BNXT_CONFIG_NS3_DEST 0x03a00000 +#define BNXT_BSPD_CFG_OFFSET 0x51b0 +#define BNXT_CONFIG_NS3_BSPD_DEST (BNXT_CONFIG_NS3_DEST + \ + BNXT_BSPD_CFG_OFFSET) +#define BNXT_BSPD_CFG_SIZE 0x200 + +#define BNXT_CRASH_DUMP_INFO_NS3_BASE 0x3a5ff00 + +#define SZ_1K 0x400 + +#define BUFFER_PADDING SZ_1K + +#define INC_SRC_ADDR 1 + +#define EOF -1 + +#define BCM_BNXT_FASTBOOT_MASK 0x3u +#define BCM_BNXT_FASTBOOT_TYPE_1 1 + +#define ADDR_IS_4BYTE_ALIGNED(addr) IS_ALIGNED(addr, 4) + +#define SECTION_IS_LOADABLE(section_ptr) \ + ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_LOADABLE) +#define SECTION_IS_ZIPPED(section_ptr) \ + ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_ZIPPED) +#define SECTION_IS_TOBE_COPIED(section_ptr) \ + ((section_ptr)->flags_src_offset & \ + (SECTION_FLAGS_IS_EXEC_INSTR | SECTION_FLAGS_IS_DATA)) +#define SECTION_IS_TOBE_ZEROED(section_ptr) \ + ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_BSS) +#define SECTION_IS_4BYTE_ALIGNED(section_ptr) \ + ADDR_IS_4BYTE_ALIGNED((section_ptr)->dest_addr) + +#define SECTION_SRC_OFFSET(section_ptr) \ + ((section_ptr)->flags_src_offset & SECTION_SRC_OFFFSET_MASK) + +/* -------------------------------------------------------------------------- */ + +/* Section header for each image block */ +struct ape_section_hdr_s { + /* Destination address that this section is to be copied to */ + uint32_t dest_addr; + + /* + * bit[0:23] source offset address that this image copy from + * bit[24:31] flags + */ + uint32_t flags_src_offset; +#define SECTION_FLAGS_MASK 0xff000000 + /* Session is compressed (zipped) */ +#define SECTION_FLAGS_IS_ZIPPED 0x01000000 + /* Session contains CRC */ +#define SECTION_FLAGS_IS_CRC 0x02000000 + /* Session contains executable code (e.g. .text) */ +#define SECTION_FLAGS_IS_EXEC_INSTR 0x04000000 + /* Session contains initialized data (e.g. .data) */ +#define SECTION_FLAGS_IS_DATA 0x08000000 + /* Session contains zero initialized data (e.g. .bss) */ +#define SECTION_FLAGS_IS_BSS 0x10000000 + /* Loadable section mask */ +#define SECTION_FLAGS_IS_LOADABLE (SECTION_FLAGS_IS_EXEC_INSTR | \ + SECTION_FLAGS_IS_DATA | \ + SECTION_FLAGS_IS_BSS) +#define SECTION_SRC_OFFFSET_MASK 0x00ffffff + + /* Original image length, dword (4byte) length */ + uint32_t org_data_len; + + /* Compressed image length (if FlAGS_IS_ZIPPED is set) */ + uint32_t zip_data_len; + + /* + * checksum value for this image block, if FLAGS_IS_CRC then + * this is CRC checksum; otherwise it is a simple summation + */ + uint32_t checksum; +}; + +struct version_s { + uint8_t version[16]; /* Null-terminated file version string */ +}; + +struct ver_ext_offset_s { + uint8_t version[12]; /* Null-terminated file version string */ + uint32_t ext_hdr_offset; +}; + +union version_and_offset_u { + struct version_s version1; + struct ver_ext_offset_s version2; +}; + +struct ape_bin_hdr_s { + /* APE binary header signature; expects APE_BIN_HDR_SIGNATURE */ + uint32_t signature; +#define APE_BIN_HDR_SIGNATURE 0x1a4d4342 /* "BCM"+0x1a */ + /* Reserved for ChiMP's use */ + uint8_t flags; + uint8_t code_type; + uint8_t device; + uint8_t media; + union version_and_offset_u ver; + uint8_t build; + uint8_t revision; + uint8_t minor_ver; + uint8_t major_ver; + uint32_t entry_address; + uint8_t reserved; + uint8_t header_dword_size; + uint8_t num_total_sections; + uint8_t num_loadable_sections; + uint32_t checksum; +} __packed __aligned(1); + +#define APE_BIN_HDR_SIZE sizeof(struct ape_bin_hdr_s) +#define APE_SECTION_HDR_SIZE sizeof(struct ape_section_hdr_s) + +/* MAX number of image sections that will be accepted */ +#define APE_IMG_MAX_SECTIONS 16 + +#define APE_IMG_LOAD_DEBUG 0 + +/* -------------------------------------------------------------------------- */ + +struct ape_mem_region_s { + uint32_t c_base; /* ChiMP's view of address */ + uint32_t h_base; /* Host's view of address */ + uint32_t size; /* Size in bytes */ +}; + +/* Memory map into various scratchpad memories */ +static struct ape_mem_region_s ape_mem_regions[] = { + /* CHIMP scratchpad */ + {0x00100000, 0x03100000, 1024 * SZ_1K}, + + /* APE scratchpad */ + {0x61000000, 0x03300000, 1152 * SZ_1K}, + + /* BONO scratchpad */ + {0x61600000, 0x03a00000, 512 * SZ_1K}, + + /* KONG scratchpad */ + {0x61400000, 0x03800000, 512 * SZ_1K}, + + /* Keep this last!! */ + {0, 0, 0} +}; + +/* Nitro crash address configuration related macros */ +#define BNXT_CRASH_INFO_SIGNATURE 0x20524444 +#define BNXT_CRASH_INFO_VALID 0x1 +#define MAX_CRASH_ADDR_ITEM 8 + +struct nitro_crash_addr_item { + uint32_t info; + uint32_t size; + uint32_t addr_hi; + uint32_t addr_lo; +}; + +struct nitro_crash_addr_info { + /* CRC of the struct content, starting at next field. */ + uint32_t crc; + uint32_t signature; + uint32_t version; + struct nitro_crash_addr_item table[MAX_CRASH_ADDR_ITEM]; +}; + +static inline void memcpy32_helper(uintptr_t src, + uintptr_t dst, + uint32_t entries, + int inc_src_addr) +{ + uint32_t copied_entries = 0; + + while (entries) { + copied_entries = bnxt_write32_multiple(dst, src, entries, + inc_src_addr); + + if (copied_entries < entries) { + dst += copied_entries * sizeof(uint32_t); + src += (inc_src_addr) ? + (copied_entries * sizeof(uint32_t)) : 0; + entries -= copied_entries; + } else { + entries = 0; + } + } +} + +static uint32_t ape_host_view_addr_get(uint32_t bnxt_view_addr, uint32_t size) +{ + struct ape_mem_region_s *region = ape_mem_regions; + uint32_t addr = 0; + + for (; region->size != 0; region++) { + if (bnxt_view_addr < region->c_base) + continue; + + if (bnxt_view_addr >= (region->c_base + region->size)) + continue; + + if (size > (region->c_base + region->size - bnxt_view_addr)) { + EMSG("ERROR: 0x%x + 0x%x spans memory boundary", + bnxt_view_addr, size); + break; + } + + addr = bnxt_view_addr - region->c_base; + addr += region->h_base; + break; + } + + return addr; +} + +static uint32_t ape_hdr_crc_calc(const struct ape_bin_hdr_s *hdr) +{ + uint32_t crc = 0; + uint32_t dummy = 0; + + /* Compute the CRC up to, but not including, the checksum field */ + crc = CRC32(CRC32_INIT_VAL, + (const char *)hdr, + (uintptr_t)(&hdr->checksum) - (uintptr_t)hdr); + + /* Compute the CRC with the checksum field zeroed out */ + crc = CRC32(~crc, (const char *)&dummy, sizeof(uint32_t)); + + /* + * Compute the remainder part of the image header, i.e., the + * section headers + */ + crc = CRC32(~crc, + (const char *)((uintptr_t)hdr + APE_BIN_HDR_SIZE), + hdr->num_total_sections * APE_SECTION_HDR_SIZE); + + return crc; +} + +static int ape_bin_hdr_valid(const struct ape_bin_hdr_s *hdr) +{ + uint32_t checksum = 0; + + if (!hdr) { + EMSG("ERROR: no APE image header"); + return BNXT_FAILURE; + } + + if (hdr->signature != APE_BIN_HDR_SIGNATURE) { + EMSG("ERROR: bad APE image signature"); + return BNXT_FAILURE; + } + + if (hdr->num_total_sections > APE_IMG_MAX_SECTIONS) { + EMSG("ERROR: too many sections in APE image"); + return BNXT_FAILURE; + } + + checksum = ape_hdr_crc_calc(hdr); + if (hdr->checksum != checksum) { + EMSG("ERROR: bad APE header checksum (exp: %x, act: %x)", + hdr->checksum, checksum); + return BNXT_FAILURE; + } + + return BNXT_SUCCESS; +} + +static int get_char(uint8_t *inbuf, size_t *inbuf_idx, size_t inbuf_size) +{ + int c = 0; + + if (*inbuf_idx >= inbuf_size) + return EOF; + + c = inbuf[*inbuf_idx]; + *inbuf_idx += 1; + + return c; +} + +static void put_char(uint8_t *outbuf, + size_t *outbuf_idx, + size_t outbuf_size, + uint8_t ch) +{ + if (*outbuf_idx >= outbuf_size) + return; + + outbuf[*outbuf_idx] = ch; + *outbuf_idx += 1; +} + +static size_t ape_section_uncompress(uint8_t *inbuf, + size_t inbuf_size, + uint8_t *outbuf, + size_t outbuf_size) +{ + int i = 0, j = 0, k = 0, r = 0, c = 0; + uint32_t flags = 0; + size_t exp_size = 0, codesize = 0; + size_t inbuf_idx = 0, outbuf_idx = 0; +#define CODE_8U_MASK 0xff00u /* 8 code units count mask (8 bits) */ +#define CODE_END_MASK 0x100u /* End of code units mask */ +#define CODE_IS_UNENCODED_MASK 1 /* Unencoded code unit mask */ +#define CODE_POS_MASK 0xe0u /* Encoded unit position mask and */ +#define CODE_POS_SHIFT 3 /* Bit shift */ +#define CODE_LEN_MASK 0x1fu /* Encoded unit length mask */ +#define NS 2048 /* Size of ring buffer */ +#define F 34 /* Upper limit for match_length */ +#define THRESHOLD 2 /* Encode string into position and + * length, if match_length is + * greater than this. + */ + /* + * Ring buffer of size NS, with an extra F-1 bytes to facilitate + * string comparisons. + */ + uint8_t text_buf[NS + F - 1]; + + inbuf_idx = 0; + outbuf_idx = 0; + + for (i = 0; i < NS - F; i++) + text_buf[i] = ' '; + + r = NS - F; + + for (;;) { + if (((flags >>= 1) & CODE_END_MASK) == 0) { + c = get_char(inbuf, &inbuf_idx, inbuf_size); + if (c == EOF) + break; + ++exp_size; + + if (exp_size > inbuf_size) + break; + + /* Use higher byte cleverly to count to eight */ + flags = c | CODE_8U_MASK; + } + + if (flags & CODE_IS_UNENCODED_MASK) { + /* Not encoded; simply copy the unit */ + c = get_char(inbuf, &inbuf_idx, inbuf_size); + if (c == EOF) + break; + + ++exp_size; + if (exp_size > inbuf_size) + break; + + put_char(outbuf, &outbuf_idx, outbuf_size, c); + text_buf[r++] = c; + r &= (NS - 1); + ++codesize; + } else { + /* Encoded; get the position and length & duplicate */ + i = get_char(inbuf, &inbuf_idx, inbuf_size); + if (i == EOF) + break; + + ++exp_size; + if (exp_size > inbuf_size) + break; + + j = get_char(inbuf, &inbuf_idx, inbuf_size); + if (j == EOF) + break; + + ++exp_size; + if (exp_size > inbuf_size) + break; + + i |= ((j & CODE_POS_MASK) << CODE_POS_SHIFT); + j = ((j & CODE_LEN_MASK) + THRESHOLD); + + for (k = 0; k <= j; k++) { + c = text_buf[((i + k) & (NS - 1))]; + put_char(outbuf, &outbuf_idx, outbuf_size, c); + text_buf[r++] = c; + r &= (NS - 1); + ++codesize; + } + } + } + + return codesize; +} + +static int ape_section_copy(struct ape_bin_hdr_s *bin_hdr, + struct ape_section_hdr_s *section) +{ + uintptr_t src = 0; + uintptr_t dst = 0; + uint32_t checksum = 0; + uint32_t i = 0; + size_t size = 0; + uint8_t *section_data = NULL; + size_t work_buff_size = 0; + void *work_buff = NULL; + int rc = BNXT_FAILURE; + + if (SECTION_IS_ZIPPED(section)) { + work_buff_size = section->org_data_len + BUFFER_PADDING; + work_buff = (void *)phys_to_virt(TEMP_MEM, MEM_AREA_RAM_SEC, + work_buff_size); + if (!work_buff) { + EMSG("ERROR: buffer allocation"); + return BNXT_FAILURE; + } + + section_data = (uint8_t *)((uintptr_t)bin_hdr + + SECTION_SRC_OFFSET(section)); + size = ape_section_uncompress(section_data, + section->zip_data_len, + work_buff, + work_buff_size); + if (size >= work_buff_size) { + EMSG("ERROR: section uncompress"); + goto ape_section_copy_exit; + } + if (size < section->org_data_len) { + EMSG("ERROR: decompressed data size mismatch "); + EMSG("(exp: %d, act: %ld)", + section->org_data_len, size); + goto ape_section_copy_exit; + } + src = (uintptr_t)work_buff; + } else { + src = (uintptr_t)bin_hdr + SECTION_SRC_OFFSET(section); + } + + size = section->org_data_len; + + if (section->flags_src_offset & SECTION_FLAGS_IS_CRC) { + checksum = CRC32(CRC32_INIT_VAL, (const char *)src, size); + } else { + checksum = 0; + for (i = 0; i < size / sizeof(uint32_t); i++) + checksum += ((uint32_t *)src)[i]; + } + if (checksum != section->checksum) { + EMSG("ERROR: checksum mismatch (exp: %x, act: %x)", + section->checksum, checksum); + goto ape_section_copy_exit; + } + + dst = ape_host_view_addr_get(section->dest_addr, size); + if (dst == 0) { + EMSG("ERROR: ChiMP-to-host address conversion of %x", + section->dest_addr); + goto ape_section_copy_exit; + } + + /* Copy the section */ + size = size / sizeof(uint32_t); + memcpy32_helper(src, dst, size, INC_SRC_ADDR); + + rc = BNXT_SUCCESS; + +ape_section_copy_exit: + return rc; +} + +static int ape_section_zero(struct ape_section_hdr_s *section) +{ + uint32_t dst = 0; + uint32_t size = section->org_data_len; + uint32_t zero = 0; + + if (section->org_data_len == 0) + return BNXT_SUCCESS; + + /* Convert ChiMP's view of the address in the image to the host view */ + dst = ape_host_view_addr_get(section->dest_addr, size); + if (dst == 0) { + EMSG("ERROR: ChiMP-to-host address conversion of %x", + section->dest_addr); + return BNXT_FAILURE; + } + + /* + * Zero the section; we simply copy zeros and do not increment the + * source buffer address. + */ + size = size / sizeof(uint32_t); + memcpy32_helper((uintptr_t)&zero, dst, size, !INC_SRC_ADDR); + + return BNXT_SUCCESS; +} + +static int bnxt_load(vaddr_t img_buffer) +{ + struct ape_bin_hdr_s *bin_hdr = NULL; + struct ape_section_hdr_s *section = NULL; + int sidx = 0; + int rc = BNXT_SUCCESS; + + bin_hdr = (struct ape_bin_hdr_s *)img_buffer; + section = (struct ape_section_hdr_s *)(img_buffer + + APE_BIN_HDR_SIZE); + + if (ape_bin_hdr_valid(bin_hdr) != BNXT_SUCCESS) + return BNXT_FAILURE; + + for (sidx = 0; sidx < bin_hdr->num_total_sections; sidx++, section++) { + if (!SECTION_IS_LOADABLE(section)) + continue; + + if (!ADDR_IS_4BYTE_ALIGNED(section->dest_addr)) { + EMSG("ERROR: unaligned section dest address 0x%x", + section->dest_addr); + rc = BNXT_FAILURE; + break; + } + + if (!ADDR_IS_4BYTE_ALIGNED(SECTION_SRC_OFFSET(section))) { + EMSG("ERROR: unaligned section src offset (0x%x)", + SECTION_SRC_OFFSET(section)); + rc = BNXT_FAILURE; + break; + } + + if (section->org_data_len % sizeof(uint32_t)) { + EMSG("ERROR: section size (%d) not divisible by 4", + section->org_data_len); + rc = BNXT_FAILURE; + break; + } + + if (SECTION_IS_TOBE_COPIED(section)) { + rc = ape_section_copy(bin_hdr, section); + if (rc != BNXT_SUCCESS) + break; + } else if (SECTION_IS_TOBE_ZEROED(section)) { + rc = ape_section_zero(section); + if (rc != BNXT_SUCCESS) + break; + } + } + + /* Set up boot mode and take BNXT out of reset */ + if (rc == BNXT_SUCCESS) { + bnxt_fastboot((bin_hdr->entry_address & + ~BCM_BNXT_FASTBOOT_MASK) | + BCM_BNXT_FASTBOOT_TYPE_1); + } + + return rc; +} + +static TEE_Result bnxt_crash_config(uintptr_t info_dst, + uint32_t crash_area_start, + uint32_t crash_len) +{ + struct nitro_crash_addr_item *item = NULL; + uintptr_t dst = 0; + struct nitro_crash_addr_info *info = NULL; + uintptr_t src = 0; + uint32_t crc = 0; + size_t size = 0; + + /* + * First we write into local memory to calculate CRC before + * updating into Nitro memory + */ + info = malloc(sizeof(struct nitro_crash_addr_info)); + if (!info) { + EMSG("ERROR: buffer allocation"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + memset(info, 0, sizeof(struct nitro_crash_addr_info)); + + info->signature = BNXT_CRASH_INFO_SIGNATURE; + info->version = 0x01000000 | MAX_CRASH_ADDR_ITEM; + + /* As of now only one item is filled */ + item = &info->table[0]; + item->info = 0; + item->size = crash_len | BNXT_CRASH_INFO_VALID; + item->addr_hi = 0; + item->addr_lo = crash_area_start; + + /* Checksum calculation */ + crc = CRC32(CRC32_INIT_VAL, + (const char *)info + sizeof(uint32_t), + sizeof(struct nitro_crash_addr_info) - sizeof(uint32_t)); + info->crc = crc; + + /* First we write the contents and then set valid bit */ + item->size &= ~BNXT_CRASH_INFO_VALID; + + size = sizeof(struct nitro_crash_addr_info) / sizeof(uint32_t); + dst = info_dst; + src = (uintptr_t)info; + memcpy32_helper(src, dst, size, INC_SRC_ADDR); + + /* Set the valid bit */ + item->size |= BNXT_CRASH_INFO_VALID; + dst = info_dst + offsetof(struct nitro_crash_addr_info, table) + + offsetof(struct nitro_crash_addr_item, size); + bnxt_write32_multiple(dst, (uintptr_t)&item->size, 1, 1); + + free(info); + + return TEE_SUCCESS; +} + +TEE_Result bnxt_load_fw(int chip_type) +{ + uint32_t size = 0; + uintptr_t dst = 0; + uintptr_t src = 0; + struct bnxt_images_info bnxt_src_image_info; + vaddr_t sec_mem_dest = (vaddr_t)phys_to_virt(BNXT_BUFFER_SEC_MEM, + MEM_AREA_RAM_SEC, 1); + + memset(&bnxt_src_image_info, 0, sizeof(struct bnxt_images_info)); + + if (get_bnxt_images_info(&bnxt_src_image_info, + chip_type, sec_mem_dest) != BNXT_SUCCESS) + return TEE_ERROR_ITEM_NOT_FOUND; + + bnxt_handshake_clear(); + bnxt_kong_halt(); + bnxt_chimp_halt(); + + /* Copy the configs */ + src = (uintptr_t)bnxt_src_image_info.bnxt_cfg_vaddr; + dst = (uintptr_t)BNXT_CONFIG_NS3_DEST; + size = bnxt_src_image_info.bnxt_cfg_len; + size = size / sizeof(uint32_t); + memcpy32_helper(src, dst, size, INC_SRC_ADDR); + + /* Copy bspd config */ + src = (uintptr_t)bnxt_src_image_info.bnxt_bspd_cfg_vaddr; + size = bnxt_src_image_info.bnxt_bspd_cfg_len; + dst = (uintptr_t)BNXT_CONFIG_NS3_BSPD_DEST; + + size = size / sizeof(uint32_t); + memcpy32_helper(src, dst, size, INC_SRC_ADDR); + + /* Fill the bnxt crash dump info */ + bnxt_crash_config((uintptr_t)BNXT_CRASH_DUMP_INFO_NS3_BASE, + BNXT_CRASH_SEC_MEM, + BNXT_CRASH_LEN); + + /* Load bnxt firmware and fastboot */ + bnxt_load(bnxt_src_image_info.bnxt_fw_vaddr); + + return TEE_SUCCESS; +} + +TEE_Result bnxt_copy_crash_dump(uint8_t *d, uint32_t offset, uint32_t len) +{ + size_t crash_len = 0; + void *s = NULL; + + if (ADD_OVERFLOW(offset, len, &crash_len) || + crash_len > BNXT_CRASH_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + s = phys_to_virt(BNXT_CRASH_SEC_MEM + offset, MEM_AREA_RAM_SEC, len); + + cache_op_inner(DCACHE_AREA_INVALIDATE, s, len); + + memcpy(d, s, len); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/bnxt/bnxt_images.c b/optee/optee_os/core/drivers/bnxt/bnxt_images.c new file mode 100644 index 0000000..18584c7 --- /dev/null +++ b/optee/optee_os/core/drivers/bnxt/bnxt_images.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include + +#define BNXT_FW_NS3_IMAGE_SIG 0xFF12345A +#define BNXT_NS3_CFG_IMAGE_SIG 0xCF54321A + +#define BNXT_BSPD_CFG_LEN 512 + +#define QSPI_BASE QSPI_MEM_BASE +#define QSPI_BNXT_IMG (QSPI_BASE + 0x400000) +#define QSPI_BSPD_ADDR (QSPI_BASE + 0x700000) + +#define BCM_NS3 1 + +static void set_bnxt_images_info(struct bnxt_images_info *bnxt_info, + int chip_type, vaddr_t src, vaddr_t dst); + +static struct bnxt_img_header { + uint32_t bnxt_fw_ns3_sig; + uint32_t bnxt_fw_ns3_size; + uint32_t bnxt_ns3_cfg_sig; + uint32_t bnxt_ns3_cfg_size; +} *img_header; + +static int verify_header(vaddr_t mem) +{ + img_header = (struct bnxt_img_header *)mem; + + if (img_header->bnxt_fw_ns3_sig == BNXT_FW_NS3_IMAGE_SIG && + img_header->bnxt_ns3_cfg_sig == BNXT_NS3_CFG_IMAGE_SIG) + return BNXT_SUCCESS; + return BNXT_FAILURE; +} + +static void set_bnxt_images_info(struct bnxt_images_info *bnxt_info, + int chip_type, vaddr_t src, vaddr_t dst) +{ + uint32_t len = 0; + struct bnxt_img_header *dst_header = NULL; + uint32_t fw_image_offset = sizeof(struct bnxt_img_header); + + img_header = (struct bnxt_img_header *)src; + if (dst) { + dst_header = (struct bnxt_img_header *)dst; + memcpy(dst_header, img_header, sizeof(*img_header)); + dst += sizeof(*img_header); + + if (chip_type != BCM_NS3) { + dst_header->bnxt_fw_ns3_size = 0; + dst_header->bnxt_ns3_cfg_size = 0; + } + } + + if (chip_type == BCM_NS3) { + len = img_header->bnxt_fw_ns3_size; + bnxt_info->bnxt_fw_vaddr = src + fw_image_offset; + bnxt_info->bnxt_fw_len = len; + if (dst) { + memcpy((void *)dst, (void *)(src + fw_image_offset), + len); + dst += len; + } + + fw_image_offset += len; + + len = img_header->bnxt_ns3_cfg_size; + bnxt_info->bnxt_cfg_vaddr = src + fw_image_offset; + bnxt_info->bnxt_cfg_len = len; + if (dst) { + memcpy((void *)dst, (void *)(src + fw_image_offset), + len); + } + } +} + +int get_bnxt_images_info(struct bnxt_images_info *bnxt_info, int chip_type, + vaddr_t ddr_dest) +{ + vaddr_t flash_dev_vaddr = 0; + + bnxt_info->bnxt_bspd_cfg_len = BNXT_BSPD_CFG_LEN; + + /* First verify if images are on sec mem */ + if (verify_header(ddr_dest + BNXT_IMG_SECMEM_OFFSET) == BNXT_SUCCESS) { + DMSG("Images found on sec memory"); + + bnxt_info->bnxt_bspd_cfg_vaddr = ddr_dest; + + set_bnxt_images_info(bnxt_info, chip_type, + ddr_dest + BNXT_IMG_SECMEM_OFFSET, 0); + } else { + flash_dev_vaddr = (vaddr_t) + phys_to_virt(QSPI_BNXT_IMG, MEM_AREA_IO_NSEC, + sizeof(struct bnxt_img_header)); + + if (verify_header(flash_dev_vaddr) != BNXT_SUCCESS) { + EMSG("failed to load fw images"); + return BNXT_FAILURE; + } + + DMSG("Images loading from flash memory"); + bnxt_info->bnxt_bspd_cfg_vaddr = + (vaddr_t)phys_to_virt(QSPI_BSPD_ADDR, + MEM_AREA_IO_NSEC, + BNXT_BSPD_CFG_LEN); + memcpy((void *)ddr_dest, (void *)bnxt_info->bnxt_bspd_cfg_vaddr, + BNXT_BSPD_CFG_LEN); + + set_bnxt_images_info(bnxt_info, chip_type, flash_dev_vaddr, + ddr_dest + BNXT_IMG_SECMEM_OFFSET); + } + + return BNXT_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/bnxt/sub.mk b/optee/optee_os/core/drivers/bnxt/sub.mk new file mode 100644 index 0000000..a0021a9 --- /dev/null +++ b/optee/optee_os/core/drivers/bnxt/sub.mk @@ -0,0 +1,3 @@ +srcs-y += bnxt.c +srcs-y += bnxt_fw.c +srcs-y += bnxt_images.c diff --git a/optee/optee_os/core/drivers/cbmem_console.c b/optee/optee_os/core/drivers/cbmem_console.c new file mode 100644 index 0000000..2e526c6 --- /dev/null +++ b/optee/optee_os/core/drivers/cbmem_console.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Google Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CURSOR_MASK (BIT(28) - 1) +#define OVERFLOW BIT(31) + +struct cbmem_console { + uint32_t size; + uint32_t cursor; + uint8_t body[0]; +}; + +struct cbmem_console_data { + paddr_t base; + struct cbmem_console *console; + struct serial_chip chip; + uint32_t size; +}; + +/* + * Structures describing coreboot's in-memory descriptor tables. See + * https://github.com/coreboot/coreboot/blob/ea2a38be323173075db3b13729a4006ea1fef72d/src/commonlib/include/commonlib/coreboot_tables.h + * for canonical implementation. + */ + +struct cb_header { + uint8_t signature[4]; + uint32_t header_bytes; + uint32_t header_checksum; + uint32_t table_bytes; + uint32_t table_checksum; + uint32_t table_entries; +}; + +#define CB_TAG_CBMEM_CONSOLE 0x17 + +struct cb_entry { + uint32_t tag; + uint32_t size; + uint64_t value; +}; + +static struct cbmem_console_data cbmem_console; + +static void cbmem_console_flush(struct serial_chip *chip __unused) +{ +} + +static int cbmem_console_getchar(struct serial_chip *chip __unused) +{ + return 0; +} + +static bool cbmem_console_have_rx_data(struct serial_chip *chip __unused) +{ + return false; +} + +static void cbmem_console_putc(struct serial_chip *chip, int ch) +{ + struct cbmem_console_data *pd = + container_of(chip, struct cbmem_console_data, chip); + struct cbmem_console *c = pd->console; + + if (!pd->size) + return; + + if ((c->cursor & CURSOR_MASK) + 1 >= pd->size) { + c->cursor &= ~CURSOR_MASK; + c->cursor |= OVERFLOW; + c->body[0] = (uint8_t)(ch & 0xFF); + } else { + c->body[c->cursor & CURSOR_MASK] = (uint8_t)(ch & 0xFF); + c->cursor++; + } +} + +static const struct serial_ops cbmem_console_ops = { + .flush = cbmem_console_flush, + .getchar = cbmem_console_getchar, + .have_rx_data = cbmem_console_have_rx_data, + .putc = cbmem_console_putc, +}; +DECLARE_KEEP_PAGER(cbmem_console_ops); + +static paddr_t get_cbmem_console_from_coreboot_table(paddr_t table_addr, + size_t table_size) +{ + struct cb_header *header = NULL; + void *ptr = NULL; + uint32_t i = 0; + struct cb_entry *entry = NULL; + paddr_t cbmem_console_base = 0; + void *base = NULL; + + base = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, table_addr, table_size); + if (!base) + return 0; + + header = (struct cb_header *)base; + if (memcmp(header->signature, "LBIO", 4)) + goto done; + + if (header->header_bytes + header->table_bytes > table_size) + goto done; + + ptr = (uint8_t *)base + header->header_bytes; + for (i = 0; i < header->table_entries; ++i) { + entry = (struct cb_entry *)ptr; + if ((uint8_t *)ptr >= (uint8_t *)base + table_size - + sizeof(struct cb_entry)) { + goto done; + } + + switch (get_le32(&entry->tag)) { + case CB_TAG_CBMEM_CONSOLE: + cbmem_console_base = get_le64(&entry->value); + goto done; + default: + /* We skip all but one tag type. */ + break; + } + + ptr = (uint8_t *)ptr + get_le32(&entry->size); + } + +done: + core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, base, table_size); + return cbmem_console_base; +} + +bool cbmem_console_init_from_dt(void *fdt) +{ + int offset = 0; + paddr_t cb_addr = 0; + size_t cb_size = 0; + paddr_t cbmem_console_base = 0; + + if (!fdt) + return false; + + offset = fdt_path_offset(fdt, "/firmware/coreboot"); + if (offset < 0) + return false; + + cb_addr = fdt_reg_base_address(fdt, offset); + cb_size = fdt_reg_size(fdt, offset); + + cbmem_console_base = get_cbmem_console_from_coreboot_table(cb_addr, + cb_size); + if (!cbmem_console_base) + return false; + + cbmem_console.base = cbmem_console_base; + cbmem_console.console = (struct cbmem_console *) + core_mmu_add_mapping(MEM_AREA_RAM_NSEC, cbmem_console_base, + sizeof(struct cbmem_console)); + if (!cbmem_console.console) + return false; + + /* + * Copy the size now to prevent non-secure world from spoofing + * it later. + */ + cbmem_console.size = cbmem_console.console->size; + cbmem_console.chip.ops = &cbmem_console_ops; + + register_serial_console(&cbmem_console.chip); + return true; +} diff --git a/optee/optee_os/core/drivers/cdns_uart.c b/optee/optee_os/core/drivers/cdns_uart.c new file mode 100644 index 0000000..b348758 --- /dev/null +++ b/optee/optee_os/core/drivers/cdns_uart.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Xilinx 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 CDNS_UART_CONTROL 0 +#define CDNS_UART_MODE 4 +#define CDNS_UART_IEN 8 +#define CDNS_UART_IRQ_STATUS 0x14 +#define CDNS_UART_CHANNEL_STATUS 0x2c +#define CDNS_UART_FIFO 0x30 +#define CDNS_UART_SIZE 0x34 + +#define CDNS_UART_CONTROL_RXRES BIT(0) +#define CDNS_UART_CONTROL_TXRES BIT(1) +#define CDNS_UART_CONTROL_RXEN BIT(2) +#define CDNS_UART_CONTROL_TXEN BIT(4) + +#define CDNS_UART_MODE_8BIT (0 << 1) +#define CDNS_UART_MODE_PARITY_NONE (0x4 << 3) +#define CDNS_UART_MODE_1STP (0 << 6) + +#define CDNS_UART_CHANNEL_STATUS_TFUL BIT(4) +#define CDNS_UART_CHANNEL_STATUS_TEMPTY BIT(3) +#define CDNS_UART_CHANNEL_STATUS_REMPTY BIT(1) + +#define CDNS_UART_IRQ_RXTRIG BIT(0) +#define CDNS_UART_IRQ_RXTOUT BIT(8) + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct cdns_uart_data *pd = + container_of(chip, struct cdns_uart_data, chip); + + return io_pa_or_va(&pd->base, CDNS_UART_SIZE); +} + +static void cdns_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read32(base + CDNS_UART_CHANNEL_STATUS) & + CDNS_UART_CHANNEL_STATUS_TEMPTY)) + ; +} + +static bool cdns_uart_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + return !(io_read32(base + CDNS_UART_CHANNEL_STATUS) & + CDNS_UART_CHANNEL_STATUS_REMPTY); +} + +static int cdns_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!cdns_uart_have_rx_data(chip)) + ; + return io_read32(base + CDNS_UART_FIFO) & 0xff; +} + +static void cdns_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + /* Wait until there is space in the FIFO */ + while (io_read32(base + CDNS_UART_CHANNEL_STATUS) & + CDNS_UART_CHANNEL_STATUS_TFUL) + ; + + /* Send the character */ + io_write32(base + CDNS_UART_FIFO, ch); +} + + +static const struct serial_ops cdns_uart_ops = { + .flush = cdns_uart_flush, + .getchar = cdns_uart_getchar, + .have_rx_data = cdns_uart_have_rx_data, + .putc = cdns_uart_putc, +}; +DECLARE_KEEP_PAGER(cdns_uart_ops); + +/* + * we rely on the bootloader having set up the HW correctly, we just enable + * transmitter/receiver here, just in case. + */ +void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk, + uint32_t baud_rate) +{ + pd->base.pa = base; + pd->chip.ops = &cdns_uart_ops; + + if (!uart_clk || !baud_rate) + return; + + /* Enable UART and RX/TX */ + io_write32(base + CDNS_UART_CONTROL, + CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN); + + cdns_uart_flush(&pd->chip); +} diff --git a/optee/optee_os/core/drivers/clk/clk-stm32-core.c b/optee/optee_os/core/drivers/clk/clk-stm32-core.c new file mode 100644 index 0000000..f4c903e --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk-stm32-core.c @@ -0,0 +1,605 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-stm32-core.h" + +#define RCC_MP_ENCLRR_OFFSET 0x4 + +#define TIMEOUT_US_200MS U(200000) +#define TIMEOUT_US_1S U(1000000) + +static struct clk_stm32_priv *stm32_clock_data; + +struct clk_stm32_priv *clk_stm32_get_priv(void) +{ + return stm32_clock_data; +} + +uintptr_t clk_stm32_get_rcc_base(void) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + + return priv->base; +} + +/* STM32 MUX API */ +size_t stm32_mux_get_parent(uint32_t mux_id) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct mux_cfg *mux = &priv->muxes[mux_id]; + uint32_t mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); + + return (io_read32(priv->base + mux->offset) & mask) >> mux->shift; +} + +TEE_Result stm32_mux_set_parent(uint16_t mux_id, uint8_t sel) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct mux_cfg *mux = &priv->muxes[mux_id]; + uint32_t mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); + uintptr_t address = priv->base + mux->offset; + + io_clrsetbits32(address, mask, (sel << mux->shift) & mask); + + if (mux->ready != MUX_NO_RDY) + return stm32_gate_wait_ready((uint16_t)mux->ready, true); + + return TEE_SUCCESS; +} + +/* STM32 GATE API */ +static void stm32_gate_endisable(uint16_t gate_id, bool enable) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t addr = priv->base + gate->offset; + + if (enable) { + if (gate->set_clr) + io_write32(addr, BIT(gate->bit_idx)); + else + io_setbits32_stm32shregs(addr, BIT(gate->bit_idx)); + } else { + if (gate->set_clr) + io_write32(addr + RCC_MP_ENCLRR_OFFSET, + BIT(gate->bit_idx)); + else + io_clrbits32_stm32shregs(addr, BIT(gate->bit_idx)); + } +} + +void stm32_gate_disable(uint16_t gate_id) +{ + stm32_gate_endisable(gate_id, false); +} + +void stm32_gate_enable(uint16_t gate_id) +{ + stm32_gate_endisable(gate_id, true); +} + +bool stm32_gate_is_enabled(uint16_t gate_id) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t addr = priv->base + gate->offset; + + return (io_read32(addr) & BIT(gate->bit_idx)) != 0U; +} + +TEE_Result stm32_gate_wait_ready(uint16_t gate_id, bool ready_on) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t address = priv->base + gate->offset; + uint32_t mask_rdy = BIT(gate->bit_idx); + uint64_t timeout = timeout_init_us(TIMEOUT_US_1S); + uint32_t mask = 0U; + + if (ready_on) + mask = BIT(gate->bit_idx); + + while ((io_read32(address) & mask_rdy) != mask) + if (timeout_elapsed(timeout)) + break; + + if ((io_read32(address) & mask_rdy) != mask) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +/* STM32 GATE READY clock operators */ +static TEE_Result stm32_gate_ready_endisable(uint16_t gate_id, bool enable, + bool wait_rdy) +{ + stm32_gate_endisable(gate_id, enable); + + if (wait_rdy) + return stm32_gate_wait_ready(gate_id + 1, enable); + + return TEE_SUCCESS; +} + +TEE_Result stm32_gate_rdy_enable(uint16_t gate_id) +{ + return stm32_gate_ready_endisable(gate_id, true, true); +} + +TEE_Result stm32_gate_rdy_disable(uint16_t gate_id) +{ + return stm32_gate_ready_endisable(gate_id, false, true); +} + +/* STM32 DIV API */ +static unsigned int _get_table_div(const struct div_table_cfg *table, + unsigned int val) +{ + const struct div_table_cfg *clkt = NULL; + + for (clkt = table; clkt->div; clkt++) + if (clkt->val == val) + return clkt->div; + + return 0; +} + +static unsigned int _get_table_val(const struct div_table_cfg *table, + unsigned int div) +{ + const struct div_table_cfg *clkt = NULL; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div == div) + return clkt->val; + + return 0; +} + +static unsigned int _get_div(const struct div_table_cfg *table, + unsigned int val, unsigned long flags, + uint8_t width) +{ + if (flags & CLK_DIVIDER_ONE_BASED) + return val; + + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return BIT(val); + + if (flags & CLK_DIVIDER_MAX_AT_ZERO) + return (val != 0U) ? val : BIT(width); + + if (table) + return _get_table_div(table, val); + + return val + 1U; +} + +static unsigned int _get_val(const struct div_table_cfg *table, + unsigned int div, unsigned long flags, + uint8_t width) +{ + if (flags & CLK_DIVIDER_ONE_BASED) + return div; + + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return __builtin_ffs(div) - 1; + + if (flags & CLK_DIVIDER_MAX_AT_ZERO) + return (div != 0U) ? div : BIT(width); + + if (table) + return _get_table_val(table, div); + + return div - 1U; +} + +static bool _is_valid_table_div(const struct div_table_cfg *table, + unsigned int div) +{ + const struct div_table_cfg *clkt = NULL; + + for (clkt = table; clkt->div; clkt++) + if (clkt->div == div) + return true; + + return false; +} + +static bool _is_valid_div(const struct div_table_cfg *table, + unsigned int div, unsigned long flags) +{ + if (flags & CLK_DIVIDER_POWER_OF_TWO) + return IS_POWER_OF_TWO(div); + + if (table) + return _is_valid_table_div(table, div); + + return true; +} + +static int divider_get_val(unsigned long rate, unsigned long parent_rate, + const struct div_table_cfg *table, uint8_t width, + unsigned long flags) +{ + unsigned int div = 0U; + unsigned int value = 0U; + + div = UDIV_ROUND_NEAREST((uint64_t)parent_rate, rate); + + if (!_is_valid_div(table, div, flags)) + return -1; + + value = _get_val(table, div, flags, width); + + return MIN(value, MASK_WIDTH_SHIFT(width, 0)); +} + +uint32_t stm32_div_get_value(int div_id) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct div_cfg *divider = &priv->div[div_id]; + uint32_t val = 0; + + val = io_read32(priv->base + divider->offset) >> divider->shift; + val &= MASK_WIDTH_SHIFT(divider->width, 0); + + return val; +} + +TEE_Result stm32_div_set_value(uint32_t div_id, uint32_t value) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct div_cfg *divider = NULL; + uintptr_t address = 0; + uint32_t mask = 0; + + if (div_id >= priv->nb_div) + panic(); + + divider = &priv->div[div_id]; + address = priv->base + divider->offset; + + mask = MASK_WIDTH_SHIFT(divider->width, divider->shift); + io_clrsetbits32(address, mask, (value << divider->shift) & mask); + + if (divider->ready == DIV_NO_RDY) + return TEE_SUCCESS; + + return stm32_gate_wait_ready((uint16_t)divider->ready, true); +} + +static unsigned long stm32_div_get_rate(int div_id, unsigned long prate) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct div_cfg *divider = &priv->div[div_id]; + uint32_t val = stm32_div_get_value(div_id); + unsigned int div = 0U; + + div = _get_div(divider->table, val, divider->flags, divider->width); + if (!div) + return prate; + + return ROUNDUP_DIV((uint64_t)prate, div); +} + +TEE_Result stm32_div_set_rate(int div_id, unsigned long rate, + unsigned long prate) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + const struct div_cfg *divider = &priv->div[div_id]; + int value = 0; + + value = divider_get_val(rate, prate, divider->table, + divider->width, divider->flags); + + if (value < 0) + return TEE_ERROR_GENERIC; + + return stm32_div_set_value(div_id, value); +} + +/* STM32 MUX clock operators */ +static size_t clk_stm32_mux_get_parent(struct clk *clk) +{ + struct clk_stm32_mux_cfg *cfg = clk->priv; + + return stm32_mux_get_parent(cfg->mux_id); +} + +static TEE_Result clk_stm32_mux_set_parent(struct clk *clk, size_t pidx) +{ + struct clk_stm32_mux_cfg *cfg = clk->priv; + + return stm32_mux_set_parent(cfg->mux_id, pidx); +} + +const struct clk_ops clk_stm32_mux_ops = { + .get_parent = clk_stm32_mux_get_parent, + .set_parent = clk_stm32_mux_set_parent, +}; + +/* STM32 GATE clock operators */ +static TEE_Result clk_stm32_gate_enable(struct clk *clk) +{ + struct clk_stm32_gate_cfg *cfg = clk->priv; + + stm32_gate_enable(cfg->gate_id); + + return TEE_SUCCESS; +} + +static void clk_stm32_gate_disable(struct clk *clk) +{ + struct clk_stm32_gate_cfg *cfg = clk->priv; + + stm32_gate_disable(cfg->gate_id); +} + +const struct clk_ops clk_stm32_gate_ops = { + .enable = clk_stm32_gate_enable, + .disable = clk_stm32_gate_disable, +}; + +static TEE_Result clk_stm32_gate_ready_enable(struct clk *clk) +{ + struct clk_stm32_gate_cfg *cfg = clk->priv; + + return stm32_gate_rdy_enable(cfg->gate_id); +} + +static void clk_stm32_gate_ready_disable(struct clk *clk) +{ + struct clk_stm32_gate_cfg *cfg = clk->priv; + + if (stm32_gate_rdy_disable(cfg->gate_id)) + panic(); +} + +const struct clk_ops clk_stm32_gate_ready_ops = { + .enable = clk_stm32_gate_ready_enable, + .disable = clk_stm32_gate_ready_disable, +}; + +/* STM32 DIV clock operators */ +unsigned long clk_stm32_divider_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_stm32_div_cfg *cfg = clk->priv; + + return stm32_div_get_rate(cfg->div_id, parent_rate); +} + +TEE_Result clk_stm32_divider_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate) +{ + struct clk_stm32_div_cfg *cfg = clk->priv; + + return stm32_div_set_rate(cfg->div_id, rate, parent_rate); +} + +const struct clk_ops clk_stm32_divider_ops = { + .get_rate = clk_stm32_divider_get_rate, + .set_rate = clk_stm32_divider_set_rate, +}; + +/* STM32 COMPOSITE clock operators */ +size_t clk_stm32_composite_get_parent(struct clk *clk) +{ + struct clk_stm32_composite_cfg *cfg = clk->priv; + + if (cfg->mux_id == NO_MUX) { + /* It could be a normal case */ + return 0; + } + + return stm32_mux_get_parent(cfg->mux_id); +} + +TEE_Result clk_stm32_composite_set_parent(struct clk *clk, size_t pidx) +{ + struct clk_stm32_composite_cfg *cfg = clk->priv; + + if (cfg->mux_id == NO_MUX) + panic(); + + return stm32_mux_set_parent(cfg->mux_id, pidx); +} + +unsigned long clk_stm32_composite_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_stm32_composite_cfg *cfg = clk->priv; + + if (cfg->div_id == NO_DIV) + return parent_rate; + + return stm32_div_get_rate(cfg->div_id, parent_rate); +} + +TEE_Result clk_stm32_composite_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_stm32_composite_cfg *cfg = clk->priv; + + if (cfg->div_id == NO_DIV) + return TEE_SUCCESS; + + return stm32_div_set_rate(cfg->div_id, rate, parent_rate); +} + +TEE_Result clk_stm32_composite_gate_enable(struct clk *clk) +{ + struct clk_stm32_composite_cfg *cfg = clk->priv; + + stm32_gate_enable(cfg->gate_id); + + return TEE_SUCCESS; +} + +void clk_stm32_composite_gate_disable(struct clk *clk) +{ + struct clk_stm32_composite_cfg *cfg = clk->priv; + + stm32_gate_disable(cfg->gate_id); +} + +const struct clk_ops clk_stm32_composite_ops = { + .get_parent = clk_stm32_composite_get_parent, + .set_parent = clk_stm32_composite_set_parent, + .get_rate = clk_stm32_composite_get_rate, + .set_rate = clk_stm32_composite_set_rate, + .enable = clk_stm32_composite_gate_enable, + .disable = clk_stm32_composite_gate_disable, +}; + +TEE_Result clk_stm32_set_parent_by_index(struct clk *clk, size_t pidx) +{ + struct clk *parent = clk_get_parent_by_index(clk, pidx); + TEE_Result res = TEE_ERROR_GENERIC; + + if (parent) + res = clk_set_parent(clk, parent); + + return res; +} + +int clk_stm32_parse_fdt_by_name(const void *fdt, int node, const char *name, + uint32_t *tab, uint32_t *nb) +{ + const fdt32_t *cell = NULL; + int len = 0; + uint32_t i = 0; + + cell = fdt_getprop(fdt, node, name, &len); + if (cell) + for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) + tab[i] = fdt32_to_cpu(cell[i]); + + *nb = (uint32_t)len / sizeof(uint32_t); + + return 0; +} + +TEE_Result clk_stm32_init(struct clk_stm32_priv *priv, uintptr_t base) +{ + stm32_clock_data = priv; + + priv->base = base; + + return TEE_SUCCESS; +} + +static unsigned long fixed_factor_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct fixed_factor_cfg *d = clk->priv; + + unsigned long long rate = (unsigned long long)parent_rate * d->mult; + + if (d->div == 0U) + panic("error division by zero"); + + return (unsigned long)(rate / d->div); +}; + +const struct clk_ops clk_fixed_factor_ops = { + .get_rate = fixed_factor_get_rate, +}; + +static unsigned long clk_fixed_get_rate(struct clk *clk, + unsigned long parent_rate __unused) +{ + struct clk_fixed_rate_cfg *cfg = clk->priv; + + return cfg->rate; +} + +const struct clk_ops clk_fixed_clk_ops = { + .get_rate = clk_fixed_get_rate, +}; + +struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + + if (clock_id > priv->nb_clk_refs) + return NULL; + + return priv->clk_refs[clock_id]; +} + +static struct clk *stm32mp_clk_dt_get_clk(struct dt_driver_phandle_args *pargs, + void *data __unused, TEE_Result *res) +{ + unsigned long clock_id = pargs->args[0]; + struct clk *clk = NULL; + + *res = TEE_ERROR_BAD_PARAMETERS; + + if (pargs->args_count != 1) + return NULL; + + clk = stm32mp_rcc_clock_id_to_clk(clock_id); + if (!clk) + return NULL; + + *res = TEE_SUCCESS; + return clk; +} + +static void clk_stm32_register_clocks(struct clk_stm32_priv *priv) +{ + unsigned int i = 0; + + for (i = 0; i < priv->nb_clk_refs; i++) { + struct clk *clk = priv->clk_refs[i]; + + if (!clk) + continue; + + refcount_set(&clk->enabled_count, 0); + + if (clk_register(clk)) + panic(); + } + + /* Critical clocks management */ + for (i = 0; i < priv->nb_clk_refs; i++) { + struct clk *clk = priv->clk_refs[i]; + + if (!clk) + continue; + + if (priv->is_critical && priv->is_critical(clk)) + clk_enable(clk); + } +} + +void stm32mp_clk_provider_probe_final(const void *fdt, int node, + struct clk_stm32_priv *priv) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + clk_stm32_register_clocks(priv); + + res = clk_dt_register_clk_provider(fdt, node, stm32mp_clk_dt_get_clk, + priv); + if (res) + panic("Couldn't register clock provider"); +} diff --git a/optee/optee_os/core/drivers/clk/clk-stm32-core.h b/optee/optee_os/core/drivers/clk/clk-stm32-core.h new file mode 100644 index 0000000..c540d6c --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk-stm32-core.h @@ -0,0 +1,257 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + */ + +#ifndef CLK_STM32_CORE_H +#define CLK_STM32_CORE_H + +#include + +struct mux_cfg { + uint16_t offset; + uint8_t shift; + uint8_t width; + uint8_t ready; +}; + +struct gate_cfg { + uint16_t offset; + uint8_t bit_idx; + uint8_t set_clr; +}; + +struct div_table_cfg { + unsigned int val; + unsigned int div; +}; + +struct div_cfg { + uint16_t offset; + uint8_t shift; + uint8_t width; + uint8_t flags; + uint8_t ready; + const struct div_table_cfg *table; +}; + +struct clk_stm32_priv { + uintptr_t base; + size_t nb_clk_refs; + struct clk **clk_refs; + const struct mux_cfg *muxes; + const uint32_t nb_muxes; + const struct gate_cfg *gates; + const uint32_t nb_gates; + const struct div_cfg *div; + const uint32_t nb_div; + bool (*is_critical)(struct clk *clk); + void *pdata; +}; + +struct clk_fixed_rate_cfg { + unsigned long rate; +}; + +struct fixed_factor_cfg { + unsigned int mult; + unsigned int div; +}; + +struct clk_gate_cfg { + uint32_t offset; + uint8_t bit_idx; +}; + +struct clk_stm32_mux_cfg { + int mux_id; +}; + +struct clk_stm32_gate_cfg { + int gate_id; +}; + +struct clk_stm32_div_cfg { + int div_id; +}; + +struct clk_stm32_composite_cfg { + int gate_id; + int div_id; + int mux_id; +}; + +struct clk_stm32_timer_cfg { + uint32_t apbdiv; + uint32_t timpre; +}; + +struct clk_stm32_gate_ready_cfg { + int gate_id; + int gate_rdy_id; +}; + +/* Define for divider clocks */ +#define CLK_DIVIDER_ONE_BASED BIT(0) +#define CLK_DIVIDER_POWER_OF_TWO BIT(1) +#define CLK_DIVIDER_ALLOW_ZERO BIT(2) +#define CLK_DIVIDER_HIWORD_MASK BIT(3) +#define CLK_DIVIDER_ROUND_CLOSEST BIT(4) +#define CLK_DIVIDER_READ_ONLY BIT(5) +#define CLK_DIVIDER_MAX_AT_ZERO BIT(6) +#define CLK_DIVIDER_BIG_ENDIAN BIT(7) + +#define DIV_NO_RDY UINT8_MAX +#define MUX_NO_RDY UINT8_MAX + +#define MASK_WIDTH_SHIFT(_width, _shift) \ + GENMASK_32(((_width) + (_shift) - 1U), (_shift)) + +/* Define for composite clocks */ +#define NO_MUX INT32_MAX +#define NO_DIV INT32_MAX +#define NO_GATE INT32_MAX + +void stm32_gate_enable(uint16_t gate_id); +void stm32_gate_disable(uint16_t gate_id); +bool stm32_gate_is_enabled(uint16_t gate_id); +TEE_Result stm32_gate_wait_ready(uint16_t gate_id, bool ready_on); +TEE_Result stm32_gate_rdy_enable(uint16_t gate_id); +TEE_Result stm32_gate_rdy_disable(uint16_t gate_id); + +size_t stm32_mux_get_parent(uint32_t mux_id); +TEE_Result stm32_mux_set_parent(uint16_t pid, uint8_t sel); + +TEE_Result stm32_div_set_rate(int div_id, unsigned long rate, + unsigned long prate); + +uint32_t stm32_div_get_value(int div_id); +TEE_Result stm32_div_set_value(uint32_t div_id, uint32_t value); + +int clk_stm32_parse_fdt_by_name(const void *fdt, int node, const char *name, + uint32_t *tab, uint32_t *nb); + +unsigned long clk_stm32_divider_get_rate(struct clk *clk, + unsigned long parent_rate); + +TEE_Result clk_stm32_divider_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate); + +size_t clk_stm32_composite_get_parent(struct clk *clk); +TEE_Result clk_stm32_composite_set_parent(struct clk *clk, size_t pidx); +unsigned long clk_stm32_composite_get_rate(struct clk *clk, + unsigned long parent_rate); +TEE_Result clk_stm32_composite_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate); +TEE_Result clk_stm32_composite_gate_enable(struct clk *clk); +void clk_stm32_composite_gate_disable(struct clk *clk); + +TEE_Result clk_stm32_set_parent_by_index(struct clk *clk, size_t pidx); + +extern const struct clk_ops clk_fixed_factor_ops; +extern const struct clk_ops clk_fixed_clk_ops; +extern const struct clk_ops clk_stm32_gate_ops; +extern const struct clk_ops clk_stm32_gate_ready_ops; +extern const struct clk_ops clk_stm32_divider_ops; +extern const struct clk_ops clk_stm32_mux_ops; +extern const struct clk_ops clk_stm32_composite_ops; + +#define PARENT(x...) { x } + +#define STM32_FIXED_RATE(_name, _rate)\ + struct clk _name = {\ + .ops = &clk_fixed_clk_ops,\ + .priv = &(struct clk_fixed_rate_cfg) {\ + .rate = (_rate),\ + },\ + .name = #_name,\ + .flags = 0,\ + .num_parents = 0,\ + } + +#define STM32_FIXED_FACTOR(_name, _parent, _flags, _mult, _div)\ + struct clk _name = {\ + .ops = &clk_fixed_factor_ops,\ + .priv = &(struct fixed_factor_cfg) {\ + .mult = _mult,\ + .div = _div,\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = 1,\ + .parents = { (_parent) },\ + } + +#define STM32_GATE(_name, _parent, _flags, _gate_id)\ + struct clk _name = {\ + .ops = &clk_stm32_gate_ops,\ + .priv = &(struct clk_stm32_gate_cfg) {\ + .gate_id = _gate_id,\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = 1,\ + .parents = { (_parent) },\ + } + +#define STM32_DIVIDER(_name, _parent, _flags, _div_id)\ + struct clk _name = {\ + .ops = &clk_stm32_divider_ops,\ + .priv = &(struct clk_stm32_div_cfg) {\ + .div_id = (_div_id),\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = 1,\ + .parents = { (_parent) },\ + } + +#define STM32_MUX(_name, _nb_parents, _parents, _flags, _mux_id)\ + struct clk _name = {\ + .ops = &clk_stm32_mux_ops,\ + .priv = &(struct clk_stm32_mux_cfg) {\ + .mux_id = (_mux_id),\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = (_nb_parents),\ + .parents = _parents,\ + } + +#define STM32_GATE_READY(_name, _parent, _flags, _gate_id)\ + struct clk _name = {\ + .ops = &clk_stm32_gate_ready_ops,\ + .priv = &(struct clk_stm32_gate_cfg) {\ + .gate_id = _gate_id,\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = 1,\ + .parents = { _parent },\ + } + +#define STM32_COMPOSITE(_name, _nb_parents, _parents, _flags,\ + _gate_id, _div_id, _mux_id)\ + struct clk _name = {\ + .ops = &clk_stm32_composite_ops,\ + .priv = &(struct clk_stm32_composite_cfg) {\ + .gate_id = (_gate_id),\ + .div_id = (_div_id),\ + .mux_id = (_mux_id),\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = (_nb_parents),\ + .parents = _parents,\ + } + +struct clk_stm32_priv *clk_stm32_get_priv(void); +uintptr_t clk_stm32_get_rcc_base(void); + +TEE_Result clk_stm32_init(struct clk_stm32_priv *priv, uintptr_t base); + +void stm32mp_clk_provider_probe_final(const void *fdt, int node, + struct clk_stm32_priv *priv); + +#endif /* CLK_STM32_CORE_H */ diff --git a/optee/optee_os/core/drivers/clk/clk-stm32mp13.c b/optee/optee_os/core/drivers/clk/clk-stm32mp13.c new file mode 100644 index 0000000..0a3d6c7 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk-stm32mp13.c @@ -0,0 +1,2663 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk-stm32-core.h" + +#define MAX_HSI_HZ 64000000 +#define USB_PHY_48_MHZ 48000000 + +#define TIMEOUT_US_200MS U(200000) +#define HSIDIV_TIMEOUT TIMEOUT_US_200MS + +#define MAX_OPP CFG_STM32MP_OPP_COUNT + +#define RCC_PLL_NAME_SIZE 12 + +struct stm32_osci_dt_cfg { + unsigned long freq; + bool bypass; + bool digbyp; + bool css; + uint32_t drive; +}; + +enum pll_mn { + PLL_CFG_M, + PLL_CFG_N, + PLL_DIV_MN_NB +}; + +enum pll_pqr { + PLL_CFG_P, + PLL_CFG_Q, + PLL_CFG_R, + PLL_DIV_PQR_NB +}; + +enum pll_csg { + PLL_CSG_MOD_PER, + PLL_CSG_INC_STEP, + PLL_CSG_SSCG_MODE, + PLL_CSG_NB +}; + +struct stm32_pll_vco { + uint32_t status; + uint32_t src; + uint32_t div_mn[PLL_DIV_MN_NB]; + uint32_t frac; + bool csg_enabled; + uint32_t csg[PLL_CSG_NB]; +}; + +struct stm32_pll_output { + uint32_t output[PLL_DIV_PQR_NB]; +}; + +struct stm32_pll_dt_cfg { + struct stm32_pll_vco vco; + struct stm32_pll_output output; +}; + +struct stm32_clk_opp_cfg { + uint32_t frq; + uint32_t src; + uint32_t div; + struct stm32_pll_dt_cfg pll_cfg; +}; + +struct stm32_clk_opp_dt_cfg { + struct stm32_clk_opp_cfg mpu_opp[MAX_OPP]; + struct stm32_clk_opp_cfg axi_opp[MAX_OPP]; + struct stm32_clk_opp_cfg mlahbs_opp[MAX_OPP]; +}; + +struct stm32_clk_platdata { + uintptr_t rcc_base; + uint32_t nosci; + struct stm32_osci_dt_cfg *osci; + uint32_t npll; + struct stm32_pll_dt_cfg *pll; + struct stm32_clk_opp_dt_cfg *opp; + uint32_t nclksrc; + uint32_t *clksrc; + uint32_t nclkdiv; + uint32_t *clkdiv; +}; + +/* + * GATE CONFIG + */ + +/* Warning GATE_XXX_RDY must follow GATE_XXX */ +enum enum_gate_cfg { + GATE_LSE, + GATE_LSE_RDY, + GATE_LSI, + GATE_LSI_RDY, + GATE_HSI, + GATE_HSI_RDY, + GATE_CSI, + GATE_CSI_RDY, + GATE_HSE, + GATE_HSE_RDY, + GATE_PLL1, + GATE_PLL1_RDY, + GATE_PLL2, + GATE_PLL2_RDY, + GATE_PLL3, + GATE_PLL3_RDY, + GATE_PLL4, + GATE_PLL4_RDY, + GATE_HSIDIVRDY, + GATE_MPUSRCRDY, + GATE_AXISSRCRDY, + GATE_MCUSSRCRDY, + GATE_PLL12SRCRDY, + GATE_PLL3SRCRDY, + GATE_PLL4SRCRDY, + GATE_MPUDIVRDY, + GATE_AXIDIVRDY, + GATE_MLAHBDIVRDY, + GATE_APB1DIVRDY, + GATE_APB2DIVRDY, + GATE_APB3DIVRDY, + GATE_APB4DIVRDY, + GATE_APB5DIVRDY, + GATE_APB6DIVRDY, + GATE_RTCCK, + GATE_MCO1, + GATE_MCO2, + GATE_DBGCK, + GATE_TRACECK, + GATE_PLL1_DIVP, + GATE_PLL1_DIVQ, + GATE_PLL1_DIVR, + GATE_PLL2_DIVP, + GATE_PLL2_DIVQ, + GATE_PLL2_DIVR, + GATE_PLL3_DIVP, + GATE_PLL3_DIVQ, + GATE_PLL3_DIVR, + GATE_PLL4_DIVP, + GATE_PLL4_DIVQ, + GATE_PLL4_DIVR, + GATE_DDRC1, + GATE_DDRC1LP, + GATE_DDRPHYC, + GATE_DDRPHYCLP, + GATE_DDRCAPB, + GATE_DDRCAPBLP, + GATE_AXIDCG, + GATE_DDRPHYCAPB, + GATE_DDRPHYCAPBLP, + GATE_TIM2, + GATE_TIM3, + GATE_TIM4, + GATE_TIM5, + GATE_TIM6, + GATE_TIM7, + GATE_LPTIM1, + GATE_SPI2, + GATE_SPI3, + GATE_USART3, + GATE_UART4, + GATE_UART5, + GATE_UART7, + GATE_UART8, + GATE_I2C1, + GATE_I2C2, + GATE_SPDIF, + GATE_TIM1, + GATE_TIM8, + GATE_SPI1, + GATE_USART6, + GATE_SAI1, + GATE_SAI2, + GATE_DFSDM, + GATE_ADFSDM, + GATE_FDCAN, + GATE_LPTIM2, + GATE_LPTIM3, + GATE_LPTIM4, + GATE_LPTIM5, + GATE_VREF, + GATE_DTS, + GATE_PMBCTRL, + GATE_HDP, + GATE_SYSCFG, + GATE_DCMIPP, + GATE_DDRPERFM, + GATE_IWDG2APB, + GATE_USBPHY, + GATE_STGENRO, + GATE_LTDC, + GATE_RTCAPB, + GATE_TZC, + GATE_ETZPC, + GATE_IWDG1APB, + GATE_BSEC, + GATE_STGENC, + GATE_USART1, + GATE_USART2, + GATE_SPI4, + GATE_SPI5, + GATE_I2C3, + GATE_I2C4, + GATE_I2C5, + GATE_TIM12, + GATE_TIM13, + GATE_TIM14, + GATE_TIM15, + GATE_TIM16, + GATE_TIM17, + GATE_DMA1, + GATE_DMA2, + GATE_DMAMUX1, + GATE_DMA3, + GATE_DMAMUX2, + GATE_ADC1, + GATE_ADC2, + GATE_USBO, + GATE_TSC, + GATE_GPIOA, + GATE_GPIOB, + GATE_GPIOC, + GATE_GPIOD, + GATE_GPIOE, + GATE_GPIOF, + GATE_GPIOG, + GATE_GPIOH, + GATE_GPIOI, + GATE_PKA, + GATE_SAES, + GATE_CRYP1, + GATE_HASH1, + GATE_RNG1, + GATE_BKPSRAM, + GATE_AXIMC, + GATE_MCE, + GATE_ETH1CK, + GATE_ETH1TX, + GATE_ETH1RX, + GATE_ETH1MAC, + GATE_FMC, + GATE_QSPI, + GATE_SDMMC1, + GATE_SDMMC2, + GATE_CRC1, + GATE_USBH, + GATE_ETH2CK, + GATE_ETH2TX, + GATE_ETH2RX, + GATE_ETH2MAC, + GATE_MDMA, + GATE_NB +}; + +#define GATE_CFG(_id, _offset, _bit_idx, _offset_clr)\ + [(_id)] = {\ + .offset = (_offset),\ + .bit_idx = (_bit_idx),\ + .set_clr = (_offset_clr),\ + } + +static const struct gate_cfg gates_mp13[GATE_NB] = { + GATE_CFG(GATE_LSE, RCC_BDCR, 0, 0), + GATE_CFG(GATE_LSE_RDY, RCC_BDCR, 2, 0), + GATE_CFG(GATE_RTCCK, RCC_BDCR, 20, 0), + GATE_CFG(GATE_LSI, RCC_RDLSICR, 0, 0), + GATE_CFG(GATE_LSI_RDY, RCC_RDLSICR, 1, 0), + GATE_CFG(GATE_HSI, RCC_OCENSETR, 0, 1), + GATE_CFG(GATE_HSI_RDY, RCC_OCRDYR, 0, 0), + GATE_CFG(GATE_CSI, RCC_OCENSETR, 4, 1), + GATE_CFG(GATE_CSI_RDY, RCC_OCRDYR, 4, 0), + GATE_CFG(GATE_HSE, RCC_OCENSETR, 8, 1), + GATE_CFG(GATE_HSE_RDY, RCC_OCRDYR, 8, 0), + GATE_CFG(GATE_HSIDIVRDY, RCC_OCRDYR, 2, 0), + GATE_CFG(GATE_MPUSRCRDY, RCC_MPCKSELR, 31, 0), + GATE_CFG(GATE_AXISSRCRDY, RCC_ASSCKSELR, 31, 0), + GATE_CFG(GATE_MCUSSRCRDY, RCC_MSSCKSELR, 31, 0), + GATE_CFG(GATE_PLL12SRCRDY, RCC_RCK12SELR, 31, 0), + GATE_CFG(GATE_PLL3SRCRDY, RCC_RCK3SELR, 31, 0), + GATE_CFG(GATE_PLL4SRCRDY, RCC_RCK4SELR, 31, 0), + GATE_CFG(GATE_MPUDIVRDY, RCC_MPCKDIVR, 31, 0), + GATE_CFG(GATE_AXIDIVRDY, RCC_AXIDIVR, 31, 0), + GATE_CFG(GATE_MLAHBDIVRDY, RCC_MLAHBDIVR, 31, 0), + GATE_CFG(GATE_APB1DIVRDY, RCC_APB1DIVR, 31, 0), + GATE_CFG(GATE_APB2DIVRDY, RCC_APB2DIVR, 31, 0), + GATE_CFG(GATE_APB3DIVRDY, RCC_APB3DIVR, 31, 0), + GATE_CFG(GATE_APB4DIVRDY, RCC_APB4DIVR, 31, 0), + GATE_CFG(GATE_APB5DIVRDY, RCC_APB5DIVR, 31, 0), + GATE_CFG(GATE_APB6DIVRDY, RCC_APB6DIVR, 31, 0), + GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 12, 0), + GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 12, 0), + GATE_CFG(GATE_DBGCK, RCC_DBGCFGR, 8, 0), + GATE_CFG(GATE_TRACECK, RCC_DBGCFGR, 9, 0), + GATE_CFG(GATE_PLL1, RCC_PLL1CR, 0, 0), + GATE_CFG(GATE_PLL1_RDY, RCC_PLL1CR, 1, 0), + GATE_CFG(GATE_PLL1_DIVP, RCC_PLL1CR, 4, 0), + GATE_CFG(GATE_PLL1_DIVQ, RCC_PLL1CR, 5, 0), + GATE_CFG(GATE_PLL1_DIVR, RCC_PLL1CR, 6, 0), + GATE_CFG(GATE_PLL2, RCC_PLL2CR, 0, 0), + GATE_CFG(GATE_PLL2_RDY, RCC_PLL2CR, 1, 0), + GATE_CFG(GATE_PLL2_DIVP, RCC_PLL2CR, 4, 0), + GATE_CFG(GATE_PLL2_DIVQ, RCC_PLL2CR, 5, 0), + GATE_CFG(GATE_PLL2_DIVR, RCC_PLL2CR, 6, 0), + GATE_CFG(GATE_PLL3, RCC_PLL3CR, 0, 0), + GATE_CFG(GATE_PLL3_RDY, RCC_PLL3CR, 1, 0), + GATE_CFG(GATE_PLL3_DIVP, RCC_PLL3CR, 4, 0), + GATE_CFG(GATE_PLL3_DIVQ, RCC_PLL3CR, 5, 0), + GATE_CFG(GATE_PLL3_DIVR, RCC_PLL3CR, 6, 0), + GATE_CFG(GATE_PLL4, RCC_PLL4CR, 0, 0), + GATE_CFG(GATE_PLL4_RDY, RCC_PLL4CR, 1, 0), + GATE_CFG(GATE_PLL4_DIVP, RCC_PLL4CR, 4, 0), + GATE_CFG(GATE_PLL4_DIVQ, RCC_PLL4CR, 5, 0), + GATE_CFG(GATE_PLL4_DIVR, RCC_PLL4CR, 6, 0), + GATE_CFG(GATE_DDRC1, RCC_DDRITFCR, 0, 0), + GATE_CFG(GATE_DDRC1LP, RCC_DDRITFCR, 1, 0), + GATE_CFG(GATE_DDRPHYC, RCC_DDRITFCR, 4, 0), + GATE_CFG(GATE_DDRPHYCLP, RCC_DDRITFCR, 5, 0), + GATE_CFG(GATE_DDRCAPB, RCC_DDRITFCR, 6, 0), + GATE_CFG(GATE_DDRCAPBLP, RCC_DDRITFCR, 7, 0), + GATE_CFG(GATE_AXIDCG, RCC_DDRITFCR, 8, 0), + GATE_CFG(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9, 0), + GATE_CFG(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10, 0), + GATE_CFG(GATE_TIM2, RCC_MP_APB1ENSETR, 0, 1), + GATE_CFG(GATE_TIM3, RCC_MP_APB1ENSETR, 1, 1), + GATE_CFG(GATE_TIM4, RCC_MP_APB1ENSETR, 2, 1), + GATE_CFG(GATE_TIM5, RCC_MP_APB1ENSETR, 3, 1), + GATE_CFG(GATE_TIM6, RCC_MP_APB1ENSETR, 4, 1), + GATE_CFG(GATE_TIM7, RCC_MP_APB1ENSETR, 5, 1), + GATE_CFG(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9, 1), + GATE_CFG(GATE_SPI2, RCC_MP_APB1ENSETR, 11, 1), + GATE_CFG(GATE_SPI3, RCC_MP_APB1ENSETR, 12, 1), + GATE_CFG(GATE_USART3, RCC_MP_APB1ENSETR, 15, 1), + GATE_CFG(GATE_UART4, RCC_MP_APB1ENSETR, 16, 1), + GATE_CFG(GATE_UART5, RCC_MP_APB1ENSETR, 17, 1), + GATE_CFG(GATE_UART7, RCC_MP_APB1ENSETR, 18, 1), + GATE_CFG(GATE_UART8, RCC_MP_APB1ENSETR, 19, 1), + GATE_CFG(GATE_I2C1, RCC_MP_APB1ENSETR, 21, 1), + GATE_CFG(GATE_I2C2, RCC_MP_APB1ENSETR, 22, 1), + GATE_CFG(GATE_SPDIF, RCC_MP_APB1ENSETR, 26, 1), + GATE_CFG(GATE_TIM1, RCC_MP_APB2ENSETR, 0, 1), + GATE_CFG(GATE_TIM8, RCC_MP_APB2ENSETR, 1, 1), + GATE_CFG(GATE_SPI1, RCC_MP_APB2ENSETR, 8, 1), + GATE_CFG(GATE_USART6, RCC_MP_APB2ENSETR, 13, 1), + GATE_CFG(GATE_SAI1, RCC_MP_APB2ENSETR, 16, 1), + GATE_CFG(GATE_SAI2, RCC_MP_APB2ENSETR, 17, 1), + GATE_CFG(GATE_DFSDM, RCC_MP_APB2ENSETR, 20, 1), + GATE_CFG(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21, 1), + GATE_CFG(GATE_FDCAN, RCC_MP_APB2ENSETR, 24, 1), + GATE_CFG(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0, 1), + GATE_CFG(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1, 1), + GATE_CFG(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2, 1), + GATE_CFG(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3, 1), + GATE_CFG(GATE_VREF, RCC_MP_APB3ENSETR, 13, 1), + GATE_CFG(GATE_DTS, RCC_MP_APB3ENSETR, 16, 1), + GATE_CFG(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17, 1), + GATE_CFG(GATE_HDP, RCC_MP_APB3ENSETR, 20, 1), + GATE_CFG(GATE_SYSCFG, RCC_MP_S_APB3ENSETR, 0, 1), + GATE_CFG(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1, 1), + GATE_CFG(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8, 1), + GATE_CFG(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15, 1), + GATE_CFG(GATE_USBPHY, RCC_MP_APB4ENSETR, 16, 1), + GATE_CFG(GATE_STGENRO, RCC_MP_APB4ENSETR, 20, 1), + GATE_CFG(GATE_LTDC, RCC_MP_S_APB4ENSETR, 0, 1), + GATE_CFG(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8, 1), + GATE_CFG(GATE_TZC, RCC_MP_APB5ENSETR, 11, 1), + GATE_CFG(GATE_ETZPC, RCC_MP_APB5ENSETR, 13, 1), + GATE_CFG(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15, 1), + GATE_CFG(GATE_BSEC, RCC_MP_APB5ENSETR, 16, 1), + GATE_CFG(GATE_STGENC, RCC_MP_APB5ENSETR, 20, 1), + GATE_CFG(GATE_USART1, RCC_MP_APB6ENSETR, 0, 1), + GATE_CFG(GATE_USART2, RCC_MP_APB6ENSETR, 1, 1), + GATE_CFG(GATE_SPI4, RCC_MP_APB6ENSETR, 2, 1), + GATE_CFG(GATE_SPI5, RCC_MP_APB6ENSETR, 3, 1), + GATE_CFG(GATE_I2C3, RCC_MP_APB6ENSETR, 4, 1), + GATE_CFG(GATE_I2C4, RCC_MP_APB6ENSETR, 5, 1), + GATE_CFG(GATE_I2C5, RCC_MP_APB6ENSETR, 6, 1), + GATE_CFG(GATE_TIM12, RCC_MP_APB6ENSETR, 7, 1), + GATE_CFG(GATE_TIM13, RCC_MP_APB6ENSETR, 8, 1), + GATE_CFG(GATE_TIM14, RCC_MP_APB6ENSETR, 9, 1), + GATE_CFG(GATE_TIM15, RCC_MP_APB6ENSETR, 10, 1), + GATE_CFG(GATE_TIM16, RCC_MP_APB6ENSETR, 11, 1), + GATE_CFG(GATE_TIM17, RCC_MP_APB6ENSETR, 12, 1), + GATE_CFG(GATE_DMA1, RCC_MP_AHB2ENSETR, 0, 1), + GATE_CFG(GATE_DMA2, RCC_MP_AHB2ENSETR, 1, 1), + GATE_CFG(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2, 1), + GATE_CFG(GATE_DMA3, RCC_MP_AHB2ENSETR, 3, 1), + GATE_CFG(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4, 1), + GATE_CFG(GATE_ADC1, RCC_MP_AHB2ENSETR, 5, 1), + GATE_CFG(GATE_ADC2, RCC_MP_AHB2ENSETR, 6, 1), + GATE_CFG(GATE_USBO, RCC_MP_AHB2ENSETR, 8, 1), + GATE_CFG(GATE_TSC, RCC_MP_AHB4ENSETR, 15, 1), + GATE_CFG(GATE_GPIOA, RCC_MP_S_AHB4ENSETR, 0, 1), + GATE_CFG(GATE_GPIOB, RCC_MP_S_AHB4ENSETR, 1, 1), + GATE_CFG(GATE_GPIOC, RCC_MP_S_AHB4ENSETR, 2, 1), + GATE_CFG(GATE_GPIOD, RCC_MP_S_AHB4ENSETR, 3, 1), + GATE_CFG(GATE_GPIOE, RCC_MP_S_AHB4ENSETR, 4, 1), + GATE_CFG(GATE_GPIOF, RCC_MP_S_AHB4ENSETR, 5, 1), + GATE_CFG(GATE_GPIOG, RCC_MP_S_AHB4ENSETR, 6, 1), + GATE_CFG(GATE_GPIOH, RCC_MP_S_AHB4ENSETR, 7, 1), + GATE_CFG(GATE_GPIOI, RCC_MP_S_AHB4ENSETR, 8, 1), + GATE_CFG(GATE_PKA, RCC_MP_AHB5ENSETR, 2, 1), + GATE_CFG(GATE_SAES, RCC_MP_AHB5ENSETR, 3, 1), + GATE_CFG(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4, 1), + GATE_CFG(GATE_HASH1, RCC_MP_AHB5ENSETR, 5, 1), + GATE_CFG(GATE_RNG1, RCC_MP_AHB5ENSETR, 6, 1), + GATE_CFG(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8, 1), + GATE_CFG(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16, 1), + GATE_CFG(GATE_MCE, RCC_MP_AHB6ENSETR, 1, 1), + GATE_CFG(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7, 1), + GATE_CFG(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8, 1), + GATE_CFG(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9, 1), + GATE_CFG(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10, 1), + GATE_CFG(GATE_FMC, RCC_MP_AHB6ENSETR, 12, 1), + GATE_CFG(GATE_QSPI, RCC_MP_AHB6ENSETR, 14, 1), + GATE_CFG(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16, 1), + GATE_CFG(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17, 1), + GATE_CFG(GATE_CRC1, RCC_MP_AHB6ENSETR, 20, 1), + GATE_CFG(GATE_USBH, RCC_MP_AHB6ENSETR, 24, 1), + GATE_CFG(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27, 1), + GATE_CFG(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28, 1), + GATE_CFG(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29, 1), + GATE_CFG(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30, 1), + GATE_CFG(GATE_MDMA, RCC_MP_S_AHB6ENSETR, 0, 1), +}; + +/* + * MUX CONFIG + */ +#define MUXRDY_CFG(_id, _offset, _shift, _witdh, _rdy)\ + [(_id)] = {\ + .offset = (_offset),\ + .shift = (_shift),\ + .width = (_witdh),\ + .ready = (_rdy),\ + } + +#define MUX_CFG(_id, _offset, _shift, _witdh)\ + MUXRDY_CFG(_id, _offset, _shift, _witdh, MUX_NO_RDY) + +static const struct mux_cfg parent_mp13[MUX_NB] = { + MUXRDY_CFG(MUX_MPU, RCC_MPCKSELR, 0, 2, GATE_MPUSRCRDY), + MUXRDY_CFG(MUX_AXI, RCC_ASSCKSELR, 0, 3, GATE_AXISSRCRDY), + MUXRDY_CFG(MUX_MLAHB, RCC_MSSCKSELR, 0, 2, GATE_MCUSSRCRDY), + MUXRDY_CFG(MUX_PLL12, RCC_RCK12SELR, 0, 2, GATE_PLL12SRCRDY), + MUXRDY_CFG(MUX_PLL3, RCC_RCK3SELR, 0, 2, GATE_PLL3SRCRDY), + MUXRDY_CFG(MUX_PLL4, RCC_RCK4SELR, 0, 2, GATE_PLL4SRCRDY), + MUX_CFG(MUX_ADC1, RCC_ADC12CKSELR, 0, 2), + MUX_CFG(MUX_ADC2, RCC_ADC12CKSELR, 2, 2), + MUX_CFG(MUX_CKPER, RCC_CPERCKSELR, 0, 2), + MUX_CFG(MUX_DCMIPP, RCC_DCMIPPCKSELR, 0, 2), + MUX_CFG(MUX_ETH1, RCC_ETH12CKSELR, 0, 2), + MUX_CFG(MUX_ETH2, RCC_ETH12CKSELR, 8, 2), + MUX_CFG(MUX_FDCAN, RCC_FDCANCKSELR, 0, 2), + MUX_CFG(MUX_FMC, RCC_FMCCKSELR, 0, 2), + MUX_CFG(MUX_I2C12, RCC_I2C12CKSELR, 0, 3), + MUX_CFG(MUX_I2C3, RCC_I2C345CKSELR, 0, 3), + MUX_CFG(MUX_I2C4, RCC_I2C345CKSELR, 3, 3), + MUX_CFG(MUX_I2C5, RCC_I2C345CKSELR, 6, 3), + MUX_CFG(MUX_LPTIM1, RCC_LPTIM1CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM2, RCC_LPTIM23CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM3, RCC_LPTIM23CKSELR, 3, 3), + MUX_CFG(MUX_LPTIM45, RCC_LPTIM45CKSELR, 0, 3), + MUX_CFG(MUX_MCO1, RCC_MCO1CFGR, 0, 3), + MUX_CFG(MUX_MCO2, RCC_MCO2CFGR, 0, 3), + MUX_CFG(MUX_QSPI, RCC_QSPICKSELR, 0, 2), + MUX_CFG(MUX_RNG1, RCC_RNG1CKSELR, 0, 2), + MUX_CFG(MUX_RTC, RCC_BDCR, 16, 2), + MUX_CFG(MUX_SAES, RCC_SAESCKSELR, 0, 2), + MUX_CFG(MUX_SAI1, RCC_SAI1CKSELR, 0, 3), + MUX_CFG(MUX_SAI2, RCC_SAI2CKSELR, 0, 3), + MUX_CFG(MUX_SDMMC1, RCC_SDMMC12CKSELR, 0, 3), + MUX_CFG(MUX_SDMMC2, RCC_SDMMC12CKSELR, 3, 3), + MUX_CFG(MUX_SPDIF, RCC_SPDIFCKSELR, 0, 2), + MUX_CFG(MUX_SPI1, RCC_SPI2S1CKSELR, 0, 3), + MUX_CFG(MUX_SPI23, RCC_SPI2S23CKSELR, 0, 3), + MUX_CFG(MUX_SPI4, RCC_SPI45CKSELR, 0, 3), + MUX_CFG(MUX_SPI5, RCC_SPI45CKSELR, 3, 3), + MUX_CFG(MUX_STGEN, RCC_STGENCKSELR, 0, 2), + MUX_CFG(MUX_UART1, RCC_UART12CKSELR, 0, 3), + MUX_CFG(MUX_UART2, RCC_UART12CKSELR, 3, 3), + MUX_CFG(MUX_UART35, RCC_UART35CKSELR, 0, 3), + MUX_CFG(MUX_UART4, RCC_UART4CKSELR, 0, 3), + MUX_CFG(MUX_UART6, RCC_UART6CKSELR, 0, 3), + MUX_CFG(MUX_UART78, RCC_UART78CKSELR, 0, 3), + MUX_CFG(MUX_USBO, RCC_USBCKSELR, 4, 1), + MUX_CFG(MUX_USBPHY, RCC_USBCKSELR, 0, 2), +}; + +/* + * DIV CONFIG + */ +static const struct div_table_cfg axi_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, + { 4, 4 }, { 5, 4 }, { 6, 4 }, { 7, 4 }, + { 0 }, +}; + +static const struct div_table_cfg mlahb_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 }, + { 8, 256 }, { 9, 512 }, { 10, 512}, { 11, 512 }, + { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 }, + { 0 }, +}; + +static const struct div_table_cfg apb_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, + { 0 }, +}; + +#define DIVRDY_CFG(_id, _offset, _shift, _width, _flags, _table, _ready)\ + [(_id)] = {\ + .offset = (_offset),\ + .shift = (_shift),\ + .width = (_width),\ + .flags = (_flags),\ + .table = (_table),\ + .ready = (_ready),\ + } + +#define DIV_CFG(_id, _offset, _shift, _width, _flags, _table)\ + DIVRDY_CFG(_id, _offset, _shift, _width, _flags, _table, DIV_NO_RDY) + +static const struct div_cfg dividers_mp13[] = { + DIVRDY_CFG(DIV_MPU, RCC_MPCKDIVR, 0, 4, 0, NULL, + GATE_MPUDIVRDY), + DIVRDY_CFG(DIV_AXI, RCC_AXIDIVR, 0, 3, 0, axi_div_table, + GATE_AXIDIVRDY), + DIVRDY_CFG(DIV_MLAHB, RCC_MLAHBDIVR, 0, 4, 0, mlahb_div_table, + GATE_MLAHBDIVRDY), + DIVRDY_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, + GATE_APB1DIVRDY), + DIVRDY_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, + GATE_APB2DIVRDY), + DIVRDY_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, + GATE_APB3DIVRDY), + DIVRDY_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, + GATE_APB4DIVRDY), + DIVRDY_CFG(DIV_APB5, RCC_APB5DIVR, 0, 3, 0, apb_div_table, + GATE_APB5DIVRDY), + DIVRDY_CFG(DIV_APB6, RCC_APB6DIVR, 0, 3, 0, apb_div_table, + GATE_APB6DIVRDY), + DIVRDY_CFG(DIV_HSI, RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL, + GATE_HSIDIVRDY), + DIV_CFG(DIV_PLL1DIVP, RCC_PLL1CFGR2, 0, 7, 0, NULL), + DIV_CFG(DIV_PLL2DIVP, RCC_PLL2CFGR2, 0, 7, 0, NULL), + DIV_CFG(DIV_PLL2DIVQ, RCC_PLL2CFGR2, 8, 7, 0, NULL), + DIV_CFG(DIV_PLL2DIVR, RCC_PLL2CFGR2, 16, 7, 0, NULL), + DIV_CFG(DIV_PLL3DIVP, RCC_PLL3CFGR2, 0, 7, 0, NULL), + DIV_CFG(DIV_PLL3DIVQ, RCC_PLL3CFGR2, 8, 7, 0, NULL), + DIV_CFG(DIV_PLL3DIVR, RCC_PLL3CFGR2, 16, 7, 0, NULL), + DIV_CFG(DIV_PLL4DIVP, RCC_PLL4CFGR2, 0, 7, 0, NULL), + DIV_CFG(DIV_PLL4DIVQ, RCC_PLL4CFGR2, 8, 7, 0, NULL), + DIV_CFG(DIV_PLL4DIVR, RCC_PLL4CFGR2, 16, 7, 0, NULL), + DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL), + DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL), + DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL), + DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, CLK_DIVIDER_POWER_OF_TWO, NULL), + DIV_CFG(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL), + DIV_CFG(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL), +}; + +enum stm32_osc { + OSC_HSI, + OSC_HSE, + OSC_CSI, + OSC_LSI, + OSC_LSE, + NB_OSCILLATOR +}; + +struct stm32_osc_cfg { + int osc_id; +}; + +struct clk_stm32_bypass { + uint16_t offset; + uint8_t bit_byp; + uint8_t bit_digbyp; +}; + +struct clk_stm32_css { + uint16_t offset; + uint8_t bit_css; +}; + +struct clk_stm32_drive { + uint16_t offset; + uint8_t drv_shift; + uint8_t drv_width; + uint8_t drv_default; +}; + +struct clk_oscillator_data { + const char *name; + unsigned long frequency; + uint16_t gate_id; + struct clk_stm32_bypass *bypass; + struct clk_stm32_css *css; + struct clk_stm32_drive *drive; +}; + +#define BYPASS(_offset, _bit_byp, _bit_digbyp) (&(struct clk_stm32_bypass){\ + .offset = (_offset),\ + .bit_byp = (_bit_byp),\ + .bit_digbyp = (_bit_digbyp),\ +}) + +#define CSS(_offset, _bit_css) (&(struct clk_stm32_css){\ + .offset = (_offset),\ + .bit_css = (_bit_css),\ +}) + +#define DRIVE(_offset, _shift, _width, _default) (&(struct clk_stm32_drive){\ + .offset = (_offset),\ + .drv_shift = (_shift),\ + .drv_width = (_width),\ + .drv_default = (_default),\ +}) + +#define OSCILLATOR(idx_osc, _name, _gate_id, _bypass, _css, _drive) \ + [(idx_osc)] = (struct clk_oscillator_data){\ + .name = (_name),\ + .gate_id = (_gate_id),\ + .bypass = (_bypass),\ + .css = (_css),\ + .drive = (_drive),\ + } + +static struct clk_oscillator_data stm32mp13_osc_data[NB_OSCILLATOR] = { + OSCILLATOR(OSC_HSI, "clk-hsi", GATE_HSI, + NULL, NULL, NULL), + + OSCILLATOR(OSC_LSI, "clk-lsi", GATE_LSI, + NULL, NULL, NULL), + + OSCILLATOR(OSC_CSI, "clk-csi", GATE_CSI, + NULL, NULL, NULL), + + OSCILLATOR(OSC_LSE, "clk-lse", GATE_LSE, + BYPASS(RCC_BDCR, 1, 3), + CSS(RCC_BDCR, 8), + DRIVE(RCC_BDCR, 4, 2, 2)), + + OSCILLATOR(OSC_HSE, "clk-hse", GATE_HSE, + BYPASS(RCC_OCENSETR, 10, 7), + CSS(RCC_OCENSETR, 11), + NULL), +}; + +static struct clk_oscillator_data *clk_oscillator_get_data(int osc_id) +{ + assert(osc_id >= 0 && osc_id < (int)ARRAY_SIZE(stm32mp13_osc_data)); + + return &stm32mp13_osc_data[osc_id]; +} + +static unsigned long clk_stm32_get_rate_oscillateur(int osc_id) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_osci_dt_cfg *osci = &pdata->osci[osc_id]; + + return osci->freq; +} + +static void clk_oscillator_set_bypass(struct clk_stm32_priv *priv, + struct clk_oscillator_data *osc_data, + bool digbyp, bool bypass) +{ + struct clk_stm32_bypass *bypass_data = osc_data->bypass; + uintptr_t address = 0; + + if (!bypass_data) + return; + + address = priv->base + bypass_data->offset; + + if (digbyp) + io_setbits32(address, BIT(bypass_data->bit_digbyp)); + + if (bypass || digbyp) + io_setbits32(address, BIT(bypass_data->bit_byp)); +} + +static void clk_oscillator_set_css(struct clk_stm32_priv *priv, + struct clk_oscillator_data *osc_data, + bool css) +{ + struct clk_stm32_css *css_data = osc_data->css; + uintptr_t address = 0; + + if (!css_data) + return; + + address = priv->base + css_data->offset; + + if (css) + io_setbits32(address, BIT(css_data->bit_css)); +} + +static void clk_oscillator_set_drive(struct clk_stm32_priv *priv, + struct clk_oscillator_data *osc_data, + uint8_t lsedrv) +{ + struct clk_stm32_drive *drive_data = osc_data->drive; + uintptr_t address = 0; + uint32_t mask = 0; + uint32_t value = 0; + + if (!drive_data) + return; + + address = priv->base + drive_data->offset; + + mask = (BIT(drive_data->drv_width) - 1U) << drive_data->drv_shift; + + /* + * Warning: not recommended to switch directly from "high drive" + * to "medium low drive", and vice-versa. + */ + value = (io_read32(address) & mask) >> drive_data->drv_shift; + + while (value != lsedrv) { + if (value > lsedrv) + value--; + else + value++; + + io_clrsetbits32(address, mask, value << drive_data->drv_shift); + } +} + +static void stm32_enable_oscillator_hse(struct clk_stm32_priv *priv, + struct stm32_clk_platdata *pdata) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_HSE); + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE]; + + if (osci->freq == 0U) + return; + + clk_oscillator_set_bypass(priv, osc_data, osci->digbyp, osci->bypass); + + /* Enable clock and wait ready bit */ + if (stm32_gate_rdy_enable(osc_data->gate_id)) { + EMSG("timeout to enable hse clock"); + panic(); + } + + clk_oscillator_set_css(priv, osc_data, osci->css); +} + +static void stm32_enable_oscillator_lse(struct clk_stm32_priv *priv, + struct stm32_clk_platdata *pdata) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; + + if (osci->freq == 0U) + return; + + clk_oscillator_set_bypass(priv, osc_data, osci->digbyp, osci->bypass); + + clk_oscillator_set_drive(priv, osc_data, osci->drive); + + /* Enable lse clock, but don't wait ready bit */ + stm32_gate_enable(osc_data->gate_id); +} + +static void +stm32_enable_oscillator_lsi(struct clk_stm32_priv *priv __maybe_unused, + struct stm32_clk_platdata *pdata) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSI); + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSI]; + + if (osci->freq == 0U) + return; + + /* Enable clock and wait ready bit */ + if (stm32_gate_rdy_enable(osc_data->gate_id)) { + EMSG("timeout to enable lsi clock"); + panic(); + } +} + +static void +stm32_enable_oscillator_csi(struct clk_stm32_priv *priv __maybe_unused, + struct stm32_clk_platdata *pdata) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_CSI); + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_CSI]; + + if (osci->freq == 0U) + return; + + /* Enable clock and wait ready bit */ + if (stm32_gate_rdy_enable(osc_data->gate_id)) { + EMSG("timeout to enable csi clock"); + panic(); + } +} + +static int stm32_clk_oscillators_lse_set_css(struct clk_stm32_priv *priv, + struct stm32_clk_platdata *pdata) + +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; + + clk_oscillator_set_css(priv, osc_data, osci->css); + + return 0; +} + +static int +stm32_clk_oscillators_wait_lse_ready(struct clk_stm32_priv *priv __maybe_unused, + struct stm32_clk_platdata *pdata) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; + + if (osci->freq == 0U) + return 0; + + if (stm32_gate_wait_ready(osc_data->gate_id, true)) + return -1; + + return 0; +} + +static void stm32_clk_oscillators_enable(struct clk_stm32_priv *priv, + struct stm32_clk_platdata *pdata) +{ + stm32_enable_oscillator_hse(priv, pdata); + stm32_enable_oscillator_lse(priv, pdata); + stm32_enable_oscillator_lsi(priv, pdata); + stm32_enable_oscillator_csi(priv, pdata); +} + +enum stm32_pll_id { + PLL1_ID, + PLL2_ID, + PLL3_ID, + PLL4_ID, + PLL_NB +}; + +enum stm32mp1_plltype { + PLL_800, + PLL_1600, + PLL_2000, + PLL_TYPE_NB +}; + +#define RCC_OFFSET_PLLXCR 0 +#define RCC_OFFSET_PLLXCFGR1 4 +#define RCC_OFFSET_PLLXCFGR2 8 +#define RCC_OFFSET_PLLXFRACR 12 +#define RCC_OFFSET_PLLXCSGR 16 + +struct stm32_clk_pll { + enum stm32mp1_plltype plltype; + uint16_t gate_id; + uint16_t mux_id; + uint16_t reg_pllxcr; +}; + +struct stm32mp1_pll { + uint8_t refclk_min; + uint8_t refclk_max; +}; + +/* Define characteristic of PLL according type */ +static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { + [PLL_800] = { + .refclk_min = 4, + .refclk_max = 16, + }, + [PLL_1600] = { + .refclk_min = 8, + .refclk_max = 16, + }, + [PLL_2000] = { + .refclk_min = 8, + .refclk_max = 16, + } +}; + +#define CLK_PLL_CFG(_idx, _type, _gate_id, _mux_id, _reg)\ + [(_idx)] = {\ + .gate_id = (_gate_id),\ + .mux_id = (_mux_id),\ + .plltype = (_type),\ + .reg_pllxcr = (_reg),\ + } + +static const struct stm32_clk_pll stm32_mp13_clk_pll[PLL_NB] = { + CLK_PLL_CFG(PLL1_ID, PLL_2000, GATE_PLL1, MUX_PLL12, RCC_PLL1CR), + CLK_PLL_CFG(PLL2_ID, PLL_1600, GATE_PLL2, MUX_PLL12, RCC_PLL2CR), + CLK_PLL_CFG(PLL3_ID, PLL_800, GATE_PLL3, MUX_PLL3, RCC_PLL3CR), + CLK_PLL_CFG(PLL4_ID, PLL_800, GATE_PLL4, MUX_PLL4, RCC_PLL4CR), +}; + +static const struct stm32_clk_pll *clk_stm32_pll_data(unsigned int idx) +{ + return &stm32_mp13_clk_pll[idx]; +} + +/* Clock TREE configuration */ + +static unsigned int stm32_clk_configure_clk_get_binding_id(uint32_t data) +{ + return (data & CLK_ID_MASK) >> CLK_ID_SHIFT; +} + +static int stm32_clk_configure_clk(struct clk_stm32_priv *priv __maybe_unused, + uint32_t data) +{ + int sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT; + int enable = (data & CLK_ON_MASK) >> CLK_ON_SHIFT; + int clk_id = 0; + int ret = 0; + int mux = -1; + int gate = -1; + + clk_id = stm32_clk_configure_clk_get_binding_id(data); + + switch (clk_id) { + case CK_MCO1: + mux = MUX_MCO1; + gate = GATE_MCO1; + break; + + case CK_MCO2: + mux = MUX_MCO2; + gate = GATE_MCO2; + break; + default: + ret = -1; + break; + } + + if (ret != 0) + return ret; + + if (stm32_mux_set_parent(mux, sel)) + return -1; + + if (enable) + stm32_gate_enable(gate); + else + stm32_gate_disable(gate); + + return 0; +} + +static int stm32_clk_configure_mux(__unused struct clk_stm32_priv *priv, + uint32_t data) +{ + int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT; + int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT; + + if (mux == MUX_RTC) { + /* Mux RTC clock only is selector is valid and RTC not yet + * enabled + */ + if (sel == 0) + return 0; + + if (stm32_gate_is_enabled(GATE_RTCCK)) + return 0; + } + + if (stm32_mux_set_parent(mux, sel)) + return -1; + + return 0; +} + +static TEE_Result +stm32_clk_configure_div(struct clk_stm32_priv *priv __maybe_unused, + uint32_t data) +{ + int div_id = (data & DIV_ID_MASK) >> DIV_ID_SHIFT; + int div_n = (data & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT; + + return stm32_div_set_value(div_id, div_n); +} + +static int stm32_clk_dividers_configure(struct clk_stm32_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + unsigned int i = 0; + + for (i = 0; i < pdata->nclkdiv; i++) { + if (stm32_clk_configure_div(priv, pdata->clkdiv[i])) + return -1; + } + + return 0; +} + +static int stm32_clk_source_configure(struct clk_stm32_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + bool ckper_disabled = false; + int ret = 0; + size_t i = 0; + + for (i = 0; i < pdata->nclksrc; i++) { + uint32_t val = pdata->clksrc[i]; + uint32_t cmd = 0; + uint32_t cmd_data = 0; + + if (val == (uint32_t)CLK_CKPER_DISABLED) { + ckper_disabled = true; + continue; + } + + cmd = (val & CMD_MASK) >> CMD_SHIFT; + cmd_data = val & ~CMD_MASK; + + switch (cmd) { + case CMD_MUX: + ret = stm32_clk_configure_mux(priv, cmd_data); + break; + + case CMD_CLK: + ret = stm32_clk_configure_clk(priv, cmd_data); + break; + default: + ret = -1; + break; + } + + if (ret != 0) + return ret; + } + + /* + * CKPER is source for some peripheral clocks + * (FMC-NAND / QPSI-NOR) and switching source is allowed + * only if previous clock is still ON + * => deactivate CKPER only after switching clock + */ + if (ckper_disabled) { + ret = stm32_clk_configure_mux(priv, + CLK_CKPER_DISABLED & CMD_MASK); + if (ret != 0) + return ret; + } + + return 0; +} + +static unsigned long clk_stm32_pll_get_oscillator_rate(int sel) +{ + const int osc[] = { OSC_HSI, OSC_HSE, OSC_CSI }; + + assert(sel >= 0 && sel < (int)ARRAY_SIZE(osc)); + + return clk_stm32_get_rate_oscillateur(osc[sel]); +} + +static int clk_stm32_pll_compute_cfgr1(const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco, + uint32_t *value) +{ + int sel = (vco->src & MUX_SEL_MASK) >> MUX_SEL_SHIFT; + uint32_t divm = vco->div_mn[PLL_CFG_M]; + uint32_t divn = vco->div_mn[PLL_CFG_N]; + unsigned long refclk = 0UL; + + refclk = clk_stm32_pll_get_oscillator_rate(sel) / (divm + 1U); + + if ((refclk < (stm32mp1_pll[pll->plltype].refclk_min * 1000000U)) || + (refclk > (stm32mp1_pll[pll->plltype].refclk_max * 1000000U))) + return -1; + + *value = 0; + + if (pll->plltype == PLL_800 && refclk >= 8000000U) + *value = 1U << RCC_PLLNCFGR1_IFRGE_SHIFT; + + *value |= (divn << RCC_PLLNCFGR1_DIVN_SHIFT) & RCC_PLLNCFGR1_DIVN_MASK; + *value |= (divm << RCC_PLLNCFGR1_DIVM_SHIFT) & RCC_PLLNCFGR1_DIVM_MASK; + + return 0; +} + +static uint32_t clk_stm32_pll_compute_cfgr2(struct stm32_pll_output *out) +{ + uint32_t value = 0; + + value |= (out->output[PLL_CFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & + RCC_PLLNCFGR2_DIVP_MASK; + value |= (out->output[PLL_CFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & + RCC_PLLNCFGR2_DIVQ_MASK; + value |= (out->output[PLL_CFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & + RCC_PLLNCFGR2_DIVR_MASK; + + return value; +} + +/* + * Check if PLL1 can be configured on the fly. + * @result (-1) => config on the fly is not possible. + * (0) => config on the fly is possible. + * (+1) => same parameters, no need to reconfigure. + * Return value is 0 if no error. + */ +static int clk_stm32_is_pll_config_on_the_fly(struct clk_stm32_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_dt_cfg *pll_conf, + int *result) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + struct stm32_pll_vco *vco = &pll_conf->vco; + struct stm32_pll_output *out = &pll_conf->output; + uint32_t fracr = 0; + uint32_t value = 0; + int ret = 0; + size_t sel = 0; + + ret = clk_stm32_pll_compute_cfgr1(pll, vco, &value); + if (ret != 0) + return ret; + + sel = (vco->src & MUX_SEL_MASK) >> MUX_SEL_SHIFT; + if (sel != stm32_mux_get_parent(pll->mux_id)) { + /* Clock source of the PLL is different */ + *result = -1; + return 0; + } + + if (io_read32(pll_base + RCC_OFFSET_PLLXCFGR1) != value) { + /* Different DIVN/DIVM, can't config on the fly */ + *result = -1; + return 0; + } + + *result = 1; + + fracr = vco->frac << RCC_PLLNFRACR_FRACV_SHIFT; + fracr |= RCC_PLLNCFGR1_DIVM_MASK; + value = clk_stm32_pll_compute_cfgr2(out); + + if ((io_read32(pll_base + RCC_OFFSET_PLLXFRACR) == fracr) && + (io_read32(pll_base + RCC_OFFSET_PLLXCFGR2) == value)) { + /* Same parameters, no need to config */ + *result = 1; + } else { + *result = 0; + } + + return 0; +} + +static int stm32_clk_hsidiv_configure(struct clk_stm32_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSI]; + + return stm32_div_set_rate(DIV_HSI, osci->freq, MAX_HSI_HZ); +} + +static void clk_stm32_pll_config_vco(struct clk_stm32_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t value = 0; + + if (clk_stm32_pll_compute_cfgr1(pll, vco, &value) != 0) { + EMSG("Invalid Vref clock"); + panic(); + } + + /* Write N / M / IFREGE fields */ + io_write32(pll_base + RCC_OFFSET_PLLXCFGR1, value); + + /* Fractional configuration */ + io_write32(pll_base + RCC_OFFSET_PLLXFRACR, 0); + + /* Frac must be enabled only once its configuration is loaded */ + io_write32(pll_base + RCC_OFFSET_PLLXFRACR, + vco->frac << RCC_PLLNFRACR_FRACV_SHIFT); + + io_setbits32(pll_base + RCC_OFFSET_PLLXFRACR, RCC_PLLNFRACR_FRACLE); +} + +static void clk_stm32_pll_config_csg(struct clk_stm32_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t mod_per = 0; + uint32_t inc_step = 0; + uint32_t sscg_mode = 0; + uint32_t value = 0; + + if (!vco->csg_enabled) + return; + + mod_per = vco->csg[PLL_CSG_MOD_PER]; + inc_step = vco->csg[PLL_CSG_INC_STEP]; + sscg_mode = vco->csg[PLL_CSG_SSCG_MODE]; + + value |= (mod_per << RCC_PLLNCSGR_MOD_PER_SHIFT) & + RCC_PLLNCSGR_MOD_PER_MASK; + value |= (inc_step << RCC_PLLNCSGR_INC_STEP_SHIFT) & + RCC_PLLNCSGR_INC_STEP_MASK; + value |= (sscg_mode << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & + RCC_PLLNCSGR_SSCG_MODE_MASK; + + io_write32(pll_base + RCC_OFFSET_PLLXCSGR, value); + io_setbits32(pll_base + RCC_OFFSET_PLLXCR, RCC_PLLNCR_SSCG_CTRL); +} + +static void clk_stm32_pll_config_out(struct clk_stm32_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_output *out) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t value = 0; + + value = clk_stm32_pll_compute_cfgr2(out); + + io_write32(pll_base + RCC_OFFSET_PLLXCFGR2, value); +} + +static struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(int pll_idx) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + struct stm32_clk_platdata *pdata = priv->pdata; + + return &pdata->pll[pll_idx]; +} + +static int clk_stm32_pll_init_switch_to_hsi_clk_system(int mux_sys) +{ + int sel = 0; + + if (mux_sys == -1) + return -1; + + /* Make a backup to the current parent */ + sel = stm32_mux_get_parent(mux_sys); + + /* Switch to HSI */ + if (stm32_mux_set_parent(mux_sys, 0)) + return -1; + + return sel; +} + +static uint32_t +clk_stm32_pll_backup_output_diven(const struct stm32_clk_pll *pll) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + uintptr_t addr = priv->base + pll->reg_pllxcr; + + return io_read32(addr + RCC_OFFSET_PLLXCR) & + (RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN); +} + +static void clk_stm32_pll_restore_output_diven(const struct stm32_clk_pll *pll, + uint32_t value) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + uintptr_t addr = priv->base + pll->reg_pllxcr; + const uint32_t mask = RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN; + + io_clrsetbits32(addr, mask, value & mask); +} + +static int clk_stm32_pll_init(struct clk_stm32_priv *priv, int pll_idx, + struct stm32_pll_dt_cfg *pll_conf) +{ + const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_idx); + int config_on_the_fly = -1; + int ret = 0; + uint8_t sel = 0; + uint32_t save_div_pqr_en = 0; + int mux_system[] = { MUX_MPU, MUX_AXI, MUX_MLAHB, -1 }; + int mux_sys = mux_system[pll_idx]; + + ret = clk_stm32_is_pll_config_on_the_fly(priv, pll, pll_conf, + &config_on_the_fly); + if (ret != 0) + return ret; + + /* Backup status of DIV DIVPEN / DIVQEN / DIVREN */ + save_div_pqr_en = clk_stm32_pll_backup_output_diven(pll); + + if (config_on_the_fly == -1) { + /* Make a backup to the current parent and switch to HSI */ + sel = clk_stm32_pll_init_switch_to_hsi_clk_system(mux_sys); + + /* Stop the PLL before */ + if (stm32_gate_is_enabled(pll->gate_id)) { + io_clrbits32(priv->base + pll->reg_pllxcr, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN); + + if (stm32_gate_rdy_disable(pll->gate_id)) + return -1; + } + + /* Configure PLLs source */ + ret = stm32_clk_configure_mux(priv, pll_conf->vco.src); + if (ret) + return ret; + + clk_stm32_pll_config_vco(priv, pll, &pll_conf->vco); + } + + if (config_on_the_fly != 1) { + clk_stm32_pll_config_out(priv, pll, &pll_conf->output); + clk_stm32_pll_config_csg(priv, pll, &pll_conf->vco); + } + + if (!stm32_gate_is_enabled(pll->gate_id)) { + if (stm32_gate_rdy_enable(pll->gate_id)) + return -1; + + clk_stm32_pll_restore_output_diven(pll, save_div_pqr_en); + } + + if ((config_on_the_fly == -1) && (mux_sys != -1)) { + /* Restore to backup parent */ + if (stm32_mux_set_parent(mux_sys, sel)) + return -1; + } + + return 0; +} + +static int stm32_clk_pll_configure(struct clk_stm32_priv *priv) +{ + struct stm32_pll_dt_cfg *pll_conf = NULL; + size_t i = 0; + const int plls[] = { PLL1_ID, PLL3_ID, PLL4_ID }; + + for (i = 0; i < ARRAY_SIZE(plls); i++) { + pll_conf = clk_stm32_pll_get_pdata(plls[i]); + + if (pll_conf->vco.status) { + int err = 0; + + err = clk_stm32_pll_init(priv, plls[i], pll_conf); + if (err) + return err; + } + } + + return 0; +} + +static int stm32mp1_init_clock_tree(struct clk_stm32_priv *priv, + struct stm32_clk_platdata *pdata) +{ + int ret = 0; + + /* + * Switch ON oscillators found in device-tree. + * Note: HSI already ON after BootROM stage. + */ + stm32_clk_oscillators_enable(priv, pdata); + + ret = stm32_clk_hsidiv_configure(priv); + if (ret != 0) + return ret; + + ret = stm32_clk_dividers_configure(priv); + if (ret != 0) + panic(); + + ret = stm32_clk_pll_configure(priv); + if (ret != 0) + panic(); + + /* Wait LSE ready before to use it */ + ret = stm32_clk_oscillators_wait_lse_ready(priv, pdata); + if (ret != 0) + panic(); + + /* Configure with expected clock source */ + ret = stm32_clk_source_configure(priv); + if (ret != 0) + panic(); + + /* Configure LSE CSS after RTC source configuration */ + ret = stm32_clk_oscillators_lse_set_css(priv, pdata); + if (ret != 0) + panic(); + + /* Software Self-Refresh mode (SSR) during DDR initilialization */ + io_clrsetbits32(priv->base + RCC_DDRITFCR, RCC_DDRITFCR_DDRCKMOD_MASK, + RCC_DDRITFCR_DDRCKMOD_SSR << + RCC_DDRITFCR_DDRCKMOD_SHIFT); + + return 0; +} + +static int clk_stm32_parse_oscillator_fdt(const void *fdt, int node, + const char *name, + struct stm32_osci_dt_cfg *osci) +{ + int subnode = 0; + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar = NULL; + const fdt32_t *cuint = NULL; + int ret = 0; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (!cchar) + return ret; + + if (strncmp(cchar, name, (size_t)ret) || + fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) + continue; + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); + if (!cuint) + panic(); + + osci->freq = fdt32_to_cpu(*cuint); + + if (fdt_getprop(fdt, subnode, "st,bypass", NULL)) + osci->bypass = true; + + if (fdt_getprop(fdt, subnode, "st,digbypass", NULL)) + osci->digbyp = true; + + if (fdt_getprop(fdt, subnode, "st,css", NULL)) + osci->css = true; + + osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive", + LSEDRV_MEDIUM_HIGH); + + return 0; + } + + return -FDT_ERR_NOTFOUND; +} + +static int stm32_clk_parse_fdt_all_oscillator(const void *fdt, + int node __maybe_unused, + struct stm32_clk_platdata *pdata) +{ + int fdt_err = 0; + size_t i = 0; + int osc_node = 0; + + osc_node = fdt_path_offset(fdt, "/clocks"); + if (osc_node < 0) + return -FDT_ERR_NOTFOUND; + + for (i = 0; i < NB_OSCILLATOR; i++) { + struct stm32_osci_dt_cfg *osci = &pdata->osci[i]; + struct clk_oscillator_data *osc_data = NULL; + + osc_data = clk_oscillator_get_data(i); + + fdt_err = clk_stm32_parse_oscillator_fdt(fdt, osc_node, + osc_data->name, osci); + if (fdt_err < 0) + panic(); + } + + return 0; +} + +static int clk_stm32_load_vco_config_fdt(const void *fdt, int subnode, + struct stm32_pll_vco *vco) +{ + int ret = 0; + + ret = fdt_read_uint32_array(fdt, subnode, "divmn", vco->div_mn, + PLL_DIV_MN_NB); + if (ret != 0) + return ret; + + ret = fdt_read_uint32_array(fdt, subnode, "csg", vco->csg, + PLL_CSG_NB); + + vco->csg_enabled = (ret == 0); + + if (ret == -FDT_ERR_NOTFOUND) + ret = 0; + + if (ret != 0) + return ret; + + vco->status = RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN | RCC_PLLNCR_PLLON; + + vco->frac = fdt_read_uint32_default(fdt, subnode, "frac", 0); + + vco->src = fdt_read_uint32_default(fdt, subnode, "src", UINT32_MAX); + + return 0; +} + +static int clk_stm32_load_output_config_fdt(const void *fdt, int subnode, + struct stm32_pll_output *output) +{ + return fdt_read_uint32_array(fdt, subnode, "st,pll_div_pqr", + output->output, (int)PLL_DIV_PQR_NB); +} + +static int clk_stm32_parse_pll_fdt(const void *fdt, int subnode, + struct stm32_pll_dt_cfg *pll) +{ + const fdt32_t *cuint = NULL; + int subnode_pll = 0; + int subnode_vco = 0; + int err = 0; + + cuint = fdt_getprop(fdt, subnode, "st,pll", NULL); + if (!cuint) + return -FDT_ERR_NOTFOUND; + + subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (subnode_pll < 0) + return -FDT_ERR_NOTFOUND; + + cuint = fdt_getprop(fdt, subnode_pll, "st,pll_vco", NULL); + if (!cuint) + return -FDT_ERR_NOTFOUND; + + subnode_vco = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (subnode_vco < 0) + return -FDT_ERR_NOTFOUND; + + err = clk_stm32_load_vco_config_fdt(fdt, subnode_vco, &pll->vco); + if (err != 0) + return err; + + err = clk_stm32_load_output_config_fdt(fdt, subnode_pll, &pll->output); + if (err != 0) + return err; + + return 0; +} + +static int stm32_clk_parse_fdt_all_pll(const void *fdt, int node, + struct stm32_clk_platdata *pdata) +{ + size_t i = 0; + + for (i = PLL1_ID; i < pdata->npll; i++) { + struct stm32_pll_dt_cfg *pll = pdata->pll + i; + char name[RCC_PLL_NAME_SIZE] = { 0 }; + int subnode = 0; + int err = 0; + + snprintf(name, sizeof(name), "st,pll@%d", i); + + subnode = fdt_subnode_offset(fdt, node, name); + if (subnode < 0) + continue; + + err = clk_stm32_parse_pll_fdt(fdt, subnode, pll); + if (err != 0) + panic(); + } + + return 0; +} + +static int stm32_clk_parse_fdt_opp(const void *fdt, int node, + const char *opp_name, + struct stm32_clk_opp_cfg *opp_cfg) +{ + int subnode = 0; + int nb_opp = 0; + int ret = 0; + + node = fdt_subnode_offset(fdt, node, opp_name); + if (node == -FDT_ERR_NOTFOUND) + return 0; + if (node < 0) + return node; + + fdt_for_each_subnode(subnode, fdt, node) { + if (nb_opp >= MAX_OPP) { + EMSG("%d MAX opp in %s", MAX_OPP, opp_name); + panic(); + } + + opp_cfg->frq = fdt_read_uint32_default(fdt, subnode, + "hz", + UINT32_MAX); + + opp_cfg->src = fdt_read_uint32_default(fdt, subnode, + "st,clksrc", + UINT32_MAX); + + opp_cfg->div = fdt_read_uint32_default(fdt, subnode, + "st,clkdiv", + UINT32_MAX); + + ret = clk_stm32_parse_pll_fdt(fdt, subnode, &opp_cfg->pll_cfg); + if (ret) + return ret; + + opp_cfg++; + nb_opp++; + } + + return 0; +} + +static int stm32_clk_parse_fdt_all_opp(const void *fdt, int node, + struct stm32_clk_platdata *pdata) +{ + struct stm32_clk_opp_dt_cfg *opp = pdata->opp; + int ret = 0; + + node = fdt_subnode_offset(fdt, node, "st,clk_opp"); + /* No opp are defined */ + if (node == -FDT_ERR_NOTFOUND) + return 0; + if (node < 0) + return node; + + ret = stm32_clk_parse_fdt_opp(fdt, node, "st,ck_mpu", opp->mpu_opp); + if (ret) + return ret; + + ret = stm32_clk_parse_fdt_opp(fdt, node, "st,ck_axi", opp->axi_opp); + if (ret) + return ret; + + ret = stm32_clk_parse_fdt_opp(fdt, node, "st,ck_mlahbs", + opp->mlahbs_opp); + if (ret) + return ret; + + return 0; +} + +static int stm32_clk_parse_fdt(const void *fdt, int node, + struct stm32_clk_platdata *pdata) +{ + int err = 0; + + err = stm32_clk_parse_fdt_all_oscillator(fdt, node, pdata); + if (err != 0) + return err; + + err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata); + if (err != 0) + return err; + + err = stm32_clk_parse_fdt_all_opp(fdt, node, pdata); + if (err != 0) + return err; + + err = clk_stm32_parse_fdt_by_name(fdt, node, "st,clkdiv", pdata->clkdiv, + &pdata->nclkdiv); + if (err != 0) + return err; + + err = clk_stm32_parse_fdt_by_name(fdt, node, "st,clksrc", pdata->clksrc, + &pdata->nclksrc); + if (err != 0) + return err; + + return 0; +} + +struct clk_stm32_pll_cfg { + uint32_t reg_pllxcr; + int gate_id; + int mux_id; +}; + +static size_t clk_stm32_pll_get_parent(struct clk *clk) +{ + struct clk_stm32_pll_cfg *cfg = clk->priv; + + return stm32_mux_get_parent(cfg->mux_id); +} + +static unsigned long clk_stm32_pll_get_rate(struct clk *clk, + unsigned long prate) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + struct clk_stm32_pll_cfg *cfg = clk->priv; + uintptr_t pll_base = priv->base + cfg->reg_pllxcr; + uint32_t cfgr1 = 0; + uint32_t fracr = 0; + uint32_t divm = 0; + uint32_t divn = 0; + unsigned long fvco = 0UL; + + cfgr1 = io_read32(pll_base + RCC_OFFSET_PLLXCFGR1); + fracr = io_read32(pll_base + RCC_OFFSET_PLLXFRACR); + + divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; + divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; + + /* + * With FRACV : + * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) + * Without FRACV + * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) + */ + if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { + uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> + RCC_PLLNFRACR_FRACV_SHIFT; + unsigned long long numerator = 0UL; + unsigned long long denominator = 0UL; + + numerator = (((unsigned long long)divn + 1U) << 13) + fracv; + numerator = prate * numerator; + denominator = ((unsigned long long)divm + 1U) << 13; + fvco = (unsigned long)(numerator / denominator); + } else { + fvco = (unsigned long)(prate * (divn + 1U) / (divm + 1U)); + } + + return fvco; +}; + +static bool clk_stm32_pll_is_enabled(struct clk *clk) +{ + struct clk_stm32_pll_cfg *cfg = clk->priv; + + return stm32_gate_is_enabled(cfg->gate_id); +} + +static TEE_Result clk_stm32_pll_enable(struct clk *clk) +{ + struct clk_stm32_pll_cfg *cfg = clk->priv; + + if (clk_stm32_pll_is_enabled(clk)) + return TEE_SUCCESS; + + return stm32_gate_rdy_enable(cfg->gate_id); +} + +static void clk_stm32_pll_disable(struct clk *clk) +{ + struct clk_stm32_pll_cfg *cfg = clk->priv; + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + uintptr_t pll_base = priv->base + cfg->reg_pllxcr; + + if (!clk_stm32_pll_is_enabled(clk)) + return; + + /* Stop all output */ + io_clrbits32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN); + + stm32_gate_rdy_disable(cfg->gate_id); +} + +static const struct clk_ops clk_stm32_pll_ops = { + .get_parent = clk_stm32_pll_get_parent, + .get_rate = clk_stm32_pll_get_rate, + .enable = clk_stm32_pll_enable, + .disable = clk_stm32_pll_disable, +}; + +static struct +stm32_clk_opp_cfg *clk_stm32_get_opp_config(struct stm32_clk_opp_cfg *opp_cfg, + unsigned long rate) +{ + unsigned int i = 0; + + for (i = 0; i < MAX_OPP; i++, opp_cfg++) { + if (opp_cfg->frq == 0UL) + break; + + if (opp_cfg->frq == rate) + return opp_cfg; + } + + return NULL; +} + +static TEE_Result clk_stm32_pll1_set_rate(struct clk *clk __maybe_unused, + unsigned long rate, + unsigned long prate __maybe_unused) +{ + const struct stm32_clk_pll *pll = clk_stm32_pll_data(PLL1_ID); + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_pll_dt_cfg *pll_conf = NULL; + struct stm32_clk_opp_cfg *opp = NULL; + int config_on_the_fly = -1; + int err = 0; + size_t sel = stm32_mux_get_parent(MUX_MPU); + + opp = clk_stm32_get_opp_config(pdata->opp->mpu_opp, rate); + if (!opp) + return TEE_ERROR_GENERIC; + + pll_conf = &opp->pll_cfg; + + err = clk_stm32_is_pll_config_on_the_fly(priv, pll, pll_conf, + &config_on_the_fly); + if (err) + return TEE_ERROR_GENERIC; + + if (config_on_the_fly == 1) + return TEE_SUCCESS; + + if (config_on_the_fly == -1) { + /* Switch to HSI and stop PLL1 before reconfiguration */ + if (stm32_mux_set_parent(MUX_MPU, 0)) + return TEE_ERROR_GENERIC; + + stm32_gate_disable(GATE_PLL1_DIVP); + stm32_gate_rdy_disable(GATE_PLL1); + clk_stm32_pll_config_vco(priv, pll, &pll_conf->vco); + } + + clk_stm32_pll_config_out(priv, pll, &pll_conf->output); + if (stm32_gate_rdy_enable(GATE_PLL1)) { + EMSG("timeout to enable PLL1 clock"); + panic(); + } + stm32_gate_enable(GATE_PLL1_DIVP); + + /* Restore MPU source */ + if (stm32_mux_set_parent(MUX_MPU, sel)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static const struct clk_ops clk_stm32_pll1_ops = { + .set_rate = clk_stm32_pll1_set_rate, + .get_parent = clk_stm32_pll_get_parent, + .get_rate = clk_stm32_pll_get_rate, + .enable = clk_stm32_pll_enable, + .disable = clk_stm32_pll_disable, +}; + +static const struct clk_ops clk_stm32_pll1p_ops = { + .get_rate = clk_stm32_composite_get_rate, + .enable = clk_stm32_composite_gate_enable, + .disable = clk_stm32_composite_gate_disable, +}; + +static const struct clk_ops clk_stm32_mpu_ops = { + .get_parent = clk_stm32_composite_get_parent, + .set_parent = clk_stm32_composite_set_parent, +}; + +static const struct clk_ops clk_stm32_axi_ops = { + .get_parent = clk_stm32_composite_get_parent, + .set_parent = clk_stm32_composite_set_parent, + .set_rate = clk_stm32_composite_set_rate, + .get_rate = clk_stm32_composite_get_rate, +}; + +const struct clk_ops clk_stm32_mlahb_ops = { + .get_parent = clk_stm32_composite_get_parent, + .set_parent = clk_stm32_composite_set_parent, + .set_rate = clk_stm32_composite_set_rate, + .get_rate = clk_stm32_composite_get_rate, +}; + +#define APB_DIV_MASK GENMASK_32(2, 0) +#define TIM_PRE_MASK BIT(0) + +static unsigned long ck_timer_get_rate_ops(struct clk *clk, unsigned long prate) +{ + struct clk_stm32_priv *priv = clk_stm32_get_priv(); + struct clk_stm32_timer_cfg *cfg = clk->priv; + uint32_t prescaler, timpre; + uintptr_t rcc_base = priv->base; + + prescaler = io_read32(rcc_base + cfg->apbdiv) & APB_DIV_MASK; + + timpre = io_read32(rcc_base + cfg->timpre) & TIM_PRE_MASK; + + if (prescaler == 0U) + return prate; + + return prate * (timpre + 1U) * 2U; +}; + +const struct clk_ops ck_timer_ops = { + .get_rate = ck_timer_get_rate_ops, +}; + +#define STM32_TIMER(_name, _parent, _flags, _apbdiv, _timpre)\ + struct clk _name = {\ + .ops = &ck_timer_ops,\ + .priv = &(struct clk_stm32_timer_cfg) {\ + .apbdiv = (_apbdiv),\ + .timpre = (_timpre),\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = 1,\ + .parents = { _parent },\ + } + +#define STM32_KCLK(_name, _nb_parents, _parents, _flags, _gate_id, _mux_id)\ + struct clk _name = {\ + .ops = &clk_stm32_composite_ops,\ + .priv = &(struct clk_stm32_composite_cfg) {\ + .gate_id = (_gate_id),\ + .div_id = (NO_DIV),\ + .mux_id = (_mux_id),\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = (_nb_parents),\ + .parents = _parents,\ + } + +#define STM32_PLL_VCO(_name, _nb_parents, _parents, _flags, _reg,\ + _gate_id, _mux_id)\ + struct clk _name = {\ + .ops = &clk_stm32_pll_ops,\ + .priv = &(struct clk_stm32_pll_cfg) {\ + .reg_pllxcr = (_reg),\ + .gate_id = (_gate_id),\ + .mux_id = (_mux_id),\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = (_nb_parents),\ + .parents = _parents,\ + } + +#define STM32_PLL_OUPUT(_name, _nb_parents, _parents, _flags,\ + _gate_id, _div_id, _mux_id)\ + struct clk _name = {\ + .ops = &clk_stm32_composite_ops,\ + .priv = &(struct clk_stm32_composite_cfg) {\ + .gate_id = (_gate_id),\ + .div_id = (_div_id),\ + .mux_id = (_mux_id),\ + },\ + .name = #_name,\ + .flags = (_flags),\ + .num_parents = (_nb_parents),\ + .parents = _parents,\ + } + +/* Oscillator clocks */ +static STM32_GATE_READY(ck_hsi, NULL, 0, GATE_HSI); +static STM32_GATE_READY(ck_hse, NULL, 0, GATE_HSE); +static STM32_GATE_READY(ck_csi, NULL, 0, GATE_CSI); +static STM32_GATE_READY(ck_lsi, NULL, 0, GATE_LSI); +static STM32_GATE_READY(ck_lse, NULL, 0, GATE_LSE); + +static STM32_FIXED_FACTOR(ck_i2sckin, NULL, 0, 1, 1); +static STM32_FIXED_FACTOR(ck_hse_div2, &ck_hse, 0, 1, 2); + +static STM32_FIXED_RATE(ck_off, 0UL); +static STM32_FIXED_RATE(ck_usb_phy_48Mhz, USB_PHY_48_MHZ); + +/* PLL1 clocks */ +static struct clk ck_pll1_vco = { + .ops = &clk_stm32_pll1_ops, + .priv = &(struct clk_stm32_pll_cfg) { + .reg_pllxcr = RCC_PLL1CR, + .gate_id = GATE_PLL1, + .mux_id = MUX_PLL12, + }, + .name = "ck_pll1_vco", + .flags = 0, + .num_parents = 2, + .parents = { &ck_hsi, &ck_hse }, +}; + +static struct clk ck_pll1p = { + .ops = &clk_stm32_pll1p_ops, + .priv = &(struct clk_stm32_composite_cfg) { + .gate_id = GATE_PLL1_DIVP, + .div_id = DIV_PLL1DIVP, + .mux_id = NO_MUX, + }, + .name = "ck_pll1p", + .flags = 0, + .num_parents = 1, + .parents = { &ck_pll1_vco }, +}; + +const struct clk_ops clk_stm32_pll1p_div_ops = { + .get_rate = clk_stm32_divider_get_rate, +}; + +static struct clk ck_pll1p_div = { + .ops = &clk_stm32_pll1p_div_ops, + .priv = &(struct clk_stm32_div_cfg) { + .div_id = DIV_MPU, + }, + .name = "ck_pll1p_div", + .flags = 0, + .num_parents = 1, + .parents = { &ck_pll1p }, +}; + +/* Other PLLs */ +static STM32_PLL_VCO(ck_pll2_vco, 2, PARENT(&ck_hsi, &ck_hse), + 0, RCC_PLL2CR, GATE_PLL2, MUX_PLL12); + +static STM32_PLL_VCO(ck_pll3_vco, 3, + PARENT(&ck_hsi, &ck_hse, &ck_csi), + 0, RCC_PLL3CR, GATE_PLL3, MUX_PLL3); + +static STM32_PLL_VCO(ck_pll4_vco, 4, + PARENT(&ck_hsi, &ck_hse, &ck_csi, &ck_i2sckin), + 0, RCC_PLL4CR, GATE_PLL4, MUX_PLL4); + +static STM32_PLL_OUPUT(ck_pll2p, 1, PARENT(&ck_pll2_vco), 0, + GATE_PLL2_DIVP, DIV_PLL2DIVP, NO_MUX); + +static STM32_PLL_OUPUT(ck_pll2q, 1, PARENT(&ck_pll2_vco), 0, + GATE_PLL2_DIVQ, DIV_PLL2DIVQ, NO_MUX); + +static STM32_PLL_OUPUT(ck_pll2r, 1, PARENT(&ck_pll2_vco), 0, + GATE_PLL2_DIVR, DIV_PLL2DIVR, NO_MUX); + +static STM32_PLL_OUPUT(ck_pll3p, 1, PARENT(&ck_pll3_vco), 0, + GATE_PLL3_DIVP, DIV_PLL3DIVP, NO_MUX); + +static STM32_PLL_OUPUT(ck_pll3q, 1, PARENT(&ck_pll3_vco), 0, + GATE_PLL3_DIVQ, DIV_PLL3DIVQ, NO_MUX); + +static STM32_PLL_OUPUT(ck_pll3r, 1, PARENT(&ck_pll3_vco), 0, + GATE_PLL3_DIVR, DIV_PLL3DIVR, NO_MUX); + +static STM32_PLL_OUPUT(ck_pll4p, 1, PARENT(&ck_pll4_vco), 0, + GATE_PLL4_DIVP, DIV_PLL4DIVP, NO_MUX); + +static STM32_PLL_OUPUT(ck_pll4q, 1, PARENT(&ck_pll4_vco), 0, + GATE_PLL4_DIVQ, DIV_PLL4DIVQ, NO_MUX); + +static STM32_PLL_OUPUT(ck_pll4r, 1, PARENT(&ck_pll4_vco), 0, + GATE_PLL4_DIVR, DIV_PLL4DIVR, NO_MUX); + +/* System clocks */ +static struct clk ck_mpu = { + .ops = &clk_stm32_mpu_ops, + .priv = &(struct clk_stm32_composite_cfg) { + .mux_id = MUX_MPU, + }, + .name = "ck_mpu", + .flags = 0, + .num_parents = 4, + .parents = { &ck_hsi, &ck_hse, &ck_pll1p, &ck_pll1p_div }, +}; + +static struct clk ck_axi = { + .ops = &clk_stm32_axi_ops, + .priv = &(struct clk_stm32_composite_cfg) { + .mux_id = MUX_AXI, + .div_id = DIV_AXI, + }, + .name = "ck_axi", + .flags = 0, + .num_parents = 3, + .parents = { &ck_hsi, &ck_hse, &ck_pll2p }, +}; + +static struct clk ck_mlahb = { + .ops = &clk_stm32_mlahb_ops, + .priv = &(struct clk_stm32_composite_cfg) { + .mux_id = MUX_MLAHB, + .div_id = DIV_MLAHB, + }, + .name = "ck_mlahb", + .flags = 0, + .num_parents = 4, + .parents = { &ck_hsi, &ck_hse, &ck_csi, &ck_pll3p }, +}; + +static STM32_MUX(ck_per, 4, PARENT(&ck_hsi, &ck_csi, &ck_hse, &ck_off), + 0, MUX_CKPER); + +/* Bus clocks */ +static STM32_DIVIDER(ck_pclk1, &ck_mlahb, 0, DIV_APB1); +static STM32_DIVIDER(ck_pclk2, &ck_mlahb, 0, DIV_APB2); +static STM32_DIVIDER(ck_pclk3, &ck_mlahb, 0, DIV_APB3); +static STM32_DIVIDER(ck_pclk4, &ck_axi, 0, DIV_APB4); +static STM32_DIVIDER(ck_pclk5, &ck_axi, 0, DIV_APB5); +static STM32_DIVIDER(ck_pclk6, &ck_mlahb, 0, DIV_APB6); + +/* Timer Clocks */ +static STM32_TIMER(ck_timg1, &ck_pclk1, 0, RCC_APB1DIVR, RCC_TIMG1PRER); +static STM32_TIMER(ck_timg2, &ck_pclk2, 0, RCC_APB2DIVR, RCC_TIMG2PRER); +static STM32_TIMER(ck_timg3, &ck_pclk6, 0, RCC_APB6DIVR, RCC_TIMG3PRER); + +/* Peripheral and Kernel Clocks */ +static STM32_GATE(ck_ddrc1, &ck_axi, 0, GATE_DDRC1); +static STM32_GATE(ck_ddrc1lp, &ck_axi, 0, GATE_DDRC1LP); +static STM32_GATE(ck_ddrphyc, &ck_pll2r, 0, GATE_DDRPHYC); +static STM32_GATE(ck_ddrphyclp, &ck_pll2r, 0, GATE_DDRPHYCLP); +static STM32_GATE(ck_ddrcapb, &ck_pclk4, 0, GATE_DDRCAPB); +static STM32_GATE(ck_ddrcapblp, &ck_pclk4, 0, GATE_DDRCAPBLP); +static STM32_GATE(ck_axidcg, &ck_axi, 0, GATE_AXIDCG); +static STM32_GATE(ck_ddrphycapb, &ck_pclk4, 0, 0); +static STM32_GATE(ck_ddrphycapblp, &ck_pclk4, 0, GATE_DDRPHYCAPBLP); +static STM32_GATE(ck_syscfg, &ck_pclk3, 0, GATE_SYSCFG); +static STM32_GATE(ck_ddrperfm, &ck_pclk4, 0, GATE_DDRPERFM); +static STM32_GATE(ck_iwdg2, &ck_pclk4, 0, GATE_IWDG2APB); +static STM32_GATE(ck_rtcapb, &ck_pclk5, 0, GATE_RTCAPB); +static STM32_GATE(ck_tzc, &ck_pclk5, 0, GATE_TZC); +static STM32_GATE(ck_etzpcb, &ck_pclk5, 0, GATE_ETZPC); +static STM32_GATE(ck_iwdg1apb, &ck_pclk5, 0, GATE_IWDG1APB); +static STM32_GATE(ck_bsec, &ck_pclk5, 0, GATE_BSEC); +static STM32_GATE(ck_tim12_k, &ck_timg3, 0, GATE_TIM12); +static STM32_GATE(ck_tim15_k, &ck_timg3, 0, GATE_TIM15); +static STM32_GATE(ck_gpioa, &ck_mlahb, 0, GATE_GPIOA); +static STM32_GATE(ck_gpiob, &ck_mlahb, 0, GATE_GPIOB); +static STM32_GATE(ck_gpioc, &ck_mlahb, 0, GATE_GPIOC); +static STM32_GATE(ck_gpiod, &ck_mlahb, 0, GATE_GPIOD); +static STM32_GATE(ck_gpioe, &ck_mlahb, 0, GATE_GPIOE); +static STM32_GATE(ck_gpiof, &ck_mlahb, 0, GATE_GPIOF); +static STM32_GATE(ck_gpiog, &ck_mlahb, 0, GATE_GPIOG); +static STM32_GATE(ck_gpioh, &ck_mlahb, 0, GATE_GPIOH); +static STM32_GATE(ck_gpioi, &ck_mlahb, 0, GATE_GPIOI); +static STM32_GATE(ck_pka, &ck_axi, 0, GATE_PKA); +static STM32_GATE(ck_cryp1, &ck_pclk5, 0, GATE_CRYP1); +static STM32_GATE(ck_hash1, &ck_pclk5, 0, GATE_HASH1); +static STM32_GATE(ck_bkpsram, &ck_pclk5, 0, GATE_BKPSRAM); +static STM32_GATE(ck_dbg, &ck_axi, 0, GATE_DBGCK); +static STM32_GATE(ck_mce, &ck_axi, 0, GATE_MCE); +static STM32_GATE(ck_tim2_k, &ck_timg1, 0, GATE_TIM2); +static STM32_GATE(ck_tim3_k, &ck_timg1, 0, GATE_TIM3); +static STM32_GATE(ck_tim4_k, &ck_timg1, 0, GATE_TIM4); +static STM32_GATE(ck_tim5_k, &ck_timg1, 0, GATE_TIM5); +static STM32_GATE(ck_tim6_k, &ck_timg1, 0, GATE_TIM6); +static STM32_GATE(ck_tim7_k, &ck_timg1, 0, GATE_TIM7); +static STM32_GATE(ck_tim13_k, &ck_timg3, 0, GATE_TIM13); +static STM32_GATE(ck_tim14_k, &ck_timg3, 0, GATE_TIM14); +static STM32_GATE(ck_tim1_k, &ck_timg2, 0, GATE_TIM1); +static STM32_GATE(ck_tim8_k, &ck_timg2, 0, GATE_TIM8); +static STM32_GATE(ck_tim16_k, &ck_timg3, 0, GATE_TIM16); +static STM32_GATE(ck_tim17_k, &ck_timg3, 0, GATE_TIM17); +static STM32_GATE(ck_ltdc_px, &ck_pll4q, 0, GATE_LTDC); +static STM32_GATE(ck_dma1, &ck_mlahb, 0, GATE_DMA1); +static STM32_GATE(ck_dma2, &ck_mlahb, 0, GATE_DMA2); +static STM32_GATE(ck_mdma, &ck_axi, 0, GATE_MDMA); +static STM32_GATE(ck_eth1mac, &ck_axi, 0, GATE_ETH1MAC); +static STM32_GATE(ck_usbh, &ck_axi, 0, GATE_USBH); +static STM32_GATE(ck_vref, &ck_pclk3, 0, GATE_VREF); +static STM32_GATE(ck_tmpsens, &ck_pclk3, 0, GATE_DTS); +static STM32_GATE(ck_pmbctrl, &ck_pclk3, 0, GATE_HDP); +static STM32_GATE(ck_hdp, &ck_pclk3, 0, GATE_PMBCTRL); +static STM32_GATE(ck_stgenro, &ck_pclk4, 0, GATE_DCMIPP); +static STM32_GATE(ck_dmamux1, &ck_axi, 0, GATE_DMAMUX1); +static STM32_GATE(ck_dmamux2, &ck_axi, 0, GATE_DMAMUX2); +static STM32_GATE(ck_dma3, &ck_axi, 0, GATE_DMAMUX2); +static STM32_GATE(ck_tsc, &ck_axi, 0, GATE_TSC); +static STM32_GATE(ck_aximc, &ck_axi, 0, GATE_AXIMC); +static STM32_GATE(ck_crc1, &ck_axi, 0, GATE_ETH1TX); +static STM32_GATE(ck_eth1tx, &ck_axi, 0, GATE_ETH1TX); +static STM32_GATE(ck_eth1rx, &ck_axi, 0, GATE_ETH1RX); +static STM32_GATE(ck_eth2tx, &ck_axi, 0, GATE_ETH2TX); +static STM32_GATE(ck_eth2rx, &ck_axi, 0, GATE_ETH2RX); +static STM32_GATE(ck_eth2mac, &ck_axi, 0, GATE_ETH2MAC); + +/* Kernel Clocks */ +static STM32_KCLK(ck_usbphy_k, 3, + PARENT(&ck_hse, &ck_pll4r, &ck_hse_div2), + 0, GATE_USBPHY, MUX_USBPHY); + +static STM32_KCLK(ck_usbo_k, 2, + PARENT(&ck_pll4r, &ck_usb_phy_48Mhz), 0, + GATE_USBO, MUX_USBO); + +static STM32_KCLK(ck_stgen_k, 2, + PARENT(&ck_hsi, &ck_hse), 0, GATE_STGENC, MUX_STGEN); + +static STM32_KCLK(ck_usart1_k, 6, + PARENT(&ck_pclk6, &ck_pll3q, &ck_hsi, + &ck_csi, &ck_pll4q, &ck_hse), + 0, GATE_USART1, MUX_UART1); + +static STM32_KCLK(ck_usart2_k, 6, + PARENT(&ck_pclk6, &ck_pll3q, &ck_hsi, &ck_csi, &ck_pll4q, + &ck_hse), + 0, GATE_USART2, MUX_UART2); + +static STM32_KCLK(ck_i2c4_k, 4, + PARENT(&ck_pclk6, &ck_pll4r, &ck_hsi, &ck_csi), + 0, GATE_I2C4, MUX_I2C4); + +static STM32_KCLK(ck_rtc, 4, + PARENT(&ck_off, &ck_lse, &ck_lsi, &ck_hse), + 0, GATE_RTCCK, MUX_RTC); + +static STM32_KCLK(ck_saes_k, 4, + PARENT(&ck_axi, &ck_per, &ck_pll4r, &ck_lsi), + 0, GATE_SAES, MUX_SAES); + +static STM32_KCLK(ck_rng1_k, 4, + PARENT(&ck_csi, &ck_pll4r, &ck_lse, &ck_lsi), + 0, GATE_RNG1, MUX_RNG1); + +static STM32_KCLK(ck_sdmmc1_k, 4, + PARENT(&ck_axi, &ck_pll3r, &ck_pll4p, &ck_hsi), + 0, GATE_SDMMC1, MUX_SDMMC1); + +static STM32_KCLK(ck_sdmmc2_k, 4, + PARENT(&ck_axi, &ck_pll3r, &ck_pll4p, &ck_hsi), + 0, GATE_SDMMC2, MUX_SDMMC2); + +static STM32_KCLK(ck_usart3_k, 5, + PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), + 0, GATE_USART3, MUX_UART35); + +static STM32_KCLK(ck_uart4_k, 5, + PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), + 0, GATE_UART4, MUX_UART4); + +static STM32_KCLK(ck_uart5_k, 5, + PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), + 0, GATE_UART5, MUX_UART35); + +static STM32_KCLK(ck_uart7_k, 5, + PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), + 0, GATE_UART7, MUX_UART78); + +static STM32_KCLK(ck_uart8_k, 5, + PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), + 0, GATE_UART8, MUX_UART78); + +static STM32_KCLK(ck_usart6_k, 5, + PARENT(&ck_pclk2, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), + 0, GATE_USART6, MUX_UART6); + +static STM32_KCLK(ck_fmc_k, 4, + PARENT(&ck_axi, &ck_pll3r, &ck_pll4p, &ck_per), + 0, GATE_FMC, MUX_FMC); + +static STM32_KCLK(ck_qspi_k, 4, + PARENT(&ck_axi, &ck_pll3r, &ck_pll4p, &ck_per), + 0, GATE_QSPI, MUX_QSPI); + +static STM32_KCLK(ck_lptim1_k, 6, + PARENT(&ck_pclk1, &ck_pll4p, &ck_pll3q, &ck_lse, &ck_lsi, + &ck_per), + 0, GATE_LPTIM1, MUX_LPTIM1); + +static STM32_KCLK(ck_spi2_k, 5, + PARENT(&ck_pll4p, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), + 0, GATE_SPI2, MUX_SPI23); + +static STM32_KCLK(ck_spi3_k, 5, + PARENT(&ck_pll4p, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), + 0, GATE_SPI3, MUX_SPI23); + +static STM32_KCLK(ck_spdif_k, 3, + PARENT(&ck_pll4p, &ck_pll3q, &ck_hsi), + 0, GATE_SPDIF, MUX_SPDIF); + +static STM32_KCLK(ck_spi1_k, 5, + PARENT(&ck_pll4p, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), + 0, GATE_SPI1, MUX_SPI1); + +static STM32_KCLK(ck_spi4_k, 6, + PARENT(&ck_pclk6, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse, + &ck_i2sckin), + 0, GATE_SPI4, MUX_SPI4); + +static STM32_KCLK(ck_spi5_k, 5, + PARENT(&ck_pclk6, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), + 0, GATE_SPI5, MUX_SPI5); + +static STM32_KCLK(ck_sai1_k, 5, + PARENT(&ck_pll4q, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), + 0, GATE_SAI1, MUX_SAI1); + +static STM32_KCLK(ck_sai2_k, 6, + PARENT(&ck_pll4q, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_off, + &ck_pll3r), + 0, GATE_SAI2, MUX_SAI2); + +static STM32_KCLK(ck_dfsdm_k, 5, + PARENT(&ck_pll4q, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), + 0, GATE_DFSDM, MUX_SAI1); + +static STM32_KCLK(ck_fdcan_k, 4, + PARENT(&ck_hse, &ck_pll3q, &ck_pll4q, &ck_pll4r), + 0, GATE_FDCAN, MUX_FDCAN); + +static STM32_KCLK(ck_i2c1_k, 4, + PARENT(&ck_pclk1, &ck_pll4r, &ck_hsi, &ck_csi), + 0, GATE_I2C1, MUX_I2C12); + +static STM32_KCLK(ck_i2c2_k, 4, + PARENT(&ck_pclk1, &ck_pll4r, &ck_hsi, &ck_csi), + 0, GATE_I2C2, MUX_I2C12); + +static STM32_KCLK(ck_adfsdm_k, 5, + PARENT(&ck_pll4q, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), + 0, GATE_ADFSDM, MUX_SAI1); + +static STM32_KCLK(ck_lptim2_k, 5, + PARENT(&ck_pclk3, &ck_pll4q, &ck_per, &ck_lse, &ck_lsi), + 0, GATE_LPTIM2, MUX_LPTIM2); + +static STM32_KCLK(ck_lptim3_k, 5, + PARENT(&ck_pclk3, &ck_pll4q, &ck_per, &ck_lse, &ck_lsi), + 0, GATE_LPTIM3, MUX_LPTIM3); + +static STM32_KCLK(ck_lptim4_k, 6, + PARENT(&ck_pclk3, &ck_pll4p, &ck_pll3q, &ck_lse, &ck_lsi, + &ck_per), + 0, GATE_LPTIM4, MUX_LPTIM45); + +static STM32_KCLK(ck_lptim5_k, 6, + PARENT(&ck_pclk3, &ck_pll4p, &ck_pll3q, &ck_lse, &ck_lsi, + &ck_per), + 0, GATE_LPTIM5, MUX_LPTIM45); + +static STM32_KCLK(ck_i2c3_k, 4, + PARENT(&ck_pclk6, &ck_pll4r, &ck_hsi, &ck_csi), + 0, GATE_I2C3, MUX_I2C3); + +static STM32_KCLK(ck_i2c5_k, 4, + PARENT(&ck_pclk6, &ck_pll4r, &ck_hsi, &ck_csi), + 0, GATE_I2C5, MUX_I2C5); + +static STM32_KCLK(ck_dcmipp_k, 4, + PARENT(&ck_axi, &ck_pll2q, &ck_pll4p, &ck_per), + 0, GATE_DCMIPP, MUX_DCMIPP); + +static STM32_KCLK(ck_adc1_k, 3, PARENT(&ck_pll4r, &ck_per, &ck_pll3q), + 0, GATE_ADC1, MUX_ADC1); + +static STM32_KCLK(ck_adc2_k, 3, PARENT(&ck_pll4r, &ck_per, &ck_pll3q), + 0, GATE_ADC2, MUX_ADC2); + +static STM32_KCLK(ck_eth1ck_k, 2, PARENT(&ck_pll4p, &ck_pll3q), + 0, GATE_ETH1CK, MUX_ETH1); + +static STM32_KCLK(ck_eth2ck_k, 2, PARENT(&ck_pll4p, &ck_pll3q), + 0, GATE_ETH2CK, MUX_ETH2); + +static STM32_COMPOSITE(ck_mco1, 5, + PARENT(&ck_hsi, &ck_hse, &ck_csi, &ck_lsi, &ck_lse), + 0, GATE_MCO1, DIV_MCO1, MUX_MCO1); + +static STM32_COMPOSITE(ck_mco2, 6, + PARENT(&ck_mpu, &ck_axi, &ck_mlahb, + &ck_pll4p, &ck_hse, &ck_hsi), + 0, GATE_MCO2, DIV_MCO2, MUX_MCO2); + +static STM32_COMPOSITE(ck_trace, 1, PARENT(&ck_axi), + 0, GATE_TRACECK, DIV_TRACE, NO_MUX); + +enum { + USB_PHY_48 = STM32MP1_LAST_CLK, + PLL1P_DIV, + CK_OFF, + I2S_CKIN, + STM32MP13_ALL_CLK_NB +}; + +static struct clk *stm32mp13_clk_provided[STM32MP13_ALL_CLK_NB] = { + [CK_HSE] = &ck_hse, + [CK_CSI] = &ck_csi, + [CK_LSI] = &ck_lsi, + [CK_LSE] = &ck_lse, + [CK_HSI] = &ck_hsi, + [CK_HSE_DIV2] = &ck_hse_div2, + [PLL1] = &ck_pll1_vco, + [PLL2] = &ck_pll2_vco, + [PLL3] = &ck_pll3_vco, + [PLL4] = &ck_pll4_vco, + [PLL1_P] = &ck_pll1p, + [PLL2_P] = &ck_pll2p, + [PLL2_Q] = &ck_pll2q, + [PLL2_R] = &ck_pll2r, + [PLL3_P] = &ck_pll3p, + [PLL3_Q] = &ck_pll3q, + [PLL3_R] = &ck_pll3r, + [PLL4_P] = &ck_pll4p, + [PLL4_Q] = &ck_pll4q, + [PLL4_R] = &ck_pll4r, + [PLL1P_DIV] = &ck_pll1p_div, + [CK_MPU] = &ck_mpu, + [CK_AXI] = &ck_axi, + [CK_MLAHB] = &ck_mlahb, + [CK_PER] = &ck_per, + [PCLK1] = &ck_pclk1, + [PCLK2] = &ck_pclk2, + [PCLK3] = &ck_pclk3, + [PCLK4] = &ck_pclk4, + [PCLK5] = &ck_pclk5, + [PCLK6] = &ck_pclk6, + [CK_TIMG1] = &ck_timg1, + [CK_TIMG2] = &ck_timg2, + [CK_TIMG3] = &ck_timg3, + [DDRC1] = &ck_ddrc1, + [DDRC1LP] = &ck_ddrc1lp, + [DDRPHYC] = &ck_ddrphyc, + [DDRPHYCLP] = &ck_ddrphyclp, + [DDRCAPB] = &ck_ddrcapb, + [DDRCAPBLP] = &ck_ddrcapblp, + [AXIDCG] = &ck_axidcg, + [DDRPHYCAPB] = &ck_ddrphycapb, + [DDRPHYCAPBLP] = &ck_ddrphycapblp, + [SYSCFG] = &ck_syscfg, + [DDRPERFM] = &ck_ddrperfm, + [IWDG2] = &ck_iwdg2, + [USBPHY_K] = &ck_usbphy_k, + [USBO_K] = &ck_usbo_k, + [RTCAPB] = &ck_rtcapb, + [TZC] = &ck_tzc, + [TZPC] = &ck_etzpcb, + [IWDG1] = &ck_iwdg1apb, + [BSEC] = &ck_bsec, + [STGEN_K] = &ck_stgen_k, + [USART1_K] = &ck_usart1_k, + [USART2_K] = &ck_usart2_k, + [I2C4_K] = &ck_i2c4_k, + [TIM12_K] = &ck_tim12_k, + [TIM15_K] = &ck_tim15_k, + [RTC] = &ck_rtc, + [GPIOA] = &ck_gpioa, + [GPIOB] = &ck_gpiob, + [GPIOC] = &ck_gpioc, + [GPIOD] = &ck_gpiod, + [GPIOE] = &ck_gpioe, + [GPIOF] = &ck_gpiof, + [GPIOG] = &ck_gpiog, + [GPIOH] = &ck_gpioh, + [GPIOI] = &ck_gpioi, + [PKA] = &ck_pka, + [SAES_K] = &ck_saes_k, + [CRYP1] = &ck_cryp1, + [HASH1] = &ck_hash1, + [RNG1_K] = &ck_rng1_k, + [BKPSRAM] = &ck_bkpsram, + [SDMMC1_K] = &ck_sdmmc1_k, + [SDMMC2_K] = &ck_sdmmc2_k, + [CK_DBG] = &ck_dbg, + [MCE] = &ck_mce, + [TIM2_K] = &ck_tim2_k, + [TIM3_K] = &ck_tim3_k, + [TIM4_K] = &ck_tim4_k, + [TIM5_K] = &ck_tim5_k, + [TIM6_K] = &ck_tim6_k, + [TIM7_K] = &ck_tim7_k, + [TIM13_K] = &ck_tim13_k, + [TIM14_K] = &ck_tim14_k, + [TIM1_K] = &ck_tim1_k, + [TIM8_K] = &ck_tim8_k, + [TIM16_K] = &ck_tim16_k, + [TIM17_K] = &ck_tim17_k, + [LTDC_PX] = &ck_ltdc_px, + [DMA1] = &ck_dma1, + [DMA2] = &ck_dma2, + [MDMA] = &ck_mdma, + [ETH1MAC] = &ck_eth1mac, + [USBH] = &ck_usbh, + [VREF] = &ck_vref, + [TMPSENS] = &ck_tmpsens, + [PMBCTRL] = &ck_pmbctrl, + [HDP] = &ck_hdp, + [STGENRO] = &ck_stgenro, + [DMAMUX1] = &ck_dmamux1, + [DMAMUX2] = &ck_dmamux2, + [DMA3] = &ck_dma3, + [TSC] = &ck_tsc, + [AXIMC] = &ck_aximc, + [CRC1] = &ck_crc1, + [ETH1TX] = &ck_eth1tx, + [ETH1RX] = &ck_eth1rx, + [ETH2TX] = &ck_eth2tx, + [ETH2RX] = &ck_eth2rx, + [ETH2MAC] = &ck_eth2mac, + [USART3_K] = &ck_usart3_k, + [UART4_K] = &ck_uart4_k, + [UART5_K] = &ck_uart5_k, + [UART7_K] = &ck_uart7_k, + [UART8_K] = &ck_uart8_k, + [USART6_K] = &ck_usart6_k, + [FMC_K] = &ck_fmc_k, + [QSPI_K] = &ck_qspi_k, + [LPTIM1_K] = &ck_lptim1_k, + [SPI2_K] = &ck_spi2_k, + [SPI3_K] = &ck_spi3_k, + [SPDIF_K] = &ck_spdif_k, + [SPI1_K] = &ck_spi1_k, + [SPI4_K] = &ck_spi4_k, + [SPI5_K] = &ck_spi5_k, + [SAI1_K] = &ck_sai1_k, + [SAI2_K] = &ck_sai2_k, + [DFSDM_K] = &ck_dfsdm_k, + [FDCAN_K] = &ck_fdcan_k, + [I2C1_K] = &ck_i2c1_k, + [I2C2_K] = &ck_i2c2_k, + [ADFSDM_K] = &ck_adfsdm_k, + [LPTIM2_K] = &ck_lptim2_k, + [LPTIM3_K] = &ck_lptim3_k, + [LPTIM4_K] = &ck_lptim4_k, + [LPTIM5_K] = &ck_lptim5_k, + [I2C3_K] = &ck_i2c3_k, + [I2C5_K] = &ck_i2c5_k, + [DCMIPP_K] = &ck_dcmipp_k, + [ADC1_K] = &ck_adc1_k, + [ADC2_K] = &ck_adc2_k, + [ETH1CK_K] = &ck_eth1ck_k, + [ETH2CK_K] = &ck_eth2ck_k, + [CK_MCO1] = &ck_mco1, + [CK_MCO2] = &ck_mco2, + [CK_TRACE] = &ck_trace, + [CK_OFF] = &ck_off, + [USB_PHY_48] = &ck_usb_phy_48Mhz, + [I2S_CKIN] = &ck_i2sckin, +}; + +static bool clk_stm32_clock_is_critical(struct clk *clk __maybe_unused) +{ + struct clk *clk_criticals[] = { + &ck_hsi, + &ck_hse, + &ck_csi, + &ck_lsi, + &ck_lse, + &ck_pll2r, + &ck_mpu, + &ck_ddrc1, + &ck_ddrc1lp, + &ck_ddrphyc, + &ck_ddrphyclp, + &ck_ddrcapb, + &ck_ddrcapblp, + &ck_axidcg, + &ck_ddrphycapb, + &ck_ddrphycapblp, + &ck_rtcapb, + &ck_tzc, + &ck_etzpcb, + &ck_iwdg1apb, + &ck_bsec, + &ck_stgen_k, + &ck_bkpsram, + &ck_mce, + &ck_mco1, + &ck_rng1_k, + &ck_mlahb, + }; + size_t i = 0; + + for (i = 0; i < ARRAY_SIZE(clk_criticals); i++) { + struct clk *clk_critical = clk_criticals[i]; + + if (clk == clk_critical) + return true; + } + + return false; +} + +static void clk_stm32_init_oscillators(const void *fdt, int node) +{ + size_t i = 0; + const char *name[6] = { "clk-hse", "clk-hsi", "clk-lse", + "clk-lsi", "clk-csi", "clk-i2sin" }; + struct clk *clks[6] = { &ck_hse, &ck_hsi, &ck_lse, + &ck_lsi, &ck_csi, &ck_i2sckin }; + + for (i = 0; i < ARRAY_SIZE(clks); i++) { + struct clk *clk = NULL; + + clk_dt_get_by_name(fdt, node, name[i], &clk); + + clks[i]->parents[0] = clk; + } +} + +static struct stm32_pll_dt_cfg mp13_pll[PLL_NB]; +static struct stm32_clk_opp_dt_cfg mp13_clk_opp; +static struct stm32_osci_dt_cfg mp13_osci[NB_OSCILLATOR]; +static uint32_t mp13_clksrc[MUX_NB]; +static uint32_t mp13_clkdiv[DIV_NB]; + +static struct stm32_clk_platdata stm32mp13_clock_pdata = { + .osci = mp13_osci, + .nosci = NB_OSCILLATOR, + .pll = mp13_pll, + .opp = &mp13_clk_opp, + .npll = PLL_NB, + .clksrc = mp13_clksrc, + .nclksrc = MUX_NB, + .clkdiv = mp13_clkdiv, + .nclkdiv = DIV_NB, +}; + +static struct clk_stm32_priv stm32mp13_clock_data = { + .muxes = parent_mp13, + .nb_muxes = ARRAY_SIZE(parent_mp13), + .gates = gates_mp13, + .nb_gates = ARRAY_SIZE(gates_mp13), + .div = dividers_mp13, + .nb_div = ARRAY_SIZE(dividers_mp13), + .pdata = &stm32mp13_clock_pdata, + .nb_clk_refs = STM32MP13_ALL_CLK_NB, + .clk_refs = stm32mp13_clk_provided, + .is_critical = clk_stm32_clock_is_critical, +}; + +static TEE_Result stm32mp13_clk_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int fdt_rc = 0; + int rc = 0; + struct clk_stm32_priv *priv = &stm32mp13_clock_data; + struct stm32_clk_platdata *pdata = &stm32mp13_clock_pdata; + + fdt_rc = stm32_clk_parse_fdt(fdt, node, pdata); + if (fdt_rc) { + EMSG("Failed to parse clock node: %d", fdt_rc); + return TEE_ERROR_GENERIC; + } + + res = clk_stm32_init(priv, stm32_rcc_base()); + if (res) + return res; + + rc = stm32mp1_init_clock_tree(priv, pdata); + if (rc) + return TEE_ERROR_GENERIC; + + clk_stm32_init_oscillators(fdt, node); + + stm32mp_clk_provider_probe_final(fdt, node, priv); + + return TEE_SUCCESS; +} + +CLK_DT_DECLARE(stm32mp13_clk, "st,stm32mp13-rcc", stm32mp13_clk_probe); diff --git a/optee/optee_os/core/drivers/clk/clk-stm32mp15.c b/optee/optee_os/core/drivers/clk/clk-stm32mp15.c new file mode 100644 index 0000000..58432bb --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk-stm32mp15.c @@ -0,0 +1,1569 @@ +// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0+) +/* + * Copyright (C) 2018-2022, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Identifiers for root oscillators */ +enum stm32mp_osc_id { + OSC_HSI, + OSC_HSE, + OSC_CSI, + OSC_LSI, + OSC_LSE, + OSC_I2S_CKIN, + OSC_USB_PHY_48, + NB_OSC, + _UNKNOWN_OSC_ID = 0xffU +}; + +/* Identifiers for parent clocks */ +enum stm32mp1_parent_id { + _HSI, + _HSE, + _CSI, + _LSI, + _LSE, + _I2S_CKIN, + _USB_PHY_48, + _HSI_KER, + _HSE_KER, + _HSE_KER_DIV2, + _HSE_RTC, + _CSI_KER, + _PLL1_P, + _PLL1_Q, + _PLL1_R, + _PLL2_P, + _PLL2_Q, + _PLL2_R, + _PLL3_P, + _PLL3_Q, + _PLL3_R, + _PLL4_P, + _PLL4_Q, + _PLL4_R, + _ACLK, + _PCLK1, + _PCLK2, + _PCLK3, + _PCLK4, + _PCLK5, + _HCLK5, + _HCLK6, + _HCLK2, + _CK_PER, + _CK_MPU, + _CK_MCU, + _PARENT_NB, + _UNKNOWN_ID = 0xff, +}; + +/* + * Identifiers for parent clock selectors. + * This enum lists only the parent clocks we are interested in. + */ +enum stm32mp1_parent_sel { + _STGEN_SEL, + _I2C35_SEL, + _I2C46_SEL, + _SPI6_SEL, + _USART1_SEL, + _RNG1_SEL, + _UART6_SEL, + _UART24_SEL, + _UART35_SEL, + _UART78_SEL, + _AXISS_SEL, + _MCUSS_SEL, + _USBPHY_SEL, + _USBO_SEL, + _RTC_SEL, + _MPU_SEL, + _PARENT_SEL_NB, + _UNKNOWN_SEL = 0xff, +}; + +static const uint8_t parent_id_clock_id[_PARENT_NB] = { + [_HSE] = CK_HSE, + [_HSI] = CK_HSI, + [_CSI] = CK_CSI, + [_LSE] = CK_LSE, + [_LSI] = CK_LSI, + [_I2S_CKIN] = _UNKNOWN_ID, + [_USB_PHY_48] = _UNKNOWN_ID, + [_HSI_KER] = CK_HSI, + [_HSE_KER] = CK_HSE, + [_HSE_KER_DIV2] = CK_HSE_DIV2, + [_HSE_RTC] = _UNKNOWN_ID, + [_CSI_KER] = CK_CSI, + [_PLL1_P] = PLL1_P, + [_PLL1_Q] = PLL1_Q, + [_PLL1_R] = PLL1_R, + [_PLL2_P] = PLL2_P, + [_PLL2_Q] = PLL2_Q, + [_PLL2_R] = PLL2_R, + [_PLL3_P] = PLL3_P, + [_PLL3_Q] = PLL3_Q, + [_PLL3_R] = PLL3_R, + [_PLL4_P] = PLL4_P, + [_PLL4_Q] = PLL4_Q, + [_PLL4_R] = PLL4_R, + [_ACLK] = CK_AXI, + [_PCLK1] = CK_AXI, + [_PCLK2] = CK_AXI, + [_PCLK3] = CK_AXI, + [_PCLK4] = CK_AXI, + [_PCLK5] = CK_AXI, + [_HCLK5] = CK_AXI, + [_HCLK6] = CK_AXI, + [_HCLK2] = CK_AXI, + [_CK_PER] = CK_PER, + [_CK_MPU] = CK_MPU, + [_CK_MCU] = CK_MCU, +}; + +static enum stm32mp1_parent_id osc_id2parent_id(enum stm32mp_osc_id osc_id) +{ + assert(osc_id >= OSC_HSI && osc_id < NB_OSC); + COMPILE_TIME_ASSERT((int)OSC_HSI == (int)_HSI && + (int)OSC_HSE == (int)_HSE && + (int)OSC_CSI == (int)_CSI && + (int)OSC_LSI == (int)_LSI && + (int)OSC_LSE == (int)_LSE && + (int)OSC_I2S_CKIN == (int)_I2S_CKIN && + (int)OSC_USB_PHY_48 == (int)_USB_PHY_48); + + return (enum stm32mp1_parent_id)osc_id; +} + +static enum stm32mp1_parent_id clock_id2parent_id(unsigned long id) +{ + size_t n = 0; + + COMPILE_TIME_ASSERT(STM32MP1_LAST_CLK < _UNKNOWN_ID); + + for (n = 0; n < ARRAY_SIZE(parent_id_clock_id); n++) + if (parent_id_clock_id[n] == id) + return (enum stm32mp1_parent_id)n; + + return _UNKNOWN_ID; +} + +/* Identifiers for PLLs and their configuration resources */ +enum stm32mp1_pll_id { + _PLL1, + _PLL2, + _PLL3, + _PLL4, + _PLL_NB +}; + +enum stm32mp1_div_id { + _DIV_P, + _DIV_Q, + _DIV_R, + _DIV_NB, +}; + +enum stm32mp1_plltype { + PLL_800, + PLL_1600, + PLL_TYPE_NB +}; + +/* + * Clock generic gates clocks which state is controlled by a single RCC bit + * + * @offset: RCC register byte offset from RCC base where clock is controlled + * @bit: Bit position in the RCC 32bit register + * @clock_id: Identifier used for the clock in the clock driver API + * @set_clr: Non-null if and only-if RCC register is a CLEAR/SET register + * (CLEAR register is at offset RCC_MP_ENCLRR_OFFSET from SET register) + * @secure: One of N_S or SEC, defined below + * @sel: _UNKNOWN_ID (fixed parent) or reference to parent clock selector + * (8bit storage of ID from enum stm32mp1_parent_sel) + * @fixed: _UNKNOWN_ID (selectable paranet) or reference to parent clock + * (8bit storage of ID from enum stm32mp1_parent_id) + */ +struct stm32mp1_clk_gate { + uint16_t offset; + uint8_t bit; + uint8_t clock_id; + uint8_t set_clr; + uint8_t secure; + uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ + uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ +}; + +/* Parent clock selection: select register info, parent clocks references */ +struct stm32mp1_clk_sel { + uint16_t offset; + uint8_t src; + uint8_t msk; + uint8_t nb_parent; + const uint8_t *parent; +}; + +#define REFCLK_SIZE 4 +/* PLL control: type, control register offsets, up-to-4 selectable parent */ +struct stm32mp1_clk_pll { + enum stm32mp1_plltype plltype; + uint16_t rckxselr; + uint16_t pllxcfgr1; + uint16_t pllxcfgr2; + uint16_t pllxfracr; + uint16_t pllxcr; + uint16_t pllxcsgr; + enum stm32mp_osc_id refclk[REFCLK_SIZE]; +}; + +#define N_S 0 /* Non-secure can access RCC interface */ +#define SEC 1 /* RCC[TZEN] protects RCC interface */ + +/* Clocks with selectable source and not set/clr register access */ +#define _CLK_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ + { \ + .offset = (_offset), \ + .bit = (_bit), \ + .clock_id = (_clock_id), \ + .set_clr = 0, \ + .secure = (_sec), \ + .sel = (_parent_sel), \ + .fixed = _UNKNOWN_ID, \ + } + +/* Clocks with fixed source and not set/clr register access */ +#define _CLK_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ + { \ + .offset = (_offset), \ + .bit = (_bit), \ + .clock_id = (_clock_id), \ + .set_clr = 0, \ + .secure = (_sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (_parent), \ + } + +/* Clocks with selectable source and set/clr register access */ +#define _CLK_SC_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ + { \ + .offset = (_offset), \ + .bit = (_bit), \ + .clock_id = (_clock_id), \ + .set_clr = 1, \ + .secure = (_sec), \ + .sel = (_parent_sel), \ + .fixed = _UNKNOWN_ID, \ + } + +/* Clocks with fixed source and set/clr register access */ +#define _CLK_SC_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ + { \ + .offset = (_offset), \ + .bit = (_bit), \ + .clock_id = (_clock_id), \ + .set_clr = 1, \ + .secure = (_sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (_parent), \ + } + +/* + * Clocks with selectable source and set/clr register access + * and enable bit position defined by a label (argument _bit) + */ +#define _CLK_SC2_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ + { \ + .offset = (_offset), \ + .clock_id = (_clock_id), \ + .bit = _offset ## _ ## _bit ## _POS, \ + .set_clr = 1, \ + .secure = (_sec), \ + .sel = (_parent_sel), \ + .fixed = _UNKNOWN_ID, \ + } +#define _CLK_SC2_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ + { \ + .offset = (_offset), \ + .clock_id = (_clock_id), \ + .bit = _offset ## _ ## _bit ## _POS, \ + .set_clr = 1, \ + .secure = (_sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (_parent), \ + } + +#define _CLK_PARENT(idx, _offset, _src, _mask, _parent) \ + [(idx)] = { \ + .offset = (_offset), \ + .src = (_src), \ + .msk = (_mask), \ + .parent = (_parent), \ + .nb_parent = ARRAY_SIZE(_parent) \ + } + +#define _CLK_PLL(_idx, _type, _off1, _off2, _off3, _off4, \ + _off5, _off6, _p1, _p2, _p3, _p4) \ + [(_idx)] = { \ + .plltype = (_type), \ + .rckxselr = (_off1), \ + .pllxcfgr1 = (_off2), \ + .pllxcfgr2 = (_off3), \ + .pllxfracr = (_off4), \ + .pllxcr = (_off5), \ + .pllxcsgr = (_off6), \ + .refclk[0] = (_p1), \ + .refclk[1] = (_p2), \ + .refclk[2] = (_p3), \ + .refclk[3] = (_p4), \ + } + +#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) + +static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { + _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), + _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), + _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), + + _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, SPI6EN, SPI6_K, _SPI6_SEL), + _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, I2C4EN, I2C4_K, _I2C46_SEL), + _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, I2C6EN, I2C6_K, _I2C46_SEL), + _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, USART1EN, USART1_K, _USART1_SEL), + _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, RTCAPBEN, RTCAPB, _PCLK5), + _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZC1EN, TZC1, _PCLK5), + _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZC2EN, TZC2, _PCLK5), + _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZPCEN, TZPC, _PCLK5), + _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, IWDG1APBEN, IWDG1, _PCLK5), + _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, BSECEN, BSEC, _PCLK5), + _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, STGENEN, STGEN_K, _STGEN_SEL), + + _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, GPIOZEN, GPIOZ, _HCLK5), + _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, CRYP1EN, CRYP1, _HCLK5), + _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, HASH1EN, HASH1, _HCLK5), + _CLK_SC2_SELEC(SEC, RCC_MP_AHB5ENSETR, RNG1EN, RNG1_K, _RNG1_SEL), + _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, BKPSRAMEN, BKPSRAM, _HCLK5), + + _CLK_SC2_FIXED(SEC, RCC_MP_TZAHB6ENSETR, MDMA, MDMA, _HCLK6), + + _CLK_SELEC(SEC, RCC_BDCR, RCC_BDCR_RTCCKEN_POS, RTC, _RTC_SEL), + + /* Non-secure clocks */ +#ifdef CFG_WITH_NSEC_I2CS + _CLK_SC2_SELEC(N_S, RCC_MP_APB1ENSETR, I2C5EN, I2C5_K, _I2C35_SEL), +#endif + +#ifdef CFG_WITH_NSEC_GPIOS + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_ID), + _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_ID), +#endif + _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), +#ifdef CFG_WITH_NSEC_UARTS + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), +#endif + _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), +#ifdef CFG_WITH_NSEC_UARTS + _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), +#endif + _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), + + _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), +}; +DECLARE_KEEP_PAGER(stm32mp1_clk_gate); + +const uint8_t stm32mp1_clk_on[] = { + CK_HSE, CK_CSI, CK_LSI, CK_LSE, CK_HSI, CK_HSE_DIV2, + PLL1_P, PLL1_Q, PLL1_R, PLL2_P, PLL2_Q, PLL2_R, PLL3_P, PLL3_Q, PLL3_R, + CK_AXI, CK_MPU, CK_MCU, +}; + +/* Parents for secure aware clocks in the xxxSELR value ordering */ +static const uint8_t stgen_parents[] = { + _HSI_KER, _HSE_KER +}; + +#ifdef CFG_WITH_NSEC_I2CS +static const uint8_t i2c35_parents[] = { + _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER +}; +#endif + +static const uint8_t i2c46_parents[] = { + _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER +}; + +static const uint8_t spi6_parents[] = { + _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q +}; + +static const uint8_t usart1_parents[] = { + _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER +}; + +static const uint8_t rng1_parents[] = { + _CSI, _PLL4_R, _LSE, _LSI +}; + +static const uint8_t mpu_parents[] = { + _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ +}; + +/* Parents for (some) non-secure clocks */ +#ifdef CFG_WITH_NSEC_UARTS +static const uint8_t uart6_parents[] = { + _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER +}; + +static const uint8_t uart234578_parents[] = { + _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER +}; +#endif + +static const uint8_t axiss_parents[] = { + _HSI, _HSE, _PLL2_P +}; + +static const uint8_t mcuss_parents[] = { + _HSI, _HSE, _CSI, _PLL3_P +}; + +static const uint8_t rtc_parents[] = { + _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC +}; + +static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + /* Secure aware clocks */ + _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), + _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), + _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents), + _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents), + _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents), + _CLK_PARENT(_RTC_SEL, RCC_BDCR, 16, 0x3, rtc_parents), + _CLK_PARENT(_MPU_SEL, RCC_MPCKSELR, 0, 0x3, mpu_parents), + /* Always non-secure clocks (maybe used in some way in secure world) */ +#ifdef CFG_WITH_NSEC_I2CS + _CLK_PARENT(_I2C35_SEL, RCC_I2C35CKSELR, 0, 0x7, i2c35_parents), +#endif +#ifdef CFG_WITH_NSEC_UARTS + _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), + _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents), + _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), + _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), +#endif + _CLK_PARENT(_AXISS_SEL, RCC_ASSCKSELR, 0, 0x3, axiss_parents), + _CLK_PARENT(_MCUSS_SEL, RCC_MSSCKSELR, 0, 0x3, mcuss_parents), +}; + +/* PLLNCFGR2 register divider by output */ +static const uint8_t pllncfgr2[_DIV_NB] = { + [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, + [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, + [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, +}; + +static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { + _CLK_PLL(_PLL1, PLL_1600, + RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, + RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, + OSC_HSI, OSC_HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL2, PLL_1600, + RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, + RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, + OSC_HSI, OSC_HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL3, PLL_800, + RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, + RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, + OSC_HSI, OSC_HSE, OSC_CSI, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL4, PLL_800, + RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, + RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, + OSC_HSI, OSC_HSE, OSC_CSI, OSC_I2S_CKIN), +}; + +/* Prescaler table lookups for clock computation */ +/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ +static const uint8_t stm32mp1_mcu_div[16] = { + 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ +#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div +#define stm32mp1_apbx_div stm32mp1_mpu_apbx_div +static const uint8_t stm32mp1_mpu_apbx_div[8] = { + 0, 1, 2, 3, 4, 4, 4, 4 +}; + +/* div = /1 /2 /3 /4 */ +static const uint8_t stm32mp1_axi_div[8] = { + 1, 2, 3, 4, 4, 4, 4, 4 +}; + +static const char __maybe_unused *const stm32mp1_clk_parent_name[_PARENT_NB] = { + [_HSI] = "HSI", + [_HSE] = "HSE", + [_CSI] = "CSI", + [_LSI] = "LSI", + [_LSE] = "LSE", + [_I2S_CKIN] = "I2S_CKIN", + [_HSI_KER] = "HSI_KER", + [_HSE_KER] = "HSE_KER", + [_HSE_KER_DIV2] = "HSE_KER_DIV2", + [_HSE_RTC] = "HSE_RTC", + [_CSI_KER] = "CSI_KER", + [_PLL1_P] = "PLL1_P", + [_PLL1_Q] = "PLL1_Q", + [_PLL1_R] = "PLL1_R", + [_PLL2_P] = "PLL2_P", + [_PLL2_Q] = "PLL2_Q", + [_PLL2_R] = "PLL2_R", + [_PLL3_P] = "PLL3_P", + [_PLL3_Q] = "PLL3_Q", + [_PLL3_R] = "PLL3_R", + [_PLL4_P] = "PLL4_P", + [_PLL4_Q] = "PLL4_Q", + [_PLL4_R] = "PLL4_R", + [_ACLK] = "ACLK", + [_PCLK1] = "PCLK1", + [_PCLK2] = "PCLK2", + [_PCLK3] = "PCLK3", + [_PCLK4] = "PCLK4", + [_PCLK5] = "PCLK5", + [_HCLK2] = "HCLK2", + [_HCLK5] = "HCLK5", + [_HCLK6] = "HCLK6", + [_CK_PER] = "CK_PER", + [_CK_MPU] = "CK_MPU", + [_CK_MCU] = "CK_MCU", + [_USB_PHY_48] = "USB_PHY_48", +}; + +/* + * Oscillator frequency in Hz. This array shall be initialized + * according to platform. + */ +static unsigned long stm32mp1_osc[NB_OSC]; + +static unsigned long osc_frequency(enum stm32mp_osc_id idx) +{ + if (idx >= ARRAY_SIZE(stm32mp1_osc)) { + DMSG("clk id %d not found", idx); + return 0; + } + + return stm32mp1_osc[idx]; +} + +static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) +{ + return &stm32mp1_clk_gate[idx]; +} + +static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) +{ + return &stm32mp1_clk_sel[idx]; +} + +static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) +{ + return &stm32mp1_clk_pll[idx]; +} + +static int stm32mp1_clk_get_gated_id(unsigned long id) +{ + unsigned int i = 0; + + for (i = 0; i < NB_GATES; i++) + if (gate_ref(i)->clock_id == id) + return i; + + DMSG("clk id %lu not found", id); + return -1; +} + +static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) +{ + return (enum stm32mp1_parent_sel)gate_ref(i)->sel; +} + +static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) +{ + return (enum stm32mp1_parent_id)gate_ref(i)->fixed; +} + +static int stm32mp1_clk_get_parent(unsigned long id) +{ + const struct stm32mp1_clk_sel *sel = NULL; + enum stm32mp1_parent_id parent_id = 0; + uint32_t p_sel = 0; + int i = 0; + enum stm32mp1_parent_id p = _UNKNOWN_ID; + enum stm32mp1_parent_sel s = _UNKNOWN_SEL; + vaddr_t rcc_base = stm32_rcc_base(); + + parent_id = clock_id2parent_id(id); + if (parent_id != _UNKNOWN_ID) + return (int)parent_id; + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) + panic(); + + p = stm32mp1_clk_get_fixed_parent(i); + if (p < _PARENT_NB) + return (int)p; + + s = stm32mp1_clk_get_sel(i); + if (s == _UNKNOWN_SEL) + return -1; + if (s >= _PARENT_SEL_NB) + panic(); + + sel = clk_sel_ref(s); + p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) & sel->msk; + if (p_sel < sel->nb_parent) + return (int)sel->parent[p_sel]; + + DMSG("No parent selected for clk %lu", id); + return -1; +} + +static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) +{ + uint32_t selr = io_read32(stm32_rcc_base() + pll->rckxselr); + uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; + + return osc_frequency(pll->refclk[src]); +} + +/* + * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL + * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) + * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) + * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) + */ +static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) +{ + unsigned long refclk = 0; + unsigned long fvco = 0; + uint32_t cfgr1 = 0; + uint32_t fracr = 0; + uint32_t divm = 0; + uint32_t divn = 0; + + cfgr1 = io_read32(stm32_rcc_base() + pll->pllxcfgr1); + fracr = io_read32(stm32_rcc_base() + pll->pllxfracr); + + divm = (cfgr1 & RCC_PLLNCFGR1_DIVM_MASK) >> RCC_PLLNCFGR1_DIVM_SHIFT; + divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; + + refclk = stm32mp1_pll_get_fref(pll); + + /* + * With FRACV : + * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) + * Without FRACV + * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) + */ + if (fracr & RCC_PLLNFRACR_FRACLE) { + unsigned long long numerator = 0; + unsigned long long denominator = 0; + uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> + RCC_PLLNFRACR_FRACV_SHIFT; + + numerator = (((unsigned long long)divn + 1U) << 13) + fracv; + numerator = refclk * numerator; + denominator = ((unsigned long long)divm + 1U) << 13; + fvco = (unsigned long)(numerator / denominator); + } else { + fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); + } + + return fvco; +} + +static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, + enum stm32mp1_div_id div_id) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + unsigned long dfout = 0; + uint32_t cfgr2 = 0; + uint32_t divy = 0; + + if (div_id >= _DIV_NB) + return 0; + + cfgr2 = io_read32(stm32_rcc_base() + pll->pllxcfgr2); + divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; + + dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); + + return dfout; +} + +static unsigned long get_clock_rate(enum stm32mp1_parent_id p) +{ + uint32_t reg = 0; + unsigned long clock = 0; + vaddr_t rcc_base = stm32_rcc_base(); + + switch (p) { + case _CK_MPU: + /* MPU sub system */ + reg = io_read32(rcc_base + RCC_MPCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_MPCKSELR_HSI: + clock = osc_frequency(OSC_HSI); + break; + case RCC_MPCKSELR_HSE: + clock = osc_frequency(OSC_HSE); + break; + case RCC_MPCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); + break; + case RCC_MPCKSELR_PLL_MPUDIV: + reg = io_read32(rcc_base + RCC_MPCKDIVR); + if (reg & RCC_MPUDIV_MASK) + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P) >> + stm32mp1_mpu_div[reg & RCC_MPUDIV_MASK]; + else + clock = 0; + break; + default: + break; + } + break; + /* AXI sub system */ + case _ACLK: + case _HCLK2: + case _HCLK5: + case _HCLK6: + case _PCLK4: + case _PCLK5: + reg = io_read32(rcc_base + RCC_ASSCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_ASSCKSELR_HSI: + clock = osc_frequency(OSC_HSI); + break; + case RCC_ASSCKSELR_HSE: + clock = osc_frequency(OSC_HSE); + break; + case RCC_ASSCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); + break; + default: + break; + } + + /* System clock divider */ + reg = io_read32(rcc_base + RCC_AXIDIVR); + clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; + + switch (p) { + case _PCLK4: + reg = io_read32(rcc_base + RCC_APB4DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK5: + reg = io_read32(rcc_base + RCC_APB5DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + default: + break; + } + break; + /* MCU sub system */ + case _CK_MCU: + case _PCLK1: + case _PCLK2: + case _PCLK3: + reg = io_read32(rcc_base + RCC_MSSCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_MSSCKSELR_HSI: + clock = osc_frequency(OSC_HSI); + break; + case RCC_MSSCKSELR_HSE: + clock = osc_frequency(OSC_HSE); + break; + case RCC_MSSCKSELR_CSI: + clock = osc_frequency(OSC_CSI); + break; + case RCC_MSSCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); + break; + default: + break; + } + + /* MCU clock divider */ + reg = io_read32(rcc_base + RCC_MCUDIVR); + clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; + + switch (p) { + case _PCLK1: + reg = io_read32(rcc_base + RCC_APB1DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK2: + reg = io_read32(rcc_base + RCC_APB2DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK3: + reg = io_read32(rcc_base + RCC_APB3DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _CK_MCU: + default: + break; + } + break; + case _CK_PER: + reg = io_read32(rcc_base + RCC_CPERCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_CPERCKSELR_HSI: + clock = osc_frequency(OSC_HSI); + break; + case RCC_CPERCKSELR_HSE: + clock = osc_frequency(OSC_HSE); + break; + case RCC_CPERCKSELR_CSI: + clock = osc_frequency(OSC_CSI); + break; + default: + break; + } + break; + case _HSI: + case _HSI_KER: + clock = osc_frequency(OSC_HSI); + break; + case _CSI: + case _CSI_KER: + clock = osc_frequency(OSC_CSI); + break; + case _HSE: + case _HSE_KER: + clock = osc_frequency(OSC_HSE); + break; + case _HSE_KER_DIV2: + clock = osc_frequency(OSC_HSE) >> 1; + break; + case _HSE_RTC: + clock = osc_frequency(OSC_HSE); + clock /= (io_read32(rcc_base + RCC_RTCDIVR) & + RCC_DIVR_DIV_MASK) + 1; + break; + case _LSI: + clock = osc_frequency(OSC_LSI); + break; + case _LSE: + clock = osc_frequency(OSC_LSE); + break; + /* PLL */ + case _PLL1_P: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); + break; + case _PLL1_Q: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); + break; + case _PLL1_R: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); + break; + case _PLL2_P: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); + break; + case _PLL2_Q: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); + break; + case _PLL2_R: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); + break; + case _PLL3_P: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); + break; + case _PLL3_Q: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); + break; + case _PLL3_R: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); + break; + case _PLL4_P: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); + break; + case _PLL4_Q: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); + break; + case _PLL4_R: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); + break; + /* Other */ + case _USB_PHY_48: + clock = osc_frequency(OSC_USB_PHY_48); + break; + default: + break; + } + + return clock; +} + +static void __clk_enable(const struct stm32mp1_clk_gate *gate) +{ + vaddr_t base = stm32_rcc_base(); + uint32_t bit = BIT(gate->bit); + + if (gate->set_clr) + io_write32(base + gate->offset, bit); + else + io_setbits32_stm32shregs(base + gate->offset, bit); + + FMSG("Clock %u has been enabled", gate->clock_id); +} + +static void __clk_disable(const struct stm32mp1_clk_gate *gate) +{ + vaddr_t base = stm32_rcc_base(); + uint32_t bit = BIT(gate->bit); + + if (gate->set_clr) + io_write32(base + gate->offset + RCC_MP_ENCLRR_OFFSET, bit); + else + io_clrbits32_stm32shregs(base + gate->offset, bit); + + FMSG("Clock %u has been disabled", gate->clock_id); +} + +static long get_timer_rate(long parent_rate, unsigned int apb_bus) +{ + uint32_t timgxpre = 0; + uint32_t apbxdiv = 0; + vaddr_t rcc_base = stm32_rcc_base(); + + switch (apb_bus) { + case 1: + apbxdiv = io_read32(rcc_base + RCC_APB1DIVR) & + RCC_APBXDIV_MASK; + timgxpre = io_read32(rcc_base + RCC_TIMG1PRER) & + RCC_TIMGXPRER_TIMGXPRE; + break; + case 2: + apbxdiv = io_read32(rcc_base + RCC_APB2DIVR) & + RCC_APBXDIV_MASK; + timgxpre = io_read32(rcc_base + RCC_TIMG2PRER) & + RCC_TIMGXPRER_TIMGXPRE; + break; + default: + panic(); + break; + } + + if (apbxdiv == 0) + return parent_rate; + + return parent_rate * (timgxpre + 1) * 2; +} + +static unsigned long _stm32_clock_get_rate(unsigned long id) +{ + enum stm32mp1_parent_id p = _UNKNOWN_ID; + unsigned long rate = 0; + + p = stm32mp1_clk_get_parent(id); + if (p < 0) + return 0; + + rate = get_clock_rate(p); + + if ((id >= TIM2_K) && (id <= TIM14_K)) + rate = get_timer_rate(rate, 1); + + if ((id >= TIM1_K) && (id <= TIM17_K)) + rate = get_timer_rate(rate, 2); + + return rate; +} + +/* + * Get the parent ID of the target parent clock, or -1 if no parent found. + */ +static enum stm32mp1_parent_id get_parent_id_parent(enum stm32mp1_parent_id id) +{ + enum stm32mp1_parent_sel s = _UNKNOWN_SEL; + enum stm32mp1_pll_id pll_id = _PLL_NB; + uint32_t p_sel = 0; + + switch (id) { + case _ACLK: + case _HCLK5: + case _HCLK6: + case _PCLK4: + case _PCLK5: + s = _AXISS_SEL; + break; + case _PLL1_P: + case _PLL1_Q: + case _PLL1_R: + pll_id = _PLL1; + break; + case _PLL2_P: + case _PLL2_Q: + case _PLL2_R: + pll_id = _PLL2; + break; + case _PLL3_P: + case _PLL3_Q: + case _PLL3_R: + pll_id = _PLL3; + break; + case _PLL4_P: + case _PLL4_Q: + case _PLL4_R: + pll_id = _PLL4; + break; + case _PCLK1: + case _PCLK2: + case _HCLK2: + case _CK_PER: + case _CK_MPU: + case _CK_MCU: + case _USB_PHY_48: + /* We do not expected to access these */ + panic(); + break; + default: + /* Other parents have no parent */ + return -1; + } + + if (s != _UNKNOWN_SEL) { + const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); + vaddr_t rcc_base = stm32_rcc_base(); + + p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) & + sel->msk; + + if (p_sel < sel->nb_parent) + return sel->parent[p_sel]; + } else { + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + + p_sel = io_read32(stm32_rcc_base() + pll->rckxselr) & + RCC_SELR_REFCLK_SRC_MASK; + + if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) + return osc_id2parent_id(pll->refclk[p_sel]); + } + + FMSG("No parent found for %s", stm32mp1_clk_parent_name[id]); + return -1; +} + +/* We are only interested in knowing if PLL3 shall be secure or not */ +static void secure_parent_clocks(enum stm32mp1_parent_id parent_id) +{ + enum stm32mp1_parent_id grandparent_id = _UNKNOWN_ID; + + switch (parent_id) { + case _ACLK: + case _HCLK2: + case _HCLK5: + case _HCLK6: + case _PCLK4: + case _PCLK5: + /* Intermediate clock mux or clock, go deeper in clock tree */ + break; + case _HSI: + case _HSI_KER: + case _LSI: + case _CSI: + case _CSI_KER: + case _HSE: + case _HSE_KER: + case _HSE_KER_DIV2: + case _HSE_RTC: + case _LSE: + case _PLL1_P: + case _PLL1_Q: + case _PLL1_R: + case _PLL2_P: + case _PLL2_Q: + case _PLL2_R: + /* Always secure clocks, no need to go further */ + return; + case _PLL3_P: + case _PLL3_Q: + case _PLL3_R: + /* PLL3 is a shared resource, registered and don't go further */ + stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); + return; + default: + DMSG("Cannot lookup parent clock %s", + stm32mp1_clk_parent_name[parent_id]); + panic(); + } + + grandparent_id = get_parent_id_parent(parent_id); + if (grandparent_id >= 0) + secure_parent_clocks(grandparent_id); +} + +void stm32mp_register_clock_parents_secure(unsigned long clock_id) +{ + enum stm32mp1_parent_id parent_id = stm32mp1_clk_get_parent(clock_id); + + if (parent_id < 0) { + DMSG("No parent for clock %lu", clock_id); + return; + } + + secure_parent_clocks(parent_id); +} + +static const char *stm32mp_osc_node_label[NB_OSC] = { + [OSC_LSI] = "clk-lsi", + [OSC_LSE] = "clk-lse", + [OSC_HSI] = "clk-hsi", + [OSC_HSE] = "clk-hse", + [OSC_CSI] = "clk-csi", + [OSC_I2S_CKIN] = "i2s_ckin", + [OSC_USB_PHY_48] = "ck_usbo_48m" +}; + +static unsigned int clk_freq_prop(const void *fdt, int node) +{ + const fdt32_t *cuint = NULL; + int ret = 0; + + /* Disabled clocks report null rate */ + if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED) + return 0; + + cuint = fdt_getprop(fdt, node, "clock-frequency", &ret); + if (!cuint) + panic(); + + return fdt32_to_cpu(*cuint); +} + +static void get_osc_freq_from_dt(const void *fdt) +{ + enum stm32mp_osc_id idx = _UNKNOWN_OSC_ID; + int clk_node = fdt_path_offset(fdt, "/clocks"); + + if (clk_node < 0) + panic(); + + COMPILE_TIME_ASSERT((int)OSC_HSI == 0); + for (idx = OSC_HSI; idx < NB_OSC; idx++) { + const char *name = stm32mp_osc_node_label[idx]; + int subnode = 0; + + fdt_for_each_subnode(subnode, fdt, clk_node) { + const char *cchar = NULL; + int ret = 0; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (!cchar) + panic(); + + if (strncmp(cchar, name, (size_t)ret) == 0) { + stm32mp1_osc[idx] = clk_freq_prop(fdt, subnode); + + DMSG("Osc %s: %lu Hz", name, stm32mp1_osc[idx]); + break; + } + } + + if (!stm32mp1_osc[idx]) + DMSG("Osc %s: no frequency info", name); + } +} + +static void enable_static_secure_clocks(void) +{ + unsigned int idx = 0; + const unsigned long secure_enable[] = { + DDRC1, DDRC1LP, DDRC2, DDRC2LP, DDRPHYC, DDRPHYCLP, DDRCAPB, + AXIDCG, DDRPHYCAPB, DDRPHYCAPBLP, TZPC, TZC1, TZC2, STGEN_K, + BSEC, + }; + + for (idx = 0; idx < ARRAY_SIZE(secure_enable); idx++) { + clk_enable(stm32mp_rcc_clock_id_to_clk(secure_enable[idx])); + stm32mp_register_clock_parents_secure(secure_enable[idx]); + } + + if (CFG_TEE_CORE_NB_CORE > 1) + clk_enable(stm32mp_rcc_clock_id_to_clk(RTCAPB)); +} + +static void __maybe_unused enable_rcc_tzen(void) +{ + io_setbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_TZEN); +} + +static void __maybe_unused disable_rcc_tzen(void) +{ + IMSG("RCC is non-secure"); + io_clrbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_TZEN); +} + +static TEE_Result stm32mp1_clk_fdt_init(const void *fdt, int node) +{ + unsigned int i = 0; + int len = 0; + int ignored = 0; + + get_osc_freq_from_dt(fdt); + + /* + * OP-TEE core is not in charge of configuring clock parenthood. + * This is expected from an earlier boot stage. Modifying the clock + * tree parenthood here may jeopardize already configured clocks. + * The sequence below ignores such DT directives with a friendly + * debug trace. + */ + if (fdt_getprop(fdt, node, "st,clksrc", &len)) { + DMSG("Ignore source clocks configuration from DT"); + ignored++; + } + if (fdt_getprop(fdt, node, "st,clkdiv", &len)) { + DMSG("Ignore clock divisors configuration from DT"); + ignored++; + } + if (fdt_getprop(fdt, node, "st,pkcs", &len)) { + DMSG("Ignore peripheral clocks tree configuration from DT"); + ignored++; + } + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + char name[] = "st,pll@X"; + + snprintf(name, sizeof(name), "st,pll@%d", i); + node = fdt_subnode_offset(fdt, node, name); + if (node < 0) + continue; + + if (fdt_getprop(fdt, node, "cfg", &len) || + fdt_getprop(fdt, node, "frac", &len)) { + DMSG("Ignore PLL%u configurations from DT", i); + ignored++; + } + } + + if (ignored != 0) + IMSG("DT clock tree configurations were ignored"); + + return TEE_SUCCESS; +} + +/* + * Conversion between clk references and clock gates and clock on internals + * + * stm32mp1_clk first cells follow stm32mp1_clk_gate[] ordering. + * stm32mp1_clk last cells follow stm32mp1_clk_on[] ordering. + */ +static struct clk stm32mp1_clk[ARRAY_SIZE(stm32mp1_clk_gate) + + ARRAY_SIZE(stm32mp1_clk_on)]; + +#define CLK_ON_INDEX_OFFSET ((int)ARRAY_SIZE(stm32mp1_clk_gate)) + +static bool clk_is_gate(struct clk *clk) +{ + int clk_index = clk - stm32mp1_clk; + + assert(clk_index >= 0 && clk_index < (int)ARRAY_SIZE(stm32mp1_clk)); + return clk_index < CLK_ON_INDEX_OFFSET; +} + +static unsigned long clk_to_clock_id(struct clk *clk) +{ + int gate_index = clk - stm32mp1_clk; + int on_index = gate_index - CLK_ON_INDEX_OFFSET; + + if (clk_is_gate(clk)) + return stm32mp1_clk_gate[gate_index].clock_id; + + return stm32mp1_clk_on[on_index]; +} + +static const struct stm32mp1_clk_gate *clk_to_gate_ref(struct clk *clk) +{ + int gate_index = clk - stm32mp1_clk; + + assert(clk_is_gate(clk)); + + return stm32mp1_clk_gate + gate_index; +} + +static int clock_id_to_gate_index(unsigned long clock_id) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(stm32mp1_clk_gate); n++) + if (stm32mp1_clk_gate[n].clock_id == clock_id) + return n; + + return -1; +} + +static int clock_id_to_always_on_index(unsigned long clock_id) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(stm32mp1_clk_on); n++) + if (stm32mp1_clk_on[n] == clock_id) + return n; + + return -1; +} + +static struct clk *clock_id_to_clk(unsigned long clock_id) +{ + int gate_index = clock_id_to_gate_index(clock_id); + int on_index = clock_id_to_always_on_index(clock_id); + + if (gate_index >= 0) + return stm32mp1_clk + gate_index; + + if (on_index >= 0) + return stm32mp1_clk + CLK_ON_INDEX_OFFSET + on_index; + + return NULL; +} + +struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id) +{ + return clock_id_to_clk(clock_id); +} + +#if (CFG_TEE_CORE_LOG_LEVEL >= TRACE_DEBUG) && defined(CFG_TEE_CORE_DEBUG) +struct clk_name { + unsigned int clock_id; + const char *name; +}; + +#define CLOCK_NAME(_binding, _name) \ + { .clock_id = (_binding), .name = (_name) } + +/* Store names only for some clocks */ +const struct clk_name exposed_clk_name[] = { + /* Clocks used by platform drivers not yet probed from DT */ + CLOCK_NAME(CK_DBG, "dbg"), + CLOCK_NAME(CK_MCU, "mcu"), + CLOCK_NAME(RTCAPB, "rtcapb"), + CLOCK_NAME(BKPSRAM, "bkpsram"), + CLOCK_NAME(RTC, "rtc"), + CLOCK_NAME(CRYP1, "crpy1"), + CLOCK_NAME(SYSCFG, "syscfg"), + CLOCK_NAME(GPIOA, "gpioa"), + CLOCK_NAME(GPIOB, "gpiob"), + CLOCK_NAME(GPIOC, "gpioc"), + CLOCK_NAME(GPIOD, "gpiod"), + CLOCK_NAME(GPIOE, "gpioe"), + CLOCK_NAME(GPIOF, "gpiof"), + CLOCK_NAME(GPIOG, "gpiog"), + CLOCK_NAME(GPIOH, "gpioh"), + CLOCK_NAME(GPIOI, "gpioi"), + CLOCK_NAME(GPIOJ, "gpioj"), + CLOCK_NAME(GPIOK, "gpiok"), + CLOCK_NAME(GPIOZ, "gpioz"), + /* Clock exposed by SCMI. SCMI clock fmro DT bindings to come... */ + CLOCK_NAME(CK_HSE, "hse"), + CLOCK_NAME(CK_HSI, "hsi"), + CLOCK_NAME(CK_CSI, "csi"), + CLOCK_NAME(CK_LSE, "lse"), + CLOCK_NAME(CK_LSI, "lsi"), + CLOCK_NAME(PLL2_Q, "pll2q"), + CLOCK_NAME(PLL2_R, "pll2r"), + CLOCK_NAME(PLL3_Q, "pll3q"), + CLOCK_NAME(PLL3_R, "pll3r"), + CLOCK_NAME(CRYP1, "cryp1"), + CLOCK_NAME(HASH1, "hash1"), + CLOCK_NAME(I2C4_K, "i2c4"), + CLOCK_NAME(I2C6_K, "i2c6"), + CLOCK_NAME(IWDG1, "iwdg"), + CLOCK_NAME(RNG1_K, "rng1"), + CLOCK_NAME(SPI6_K, "spi6"), + CLOCK_NAME(USART1_K, "usart1"), + CLOCK_NAME(CK_MCU, "mcu"), +}; +DECLARE_KEEP_PAGER(exposed_clk_name); + +static const char *clk_op_get_name(struct clk *clk) +{ + unsigned long clock_id = clk_to_clock_id(clk); + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(exposed_clk_name); n++) + if (exposed_clk_name[n].clock_id == clock_id) + return exposed_clk_name[n].name; + + return NULL; +} +#else +static const char *clk_op_get_name(struct clk *clk __unused) +{ + return NULL; +} +#endif /*CFG_TEE_CORE_LOG_LEVEL*/ + +static unsigned long clk_op_compute_rate(struct clk *clk, + unsigned long parent_rate __unused) +{ + return _stm32_clock_get_rate(clk_to_clock_id(clk)); +} + +static TEE_Result clk_op_enable(struct clk *clk) +{ + if (clk_is_gate(clk)) + __clk_enable(clk_to_gate_ref(clk)); + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(clk_op_enable); + +static void clk_op_disable(struct clk *clk) +{ + if (clk_is_gate(clk)) + __clk_disable(clk_to_gate_ref(clk)); +} +DECLARE_KEEP_PAGER(clk_op_disable); + +/* This variable is weak to break its dependency chain when linked as unpaged */ +const struct clk_ops stm32mp1_clk_ops +__weak __relrodata_unpaged("stm32mp1_clk_ops") = { + .enable = clk_op_enable, + .disable = clk_op_disable, + .get_rate = clk_op_compute_rate, +}; + +static TEE_Result register_stm32mp1_clocks(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(stm32mp1_clk); n++) { + stm32mp1_clk[n].ops = &stm32mp1_clk_ops; + stm32mp1_clk[n].name = clk_op_get_name(stm32mp1_clk + n); + refcount_set(&stm32mp1_clk[n].enabled_count, 0); + + res = clk_register(stm32mp1_clk + n); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +static struct clk *stm32mp1_clk_dt_get_clk(struct dt_driver_phandle_args *pargs, + void *data __unused, TEE_Result *res) +{ + unsigned long clock_id = pargs->args[0]; + struct clk *clk = NULL; + + *res = TEE_ERROR_BAD_PARAMETERS; + + if (pargs->args_count != 1) + return NULL; + + clk = clock_id_to_clk(clock_id); + if (!clk) + return NULL; + + *res = TEE_SUCCESS; + return clk; +} + +/* Non-null reference for compat data */ +static const uint8_t non_secure_rcc; + +static TEE_Result stm32mp1_clock_provider_probe(const void *fdt, int offs, + const void *compat_data) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (compat_data == &non_secure_rcc) + disable_rcc_tzen(); + else + enable_rcc_tzen(); + + res = stm32mp1_clk_fdt_init(fdt, offs); + if (res) { + EMSG("Failed to initialize clocks from DT: %#"PRIx32, res); + panic(); + } + + res = register_stm32mp1_clocks(); + if (res) { + EMSG("Failed to register clocks: %#"PRIx32, res); + panic(); + } + + res = clk_dt_register_clk_provider(fdt, offs, stm32mp1_clk_dt_get_clk, + NULL); + if (res) { + EMSG("Failed to register clock provider: %#"PRIx32, res); + panic(); + } + + enable_static_secure_clocks(); + + return TEE_SUCCESS; +} + +static const struct dt_device_match stm32mp1_clock_match_table[] = { + { .compatible = "st,stm32mp1-rcc", .compat_data = &non_secure_rcc, }, + { .compatible = "st,stm32mp1-rcc-secure", }, + { } +}; + +DEFINE_DT_DRIVER(stm32mp1_clock_dt_driver) = { + .name = "stm32mp1_clock", + .type = DT_DRIVER_CLK, + .match_table = stm32mp1_clock_match_table, + .probe = stm32mp1_clock_provider_probe, +}; diff --git a/optee/optee_os/core/drivers/clk/clk.c b/optee/optee_os/core/drivers/clk/clk.c new file mode 100644 index 0000000..00cb57e --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Bootlin + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Global clock tree lock */ +static unsigned int clk_lock = SPINLOCK_UNLOCK; + +struct clk *clk_alloc(const char *name, const struct clk_ops *ops, + struct clk **parent_clks, size_t parent_count) +{ + struct clk *clk = NULL; + size_t parent = 0; + + clk = calloc(1, sizeof(*clk) + parent_count * sizeof(clk)); + if (!clk) + return NULL; + + clk->num_parents = parent_count; + for (parent = 0; parent < parent_count; parent++) + clk->parents[parent] = parent_clks[parent]; + + clk->name = name; + clk->ops = ops; + refcount_set(&clk->enabled_count, 0); + + return clk; +} + +void clk_free(struct clk *clk) +{ + free(clk); +} + +static bool __maybe_unused clk_check(struct clk *clk) +{ + if (!clk->ops) + return false; + + if (clk->ops->set_parent && !clk->ops->get_parent) + return false; + + if (clk->num_parents > 1 && !clk->ops->get_parent) + return false; + + return true; +} + +static void clk_compute_rate_no_lock(struct clk *clk) +{ + unsigned long parent_rate = 0; + + if (clk->parent) + parent_rate = clk->parent->rate; + + if (clk->ops->get_rate) + clk->rate = clk->ops->get_rate(clk, parent_rate); + else + clk->rate = parent_rate; +} + +struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx) +{ + if (pidx >= clk->num_parents) + return NULL; + + return clk->parents[pidx]; +} + +static void clk_init_parent(struct clk *clk) +{ + size_t pidx = 0; + + switch (clk->num_parents) { + case 0: + break; + case 1: + clk->parent = clk->parents[0]; + break; + default: + pidx = clk->ops->get_parent(clk); + assert(pidx < clk->num_parents); + + clk->parent = clk->parents[pidx]; + break; + } +} + +TEE_Result clk_register(struct clk *clk) +{ + assert(clk_check(clk)); + + clk_init_parent(clk); + clk_compute_rate_no_lock(clk); + + DMSG("Registered clock %s, freq %lu", clk->name, clk_get_rate(clk)); + + return TEE_SUCCESS; +} + +static bool clk_is_enabled_no_lock(struct clk *clk) +{ + return refcount_val(&clk->enabled_count) != 0; +} + +bool clk_is_enabled(struct clk *clk) +{ + return clk_is_enabled_no_lock(clk); +} + +static void clk_disable_no_lock(struct clk *clk) +{ + struct clk *parent = NULL; + + if (!refcount_dec(&clk->enabled_count)) + return; + + if (clk->ops->disable) + clk->ops->disable(clk); + + parent = clk_get_parent(clk); + if (parent) + clk_disable_no_lock(parent); +} + +static TEE_Result clk_enable_no_lock(struct clk *clk) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct clk *parent = NULL; + + if (refcount_inc(&clk->enabled_count)) + return TEE_SUCCESS; + + parent = clk_get_parent(clk); + if (parent) { + res = clk_enable_no_lock(parent); + if (res) + return res; + } + + if (clk->ops->enable) { + res = clk->ops->enable(clk); + if (res) { + if (parent) + clk_disable_no_lock(parent); + + return res; + } + } + + refcount_set(&clk->enabled_count, 1); + + return TEE_SUCCESS; +} + +TEE_Result clk_enable(struct clk *clk) +{ + uint32_t exceptions = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + exceptions = cpu_spin_lock_xsave(&clk_lock); + res = clk_enable_no_lock(clk); + cpu_spin_unlock_xrestore(&clk_lock, exceptions); + + return res; +} + +void clk_disable(struct clk *clk) +{ + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&clk_lock); + clk_disable_no_lock(clk); + cpu_spin_unlock_xrestore(&clk_lock, exceptions); +} + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} + +static TEE_Result clk_set_rate_no_lock(struct clk *clk, unsigned long rate) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned long parent_rate = 0; + + if (clk->parent) + parent_rate = clk_get_rate(clk->parent); + + res = clk->ops->set_rate(clk, rate, parent_rate); + if (res) + return res; + + clk_compute_rate_no_lock(clk); + + return TEE_SUCCESS; +} + +TEE_Result clk_set_rate(struct clk *clk, unsigned long rate) +{ + uint32_t exceptions = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (!clk->ops->set_rate) + return TEE_ERROR_NOT_SUPPORTED; + + exceptions = cpu_spin_lock_xsave(&clk_lock); + + if (clk->flags & CLK_SET_RATE_GATE && clk_is_enabled_no_lock(clk)) + res = TEE_ERROR_BAD_STATE; + else + res = clk_set_rate_no_lock(clk, rate); + + cpu_spin_unlock_xrestore(&clk_lock, exceptions); + + return res; +} + +struct clk *clk_get_parent(struct clk *clk) +{ + return clk->parent; +} + +static TEE_Result clk_get_parent_idx(struct clk *clk, struct clk *parent, + size_t *pidx) +{ + size_t i = 0; + + for (i = 0; i < clk_get_num_parents(clk); i++) { + if (clk_get_parent_by_index(clk, i) == parent) { + *pidx = i; + return TEE_SUCCESS; + } + } + EMSG("Clock %s is not a parent of clock %s", parent->name, clk->name); + + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result clk_set_parent_no_lock(struct clk *clk, struct clk *parent, + size_t pidx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + bool was_enabled = false; + + /* Requested parent is already the one set */ + if (clk->parent == parent) + return TEE_SUCCESS; + + was_enabled = clk_is_enabled_no_lock(clk); + /* Call is needed to decrement refcount on current parent tree */ + if (was_enabled) + clk_disable_no_lock(clk); + + res = clk->ops->set_parent(clk, pidx); + if (res) + goto out; + + clk->parent = parent; + + /* The parent changed and the rate might also have changed */ + clk_compute_rate_no_lock(clk); + +out: + /* Call is needed to increment refcount on the new parent tree */ + if (was_enabled) { + res = clk_enable_no_lock(clk); + if (res) + panic("Failed to re-enable clock after setting parent"); + } + + return res; +} + +TEE_Result clk_set_parent(struct clk *clk, struct clk *parent) +{ + size_t pidx = 0; + uint32_t exceptions = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (clk_get_parent_idx(clk, parent, &pidx) || !clk->ops->set_parent) + return TEE_ERROR_BAD_PARAMETERS; + + exceptions = cpu_spin_lock_xsave(&clk_lock); + if (clk->flags & CLK_SET_PARENT_GATE && clk_is_enabled_no_lock(clk)) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + res = clk_set_parent_no_lock(clk, parent, pidx); +out: + cpu_spin_unlock_xrestore(&clk_lock, exceptions); + + return res; +} + +TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index, + unsigned long *rates, size_t *nb_elts) +{ + if (!clk->ops->get_rates_array) + return TEE_ERROR_NOT_SUPPORTED; + + return clk->ops->get_rates_array(clk, start_index, rates, nb_elts); +} diff --git a/optee/optee_os/core/drivers/clk/clk_dt.c b/optee/optee_os/core/drivers/clk/clk_dt.c new file mode 100644 index 0000000..cf2f6fb --- /dev/null +++ b/optee/optee_os/core/drivers/clk/clk_dt.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Bootlin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result clk_dt_get_by_name(const void *fdt, int nodeoffset, + const char *name, struct clk **clk) +{ + int clk_id = 0; + + clk_id = fdt_stringlist_search(fdt, nodeoffset, "clock-names", name); + if (clk_id < 0) { + *clk = NULL; + return TEE_ERROR_GENERIC; + } + + return clk_dt_get_by_index(fdt, nodeoffset, clk_id, clk); +} + +static TEE_Result clk_dt_get_by_idx_prop(const char *prop_name, const void *fdt, + int nodeoffset, unsigned int clk_idx, + struct clk **clk) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + *clk = dt_driver_device_from_node_idx_prop(prop_name, fdt, nodeoffset, + clk_idx, DT_DRIVER_CLK, + &res); + return res; +} + +TEE_Result clk_dt_get_by_index(const void *fdt, int nodeoffset, + unsigned int clk_idx, struct clk **clk) +{ + return clk_dt_get_by_idx_prop("clocks", fdt, nodeoffset, clk_idx, clk); +} + +#ifdef CFG_DRIVERS_CLK_EARLY_PROBE +/* Recursively called from parse_clock_property() */ +static TEE_Result clk_probe_clock_provider_node(const void *fdt, int node); + +static TEE_Result parse_clock_property(const void *fdt, int node) +{ + int len = 0; + int idx = 0; + int parent_node = 0; + int clock_cells = 0; + uint32_t phandle = 0; + const uint32_t *prop = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + prop = fdt_getprop(fdt, node, "clocks", &len); + if (!prop) + return TEE_SUCCESS; + + len /= sizeof(uint32_t); + while (idx < len) { + phandle = fdt32_to_cpu(prop[idx]); + + parent_node = fdt_node_offset_by_phandle(fdt, phandle); + if (parent_node < 0) + return TEE_ERROR_GENERIC; + + /* Parent probe should not fail or clock won't be available */ + res = clk_probe_clock_provider_node(fdt, parent_node); + if (res) { + EMSG("Probe parent clock node %s on node %s: %#"PRIx32, + fdt_get_name(fdt, parent_node, NULL), + fdt_get_name(fdt, node, NULL), res); + panic(); + } + + clock_cells = fdt_get_dt_driver_cells(fdt, parent_node, + DT_DRIVER_CLK); + if (clock_cells < 0) + return TEE_ERROR_GENERIC; + + idx += 1 + clock_cells; + } + + return TEE_SUCCESS; +} + +static TEE_Result clk_probe_clock_provider_node(const void *fdt, int node) +{ + int len = 0; + int status = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + status = fdt_get_status(fdt, node); + if (!(status & DT_STATUS_OK_SEC)) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* Check if the node is a clock provider */ + if (!fdt_getprop(fdt, node, "#clock-cells", &len)) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* Check if node has already been probed */ + if (dt_driver_get_provider_by_node(node, DT_DRIVER_CLK)) + return TEE_SUCCESS; + + /* Check if the node has a clock property first to probe parent */ + res = parse_clock_property(fdt, node); + if (res) + return res; + + return dt_driver_probe_device_by_node(fdt, node, DT_DRIVER_CLK); +} + +static void clk_probe_node(const void *fdt, int parent_node) +{ + int child = 0; + int status = 0; + __maybe_unused TEE_Result res = TEE_ERROR_GENERIC; + + fdt_for_each_subnode(child, fdt, parent_node) { + status = fdt_get_status(fdt, child); + if (status == DT_STATUS_DISABLED) + continue; + + res = clk_probe_clock_provider_node(fdt, child); + assert(res == TEE_SUCCESS || res == TEE_ERROR_ITEM_NOT_FOUND); + + clk_probe_node(fdt, child); + } +} + +static void parse_assigned_clock(const void *fdt, int nodeoffset) +{ + int rate_len = 0; + int clock_idx = 0; + struct clk *clk = NULL; + unsigned long rate = 0; + struct clk *parent = NULL; + const uint32_t *rate_prop = NULL; + TEE_Result __maybe_unused res = TEE_ERROR_GENERIC; + + rate_prop = fdt_getprop(fdt, nodeoffset, "assigned-clock-rates", + &rate_len); + rate_len /= sizeof(uint32_t); + + while (true) { + res = clk_dt_get_by_idx_prop("assigned-clocks", fdt, nodeoffset, + clock_idx, &clk); + if (!clk) + return; + assert(!res); + + res = clk_dt_get_by_idx_prop("assigned-clock-parents", fdt, + nodeoffset, clock_idx, &parent); + if (parent) { + assert(!res); + if (clk_set_parent(clk, parent)) { + EMSG("Could not set clk %s parent to clock %s", + clk->name, parent->name); + panic(); + } + } + + if (rate_prop && clock_idx < rate_len) { + rate = fdt32_to_cpu(rate_prop[clock_idx]); + if (rate && clk_set_rate(clk, rate) != TEE_SUCCESS) + panic(); + } + + clock_idx++; + } +} + +static void clk_probe_assigned(const void *fdt, int parent_node) +{ + int len = 0; + int child = 0; + int status = 0; + + fdt_for_each_subnode(child, fdt, parent_node) { + clk_probe_assigned(fdt, child); + + status = fdt_get_status(fdt, child); + if (status == DT_STATUS_DISABLED) + continue; + + if (fdt_getprop(fdt, child, "assigned-clocks", &len)) + parse_assigned_clock(fdt, child); + } +} + +static TEE_Result clk_dt_probe(void) +{ + const void *fdt = get_secure_dt(); + + DMSG("Probing clocks from devicetree"); + if (!fdt) + panic(); + + clk_probe_node(fdt, -1); + + clk_probe_assigned(fdt, -1); + + return TEE_SUCCESS; +} +early_init(clk_dt_probe); +#endif diff --git a/optee/optee_os/core/drivers/clk/fixed_clk.c b/optee/optee_os/core/drivers/clk/fixed_clk.c new file mode 100644 index 0000000..2da1df9 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/fixed_clk.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Bootlin + */ + +#include +#include +#include +#include +#include + +struct fixed_clock_data { + unsigned long rate; +}; + +static unsigned long fixed_clk_get_rate(struct clk *clk, + unsigned long parent_rate __unused) +{ + struct fixed_clock_data *d = clk->priv; + + return d->rate; +} + +static const struct clk_ops fixed_clk_clk_ops = { + .get_rate = fixed_clk_get_rate, +}; + +static TEE_Result fixed_clock_probe(const void *fdt, int offs, + const void *compat_data __unused) +{ + const uint32_t *freq = NULL; + const char *name = NULL; + struct clk *clk = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + struct fixed_clock_data *fcd = NULL; + + name = fdt_get_name(fdt, offs, NULL); + if (!name) + name = "fixed-clock"; + + clk = clk_alloc(name, &fixed_clk_clk_ops, NULL, 0); + if (!clk) + return TEE_ERROR_OUT_OF_MEMORY; + + fcd = calloc(1, sizeof(struct fixed_clock_data)); + if (!fcd) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto free_clk; + } + + freq = fdt_getprop(fdt, offs, "clock-frequency", NULL); + if (!freq) { + res = TEE_ERROR_BAD_FORMAT; + goto free_fcd; + } + + fcd->rate = fdt32_to_cpu(*freq); + clk->priv = fcd; + + res = clk_register(clk); + if (res) + goto free_fcd; + + res = clk_dt_register_clk_provider(fdt, offs, clk_dt_get_simple_clk, + clk); + if (!res) + return TEE_SUCCESS; + +free_fcd: + free(fcd); +free_clk: + clk_free(clk); + + return res; +} + +CLK_DT_DECLARE(fixed_clock, "fixed-clock", fixed_clock_probe); diff --git a/optee/optee_os/core/drivers/clk/sam/at91_audio_pll.c b/optee/optee_os/core/drivers/clk/sam/at91_audio_pll.c new file mode 100644 index 0000000..72b6e60 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_audio_pll.c @@ -0,0 +1,390 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2016 Atmel Corporation, + * Songjun Wu , + * Nicolas Ferre + * Copyright (C) 2017 Free Electrons, + * Quentin Schulz + * + * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent + * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of + * its own parent. PMC and PAD can then divide the FRAC rate to best match the + * asked rate. + * + * Traits of FRAC clock: + * enable - clk_enable writes nd, fracr parameters and enables PLL + * rate - rate is adjustable. + * clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22)) + * parent - fixed parent. No clk_set_parent support + * + * Traits of PMC clock: + * enable - clk_enable writes qdpmc, and enables PMC output + * rate - rate is adjustable. + * clk->rate = parent->rate / (qdpmc + 1) + * parent - fixed parent. No clk_set_parent support + * + * Traits of PAD clock: + * enable - clk_enable writes divisors and enables PAD output + * rate - rate is adjustable. + * clk->rate = parent->rate / (qdaudio * div)) + * parent - fixed parent. No clk_set_parent support + */ + +#include +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define AUDIO_PLL_DIV_FRAC BIT(22) +#define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \ + AT91_PMC_AUDIO_PLL_ND_OFFSET) + +#define AUDIO_PLL_QDPAD(qd, div) \ + ((AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(qd) & \ + AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK) | \ + (AT91_PMC_AUDIO_PLL_QDPAD_DIV(div) & \ + AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK)) + +#define AUDIO_PLL_QDPMC_MAX (AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \ + AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) + +#define AUDIO_PLL_FOUT_MIN 620000000UL +#define AUDIO_PLL_FOUT_MAX 700000000UL + +struct clk_audio_frac { + vaddr_t base; + uint32_t fracr; + uint8_t nd; +}; + +struct clk_audio_pad { + vaddr_t base; + uint8_t qdaudio; + uint8_t div; +}; + +struct clk_audio_pmc { + vaddr_t base; + uint8_t qdpmc; +}; + +static TEE_Result clk_audio_pll_frac_enable(struct clk *clk) +{ + struct clk_audio_frac *frac = clk->priv; + + io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_RESETN); + io_setbits32(frac->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_RESETN); + io_clrsetbits32(frac->base + AT91_PMC_AUDIO_PLL1, + AT91_PMC_AUDIO_PLL_FRACR_MASK, frac->fracr); + + /* + * reset and enable have to be done in 2 separated writes + * for AT91_PMC_AUDIO_PLL0 + */ + io_clrsetbits32(frac->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_PLLEN | + AT91_PMC_AUDIO_PLL_ND_MASK, + AT91_PMC_AUDIO_PLL_PLLEN | + AT91_PMC_AUDIO_PLL_ND(frac->nd)); + + return TEE_SUCCESS; +} + +static TEE_Result clk_audio_pll_pad_enable(struct clk *clk) +{ + struct clk_audio_pad *apad_ck = clk->priv; + + io_clrsetbits32(apad_ck->base + AT91_PMC_AUDIO_PLL1, + AT91_PMC_AUDIO_PLL_QDPAD_MASK, + AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div)); + io_clrsetbits32(apad_ck->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN); + + return TEE_SUCCESS; +} + +static TEE_Result clk_audio_pll_pmc_enable(struct clk *clk) +{ + struct clk_audio_pmc *apmc_ck = clk->priv; + + io_clrsetbits32(apmc_ck->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_PMCEN | + AT91_PMC_AUDIO_PLL_QDPMC_MASK, + AT91_PMC_AUDIO_PLL_PMCEN | + AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc)); + return TEE_SUCCESS; +} + +static void clk_audio_pll_frac_disable(struct clk *clk) +{ + struct clk_audio_frac *frac = clk->priv; + + io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_PLLEN); + /* Requires 2 separated writes */ + io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_RESETN); +} + +static void clk_audio_pll_pad_disable(struct clk *clk) +{ + struct clk_audio_pad *apad_ck = clk->priv; + + io_clrbits32(apad_ck->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_PADEN); +} + +static void clk_audio_pll_pmc_disable(struct clk *clk) +{ + struct clk_audio_pmc *apmc_ck = clk->priv; + + io_clrbits32(apmc_ck->base + AT91_PMC_AUDIO_PLL0, + AT91_PMC_AUDIO_PLL_PMCEN); +} + +static unsigned long clk_audio_pll_fout(unsigned long parent_rate, + unsigned long nd, unsigned long fracr) +{ + unsigned long long fr = (unsigned long long)parent_rate * fracr; + + fr = UDIV_ROUND_NEAREST(fr, AUDIO_PLL_DIV_FRAC); + + return parent_rate * (nd + 1) + fr; +} + +static unsigned long clk_audio_pll_frac_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_audio_frac *frac = clk->priv; + + return clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr); +} + +static unsigned long clk_audio_pll_pad_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_audio_pad *apad_ck = clk->priv; + unsigned long apad_rate = 0; + + if (apad_ck->qdaudio && apad_ck->div) + apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div); + + return apad_rate; +} + +static unsigned long clk_audio_pll_pmc_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_audio_pmc *apmc_ck = clk->priv; + + return parent_rate / (apmc_ck->qdpmc + 1); +} + +static TEE_Result clk_audio_pll_frac_compute_frac(unsigned long rate, + unsigned long parent_rate, + unsigned long *nd, + unsigned long *fracr) +{ + unsigned long long tmp = 0; + unsigned long long rem = 0; + + if (!rate || !parent_rate) + return TEE_ERROR_BAD_PARAMETERS; + + tmp = rate; + rem = tmp % parent_rate; + tmp /= parent_rate; + if (!tmp || tmp >= AUDIO_PLL_ND_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + *nd = tmp - 1; + + tmp = rem * AUDIO_PLL_DIV_FRAC; + tmp = UDIV_ROUND_NEAREST(tmp, parent_rate); + if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK) + return TEE_ERROR_BAD_PARAMETERS; + + /* we can cast here as we verified the bounds just above */ + *fracr = (unsigned long)tmp; + + return TEE_SUCCESS; +} + +static TEE_Result clk_audio_pll_frac_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate) +{ + struct clk_audio_frac *frac = clk->priv; + unsigned long fracr = 0; + unsigned long nd = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX) + return TEE_ERROR_BAD_PARAMETERS; + + res = clk_audio_pll_frac_compute_frac(rate, parent_rate, &nd, &fracr); + if (res) + return res; + + frac->nd = nd; + frac->fracr = fracr; + + return TEE_SUCCESS; +} + +static TEE_Result clk_audio_pll_pad_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate) +{ + struct clk_audio_pad *apad_ck = clk->priv; + uint8_t tmp_div = 1; + + if (!rate) + return TEE_ERROR_BAD_PARAMETERS; + + tmp_div = parent_rate / rate; + if (tmp_div % 3 == 0) { + apad_ck->qdaudio = tmp_div / 3; + apad_ck->div = 3; + } else { + apad_ck->qdaudio = tmp_div / 2; + apad_ck->div = 2; + } + + return TEE_SUCCESS; +} + +static TEE_Result clk_audio_pll_pmc_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate) +{ + struct clk_audio_pmc *apmc_ck = clk->priv; + + if (!rate) + return TEE_ERROR_BAD_PARAMETERS; + + apmc_ck->qdpmc = parent_rate / rate - 1; + + return TEE_SUCCESS; +} + +static const struct clk_ops audio_pll_frac_ops = { + .enable = clk_audio_pll_frac_enable, + .disable = clk_audio_pll_frac_disable, + .get_rate = clk_audio_pll_frac_get_rate, + .set_rate = clk_audio_pll_frac_set_rate, +}; + +static const struct clk_ops audio_pll_pad_ops = { + .enable = clk_audio_pll_pad_enable, + .disable = clk_audio_pll_pad_disable, + .get_rate = clk_audio_pll_pad_get_rate, + .set_rate = clk_audio_pll_pad_set_rate, +}; + +static const struct clk_ops audio_pll_pmc_ops = { + .enable = clk_audio_pll_pmc_enable, + .disable = clk_audio_pll_pmc_disable, + .get_rate = clk_audio_pll_pmc_get_rate, + .set_rate = clk_audio_pll_pmc_set_rate, +}; + +struct clk * +at91_clk_register_audio_pll_frac(struct pmc_data *pmc, const char *name, + struct clk *parent) +{ + struct clk_audio_frac *frac_ck = NULL; + struct clk *clk = NULL; + + clk = clk_alloc(name, &audio_pll_frac_ops, &parent, 1); + if (!clk) + return NULL; + + frac_ck = calloc(1, sizeof(*frac_ck)); + if (!frac_ck) { + clk_free(clk); + return NULL; + } + + clk->flags = CLK_SET_RATE_GATE; + + frac_ck->base = pmc->base; + + clk->priv = frac_ck; + if (clk_register(clk)) { + clk_free(clk); + free(frac_ck); + return NULL; + } + + return clk; +} + +struct clk * +at91_clk_register_audio_pll_pad(struct pmc_data *pmc, const char *name, + struct clk *parent) +{ + struct clk_audio_pad *apad_ck = NULL; + struct clk *clk = NULL; + + clk = clk_alloc(name, &audio_pll_pad_ops, &parent, 1); + if (!clk) + return NULL; + + apad_ck = calloc(1, sizeof(*apad_ck)); + if (!apad_ck) { + clk_free(clk); + return NULL; + } + + clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + apad_ck->base = pmc->base; + + clk->priv = apad_ck; + if (clk_register(clk)) { + clk_free(clk); + free(apad_ck); + return NULL; + } + + return clk; +} + +struct clk * +at91_clk_register_audio_pll_pmc(struct pmc_data *pmc, const char *name, + struct clk *parent) +{ + struct clk_audio_pmc *apmc_ck = NULL; + struct clk *clk = NULL; + + clk = clk_alloc(name, &audio_pll_pmc_ops, &parent, 1); + if (!clk) + return NULL; + + apmc_ck = calloc(1, sizeof(*apmc_ck)); + if (!apmc_ck) { + clk_free(clk); + return NULL; + } + + clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + apmc_ck->base = pmc->base; + + clk->priv = apmc_ck; + + if (clk_register(clk)) { + clk_free(clk); + free(apmc_ck); + return NULL; + } + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_clk.h b/optee/optee_os/core/drivers/clk/sam/at91_clk.h new file mode 100644 index 0000000..5918418 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_clk.h @@ -0,0 +1,236 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * include/linux/clk/at91_pmc.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * Copyright (C) 2021 Microchip + * + * Power Management Controller (PMC) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + */ + +#ifndef AT91_CLK_H +#define AT91_CLK_H + +#include +#include + +#include "at91_pmc.h" + +#define ffs(x) __builtin_ffs(x) + +#define field_get(_mask, _reg) \ + ({ \ + typeof(_mask) __mask = _mask; \ + \ + (((_reg) & (__mask)) >> (ffs(__mask) - 1)); \ + }) +#define field_prep(_mask, _val) \ + ({ \ + typeof(_mask) __mask = _mask; \ + \ + (((_val) << (ffs(__mask) - 1)) & (__mask)); \ + }) + +struct clk_range { + unsigned long min; + unsigned long max; +}; + +#define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,} + +struct pmc_clk { + struct clk *clk; + uint8_t id; +}; + +struct pmc_data { + vaddr_t base; + unsigned int ncore; + struct pmc_clk *chws; + unsigned int nsystem; + struct pmc_clk *shws; + unsigned int nperiph; + struct pmc_clk *phws; + unsigned int ngck; + struct pmc_clk *ghws; + unsigned int npck; + struct pmc_clk *pchws; + + struct pmc_clk hwtable[]; +}; + +/* PLL */ +struct clk_pll_layout { + uint32_t pllr_mask; + uint32_t mul_mask; + uint32_t frac_mask; + uint32_t div_mask; + uint32_t endiv_mask; + uint8_t mul_shift; + uint8_t frac_shift; + uint8_t div_shift; + uint8_t endiv_shift; +}; + +struct clk_pcr_layout { + uint32_t offset; + uint32_t cmd; + uint32_t div_mask; + uint32_t gckcss_mask; + uint32_t pid_mask; +}; + +struct clk_pll_charac { + struct clk_range input; + int num_output; + const struct clk_range *output; + uint16_t *icpll; + uint8_t *out; + uint8_t upll : 1; +}; + +extern const struct clk_pll_layout sama5d3_pll_layout; + +/* Master */ +struct clk_master_charac { + struct clk_range output; + uint32_t divisors[5]; + uint8_t have_div3_pres; +}; + +struct clk_master_layout { + uint32_t offset; + uint32_t mask; + uint8_t pres_shift; +}; + +struct clk_programmable_layout { + uint8_t pres_mask; + uint8_t pres_shift; + uint8_t css_mask; + uint8_t have_slck_mck; + uint8_t is_pres_direct; +}; + +extern const struct clk_master_layout at91sam9x5_master_layout; + +vaddr_t at91_pmc_get_base(void); + +struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem, + unsigned int nperiph, unsigned int ngck, + unsigned int npck); + +struct clk *clk_dt_pmc_get(struct dt_driver_phandle_args *args, void *data, + TEE_Result *res); + +struct clk *pmc_clk_get_by_name(struct pmc_clk *clks, unsigned int nclk, + const char *name); + +/* Main clock */ +struct clk *pmc_register_main_rc_osc(struct pmc_data *pmc, const char *name, + unsigned long freq); + +struct clk *pmc_register_main_osc(struct pmc_data *pmc, const char *name, + struct clk *parent, bool bypass); + +struct clk *at91_clk_register_sam9x5_main(struct pmc_data *pmc, + const char *name, + struct clk **parent_clocks, + unsigned int num_parents); + +/* PLL */ +struct clk * +at91_clk_register_pll(struct pmc_data *pmc, const char *name, + struct clk *parent, uint8_t id, + const struct clk_pll_layout *layout, + const struct clk_pll_charac *charac); + +struct clk * +at91_clk_register_plldiv(struct pmc_data *pmc, const char *name, + struct clk *parent); + +/* UTMI */ +struct clk * +at91_clk_register_utmi(struct pmc_data *pmc, const char *name, + struct clk *parent); + +/* Master */ +struct clk * +at91_clk_register_master_pres(struct pmc_data *pmc, + const char *name, int num_parents, + struct clk **parents, + const struct clk_master_layout *layout, + const struct clk_master_charac *charac, + int chg_pid); + +struct clk * +at91_clk_register_master_div(struct pmc_data *pmc, + const char *name, struct clk *parent, + const struct clk_master_layout *layout, + const struct clk_master_charac *charac); + +/* H32MX */ +struct clk * +at91_clk_register_h32mx(struct pmc_data *pmc, const char *name, + struct clk *parent); + +/* USB */ +struct clk * +at91sam9x5_clk_register_usb(struct pmc_data *pmc, const char *name, + struct clk **parents, uint8_t num_parents); + +/* Programmable */ +struct clk * +at91_clk_register_programmable(struct pmc_data *pmc, + const char *name, struct clk **parents, + uint8_t num_parents, uint8_t id, + const struct clk_programmable_layout *layout); + +struct clk * +at91_clk_register_system(struct pmc_data *pmc, const char *name, + struct clk *parent, uint8_t id); + +struct clk * +at91_clk_register_sam9x5_periph(struct pmc_data *pmc, + const struct clk_pcr_layout *layout, + const char *name, struct clk *parent, + uint32_t id, const struct clk_range *range); + +struct clk * +at91_clk_register_generated(struct pmc_data *pmc, + const struct clk_pcr_layout *layout, + const char *name, struct clk **parents, + uint8_t num_parents, uint8_t id, + const struct clk_range *range, + int chg_pid); + +struct clk * +at91_clk_i2s_mux_register(const char *name, struct clk **parents, + unsigned int num_parents, uint8_t bus_id); + +/* Audio PLL */ +struct clk * +at91_clk_register_audio_pll_frac(struct pmc_data *pmc, const char *name, + struct clk *parent); + +struct clk * +at91_clk_register_audio_pll_pad(struct pmc_data *pmc, const char *name, + struct clk *parent); + +struct clk * +at91_clk_register_audio_pll_pmc(struct pmc_data *pmc, const char *name, + struct clk *parent); + +#ifdef CFG_PM_ARM32 +void pmc_register_id(uint8_t id); +void pmc_register_pck(uint8_t pck); +void pmc_register_pm(void); +#else +static inline void pmc_register_id(uint8_t id __unused) {} +static inline void pmc_register_pck(uint8_t pck __unused) {} +static inline void pmc_register_pm(void) {} +#endif + +#endif diff --git a/optee/optee_os/core/drivers/clk/sam/at91_generated.c b/optee/optee_os/core/drivers/clk/sam/at91_generated.c new file mode 100644 index 0000000..3c4c2af --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_generated.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2015 - 2021 Atmel Corporation, + * Nicolas Ferre + * + * Based on clk-programmable & clk-peripheral drivers by Boris BREZILLON. + */ + +#include +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define GENERATED_MAX_DIV 255 + +struct clk_generated { + vaddr_t base; + struct clk_range range; + uint32_t *mux_table; + uint32_t id; + uint32_t gckdiv; + const struct clk_pcr_layout *layout; + uint8_t parent_id; + int chg_pid; +}; + +static TEE_Result clk_generated_enable(struct clk *clk) +{ + struct clk_generated *gck = clk->priv; + + io_write32(gck->base + gck->layout->offset, + (gck->id & gck->layout->pid_mask)); + io_clrsetbits32(gck->base + gck->layout->offset, + AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask | + gck->layout->cmd | AT91_PMC_PCR_GCKEN, + field_prep(gck->layout->gckcss_mask, gck->parent_id) | + gck->layout->cmd | + ((gck->gckdiv << AT91_PMC_PCR_GCKDIV_SHIFT) & + AT91_PMC_PCR_GCKDIV_MASK) | + AT91_PMC_PCR_GCKEN); + + return TEE_SUCCESS; +} + +static void clk_generated_disable(struct clk *clk) +{ + struct clk_generated *gck = clk->priv; + + io_write32(gck->base + gck->layout->offset, + gck->id & gck->layout->pid_mask); + io_clrsetbits32(gck->base + gck->layout->offset, AT91_PMC_PCR_GCKEN, + gck->layout->cmd); +} + +static unsigned long +clk_generated_get_rate(struct clk *clk, unsigned long parent_rate) +{ + struct clk_generated *gck = clk->priv; + + return UDIV_ROUND_NEAREST(parent_rate, gck->gckdiv + 1); +} + +/* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */ +static TEE_Result clk_generated_set_parent(struct clk *clk, size_t index) +{ + struct clk_generated *gck = clk->priv; + + if (index >= clk_get_num_parents(clk)) + return TEE_ERROR_BAD_PARAMETERS; + + gck->parent_id = index; + + return TEE_SUCCESS; +} + +static size_t clk_generated_get_parent(struct clk *clk) +{ + struct clk_generated *gck = clk->priv; + + return gck->parent_id; +} + +/* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */ +static TEE_Result clk_generated_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_generated *gck = clk->priv; + uint32_t div = 1; + + if (!rate) + return TEE_ERROR_BAD_PARAMETERS; + + if (gck->range.max && rate > gck->range.max) + return TEE_ERROR_BAD_PARAMETERS; + + div = UDIV_ROUND_NEAREST(parent_rate, rate); + if (div > GENERATED_MAX_DIV + 1 || !div) + return TEE_ERROR_GENERIC; + + gck->gckdiv = div - 1; + return TEE_SUCCESS; +} + +static const struct clk_ops generated_ops = { + .enable = clk_generated_enable, + .disable = clk_generated_disable, + .get_rate = clk_generated_get_rate, + .get_parent = clk_generated_get_parent, + .set_parent = clk_generated_set_parent, + .set_rate = clk_generated_set_rate, +}; + +/** + * clk_generated_startup - Initialize a given clock to its default parent and + * divisor parameter. + * + * @gck: Generated clock to set the startup parameters for. + * + * Take parameters from the hardware and update local clock configuration + * accordingly. + */ +static void clk_generated_startup(struct clk_generated *gck) +{ + uint32_t tmp = 0; + + io_write32(gck->base + gck->layout->offset, + (gck->id & gck->layout->pid_mask)); + tmp = io_read32(gck->base + gck->layout->offset); + + gck->parent_id = field_get(gck->layout->gckcss_mask, tmp); + gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK) >> + AT91_PMC_PCR_GCKDIV_SHIFT; +} + +struct clk * +at91_clk_register_generated(struct pmc_data *pmc, + const struct clk_pcr_layout *layout, + const char *name, struct clk **parents, + uint8_t num_parents, uint8_t id, + const struct clk_range *range, + int chg_pid) +{ + struct clk_generated *gck = NULL; + struct clk *clk = NULL; + + clk = clk_alloc(name, &generated_ops, parents, num_parents); + if (!clk) + return NULL; + + gck = calloc(1, sizeof(*gck)); + if (!gck) { + clk_free(clk); + return NULL; + } + + clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + gck->id = id; + gck->base = pmc->base; + memcpy(&gck->range, range, sizeof(gck->range)); + gck->chg_pid = chg_pid; + gck->layout = layout; + + clk->priv = gck; + + clk_generated_startup(gck); + + if (clk_register(clk)) { + clk_free(clk); + free(gck); + return NULL; + } + pmc_register_id(id); + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_h32mx.c b/optee/optee_os/core/drivers/clk/sam/at91_h32mx.c new file mode 100644 index 0000000..404aa4f --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_h32mx.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2014 Atmel + * + * Alexandre Belloni + */ + +#include +#include +#include +#include + +#include "at91_clk.h" + +#define H32MX_MAX_FREQ 90000000 + +static unsigned long clk_sama5d4_h32mx_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct pmc_data *pmc = clk->priv; + unsigned int mckr = io_read32(pmc->base + AT91_PMC_MCKR); + + if (mckr & AT91_PMC_H32MXDIV) + return parent_rate / 2; + + if (parent_rate > H32MX_MAX_FREQ) + IMSG("H32MX clock is too fast"); + + return parent_rate; +} + +static TEE_Result clk_sama5d4_h32mx_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate) +{ + struct pmc_data *pmc = clk->priv; + uint32_t mckr = 0; + + if (parent_rate != rate && (parent_rate / 2) != rate) + return TEE_ERROR_BAD_PARAMETERS; + + if ((parent_rate / 2) == rate) + mckr = AT91_PMC_H32MXDIV; + + io_clrsetbits32(pmc->base + AT91_PMC_MCKR, AT91_PMC_H32MXDIV, mckr); + + return TEE_SUCCESS; +} + +static const struct clk_ops h32mx_ops = { + .get_rate = clk_sama5d4_h32mx_get_rate, + .set_rate = clk_sama5d4_h32mx_set_rate, +}; + +struct clk * +at91_clk_register_h32mx(struct pmc_data *pmc, const char *name, + struct clk *parent) +{ + struct clk *clk = NULL; + + clk = clk_alloc(name, &h32mx_ops, &parent, 1); + if (!clk) + return NULL; + + clk->ops = &h32mx_ops; + clk->priv = pmc; + clk->name = name; + clk->flags = CLK_SET_RATE_GATE; + + if (clk_register(clk)) { + clk_free(clk); + return NULL; + } + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_i2s_mux.c b/optee/optee_os/core/drivers/clk/sam/at91_i2s_mux.c new file mode 100644 index 0000000..6d767bd --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_i2s_mux.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2018 Microchip Technology Inc, + * Codrin Ciubotariu + */ + +#include +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +struct clk_i2s_mux { + vaddr_t sfr_base; + uint8_t bus_id; +}; + +static size_t clk_i2s_mux_get_parent(struct clk *clk) +{ + struct clk_i2s_mux *mux = clk->priv; + uint32_t val = io_read32(mux->sfr_base + AT91_SFR_I2SCLKSEL); + + return (val & BIT(mux->bus_id)) >> mux->bus_id; +} + +static TEE_Result clk_i2s_mux_set_parent(struct clk *clk, size_t index) +{ + struct clk_i2s_mux *mux = clk->priv; + + io_clrsetbits32(mux->sfr_base + AT91_SFR_I2SCLKSEL, + BIT(mux->bus_id), index << mux->bus_id); + + return TEE_SUCCESS; +} + +static const struct clk_ops clk_i2s_mux_ops = { + .get_parent = clk_i2s_mux_get_parent, + .set_parent = clk_i2s_mux_set_parent, +}; + +struct clk * +at91_clk_i2s_mux_register(const char *name, struct clk **parents, + unsigned int num_parents, uint8_t bus_id) +{ + struct clk_i2s_mux *i2s_ck = NULL; + struct clk *clk = NULL; + + clk = clk_alloc(name, &clk_i2s_mux_ops, parents, num_parents); + if (!clk) + return NULL; + + i2s_ck = calloc(1, sizeof(*i2s_ck)); + if (!i2s_ck) { + clk_free(clk); + return NULL; + } + + i2s_ck->bus_id = bus_id; + i2s_ck->sfr_base = sam_sfr_base(); + + clk->priv = i2s_ck; + + if (clk_register(clk)) { + clk_free(clk); + free(i2s_ck); + return NULL; + } + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_main.c b/optee/optee_os/core/drivers/clk/sam/at91_main.c new file mode 100644 index 0000000..0f4229d --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_main.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define SLOW_CLOCK_FREQ 32768 +#define MAINF_DIV 16 +#define USEC_PER_SEC 1000000L +#define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ) + +#define OSC_READY_TIMEOUT_US 1000 + +#define MOR_KEY_MASK (0xFF << 16) + +#define CLK_MAIN_PARENT_SELECT(s) (((s) & \ + (AT91_PMC_MOSCEN | \ + AT91_PMC_OSCBYPASS)) ? 1 : 0) + +/* + * Main RC Oscillator + */ + +struct main_rc_osc { + unsigned long freq; + vaddr_t base; +}; + +static bool pmc_main_rc_osc_ready(struct main_rc_osc *osc) +{ + uint32_t status = io_read32(osc->base + AT91_PMC_SR); + + return status & AT91_PMC_MOSCRCS; +} + +static TEE_Result pmc_main_rc_osc_enable(struct clk *clk) +{ + struct main_rc_osc *osc = clk->priv; + uint32_t mor = io_read32(osc->base + AT91_CKGR_MOR); + + /* Enable the oscillator if not */ + if (!(mor & AT91_PMC_MOSCRCEN)) { + io_clrsetbits32(osc->base + AT91_CKGR_MOR, + MOR_KEY_MASK | AT91_PMC_MOSCRCEN, + AT91_PMC_MOSCRCEN | AT91_PMC_KEY); + } + + while (!pmc_main_rc_osc_ready(osc)) + ; + + return TEE_SUCCESS; +} + +static void pmc_main_rc_osc_disable(struct clk *clk) +{ + struct main_rc_osc *osc = clk->priv; + uint32_t mor = io_read32(osc->base + AT91_CKGR_MOR); + + if (!(mor & AT91_PMC_MOSCRCEN)) + return; + + io_clrsetbits32(osc->base + AT91_CKGR_MOR, + MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY); +} + +static unsigned long +pmc_main_rc_osc_get_rate(struct clk *clk, unsigned long parent_rate __unused) +{ + struct main_rc_osc *osc = clk->priv; + + return osc->freq; +} + +static const struct clk_ops pmc_main_rc_osc_clk_ops = { + .enable = pmc_main_rc_osc_enable, + .disable = pmc_main_rc_osc_disable, + .get_rate = pmc_main_rc_osc_get_rate, +}; + +struct clk *pmc_register_main_rc_osc(struct pmc_data *pmc, const char *name, + unsigned long freq) +{ + struct clk *clk = NULL; + struct main_rc_osc *osc = NULL; + + clk = clk_alloc(name, &pmc_main_rc_osc_clk_ops, NULL, 0); + if (!clk) + return NULL; + + osc = calloc(1, sizeof(*osc)); + if (!osc) { + clk_free(clk); + return NULL; + } + + osc->freq = freq; + osc->base = pmc->base; + + clk->priv = osc; + + if (clk_register(clk)) { + free(osc); + clk_free(clk); + return NULL; + } + + return clk; +} + +/* + * Main Oscillator + */ +static bool pmc_main_osc_ready(struct pmc_data *pmc) +{ + uint32_t status = io_read32(pmc->base + AT91_PMC_SR); + + return status & AT91_PMC_MOSCS; +} + +static TEE_Result pmc_main_osc_enable(struct clk *clk) +{ + struct pmc_data *pmc = clk->priv; + uint32_t mor = io_read32(pmc->base + AT91_CKGR_MOR); + + mor &= ~MOR_KEY_MASK; + + if (mor & AT91_PMC_OSCBYPASS) + return TEE_SUCCESS; + + if (!(mor & AT91_PMC_MOSCEN)) { + mor |= AT91_PMC_MOSCEN | AT91_PMC_KEY; + io_write32(pmc->base + AT91_CKGR_MOR, mor); + } + + while (!pmc_main_osc_ready(pmc)) + ; + + return TEE_SUCCESS; +} + +static void pmc_main_osc_disable(struct clk *clk) +{ + struct pmc_data *pmc = clk->priv; + uint32_t mor = io_read32(pmc->base + AT91_CKGR_MOR); + + if (mor & AT91_PMC_OSCBYPASS) + return; + + if (!(mor & AT91_PMC_MOSCEN)) + return; + + mor &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN); + io_write32(pmc->base + AT91_CKGR_MOR, mor | AT91_PMC_KEY); +} + +static const struct clk_ops pmc_main_osc_clk_ops = { + .enable = pmc_main_osc_enable, + .disable = pmc_main_osc_disable, +}; + +struct clk *pmc_register_main_osc(struct pmc_data *pmc, const char *name, + struct clk *parent, bool bypass) +{ + struct clk *clk = NULL; + + clk = clk_alloc(name, &pmc_main_osc_clk_ops, &parent, 1); + if (!clk) + panic(); + + clk->priv = pmc; + + if (bypass) + io_clrsetbits32(pmc->base + AT91_CKGR_MOR, + MOR_KEY_MASK | AT91_PMC_OSCBYPASS, + AT91_PMC_OSCBYPASS | AT91_PMC_KEY); + + if (clk_register(clk)) { + clk_free(clk); + return NULL; + } + + return clk; +} + +/* + * Main Clock + */ +static TEE_Result clk_main_probe_frequency(vaddr_t base) +{ + while (!(io_read32(base + AT91_CKGR_MCFR) & AT91_PMC_MAINRDY)) + ; + + return TEE_SUCCESS; +} + +static unsigned long clk_main_get_rate(vaddr_t base, + unsigned long parent_rate) +{ + uint32_t mcfr = 0; + + if (parent_rate) + return parent_rate; + + IMSG("Main crystal frequency not set, using approximate value"); + mcfr = io_read32(base + AT91_CKGR_MCFR); + if (!(mcfr & AT91_PMC_MAINRDY)) + return 0; + + return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; +} + +static bool clk_sam9x5_main_ready(vaddr_t base) +{ + uint32_t status = io_read32(base + AT91_PMC_SR); + + return status & AT91_PMC_MOSCSELS; +} + +static TEE_Result clk_sam9x5_main_enable(struct clk *clk) +{ + struct pmc_data *pmc = clk->priv; + + while (!clk_sam9x5_main_ready(pmc->base)) + ; + + return clk_main_probe_frequency(pmc->base); +} + +static unsigned long clk_sam9x5_main_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct pmc_data *pmc = clk->priv; + + return clk_main_get_rate(pmc->base, parent_rate); +} + +static TEE_Result clk_sam9x5_main_set_parent(struct clk *clk, size_t index) +{ + struct pmc_data *pmc = clk->priv; + uint32_t tmp = 0; + + if (index > 1) + return TEE_ERROR_BAD_PARAMETERS; + + tmp = io_read32(pmc->base + AT91_CKGR_MOR); + + if (index && !(tmp & AT91_PMC_MOSCSEL)) + tmp = AT91_PMC_MOSCSEL; + else if (!index && (tmp & AT91_PMC_MOSCSEL)) + tmp = 0; + else + return TEE_SUCCESS; + + io_clrsetbits32(pmc->base + AT91_CKGR_MOR, + AT91_PMC_MOSCSEL | MOR_KEY_MASK, + tmp | AT91_PMC_KEY); + + while (!clk_sam9x5_main_ready(pmc->base)) + ; + + return TEE_SUCCESS; +} + +static size_t clk_sam9x5_main_get_parent(struct clk *clk) +{ + struct pmc_data *pmc = clk->priv; + uint32_t status = io_read32(pmc->base + AT91_CKGR_MOR); + + return CLK_MAIN_PARENT_SELECT(status); +} + +static const struct clk_ops sam9x5_main_ops = { + .enable = clk_sam9x5_main_enable, + .get_rate = clk_sam9x5_main_get_rate, + .set_parent = clk_sam9x5_main_set_parent, + .get_parent = clk_sam9x5_main_get_parent, +}; + +struct clk * +at91_clk_register_sam9x5_main(struct pmc_data *pmc, + const char *name, + struct clk **parent_clocks, + unsigned int num_parents) +{ + struct clk *clk = NULL; + + if (!name) + return NULL; + + if (!parent_clocks || !num_parents) + return NULL; + + clk = clk_alloc(name, &sam9x5_main_ops, parent_clocks, num_parents); + if (!clk) + return NULL; + + clk->flags = CLK_SET_PARENT_GATE; + clk->priv = pmc; + + if (clk_register(clk)) { + clk_free(clk); + return NULL; + } + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_master.c b/optee/optee_os/core/drivers/clk/sam/at91_master.c new file mode 100644 index 0000000..1780d48 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_master.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include + +#include "at91_clk.h" + +#define MASTER_PRES_MASK 0x7 +#define MASTER_PRES_MAX MASTER_PRES_MASK +#define MASTER_DIV_SHIFT 8 +#define MASTER_DIV_MASK 0x7 + +struct clk_master { + vaddr_t base; + const struct clk_master_layout *layout; + const struct clk_master_charac *charac; + uint32_t *mux_table; + uint32_t mckr; + int chg_pid; + uint8_t div; +}; + +static bool clk_master_ready(struct clk_master *master) +{ + uint32_t status = io_read32(master->base + AT91_PMC_SR); + + return status & AT91_PMC_MCKRDY; +} + +static TEE_Result clk_master_enable(struct clk *clk) +{ + struct clk_master *master = clk->priv; + + while (!clk_master_ready(master)) + ; + + return TEE_SUCCESS; +} + +static unsigned long clk_master_div_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + uint8_t div = 1; + uint32_t mckr = 0; + unsigned long rate = parent_rate; + struct clk_master *master = clk->priv; + const struct clk_master_layout *layout = master->layout; + const struct clk_master_charac *charac = master->charac; + + mckr = io_read32(master->base + master->layout->offset); + + mckr &= layout->mask; + + div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; + + rate /= charac->divisors[div]; + + if (rate < charac->output.min) + IMSG("master clk div is underclocked"); + else if (rate > charac->output.max) + IMSG("master clk div is overclocked"); + + return rate; +} + +static const struct clk_ops master_div_ops = { + .enable = clk_master_enable, + .get_rate = clk_master_div_get_rate, +}; + +static unsigned long clk_master_pres_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_master *master = clk->priv; + const struct clk_master_charac *charac = master->charac; + uint32_t val = 0; + unsigned int pres = 0; + + val = io_read32(master->base + master->layout->offset); + + pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK; + if (pres != 3 || !charac->have_div3_pres) + pres = BIT(pres); + + return UDIV_ROUND_NEAREST(parent_rate, pres); +} + +static size_t clk_master_pres_get_parent(struct clk *clk) +{ + struct clk_master *master = clk->priv; + uint32_t mckr = 0; + + mckr = io_read32(master->base + master->layout->offset); + + return mckr & AT91_PMC_CSS; +} + +static const struct clk_ops master_pres_ops = { + .enable = clk_master_enable, + .get_rate = clk_master_pres_get_rate, + .get_parent = clk_master_pres_get_parent, +}; + +static struct clk * +at91_clk_register_master_internal(struct pmc_data *pmc, + const char *name, int num_parents, + struct clk **parents, + const struct clk_master_layout *layout, + const struct clk_master_charac *charac, + const struct clk_ops *ops, int chg_pid) +{ + struct clk_master *master = NULL; + struct clk *clk = NULL; + + if (!name || !num_parents || !parents) + return NULL; + + clk = clk_alloc(name, ops, parents, num_parents); + if (!clk) + return NULL; + + master = calloc(1, sizeof(*master)); + if (!master) { + clk_free(clk); + return NULL; + } + + master->layout = layout; + master->charac = charac; + master->base = pmc->base; + master->chg_pid = chg_pid; + + clk->priv = master; + clk->flags = CLK_SET_RATE_GATE; + + if (clk_register(clk)) { + clk_free(clk); + free(master); + return NULL; + } + + return clk; +} + +struct clk * +at91_clk_register_master_pres(struct pmc_data *pmc, + const char *name, int num_parents, + struct clk **parents, + const struct clk_master_layout *layout, + const struct clk_master_charac *charac, + int chg_pid) +{ + return at91_clk_register_master_internal(pmc, name, num_parents, + parents, layout, + charac, + &master_pres_ops, chg_pid); +} + +struct clk * +at91_clk_register_master_div(struct pmc_data *pmc, + const char *name, struct clk *parent, + const struct clk_master_layout *layout, + const struct clk_master_charac *charac) +{ + return at91_clk_register_master_internal(pmc, name, 1, + &parent, layout, + charac, + &master_div_ops, -1); +} + +const struct clk_master_layout at91sam9x5_master_layout = { + .mask = 0x373, + .pres_shift = 4, + .offset = AT91_PMC_MCKR, +}; diff --git a/optee/optee_os/core/drivers/clk/sam/at91_peripheral.c b/optee/optee_os/core/drivers/clk/sam/at91_peripheral.c new file mode 100644 index 0000000..7538a6c --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_peripheral.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define PERIPHERAL_ID_MIN 2 +#define PERIPHERAL_ID_MASK 31 +#define PERIPHERAL_MASK(id) BIT((id) & PERIPHERAL_ID_MASK) + +#define PERIPHERAL_MAX_SHIFT 3 + +struct clk_sam9x5_peripheral { + vaddr_t base; + struct clk_range range; + uint32_t id; + uint32_t div; + const struct clk_pcr_layout *layout; + bool auto_div; +}; + +static void clk_sam9x5_peripheral_autodiv(struct clk *clk) +{ + struct clk *parent = NULL; + struct clk_sam9x5_peripheral *periph = clk->priv; + unsigned long parent_rate = 0; + int shift = 0; + + if (!periph->auto_div) + return; + + if (periph->range.max) { + parent = clk_get_parent_by_index(clk, 0); + parent_rate = clk_get_rate(parent); + if (!parent_rate) + return; + + for (shift = 0; shift < PERIPHERAL_MAX_SHIFT; shift++) { + if (parent_rate >> shift <= periph->range.max) + break; + } + } + + periph->auto_div = false; + periph->div = shift; +} + +static TEE_Result clk_sam9x5_peripheral_enable(struct clk *clk) +{ + struct clk_sam9x5_peripheral *periph = clk->priv; + + if (periph->id < PERIPHERAL_ID_MIN) + return TEE_SUCCESS; + + io_write32(periph->base + periph->layout->offset, + (periph->id & periph->layout->pid_mask)); + io_clrsetbits32(periph->base + periph->layout->offset, + periph->layout->div_mask | periph->layout->cmd | + AT91_PMC_PCR_EN, + field_prep(periph->layout->div_mask, periph->div) | + periph->layout->cmd | + AT91_PMC_PCR_EN); + + return TEE_SUCCESS; +} + +static void clk_sam9x5_peripheral_disable(struct clk *clk) +{ + struct clk_sam9x5_peripheral *periph = clk->priv; + + if (periph->id < PERIPHERAL_ID_MIN) + return; + + io_write32(periph->base + periph->layout->offset, + (periph->id & periph->layout->pid_mask)); + io_clrsetbits32(periph->base + periph->layout->offset, + AT91_PMC_PCR_EN | periph->layout->cmd, + periph->layout->cmd); +} + +static unsigned long +clk_sam9x5_peripheral_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_sam9x5_peripheral *periph = clk->priv; + uint32_t status = 0; + + if (periph->id < PERIPHERAL_ID_MIN) + return parent_rate; + + io_write32(periph->base + periph->layout->offset, + periph->id & periph->layout->pid_mask); + status = io_read32(periph->base + periph->layout->offset); + + if (status & AT91_PMC_PCR_EN) { + periph->div = field_get(periph->layout->div_mask, status); + periph->auto_div = false; + } else { + clk_sam9x5_peripheral_autodiv(clk); + } + + return parent_rate >> periph->div; +} + +static TEE_Result clk_sam9x5_peripheral_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned int shift = 0; + struct clk_sam9x5_peripheral *periph = clk->priv; + + if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) { + if (parent_rate == rate) + return TEE_SUCCESS; + else + return TEE_ERROR_GENERIC; + } + + if (periph->range.max && rate > periph->range.max) + return TEE_ERROR_GENERIC; + + for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) { + if (parent_rate >> shift == rate) { + periph->auto_div = false; + periph->div = shift; + return TEE_SUCCESS; + } + } + + return TEE_ERROR_GENERIC; +} + +static const struct clk_ops sam9x5_peripheral_ops = { + .enable = clk_sam9x5_peripheral_enable, + .disable = clk_sam9x5_peripheral_disable, + .get_rate = clk_sam9x5_peripheral_get_rate, + .set_rate = clk_sam9x5_peripheral_set_rate, +}; + +struct clk * +at91_clk_register_sam9x5_periph(struct pmc_data *pmc, + const struct clk_pcr_layout *layout, + const char *name, struct clk *parent, + uint32_t id, const struct clk_range *range) +{ + struct clk_sam9x5_peripheral *periph = NULL; + struct clk *clk = NULL; + + if (!name || !parent) + return NULL; + + clk = clk_alloc(name, &sam9x5_peripheral_ops, &parent, 1); + if (!clk) + return NULL; + + periph = calloc(1, sizeof(*periph)); + if (!periph) { + clk_free(clk); + return NULL; + } + + periph->id = id; + periph->div = 0; + periph->base = pmc->base; + if (layout->div_mask) + periph->auto_div = true; + periph->layout = layout; + periph->range = *range; + + clk->priv = periph; + + if (clk_register(clk)) { + clk_free(clk); + free(periph); + return 0; + } + + clk_sam9x5_peripheral_autodiv(clk); + pmc_register_id(id); + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_pll.c b/optee/optee_os/core/drivers/clk/sam/at91_pll.c new file mode 100644 index 0000000..57e5f88 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_pll.c @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define PLL_STATUS_MASK(id) BIT(1 + (id)) +#define PLL_REG(id) (AT91_CKGR_PLLAR + ((id) * 4)) +#define PLL_DIV_MASK 0xff +#define PLL_DIV_MAX PLL_DIV_MASK +#define PLL_DIV(reg) ((reg) & PLL_DIV_MASK) +#define PLL_MUL(reg, layout) \ + ({ \ + typeof(layout) __layout = layout; \ + \ + (((reg) >> (__layout)->mul_shift) & (__layout)->mul_mask); \ + }) +#define PLL_MUL_MIN 2 +#define PLL_MUL_MASK(layout) ((layout)->mul_mask) +#define PLL_MUL_MAX(layout) (PLL_MUL_MASK(layout) + 1) +#define PLL_ICPR_SHIFT(id) ((id) * 16) +#define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id)) +#define PLL_MAX_COUNT 0x3f +#define PLL_COUNT_SHIFT 8 +#define PLL_OUT_SHIFT 14 +#define PLL_MAX_ID 1 + +struct clk_pll { + vaddr_t base; + uint8_t id; + uint8_t div; + uint8_t range; + uint16_t mul; + const struct clk_pll_layout *layout; + const struct clk_pll_charac *charac; +}; + +static bool clk_pll_ready(vaddr_t base, int id) +{ + unsigned int status = io_read32(base + AT91_PMC_SR); + + return status & PLL_STATUS_MASK(id); +} + +static TEE_Result clk_pll_enable(struct clk *clk) +{ + struct clk_pll *pll = clk->priv; + const struct clk_pll_layout *layout = pll->layout; + const struct clk_pll_charac *charac = pll->charac; + uint8_t id = pll->id; + uint32_t mask = PLL_STATUS_MASK(id); + int offset = PLL_REG(id); + uint8_t out = 0; + unsigned int pllr = 0; + unsigned int status = 0; + uint8_t div = 0; + uint16_t mul = 0; + + pllr = io_read32(pll->base + offset); + div = PLL_DIV(pllr); + mul = PLL_MUL(pllr, layout); + + status = io_read32(pll->base + AT91_PMC_SR); + if ((status & mask) && + (div == pll->div && mul == pll->mul)) + return TEE_SUCCESS; + + if (charac->out) + out = charac->out[pll->range]; + + if (charac->icpll) + io_clrsetbits32(pll->base + AT91_PMC_PLLICPR, PLL_ICPR_MASK(id), + charac->icpll[pll->range] << + PLL_ICPR_SHIFT(id)); + + io_clrsetbits32(pll->base + offset, layout->pllr_mask, + pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | + (out << PLL_OUT_SHIFT) | + ((pll->mul & layout->mul_mask) << layout->mul_shift)); + + while (!clk_pll_ready(pll->base, pll->id)) + ; + + return TEE_SUCCESS; +} + +static void clk_pll_disable(struct clk *clk) +{ + struct clk_pll *pll = clk->priv; + unsigned int mask = pll->layout->pllr_mask; + + io_clrsetbits32(pll->base + PLL_REG(pll->id), mask, ~mask); +} + +static unsigned long clk_pll_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_pll *pll = clk->priv; + + if (!pll->div || !pll->mul) + return 0; + + return (parent_rate / pll->div) * (pll->mul + 1); +} + +static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, + unsigned long parent_rate, + uint32_t *div, uint32_t *mul, + uint32_t *index) +{ + const struct clk_pll_layout *layout = pll->layout; + const struct clk_pll_charac *charac = pll->charac; + unsigned long bestremainder = ULONG_MAX; + unsigned long maxdiv = 1; + unsigned long mindiv = 1; + unsigned long tmpdiv = 1; + long bestrate = -1; + unsigned long bestdiv = 0; + unsigned long bestmul = 0; + int i = 0; + + /* Check if parent_rate is a valid input rate */ + if (parent_rate < charac->input.min) + return -1; + + /* + * Calculate minimum divider based on the minimum multiplier, the + * parent_rate and the requested rate. + * Should always be 2 according to the input and output charac + * of the PLL blocks. + */ + mindiv = (parent_rate * PLL_MUL_MIN) / rate; + if (!mindiv) + mindiv = 1; + + if (parent_rate > charac->input.max) { + tmpdiv = DIV_ROUND_UP(parent_rate, charac->input.max); + if (tmpdiv > PLL_DIV_MAX) + return -1; + + if (tmpdiv > mindiv) + mindiv = tmpdiv; + } + + /* + * Calculate the maximum divider which is limited by PLL register + * layout (limited by the MUL or DIV field size). + */ + maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX(layout), rate); + if (maxdiv > PLL_DIV_MAX) + maxdiv = PLL_DIV_MAX; + + /* + * Iterate over the acceptable divider values to find the best + * divider/multiplier pair (the one that generates the closest + * rate to the requested one). + */ + for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) { + unsigned long remainder = 0; + unsigned long tmprate = 0; + unsigned long tmpmul = 0; + + /* + * Calculate the multiplier associated with the current + * divider that provide the closest rate to the requested one. + */ + tmpmul = UDIV_ROUND_NEAREST(rate, parent_rate / tmpdiv); + tmprate = (parent_rate / tmpdiv) * tmpmul; + if (tmprate > rate) + remainder = tmprate - rate; + else + remainder = rate - tmprate; + + /* + * Compare the remainder with the best remainder found until + * now and elect a new best multiplier/divider pair if the + * current remainder is smaller than the best one. + */ + if (remainder < bestremainder) { + bestremainder = remainder; + bestdiv = tmpdiv; + bestmul = tmpmul; + bestrate = tmprate; + } + + /* + * We've found a perfect match! + * Stop searching now and use this multiplier/divider pair. + */ + if (!remainder) + break; + } + + /* We haven't found any multiplier/divider pair => return -ERANGE */ + if (bestrate < 0) + return bestrate; + + /* Check if bestrate is a valid output rate */ + for (i = 0; i < charac->num_output; i++) { + if (bestrate >= (long)charac->output[i].min && + bestrate <= (long)charac->output[i].max) + break; + } + + if (i >= charac->num_output) + return -1; + + if (div) + *div = bestdiv; + if (mul) + *mul = bestmul - 1; + if (index) + *index = i; + + return bestrate; +} + +static TEE_Result clk_pll_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_pll *pll = clk->priv; + long ret = -1; + uint32_t div = 1; + uint32_t mul = 0; + uint32_t index = 0; + + ret = clk_pll_get_best_div_mul(pll, rate, parent_rate, + &div, &mul, &index); + if (ret < 0) + return TEE_ERROR_BAD_PARAMETERS; + + pll->range = index; + pll->div = div; + pll->mul = mul; + + return TEE_SUCCESS; +} + +static const struct clk_ops pll_ops = { + .enable = clk_pll_enable, + .disable = clk_pll_disable, + .get_rate = clk_pll_get_rate, + .set_rate = clk_pll_set_rate, +}; + +struct clk * +at91_clk_register_pll(struct pmc_data *pmc, const char *name, + struct clk *parent, uint8_t id, + const struct clk_pll_layout *layout, + const struct clk_pll_charac *charac) +{ + struct clk *clk = NULL; + struct clk_pll *pll = NULL; + int offset = PLL_REG(id); + uint32_t pllr = 0; + + if (!name || !parent) + return NULL; + + clk = clk_alloc(name, &pll_ops, &parent, 1); + if (!clk) + return NULL; + + if (id > PLL_MAX_ID) + return NULL; + + pll = calloc(1, sizeof(*pll)); + if (!pll) { + clk_free(clk); + return NULL; + } + + pll->id = id; + pll->layout = layout; + pll->charac = charac; + pll->base = pmc->base; + pllr = io_read32(pmc->base + offset); + pll->div = PLL_DIV(pllr); + pll->mul = PLL_MUL(pllr, layout); + + clk->flags = CLK_SET_RATE_GATE; + clk->priv = pll; + + if (clk_register(clk)) { + clk_free(clk); + free(pll); + return NULL; + } + + return clk; +} + +const struct clk_pll_layout sama5d3_pll_layout = { + .pllr_mask = 0x1FFFFFF, + .mul_shift = 18, + .mul_mask = 0x7F, +}; diff --git a/optee/optee_os/core/drivers/clk/sam/at91_plldiv.c b/optee/optee_os/core/drivers/clk/sam/at91_plldiv.c new file mode 100644 index 0000000..eca14ec --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_plldiv.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +static unsigned long clk_plldiv_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct pmc_data *pmc = clk->priv; + unsigned int mckr = io_read32(pmc->base + AT91_PMC_MCKR); + + if (mckr & AT91_PMC_PLLADIV2) + return parent_rate / 2; + + return parent_rate; +} + +static TEE_Result clk_plldiv_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct pmc_data *pmc = clk->priv; + + if (parent_rate != rate && (parent_rate / 2 != rate)) + return TEE_ERROR_GENERIC; + + io_clrsetbits32(pmc->base + AT91_PMC_MCKR, AT91_PMC_PLLADIV2, + parent_rate != rate ? AT91_PMC_PLLADIV2 : 0); + + return TEE_SUCCESS; +} + +static const struct clk_ops plldiv_ops = { + .get_rate = clk_plldiv_get_rate, + .set_rate = clk_plldiv_set_rate, +}; + +struct clk * +at91_clk_register_plldiv(struct pmc_data *pmc, const char *name, + struct clk *parent) +{ + struct clk *clk = NULL; + + clk = clk_alloc(name, &plldiv_ops, &parent, 1); + if (!clk) + return NULL; + + clk->priv = pmc; + clk->flags = CLK_SET_RATE_GATE; + + if (clk_register(clk)) { + clk_free(clk); + return NULL; + } + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_pmc.c b/optee/optee_os/core/drivers/clk/sam/at91_pmc.c new file mode 100644 index 0000000..a7200c0 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_pmc.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define PMC_MAX_IDS 128 +#define PMC_MAX_PCKS 8 + +static struct clk *pmc_clk_get_by_id(struct pmc_clk *clks, unsigned int nclk, + unsigned int id) +{ + unsigned int i = 0; + + for (i = 0; i < nclk; i++) { + if (clks[i].clk && clks[i].id == id) + return clks[i].clk; + } + + return NULL; +} + +struct clk *pmc_clk_get_by_name(struct pmc_clk *clks, unsigned int nclk, + const char *name) +{ + unsigned int i = 0; + + for (i = 0; i < nclk; i++) + if (strcmp(clks[i].clk->name, name) == 0) + return clks[i].clk; + + return NULL; +} + +struct clk *clk_dt_pmc_get(struct dt_driver_phandle_args *clkspec, void *data, + TEE_Result *res) +{ + unsigned int type = clkspec->args[0]; + unsigned int idx = clkspec->args[1]; + struct pmc_data *pmc_data = data; + struct pmc_clk *clks = NULL; + struct clk *clk = NULL; + unsigned int nclk = 0; + *res = TEE_ERROR_GENERIC; + + if (clkspec->args_count != 2) { + *res = TEE_ERROR_BAD_PARAMETERS; + return NULL; + } + + switch (type) { + case PMC_TYPE_CORE: + nclk = pmc_data->ncore; + clks = pmc_data->chws; + break; + case PMC_TYPE_SYSTEM: + nclk = pmc_data->nsystem; + clks = pmc_data->shws; + break; + case PMC_TYPE_PERIPHERAL: + nclk = pmc_data->nperiph; + clks = pmc_data->phws; + break; + case PMC_TYPE_GCK: + nclk = pmc_data->ngck; + clks = pmc_data->ghws; + break; + case PMC_TYPE_PROGRAMMABLE: + nclk = pmc_data->npck; + clks = pmc_data->pchws; + break; + default: + return NULL; + } + + clk = pmc_clk_get_by_id(clks, nclk, idx); + if (clk) + *res = TEE_SUCCESS; + + return clk; +} + +struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem, + unsigned int nperiph, unsigned int ngck, + unsigned int npck) +{ + unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck; + unsigned int alloc_size = sizeof(struct pmc_data) + + num_clks * sizeof(struct pmc_clk); + struct pmc_data *pmc_data = NULL; + + pmc_data = calloc(1, alloc_size); + if (!pmc_data) + return NULL; + + pmc_data->ncore = ncore; + pmc_data->chws = pmc_data->hwtable; + + pmc_data->nsystem = nsystem; + pmc_data->shws = pmc_data->chws + ncore; + + pmc_data->nperiph = nperiph; + pmc_data->phws = pmc_data->shws + nsystem; + + pmc_data->ngck = ngck; + pmc_data->ghws = pmc_data->phws + nperiph; + + pmc_data->npck = npck; + pmc_data->pchws = pmc_data->ghws + ngck; + + return pmc_data; +} + +#ifdef CFG_PM_ARM32 +static uint8_t registered_ids[PMC_MAX_IDS]; +static uint8_t registered_pcks[PMC_MAX_PCKS]; + +static struct +{ + uint32_t scsr; + uint32_t pcsr0; + uint32_t uckr; + uint32_t mor; + uint32_t mcfr; + uint32_t pllar; + uint32_t mckr; + uint32_t usb; + uint32_t imr; + uint32_t pcsr1; + uint32_t pcr[PMC_MAX_IDS]; + uint32_t audio_pll0; + uint32_t audio_pll1; + uint32_t pckr[PMC_MAX_PCKS]; +} pmc_cache; + +/* + * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored + * without alteration in the table, and 0 is for unused clocks. + */ +void pmc_register_id(uint8_t id) +{ + int i = 0; + + for (i = 0; i < PMC_MAX_IDS; i++) { + if (registered_ids[i] == 0) { + registered_ids[i] = id; + return; + } + if (registered_ids[i] == id) + return; + } + + panic("Invalid clock ID"); +} + +/* + * As Programmable Clock 0 is valid on AT91 chips, there is an offset + * of 1 between the stored value and the real clock ID. + */ +void pmc_register_pck(uint8_t pck) +{ + int i = 0; + + for (i = 0; i < PMC_MAX_PCKS; i++) { + if (registered_pcks[i] == 0) { + registered_pcks[i] = pck + 1; + return; + } + if (registered_pcks[i] == pck + 1) + return; + } + + panic("Invalid clock ID"); +} + +static void pmc_suspend(void) +{ + int i = 0; + uint8_t num = 0; + vaddr_t pmc_base = at91_pmc_get_base(); + + pmc_cache.scsr = io_read32(pmc_base + AT91_PMC_SCSR); + pmc_cache.pcsr0 = io_read32(pmc_base + AT91_PMC_PCSR); + pmc_cache.uckr = io_read32(pmc_base + AT91_CKGR_UCKR); + pmc_cache.mor = io_read32(pmc_base + AT91_CKGR_MOR); + pmc_cache.mcfr = io_read32(pmc_base + AT91_CKGR_MCFR); + pmc_cache.pllar = io_read32(pmc_base + AT91_CKGR_PLLAR); + pmc_cache.mckr = io_read32(pmc_base + AT91_PMC_MCKR); + pmc_cache.usb = io_read32(pmc_base + AT91_PMC_USB); + pmc_cache.imr = io_read32(pmc_base + AT91_PMC_IMR); + pmc_cache.pcsr1 = io_read32(pmc_base + AT91_PMC_PCSR1); + + for (i = 0; registered_ids[i]; i++) { + io_write32(pmc_base + AT91_PMC_PCR, + registered_ids[i] & AT91_PMC_PCR_PID_MASK); + pmc_cache.pcr[registered_ids[i]] = io_read32(pmc_base + + AT91_PMC_PCR); + } + for (i = 0; registered_pcks[i]; i++) { + num = registered_pcks[i] - 1; + pmc_cache.pckr[num] = io_read32(pmc_base + AT91_PMC_PCKR(num)); + } +} + +static bool pmc_ready(vaddr_t pmc_base, unsigned int mask) +{ + uint32_t status = 0; + + status = io_read32(pmc_base + AT91_PMC_SR); + + return (status & mask) == mask; +} + +static void pmc_resume(void) +{ + int i = 0; + uint8_t num = 0; + uint32_t tmp = 0; + vaddr_t pmc_base = at91_pmc_get_base(); + uint32_t mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA; + + tmp = io_read32(pmc_base + AT91_PMC_MCKR); + if (pmc_cache.mckr != tmp) + panic("MCKR was not configured properly by the previous bootstage"); + tmp = io_read32(pmc_base + AT91_CKGR_PLLAR); + if (pmc_cache.pllar != tmp) + panic("PLLAR was not configured properly by the previous bootstage"); + + io_write32(pmc_base + AT91_PMC_SCER, pmc_cache.scsr); + io_write32(pmc_base + AT91_PMC_PCER, pmc_cache.pcsr0); + io_write32(pmc_base + AT91_CKGR_UCKR, pmc_cache.uckr); + io_write32(pmc_base + AT91_CKGR_MOR, pmc_cache.mor); + io_write32(pmc_base + AT91_CKGR_MCFR, pmc_cache.mcfr); + io_write32(pmc_base + AT91_PMC_USB, pmc_cache.usb); + io_write32(pmc_base + AT91_PMC_IMR, pmc_cache.imr); + io_write32(pmc_base + AT91_PMC_PCER1, pmc_cache.pcsr1); + + for (i = 0; registered_ids[i]; i++) { + io_write32(pmc_base + AT91_PMC_PCR, + pmc_cache.pcr[registered_ids[i]] | AT91_PMC_PCR_CMD); + } + for (i = 0; registered_pcks[i]; i++) { + num = registered_pcks[i] - 1; + io_write32(pmc_base + AT91_PMC_PCKR(num), pmc_cache.pckr[num]); + } + + if (pmc_cache.uckr & AT91_PMC_UPLLEN) + mask |= AT91_PMC_LOCKU; + + while (!pmc_ready(pmc_base, mask)) + ; +} + +static TEE_Result pmc_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *hdl __unused) +{ + switch (op) { + case PM_OP_RESUME: + pmc_resume(); + break; + case PM_OP_SUSPEND: + pmc_suspend(); + break; + default: + panic("Invalid PM operation"); + } + + return TEE_SUCCESS; +} + +void pmc_register_pm(void) +{ + /* + * We register the clock as a core service since clocks must be + * re-enable prior to accessing devices + */ + register_pm_core_service_cb(pmc_pm, NULL, "pmc"); +} + +#endif diff --git a/optee/optee_os/core/drivers/clk/sam/at91_pmc.h b/optee/optee_os/core/drivers/clk/sam/at91_pmc.h new file mode 100644 index 0000000..5b4a554 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_pmc.h @@ -0,0 +1,260 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Power Management Controller (PMC) - System peripherals registers. + * Based on AT91RM9200 datasheet revision E. + */ + +#ifndef DRIVERS_CLK_SAM_AT91_PM_H +#define DRIVERS_CLK_SAM_AT91_PM_H + +#include + +#define AT91_PMC_V1 (1) +#define AT91_PMC_V2 (2) + +#define AT91_PMC_SCER 0x00 +#define AT91_PMC_SCDR 0x04 + +#define AT91_PMC_SCSR 0x08 +#define AT91_PMC_PCK BIT(0) +#define AT91RM9200_PMC_UDP BIT(1) +#define AT91RM9200_PMC_MCKUDP BIT(2) +#define AT91RM9200_PMC_UHP BIT(4) +#define AT91SAM926x_PMC_UHP BIT(6) +#define AT91SAM926x_PMC_UDP BIT(7) +#define AT91_PMC_PCK0 BIT(8) +#define AT91_PMC_PCK1 BIT(9) +#define AT91_PMC_PCK2 BIT(10) +#define AT91_PMC_PCK3 BIT(11) +#define AT91_PMC_PCK4 BIT(12) +#define AT91_PMC_HCK0 BIT(16) +#define AT91_PMC_HCK1 BIT(17) + +#define AT91_PMC_PLL_CTRL0 0x0C +#define AT91_PMC_PLL_CTRL0_ENPLL BIT(28) +#define AT91_PMC_PLL_CTRL0_ENPLLCK BIT(29) +#define AT91_PMC_PLL_CTRL0_ENLOCK BIT(31) + +#define AT91_PMC_PLL_CTRL1 0x10 + +#define AT91_PMC_PCER 0x10 +#define AT91_PMC_PCDR 0x14 +#define AT91_PMC_PCSR 0x18 + +#define AT91_PMC_PLL_ACR 0x18 +#define AT91_PMC_PLL_ACR_DEFAULT_UPLL 0x12020010UL +#define AT91_PMC_PLL_ACR_DEFAULT_PLLA 0x00020010UL +#define AT91_PMC_PLL_ACR_UTMIVR BIT(12) +#define AT91_PMC_PLL_ACR_UTMIBG BIT(13) + +#define AT91_CKGR_UCKR 0x1C +#define AT91_PMC_UPLLEN BIT(16) +#define AT91_PMC_UPLLCOUNT (0xf << 20) +#define AT91_PMC_BIASEN BIT(24) +#define AT91_PMC_BIASCOUNT (0xf << 28) + +#define AT91_PMC_PLL_UPDT 0x1C +#define AT91_PMC_PLL_UPDT_UPDATE BIT(8) +#define AT91_PMC_PLL_UPDT_ID BIT(0) +#define AT91_PMC_PLL_UPDT_ID_MSK (0xf) +#define AT91_PMC_PLL_UPDT_STUPTIM (0xff << 16) + +#define AT91_CKGR_MOR 0x20 +#define AT91_PMC_MOSCEN BIT(0) +#define AT91_PMC_OSCBYPASS BIT(1) +#define AT91_PMC_WAITMODE BIT(2) +#define AT91_PMC_MOSCRCEN BIT(3) +#define AT91_PMC_OSCOUNT (0xff << 8) +#define AT91_PMC_KEY_MASK (0xff << 16) +#define AT91_PMC_KEY (0x37 << 16) +#define AT91_PMC_MOSCSEL BIT(24) +#define AT91_PMC_CFDEN BIT(25) + +#define AT91_CKGR_MCFR 0x24 +#define AT91_PMC_MAINF (0xffff << 0) +#define AT91_PMC_MAINRDY BIT(16) + +#define AT91_CKGR_PLLAR 0x28 +#define AT91_CKGR_PLLBR 0x2c +#define AT91_PMC_DIV (0xff << 0) +#define AT91_PMC_PLLCOUNT (0x3f << 8) +#define AT91_PMC_OUT (3 << 14) +#define AT91_PMC_MUL (0x7ff << 16) +#define AT91_PMC_MUL_GET(n) ((n) >> 16 & 0x7ff) +#define AT91_PMC3_MUL (0x7f << 18) +#define AT91_PMC3_MUL_GET(n) ((n) >> 18 & 0x7f) +#define AT91_PMC_USBDIV (3 << 28) +#define AT91_PMC_USBDIV_1 (0 << 28) +#define AT91_PMC_USBDIV_2 BIT(28) +#define AT91_PMC_USBDIV_4 (2 << 28) +#define AT91_PMC_USB96M BIT(28) + +#define AT91_PMC_CPU_CKR 0x28 + +#define AT91_PMC_MCKR 0x30 +#define AT91_PMC_CSS (3 << 0) +#define AT91_PMC_CSS_SLOW (0 << 0) +#define AT91_PMC_CSS_MAIN BIT(0) +#define AT91_PMC_CSS_PLLA (2 << 0) +#define AT91_PMC_CSS_PLLB (3 << 0) +#define AT91_PMC_CSS_UPLL (3 << 0) +#define PMC_PRES_OFFSET 2 +#define AT91_PMC_PRES (7 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_1 (0 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_2 BIT(PMC_PRES_OFFSET) +#define AT91_PMC_PRES_4 (2 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_8 (3 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_16 (4 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_32 (5 << PMC_PRES_OFFSET) +#define AT91_PMC_PRES_64 (6 << PMC_PRES_OFFSET) +#define PMC_ALT_PRES_OFFSET 4 +#define AT91_PMC_ALT_PRES (7 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_1 (0 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_2 BIT(PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_4 (2 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_8 (3 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_16 (4 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_32 (5 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_ALT_PRES_64 (6 << PMC_ALT_PRES_OFFSET) +#define AT91_PMC_MDIV (3 << 8) +#define AT91RM9200_PMC_MDIV_1 (0 << 8) +#define AT91RM9200_PMC_MDIV_2 BIT(8) +#define AT91RM9200_PMC_MDIV_3 (2 << 8) +#define AT91RM9200_PMC_MDIV_4 (3 << 8) +#define AT91SAM9_PMC_MDIV_1 (0 << 8) +#define AT91SAM9_PMC_MDIV_2 BIT(8) +#define AT91SAM9_PMC_MDIV_4 (2 << 8) +#define AT91SAM9_PMC_MDIV_6 (3 << 8) +#define AT91SAM9_PMC_MDIV_3 (3 << 8) +#define AT91_PMC_PDIV BIT(12) +#define AT91_PMC_PDIV_1 (0 << 12) +#define AT91_PMC_PDIV_2 BIT(12) +#define AT91_PMC_PLLADIV2 BIT(12) +#define AT91_PMC_PLLADIV2_OFF (0 << 12) +#define AT91_PMC_PLLADIV2_ON BIT(12) +#define AT91_PMC_H32MXDIV BIT(24) + +#define AT91_PMC_XTALF 0x34 + +#define AT91_PMC_USB 0x38 +#define AT91_PMC_USBS (0x1 << 0) +#define AT91_PMC_USBS_PLLA (0 << 0) +#define AT91_PMC_USBS_UPLL BIT(0) +#define AT91_PMC_USBS_PLLB BIT(0) +#define AT91_PMC_OHCIUSBDIV (0xF << 8) +#define AT91_PMC_OHCIUSBDIV_1 (0x0 << 8) +#define AT91_PMC_OHCIUSBDIV_2 (0x1 << 8) + +#define AT91_PMC_SMD 0x3c +#define AT91_PMC_SMDS (0x1 << 0) +#define AT91_PMC_SMD_DIV (0x1f << 8) +#define AT91_PMC_SMDDIV(n) (((n) << 8) & AT91_PMC_SMD_DIV) + +#define AT91_PMC_PCKR(n) (0x40 + ((n) * 4)) +#define AT91_PMC_ALT_PCKR_CSS (0x7 << 0) +#define AT91_PMC_CSS_MASTER (4 << 0) +#define AT91_PMC_CSSMCK (0x1 << 8) +#define AT91_PMC_CSSMCK_CSS (0 << 8) +#define AT91_PMC_CSSMCK_MCK BIT(8) + +#define AT91_PMC_IER 0x60 +#define AT91_PMC_IDR 0x64 +#define AT91_PMC_SR 0x68 +#define AT91_PMC_MOSCS BIT(0) +#define AT91_PMC_LOCKA BIT(1) +#define AT91_PMC_LOCKB BIT(2) +#define AT91_PMC_MCKRDY BIT(3) +#define AT91_PMC_LOCKU BIT(6) +#define AT91_PMC_OSCSEL BIT(7) +#define AT91_PMC_PCK0RDY BIT(8) +#define AT91_PMC_PCK1RDY BIT(9) +#define AT91_PMC_PCK2RDY BIT(10) +#define AT91_PMC_PCK3RDY BIT(11) +#define AT91_PMC_MOSCSELS BIT(16) +#define AT91_PMC_MOSCRCS BIT(17) +#define AT91_PMC_CFDEV BIT(18) +#define AT91_PMC_GCKRDY BIT(24) +#define AT91_PMC_MCKXRDY BIT(26) +#define AT91_PMC_IMR 0x6c + +#define AT91_PMC_FSMR 0x70 +#define AT91_PMC_FSTT(n) BIT(n) +#define AT91_PMC_RTTAL BIT(16) +#define AT91_PMC_RTCAL BIT(17) +#define AT91_PMC_USBAL BIT(18) +#define AT91_PMC_SDMMC_CD BIT(19) +#define AT91_PMC_LPM BIT(20) +#define AT91_PMC_RXLP_MCE BIT(24) +#define AT91_PMC_ACC_CE BIT(25) + +#define AT91_PMC_FSPR 0x74 + +#define AT91_PMC_FS_INPUT_MASK 0x7ff + +#define AT91_PMC_PLLICPR 0x80 + +#define AT91_PMC_PROT 0xe4 +#define AT91_PMC_WPEN (0x1 << 0) +#define AT91_PMC_WPKEY (0xffffff << 8) +#define AT91_PMC_PROTKEY (0x504d43 << 8) + +#define AT91_PMC_WPSR 0xe8 +#define AT91_PMC_WPVS (0x1 << 0) +#define AT91_PMC_WPVSRC (0xffff << 8) + +#define AT91_PMC_PLL_ISR0 0xEC + +#define AT91_PMC_PCER1 0x100 +#define AT91_PMC_PCDR1 0x104 +#define AT91_PMC_PCSR1 0x108 + +#define AT91_PMC_PCR 0x10c +#define AT91_PMC_PCR_PID_MASK 0x3f +#define AT91_PMC_PCR_CMD (0x1 << 12) +#define AT91_PMC_PCR_GCKDIV_SHIFT 20 +#define AT91_PMC_PCR_GCKDIV_MASK \ + GENMASK_32(27, AT91_PMC_PCR_GCKDIV_SHIFT) +#define AT91_PMC_PCR_EN (0x1 << 28) +#define AT91_PMC_PCR_GCKEN (0x1 << 29) + +#define AT91_PMC_AUDIO_PLL0 0x14c +#define AT91_PMC_AUDIO_PLL_PLLEN BIT(0) +#define AT91_PMC_AUDIO_PLL_PADEN BIT(1) +#define AT91_PMC_AUDIO_PLL_PMCEN BIT(2) +#define AT91_PMC_AUDIO_PLL_RESETN BIT(3) +#define AT91_PMC_AUDIO_PLL_ND_OFFSET 8 +#define AT91_PMC_AUDIO_PLL_ND_MASK \ + (0x7f << AT91_PMC_AUDIO_PLL_ND_OFFSET) +#define AT91_PMC_AUDIO_PLL_ND(n) \ + SHIFT_U32(n, AT91_PMC_AUDIO_PLL_ND_OFFSET) +#define AT91_PMC_AUDIO_PLL_QDPMC_OFFSET 16 +#define AT91_PMC_AUDIO_PLL_QDPMC_MASK \ + (0x7f << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) +#define AT91_PMC_AUDIO_PLL_QDPMC(n) \ + SHIFT_U32(n, AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) + +#define AT91_PMC_AUDIO_PLL1 0x150 +#define AT91_PMC_AUDIO_PLL_FRACR_MASK 0x3fffff +#define AT91_PMC_AUDIO_PLL_QDPAD_OFFSET 24 +#define AT91_PMC_AUDIO_PLL_QDPAD_MASK \ + (0x7f << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET) +#define AT91_PMC_AUDIO_PLL_QDPAD(n) \ + SHIFT_U32(n, AT91_PMC_AUDIO_PLL_QDPAD_OFFSET) +#define AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET \ + AT91_PMC_AUDIO_PLL_QDPAD_OFFSET +#define AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK \ + (0x3 << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) +#define AT91_PMC_AUDIO_PLL_QDPAD_DIV(n) \ + SHIFT_U32(n, AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) +#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET 26 +#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX 0x1f +#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK \ + (AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX << \ + AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET) +#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(n) \ + SHIFT_U32(n, AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET) + +#endif diff --git a/optee/optee_os/core/drivers/clk/sam/at91_programmable.c b/optee/optee_os/core/drivers/clk/sam/at91_programmable.c new file mode 100644 index 0000000..4f24442 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_programmable.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define PROG_ID_MAX 7 + +#define PROG_STATUS_MASK(id) (1 << ((id) + 8)) +#define PROG_PRES(layout, pckr) \ + ({ \ + typeof(layout) __layout = layout; \ + \ + (((pckr) >> (__layout)->pres_shift) & (__layout)->pres_mask); \ + }) +#define PROG_MAX_RM9200_CSS 3 + +struct clk_programmable { + vaddr_t base; + uint8_t id; + const struct clk_programmable_layout *layout; +}; + +static unsigned long clk_programmable_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_programmable *prog = clk->priv; + const struct clk_programmable_layout *layout = prog->layout; + unsigned int pckr = io_read32(prog->base + AT91_PMC_PCKR(prog->id)); + unsigned long rate = 0; + + if (layout->is_pres_direct) + rate = parent_rate / (PROG_PRES(layout, pckr) + 1); + else + rate = parent_rate >> PROG_PRES(layout, pckr); + + return rate; +} + +static TEE_Result clk_programmable_set_parent(struct clk *clk, size_t index) +{ + struct clk_programmable *prog = clk->priv; + const struct clk_programmable_layout *layout = prog->layout; + unsigned int mask = layout->css_mask; + unsigned int pckr = index; + + if (layout->have_slck_mck) + mask |= AT91_PMC_CSSMCK_MCK; + + if (index > layout->css_mask) { + if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck) + return TEE_ERROR_BAD_PARAMETERS; + + pckr |= AT91_PMC_CSSMCK_MCK; + } + + io_clrsetbits32(prog->base + AT91_PMC_PCKR(prog->id), mask, pckr); + + return TEE_SUCCESS; +} + +static size_t clk_programmable_get_parent(struct clk *clk) +{ + struct clk_programmable *prog = clk->priv; + const struct clk_programmable_layout *layout = prog->layout; + unsigned int pckr = io_read32(prog->base + AT91_PMC_PCKR(prog->id)); + size_t ret = 0; + + ret = pckr & layout->css_mask; + + if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret) + ret = PROG_MAX_RM9200_CSS + 1; + + return ret; +} + +static unsigned int flsi(unsigned int val) +{ + if (val == 0) + return 0; + + return sizeof(unsigned int) * 8 - __builtin_clz(val); +} + +static TEE_Result clk_programmable_set_rate(struct clk *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_programmable *prog = clk->priv; + const struct clk_programmable_layout *layout = prog->layout; + unsigned long div = parent_rate / rate; + int shift = 0; + + if (!div) + return TEE_ERROR_BAD_PARAMETERS; + + if (layout->is_pres_direct) { + shift = div - 1; + + if (shift > layout->pres_mask) + return TEE_ERROR_BAD_PARAMETERS; + } else { + shift = flsi(div) - 1; + + if (div != (1ULL << shift)) + return TEE_ERROR_BAD_PARAMETERS; + + if (shift >= layout->pres_mask) + return TEE_ERROR_BAD_PARAMETERS; + } + + io_clrsetbits32(prog->base + AT91_PMC_PCKR(prog->id), + layout->pres_mask << layout->pres_shift, + shift << layout->pres_shift); + + return TEE_SUCCESS; +} + +static const struct clk_ops programmable_ops = { + .get_rate = clk_programmable_get_rate, + .get_parent = clk_programmable_get_parent, + .set_parent = clk_programmable_set_parent, + .set_rate = clk_programmable_set_rate, +}; + +struct clk * +at91_clk_register_programmable(struct pmc_data *pmc, + const char *name, struct clk **parents, + uint8_t num_parents, uint8_t id, + const struct clk_programmable_layout *layout) +{ + struct clk_programmable *prog = NULL; + struct clk *clk = NULL; + + assert(id <= PROG_ID_MAX); + + clk = clk_alloc(name, &programmable_ops, parents, num_parents); + prog = calloc(1, sizeof(*prog)); + if (!prog || !clk) + return NULL; + + prog->id = id; + prog->layout = layout; + prog->base = pmc->base; + + clk->priv = prog; + clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + if (clk_register(clk)) { + clk_free(clk); + free(prog); + return NULL; + } + + pmc_register_pck(id); + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_sckc.c b/optee/optee_os/core/drivers/clk/sam/at91_sckc.c new file mode 100644 index 0000000..2aeb4a6 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_sckc.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include + +#define SLOW_CLOCK_FREQ 32768 + +static unsigned long sckc_get_rate(struct clk *clk __unused, + unsigned long parent_rate __unused) +{ + return SLOW_CLOCK_FREQ; +} + +static const struct clk_ops sckc_clk_ops = { + .get_rate = sckc_get_rate, +}; + +static TEE_Result sckc_pmc_setup(const void *fdt __unused, int offs, + const void *data __unused) +{ + struct clk *clk = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + clk = clk_alloc("slowck", &sckc_clk_ops, NULL, 0); + if (!clk) + return TEE_ERROR_OUT_OF_MEMORY; + + res = clk_register(clk); + if (res) { + clk_free(clk); + return res; + } + + return clk_dt_register_clk_provider(fdt, offs, clk_dt_get_simple_clk, + clk); +} + +CLK_DT_DECLARE(at91_sckc, "atmel,sama5d4-sckc", sckc_pmc_setup); diff --git a/optee/optee_os/core/drivers/clk/sam/at91_system.c b/optee/optee_os/core/drivers/clk/sam/at91_system.c new file mode 100644 index 0000000..c9f881f --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_system.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define SYSTEM_MAX_ID 31 + +#define SYSTEM_MAX_NAME_SZ 32 + +struct clk_system { + vaddr_t base; + uint8_t id; +}; + +static bool is_pck(int id) +{ + return (id >= 8) && (id <= 15); +} + +static bool clk_system_ready(vaddr_t base, int id) +{ + uint32_t status = io_read32(base + AT91_PMC_SR); + + return status & BIT(id); +} + +static TEE_Result clk_system_enable(struct clk *clk) +{ + struct clk_system *sys = clk->priv; + + io_write32(sys->base + AT91_PMC_SCER, 1 << sys->id); + + if (!is_pck(sys->id)) + return TEE_SUCCESS; + + while (!clk_system_ready(sys->base, sys->id)) + ; + + return TEE_SUCCESS; +} + +static void clk_system_disable(struct clk *clk) +{ + struct clk_system *sys = clk->priv; + + io_write32(sys->base + AT91_PMC_SCDR, 1 << sys->id); +} + +static const struct clk_ops system_ops = { + .enable = clk_system_enable, + .disable = clk_system_disable, +}; + +struct clk * +at91_clk_register_system(struct pmc_data *pmc, const char *name, + struct clk *parent, uint8_t id) +{ + struct clk_system *sys = NULL; + struct clk *clk = NULL; + + if (!parent || id > SYSTEM_MAX_ID) + return NULL; + + clk = clk_alloc(name, &system_ops, &parent, 1); + if (!clk) + return NULL; + + sys = calloc(1, sizeof(*sys)); + if (!sys) { + clk_free(clk); + return NULL; + } + + sys->id = id; + sys->base = pmc->base; + + clk->priv = sys; + + if (clk_register(clk)) { + clk_free(clk); + free(sys); + return NULL; + } + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_usb.c b/optee/optee_os/core/drivers/clk/sam/at91_usb.c new file mode 100644 index 0000000..b5a0db3 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_usb.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#define SAM9X5_USB_DIV_SHIFT 8 +#define SAM9X5_USB_DIV_COUNT BIT32(4) +#define SAM9X5_USB_MAX_DIV (SAM9X5_USB_DIV_COUNT - 1) + +#define SAM9X5_USBS_MASK BIT(0) + +struct at91sam9x5_clk_usb { + vaddr_t base; + uint32_t usbs_mask; +}; + +static unsigned long at91sam9x5_clk_usb_get_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct at91sam9x5_clk_usb *usb = clk->priv; + uint8_t usbdiv = 1; + unsigned int usbr = io_read32(usb->base + AT91_PMC_USB); + + usbdiv = (usbr & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; + + return UDIV_ROUND_NEAREST(parent_rate, (usbdiv + 1)); +} + +static TEE_Result at91sam9x5_clk_usb_set_parent(struct clk *clk, size_t index) +{ + struct at91sam9x5_clk_usb *usb = clk->priv; + + if (index >= clk_get_num_parents(clk)) + return TEE_ERROR_BAD_PARAMETERS; + + io_clrsetbits32(usb->base + AT91_PMC_USB, usb->usbs_mask, index); + + return TEE_SUCCESS; +} + +static size_t at91sam9x5_clk_usb_get_parent(struct clk *clk) +{ + struct at91sam9x5_clk_usb *usb = clk->priv; + unsigned int usbr = io_read32(usb->base + AT91_PMC_USB); + + return usbr & usb->usbs_mask; +} + +static TEE_Result at91sam9x5_clk_usb_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate) +{ + struct at91sam9x5_clk_usb *usb = clk->priv; + unsigned long div = 1; + + if (!rate) + return TEE_ERROR_BAD_PARAMETERS; + + div = UDIV_ROUND_NEAREST(parent_rate, rate); + if (div > SAM9X5_USB_MAX_DIV + 1 || !div) + return TEE_ERROR_BAD_PARAMETERS; + + io_clrsetbits32(usb->base + AT91_PMC_USB, AT91_PMC_OHCIUSBDIV, + (div - 1) << SAM9X5_USB_DIV_SHIFT); + + return TEE_SUCCESS; +} + +static const struct clk_ops at91sam9x5_usb_ops = { + .get_rate = at91sam9x5_clk_usb_get_rate, + .get_parent = at91sam9x5_clk_usb_get_parent, + .set_parent = at91sam9x5_clk_usb_set_parent, + .set_rate = at91sam9x5_clk_usb_set_rate, +}; + +static struct clk * +_at91sam9x5_clk_register_usb(struct pmc_data *pmc, const char *name, + struct clk **parents, uint8_t num_parents, + uint32_t usbs_mask) +{ + struct at91sam9x5_clk_usb *usb = NULL; + struct clk *clk = NULL; + + clk = clk_alloc(name, &at91sam9x5_usb_ops, parents, num_parents); + if (!clk) + return NULL; + + usb = calloc(1, sizeof(*usb)); + if (!usb) + return NULL; + + usb->base = pmc->base; + usb->usbs_mask = usbs_mask; + + clk->priv = usb; + clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + + if (clk_register(clk)) { + clk_free(clk); + free(usb); + return NULL; + } + + return clk; +} + +struct clk * +at91sam9x5_clk_register_usb(struct pmc_data *pmc, const char *name, + struct clk **parents, uint8_t num_parents) +{ + return _at91sam9x5_clk_register_usb(pmc, name, parents, + num_parents, SAM9X5_USBS_MASK); +} diff --git a/optee/optee_os/core/drivers/clk/sam/at91_utmi.c b/optee/optee_os/core/drivers/clk/sam/at91_utmi.c new file mode 100644 index 0000000..d5be945 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/at91_utmi.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (C) 2013 Boris BREZILLON + * Copyright (C) 2021 Microchip + */ + +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +/* + * The purpose of this clock is to generate a 480 MHz signal. A different + * rate can't be configured. + */ +#define UTMI_RATE 480000000 + +struct clk_utmi { + vaddr_t pmc_base; + vaddr_t sfr_base; +}; + +static bool clk_utmi_ready(vaddr_t pmc_base) +{ + uint32_t status = io_read32(pmc_base + AT91_PMC_SR); + + return status & AT91_PMC_LOCKU; +} + +static TEE_Result clk_utmi_enable(struct clk *clk) +{ + struct clk *clk_parent = NULL; + struct clk_utmi *utmi = clk->priv; + unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT | + AT91_PMC_BIASEN; + unsigned int utmi_ref_clk_freq = 0; + unsigned long parent_rate = 0; + + /* + * If mainck rate is different from 12 MHz, we have to configure the + * FREQ field of the SFR_UTMICKTRIM register to generate properly + * the utmi clock. + */ + clk_parent = clk_get_parent(clk); + parent_rate = clk_get_rate(clk_parent); + + switch (parent_rate) { + case 12000000: + utmi_ref_clk_freq = 0; + break; + case 16000000: + utmi_ref_clk_freq = 1; + break; + case 24000000: + utmi_ref_clk_freq = 2; + break; + /* + * Not supported on SAMA5D2 but it's not an issue since MAINCK + * maximum value is 24 MHz. + */ + case 48000000: + utmi_ref_clk_freq = 3; + break; + default: + EMSG("UTMICK: unsupported mainck rate"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (utmi->sfr_base) { + io_clrsetbits32(utmi->sfr_base + AT91_SFR_UTMICKTRIM, + AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq); + } else if (utmi_ref_clk_freq) { + EMSG("UTMICK: sfr node required"); + return TEE_ERROR_BAD_STATE; + } + + io_clrsetbits32(utmi->pmc_base + AT91_CKGR_UCKR, uckr, uckr); + + while (!clk_utmi_ready(utmi->pmc_base)) + ; + + return TEE_SUCCESS; +} + +static void clk_utmi_disable(struct clk *clk) +{ + struct clk_utmi *utmi = clk->priv; + + io_clrbits32(utmi->pmc_base + AT91_CKGR_UCKR, AT91_PMC_UPLLEN); +} + +static unsigned long clk_utmi_get_rate(struct clk *clk __unused, + unsigned long parent_rate __unused) +{ + /* UTMI clk rate is fixed. */ + return UTMI_RATE; +} + +static const struct clk_ops utmi_ops = { + .enable = clk_utmi_enable, + .disable = clk_utmi_disable, + .get_rate = clk_utmi_get_rate, +}; + +struct clk * +at91_clk_register_utmi(struct pmc_data *pmc, const char *name, + struct clk *parent) +{ + struct clk_utmi *utmi = NULL; + struct clk *clk = NULL; + + clk = clk_alloc(name, &utmi_ops, &parent, 1); + if (!clk) + return NULL; + + utmi = calloc(1, sizeof(*utmi)); + if (!utmi) { + clk_free(clk); + return NULL; + } + + utmi->pmc_base = pmc->base; + utmi->sfr_base = sam_sfr_base(); + clk->flags = CLK_SET_RATE_GATE; + + clk->priv = utmi; + + if (clk_register(clk)) { + clk_free(clk); + free(utmi); + return NULL; + } + + return clk; +} diff --git a/optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c b/optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c new file mode 100644 index 0000000..5920e13 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/sama5d2_clk.c @@ -0,0 +1,606 @@ +// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause +/* + * Copyright (c) 2021, Microchip + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "at91_clk.h" + +#include + +#define PROGCK_PARENT_COUNT 6 +#define PARENT_SIZE ARRAY_SIZE(sama5d2_systemck) + +struct sam_clk { + const char *n; + uint8_t id; +}; + +static const struct clk_master_charac mck_charac = { + .output = { .min = 124000000, .max = 166000000 }, + .divisors = { 1, 2, 4, 3 }, +}; + +static uint8_t plla_out[1]; + +static uint16_t plla_icpll[1]; + +static const struct clk_range plla_outputs[] = { + { .min = 600000000, .max = 1200000000 }, +}; + +static const struct clk_pll_charac plla_charac = { + .input = { .min = 12000000, .max = 24000000 }, + .num_output = ARRAY_SIZE(plla_outputs), + .output = plla_outputs, + .icpll = plla_icpll, + .out = plla_out, +}; + +static const struct clk_pcr_layout sama5d2_pcr_layout = { + .offset = 0x10c, + .cmd = BIT(12), + .gckcss_mask = GENMASK_32(10, 8), + .pid_mask = GENMASK_32(6, 0), +}; + +static const struct clk_programmable_layout sama5d2_prog_layout = { + .pres_mask = 0xff, + .pres_shift = 4, + .css_mask = 0x7, + .have_slck_mck = 0, + .is_pres_direct = 1, +}; + +static const struct sam_clk sama5d2_systemck[] = { + { .n = "ddrck", .id = 2 }, + { .n = "lcdck", .id = 3 }, + { .n = "uhpck", .id = 6 }, + { .n = "udpck", .id = 7 }, + { .n = "pck0", .id = 8 }, + { .n = "pck1", .id = 9 }, + { .n = "pck2", .id = 10 }, + { .n = "iscck", .id = 18 }, +}; + +static const struct { + struct sam_clk clk; + struct clk_range r; +} sama5d2_peri32ck[] = { + { + .clk = { .n = "macb0_clk", .id = 5 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "tdes_clk", .id = 11 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "matrix1_clk", .id = 14 }, + }, + { + .clk = { .n = "hsmc_clk", .id = 17 }, + }, + { + .clk = { .n = "pioA_clk", .id = 18 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "flx0_clk", .id = 19 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "flx1_clk", .id = 20 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "flx2_clk", .id = 21 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "flx3_clk", .id = 22 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "flx4_clk", .id = 23 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "uart0_clk", .id = 24 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "uart1_clk", .id = 25 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "uart2_clk", .id = 26 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "uart3_clk", .id = 27 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "uart4_clk", .id = 28 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "twi0_clk", .id = 29 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "twi1_clk", .id = 30 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "spi0_clk", .id = 33 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "spi1_clk", .id = 34 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "tcb0_clk", .id = 35 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "tcb1_clk", .id = 36 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "pwm_clk", .id = 38 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "adc_clk", .id = 40 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "uhphs_clk", .id = 41 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "udphs_clk", .id = 42 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "ssc0_clk", .id = 43 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "ssc1_clk", .id = 44 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "trng_clk", .id = 47 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "pdmic_clk", .id = 48 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "securam_clk", .id = 51 }, }, + { + .clk = { .n = "i2s0_clk", .id = 54 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "i2s1_clk", .id = 55 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "can0_clk", .id = 56 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "can1_clk", .id = 57 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "ptc_clk", .id = 58 }, + .r = { .min = 0, .max = 83000000 }, + }, + { + .clk = { .n = "classd_clk", .id = 59 }, + .r = { .min = 0, .max = 83000000 }, + }, +}; + +static const struct sam_clk sama5d2_perick[] = { + { .n = "dma0_clk", .id = 6 }, + { .n = "dma1_clk", .id = 7 }, + { .n = "aes_clk", .id = 9 }, + { .n = "aesb_clk", .id = 10 }, + { .n = "sha_clk", .id = 12 }, + { .n = "mpddr_clk", .id = 13 }, + { .n = "matrix0_clk", .id = 15 }, + { .n = "sdmmc0_hclk", .id = 31 }, + { .n = "sdmmc1_hclk", .id = 32 }, + { .n = "lcdc_clk", .id = 45 }, + { .n = "isc_clk", .id = 46 }, + { .n = "qspi0_clk", .id = 52 }, + { .n = "qspi1_clk", .id = 53 }, +}; + +static const struct { + struct sam_clk clk; + struct clk_range r; + int chg_pid; +} sama5d2_gck[] = { + { + .clk = { .n = "sdmmc0_gclk", .id = 31 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "sdmmc1_gclk", .id = 32 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "tcb0_gclk", .id = 35 }, + .r = { .min = 0, .max = 83000000 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "tcb1_gclk", .id = 36 }, + .r = { .min = 0, .max = 83000000 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "pwm_gclk", .id = 38 }, + .r = { .min = 0, .max = 83000000 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "isc_gclk", .id = 46 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "pdmic_gclk", .id = 48 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "i2s0_gclk", .id = 54 }, + .chg_pid = 5, + }, + { + .clk = { .n = "i2s1_gclk", .id = 55 }, + .chg_pid = 5, + }, + { + .clk = { .n = "can0_gclk", .id = 56 }, + .r = { .min = 0, .max = 80000000 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "can1_gclk", .id = 57 }, + .r = { .min = 0, .max = 80000000 }, + .chg_pid = INT_MIN, + }, + { + .clk = { .n = "classd_gclk", .id = 59 }, + .chg_pid = 5, + .r = { .min = 0, .max = 100000000 }, + }, +}; + +static const struct sam_clk sama5d2_progck[] = { + { .n = "prog0", .id = 0 }, + { .n = "prog1", .id = 1 }, + { .n = "prog2", .id = 2 }, +}; + +static struct pmc_data *pmc; + +vaddr_t at91_pmc_get_base(void) +{ + assert(pmc); + + return pmc->base; +} + +static TEE_Result pmc_setup(const void *fdt, int nodeoffset, + const void *data __unused) +{ + size_t size = 0; + vaddr_t base = 0; + unsigned int i = 0; + int bypass = 0; + const uint32_t *fdt_prop = NULL; + struct pmc_clk *pmc_clk = NULL; + const struct sam_clk *sam_clk = NULL; + struct clk_range range = CLK_RANGE(0, 0); + struct clk *h32mxck = NULL; + struct clk *mckdivck = NULL; + struct clk *plladivck = NULL; + struct clk *usbck = NULL; + struct clk *audiopll_pmcck = NULL; + struct clk *parents[PARENT_SIZE] = {NULL}; + struct clk *main_clk = NULL; + struct clk *utmi_clk = NULL; + struct clk *slow_clk = NULL; + struct clk *clk = NULL; + struct clk *main_rc_osc = NULL; + struct clk *main_osc = NULL; + struct clk *main_xtal_clk = NULL; + struct clk *audiopll_fracck = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + /* + * We want PARENT_SIZE to be MAX(ARRAY_SIZE(sama5d2_systemck),6) + * but using this define won't allow static initialization of parents + * due to dynamic size. + */ + COMPILE_TIME_ASSERT(ARRAY_SIZE(sama5d2_systemck) == PARENT_SIZE); + COMPILE_TIME_ASSERT(PARENT_SIZE >= 6); + + if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0) + panic(); + + if (fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC) + matrix_configure_periph_secure(AT91C_ID_PMC); + + res = clk_dt_get_by_name(fdt, nodeoffset, "slow_clk", &slow_clk); + if (res) + panic(); + + res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk); + if (res) + panic(); + + pmc = pmc_data_allocate(PMC_SAMA5D2_CORE_CLK_COUNT, + ARRAY_SIZE(sama5d2_systemck), + ARRAY_SIZE(sama5d2_perick) + + ARRAY_SIZE(sama5d2_peri32ck), + ARRAY_SIZE(sama5d2_gck), + ARRAY_SIZE(sama5d2_progck)); + if (!pmc) + panic(); + pmc->base = base; + + main_rc_osc = pmc_register_main_rc_osc(pmc, "main_rc_osc", 12000000); + if (!main_rc_osc) + panic(); + + fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL); + if (fdt_prop) + bypass = fdt32_to_cpu(*fdt_prop); + + main_osc = pmc_register_main_osc(pmc, "main_osc", main_xtal_clk, + bypass); + if (!main_osc) + panic(); + + parents[0] = main_rc_osc; + parents[1] = main_osc; + main_clk = at91_clk_register_sam9x5_main(pmc, "mainck", parents, 2); + if (!main_clk) + panic(); + + pmc_clk = &pmc->chws[PMC_MAIN]; + pmc_clk->clk = main_clk; + pmc_clk->id = PMC_MAIN; + + clk = at91_clk_register_pll(pmc, "pllack", main_clk, 0, + &sama5d3_pll_layout, &plla_charac); + if (!clk) + panic(); + + plladivck = at91_clk_register_plldiv(pmc, "plladivck", clk); + if (!plladivck) + panic(); + + pmc_clk = &pmc->chws[PMC_PLLACK]; + pmc_clk->clk = plladivck; + pmc_clk->id = PMC_PLLACK; + + audiopll_fracck = at91_clk_register_audio_pll_frac(pmc, + "audiopll_fracck", + main_clk); + if (!audiopll_fracck) + panic(); + + pmc_clk = &pmc->chws[PMC_AUDIOPLL_FRACCK]; + pmc_clk->clk = audiopll_fracck; + pmc_clk->id = PMC_AUDIOPLL_FRACCK; + + clk = at91_clk_register_audio_pll_pad(pmc, "audiopll_padck", + audiopll_fracck); + if (!clk) + panic(); + + audiopll_pmcck = at91_clk_register_audio_pll_pmc(pmc, "audiopll_pmcck", + audiopll_fracck); + if (!audiopll_pmcck) + panic(); + + pmc_clk = &pmc->chws[PMC_AUDIOPLLCK]; + pmc_clk->clk = audiopll_pmcck; + pmc_clk->id = PMC_AUDIOPLLCK; + + utmi_clk = at91_clk_register_utmi(pmc, "utmick", main_clk); + if (!utmi_clk) + panic(); + + pmc_clk = &pmc->chws[PMC_UTMI]; + pmc_clk->clk = utmi_clk; + pmc_clk->id = PMC_UTMI; + + parents[0] = slow_clk; + parents[1] = main_clk; + parents[2] = plladivck; + parents[3] = utmi_clk; + + clk = at91_clk_register_master_pres(pmc, "masterck_pres", 4, + parents, + &at91sam9x5_master_layout, + &mck_charac, INT_MIN); + if (!clk) + panic(); + + pmc_clk = &pmc->chws[PMC_MCK_PRES]; + pmc_clk->clk = clk; + pmc_clk->id = PMC_MCK_PRES; + + mckdivck = at91_clk_register_master_div(pmc, "masterck_div", + clk, + &at91sam9x5_master_layout, + &mck_charac); + if (!mckdivck) + panic(); + + pmc_clk = &pmc->chws[PMC_MCK]; + pmc_clk->clk = mckdivck; + pmc_clk->id = PMC_MCK; + + h32mxck = at91_clk_register_h32mx(pmc, "h32mxck", mckdivck); + if (!h32mxck) + panic(); + + pmc_clk = &pmc->chws[PMC_MCK2]; + pmc_clk->clk = h32mxck; + pmc_clk->id = PMC_MCK2; + + parents[0] = plladivck; + parents[1] = utmi_clk; + usbck = at91sam9x5_clk_register_usb(pmc, "usbck", parents, 2); + if (!usbck) + panic(); + + pmc_clk = &pmc->chws[PMC_USBCK]; + pmc_clk->clk = usbck; + pmc_clk->id = PMC_USBCK; + + parents[0] = slow_clk; + parents[1] = main_clk; + parents[2] = plladivck; + parents[3] = utmi_clk; + parents[4] = mckdivck; + parents[5] = audiopll_pmcck; + for (i = 0; i < ARRAY_SIZE(sama5d2_progck); i++) { + sam_clk = &sama5d2_progck[i]; + clk = at91_clk_register_programmable(pmc, sam_clk->n, + parents, + PROGCK_PARENT_COUNT, i, + &sama5d2_prog_layout); + if (!clk) + panic(); + + pmc_clk = &pmc->pchws[i]; + pmc_clk->clk = clk; + pmc_clk->id = sam_clk->id; + } + + /* This array order must match the one in sama5d2_systemck */ + parents[0] = mckdivck; + parents[1] = mckdivck; + parents[2] = usbck; + parents[3] = usbck; + parents[4] = pmc->pchws[0].clk; + parents[5] = pmc->pchws[1].clk; + parents[6] = pmc->pchws[2].clk; + parents[7] = mckdivck; + for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) { + sam_clk = &sama5d2_systemck[i]; + clk = at91_clk_register_system(pmc, sam_clk->n, + parents[i], + sam_clk->id); + if (!clk) + panic(); + + pmc_clk = &pmc->shws[i]; + pmc_clk->clk = clk; + pmc_clk->id = sam_clk->id; + } + + for (i = 0; i < ARRAY_SIZE(sama5d2_perick); i++) { + sam_clk = &sama5d2_perick[i]; + clk = at91_clk_register_sam9x5_periph(pmc, + &sama5d2_pcr_layout, + sam_clk->n, + mckdivck, + sam_clk->id, + &range); + if (!clk) + panic(); + + pmc_clk = &pmc->phws[i]; + pmc_clk->clk = clk; + pmc_clk->id = sam_clk->id; + } + + for (i = 0; i < ARRAY_SIZE(sama5d2_peri32ck); i++) { + sam_clk = &sama5d2_peri32ck[i].clk; + clk = at91_clk_register_sam9x5_periph(pmc, + &sama5d2_pcr_layout, + sam_clk->n, + h32mxck, + sam_clk->id, + &sama5d2_peri32ck[i].r); + if (!clk) + panic(); + + pmc_clk = &pmc->phws[ARRAY_SIZE(sama5d2_perick) + i]; + pmc_clk->clk = clk; + pmc_clk->id = sam_clk->id; + } + + parents[0] = slow_clk; + parents[1] = main_clk; + parents[2] = plladivck; + parents[3] = utmi_clk; + parents[4] = mckdivck; + parents[5] = audiopll_pmcck; + for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) { + sam_clk = &sama5d2_gck[i].clk; + clk = at91_clk_register_generated(pmc, + &sama5d2_pcr_layout, + sam_clk->n, + parents, 6, + sam_clk->id, + &sama5d2_gck[i].r, + sama5d2_gck[i].chg_pid); + if (!clk) + panic(); + + pmc_clk = &pmc->ghws[i]; + pmc_clk->clk = clk; + pmc_clk->id = sam_clk->id; + } + + parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s0_clk"); + parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s0_gclk"); + clk = at91_clk_i2s_mux_register("i2s0_muxclk", parents, 2, 0); + if (!clk) + panic(); + + pmc->chws[PMC_I2S0_MUX].clk = clk; + pmc->chws[PMC_I2S0_MUX].id = PMC_I2S0_MUX; + + parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s1_clk"); + parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s1_gclk"); + clk = at91_clk_i2s_mux_register("i2s1_muxclk", parents, 2, 1); + if (!clk) + panic(); + + pmc->chws[PMC_I2S1_MUX].clk = clk; + pmc->chws[PMC_I2S1_MUX].id = PMC_I2S1_MUX; + + clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get, pmc); + + pmc_register_pm(); + + return TEE_SUCCESS; +} + +CLK_DT_DECLARE(sama5d2_clk, "atmel,sama5d2-pmc", pmc_setup); diff --git a/optee/optee_os/core/drivers/clk/sam/sub.mk b/optee/optee_os/core/drivers/clk/sam/sub.mk new file mode 100644 index 0000000..eca5a70 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sam/sub.mk @@ -0,0 +1,8 @@ +global-incdirs-y += . + +at91-common = at91_sckc.c at91_main.c at91_pmc.c at91_pll.c at91_plldiv.c +at91-common += at91_utmi.c at91_master.c at91_h32mx.c at91_usb.c +at91-common += at91_programmable.c at91_system.c at91_peripheral.c +at91-common += at91_generated.c at91_i2s_mux.c at91_audio_pll.c + +srcs-$(CFG_DRIVERS_SAMA5D2_CLK) += $(at91-common) sama5d2_clk.c diff --git a/optee/optee_os/core/drivers/clk/sub.mk b/optee/optee_os/core/drivers/clk/sub.mk new file mode 100644 index 0000000..6233483 --- /dev/null +++ b/optee/optee_os/core/drivers/clk/sub.mk @@ -0,0 +1,8 @@ +srcs-y += clk.c +srcs-$(CFG_DRIVERS_CLK_DT) += clk_dt.c +srcs-$(CFG_DRIVERS_CLK_FIXED) += fixed_clk.c +srcs-$(CFG_STM32MP_CLK_CORE) += clk-stm32-core.c +srcs-$(CFG_STM32MP13_CLK) += clk-stm32mp13.c +srcs-$(CFG_STM32MP15_CLK) += clk-stm32mp15.c + +subdirs-$(CFG_DRIVERS_SAM_CLK) += sam \ No newline at end of file diff --git a/optee/optee_os/core/drivers/crypto/aspeed/crypto_ast2600.c b/optee/optee_os/core/drivers/crypto/aspeed/crypto_ast2600.c new file mode 100644 index 0000000..c5e0317 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/aspeed/crypto_ast2600.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Aspeed Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "hace_ast2600.h" + +#define SCU_RST1 0x40 +#define SCU_RSTCLR1 0x44 +#define SCU_RST_CRYPTO BIT(4) + +#define SCU_CLKGATE1 0x80 +#define SCU_CLKGATECLR1 0x84 +#define SCU_CLKGATE_HACE BIT(13) + +static TEE_Result crypto_ast2600_init(void) +{ + TEE_Result rc = TEE_ERROR_GENERIC; + vaddr_t scu_virt = 0; + + scu_virt = core_mmu_get_va(SCU_BASE, MEM_AREA_IO_NSEC, SMALL_PAGE_SIZE); + if (!scu_virt) + panic(); + + /* ast2600 crypto engines share the same reset control */ + io_write32(scu_virt + SCU_RST1, SCU_RST_CRYPTO); + udelay(100); + io_write32(scu_virt + SCU_RSTCLR1, SCU_RST_CRYPTO); + + if (IS_ENABLED(CFG_CRYPTO_DRV_HASH)) { + io_write32(scu_virt + SCU_CLKGATECLR1, SCU_CLKGATE_HACE); + + rc = ast2600_drvcrypt_register_hash(); + if (rc) { + EMSG("cannot register hash driver, rc=%d", rc); + return rc; + } + } + + return TEE_SUCCESS; +} + +early_init_late(crypto_ast2600_init); diff --git a/optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.c b/optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.c new file mode 100644 index 0000000..1055025 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.c @@ -0,0 +1,400 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Aspeed Technology Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hace_ast2600.h" + +#define HACE_BASE 0x1e6d0000 + +/* register offsets and bit fields */ +#define HACE_STS 0x1C +#define HACE_STS_HASH_INT BIT(9) +#define HACE_STS_HASH_BUSY BIT(0) +#define HACE_HASH_DATA 0x20 +#define HACE_HASH_DIGEST 0x24 +#define HACE_HASH_HMAC_KEY 0x28 +#define HACE_HASH_DATA_LEN 0x2C +#define HACE_HASH_CMD 0x30 +#define HACE_HASH_CMD_ACCUM BIT(8) +#define HACE_HASH_CMD_ALG_SHA1 BIT(5) +#define HACE_HASH_CMD_ALG_SHA256 (BIT(6) | BIT(4)) +#define HACE_HASH_CMD_ALG_SHA384 (BIT(10) | BIT(6) | BIT(5)) +#define HACE_HASH_CMD_ALG_SHA512 (BIT(6) | BIT(5)) +#define HACE_HASH_CMD_SHA_BE BIT(3) + +/* buffer size based on SHA-512 need */ +#define HASH_BLK_BUFSZ 128 +#define HASH_DGT_BUFSZ 64 + +register_phys_mem(MEM_AREA_IO_SEC, HACE_BASE, SMALL_PAGE_SIZE); + +struct ast2600_hace_ctx { + struct crypto_hash_ctx hash_ctx; + uint32_t cmd; + uint32_t algo; + uint32_t dgt_size; + uint32_t blk_size; + uint32_t pad_size; + uint64_t total[2]; + + /* DMA memory to interact with HACE */ + uint8_t *buf; + uint8_t *digest; +}; + +static vaddr_t hace_virt; +struct mutex hace_mtx = MUTEX_INITIALIZER; + +static const uint32_t iv_sha1[8] = { + 0x01234567, 0x89abcdef, 0xfedcba98, 0x76543210, + 0xf0e1d2c3, 0, 0, 0 +}; + +static const uint32_t iv_sha256[8] = { + 0x67e6096a, 0x85ae67bb, 0x72f36e3c, 0x3af54fa5, + 0x7f520e51, 0x8c68059b, 0xabd9831f, 0x19cde05b +}; + +static const uint32_t iv_sha384[16] = { + 0x5d9dbbcb, 0xd89e05c1, 0x2a299a62, 0x07d57c36, + 0x5a015991, 0x17dd7030, 0xd8ec2f15, 0x39590ef7, + 0x67263367, 0x310bc0ff, 0x874ab48e, 0x11155868, + 0x0d2e0cdb, 0xa78ff964, 0x1d48b547, 0xa44ffabe +}; + +static const uint32_t iv_sha512[16] = { + 0x67e6096a, 0x08c9bcf3, 0x85ae67bb, 0x3ba7ca84, + 0x72f36e3c, 0x2bf894fe, 0x3af54fa5, 0xf1361d5f, + 0x7f520e51, 0xd182e6ad, 0x8c68059b, 0x1f6c3e2b, + 0xabd9831f, 0x6bbd41fb, 0x19cde05b, 0x79217e13 +}; + +static TEE_Result ast2600_hace_process(struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len) +{ + TEE_Result rc = TEE_ERROR_GENERIC; + uint32_t sts = 0; + uint64_t tref = 0; + paddr_t data_phys = 0; + paddr_t digest_phys = 0; + struct ast2600_hace_ctx *hctx = NULL; + + mutex_lock(&hace_mtx); + + hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); + + sts = io_read32(hace_virt + HACE_STS); + if (sts & HACE_STS_HASH_BUSY) { + rc = TEE_ERROR_BUSY; + goto out; + } + + cache_operation(TEE_CACHEFLUSH, (void *)data, len); + + data_phys = virt_to_phys((void *)data); + digest_phys = virt_to_phys(hctx->digest); + + io_write32(hace_virt + HACE_HASH_DATA, (uint32_t)data_phys); + io_write32(hace_virt + HACE_HASH_DIGEST, (uint32_t)digest_phys); + io_write32(hace_virt + HACE_HASH_HMAC_KEY, (uint32_t)digest_phys); + + io_write32(hace_virt + HACE_HASH_DATA_LEN, len); + io_write32(hace_virt + HACE_HASH_CMD, hctx->cmd); + + /* poll for completion */ + tref = timeout_init_us(1000 + (len >> 3)); + + do { + sts = io_read32(hace_virt + HACE_STS); + if (timeout_elapsed(tref)) { + rc = TEE_ERROR_TARGET_DEAD; + goto out; + } + } while (!(sts & HACE_STS_HASH_INT)); + + io_write32(hace_virt + HACE_STS, HACE_STS_HASH_INT); + + rc = TEE_SUCCESS; +out: + mutex_unlock(&hace_mtx); + + return rc; +} + +static TEE_Result ast2600_hace_init(struct crypto_hash_ctx *ctx) +{ + struct ast2600_hace_ctx *hctx = NULL; + + hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); + + switch (hctx->algo) { + case TEE_ALG_SHA1: + memcpy(hctx->digest, iv_sha1, sizeof(iv_sha1)); + break; + case TEE_ALG_SHA256: + memcpy(hctx->digest, iv_sha256, sizeof(iv_sha256)); + break; + case TEE_ALG_SHA384: + memcpy(hctx->digest, iv_sha384, sizeof(iv_sha384)); + break; + case TEE_ALG_SHA512: + memcpy(hctx->digest, iv_sha512, sizeof(iv_sha512)); + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + hctx->total[0] = 0; + hctx->total[1] = 0; + + cache_operation(TEE_CACHEFLUSH, hctx->digest, HASH_DGT_BUFSZ); + + return TEE_SUCCESS; +} + +static TEE_Result ast2600_hace_update(struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len) +{ + TEE_Result rc = TEE_ERROR_GENERIC; + uint32_t left = 0; + uint32_t fill = 0; + size_t blk_size = 0; + struct ast2600_hace_ctx *hctx = NULL; + + if (!ctx || !data || !len) + return TEE_ERROR_BAD_PARAMETERS; + + hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); + + blk_size = hctx->blk_size; + + left = hctx->total[0] & (blk_size - 1); + fill = blk_size - left; + + hctx->total[0] += len; + if (hctx->total[0] < len) + hctx->total[1]++; + + if (left && len >= fill) { + memcpy(hctx->buf + left, data, fill); + rc = ast2600_hace_process(ctx, hctx->buf, blk_size); + if (rc) + return rc; + + data += fill; + len -= fill; + left = 0; + } + + while (len >= blk_size) { + memcpy(hctx->buf, data, blk_size); + rc = ast2600_hace_process(ctx, hctx->buf, blk_size); + if (rc) + return rc; + + data += blk_size; + len -= blk_size; + } + + if (len) + memcpy(hctx->buf + left, data, len); + + return TEE_SUCCESS; +} + +static TEE_Result ast2600_hace_final(struct crypto_hash_ctx *ctx, + uint8_t *digest, size_t len) +{ + TEE_Result rc = TEE_ERROR_GENERIC; + uint32_t last = 0; + uint32_t padn = 0; + uint8_t pad[HASH_BLK_BUFSZ * 2] = { }; + uint64_t dbits[2] = { }; + uint64_t dbits_be[2] = { }; + struct ast2600_hace_ctx *hctx = NULL; + size_t length = 0; + + hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); + length = MIN(len, hctx->dgt_size); + + memset(pad, 0, sizeof(pad)); + pad[0] = 0x80; + + dbits[0] = (hctx->total[0] << 3); + dbits_be[0] = get_be64(&dbits[0]); + + dbits[1] = (hctx->total[0] >> 61) | (hctx->total[1] << 3); + dbits_be[1] = get_be64(&dbits[1]); + + last = hctx->total[0] & (hctx->blk_size - 1); + + switch (hctx->algo) { + case TEE_ALG_SHA1: + case TEE_ALG_SHA256: + if (last < 56) + padn = 56 - last; + else + padn = 120 - last; + + rc = ast2600_hace_update(ctx, pad, padn); + if (rc) + return rc; + + rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[0], + sizeof(dbits_be[0])); + if (rc) + return rc; + break; + case TEE_ALG_SHA384: + case TEE_ALG_SHA512: + if (last < 112) + padn = 112 - last; + else + padn = 240 - last; + + rc = ast2600_hace_update(ctx, pad, padn); + if (rc) + return rc; + + rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[1], + sizeof(dbits_be[1])); + if (rc) + return rc; + + rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[0], + sizeof(dbits_be[0])); + if (rc) + return rc; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + cache_operation(TEE_CACHEINVALIDATE, hctx->digest, HASH_DGT_BUFSZ); + + memcpy(digest, hctx->digest, length); + + return TEE_SUCCESS; +} + +static void ast2600_hace_free(struct crypto_hash_ctx *ctx) +{ + struct ast2600_hace_ctx *hctx = NULL; + + hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); + + free(hctx->buf); + free(hctx->digest); + free(hctx); +} + +static void ast2600_hace_copy_state(struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx) +{ + struct ast2600_hace_ctx *src_hctx = NULL; + struct ast2600_hace_ctx *dst_hctx = NULL; + + src_hctx = container_of(src_ctx, struct ast2600_hace_ctx, hash_ctx); + dst_hctx = container_of(dst_ctx, struct ast2600_hace_ctx, hash_ctx); + + dst_hctx->hash_ctx = src_hctx->hash_ctx; + dst_hctx->cmd = src_hctx->cmd; + dst_hctx->dgt_size = src_hctx->dgt_size; + dst_hctx->blk_size = src_hctx->blk_size; + dst_hctx->pad_size = src_hctx->pad_size; + dst_hctx->total[0] = src_hctx->total[0]; + dst_hctx->total[1] = src_hctx->total[1]; + + cache_operation(TEE_CACHEINVALIDATE, src_hctx->buf, HASH_BLK_BUFSZ); + memcpy(dst_hctx->buf, src_hctx->buf, HASH_BLK_BUFSZ); + cache_operation(TEE_CACHEFLUSH, dst_hctx->buf, HASH_BLK_BUFSZ); + + cache_operation(TEE_CACHEINVALIDATE, src_hctx->digest, HASH_DGT_BUFSZ); + memcpy(dst_hctx->digest, src_hctx->digest, HASH_DGT_BUFSZ); + cache_operation(TEE_CACHEFLUSH, dst_hctx->digest, HASH_DGT_BUFSZ); +} + +static const struct crypto_hash_ops ast2600_hace_ops = { + .init = ast2600_hace_init, + .update = ast2600_hace_update, + .final = ast2600_hace_final, + .free_ctx = ast2600_hace_free, + .copy_state = ast2600_hace_copy_state, +}; + +static TEE_Result ast2600_hace_alloc(struct crypto_hash_ctx **pctx, + uint32_t algo) +{ + struct ast2600_hace_ctx *hctx = calloc(1, sizeof(*hctx)); + + if (!hctx) + return TEE_ERROR_OUT_OF_MEMORY; + hctx->buf = memalign(HASH_BLK_BUFSZ, HASH_BLK_BUFSZ); + if (!hctx->buf) + return TEE_ERROR_OUT_OF_MEMORY; + + hctx->digest = memalign(HASH_DGT_BUFSZ, HASH_DGT_BUFSZ); + if (!hctx->digest) + return TEE_ERROR_OUT_OF_MEMORY; + + hctx->hash_ctx.ops = &ast2600_hace_ops; + hctx->algo = algo; + hctx->cmd = HACE_HASH_CMD_ACCUM | HACE_HASH_CMD_SHA_BE; + + switch (algo) { + case TEE_ALG_SHA1: + hctx->dgt_size = 20; + hctx->blk_size = 64; + hctx->pad_size = 8; + hctx->cmd |= HACE_HASH_CMD_ALG_SHA1; + break; + case TEE_ALG_SHA256: + hctx->dgt_size = 32; + hctx->blk_size = 64; + hctx->pad_size = 8; + hctx->cmd |= HACE_HASH_CMD_ALG_SHA256; + break; + case TEE_ALG_SHA384: + hctx->dgt_size = 48; + hctx->blk_size = 128; + hctx->pad_size = 16; + hctx->cmd |= HACE_HASH_CMD_ALG_SHA384; + break; + case TEE_ALG_SHA512: + hctx->dgt_size = 64; + hctx->blk_size = 128; + hctx->pad_size = 16; + hctx->cmd |= HACE_HASH_CMD_ALG_SHA512; + break; + default: + free(hctx); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + *pctx = &hctx->hash_ctx; + + return TEE_SUCCESS; +} + +TEE_Result ast2600_drvcrypt_register_hash(void) +{ + hace_virt = core_mmu_get_va(HACE_BASE, MEM_AREA_IO_SEC, + SMALL_PAGE_SIZE); + if (!hace_virt) { + EMSG("cannot get HACE virtual address"); + return TEE_ERROR_GENERIC; + } + + return drvcrypt_register_hash(ast2600_hace_alloc); +} diff --git a/optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.h b/optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.h new file mode 100644 index 0000000..09da7b6 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/aspeed/hace_ast2600.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Aspeed Technology Inc. + */ +#ifndef __HACE_AST2600_H__ +#define __HACE_AST2600_H__ + +#include + +#ifdef CFG_CRYPTO_DRV_HASH +TEE_Result ast2600_drvcrypt_register_hash(void); +#else +static inline TEE_Result ast2600_drvcrypt_register_hash(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif +#endif diff --git a/optee/optee_os/core/drivers/crypto/aspeed/sub.mk b/optee/optee_os/core/drivers/crypto/aspeed/sub.mk new file mode 100644 index 0000000..69f9920 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/aspeed/sub.mk @@ -0,0 +1,4 @@ +ifeq ($(PLATFORM_FLAVOR),ast2600) +srcs-y += crypto_ast2600.c +srcs-$(CFG_CRYPTO_DRV_HASH) += hace_ast2600.c +endif diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c new file mode 100644 index 0000000..6131ff0 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_dh.c @@ -0,0 +1,493 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Implementation of DH + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_CAAM_64BIT +#define MAX_DESC_KEY_GEN 14 +#define MAX_DESC_SHARED 14 +#else +#define MAX_DESC_KEY_GEN 9 +#define MAX_DESC_SHARED 9 +#endif + +/* + * Definition of the local DH Keypair + */ +struct caam_dh_keypair { + struct caambuf g; /* Generator */ + struct caambuf p; /* Prime Number Modulus */ + struct caambuf x; /* Private key */ + struct caambuf y; /* Public key */ +}; + +/* + * Free local DH keypair + * + * @key DH keypair + */ +static void do_keypair_free(struct caam_dh_keypair *key) +{ + caam_free_buf(&key->g); + caam_free_buf(&key->p); + caam_free_buf(&key->x); + caam_free_buf(&key->y); +} + +/* + * Convert Crypto DH Key p and g bignumbers to local buffers + * (via keypair object). + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + */ +static enum caam_status do_keypair_conv_p_g(struct caam_dh_keypair *outkey, + const struct dh_keypair *inkey) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + size_t p_size = 0; + size_t field_size = 0; + + p_size = crypto_bignum_num_bytes(inkey->p); + + DH_TRACE("DH Convert Key Parameters (p,g) size %zu bytes", p_size); + + /* Prime Number Modulus */ + retstatus = caam_calloc_buf(&outkey->p, p_size); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + crypto_bignum_bn2bin(inkey->p, outkey->p.data); + cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); + + /* Generator */ + retstatus = caam_calloc_buf(&outkey->g, p_size); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of g to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->g); + crypto_bignum_bn2bin(inkey->g, outkey->g.data + p_size - field_size); + cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length); + + return CAAM_NO_ERROR; +} + +/* + * Convert Crypto DH Private Key to a local Private Key (via keypair object) + * + * @outkey [out] Output local keypair + * @inkey Input Private key in TEE Crypto format + */ +static enum caam_status do_keypriv_conv(struct caam_dh_keypair *outkey, + const struct dh_keypair *inkey) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + size_t key_size = inkey->xbits / 8; + size_t p_size = 0; + + if (!key_size) + key_size = crypto_bignum_num_bytes(inkey->x); + + DH_TRACE("DH Convert Private Key size %zu bytes", key_size); + + /* Prime */ + p_size = crypto_bignum_num_bytes(inkey->p); + retstatus = caam_calloc_buf(&outkey->p, p_size); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + crypto_bignum_bn2bin(inkey->p, outkey->p.data); + cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); + + /* Private Key X */ + retstatus = caam_calloc_buf(&outkey->x, key_size); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + crypto_bignum_bn2bin(inkey->x, outkey->x.data); + cache_operation(TEE_CACHECLEAN, outkey->x.data, outkey->x.length); + + return CAAM_NO_ERROR; +} + +/* + * Convert Crypto DH Public Key to local Public Key (via a keypair object) + * + * @outkey [out] Output local keypair + * @inkey Input Public key in TEE Crypto format + */ +static enum caam_status do_keypub_conv(struct caam_dh_keypair *outkey, + const struct bignum *inkey) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + size_t key_size = 0; + + key_size = crypto_bignum_num_bytes((struct bignum *)inkey); + DH_TRACE("DH Convert Keypair size %zu bytes", key_size); + + /* Public Key Y */ + retstatus = caam_calloc_buf(&outkey->y, key_size); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + crypto_bignum_bn2bin(inkey, outkey->y.data); + cache_operation(TEE_CACHECLEAN, outkey->y.data, outkey->y.length); + + return CAAM_NO_ERROR; +} + +/* + * Allocate a TEE DH keypair. + * Note: The subprime q is not used but it must be allocated to prevent + * system referencing issues when object is destroyed. + * + * @key Keypair + * @size_bits Key size in bits + */ +static TEE_Result do_allocate_keypair(struct dh_keypair *key, size_t size_bits) +{ + DH_TRACE("Allocate Keypair of %zu bits", size_bits); + + /* Initialize the key fields to NULL */ + memset(key, 0, sizeof(*key)); + + /* Allocate Generator Scalar */ + key->g = crypto_bignum_allocate(size_bits); + if (!key->g) + goto err; + + /* Allocate Prime Number Modulus */ + key->p = crypto_bignum_allocate(size_bits); + if (!key->p) + goto err; + + /* Allocate Private key X */ + key->x = crypto_bignum_allocate(size_bits); + if (!key->x) + goto err; + + /* Allocate Public Key Y */ + key->y = crypto_bignum_allocate(size_bits); + if (!key->y) + goto err; + + /* Allocate Subprime even if not used */ + key->q = crypto_bignum_allocate(size_bits); + if (!key->q) + goto err; + + return TEE_SUCCESS; + +err: + DH_TRACE("Allocation error"); + + crypto_bignum_free(key->g); + crypto_bignum_free(key->p); + crypto_bignum_free(key->x); + crypto_bignum_free(key->y); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +/* + * Generates an DH keypair + * Keypair @key contains the input prime p and generator g values + * The function calculates private x and public y, knowing that the + * number of bits of x is either key_size if specified or p size. + * + * @key [in/out] Keypair + * @q Sub Prime (not used) + * @key_size Key size in bits multiple of 8 bits + */ +static TEE_Result do_gen_keypair(struct dh_keypair *key, + struct bignum *q __unused, size_t key_size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_dh_keypair caam_dh_key = { }; + struct caambuf dh_r = { }; + size_t n_bytes = key_size / 8; + size_t l_bytes = 0; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + int counter = 0; + + l_bytes = crypto_bignum_num_bytes(key->p); + if (!l_bytes) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * If @key_size not specified, private key size is + * same as the public key size (same as prime size) + */ + if (!n_bytes) + n_bytes = l_bytes; + + /* + * CAAM private key support is limited to the descriptor PDB + * N maximum value (PDB_DL_KEY_N_MASK) + */ + if (n_bytes > PDB_DL_KEY_N_MASK) + n_bytes = PDB_DL_KEY_N_MASK; + + DH_TRACE("Request %zu bits key -> so do %zu bytes key", key_size, + n_bytes); + + /* Allocate the job used to prepare the operation */ + desc = caam_calloc_desc(MAX_DESC_KEY_GEN); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Allocate Private Key to be generated */ + retstatus = caam_calloc_align_buf(&caam_dh_key.x, n_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + cache_operation(TEE_CACHEFLUSH, caam_dh_key.x.data, + caam_dh_key.x.length); + + /* Allocate Public Key to be generated */ + retstatus = caam_calloc_align_buf(&caam_dh_key.y, l_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + cache_operation(TEE_CACHEFLUSH, caam_dh_key.y.data, + caam_dh_key.y.length); + + /* Allocate Private Key modulus (r) and fill it with one's */ + retstatus = caam_calloc_buf(&dh_r, n_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + memset(dh_r.data, UINT8_MAX, dh_r.length); + cache_operation(TEE_CACHECLEAN, dh_r.data, dh_r.length); + + /* Generator and Prime */ + retstatus = do_keypair_conv_p_g(&caam_dh_key, key); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* + * Build the descriptor using the PDB Public Key generation + * block (PD=0) + */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_DL_KEY_L_SIZE(l_bytes) | + PDB_DL_KEY_N_SIZE(n_bytes)); + caam_desc_add_ptr(desc, caam_dh_key.p.paddr); + caam_desc_add_ptr(desc, dh_r.paddr); + caam_desc_add_ptr(desc, caam_dh_key.g.paddr); + caam_desc_add_ptr(desc, caam_dh_key.x.paddr); + caam_desc_add_ptr(desc, caam_dh_key.y.paddr); + caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL)); + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + DH_DUMPDESC(desc); + + /* + * If the Secure Key X doesn't have the correct size + * retry a new generation. + * Retry 10 times before returing an error to not lock the system. + */ + for (counter = 0; counter < 10; counter++) { + memset(&jobctx, 0, sizeof(jobctx)); + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + cache_operation(TEE_CACHEINVALIDATE, caam_dh_key.x.data, + caam_dh_key.x.length); + cache_operation(TEE_CACHEINVALIDATE, caam_dh_key.y.data, + caam_dh_key.y.length); + + /* Copy Private and Public keypair */ + ret = crypto_bignum_bin2bn(caam_dh_key.x.data, + caam_dh_key.x.length, + key->x); + if (ret != TEE_SUCCESS) + goto out; + + if (crypto_bignum_num_bytes(key->x) != n_bytes) { + DH_TRACE("Error X size=%zu expected %zu", + crypto_bignum_num_bytes(key->x), + n_bytes); + DH_DUMPBUF("X", caam_dh_key.x.data, + caam_dh_key.x.length); + DH_DUMPBUF("Y", caam_dh_key.y.data, + caam_dh_key.y.length); + continue; + } + + ret = crypto_bignum_bin2bn(caam_dh_key.y.data, + caam_dh_key.y.length, + key->y); + if (ret != TEE_SUCCESS) + goto out; + + /* Set the Private Key size in bits */ + key->xbits = n_bytes * 8; + + ret = TEE_SUCCESS; + goto out; + } else { + DH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + goto out; + } + } + +out: + caam_free_desc(&desc); + caam_free_buf(&dh_r); + do_keypair_free(&caam_dh_key); + + return ret; +} + +/* + * Compute the shared secret data from DH Private key and Public Key + * + * @sdata [in/out] DH Shared Secret data + */ +static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct dh_keypair *inkeypair = sdata->key_priv; + struct caam_dh_keypair caam_dh_key = { }; + struct caamdmaobj secret = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + uint32_t pdb_sgt_flags = 0; + + DH_TRACE("DH Shared Secret"); + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(MAX_DESC_SHARED); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* + * ReAllocate the secret result buffer with a maximum size + * of the secret size if not cache aligned + */ + ret = caam_dmaobj_output_sgtbuf(&secret, sdata->secret.data, + sdata->secret.length, + sdata->secret.length); + if (ret) + goto out; + + if (secret.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKDH_SECRET; + + caam_dmaobj_cache_push(&secret); + + /* Convert the Private key to local key */ + retstatus = do_keypriv_conv(&caam_dh_key, inkeypair); + if (retstatus != CAAM_NO_ERROR) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Convert the Public key to local key */ + retstatus = do_keypub_conv(&caam_dh_key, sdata->key_pub); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* + * Build the descriptor using PDB Shared Secret + */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, pdb_sgt_flags | + PDB_DL_KEY_L_SIZE(caam_dh_key.y.length) | + PDB_DL_KEY_N_SIZE(caam_dh_key.x.length)); + /* Prime */ + caam_desc_add_ptr(desc, caam_dh_key.p.paddr); + /* Modulus - Not used */ + caam_desc_add_ptr(desc, 0); + /* Public key */ + caam_desc_add_ptr(desc, caam_dh_key.y.paddr); + /* Private key */ + caam_desc_add_ptr(desc, caam_dh_key.x.paddr); + /* Output secret */ + caam_desc_add_ptr(desc, secret.sgtbuf.paddr); + + caam_desc_add_word(desc, SHARED_SECRET(DL)); + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + DH_DUMPDESC(desc); + jobctx.desc = desc; + + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + sdata->secret.length = caam_dmaobj_copy_to_orig(&secret); + + DH_DUMPBUF("Secret", sdata->secret.data, sdata->secret.length); + ret = caam_status_to_tee_result(retstatus); + } else { + DH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_free_desc(&desc); + do_keypair_free(&caam_dh_key); + caam_dmaobj_free(&secret); + + return ret; +} + +/* + * Registration of the ECC Driver + */ +static struct drvcrypt_dh driver_dh = { + .alloc_keypair = do_allocate_keypair, + .gen_keypair = do_gen_keypair, + .shared_secret = do_shared_secret, +}; + +enum caam_status caam_dh_init(struct caam_jrcfg *caam_jrcfg) +{ + enum caam_status retstatus = CAAM_FAILURE; + vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; + + if (caam_hal_ctrl_pknum(jr_base) && + drvcrypt_register_dh(&driver_dh) == TEE_SUCCESS) + retstatus = CAAM_NO_ERROR; + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c new file mode 100644 index 0000000..2696f0b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_dsa.c @@ -0,0 +1,777 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019-2021 NXP + * + * Implementation of DSA functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +#ifdef CFG_CAAM_64BIT +#define MAX_DESC_KEY_GEN 14 +#define MAX_DESC_SIGN 19 +#define MAX_DESC_VERIFY 21 +#else +#define MAX_DESC_KEY_GEN 9 +#define MAX_DESC_SIGN 12 +#define MAX_DESC_VERIFY 13 +#endif + +/* + * Definition of the local DSA Keypair + * Domain Parameters (p, q, g) + * Private Key format (x) + * Public Key format (y) + */ +struct caam_dsa_keypair { + struct caambuf g; /* Generator */ + struct caambuf p; /* Prime Number (L bits) */ + struct caambuf q; /* Subprime Number (N bits) */ + struct caambuf x; /* Private key */ + struct caambuf y; /* Public key */ +}; + +/* + * Free local DSA keypair + * + * @key DSA keypair + */ +static void do_keypair_free(struct caam_dsa_keypair *key) +{ + caam_free_buf(&key->g); + caam_free_buf(&key->p); + caam_free_buf(&key->q); + caam_free_buf(&key->x); + caam_free_buf(&key->y); +} + +/* + * If all DSA parameters p, q and g are present, convert them from bignumbers + * to local buffers (via keypair object). Otherwise generate them. + * + * @outkey [out] Output keypair in local format + * @key Input key in TEE Crypto format + * @l_bytes Prime p size in bytes + * @n_bytes Subprime q size in bytes + */ +static TEE_Result get_keypair_domain_params(struct caam_dsa_keypair *outkey, + const struct dsa_keypair *key, + size_t l_bytes, size_t n_bytes) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + size_t in_q_size = 0; + size_t in_p_size = 0; + size_t in_g_size = 0; + struct prime_data_dsa prime = { }; + + DSA_TRACE("DSA conv key param (p, g) of %zu bytes and (q) of %zu bytes", + l_bytes, n_bytes); + + retstatus = caam_calloc_buf(&outkey->q, n_bytes); + if (retstatus != CAAM_NO_ERROR) + return caam_status_to_tee_result(retstatus); + + retstatus = caam_calloc_buf(&outkey->g, l_bytes); + if (retstatus != CAAM_NO_ERROR) + return caam_status_to_tee_result(retstatus); + + retstatus = caam_calloc_buf(&outkey->p, l_bytes); + if (retstatus != CAAM_NO_ERROR) + return caam_status_to_tee_result(retstatus); + + /* + * Get all inputs parameters size, if one of them is not + * define generate new parameters + */ + in_g_size = crypto_bignum_num_bytes(key->g); + in_p_size = crypto_bignum_num_bytes(key->p); + in_q_size = crypto_bignum_num_bytes(key->q); + + if (!in_q_size || !in_g_size || !in_p_size) { + /* Generate DSA parameters: Generator G and Primes P/Q */ + prime.g = &outkey->g; + prime.p = &outkey->p; + prime.q = &outkey->q; + + retstatus = caam_prime_dsa_gen(&prime); + DSA_TRACE("Generate G and Primes P/Q returned %#x", retstatus); + + if (retstatus != CAAM_NO_ERROR) + return caam_status_to_tee_result(retstatus); + + /* Copy Generated DSA Parameter */ + crypto_bignum_bin2bn(outkey->q.data, outkey->q.length, key->q); + crypto_bignum_bin2bn(outkey->g.data, outkey->g.length, key->g); + crypto_bignum_bin2bn(outkey->p.data, outkey->p.length, key->p); + + } else { + DSA_TRACE("Prime Q is defined"); + + crypto_bignum_bn2bin(key->q, + outkey->q.data + n_bytes - in_q_size); + cache_operation(TEE_CACHECLEAN, outkey->q.data, + outkey->q.length); + + DSA_TRACE("Prime G is defined"); + crypto_bignum_bn2bin(key->g, + outkey->g.data + l_bytes - in_g_size); + cache_operation(TEE_CACHECLEAN, outkey->g.data, + outkey->g.length); + + DSA_TRACE("Prime P is defined"); + crypto_bignum_bn2bin(key->p, + outkey->p.data + l_bytes - in_p_size); + cache_operation(TEE_CACHECLEAN, outkey->p.data, + outkey->p.length); + } + + return TEE_SUCCESS; +} + +/* + * Convert Crypto DSA Private Key to local Keypair Key + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + * @l_bytes Prime p size in bytes + * @n_bytes Subprime q size in bytes + */ +static enum caam_status do_keypriv_conv(struct caam_dsa_keypair *outkey, + const struct dsa_keypair *inkey, + size_t l_bytes, size_t n_bytes) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + size_t field_size = 0; + + DSA_TRACE("DSA Convert Key Private size l=%zu bytes, n=%zu bytes", + l_bytes, n_bytes); + + /* Generator */ + retstatus = caam_calloc_buf(&outkey->g, l_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of g to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->g); + crypto_bignum_bn2bin(inkey->g, outkey->g.data + l_bytes - field_size); + + /* Prime Number Modulus */ + retstatus = caam_calloc_buf(&outkey->p, l_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of p to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->p); + crypto_bignum_bn2bin(inkey->p, outkey->p.data + l_bytes - field_size); + + /* Subprime Number Modulus */ + retstatus = caam_calloc_buf(&outkey->q, n_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of q to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->q); + crypto_bignum_bn2bin(inkey->q, outkey->q.data + n_bytes - field_size); + + /* Private key is only scalar x of n bytes */ + retstatus = caam_calloc_buf(&outkey->x, n_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of x to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->x); + crypto_bignum_bn2bin(inkey->x, outkey->x.data + n_bytes - field_size); + + cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length); + cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); + cache_operation(TEE_CACHECLEAN, outkey->q.data, outkey->q.length); + cache_operation(TEE_CACHECLEAN, outkey->x.data, outkey->x.length); + + return CAAM_NO_ERROR; +} + +/* + * Convert Crypto DSA Public Key to local DSA Keypair Key + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + * @l_bytes Prime p size in bytes + * @n_bytes Subprime q size in bytes + */ +static enum caam_status do_keypub_conv(struct caam_dsa_keypair *outkey, + const struct dsa_public_key *inkey, + size_t l_bytes, size_t n_bytes) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + size_t field_size = 0; + + DSA_TRACE("DSA Convert Public Key size l=%zu bytes, n=%zu bytes", + l_bytes, n_bytes); + + /* Generator */ + retstatus = caam_calloc_buf(&outkey->g, l_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of g to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->g); + crypto_bignum_bn2bin(inkey->g, outkey->g.data + l_bytes - field_size); + + /* Prime Number Modulus */ + retstatus = caam_calloc_buf(&outkey->p, l_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of p to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->p); + crypto_bignum_bn2bin(inkey->p, outkey->p.data + l_bytes - field_size); + + /* Subprime Number Modulus */ + retstatus = caam_calloc_buf(&outkey->q, n_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of q to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->q); + crypto_bignum_bn2bin(inkey->q, outkey->q.data + n_bytes - field_size); + + /* Public key is only scalar y of l bytes */ + retstatus = caam_calloc_buf(&outkey->y, l_bytes); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of y to pad with 0's */ + field_size = crypto_bignum_num_bytes(inkey->y); + crypto_bignum_bn2bin(inkey->y, outkey->y.data + l_bytes - field_size); + + cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length); + cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); + cache_operation(TEE_CACHECLEAN, outkey->q.data, outkey->q.length); + cache_operation(TEE_CACHECLEAN, outkey->y.data, outkey->y.length); + + return CAAM_NO_ERROR; +} + +/* + * Allocate a TEE DSA keypair. + * + * @key Keypair + * @l_bits L bits size (prime p size) + * @n_bits N bits size (subprime q size) + */ +static TEE_Result do_allocate_keypair(struct dsa_keypair *key, size_t l_bits, + size_t n_bits) +{ + DSA_TRACE("DSA allocate Keypair of L=%zu bits and N=%zu bits", l_bits, + n_bits); + + /* Initialize the key fields to NULL */ + memset(key, 0, sizeof(*key)); + + /* Allocate Generator Scalar */ + key->g = crypto_bignum_allocate(l_bits); + if (!key->g) + goto err; + + /* Allocate Prime Number Modulus */ + key->p = crypto_bignum_allocate(l_bits); + if (!key->p) + goto err; + + /* Allocate Prime Number Modulus */ + key->q = crypto_bignum_allocate(n_bits); + if (!key->q) + goto err; + + /* Allocate Private key X */ + key->x = crypto_bignum_allocate(n_bits); + if (!key->x) + goto err; + + /* Allocate Public Key Y */ + key->y = crypto_bignum_allocate(l_bits); + if (!key->y) + goto err; + + return TEE_SUCCESS; + +err: + DSA_TRACE("Allocation error"); + + crypto_bignum_free(key->g); + crypto_bignum_free(key->p); + crypto_bignum_free(key->q); + crypto_bignum_free(key->x); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +/* + * Allocate a DSA Public Key + * + * @key Public Key + * @l_bits L bits size (prime p size) + * @n_bits N bits size (subprime q size) + */ +static TEE_Result do_allocate_publickey(struct dsa_public_key *key, + size_t l_bits, size_t n_bits) +{ + DSA_TRACE("DSA Allocate Public of L=%zu bits and N=%zu bits", l_bits, + n_bits); + + /* Initialize the key fields to NULL */ + memset(key, 0, sizeof(*key)); + + /* Allocate Generator Scalar */ + key->g = crypto_bignum_allocate(l_bits); + if (!key->g) + goto err; + + /* Allocate Prime Number Modulus */ + key->p = crypto_bignum_allocate(l_bits); + if (!key->p) + goto err; + + /* Allocate Prime Number Modulus */ + key->q = crypto_bignum_allocate(n_bits); + if (!key->q) + goto err; + + /* Allocate Public Key Y */ + key->y = crypto_bignum_allocate(l_bits); + if (!key->y) + goto err; + + return TEE_SUCCESS; + +err: + DSA_TRACE("Allocation error"); + + crypto_bignum_free(key->g); + crypto_bignum_free(key->p); + crypto_bignum_free(key->q); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +/* + * Generates an DSA keypair + * Keypair @key contains the input primes p, g and generator g values + * The function computes private x and public y. + * + * @key [in/out] Keypair + * @l_bits L bits size (prime p size) + * @n_bits N bits size (subprime q size) + */ +static TEE_Result do_gen_keypair(struct dsa_keypair *key, size_t l_bits, + size_t n_bits) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_dsa_keypair caam_dsa_key = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + size_t l_bytes = l_bits / 8; + size_t n_bytes = n_bits / 8; + + DSA_TRACE("Generate Key - Private (%zu bits) and Public (%zu bits)", + n_bits, l_bits); + + /* Allocate the job used to prepare the operation */ + desc = caam_calloc_desc(MAX_DESC_KEY_GEN); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Allocate Private Key to be generated */ + retstatus = caam_calloc_align_buf(&caam_dsa_key.x, n_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + cache_operation(TEE_CACHEFLUSH, caam_dsa_key.x.data, + caam_dsa_key.x.length); + + /* Allocate Public Key to be generated */ + retstatus = caam_calloc_align_buf(&caam_dsa_key.y, l_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + cache_operation(TEE_CACHEFLUSH, caam_dsa_key.y.data, + caam_dsa_key.y.length); + + /* Generator and Prime */ + ret = get_keypair_domain_params(&caam_dsa_key, key, l_bytes, n_bytes); + if (ret != TEE_SUCCESS) + goto out; + + /* + * Build the descriptor using the PDB Public Key generation + * block (PD=0) + */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_DL_KEY_L_SIZE(l_bytes) | + PDB_DL_KEY_N_SIZE(n_bytes)); + caam_desc_add_ptr(desc, caam_dsa_key.p.paddr); + caam_desc_add_ptr(desc, caam_dsa_key.q.paddr); + caam_desc_add_ptr(desc, caam_dsa_key.g.paddr); + caam_desc_add_ptr(desc, caam_dsa_key.x.paddr); + caam_desc_add_ptr(desc, caam_dsa_key.y.paddr); + caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL)); + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + DSA_DUMPDESC(desc); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + cache_operation(TEE_CACHEINVALIDATE, caam_dsa_key.x.data, + caam_dsa_key.x.length); + cache_operation(TEE_CACHEINVALIDATE, caam_dsa_key.y.data, + caam_dsa_key.y.length); + + /* Copy Private and Public keypair */ + ret = crypto_bignum_bin2bn(caam_dsa_key.x.data, + caam_dsa_key.x.length, key->x); + if (ret != TEE_SUCCESS) + goto out; + + ret = crypto_bignum_bin2bn(caam_dsa_key.y.data, + caam_dsa_key.y.length, key->y); + if (ret != TEE_SUCCESS) + goto out; + + DSA_DUMPBUF("X", caam_dsa_key.x.data, caam_dsa_key.x.length); + DSA_DUMPBUF("Y", caam_dsa_key.y.data, caam_dsa_key.y.length); + } else { + DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_free_desc(&desc); + do_keypair_free(&caam_dsa_key); + + return ret; +} + +/* + * Signature of DSA message + * Note : the message to sign is already hashed + * + * @sdata [in/out] DSA data to sign / Signature + * @l_bytes L bytes size (prime p size) + * @n_bytes N bytes size (subprime q size) + */ +static TEE_Result do_sign(struct drvcrypt_sign_data *sdata, size_t l_bytes, + size_t n_bytes) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct dsa_keypair *inkey = sdata->key; + struct caam_dsa_keypair dsakey = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + struct caamdmaobj msg = { }; + size_t sign_len = 0; + struct caamdmaobj sign_c = { }; + struct caamdmaobj sign_d = { }; + uint32_t pdb_sgt_flags = 0; + + DSA_TRACE("DSA Signature"); + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(MAX_DESC_SIGN); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Convert the private key to a local key */ + retstatus = do_keypriv_conv(&dsakey, inkey, l_bytes, n_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, + sdata->message.length); + if (ret) + goto out; + + if (msg.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG; + + caam_dmaobj_cache_push(&msg); + + DSA_DUMPBUF("Message", sdata->message.data, sdata->message.length); + + /* + * Re-allocate the signature result buffer with a maximum size + * of the roundup to 16 bytes of the secure size in bytes if + * the signature buffer is not aligned or too short. + * + * - 1st Part: size_sec + * - 2nd Part: size_sec roundup to 16 bytes + */ + sign_len = ROUNDUP(sdata->size_sec, 16) + sdata->size_sec; + + ret = caam_dmaobj_output_sgtbuf(&sign_c, sdata->signature.data, + sdata->signature.length, sign_len); + if (ret) + goto out; + + if (sign_c.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_C; + + /* Prepare the 2nd Part of the signature. Derive from sign_c */ + ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec, + ROUNDUP(sdata->size_sec, 16)); + if (ret) + goto out; + + if (sign_d.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_D; + + caam_dmaobj_cache_push(&sign_c); + + /* + * Build the descriptor using Predifined ECC curve + */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_DSA_SIGN_N(n_bytes) | + PDB_DSA_SIGN_L(l_bytes) | pdb_sgt_flags); + /* Prime number */ + caam_desc_add_ptr(desc, dsakey.p.paddr); + /* Prime Modulus */ + caam_desc_add_ptr(desc, dsakey.q.paddr); + /* Generator */ + caam_desc_add_ptr(desc, dsakey.g.paddr); + /* Secret key */ + caam_desc_add_ptr(desc, dsakey.x.paddr); + /* Input message */ + caam_desc_add_ptr(desc, msg.sgtbuf.paddr); + /* Signature 1st part */ + caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); + /* Signature 2nd part */ + caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); + /* Message length */ + caam_desc_add_word(desc, sdata->message.length); + + caam_desc_add_word(desc, DSA_SIGN(DL)); + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + ECC_DUMPDESC(desc); + + jobctx.desc = desc; + + retstatus = caam_jr_enqueue(&jobctx, NULL); + if (retstatus == CAAM_NO_ERROR) { + /* Limit the copy to 2 * sdata->size_sec */ + sign_c.orig.length = 2 * sdata->size_sec; + sdata->signature.length = caam_dmaobj_copy_to_orig(&sign_c); + + DSA_DUMPBUF("Signature", sdata->signature.data, + sdata->signature.length); + + ret = caam_status_to_tee_result(retstatus); + } else { + DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_free_desc(&desc); + do_keypair_free(&dsakey); + caam_dmaobj_free(&msg); + caam_dmaobj_free(&sign_c); + caam_dmaobj_free(&sign_d); + + return ret; +} + +/* + * Verification of the Signature of DSA message + * Note the message is already hashed + * + * @sdata [in/out] DSA Signature to verify + * @l_bytes L bytes size (prime p size) + * @n_bytes N bytes size (subprime q size) + */ +static TEE_Result do_verify(struct drvcrypt_sign_data *sdata, size_t l_bytes, + size_t n_bytes) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct dsa_public_key *inkey = sdata->key; + struct caam_dsa_keypair dsakey = { }; + struct caambuf tmp = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + struct caamdmaobj msg = { }; + struct caamdmaobj sign_c = { }; + struct caamdmaobj sign_d = { }; + uint32_t pdb_sgt_flags = 0; + + DSA_TRACE("DSA Verify"); + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(MAX_DESC_VERIFY); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Convert the Public key to local key */ + retstatus = do_keypub_conv(&dsakey, inkey, l_bytes, n_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, + sdata->message.length); + if (ret) + goto out; + + if (msg.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG; + + caam_dmaobj_cache_push(&msg); + + /* + * Prepare the 1st Part of the signature + * Handle the full signature in case signature buffer needs to + * be reallocated. + */ + ret = caam_dmaobj_input_sgtbuf(&sign_c, sdata->signature.data, + sdata->signature.length); + if (ret) + goto out; + + if (sign_c.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_C; + + /* Prepare the 2nd Part of the signature, derive from sign_c */ + ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec, + sdata->size_sec); + if (ret) + goto out; + + if (sign_d.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_D; + + caam_dmaobj_cache_push(&sign_c); + + /* Allocate a Temporary buffer used by the CAAM */ + retstatus = caam_alloc_align_buf(&tmp, l_bytes); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* + * Build the descriptor using Predifined ECC curve + */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_DSA_VERIF_N(n_bytes) | + PDB_DSA_VERIF_L(l_bytes) | pdb_sgt_flags); + /* Prime number */ + caam_desc_add_ptr(desc, dsakey.p.paddr); + /* Prime Modulus */ + caam_desc_add_ptr(desc, dsakey.q.paddr); + /* Generator */ + caam_desc_add_ptr(desc, dsakey.g.paddr); + /* Public key */ + caam_desc_add_ptr(desc, dsakey.y.paddr); + /* Input message */ + caam_desc_add_ptr(desc, msg.sgtbuf.paddr); + /* Signature 1st part */ + caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); + /* Signature 2nd part */ + caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); + /* Temporary buffer */ + caam_desc_add_ptr(desc, tmp.paddr); + /* Message length */ + caam_desc_add_word(desc, sdata->message.length); + + caam_desc_add_word(desc, DSA_VERIFY(DL)); + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + DSA_DUMPDESC(desc); + + jobctx.desc = desc; + + cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length); + + retstatus = caam_jr_enqueue(&jobctx, NULL); + if (retstatus == CAAM_JOB_STATUS && !jobctx.status) { + DSA_TRACE("DSA Verify Status 0x%08" PRIx32, jobctx.status); + ret = TEE_ERROR_SIGNATURE_INVALID; + } else if (retstatus != CAAM_NO_ERROR) { + DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } else { + ret = caam_status_to_tee_result(retstatus); + } + +out: + caam_free_desc(&desc); + do_keypair_free(&dsakey); + caam_free_buf(&tmp); + caam_dmaobj_free(&msg); + caam_dmaobj_free(&sign_c); + caam_dmaobj_free(&sign_d); + + return ret; +} + +/* + * Registration of the DSA Driver + */ +static struct drvcrypt_dsa driver_dsa = { + .alloc_keypair = do_allocate_keypair, + .alloc_publickey = do_allocate_publickey, + .gen_keypair = do_gen_keypair, + .sign = do_sign, + .verify = do_verify, +}; + +enum caam_status caam_dsa_init(struct caam_jrcfg *caam_jrcfg) +{ + enum caam_status retstatus = CAAM_FAILURE; + vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; + + if (caam_hal_ctrl_pknum(jr_base) && + drvcrypt_register_dsa(&driver_dsa) == TEE_SUCCESS) + retstatus = CAAM_NO_ERROR; + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c new file mode 100644 index 0000000..db4c15f --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_ecc.c @@ -0,0 +1,719 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Implementation of ECC functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_CAAM_64BIT +#define MAX_DESC_KEY_GEN 8 +#define MAX_DESC_SIGN 13 +#define MAX_DESC_VERIFY 15 +#define MAX_DESC_SHARED 10 +#else +#define MAX_DESC_KEY_GEN 6 +#define MAX_DESC_SIGN 9 +#define MAX_DESC_VERIFY 10 +#define MAX_DESC_SHARED 7 +#endif + +/* + * Definition of the local ECC Keypair + * Public Key format (x, y) + * Private Key format (d) + */ +struct caam_ecc_keypair { + struct caambuf xy; + struct caambuf d; +}; + +/* + * Free local ECC keypair + * + * @key ECC keypair + */ +static void do_keypair_free(struct caam_ecc_keypair *key) +{ + caam_free_buf(&key->xy); + caam_free_buf(&key->d); +} + +/* + * Convert Crypto ECC Key to local ECC Public Key + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + * @size_sec Security size in bytes + */ +static enum caam_status do_keypub_conv(struct caam_ecc_keypair *outkey, + const struct ecc_public_key *inkey, + size_t size_sec) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + size_t x_size = 0; + size_t y_size = 0; + + ECC_TRACE("ECC Convert Public Key size %zu bytes", size_sec); + + /* Point (x y) is twice security key size */ + retstatus = caam_calloc_buf(&outkey->xy, 2 * size_sec); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Copy x and y and get the number of bytes to pad with 0's */ + x_size = crypto_bignum_num_bytes(inkey->x); + crypto_bignum_bn2bin(inkey->x, outkey->xy.data + size_sec - x_size); + + y_size = crypto_bignum_num_bytes(inkey->y); + crypto_bignum_bn2bin(inkey->y, outkey->xy.data + 2 * size_sec - y_size); + + cache_operation(TEE_CACHECLEAN, outkey->xy.data, outkey->xy.length); + + return CAAM_NO_ERROR; +} + +/* + * Convert Crypto ECC Key to local ECC Keypair Key + * Don't convert the exponent e not used in decrytion + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + * @size_sec Security size in bytes + */ +static enum caam_status do_keypair_conv(struct caam_ecc_keypair *outkey, + const struct ecc_keypair *inkey, + size_t size_sec) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + size_t d_size = 0; + + ECC_TRACE("ECC Convert Keypair size %zu bytes", size_sec); + + /* Private key is only scalar d of sec_size bytes */ + retstatus = caam_calloc_buf(&outkey->d, size_sec); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + /* Get the number of bytes of d to pad with 0's */ + d_size = crypto_bignum_num_bytes(inkey->d); + crypto_bignum_bn2bin(inkey->d, outkey->d.data + size_sec - d_size); + + cache_operation(TEE_CACHECLEAN, outkey->d.data, outkey->d.length); + + return CAAM_NO_ERROR; +} + +/* + * Convert TEE ECC Curve to CAAM ECC Curve + * + * @tee_curve TEE ECC Curve + */ +static enum caam_ecc_curve get_caam_curve(uint32_t tee_curve) +{ + enum caam_ecc_curve caam_curve = CAAM_ECC_UNKNOWN; + + if (tee_curve > 0 && + tee_curve < CAAM_ECC_MAX + TEE_ECC_CURVE_NIST_P192) { + /* + * Realign TEE Curve assuming NIST_P192 is the first entry in + * the list of supported ECC curves. + */ + caam_curve = tee_curve - TEE_ECC_CURVE_NIST_P192 + + CAAM_ECC_P192; + } + + return caam_curve; +} + +/* + * Allocate a ECC keypair + * + * @key Keypair + * @size_bits Key size in bits + */ +static TEE_Result do_allocate_keypair(struct ecc_keypair *key, + uint32_t type __unused, + size_t size_bits) +{ + ECC_TRACE("Allocate Keypair of %zu bits", size_bits); + + /* Initialize the key fields to NULL */ + memset(key, 0, sizeof(*key)); + + /* Allocate Secure Scalar */ + key->d = crypto_bignum_allocate(size_bits); + if (!key->d) + goto err; + + /* Allocate Public coordinate X */ + key->x = crypto_bignum_allocate(size_bits); + if (!key->x) + goto err; + + /* Allocate Public coordinate Y */ + key->y = crypto_bignum_allocate(size_bits); + if (!key->y) + goto err; + + return TEE_SUCCESS; + +err: + ECC_TRACE("Allocation error"); + + crypto_bignum_free(key->d); + crypto_bignum_free(key->x); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +/* + * Allocate an ECC Public Key + * + * @key Public Key + * @size_bits Key size in bits + */ +static TEE_Result do_allocate_publickey(struct ecc_public_key *key, + uint32_t type __unused, + size_t size_bits) +{ + ECC_TRACE("Allocate Public Key of %zu bits", size_bits); + + /* Initialize the key fields to NULL */ + memset(key, 0, sizeof(*key)); + + /* Allocate Public coordinate X */ + key->x = crypto_bignum_allocate(size_bits); + if (!key->x) + goto err; + + /* Allocate Public coordinate Y */ + key->y = crypto_bignum_allocate(size_bits); + if (!key->y) + goto err; + + return TEE_SUCCESS; + +err: + ECC_TRACE("Allocation error"); + + crypto_bignum_free(key->x); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +/* + * Free an ECC public key + * + * @key Public Key + */ +static void do_free_publickey(struct ecc_public_key *key) +{ + crypto_bignum_free(key->x); + crypto_bignum_free(key->y); +} + +/* + * Generate ECC keypair + * + * @key [out] Keypair + * @key_size Key size in bits multiple of 8 bits + */ +static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t key_size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN; + struct caambuf d = { }; + struct caambuf xy = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + + ECC_TRACE("Generate Keypair of %zu bits", key_size); + + /* The key size must be a multiple of 8 bits */ + key_size = ROUNDUP(key_size, 8); + + /* Verify first if the curve is supported */ + curve = get_caam_curve(key->curve); + if (curve == CAAM_ECC_UNKNOWN) + return TEE_ERROR_BAD_PARAMETERS; + + /* Allocate the job used to prepare the operation */ + desc = caam_calloc_desc(MAX_DESC_KEY_GEN); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* + * Allocate secure and public keys in one buffer + * Secure key size = key_size align in bytes + * Public key size = (key_size * 2) align in bytes + */ + retstatus = caam_alloc_align_buf(&d, (key_size / 8) * 3); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* Build the xy buffer to simplify the code */ + xy.data = d.data + key_size / 8; + xy.length = 2 * (key_size / 8); + xy.paddr = d.paddr + key_size / 8; + + /* Build the descriptor using Predifined ECC curve */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_PKGEN_PD1 | PDB_ECC_ECDSEL(curve)); + caam_desc_add_ptr(desc, d.paddr); + caam_desc_add_ptr(desc, xy.paddr); + caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC)); + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + ECC_DUMPDESC(desc); + + jobctx.desc = desc; + cache_operation(TEE_CACHEFLUSH, d.data, d.length); + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + cache_operation(TEE_CACHEINVALIDATE, d.data, d.length); + + /* Copy all keypair parameters */ + ret = crypto_bignum_bin2bn(d.data, key_size / 8, key->d); + if (ret != TEE_SUCCESS) + goto out; + + ret = crypto_bignum_bin2bn(xy.data, xy.length / 2, key->x); + if (ret != TEE_SUCCESS) + goto out; + + ret = crypto_bignum_bin2bn(xy.data + xy.length / 2, + xy.length / 2, key->y); + if (ret != TEE_SUCCESS) + goto out; + + ECC_DUMPBUF("D", d.data, key_size / 8); + ECC_DUMPBUF("X", xy.data, xy.length / 2); + ECC_DUMPBUF("Y", xy.data + xy.length / 2, xy.length / 2); + } else { + ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_free_desc(&desc); + caam_free_buf(&d); + + return ret; +} + +/* + * Signature of ECC message + * Note the message to sign is already hashed + * + * @sdata [in/out] ECC data to sign / Signature + */ +static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN; + struct ecc_keypair *inkey = sdata->key; + struct caam_ecc_keypair ecckey = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + struct caamdmaobj msg = { }; + size_t sign_len = 0; + struct caamdmaobj sign_c = { }; + struct caamdmaobj sign_d = { }; + uint32_t pdb_sgt_flags = 0; + + ECC_TRACE("ECC Signature"); + + /* Verify first if the curve is supported */ + curve = get_caam_curve(inkey->curve); + if (curve == CAAM_ECC_UNKNOWN) + return TEE_ERROR_BAD_PARAMETERS; + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(MAX_DESC_SIGN); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Convert the private key to a local key */ + retstatus = do_keypair_conv(&ecckey, inkey, sdata->size_sec); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, + sdata->message.length); + if (ret) + goto out; + + if (msg.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG; + + caam_dmaobj_cache_push(&msg); + + ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length); + + /* + * ReAllocate the signature result buffer with a maximum size + * of the roundup to 16 bytes of the secure size in bytes if + * the signature buffer is not aligned or too short. + * + * - 1st Part: size_sec + * - 2nd Part: size_sec roundup to 16 bytes + */ + sign_len = ROUNDUP(sdata->size_sec, 16) + sdata->size_sec; + + ret = caam_dmaobj_output_sgtbuf(&sign_c, sdata->signature.data, + sdata->signature.length, sign_len); + if (ret) + goto out; + + if (sign_c.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_C; + + /* Derive sign_d from created sign_c DMA object */ + ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec, + ROUNDUP(sdata->size_sec, 16)); + if (ret) + goto out; + + if (sign_d.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_D; + + caam_dmaobj_cache_push(&sign_c); + + /* Build the descriptor using Predifined ECC curve */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_PKSIGN_PD1 | PDB_ECC_ECDSEL(curve) | + pdb_sgt_flags); + /* Secret key */ + caam_desc_add_ptr(desc, ecckey.d.paddr); + /* Input message */ + caam_desc_add_ptr(desc, msg.sgtbuf.paddr); + /* Signature 1st part */ + caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); + /* Signature 2nd part */ + caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); + /* Message length */ + caam_desc_add_word(desc, sdata->message.length); + + caam_desc_add_word(desc, DSA_SIGN(ECC)); + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + ECC_DUMPDESC(desc); + + jobctx.desc = desc; + + retstatus = caam_jr_enqueue(&jobctx, NULL); + if (retstatus == CAAM_NO_ERROR) { + sign_c.orig.length = 2 * sdata->size_sec; + sdata->signature.length = caam_dmaobj_copy_to_orig(&sign_c); + + ECC_DUMPBUF("Signature", sdata->signature.data, + sdata->signature.length); + + ret = caam_status_to_tee_result(retstatus); + } else { + ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_free_desc(&desc); + do_keypair_free(&ecckey); + caam_dmaobj_free(&msg); + caam_dmaobj_free(&sign_d); + caam_dmaobj_free(&sign_c); + + return ret; +} + +/* + * Verification of the Signature of ECC message + * Note the message is already hashed + * + * @sdata [in/out] ECC Signature to verify + */ +static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN; + struct ecc_public_key *inkey = sdata->key; + struct caam_ecc_keypair ecckey = { }; + struct caambuf tmp = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + struct caamdmaobj msg = { }; + struct caamdmaobj sign_c = { }; + struct caamdmaobj sign_d = { }; + uint32_t pdb_sgt_flags = 0; + + ECC_TRACE("ECC Verify"); + + /* Verify first if the curve is supported */ + curve = get_caam_curve(inkey->curve); + if (curve == CAAM_ECC_UNKNOWN) + return TEE_ERROR_BAD_PARAMETERS; + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(MAX_DESC_VERIFY); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Convert the Public key to local key */ + retstatus = do_keypub_conv(&ecckey, inkey, sdata->size_sec); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* Prepare the input message CAAM Descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, + sdata->message.length); + if (ret) + goto out; + + if (msg.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG; + + caam_dmaobj_cache_push(&msg); + + /* + * Prepare the 1st Part of the signature + * Handle the full signature in case signature buffer needs to + * be reallocated. + */ + ret = caam_dmaobj_input_sgtbuf(&sign_c, sdata->signature.data, + sdata->signature.length); + if (ret) + goto out; + + if (sign_c.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_C; + + /* Prepare the 2nd Part of the signature, derived from sign_c */ + ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec, + sdata->size_sec); + if (ret) + goto out; + + if (sign_d.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_D; + + caam_dmaobj_cache_push(&sign_c); + + /* Allocate a Temporary buffer used by the CAAM */ + retstatus = caam_alloc_align_buf(&tmp, 2 * sdata->size_sec); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* Build the descriptor using Predifined ECC curve */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_PKVERIFY_PD1 | PDB_ECC_ECDSEL(curve) | + pdb_sgt_flags); + /* Public key */ + caam_desc_add_ptr(desc, ecckey.xy.paddr); + /* Input message */ + caam_desc_add_ptr(desc, msg.sgtbuf.paddr); + /* Signature 1st part */ + caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); + /* Signature 2nd part */ + caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); + /* Temporary buffer */ + caam_desc_add_ptr(desc, tmp.paddr); + /* Message length */ + caam_desc_add_word(desc, sdata->message.length); + + caam_desc_add_word(desc, DSA_VERIFY(ECC)); + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + ECC_DUMPDESC(desc); + + jobctx.desc = desc; + + cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length); + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_JOB_STATUS && !jobctx.status) { + ECC_TRACE("ECC Verify Status 0x%08" PRIx32, jobctx.status); + ret = TEE_ERROR_SIGNATURE_INVALID; + } else if (retstatus != CAAM_NO_ERROR) { + ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } else { + ret = caam_status_to_tee_result(retstatus); + } + +out: + caam_free_desc(&desc); + do_keypair_free(&ecckey); + caam_free_buf(&tmp); + caam_dmaobj_free(&msg); + caam_dmaobj_free(&sign_c); + caam_dmaobj_free(&sign_d); + + return ret; +} + +/* + * Compute the shared secret data from ECC Private key and Public Key + * + * @sdata [in/out] ECC Shared Secret data + */ +static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN; + struct ecc_keypair *inprivkey = sdata->key_priv; + struct ecc_public_key *inpubkey = sdata->key_pub; + struct caam_ecc_keypair ecckey = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + struct caamdmaobj secret = { }; + uint32_t pdb_sgt_flags = 0; + + ECC_TRACE("ECC Shared Secret"); + + /* Verify first if the curve is supported */ + curve = get_caam_curve(inpubkey->curve); + if (curve == CAAM_ECC_UNKNOWN) + return TEE_ERROR_BAD_PARAMETERS; + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(MAX_DESC_SHARED); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Convert the Private key to local key */ + retstatus = do_keypair_conv(&ecckey, inprivkey, sdata->size_sec); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* Convert the Public key to local key */ + retstatus = do_keypub_conv(&ecckey, inpubkey, sdata->size_sec); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + /* + * Re-allocate the secret result buffer with a maximum size + * of the secret size if not cache aligned + */ + ret = caam_dmaobj_output_sgtbuf(&secret, sdata->secret.data, + sdata->secret.length, sdata->size_sec); + if (ret) + goto out; + + if (secret.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_PKDH_SECRET; + + caam_dmaobj_cache_push(&secret); + + /* Build the descriptor using Predifined ECC curve */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_SHARED_SECRET_PD1 | PDB_ECC_ECDSEL(curve) | + pdb_sgt_flags); + /* Public key */ + caam_desc_add_ptr(desc, ecckey.xy.paddr); + /* Private key */ + caam_desc_add_ptr(desc, ecckey.d.paddr); + /* Output secret */ + caam_desc_add_ptr(desc, secret.sgtbuf.paddr); + + caam_desc_add_word(desc, SHARED_SECRET(ECC)); + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + ECC_DUMPDESC(desc); + + jobctx.desc = desc; + + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + sdata->secret.length = caam_dmaobj_copy_to_orig(&secret); + + ECC_DUMPBUF("Secret", sdata->secret.data, sdata->secret.length); + + ret = caam_status_to_tee_result(retstatus); + } else { + ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_free_desc(&desc); + do_keypair_free(&ecckey); + caam_dmaobj_free(&secret); + + return ret; +} + +/* + * Registration of the ECC Driver + */ +static struct drvcrypt_ecc driver_ecc = { + .alloc_keypair = do_allocate_keypair, + .alloc_publickey = do_allocate_publickey, + .free_publickey = do_free_publickey, + .gen_keypair = do_gen_keypair, + .sign = do_sign, + .verify = do_verify, + .shared_secret = do_shared_secret, +}; + +enum caam_status caam_ecc_init(struct caam_jrcfg *caam_jrcfg) +{ + enum caam_status retstatus = CAAM_FAILURE; + vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; + + if (caam_hal_ctrl_pknum(jr_base)) + if (drvcrypt_register_ecc(&driver_ecc) == TEE_SUCCESS) + retstatus = CAAM_NO_ERROR; + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/caam_math.c b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_math.c new file mode 100644 index 0000000..1cdddb5 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_math.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * CAAM Mathematical Operation manager. + * Implementation of Mathematical operation using CAAM's MATH function + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * MATH operation A xor B modulus n + * + * @data [in/out] operation data + */ +static TEE_Result do_xor_mod_n(struct drvcrypt_mod_op *data) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + struct caamdmaobj res = { }; + struct caamdmaobj data_a = { }; + struct caamdmaobj data_b = { }; + + RSA_TRACE("(A xor B) mod n"); + + ret = caam_dmaobj_input_sgtbuf(&data_a, data->a.data, data->a.length); + if (ret) + return ret; + + ret = caam_dmaobj_input_sgtbuf(&data_b, data->b.data, data->b.length); + if (ret) + goto out; + + /* + * ReAllocate the result buffer with a maximum size + * of the Key Modulus's size (N) if not cache aligned + */ + ret = caam_dmaobj_output_sgtbuf(&res, data->result.data, + data->result.length, + data->result.length); + if (ret) + goto out; + +#ifdef CFG_CAAM_64BIT +#define XOR_OP_DESC_SIZE 14 +#else +#define XOR_OP_DESC_SIZE 11 +#endif + /* Allocate the job descriptor */ + desc = caam_calloc_desc(XOR_OP_DESC_SIZE); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Load in N Modulus Size */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_N_SIZE, 4)); + caam_desc_add_word(desc, data->n.length); + + /* Load in A f irst value */ + caam_desc_fifo_load(desc, &data_a, CLASS_1, PKHA_A, NOACTION); + caam_desc_fifo_load(desc, &data_b, CLASS_1, PKHA_B, NOACTION); + + /* Operation B = A xor B mod n */ + caam_desc_add_word(desc, PKHA_F2M_OP(MOD_ADD_A_B, B)); + + /* Store the result */ + caam_desc_fifo_store(desc, &res, PKHA_B); + + caam_dmaobj_cache_push(&data_a); + caam_dmaobj_cache_push(&data_b); + caam_dmaobj_cache_push(&res); + + RSA_DUMPDESC(desc); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + caam_dmaobj_copy_to_orig(&res); + RSA_DUMPBUF("Output", data->result.data, data->result.length); + ret = caam_status_to_tee_result(retstatus); + } else { + RSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_free_desc(&desc); + caam_dmaobj_free(&data_a); + caam_dmaobj_free(&data_b); + caam_dmaobj_free(&res); + + return ret; +} + +/* + * Registration of the MATH Driver + */ +static const struct drvcrypt_math driver_math = { + .xor_mod_n = &do_xor_mod_n, +}; + +enum caam_status caam_math_init(struct caam_jrcfg *caam_jrcfg) +{ + enum caam_status retstatus = CAAM_FAILURE; + vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; + + if (caam_hal_ctrl_pknum(jr_base)) + if (!drvcrypt_register_math(&driver_math)) + retstatus = CAAM_NO_ERROR; + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_dsa.c b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_dsa.c new file mode 100644 index 0000000..c02c132 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_dsa.c @@ -0,0 +1,758 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021 NXP + * + * CAAM DSA Prime Numbering. + * Implementation of Prime Number functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +#define PRIME_DESC_ENTRIES 62 + +/* Define the number max of try to generate valid primes */ +#define DSA_MAX_TRIES_PRIME_Q 50000 +#define DSA_MAX_TRIES_PRIME_P 500 + +#define DSA_TRY_FAIL 0x42 +#define DSA_NOT_PRIME 0x43 +#define DSA_PRIME_TOO_SMALL 0x44 + +struct dsa_hash { + unsigned int op; /* CAAM Hash operation code */ + size_t size; /* Hash digest size */ +}; + +/* + * Build the descriptor generating a DSA prime Q + * Referring to FIPS.186-4, Section A.1.1.2 Generation of the + * Probable Primes p and q Using an Approved Hash Function + * + * @desc [out] Descriptor built + * @seed [out] Resulting seed used to generate prime + * @prime [in/out] Prime generation data + * @hash_func Selected Hash function + */ +static void do_desc_prime_q(uint32_t *desc, struct caambuf *seed, + struct prime_data_dsa *prime, + struct dsa_hash *hash_func) +{ + unsigned int desclen = 0; + unsigned int retry_new_mr_failed = 0; + unsigned int retry_mr_test = 0; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + /* Set the PKHA N and A register size */ + caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_N_SIZE, 4)); + caam_desc_add_word(desc, prime->q->length); + caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_A_SIZE, 4)); + caam_desc_add_word(desc, prime->q->length); + + caam_desc_add_word(desc, MATH(ADD, ZERO, IMM_DATA, VSOL, 4)); + caam_desc_add_word(desc, DSA_MAX_TRIES_PRIME_Q); + + caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8)); + + retry_new_mr_failed = caam_desc_get_len(desc); + + /* Decrement the number of try */ + caam_desc_add_word(desc, MATH(SUB, VSOL, ONE, VSOL, 4)); + /* Exceed retry count - exit with DSA_TRY_FAIL error */ + caam_desc_add_word(desc, + HALT_USER(ALL_COND_TRUE, MATH_N, DSA_TRY_FAIL)); + + /* Clear Class 2 SHA */ + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4)); + caam_desc_add_word(desc, CLR_WR_RST_C2_CHA | CLR_WR_RST_C2_DSZ); + + /* + * Step 5. Generate Random Seed + * + * Seed Length shall be equal or greater than N (Q prime length) + * Seed result push in Message Data + */ + if (seed->length > 16) { + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4)); + caam_desc_add_word(desc, NFIFO_PAD(BOTH, 0, MSG, RND, 16)); + + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4)); + caam_desc_add_word(desc, + NFIFO_PAD(BOTH, NFIFO_LC1 | NFIFO_LC2, MSG, + RND, seed->length - 16)); + } else { + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4)); + caam_desc_add_word(desc, NFIFO_PAD(BOTH, NFIFO_LC1 | NFIFO_LC2, + MSG, RND, seed->length)); + } + + caam_desc_add_word(desc, MOVE(C1_ALIGN, OFIFO, 0, seed->length)); + caam_desc_add_word(desc, FIFO_ST(MSG_DATA, seed->length)); + caam_desc_add_ptr(desc, seed->paddr); + + /* + * Hash the Seed, this is a pseudo U, bits upper N - 1 still present + */ + caam_desc_add_word(desc, HASH_INITFINAL(hash_func->op)); + + /* + * Step 6. U = hash(seed) mod 2^(N-1) + * Step 7. q = 2^(N-1) + U + 1 - (U mod 2) + */ + /* Trash the bits > N - 1, the hash size is >= N */ + caam_desc_add_word(desc, + MOVE_WAIT(C2_CTX_REG, MATH_REG0, + hash_func->size - prime->q->length, 8)); + + /* Get the MSB of U and set the bit N-1 */ + caam_desc_add_word(desc, MATH(OR, REG2, REG0, REG0, 8)); + + /* Move the candidate prime q's MSB into IFIFO */ + caam_desc_add_word(desc, MOVE_WAIT(MATH_REG0, IFIFO, 0, 8)); + + /* + * Move the candidate prime q's intermediate value into IFIFO + */ + caam_desc_add_word(desc, + MOVE_WAIT(C2_CTX_REG, IFIFO, + hash_func->size - prime->q->length + 8, + prime->q->length - 16)); + + /* Get the LSB of U and set the bit 0 */ + caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, MATH_REG0, + hash_func->size - 8, 8)); + caam_desc_add_word(desc, MATH(OR, ONE, REG0, REG0, 8)); + + /* Move the candidate prime q's LSB into IFIFO */ + caam_desc_add_word(desc, MOVE_WAIT(MATH_REG0, IFIFO, 0, 8)); + + /* Move the IFIFO in to PKHA N */ + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); + caam_desc_add_word(desc, NFIFO_NOPAD(C1, NFIFO_FC1, IFIFO, PKHA_N, 0)); + caam_desc_add_word(desc, prime->q->length); + + /* Store the Prime q here because Miller-Rabin test affect PKHA N */ + caam_desc_add_word(desc, FIFO_ST(PKHA_N, prime->q->length)); + caam_desc_add_ptr(desc, prime->q->paddr); + + /* + * Step 8. Test q prime with 'miller-rabin' test + * + * Load the number of Miller-Rabin test iteration + */ + caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, SIL, 4)); + if (prime->p->length <= 1024 / 8) + caam_desc_add_word(desc, 40); + else if (prime->p->length >= 3072 / 8) + caam_desc_add_word(desc, 64); + else + caam_desc_add_word(desc, 56); + + retry_mr_test = caam_desc_get_len(desc); + + /* Generate 8 random bytes 'miller-rabin seed' */ + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); + caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0)); + caam_desc_add_word(desc, prime->q->length); + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_word(desc, 0x01); + caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B)); + + desclen = caam_desc_get_len(desc); + + /* + * Step 9. If q is not q prime back to step 5 + */ + caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, + JMP_COND(PKHA_IS_PRIME), + retry_new_mr_failed - desclen)); + caam_desc_add_word(desc, MATH(SUB, SIL, ONE, SIL, 4)); + + desclen = caam_desc_get_len(desc); + /* Test while number of MR test iteration not complete */ + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ALL_COND_FALSE, + JMP_COND(MATH_N) | JMP_COND(MATH_Z), + retry_mr_test - desclen)); + DSA_TRACE("Prime Q descriptor"); + DSA_DUMPDESC(desc); +} + +/* + * Build the descriptor generating the intermediate value X (step 11.3) + * Referring to FIPS.186-4, Section A.1.1.2 Generation of the + * Probable Primes p and q Using an Approved Hash Function + * + * @desc [out] Descriptor built + * @x [out] Value X + * @seed [in/out] Seed to hash and next seed for next loop + * @prime [in/out] Prime generation data + * @hash_func Selected Hash function + * @mod_n Modular value (0xFF filled buffer) + * @desc_p Physical address of the descriptor doing Prime P + */ +static void do_desc_gen_x(uint32_t *desc, struct caambuf *x, + struct caambuf *seed, struct prime_data_dsa *prime, + struct dsa_hash *hash_func, struct caambuf *mod_n, + paddr_t desc_p) +{ + unsigned int desclen = 0; + unsigned int loop_n = 0; + size_t n = 0; + size_t b = 0; + size_t b_offset = 0; + + /* + * Step 3. n = ceil(L / outlen) - 1 + * where outlen is the hash size in bits + * + * Note build descriptor with n = ceil(L / outlen) to + * pre-calculate seed for next run. + */ + n = (prime->p->length + hash_func->size) * 8 - 1; + n /= hash_func->size * 8; + + /* + * Step 4. b = L - 1 - (n * outlen) + * + * Note b determine the number of bits to keep in the last + * Vn computed. + * Calculate b_offset which is the offset in bytes to remove from + * the calculated hash + */ + b = prime->p->length * 8 - 1 - (n - 1) * hash_func->size * 8; + + DSA_TRACE("Prime p => n = %zu | b = %zu", n - 1, b); + b_offset = hash_func->size - (b + 1) / 8; + DSA_TRACE("Vn offset is %zu", b_offset); + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + caam_desc_add_word(desc, SEQ_OUT_PTR(x->length)); + caam_desc_add_ptr(desc, x->paddr); + + caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8)); + + caam_desc_add_word(desc, MATH(ADD, ZERO, IMM_DATA, REG0, 4)); + caam_desc_add_word(desc, n); + + caam_desc_add_word(desc, + FIFO_LD(CLASS_1, PKHA_N, NOACTION, seed->length)); + caam_desc_add_ptr(desc, mod_n->paddr); + + /* + * Because the Sequence Out Pointer is incremental store, we need + * to build w number in reverse. + * + * Hence, calculate the last seed number of the loop and save it. + * Step 11.9 is automatically done here by incrementing seed number. + */ + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_word(desc, n); + caam_desc_add_word(desc, + FIFO_LD(CLASS_1, PKHA_A, NOACTION, seed->length)); + caam_desc_add_ptr(desc, seed->paddr); + caam_desc_add_word(desc, PKHA_OP(MOD_ADD_A_B, A)); + caam_desc_add_word(desc, FIFO_ST(PKHA_A, seed->length)); + caam_desc_add_ptr(desc, seed->paddr); + + caam_desc_add_word(desc, PKHA_CPY_NSIZE(A0, B1)); + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_word(desc, 1); + + caam_desc_add_word(desc, WAIT_COND(ALL_COND_TRUE, NIFP)); + + /* + * Step 11.1 + * For j = 0 to n do + * Vj = hash((seed + offset + j) mod 2^seedlen + * Step 11.2 + * W = V0 + (V1 * 2^outlen) + ... + + * (Vn-1 * 2^((n-1)*outlen)) + + * ((Vn mod 2^b) * 2^(n*outlen)) + */ + loop_n = caam_desc_get_len(desc); + + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4)); + caam_desc_add_word(desc, CLR_WR_IFIFO_NFIFO | CLR_WR_RST_C2_CHA | + CLR_WR_RST_C2_DSZ); + + caam_desc_add_word(desc, HASH_INITFINAL(hash_func->op)); + caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CHA_CTRL, 4)); + caam_desc_add_word(desc, CCTRL_ULOAD_PKHA_A); + + caam_desc_add_word(desc, + MOVE_WAIT(OFIFO, IFIFO_C2_LC2, 0, seed->length)); + + /* If Math Register 2 is zero bypass the high bit set to one */ + caam_desc_add_word(desc, MATH(SUB, REG2, ONE, NODEST, 8)); + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ANY_COND_TRUE, + JMP_COND(MATH_N) | JMP_COND(MATH_Z), + 8)); + /* + * Step 11.3 + * X = W + 2^(L-1) + * + * Set the high bit to one + * Remark: the DSA key is a modulus 8 bytes, hence no need + * to check if the b_offset is less than 8. + */ + caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, MATH_REG1, b_offset, 8)); + caam_desc_add_word(desc, MATH(OR, REG2, REG1, REG1, 8)); + caam_desc_add_word(desc, MOVE(MATH_REG1, OFIFO, 0, 8)); + + if (hash_func->size - b_offset > 8) + caam_desc_add_word(desc, + MOVE_WAIT(C2_CTX_REG, OFIFO, b_offset + 8, + hash_func->size - b_offset - 8)); + caam_desc_add_word(desc, + FIFO_ST_SEQ(MSG_DATA, hash_func->size - b_offset)); + + /* + * Reset MATH Register 2 to bypass the High Bit set + * operation next loop + */ + caam_desc_add_word(desc, MATH(AND, REG2, ZERO, REG2, 8)); + + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(NONE), 2)); + + /* Bypass High Bit set */ + caam_desc_add_word(desc, + ST_NOIMM_SEQ(CLASS_2, REG_CTX, hash_func->size)); + + caam_desc_add_word(desc, PKHA_CPY_NSIZE(B1, A0)); + caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, A)); + caam_desc_add_word(desc, PKHA_CPY_NSIZE(A0, B1)); + + desclen = caam_desc_get_len(desc); + caam_desc_add_word(desc, JUMP_CNO_LOCAL_DEC(ALL_COND_FALSE, MATH_0, + JMP_COND_MATH(N) | + JMP_COND_MATH(Z), + loop_n - desclen)); + /* Jump to the next descriptor desc */ + caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE, + JMP_COND(NONE))); + caam_desc_add_ptr(desc, desc_p); + + DSA_TRACE("X descriptor"); + DSA_DUMPDESC(desc); +} + +/* + * Build the descriptor generating the Prime P from value X + * Referring to FIPS.186-4, Section A.1.1.2 Generation of the + * Probable Primes p and q Using an Approved Hash Function + * + * @desc [out] Descriptor built + * @prime [in/out] Prime generation data + * @x Value X + * @mod_n Modular value (0xFF filled buffer) + */ +static void do_desc_prime_p(uint32_t *desc, struct prime_data_dsa *prime, + struct caambuf *x, struct caambuf *mod_n) +{ + unsigned int desclen = 0; + unsigned int retry_mr_test = 0; + size_t index = 0; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + caam_desc_add_word(desc, + FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length)); + caam_desc_add_ptr(desc, mod_n->paddr); + + /* + * Step 11.4 + * c = X mod 2q + */ + + /* Calculate 2q and store it in PKHA N */ + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, + prime->q->length)); + caam_desc_add_ptr(desc, prime->q->paddr); + caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, B0)); + caam_desc_add_word(desc, PKHA_OP(MOD_ADD_A_B, A)); + + caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, N0)); + + /* c = X mod 2q */ + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, x->length)); + caam_desc_add_ptr(desc, x->paddr); + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(NIFP), 1) | + BIT(24)); + caam_desc_add_word(desc, PKHA_OP(MOD_AMODN, A)); + + /* + * Step 11.5 + * p = X - (c - 1) + */ + caam_desc_add_word(desc, + FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length)); + caam_desc_add_ptr(desc, mod_n->paddr); + + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_ptr(desc, 1); + caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, B)); + + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, x->length)); + caam_desc_add_ptr(desc, x->paddr); + caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, A)); + + /* + * Save the candidate Prime q now because N is going to be + * affected by the Miller-Rabin test + */ + caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, N0)); + caam_desc_add_word(desc, FIFO_ST(PKHA_N, prime->p->length)); + caam_desc_add_ptr(desc, prime->p->paddr); + caam_desc_add_word(desc, FIFO_ST_SEQ(MSG_DATA, 0)); + + /* + * Step 11.6 + * if (p < 2^(L-1)) then go to step 11.9 + * + */ + caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CHA_CTRL, 4)); + caam_desc_add_word(desc, CCTRL_ULOAD_PKHA_A); + + /* Keep the MSB from p candidate and check if bit 2^(L-1) is set */ + caam_desc_add_word(desc, MOVE_WAIT(OFIFO, MATH_REG0, 0, 8)); + for (index = 1; index < prime->p->length / 128; index++) + caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, 128)); + + caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, 124)); + + caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8)); + caam_desc_add_word(desc, MATH(AND, REG0, REG2, REG0, 8)); + + caam_desc_add_word(desc, HALT_USER(ALL_COND_TRUE, MATH_Z, + DSA_PRIME_TOO_SMALL)); + + /* + * Step 11.7 + * Test whether or not p is prime + * + * Referring to FIPS.186-4, Table C.1 + * Get the number Miller-Rabin test interation function + * of the prime number size + */ + caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, REG0, 4)); + if (prime->p->length <= 1024 / 8) + caam_desc_add_word(desc, 40); + else if (prime->p->length >= 3072 / 8) + caam_desc_add_word(desc, 64); + else + caam_desc_add_word(desc, 56); + + retry_mr_test = caam_desc_get_len(desc); + /* Generate 8 random bytes 'miller-rabin seed' */ + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); + caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0)); + caam_desc_add_word(desc, prime->p->length); + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_word(desc, 0x01); + caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B)); + + desclen = caam_desc_get_len(desc); + + /* + * Step 11.8 + * if p is not a prime continue to step 11.9 + */ + caam_desc_add_word(desc, HALT_USER(ALL_COND_FALSE, PKHA_IS_PRIME, + DSA_NOT_PRIME)); + + desclen = caam_desc_get_len(desc); + /* Test while number of MR test iteration not complete */ + caam_desc_add_word(desc, JUMP_CNO_LOCAL_DEC(ALL_COND_FALSE, MATH_0, + JMP_COND_MATH(N) | + JMP_COND_MATH(Z), + retry_mr_test - desclen)); + + DSA_TRACE("Prime P descriptor"); + DSA_DUMPDESC(desc); + + /* + * Ensure descriptor is pushed in physical memory because it's + * called from another descriptor. + */ + cache_operation(TEE_CACHECLEAN, desc, DESC_SZBYTES(PRIME_DESC_ENTRIES)); +} + +/* + * Run the Prime Q descriptor. + * + * @desc Descriptor built + */ +static enum caam_status run_prime_q(uint32_t *desc, + struct prime_data_dsa *prime) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + + cache_operation(TEE_CACHEFLUSH, prime->q->data, prime->q->length); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus != CAAM_NO_ERROR) { + DSA_TRACE("Prime Q Status 0x%08" PRIx32 " ret 0x%08" PRIx32, + jobctx.status, retstatus); + retstatus = CAAM_FAILURE; + } else { + cache_operation(TEE_CACHEINVALIDATE, prime->q->data, + prime->q->length); + DSA_DUMPBUF("Prime Q", prime->q->data, prime->q->length); + } + + return retstatus; +} + +/* + * Run the Prime P descriptors. + * + * @desc Descriptor built + * @prime Prime generation data + */ +static enum caam_status run_prime_p(uint32_t *desc, + struct prime_data_dsa *prime) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + size_t counter = 0; + + cache_operation(TEE_CACHEFLUSH, prime->p->data, prime->p->length); + + jobctx.desc = desc; + for (counter = 0; counter < 4 * prime->p->length * 8; counter++) { + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + DSA_TRACE("Prime P try: counter=%zu", counter); + cache_operation(TEE_CACHEINVALIDATE, prime->p->data, + prime->p->length); + DSA_DUMPBUF("Prime P", prime->p->data, + prime->p->length); + + return retstatus; + } + + if (retstatus == CAAM_JOB_STATUS) { + if (JRSTA_GET_HALT_USER(jobctx.status) != + DSA_NOT_PRIME && + JRSTA_GET_HALT_USER(jobctx.status) != + DSA_PRIME_TOO_SMALL) { + DSA_TRACE("Prime P status 0x%08" PRIx32, + jobctx.status); + return CAAM_FAILURE; + } + } + } + + /* This is not a prime, will try with another prime q */ + return CAAM_BAD_PARAM; +} + +/* + * Generate the DSA parameter G (generator) + * Referring to FIPS.186-4, Section A.2.1 Unverifiable Generation of the + * Generator g + * + * @desc Descriptor buffer to use + * @prime [in/out] Prime generation data + * @mod_n Modular value (0xFF filled buffer) + */ +static enum caam_status do_generator(uint32_t *desc, + struct prime_data_dsa *prime, + struct caambuf *mod_n) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + unsigned int desclen = 0; + unsigned int retry_new_h = 0; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + caam_desc_add_word(desc, + FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length)); + caam_desc_add_ptr(desc, mod_n->paddr); + + /* + * Step 1. + * e = (p - 1)/q + */ + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, + prime->p->length)); + caam_desc_add_ptr(desc, prime->p->paddr); + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_ptr(desc, 1); + /* PKHA B = (p - 1) */ + caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, B)); + + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, + prime->q->length)); + caam_desc_add_ptr(desc, prime->q->paddr); + /* PKHA A = 1/q */ + caam_desc_add_word(desc, PKHA_OP(MOD_INV_A, A)); + + /* PKHA E = (p - 1)/q */ + caam_desc_add_word(desc, PKHA_OP(MOD_MUL_A_B, A)); + caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, E)); + + /* Load N with prime p */ + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_N, NOACTION, + prime->p->length)); + caam_desc_add_ptr(desc, prime->p->paddr); + + /* + * Step 2. Generate a Random h + * where 1 < h < (p - 1) + * + * To ensure h < (p - 1), generate a random of p length - 2 + */ + retry_new_h = caam_desc_get_len(desc); + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); + caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0)); + caam_desc_add_word(desc, prime->p->length - 2); + + /* + * Step 3. + * g = h^e mod p + */ + caam_desc_add_word(desc, PKHA_OP(MOD_EXP_A_E, A)); + + /* + * Step 4. + * if (g = 1) then go to step 2 + */ + desclen = caam_desc_get_len(desc); + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(PKHA_GCD_1), + retry_new_h - desclen)); + + /* g is good save it */ + caam_desc_add_word(desc, FIFO_ST(PKHA_A, prime->g->length)); + caam_desc_add_ptr(desc, prime->g->paddr); + + DSA_DUMPDESC(desc); + + cache_operation(TEE_CACHEFLUSH, prime->g->data, prime->g->length); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus != CAAM_NO_ERROR) { + DSA_TRACE("Generator G Status 0x%08" PRIx32 " ret 0x%08" PRIx32, + jobctx.status, retstatus); + return CAAM_FAILURE; + } + + cache_operation(TEE_CACHEINVALIDATE, prime->g->data, prime->g->length); + DSA_DUMPBUF("Generator G", prime->g->data, prime->g->length); + + return CAAM_NO_ERROR; +} + +enum caam_status caam_prime_dsa_gen(struct prime_data_dsa *data) +{ + enum caam_status retstatus = CAAM_FAILURE; + uint32_t *desc_all = NULL; + uint32_t *desc_q = NULL; + uint32_t *desc_x = NULL; + uint32_t *desc_p = NULL; + struct caambuf seed = { }; + struct caambuf mod_n = { }; + struct dsa_hash hash_func = { OP_ALGO(SHA256), TEE_SHA256_HASH_SIZE }; + size_t nb_tries = 0; + struct caambuf x = { }; + + /* + * For the now as the DSA Prime p size is limited to 3072, Prime q + * is also limited to 256. Hence the hash function to use is + * SHA-256. + * Ensure here that limit is not crossed because on some i.MX device + * hash is limited to 256. + */ + if (data->q->length > 256) + return CAAM_BAD_PARAM; + + retstatus = caam_calloc_buf(&mod_n, data->p->length); + if (retstatus != CAAM_NO_ERROR) + goto out; + + memset(mod_n.data, 0xFF, mod_n.length); + cache_operation(TEE_CACHECLEAN, mod_n.data, mod_n.length); + + retstatus = caam_calloc_align_buf(&seed, data->q->length); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + retstatus = caam_calloc_buf(&x, data->p->length); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + desc_all = caam_calloc_desc(PRIME_DESC_ENTRIES * 3); + if (!desc_all) { + retstatus = CAAM_OUT_MEMORY; + goto out; + } + + DSA_TRACE("Do primes P %zu bytes, Q %zu bytes", data->p->length, + data->q->length); + + desc_q = desc_all; + desc_x = desc_q + PRIME_DESC_ENTRIES; + desc_p = desc_x + PRIME_DESC_ENTRIES; + + do_desc_prime_q(desc_q, &seed, data, &hash_func); + do_desc_gen_x(desc_x, &x, &seed, data, &hash_func, &mod_n, + virt_to_phys(desc_p)); + do_desc_prime_p(desc_p, data, &x, &mod_n); + + cache_operation(TEE_CACHEFLUSH, data->p->data, data->p->length); + cache_operation(TEE_CACHEFLUSH, seed.data, seed.length); + cache_operation(TEE_CACHEFLUSH, x.data, x.length); + + for (nb_tries = DSA_MAX_TRIES_PRIME_P; nb_tries > 0; nb_tries--) { + retstatus = run_prime_q(desc_q, data); + + if (retstatus == CAAM_NO_ERROR) { + retstatus = run_prime_p(desc_x, data); + if (retstatus == CAAM_NO_ERROR) + break; + } + + if (retstatus == CAAM_FAILURE) { + DSA_TRACE("DSA Prime P/Q Generation failed"); + break; + } + } + + if (retstatus == CAAM_NO_ERROR) + retstatus = do_generator(desc_all, data, &mod_n); + +out: + caam_free_desc(&desc_all); + caam_free_buf(&seed); + caam_free_buf(&x); + caam_free_buf(&mod_n); + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c new file mode 100644 index 0000000..d3b16ed --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_prime_rsa.c @@ -0,0 +1,863 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * CAAM Prime Numbering. + * Implementation of Prime Number functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +#define RSA_TRY_FAIL 0x42 +#define RETRY_TOO_SMALL 0x2A + +#define STATUS_GOOD_Q 0xCA + +#define MR_PRIME_SIZE 1536 +#define MAX_RETRY_PRIME_GEN 1000 +#define RSA_MAX_TRIES_PRIMES 100 + +#ifdef CFG_CAAM_64BIT +#define SETUP_RSA_DESC_ENTRIES 20 +#define GEN_RSA_DESC_ENTRIES 62 +#define CHECK_P_Q_DESC_ENTRIES 32 +#else +#define SETUP_RSA_DESC_ENTRIES 17 +#define GEN_RSA_DESC_ENTRIES 58 +#define CHECK_P_Q_DESC_ENTRIES 29 +#endif + +/* + * Predefined const value corresponding to the + * operation sqrt(2) * (2 ^ ((nlen / 2) - 1)) + * Used at step 4.4 + */ +static const uint8_t sqrt_value[] = { + 0xb5, 0x04, 0xf3, 0x33, 0xf9, 0xde, 0x64, 0x84, 0x59, 0x7d, 0x89, 0xb3, + 0x75, 0x4a, 0xbe, 0x9f, 0x1d, 0x6f, 0x60, 0xba, 0x89, 0x3b, 0xa8, 0x4c, + 0xed, 0x17, 0xac, 0x85, 0x83, 0x33, 0x99, 0x15, 0x4a, 0xfc, 0x83, 0x04, + 0x3a, 0xb8, 0xa2, 0xc3, 0xa8, 0xb1, 0xfe, 0x6f, 0xdc, 0x83, 0xdb, 0x39, + 0x0f, 0x74, 0xa8, 0x5e, 0x43, 0x9c, 0x7b, 0x4a, 0x78, 0x04, 0x87, 0x36, + 0x3d, 0xfa, 0x27, 0x68, 0xd2, 0x20, 0x2e, 0x87, 0x42, 0xaf, 0x1f, 0x4e, + 0x53, 0x05, 0x9c, 0x60, 0x11, 0xbc, 0x33, 0x7b, 0xca, 0xb1, 0xbc, 0x91, + 0x16, 0x88, 0x45, 0x8a, 0x46, 0x0a, 0xbc, 0x72, 0x2f, 0x7c, 0x4e, 0x33, + 0xc6, 0xd5, 0xa8, 0xa3, 0x8b, 0xb7, 0xe9, 0xdc, 0xcb, 0x2a, 0x63, 0x43, + 0x31, 0xf3, 0xc8, 0x4d, 0xf5, 0x2f, 0x12, 0x0f, 0x83, 0x6e, 0x58, 0x2e, + 0xea, 0xa4, 0xa0, 0x89, 0x90, 0x40, 0xca, 0x4a, 0x81, 0x39, 0x4a, 0xb6, + 0xd8, 0xfd, 0x0e, 0xfd, 0xf4, 0xd3, 0xa0, 0x2c, 0xeb, 0xc9, 0x3e, 0x0c, + 0x42, 0x64, 0xda, 0xbc, 0xd5, 0x28, 0xb6, 0x51, 0xb8, 0xcf, 0x34, 0x1b, + 0x6f, 0x82, 0x36, 0xc7, 0x01, 0x04, 0xdc, 0x01, 0xfe, 0x32, 0x35, 0x2f, + 0x33, 0x2a, 0x5e, 0x9f, 0x7b, 0xda, 0x1e, 0xbf, 0xf6, 0xa1, 0xbe, 0x3f, + 0xca, 0x22, 0x13, 0x07, 0xde, 0xa0, 0x62, 0x41, 0xf7, 0xaa, 0x81, 0xc2, + 0xc1, 0xfc, 0xbd, 0xde, 0xa2, 0xf7, 0xdc, 0x33, 0x18, 0x83, 0x8a, 0x2e, + 0xaf, 0xf5, 0xf3, 0xb2, 0xd2, 0x4f, 0x4a, 0x76, 0x3f, 0xac, 0xb8, 0x82, + 0xfd, 0xfe, 0x17, 0x0f, 0xd3, 0xb1, 0xf7, 0x80, 0xf9, 0xac, 0xce, 0x41, + 0x79, 0x7f, 0x28, 0x05, 0xc2, 0x46, 0x78, 0x5e, 0x92, 0x95, 0x70, 0x23, + 0x5f, 0xcf, 0x8f, 0x7b, 0xca, 0x3e, 0xa3, 0x3b, 0x4d, 0x7c, 0x60, 0xa5, + 0xe6, 0x33, 0xe3, 0xe1 +}; + +/* + * Speedups for prime searching + * + * These values are products of small primes. Information about the product + * preceeds it. These values have been pre-computed by the CAAM design team. + * + * Per Handbook of Applied Cryptography, Menezes et al, 4.4.1, one can compute + * the percentage of non-primes weeded out by checking for small prime factors + * in the candidates. In the table below, "highest prime" is used for B, and + * "%weeded" is the number of candidates which get through this + * sieve. As you can see, even with relatively few primes, there are + * diminishing returns to using larger numbers of primes. + * + * Percentage weeded: 1 - 1.12/ln B + * + * These can be used to compute GCD(prime, smallprime) before the Miller + * Rabin; this will weed out those candidates with 'small' primes before doing + * the costly modular exponentation inside of Miller-Rabin. (If the result is + * not one, then the candidate has as a factor at least one of the small primes + * in the product). + * + * So, where is the sweet spot for the size of the product versus the size of + * the candidate? Does it depend upon the size of the PKHA multiplier? Hunt + * time for primes takes a long time to actually compute, and what are the + * stats for percentage of candidates that might be weeded out? If not many, + * then there is an extra computation. + */ +struct smallprime { + const size_t length; + const uint8_t *data; +}; + +/* sizes | #primes | highest prime | %weeded */ +/* bits / bytes | | */ +/* 64 / 8 | 15 | 53 | 72 */ +static const uint8_t smallprime_8[] = { + 0xe2, 0x21, 0xf9, 0x7c, 0x30, 0xe9, 0x4e, 0x1d, +}; + +/* 128 / 16 | 25 | 101 | 76 */ +static const uint8_t smallprime_16[] = { + 0x57, 0x97, 0xd4, 0x7c, 0x51, 0x68, 0x15, 0x49, 0xd7, 0x34, 0xe4, 0xfc, + 0x4c, 0x3e, 0xaf, 0x7f, +}; + +/* 256 / 32 | 43 | 193 | 79 */ +static const uint8_t smallprime_32[] = { + 0xdb, 0xf0, 0x5b, 0x6f, 0x56, 0x54, 0xb3, 0xc0, 0xf5, 0x24, 0x35, 0x51, + 0x43, 0x95, 0x86, 0x88, 0x9f, 0x15, 0x58, 0x87, 0x81, 0x9a, 0xed, 0x2a, + 0xc0, 0x5b, 0x93, 0x35, 0x2b, 0xe9, 0x86, 0x77, +}; + +/* 384 / 48 | 59 | 281 | 80 */ +static const uint8_t smallprime_48[] = { + 0x50, 0x12, 0x01, 0xcc, 0x51, 0xa4, 0x92, 0xa5, 0x44, 0xd3, 0x90, 0x0a, + 0xd4, 0xf8, 0xb3, 0x2a, 0x20, 0x3c, 0x85, 0x84, 0x06, 0xa4, 0x45, 0x7c, + 0xab, 0x0b, 0x4f, 0x80, 0x5a, 0xb1, 0x8a, 0xc6, 0xeb, 0x95, 0x72, 0xac, + 0x6e, 0x93, 0x94, 0xfa, 0x52, 0x2b, 0xff, 0xb6, 0xf4, 0x4a, 0xf2, 0xf3, +}; + +/* 512 / 64 | 74 | 379 | 81 */ +static const uint8_t smallprime_64[] = { + 0x10, 0x6a, 0xa9, 0xfb, 0x76, 0x46, 0xfa, 0x6e, 0xb0, 0x81, 0x3c, 0x28, + 0xc5, 0xd5, 0xf0, 0x9f, 0x07, 0x7e, 0xc3, 0xba, 0x23, 0x8b, 0xfb, 0x99, + 0xc1, 0xb6, 0x31, 0xa2, 0x03, 0xe8, 0x11, 0x87, 0x23, 0x3d, 0xb1, 0x17, + 0xcb, 0xc3, 0x84, 0x05, 0x6e, 0xf0, 0x46, 0x59, 0xa4, 0xa1, 0x1d, 0xe4, + 0x9f, 0x7e, 0xcb, 0x29, 0xba, 0xda, 0x8f, 0x98, 0x0d, 0xec, 0xec, 0xe9, + 0x2e, 0x30, 0xc4, 0x8f, +}; + +/* 576 / 72 | 81 | 421 | 82 */ +static const uint8_t smallprime_72[] = { + 0x01, 0x85, 0xdb, 0xeb, 0x2b, 0x8b, 0x11, 0xd3, 0x76, 0x33, 0xe9, 0xdc, + 0x1e, 0xec, 0x54, 0x15, 0x65, 0xc6, 0xce, 0x84, 0x31, 0xd2, 0x27, 0xee, + 0x28, 0xf0, 0x32, 0x8a, 0x60, 0xc9, 0x01, 0x18, 0xae, 0x03, 0x1c, 0xc5, + 0xa7, 0x81, 0xc8, 0x24, 0xd1, 0xf1, 0x6d, 0x25, 0xf4, 0xf0, 0xcc, 0xcf, + 0xf3, 0x5e, 0x97, 0x45, 0x79, 0x07, 0x2e, 0xc8, 0xca, 0xf1, 0xac, 0x8e, + 0xef, 0xd5, 0x56, 0x6f, 0xa1, 0x5f, 0xb9, 0x4f, 0xe3, 0x4f, 0x5d, 0x37, +}; + +/* 768 / 96 | 103 | 569 | 82 */ +static const uint8_t smallprime_96[] = { + 0x25, 0xea, 0xc8, 0x9f, 0x8d, 0x4d, 0xa3, 0x38, 0x33, 0x7b, 0x49, 0x85, + 0x0d, 0x2d, 0x14, 0x89, 0x26, 0x63, 0x17, 0x7b, 0x40, 0x10, 0xaf, 0x3d, + 0xd2, 0x3e, 0xeb, 0x0b, 0x22, 0x8f, 0x38, 0x32, 0xff, 0xce, 0xe2, 0xe5, + 0xcb, 0xd1, 0xac, 0xc9, 0x8f, 0x47, 0xf2, 0x51, 0x87, 0x33, 0x80, 0xae, + 0x10, 0xf0, 0xff, 0xdd, 0x8e, 0x60, 0x2f, 0xfa, 0x21, 0x0f, 0x41, 0xf6, + 0x69, 0xa1, 0x57, 0x0a, 0x93, 0xc1, 0x58, 0xc1, 0xa9, 0xa8, 0x22, 0x7f, + 0xf8, 0x1a, 0x90, 0xc5, 0x63, 0x0e, 0x9c, 0x44, 0x84, 0x5c, 0x75, 0x5c, + 0x7d, 0xf3, 0x5a, 0x7d, 0x43, 0x0c, 0x67, 0x9a, 0x11, 0x57, 0x56, 0x55, +}; + +/* 1024 / 128 | 130 | 739 | 83 */ +static const uint8_t smallprime_128[] = { + 0x02, 0xc8, 0x5f, 0xf8, 0x70, 0xf2, 0x4b, 0xe8, 0x0f, 0x62, 0xb1, 0xba, + 0x6c, 0x20, 0xbd, 0x72, 0xb8, 0x37, 0xef, 0xdf, 0x12, 0x12, 0x06, 0xd8, + 0x7d, 0xb5, 0x6b, 0x7d, 0x69, 0xfa, 0x4c, 0x02, 0x1c, 0x10, 0x7c, 0x3c, + 0xa2, 0x06, 0xfe, 0x8f, 0xa7, 0x08, 0x0e, 0xf5, 0x76, 0xef, 0xfc, 0x82, + 0xf9, 0xb1, 0x0f, 0x57, 0x50, 0x65, 0x6b, 0x77, 0x94, 0xb1, 0x6a, 0xfd, + 0x70, 0x99, 0x6e, 0x91, 0xae, 0xf6, 0xe0, 0xad, 0x15, 0xe9, 0x1b, 0x07, + 0x1a, 0xc9, 0xb2, 0x4d, 0x98, 0xb2, 0x33, 0xad, 0x86, 0xee, 0x05, 0x55, + 0x18, 0xe5, 0x8e, 0x56, 0x63, 0x8e, 0xf1, 0x8b, 0xac, 0x5c, 0x74, 0xcb, + 0x35, 0xbb, 0xb6, 0xe5, 0xda, 0xe2, 0x78, 0x3d, 0xd1, 0xc0, 0xce, 0x7d, + 0xec, 0x4f, 0xc7, 0x0e, 0x51, 0x86, 0xd4, 0x11, 0xdf, 0x36, 0x36, 0x8f, + 0x06, 0x1a, 0xa3, 0x60, 0x11, 0xf3, 0x01, 0x79, +}; + +/* 1088 / 184 | 136 | 787 | 83 */ +static const uint8_t smallprime_184[] = { + 0x16, 0xaf, 0x5c, 0x18, 0xa2, 0xbe, 0xf8, 0xef, 0xf2, 0x27, 0x83, 0x32, + 0x18, 0x2d, 0x0f, 0xbf, 0x00, 0x38, 0xcc, 0x20, 0x51, 0x48, 0xb8, 0x3d, + 0x06, 0xe3, 0xd7, 0xd9, 0x32, 0x82, 0x8b, 0x18, 0xe1, 0x1e, 0x09, 0x40, + 0x28, 0xc7, 0xea, 0xed, 0xa3, 0x39, 0x50, 0x17, 0xe0, 0x7d, 0x8a, 0xe9, + 0xb5, 0x94, 0x06, 0x04, 0x51, 0xd0, 0x5f, 0x93, 0x08, 0x4c, 0xb4, 0x81, + 0x66, 0x3c, 0x94, 0xc6, 0xff, 0x98, 0x0d, 0xde, 0xcc, 0xdb, 0x42, 0xad, + 0x37, 0x09, 0x7f, 0x41, 0xa7, 0x83, 0x7f, 0xc9, 0x5a, 0xfe, 0x3f, 0x18, + 0xad, 0x76, 0xf2, 0x34, 0x83, 0xae, 0x94, 0x2e, 0x0f, 0x0c, 0x0b, 0xc6, + 0xe4, 0x00, 0x16, 0x12, 0x31, 0x89, 0x87, 0x2b, 0xe5, 0x8f, 0x6d, 0xfc, + 0x23, 0x9c, 0xa2, 0x8f, 0xb0, 0xcf, 0xbf, 0x96, 0x4c, 0x8f, 0x27, 0xce, + 0x05, 0xd6, 0xc7, 0x7a, 0x01, 0xf9, 0xd3, 0x32, 0x36, 0xc9, 0xd4, 0x42, + 0xad, 0x69, 0xed, 0x33, +}; + +/* 1536 / 192 | 182 | 1093 | 84 */ +static const uint8_t smallprime_192[] = { + 0x02, 0x1b, 0xf9, 0x49, 0x70, 0x91, 0xb8, 0xc3, 0x68, 0xcc, 0x7c, 0x8e, + 0x00, 0xc1, 0x99, 0x0c, 0x60, 0x27, 0x48, 0x1b, 0x79, 0x21, 0x5a, 0xc8, + 0xa7, 0x51, 0x77, 0x49, 0xa2, 0x15, 0x13, 0x77, 0x9a, 0x99, 0x3d, 0x29, + 0x58, 0xfc, 0xb4, 0x9a, 0x73, 0x68, 0x02, 0x92, 0x68, 0x52, 0x79, 0x94, + 0xc6, 0xcc, 0x19, 0x28, 0xad, 0xd4, 0x12, 0x95, 0x96, 0x76, 0x5f, 0x4c, + 0xc3, 0x14, 0x1a, 0x04, 0x4e, 0xb1, 0xd6, 0x15, 0x78, 0x88, 0x16, 0x67, + 0x57, 0xd8, 0x61, 0x87, 0x81, 0x81, 0x30, 0x62, 0x03, 0x22, 0x67, 0x98, + 0x7d, 0xf0, 0xd4, 0x71, 0x9c, 0xd3, 0x8f, 0x1b, 0x70, 0x85, 0xfc, 0xa5, + 0x33, 0x4b, 0xe3, 0xa6, 0x00, 0x3a, 0x3c, 0xe7, 0xe1, 0x9a, 0xba, 0x55, + 0x3e, 0x80, 0xcc, 0x5a, 0xe4, 0x06, 0x0e, 0xff, 0x6e, 0x18, 0x06, 0x66, + 0x1d, 0xa5, 0xee, 0xb7, 0xd1, 0x42, 0xd3, 0xb2, 0xe4, 0x07, 0x39, 0xf1, + 0x44, 0x3d, 0xee, 0x3a, 0x19, 0x86, 0x37, 0xf0, 0x3c, 0x06, 0x28, 0x45, + 0xea, 0xff, 0x3f, 0xf2, 0x7e, 0xa3, 0x8d, 0x93, 0x44, 0xd8, 0xa9, 0x02, + 0x22, 0x47, 0x2d, 0xf0, 0x7d, 0xfb, 0x5c, 0x9c, 0x8a, 0xda, 0x77, 0xcd, + 0x0d, 0x5b, 0x94, 0xef, 0xf0, 0x21, 0xe0, 0x2e, 0x30, 0x7d, 0x08, 0x01, + 0x03, 0x12, 0xd5, 0x7c, 0xb5, 0xd9, 0x75, 0x76, 0x46, 0x97, 0x84, 0x2d, +}; + +/* 2048 / 256 | 232 | 1471 | 85 */ +static const uint8_t smallprime_256[] = { + 0x24, 0x65, 0xa7, 0xbd, 0x85, 0x01, 0x1e, 0x1c, 0x9e, 0x05, 0x27, 0x92, + 0x9f, 0xff, 0x26, 0x8c, 0x82, 0xef, 0x7e, 0xfa, 0x41, 0x68, 0x63, 0xba, + 0xa5, 0xac, 0xdb, 0x09, 0x71, 0xdb, 0xa0, 0xcc, 0xac, 0x3e, 0xe4, 0x99, + 0x93, 0x45, 0x02, 0x9f, 0x2c, 0xf8, 0x10, 0xb9, 0x9e, 0x40, 0x6a, 0xac, + 0x5f, 0xce, 0x5d, 0xd6, 0x9d, 0x1c, 0x71, 0x7d, 0xae, 0xa5, 0xd1, 0x8a, + 0xb9, 0x13, 0xf4, 0x56, 0x50, 0x56, 0x79, 0xbc, 0x91, 0xc5, 0x7d, 0x46, + 0xd9, 0x88, 0x88, 0x57, 0x86, 0x2b, 0x36, 0xe2, 0xed, 0xe2, 0xe4, 0x73, + 0xc1, 0xf0, 0xab, 0x35, 0x9d, 0xa2, 0x52, 0x71, 0xaf, 0xfe, 0x15, 0xff, + 0x24, 0x0e, 0x29, 0x9d, 0x0b, 0x04, 0xf4, 0xcd, 0x0e, 0x4d, 0x7c, 0x0e, + 0x47, 0xb1, 0xa7, 0xba, 0x00, 0x7d, 0xe8, 0x9a, 0xae, 0x84, 0x8f, 0xd5, + 0xbd, 0xcd, 0x7f, 0x98, 0x15, 0x56, 0x4e, 0xb0, 0x60, 0xae, 0x14, 0xf1, + 0x9c, 0xb5, 0x0c, 0x29, 0x1f, 0x0b, 0xbd, 0x8e, 0xd1, 0xc4, 0xc7, 0xf8, + 0xfc, 0x5f, 0xba, 0x51, 0x66, 0x20, 0x01, 0x93, 0x9b, 0x53, 0x2d, 0x92, + 0xda, 0xc8, 0x44, 0xa8, 0x43, 0x1d, 0x40, 0x0c, 0x83, 0x2d, 0x03, 0x9f, + 0x5f, 0x90, 0x0b, 0x27, 0x8a, 0x75, 0x21, 0x9c, 0x29, 0x86, 0x14, 0x0c, + 0x79, 0x04, 0x5d, 0x77, 0x59, 0x54, 0x08, 0x54, 0xc3, 0x15, 0x04, 0xdc, + 0x56, 0xf1, 0xdf, 0x5e, 0xeb, 0xe7, 0xbe, 0xe4, 0x47, 0x65, 0x8b, 0x91, + 0x7b, 0xf6, 0x96, 0xd6, 0x92, 0x7f, 0x2e, 0x24, 0x28, 0xfb, 0xeb, 0x34, + 0x0e, 0x51, 0x5c, 0xb9, 0x83, 0x5d, 0x63, 0x87, 0x1b, 0xe8, 0xbb, 0xe0, + 0x9c, 0xf1, 0x34, 0x45, 0x79, 0x9f, 0x2e, 0x67, 0x78, 0x81, 0x51, 0x57, + 0x1a, 0x93, 0xb4, 0xc1, 0xee, 0xe5, 0x5d, 0x1b, 0x90, 0x72, 0xe0, 0xb2, + 0xf5, 0xc4, 0x60, 0x7f, +}; + +/* 3072 / 384 | 326 | 2179 | 85 */ +static const uint8_t smallprime_384[] = { + 0x00, 0x4d, 0xc2, 0x0e, 0x27, 0x31, 0x51, 0x23, 0xfd, 0xab, 0xcd, 0x18, + 0xca, 0x81, 0x2e, 0xe0, 0xee, 0x44, 0x49, 0x23, 0x87, 0x38, 0x9e, 0xd6, + 0xc9, 0x16, 0x97, 0x95, 0x89, 0x65, 0xed, 0xc5, 0x3d, 0x89, 0x13, 0xa8, + 0xe6, 0xec, 0x7f, 0x83, 0x6a, 0x8b, 0xd6, 0x03, 0x7e, 0x57, 0xed, 0x0c, + 0x69, 0x30, 0xef, 0x26, 0x49, 0x0d, 0xc3, 0x5d, 0x05, 0xd0, 0x98, 0xa4, + 0x66, 0xad, 0xf8, 0x17, 0x9f, 0x82, 0x99, 0x69, 0xd1, 0x39, 0x55, 0x8f, + 0x16, 0xe9, 0x8b, 0x3f, 0x76, 0xfc, 0x90, 0x62, 0xc1, 0x57, 0x25, 0xce, + 0x09, 0x88, 0xfa, 0xed, 0xca, 0x96, 0x6a, 0x6b, 0x92, 0x5f, 0x9b, 0x9c, + 0x67, 0x03, 0x43, 0xea, 0x7e, 0x84, 0x20, 0x65, 0xbd, 0x26, 0xf2, 0xbf, + 0x29, 0x90, 0x4f, 0xa7, 0xf4, 0x9f, 0x33, 0x49, 0x28, 0x96, 0x33, 0x73, + 0xba, 0x08, 0x95, 0x96, 0x51, 0x3d, 0xac, 0xa7, 0x39, 0x28, 0xcf, 0x30, + 0x5a, 0xdf, 0x8c, 0x24, 0x6e, 0x1d, 0x99, 0xa2, 0x42, 0xd9, 0x23, 0x56, + 0x23, 0xc4, 0x9a, 0xf2, 0x91, 0x45, 0x06, 0xc9, 0x11, 0x21, 0x5e, 0x1e, + 0x49, 0xaf, 0x84, 0x80, 0x3e, 0xd9, 0xa2, 0xca, 0x05, 0x51, 0x72, 0x1f, + 0xe6, 0x31, 0x9b, 0xf2, 0x38, 0xc0, 0x8a, 0xae, 0x6f, 0xd5, 0x01, 0x54, + 0x03, 0xd9, 0xe5, 0x55, 0x09, 0xee, 0x31, 0xc9, 0x60, 0x12, 0xf9, 0x08, + 0x35, 0x18, 0x5f, 0x31, 0xcb, 0xd2, 0xe4, 0x89, 0x83, 0x3c, 0x1d, 0x54, + 0x62, 0xfa, 0x80, 0x53, 0x59, 0x04, 0x86, 0x7b, 0x2c, 0x94, 0x5e, 0x9a, + 0x0c, 0x2f, 0x7a, 0xa3, 0x6e, 0x0a, 0xc0, 0xeb, 0x9b, 0xb4, 0xc1, 0x1b, + 0xf5, 0x80, 0xcf, 0x0d, 0x6d, 0x2a, 0x49, 0xed, 0x1a, 0x2d, 0x74, 0xca, + 0xe0, 0xf4, 0xc3, 0xad, 0xff, 0x61, 0xd6, 0x48, 0xca, 0x6a, 0x12, 0x08, + 0x58, 0xf4, 0xab, 0xb3, 0xb3, 0x12, 0x07, 0xcf, 0x9b, 0x7c, 0x2f, 0xda, + 0x74, 0xf7, 0x72, 0x2b, 0x14, 0x99, 0x17, 0x87, 0x5a, 0xac, 0x9d, 0x61, + 0x53, 0xc9, 0x71, 0x13, 0xfc, 0xd3, 0x74, 0xaf, 0x93, 0xdd, 0x3f, 0xa2, + 0x1a, 0x7d, 0xe5, 0x1f, 0x1a, 0x70, 0xc6, 0x31, 0xba, 0x6c, 0x92, 0x26, + 0x1e, 0x89, 0x54, 0x1a, 0xa4, 0x71, 0x41, 0xf4, 0x4e, 0x07, 0x5a, 0x1c, + 0x52, 0x2a, 0xe5, 0x81, 0x60, 0xda, 0xc8, 0x70, 0xdf, 0xbd, 0x86, 0x06, + 0xe4, 0xec, 0xa0, 0x89, 0x2a, 0xe5, 0x1c, 0x87, 0x34, 0xf5, 0xb7, 0x71, + 0x2b, 0xcd, 0x3d, 0xe3, 0x32, 0x5e, 0xc2, 0x5f, 0x07, 0xd4, 0xef, 0x94, + 0x33, 0x94, 0xd5, 0xe7, 0xb3, 0x84, 0x10, 0x05, 0xa3, 0xbd, 0x1a, 0x3e, + 0x4d, 0x27, 0x06, 0x1d, 0x54, 0xd2, 0x44, 0x58, 0x24, 0xf8, 0x51, 0x17, + 0xd0, 0xf6, 0x97, 0x12, 0x84, 0xa8, 0xc9, 0x7a, 0x42, 0x50, 0xb9, 0x9b, +}; + +/* 4096 / 512 | 417 | 2887 | 86 */ +static const uint8_t smallprime_512[] = { + 0x09, 0x62, 0x07, 0xfc, 0xcb, 0x19, 0xd6, 0x75, 0x8e, 0x37, 0x4b, 0xee, + 0x6c, 0x37, 0x09, 0xaf, 0x0a, 0x54, 0xa9, 0x82, 0xbf, 0x90, 0x14, 0xe4, + 0x50, 0xb7, 0x48, 0x18, 0x13, 0xb7, 0x30, 0x5b, 0x4c, 0x25, 0xf0, 0xe2, + 0xea, 0x6e, 0x2b, 0x56, 0xf9, 0x1e, 0x59, 0x92, 0x14, 0x2d, 0x21, 0x6e, + 0xae, 0xb2, 0xec, 0xe0, 0x05, 0xfa, 0x0d, 0x18, 0xef, 0xeb, 0x78, 0xef, + 0xc3, 0x41, 0xf3, 0x1f, 0x78, 0x3e, 0xe4, 0x4a, 0xc5, 0xef, 0x5d, 0xfe, + 0x35, 0x57, 0x91, 0x28, 0x21, 0x06, 0x15, 0x6c, 0x64, 0xd1, 0x67, 0xa5, + 0x42, 0x1c, 0xfe, 0xc3, 0x3c, 0xbb, 0xd3, 0x88, 0x38, 0x0b, 0xe8, 0x54, + 0x14, 0x9f, 0xb6, 0x5c, 0x08, 0xe7, 0x9c, 0xd0, 0x4e, 0xc4, 0x8b, 0x45, + 0x62, 0x8e, 0xe6, 0x7f, 0x5c, 0x6f, 0xb0, 0x18, 0x18, 0xfa, 0x1f, 0xf7, + 0x32, 0x24, 0x0c, 0x0b, 0xb1, 0xc7, 0xfe, 0xc1, 0x4c, 0x48, 0x23, 0x4c, + 0x6f, 0xc3, 0xe0, 0x75, 0x76, 0x4f, 0x63, 0xc0, 0x26, 0x83, 0x61, 0x83, + 0x1d, 0x89, 0x60, 0xf2, 0x4b, 0x23, 0x7e, 0x96, 0xc2, 0xca, 0xba, 0x4c, + 0x1a, 0x21, 0x23, 0xff, 0x33, 0xa4, 0x9b, 0xca, 0x39, 0x49, 0xe8, 0xab, + 0xad, 0xde, 0x06, 0xda, 0xc5, 0x70, 0x3d, 0x16, 0xdb, 0x76, 0x77, 0xdf, + 0x2b, 0x0c, 0xe2, 0xc7, 0x84, 0x85, 0xeb, 0xd5, 0xe6, 0x9b, 0xd8, 0x0a, + 0x18, 0x48, 0xa9, 0xfe, 0x28, 0x9c, 0xa2, 0xba, 0x66, 0x4a, 0x68, 0x7b, + 0x3f, 0x05, 0x40, 0x15, 0x6e, 0x67, 0xae, 0x67, 0x69, 0xc0, 0x9e, 0x11, + 0xce, 0x56, 0x73, 0x57, 0xf5, 0xa5, 0x76, 0xa4, 0x8e, 0xed, 0xd9, 0x63, + 0x35, 0xe6, 0x28, 0x77, 0xc7, 0x3a, 0x65, 0x40, 0x8b, 0x71, 0x48, 0x4e, + 0xd0, 0xf1, 0x1d, 0x20, 0xd5, 0x1e, 0x8e, 0x54, 0x67, 0xa1, 0xe4, 0xc0, + 0x9b, 0xf7, 0x29, 0xba, 0x16, 0x9f, 0xcf, 0xdb, 0xa8, 0xb5, 0x5c, 0x4c, + 0x5b, 0x68, 0x2f, 0xaa, 0x28, 0x71, 0x9b, 0x9f, 0x49, 0xbf, 0x36, 0x2d, + 0x9f, 0x03, 0xee, 0x6b, 0xde, 0x79, 0x01, 0xe9, 0x40, 0xe2, 0x49, 0xb4, + 0x1c, 0x93, 0xb9, 0xab, 0x05, 0x4a, 0xbc, 0xab, 0x10, 0x9a, 0xf1, 0x2a, + 0xa6, 0x53, 0x5e, 0xd8, 0xf6, 0x23, 0xab, 0xfd, 0x31, 0x2a, 0xaa, 0x08, + 0x4a, 0x74, 0x8f, 0x86, 0x53, 0x83, 0xbc, 0xe3, 0x15, 0xdc, 0x0d, 0x45, + 0xcb, 0x89, 0x50, 0x8d, 0xec, 0xa9, 0x3b, 0xda, 0x22, 0xf0, 0xe7, 0x7a, + 0x4f, 0xea, 0xa2, 0xa7, 0x90, 0xe0, 0x0e, 0x5a, 0xda, 0x9b, 0xbb, 0x9a, + 0xe7, 0xd5, 0xfb, 0x63, 0x54, 0xa2, 0x52, 0xda, 0x7d, 0xc2, 0x6e, 0x6a, + 0xc2, 0xd7, 0xa6, 0x42, 0xea, 0xbf, 0x48, 0x12, 0xe6, 0x4a, 0xe1, 0x95, + 0xbf, 0x29, 0xcc, 0x9e, 0xe0, 0x25, 0x84, 0xb7, 0x74, 0xdc, 0xb1, 0x12, + 0x91, 0x57, 0xbf, 0x52, 0x43, 0x8f, 0xb7, 0xb7, 0xcd, 0x6a, 0x78, 0x24, + 0xa7, 0x41, 0x8b, 0xcc, 0x65, 0x83, 0x05, 0x8e, 0xc2, 0xf0, 0x69, 0x28, + 0xe4, 0x42, 0x62, 0x37, 0x98, 0xb5, 0x03, 0xf6, 0x75, 0x1d, 0xce, 0xe2, + 0xc0, 0x1f, 0x39, 0xac, 0xb0, 0xfb, 0x47, 0x8f, 0x6e, 0x8b, 0x16, 0xa3, + 0x0f, 0xe8, 0x21, 0x9b, 0x8e, 0x67, 0x04, 0xc7, 0x26, 0xb6, 0x03, 0xe1, + 0x00, 0x09, 0xf6, 0x77, 0x76, 0x46, 0x51, 0x41, 0x57, 0x0d, 0x4b, 0x4c, + 0x2a, 0x30, 0xdb, 0x84, 0x02, 0x6f, 0x93, 0x4b, 0x81, 0xf0, 0xd5, 0xe9, + 0x85, 0xc9, 0x75, 0xd6, 0xa9, 0x07, 0x5a, 0x41, 0xd4, 0x17, 0xc6, 0xd9, + 0x93, 0xcb, 0x49, 0x73, 0xcb, 0xe5, 0x12, 0xa6, 0x7d, 0xb3, 0x1f, 0x6a, + 0xec, 0x8c, 0xc3, 0xe9, 0xe5, 0xeb, 0xdc, 0x1e, 0xb7, 0xb4, 0x74, 0x54, + 0x51, 0x52, 0xa1, 0x56, 0xd5, 0xac, 0x58, 0x7d, +}; + +static const struct smallprime smallprimes[] = { + { .data = smallprime_8, .length = sizeof(smallprime_8) }, + { .data = smallprime_16, .length = sizeof(smallprime_16) }, + { .data = smallprime_32, .length = sizeof(smallprime_32) }, + { .data = smallprime_48, .length = sizeof(smallprime_48) }, + { .data = smallprime_64, .length = sizeof(smallprime_64) }, + { .data = smallprime_72, .length = sizeof(smallprime_72) }, + { .data = smallprime_96, .length = sizeof(smallprime_96) }, + { .data = smallprime_128, .length = sizeof(smallprime_128) }, + { .data = smallprime_184, .length = sizeof(smallprime_184) }, + { .data = smallprime_192, .length = sizeof(smallprime_192) }, + { .data = smallprime_256, .length = sizeof(smallprime_256) }, + { .data = smallprime_384, .length = sizeof(smallprime_384) }, + { .data = smallprime_512, .length = sizeof(smallprime_512) }, +}; + +/* + * Search the small prime closed to the given input bytes size + * + * @size Size in bytes + * @prime [out] Output predefined small prime + */ +static void search_smallprime(size_t size, struct caambuf *prime) +{ + size_t nb_elem = ARRAY_SIZE(smallprimes); + size_t idx = 0; + size_t psize = 0; + + for (; idx < nb_elem; idx++) { + psize = smallprimes[idx].length; + + if (psize == size) { + /* Found a predefined prime */ + RSA_TRACE("Found prime idx %zu", idx); + prime->data = (uint8_t *)smallprimes[idx].data; + prime->length = psize; + prime->paddr = virt_to_phys(prime->data); + break; + } + } +} + +/* + * Build the descriptor preparing the CAAM global variables used during the + * prime generation + * + * @desc [out] Descriptor built + * @data Prime generation data + * @small_prime Pre-generated small prime value + * @desc_prime Physical address of the prime generator descriptor + */ +static void do_desc_setup(uint32_t *desc, struct prime_data_rsa *data, + const struct caambuf *small_prime, + const paddr_t desc_prime) +{ + /* + * Referring to FIPS.186-4, B.3.3 (step 4.7) + * Maximum tries = 5 * (nlen / 2) + * Where nlen is the RSA security length in bit + */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, SOL, 4)); + caam_desc_add_word(desc, 5 * (data->key_size / 2)); + + /* + * Referring to FIPS.186-4, Table C.2 + * Get the number Miller-Rabin test interation function + * of the prime number size + */ + caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, SIL, 4)); + if (data->p->length > (MR_PRIME_SIZE / 8)) + caam_desc_add_word(desc, 0x4); + else + caam_desc_add_word(desc, 0x5); + + /* + * Preload PKHA A2 with the sqrt_value array (step 4.4) + * Do it once, not at each loop + */ + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A2, NOACTION, + data->p->length)); + caam_desc_add_ptr(desc, virt_to_phys((void *)sqrt_value)); + + if (data->era >= 8 && small_prime->paddr) { + /* + * Preload PKHA B2 with small prime predefined + * (preload only prime size requested) + * + * Before Era 8, the PRIME TEST function overwrites PKHA B2 + * hence PKHA B2 must be reloaded if new prime tentative after + * PRIME TEST on Era < 8 + */ + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_B2, NOACTION, + small_prime->length)); + caam_desc_add_ptr(desc, small_prime->paddr); + } + + /* Set the High order bit used to turn on MSB in prime candidate */ + caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 0x3F, REG2, 8)); + + /* Load PKHA N Size with the prime size */ + caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_N_SIZE, 4)); + caam_desc_add_word(desc, data->p->length); + + /* + * Set the number of maximum tries because of generated value + * is too small. This value is used to not lock the system + * in prime number generation + */ + caam_desc_add_word(desc, MATH(ADD, ZERO, IMM_DATA, DPOVRD, 4)); + caam_desc_add_word(desc, MAX_RETRY_PRIME_GEN); + + /* Jump to the next descriptor desc */ + caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE, + JMP_COND(NONE))); + caam_desc_add_ptr(desc, desc_prime); + + RSA_DUMPDESC(desc); + cache_operation(TEE_CACHECLEAN, (void *)sqrt_value, data->p->length); +} + +/* + * Build the descriptor generating a prime + * + * @desc [out] Descriptor built + * @data Prime generation data + * @small_prime Pre-generated small prime value + * @do_prime_q Generate Prime Q + * @desc_next Physical address of the next descriptor (can be NULL) + */ +static void do_desc_prime(uint32_t *desc, struct prime_data_rsa *data, + const struct caambuf *small_prime, bool do_prime_q, + const paddr_t desc_next) +{ + uint32_t desclen = 0; + uint32_t retry_too_small = 0; + uint32_t retry_new_number = 0; + uint32_t retry_new_mr_failed = 0; + uint32_t retry_mr_test = 0; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + /* Setup the number of try counter = MAX (counting down) */ + caam_desc_add_word(desc, MATH(ADD, SOL, ZERO, VSOL, 4)); + + retry_new_mr_failed = caam_desc_get_len(desc); + if (data->era < 8 && small_prime->paddr) { + /* + * Preload PKHA B2 with small prime predefined + * (preload only prime size requested) + */ + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_B2, NOACTION, + small_prime->length)); + caam_desc_add_ptr(desc, small_prime->paddr); + } + + retry_new_number = caam_desc_get_len(desc); + /* Decrement the number of try */ + caam_desc_add_word(desc, MATH(SUB, VSOL, ONE, VSOL, 4)); + /* Exceed retry count - exit with RSA_TRY_FAIL error */ + caam_desc_add_word(desc, + HALT_USER(ALL_COND_TRUE, MATH_N, RSA_TRY_FAIL)); + + retry_too_small = caam_desc_get_len(desc); + /* Check internal limit on random value generation */ + caam_desc_add_word(desc, MATH(SUB, DPOVRD, ONE, DPOVRD, 4)); + caam_desc_add_word(desc, + HALT_USER(ALL_COND_TRUE, MATH_Z, RETRY_TOO_SMALL)); + + /* + * Step 4.2 - Obtain a string p of (nlen/2) bits + * Step 4.3 - if (p is not odd) then p = p + 1 + */ + /* Generate 16 random bytes load into DECO fifo */ + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 4)); + caam_desc_add_word(desc, NFIFO_PAD(DECO, NFIFO_LC1, MSG, RND, 16)); + + /* Get the DECO Input fifo 8 MSB and force on high bit */ + caam_desc_add_word(desc, MATH(OR, REG2, IFIFO, REG0, 8)); + /* Get the DECO Input fifo 8 LSB and force it be be odd */ + caam_desc_add_word(desc, MATH(OR, ONE, IFIFO, REG1, 8)); + /* Move the MSB and LSB into IFIFO */ + caam_desc_add_word(desc, MOVE(MATH_REG0, IFIFO, 0, 16)); + /* Send the 8 MSB into PKHA N */ + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 4)); + caam_desc_add_word(desc, NFIFO_NOPAD(C1, 0, IFIFO, PKHA_N, 8)); + + /* + * Generate the "middle" random bytes and start them + * on their way into PKHA N + */ + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); + caam_desc_add_word(desc, NFIFO_PAD(C1, 0, PKHA_N, RND, 0)); + caam_desc_add_word(desc, data->p->length - 16); + + /* And send the 8 LSB into PKHA N */ + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 4)); + caam_desc_add_word(desc, NFIFO_NOPAD(C1, NFIFO_FC1, IFIFO, PKHA_N, 8)); + + /* + * Step 4.4 - if ((prime < (sqrt 2)(2^((nlen / 2) - 1)) + * ==> retry_too_small + */ + caam_desc_add_word(desc, PKHA_CPY_SSIZE(A2, B0)); + caam_desc_add_word(desc, PKHA_CPY_SSIZE(B0, A0)); + caam_desc_add_word(desc, PKHA_OP(MOD_AMODN, A)); + caam_desc_add_word(desc, PKHA_CPY_SSIZE(A2, B0)); + caam_desc_add_word(desc, PKHA_F2M_OP(MOD_ADD_A_B, B)); + + desclen = caam_desc_get_len(desc); + caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, + JMP_COND(PKHA_IS_ZERO), + retry_too_small - desclen)); + + /* + * Step 4.5 - Compute GCD(prime-1, e) and test if = 1 else try + * another candidate + */ + caam_desc_add_word(desc, PKHA_CPY_SSIZE(N0, A0)); + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_word(desc, 0x01); + caam_desc_add_word(desc, PKHA_F2M_OP(MOD_ADD_A_B, B)); + caam_desc_add_word(desc, PKHA_CPY_SSIZE(B0, N0)); + + caam_desc_add_word(desc, + FIFO_LD(CLASS_1, PKHA_A, NOACTION, data->e->length)); + caam_desc_add_ptr(desc, data->e->paddr); + caam_desc_add_word(desc, PKHA_OP(GCD_A_N, B)); + + desclen = caam_desc_get_len(desc); + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ANY_COND_FALSE, JMP_COND(PKHA_GCD_1), + retry_new_number - desclen)); + + caam_desc_add_word(desc, PKHA_CPY_SSIZE(N0, A0)); + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_word(desc, 0x01); + caam_desc_add_word(desc, PKHA_F2M_OP(MOD_ADD_A_B, B)); + caam_desc_add_word(desc, PKHA_CPY_SSIZE(B0, N0)); + + /* + * Step 4.5.1 - test primality + */ + if (small_prime->paddr) { + caam_desc_add_word(desc, PKHA_CPY_SSIZE(B2, A0)); + caam_desc_add_word(desc, PKHA_OP(GCD_A_N, B)); + desclen = caam_desc_get_len(desc); + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ANY_COND_FALSE, + JMP_COND(PKHA_GCD_1), + retry_new_number - desclen)); + } + + /* Generate 8 random bytes 'miller-rabin seed' */ + /* Load the number of Miller-Rabin test iteration */ + caam_desc_add_word(desc, MATH(ADD, SIL, ZERO, VSIL, 4)); + retry_mr_test = caam_desc_get_len(desc); + caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); + caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0)); + caam_desc_add_word(desc, data->p->length); + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); + caam_desc_add_word(desc, 0x01); + caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B)); + + desclen = caam_desc_get_len(desc); + caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, + JMP_COND(PKHA_IS_PRIME), + retry_new_mr_failed - desclen)); + caam_desc_add_word(desc, MATH(SUB, VSIL, ONE, VSIL, 4)); + + desclen = caam_desc_get_len(desc); + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ALL_COND_FALSE, + JMP_COND(MATH_N) | JMP_COND(MATH_Z), + retry_mr_test - desclen)); + + /* Save prime generated */ + caam_desc_add_word(desc, FIFO_ST(PKHA_N, data->p->length)); + + if (do_prime_q) + caam_desc_add_ptr(desc, data->q->paddr); + else + caam_desc_add_ptr(desc, data->p->paddr); + + if (desc_next) { + /* Jump to the next descriptor desc */ + caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE, + JMP_COND(NONE))); + caam_desc_add_ptr(desc, desc_next); + } + + RSA_DUMPDESC(desc); +} + +/* + * Build the descriptor to check primes p and q not too closed. + * Check the upper 100 bits with operation: + * |p - q| <= 2^(nlen/2-100) + * + * @desc [out] Descriptor built + * @p Prime P + * @max_n Max N built with 0xFFFF... + * @desc_new_q Physical address to generate a new Q value + */ +static void do_checks_primes(uint32_t *desc, const struct caambuf *p, + const struct caambuf *max_n, + const paddr_t desc_new_q) +{ + const uint8_t check_len = 16; /* Check 128 bits */ + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + /* Load prime p */ + caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_B, NOACTION, p->length)); + caam_desc_add_ptr(desc, p->paddr); + + /* Retrieve Q from PKHA N, previously computed */ + caam_desc_add_word(desc, PKHA_CPY_SSIZE(N0, A0)); + + /* Calculate p - q, need a modulus of size prime p filled with 0xFF */ + caam_desc_add_word(desc, + FIFO_LD(CLASS_1, PKHA_N, NOACTION, max_n->length)); + caam_desc_add_ptr(desc, max_n->paddr); + + /* PKHA_B = p - q */ + caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, B)); + + /* Unload PKHA register B to output Data FIFO */ + caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CHA_CTRL, 4)); + caam_desc_add_word(desc, CCTRL_ULOAD_PKHA_B); + + /* Get the first 128 bits in MATH 0 */ + caam_desc_add_word(desc, MOVE_WAIT(OFIFO, MATH_REG0, 0, check_len)); + + /* + * We now need to trash the rest of the result. + * We started with 128, 192, or 256 bytes in the OFIFO before we moved + * check_len bytes into MATH registers. + */ + if (p->length > 128 + (size_t)check_len) { + caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, check_len)); + caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, + (p->length - 128 - check_len))); + } else if (p->length > check_len) { + caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, + (p->length - check_len))); + } + + /* + * In MATH registers we have the p - q value modulo 0xFFFFF... + * Check the upper 100 bits are either zero or one meaning + * q is too close to p + */ + /* Check first 64 bits if not 0's check if 1's */ + caam_desc_add_word(desc, MATH(ADD, ZERO, REG0, REG0, 8)); + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ANY_COND_FALSE, JMP_COND(MATH_Z), 6)); + /* First 64 bits are 0's, check next 36 bits */ + caam_desc_add_word(desc, MATH(AND, REG1, IMM_DATA, REG1, 8)); + caam_desc_add_word(desc, UINT32_MAX); + caam_desc_add_word(desc, 0xF0000000); + + /* Next 36 bits are 0 */ + caam_desc_add_word(desc, + JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(MATH_Z), 10)); + /* Exit status GOOD Q */ + caam_desc_add_word(desc, HALT_USER(ALL_COND_TRUE, NONE, STATUS_GOOD_Q)); + + /* Check if 100 bits are 1's */ + caam_desc_add_word(desc, MATH(ADD, ONE, REG0, REG0, 8)); + /* Not all 1's exit status GOOD Q */ + caam_desc_add_word(desc, + HALT_USER(ANY_COND_FALSE, MATH_Z, STATUS_GOOD_Q)); + /* First 64 bits are 1's, check next 36 bits */ + caam_desc_add_word(desc, MATH(AND, REG1, IMM_DATA, REG1, 8)); + caam_desc_add_word(desc, UINT32_MAX); + caam_desc_add_word(desc, SHIFT_U32(0xF, 28)); + + /* Use only 4 bytes of immediate data even is operation is 8 bytes */ + caam_desc_add_word(desc, MATH(ADD, REG1, IMM_DATA, REG1, 8) | MATH_IFB); + caam_desc_add_word(desc, SHIFT_U32(1, 28)); + + /* Not all 1's exit status GOOD Q */ + caam_desc_add_word(desc, + HALT_USER(ANY_COND_FALSE, MATH_Z, STATUS_GOOD_Q)); + + if (desc_new_q) { + caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE, + JMP_COND(NONE))); + caam_desc_add_ptr(desc, desc_new_q); + } + + RSA_DUMPDESC(desc); +} + +/* + * Run the Primes descriptor. + * + * @desc Descriptor built + * @prime Prime generation data + */ +static enum caam_status run_primes(uint32_t *desc, struct prime_data_rsa *data) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + + cache_operation(TEE_CACHEFLUSH, data->p->data, data->p->length); + + if (data->q) + cache_operation(TEE_CACHEFLUSH, data->q->data, data->q->length); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (data->q && retstatus == CAAM_JOB_STATUS) { + /* + * Expect to have a retstatus == CAAM_JOB_STATUS, where + * job status == STATUS_GOOD_Q + */ + RSA_TRACE("Check Prime Q Status 0x%08" PRIx32, jobctx.status); + + if (JRSTA_GET_HALT_USER(jobctx.status) == STATUS_GOOD_Q) { + cache_operation(TEE_CACHEINVALIDATE, data->p->data, + data->p->length); + cache_operation(TEE_CACHEINVALIDATE, data->q->data, + data->q->length); + + RSA_DUMPBUF("Prime P", data->p->data, data->p->length); + RSA_DUMPBUF("Prime Q", data->q->data, data->q->length); + retstatus = CAAM_NO_ERROR; + } + } else if (retstatus == CAAM_NO_ERROR && !data->q) { + cache_operation(TEE_CACHEINVALIDATE, data->p->data, + data->p->length); + + RSA_DUMPBUF("Prime", data->p->data, data->p->length); + } else if (retstatus != CAAM_NO_ERROR) { + RSA_TRACE("Prime Status 0x%08" PRIx32, jobctx.status); + } + + return retstatus; +} + +enum caam_status caam_prime_rsa_gen(struct prime_data_rsa *data) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct caambuf small_prime = { }; + struct caambuf max_n = { }; + uint32_t *all_descs = NULL; + uint32_t *desc_p = NULL; + uint32_t *desc_q = NULL; + uint32_t *desc_check_p_q = NULL; + paddr_t paddr_desc_p = 0; + paddr_t paddr_desc_q = 0; + paddr_t paddr_desc_check_p_q = 0; + size_t size_all_descs = 0; + size_t nb_tries = RSA_MAX_TRIES_PRIMES; + + /* Allocate the job used to prepare the operation */ + if (data->q) { + size_all_descs = SETUP_RSA_DESC_ENTRIES + + GEN_RSA_DESC_ENTRIES * 2 + + CHECK_P_Q_DESC_ENTRIES; + + retstatus = caam_calloc_buf(&max_n, data->p->length + 1); + if (retstatus != CAAM_NO_ERROR) + goto end_gen_prime; + + /* Set the max_n with 0xFFF... to operate the check P and Q */ + memset(max_n.data, UINT8_MAX, max_n.length); + cache_operation(TEE_CACHECLEAN, max_n.data, max_n.length); + } else { + size_all_descs = SETUP_RSA_DESC_ENTRIES + GEN_RSA_DESC_ENTRIES; + } + + all_descs = caam_calloc_desc(size_all_descs); + if (!all_descs) { + retstatus = CAAM_OUT_MEMORY; + goto end_gen_prime; + } + + /* Descriptor Prime P */ + desc_p = all_descs + SETUP_RSA_DESC_ENTRIES; + paddr_desc_p = virt_to_phys(desc_p); + if (!paddr_desc_p) { + retstatus = CAAM_FAILURE; + goto end_gen_prime; + } + + /* + * Search predefined prime in the small_prime list, if the + * small prime is not found in the list, continue anyway + * but prime will be probably not so strong + */ + search_smallprime(data->p->length, &small_prime); + + RSA_TRACE("Do prime of %zu bytes (security len %zu bits) (ERA=%" PRId8 + ")", + data->p->length, data->key_size, data->era); + + do_desc_setup(all_descs, data, &small_prime, paddr_desc_p); + + if (data->q) { + /* Descriptor Prime Q */ + desc_q = desc_p + GEN_RSA_DESC_ENTRIES; + paddr_desc_q = + paddr_desc_p + DESC_SZBYTES(GEN_RSA_DESC_ENTRIES); + + /* Descriptor Check Primes P & Q */ + desc_check_p_q = desc_q + GEN_RSA_DESC_ENTRIES; + paddr_desc_check_p_q = + paddr_desc_q + DESC_SZBYTES(GEN_RSA_DESC_ENTRIES); + + /* Generate Prime P and Q then check Q not too close than P */ + do_desc_prime(desc_p, data, &small_prime, false, paddr_desc_q); + + do_desc_prime(desc_q, data, &small_prime, true, + paddr_desc_check_p_q); + + do_checks_primes(desc_check_p_q, data->p, &max_n, paddr_desc_q); + } else { + do_desc_prime(desc_p, data, &small_prime, false, 0); + } + + cache_operation(TEE_CACHECLEAN, small_prime.data, data->p->length); + cache_operation(TEE_CACHECLEAN, data->e->data, data->e->length); + cache_operation(TEE_CACHECLEAN, (void *)all_descs, + DESC_SZBYTES(size_all_descs)); + + do { + retstatus = run_primes(all_descs, data); + } while (--nb_tries && retstatus != CAAM_NO_ERROR); + +end_gen_prime: + caam_free_desc(&all_descs); + caam_free_buf(&max_n); + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c new file mode 100644 index 0000000..055ce9d --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/caam_rsa.c @@ -0,0 +1,1580 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * CAAM RSA manager. + * Implementation of RSA functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +/* + * Definition of the maximum bits of Exponent e + * Refer to sp800-56b + */ +#define MAX_BITS_EXP_E 256 + +/* + * Define the maximum number of entries in a descriptor + * function of the encrypt/decrypt and private key format + */ +#ifdef CFG_CAAM_64BIT +#define MAX_DESC_ENC (8 + 4) +#define MAX_DESC_DEC_1 (7 + 2 + 4) +#define MAX_DESC_DEC_2 (11 + 2 + 7) +#define MAX_DESC_DEC_3 (13 + 2 + 10) +/* Define the maximum number of entries in the RSA Finish Key descriptor */ +#define MAX_DESC_KEY_FINISH 24 +#else +#define MAX_DESC_ENC 8 +#define MAX_DESC_DEC_1 (7 + 2) +#define MAX_DESC_DEC_2 (11 + 2) +#define MAX_DESC_DEC_3 (13 + 2) +/* Define the maximum number of entries in the RSA Finish Key descriptor */ +#define MAX_DESC_KEY_FINISH 15 +#endif /* CFG_CAAM_64BIT */ + +static TEE_Result do_caam_encrypt(struct drvcrypt_rsa_ed *rsa_data, + uint32_t operation); +static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data, + uint32_t operation); + +/* + * Definition of the local RSA keypair + * Public Key Format: (n, e) + * Private Key Format #1: (n, d) + * Private Key Format #2: (p, q, d) + * Private Key Format #3: (p, q, dp, dq, qp) + */ +struct caam_rsa_keypair { + uint8_t format; /* Define the Private Key Format (1, 2 or 3) */ + struct caambuf n; /* Modulus [n = p * q] */ + struct caambuf e; /* Public Exponent 65537 <= e < 2^256 */ + struct caambuf d; /* Private Exponent [d = 1/e mod LCM(p-1, q-1)] */ + struct caambuf p; /* Private Prime p */ + struct caambuf q; /* Private Prime q */ + struct caambuf dp; /* Private [dp = d mod (p-1)] */ + struct caambuf dq; /* Private [dq = d mod (q-1)] */ + struct caambuf qp; /* Private [qp = 1/q mod p] */ +}; + +#define RSA_PRIVATE_KEY_FORMAT_1 1 +#define RSA_PRIVATE_KEY_FORMAT_2 2 +#define RSA_PRIVATE_KEY_FORMAT_3 3 + +/* CAAM Era version */ +static uint8_t caam_era; + +/* + * Free RSA keypair + * + * @key RSA keypair + */ +static void do_free_keypair(struct rsa_keypair *key) +{ + crypto_bignum_free(key->e); + crypto_bignum_free(key->d); + crypto_bignum_free(key->n); + crypto_bignum_free(key->p); + crypto_bignum_free(key->q); + crypto_bignum_free(key->qp); + crypto_bignum_free(key->dp); + crypto_bignum_free(key->dq); +} + +/* + * Free local caam RSA keypair + * + * @key caam RSA keypair + */ +static void do_keypair_free(struct caam_rsa_keypair *key) +{ + caam_free_buf(&key->e); + caam_free_buf(&key->n); + caam_free_buf(&key->d); + + if (key->format > RSA_PRIVATE_KEY_FORMAT_1 && key->p.data) { + key->p.length += key->q.length; + caam_free_buf(&key->p); + } + + if (key->format > RSA_PRIVATE_KEY_FORMAT_2 && key->dp.data) { + key->dp.length += key->dq.length + key->qp.length; + caam_free_buf(&key->dp); + } +} + +/* + * Convert Crypto RSA Key to local RSA Public Key + * Ensure Key is push in physical memory + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + */ +static enum caam_status do_keypub_conv(struct caam_rsa_keypair *outkey, + const struct rsa_public_key *inkey) +{ + enum caam_status retstatus = CAAM_FAILURE; + + RSA_TRACE("RSA Convert Public Key size N=%zu", + crypto_bignum_num_bytes(inkey->n)); + + retstatus = caam_calloc_align_buf(&outkey->e, + crypto_bignum_num_bytes(inkey->e)); + if (retstatus != CAAM_NO_ERROR) + goto exit_conv; + + crypto_bignum_bn2bin(inkey->e, outkey->e.data); + cache_operation(TEE_CACHECLEAN, outkey->e.data, outkey->e.length); + + retstatus = caam_calloc_align_buf(&outkey->n, + crypto_bignum_num_bytes(inkey->n)); + if (retstatus != CAAM_NO_ERROR) + goto exit_conv; + + crypto_bignum_bn2bin(inkey->n, outkey->n.data); + cache_operation(TEE_CACHECLEAN, outkey->n.data, outkey->n.length); + + return CAAM_NO_ERROR; + +exit_conv: + do_keypair_free(outkey); + + return CAAM_OUT_MEMORY; +} + +/* + * Convert Crypto RSA Key additional fields of the key format #3 + * Optional fields (dp, dq, qp) + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + */ +static enum caam_status do_keypair_conv_f3(struct caam_rsa_keypair *outkey, + const struct rsa_keypair *inkey) +{ + enum caam_status retstatus = CAAM_FAILURE; + size_t size_p = 0; + size_t size_q = 0; + size_t size_dp = 0; + size_t size_dq = 0; + size_t size_qp = 0; + + size_p = outkey->p.length; + size_q = outkey->q.length; + size_dp = crypto_bignum_num_bytes(inkey->dp); + size_dq = crypto_bignum_num_bytes(inkey->dq); + size_qp = crypto_bignum_num_bytes(inkey->qp); + + /* Check that dp, dq and qp size not exceed p and q size */ + if (size_dp > size_p || size_dq > size_q || size_qp > size_p) + return CAAM_FAILURE; + + /* + * If one of the parameters dp, dq or qp are not filled, + * returns immediately. This is not an error. + */ + if (!size_dp || !size_dq || !size_qp) + return CAAM_NO_ERROR; + + /* + * CAAM is assuming that: + * - dp and dq are same size as p + * - dq same size as q + * + * Because calculation of dp, dq and qp can be less + * than above assumption, force the dp, dq and qp + * buffer size. + */ + /* Allocate one buffer for the 3 fields */ + retstatus = + caam_calloc_align_buf(&outkey->dp, size_p + size_q + size_p); + if (retstatus != CAAM_NO_ERROR) + return CAAM_OUT_MEMORY; + + /* Field dp */ + outkey->dp.length = size_p; + + /* + * Ensure buffer is copied starting with 0's + * if size_dp != size_p + */ + crypto_bignum_bn2bin(inkey->dp, outkey->dp.data + size_p - size_dp); + + /* Field dq */ + outkey->dq.data = outkey->dp.data + size_p; + outkey->dq.length = size_q; + outkey->dq.paddr = outkey->dp.paddr + size_p; + + /* + * Ensure buffer is copied starting with 0's + * if size_dq != size_q + */ + crypto_bignum_bn2bin(inkey->dq, outkey->dq.data + size_q - size_dq); + + /* Field qp */ + outkey->qp.data = outkey->dq.data + size_q; + outkey->qp.length = size_p; + outkey->qp.paddr = outkey->dq.paddr + size_q; + + /* + * Ensure buffer is copied starting with 0's + * if size_qp != size_p + */ + crypto_bignum_bn2bin(inkey->qp, outkey->qp.data + size_p - size_qp); + + /* Push fields value to the physical memory */ + cache_operation(TEE_CACHECLEAN, outkey->dp.data, + outkey->dp.length + outkey->dq.length + + outkey->qp.length); + + outkey->format = RSA_PRIVATE_KEY_FORMAT_3; + + return CAAM_NO_ERROR; +} + +/* + * Convert Crypto RSA Key additional fields of the key format #2 + * Optional fields (p, q) + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + */ +static enum caam_status do_keypair_conv_f2(struct caam_rsa_keypair *outkey, + const struct rsa_keypair *inkey) +{ + enum caam_status retstatus = CAAM_FAILURE; + size_t size_p = 0; + size_t size_q = 0; + + size_p = crypto_bignum_num_bytes(inkey->p); + size_q = crypto_bignum_num_bytes(inkey->q); + + /* + * If the Prime P or Prime Q are not filled, returns + * immediately. This is not an error. + */ + if (size_p || !size_q) + return CAAM_NO_ERROR; + + /* Allocate one buffer for both */ + retstatus = caam_calloc_align_buf(&outkey->p, size_p + size_q); + if (retstatus != CAAM_NO_ERROR) + return CAAM_OUT_MEMORY; + + /* Field Prime p */ + outkey->p.length = size_p; + crypto_bignum_bn2bin(inkey->p, outkey->p.data); + + /* Field Prime q */ + outkey->q.data = outkey->p.data + size_p; + outkey->q.length = size_q; + outkey->q.paddr = outkey->p.paddr + size_p; + + crypto_bignum_bn2bin(inkey->q, outkey->q.data); + + /* Push fields value to the physical memory */ + cache_operation(TEE_CACHECLEAN, outkey->p.data, size_p + size_q); + + outkey->format = RSA_PRIVATE_KEY_FORMAT_2; + + if (CFG_NXP_CAAM_RSA_KEY_FORMAT > RSA_PRIVATE_KEY_FORMAT_2) { + retstatus = do_keypair_conv_f3(outkey, inkey); + RSA_TRACE("do_keypair_conv_f3 returned 0x%" PRIx32, retstatus); + } + + return retstatus; +} + +/* + * Convert Crypto RSA Key to local RSA Keypair Key + * Ensure Key is push in physical memory + * Don't convert the exponent e not used in decrytion + * + * @outkey [out] Output keypair in local format + * @inkey Input key in TEE Crypto format + */ +static enum caam_status do_keypair_conv(struct caam_rsa_keypair *outkey, + const struct rsa_keypair *inkey) +{ + enum caam_status retstatus = CAAM_FAILURE; + + RSA_TRACE("RSA Convert Keypair size N=%zu", + crypto_bignum_num_bytes(inkey->n)); + + /* Mandatory fields are n and d => Private Key Format #1 */ + retstatus = caam_calloc_align_buf(&outkey->n, + crypto_bignum_num_bytes(inkey->n)); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + crypto_bignum_bn2bin(inkey->n, outkey->n.data); + cache_operation(TEE_CACHECLEAN, outkey->n.data, outkey->n.length); + + retstatus = caam_calloc_align_buf(&outkey->d, + crypto_bignum_num_bytes(inkey->d)); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + crypto_bignum_bn2bin(inkey->d, outkey->d.data); + cache_operation(TEE_CACHECLEAN, outkey->d.data, outkey->d.length); + + outkey->format = RSA_PRIVATE_KEY_FORMAT_1; + + if (CFG_NXP_CAAM_RSA_KEY_FORMAT > RSA_PRIVATE_KEY_FORMAT_1) { + retstatus = do_keypair_conv_f2(outkey, inkey); + RSA_TRACE("do_keypair_conv_f2 returned 0x%" PRIx32, retstatus); + } + + return retstatus; +} + +/* + * Allocate a RSA keypair + * + * @key Keypair + * @size_bits Key size in bits + */ +static TEE_Result do_allocate_keypair(struct rsa_keypair *key, size_t size_bits) +{ + RSA_TRACE("Allocate Keypair of %zu bits", size_bits); + + /* Initialize all input key fields to 0 */ + memset(key, 0, sizeof(*key)); + + /* Allocate the Public Exponent to maximum size */ + key->e = crypto_bignum_allocate(MAX_BITS_EXP_E); + if (!key->e) + goto err_alloc_keypair; + + /* Allocate the Private Exponent [d = 1/e mod LCM(p-1, q-1)] */ + key->d = crypto_bignum_allocate(size_bits); + if (!key->d) + goto err_alloc_keypair; + + /* Allocate the Modulus (size_bits) [n = p * q] */ + key->n = crypto_bignum_allocate(size_bits); + if (!key->n) + goto err_alloc_keypair; + + /* Allocate the prime number p of size (size_bits / 2) */ + key->p = crypto_bignum_allocate(size_bits / 2); + if (!key->p) + goto err_alloc_keypair; + + /* Allocate the prime number q of size (size_bits / 2) */ + key->q = crypto_bignum_allocate(size_bits / 2); + if (!key->q) + goto err_alloc_keypair; + + /* Allocate dp (size_bits / 2) [d mod (p-1)] */ + key->dp = crypto_bignum_allocate(size_bits / 2); + if (!key->dp) + goto err_alloc_keypair; + + /* Allocate dq (size_bits / 2) [d mod (q-1)] */ + key->dq = crypto_bignum_allocate(size_bits / 2); + if (!key->dq) + goto err_alloc_keypair; + + /* Allocate qp (size_bits / 2) [1/q mod p] */ + key->qp = crypto_bignum_allocate(size_bits / 2); + if (!key->qp) + goto err_alloc_keypair; + + return TEE_SUCCESS; + +err_alloc_keypair: + RSA_TRACE("Allocation error"); + + do_free_keypair(key); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +/* + * Allocate a RSA public key + * + * @key Public Key + * @size_bits Key size in bits + */ +static TEE_Result do_allocate_publickey(struct rsa_public_key *key, + size_t size_bits) +{ + RSA_TRACE("Allocate Public Key of %zu bits", size_bits); + + /* Initialize all input key fields to 0 */ + memset(key, 0, sizeof(*key)); + + /* Allocate the Public Exponent to maximum size */ + key->e = crypto_bignum_allocate(MAX_BITS_EXP_E); + if (!key->e) + goto err_alloc_publickey; + + /* Allocate the Modulus (size_bits) [n = p * q] */ + key->n = crypto_bignum_allocate(size_bits); + if (!key->n) + goto err_alloc_publickey; + + return TEE_SUCCESS; + +err_alloc_publickey: + RSA_TRACE("Allocation error"); + + crypto_bignum_free(key->e); + crypto_bignum_free(key->n); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +/* + * Free a RSA public key + * + * @key Public Key + */ +static void do_free_publickey(struct rsa_public_key *key) +{ + crypto_bignum_free(key->e); + crypto_bignum_free(key->n); +} + +/* + * Output the RSA keypair format 3 additional fields in bignumber object + * + * @key [out] Keypair + * @key_size Key size in bits + */ +static TEE_Result gen_keypair_get_f3(struct rsa_keypair *key, + struct caam_rsa_keypair *genkey) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + cache_operation(TEE_CACHEINVALIDATE, genkey->dp.data, + genkey->dp.length + genkey->dq.length + + genkey->qp.length); + + RSA_DUMPBUF("dp", genkey->dp.data, genkey->dp.length); + RSA_DUMPBUF("dq", genkey->dq.data, genkey->dq.length); + RSA_DUMPBUF("qp", genkey->qp.data, genkey->qp.length); + + ret = crypto_bignum_bin2bn(genkey->dp.data, genkey->dp.length, key->dp); + if (ret != TEE_SUCCESS) + return ret; + + ret = crypto_bignum_bin2bn(genkey->dq.data, genkey->dq.length, key->dq); + if (ret != TEE_SUCCESS) + return ret; + + ret = crypto_bignum_bin2bn(genkey->qp.data, genkey->qp.length, key->qp); + return ret; +} + +/* + * Output the RSA keypair format 2 additional fields in big number object + * + * @key [out] Keypair + * @key_size Key size in bits + */ +static TEE_Result gen_keypair_get_f2(struct rsa_keypair *key, + struct caam_rsa_keypair *genkey) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + cache_operation(TEE_CACHEINVALIDATE, genkey->p.data, + genkey->p.length + genkey->q.length); + + ret = crypto_bignum_bin2bn(genkey->p.data, genkey->p.length, key->p); + if (ret != TEE_SUCCESS) + return ret; + + ret = crypto_bignum_bin2bn(genkey->q.data, genkey->q.length, key->q); + + if (ret == TEE_SUCCESS && genkey->format > RSA_PRIVATE_KEY_FORMAT_2) + ret = gen_keypair_get_f3(key, genkey); + + return ret; +} + +/* + * Generates a RSA keypair + * + * @key [out] Keypair + * @key_size Key size in bits + */ +static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_rsa_keypair genkey = { }; + size_t size_d = 0; + size_t size_n = 0; + size_t size_d_gen = 0; + struct caam_jobctx jobctx = { }; + uint32_t *desc = 0; + uint32_t desclen = 0; + struct prime_data_rsa prime = { }; + + RSA_TRACE("Generate Keypair of %zu bits", key_size); + + genkey.format = CFG_NXP_CAAM_RSA_KEY_FORMAT; + + /* Allocate the job used to prepare the operation */ + desc = caam_calloc_desc(MAX_DESC_KEY_FINISH); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto exit_gen_keypair; + } + + /* First allocate primes p and q in one buffer */ + retstatus = caam_calloc_align_buf(&genkey.p, key_size / 8); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + /* Prepare q */ + genkey.p.length /= 2; + genkey.q.data = genkey.p.data + genkey.p.length; + genkey.q.length = genkey.p.length; + genkey.q.paddr = genkey.p.paddr + genkey.p.length; + + /* Allocate Public exponent to a caam buffer */ + retstatus = caam_calloc_buf(&genkey.e, crypto_bignum_num_bytes(key->e)); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + /* + * Allocate d and n in one buffer. + * Size of d is (key_size + 1) bits - Add a 32 bits word to + * retrieve the length of d generated by CAAM RSA Finalize Key + */ + size_d = sizeof(uint32_t) + key_size / 8 + 1; + size_n = key_size / 8; + + retstatus = caam_calloc_align_buf(&genkey.d, size_d + size_n); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + genkey.d.length = size_d; + genkey.n.data = genkey.d.data + size_d; + genkey.n.length = size_n; + genkey.n.paddr = genkey.d.paddr + size_d; + + if (genkey.format > RSA_PRIVATE_KEY_FORMAT_2) { + /* Allocate dp, dq and qp in one buffer */ + retstatus = caam_calloc_align_buf(&genkey.dp, + ((key_size / 8) / 2) * 3); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + genkey.dp.length /= 3; + /* Prepare dq and qp */ + genkey.dq.data = genkey.dp.data + genkey.dp.length; + genkey.dq.length = genkey.dp.length; + genkey.dq.paddr = genkey.dp.paddr + genkey.dp.length; + + genkey.qp.data = genkey.dq.data + genkey.dq.length; + genkey.qp.length = genkey.dq.length; + genkey.qp.paddr = genkey.dq.paddr + genkey.dq.length; + } + + crypto_bignum_bn2bin(key->e, genkey.e.data); + + prime.era = caam_era; + prime.key_size = key_size; + prime.e = &genkey.e; + prime.p = &genkey.p; + prime.q = &genkey.q; + + /* Generate prime p and q */ + retstatus = caam_prime_rsa_gen(&prime); + RSA_TRACE("Generate Prime P and Q returned 0x%" PRIx32, retstatus); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_gen_keypair; + } + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + caam_desc_add_word(desc, 0); + caam_desc_add_word(desc, PDB_RSA_KEY_P_SIZE(genkey.p.length)); + caam_desc_add_word(desc, PDB_RSA_KEY_N_SIZE(genkey.n.length) | + PDB_RSA_KEY_E_SIZE(genkey.e.length)); + + caam_desc_add_ptr(desc, genkey.p.paddr); + caam_desc_add_ptr(desc, genkey.q.paddr); + caam_desc_add_ptr(desc, genkey.e.paddr); + caam_desc_add_ptr(desc, genkey.n.paddr); + caam_desc_add_ptr(desc, genkey.d.paddr + sizeof(uint32_t)); + caam_desc_add_ptr(desc, genkey.d.paddr); + + if (genkey.format > RSA_PRIVATE_KEY_FORMAT_2) { + caam_desc_add_ptr(desc, genkey.dp.paddr); + caam_desc_add_ptr(desc, genkey.dq.paddr); + caam_desc_add_ptr(desc, genkey.qp.paddr); + caam_desc_add_word(desc, RSA_FINAL_KEY(ALL)); + + cache_operation(TEE_CACHEFLUSH, genkey.dp.data, + genkey.dp.length + genkey.dq.length + + genkey.qp.length); + + } else { + caam_desc_add_word(desc, RSA_FINAL_KEY(N_D)); + } + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + jobctx.desc = desc; + RSA_DUMPDESC(desc); + + cache_operation(TEE_CACHECLEAN, genkey.e.data, genkey.e.length); + cache_operation(TEE_CACHEFLUSH, genkey.p.data, + genkey.p.length + genkey.q.length); + cache_operation(TEE_CACHEFLUSH, genkey.d.data, + genkey.d.length + genkey.n.length); + + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + cache_operation(TEE_CACHEINVALIDATE, genkey.d.data, + genkey.d.length + genkey.n.length); + + size_d_gen = caam_read_val32(genkey.d.data); + RSA_TRACE("D size %zu", size_d_gen); + RSA_DUMPBUF("N", genkey.n.data, genkey.n.length); + RSA_DUMPBUF("D", genkey.d.data + sizeof(uint32_t), size_d_gen); + + ret = crypto_bignum_bin2bn(genkey.n.data, genkey.n.length, + key->n); + if (ret != TEE_SUCCESS) + goto exit_gen_keypair; + + ret = crypto_bignum_bin2bn(genkey.d.data + sizeof(uint32_t), + size_d_gen, key->d); + if (ret != TEE_SUCCESS) + goto exit_gen_keypair; + + if (genkey.format > RSA_PRIVATE_KEY_FORMAT_1) + ret = gen_keypair_get_f2(key, &genkey); + } else { + RSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +exit_gen_keypair: + genkey.d.length += genkey.n.length; + genkey.n.data = NULL; + do_keypair_free(&genkey); + + caam_free_desc(&desc); + + return ret; +} + +/* + * RSA EME-OAEP Decoding operation + * Refer the chapter 7.1.2 Decryption operation of pkcs-1v2-1 specification + * + * @rsa_data [in/out] RSA Data to encode + */ +static TEE_Result do_oaep_decoding(struct drvcrypt_rsa_ed *rsa_data) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caambuf DB = { }; + struct caambuf lHash = { }; + struct caambuf seed = { }; + struct caambuf dbMask = { }; + struct caambuf maskedDB = { }; + struct caambuf maskedSeed = { }; + struct caambuf EM = { }; + size_t db_size = 0; + size_t b01_idx = 0; + size_t db_len = 0; + struct drvcrypt_rsa_mgf mgf_data = { }; + struct drvcrypt_rsa_ed dec_data = { }; + struct drvcrypt_mod_op mod_op = { }; + + RSA_TRACE("RSA OAEP Decoding"); + + /* + * First Decryption of the Cipher to a EM of modulus size + */ + retstatus = caam_calloc_align_buf(&EM, rsa_data->key.n_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_decrypt; + } + + memcpy(&dec_data, rsa_data, sizeof(dec_data)); + dec_data.message.data = EM.data; + dec_data.message.length = EM.length; + + ret = do_caam_decrypt(&dec_data, RSA_DECRYPT(NO)); + + RSA_DUMPBUF("EM", EM.data, EM.length); + + /* + * DB = lHash' || PS || 0x01 || M + * DB length = k - hLen - 1 + * + * PS is a 0's buffer of length h - mLen - 2hLen - 2 + * + * k is the key modulus length + * hLen is the Hash digest length + * mLen is the input RSA message length + */ + /* Calculate the DB size */ + db_size = rsa_data->key.n_size - rsa_data->digest_size - 1; + RSA_TRACE("DB is %zu bytes", db_size); + + /* Allocate the DB buffer */ + retstatus = caam_calloc_align_buf(&DB, db_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_decrypt; + } + + /* + * Step a + * Generate the lHash + */ + /* Allocate the lHash buffer */ + retstatus = caam_calloc_align_buf(&lHash, rsa_data->digest_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_decrypt; + } + + RSA_TRACE("Hash the RSA Label of %zu bytes", rsa_data->label.length); + ret = tee_hash_createdigest(rsa_data->hash_algo, rsa_data->label.data, + rsa_data->label.length, lHash.data, + lHash.length); + RSA_TRACE("Hash the RSA Label returned 0x%08" PRIx32, ret); + if (ret != TEE_SUCCESS) + goto exit_oaep_decrypt; + + RSA_DUMPBUF("lHash", lHash.data, lHash.length); + + /* Allocate the seed buffer */ + retstatus = caam_calloc_align_buf(&seed, rsa_data->digest_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_decrypt; + } + + /* Allocate the dbMask buffer */ + retstatus = caam_calloc_align_buf(&dbMask, db_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_decrypt; + } + + /* + * Step b + * Split the EM string + * EM = Y || maskedSeed || maskedDB + * + * Where: + * Y size = 1 byte + * maskedSeed size = hLen + * maskedDB size = k - hLen - 1 bytes + * + * k is the key modulus length + * hLen is the Hash digest length + * mLen is the input RSA message length + * + * Note Y should have been remove during the + */ + maskedSeed.data = &EM.data[1]; + maskedSeed.length = rsa_data->digest_size; + maskedSeed.paddr = EM.paddr + sizeof(uint8_t); + + maskedDB.data = &EM.data[1 + rsa_data->digest_size]; + maskedDB.length = dbMask.length; + maskedDB.paddr = EM.paddr + sizeof(uint8_t) + rsa_data->digest_size; + + /* + * Step c + * Generate a Mask of the maskedDB + * seedMask = MGF(maskedDB, k - hLen - 1) + * + * Note: Use same buffer for seed and seedMask + */ + mgf_data.hash_algo = rsa_data->hash_algo; + mgf_data.digest_size = rsa_data->digest_size; + mgf_data.seed.data = maskedDB.data; + mgf_data.seed.length = maskedDB.length; + mgf_data.mask.data = seed.data; + mgf_data.mask.length = seed.length; + + ret = rsa_data->mgf(&mgf_data); + if (ret != TEE_SUCCESS) + goto exit_oaep_decrypt; + + /* + * Step d + * seed = maskedSeed xor seedMask + * + * Note: Use same buffer for seed and seedMask + */ + mod_op.n.length = seed.length; + mod_op.a.data = maskedSeed.data; + mod_op.a.length = maskedSeed.length; + mod_op.b.data = seed.data; + mod_op.b.length = seed.length; + mod_op.result.data = seed.data; + mod_op.result.length = seed.length; + + retstatus = drvcrypt_xor_mod_n(&mod_op); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_decrypt; + } + + RSA_DUMPBUF("Seed", seed.data, seed.length); + + /* + * Step e + * Generate a Mask of the seed value + * dbMask = MGF(seed, k - hLen - 1) + */ + mgf_data.seed.data = seed.data; + mgf_data.seed.length = seed.length; + mgf_data.mask.data = dbMask.data; + mgf_data.mask.length = dbMask.length; + + ret = rsa_data->mgf(&mgf_data); + if (ret != TEE_SUCCESS) + goto exit_oaep_decrypt; + + /* + * Step f + * DB = maskedDB xor dbMask + */ + mod_op.n.length = DB.length; + mod_op.a.data = maskedDB.data; + mod_op.a.length = maskedDB.length; + mod_op.b.data = dbMask.data; + mod_op.b.length = dbMask.length; + mod_op.result.data = DB.data; + mod_op.result.length = DB.length; + + retstatus = drvcrypt_xor_mod_n(&mod_op); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_decrypt; + } + + RSA_DUMPBUF("DB", DB.data, DB.length); + + /* + * Step g + * Check the DB generated + * DB = lHash' || PS || 0x01 || M + * + * Error if: + * - lHash' != lHash (First step - Hash the Label) + * - byte 0x01 between PS and M is not present + */ + /* Check Hash values */ + if (memcmp(DB.data, lHash.data, lHash.length)) { + RSA_TRACE("Hash error"); + ret = TEE_ERROR_BAD_PARAMETERS; + goto exit_oaep_decrypt; + } + + /* Find the byte 0x01 separating PS and M */ + for (b01_idx = rsa_data->digest_size; + b01_idx < db_size && !DB.data[b01_idx]; b01_idx++) + ; + + if (b01_idx == db_size) { + RSA_TRACE("byte 0x01 not present"); + ret = TEE_ERROR_BAD_PARAMETERS; + goto exit_oaep_decrypt; + } + + db_len = DB.length - b01_idx - 1; + + if (rsa_data->message.length < db_len) { + rsa_data->message.length = db_len; + ret = TEE_ERROR_SHORT_BUFFER; + goto exit_oaep_decrypt; + } + + rsa_data->message.length = db_len; + memcpy(rsa_data->message.data, &DB.data[b01_idx + 1], + rsa_data->message.length); + + RSA_DUMPBUF("Message decrypted", rsa_data->message.data, + rsa_data->message.length); + ret = TEE_SUCCESS; + +exit_oaep_decrypt: + caam_free_buf(&EM); + caam_free_buf(&DB); + caam_free_buf(&seed); + caam_free_buf(&dbMask); + caam_free_buf(&lHash); + + return ret; +} + +/* + * RSA EME-OAEP Encoding operation + * Refer the chapter 7.1.1 Encryption operation of pkcs-1v2-1 specification + * + * @rsa_data [int/out] RSA Data to encode + */ +static TEE_Result do_oaep_encoding(struct drvcrypt_rsa_ed *rsa_data) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus; + struct caambuf DB = { }; + struct caambuf lHash = { }; + struct caambuf seed = { }; + struct caambuf dbMask = { }; + struct caambuf maskedDB = { }; + struct caambuf maskedSeed = { }; + struct caambuf EM = { }; + size_t db_size = 0; + size_t ps_size = 0; + struct drvcrypt_rsa_mgf mgf_data = { }; + struct drvcrypt_rsa_ed enc_data = { }; + struct drvcrypt_mod_op mod_op = { }; + + RSA_TRACE("RSA OAEP Encoding"); + + /* + * DB = lHash || PS || 0x01 || M + * DB length = k - hLen - 1 + * + * PS is a 0's buffer of length h - mLen - 2hLen - 2 + * + * k is the key modulus length + * hLen is the Hash digest length + * mLen is the input RSA message length + */ + /* Calculate the DB size */ + db_size = rsa_data->key.n_size - rsa_data->digest_size - 1; + RSA_TRACE("DB is %zu bytes", db_size); + + /* Allocate the DB buffer */ + retstatus = caam_calloc_align_buf(&DB, db_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_encrypt; + } + + /* + * Step a + * Generate the lHash + */ + lHash.length = rsa_data->digest_size; + lHash.data = DB.data; + + RSA_TRACE("Hash the RSA Label of %zu bytes", rsa_data->label.length); + ret = tee_hash_createdigest(rsa_data->hash_algo, rsa_data->label.data, + rsa_data->label.length, lHash.data, + lHash.length); + RSA_TRACE("Hash the RSA Label returned 0x%08" PRIx32, ret); + if (ret != TEE_SUCCESS) + goto exit_oaep_encrypt; + RSA_DUMPBUF("lHash", lHash.data, lHash.length); + + /* + * Step b + * Add PS 0's + * Note: DB is already filled with 0's at the allocation + */ + ps_size = rsa_data->key.n_size - rsa_data->message.length - + 2 * rsa_data->digest_size - 2; + RSA_TRACE("PS is %zu bytes", ps_size); + + /* + * Step c + * Set the value 0x01 after the lHash and the PS + * Concatenate result with input message + */ + DB.data[lHash.length + ps_size] = 0x01; + memcpy(&DB.data[lHash.length + ps_size + 1], rsa_data->message.data, + rsa_data->message.length); + + RSA_DUMPBUF("DB", DB.data, DB.length); + + /* + * Step d + * Generate a random seed of hLen + */ + /* Allocate the seed buffer */ + retstatus = caam_calloc_align_buf(&seed, rsa_data->digest_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_encrypt; + } + + /* Allocate the dbMask buffer */ + retstatus = caam_calloc_align_buf(&dbMask, db_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_encrypt; + } + + ret = crypto_rng_read(seed.data, seed.length); + RSA_TRACE("Get seed of %zu bytes (ret = 0x%08" PRIx32 ")", seed.length, + ret); + if (ret != TEE_SUCCESS) + goto exit_oaep_encrypt; + + RSA_DUMPBUF("Seed", seed.data, seed.length); + + /* + * Step e + * Generate a Mask of the seed value + * dbMask = MGF(seed, k - hLen - 1) + */ + mgf_data.hash_algo = rsa_data->hash_algo; + mgf_data.digest_size = rsa_data->digest_size; + mgf_data.seed.data = seed.data; + mgf_data.seed.length = seed.length; + mgf_data.mask.data = dbMask.data; + mgf_data.mask.length = dbMask.length; + + ret = rsa_data->mgf(&mgf_data); + if (ret != TEE_SUCCESS) + goto exit_oaep_encrypt; + + /* + * Step f + * maskedDB = DB xor dbMask + */ + retstatus = caam_calloc_align_buf(&EM, rsa_data->key.n_size); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_oaep_encrypt; + } + + maskedDB.data = &EM.data[1 + rsa_data->digest_size]; + maskedDB.length = dbMask.length; + maskedDB.paddr = EM.paddr + sizeof(uint8_t) + rsa_data->digest_size; + + mod_op.n.length = maskedDB.length; + mod_op.a.data = DB.data; + mod_op.a.length = DB.length; + mod_op.b.data = dbMask.data; + mod_op.b.length = dbMask.length; + mod_op.result.data = maskedDB.data; + mod_op.result.length = maskedDB.length; + + ret = drvcrypt_xor_mod_n(&mod_op); + if (ret != TEE_SUCCESS) + goto exit_oaep_encrypt; + + /* + * Step g + * Generate a Mask of the maskedDB + * seedMask = MGF(maskedDB, hLen) + * + * Note: Use same buffer for seedMask and maskedSeed + */ + maskedSeed.data = &EM.data[1]; + maskedSeed.length = rsa_data->digest_size; + maskedSeed.paddr = EM.paddr + sizeof(uint8_t); + + mgf_data.seed.data = maskedDB.data; + mgf_data.seed.length = maskedDB.length; + mgf_data.mask.data = maskedSeed.data; + mgf_data.mask.length = maskedSeed.length; + ret = rsa_data->mgf(&mgf_data); + if (ret != TEE_SUCCESS) + goto exit_oaep_encrypt; + + /* + * Step h + * maskedSeed = seed xor seedMask + */ + mod_op.n.length = maskedSeed.length; + mod_op.a.data = seed.data; + mod_op.a.length = seed.length; + mod_op.b.data = maskedSeed.data; + mod_op.b.length = maskedSeed.length; + mod_op.result.data = maskedSeed.data; + mod_op.result.length = maskedSeed.length; + + ret = drvcrypt_xor_mod_n(&mod_op); + if (ret != TEE_SUCCESS) + goto exit_oaep_encrypt; + + RSA_DUMPBUF("EM", EM.data, EM.length); + + /* + * Last Encryption of the EM of modulus size to Cipher + */ + memcpy(&enc_data, rsa_data, sizeof(enc_data)); + + enc_data.message.data = EM.data; + enc_data.message.length = EM.length; + + ret = do_caam_encrypt(&enc_data, RSA_ENCRYPT(NO)); + +exit_oaep_encrypt: + caam_free_buf(&DB); + caam_free_buf(&seed); + caam_free_buf(&dbMask); + caam_free_buf(&EM); + + return ret; +} + +/* + * CAAM RSA Encryption of the input message to a cipher + * + * @rsa_data [in/out] RSA Data to encrypt + * @operation CAAM RSA Encryption operation + */ +static TEE_Result do_caam_encrypt(struct drvcrypt_rsa_ed *rsa_data, + uint32_t operation) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_rsa_keypair key = { }; + struct caamdmaobj msg = { }; + struct caamdmaobj cipher = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + uint32_t pdb_sgt_flags = 0; + + RSA_TRACE("RSA Encrypt mode %d", rsa_data->rsa_id); + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(MAX_DESC_ENC); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto exit_encrypt; + } + + /* + * Convert TEE rsa key type to CAAM rsa key type + * Push key value to memory + */ + retstatus = do_keypub_conv(&key, rsa_data->key.key); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_encrypt; + } + + /* + * ReAllocate the cipher result buffer with a maximum size + * of the Key Modulus's size (N) if not cache aligned + */ + ret = caam_dmaobj_output_sgtbuf(&cipher, rsa_data->cipher.data, + rsa_data->cipher.length, key.n.length); + if (ret) + goto exit_encrypt; + + if (cipher.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_RSA_ENC_SGT_G; + + caam_dmaobj_cache_push(&cipher); + + /* Prepare the input message CAAM descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&msg, rsa_data->message.data, + rsa_data->message.length); + if (ret) + goto exit_encrypt; + + if (msg.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_RSA_ENC_SGT_F; + + caam_dmaobj_cache_push(&msg); + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PDB_RSA_ENC_E_SIZE(key.e.length) | + PDB_RSA_ENC_N_SIZE(key.n.length) | + pdb_sgt_flags); + caam_desc_add_ptr(desc, msg.sgtbuf.paddr); + caam_desc_add_ptr(desc, cipher.sgtbuf.paddr); + caam_desc_add_ptr(desc, key.n.paddr); + caam_desc_add_ptr(desc, key.e.paddr); + caam_desc_add_word(desc, PDB_RSA_ENC_F_SIZE(rsa_data->message.length)); + caam_desc_add_word(desc, operation); + + /* Set the descriptor Header with length */ + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + RSA_DUMPDESC(desc); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + rsa_data->cipher.length = caam_dmaobj_copy_to_orig(&cipher); + + RSA_DUMPBUF("Output", rsa_data->cipher.data, + rsa_data->cipher.length); + ret = caam_status_to_tee_result(retstatus); + } else { + RSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +exit_encrypt: + caam_free_desc(&desc); + do_keypair_free(&key); + caam_dmaobj_free(&msg); + caam_dmaobj_free(&cipher); + + return ret; +} + +/* + * CAAM RSA Decryption of the input cipher to a message + * + * @rsa_data [in/out] RSA Data to decrypt + * @operation CAAM RSA Decryption operation + */ +static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data, + uint32_t operation) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_rsa_keypair key = { }; + struct caamdmaobj cipher = { }; + struct caamdmaobj msg = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + uint32_t pdb_sgt_flags = 0; + struct caambuf size_msg = { }; + struct caambuf tmp = { }; + + RSA_TRACE("RSA Decrypt mode %d", rsa_data->rsa_id); + + /* + * Convert TEE rsa key type to CAAM rsa key type + * Push key value to memory + */ + retstatus = do_keypair_conv(&key, rsa_data->key.key); + if (retstatus != CAAM_NO_ERROR) { + RSA_TRACE("do_keypair_conv returned 0x%" PRIx32, retstatus); + ret = caam_status_to_tee_result(retstatus); + goto exit_decrypt; + } + + /* + * Allocate the temporary result buffer with a maximum size + * of the Key Modulus's size (N) + */ + ret = caam_dmaobj_output_sgtbuf(&msg, rsa_data->message.data, + rsa_data->message.length, key.n.length); + + if (ret) + goto exit_decrypt; + + if (msg.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_RSA_DEC_SGT_F; + + caam_dmaobj_cache_push(&msg); + + /* Allocate the returned computed size when PKCS V1.5 */ + if (operation == RSA_DECRYPT(PKCS_V1_5)) { + retstatus = caam_alloc_align_buf(&size_msg, 4); + if (retstatus != CAAM_NO_ERROR) + goto exit_decrypt; + + cache_operation(TEE_CACHEFLUSH, size_msg.data, size_msg.length); + } + + /* Prepare the input cipher CAAM descriptor entry */ + ret = caam_dmaobj_input_sgtbuf(&cipher, rsa_data->cipher.data, + rsa_data->cipher.length); + + if (cipher.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_RSA_DEC_SGT_G; + + caam_dmaobj_cache_push(&cipher); + + /* Allocate the job descriptor function of the Private key format */ + switch (key.format) { + case RSA_PRIVATE_KEY_FORMAT_1: + desc = caam_calloc_desc(MAX_DESC_DEC_1); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto exit_decrypt; + } + break; + + case RSA_PRIVATE_KEY_FORMAT_2: + case RSA_PRIVATE_KEY_FORMAT_3: + if (key.format == RSA_PRIVATE_KEY_FORMAT_2) + desc = caam_calloc_desc(MAX_DESC_DEC_2); + else + desc = caam_calloc_desc(MAX_DESC_DEC_3); + + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto exit_decrypt; + } + /* Allocate temporary buffers used by the CAAM */ + retstatus = + caam_alloc_align_buf(&tmp, key.p.length + key.q.length); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto exit_decrypt; + } + + cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length); + break; + + default: + ret = TEE_ERROR_GENERIC; + goto exit_decrypt; + } + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + /* Build the descriptor function of the Private Key format */ + switch (key.format) { + case RSA_PRIVATE_KEY_FORMAT_1: + caam_desc_add_word(desc, + PDB_RSA_DEC_D_SIZE(key.d.length) | + PDB_RSA_DEC_N_SIZE(key.n.length) | + pdb_sgt_flags); + caam_desc_add_ptr(desc, cipher.sgtbuf.paddr); + caam_desc_add_ptr(desc, msg.sgtbuf.paddr); + caam_desc_add_ptr(desc, key.n.paddr); + caam_desc_add_ptr(desc, key.d.paddr); + + break; + + case RSA_PRIVATE_KEY_FORMAT_2: + caam_desc_add_word(desc, + PDB_RSA_DEC_D_SIZE(key.d.length) | + PDB_RSA_DEC_N_SIZE(key.n.length) | + pdb_sgt_flags); + caam_desc_add_ptr(desc, cipher.sgtbuf.paddr); + caam_desc_add_ptr(desc, msg.sgtbuf.paddr); + caam_desc_add_ptr(desc, key.d.paddr); + caam_desc_add_ptr(desc, key.p.paddr); + caam_desc_add_ptr(desc, key.q.paddr); + caam_desc_add_ptr(desc, tmp.paddr); + caam_desc_add_ptr(desc, tmp.paddr + key.p.length); + caam_desc_add_word(desc, + PDB_RSA_DEC_Q_SIZE(key.q.length) | + PDB_RSA_DEC_P_SIZE(key.p.length)); + break; + + case RSA_PRIVATE_KEY_FORMAT_3: + caam_desc_add_word(desc, PDB_RSA_DEC_N_SIZE(key.n.length) | + pdb_sgt_flags); + caam_desc_add_ptr(desc, cipher.sgtbuf.paddr); + caam_desc_add_ptr(desc, msg.sgtbuf.paddr); + caam_desc_add_ptr(desc, key.qp.paddr); + caam_desc_add_ptr(desc, key.p.paddr); + caam_desc_add_ptr(desc, key.q.paddr); + caam_desc_add_ptr(desc, key.dp.paddr); + caam_desc_add_ptr(desc, key.dq.paddr); + caam_desc_add_ptr(desc, tmp.paddr); + caam_desc_add_ptr(desc, tmp.paddr + key.p.length); + caam_desc_add_word(desc, + PDB_RSA_DEC_Q_SIZE(key.q.length) | + PDB_RSA_DEC_P_SIZE(key.p.length)); + break; + + default: + ret = TEE_ERROR_GENERIC; + goto exit_decrypt; + } + + /* Set the Decryption operation type */ + caam_desc_add_word(desc, operation | PROT_RSA_DEC_KEYFORM(key.format)); + + if (operation == RSA_DECRYPT(PKCS_V1_5)) { + /* Get the PPKCS1 v1.5 Message length generated */ + caam_desc_add_word(desc, + ST_NOIMM_OFF(CLASS_DECO, REG_MATH0, 4, 4)); + caam_desc_add_ptr(desc, size_msg.paddr); + /* Set the descriptor Header with length */ + desclen = caam_desc_get_len(desc); +#ifdef CFG_CAAM_64BIT + caam_desc_update_hdr(desc, + DESC_HEADER_IDX(desclen, desclen - 1 - 3)); +#else + caam_desc_update_hdr(desc, + DESC_HEADER_IDX(desclen, desclen - 1 - 2)); +#endif /* CFG_CAAM_64BIT */ + } else { + desclen = caam_desc_get_len(desc); + /* Set the descriptor Header with length */ + caam_desc_update_hdr(desc, + DESC_HEADER_IDX(desclen, desclen - 1)); + } + + RSA_DUMPDESC(desc); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus != CAAM_NO_ERROR) { + RSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + goto exit_decrypt; + } + + if (operation == RSA_DECRYPT(NO) && + rsa_data->rsa_id == DRVCRYPT_RSA_NOPAD) { + rsa_data->message.length = caam_dmaobj_copy_ltrim_to_orig(&msg); + } else { + if (operation == RSA_DECRYPT(PKCS_V1_5)) { + /* PKCS 1 v1.5 */ + cache_operation(TEE_CACHEINVALIDATE, size_msg.data, + size_msg.length); + + /* Check if the original buffer size is large enough */ + if (msg.orig.length < caam_read_val32(size_msg.data)) { + rsa_data->message.length = + caam_read_val32(size_msg.data); + ret = TEE_ERROR_SHORT_BUFFER; + goto exit_decrypt; + } + + msg.orig.length = caam_read_val32(size_msg.data); + RSA_TRACE("New length %zu", msg.orig.length); + } + + rsa_data->message.length = caam_dmaobj_copy_to_orig(&msg); + } + + RSA_DUMPBUF("Output", rsa_data->message.data, rsa_data->message.length); + ret = TEE_SUCCESS; + +exit_decrypt: + caam_free_desc(&desc); + do_keypair_free(&key); + caam_free_buf(&size_msg); + caam_dmaobj_free(&msg); + caam_dmaobj_free(&cipher); + + caam_free_buf(&tmp); + + return ret; +} + +/* + * RSA Encryption + * + * @rsa_data [in/out] RSA Data to encrypt / Cipher resulting + */ +static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + + switch (rsa_data->rsa_id) { + case DRVCRYPT_RSA_NOPAD: + case DRVCRYPT_RSASSA_PKCS_V1_5: + case DRVCRYPT_RSASSA_PSS: + ret = do_caam_encrypt(rsa_data, RSA_ENCRYPT(NO)); + break; + + case DRVCRYPT_RSA_PKCS_V1_5: + ret = do_caam_encrypt(rsa_data, RSA_ENCRYPT(PKCS_V1_5)); + break; + + case DRVCRYPT_RSA_OAEP: + ret = do_oaep_encoding(rsa_data); + break; + + default: + break; + } + + return ret; +} + +/* + * RSA Decryption + * + * @rsa_data [in/out] RSA Data to decrypt / Message resulting + */ +static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + + switch (rsa_data->rsa_id) { + case DRVCRYPT_RSA_NOPAD: + case DRVCRYPT_RSASSA_PKCS_V1_5: + case DRVCRYPT_RSASSA_PSS: + ret = do_caam_decrypt(rsa_data, RSA_DECRYPT(NO)); + break; + + case DRVCRYPT_RSA_PKCS_V1_5: + ret = do_caam_decrypt(rsa_data, RSA_DECRYPT(PKCS_V1_5)); + break; + + case DRVCRYPT_RSA_OAEP: + ret = do_oaep_decoding(rsa_data); + break; + + default: + break; + } + + return ret; +} + +/* + * Registration of the RSA Driver + */ +static const struct drvcrypt_rsa driver_rsa = { + .alloc_keypair = do_allocate_keypair, + .alloc_publickey = do_allocate_publickey, + .free_publickey = do_free_publickey, + .free_keypair = do_free_keypair, + .gen_keypair = do_gen_keypair, + .encrypt = do_encrypt, + .decrypt = do_decrypt, + .optional.ssa_sign = NULL, + .optional.ssa_verify = NULL, +}; + +enum caam_status caam_rsa_init(struct caam_jrcfg *caam_jrcfg) +{ + enum caam_status retstatus = CAAM_FAILURE; + vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; + + if (caam_hal_ctrl_pknum(jr_base)) { + caam_era = caam_hal_ctrl_era(jr_base); + RSA_TRACE("CAAM Era %d", caam_era); + + if (!drvcrypt_register_rsa(&driver_rsa)) + retstatus = CAAM_NO_ERROR; + } + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/local.h b/optee/optee_os/core/drivers/crypto/caam/acipher/local.h new file mode 100644 index 0000000..60b6fbc --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/local.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * CAAM Cipher Local header. + */ +#ifndef __LOCAL_H__ +#define __LOCAL_H__ + +#include "caam_common.h" + +/* + * Prime generator structure for RSA + */ +struct prime_data_rsa { + uint8_t era; /* CAAM Era version */ + size_t key_size; /* Key size in bits */ + struct caambuf *e; /* Key exponent e */ + struct caambuf *p; /* Prime p */ + struct caambuf *q; /* Prime q (can be NULL of only p asked) */ +}; + +/* + * Generate prime numbers for RSA + * Algorithm based on the Chapter B.3.3 of the FIPS.184-6 specification + * + * @data [in/out] Prime generation data + */ +enum caam_status caam_prime_rsa_gen(struct prime_data_rsa *data); + +/* + * Prime generator structure for DSA + */ +struct prime_data_dsa { + struct caambuf *g; /* Generator g */ + struct caambuf *p; /* Prime p */ + struct caambuf *q; /* Prime q */ +}; + +/* + * Generate prime numbers for DSA + * Algorithm based on the Chapter A.1.2 of the FIPS.186-4 specification + * + * @data [in/out] Prime generation data + */ +enum caam_status caam_prime_dsa_gen(struct prime_data_dsa *data); + +#endif /* __LOCAL_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/acipher/sub.mk b/optee/optee_os/core/drivers/crypto/caam/acipher/sub.mk new file mode 100644 index 0000000..ada3830 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/acipher/sub.mk @@ -0,0 +1,7 @@ +incdirs-y += ../include + +srcs-$(CFG_NXP_CAAM_RSA_DRV) += caam_rsa.c caam_prime_rsa.c +srcs-$(CFG_NXP_CAAM_DH_DRV) += caam_dh.c +srcs-$(CFG_NXP_CAAM_ECC_DRV) += caam_ecc.c +srcs-$(CFG_NXP_CAAM_DSA_DRV) += caam_dsa.c caam_prime_dsa.c +srcs-$(CFG_NXP_CAAM_MATH_DRV) += caam_math.c \ No newline at end of file diff --git a/optee/optee_os/core/drivers/crypto/caam/blob/caam_blob.c b/optee/optee_os/core/drivers/crypto/caam/blob/caam_blob.c new file mode 100644 index 0000000..5898e40 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/blob/caam_blob.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020 Pengutronix, Rouven Czerwinski + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MKVB_SIZE 32 + +static uint8_t stored_key[MKVB_SIZE]; +static bool mkvb_retrieved; + +enum caam_status caam_blob_mkvb_init(vaddr_t baseaddr) +{ + struct caam_jobctx jobctx = { }; + enum caam_status res = CAAM_NO_ERROR; + struct caambuf buf = { }; + uint32_t *desc = NULL; + + assert(!mkvb_retrieved); + + res = caam_calloc_align_buf(&buf, MKVB_SIZE); + if (res != CAAM_NO_ERROR) + goto out; + + desc = caam_calloc_desc(8); + if (!desc) { + res = CAAM_OUT_MEMORY; + goto out_buf; + } + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, SEQ_OUT_PTR(32)); + caam_desc_add_ptr(desc, buf.paddr); + caam_desc_add_word(desc, BLOB_MSTR_KEY); + BLOB_DUMPDESC(desc); + + cache_operation(TEE_CACHEFLUSH, buf.data, buf.length); + + jobctx.desc = desc; + res = caam_jr_enqueue(&jobctx, NULL); + + if (res != CAAM_NO_ERROR) { + BLOB_TRACE("JR return code: %#"PRIx32, res); + BLOB_TRACE("MKVB failed: Job status %#"PRIx32, jobctx.status); + } else { + cache_operation(TEE_CACHEINVALIDATE, buf.data, MKVB_SIZE); + BLOB_DUMPBUF("MKVB", buf.data, buf.length); + memcpy(&stored_key, buf.data, buf.length); + mkvb_retrieved = true; + } + +out_buf: + caam_free_desc(&desc); + caam_free_buf(&buf); +out: + caam_hal_ctrl_inc_priblob(baseaddr); + + return res; +} + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + COMPILE_TIME_ASSERT(sizeof(hwkey->data) <= sizeof(stored_key)); + + if (!mkvb_retrieved) + return TEE_ERROR_SECURITY; + + memcpy(&hwkey->data, &stored_key, sizeof(hwkey->data)); + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/blob/sub.mk b/optee/optee_os/core/drivers/crypto/caam/blob/sub.mk new file mode 100644 index 0000000..1c234f4 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/blob/sub.mk @@ -0,0 +1,3 @@ +srcs-y += caam_blob.c + +incdirs-y += ../include diff --git a/optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c b/optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c new file mode 100644 index 0000000..b72508f --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_ctrl.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2021 NXP + * + * Brief CAAM Global Controller. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Crypto driver initialization */ +static TEE_Result crypto_driver_init(void) +{ + TEE_Result retresult = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jrcfg jrcfg = {}; + + /* Enable the CAAM Clock */ + caam_hal_clk_enable(true); + + /* Set OTP as master key if the platform is closed */ + if (snvs_is_device_closed()) { + retresult = imx_snvs_set_master_otpmk(); + if (retresult && retresult != TEE_ERROR_NOT_IMPLEMENTED) + goto exit_init; + } + + retstatus = caam_hal_cfg_get_conf(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_NOT_SUPPORTED; + goto exit_init; + } + + /* Initialize the CAAM Controller */ + caam_hal_ctrl_init(jrcfg.base); + + /* Initialize the Job Ring to be used */ + retstatus = caam_jr_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the RNG Module */ + retstatus = caam_rng_init(jrcfg.base); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the Hash Module */ + retstatus = caam_hash_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the MATH Module */ + retstatus = caam_math_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the RSA Module */ + retstatus = caam_rsa_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the Cipher Module */ + retstatus = caam_cipher_init(jrcfg.base); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the HMAC Module */ + retstatus = caam_hmac_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the BLOB Module */ + retstatus = caam_blob_mkvb_init(jrcfg.base); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the CMAC Module */ + retstatus = caam_cmac_init(jrcfg.base); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the ECC Module */ + retstatus = caam_ecc_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the DH Module */ + retstatus = caam_dh_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the DSA Module */ + retstatus = caam_dsa_init(&jrcfg); + if (retstatus != CAAM_NO_ERROR) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Initialize the Manufacturing Protection Module */ + retstatus = caam_mp_init(jrcfg.base); + if (retstatus != CAAM_NO_ERROR && retstatus != CAAM_NOT_SUPPORTED) { + retresult = TEE_ERROR_GENERIC; + goto exit_init; + } + + /* Everything is OK, register the Power Management handler */ + caam_pwr_init(); + + /* + * Configure Job Rings to NS World + * If the Driver Crypto is not used CFG_NXP_CAAM_RUNTIME_JR is not + * enable, hence relax the JR used for the CAAM configuration to + * the Non-Secure + */ + if (jrcfg.base) + caam_hal_cfg_setup_nsjobring(&jrcfg); + + retresult = TEE_SUCCESS; +exit_init: + if (retresult != TEE_SUCCESS) { + EMSG("CAAM Driver initialization (0x%" PRIx32 ")", retresult); + panic(); + } + + return retresult; +} + +early_init(crypto_driver_init); + +/* Crypto driver late initialization to complete on-going CAAM operations */ +static TEE_Result init_caam_late(void) +{ + enum caam_status ret = CAAM_BUSY; + + ret = caam_jr_complete(); + + if (ret != CAAM_NO_ERROR) { + EMSG("CAAM initialization failed"); + panic(); + } + + return TEE_SUCCESS; +} + +early_init_late(init_caam_late); diff --git a/optee/optee_os/core/drivers/crypto/caam/caam_desc.c b/optee/optee_os/core/drivers/crypto/caam/caam_desc.c new file mode 100644 index 0000000..361e1aa --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_desc.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019, 2021 NXP + * + * Brief Descriptor construction functions. + */ +#include +#include +#include +#include + +struct ptr_addr { +#ifdef CFG_CAAM_BIG_ENDIAN + uint32_t high; + uint32_t low; +#else + uint32_t low; + uint32_t high; +#endif /* CFG_CAAM_BIG_ENDIAN */ +}; + +uint32_t caam_desc_get_len(uint32_t *desc) +{ + return GET_JD_DESCLEN(caam_read_val32((void *)desc)); +} + +void caam_desc_init(uint32_t *desc) +{ + *desc = 0; +} + +void caam_desc_update_hdr(uint32_t *desc, uint32_t word) +{ + /* Update first word of desc */ + caam_write_val32((void *)desc, word); +} + +void caam_desc_add_word(uint32_t *desc, uint32_t word) +{ + uint32_t len = caam_desc_get_len(desc); + uint32_t *last = desc + len; + + /* Add Word at Last */ + caam_write_val32((void *)last, word); + + /* Increase the length */ + caam_write_val32((void *)desc, caam_read_val32((void *)desc) + 1); +} + +void caam_desc_add_ptr(uint32_t *desc, paddr_t ptr) +{ + uint32_t len = caam_desc_get_len(desc); + uint32_t *last = desc + len; + uint32_t inc = 1; + + /* Add Word at Last */ +#ifdef CFG_CAAM_64BIT + struct ptr_addr *ptr_addr = (struct ptr_addr *)(uintptr_t)last; + +#ifdef CFG_ARM64_core + caam_write_val32(&ptr_addr->high, ptr >> 32); +#else + caam_write_val32(&ptr_addr->high, 0); +#endif /* CFG_ARM64_core */ + caam_write_val32(&ptr_addr->low, ptr); + inc++; +#else + caam_write_val32((void *)last, ptr); +#endif /* CFG_CAAM_64BIT */ + + /* Increase the length */ + caam_write_val32((void *)desc, caam_read_val32((void *)desc) + inc); +} + +#ifdef CFG_CAAM_64BIT +void caam_desc_push(struct caam_inring_entry *in_entry, paddr_t paddr) +{ +#ifdef CFG_CAAM_BIG_ENDIAN + put_be64(&in_entry->desc, paddr); +#else + put_le64(&in_entry->desc, paddr); +#endif /* CFG_CAAM_BIG_ENDIAN */ +} + +paddr_t caam_desc_pop(struct caam_outring_entry *out_entry) +{ + const uintptr_t v_desc = (uintptr_t)&out_entry->desc; + const uint32_t *a32 = (const uint32_t *)v_desc; + +#ifdef CFG_CAAM_BIG_ENDIAN + return SHIFT_U64(get_be32(&a32[0]), 32) | get_be32(&a32[1]); +#else + return SHIFT_U64(a32[1], 32) | a32[0]; +#endif /* CFG_CAAM_BIG_ENDIAN */ +} +#else /* CFG_CAAM_64BIT */ +void caam_desc_push(struct caam_inring_entry *in_entry, paddr_t paddr) +{ + caam_write_val32(&in_entry->desc, paddr); +} + +paddr_t caam_desc_pop(struct caam_outring_entry *out_entry) +{ + return caam_read_val32(&out_entry->desc); +} +#endif /* CFG_CAAM_64BIT */ + +uint32_t caam_read_jobstatus(struct caam_outring_entry *out) +{ + return caam_read_val32(&out->status); +} + +void caam_desc_add_dmaobj(uint32_t *desc, struct caamdmaobj *data, + unsigned int pre_op) +{ + uint32_t operation = pre_op; + size_t op_length = 0; + uint32_t op_ext_length = 0; + + if (data->sgtbuf.sgt_type) + operation |= CMD_SGT; + + /* Check the operation length to set extension length or not */ + switch (GET_CMD_TYPE(pre_op)) { + case CMD_FIFO_LOAD_TYPE: + op_length = FIFO_LOAD_LENGTH(data->sgtbuf.length); + op_ext_length = FIFO_LOAD_EXT; + break; + + case CMD_STORE_TYPE: + /* Note: there is extension length for the STORE command */ + op_length = STORE_LENGTH(data->sgtbuf.length); + break; + + case CMD_FIFO_STORE_TYPE: + op_length = FIFO_STORE_LENGTH(data->sgtbuf.length); + op_ext_length = FIFO_STORE_EXT; + break; + + case CMD_KEY_TYPE: + /* Note: there is extension length for the KEY command */ + op_length = KEY_LENGTH(data->sgtbuf.length); + break; + + case CMD_SEQ_OUT_TYPE: + op_length = SEQ_LENGTH(data->sgtbuf.length); + op_ext_length = SEQ_EXT; + break; + + default: + break; + } + + if (op_length == data->sgtbuf.length) + operation |= op_length; + else + operation |= op_ext_length; + + caam_desc_add_word(desc, operation); + caam_desc_add_ptr(desc, data->sgtbuf.paddr); + + if (op_length != data->sgtbuf.length) + caam_desc_add_word(desc, data->sgtbuf.length); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/caam_jr.c b/optee/optee_os/core/drivers/crypto/caam/caam_jr.c new file mode 100644 index 0000000..eeb64f0 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_jr.c @@ -0,0 +1,684 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Job Rings manager. + * Implementation of functions to enqueue/dequeue CAAM Job Descriptor + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Job Free define + */ +#define JR_JOB_FREE 0 + +/* + * Caller information context object + */ +struct caller_info { + struct caam_jobctx *jobctx; /* Caller job context object */ + uint32_t job_id; /* Current Job ID */ + paddr_t pdesc; /* Physical address of the descriptor */ +}; + +/* + * Job Ring module private data + */ +struct jr_privdata { + vaddr_t baseaddr; /* Job Ring base address */ + + vaddr_t ctrladdr; /* CAAM virtual base address */ + paddr_t jroffset; /* Job Ring address offset */ + uint64_t paddr_inrings; /* CAAM physical addr of input queue */ + uint64_t paddr_outrings; /* CAAM physical addr of output queue */ + + uint8_t nb_jobs; /* Number of Job ring entries managed */ + + /* Input Job Ring Variables */ + struct caam_inring_entry *inrings; /* Input JR HW queue */ + unsigned int inlock; /* Input JR spin lock */ + uint16_t inwrite_index; /* SW Index - next JR entry free */ + + /* Output Job Ring Variables */ + struct caam_outring_entry *outrings; /* Output JR HW queue */ + unsigned int outlock; /* Output JR spin lock */ + uint16_t outread_index; /* SW Index - next JR output done */ + + /* Caller Information Variables */ + struct caller_info *callers; /* Job Ring Caller information */ + unsigned int callers_lock; /* Job Ring Caller spin lock */ + + struct itr_handler it_handler; /* Interrupt handler */ +}; + +/* + * Job Ring module private data reference + */ +static struct jr_privdata *jr_privdata; + +/* + * Free module resources + * + * @jr_priv Reference to the module private data + */ +static void do_jr_free(struct jr_privdata *jr_priv) +{ + if (jr_priv) { + caam_free(jr_priv->inrings); + caam_free(jr_priv->outrings); + caam_free(jr_priv->callers); + caam_free(jr_priv); + } +} + +/* + * Allocate module resources + * + * @privdata [out] Allocated Job Ring private data + * @nb_jobs Number of jobs to manage in the queue + */ +static enum caam_status do_jr_alloc(struct jr_privdata **privdata, + uint8_t nb_jobs) +{ + enum caam_status retstatus = CAAM_OUT_MEMORY; + struct jr_privdata *jr_priv = NULL; + + /* Allocate the Job Ring private data */ + jr_priv = caam_calloc(sizeof(*jr_priv)); + + if (!jr_priv) { + JR_TRACE("Private Data allocation error"); + goto end_alloc; + } + + /* Setup the number of jobs */ + jr_priv->nb_jobs = nb_jobs; + + /* Allocate the input and output job ring queues */ + jr_priv->inrings = + caam_calloc_align(nb_jobs * sizeof(struct caam_inring_entry)); + jr_priv->outrings = + caam_calloc_align(nb_jobs * sizeof(struct caam_outring_entry)); + + /* Allocate the callers information */ + jr_priv->callers = caam_calloc(nb_jobs * sizeof(struct caller_info)); + + if (!jr_priv->inrings || !jr_priv->outrings || !jr_priv->callers) { + JR_TRACE("JR resources allocation error"); + goto end_alloc; + } + + /* Initialize the spin locks */ + jr_priv->inlock = SPINLOCK_UNLOCK; + jr_priv->outlock = SPINLOCK_UNLOCK; + jr_priv->callers_lock = SPINLOCK_UNLOCK; + + /* Initialize the queue counter */ + jr_priv->inwrite_index = 0; + jr_priv->outread_index = 0; + + /* + * Ensure that allocated queue initialization is pushed to the physical + * memory + */ + cache_operation(TEE_CACHEFLUSH, jr_priv->inrings, + nb_jobs * sizeof(struct caam_inring_entry)); + cache_operation(TEE_CACHEFLUSH, jr_priv->outrings, + nb_jobs * sizeof(struct caam_outring_entry)); + + retstatus = CAAM_NO_ERROR; +end_alloc: + if (retstatus != CAAM_NO_ERROR) + do_jr_free(jr_priv); + else + *privdata = jr_priv; + + return retstatus; +} + +/* + * Job Ring Interrupt handler + * + * @handler Interrupt Handler structure + */ +static enum itr_return caam_jr_irqhandler(struct itr_handler *handler) +{ + JR_TRACE("Disable the interrupt"); + itr_disable(handler->it); + + /* Send a signal to exit WFE loop */ + sev(); + + return ITRR_HANDLED; +} + +/* + * Returns all jobs completed depending on the input @wait_job_ids mask. + * + * Dequeues all Jobs completed. Call the job context callback + * function. Function returns the bit mask of the expected completed job + * (@wait_job_ids parameter) + * + * @wait_job_ids Expected Jobs to be complete + */ +static uint32_t do_jr_dequeue(uint32_t wait_job_ids) +{ + uint32_t ret_job_id = 0; + struct caller_info *caller = NULL; + struct caam_outring_entry *jr_out = NULL; + struct caam_jobctx *jobctx = NULL; + uint32_t exceptions = 0; + bool found = false; + uint16_t idx_jr = 0; + uint32_t nb_jobs_done = 0; + size_t nb_jobs_inv = 0; + + exceptions = cpu_spin_lock_xsave(&jr_privdata->outlock); + + nb_jobs_done = caam_hal_jr_get_nbjob_done(jr_privdata->baseaddr); + + if (nb_jobs_done == 0) { + cpu_spin_unlock_xrestore(&jr_privdata->outlock, exceptions); + return ret_job_id; + } + + /* Ensure that output ring descriptor entries are not in cache */ + if ((jr_privdata->outread_index + nb_jobs_done) > + jr_privdata->nb_jobs) { + /* + * Invalidate the whole circular job buffer because some + * completed job rings are at the beginning of the buffer + */ + jr_out = jr_privdata->outrings; + nb_jobs_inv = jr_privdata->nb_jobs; + } else { + /* Invalidate only the completed job */ + jr_out = &jr_privdata->outrings[jr_privdata->outread_index]; + nb_jobs_inv = nb_jobs_done; + } + + cache_operation(TEE_CACHEINVALIDATE, jr_out, + sizeof(struct caam_outring_entry) * nb_jobs_inv); + + for (; nb_jobs_done; nb_jobs_done--) { + jr_out = &jr_privdata->outrings[jr_privdata->outread_index]; + + /* + * Lock the caller information array because enqueue is + * also touching it + */ + cpu_spin_lock(&jr_privdata->callers_lock); + for (idx_jr = 0, found = false; idx_jr < jr_privdata->nb_jobs; + idx_jr++) { + /* + * Search for the caller information corresponding to + * the completed JR. + * Don't use the outread_index or inwrite_index because + * completion can be out of order compared to input + * buffer + */ + caller = &jr_privdata->callers[idx_jr]; + if (caam_desc_pop(jr_out) == caller->pdesc) { + jobctx = caller->jobctx; + jobctx->status = caam_read_jobstatus(jr_out); + + /* Update return Job IDs mask */ + if (caller->job_id & wait_job_ids) + ret_job_id |= caller->job_id; + + JR_TRACE("JR id=%" PRId32 + ", context @0x%08" PRIxVA, + caller->job_id, (vaddr_t)jobctx); + /* Clear the Entry Descriptor DMA */ + caller->pdesc = 0; + caller->jobctx = NULL; + caller->job_id = JR_JOB_FREE; + found = true; + JR_TRACE("Free space #%" PRId16 + " in the callers array", + idx_jr); + break; + } + } + cpu_spin_unlock(&jr_privdata->callers_lock); + + /* + * Remove the JR from the output list even if no + * JR caller found + */ + caam_hal_jr_del_job(jr_privdata->baseaddr); + + /* + * Increment index to next JR output entry taking care that + * it is a circular buffer of nb_jobs size. + */ + jr_privdata->outread_index++; + jr_privdata->outread_index %= jr_privdata->nb_jobs; + + if (found && jobctx->callback) { + /* Finally, execute user's callback */ + jobctx->callback(jobctx); + } + } + + cpu_spin_unlock_xrestore(&jr_privdata->outlock, exceptions); + + return ret_job_id; +} + +/* + * Enqueues a new job in the Job Ring input queue. Keep the caller's + * job context in private array. + * + * @jobctx Caller's job context + * @job_id [out] Job ID enqueued + */ +static enum caam_status do_jr_enqueue(struct caam_jobctx *jobctx, + uint32_t *job_id) +{ + enum caam_status retstatus = CAAM_BUSY; + struct caam_inring_entry *cur_inrings = NULL; + struct caller_info *caller = NULL; + uint32_t exceptions = 0; + uint32_t job_mask = 0; + uint8_t idx_jr = 0; + bool found = false; + + exceptions = cpu_spin_lock_xsave(&jr_privdata->inlock); + + caam_hal_clk_enable(true); + + /* + * Stay locked until a job is available + * Check if there is an available JR index in the HW + */ + while (caam_hal_jr_read_nbslot_available(jr_privdata->baseaddr) == 0) { + /* + * WFE will return thanks to a SEV generated by the + * interrupt handler or by a spin_unlock + */ + wfe(); + }; + + /* + * There is a space free in the input ring but it doesn't mean + * that the job pushed is completed. + * Completion is out of order. Look for a free space in the + * caller data to push them and get a job ID for the completion + * + * Lock the caller information array because dequeue is + * also touching it + */ + cpu_spin_lock(&jr_privdata->callers_lock); + for (idx_jr = 0; idx_jr < jr_privdata->nb_jobs; idx_jr++) { + if (jr_privdata->callers[idx_jr].job_id == JR_JOB_FREE) { + JR_TRACE("Found a space #%" PRId8 + " free in the callers array", + idx_jr); + job_mask = 1 << idx_jr; + + /* Store the caller information for the JR completion */ + caller = &jr_privdata->callers[idx_jr]; + caller->job_id = job_mask; + caller->jobctx = jobctx; + caller->pdesc = virt_to_phys((void *)jobctx->desc); + + found = true; + break; + } + } + cpu_spin_unlock(&jr_privdata->callers_lock); + + if (!found) { + JR_TRACE("Error didn't find a free space in the callers array"); + goto end_enqueue; + } + + JR_TRACE("Push id=%" PRId16 ", job (0x%08" PRIx32 + ") context @0x%08" PRIxVA, + jr_privdata->inwrite_index, job_mask, (vaddr_t)jobctx); + + cur_inrings = &jr_privdata->inrings[jr_privdata->inwrite_index]; + + /* Push the descriptor into the JR HW list */ + caam_desc_push(cur_inrings, caller->pdesc); + + /* Ensure that physical memory is up to date */ + cache_operation(TEE_CACHECLEAN, cur_inrings, + sizeof(struct caam_inring_entry)); + + /* + * Increment index to next JR input entry taking care that + * it is a circular buffer of nb_jobs size. + */ + jr_privdata->inwrite_index++; + jr_privdata->inwrite_index %= jr_privdata->nb_jobs; + + /* Ensure that input descriptor is pushed in physical memory */ + cache_operation(TEE_CACHECLEAN, jobctx->desc, + DESC_SZBYTES(caam_desc_get_len(jobctx->desc))); + + /* Inform HW that a new JR is available */ + caam_hal_jr_add_newjob(jr_privdata->baseaddr); + + *job_id = job_mask; + retstatus = CAAM_NO_ERROR; + +end_enqueue: + cpu_spin_unlock_xrestore(&jr_privdata->inlock, exceptions); + + return retstatus; +} + +/* + * Synchronous job completion callback + * + * @jobctx Job context + */ +static void job_done(struct caam_jobctx *jobctx) +{ + jobctx->completion = true; +} + +void caam_jr_cancel(uint32_t job_id) +{ + unsigned int idx = 0; + + cpu_spin_lock(&jr_privdata->callers_lock); + + JR_TRACE("Job cancel 0x%" PRIx32, job_id); + for (idx = 0; idx < jr_privdata->nb_jobs; idx++) { + /* + * Search for the caller information corresponding to + * the job_id mask. + */ + if (jr_privdata->callers[idx].job_id == job_id) { + /* Clear the Entry Descriptor */ + jr_privdata->callers[idx].pdesc = 0; + jr_privdata->callers[idx].jobctx = NULL; + jr_privdata->callers[idx].job_id = JR_JOB_FREE; + return; + } + } + + cpu_spin_unlock(&jr_privdata->callers_lock); +} + +enum caam_status caam_jr_dequeue(uint32_t job_ids, unsigned int timeout_ms) +{ + uint32_t job_complete = 0; + uint32_t nb_loop = 0; + bool infinite = false; + bool it_active = false; + + if (timeout_ms == UINT_MAX) + infinite = true; + else + nb_loop = timeout_ms * 100; + + do { + /* Call the do_jr_dequeue function to dequeue the jobs */ + job_complete = do_jr_dequeue(job_ids); + + /* Check if new job has been submitted and acknowledge it */ + it_active = caam_hal_jr_check_ack_itr(jr_privdata->baseaddr); + + if (job_complete & job_ids) + return CAAM_NO_ERROR; + + /* Check if JR interrupt otherwise wait a bit */ + if (!it_active) + caam_udelay(10); + } while (infinite || (nb_loop--)); + + return CAAM_TIMEOUT; +} + +enum caam_status caam_jr_enqueue(struct caam_jobctx *jobctx, uint32_t *job_id) +{ + enum caam_status retstatus = CAAM_FAILURE; + __maybe_unused int timeout = 10; /* Nb loops to pool job completion */ + + if (!jobctx) + return CAAM_BAD_PARAM; + + JR_DUMPDESC(jobctx->desc); + + if (!jobctx->callback && job_id) { + JR_TRACE("Job Callback not defined whereas asynchronous"); + return CAAM_BAD_PARAM; + } + + if (jobctx->callback && !job_id) { + JR_TRACE("Job Id not defined whereas asynchronous"); + return CAAM_BAD_PARAM; + } + + jobctx->completion = false; + jobctx->status = 0; + + /* + * If parameter job_id is NULL, the job is synchronous, hence use + * the local job_done callback function + */ + if (!jobctx->callback && !job_id) { + jobctx->callback = job_done; + jobctx->context = jobctx; + } + + retstatus = do_jr_enqueue(jobctx, &jobctx->id); + + if (retstatus != CAAM_NO_ERROR) { + JR_TRACE("enqueue job error 0x%08x", retstatus); + return retstatus; + } + + /* + * If parameter job_id is defined, the job is asynchronous, so + * returns with setting the job_id value + */ + if (job_id) { + *job_id = jobctx->id; + return CAAM_PENDING; + } + +#ifdef TIMEOUT_COMPLETION + /* + * Job is synchronous wait until job completion or timeout + */ + while (!jobctx->completion && timeout--) + caam_jr_dequeue(jobctx->id, 100); + + if (timeout <= 0) { + /* Job timeout, cancel it and return in error */ + caam_jr_cancel(jobctx->id); + retstatus = CAAM_TIMEOUT; + } else { + if (JRSTA_SRC_GET(jobctx->status) != JRSTA_SRC(NONE)) + retstatus = CAAM_JOB_STATUS; + else + retstatus = CAAM_NO_ERROR; + } +#else + /* + * Job is synchronous wait until job complete + * Don't use a timeout because there is no HW timer and + * so the timeout is not precise + */ + while (!jobctx->completion) + caam_jr_dequeue(jobctx->id, 100); + + if (JRSTA_SRC_GET(jobctx->status) != JRSTA_SRC(NONE)) + retstatus = CAAM_JOB_STATUS; + else + retstatus = CAAM_NO_ERROR; +#endif + + /* Erase local callback function */ + jobctx->callback = NULL; + + return retstatus; +} + +enum caam_status caam_jr_init(struct caam_jrcfg *jrcfg) +{ + enum caam_status retstatus = CAAM_FAILURE; + + JR_TRACE("Initialization"); + + /* Allocate the Job Ring resources */ + retstatus = do_jr_alloc(&jr_privdata, jrcfg->nb_jobs); + if (retstatus != CAAM_NO_ERROR) + goto end_init; + + jr_privdata->ctrladdr = jrcfg->base; + jr_privdata->jroffset = jrcfg->offset; + + retstatus = + caam_hal_jr_setowner(jrcfg->base, jrcfg->offset, JROWN_ARM_S); + JR_TRACE("JR setowner returned 0x%x", retstatus); + + if (retstatus != CAAM_NO_ERROR) + goto end_init; + + jr_privdata->baseaddr = jrcfg->base + jrcfg->offset; + retstatus = caam_hal_jr_reset(jr_privdata->baseaddr); + if (retstatus != CAAM_NO_ERROR) + goto end_init; + + /* + * Get the physical address of the Input/Output queue + * The HW configuration is 64 bits registers regardless + * the CAAM or CPU addressing mode. + */ + jr_privdata->paddr_inrings = virt_to_phys(jr_privdata->inrings); + jr_privdata->paddr_outrings = virt_to_phys(jr_privdata->outrings); + if (!jr_privdata->paddr_inrings || !jr_privdata->paddr_outrings) { + JR_TRACE("JR bad queue pointers"); + retstatus = CAAM_FAILURE; + goto end_init; + } + + caam_hal_jr_config(jr_privdata->baseaddr, jr_privdata->nb_jobs, + jr_privdata->paddr_inrings, + jr_privdata->paddr_outrings); + + /* + * Prepare the interrupt handler to secure the interrupt even + * if the interrupt is not used + */ + jr_privdata->it_handler.it = jrcfg->it_num; + jr_privdata->it_handler.flags = ITRF_TRIGGER_LEVEL; + jr_privdata->it_handler.handler = caam_jr_irqhandler; + jr_privdata->it_handler.data = jr_privdata; + +#if defined(CFG_NXP_CAAM_RUNTIME_JR) && defined(CFG_CAAM_ITR) + itr_add(&jr_privdata->it_handler); +#endif + caam_hal_jr_enable_itr(jr_privdata->baseaddr); + + retstatus = CAAM_NO_ERROR; + +end_init: + if (retstatus != CAAM_NO_ERROR) + do_jr_free(jr_privdata); + + return retstatus; +} + +enum caam_status caam_jr_halt(void) +{ + enum caam_status retstatus = CAAM_FAILURE; + __maybe_unused uint32_t job_complete = 0; + + retstatus = caam_hal_jr_halt(jr_privdata->baseaddr); + + /* + * All jobs in the input queue have been done, call the + * dequeue function to complete them. + */ + job_complete = do_jr_dequeue(UINT32_MAX); + JR_TRACE("Completion of jobs mask 0x%" PRIx32, job_complete); + + return retstatus; +} + +enum caam_status caam_jr_flush(void) +{ + enum caam_status retstatus = CAAM_FAILURE; + __maybe_unused uint32_t job_complete = 0; + + retstatus = caam_hal_jr_flush(jr_privdata->baseaddr); + + /* + * All jobs in the input queue have been done, call the + * dequeue function to complete them. + */ + job_complete = do_jr_dequeue(UINT32_MAX); + JR_TRACE("Completion of jobs mask 0x%" PRIx32, job_complete); + + return retstatus; +} + +void caam_jr_resume(uint32_t pm_hint) +{ + if (pm_hint == PM_HINT_CONTEXT_STATE) { +#ifndef CFG_NXP_CAAM_RUNTIME_JR + /* + * In case the CAAM is not used the JR used to + * instantiate the RNG has been released to Non-Secure + * hence, need reconfigure the Secure JR and release + * it after RNG instantiation + */ + caam_hal_jr_setowner(jr_privdata->ctrladdr, + jr_privdata->jroffset, JROWN_ARM_S); + + caam_hal_jr_config(jr_privdata->baseaddr, jr_privdata->nb_jobs, + jr_privdata->paddr_inrings, + jr_privdata->paddr_outrings); +#endif /* CFG_NXP_CAAM_RUNTIME_JR */ + + /* Read the current job ring index */ + jr_privdata->inwrite_index = + caam_hal_jr_input_index(jr_privdata->baseaddr); + /* Read the current output ring index */ + jr_privdata->outread_index = + caam_hal_jr_output_index(jr_privdata->baseaddr); + + if (caam_rng_instantiation() != CAAM_NO_ERROR) + panic(); + +#ifndef CFG_NXP_CAAM_RUNTIME_JR + caam_hal_jr_setowner(jr_privdata->ctrladdr, + jr_privdata->jroffset, JROWN_ARM_NS); +#endif /* CFG_NXP_CAAM_RUNTIME_JR */ + } else { + caam_hal_jr_resume(jr_privdata->baseaddr); + } +} + +enum caam_status caam_jr_complete(void) +{ + enum caam_status ret = CAAM_BUSY; + + ret = caam_hal_jr_flush(jr_privdata->baseaddr); + if (ret == CAAM_NO_ERROR) + caam_hal_jr_resume(jr_privdata->baseaddr); + + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/caam_pwr.c b/optee/optee_os/core/drivers/crypto/caam/caam_pwr.c new file mode 100644 index 0000000..d5a6ed4 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_pwr.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019, 2021, 2023 NXP + * + * Brief CAAM Power state management. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static SLIST_HEAD(, + backup_data) data_list = SLIST_HEAD_INITIALIZER(backup_data); + +void caam_pwr_add_backup(vaddr_t baseaddr, const struct reglist *regs, + size_t nbentries) +{ + struct backup_data *newelem = NULL; + struct backup_data *elem = NULL; + uint32_t idx = 0; + uint32_t nbregs = 0; + + newelem = malloc(sizeof(*newelem)); + if (!newelem) + panic(); + + /* Count the number of registers to save/restore */ + for (idx = 0; idx < nbentries; idx++) + nbregs += regs[idx].nbregs; + + newelem->baseaddr = baseaddr; + newelem->nbentries = nbentries; + newelem->regs = regs; + newelem->val = malloc(nbregs * sizeof(*newelem->val)); + + if (!newelem->val) + panic(); + + /* Add the new backup data element at the end of the list */ + elem = SLIST_FIRST(&data_list); + if (elem) { + while (SLIST_NEXT(elem, next)) + elem = SLIST_NEXT(elem, next); + + SLIST_INSERT_AFTER(elem, newelem, next); + } else { + SLIST_INSERT_HEAD(&data_list, newelem, next); + } +} + +/* Backup all registers present in the data_list */ +static void do_save_regs(void) +{ + struct backup_data *elem = NULL; + const struct reglist *reg = NULL; + uint32_t idx = 0; + uint32_t validx = 0; + uint32_t regidx = 0; + + SLIST_FOREACH(elem, &data_list, next) { + reg = elem->regs; + validx = 0; + for (idx = 0; idx < elem->nbentries; idx++, reg++) { + for (regidx = 0; regidx < reg->nbregs; + regidx++, validx++) { + elem->val[validx] = + io_caam_read32(elem->baseaddr + + reg->offset + + (4 * regidx)); + elem->val[validx] &= ~reg->mask_clr; + + PWR_TRACE("Save @0x%" PRIxPTR "=0x%" PRIx32, + elem->baseaddr + reg->offset + + 4 * regidx, + elem->val[validx]); + } + } + } +} + +/* Restore all registers present in the data_list */ +static void do_restore_regs(void) +{ + struct backup_data *elem = NULL; + const struct reglist *reg = NULL; + uint32_t idx = 0; + uint32_t validx = 0; + uint32_t regidx = 0; + + SLIST_FOREACH(elem, &data_list, next) { + reg = elem->regs; + validx = 0; + for (idx = 0; idx < elem->nbentries; idx++, reg++) { + for (regidx = 0; regidx < reg->nbregs; + regidx++, validx++) { + PWR_TRACE("Restore @0x%" PRIxPTR "=0x%" PRIx32, + elem->baseaddr + reg->offset + + 4 * regidx, + elem->val[validx]); + io_caam_write32(elem->baseaddr + reg->offset + + 4 * regidx, + elem->val[validx] | + reg->mask_set); + } + } + } +} + +/* + * CAAM Power state preparation/entry + * + * @pm_hint Power mode type + */ +static TEE_Result pm_enter(uint32_t pm_hint) +{ + enum caam_status ret = CAAM_BUSY; + + PWR_TRACE("CAAM power mode %" PRIu32 " entry", pm_hint); + + if (pm_hint == PM_HINT_CLOCK_STATE) { + ret = caam_jr_halt(); + } else if (pm_hint == PM_HINT_CONTEXT_STATE) { + do_save_regs(); + ret = caam_jr_flush(); + } + + if (ret == CAAM_NO_ERROR) + return TEE_SUCCESS; + else + return TEE_ERROR_GENERIC; +} + +/* + * CAAM Power state resume + * + * @pm_hint Power mode type + */ +static TEE_Result pm_resume(uint32_t pm_hint) +{ + enum caam_status ret = CAAM_FAILURE; + + PWR_TRACE("CAAM power mode %" PRIu32 " resume", pm_hint); + if (pm_hint == PM_HINT_CONTEXT_STATE) { + caam_hal_clk_enable(true); + do_restore_regs(); + } + + caam_jr_resume(pm_hint); + + ret = caam_mp_resume(pm_hint); + + return caam_status_to_tee_result(ret); +} + +/* + * Power Management Callback function executed when system enter or resume + * from a power mode + * + * @op Operation mode SUSPEND/RESUME + * @pm_hint Power mode type + * @pm_handle Driver private handle (not used) + */ +static TEE_Result +pm_enter_resume(enum pm_op op, uint32_t pm_hint, + const struct pm_callback_handle *pm_handle __unused) +{ + if (op == PM_OP_SUSPEND) + return pm_enter(pm_hint); + else + return pm_resume(pm_hint); +} + +void caam_pwr_init(void) +{ + register_pm_driver_cb(pm_enter_resume, NULL, "caam_pwr"); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/caam_rng.c b/optee/optee_os/core/drivers/crypto/caam/caam_rng.c new file mode 100644 index 0000000..fa81c22 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/caam_rng.c @@ -0,0 +1,570 @@ +// SPDX-License-Identifier: BSD-2-Clause +/** + * Copyright 2017-2021 NXP + * + * Brief CAAM Random Number Generator manager. + * Implementation of RNG functions. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Define the RNG Data buffer size and number + */ +#define RNG_DATABUF_SIZE 1024 +#define RNG_DATABUF_NB 2 + +/* + * Define the number of descriptor entry to generate random data + */ +#define RNG_GEN_DESC_ENTRIES 5 + +/* + * Status of the data generation + */ +enum rngsta { + DATA_EMPTY = 0, /* Data bufer empty */ + DATA_ONGOING, /* Data generation on going */ + DATA_FAILURE, /* Error during data generation */ + DATA_OK, /* Data generation complete with success */ +}; + +/* + * RNG Data generation + */ +struct rngdata { + struct caam_jobctx jobctx; /* Job Ring Context */ + uint32_t job_id; /* Job Id enqueued */ + + uint8_t *data; /* Random Data buffer */ + size_t size; /* Size in bytes of the Random data buffer */ + size_t rdindex; /* Current data index in the buffer */ + + enum rngsta status; /* Status of the data generation */ +}; + +/* + * RNG module private data + */ +struct rng_privdata { + vaddr_t baseaddr; /* RNG base address */ + bool instantiated; /* RNG instantiated */ + struct rngdata databuf[RNG_DATABUF_NB]; /* RNG Data generation */ + uint8_t dataidx; /* Current RNG Data buffer */ +}; + +static struct rng_privdata *rng_privdata; + +/* Allocate and initialize module private data */ +static enum caam_status do_allocate(void) +{ + struct rngdata *rngdata = NULL; + unsigned int idx = 0; + + /* Allocate the Module resources */ + rng_privdata = caam_calloc(sizeof(*rng_privdata)); + if (!rng_privdata) { + RNG_TRACE("Private Data allocation error"); + return CAAM_OUT_MEMORY; + } + + rng_privdata->instantiated = false; + + /* Allocates the RNG Data Buffers */ + for (idx = 0; idx < RNG_DATABUF_NB; idx++) { + rngdata = &rng_privdata->databuf[idx]; + rngdata->data = caam_calloc_align(RNG_DATABUF_SIZE); + if (!rngdata->data) + return CAAM_OUT_MEMORY; + + rngdata->size = RNG_DATABUF_SIZE; + rngdata->jobctx.desc = caam_calloc_desc(RNG_GEN_DESC_ENTRIES); + if (!rngdata->jobctx.desc) + return CAAM_OUT_MEMORY; + } + + return CAAM_NO_ERROR; +} + +/* Free module private data */ +static void do_free(void) +{ + struct rngdata *rng = NULL; + unsigned int idx = 0; + + if (rng_privdata) { + for (idx = 0; idx < RNG_DATABUF_NB; idx++) { + rng = &rng_privdata->databuf[idx]; + + /* Check if there is a Job ongoing to cancel it */ + if (atomic_load_u32(&rng->status) == DATA_ONGOING) + caam_jr_cancel(rng->job_id); + + caam_free_desc(&rng->jobctx.desc); + caam_free(rng->data); + rng->data = NULL; + } + + caam_free(rng_privdata); + rng_privdata = NULL; + } +} + +#ifdef CFG_NXP_CAAM_RNG_DRV +/* + * RNG data generation job ring callback completion + * + * @jobctx RNG data JR Job Context + */ +static void rng_data_done(struct caam_jobctx *jobctx) +{ + struct rngdata *rng = jobctx->context; + + RNG_TRACE("RNG Data id 0x%08" PRIx32 " done with status 0x%" PRIx32, + rng->job_id, jobctx->status); + + if (JRSTA_SRC_GET(jobctx->status) == JRSTA_SRC(NONE)) { + atomic_store_u32(&rng->status, DATA_OK); + + /* Invalidate the data buffer to ensure software gets it */ + cache_operation(TEE_CACHEINVALIDATE, rng->data, rng->size); + } else { + RNG_TRACE("RNG Data completion in error 0x%" PRIx32, + jobctx->status); + atomic_store_u32(&rng->status, DATA_FAILURE); + } + + rng->job_id = 0; + rng->rdindex = 0; +} + +/* + * Prepares the data generation descriptors + * + * @rng Reference to the RNG Data object + */ +static enum caam_status prepare_gen_desc(struct rngdata *rng) +{ + paddr_t paddr = 0; + uint32_t *desc = NULL; + + /* Convert the buffer virtual address to physical address */ + paddr = virt_to_phys(rng->data); + if (!paddr) + return CAAM_FAILURE; + + desc = rng->jobctx.desc; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, RNG_GEN_DATA); + caam_desc_add_word(desc, FIFO_ST(RNG_TO_MEM, rng->size)); + caam_desc_add_ptr(desc, paddr); + + RNG_DUMPDESC(desc); + + /* Prepare the job context */ + rng->jobctx.context = rng; + rng->jobctx.callback = rng_data_done; + return CAAM_NO_ERROR; +} + +/* + * Launches a RNG Data generation + * + * @rng RNG Data context + */ +static enum caam_status do_rng_start(struct rngdata *rng) +{ + enum caam_status ret = CAAM_FAILURE; + + /* Ensure that data buffer is visible from the HW */ + cache_operation(TEE_CACHEFLUSH, rng->data, rng->size); + + rng->job_id = 0; + atomic_store_u32(&rng->status, DATA_EMPTY); + + ret = caam_jr_enqueue(&rng->jobctx, &rng->job_id); + + if (ret == CAAM_PENDING) { + atomic_store_u32(&rng->status, DATA_ONGOING); + ret = CAAM_NO_ERROR; + } else { + RNG_TRACE("RNG Job Ring Error 0x%08x", ret); + atomic_store_u32(&rng->status, DATA_FAILURE); + ret = CAAM_FAILURE; + } + + return ret; +} + +/* Checks if there are random data available */ +static enum caam_status do_check_data(void) +{ + enum caam_status ret = CAAM_FAILURE; + struct rngdata *rng = NULL; + uint32_t wait_jobs = 0; + unsigned int idx = 0; + unsigned int loop = 4; + + /* Check if there is a RNG Job to be run */ + for (idx = 0; idx < RNG_DATABUF_NB; idx++) { + rng = &rng_privdata->databuf[idx]; + if (atomic_load_u32(&rng->status) == DATA_EMPTY) { + RNG_TRACE("Start RNG #%" PRIu32 " data generation", + idx); + ret = do_rng_start(rng); + if (ret != CAAM_NO_ERROR) + return CAAM_FAILURE; + } + } + + /* Check if the current data buffer contains data */ + rng = &rng_privdata->databuf[rng_privdata->dataidx]; + + switch (atomic_load_u32(&rng->status)) { + case DATA_OK: + return CAAM_NO_ERROR; + + case DATA_FAILURE: + return CAAM_FAILURE; + + default: + /* Wait until one of the data buffer completes */ + do { + wait_jobs = 0; + for (idx = 0; idx < RNG_DATABUF_NB; idx++) { + rng = &rng_privdata->databuf[idx]; + wait_jobs |= rng->job_id; + + if (atomic_load_u32(&rng->status) == DATA_OK) { + RNG_TRACE("RNG Data buffer #%" PRIu32 + " ready", + idx); + rng_privdata->dataidx = idx; + return CAAM_NO_ERROR; + } + } + + if (!wait_jobs) { + RNG_TRACE("There are no Data Buffers ongoing"); + return CAAM_FAILURE; + } + + /* Need to wait until one of the jobs completes */ + (void)caam_jr_dequeue(wait_jobs, 100); + } while (loop--); + + break; + } + + return CAAM_FAILURE; +} + +/* + * Return the requested random data + * + * @buf [out] data buffer + * @len number of bytes to returns + */ +static TEE_Result do_rng_read(uint8_t *buf, size_t len) +{ + struct rngdata *rng = NULL; + size_t remlen = len; + uint8_t *rngbuf = buf; + + if (!rng_privdata) { + RNG_TRACE("RNG Driver not initialized"); + return TEE_ERROR_BAD_STATE; + } + + if (!rng_privdata->instantiated) { + RNG_TRACE("RNG Driver not initialized"); + return TEE_ERROR_BAD_STATE; + } + + do { + if (do_check_data() != CAAM_NO_ERROR) { + RNG_TRACE("No Data available or Error"); + return TEE_ERROR_BAD_STATE; + } + + rng = &rng_privdata->databuf[rng_privdata->dataidx]; + RNG_TRACE("Context #%" PRIu8 + " contains %zu data asked %zu (%zu)", + rng_privdata->dataidx, rng->size - rng->rdindex, + remlen, len); + + /* Check that current context data are available */ + if ((rng->size - rng->rdindex) <= remlen) { + /* + * There is no or just enough data available, + * copy all data + */ + RNG_TRACE("Copy all available data"); + memcpy(rngbuf, &rng->data[rng->rdindex], + rng->size - rng->rdindex); + + remlen -= rng->size - rng->rdindex; + rngbuf += rng->size - rng->rdindex; + /* Set the RNG data status as empty */ + atomic_store_u32(&rng->status, DATA_EMPTY); + } else { + /* There is enough data in the current context */ + RNG_TRACE("Copy %zu data", remlen); + memcpy(rngbuf, &rng->data[rng->rdindex], remlen); + rng->rdindex += remlen; + remlen = 0; + } + } while (remlen); + + return TEE_SUCCESS; +} + +/* Initialize the RNG module to generate data */ +static enum caam_status caam_rng_init_data(void) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct rngdata *rng = NULL; + unsigned int idx = 0; + + for (idx = 0; idx < RNG_DATABUF_NB; idx++) { + rng = &rng_privdata->databuf[idx]; + retstatus = prepare_gen_desc(rng); + + if (retstatus != CAAM_NO_ERROR) + break; + } + + return retstatus; +} +#endif /* CFG_NXP_CAAM_RNG_DRV */ + +/* + * Prepares the instantiation descriptor + * + * @nb_sh Number of the State Handle + * @sh_status State Handles status + * @desc Reference to the descriptor + * @desc [out] Descriptor filled + */ +static void prepare_inst_desc(uint32_t nb_sh, uint32_t sh_status, + uint32_t *desc) +{ + bool key_loaded = false; + unsigned int sh_idx = 0; + unsigned int nb_max_sh = nb_sh; + + /* Read the SH and secure key status */ + key_loaded = caam_hal_rng_key_loaded(rng_privdata->baseaddr); + RNG_TRACE("RNG SH Status 0x%08" PRIx32 " - Key Status %" PRId8, + sh_status, key_loaded); + + while (sh_status & BIT(sh_idx)) + sh_idx++; + + RNG_TRACE("Instantiation start at SH%" PRIu32 " (%" PRIu32 ")", sh_idx, + nb_max_sh); + + /* Don't set the descriptor header now */ + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + /* First State Handle to instantiate */ + caam_desc_add_word(desc, RNG_SH_INST(sh_idx)); + + /* Next State Handles */ + for (sh_idx++; sh_idx < nb_max_sh; sh_idx++) { + if (!(sh_status & BIT(sh_idx))) { + /* + * If there is more SH to instantiate, add a wait loop + * followed by a reset of the done status to execute + * next command + */ + caam_desc_add_word(desc, + JUMP_C1_LOCAL(ALL_COND_TRUE, + JMP_COND(NONE), 1)); + caam_desc_add_word(desc, + LD_NOCLASS_IMM(REG_CLEAR_WRITTEN, + sizeof(uint32_t))); + caam_desc_add_word(desc, 0x1); + caam_desc_add_word(desc, RNG_SH_INST(sh_idx)); + } + } + + /* Load the Key if needed */ + if (!key_loaded) { + /* + * Add a wait loop while previous operation not completed, + * followed by a register clear before executing next command + */ + caam_desc_add_word(desc, JUMP_C1_LOCAL(ALL_COND_TRUE, + JMP_COND(NONE), 1)); + caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CLEAR_WRITTEN, + sizeof(uint32_t))); + caam_desc_add_word(desc, 0x1); + caam_desc_add_word(desc, RNG_GEN_SECKEYS); + } + + RNG_DUMPDESC(desc); +} + +enum caam_status caam_rng_instantiation(void) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = {}; + uint32_t *desc = NULL; + uint32_t sh_status = 0; + uint32_t nb_sh = 0; + uint32_t sh_mask = 0; + uint32_t inc_delay = 0; + + RNG_TRACE("RNG Instantation"); + + /* Check if RNG is already instantiated */ + retstatus = caam_hal_rng_instantiated(rng_privdata->baseaddr); + + /* RNG is already instantiated or an error occurred */ + if (retstatus != CAAM_NOT_INIT) + goto end_inst; + + /* + * RNG needs to be instantiated. Allocate and prepare the + * Job Descriptor + */ + + /* Calculate the State Handles bit mask */ + nb_sh = caam_hal_rng_get_nb_sh(rng_privdata->baseaddr); + sh_mask = GENMASK_32(nb_sh - 1, 0); + + /* + * The maximum size of the descriptor is: + * |----------------------| + * | Header | = 1 + * |----------------------| + * | First instantation | = 1 + * |----------------------|------------------------- + * | wait complete | = 1 + * |----------------------| + * | Clear done status | Repeat (nb_sh - 1) + * | | = 2 + * |----------------------| + * | next SH instantation | = 1 + * |----------------------|------------------------- + * | wait complete | = 1 + * |----------------------| + * | Clear done status | = 2 + * | | + * |----------------------| + * | Generate Secure Keys | = 1 + * |----------------------| + * | Pad with a 0 | = 1 + */ + desc = caam_calloc_desc(2 + (nb_sh - 1) * 4 + 4 + 1); + if (!desc) { + RNG_TRACE("Descriptor Allocation error"); + retstatus = CAAM_OUT_MEMORY; + goto end_inst; + } + + jobctx.desc = desc; + + do { + /* Check if all State Handles are instantiated */ + sh_status = caam_hal_rng_get_sh_status(rng_privdata->baseaddr); + if ((sh_status & sh_mask) == sh_mask) { + RNG_TRACE("RNG All SH are instantiated (0x%08" PRIx32 + ")", + sh_status); + retstatus = CAAM_NO_ERROR; + goto end_inst; + } + + if (sh_status == 0) { + retstatus = caam_hal_rng_kick(rng_privdata->baseaddr, + inc_delay); + RNG_TRACE("RNG Kick (inc=%" PRIu32 ") ret 0x%08x", + inc_delay, retstatus); + if (retstatus != CAAM_NO_ERROR) { + retstatus = CAAM_FAILURE; + goto end_inst; + } + inc_delay += 200; + } + + prepare_inst_desc(nb_sh, sh_status, desc); + + retstatus = caam_jr_enqueue(&jobctx, NULL); + RNG_TRACE("RNG Job returned 0x%08x", retstatus); + + if (retstatus != CAAM_NO_ERROR && + retstatus != CAAM_JOB_STATUS) + goto end_inst; + + if (retstatus == CAAM_JOB_STATUS) { + RNG_TRACE("RNG Job status 0x%08" PRIx32, jobctx.status); + if ((JRSTA_SRC_GET(jobctx.status) != JRSTA_SRC(CCB)) || + (JRSTA_CCB_GET_ERR(jobctx.status) != + (JRSTA_CCB_CHAID_RNG | JRSTA_CCB_ERRID_HW))) + retstatus = CAAM_FAILURE; + else + retstatus = CAAM_NO_ERROR; + } + } while (retstatus == CAAM_NO_ERROR); + +end_inst: + if (retstatus == CAAM_NO_ERROR) + rng_privdata->instantiated = true; + + caam_free_desc(&desc); + + RNG_TRACE("RNG Instantiation return 0x%08x", retstatus); + + return retstatus; +} + +enum caam_status caam_rng_init(vaddr_t ctrl_addr) +{ + enum caam_status retstatus = CAAM_FAILURE; + + RNG_TRACE("Initialization"); + retstatus = do_allocate(); + if (retstatus == CAAM_NO_ERROR) { + rng_privdata->baseaddr = ctrl_addr; + retstatus = caam_rng_instantiation(); + } + +#ifdef CFG_NXP_CAAM_RNG_DRV + if (retstatus == CAAM_NO_ERROR) + retstatus = caam_rng_init_data(); +#endif + + if (retstatus != CAAM_NO_ERROR) + do_free(); + + return retstatus; +} + +#ifdef CFG_NXP_CAAM_RNG_DRV +TEE_Result hw_get_random_bytes(void *buf, size_t blen) +{ + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + return do_rng_read(buf, blen); +} + +void plat_rng_init(void) +{ +} +#endif diff --git a/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher.c b/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher.c new file mode 100644 index 0000000..29cb8f4 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher.c @@ -0,0 +1,901 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Implementation of Cipher functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +/* Local Function declaration */ +static TEE_Result do_update_streaming(struct drvcrypt_cipher_update *dupdate); +static TEE_Result do_update_cipher(struct drvcrypt_cipher_update *dupdate); + +/* + * Constants definition of the AES algorithm + */ +static const struct cipheralg aes_alg[] = { + [TEE_CHAIN_MODE_ECB_NOPAD] = { + .type = OP_ALGO(AES) | ALGO_AAI(AES_ECB), + .size_block = TEE_AES_BLOCK_SIZE, + .size_ctx = 0, + .ctx_offset = 0, + .require_key = NEED_KEY1, + .def_key = { .min = 16, .max = 32, .mod = 8 }, + .update = do_update_cipher, + }, + [TEE_CHAIN_MODE_CBC_NOPAD] = { + .type = OP_ALGO(AES) | ALGO_AAI(AES_CBC), + .size_block = TEE_AES_BLOCK_SIZE, + .size_ctx = 2 * sizeof(uint64_t), + .ctx_offset = 0, + .require_key = NEED_KEY1 | NEED_IV, + .def_key = { .min = 16, .max = 32, .mod = 8 }, + .update = do_update_cipher, + }, + [TEE_CHAIN_MODE_CTR] = { + .type = OP_ALGO(AES) | ALGO_AAI(AES_CTR_MOD128), + .size_block = TEE_AES_BLOCK_SIZE, + .size_ctx = 2 * sizeof(uint64_t), + .ctx_offset = 16, + .require_key = NEED_KEY1 | NEED_IV, + .def_key = { .min = 16, .max = 32, .mod = 8 }, + .update = do_update_streaming, + }, + [TEE_CHAIN_MODE_CTS] = { + .type = 0, + }, + [TEE_CHAIN_MODE_XTS] = { + .type = OP_ALGO(AES) | ALGO_AAI(AES_ECB), + .size_block = TEE_AES_BLOCK_SIZE, + .size_ctx = 0, + .ctx_offset = 0, + .require_key = NEED_KEY1 | NEED_KEY2 | NEED_TWEAK, + .def_key = { .min = 16, .max = 32, .mod = 8 }, + .update = caam_cipher_update_xts, + }, +}; + +/* + * Constants definition of the DES algorithm + */ +static const struct cipheralg des_alg[] = { + [TEE_CHAIN_MODE_ECB_NOPAD] = { + .type = OP_ALGO(DES) | ALGO_AAI(DES_ECB), + .size_block = TEE_DES_BLOCK_SIZE, + .size_ctx = 0, + .ctx_offset = 0, + .require_key = NEED_KEY1, + .def_key = { .min = 8, .max = 8, .mod = 8 }, + .update = do_update_cipher, + }, + [TEE_CHAIN_MODE_CBC_NOPAD] = { + .type = OP_ALGO(DES) | ALGO_AAI(DES_CBC), + .size_block = TEE_DES_BLOCK_SIZE, + .size_ctx = sizeof(uint64_t), + .ctx_offset = 0, + .require_key = NEED_KEY1 | NEED_IV, + .def_key = { .min = 8, .max = 8, .mod = 8 }, + .update = do_update_cipher, + }, +}; + +/* + * Constants definition of the DES3 algorithm + */ +static const struct cipheralg des3_alg[] = { + [TEE_CHAIN_MODE_ECB_NOPAD] = { + .type = OP_ALGO(3DES) | ALGO_AAI(DES_ECB), + .size_block = TEE_DES_BLOCK_SIZE, + .size_ctx = 0, + .ctx_offset = 0, + .require_key = NEED_KEY1, + .def_key = { .min = 16, .max = 24, .mod = 8 }, + .update = do_update_cipher, + }, + [TEE_CHAIN_MODE_CBC_NOPAD] = { + /* Triple-DES CBC No Pad */ + .type = OP_ALGO(3DES) | ALGO_AAI(DES_CBC), + .size_block = TEE_DES_BLOCK_SIZE, + .size_ctx = sizeof(uint64_t), + .ctx_offset = 0, + .require_key = NEED_KEY1 | NEED_IV, + .def_key = { .min = 16, .max = 24, .mod = 8 }, + .update = do_update_cipher, + }, +}; + +/* + * Allocate context data and copy input data into + * + * @dst [out] Destination data to allocate and fill + * @src Source of data to copy + */ +static enum caam_status copy_ctx_data(struct caambuf *dst, + struct drvcrypt_buf *src) +{ + enum caam_status ret = CAAM_OUT_MEMORY; + + if (!dst->data) { + /* Allocate the destination buffer */ + ret = caam_alloc_align_buf(dst, src->length); + if (ret != CAAM_NO_ERROR) + return CAAM_OUT_MEMORY; + } + + /* Do the copy */ + memcpy(dst->data, src->data, dst->length); + + /* Push data to physical memory */ + cache_operation(TEE_CACHEFLUSH, dst->data, dst->length); + + return CAAM_NO_ERROR; +} + +/* + * Verify the input key size with the requirements + * + * @def Key requirements + * @size Key size to verify + */ +static enum caam_status do_check_keysize(const struct caamdefkey *def, + size_t size) +{ + if (size >= def->min && size <= def->max && !(size % def->mod)) + return CAAM_NO_ERROR; + + return CAAM_BAD_PARAM; +} + +enum caam_status caam_cipher_block(struct cipherdata *ctx, bool savectx, + uint8_t keyid, bool encrypt, + struct caamdmaobj *src, + struct caamdmaobj *dst) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + uint32_t *desc = ctx->descriptor; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + if (keyid == NEED_KEY1) { + /* Build the descriptor */ + caam_desc_add_word(desc, LD_KEY_PLAIN(CLASS_1, REG, + ctx->key1.length)); + caam_desc_add_ptr(desc, ctx->key1.paddr); + } else if (keyid == NEED_KEY2) { + /* Build the descriptor */ + caam_desc_add_word(desc, LD_KEY_PLAIN(CLASS_1, REG, + ctx->key2.length)); + caam_desc_add_ptr(desc, ctx->key2.paddr); + } + + /* If there is a context register load it */ + if (ctx->ctx.length && ctx->alg->size_ctx) { + caam_desc_add_word(desc, LD_NOIMM_OFF(CLASS_1, REG_CTX, + ctx->ctx.length, + ctx->alg->ctx_offset)); + caam_desc_add_ptr(desc, ctx->ctx.paddr); + /* Operation with the direction */ + caam_desc_add_word(desc, CIPHER_INIT(ctx->alg->type, encrypt)); + } else { + /* Operation with the direction */ + caam_desc_add_word(desc, + CIPHER_INITFINAL(ctx->alg->type, encrypt)); + } + + /* Load the source data if any */ + if (src) { + caam_desc_fifo_load(desc, src, CLASS_1, MSG, LAST_C1); + caam_dmaobj_cache_push(src); + } + + /* Store the output data if any */ + if (dst) { + caam_desc_fifo_store(desc, dst, MSG_DATA); + caam_dmaobj_cache_push(dst); + } + + if (ctx->ctx.length && ctx->alg->size_ctx) { + if (savectx) { + /* Store the context */ + caam_desc_add_word(desc, + ST_NOIMM_OFF(CLASS_1, REG_CTX, + ctx->ctx.length, + ctx->alg->ctx_offset)); + caam_desc_add_ptr(desc, ctx->ctx.paddr); + } + + /* Ensure Context register data are not in cache */ + cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data, + ctx->ctx.length); + } + + CIPHER_DUMPDESC(desc); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus != CAAM_NO_ERROR) { + CIPHER_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32, + retstatus, jobctx.status); + retstatus = CAAM_FAILURE; + } + + return retstatus; +} + +/* + * Checks if the algorithm @algo is supported and returns the + * local algorithm entry in the corresponding cipher array + */ +static const struct cipheralg *get_cipheralgo(uint32_t algo) +{ + unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo); + unsigned int algo_md = TEE_ALG_GET_CHAIN_MODE(algo); + const struct cipheralg *ca = NULL; + + CIPHER_TRACE("Algo id:%" PRId32 " md:%" PRId32, algo_id, algo_md); + + switch (algo_id) { + case TEE_MAIN_ALGO_AES: + if (algo_md < ARRAY_SIZE(aes_alg)) + ca = &aes_alg[algo_md]; + break; + + case TEE_MAIN_ALGO_DES: + if (algo_md < ARRAY_SIZE(des_alg)) + ca = &des_alg[algo_md]; + break; + + case TEE_MAIN_ALGO_DES3: + if (algo_md < ARRAY_SIZE(des3_alg)) + ca = &des3_alg[algo_md]; + break; + + default: + break; + } + + if (ca && ca->type) + return ca; + + return NULL; +} + +/* + * Allocate the SW cipher data context + * + * @ctx [out] Caller context variable + * @algo Algorithm ID of the context + */ +static TEE_Result do_allocate(void **ctx, uint32_t algo) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct cipherdata *cipherdata = NULL; + const struct cipheralg *alg = NULL; + + CIPHER_TRACE("Allocate Algo 0x%" PRIX32 " Context (%p)", algo, ctx); + + alg = get_cipheralgo(algo); + if (!alg) { + CIPHER_TRACE("Algorithm not supported"); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + cipherdata = caam_calloc(sizeof(*cipherdata)); + if (!cipherdata) { + CIPHER_TRACE("Allocation Cipher data error"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + /* Allocate the descriptor */ + cipherdata->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES); + if (!cipherdata->descriptor) { + CIPHER_TRACE("Allocation descriptor error"); + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Setup the Algorithm pointer */ + cipherdata->alg = alg; + + /* Initialize the block buffer */ + cipherdata->blockbuf.max = cipherdata->alg->size_block; + + *ctx = cipherdata; + + return TEE_SUCCESS; + +out: + caam_free_desc(&cipherdata->descriptor); + caam_free(cipherdata); + + return ret; +} + +/* + * Free the internal cipher data context + * + * @ctx Caller context variable or NULL + */ +static void do_free_intern(struct cipherdata *ctx) +{ + CIPHER_TRACE("Free Context (%p)", ctx); + + if (ctx) { + /* Free the descriptor */ + caam_free_desc(&ctx->descriptor); + + /* Free the Key 1 */ + caam_free_buf(&ctx->key1); + + /* Free the Key 2 */ + caam_free_buf(&ctx->key2); + + /* Free the Tweak */ + caam_free_buf(&ctx->tweak); + + /* Free the Context Register */ + caam_free_buf(&ctx->ctx); + + /* Free Temporary buffer */ + caam_free_buf(&ctx->blockbuf.buf); + } +} + +void caam_cipher_free(void *ctx) +{ + CIPHER_TRACE("Free Context (%p)", ctx); + + if (ctx) { + do_free_intern(ctx); + caam_free(ctx); + } +} + +void caam_cipher_copy_state(void *dst_ctx, void *src_ctx) +{ + struct cipherdata *dst = dst_ctx; + struct cipherdata *src = src_ctx; + + CIPHER_TRACE("Copy State context (%p) to (%p)", src_ctx, dst_ctx); + + dst->alg = src->alg; + dst->encrypt = src->encrypt; + + if (src->blockbuf.filled) { + struct caambuf srcdata = { + .data = src->blockbuf.buf.data, + .length = src->blockbuf.filled + }; + caam_cpy_block_src(&dst->blockbuf, &srcdata, 0); + } + + if (src->key1.length) { + struct drvcrypt_buf key1 = { + .data = src->key1.data, + .length = src->key1.length + }; + copy_ctx_data(&dst->key1, &key1); + } + + if (src->key2.length) { + struct drvcrypt_buf key2 = { + .data = src->key2.data, + .length = src->key2.length + }; + copy_ctx_data(&dst->key2, &key2); + } + + if (src->ctx.length) { + struct drvcrypt_buf ctx = { + .data = src->ctx.data, + .length = src->ctx.length + }; + cache_operation(TEE_CACHEINVALIDATE, ctx.data, ctx.length); + copy_ctx_data(&dst->ctx, &ctx); + } + + if (src->tweak.length) { + struct drvcrypt_buf tweak = { + .data = src->tweak.data, + .length = src->tweak.length + }; + copy_ctx_data(&dst->tweak, &tweak); + } +} + +TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + enum caam_status retstatus = CAAM_FAILURE; + struct cipherdata *cipherdata = dinit->ctx; + const struct cipheralg *alg = NULL; + + CIPHER_TRACE("Action %s", dinit->encrypt ? "Encrypt" : "Decrypt"); + + if (!cipherdata) + return ret; + + alg = cipherdata->alg; + + /* Check if all required keys are defined */ + if (alg->require_key & NEED_KEY1) { + if (!dinit->key1.data || !dinit->key1.length) + goto out; + + retstatus = do_check_keysize(&alg->def_key, dinit->key1.length); + if (retstatus != CAAM_NO_ERROR) { + CIPHER_TRACE("Bad Key 1 size"); + goto out; + } + + /* Copy the key 1 */ + retstatus = copy_ctx_data(&cipherdata->key1, &dinit->key1); + CIPHER_TRACE("Copy Key 1 returned 0x%" PRIx32, retstatus); + + if (retstatus != CAAM_NO_ERROR) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + if (alg->require_key & NEED_KEY2) { + if (!dinit->key2.data || !dinit->key2.length) + goto out; + + retstatus = do_check_keysize(&alg->def_key, dinit->key2.length); + if (retstatus != CAAM_NO_ERROR) { + CIPHER_TRACE("Bad Key 2 size"); + goto out; + } + + /* Copy the key 2 */ + retstatus = copy_ctx_data(&cipherdata->key2, &dinit->key2); + CIPHER_TRACE("Copy Key 2 returned 0x%" PRIx32, retstatus); + + if (retstatus != CAAM_NO_ERROR) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + if (alg->require_key & NEED_IV) { + if (!dinit->iv.data || !dinit->iv.length) + goto out; + + if (dinit->iv.length != alg->size_ctx) { + CIPHER_TRACE("Bad IV size %zu (expected %" PRId32 ")", + dinit->iv.length, alg->size_ctx); + goto out; + } + + CIPHER_TRACE("Allocate CAAM Context Register (%" PRId32 + " bytes)", + alg->size_ctx); + + /* Copy the IV into the context register */ + retstatus = copy_ctx_data(&cipherdata->ctx, &dinit->iv); + CIPHER_TRACE("Copy IV returned 0x%" PRIx32, retstatus); + + if (retstatus != CAAM_NO_ERROR) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + if (alg->require_key & NEED_TWEAK) { + /* This is accepted to start with a NULL Tweak */ + if (dinit->iv.length) { + if (dinit->iv.length != alg->size_block) { + CIPHER_TRACE("Bad tweak 2 size"); + goto out; + } + + /* Copy the tweak */ + retstatus = copy_ctx_data(&cipherdata->tweak, + &dinit->iv); + CIPHER_TRACE("Copy Tweak returned 0x%" PRIx32, + retstatus); + + if (retstatus != CAAM_NO_ERROR) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } else { + /* Create tweak 0's */ + if (!cipherdata->tweak.data) { + /* + * Allocate the destination buffer and + * fill it with 0's + */ + ret = caam_calloc_align_buf(&cipherdata->tweak, + alg->size_block); + if (ret != CAAM_NO_ERROR) + goto out; + } else { + /* Fill it with 0's */ + memset(cipherdata->tweak.data, 0, + cipherdata->tweak.length); + } + + /* Push data to physical memory */ + cache_operation(TEE_CACHEFLUSH, cipherdata->tweak.data, + cipherdata->tweak.length); + } + } + + /* Save the operation direction */ + cipherdata->encrypt = dinit->encrypt; + cipherdata->blockbuf.filled = 0; + + ret = TEE_SUCCESS; + +out: + /* Free the internal context in case of error */ + if (ret != TEE_SUCCESS) + do_free_intern(cipherdata); + + return ret; +} + +/* + * Update of the cipher operation in streaming mode, meaning + * doing partial intermediate block. + * If there is a context, the context is saved only when a + * full block is done. + * The partial block (if not the last block) is encrypted or + * decrypted to return the result and it's saved to be concatened + * to next data to rebuild a full block. + * + * @dupdate Data update object + */ +static TEE_Result do_update_streaming(struct drvcrypt_cipher_update *dupdate) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct cipherdata *ctx = dupdate->ctx; + struct caamdmaobj src = { }; + struct caamdmaobj dst = { }; + struct caamblock trash_bck = { }; + size_t fullsize = 0; + size_t size_topost = 0; + size_t size_todo = 0; + size_t size_inmade = 0; + size_t size_done = 0; + size_t offset = 0; + + CIPHER_TRACE("Length=%zu - %s", dupdate->src.length, + ctx->encrypt ? "Encrypt" : "Decrypt"); + + /* Calculate the total data to be handled */ + fullsize = ctx->blockbuf.filled + dupdate->src.length; + CIPHER_TRACE("Fullsize %zu", fullsize); + if (fullsize < ctx->alg->size_block) { + size_topost = dupdate->src.length; + goto end_streaming_post; + } else { + size_topost = fullsize % ctx->alg->size_block; + /* Total size that is a cipher block multiple */ + size_todo = fullsize - size_topost; + size_inmade = size_todo - ctx->blockbuf.filled; + } + + CIPHER_TRACE("FullSize %zu - posted %zu - todo %zu", fullsize, + size_topost, size_todo); + + if (size_todo) { + ret = caam_dmaobj_init_input(&src, dupdate->src.data, + dupdate->src.length); + if (ret) + goto end_streaming; + + ret = caam_dmaobj_init_output(&dst, dupdate->dst.data, + dupdate->dst.length, + dupdate->dst.length); + if (ret) + goto end_streaming; + + ret = caam_dmaobj_prepare(&src, &dst, ctx->alg->size_block); + if (ret) + goto end_streaming; + } + + /* + * Check first if there is some data saved to complete the + * buffer. + */ + if (ctx->blockbuf.filled) { + ret = caam_dmaobj_add_first_block(&src, &ctx->blockbuf); + if (ret) + goto end_streaming; + + ret = caam_dmaobj_add_first_block(&dst, &ctx->blockbuf); + if (ret) + goto end_streaming; + + ctx->blockbuf.filled = 0; + } + + size_done = size_todo; + dupdate->dst.length = 0; + for (offset = 0; size_todo; + offset += size_done, size_todo -= size_done) { + CIPHER_TRACE("Do input %zu bytes (%zu), offset %zu", size_done, + size_todo, offset); + + size_done = size_todo; + ret = caam_dmaobj_sgtbuf_inout_build(&src, &dst, &size_done, + offset, + ctx->alg->size_block); + if (ret) + goto end_streaming; + + retstatus = caam_cipher_block(ctx, true, NEED_KEY1, + ctx->encrypt, &src, &dst); + + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto end_streaming; + } + + dupdate->dst.length += caam_dmaobj_copy_to_orig(&dst); + } + + CIPHER_DUMPBUF("Source", dupdate->src.data, dupdate->src.length); + CIPHER_DUMPBUF("Result", dupdate->dst.data, dupdate->dst.length); + +end_streaming_post: + if (size_topost) { + /* + * Save the input data in the block buffer for next operation + * and prepare the source DMA Object with the overall saved + * data to generate destination bytes. + */ + struct caambuf cpysrc = { + .data = dupdate->src.data, + .length = dupdate->src.length + }; + + caam_dmaobj_free(&src); + caam_dmaobj_free(&dst); + CIPHER_TRACE("Save input data %zu bytes (done %zu) - off %zu", + size_topost, size_inmade, offset); + + size_todo = size_topost + ctx->blockbuf.filled; + + /* + * Prepare the destination DMA Object: + * - Use given destination parameter bytes to return + * - If the previous operation saved data, use a trash + * buffer to do the operation but not use unneeded data. + */ + ret = caam_dmaobj_init_output(&dst, + dupdate->dst.data + size_inmade, + size_topost, size_topost); + if (ret) + goto end_streaming; + + ret = caam_dmaobj_prepare(NULL, &dst, ctx->alg->size_block); + if (ret) + goto end_streaming; + + if (ctx->blockbuf.filled) { + /* + * Because there are some bytes to trash, use + * a block buffer that will be added to the + * destination SGT/Buffer structure to do the + * cipher operation. + */ + ret = caam_alloc_align_buf(&trash_bck.buf, + ctx->blockbuf.filled); + if (ret != CAAM_NO_ERROR) { + CIPHER_TRACE("Allocation Trash Block error"); + goto end_streaming; + } + trash_bck.filled = ctx->blockbuf.filled; + + ret = caam_dmaobj_add_first_block(&dst, &trash_bck); + if (ret) + goto end_streaming; + } + + retstatus = caam_cpy_block_src(&ctx->blockbuf, &cpysrc, + size_inmade); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto end_streaming; + } + + ret = caam_dmaobj_init_input(&src, ctx->blockbuf.buf.data, + ctx->blockbuf.filled); + if (ret) + goto end_streaming; + + ret = caam_dmaobj_prepare(&src, NULL, ctx->alg->size_block); + if (ret) + goto end_streaming; + + /* + * Build input and output DMA Object with the same size. + */ + size_done = size_todo; + ret = caam_dmaobj_sgtbuf_inout_build(&src, &dst, &size_done, 0, + size_todo); + if (ret) + goto end_streaming; + + if (size_todo != size_done) { + CIPHER_TRACE("Invalid end streaming size %zu vs %zu", + size_done, size_todo); + ret = TEE_ERROR_GENERIC; + goto end_streaming; + } + + retstatus = caam_cipher_block(ctx, false, NEED_KEY1, + ctx->encrypt, &src, &dst); + + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto end_streaming; + } + + dupdate->dst.length += caam_dmaobj_copy_to_orig(&dst); + + CIPHER_DUMPBUF("Source", ctx->blockbuf.buf.data, + ctx->blockbuf.filled); + CIPHER_DUMPBUF("Result", dupdate->dst.data + size_inmade, + size_topost); + } + + ret = TEE_SUCCESS; + +end_streaming: + caam_dmaobj_free(&src); + caam_dmaobj_free(&dst); + + /* Free Trash block buffer */ + caam_free_buf(&trash_bck.buf); + + return ret; +} + +/* + * Update of the cipher operation with complete block except + * if last block. Last block can be partial block. + * + * @dupdate Data update object + */ +static TEE_Result do_update_cipher(struct drvcrypt_cipher_update *dupdate) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct cipherdata *ctx = dupdate->ctx; + struct caamdmaobj src = { }; + struct caamdmaobj dst = { }; + size_t offset = 0; + size_t size_todo = 0; + size_t size_done = 0; + + CIPHER_TRACE("Length=%zu - %s", dupdate->src.length, + (ctx->encrypt ? "Encrypt" : "Decrypt")); + + /* + * Check the length of the payload/cipher to be at least + * one or n cipher block. + */ + if (dupdate->src.length < ctx->alg->size_block || + dupdate->src.length % ctx->alg->size_block) { + CIPHER_TRACE("Bad payload/cipher size %zu bytes", + dupdate->src.length); + return TEE_ERROR_BAD_PARAMETERS; + } + + ret = caam_dmaobj_init_input(&src, dupdate->src.data, + dupdate->src.length); + if (ret) + goto end_cipher; + + ret = caam_dmaobj_init_output(&dst, dupdate->dst.data, + dupdate->dst.length, dupdate->dst.length); + if (ret) + goto end_cipher; + + ret = caam_dmaobj_prepare(&src, &dst, ctx->alg->size_block); + if (ret) + goto end_cipher; + + size_todo = dupdate->src.length; + dupdate->dst.length = 0; + for (offset = 0; size_todo; + offset += size_done, size_todo -= size_done) { + size_done = size_todo; + CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done, + offset); + ret = caam_dmaobj_sgtbuf_inout_build(&src, &dst, &size_done, + offset, + ctx->alg->size_block); + if (ret) + goto end_cipher; + + retstatus = caam_cipher_block(ctx, true, NEED_KEY1, + ctx->encrypt, &src, &dst); + + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto end_cipher; + } + + dupdate->dst.length += caam_dmaobj_copy_to_orig(&dst); + } + + ret = TEE_SUCCESS; + +end_cipher: + caam_dmaobj_free(&src); + caam_dmaobj_free(&dst); + + return ret; +} + +/* + * Update of the cipher operation. Call the algorithm update + * function associated. + * + * @dupdate Data update object + */ +static TEE_Result do_update(struct drvcrypt_cipher_update *dupdate) +{ + struct cipherdata *cipherdata = dupdate->ctx; + + return cipherdata->alg->update(dupdate); +} + +/* + * Finalize of the cipher operation + * + * @ctx Caller context variable or NULL + */ +static void do_final(void *ctx __unused) +{ +} + +/* + * Registration of the Cipher Driver + */ +static struct drvcrypt_cipher driver_cipher = { + .alloc_ctx = do_allocate, + .free_ctx = caam_cipher_free, + .init = caam_cipher_initialize, + .update = do_update, + .final = do_final, + .copy_state = caam_cipher_copy_state, +}; + +/* + * Initialize the Cipher module + * + * @ctrl_addr Controller base address + */ +enum caam_status caam_cipher_init(vaddr_t ctrl_addr __unused) +{ + enum caam_status retstatus = CAAM_FAILURE; + + if (drvcrypt_register_cipher(&driver_cipher) == TEE_SUCCESS) + retstatus = CAAM_NO_ERROR; + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_mac.c b/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_mac.c new file mode 100644 index 0000000..511bfc6 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_mac.c @@ -0,0 +1,816 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Implementation of CMAC functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +static TEE_Result do_update_mac(struct drvcrypt_cipher_update *dupdate); +static TEE_Result do_update_cmac(struct drvcrypt_cipher_update *dupdate); + +/* + * Constant definitions of AES MAC algorithms + */ +static const struct cipheralg aes_cbc_mac_alg = { + .type = OP_ALGO(AES) | ALGO_AAI(AES_CBC), + .size_block = TEE_AES_BLOCK_SIZE, + .size_ctx = 2 * sizeof(uint64_t), + .ctx_offset = 0, + .require_key = NEED_KEY1 | NEED_IV, + .def_key = { + .min = 16, + .max = 32, + .mod = 8 + }, + .update = do_update_mac, +}; + +static const struct cipheralg aes_cmac_alg = { + .type = OP_ALGO(AES) | ALGO_AAI(AES_CMAC), + .size_block = TEE_AES_BLOCK_SIZE, + .size_ctx = 4 * sizeof(uint64_t), + .ctx_offset = 0, + .require_key = NEED_KEY1, + .def_key = { + .min = 16, + .max = 32, + .mod = 8 + }, + .update = do_update_cmac, +}; + +/* + * Constant definitions of DES MAC algorithm + */ +static const struct cipheralg des_mac_alg = { + .type = OP_ALGO(DES) | ALGO_AAI(DES_CBC), + .size_block = TEE_DES_BLOCK_SIZE, + .size_ctx = sizeof(uint64_t), + .ctx_offset = 0, + .require_key = NEED_KEY1 | NEED_IV, + .def_key = { + .min = 8, + .max = 8, + .mod = 8 + }, + .update = do_update_mac, +}; + +/* + * Constant definitions of DES3 MAC algorithm + */ +static const struct cipheralg des3_mac_alg = { + .type = OP_ALGO(3DES) | ALGO_AAI(DES_CBC), + .size_block = TEE_DES_BLOCK_SIZE, + .size_ctx = sizeof(uint64_t), + .ctx_offset = 0, + .require_key = NEED_KEY1 | NEED_IV, + .def_key = { + .min = 16, + .max = 24, + .mod = 8 + }, + .update = do_update_mac, +}; + +static const struct crypto_mac_ops cmac_ops; + +/* + * Format the MAC context to keep the reference to the operation driver + */ +struct crypto_mac { + struct crypto_mac_ctx mac_ctx; /* Crypto MAC API context */ + struct cipherdata *ctx; /* CMAC context */ +}; + +/* + * Returns the reference to the driver context + * + * @ctx API context + */ +static struct crypto_mac *to_mac_ctx(struct crypto_mac_ctx *ctx) +{ + assert(ctx && ctx->ops == &cmac_ops); + + return container_of(ctx, struct crypto_mac, mac_ctx); +} + +/* + * Checks if the algorithm @algo is supported and returns the + * local algorithm entry in the corresponding cipher array. + * + * @algo Algorithm ID + */ +static const struct cipheralg *get_macalgo(uint32_t algo) +{ + switch (algo) { + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + return &aes_cbc_mac_alg; + case TEE_ALG_AES_CMAC: + return &aes_cmac_alg; + case TEE_ALG_DES_CBC_MAC_NOPAD: + case TEE_ALG_DES_CBC_MAC_PKCS5: + return &des_mac_alg; + case TEE_ALG_DES3_CBC_MAC_NOPAD: + case TEE_ALG_DES3_CBC_MAC_PKCS5: + return &des3_mac_alg; + default: + return NULL; + } +} + +/* + * MAC update of the cipher operation of complete block except + * if last block. Last block can be partial block. + * + * @dupdate Data update object + */ +static TEE_Result do_update_mac(struct drvcrypt_cipher_update *dupdate) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + enum caam_status retstatus = CAAM_FAILURE; + struct cipherdata *ctx = dupdate->ctx; + struct caamdmaobj src = { }; + struct caamdmaobj dst = { }; + size_t full_size = 0; + size_t size_topost = 0; + size_t size_todo = 0; + size_t size_done = 0; + size_t size_inmade = 0; + size_t offset = 0; + + CIPHER_TRACE("Length=%zu - %s", dupdate->src.length, + ctx->encrypt ? "Encrypt" : "Decrypt"); + + /* Calculate the total data to be handled */ + full_size = ctx->blockbuf.filled + dupdate->src.length; + if (full_size < ctx->alg->size_block) { + size_topost = dupdate->src.length; + } else { + size_topost = full_size % ctx->alg->size_block; + size_inmade = dupdate->src.length - size_topost; + /* Total size that is a cipher block multiple */ + size_todo = full_size - size_topost; + } + + CIPHER_TRACE("FullSize %zu - posted %zu - todo %zu", full_size, + size_topost, size_todo); + + if (!size_todo) { + /* + * There is no complete block to do: + * - either input size + already saved data < block size + * - or no input data and this is the last block + */ + if (dupdate->last) + memcpy(dupdate->dst.data, ctx->ctx.data, + MIN(dupdate->dst.length, ctx->alg->size_ctx)); + + ret = TEE_SUCCESS; + goto end_mac_post; + } + + if (dupdate->src.length) { + ret = caam_dmaobj_init_input(&src, dupdate->src.data, + dupdate->src.length); + if (ret) + goto end_mac; + + ret = caam_dmaobj_prepare(&src, NULL, ctx->alg->size_block); + if (ret) + goto end_mac; + } + + if (dupdate->last) { + ret = caam_dmaobj_output_sgtbuf(&dst, dupdate->dst.data, + dupdate->dst.length, + dupdate->dst.length); + if (ret) + goto end_mac; + + /* Remove a block of data to do the last block */ + if (size_todo > ctx->alg->size_block) + size_todo -= ctx->alg->size_block; + else + size_todo = 0; + } + + /* Check if there is some data saved to complete the buffer */ + if (ctx->blockbuf.filled) { + ret = caam_dmaobj_add_first_block(&src, &ctx->blockbuf); + if (ret) + goto end_mac; + ctx->blockbuf.filled = 0; + } + + size_done = ctx->alg->size_block; + for (offset = 0; size_todo; + offset += size_done, size_todo -= size_done) { + CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done, + offset); + + ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, + ctx->alg->size_block); + if (ret) + goto end_mac; + + if (size_done != ctx->alg->size_block) { + ret = TEE_ERROR_GENERIC; + goto end_mac; + } + + retstatus = caam_cipher_block(ctx, true, NEED_KEY1, true, &src, + NULL); + + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto end_mac; + } + } + + if (dupdate->last) { + CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done, + offset); + + ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, + ctx->alg->size_block); + if (ret) + goto end_mac; + + if (size_done != ctx->alg->size_block) { + ret = TEE_ERROR_GENERIC; + goto end_mac; + } + + retstatus = caam_cipher_block(ctx, true, NEED_KEY1, true, &src, + &dst); + + if (retstatus == CAAM_NO_ERROR) + caam_dmaobj_copy_to_orig(&dst); + + ret = caam_status_to_tee_result(retstatus); + } + +end_mac_post: + if (size_topost) { + struct caambuf cpysrc = { + .data = dupdate->src.data, + .length = dupdate->src.length + }; + + CIPHER_TRACE("Save input data %zu bytes of %zu (%zu)", + size_topost, dupdate->src.length, size_inmade); + + retstatus = caam_cpy_block_src(&ctx->blockbuf, &cpysrc, + size_inmade); + ret = caam_status_to_tee_result(retstatus); + } + +end_mac: + caam_dmaobj_free(&src); + caam_dmaobj_free(&dst); + + return ret; +} + +/* + * Build and run the CMAC descriptor (AES only) + * + * @ctx Cipher Data context + * @src Input data + * @dstbuf [out] Output data if last block + * @last Last block flag + */ +static TEE_Result run_cmac_desc(struct cipherdata *ctx, struct caamdmaobj *src, + struct caamdmaobj *dst, bool last) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + + desc = ctx->descriptor; + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + if (ctx->alg->require_key & NEED_KEY1) { + /* Build the descriptor */ + caam_desc_add_word(desc, LD_KEY_PLAIN(CLASS_1, REG, + ctx->key1.length)); + caam_desc_add_ptr(desc, ctx->key1.paddr); + } + + /* If context already allocated, this is an update */ + if (ctx->ctx.length) { + CIPHER_TRACE("%s operation", last ? "Final" : "Update"); + caam_desc_add_word(desc, LD_NOIMM_OFF(CLASS_1, REG_CTX, + ctx->ctx.length, + ctx->alg->ctx_offset)); + caam_desc_add_ptr(desc, ctx->ctx.paddr); + if (last) + caam_desc_add_word(desc, + CIPHER_FINAL(ctx->alg->type, true)); + else + caam_desc_add_word(desc, + CIPHER_UPDATE(ctx->alg->type, true)); + } else if (last) { + CIPHER_TRACE("Init/Final operation"); + + caam_desc_add_word(desc, + CIPHER_INITFINAL(ctx->alg->type, true)); + } else { + CIPHER_TRACE("Init operation"); + + caam_desc_add_word(desc, CIPHER_INIT(ctx->alg->type, true)); + if (!ctx->ctx.data) { + retstatus = caam_alloc_align_buf(&ctx->ctx, + ctx->alg->size_ctx); + if (retstatus != CAAM_NO_ERROR) + return TEE_ERROR_OUT_OF_MEMORY; + } + } + + /* Check first if there is some pending data from previous updates */ + if (ctx->blockbuf.filled) { + /* Add the temporary buffer */ + if (src) + caam_desc_add_word(desc, + FIFO_LD_EXT(CLASS_1, MSG, NOACTION)); + else + caam_desc_add_word(desc, + FIFO_LD_EXT(CLASS_1, MSG, LAST_C1)); + + caam_desc_add_ptr(desc, ctx->blockbuf.buf.paddr); + caam_desc_add_word(desc, ctx->blockbuf.filled); + + /* Clean the circular buffer data to be loaded */ + cache_operation(TEE_CACHECLEAN, ctx->blockbuf.buf.data, + ctx->blockbuf.filled); + } + + if (src) { + caam_desc_fifo_load(desc, src, CLASS_1, MSG, LAST_C1); + caam_dmaobj_cache_push(src); + } else { + if (last && !ctx->blockbuf.filled) { + /* + * Add the input data of 0 bytes to start + * algorithm by setting the input data size + */ + caam_desc_add_word(desc, + FIFO_LD(CLASS_1, MSG, LAST_C1, 0)); + caam_desc_add_ptr(desc, 0); + } + } + + ctx->blockbuf.filled = 0; + + if (last) { + caam_desc_store(desc, dst, CLASS_1, REG_CTX); + caam_dmaobj_cache_push(dst); + } else { + /* Store the context */ + caam_desc_add_word(desc, ST_NOIMM_OFF(CLASS_1, REG_CTX, + ctx->ctx.length, + ctx->alg->ctx_offset)); + caam_desc_add_ptr(desc, ctx->ctx.paddr); + } + + CIPHER_DUMPDESC(desc); + + /* Invalidate Context register */ + if (ctx->ctx.length) + cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data, + ctx->ctx.length); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + ret = TEE_SUCCESS; + } else { + CIPHER_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + + return ret; +} + +/* + * Update of the CMAC operation of complete block except + * if last block. Last block can be a partial block. + * + * @dupdate Data update object + */ +static TEE_Result do_update_cmac(struct drvcrypt_cipher_update *dupdate) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + enum caam_status retstatus = CAAM_FAILURE; + struct cipherdata *ctx = dupdate->ctx; + size_t full_size = 0; + size_t size_topost = 0; + size_t size_todo = 0; + size_t size_inmade = 0; + size_t size_done = 0; + size_t offset = 0; + struct caamdmaobj src = { }; + struct caamdmaobj dst = { }; + + CIPHER_TRACE("Length=%zu - %s", dupdate->src.length, + dupdate->encrypt ? "Encrypt" : "Decrypt"); + + /* Calculate the total data to be handled */ + full_size = ctx->blockbuf.filled + dupdate->src.length; + if (!dupdate->last) { + /* + * In case there is no data to save and because it's + * not the final operation, ensure that a block of data + * is kept for the final operation. + */ + if (full_size <= ctx->alg->size_block) { + size_topost = dupdate->src.length; + goto end_cmac_post; + } + + size_topost = full_size % ctx->alg->size_block; + + if (!size_topost) + size_topost = ctx->alg->size_block; + + size_inmade = dupdate->src.length - size_topost; + size_todo = full_size - size_topost; + } else { + ret = caam_dmaobj_output_sgtbuf(&dst, dupdate->dst.data, + dupdate->dst.length, + dupdate->dst.length); + if (ret) + goto end_cmac; + + /* + * If there more than one block to do, keep the last + * block to build the CMAC output. + */ + if (full_size > ctx->alg->size_block) { + size_todo = full_size - ctx->alg->size_block; + size_inmade = size_todo - ctx->blockbuf.filled; + } + } + + if (size_inmade) { + ret = caam_dmaobj_init_input(&src, dupdate->src.data, + size_inmade); + if (ret) + goto end_cmac; + + ret = caam_dmaobj_prepare(&src, NULL, ctx->alg->size_block); + if (ret) + goto end_cmac; + } + + CIPHER_TRACE("FullSize %zu - posted %zu - todo %zu", full_size, + size_topost, size_todo); + + for (offset = 0; size_todo; + offset += size_done, size_todo -= size_done) { + /* + * At least one block is to be done. + * At first iteration, we can have less than one block + * data available from previous update operation which + * was not block modulus. + * Remove the previous saved data (blockbuf) from the data to + * take from input data. + * Next iteration, blockbuf will be empty. + */ + size_todo -= ctx->blockbuf.filled; + size_done = size_todo; + + if (size_inmade) { + ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, + ctx->alg->size_block); + if (ret) + goto end_cmac; + + CIPHER_TRACE("Do input %zu bytes, offset %zu", + size_done, offset); + + ret = run_cmac_desc(ctx, &src, NULL, false); + } else { + CIPHER_TRACE("Do saved blockbuf %zu bytes (done = %zu)", + ctx->blockbuf.filled, size_done); + ret = run_cmac_desc(ctx, NULL, NULL, false); + } + + if (ret) + goto end_cmac; + } + + if (dupdate->last) { + if (dupdate->src.length - size_inmade) { + size_done = dupdate->src.length - size_inmade; + ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, + ctx->alg->size_block); + if (ret) + goto end_cmac; + + if (size_done != dupdate->src.length - size_inmade) { + ret = TEE_ERROR_GENERIC; + goto end_cmac; + } + + ret = run_cmac_desc(ctx, &src, &dst, true); + } else { + ret = run_cmac_desc(ctx, NULL, &dst, true); + } + + if (!ret) + caam_dmaobj_copy_to_orig(&dst); + } + +end_cmac_post: + if (size_topost) { + struct caambuf srcbuf = { .data = dupdate->src.data, + .length = dupdate->src.length }; + + CIPHER_TRACE("Post %zu of input len %zu made %zu", size_topost, + srcbuf.length, size_inmade); + + retstatus = caam_cpy_block_src(&ctx->blockbuf, &srcbuf, + size_inmade); + ret = caam_status_to_tee_result(retstatus); + } + +end_cmac: + caam_dmaobj_free(&src); + caam_dmaobj_free(&dst); + + return ret; +} + +/* + * Initialization of the CMAC operation. + * + * @ctx Operation software context + * @key Input key to compute + * @len Key length + */ +static TEE_Result do_cmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, + size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + uint8_t *iv_tmp = NULL; + struct drvcrypt_cipher_init dinit = { }; + struct crypto_mac *mac = to_mac_ctx(ctx); + struct cipherdata *macdata = mac->ctx; + + if (macdata->mode != TEE_CHAIN_MODE_CMAC) { + /* Allocate temporary IV initialize with 0's */ + iv_tmp = caam_calloc(macdata->alg->size_ctx); + if (!iv_tmp) + return TEE_ERROR_OUT_OF_MEMORY; + } else { + /* + * Check if the context register is allocated to free it, + * because in case of CMAC mode, the context register + * is allocated during do_update_cmac() operation if + * necessary. + */ + if (macdata->ctx.data) + caam_free_buf(&macdata->ctx); + } + + macdata->countdata = 0; + + /* Prepare the initialization data */ + dinit.ctx = macdata; + dinit.encrypt = true; + dinit.key1.data = (uint8_t *)key; + dinit.key1.length = len; + dinit.key2.data = NULL; + dinit.key2.length = 0; + dinit.iv.data = iv_tmp; + dinit.iv.length = macdata->alg->size_ctx; + ret = caam_cipher_initialize(&dinit); + + caam_free(iv_tmp); + + return ret; +} + +/* + * Update of the CMAC operation. + * + * @ctx Operation software context + * @data Data to encrypt + * @len Data length + */ +static TEE_Result do_cmac_update(struct crypto_mac_ctx *ctx, + const uint8_t *data, size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct crypto_mac *mac = to_mac_ctx(ctx); + struct cipherdata *macdata = mac->ctx; + struct drvcrypt_cipher_update dupdate = { }; + + /* Prepare the update data */ + dupdate.ctx = macdata; + dupdate.encrypt = true; + dupdate.last = false; + dupdate.src.data = (uint8_t *)data; + dupdate.src.length = len; + dupdate.dst.data = NULL; + dupdate.dst.length = 0; + + ret = macdata->alg->update(&dupdate); + + if (!ret && macdata->mode == TEE_CHAIN_MODE_CBC_MAC_PKCS5) + macdata->countdata += len; + + return ret; +} + +/* + * Finalize the CMAC operation + * + * @ctx Operation software context + * @digest [out] Digest buffer + * @len Digest buffer length + */ +static TEE_Result do_cmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, + size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + uint8_t *pad_src = NULL; + size_t pad_size = 0; + struct crypto_mac *mac = to_mac_ctx(ctx); + struct cipherdata *macdata = mac->ctx; + struct drvcrypt_cipher_update dupdate = { }; + + if (macdata->mode == TEE_CHAIN_MODE_CBC_MAC_PKCS5) { + /* Calculate the last block PAD size */ + pad_size = macdata->alg->size_block - + (macdata->countdata % macdata->alg->size_block); + CIPHER_TRACE("Pad size = %zu", pad_size); + + if (pad_size) { + /* Need to pad the last block */ + pad_src = caam_calloc(pad_size); + if (!pad_src) { + CIPHER_TRACE("Pad src allocation error"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + memset(pad_src, pad_size, pad_size); + } + } + + /* Prepare the update data */ + dupdate.ctx = macdata; + dupdate.encrypt = true; + dupdate.last = true; + dupdate.src.data = pad_src; + dupdate.src.length = pad_size; + dupdate.dst.data = digest; + dupdate.dst.length = MIN(len, macdata->alg->size_block); + + ret = macdata->alg->update(&dupdate); + + caam_free(pad_src); + + return ret; +} + +/* + * Free the software context + * + * @ctx [in/out] Caller context variable + */ +static void do_cmac_free(struct crypto_mac_ctx *ctx) +{ + struct crypto_mac *mac = to_mac_ctx(ctx); + + caam_cipher_free(mac->ctx); + free(mac); +} + +/* + * Copy software CMAC context + * + * @dst_ctx [out] Reference the context destination + * @src_ctx Reference the context source + */ +static void do_cmac_copy_state(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx) +{ + struct crypto_mac *mac_src = to_mac_ctx(src_ctx); + struct crypto_mac *mac_dst = to_mac_ctx(dst_ctx); + struct cipherdata *macdata_dst = mac_dst->ctx; + struct cipherdata *macdata_src = mac_src->ctx; + + caam_cipher_copy_state(macdata_dst, macdata_src); + + macdata_dst->countdata = macdata_src->countdata; + macdata_dst->mode = macdata_src->mode; +} + +/* + * Registration of the CMAC driver + */ +static const struct crypto_mac_ops cmac_ops = { + .init = do_cmac_init, + .update = do_cmac_update, + .final = do_cmac_final, + .free_ctx = do_cmac_free, + .copy_state = do_cmac_copy_state, +}; + +/* + * Allocate the software context + * + * @ctx [out] Caller context variable + * @algo Algorithm ID + */ +static TEE_Result caam_cmac_allocate(struct crypto_mac_ctx **ctx, uint32_t algo) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_mac *mac = NULL; + const struct cipheralg *alg = NULL; + struct cipherdata *macdata = NULL; + + CIPHER_TRACE("Allocate Context (%p) algo %" PRIx32, ctx, algo); + + alg = get_macalgo(algo); + if (!alg) { + CIPHER_TRACE("Algorithm not supported"); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + mac = calloc(1, sizeof(*mac)); + if (!mac) + return TEE_ERROR_OUT_OF_MEMORY; + + macdata = caam_calloc(sizeof(*macdata)); + if (!macdata) { + CIPHER_TRACE("Allocation MAC data error"); + ret = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + /* Allocate the descriptor */ + macdata->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES); + if (!macdata->descriptor) { + CIPHER_TRACE("Allocation descriptor error"); + ret = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + /* Setup the algorithm pointer */ + macdata->alg = alg; + + /* Initialize the block buffer */ + macdata->blockbuf.max = alg->size_block; + + /* Keep the MAC mode */ + macdata->mode = TEE_ALG_GET_CHAIN_MODE(algo); + + mac->mac_ctx.ops = &cmac_ops; + mac->ctx = macdata; + + *ctx = &mac->mac_ctx; + + return TEE_SUCCESS; + +err: + if (macdata) + caam_free_desc(&macdata->descriptor); + + caam_free(macdata); + free(mac); + + return ret; +} + +/* + * Initialize the CMAC module + * + * @ctrl_addr Controller base address + */ +enum caam_status caam_cmac_init(vaddr_t ctrl_addr __unused) +{ + if (drvcrypt_register(CRYPTO_CMAC, &caam_cmac_allocate)) + return CAAM_FAILURE; + + return CAAM_NO_ERROR; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_xts.c b/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_xts.c new file mode 100644 index 0000000..e3c1bde --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/cipher/caam_cipher_xts.c @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Implementation of Cipher XTS functions + */ +#include +#include +#include +#include +#include + +#include "local.h" + +/* + * Galois Multiplication + * + * @buf [in/out] buffer to multiply + */ +static void do_galois_mult(struct caambuf *buf) +{ + size_t idx = 0; + uint8_t tmp = 0; + uint8_t tmptmp = 0; + + for (idx = 0; idx < buf->length; idx++) { + tmptmp = buf->data[idx] >> 7; + buf->data[idx] = (buf->data[idx] << 1) | tmp; + tmp = tmptmp; + } + + if (tmptmp) + buf->data[0] ^= 0x87; +} + +/* + * Tweak a cipher block (XTS mode) + * + * @ctx Cipher context + * @enc_tweak [in/out] Encrypted tweak (Galois multiplication) + * @srcbuf Source data to encrypt/decrypt + * @dstbuf [out] Destination data encrypted/decrypted + * @tmp Temporary data buffer + */ +static TEE_Result do_tweak_block(struct cipherdata *ctx, + struct caambuf *enc_tweak, + struct caambuf *srcbuf, struct caambuf *dstbuf, + struct caamdmaobj *tmp) +{ + enum caam_status retstatus = CAAM_FAILURE; + unsigned int idx = 0; + + /* + * TODO: Optimization by using CAAM to do it with MATH op in the + * operation description + */ + for (idx = 0; idx < ctx->alg->size_block; idx++) + tmp->orig.data[idx] = srcbuf->data[idx] ^ enc_tweak->data[idx]; + + retstatus = caam_cipher_block(ctx, false, NEED_KEY1, ctx->encrypt, tmp, + tmp); + + if (retstatus != CAAM_NO_ERROR) + return caam_status_to_tee_result(retstatus); + + caam_dmaobj_copy_to_orig(tmp); + + for (idx = 0; idx < ctx->alg->size_block; idx++) + dstbuf->data[idx] = tmp->orig.data[idx] ^ enc_tweak->data[idx]; + + /* Galois field multiplication of the tweak */ + do_galois_mult(enc_tweak); + + return TEE_SUCCESS; +} + +TEE_Result caam_cipher_update_xts(struct drvcrypt_cipher_update *dupdate) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct cipherdata *ctx = dupdate->ctx; + struct caambuf tmpsrc = { }; + struct caamdmaobj tmpdst = { }; + struct caamdmaobj tweak = { }; + struct caamdmaobj enc_tweak = { }; + struct caambuf srcbuf = { }; + struct caambuf dstbuf = { }; + size_t idx = 0; + size_t fullsize = 0; + size_t lastblk = 0; + paddr_t psrc = 0; + paddr_t pdst = 0; + + CIPHER_TRACE("Algo AES XTS length=%zu - %s", dupdate->src.length, + ctx->encrypt ? "Encrypt" : " Decrypt"); + + psrc = virt_to_phys(dupdate->src.data); + pdst = virt_to_phys(dupdate->dst.data); + + /* Check the payload/cipher physical addresses */ + if (!psrc || !pdst) { + CIPHER_TRACE("Bad Addr (src %#" PRIxPA ") (dst %#" PRIxPA ")", + psrc, pdst); + return TEE_ERROR_GENERIC; + } + + ret = caam_dmaobj_input_sgtbuf(&tweak, ctx->tweak.data, + ctx->tweak.length); + if (ret) + goto out; + + /* + * First operation is to encrypt the tweak with the key #2 + * Allocate the encrypted tweak buffer + */ + ret = caam_dmaobj_output_sgtbuf(&enc_tweak, NULL, 0, ctx->tweak.length); + if (ret) + goto out; + + ret = caam_dmaobj_output_sgtbuf(&tmpdst, NULL, 0, ctx->alg->size_block); + if (ret) + goto out; + + retstatus = caam_cipher_block(ctx, false, NEED_KEY2, true, &tweak, + &enc_tweak); + if (retstatus != CAAM_NO_ERROR) { + CIPHER_TRACE("Tweak encryption error"); + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + caam_dmaobj_copy_to_orig(&enc_tweak); + + /* + * Encrypt or Decrypt input data. + * Check if the last block is partial or not + * - if last block is partial, rebuild a complete + * block using the penultimate complete block + * encryption/decryption. + * - else do all blocks. + */ + + /* Calculate the number of complete block */ + fullsize = dupdate->src.length; + lastblk = fullsize % ctx->alg->size_block; + fullsize -= lastblk; + + /* One full block is needed */ + if (!fullsize) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (lastblk) + fullsize -= ctx->alg->size_block; + + srcbuf.data = dupdate->src.data; + srcbuf.length = ctx->alg->size_block; + srcbuf.paddr = psrc; + + dstbuf.data = dupdate->dst.data; + dstbuf.length = ctx->alg->size_block; + dstbuf.paddr = pdst; + + for (; fullsize > 0; fullsize -= ctx->alg->size_block) { + CIPHER_TRACE("Tweak block fullsize %zu", fullsize); + ret = do_tweak_block(ctx, &enc_tweak.orig, &srcbuf, &dstbuf, + &tmpdst); + + CIPHER_TRACE("Tweak block ret 0x%" PRIx32, ret); + if (ret) + goto out; + + CIPHER_DUMPBUF("Source", srcbuf.data, srcbuf.length); + CIPHER_DUMPBUF("Dest", dstbuf.data, dstbuf.length); + + /* Increment the source and destination block */ + srcbuf.data += ctx->alg->size_block; + srcbuf.paddr += ctx->alg->size_block; + + dstbuf.data += ctx->alg->size_block; + dstbuf.paddr += ctx->alg->size_block; + } + + if (lastblk) { + CIPHER_TRACE("Last block size is %zu", lastblk); + + /* + * Allocate the temporary buffer containing the + * penultimate block computed + */ + retstatus = caam_alloc_align_buf(&tmpsrc, ctx->alg->size_block); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + if (!ctx->encrypt) { + /* + * In case of decryption, need to multiply + * the tweak first + */ + memcpy(tmpsrc.data, enc_tweak.orig.data, + enc_tweak.orig.length); + do_galois_mult(&tmpsrc); + + ret = do_tweak_block(ctx, &tmpsrc, &srcbuf, + &tmpdst.orig, &tmpdst); + } else { + ret = do_tweak_block(ctx, &enc_tweak.orig, &srcbuf, + &tmpdst.orig, &tmpdst); + } + + CIPHER_TRACE("Tweak penultimate block ret 0x%" PRIx32, ret); + + if (ret) + goto out; + + /* Build the last block and create the last destination block */ + for (idx = 0; idx < lastblk; idx++) { + tmpsrc.data[idx] = + srcbuf.data[ctx->alg->size_block + idx]; + dstbuf.data[ctx->alg->size_block + idx] = + tmpdst.orig.data[idx]; + } + + for (; idx < ctx->alg->size_block; idx++) + tmpsrc.data[idx] = tmpdst.orig.data[idx]; + + ret = do_tweak_block(ctx, &enc_tweak.orig, &tmpsrc, &dstbuf, + &tmpdst); + + CIPHER_TRACE("Tweak last block ret 0x%" PRIx32, ret); + if (ret) + goto out; + + CIPHER_DUMPBUF("Source", tmpsrc.data, tmpsrc.length); + CIPHER_DUMPBUF("Dest", dstbuf.data, dstbuf.length); + } + + /* Finalize by decrypting the tweak back */ + retstatus = caam_cipher_block(ctx, false, NEED_KEY2, false, &enc_tweak, + &tweak); + if (retstatus != CAAM_NO_ERROR) { + CIPHER_TRACE("Tweak decryption error"); + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + caam_dmaobj_copy_to_orig(&tweak); + + ret = TEE_SUCCESS; +out: + caam_free_buf(&tmpsrc); + caam_dmaobj_free(&tmpdst); + caam_dmaobj_free(&tweak); + caam_dmaobj_free(&enc_tweak); + + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/cipher/local.h b/optee/optee_os/core/drivers/crypto/caam/cipher/local.h new file mode 100644 index 0000000..ac0965d --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/cipher/local.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * CAAM Cipher Local header. + */ +#ifndef __LOCAL_H__ +#define __LOCAL_H__ + +#include +#include +#include + +/* + * Definition of the maximum number of CAAM Job descriptor entries + */ +#ifdef CFG_CAAM_64BIT +#define MAX_DESC_ENTRIES 22 +#else +#define MAX_DESC_ENTRIES 16 +#endif + +/* + * Definition of flags tagging which key(s) is required + */ +#define NEED_KEY1 BIT(0) +#define NEED_KEY2 BIT(1) +#define NEED_IV BIT(2) +#define NEED_TWEAK BIT(3) + +/* + * Cipher Algorithm definition + */ +struct cipheralg { + uint32_t type; /* Algo type for operation */ + uint8_t size_block; /* Computing block size */ + uint8_t size_ctx; /* CAAM Context Register size */ + uint8_t ctx_offset; /* CAAM Context Register offset */ + uint8_t require_key; /* Tag defining key(s) required */ + struct caamdefkey def_key; /* Key size accepted */ + + TEE_Result (*update)(struct drvcrypt_cipher_update *dupdate); +}; + +/* + * Full Cipher data SW context + */ +struct cipherdata { + uint32_t *descriptor; /* Job descriptor */ + bool encrypt; /* Encrypt direction */ + struct caambuf key1; /* First Key */ + struct caambuf key2; /* Second Key */ + struct caambuf tweak; /* XTS Tweak */ + struct caambuf ctx; /* CAAM Context Register */ + struct caamblock blockbuf; /* Temporary Block buffer */ + const struct cipheralg *alg; /* Reference to the algo constants */ + + /* Additionnal Data for the MAC */ + unsigned int mode; /* MAC TEE_CHAIN_MODE* */ + size_t countdata; /* MAC Number of input data */ +}; + +/* + * Cipher additionnal data block + */ +enum caam_cipher_block { + CIPHER_BLOCK_NONE = 0, + CIPHER_BLOCK_IN, + CIPHER_BLOCK_OUT, + CIPHER_BLOCK_BOTH, +}; + +/* + * Update of the cipher operation of complete block except + * if last block. Last block can be partial block. + * + * @ctx Cipher context + * @savectx Save or not the context + * @keyid Id of the key to be used during operation + * @encrypt Encrypt or decrypt direction + * @src Source data to encrypt/decrypt + * @dst [out] Destination data encrypted/decrypted + */ +enum caam_status caam_cipher_block(struct cipherdata *ctx, bool savectx, + uint8_t keyid, bool encrypt, + struct caamdmaobj *src, + struct caamdmaobj *dst); + +/* + * Update of the cipher operation in xts mode. + * + * @dupdate Data update object + */ +TEE_Result caam_cipher_update_xts(struct drvcrypt_cipher_update *dupdate); + +/* + * Initialization of the cipher operation + * + * @dinit Data initialization object + */ +TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit); + +/* + * Free software context + * + * @ctx Caller context variable + */ +void caam_cipher_free(void *ctx); + +/* + * Copy software Context + * + * @dst_ctx [out] Reference the context destination + * @src_ctx Reference the context source + */ +void caam_cipher_copy_state(void *dst_ctx, void *src_ctx); + +#endif /* __LOCAL_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/cipher/sub.mk b/optee/optee_os/core/drivers/crypto/caam/cipher/sub.mk new file mode 100644 index 0000000..802f99d --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/cipher/sub.mk @@ -0,0 +1,5 @@ +incdirs-y += ../include + +srcs-y += caam_cipher.c +srcs-y += caam_cipher_xts.c +srcs-$(CFG_NXP_CAAM_CMAC_DRV) += caam_cipher_mac.c diff --git a/optee/optee_os/core/drivers/crypto/caam/crypto.mk b/optee/optee_os/core/drivers/crypto/caam/crypto.mk new file mode 100644 index 0000000..f9353ef --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/crypto.mk @@ -0,0 +1,198 @@ +ifeq ($(CFG_NXP_CAAM),y) +# CAAM Debug: define 3x32 bits value (same bit used to debug a module) +# CFG_DBG_CAAM_TRACE Module print trace +# CFG_DBG_CAAM_DESC Module descriptor dump +# CFG_DBG_CAAM_BUF Module buffer dump +# +# DBG_HAL BIT32(0) // HAL trace +# DBG_CTRL BIT32(1) // Controller trace +# DBG_MEM BIT32(2) // Memory utility trace +# DBG_SGT BIT32(3) // Scatter Gather trace +# DBG_PWR BIT32(4) // Power trace +# DBG_JR BIT32(5) // Job Ring trace +# DBG_RNG BIT32(6) // RNG trace +# DBG_HASH BIT32(7) // Hash trace +# DBG_RSA BIT32(8) // RSA trace +# DBG_CIPHER BIT32(9) // Cipher trace +# DBG_BLOB BIT32(10) // BLOB trace +# DBG_DMAOBJ BIT32(11) // DMA Object Trace +# DBG_ECC BIT32(12) // ECC trace +# DBG_DH BIT32(13) // DH Trace +# DBG_DSA BIT32(14) // DSA trace +# DBG_MP BIT32(15) // MP trace +CFG_DBG_CAAM_TRACE ?= 0x2 +CFG_DBG_CAAM_DESC ?= 0x0 +CFG_DBG_CAAM_BUF ?= 0x0 + +# CAAM default drivers +caam-drivers = RNG BLOB + +# CAAM default drivers connected to the HW crypto API +caam-crypto-drivers = CIPHER HASH HMAC CMAC + +ifneq (,$(filter $(PLATFORM_FLAVOR),ls1012ardb ls1043ardb ls1046ardb)) +$(call force, CFG_CAAM_BIG_ENDIAN,y) +$(call force, CFG_JR_BLOCK_SIZE,0x10000) +$(call force, CFG_JR_INDEX,2) +$(call force, CFG_JR_INT,105) +$(call force, CFG_CAAM_SGT_ALIGN,4) +$(call force, CFG_CAAM_64BIT,y) +$(call force, CFG_NXP_CAAM_SGT_V1,y) +$(call force, CFG_CAAM_ITR,n) +caam-crypto-drivers += RSA DSA ECC DH MATH +else ifneq (,$(filter $(PLATFORM_FLAVOR),ls1088ardb ls2088ardb ls1028ardb)) +$(call force, CFG_CAAM_LITTLE_ENDIAN,y) +$(call force, CFG_JR_BLOCK_SIZE,0x10000) +$(call force, CFG_JR_INDEX,2) +$(call force, CFG_JR_INT,174) +$(call force, CFG_NXP_CAAM_SGT_V2,y) +$(call force, CFG_CAAM_SGT_ALIGN,4) +$(call force, CFG_CAAM_64BIT,y) +$(call force, CFG_CAAM_ITR,n) +caam-crypto-drivers += RSA DSA ECC DH MATH +else ifneq (,$(filter $(PLATFORM_FLAVOR),lx2160aqds lx2160ardb)) +$(call force, CFG_CAAM_LITTLE_ENDIAN,y) +$(call force, CFG_JR_BLOCK_SIZE,0x10000) +$(call force, CFG_JR_INDEX,2) +$(call force, CFG_JR_INT, 174) +$(call force, CFG_NB_JOBS_QUEUE, 80) +$(call force, CFG_NXP_CAAM_SGT_V2,y) +$(call force, CFG_CAAM_SGT_ALIGN,4) +$(call force, CFG_CAAM_64BIT,y) +$(call force, CFG_CAAM_ITR,n) +caam-crypto-drivers += RSA DSA ECC DH MATH +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8qm-flavorlist) $(mx8qx-flavorlist))) +$(call force, CFG_CAAM_SIZE_ALIGN,4) +$(call force, CFG_JR_BLOCK_SIZE,0x10000) +$(call force, CFG_JR_INDEX,3) +$(call force, CFG_JR_INT,486) +$(call force, CFG_NXP_CAAM_SGT_V1,y) +caam-crypto-drivers += RSA DSA ECC DH MATH +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mm-flavorlist) $(mx8mn-flavorlist) \ + $(mx8mp-flavorlist) $(mx8mq-flavorlist))) +$(call force, CFG_JR_BLOCK_SIZE,0x1000) +$(call force, CFG_JR_INDEX,2) +$(call force, CFG_JR_INT,146) +$(call force, CFG_NXP_CAAM_SGT_V1,y) +$(call force, CFG_JR_HAB_INDEX,0) +caam-drivers += MP +caam-crypto-drivers += RSA DSA ECC DH MATH +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8ulp-flavorlist))) +$(call force, CFG_JR_BLOCK_SIZE,0x1000) +$(call force, CFG_JR_INDEX,2) +$(call force, CFG_JR_INT,114) +$(call force, CFG_NXP_CAAM_SGT_V1,y) +$(call force, CFG_CAAM_ITR,n) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7ulp-flavorlist))) +$(call force, CFG_JR_BLOCK_SIZE,0x1000) +$(call force, CFG_JR_INDEX,0) +$(call force, CFG_JR_INT,137) +$(call force, CFG_NXP_CAAM_SGT_V1,y) +$(call force, CFG_CAAM_ITR,n) +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6ul-flavorlist) $(mx7d-flavorlist) \ + $(mx7s-flavorlist))) +$(call force, CFG_JR_BLOCK_SIZE,0x1000) +$(call force, CFG_JR_INDEX,0) +$(call force, CFG_JR_INT,137) +$(call force, CFG_NXP_CAAM_SGT_V1,y) +caam-drivers += MP +caam-crypto-drivers += RSA DSA ECC DH MATH +else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6q-flavorlist) $(mx6qp-flavorlist) \ + $(mx6sx-flavorlist) $(mx6d-flavorlist) $(mx6dl-flavorlist) \ + $(mx6s-flavorlist) $(mx8ulp-flavorlist))) +$(call force, CFG_JR_BLOCK_SIZE,0x1000) +$(call force, CFG_JR_INDEX,0) +$(call force, CFG_JR_INT,137) +$(call force, CFG_NXP_CAAM_SGT_V1,y) +else +$(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)") +endif + +# Disable the i.MX CAAM driver +$(call force,CFG_IMX_CAAM,n,Mandated by CFG_NXP_CAAM) + +# CAAM buffer alignment size +CFG_CAAM_SIZE_ALIGN ?= 1 + +# Default padding number for SGT allocation +CFG_CAAM_SGT_ALIGN ?= 1 + +# Enable job ring interruption +CFG_CAAM_ITR ?= y + +# Keep the CFG_JR_INDEX as secure at runtime +CFG_NXP_CAAM_RUNTIME_JR ?= y + +# Define the RSA Private Key Format used by the CAAM +# Format #1: (n, d) +# Format #2: (p, q, d) +# Format #3: (p, q, dp, dq, qp) +CFG_NXP_CAAM_RSA_KEY_FORMAT ?= 3 + +# Disable device tree status of the secure job ring +CFG_CAAM_JR_DISABLE_NODE ?= y + +# Enable CAAM non-crypto drivers +$(foreach drv, $(caam-drivers), $(eval CFG_NXP_CAAM_$(drv)_DRV ?= y)) + +# Disable software RNG if CAAM RNG driver is enabled +ifeq ($(CFG_NXP_CAAM_RNG_DRV), y) +$(call force, CFG_WITH_SOFTWARE_PRNG,n,Mandated by CFG_NXP_CAAM_RNG_DRV) +endif + +ifeq ($(CFG_CRYPTO_DRIVER), y) +CFG_CRYPTO_DRIVER_DEBUG ?= 0 + +# Enable CAAM Crypto drivers +$(foreach drv, $(caam-crypto-drivers), $(eval CFG_NXP_CAAM_$(drv)_DRV ?= y)) + +# Enable MAC crypto driver +ifeq ($(call cfg-one-enabled,CFG_NXP_CAAM_HMAC_DRV CFG_NXP_CAAM_CMAC_DRV),y) +$(call force, CFG_CRYPTO_DRV_MAC,y,Mandated by CFG_NXP_CAAM_HMAC/CMAC_DRV) +endif + +# Enable CIPHER crypto driver +ifeq ($(CFG_NXP_CAAM_CIPHER_DRV), y) +$(call force, CFG_CRYPTO_DRV_CIPHER,y,Mandated by CFG_NXP_CAAM_CIPHER_DRV) +endif + +# Enable HASH crypto driver +ifeq ($(CFG_NXP_CAAM_HASH_DRV), y) +$(call force, CFG_CRYPTO_DRV_HASH,y,Mandated by CFG_NXP_CAAM_HASH_DRV) +endif + +# Enable RSA crypto driver +ifeq ($(CFG_NXP_CAAM_RSA_DRV), y) +$(call force, CFG_CRYPTO_DRV_RSA,y,Mandated by CFG_NXP_CAAM_RSA_DRV) +endif + +# Enable ECC crypto driver +ifeq ($(CFG_NXP_CAAM_ECC_DRV), y) +$(call force, CFG_CRYPTO_DRV_ECC,y,Mandated by CFG_NXP_CAAM_ECC_DRV) +endif + +# Enable DSA crypto driver +ifeq ($(CFG_NXP_CAAM_DSA_DRV), y) +$(call force, CFG_CRYPTO_DRV_DSA,y,Mandated by CFG_NXP_CAAM_DSA_DRV) +endif + +# Enable DH crypto driver +ifeq ($(CFG_NXP_CAAM_DH_DRV), y) +$(call force, CFG_CRYPTO_DRV_DH,y,Mandated by CFG_NXP_CAAM_DH_DRV) +endif + +# Enable ACIPHER crypto driver +ifeq ($(call cfg-one-enabled,CFG_CRYPTO_DRV_RSA CFG_CRYPTO_DRV_ECC \ + CFG_CRYPTO_DRV_DSA CFG_CRYPTO_DRV_DH),y) +$(call force, CFG_CRYPTO_DRV_ACIPHER,y,Mandated by CFG_CRYPTO_DRV_{RSA|ECC|DSA|DH}) +endif + +# Disable SM2 as it is not supported by the CAAM driver +ifeq ($(CFG_NXP_CAAM_ECC_DRV),y) +$(call force,CFG_CRYPTO_SM2_PKE,n) +$(call force,CFG_CRYPTO_SM2_KEP,n) +$(call force,CFG_CRYPTO_SM2_DSA,n) +endif + +endif # CFG_CRYPTO_DRIVER +endif # CFG_NXP_CAAM diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c new file mode 100644 index 0000000..df3338a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2019, 2021 NXP + * + * Brief CAAM Configuration. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum caam_status caam_hal_cfg_get_conf(struct caam_jrcfg *jrcfg) +{ + enum caam_status retstatus = CAAM_FAILURE; + vaddr_t ctrl_base = 0; + void *fdt = NULL; + + fdt = get_dt(); + + /* + * First get the CAAM Controller base address from the DTB, + * if DTB present and if the CAAM Controller defined in it. + */ + if (fdt) + caam_hal_cfg_get_ctrl_dt(fdt, &ctrl_base); + + if (!ctrl_base) { + ctrl_base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + CAAM_BASE, CAAM_SIZE); + if (!ctrl_base) { + EMSG("Unable to map CAAM Registers"); + goto exit_get_conf; + } + } + + jrcfg->base = ctrl_base; + + /* + * Next get the Job Ring reserved for the Secure environment + * into the DTB. If nothing reserved use the default hard coded + * value. + */ + if (fdt) + caam_hal_cfg_get_jobring_dt(fdt, jrcfg); + + if (!jrcfg->offset) { + jrcfg->offset = (CFG_JR_INDEX + 1) * JRX_BLOCK_SIZE; + jrcfg->it_num = CFG_JR_INT; + + if (IS_ENABLED(CFG_NXP_CAAM_RUNTIME_JR) && + !is_embedded_dt(fdt)) { + if (fdt) { + /* Ensure Secure Job Ring is secure in DTB */ + caam_hal_cfg_disable_jobring_dt(fdt, jrcfg); + } + } + } + + jrcfg->nb_jobs = NB_JOBS_QUEUE; + + retstatus = CAAM_NO_ERROR; + +exit_get_conf: + HAL_TRACE("HAL CFG Get CAAM config ret (0x%x)\n", retstatus); + return retstatus; +} + +void __weak caam_hal_cfg_setup_nsjobring(struct caam_jrcfg *jrcfg) +{ + enum caam_status status = CAAM_FAILURE; + paddr_t jr_offset = 0; + uint8_t jrnum = 0; + + for (jrnum = caam_hal_ctrl_jrnum(jrcfg->base); jrnum; jrnum--) { + jr_offset = jrnum * JRX_BLOCK_SIZE; + +#ifdef CFG_NXP_CAAM_RUNTIME_JR + /* + * When the Cryptographic driver is enabled, keep the + * Secure Job Ring don't release it. + * But save the configuration to restore it when + * device reset after suspend. + */ + if (jr_offset == jrcfg->offset) { + caam_hal_jr_prepare_backup(jrcfg->base, jr_offset); + continue; + } +#endif + status = caam_hal_jr_setowner(jrcfg->base, jr_offset, + JROWN_ARM_NS); + if (status == CAAM_NO_ERROR) + caam_hal_jr_prepare_backup(jrcfg->base, jr_offset); + } +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c new file mode 100644 index 0000000..9a84b2c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2019, 2021 NXP + * + * Brief CAAM Configuration. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *dt_caam_match_table = { + "fsl,sec-v4.0", +}; + +static const char *dt_jr_match_table = { + "fsl,sec-v4.0-job-ring", +}; + +/* + * Finds the Job Ring reserved for the Secure Mode in the DTB + * + * @fdt Reference to the Device Tree + * @status Status mask flag of the node to found + * @find_node [out] Node offset found + */ +static paddr_t find_jr_offset(void *fdt, int status, int *find_node) +{ + paddr_t jr_offset = 0; + int node = fdt_node_offset_by_compatible(fdt, 0, dt_jr_match_table); + + for (; node != -FDT_ERR_NOTFOUND; + node = fdt_node_offset_by_compatible(fdt, node, + dt_jr_match_table)) { + HAL_TRACE("Found Job Ring node status @%" PRId32, node); + if (fdt_get_status(fdt, node) == status) { + HAL_TRACE("Found Job Ring node @%" PRId32, node); + jr_offset = fdt_reg_base_address(fdt, node); + *find_node = node; + break; + } + } + + HAL_TRACE("JR Offset return 0x%" PRIxPTR, jr_offset); + return jr_offset; +} + +void caam_hal_cfg_get_ctrl_dt(void *fdt, vaddr_t *ctrl_base) +{ + size_t size = 0; + int node = 0; + paddr_t pctrl_base = 0; + + *ctrl_base = 0; + /* Get the CAAM Node to get the controller base address */ + node = fdt_node_offset_by_compatible(fdt, 0, dt_caam_match_table); + + if (node < 0) + return; + + /* + * Map CAAM controller base address as Secure IO if not + * already present in the MMU table. + * Then get the virtual address of the CAAM controller + */ + pctrl_base = fdt_reg_base_address(fdt, node); + if (pctrl_base == DT_INFO_INVALID_REG) { + HAL_TRACE("CAAM control base address not defined"); + return; + } + + size = fdt_reg_size(fdt, node); + if (size == DT_INFO_INVALID_REG_SIZE) { + HAL_TRACE("CAAM control base address size not defined"); + return; + } + + *ctrl_base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, pctrl_base, + size); + if (!*ctrl_base) { + EMSG("CAAM control base MMU PA mapping failure"); + return; + } + + HAL_TRACE("Map Controller 0x%" PRIxVA, *ctrl_base); +} + +void caam_hal_cfg_get_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg) +{ + paddr_t jr_offset = 0; + int jr_it_num = 0; + int node = 0; + + jr_offset = find_jr_offset(fdt, DT_STATUS_OK_SEC, &node); + if (jr_offset) { + if (!is_embedded_dt(fdt)) { + /* Disable JR for Normal World */ + if (dt_enable_secure_status(fdt, node)) { + EMSG("Not able to disable JR DTB entry"); + return; + } + } + + /* Get the job ring interrupt */ + jr_it_num = dt_get_irq(fdt, node); + if (jr_it_num == DT_INFO_INVALID_INTERRUPT) { + EMSG("Job Ring interrupt number not defined in DTB"); + return; + } + + jrcfg->offset = jr_offset; + jrcfg->it_num = jr_it_num; + } +} + +void caam_hal_cfg_disable_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg) +{ + int node = fdt_node_offset_by_compatible(fdt, 0, dt_jr_match_table); + + for (; node != -FDT_ERR_NOTFOUND; + node = fdt_node_offset_by_compatible(fdt, node, + dt_jr_match_table)) { + HAL_TRACE("Found Job Ring node @%" PRId32, node); + if (fdt_reg_base_address(fdt, node) == jrcfg->offset) { + HAL_TRACE("Disable Job Ring node @%" PRId32, node); + if (dt_enable_secure_status(fdt, node)) + panic(); + break; + } + } +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c new file mode 100644 index 0000000..4c73765 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_ctrl.c @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2020 NXP + * + * Brief CAAM Controller Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +uint8_t caam_hal_ctrl_era(vaddr_t baseaddr) +{ + /* Read the number of instance */ + uint32_t val = io_caam_read32(baseaddr + CCBVID); + + return GET_CCBVID_CAAM_ERA(val); +} + +uint8_t caam_hal_ctrl_jrnum(vaddr_t baseaddr) +{ + uint32_t val = 0; + uint8_t jrnum = 0; + + if (caam_hal_ctrl_era(baseaddr) < 10) { + val = io_caam_read32(baseaddr + CHANUM_MS); + jrnum = GET_CHANUM_MS_JRNUM(val); + } else { + val = io_caam_read32(baseaddr + JR_VERSION); + jrnum = GET_JR_VERSION_JRNUM(val); + } + + return jrnum; +} + +uint8_t caam_hal_ctrl_hash_limit(vaddr_t baseaddr) +{ + uint32_t val = 0; + + if (caam_hal_ctrl_era(baseaddr) < 10) { + /* Read the number of instance */ + val = io_caam_read32(baseaddr + CHANUM_LS); + + if (GET_CHANUM_LS_MDNUM(val)) { + /* Hashing is supported */ + val = io_caam_read32(baseaddr + CHAVID_LS); + val &= BM_CHAVID_LS_MDVID; + if (val == CHAVID_LS_MDVID_LP256) + return TEE_MAIN_ALGO_SHA256; + + return TEE_MAIN_ALGO_SHA512; + } + } else { + /* Read the number of instance */ + val = io_caam_read32(baseaddr + MDHA_VERSION); + + if (GET_MDHA_VERSION_MDNUM(val)) { + /* Hashing is supported */ + val &= BM_MDHA_VERSION_MDVID; + if (val == MDHA_VERSION_MDVID_LP256) + return TEE_MAIN_ALGO_SHA256; + + return TEE_MAIN_ALGO_SHA512; + } + } + + return UINT8_MAX; +} + +bool caam_hal_ctrl_splitkey_support(vaddr_t baseaddr) +{ + uint32_t val = io_caam_read32(baseaddr + CTPR_LS); + + return GET_CTPR_LS_SPLIT_KEY(val); +} + +uint8_t caam_hal_ctrl_pknum(vaddr_t baseaddr) +{ + uint32_t val = 0; + uint8_t pknum = 0; + + if (caam_hal_ctrl_era(baseaddr) < 10) { + val = io_caam_read32(baseaddr + CHANUM_LS); + pknum = GET_CHANUM_LS_PKNUM(val); + } else { + val = io_caam_read32(baseaddr + PKHA_VERSION); + pknum = GET_PKHA_VERSION_PKNUM(val); + } + + return pknum; +} + +#define PRIBLOB_MASK GENMASK_32(1, 0) + +void caam_hal_ctrl_inc_priblob(vaddr_t baseaddr) +{ + uint32_t val = 0; + uint32_t blob = 0; + + if (!IS_ENABLED(CFG_CAAM_INC_PRIBLOB)) + return; + + val = io_caam_read32(baseaddr + SCFGR); + val &= PRIBLOB_MASK; + CTRL_TRACE("Reading CAAM PRIBLOB: 0x%"PRIx32, val); + + if (val == 0 || val == 2) + blob = val + 1; + else if (val == 1) + blob = val + 2; + else + panic("Error locking PRIBLOB, PRIBLOB =3"); + + CTRL_TRACE("New CAAM PRIBLOB value: 0x%"PRIx32, blob); + + val = io_caam_read32(baseaddr + SCFGR); + val |= blob; + io_caam_write32(baseaddr + SCFGR, val); + + val = io_caam_read32(baseaddr + SCFGR); + val &= PRIBLOB_MASK; + CTRL_TRACE("Checking: CAAM PRIBLOB: 0x%"PRIx32 " want: 0x%"PRIx32, val, + blob); + if (val != blob) + panic("Written PRIBLOB and read PRIBLOB do not match!"); +} + +#ifdef CFG_NXP_CAAM_MP_DRV +uint8_t caam_hal_ctrl_get_mpcurve(vaddr_t ctrl_addr) +{ + uint32_t val_scfgr = 0; + + /* + * On i.MX8MQ B0, the MP is not usable, hence + * return UINT8_MAX + */ + if (soc_is_imx8mq_b0_layer()) + return UINT8_MAX; + + /* + * Verify if the device is closed or not + * If device is closed, check get the MPCurve + */ + if (snvs_is_device_closed()) { + /* Get the SCFGR content */ + val_scfgr = io_caam_read32(ctrl_addr + SCFGR); + + /* Get the MPCurve field value - 4 bits */ + val_scfgr = (val_scfgr & BM_SCFGR_MPCURVE) >> BS_SCFGR_MPCURVE; + + /* + * If the device is closed and the MPCurve field is 0 + * return UINT8_MAX indicating that there is a problem and the + * MP can not be supported. + */ + if (!val_scfgr) + return UINT8_MAX; + } + + return val_scfgr; +} + +TEE_Result caam_hal_ctrl_read_mpmr(vaddr_t ctrl_addr, struct caambuf *mpmr) +{ + unsigned int i = 0; + uint32_t val = 0; + + if (mpmr->length < MPMR_NB_REG) { + mpmr->length = MPMR_NB_REG; + return TEE_ERROR_SHORT_BUFFER; + } + + /* MPMR endianness is reverted between write and read */ + for (i = 0; i < MPMR_NB_REG; i += 4) { + val = io_caam_read32(ctrl_addr + MPMR + i); + mpmr->data[i] = (uint8_t)(val >> 24); + mpmr->data[i + 1] = (uint8_t)(val >> 16); + mpmr->data[i + 2] = (uint8_t)(val >> 8); + mpmr->data[i + 3] = (uint8_t)val; + } + + mpmr->length = MPMR_NB_REG; + return TEE_SUCCESS; +} + +bool caam_hal_ctrl_is_mp_set(vaddr_t ctrl_addr) +{ + return io_caam_read32(ctrl_addr + SCFGR) & BM_SCFGR_MPMRL; +} + +void caam_hal_ctrl_fill_mpmr(vaddr_t ctrl_addr, struct caambuf *msg_mpmr) +{ + size_t i = 0; + vaddr_t reg = ctrl_addr + MPMR; + bool is_filled = false; + uint32_t val = 0; + size_t min_size = 0; + size_t remain_size = 0; + + /* check if the MPMR is filled */ + is_filled = caam_hal_ctrl_is_mp_set(ctrl_addr); + + DMSG("is_filled = %s", is_filled ? "true" : "false"); + + if (!is_filled) { + /* + * Fill the MPMR with the most significant input value and + * complete with 0's if value too short. + */ + min_size = MIN(msg_mpmr->length, (size_t)MPMR_NB_REG); + remain_size = min_size % 4; + + for (i = 0; i < min_size - remain_size; i += 4, reg += 4) { + val = msg_mpmr->data[i] | msg_mpmr->data[i + 1] << 8 | + msg_mpmr->data[i + 2] << 16 | + msg_mpmr->data[i + 3] << 24; + io_caam_write32(reg, val); + } + + /* Last input bytes value */ + if (remain_size) { + val = 0; + + /* + * Fill the MPMR with the 8 bits values + * until the end of the message length + */ + for (i = 0; i < remain_size; i++) + val |= msg_mpmr->data[i] << (i * 8); + io_caam_write32(reg, val); + reg += 4; + } + + /* Complete with 0's */ + remain_size = (MPMR_NB_REG - ROUNDUP(msg_mpmr->length, 4)) / 4; + for (i = 0; i < remain_size; i++, reg += 4) + io_caam_write32(reg, 0x0); + + /* + * Locks the MPMR for writing and remains locked until + * the next power-on session. + */ + io_caam_write32(ctrl_addr + SCFGR, + io_caam_read32(ctrl_addr + SCFGR) | + BM_SCFGR_MPMRL); + + DMSG("val_scfgr = %#"PRIx32, io_caam_read32(ctrl_addr + SCFGR)); + } +} +#endif /* CFG_NXP_CAAM_MP_DRV */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_jr.c b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_jr.c new file mode 100644 index 0000000..1d344b4 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_jr.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Job Rings Hardware Abstration Layer. + * Implementation of primitives to access HW + */ +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_NXP_CAAM_RUNTIME_JR +/* + * List of common JR registers to save/restore + */ +static const struct reglist jr_backup[] = { + BACKUP_REG(JRX_IRBAR, 2, 0, 0), + BACKUP_REG(JRX_IRSR, 1, 0, 0), + BACKUP_REG(JRX_ORBAR, 2, 0, 0), + BACKUP_REG(JRX_ORSR, 1, 0, 0), + BACKUP_REG(JRX_JRCFGR_LS, 1, 0, 0), +}; +#endif /* CFG_NXP_CAAM_RUNTIME_JR */ + +enum caam_status caam_hal_jr_reset(vaddr_t baseaddr) +{ + uint16_t timeout = 10000; + uint32_t reg_val = 0; + + /* + * Reset is done in 2 steps: + * - Flush all pending jobs (Set RESET bit) + * - Reset the Job Ring (Set RESET bit second time) + */ + + /* Mask interrupts to poll for reset completion status */ + io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK); + + /* Initiate flush (required prior to reset) */ + io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET); + + do { + caam_udelay(100); + reg_val = io_caam_read32(baseaddr + JRX_JRINTR); + reg_val &= BM_JRX_JRINTR_HALT; + } while ((reg_val == JRINTR_HALT_ONGOING) && --timeout); + + if (!timeout || reg_val != JRINTR_HALT_DONE) { + EMSG("Failed to flush job ring\n"); + return CAAM_FAILURE; + } + + /* Initiate reset */ + timeout = 100; + io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET); + do { + caam_udelay(100); + reg_val = io_caam_read32(baseaddr + JRX_JRCR); + } while ((reg_val & JRX_JRCR_RESET) && --timeout); + + if (!timeout) { + EMSG("Failed to reset job ring\n"); + return CAAM_FAILURE; + } + + return CAAM_NO_ERROR; +} + +void caam_hal_jr_config(vaddr_t baseaddr, uint8_t nbjobs, uint64_t inrings, + uint64_t outrings) +{ + uint32_t value = 0; + + /* Setup the JR input queue */ +#if defined(CFG_CAAM_64BIT) && defined(CFG_CAAM_LITTLE_ENDIAN) + io_caam_write32(baseaddr + JRX_IRBAR, inrings); + io_caam_write32(baseaddr + JRX_IRBAR + 4, inrings >> 32); +#else + io_caam_write32(baseaddr + JRX_IRBAR, inrings >> 32); + io_caam_write32(baseaddr + JRX_IRBAR + 4, inrings); +#endif + io_caam_write32(baseaddr + JRX_IRSR, nbjobs); + + /* Setup the JR output queue */ +#if defined(CFG_CAAM_64BIT) && defined(CFG_CAAM_LITTLE_ENDIAN) + io_caam_write32(baseaddr + JRX_ORBAR, outrings); + io_caam_write32(baseaddr + JRX_ORBAR + 4, outrings >> 32); +#else + io_caam_write32(baseaddr + JRX_ORBAR, outrings >> 32); + io_caam_write32(baseaddr + JRX_ORBAR + 4, outrings); +#endif + io_caam_write32(baseaddr + JRX_ORSR, nbjobs); + + /* Disable the JR interrupt */ + caam_hal_jr_disable_itr(baseaddr); + + /* + * Configure interrupt and disable it: + * Optimization to generate an interrupt either when there are + * half of the job done + * or when there is a job done and 10 clock cycles elapsed without + * new job completion + */ + value = JRX_JRCFGR_LS_ICTT(10); + value |= JRX_JRCFGR_LS_ICDCT(nbjobs / 2); + value |= JRX_JRCFGR_LS_ICEN; + value |= JRX_JRCFGR_LS_IMSK; + io_caam_write32(baseaddr + JRX_JRCFGR_LS, value); + +#ifdef CFG_NXP_CAAM_RUNTIME_JR + caam_pwr_add_backup(baseaddr, jr_backup, ARRAY_SIZE(jr_backup)); +#endif +} + +uint32_t caam_hal_jr_read_nbslot_available(vaddr_t baseaddr) +{ + return io_caam_read32(baseaddr + JRX_IRSAR); +} + +void caam_hal_jr_add_newjob(vaddr_t baseaddr) +{ + io_caam_write32(baseaddr + JRX_IRJAR, 1); +} + +uint32_t caam_hal_jr_get_nbjob_done(vaddr_t baseaddr) +{ + return io_caam_read32(baseaddr + JRX_ORSFR); +} + +void caam_hal_jr_del_job(vaddr_t baseaddr) +{ + io_caam_write32(baseaddr + JRX_ORJRR, 1); +} + +#ifdef CFG_CAAM_ITR +void caam_hal_jr_disable_itr(vaddr_t baseaddr) +{ + io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK); + io_setbits32(baseaddr + JRX_JRINTR, JRX_JRINTR_JRI); +} + +void caam_hal_jr_enable_itr(vaddr_t baseaddr) +{ + io_mask32(baseaddr + JRX_JRCFGR_LS, ~JRX_JRCFGR_LS_IMSK, + JRX_JRCFGR_LS_IMSK); +} +#else +void caam_hal_jr_disable_itr(vaddr_t baseaddr __unused) {} +void caam_hal_jr_enable_itr(vaddr_t baseaddr __unused) {} +#endif /* CFG_CAAM_ITR */ + +bool caam_hal_jr_check_ack_itr(vaddr_t baseaddr) +{ + uint32_t val = 0; + + val = io_caam_read32(baseaddr + JRX_JRINTR); + + if ((val & JRX_JRINTR_JRI) == JRX_JRINTR_JRI) { + /* Acknowledge interrupt */ + io_setbits32(baseaddr + JRX_JRINTR, JRX_JRINTR_JRI); + return true; + } + + return false; +} + +enum caam_status caam_hal_jr_halt(vaddr_t baseaddr) +{ + uint16_t timeout = 10000; + uint32_t val = 0; + + /* Mask interrupts to poll for completion status */ + io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK); + + /* Request Job ring halt */ + io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_PARK); + + /* Check if there is a job running */ + val = io_caam_read32(baseaddr + JRX_IRSR); + if ((caam_hal_jr_read_nbslot_available(baseaddr) == val) && + (io_caam_read32(baseaddr + JRX_CSTA) != JRX_CSTA_BSY)) + return CAAM_NO_ERROR; + + /* Wait until all jobs complete */ + do { + caam_udelay(10); + val = io_caam_read32(baseaddr + JRX_JRINTR); + val &= BM_JRX_JRINTR_HALT; + } while ((val != JRINTR_HALT_DONE) && --timeout); + + if (!timeout) + return CAAM_BUSY; + + return CAAM_NO_ERROR; +} + +enum caam_status caam_hal_jr_flush(vaddr_t baseaddr) +{ + uint16_t timeout = 10000; + uint32_t val = 0; + + /* Mask interrupts to poll for completion status */ + io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK); + + /* Request Job ring to flush input queue */ + io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET); + + /* Check if there is a job running */ + val = io_caam_read32(baseaddr + JRX_IRSR); + if ((caam_hal_jr_read_nbslot_available(baseaddr) == val) && + (io_caam_read32(baseaddr + JRX_CSTA) != JRX_CSTA_BSY)) + return CAAM_NO_ERROR; + + /* Wait until all jobs complete */ + do { + caam_udelay(10); + val = io_caam_read32(baseaddr + JRX_JRINTR); + val &= BM_JRX_JRINTR_HALT; + } while ((val == JRINTR_HALT_ONGOING) && --timeout); + + if (!timeout) + return CAAM_BUSY; + + return CAAM_NO_ERROR; +} + +void caam_hal_jr_resume(vaddr_t baseaddr) +{ + io_caam_write32(baseaddr + JRX_JRINTR, JRINTR_HALT_RESUME); + + caam_hal_jr_enable_itr(baseaddr); +} + +uint8_t caam_hal_jr_input_index(vaddr_t baseaddr) +{ + return io_caam_read32(baseaddr + JRX_IRRIR) >> 2; +} + +uint8_t caam_hal_jr_output_index(vaddr_t baseaddr) +{ + return io_caam_read32(baseaddr + JRX_ORWIR) >> 3; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c new file mode 100644 index 0000000..c98ee4d --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/hal_rng.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Brief CAAM Random Number Generator Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include +#include +#include +#include +#include + +enum caam_status __weak caam_hal_rng_instantiated(vaddr_t baseaddr) +{ + uint32_t vid = 0; + uint32_t nb_sh = 0; + uint32_t status = 0; + + /* RNG version < 4 and RNG state handle is already instantiated */ + if (caam_hal_ctrl_era(baseaddr) < 10) { + vid = io_caam_read32(baseaddr + CHAVID_LS); + + if (GET_CHAVID_LS_RNGVID(vid) < 4) + return CAAM_NO_ERROR; + } else { + vid = io_caam_read32(baseaddr + RNG_VERSION); + + if (GET_RNG_VERSION_VID(vid) < 4) + return CAAM_NO_ERROR; + } + + /* Get the Number of State Handles */ + nb_sh = caam_hal_rng_get_nb_sh(baseaddr); + + /* Read the RNG Status and checks if all channels are instantiatied */ + status = caam_hal_rng_get_sh_status(baseaddr); + + if (status != GENMASK_32(nb_sh - 1, 0)) + return CAAM_NOT_INIT; + + return CAAM_NO_ERROR; +} + +uint32_t caam_hal_rng_get_nb_sh(vaddr_t baseaddr) +{ + uint32_t reg = 0; + + reg = io_caam_read32(baseaddr + CTPR_MS); + + return GET_CTPR_MS_RNG_I(reg); +} + +uint32_t caam_hal_rng_get_sh_status(vaddr_t baseaddr) +{ + return io_caam_read32(baseaddr + RNG_STA) & (RNG_STA_IF1 | RNG_STA_IF0); +} + +bool caam_hal_rng_key_loaded(vaddr_t baseaddr) +{ + return io_caam_read32(baseaddr + RNG_STA) & RNG_STA_SKVN; +} + +enum caam_status caam_hal_rng_kick(vaddr_t baseaddr, uint32_t inc_delay) +{ + uint32_t val = 0; + uint32_t ent_delay = TRNG_SDCTL_ENT_DLY_MIN + inc_delay; + + if (ent_delay > TRNG_SDCTL_ENT_DLY_MAX) + return CAAM_OUT_OF_BOUND; + + /* + * Switch RNG in program mode + * Setting both RTMCTL:PRGM and RTMCTL:TRNG_ACC causes TRNG to + * properly invalidate the entropy in the entropy register and + * force re-generation + */ + io_setbits32(baseaddr + TRNG_MCTL, TRNG_MCTL_PRGM | TRNG_MCTL_ACC); + + /* + * Configure the RNG Entropy Delay + * Performance-wise, it does not make sense to + * set the delay to a value that is lower + * than the last one that worked (i.e. the state handles + * were instantiated correctly). Thus, instead of wasting + * time trying to set the values controlling the sample + * frequency, the function simply returns. + */ + val = io_caam_read32(baseaddr + TRNG_SDCTL); + val = GET_TRNG_SDCTL_ENT_DLY(val); + + if (ent_delay < val) { + /* + * In this case do the programmation anyway because on some + * device the other registers value can be wrong. + */ + ent_delay = val; + } + + io_caam_write32(baseaddr + TRNG_SDCTL, TRNG_SDCTL_ENT_DLY(ent_delay) | + TRNG_SDCTL_SAMP_SIZE(512)); + + /* min. freq. count, equal to 1/4 of the entropy sample length */ + io_caam_write32(baseaddr + TRNG_FRQMIN, ent_delay >> 2); + + /* max. freq. count, equal to 16 times the entropy sample length */ + io_caam_write32(baseaddr + TRNG_FRQMAX, ent_delay << 4); + + io_caam_write32(baseaddr + TRNG_RTSCMISC, + TRNG_RTSCMISC_RTY_CNT(2) | TRNG_RTSCMISC_LRUN_MAX(32)); + io_caam_write32(baseaddr + TRNG_RTPKRRNG, TRNG_RTPKRRNG_PKR_RNG(570)); + io_caam_write32(baseaddr + TRNG_RTPKRMAX, TRNG_RTPKRMAX_PKR_MAX(1600)); + io_caam_write32(baseaddr + TRNG_RTSCML, + TRNG_RTSCML_MONO_RNG(122) | TRNG_RTSCML_MONO_MAX(317)); + io_caam_write32(baseaddr + TRNG_RTSCR1L, + TRNG_RTSCR1L_RUN1_RNG(80) | TRNG_RTSCR1L_RUN1_MAX(107)); + io_caam_write32(baseaddr + TRNG_RTSCR2L, + TRNG_RTSCR2L_RUN2_RNG(57) | TRNG_RTSCR2L_RUN2_MAX(62)); + io_caam_write32(baseaddr + TRNG_RTSCR3L, + TRNG_RTSCR3L_RUN3_RNG(39) | TRNG_RTSCR3L_RUN3_MAX(39)); + io_caam_write32(baseaddr + TRNG_RTSCR4L, + TRNG_RTSCR4L_RUN4_RNG(27) | TRNG_RTSCR4L_RUN4_MAX(26)); + io_caam_write32(baseaddr + TRNG_RTSCR5L, + TRNG_RTSCR5L_RUN5_RNG(19) | TRNG_RTSCR5L_RUN5_MAX(18)); + io_caam_write32(baseaddr + TRNG_RTSCR6PL, + TRNG_RTSCR5L_RUN5_RNG(18) | TRNG_RTSCR5L_RUN5_MAX(17)); + + val = io_caam_read32(baseaddr + TRNG_MCTL); + /* + * Select raw sampling in both entropy shifter + * and statistical checker + */ + val &= ~BM_TRNG_MCTL_SAMP_MODE; + val |= TRNG_MCTL_SAMP_MODE_RAW_ES_SC; + /* Put RNG4 into run mode with handling CAAM/RNG4-TRNG Errata */ + val &= ~(TRNG_MCTL_PRGM | TRNG_MCTL_ACC); + io_caam_write32(baseaddr + TRNG_MCTL, val); + + /* + * Clear the ERR bit in RTMCTL if set. The TRNG error can occur when + * the RNG clock is not within 1/2x to 8x the system clock. + * This error is possible if ROM code does not initialize the system + * PLLs immediately after PoR. + */ + io_setbits32(baseaddr + TRNG_MCTL, TRNG_MCTL_ERR); + + return CAAM_NO_ERROR; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/jr_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/jr_regs.h new file mode 100644 index 0000000..8fa24b0 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/jr_regs.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019 NXP + * + * Brief Job Ring Registers. + */ +#ifndef __JR_REGS_H__ +#define __JR_REGS_H__ + +#include + +/* Job Ring Block Register Size */ +#define JRX_BLOCK_SIZE CFG_JR_BLOCK_SIZE +#define JRX_IDX(offset) (((offset) - JRX_BLOCK_SIZE) / JRX_BLOCK_SIZE) + +/* + * Input Ring + */ +/* Base Address */ +#define JRX_IRBAR 0x0000 +/* Size */ +#define JRX_IRSR 0x000C +/* Slots Available */ +#define JRX_IRSAR 0x0014 +/* Jobs Added */ +#define JRX_IRJAR 0x001C + +/* + * Output Ring + */ +/* Base Address */ +#define JRX_ORBAR 0x0020 +/* Size */ +#define JRX_ORSR 0x002C +/* Jobs Removed */ +#define JRX_ORJRR 0x0034 +/* Slots Full */ +#define JRX_ORSFR 0x003C + +/* Interrupt Status */ +#define JRX_JRINTR 0x004C +#define BM_JRX_JRINTR_HALT SHIFT_U32(0x3, 2) +#define JRINTR_HALT_RESUME SHIFT_U32(0x2, 2) +#define JRINTR_HALT_ONGOING SHIFT_U32(0x1, 2) +#define JRINTR_HALT_DONE SHIFT_U32(0x2, 2) +#define JRX_JRINTR_JRI BIT32(0) + +/* Configuration */ +#define JRX_JRCFGR_LS 0x0054 +#define JRX_JRCFGR_LS_ICTT(val) SHIFT_U32((val) & 0xFFFF, 16) +#define JRX_JRCFGR_LS_ICDCT(val) SHIFT_U32((val) & 0xFF, 8) +#define JRX_JRCFGR_LS_ICEN BIT32(1) +#define JRX_JRCFGR_LS_IMSK BIT32(0) + +/* Input Ring Read Index */ +#define JRX_IRRIR 0x005C + +/* Output Ring Write Index */ +#define JRX_ORWIR 0x0064 + +/* Command */ +#define JRX_JRCR 0x006C +#define JRX_JRCR_PARK BIT32(1) +#define JRX_JRCR_RESET BIT32(0) + +/* CAAM Status register - duplicated */ +#define JRX_CSTA 0x0FD4 +#define JRX_CSTA_TRNG_IDLE BIT32(2) +#define JRX_CSTA_IDLE BIT32(1) +#define JRX_CSTA_BSY BIT32(0) + +#endif /* __JR_REGS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/rng_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/rng_regs.h new file mode 100644 index 0000000..f96acee --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/rng_regs.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + * + * Brief Random Number Generator Registers. + */ +#ifndef __RNG_REGS_H__ +#define __RNG_REGS_H__ + +#include + +/* + * RNG Test Registers + */ +/* Miscellaneous Control */ +#define TRNG_MCTL 0x0600 +#define TRNG_MCTL_PRGM BIT32(16) +#define TRNG_MCTL_ERR BIT32(12) +#define TRNG_MCTL_ACC BIT32(5) +#define BM_TRNG_MCTL_SAMP_MODE SHIFT_U32(0x3, 0) +/* Use raw data in both entropy shifter and statistical checker */ +#define TRNG_MCTL_SAMP_MODE_RAW_ES_SC SHIFT_U32(1, 0) + +/* Seed Control */ +#define TRNG_SDCTL 0x0610 +#define BM_TRNG_SDCTL_ENT_DLY SHIFT_U32(0xFFFF, 16) +#define GET_TRNG_SDCTL_ENT_DLY(val) (((val) & BM_TRNG_SDCTL_ENT_DLY) >> 16) +#define TRNG_SDCTL_ENT_DLY(val) SHIFT_U32(((val) & 0xFFFF), 16) +#define TRNG_SDCTL_SAMP_SIZE(val) ((val) & 0xFFFF) + +#ifdef CFG_MX6SX +#define TRNG_SDCTL_ENT_DLY_MIN 12000 +#else +#define TRNG_SDCTL_ENT_DLY_MIN 3200 +#endif +#define TRNG_SDCTL_ENT_DLY_MAX 12800 + +/* Frequency Count Minimum Limit */ +#define TRNG_FRQMIN 0x0618 +/* Frequency Count Maximum Limit */ +#define TRNG_FRQMAX 0x061C + +/* Statistical Check Miscellaneous */ +#define TRNG_RTSCMISC 0x0604 +#define BM_TRNG_RTSCMISC_RTY_CNT SHIFT_U32(0xF, 16) +#define TRNG_RTSCMISC_RTY_CNT(val) SHIFT_U32(((val) & (0xF)), 16) +#define BM_TRNG_RTSCMISC_LRUN_MAX SHIFT_U32(0xFF, 0) +#define TRNG_RTSCMISC_LRUN_MAX(val) SHIFT_U32(((val) & (0xFF)), 0) + +/* Poker Range */ +#define TRNG_RTPKRRNG 0x0608 +#define BM_TRNG_RTPKRRNG_PKR_RNG SHIFT_U32(0xFFFF, 0) +#define TRNG_RTPKRRNG_PKR_RNG(val) SHIFT_U32(((val) & (0xFFFF)), 0) + +/* Poker Maximum Limit */ +#define TRNG_RTPKRMAX 0x060C +#define BM_TRNG_RTPKRMAX_PKR_MAX SHIFT_U32(0xFFFFFF, 0) +#define TRNG_RTPKRMAX_PKR_MAX(val) SHIFT_U32(((val) & (0xFFFFFF)), 0) + +/* Statistical Check Monobit Limit */ +#define TRNG_RTSCML 0x0620 +#define BM_TRNG_RTSCML_MONO_RNG SHIFT_U32(0xFFFF, 16) +#define TRNG_RTSCML_MONO_RNG(val) SHIFT_U32(((val) & (0xFFFF)), 16) +#define BM_TRNG_RTSCML_MONO_MAX SHIFT_U32(0xFFFF, 0) +#define TRNG_RTSCML_MONO_MAX(val) SHIFT_U32(((val) & (0xFFFF)), 0) + +/* Statistical Check Run Length 1 Limit */ +#define TRNG_RTSCR1L 0x0624 +#define BM_TRNG_RTSCR1L_RUN1_RNG SHIFT_U32(0x7FFF, 16) +#define TRNG_RTSCR1L_RUN1_RNG(val) SHIFT_U32(((val) & (0x7FFF)), 16) +#define BM_TRNG_RTSCR1L_RUN1_MAX SHIFT_U32(0x7FFF, 0) +#define TRNG_RTSCR1L_RUN1_MAX(val) SHIFT_U32(((val) & (0x7FFF)), 0) + +/* Statistical Check Run Length 2 Limit */ +#define TRNG_RTSCR2L 0x0628 +#define BM_TRNG_RTSCR2L_RUN2_RNG SHIFT_U32(0x3FFF, 16) +#define TRNG_RTSCR2L_RUN2_RNG(val) SHIFT_U32(((val) & (0x3FFF)), 16) +#define BM_TRNG_RTSCR2L_RUN2_MAX SHIFT_U32(0x3FFF, 0) +#define TRNG_RTSCR2L_RUN2_MAX(val) SHIFT_U32(((val) & (0x3FFF)), 0) + +/* Statistical Check Run Length 3 Limit */ +#define TRNG_RTSCR3L 0x062C +#define BM_TRNG_RTSCR3L_RUN3_RNG SHIFT_U32(0x1FFF, 16) +#define TRNG_RTSCR3L_RUN3_RNG(val) SHIFT_U32(((val) & (0x1FFF)), 16) +#define BM_TRNG_RTSCR3L_RUN3_MAX SHIFT_U32(0x1FFF, 0) +#define TRNG_RTSCR3L_RUN3_MAX(val) SHIFT_U32(((val) & (0x1FFF)), 0) + +/* Statistical Check Run Length 4 Limit */ +#define TRNG_RTSCR4L 0x0630 +#define BM_TRNG_RTSCR4L_RUN4_RNG SHIFT_U32(0xFFF, 16) +#define TRNG_RTSCR4L_RUN4_RNG(val) SHIFT_U32(((val) & (0xFFF)), 16) +#define BM_TRNG_RTSCR4L_RUN4_MAX SHIFT_U32(0xFFF, 0) +#define TRNG_RTSCR4L_RUN4_MAX(val) SHIFT_U32(((val) & (0xFFF)), 0) + +/* Statistical Check Run Length 5 Limit */ +#define TRNG_RTSCR5L 0x0634 +#define BM_TRNG_RTSCR5L_RUN5_RNG SHIFT_U32(0x7FF, 16) +#define TRNG_RTSCR5L_RUN5_RNG(val) SHIFT_U32(((val) & (0x7FF)), 16) +#define BM_TRNG_RTSCR5L_RUN5_MAX SHIFT_U32(0x7FF, 0) +#define TRNG_RTSCR5L_RUN5_MAX(val) SHIFT_U32(((val) & (0x7FF)), 0) + +/* Statistical Check Run Length 6+ Limit */ +#define TRNG_RTSCR6PL 0x0638 +#define BM_TRNG_RTSCR6PL_RUN6P_RNG SHIFT_U32(0x7FF, 16) +#define TRNG_RTSCR6PL_RUN6P_RNG(val) SHIFT_U32(((val) & (0x7FF)), 16) +#define BM_TRNG_RTSCR6PL_RUN6P_MAX SHIFT_U32(0x7FF, 0) +#define TRNG_RTSCR6PL_RUN6P_MAX(val) SHIFT_U32(((val) & (0x7FF)), 0) + +/* + * RNG Registers + */ +/* Status */ +#define RNG_STA 0x06C0 + +#define RNG_STA_SKVN BIT32(30) +#define RNG_STA_IF1 BIT32(1) +#define RNG_STA_IF0 BIT32(0) + +#endif /* __RNG_REGS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/version_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/version_regs.h new file mode 100644 index 0000000..9691117 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/registers/version_regs.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2020 NXP + * + * Brief Version Registers. + */ +#ifndef __VERSION_REGS_H__ +#define __VERSION_REGS_H__ + +#include + +/* Compile Time Parameters */ +#define CTPR_MS 0x0FA8 +#define BM_CTPR_MS_RNG_I SHIFT_U32(0x7, 8) +#define GET_CTPR_MS_RNG_I(val) (((val) & BM_CTPR_MS_RNG_I) >> 8) + +#define CTPR_LS 0x0FAC +#define BM_CTPR_LS_SPLIT_KEY BIT(14) +#define GET_CTPR_LS_SPLIT_KEY(val) (((val) & BM_CTPR_LS_SPLIT_KEY) >> 14) + +/* Secure Memory Version ID */ +#define SMVID_MS 0x0FD8 +#define BM_SMVID_MS_MAX_NPAG SHIFT_U32(0x3FF, 16) +#define GET_SMVID_MS_MAX_NPAG(val) (((val) & BM_SMVID_MS_MAX_NPAG) >> 16) +#define BM_SMVID_MS_NPRT SHIFT_U32(0xF, 12) +#define GET_SMVID_MS_NPRT(val) (((val) & BM_SMVID_MS_NPRT) >> 12) + +#define SMVID_LS 0x0FDC +#define BM_SMVID_LS_PSIZ SHIFT_U32(0x7, 16) +#define GET_SMVID_LS_PSIZ(val) (((val) & BM_SMVID_LS_PSIZ) >> 16) + +/* CHA Cluster Block Version ID */ +#define CCBVID 0x0FE4 +#define BM_CCBVID_CAAM_ERA SHIFT_U32(0xFF, 24) +#define GET_CCBVID_CAAM_ERA(val) (((val) & BM_CCBVID_CAAM_ERA) >> 24) + +/* CHA Version ID */ +#define CHAVID_LS 0x0FEC +#define BM_CHAVID_LS_RNGVID SHIFT_U32(0xF, 16) +#define GET_CHAVID_LS_RNGVID(val) (((val) & BM_CHAVID_LS_RNGVID) >> 16) +#define BM_CHAVID_LS_MDVID SHIFT_U32(0xF, 12) + +#define CHAVID_LS_MDVID_LP256 SHIFT_U32(0, 12) + +/* CHA Number */ +#define CHANUM_MS 0x0FF0 +#define BM_CHANUM_MS_JRNUM SHIFT_U32(0xF, 28) +#define GET_CHANUM_MS_JRNUM(val) (((val) & BM_CHANUM_MS_JRNUM) >> 28) + +#define CHANUM_LS 0x0FF4 +#define BM_CHANUM_LS_PKNUM SHIFT_U32(0xF, 28) +#define GET_CHANUM_LS_PKNUM(val) (((val) & BM_CHANUM_LS_PKNUM) >> 28) +#define BM_CHANUM_LS_MDNUM SHIFT_U32(0xF, 12) +#define GET_CHANUM_LS_MDNUM(val) (((val) & BM_CHANUM_LS_MDNUM) >> 12) + +/* PKHA Version for Era > 10 */ +#define PKHA_VERSION 0x0E8C +#define BM_PKHA_VERSION_PKNUM 0xFF +#define GET_PKHA_VERSION_PKNUM(val) ((val) & BM_PKHA_VERSION_PKNUM) + +/* MDHA Version for Era > 10 */ +#define MDHA_VERSION 0xE94 +#define BM_MDHA_VERSION_MDNUM 0xFF +#define GET_MDHA_VERSION_MDNUM(val) ((val) & BM_MDHA_VERSION_MDNUM) +#define BM_MDHA_VERSION_MDVID SHIFT_U32(0xFF, 24) + +#define MDHA_VERSION_MDVID_LP256 SHIFT_U32(0, 24) + +/* RNG Version for Era > 10 */ +#define RNG_VERSION 0x0EF8 +#define BM_RNG_VERSION_VID SHIFT_U32(0xFF, 24) +#define GET_RNG_VERSION_VID(val) ((val) & BM_RNG_VERSION_VID) + +/* JR Version for Era > 10 */ +#define JR_VERSION 0x0EF8 +#define BM_JR_VERSION_JRNUM 0xFF +#define GET_JR_VERSION_JRNUM(val) ((val) & BM_JR_VERSION_JRNUM) + +#endif /* __VERSION_REGS_H__ */ + diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/common/sub.mk b/optee/optee_os/core/drivers/crypto/caam/hal/common/sub.mk new file mode 100644 index 0000000..0b101ef --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/common/sub.mk @@ -0,0 +1,9 @@ +incdirs-y += ../../include +incdirs-y += ../$(CAAM_HAL_DIR) +incdirs-y += . + +srcs-$(CFG_DT) += hal_cfg_dt.c +srcs-y += hal_cfg.c +srcs-y += hal_rng.c +srcs-y += hal_jr.c +srcs-y += hal_ctrl.c diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c new file mode 100644 index 0000000..3333a22 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Clock functions. + */ +#include +#include +#include +#include + +void caam_hal_clk_enable(bool enable) +{ + vaddr_t ccm_base = (vaddr_t)phys_to_virt(CCM_BASE, MEM_AREA_IO_SEC, + CCM_SIZE); + uint32_t reg = 0; + uint32_t mask = 0; + + reg = io_read32(ccm_base + CCM_CCGR0); + + mask = BM_CCM_CCGR0_CAAM_WRAPPER_IPG | BM_CCM_CCGR0_CAAM_WRAPPER_ACLK | + BM_CCM_CCGR0_CAAM_SECURE_MEM; + + if (enable) + reg |= mask; + else + reg &= ~mask; + + io_write32(ccm_base + CCM_CCGR0, reg); + + if (!soc_is_imx6ul()) { + /* EMI slow clk */ + reg = io_read32(ccm_base + CCM_CCGR6); + mask = BM_CCM_CCGR6_EMI_SLOW; + + if (enable) + reg |= mask; + else + reg &= ~mask; + + io_write32(ccm_base + CCM_CCGR6, reg); + } +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c new file mode 100644 index 0000000..51f29e6 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Clock functions. + */ +#include +#include +#include +#include + +void caam_hal_clk_enable(bool enable) +{ + vaddr_t ccm_base = (vaddr_t)phys_to_virt(CCM_BASE, MEM_AREA_IO_SEC, 1); + + if (enable) { + io_write32(ccm_base + CCM_CCGRx_SET(CCM_CLOCK_DOMAIN_CAAM), + CCM_CCGRx_ALWAYS_ON(0)); + } else { + io_write32(ccm_base + CCM_CCGRx_CLR(CCM_CLOCK_DOMAIN_CAAM), + CCM_CCGRx_ALWAYS_ON(0)); + } +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7ulp.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7ulp.c new file mode 100644 index 0000000..9cb1594 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7ulp.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Clock functions. + */ +#include +#include +#include +#include + +void caam_hal_clk_enable(bool enable) +{ + vaddr_t pcc2_base = (vaddr_t)phys_to_virt(PCC2_BASE, MEM_AREA_IO_SEC, + PCC_CAAM + sizeof(uint32_t)); + + if (enable) + io_write32(pcc2_base + PCC_CAAM, PCC_ENABLE_CLOCK); + else + io_write32(pcc2_base + PCC_CAAM, PCC_DISABLE_CLOCK); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_ctrl.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_ctrl.c new file mode 100644 index 0000000..d0a5086 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_ctrl.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Controller Hardware Abstration Layer. + * Implementation of primitives to access HW + */ +#include +#include +#include +#include + +/* + * List of control registers to save/restore + */ +static const struct reglist ctrl_backup[] = { + BACKUP_REG(MCFGR, 1, 0, 0), +#ifdef CFG_NXP_CAAM_MP_DRV + BACKUP_REG(SCFGR, 1, BM_SCFGR_MPMRL | BM_SCFGR_MPCURVE, 0), +#else + /* For device not supporting MP (bits not defined) */ + BACKUP_REG(SCFGR, 1, 0, 0), +#endif +}; + +void caam_hal_ctrl_init(vaddr_t baseaddr) +{ + /* Enable DECO watchdogs */ + io_setbits32(baseaddr + MCFGR, MCFGR_WDE); + + /* + * ERRATA: mx6 devices have an issue wherein AXI bus transactions + * may not occur in the correct order. This isn't a problem running + * single descriptors, but can be if running multiple concurrent + * descriptors. Reworking the driver to throttle to single requests + * is impractical, thus the workaround is to limit the AXI pipeline + * to a depth of 1 (default depth is 4) to preclude this situation + * from occurring. + * + * mx7 devices, this bit has no effect. + */ + io_mask32(baseaddr + MCFGR, MCFGR_AXIPIPE(1), BM_MCFGR_AXIPIPE); + + caam_pwr_add_backup(baseaddr, ctrl_backup, ARRAY_SIZE(ctrl_backup)); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_jr.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_jr.c new file mode 100644 index 0000000..cda6f75 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/hal_jr.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Job Rings Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include +#include +#include +#include +#include + +/* + * List of JR configuration registers to save/restore + */ +static const struct reglist jrcfg_backup[] = { + BACKUP_REG(JR0MIDR_LS, 1, 0, 0), + BACKUP_REG(JR0MIDR_MS, 1, 0, 0), +}; + +enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, + enum caam_jr_owner owner) +{ + enum caam_status retstatus = CAAM_FAILURE; + uint32_t val = 0; + uint32_t cfg_ms = 0; + uint32_t cfg_ls = 0; + unsigned int jr_idx = JRX_IDX(jr_offset); + + /* Read the Job Ring Lock bit */ + val = io_caam_read32(ctrl_base + JRxMIDR_MS(jr_idx)); + HAL_TRACE("JR%" PRIu32 "MIDR_MS value 0x%" PRIx32, jr_idx, val); + + /* Prepare the Job Ring MS/LS registers */ + if (owner & JROWNER_SECURE) { + /* Configuration only lock for the Secure JR */ + cfg_ms = JRxMIDR_MS_JROWN_MID(owner & ~JROWNER_SECURE); + cfg_ms |= JRxMIDR_MS_AMTD; +#ifdef CFG_NXP_CAAM_RUNTIME_JR + cfg_ms |= JRxMIDR_MS_LAMTD; + cfg_ms |= JRxMIDR_MS_LMID; +#endif + cfg_ls = JRxMIDR_LS_SEQ_MID(owner & ~JROWNER_SECURE); + cfg_ls |= JRxMIDR_LS_NONSEQ_MID(owner & ~JROWNER_SECURE); + } else { + cfg_ms = JRxMIDR_MS_JROWN_MID(owner) | JRxMIDR_MS_JROWN_NS; + cfg_ls = JRxMIDR_LS_SEQ_MID(owner) | JRxMIDR_LS_SEQ_NS; + cfg_ls |= JRxMIDR_LS_NONSEQ_MID(owner) | JRxMIDR_LS_NONSEQ_NS; + } + + if (val & JRxMIDR_MS_LMID) { + /* + * Configuration already locked, check it is the + * expected configuration. + */ + HAL_TRACE("JR%" PRIu32 "MIDR_MS value 0x%" PRIx32 " (0x%" PRIx32 + ")", + jr_idx, val, cfg_ms); + if ((cfg_ms | JRxMIDR_MS_LMID) == val) { + /* + * Read the LS register and compare with expected + * value + */ + val = io_caam_read32(ctrl_base + JRxMIDR_LS(jr_idx)); + HAL_TRACE("JR%" PRIu32 "MIDR_LS value 0x%" PRIx32 + " (0x%" PRIX32 ")", + jr_idx, val, cfg_ls); + if (val == cfg_ls) + retstatus = CAAM_NO_ERROR; + } + } else { + HAL_TRACE("JR%" PRIu32 "MIDR_LS set value 0x%" PRIx32, jr_idx, + cfg_ls); + HAL_TRACE("JR%" PRIu32 "MIDR_MS set value 0x%" PRIx32, jr_idx, + cfg_ms); + /* Set the configuration */ + io_caam_write32(ctrl_base + JRxMIDR_LS(jr_idx), cfg_ls); + io_caam_write32(ctrl_base + JRxMIDR_MS(jr_idx), cfg_ms); + retstatus = CAAM_NO_ERROR; + } + + return retstatus; +} + +void caam_hal_jr_prepare_backup(vaddr_t ctrl_base, paddr_t jr_offset) +{ + unsigned int jr_idx = JRX_IDX(jr_offset); + + caam_pwr_add_backup(ctrl_base + (jr_idx * JRxMIDR_SIZE), jrcfg_backup, + ARRAY_SIZE(jrcfg_backup)); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h new file mode 100644 index 0000000..4edc68d --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + * + * Brief Control Registers. + */ +#ifndef __CTRL_REGS_H__ +#define __CTRL_REGS_H__ + +#include + +/* Master Configuration */ +#define MCFGR 0x0004 +#define MCFGR_WDE BIT32(30) +#define MCFGR_AXIPIPE(val) SHIFT_U32(val, 4) +#define BM_MCFGR_AXIPIPE SHIFT_U32(0xF, 4) + +/* Job Ring x MID */ +#define JRxMIDR_SIZE 0x8 +#define JR0MIDR_MS 0x0010 +#define JR0MIDR_LS 0x0014 +#define JRxMIDR_MS(idx) (JR0MIDR_MS + (idx) * JRxMIDR_SIZE) +#define JRxMIDR_LS(idx) (JR0MIDR_LS + (idx) * JRxMIDR_SIZE) + +#define JRxMIDR_MS_LMID BIT32(31) +#define JRxMIDR_MS_LAMTD BIT32(17) +#define JRxMIDR_MS_AMTD BIT32(16) +#if !defined(CFG_MX7ULP) +#define JRxMIDR_MS_JROWN_NS BIT32(3) +#define JRxMIDR_MS_JROWN_MID(val) SHIFT_U32((val) & 0x7, 0) + +#define JRxMIDR_LS_NONSEQ_NS BIT32(19) +#define JRxMIDR_LS_NONSEQ_MID(val) SHIFT_U32((val) & 0x7, 16) +#define JRxMIDR_LS_SEQ_NS BIT32(3) +#define JRxMIDR_LS_SEQ_MID(val) SHIFT_U32((val) & 0x7, 0) +#else +#define JRxMIDR_MS_JROWN_NS BIT32(4) +#define JRxMIDR_MS_JROWN_MID(val) SHIFT_U32((val) & 0xF, 0) + +#define JRxMIDR_LS_NONSEQ_NS BIT32(20) +#define JRxMIDR_LS_NONSEQ_MID(val) SHIFT_U32((val) & 0xF, 16) +#define JRxMIDR_LS_SEQ_NS BIT32(4) +#define JRxMIDR_LS_SEQ_MID(val) SHIFT_U32((val) & 0xF, 0) +#endif + +/* Security Configuration */ +#define SCFGR 0x000C +#define BS_SCFGR_MPCURVE 28 +#define BM_SCFGR_MPCURVE SHIFT_U32(0xF, BS_SCFGR_MPCURVE) +#define BM_SCFGR_MPMRL BIT32(26) + +/* Manufacturing Protection Message */ +#define MPMR 0x0380 +#define MPMR_NB_REG 0x20 + +#endif /* __CTRL_REGS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/sub.mk b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/sub.mk new file mode 100644 index 0000000..b306fdc --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_6_7/sub.mk @@ -0,0 +1,9 @@ +incdirs-y += ../common +incdirs-y += ../../include +incdirs-y += . + +srcs-$(CFG_MX6) += hal_clk_mx6.c +srcs-$(CFG_MX7) += hal_clk_mx7.c +srcs-$(CFG_MX7ULP) += hal_clk_mx7ulp.c +srcs-y += hal_ctrl.c +srcs-y += hal_jr.c diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c new file mode 100644 index 0000000..eee59d6 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018 NXP + * + * Brief CAAM Clock functions. + */ +#include +#include + +void caam_hal_clk_enable(bool enable __unused) +{ +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_ctrl.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_ctrl.c new file mode 100644 index 0000000..571194e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_ctrl.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Controller Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include +#include + +void caam_hal_ctrl_init(vaddr_t baseaddr) +{ + /* Enable DECO watchdogs */ + io_setbits32(baseaddr + MCFGR, MCFGR_WDE); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_jr.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_jr.c new file mode 100644 index 0000000..f188815 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/hal_jr.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Job Rings Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include +#include +#include +#include +#include + +/* + * List of JR configuration registers to save/restore + */ +static const struct reglist jrcfg_backup[] = { + BACKUP_REG(JR0DID_MS, 1, 0, 0), + BACKUP_REG(JR0DID_LS, 1, 0, 0), +}; + +enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, + enum caam_jr_owner owner) +{ + enum caam_status retstatus = CAAM_FAILURE; + uint32_t val = 0; + uint32_t cfg_ms = 0; + uint32_t cfg_ls = 0; + unsigned int jr_idx = JRX_IDX(jr_offset); + + /* Read the Job Ring Lock bit */ + val = io_caam_read32(ctrl_base + JRxDID_MS(jr_idx)); + HAL_TRACE("JR%" PRIu32 "DID_MS value 0x%" PRIx32, jr_idx, val); + + /* Prepare the Job Ring MS/LS registers */ + if (owner & JROWNER_SECURE) { + /* Configuration only locked for the Secure JR */ + cfg_ms = JRxDID_MS_PRIM_DID(owner & ~JROWNER_SECURE); + cfg_ms |= JRxDID_MS_PRIM_TZ | JRxDID_MS_TZ_OWN; + cfg_ms |= JRxDID_MS_AMTD; + cfg_ms |= JRxDID_MS_PRIM_ICID(owner & ~JROWNER_SECURE); +#ifdef CFG_NXP_CAAM_RUNTIME_JR + cfg_ms |= JRxDID_MS_LDID; + cfg_ms |= JRxDID_MS_LAMTD; +#endif + } else { + cfg_ms = JRxDID_MS_PRIM_DID(owner); + cfg_ms |= JRxDID_MS_PRIM_ICID(owner); + } + + if (val & JRxDID_MS_LDID) { + /* + * Configuration already locked, check it is the + * expected configuration. + */ + HAL_TRACE("JR%" PRIu32 "DID_MS value 0x%" PRIx32 " (0x%" PRIx32 + ")", + jr_idx, val, cfg_ms); + if ((cfg_ms | JRxDID_MS_LDID) == val) { + /* Read LS register and compare with expected value */ + val = io_caam_read32(ctrl_base + JRxDID_LS(jr_idx)); + HAL_TRACE("JR%" PRIu32 "DID_LS value 0x%" PRIx32 + " (0x%" PRIx32 ")", + jr_idx, val, cfg_ls); + if (val == cfg_ls) + retstatus = CAAM_NO_ERROR; + } + } else { + HAL_TRACE("JR%" PRIu32 "DID_LS set value 0x%" PRIx32, jr_idx, + cfg_ls); + HAL_TRACE("JR%" PRIu32 "DID_MS set value 0x%" PRIx32, jr_idx, + cfg_ms); + /* Set the configuration */ + io_caam_write32(ctrl_base + JRxDID_LS(jr_idx), cfg_ls); + io_caam_write32(ctrl_base + JRxDID_MS(jr_idx), cfg_ms); + retstatus = CAAM_NO_ERROR; + } + + return retstatus; +} + +void caam_hal_jr_prepare_backup(vaddr_t ctrl_base, paddr_t jr_offset) +{ + unsigned int jr_idx = JRX_IDX(jr_offset); + + caam_pwr_add_backup(ctrl_base + (jr_idx * JRxDID_SIZE), jrcfg_backup, + ARRAY_SIZE(jrcfg_backup)); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h new file mode 100644 index 0000000..698891d --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + * + * Brief Control Registers. + */ +#ifndef __CTRL_REGS_H__ +#define __CTRL_REGS_H__ + +#include + +/* Master Configuration */ +#define MCFGR 0x0004 +#define MCFGR_WDE BIT32(30) + +/* Job Ring x MID */ +#define JRxDID_SIZE 0x8 +#define JR0DID_MS 0x0010 +#define JR0DID_LS 0x0014 +#define JRxDID_MS(idx) (JR0DID_MS + ((idx) * JRxDID_SIZE)) +#define JRxDID_LS(idx) (JR0DID_LS + ((idx) * JRxDID_SIZE)) + +#define JRxDID_MS_LDID BIT32(31) +#define JRxDID_MS_PRIM_ICID(val) SHIFT_U32(((val) & 0x3FF), 19) +#define JRxDID_MS_LAMTD BIT32(17) +#define JRxDID_MS_AMTD BIT32(16) +#define JRxDID_MS_TZ_OWN BIT32(15) +#define JRxDID_MS_PRIM_TZ BIT32(4) +#define JRxDID_MS_PRIM_DID(val) SHIFT_U32(((val) & 0xF), 0) + +/* Security Configuration */ +#define SCFGR 0x000C +#define BS_SCFGR_MPCURVE 28 +#define BM_SCFGR_MPCURVE SHIFT_U32(0xF, BS_SCFGR_MPCURVE) +#define BM_SCFGR_MPMRL BIT32(26) + +/* Manufacturing Protection Message */ +#define MPMR 0x0380 +#define MPMR_NB_REG U(32) + +#endif /* __CTRL_REGS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/sub.mk b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/sub.mk new file mode 100644 index 0000000..5231cce --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8m/sub.mk @@ -0,0 +1,7 @@ +incdirs-y += ../common +incdirs-y += ../../include +incdirs-y += . + +srcs-y += hal_clk.c +srcs-y += hal_ctrl.c +srcs-y += hal_jr.c diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_cfg.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_cfg.c new file mode 100644 index 0000000..2fff1c1 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_cfg.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021 NXP + */ +#include + +void caam_hal_cfg_setup_nsjobring(struct caam_jrcfg *jrcfg __unused) +{ +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_clk.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_clk.c new file mode 100644 index 0000000..fe8bf25 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_clk.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021 NXP + */ +#include +#include + +void caam_hal_clk_enable(bool enable __unused) +{ +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_ctrl.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_ctrl.c new file mode 100644 index 0000000..dfec080 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_ctrl.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021 NXP + */ +#include +#include + +void caam_hal_ctrl_init(vaddr_t baseaddr __unused) +{ +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_jr.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_jr.c new file mode 100644 index 0000000..f92745f --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_jr.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021 NXP + */ +#include +#include +#include +#include +#include + +enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base __unused, + paddr_t jr_offset __unused, + enum caam_jr_owner owner __unused) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + ret = imx_sc_driver_init(); + if (ret != TEE_SUCCESS) + return CAAM_FAILURE; + + ret = imx_sc_rm_enable_jr(CFG_JR_INDEX); + if (ret != TEE_SUCCESS) + return CAAM_FAILURE; + else + return CAAM_NO_ERROR; +} + +void caam_hal_jr_prepare_backup(vaddr_t ctrl_base __unused, + paddr_t jr_offset __unused) +{ +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c new file mode 100644 index 0000000..a561ab1 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021 NXP + */ +#include +#include +#include +#include +#include + +enum caam_status caam_hal_rng_instantiated(vaddr_t baseaddr __unused) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + ret = imx_sc_seco_start_rng(); + if (ret != TEE_SUCCESS) + return CAAM_FAILURE; + else + return CAAM_NO_ERROR; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h new file mode 100644 index 0000000..70296b3 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020 NXP + */ +#ifndef __CTRL_REGS_H__ +#define __CTRL_REGS_H__ + +/* Global includes */ +#include + +/* Job Ring x MID */ +#define JRxDID_SIZE 0x8 +#define JR0DID_MS 0x0010 +#define JR0DID_LS 0x0014 +#define JRxDID_MS(idx) (JR0DID_MS + (idx) * (JRxDID_SIZE)) +#define JRxDID_LS(idx) (JR0DID_LS + (idx) * (JRxDID_SIZE)) + +#define JRxDID_MS_LDID BIT32(31) +#define JRxDID_MS_PRIM_ICID(val) SHIFT_U32((val) & (0x3FF), 19) +#define JRxDID_MS_LAMTD BIT32(17) +#define JRxDID_MS_AMTD BIT32(16) +#define JRxDID_MS_TZ_OWN BIT32(15) +#define JRxDID_MS_PRIM_TZ BIT32(4) +#define JRxDID_MS_PRIM_DID(val) SHIFT_U32((val) & (0xF), 0) + +/* Security Configuration */ +#define SCFGR 0x000C +#define BS_SCFGR_MPCURVE 28 +#define BM_SCFGR_MPCURVE SHIFT_U32(0xF, BS_SCFGR_MPCURVE) +#define BM_SCFGR_MPMRL BIT32(26) + +/* Secure Memory Virtual Base Address */ +#define JRX_SMVBAR(idx) (0x0184 + (idx) * (8)) + +/* Manufacturing Protection Message */ +#define MPMR 0x0380 +#define MPMR_NB_REG 0x20 + +#endif /* __CTRL_REGS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/sub.mk b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/sub.mk new file mode 100644 index 0000000..72f3eab --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8q/sub.mk @@ -0,0 +1,9 @@ +incdirs-y += ../common +incdirs-y += ../../include +incdirs-y += . + +srcs-y += hal_clk.c +srcs-y += hal_ctrl.c +srcs-y += hal_jr.c +srcs-y += hal_cfg.c +srcs-y += hal_rng.c diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c new file mode 100644 index 0000000..1f49479 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + * + * Brief CAAM Clock functions. + */ +#include +#include +#include +#include + +void caam_hal_clk_enable(bool enable) +{ + vaddr_t pcc3_base = (vaddr_t)phys_to_virt(PCC3_BASE, MEM_AREA_IO_SEC, + PCC3_SIZE); + + if (enable) + io_setbits32(pcc3_base + PCC_CAAM, PCC_ENABLE_CLOCK); + else + io_clrbits32(pcc3_base + PCC_CAAM, PCC_ENABLE_CLOCK); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_ctrl.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_ctrl.c new file mode 100644 index 0000000..8ec1fb8 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_ctrl.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + * + * Brief CAAM Controller Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include +#include +#include + +void caam_hal_ctrl_init(vaddr_t baseaddr) +{ + /* Enable DECO watchdogs */ + io_setbits32(baseaddr + MCFGR, MCFGR_WDE); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_jr.c b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_jr.c new file mode 100644 index 0000000..a022bb5 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/hal_jr.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + * + * Brief CAAM Job Rings Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * List of JR configuration registers to save/restore + */ +static const struct reglist jrcfg_backup[] = { + BACKUP_REG(JR0DID_MS, 1, 0, 0), + BACKUP_REG(JR0DID_LS, 1, 0, 0), +}; + +enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, + enum caam_jr_owner owner) +{ + enum caam_status retstatus = CAAM_FAILURE; + uint32_t val = 0; + uint32_t cfg_ms = 0; + uint32_t cfg_ls = 0; + unsigned int jr_idx = JRX_IDX(jr_offset); + + /* Read the Job Ring Lock bit */ + val = io_caam_read32(ctrl_base + JRxDID_MS(jr_idx)); + HAL_TRACE("JR%" PRIu32 "DID_MS value 0x%" PRIx32, jr_idx, val); + + /* Prepare the Job Ring MS/LS registers */ + if (owner & JROWNER_SECURE) { + /* Configuration only locked for the Secure JR */ + cfg_ms = JRxDID_MS_PRIM_DID(owner & ~JROWNER_SECURE); + cfg_ms |= JRxDID_MS_PRIM_TZ | JRxDID_MS_TZ_OWN; + cfg_ms |= JRxDID_MS_AMTD; + cfg_ms |= JRxDID_MS_PRIM_ICID(owner & ~JROWNER_SECURE); + if (IS_ENABLED(CFG_NXP_CAAM_RUNTIME_JR)) { + cfg_ms |= JRxDID_MS_LDID; + cfg_ms |= JRxDID_MS_LAMTD; + } + } else { + cfg_ms = JRxDID_MS_PRIM_DID(owner); + cfg_ms |= JRxDID_MS_PRIM_ICID(owner); + } + + if (val & JRxDID_MS_LDID) { + /* + * Configuration already locked, check it is the + * expected configuration. + */ + HAL_TRACE("JR%" PRIu32 "DID_MS value 0x%" PRIx32 " (0x%" PRIx32 + ")", + jr_idx, val, cfg_ms); + if ((cfg_ms | JRxDID_MS_LDID) == val) { + /* Read LS register and compare with expected value */ + val = io_caam_read32(ctrl_base + JRxDID_LS(jr_idx)); + HAL_TRACE("JR%" PRIu32 "DID_LS value 0x%" PRIx32 + " (0x%" PRIx32 ")", + jr_idx, val, cfg_ls); + if (val == cfg_ls) + retstatus = CAAM_NO_ERROR; + } + } else { + HAL_TRACE("JR%" PRIu32 "DID_LS set value 0x%" PRIx32, jr_idx, + cfg_ls); + HAL_TRACE("JR%" PRIu32 "DID_MS set value 0x%" PRIx32, jr_idx, + cfg_ms); + /* Set the configuration */ + io_caam_write32(ctrl_base + JRxDID_LS(jr_idx), cfg_ls); + io_caam_write32(ctrl_base + JRxDID_MS(jr_idx), cfg_ms); + retstatus = CAAM_NO_ERROR; + } + + return retstatus; +} + +void caam_hal_jr_prepare_backup(vaddr_t ctrl_base, paddr_t jr_offset) +{ + unsigned int jr_idx = JRX_IDX(jr_offset); + + caam_pwr_add_backup(ctrl_base + (jr_idx * JRxDID_SIZE), jrcfg_backup, + ARRAY_SIZE(jrcfg_backup)); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h new file mode 100644 index 0000000..fae7969 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + * + * Brief Control Registers. + */ +#ifndef __CTRL_REGS_H__ +#define __CTRL_REGS_H__ + +#include + +/* Master Configuration */ +#define MCFGR 0x0004 +#define MCFGR_WDE BIT32(30) + +/* Job Ring x MID */ +#define JRxDID_SIZE 0x8 +#define JR0DID_MS 0x0010 +#define JR0DID_LS 0x0014 +#define JRxDID_MS(idx) (JR0DID_MS + ((idx) * (JRxDID_SIZE))) +#define JRxDID_LS(idx) (JR0DID_LS + ((idx) * (JRxDID_SIZE))) + +#define JRxDID_MS_LDID BIT32(31) +#define JRxDID_MS_PRIM_ICID(val) SHIFT_U32(((val) & (0x3FF)), 19) +#define JRxDID_MS_LAMTD BIT32(17) +#define JRxDID_MS_AMTD BIT32(16) +#define JRxDID_MS_TZ_OWN BIT32(15) +#define JRxDID_MS_PRIM_TZ BIT32(4) +#define JRxDID_MS_PRIM_DID(val) SHIFT_U32(((val) & (0xF)), 0) + +/* Security Configuration */ +#define SCFGR 0x000C +#define BS_SCFGR_MPCURVE 28 +#define BM_SCFGR_MPCURVE SHIFT_U32(0xF, BS_SCFGR_MPCURVE) +#define BM_SCFGR_MPMRL BIT32(26) + +/* Secure Memory Virtual Base Address */ +#define JRX_SMVBAR(idx) (0x0184 + (idx) * (8)) + +/* Manufacturing Protection Message */ +#define MPMR 0x0380 +#define MPMR_NB_REG 0x20 + +#endif /* __CTRL_REGS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/sub.mk b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/sub.mk new file mode 100644 index 0000000..5231cce --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/imx_8ulp/sub.mk @@ -0,0 +1,7 @@ +incdirs-y += ../common +incdirs-y += ../../include +incdirs-y += . + +srcs-y += hal_clk.c +srcs-y += hal_ctrl.c +srcs-y += hal_jr.c diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_clk.c b/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_clk.c new file mode 100644 index 0000000..e3e059c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_clk.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 NXP + * + * Brief CAAM Clock functions. + */ +#include +#include + +void caam_hal_clk_enable(bool enable __unused) +{ +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_ctrl.c b/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_ctrl.c new file mode 100644 index 0000000..dab1821 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_ctrl.c @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 NXP + * + * Brief CAAM Controller Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include + +void caam_hal_ctrl_init(vaddr_t baseaddr __unused) +{ +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_jr.c b/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_jr.c new file mode 100644 index 0000000..7352677 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/ls/hal_jr.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 NXP + * + * Brief CAAM Job Rings Hardware Abstration Layer. + * Implementation of primitives to access HW. + */ +#include +#include +#include +#include +#include + +enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, + enum caam_jr_owner owner) +{ + uint32_t val = 0; + unsigned int jr_idx = JRX_IDX(jr_offset); + + if (owner == JROWN_ARM_S) { + /* Read the Job Ring Lock bit */ + val = io_caam_read32(ctrl_base + JRxMIDR_MS(jr_idx)); + HAL_TRACE("JR%" PRIu32 "MIDR_MS value 0x%" PRIx32, jr_idx, val); + val |= JRxMIDR_MS_TZ; + + io_caam_write32(ctrl_base + JRxMIDR_MS(jr_idx), val); + } + + return CAAM_NO_ERROR; +} + +void caam_hal_jr_prepare_backup(vaddr_t ctrl_base __unused, + paddr_t jr_offset __unused) +{ +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h b/optee/optee_os/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h new file mode 100644 index 0000000..2432b95 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019, 2021 NXP + * + * Brief Control Registers. + */ +#ifndef __CTRL_REGS_H__ +#define __CTRL_REGS_H__ + +#include + +/* Master Configuration */ +#define MCFGR 0x0004 +#define MCFGR_WDE BIT32(30) +#define MCFGR_AXIPIPE(val) SHIFT_U32(val, 4) +#define BM_MCFGR_AXIPIPE SHIFT_U32(0xF, 4) + +/* Job Ring x MID */ +#define JRxMIDR_SIZE 0x8 +#define JR0MIDR_MS 0x0010 +#define JR0MIDR_LS 0x0014 +#define JRxMIDR_MS(idx) (JR0MIDR_MS + (idx) * JRxMIDR_SIZE) +#define JRxMIDR_LS(idx) (JR0MIDR_LS + (idx) * JRxMIDR_SIZE) + +#define JRxMIDR_MS_LMID BIT32(31) +#define JRxMIDR_MS_LAMTD BIT32(17) +#define JRxMIDR_MS_TZ BIT32(15) +#define JRxMIDR_MS_AMTD BIT32(16) +#define JRxMIDR_MS_JROWN_NS BIT32(3) +#define JRxMIDR_MS_JROWN_MID(val) SHIFT_U32((val) & 0x7, 0) + +#define JRxMIDR_LS_NONSEQ_NS BIT32(19) +#define JRxMIDR_LS_NONSEQ_MID(val) SHIFT_U32((val) & 0x7, 16) +#define JRxMIDR_LS_SEQ_NS BIT32(3) +#define JRxMIDR_LS_SEQ_MID(val) SHIFT_U32((val) & 0x7, 0) + +/* Security Configuration */ +#define SCFGR 0x000C + +#endif /* __CTRL_REGS_H__ */ + diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/ls/sub.mk b/optee/optee_os/core/drivers/crypto/caam/hal/ls/sub.mk new file mode 100644 index 0000000..5231cce --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/ls/sub.mk @@ -0,0 +1,7 @@ +incdirs-y += ../common +incdirs-y += ../../include +incdirs-y += . + +srcs-y += hal_clk.c +srcs-y += hal_ctrl.c +srcs-y += hal_jr.c diff --git a/optee/optee_os/core/drivers/crypto/caam/hal/sub.mk b/optee/optee_os/core/drivers/crypto/caam/hal/sub.mk new file mode 100644 index 0000000..779a972 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hal/sub.mk @@ -0,0 +1,19 @@ +ifeq ($(CFG_LS),y) +CAAM_HAL_DIR = ls +endif +ifeq ($(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX7ULP)),y) +CAAM_HAL_DIR = imx_6_7 +endif +ifeq ($(filter y, $(CFG_MX8MQ) $(CFG_MX8MM) $(CFG_MX8MN) $(CFG_MX8MP)),y) +CAAM_HAL_DIR = imx_8m +endif +ifeq ($(filter y, $(CFG_MX8QM) $(CFG_MX8QX)),y) +CAAM_HAL_DIR = imx_8q +endif +ifeq ($(filter y, $(CFG_MX8ULP)),y) +CAAM_HAL_DIR = imx_8ulp +endif + + +subdirs-y += common +subdirs-y += $(CAAM_HAL_DIR) diff --git a/optee/optee_os/core/drivers/crypto/caam/hash/caam_hash.c b/optee/optee_os/core/drivers/crypto/caam/hash/caam_hash.c new file mode 100644 index 0000000..fbcf4a4 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hash/caam_hash.c @@ -0,0 +1,719 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019, 2021 NXP + * + * Implementation of Hashing functions. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +static const struct crypto_hash_ops hash_ops; + +/* + * Maximum number of entries in the descriptor + */ +#define MAX_DESC_ENTRIES 20 + +/* + * Constants definition of the hash/HMAC algorithm + */ +static const struct hashalg hash_alg[] = { + { + /* md5 */ + .type = OP_ALGO(MD5), + .size_digest = TEE_MD5_HASH_SIZE, + .size_block = TEE_MD5_HASH_SIZE * 4, + .size_ctx = HASH_MSG_LEN + TEE_MD5_HASH_SIZE, + .size_key = 32, + }, + { + /* sha1 */ + .type = OP_ALGO(SHA1), + .size_digest = TEE_SHA1_HASH_SIZE, + .size_block = TEE_MAX_HASH_SIZE, + .size_ctx = HASH_MSG_LEN + TEE_SHA1_HASH_SIZE, + .size_key = 40, + }, + { + /* sha224 */ + .type = OP_ALGO(SHA224), + .size_digest = TEE_SHA224_HASH_SIZE, + .size_block = TEE_MAX_HASH_SIZE, + .size_ctx = HASH_MSG_LEN + TEE_SHA256_HASH_SIZE, + .size_key = 64, + }, + { + /* sha256 */ + .type = OP_ALGO(SHA256), + .size_digest = TEE_SHA256_HASH_SIZE, + .size_block = TEE_MAX_HASH_SIZE, + .size_ctx = HASH_MSG_LEN + TEE_SHA256_HASH_SIZE, + .size_key = 64, + }, + { + /* sha384 */ + .type = OP_ALGO(SHA384), + .size_digest = TEE_SHA384_HASH_SIZE, + .size_block = TEE_MAX_HASH_SIZE * 2, + .size_ctx = HASH_MSG_LEN + TEE_SHA512_HASH_SIZE, + .size_key = 128, + }, + { + /* sha512 */ + .type = OP_ALGO(SHA512), + .size_digest = TEE_SHA512_HASH_SIZE, + .size_block = TEE_MAX_HASH_SIZE * 2, + .size_ctx = HASH_MSG_LEN + TEE_SHA512_HASH_SIZE, + .size_key = 128, + }, +}; + +/* + * Format the hash context to keep the reference to the + * operation driver + */ +struct crypto_hash { + struct crypto_hash_ctx hash_ctx; /* Crypto Hash API context */ + struct hashctx *ctx; /* Hash Context */ +}; + +/* + * Keep the HW hash limit because after the initialization + * of the module, we don't have the CAAM Controller base address + * to call the function returning the HW capacity. + */ +static uint8_t caam_hash_limit; + +/* + * Returns the reference to the driver context + * + * @ctx API Context + */ +static struct crypto_hash *to_hash_ctx(struct crypto_hash_ctx *ctx) +{ + assert(ctx && ctx->ops == &hash_ops); + + return container_of(ctx, struct crypto_hash, hash_ctx); +} + +/* + * Add the load key in the CAAM descriptor and clean the key buffer. + * + * @desc CAAM Descriptor + * @key Key to load + */ +static void do_desc_load_key(uint32_t *desc, struct caambuf *key) +{ + HASH_TRACE("Insert Key"); + caam_desc_add_word(desc, LD_KEY_SPLIT(key->length)); + caam_desc_add_ptr(desc, key->paddr); + + cache_operation(TEE_CACHECLEAN, key->data, key->length); +} + +/* + * Free the internal hashing data context + * + * @ctx [in/out] Caller context variable + */ +static void do_free_intern(struct hashctx *ctx) +{ + HASH_TRACE("Free Context (%p)", ctx); + + if (ctx) { + /* Free the descriptor */ + caam_free_desc(&ctx->descriptor); + + /* Free the Temporary buffer */ + caam_free_buf(&ctx->blockbuf.buf); + + /* Free the context register */ + caam_free_buf(&ctx->ctx); + + /* Free the HMAC Key */ + caam_free_buf(&ctx->key); + } +} + +/* + * Initialization of the Hash operation + * Call common initialization operation between hash and HMAC + * + * @ctx Operation software context + */ +static TEE_Result do_hash_init(struct crypto_hash_ctx *ctx) +{ + struct crypto_hash *hash = to_hash_ctx(ctx); + + return caam_hash_hmac_init(hash->ctx); +} + +/* + * Update the Hash operation + * Call common update operation between hash and HMAC + * + * @ctx Operation software context + * @data Data to hash + * @len Data length + */ +static TEE_Result do_hash_update(struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len) +{ + struct crypto_hash *hash = to_hash_ctx(ctx); + + return caam_hash_hmac_update(hash->ctx, data, len); +} + +/* + * Finalize the Hash operation + * Call common final operation between hash and HMAC + * + * @ctx Operation software context + * @digest [out] Hash digest buffer + * @len Digest buffer length + */ +static TEE_Result do_hash_final(struct crypto_hash_ctx *ctx, uint8_t *digest, + size_t len) +{ + struct crypto_hash *hash = to_hash_ctx(ctx); + + return caam_hash_hmac_final(hash->ctx, digest, len); +} + +/* + * Free the SW hashing data context + * Call common free operation between hash and HMAC + * + * @ctx [in/out] Caller context variable + */ +static void do_hash_free(struct crypto_hash_ctx *ctx) +{ + struct crypto_hash *hash = to_hash_ctx(ctx); + + caam_hash_hmac_free(hash->ctx); + + free(hash); +} + +/* + * Copy Software Hashing Context + * Call common copy operation between hash and HMAC + * + * @dst_ctx [out] Reference the context destination + * @src_ctx Reference the context source + */ +static void do_hash_copy_state(struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx) +{ + struct crypto_hash *hash_src = to_hash_ctx(src_ctx); + struct crypto_hash *hash_dst = to_hash_ctx(dst_ctx); + + return caam_hash_hmac_copy_state(hash_dst->ctx, hash_src->ctx); +} + +/* + * Registration of the hash Driver + */ +static const struct crypto_hash_ops hash_ops = { + .init = do_hash_init, + .update = do_hash_update, + .final = do_hash_final, + .free_ctx = do_hash_free, + .copy_state = do_hash_copy_state, +}; + +/* + * Allocate the internal hashing data context + * + * @ctx [out] Caller context variable + * @algo Algorithm ID + */ +static TEE_Result caam_hash_allocate(struct crypto_hash_ctx **ctx, + uint32_t algo) +{ + struct crypto_hash *hash = NULL; + struct hashctx *hash_ctx = NULL; + const struct hashalg *alg = NULL; + TEE_Result ret = TEE_ERROR_GENERIC; + + HASH_TRACE("Allocate Context (%p) algo %" PRId32, ctx, algo); + + *ctx = NULL; + + alg = caam_hash_get_alg(algo); + if (!alg) + return TEE_ERROR_NOT_IMPLEMENTED; + + hash = calloc(1, sizeof(*hash)); + if (!hash) + return TEE_ERROR_OUT_OF_MEMORY; + + hash_ctx = caam_calloc(sizeof(*hash_ctx)); + if (!hash_ctx) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + hash_ctx->alg = alg; + hash->hash_ctx.ops = &hash_ops; + hash->ctx = hash_ctx; + + *ctx = &hash->hash_ctx; + + ret = caam_hash_hmac_allocate(hash_ctx); + if (ret != TEE_SUCCESS) + goto err; + + HASH_TRACE("Allocated Context (%p)", hash_ctx); + + return TEE_SUCCESS; + +err: + free(hash); + + if (hash_ctx) + caam_free(hash_ctx); + + return ret; +} + +TEE_Result caam_hash_hmac_allocate(struct hashctx *ctx) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + HASH_TRACE("Allocate Context (%p)", ctx); + + /* Allocate the descriptor */ + ctx->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES); + if (!ctx->descriptor) { + HASH_TRACE("Allocation context descriptor error"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + /* Initialize the block buffer */ + ctx->blockbuf.filled = 0; + ctx->blockbuf.max = ctx->alg->size_block; + + /* Allocate the CAAM Context register */ + if (caam_calloc_align_buf(&ctx->ctx, ctx->alg->size_ctx) != + CAAM_NO_ERROR) { + HASH_TRACE("Allocation context register error"); + ret = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + /* Allocate the Hash Key */ + if (caam_calloc_align_buf(&ctx->key, ctx->alg->size_key) != + CAAM_NO_ERROR) { + HASH_TRACE("Allocation context key error"); + ret = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + cache_operation(TEE_CACHEFLUSH, ctx->ctx.data, ctx->ctx.length); + + /* Ensure buffer length is 0 */ + ctx->ctx.length = 0; + + return TEE_SUCCESS; + +err: + do_free_intern(ctx); + + return ret; +} + +/* + * Free the SW hashing data context + * + * @ctx Caller context variable + */ +void caam_hash_hmac_free(struct hashctx *ctx) +{ + HASH_TRACE("Free Context (%p)", ctx); + + if (ctx) { + do_free_intern(ctx); + caam_free(ctx); + } +} + +const struct hashalg *caam_hash_get_alg(uint32_t algo) +{ + uint8_t hash_id = TEE_ALG_GET_MAIN_ALG(algo); + unsigned int idx = hash_id - TEE_MAIN_ALGO_MD5; + + if (hash_id > caam_hash_limit || idx > ARRAY_SIZE(hash_alg)) + return NULL; + + return &hash_alg[idx]; +} + +TEE_Result caam_hash_hmac_init(struct hashctx *ctx) +{ + HASH_TRACE("Hash/HMAC Init (%p)", ctx); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + /* Initialize the block buffer */ + ctx->blockbuf.filled = 0; + ctx->blockbuf.max = ctx->alg->size_block; + + /* Ensure Context length is 0 */ + ctx->ctx.length = 0; + + /* Initialize the HMAC Key */ + ctx->key.length = 0; + + ctx->initialized = true; + + return TEE_SUCCESS; +} + +/* + * Build and run the CAAM Hash descriptor to update (or start) the + * data digest. + * + * @ctx [in/out] Caller context variable + * @src Input data to digest + */ +static TEE_Result do_update_hash(struct hashctx *ctx, struct caamdmaobj *src) +{ + enum caam_status retstatus = CAAM_FAILURE; + const struct hashalg *alg = ctx->alg; + struct caam_jobctx jobctx = { }; + uint32_t *desc = ctx->descriptor; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + + /* There are blocks to hash - Create the Descriptor */ + if (ctx->ctx.length) { + HASH_TRACE("Update Operation"); + /* Algo Operation - Update */ + caam_desc_add_word(desc, HASH_UPDATE(alg->type)); + /* Running context to restore */ + caam_desc_add_word(desc, + LD_NOIMM(CLASS_2, REG_CTX, ctx->ctx.length)); + caam_desc_add_ptr(desc, ctx->ctx.paddr); + } else { + HASH_TRACE("Init Operation"); + + /* Check if there is a key to load it */ + if (ctx->key.length) { + do_desc_load_key(desc, &ctx->key); + + /* Algo Operation - HMAC Init */ + caam_desc_add_word(desc, HMAC_INIT_PRECOMP(alg->type)); + } else { + /* Algo Operation - Init */ + caam_desc_add_word(desc, HASH_INIT(alg->type)); + } + ctx->ctx.length = alg->size_ctx; + } + + if (ctx->blockbuf.filled) { + caam_desc_add_word(desc, FIFO_LD(CLASS_2, MSG, NOACTION, + ctx->blockbuf.filled)); + caam_desc_add_ptr(desc, ctx->blockbuf.buf.paddr); + cache_operation(TEE_CACHECLEAN, ctx->blockbuf.buf.data, + ctx->blockbuf.filled); + } + + caam_desc_fifo_load(desc, src, CLASS_2, MSG, LAST_C2); + caam_dmaobj_cache_push(src); + + ctx->blockbuf.filled = 0; + + if (ctx->ctx.length) { + /* Save the running context */ + caam_desc_add_word(desc, + ST_NOIMM(CLASS_2, REG_CTX, ctx->ctx.length)); + caam_desc_add_ptr(desc, ctx->ctx.paddr); + + /* Ensure Context register data are not in cache */ + cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data, + ctx->ctx.length); + } + + HASH_DUMPDESC(desc); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus != CAAM_NO_ERROR) { + HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + return job_status_to_tee_result(jobctx.status); + } + + HASH_DUMPBUF("CTX", ctx->ctx.data, ctx->ctx.length); + + return TEE_SUCCESS; +} + +TEE_Result caam_hash_hmac_update(struct hashctx *ctx, const uint8_t *data, + size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + const struct hashalg *alg = NULL; + size_t fullsize = 0; + size_t size_topost = 0; + size_t size_todo = 0; + size_t size_done = 0; + size_t size_inmade = 0; + struct caamdmaobj src = { }; + size_t offset = 0; + + HASH_TRACE("Hash/HMAC Update (%p) %p - %zu", ctx, data, len); + + if ((!data && len) || !ctx) + return TEE_ERROR_BAD_PARAMETERS; + + alg = ctx->alg; + + if (!ctx->ctx.data) + return TEE_ERROR_GENERIC; + + HASH_TRACE("Update Type 0x%" PRIX32 " - Input @%p-%zu", alg->type, data, + len); + + /* Calculate the total data to be handled */ + fullsize = ctx->blockbuf.filled + len; + size_topost = fullsize % alg->size_block; + size_todo = fullsize - size_topost; + size_inmade = len - size_topost; + HASH_TRACE("FullSize %zu - posted %zu - todo %zu", fullsize, + size_topost, size_todo); + + if (!size_todo) { + ret = TEE_SUCCESS; + + /* All input data must be saved */ + if (size_topost) + size_inmade = 0; + + goto save_posted; + } + + ret = caam_dmaobj_init_input(&src, data, size_inmade); + if (ret) + goto exit_update; + + ret = caam_dmaobj_prepare(&src, NULL, alg->size_block); + if (ret) + goto exit_update; + + size_todo = size_inmade; + + for (offset = 0; offset < size_inmade; + offset += size_done, size_todo -= size_done) { + size_done = size_todo; + HASH_TRACE("Do input %zu bytes, offset %zu", size_done, offset); + + ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, + alg->size_block); + if (ret) + goto exit_update; + + /* + * Need to re-adjust the length of the data if the + * posted data block is not empty and the SGT/Buffer + * is part of the full input data to do. + */ + if (ctx->blockbuf.filled && size_done < size_todo) { + size_done -= ctx->blockbuf.filled; + src.sgtbuf.length = size_done; + } + + ret = do_update_hash(ctx, &src); + if (ret) + goto exit_update; + } + +save_posted: + if (size_topost && data) { + struct caambuf srcdata = { + .data = (uint8_t *)data, + .length = len, + }; + + HASH_TRACE("Posted %zu of input len %zu made %zu", size_topost, + len, size_inmade); + + retstatus = caam_cpy_block_src(&ctx->blockbuf, &srcdata, + size_inmade); + ret = caam_status_to_tee_result(retstatus); + } + +exit_update: + caam_dmaobj_free(&src); + + if (ret) + do_free_intern(ctx); + + return ret; +} + +TEE_Result caam_hash_hmac_final(struct hashctx *ctx, uint8_t *digest, + size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + const struct hashalg *alg = NULL; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + struct caamdmaobj dig = { }; + + HASH_TRACE("Hash/HMAC Final (%p)", ctx); + + if (!digest || !len || !ctx) + return TEE_ERROR_BAD_PARAMETERS; + + alg = ctx->alg; + + if (!ctx->ctx.data) + return TEE_ERROR_GENERIC; + + ret = caam_dmaobj_output_sgtbuf(&dig, digest, len, alg->size_digest); + if (ret) + goto out; + + HASH_TRACE("Final Type 0x%" PRIX32 " - Digest %zu", alg->type, len); + + desc = ctx->descriptor; + caam_desc_init(desc); + + /* Set the descriptor Header with length */ + caam_desc_add_word(desc, DESC_HEADER(0)); + + /* Load key if any */ + if (ctx->key.length) + do_desc_load_key(desc, &ctx->key); + + if (ctx->ctx.length) { + HASH_TRACE("Final Operation"); + + if (ctx->key.length) + caam_desc_add_word(desc, HMAC_FINAL_PRECOMP(alg->type)); + else + caam_desc_add_word(desc, HASH_FINAL(alg->type)); + + /* Running context to restore */ + caam_desc_add_word(desc, + LD_NOIMM(CLASS_2, REG_CTX, ctx->ctx.length)); + caam_desc_add_ptr(desc, ctx->ctx.paddr); + + cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data, + ctx->ctx.length); + HASH_DUMPBUF("CTX", ctx->ctx.data, ctx->ctx.length); + ctx->ctx.length = 0; + } else { + HASH_TRACE("Init/Final Operation"); + if (ctx->key.length) + caam_desc_add_word(desc, + HMAC_INITFINAL_PRECOMP(alg->type)); + else + caam_desc_add_word(desc, HASH_INITFINAL(alg->type)); + } + + HASH_DUMPBUF("Temporary Block", ctx->blockbuf.buf.data, + ctx->blockbuf.filled); + + caam_desc_add_word(desc, FIFO_LD_EXT(CLASS_2, MSG, LAST_C2)); + caam_desc_add_ptr(desc, ctx->blockbuf.buf.paddr); + caam_desc_add_word(desc, ctx->blockbuf.filled); + + if (ctx->blockbuf.filled) + cache_operation(TEE_CACHECLEAN, ctx->blockbuf.buf.data, + ctx->blockbuf.filled); + + ctx->blockbuf.filled = 0; + + /* Save the final digest */ + caam_desc_store(desc, &dig, CLASS_2, REG_CTX); + caam_dmaobj_cache_push(&dig); + + HASH_DUMPDESC(desc); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + caam_dmaobj_copy_to_orig(&dig); + + HASH_DUMPBUF("Digest", digest, (size_t)alg->size_digest); + + ret = TEE_SUCCESS; + } else { + HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_dmaobj_free(&dig); + + return ret; +} + +void caam_hash_hmac_copy_state(struct hashctx *dst, struct hashctx *src) +{ + HASH_TRACE("Copy State context (%p) to (%p)", src, dst); + + assert(dst && src); + + if (!dst->initialized && caam_hash_hmac_init(dst)) + panic(); + + dst->alg = src->alg; + + if (src->ctx.length) { + cache_operation(TEE_CACHEINVALIDATE, src->ctx.data, + src->ctx.length); + memcpy(dst->ctx.data, src->ctx.data, src->ctx.length); + dst->ctx.length = src->ctx.length; + cache_operation(TEE_CACHECLEAN, dst->ctx.data, dst->ctx.length); + } + + if (src->blockbuf.filled) { + struct caambuf srcdata = { + .data = src->blockbuf.buf.data, + .length = src->blockbuf.filled + }; + + caam_cpy_block_src(&dst->blockbuf, &srcdata, 0); + } + + if (src->key.data) { + memcpy(dst->key.data, src->key.data, src->key.length); + dst->key.length = src->key.length; + } +} + +enum caam_status caam_hash_init(struct caam_jrcfg *caam_jrcfg) +{ + enum caam_status retstatus = CAAM_FAILURE; + vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; + + caam_hash_limit = caam_hal_ctrl_hash_limit(jr_base); + + if (caam_hash_limit != UINT8_MAX) { + if (drvcrypt_register_hash(&caam_hash_allocate) == TEE_SUCCESS) + retstatus = CAAM_NO_ERROR; + } + + return retstatus; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c b/optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c new file mode 100644 index 0000000..423e90f --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hash/caam_hash_mac.c @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Implementation of Hashing functions. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +#ifdef CFG_PHYS_64BIT +#define KEY_REDUCE_DESC_ENTRIES 10 +#define KEY_COMPUTE_DESC_ENTRIES 10 +#else +#define KEY_REDUCE_DESC_ENTRIES 8 +#define KEY_COMPUTE_DESC_ENTRIES 8 +#endif + +static const struct crypto_mac_ops hmac_ops; + +/* + * Format the MAC context to keep the reference to the operation driver. + */ +struct crypto_mac { + struct crypto_mac_ctx mac_ctx; /* Crypto MAC API context */ + struct hashctx *ctx; /* HMAC context */ +}; + +/* + * Keep the HW hash limit because after the initialization + * of the module, we don't have the CAAM Controller base address + * to call the function returning the HW capacity. + */ +static uint8_t caam_hash_limit; + +/* + * Returns the reference to the driver context + * + * @ctx API Context + */ +static struct crypto_mac *to_mac_ctx(struct crypto_mac_ctx *ctx) +{ + assert(ctx && ctx->ops == &hmac_ops); + + return container_of(ctx, struct crypto_mac, mac_ctx); +} + +/* + * Reduce key to be a hash algorithm block size maximum + * + * @alg Reference to the algorithm definition + * @inkey Key to be reduced + * @outkey [out] key resulting + */ +static enum caam_status do_reduce_key(struct caamdmaobj *reduce_key, + const struct hashalg *alg, + const uint8_t *inkey, size_t len) +{ + enum caam_status retstatus = CAAM_FAILURE; + struct caamdmaobj key = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + + if (caam_dmaobj_input_sgtbuf(&key, inkey, len)) + return CAAM_OUT_MEMORY; + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(KEY_REDUCE_DESC_ENTRIES); + if (!desc) { + retstatus = CAAM_OUT_MEMORY; + goto out; + } + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, HASH_INITFINAL(alg->type)); + + /* Load the input key */ + caam_desc_fifo_load(desc, &key, CLASS_2, MSG, LAST_C2); + /* Store key reduced */ + caam_desc_store(desc, reduce_key, CLASS_2, REG_CTX); + + caam_dmaobj_cache_push(&key); + caam_dmaobj_cache_push(reduce_key); + + HASH_DUMPDESC(desc); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus != CAAM_NO_ERROR) { + HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + retstatus = CAAM_FAILURE; + } + +out: + caam_dmaobj_free(&key); + caam_free_desc(&desc); + + return retstatus; +} + +/* + * Initialization of the HMAC operation. + * Split the input key using the CAAM HW HMAC operation + * Call common initialization operation between hash and HMAC + * + * @ctx Operation software context + * @key Input key to compute + * @len Key length + */ +static TEE_Result do_hmac_init(struct crypto_mac_ctx *ctx, const uint8_t *inkey, + size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct crypto_mac *mac = to_mac_ctx(ctx); + struct hashctx *hmac_ctx = mac->ctx; + const struct hashalg *alg = hmac_ctx->alg; + struct caamdmaobj reduce_key = { }; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + + /* First initialize the context */ + ret = caam_hash_hmac_init(hmac_ctx); + if (ret != TEE_SUCCESS) + return ret; + + HASH_TRACE("split key length %zu", len); + + /* Allocate the job descriptor */ + desc = caam_calloc_desc(KEY_COMPUTE_DESC_ENTRIES); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + hmac_ctx->key.length = alg->size_key; + + if (len > alg->size_block) { + HASH_TRACE("Input key must be reduced"); + + ret = caam_dmaobj_output_sgtbuf(&reduce_key, NULL, 0, + alg->size_digest); + if (ret) { + HASH_TRACE("Reduced Key allocation error"); + goto out; + } + + retstatus = do_reduce_key(&reduce_key, alg, inkey, len); + if (retstatus != CAAM_NO_ERROR) + goto out; + } else { + /* Key size is correct use directly the input key */ + ret = caam_dmaobj_input_sgtbuf(&reduce_key, inkey, len); + if (ret) + goto out; + } + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + /* Load either input key or the reduced input key into key register */ + caam_desc_load_key(desc, &reduce_key, CLASS_2, REG); + /* Split the key */ + caam_desc_add_word(desc, HMAC_INIT_DECRYPT(alg->type)); + caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_2, MSG, LAST_C2, 0)); + /* Store the split key */ + caam_desc_add_word(desc, FIFO_ST(C2_MDHA_SPLIT_KEY_AES_ECB_JKEK, + hmac_ctx->key.length)); + caam_desc_add_ptr(desc, hmac_ctx->key.paddr); + HASH_DUMPDESC(desc); + + caam_dmaobj_cache_push(&reduce_key); + cache_operation(TEE_CACHEFLUSH, hmac_ctx->key.data, + hmac_ctx->key.length); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + HASH_DUMPBUF("Split Key", hmac_ctx->key.data, + hmac_ctx->key.length); + + ret = TEE_SUCCESS; + } else { + HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +out: + caam_dmaobj_free(&reduce_key); + caam_free_desc(&desc); + + return ret; +} + +/* + * Update the HMAC operation + * Call common update operation between hash and HMAC + * + * @ctx Operation Software context + * @data Data to hash + * @len Data length + */ +static TEE_Result do_hmac_update(struct crypto_mac_ctx *ctx, + const uint8_t *data, size_t len) +{ + struct crypto_mac *mac = to_mac_ctx(ctx); + + return caam_hash_hmac_update(mac->ctx, data, len); +} + +/* + * Finalize the HMAC operation + * Call common final operation between hash and HMAC + * + * @ctx Operation Software context + * @digest [out] Hash digest buffer + * @len Digest buffer length + */ +static TEE_Result do_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, + size_t len) +{ + struct crypto_mac *mac = to_mac_ctx(ctx); + + return caam_hash_hmac_final(mac->ctx, digest, len); +} + +/* + * Free the software context + * Call common free operation between hash and HMAC + * + * @ctx Caller context variable + */ +static void do_hmac_free(struct crypto_mac_ctx *ctx) +{ + struct crypto_mac *mac = to_mac_ctx(ctx); + + caam_hash_hmac_free(mac->ctx); + + free(mac); +} + +/* + * Copy sofware HMAC context + * Call common copy operation between hash and HMAC + * + * @dst_ctx [out] Reference the context destination + * @src_ctx Reference the context source + */ +static void do_hmac_copy_state(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx) +{ + struct crypto_mac *mac_src = to_mac_ctx(src_ctx); + struct crypto_mac *mac_dst = to_mac_ctx(dst_ctx); + + return caam_hash_hmac_copy_state(mac_dst->ctx, mac_src->ctx); +} + +/* + * Registration of the HMAC driver + */ +static const struct crypto_mac_ops hmac_ops = { + .init = do_hmac_init, + .update = do_hmac_update, + .final = do_hmac_final, + .free_ctx = do_hmac_free, + .copy_state = do_hmac_copy_state, +}; + +/* + * Allocate the internal hashing data context + * + * @ctx [out] Caller context reference + * @algo Algorithm ID + */ +static TEE_Result caam_hmac_allocate(struct crypto_mac_ctx **ctx, uint32_t algo) +{ + struct crypto_mac *mac = NULL; + struct hashctx *hmac_ctx = NULL; + const struct hashalg *alg = NULL; + TEE_Result ret = TEE_ERROR_GENERIC; + + HASH_TRACE("Allocate Context (%p) algo %" PRId32, ctx, algo); + + *ctx = NULL; + + alg = caam_hash_get_alg(algo); + if (!alg) + return TEE_ERROR_NOT_IMPLEMENTED; + + mac = calloc(1, sizeof(*mac)); + if (!mac) + return TEE_ERROR_OUT_OF_MEMORY; + + hmac_ctx = caam_calloc(sizeof(*hmac_ctx)); + if (!hmac_ctx) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + hmac_ctx->alg = alg; + mac->mac_ctx.ops = &hmac_ops; + mac->ctx = hmac_ctx; + + *ctx = &mac->mac_ctx; + + ret = caam_hash_hmac_allocate(hmac_ctx); + if (ret != TEE_SUCCESS) + goto err; + + HASH_TRACE("Allocated Context (%p)", hmac_ctx); + + return TEE_SUCCESS; + +err: + free(mac); + + if (hmac_ctx) + caam_free(hmac_ctx); + + return ret; +} + +enum caam_status caam_hmac_init(struct caam_jrcfg *caam_jrcfg) +{ + vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; + + caam_hash_limit = caam_hal_ctrl_hash_limit(jr_base); + + if (caam_hash_limit != UINT8_MAX && + caam_hal_ctrl_splitkey_support(jr_base)) { + if (drvcrypt_register_hmac(&caam_hmac_allocate)) + return CAAM_FAILURE; + } + + return CAAM_NO_ERROR; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/hash/local.h b/optee/optee_os/core/drivers/crypto/caam/hash/local.h new file mode 100644 index 0000000..01da063 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hash/local.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019-2021 NXP + * + * CAAM hash/HMAC local header. + */ +#ifndef __LOCAL_H__ +#define __LOCAL_H__ + +#include + +/* + * Full hashing/HMAC data SW context + */ +struct hashctx { + uint32_t *descriptor; /* Job descriptor */ + struct caamblock blockbuf; /* Temporary block buffer */ + struct caambuf ctx; /* Hash context used by the CAAM */ + const struct hashalg *alg; /* Reference to the algo constants */ + struct caambuf key; /* HMAC split key */ + bool initialized; /* Context initialization flag */ +}; + +/* + * Hash/HMAC algorithm definition + */ +struct hashalg { + uint32_t type; /* Algo type for operation */ + uint8_t size_digest; /* Digest size */ + uint8_t size_block; /* Computing block size */ + uint8_t size_ctx; /* CAAM context register size (8 + digest size) */ + uint8_t size_key; /* HMAC split key size */ +}; + +/* First part CAAM HW context - message length */ +#define HASH_MSG_LEN 8 + +/* + * Initialization of the hash/HMAC operation + * + * @ctx Operation software context + */ +TEE_Result caam_hash_hmac_init(struct hashctx *ctx); + +/* + * Update the hash/HMAC operation + * + * @ctx Operation software context + * @data Data to hash + * @len Data length + */ +TEE_Result caam_hash_hmac_update(struct hashctx *ctx, const uint8_t *data, + size_t len); + +/* + * Finalize the hash/HMAC operation + * + * @ctx Operation software context + * @digest [out] Hash digest buffer + * @len Digest buffer length + */ +TEE_Result caam_hash_hmac_final(struct hashctx *ctx, uint8_t *digest, + size_t len); + +/* + * Copy sofware hashing context + * + * @dst [out] Reference the destination context + * @src Reference the source context + */ +void caam_hash_hmac_copy_state(struct hashctx *dst, struct hashctx *src); + +/* + * Free the software context + * + * @ctx [in/out] Caller context variable + */ +void caam_hash_hmac_free(struct hashctx *ctx); + +/* + * Get hash/HMAC algorithm definition + * + * @algo Hash algorithm + */ +const struct hashalg *caam_hash_get_alg(uint32_t algo); + +/* + * Allocate the internal hashing data context + * + * @ctx [in/out] Caller context variable + */ +TEE_Result caam_hash_hmac_allocate(struct hashctx *ctx); + +#endif /* __LOCAL_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/hash/sub.mk b/optee/optee_os/core/drivers/crypto/caam/hash/sub.mk new file mode 100644 index 0000000..37f2b6e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/hash/sub.mk @@ -0,0 +1,4 @@ +incdirs-y += ../include + +srcs-y += caam_hash.c +srcs-$(CFG_NXP_CAAM_HMAC_DRV) += caam_hash_mac.c diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_acipher.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_acipher.h new file mode 100644 index 0000000..6cdb85a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_acipher.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief CAAM Asymmetric Cipher manager header. + */ +#ifndef __CAAM_ACIPHER_H__ +#define __CAAM_ACIPHER_H__ + +#include +#include + +#ifdef CFG_NXP_CAAM_RSA_DRV +/* + * Initialize the RSA module + * + * @caam_jrcfg JR configuration structure + */ +enum caam_status caam_rsa_init(struct caam_jrcfg *caam_jrcfg); +#else +static inline enum caam_status +caam_rsa_init(struct caam_jrcfg *caam_jrcfg __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_RSA_DRV */ + +#ifdef CFG_NXP_CAAM_DH_DRV +/* + * Initialize the DH module + * + * @caam_jrcfg JR configuration structure + */ +enum caam_status caam_dh_init(struct caam_jrcfg *caam_jrcfg); +#else +static inline enum caam_status +caam_dh_init(struct caam_jrcfg *caam_jrcfg __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_DH_DRV */ + +#ifdef CFG_NXP_CAAM_MATH_DRV +/* + * Initialize the MATH module + * + * @caam_jrcfg JR configuration structure + */ +enum caam_status caam_math_init(struct caam_jrcfg *caam_jrcfg); +#else +static inline enum caam_status +caam_math_init(struct caam_jrcfg *caam_jrcfg __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_MATH_DRV */ + +#ifdef CFG_NXP_CAAM_ECC_DRV +/* + * Initialize the Cipher module + * + * @caam_jrcfg JR configuration structure + */ +enum caam_status caam_ecc_init(struct caam_jrcfg *caam_jrcfg); +#else +static inline enum caam_status +caam_ecc_init(struct caam_jrcfg *caam_jrcfg __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_ECC_DRV */ + +#ifdef CFG_NXP_CAAM_DSA_DRV +/* + * Initialize the DSA module + * + * @caam_jrcfg CAAM job ring configuration + */ +enum caam_status caam_dsa_init(struct caam_jrcfg *caam_jrcfg); +#else +static inline enum caam_status +caam_dsa_init(struct caam_jrcfg *caam_jrcfg __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_DSA_DRV */ +#endif /* __CAAM_ACIPHER_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_blob.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_blob.h new file mode 100644 index 0000000..768cdaa --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_blob.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020 Pengutronix, Rouven Czerwinski + */ +#ifndef __CAAM_BLOB_H__ +#define __CAAM_BLOB_H__ + +#include + +#ifdef CFG_NXP_CAAM_BLOB_DRV +/* + * Initialize the BLOB module + * + * @ctrl_addr Controller base address + */ +enum caam_status caam_blob_mkvb_init(vaddr_t baseaddr); +#else +static inline enum caam_status caam_blob_mkvb_init(vaddr_t baseaddr __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_BLOB_DRV */ + +#endif /* __CAAM_BLOB_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_cipher.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_cipher.h new file mode 100644 index 0000000..8a92f20 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_cipher.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2020 NXP + * + * Brief CAAM Cipher manager header. + */ +#ifndef __CAAM_CIPHER_H__ +#define __CAAM_CIPHER_H__ + +#include + +#ifdef CFG_NXP_CAAM_CIPHER_DRV +/* + * Initialize the Cipher module + * + * @ctrl_addr Controller base address + */ +enum caam_status caam_cipher_init(vaddr_t ctrl_addr); +#else +static inline enum caam_status caam_cipher_init(vaddr_t ctrl_addr __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_CIPHER_DRV */ +#ifdef CFG_NXP_CAAM_CMAC_DRV +/* + * Initialize the CMAC module + * + * @ctrl_addr Controller base address + */ +enum caam_status caam_cmac_init(vaddr_t ctrl_addr); +#else +static inline enum caam_status caam_cmac_init(vaddr_t ctrl_addr __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_CMAC_DRV */ +#endif /* __CAAM_CIPHER_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_common.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_common.h new file mode 100644 index 0000000..a502851 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_common.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019, 2021 NXP + * + * CAAM driver common include file. + */ + +#ifndef __CAAM_COMMON_H__ +#define __CAAM_COMMON_H__ + +#include +#include +#include +#include + +/* + * Definition of the number of CAAM Jobs to manage in JR queues + */ +#if defined(CFG_NB_JOBS_QUEUE) +#define NB_JOBS_QUEUE CFG_NB_JOBS_QUEUE +#else +#define NB_JOBS_QUEUE 10 +#endif + +/* + * Flag Job Ring Owner is Secure + */ +#define JROWNER_SECURE 0x10 + +/* + * Job Ring Owner. Enumerate Id (expect the Secure Flag) correspond + * to the HW ID. + */ +#if defined(CFG_MX7ULP) +enum caam_jr_owner { + JROWN_ARM_NS = 0x4, /* Non-Secure ARM */ + JROWN_ARM_S = JROWNER_SECURE | 0x4, /* Secure ARM */ +}; +#elif defined(CFG_MX8ULP) +enum caam_jr_owner { + JROWN_ARM_NS = 0x7, /* Non-Secure ARM */ + JROWN_ARM_S = JROWNER_SECURE | 0x7, /* Secure ARM */ +}; +#else +enum caam_jr_owner { + JROWN_ARM_NS = 0x1, /* Non-Secure ARM */ + JROWN_ARM_S = JROWNER_SECURE | 0x1, /* Secure ARM */ +}; +#endif + +#endif /* __CAAM_COMMON_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h new file mode 100644 index 0000000..8bfd512 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief Define the CCB Registers to use in the CAAM descriptor + */ +#ifndef __CAAM_DESC_CCB_DEFINES_H__ +#define __CAAM_DESC_CCB_DEFINES_H__ + +/* CCB CHA Control Register */ +#define CCTRL_ULOAD_PKHA_B BIT32(27) +#define CCTRL_ULOAD_PKHA_A BIT32(26) + +/* CCB Clear Written Register */ +#define CLR_WR_IFIFO_NFIFO BIT32(31) +#define CLR_WR_RST_C2_CHA BIT32(28) +#define CLR_WR_RST_C2_DSZ BIT32(18) + +/* CCB NFIFO */ +#define NFIFO_CLASS(cla) SHIFT_U32(NFIFO_CLASS_##cla & 0x3, 30) +#define NFIFO_CLASS_DECO 0x0 +#define NFIFO_CLASS_C1 0x1 +#define NFIFO_CLASS_BOTH 0x3 + +#define NFIFO_LC2 BIT32(29) +#define NFIFO_LC1 BIT32(28) +#define NFIFO_FC1 BIT32(26) + +#define NFIFO_STYPE(src) SHIFT_U32(NFIFO_STYPE_##src & 0x3, 24) +#define NFIFO_STYPE_IFIFO 0x0 +#define NFIFO_STYPE_PAD 0x2 + +#define NFIFO_DTYPE(data) SHIFT_U32(NFIFO_DTYPE_##data & 0xF, 20) +#define NFIFO_DTYPE_MSG 0xF +#define NFIFO_DTYPE_PKHA_N 0x8 +#define NFIFO_DTYPE_PKHA_A 0xC + +#define NFIFO_PTYPE(pad) SHIFT_U32(NFIFO_PTYPE_##pad & 0x7, 16) +#define NFIFO_PTYPE_ZERO 0x0 +#define NFIFO_PTYPE_RND 0x3 + +#define NFIFO_DATA_LENGTH(len) SHIFT_U32((len) & 0xFFF, 0) +#define NFIFO_PAD_LENGTH(len) SHIFT_U32((len) & 0x7F, 0) + +/* + * CCB NFIFO Entry to pad data with pad type + */ +#define NFIFO_PAD(cla, options, data, pad, len) \ + (NFIFO_CLASS(cla) | (options) | NFIFO_STYPE(PAD) | NFIFO_DTYPE(data) | \ + NFIFO_PTYPE(pad) | NFIFO_PAD_LENGTH(len)) + +/* + * CCB NFIFO Entry to move data from src to data + */ +#define NFIFO_NOPAD(cla, options, src, data, len) \ + (NFIFO_CLASS(cla) | (options) | NFIFO_STYPE(src) | NFIFO_DTYPE(data) | \ + NFIFO_PTYPE(ZERO) | NFIFO_DATA_LENGTH(len)) + +#endif /* __CAAM_DESC_CCB_DEFINES_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h new file mode 100644 index 0000000..684bb66 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_defines.h @@ -0,0 +1,715 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief CAAM Descriptor defines. + */ +#ifndef __CAAM_DESC_DEFINES_H__ +#define __CAAM_DESC_DEFINES_H__ + +#include + +/* + * Common Command constants + */ +#define CMD_TYPE(cmd) SHIFT_U32((cmd) & 0x1F, 27) +#define GET_CMD_TYPE(op) ((op) & (SHIFT_U32(0x1F, 27))) +#define CMD_CLASS(val) SHIFT_U32((val) & 0x3, 25) +#define CLASS_NO 0x0 +#define CLASS_1 0x1 +#define CLASS_2 0x2 +#define CLASS_DECO 0x3 + +#define CMD_SGT BIT32(24) +#define CMD_IMM BIT32(23) + +/* + * HEADER Job Descriptor Header format + */ +#define CMD_HDR_JD_TYPE CMD_TYPE(0x16) + +/* Must be ONE */ +#define HDR_JD_ONE BIT32(23) + +/* Start Index if SHR = 0 */ +#define HDR_JD_START_IDX(line) SHIFT_U32((line) & 0x3F, 16) + +/* Descriptor Length */ +#define HDR_JD_DESCLEN(len) SHIFT_U32((len) & 0x7F, 0) +#define GET_JD_DESCLEN(entry) ((entry) & 0x7F) + +/* + * KEY Command fields + */ +#define CMD_KEY_TYPE CMD_TYPE(0x00) + +/* Key Destination */ +#define KEY_DEST(val) SHIFT_U32((KEY_DEST_##val) & 0x3, 16) +#define KEY_DEST_REG 0x0 +#define KEY_DEST_PKHA_E 0x1 +#define KEY_DEST_AFHA_SBOX 0x2 +#define KEY_DEST_MDHA_SPLIT 0x3 + +/* Plaintext Store */ +#define KEY_PTS BIT32(14) + +/* Key Length */ +#define KEY_LENGTH(len) SHIFT_U32((len) & 0x3FF, 0) + +/* + * LOAD Command fields + */ +#define CMD_LOAD_TYPE CMD_TYPE(0x02) + +/* Load Destination */ +#define LOAD_DST(reg) SHIFT_U32((reg) & 0x7F, 16) + +/* Offset in destination register */ +#define LOAD_OFFSET(off) SHIFT_U32((off) & 0xFF, 8) + +/* Length */ +#define LOAD_LENGTH(len) SHIFT_U32((len) & 0xFF, 0) + +/* + * STORE Command fields + */ +#define CMD_STORE_TYPE CMD_TYPE(0x0A) +#define CMD_STORE_SEQ_TYPE CMD_TYPE(0x0B) + +/* Store Source */ +#define STORE_SRC(reg) SHIFT_U32((reg) & 0x7F, 16) + +/* Offset in source register */ +#define STORE_OFFSET(off) SHIFT_U32((off) & 0xFF, 8) + +/* Length */ +#define STORE_LENGTH(len) SHIFT_U32((len) & 0xFF, 0) + +/* + * Define the Load/Store Registers Source and Destination + */ +#define REG_MODE 0x00 +#define REG_KEY_SIZE 0x01 +#define REG_DATA_SIZE 0x02 +#define REG_ICV_SIZE 0x03 +#define REG_DECO_MID_STATUS 0x04 +#define REG_DECO_CTRL2 0x05 +#define REG_CHA_CTRL 0x06 +#define REG_DECO_CTRL 0x06 +#define REG_IRQ_CTRL 0x07 +#define REG_DECO_PROT_OVERWRITE 0x07 +#define REG_CLEAR_WRITTEN 0x08 +#define REG_MATH0 0x08 +#define REG_MATH1 0x09 +#define REG_MATH2 0x0A +#define REG_CHA_INST_SELECT 0x0A +#define REG_AAD_SIZE 0x0B +#define REG_MATH3 0x0B +#define REG_ALT_DATA_SIZE_C1 0x0F +#define REG_PKHA_A_SIZE 0x10 +#define REG_PKHA_B_SIZE 0x11 +#define REG_PKHA_N_SIZE 0x12 +#define REG_PKHA_E_SIZE 0x13 +#define REG_CTX 0x20 +#define REG_MATH0_DW 0x30 +#define REG_MATH1_DW 0x31 +#define REG_MATH2_DW 0x32 +#define REG_MATH3_DW 0x33 +#define REG_MATH0_B 0x38 +#define REG_MATH1_B 0x39 +#define REG_MATH2_B 0x3A +#define REG_MATH3_B 0x3B +#define REG_KEY 0x40 +#define REG_DECO_DESC 0x40 +#define REG_NFIFO_n_SIZE 0x70 +#define REG_NFIFO_MATH 0x73 +#define REG_SIZE 0x74 +#define REG_SIZE_MATH 0x75 +#define REG_IFIFO_SHIFT 0x76 +#define REG_OFIFO_SHIFT 0x77 +#define REG_AUX_FIFO 0x78 +#define REG_NFIFO 0x7A +#define REG_IFIFO 0x7C +#define REG_OFIFO 0x7E + +/* + * FIFO LOAD Command fields + */ +#define CMD_FIFO_LOAD_TYPE CMD_TYPE(0x04) + +/* Extended Length */ +#define FIFO_LOAD_EXT BIT32(22) + +/* Input data */ +#define FIFO_LOAD_INPUT(reg) SHIFT_U32((FIFO_LOAD_##reg) & 0x3F, 16) +#define FIFO_LOAD_ACTION(act) SHIFT_U32((FIFO_LOAD_##act) & 0x3F, 16) + +/* Length */ +#define FIFO_LOAD_MAX 0xFFFF +#define FIFO_LOAD_LENGTH(len) SHIFT_U32((len) & FIFO_LOAD_MAX, 0) + +/* + * Define the FIFO Load Type Input + */ +#define FIFO_LOAD_PKHA_A0 0x00 +#define FIFO_LOAD_PKHA_A1 0x01 +#define FIFO_LOAD_PKHA_A2 0x02 +#define FIFO_LOAD_PKHA_A3 0x03 +#define FIFO_LOAD_PKHA_B0 0x04 +#define FIFO_LOAD_PKHA_B1 0x05 +#define FIFO_LOAD_PKHA_B2 0x06 +#define FIFO_LOAD_PKHA_B3 0x07 +#define FIFO_LOAD_PKHA_N 0x08 +#define FIFO_LOAD_PKHA_A 0x0C +#define FIFO_LOAD_PKHA_B 0x0D +#define FIFO_LOAD_NO_INFO_NFIFO 0x0F +#define FIFO_LOAD_MSG 0x10 +#define FIFO_LOAD_MSG_C1_OUT_C2 0x18 +#define FIFO_LOAD_IV 0x20 +#define FIFO_LOAD_BITDATA 0x2C +#define FIFO_LOAD_AAD 0x30 +#define FIFO_LOAD_ICV 0x38 + +/* Define Action of some FIFO Data */ +#define FIFO_LOAD_NOACTION 0x0 +#define FIFO_LOAD_FLUSH 0x1 +#define FIFO_LOAD_LAST_C1 0x2 +#define FIFO_LOAD_LAST_C2 0x4 + +/* + * FIFO STORE Command fields + */ +#define CMD_FIFO_STORE_TYPE CMD_TYPE(0x0C) +#define CMD_SEQ_FIFO_STORE_TYPE CMD_TYPE(0x0D) + +/* Extended Length */ +#define FIFO_STORE_EXT BIT32(22) + +/* Output data */ +#define FIFO_STORE_OUTPUT(reg) SHIFT_U32((FIFO_STORE_##reg) & 0x3F, 16) + +/* Length */ +#define FIFO_STORE_MAX 0xFFFF +#define FIFO_STORE_LENGTH(len) SHIFT_U32((len) & FIFO_STORE_MAX, 0) + +/* + * Define the FIFO Store Type Output + */ +#define FIFO_STORE_PKHA_A0 0x00 +#define FIFO_STORE_PKHA_A1 0x01 +#define FIFO_STORE_PKHA_A2 0x02 +#define FIFO_STORE_PKHA_A3 0x03 +#define FIFO_STORE_PKHA_B0 0x04 +#define FIFO_STORE_PKHA_B1 0x05 +#define FIFO_STORE_PKHA_B2 0x06 +#define FIFO_STORE_PKHA_B3 0x07 +#define FIFO_STORE_PKHA_N 0x08 +#define FIFO_STORE_PKHA_A 0x0C +#define FIFO_STORE_PKHA_B 0x0D +#define FIFO_STORE_AFHA_SBOX_AES_CCM_JKEK 0x10 +#define FIFO_STORE_AFHA_SBOX_AES_CCM_TKEK 0x11 +#define FIFO_STORE_PKHA_E_AES_CCM_JKEK 0x12 +#define FIFO_STORE_PKHA_E_AES_CCM_TKEK 0x13 +#define FIFO_STORE_KEY_AES_CCM_JKEK 0x14 +#define FIFO_STORE_KEY_AES_CCM_TKEK 0x15 +#define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_CCM_JKEK 0x16 +#define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_CCM_TKEK 0x17 +#define FIFO_STORE_AFHA_SBOX_AES_ECB_JKEK 0x20 +#define FIFO_STORE_AFHA_SBOX_AES_ECB_TKEK 0x21 +#define FIFO_STORE_PKHA_E_AES_ECB_JKEK 0x22 +#define FIFO_STORE_PKHA_E_AES_ECB_TKEK 0x23 +#define FIFO_STORE_KEY_AES_ECB_JKEK 0x24 +#define FIFO_STORE_KEY_AES_ECB_TKEK 0x25 +#define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_ECB_JKEK 0x26 +#define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_ECB_TKEK 0x27 +#define FIFO_STORE_MSG_DATA 0x30 +#define FIFO_STORE_RNG_TO_MEM 0x34 +#define FIFO_STORE_RNG_STAY_FIFO 0x35 +#define FIFO_STORE_SKIP 0x3F + +/* + * MOVE Command fields + */ +#define CMD_MOVE_TYPE CMD_TYPE(0x0F) + +/* Auxiliary */ +#define MOVE_AUX(val) SHIFT_U32((val) & 0x3, 25) + +/* Wait for completion */ +#define MOVE_WC BIT32(24) + +/* Source */ +#define MOVE_SRC(src) MOVE_SRC_##src +#define MOVE_REG_SRC(reg) SHIFT_U32((reg) & 0xF, 20) +#define MOVE_SRC_C1_CTX_REG MOVE_REG_SRC(0x0) +#define MOVE_SRC_C2_CTX_REG MOVE_REG_SRC(0x1) +#define MOVE_SRC_OFIFO MOVE_REG_SRC(0x2) +#define MOVE_SRC_DESC_BUF MOVE_REG_SRC(0x3) +#define MOVE_SRC_MATH_REG0 MOVE_REG_SRC(0x4) +#define MOVE_SRC_MATH_REG1 MOVE_REG_SRC(0x5) +#define MOVE_SRC_MATH_REG2 MOVE_REG_SRC(0x6) +#define MOVE_SRC_MATH_REG3 MOVE_REG_SRC(0x7) +#define MOVE_SRC_NFIFO_DECO_ALIGN MOVE_REG_SRC(0x8) +#define MOVE_SRC_NFIFO_C1_ALIGN (MOVE_REG_SRC(0x9) | MOVE_AUX(0x1)) +#define MOVE_SRC_NFIFO_C2_ALIGN (MOVE_REG_SRC(0x9) | MOVE_AUX(0x0)) +#define MOVE_SRC_DECO_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x0)) +#define MOVE_SRC_C1_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x1)) +#define MOVE_SRC_C2_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x2)) +#define MOVE_SRC_C1_KEY MOVE_REG_SRC(0xD) +#define MOVE_SRC_C2_KEY MOVE_REG_SRC(0xE) + +/* Destination */ +#define MOVE_DST(dst) SHIFT_U32((MOVE_DST_##dst), 16) +#define MOVE_DST_C1_CTX_REG 0x0 +#define MOVE_DST_C2_CTX_REG 0x1 +#define MOVE_DST_OFIFO 0x2 +#define MOVE_DST_DESC_BUF 0x3 +#define MOVE_DST_MATH_REG0 0x4 +#define MOVE_DST_MATH_REG1 0x5 +#define MOVE_DST_MATH_REG2 0x6 +#define MOVE_DST_MATH_REG3 0x7 +#define MOVE_DST_IFIFO_C1 0x8 +#define MOVE_DST_IFIFO_C2 0x9 +#define MOVE_DST_IFIFO_C2_LC2 ((0x9 << 16 | MOVE_AUX(0x1)) >> 16) +#define MOVE_DST_IFIFO 0xA +#define MOVE_DST_PKHA_A 0xC +#define MOVE_DST_C1_KEY 0xD +#define MOVE_DST_C2_KEY 0xE +#define MOVE_DST_AUX_FIFO 0xF + +/* Offset */ +#define MOVE_OFFSET(off) SHIFT_U32((off) & 0xFF, 8) + +/* Length */ +#define MOVE_LENGTH(len) SHIFT_U32((len) & 0xFF, 0) + +/* + * Operation Command fields + * Algorithm/Protocol/PKHA + */ +#define CMD_OP_TYPE CMD_TYPE(0x10) + +/* Operation Type */ +#define OP_TYPE(type) SHIFT_U32((OP_TYPE_##type) & 0x7, 24) +#define OP_TYPE_UNI 0x0 +#define OP_TYPE_PKHA 0x1 +#define OP_TYPE_CLASS1 0x2 +#define OP_TYPE_CLASS2 0x4 +#define OP_TYPE_DECAPS 0x6 +#define OP_TYPE_ENCAPS 0x7 + +/* Protocol Identifier */ +#define PROTID(id) SHIFT_U32((PROTID_##id) & 0xFF, 16) +#define PROTID_BLOB 0x0D +#define PROTID_MPKEY 0x14 +#define PROTID_PKKEY 0x14 +#define PROTID_MPSIGN 0x15 +#define PROTID_DSASIGN 0x15 +#define PROTID_DSAVERIFY 0x16 +#define PROTID_SHARED_SECRET 0x17 +#define PROTID_RSA_ENC 0x18 +#define PROTID_RSA_DEC 0x19 +#define PROTID_RSA_FINISH_KEY 0x1A + +/* + * RSA Protocol Information + */ +#define PROT_RSA_FMT(format) SHIFT_U32((PROT_RSA_FMT_##format) & 0x1, 12) +#define PROT_RSA_FMT_NO 0 +#define PROT_RSA_FMT_PKCS_V1_5 1 + +#define PROT_RSA_DEC_KEYFORM(format) SHIFT_U32(((format) - 1) & 0x3, 0) + +/* RSA Key Protocol Information */ +#define PROT_RSA_KEY(format) SHIFT_U32((PROT_RSA_KEY_##format) & 0x3, 0) +#define PROT_RSA_KEY_ALL 0 +#define PROT_RSA_KEY_N_D 2 + +/* + * ECC Protocol Information + */ +#define PROT_PK_MSG(type) SHIFT_U32(PROT_PK_MSG_##type, 10) +#define PROT_PK_MSG_HASHED 2 +#define PROT_PK_TYPE(type) SHIFT_U32(PROT_PK_##type, 1) +#define PROT_PK_DL 0 +#define PROT_PK_ECC 1 + +/* + * BLOB Protocol Information + */ +#define PROT_BLOB_FMT_MSTR BIT32(1) +#define PROT_BLOB_TYPE(type) SHIFT_U32(1, PROT_BLOB_TYPE_##type) +#define PROT_BLOB_TYPE_BLACK_KEY 2 +#define PROT_BLOB_EKT 8 +#define PROT_BLOB_INFO(aes) SHIFT_U32(PROT_BLOB_AES_##aes, \ + PROT_BLOB_EKT) +#define PROT_BLOB_AES_CCM 1 +#define PROT_BLOB_AES_ECB 0 +#define PROT_BLOB_FORMAT(format) SHIFT_U32(0, PROT_BLOB_FORMAT_##format) +#define PROT_BLOB_FORMAT_NORMAL 0 + +/* + * MP Protocol Information + */ +#define PROT_MP_PUBK_SGT BIT32(31) +#define PROT_MP_CURVE(curve) SHIFT_U32((curve) & 0xF, 17) + +/* + * Algorithm Identifier + */ +#define OP_ALGO(algo) SHIFT_U32((ALGO_##algo) & 0xFF, 16) +#define ALGO_AES 0x10 +#define ALGO_DES 0x20 +#define ALGO_3DES 0x21 +#define ALGO_ARC4 0x30 +#define ALGO_RNG 0x50 +#define ALGO_MD5 0x40 +#define ALGO_SHA1 0x41 +#define ALGO_SHA224 0x42 +#define ALGO_SHA256 0x43 +#define ALGO_SHA384 0x44 +#define ALGO_SHA512 0x45 +#define ALGO_SHA512_224 0x46 +#define ALGO_SHA512_256 0x47 + +/* Algorithm Additional Information */ +#define ALGO_AAI(info) SHIFT_U32((AAI_##info) & 0x1FF, 4) + +/* AES AAI */ +#define AAI_AES_CTR_MOD128 0x00 +#define AAI_AES_CBC 0x10 +#define AAI_AES_ECB 0x20 +#define AAI_AES_CFB 0x30 +#define AAI_AES_OFB 0x40 +#define AAI_AES_CMAC 0x60 +#define AAI_AES_XCBC_MAC 0x70 +#define AAI_AES_CCM 0x80 +#define AAI_AES_GCM 0x90 + +/* DES AAI */ +#define AAI_DES_CBC 0x10 +#define AAI_DES_ECB 0x20 +#define AAI_DES_CFB 0x30 +#define AAI_DES_OFB 0x40 + +/* Digest MD5/SHA AAI */ +#define AAI_DIGEST_HASH 0x00 +#define AAI_DIGEST_HMAC 0x01 +#define AAI_DIGEST_SMAC 0x02 +#define AAI_DIGEST_HMAC_PRECOMP 0x04 + +/* Algorithm State */ +#define ALGO_AS(state) SHIFT_U32((AS_##state) & 0x3, 2) +#define AS_UPDATE 0x0 +#define AS_INIT 0x1 +#define AS_FINAL 0x2 +#define AS_INIT_FINAL 0x3 + +/* Algorithm Encrypt/Decrypt */ +#define ALGO_DECRYPT SHIFT_U32(0x0, 0) +#define ALGO_ENCRYPT SHIFT_U32(0x1, 0) + +/* + * Specific RNG Algorithm bits 12-0 + */ +/* Secure Key */ +#define ALGO_RNG_SK BIT32(12) + +/* State Handle */ +#define ALGO_RNG_SH(sh) SHIFT_U32((sh) & 0x3, 4) + +/* Prediction Resistance */ +#define ALGO_RNG_PR BIT32(1) + +/* State */ +#define AS_RNG_GENERATE 0x0 +#define AS_RNG_INSTANTIATE 0x1 +#define AS_RNG_RESEED 0x2 +#define AS_RNG_UNINSTANTIATE 0x3 + +/* + * JUMP Command fields + */ +#define CMD_JUMP_TYPE CMD_TYPE(0x14) + +/* Jump Select Type */ +#define JMP_JSL BIT32(24) + +/* Jump Type */ +#define JUMP_TYPE(type) SHIFT_U32((JMP_##type) & 0xF, 20) +#define JMP_LOCAL 0x0 +#define JMP_LOCAL_INC 0x1 +#define JMP_SUBROUTINE_CALL 0x2 +#define JMP_LOCAL_DEC 0x3 +#define JMP_NON_LOCAL 0x4 +#define JMP_SUBROUTINE_RET 0x6 +#define JMP_HALT 0x8 +#define JMP_HALT_USER_STATUS 0xC + +/* Test Type */ +#define JUMP_TST_TYPE(type) SHIFT_U32((JMP_TST_##type) & 0x3, 16) +#define JMP_TST_ALL_COND_TRUE 0x0 +#define JMP_TST_ALL_COND_FALSE 0x1 +#define JMP_TST_ANY_COND_TRUE 0x2 +#define JMP_TST_ANY_COND_FALSE 0x3 + +/* Jump Source to increment/decrement */ +#define JMP_SRC(src) SHIFT_U32((JMP_SRC_##src) & 0xF, 12) +#define JMP_SRC_MATH_0 0x0 + +/* Test Condition */ +#define JMP_COND(cond) SHIFT_U32((JMP_COND_##cond) & 0xFF, 8) +#define JMP_COND_MATH(cond) SHIFT_U32((JMP_COND_MATH_##cond) & 0xF, 8) +#define JMP_COND_NONE 0x00 +#define JMP_COND_PKHA_IS_ZERO 0x80 +#define JMP_COND_PKHA_GCD_1 0x40 +#define JMP_COND_PKHA_IS_PRIME 0x20 +#define JMP_COND_MATH_N 0x08 +#define JMP_COND_MATH_Z 0x04 +#define JMP_COND_NIFP 0x04 +#define JMP_COND_MATH_C 0x02 +#define JMP_COND_MATH_NV 0x01 + +/* Local Offset */ +#define JMP_LOCAL_OFFSET(off) SHIFT_U32((off) & 0xFF, 0) + +/* + * MATH Command fields + */ +#define CMD_MATH_TYPE CMD_TYPE(0x15) +#define CMD_MATHI_TYPE CMD_TYPE(0x1D) + +/* Immediate Four Bytes */ +#define MATH_IFB BIT32(26) + +/* Function Mathematical */ +#define MATH_FUNC(func) SHIFT_U32((MATH_FUNC_##func) & 0xF, 20) +#define MATH_FUNC_ADD 0x0 +#define MATH_FUNC_ADD_W_CARRY 0x1 +#define MATH_FUNC_SUB 0x2 +#define MATH_FUNC_SUB_W_BORROW 0x3 +#define MATH_FUNC_OR 0x4 +#define MATH_FUNC_AND 0x5 +#define MATH_FUNC_XOR 0x6 +#define MATH_FUNC_SHIFT_L 0x7 +#define MATH_FUNC_SHIFT_R 0x8 +#define MATH_FUNC_SHLD 0x9 +#define MATH_FUNC_ZBYTE 0xA +#define MATH_FUNC_SWAP_BYTES 0xB + +/* Source 0 */ +#define MATH_SRC0(reg) SHIFT_U32((MATH_SRC0_##reg) & 0xF, 16) +#define MATH_SRC0_REG0 0x0 +#define MATH_SRC0_REG1 0x1 +#define MATH_SRC0_REG2 0x2 +#define MATH_SRC0_IMM_DATA 0x4 +#define MATH_SRC0_DPOVRD 0x7 +#define MATH_SRC0_SIL 0x8 +#define MATH_SRC0_SOL 0x9 +#define MATH_SRC0_VSIL 0xA +#define MATH_SRC0_VSOL 0xB +#define MATH_SRC0_ZERO 0xC +#define MATH_SRC0_ONE 0xF + +/* Source 1 */ +#define MATH_SRC1(reg) SHIFT_U32((MATH_SRC1_##reg) & 0xF, 12) +#define MATH_SRC1_REG0 0x0 +#define MATH_SRC1_REG1 0x1 +#define MATH_SRC1_REG2 0x2 +#define MATH_SRC1_IMM_DATA 0x4 +#define MATH_SRC1_DPOVRD 0x7 +#define MATH_SRC1_VSIL 0x8 +#define MATH_SRC1_VSOL 0x9 +#define MATH_SRC1_IFIFO 0xA +#define MATH_SRC1_OFIFO 0xB +#define MATH_SRC1_ONE 0xC +#define MATH_SRC1_ZERO 0xF + +/* Destination */ +#define MATH_DST(reg) SHIFT_U32((MATH_DST_##reg) & 0xF, 8) +#define MATH_DST_REG0 0x0 +#define MATH_DST_REG1 0x1 +#define MATH_DST_REG2 0x2 +#define MATH_DST_DPOVRD 0x7 +#define MATH_DST_SIL 0x8 +#define MATH_DST_SOL 0x9 +#define MATH_DST_VSIL 0xA +#define MATH_DST_VSOL 0xB +#define MATH_DST_NODEST 0xF + +/* Length */ +#define MATH_LENGTH(len) SHIFT_U32((len) & 0xF, 0) + +/* Immediate Value - MATHI operation */ +#define MATHI_SRC(reg) SHIFT_U32((MATH_SRC0_##reg) & 0xF, 16) +#define MATHI_DST(reg) SHIFT_U32((MATH_DST_##reg) & 0xF, 12) +#define MATHI_IMM_VALUE(val) SHIFT_U32((val) & 0xFF, 4) + +/* + * Sequence Input/Output + */ +#define CMD_SEQ_IN_TYPE CMD_TYPE(0x1E) +#define CMD_SEQ_OUT_TYPE CMD_TYPE(0x1F) + +/* Extended Length */ +#define SEQ_EXT BIT(22) + +/* Length */ +#define SEQ_LENGTH(len) SHIFT_U32((len) & 0xFFFF, 0) + +/* + * PKHA Operation + */ +#define PKHA_ALG SHIFT_U32(0x8, 20) + +#define PKHA_F2M BIT32(17) + +#define PKHA_OUTSEL(dst) SHIFT_U32((PKHA_OUTSEL_##dst) & 0x3, 8) +#define PKHA_OUTSEL_B 0x0 +#define PKHA_OUTSEL_A 0x1 + +#define PKHA_FUNC(func) SHIFT_U32((PKHA_FUNC_##func) & 0x3F, 0) +#define PKHA_FUNC_CPY_NSIZE 0x10 +#define PKHA_FUNC_CPY_SSIZE 0x11 +#define PKHA_FUNC_MOD_ADD_A_B 0x02 +#define PKHA_FUNC_MOD_SUB_A_B 0x03 +#define PKHA_FUNC_MOD_SUB_B_A 0x04 +#define PKHA_FUNC_MOD_MUL_A_B 0x05 +#define PKHA_FUNC_MOD_EXP_A_E 0x06 +#define PKHA_FUNC_MOD_AMODN 0x07 +#define PKHA_FUNC_MOD_INV_A 0x08 +#define PKHA_FUNC_ECC_POINT_ADD_P1_P2 0x09 +#define PKHA_FUNC_ECC_POINT_DBL_P1 0x0A +#define PKHA_FUNC_ECC_POINT_MUL_E_P1 0x0B +#define PKHA_FUNC_MONT_RADIX_R2_MODE_N 0x0C +#define PKHA_FUNC_GCD_A_N 0x0E +#define PKHA_FUNC_MR_PRIMER_TEST 0x0F +#define PKHA_FUNC_MOD_CHECK_POINT 0x1C + +/* PKHA Copy Memory Source and Destination */ +#define PKHA_REG_SRC(reg) SHIFT_U32((PKHA_REG_##reg) & 0x7, 17) +#define PKHA_REG_DST(reg) SHIFT_U32((PKHA_REG_##reg) & 0x3, 10) +#define PKHA_REG_A 0x0 +#define PKHA_REG_B 0x1 +#define PKHA_REG_E 0x2 +#define PKHA_REG_N 0x3 + +#define PKHA_SEG_SRC(seg) SHIFT_U32((seg) & 0x3, 8) +#define PKHA_SEG_DST(seg) SHIFT_U32((seg) & 0x3, 6) + +#define PKHA_CPY_SRC(src) PKHA_CPY_SRC_##src +#define PKHA_CPY_SRC_A0 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(0)) +#define PKHA_CPY_SRC_A1 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(1)) +#define PKHA_CPY_SRC_A2 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(2)) +#define PKHA_CPY_SRC_A3 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(3)) +#define PKHA_CPY_SRC_B0 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(0)) +#define PKHA_CPY_SRC_B1 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(1)) +#define PKHA_CPY_SRC_B2 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(2)) +#define PKHA_CPY_SRC_B3 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(3)) +#define PKHA_CPY_SRC_N0 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(0)) +#define PKHA_CPY_SRC_N1 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(1)) +#define PKHA_CPY_SRC_N2 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(2)) +#define PKHA_CPY_SRC_N3 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(3)) + +#define PKHA_CPY_DST(dst) PKHA_CPY_DST_##dst +#define PKHA_CPY_DST_A0 (PKHA_REG_DST(A) | PKHA_SEG_DST(0)) +#define PKHA_CPY_DST_A1 (PKHA_REG_DST(A) | PKHA_SEG_DST(1)) +#define PKHA_CPY_DST_A2 (PKHA_REG_DST(A) | PKHA_SEG_DST(2)) +#define PKHA_CPY_DST_A3 (PKHA_REG_DST(A) | PKHA_SEG_DST(3)) +#define PKHA_CPY_DST_B0 (PKHA_REG_DST(B) | PKHA_SEG_DST(0)) +#define PKHA_CPY_DST_B1 (PKHA_REG_DST(B) | PKHA_SEG_DST(1)) +#define PKHA_CPY_DST_B2 (PKHA_REG_DST(B) | PKHA_SEG_DST(2)) +#define PKHA_CPY_DST_B3 (PKHA_REG_DST(B) | PKHA_SEG_DST(3)) +#define PKHA_CPY_DST_N0 (PKHA_REG_DST(N) | PKHA_SEG_DST(0)) +#define PKHA_CPY_DST_N1 (PKHA_REG_DST(N) | PKHA_SEG_DST(1)) +#define PKHA_CPY_DST_N2 (PKHA_REG_DST(N) | PKHA_SEG_DST(2)) +#define PKHA_CPY_DST_N3 (PKHA_REG_DST(N) | PKHA_SEG_DST(3)) +#define PKHA_CPY_DST_E (PKHA_REG_DST(E)) + +/* + * Descriptor Protocol Data Block + */ +/* RSA Encryption */ +#define PDB_RSA_ENC_SGT_F SHIFT_U32(1, 31) +#define PDB_RSA_ENC_SGT_G SHIFT_U32(1, 30) +#define PDB_RSA_ENC_E_SIZE(len) SHIFT_U32((len) & 0xFFF, 12) +#define PDB_RSA_ENC_N_SIZE(len) SHIFT_U32((len) & 0xFFF, 0) +#define PDB_RSA_ENC_F_SIZE(len) SHIFT_U32((len) & 0xFFF, 0) + +/* RSA Decryption */ +#define PDB_RSA_DEC_SGT_G SHIFT_U32(1, 31) +#define PDB_RSA_DEC_SGT_F SHIFT_U32(1, 30) +#define PDB_RSA_DEC_D_SIZE(len) SHIFT_U32((len) & 0xFFF, 12) +#define PDB_RSA_DEC_N_SIZE(len) SHIFT_U32((len) & 0xFFF, 0) +#define PDB_RSA_DEC_Q_SIZE(len) SHIFT_U32((len) & 0xFFF, 12) +#define PDB_RSA_DEC_P_SIZE(len) SHIFT_U32((len) & 0xFFF, 0) + +/* RSA Finalize Key */ +#define PDB_RSA_KEY_P_SIZE(len) SHIFT_U32((len) & 0x1FF, 0) +#define PDB_RSA_KEY_E_SIZE(len) SHIFT_U32((len) & 0x3FF, 0) +#define PDB_RSA_KEY_N_SIZE(len) SHIFT_U32((len) & 0x3FF, 16) + +/* Manufacturing Curve Select */ +#define PDB_SGT_MP_SIGN_MSG SHIFT_U32(1, 31) +#define PDB_SGT_MP_SIGN_C SHIFT_U32(1, 29) +#define PDB_SGT_MP_SIGN_D SHIFT_U32(1, 28) +#define PDB_MP_CSEL_P256 0x03 +#define PDB_MP_CSEL_P384 0x04 +#define PDB_MP_CSEL_P521 0x05 + +/* Public Key Generation */ +#define PDB_PKGEN_PD1 SHIFT_U32(1, 25) +/* Public Key Signature */ +#define PDB_PKSIGN_PD1 SHIFT_U32(1, 22) +/* Public Key Verify */ +#define PDB_PKVERIFY_PD1 SHIFT_U32(1, 22) +/* Shared Secret */ +#define PDB_SHARED_SECRET_PD1 SHIFT_U32(1, 25) + +/* DSA Signatures */ +#define PDB_DSA_SIGN_N(len) SHIFT_U32((len) & (0x7F), 0) +#define PDB_DSA_SIGN_L(len) SHIFT_U32((len) & (0x3FF), 7) + +/* SGT Flags Signature */ +#define PDB_SGT_PKSIGN_MSG SHIFT_U32(1, 27) +#define PDB_SGT_PKSIGN_SIGN_C SHIFT_U32(1, 26) +#define PDB_SGT_PKSIGN_SIGN_D SHIFT_U32(1, 25) + +/* DSA Verify */ +#define PDB_DSA_VERIF_N(len) SHIFT_U32((len) & (0x7F), 0) +#define PDB_DSA_VERIF_L(len) SHIFT_U32((len) & (0x3FF), 7) + +/* SGT Flags Verify */ +#define PDB_SGT_PKVERIF_MSG SHIFT_U32(1, 27) +#define PDB_SGT_PKVERIF_SIGN_C SHIFT_U32(1, 26) +#define PDB_SGT_PKVERIF_SIGN_D SHIFT_U32(1, 25) + +/* SGT Flags Shared Secret */ +#define PDB_SGT_PKDH_SECRET SHIFT_U32(1, 27) + +/* DL Keypair Generation */ +#define PDB_DL_KEY_L_SIZE(len) SHIFT_U32((len) & (0x3FF), 7) +#define PDB_DL_KEY_N_MASK 0x7F +#define PDB_DL_KEY_N_SIZE(len) SHIFT_U32((len) & (PDB_DL_KEY_N_MASK), 0) + +/* ECC Domain Selection */ +#define PDB_ECC_ECDSEL(curve) SHIFT_U32((curve) & 0x3F, 7) + +/* Black key padding */ +#define BLACK_KEY_NONCE_SIZE 6 +#define BLACK_KEY_ICV_SIZE 6 + +/* + * ECC Predefined Domain + */ +enum caam_ecc_curve { + CAAM_ECC_P192 = (0x00), + CAAM_ECC_P224, + CAAM_ECC_P256, + CAAM_ECC_P384, + CAAM_ECC_P521, + CAAM_ECC_MAX, + CAAM_ECC_UNKNOWN = (0xFF), +}; + +#endif /* __CAAM_DESC_DEFINES_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h new file mode 100644 index 0000000..db718be --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_desc_helper.h @@ -0,0 +1,550 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief CAAM Descriptor interface. + */ +#ifndef __CAAM_DESC_HELPER_H__ +#define __CAAM_DESC_HELPER_H__ + +#include +#include +#include +#include + +/* + * Returns the number of entries of the descriptor + */ +uint32_t caam_desc_get_len(uint32_t *desc); + +/* Descriptor Modification function */ +void caam_desc_init(uint32_t *desc); +void caam_desc_update_hdr(uint32_t *desc, uint32_t word); +void caam_desc_add_ptr(uint32_t *desc, paddr_t ptr); +void caam_desc_add_word(uint32_t *desc, uint32_t word); +void caam_desc_add_dmaobj(uint32_t *desc, struct caamdmaobj *data, + uint32_t pre_operation); + +#define caam_desc_fifo_load(desc, data, cla, dst, act) \ + caam_desc_add_dmaobj(desc, data, FIFO_LD(cla, dst, act, 0)) +#define caam_desc_load_key(desc, data, cla, dst) \ + caam_desc_add_dmaobj(desc, data, LD_KEY_PLAIN(cla, dst, 0)) +#define caam_desc_store(desc, data, cla, src) \ + caam_desc_add_dmaobj(desc, data, ST_NOIMM(cla, src, 0)) +#define caam_desc_fifo_store(desc, data, src) \ + caam_desc_add_dmaobj(desc, data, FIFO_ST(src, 0)) +#define caam_desc_seq_out(desc, data) \ + caam_desc_add_dmaobj(desc, data, SEQ_OUT_PTR(0)) + +/* Push/Pop descriptor rings queue */ +void caam_desc_push(struct caam_inring_entry *in_entry, paddr_t paddr); +paddr_t caam_desc_pop(struct caam_outring_entry *out_entry); + +uint32_t caam_read_jobstatus(struct caam_outring_entry *out); + +/* Debug print function to dump a Descriptor in hex */ +static inline void dump_desc(uint32_t *desc) +{ + size_t idx = 0; + size_t len = 0; + + len = caam_desc_get_len(desc); + + for (idx = 0; idx < len; idx++) + trace_printf(NULL, 0, 0, false, "[%02zu] %08" PRIX32, idx, + desc[idx]); +} + +/* + * Returns the descriptor size in bytes of nbEntries + */ +#define DESC_SZBYTES(nbentries) ((nbentries) * sizeof(uint32_t)) + +/* + * Descriptor Header starting at idx w/o descriptor length + */ +#define DESC_HDR(idx) (CMD_HDR_JD_TYPE | HDR_JD_ONE | HDR_JD_START_IDX(idx)) + +/* + * Descriptor Header starting at index 0 with descriptor length len + */ +#define DESC_HEADER(len) (DESC_HDR(0) | HDR_JD_DESCLEN(len)) + +/* + * Descriptor Header starting at idx with descriptor length len + */ +#define DESC_HEADER_IDX(len, idx) (DESC_HDR(idx) | HDR_JD_DESCLEN(len)) + +/* + * Jump Local of class cla to descriptor offset if test meet the + * condition cond + */ +#define JUMP_LOCAL(cla, test, cond, offset) \ + (CMD_JUMP_TYPE | CMD_CLASS(cla) | JUMP_TYPE(LOCAL) | \ + JUMP_TST_TYPE(test) | (cond) | JMP_LOCAL_OFFSET(offset)) + +/* + * Jump Local of no class to descriptor offset if test meet the + * condition cond + */ +#define JUMP_CNO_LOCAL(test, cond, offset) \ + JUMP_LOCAL(CLASS_NO, test, cond, offset) + +/* + * Jump Local of class 1 to descriptor offset if test meet the + * condition cond + */ +#define JUMP_C1_LOCAL(test, cond, offset) \ + JUMP_LOCAL(CLASS_1, test, cond, offset) + +/* + * First decrement specified source then + * Jump Local of no class to descriptor offset if test meet the + * condition cond + */ +#define JUMP_CNO_LOCAL_DEC(test, src, cond, offset) \ + (CMD_JUMP_TYPE | CMD_CLASS(CLASS_NO) | JUMP_TYPE(LOCAL_DEC) | \ + JUMP_TST_TYPE(test) | JMP_SRC(src) | (cond) | \ + JMP_LOCAL_OFFSET(offset)) + +/* + * Wait until test condition meet and jump next + */ +#define WAIT_COND(test, cond) \ + (JUMP_LOCAL(CLASS_NO, test, JMP_COND(cond), 1) | JMP_JSL) + +/* + * Jump No Local of class cla to descriptor offset if test meet the + * condition cond + */ +#define JUMP_NOTLOCAL(cla, test, cond) \ + (CMD_JUMP_TYPE | CMD_CLASS(cla) | JUMP_TYPE(NON_LOCAL) | \ + JUMP_TST_TYPE(test) | (cond)) + +/* + * User Halt with error if test meet the condition cond + */ +#define HALT_USER(test, cond, error) \ + (CMD_JUMP_TYPE | JUMP_TYPE(HALT_USER_STATUS) | JUMP_TST_TYPE(test) | \ + JMP_COND(cond) | JMP_LOCAL_OFFSET(error)) + +/* + * Load Immediate value of length len to register dst of class cla + */ +#define LD_IMM(cla, dst, len) \ + (CMD_LOAD_TYPE | CMD_CLASS(cla) | CMD_IMM | LOAD_DST(dst) | \ + LOAD_LENGTH(len)) + +/* + * Load Immediate value of length len to register dst w/o class + */ +#define LD_NOCLASS_IMM(dst, len) LD_IMM(CLASS_NO, dst, len) + +/* + * Load value of length len to register dst of class cla + */ +#define LD_NOIMM(cla, dst, len) \ + (CMD_LOAD_TYPE | CMD_CLASS(cla) | LOAD_DST(dst) | LOAD_LENGTH(len)) + +/* + * Load value of length len to register dst of class cla starting + * at register offset off + */ +#define LD_NOIMM_OFF(cla, dst, len, off) \ + (CMD_LOAD_TYPE | CMD_CLASS(cla) | LOAD_DST(dst) | LOAD_OFFSET(off) | \ + LOAD_LENGTH(len)) + +/* + * FIFO Load to register dst class cla with action act + */ +#define FIFO_LD(cla, dst, act, len) \ + (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | FIFO_LOAD_INPUT(dst) | \ + FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len)) + +/* + * FIFO Load to register dst class cla with action act. + * Pointer is a Scatter/Gather Table + */ +#define FIFO_LD_SGT(cla, dst, act, len) \ + (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | CMD_SGT | \ + FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len)) + +/* + * FIFO Load to register dst class cla with action act. + * Pointer is a Scatter/Gather Table + * The length is externally defined + */ +#define FIFO_LD_SGT_EXT(cla, dst, act) \ + (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | CMD_SGT | FIFO_LOAD_EXT | \ + FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act)) + +/* + * FIFO Load to register dst class cla with action act. + * The length is externally defined + */ +#define FIFO_LD_EXT(cla, dst, act) \ + (CMD_FIFO_LOAD_TYPE | FIFO_LOAD_EXT | CMD_CLASS(cla) | \ + FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act)) + +/* + * FIFO Load Immediate data length len to register dst class cla + * with action act. + */ +#define FIFO_LD_IMM(cla, dst, act, len) \ + (CMD_FIFO_LOAD_TYPE | CMD_IMM | CMD_CLASS(cla) | \ + FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len)) + +/* + * Store value of length len from register src of class cla + */ +#define ST_NOIMM(cla, src, len) \ + (CMD_STORE_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | STORE_LENGTH(len)) + +/* + * Store value of length len from register src of class cla + * Pointer is a Scatter/Gather Table + */ +#define ST_SGT_NOIMM(cla, src, len) \ + (CMD_STORE_TYPE | CMD_CLASS(cla) | CMD_SGT | STORE_SRC(src) | \ + STORE_LENGTH(len)) + +/* + * Store value of length len from register src of class cla starting + * at register offset off + */ +#define ST_NOIMM_OFF(cla, src, len, off) \ + (CMD_STORE_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | \ + STORE_OFFSET(off) | STORE_LENGTH(len)) + +/* + * Store value of length len from register src of class cla + */ +#define ST_NOIMM_SEQ(cla, src, len) \ + (CMD_STORE_SEQ_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | \ + STORE_LENGTH(len)) + +/* + * FIFO Store from register src of length len + */ +#define FIFO_ST(src, len) \ + (CMD_FIFO_STORE_TYPE | FIFO_STORE_OUTPUT(src) | FIFO_STORE_LENGTH(len)) + +/* + * FIFO Store from register src. + * The length is externally defined + */ +#define FIFO_ST_EXT(src) \ + (CMD_FIFO_STORE_TYPE | FIFO_STORE_EXT | FIFO_STORE_OUTPUT(src)) + +/* + * FIFO Store from register src of length len. + * Pointer is a Scatter/Gather Table + */ +#define FIFO_ST_SGT(src, len) \ + (CMD_FIFO_STORE_TYPE | CMD_SGT | FIFO_STORE_OUTPUT(src) | \ + FIFO_STORE_LENGTH(len)) + +/* + * FIFO Store from register src. + * Pointer is a Scatter/Gather Table + * The length is externally defined + */ +#define FIFO_ST_SGT_EXT(src) \ + (CMD_FIFO_STORE_TYPE | CMD_SGT | FIFO_STORE_EXT | \ + FIFO_STORE_OUTPUT(src)) + +/* + * SEQ FIFO Store from register src of length len + */ +#define FIFO_ST_SEQ(src, len) \ + (CMD_SEQ_FIFO_STORE_TYPE | FIFO_STORE_OUTPUT(src) | \ + FIFO_STORE_LENGTH(len)) + +/* + * RNG State Handle instantation operation for sh ID + */ +#define RNG_SH_INST(sh) \ + (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_RNG_SH(sh) | \ + ALGO_AS(RNG_INSTANTIATE) | ALGO_RNG_PR) + +/* + * RNG Generates Secure Keys + */ +#define RNG_GEN_SECKEYS \ + (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_RNG_SK | \ + ALGO_AS(RNG_GENERATE)) + +/* + * RNG Generates Data + */ +#define RNG_GEN_DATA \ + (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_AS(RNG_GENERATE)) + +/* + * Hash Init Operation of algorithm algo + */ +#define HASH_INIT(algo) \ + (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | ALGO_ENCRYPT) + +/* + * Hash Update Operation of algorithm algo + */ +#define HASH_UPDATE(algo) \ + (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(UPDATE) | \ + ALGO_ENCRYPT) + +/* + * Hash Final Operation of algorithm algo + */ +#define HASH_FINAL(algo) \ + (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(FINAL) | ALGO_ENCRYPT) + +/* + * Hash Init and Final Operation of algorithm algo + */ +#define HASH_INITFINAL(algo) \ + (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT_FINAL) | \ + ALGO_ENCRYPT) + +/* + * HMAC Init Decryption Operation of algorithm algo + */ +#define HMAC_INIT_DECRYPT(algo) \ + (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | \ + ALGO_AAI(DIGEST_HMAC) | ALGO_DECRYPT) + +/* + * HMAC Init and Final Operation of algorithm algo with Precomp key + */ +#define HMAC_INITFINAL_PRECOMP(algo) \ + (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT_FINAL) | \ + ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT) + +/* + * HMAC Init Operation of algorithm algo with Precomp key + */ +#define HMAC_INIT_PRECOMP(algo) \ + (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | \ + ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT) + +/* + * HMAC Final Operation of algorithm algo with Precomp key + */ +#define HMAC_FINAL_PRECOMP(algo) \ + (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(FINAL) | \ + ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT) + +/* + * Cipher Init and Final Operation of algorithm algo + */ +#define CIPHER_INITFINAL(algo, encrypt) \ + (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(INIT_FINAL) | \ + ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT)) + +/* + * Cipher Init Operation of algorithm algo + */ +#define CIPHER_INIT(algo, encrypt) \ + (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(INIT) | \ + ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT)) + +/* + * Cipher Update Operation of algorithm algo + */ +#define CIPHER_UPDATE(algo, encrypt) \ + (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(UPDATE) | \ + ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT)) + +/* + * Cipher Final Operation of algorithm algo + */ +#define CIPHER_FINAL(algo, encrypt) \ + (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(FINAL) | \ + ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT)) + +/* + * Load a class cla key of length len to register dst. + * Key can be stored in plain text. + */ +#define LD_KEY_PLAIN(cla, dst, len) \ + (CMD_KEY_TYPE | CMD_CLASS(cla) | KEY_PTS | KEY_DEST(dst) | \ + KEY_LENGTH(len)) + +/* + * Load a class cla key of length len to register dst. + * Key can be stored in plain text. + * Pointer is a Scatter/Gatter Table + */ +#define LD_KEY_SGT_PLAIN(cla, dst, len) \ + (CMD_KEY_TYPE | CMD_CLASS(cla) | CMD_SGT | KEY_PTS | KEY_DEST(dst) | \ + KEY_LENGTH(len)) + +/* + * Load a split key of length len. + */ +#define LD_KEY_SPLIT(len) \ + (CMD_KEY_TYPE | CMD_CLASS(CLASS_2) | KEY_DEST(MDHA_SPLIT) | \ + KEY_LENGTH(len)) + +/* + * MPPRIVK generation function. + */ +#define MPPRIVK (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(MPKEY)) + +/* + * MPPUBK generation function. + */ +#define MPPUBK (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(MPKEY)) + +/* + * MPSIGN function. + */ +#define MPSIGN_OP (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(MPSIGN)) + +/* + * Operation Mathematical of length len + * dest = src0 (operation func) src1 + */ +#define MATH(func, src0, src1, dst, len) \ + (CMD_MATH_TYPE | MATH_FUNC(func) | MATH_SRC0(src0) | MATH_SRC1(src1) | \ + MATH_DST(dst) | MATH_LENGTH(len)) + +/* + * Operation Mathematical of length len using an immediate value as operand 1 + * dest = src (operation func) val + */ +#define MATHI_OP1(func, src, val, dst, len) \ + (CMD_MATHI_TYPE | MATH_FUNC(func) | MATHI_SRC(src) | \ + MATHI_IMM_VALUE(val) | MATHI_DST(dst) | MATH_LENGTH(len)) + +/* + * PKHA Copy function from src to dst. Copy number of words specified + * in Source size register + */ +#define PKHA_CPY_SSIZE(src, dst) \ + (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(CPY_SSIZE) | \ + PKHA_CPY_SRC(src) | PKHA_CPY_DST(dst)) + +/* + * PKHA Copy N-Size function from src to dst. Copy number of words specified + * in PKHA N size register + */ +#define PKHA_CPY_NSIZE(src, dst) \ + (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(CPY_NSIZE) | \ + PKHA_CPY_SRC(src) | PKHA_CPY_DST(dst)) + +/* + * PKHA Operation op result into dst + */ +#define PKHA_OP(op, dst) \ + (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(op) | \ + PKHA_OUTSEL(dst)) + +/* + * PKHA Binomial operation op result into dst + */ +#define PKHA_F2M_OP(op, dst) \ + (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_F2M | PKHA_FUNC(op) | \ + PKHA_OUTSEL(dst)) + +/* + * Move src to dst + */ +#define MOVE(src, dst, off, len) \ + (CMD_MOVE_TYPE | MOVE_SRC(src) | MOVE_DST(dst) | MOVE_OFFSET(off) | \ + MOVE_LENGTH(len)) + +/* + * Move src to dst and wait until completion + */ +#define MOVE_WAIT(src, dst, off, len) \ + (CMD_MOVE_TYPE | MOVE_WC | MOVE_SRC(src) | MOVE_DST(dst) | \ + MOVE_OFFSET(off) | MOVE_LENGTH(len)) + +/* + * RSA Encryption using format + */ +#define RSA_ENCRYPT(format) \ + (CMD_OP_TYPE | PROTID(RSA_ENC) | PROT_RSA_FMT(format)) + +/* + * RSA Decryption using format + */ +#define RSA_DECRYPT(format) \ + (CMD_OP_TYPE | PROTID(RSA_DEC) | PROT_RSA_FMT(format)) + +/* + * RSA Finalize Key in format + */ +#define RSA_FINAL_KEY(format) \ + (CMD_OP_TYPE | PROTID(RSA_FINISH_KEY) | PROT_RSA_KEY(format)) + +/* + * Public Keypair generation + */ +#define PK_KEYPAIR_GEN(type) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(PKKEY) | PROT_PK_TYPE(type)) + +/* + * DSA/ECDSA signature of message hashed + */ +#define DSA_SIGN(type) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | PROT_PK_MSG(HASHED) | \ + PROT_PK_TYPE(type)) + +/* + * DSA/ECDSA signature verify message hashed + */ +#define DSA_VERIFY(type) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSAVERIFY) | \ + PROT_PK_MSG(HASHED) | PROT_PK_TYPE(type)) + +/* + * DH/ECC Shared Secret + */ +#define SHARED_SECRET(type) \ + (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(SHARED_SECRET) | \ + PROT_PK_TYPE(type)) + +/* + * Blob Master Key Verification + */ +#define BLOB_MSTR_KEY \ + (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(BLOB) | PROT_BLOB_FMT_MSTR) + +/* + * Blob encapsulation + */ +#define BLOB_ENCAPS \ + (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(BLOB) | \ + PROT_BLOB_FORMAT(NORMAL)) + +/* + * Blob decapsulation + */ +#define BLOB_DECAPS \ + (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(BLOB) | \ + PROT_BLOB_FORMAT(NORMAL)) + +/* + * Black key CCM size + */ +#define BLACK_KEY_CCM_SIZE(size) \ + (ROUNDUP(size, 8) + BLACK_KEY_NONCE_SIZE + BLACK_KEY_ICV_SIZE) + +/* + * Black key ECB size + */ +#define BLACK_KEY_ECB_SIZE(size) ROUNDUP(size, 16) + +/* + * Sequence Inout Pointer of length len + */ +#define SEQ_IN_PTR(len) (CMD_SEQ_IN_TYPE | SEQ_LENGTH(len)) + +/* + * Sequence Output Pointer of length len + */ +#define SEQ_OUT_PTR(len) (CMD_SEQ_OUT_TYPE | SEQ_LENGTH(len)) + +#endif /* __CAAM_DESC_HELPER_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_cfg.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_cfg.h new file mode 100644 index 0000000..2d80562 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_cfg.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Configuration header. + */ +#ifndef __CAAM_HAL_CFG_H__ +#define __CAAM_HAL_CFG_H__ + +#include + +/* + * Returns the Job Ring Configuration to be used by the TEE + * + * @jrcfg [out] Job Ring Configuration + * + * Returns: + * CAAM_NO_ERROR Success + * CAAM_FAILURE An error occurred + */ +enum caam_status caam_hal_cfg_get_conf(struct caam_jrcfg *jrcfg); + +/* + * Setup the Non-Secure Job Ring + * + * @jrcfg Job Ring configuration + */ +void caam_hal_cfg_setup_nsjobring(struct caam_jrcfg *jrcfg); + +#ifdef CFG_DT +/* + * Returns the Job Ring configuration to be used by the TEE + * + * @fdt Device Tree handle + * @ctrl_base [out] CAAM Controller base address + */ +void caam_hal_cfg_get_ctrl_dt(void *fdt, vaddr_t *ctrl_base); + +/* + * Returns the Job Ring configuration to be used by the TEE + * + * @fdt Device Tree handle + * @jrcfg [out] Job Ring configuration + */ +void caam_hal_cfg_get_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg); + +/* + * Disable the DT node related to the Job Ring used by secure world + * + * @fdt Device Tree handle + * @jrcfg Job Ring configuration + */ +void caam_hal_cfg_disable_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg); +#else +static inline void caam_hal_cfg_get_ctrl_dt(void *fdt __unused, + vaddr_t *ctrl_base) +{ + *ctrl_base = 0; +} + +static inline void +caam_hal_cfg_get_jobring_dt(void *fdt __unused, + struct caam_jrcfg *jrcfg) +{ + jrcfg->offset = 0; + jrcfg->it_num = 0; +} + +static inline void +caam_hal_cfg_disable_jobring_dt(void *fdt __unused, + struct caam_jrcfg *jrcfg __unused) +{ +} +#endif /* CFG_DT */ + +#endif /* __CAAM_HAL_CFG_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_clk.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_clk.h new file mode 100644 index 0000000..b9f296e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_clk.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Clock functions header. + */ +#ifndef __CAAM_HAL_CLK_H__ +#define __CAAM_HAL_CLK_H__ + +#include + +/* + * Enable/disable the CAAM clocks + * + * @enable Enable the clock if true + */ +void caam_hal_clk_enable(bool enable); + +#endif /* __CAAM_HAL_CLK_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h new file mode 100644 index 0000000..9668cc3 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_ctrl.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2020 NXP + * + * Brief CAAM Controller Hardware Abstration Layer header. + */ +#ifndef __CAAM_HAL_CTRL_H__ +#define __CAAM_HAL_CTRL_H__ + +#include +#include + +/* + * Initializes the CAAM HW Controller + * + * @baseaddr Controller base address + */ +void caam_hal_ctrl_init(vaddr_t baseaddr); + +/* + * Returns the number of Job Ring supported + * + * @baseaddr Controller base address + */ +uint8_t caam_hal_ctrl_jrnum(vaddr_t baseaddr); + +/* + * If Hash operation is supported, returns the Maximum Hash Algorithm + * supported by the HW else UINT8_MAX + * + * @baseaddr Controller base address + */ +uint8_t caam_hal_ctrl_hash_limit(vaddr_t baseaddr); + +/* + * Returns the number of Public Key module supported + * + * @baseaddr Controller base address + */ +uint8_t caam_hal_ctrl_pknum(vaddr_t baseaddr); + +/* + * Returns if the HW support the split key operation. + * + * @baseaddr Controller base address + */ +bool caam_hal_ctrl_splitkey_support(vaddr_t baseaddr); + +/* + * Returns the CAAM Era + * + * @baseaddr Controller base address + */ +uint8_t caam_hal_ctrl_era(vaddr_t baseaddr); + +/* + * Increment the CAAM PRIBLOB field + * + * @baseaddr Controller base address + */ +void caam_hal_ctrl_inc_priblob(vaddr_t baseaddr); + +#ifdef CFG_NXP_CAAM_MP_DRV +/* + * Get the SCFGR content and check the MPCURVE fields. + * The function returns either: + * - UINT8_MAX if the Manafacturing Protection is not supported + * - The MP Curve Value if programmed (4 bits value) + * - 0 if the MP Curve is not programmed + * + * @ctrl_addr Controller base address + */ +uint8_t caam_hal_ctrl_get_mpcurve(vaddr_t ctrl_addr); + +/* + * Read the MPMR content + * + * @ctrl_addr Controller base address + * @mpmr [out] MPMR buffer read + */ +TEE_Result caam_hal_ctrl_read_mpmr(vaddr_t ctrl_addr, struct caambuf *mpmr); + +/* + * Fill the MPMR content then lock the register + * + * @ctrl_addr Controller base address + * @msg_mpmr Buffer with the message and length to fill the MPMR content + */ +void caam_hal_ctrl_fill_mpmr(vaddr_t ctrl_addr, struct caambuf *msg_mpmr); + +/* + * Indicate if the MP is set + * + * @ctrl_addr Controller base address + */ +bool caam_hal_ctrl_is_mp_set(vaddr_t ctrl_addr); +#endif /* CFG_NXP_CAAM_MP_DRV */ +#endif /* __CAAM_HAL_CTRL_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_jr.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_jr.h new file mode 100644 index 0000000..19cc68b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_jr.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Job Rings Hardware Abstration Layer header. + */ +#ifndef __CAAM_HAL_JR_H__ +#define __CAAM_HAL_JR_H__ + +#include + +/* + * Configures the Job Ring Owner and lock it. + * If the configuration is already locked, checks the configuration + * set and returns an error if value is not corresponding to the + * expected value. + * + * @ctrl_base Base address of the controller + * @jr_offset Job Ring offset to configure + * @owner Onwer ID to configure + */ +enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, + enum caam_jr_owner owner); + +/* + * Resets the Job Ring to ensure that all pending jobs are completed + * and no other will be executed + * + * @baseaddr Job Ring Base address + */ +enum caam_status caam_hal_jr_reset(vaddr_t baseaddr); + +/* + * Configures the Job Ring HW queues. + * + * @baseaddr Job Ring Base Address + * @nbjobs Number of job rings supported + * @inrings physical address of the JR input queue + * @outrings physical address of the JR output queue + */ +void caam_hal_jr_config(vaddr_t baseaddr, uint8_t nbjobs, uint64_t inrings, + uint64_t outrings); + +/* + * Returns the number of slots available in the input job ring + * + * @baseaddr Job Ring Base address + */ +uint32_t caam_hal_jr_read_nbslot_available(vaddr_t baseaddr); + +/* + * Indicates to HW that a new job is available + * + * @baseaddr Job Ring Base Address + */ +void caam_hal_jr_add_newjob(vaddr_t baseaddr); + +/* + * Returns the number of job completed and present in the output ring slots + * + * @baseaddr Job Ring Base Address + */ +uint32_t caam_hal_jr_get_nbjob_done(vaddr_t baseaddr); + +/* + * Removes a job from the job ring output queue + * + * @baseaddr Job Ring Base Address + */ +void caam_hal_jr_del_job(vaddr_t baseaddr); + +/* + * Disable and acknwoledge the Job Ring interrupt + * + * @baseaddr Job Ring Base Address + */ +void caam_hal_jr_disable_itr(vaddr_t baseaddr); + +/* + * Enable the Job Ring interrupt + * + * @baseaddr Job Ring Base Address + */ +void caam_hal_jr_enable_itr(vaddr_t baseaddr); + +/* + * If an interrupt is pending, acknowledges it and returns true. + * + * @baseaddr Job Ring Base Address + */ +bool caam_hal_jr_check_ack_itr(vaddr_t baseaddr); + +/* + * Halt the Job Ring processing. Stop fetching input queue and wait + * all running jobs normal completion. + * + * @baseaddr Job Ring Base Address + */ +enum caam_status caam_hal_jr_halt(vaddr_t baseaddr); + +/* + * Wait all Input queue Job Ring processing. + * + * @baseaddr Job Ring Base Address + */ +enum caam_status caam_hal_jr_flush(vaddr_t baseaddr); + +/* + * Resume the Job Ring processing. + * + * @baseaddr Job Ring Base Address + */ +void caam_hal_jr_resume(vaddr_t baseaddr); + +/* + * Returns the next entry free in the JR input queue. + * The HW increments register by 4. Convert it to a software index number + * + * @baseaddr CAAM JR Base Address + */ +uint8_t caam_hal_jr_input_index(vaddr_t baseaddr); + +/* + * Returns the next entry to read from the JR output queue. + * The HW increments register by 8. Convert it to a software index number + * + * @baseaddr CAAM JR Base Address + */ +uint8_t caam_hal_jr_output_index(vaddr_t baseaddr); + +/* + * Let the JR prepare data that need backup + * + * @ctrl_base CAAM JR Base Address + * @jr_offset Job Ring offset to prepare backup for + */ +void caam_hal_jr_prepare_backup(vaddr_t ctrl_base, paddr_t jr_offset); + +#endif /* __CAAM_HAL_JR_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h new file mode 100644 index 0000000..9b87215 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hal_rng.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019-2021 NXP + * + * Brief CAAM Random Number Generator Hardware Abstration Layer. + * Implementation of primitives to access HW + */ +#ifndef __CAAM_HAL_RNG_H__ +#define __CAAM_HAL_RNG_H__ + +#include +#include + +/* + * Returns if all RNG State Handler already instantiated or not + * + * @baseaddr RNG Base Address + */ +enum caam_status caam_hal_rng_instantiated(vaddr_t baseaddr); + +/* + * Returns the number of RNG State Handle + * + * @baseaddr RNG Base Address + */ +uint32_t caam_hal_rng_get_nb_sh(vaddr_t baseaddr); + +/* + * Returns the RNG Status State Handle + * + * @baseaddr RNG Base Address + */ +uint32_t caam_hal_rng_get_sh_status(vaddr_t baseaddr); + +/* + * Returns true if the RNG Key is loaded, false otherwise + * + * @baseaddr RNG Base Address + */ +bool caam_hal_rng_key_loaded(vaddr_t baseaddr); + +/* + * Configures the RNG entropy delay + * + * @baseaddr RNG Base Address + * @inc_delay Entropy Delay incrementation + */ +enum caam_status caam_hal_rng_kick(vaddr_t baseaddr, uint32_t inc_delay); + +#endif /* __CAAM_HAL_RNG_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_hash.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_hash.h new file mode 100644 index 0000000..62ef758 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_hash.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief CAAM Hash manager header. + */ +#ifndef __CAAM_HASH_H__ +#define __CAAM_HASH_H__ + +#include + +#ifdef CFG_NXP_CAAM_HASH_DRV +/* + * Initialize the Hash module + * + * @caam_jrcfg JR configuration structure + */ +enum caam_status caam_hash_init(struct caam_jrcfg *caam_jrcfg); +#else +static inline enum caam_status +caam_hash_init(struct caam_jrcfg *caam_jrcfg __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_HASH_DRV */ + +#ifdef CFG_NXP_CAAM_HMAC_DRV +/* + * Initialize the HMAC module + * + * @caam_jrcfg JR configuration structure + */ +enum caam_status caam_hmac_init(struct caam_jrcfg *caam_jrcfg); +#else +static inline enum caam_status +caam_hmac_init(struct caam_jrcfg *caam_jrcfg __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_HMAC_DRV */ +#endif /* __CAAM_HASH_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_io.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_io.h new file mode 100644 index 0000000..166875a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_io.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019, 2021 NXP + * + * Brief Specific Macro used to read/write value with a specific + * format (BE/LE, 32/64 bits) to be updated for future platform + * support. + */ + +#ifndef __CAAM_IO_H__ +#define __CAAM_IO_H__ + +#include + +#ifdef CFG_CAAM_BIG_ENDIAN +/* Big Endian 32 bits Registers access */ +#define io_caam_read32(a) TEE_U32_FROM_BIG_ENDIAN(io_read32(a)) +#define io_caam_write32(a, val) io_write32(a, TEE_U32_TO_BIG_ENDIAN(val)) + +/* Big Endian 32 bits Value access */ +#define caam_read_val32(a) get_be32(a) +#define caam_write_val32(a, v) put_be32(a, v) +#else +/* Little Endian 32 bits Registers access */ +#define io_caam_read32(a) io_read32(a) +#define io_caam_write32(a, val) io_write32(a, val) + +/* Little Endian 32 bits Value access */ +#define caam_read_val32(a) get_le32(a) +#define caam_write_val32(a, v) put_le32(a, v) + +#define caam_read_val64(a) get_le64(a) +#define caam_write_val64(a, v) put_le64(a, v) +#endif + +#endif /* __CAAM_IO_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_jr.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_jr.h new file mode 100644 index 0000000..4456457 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_jr.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM Job Rings module header. + */ +#ifndef __CAAM_JR_H__ +#define __CAAM_JR_H__ + +#include +#include + +/* + * Job context to enqueue/dequeue + */ +struct caam_jobctx { + uint32_t *desc; /* reference to the descriptor */ + uint32_t status; /* executed job status */ + uint32_t id; /* Job identifier */ + bool completion; /* job completion flag */ + void *context; /* caller job context */ + void (*callback)(struct caam_jobctx *ctx); /* job completion callback */ +}; + +/* + * Job Ring module configuration + */ +struct caam_jrcfg { + vaddr_t base; /* CAAM virtual base address */ + paddr_t offset; /* Job Ring address offset */ + int it_num; /* Job Ring interrupt number */ + uint8_t nb_jobs; /* Number of Jobs to managed */ +}; + +/* + * The CAAM physical address is decorrelated from the CPU addressing mode. + * CAAM can manage 32 or 64 bits address depending on its version and the + * device. + */ +/* + * Definition of input and output ring object + */ +#ifdef CFG_CAAM_64BIT +struct caam_inring_entry { + uint64_t desc; /* Physical address of the descriptor */ +}; + +struct caam_outring_entry { + uint64_t desc; /* Physical address of the descriptor */ + uint32_t status; /* Status of the executed job */ +} __packed; +#else +struct caam_inring_entry { + uint32_t desc; /* Physical address of the descriptor */ +}; + +struct caam_outring_entry { + uint32_t desc; /* Physical address of the descriptor */ + uint32_t status; /* Status of the executed job */ +} __packed; +#endif /* CFG_CAAM_64BIT */ + +/* + * Initialization of the CAAM Job Ring module + * + * @jrcfg Job Ring Configuration + */ +enum caam_status caam_jr_init(struct caam_jrcfg *jrcfg); + +/* + * Cancels a job ID. Remove the job from SW Job array + * + * @job_id Job ID + */ +void caam_jr_cancel(uint32_t job_id); + +/* + * Checks if one of the given job IDs in bit mask format + * is completed. If none is completed, wait until timeout expires. + * Endlessly wait if @timeout_ms = UINT_MAX + * + * @job_ids Job IDs Mask + * @timeout_ms Timeout in millisecond + */ +enum caam_status caam_jr_dequeue(uint32_t job_ids, unsigned int timeout_ms); + +/* + * Enqueues a job in the Job Ring input queue and either wait until job + * completion or if job is asynchrnous, returns immediately (if status + * success, the output parameter job_id is filled with the Job Id pushed) + * + * @jobctx Reference to the job context + * @job_id [out] If pointer not NULL, job is asynchronous and parameter is + * the Job Id enqueued + */ +enum caam_status caam_jr_enqueue(struct caam_jobctx *jobctx, uint32_t *job_id); + +/* + * Request the CAAM JR to halt. + * Stop fetching input queue and wait running job completion. + */ +enum caam_status caam_jr_halt(void); + +/* Request the CAAM JR to flush all job running. */ +enum caam_status caam_jr_flush(void); + +/* + * Resume the CAAM JR processing. + * + * @pm_hints Hint on current power transition + */ +void caam_jr_resume(uint32_t pm_hints); + +/* Forces the completion of all CAAM Job to ensure CAAM is not BUSY. */ +enum caam_status caam_jr_complete(void); +#endif /* __CAAM_JR_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_jr_status.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_jr_status.h new file mode 100644 index 0000000..f978622 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_jr_status.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief CAAM Job Ring Status definition header. + */ +#ifndef __JR_STATUS_H__ +#define __JR_STATUS_H__ + +#include + +/* Source */ +#define BM_JRSTA_SRC SHIFT_U32(0xF, 28) + +#define JRSTA_SRC_GET(status) ((status) & BM_JRSTA_SRC) +#define JRSTA_SRC(src) SHIFT_U32(JRSTA_SRC_##src, 28) + +#define JRSTA_SRC_NONE 0x0 +#define JRSTA_SRC_CCB 0x2 +#define JRSTA_SRC_JMP_HALT_USER 0x3 +#define JRSTA_SRC_DECO 0x4 +#define JRSTA_SRC_JR 0x6 +#define JRSTA_SRC_JMP_HALT_COND 0x7 + +#define JRSTA_CCB_GET_ERR(status) ((status) & SHIFT_U32(0xFF, 0)) +#define JRSTA_CCB_CHAID_RNG SHIFT_U32(0x5, 4) +#define JRSTA_CCB_ERRID_HW SHIFT_U32(0xB, 0) +#define JRSTA_DECO_ERRID_FORMAT SHIFT_U32(0x88, 0) +#define JRSTA_DECO_INV_SIGNATURE SHIFT_U32(0x86, 0) + +/* Return the Halt User status else 0 if not a Jump Halt User */ +#define JRSTA_GET_HALT_USER(status) \ + (__extension__({ \ + __typeof__(status) _status = (status); \ + JRSTA_SRC_GET(_status) == JRSTA_SRC(JMP_HALT_USER) ? \ + _status & UINT8_MAX : \ + 0; })) +#endif /* __CAAM_JR_STATUS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_mp.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_mp.h new file mode 100644 index 0000000..ba37a1b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_mp.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019, 2021, 2023 NXP + */ +#ifndef __CAAM_MP_H__ +#define __CAAM_MP_H__ + +#include "tee_api_types.h" +#include "types_ext.h" + +#ifdef CFG_NXP_CAAM_MP_DRV +/* + * Initialize the MP module and generate the private key + * + * @ctrl_addr Controller base address + */ +enum caam_status caam_mp_init(vaddr_t ctrl_addr); + +/* + * Power Management for MP + * + * @pm_hint Power mode type + */ +enum caam_status caam_mp_resume(uint32_t pm_hint); +#else +static inline enum caam_status caam_mp_init(vaddr_t ctrl_addr __unused) +{ + return CAAM_NO_ERROR; +} + +static inline enum caam_status caam_mp_resume(uint32_t pm_hint __unused) +{ + return CAAM_NO_ERROR; +} +#endif /* CFG_NXP_CAAM_MP_DRV */ + +#endif /* __CAAM_MP_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_pwr.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_pwr.h new file mode 100644 index 0000000..b8a365a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_pwr.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019 NXP + * + * Brief CAAM driver common include file. + * Definition of the structure type to save and restore + * HW registers configuration + */ +#ifndef __CAAM_PWR_H__ +#define __CAAM_PWR_H__ + +#include + +/* + * Definition of the structure type used to list HW registers + * to be saved and restored. + */ +struct reglist { + uint32_t offset; /* Register offset */ + uint32_t nbregs; /* Number of consecutive registers */ + uint32_t mask_clr; /* Clear mask of bit to exclude in restore value */ + uint32_t mask_set; /* Set mask of bit to force in restore value */ +}; + +#define BACKUP_REG(_offset, _nbregs, _mask_clr, _mask_set) \ + { \ + .offset = _offset, .nbregs = _nbregs, .mask_clr = _mask_clr, \ + .mask_set = _mask_set, \ + } +/* + * Definition of the structure type used to store registers to backup + */ +struct backup_data { + vaddr_t baseaddr; /* Register virtual base address */ + size_t nbentries; /* Number of entries in the list */ + const struct reglist *regs; /* Register list */ + uint32_t *val; /* Register value */ + + SLIST_ENTRY(backup_data) next; /* Link to next data */ +}; + +/* + * Add definition of the backup data in the list + * + * @baseaddr Register base address + * @regs Register list + * @nbentries Number of entries in the list + */ +void caam_pwr_add_backup(vaddr_t baseaddr, const struct reglist *regs, + size_t nbentries); + +/* + * Power Initialization function called when all CAAM modules are + * initialized correctly. + * Register the PM callback in the system. + */ +void caam_pwr_init(void); + +#endif /* __CAAM_PWR_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_rng.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_rng.h new file mode 100644 index 0000000..3c5d100 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_rng.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + * + * Brief CAAM Random Number Generator manager header. + */ +#ifndef __CAAM_RNG_H__ +#define __CAAM_RNG_H__ + +/* + * Initialize the RNG module to generate data + * + * @ctrl_addr Controller base address + */ +enum caam_status caam_rng_init(vaddr_t ctrl_addr); + +/* Instantiates the RNG State Handles if not already done */ +enum caam_status caam_rng_instantiation(void); + +#endif /* __CAAM_RNG_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_status.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_status.h new file mode 100644 index 0000000..9048578 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_status.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019, 2021 NXP + * + * Brief CAAM driver internal status definition + */ + +#ifndef __CAAM_STATUS_H__ +#define __CAAM_STATUS_H__ + +/* + * Internal CAAM Driver status codes + */ +enum caam_status { + CAAM_NO_ERROR = 0, /* No Error */ + CAAM_FAILURE, /* General failure */ + CAAM_NOT_SUPPORTED, /* Feature not supported */ + CAAM_OUT_MEMORY, /* Out of memory */ + CAAM_BAD_PARAM, /* Bad parameters */ + CAAM_SHORT_BUFFER, /* Buffer is too short */ + CAAM_BUSY, /* Operation is not possible, system busy */ + CAAM_PENDING, /* Operation is pending */ + CAAM_TIMEOUT, /* Operation timeout */ + CAAM_OUT_OF_BOUND, /* Value is out of boundary */ + CAAM_JOB_STATUS, /* A job status is available */ + CAAM_NOT_INIT, /* Feature is not initialized */ +}; + +#endif /* __CAAM_STATUS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_trace.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_trace.h new file mode 100644 index 0000000..df9f478 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_trace.h @@ -0,0 +1,325 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019-2021 NXP + * + * Brief CAAM driver trace include file. + * Definition of the internal driver trace macros. + */ + +#ifndef __CAAM_TRACE_H__ +#define __CAAM_TRACE_H__ + +#include +#include + +#define CAAM_DBG_TRACE(var) (CFG_DBG_CAAM_TRACE & DBG_TRACE_##var) +#define CAAM_DBG_DESC(var) (CFG_DBG_CAAM_DESC & DBG_TRACE_##var) +#define CAAM_DBG_BUF(var) (CFG_DBG_CAAM_BUF & DBG_TRACE_##var) + +/* + * Debug Macros function of CAAM Debug Level setting + * CFG_DBG_CAAM_TRACE Module print trace + * CFG_DBG_CAAM_DESC Module descriptor dump + * CFG_DBG_CAAM_BUF Module buffer dump + * + * A module is represented with the same bit in each configuration value. + * Module Bit definition is as follow: + */ +#define DBG_TRACE_HAL BIT32(0) /* HAL trace */ +#define DBG_TRACE_CTRL BIT32(1) /* Controller trace */ +#define DBG_TRACE_MEM BIT32(2) /* Memory utility trace */ +#define DBG_TRACE_SGT BIT32(3) /* Scatter Gather trace */ +#define DBG_TRACE_PWR BIT32(4) /* Power trace */ +#define DBG_TRACE_JR BIT32(5) /* Job Ring trace */ +#define DBG_TRACE_RNG BIT32(6) /* RNG trace */ +#define DBG_TRACE_HASH BIT32(7) /* Hash trace */ +#define DBG_TRACE_RSA BIT32(8) /* RSA trace */ +#define DBG_TRACE_CIPHER BIT32(9) /* Cipher dump Buffer */ +#define DBG_TRACE_BLOB BIT32(10) /* BLOB trace */ +#define DBG_TRACE_DMAOBJ BIT32(11) /* DMA Object trace */ +#define DBG_TRACE_ECC BIT32(12) /* ECC trace */ +#define DBG_TRACE_DH BIT32(13) /* DH trace */ +#define DBG_TRACE_DSA BIT32(14) /* DSA trace */ +#define DBG_TRACE_MP BIT32(15) /* MP trace */ + +/* HAL */ +#if CAAM_DBG_TRACE(HAL) +#define HAL_TRACE DRV_TRACE +#else +#define HAL_TRACE(...) +#endif + +/* Controller */ +#if CAAM_DBG_TRACE(CTRL) +#define CTRL_TRACE DRV_TRACE +#else +#define CTRL_TRACE(...) +#endif + +/* Memory Utility */ +#if CAAM_DBG_TRACE(MEM) +#define MEM_TRACE DRV_TRACE +#else +#define MEM_TRACE(...) +#endif + +/* Scatter Gether Table */ +#if CAAM_DBG_TRACE(SGT) +#define SGT_TRACE DRV_TRACE +#else +#define SGT_TRACE(...) +#endif + +/* Power */ +#if CAAM_DBG_TRACE(PWR) +#define PWR_TRACE DRV_TRACE +#else +#define PWR_TRACE(...) +#endif + +/* Job Ring */ +#if CAAM_DBG_TRACE(JR) +#define JR_TRACE DRV_TRACE +#if CAAM_DBG_DESC(JR) +#define JR_DUMPDESC(desc) \ + do { \ + JR_TRACE("Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define JR_DUMPDESC(desc) +#endif +#else +#define JR_TRACE(...) +#define JR_DUMPDESC(desc) +#endif + +/* RNG */ +#if CAAM_DBG_TRACE(RNG) +#define RNG_TRACE DRV_TRACE +#if CAAM_DBG_DESC(RNG) +#define RNG_DUMPDESC(desc) \ + do { \ + RNG_TRACE("RNG Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define RNG_DUMPDESC(desc) +#endif +#else +#define RNG_TRACE(...) +#define RNG_DUMPDESC(desc) +#endif + +/* Hash */ +#if CAAM_DBG_TRACE(HASH) +#define HASH_TRACE DRV_TRACE +#if CAAM_DBG_DESC(HASH) +#define HASH_DUMPDESC(desc) \ + do { \ + HASH_TRACE("HASH Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define HASH_DUMPDESC(desc) +#endif +#if CAAM_DBG_BUF(HASH) +#define HASH_DUMPBUF DRV_DUMPBUF +#else +#define HASH_DUMPBUF(...) +#endif +#else +#define HASH_TRACE(...) +#define HASH_DUMPDESC(desc) +#define HASH_DUMPBUF(...) +#endif + +/* RSA */ +#if CAAM_DBG_TRACE(RSA) +#define RSA_TRACE DRV_TRACE +#if CAAM_DBG_DESC(RSA) +#define RSA_DUMPDESC(desc) \ + do { \ + RSA_TRACE("RSA Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define RSA_DUMPDESC(desc) +#endif +#if CAAM_DBG_BUF(RSA) +#define RSA_DUMPBUF DRV_DUMPBUF +#else +#define RSA_DUMPBUF(...) +#endif +#else +#define RSA_TRACE(...) +#define RSA_DUMPDESC(desc) +#define RSA_DUMPBUF(...) +#endif + +/* Cipher */ +#if CAAM_DBG_TRACE(CIPHER) +#define CIPHER_TRACE DRV_TRACE +#if CAAM_DBG_DESC(CIPHER) +#define CIPHER_DUMPDESC(desc) \ + do { \ + CIPHER_TRACE("CIPHER Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define CIPHER_DUMPDESC(desc) +#endif +#if CAAM_DBG_BUF(CIPHER) +#define CIPHER_DUMPBUF DRV_DUMPBUF +#else +#define CIPHER_DUMPBUF(...) +#endif +#else +#define CIPHER_TRACE(...) +#define CIPHER_DUMPDESC(desc) +#define CIPHER_DUMPBUF(...) +#endif + +/* DMA Object */ +#if CAAM_DBG_TRACE(DMAOBJ) +#define DMAOBJ_TRACE DRV_TRACE +#else +#define DMAOBJ_TRACE(...) +#endif + +/* ECC */ +#if CAAM_DBG_TRACE(ECC) +#define ECC_TRACE DRV_TRACE +#if CAAM_DBG_DESC(ECC) +#define ECC_DUMPDESC(desc) \ + do { \ + ECC_TRACE("ECC Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define ECC_DUMPDESC(desc) do { } while (0) +#endif +#if CAAM_DBG_BUF(ECC) +#define ECC_DUMPBUF DRV_DUMPBUF +#else +#define ECC_DUMPBUF(...) do { } while (0) +#endif +#else +#define ECC_TRACE(...) do { } while (0) +#define ECC_DUMPDESC(desc) do { } while (0) +#define ECC_DUMPBUF(...) do { } while (0) +#endif + +/* DH */ +#if CAAM_DBG_TRACE(DH) +#define DH_TRACE DRV_TRACE +#if CAAM_DBG_DESC(DH) +#define DH_DUMPDESC(desc) \ + { \ + DH_TRACE("DH Descriptor"); \ + DRV_DUMPDESC(desc); \ + } +#else +#define DH_DUMPDESC(desc) +#endif +#if CAAM_DBG_BUF(DH) +#define DH_DUMPBUF DRV_DUMPBUF +#else +#define DH_DUMPBUF(...) +#endif +#else +#define DH_TRACE(...) +#define DH_DUMPDESC(desc) +#define DH_DUMPBUF(...) +#endif + +/* DSA */ +#if CAAM_DBG_TRACE(DSA) +#define DSA_TRACE DRV_TRACE +#if CAAM_DBG_DESC(DSA) +#define DSA_DUMPDESC(desc) \ + do { \ + MP_TRACE("DSA Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define DSA_DUMPDESC(desc) +#endif +#if CAAM_DBG_BUF(DSA) +#define DSA_DUMPBUF DRV_DUMPBUF +#else +#define DSA_DUMPBUF(...) +#endif +#else +#define DSA_TRACE(...) +#define DSA_DUMPDESC(desc) +#define DSA_DUMPBUF(...) +#endif + +/* MP */ +#if CAAM_DBG_TRACE(MP) +#define MP_TRACE DRV_TRACE +#if CAAM_DBG_DESC(MP) +#define MP_DUMPDESC(desc) \ + do { \ + MP_TRACE("MP Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define MP_DUMPDESC(desc) +#endif +#if CAAM_DBG_BUF(MP) +#define MP_DUMPBUF DRV_DUMPBUF +#else +#define MP_DUMPBUF(...) +#endif +#else +#define MP_TRACE(...) do { } while (0) +#define MP_DUMPDESC(desc) +#define MP_DUMPBUF(...) +#endif + +#if (TRACE_LEVEL >= TRACE_DEBUG) +#define DRV_TRACE(...) \ + trace_printf(__func__, __LINE__, TRACE_DEBUG, true, __VA_ARGS__) +#define DRV_DUMPDESC(desc) dump_desc(desc) + +#define DRV_DUMPBUF(title, buf, len) \ + do { \ + __typeof__(buf) _buf = (buf); \ + __typeof__(len) _len = (len); \ + \ + DRV_TRACE("%s @%p : %zu", title, _buf, _len); \ + dhex_dump(NULL, 0, 0, _buf, _len); \ + } while (0) + +#else +#define DRV_TRACE(...) +#define DRV_DUMPDESC(...) +#define DRV_DUMPBUF(...) +#endif + +/* BLOB */ +#if CAAM_DBG_TRACE(BLOB) +#define BLOB_TRACE DRV_TRACE +#if CAAM_DBG_DESC(BLOB) +#define BLOB_DUMPDESC(desc) \ + do { \ + BLOB_TRACE("BLOB Descriptor"); \ + DRV_DUMPDESC(desc); \ + } while (0) +#else +#define BLOB_DUMPDESC(desc) +#endif +#if CAAM_DBG_BUF(BLOB) +#define BLOB_DUMPBUF DRV_DUMPBUF +#else +#define BLOB_DUMPBUF(...) +#endif +#else +#define BLOB_TRACE(...) +#define BLOB_DUMPDESC(desc) +#define BLOB_DUMPBUF(...) +#endif + +#endif /* CAAM_TRACE_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_types.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_types.h new file mode 100644 index 0000000..ffa0638 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_types.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020-2021 NXP + * + * CAAM driver data type definition. + */ + +#ifndef __CAAM_TYPES_H__ +#define __CAAM_TYPES_H__ + +#include + +/* + * Definition of a CAAM buffer type + */ +struct caambuf { + uint8_t *data; /* Data buffer */ + paddr_t paddr; /* Physical address of the buffer */ + size_t length; /* Number of bytes in the data buffer */ + uint8_t nocache; /* =1 if buffer is not cacheable, 0 otherwise */ +}; + +/* + * Definition of a CAAM Block buffer. Buffer used to store + * user source data to build a full algorithm block buffer + */ +struct caamblock { + struct caambuf buf; /* Data buffer */ + size_t filled; /* Current length filled in the buffer */ + size_t max; /* Maximum size of the block */ +}; + +/* + * Definition of key size + */ +struct caamdefkey { + uint8_t min; /* Minimum size */ + uint8_t max; /* Maximum size */ + uint8_t mod; /* Key modulus */ +}; + +#endif /* __CAAM_TYPES_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_delay.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_delay.h new file mode 100644 index 0000000..8d41601 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_delay.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019 NXP + * + * Brief Delay management utilities header. + */ +#ifndef __CAAM_UTILS_DELAY_H__ +#define __CAAM_UTILS_DELAY_H__ + +/* + * Wait given microsecond + * + * @time Time in microsecond + */ +void caam_udelay(uint32_t time); + +#endif /* __CAAM_UTILS_DELAY_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_dmaobj.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_dmaobj.h new file mode 100644 index 0000000..518ebb6 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_dmaobj.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020-2021 NXP + * + * CAAM DMA data object utilities include file. + */ +#ifndef __CAAM_UTILS_DMAOBJ_H__ +#define __CAAM_UTILS_DMAOBJ_H__ + +#include +#include +#include + +/* + * CAAM DMA Object type + * @priv Private object data not used externally. + * @orig Original data buffer + * @sgtbuf CAAM SGT/Buffer object + */ +struct caamdmaobj { + void *priv; + struct caambuf orig; + struct caamsgtbuf sgtbuf; +}; + +/* + * Initialize a CAAM DMA object of type input data. + * If necessary, a new CAAM Buffer will be reallocated if given @data is not + * accessible by the CAAM DMA and input data copied into. + * + * @obj [out] CAAM DMA object initialized + * @data Input data pointer + * @length Length in bytes of the input data + */ +TEE_Result caam_dmaobj_init_input(struct caamdmaobj *obj, const void *data, + size_t len); +/* + * Initialize and build the SGT/Buffer Object of a CAAM DMA object of type + * input data. + * Function call the caam_dmaobj_init_input function and if success + * the caam_dmaobj_sgtbuf_build function. If the full size of the input + * data can't be handled in the SGT/Buffer Object, returns in error. + * + * @obj [out] CAAM DMA object initialized + * @data Input data pointer + * @length Length in bytes of the input data + */ +TEE_Result caam_dmaobj_input_sgtbuf(struct caamdmaobj *obj, const void *data, + size_t len); +/* + * Initialize a CAAM DMA object of type output data. + * If necessary, a new CAAM Buffer will be reallocated if given @data is not + * accessible by the CAAM DMA or if the given @length is lower than + * @min_length requested for the CAAM operation. + * + * @obj [out] CAAM DMA object initialized + * @data Output data pointer + * @length Length in bytes of the output data + * @min_length Minimum length in bytes needed for the output data + */ +TEE_Result caam_dmaobj_init_output(struct caamdmaobj *obj, void *data, + size_t length, size_t min_length); + +/* + * Initialize and build the SGT/Buffer Object of a CAAM DMA object of type + * output data. + * Function call the caam_dmaobj_init_output function and if success + * the caam_dmaobj_sgtbuf_build function. If the full size of the output + * data can't be handled in the SGT/Buffer Object, returns in error. + * + * Note: to allocate a output buffer, set @data = NULL and length = 0, the + * buffer size allocated will be the @min_length size. Caution, the field + * orig of the @obj is kept empty. + * + * @obj [out] CAAM DMA object initialized + * @data Output data pointer + * @length Length in bytes of the output data + * @min_length Minimum length in bytes needed for the output data + */ +TEE_Result caam_dmaobj_output_sgtbuf(struct caamdmaobj *obj, void *data, + size_t length, size_t min_length); + +/* + * Push the data to physical memory with a cache clean or flush depending + * on the type of data, respectively input or output. + * + * @obj CAAM DMA object + */ +void caam_dmaobj_cache_push(struct caamdmaobj *obj); + +/* + * Copy the CAAM DMA object buffer to the original data buffer. + * Return the number of bytes copied. + * + * @obj CAAM DMA object + */ +size_t caam_dmaobj_copy_to_orig(struct caamdmaobj *obj); + +/* + * Copy the CAAM DMA object buffer to the original data buffer removing + * non-significant first zeros (left zeros). + * If all DMA object buffer is zero, left only one zero in the destination. + * Return the number of bytes copied. + * + * @obj CAAM DMA object + */ +size_t caam_dmaobj_copy_ltrim_to_orig(struct caamdmaobj *obj); + +/* + * Free the CAAM DMA object. + * If a buffer has been reallocated, free it. + * Free the sgtbuf object. + * + * @obj CAAM DMA object + */ +void caam_dmaobj_free(struct caamdmaobj *obj); + +/* + * Create a CAAM DMA object SGT type with the block buffer @block first and + * the CAAM DMA Object after + * + * @res CAAM DMA object resulting + * @block CAAM Block buffer to add first + * @obj CAAM DMA object to add secondly + */ +TEE_Result caam_dmaobj_add_first_block(struct caamdmaobj *obj, + struct caamblock *block); + +/* + * Derive a CAAM DMA object's sgtbuf object to a new DMA object. + * The @from CAAM DMA object sgtbuf must have to be created first to + * allocate the DMA Buffers. + * + * @obj [out] CAAM DMA object derived + * @from Original CAAM DMA object + * @offset Offset to start from + * @length Length in bytes of the data + */ +TEE_Result caam_dmaobj_derive_sgtbuf(struct caamdmaobj *obj, + const struct caamdmaobj *from, + size_t offset, size_t length); + +/* + * Build the CAAM DMA Object's sgtbuf input and output with the same data + * length. + * First try to build input sgtbuf of maximum @length starting at @offset. + * Then build output sgtbuf with same input data length built start at @offset. + * If output sgtbuf built data length is not the same as the input's one, + * rebuild the input with same output data length. + * + * If the both input and output length are not equal returns an error. + * + * @input CAAM DMA Input object + * @output CAAM DMA Output object + * @length [in/out] maximum length to do/done + * @off Starting offset + * @align Buffer allocation alignment + */ +TEE_Result caam_dmaobj_sgtbuf_inout_build(struct caamdmaobj *input, + struct caamdmaobj *output, + size_t *length, size_t off, + size_t align); + +/* + * Prepare input/output CAAM DMA Object's by allocating the DMA Buffers + * if needed. + * If @input or @output is NULL, allocates DMA buffer of given object. + * Else if both objects are set, allocates DMA buffer of the same + * size for the @input and @output objects. + * Minimum DMA Buffer size allocated is the @min_size value. Even if this + * minimum size allocation failed, returns an error. + * + * @input CAAM DMA object input + * @output CAAM DMA object output + * @min_size Mimimum length to allocate + */ +TEE_Result caam_dmaobj_prepare(struct caamdmaobj *input, + struct caamdmaobj *output, size_t min_size); + +/* + * Build the CAAM DMA Object's sgtbuf object. Try to build a sgtbuf of + * maximum @length starting at @offset. + * Return the @length mapped in the sgtbuf object. + * + * @obj CAAM DMA object + * @length [in/out] maximum length to do/done + * @off Starting offset + * @align Buffer allocation alignment + */ +TEE_Result caam_dmaobj_sgtbuf_build(struct caamdmaobj *obj, size_t *length, + size_t off, size_t align); + +#endif /* __CAAM_UTILS_DMAOBJ_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_mem.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_mem.h new file mode 100644 index 0000000..cb7ce2c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_mem.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief Memory management utilities. + * Primitive to allocate, free memory. + */ + +#ifndef __CAAM_UTILS_MEM_H__ +#define __CAAM_UTILS_MEM_H__ + +#include + +/* + * Allocate normal memory. + * + * @size size in bytes of the memory to allocate + */ +void *caam_alloc(size_t size); + +/* + * Allocate normal memory and initialize it to 0's. + * + * @size size in bytes of the memory to allocate + */ +void *caam_calloc(size_t size); + +/* + * Allocate memory aligned with a cache line and initialize it to 0's. + * + * @size size in bytes of the memory to allocate + */ +void *caam_calloc_align(size_t size); + +/* + * Free allocated memory + * + * @ptr reference to the object to free + */ +void caam_free(void *ptr); + +/* + * Allocate Job descriptor and initialize it to 0's. + * + * @nbentries Number of descriptor entries + */ +uint32_t *caam_calloc_desc(uint8_t nbentries); + +/* + * Free descriptor + * + * @ptr Reference to the descriptor to free + */ +void caam_free_desc(uint32_t **ptr); + +/* + * Allocate internal driver buffer and initialize it with 0s. + * + * @buf [out] buffer allocated + * @size size in bytes of the memory to allocate + */ +enum caam_status caam_calloc_buf(struct caambuf *buf, size_t size); + +/* + * Allocate internal driver buffer. + * + * @buf [out] buffer allocated + * @size size in bytes of the memory to allocate + */ +enum caam_status caam_alloc_buf(struct caambuf *buf, size_t size); + +/* + * Allocate internal driver buffer aligned with a cache line and initialize + * if with 0's. + * + * @buf [out] buffer allocated + * @size size in bytes of the memory to allocate + */ +enum caam_status caam_calloc_align_buf(struct caambuf *buf, size_t size); + +/* + * Allocate internal driver buffer aligned with a cache line. + * + * @buf [out] buffer allocated + * @size size in bytes of the memory to allocate + */ +enum caam_status caam_alloc_align_buf(struct caambuf *buf, size_t size); + +/* + * Free internal driver buffer allocated memory + * + * @buf Driver buffer to free + */ +void caam_free_buf(struct caambuf *buf); + +/* + * Copy source data into the block buffer. Allocate block buffer if + * it's not defined. + * + * @block [in/out] Block buffer information. Return buffer filled. + * @src Source to copy + * @offset Source offset to start + */ +enum caam_status caam_cpy_block_src(struct caamblock *block, + struct caambuf *src, size_t offset); + +/* + * Return the number of Physical Areas used by the buffer @buf. + * If @pabufs is not NULL, function fills it with the Physical Areas used + * to map the buffer @buf. + * + * @buf Data buffer to analyze + * @pabufs[out] If not NULL, list the Physical Areas of the @buf + * + * Returns: + * Number of physical area used + * (-1) if error + */ +int caam_mem_get_pa_area(struct caambuf *buf, struct caambuf **pabufs); + +/* + * Return if the buffer @buf is cacheable or not + * + * @buf Buffer address + * @size Buffer size + */ +bool caam_mem_is_cached_buf(void *buf, size_t size); + +/* + * Copy source data into the destination buffer removing non-significant + * first zeros (left zeros). + * If all source @src buffer is zero, left only one zero in the destination. + * + * @dst [out] Destination buffer + * @src Source to copy + */ +void caam_mem_cpy_ltrim_buf(struct caambuf *dst, struct caambuf *src); + +#endif /* __CAAM_UTILS_MEM_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_sgt.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_sgt.h new file mode 100644 index 0000000..4dd6b68 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_sgt.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019, 2021 NXP + * + * Brief Scatter-Gather Table management utilities header. + */ +#ifndef __CAAM_UTILS_SGT_H__ +#define __CAAM_UTILS_SGT_H__ + +#include +#include + +#define BP_SGT_V2_OFFSET 48 +#define BS_SGT_V2_OFFSET 12 +#define SGT_V2_OFFSET_MAX_VALUE GENMASK_64(BS_SGT_V2_OFFSET - 1, 0) +#define BM_SGT_V2_OFFSET \ + SHIFT_U64(GENMASK_64(BS_SGT_V2_OFFSET - 1, 0), BP_SGT_V2_OFFSET) +#define BV_SGT_V2_OFFSET(_x) SHIFT_U64(((uint64_t)_x), BP_SGT_V2_OFFSET) +#define SGT_V2_ENTRY_OFFSET(_x) \ + ((((uint64_t)_x) & BM_SGT_V2_OFFSET) >> BP_SGT_V2_OFFSET) + +#define BP_SGT_V2_AVAIL_LENGTH 0 +#define BS_SGT_V2_AVAIL_LENGTH 32 +#define SGT_V2_AVAIL_LENGTH_MAX_VALUE GENMASK_64(BS_SGT_V2_AVAIL_LENGTH - 1, 0) +#define BM_SGT_V2_AVAIL_LENGTH \ + SHIFT_U64(SGT_V2_AVAIL_LENGTH_MAX_VALUE, BP_SGT_V2_AVAIL_LENGTH) +#define BV_SGT_V2_AVAIL_LENGTH(_x) \ + SHIFT_U64(((uint64_t)_x), BP_SGT_V2_AVAIL_LENGTH) +#define SGT_V2_ENTRY_AVAIL_LENGTH(_x) \ + ((((uint64_t)_x) & BM_SGT_V2_AVAIL_LENGTH) >> BP_SGT_V2_AVAIL_LENGTH) + +#define BP_SGT_V2_F 63 +#define BM_SGT_V2_F BIT64(BP_SGT_V2_F) +#define BP_SGT_V2_IVP 46 +#define BM_SGT_V2_IVP BIT64(BP_SGT_V2_IVP) + +/* + * Scatter/Gather Table type for input and output data + */ +union caamsgt { + struct { + /* W0 - Address pointer (MS 8 LSBs) */ + uint32_t ptr_ms; + /* W1 - Address pointer (LS 32 bits) */ + uint32_t ptr_ls; + /* W2 - Length 30bits, 1bit Final, 1bit Extension */ + uint32_t len_f_e; + /* W3- Offset in memory buffer (13 LSBs) */ + uint32_t offset; + } v1; + struct { + uint64_t w1; /* Address of the data */ + uint64_t w2; /* Final bit, offset and length */ + } v2; +}; + +/* + * Data buffer encoded in SGT format + */ +struct caamsgtbuf { + union caamsgt *sgt; /* SGT Array */ + struct caambuf *buf; /* Buffer Array */ + unsigned int number; /* Number of SGT/Buf */ + size_t length; /* Total length of the data encoded */ + paddr_t paddr; /* Physical address to use in CAAM descriptor */ + bool sgt_type; /* Define the data format */ +}; + +/* + * Allocate data of type struct caamsgtbuf + * + * @data [out] Data object allocated + */ +enum caam_status caam_sgtbuf_alloc(struct caamsgtbuf *data); + +/* + * Free data of type struct caamsgtbuf + * + * @data Data object to free + */ +void caam_sgtbuf_free(struct caamsgtbuf *data); + +/* + * Cache operation on SGT table + * + * @op Cache operation + * @insgt SGT table + * @length Length of data to maintain + */ +void caam_sgt_cache_op(enum utee_cache_operation op, struct caamsgtbuf *insgt, + size_t length); + +/* + * Set a Scatter Gather Table Entry + * + * @sgt SGT entry + * @paddr Data's physical address + * @len Data's length + * @offset Offset to start in data buffer + * @final_e Final entry in the table if true + */ +void caam_sgt_set_entry(union caamsgt *sgt, vaddr_t paddr, size_t len, + unsigned int offset, bool final_e); + +#define CAAM_SGT_ENTRY(sgt, paddr, len) \ + caam_sgt_set_entry(sgt, paddr, len, 0, false) +#define CAAM_SGT_ENTRY_FINAL(sgt, paddr, len) \ + caam_sgt_set_entry(sgt, paddr, len, 0, true) + +/* + * Build a SGT object with @data buffer. + * If the @data buffer is a buffer mapped on non-contiguous physical areas, + * convert it in SGT entries. + * Fill the CAAM SGT table with the buffer list in @sgt parameter + * + * @sgt [in/out] SGT buffer list and table + */ +void caam_sgt_fill_table(struct caamsgtbuf *sgt); + +/* + * Derive a CAAM SGT table from the @from SGT table starting @offset. + * Allocate the resulting SGT table derived. + * + * @sgt [out] SGT buffer list and table + * @from Input SGT table + * @offset Offset to start + * @length Length of the new SGT data + */ +enum caam_status caam_sgt_derive(struct caamsgtbuf *sgt, + const struct caamsgtbuf *from, size_t offset, + size_t length); + +/* + * Print the details of an SGT entry using the trace macro + * + * @idx [in]Index of the sgt to print + * @sgt [in] SGT buffer list and table + */ +void sgt_entry_trace(unsigned int idx, const struct caamsgtbuf *sgt); + +/* + * Add an @offset to the SGT entry + * + * @sgt [in/out] Sgt entry + * @offset Offset to add + */ +void sgt_entry_offset(union caamsgt *sgt, unsigned int offset); + +#endif /* __CAAM_UTILS_SGT_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h new file mode 100644 index 0000000..8da32dc --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/include/caam_utils_status.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019, 2021 NXP + * + * Brief Status code management utilities header. + */ +#ifndef __CAAM_UTILS_STATUS_H__ +#define __CAAM_UTILS_STATUS_H__ + +#include +#include + +/* + * Convert Job status code to TEE Result + * + * @status Job status code + */ +TEE_Result job_status_to_tee_result(uint32_t status); + +/* + * Convert caam status code to TEE Result + * + * @status caam status code + */ +TEE_Result caam_status_to_tee_result(enum caam_status status); + +#endif /* __CAAM_UTILS_STATUS_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c b/optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c new file mode 100644 index 0000000..df552ac --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/mp/caam_mp.c @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021, 2023 NXP + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MP_SIGN_MAX_MSG_SIZE (4 * 1024) + +#ifdef CFG_PHYS_64BIT +#define MP_PRIV_DESC_ENTRIES 7 +#define MP_PUB_DESC_ENTRIES 7 +#define MP_SIGN_DESC_ENTRIES 13 +#else +#define MP_PRIV_DESC_ENTRIES 6 +#define MP_PUB_DESC_ENTRIES 6 +#define MP_SIGN_DESC_ENTRIES 9 +#endif + +/* + * MP module private data + */ +static struct mp_privdata { + uint8_t curve; /* Protocol Data Block curve selection */ + uint8_t sec_size; /* Security key size in bytes */ + vaddr_t ctrl_addr; /* Base address of the controller */ + enum caam_status mp_status; /* Indicate the MP status */ +} mp_privdata; + +/* + * Generate manufacturing private key. + * The ECDSA private key is securely stored in the MPPKR. + * This register is locked to prevent reading or writing. + * + * @passphrase Passphrase + * @len Passphrase length + */ +static enum caam_status do_mppriv_gen(const char *passphrase, size_t len) +{ + enum caam_status ret = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + + MP_TRACE("MP private key generation"); + + assert(passphrase && len); + + desc = caam_calloc_desc(MP_PRIV_DESC_ENTRIES); + if (!desc) + return CAAM_OUT_MEMORY; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, PROT_MP_CURVE(mp_privdata.curve)); + caam_desc_add_ptr(desc, virt_to_phys((void *)passphrase)); + caam_desc_add_word(desc, len); + caam_desc_add_word(desc, MPPRIVK); + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + MP_DUMPDESC(desc); + + cache_operation(TEE_CACHECLEAN, (void *)passphrase, len); + + jobctx.desc = desc; + ret = caam_jr_enqueue(&jobctx, NULL); + + if (ret != CAAM_NO_ERROR) { + MP_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = CAAM_NOT_SUPPORTED; + } + + caam_free_desc(&desc); + return ret; +} + +TEE_Result caam_mp_export_mpmr(uint8_t *mpmr, size_t *size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct caambuf caam_mpmr = { + .data = mpmr, + .length = *size, + }; + + MP_TRACE("Get MP message"); + + ret = caam_hal_ctrl_read_mpmr(mp_privdata.ctrl_addr, &caam_mpmr); + *size = caam_mpmr.length; + + return ret; +} + +TEE_Result caam_mp_export_publickey(uint8_t *pubkey, size_t *size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + struct caamdmaobj reskey = { }; + uint32_t pdb_sgt_flag = 0; + uint32_t desclen = 0; + uint32_t *desc = NULL; + + /* Check if MP is operational */ + if (mp_privdata.mp_status != CAAM_NO_ERROR) + return caam_status_to_tee_result(mp_privdata.mp_status); + + if (!pubkey || !size) + return TEE_ERROR_BAD_PARAMETERS; + + /* The public key size is twice the private key size */ + if (*size < 2 * mp_privdata.sec_size) { + *size = 2 * mp_privdata.sec_size; + return TEE_ERROR_SHORT_BUFFER; + } + + ret = caam_dmaobj_output_sgtbuf(&reskey, pubkey, *size, + 2 * mp_privdata.sec_size); + if (ret) + return ret; + + if (reskey.sgtbuf.sgt_type) + pdb_sgt_flag = PROT_MP_PUBK_SGT; + + desc = caam_calloc_desc(MP_PUB_DESC_ENTRIES); + if (!desc) + return TEE_ERROR_OUT_OF_MEMORY; + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, + PROT_MP_CURVE(mp_privdata.curve) | pdb_sgt_flag); + caam_desc_add_ptr(desc, reskey.sgtbuf.paddr); + caam_desc_add_word(desc, reskey.sgtbuf.length); + caam_desc_add_word(desc, MPPUBK); + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + MP_DUMPDESC(desc); + + caam_dmaobj_cache_push(&reskey); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + MP_TRACE("MP Public Key generated"); + reskey.orig.length = 2 * mp_privdata.sec_size; + *size = caam_dmaobj_copy_to_orig(&reskey); + + MP_DUMPBUF("MP PubKey", pubkey, *size); + + ret = caam_status_to_tee_result(retstatus); + } else { + MP_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + + caam_dmaobj_free(&reskey); + caam_free_desc(&desc); + + return ret; +} + +TEE_Result caam_mp_sign(uint8_t *msg, size_t *msg_size, uint8_t *sig, + size_t *sig_size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct caam_jobctx jobctx = { }; + struct caamdmaobj msg_input = { }; + struct caamdmaobj sign_c = { }; + struct caamdmaobj sign_d = { }; + struct caambuf hash = { }; + uint32_t *desc = NULL; + uint32_t desclen = 0; + uint32_t pdb_sgt_flags = 0; + uint8_t *aligned_msg = NULL; + size_t sign_len = 0; + + MP_TRACE("MP sign operation"); + + /* Check if MP is operational */ + if (mp_privdata.mp_status != CAAM_NO_ERROR) + return caam_status_to_tee_result(mp_privdata.mp_status); + + if (!msg || !msg_size || !sig || !sig_size) + return TEE_ERROR_BAD_PARAMETERS; + + if (*sig_size < 2 * mp_privdata.sec_size) { + *sig_size = 2 * mp_privdata.sec_size; + return TEE_ERROR_SHORT_BUFFER; + } + + if (*msg_size > MP_SIGN_MAX_MSG_SIZE) + return TEE_ERROR_EXCESS_DATA; + + /* Re-allocate the message to a cache-aligned buffer */ + aligned_msg = caam_alloc(*msg_size); + if (!aligned_msg) { + MP_TRACE("Message reallocation error"); + ret = TEE_ERROR_OUT_OF_MEMORY; + goto exit_mpsign; + } + memcpy(aligned_msg, msg, *msg_size); + + /* + * Allocate the hash buffer of the Message + MPMR payload + * Note: Hash is not retrieve, hence no need to do cache + * maintenance + */ + retstatus = caam_alloc_align_buf(&hash, TEE_MAX_HASH_SIZE); + if (retstatus != CAAM_NO_ERROR) { + MP_TRACE("Hash allocation error"); + ret = caam_status_to_tee_result(retstatus); + goto exit_mpsign; + } + + /* + * Re-allocate the signature result buffer with a maximum size + * of the roundup to 16 bytes of the secure size in bytes if + * the signature buffer is not aligned or too short. + * + * - 1st Part: size_sec + * - 2nd Part: size_sec roundup to 16 bytes + */ + sign_len = ROUNDUP(mp_privdata.sec_size, 16) + mp_privdata.sec_size; + + ret = caam_dmaobj_output_sgtbuf(&sign_c, sig, *sig_size, sign_len); + if (ret) + goto exit_mpsign; + + if (sign_c.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_MP_SIGN_C; + + /* Prepare the 2nd Part of the signature. Derived from sign_c */ + ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, mp_privdata.sec_size, + ROUNDUP(mp_privdata.sec_size, 16)); + if (ret) + goto exit_mpsign; + + if (sign_d.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_MP_SIGN_D; + + ret = caam_dmaobj_input_sgtbuf(&msg_input, aligned_msg, *msg_size); + if (ret) + goto exit_mpsign; + + if (msg_input.sgtbuf.sgt_type) + pdb_sgt_flags |= PDB_SGT_MP_SIGN_MSG; + + desc = caam_calloc_desc(MP_SIGN_DESC_ENTRIES); + if (!desc) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto exit_mpsign; + } + + caam_desc_init(desc); + caam_desc_add_word(desc, DESC_HEADER(0)); + caam_desc_add_word(desc, + PROT_MP_CURVE(mp_privdata.curve) | pdb_sgt_flags); + caam_desc_add_ptr(desc, msg_input.sgtbuf.paddr); + caam_desc_add_ptr(desc, hash.paddr); + caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); + caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); + caam_desc_add_word(desc, msg_input.sgtbuf.length); + caam_desc_add_word(desc, MPSIGN_OP); + + desclen = caam_desc_get_len(desc); + caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); + + MP_DUMPDESC(desc); + + caam_dmaobj_cache_push(&msg_input); + caam_dmaobj_cache_push(&sign_c); + + jobctx.desc = desc; + retstatus = caam_jr_enqueue(&jobctx, NULL); + + if (retstatus == CAAM_NO_ERROR) { + sign_c.orig.length = 2 * mp_privdata.sec_size; + *sig_size = caam_dmaobj_copy_to_orig(&sign_c); + + MP_DUMPBUF("MP Signature", sdata->signature.data, + sdata->signature.length); + + ret = caam_status_to_tee_result(retstatus); + } else { + MP_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); + ret = job_status_to_tee_result(jobctx.status); + } + +exit_mpsign: + caam_free(aligned_msg); + caam_free_buf(&hash); + caam_free_desc(&desc); + caam_dmaobj_free(&msg_input); + caam_dmaobj_free(&sign_c); + caam_dmaobj_free(&sign_d); + + return ret; +} + +enum caam_status caam_mp_init(vaddr_t ctrl_addr) +{ + /* + * Manufacturing protection secret values for DSA key pair + * generation. + */ + static const char passphrase[] = "manufacturing protection"; + static const char mpmr_data[] = "value to fill the MPMR content"; + enum caam_status retstatus = CAAM_FAILURE; + uint8_t curve = 0; + uint8_t hash_limit = 0; + + struct caambuf msg_mpmr = { + .data = (uint8_t *)mpmr_data, + .length = strlen(mpmr_data) + }; + + mp_privdata.ctrl_addr = ctrl_addr; + mp_privdata.mp_status = CAAM_NOT_INIT; + + curve = caam_hal_ctrl_get_mpcurve(ctrl_addr); + + if (curve == UINT8_MAX) { + mp_privdata.mp_status = CAAM_NOT_SUPPORTED; + return mp_privdata.mp_status; + } + + if (caam_hal_ctrl_is_mp_set(ctrl_addr)) { + mp_privdata.mp_status = CAAM_NO_ERROR; + return CAAM_NO_ERROR; + } + + if (!curve) { + /* Get the device HASH Limit to select the MP Curve */ + hash_limit = caam_hal_ctrl_hash_limit(ctrl_addr); + + switch (hash_limit) { + case TEE_MAIN_ALGO_SHA256: + mp_privdata.curve = PDB_MP_CSEL_P256; + mp_privdata.sec_size = 32; + break; + case TEE_MAIN_ALGO_SHA512: + mp_privdata.curve = PDB_MP_CSEL_P521; + mp_privdata.sec_size = 66; + break; + default: + MP_TRACE("This curve doesn't exist"); + return CAAM_FAILURE; + } + + MP_TRACE("Generating MP Private key"); + retstatus = do_mppriv_gen(passphrase, strlen(passphrase)); + + if (retstatus != CAAM_NO_ERROR) { + MP_TRACE("do_mppriv_gen failed!"); + return retstatus; + } + } else { + /* MP Curve is already programmed. Set the right key size */ + mp_privdata.curve = curve; + + switch (curve) { + case PDB_MP_CSEL_P256: + mp_privdata.sec_size = 32; + break; + case PDB_MP_CSEL_P521: + mp_privdata.sec_size = 66; + break; + default: + MP_TRACE("This curve is not supported"); + return CAAM_FAILURE; + } + } + + /* Fill the MPMR content then lock it */ + caam_hal_ctrl_fill_mpmr(ctrl_addr, &msg_mpmr); + + mp_privdata.mp_status = CAAM_NO_ERROR; + + return CAAM_NO_ERROR; +} + +enum caam_status caam_mp_resume(uint32_t pm_hint) +{ + if (pm_hint == PM_HINT_CONTEXT_STATE) + return caam_mp_init(mp_privdata.ctrl_addr); + + return CAAM_NO_ERROR; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/mp/sub.mk b/optee/optee_os/core/drivers/crypto/caam/mp/sub.mk new file mode 100644 index 0000000..1aa9326 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/mp/sub.mk @@ -0,0 +1,3 @@ +incdirs-y += ../include + +srcs-y += caam_mp.c diff --git a/optee/optee_os/core/drivers/crypto/caam/sub.mk b/optee/optee_os/core/drivers/crypto/caam/sub.mk new file mode 100644 index 0000000..77229dd --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/sub.mk @@ -0,0 +1,15 @@ +incdirs-y += include + +subdirs-y += hal +subdirs-y += utils + +srcs-y += caam_pwr.c +srcs-y += caam_ctrl.c +srcs-y += caam_jr.c +srcs-y += caam_rng.c +srcs-y += caam_desc.c +subdirs-$(call cfg-one-enabled, CFG_NXP_CAAM_HASH_DRV CFG_NXP_CAAM_HMAC_DRV) += hash +subdirs-$(call cfg-one-enabled, CFG_NXP_CAAM_CIPHER_DRV CFG_NXP_CAAM_CMAC_DRV) += cipher +subdirs-y += acipher +subdirs-$(CFG_NXP_CAAM_BLOB_DRV) += blob +subdirs-$(CFG_NXP_CAAM_MP_DRV) += mp diff --git a/optee/optee_os/core/drivers/crypto/caam/utils/sub.mk b/optee/optee_os/core/drivers/crypto/caam/utils/sub.mk new file mode 100644 index 0000000..f69195b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/sub.mk @@ -0,0 +1,9 @@ +incdirs-y += ../include + +srcs-y += utils_mem.c +srcs-y += utils_delay.c +srcs-y += utils_sgt.c +srcs-$(CFG_NXP_CAAM_SGT_V1) += utils_sgt_v1.c +srcs-$(CFG_NXP_CAAM_SGT_V2) += utils_sgt_v2.c +srcs-y += utils_status.c +srcs-y += utils_dmaobj.c diff --git a/optee/optee_os/core/drivers/crypto/caam/utils/utils_delay.c b/optee/optee_os/core/drivers/crypto/caam/utils/utils_delay.c new file mode 100644 index 0000000..84be5c8 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/utils_delay.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018 NXP + * + * Brief Delay management utilities. + * Primitive to delay a delay. + */ +#include +#include + +void caam_udelay(uint32_t time) +{ + uint32_t counter = time * 500; + + /* Implementation of a Software loop assuming CPU clock of 500MHz */ + while (counter--) { + isb(); + dsb(); + }; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c b/optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c new file mode 100644 index 0000000..04f9122 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/utils_dmaobj.c @@ -0,0 +1,1411 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2021 NXP + * + * CAAM DMA data object utilities. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_DMA_OVERFLOW(addr) ((addr) > UINT32_MAX) +#define MAX_BUFFER_ALLOC_SIZE ((size_t)(8 * 1024)) + +/* + * Local defines used to identify Object type as: + * - input or output data + * - SGT object created because buffer is not physical contiguous + * - derived object (not buffer reallocation) + * - allocated origin buffer + */ +#define DMAOBJ_INPUT BIT(0) +#define DMAOBJ_OUTPUT BIT(1) +#define DMAOBJ_ALLOC_ORIG BIT(2) +#define DMAOBJ_DONT_COPY BIT(3) + +/* + * DMA Buffer + * + * @require DMA Buffer size require + * @allocated Size of the buffer allocated + * @remind Size available in the buffer + * @buf CAAM Buffer + */ +struct caamdmabuf { + size_t require; + size_t allocated; + size_t remind; + struct caambuf buf; +}; + +/* + * DMA Object buffer entry + * + * @newbuf True if list entry is a new DMA Buffer + * @nodma_access Buffer is not accessible from CAAM DMA + * @nocopy Buffer doesn't have to be copied back to the origin + * @origbuf Original buffer reference + * @link Pointer to next entry + */ +struct dmaentry { + bool newbuf; + bool nodma_access; + bool nocopy; + + struct caambuf origbuf; + + TAILQ_ENTRY(dmaentry) link; +}; + +/* + * SGT/Buffer Data currently handled + * + * @orig Original buffer reference + * @dma DMA Buffer (new or original) + * @length Buffer length + */ +struct sgtdata { + uint8_t *orig; + uint8_t *dma; + size_t length; +}; + +/* + * CAAM DMA private Object data + * @type Type of DMA Object + * @nb_sgtbuf Number of SGT/Buffer entries allocated + * @dmabuf DMA Buffer allocated + * @sgtdata Reference to SGT/Buffer list in used + * @list List of the DMA Object buffer entry + */ +struct priv_dmaobj { + unsigned int type; + unsigned int nb_sgtbuf; + + struct caamdmabuf dmabuf; + struct sgtdata *sgtdata; + + TAILQ_HEAD(dmalist, dmaentry) list; +}; + +/* + * Memory allocation and free spinlock to ensure that in case + * of big buffer reallocation, memory used is freed + */ +static unsigned int memlock; + +/* + * Try to allocate a DMA Buffer of type input or output data of @size bytes. + * If allocation success, set the DMA Buffer settings, else + * return in error. + * + * @priv CAAM DMA object private data + * @size Size of the DMA Buffer to allocate + */ +static TEE_Result try_allocate_dmabuf(struct priv_dmaobj *priv, size_t size) +{ + enum caam_status retstatus = CAAM_FAILURE; + + if (priv->dmabuf.allocated) { + caam_free_buf(&priv->dmabuf.buf); + priv->dmabuf.allocated = 0; + } + + if (priv->type & DMAOBJ_INPUT) + retstatus = caam_alloc_buf(&priv->dmabuf.buf, size); + else + retstatus = caam_alloc_align_buf(&priv->dmabuf.buf, size); + + DMAOBJ_TRACE("Alloc %s DMA buffer (%zu) ret 0x%" PRIx32, + (priv->type & DMAOBJ_INPUT) ? "Input" : "Output", size, + retstatus); + + if (retstatus == CAAM_NO_ERROR) { + DMAOBJ_TRACE("DMA buffer Allocation Success"); + /* Set the Object's DMA Buffer settings */ + priv->dmabuf.allocated = size; + priv->dmabuf.remind = size; + priv->dmabuf.buf.length = 0; + return TEE_SUCCESS; + } + + DMAOBJ_TRACE("DMA buffer Allocation Failure"); + return TEE_ERROR_OUT_OF_MEMORY; +} + +/* + * Allocate and initialize the CAAM DMA object's private data. + * + * @obj CAAM DMA Object + * @type Type of the CAAM DMA Object (i.e. Input or Output) + */ +static TEE_Result allocate_private(struct caamdmaobj *obj, unsigned int type) +{ + struct priv_dmaobj *priv = NULL; + + priv = caam_calloc(sizeof(*priv)); + if (!priv) + return TEE_ERROR_OUT_OF_MEMORY; + + obj->priv = priv; + + /* Set the object type as input */ + priv->type = type; + + TAILQ_INIT(&priv->list); + + return TEE_SUCCESS; +} + +/* + * Fill the @sgtdata object to record the current input/output data + * handled in the DMA SGT/Buffer object. + * Increment the SGT/Buffer length according + * + * @obj CAAM DMA object + * @sgtdata [out] SGT Data handled + * @entry DMA Object buffer entry + * @dma DMA SGT/Buffer object + * @offset Start offset of the DMA Object buffer + */ +static void add_sgtdata_entry(struct caamdmaobj *obj, struct sgtdata *sgtdata, + struct dmaentry *entry, struct caambuf *dma, + size_t offset) +{ + if (entry->nocopy) { + sgtdata->orig = 0; + sgtdata->length = 0; + sgtdata->dma = 0; + } else { + sgtdata->orig = entry->origbuf.data + offset; + sgtdata->length = dma->length; + sgtdata->dma = dma->data; + } + + obj->sgtbuf.length += dma->length; +} + +/* + * Add a new DMA Buffer entry as first element of the list. + * Return NULL if error, else the new entry in the list + * + * @priv DMA Object private data + * @orig Original buffer reference + */ +static struct dmaentry *dmalist_add_entry_head(struct priv_dmaobj *priv, + struct caambuf *orig) +{ + struct dmaentry *entry = NULL; + + entry = caam_calloc(sizeof(*entry)); + if (entry) { + /* Save the original buffer reference */ + memcpy(&entry->origbuf, orig, sizeof(entry->origbuf)); + DMAOBJ_TRACE("entry %p - insert head entry of %zu bytes", entry, + orig->length); + TAILQ_INSERT_HEAD(&priv->list, entry, link); + } + + return entry; +} + +/* + * Add a new DMA Buffer entry in the list. + * Return NULL if error, else the new entry in the list + * + * @priv DMA Object private data + * @orig Original buffer reference + */ +static struct dmaentry *dmalist_add_entry(struct priv_dmaobj *priv, + struct caambuf *orig) +{ + struct dmaentry *entry = NULL; + + entry = caam_calloc(sizeof(*entry)); + if (entry) { + /* Save the original buffer reference */ + memcpy(&entry->origbuf, orig, sizeof(entry->origbuf)); + DMAOBJ_TRACE("entry %p - insert entry of %zu bytes", entry, + orig->length); + if (TAILQ_EMPTY(&priv->list)) + TAILQ_INSERT_HEAD(&priv->list, entry, link); + else + TAILQ_INSERT_TAIL(&priv->list, entry, link); + } + + return entry; +} + +/* + * Insert and allocate a DMA entry in the list before the given DMA entry. + * Return the allocated DMA entry. + * + * @priv DMA Object private data + * @before DMA entry after the new DMA entry + * @new CAAM buffer of the new DMA entry + */ +static struct dmaentry *dmalist_insert_before_entry(struct priv_dmaobj *priv, + struct dmaentry *before, + struct caambuf *new) +{ + struct dmaentry *entry = NULL; + + entry = caam_calloc(sizeof(*entry)); + if (entry) { + /* Save the original buffer reference */ + memcpy(&entry->origbuf, new, sizeof(entry->origbuf)); + DMAOBJ_TRACE("entry %p - insert entry of %zu bytes", entry, + new->length); + if (TAILQ_FIRST(&priv->list) == before) + TAILQ_INSERT_HEAD(&priv->list, entry, link); + else + TAILQ_INSERT_BEFORE(before, entry, link); + } + + return entry; +} + +/* + * Insert and allocate a DMA entry in the list after the given DMA entry. + * Return the allocated DMA entry. + * + * @priv DMA Object private data + * @after DMA entry before the new DMA entry + * @new CAAM buffer of the new DMA entry + */ +static struct dmaentry *dmalist_insert_after_entry(struct priv_dmaobj *priv, + struct dmaentry *after, + struct caambuf *new) +{ + struct dmaentry *entry = NULL; + + entry = caam_calloc(sizeof(*entry)); + if (entry) { + /* Save the original buffer reference */ + memcpy(&entry->origbuf, new, sizeof(entry->origbuf)); + DMAOBJ_TRACE("entry %p - insert entry of %zu bytes", entry, + new->length); + TAILQ_INSERT_AFTER(&priv->list, after, entry, link); + } + + return entry; +} + +/* + * Apply the cache operation @op to the DMA Object (SGT or buffer) + * + * @op Cache operation + * @obj CAAM DMA object + */ +static inline void dmaobj_cache_operation(enum utee_cache_operation op, + struct caamdmaobj *obj) +{ + if (!obj->sgtbuf.length) + return; + + if (obj->sgtbuf.sgt_type) + caam_sgt_cache_op(op, &obj->sgtbuf, obj->sgtbuf.length); + else if (!obj->sgtbuf.buf->nocache) + cache_operation(op, obj->sgtbuf.buf->data, obj->sgtbuf.length); +} + +/* + * Set the required allocation size for the DMA buffer. + * + * @priv DMA Object private data + * @length Required buffer size + */ +static inline void add_dma_require(struct priv_dmaobj *priv, size_t length) +{ + size_t tmp = 0; + + if (ADD_OVERFLOW(priv->dmabuf.require, length, &tmp)) + priv->dmabuf.require = SIZE_MAX; + else + priv->dmabuf.require = tmp; +} + +/* + * Check if the buffer start/end addresses are aligned on the cache line. + * If not flags as start and/or end addresses not aligned, expect if the + * maximum length @maxlen to use is inside a cache line size. In this case, + * flags to allocate a new buffer. + * + * @priv DMA Object private data + * @maxlen Maximum length to use + */ +static TEE_Result check_buffer_alignment(struct priv_dmaobj *priv, + size_t maxlen) +{ + unsigned int cacheline_size = 0; + struct dmaentry *entry = NULL; + struct dmaentry *new_entry = NULL; + struct caambuf newbuf = {}; + vaddr_t va_start = 0; + vaddr_t va_end = 0; + vaddr_t va_end_align = 0; + vaddr_t va_start_align = 0; + size_t remlen = 0; + size_t acclen = 0; + + cacheline_size = dcache_get_line_size(); + + TAILQ_FOREACH(entry, &priv->list, link) { + DMAOBJ_TRACE("Entry %p: start %p len %zu (%zu >= %zu)", entry, + entry->origbuf.data, entry->origbuf.length, acclen, + maxlen); + + /* No need to continue if we convert the needed length */ + if (acclen >= maxlen) + return TEE_SUCCESS; + + acclen += entry->origbuf.length; + + if (entry->nodma_access || entry->newbuf) + continue; + + if (entry->origbuf.length < cacheline_size) { + /* + * Length of the entry is not aligned on cache size + * Require a full aligned buffer + */ + DMAOBJ_TRACE("Length %zu vs cache line %u", + entry->origbuf.length, cacheline_size); + + entry->newbuf = true; + add_dma_require(priv, entry->origbuf.length); + continue; + } + + va_start = (vaddr_t)entry->origbuf.data; + va_start_align = ROUNDUP(va_start, cacheline_size); + + if (va_start_align != va_start) { + DMAOBJ_TRACE("Start 0x%" PRIxVA " vs align 0x%" PRIxVA, + va_start, va_start_align); + + remlen = entry->origbuf.length - + (va_start_align - va_start); + if (remlen <= cacheline_size) { + /* + * Start address is not aligned and the + * remaining length if after re-alignment + * is not cache size aligned. + * Require a full aligned buffer + */ + DMAOBJ_TRACE("Rem length %zu vs cache line %u", + remlen, cacheline_size); + entry->newbuf = true; + add_dma_require(priv, entry->origbuf.length); + continue; + } + + /* + * Insert a new entry to make buffer on a cache line. + */ + newbuf.data = entry->origbuf.data; + newbuf.length = va_start_align - va_start; + newbuf.paddr = entry->origbuf.paddr; + newbuf.nocache = entry->origbuf.nocache; + + add_dma_require(priv, newbuf.length); + new_entry = dmalist_insert_before_entry(priv, entry, + &newbuf); + if (!new_entry) + return TEE_ERROR_OUT_OF_MEMORY; + + new_entry->newbuf = true; + + /* + * Update current entry with align address and new + * length. + */ + entry->origbuf.data = (uint8_t *)va_start_align; + entry->origbuf.length -= newbuf.length; + entry->origbuf.paddr += newbuf.length; + + /* + * Set current entry to new entry to continue + * the FOREACH loop from this new_entry and then + * verify the rest of the entry modified. + */ + entry = new_entry; + acclen -= entry->origbuf.length; + continue; + } + + va_end = (vaddr_t)entry->origbuf.data + entry->origbuf.length; + va_end_align = ROUNDUP(va_end, cacheline_size); + + if (va_end != va_end_align) { + DMAOBJ_TRACE("End 0x%" PRIxVA " vs align 0x%" PRIxVA, + va_end, va_end_align); + + va_end_align = ROUNDDOWN(va_end, cacheline_size); + remlen = entry->origbuf.length - va_end_align; + + if (remlen <= cacheline_size) { + /* + * End address is not aligned and the remaining + * length if after re-alignment is not cache + * size aligned. + * Require a full aligned buffer + */ + DMAOBJ_TRACE("Rem length %zu vs cache line %u", + remlen, cacheline_size); + entry->newbuf = true; + add_dma_require(priv, entry->origbuf.length); + continue; + } + + /* + * Insert a new entry to make buffer on a cache line. + */ + newbuf.data = (uint8_t *)va_end_align; + newbuf.length = va_end - va_end_align; + newbuf.paddr = entry->origbuf.paddr + newbuf.length; + newbuf.nocache = entry->origbuf.nocache; + + add_dma_require(priv, newbuf.length); + + new_entry = dmalist_insert_after_entry(priv, entry, + &newbuf); + if (!new_entry) + return TEE_ERROR_OUT_OF_MEMORY; + + new_entry->newbuf = true; + + /* Update current entry with new length */ + entry->origbuf.length -= newbuf.length; + + /* + * Set current entry to new entry to continue + * the FOREACH loop from this new_entry and then + * verify the rest of the entry modified. + */ + entry = new_entry; + acclen -= newbuf.length; + continue; + } + } + + return TEE_SUCCESS; +} + +/* + * Go through all the @orig space to extract all physical area used to + * map the buffer. + * If one of the physical area is not accessible by the CAAM DMA, flag it + * to be reallocated with DMA accessible buffer. + * If the DMA Object is an output buffer, check and flag the start/end + * address of the buffer to be aligned on a cache line. + * + * @obj CAAM DMA object + * @orig Original Data + * @maxlen Maximum length to use + */ +static TEE_Result check_buffer_boundary(struct caamdmaobj *obj, + struct caambuf *orig, size_t maxlen) +{ + TEE_Result ret = TEE_ERROR_OUT_OF_MEMORY; + struct priv_dmaobj *priv = obj->priv; + struct dmaentry *entry = NULL; + struct caambuf *pabufs = NULL; + int nb_pa_area = -1; + int idx = 0; + paddr_t last_pa = 0; + size_t remlen = maxlen; + size_t tmp = 0; + + /* + * Get the number of physical areas used by the + * DMA Buffer + */ + nb_pa_area = caam_mem_get_pa_area(orig, &pabufs); + DMAOBJ_TRACE("Number of pa areas = %d (for max length %zu bytes)", + nb_pa_area, remlen); + if (nb_pa_area == -1) + goto out; + + for (idx = 0; idx < nb_pa_area && remlen; idx++) { + DMAOBJ_TRACE("Remaining length = %zu", remlen); + if (ADD_OVERFLOW(pabufs[idx].paddr, pabufs[idx].length, + &last_pa)) + goto out; + + DMAOBJ_TRACE("PA 0x%" PRIxPA " = 0x%" PRIxPA " + %zu", last_pa, + pabufs[idx].paddr, pabufs[idx].length); + + entry = dmalist_add_entry(priv, &pabufs[idx]); + if (!entry) + goto out; + + if (IS_DMA_OVERFLOW(last_pa)) { + entry->nodma_access = true; + if (ADD_OVERFLOW(priv->dmabuf.require, + pabufs[idx].length, &tmp)) + priv->dmabuf.require = SIZE_MAX; + else + priv->dmabuf.require = tmp; + } + + if (remlen > pabufs[idx].length) + remlen -= pabufs[idx].length; + else + remlen = 0; + } + + /* + * Check the buffer alignment if the buffer is cacheable and + * an output buffer. + */ + if (priv->type & DMAOBJ_OUTPUT && !orig->nocache) { + ret = check_buffer_alignment(priv, maxlen); + if (ret) + goto out; + } + + orig->length = maxlen; + + ret = TEE_SUCCESS; +out: + caam_free(pabufs); + return ret; +} + +/* + * Re-map a DMA entry into a CAAM DMA accessible buffer. + * Create the SGT/Buffer entry to be used in the CAAM Descriptor + * Record this entry in the SGT/Buffer Data to get information on current + * working data. + * + * @obj CAAM DMA object + * @entry DMA entry to re-map + * @index Index in the SGT/Buffer table + * @off Start offset of the DMA entry data + */ +static enum caam_status entry_sgtbuf_dmabuf(struct caamdmaobj *obj, + struct dmaentry *entry, + unsigned int index, size_t off) +{ + struct priv_dmaobj *priv = obj->priv; + struct caambuf *sgtbuf = &obj->sgtbuf.buf[index]; + struct caamdmabuf *dmabuf = &priv->dmabuf; + + if (!priv->dmabuf.allocated) + return CAAM_OUT_MEMORY; + + sgtbuf->data = dmabuf->buf.data + dmabuf->buf.length; + sgtbuf->length = MIN(dmabuf->remind, entry->origbuf.length - off); + sgtbuf->paddr = dmabuf->buf.paddr + dmabuf->buf.length; + sgtbuf->nocache = dmabuf->buf.nocache; + dmabuf->remind -= sgtbuf->length; + dmabuf->buf.length += sgtbuf->length; + + if (priv->type & DMAOBJ_INPUT) + memcpy(sgtbuf->data, &entry->origbuf.data[off], sgtbuf->length); + else + entry->newbuf = true; + + add_sgtdata_entry(obj, &priv->sgtdata[index], entry, sgtbuf, off); + + return CAAM_NO_ERROR; +} + +/* + * Create the SGT/Buffer entry mapping the DMA @entry. + * Record these entry in the SGT/buffer Data to get information on current + * working data. + * + * @obj CAAM DMA object + * @entry DMA entry to re-map + * @index Index in the SGT/Buffer table + * @off Start offset of the DMA entry data + */ +static enum caam_status entry_sgtbuf(struct caamdmaobj *obj, + struct dmaentry *entry, unsigned int index, + size_t off) +{ + struct priv_dmaobj *priv = obj->priv; + struct caambuf *sgtbuf = &obj->sgtbuf.buf[index]; + struct sgtdata *sgtdata = &priv->sgtdata[index]; + + memcpy(sgtbuf, &entry->origbuf, sizeof(*sgtbuf)); + sgtbuf->data += off; + sgtbuf->paddr += off; + sgtbuf->length -= off; + + DMAOBJ_TRACE("DMA buffer %p - %zu", sgtbuf->data, sgtbuf->length); + add_sgtdata_entry(obj, sgtdata, entry, sgtbuf, off); + + return CAAM_NO_ERROR; +} + +TEE_Result caam_dmaobj_init_input(struct caamdmaobj *obj, const void *data, + size_t length) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + DMAOBJ_TRACE("Input object with data @%p of %zu bytes", data, length); + + if (!data || !length || !obj) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + obj->orig.paddr = virt_to_phys((void *)data); + if (!obj->orig.paddr) { + DMAOBJ_TRACE("Object virtual address error"); + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + obj->orig.data = (void *)data; + obj->orig.length = length; + if (!caam_mem_is_cached_buf((void *)data, length)) + obj->orig.nocache = 1; + + ret = allocate_private(obj, DMAOBJ_INPUT); + if (!ret) + ret = check_buffer_boundary(obj, &obj->orig, obj->orig.length); + +out: + DMAOBJ_TRACE("Object returns 0x%" PRIx32, ret); + return ret; +} + +TEE_Result caam_dmaobj_input_sgtbuf(struct caamdmaobj *obj, const void *data, + size_t length) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t size_done = length; + + ret = caam_dmaobj_init_input(obj, data, length); + if (ret) + return ret; + + ret = caam_dmaobj_prepare(obj, NULL, length); + if (ret) + return ret; + + ret = caam_dmaobj_sgtbuf_build(obj, &size_done, 0, length); + if (ret) + return ret; + + if (size_done != length) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} + +TEE_Result caam_dmaobj_init_output(struct caamdmaobj *obj, void *data, + size_t length, size_t min_length) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct dmaentry *entry = NULL; + struct caambuf newbuf = {}; + + DMAOBJ_TRACE("Output object with data @%p of %zu bytes (%zu)", data, + length, min_length); + + if (!obj) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + ret = allocate_private(obj, DMAOBJ_OUTPUT); + if (ret) + goto out; + + if (data) { + obj->orig.paddr = virt_to_phys((void *)data); + if (!obj->orig.paddr) { + DMAOBJ_TRACE("Object virtual address error"); + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + obj->orig.data = (void *)data; + obj->orig.length = length; + if (!caam_mem_is_cached_buf((void *)data, length)) + obj->orig.nocache = 1; + + ret = check_buffer_boundary(obj, &obj->orig, + MIN(min_length, obj->orig.length)); + if (ret) + goto out; + } + + if (length < min_length || !data) { + DMAOBJ_TRACE("Output buffer too short need %zu bytes (+%zu)", + min_length, min_length - length); + newbuf.length = min_length - length; + + entry = dmalist_add_entry(obj->priv, &newbuf); + if (!entry) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Add the additional size in the DMA buffer length */ + add_dma_require(obj->priv, newbuf.length); + + entry->nocopy = true; + entry->newbuf = true; + } + + ret = TEE_SUCCESS; + +out: + DMAOBJ_TRACE("Object returns 0x%" PRIx32, ret); + return ret; +} + +TEE_Result caam_dmaobj_output_sgtbuf(struct caamdmaobj *obj, void *data, + size_t length, size_t min_length) +{ + enum caam_status retstatus = CAAM_FAILURE; + TEE_Result ret = TEE_ERROR_GENERIC; + struct priv_dmaobj *priv = NULL; + size_t size = 0; + struct caambuf buf = {}; + + if (!data && !length && min_length) { + /* + * We are sure that the minimum size of the allocated + * buffer is a cache line, hence we know that + * start/end address are cache aligned. + * If the @min_length is less than a cache line size, we + * can initializing the output buffer with the cache line size + * to prevent end buffer misalignement so reallocate a not used + * buffer. + */ + size = MAX(min_length, dcache_get_line_size()); + + /* Allocate a new cache aligned buffer */ + retstatus = caam_alloc_align_buf(&buf, size); + DMAOBJ_TRACE("New output buffer of %zu bytes ret 0x%" PRIx32, + min_length, retstatus); + if (retstatus != CAAM_NO_ERROR) + return caam_status_to_tee_result(retstatus); + + ret = caam_dmaobj_init_output(obj, buf.data, buf.length, size); + if (ret) + return ret; + + /* Set the correct origin buffer length asked */ + obj->orig.length = min_length; + + /* Flag origin buffer as new allocation to free it */ + priv = obj->priv; + priv->type |= DMAOBJ_ALLOC_ORIG; + } else { + ret = caam_dmaobj_init_output(obj, data, length, min_length); + if (ret) + return ret; + } + + ret = caam_dmaobj_prepare(NULL, obj, min_length); + if (ret) + return ret; + + size = min_length; + ret = caam_dmaobj_sgtbuf_build(obj, &size, 0, min_length); + if (ret) + return ret; + + if (size != min_length) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} + +void caam_dmaobj_cache_push(struct caamdmaobj *obj) +{ + struct priv_dmaobj *priv = NULL; + enum utee_cache_operation op = TEE_CACHECLEAN; + + if (!obj || !obj->priv) + return; + + priv = obj->priv; + if (priv->type & DMAOBJ_OUTPUT) + op = TEE_CACHEFLUSH; + + dmaobj_cache_operation(op, obj); +} + +size_t caam_dmaobj_copy_to_orig(struct caamdmaobj *obj) +{ + struct priv_dmaobj *priv = NULL; + unsigned int idx = 0; + size_t length = 0; + size_t dst_rlen = 0; + size_t copy_size = 0; + + if (!obj || !obj->orig.data || !obj->priv) + return 0; + + dmaobj_cache_operation(TEE_CACHEINVALIDATE, obj); + + priv = obj->priv; + + /* + * The maximum data size to copy cannot exceed the output buffer size + * (obj->orig.length) and cannot exceed the data processed by the + * CAAM (obj->sgtbuf.length). + */ + dst_rlen = MIN(obj->orig.length, obj->sgtbuf.length); + + DMAOBJ_TRACE("Copy (len=%zu)", dst_rlen); + + for (idx = 0; idx < obj->sgtbuf.number; idx++) { + struct sgtdata *sgtdata = &priv->sgtdata[idx]; + + if (!sgtdata) + break; + + copy_size = MIN(dst_rlen, sgtdata->length); + if (sgtdata->orig != sgtdata->dma && sgtdata->orig) { + copy_size = MIN(dst_rlen, sgtdata->length); + memcpy(sgtdata->orig, sgtdata->dma, copy_size); + } + + length += copy_size; + dst_rlen -= copy_size; + } + + return length; +} + +size_t caam_dmaobj_copy_ltrim_to_orig(struct caamdmaobj *obj) +{ + struct priv_dmaobj *priv = NULL; + uint8_t *dst = NULL; + size_t off = 0; + size_t offset = 0; + size_t dst_rlen = 0; + size_t copy_size = 0; + unsigned int idx = 0; + size_t length = 0; + + if (!obj || !obj->orig.data || !obj->priv) + return 0; + + dmaobj_cache_operation(TEE_CACHEINVALIDATE, obj); + + priv = obj->priv; + + /* Parse the SGT data list to discard leading zeros */ + for (idx = 0; idx < obj->sgtbuf.number; idx++) { + struct sgtdata *sgtdata = priv->sgtdata + idx; + + if (!sgtdata) + break; + + if (!sgtdata->orig) + continue; + + for (offset = 0; offset < sgtdata->length; off++, offset++) { + if (sgtdata->dma[offset]) + goto do_copy; + } + } + +do_copy: + if (off < obj->orig.length) + dst_rlen = obj->orig.length - off; + + dst = obj->orig.data; + + DMAOBJ_TRACE("Copy/Move Offset=%zu (len=%zu) TYPE=%d", off, dst_rlen, + obj->sgtbuf.sgt_type); + + if (!dst_rlen) { + dst[0] = 0; + return 1; + } + + /* + * After discarding leading zeros in the SGT data list, start the copy + * operation on the remaining elements of the data list. + * List index must not be re-initialized before entering this loop. + */ + for (; idx < obj->sgtbuf.number; idx++) { + struct sgtdata *sgtdata = &priv->sgtdata[idx]; + + if (!sgtdata) + break; + + if (!sgtdata->orig) + continue; + + if (offset) { + copy_size = MIN(dst_rlen, sgtdata->length - offset); + memmove(dst, &sgtdata->dma[offset], copy_size); + offset = 0; + } else { + copy_size = MIN(dst_rlen, sgtdata->length); + if (dst != sgtdata->dma) + memmove(dst, sgtdata->dma, copy_size); + } + + dst += copy_size; + dst_rlen -= copy_size; + length += copy_size; + } + + return length; +} + +void caam_dmaobj_free(struct caamdmaobj *obj) +{ + struct priv_dmaobj *priv = NULL; + struct dmaentry *entry = NULL; + struct dmaentry *next = NULL; + uint32_t exceptions = 0; + + if (!obj) + return; + + exceptions = cpu_spin_lock_xsave(&memlock); + priv = obj->priv; + if (!priv) + goto out; + + DMAOBJ_TRACE("Free %s object with data @%p of %zu bytes", + priv->type & DMAOBJ_INPUT ? "Input" : "Output", + obj->orig.data, obj->orig.length); + + TAILQ_FOREACH_SAFE(entry, &priv->list, link, next) { + DMAOBJ_TRACE("Is type 0x%" PRIx8 " newbuf %s", priv->type, + entry->newbuf ? "true" : "false"); + + DMAOBJ_TRACE("Free entry %p", entry); + caam_free(entry); + } + + if (priv->nb_sgtbuf) { + DMAOBJ_TRACE("Free #%d SGT data %p", priv->nb_sgtbuf, + priv->sgtdata); + caam_free(priv->sgtdata); + + obj->sgtbuf.number = priv->nb_sgtbuf; + obj->sgtbuf.sgt_type = (priv->nb_sgtbuf > 1) ? true : false; + } + + if (priv->dmabuf.allocated) { + DMAOBJ_TRACE("Free CAAM DMA buffer"); + caam_free_buf(&priv->dmabuf.buf); + } + + if (priv->type & DMAOBJ_ALLOC_ORIG) { + DMAOBJ_TRACE("Free Allocated origin"); + caam_free_buf(&obj->orig); + } + + DMAOBJ_TRACE("Free private object %p", priv); + caam_free(priv); + +out: + if (obj->sgtbuf.number) { + DMAOBJ_TRACE("Free #%d SGT/Buffer %p", obj->sgtbuf.number, + &obj->sgtbuf); + caam_sgtbuf_free(&obj->sgtbuf); + } + + memset(obj, 0, sizeof(*obj)); + + cpu_spin_unlock_xrestore(&memlock, exceptions); +} + +TEE_Result caam_dmaobj_add_first_block(struct caamdmaobj *obj, + struct caamblock *block) +{ + struct priv_dmaobj *priv = NULL; + struct caambuf newbuf = {}; + struct dmaentry *entry = NULL; + + if (!obj || !obj->priv || !block) + return TEE_ERROR_BAD_PARAMETERS; + + priv = obj->priv; + + /* Save the block buffer reference and insert it at the head list */ + newbuf.data = block->buf.data; + newbuf.length = block->filled; + newbuf.paddr = block->buf.paddr; + newbuf.nocache = block->buf.nocache; + + entry = dmalist_add_entry_head(priv, &newbuf); + + if (!entry) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * Block buffer added in the output DMA buffer doesn't have to + * be part of the output copy to origin buffer. + */ + if (priv->type & DMAOBJ_OUTPUT) + entry->nocopy = true; + + return TEE_SUCCESS; +} + +TEE_Result caam_dmaobj_derive_sgtbuf(struct caamdmaobj *obj, + const struct caamdmaobj *from, + size_t offset, size_t length) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct priv_dmaobj *priv = NULL; + + DMAOBJ_TRACE("Derive object %p - offset %zu - length %zu bytes", from, + offset, length); + + if (!obj || !from || !length || !from->priv) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (!from->orig.data || !from->orig.length) { + DMAOBJ_TRACE("No data/length to derive from"); + ret = TEE_ERROR_NO_DATA; + goto out; + } + + priv = from->priv; + if (!priv->nb_sgtbuf) { + DMAOBJ_TRACE("From SGT/Buffer not prepared"); + ret = TEE_ERROR_NO_DATA; + goto out; + } + + retstatus = caam_sgt_derive(&obj->sgtbuf, &from->sgtbuf, offset, + length); + + ret = caam_status_to_tee_result(retstatus); + +out: + DMAOBJ_TRACE("Object returns 0x%" PRIx32, ret); + return ret; +} + +/* + * Get the maximum allocation size for the given CAAM DMA object. + * Return the maximum allocation size. + * + * @obj CAAM DMA object + */ +static size_t get_dma_max_alloc_size(struct caamdmaobj *obj) +{ + size_t alloc_size = 0; + struct priv_dmaobj *priv = NULL; + + if (!obj) + return 0; + + priv = obj->priv; + + DMAOBJ_TRACE("DMA buffer size require %zu", priv->dmabuf.require); + alloc_size = MIN(priv->dmabuf.require, MAX_BUFFER_ALLOC_SIZE); + if (alloc_size > 1024) + alloc_size = ROUNDDOWN(alloc_size, 1024); + + return alloc_size; +} + +/* + * Allocate the CAAM DMA buffer. + * First, try to allocate the with the maximum size. If it fails, try to + * allocate with the same size divided by two. Try to allocate until + * minimum size is reached. If the allocation cannot be done with the + * minimum size, return TEE_ERROR_OUT_OF_MEMORY, TEE_SUCCESS otherwise. + * + * @obj CAAM DMA object + * @min_size minimum size allocation + * @size[out] successful allocation size + */ +static TEE_Result try_allocate_dmabuf_max_size(struct caamdmaobj *obj, + size_t min_size, + size_t *size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t alloc_size = 0; + struct priv_dmaobj *priv = NULL; + bool try_alloc = false; + uint32_t exceptions = 0; + + alloc_size = get_dma_max_alloc_size(obj); + if (alloc_size) { + try_alloc = true; + } else { + ret = TEE_SUCCESS; + goto out; + } + + priv = obj->priv; + + exceptions = cpu_spin_lock_xsave(&memlock); + + while (try_alloc) { + ret = try_allocate_dmabuf(priv, alloc_size); + if (!ret) { + try_alloc = false; + } else { + if (alloc_size > min_size) + alloc_size = MAX(min_size, alloc_size / 2); + else + try_alloc = false; + } + } + + cpu_spin_unlock_xrestore(&memlock, exceptions); + +out: + *size = alloc_size; + + return ret; +} + +TEE_Result caam_dmaobj_prepare(struct caamdmaobj *input, + struct caamdmaobj *output, size_t min_size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t alloc_input = 0; + size_t alloc_output = 0; + + if (!input && !output) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((input && !input->priv) || (output && !output->priv)) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + DMAOBJ_TRACE("input=%p - output=%p - min=%zu", input, output, min_size); + + ret = try_allocate_dmabuf_max_size(input, min_size, &alloc_input); + if (ret) + goto out; + + ret = try_allocate_dmabuf_max_size(output, min_size, &alloc_output); + if (ret) + goto out; + +out: + DMAOBJ_TRACE("Allocation (input %zu, output %zu) returns 0x%" PRIx32, + input ? alloc_input : 0, output ? alloc_output : 0, + ret); + + return ret; +} + +TEE_Result caam_dmaobj_sgtbuf_inout_build(struct caamdmaobj *input, + struct caamdmaobj *output, + size_t *length, size_t off, + size_t align) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t len = 0; + + DMAOBJ_TRACE("input=%p/output=%p %zu bytes (offset=%zu, align=%zu)", + input, output, *length, off, align); + + if (!input || !output || !length || !input->priv || !output->priv || + !*length) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * First build the input SGT/Buffer + */ + ret = caam_dmaobj_sgtbuf_build(input, length, off, align); + if (ret) + goto out; + + /* + * Next build the output SGT/Buffer. + * If returned length is not same as input, redo the input + * SGT/Buffer with the same length as the output. + */ + len = *length; + ret = caam_dmaobj_sgtbuf_build(output, &len, off, *length); + if (ret) + goto out; + + if (len != *length) { + DMAOBJ_TRACE("Retry In %zu bytes vs Out %zu bytes", *length, + len); + + /* Redo the input with the output length */ + *length = len; + ret = caam_dmaobj_sgtbuf_build(input, length, off, len); + if (!ret && *length != len) { + DMAOBJ_TRACE("Error In %zu bytes vs Out %zu bytes", + *length, len); + ret = TEE_ERROR_OUT_OF_MEMORY; + } + } + +out: + DMAOBJ_TRACE("Input/Output SGTBUF returns 0x%" PRIx32, ret); + + return ret; +} + +TEE_Result caam_dmaobj_sgtbuf_build(struct caamdmaobj *obj, size_t *length, + size_t off, size_t align) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + enum caam_status retstatus = CAAM_FAILURE; + struct priv_dmaobj *priv = NULL; + struct dmaentry *entry = NULL; + struct dmaentry *start_entry = NULL; + size_t max_length = 0; + size_t acc_length = 0; + size_t offset = off; + unsigned int idx = 0; + unsigned int nb_sgt = 0; + + DMAOBJ_TRACE("obj=%p of %zu bytes (offset=%zu) - align %zu", obj, + *length, off, align); + + if (!obj || !obj->priv || !length || !*length) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + priv = obj->priv; + + max_length = *length; + if (priv->dmabuf.allocated && max_length > priv->dmabuf.allocated && + priv->dmabuf.allocated > align) + max_length = ROUNDDOWN(priv->dmabuf.allocated, align); + + DMAOBJ_TRACE("Prepare SGT/Buffer to do %zu of %zu", max_length, + *length); + + /* Find the first DMA buffer to start with */ + TAILQ_FOREACH(entry, &priv->list, link) { + if (offset < entry->origbuf.length) + break; + + offset -= entry->origbuf.length; + } + + if (!entry) { + DMAOBJ_TRACE("There is no DMA Object available"); + ret = TEE_ERROR_GENERIC; + goto out; + } + + start_entry = entry; + DMAOBJ_TRACE("Start with %p data %p offset %zu", start_entry, + start_entry->origbuf.data, offset); + + acc_length = entry->origbuf.length - offset; + nb_sgt = 1; + + /* Calculate the number of SGT entry */ + for (entry = TAILQ_NEXT(entry, link); entry && acc_length < max_length; + entry = TAILQ_NEXT(entry, link)) { + acc_length += entry->origbuf.length; + nb_sgt++; + } + + DMAOBJ_TRACE("%d of %d SGT/Buffer entries to handle", nb_sgt, + priv->nb_sgtbuf); + if (priv->nb_sgtbuf < nb_sgt) { + if (priv->nb_sgtbuf) { + obj->sgtbuf.number = priv->nb_sgtbuf; + obj->sgtbuf.sgt_type = (priv->nb_sgtbuf > 1); + + caam_sgtbuf_free(&obj->sgtbuf); + caam_free(priv->sgtdata); + priv->nb_sgtbuf = 0; + } + + obj->sgtbuf.number = nb_sgt; + obj->sgtbuf.sgt_type = (nb_sgt > 1) ? true : false; + + /* Allocate a new SGT/Buffer object */ + retstatus = caam_sgtbuf_alloc(&obj->sgtbuf); + DMAOBJ_TRACE("Allocate %d SGT entries ret 0x%" PRIx32, + obj->sgtbuf.number, retstatus); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + + priv->sgtdata = caam_calloc(nb_sgt * sizeof(*priv->sgtdata)); + if (!priv->sgtdata) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + priv->nb_sgtbuf = nb_sgt; + } else { + obj->sgtbuf.number = nb_sgt; + obj->sgtbuf.sgt_type = (nb_sgt > 1) ? true : false; + } + + /* Reset the DMA Buffer index if allocated */ + if (priv->dmabuf.allocated) { + priv->dmabuf.remind = priv->dmabuf.allocated; + priv->dmabuf.buf.length = 0; + } + + obj->sgtbuf.length = 0; + for (entry = start_entry; entry && idx < nb_sgt; + entry = TAILQ_NEXT(entry, link), idx++) { + DMAOBJ_TRACE("entry %p (%d)", entry, idx); + if (entry->nodma_access || entry->newbuf) { + retstatus = entry_sgtbuf_dmabuf(obj, entry, idx, + offset); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + } else { + retstatus = entry_sgtbuf(obj, entry, idx, offset); + if (retstatus != CAAM_NO_ERROR) { + ret = caam_status_to_tee_result(retstatus); + goto out; + } + } + + if (obj->sgtbuf.length >= max_length) { + DMAOBJ_TRACE("Hold-on enough length %zu", max_length); + obj->sgtbuf.length = max_length; + break; + } + offset = 0; + } + + if (obj->sgtbuf.sgt_type) { + /* Build the SGT table based on the physical area list */ + caam_sgt_fill_table(&obj->sgtbuf); + + obj->sgtbuf.paddr = virt_to_phys(obj->sgtbuf.sgt); + } else { + obj->sgtbuf.paddr = obj->sgtbuf.buf->paddr; + } + + *length = obj->sgtbuf.length; + ret = TEE_SUCCESS; +out: + DMAOBJ_TRACE("SGTBUF (%zu) returns 0x%" PRIx32, *length, ret); + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/utils/utils_mem.c b/optee/optee_os/core/drivers/crypto/caam/utils/utils_mem.c new file mode 100644 index 0000000..e7c23cd --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/utils_mem.c @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Brief Memory management utilities. + * Primitive to allocate, free memory. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MEM_TYPE_NORMAL 0 /* Normal allocation */ +#define MEM_TYPE_ZEROED BIT(0) /* Buffer filled with 0's */ +#define MEM_TYPE_ALIGN BIT(1) /* Address and size aligned on a cache line */ + +/* + * Read the first byte at the given @addr to ensure that + * virtual page is mapped before getting its physical address. + * + * @addr: address to read + */ +static inline void touch_page(vaddr_t addr) +{ + io_read8(addr); +} + +/* + * Allocate an area of given size in bytes. Add the memory allocator + * information in the newly allocated area. + * + * @size Size in bytes to allocate + * @type Type of area to allocate (refer to MEM_TYPE_*) + */ +static void *mem_alloc(size_t size, uint8_t type) +{ + void *ptr = NULL; + size_t alloc_size = size; + + MEM_TRACE("alloc %zu bytes of type %" PRIu8, size, type); + + if (type & MEM_TYPE_ALIGN) { + size_t cacheline_size = dcache_get_line_size(); + + if (ROUNDUP_OVERFLOW(alloc_size, CFG_CAAM_SIZE_ALIGN, + &alloc_size)) + return NULL; + + if (ROUNDUP_OVERFLOW(alloc_size, cacheline_size, &alloc_size)) + return NULL; + + ptr = memalign(cacheline_size, alloc_size); + } else { + ptr = malloc(alloc_size); + } + + if (!ptr) { + MEM_TRACE("alloc Error - NULL"); + return NULL; + } + + if (type & MEM_TYPE_ZEROED) + memset(ptr, 0, alloc_size); + + MEM_TRACE("alloc returned %p", ptr); + return ptr; +} + +/* + * Free allocated area + * + * @ptr area to free + */ +static void mem_free(void *ptr) +{ + if (ptr) { + MEM_TRACE("free %p", ptr); + free(ptr); + } +} + +/* + * Allocate internal driver buffer aligned with a cache line. + * + * @buf [out] buffer allocated + * @size size in bytes of the memory to allocate + * @type Type of area to allocate (refer to MEM_TYPE_*) + */ +static enum caam_status mem_alloc_buf(struct caambuf *buf, size_t size, + uint8_t type) +{ + buf->data = mem_alloc(size, type); + + if (!buf->data) + return CAAM_OUT_MEMORY; + + buf->paddr = virt_to_phys(buf->data); + if (!buf->paddr) { + caam_free_buf(buf); + return CAAM_OUT_MEMORY; + } + + buf->length = size; + buf->nocache = 0; + return CAAM_NO_ERROR; +} + +void *caam_alloc(size_t size) +{ + return mem_alloc(size, MEM_TYPE_NORMAL); +} + +void *caam_calloc(size_t size) +{ + return mem_alloc(size, MEM_TYPE_ZEROED); +} + +void *caam_calloc_align(size_t size) +{ + return mem_alloc(size, MEM_TYPE_ZEROED | MEM_TYPE_ALIGN); +} + +void caam_free(void *ptr) +{ + mem_free(ptr); +} + +uint32_t *caam_calloc_desc(uint8_t nbentries) +{ + return mem_alloc(DESC_SZBYTES(nbentries), + MEM_TYPE_ZEROED | MEM_TYPE_ALIGN); +} + +void caam_free_desc(uint32_t **ptr) +{ + mem_free(*ptr); + *ptr = NULL; +} + +enum caam_status caam_alloc_buf(struct caambuf *buf, size_t size) +{ + return mem_alloc_buf(buf, size, MEM_TYPE_NORMAL); +} + +enum caam_status caam_calloc_buf(struct caambuf *buf, size_t size) +{ + return mem_alloc_buf(buf, size, MEM_TYPE_ZEROED); +} + +enum caam_status caam_calloc_align_buf(struct caambuf *buf, size_t size) +{ + return mem_alloc_buf(buf, size, MEM_TYPE_ZEROED | MEM_TYPE_ALIGN); +} + +enum caam_status caam_alloc_align_buf(struct caambuf *buf, size_t size) +{ + return mem_alloc_buf(buf, size, MEM_TYPE_ALIGN); +} + +void caam_free_buf(struct caambuf *buf) +{ + if (buf) { + if (buf->data) { + caam_free(buf->data); + buf->data = NULL; + } + + buf->length = 0; + buf->paddr = 0; + buf->nocache = 0; + } +} + +bool caam_mem_is_cached_buf(void *buf, size_t size) +{ + enum teecore_memtypes mtype = MEM_AREA_MAXTYPE; + bool is_cached = false; + + /* + * First check if the buffer is a known memory area mapped + * with a type listed in the teecore_memtypes enum. + * If not mapped, this is a User Area and so assume + * it cacheable + */ + mtype = core_mmu_get_type_by_pa(virt_to_phys(buf)); + if (mtype == MEM_AREA_MAXTYPE) + is_cached = true; + else + is_cached = core_vbuf_is(CORE_MEM_CACHED, buf, size); + + return is_cached; +} + +enum caam_status caam_cpy_block_src(struct caamblock *block, + struct caambuf *src, size_t offset) +{ + enum caam_status ret = CAAM_FAILURE; + size_t cpy_size = 0; + + if (!src->data) + return CAAM_FAILURE; + + /* Check if the temporary buffer is allocated, else allocate it */ + if (!block->buf.data) { + ret = caam_alloc_align_buf(&block->buf, block->max); + if (ret != CAAM_NO_ERROR) { + MEM_TRACE("Allocation Block buffer error"); + goto end_cpy; + } + } + + /* Calculate the number of bytes to copy in the block buffer */ + MEM_TRACE("Current buffer is %zu (%zu) bytes", block->filled, + block->max); + + cpy_size = block->max - block->filled; + cpy_size = MIN(cpy_size, src->length - offset); + + memcpy(&block->buf.data[block->filled], &src->data[offset], cpy_size); + + block->filled += cpy_size; + + ret = CAAM_NO_ERROR; + +end_cpy: + return ret; +} + +int caam_mem_get_pa_area(struct caambuf *buf, struct caambuf **out_pabufs) +{ + int nb_pa_area = 0; + size_t len = 0; + size_t len_tohandle = 0; + vaddr_t va = 0; + vaddr_t next_va = 0; + paddr_t pa = 0; + paddr_t next_pa = 0; + struct caambuf *pabufs = NULL; + + MEM_TRACE("Get PA Areas of %p-%zu (out %p)", buf->data, buf->length, + out_pabufs); + + if (out_pabufs) { + /* + * Caller asked for the extracted contiguous + * physical areas. + * Allocate maximum possible small pages + */ + if (buf->length > SMALL_PAGE_SIZE) { + nb_pa_area = buf->length / SMALL_PAGE_SIZE + 1; + if (buf->length % SMALL_PAGE_SIZE) + nb_pa_area++; + } else { + nb_pa_area = 2; + } + + pabufs = caam_calloc(nb_pa_area * sizeof(*pabufs)); + if (!pabufs) + return -1; + + MEM_TRACE("Allocate max %d Physical Areas", nb_pa_area); + } + + /* + * Go thru all the VA space to extract the contiguous + * physical areas + */ + va = (vaddr_t)buf->data; + pa = virt_to_phys((void *)va); + if (!pa) + goto err; + + nb_pa_area = 0; + if (pabufs) { + pabufs[nb_pa_area].data = (uint8_t *)va; + pabufs[nb_pa_area].paddr = pa; + pabufs[nb_pa_area].length = 0; + pabufs[nb_pa_area].nocache = buf->nocache; + MEM_TRACE("Add %d PA 0x%" PRIxPA " VA 0x%" PRIxVA, nb_pa_area, + pa, va); + } + + for (len = buf->length; len; len -= len_tohandle) { + len_tohandle = + MIN(SMALL_PAGE_SIZE - (va & SMALL_PAGE_MASK), len); + next_va = va + len_tohandle; + if (pabufs) + pabufs[nb_pa_area].length += len_tohandle; + + /* + * Reaches the end of buffer, exits here because + * the next virtual address is out of scope. + */ + if (len == len_tohandle) + break; + + touch_page(next_va); + next_pa = virt_to_phys((void *)next_va); + if (!next_pa) + goto err; + + if (next_pa != (pa + len_tohandle)) { + nb_pa_area++; + if (pabufs) { + pabufs[nb_pa_area].data = (uint8_t *)next_va; + pabufs[nb_pa_area].paddr = next_pa; + pabufs[nb_pa_area].length = 0; + pabufs[nb_pa_area].nocache = buf->nocache; + } + MEM_TRACE("Add %d PA 0x%" PRIxPA " VA 0x%" PRIxVA, + nb_pa_area, next_pa, next_va); + } + + va = next_va; + pa = next_pa; + } + + if (out_pabufs) + *out_pabufs = pabufs; + + MEM_TRACE("Nb Physical Area %d", nb_pa_area + 1); + return nb_pa_area + 1; + +err: + free(pabufs); + return -1; +} + +void caam_mem_cpy_ltrim_buf(struct caambuf *dst, struct caambuf *src) +{ + size_t offset = 0; + size_t cpy_size = 0; + + /* Calculate the offset to start the copy */ + while (!src->data[offset] && offset < src->length) + offset++; + + if (offset >= src->length) + offset = src->length - 1; + + cpy_size = MIN(dst->length, (src->length - offset)); + MEM_TRACE("Copy %zu of src %zu bytes (offset = %zu)", cpy_size, + src->length, offset); + memcpy(dst->data, &src->data[offset], cpy_size); + + dst->length = cpy_size; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt.c b/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt.c new file mode 100644 index 0000000..4ebbb25 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019, 2021 NXP + * + * Brief Scatter-Gatter Table management utilities. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Perform cache management clean operation on the SGT table entry + * + * @sgtbuf SGT table to manage + */ +static void caam_sgt_entries_cache_clean(const struct caamsgtbuf *sgtbuf) +{ + cache_operation(TEE_CACHECLEAN, (void *)sgtbuf->sgt, + ROUNDUP(sgtbuf->number, CFG_CAAM_SGT_ALIGN) * + sizeof(*sgtbuf->sgt)); +} + +void caam_sgt_cache_op(enum utee_cache_operation op, struct caamsgtbuf *insgt, + size_t length) +{ + unsigned int idx = 0; + size_t op_size = 0; + size_t rem_length = length; + + caam_sgt_entries_cache_clean(insgt); + + SGT_TRACE("SGT @%p %d entries", insgt, insgt->number); + for (idx = 0; idx < insgt->number && rem_length; idx++) { + op_size = MIN(rem_length, insgt->buf[idx].length); + if (!insgt->buf[idx].nocache) + cache_operation(op, (void *)insgt->buf[idx].data, + op_size); + rem_length -= op_size; + } +} + +void caam_sgt_fill_table(struct caamsgtbuf *sgt) +{ + unsigned int idx = 0; + + SGT_TRACE("Create %d SGT entries", sgt->number); + + for (idx = 0; idx < sgt->number - 1; idx++) { + CAAM_SGT_ENTRY(&sgt->sgt[idx], sgt->buf[idx].paddr, + sgt->buf[idx].length); + sgt_entry_trace(idx, sgt); + } + + CAAM_SGT_ENTRY_FINAL(&sgt->sgt[idx], sgt->buf[idx].paddr, + sgt->buf[idx].length); + sgt_entry_trace(idx, sgt); +} + +enum caam_status caam_sgt_derive(struct caamsgtbuf *sgt, + const struct caamsgtbuf *from, size_t offset, + size_t length) +{ + enum caam_status retstatus = CAAM_FAILURE; + unsigned int idx = 0; + unsigned int st_idx = 0; + size_t off = offset; + size_t rlength = length; + + SGT_TRACE("Derive from %p - offset %zu, %d SGT entries", from, offset, + from->number); + + if (from->length - offset < length) { + SGT_TRACE("From SGT/Buffer too short (%zu)", from->length); + return CAAM_SHORT_BUFFER; + } + + for (; idx < from->number && off >= from->buf[idx].length; idx++) + off -= from->buf[idx].length; + + st_idx = idx; + sgt->number = 1; + rlength -= MIN(rlength, from->buf[idx].length - off); + + for (idx++; idx < from->number && rlength; idx++) { + rlength -= MIN(rlength, from->buf[idx].length); + sgt->number++; + } + + sgt->sgt_type = (sgt->number > 1) ? true : false; + + /* Allocate a new SGT/Buffer object */ + retstatus = caam_sgtbuf_alloc(sgt); + SGT_TRACE("Allocate %d SGT entries ret 0x%" PRIx32, sgt->number, + retstatus); + if (retstatus != CAAM_NO_ERROR) + return retstatus; + + memcpy(sgt->buf, &from->buf[st_idx], sgt->number * sizeof(*sgt->buf)); + + if (sgt->sgt_type) { + memcpy(sgt->sgt, &from->sgt[st_idx], + sgt->number * sizeof(*sgt->sgt)); + + /* Set the offset of the first sgt entry */ + sgt_entry_offset(sgt->sgt, off); + + /* + * Push the SGT Table into memory now because + * derived objects are not pushed. + */ + caam_sgt_entries_cache_clean(sgt); + + sgt->paddr = virt_to_phys(sgt->sgt); + } else { + sgt->paddr = sgt->buf->paddr + off; + } + + sgt->length = length; + + return CAAM_NO_ERROR; +} + +void caam_sgtbuf_free(struct caamsgtbuf *data) +{ + if (data->sgt_type) + caam_free(data->sgt); + else + caam_free(data->buf); + + data->sgt = NULL; + data->buf = NULL; +} + +enum caam_status caam_sgtbuf_alloc(struct caamsgtbuf *data) +{ + unsigned int nb_sgt = 0; + + if (!data || !data->number) + return CAAM_BAD_PARAM; + + if (data->sgt_type) { + nb_sgt = ROUNDUP(data->number, CFG_CAAM_SGT_ALIGN); + data->sgt = caam_calloc(nb_sgt * (sizeof(union caamsgt) + + sizeof(struct caambuf))); + data->buf = (void *)(((uint8_t *)data->sgt) + + (nb_sgt * sizeof(union caamsgt))); + } else { + data->buf = caam_calloc(data->number * sizeof(struct caambuf)); + data->sgt = NULL; + } + + if (!data->buf || (!data->sgt && data->sgt_type)) { + caam_sgtbuf_free(data); + return CAAM_OUT_MEMORY; + } + + return CAAM_NO_ERROR; +} diff --git a/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v1.c b/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v1.c new file mode 100644 index 0000000..577585b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v1.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + * + * Scatter-gather entry management code for version 1 + */ + +#include +#include +#include + +#define ENTRY_LEN(len) (((uint32_t)len) & GENMASK_32(29, 0)) +#define BS_ENTRY_FINAL BIT32(30) + +void sgt_entry_trace(unsigned int idx __maybe_unused, + const struct caamsgtbuf *sgt __maybe_unused) +{ + SGT_TRACE("SGT[%d] (%p)", idx, &sgt->sgt[idx]); + SGT_TRACE("SGT[%d]->data = %p", idx, sgt->buf[idx].data); + SGT_TRACE("SGT[%d]->length = %zu", idx, sgt->buf[idx].length); + SGT_TRACE("SGT[%d]->paddr = 0x%" PRIxPA, idx, sgt->buf[idx].paddr); + SGT_TRACE("SGT[%d]->ptr_ms = %" PRIx32, idx, sgt->sgt[idx].v1.ptr_ms); + SGT_TRACE("SGT[%d]->ptr_ls = %" PRIx32, idx, sgt->sgt[idx].v1.ptr_ls); + SGT_TRACE("SGT[%d]->len_f_e = %" PRIx32, idx, + sgt->sgt[idx].v1.len_f_e); + SGT_TRACE("SGT[%d]->offset = %" PRIx32, idx, sgt->sgt[idx].v1.offset); +} + +void sgt_entry_offset(union caamsgt *sgt, unsigned int offset) +{ + uint32_t len_f_e = 0; + + len_f_e = caam_read_val32(&sgt->v1.len_f_e); + + /* Set the new length and keep the Final bit if set */ + len_f_e = (ENTRY_LEN(len_f_e) - offset) | (len_f_e & BS_ENTRY_FINAL); + + caam_write_val32(&sgt->v1.len_f_e, len_f_e); + caam_write_val32(&sgt->v1.offset, offset); +} + +void caam_sgt_set_entry(union caamsgt *sgt, paddr_t paddr, size_t len, + unsigned int offset, bool final_e) +{ + unsigned int len_f_e = 0; + + caam_write_val32(&sgt->v1.ptr_ls, paddr); +#if defined(CFG_CAAM_64BIT) && defined(CFG_ARM64_core) + caam_write_val32(&sgt->v1.ptr_ms, paddr >> 32); +#else + caam_write_val32(&sgt->v1.ptr_ms, 0); +#endif + + len_f_e = ENTRY_LEN(len); + if (final_e) + len_f_e |= BS_ENTRY_FINAL; + + caam_write_val32(&sgt->v1.len_f_e, len_f_e); + caam_write_val32(&sgt->v1.offset, offset); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v2.c b/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v2.c new file mode 100644 index 0000000..5d7fd39 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/utils_sgt_v2.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + * + * Scatter-gather entry management code for version 2 + */ + +#include +#include +#include + +void sgt_entry_trace(unsigned int idx __maybe_unused, + const struct caamsgtbuf *sgt __maybe_unused) +{ + SGT_TRACE("SGT[%d] (%p)", idx, &sgt->sgt[idx]); + SGT_TRACE("SGT[%d]->data = %p", idx, sgt->buf[idx].data); + SGT_TRACE("SGT[%d]->length = %zu", idx, sgt->buf[idx].length); + SGT_TRACE("SGT[%d]->paddr = 0x%" PRIxPA, idx, sgt->buf[idx].paddr); + SGT_TRACE("SGT[%d]->w1 = %" PRIx64, idx, sgt->sgt[idx].v2.w1); + SGT_TRACE("SGT[%d]->w2 = %" PRIx64, idx, sgt->sgt[idx].v2.w2); +} + +void sgt_entry_offset(union caamsgt *sgt, unsigned int offset) +{ + uint64_t w2 = 0; + uint64_t len = 0; + uint64_t off = 0; + + w2 = caam_read_val64(&sgt->v2.w2); + + /* + * Compute the new offset reading the one present and adding the + * input + */ + off = SGT_V2_ENTRY_OFFSET(w2); + off += offset; + + /* Reading length and computing new value by subtracting the offset */ + len = SGT_V2_ENTRY_AVAIL_LENGTH(w2); + len = (offset > len) ? 0 : len - offset; + + /* Clear the offset and length fields */ + w2 &= ~(BM_SGT_V2_OFFSET | BM_SGT_V2_AVAIL_LENGTH); + + /* Update offset and field */ + w2 |= BV_SGT_V2_OFFSET(offset) | BV_SGT_V2_AVAIL_LENGTH(len); + + caam_write_val64(&sgt->v2.w2, w2); +} + +void caam_sgt_set_entry(union caamsgt *sgt, paddr_t paddr, size_t len, + unsigned int offset, bool final_e) +{ + uint64_t w2 = 0; + + /* Write the address to set */ + caam_write_val64(&sgt->v2.w1, paddr); + + /* Compute the second word */ + w2 = (final_e ? BM_SGT_V2_F : 0) | BV_SGT_V2_OFFSET(offset) | + BM_SGT_V2_IVP | BV_SGT_V2_AVAIL_LENGTH(len); + + caam_write_val64(&sgt->v2.w2, w2); +} diff --git a/optee/optee_os/core/drivers/crypto/caam/utils/utils_status.c b/optee/optee_os/core/drivers/crypto/caam/utils/utils_status.c new file mode 100644 index 0000000..1bade52 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/caam/utils/utils_status.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019, 2021 NXP + * + * Brief Status management utilities. + */ +#include +#include +#include + +TEE_Result job_status_to_tee_result(uint32_t status) +{ + /* + * Add all status code that can be translated + * to a TEE_Result other than TEE_ERROR_GENERIC + */ + switch (JRSTA_SRC_GET(status)) { + case JRSTA_SRC(NONE): + return TEE_SUCCESS; + + case JRSTA_SRC(DECO): + if (JRSTA_CCB_GET_ERR(status) == JRSTA_DECO_ERRID_FORMAT) + return TEE_ERROR_BAD_PARAMETERS; + + if (JRSTA_CCB_GET_ERR(status) == JRSTA_DECO_INV_SIGNATURE) + return TEE_ERROR_SIGNATURE_INVALID; + + break; + + default: + break; + } + + return TEE_ERROR_GENERIC; +} + +TEE_Result caam_status_to_tee_result(enum caam_status status) +{ + switch (status) { + case CAAM_NO_ERROR: + return TEE_SUCCESS; + + case CAAM_OUT_MEMORY: + return TEE_ERROR_OUT_OF_MEMORY; + + case CAAM_BAD_PARAM: + return TEE_ERROR_BAD_PARAMETERS; + + case CAAM_SHORT_BUFFER: + return TEE_ERROR_SHORT_BUFFER; + + case CAAM_NOT_SUPPORTED: + return TEE_ERROR_NOT_SUPPORTED; + + default: + break; + } + + return TEE_ERROR_GENERIC; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/acipher/dh.c b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/dh.c new file mode 100644 index 0000000..7b5011c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/dh.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Crypto DH interface implementation to enable HW driver. + */ +#include +#include +#include +#include + +TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *key, + size_t size_bits) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_dh *dh = NULL; + + if (!key || !size_bits) { + CRYPTO_TRACE("Param error key @%#" PRIxPTR " size %zu bits", + (uintptr_t)key, size_bits); + return TEE_ERROR_BAD_PARAMETERS; + } + + dh = drvcrypt_get_ops(CRYPTO_DH); + if (dh) + ret = dh->alloc_keypair(key, size_bits); + + CRYPTO_TRACE("DH Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits, + ret); + return ret; +} + +TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q, + size_t xbits, size_t key_size) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_dh *dh = NULL; + + if (!key) { + CRYPTO_TRACE("Parameters error key is NULL"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (key_size != 8 * crypto_bignum_num_bytes(key->p)) + return TEE_ERROR_BAD_PARAMETERS; + + dh = drvcrypt_get_ops(CRYPTO_DH); + if (dh) + ret = dh->gen_keypair(key, q, xbits); + + CRYPTO_TRACE("DH Keypair (%zu bits) generate ret = 0x%" PRIx32, + key_size, ret); + + return ret; +} + +TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, + struct bignum *public_key, + struct bignum *secret) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_dh *dh = NULL; + struct drvcrypt_secret_data sdata = { }; + uint8_t *secret_buf = NULL; + + if (!private_key || !public_key || !secret) { + CRYPTO_TRACE("Input parameters reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + dh = drvcrypt_get_ops(CRYPTO_DH); + if (dh) { + /* Allocate the binary Secret buffer */ + sdata.secret.length = crypto_bignum_num_bytes(public_key); + secret_buf = malloc(sdata.secret.length); + if (!secret_buf) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Prepare the Secret structure data */ + sdata.key_priv = private_key; + sdata.key_pub = public_key; + sdata.secret.data = secret_buf; + + ret = dh->shared_secret(&sdata); + if (ret == TEE_SUCCESS) + ret = crypto_bignum_bin2bn(secret_buf, + sdata.secret.length, secret); + + free(secret_buf); + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("Shared Secret returned 0x%" PRIx32, ret); + + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/acipher/dsa.c b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/dsa.c new file mode 100644 index 0000000..780b8be --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/dsa.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Crypto DSA interface implementation to enable HW driver. + */ +#include +#include +#include + +/* + * Get the recommended L and N bits parameters corresponding + * respectively to the size of the Primes P and G (and so + * the Public Key and Private Key). + * + * Refer the NIST.FIPS 186-4 section 4.2 + * + * @size_bits Maximum key size bits + * @l_bits [out] L size in bits + * @n_bits [out] N size in bits + */ +static TEE_Result get_keys_size(size_t size_bits, size_t *l_bits, + size_t *n_bits) +{ + if (size_bits <= 1024) + *n_bits = 160; + else if (size_bits <= 3072) + *n_bits = 256; + else + return TEE_ERROR_NOT_IMPLEMENTED; + + *l_bits = size_bits; + + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *key, + size_t size_bits) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_dsa *dsa = NULL; + size_t l_bits = 0; + size_t n_bits = 0; + + if (!key || !size_bits) { + CRYPTO_TRACE("Param error key @0x%" PRIxPTR " size %zu bits", + (uintptr_t)key, size_bits); + return TEE_ERROR_BAD_PARAMETERS; + } + + ret = get_keys_size(size_bits, &l_bits, &n_bits); + if (ret == TEE_SUCCESS) { + dsa = drvcrypt_get_ops(CRYPTO_DSA); + if (dsa) + ret = dsa->alloc_keypair(key, l_bits, n_bits); + else + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("DSA Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits, + ret); + return ret; +} + +TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *key, + size_t size_bits) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_dsa *dsa = NULL; + size_t l_bits = 0; + size_t n_bits = 0; + + if (!key || !size_bits) { + CRYPTO_TRACE("Param error key @0x%" PRIxPTR " size %zu bits", + (uintptr_t)key, size_bits); + return TEE_ERROR_BAD_PARAMETERS; + } + + ret = get_keys_size(size_bits, &l_bits, &n_bits); + if (ret == TEE_SUCCESS) { + dsa = drvcrypt_get_ops(CRYPTO_DSA); + if (dsa) + ret = dsa->alloc_publickey(key, l_bits, n_bits); + else + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("DSA Public Key (%zu bits) alloc ret = 0x%" PRIx32, + size_bits, ret); + return ret; +} + +TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_dsa *dsa = NULL; + size_t l_bits = 0; + size_t n_bits = 0; + + if (!key || !key_size) { + CRYPTO_TRACE("Param error key @0x%" PRIxPTR " size %zu bits", + (uintptr_t)key, key_size); + return TEE_ERROR_BAD_PARAMETERS; + } + + ret = get_keys_size(key_size, &l_bits, &n_bits); + if (ret == TEE_SUCCESS) { + dsa = drvcrypt_get_ops(CRYPTO_DSA); + if (dsa) + ret = dsa->gen_keypair(key, l_bits, n_bits); + else + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("DSA Keypair (%zu bits) generate ret = 0x%" PRIx32, + key_size, ret); + + return ret; +} + +TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_dsa *dsa = NULL; + struct drvcrypt_sign_data sdata = { }; + size_t l_bytes = 0; + size_t n_bytes = 0; + + if (!key || !msg || !sig_len) { + CRYPTO_TRACE("Input parameters reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* + * Verify the signature length function of the key size + * + * Prime number sizes are not stored but deducted from bignum size. + * This requires prime numbers p and q to have their MSB set otherwise + * crypto_bignum_num_bytes() will return a wrong size. + */ + n_bytes = crypto_bignum_num_bytes(key->q); + l_bytes = crypto_bignum_num_bytes(key->p); + if (*sig_len < 2 * n_bytes) { + CRYPTO_TRACE("Length (%zu) too short expected %zu bytes", + *sig_len, 2 * n_bytes); + *sig_len = 2 * n_bytes; + return TEE_ERROR_SHORT_BUFFER; + } + + if (!sig) { + CRYPTO_TRACE("Parameter \"sig\" reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + dsa = drvcrypt_get_ops(CRYPTO_DSA); + if (dsa) { + sdata.algo = algo; + sdata.key = key; + sdata.size_sec = n_bytes; + sdata.message.data = (uint8_t *)msg; + sdata.message.length = msg_len; + sdata.signature.data = sig; + sdata.signature.length = *sig_len; + + ret = dsa->sign(&sdata, l_bytes, n_bytes); + + /* Set the signature length */ + *sig_len = sdata.signature.length; + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("Sign algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, + ret); + + return ret; +} + +TEE_Result crypto_acipher_dsa_verify(uint32_t algo, struct dsa_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_dsa *dsa = NULL; + struct drvcrypt_sign_data sdata = { }; + size_t l_bytes = 0; + size_t n_bytes = 0; + + if (!key || !msg || !sig) { + CRYPTO_TRACE("Input parameters reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* + * Verify the signature length function of the key size + * + * Prime number sizes are not stored but deducted from bignum size. + * This requires prime numbers p and q to have their MSB set otherwise + * crypto_bignum_num_bytes() will return a wrong size. + */ + n_bytes = crypto_bignum_num_bytes(key->q); + l_bytes = crypto_bignum_num_bytes(key->p); + if (sig_len != 2 * n_bytes) { + CRYPTO_TRACE("Length (%zu) is invalid expected %zu bytes", + sig_len, 2 * n_bytes); + return TEE_ERROR_SIGNATURE_INVALID; + } + + dsa = drvcrypt_get_ops(CRYPTO_DSA); + if (dsa) { + sdata.algo = algo; + sdata.key = key; + sdata.size_sec = n_bytes; + sdata.message.data = (uint8_t *)msg; + sdata.message.length = msg_len; + sdata.signature.data = (uint8_t *)sig; + sdata.signature.length = sig_len; + + ret = dsa->verify(&sdata, l_bytes, n_bytes); + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("Verify algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, + ret); + + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/acipher/ecc.c b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/ecc.c new file mode 100644 index 0000000..6ec0e10 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/ecc.c @@ -0,0 +1,596 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2021 NXP + * + * Crypto ECC interface implementation to enable HW driver. + */ +#include +#include +#include +#include + +/* + * Returns the key size in bytes for the given ECC curve + * + * @curve ECC Curve ID + */ +static size_t get_ecc_key_size_bytes(uint32_t curve) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + return 24; + + case TEE_ECC_CURVE_NIST_P224: + return 28; + + case TEE_ECC_CURVE_NIST_P256: + case TEE_ECC_CURVE_SM2: + return 32; + + case TEE_ECC_CURVE_NIST_P384: + return 48; + + case TEE_ECC_CURVE_NIST_P521: + return 66; + + default: + return 0; + } +} + +/* + * Returns the key size in bits for the given ECC curve + * + * @curve ECC Curve ID + */ + +static size_t get_ecc_key_size_bits(uint32_t curve) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + case TEE_ECC_CURVE_NIST_P224: + case TEE_ECC_CURVE_NIST_P256: + case TEE_ECC_CURVE_NIST_P384: + case TEE_ECC_CURVE_SM2: + return get_ecc_key_size_bytes(curve) * 8; + + case TEE_ECC_CURVE_NIST_P521: + return 521; + + default: + return 0; + } +} + +/* + * Verify if the cryptographic algorithm @algo is valid for + * the ECC curve + * + * @curve ECC curve + * @algo Cryptographic algorithm + */ +static bool algo_is_valid(uint32_t curve, uint32_t algo) +{ + unsigned int algo_op = TEE_ALG_GET_CLASS(algo); + unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo); + unsigned int algo_curve = TEE_ALG_GET_DIGEST_HASH(algo); + + /* Check first the algo operation and id */ + if ((algo_op == TEE_OPERATION_ASYMMETRIC_SIGNATURE && + algo_id == TEE_MAIN_ALGO_ECDSA) || + (algo_op == TEE_OPERATION_KEY_DERIVATION && + algo_id == TEE_MAIN_ALGO_ECDH)) { + if (curve == algo_curve) { + CRYPTO_TRACE("Algo 0x%" PRIx32 " curve 0x%" PRIx32 + " is valid", algo, curve); + return true; + } + } + + if (algo_op == TEE_OPERATION_ASYMMETRIC_SIGNATURE && + algo_id == TEE_MAIN_ALGO_SM2_DSA_SM3) { + if (curve == TEE_ECC_CURVE_SM2) + return true; + } + + CRYPTO_TRACE("Algo 0x%" PRIx32 " curve 0x%" PRIx32 " is not valid", + algo, curve); + + return false; +} + +/* + * Free an ECC public key + * + * @key Public Key + */ +static void ecc_free_public_key(struct ecc_public_key *key) +{ + struct drvcrypt_ecc *ecc = NULL; + + if (key) { + ecc = drvcrypt_get_ops(CRYPTO_ECC); + if (ecc) { + CRYPTO_TRACE("ECC Public Key free"); + ecc->free_publickey(key); + } + } +} + +/* + * Generates an ECC keypair + * + * @key Keypair + * @size_bits Key size in bits + */ +static TEE_Result ecc_generate_keypair(struct ecc_keypair *key, + size_t size_bits __maybe_unused) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_ecc *ecc = NULL; + size_t key_size_bits = 0; + + /* Check input parameters */ + if (!key) { + CRYPTO_TRACE("Parameters error key is NULL"); + return TEE_ERROR_BAD_PARAMETERS; + } + + key_size_bits = get_ecc_key_size_bits(key->curve); + + ecc = drvcrypt_get_ops(CRYPTO_ECC); + if (ecc) + ret = ecc->gen_keypair(key, key_size_bits); + + CRYPTO_TRACE("ECC Keypair (%zu bits) generate ret = 0x%" PRIx32, + key_size_bits, ret); + + return ret; +} + +/* + * Sign the message with the ECC Key given by the Keypair + * + * @algo ECC algorithm + * @key ECC Keypair + * @msg Message to sign + * @msg_len Length of the message (bytes) + * @sig Signature + * @sig_len [in/out] Length of the signature (bytes) + */ +static TEE_Result ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, uint8_t *sig, + size_t *sig_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_ecc *ecc = NULL; + struct drvcrypt_sign_data sdata = { }; + size_t size_bytes = 0; + + /* Verify first the input parameters */ + if (!key || !msg || !sig_len) { + CRYPTO_TRACE("Input parameters reference error"); + return ret; + } + + if (!algo_is_valid(key->curve, algo)) + return ret; + + size_bytes = get_ecc_key_size_bytes(key->curve); + if (!size_bytes) + return TEE_ERROR_BAD_PARAMETERS; + + /* Verify the signature length function of the key size */ + if (*sig_len < 2 * size_bytes) { + CRYPTO_TRACE("Length (%zu) too short expected %zu bytes", + *sig_len, 2 * size_bytes); + *sig_len = 2 * size_bytes; + return TEE_ERROR_SHORT_BUFFER; + } + + if (!sig) { + CRYPTO_TRACE("Parameter \"sig\" reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + ecc = drvcrypt_get_ops(CRYPTO_ECC); + if (ecc) { + /* + * Prepare the Signature structure data + */ + sdata.algo = algo; + sdata.key = key; + sdata.size_sec = size_bytes; + sdata.message.data = (uint8_t *)msg; + sdata.message.length = msg_len; + sdata.signature.data = (uint8_t *)sig; + sdata.signature.length = *sig_len; + + ret = ecc->sign(&sdata); + + /* Set the signature length */ + *sig_len = sdata.signature.length; + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("Sign algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, + ret); + + return ret; +} + +/* + * Verify if signature is signed with the given public key. + * + * @algo ECC algorithm + * @key ECC Public key + * @msg Message to sign + * @msg_len Length of the message (bytes) + * @sig Signature + * @sig_len Length of the signature (bytes) + */ +static TEE_Result ecc_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_ecc *ecc = NULL; + struct drvcrypt_sign_data sdata = { }; + size_t size_bytes = 0; + + /* Verify first the input parameters */ + if (!key || !msg || !sig) { + CRYPTO_TRACE("Input parameters reference error"); + return ret; + } + + if (!algo_is_valid(key->curve, algo)) + return ret; + + size_bytes = get_ecc_key_size_bytes(key->curve); + if (!size_bytes) + return TEE_ERROR_BAD_PARAMETERS; + + /* Verify the signature length against key size */ + if (sig_len != 2 * size_bytes) { + CRYPTO_TRACE("Length (%zu) is invalid expected %zu bytes", + sig_len, 2 * size_bytes); + return TEE_ERROR_SIGNATURE_INVALID; + } + + ecc = drvcrypt_get_ops(CRYPTO_ECC); + if (ecc) { + sdata.algo = algo; + sdata.key = key; + sdata.size_sec = size_bytes; + sdata.message.data = (uint8_t *)msg; + sdata.message.length = msg_len; + sdata.signature.data = (uint8_t *)sig; + sdata.signature.length = sig_len; + + ret = ecc->verify(&sdata); + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("Verify algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, + ret); + + return ret; +} + +/* + * Compute the shared secret data from ECC Private key and Public Key + * + * @private_key ECC Private key + * @public_key ECC Public key + * @secret Secret + * @secret_len Length of the secret (bytes) + */ +static TEE_Result ecc_shared_secret(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, unsigned long *secret_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_ecc *ecc = NULL; + struct drvcrypt_secret_data sdata = { }; + size_t size_bytes = 0; + + /* Verify first the input parameters */ + if (!private_key || !public_key || !secret_len) { + CRYPTO_TRACE("Input parameters reference error"); + return ret; + } + + if (private_key->curve != public_key->curve) { + CRYPTO_TRACE("Private Key curve (%d) != Public Key curve (%d)", + private_key->curve, public_key->curve); + return ret; + } + + size_bytes = get_ecc_key_size_bytes(public_key->curve); + if (!size_bytes) + return ret; + + if (*secret_len < size_bytes) { + *secret_len = size_bytes; + return TEE_ERROR_SHORT_BUFFER; + } + + if (!secret) { + CRYPTO_TRACE("Parameter \"secret\" reference error"); + return ret; + } + + ecc = drvcrypt_get_ops(CRYPTO_ECC); + if (ecc) { + /* + * Prepare the Secret structure data + */ + sdata.key_priv = private_key; + sdata.key_pub = public_key; + sdata.size_sec = size_bytes; + sdata.secret.data = secret; + sdata.secret.length = *secret_len; + + ret = ecc->shared_secret(&sdata); + + /* Set the secret length */ + *secret_len = sdata.secret.length; + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("Shared Secret returned 0x%" PRIx32, ret); + + return ret; +} + +static TEE_Result ecc_sm2_encrypt(struct ecc_public_key *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_ecc_ed cdata = { }; + struct drvcrypt_ecc *ecc = NULL; + size_t ciphertext_len = 0; + size_t size_bytes = 0; + + ecc = drvcrypt_get_ops(CRYPTO_ECC); + + size_bytes = get_ecc_key_size_bytes(key->curve); + if (!size_bytes) { + CRYPTO_TRACE("Curve 0x%08"PRIx32" not supported", key->curve); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Uncompressed form indicator */ + dst[0] = 0x04; + + ciphertext_len = 2 * size_bytes + src_len + TEE_SM3_HASH_SIZE; + + cdata.key = key; + cdata.size_sec = size_bytes; + cdata.plaintext.data = (uint8_t *)src; + cdata.plaintext.length = src_len; + cdata.ciphertext.data = dst + 1; + cdata.ciphertext.length = ciphertext_len; + + ret = ecc->encrypt(&cdata); + + if (!ret || ret == TEE_ERROR_SHORT_BUFFER) + *dst_len = cdata.ciphertext.length + 1; + + return ret; +} + +static TEE_Result ecc_encrypt(struct ecc_public_key *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + struct drvcrypt_ecc *ecc = NULL; + + if (!key || !src || !dst) { + CRYPTO_TRACE("Input parameters reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + ecc = drvcrypt_get_ops(CRYPTO_ECC); + if (!ecc || !ecc->encrypt) + return TEE_ERROR_NOT_IMPLEMENTED; + + switch (key->curve) { + case TEE_ECC_CURVE_SM2: + return ecc_sm2_encrypt(key, src, src_len, dst, dst_len); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +static TEE_Result ecc_sm2_decrypt(struct ecc_keypair *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_ecc_ed cdata = { }; + struct drvcrypt_ecc *ecc = NULL; + uint8_t *ciphertext = NULL; + size_t ciphertext_len = 0; + size_t size_bytes = 0; + size_t plaintext_len = 0; + /* Point Compression */ + uint8_t pc = 0; + + ecc = drvcrypt_get_ops(CRYPTO_ECC); + + size_bytes = get_ecc_key_size_bytes(key->curve); + if (!size_bytes) { + CRYPTO_TRACE("Curve 0x%08"PRIx32" not supported", key->curve); + return TEE_ERROR_BAD_PARAMETERS; + } + + pc = src[0]; + switch (pc) { + case 0x02: + case 0x03: + /* Compressed form */ + return TEE_ERROR_NOT_SUPPORTED; + case 0x04: + /* Uncompressed form */ + ciphertext = (uint8_t *)src + 1; + ciphertext_len = src_len - 1; + break; + case 0x06: + case 0x07: + /* Hybrid form */ + return TEE_ERROR_NOT_SUPPORTED; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (SUB_OVERFLOW(ciphertext_len, 2 * size_bytes + TEE_SM3_HASH_SIZE, + &plaintext_len)) + return TEE_ERROR_BAD_PARAMETERS; + + cdata.key = key; + cdata.size_sec = size_bytes; + cdata.ciphertext.data = ciphertext; + cdata.ciphertext.length = ciphertext_len; + cdata.plaintext.data = dst; + cdata.plaintext.length = plaintext_len; + + ret = ecc->decrypt(&cdata); + + /* Set the plaintext length */ + if (!ret || ret == TEE_ERROR_SHORT_BUFFER) + *dst_len = cdata.plaintext.length; + + return ret; +} + +static TEE_Result ecc_decrypt(struct ecc_keypair *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + struct drvcrypt_ecc *ecc = NULL; + + if (!key || !src || !dst) { + CRYPTO_TRACE("Input parameters reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + ecc = drvcrypt_get_ops(CRYPTO_ECC); + if (!ecc || !ecc->decrypt) + return TEE_ERROR_NOT_IMPLEMENTED; + + switch (key->curve) { + case TEE_ECC_CURVE_SM2: + return ecc_sm2_decrypt(key, src, src_len, dst, dst_len); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +static const struct crypto_ecc_keypair_ops ecc_keypair_ops = { + .generate = ecc_generate_keypair, + .sign = ecc_sign, + .shared_secret = ecc_shared_secret, + .decrypt = ecc_decrypt, +}; + +TEE_Result drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair *key, + uint32_t type, size_t size_bits) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_ecc *ecc = NULL; + + if (!key || !size_bits) { + CRYPTO_TRACE("Bad parameters (key @%p)(size %zu bits)", key, + size_bits); + return TEE_ERROR_BAD_PARAMETERS; + } + + switch (type) { + case TEE_TYPE_ECDSA_KEYPAIR: + case TEE_TYPE_ECDH_KEYPAIR: + case TEE_TYPE_SM2_PKE_KEYPAIR: + case TEE_TYPE_SM2_DSA_KEYPAIR: + ecc = drvcrypt_get_ops(CRYPTO_ECC); + break; + default: + break; + } + + if (ecc) + ret = ecc->alloc_keypair(key, type, size_bits); + + if (!ret) { + key->ops = &ecc_keypair_ops; + + /* ecc->alloc_keypair() can not get type to set curve */ + switch (type) { + case TEE_TYPE_SM2_PKE_KEYPAIR: + case TEE_TYPE_SM2_DSA_KEYPAIR: + key->curve = TEE_ECC_CURVE_SM2; + break; + default: + break; + } + } + + CRYPTO_TRACE("ECC Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits, + ret); + return ret; +} + +static const struct crypto_ecc_public_ops ecc_public_key_ops = { + .free = ecc_free_public_key, + .verify = ecc_verify, + .encrypt = ecc_encrypt, +}; + +TEE_Result drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key *key, + uint32_t type, size_t size_bits) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_ecc *ecc = NULL; + + if (!key || !size_bits) { + CRYPTO_TRACE("Bad parameters (key @%p)(size %zu bits)", key, + size_bits); + return TEE_ERROR_BAD_PARAMETERS; + } + + switch (type) { + case TEE_TYPE_ECDSA_PUBLIC_KEY: + case TEE_TYPE_ECDH_PUBLIC_KEY: + case TEE_TYPE_SM2_PKE_PUBLIC_KEY: + case TEE_TYPE_SM2_DSA_PUBLIC_KEY: + ecc = drvcrypt_get_ops(CRYPTO_ECC); + break; + default: + break; + } + + if (ecc) + ret = ecc->alloc_publickey(key, type, size_bits); + + if (!ret) { + key->ops = &ecc_public_key_ops; + + /* ecc->alloc_publickey() can not get type to set curve */ + switch (type) { + case TEE_TYPE_SM2_PKE_PUBLIC_KEY: + case TEE_TYPE_SM2_DSA_PUBLIC_KEY: + key->curve = TEE_ECC_CURVE_SM2; + break; + default: + break; + } + } + + CRYPTO_TRACE("ECC Public Key (%zu bits) alloc ret = 0x%" PRIx32, + size_bits, ret); + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/acipher/local.h b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/local.h new file mode 100644 index 0000000..2700328 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/local.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2020 NXP + * + * Definition of the functions shared locally. + */ +#ifndef __LOCAL_H__ +#define __LOCAL_H__ + +#include + +/* + * Mask Generation function. Use a Hash operation + * to generate an output @mask from an input @seed + * + * @mgf_data [in/out] MGF data + */ +TEE_Result drvcrypt_rsa_mgf1(struct drvcrypt_rsa_mgf *mgf_data); + +/* + * PKCS#1 - Signature of RSA message and encodes the signature. + * + * @ssa_data [in/out] RSA data to sign / Signature + */ +TEE_Result drvcrypt_rsassa_sign(struct drvcrypt_rsa_ssa *ssa_data); + +/* + * PKCS#1 - Verification the encoded signature of RSA message. + * + * @ssa_data RSA Encoded signature data + */ +TEE_Result drvcrypt_rsassa_verify(struct drvcrypt_rsa_ssa *ssa_data); + +#endif /* __LOCAL_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsa.c b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsa.c new file mode 100644 index 0000000..24b26c2 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsa.c @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2020 NXP + * + * Crypto RSA interface implementation to enable HW driver. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *key, + size_t size_bits) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + + struct drvcrypt_rsa *rsa = NULL; + + if (!key || !size_bits) { + CRYPTO_TRACE("Parameters error (key @%p) (size %zu bits)", key, + size_bits); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) + ret = rsa->alloc_keypair(key, size_bits); + + CRYPTO_TRACE("RSA Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits, + ret); + return ret; +} + +TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *key, + size_t size_bits) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_rsa *rsa = NULL; + + if (!key || !size_bits) { + CRYPTO_TRACE("Parameters error (key @%p) (size %zu bits)", key, + size_bits); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) + ret = rsa->alloc_publickey(key, size_bits); + + CRYPTO_TRACE("RSA Public Key (%zu bits) alloc ret = 0x%" PRIx32, + size_bits, ret); + return ret; +} + +void crypto_acipher_free_rsa_public_key(struct rsa_public_key *key) +{ + struct drvcrypt_rsa *rsa = NULL; + + if (key) { + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + CRYPTO_TRACE("RSA Public Key free"); + rsa->free_publickey(key); + } + } +} + +void crypto_acipher_free_rsa_keypair(struct rsa_keypair *key) +{ + struct drvcrypt_rsa *rsa = NULL; + + if (key) { + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + CRYPTO_TRACE("RSA Keypair free"); + rsa->free_keypair(key); + } + } +} + +TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t size_bits) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_rsa *rsa = NULL; + + if (!key || !size_bits) { + CRYPTO_TRACE("Parameters error (key @%p) (size %zu bits) ", + key, size_bits); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) + ret = rsa->gen_keypair(key, size_bits); + + CRYPTO_TRACE("RSA Keypair (%zu bits) generate ret = 0x%" PRIx32, + size_bits, ret); + + return ret; +} + +TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, + const uint8_t *cipher, + size_t cipher_len, uint8_t *msg, + size_t *msg_len) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_rsa *rsa = NULL; + struct drvcrypt_rsa_ed rsa_data = { }; + + if (!key || !msg || !cipher || !msg_len) { + CRYPTO_TRACE("Parameters error (key @%p)\n" + "(msg @%p size %zu bytes)\n" + "(cipher @0%p size %zu bytes)", + key, msg, msg_len ? *msg_len : 0, + cipher, cipher_len); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa_data.key.key = key; + rsa_data.key.isprivate = true; + rsa_data.key.n_size = crypto_bignum_num_bytes(key->n); + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + rsa_data.rsa_id = DRVCRYPT_RSA_NOPAD; + rsa_data.message.data = msg; + rsa_data.message.length = *msg_len; + rsa_data.cipher.data = (uint8_t *)cipher; + rsa_data.cipher.length = cipher_len; + + ret = rsa->decrypt(&rsa_data); + + *msg_len = rsa_data.message.length; + } + + CRYPTO_TRACE("RSA Decrypt NO PAD ret = 0x%" PRIx32, ret); + + return ret; +} + +TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, + const uint8_t *msg, size_t msg_len, + uint8_t *cipher, size_t *cipher_len) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_rsa *rsa = NULL; + struct drvcrypt_rsa_ed rsa_data = { }; + + if (!key || !msg || !cipher_len) { + CRYPTO_TRACE("Parameters error (key @%p)\n" + "(msg @%p size %zu bytes)\n" + "(cipher @%p size %zu bytes)", + key, msg, msg_len, + cipher, cipher_len ? *cipher_len : 0); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa_data.key.key = key; + rsa_data.key.isprivate = false; + rsa_data.key.n_size = crypto_bignum_num_bytes(key->n); + + if (rsa_data.key.n_size > *cipher_len) { + CRYPTO_TRACE("Cipher length (%zu) too short expected %zu bytes", + *cipher_len, rsa_data.key.n_size); + *cipher_len = rsa_data.key.n_size; + return TEE_ERROR_SHORT_BUFFER; + } + + if (!cipher) { + CRYPTO_TRACE("Parameter \"cipher\" reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + /* Prepare the encryption data parameters */ + rsa_data.rsa_id = DRVCRYPT_RSA_NOPAD; + rsa_data.message.data = (uint8_t *)msg; + rsa_data.message.length = msg_len; + rsa_data.cipher.data = cipher; + rsa_data.cipher.length = *cipher_len; + + ret = rsa->encrypt(&rsa_data); + + /* Set the cipher size */ + *cipher_len = rsa_data.cipher.length; + } + + CRYPTO_TRACE("RSA Encrypt NO PAD ret = 0x%" PRIx32, ret); + + return ret; +} + +TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, + const uint8_t *label, size_t label_len, + const uint8_t *cipher, + size_t cipher_len, uint8_t *msg, + size_t *msg_len) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_rsa *rsa = NULL; + struct drvcrypt_rsa_ed rsa_data = { }; + + if (!key || !msg || !cipher || !msg_len || (!label && label_len)) { + CRYPTO_TRACE("Parameters error (key @%p)\n" + "(msg @%p size %zu bytes)\n" + "(cipher @%p size %zu bytes)\n" + "(label @%p size %zu bytes)", + key, msg, msg_len ? *msg_len : 0, + cipher, cipher_len, label, label_len); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + /* Prepare the encryption data parameters */ + if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { + rsa_data.rsa_id = DRVCRYPT_RSA_PKCS_V1_5; + } else { + rsa_data.rsa_id = DRVCRYPT_RSA_OAEP; + rsa_data.hash_algo = TEE_INTERNAL_HASH_TO_ALGO(algo); + + ret = tee_alg_get_digest_size(rsa_data.hash_algo, + &rsa_data.digest_size); + if (ret != TEE_SUCCESS) + return ret; + + rsa_data.mgf = &drvcrypt_rsa_mgf1; + } + + rsa_data.key.key = key; + rsa_data.key.isprivate = true; + rsa_data.key.n_size = crypto_bignum_num_bytes(key->n); + + rsa_data.message.data = msg; + rsa_data.message.length = *msg_len; + rsa_data.cipher.data = (uint8_t *)cipher; + rsa_data.cipher.length = cipher_len; + rsa_data.label.data = + ((label_len > 0) ? (uint8_t *)label : NULL); + rsa_data.label.length = label_len; + rsa_data.algo = algo; + + ret = rsa->decrypt(&rsa_data); + + /* Set the message size */ + *msg_len = rsa_data.message.length; + } + + CRYPTO_TRACE("RSAES Decrypt ret = 0x%" PRIx32, ret); + + return ret; +} + +TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, + struct rsa_public_key *key, + const uint8_t *label, size_t label_len, + const uint8_t *msg, size_t msg_len, + uint8_t *cipher, size_t *cipher_len) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct drvcrypt_rsa *rsa = NULL; + struct drvcrypt_rsa_ed rsa_data = { }; + + if (!key || !msg || !cipher_len || (!label && label_len)) { + CRYPTO_TRACE("Parameters error (key @%p\n" + "(msg @%p size %zu bytes)\n" + "(cipher @%p size %zu bytes)\n" + "(label @%p size %zu bytes)", + key, msg, msg_len, + cipher, cipher_len ? *cipher_len : 0, + label, label_len); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa_data.key.key = key; + rsa_data.key.isprivate = false; + rsa_data.key.n_size = crypto_bignum_num_bytes(key->n); + + if (rsa_data.key.n_size > *cipher_len) { + CRYPTO_TRACE("Cipher length (%zu) too short expected %zu bytes", + *cipher_len, rsa_data.key.n_size); + *cipher_len = rsa_data.key.n_size; + return TEE_ERROR_SHORT_BUFFER; + } + + if (!cipher) { + CRYPTO_TRACE("Parameter \"cipher\" reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + /* Prepare the encryption data parameters */ + if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { + rsa_data.rsa_id = DRVCRYPT_RSA_PKCS_V1_5; + + /* Message length <= (modulus_size - 11) */ + if (msg_len > rsa_data.key.n_size - 11) + return TEE_ERROR_BAD_PARAMETERS; + + } else { + rsa_data.rsa_id = DRVCRYPT_RSA_OAEP; + rsa_data.hash_algo = TEE_INTERNAL_HASH_TO_ALGO(algo); + + /* Message length <= (modulus_size - 2 * hLength - 2) */ + ret = tee_alg_get_digest_size(rsa_data.hash_algo, + &rsa_data.digest_size); + if (ret != TEE_SUCCESS) + return ret; + + if (2 * rsa_data.digest_size >= rsa_data.key.n_size - 2) + return TEE_ERROR_BAD_PARAMETERS; + + if (msg_len > + rsa_data.key.n_size - 2 * rsa_data.digest_size - 2) + return TEE_ERROR_BAD_PARAMETERS; + + rsa_data.mgf = &drvcrypt_rsa_mgf1; + } + + rsa_data.message.data = (uint8_t *)msg; + rsa_data.message.length = msg_len; + rsa_data.cipher.data = cipher; + rsa_data.cipher.length = rsa_data.key.n_size; + rsa_data.label.data = (label_len > 0) ? (uint8_t *)label : NULL; + rsa_data.label.length = label_len; + rsa_data.algo = algo; + + ret = rsa->encrypt(&rsa_data); + + /* Set the cipher size */ + *cipher_len = rsa_data.cipher.length; + } + + CRYPTO_TRACE("RSAES Encrypt ret = 0x%" PRIx32, ret); + + return ret; +} + +TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, + int salt_len, const uint8_t *msg, + size_t msg_len, uint8_t *sig, + size_t *sig_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_rsa *rsa = NULL; + struct drvcrypt_rsa_ssa rsa_ssa = { }; + + if (!key || !msg || !sig_len) { + CRYPTO_TRACE("Input parameters reference error"); + return ret; + } + + if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { + /* Prepare the Digest */ + rsa_ssa.hash_algo = TEE_DIGEST_HASH_TO_ALGO(algo); + + /* Check if the message length is digest hash size */ + ret = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), + &rsa_ssa.digest_size); + if (ret != TEE_SUCCESS) + return ret; + + if (msg_len != rsa_ssa.digest_size) { + CRYPTO_TRACE("Msg length (%zu expected %zu)", msg_len, + rsa_ssa.digest_size); + return TEE_ERROR_BAD_PARAMETERS; + } + } else { + rsa_ssa.hash_algo = 0; + rsa_ssa.digest_size = 0; + } + + /* Prepare the Key */ + rsa_ssa.key.key = key; + rsa_ssa.key.isprivate = true; + rsa_ssa.key.n_size = crypto_bignum_num_bytes(key->n); + + if (rsa_ssa.key.n_size > *sig_len) { + CRYPTO_TRACE("Sign length (%zu) too short must be %zu bytes", + *sig_len, rsa_ssa.key.n_size); + *sig_len = rsa_ssa.key.n_size; + return TEE_ERROR_SHORT_BUFFER; + } + + if (!sig) { + CRYPTO_TRACE("Parameter \"sig\" reference error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + /* Prepare the Encoded Signature structure data */ + rsa_ssa.algo = algo; + rsa_ssa.message.data = (uint8_t *)msg; + rsa_ssa.message.length = msg_len; + rsa_ssa.signature.data = (uint8_t *)sig; + rsa_ssa.signature.length = rsa_ssa.key.n_size; + rsa_ssa.salt_len = salt_len; + rsa_ssa.mgf = &drvcrypt_rsa_mgf1; + + ret = TEE_ERROR_NOT_IMPLEMENTED; + if (rsa->optional.ssa_sign) + ret = rsa->optional.ssa_sign(&rsa_ssa); + + if (ret == TEE_ERROR_NOT_IMPLEMENTED) + ret = drvcrypt_rsassa_sign(&rsa_ssa); + + /* Set the signature length */ + *sig_len = rsa_ssa.signature.length; + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("Encode signature algo (0x%" PRIx32 + ") returned 0x%" PRIx32, + algo, ret); + return ret; +} + +TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, + struct rsa_public_key *key, + int salt_len, const uint8_t *msg, + size_t msg_len, const uint8_t *sig, + size_t sig_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_rsa *rsa = NULL; + struct drvcrypt_rsa_ssa rsa_ssa = { }; + + if (!key || !msg || !sig) { + CRYPTO_TRACE("Input parameters reference error"); + goto out; + } + + if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { + /* Prepare the Digest */ + rsa_ssa.hash_algo = TEE_DIGEST_HASH_TO_ALGO(algo); + + /* Check if the message length is digest hash size */ + ret = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), + &rsa_ssa.digest_size); + if (ret != TEE_SUCCESS) + goto out; + + if (msg_len != rsa_ssa.digest_size) { + CRYPTO_TRACE("Input msg length (%zu expected %zu)", + msg_len, rsa_ssa.digest_size); + ret = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + } else { + rsa_ssa.hash_algo = 0; + rsa_ssa.digest_size = 0; + } + + /* Prepare the Key */ + rsa_ssa.key.key = key; + rsa_ssa.key.isprivate = false; + rsa_ssa.key.n_size = crypto_bignum_num_bytes(key->n); + + if (rsa_ssa.key.n_size > sig_len) { + CRYPTO_TRACE("Signature length expected %zu", + rsa_ssa.key.n_size); + ret = TEE_ERROR_SIGNATURE_INVALID; + goto out; + } + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + /* Prepare the Encoded Signature structure data */ + rsa_ssa.algo = algo; + rsa_ssa.message.data = (uint8_t *)msg; + rsa_ssa.message.length = msg_len; + rsa_ssa.signature.data = (uint8_t *)sig; + rsa_ssa.signature.length = sig_len; + rsa_ssa.salt_len = salt_len; + rsa_ssa.mgf = &drvcrypt_rsa_mgf1; + + ret = TEE_ERROR_NOT_IMPLEMENTED; + if (rsa->optional.ssa_verify) + ret = rsa->optional.ssa_verify(&rsa_ssa); + + if (ret == TEE_ERROR_NOT_IMPLEMENTED) + ret = drvcrypt_rsassa_verify(&rsa_ssa); + + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + CRYPTO_TRACE("Signature verif algo (0x%" PRIx32 ") returned 0x%" PRIx32, + algo, ret); + +out: + FTMN_CALLEE_DONE(ret); + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsamgf.c b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsamgf.c new file mode 100644 index 0000000..1663e51 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsamgf.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2020 NXP + * + * RSA Mask Generation function implementation. + */ +#include +#include +#include +#include + +#include "local.h" + +TEE_Result drvcrypt_rsa_mgf1(struct drvcrypt_rsa_mgf *mgf_data) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + void *ctx = NULL; + size_t lastBlock_size = 0; + size_t nbBlock = 0; + uint32_t counter = 0; + uint32_t swapcount = 0; + uint8_t *cur_mask = mgf_data->mask.data; + uint8_t *tmpdigest = NULL; + + CRYPTO_TRACE("Generate Mask (%zu bytes) with seed of %zu bytes", + mgf_data->mask.length, mgf_data->seed.length); + + /* Calculate the number of complet hash digest */ + lastBlock_size = mgf_data->mask.length % mgf_data->digest_size; + if (lastBlock_size) { + /* Allocate a digest buffer for the last block */ + tmpdigest = malloc(mgf_data->digest_size); + if (!tmpdigest) + return TEE_ERROR_OUT_OF_MEMORY; + } + + /* Allocate the Hash Context */ + ret = crypto_hash_alloc_ctx(&ctx, mgf_data->hash_algo); + if (ret != TEE_SUCCESS) + goto exit_mgf; + + nbBlock = (mgf_data->mask.length - lastBlock_size) / + mgf_data->digest_size; + + CRYPTO_TRACE("Nb Loop (%zu bytes) = %zu, last Block = %zu bytes", + mgf_data->digest_size, nbBlock, lastBlock_size); + + for (; counter < nbBlock; + counter++, cur_mask += mgf_data->digest_size) { + swapcount = TEE_U32_TO_BIG_ENDIAN(counter); + + ret = crypto_hash_init(ctx); + if (ret != TEE_SUCCESS) + goto exit_mgf; + + ret = crypto_hash_update(ctx, mgf_data->seed.data, + mgf_data->seed.length); + if (ret != TEE_SUCCESS) + goto exit_mgf; + + ret = crypto_hash_update(ctx, (uint8_t *)&swapcount, + sizeof(swapcount)); + if (ret != TEE_SUCCESS) + goto exit_mgf; + + ret = crypto_hash_final(ctx, cur_mask, mgf_data->digest_size); + if (ret != TEE_SUCCESS) + goto exit_mgf; + } + + if (lastBlock_size) { + CRYPTO_TRACE("Last Block = %zu bytes", lastBlock_size); + + swapcount = TEE_U32_TO_BIG_ENDIAN(counter); + + ret = crypto_hash_init(ctx); + if (ret != TEE_SUCCESS) + goto exit_mgf; + + ret = crypto_hash_update(ctx, mgf_data->seed.data, + mgf_data->seed.length); + if (ret != TEE_SUCCESS) + goto exit_mgf; + + ret = crypto_hash_update(ctx, (uint8_t *)&swapcount, + sizeof(swapcount)); + if (ret != TEE_SUCCESS) + goto exit_mgf; + + ret = crypto_hash_final(ctx, tmpdigest, mgf_data->digest_size); + if (ret != TEE_SUCCESS) + goto exit_mgf; + + memcpy(cur_mask, tmpdigest, lastBlock_size); + } + + ret = TEE_SUCCESS; + +exit_mgf: + crypto_hash_free_ctx(ctx); + free(tmpdigest); + + CRYPTO_TRACE("return 0x%08" PRIx32, ret); + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsassa.c b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsassa.c new file mode 100644 index 0000000..c37670c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/rsassa.c @@ -0,0 +1,932 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2020 NXP + * + * RSA Signature Software common implementation. + * Functions preparing and/or verifying the signature + * encoded string. + * + * PKCS #1 v2.1: RSA Cryptography Standard + * https://www.ietf.org/rfc/rfc3447.txt + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "local.h" + +/* + * PKCS#1 V1.5 - Encode the message in Distinguished Encoding Rules + * (DER) format. + * Refer to EMSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 + * + * @ssa_data RSA data to encode + * @EM [out] Encoded Message + */ +static TEE_Result emsa_pkcs1_v1_5_encode(struct drvcrypt_rsa_ssa *ssa_data, + struct drvcrypt_buf *EM) +{ + const struct drvcrypt_oid *hash_oid = NULL; + size_t ps_size = 0; + uint8_t *buf = NULL; + + hash_oid = drvcrypt_get_alg_hash_oid(ssa_data->hash_algo); + if (!hash_oid) + return TEE_ERROR_NOT_SUPPORTED; + + /* + * Calculate the PS size + * EM Size (modulus size) - 3 bytes - DigestInfo DER format size + */ + ps_size = ssa_data->key.n_size - 3; + ps_size -= ssa_data->digest_size; + ps_size -= 10 + hash_oid->asn1_length; + + CRYPTO_TRACE("PS size = %zu (n %zu)", ps_size, ssa_data->key.n_size); + + /* + * EM = 0x00 || 0x01 || PS || 0x00 || T + * + * where T represent the message DigestInfo in DER: + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * T Length = digest length + oid length + * EM Length = T Length + 11 + PS Length + */ + buf = EM->data; + + /* Set the EM first byte to 0x00 */ + *buf++ = 0x00; + + /* Set the EM second byte to 0x01 */ + *buf++ = 0x01; + + /* Fill PS with 0xFF */ + memset(buf, UINT8_MAX, ps_size); + buf += ps_size; + + /* Set the Byte after PS to 0x00 */ + *buf++ = 0x00; + + /* + * Create the DigestInfo DER Sequence + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + */ + /* SEQUENCE { */ + *buf++ = DRVCRYPT_ASN1_SEQUENCE | DRVCRYPT_ASN1_CONSTRUCTED; + *buf++ = 0x08 + hash_oid->asn1_length + ssa_data->digest_size; + + /* digestAlgorithm AlgorithmIdentifier */ + *buf++ = DRVCRYPT_ASN1_SEQUENCE | DRVCRYPT_ASN1_CONSTRUCTED; + *buf++ = 0x04 + hash_oid->asn1_length; + *buf++ = DRVCRYPT_ASN1_OID; + *buf++ = hash_oid->asn1_length; + + /* digest OCTET STRING */ + memcpy(buf, hash_oid->asn1, hash_oid->asn1_length); + buf += hash_oid->asn1_length; + *buf++ = DRVCRYPT_ASN1_NULL; + *buf++ = 0x00; + *buf++ = DRVCRYPT_ASN1_OCTET_STRING; + *buf++ = ssa_data->digest_size; + /* } */ + + memcpy(buf, ssa_data->message.data, ssa_data->digest_size); + + CRYPTO_DUMPBUF("Encoded Message", EM->data, (size_t)EM->length); + + return TEE_SUCCESS; +} + +/* + * PKCS#1 V1.5 - Encode the message in Distinguished Encoding Rules + * (DER) format. + * Refer to EMSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 + * + * @ssa_data RSA data to encode + * @EM [out] Encoded Message + */ +static TEE_Result +emsa_pkcs1_v1_5_encode_noasn1(struct drvcrypt_rsa_ssa *ssa_data, + struct drvcrypt_buf *EM) +{ + size_t ps_size = 0; + uint8_t *buf = NULL; + + /* + * Calculate the PS size + * EM Size (modulus size) - 3 bytes - Message Length + */ + ps_size = ssa_data->key.n_size - 3; + + if (ps_size < ssa_data->message.length) + return TEE_ERROR_BAD_PARAMETERS; + + ps_size -= ssa_data->message.length; + + CRYPTO_TRACE("PS size = %zu (n %zu)", ps_size, ssa_data->key.n_size); + + /* + * EM = 0x00 || 0x01 || PS || 0x00 || T + * + * T Length = message length + * EM Length = T Length + PS Length + */ + buf = EM->data; + + /* Set the EM first byte to 0x00 */ + *buf++ = 0x00; + + /* Set the EM second byte to 0x01 */ + *buf++ = 0x01; + + /* Fill PS with 0xFF */ + memset(buf, UINT8_MAX, ps_size); + buf += ps_size; + + /* Set the Byte after PS to 0x00 */ + *buf++ = 0x00; + + memcpy(buf, ssa_data->message.data, ssa_data->message.length); + + CRYPTO_DUMPBUF("Encoded Message", EM->data, EM->length); + + return TEE_SUCCESS; +} + +/* + * PKCS#1 V1.5 - Signature of RSA message and encodes the signature. + * Refer to RSASSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 + * + * @ssa_data [in/out] RSA data to sign / Signature + */ +static TEE_Result rsassa_pkcs1_v1_5_sign(struct drvcrypt_rsa_ssa *ssa_data) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_buf EM = { }; + struct drvcrypt_rsa_ed rsa_data = { }; + struct drvcrypt_rsa *rsa = NULL; + + EM.length = ssa_data->key.n_size; + EM.data = malloc(EM.length); + if (!EM.data) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Encode the Message */ + if (ssa_data->algo != TEE_ALG_RSASSA_PKCS1_V1_5) + ret = emsa_pkcs1_v1_5_encode(ssa_data, &EM); + else + ret = emsa_pkcs1_v1_5_encode_noasn1(ssa_data, &EM); + + if (ret != TEE_SUCCESS) + goto out; + + /* + * RSA Encrypt/Decrypt are doing the same operation except + * that decrypt takes a RSA Private key in parameter + */ + rsa_data.key.key = ssa_data->key.key; + rsa_data.key.isprivate = true; + rsa_data.key.n_size = ssa_data->key.n_size; + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (!rsa) { + ret = TEE_ERROR_NOT_IMPLEMENTED; + goto out; + } + + /* Prepare the decryption data parameters */ + rsa_data.rsa_id = DRVCRYPT_RSASSA_PKCS_V1_5; + rsa_data.message.data = ssa_data->signature.data; + rsa_data.message.length = ssa_data->signature.length; + rsa_data.cipher.data = EM.data; + rsa_data.cipher.length = EM.length; + rsa_data.hash_algo = ssa_data->hash_algo; + rsa_data.algo = ssa_data->algo; + + ret = rsa->decrypt(&rsa_data); + + /* Set the message decrypted size */ + ssa_data->signature.length = rsa_data.message.length; + +out: + free(EM.data); + + return ret; +} + +/* + * PKCS#1 V1.5 - Verification of the RSA message's signature. + * Refer to RSASSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 + * + * @ssa_data [int/out] RSA data signed and encoded signature + */ +static TEE_Result rsassa_pkcs1_v1_5_verify(struct drvcrypt_rsa_ssa *ssa_data) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + struct drvcrypt_buf EM = { }; + struct drvcrypt_buf EM_gen = { }; + struct drvcrypt_rsa_ed rsa_data = { }; + struct drvcrypt_rsa *rsa = NULL; + + EM.length = ssa_data->key.n_size; + EM.data = malloc(EM.length); + + if (!EM.data) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto end_verify; + } + + EM_gen.length = ssa_data->key.n_size; + EM_gen.data = malloc(EM.length); + + if (!EM_gen.data) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto end_verify; + } + + /* + * RSA Encrypt/Decrypt are doing the same operation except + * that the encrypt takes a RSA Public key in parameter + */ + rsa_data.key.key = ssa_data->key.key; + rsa_data.key.isprivate = false; + rsa_data.key.n_size = ssa_data->key.n_size; + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + /* Prepare the encryption data parameters */ + rsa_data.rsa_id = DRVCRYPT_RSASSA_PKCS_V1_5; + rsa_data.message.data = ssa_data->signature.data; + rsa_data.message.length = ssa_data->signature.length; + rsa_data.cipher.data = EM.data; + rsa_data.cipher.length = EM.length; + rsa_data.hash_algo = ssa_data->hash_algo; + ret = rsa->encrypt(&rsa_data); + + /* Set the cipher size */ + EM.length = rsa_data.cipher.length; + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + + if (ret != TEE_SUCCESS) + goto end_verify; + + /* Encode the Message */ + if (ssa_data->algo != TEE_ALG_RSASSA_PKCS1_V1_5) + ret = emsa_pkcs1_v1_5_encode(ssa_data, &EM_gen); + else + ret = emsa_pkcs1_v1_5_encode_noasn1(ssa_data, &EM_gen); + + if (ret != TEE_SUCCESS) + goto end_verify; + + /* Check if EM decrypted and EM re-generated are identical */ + ret = TEE_ERROR_SIGNATURE_INVALID; + if (EM.length == EM_gen.length) { + if (!memcmp(EM.data, EM_gen.data, EM.length)) + ret = TEE_SUCCESS; + } + +end_verify: + free(EM.data); + free(EM_gen.data); + + return ret; +} + +/* + * PSS - Encode the message using a Probabilistic Signature Scheme (PSS) + * Refer to EMSA-PSS (encoding) chapter of the PKCS#1 v2.1 + * + * @ssa_data RSA data to encode + * @emBits EM size in bits + * @EM [out] Encoded Message + */ +static TEE_Result emsa_pss_encode(struct drvcrypt_rsa_ssa *ssa_data, + size_t emBits, struct drvcrypt_buf *EM) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct drvcrypt_rsa_mgf mgf_data = { }; + struct drvcrypt_buf hash = { }; + struct drvcrypt_buf dbMask = { }; + struct drvcrypt_buf DB = { }; + size_t db_size = 0; + size_t ps_size = 0; + size_t msg_size = 0; + uint8_t *buf = NULL; + uint8_t *msg_db = NULL; + uint8_t *salt = NULL; + struct drvcrypt_mod_op mod_op = { }; + + /* + * Build EM = maskedDB || H || 0xbc + * + * where + * maskedDB = DB xor dbMask + * DB = PS || 0x01 || salt + * dbMask = MGF(H, emLen - hLen - 1) + * + * H = Hash(M') + * M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt + * + * PS size = emLen - sLen - hLen - 2 (may be = 0) + */ + + /* + * Calculate the M' and DB size to allocate a temporary buffer + * used for both object + */ + ps_size = EM->length - ssa_data->digest_size - ssa_data->salt_len - 2; + db_size = EM->length - ssa_data->digest_size - 1; + msg_size = 8 + ssa_data->digest_size + ssa_data->salt_len; + + CRYPTO_TRACE("PS Len = %zu, DB Len = %zu, M' Len = %zu", ps_size, + db_size, msg_size); + + msg_db = malloc(MAX(db_size, msg_size)); + if (!msg_db) + return TEE_ERROR_OUT_OF_MEMORY; + + if (ssa_data->salt_len) { + salt = malloc(ssa_data->salt_len); + + if (!salt) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto end_pss_encode; + } + } + + /* + * Step 4 and 5 + * Generate the M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt + * + * where + * mHash is the input message (already hash) + * salt is a random number of salt_len (input data) can be empty + */ + buf = msg_db; + + memset(buf, 0, 8); + buf += 8; + + memcpy(buf, ssa_data->message.data, ssa_data->message.length); + buf += ssa_data->message.length; + + /* Get salt random number if salt length not 0 */ + if (ssa_data->salt_len) { + ret = crypto_rng_read(salt, ssa_data->salt_len); + CRYPTO_TRACE("Get salt of %zu bytes (ret = 0x%08" PRIx32 ")", + ssa_data->salt_len, ret); + if (ret != TEE_SUCCESS) + goto end_pss_encode; + + memcpy(buf, salt, ssa_data->salt_len); + } + + /* + * Step 6 + * Hash the M' generated new message + * H = hash(M') + */ + hash.data = &EM->data[db_size]; + hash.length = ssa_data->digest_size; + + ret = tee_hash_createdigest(ssa_data->hash_algo, msg_db, msg_size, + hash.data, hash.length); + + CRYPTO_TRACE("H = hash(M') returned 0x%08" PRIx32, ret); + if (ret != TEE_SUCCESS) + goto end_pss_encode; + + CRYPTO_DUMPBUF("H = hash(M')", hash.data, hash.length); + + /* + * Step 7 and 8 + * DB = PS || 0x01 || salt + */ + buf = msg_db; + if (ps_size) + memset(buf, 0, ps_size); + buf += ps_size; + *buf++ = 0x01; + + if (ssa_data->salt_len) + memcpy(buf, salt, ssa_data->salt_len); + + DB.data = msg_db; + DB.length = db_size; + + CRYPTO_DUMPBUF("DB", DB.data, DB.length); + + /* + * Step 9 + * Generate a Mask of the seed value + * dbMask = MGF(H, emLen - hLen - 1) + * + * Note: Will use the same buffer for the dbMask and maskedDB + * maskedDB is in the EM output + */ + dbMask.data = EM->data; + dbMask.length = db_size; + + mgf_data.hash_algo = ssa_data->hash_algo; + mgf_data.digest_size = ssa_data->digest_size; + mgf_data.seed.data = hash.data; + mgf_data.seed.length = hash.length; + mgf_data.mask.data = dbMask.data; + mgf_data.mask.length = dbMask.length; + ret = ssa_data->mgf(&mgf_data); + + CRYPTO_TRACE("dbMask = MGF(H, emLen - hLen - 1) returned 0x%08" PRIx32, + ret); + if (ret != TEE_SUCCESS) + goto end_pss_encode; + + CRYPTO_DUMPBUF("dbMask", dbMask.data, dbMask.length); + + /* + * Step 10 + * maskedDB = DB xor dbMask + */ + mod_op.n.length = dbMask.length; + mod_op.a.data = DB.data; + mod_op.a.length = DB.length; + mod_op.b.data = dbMask.data; + mod_op.b.length = dbMask.length; + mod_op.result.data = dbMask.data; + mod_op.result.length = dbMask.length; + + ret = drvcrypt_xor_mod_n(&mod_op); + CRYPTO_TRACE("maskedDB = DB xor dbMask returned 0x%08" PRIx32, ret); + if (ret != TEE_SUCCESS) + goto end_pss_encode; + + CRYPTO_DUMPBUF("maskedDB", dbMask.data, dbMask.length); + + /* + * Step 11 + * Set the leftmost 8emLen - emBits of the leftmost octet + * in maskedDB to 0' + */ + EM->data[0] &= (UINT8_MAX >> ((EM->length * 8) - emBits)); + + /* + * Step 12 + * EM = maskedDB || H || 0xbc + */ + EM->data[EM->length - 1] = 0xbc; + + CRYPTO_DUMPBUF("EM", EM->data, EM->length); + + ret = TEE_SUCCESS; +end_pss_encode: + free(msg_db); + free(salt); + + return ret; +} + +/* + * PSS - Verify the message using a Probabilistic Signature Scheme (PSS) + * Refer to EMSA-PSS (verification) chapter of the PKCS#1 v2.1 + * + * @ssa_data RSA data to encode + * @emBits EM size in bits + * @EM [out] Encoded Message + */ +static TEE_Result emsa_pss_verify(struct drvcrypt_rsa_ssa *ssa_data, + size_t emBits, struct drvcrypt_buf *EM) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct drvcrypt_rsa_mgf mgf_data = { }; + struct drvcrypt_buf hash = { }; + struct drvcrypt_buf hash_gen = { }; + size_t db_size = 0; + size_t ps_size = 0; + size_t msg_size = 0; + uint8_t *msg_db = NULL; + uint8_t *salt = NULL; + uint8_t *buf = NULL; + struct drvcrypt_mod_op mod_op = { }; + + /* + * EM = maskedDB || H || 0xbc + * + * where + * maskedDB = DB xor dbMask + * DB = PS || 0x01 || salt + * dbMask = MGF(H, emLen - hLen - 1) + * + * H = Hash(M') + * M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt + * + * PS size = emLen - sLen - hLen - 2 (may be = 0) + */ + + /* + * Calculate the M' and DB size to allocate a temporary buffer + * used for both object + */ + ps_size = EM->length - ssa_data->digest_size - ssa_data->salt_len - 2; + db_size = EM->length - ssa_data->digest_size - 1; + msg_size = 8 + ssa_data->digest_size + ssa_data->salt_len; + + CRYPTO_TRACE("PS Len = %zu, DB Len = %zu, M' Len = %zu", ps_size, + db_size, msg_size); + + msg_db = malloc(MAX(db_size, msg_size)); + if (!msg_db) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * Step 4 + * Check if rightmost octet of EM is 0xbc + */ + if (EM->data[EM->length - 1] != 0xbc) { + CRYPTO_TRACE("rigthmost octet != 0xbc (0x%" PRIX8 ")", + EM->data[EM->length - 1]); + ret = TEE_ERROR_SIGNATURE_INVALID; + goto end_pss_verify; + } + + /* + * Step 6 + * Check if the leftmost 8emLen - emBits of the leftmost octet + * in maskedDB are 0's + */ + if (EM->data[0] & ~(UINT8_MAX >> (EM->length * 8 - emBits))) { + CRYPTO_TRACE("Error leftmost octet maskedDB not 0's"); + CRYPTO_TRACE("EM[0] = 0x%" PRIX8 + " - EM Len = %zu, emBits = %zu", + EM->data[0], EM->length, emBits); + ret = TEE_ERROR_SIGNATURE_INVALID; + goto end_pss_verify; + } + + hash.data = &EM->data[db_size]; + hash.length = ssa_data->digest_size; + + /* + * Step 7 + * dbMask = MGF(H, emLen - hLen - 1) + * + * Note: Will use the same buffer for the dbMask and DB + */ + mgf_data.hash_algo = ssa_data->hash_algo; + mgf_data.digest_size = ssa_data->digest_size; + mgf_data.seed.data = hash.data; + mgf_data.seed.length = hash.length; + mgf_data.mask.data = msg_db; + mgf_data.mask.length = db_size; + ret = ssa_data->mgf(&mgf_data); + + CRYPTO_TRACE("dbMask = MGF(H, emLen - hLen - 1) returned 0x%08" PRIx32, + ret); + if (ret != TEE_SUCCESS) + goto end_pss_verify; + + CRYPTO_DUMPBUF("dbMask", msg_db, db_size); + + /* + * Step 8 + * DB = maskedDB xor dbMask + * + * + * Note: maskedDB is in the EM input + */ + mod_op.n.length = db_size; + mod_op.a.data = EM->data; + mod_op.a.length = db_size; + mod_op.b.data = msg_db; + mod_op.b.length = db_size; + mod_op.result.data = msg_db; + mod_op.result.length = db_size; + + ret = drvcrypt_xor_mod_n(&mod_op); + CRYPTO_TRACE("DB = maskedDB xor dbMask returned 0x%08" PRIx32, ret); + if (ret != TEE_SUCCESS) + goto end_pss_verify; + + /* + * Step 9 + * Set the leftmost 8emLen - emBits of the leftmost octet in + * DB to zero + */ + *msg_db &= UINT8_MAX >> (EM->length * 8 - emBits); + + CRYPTO_DUMPBUF("DB", msg_db, db_size); + + /* + * Step 10 + * Expected to have + * DB = PS || 0x01 || salt + * + * PS must be 0 + * PS size = emLen - sLen - hLen - 2 (may be = 0) + */ + buf = msg_db; + while (buf < msg_db + ps_size) { + if (*buf++ != 0) { + ret = TEE_ERROR_SIGNATURE_INVALID; + goto end_pss_verify; + } + } + + if (*buf++ != 0x01) { + ret = TEE_ERROR_SIGNATURE_INVALID; + goto end_pss_verify; + } + + /* + * Step 11 + * Get the salt value + */ + if (ssa_data->salt_len) { + salt = malloc(ssa_data->salt_len); + if (!salt) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto end_pss_verify; + } + + memcpy(salt, buf, ssa_data->salt_len); + } + + /* + * Step 12 + * Generate the M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt + * + * where + * mHash is the input message (already hash) + * salt is a random number of salt_len (input data) can be empty + */ + buf = msg_db; + + memset(buf, 0, 8); + buf += 8; + + memcpy(buf, ssa_data->message.data, ssa_data->message.length); + buf += ssa_data->message.length; + + if (ssa_data->salt_len) + memcpy(buf, salt, ssa_data->salt_len); + + /* + * Step 13 + * Hash the M' generated new message + * H' = hash(M') + * + * Note: reuse the msg_db buffer as Hash result + */ + hash_gen.data = msg_db; + hash_gen.length = ssa_data->digest_size; + + ret = tee_hash_createdigest(ssa_data->hash_algo, msg_db, msg_size, + hash_gen.data, hash_gen.length); + + CRYPTO_TRACE("H' = hash(M') returned 0x%08" PRIx32, ret); + if (ret != TEE_SUCCESS) + goto end_pss_verify; + + CRYPTO_DUMPBUF("H' = hash(M')", hash_gen.data, hash_gen.length); + + /* + * Step 14 + * Compare H and H' + */ + ret = TEE_ERROR_SIGNATURE_INVALID; + if (!memcmp(hash_gen.data, hash.data, hash_gen.length)) + ret = TEE_SUCCESS; + +end_pss_verify: + free(msg_db); + free(salt); + + return ret; +} + +/* + * PSS - Signature of RSA message and encodes the signature. + * Refer to RSASSA-PSS chapter of the PKCS#1 v2.1 + * + * @ssa_data [in/out] RSA data to sign / Signature + */ +static TEE_Result rsassa_pss_sign(struct drvcrypt_rsa_ssa *ssa_data) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct rsa_keypair *key = NULL; + struct drvcrypt_buf EM = { }; + size_t modBits = 0; + struct drvcrypt_rsa_ed rsa_data = { }; + struct drvcrypt_rsa *rsa = NULL; + + key = ssa_data->key.key; + + /* Get modulus length in bits */ + modBits = crypto_bignum_num_bits(key->n); + if (modBits <= 0) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * EM Length = (modBits - 1) / 8 + * if (modBits - 1) is not divisible by 8, one more byte is needed + */ + modBits--; + EM.length = ROUNDUP(modBits, 8) / 8; + + if (EM.length < ssa_data->digest_size + ssa_data->salt_len + 2) + return TEE_ERROR_BAD_PARAMETERS; + + EM.data = malloc(EM.length); + if (!EM.data) + return TEE_ERROR_OUT_OF_MEMORY; + + CRYPTO_TRACE("modBits = %zu, hence EM Length = %zu", modBits + 1, + EM.length); + + /* Encode the Message */ + ret = emsa_pss_encode(ssa_data, modBits, &EM); + CRYPTO_TRACE("EMSA PSS Encode returned 0x%08" PRIx32, ret); + + /* + * RSA Encrypt/Decrypt are doing the same operation + * expect that the decrypt takes a RSA Private key in parameter + */ + if (ret == TEE_SUCCESS) { + rsa_data.key.key = ssa_data->key.key; + rsa_data.key.isprivate = true; + rsa_data.key.n_size = ssa_data->key.n_size; + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + /* Prepare the decryption data parameters */ + rsa_data.rsa_id = DRVCRYPT_RSASSA_PSS; + rsa_data.message.data = ssa_data->signature.data; + rsa_data.message.length = ssa_data->signature.length; + rsa_data.cipher.data = EM.data; + rsa_data.cipher.length = EM.length; + rsa_data.algo = ssa_data->algo; + + ret = rsa->decrypt(&rsa_data); + + /* Set the message decrypted size */ + ssa_data->signature.length = rsa_data.message.length; + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + } + } + free(EM.data); + + return ret; +} + +/* + * PSS - Signature verification of RSA message. + * Refer to RSASSA-PSS chapter of the PKCS#1 v2.1 + * + * @ssa_data [in/out] RSA Signature vs. message to verify + */ +static TEE_Result rsassa_pss_verify(struct drvcrypt_rsa_ssa *ssa_data) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct rsa_public_key *key = NULL; + struct drvcrypt_buf EM = { }; + size_t modBits = 0; + struct drvcrypt_rsa_ed rsa_data = { }; + struct drvcrypt_rsa *rsa = NULL; + + key = ssa_data->key.key; + + /* Get modulus length in bits */ + modBits = crypto_bignum_num_bits(key->n); + if (modBits <= 0) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * EM Length = (modBits - 1) / 8 + * if (modBits - 1) is not divisible by 8, one more byte is needed + */ + modBits--; + EM.length = ROUNDUP(modBits, 8) / 8; + + if (EM.length < ssa_data->digest_size + ssa_data->salt_len + 2) + return TEE_ERROR_BAD_PARAMETERS; + + EM.data = malloc(EM.length); + if (!EM.data) + return TEE_ERROR_OUT_OF_MEMORY; + + CRYPTO_TRACE("modBits = %zu, hence EM Length = %zu", modBits + 1, + EM.length); + + /* + * RSA Encrypt/Decrypt are doing the same operation + * expect that the encrypt takes a RSA Public key in parameter + */ + rsa_data.key.key = ssa_data->key.key; + rsa_data.key.isprivate = false; + rsa_data.key.n_size = ssa_data->key.n_size; + + rsa = drvcrypt_get_ops(CRYPTO_RSA); + if (rsa) { + /* Prepare the encryption data parameters */ + rsa_data.rsa_id = DRVCRYPT_RSASSA_PSS; + rsa_data.message.data = ssa_data->signature.data; + rsa_data.message.length = ssa_data->signature.length; + rsa_data.cipher.data = EM.data; + rsa_data.cipher.length = EM.length; + rsa_data.algo = ssa_data->algo; + + ret = rsa->encrypt(&rsa_data); + + /* Set the cipher size */ + EM.length = rsa_data.cipher.length; + } else { + ret = TEE_ERROR_NOT_IMPLEMENTED; + goto end_pss_verify; + } + + if (ret == TEE_SUCCESS) { + /* Verify the Message */ + ret = emsa_pss_verify(ssa_data, modBits, &EM); + CRYPTO_TRACE("EMSA PSS Verify returned 0x%08" PRIx32, ret); + } else { + CRYPTO_TRACE("RSA NO PAD returned 0x%08" PRIx32, ret); + ret = TEE_ERROR_SIGNATURE_INVALID; + } + +end_pss_verify: + free(EM.data); + + return ret; +} + +TEE_Result drvcrypt_rsassa_sign(struct drvcrypt_rsa_ssa *ssa_data) +{ + switch (ssa_data->algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5: + 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: + return rsassa_pkcs1_v1_5_sign(ssa_data); + + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: + 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: + return rsassa_pss_sign(ssa_data); + + default: + break; + } + + return TEE_ERROR_BAD_PARAMETERS; +} + +TEE_Result drvcrypt_rsassa_verify(struct drvcrypt_rsa_ssa *ssa_data) +{ + switch (ssa_data->algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5: + 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: + return rsassa_pkcs1_v1_5_verify(ssa_data); + + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: + 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: + return rsassa_pss_verify(ssa_data); + + default: + break; + } + + return TEE_ERROR_BAD_PARAMETERS; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/acipher/sub.mk b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/sub.mk new file mode 100644 index 0000000..c6a7378 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/acipher/sub.mk @@ -0,0 +1,4 @@ +srcs-$(CFG_CRYPTO_DRV_RSA) += rsa.c rsamgf.c rsassa.c +srcs-$(CFG_CRYPTO_DRV_ECC) += ecc.c +srcs-$(CFG_CRYPTO_DRV_DH) += dh.c +srcs-$(CFG_CRYPTO_DRV_DSA) += dsa.c diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/authenc/authenc.c b/optee/optee_os/core/drivers/crypto/crypto_api/authenc/authenc.c new file mode 100644 index 0000000..6563e68 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/authenc/authenc.c @@ -0,0 +1,332 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * Crypto authenc interface implementation to enable HW driver. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct crypto_authenc_ops authenc_ops; + +/* + * Returns the reference to the driver context + * + * @ctx Reference the API context pointer + */ +static struct crypto_authenc *to_authenc_ctx(struct crypto_authenc_ctx *ctx) +{ + assert(ctx && ctx->ops == &authenc_ops); + + return container_of(ctx, struct crypto_authenc, authenc_ctx); +} + +/* + * Free authenc context + * + * @ctx Reference the API context pointer + */ +static void authenc_free_ctx(struct crypto_authenc_ctx *ctx) +{ + struct crypto_authenc *authenc = to_authenc_ctx(ctx); + + if (authenc->op && authenc->op->free_ctx) + authenc->op->free_ctx(authenc->ctx); + + free(authenc); +} + +/* + * Copy authenc context + * + * @dst_ctx [out] Reference the API context pointer destination + * @src_ctx Reference the API context pointer source + */ +static void authenc_copy_state(struct crypto_authenc_ctx *dst_ctx, + struct crypto_authenc_ctx *src_ctx) +{ + struct crypto_authenc *authenc_src = to_authenc_ctx(src_ctx); + struct crypto_authenc *authenc_dst = to_authenc_ctx(dst_ctx); + + if (authenc_src->op && authenc_src->op->copy_state) + authenc_src->op->copy_state(authenc_dst->ctx, authenc_src->ctx); +} + +/* + * Initialization of the authenc operation + * + * @ctx Reference the API context pointer + * @mode Operation mode + * @key Key + * @key_len Length of the key + * @nonce Nonce + * @nonce_len Length of the nonce + * @tag_len Length of the requested tag + * @aad_len Length of the associated authenticated data + * @payload_len Length of payload + */ +static TEE_Result authenc_init(struct crypto_authenc_ctx *ctx, + 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 ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_authenc *authenc = to_authenc_ctx(ctx); + + if ((!key && key_len) || (!nonce && nonce_len)) { + CRYPTO_TRACE("One of the key is not correct"); + CRYPTO_TRACE("key @%p-%zu bytes", key, key_len); + CRYPTO_TRACE("nonce @%p-%zu bytes", nonce, nonce_len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (authenc->op && authenc->op->init) { + struct drvcrypt_authenc_init dinit = { + .ctx = authenc->ctx, + .encrypt = (mode == TEE_MODE_ENCRYPT), + .key.data = (uint8_t *)key, + .key.length = key_len, + .nonce.data = (uint8_t *)nonce, + .nonce.length = nonce_len, + .tag_len = tag_len, + .aad_len = aad_len, + .payload_len = payload_len, + }; + + ret = authenc->op->init(&dinit); + } + + CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); + return ret; +} + +/* + * Update Additional Authenticated Data part of the authenc operation + * + * @ctx Reference the API context pointer + * @data Data to authenticate without encrypt/decrypt (AAD) + * @len AAD length in bytes + */ +static TEE_Result authenc_update_aad(struct crypto_authenc_ctx *ctx, + const uint8_t *data, size_t len) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_authenc *authenc = to_authenc_ctx(ctx); + + if (!data && len) { + CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (authenc->op && authenc->op->update_aad) { + struct drvcrypt_authenc_update_aad dupdate = { + .ctx = authenc->ctx, + .aad.data = (uint8_t *)data, + .aad.length = len, + }; + + ret = authenc->op->update_aad(&dupdate); + } + + CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); + return ret; +} + +/* + * Update payload part of the authenc operation + * + * @ctx Reference the API context pointer + * @data Data to authenticate and encrypt/decrypt + * @len Length of the input data and output result + * @dst [out] Output data of the operation + */ +static TEE_Result authenc_update_payload(struct crypto_authenc_ctx *ctx, + TEE_OperationMode mode, + const uint8_t *data, + size_t len, uint8_t *dst) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_authenc *authenc = to_authenc_ctx(ctx); + + if (!dst) { + CRYPTO_TRACE("Destination buffer error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!data && len) { + CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (authenc->op && authenc->op->update_payload) { + struct drvcrypt_authenc_update_payload dupdate = { + .ctx = authenc->ctx, + .encrypt = (mode == TEE_MODE_ENCRYPT), + .src.data = (uint8_t *)data, + .src.length = len, + .dst.data = dst, + .dst.length = len, + }; + + ret = authenc->op->update_payload(&dupdate); + } + + CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); + return ret; +} + +/* + * Last block for the authenc encrypt and get tag operation + * + * @ctx Reference the API context pointer + * @data Data to authenticate and encrypt (can be NULL) + * @len Length of the input data and output result (can be 0) + * @dst [out] Output data of the operation + * @tag [out] Output tag of the operation + * @tag_len [in/out] in: size of the dst_tag buffer + * out: size of the computed tag + */ +static TEE_Result authenc_enc_final(struct crypto_authenc_ctx *ctx, + const uint8_t *data, size_t len, + uint8_t *dst, uint8_t *tag, + size_t *tag_len) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_authenc *authenc = to_authenc_ctx(ctx); + + if (!dst && len) { + CRYPTO_TRACE("Bad output @%p-%zu bytes", dst, len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!data && len) { + CRYPTO_TRACE("Bad input @%p-%zu bytes", data, len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (authenc->op && authenc->op->enc_final) { + struct drvcrypt_authenc_final dfinal = { + .ctx = authenc->ctx, + .src.data = (uint8_t *)data, + .src.length = len, + .dst.data = dst, + .dst.length = len, + .tag.data = tag, + .tag.length = *tag_len + }; + + ret = authenc->op->enc_final(&dfinal); + if (ret == TEE_SUCCESS) + *tag_len = dfinal.tag.length; + } + + CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); + return ret; +} + +/* + * Last block for the authenc decrypt and check tag operation + * + * @ctx Reference the API context pointer + * @src_data Data to authenticate and encrypt (can be NULL) + * @len Length of the input data and output result (can be 0) + * @dst [out] Output data of the operation + * @tag Tag to check at end of operation + * @tag_len Length of @tag + */ +static TEE_Result authenc_dec_final(struct crypto_authenc_ctx *ctx, + const uint8_t *data, size_t len, + uint8_t *dst, const uint8_t *tag, + size_t tag_len) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_authenc *authenc = to_authenc_ctx(ctx); + + if (!dst && len) { + CRYPTO_TRACE("Bad output @%p-%zu bytes", dst, len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!data && len) { + CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (authenc->op && authenc->op->dec_final) { + struct drvcrypt_authenc_final dfinal = { + .ctx = authenc->ctx, + .src.data = (uint8_t *)data, + .src.length = len, + .dst.data = dst, + .dst.length = len, + .tag.data = (uint8_t *)tag, + .tag.length = tag_len + }; + + ret = authenc->op->dec_final(&dfinal); + } + + CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); + return ret; +} + +/* + * Finalize the authenc operation + * + * @ctx Reference the API context pointer + */ +static void authenc_final(struct crypto_authenc_ctx *ctx) +{ + struct crypto_authenc *authenc = to_authenc_ctx(ctx); + + if (authenc->op && authenc->op->final) + authenc->op->final(authenc->ctx); +} + +static const struct crypto_authenc_ops authenc_ops = { + .init = authenc_init, + .update_aad = authenc_update_aad, + .update_payload = authenc_update_payload, + .enc_final = authenc_enc_final, + .dec_final = authenc_dec_final, + .final = authenc_final, + .free_ctx = authenc_free_ctx, + .copy_state = authenc_copy_state, +}; + +TEE_Result drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx **ctx, + uint32_t algo) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_authenc *authenc = NULL; + + CRYPTO_TRACE("authenc alloc_ctx algo 0x%" PRIx32, algo); + + assert(ctx); + + authenc = calloc(1, sizeof(*authenc)); + if (!authenc) + return TEE_ERROR_OUT_OF_MEMORY; + + authenc->op = drvcrypt_get_ops(CRYPTO_AUTHENC); + if (authenc->op && authenc->op->alloc_ctx) + ret = authenc->op->alloc_ctx(&authenc->ctx, algo); + + if (ret != TEE_SUCCESS) { + free(authenc); + } else { + authenc->authenc_ctx.ops = &authenc_ops; + *ctx = &authenc->authenc_ctx; + } + + CRYPTO_TRACE("authenc alloc_ctx ret 0x%" PRIx32, ret); + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/authenc/sub.mk b/optee/optee_os/core/drivers/crypto/crypto_api/authenc/sub.mk new file mode 100644 index 0000000..1065a67 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/authenc/sub.mk @@ -0,0 +1 @@ +srcs-y += authenc.c diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c b/optee/optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c new file mode 100644 index 0000000..3d9d548 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/cipher/cipher.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2020 NXP + * + * Crypto Cipher interface implementation to enable HW driver. + */ +#include +#include +#include +#include +#include +#include +#include + +static const struct crypto_cipher_ops cipher_ops; + +/* + * Returns the reference to the driver context + * + * @ctx Reference the API context pointer + */ +static struct crypto_cipher *to_cipher_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &cipher_ops); + + return container_of(ctx, struct crypto_cipher, cipher_ctx); +} + +/* + * Free cipher context + * + * @ctx Reference the API context pointer + */ +static void cipher_free_ctx(struct crypto_cipher_ctx *ctx) +{ + struct crypto_cipher *cipher = to_cipher_ctx(ctx); + + if (cipher->op && cipher->op->free_ctx) + cipher->op->free_ctx(cipher->ctx); + + free(cipher); +} + +/* + * Copy cipher context + * + * @dst_ctx [out] Reference the API context pointer destination + * @src_ctx Reference the API context pointer source + */ +static void cipher_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct crypto_cipher *cipher_src = to_cipher_ctx(src_ctx); + struct crypto_cipher *cipher_dst = to_cipher_ctx(dst_ctx); + + if (cipher_src->op && cipher_src->op->copy_state) + cipher_src->op->copy_state(cipher_dst->ctx, cipher_src->ctx); +} + +/* + * Initialization of the cipher operation + * + * @ctx Reference the API context pointer + * @mode Operation mode + * @key1 First Key + * @key1_len Length of the first key + * @key2 Second Key + * @key2_len Length of the second key + * @iv Initial Vector + * @iv_len Length of the IV + */ +static TEE_Result cipher_init(struct crypto_cipher_ctx *ctx, + 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 ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_cipher *cipher = to_cipher_ctx(ctx); + + if ((!key1 && key1_len) || (!key2 && key2_len) || (!iv && iv_len)) { + CRYPTO_TRACE("One of the key is not correct"); + CRYPTO_TRACE("key1 @%p-%zu bytes", key1, key1_len); + CRYPTO_TRACE("key2 @%p-%zu bytes", key1, key1_len); + CRYPTO_TRACE("iv @%p-%zu bytes", iv, iv_len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (cipher->op && cipher->op->init) { + struct drvcrypt_cipher_init dinit = { + .ctx = cipher->ctx, + .encrypt = (mode == TEE_MODE_ENCRYPT), + .key1.data = (uint8_t *)key1, + .key1.length = key1_len, + .key2.data = (uint8_t *)key2, + .key2.length = key2_len, + .iv.data = (uint8_t *)iv, + .iv.length = iv_len, + }; + + ret = cipher->op->init(&dinit); + } + + CRYPTO_TRACE("cipher ret 0x%" PRIX32, ret); + return ret; +} + +/* + * Update of the cipher operation + * + * @ctx Reference the API context pointer + * @last_block True if last block to handle + * @data Data to encrypt/decrypt + * @len Length of the input data and output result + * @dst [out] Output data of the operation + */ +static TEE_Result cipher_update(struct crypto_cipher_ctx *ctx, bool last_block, + const uint8_t *data, size_t len, uint8_t *dst) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_cipher *cipher = to_cipher_ctx(ctx); + + if (!dst) { + CRYPTO_TRACE("Destination buffer error"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!data && len) { + CRYPTO_TRACE("Bad data data @%p-%zu bytes", data, len); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (cipher->op && cipher->op->update) { + struct drvcrypt_cipher_update dupdate = { + .ctx = cipher->ctx, + .last = last_block, + .src.data = (uint8_t *)data, + .src.length = len, + .dst.data = dst, + .dst.length = len, + }; + + ret = cipher->op->update(&dupdate); + } + + CRYPTO_TRACE("cipher ret 0x%" PRIX32, ret); + return ret; +} + +/* + * Finalize the cipher operation + * + * @ctx Reference the API context pointer + */ +static void cipher_final(struct crypto_cipher_ctx *ctx) +{ + struct crypto_cipher *cipher = to_cipher_ctx(ctx); + + if (cipher->op && cipher->op->final) + cipher->op->final(cipher->ctx); +} + +static const struct crypto_cipher_ops cipher_ops = { + .init = cipher_init, + .update = cipher_update, + .final = cipher_final, + .free_ctx = cipher_free_ctx, + .copy_state = cipher_copy_state, +}; + +TEE_Result drvcrypt_cipher_alloc_ctx(struct crypto_cipher_ctx **ctx, + uint32_t algo) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + struct crypto_cipher *cipher = NULL; + + CRYPTO_TRACE("Cipher alloc_ctx algo 0x%" PRIX32, algo); + + assert(ctx); + + cipher = calloc(1, sizeof(*cipher)); + if (!cipher) + return TEE_ERROR_OUT_OF_MEMORY; + + cipher->op = drvcrypt_get_ops(CRYPTO_CIPHER); + if (cipher->op && cipher->op->alloc_ctx) + ret = cipher->op->alloc_ctx(&cipher->ctx, algo); + + if (ret != TEE_SUCCESS) { + free(cipher); + } else { + cipher->cipher_ctx.ops = &cipher_ops; + *ctx = &cipher->cipher_ctx; + } + + CRYPTO_TRACE("Cipher alloc_ctx ret 0x%" PRIX32, ret); + + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/cipher/sub.mk b/optee/optee_os/core/drivers/crypto/crypto_api/cipher/sub.mk new file mode 100644 index 0000000..e17a654 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/cipher/sub.mk @@ -0,0 +1 @@ +srcs-y += cipher.c diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/drvcrypt.c b/optee/optee_os/core/drivers/crypto/crypto_api/drvcrypt.c new file mode 100644 index 0000000..94bb9f9 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/drvcrypt.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief This driver interfaces TEE Cryptographic API crypto_* + */ +#include +#include +#include + +static void *crypt_algo[CRYPTO_MAX_ALGO]; + +TEE_Result drvcrypt_register(enum drvcrypt_algo_id algo_id, void *ops) +{ + if (!crypt_algo[algo_id]) { + CRYPTO_TRACE("Registering module id %d with 0x%p", algo_id, + ops); + crypt_algo[algo_id] = ops; + return TEE_SUCCESS; + } + + CRYPTO_TRACE("Fail to register module id %d with 0x%p", algo_id, ops); + return TEE_ERROR_GENERIC; +} + +void drvcrypt_register_change(enum drvcrypt_algo_id algo_id, void *ops) +{ + CRYPTO_TRACE("Change registered module id %d with 0x%p", algo_id, ops); + crypt_algo[algo_id] = ops; +} + +void *drvcrypt_get_ops(enum drvcrypt_algo_id algo_id) +{ + return crypt_algo[algo_id]; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/hash/hash.c b/optee/optee_os/core/drivers/crypto/crypto_api/hash/hash.c new file mode 100644 index 0000000..51db02f --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/hash/hash.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019 NXP + * + * Brief Crypto Hash interface implementation to enable HW driver. + */ +#include +#include +#include +#include + +TEE_Result drvcrypt_hash_alloc_ctx(struct crypto_hash_ctx **ctx, uint32_t algo) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + hw_hash_allocate hash_alloc = NULL; + + CRYPTO_TRACE("hash alloc_ctx algo 0x%" PRIX32, algo); + + assert(ctx); + + hash_alloc = drvcrypt_get_ops(CRYPTO_HASH); + + if (hash_alloc) + ret = hash_alloc(ctx, algo); + + CRYPTO_TRACE("hash alloc_ctx ret 0x%" PRIX32, ret); + + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/hash/sub.mk b/optee/optee_os/core/drivers/crypto/crypto_api/hash/sub.mk new file mode 100644 index 0000000..8336568 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/hash/sub.mk @@ -0,0 +1 @@ +srcs-y += hash.c diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h new file mode 100644 index 0000000..6eab9d2 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief Crypto Driver exported constants and interfaces. + */ +#ifndef __DRVCRYPT_H__ +#define __DRVCRYPT_H__ + +#include +#include +#include + +/* + * Debug Macros function of Crypto Driver Debug Level setting + * The CFG_CRYPTO_DRV_DBG is a bit mask 32 bits value defined + * as followed: + */ +#define DRV_DBG_TRACE BIT32(0) /* Driver trace */ +#define DRV_DBG_BUF BIT32(1) /* Driver dump Buffer */ + +#if (CFG_CRYPTO_DRIVER_DEBUG & DRV_DBG_TRACE) +#define CRYPTO_TRACE DMSG +#else +#define CRYPTO_TRACE(...) +#endif +#if (CFG_CRYPTO_DRIVER_DEBUG & DRV_DBG_BUF) +#define CRYPTO_DUMPBUF(title, buf, len) \ + do { \ + __typeof__(buf) _buf = (buf); \ + __typeof__(len) _len = (len); \ + CRYPTO_TRACE("%s @%p: %zu", title, _buf, _len); \ + dhex_dump(NULL, 0, 0, _buf, _len); \ + } while (0) +#else +#define CRYPTO_DUMPBUF(...) +#endif + +/* + * Definition of a crypto buffer type + */ +struct drvcrypt_buf { + uint8_t *data; + size_t length; +}; + +/* + * Crypto Library Algorithm enumeration + */ +enum drvcrypt_algo_id { + CRYPTO_HASH = 0, /* Hash driver */ + CRYPTO_HMAC, /* HMAC driver */ + CRYPTO_CMAC, /* CMAC driver */ + CRYPTO_RSA, /* Asymmetric RSA driver */ + CRYPTO_MATH, /* Mathematical driver */ + CRYPTO_CIPHER, /* Cipher driver */ + CRYPTO_ECC, /* Asymmetric ECC driver */ + CRYPTO_DH, /* Asymmetric DH driver */ + CRYPTO_DSA, /* Asymmetric DSA driver */ + CRYPTO_AUTHENC, /* Authenticated Encryption driver */ + CRYPTO_MAX_ALGO /* Maximum number of algo supported */ +}; + +/* + * Register the Cryptographic's operation in the table of modules + * + * @algo_id ID of the Cryptographic module + * @ops Operation (function/structure) to register + */ +TEE_Result drvcrypt_register(enum drvcrypt_algo_id algo_id, void *ops); + +/* + * Modify the Cryptographic algorithm in the table of modules + * + * @algo_id ID of the Cryptographic module + * @ops Operation (function/structure) to register + */ +void drvcrypt_register_change(enum drvcrypt_algo_id algo_id, void *ops); + +/* + * Return the Cryptographic's operation (function/structure) registered in + * the table of modules. + * + * @algo_id ID of the Cryptographic module + */ +void *drvcrypt_get_ops(enum drvcrypt_algo_id algo_id); + +#endif /* __DRVCRYPT_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h new file mode 100644 index 0000000..fa5a142 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2021 NXP + * + * Brief Asymmetric Cipher interface calling the HW crypto driver. + */ +#ifndef __DRVCRYPT_ACIPHER_H__ +#define __DRVCRYPT_ACIPHER_H__ + +#include +#include + +/* + * Assymetric Cipher RSA Algorithm enumerate + */ +enum drvcrypt_rsa_id { + DRVCRYPT_RSA_NOPAD = 0, /* RSA Algo mode NO PAD */ + DRVCRYPT_RSA_OAEP, /* RSA Algo mode OAEP */ + DRVCRYPT_RSA_PKCS_V1_5, /* RSA Algo mode PKCSv1.5 */ + DRVCRYPT_RSASSA_PKCS_V1_5, /* RSA Signature Algo mode PKCSv1.5 */ + DRVCRYPT_RSASSA_PSS, /* RSA Signature Algo mode PSS */ +}; + +/* + * RSA Key object + */ +struct drvcrypt_rsakey { + void *key; /* Public or Private key */ + size_t n_size; /* Size in bytes of the Modulus N */ + bool isprivate; /* True if private key */ +}; + +/* + * RSA Mask Generation data + */ +struct drvcrypt_rsa_mgf { + uint32_t hash_algo; /* HASH Algorithm */ + size_t digest_size; /* Hash Digest Size */ + struct drvcrypt_buf seed; /* Seed to generate mask */ + struct drvcrypt_buf mask; /* Mask generated */ +}; + +/* + * RSA Encoded Signature data + */ +struct drvcrypt_rsa_ssa { + uint32_t algo; /* Operation algorithm */ + uint32_t hash_algo; /* HASH Algorithm */ + size_t digest_size; /* Hash Digest Size */ + struct drvcrypt_rsakey key; /* Public or Private Key */ + struct drvcrypt_buf message; /* Message to sign or signed */ + struct drvcrypt_buf signature; /* Signature of the message */ + size_t salt_len; /* Signature Salt length */ + + /* RSA Mask Generation function */ + TEE_Result (*mgf)(struct drvcrypt_rsa_mgf *mgf_data); +}; + +/* + * RSA Encrypt/Decrypt data + */ +struct drvcrypt_rsa_ed { + uint32_t algo; /* Operation algorithm */ + enum drvcrypt_rsa_id rsa_id; /* RSA Algorithm Id */ + uint32_t hash_algo; /* HASH Algorithm */ + size_t digest_size; /* Hash Digest Size */ + struct drvcrypt_rsakey key; /* Public or Private key */ + struct drvcrypt_buf message; /* Message to encrypt or decrypted */ + struct drvcrypt_buf cipher; /* Cipher encrypted or to decrypt */ + struct drvcrypt_buf label; /* Additional Label (RSAES) */ + + /* RSA Mask Generation function */ + TEE_Result (*mgf)(struct drvcrypt_rsa_mgf *mgf_data); +}; + +/* + * Crypto Library RSA driver operations + */ +struct drvcrypt_rsa { + /* Allocates the RSA keypair */ + TEE_Result (*alloc_keypair)(struct rsa_keypair *key, size_t size_bits); + /* Allocates the RSA public key */ + TEE_Result (*alloc_publickey)(struct rsa_public_key *key, + size_t size_bits); + /* Free RSA public key */ + void (*free_publickey)(struct rsa_public_key *key); + /* Free RSA keypair */ + void (*free_keypair)(struct rsa_keypair *key); + /* Generates the RSA keypair */ + TEE_Result (*gen_keypair)(struct rsa_keypair *key, size_t size_bits); + + /* RSA Encryption */ + TEE_Result (*encrypt)(struct drvcrypt_rsa_ed *rsa_data); + /* RSA Decryption */ + TEE_Result (*decrypt)(struct drvcrypt_rsa_ed *rsa_data); + + struct { + /* RSA Sign a message and encode the signature */ + TEE_Result (*ssa_sign)(struct drvcrypt_rsa_ssa *ssa_data); + /* RSA Encoded Signature Verification */ + TEE_Result (*ssa_verify)(struct drvcrypt_rsa_ssa *ssa_data); + } optional; +}; + +/* + * Register a RSA processing driver in the crypto API + * + * @ops - Driver operations in the HW layer + */ +static inline TEE_Result drvcrypt_register_rsa(const struct drvcrypt_rsa *ops) +{ + return drvcrypt_register(CRYPTO_RSA, (void *)ops); +} + +/* + * Signature data + */ +struct drvcrypt_sign_data { + uint32_t algo; /* Operation algorithm */ + void *key; /* Public or Private Key */ + size_t size_sec; /* Security size in bytes */ + struct drvcrypt_buf message; /* Message to sign or signed */ + struct drvcrypt_buf signature; /* Signature of the message */ +}; + +/* + * Shared Secret data + */ +struct drvcrypt_secret_data { + void *key_priv; /* Private Key */ + void *key_pub; /* Public Key */ + size_t size_sec; /* Security size in bytes */ + struct drvcrypt_buf secret; /* Shared secret */ +}; + +/* + * Encrypt/Decrypt data + */ +struct drvcrypt_ecc_ed { + uint32_t algo; /* Operation algorithm */ + void *key; /* Public or Private Key */ + size_t size_sec; /* Security size in bytes */ + struct drvcrypt_buf plaintext; /* Clear text message */ + struct drvcrypt_buf ciphertext; /* Encrypted message */ +}; + +/* + * Crypto ECC driver operations + */ +struct drvcrypt_ecc { + /* Allocates the ECC keypair */ + TEE_Result (*alloc_keypair)(struct ecc_keypair *key, uint32_t type, + size_t size_bits); + /* Allocates the ECC public key */ + TEE_Result (*alloc_publickey)(struct ecc_public_key *key, uint32_t type, + size_t size_bits); + /* Free ECC public key */ + void (*free_publickey)(struct ecc_public_key *key); + /* Generates the ECC keypair */ + TEE_Result (*gen_keypair)(struct ecc_keypair *key, size_t size_bytes); + /* ECC Sign a message and returns the signature */ + TEE_Result (*sign)(struct drvcrypt_sign_data *sdata); + /* ECC Verify a message's signature */ + TEE_Result (*verify)(struct drvcrypt_sign_data *sdata); + /* ECC Shared Secret */ + TEE_Result (*shared_secret)(struct drvcrypt_secret_data *sdata); + /* ECC Encrypt */ + TEE_Result (*encrypt)(struct drvcrypt_ecc_ed *cdata); + /* ECC Decrypt */ + TEE_Result (*decrypt)(struct drvcrypt_ecc_ed *cdata); +}; + +/* + * Register an ECC processing driver in the crypto API + * + * @ops - Driver operations in the HW layer + */ +static inline TEE_Result drvcrypt_register_ecc(struct drvcrypt_ecc *ops) +{ + return drvcrypt_register(CRYPTO_ECC, (void *)ops); +} + +/* + * Crypto Library DH driver operations + */ +struct drvcrypt_dh { + /* Allocates the DH keypair */ + TEE_Result (*alloc_keypair)(struct dh_keypair *key, size_t size_bits); + /* Generates the DH keypair */ + TEE_Result (*gen_keypair)(struct dh_keypair *key, struct bignum *q, + size_t size_bits); + /* DH Shared Secret */ + TEE_Result (*shared_secret)(struct drvcrypt_secret_data *sdata); +}; + +/* + * Register a DH processing driver in the crypto API + * + * @ops - Driver operations in the HW layer + */ +static inline TEE_Result drvcrypt_register_dh(struct drvcrypt_dh *ops) +{ + return drvcrypt_register(CRYPTO_DH, (void *)ops); +} + +/* + * Crypto Library DSA driver operations + */ +struct drvcrypt_dsa { + /* Allocates the DSA keypair */ + TEE_Result (*alloc_keypair)(struct dsa_keypair *key, size_t l_bits, + size_t n_bits); + /* Allocates the DSA public key */ + TEE_Result (*alloc_publickey)(struct dsa_public_key *key, size_t l_bits, + size_t n_bits); + /* Generates the DSA keypair */ + TEE_Result (*gen_keypair)(struct dsa_keypair *key, size_t l_bits, + size_t n_bits); + /* DSA Sign a message and returns the signature */ + TEE_Result (*sign)(struct drvcrypt_sign_data *sdata, size_t l_bytes, + size_t n_bytes); + /* DSA Verify a message's signature */ + TEE_Result (*verify)(struct drvcrypt_sign_data *sdata, size_t l_bytes, + size_t n_bytes); +}; + +/* + * Register a DSA processing driver in the crypto API + * + * @ops - Driver operations in the HW layer + */ +static inline TEE_Result drvcrypt_register_dsa(struct drvcrypt_dsa *ops) +{ + return drvcrypt_register(CRYPTO_DSA, (void *)ops); +} + +#endif /* __DRVCRYPT_ACIPHER_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.h b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.h new file mode 100644 index 0000000..7d62819 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2020 NXP + * + * Brief Definition of the cryptographic algorthim's OID in the + * ASN1 String format. + * Definition of the ASN1 DER tags. + * + * Computer Security Objects Register + * http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html + */ +#ifndef __ASN1_OID_H__ +#define __ASN1_OID_H__ + +#include +#include + +/* + * ASN1 Tags + */ +#define DRVCRYPT_ASN1_CONSTRUCTED 0x20 +#define DRVCRYPT_ASN1_SEQUENCE 0x10 +#define DRVCRYPT_ASN1_OID 0x06 +#define DRVCRYPT_ASN1_NULL 0x05 +#define DRVCRYPT_ASN1_OCTET_STRING 0x04 + +/* + * OID Top Level = first two Node (Standard and Registration-authority) + * + * iso(1) member-body(2) + * iso(1) identified-organization(3) + * joint-iso-itu-t(2) country(16) + */ +#define DRVCRYPT_OID_ISO_MEMBER_BODY "\x2a" +#define DRVCRYPT_OID_ISO_ID_ORG "\x2b" +#define DRVCRYPT_OID_ISO_ITU_COUNTRY "\x60" + +/* + * ISO Member body + * + * us(840) + * us(840) rsadsi(113549) + */ +#define DRVCRYPT_OID_MB_US "\x86\x48" +#define DRVCRYPT_OID_MB_US_RSADSI DRVCRYPT_OID_MB_US "\x86\xF7\x0D" + +/* + * ISO Identified organization + * + * oiw(14) + * oiw(14) secsig(3) + */ +#define DRVCRYPT_OID_IO_OIW "\x0e" +#define DRVCRYPT_OID_IO_OIW_SECSIG DRVCRYPT_OID_IO_OIW "\x03" + +/* + * ISO ITU OID + * + * organization(1) + * organization(1) gov(101) + */ +#define DRVCRYPT_OID_ITU_ORG "\x01" +#define DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_ITU_ORG "\x65" + +/* + * Digest Algorithm + * + * digestAlgorithm(2) + * csor(3) nistalgotrithm(4) + */ +#define DRVCRYPT_OID_DIGEST "\x02" +#define DRVCRYPT_OID_DIGEST_CSOR_NIST "\x03\x04" + +/* + * Definition of the Hash OID String + * + * id-md5 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 + * } + * id-sha1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 + * } + * id-sha224 OBJECT IDENTIFIER ::= { + * joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) + * csor(3) nistalgorithm(4) hashalgs(2) 4 + * } + * id-sha256 OBJECT IDENTIFIER ::= { + * joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) + * csor(3) nistalgorithm(4) hashalgs(2) 1 + * } + * id-sha384 OBJECT IDENTIFIER ::= { + * joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) + * csor(3) nistalgorithm(4) hashalgs(2) 2 + * } + * id-sha512 OBJECT IDENTIFIER ::= { + * joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) + * csor(3) nistalgorithm(4) hashalgs(2) 3 + * } + * + */ +#define DRVCRYPT_OID_ID_MD5 \ + DRVCRYPT_OID_ISO_MEMBER_BODY DRVCRYPT_OID_MB_US_RSADSI \ + DRVCRYPT_OID_DIGEST "\x05" + +#define DRVCRYPT_OID_ID_SHA1 \ + DRVCRYPT_OID_ISO_ID_ORG DRVCRYPT_OID_IO_OIW_SECSIG DRVCRYPT_OID_DIGEST \ + "\x1a" + +#define DRVCRYPT_OID_ID_SHA224 \ + DRVCRYPT_OID_ISO_ITU_COUNTRY DRVCRYPT_OID_MB_US \ + DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_DIGEST_CSOR_NIST \ + DRVCRYPT_OID_DIGEST "\x04" + +#define DRVCRYPT_OID_ID_SHA256 \ + DRVCRYPT_OID_ISO_ITU_COUNTRY DRVCRYPT_OID_MB_US \ + DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_DIGEST_CSOR_NIST \ + DRVCRYPT_OID_DIGEST "\x01" + +#define DRVCRYPT_OID_ID_SHA384 \ + DRVCRYPT_OID_ISO_ITU_COUNTRY DRVCRYPT_OID_MB_US \ + DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_DIGEST_CSOR_NIST \ + DRVCRYPT_OID_DIGEST "\x02" + +#define DRVCRYPT_OID_ID_SHA512 \ + DRVCRYPT_OID_ISO_ITU_COUNTRY DRVCRYPT_OID_MB_US \ + DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_DIGEST_CSOR_NIST \ + DRVCRYPT_OID_DIGEST "\x03" + +#define DRVCRYPT_OID_LEN(_id) (sizeof(_id) - 1) + +/* + * Definition of the ASN1 OID structure + */ +struct drvcrypt_oid { + const char *asn1; /* OID ASN1 string */ + const size_t asn1_length; /* OID ASN1 string length */ +}; + +/* + * Hash OID constant array + */ +extern const struct drvcrypt_oid drvcrypt_hash_oid[]; + +/* + * Return the Hash OID value registered in the Hash OID table. + * + * @algo Hash algorithm identifier + */ +const struct drvcrypt_oid *drvcrypt_get_alg_hash_oid(uint32_t algo); + +#endif /* __ASN1_OID_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h new file mode 100644 index 0000000..3944869 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * Authenticated Encryption interface calling the crypto driver + */ +#ifndef __DRVCRYPT_AUTHENC_H__ +#define __DRVCRYPT_AUTHENC_H__ + +#include +#include + +/* + * Authenticated Encryption operation context + */ +struct crypto_authenc { + struct crypto_authenc_ctx authenc_ctx; /* Crypto authenc API context */ + void *ctx; /* Authenc context */ + struct drvcrypt_authenc *op; /* Reference to the operation */ +}; + +/* + * Authenticated Encryption algorithm initialization data + */ +struct drvcrypt_authenc_init { + void *ctx; /* Software context */ + bool encrypt; /* Encrypt or decrypt direction */ + struct drvcrypt_buf key; /* First key */ + struct drvcrypt_buf nonce; /* Nonce */ + size_t tag_len; /* Tag length */ + size_t aad_len; /* Additional Authenticated Data length */ + size_t payload_len; /* Payload length */ +}; + +/* + * Authenticated Encryption algorithm update_aad data + */ +struct drvcrypt_authenc_update_aad { + void *ctx; /* Software context */ + bool encrypt; /* Encrypt or decrypt direction */ + struct drvcrypt_buf aad; /* Additional Authenticated Data buffer */ +}; + +/* + * Authenticated Encryption algorithm update_aad data + */ +struct drvcrypt_authenc_update_payload { + void *ctx; /* Software context */ + bool encrypt; /* Encrypt or decrypt direction */ + struct drvcrypt_buf src; /* Buffer source (message or cipher) */ + struct drvcrypt_buf dst; /* Buffer destination (cipher or message) */ +}; + +/* + * Authenticated Encryption algorithm final data + */ +struct drvcrypt_authenc_final { + void *ctx; /* Software context */ + bool encrypt; /* Encrypt or decrypt direction */ + struct drvcrypt_buf src; /* Buffer source (message or cipher) */ + struct drvcrypt_buf dst; /* Buffer destination (cipher or message) */ + struct drvcrypt_buf tag; /* Tag buffer */ +}; + +/* + * Crypto library authenc driver operations + */ +struct drvcrypt_authenc { + /* Allocate context */ + TEE_Result (*alloc_ctx)(void **ctx, uint32_t algo); + /* Free context */ + void (*free_ctx)(void *ctx); + /* Initialize the authenc operation */ + TEE_Result (*init)(struct drvcrypt_authenc_init *dinit); + /* Update the authenc operation with associated data */ + TEE_Result (*update_aad)(struct drvcrypt_authenc_update_aad *dupdate); + /* Update the authenc operation with payload data */ + TEE_Result (*update_payload)(struct drvcrypt_authenc_update_payload *d); + /* Update (or not) with payload data and get tag for encrypt op. */ + TEE_Result (*enc_final)(struct drvcrypt_authenc_final *dfinal); + /* Update (or not) with payload data and verify tag for decrypt op. */ + TEE_Result (*dec_final)(struct drvcrypt_authenc_final *dfinal); + /* Finalize the authenc operation */ + void (*final)(void *ctx); + /* Copy authenc context */ + void (*copy_state)(void *dst_ctx, void *src_ctx); +}; + +/* + * Register an authenc processing driver in the crypto API + * + * @ops - Driver operations + */ +static inline TEE_Result drvcrypt_register_authenc(struct drvcrypt_authenc *ops) +{ + return drvcrypt_register(CRYPTO_AUTHENC, (void *)ops); +} + +#endif /* __DRVCRYPT_AUTHENC_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_cipher.h b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_cipher.h new file mode 100644 index 0000000..a609b15 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_cipher.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2020 NXP + * + * Cipher interface calling the crypto driver. + */ +#ifndef __DRVCRYPT_CIPHER_H__ +#define __DRVCRYPT_CIPHER_H__ + +#include +#include + +/* + * Cipher operation context + */ +struct crypto_cipher { + struct crypto_cipher_ctx cipher_ctx; /* Crypto cipher API context */ + void *ctx; /* Cipher context */ + struct drvcrypt_cipher *op; /* Reference to the operation */ +}; + +/* + * Cipher algorithm initialization data + */ +struct drvcrypt_cipher_init { + void *ctx; /* Software context */ + bool encrypt; /* Encrypt or decrypt direction */ + struct drvcrypt_buf key1; /* First key */ + struct drvcrypt_buf key2; /* Second key */ + struct drvcrypt_buf iv; /* Initial vector */ +}; + +/* + * Cipher algorithm update data + */ +struct drvcrypt_cipher_update { + void *ctx; /* Software context */ + bool encrypt; /* Encrypt or decrypt direction */ + bool last; /* Last block to handle */ + struct drvcrypt_buf src; /* Buffer source (message or cipher) */ + struct drvcrypt_buf dst; /* Buffer dest (message or cipher) */ +}; + +/* + * Crypto library cipher driver operations + */ +struct drvcrypt_cipher { + /* Allocate context */ + TEE_Result (*alloc_ctx)(void **ctx, uint32_t algo); + /* Free context */ + void (*free_ctx)(void *ctx); + /* Initialize the cipher operation */ + TEE_Result (*init)(struct drvcrypt_cipher_init *dinit); + /* Update the cipher operation */ + TEE_Result (*update)(struct drvcrypt_cipher_update *dupdate); + /* Finalize the cipher operation */ + void (*final)(void *ctx); + /* Copy cipher context */ + void (*copy_state)(void *dst_ctx, void *src_ctx); +}; + +/* + * Register a cipher processing driver in the crypto API + * + * @ops - Driver operations + */ +static inline TEE_Result drvcrypt_register_cipher(struct drvcrypt_cipher *ops) +{ + return drvcrypt_register(CRYPTO_CIPHER, (void *)ops); +} + +#endif /* __DRVCRYPT_CIPHER_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_hash.h b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_hash.h new file mode 100644 index 0000000..2be4573 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_hash.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2020 NXP + * + * Brief Hash interface calling the HW crypto driver. + */ +#ifndef __DRVCRYPT_HASH_H__ +#define __DRVCRYPT_HASH_H__ + +#include +#include +#include + +/* + * Crypto Library Hash driver allocation function prototype + */ +typedef TEE_Result (*hw_hash_allocate)(struct crypto_hash_ctx **ctx, + uint32_t algo); + +/* + * Register a hash processing driver in the crypto API + * + * @allocate - Callback for driver context allocation in the crypto layer + */ +static inline TEE_Result drvcrypt_register_hash(hw_hash_allocate allocate) +{ + return drvcrypt_register(CRYPTO_HASH, (void *)allocate); +} + +#endif /* __DRVCRYPT_HASH_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_mac.h b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_mac.h new file mode 100644 index 0000000..c000366 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_mac.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019-2020 NXP + * + * MAC interface calling the HW crypto driver. + */ +#ifndef __DRVCRYPT_MAC_H__ +#define __DRVCRYPT_MAC_H__ + +#include +#include +#include + +/* + * Crypto library HMAC driver allocation function prototype + */ +typedef TEE_Result (*drvcrypt_mac_allocate)(struct crypto_mac_ctx **ctx, + uint32_t algo); + +/* + * Register a HMAC processing driver in the crypto API + * + * @allocate - Callback for driver context allocation in the crypto layer + */ +static inline TEE_Result drvcrypt_register_hmac(drvcrypt_mac_allocate allocate) +{ + return drvcrypt_register(CRYPTO_HMAC, (void *)allocate); +} + +/* + * Register a CMAC processing driver in the crypto API + * + * @allocate - Callback for driver context allocation in the crypto layer + */ +static inline TEE_Result drvcrypt_register_cmac(drvcrypt_mac_allocate allocate) +{ + return drvcrypt_register(CRYPTO_CMAC, (void *)allocate); +} +#endif /* __DRVCRYPT_MAC_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_math.h b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_math.h new file mode 100644 index 0000000..3069a29 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/include/drvcrypt_math.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2020 NXP + * + * Brief Cryptographic library using the HW crypto driver. + * Mathematical operation using HW if available. + */ +#ifndef __DRVCRYPT_MATH_H__ +#define __DRVCRYPT_MATH_H__ + +#include + +/* + * Binary Modular operation data + */ +struct drvcrypt_mod_op { + struct drvcrypt_buf n; /* Modulus N */ + struct drvcrypt_buf a; /* Operand A */ + struct drvcrypt_buf b; /* Operand B */ + struct drvcrypt_buf result; /* Result of operation */ +}; + +/* + * Operation (A xor B) mod N + * + * @data [in/out] Data operation + */ +TEE_Result drvcrypt_xor_mod_n(struct drvcrypt_mod_op *data); + +/* + * Crypto Library Binaries Modular driver operations + */ +struct drvcrypt_math { + /* (A xor B) mod N */ + TEE_Result (*xor_mod_n)(struct drvcrypt_mod_op *op_data); +}; + +/* + * Register a mathematical processing driver in the crypto API + * + * @ops - Driver operations in the HW layer + */ +static inline TEE_Result drvcrypt_register_math(const struct drvcrypt_math *ops) +{ + return drvcrypt_register(CRYPTO_MATH, (void *)ops); +} +#endif /* __DRVCRYPT_MATH_H__ */ diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/mac/mac.c b/optee/optee_os/core/drivers/crypto/crypto_api/mac/mac.c new file mode 100644 index 0000000..a233ab0 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/mac/mac.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2020 NXP + * + * Crypto MAC interface implementation to enable HW driver. + */ +#include +#include +#include +#include +#include + +TEE_Result drvcrypt_mac_alloc_ctx(struct crypto_mac_ctx **ctx, uint32_t algo) +{ + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + drvcrypt_mac_allocate mac_alloc = NULL; + unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo); + + CRYPTO_TRACE("mac alloc_ctx algo 0x%" PRIX32, algo); + + assert(ctx); + + if (algo_id >= TEE_MAIN_ALGO_MD5 && algo_id <= TEE_MAIN_ALGO_SHA512) + mac_alloc = drvcrypt_get_ops(CRYPTO_HMAC); + else + mac_alloc = drvcrypt_get_ops(CRYPTO_CMAC); + + if (mac_alloc) + ret = mac_alloc(ctx, algo); + + CRYPTO_TRACE("mac alloc_ctx ret 0x%" PRIX32, ret); + + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/mac/sub.mk b/optee/optee_os/core/drivers/crypto/crypto_api/mac/sub.mk new file mode 100644 index 0000000..68b265b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/mac/sub.mk @@ -0,0 +1 @@ +srcs-y += mac.c diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/math/modulus.c b/optee/optee_os/core/drivers/crypto/crypto_api/math/modulus.c new file mode 100644 index 0000000..4080af7 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/math/modulus.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2020 NXP + * + * Brief Cryptographic library using the NXP CAAM driver. + * Mathematical Modulus operation implementation. + */ +#include +#include +#include +#include + +TEE_Result drvcrypt_xor_mod_n(struct drvcrypt_mod_op *data) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct drvcrypt_math *math = NULL; + + if (!data->a.data || !data->a.length || !data->b.data || + !data->b.length || !data->result.data || !data->result.length || + !data->n.length) + return TEE_ERROR_BAD_PARAMETERS; + + if (data->result.length < data->n.length) + return TEE_ERROR_BAD_PARAMETERS; + + math = drvcrypt_get_ops(CRYPTO_MATH); + if (math) { + /* Operation done by Math driver */ + ret = math->xor_mod_n(data); + } else { + /* Operation done by Software */ + size_t min = 0, idx = 0; + + /* Calculate the minimum size to do A xor B */ + min = MIN(data->a.length, data->b.length); + min = MIN(min, data->n.length); + + for (; idx < min; idx++) + data->result.data[idx] = + data->a.data[idx] ^ data->b.data[idx]; + + if (min < data->n.length) { + /* Complete result to make a N modulus number */ + if (data->a.length > min) { + memcpy(&data->result.data[idx], + &data->a.data[idx], + data->n.length - min); + } else if (data->b.length > min) { + memcpy(&data->result.data[idx], + &data->b.data[idx], + data->n.length - min); + } else { + memset(&data->result.data[idx], 0, + data->n.length - min); + } + } + + ret = TEE_SUCCESS; + } + + return ret; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/math/sub.mk b/optee/optee_os/core/drivers/crypto/crypto_api/math/sub.mk new file mode 100644 index 0000000..e718dff --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/math/sub.mk @@ -0,0 +1 @@ +srcs-y += modulus.c diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/oid/hash_oid.c b/optee/optee_os/core/drivers/crypto/crypto_api/oid/hash_oid.c new file mode 100644 index 0000000..1d7f12b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/oid/hash_oid.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2020 NXP + * + * Brief Definition of the Hash's OID + */ + +/* Driver Crypto includes */ +#include +#include + +/* + * Hash OID values + */ +const struct drvcrypt_oid drvcrypt_hash_oid[] = { + /* empty entry */ + { NULL, 0 }, + /* MD5 */ + { DRVCRYPT_OID_ID_MD5, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_MD5) }, + /* SHA1 */ + { DRVCRYPT_OID_ID_SHA1, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA1) }, + /* SHA224 */ + { DRVCRYPT_OID_ID_SHA224, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA224) }, + /* SHA256 */ + { DRVCRYPT_OID_ID_SHA256, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA256) }, + /* SHA384 */ + { DRVCRYPT_OID_ID_SHA384, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA384) }, + /* SHA512 */ + { DRVCRYPT_OID_ID_SHA512, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA512) }, +}; + +const struct drvcrypt_oid *drvcrypt_get_alg_hash_oid(uint32_t algo) +{ + uint32_t main_alg = TEE_ALG_GET_MAIN_ALG(algo); + + if (main_alg < ARRAY_SIZE(drvcrypt_hash_oid)) + return &drvcrypt_hash_oid[main_alg]; + + return NULL; +} diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/oid/sub.mk b/optee/optee_os/core/drivers/crypto/crypto_api/oid/sub.mk new file mode 100644 index 0000000..1b051f3 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/oid/sub.mk @@ -0,0 +1 @@ +srcs-y += hash_oid.c diff --git a/optee/optee_os/core/drivers/crypto/crypto_api/sub.mk b/optee/optee_os/core/drivers/crypto/crypto_api/sub.mk new file mode 100644 index 0000000..0577e3f --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/crypto_api/sub.mk @@ -0,0 +1,10 @@ +srcs-y += drvcrypt.c + +subdirs-y += math + +subdirs-$(CFG_CRYPTO_DRV_HASH) += hash +subdirs-$(CFG_CRYPTO_DRV_ACIPHER) += acipher +subdirs-$(CFG_CRYPTO_DRV_ACIPHER) += oid +subdirs-$(CFG_CRYPTO_DRV_CIPHER) += cipher +subdirs-$(CFG_CRYPTO_DRV_MAC) += mac +subdirs-$(CFG_CRYPTO_DRV_AUTHENC) += authenc diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/apdu.c b/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/apdu.c new file mode 100644 index 0000000..b2d0af5 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/apdu.c @@ -0,0 +1,733 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include + +sss_status_t se050_factory_reset(pSe05xSession_t ctx) +{ + if (!ctx) + return kStatus_SSS_Fail; + + if (Se05x_API_DeleteAll_Iterative(ctx) == SM_OK) + return kStatus_SSS_Success; + + return kStatus_SSS_Fail; +} + +bool se050_key_exists(uint32_t key_id, pSe05xSession_t ctx) +{ + SE05x_Result_t inuse = kSE05x_Result_FAILURE; + smStatus_t status = SM_OK; + + if (!ctx) + return false; + + status = Se05x_API_CheckObjectExists(ctx, key_id, &inuse); + if (status != SM_OK) + return false; + + if (inuse == kSE05x_Result_SUCCESS) + return true; + + return false; +} + +static sss_status_t set_rsa_public(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + struct se050_rsa_keypub *keypub, + size_t key_bit_len) +{ + SE05x_TransientType_t type = kSE05x_TransientType_Transient; + SE05x_RSAKeyFormat_t rsa_format = kSE05x_RSAKeyFormat_RAW; + smStatus_t status = SM_OK; + + if (k_object->isPersistant) + type = kSE05x_TransientType_Persistent; + + switch (k_object->cipherType) { + case kSSS_CipherType_RSA: + rsa_format = kSE05x_RSAKeyFormat_RAW; + break; + case kSSS_CipherType_RSA_CRT: + rsa_format = kSE05x_RSAKeyFormat_CRT; + break; + default: + return kStatus_SSS_Fail; + } + + status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, + (U16)key_bit_len, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + keypub->e, keypub->e_len, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_Public, + rsa_format); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + keypub->n, keypub->n_len, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + rsa_format); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_rsa_private_rsa(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + struct se050_rsa_keypair *keypair, + size_t key_bit_len) +{ + SE05x_TransientType_t type = kSE05x_TransientType_Transient; + smStatus_t status = SM_OK; + + if (k_object->isPersistant) + type = kSE05x_TransientType_Persistent; + + status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, + (U16)key_bit_len, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + keypair->d, keypair->d_len, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_Pair, + kSE05x_RSAKeyFormat_RAW); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + keypair->n, keypair->n_len, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_RAW); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_rsa_private_rsa_crt(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + struct se050_rsa_keypair *keypair, + size_t key_bit_len) +{ + SE05x_TransientType_t type = kSE05x_TransientType_Transient; + smStatus_t status = SM_OK; + + if (k_object->isPersistant) + type = kSE05x_TransientType_Persistent; + + status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, + (U16)key_bit_len, + keypair->p, + keypair->p_len, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_Private, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + keypair->q, + keypair->q_len, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + keypair->dp, + keypair->dp_len, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + keypair->dq, + keypair->dq_len, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + keypair->qp, + keypair->qp_len, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_rsa_keypair_rsa(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + struct se050_rsa_keypair *keypair, + size_t key_bit_len) +{ + SE05x_TransientType_t type = kSE05x_TransientType_Transient; + smStatus_t status = SM_OK; + + if (k_object->isPersistant) + type = kSE05x_TransientType_Persistent; + + status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, + (U16)key_bit_len, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + keypair->e, keypair->e_len, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_Pair, + kSE05x_RSAKeyFormat_RAW); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + keypair->d, keypair->d_len, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_RAW); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + keypair->n, keypair->n_len, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_RAW); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_rsa_keypair_rsa_crt(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + struct se050_rsa_keypair *keypair, + size_t key_bit_len) +{ + SE05x_TransientType_t type = kSE05x_TransientType_Transient; + smStatus_t status = SM_OK; + + if (k_object->isPersistant) + type = kSE05x_TransientType_Persistent; + + status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, + (U16)key_bit_len, + keypair->p, keypair->p_len, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_Pair, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + keypair->q, keypair->q_len, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + keypair->dp, keypair->dp_len, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + keypair->dq, keypair->dq_len, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + keypair->qp, keypair->qp_len, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + keypair->e, keypair->e_len, + SE05X_RSA_NO_priv, + SE05X_RSA_NO_pubMod, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, + 0, + SE05X_RSA_NO_p, + SE05X_RSA_NO_q, + SE05X_RSA_NO_dp, + SE05X_RSA_NO_dq, + SE05X_RSA_NO_qInv, + SE05X_RSA_NO_pubExp, + SE05X_RSA_NO_priv, + keypair->n, keypair->n_len, + (SE05x_INS_t)type, + kSE05x_KeyPart_NA, + kSE05x_RSAKeyFormat_CRT); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +sss_status_t se050_key_store_set_rsa_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *k_object, + struct se050_rsa_keypair *keypair, + struct se050_rsa_keypub *keypub, + size_t key_bit_len) +{ + Se05xPolicy_t policy = { }; + + if (!store || !store->session || !k_object) + return kStatus_SSS_Fail; + + if (se050_key_exists(k_object->keyId, &store->session->s_ctx)) + key_bit_len = 0; + + switch (k_object->objectType) { + case kSSS_KeyPart_Public: + return set_rsa_public(&store->session->s_ctx, + &policy, k_object, + keypub, key_bit_len); + case kSSS_KeyPart_Private: + if (k_object->cipherType == kSSS_CipherType_RSA) + return set_rsa_private_rsa(&store->session->s_ctx, + &policy, k_object, + keypair, key_bit_len); + + if (k_object->cipherType == kSSS_CipherType_RSA_CRT) + return set_rsa_private_rsa_crt(&store->session->s_ctx, + &policy, k_object, + keypair, key_bit_len); + return kStatus_SSS_Fail; + case kSSS_KeyPart_Pair: + if (k_object->cipherType == kSSS_CipherType_RSA) + return set_rsa_keypair_rsa(&store->session->s_ctx, + &policy, k_object, + keypair, key_bit_len); + + if (k_object->cipherType == kSSS_CipherType_RSA_CRT) + return set_rsa_keypair_rsa_crt(&store->session->s_ctx, + &policy, k_object, + keypair, key_bit_len); + return kStatus_SSS_Fail; + default: + return kStatus_SSS_Fail; + } +} + +sss_status_t se050_get_free_memory(pSe05xSession_t ctx, uint16_t *p, + SE05x_MemoryType_t type) +{ + if (p && ctx && Se05x_API_GetFreeMemory(ctx, type, p) == SM_OK) + return kStatus_SSS_Success; + + return kStatus_SSS_Fail; +} + +sss_status_t se050_scp03_send_rotate_cmd(pSe05xSession_t ctx, + struct s050_scp_rotate_cmd *cmd) +{ + uint8_t rsp[64] = { 0 }; + size_t rsp_len = sizeof(rsp); + tlvHeader_t hdr = { + .hdr = { + [0] = 0x80, + [1] = 0xd8, + [2] = 0, + [3] = PUT_KEYS_KEY_IDENTIFIER, + }, + }; + smStatus_t st = SM_NOT_OK; + + if (!ctx || !cmd) + return kStatus_SSS_Fail; + + hdr.hdr[2] = cmd->cmd[0]; + st = DoAPDUTxRx_s_Case4(ctx, &hdr, cmd->cmd, cmd->cmd_len, + rsp, &rsp_len); + + if ((rsp_len - 1 > sizeof(rsp)) || rsp_len < 2) + return kStatus_SSS_Fail; + + st = (rsp[rsp_len - 2] << 8) + rsp[rsp_len - 1]; + if (st != SM_OK) + return kStatus_SSS_Fail; + + if (!memcmp(rsp, cmd->kcv, cmd->kcv_len)) + return kStatus_SSS_Success; + + return kStatus_SSS_Fail; +} + +static uint8_t *alloc_pubkey_buf(struct se050_ecc_keypub *keypub, size_t *len) +{ + size_t pubkey_len = 0; + uint8_t *pubkey = NULL; + uint8_t *buf = NULL; + + pubkey_len = keypub->x_len + keypub->y_len + 1; + buf = malloc(pubkey_len); + if (!buf) + return NULL; + + *buf = 0x04; + pubkey = buf + 1; + memcpy(pubkey, keypub->x, keypub->x_len); + memcpy(pubkey + keypub->x_len, keypub->y, keypub->y_len); + *len = pubkey_len; + + return buf; +} + +sss_status_t se050_ecc_gen_shared_secret(pSe05xSession_t ctx, uint32_t kid, + struct se050_ecc_keypub *keypub, + uint8_t *secret, size_t *len) +{ + smStatus_t status = SM_OK; + uint8_t *buf = NULL; + size_t pubkey_len = 0; + + if (!keypub || !secret || !len) + return kStatus_SSS_Fail; + + buf = alloc_pubkey_buf(keypub, &pubkey_len); + if (!buf) + return kStatus_SSS_Fail; + + status = Se05x_API_ECGenSharedSecret(ctx, kid, + buf, pubkey_len, secret, len); + free(buf); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_ecc_public(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + SE05x_TransientType_t type, + struct se050_ecc_keypub *keypub) +{ + size_t pubkey_len = 0; + smStatus_t status = SM_NOT_OK; + uint8_t *buf = NULL; + + buf = alloc_pubkey_buf(keypub, &pubkey_len); + if (!buf) + return kStatus_SSS_Fail; + + k_object->curve_id = keypub->curve; + status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, + k_object->keyId, + keypub->curve, + NULL, + 0, + buf, + pubkey_len, + (SE05x_INS_t)type, + kSE05x_KeyPart_Public); + free(buf); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_ecc_private(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + SE05x_TransientType_t type, + struct se050_ecc_keypair *keypair) +{ + smStatus_t status = SM_NOT_OK; + + k_object->curve_id = keypair->pub.curve; + status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, + k_object->keyId, + keypair->pub.curve, + keypair->d, + keypair->d_len, + NULL, + 0, + (SE05x_INS_t)type, + kSE05x_KeyPart_Private); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +static sss_status_t set_ecc_pair(Se05xSession_t *s_ctx, + Se05xPolicy_t *policy, + sss_se05x_object_t *k_object, + SE05x_TransientType_t type, + struct se050_ecc_keypair *keypair) +{ + size_t pubkey_len = 0; + smStatus_t status = SM_NOT_OK; + uint8_t *buf = NULL; + + buf = alloc_pubkey_buf(&keypair->pub, &pubkey_len); + if (!buf) + return kStatus_SSS_Fail; + + k_object->curve_id = keypair->pub.curve; + status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, + k_object->keyId, + keypair->pub.curve, + keypair->d, + keypair->d_len, + buf, + pubkey_len, + (SE05x_INS_t)type, + kSE05x_KeyPart_Pair); + free(buf); + if (status != SM_OK) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +sss_status_t se050_key_store_set_ecc_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *k_object, + struct se050_ecc_keypair *keypair, + struct se050_ecc_keypub *keypub) +{ + SE05x_TransientType_t type = kSE05x_TransientType_Transient; + Se05xPolicy_t policy = { }; + + if (!store || !store->session || !k_object) + return kStatus_SSS_Fail; + + if (k_object->isPersistant) + type = kSE05x_TransientType_Persistent; + + switch (k_object->objectType) { + case kSSS_KeyPart_Public: + if (!keypub) + return kStatus_SSS_Fail; + + return set_ecc_public(&store->session->s_ctx, + &policy, k_object, type, keypub); + case kSSS_KeyPart_Private: + if (!keypair) + return kStatus_SSS_Fail; + + return set_ecc_private(&store->session->s_ctx, + &policy, k_object, type, keypair); + case kSSS_KeyPart_Pair: + if (!keypair) + return kStatus_SSS_Fail; + + return set_ecc_pair(&store->session->s_ctx, + &policy, k_object, type, keypair); + default: + return kStatus_SSS_Fail; + } +} + +sss_status_t se050_key_store_get_ecc_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *k_object, + uint8_t *key, size_t *key_len) +{ + smStatus_t status = SM_NOT_OK; + uint8_t *buf = NULL; + size_t buflen = 0; + + if (!store || !store->session || !k_object || !key || !key_len) + return kStatus_SSS_Fail; + + switch (k_object->cipherType) { + case kSSS_CipherType_EC_NIST_P: + case kSSS_CipherType_EC_NIST_K: + case kSSS_CipherType_EC_BRAINPOOL: + case kSSS_CipherType_EC_BARRETO_NAEHRIG: + case kSSS_CipherType_EC_MONTGOMERY: + case kSSS_CipherType_EC_TWISTED_ED: + add_ecc_header(key, key_len, &buf, &buflen, k_object->curve_id); + status = Se05x_API_ReadObject(&store->session->s_ctx, + k_object->keyId, 0, 0, + buf, key_len); + if (status != SM_OK) + return kStatus_SSS_Fail; + + *key_len += buflen; + buflen = *key_len; + get_ecc_raw_data(key, *key_len, &buf, &buflen, + k_object->curve_id); + + /* return only the binary data */ + *key_len = buflen; + memcpy(key, buf, buflen); + return kStatus_SSS_Success; + default: + return kStatus_SSS_Fail; + } +} diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/sss.c b/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/sss.c new file mode 100644 index 0000000..197ee6e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/sss.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include + +static const sss_policy_u asym_key = { + .type = KPolicy_Asym_Key, + .auth_obj_id = 0, + .policy = { + .asymmkey = { + .can_Sign = 1, + .can_Verify = 1, + .can_Encrypt = 1, + .can_Decrypt = 1, + .can_KD = 1, + .can_Wrap = 1, + .can_Write = 1, + .can_Gen = 1, + .can_Import_Export = 1, + .can_KA = 1, + .can_Read = 1, + .can_Attest = 1, + } + } +}; + +static const sss_policy_u common = { + .type = KPolicy_Common, + .auth_obj_id = 0, + .policy = { + .common = { + .can_Delete = 1, + .can_Read = 1, + .can_Write = 1, + .req_Sm = 1, + }, + }, +}; + +sss_policy_t se050_asym_policy = { + .nPolicies = 2, + .policies = { &asym_key, &common }, +}; + +sss_status_t se050_rotate_scp03_keys(struct sss_se05x_ctx *ctx) +{ + struct s050_scp_rotate_cmd cmd = { }; + sss_status_t status = kStatus_SSS_Fail; + struct se050_scp_key cur_keys = { }; + struct se050_scp_key new_keys = { }; + SE_Connect_Ctx_t *connect_ctx = NULL; + sss_se05x_session_t *session = NULL; + + if (!ctx) + return kStatus_SSS_Fail; + + if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_WITH_FACTORY_KEYS)) { + /* Public */ + status = se050_scp03_get_keys(&new_keys, SCP03_OFID); + if (status != kStatus_SSS_Success) + return status; + } else { + /* Secret */ + status = se050_scp03_subkey_derive(&new_keys); + if (status != kStatus_SSS_Success) + return status; + } + + status = se050_scp03_get_current_keys(&cur_keys); + if (status != kStatus_SSS_Success) + return status; + + if (IS_ENABLED(CFG_CORE_SE05X_DISPLAY_SCP03_KEYS)) { + IMSG("scp03: current keys"); + nLog_au8("scp03", 0xff, "dek: ", + cur_keys.dek, SE050_SCP03_KEY_SZ); + nLog_au8("scp03", 0xff, "mac: ", + cur_keys.mac, SE050_SCP03_KEY_SZ); + nLog_au8("scp03", 0xff, "enc: ", + cur_keys.enc, SE050_SCP03_KEY_SZ); + IMSG("scp03: proposed new keys"); + nLog_au8("scp03", 0xff, "dek: ", + new_keys.dek, SE050_SCP03_KEY_SZ); + nLog_au8("scp03", 0xff, "mac: ", + new_keys.mac, SE050_SCP03_KEY_SZ); + nLog_au8("scp03", 0xff, "enc: ", + new_keys.enc, SE050_SCP03_KEY_SZ); + } + + if (!consttime_memcmp(new_keys.enc, cur_keys.enc, SE050_SCP03_KEY_SZ) && + !consttime_memcmp(new_keys.mac, cur_keys.mac, SE050_SCP03_KEY_SZ) && + !consttime_memcmp(new_keys.dek, cur_keys.dek, SE050_SCP03_KEY_SZ)) + return kStatus_SSS_Success; + + connect_ctx = &ctx->open_ctx; + session = &ctx->session; + + status = se050_scp03_prepare_rotate_cmd(ctx, &cmd, &new_keys); + if (status != kStatus_SSS_Success) + return status; + + sss_se05x_refresh_session(se050_session, NULL); + sss_se05x_session_close(session); + + /* re-open session with same keys */ + connect_ctx->skip_select_applet = 1; + status = sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0, + kSSS_ConnectionType_Encrypted, + connect_ctx); + if (status != kStatus_SSS_Success) { + se050_scp03_set_disable(); + EMSG("scp03 re-open failed, session lost"); + return kStatus_SSS_Fail; + } + + status = se050_scp03_send_rotate_cmd(&session->s_ctx, &cmd); + if (status != kStatus_SSS_Success) { + EMSG("scp03 keys not updated"); + return kStatus_SSS_Fail; + } + + sss_host_session_close(&ctx->host_session); + sss_se05x_session_close(se050_session); + memset(ctx, 0, sizeof(*ctx)); + + /* open session with new keys */ + if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_WITH_FACTORY_KEYS)) + se050_scp03_set_enable(SCP03_OFID); + else + se050_scp03_set_enable(SCP03_DERIVED); + + if (se050_core_early_init(&new_keys)) { + se050_scp03_set_disable(); + EMSG("scp03 keys rejected, session lost"); + return kStatus_SSS_Fail; + } + + return kStatus_SSS_Success; +} + +sss_status_t se050_enable_scp03(sss_se05x_session_t *session) +{ + struct se050_scp_key keys = { }; + sss_status_t status = kStatus_SSS_Success; + enum se050_scp03_ksrc key_src[] = { SCP03_DERIVED, SCP03_CFG, + SCP03_OFID }; + size_t i = 0; + + if (se050_scp03_enabled()) + return kStatus_SSS_Success; + + for (i = 0; i < ARRAY_SIZE(key_src); i++) { + status = se050_scp03_get_keys(&keys, key_src[i]); + if (status != kStatus_SSS_Success) + continue; + + if (session->subsystem) + sss_se05x_session_close(session); + + if (!se050_core_early_init(&keys)) { + se050_scp03_set_enable(key_src[i]); + goto out; + } + + sss_host_session_close(&se050_ctx.host_session); + } + + return kStatus_SSS_Fail; +out: + if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_ON_INIT)) + return se050_rotate_scp03_keys(&se050_ctx); + + return kStatus_SSS_Success; +} + +sss_status_t se050_session_open(struct sss_se05x_ctx *ctx, + struct se050_scp_key *current_keys) +{ + sss_status_t status = kStatus_SSS_Fail; + SE_Connect_Ctx_t *connect_ctx = NULL; + sss_se05x_session_t *session = NULL; + + if (!ctx) + return kStatus_SSS_Fail; + + connect_ctx = &ctx->open_ctx; + session = &ctx->session; + connect_ctx->connType = kType_SE_Conn_Type_T1oI2C; + connect_ctx->portName = NULL; + + if (!current_keys) { + return sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0, + kSSS_ConnectionType_Plain, + connect_ctx); + } + + status = se050_configure_host(&ctx->host_session, + &ctx->host_ks, + &ctx->open_ctx, + &ctx->se05x_auth, + kSSS_AuthType_SCP03, + current_keys); + if (status != kStatus_SSS_Success) + return status; + + return sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0, + kSSS_ConnectionType_Encrypted, + connect_ctx); +} + +sss_status_t se050_key_store_and_object_init(struct sss_se05x_ctx *ctx) +{ + if (!ctx) + return kStatus_SSS_Fail; + + return sss_se05x_key_store_context_init(&ctx->ks, &ctx->session); +} diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/user.c b/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/user.c new file mode 100644 index 0000000..e3a4eaa --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/apis/user.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include + +static sss_status_t alloc_scp_key_to_auth(sss_object_t *k_object, + sss_key_store_t *k_store, + uint32_t key_id) +{ + sss_status_t status = kStatus_SSS_Fail; + + if (!k_object || !k_store) + return kStatus_SSS_Fail; + + status = sss_host_key_object_init(k_object, k_store); + if (status != kStatus_SSS_Success) + return status; + + return sss_host_key_object_allocate_handle(k_object, key_id, + kSSS_KeyPart_Default, + kSSS_CipherType_AES, 16, + kKeyObject_Mode_Transient); +} + +static sss_status_t prepare_host_scp(NXSCP03_AuthCtx_t *scp, + struct se050_auth_ctx *auth, + sss_key_store_t *k_store, + struct se050_scp_key *keys, + uint32_t oid) +{ + sss_status_t status = kStatus_SSS_Fail; + NXSCP03_StaticCtx_t *pStatic_ctx = NULL; + NXSCP03_DynCtx_t *pDyn_ctx = NULL; + size_t len = 0; + + if (!scp || !auth || !k_store) + return kStatus_SSS_Fail; + + pStatic_ctx = &auth->static_ctx; + pDyn_ctx = &auth->dynamic_ctx; + + scp->pStatic_ctx = pStatic_ctx; + scp->pDyn_ctx = pDyn_ctx; + pStatic_ctx->keyVerNo = 0x0B; + + status = alloc_scp_key_to_auth(&pStatic_ctx->Enc, k_store, oid++); + if (status != kStatus_SSS_Success) + return status; + + len = sizeof(keys->enc); + status = sss_host_key_store_set_key(k_store, &pStatic_ctx->Enc, + keys->enc, len, len * 8, NULL, 0); + if (status != kStatus_SSS_Success) + return status; + + status = alloc_scp_key_to_auth(&pStatic_ctx->Mac, k_store, oid++); + if (status != kStatus_SSS_Success) + return status; + + len = sizeof(keys->mac); + status = sss_host_key_store_set_key(k_store, &pStatic_ctx->Mac, + keys->mac, len, len * 8, NULL, 0); + if (status != kStatus_SSS_Success) + return status; + + status = alloc_scp_key_to_auth(&pStatic_ctx->Dek, k_store, oid++); + if (status != kStatus_SSS_Success) + return status; + + len = sizeof(keys->dek); + status = sss_host_key_store_set_key(k_store, &pStatic_ctx->Dek, + keys->dek, len, len * 8, NULL, 0); + if (status != kStatus_SSS_Success) + return status; + + status = alloc_scp_key_to_auth(&pDyn_ctx->Enc, k_store, oid++); + if (status != kStatus_SSS_Success) + return status; + + status = alloc_scp_key_to_auth(&pDyn_ctx->Mac, k_store, oid++); + if (status != kStatus_SSS_Success) + return status; + + return alloc_scp_key_to_auth(&pDyn_ctx->Rmac, k_store, oid++); +} + +sss_status_t se050_configure_host(sss_user_impl_session_t *host_session, + sss_key_store_t *host_ks, + SE_Connect_Ctx_t *open_ctx, + struct se050_auth_ctx *auth, + SE_AuthType_t auth_type, + struct se050_scp_key *keys) +{ + sss_status_t status = kStatus_SSS_Fail; + uint32_t host_oid = 0; + + if (!host_session || !host_ks || !open_ctx || !auth) + return kStatus_SSS_Fail; + + if (host_session->subsystem != kType_SSS_SubSystem_NONE) + goto prepare; + + status = sss_host_session_open(host_session, kType_SSS_Software, 0, + kSSS_ConnectionType_Plain, NULL); + if (status != kStatus_SSS_Success) + return status; + + status = sss_host_key_store_context_init(host_ks, host_session); + if (status != kStatus_SSS_Success) + goto error; + + status = sss_host_key_store_allocate(host_ks, host_oid++); + if (status != kStatus_SSS_Success) + goto error; +prepare: + status = prepare_host_scp(&open_ctx->auth.ctx.scp03, auth, host_ks, + keys, host_oid); + if (status != kStatus_SSS_Success) + goto error; + + open_ctx->auth.authType = auth_type; + return status; + +error: + sss_host_session_close(host_session); + return status; +} + +TEE_Result se050_host_key_store_get_key(sss_key_store_t *ks __unused, + sss_object_t *ko, uint8_t *data, + size_t *byte_len, size_t *bit_len) +{ + sss_user_impl_object_t *key_object = (sss_user_impl_object_t *)ko; + + if (!ko) + return TEE_ERROR_GENERIC; + + if (*byte_len < sizeof(key_object->key)) + return TEE_ERROR_EXCESS_DATA; + + memcpy(data, key_object->key, sizeof(key_object->key)); + *byte_len = sizeof(key_object->key); + *bit_len = 8 * sizeof(key_object->key); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050.h b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050.h new file mode 100644 index 0000000..e5f8f66 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#ifndef SE050_H_ +#define SE050_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Supported Devices*/ +#define SE050A1_ID 0xA204 +#define SE050A2_ID 0xA205 +#define SE050B1_ID 0xA202 +#define SE050B2_ID 0xA203 +#define SE050C1_ID 0xA200 +#define SE050C2_ID 0xA201 +#define SE050DV_ID 0xA1F4 +#define SE051A2_ID 0xA565 +#define SE051C2_ID 0xA564 +#define SE050F2_ID 0xA77E +#define SE050E_ID 0xA921 +#define SE051A_ID 0xA920 +#define SE051C_ID 0xA8FA +#define SE051W_ID 0xA739 +#define SE050F_ID 0xA92A + +TEE_Result se050_core_early_init(struct se050_scp_key *keys); + +extern sss_se05x_key_store_t *se050_kstore; +extern sss_se05x_session_t *se050_session; +extern struct sss_se05x_ctx se050_ctx; + +static inline uint32_t se050_get_oefid(void) +{ + return SHIFT_U32(se050_ctx.se_info.oefid[0], 8) | + SHIFT_U32(se050_ctx.se_info.oefid[1], 0); +} + +#endif /* SE050_H_ */ diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h new file mode 100644 index 0000000..766d12e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#ifndef SE050_APDU_APIS_H_ +#define SE050_APDU_APIS_H_ + +#include + +struct s050_scp_rotate_cmd; + +sss_status_t se050_factory_reset(pSe05xSession_t ctx); + +bool se050_key_exists(uint32_t k_id, pSe05xSession_t ctx); + +struct se050_rsa_keypair { + uint8_t *e; + size_t e_len; + uint8_t *d; + size_t d_len; + uint8_t *n; + size_t n_len; + + uint8_t *p; + size_t p_len; + uint8_t *q; + size_t q_len; + uint8_t *qp; + size_t qp_len; + uint8_t *dp; + size_t dp_len; + uint8_t *dq; + size_t dq_len; +}; + +struct se050_rsa_keypub { + uint8_t *e; + size_t e_len; + uint8_t *n; + size_t n_len; +}; + +sss_status_t se050_key_store_set_rsa_key_bin(sss_se05x_key_store_t *k_store, + sss_se05x_object_t *k_object, + struct se050_rsa_keypair *k_pair, + struct se050_rsa_keypub *k_pub, + size_t k_bit_len); + +sss_status_t se050_get_free_memory(pSe05xSession_t ctx, uint16_t *t, + SE05x_MemoryType_t type); + +sss_status_t se050_scp03_send_rotate_cmd(pSe05xSession_t ctx, + struct s050_scp_rotate_cmd *cmd); + +struct se050_ecc_keypub { + uint8_t *x; + size_t x_len; + uint8_t *y; + size_t y_len; + uint32_t curve; +}; + +struct se050_ecc_keypair { + struct se050_ecc_keypub pub; + uint8_t *d; + size_t d_len; +}; + +sss_status_t se050_key_store_set_ecc_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *object, + struct se050_ecc_keypair *pair, + struct se050_ecc_keypub *pub); + +sss_status_t se050_key_store_get_ecc_key_bin(sss_se05x_key_store_t *store, + sss_se05x_object_t *object, + uint8_t *key, size_t *len); + +sss_status_t se050_ecc_gen_shared_secret(pSe05xSession_t ctx, uint32_t id, + struct se050_ecc_keypub *pub, + uint8_t *secret, size_t *len); + +#endif /* SE050_APDU_APIS_H_ */ diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_sss_apis.h b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_sss_apis.h new file mode 100644 index 0000000..6b20a8f --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_sss_apis.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#ifndef SE050_SSS_APIS_H_ +#define SE050_SSS_APIS_H_ + +#include +#include + +extern sss_policy_t se050_asym_policy; +struct se050_scp_key; + +struct sss_se05x_ctx { + SE_Connect_Ctx_t open_ctx; + sss_se05x_session_t session; + sss_se05x_key_store_t ks; + + struct se050_auth_ctx { + NXSCP03_StaticCtx_t static_ctx; + NXSCP03_DynCtx_t dynamic_ctx; + } se05x_auth; + + sss_user_impl_session_t host_session; + sss_key_store_t host_ks; + + struct se05x_se_info { + uint8_t applet[3]; + uint8_t oefid[2]; + } se_info; +}; + +sss_status_t se050_key_store_and_object_init(struct sss_se05x_ctx *ctx); +sss_status_t se050_enable_scp03(sss_se05x_session_t *session); +sss_status_t se050_rotate_scp03_keys(struct sss_se05x_ctx *ctx); +sss_status_t se050_session_open(struct sss_se05x_ctx *ctx, + struct se050_scp_key *key); +#endif /* SE050_SSS_APIS_H_ */ diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_user_apis.h b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_user_apis.h new file mode 100644 index 0000000..ad83388 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_user_apis.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#ifndef SE050_USER_APIS_H_ +#define SE050_USER_APIS_H_ + +#include +#include +#include +#include +#include + +sss_status_t se050_configure_host(sss_user_impl_session_t *host_session, + sss_key_store_t *host_ks, + SE_Connect_Ctx_t *open_ctx, + struct se050_auth_ctx *auth_ctx, + SE_AuthType_t auth_type, + struct se050_scp_key *keys); + +TEE_Result se050_host_key_store_get_key(sss_key_store_t *ks __unused, + sss_object_t *ko, uint8_t *data, + size_t *byte_len, size_t *bit_len); +#endif /* SE050_USER_APIS_H_ */ diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_utils.h b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_utils.h new file mode 100644 index 0000000..7a0a427 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/include/se050_utils.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#ifndef SE050_UTILS_H_ +#define SE050_UTILS_H_ + +#include +#include + +#define SE050_SCP03_KEY_SZ 16 + +struct se050_scp_key { + uint8_t enc[SE050_SCP03_KEY_SZ]; + uint8_t mac[SE050_SCP03_KEY_SZ]; + uint8_t dek[SE050_SCP03_KEY_SZ]; +}; + +struct s050_scp_rotate_cmd { + uint8_t cmd[128]; + size_t cmd_len; + uint8_t kcv[16]; + size_t kcv_len; +}; + +#define OID_MIN ((uint32_t)(0x00000001)) +#define OID_MAX ((uint32_t)(OID_MIN + 0x7BFFFFFE)) + +#define SE050_KEY_WATERMARK 0x57721566 +#define WATERMARKED(x) \ + ((uint64_t)(((uint64_t)SE050_KEY_WATERMARK) << 32) + (x)) + +sss_status_t se050_get_oid(uint32_t *val); + +struct rsa_keypair; +struct ecc_keypair; + +uint32_t se050_rsa_keypair_from_nvm(struct rsa_keypair *key); +uint32_t se050_ecc_keypair_from_nvm(struct ecc_keypair *key); +uint64_t se050_generate_private_key(uint32_t oid); + +void se050_refcount_init_ctx(uint8_t **cnt); +int se050_refcount_final_ctx(uint8_t *cnt); + +sss_status_t se050_get_se_info(sss_se05x_session_t *session, bool display); + +enum se050_scp03_ksrc { SCP03_CFG, SCP03_DERIVED, SCP03_OFID }; +void se050_scp03_set_enable(enum se050_scp03_ksrc ksrc); +void se050_scp03_set_disable(void); +bool se050_scp03_enabled(void); +sss_status_t se050_scp03_get_current_keys(struct se050_scp_key *keys); +sss_status_t se050_scp03_get_keys(struct se050_scp_key *keys, + enum se050_scp03_ksrc); +sss_status_t se050_scp03_subkey_derive(struct se050_scp_key *keys); +sss_status_t se050_scp03_prepare_rotate_cmd(struct sss_se05x_ctx *ctx, + struct s050_scp_rotate_cmd *cmd, + struct se050_scp_key *keys); +#endif /* SE050_UTILS_H_ */ diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/sub.mk b/optee/optee_os/core/drivers/crypto/se050/adaptors/sub.mk new file mode 100644 index 0000000..87c9ea6 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/sub.mk @@ -0,0 +1,12 @@ +cflags-y += -Wno-strict-aliasing +include ${CFG_NXP_SE05X_PLUG_AND_TRUST}/cflags.mk + +incdirs_ext-y += ${CFG_NXP_SE05X_PLUG_AND_TRUST}/optee_lib/include +incdirs-y += ./include + +srcs-y += utils/scp_config.c +srcs-y += utils/utils.c +srcs-y += utils/info.c +srcs-y += apis/apdu.c +srcs-y += apis/user.c +srcs-y += apis/sss.c diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/info.c b/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/info.c new file mode 100644 index 0000000..aa9759c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/info.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Force the output until the P&T stack fixes its verbosity */ +#define LOG_MAU8_I(msg, buf, len) nLog_au8("Info", 0xff, msg, buf, len) +#define LOG_I(format, ...) nLog("Info", 0xff, format, ##__VA_ARGS__) +#define LOG_E(format, ...) nLog("Info", NX_LEVEL_ERROR, format, ##__VA_ARGS__) +#define LOG_MAU8_E(msg, buf, len) \ + nLog_au8("Info", NX_LEVEL_ERROR, msg, buf, len) + +static sss_status_t jcop4_get_id(void *ctx, bool display) +{ + char jcop_platform_id[17] = { 0 }; + smStatus_t ret = SM_OK; + unsigned char cmd[] = { + 0x80, /* CLA '80' / '00' GlobalPlatform / ISO / IEC */ + 0xCA, /* INS 'CA' GET DATA(IDENTIFY) */ + 0x00, /* P1 '00' High order tag value */ + 0xFE, /* P2 'FE' Low order tag value - proprietary data */ + 0x02, /* Lc '02' Length of data field */ + 0xDF, + 0x28, /* Data 'DF28' Card identification data */ + 0x00 /* Le '00' Length of response data */ + }; + struct msg_rsp { + uint8_t vTag_value_proprietary_data; + uint8_t vLength_of_following_data; + uint8_t vTag_card_identification_data[0x02]; + uint8_t vLength_of_card_identification_data; + uint8_t vTag_configuration_ID; + uint8_t vLength_configuration_ID; + uint8_t vConfiguration_ID[0x0C]; + uint8_t vTag_patch_ID; + uint8_t vLength_patch_ID; + uint8_t vPatch_ID[0x08]; + uint8_t vTag_platform_build_ID1; + uint8_t vLength_platform_build_ID; + uint8_t vPlatform_build_ID[0x18]; + uint8_t vTag_FIPS_mode; + uint8_t vLength_FIPS_mode; + uint8_t vFIPS_mode; + uint8_t vTag_pre_perso_state; + uint8_t vLength_pre_perso_state; + uint8_t vBit_mask_of_pre_perso_state; + uint8_t vTag_ROM_ID; + uint8_t vLength_ROM_ID; + uint8_t vROM_ID[0x08]; + uint8_t vStatus_Word_SW_[0x02]; + } rsp = { 0 }; + uint8_t *p = (uint8_t *)&rsp; + uint32_t len = sizeof(struct msg_rsp); + uint16_t dummy = sizeof(struct msg_rsp); + + ret = GP_Select(ctx, p, 0, p, &dummy); + if (ret != SM_OK) { + LOG_E("Could not select ISD."); + return kStatus_SSS_Fail; + } + + ret = smCom_TransceiveRaw(ctx, cmd, sizeof(cmd), p, &len); + if (ret != SM_OK || len != sizeof(rsp)) { + LOG_MAU8_E("Error reading JCOP ID", p, sizeof(rsp)); + return kStatus_SSS_Fail; + } + + memcpy(se050_ctx.se_info.oefid, &rsp.vConfiguration_ID[2], 2); + if (!display) + return kStatus_SSS_Success; + + LOG_I("SE050 JCOP4 Information:"); + LOG_I("%s = 0x%02X", "Tag value - proprietary data 0xFE", + rsp.vTag_value_proprietary_data); + LOG_I("%s = 0x%02X", "Length of following data 0x45", + rsp.vLength_of_following_data); + LOG_MAU8_I("Tag card identification data", + rsp.vTag_card_identification_data, + sizeof(rsp.vTag_card_identification_data)); + LOG_I("%s = 0x%02X", "Length of card identification data", + rsp.vLength_of_card_identification_data); + LOG_I("%s = 0x%02X", "Tag configuration ID (Must be 0x01)", + rsp.vTag_configuration_ID); + LOG_I("%s = 0x%02X", "Length configuration ID 0x0C", + rsp.vLength_configuration_ID); + LOG_MAU8_I("Configuration ID", + rsp.vConfiguration_ID, sizeof(rsp.vConfiguration_ID)); + LOG_MAU8_I("OEF ID", &rsp.vConfiguration_ID[2], 2); + LOG_I("%s = 0x%02X", "Tag patch ID (Must be 0x02)", rsp.vTag_patch_ID); + LOG_I("%s = 0x%02X", "Length patch ID 0x08", rsp.vLength_patch_ID); + LOG_MAU8_I("Patch ID", rsp.vPatch_ID, sizeof(rsp.vPatch_ID)); + LOG_I("%s = 0x%02X", "Tag platform build ID1 (Must be 0x03)", + rsp.vTag_platform_build_ID1); + LOG_I("%s = 0x%02X", "Length platform build ID 0x18", + rsp.vLength_platform_build_ID); + LOG_MAU8_I("Platform build ID", + rsp.vPlatform_build_ID, sizeof(rsp.vPlatform_build_ID)); + memcpy(jcop_platform_id, rsp.vPlatform_build_ID, 16); + + LOG_I("%s = %s", "JCOP Platform ID", jcop_platform_id); + LOG_I("%s = 0x%02X", "Tag FIPS mode (Must be 0x05)", + rsp.vTag_FIPS_mode); + LOG_I("%s = 0x%02X", "Length FIPS mode 0x01", rsp.vLength_FIPS_mode); + LOG_I("%s = 0x%02X", "FIPS mode var", rsp.vFIPS_mode); + LOG_I("%s = 0x%02X", "Tag pre-perso state (Must be 0x07)", + rsp.vTag_pre_perso_state); + LOG_I("%s = 0x%02X", "Length pre-perso state 0x01", + rsp.vLength_pre_perso_state); + LOG_I("%s = 0x%02X", "Bit mask of pre-perso state var", + rsp.vBit_mask_of_pre_perso_state); + + LOG_I("%s = 0x%02X", "Tag ROM ID (Must be 0x08)", rsp.vTag_ROM_ID); + LOG_I("%s = 0x%02X", "Length ROM ID 0x08", rsp.vLength_ROM_ID); + LOG_MAU8_I("ROM ID", rsp.vROM_ID, sizeof(rsp.vROM_ID)); + LOG_MAU8_I("Status Word (SW)", rsp.vStatus_Word_SW_, + sizeof(rsp.vStatus_Word_SW_)); + + return kStatus_SSS_Success; +} + +#define ITEM(__x) { \ + .name = #__x, \ + .val = (kSE05x_AppletConfig_##__x), \ + } + +static void show_config(uint16_t cfg) +{ + struct items { + uint16_t val; + const char *name; + } features[] = { + ITEM(ECDAA), ITEM(ECDSA_ECDH_ECDHE), ITEM(EDDSA), ITEM(DH_MONT), + ITEM(HMAC), ITEM(RSA_PLAIN), ITEM(RSA_CRT), ITEM(AES), + ITEM(DES), ITEM(PBKDF), ITEM(TLS), ITEM(MIFARE), ITEM(I2CM), + }; + size_t i = 0; + + for (i = 0; i < ARRAY_SIZE(features); i++) { + LOG_I("\t%s%s", cfg & features[i].val ? "with\t" : "without\t", + features[i].name); + } +} + +static sss_status_t applet_get_id(sss_se05x_session_t *session, bool display) +{ + SE05x_Result_t result = kSE05x_Result_NA; + smStatus_t ret = SM_OK; + uint8_t uid[SE050_MODULE_UNIQUE_ID_LEN] = { 0 }; + size_t uidLen = sizeof(uid); + uint8_t applet_version[7] = { 0 }; + size_t applet_versionLen = sizeof(applet_version); + + ret = Se05x_API_CheckObjectExists(&session->s_ctx, + kSE05x_AppletResID_UNIQUE_ID, + &result); + if (ret != SM_OK) + return kStatus_SSS_Fail; + + ret = Se05x_API_ReadObject(&session->s_ctx, + kSE05x_AppletResID_UNIQUE_ID, 0, + (uint16_t)uidLen, uid, &uidLen); + if (ret != SM_OK) + return kStatus_SSS_Fail; + + /* + * VersionInfo is a 7 - byte value consisting of: + * - 1 - byte Major applet version + * - 1 - byte Minor applet version + * - 1 - byte patch applet version + * - 2 - byte AppletConfig, indicating the supported applet features + * - 2-byte Secure Box version: major version (MSB) concatenated with + * minor version (LSB). + */ + ret = Se05x_API_GetVersion(&session->s_ctx, applet_version, + &applet_versionLen); + if (ret != SM_OK) { + LOG_E("Failed Se05x_API_GetVersion"); + return kStatus_SSS_Fail; + } + + memcpy(se050_ctx.se_info.applet, applet_version, 3); + if (!display) + return kStatus_SSS_Success; + + LOG_MAU8_I("Applet ID", uid, uidLen); + + LOG_I("Applet Major = %d", applet_version[0]); + LOG_I("Applet Minor = %d", applet_version[1]); + LOG_I("Applet patch = %d", applet_version[2]); + LOG_I("AppletConfig = %02X%02X", applet_version[3], applet_version[4]); + show_config(applet_version[3] << 8 | applet_version[4]); + LOG_I("Internal = %02X%02X", applet_version[5], applet_version[6]); + + return kStatus_SSS_Success; +} + +sss_status_t se050_get_se_info(sss_se05x_session_t *session, bool display) +{ + sss_status_t ret = kStatus_SSS_Fail; + __maybe_unused uint32_t oefid = 0; + + if (session) { + ret = applet_get_id(session, display); + if (ret != kStatus_SSS_Success) { + EMSG("Can't retrieve Applet information"); + return ret; + } + + ret = jcop4_get_id(session->s_ctx.conn_ctx, display); + if (ret != kStatus_SSS_Success) { + EMSG("Can't retrieve JCOP information"); + return ret; + } + +#ifdef CFG_CORE_SE05X_OEFID + /* validate the requested OEFID against the runtime detected */ + oefid = SHIFT_U32(se050_ctx.se_info.oefid[0], 8) | + SHIFT_U32(se050_ctx.se_info.oefid[1], 0); + + if (oefid != CFG_CORE_SE05X_OEFID) { + EMSG("OEFID configuration error, 0x%x != 0x%"PRIx32, + CFG_CORE_SE05X_OEFID, oefid); + return kStatus_SSS_Fail; + } +#endif + return kStatus_SSS_Success; + } + + return kStatus_SSS_Fail; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/scp_config.c b/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/scp_config.c new file mode 100644 index 0000000..493dede --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/scp_config.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static enum se050_scp03_ksrc scp03_ksrc; +static bool scp03_enabled; + +#define SE050A1 0 +#define SE050A2 1 +#define SE050B1 2 +#define SE050B2 3 +#define SE050C1 4 +#define SE050C2 5 +#define SE050DV 6 +#define SE051A2 7 +#define SE051C2 8 +#define SE050F2 9 +#define SE050E 10 +#define SE051A 11 +#define SE051C 12 +#define SE051W 13 +#define SE050F 14 + +static const struct se050_scp_key se050_default_keys[] = { + [SE050A1] = { + .enc = { 0x34, 0xae, 0x09, 0x67, 0xe3, 0x29, 0xe9, 0x51, + 0x8e, 0x72, 0x65, 0xd5, 0xad, 0xcc, 0x01, 0xc2 }, + .mac = { 0x52, 0xb2, 0x53, 0xca, 0xdf, 0x47, 0x2b, 0xdb, + 0x3d, 0x0f, 0xb3, 0x8e, 0x09, 0x77, 0x00, 0x99 }, + .dek = { 0xac, 0xc9, 0x14, 0x31, 0xfe, 0x26, 0x81, 0x1b, + 0x5e, 0xcb, 0xc8, 0x45, 0x62, 0x0d, 0x83, 0x44 }, + }, + [SE050A2] = { + .enc = { 0x46, 0xa9, 0xc4, 0x8c, 0x34, 0xef, 0xe3, 0x44, + 0xa5, 0x22, 0xe6, 0x67, 0x44, 0xf8, 0x99, 0x6a }, + .mac = { 0x12, 0x03, 0xff, 0x61, 0xdf, 0xbc, 0x9c, 0x86, + 0x19, 0x6a, 0x22, 0x74, 0xae, 0xf4, 0xed, 0x28 }, + .dek = { 0xf7, 0x56, 0x1c, 0x6f, 0x48, 0x33, 0x61, 0x19, + 0xee, 0x39, 0x43, 0x9a, 0xab, 0x34, 0x09, 0x8e }, + }, + [SE050B1] = { + .enc = { 0xd4, 0x99, 0xbc, 0x90, 0xde, 0xa5, 0x42, 0xcf, + 0x78, 0xd2, 0x5e, 0x13, 0xd6, 0x4c, 0xbb, 0x1f }, + .mac = { 0x08, 0x15, 0x55, 0x96, 0x43, 0xfb, 0x79, 0xeb, + 0x85, 0x01, 0xa0, 0xdc, 0x83, 0x3d, 0x90, 0x1f }, + .dek = { 0xbe, 0x7d, 0xdf, 0xb4, 0x06, 0xe8, 0x1a, 0xe4, + 0xe9, 0x66, 0x5a, 0x9f, 0xed, 0x64, 0x26, 0x7c }, + }, + [SE050B2] = { + .enc = { 0x5f, 0xa4, 0x3d, 0x82, 0x02, 0xd2, 0x5e, 0x9a, + 0x85, 0xb1, 0xfe, 0x7e, 0x2d, 0x26, 0x47, 0x8d }, + .mac = { 0x10, 0x5c, 0xea, 0x22, 0x19, 0xf5, 0x2b, 0xd1, + 0x67, 0xa0, 0x74, 0x63, 0xc6, 0x93, 0x79, 0xc3 }, + .dek = { 0xd7, 0x02, 0x81, 0x57, 0xf2, 0xad, 0x37, 0x2c, + 0x74, 0xbe, 0x96, 0x9b, 0xcc, 0x39, 0x06, 0x27 }, + }, + [SE050C1] = { + .enc = { 0x85, 0x2b, 0x59, 0x62, 0xe9, 0xcc, 0xe5, 0xd0, + 0xbe, 0x74, 0x6b, 0x83, 0x3b, 0xcc, 0x62, 0x87 }, + .mac = { 0xdb, 0x0a, 0xa3, 0x19, 0xa4, 0x08, 0x69, 0x6c, + 0x8e, 0x10, 0x7a, 0xb4, 0xe3, 0xc2, 0x6b, 0x47 }, + .dek = { 0x4c, 0x2f, 0x75, 0xc6, 0xa2, 0x78, 0xa4, 0xae, + 0xe5, 0xc9, 0xaf, 0x7c, 0x50, 0xee, 0xa8, 0x0c }, + }, + [SE050C2] = { + .enc = { 0xbd, 0x1d, 0xe2, 0x0a, 0x81, 0xea, 0xb2, 0xbf, + 0x3b, 0x70, 0x9a, 0x9d, 0x69, 0xa3, 0x12, 0x54 }, + .mac = { 0x9a, 0x76, 0x1b, 0x8d, 0xba, 0x6b, 0xed, 0xf2, + 0x27, 0x41, 0xe4, 0x5d, 0x8d, 0x42, 0x36, 0xf5 }, + .dek = { 0x9b, 0x99, 0x3b, 0x60, 0x0f, 0x1c, 0x64, 0xf5, + 0xad, 0xc0, 0x63, 0x19, 0x2a, 0x96, 0xc9, 0x47 }, + }, + [SE050DV] = { + .enc = { 0x35, 0xc2, 0x56, 0x45, 0x89, 0x58, 0xa3, 0x4f, + 0x61, 0x36, 0x15, 0x5f, 0x82, 0x09, 0xd6, 0xcd }, + .mac = { 0xaf, 0x17, 0x7d, 0x5d, 0xbd, 0xf7, 0xc0, 0xd5, + 0xc1, 0x0a, 0x05, 0xb9, 0xf1, 0x60, 0x7f, 0x78 }, + .dek = { 0xa1, 0xbc, 0x84, 0x38, 0xbf, 0x77, 0x93, 0x5b, + 0x36, 0x1a, 0x44, 0x25, 0xfe, 0x79, 0xfa, 0x29 }, + }, + [SE051A2] = { + .enc = { 0x84, 0x0a, 0x5d, 0x51, 0x79, 0x55, 0x11, 0xc9, + 0xce, 0xf0, 0xc9, 0x6f, 0xd2, 0xcb, 0xf0, 0x41 }, + .mac = { 0x64, 0x6b, 0xc2, 0xb8, 0xc3, 0xa4, 0xd9, 0xc1, + 0xfa, 0x8d, 0x71, 0x16, 0xbe, 0x04, 0xfd, 0xfe }, + .dek = { 0x03, 0xe6, 0x69, 0x9a, 0xca, 0x94, 0x26, 0xd9, + 0xc3, 0x89, 0x22, 0xf8, 0x91, 0x4c, 0xe5, 0xf7 }, + }, + [SE051C2] = { + .enc = { 0x88, 0xdb, 0xcd, 0x65, 0x82, 0x0d, 0x2a, 0xa0, + 0x6f, 0xfa, 0xb9, 0x2a, 0xa8, 0xe7, 0x93, 0x64 }, + .mac = { 0xa8, 0x64, 0x4e, 0x2a, 0x04, 0xd9, 0xe9, 0xc8, + 0xc0, 0xea, 0x60, 0x86, 0x68, 0x29, 0x99, 0xe5 }, + .dek = { 0x8a, 0x38, 0x72, 0x38, 0x99, 0x88, 0x18, 0x44, + 0xe2, 0xc1, 0x51, 0x3d, 0xac, 0xd9, 0xf8, 0x0d }, + }, + [SE050F2] = { + .enc = { 0x91, 0x88, 0xda, 0x8c, 0xf3, 0x69, 0xcf, 0xa9, + 0xa0, 0x08, 0x91, 0x62, 0x7b, 0x65, 0x34, 0x5a }, + .mac = { 0xcb, 0x20, 0xf8, 0x09, 0xc7, 0xa0, 0x39, 0x32, + 0xbc, 0x20, 0x3b, 0x0a, 0x01, 0x81, 0x6c, 0x81 }, + .dek = { 0x27, 0x8e, 0x61, 0x9d, 0x83, 0x51, 0x8e, 0x14, + 0xc6, 0xf1, 0xe4, 0xfa, 0x96, 0x8b, 0xe5, 0x1c }, + }, + [SE050E] = { + .enc = { 0xd2, 0xdb, 0x63, 0xe7, 0xa0, 0xa5, 0xae, 0xd7, + 0x2a, 0x64, 0x60, 0xc4, 0xdf, 0xdc, 0xaf, 0x64 }, + .mac = { 0x73, 0x8d, 0x5b, 0x79, 0x8e, 0xd2, 0x41, 0xb0, + 0xb2, 0x47, 0x68, 0x51, 0x4b, 0xfb, 0xa9, 0x5b }, + .dek = { 0x67, 0x02, 0xda, 0xc3, 0x09, 0x42, 0xb2, 0xc8, + 0x5e, 0x7f, 0x47, 0xb4, 0x2c, 0xed, 0x4e, 0x7f }, + }, + [SE051A] = { + .enc = { 0x88, 0xea, 0x9f, 0xa6, 0x86, 0xf3, 0xcf, 0x2f, + 0xfc, 0xaf, 0x4b, 0x1c, 0xba, 0x93, 0xe4, 0x42 }, + .mac = { 0x4f, 0x16, 0x3f, 0x59, 0xf0, 0x74, 0x31, 0xf4, + 0x3e, 0xe2, 0xee, 0x18, 0x34, 0xa5, 0x23, 0x34 }, + .dek = { 0xd4, 0x76, 0xcf, 0x47, 0xaa, 0x27, 0xb5, 0x4a, + 0xb3, 0xdb, 0xeb, 0xe7, 0x65, 0x6d, 0x67, 0x70 }, + }, + [SE051C] = { + .enc = { 0xbf, 0xc2, 0xdb, 0xe1, 0x82, 0x8e, 0x03, 0x5d, + 0x3e, 0x7f, 0xa3, 0x6b, 0x90, 0x2a, 0x05, 0xc6 }, + .mac = { 0xbe, 0xf8, 0x5b, 0xd7, 0xba, 0x04, 0x97, 0xd6, + 0x28, 0x78, 0x1c, 0xe4, 0x7b, 0x18, 0x8c, 0x96 }, + .dek = { 0xd8, 0x73, 0xf3, 0x16, 0xbe, 0x29, 0x7f, 0x2f, + 0xc9, 0xc0, 0xe4, 0x5f, 0x54, 0x71, 0x06, 0x99 } + }, + [SE051W] = { + .enc = { 0x18, 0xb3, 0xb4, 0xe3, 0x40, 0xc0, 0x80, 0xd9, + 0x9b, 0xeb, 0xb8, 0xb8, 0x64, 0x4b, 0x8c, 0x52 }, + .mac = { 0x3d, 0x0c, 0xfa, 0xc8, 0x7b, 0x96, 0x7c, 0x00, + 0xe3, 0x3b, 0xa4, 0x96, 0x61, 0x38, 0x38, 0xa2 }, + .dek = { 0x68, 0x06, 0x83, 0xf9, 0x4e, 0x6b, 0xcb, 0x94, + 0x73, 0xec, 0xc1, 0x56, 0x7a, 0x1b, 0xd1, 0x09 }, + }, + [SE050F] = { + .enc = { 0xB5, 0x0E, 0x1F, 0x12, 0xB8, 0x1F, 0xE5, 0x3B, + 0x6C, 0x3B, 0x53, 0x87, 0x91, 0x2A, 0x1A, 0x5A, }, + .mac = { 0x71, 0x93, 0x69, 0x59, 0xD3, 0x7F, 0x2B, 0x22, + 0xC5, 0xA0, 0xC3, 0x49, 0x19, 0xA2, 0xBC, 0x1F, }, + .dek = { 0x86, 0x95, 0x93, 0x23, 0x98, 0x54, 0xDC, 0x0D, + 0x86, 0x99, 0x00, 0x50, 0x0C, 0xA7, 0x9C, 0x15, }, + }, +}; + +static sss_status_t get_id_from_ofid(uint32_t ofid, uint32_t *id) +{ + switch (ofid) { + case SE050A1_ID: + *id = SE050A1; + break; + case SE050A2_ID: + *id = SE050A2; + break; + case SE050B1_ID: + *id = SE050B1; + break; + case SE050B2_ID: + *id = SE050B2; + break; + case SE050C1_ID: + *id = SE050C1; + break; + case SE050C2_ID: + *id = SE050C2; + break; + case SE050DV_ID: + *id = SE050DV; + break; + case SE051A2_ID: + *id = SE051A2; + break; + case SE051C2_ID: + *id = SE051C2; + break; + case SE050F2_ID: + *id = SE050F2; + break; + case SE050E_ID: + *id = SE050E; + break; + case SE051A_ID: + *id = SE051A; + break; + case SE051C_ID: + *id = SE051C; + break; + case SE051W_ID: + *id = SE051W; + break; + case SE050F_ID: + *id = SE050F; + break; + default: + return kStatus_SSS_Fail; + } + + return kStatus_SSS_Success; +} + +static sss_status_t encrypt_key_and_get_kcv(uint8_t *enc, uint8_t *kc, + uint8_t *key, + struct sss_se05x_ctx *ctx, + uint32_t id) +{ + static const uint8_t ones[] = { [0 ... AES_KEY_LEN_nBYTE - 1] = 1 }; + uint8_t enc_len = AES_KEY_LEN_nBYTE; + uint8_t kc_len = AES_KEY_LEN_nBYTE; + sss_status_t st = kStatus_SSS_Fail; + sss_object_t *dek_object = NULL; + sss_se05x_symmetric_t symm = { }; + sss_se05x_object_t ko = { }; + uint8_t dek[AES_KEY_LEN_nBYTE] = { 0 }; + size_t dek_len = sizeof(dek); + size_t dek_bit_len = dek_len * 8; + + st = sss_se05x_key_object_init(&ko, &ctx->ks); + if (st != kStatus_SSS_Success) + return kStatus_SSS_Fail; + + st = sss_se05x_key_object_allocate_handle(&ko, id, + kSSS_KeyPart_Default, + kSSS_CipherType_AES, + AES_KEY_LEN_nBYTE, + kKeyObject_Mode_Transient); + if (st != kStatus_SSS_Success) + return kStatus_SSS_Fail; + + st = sss_se05x_key_store_set_key(&ctx->ks, &ko, key, AES_KEY_LEN_nBYTE, + AES_KEY_LEN_nBYTE * 8, NULL, 0); + if (st != kStatus_SSS_Success) + goto out; + + st = sss_se05x_symmetric_context_init(&symm, &ctx->session, &ko, + kAlgorithm_SSS_AES_ECB, + kMode_SSS_Encrypt); + if (st != kStatus_SSS_Success) + goto out; + + st = sss_se05x_cipher_one_go(&symm, NULL, 0, ones, kc, kc_len); + if (st != kStatus_SSS_Success) + goto out; + + dek_object = &ctx->open_ctx.auth.ctx.scp03.pStatic_ctx->Dek; + if (se050_host_key_store_get_key(&ctx->host_ks, dek_object, + dek, &dek_len, &dek_bit_len)) + goto out; + + st = sss_se05x_key_store_set_key(&ctx->ks, &ko, dek, AES_KEY_LEN_nBYTE, + AES_KEY_LEN_nBYTE * 8, NULL, 0); + if (st != kStatus_SSS_Success) + goto out; + + st = sss_se05x_cipher_one_go(&symm, NULL, 0, key, enc, enc_len); +out: + if (symm.keyObject) + sss_se05x_symmetric_context_free(&symm); + + sss_se05x_key_object_free(&ko); + + Se05x_API_DeleteSecureObject(&ctx->session.s_ctx, id); + + return st; +} + +static sss_status_t prepare_key_data(uint8_t *key, uint8_t *cmd, + struct sss_se05x_ctx *ctx, uint32_t id) +{ + uint8_t kc[AES_KEY_LEN_nBYTE] = { 0 }; + sss_status_t status = kStatus_SSS_Fail; + + cmd[0] = PUT_KEYS_KEY_TYPE_CODING_AES; + cmd[1] = AES_KEY_LEN_nBYTE + 1; + cmd[2] = AES_KEY_LEN_nBYTE; + cmd[3 + AES_KEY_LEN_nBYTE] = CRYPTO_KEY_CHECK_LEN; + + status = encrypt_key_and_get_kcv(&cmd[3], kc, key, ctx, id); + if (status != kStatus_SSS_Success) + return status; + + memcpy(&cmd[3 + AES_KEY_LEN_nBYTE + 1], kc, CRYPTO_KEY_CHECK_LEN); + + return kStatus_SSS_Success; +} + +sss_status_t se050_scp03_prepare_rotate_cmd(struct sss_se05x_ctx *ctx, + struct s050_scp_rotate_cmd *cmd, + struct se050_scp_key *keys) + +{ + sss_status_t status = kStatus_SSS_Fail; + size_t kcv_len = 0; + size_t cmd_len = 0; + uint8_t key_version = 0; + uint8_t *key[] = { + [0] = keys->enc, + [1] = keys->mac, + [2] = keys->dek, + }; + uint32_t oid = 0; + size_t i = 0; + + key_version = ctx->open_ctx.auth.ctx.scp03.pStatic_ctx->keyVerNo; + cmd->cmd[cmd_len] = key_version; + cmd_len += 1; + + cmd->kcv[kcv_len] = key_version; + kcv_len += 1; + + for (i = 0; i < ARRAY_SIZE(key); i++) { + status = se050_get_oid(&oid); + if (status != kStatus_SSS_Success) + return kStatus_SSS_Fail; + + status = prepare_key_data(key[i], &cmd->cmd[cmd_len], ctx, oid); + if (status != kStatus_SSS_Success) + return kStatus_SSS_Fail; + + memcpy(&cmd->kcv[kcv_len], + &cmd->cmd[cmd_len + 3 + AES_KEY_LEN_nBYTE + 1], + CRYPTO_KEY_CHECK_LEN); + + cmd_len += 3 + AES_KEY_LEN_nBYTE + 1 + CRYPTO_KEY_CHECK_LEN; + kcv_len += CRYPTO_KEY_CHECK_LEN; + } + + cmd->cmd_len = cmd_len; + cmd->kcv_len = kcv_len; + + return kStatus_SSS_Success; +} + +static sss_status_t get_ofid_key(struct se050_scp_key *keys) +{ + uint32_t oefid = SHIFT_U32(se050_ctx.se_info.oefid[0], 8) | + SHIFT_U32(se050_ctx.se_info.oefid[1], 0); + sss_status_t status = kStatus_SSS_Success; + uint32_t id = 0; + + status = get_id_from_ofid(oefid, &id); + if (status != kStatus_SSS_Success) + return status; + + memcpy(keys, &se050_default_keys[id], sizeof(*keys)); + return kStatus_SSS_Success; +} + +static sss_status_t get_config_key(struct se050_scp_key *keys __maybe_unused) +{ +#ifdef CFG_CORE_SE05X_SCP03_CURRENT_DEK + struct se050_scp_key current_keys = { + .dek = { CFG_CORE_SE05X_SCP03_CURRENT_DEK }, + .mac = { CFG_CORE_SE05X_SCP03_CURRENT_MAC }, + .enc = { CFG_CORE_SE05X_SCP03_CURRENT_ENC }, + }; + + memcpy(keys, ¤t_keys, sizeof(*keys)); + return kStatus_SSS_Success; +#else + return kStatus_SSS_Fail; +#endif +} + +static const char * __maybe_unused get_scp03_ksrc_name(enum se050_scp03_ksrc k) +{ + switch (k) { + case SCP03_DERIVED: + return "derived"; + case SCP03_CFG: + return "built-in"; + case SCP03_OFID: + return "factory"; + default: + panic(); + } + + return NULL; +} + +sss_status_t se050_scp03_subkey_derive(struct se050_scp_key *keys) +{ + struct { + const char *name; + uint8_t *data; + } key[3] = { + [0] = { .name = "dek", .data = keys->dek }, + [1] = { .name = "mac", .data = keys->mac }, + [2] = { .name = "enc", .data = keys->enc }, + }; + uint8_t msg[SE050_SCP03_KEY_SZ + 3] = { 0 }; + size_t i = 0; + + if (IS_ENABLED(CFG_CORE_SCP03_ONLY)) { + memset(msg, 0x55, sizeof(msg)); + } else { + /* add some randomness */ + if (tee_otp_get_die_id(msg + 3, SE050_SCP03_KEY_SZ)) + return kStatus_SSS_Fail; + } + + for (i = 0; i < ARRAY_SIZE(key); i++) { + memcpy(msg, key[i].name, 3); + if (huk_subkey_derive(HUK_SUBKEY_SE050, msg, sizeof(msg), + key[i].data, SE050_SCP03_KEY_SZ)) + return kStatus_SSS_Fail; + } + + return kStatus_SSS_Success; +} + +bool se050_scp03_enabled(void) +{ + return scp03_enabled; +} + +void se050_scp03_set_enable(enum se050_scp03_ksrc ksrc) +{ + scp03_enabled = true; + scp03_ksrc = ksrc; + + IMSG("SE05X SCP03 using %s keys", get_scp03_ksrc_name(ksrc)); +} + +void se050_scp03_set_disable(void) +{ + scp03_enabled = false; +} + +sss_status_t se050_scp03_get_keys(struct se050_scp_key *keys, + enum se050_scp03_ksrc ksrc) +{ + switch (ksrc) { + case SCP03_CFG: + return get_config_key(keys); + case SCP03_DERIVED: + return se050_scp03_subkey_derive(keys); + case SCP03_OFID: + return get_ofid_key(keys); + default: + return kStatus_SSS_Fail; + } +} + +sss_status_t se050_scp03_get_current_keys(struct se050_scp_key *keys) +{ + if (se050_scp03_enabled()) + return se050_scp03_get_keys(keys, scp03_ksrc); + + return kStatus_SSS_Fail; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c b/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c new file mode 100644 index 0000000..88fcad9 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/adaptors/utils/utils.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include + +/* exp: minimal amount of transient memory required to generate an RSA key */ +#define TRANSIENT_MEMORY_THRESHOLD 0x140 + +#define NBR_OID ((uint32_t)(OID_MAX - OID_MIN)) +#define IS_WATERMARKED(x) (((x) & WATERMARKED(0)) == WATERMARKED(0)) + +static void delete_transient_objects(void) +{ + SE05x_AttestationType_t att = kSE05x_AttestationType_None; + SE05x_SecureObjectType_t type = kSE05x_SecObjTyp_HMAC_KEY; + uint8_t more = kSE05x_MoreIndicator_NA; + smStatus_t status = SM_NOT_OK; + Se05xSession_t *ctx = NULL; + uint8_t *list = NULL; + size_t len = 1024; + uint16_t offset = 0; + uint8_t mode = 0; + uint32_t id = 0; + size_t i = 0; + + if (!se050_session) + return; + + ctx = &se050_session->s_ctx; + + list = calloc(1, len); + if (!list) + return; + do { + status = Se05x_API_ReadIDList(ctx, offset, 0xFF, &more, + list, &len); + if (status != SM_OK) + break; + + offset = len; + for (i = 0; i < len; i += 4) { + id = (list[i + 0] << (3 * 8)) | + (list[i + 1] << (2 * 8)) | + (list[i + 2] << (1 * 8)) | + (list[i + 3] << (0 * 8)); + + if (id >= OID_MAX || id == 0) + continue; + + status = Se05x_API_ReadType(ctx, id, &type, &mode, att); + if (status != SM_OK) + continue; + + if (mode == kKeyObject_Mode_Transient) + Se05x_API_DeleteSecureObject(ctx, id); + } + } while (more == kSE05x_MoreIndicator_MORE); + + free(list); +} + +static sss_status_t generate_oid(uint32_t *val) +{ + uint32_t oid = OID_MIN; + uint32_t random = 0; + size_t i = 0; + + for (i = 0; i < NBR_OID; i++) { + if (crypto_rng_read(&random, sizeof(random))) + return kStatus_SSS_Fail; + + oid = OID_MIN + (random & OID_MAX); + + /* + * The less significant byte different than zero prevents bignum + * conversions from discarding it + */ + if (oid > OID_MAX || !(oid & 0xFF)) + continue; + + if (!se050_key_exists(oid, &se050_session->s_ctx)) { + *val = oid; + return kStatus_SSS_Success; + } + } + + return kStatus_SSS_Fail; +} + +sss_status_t se050_get_oid(uint32_t *val) +{ + sss_status_t status = kStatus_SSS_Success; + uint16_t mem_t = 0; + + if (!val) + return kStatus_SSS_Fail; + + status = se050_get_free_memory(&se050_session->s_ctx, &mem_t, + kSE05x_MemoryType_TRANSIENT_DESELECT); + if (status != kStatus_SSS_Success) + return kStatus_SSS_Fail; + + if (mem_t < TRANSIENT_MEMORY_THRESHOLD) + delete_transient_objects(); + + return generate_oid(val); +} + +static uint32_t se050_key(uint64_t key) +{ + uint32_t oid = (uint32_t)key; + + if (!IS_WATERMARKED(key)) + return 0; + + /* oid > OID_MAX could have been created by an external client */ + if (oid < OID_MIN) + return 0; + + return oid; +} + +uint32_t se050_rsa_keypair_from_nvm(struct rsa_keypair *key) +{ + uint64_t key_id = 0; + + if (!key) + return 0; + + if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t)) + return 0; + + crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id); + + return se050_key(key_id); +} + +uint32_t se050_ecc_keypair_from_nvm(struct ecc_keypair *key) +{ + uint64_t key_id = 0; + + if (!key) + return 0; + + if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t)) + return 0; + + crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id); + + return se050_key(key_id); +} + +uint64_t se050_generate_private_key(uint32_t oid) +{ + return WATERMARKED(oid); +} + +void se050_refcount_init_ctx(uint8_t **cnt) +{ + if (!*cnt) { + *cnt = calloc(1, sizeof(uint8_t)); + if (*cnt) + **cnt = 1; + else + EMSG("can't allocate refcount"); + } else { + **cnt = **cnt + 1; + } +} + +int se050_refcount_final_ctx(uint8_t *cnt) +{ + if (!cnt) + return 1; + + if (!*cnt) { + free(cnt); + return 1; + } + + *cnt = *cnt - 1; + + return 0; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/core/apdu.c b/optee/optee_os/core/drivers/crypto/se050/core/apdu.c new file mode 100644 index 0000000..c526e0d --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/apdu.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2021 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include + +TEE_Result crypto_se_do_apdu(enum crypto_apdu_type type, + uint8_t *hdr, size_t hdr_len, + uint8_t *src_data, size_t src_len, + uint8_t *dst_data, size_t *dst_len) +{ + sss_status_t status = kStatus_SSS_Fail; + + status = sss_se05x_do_apdu(&se050_session->s_ctx, type, + hdr, hdr_len, src_data, src_len, + dst_data, dst_len); + if (status != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/core/cipher.c b/optee/optee_os/core/drivers/crypto/se050/core/cipher.c new file mode 100644 index 0000000..ce0a1e5 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/cipher.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result do_init(struct drvcrypt_cipher_init *dinit) +{ + struct crypto_cipher_ctx *ctx = dinit->ctx; + TEE_OperationMode mode = TEE_MODE_DECRYPT; + + if (dinit->encrypt) + mode = TEE_MODE_ENCRYPT; + + return ctx->ops->init(dinit->ctx, mode, + dinit->key1.data, dinit->key1.length, + dinit->key2.data, dinit->key2.length, + dinit->iv.data, dinit->iv.length); +} + +static TEE_Result do_update(struct drvcrypt_cipher_update *dupdate) +{ + struct crypto_cipher_ctx *ctx = dupdate->ctx; + + return ctx->ops->update(ctx, dupdate->last, dupdate->src.data, + dupdate->src.length, dupdate->dst.data); +} + +static void do_final(void *context) +{ + struct crypto_cipher_ctx *ctx = context; + + ctx->ops->final(ctx); +} + +static void do_free(void *context) +{ + struct crypto_cipher_ctx *ctx = context; + + ctx->ops->free_ctx(ctx); +} + +static void do_copy_state(void *out, void *in) +{ + struct crypto_cipher_ctx *dst_ctx = out; + struct crypto_cipher_ctx *src_ctx = in; + + src_ctx->ops->copy_state(dst_ctx, src_ctx); +} + +static TEE_Result do_allocate(void **ctx, uint32_t algo) +{ + switch (algo) { + case TEE_ALG_AES_CTR: + return se050_aes_ctr_allocate(ctx); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +static struct drvcrypt_cipher driver_cipher = { + .alloc_ctx = do_allocate, + .free_ctx = do_free, + .init = do_init, + .update = do_update, + .final = do_final, + .copy_state = do_copy_state, +}; + +static TEE_Result se050_cipher_init(void) +{ + return drvcrypt_register_cipher(&driver_cipher); +} + +driver_init_late(se050_cipher_init); diff --git a/optee/optee_os/core/drivers/crypto/se050/core/ctr.c b/optee/optee_os/core/drivers/crypto/se050/core/ctr.c new file mode 100644 index 0000000..1b161fa --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/ctr.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include + +struct se050_aes_ctr_ctx { + struct crypto_cipher_ctx ctx; + sss_se05x_symmetric_t aes_ctx; + sss_se05x_object_t key_obj; + uint8_t *cnt; /* shared reference counter for duplicated ciphers */ + int nc_off; + unsigned char counter[TEE_AES_BLOCK_SIZE]; + unsigned char block[TEE_AES_BLOCK_SIZE]; +}; + +static struct se050_aes_ctr_ctx *to_aes_ctr_ctx(struct crypto_cipher_ctx *ctx) +{ + return container_of(ctx, struct se050_aes_ctr_ctx, ctx); +} + +static TEE_Result se050_aes_ctr_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode __unused, + const uint8_t *key1, + size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv, size_t iv_len __unused) +{ + struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); + sss_status_t st = kStatus_SSS_Success; + uint32_t oid = 0; + + if (c->key_obj.keyId) + goto init; + + memcpy(c->counter, iv, sizeof(c->counter)); + + st = sss_se05x_key_object_init(&c->key_obj, se050_kstore); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + st = se050_get_oid(&oid); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + st = sss_se05x_key_object_allocate_handle(&c->key_obj, oid, + kSSS_KeyPart_Default, + kSSS_CipherType_AES, 0, + kKeyObject_Mode_Transient); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + st = sss_se05x_key_store_set_key(se050_kstore, &c->key_obj, + key1, key1_len, key1_len * 8, NULL, 0); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + st = sss_se05x_symmetric_context_init(&c->aes_ctx, se050_session, + &c->key_obj, + kAlgorithm_SSS_AES_ECB, + kMode_SSS_Encrypt); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; +init: + st = sss_se05x_cipher_init(&c->aes_ctx, (uint8_t *)NULL, 0); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result se050_aes_ctr_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, + uint8_t *dst) +{ + struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); + sss_status_t st = kStatus_SSS_Success; + size_t dst_len = len; + int i = 0; + int n = 0; + int j = 0; + + n = c->nc_off; + while (len--) { + dst_len = sizeof(c->counter); + if (n == 0) { + st = sss_se05x_cipher_update(&c->aes_ctx, + c->counter, 16, + c->block, &dst_len); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_STATE; + + for (i = 16; i > 0; i--) + if (++c->counter[i - 1] != 0) + break; + } + j = *data++; + *dst++ = (unsigned char)(j ^ c->block[n]); + n = (n + 1) & 0x0F; + } + + c->nc_off = n; + return TEE_SUCCESS; +} + +static void do_final(struct crypto_cipher_ctx *ctx) +{ + struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); + + if (!se050_refcount_final_ctx(c->cnt)) { + memset(c->block, 0, sizeof(c->block)); + return; + } + + if (c->key_obj.keyId) + sss_se05x_key_store_erase_key(se050_kstore, &c->key_obj); + + sss_se05x_symmetric_context_free(&c->aes_ctx); +} + +static void do_free(struct crypto_cipher_ctx *ctx) +{ + free(to_aes_ctr_ctx(ctx)); +} + +static void do_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct se050_aes_ctr_ctx *src = to_aes_ctr_ctx(src_ctx); + struct se050_aes_ctr_ctx *dst = to_aes_ctr_ctx(dst_ctx); + + se050_refcount_init_ctx(&src->cnt); + memcpy(dst, src, sizeof(*dst)); +} + +static struct crypto_cipher_ops aes_ctr_ops = { + .update = se050_aes_ctr_update, + .copy_state = do_copy_state, + .init = se050_aes_ctr_init, + .free_ctx = do_free, + .final = do_final, +}; + +TEE_Result se050_aes_ctr_allocate(void **ctx) +{ + struct se050_aes_ctr_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &aes_ctr_ops; + *ctx = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/core/die_id.c b/optee/optee_os/core/drivers/crypto/se050/core/die_id.c new file mode 100644 index 0000000..cf4fc92 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/die_id.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include + +int tee_otp_get_die_id(uint8_t *buffer, size_t len) +{ + uint8_t die_id[SE050_MODULE_UNIQUE_ID_LEN] = { 0 }; + size_t die_id_len = sizeof(die_id); + sss_status_t status = kStatus_SSS_Fail; + + status = sss_se05x_session_prop_get_au8(se050_session, + kSSS_SessionProp_UID, + die_id, &die_id_len); + if (status != kStatus_SSS_Success) + return -1; + + if (tee_hash_createdigest(TEE_ALG_SHA256, die_id, die_id_len, buffer, + len)) + return -1; + + return 0; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/core/ecc.c b/optee/optee_os/core/drivers/crypto/se050/core/ecc.c new file mode 100644 index 0000000..1d942df --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/ecc.c @@ -0,0 +1,810 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct crypto_ecc_keypair_ops *pair_ops; +static const struct crypto_ecc_public_ops *pub_ops; + +static bool oefid_key_supported(size_t bits) +{ + switch (se050_get_oefid()) { + case SE050F_ID: + return bits >= 224; + default: + return true; + } +} + +static bool oefid_algo_supported(uint32_t algo) +{ + switch (se050_get_oefid()) { + case SE050F_ID: + switch (algo) { + case TEE_ALG_ECDSA_SHA224: + case TEE_ALG_ECDSA_SHA256: + case TEE_ALG_ECDSA_SHA384: + case TEE_ALG_ECDSA_SHA512: + return true; + default: + return false; + } + default: + return true; + } +} + +static uint32_t algo_tee2se050(uint32_t algo) +{ + switch (algo) { + case TEE_ALG_ECDSA_SHA1: + return kAlgorithm_SSS_ECDSA_SHA1; + case TEE_ALG_ECDSA_SHA224: + return kAlgorithm_SSS_ECDSA_SHA224; + case TEE_ALG_ECDSA_SHA256: + return kAlgorithm_SSS_ECDSA_SHA256; + case TEE_ALG_ECDSA_SHA384: + return kAlgorithm_SSS_ECDSA_SHA384; + case TEE_ALG_ECDSA_SHA512: + return kAlgorithm_SSS_ECDSA_SHA512; + default: + EMSG("algorithm %#"PRIx32" not enabled", algo); + return kAlgorithm_None; + } +} + +static uint32_t cipher_tee2se050(uint32_t curve) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + case TEE_ECC_CURVE_NIST_P224: + case TEE_ECC_CURVE_NIST_P256: + case TEE_ECC_CURVE_NIST_P384: + case TEE_ECC_CURVE_NIST_P521: + return kSSS_CipherType_EC_NIST_P; + default: + EMSG("cipher %#"PRIx32" not enabled", curve); + return kSSS_CipherType_NONE; + } +} + +static uint32_t curve_tee2se050(uint32_t curve) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + return kSE05x_ECCurve_NIST_P192; + case TEE_ECC_CURVE_NIST_P224: + return kSE05x_ECCurve_NIST_P224; + case TEE_ECC_CURVE_NIST_P256: + return kSE05x_ECCurve_NIST_P256; + case TEE_ECC_CURVE_NIST_P384: + return kSE05x_ECCurve_NIST_P384; + case TEE_ECC_CURVE_NIST_P521: + return kSE05x_ECCurve_NIST_P521; + default: + EMSG("curve %#"PRIx32" not enabled", curve); + return kSE05x_ECCurve_NA; + } +} + +static uint32_t curve_se0502tee(uint32_t curve) +{ + switch (curve) { + case kSE05x_ECCurve_NIST_P192: + return TEE_ECC_CURVE_NIST_P192; + case kSE05x_ECCurve_NIST_P224: + return TEE_ECC_CURVE_NIST_P224; + case kSE05x_ECCurve_NIST_P256: + return TEE_ECC_CURVE_NIST_P256; + case kSE05x_ECCurve_NIST_P384: + return TEE_ECC_CURVE_NIST_P384; + case kSE05x_ECCurve_NIST_P521: + return TEE_ECC_CURVE_NIST_P521; + default: + EMSG("curve %#"PRIx32" not enabled", curve); + return TEE_CRYPTO_ELEMENT_NONE; + } +} + +static bool bn_alloc_max(struct bignum **s) +{ + *s = crypto_bignum_allocate(4096); + + return *s; +} + +static TEE_Result ecc_get_key_size(uint32_t curve, uint32_t algo, + size_t *bytes, size_t *bits) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + *bits = 192; + *bytes = 24; + break; + case TEE_ECC_CURVE_NIST_P224: + *bits = 224; + *bytes = 28; + break; + case TEE_ECC_CURVE_NIST_P256: + *bits = 256; + *bytes = 32; + break; + case TEE_ECC_CURVE_NIST_P384: + *bits = 384; + *bytes = 48; + break; + case TEE_ECC_CURVE_NIST_P521: + *bits = 521; + *bytes = 66; + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + + if (!oefid_key_supported(*bits)) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (!oefid_algo_supported(algo)) + return TEE_ERROR_NOT_IMPLEMENTED; + + return TEE_SUCCESS; +} + +static TEE_Result ecc_prepare_msg(uint32_t algo, const uint8_t *msg, + size_t *msg_len, uint8_t **msg_padded) +{ + struct { + uint32_t algo; + size_t len; + } map[] = { + { kAlgorithm_SSS_ECDSA_SHA1, TEE_SHA1_HASH_SIZE }, + { kAlgorithm_SSS_ECDSA_SHA224, TEE_SHA224_HASH_SIZE }, + { kAlgorithm_SSS_ECDSA_SHA256, TEE_SHA256_HASH_SIZE }, + { kAlgorithm_SSS_ECDSA_SHA384, TEE_SHA384_HASH_SIZE }, + { kAlgorithm_SSS_ECDSA_SHA512, TEE_SHA512_HASH_SIZE }, + }; + size_t i = 0; + + for (i = 0; i < ARRAY_SIZE(map); i++) { + if (algo == map[i].algo) + break; + } + + if (i >= ARRAY_SIZE(map)) + return TEE_ERROR_BAD_PARAMETERS; + + if (*msg_len >= map[i].len) { + /* truncate */ + *msg_len = map[i].len; + return TEE_SUCCESS; + } + + /* pad */ + *msg_padded = calloc(1, map[i].len); + if (!*msg_padded) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(*msg_padded, msg, *msg_len); + *msg_len = map[i].len; + + return TEE_SUCCESS; +} + +static TEE_Result set_binary_data(struct bignum *b, size_t key_len, uint8_t **p, + size_t *len) +{ + size_t a = crypto_bignum_num_bytes(b); + uint8_t leading_zeros = 0; + uint8_t *q = NULL; + + if (!a) + return TEE_ERROR_GENERIC; + + if (a != key_len) { + leading_zeros = key_len - a; + a = key_len; + } + + q = calloc(1, a); + if (!q) + return TEE_ERROR_OUT_OF_MEMORY; + + crypto_bignum_bn2bin(b, q + leading_zeros); + *len = a; + *p = q; + + return TEE_SUCCESS; +} + +static TEE_Result se050_inject_public_key(sss_se05x_object_t *k_object, + struct ecc_public_key *key, + size_t key_len) +{ + struct se050_ecc_keypub key_bin = { }; + TEE_Result ret = TEE_ERROR_GENERIC; + sss_status_t st = kStatus_SSS_Fail; + uint32_t oid = 0; + + st = sss_se05x_key_object_init(k_object, se050_kstore); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * This function might return an error if the curve already + * exists in the secure element. An actual error creating the + * curve will be caught when attempting to set the key. + */ + sss_se05x_key_store_create_curve(&se050_session->s_ctx, + curve_tee2se050(key->curve)); + + st = se050_get_oid(&oid); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + st = sss_se05x_key_object_allocate_handle(k_object, oid, + kSSS_KeyPart_Public, + cipher_tee2se050(key->curve), + 0, + kKeyObject_Mode_Transient); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + ret = set_binary_data(key->x, key_len, &key_bin.x, &key_bin.x_len); + if (ret != TEE_SUCCESS) + return ret; + + ret = set_binary_data(key->y, key_len, &key_bin.y, &key_bin.y_len); + if (ret != TEE_SUCCESS) { + free(key_bin.x); + return ret; + } + + key_bin.curve = curve_tee2se050(key->curve); + st = se050_key_store_set_ecc_key_bin(se050_kstore, k_object, NULL, + &key_bin); + free(key_bin.x); + free(key_bin.y); + if (st != kStatus_SSS_Success) { + EMSG("Can't inject transient key, curve: %#"PRIx32, key->curve); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result se050_inject_keypair(sss_se05x_object_t *k_object, + struct ecc_keypair *key, + size_t key_len) +{ + struct se050_ecc_keypair key_bin = { }; + sss_status_t st = kStatus_SSS_Fail; + TEE_Result ret = TEE_ERROR_GENERIC; + uint32_t key_id = 0; + uint32_t oid = 0; + + st = sss_se05x_key_object_init(k_object, se050_kstore); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + key_id = se050_ecc_keypair_from_nvm(key); + if (key_id) { + st = sss_se05x_key_object_get_handle(k_object, key_id); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; + } + + /* + * This function might return an error if the curve already + * exists in the secure element. An actual error creating the + * curve will be caught when attempting to set the key. + */ + sss_se05x_key_store_create_curve(&se050_session->s_ctx, + curve_tee2se050(key->curve)); + + st = se050_get_oid(&oid); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + st = sss_se05x_key_object_allocate_handle(k_object, oid, + kSSS_KeyPart_Pair, + cipher_tee2se050(key->curve), + 0, + kKeyObject_Mode_Transient); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + ret = set_binary_data(key->d, key_len, &key_bin.d, &key_bin.d_len); + if (ret != TEE_SUCCESS) + return ret; + + ret = set_binary_data(key->x, key_len, + &key_bin.pub.x, &key_bin.pub.x_len); + if (ret != TEE_SUCCESS) { + free(key_bin.d); + return ret; + } + + ret = set_binary_data(key->y, key_len, + &key_bin.pub.y, &key_bin.pub.y_len); + if (ret != TEE_SUCCESS) { + free(key_bin.d); + free(key_bin.pub.x); + return ret; + } + + key_bin.pub.curve = curve_tee2se050(key->curve); + st = se050_key_store_set_ecc_key_bin(se050_kstore, k_object, &key_bin, + NULL); + free(key_bin.d); + free(key_bin.pub.x); + free(key_bin.pub.y); + if (st != kStatus_SSS_Success) { + EMSG("Can't inject transient key, curve: %#"PRIx32, key->curve); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result gen_fallback(struct ecc_keypair *key, size_t len) +{ + if (!IS_ENABLED(CFG_NXP_SE05X_ECC_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + DMSG("se050: debug: ECC software fallback: KEYGEN"); + return pair_ops->generate(key, len); +} + +static TEE_Result shared_secret_fallback(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, size_t *secret_len) +{ + const struct crypto_ecc_keypair_ops *ops = NULL; + + if (!IS_ENABLED(CFG_NXP_SE05X_ECC_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (se050_ecc_keypair_from_nvm(private_key)) + return TEE_ERROR_NOT_IMPLEMENTED; + + ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR); + if (!ops) + return TEE_ERROR_NOT_IMPLEMENTED; + + DMSG("se050: debug: ECC software fallback: ECDH"); + return ops->shared_secret(private_key, public_key, + secret, (unsigned long *)secret_len); +} + +static TEE_Result verify_fallback(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + if (!IS_ENABLED(CFG_NXP_SE05X_ECC_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + DMSG("se050: debug: ECC software fallback: VERIFY"); + return pub_ops->verify(algo, key, msg, msg_len, sig, sig_len); +} + +static TEE_Result sign_fallback(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + if (!IS_ENABLED(CFG_NXP_SE05X_ECC_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (se050_ecc_keypair_from_nvm(key)) + return TEE_ERROR_NOT_IMPLEMENTED; + + DMSG("se050: debug: ECC software fallback: SIGN"); + return pair_ops->sign(algo, key, msg, msg_len, sig, sig_len); +} + +static TEE_Result shared_secret(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, size_t *secret_len) +{ + struct se050_ecc_keypub key = { }; + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_derive_key_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result ret = TEE_SUCCESS; + size_t key_bits = 0; + size_t key_bytes = 0; + + if (private_key->curve != public_key->curve) + return TEE_ERROR_BAD_PARAMETERS; + + ret = ecc_get_key_size(private_key->curve, 0, &key_bytes, &key_bits); + if (ret) { + if (ret != TEE_ERROR_NOT_IMPLEMENTED) + return ret; + + return shared_secret_fallback(private_key, public_key, + secret, secret_len); + } + + ret = se050_inject_keypair(&kobject, private_key, key_bytes); + if (ret != TEE_SUCCESS) + return TEE_ERROR_BAD_PARAMETERS; + + st = sss_se05x_derive_key_context_init(&ctx, se050_session, &kobject, + kAlgorithm_SSS_ECDH, + kMode_SSS_ComputeSharedSecret); + if (st != kStatus_SSS_Success) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + /* prepare the public key (must be in raw format) */ + ret = set_binary_data(public_key->x, key_bytes, &key.x, &key.x_len); + if (ret != TEE_SUCCESS) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + ret = set_binary_data(public_key->y, key_bytes, &key.y, &key.y_len); + if (ret != TEE_SUCCESS) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + st = se050_ecc_gen_shared_secret(&se050_session->s_ctx, + kobject.keyId, &key, + secret, secret_len); + + if (st != kStatus_SSS_Success) + ret = TEE_ERROR_BAD_PARAMETERS; +exit: + if (!se050_ecc_keypair_from_nvm(private_key)) + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + + free(key.x); + free(key.y); + + return ret; +} + +static TEE_Result sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_asymmetric_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result res = TEE_SUCCESS; + uint8_t *sig_der = NULL; + size_t sig_der_len = 0; + size_t key_bytes = 0; + size_t key_bits = 0; + uint8_t *p = NULL; + + res = ecc_get_key_size(key->curve, algo, &key_bytes, &key_bits); + if (res) { + if (res != TEE_ERROR_NOT_IMPLEMENTED) + goto exit; + + return sign_fallback(algo, key, msg, msg_len, sig, sig_len); + } + + /* allocate temporary buffer to retrieve the signature in DER format */ + sig_der_len = 2 * key_bytes + DER_SIGNATURE_SZ; + + sig_der = malloc(sig_der_len); + if (!sig_der) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + /* truncate or pad the message as needed */ + res = ecc_prepare_msg(algo_tee2se050(algo), msg, &msg_len, &p); + if (res != TEE_SUCCESS) + goto exit; + + res = se050_inject_keypair(&kobject, key, key_bytes); + if (res != TEE_SUCCESS) + goto exit; + + st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, + algo_tee2se050(algo), + kMode_SSS_Sign); + if (st != kStatus_SSS_Success) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + st = sss_se05x_asymmetric_sign_digest(&ctx, p ? p : (uint8_t *)msg, + msg_len, sig_der, &sig_der_len); + if (st != kStatus_SSS_Success) { + EMSG("curve: %#"PRIx32, key->curve); + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + sss_se05x_signature_der2bin(sig_der, &sig_der_len); + + if (sig_der_len > *sig_len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + memcpy(sig, sig_der, sig_der_len); + *sig_len = sig_der_len; +exit: + if (!se050_ecc_keypair_from_nvm(key)) + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + + sss_se05x_asymmetric_context_free(&ctx); + + free(sig_der); + free(p); + + return res; +} + +static TEE_Result verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_asymmetric_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result res = TEE_SUCCESS; + uint8_t *signature = NULL; + size_t signature_len = sig_len + DER_SIGNATURE_SZ; + size_t key_bytes = 0; + size_t key_bits = 0; + uint8_t *p = NULL; + + res = ecc_get_key_size(key->curve, algo, &key_bytes, &key_bits); + if (res) { + if (res != TEE_ERROR_NOT_IMPLEMENTED) + goto exit; + + return verify_fallback(algo, key, msg, msg_len, sig, sig_len); + } + + /* truncate or pad the message as needed */ + res = ecc_prepare_msg(algo_tee2se050(algo), msg, &msg_len, &p); + if (res != TEE_SUCCESS) + goto exit; + + res = se050_inject_public_key(&kobject, key, key_bytes); + if (res != TEE_SUCCESS) + goto exit; + + st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, + algo_tee2se050(algo), + kMode_SSS_Verify); + if (st != kStatus_SSS_Success) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + signature = calloc(1, signature_len); + if (!signature) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + st = sss_se05x_signature_bin2der(signature, &signature_len, + (uint8_t *)sig, sig_len); + if (st != kStatus_SSS_Success) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + st = sss_se05x_asymmetric_verify_digest(&ctx, p ? p : (uint8_t *)msg, + msg_len, (uint8_t *)signature, + signature_len); + if (st != kStatus_SSS_Success) + res = TEE_ERROR_SIGNATURE_INVALID; +exit: + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + sss_se05x_asymmetric_context_free(&ctx); + free(p); + free(signature); + + return res; +} + +static TEE_Result gen_keypair(struct ecc_keypair *key, size_t key_size) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_object_t k_object = { }; + TEE_Result ret = TEE_SUCCESS; + uint8_t kf[512] = { }; + uint32_t oid = 0; + uint64_t kid = 0; + size_t bytes = 0; + size_t bits = 0; + + ret = ecc_get_key_size(key->curve, 0, &bytes, &bits); + if (ret) { + if (ret != TEE_ERROR_NOT_IMPLEMENTED) + return ret; + + return gen_fallback(key, key_size); + } + + st = sss_se05x_key_object_init(&k_object, se050_kstore); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + st = se050_get_oid(&oid); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + st = sss_se05x_key_object_allocate_handle(&k_object, oid, + kSSS_KeyPart_Pair, + cipher_tee2se050(key->curve), + 0, + kKeyObject_Mode_Persistent); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + st = sss_se05x_key_store_generate_key(se050_kstore, &k_object, bits, + &se050_asym_policy); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + bytes = sizeof(kf); + st = se050_key_store_get_ecc_key_bin(se050_kstore, &k_object, kf, + &bytes); + if (st != kStatus_SSS_Success) { + sss_se05x_key_store_erase_key(se050_kstore, &k_object); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* skip the DER tag */ + crypto_bignum_bin2bn(kf + 1, bytes / 2, key->x); + crypto_bignum_bin2bn(kf + 1 + bytes / 2, bytes / 2, key->y); + + kid = se050_generate_private_key(oid); + crypto_bignum_bin2bn((uint8_t *)&kid, sizeof(kid), key->d); + key->curve = curve_se0502tee(k_object.curve_id); + if (key->curve != TEE_CRYPTO_ELEMENT_NONE) + return TEE_SUCCESS; + + EMSG("ecc key generation failed"); + sss_se05x_key_store_erase_key(se050_kstore, &k_object); + + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t size_bytes) +{ + return gen_keypair(key, size_bytes); +} + +static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) +{ + return shared_secret(sdata->key_priv, + sdata->key_pub, + sdata->secret.data, + &sdata->secret.length); +} + +static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) +{ + return sign(sdata->algo, + sdata->key, + sdata->message.data, + sdata->message.length, + sdata->signature.data, + &sdata->signature.length); +} + +static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) +{ + return verify(sdata->algo, + sdata->key, + sdata->message.data, + sdata->message.length, + sdata->signature.data, + sdata->signature.length); +} + +static TEE_Result do_alloc_keypair(struct ecc_keypair *s, uint32_t type, + size_t size_bits __unused) +{ + /* This driver only supports ECDH/ECDSA */ + if (type != TEE_TYPE_ECDSA_KEYPAIR && + type != TEE_TYPE_ECDH_KEYPAIR) + return TEE_ERROR_NOT_IMPLEMENTED; + + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->d)) + goto err; + if (!bn_alloc_max(&s->x)) + goto err; + if (!bn_alloc_max(&s->y)) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->d); + crypto_bignum_free(s->x); + crypto_bignum_free(s->y); + return TEE_ERROR_OUT_OF_MEMORY; +} + +static TEE_Result do_alloc_publickey(struct ecc_public_key *s, uint32_t type, + size_t size_bits __unused) +{ + /* This driver only supports ECDH/ECDSA */ + if (type != TEE_TYPE_ECDSA_PUBLIC_KEY && + type != TEE_TYPE_ECDH_PUBLIC_KEY) + return TEE_ERROR_NOT_IMPLEMENTED; + + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->x)) + goto err; + if (!bn_alloc_max(&s->y)) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->x); + crypto_bignum_free(s->y); + return TEE_ERROR_OUT_OF_MEMORY; +} + +static void do_free_publickey(struct ecc_public_key *s) +{ + if (!s) + return; + + crypto_bignum_free(s->x); + crypto_bignum_free(s->y); +} + +static struct drvcrypt_ecc driver_ecc = { + .alloc_keypair = do_alloc_keypair, + .alloc_publickey = do_alloc_publickey, + .free_publickey = do_free_publickey, + .gen_keypair = do_gen_keypair, + .sign = do_sign, + .verify = do_verify, + .shared_secret = do_shared_secret, +}; + +static TEE_Result ecc_init(void) +{ + pub_ops = crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDSA_PUBLIC_KEY); + if (!pub_ops) + return TEE_ERROR_GENERIC; + + pair_ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDSA_KEYPAIR); + if (!pair_ops) + return TEE_ERROR_GENERIC; + + /* This driver supports both ECDH and ECDSA */ + assert((pub_ops == + crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDH_PUBLIC_KEY)) && + (pair_ops == + crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR))); + + return drvcrypt_register_ecc(&driver_ecc); +} + +driver_init_late(ecc_init); diff --git a/optee/optee_os/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h b/optee/optee_os/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h new file mode 100644 index 0000000..2fa3b33 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#ifndef SE050_CIPHER_ALGORITHMS_H_ +#define SE050_CIPHER_ALGORITHMS_H_ + +#include + +#if defined(CFG_NXP_SE05X_CTR_DRV) +TEE_Result se050_aes_ctr_allocate(void **ctx); +#else +static inline TEE_Result se050_aes_ctr_allocate(void **ctx __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif + +#endif /* SE050_CIPHER_ALGORITHMS_H_ */ diff --git a/optee/optee_os/core/drivers/crypto/se050/core/rng.c b/optee/optee_os/core/drivers/crypto/se050/core/rng.c new file mode 100644 index 0000000..bedcff8 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/rng.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include + +static TEE_Result do_rng_read(void *buf, size_t blen) +{ + sss_status_t status = kStatus_SSS_Success; + sss_se05x_rng_context_t rng = { }; + + sss_se05x_rng_context_init(&rng, se050_session); + status = sss_se05x_rng_get_random(&rng, buf, blen); + sss_se05x_rng_context_free(&rng); + + if (status != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +void plat_rng_init(void) +{ +} + +TEE_Result hw_get_random_bytes(void *buf, size_t blen) +{ + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + return do_rng_read(buf, blen); +} diff --git a/optee/optee_os/core/drivers/crypto/se050/core/rsa.c b/optee/optee_os/core/drivers/crypto/se050/core/rsa.c new file mode 100644 index 0000000..815abb3 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/rsa.c @@ -0,0 +1,933 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static sss_cipher_type_t oefid_cipher_type(void) +{ + switch (se050_get_oefid()) { + case SE050F_ID: + return kSSS_CipherType_RSA_CRT; + default: + return kSSS_CipherType_RSA; + } +} + +static bool oefid_keylen_supported(size_t bits) +{ + switch (se050_get_oefid()) { + case SE050F_ID: + return bits >= 2048; + default: + return true; + } +} + +static bool rsa_keypair_has_crt(struct rsa_keypair *key) +{ + if (key->p && crypto_bignum_num_bytes(key->p) && + key->q && crypto_bignum_num_bytes(key->q) && + key->qp && crypto_bignum_num_bytes(key->qp) && + key->dp && crypto_bignum_num_bytes(key->dp) && + key->dq && crypto_bignum_num_bytes(key->dq)) + return true; + + return false; +} + +static bool keypair_supported(struct rsa_keypair *key, sss_cipher_type_t ctype) +{ + if (se050_rsa_keypair_from_nvm(key)) + return true; + + if (ctype == kSSS_CipherType_RSA_CRT) + return rsa_keypair_has_crt(key); + + return true; +} + +static uint32_t tee2se050(uint32_t algo) +{ + switch (algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA1; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA224; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA256; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA384; + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA1; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA224; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA256; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA384; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512; + case TEE_ALG_RSAES_PKCS1_V1_5: + return kAlgorithm_SSS_RSAES_PKCS1_V1_5_SHA256; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA1; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA224; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA256; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA384; + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA512; + case TEE_ALG_RSA_NOPAD: + return kAlgorithm_SSS_RSASSA_NO_PADDING; +#ifdef CFG_CRYPTO_RSASSA_NA1 + case TEE_ALG_RSASSA_PKCS1_V1_5: + return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_NO_HASH; +#endif + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1: + default: + return kAlgorithm_None; + } +} + +static bool bn_alloc_max(struct bignum **s) +{ + *s = crypto_bignum_allocate(4096); + + return *s; +} + +static TEE_Result set_binary_data(struct bignum *b, uint8_t **p, size_t *len) +{ + *len = crypto_bignum_num_bytes(b); + if (*len) { + *p = (uint8_t *)calloc(1, *len); + if (!*p) + return TEE_ERROR_OUT_OF_MEMORY; + crypto_bignum_bn2bin(b, *p); + } + return TEE_SUCCESS; +} + +static TEE_Result se050_inject_public_key(sss_se05x_object_t *k_object, + struct rsa_public_key *key) +{ + sss_status_t st = kStatus_SSS_Fail; + struct se050_rsa_keypub key_bin = { }; + uint32_t oid = 0; + + st = sss_se05x_key_object_init(k_object, se050_kstore); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + st = se050_get_oid(&oid); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + /* + * Keys 2048 and above MUST to be placed on persistent storage even + * though the keys will be deleted after the operation. This is a + * memory restriction in the secure element. + */ + st = sss_se05x_key_object_allocate_handle(k_object, oid, + kSSS_KeyPart_Public, + oefid_cipher_type(), 0, + kKeyObject_Mode_Persistent); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + set_binary_data(key->e, &key_bin.e, &key_bin.e_len); + set_binary_data(key->n, &key_bin.n, &key_bin.n_len); + st = se050_key_store_set_rsa_key_bin(se050_kstore, k_object, NULL, + &key_bin, key_bin.n_len * 8); + free(key_bin.n); + free(key_bin.e); + + if (st != kStatus_SSS_Success) { + sss_se05x_key_store_erase_key(se050_kstore, k_object); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result se050_inject_keypair(sss_se05x_object_t *k_object, + struct rsa_keypair *key) +{ + sss_status_t st = kStatus_SSS_Fail; + struct se050_rsa_keypair key_bin = { }; + uint32_t key_id = 0; + uint32_t oid = 0; + + st = sss_se05x_key_object_init(k_object, se050_kstore); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + key_id = se050_rsa_keypair_from_nvm(key); + if (key_id) { + st = sss_se05x_key_object_get_handle(k_object, key_id); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + return TEE_SUCCESS; + } + + st = se050_get_oid(&oid); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + /* Keys 2048 and above need to be placed on persistent storage */ + st = sss_se05x_key_object_allocate_handle(k_object, oid, + kSSS_KeyPart_Pair, + oefid_cipher_type(), 0, + kKeyObject_Mode_Persistent); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + set_binary_data(key->e, &key_bin.e, &key_bin.e_len); + set_binary_data(key->d, &key_bin.d, &key_bin.d_len); + set_binary_data(key->n, &key_bin.n, &key_bin.n_len); + set_binary_data(key->p, &key_bin.p, &key_bin.p_len); + set_binary_data(key->q, &key_bin.q, &key_bin.q_len); + set_binary_data(key->qp, &key_bin.qp, &key_bin.qp_len); + set_binary_data(key->dp, &key_bin.dp, &key_bin.dp_len); + set_binary_data(key->dq, &key_bin.dq, &key_bin.dq_len); + st = se050_key_store_set_rsa_key_bin(se050_kstore, k_object, + &key_bin, NULL, + crypto_bignum_num_bits(key->n)); + free(key_bin.e); + free(key_bin.d); + free(key_bin.n); + free(key_bin.p); + free(key_bin.q); + free(key_bin.qp); + free(key_bin.dp); + free(key_bin.dq); + + if (st != kStatus_SSS_Success) { + sss_se05x_key_store_erase_key(se050_kstore, k_object); + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static TEE_Result decrypt_es(uint32_t algo, struct rsa_keypair *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_asymmetric_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result res = TEE_SUCCESS; + uint8_t *buf = NULL; + size_t buf_len = src_len; + + res = se050_inject_keypair(&kobject, key); + if (res) + return res; + + st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, + tee2se050(algo), + kMode_SSS_Decrypt); + if (st != kStatus_SSS_Success) { + if (!se050_rsa_keypair_from_nvm(key)) + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* we don't know the size of the decrypted data, just the upper limit */ + buf = mempool_calloc(mempool_default, 1, buf_len); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + st = sss_se05x_asymmetric_decrypt(&ctx, src, src_len, buf, &buf_len); + if (st != kStatus_SSS_Success) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (buf_len > *dst_len) { + *dst_len = buf_len; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + *dst_len = buf_len; + memcpy(dst, buf, buf_len); +out: + if (!se050_rsa_keypair_from_nvm(key)) + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + + sss_se05x_asymmetric_context_free(&ctx); + mempool_free(mempool_default, buf); + + return res; +} + +static TEE_Result encrypt_es(uint32_t algo, struct rsa_public_key *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_asymmetric_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result res = TEE_SUCCESS; + + if (*dst_len < crypto_bignum_num_bytes(key->n)) { + *dst_len = crypto_bignum_num_bytes(key->n); + return TEE_ERROR_SHORT_BUFFER; + } + + if (se050_inject_public_key(&kobject, key)) + return TEE_ERROR_BAD_PARAMETERS; + + st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, + tee2se050(algo), + kMode_SSS_Encrypt); + if (st != kStatus_SSS_Success) { + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + return TEE_ERROR_BAD_PARAMETERS; + } + + st = sss_se05x_asymmetric_encrypt(&ctx, src, src_len, dst, dst_len); + if (st != kStatus_SSS_Success) + res = TEE_ERROR_BAD_PARAMETERS; + + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + sss_se05x_asymmetric_context_free(&ctx); + + return res; +} + +static TEE_Result decrypt_nopad(struct rsa_keypair *key, const uint8_t *src, + size_t src_len, uint8_t *dst, size_t *dst_len) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_asymmetric_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result res = TEE_SUCCESS; + uint8_t *buf = NULL; + size_t offset = 0; + size_t blen = 0; + size_t rsa_len = 0; + + res = se050_inject_keypair(&kobject, key); + if (res) + return res; + + st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, + kAlgorithm_SSS_RSASSA_NO_PADDING, + kMode_SSS_Decrypt); + if (st != kStatus_SSS_Success) { + if (!se050_rsa_keypair_from_nvm(key)) + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + return TEE_ERROR_BAD_PARAMETERS; + } + + blen = CFG_CORE_BIGNUM_MAX_BITS / 8; + buf = mempool_calloc(mempool_default, 1, blen); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + rsa_len = crypto_bignum_num_bytes(key->n); + memcpy(buf + rsa_len - src_len, src, src_len); + + st = sss_se05x_asymmetric_decrypt(&ctx, buf, rsa_len, buf, &blen); + if (st != kStatus_SSS_Success) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* Remove the zero-padding (leave one zero if buff is all zeroes) */ + offset = 0; + while ((offset < blen - 1) && (buf[offset] == 0)) + offset++; + + if (*dst_len < blen - offset) { + *dst_len = blen - offset; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + *dst_len = blen - offset; + memcpy(dst, buf + offset, *dst_len); +out: + mempool_free(mempool_default, buf); + if (!se050_rsa_keypair_from_nvm(key)) + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + + sss_se05x_asymmetric_context_free(&ctx); + + return res; +} + +static TEE_Result encrypt_nopad(struct rsa_public_key *key, const uint8_t *src, + size_t src_len, uint8_t *dst, size_t *dst_len) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_asymmetric_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result res = TEE_SUCCESS; + uint8_t *buf = NULL; + size_t offset = 0; + size_t blen = 0; + size_t rsa_len = 0; + + if (se050_inject_public_key(&kobject, key)) + return TEE_ERROR_BAD_PARAMETERS; + + st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, + kAlgorithm_SSS_RSASSA_NO_PADDING, + kMode_SSS_Encrypt); + if (st != kStatus_SSS_Success) { + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + return TEE_ERROR_BAD_PARAMETERS; + } + + blen = CFG_CORE_BIGNUM_MAX_BITS / 8; + buf = mempool_calloc(mempool_default, 1, blen); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + rsa_len = crypto_bignum_num_bytes(key->n); + memcpy(buf + rsa_len - src_len, src, src_len); + + st = sss_se05x_asymmetric_encrypt(&ctx, buf, rsa_len, buf, &blen); + if (st != kStatus_SSS_Success) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* Remove the zero-padding (leave one zero if buff is all zeroes) */ + offset = 0; + while ((offset < blen - 1) && (buf[offset] == 0)) + offset++; + + if (*dst_len < blen - offset) { + *dst_len = blen - offset; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + *dst_len = blen - offset; + memcpy(dst, buf + offset, *dst_len); +out: + mempool_free(mempool_default, buf); + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + sss_se05x_asymmetric_context_free(&ctx); + + return res; +} + +static TEE_Result sign_ssa(uint32_t algo, struct rsa_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_asymmetric_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result res = TEE_SUCCESS; + + if (*sig_len < crypto_bignum_num_bytes(key->n)) { + *sig_len = crypto_bignum_num_bytes(key->n); + return TEE_ERROR_SHORT_BUFFER; + } + + res = se050_inject_keypair(&kobject, key); + if (res) + return res; + + st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, + tee2se050(algo), kMode_SSS_Sign); + if (st != kStatus_SSS_Success) { + if (!se050_rsa_keypair_from_nvm(key)) + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + return TEE_ERROR_BAD_PARAMETERS; + } + + st = sss_se05x_asymmetric_sign_digest(&ctx, (uint8_t *)msg, msg_len, + sig, sig_len); + if (st != kStatus_SSS_Success) + res = TEE_ERROR_BAD_PARAMETERS; + + if (!se050_rsa_keypair_from_nvm(key)) + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + + sss_se05x_asymmetric_context_free(&ctx); + + return res; +} + +static TEE_Result verify_ssa(uint32_t algo, struct rsa_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_asymmetric_t ctx = { }; + sss_se05x_object_t kobject = { }; + TEE_Result res = TEE_SUCCESS; + + if (se050_inject_public_key(&kobject, key)) + return TEE_ERROR_BAD_PARAMETERS; + + st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, + tee2se050(algo), + kMode_SSS_Verify); + if (st != kStatus_SSS_Success) { + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + return TEE_ERROR_BAD_PARAMETERS; + } + + st = sss_se05x_asymmetric_verify_digest(&ctx, (uint8_t *)msg, msg_len, + (uint8_t *)sig, sig_len); + if (st != kStatus_SSS_Success) + res = TEE_ERROR_SIGNATURE_INVALID; + + sss_se05x_key_store_erase_key(se050_kstore, &kobject); + sss_se05x_asymmetric_context_free(&ctx); + + return res; +} + +static TEE_Result do_alloc_keypair(struct rsa_keypair *s, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->e)) + return TEE_ERROR_OUT_OF_MEMORY; + if (!bn_alloc_max(&s->d)) + goto err; + if (!bn_alloc_max(&s->n)) + goto err; + if (!bn_alloc_max(&s->p)) + goto err; + if (!bn_alloc_max(&s->q)) + goto err; + if (!bn_alloc_max(&s->qp)) + goto err; + if (!bn_alloc_max(&s->dp)) + goto err; + if (!bn_alloc_max(&s->dq)) + goto err; + + return TEE_SUCCESS; +err: + crypto_bignum_free(s->e); + crypto_bignum_free(s->d); + crypto_bignum_free(s->n); + crypto_bignum_free(s->p); + crypto_bignum_free(s->q); + crypto_bignum_free(s->qp); + crypto_bignum_free(s->dp); + crypto_bignum_free(s->dq); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +static TEE_Result do_alloc_publickey(struct rsa_public_key *s, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->e)) + return TEE_ERROR_OUT_OF_MEMORY; + if (!bn_alloc_max(&s->n)) { + crypto_bignum_free(s->e); + return TEE_ERROR_OUT_OF_MEMORY; + } + + return TEE_SUCCESS; +} + +static void do_free_publickey(struct rsa_public_key *s) +{ + if (s) { + crypto_bignum_free(s->n); + crypto_bignum_free(s->e); + } +} + +static void do_free_keypair(struct rsa_keypair *s) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_object_t k_object = { }; + uint32_t key_id = 0; + + if (!s) + return; + + key_id = se050_rsa_keypair_from_nvm(s); + if (key_id) { + st = sss_se05x_key_object_get_handle(&k_object, key_id); + if (st == kStatus_SSS_Success) + sss_se05x_key_store_erase_key(se050_kstore, &k_object); + } + + crypto_bignum_free(s->e); + crypto_bignum_free(s->d); + crypto_bignum_free(s->n); + crypto_bignum_free(s->p); + crypto_bignum_free(s->q); + crypto_bignum_free(s->qp); + crypto_bignum_free(s->dp); + crypto_bignum_free(s->dq); +} + +static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t kb) +{ + sss_status_t st = kStatus_SSS_Fail; + sss_se05x_object_t k_object = { }; + uint32_t oid = 0; + uint64_t kid = 0; + uint8_t k[2048] = { 0 }; + uint8_t *n = NULL; + uint8_t *e = NULL; + size_t n_len = 0; + size_t e_len = 0; + size_t k_len = sizeof(k); + + if (!oefid_keylen_supported(kb)) { + if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + DMSG("se050: debug: RSA software fallback: KEYGEN"); + return sw_crypto_acipher_gen_rsa_key(key, kb); + } + + st = sss_se05x_key_object_init(&k_object, se050_kstore); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + st = se050_get_oid(&oid); + if (st != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + st = sss_se05x_key_object_allocate_handle(&k_object, oid, + kSSS_KeyPart_Pair, + oefid_cipher_type(), 0, + kKeyObject_Mode_Persistent); + if (st != kStatus_SSS_Success) + return TEE_ERROR_BAD_PARAMETERS; + + st = sss_se05x_key_store_generate_key(se050_kstore, &k_object, kb, + &se050_asym_policy); + if (st != kStatus_SSS_Success) + goto error; + + st = sss_se05x_key_store_get_key(se050_kstore, &k_object, k, &k_len, + &kb); + if (st != kStatus_SSS_Success) + goto error; + + st = sss_util_asn1_rsa_parse_public(k, k_len, &n, &n_len, &e, &e_len); + if (st != kStatus_SSS_Success) + goto error; + + crypto_bignum_bin2bn(n, n_len, key->n); + crypto_bignum_bin2bn(e, e_len, key->e); + kid = se050_generate_private_key(oid); + crypto_bignum_bin2bn((uint8_t *)&kid, sizeof(kid), (key->d)); + crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->p); + crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->q); + crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->qp); + crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->dp); + crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->dq); + free(n); + free(e); + + return TEE_SUCCESS; +error: + sss_se05x_key_store_erase_key(se050_kstore, &k_object); + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result encrypt_fallback(struct drvcrypt_rsa_ed *p) +{ + if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + switch (p->rsa_id) { + case DRVCRYPT_RSA_NOPAD: + DMSG("se050: debug: RSA software fallback: ENCRYPT_NOPAD"); + return sw_crypto_acipher_rsanopad_encrypt(p->key.key, + p->message.data, + p->message.length, + p->cipher.data, + &p->cipher.length); + + case DRVCRYPT_RSA_OAEP: + case DRVCRYPT_RSA_PKCS_V1_5: + case DRVCRYPT_RSASSA_PKCS_V1_5: + case DRVCRYPT_RSASSA_PSS: + default: + DMSG("se050: debug: RSA software fallback: ENCRYPT_ES"); + return sw_crypto_acipher_rsaes_encrypt(p->algo, + p->key.key, + p->label.data, + p->label.length, + p->message.data, + p->message.length, + p->cipher.data, + &p->cipher.length); + } +} + +static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data) +{ + if (!oefid_keylen_supported(rsa_data->key.n_size * 8)) + return encrypt_fallback(rsa_data); + + switch (rsa_data->rsa_id) { + case DRVCRYPT_RSA_NOPAD: + case DRVCRYPT_RSASSA_PSS: + case DRVCRYPT_RSASSA_PKCS_V1_5: + return encrypt_nopad(rsa_data->key.key, + rsa_data->message.data, + rsa_data->message.length, + rsa_data->cipher.data, + &rsa_data->cipher.length); + + case DRVCRYPT_RSA_PKCS_V1_5: + return encrypt_es(TEE_ALG_RSAES_PKCS1_V1_5, + rsa_data->key.key, + rsa_data->message.data, + rsa_data->message.length, + rsa_data->cipher.data, + &rsa_data->cipher.length); + + case DRVCRYPT_RSA_OAEP: + if (rsa_data->hash_algo != TEE_ALG_SHA1) + return encrypt_fallback(rsa_data); + + return encrypt_es(TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + rsa_data->key.key, + rsa_data->message.data, + rsa_data->message.length, + rsa_data->cipher.data, + &rsa_data->cipher.length); + + default: + break; + } + + return encrypt_fallback(rsa_data); +} + +static TEE_Result decrypt_fallback(struct drvcrypt_rsa_ed *p) +{ + if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (se050_rsa_keypair_from_nvm(p->key.key)) + return TEE_ERROR_NOT_IMPLEMENTED; + + switch (p->rsa_id) { + case DRVCRYPT_RSA_NOPAD: + DMSG("se050: debug: RSA software fallback: DECRYPT_NOPAD"); + return sw_crypto_acipher_rsanopad_decrypt(p->key.key, + p->cipher.data, + p->cipher.length, + p->message.data, + &p->message.length); + + case DRVCRYPT_RSA_OAEP: + case DRVCRYPT_RSA_PKCS_V1_5: + case DRVCRYPT_RSASSA_PKCS_V1_5: + case DRVCRYPT_RSASSA_PSS: + default: + DMSG("se050: debug: RSA software fallback: DECRYPT_ES"); + return sw_crypto_acipher_rsaes_decrypt(p->algo, + p->key.key, + p->label.data, + p->label.length, + p->cipher.data, + p->cipher.length, + p->message.data, + &p->message.length); + } +} + +static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data) +{ + if (!oefid_keylen_supported(rsa_data->key.n_size * 8)) + return decrypt_fallback(rsa_data); + + if (!keypair_supported(rsa_data->key.key, oefid_cipher_type())) + return decrypt_fallback(rsa_data); + + switch (rsa_data->rsa_id) { + case DRVCRYPT_RSA_NOPAD: + case DRVCRYPT_RSASSA_PSS: + case DRVCRYPT_RSASSA_PKCS_V1_5: + return decrypt_nopad(rsa_data->key.key, + rsa_data->cipher.data, + rsa_data->cipher.length, + rsa_data->message.data, + &rsa_data->message.length); + + case DRVCRYPT_RSA_PKCS_V1_5: + return decrypt_es(TEE_ALG_RSAES_PKCS1_V1_5, + rsa_data->key.key, + rsa_data->cipher.data, + rsa_data->cipher.length, + rsa_data->message.data, + &rsa_data->message.length); + + case DRVCRYPT_RSA_OAEP: + if (rsa_data->hash_algo != TEE_ALG_SHA1) + return decrypt_fallback(rsa_data); + + return decrypt_es(TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + rsa_data->key.key, + rsa_data->cipher.data, + rsa_data->cipher.length, + rsa_data->message.data, + &rsa_data->message.length); + + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static TEE_Result sign_ssa_fallback(struct drvcrypt_rsa_ssa *p) +{ + if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (se050_rsa_keypair_from_nvm(p->key.key)) + return TEE_ERROR_NOT_IMPLEMENTED; + + DMSG("se050: debug: RSA software fallback: SIGN"); + return sw_crypto_acipher_rsassa_sign(p->algo, + p->key.key, + p->salt_len, + p->message.data, + p->message.length, + p->signature.data, + &p->signature.length); +} + +static TEE_Result do_ssa_sign(struct drvcrypt_rsa_ssa *ssa_data) +{ + if (!oefid_keylen_supported(ssa_data->key.n_size * 8)) + return sign_ssa_fallback(ssa_data); + + if (!keypair_supported(ssa_data->key.key, oefid_cipher_type())) + return sign_ssa_fallback(ssa_data); + + /* PKCS1_PSS_MGF1 padding limitations */ + switch (ssa_data->algo) { + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + if (ssa_data->key.n_size * 8 <= 512) + return sign_ssa_fallback(ssa_data); + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + if (ssa_data->key.n_size * 8 <= 1024) + return sign_ssa_fallback(ssa_data); + break; + default: + break; + } + + return sign_ssa(ssa_data->algo, + ssa_data->key.key, + ssa_data->message.data, + ssa_data->message.length, + ssa_data->signature.data, + &ssa_data->signature.length); +} + +static TEE_Result verify_ssa_fallback(struct drvcrypt_rsa_ssa *p) +{ + if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) + return TEE_ERROR_NOT_IMPLEMENTED; + + DMSG("se050: debug: RSA software fallback: VERIFY"); + return sw_crypto_acipher_rsassa_verify(p->algo, + p->key.key, + p->salt_len, + p->message.data, + p->message.length, + p->signature.data, + p->signature.length); +} + +static TEE_Result do_ssa_verify(struct drvcrypt_rsa_ssa *ssa_data) +{ + if (!oefid_keylen_supported(ssa_data->key.n_size * 8)) + return verify_ssa_fallback(ssa_data); + + /* PKCS1_PSS_MGF1 padding limitations */ + switch (ssa_data->algo) { + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + if (ssa_data->key.n_size * 8 <= 512) + return verify_ssa_fallback(ssa_data); + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + if (ssa_data->key.n_size * 8 <= 1024) + return verify_ssa_fallback(ssa_data); + break; + default: + break; + } + + return verify_ssa(ssa_data->algo, + ssa_data->key.key, + ssa_data->message.data, + ssa_data->message.length, + ssa_data->signature.data, + ssa_data->signature.length); +} + +static const struct drvcrypt_rsa driver_rsa = { + .alloc_keypair = do_alloc_keypair, + .alloc_publickey = do_alloc_publickey, + .free_publickey = do_free_publickey, + .free_keypair = do_free_keypair, + .gen_keypair = do_gen_keypair, + .encrypt = do_encrypt, + .decrypt = do_decrypt, + .optional.ssa_sign = do_ssa_sign, + .optional.ssa_verify = do_ssa_verify, +}; + +static TEE_Result rsa_init(void) +{ + return drvcrypt_register_rsa(&driver_rsa); +} + +driver_init_late(rsa_init); diff --git a/optee/optee_os/core/drivers/crypto/se050/core/scp03.c b/optee/optee_os/core/drivers/crypto/se050/core/scp03.c new file mode 100644 index 0000000..153e5c8 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/scp03.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include + +TEE_Result crypto_se_enable_scp03(bool rotate_keys) +{ + sss_status_t status = kStatus_SSS_Success; + + status = se050_enable_scp03(se050_session); + if (status != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + if (rotate_keys) { + if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION)) { + status = se050_rotate_scp03_keys(&se050_ctx); + if (status != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; + } + return TEE_ERROR_BAD_PARAMETERS; + } + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/core/storage.c b/optee/optee_os/core/drivers/crypto/se050/core/storage.c new file mode 100644 index 0000000..de97a7a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/storage.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result crypto_storage_obj_del(struct tee_obj *o) +{ + sss_status_t status = kStatus_SSS_Success; + uint32_t val = SE050_KEY_WATERMARK; + TEE_Result ret = TEE_ERROR_GENERIC; + sss_se05x_object_t k_object = { }; + uint8_t *data = NULL; + uint8_t *p = NULL; + bool found = false; + size_t len = 0; + + if (!o) + return TEE_ERROR_BAD_PARAMETERS; + + len = o->info.dataSize; + + /* Supported keys (ECC/RSA) require less than 4KB of storage */ + if (len > SMALL_PAGE_SIZE || len <= sizeof(uint64_t)) + return TEE_SUCCESS; + + data = calloc(1, len); + if (!data) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Read the object into memory */ + ret = o->pobj->fops->read(o->fh, o->info.dataPosition, data, &len); + if (ret) { + EMSG("se05x: can not read the object prior removal"); + free(data); + goto out; + } + + /* Scan the object for the watermark */ + p = data; + while (len >= sizeof(uint32_t) && !found) { + if (memcmp(p, &val, sizeof(val)) != 0) { + p++; + len--; + continue; + } + found = true; + } + + if (!found) { + free(data); + return TEE_SUCCESS; + } + + /* Retrieve the object identifier */ + p = p - 4; + memcpy((void *)&val, p, sizeof(val)); + free(data); + + if (val < OID_MIN || val > OID_MAX) + return TEE_SUCCESS; + + status = sss_se05x_key_object_init(&k_object, se050_kstore); + if (status != kStatus_SSS_Success) { + ret = TEE_ERROR_BAD_STATE; + goto out; + } + + status = sss_se05x_key_object_get_handle(&k_object, val); + if (status != kStatus_SSS_Success) { + EMSG("se05x: can not communicate with the secure element"); + ret = TEE_ERROR_BAD_STATE; + goto out; + } + + status = sss_se05x_key_store_erase_key(se050_kstore, &k_object); + if (status != kStatus_SSS_Success) { + EMSG("se05x: can not communicate with the secure element"); + ret = TEE_ERROR_BAD_STATE; + goto out; + } + +out: + /* + * Users can delete the SE05X NVM objects during boot using a built + * time configuration flag (CFG_CORE_SE05X_INIT_NVM). + * + * This could cause the deletion of the secure storage objects holding + * references to those IDs via crypto_storage_obj_del() to fail, leaving + * broken links in the file system. + * + * Therefore we only permit this call to block the deletion upon an + * additional specific config. + */ + if (ret && IS_ENABLED(CFG_CORE_SE05X_BLOCK_OBJ_DEL_ON_ERROR)) + return ret; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/core/sub.mk b/optee/optee_os/core/drivers/crypto/se050/core/sub.mk new file mode 100644 index 0000000..615579e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/core/sub.mk @@ -0,0 +1,15 @@ +include ${CFG_NXP_SE05X_PLUG_AND_TRUST}/cflags.mk + +incdirs_ext-y += ${CFG_NXP_SE05X_PLUG_AND_TRUST}/optee_lib/include +incdirs-y += ../adaptors/include +incdirs-y += include + +srcs-y += storage.c +srcs-$(CFG_NXP_SE05X_RSA_DRV) += rsa.c +srcs-$(CFG_NXP_SE05X_ECC_DRV) += ecc.c +srcs-$(CFG_NXP_SE05X_CTR_DRV) += ctr.c +srcs-$(CFG_NXP_SE05X_DIEID_DRV) += die_id.c +srcs-$(CFG_NXP_SE05X_RNG_DRV) += rng.c +srcs-$(CFG_NXP_SE05X_CIPHER_DRV) += cipher.c +srcs-$(CFG_NXP_SE05X_SCP03_DRV) += scp03.c +srcs-$(CFG_NXP_SE05X_APDU_DRV) += apdu.c diff --git a/optee/optee_os/core/drivers/crypto/se050/crypto.mk b/optee/optee_os/core/drivers/crypto/se050/crypto.mk new file mode 100644 index 0000000..473cd82 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/crypto.mk @@ -0,0 +1,104 @@ +ifeq ($(CFG_NXP_SE05X),y) +# Enable the crypto driver +$(call force,CFG_CRYPTO_DRIVER,y) +CFG_CRYPTO_DRIVER_DEBUG ?= 0 + +# SE050 initialization +# Some secure elements can only be accessed over an SCP03 enabled session. +# Some of the NXP SE05X devices fall in this category (i.e NXP SE050F). +# Only enable this configuration to support those systems. +CFG_CORE_SCP03_ONLY ?= n +# Rotate the SCP03 keys during SCP03 init (does not require user intervention). +# CAUTION: the provisioning configuration chosen might require a stable HUK. +CFG_CORE_SE05X_SCP03_PROVISION_ON_INIT ?= n +# Rotate the SCP03 keys via PTA (request from Normal World). +CFG_CORE_SE05X_SCP03_PROVISION ?= n +# The Provision request will rotate the SCP03 keys back to its factory settings. +CFG_CORE_SE05X_SCP03_PROVISION_WITH_FACTORY_KEYS ?= n +# CAUTION: Leaks the SCP03 keys that are going to be programmed on the device's +# NVM during a provisioning operation. +CFG_CORE_SE05X_DISPLAY_SCP03_KEYS ?= n +# Displays the SE050 device information on the console at boot (i.e. OEFID) +CFG_CORE_SE05X_DISPLAY_INFO ?= y +# Enables SCP03 protocol during boot (does not require user intervention) +CFG_CORE_SE05X_SCP03_EARLY ?= y +# CAUTION: Deletes all persistent storage (keys/certs) from the SE05X at boot +CFG_CORE_SE05X_INIT_NVM ?= n +# Prevents the deletion of the secure storage object holding a reference to a +# Secure Element (SE) Non Volatile Memory object unless there is explicit +# confirmation from the SE that the NVM object has been removed. +CFG_CORE_SE05X_BLOCK_OBJ_DEL_ON_ERROR ?= n +# Select the SE05X applet version for aligning the built-in features ++CFG_CORE_SE05X_VER ?= 03_XX + +# I2C bus baudrate (depends on SoC) +CFG_CORE_SE05X_BAUDRATE ?= 3400000 +# I2C bus [0..2] (depends on board) +CFG_CORE_SE05X_I2C_BUS ?= 2 +# I2C access via REE after TEE boot +CFG_CORE_SE05X_I2C_TRAMPOLINE ?= y + +# Extra stacks required to support the Plug and Trust external library +ifeq ($(shell test $(CFG_STACK_THREAD_EXTRA) -lt 8192; echo $$?), 0) +$(error Error: SE050 requires CFG_STACK_THREAD_EXTRA at least 8192) +endif +ifeq ($(shell test $(CFG_STACK_TMP_EXTRA) -lt 8192; echo $$?), 0) +$(error Error: SE050 requires CFG_STACK_TMP_EXTRA at least 8192) +endif + +# SE05X Die Identifier +CFG_NXP_SE05X_DIEID_DRV ?= y + +# Allow a secure client to enable the SCP03 session +CFG_NXP_SE05X_SCP03_DRV ?= y +ifeq ($(CFG_NXP_SE05X_SCP03_DRV),y) +$(call force,CFG_SCP03_PTA,y,Mandated by CFG_NXP_SE05X_SCP03) +endif + +# Allow a secure client to send APDU raw frames +CFG_NXP_SE05X_APDU_DRV ?= y +ifeq ($(CFG_NXP_SE05X_APDU_DRV),y) +$(call force,CFG_APDU_PTA,y,Mandated by CFG_NXP_SE05X_APDU) +endif + +# Random Number Generator +CFG_NXP_SE05X_RNG_DRV ?= y +ifeq ($(CFG_NXP_SE05X_RNG_DRV),y) +$(call force,CFG_WITH_SOFTWARE_PRNG,n) +endif + +se050-one-enabled = $(call cfg-one-enabled, \ + $(foreach v,$(1), CFG_NXP_SE05X_$(v)_DRV)) +# Asymmetric ciphers +CFG_NXP_SE05X_RSA_DRV ?= y +CFG_NXP_SE05X_RSA_DRV_FALLBACK ?= n +CFG_NXP_SE05X_ECC_DRV ?= y +CFG_NXP_SE05X_ECC_DRV_FALLBACK ?= n +$(call force,CFG_NXP_SE05X_ACIPHER_DRV,$(call se050-one-enabled,RSA ECC)) + +# Asymmetric driver +ifeq ($(CFG_NXP_SE05X_ACIPHER_DRV),y) +$(call force,CFG_CRYPTO_DRV_ACIPHER,y,Mandated by CFG_NXP_SE05X_ACIPHER_DRV) +endif + +# Asymmetric ciphers configuration +# - RSA +ifeq ($(CFG_NXP_SE05X_RSA_DRV),y) +$(call force,CFG_CRYPTO_DRV_RSA,y) +CFG_CRYPTO_RSASSA_NA1 ?= y +endif +# - ECC +ifeq ($(CFG_NXP_SE05X_ECC_DRV),y) +$(call force,CFG_CRYPTO_DRV_ECC,y) +endif + +# Symmetric ciphers +CFG_NXP_SE05X_CTR_DRV ?= y +$(call force,CFG_NXP_SE05X_CIPHER_DRV,$(call se050-one-enabled,CTR)) + +# Symmetric driver +ifeq ($(CFG_NXP_SE05X_CIPHER_DRV),y) +$(call force,CFG_CRYPTO_DRV_CIPHER,y,Mandated by CFG_NXP_SE05X_CIPHER_DRV) +endif + +endif # CFG_NXP_SE05X diff --git a/optee/optee_os/core/drivers/crypto/se050/glue/i2c.c b/optee/optee_os/core/drivers/crypto/se050/glue/i2c.c new file mode 100644 index 0000000..aa05aec --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/glue/i2c.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result (*transfer)(struct rpc_i2c_request *req, size_t *bytes); + +static int i2c_transfer(uint8_t *buffer, int len, enum rpc_i2c_mode mode) +{ + struct rpc_i2c_request request = { + .bus = CFG_CORE_SE05X_I2C_BUS, + .chip = SMCOM_I2C_ADDRESS >> 1, + .mode = mode, + .buffer = buffer, + .buffer_len = len, + .flags = 0, + }; + size_t bytes = 0; + int retry = 5; + + do { + if ((*transfer)(&request, &bytes) == TEE_SUCCESS) + return bytes; + } while (--retry); + + return -1; +} + +int glue_i2c_read(uint8_t *buffer, int len) +{ + return i2c_transfer(buffer, len, RPC_I2C_MODE_READ); +} + +int glue_i2c_write(uint8_t *buffer, int len) +{ + return i2c_transfer(buffer, len, RPC_I2C_MODE_WRITE); +} + +int glue_i2c_init(void) +{ + if (transfer == rpc_io_i2c_transfer) + return 0; + + transfer = native_i2c_transfer; + + return native_i2c_init(); +} + +static TEE_Result load_trampoline(void) +{ + if (IS_ENABLED(CFG_CORE_SE05X_I2C_TRAMPOLINE)) + transfer = rpc_io_i2c_transfer; + + return TEE_SUCCESS; +} + +boot_final(load_trampoline); diff --git a/optee/optee_os/core/drivers/crypto/se050/glue/i2c_imx.c b/optee/optee_os/core/drivers/crypto/se050/glue/i2c_imx.c new file mode 100644 index 0000000..4a4add3 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/glue/i2c_imx.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include + +TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, + size_t *bytes) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + if (req->mode == RPC_I2C_MODE_READ) + ret = imx_i2c_read(req->bus, req->chip, req->buffer, + req->buffer_len); + else + ret = imx_i2c_write(req->bus, req->chip, req->buffer, + req->buffer_len); + + if (!ret) + *bytes = req->buffer_len; + + return ret; +} + +int native_i2c_init(void) +{ + if (imx_i2c_init(CFG_CORE_SE05X_I2C_BUS, CFG_CORE_SE05X_BAUDRATE)) + return -1; + + if (imx_i2c_probe(CFG_CORE_SE05X_I2C_BUS, SMCOM_I2C_ADDRESS >> 1)) + return -1; + + return 0; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c b/optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c new file mode 100644 index 0000000..fb2ad6b --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/glue/i2c_stm32.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved + * Author: Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include + +static_assert(CFG_CORE_SE05X_I2C_BUS < 10); +static struct i2c_handle_s i2c; + +TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, size_t *bytes) +{ + if (req->mode == RPC_I2C_MODE_READ) { + if (stm32_i2c_master_receive(&i2c, req->chip << 1, req->buffer, + req->buffer_len, 25)) + return TEE_ERROR_GENERIC; + } else { + if (stm32_i2c_master_transmit(&i2c, req->chip << 1, req->buffer, + req->buffer_len, 25)) + return TEE_ERROR_GENERIC; + } + + *bytes = req->buffer_len; + + return TEE_SUCCESS; +} + +static int dt_i2c_bus_config(struct stm32_i2c_init_s *init, + struct stm32_pinctrl **pctrl, size_t *pcnt) +{ + const fdt32_t *cuint = NULL; + const char *path = NULL; + char bus[6] = { }; + void *fdt = NULL; + int node = 0; + + fdt = get_embedded_dt(); + if (!fdt) + return -FDT_ERR_NOTFOUND; + + snprintf(bus, sizeof(bus), "i2c%d", CFG_CORE_SE05X_I2C_BUS); + + path = fdt_get_alias(fdt, bus); + if (!path) + return -FDT_ERR_NOTFOUND; + + node = fdt_path_offset(fdt, path); + if (node < 0) + return -FDT_ERR_NOTFOUND; + + cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); + if (cuint && fdt32_to_cpu(*cuint) != CFG_CORE_SE05X_BAUDRATE) + IMSG("SE05X ignoring CFG_CORE_SE05X_BAUDRATE, use DTB"); + else if (I2C_STANDARD_RATE != CFG_CORE_SE05X_BAUDRATE) + IMSG("SE05x ignoring CFG_CORE_SE05X_BAUDRATE, use built-in"); + + return stm32_i2c_get_setup_from_fdt(fdt, node, init, pctrl, pcnt); +} + +int native_i2c_init(void) +{ + struct stm32_i2c_init_s i2c_init = { }; + struct stm32_pinctrl *pinctrl = NULL; + size_t pin_count = 0; + + /* No need to re-initialize */ + if (i2c.base.pa) + return 0; + + /* Support only one device on the platform */ + if (dt_i2c_bus_config(&i2c_init, &pinctrl, &pin_count)) + return -1; + + /* Probe the device */ + i2c_init.own_address1 = SMCOM_I2C_ADDRESS; + i2c_init.digital_filter_coef = 0; + i2c_init.analog_filter = true; + i2c.pinctrl_count = pin_count; + i2c.pinctrl = pinctrl; + + stm32_i2c_resume(&i2c); + + return stm32_i2c_init(&i2c, &i2c_init); +} diff --git a/optee/optee_os/core/drivers/crypto/se050/glue/include/i2c_native.h b/optee/optee_os/core/drivers/crypto/se050/glue/include/i2c_native.h new file mode 100644 index 0000000..19238c4 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/glue/include/i2c_native.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#ifndef I2C_NATIVE_H_ +#define I2C_NATIVE_H_ + +#include + +TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, + size_t *bytes); +int native_i2c_init(void); + +#endif diff --git a/optee/optee_os/core/drivers/crypto/se050/glue/user.c b/optee/optee_os/core/drivers/crypto/se050/glue/user.c new file mode 100644 index 0000000..9c762de --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/glue/user.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ +#include +#include +#include +#include +#include +#include + +sss_status_t glue_mac_context_init(void **mac, const uint8_t *key, size_t len) +{ + if (crypto_mac_alloc_ctx(mac, TEE_ALG_AES_CMAC)) + return kStatus_SSS_Fail; + + if (crypto_mac_init(*mac, key, len)) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +void glue_mac_context_free(void *mac) +{ + crypto_mac_free_ctx(mac); +} + +sss_status_t glue_mac_update(void *mac, const uint8_t *msg, size_t len) +{ + if (crypto_mac_update(mac, msg, len)) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +sss_status_t glue_mac_final(void *mac, uint8_t *buf, size_t len) +{ + if (crypto_mac_final(mac, buf, len)) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +sss_status_t glue_mac_one_go(void *mac, const uint8_t *msg, size_t msg_len, + uint8_t *buf, size_t mac_len) +{ + if (crypto_mac_update(mac, msg, msg_len)) + return kStatus_SSS_Fail; + + if (crypto_mac_final(mac, buf, mac_len)) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +sss_status_t glue_symmetric_context_init(void **cipher) +{ + if (crypto_cipher_alloc_ctx(cipher, TEE_ALG_AES_CBC_NOPAD)) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} + +sss_status_t glue_cipher_one_go(void *cipher, TEE_OperationMode mode, + uint8_t *iv, size_t iv_len, + uint8_t *key, size_t key_len, + const uint8_t *src, uint8_t *dst, size_t len) +{ + if (crypto_cipher_init(cipher, mode, key, key_len, NULL, 0, iv, iv_len)) + return kStatus_SSS_Fail; + + if (crypto_cipher_update(cipher, 0, true, src, len, dst)) + return kStatus_SSS_Fail; + + crypto_cipher_final(cipher); + + return kStatus_SSS_Success; +} + +void glue_context_free(void *cipher) +{ + crypto_cipher_free_ctx(cipher); +} + +sss_status_t glue_rng_get_random(uint8_t *data, size_t len) +{ + if (IS_ENABLED(CFG_NXP_SE05X_RNG_DRV)) + return kStatus_SSS_InvalidArgument; + + if (crypto_rng_read(data, len)) + return kStatus_SSS_Fail; + + return kStatus_SSS_Success; +} diff --git a/optee/optee_os/core/drivers/crypto/se050/session.c b/optee/optee_os/core/drivers/crypto/se050/session.c new file mode 100644 index 0000000..cb6e93e --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/session.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include + +sss_se05x_key_store_t *se050_kstore; +sss_se05x_session_t *se050_session; +struct sss_se05x_ctx se050_ctx; + +TEE_Result se050_core_early_init(struct se050_scp_key *keys) +{ + sss_status_t status = kStatus_SSS_Success; + + status = se050_session_open(&se050_ctx, keys); + if (status != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + if (IS_ENABLED(CFG_CORE_SE05X_INIT_NVM)) { + status = se050_factory_reset(&se050_ctx.session.s_ctx); + if (status != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + } + + if (se050_ctx.session.subsystem == kType_SSS_SubSystem_NONE) + return TEE_ERROR_GENERIC; + + status = se050_key_store_and_object_init(&se050_ctx); + if (status != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + se050_session = (sss_se05x_session_t *)((void *)&se050_ctx.session); + se050_kstore = (sss_se05x_key_store_t *)((void *)&se050_ctx.ks); + + return TEE_SUCCESS; +} + +static TEE_Result update_se_info(void) +{ + sss_status_t status = kStatus_SSS_Success; + + status = se050_get_se_info(se050_session, + IS_ENABLED(CFG_CORE_SE05X_DISPLAY_INFO)); + + /* the session must be closed after accessing the board information */ + sss_se05x_session_close(se050_session); + se050_scp03_set_disable(); + + if (status != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + if (IS_ENABLED(CFG_CORE_SCP03_ONLY)) + return TEE_SUCCESS; + + return se050_core_early_init(NULL); +} + +static TEE_Result enable_scp03(void) +{ + if (se050_enable_scp03(se050_session) != kStatus_SSS_Success) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result se050_early_init_default(void) +{ + if (se050_core_early_init(NULL)) { + EMSG("Failed to open the default session"); + panic(); + } + + if (update_se_info()) { + EMSG("Failed to read the secure element configuration"); + panic(); + } + + if (IS_ENABLED(CFG_CORE_SE05X_SCP03_EARLY)) { + if (enable_scp03()) { + EMSG("Failed to open the SCP03 session"); + panic(); + } + } + + return TEE_SUCCESS; +} + +static TEE_Result se050_early_init_scp03(void) +{ + /* Initialize session */ + se050_session = (sss_se05x_session_t *)((void *)&se050_ctx.session); + se050_kstore = (sss_se05x_key_store_t *)((void *)&se050_ctx.ks); + +#ifdef CFG_CORE_SE05X_OEFID + se050_ctx.se_info.oefid[0] = CFG_CORE_SE05X_OEFID >> 8; + se050_ctx.se_info.oefid[1] = CFG_CORE_SE05X_OEFID & 0xff; +#endif + if (enable_scp03()) { + EMSG("Failed to enable SCP03 session"); + panic(); + } + + if (update_se_info()) { + EMSG("Failed to read the secure element configuration"); + panic(); + } + + if (enable_scp03()) { + EMSG("Failed to re-open the SCP03 session"); + panic(); + } + + return TEE_SUCCESS; +} + +static TEE_Result se050_session_init(void) +{ + if (IS_ENABLED(CFG_CORE_SCP03_ONLY)) + return se050_early_init_scp03(); + + return se050_early_init_default(); +} + +driver_init(se050_session_init); diff --git a/optee/optee_os/core/drivers/crypto/se050/sub.mk b/optee/optee_os/core/drivers/crypto/se050/sub.mk new file mode 100644 index 0000000..cb02572 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/se050/sub.mk @@ -0,0 +1,15 @@ +include ${CFG_NXP_SE05X_PLUG_AND_TRUST}/cflags.mk + +incdirs_ext-y += ${CFG_NXP_SE05X_PLUG_AND_TRUST}/optee_lib/include +incdirs-y += adaptors/include +incdirs-y += glue/include + +subdirs-y += adaptors +subdirs-y += core +subdirs_ext-y += ${CFG_NXP_SE05X_PLUG_AND_TRUST} + +srcs-y += session.c +srcs-$(CFG_IMX_I2C) += glue/i2c_imx.c +srcs-$(CFG_STM32_I2C) += glue/i2c_stm32.c +srcs-y += glue/i2c.c +srcs-y += glue/user.c diff --git a/optee/optee_os/core/drivers/crypto/stm32/authenc.c b/optee/optee_os/core/drivers/crypto/stm32/authenc.c new file mode 100644 index 0000000..d392989 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/authenc.c @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "stm32_cryp.h" + +#define TOBE32(x) TEE_U32_BSWAP(x) +#define FROMBE32(x) TEE_U32_BSWAP(x) + +#define MAX_TAG_SIZE 16U + +struct stm32_ae_ctx { + struct crypto_authenc_ctx a_ctx; + struct stm32_cryp_context cryp; + enum stm32_cryp_algo_mode algo; + uint8_t tag_mask[MAX_TAG_SIZE]; +}; + +static void xor_vec(uint8_t *r, uint8_t *a, uint8_t *b, size_t len) +{ + size_t i = 0; + + for (i = 0; i < len; i++) + r[i] = a[i] ^ b[i]; +} + +static struct stm32_ae_ctx *to_stm32_ae_ctx(struct crypto_authenc_ctx *ctx) +{ + assert(ctx); + + return container_of(ctx, struct stm32_ae_ctx, a_ctx); +} + +static TEE_Result stm32_ae_gcm_generate_iv(struct stm32_ae_ctx *c, + uint32_t *iv, + struct drvcrypt_authenc_init *dinit) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t tag1[MAX_TAG_SIZE] = { 0 }; + uint8_t tag2[MAX_TAG_SIZE] = { 0 }; + uint32_t j0[MAX_TAG_SIZE / sizeof(uint32_t)] = { 0 }; + uint8_t dummy_iv[MAX_TAG_SIZE] = { 0 }; + struct stm32_cryp_context ctx = { }; + uint8_t *data_out = NULL; + + if (dinit->nonce.length == 12) { + memcpy(iv, dinit->nonce.data, dinit->nonce.length); + iv[3] = TOBE32(2); + return TEE_SUCCESS; + } + + /* Calculate GHASH(dinit->nonce.data) */ + dummy_iv[15] = 2; + + res = stm32_cryp_init(&ctx, true, STM32_CRYP_MODE_AES_GCM, + dinit->key.data, dinit->key.length, + dummy_iv, sizeof(dummy_iv)); + if (res) + return res; + + res = stm32_cryp_final(&ctx, tag1, sizeof(tag1)); + if (res) + return res; + + memset(&ctx, 0, sizeof(ctx)); + res = stm32_cryp_init(&ctx, true, STM32_CRYP_MODE_AES_GCM, + dinit->key.data, dinit->key.length, + dummy_iv, sizeof(dummy_iv)); + if (res) + return res; + + data_out = malloc(dinit->nonce.length); + if (!data_out) + return TEE_ERROR_OUT_OF_MEMORY; + + res = stm32_cryp_update_load(&ctx, dinit->nonce.data, data_out, + dinit->nonce.length); + free(data_out); + + if (res) + return res; + + res = stm32_cryp_final(&ctx, tag2, sizeof(tag2)); + if (res) + return res; + + xor_vec((uint8_t *)j0, tag1, tag2, sizeof(tag1)); + + memcpy(iv, j0, sizeof(j0)); + iv[3] = TOBE32(FROMBE32(iv[3]) + 1); + + /* Compute first mask=AES_ECB(J0_real) into tag1 */ + memset(&ctx, 0, sizeof(ctx)); + res = stm32_cryp_init(&ctx, false, STM32_CRYP_MODE_AES_ECB, + dinit->key.data, dinit->key.length, + NULL, 0); + if (res) + return res; + + res = stm32_cryp_update(&ctx, true, (uint8_t *)j0, tag1, + sizeof(tag1)); + if (res) + return res; + + /* Compute second mask=AES_ECB(J0_used_by_HW) into tag2 */ + memset(&ctx, 0, sizeof(ctx)); + j0[3] = TOBE32(1); + res = stm32_cryp_init(&ctx, false, STM32_CRYP_MODE_AES_ECB, + dinit->key.data, dinit->key.length, + NULL, 0); + if (res) + return res; + + res = stm32_cryp_update(&ctx, true, (uint8_t *)j0, tag2, + sizeof(tag2)); + if (res) + return res; + + /* + * Save the mask we will apply in {enc,dec}_final() to the + * (wrongly) computed tag to get the expected one. + */ + xor_vec(c->tag_mask, tag1, tag2, sizeof(c->tag_mask)); + + return TEE_SUCCESS; +} + +static void stm32_ae_ccm_generate_b0(uint8_t *b0, + struct drvcrypt_authenc_init *dinit) +{ + size_t m = dinit->tag_len; + size_t l = 15 - dinit->nonce.length; + size_t payload_len = dinit->payload_len; + size_t i = 15; + + /* The tag_len should be 4, 6, 8, 10, 12, 14 or 16 */ + assert(m >= 4 && m <= 16 && (m % 2) == 0); + + memset(b0, 0, TEE_AES_BLOCK_SIZE); + /* Flags: (Adata << 6) | (M' << 3) | L' */ + b0[0] = ((dinit->aad_len ? 1 : 0) << 6) | + (((m - 2) / 2) << 3) | + (l - 1); + + /* Nonce */ + memcpy(b0 + 1, dinit->nonce.data, dinit->nonce.length); + + /* Payload length */ + for (i = 15; i >= 15 - l + 1; i--, payload_len >>= 8) + b0[i] = payload_len & 0xFF; +} + +static TEE_Result stm32_ae_ccm_push_b1(struct stm32_ae_ctx *c, + struct drvcrypt_authenc_init *dinit) +{ + uint8_t b1[TEE_AES_BLOCK_SIZE] = { 0 }; + size_t len = 0; + + if (dinit->aad_len == 0) + return TEE_SUCCESS; + + if (dinit->aad_len < 0x100) { + b1[1] = dinit->aad_len; + len = 2; + } else if (dinit->aad_len < 0xFF00) { + b1[0] = dinit->aad_len / 0x100; + b1[1] = dinit->aad_len % 0x100; + len = 2; + } else if (dinit->aad_len <= UINT32_MAX) { + b1[0] = 0xFF; + b1[1] = 0xFE; + b1[2] = dinit->aad_len & GENMASK_32(7, 0); + b1[3] = (dinit->aad_len & GENMASK_32(15, 8)) >> 8; + b1[4] = (dinit->aad_len & GENMASK_32(23, 16)) >> 16; + b1[5] = (dinit->aad_len & GENMASK_32(31, 24)) >> 24; + len = 6; + } else { + b1[0] = 0xFF; + b1[1] = 0xFF; + b1[2] = dinit->aad_len & GENMASK_64(7, 0); + b1[3] = (dinit->aad_len & GENMASK_64(15, 8)) >> 8; + b1[4] = (dinit->aad_len & GENMASK_64(23, 16)) >> 16; + b1[5] = (dinit->aad_len & GENMASK_64(31, 24)) >> 24; + b1[6] = (dinit->aad_len & GENMASK_64(39, 32)) >> 32; + b1[7] = (dinit->aad_len & GENMASK_64(47, 40)) >> 40; + b1[8] = (dinit->aad_len & GENMASK_64(55, 48)) >> 48; + b1[9] = (dinit->aad_len & GENMASK_64(63, 56)) >> 56; + len = 10; + } + + return stm32_cryp_update_assodata(&c->cryp, b1, len); +} + +static TEE_Result stm32_ae_initialize(struct drvcrypt_authenc_init *dinit) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t iv[4] = { 0 }; + struct stm32_ae_ctx *c = to_stm32_ae_ctx(dinit->ctx); + + if (c->algo == STM32_CRYP_MODE_AES_GCM) { + res = stm32_ae_gcm_generate_iv(c, iv, dinit); + if (res) + return res; + } else if (c->algo == STM32_CRYP_MODE_AES_CCM) { + stm32_ae_ccm_generate_b0((uint8_t *)iv, dinit); + } + + res = stm32_cryp_init(&c->cryp, !dinit->encrypt, c->algo, + dinit->key.data, dinit->key.length, iv, + sizeof(iv)); + if (res) + return res; + + if (c->algo == STM32_CRYP_MODE_AES_CCM) + return stm32_ae_ccm_push_b1(c, dinit); + + return TEE_SUCCESS; +} + +static TEE_Result +stm32_ae_update_aad(struct drvcrypt_authenc_update_aad *dupdate) +{ + struct stm32_ae_ctx *c = to_stm32_ae_ctx(dupdate->ctx); + + return stm32_cryp_update_assodata(&c->cryp, dupdate->aad.data, + dupdate->aad.length); +} + +static TEE_Result +stm32_ae_update_payload(struct drvcrypt_authenc_update_payload *dupdate) +{ + struct stm32_ae_ctx *c = to_stm32_ae_ctx(dupdate->ctx); + size_t len = MIN(dupdate->src.length, dupdate->dst.length); + + return stm32_cryp_update_load(&c->cryp, dupdate->src.data, + dupdate->dst.data, len); +} + +static TEE_Result stm32_ae_encdec_final(struct stm32_ae_ctx *c, uint8_t *tag, + size_t tag_size) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t t[MAX_TAG_SIZE] = { 0 }; + + res = stm32_cryp_final(&c->cryp, t, sizeof(t)); + if (res) + return res; + + xor_vec(tag, t, c->tag_mask, tag_size); + + return TEE_SUCCESS; +} + +static TEE_Result stm32_ae_enc_final(struct drvcrypt_authenc_final *dfinal) +{ + TEE_Result res = TEE_SUCCESS; + struct stm32_ae_ctx *c = to_stm32_ae_ctx(dfinal->ctx); + size_t len = MIN(dfinal->src.length, dfinal->dst.length); + + res = stm32_cryp_update_load(&c->cryp, dfinal->src.data, + dfinal->dst.data, len); + if (res) + return res; + + return stm32_ae_encdec_final(c, dfinal->tag.data, dfinal->tag.length); +} + +static TEE_Result stm32_ae_dec_final(struct drvcrypt_authenc_final *dfinal) +{ + TEE_Result res = TEE_SUCCESS; + struct stm32_ae_ctx *c = to_stm32_ae_ctx(dfinal->ctx); + size_t len = MIN(dfinal->src.length, dfinal->dst.length); + unsigned char tag_buf[MAX_TAG_SIZE] = { 0 }; + + res = stm32_cryp_update_load(&c->cryp, dfinal->src.data, + dfinal->dst.data, len); + if (res) + return res; + + res = stm32_ae_encdec_final(c, tag_buf, sizeof(tag_buf)); + if (res) + return res; + + if (consttime_memcmp(tag_buf, dfinal->tag.data, dfinal->tag.length)) + return TEE_ERROR_MAC_INVALID; + + return TEE_SUCCESS; +} + +static void stm32_ae_final(void *ctx __unused) +{ +} + +static void stm32_ae_free(void *ctx) +{ + struct stm32_ae_ctx *c = to_stm32_ae_ctx(ctx); + + free(c); +} + +static void stm32_ae_copy_state(void *dst_ctx, void *src_ctx) +{ + struct stm32_ae_ctx *src = to_stm32_ae_ctx(src_ctx); + struct stm32_ae_ctx *dst = to_stm32_ae_ctx(dst_ctx); + + memcpy(dst, src, sizeof(*dst)); +} + +static TEE_Result alloc_ctx(void **ctx, enum stm32_cryp_algo_mode algo) +{ + struct stm32_ae_ctx *c = calloc(1, sizeof(*c)); + + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->algo = algo; + *ctx = &c->a_ctx; + + return TEE_SUCCESS; +} + +/* + * Allocate the SW authenc data context + * + * @ctx [out] Caller context variable + * @algo Algorithm ID of the context + */ +static TEE_Result stm32_ae_allocate(void **ctx, uint32_t algo) +{ + /* Convert TEE_ALGO id to CRYP id */ + switch (algo) { + case TEE_ALG_AES_CCM: + return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CCM); + case TEE_ALG_AES_GCM: + return alloc_ctx(ctx, STM32_CRYP_MODE_AES_GCM); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +/* + * Registration of the Authenc Driver + */ +static struct drvcrypt_authenc driver_authenc = { + .alloc_ctx = &stm32_ae_allocate, + .free_ctx = &stm32_ae_free, + .init = &stm32_ae_initialize, + .update_aad = &stm32_ae_update_aad, + .update_payload = &stm32_ae_update_payload, + .enc_final = &stm32_ae_enc_final, + .dec_final = &stm32_ae_dec_final, + .final = &stm32_ae_final, + .copy_state = &stm32_ae_copy_state, +}; + +TEE_Result stm32_register_authenc(void) +{ + return drvcrypt_register_authenc(&driver_authenc); +} diff --git a/optee/optee_os/core/drivers/crypto/stm32/cipher.c b/optee/optee_os/core/drivers/crypto/stm32/cipher.c new file mode 100644 index 0000000..99a36a7 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/cipher.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "stm32_cryp.h" + +#define DES3_KEY_SIZE 24 + +struct stm32_cipher_ctx { + struct crypto_cipher_ctx c_ctx; + struct stm32_cryp_context cryp; + enum stm32_cryp_algo_mode algo; +}; + +static struct stm32_cipher_ctx * +to_stm32_cipher_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx); + + return container_of(ctx, struct stm32_cipher_ctx, c_ctx); +} + +static TEE_Result stm32_cipher_initialize(struct drvcrypt_cipher_init *dinit) +{ + struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dinit->ctx); + uint8_t temp_key[DES3_KEY_SIZE] = { 0 }; + uint8_t *key = NULL; + size_t key_size = 0; + + if (dinit->key1.length == 16 && + (c->algo == STM32_CRYP_MODE_TDES_ECB || + c->algo == STM32_CRYP_MODE_TDES_CBC)) { + /* Manage DES2: ie K=K1.K2.K1 */ + memcpy(temp_key, dinit->key1.data, dinit->key1.length); + memcpy(temp_key + dinit->key1.length, dinit->key1.data, + dinit->key1.length / 2); + key_size = DES3_KEY_SIZE; + key = temp_key; + } else { + key_size = dinit->key1.length; + key = dinit->key1.data; + } + + return stm32_cryp_init(&c->cryp, !dinit->encrypt, c->algo, + key, key_size, dinit->iv.data, + dinit->iv.length); +} + +static TEE_Result stm32_cipher_update(struct drvcrypt_cipher_update *dupdate) +{ + struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dupdate->ctx); + size_t len = MIN(dupdate->src.length, dupdate->dst.length); + + return stm32_cryp_update(&c->cryp, dupdate->last, + dupdate->src.data, dupdate->dst.data, + len); +} + +static void stm32_cipher_final(void *ctx __unused) +{ +} + +static void stm32_cipher_free(void *ctx) +{ + struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx); + + free(c); +} + +static void stm32_cipher_copy_state(void *dst_ctx, void *src_ctx) +{ + struct stm32_cipher_ctx *src = to_stm32_cipher_ctx(src_ctx); + struct stm32_cipher_ctx *dst = to_stm32_cipher_ctx(dst_ctx); + + memcpy(dst, src, sizeof(*dst)); +} + +static TEE_Result alloc_ctx(void **ctx, enum stm32_cryp_algo_mode algo) +{ + struct stm32_cipher_ctx *c = calloc(1, sizeof(*c)); + + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->algo = algo; + *ctx = &c->c_ctx; + + return TEE_SUCCESS; +} + +/* + * Allocate the SW cipher data context. + * + * @ctx [out] Caller context variable + * @algo Algorithm ID of the context + */ +static TEE_Result stm32_cipher_allocate(void **ctx, uint32_t algo) +{ + /* + * Convert TEE_ALGO id to internal id + */ + switch (algo) { + case TEE_ALG_DES_ECB_NOPAD: + return alloc_ctx(ctx, STM32_CRYP_MODE_DES_ECB); + case TEE_ALG_DES_CBC_NOPAD: + return alloc_ctx(ctx, STM32_CRYP_MODE_DES_CBC); + case TEE_ALG_DES3_ECB_NOPAD: + return alloc_ctx(ctx, STM32_CRYP_MODE_TDES_ECB); + case TEE_ALG_DES3_CBC_NOPAD: + return alloc_ctx(ctx, STM32_CRYP_MODE_TDES_CBC); + case TEE_ALG_AES_ECB_NOPAD: + return alloc_ctx(ctx, STM32_CRYP_MODE_AES_ECB); + case TEE_ALG_AES_CBC_NOPAD: + return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CBC); + case TEE_ALG_AES_CTR: + return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CTR); + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } +} + +static struct drvcrypt_cipher driver_cipher = { + .alloc_ctx = &stm32_cipher_allocate, + .free_ctx = &stm32_cipher_free, + .init = &stm32_cipher_initialize, + .update = &stm32_cipher_update, + .final = &stm32_cipher_final, + .copy_state = &stm32_cipher_copy_state, +}; + +TEE_Result stm32_register_cipher(void) +{ + return drvcrypt_register_cipher(&driver_cipher); +} diff --git a/optee/optee_os/core/drivers/crypto/stm32/common.h b/optee/optee_os/core/drivers/crypto/stm32/common.h new file mode 100644 index 0000000..d8f5f85 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/common.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#ifndef __DRIVERS_CRYPTO_STM32_COMMON_H +#define __DRIVERS_CRYPTO_STM32_COMMON_H + +#include + +TEE_Result stm32_register_authenc(void); +TEE_Result stm32_register_cipher(void); + +#endif /* __DRIVERS_CRYPTO_STM32_COMMON_H */ diff --git a/optee/optee_os/core/drivers/crypto/stm32/crypto.mk b/optee/optee_os/core/drivers/crypto/stm32/crypto.mk new file mode 100644 index 0000000..bceb2df --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/crypto.mk @@ -0,0 +1,21 @@ +# CFG_STM32_CRYPTO_DRIVER, when enabled, embeds +# STM32 HW cryptographic support and OP-TEE Crypto Driver. +# CFG_STM32_CRYP, when enabled, embeds +# STM32 CRYP module support, +# CIPHER Crypto Driver, +# AUTHENC Crypto Driver. + +ifeq ($(CFG_STM32_CRYPTO_DRIVER),y) + +$(call force,CFG_CRYPTO_DRIVER,y) +CFG_CRYPTO_DRIVER_DEBUG ?= 0 + +ifeq ($(CFG_STM32_CRYP),y) +$(call force,CFG_CRYPTO_DRV_CIPHER,y,Mandated by CFG_STM32_CRYP) +endif + +ifeq ($(CFG_STM32_CRYP),y) +$(call force,CFG_CRYPTO_DRV_AUTHENC,y,Mandated by CFG_STM32_CRYP) +endif + +endif # CFG_STM32_CRYPTO_DRIVER diff --git a/optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c b/optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c new file mode 100644 index 0000000..e47af5c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.c @@ -0,0 +1,1318 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stm32_cryp.h" +#include "common.h" + +#define INT8_BIT 8U +#define AES_BLOCK_SIZE_BIT 128U +#define AES_BLOCK_SIZE (AES_BLOCK_SIZE_BIT / INT8_BIT) +#define AES_BLOCK_NB_U32 (AES_BLOCK_SIZE / sizeof(uint32_t)) +#define DES_BLOCK_SIZE_BIT 64U +#define DES_BLOCK_SIZE (DES_BLOCK_SIZE_BIT / INT8_BIT) +#define DES_BLOCK_NB_U32 (DES_BLOCK_SIZE / sizeof(uint32_t)) +#define MAX_BLOCK_SIZE_BIT AES_BLOCK_SIZE_BIT +#define MAX_BLOCK_SIZE AES_BLOCK_SIZE +#define MAX_BLOCK_NB_U32 AES_BLOCK_NB_U32 +#define AES_KEYSIZE_128 16U +#define AES_KEYSIZE_192 24U +#define AES_KEYSIZE_256 32U + +/* CRYP control register */ +#define _CRYP_CR 0x0U +/* CRYP status register */ +#define _CRYP_SR 0x04U +/* CRYP data input register */ +#define _CRYP_DIN 0x08U +/* CRYP data output register */ +#define _CRYP_DOUT 0x0CU +/* CRYP DMA control register */ +#define _CRYP_DMACR 0x10U +/* CRYP interrupt mask set/clear register */ +#define _CRYP_IMSCR 0x14U +/* CRYP raw interrupt status register */ +#define _CRYP_RISR 0x18U +/* CRYP masked interrupt status register */ +#define _CRYP_MISR 0x1CU +/* CRYP key registers */ +#define _CRYP_K0LR 0x20U +#define _CRYP_K0RR 0x24U +#define _CRYP_K1LR 0x28U +#define _CRYP_K1RR 0x2CU +#define _CRYP_K2LR 0x30U +#define _CRYP_K2RR 0x34U +#define _CRYP_K3LR 0x38U +#define _CRYP_K3RR 0x3CU +/* CRYP initialization vector registers */ +#define _CRYP_IV0LR 0x40U +#define _CRYP_IV0RR 0x44U +#define _CRYP_IV1LR 0x48U +#define _CRYP_IV1RR 0x4CU +/* CRYP context swap GCM-CCM registers */ +#define _CRYP_CSGCMCCM0R 0x50U +#define _CRYP_CSGCMCCM1R 0x54U +#define _CRYP_CSGCMCCM2R 0x58U +#define _CRYP_CSGCMCCM3R 0x5CU +#define _CRYP_CSGCMCCM4R 0x60U +#define _CRYP_CSGCMCCM5R 0x64U +#define _CRYP_CSGCMCCM6R 0x68U +#define _CRYP_CSGCMCCM7R 0x6CU +/* CRYP context swap GCM registers */ +#define _CRYP_CSGCM0R 0x70U +#define _CRYP_CSGCM1R 0x74U +#define _CRYP_CSGCM2R 0x78U +#define _CRYP_CSGCM3R 0x7CU +#define _CRYP_CSGCM4R 0x80U +#define _CRYP_CSGCM5R 0x84U +#define _CRYP_CSGCM6R 0x88U +#define _CRYP_CSGCM7R 0x8CU +/* CRYP hardware configuration register */ +#define _CRYP_HWCFGR 0x3F0U +/* CRYP HW version register */ +#define _CRYP_VERR 0x3F4U +/* CRYP identification */ +#define _CRYP_IPIDR 0x3F8U +/* CRYP HW magic ID */ +#define _CRYP_MID 0x3FCU + +#define CRYP_TIMEOUT_US 1000000U +#define TIMEOUT_US_1MS 1000U + +/* CRYP control register fields */ +#define _CRYP_CR_RESET_VALUE 0x0U +#define _CRYP_CR_NPBLB_MSK GENMASK_32(23, 20) +#define _CRYP_CR_NPBLB_OFF 20U +#define _CRYP_CR_GCM_CCMPH_MSK GENMASK_32(17, 16) +#define _CRYP_CR_GCM_CCMPH_OFF 16U +#define _CRYP_CR_GCM_CCMPH_INIT 0U +#define _CRYP_CR_GCM_CCMPH_HEADER 1U +#define _CRYP_CR_GCM_CCMPH_PAYLOAD 2U +#define _CRYP_CR_GCM_CCMPH_FINAL 3U +#define _CRYP_CR_CRYPEN BIT(15) +#define _CRYP_CR_FFLUSH BIT(14) +#define _CRYP_CR_KEYSIZE_MSK GENMASK_32(9, 8) +#define _CRYP_CR_KEYSIZE_OFF 8U +#define _CRYP_CR_KSIZE_128 0U +#define _CRYP_CR_KSIZE_192 1U +#define _CRYP_CR_KSIZE_256 2U +#define _CRYP_CR_DATATYPE_MSK GENMASK_32(7, 6) +#define _CRYP_CR_DATATYPE_OFF 6U +#define _CRYP_CR_DATATYPE_NONE 0U +#define _CRYP_CR_DATATYPE_HALF_WORD 1U +#define _CRYP_CR_DATATYPE_BYTE 2U +#define _CRYP_CR_DATATYPE_BIT 3U +#define _CRYP_CR_ALGOMODE_MSK (BIT(19) | GENMASK_32(5, 3)) +#define _CRYP_CR_ALGOMODE_OFF 3U +#define _CRYP_CR_ALGOMODE_TDES_ECB 0x0U +#define _CRYP_CR_ALGOMODE_TDES_CBC 0x1U +#define _CRYP_CR_ALGOMODE_DES_ECB 0x2U +#define _CRYP_CR_ALGOMODE_DES_CBC 0x3U +#define _CRYP_CR_ALGOMODE_AES_ECB 0x4U +#define _CRYP_CR_ALGOMODE_AES_CBC 0x5U +#define _CRYP_CR_ALGOMODE_AES_CTR 0x6U +#define _CRYP_CR_ALGOMODE_AES 0x7U +#define _CRYP_CR_ALGOMODE_AES_GCM BIT(16) +#define _CRYP_CR_ALGOMODE_AES_CCM (BIT(16) | BIT(0)) +#define _CRYP_CR_ALGODIR BIT(2) +#define _CRYP_CR_ALGODIR_ENC 0U +#define _CRYP_CR_ALGODIR_DEC BIT(2) + +/* CRYP status register fields */ +#define _CRYP_SR_BUSY BIT(4) +#define _CRYP_SR_OFFU BIT(3) +#define _CRYP_SR_OFNE BIT(2) +#define _CRYP_SR_IFNF BIT(1) +#define _CRYP_SR_IFEM BIT(0) + +/* CRYP DMA control register fields */ +#define _CRYP_DMACR_DOEN BIT(1) +#define _CRYP_DMACR_DIEN BIT(0) + +/* CRYP interrupt fields */ +#define _CRYP_I_OUT BIT(1) +#define _CRYP_I_IN BIT(0) + +/* CRYP hardware configuration register fields */ +#define _CRYP_HWCFGR_CFG1_MSK GENMASK_32(3, 0) +#define _CRYP_HWCFGR_CFG1_OFF 0U +#define _CRYP_HWCFGR_CFG2_MSK GENMASK_32(7, 4) +#define _CRYP_HWCFGR_CFG2_OFF 4U +#define _CRYP_HWCFGR_CFG3_MSK GENMASK_32(11, 8) +#define _CRYP_HWCFGR_CFG3_OFF 8U +#define _CRYP_HWCFGR_CFG4_MSK GENMASK_32(15, 12) +#define _CRYP_HWCFGR_CFG4_OFF 12U + +/* CRYP HW version register */ +#define _CRYP_VERR_MSK GENMASK_32(7, 0) +#define _CRYP_VERR_OFF 0U + +/* + * Macro to manage bit manipulation when we work on local variable + * before writing only once to the real register. + */ +#define CLRBITS(v, bits) ((v) &= ~(bits)) +#define SETBITS(v, bits) ((v) |= (bits)) + +#define IS_ALGOMODE(cr, mod) \ + (((cr) & _CRYP_CR_ALGOMODE_MSK) == (_CRYP_CR_ALGOMODE_##mod << \ + _CRYP_CR_ALGOMODE_OFF)) + +#define SET_ALGOMODE(mod, cr) \ + clrsetbits(&(cr), _CRYP_CR_ALGOMODE_MSK, (_CRYP_CR_ALGOMODE_##mod << \ + _CRYP_CR_ALGOMODE_OFF)) + +#define GET_ALGOMODE(cr) \ + (((cr) & _CRYP_CR_ALGOMODE_MSK) >> _CRYP_CR_ALGOMODE_OFF) + +#define TOBE32(x) TEE_U32_BSWAP(x) +#define FROMBE32(x) TEE_U32_BSWAP(x) + +static struct stm32_cryp_platdata cryp_pdata; +static struct mutex cryp_lock = MUTEX_INITIALIZER; + +static void clrsetbits(uint32_t *v, uint32_t mask, uint32_t bits) +{ + *v = (*v & ~mask) | bits; +} + +static bool algo_mode_needs_iv(uint32_t cr) +{ + return !IS_ALGOMODE(cr, TDES_ECB) && !IS_ALGOMODE(cr, DES_ECB) && + !IS_ALGOMODE(cr, AES_ECB); +} + +static bool algo_mode_is_ecb_cbc(uint32_t cr) +{ + return GET_ALGOMODE(cr) < _CRYP_CR_ALGOMODE_AES_CTR; +} + +static bool algo_mode_is_aes(uint32_t cr) +{ + return ((cr & _CRYP_CR_ALGOMODE_MSK) >> _CRYP_CR_ALGOMODE_OFF) >= + _CRYP_CR_ALGOMODE_AES_ECB; +} + +static bool is_decrypt(uint32_t cr) +{ + return (cr & _CRYP_CR_ALGODIR) == _CRYP_CR_ALGODIR_DEC; +} + +static bool is_encrypt(uint32_t cr) +{ + return !is_decrypt(cr); +} + +static bool does_need_npblb(uint32_t cr) +{ + return (IS_ALGOMODE(cr, AES_GCM) && is_encrypt(cr)) || + (IS_ALGOMODE(cr, AES_CCM) && is_decrypt(cr)); +} + +static TEE_Result wait_sr_bits(vaddr_t base, uint32_t bits) +{ + uint64_t timeout_ref = timeout_init_us(CRYP_TIMEOUT_US); + + while ((io_read32(base + _CRYP_SR) & bits) != bits) + if (timeout_elapsed(timeout_ref)) + break; + + if ((io_read32(base + _CRYP_SR) & bits) != bits) + return TEE_ERROR_BUSY; + + return TEE_SUCCESS; +} + +static TEE_Result wait_end_busy(vaddr_t base) +{ + uint64_t timeout_ref = timeout_init_us(CRYP_TIMEOUT_US); + + while (io_read32(base + _CRYP_SR) & _CRYP_SR_BUSY) + if (timeout_elapsed(timeout_ref)) + break; + + if (io_read32(base + _CRYP_SR) & _CRYP_SR_BUSY) + return TEE_ERROR_BUSY; + + return TEE_SUCCESS; +} + +static TEE_Result wait_end_enable(vaddr_t base) +{ + uint64_t timeout_ref = timeout_init_us(CRYP_TIMEOUT_US); + + while (io_read32(base + _CRYP_CR) & _CRYP_CR_CRYPEN) + if (timeout_elapsed(timeout_ref)) + break; + + if (io_read32(base + _CRYP_CR) & _CRYP_CR_CRYPEN) + return TEE_ERROR_BUSY; + + return TEE_SUCCESS; +} + +static TEE_Result __must_check write_align_block(struct stm32_cryp_context *ctx, + uint32_t *data) +{ + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + + res = wait_sr_bits(ctx->base, _CRYP_SR_IFNF); + if (res) + return res; + + for (i = 0; i < ctx->block_u32; i++) { + /* No need to htobe() as we configure the HW to swap bytes */ + io_write32(ctx->base + _CRYP_DIN, data[i]); + } + + return TEE_SUCCESS; +} + +static TEE_Result __must_check write_block(struct stm32_cryp_context *ctx, + uint8_t *data) +{ + if (!IS_ALIGNED_WITH_TYPE(data, uint32_t)) { + uint32_t data_u32[MAX_BLOCK_NB_U32] = { 0 }; + + memcpy(data_u32, data, ctx->block_u32 * sizeof(uint32_t)); + return write_align_block(ctx, data_u32); + } + + return write_align_block(ctx, (void *)data); +} + +static TEE_Result __must_check read_align_block(struct stm32_cryp_context *ctx, + uint32_t *data) +{ + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + + res = wait_sr_bits(ctx->base, _CRYP_SR_OFNE); + if (res) + return res; + + for (i = 0; i < ctx->block_u32; i++) { + /* No need to htobe() as we configure the HW to swap bytes */ + data[i] = io_read32(ctx->base + _CRYP_DOUT); + } + + return TEE_SUCCESS; +} + +static TEE_Result __must_check read_block(struct stm32_cryp_context *ctx, + uint8_t *data) +{ + if (!IS_ALIGNED_WITH_TYPE(data, uint32_t)) { + TEE_Result res = TEE_SUCCESS; + uint32_t data_u32[MAX_BLOCK_NB_U32] = { 0 }; + + res = read_align_block(ctx, data_u32); + if (res) + return res; + + memcpy(data, data_u32, ctx->block_u32 * sizeof(uint32_t)); + + return TEE_SUCCESS; + } + + return read_align_block(ctx, (void *)data); +} + +static void cryp_end(struct stm32_cryp_context *ctx, TEE_Result prev_error) +{ + if (prev_error) { + if (rstctrl_assert_to(cryp_pdata.reset, TIMEOUT_US_1MS)) + panic(); + if (rstctrl_deassert_to(cryp_pdata.reset, TIMEOUT_US_1MS)) + panic(); + } + + /* Disable the CRYP peripheral */ + io_clrbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); +} + +static void cryp_write_iv(struct stm32_cryp_context *ctx) +{ + if (algo_mode_needs_iv(ctx->cr)) { + unsigned int i = 0; + + /* Restore the _CRYP_IVRx */ + for (i = 0; i < ctx->block_u32; i++) + io_write32(ctx->base + _CRYP_IV0LR + i * + sizeof(uint32_t), ctx->iv[i]); + } +} + +static void cryp_save_suspend(struct stm32_cryp_context *ctx) +{ + unsigned int i = 0; + + if (IS_ALGOMODE(ctx->cr, AES_GCM) || IS_ALGOMODE(ctx->cr, AES_CCM)) + for (i = 0; i < ARRAY_SIZE(ctx->pm_gcmccm); i++) + ctx->pm_gcmccm[i] = io_read32(ctx->base + + _CRYP_CSGCMCCM0R + + i * sizeof(uint32_t)); + + if (IS_ALGOMODE(ctx->cr, AES_GCM)) + for (i = 0; i < ARRAY_SIZE(ctx->pm_gcm); i++) + ctx->pm_gcm[i] = io_read32(ctx->base + _CRYP_CSGCM0R + + i * sizeof(uint32_t)); +} + +static void cryp_restore_suspend(struct stm32_cryp_context *ctx) +{ + unsigned int i = 0; + + if (IS_ALGOMODE(ctx->cr, AES_GCM) || IS_ALGOMODE(ctx->cr, AES_CCM)) + for (i = 0; i < ARRAY_SIZE(ctx->pm_gcmccm); i++) + io_write32(ctx->base + _CRYP_CSGCMCCM0R + + i * sizeof(uint32_t), ctx->pm_gcmccm[i]); + + if (IS_ALGOMODE(ctx->cr, AES_GCM)) + for (i = 0; i < ARRAY_SIZE(ctx->pm_gcm); i++) + io_write32(ctx->base + _CRYP_CSGCM0R + + i * sizeof(uint32_t), ctx->pm_gcm[i]); +} + +static void cryp_write_key(struct stm32_cryp_context *ctx) +{ + vaddr_t reg = 0; + int i = 0; + uint32_t algo = GET_ALGOMODE(ctx->cr); + + if (algo == _CRYP_CR_ALGOMODE_DES_ECB || + algo == _CRYP_CR_ALGOMODE_DES_CBC) + reg = ctx->base + _CRYP_K1RR; + else + reg = ctx->base + _CRYP_K3RR; + + for (i = ctx->key_size / sizeof(uint32_t) - 1; + i >= 0; + i--, reg -= sizeof(uint32_t)) + io_write32(reg, ctx->key[i]); +} + +static TEE_Result cryp_prepare_key(struct stm32_cryp_context *ctx) +{ + TEE_Result res = TEE_SUCCESS; + + /* + * For AES ECB/CBC decryption, key preparation mode must be selected + * to populate the key. + */ + if (is_decrypt(ctx->cr) && (IS_ALGOMODE(ctx->cr, AES_ECB) || + IS_ALGOMODE(ctx->cr, AES_CBC))) { + /* Select Algomode "prepare key" */ + io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_ALGOMODE_MSK, + _CRYP_CR_ALGOMODE_AES << _CRYP_CR_ALGOMODE_OFF); + + cryp_write_key(ctx); + + /* Enable CRYP */ + io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); + + res = wait_end_busy(ctx->base); + if (res) + return res; + + /* Reset 'real' algomode */ + io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_ALGOMODE_MSK, + ctx->cr & _CRYP_CR_ALGOMODE_MSK); + } else { + cryp_write_key(ctx); + } + + return TEE_SUCCESS; +} + +static TEE_Result save_context(struct stm32_cryp_context *ctx) +{ + /* Device should not be in a processing phase */ + if (io_read32(ctx->base + _CRYP_SR) & _CRYP_SR_BUSY) + return TEE_ERROR_BAD_STATE; + + /* Disable the CRYP peripheral */ + io_clrbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); + + /* Save CR */ + ctx->cr = io_read32(ctx->base + _CRYP_CR); + + cryp_save_suspend(ctx); + + /* If algo mode needs to save current IV */ + if (algo_mode_needs_iv(ctx->cr)) { + unsigned int i = 0; + + /* Save IV */ + for (i = 0; i < ctx->block_u32; i++) + ctx->iv[i] = io_read32(ctx->base + _CRYP_IV0LR + i * + sizeof(uint32_t)); + } + + return TEE_SUCCESS; +} + +/* To resume the processing of a message */ +static TEE_Result restore_context(struct stm32_cryp_context *ctx) +{ + TEE_Result res = TEE_SUCCESS; + + /* IP should be disabled */ + if (io_read32(ctx->base + _CRYP_CR) & _CRYP_CR_CRYPEN) { + DMSG("Device is still enabled"); + return TEE_ERROR_BAD_STATE; + } + + /* Restore the _CRYP_CR */ + io_write32(ctx->base + _CRYP_CR, ctx->cr); + + /* Write key and, in case of AES_CBC or AES_ECB decrypt, prepare it */ + res = cryp_prepare_key(ctx); + if (res) + return res; + + cryp_restore_suspend(ctx); + + cryp_write_iv(ctx); + + /* Flush internal fifo */ + io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_FFLUSH); + + /* Enable the CRYP peripheral */ + io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); + + return TEE_SUCCESS; +} + +/* + * Translate a byte index in an array of BE uint32_t into the index of same + * byte in the corresponding LE uint32_t array. + */ +static size_t be_index(size_t index) +{ + return (index & ~0x3) + 3 - (index & 0x3); +} + +static TEE_Result ccm_first_context(struct stm32_cryp_context *ctx) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t b0[AES_BLOCK_NB_U32] = { 0 }; + uint8_t *iv = (uint8_t *)ctx->iv; + size_t l = 0; + size_t i = 15; + + /* IP should be disabled */ + if (io_read32(ctx->base + _CRYP_CR) & _CRYP_CR_CRYPEN) + return TEE_ERROR_BAD_STATE; + + /* Write the _CRYP_CR */ + io_write32(ctx->base + _CRYP_CR, ctx->cr); + + /* Write key */ + res = cryp_prepare_key(ctx); + if (res) + return res; + + /* Save full IV that will be b0 */ + memcpy(b0, iv, sizeof(b0)); + + /* + * Update IV to become CTR0/1 before setting it. + * IV is saved as LE uint32_t[4] as expected by hardware, + * but CCM RFC defines bytes to update in a BE array. + */ + /* Set flag bits to 0 (5 higher bits), keep 3 low bits */ + iv[be_index(0)] &= 0x7; + /* Get size of length field (can be from 2 to 8) */ + l = iv[be_index(0)] + 1; + /* Set Q to 0 */ + for (i = 15; i >= 15 - l + 1; i--) + iv[be_index(i)] = 0; + /* Save CTR0 */ + memcpy(ctx->ctr0_ccm, iv, sizeof(b0)); + /* Increment Q */ + iv[be_index(15)] |= 0x1; + + cryp_write_iv(ctx); + + /* Enable the CRYP peripheral */ + io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); + + res = write_align_block(ctx, b0); + + return res; +} + +static TEE_Result do_from_init_to_phase(struct stm32_cryp_context *ctx, + uint32_t new_phase) +{ + TEE_Result res = TEE_SUCCESS; + + /* + * We didn't run the init phase yet + * CCM need a specific restore_context phase for the init phase + */ + if (IS_ALGOMODE(ctx->cr, AES_CCM)) + res = ccm_first_context(ctx); + else + res = restore_context(ctx); + + if (res) + return res; + + res = wait_end_enable(ctx->base); + if (res) + return res; + + /* Move to 'new_phase' */ + io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_GCM_CCMPH_MSK, + new_phase << _CRYP_CR_GCM_CCMPH_OFF); + + /* Enable the CRYP peripheral (init disabled it) */ + io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); + + return TEE_SUCCESS; +} + +static TEE_Result do_from_header_to_phase(struct stm32_cryp_context *ctx, + uint32_t new_phase) +{ + TEE_Result res = TEE_SUCCESS; + + res = restore_context(ctx); + if (res) + return res; + + if (ctx->extra_size) { + /* Manage unaligned header data before moving to next phase */ + memset((uint8_t *)ctx->extra + ctx->extra_size, 0, + ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); + + res = write_align_block(ctx, ctx->extra); + if (res) + return res; + + ctx->assoc_len += (ctx->extra_size) * INT8_BIT; + ctx->extra_size = 0; + } + + /* Move to 'new_phase' */ + io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_GCM_CCMPH_MSK, + new_phase << _CRYP_CR_GCM_CCMPH_OFF); + + return TEE_SUCCESS; +} + +/** + * @brief Start a AES computation. + * @param ctx: CRYP process context + * @param is_dec: true if decryption, false if encryption + * @param algo: define the algo mode + * @param key: pointer to key + * @param key_size: key size + * @param iv: pointer to initialization vector (unused if algo is ECB) + * @param iv_size: iv size + * @note this function doesn't access to hardware but stores in ctx the values + * + * @retval TEE_SUCCESS if OK. + */ +TEE_Result stm32_cryp_init(struct stm32_cryp_context *ctx, bool is_dec, + enum stm32_cryp_algo_mode algo, + const void *key, size_t key_size, const void *iv, + size_t iv_size) +{ + unsigned int i = 0; + const uint32_t *iv_u32 = NULL; + uint32_t local_iv[4] = { 0 }; + const uint32_t *key_u32 = NULL; + uint32_t local_key[8] = { 0 }; + + ctx->assoc_len = 0; + ctx->load_len = 0; + ctx->extra_size = 0; + ctx->lock = &cryp_lock; + + ctx->base = io_pa_or_va(&cryp_pdata.base, 1); + ctx->cr = _CRYP_CR_RESET_VALUE; + + /* We want buffer to be u32 aligned */ + if (IS_ALIGNED_WITH_TYPE(key, uint32_t)) { + key_u32 = key; + } else { + memcpy(local_key, key, key_size); + key_u32 = local_key; + } + + if (IS_ALIGNED_WITH_TYPE(iv, uint32_t)) { + iv_u32 = iv; + } else { + memcpy(local_iv, iv, iv_size); + iv_u32 = local_iv; + } + + if (is_dec) + SETBITS(ctx->cr, _CRYP_CR_ALGODIR); + else + CLRBITS(ctx->cr, _CRYP_CR_ALGODIR); + + /* Save algo mode */ + switch (algo) { + case STM32_CRYP_MODE_TDES_ECB: + SET_ALGOMODE(TDES_ECB, ctx->cr); + break; + case STM32_CRYP_MODE_TDES_CBC: + SET_ALGOMODE(TDES_CBC, ctx->cr); + break; + case STM32_CRYP_MODE_DES_ECB: + SET_ALGOMODE(DES_ECB, ctx->cr); + break; + case STM32_CRYP_MODE_DES_CBC: + SET_ALGOMODE(DES_CBC, ctx->cr); + break; + case STM32_CRYP_MODE_AES_ECB: + SET_ALGOMODE(AES_ECB, ctx->cr); + break; + case STM32_CRYP_MODE_AES_CBC: + SET_ALGOMODE(AES_CBC, ctx->cr); + break; + case STM32_CRYP_MODE_AES_CTR: + SET_ALGOMODE(AES_CTR, ctx->cr); + break; + case STM32_CRYP_MODE_AES_GCM: + SET_ALGOMODE(AES_GCM, ctx->cr); + break; + case STM32_CRYP_MODE_AES_CCM: + SET_ALGOMODE(AES_CCM, ctx->cr); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + /* + * We will use HW Byte swap (_CRYP_CR_DATATYPE_BYTE) for data. + * So we won't need to + * TOBE32(data) before write to DIN + * nor + * FROMBE32 after reading from DOUT. + */ + clrsetbits(&ctx->cr, _CRYP_CR_DATATYPE_MSK, + _CRYP_CR_DATATYPE_BYTE << _CRYP_CR_DATATYPE_OFF); + + /* + * Configure keysize for AES algorithms + * And save block size + */ + if (algo_mode_is_aes(ctx->cr)) { + switch (key_size) { + case AES_KEYSIZE_128: + clrsetbits(&ctx->cr, _CRYP_CR_KEYSIZE_MSK, + _CRYP_CR_KSIZE_128 << _CRYP_CR_KEYSIZE_OFF); + break; + case AES_KEYSIZE_192: + clrsetbits(&ctx->cr, _CRYP_CR_KEYSIZE_MSK, + _CRYP_CR_KSIZE_192 << _CRYP_CR_KEYSIZE_OFF); + break; + case AES_KEYSIZE_256: + clrsetbits(&ctx->cr, _CRYP_CR_KEYSIZE_MSK, + _CRYP_CR_KSIZE_256 << _CRYP_CR_KEYSIZE_OFF); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + /* And set block size */ + ctx->block_u32 = AES_BLOCK_NB_U32; + } else { + /* And set DES/TDES block size */ + ctx->block_u32 = DES_BLOCK_NB_U32; + } + + /* Save key in HW order */ + ctx->key_size = key_size; + for (i = 0; i < key_size / sizeof(uint32_t); i++) + ctx->key[i] = TOBE32(key_u32[i]); + + /* Save IV */ + if (algo_mode_needs_iv(ctx->cr)) { + if (!iv || iv_size != ctx->block_u32 * sizeof(uint32_t)) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * We save IV in the byte order expected by the + * IV registers + */ + for (i = 0; i < ctx->block_u32; i++) + ctx->iv[i] = TOBE32(iv_u32[i]); + } + + /* Reset suspend registers */ + memset(ctx->pm_gcmccm, 0, sizeof(ctx->pm_gcmccm)); + memset(ctx->pm_gcm, 0, sizeof(ctx->pm_gcm)); + + return TEE_SUCCESS; +} + +/** + * @brief Update (or start) a AES authenticate process of + * associated data (CCM or GCM). + * @param ctx: CRYP process context + * @param data: pointer to associated data + * @param data_size: data size + * @retval TEE_SUCCESS if OK. + */ +TEE_Result stm32_cryp_update_assodata(struct stm32_cryp_context *ctx, + uint8_t *data, size_t data_size) +{ + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + uint32_t previous_phase = 0; + + /* If no associated data, nothing to do */ + if (!data || !data_size) + return TEE_SUCCESS; + + mutex_lock(ctx->lock); + + previous_phase = (ctx->cr & _CRYP_CR_GCM_CCMPH_MSK) >> + _CRYP_CR_GCM_CCMPH_OFF; + + switch (previous_phase) { + case _CRYP_CR_GCM_CCMPH_INIT: + res = do_from_init_to_phase(ctx, _CRYP_CR_GCM_CCMPH_HEADER); + break; + case _CRYP_CR_GCM_CCMPH_HEADER: + /* + * Function update_assodata was already called. + * We only need to restore the context. + */ + res = restore_context(ctx); + break; + default: + assert(0); + res = TEE_ERROR_BAD_STATE; + } + + if (res) + goto out; + + /* Manage if remaining data from a previous update_assodata call */ + if (ctx->extra_size && + (ctx->extra_size + data_size >= + ctx->block_u32 * sizeof(uint32_t))) { + uint32_t block[MAX_BLOCK_NB_U32] = { 0 }; + + memcpy(block, ctx->extra, ctx->extra_size); + memcpy((uint8_t *)block + ctx->extra_size, data, + ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); + + res = write_align_block(ctx, block); + if (res) + goto out; + + i += ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size; + ctx->extra_size = 0; + ctx->assoc_len += ctx->block_u32 * sizeof(uint32_t) * INT8_BIT; + } + + while (data_size - i >= ctx->block_u32 * sizeof(uint32_t)) { + res = write_block(ctx, data + i); + if (res) + goto out; + + /* Process next block */ + i += ctx->block_u32 * sizeof(uint32_t); + ctx->assoc_len += ctx->block_u32 * sizeof(uint32_t) * INT8_BIT; + } + + /* + * Manage last block if not a block size multiple: + * Save remaining data to manage them later (potentially with new + * associated data). + */ + if (i < data_size) { + memcpy((uint8_t *)ctx->extra + ctx->extra_size, data + i, + data_size - i); + ctx->extra_size += data_size - i; + } + + res = save_context(ctx); +out: + if (res) + cryp_end(ctx, res); + + mutex_unlock(ctx->lock); + + return res; +} + +/** + * @brief Update (or start) a AES authenticate and de/encrypt with + * payload data (CCM or GCM). + * @param ctx: CRYP process context + * @param data_in: pointer to payload + * @param data_out: pointer where to save de/encrypted payload + * @param data_size: payload size + * + * @retval TEE_SUCCESS if OK. + */ +TEE_Result stm32_cryp_update_load(struct stm32_cryp_context *ctx, + uint8_t *data_in, uint8_t *data_out, + size_t data_size) +{ + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + uint32_t previous_phase = 0; + + if (!data_in || !data_size) + return TEE_SUCCESS; + + mutex_lock(ctx->lock); + + previous_phase = (ctx->cr & _CRYP_CR_GCM_CCMPH_MSK) >> + _CRYP_CR_GCM_CCMPH_OFF; + + switch (previous_phase) { + case _CRYP_CR_GCM_CCMPH_INIT: + res = do_from_init_to_phase(ctx, _CRYP_CR_GCM_CCMPH_PAYLOAD); + break; + case _CRYP_CR_GCM_CCMPH_HEADER: + res = do_from_header_to_phase(ctx, _CRYP_CR_GCM_CCMPH_PAYLOAD); + break; + case _CRYP_CR_GCM_CCMPH_PAYLOAD: + /* new update_load call, we only need to restore context */ + res = restore_context(ctx); + break; + default: + assert(0); + res = TEE_ERROR_BAD_STATE; + } + + if (res) + goto out; + + /* Manage if incomplete block from a previous update_load call */ + if (ctx->extra_size && + (ctx->extra_size + data_size >= + ctx->block_u32 * sizeof(uint32_t))) { + uint32_t block_out[MAX_BLOCK_NB_U32] = { 0 }; + + memcpy((uint8_t *)ctx->extra + ctx->extra_size, data_in + i, + ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); + + res = write_align_block(ctx, ctx->extra); + if (res) + goto out; + + res = read_align_block(ctx, block_out); + if (res) + goto out; + + memcpy(data_out + i, (uint8_t *)block_out + ctx->extra_size, + ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); + + i += ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size; + ctx->extra_size = 0; + + ctx->load_len += ctx->block_u32 * sizeof(uint32_t) * INT8_BIT; + } + + while (data_size - i >= ctx->block_u32 * sizeof(uint32_t)) { + res = write_block(ctx, data_in + i); + if (res) + goto out; + + res = read_block(ctx, data_out + i); + if (res) + goto out; + + /* Process next block */ + i += ctx->block_u32 * sizeof(uint32_t); + ctx->load_len += ctx->block_u32 * sizeof(uint32_t) * INT8_BIT; + } + + res = save_context(ctx); + if (res) + goto out; + + /* + * Manage last block if not a block size multiple + * We saved context, + * Complete block with 0 and send to CRYP to get {en,de}crypted data + * Store data to resend as last block in final() + * or to complete next update_load() to get correct tag. + */ + if (i < data_size) { + uint32_t block_out[MAX_BLOCK_NB_U32] = { 0 }; + size_t prev_extra_size = ctx->extra_size; + + /* Re-enable the CRYP peripheral */ + io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); + + memcpy((uint8_t *)ctx->extra + ctx->extra_size, data_in + i, + data_size - i); + ctx->extra_size += data_size - i; + memset((uint8_t *)ctx->extra + ctx->extra_size, 0, + ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); + + res = write_align_block(ctx, ctx->extra); + if (res) + goto out; + + res = read_align_block(ctx, block_out); + if (res) + goto out; + + memcpy(data_out + i, (uint8_t *)block_out + prev_extra_size, + data_size - i); + + /* Disable the CRYP peripheral */ + io_clrbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); + } + +out: + if (res) + cryp_end(ctx, res); + + mutex_unlock(ctx->lock); + + return res; +} + +/** + * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM). + * @param ctx: CRYP process context + * @param tag: pointer where to save the tag + * @param data_size: tag size + * + * @retval TEE_SUCCESS if OK. + */ +TEE_Result stm32_cryp_final(struct stm32_cryp_context *ctx, uint8_t *tag, + size_t tag_size) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t tag_u32[4] = { 0 }; + uint32_t previous_phase = 0; + + mutex_lock(ctx->lock); + + previous_phase = (ctx->cr & _CRYP_CR_GCM_CCMPH_MSK) >> + _CRYP_CR_GCM_CCMPH_OFF; + + switch (previous_phase) { + case _CRYP_CR_GCM_CCMPH_INIT: + res = do_from_init_to_phase(ctx, _CRYP_CR_GCM_CCMPH_FINAL); + break; + case _CRYP_CR_GCM_CCMPH_HEADER: + res = do_from_header_to_phase(ctx, _CRYP_CR_GCM_CCMPH_FINAL); + break; + case _CRYP_CR_GCM_CCMPH_PAYLOAD: + res = restore_context(ctx); + if (res) + break; + + /* Manage if incomplete block from a previous update_load() */ + if (ctx->extra_size) { + uint32_t block_out[MAX_BLOCK_NB_U32] = { 0 }; + size_t sz = ctx->block_u32 * sizeof(uint32_t) - + ctx->extra_size; + + if (does_need_npblb(ctx->cr)) { + io_clrsetbits32(ctx->base + _CRYP_CR, + _CRYP_CR_NPBLB_MSK, + sz << _CRYP_CR_NPBLB_OFF); + } + + memset((uint8_t *)ctx->extra + ctx->extra_size, 0, sz); + + res = write_align_block(ctx, ctx->extra); + if (res) + break; + + /* Don't care {en,de}crypted data, already saved */ + res = read_align_block(ctx, block_out); + if (res) + break; + + ctx->load_len += (ctx->extra_size * INT8_BIT); + ctx->extra_size = 0; + } + + /* Move to final phase */ + io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_GCM_CCMPH_MSK, + _CRYP_CR_GCM_CCMPH_FINAL << + _CRYP_CR_GCM_CCMPH_OFF); + break; + default: + assert(0); + res = TEE_ERROR_BAD_STATE; + } + + if (res) + goto out; + + if (IS_ALGOMODE(ctx->cr, AES_GCM)) { + /* No need to htobe() as we configure the HW to swap bytes */ + io_write32(ctx->base + _CRYP_DIN, 0U); + io_write32(ctx->base + _CRYP_DIN, ctx->assoc_len); + io_write32(ctx->base + _CRYP_DIN, 0U); + io_write32(ctx->base + _CRYP_DIN, ctx->load_len); + } else if (IS_ALGOMODE(ctx->cr, AES_CCM)) { + /* No need to htobe() in this phase */ + res = write_align_block(ctx, ctx->ctr0_ccm); + if (res) + goto out; + } + + res = read_align_block(ctx, tag_u32); + if (res) + goto out; + + memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size)); + +out: + cryp_end(ctx, res); + mutex_unlock(ctx->lock); + + return res; +} + +/** + * @brief Update (or start) a de/encrypt process. + * @param ctx: CRYP process context + * @param last_block: true if last payload data block + * @param data_in: pointer to payload + * @param data_out: pointer where to save de/encrypted payload + * @param data_size: payload size + * + * @retval TEE_SUCCESS if OK. + */ +TEE_Result stm32_cryp_update(struct stm32_cryp_context *ctx, bool last_block, + uint8_t *data_in, uint8_t *data_out, + size_t data_size) +{ + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + + mutex_lock(ctx->lock); + + /* + * In CBC and ECB encryption we need to manage specifically last + * 2 blocks if total size in not aligned to a block size. + * Currently return TEE_ERROR_NOT_IMPLEMENTED. Moreover as we need to + * know last 2 blocks, if unaligned and call with less than two blocks, + * return TEE_ERROR_BAD_STATE. + */ + if (last_block && algo_mode_is_ecb_cbc(ctx->cr) && + is_encrypt(ctx->cr) && + (ROUNDDOWN(data_size, ctx->block_u32 * sizeof(uint32_t)) != + data_size)) { + if (data_size < ctx->block_u32 * sizeof(uint32_t) * 2) { + /* + * If CBC, size of the last part should be at + * least 2*BLOCK_SIZE + */ + EMSG("Unexpected last block size"); + res = TEE_ERROR_BAD_STATE; + goto out; + } + /* + * Moreover the ECB/CBC specific padding for encrypt is not + * yet implemented, and not used in OPTEE + */ + res = TEE_ERROR_NOT_IMPLEMENTED; + goto out; + } + + /* Manage remaining CTR mask from previous update call */ + if (IS_ALGOMODE(ctx->cr, AES_CTR) && ctx->extra_size) { + unsigned int j = 0; + uint8_t *mask = (uint8_t *)ctx->extra; + + for (j = 0; j < ctx->extra_size && i < data_size; j++, i++) + data_out[i] = data_in[i] ^ mask[j]; + + if (j != ctx->extra_size) { + /* + * We didn't consume all saved mask, + * but no more data. + */ + + /* We save remaining mask and its new size */ + memmove(ctx->extra, ctx->extra + j, + ctx->extra_size - j); + ctx->extra_size -= j; + + /* + * We don't need to save HW context we didn't + * modify HW state. + */ + res = TEE_SUCCESS; + goto out; + } + + /* All extra mask consumed */ + ctx->extra_size = 0; + } + + res = restore_context(ctx); + if (res) + goto out; + + while (data_size - i >= ctx->block_u32 * sizeof(uint32_t)) { + /* + * We only write/read one block at a time + * but CRYP use a in (and out) FIFO of 8 * uint32_t + */ + res = write_block(ctx, data_in + i); + if (res) + goto out; + + res = read_block(ctx, data_out + i); + if (res) + goto out; + + /* Process next block */ + i += ctx->block_u32 * sizeof(uint32_t); + } + + /* Manage last block if not a block size multiple */ + if (i < data_size) { + uint32_t block_in[MAX_BLOCK_NB_U32] = { 0 }; + uint32_t block_out[MAX_BLOCK_NB_U32] = { 0 }; + + if (!IS_ALGOMODE(ctx->cr, AES_CTR)) { + /* + * Other algorithm than CTR can manage only multiple + * of block_size. + */ + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * For CTR we save the generated mask to use it at next + * update call. + */ + memcpy(block_in, data_in + i, data_size - i); + + res = write_align_block(ctx, block_in); + if (res) + goto out; + + res = read_align_block(ctx, block_out); + if (res) + goto out; + + memcpy(data_out + i, block_out, data_size - i); + + /* Save mask for possibly next call */ + ctx->extra_size = ctx->block_u32 * sizeof(uint32_t) - + (data_size - i); + memcpy(ctx->extra, (uint8_t *)block_out + data_size - i, + ctx->extra_size); + } + + if (!last_block) + res = save_context(ctx); + +out: + /* If last block or error, end of CRYP process */ + if (last_block || res) + cryp_end(ctx, res); + + mutex_unlock(ctx->lock); + + return res; +} + +static TEE_Result stm32_cryp_probe(const void *fdt, int node, + const void *compt_data __unused) +{ + TEE_Result res = TEE_SUCCESS; + struct dt_node_info dt_cryp = { }; + struct rstctrl *rstctrl = NULL; + struct clk *clk = NULL; + + fdt_fill_device_info(fdt, &dt_cryp, node); + + if (dt_cryp.reg == DT_INFO_INVALID_REG || + dt_cryp.reg_size == DT_INFO_INVALID_REG_SIZE) + panic(); + + res = clk_dt_get_by_index(fdt, node, 0, &clk); + if (res) + return res; + + res = rstctrl_dt_get_by_index(fdt, node, 0, &rstctrl); + if (res) + return res; + + cryp_pdata.clock = clk; + cryp_pdata.reset = rstctrl; + cryp_pdata.base.pa = dt_cryp.reg; + + io_pa_or_va_secure(&cryp_pdata.base, dt_cryp.reg_size); + if (!cryp_pdata.base.va) + panic(); + + stm32mp_register_secure_periph_iomem(cryp_pdata.base.pa); + + if (clk_enable(cryp_pdata.clock)) + panic(); + + if (rstctrl_assert_to(cryp_pdata.reset, TIMEOUT_US_1MS)) + panic(); + + if (rstctrl_deassert_to(cryp_pdata.reset, TIMEOUT_US_1MS)) + panic(); + + if (IS_ENABLED(CFG_CRYPTO_DRV_AUTHENC)) { + res = stm32_register_authenc(); + if (res) { + EMSG("Failed to register to authenc: %#"PRIx32, res); + panic(); + } + } + + if (IS_ENABLED(CFG_CRYPTO_DRV_CIPHER)) { + res = stm32_register_cipher(); + if (res) { + EMSG("Failed to register to cipher: %#"PRIx32, res); + panic(); + } + } + + return TEE_SUCCESS; +} + +static const struct dt_device_match stm32_cryp_match_table[] = { + { .compatible = "st,stm32mp1-cryp" }, + { } +}; + +DEFINE_DT_DRIVER(stm32_cryp_dt_driver) = { + .name = "stm32-cryp", + .match_table = stm32_cryp_match_table, + .probe = stm32_cryp_probe, +}; diff --git a/optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.h b/optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.h new file mode 100644 index 0000000..a8f609c --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/stm32_cryp.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#ifndef STM32_CRYP_H +#define STM32_CRYP_H + +#include +#include +#include +#include +#include +#include +#include + +/* + * Platform data related to CRYP instance + * @base - IO memory base address + * @clk - CRYP clock reference + * @rstctrl - CRYP reset controller reference + */ +struct stm32_cryp_platdata { + struct io_pa_va base; + struct clk *clock; + struct rstctrl *reset; +}; + +enum stm32_cryp_algo_mode { + STM32_CRYP_MODE_TDES_ECB, + STM32_CRYP_MODE_TDES_CBC, + STM32_CRYP_MODE_DES_ECB, + STM32_CRYP_MODE_DES_CBC, + STM32_CRYP_MODE_AES_ECB, + STM32_CRYP_MODE_AES_CBC, + STM32_CRYP_MODE_AES_CTR, + STM32_CRYP_MODE_AES_GCM, + STM32_CRYP_MODE_AES_CCM, +}; + +/* + * Full CRYP context. + * Store CRYP internal state to be able to compute any supported algorithm. + */ +struct stm32_cryp_context { + vaddr_t base; + uint32_t cr; + struct mutex *lock; /* Protect CRYP HW instance access */ + uint32_t assoc_len; + uint32_t load_len; + uint32_t key[8]; /* In HW byte order */ + size_t key_size; + size_t block_u32; + uint32_t iv[4]; /* In HW byte order */ + uint32_t pm_gcmccm[8]; + union { + uint32_t pm_gcm[8]; + uint32_t ctr0_ccm[4]; + }; + uint32_t extra[4]; + size_t extra_size; +}; + +TEE_Result stm32_cryp_init(struct stm32_cryp_context *ctx, bool is_decrypt, + enum stm32_cryp_algo_mode mode, + const void *key, size_t key_size, const void *iv, + size_t iv_size); +TEE_Result stm32_cryp_update(struct stm32_cryp_context *ctx, bool last_block, + uint8_t *data_in, uint8_t *data_out, + size_t data_size); +TEE_Result stm32_cryp_update_assodata(struct stm32_cryp_context *ctx, + uint8_t *data, size_t data_size); +TEE_Result stm32_cryp_update_load(struct stm32_cryp_context *ctx, + uint8_t *data_in, uint8_t *data_out, + size_t data_size); +TEE_Result stm32_cryp_final(struct stm32_cryp_context *ctx, uint8_t *tag, + size_t tag_size); +#endif diff --git a/optee/optee_os/core/drivers/crypto/stm32/sub.mk b/optee/optee_os/core/drivers/crypto/stm32/sub.mk new file mode 100644 index 0000000..675be03 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/stm32/sub.mk @@ -0,0 +1,3 @@ +srcs-$(CFG_STM32_CRYP) += stm32_cryp.c +srcs-$(CFG_CRYPTO_DRV_CIPHER) += cipher.c +srcs-$(CFG_CRYPTO_DRV_AUTHENC) += authenc.c diff --git a/optee/optee_os/core/drivers/crypto/sub.mk b/optee/optee_os/core/drivers/crypto/sub.mk new file mode 100644 index 0000000..3c26eda --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/sub.mk @@ -0,0 +1,13 @@ +global-incdirs-$(CFG_CRYPTO_DRIVER) += crypto_api/include + +subdirs-$(CFG_CRYPTO_DRIVER) += crypto_api + +subdirs-$(CFG_NXP_CAAM) += caam + +subdirs-$(CFG_NXP_SE05X) += se050 + +subdirs-$(CFG_STM32_CRYPTO_DRIVER) += stm32 + +subdirs-$(CFG_ASPEED_CRYPTO_DRIVER) += aspeed + +subdirs-$(CFG_VERSAL_CRYPTO_DRIVER) += versal diff --git a/optee/optee_os/core/drivers/crypto/versal/authenc.c b/optee/optee_os/core/drivers/crypto/versal/authenc.c new file mode 100644 index 0000000..8776dac --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/versal/authenc.c @@ -0,0 +1,870 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022. + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This driver does not queue/pad non-aligned data. + * + * Allow debug information for future PLM work: if the PLM can not implement + * the required changes, we might be able to do it in OP-TEE. + */ +#define DEBUG_VERSAL_AES 0 + +#define GCM_TAG_LEN 16 + +#define XSECURE_AES_KEY_SIZE_128 0 /* Key Length = 32 bytes = 256 bits */ +#define XSECURE_AES_KEY_SIZE_256 2 /* Key Length = 16 bytes = 128 bits */ + +#define XSECURE_ENCRYPT 0 +#define XSECURE_DECRYPT 1 + +enum versal_aes_err { + AES_GCM_TAG_MISMATCH = 0x40, + AES_KEY_CLEAR_ERROR, + AES_DPA_CM_NOT_SUPPORTED, + AES_KAT_WRITE_KEY_FAILED_ERROR, + AES_KAT_DECRYPT_INIT_FAILED_ERROR, + AES_KAT_GCM_TAG_MISMATCH_ERROR, + AES_KAT_DATA_MISMATCH_ERROR, + AES_KAT_FAILED_ERROR, + AESDPACM_KAT_WRITE_KEY_FAILED_ERROR, + AESDPACM_KAT_KEYLOAD_FAILED_ERROR, + AESDPACM_SSS_CFG_FAILED_ERROR, + AESDPACM_KAT_FAILED_ERROR, + AESDPACM_KAT_CHECK1_FAILED_ERROR, + AESDPACM_KAT_CHECK2_FAILED_ERROR, + AESDPACM_KAT_CHECK3_FAILED_ERROR, + AESDPACM_KAT_CHECK4_FAILED_ERROR, + AESDPACM_KAT_CHECK5_FAILED_ERROR, + AES_INVALID_PARAM, + AESKAT_INVALID_PARAM, + AES_STATE_MISMATCH_ERROR, + AES_DEVICE_KEY_NOT_ALLOWED, +}; + +#define VERSAL_AES_ERROR(m) { . error = (m), .name = TO_STR(m) } + +static const char *versal_aes_error(uint8_t err) +{ + const struct { + enum versal_aes_err error; + const char *name; + } elist[] = { + VERSAL_AES_ERROR(AES_GCM_TAG_MISMATCH), + VERSAL_AES_ERROR(AES_KEY_CLEAR_ERROR), + VERSAL_AES_ERROR(AES_DPA_CM_NOT_SUPPORTED), + VERSAL_AES_ERROR(AES_KAT_WRITE_KEY_FAILED_ERROR), + VERSAL_AES_ERROR(AES_KAT_DECRYPT_INIT_FAILED_ERROR), + VERSAL_AES_ERROR(AES_KAT_GCM_TAG_MISMATCH_ERROR), + VERSAL_AES_ERROR(AES_KAT_DATA_MISMATCH_ERROR), + VERSAL_AES_ERROR(AES_KAT_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_KAT_WRITE_KEY_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_KAT_KEYLOAD_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_SSS_CFG_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_KAT_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_KAT_CHECK1_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_KAT_CHECK2_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_KAT_CHECK3_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_KAT_CHECK4_FAILED_ERROR), + VERSAL_AES_ERROR(AESDPACM_KAT_CHECK5_FAILED_ERROR), + VERSAL_AES_ERROR(AES_INVALID_PARAM), + VERSAL_AES_ERROR(AESKAT_INVALID_PARAM), + VERSAL_AES_ERROR(AES_STATE_MISMATCH_ERROR), + VERSAL_AES_ERROR(AES_DEVICE_KEY_NOT_ALLOWED), + }; + + if (err >= AES_GCM_TAG_MISMATCH && err <= AES_DEVICE_KEY_NOT_ALLOWED) { + if (elist[err - AES_GCM_TAG_MISMATCH].name) + return elist[err - AES_GCM_TAG_MISMATCH].name; + + return "Invalid"; + } + + return "Unknown"; +} + +enum aes_key_src { + XSECURE_AES_BBRAM_KEY = 0, /* BBRAM Key */ + XSECURE_AES_BBRAM_RED_KEY, /* BBRAM Red Key */ + XSECURE_AES_BH_KEY, /* BH Key */ + XSECURE_AES_BH_RED_KEY, /* BH Red Key */ + XSECURE_AES_EFUSE_KEY, /* eFUSE Key */ + XSECURE_AES_EFUSE_RED_KEY, /* eFUSE Red Key */ + XSECURE_AES_EFUSE_USER_KEY_0, /* eFUSE User Key 0 */ + XSECURE_AES_EFUSE_USER_KEY_1, /* eFUSE User Key 1 */ + XSECURE_AES_EFUSE_USER_RED_KEY_0, /* eFUSE User Red Key 0 */ + XSECURE_AES_EFUSE_USER_RED_KEY_1, /* eFUSE User Red Key 1 */ + XSECURE_AES_KUP_KEY, /* KUP key */ + XSECURE_AES_PUF_KEY, /* PUF key */ + XSECURE_AES_USER_KEY_0, /* User Key 0 */ + XSECURE_AES_USER_KEY_1, /* User Key 1 */ + XSECURE_AES_USER_KEY_2, /* User Key 2 */ + XSECURE_AES_USER_KEY_3, /* User Key 3 */ + XSECURE_AES_USER_KEY_4, /* User Key 4 */ + XSECURE_AES_USER_KEY_5, /* User Key 5 */ + XSECURE_AES_USER_KEY_6, /* User Key 6 */ + XSECURE_AES_USER_KEY_7, /* User Key 7 */ + XSECURE_AES_EXPANDED_KEYS, /* Expanded keys */ + XSECURE_AES_ALL_KEYS, /* AES All keys */ +}; + +struct versal_payload { + struct versal_mbox_mem input_cmd; + struct versal_mbox_mem src; + struct versal_mbox_mem dst; + bool encrypt; +}; + +struct versal_aad { + struct versal_mbox_mem mem; +}; + +struct versal_node { + struct versal_payload payload; + struct versal_aad aad; + bool is_aad; + STAILQ_ENTRY(versal_node) link; +}; + +struct versal_init { + uint32_t key_len; + uint32_t operation; + struct versal_mbox_mem key; + struct versal_mbox_mem nonce; + struct versal_mbox_mem init_buf; +}; + +struct versal_ae_ctx { + struct crypto_authenc_ctx a_ctx; +}; + +struct versal_context_node { + struct versal_ae_ctx *ctx; + STAILQ_ENTRY(versal_context_node) link; +}; + +enum engine_state { + READY = 1, INIT = 2, FINALIZED = 3, +}; + +static struct mutex engine_lock = MUTEX_INITIALIZER; + +static struct versal_engine { + enum aes_key_src key_src; + enum engine_state state; + struct versal_init init; + struct refcount refc; + struct mutex *lock; /* protect the HW instance */ + STAILQ_HEAD(authenc_context_list, versal_context_node) context_list; + STAILQ_HEAD(authenc_replay_list, versal_node) replay_list; +} engine = { + .key_src = XSECURE_AES_USER_KEY_0, + .lock = &engine_lock, +}; + +static struct versal_ae_ctx *to_versal_ctx(struct crypto_authenc_ctx *ctx) +{ + assert(ctx); + + return container_of(ctx, struct versal_ae_ctx, a_ctx); +} + +static TEE_Result replay_init(void) +{ + struct versal_cmd_args arg = { }; + uint32_t err = 0; + + if (versal_crypto_request(VERSAL_AES_INIT, &arg, &err)) { + EMSG("AES_INIT error"); + return TEE_ERROR_GENERIC; + } + + arg.data[arg.dlen++] = engine.init.key_len; + arg.data[arg.dlen++] = engine.key_src; + arg.ibuf[0].mem = engine.init.key; + + if (versal_crypto_request(VERSAL_AES_WRITE_KEY, &arg, &err)) { + EMSG("AES_WRITE_KEY error"); + return TEE_ERROR_GENERIC; + } + + memset(&arg, 0, sizeof(arg)); + + arg.ibuf[0].mem = engine.init.init_buf; + arg.ibuf[1].mem = engine.init.nonce; + arg.ibuf[1].only_cache = true; + + if (versal_crypto_request(VERSAL_AES_OP_INIT, &arg, &err)) { + EMSG("AES_OP_INIT error"); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static TEE_Result replay_aad(struct versal_aad *p) +{ + struct versal_cmd_args arg = { }; + uint32_t err = 0; + + arg.data[arg.dlen++] = p->mem.len % 16 ? p->mem.alloc_len : p->mem.len; + arg.ibuf[0].mem = p->mem; + + if (versal_crypto_request(VERSAL_AES_UPDATE_AAD, &arg, &err)) { + EMSG("AES_UPDATE_AAD error: %s", versal_aes_error(err)); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static TEE_Result replay_payload(struct versal_payload *p) +{ + enum versal_crypto_api id = VERSAL_AES_DECRYPT_UPDATE; + struct versal_cmd_args arg = { }; + uint32_t err = 0; + + arg.ibuf[0].mem = p->input_cmd; + arg.ibuf[1].mem = p->dst; + arg.ibuf[2].mem = p->src; + + if (p->encrypt) + id = VERSAL_AES_ENCRYPT_UPDATE; + + if (versal_crypto_request(id, &arg, &err)) { + EMSG("AES_UPDATE_PAYLOAD error: %s", versal_aes_error(err)); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static TEE_Result do_replay(void) +{ + struct versal_node *node = NULL; + TEE_Result ret = TEE_SUCCESS; + + ret = replay_init(); + if (ret) + return ret; + + STAILQ_FOREACH(node, &engine.replay_list, link) { + if (node->is_aad) { + ret = replay_aad(&node->aad); + if (ret) + return ret; + } else { + ret = replay_payload(&node->payload); + if (ret) + return ret; + } + } + + /* Engine has been init */ + engine.state = INIT; + + return TEE_SUCCESS; +} + +static bool engine_in_use(void) +{ + if (STAILQ_EMPTY(&engine.context_list)) + return false; + + return true; +} + +static bool context_allowed(struct crypto_authenc_ctx *ctx) +{ + struct versal_context_node *node = NULL; + + STAILQ_FOREACH(node, &engine.context_list, link) { + if (node->ctx == to_versal_ctx(ctx)) + return true; + } + + return false; +} + +static TEE_Result do_init(struct drvcrypt_authenc_init *dinit) +{ + uint32_t key_len = XSECURE_AES_KEY_SIZE_128; + struct versal_context_node *node = NULL; + struct versal_aes_init *init = NULL; + struct versal_mbox_mem init_buf = { }; + struct versal_mbox_mem key = { }; + struct versal_mbox_mem nonce = { }; + struct versal_cmd_args arg = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + + if (engine_in_use()) { + EMSG("Versal: AES-GCM Engine busy"); + return TEE_ERROR_BUSY; + } + + if (dinit->key.length != 32 && dinit->key.length != 16) + return TEE_ERROR_BAD_PARAMETERS; + + if (dinit->key.length == 32) + key_len = XSECURE_AES_KEY_SIZE_256; + + if (engine.state != READY) + return TEE_ERROR_BAD_STATE; + + /* Initialize the AES engine */ + if (versal_crypto_request(VERSAL_AES_INIT, &arg, &err)) { + EMSG("AES_INIT error: %s", versal_aes_error(err)); + return TEE_ERROR_GENERIC; + } + + /* Write the key */ + versal_mbox_alloc(dinit->key.length, dinit->key.data, &key); + + arg.data[arg.dlen++] = key_len; + arg.data[arg.dlen++] = engine.key_src; + arg.ibuf[0].mem = key; + + if (versal_crypto_request(VERSAL_AES_WRITE_KEY, &arg, &err)) { + EMSG("AES_WRITE_KEY error: %s", versal_aes_error(err)); + ret = TEE_ERROR_GENERIC; + goto error; + } + + memset(&arg, 0, sizeof(arg)); + + /* Send the initialization structure */ + versal_mbox_alloc(sizeof(*init), NULL, &init_buf); + versal_mbox_alloc(dinit->nonce.length, dinit->nonce.data, &nonce); + + init = init_buf.buf; + init->iv_addr = virt_to_phys(nonce.buf); + init->operation = dinit->encrypt ? XSECURE_ENCRYPT : XSECURE_DECRYPT; + init->key_src = engine.key_src; + init->key_len = key_len; + + arg.ibuf[0].mem = init_buf; + arg.ibuf[1].mem = nonce; + arg.ibuf[1].only_cache = true; + + if (versal_crypto_request(VERSAL_AES_OP_INIT, &arg, &err)) { + EMSG("AES_OP_INIT error: %s", versal_aes_error(err)); + ret = TEE_ERROR_GENERIC; + goto error; + } + + node = calloc(1, sizeof(*node)); + if (!node) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto error; + } + + /* Save key context */ + engine.init.operation = dinit->encrypt ? + XSECURE_ENCRYPT : XSECURE_DECRYPT; + engine.init.key_len = key_len; + engine.init.init_buf = init_buf; + engine.init.nonce = nonce; + engine.init.key = key; + + /* Active context */ + node->ctx = to_versal_ctx(dinit->ctx); + STAILQ_INSERT_TAIL(&engine.context_list, node, link); + + /* Engine has been init*/ + engine.state = INIT; + + return TEE_SUCCESS; +error: + free(key.buf); + free(init_buf.buf); + free(nonce.buf); + + return ret; +} + +static TEE_Result do_update_aad(struct drvcrypt_authenc_update_aad *dupdate) +{ + struct versal_cmd_args arg = { }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + struct versal_node *node = NULL; + uint32_t err = 0; + + /* This context has not been inited */ + if (!context_allowed(dupdate->ctx)) + return TEE_ERROR_BUSY; + + /* There is a copy of the context: don't allow updates, only finalize */ + if (refcount_val(&engine.refc) > 1) + return TEE_ERROR_BUSY; + + /* There was a copy of the context and it was finalized, then replay */ + if (engine.state == FINALIZED) + do_replay(); + + versal_mbox_alloc(dupdate->aad.length, dupdate->aad.data, &p); + + arg.data[arg.dlen++] = p.len % 16 ? p.alloc_len : p.len; + arg.ibuf[0].mem = p; + +#if DEBUG_VERSAL_AES + IMSG("versal: aad length - requested: %zu, sent to plm: %"PRIu32, + dupdate->aad.length, arg.data[0]); +#endif + if (versal_crypto_request(VERSAL_AES_UPDATE_AAD, &arg, &err)) { + EMSG("AES_UPDATE_AAD error: %s", versal_aes_error(err)); + ret = TEE_ERROR_GENERIC; + goto error; + } + + node = calloc(1, sizeof(*node)); + if (!node) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto error; + } + + /* Save the context */ + node->aad.mem = p; + node->is_aad = true; + STAILQ_INSERT_TAIL(&engine.replay_list, node, link); + + return TEE_SUCCESS; +error: + free(p.buf); + return ret; +} + +static TEE_Result +update_payload(struct drvcrypt_authenc_update_payload *dupdate, bool is_last) +{ + enum versal_crypto_api id = VERSAL_AES_DECRYPT_UPDATE; + struct versal_aes_input_param *input = NULL; + struct versal_mbox_mem input_cmd = { }; + struct versal_mbox_mem p = { }; + struct versal_mbox_mem q = { }; + TEE_Result ret = TEE_SUCCESS; + struct versal_cmd_args arg = { }; + struct versal_node *node = NULL; + uint32_t err = 0; + + if (!context_allowed(dupdate->ctx)) + return TEE_ERROR_BUSY; + + if (!dupdate->src.length || dupdate->src.length % 4) { + EMSG("Versal AES payload length not word aligned (len = %zu)", + dupdate->src.length); + return TEE_ERROR_BAD_PARAMETERS; + } + + versal_mbox_alloc(dupdate->src.length, dupdate->src.data, &p); + versal_mbox_alloc(dupdate->dst.length, NULL, &q); + versal_mbox_alloc(sizeof(*input), NULL, &input_cmd); + + input = input_cmd.buf; + input->input_addr = virt_to_phys(p.buf); + input->input_len = p.len % 16 ? p.alloc_len : p.len; + input->is_last = is_last; + + arg.ibuf[0].mem = input_cmd; + arg.ibuf[1].mem = q; + arg.ibuf[2].mem = p; + + if (dupdate->encrypt) + id = VERSAL_AES_ENCRYPT_UPDATE; + +#if DEBUG_VERSAL_AES + IMSG("versal: payload length - requested %zu, sent to plm: %"PRIu32, + dupdate->src.length, input->input_len); + IMSG("versal: destination length - %zu ", dupdate->dst.length); +#endif + if (versal_crypto_request(id, &arg, &err)) { + EMSG("AES_UPDATE_PAYLOAD error: %s", versal_aes_error(err)); + ret = TEE_ERROR_GENERIC; + goto out; + } + + if (dupdate->dst.data) + memcpy(dupdate->dst.data, q.buf, dupdate->dst.length); + + if (!is_last) { + node = calloc(1, sizeof(*node)); + if (!node) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + node->is_aad = false; + node->payload.dst = q; + node->payload.src = p; + node->payload.input_cmd = input_cmd; + node->payload.encrypt = dupdate->encrypt; + STAILQ_INSERT_TAIL(&engine.replay_list, node, link); + + return TEE_SUCCESS; + } +out: + free(p.buf); + free(q.buf); + free(input_cmd.buf); + + return ret; +} + +static TEE_Result do_update_payload(struct drvcrypt_authenc_update_payload *p) +{ + TEE_Result ret = TEE_SUCCESS; + + if (!context_allowed(p->ctx)) + return TEE_ERROR_BUSY; + + /* + * If there is a copy, we don't allow updates until one of the copies + * has been deleted + */ + if (refcount_val(&engine.refc) > 1) + return TEE_ERROR_BUSY; + + /* + * If there was a copy and it was finalized, we need to replay before + * we can update; do not clear the list so the state can be copied + */ + if (engine.state == FINALIZED) { + ret = do_replay(); + if (ret) + return ret; + } + + return update_payload(p, false); +} + +static TEE_Result do_enc_final(struct drvcrypt_authenc_final *dfinal) +{ + struct drvcrypt_authenc_update_payload last = { }; + struct versal_cmd_args arg = { }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + + if (!context_allowed(dfinal->ctx)) + return TEE_ERROR_BUSY; + + if (engine.state == FINALIZED) { + DMSG("Operation was already finalized"); + ret = do_replay(); + if (ret) + return ret; + } + + if (engine.state != INIT) + panic(); + + last.ctx = dfinal->ctx; + last.dst = dfinal->dst; + last.encrypt = true; + last.src = dfinal->src; + + ret = update_payload(&last, true); + if (ret) + return ret; + + memcpy(dfinal->dst.data, last.dst.data, dfinal->dst.length); + + versal_mbox_alloc(GCM_TAG_LEN, NULL, &p); + + arg.ibuf[0].mem = p; + if (versal_crypto_request(VERSAL_AES_ENCRYPT_FINAL, &arg, &err)) { + EMSG("AES_ENCRYPT_FINAL error: %s", versal_aes_error(err)); + ret = TEE_ERROR_GENERIC; + goto out; + } + + memcpy(dfinal->tag.data, p.buf, GCM_TAG_LEN); + dfinal->tag.length = GCM_TAG_LEN; +out: + free(p.buf); + + if (refcount_val(&engine.refc) > 1) + engine.state = FINALIZED; + else + engine.state = READY; + + return ret; +} + +static TEE_Result do_dec_final(struct drvcrypt_authenc_final *dfinal) +{ + struct drvcrypt_authenc_update_payload last = { }; + struct versal_cmd_args arg = { }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + + if (!context_allowed(dfinal->ctx)) + return TEE_ERROR_BUSY; + + if (engine.state == FINALIZED) { + DMSG("Operation was already finalized"); + ret = do_replay(); + if (ret) + return ret; + } + + if (engine.state != INIT) + panic(); + + last.encrypt = false; + last.ctx = dfinal->ctx; + last.dst = dfinal->dst; + last.src = dfinal->src; + + ret = update_payload(&last, true); + if (ret) + return ret; + + versal_mbox_alloc(dfinal->tag.length, dfinal->tag.data, &p); + arg.ibuf[0].mem = p; + + if (versal_crypto_request(VERSAL_AES_DECRYPT_FINAL, &arg, &err)) { + EMSG("AES_DECRYPT_FINAL error: %s", versal_aes_error(err)); + ret = TEE_ERROR_GENERIC; + goto out; + } + + memcpy(dfinal->dst.data, last.dst.data, dfinal->dst.length); + memcpy(dfinal->tag.data, p.buf, GCM_TAG_LEN); + dfinal->tag.length = GCM_TAG_LEN; +out: + free(p.buf); + + if (refcount_val(&engine.refc) > 1) + engine.state = FINALIZED; + else + engine.state = READY; + + return ret; +} + +static void do_final(void *ctx __unused) +{ +} + +static void do_free(void *ctx) +{ + struct versal_ae_ctx *c = to_versal_ctx(ctx); + struct versal_node *next = NULL; + struct versal_node *node = NULL; + struct versal_context_node *ctx_next = NULL; + struct versal_context_node *ctx_node = NULL; + bool release = false; + + if (refcount_dec(&engine.refc)) { + /* this is a final release */ + release = true; + refcount_set(&engine.refc, 1); + engine.state = READY; + free(engine.init.init_buf.buf); + free(engine.init.nonce.buf); + free(engine.init.key.buf); + memset(&engine.init, 0, sizeof(engine.init)); + STAILQ_FOREACH_SAFE(node, &engine.replay_list, link, next) { + STAILQ_REMOVE(&engine.replay_list, node, + versal_node, link); + if (node->is_aad) { + free(node->aad.mem.buf); + } else { + free(node->payload.dst.buf); + free(node->payload.src.buf); + free(node->payload.input_cmd.buf); + } + free(node); + } + } + + STAILQ_FOREACH_SAFE(ctx_node, &engine.context_list, link, ctx_next) { + if (c == ctx_node->ctx) { + STAILQ_REMOVE(&engine.context_list, ctx_node, + versal_context_node, link); + free(ctx_node); + } + } + + if (release && engine_in_use()) + panic(); + + free(c); +} + +static void do_copy_state(void *dst_ctx, void *src_ctx) +{ + struct versal_context_node *node = NULL; + + STAILQ_FOREACH(node, &engine.context_list, link) { + if (node->ctx != to_versal_ctx(src_ctx)) + continue; + /* + * The running context has been copied: from now on we can only + * finalize any of the contexts until there is only one active + * again. + */ + node = calloc(1, sizeof(*node)); + if (!node) + panic(); + + node->ctx = to_versal_ctx(dst_ctx); + STAILQ_INSERT_TAIL(&engine.context_list, node, link); + + /* number of active contexts */ + refcount_inc(&engine.refc); + + return; + } + + panic(); +} + +static TEE_Result do_allocate(void **ctx, uint32_t algo) +{ + struct versal_ae_ctx *c = NULL; + + if (algo != TEE_ALG_AES_GCM) + return TEE_ERROR_NOT_IMPLEMENTED; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + *ctx = &c->a_ctx; + + return TEE_SUCCESS; +} + +static TEE_Result +do_update_payload_locked(struct drvcrypt_authenc_update_payload *p) +{ + TEE_Result ret = TEE_SUCCESS; + + mutex_lock(engine.lock); + ret = do_update_payload(p); + mutex_unlock(engine.lock); + return ret; +} + +static TEE_Result +do_update_aad_locked(struct drvcrypt_authenc_update_aad *p) +{ + TEE_Result ret = TEE_SUCCESS; + + mutex_lock(engine.lock); + ret = do_update_aad(p); + mutex_unlock(engine.lock); + return ret; +} + +static void do_copy_state_locked(void *dst, void *src) +{ + mutex_lock(engine.lock); + do_copy_state(dst, src); + mutex_unlock(engine.lock); +} + +static TEE_Result do_enc_final_locked(struct drvcrypt_authenc_final *p) +{ + TEE_Result ret = TEE_SUCCESS; + + mutex_lock(engine.lock); + ret = do_enc_final(p); + mutex_unlock(engine.lock); + return ret; +} + +static TEE_Result do_dec_final_locked(struct drvcrypt_authenc_final *p) +{ + TEE_Result ret = TEE_SUCCESS; + + mutex_lock(engine.lock); + ret = do_dec_final(p); + mutex_unlock(engine.lock); + return ret; +} + +static void do_free_locked(void *p) +{ + mutex_lock(engine.lock); + do_free(p); + mutex_unlock(engine.lock); +} + +static TEE_Result do_init_locked(struct drvcrypt_authenc_init *p) +{ + TEE_Result ret = TEE_SUCCESS; + + mutex_lock(engine.lock); + ret = do_init(p); + mutex_unlock(engine.lock); + return ret; +} + +static struct drvcrypt_authenc versal_authenc = { + .update_payload = do_update_payload_locked, + .update_aad = do_update_aad_locked, + .copy_state = do_copy_state_locked, + .enc_final = do_enc_final_locked, + .dec_final = do_dec_final_locked, + .free_ctx = do_free_locked, + .alloc_ctx = do_allocate, + .init = do_init_locked, + .final = do_final, +}; + +static TEE_Result enable_secure_status(void) +{ + /* Once Linux has support, we need to reserve the device */ + return TEE_SUCCESS; +} + +static TEE_Result versal_register_authenc(void) +{ + TEE_Result ret = TEE_SUCCESS; + + ret = drvcrypt_register_authenc(&versal_authenc); + if (ret) + return ret; + + if (engine.key_src < XSECURE_AES_USER_KEY_0 || + engine.key_src > XSECURE_AES_USER_KEY_7) + return TEE_ERROR_GENERIC; + + engine.state = READY; + STAILQ_INIT(&engine.replay_list); + STAILQ_INIT(&engine.context_list); + refcount_set(&engine.refc, 1); + + return enable_secure_status(); +} + +driver_init_late(versal_register_authenc); diff --git a/optee/optee_os/core/drivers/crypto/versal/crypto.mk b/optee/optee_os/core/drivers/crypto/versal/crypto.mk new file mode 100644 index 0000000..2dc92c2 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/versal/crypto.mk @@ -0,0 +1,11 @@ +ifeq ($(CFG_VERSAL_CRYPTO_DRIVER),y) +# Enable the crypto driver +$(call force,CFG_CRYPTO_DRIVER,y) + +CFG_CRYPTO_DRIVER_DEBUG ?= 0 +$(call force,CFG_CRYPTO_DRV_ACIPHER,y) +$(call force,CFG_CRYPTO_DRV_ECC,y) +$(call force,CFG_CRYPTO_DRV_RSA,y) +$(call force,CFG_CRYPTO_DRV_AUTHENC,y) + +endif diff --git a/optee/optee_os/core/drivers/crypto/versal/ecc.c b/optee/optee_os/core/drivers/crypto/versal/ecc.c new file mode 100644 index 0000000..ff8ea37 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/versal/ecc.c @@ -0,0 +1,469 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022. + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* AMD/Xilinx Versal's Known Answer Tests */ +#define XSECURE_ECDSA_KAT_NIST_P384 0 +#define XSECURE_ECDSA_KAT_NIST_P521 2 + +/* Software based ECDSA operations */ +static const struct crypto_ecc_keypair_ops *pair_ops; +static const struct crypto_ecc_public_ops *pub_ops; + +enum versal_ecc_err { + KAT_KEY_NOTVALID_ERROR = 0xC0, + KAT_FAILED_ERROR, + NON_SUPPORTED_CURVE, + KEY_ZERO, + KEY_WRONG_ORDER, + KEY_NOT_ON_CURVE, + BAD_SIGN, + GEN_SIGN_INCORRECT_HASH_LEN, + VER_SIGN_INCORRECT_HASH_LEN, + GEN_SIGN_BAD_RAND_NUM, + GEN_KEY_ERR, + INVALID_PARAM, + VER_SIGN_R_ZERO, + VER_SIGN_S_ZERO, + VER_SIGN_R_ORDER_ERROR, + VER_SIGN_S_ORDER_ERROR, + KAT_INVLD_CRV_ERROR, +}; + +#define VERSAL_ECC_ERROR(m) { .error = (m), .name = TO_STR(m) } + +static const char *versal_ecc_error(uint8_t err) +{ + struct { + enum versal_ecc_err error; + const char *name; + } elist[] = { + VERSAL_ECC_ERROR(KAT_KEY_NOTVALID_ERROR), + VERSAL_ECC_ERROR(KAT_FAILED_ERROR), + VERSAL_ECC_ERROR(NON_SUPPORTED_CURVE), + VERSAL_ECC_ERROR(KEY_ZERO), + VERSAL_ECC_ERROR(KEY_WRONG_ORDER), + VERSAL_ECC_ERROR(KEY_NOT_ON_CURVE), + VERSAL_ECC_ERROR(BAD_SIGN), + VERSAL_ECC_ERROR(GEN_SIGN_INCORRECT_HASH_LEN), + VERSAL_ECC_ERROR(VER_SIGN_INCORRECT_HASH_LEN), + VERSAL_ECC_ERROR(GEN_SIGN_BAD_RAND_NUM), + VERSAL_ECC_ERROR(GEN_KEY_ERR), + VERSAL_ECC_ERROR(INVALID_PARAM), + VERSAL_ECC_ERROR(VER_SIGN_R_ZERO), + VERSAL_ECC_ERROR(VER_SIGN_S_ZERO), + VERSAL_ECC_ERROR(VER_SIGN_R_ORDER_ERROR), + VERSAL_ECC_ERROR(VER_SIGN_S_ORDER_ERROR), + VERSAL_ECC_ERROR(KAT_INVLD_CRV_ERROR), + }; + + if (err <= KAT_INVLD_CRV_ERROR && err >= KAT_KEY_NOTVALID_ERROR) { + if (elist[err - KAT_KEY_NOTVALID_ERROR].name) + return elist[err - KAT_KEY_NOTVALID_ERROR].name; + + return "Invalid"; + } + + return "Unknown"; +} + +static TEE_Result ecc_get_key_size(uint32_t curve, size_t *bytes, size_t *bits) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P384: + *bits = 384; + *bytes = 48; + break; + case TEE_ECC_CURVE_NIST_P521: + *bits = 521; + *bytes = 66; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +static void memcpy_swp(uint8_t *to, const uint8_t *from, size_t len) +{ + size_t i = 0; + + for (i = 0; i < len; i++) + to[i] = from[len - 1 - i]; +} + +static void crypto_bignum_bn2bin_eswap(uint32_t curve, + struct bignum *from, uint8_t *to) +{ + uint8_t pad[66] = { 0 }; + size_t len = crypto_bignum_num_bytes(from); + size_t bytes = 0; + size_t bits = 0; + + if (ecc_get_key_size(curve, &bytes, &bits)) + panic(); + + crypto_bignum_bn2bin(from, pad + bytes - len); + memcpy_swp(to, pad, bytes); +} + +static TEE_Result ecc_prepare_msg(uint32_t algo, const uint8_t *msg, + size_t msg_len, struct versal_mbox_mem *p) +{ + uint8_t swp[TEE_SHA512_HASH_SIZE + 2] = { 0 }; + size_t len = 0; + + if (msg_len > TEE_SHA512_HASH_SIZE + 2) + return TEE_ERROR_BAD_PARAMETERS; + + if (algo == TEE_ALG_ECDSA_SHA384) + len = TEE_SHA384_HASH_SIZE; + else if (algo == TEE_ALG_ECDSA_SHA512) + len = TEE_SHA512_HASH_SIZE + 2; + else + return TEE_ERROR_NOT_SUPPORTED; + + /* Swap the hash/message and pad if necessary */ + memcpy_swp(swp, msg, msg_len); + return versal_mbox_alloc(len, swp, p); +} + +static TEE_Result verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result ret = TEE_SUCCESS; + struct versal_ecc_verify_param *cmd = NULL; + struct versal_cmd_args arg = { }; + struct versal_mbox_mem x = { }; + struct versal_mbox_mem s = { }; + struct versal_mbox_mem p = { }; + struct versal_mbox_mem cmd_buf = { }; + uint32_t err = 0; + size_t bytes = 0; + size_t bits = 0; + + if (sig_len % 2) + return TEE_ERROR_SIGNATURE_INVALID; + + ret = ecc_get_key_size(key->curve, &bytes, &bits); + if (ret != TEE_SUCCESS) { + if (ret != TEE_ERROR_NOT_SUPPORTED) + return ret; + + /* Fallback to software */ + return pub_ops->verify(algo, key, msg, msg_len, sig, sig_len); + } + + ret = ecc_prepare_msg(algo, msg, msg_len, &p); + if (ret) + return ret; + + versal_mbox_alloc(bytes * 2, NULL, &x); + crypto_bignum_bn2bin_eswap(key->curve, key->x, x.buf); + crypto_bignum_bn2bin_eswap(key->curve, key->y, + (uint8_t *)x.buf + bytes); + /* Validate the public key for the curve */ + arg.data[0] = key->curve; + arg.dlen = 1; + arg.ibuf[0].mem = x; + if (versal_crypto_request(VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY, + &arg, &err)) { + EMSG("Versal ECC: %s", versal_ecc_error(err)); + ret = TEE_ERROR_GENERIC; + goto out; + } + memset(&arg, 0, sizeof(arg)); + + versal_mbox_alloc(sig_len, NULL, &s); + /* Swap the {R,S} components */ + memcpy_swp(s.buf, sig, sig_len / 2); + memcpy_swp((uint8_t *)s.buf + sig_len / 2, sig + sig_len / 2, + sig_len / 2); + versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + + cmd = cmd_buf.buf; + cmd->signature_addr = virt_to_phys(s.buf); + cmd->pub_key_addr = virt_to_phys(x.buf); + cmd->hash_addr = virt_to_phys(p.buf); + cmd->hash_len = p.len; + cmd->curve = key->curve; + + arg.ibuf[0].mem = cmd_buf; + arg.ibuf[1].mem = p; + arg.ibuf[1].only_cache = true; + arg.ibuf[2].mem = x; + arg.ibuf[3].mem = s; + + if (versal_crypto_request(VERSAL_ELLIPTIC_VERIFY_SIGN, &arg, &err)) { + EMSG("Versal ECC: %s", versal_ecc_error(err)); + ret = TEE_ERROR_GENERIC; + } +out: + free(p.buf); + free(x.buf); + free(s.buf); + free(cmd); + + return ret; +} + +static TEE_Result sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + struct versal_ecc_sign_param *cmd = NULL; + struct versal_mbox_mem cmd_buf = { }; + struct ecc_keypair ephemeral = { }; + struct versal_cmd_args arg = { }; + struct versal_mbox_mem p = { }; + struct versal_mbox_mem k = { }; + struct versal_mbox_mem d = { }; + struct versal_mbox_mem s = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + size_t bytes = 0; + size_t bits = 0; + + ret = ecc_get_key_size(key->curve, &bytes, &bits); + if (ret != TEE_SUCCESS) { + if (ret != TEE_ERROR_NOT_SUPPORTED) + return ret; + + /* Fallback to software */ + return pair_ops->sign(algo, key, msg, msg_len, sig, sig_len); + } + + /* Hash and update the length */ + ret = ecc_prepare_msg(algo, msg, msg_len, &p); + if (ret) + return ret; + + /* Ephemeral private key */ + ret = drvcrypt_asym_alloc_ecc_keypair(&ephemeral, + TEE_TYPE_ECDSA_KEYPAIR, bits); + if (ret) { + EMSG("Versal, can't allocate the ephemeral key"); + return ret; + } + + ephemeral.curve = key->curve; + ret = crypto_acipher_gen_ecc_key(&ephemeral, bits); + if (ret) { + EMSG("Versal, can't generate the ephemeral key"); + return ret; + } + + versal_mbox_alloc(bytes, NULL, &k); + crypto_bignum_bn2bin_eswap(key->curve, ephemeral.d, k.buf); + crypto_bignum_free(ephemeral.d); + crypto_bignum_free(ephemeral.x); + crypto_bignum_free(ephemeral.y); + + /* Private key*/ + versal_mbox_alloc(bytes, NULL, &d); + crypto_bignum_bn2bin_eswap(key->curve, key->d, d.buf); + + /* Signature */ + versal_mbox_alloc(*sig_len, NULL, &s); + + /* IPI command */ + versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + + cmd = cmd_buf.buf; + cmd->priv_key_addr = virt_to_phys(d.buf); + cmd->epriv_key_addr = virt_to_phys(k.buf); + cmd->hash_addr = virt_to_phys(p.buf); + cmd->hash_len = p.len; + cmd->curve = key->curve; + + arg.ibuf[0].mem = cmd_buf; + arg.ibuf[1].mem = s; + arg.ibuf[2].mem = k; + arg.ibuf[3].mem = d; + arg.ibuf[4].mem = p; + + if (versal_crypto_request(VERSAL_ELLIPTIC_GENERATE_SIGN, &arg, &err)) { + EMSG("Versal ECC: %s", versal_ecc_error(err)); + ret = TEE_ERROR_GENERIC; + goto out; + } + + *sig_len = 2 * bytes; + + /* Swap the {R,S} components */ + memcpy_swp(sig, s.buf, *sig_len / 2); + memcpy_swp(sig + *sig_len / 2, (uint8_t *)s.buf + *sig_len / 2, + *sig_len / 2); +out: + free(cmd); + free(k.buf); + free(p.buf); + free(s.buf); + free(d.buf); + + return ret; +} + +static TEE_Result shared_secret(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, size_t *secret_len) +{ + return pair_ops->shared_secret(private_key, public_key, + secret, secret_len); +} + +static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) +{ + return shared_secret(sdata->key_priv, + sdata->key_pub, + sdata->secret.data, + &sdata->secret.length); +} + +static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) +{ + return sign(sdata->algo, + sdata->key, + sdata->message.data, + sdata->message.length, + sdata->signature.data, + &sdata->signature.length); +} + +static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) +{ + return verify(sdata->algo, + sdata->key, + sdata->message.data, + sdata->message.length, + sdata->signature.data, + sdata->signature.length); +} + +static TEE_Result do_gen_keypair(struct ecc_keypair *s, size_t size_bits) +{ + /* + * Versal requires little endian so need to memcpy_swp on Versal IP ops. + * We chose not to do it here because some tests might be using + * their own keys + */ + return pair_ops->generate(s, size_bits); +} + +static TEE_Result do_alloc_keypair(struct ecc_keypair *s, + uint32_t type, size_t size_bits) +{ + TEE_Result ret = TEE_SUCCESS; + + /* This driver only supports ECDH/ECDSA */ + if (type != TEE_TYPE_ECDSA_KEYPAIR && + type != TEE_TYPE_ECDH_KEYPAIR) + return TEE_ERROR_NOT_IMPLEMENTED; + + ret = crypto_asym_alloc_ecc_keypair(s, TEE_TYPE_ECDSA_KEYPAIR, + size_bits); + if (ret) + return TEE_ERROR_NOT_IMPLEMENTED; + + /* + * Ignore the software operations, the crypto API will populate + * this interface. + */ + s->ops = NULL; + + return TEE_SUCCESS; +} + +static TEE_Result do_alloc_publickey(struct ecc_public_key *s, + uint32_t type, size_t size_bits) +{ + TEE_Result ret = TEE_SUCCESS; + + /* This driver only supports ECDH/ECDSA */ + if (type != TEE_TYPE_ECDSA_PUBLIC_KEY && + type != TEE_TYPE_ECDH_PUBLIC_KEY) + return TEE_ERROR_NOT_IMPLEMENTED; + + ret = crypto_asym_alloc_ecc_public_key(s, TEE_TYPE_ECDSA_PUBLIC_KEY, + size_bits); + if (ret) + return TEE_ERROR_NOT_IMPLEMENTED; + + /* + * Ignore the software operations, the crypto API will populate + * this interface. + */ + s->ops = NULL; + + return TEE_SUCCESS; +} + +static void do_free_publickey(struct ecc_public_key *s) +{ + return pub_ops->free(s); +} + +static struct drvcrypt_ecc driver_ecc = { + .shared_secret = do_shared_secret, + .alloc_publickey = do_alloc_publickey, + .free_publickey = do_free_publickey, + .alloc_keypair = do_alloc_keypair, + .gen_keypair = do_gen_keypair, + .verify = do_verify, + .sign = do_sign, +}; + +static TEE_Result ecc_init(void) +{ + struct versal_cmd_args arg = { }; + uint32_t err = 0; + + arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P384; + if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) { + EMSG("Versal KAG NIST_P384: %s", versal_ecc_error(err)); + return TEE_ERROR_GENERIC; + } + + /* Clean previous request */ + arg.dlen = 0; + + arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P521; + if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) { + EMSG("Versal KAG NIST_P521 %s", versal_ecc_error(err)); + return TEE_ERROR_GENERIC; + } + + pair_ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDSA_KEYPAIR); + if (!pair_ops) + return TEE_ERROR_GENERIC; + + pub_ops = crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDSA_PUBLIC_KEY); + if (!pub_ops) + return TEE_ERROR_GENERIC; + + /* This driver supports both ECDH and ECDSA */ + assert((pub_ops == + crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDH_PUBLIC_KEY)) && + (pair_ops == + crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR))); + + return drvcrypt_register_ecc(&driver_ecc); +} + +driver_init(ecc_init); diff --git a/optee/optee_os/core/drivers/crypto/versal/include/ipi.h b/optee/optee_os/core/drivers/crypto/versal/include/ipi.h new file mode 100644 index 0000000..2c92a1a --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/versal/include/ipi.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2022 + * Author: Jorge Ramirez + */ + +#ifndef IPI_H +#define IPI_H + +#include + +struct versal_rsa_input_param { + uint64_t key_addr; + uint64_t data_addr; + uint32_t key_len; +}; + +struct versal_rsa_sign_param { + uint64_t sign_addr; + uint64_t hash_addr; + uint32_t hash_len; +}; + +struct versal_ecc_sign_param { + uint64_t hash_addr; + uint64_t priv_key_addr; + uint64_t epriv_key_addr; + uint32_t curve; + uint32_t hash_len; +}; + +struct versal_ecc_verify_param { + uint64_t hash_addr; + uint64_t pub_key_addr; + uint64_t signature_addr; + uint32_t curve; + uint32_t hash_len; +}; + +enum versal_aes_operation { VERSAL_AES_ENCRYPT, VERSAL_AES_DECRYPT }; + +struct versal_aes_init { + uint64_t iv_addr; + uint32_t operation; + uint32_t key_src; + uint32_t key_len; +}; + +struct versal_aes_input_param { + uint64_t input_addr; + uint32_t input_len; + uint32_t is_last; +}; + +enum versal_crypto_api { + VERSAL_FEATURES = 0U, + VERSAL_RSA_SIGN_VERIFY, + VERSAL_RSA_PUBLIC_ENCRYPT, + VERSAL_RSA_PRIVATE_DECRYPT, + VERSAL_RSA_KAT, + VERSAL_SHA3_UPDATE = 32U, + VERSAL_SHA3_KAT, + VERSAL_ELLIPTIC_GENERATE_PUBLIC_KEY = 64U, + VERSAL_ELLIPTIC_GENERATE_SIGN, + VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY, + VERSAL_ELLIPTIC_VERIFY_SIGN, + VERSAL_ELLIPTIC_KAT, + VERSAL_AES_INIT = 96U, + VERSAL_AES_OP_INIT, + VERSAL_AES_UPDATE_AAD, + VERSAL_AES_ENCRYPT_UPDATE, + VERSAL_AES_ENCRYPT_FINAL, + VERSAL_AES_DECRYPT_UPDATE, + VERSAL_AES_DECRYPT_FINAL, + VERSAL_AES_KEY_ZERO, + VERSAL_AES_WRITE_KEY, + VERSAL_AES_LOCK_USER_KEY, + VERSAL_AES_KEK_DECRYPT, + VERSAL_AES_SET_DPA_CM, + VERSAL_AES_DECRYPT_KAT, + VERSAL_AES_DECRYPT_CM_KAT, + VERSAL_CRYPTO_API_MAX +}; + +#define VERSAL_MAX_IPI_REGS 6 + +struct versal_cmd_args { + uint32_t data[VERSAL_MAX_IPI_REGS]; + size_t dlen; + struct versal_ipi_buf ibuf[VERSAL_MAX_IPI_BUF]; +}; + +TEE_Result versal_crypto_request(enum versal_crypto_api id, + struct versal_cmd_args *arg, uint32_t *err); +#endif + diff --git a/optee/optee_os/core/drivers/crypto/versal/ipi.c b/optee/optee_os/core/drivers/crypto/versal/ipi.c new file mode 100644 index 0000000..ba2b636 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/versal/ipi.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022 + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEC_MODULE_SHIFT 8 +#define SEC_MODULE_ID 5 + +#define CRYPTO_API_ID(__x) ((SEC_MODULE_ID << SEC_MODULE_SHIFT) | (__x)) + +static TEE_Result versal_sha3_request(enum versal_crypto_api id, + struct versal_cmd_args *arg) +{ + struct versal_ipi_cmd cmd = { }; + uint32_t a = 0; + uint32_t b = 0; + + cmd.data[0] = CRYPTO_API_ID(id); + + if (arg->data[0]) { + /* write */ + reg_pair_from_64(virt_to_phys(arg->ibuf[0].mem.buf), &b, &a); + cmd.data[1] = a; + cmd.data[2] = b; + cmd.data[3] = arg->data[0]; + + cmd.ibuf[0].mem = arg->ibuf[0].mem; + } else { + /* read */ + reg_pair_from_64(virt_to_phys(arg->ibuf[0].mem.buf), &b, &a); + cmd.data[4] = a; + cmd.data[5] = b; + + cmd.ibuf[0].mem = arg->ibuf[0].mem; + } + + return versal_mbox_notify(&cmd, NULL, NULL); +} + +static TEE_Result versal_aes_update_aad_request(enum versal_crypto_api id, + struct versal_cmd_args *arg) +{ + struct versal_ipi_cmd cmd = { }; + uint32_t a = 0; + uint32_t b = 0; + + reg_pair_from_64(virt_to_phys(arg->ibuf[0].mem.buf), &b, &a); + + cmd.data[0] = CRYPTO_API_ID(id); + cmd.data[1] = a; + cmd.data[2] = b; + cmd.data[3] = arg->data[0]; + + cmd.ibuf[0].mem = arg->ibuf[0].mem; + + return versal_mbox_notify(&cmd, NULL, NULL); +} + +TEE_Result versal_crypto_request(enum versal_crypto_api id, + struct versal_cmd_args *arg, uint32_t *err) +{ + struct versal_ipi_cmd cmd = { }; + uint32_t a = 0; + uint32_t b = 0; + size_t i = 0; + + if (id == VERSAL_SHA3_UPDATE) + return versal_sha3_request(id, arg); + + if (id == VERSAL_AES_UPDATE_AAD) + return versal_aes_update_aad_request(id, arg); + + cmd.data[0] = CRYPTO_API_ID(id); + for (i = 1; i < arg->dlen + 1; i++) + cmd.data[i] = arg->data[i - 1]; + + /* src */ + if (!arg->ibuf[0].mem.buf) + goto notify; + + reg_pair_from_64(virt_to_phys(arg->ibuf[0].mem.buf), &b, &a); + cmd.data[i++] = a; + cmd.data[i++] = b; + + /* dst */ + if (!arg->ibuf[1].mem.buf) + goto cache; + + if (arg->ibuf[1].only_cache) + goto cache; + + reg_pair_from_64(virt_to_phys(arg->ibuf[1].mem.buf), &b, &a); + cmd.data[i++] = a; + cmd.data[i++] = b; +cache: + for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) + cmd.ibuf[i].mem = arg->ibuf[i].mem; +notify: + return versal_mbox_notify(&cmd, NULL, err); +} diff --git a/optee/optee_os/core/drivers/crypto/versal/rsa.c b/optee/optee_os/core/drivers/crypto/versal/rsa.c new file mode 100644 index 0000000..bbfe979 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/versal/rsa.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022. + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RSA_MAX_PRIV_EXP_LEN 512 +#define RSA_MAX_PUB_EXP_LEN 4 +#define RSA_MAX_MOD_LEN 512 + +static void crypto_bignum_bn2bin_pad(size_t size, + struct bignum *from, uint8_t *to) +{ + size_t len = crypto_bignum_num_bytes(from); + + crypto_bignum_bn2bin(from, to + size - len); +} + +static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data) +{ + struct rsa_public_key *p = rsa_data->key.key; + struct versal_rsa_input_param *cmd = NULL; + struct versal_mbox_mem cmd_buf = { }; + struct versal_mbox_mem cipher = { }; + struct versal_mbox_mem key = { }; + struct versal_mbox_mem msg = { }; + struct versal_cmd_args arg = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + + switch (rsa_data->rsa_id) { + case DRVCRYPT_RSA_PKCS_V1_5: + return sw_crypto_acipher_rsaes_encrypt(rsa_data->algo, + rsa_data->key.key, + rsa_data->label.data, + rsa_data->label.length, + rsa_data->message.data, + rsa_data->message.length, + rsa_data->cipher.data, + &rsa_data->cipher.length); + case DRVCRYPT_RSA_OAEP: + return sw_crypto_acipher_rsaes_encrypt(rsa_data->algo, + rsa_data->key.key, + rsa_data->label.data, + rsa_data->label.length, + rsa_data->message.data, + rsa_data->message.length, + rsa_data->cipher.data, + &rsa_data->cipher.length); + case DRVCRYPT_RSA_NOPAD: + return sw_crypto_acipher_rsanopad_encrypt(rsa_data->key.key, + rsa_data->message.data, + rsa_data->message.length, + rsa_data->cipher.data, + &rsa_data->cipher.length); + case DRVCRYPT_RSASSA_PKCS_V1_5: + assert(rsa_data->hash_algo != TEE_ALG_SHA1); + assert(rsa_data->key.n_size != 128); + break; + case DRVCRYPT_RSASSA_PSS: + default: + assert(0); + } + + versal_mbox_alloc(RSA_MAX_MOD_LEN + RSA_MAX_PUB_EXP_LEN, NULL, &key); + crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->n, key.buf); + crypto_bignum_bn2bin_pad(RSA_MAX_PUB_EXP_LEN, + p->e, (uint8_t *)key.buf + RSA_MAX_MOD_LEN); + + versal_mbox_alloc(rsa_data->message.length, rsa_data->message.data, + &msg); + versal_mbox_alloc(rsa_data->cipher.length, NULL, &cipher); + versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + + cmd = cmd_buf.buf; + cmd->key_len = rsa_data->key.n_size; + cmd->data_addr = virt_to_phys(msg.buf); + cmd->key_addr = virt_to_phys(key.buf); + + arg.ibuf[0].mem = cmd_buf; + arg.ibuf[1].mem = cipher; + arg.ibuf[2].mem = msg; + arg.ibuf[3].mem = key; + + if (versal_crypto_request(VERSAL_RSA_PUBLIC_ENCRYPT, &arg, &err)) { + EMSG("Versal RSA: encrypt: error 0x%x [id:0x%x, len:%zu]", + err, rsa_data->rsa_id, rsa_data->key.n_size); + + if (rsa_data->rsa_id == DRVCRYPT_RSASSA_PKCS_V1_5) + ret = TEE_ERROR_SIGNATURE_INVALID; + else + ret = TEE_ERROR_GENERIC; + } + + if (!ret) { + rsa_data->cipher.length = rsa_data->key.n_size; + memcpy(rsa_data->cipher.data, cipher.buf, rsa_data->key.n_size); + } + + free(cipher.buf); + free(cmd); + free(msg.buf); + free(key.buf); + + return ret; +} + +static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data) +{ + struct versal_rsa_input_param *cmd = NULL; + struct rsa_keypair *p = rsa_data->key.key; + struct versal_mbox_mem cmd_buf = { }; + struct versal_mbox_mem cipher = { }; + struct versal_mbox_mem key = { }; + struct versal_mbox_mem msg = { }; + struct versal_cmd_args arg = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + + switch (rsa_data->rsa_id) { + case DRVCRYPT_RSA_PKCS_V1_5: + return sw_crypto_acipher_rsaes_decrypt(rsa_data->algo, + rsa_data->key.key, + rsa_data->label.data, + rsa_data->label.length, + rsa_data->cipher.data, + rsa_data->cipher.length, + rsa_data->message.data, + &rsa_data->message.length); + case DRVCRYPT_RSA_OAEP: + return sw_crypto_acipher_rsaes_decrypt(rsa_data->algo, + rsa_data->key.key, + rsa_data->label.data, + rsa_data->label.length, + rsa_data->cipher.data, + rsa_data->cipher.length, + rsa_data->message.data, + &rsa_data->message.length); + case DRVCRYPT_RSA_NOPAD: + return sw_crypto_acipher_rsanopad_decrypt(rsa_data->key.key, + rsa_data->cipher.data, + rsa_data->cipher.length, + rsa_data->message.data, + &rsa_data->message.length); + case DRVCRYPT_RSASSA_PKCS_V1_5: + assert(rsa_data->hash_algo != TEE_ALG_SHA1); + assert(rsa_data->key.n_size != 128); + break; + case DRVCRYPT_RSASSA_PSS: + default: + assert(0); + } + + versal_mbox_alloc(RSA_MAX_MOD_LEN + RSA_MAX_PRIV_EXP_LEN, NULL, &key); + crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->n, key.buf); + crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->d, + (uint8_t *)key.buf + RSA_MAX_MOD_LEN); + + versal_mbox_alloc(rsa_data->cipher.length, rsa_data->cipher.data, + &cipher); + versal_mbox_alloc(rsa_data->message.length, NULL, &msg); + versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); + + cmd = cmd_buf.buf; + cmd->key_len = rsa_data->key.n_size; + cmd->data_addr = virt_to_phys(cipher.buf); + cmd->key_addr = virt_to_phys(key.buf); + + arg.ibuf[0].mem = cmd_buf; + arg.ibuf[1].mem = msg; + arg.ibuf[2].mem = cipher; + arg.ibuf[3].mem = key; + + if (versal_crypto_request(VERSAL_RSA_PRIVATE_DECRYPT, &arg, &err)) { + EMSG("Versal RSA: decrypt: error 0x%x [id:0x%x, len:%zu]", + err, rsa_data->rsa_id, rsa_data->key.n_size); + ret = TEE_ERROR_GENERIC; + } + + if (!ret) { + rsa_data->message.length = rsa_data->key.n_size; + memcpy(rsa_data->message.data, msg.buf, rsa_data->key.n_size); + } + + free(cipher.buf); + free(cmd); + free(key.buf); + free(msg.buf); + + return ret; +} + +static TEE_Result do_ssa_sign(struct drvcrypt_rsa_ssa *p) +{ + switch (p->algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5: + 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: + if (p->key.n_size != 128) { + /* use DRVCRYPT_RSASSA_PKCS_V1_5, decrypt */ + return TEE_ERROR_NOT_IMPLEMENTED; + } + return sw_crypto_acipher_rsassa_sign(p->algo, + p->key.key, + p->salt_len, + p->message.data, + p->message.length, + p->signature.data, + &p->signature.length); + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + return sw_crypto_acipher_rsassa_sign(p->algo, + p->key.key, + p->salt_len, + p->message.data, + p->message.length, + p->signature.data, + &p->signature.length); + 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: + return sw_crypto_acipher_rsassa_sign(p->algo, + p->key.key, + p->salt_len, + p->message.data, + p->message.length, + p->signature.data, + &p->signature.length); + default: + break; + } + + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result do_ssa_verify(struct drvcrypt_rsa_ssa *p) +{ + switch (p->algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5: + 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: + if (p->key.n_size != 128) { + /* use DRVCRYPT_RSASSA_PKCS_V1_5, encrypt */ + return TEE_ERROR_NOT_IMPLEMENTED; + } + return sw_crypto_acipher_rsassa_verify(p->algo, + p->key.key, + p->salt_len, + p->message.data, + p->message.length, + p->signature.data, + p->signature.length); + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + return sw_crypto_acipher_rsassa_verify(p->algo, + p->key.key, + p->salt_len, + p->message.data, + p->message.length, + p->signature.data, + p->signature.length); + 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: + return sw_crypto_acipher_rsassa_verify(p->algo, + p->key.key, + p->salt_len, + p->message.data, + p->message.length, + p->signature.data, + p->signature.length); + default: + break; + } + + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result do_gen_keypair(struct rsa_keypair *s, size_t size_bits) +{ + return sw_crypto_acipher_gen_rsa_key(s, size_bits); +} + +static TEE_Result do_alloc_keypair(struct rsa_keypair *s, size_t size_bits) +{ + return sw_crypto_acipher_alloc_rsa_keypair(s, size_bits); +} + +static TEE_Result do_alloc_publickey(struct rsa_public_key *key, size_t bits) +{ + return sw_crypto_acipher_alloc_rsa_public_key(key, bits); +} + +static void do_free_publickey(struct rsa_public_key *s) +{ + sw_crypto_acipher_free_rsa_public_key(s); +} + +static void do_free_keypair(struct rsa_keypair *s) +{ + sw_crypto_acipher_free_rsa_keypair(s); +} + +static struct drvcrypt_rsa driver_rsa = { + .alloc_publickey = do_alloc_publickey, + .free_publickey = do_free_publickey, + .alloc_keypair = do_alloc_keypair, + .optional.ssa_verify = do_ssa_verify, + .optional.ssa_sign = do_ssa_sign, + .free_keypair = do_free_keypair, + .gen_keypair = do_gen_keypair, + .encrypt = do_encrypt, + .decrypt = do_decrypt, +}; + +static TEE_Result rsa_init(void) +{ + struct versal_cmd_args arg = { }; + + if (versal_crypto_request(VERSAL_RSA_KAT, &arg, NULL)) + return TEE_ERROR_GENERIC; + + return drvcrypt_register_rsa(&driver_rsa); +} + +driver_init(rsa_init); diff --git a/optee/optee_os/core/drivers/crypto/versal/sub.mk b/optee/optee_os/core/drivers/crypto/versal/sub.mk new file mode 100644 index 0000000..5618469 --- /dev/null +++ b/optee/optee_os/core/drivers/crypto/versal/sub.mk @@ -0,0 +1,6 @@ +incdirs-y += include + +srcs-y += ipi.c +srcs-y += authenc.c +srcs-y += ecc.c +srcs-y += rsa.c diff --git a/optee/optee_os/core/drivers/dra7_rng.c b/optee/optee_os/core/drivers/dra7_rng.c new file mode 100644 index 0000000..c3af335 --- /dev/null +++ b/optee/optee_os/core/drivers/dra7_rng.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RNG_OUTPUT_L 0x0000 +#define RNG_OUTPUT_H 0x0004 +#define RNG_STATUS 0x0008 +# define RNG_READY BIT(0) +# define SHUTDOWN_OFLO BIT(1) +#define RNG_INTMASK 0x000C +#define RNG_INTACK 0x0010 +#define RNG_CONTROL 0x0014 +# define ENABLE_TRNG BIT(10) +#define RNG_CONFIG 0x0018 +#define RNG_ALARMCNT 0x001C +#define RNG_FROENABLE 0x0020 +#define RNG_FRODETUNE 0x0024 +#define RNG_ALARMMASK 0x0028 +#define RNG_ALARMSTOP 0x002C +#define RNG_LFSR_L 0x0030 +#define RNG_LFSR_M 0x0034 +#define RNG_LFSR_H 0x0038 +#define RNG_COUNT 0x003C +#define RNG_OPTIONS 0x0078 +#define RNG_EIP_REV 0x007C +#define RNG_MMR_STATUS_EN 0x1FD8 +#define RNG_REV 0x1FE0 +#define RNG_SYS_CONFIG_REG 0x1FE4 +# define RNG_AUTOIDLE BIT(0) +#define RNG_MMR_STATUS_SET 0x1FEC +#define RNG_SOFT_RESET_REG 0x1FF0 +# define RNG_SOFT_RESET BIT(0) +#define RNG_IRQ_EOI_REG 0x1FF4 +#define RNG_IRQSTATUS 0x1FF8 + +#define RNG_CONTROL_STARTUP_CYCLES_SHIFT 16 +#define RNG_CONTROL_STARTUP_CYCLES_MASK GENMASK_32(31, 16) + +#define RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT 16 +#define RNG_CONFIG_MAX_REFIL_CYCLES_MASK GENMASK_32(31, 16) +#define RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT 0 +#define RNG_CONFIG_MIN_REFIL_CYCLES_MASK GENMASK_32(7, 0) + +#define RNG_ALARMCNT_ALARM_TH_SHIFT 0 +#define RNG_ALARMCNT_ALARM_TH_MASK GENMASK_32(7, 0) +#define RNG_ALARMCNT_SHUTDOWN_TH_SHIFT 16 +#define RNG_ALARMCNT_SHUTDOWN_TH_MASK GENMASK_32(20, 16) + +#define RNG_CONTROL_STARTUP_CYCLES 0xff +#define RNG_CONFIG_MIN_REFIL_CYCLES 0x21 +#define RNG_CONFIG_MAX_REFIL_CYCLES 0x22 +#define RNG_ALARM_THRESHOLD 0xff +#define RNG_SHUTDOWN_THRESHOLD 0x4 + +#define RNG_FRO_MASK GENMASK_32(23, 0) + +#define RNG_REG_SIZE 0x2000 + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); + +static unsigned int rng_lock = SPINLOCK_UNLOCK; +static vaddr_t rng; + +static void dra7_rng_read64(uint32_t *low_word, uint32_t *high_word) +{ + /* Is the result ready (available)? */ + while (!(io_read32(rng + RNG_STATUS) & RNG_READY)) { + /* Is the shutdown threshold reached? */ + if (io_read32(rng + RNG_STATUS) & SHUTDOWN_OFLO) { + uint32_t alarm = io_read32(rng + RNG_ALARMSTOP); + uint32_t tune = io_read32(rng + RNG_FRODETUNE); + + /* Clear the alarm events */ + io_write32(rng + RNG_ALARMMASK, 0x0); + io_write32(rng + RNG_ALARMSTOP, 0x0); + /* De-tune offending FROs */ + io_write32(rng + RNG_FRODETUNE, tune ^ alarm); + /* Re-enable the shut down FROs */ + io_write32(rng + RNG_FROENABLE, RNG_FRO_MASK); + /* Clear the shutdown overflow event */ + io_write32(rng + RNG_INTACK, SHUTDOWN_OFLO); + + DMSG("Fixed FRO shutdown\n"); + } + } + /* Read random value */ + *low_word = io_read32(rng + RNG_OUTPUT_L); + *high_word = io_read32(rng + RNG_OUTPUT_H); + /* Acknowledge read complete */ + io_write32(rng + RNG_INTACK, RNG_READY); +} + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + static union { + uint32_t val[2]; + uint8_t byte[8]; + } fifo; + static size_t fifo_pos; + uint8_t *buffer = buf; + size_t buffer_pos = 0; + + while (buffer_pos < len) { + uint32_t exceptions = cpu_spin_lock_xsave(&rng_lock); + + /* Refill our FIFO */ + if (fifo_pos == 0) + dra7_rng_read64(&fifo.val[0], &fifo.val[1]); + + buffer[buffer_pos++] = fifo.byte[fifo_pos++]; + fifo_pos %= 8; + + cpu_spin_unlock_xrestore(&rng_lock, exceptions); + } + + return TEE_SUCCESS; +} + +static TEE_Result dra7_rng_init(void) +{ + uint32_t val; + + rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE); + + /* Execute a software reset */ + io_write32(rng + RNG_SOFT_RESET_REG, RNG_SOFT_RESET); + + /* Wait for the software reset completion by polling */ + while (io_read32(rng + RNG_SOFT_RESET_REG) & RNG_SOFT_RESET) + ; + + /* Switch to low-power operating mode */ + io_write32(rng + RNG_SYS_CONFIG_REG, RNG_AUTOIDLE); + + /* + * Select the number of clock input cycles to the + * FROs between two samples + */ + val = 0; + + /* Ensure initial latency */ + val |= RNG_CONFIG_MIN_REFIL_CYCLES << + RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; + val |= RNG_CONFIG_MAX_REFIL_CYCLES << + RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT; + io_write32(rng + RNG_CONFIG, val); + + /* Configure the desired FROs */ + io_write32(rng + RNG_FRODETUNE, 0x0); + + /* Enable all FROs */ + io_write32(rng + RNG_FROENABLE, 0xffffff); + + /* + * Select the maximum number of samples after + * which if a repeating pattern is still detected, an + * alarm event is generated + */ + val = RNG_ALARM_THRESHOLD << RNG_ALARMCNT_ALARM_TH_SHIFT; + + /* + * Set the shutdown threshold to the number of FROs + * allowed to be shut downed + */ + val |= RNG_SHUTDOWN_THRESHOLD << RNG_ALARMCNT_SHUTDOWN_TH_SHIFT; + io_write32(rng + RNG_ALARMCNT, val); + + /* Enable the RNG module */ + val = RNG_CONTROL_STARTUP_CYCLES << RNG_CONTROL_STARTUP_CYCLES_SHIFT; + val |= ENABLE_TRNG; + io_write32(rng + RNG_CONTROL, val); + + IMSG("DRA7x TRNG initialized"); + + return TEE_SUCCESS; +} +driver_init(dra7_rng_init); diff --git a/optee/optee_os/core/drivers/gic.c b/optee/optee_os/core/drivers/gic.c new file mode 100644 index 0000000..d836d6f --- /dev/null +++ b/optee/optee_os/core/drivers/gic.c @@ -0,0 +1,524 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2017, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Offsets from gic.gicc_base */ +#define GICC_CTLR (0x000) +#define GICC_PMR (0x004) +#define GICC_IAR (0x00C) +#define GICC_EOIR (0x010) + +#define GICC_CTLR_ENABLEGRP0 (1 << 0) +#define GICC_CTLR_ENABLEGRP1 (1 << 1) +#define GICD_CTLR_ENABLEGRP1S (1 << 2) +#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_ISPENDR(n) (0x200 + (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_IGROUPMODR(n) (0xd00 + (n) * 4) +#define GICD_SGIR (0xF00) + +#define GICD_CTLR_ENABLEGRP0 (1 << 0) +#define GICD_CTLR_ENABLEGRP1 (1 << 1) + +/* Number of Private Peripheral Interrupt */ +#define NUM_PPI 32 + +/* Number of Software Generated Interrupt */ +#define NUM_SGI 16 + +/* Number of Non-secure Software Generated Interrupt */ +#define NUM_NS_SGI 8 + +/* Number of interrupts in one register */ +#define NUM_INTS_PER_REG 32 + +/* Number of targets in one register */ +#define NUM_TARGETS_PER_REG 4 + +/* Accessors to access ITARGETSRn */ +#define ITARGETSR_FIELD_BITS 8 +#define ITARGETSR_FIELD_MASK 0xff + +/* Maximum number of interrups a GIC can support */ +#define GIC_MAX_INTS 1020 + +#define GICC_IAR_IT_ID_MASK 0x3ff +#define GICC_IAR_CPU_ID_MASK 0x7 +#define GICC_IAR_CPU_ID_SHIFT 10 + +static void gic_op_add(struct itr_chip *chip, size_t it, uint32_t type, + uint32_t prio); +static void gic_op_enable(struct itr_chip *chip, size_t it); +static void gic_op_disable(struct itr_chip *chip, size_t it); +static void gic_op_raise_pi(struct itr_chip *chip, size_t it); +static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, + uint8_t cpu_mask); +static void gic_op_set_affinity(struct itr_chip *chip, size_t it, + uint8_t cpu_mask); + +static const struct itr_ops gic_ops = { + .add = gic_op_add, + .enable = gic_op_enable, + .disable = gic_op_disable, + .raise_pi = gic_op_raise_pi, + .raise_sgi = gic_op_raise_sgi, + .set_affinity = gic_op_set_affinity, +}; +DECLARE_KEEP_PAGER(gic_ops); + +static size_t probe_max_it(vaddr_t gicc_base __maybe_unused, vaddr_t gicd_base) +{ + int i; + uint32_t old_ctlr; + size_t ret = 0; + const size_t max_regs = ((GIC_MAX_INTS + NUM_INTS_PER_REG - 1) / + NUM_INTS_PER_REG) - 1; + + /* + * Probe which interrupt number is the largest. + */ +#if defined(CFG_ARM_GICV3) + old_ctlr = read_icc_ctlr(); + write_icc_ctlr(0); +#else + old_ctlr = io_read32(gicc_base + GICC_CTLR); + io_write32(gicc_base + GICC_CTLR, 0); +#endif + for (i = max_regs; i >= 0; i--) { + uint32_t old_reg; + uint32_t reg; + int b; + + old_reg = io_read32(gicd_base + GICD_ISENABLER(i)); + io_write32(gicd_base + GICD_ISENABLER(i), 0xffffffff); + reg = io_read32(gicd_base + GICD_ISENABLER(i)); + io_write32(gicd_base + GICD_ICENABLER(i), ~old_reg); + for (b = NUM_INTS_PER_REG - 1; b >= 0; b--) { + if (BIT32(b) & reg) { + ret = i * NUM_INTS_PER_REG + b; + goto out; + } + } + } +out: +#if defined(CFG_ARM_GICV3) + write_icc_ctlr(old_ctlr); +#else + io_write32(gicc_base + GICC_CTLR, old_ctlr); +#endif + return ret; +} + +void gic_cpu_init(struct gic_data *gd) +{ +#if defined(CFG_ARM_GICV3) + assert(gd->gicd_base); +#else + assert(gd->gicd_base && gd->gicc_base); +#endif + + /* per-CPU interrupts config: + * ID0-ID7(SGI) for Non-secure interrupts + * ID8-ID15(SGI) for Secure interrupts. + * All PPI config as Non-secure interrupts. + */ + io_write32(gd->gicd_base + GICD_IGROUPR(0), 0xffff00ff); + + /* Set the priority mask to permit Non-secure interrupts, and to + * allow the Non-secure world to adjust the priority mask itself + */ +#if defined(CFG_ARM_GICV3) + write_icc_pmr(0x80); + write_icc_igrpen1(1); +#else + io_write32(gd->gicc_base + GICC_PMR, 0x80); + + /* Enable GIC */ + io_write32(gd->gicc_base + GICC_CTLR, + GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | + GICC_CTLR_FIQEN); +#endif +} + +void gic_init(struct gic_data *gd, paddr_t gicc_base_pa, paddr_t gicd_base_pa) +{ + size_t n; + + gic_init_base_addr(gd, gicc_base_pa, gicd_base_pa); + + for (n = 0; n <= gd->max_it / NUM_INTS_PER_REG; n++) { + /* Disable interrupts */ + io_write32(gd->gicd_base + GICD_ICENABLER(n), 0xffffffff); + + /* Make interrupts non-pending */ + io_write32(gd->gicd_base + GICD_ICPENDR(n), 0xffffffff); + + /* Mark interrupts non-secure */ + if (n == 0) { + /* per-CPU inerrupts config: + * ID0-ID7(SGI) for Non-secure interrupts + * ID8-ID15(SGI) for Secure interrupts. + * All PPI config as Non-secure interrupts. + */ + io_write32(gd->gicd_base + GICD_IGROUPR(n), 0xffff00ff); + } else { + io_write32(gd->gicd_base + GICD_IGROUPR(n), 0xffffffff); + } + } + + /* Set the priority mask to permit Non-secure interrupts, and to + * allow the Non-secure world to adjust the priority mask itself + */ +#if defined(CFG_ARM_GICV3) + write_icc_pmr(0x80); + write_icc_igrpen1(1); + io_setbits32(gd->gicd_base + GICD_CTLR, GICD_CTLR_ENABLEGRP1S); +#else + io_write32(gd->gicc_base + GICC_PMR, 0x80); + + /* Enable GIC */ + io_write32(gd->gicc_base + GICC_CTLR, GICC_CTLR_FIQEN | + GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1); + io_setbits32(gd->gicd_base + GICD_CTLR, + GICD_CTLR_ENABLEGRP0 | GICD_CTLR_ENABLEGRP1); +#endif +} + +static int gic_dt_get_irq(const uint32_t *properties, int count, uint32_t *type, + uint32_t *prio) +{ + int it_num = DT_INFO_INVALID_INTERRUPT; + + if (type) + *type = IRQ_TYPE_NONE; + + if (prio) + *prio = 0; + + if (!properties || count < 2) + return DT_INFO_INVALID_INTERRUPT; + + it_num = fdt32_to_cpu(properties[1]); + + switch (fdt32_to_cpu(properties[0])) { + case 1: + it_num += 16; + break; + case 0: + it_num += 32; + break; + default: + it_num = DT_INFO_INVALID_INTERRUPT; + } + + return it_num; +} + +void gic_init_base_addr(struct gic_data *gd, + paddr_t gicc_base_pa __maybe_unused, + paddr_t gicd_base_pa) +{ + vaddr_t gicc_base = 0; + vaddr_t gicd_base = 0; + + assert(cpu_mmu_enabled()); + + gicd_base = core_mmu_get_va(gicd_base_pa, MEM_AREA_IO_SEC, + GIC_DIST_REG_SIZE); + if (!gicd_base) + panic(); + + if (!IS_ENABLED(CFG_ARM_GICV3)) { + gicc_base = core_mmu_get_va(gicc_base_pa, MEM_AREA_IO_SEC, + GIC_CPU_REG_SIZE); + if (!gicc_base) + panic(); + } + + gd->gicc_base = gicc_base; + gd->gicd_base = gicd_base; + gd->max_it = probe_max_it(gicc_base, gicd_base); + gd->chip.ops = &gic_ops; + + if (IS_ENABLED(CFG_DT)) + gd->chip.dt_get_irq = gic_dt_get_irq; +} + +static void gic_it_add(struct gic_data *gd, size_t it) +{ + size_t idx = it / NUM_INTS_PER_REG; + uint32_t mask = 1 << (it % NUM_INTS_PER_REG); + + /* Disable the interrupt */ + io_write32(gd->gicd_base + GICD_ICENABLER(idx), mask); + /* Make it non-pending */ + io_write32(gd->gicd_base + GICD_ICPENDR(idx), mask); + /* Assign it to group0 */ + io_clrbits32(gd->gicd_base + GICD_IGROUPR(idx), mask); +#if defined(CFG_ARM_GICV3) + /* Assign it to group1S */ + io_setbits32(gd->gicd_base + GICD_IGROUPMODR(idx), mask); +#endif +} + +static void gic_it_set_cpu_mask(struct gic_data *gd, size_t it, + uint8_t cpu_mask) +{ + size_t idx __maybe_unused = it / NUM_INTS_PER_REG; + uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG); + uint32_t target, target_shift; + vaddr_t itargetsr = gd->gicd_base + + GICD_ITARGETSR(it / NUM_TARGETS_PER_REG); + + /* Assigned to group0 */ + assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); + + /* Route it to selected CPUs */ + target = io_read32(itargetsr); + target_shift = (it % NUM_TARGETS_PER_REG) * ITARGETSR_FIELD_BITS; + target &= ~(ITARGETSR_FIELD_MASK << target_shift); + target |= cpu_mask << target_shift; + DMSG("cpu_mask: writing 0x%x to 0x%" PRIxVA, target, itargetsr); + io_write32(itargetsr, target); + DMSG("cpu_mask: 0x%x", io_read32(itargetsr)); +} + +static void gic_it_set_prio(struct gic_data *gd, size_t it, uint8_t prio) +{ + size_t idx __maybe_unused = it / NUM_INTS_PER_REG; + uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG); + + /* Assigned to group0 */ + assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); + + /* Set prio it to selected CPUs */ + DMSG("prio: writing 0x%x to 0x%" PRIxVA, + prio, gd->gicd_base + GICD_IPRIORITYR(0) + it); + io_write8(gd->gicd_base + GICD_IPRIORITYR(0) + it, prio); +} + +static void gic_it_enable(struct gic_data *gd, size_t it) +{ + size_t idx = it / NUM_INTS_PER_REG; + uint32_t mask = 1 << (it % NUM_INTS_PER_REG); + vaddr_t base = gd->gicd_base; + + /* Assigned to group0 */ + assert(!(io_read32(base + GICD_IGROUPR(idx)) & mask)); + + /* Enable the interrupt */ + io_write32(base + GICD_ISENABLER(idx), mask); +} + +static void gic_it_disable(struct gic_data *gd, size_t it) +{ + size_t idx = it / NUM_INTS_PER_REG; + uint32_t mask = 1 << (it % NUM_INTS_PER_REG); + + /* Assigned to group0 */ + assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); + + /* Disable the interrupt */ + io_write32(gd->gicd_base + GICD_ICENABLER(idx), mask); +} + +static void gic_it_set_pending(struct gic_data *gd, size_t it) +{ + size_t idx = it / NUM_INTS_PER_REG; + uint32_t mask = BIT32(it % NUM_INTS_PER_REG); + + /* Should be Peripheral Interrupt */ + assert(it >= NUM_SGI); + + /* Raise the interrupt */ + io_write32(gd->gicd_base + GICD_ISPENDR(idx), mask); +} + +static void gic_it_raise_sgi(struct gic_data *gd, size_t it, + uint8_t cpu_mask, uint8_t group) +{ + uint32_t mask_id = it & 0xf; + uint32_t mask_group = group & 0x1; + uint32_t mask_cpu = cpu_mask & 0xff; + uint32_t mask = (mask_id | SHIFT_U32(mask_group, 15) | + SHIFT_U32(mask_cpu, 16)); + + /* Should be Software Generated Interrupt */ + assert(it < NUM_SGI); + + /* Raise the interrupt */ + io_write32(gd->gicd_base + GICD_SGIR, mask); +} + +static uint32_t gic_read_iar(struct gic_data *gd __maybe_unused) +{ +#if defined(CFG_ARM_GICV3) + return read_icc_iar1(); +#else + return io_read32(gd->gicc_base + GICC_IAR); +#endif +} + +static void gic_write_eoir(struct gic_data *gd __maybe_unused, uint32_t eoir) +{ +#if defined(CFG_ARM_GICV3) + write_icc_eoir1(eoir); +#else + io_write32(gd->gicc_base + GICC_EOIR, eoir); +#endif +} + +static bool gic_it_is_enabled(struct gic_data *gd, size_t it) +{ + size_t idx = it / NUM_INTS_PER_REG; + uint32_t mask = 1 << (it % NUM_INTS_PER_REG); + return !!(io_read32(gd->gicd_base + GICD_ISENABLER(idx)) & mask); +} + +static bool __maybe_unused gic_it_get_group(struct gic_data *gd, size_t it) +{ + size_t idx = it / NUM_INTS_PER_REG; + uint32_t mask = 1 << (it % NUM_INTS_PER_REG); + return !!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask); +} + +static uint32_t __maybe_unused gic_it_get_target(struct gic_data *gd, size_t it) +{ + size_t reg_idx = it / NUM_TARGETS_PER_REG; + uint32_t target_shift = (it % NUM_TARGETS_PER_REG) * + ITARGETSR_FIELD_BITS; + uint32_t target_mask = ITARGETSR_FIELD_MASK << target_shift; + uint32_t target = io_read32(gd->gicd_base + GICD_ITARGETSR(reg_idx)); + + return (target & target_mask) >> target_shift; +} + +void gic_dump_state(struct gic_data *gd) +{ + int i; + +#if defined(CFG_ARM_GICV3) + DMSG("GICC_CTLR: 0x%x", read_icc_ctlr()); +#else + DMSG("GICC_CTLR: 0x%x", io_read32(gd->gicc_base + GICC_CTLR)); +#endif + DMSG("GICD_CTLR: 0x%x", io_read32(gd->gicd_base + GICD_CTLR)); + + for (i = 0; i <= (int)gd->max_it; i++) { + if (gic_it_is_enabled(gd, i)) { + DMSG("irq%d: enabled, group:%d, target:%x", i, + gic_it_get_group(gd, i), gic_it_get_target(gd, i)); + } + } +} + +void gic_it_handle(struct gic_data *gd) +{ + uint32_t iar; + uint32_t id; + + iar = gic_read_iar(gd); + id = iar & GICC_IAR_IT_ID_MASK; + + if (id <= gd->max_it) + itr_handle(id); + else + DMSG("ignoring interrupt %" PRIu32, id); + + gic_write_eoir(gd, iar); +} + +static void gic_op_add(struct itr_chip *chip, size_t it, + uint32_t type __unused, + uint32_t prio __unused) +{ + struct gic_data *gd = container_of(chip, struct gic_data, chip); + + if (it > gd->max_it) + panic(); + + gic_it_add(gd, it); + /* Set the CPU mask to deliver interrupts to any online core */ + gic_it_set_cpu_mask(gd, it, 0xff); + gic_it_set_prio(gd, it, 0x1); +} + +static void gic_op_enable(struct itr_chip *chip, size_t it) +{ + struct gic_data *gd = container_of(chip, struct gic_data, chip); + + if (it > gd->max_it) + panic(); + + gic_it_enable(gd, it); +} + +static void gic_op_disable(struct itr_chip *chip, size_t it) +{ + struct gic_data *gd = container_of(chip, struct gic_data, chip); + + if (it > gd->max_it) + panic(); + + gic_it_disable(gd, it); +} + +static void gic_op_raise_pi(struct itr_chip *chip, size_t it) +{ + struct gic_data *gd = container_of(chip, struct gic_data, chip); + + if (it > gd->max_it) + panic(); + + gic_it_set_pending(gd, it); +} + +static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, + uint8_t cpu_mask) +{ + struct gic_data *gd = container_of(chip, struct gic_data, chip); + + if (it > gd->max_it) + panic(); + + if (it < NUM_NS_SGI) + gic_it_raise_sgi(gd, it, cpu_mask, 1); + else + gic_it_raise_sgi(gd, it, cpu_mask, 0); +} +static void gic_op_set_affinity(struct itr_chip *chip, size_t it, + uint8_t cpu_mask) +{ + struct gic_data *gd = container_of(chip, struct gic_data, chip); + + if (it > gd->max_it) + panic(); + + gic_it_set_cpu_mask(gd, it, cpu_mask); +} diff --git a/optee/optee_os/core/drivers/hfic.c b/optee/optee_os/core/drivers/hfic.c new file mode 100644 index 0000000..ec3f996 --- /dev/null +++ b/optee/optee_os/core/drivers/hfic.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +static void hfic_op_add(struct itr_chip *chip __unused, size_t it __unused, + uint32_t type __unused, uint32_t prio __unused) +{ +} + +static void hfic_op_enable(struct itr_chip *chip __unused, size_t it) +{ + uint32_t res __maybe_unused = 0; + + res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_ENABLE, + HF_INTERRUPT_TYPE_IRQ); + assert(!res); +} + +static void hfic_op_disable(struct itr_chip *chip __unused, size_t it) +{ + uint32_t res __maybe_unused = 0; + + res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_DISABLE, + HF_INTERRUPT_TYPE_IRQ); + assert(!res); +} + +static void hfic_op_raise_pi(struct itr_chip *chip __unused, size_t it __unused) +{ + panic(); +} + +static void hfic_op_raise_sgi(struct itr_chip *chip __unused, + size_t it __unused, uint8_t cpu_mask __unused) +{ + panic(); +} + +static void hfic_op_set_affinity(struct itr_chip *chip __unused, + size_t it __unused, uint8_t cpu_mask __unused) +{ + panic(); +} + +static const struct itr_ops hfic_ops = { + .add = hfic_op_add, + .enable = hfic_op_enable, + .disable = hfic_op_disable, + .raise_pi = hfic_op_raise_pi, + .raise_sgi = hfic_op_raise_sgi, + .set_affinity = hfic_op_set_affinity, +}; + +void hfic_init(struct hfic_data *hd) +{ + hd->chip.ops = &hfic_ops; +} + +void hfic_it_handle(struct hfic_data *hd __unused) +{ + uint32_t id = 0; + uint32_t res __maybe_unused = 0; + + id = thread_hvc(HF_INTERRUPT_GET, 0, 0, 0); + if (id == HF_INVALID_INTID) { + DMSG("ignoring invalid interrupt %#"PRIx32, id); + return; + } + + itr_handle(id); + res = thread_hvc(HF_INTERRUPT_DEACTIVATE, id, id, 0); + assert(!res); +} diff --git a/optee/optee_os/core/drivers/hi16xx_rng.c b/optee/optee_os/core/drivers/hi16xx_rng.c new file mode 100644 index 0000000..a3ba2cd --- /dev/null +++ b/optee/optee_os/core/drivers/hi16xx_rng.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +/* Driver for the internal Random Number Generator of HiSilicon P660/Hi16xx */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ALG sub-controller registers */ + +#define ALG_SC_RNG_RESET_DREQ 0xAB4 /* RNG reset cancel */ +# define ALG_SC_SRST_DREQ_RNG BIT(0) + +/* RNG registers */ + +#define RNG_SEED 0x0 /* Initial seed */ +#define RNG_CTRL 0x4 /* Control register */ +# define RNG_SEED_SEL BIT(2) /* Re-seed source: 1: ring osc., 0: LFSR */ +# define RNG_RING_EN BIT(1) /* Enable ring oscillator */ +# define RNG_EN BIT(0) /* Enable RNG */ +#define RNG_NUM 0x10 /* Random number output */ +#define RNG_PHY_SEED 0x14 /* Ring oscillator output */ + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, ALG_SC_BASE, ALG_SC_REG_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); + +static unsigned int rng_lock = SPINLOCK_UNLOCK; + +static TEE_Result hi16xx_rng_init(void) +{ + vaddr_t alg = (vaddr_t)phys_to_virt(ALG_SC_BASE, MEM_AREA_IO_SEC, + ALG_SC_REG_SIZE); + vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, + RNG_REG_SIZE); + TEE_Time time; + + /* ALG sub-controller must allow RNG out of reset */ + io_write32(alg + ALG_SC_RNG_RESET_DREQ, ALG_SC_SRST_DREQ_RNG); + + /* Set initial seed */ + tee_time_get_sys_time(&time); + io_write32(rng + RNG_SEED, time.seconds * 1000 + time.millis); + + /* + * Enable RNG and configure it to re-seed automatically from the + * internal ring oscillator + */ + io_write32(rng + RNG_CTRL, RNG_EN | RNG_RING_EN | RNG_SEED_SEL); + + IMSG("Hi16xx RNG initialized"); + return TEE_SUCCESS; +} + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + static vaddr_t r; + static int pos; + static union { + uint32_t val; + uint8_t byte[4]; + } random; + size_t buffer_pos = 0; + uint8_t *buffer = buf; + uint32_t exceptions; + + exceptions = cpu_spin_lock_xsave(&rng_lock); + if (!r) + r = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, 1) + + RNG_NUM; + cpu_spin_unlock_xrestore(&rng_lock, exceptions); + + while (buffer_pos < len) { + exceptions = cpu_spin_lock_xsave(&rng_lock); + + /* Refill our FIFO */ + if (pos == 0) + random.val = io_read32(r); + + buffer[buffer_pos++] = random.byte[pos++]; + if (pos == 4) + pos = 0; + + cpu_spin_unlock_xrestore(&rng_lock, exceptions); + } + + return TEE_SUCCESS; +} + +driver_init(hi16xx_rng_init); diff --git a/optee/optee_os/core/drivers/hi16xx_uart.c b/optee/optee_os/core/drivers/hi16xx_uart.c new file mode 100644 index 0000000..6f987c3 --- /dev/null +++ b/optee/optee_os/core/drivers/hi16xx_uart.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ +#include +#include +#include +#include +#include +#include + +/* Register offsets */ + +#define UART_RBR 0x00 /* RX data buffer register */ +#define UART_THR 0x00 /* TX data buffer register */ +#define UART_DLL 0x00 /* Lower-bit frequency divider register */ + +#define UART_IEL 0x04 /* Interrupt enable register */ +#define UART_DLH 0x04 /* Upper-bit frequency divider register */ + +#define UART_FCR 0x08 /* FIFO control register */ + +#define UART_LCR 0x0C /* Line control register */ + +#define UART_LSR 0x14 /* Line status register */ + +#define UART_USR 0x7C /* Status register */ + +/* + * Line control register + */ + +/* Data length selection */ +#define UART_LCR_DLS5 0x0 /* 5 bits */ +#define UART_LCR_DLS6 0x1 /* 6 bits */ +#define UART_LCR_DLS7 0x2 /* 7 bits */ +#define UART_LCR_DLS8 0x3 /* 8 bits */ + +/* Enable access to UART_DLL and UART_DLH */ +#define UART_LCR_DLAB 0x80 + +/* + * FIFO control register + */ + +#define UART_FCR_FIFO_EN 0x1 /* Enable FIFO (depth: 32 bytes) */ +#define UART_FCR_RX_FIFO_RST 0x2 /* Clear receive FIFO (auto reset) */ +#define UART_FCR_TX_FIFO_RST 0x4 /* Clear send FIFO (auto reset) */ + + +/* + * Status register + */ + +#define UART_USR_BUSY_BIT 0 /* 0: idle/non-activated, 1: busy */ +#define UART_USR_TFNF_BIT 1 /* Transmit FIFO not full bit */ +#define UART_USR_TFE_BIT 2 /* Transmit FIFO empty bit */ +#define UART_USR_RFNE_BIT 3 /* Receive FIFO not empty bit */ +#define UART_USR_RFF_BIT 4 /* Receive FIFO full bit */ + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct hi16xx_uart_data *pd = + container_of(chip, struct hi16xx_uart_data, chip); + + return io_pa_or_va(&pd->base, HI16XX_UART_REG_SIZE); +} + +static void hi16xx_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read32(base + UART_USR) & UART_USR_TFE_BIT)) + ; +} + +static void hi16xx_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + /* Wait until TX FIFO is empty */ + while (!(io_read32(base + UART_USR) & UART_USR_TFE_BIT)) + ; + + /* Put character into TX FIFO */ + io_write32(base + UART_THR, ch & 0xFF); +} + +static bool hi16xx_uart_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + return (io_read32(base + UART_USR) & UART_USR_RFNE_BIT); +} + +static int hi16xx_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!hi16xx_uart_have_rx_data(chip)) + ; + return io_read32(base + UART_RBR) & 0xFF; +} + +static const struct serial_ops hi16xx_uart_ops = { + .flush = hi16xx_uart_flush, + .getchar = hi16xx_uart_getchar, + .have_rx_data = hi16xx_uart_have_rx_data, + .putc = hi16xx_uart_putc, +}; +DECLARE_KEEP_PAGER(hi16xx_uart_ops); + +void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base, + uint32_t uart_clk, uint32_t baud_rate) +{ + uint16_t freq_div = uart_clk / (16 * baud_rate); + + pd->base.pa = base; + pd->chip.ops = &hi16xx_uart_ops; + + /* Enable (and clear) FIFOs */ + io_write32(base + UART_FCR, UART_FCR_FIFO_EN); + + /* Enable access to _DLL and _DLH */ + io_write32(base + UART_LCR, UART_LCR_DLAB); + + /* Calculate and set UART_DLL */ + io_write32(base + UART_DLL, freq_div & 0xFF); + + /* Calculate and set UART_DLH */ + io_write32(base + UART_DLH, (freq_div >> 8) & 0xFF); + + /* Clear _DLL/_DLH access bit, set data size (8 bits), parity etc. */ + io_write32(base + UART_LCR, UART_LCR_DLS8); + + /* Disable interrupt mode */ + io_write32(base + UART_IEL, 0); + + hi16xx_uart_flush(&pd->chip); +} + diff --git a/optee/optee_os/core/drivers/i2c/atmel_i2c.c b/optee/optee_os/core/drivers/i2c/atmel_i2c.c new file mode 100644 index 0000000..13c8eb7 --- /dev/null +++ b/optee/optee_os/core/drivers/i2c/atmel_i2c.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021-2023 Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TWIHS_CR 0x0 +#define TWIHS_CR_SWRST BIT(7) +#define TWIHS_CR_SVDIS BIT(5) +#define TWIHS_CR_MSEN BIT(2) +#define TWIHS_CR_STOP BIT(1) +#define TWIHS_CR_START BIT(0) + +#define TWIHS_MMR 0x4 +#define TWIHS_MMR_DADR_SHIFT 16 +#define TWIHS_MMR_DADR_MASK 0x7F +#define TWIHS_MMR_MREAD BIT32(12) + +#define TWIHS_CWGR 0x10 +#define TWIHS_CWGR_HOLD_SHIFT 24 +#define TWIHS_CWGR_HOLD_MAX 0x1F +#define TWIHS_CWGR_CKDIV_SHIFT 16 +#define TWIHS_CWGR_CKDIV_MAX 0x7 +#define TWIHS_CWGR_CHDIV_SHIFT 8 + +#define TWIHS_CKSRC BIT32(20) + +#define TWIHS_SR 0x20 +#define TWIHS_SR_NACK BIT32(8) +#define TWIHS_SR_TXRDY BIT32(2) +#define TWIHS_SR_RXRDY BIT32(1) +#define TWIHS_SR_TXCOMP BIT32(0) + +#define TWIHS_RHR 0x30 +#define TWIHS_THR 0x34 + +#define TWIHS_WPMR 0xE4 +#define TWIHS_WPMR_WPKEY SHIFT_U32(0x545749, 8) + +#define I2C_BUS_FREQ 400000 + +struct atmel_i2c { + uint32_t sda_hold_time; + vaddr_t base; + struct clk *clk; + struct i2c_ctrl i2c_ctrl; +}; + +static struct atmel_i2c *atmel_i2c_from_i2c_ctrl(struct i2c_ctrl *i2c_ctrl) +{ + return container_of(i2c_ctrl, struct atmel_i2c, i2c_ctrl); +} + +static TEE_Result atmel_i2c_send_one_byte(struct atmel_i2c *i2c, uint8_t byte) +{ + uint32_t sr = 0; + + io_write32(i2c->base + TWIHS_THR, byte); + + while (true) { + sr = io_read32(i2c->base + TWIHS_SR); + if (sr & TWIHS_SR_NACK) { + EMSG("I2C received NACK while writing"); + return TEE_ERROR_GENERIC; + } + if (sr & TWIHS_SR_TXRDY) + break; + } + + return TEE_SUCCESS; +} + +static void atmel_i2c_wait_txcomp(struct atmel_i2c *i2c) +{ + uint32_t sr = 0; + + while (true) { + sr = io_read32(i2c->base + TWIHS_SR); + if (sr & TWIHS_SR_TXCOMP) + return; + } +} + +static void atmel_i2c_send_start(struct atmel_i2c *i2c) +{ + io_write32(i2c->base + TWIHS_CR, TWIHS_CR_START); +} + +static void atmel_i2c_send_stop(struct atmel_i2c *i2c) +{ + io_write32(i2c->base + TWIHS_CR, TWIHS_CR_STOP); +} + +static TEE_Result atmel_i2c_write_data_no_stop(struct i2c_dev *i2c_dev, + const uint8_t *buf, size_t len) +{ + size_t i = 0; + TEE_Result res = TEE_ERROR_GENERIC; + struct atmel_i2c *i2c = atmel_i2c_from_i2c_ctrl(i2c_dev->ctrl); + uint32_t mmr = SHIFT_U32(i2c_dev->addr, TWIHS_MMR_DADR_SHIFT); + + io_write32(i2c->base + TWIHS_MMR, mmr); + + for (i = 0; i < len; i++) { + res = atmel_i2c_send_one_byte(i2c, buf[i]); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +static TEE_Result atmel_i2c_write_data(struct i2c_dev *i2c_dev, + const uint8_t *buf, size_t len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct atmel_i2c *i2c = atmel_i2c_from_i2c_ctrl(i2c_dev->ctrl); + + res = atmel_i2c_write_data_no_stop(i2c_dev, buf, len); + if (res) + return res; + + atmel_i2c_send_stop(i2c); + atmel_i2c_wait_txcomp(i2c); + + return TEE_SUCCESS; +} + +static TEE_Result atmel_i2c_recv_one_byte(struct atmel_i2c *i2c, + uint8_t *byte) +{ + uint32_t sr = 0; + + while (true) { + sr = io_read32(i2c->base + TWIHS_SR); + if (sr & TWIHS_SR_NACK) { + EMSG("I2C received NACK while reading"); + return TEE_ERROR_GENERIC; + } + if (sr & TWIHS_SR_RXRDY) + break; + } + + *byte = io_read32(i2c->base + TWIHS_RHR); + + return TEE_SUCCESS; +} + +static TEE_Result atmel_i2c_read_data(struct i2c_dev *i2c_dev, uint8_t *buf, + size_t len) +{ + size_t i = 0; + TEE_Result res = TEE_ERROR_GENERIC; + struct atmel_i2c *i2c = atmel_i2c_from_i2c_ctrl(i2c_dev->ctrl); + uint32_t mmr = TWIHS_MMR_MREAD | SHIFT_U32(i2c_dev->addr, + TWIHS_MMR_DADR_SHIFT); + + io_write32(i2c->base + TWIHS_MMR, mmr); + + atmel_i2c_send_start(i2c); + + for (i = 0; i < len; i++) { + if (i == len - 1) + atmel_i2c_send_stop(i2c); + + res = atmel_i2c_recv_one_byte(i2c, &buf[i]); + if (res) + return res; + } + + atmel_i2c_wait_txcomp(i2c); + + return TEE_SUCCESS; +} + +static TEE_Result atmel_i2c_smbus(struct i2c_dev *i2c_dev, + enum i2c_smbus_dir dir, + enum i2c_smbus_protocol proto __unused, + uint8_t cmd_code, + uint8_t buf[I2C_SMBUS_MAX_BUF_SIZE], + size_t len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* Send command code first */ + res = atmel_i2c_write_data_no_stop(i2c_dev, &cmd_code, 1); + if (res) + return res; + + if (dir == I2C_SMBUS_READ) + return atmel_i2c_read_data(i2c_dev, buf, len); + else + return atmel_i2c_write_data(i2c_dev, buf, len); +} + +static unsigned int flsi(unsigned int val) +{ + if (val == 0) + return 0; + + return sizeof(unsigned int) * 8 - __builtin_clz(val); +} + +static TEE_Result atmel_i2c_init_clk(struct atmel_i2c *i2c) +{ + long div = 0; + long hold = 0; + uint32_t cwgr = 0; + uint32_t cxdiv = 0; + uint32_t ckdiv = 0; + unsigned long clk = clk_get_rate(i2c->clk); + + /* + * Since we will configure both CHDIV and CLDIV with the same value + * use 2 * clk + */ + div = UDIV_ROUND_NEAREST(clk, 2 * I2C_BUS_FREQ) - 3; + if (div < 0) + div = 0; + + /* CHDIV/CLDIV are on 8 bits, CKDIV on 3 bits */ + ckdiv = flsi(div >> 8); + if (ckdiv > TWIHS_CWGR_CKDIV_MAX) { + EMSG("CKDIV value too large"); + return TEE_ERROR_BAD_PARAMETERS; + } + cxdiv = div >> ckdiv; + + if (i2c->sda_hold_time) { + /* hold_time = (HOLD + 3) x tperipheral clock */ + hold = UDIV_ROUND_NEAREST(i2c->sda_hold_time * clk, 1000000000); + hold -= 3; + if (hold < 0 || hold > TWIHS_CWGR_HOLD_MAX) { + EMSG("Incorrect hold value"); + return TEE_ERROR_BAD_PARAMETERS; + } + + cwgr |= hold << TWIHS_CWGR_HOLD_SHIFT; + } + + cwgr |= ckdiv << TWIHS_CWGR_CKDIV_SHIFT; + /* CHDIV == CLDIV */ + cwgr |= cxdiv << TWIHS_CWGR_CHDIV_SHIFT; + cwgr |= cxdiv; + io_write32(i2c->base + TWIHS_CWGR, cwgr); + + return TEE_SUCCESS; +} + +static TEE_Result atmel_i2c_init_hw(struct atmel_i2c *i2c) +{ + /* Unlock TWIHS IP */ + io_write32(i2c->base + TWIHS_WPMR, TWIHS_WPMR_WPKEY); + + /* Configure master mode */ + io_write32(i2c->base + TWIHS_CR, TWIHS_CR_SWRST); + + io_write32(i2c->base + TWIHS_CR, TWIHS_CR_SVDIS); + io_write32(i2c->base + TWIHS_CR, TWIHS_CR_MSEN); + + return atmel_i2c_init_clk(i2c); +} + +static const struct i2c_ctrl_ops atmel_i2c_ops = { + .read = atmel_i2c_read_data, + .write = atmel_i2c_write_data, + .smbus = atmel_i2c_smbus, +}; + +static struct i2c_dev *atmel_i2c_get_dt_i2c(struct dt_driver_phandle_args *a, + void *data, TEE_Result *res) +{ + struct i2c_dev *i2c_dev = NULL; + struct i2c_ctrl *i2c_ctrl = data; + + i2c_dev = i2c_create_dev(i2c_ctrl, a->fdt, a->phandle_node); + if (!i2c_dev) { + *res = TEE_ERROR_OUT_OF_MEMORY; + return NULL; + } + + *res = TEE_SUCCESS; + return i2c_dev; +} + +static TEE_Result atmel_i2c_node_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + size_t size = 0; + const uint32_t *cuint = 0; + unsigned int matrix_id = 0; + struct i2c_ctrl *i2c_ctrl = NULL; + struct atmel_i2c *atmel_i2c = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + int status = fdt_get_status(fdt, node); + + if (status != DT_STATUS_OK_SEC) + return TEE_SUCCESS; + + atmel_i2c = calloc(1, sizeof(struct atmel_i2c)); + if (!atmel_i2c) + return TEE_ERROR_OUT_OF_MEMORY; + + i2c_ctrl = &atmel_i2c->i2c_ctrl; + i2c_ctrl->ops = &atmel_i2c_ops; + + res = clk_dt_get_by_index(fdt, node, 0, &atmel_i2c->clk); + if (res) + goto err_free; + + res = matrix_dt_get_id(fdt, node, &matrix_id); + if (res) + goto err_free; + + if (dt_map_dev(fdt, node, &atmel_i2c->base, &size, DT_MAP_AUTO) < 0) { + res = TEE_ERROR_GENERIC; + goto err_free; + } + + matrix_configure_periph_secure(matrix_id); + + cuint = fdt_getprop(fdt, node, "i2c-sda-hold-time-ns", NULL); + if (cuint) + atmel_i2c->sda_hold_time = fdt32_to_cpu(*cuint); + + clk_enable(atmel_i2c->clk); + + res = atmel_i2c_init_hw(atmel_i2c); + if (res) + goto err_clk_disable; + + res = i2c_register_provider(fdt, node, atmel_i2c_get_dt_i2c, i2c_ctrl); + if (res) + goto err_clk_disable; + + return TEE_SUCCESS; + +err_clk_disable: + clk_disable(atmel_i2c->clk); +err_free: + free(atmel_i2c); + + return res; +} + +static const struct dt_device_match atmel_i2c_match_table[] = { + { .compatible = "atmel,sama5d2-i2c" }, + { } +}; + +DEFINE_DT_DRIVER(atmel_i2c_dt_driver) = { + .name = "atmel_i2c", + .type = DT_DRIVER_NOTYPE, + .match_table = atmel_i2c_match_table, + .probe = atmel_i2c_node_probe, +}; diff --git a/optee/optee_os/core/drivers/i2c/i2c.c b/optee/optee_os/core/drivers/i2c/i2c.c new file mode 100644 index 0000000..37ca1f2 --- /dev/null +++ b/optee/optee_os/core/drivers/i2c/i2c.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2023 Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct i2c_dev *i2c_create_dev(struct i2c_ctrl *i2c_ctrl, const void *fdt, + int node) +{ + struct i2c_dev *i2c_dev = NULL; + paddr_t addr = fdt_reg_base_address(fdt, node); + + if (addr == DT_INFO_INVALID_REG) + return NULL; + + i2c_dev = calloc(1, sizeof(struct i2c_dev)); + if (!i2c_dev) + return NULL; + + i2c_dev->addr = addr; + i2c_dev->ctrl = i2c_ctrl; + + return i2c_dev; +} diff --git a/optee/optee_os/core/drivers/i2c/sub.mk b/optee/optee_os/core/drivers/i2c/sub.mk new file mode 100644 index 0000000..e2a28bc --- /dev/null +++ b/optee/optee_os/core/drivers/i2c/sub.mk @@ -0,0 +1,2 @@ +srcs-y += i2c.c +srcs-$(CFG_ATMEL_I2C) += atmel_i2c.c \ No newline at end of file diff --git a/optee/optee_os/core/drivers/imx/dcp/dcp.c b/optee/optee_os/core/drivers/imx/dcp/dcp.c new file mode 100644 index 0000000..34324b9 --- /dev/null +++ b/optee/optee_os/core/drivers/imx/dcp/dcp.c @@ -0,0 +1,776 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const uint8_t sha1_null_msg[] = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, + 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, +}; + +static const uint8_t sha256_null_msg[] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, + 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, + 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, +}; + +static vaddr_t dcp_base; +static bool driver_initialized; +static unsigned int clk_refcount; +static unsigned int key_store_spinlock = SPINLOCK_UNLOCK; +static unsigned int clock_spinlock = SPINLOCK_UNLOCK; +static struct dcp_align_buf hw_context_buffer; + +static struct mutex lock_channel[DCP_NB_CHANNELS] = { + [DCP_CHANN0] = MUTEX_INITIALIZER, + [DCP_CHANN1] = MUTEX_INITIALIZER, + [DCP_CHANN2] = MUTEX_INITIALIZER, + [DCP_CHANN3] = MUTEX_INITIALIZER, +}; + +static const struct dcp_hashalg hash_alg[2] = { + [DCP_SHA1] = { + .type = DCP_CONTROL1_HASH_SELECT_SHA1, + .size = TEE_SHA1_HASH_SIZE, + }, + [DCP_SHA256] = { + .type = DCP_CONTROL1_HASH_SELECT_SHA256, + .size = TEE_SHA256_HASH_SIZE, + }, +}; + +/* + * Enable/disable DCP clock. + * + * @enable Enable the clock if true, disable if false. + */ +static void dcp_clk_enable(bool enable) +{ + vaddr_t ccm_base = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, + CCM_CCGR0 + sizeof(uint32_t)); + uint32_t clock_except = cpu_spin_lock_xsave(&clock_spinlock); + + if (enable) { + if (clk_refcount > 0) { + clk_refcount++; + goto out; + } else { + clk_refcount++; + io_setbits32(ccm_base + CCM_CCGR0, DCP_CLK_ENABLE_MASK); + } + } else { + assert(clk_refcount != 0); + + clk_refcount--; + if (clk_refcount > 0) + goto out; + else + io_clrbits32(ccm_base + CCM_CCGR0, DCP_CLK_ENABLE_MASK); + } +out: + cpu_spin_unlock_xrestore(&clock_spinlock, clock_except); +} + +/* + * Lock the given channel with a mutex. + * + * @chan DCP channel to lock + */ +static TEE_Result dcp_lock_known_channel(enum dcp_channel chan) +{ + if (mutex_trylock(&lock_channel[chan])) + return TEE_SUCCESS; + else + return TEE_ERROR_BUSY; +} + +/* + * Lock a DCP channel + * + * @channel Pointer on operation channel parameter + */ +static TEE_Result dcp_lock_channel(enum dcp_channel *channel) +{ + TEE_Result ret = TEE_ERROR_BUSY; + enum dcp_channel chan = DCP_CHANN0; + + for (chan = DCP_CHANN0; chan < DCP_NB_CHANNELS; chan++) { + ret = dcp_lock_known_channel(chan); + if (ret == TEE_SUCCESS) { + *channel = chan; + return ret; + } + } + + EMSG("All channels are busy"); + + return ret; +} + +/* + * Unlock the given channel. + * + * @chan DCP channel to unlock + */ +static void dcp_unlock_channel(enum dcp_channel chan) +{ + mutex_unlock(&lock_channel[chan]); +} + +/* + * Start the DCP operation. + * + * @dcp_data Structure containing dcp_descriptor configuration and channel to + * use. + */ +static TEE_Result dcp_run(struct dcp_data *dcp_data) +{ + TEE_Result ret = TEE_SUCCESS; + unsigned int timeout = 0; + uint32_t val = 0; + + dcp_data->desc.next = 0; + cache_operation(TEE_CACHEFLUSH, &dcp_data->desc, + sizeof(dcp_data->desc)); + + /* Enable clock if it's not done */ + dcp_clk_enable(true); + + /* Clear DCP_STAT IRQ field for the channel used by the operation */ + io_clrbits32(dcp_base + DCP_STAT, BIT32(dcp_data->channel)); + + /* Clear CH_N_STAT to clear IRQ and error codes */ + io_write32(dcp_base + DCP_CH_N_STAT(dcp_data->channel), 0x0); + + /* Update descriptor structure to be processed for the channel */ + io_write32(dcp_base + DCP_CH_N_CMDPTR(dcp_data->channel), + virt_to_phys(&dcp_data->desc)); + + /* Increment the semaphore to start the transfer */ + io_write32(dcp_base + DCP_CH_N_SEMA(dcp_data->channel), 0x1); + + for (timeout = 0; timeout < DCP_MAX_TIMEOUT; timeout++) { + dcp_udelay(10); + val = io_read32(dcp_base + DCP_STAT); + if (val & BIT(dcp_data->channel)) + break; + } + + if (timeout == DCP_MAX_TIMEOUT) { + EMSG("Timeout elapsed before operation"); + ret = TEE_ERROR_GENERIC; + goto out; + } + + val = io_read32(dcp_base + DCP_CH_N_STAT(dcp_data->channel)); + if (val & DCP_CH_STAT_ERROR_MASK) { + EMSG("Error operation, 0x%" PRIx32, val); + ret = TEE_ERROR_GENERIC; + } + +out: + dcp_clk_enable(false); + + return ret; +} + +static TEE_Result dcp_cmac_subkey_generation(struct dcp_cipher_init *init, + uint8_t *k1, uint8_t *k2) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct dcp_cipher_data data = { }; + uint8_t l[16] = { }; + uint8_t tmp[16] = { }; + uint8_t const_zero[16] = { }; + uint8_t const_rb[16] = { [15] = 0x87 }; + + ret = dcp_cipher_do_init(&data, init); + if (ret != TEE_SUCCESS) + return ret; + + ret = dcp_cipher_do_update(&data, const_zero, l, sizeof(l)); + if (ret != TEE_SUCCESS) + goto out; + + if ((l[0] & BIT(7)) == 0) { + dcp_left_shift_buffer(l, k1, 16); + } else { + dcp_left_shift_buffer(l, tmp, 16); + dcp_xor(tmp, const_rb, k1, 16); + } + + if ((k1[0] & BIT(7)) == 0) { + dcp_left_shift_buffer(k1, k2, 16); + } else { + dcp_left_shift_buffer(k1, tmp, 16); + dcp_xor(tmp, const_rb, k2, 16); + } + + ret = TEE_SUCCESS; +out: + dcp_cipher_do_final(&data); + + return ret; +} + +TEE_Result dcp_store_key(uint32_t *key, unsigned int index) +{ + uint32_t val = 0; + unsigned int i = 0; + uint32_t key_store_except = 0; + + if (!key) + return TEE_ERROR_BAD_PARAMETERS; + + if (index > DCP_SRAM_KEY_NB_SUBWORD - 1) { + EMSG("Bad parameters, index must be < %u", + DCP_SRAM_KEY_NB_SUBWORD); + return TEE_ERROR_BAD_PARAMETERS; + } + + key_store_except = cpu_spin_lock_xsave(&key_store_spinlock); + + dcp_clk_enable(true); + + val = DCP_SRAM_KEY_INDEX(index); + io_write32(dcp_base + DCP_KEY, val); + + /* + * Key is stored as four uint32 values, starting with subword0 + * (least-significant word) + */ + for (i = 0; i < DCP_SRAM_KEY_NB_SUBWORD; i++) { + val = TEE_U32_TO_BIG_ENDIAN(key[i]); + io_write32(dcp_base + DCP_KEYDATA, val); + } + + dcp_clk_enable(false); + + cpu_spin_unlock_xrestore(&key_store_spinlock, key_store_except); + + return TEE_SUCCESS; +} + +TEE_Result dcp_cmac(struct dcp_cipher_init *init, uint8_t *input, + size_t input_size, uint8_t *output) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + uint8_t key1[DCP_AES128_KEY_SIZE] = { }; + uint8_t key2[DCP_AES128_KEY_SIZE] = { }; + unsigned int nb_blocks = 0; + bool block_complete = false; + struct dcp_cipher_data data = { }; + uint8_t y[DCP_AES128_BLOCK_SIZE] = { }; + uint8_t x[DCP_AES128_BLOCK_SIZE] = { }; + uint8_t last[DCP_AES128_BLOCK_SIZE] = { }; + unsigned int i = 0; + uint8_t offset = 0; + + if (!output || !init) + return TEE_ERROR_BAD_PARAMETERS; + + if (!input && input_size) + return TEE_ERROR_BAD_PARAMETERS; + + ret = dcp_cipher_do_init(&data, init); + if (ret != TEE_SUCCESS) { + ret = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* Generate CMAC subkeys */ + ret = dcp_cmac_subkey_generation(init, key1, key2); + if (ret != TEE_SUCCESS) + goto out; + + /* Get number of block */ + nb_blocks = ROUNDUP(input_size, DCP_AES128_BLOCK_SIZE) / + DCP_AES128_BLOCK_SIZE; + + block_complete = nb_blocks && !(input_size % DCP_AES128_BLOCK_SIZE); + if (nb_blocks == 0) + nb_blocks = 1; + + for (i = 0; i < nb_blocks - 1; i++) { + dcp_xor(x, input + offset, y, DCP_AES128_BLOCK_SIZE); + ret = dcp_cipher_do_update(&data, y, x, + DCP_AES128_BLOCK_SIZE); + if (ret) + goto out; + offset += DCP_AES128_BLOCK_SIZE; + } + + /* Process the last block */ + memcpy(last, input + offset, input_size - offset); + + if (block_complete) { + dcp_xor(last, key1, last, DCP_AES128_BLOCK_SIZE); + } else { + dcp_cmac_padding(last, input_size % DCP_AES128_BLOCK_SIZE); + dcp_xor(last, key2, last, DCP_AES128_BLOCK_SIZE); + } + + dcp_xor(x, last, y, DCP_AES128_BLOCK_SIZE); + ret = dcp_cipher_do_update(&data, y, x, + DCP_AES128_BLOCK_SIZE); + if (ret) + goto out; + + memcpy(output, x, DCP_AES128_BLOCK_SIZE); + +out: + dcp_cipher_do_final(&data); + + return ret; +} + +TEE_Result dcp_cipher_do_init(struct dcp_cipher_data *data, + struct dcp_cipher_init *init) +{ + struct dcp_descriptor *desc = NULL; + TEE_Result ret = TEE_ERROR_GENERIC; + + if (!init || !data) + return TEE_ERROR_BAD_PARAMETERS; + + ret = dcp_lock_channel(&data->dcp_data.channel); + if (ret != TEE_SUCCESS) + return ret; + + desc = &data->dcp_data.desc; + + desc->ctrl0 = DCP_CONTROL0_DECR_SEMAPHORE | DCP_CONTROL0_ENABLE_CIPHER | + DCP_CONTROL0_INTERRUPT_ENABLE; + desc->ctrl1 = DCP_CONTROL1_CIPHER_SELECT_AES128; + + if (init->op == DCP_ENCRYPT) + desc->ctrl0 |= DCP_CONTROL0_CIPHER_ENCRYPT; + + if (init->key_mode == DCP_OTP) { + desc->ctrl0 &= ~DCP_CONTROL0_OTP_KEY; + desc->ctrl1 |= DCP_CONTROL1_KEY_SELECT_OTP_CRYPTO; + } else if (init->key_mode == DCP_PAYLOAD) { + desc->ctrl0 |= DCP_CONTROL0_PAYLOAD_KEY; + if (!init->key) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(data->key, init->key, DCP_AES128_KEY_SIZE); + } else { + desc->ctrl1 |= SHIFT_U32(init->key_mode, 8); + } + + if (init->mode == DCP_CBC) { + desc->ctrl0 |= DCP_CONTROL0_CIPHER_INIT; + desc->ctrl1 |= DCP_CONTROL1_CIPHER_MODE_CBC; + if (!init->iv) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(data->iv, init->iv, DCP_AES128_IV_SIZE); + } + + /* Allocate aligned buffer for dcp iv and key */ + ret = dcp_calloc_align_buf(&data->payload, + DCP_AES128_IV_SIZE + DCP_AES128_KEY_SIZE); + if (ret != TEE_SUCCESS) + return ret; + + desc->src_buffer = 0; + desc->dest_buffer = 0; + desc->status = 0; + desc->buff_size = 0; + desc->next = virt_to_phys(desc); + + data->initialized = true; + + return ret; +} + +TEE_Result dcp_cipher_do_update(struct dcp_cipher_data *data, + const uint8_t *src, uint8_t *dst, size_t size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct dcp_align_buf output = { }; + struct dcp_align_buf input = { }; + struct dcp_descriptor *desc = NULL; + + if (!data || !src || !dst) + return TEE_ERROR_BAD_PARAMETERS; + + if (!data->initialized) { + EMSG("Error, please call dcp_aes_do_init() before"); + return TEE_ERROR_BAD_STATE; + } + + if (size % DCP_AES128_BLOCK_SIZE) { + EMSG("Input size has to be a multiple of %zu bytes", + DCP_AES128_BLOCK_SIZE); + return TEE_ERROR_BAD_PARAMETERS; + } + + ret = dcp_calloc_align_buf(&output, size); + if (ret != TEE_SUCCESS) + goto out; + + ret = dcp_calloc_align_buf(&input, size); + if (ret != TEE_SUCCESS) + goto out; + + desc = &data->dcp_data.desc; + + /* Copy input data */ + memcpy(input.data, src, size); + + /* Copy key and IV */ + memcpy(data->payload.data, data->key, DCP_AES128_KEY_SIZE); + data->payload_size = DCP_AES128_KEY_SIZE; + if (desc->ctrl0 & DCP_CONTROL0_CIPHER_INIT) { + memcpy(data->payload.data + DCP_AES128_KEY_SIZE, data->iv, + DCP_AES128_IV_SIZE); + data->payload_size += DCP_AES128_IV_SIZE; + } + + desc->src_buffer = input.paddr; + desc->dest_buffer = output.paddr; + desc->payload = data->payload.paddr; + desc->buff_size = size; + + cache_operation(TEE_CACHECLEAN, data->payload.data, + data->payload_size); + cache_operation(TEE_CACHECLEAN, input.data, size); + cache_operation(TEE_CACHEINVALIDATE, output.data, size); + + ret = dcp_run(&data->dcp_data); + if (ret) + goto out; + + cache_operation(TEE_CACHEINVALIDATE, output.data, size); + + desc->ctrl0 &= ~DCP_CONTROL0_CIPHER_INIT; + + memcpy(dst, output.data, size); +out: + dcp_free(&output); + dcp_free(&input); + + return ret; +} + +void dcp_cipher_do_final(struct dcp_cipher_data *data) +{ + if (data) + data->initialized = false; + + dcp_free(&data->payload); + dcp_unlock_channel(data->dcp_data.channel); +} + +TEE_Result dcp_sha_do_init(struct dcp_hash_data *hashdata) +{ + struct dcp_descriptor *desc = NULL; + TEE_Result ret = TEE_ERROR_GENERIC; + + if (!hashdata) { + EMSG("Bad parameters, hashdata is NULL"); + return TEE_ERROR_BAD_PARAMETERS; + } + + desc = &hashdata->dcp_data.desc; + + /* DCP descriptor init */ + desc->status = 0; + desc->payload = 0; + desc->dest_buffer = 0; + desc->ctrl0 = DCP_CONTROL0_ENABLE_HASH | DCP_CONTROL0_INTERRUPT_ENABLE | + DCP_CONTROL0_DECR_SEMAPHORE | DCP_CONTROL0_HASH_INIT; + desc->ctrl1 = hash_alg[hashdata->alg].type; + desc->buff_size = 0; + desc->next = 0; + desc->src_buffer = 0; + + ret = dcp_lock_channel(&hashdata->dcp_data.channel); + if (ret != TEE_SUCCESS) { + EMSG("Channel is busy, can't start operation now"); + return ret; + } + + /* Allocate context data */ + ret = dcp_calloc_align_buf(&hashdata->ctx, DCP_SHA_BLOCK_SIZE); + if (ret != TEE_SUCCESS) + return ret; + + hashdata->initialized = true; + hashdata->ctx_size = 0; + + return ret; +} + +TEE_Result dcp_sha_do_update(struct dcp_hash_data *hashdata, + const uint8_t *data, size_t len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + struct dcp_descriptor *desc = NULL; + struct dcp_align_buf input = { }; + uint32_t offset = 0; + uint32_t nb_blocks = 0; + size_t size_todo = 0; + size_t size_left = 0; + size_t size_total = 0; + + if (!hashdata || !data || !len) + return TEE_ERROR_BAD_PARAMETERS; + + if (!hashdata->initialized) { + EMSG("hashdata is uninitialized"); + return TEE_ERROR_BAD_STATE; + } + + /* Get number of blocks */ + if (ADD_OVERFLOW(hashdata->ctx_size, len, &size_total)) + return TEE_ERROR_BAD_PARAMETERS; + + nb_blocks = size_total / DCP_SHA_BLOCK_SIZE; + size_todo = nb_blocks * DCP_SHA_BLOCK_SIZE; + size_left = len - size_todo + hashdata->ctx_size; + desc = &hashdata->dcp_data.desc; + + if (size_todo) { + /* Allocate buffer as input */ + ret = dcp_calloc_align_buf(&input, size_todo); + if (ret != TEE_SUCCESS) + return ret; + + /* Copy previous data if any */ + offset = size_todo - hashdata->ctx_size; + memcpy(input.data, hashdata->ctx.data, hashdata->ctx_size); + memcpy(input.data + hashdata->ctx_size, data, offset); + hashdata->ctx_size = 0; + + desc->src_buffer = input.paddr; + desc->buff_size = size_todo; + + cache_operation(TEE_CACHECLEAN, input.data, size_todo); + + ret = dcp_run(&hashdata->dcp_data); + desc->ctrl0 &= ~DCP_CONTROL0_HASH_INIT; + + dcp_free(&input); + } else { + size_left = len; + offset = 0; + ret = TEE_SUCCESS; + } + + /* Save any data left */ + memcpy(hashdata->ctx.data + hashdata->ctx_size, data + offset, + size_left); + hashdata->ctx_size += size_left; + + return ret; +} + +TEE_Result dcp_sha_do_final(struct dcp_hash_data *hashdata, uint8_t *digest, + size_t digest_size) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t payload_size = 0; + struct dcp_descriptor *desc = NULL; + struct dcp_align_buf payload = { }; + + if (!hashdata || !digest) + return TEE_ERROR_BAD_PARAMETERS; + + if (!hashdata->initialized) { + EMSG("hashdata is uninitialized"); + return TEE_ERROR_BAD_STATE; + } + + if (digest_size < hash_alg[hashdata->alg].size) { + EMSG("Digest buffer size is to small, should be %" PRId32, + hash_alg[hashdata->alg].size); + return TEE_ERROR_BAD_PARAMETERS; + } + + desc = &hashdata->dcp_data.desc; + payload_size = hash_alg[hashdata->alg].size; + + /* Handle the case where the input message is NULL */ + if ((desc->ctrl0 & DCP_CONTROL0_HASH_INIT) && hashdata->ctx_size == 0) { + if (hashdata->alg == DCP_SHA1) + memcpy(digest, sha1_null_msg, payload_size); + if (hashdata->alg == DCP_SHA256) + memcpy(digest, sha256_null_msg, payload_size); + ret = TEE_SUCCESS; + } else { + /* Allocate buffer for the digest */ + ret = dcp_calloc_align_buf(&payload, payload_size); + if (ret != TEE_SUCCESS) + return ret; + + /* Set work packet for last iteration */ + desc->ctrl0 |= DCP_CONTROL0_HASH_TERM; + desc->src_buffer = hashdata->ctx.paddr; + desc->buff_size = hashdata->ctx_size; + desc->payload = payload.paddr; + + cache_operation(TEE_CACHECLEAN, hashdata->ctx.data, + hashdata->ctx_size); + cache_operation(TEE_CACHEINVALIDATE, payload.data, + payload_size); + + ret = dcp_run(&hashdata->dcp_data); + + /* Copy the result */ + cache_operation(TEE_CACHEINVALIDATE, payload.data, + payload_size); + /* DCP payload result is flipped */ + dcp_reverse(payload.data, digest, payload_size); + + dcp_free(&payload); + } + + dcp_free(&hashdata->ctx); + + /* Reset hashdata strcuture */ + hashdata->initialized = false; + + dcp_unlock_channel(hashdata->dcp_data.channel); + + return ret; +} + +void dcp_disable_unique_key(void) +{ + dcp_clk_enable(true); + io_setbits32(dcp_base + DCP_CAPABILITY0, + DCP_CAPABILITY0_DISABLE_UNIQUE_KEY); + dcp_clk_enable(false); +} + +#ifdef CFG_DT +static const char *const dt_ctrl_match_table[] = { + "fsl,imx28-dcp", + "fsl,imx6sl-dcp", +}; + +/* + * Fetch DCP base address from DT + * + * @base [out] DCP base address + */ +static TEE_Result dcp_pbase(paddr_t *base) +{ + void *fdt = NULL; + int node = -1; + unsigned int i = 0; + + fdt = get_dt(); + if (!fdt) { + EMSG("DTB no present"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + for (i = 0; i < ARRAY_SIZE(dt_ctrl_match_table); i++) { + node = fdt_node_offset_by_compatible(fdt, 0, + dt_ctrl_match_table[i]); + if (node >= 0) + break; + } + + if (node < 0) { + EMSG("DCP node not found err = %d", node); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* Force secure-status = "okay" and status="disabled" */ + if (dt_enable_secure_status(fdt, node)) { + EMSG("Not able to set DCP Control DTB entry secure"); + return TEE_ERROR_NOT_SUPPORTED; + } + + *base = fdt_reg_base_address(fdt, node); + if (*base == DT_INFO_INVALID_REG) { + EMSG("Unable to get the DCP Base address"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + return TEE_SUCCESS; +} +#endif /* CFG_DT */ + +TEE_Result dcp_init(void) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + paddr_t pbase = 0; + + if (driver_initialized) + return TEE_SUCCESS; + + dcp_clk_enable(true); + + ret = dcp_pbase(&pbase); + if (ret != TEE_SUCCESS) + pbase = DCP_BASE; + + dcp_base = core_mmu_get_va(pbase, MEM_AREA_IO_SEC, DCP_CONTEXT + + sizeof(uint32_t)); + if (!dcp_base) { + EMSG("Unable to get DCP physical address"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + /* Context switching buffer memory allocation */ + ret = dcp_calloc_align_buf(&hw_context_buffer, DCP_CONTEXT_BUFFER_SIZE); + if (ret != TEE_SUCCESS) { + EMSG("hw_context_buffer allocation failed"); + return ret; + } + + /* + * Reset the DCP before initialization. Depending on the SoC lifecycle + * state, the DCP needs to be reset to reload the OTP master key from + * the SNVS. + */ + io_write32(dcp_base + DCP_CTRL_SET, DCP_CTRL_SFTRST | DCP_CTRL_CLKGATE); + + /* + * Initialize control register. + * Enable normal DCP operation (SFTRST & CLKGATE bits set to 0) + */ + io_write32(dcp_base + DCP_CTRL_CLR, DCP_CTRL_SFTRST | DCP_CTRL_CLKGATE); + + io_write32(dcp_base + DCP_CTRL_SET, + DCP_CTRL_GATHER_RESIDUAL_WRITES | + DCP_CTRL_ENABLE_CONTEXT_SWITCHING); + + /* Enable all DCP channels */ + io_write32(dcp_base + DCP_CHANNELCTRL, + DCP_CHANNELCTRL_ENABLE_CHANNEL_MASK); + + /* Clear DCP_STAT register */ + io_write32(dcp_base + DCP_STAT_CLR, DCP_STAT_CLEAR); + + /* Copy context switching buffer address in DCP_CONTEXT register */ + io_write32(dcp_base + DCP_CONTEXT, (uint32_t)hw_context_buffer.paddr); + + driver_initialized = true; + + dcp_clk_enable(false); + + return ret; +} diff --git a/optee/optee_os/core/drivers/imx/dcp/dcp_huk.c b/optee/optee_os/core/drivers/imx/dcp/dcp_huk.c new file mode 100644 index 0000000..ca79ff7 --- /dev/null +++ b/optee/optee_os/core/drivers/imx/dcp/dcp_huk.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020 NXP + */ + +#include +#include +#include +#include + +#define HUK_MESSAGE_NULL_BYTE 0 +#define NB_ITERATION_HUK 1 +#define HUK_SIZE_BITS 128 + +/* State of the generated HUK */ +enum dcp_huk_state { + DCP_HUK_EMPTY = 0, + DCP_HUK_GENERATED, + DCP_HUK_ERROR, +}; + +/* Information about HUK */ +static struct { + enum dcp_huk_state state; + uint8_t data[HW_UNIQUE_KEY_LENGTH]; +} dcp_huk = { .state = DCP_HUK_EMPTY }; + +/* + * Generate Hardware Unique Key using the Data Co-Processor (DCP) AES128-CMAC + * cryptographic operation + * Follow dcp_aes_cmac() message format + * + * @hwkey [out] Hardware Unique Key private data + */ +static TEE_Result dcp_generate_huk(struct tee_hw_unique_key *hwkey) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct dcp_cipher_init init = { + .key_mode = DCP_OTP, + .mode = DCP_ECB, + .op = DCP_ENCRYPT, + }; + uint8_t content[DCP_AES128_BLOCK_SIZE] = { NB_ITERATION_HUK, + 'h', + 'u', + 'k', + HUK_MESSAGE_NULL_BYTE, + 'o', + 'p', + 't', + 'e', + 'e', + 'o', + 's', + 'd', + 'c', + 'p', + HUK_SIZE_BITS }; + + res = dcp_cmac(&init, content, DCP_AES128_BLOCK_SIZE, hwkey->data); + + dcp_disable_unique_key(); + + return res; +} + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + if (!hwkey) { + EMSG("HUK generation failed, hwkey structure is NULL"); + return TEE_ERROR_BAD_PARAMETERS; + } + + ret = dcp_init(); + if (ret != TEE_SUCCESS) { + dcp_huk.state = DCP_HUK_ERROR; + return ret; + } + + if (dcp_huk.state == DCP_HUK_EMPTY) { + ret = dcp_generate_huk(hwkey); + if (ret != TEE_SUCCESS) { + dcp_huk.state = DCP_HUK_ERROR; + } else { + memcpy(dcp_huk.data, hwkey->data, HW_UNIQUE_KEY_LENGTH); + dcp_huk.state = DCP_HUK_GENERATED; + } + } else if (dcp_huk.state == DCP_HUK_GENERATED) { + memcpy(hwkey->data, dcp_huk.data, HW_UNIQUE_KEY_LENGTH); + ret = TEE_SUCCESS; + } else { + ret = TEE_ERROR_GENERIC; + } + + return ret; +} diff --git a/optee/optee_os/core/drivers/imx/dcp/dcp_utils.c b/optee/optee_os/core/drivers/imx/dcp/dcp_utils.c new file mode 100644 index 0000000..9d21d7a --- /dev/null +++ b/optee/optee_os/core/drivers/imx/dcp/dcp_utils.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020 NXP + */ +#include +#include +#include +#include +#include +#include +#include + +TEE_Result dcp_calloc_align_buf(struct dcp_align_buf *buf, size_t size) +{ + if (!buf) { + EMSG("Error, buf is null"); + return TEE_ERROR_BAD_PARAMETERS; + } + + buf->data = alloc_cache_aligned(size); + if (!buf->data) + return TEE_ERROR_OUT_OF_MEMORY; + + buf->paddr = virt_to_phys(buf->data); + + if (!buf->paddr) { + dcp_free(buf); + return TEE_ERROR_OUT_OF_MEMORY; + } + + buf->size = size; + + return TEE_SUCCESS; +} + +void dcp_free(struct dcp_align_buf *buf) +{ + free(buf->data); +} + +void dcp_left_shift_buffer(uint8_t *input, uint8_t *result, size_t buffer_size) +{ + unsigned int i = 0; + uint8_t overflow = 0; + + /* For each byte */ + for (i = 0; i < buffer_size; i++) { + /* Left shift a bytes by one */ + result[buffer_size - 1 - i] = + input[buffer_size - 1 - i] << 1 | overflow; + + overflow = input[buffer_size - 1 - i] >> 7; + } +} + +void dcp_udelay(uint32_t time) +{ + uint32_t counter = time * 500; + + /* Implementation of a Software loop assuming CPU clock of 500MHz */ + while (counter--) { + isb(); + dsb(); + }; +} + +void dcp_reverse(uint8_t *in, uint8_t *out, size_t size) +{ + unsigned int i = 0; + + for (i = 0; i < size; i++) + out[i] = in[size - 1 - i]; +} + +void dcp_xor(uint8_t *a, uint8_t *b, uint8_t *out, size_t size) +{ + unsigned int i = 0; + + for (i = 0; i < size; i++) + out[i] = a[i] ^ b[i]; +} + +void dcp_cmac_padding(uint8_t *block, size_t len) +{ + unsigned int i = 0; + + for (i = len; i < DCP_AES128_BLOCK_SIZE; i++) { + if (i == len) + block[i] = BIT(7); + else + block[i] = 0x0; + } +} diff --git a/optee/optee_os/core/drivers/imx/dcp/include/dcp_utils.h b/optee/optee_os/core/drivers/imx/dcp/include/dcp_utils.h new file mode 100644 index 0000000..c96c501 --- /dev/null +++ b/optee/optee_os/core/drivers/imx/dcp/include/dcp_utils.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020 NXP + */ +#ifndef __DCP_UTILS_H__ +#define __DCP_UTILS_H__ + +#include +#include + +/* Adjust index value for writing in register */ +#define DCP_SRAM_KEY_INDEX(idx) SHIFT_U32(idx, 4) + +/* Calculate context switching buffer offset */ +#define DCP_CONTEXT_SW_OFFSET(chann) ((DCP_NB_CHANNELS - 1 - (chann)) * 52) + +/* + * Allocate internal driver buffer aligned with a cache line and initialize it + * with 0s + * + * @buf [out] Buffer to allocate + * @size Size in bytes of the memory to allocate + */ +TEE_Result dcp_calloc_align_buf(struct dcp_align_buf *buf, size_t size); + +/* + * Free allocated memory + * + * @buf buffer to free. + */ +void dcp_free(struct dcp_align_buf *buf); + +/* + * Left shifting a multi bytes buffer by one bit + * + * @result [out] Buffer containing the result of the operation + * @input Input buffer for the operation + * @buffer_size Size of the buffer in bytes + */ +void dcp_left_shift_buffer(uint8_t *result, uint8_t *input, size_t buffer_size); + +/* + * Wait given microsecond + * + * @time Time in microsecond + */ +void dcp_udelay(uint32_t time); + +/* + * Copies elements from a buffer to another one. These elements are copied in + * reverse order. + * + * @in input buffer + * @out output buffer + * @size bytes to copy + */ +void dcp_reverse(uint8_t *in, uint8_t *out, size_t size); + +/* + * Operate a XOR between two same size buffers + * + * @a Input buffer to XOR + * @b Input buffer to XOR + * @out Result of the XOR operation + * @size Size of input and output buffers + */ +void dcp_xor(uint8_t *a, uint8_t *b, uint8_t *out, size_t size); + +/* + * CMAC padding. + * The padding result is the concatenation of the input buffer block and a + * single '1' followed by the minimum number of '0's to get a 128 bits + * block. + * + * @block Block to pad + * @len Length of the padding + */ +void dcp_cmac_padding(uint8_t *block, size_t len); + +#endif /* __DCP_UTILS_H__ */ diff --git a/optee/optee_os/core/drivers/imx/dcp/include/local.h b/optee/optee_os/core/drivers/imx/dcp/include/local.h new file mode 100644 index 0000000..9d6b312 --- /dev/null +++ b/optee/optee_os/core/drivers/imx/dcp/include/local.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020 NXP + */ +#ifndef __LOCAL_H__ +#define __LOCAL_H__ + +#define DCP_CONTEXT_BUFFER_SIZE 208 +#define DCP_MAX_TIMEOUT 10 +#define DCP_SRAM_KEY_NB_SUBWORD 4 +#define DCP_CLK_ENABLE_MASK GENMASK_32(11, 10) + +#endif /* __LOCAL_H__ */ diff --git a/optee/optee_os/core/drivers/imx/dcp/sub.mk b/optee/optee_os/core/drivers/imx/dcp/sub.mk new file mode 100644 index 0000000..ddc13b7 --- /dev/null +++ b/optee/optee_os/core/drivers/imx/dcp/sub.mk @@ -0,0 +1,5 @@ +srcs-y += dcp_huk.c +srcs-y += dcp.c +srcs-y += dcp_utils.c + +incdirs-y += include diff --git a/optee/optee_os/core/drivers/imx/mu/imx_mu.c b/optee/optee_os/core/drivers/imx/mu/imx_mu.c new file mode 100644 index 0000000..eebef6b --- /dev/null +++ b/optee/optee_os/core/drivers/imx/mu/imx_mu.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ +#include +#include +#include +#include +#include +#include + +#include "imx_mu_platform.h" + +#define RX_TIMEOUT (100 * 1000) + +static unsigned int mu_spinlock = SPINLOCK_UNLOCK; + +__weak void imx_mu_plat_init(vaddr_t base __unused) +{ +} + +__weak TEE_Result imx_mu_plat_send(vaddr_t base __unused, + unsigned int index __unused, + uint32_t msg __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +__weak TEE_Result imx_mu_plat_receive(vaddr_t base __unused, + unsigned int index __unused, + uint32_t *msg __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +/* + * Receive a message via the MU + * + * @base: virtual base address of the MU controller + * @[out]msg: message received + */ +static TEE_Result imx_mu_receive_msg(vaddr_t base, struct imx_mu_msg *msg) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int count = 0; + uint32_t response = 0; + unsigned int nb_channel = 0; + uint64_t tout_rx = timeout_init_us(RX_TIMEOUT); + + assert(base && msg); + + do { + res = imx_mu_plat_receive(base, 0, &response); + if (timeout_elapsed(tout_rx)) + break; + } while (res == TEE_ERROR_NO_DATA); + + if (res) + return res; + + memcpy(&msg->header, &response, sizeof(response)); + + /* Check the size of the message to receive */ + if (msg->header.size > IMX_MU_MSG_SIZE) { + EMSG("Size of the message is > than IMX_MU_MSG_SIZE"); + return TEE_ERROR_BAD_FORMAT; + } + + nb_channel = imx_mu_plat_get_rx_channel(); + + for (count = 1; count < msg->header.size; count++) { + res = imx_mu_plat_receive(base, count % nb_channel, + &msg->data.u32[count - 1]); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +/* + * Send a message via the MU + * + * @base: virtual base address of the MU controller + * @[in]msg: message to send + */ +static TEE_Result imx_mu_send_msg(vaddr_t base, struct imx_mu_msg *msg) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int count = 0; + unsigned int nb_channel = 0; + uint32_t word = 0; + + assert(base && msg); + + if (msg->header.size > IMX_MU_MSG_SIZE) { + EMSG("msg->size is > than IMX_MU_MSG_SIZE"); + return TEE_ERROR_BAD_FORMAT; + } + + memcpy(&word, &msg->header, sizeof(uint32_t)); + res = imx_mu_plat_send(base, 0, word); + if (res) + return res; + + nb_channel = imx_mu_plat_get_tx_channel(); + + for (count = 1; count < msg->header.size; count++) { + res = imx_mu_plat_send(base, count % nb_channel, + msg->data.u32[count - 1]); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +void imx_mu_init(vaddr_t base) +{ + uint32_t exceptions = 0; + + if (!base) { + EMSG("Bad MU base address"); + return; + } + + exceptions = cpu_spin_lock_xsave(&mu_spinlock); + + imx_mu_plat_init(base); + + cpu_spin_unlock_xrestore(&mu_spinlock, exceptions); +} + +TEE_Result imx_mu_call(vaddr_t base, struct imx_mu_msg *msg, + bool wait_for_answer) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t exceptions = 0; + + if (!base || !msg) + return TEE_ERROR_BAD_PARAMETERS; + + exceptions = cpu_spin_lock_xsave(&mu_spinlock); + + res = imx_mu_send_msg(base, msg); + if (res == TEE_SUCCESS && wait_for_answer) + res = imx_mu_receive_msg(base, msg); + + cpu_spin_unlock_xrestore(&mu_spinlock, exceptions); + + return res; +} diff --git a/optee/optee_os/core/drivers/imx/mu/imx_mu_8q.c b/optee/optee_os/core/drivers/imx/mu/imx_mu_8q.c new file mode 100644 index 0000000..46a30e3 --- /dev/null +++ b/optee/optee_os/core/drivers/imx/mu/imx_mu_8q.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2020-2022 NXP + */ +#include +#include +#include +#include +#include + +#include "imx_mu_platform.h" + +#define MU_ATR(n) (0x0 + (n) * (4)) +#define MU_ARR(n) (0x10 + (n) * (4)) +#define MU_ASR_OFFSET 0x20 +#define MU_ACR_OFFSET 0x24 + +#define MU_SR_RF(n) SHIFT_U32(1, 27 - (n)) +#define MU_SR_TE(n) SHIFT_U32(1, 23 - (n)) + +#define MU_CR_GIE_MASK GENMASK_32(31, 28) +#define MU_CR_RIE_MASK GENMASK_32(27, 24) +#define MU_CR_TIE_MASK GENMASK_32(23, 20) +#define MU_CR_GIR_MASK GENMASK_32(19, 16) +#define MU_CR_F_MASK GENMASK_32(2, 0) + +#define MU_MAX_CHANNEL 4 + +static TEE_Result mu_wait_for(vaddr_t addr, uint32_t mask) +{ + uint64_t timeout = timeout_init_us(1000); + + while (!(io_read32(addr) & mask)) + if (timeout_elapsed(timeout)) + break; + + if (io_read32(addr) & mask) + return TEE_SUCCESS; + else + return TEE_ERROR_BUSY; + + return TEE_SUCCESS; +} + +unsigned int imx_mu_plat_get_rx_channel(void) +{ + return MU_MAX_CHANNEL; +} + +unsigned int imx_mu_plat_get_tx_channel(void) +{ + return MU_MAX_CHANNEL; +} + +void imx_mu_plat_init(vaddr_t base) +{ + io_clrbits32(base + MU_ACR_OFFSET, + MU_CR_GIE_MASK | MU_CR_RIE_MASK | MU_CR_TIE_MASK | + MU_CR_GIR_MASK | MU_CR_F_MASK); +} + +TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg) +{ + assert(index < MU_MAX_CHANNEL); + + /* Wait TX register to be empty */ + if (mu_wait_for(base + MU_ASR_OFFSET, MU_SR_TE(index))) + return TEE_ERROR_BUSY; + + /* Write message in TX register */ + io_write32(base + MU_ATR(index), msg); + + return TEE_SUCCESS; +} + +TEE_Result imx_mu_plat_receive(vaddr_t base, unsigned int index, uint32_t *msg) +{ + assert(index < MU_MAX_CHANNEL); + + /* Wait RX register to be full */ + if (mu_wait_for(base + MU_ASR_OFFSET, MU_SR_RF(index))) + return TEE_ERROR_NO_DATA; + + /* Read message in RX register */ + *msg = io_read32(base + MU_ARR(index)); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c b/optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c new file mode 100644 index 0000000..5cb559e --- /dev/null +++ b/optee/optee_os/core/drivers/imx/mu/imx_mu_8ulp.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 NXP + */ +#include +#include +#include +#include +#include + +#include "imx_mu_platform.h" + +#define MU_TCR 0x120 +#define MU_TSR 0x124 +#define MU_RCR 0x128 +#define MU_RSR 0x12C +#define MU_TR(n) (0x200 + 0x4 * (n)) +#define MU_RR(n) (0x280 + 0x4 * (n)) +#define MU_TSR_TE(n) BIT32(n) +#define MU_RSR_RF(n) BIT32(n) +#define MU_MAX_RX_CHANNEL 4 +#define MU_MAX_TX_CHANNEL 8 + +static TEE_Result mu_wait_for(vaddr_t addr, uint32_t mask) +{ + uint64_t timeout = timeout_init_us(1000); + + while (!(io_read32(addr) & mask)) + if (timeout_elapsed(timeout)) + break; + + if (io_read32(addr) & mask) + return TEE_SUCCESS; + else + return TEE_ERROR_BUSY; + + return TEE_SUCCESS; +} + +unsigned int imx_mu_plat_get_rx_channel(void) +{ + return MU_MAX_RX_CHANNEL; +} + +unsigned int imx_mu_plat_get_tx_channel(void) +{ + return MU_MAX_TX_CHANNEL; +} + +TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg) +{ + assert(index < MU_MAX_TX_CHANNEL); + + /* Wait TX register to be empty */ + if (mu_wait_for(base + MU_TSR, MU_TSR_TE(index))) + return TEE_ERROR_BUSY; + + io_write32(base + MU_TR(index), msg); + + return TEE_SUCCESS; +} + +TEE_Result imx_mu_plat_receive(vaddr_t base, unsigned int index, uint32_t *msg) +{ + assert(index < MU_MAX_RX_CHANNEL); + + /* Wait RX register to be full */ + if (mu_wait_for(base + MU_RSR, MU_RSR_RF(index))) + return TEE_ERROR_NO_DATA; + + *msg = io_read32(base + MU_RR(index)); + + return TEE_SUCCESS; +} + +void imx_mu_plat_init(vaddr_t base) +{ + /* Reset status registers */ + io_write32(base + MU_TCR, 0x0); + io_write32(base + MU_RCR, 0x0); +} diff --git a/optee/optee_os/core/drivers/imx/mu/imx_mu_platform.h b/optee/optee_os/core/drivers/imx/mu/imx_mu_platform.h new file mode 100644 index 0000000..77a573f --- /dev/null +++ b/optee/optee_os/core/drivers/imx/mu/imx_mu_platform.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 NXP + */ + +#ifndef __IMX_MU_PLATFORM_H__ +#define __IMX_MU_PLATFORM_H__ + +/* + * Return the number of reception channels + */ +unsigned int imx_mu_plat_get_rx_channel(void); + +/* + * Return the number of transmission channels + */ +unsigned int imx_mu_plat_get_tx_channel(void); + +/* + * Send a 32bits word via the MU + * + * @base: virtual base address of the MU controller + * @index: MU channel index + * @[in]msg: word to send + */ +TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg); + +/* + * Get the 32bits word received by the MU + * + * @base: virtual base address of the MU controller + * @index: MU channel index + * @[out]msg: word received + */ +TEE_Result imx_mu_plat_receive(vaddr_t base, unsigned int index, uint32_t *msg); + +/* + * Initialize the MU interface + * + * @base: virtual base address of the MU controller + */ +void imx_mu_plat_init(vaddr_t base); +#endif /* __IMX_MU_PLATFORM_H__ */ diff --git a/optee/optee_os/core/drivers/imx/mu/sub.mk b/optee/optee_os/core/drivers/imx/mu/sub.mk new file mode 100644 index 0000000..830d521 --- /dev/null +++ b/optee/optee_os/core/drivers/imx/mu/sub.mk @@ -0,0 +1,5 @@ +srcs-y += imx_mu.c +srcs-$(call cfg-one-enabled,CFG_MX8ULP CFG_MX93) += imx_mu_8ulp.c +ifeq ($(filter y, $(CFG_MX8QM) $(CFG_MX8QX)),y) +srcs-y += imx_mu_8q.c +endif diff --git a/optee/optee_os/core/drivers/imx/sub.mk b/optee/optee_os/core/drivers/imx/sub.mk new file mode 100644 index 0000000..5b4df0b --- /dev/null +++ b/optee/optee_os/core/drivers/imx/sub.mk @@ -0,0 +1,2 @@ +subdirs-$(CFG_IMX_DCP) += dcp +subdirs-$(CFG_IMX_MU) += mu \ No newline at end of file diff --git a/optee/optee_os/core/drivers/imx_caam.c b/optee/optee_os/core/drivers/imx_caam.c new file mode 100644 index 0000000..747957a --- /dev/null +++ b/optee/optee_os/core/drivers/imx_caam.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019 Bryan O'Donoghue + * Copyright 2019, 2023 NXP + * + * Bryan O'Donoghue + */ + +#include +#include +#include + +struct imx_caam_job_ring { + uint32_t jrmidr_ms; + uint32_t jrmidr_ls; +}; + +#define CAAM_NUM_JOB_RINGS 4 + +/* CAAM ownersip definition bits */ +#define JROWN_NS BIT(3) +#define JROWN_MID 0x01 + +/* A basic sub-set of the CAAM */ +struct imx_caam_ctrl { + uint32_t res0; + uint32_t mcfgr; + uint32_t res1; + uint32_t scfgr; + struct imx_caam_job_ring jr[CAAM_NUM_JOB_RINGS]; +}; + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CAAM_BASE, CORE_MMU_PGDIR_SIZE); + +static TEE_Result init_caam(void) +{ + struct imx_caam_ctrl *caam; + uint32_t reg; + int i; + + caam = (struct imx_caam_ctrl *) + core_mmu_get_va(CAAM_BASE, MEM_AREA_IO_SEC, + sizeof(struct imx_caam_ctrl)); + if (!caam) + return TEE_ERROR_GENERIC; + + /* + * Set job-ring ownership to non-secure by default. + * A Linux kernel that runs after OP-TEE will run in normal-world + * so we want to enable that kernel to have total ownership of the + * CAAM job-rings. + * + * It is possible to use CAAM job-rings inside of OP-TEE i.e. in + * secure world code but, to do that OP-TEE and kernel should agree + * via a DTB which job-rings are owned by OP-TEE and which are + * owned by Kernel, something that the OP-TEE CAAM driver should + * set up. + * + * This code below simply sets a default for the case where no + * runtime OP-TEE CAAM code will be run + */ + for (i = 0; i < CAAM_NUM_JOB_RINGS; i++) { + reg = io_read32((vaddr_t)&caam->jr[i].jrmidr_ms); + reg |= JROWN_NS | JROWN_MID; + io_write32((vaddr_t)&caam->jr[i].jrmidr_ms, reg); + } + + return TEE_SUCCESS; +} + +driver_init(init_caam); diff --git a/optee/optee_os/core/drivers/imx_csu.c b/optee/optee_os/core/drivers/imx_csu.c new file mode 100644 index 0000000..72abb6c --- /dev/null +++ b/optee/optee_os/core/drivers/imx_csu.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2019 NXP + * + */ + +#include +#include +#include +#include +#include +#include + +struct csu_setting { + int csu_index; + uint32_t value; +}; + +const struct csu_setting csu_setting_imx6[] = { + {13, 0xFF0033}, /* Protect ROMCP */ + {16, 0x330033}, /* Protect TZASC */ + {26, 0xFF0033}, /* Protect OCRAM */ + {(-1), 0}, +}; + +struct csu_sa_setting { + uint32_t access_value; + uint32_t lock_value; +}; + +struct csu_config { + const struct csu_sa_setting * const sa; + const struct csu_setting * const csl; +}; + +const struct csu_setting csu_setting_imx6ul[] = { + {13, 0xFF0033}, /* Protect ROMCP */ + {16, 0x3300FF}, /* Protect TZASC */ + {39, 0x3300FF}, /* Protect OCRAM */ + {(-1), 0}, +}; + +const struct csu_setting csu_setting_imx6ull[] = { + { 13, 0xFF0033 }, /* Protect ROMCP */ + { 16, 0x3300FF }, /* Protect TZASC */ + { 34, 0xFF0033 }, /* Protect DCP */ + { 39, 0x3300FF }, /* Protect OCRAM */ + { (-1), 0 }, +}; + +const struct csu_setting csu_setting_imx6sl[] = { + { 13, 0x3F0033 }, /* Protect DCP/ROMCP */ + { 16, 0xFF0033 }, /* Protect TZASC */ + { 26, 0xFF0033 }, /* Protect OCRAM */ + { (-1), 0 }, +}; + +const struct csu_setting csu_setting_imx6sx[] = { + {13, 0xFF0033}, /* Protect ROMCP */ + {15, 0xFF0033}, /* Protect RDC */ + {16, 0x3300FF}, /* Protect TZASC */ + {34, 0x3300FF}, /* Protect OCRAM */ + {(-1), 0}, +}; + +const struct csu_setting csu_setting_imx7ds[] = { + {14, 0x3300FF}, /* Protect RDC */ + {15, 0xFF0033}, /* Protect CSU */ + {28, 0xFF0033}, /* Protect TZASC */ + {59, 0x3300FF}, /* Protect OCRAM_S */ + {(-1), 0}, +}; + +/* Set all masters to non-secure except the Cortex-A7 */ +const struct csu_sa_setting csu_sa_imx6ul = { 0x10554550, 0x20aa8aa2 }; +const struct csu_sa_setting csu_sa_imx7ds = { 0x15554554, 0x2aaa8aaa }; + +const struct csu_config csu_imx6 = { NULL, csu_setting_imx6 }; +const struct csu_config csu_imx6ul = { &csu_sa_imx6ul, csu_setting_imx6ul }; +const struct csu_config csu_imx6ull = { NULL, csu_setting_imx6ull }; +const struct csu_config csu_imx6sl = { NULL, csu_setting_imx6sl }; +const struct csu_config csu_imx6sx = { NULL, csu_setting_imx6sx }; +const struct csu_config csu_imx7ds = { &csu_sa_imx7ds, csu_setting_imx7ds }; + +static void rngb_configure(vaddr_t csu_base) +{ + int csu_index = 0; + + if (soc_is_imx6sl() || soc_is_imx6sll()) + csu_index = 16; + else if (soc_is_imx6ull()) + csu_index = 34; + else + return; + + /* Protect RNGB */ + io_mask32(csu_base + csu_index * 4, 0x330000, 0xFF0000); +} + +static TEE_Result csu_init(void) +{ + vaddr_t csu_base; + vaddr_t offset; + const struct csu_config *csu_config = NULL; + const struct csu_setting *csu_setting = NULL; + + csu_base = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, 1); + if (!csu_base) + panic(); + + if (soc_is_imx6sx()) + csu_config = &csu_imx6sx; + else if (soc_is_imx6ul()) + csu_config = &csu_imx6ul; + else if (soc_is_imx6ull()) + csu_config = &csu_imx6ull; + else if (soc_is_imx6sll() || soc_is_imx6sl()) + csu_config = &csu_imx6sl; + else if (soc_is_imx6()) + csu_config = &csu_imx6; + else if (soc_is_imx7ds()) + csu_config = &csu_imx7ds; + else + return TEE_SUCCESS; + + /* first grant all peripherals */ + for (offset = CSU_CSL_START; offset < CSU_CSL_END; offset += 4) + io_write32(csu_base + offset, CSU_ACCESS_ALL); + + csu_setting = csu_config->csl; + + while (csu_setting->csu_index >= 0) { + io_write32(csu_base + (csu_setting->csu_index * 4), + csu_setting->value); + + csu_setting++; + } + + if (IS_ENABLED(CFG_IMX_RNGB)) + rngb_configure(csu_base); + + /* lock the settings */ + for (offset = CSU_CSL_START; offset < CSU_CSL_END; offset += 4) { + io_write32(csu_base + offset, + io_read32(csu_base + offset) | CSU_SETTING_LOCK); + } + + if (csu_config->sa) { + io_write32(csu_base + CSU_SA, csu_config->sa->access_value); + io_setbits32(csu_base + CSU_SA, csu_config->sa->lock_value); + } + + return TEE_SUCCESS; +} + +driver_init(csu_init); diff --git a/optee/optee_os/core/drivers/imx_ele.c b/optee/optee_os/core/drivers/imx_ele.c new file mode 100644 index 0000000..d85f693 --- /dev/null +++ b/optee/optee_os/core/drivers/imx_ele.c @@ -0,0 +1,547 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022-2023 NXP + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ELE_BASE_ADDR MU_BASE +#define ELE_BASE_SIZE MU_SIZE + +#define ELE_VERSION_BASELINE 0x06 +#define ELE_VERSION_HSM 0x07 +#define ELE_COMMAND_SUCCEED 0xd6 +#define ELE_REQUEST_TAG 0x17 +#define ELE_RESPONSE_TAG 0xe1 + +#define ELE_CMD_SESSION_OPEN 0x10 +#define ELE_CMD_SESSION_CLOSE 0x11 +#define ELE_CMD_SESSION_DEVICE_INFO 0x16 +#define ELE_CMD_RNG_GET 0x22 +#define ELE_CMD_TRNG_STATE 0xA4 +#define ELE_CMD_GET_INFO 0xDA +#define ELE_CMD_DERIVE_KEY 0xA9 + +#define IMX_ELE_TRNG_STATUS_READY 0x3 + +#define ELE_MU_ID 0x2 +#define ELE_MU_IRQ 0x0 + +#if defined(CFG_MX8ULP) +#define ELE_MU_DID 0x7 +#define CACHELINE_SIZE 64 +#elif defined(CFG_MX93) +#define ELE_MU_DID 0x3 +#define CACHELINE_SIZE 64 +#else +#error "Platform DID is not defined" +#endif + +#define SIZE_MSG_32(_msg) size_msg_32(sizeof(_msg)) + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, ELE_BASE_ADDR, ELE_BASE_SIZE); + +struct get_info_msg_rsp { + uint32_t rsp_code; + uint16_t soc_id; + uint16_t soc_rev; + uint16_t lifecycle; + uint16_t sssm_state; + uint32_t uid[4]; + uint32_t sha256_rom_patch[8]; + uint32_t sha256_fw[8]; +} __packed; + +struct session_get_device_info_rsp { + uint32_t rsp_code; + uint32_t user_sab_id; + uint32_t chip_uid[4]; + uint16_t chip_life_cycle; + uint16_t chip_monotonic_counter; + uint32_t ele_version; + uint32_t ele_version_ext; + uint8_t fips_mode; + uint8_t reserved[3]; + uint32_t crc; +} __packed; + +struct response_code { + uint8_t status; + uint8_t rating; + uint16_t rating_extension; +} __packed; + +/* + * Print ELE response status and rating + * + * @rsp response code structure + */ +static void print_rsp_code(struct response_code rsp __maybe_unused) +{ + DMSG("Response status %#"PRIx8", rating %#"PRIx8" (ext %#"PRIx16")", + rsp.status, rsp.rating, rsp.rating_extension); +} + +/* + * Print ELE message header + * + * @hdr message header + */ +static void print_msg_header(struct imx_mu_msg_header hdr __maybe_unused) +{ + DMSG("Header ver %#"PRIx8", size %"PRId8", tag %#"PRIx8", cmd %#"PRIx8, + hdr.version, hdr.size, hdr.tag, hdr.command); +} + +/* + * Print full ELE message content + * + * @msg message + */ +static void dump_message(const struct imx_mu_msg *msg __maybe_unused) +{ + size_t i = 0; + size_t size __maybe_unused = msg->header.size; + uint32_t *data __maybe_unused = (uint32_t *)msg; + + DMSG("Dump of message %p(%zu)", data, size); + for (i = 0; i < size; i++) + DMSG("word %zu: %#"PRIx32, i, data[i]); +} + +/* + * Return the number of 32 bits words of the given message. + * + * @cmd command size in byte + */ +static size_t size_msg_32(size_t cmd) +{ + /* Roundup and add header size */ + return ROUNDUP_DIV(cmd, sizeof(uint32_t)) + 1; +} + +/* + * The CRC for the message is computed xor-ing all the words of the message: + * the header and all the words except the word storing the CRC. + * + * @msg MU message to hash + */ +static uint32_t compute_crc(const struct imx_mu_msg *msg) +{ + uint32_t crc = 0; + uint8_t i = 0; + uint32_t *payload = (uint32_t *)msg; + + assert(msg); + + for (i = 0; i < msg->header.size - 1; i++) + crc ^= payload[i]; + + return crc; +} + +/* + * Compute message CRC and update CRC in message header. + * + * @msg MU message to hash + */ +static void update_crc(struct imx_mu_msg *msg) +{ + assert(msg); + /* + * The CRC field is the last element of array. The size of the header + * is also subtracted from CRC computation. + */ + msg->data.u32[msg->header.size - 2] = compute_crc(msg); +} + +/* + * Return the given MU base address, depending on the MMU state. + * + * @pa MU physical base address + * @sz MU size + */ +static vaddr_t imx_ele_init(paddr_t pa, size_t sz) +{ + static bool is_initialized; + vaddr_t va = 0; + + assert(pa && sz); + + if (cpu_mmu_enabled()) + va = core_mmu_get_va(pa, MEM_AREA_IO_SEC, sz); + else + va = (vaddr_t)pa; + + if (!is_initialized) { + imx_mu_init(va); + is_initialized = true; + } + + return va; +} + +/* + * Extract response codes from the given word + * + * @word 32 bits word MU response + */ +static struct response_code get_response_code(uint32_t word) +{ + struct response_code rsp = { + .rating_extension = (word & GENMASK_32(31, 16)) >> 16, + .rating = (word & GENMASK_32(15, 8)) >> 8, + .status = (word & GENMASK_32(7, 0)) >> 0, + }; + + return rsp; +} + +/* + * Initiate a communication with the EdgeLock Enclave. It sends a message + * and expects an answer. + * + * @msg MU message + */ +static TEE_Result imx_ele_call(struct imx_mu_msg *msg) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct response_code rsp = { }; + vaddr_t va = 0; + + assert(msg); + + if (msg->header.tag != ELE_REQUEST_TAG) { + EMSG("Request has invalid tag: %#"PRIx8" instead of %#"PRIx8, + msg->header.tag, ELE_REQUEST_TAG); + return TEE_ERROR_BAD_PARAMETERS; + } + + va = imx_ele_init(ELE_BASE_ADDR, ELE_BASE_SIZE); + if (!va) { + EMSG("Fail to get base address"); + return TEE_ERROR_GENERIC; + } + + res = imx_mu_call(va, msg, true); + if (res) { + EMSG("Failed to transmit message: %#"PRIx32, res); + print_msg_header(msg->header); + dump_message(msg); + return res; + } + + rsp = get_response_code(msg->data.u32[0]); + + if (msg->header.tag != ELE_RESPONSE_TAG) { + EMSG("Response has invalid tag: %#"PRIx8" instead of %#"PRIx8, + msg->header.tag, ELE_RESPONSE_TAG); + print_msg_header(msg->header); + return TEE_ERROR_GENERIC; + } + + if (rsp.status != ELE_COMMAND_SUCCEED) { + EMSG("Command has failed"); + print_rsp_code(rsp); + return TEE_ERROR_GENERIC; + } + + /* The rating can be different in success and failing cases */ + if (rsp.rating != 0) { + EMSG("Command has invalid rating: %#"PRIx8, rsp.rating); + print_rsp_code(rsp); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +/* + * Get device information from EdgeLock Enclave + * + * @session_handle EdgeLock Enclave session handle + * @rsp Device info + */ +static TEE_Result +imx_ele_session_get_device_info(uint32_t session_handle, + struct session_get_device_info_rsp *rsp) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct session_get_device_info_cmd { + uint32_t session_handle; + } cmd = { + .session_handle = session_handle, + }; + struct imx_mu_msg msg = { + .header.version = ELE_VERSION_HSM, + .header.size = SIZE_MSG_32(cmd), + .header.tag = ELE_REQUEST_TAG, + .header.command = ELE_CMD_SESSION_DEVICE_INFO, + }; + + assert(rsp); + + memcpy(msg.data.u8, &cmd, sizeof(cmd)); + + res = imx_ele_call(&msg); + if (res) + return res; + + memcpy(rsp, msg.data.u32, sizeof(*rsp)); + + if (compute_crc(&msg) != rsp->crc) + return TEE_ERROR_CORRUPT_OBJECT; + + return TEE_SUCCESS; +} + +/* + * Open a session with EdgeLock Enclave. It returns a session handle. + * + * @session_handle EdgeLock Enclave session handle + */ +static TEE_Result imx_ele_session_open(uint32_t *session_handle) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct open_session_cmd { + uint8_t mu_id; + uint8_t interrupt_num; + uint8_t tz; + uint8_t did; + uint8_t priority; + uint8_t op_mode; + uint16_t reserved; + } __packed cmd = { + .mu_id = ELE_MU_ID, + .interrupt_num = ELE_MU_IRQ, + .tz = 0, + .did = ELE_MU_DID, + .priority = 0, + .op_mode = 0, + .reserved = 0, + }; + struct open_session_rsp { + uint32_t rsp_code; + uint32_t session_handle; + } rsp = { }; + struct imx_mu_msg msg = { + .header.version = ELE_VERSION_HSM, + .header.size = SIZE_MSG_32(cmd), + .header.tag = ELE_REQUEST_TAG, + .header.command = ELE_CMD_SESSION_OPEN, + }; + + assert(session_handle); + + memcpy(msg.data.u8, &cmd, sizeof(cmd)); + + res = imx_ele_call(&msg); + if (res) + return res; + + memcpy(&rsp, msg.data.u8, sizeof(rsp)); + + *session_handle = rsp.session_handle; + + return TEE_SUCCESS; +} + +/* + * Close a session with EdgeLock Enclave. + * + * @session_handle EdgeLock Enclave session handle + */ +static TEE_Result imx_ele_session_close(uint32_t session_handle) +{ + struct close_session_cmd { + uint32_t session_handle; + } cmd = { + .session_handle = session_handle, + }; + struct imx_mu_msg msg = { + .header.version = ELE_VERSION_HSM, + .header.size = SIZE_MSG_32(cmd), + .header.tag = ELE_REQUEST_TAG, + .header.command = ELE_CMD_SESSION_CLOSE, + }; + + memcpy(msg.data.u8, &cmd, sizeof(cmd)); + + return imx_ele_call(&msg); +} + +/* + * Get the current state of the ELE TRNG + */ +static TEE_Result imx_ele_rng_get_trng_state(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct rng_get_trng_state_msg_rsp { + uint32_t rsp_code; + uint8_t trng_state; + uint8_t csal_state; + } __packed rsp = { }; + struct imx_mu_msg msg = { + .header.version = ELE_VERSION_BASELINE, + .header.size = 1, + .header.tag = ELE_REQUEST_TAG, + .header.command = ELE_CMD_TRNG_STATE, + }; + + res = imx_ele_call(&msg); + if (res) + return res; + + memcpy(&rsp, msg.data.u8, sizeof(rsp)); + + if (rsp.trng_state != IMX_ELE_TRNG_STATUS_READY) + return TEE_ERROR_BUSY; + else + return TEE_SUCCESS; +} + +unsigned long plat_get_aslr_seed(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint64_t timeout = timeout_init_us(10 * 1000); + struct rng_get_random_cmd { + uint32_t addr_msb; + uint32_t addr_lsb; + uint32_t size; + uint32_t crc; + } cmd = { }; + struct imx_mu_msg msg = { + .header.version = ELE_VERSION_HSM, + .header.size = SIZE_MSG_32(cmd), + .header.tag = ELE_REQUEST_TAG, + .header.command = ELE_CMD_RNG_GET, + }; + unsigned long aslr __aligned(CACHELINE_SIZE) = 0; + + /* + * This function can only be called when the MMU is off. No + * virtual/physical address translation is performed, nor cache + * maintenance. + */ + assert(!cpu_mmu_enabled()); + + reg_pair_from_64((uint64_t)&aslr, &cmd.addr_msb, &cmd.addr_lsb); + cmd.size = sizeof(aslr); + + /* + * Check the current TRNG state of the ELE. The TRNG must be + * started with a command earlier in the boot to allow the TRNG + * to generate enough entropy. + */ + while (imx_ele_rng_get_trng_state() == TEE_ERROR_BUSY) + if (timeout_elapsed(timeout)) + panic("ELE RNG is busy"); + + memcpy(msg.data.u8, &cmd, sizeof(cmd)); + update_crc(&msg); + + res = imx_ele_call(&msg); + if (res) + panic("Cannot retrieve random data from ELE"); + + return aslr; +} + +int tee_otp_get_die_id(uint8_t *buffer, size_t len) +{ + uint32_t session_handle = 0; + /* + * The die ID must be cached because some board configuration prevents + * the MU to be used by OPTEE at runtime. + */ + static struct session_get_device_info_rsp rsp; + + if (rsp.rsp_code) + goto out; + + if (imx_ele_session_open(&session_handle)) + goto err; + + if (imx_ele_session_get_device_info(session_handle, &rsp)) + goto err; + + if (imx_ele_session_close(session_handle)) + goto err; + +out: + /* + * In the device info array return by the ELE, the words 2, 3, 4 and 5 + * are the device UID. + */ + memcpy(buffer, rsp.chip_uid, MIN(sizeof(rsp.chip_uid), len)); + + return 0; +err: + panic("Fail to get the device UID"); +} + +#if defined(CFG_MX93) +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + TEE_Result res = TEE_ERROR_GENERIC; + static uint8_t key[CACHELINE_SIZE] __aligned(CACHELINE_SIZE); + static bool is_fetched; + uint32_t msb = 0; + uint32_t lsb = 0; + struct key_derive_cmd { + uint32_t key_addr_msb; + uint32_t key_addr_lsb; + uint16_t key_size; + uint8_t res; + } __packed cmd = { }; + struct imx_mu_msg msg = { + .header.version = ELE_VERSION_BASELINE, + .header.size = SIZE_MSG_32(cmd), + .header.tag = ELE_REQUEST_TAG, + .header.command = ELE_CMD_DERIVE_KEY, + }; + + if (is_fetched) + goto out; + + /* + * Intermediate msb and lsb values are needed. Directly using + * key_addr_msb and key_addr_lsb might be unaligned because of the + * __packed attribute of key_derive_cmd {} + */ + reg_pair_from_64((uint64_t)virt_to_phys(key), &msb, &lsb); + + cmd.key_addr_lsb = lsb; + cmd.key_addr_msb = msb; + cmd.key_size = HW_UNIQUE_KEY_LENGTH; + + memcpy(msg.data.u8, &cmd, sizeof(cmd)); + + cache_operation(TEE_CACHEFLUSH, key, HW_UNIQUE_KEY_LENGTH); + + res = imx_ele_call(&msg); + if (res) + panic("failed to get the huk"); + + cache_operation(TEE_CACHEINVALIDATE, key, HW_UNIQUE_KEY_LENGTH); + is_fetched = true; +out: + memcpy(hwkey->data, key, + MIN(sizeof(key), (size_t)HW_UNIQUE_KEY_LENGTH)); + + return TEE_SUCCESS; +} +#endif /* CFG_MX93 */ diff --git a/optee/optee_os/core/drivers/imx_i2c.c b/optee/optee_os/core/drivers/imx_i2c.c new file mode 100644 index 0000000..8ef093b --- /dev/null +++ b/optee/optee_os/core/drivers/imx_i2c.c @@ -0,0 +1,571 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * (c) 2020 Jorge Ramirez , Foundries Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_CLK_RATE 24000000 /* Bits per second */ + +/* Utility macros (__x identifies the bus [1 .. 3]) */ +#define I2C_CFG_SCL(__x) (IOMUXC_I2C1_SCL_CFG_OFF + ((__x) - 1) * 0x8) +#define I2C_CFG_SDA(__x) (IOMUXC_I2C1_SDA_CFG_OFF + ((__x) - 1) * 0x8) +#define I2C_MUX_SCL(__x) (IOMUXC_I2C1_SCL_MUX_OFF + ((__x) - 1) * 0x8) +#define I2C_MUX_SDA(__x) (IOMUXC_I2C1_SDA_MUX_OFF + ((__x) - 1) * 0x8) +#if defined(CFG_MX8MM) || defined(CFG_MX8MQ) || defined(CFG_MX8MP) || \ + defined(CFG_MX8MN) +/* IOMUX */ +#define I2C_INP_SCL(__x) 0 /* Not implemented */ +#define I2C_INP_SDA(__x) 0 /* Not implemented */ +#define I2C_INP_VAL(__x) 0 /* Not implemented */ +#define I2C_MUX_VAL(__x) 0x010 +#define I2C_CFG_VAL(__x) 0x1c3 +/* Clock */ +#define I2C_CLK_CGRBM(__x) 0 /* Not implemented */ +#define I2C_CLK_CGR6BM(__x) 0 +#define I2C_CLK_CGR(__x) CCM_CCRG_I2C##__x +#elif defined(CFG_MX6ULL) +/* IOMUX */ +#define I2C_INP_SCL(__x) (IOMUXC_I2C1_SCL_INP_OFF + ((__x) - 1) * 0x8) +#define I2C_INP_SDA(__x) (IOMUXC_I2C1_SDA_INP_OFF + ((__x) - 1) * 0x8) +#define I2C_INP_VAL(__x) (((__x) == 1) ? 0x1 : 0x2) +#define I2C_MUX_VAL(__x) 0x012 +#define I2C_CFG_VAL(__x) 0x1b8b0 +/* Clock */ +#define I2C_CLK_CGRBM(__x) BM_CCM_CCGR2_I2C##__x##_SERIAL +#define I2C_CLK_CGR6BM(__x) BM_CCM_CCGR6_I2C##__x##_SERIAL +#define I2C_CLK_CGR(__x) (((__x) == 4) ? CCM_CCGR6 : CCM_CCGR2) +#else +#error IMX_I2C driver not supported on this platform +#endif + +#if !defined(CFG_MX8MP) +static struct io_pa_va i2c_bus[4] = { +#if !defined(CFG_DT) || defined(CFG_EXTERNAL_DTB_OVERLAY) +#if defined(I2C1_BASE) + [0] = { .pa = I2C1_BASE, }, +#endif +#if defined(I2C2_BASE) + [1] = { .pa = I2C2_BASE, }, +#endif +#if defined(I2C3_BASE) + [2] = { .pa = I2C3_BASE, }, +#endif +#if defined(I2C4_BASE) + [3] = { .pa = I2C4_BASE, }, +#endif +#endif +}; +#else +static struct io_pa_va i2c_bus[6] = { +#if !defined(CFG_DT) || defined(CFG_EXTERNAL_DTB_OVERLAY) +#if defined(I2C1_BASE) + [0] = { .pa = I2C1_BASE, }, +#endif +#if defined(I2C2_BASE) + [1] = { .pa = I2C2_BASE, }, +#endif +#if defined(I2C3_BASE) + [2] = { .pa = I2C3_BASE, }, +#endif +#if defined(I2C4_BASE) + [3] = { .pa = I2C4_BASE, }, +#endif +#if defined(I2C5_BASE) + [4] = { .pa = I2C5_BASE, }, +#endif +#if defined(I2C6_BASE) + [5] = { .pa = I2C6_BASE, }, +#endif + +#endif +}; +#endif + +static struct imx_i2c_clk { + struct io_pa_va base; + uint32_t i2c[ARRAY_SIZE(i2c_bus)]; + uint32_t cgrbm[ARRAY_SIZE(i2c_bus)]; +} i2c_clk = { + .base.pa = CCM_BASE, + .i2c = { I2C_CLK_CGR(1), I2C_CLK_CGR(2), I2C_CLK_CGR(3), I2C_CLK_CGR(4), }, + .cgrbm = { I2C_CLK_CGRBM(1), I2C_CLK_CGRBM(2), I2C_CLK_CGRBM(3), I2C_CLK_CGR6BM(4),}, +}; + +static struct imx_i2c_mux { + struct io_pa_va base; + struct imx_i2c_mux_regs { + uint32_t scl_mux; + uint32_t scl_cfg; + uint32_t scl_inp; + uint32_t sda_mux; + uint32_t sda_cfg; + uint32_t sda_inp; + } i2c[ARRAY_SIZE(i2c_bus)]; +} i2c_mux = { + .base.pa = IOMUXC_BASE, + .i2c = {{ .scl_mux = I2C_MUX_SCL(1), .scl_cfg = I2C_CFG_SCL(1), + .scl_inp = I2C_INP_SCL(1), .sda_mux = I2C_MUX_SDA(1), + .sda_cfg = I2C_CFG_SDA(1), .sda_inp = I2C_INP_SDA(1), }, + { .scl_mux = I2C_MUX_SCL(2), .scl_cfg = I2C_CFG_SCL(2), + .scl_inp = I2C_INP_SCL(2), .sda_mux = I2C_MUX_SDA(2), + .sda_cfg = I2C_CFG_SDA(2), .sda_inp = I2C_INP_SDA(2), }, + { .scl_mux = I2C_MUX_SCL(3), .scl_cfg = I2C_CFG_SCL(3), + .scl_inp = I2C_INP_SCL(3), .sda_mux = I2C_MUX_SDA(3), + .sda_cfg = I2C_CFG_SDA(3), .sda_inp = I2C_INP_SDA(3), }, + { .scl_mux = I2C_MUX_SCL(4), .scl_cfg = I2C_CFG_SCL(4), + .scl_inp = I2C_INP_SCL(4), .sda_mux = I2C_MUX_SDA(4), + .sda_cfg = I2C_CFG_SDA(4), .sda_inp = I2C_INP_SDA(4), },}, +}; + +#define I2DR 0x10 +#define I2SR 0x0C +#define I2CR 0x08 +#define IFDR 0x04 + +#define I2CR_IEN BIT(7) +#define I2CR_IIEN BIT(6) +#define I2CR_MSTA BIT(5) +#define I2CR_MTX BIT(4) +#define I2CR_TX_NO_AK BIT(3) +#define I2CR_RSTA BIT(2) + +#define I2SR_ICF BIT(7) +#define I2SR_IBB BIT(5) +#define I2SR_IAL BIT(4) +#define I2SR_IIF BIT(1) +#define I2SR_RX_NO_AK BIT(0) + +static uint8_t i2c_io_read8(uint8_t bid, uint32_t address) +{ + return io_read8(i2c_bus[bid].va + address); +} + +static void i2c_io_write8(uint8_t bid, uint32_t address, uint8_t data) +{ + return io_write8(i2c_bus[bid].va + address, data); +} + +static bool bus_is_idle(uint32_t sr) +{ + return (sr & I2SR_IBB) == 0; +} + +static bool bus_is_busy(uint32_t sr) +{ + return !bus_is_idle(sr); +} + +static bool isr_active(uint32_t sr) +{ + return (sr & I2SR_IIF) == I2SR_IIF; +} + +static struct ifdr_pair { + uint32_t divider; + uint8_t prescaler; +} ifdr_table[] = { + { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, + { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, + { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 }, + { 56, 0x29 }, { 60, 0x06 }, { 64, 0x2A }, { 72, 0x2B }, + { 80, 0x2C }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A }, + { 112, 0x2E }, { 128, 0x2F }, { 144, 0x0C }, { 160, 0x30 }, + { 192, 0x31 }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 }, + { 288, 0x10 }, { 320, 0x34 }, { 384, 0x35 }, { 448, 0x36 }, + { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x38 }, + { 768, 0x39 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B }, + { 1152, 0x18 }, { 1280, 0x3C }, { 1536, 0x3D }, { 1792, 0x3E }, + { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, + { 3072, 0x1E }, { 3840, 0x1F } +}; + +static void i2c_set_prescaler(uint8_t bid, uint32_t bps) +{ + struct ifdr_pair *p = ifdr_table; + struct ifdr_pair *q = p + ARRAY_SIZE(ifdr_table) - 1; + uint32_t div = (I2C_CLK_RATE + bps - 1) / bps; + + if (div < p->divider) + q = p; + else if (div > q->divider) + p = q; + + while (p != q) { + if (div <= p->divider) + break; + p++; + } + + i2c_io_write8(bid, IFDR, p->prescaler); +} + +static void i2c_set_bus_speed(uint8_t bid, int bps) +{ + vaddr_t addr = i2c_clk.base.va; + uint32_t val = 0; + +#if defined(CFG_MX8MM) || defined(CFG_MX8MQ) || defined(CFG_MX8MP) || \ + defined(CFG_MX8MN) + addr += CCM_CCGRx_SET(i2c_clk.i2c[bid]); + val = CCM_CCGRx_ALWAYS_ON(0); +#elif defined(CFG_MX6ULL) + addr += i2c_clk.i2c[bid]; + val = i2c_clk.cgrbm[bid] | io_read32(addr); +#else +#error IMX_I2C driver not supported on this platform +#endif + io_write32(addr, val); + i2c_set_prescaler(bid, bps); +} + +static TEE_Result i2c_sync_bus(uint8_t bid, bool (*match)(uint32_t), + uint32_t *status) +{ + uint64_t tref = timeout_init_us(100000); + uint32_t sr = 0; + + while (!timeout_elapsed(tref)) { + sr = i2c_io_read8(bid, I2SR); + if (sr & I2SR_IAL) { + EMSG("bus arbitration lost"); + i2c_io_write8(bid, I2SR, sr & ~I2SR_IAL); + return TEE_ERROR_COMMUNICATION; + } + if ((*match)(sr)) { + if (status) + *status = sr; + return TEE_SUCCESS; + } + } + + return TEE_ERROR_BUSY; +} + +static TEE_Result i2c_idle_bus(uint8_t bid) +{ + uint8_t tmp = i2c_io_read8(bid, I2CR) & ~I2CR_MSTA; + TEE_Result ret = TEE_SUCCESS; + + i2c_io_write8(bid, I2CR, tmp); + ret = i2c_sync_bus(bid, &bus_is_idle, NULL); + i2c_io_write8(bid, I2SR, 0); + + return ret; +} + +static TEE_Result i2c_write_byte(uint8_t bid, uint8_t byte) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t status = 0; + + i2c_io_write8(bid, I2DR, byte); + ret = i2c_sync_bus(bid, &isr_active, &status); + i2c_io_write8(bid, I2SR, 0); + + if (!ret && (status & I2SR_RX_NO_AK)) + return TEE_ERROR_BAD_STATE; + + return ret; +} + +static TEE_Result i2c_read_byte(uint8_t bid, uint8_t *p) +{ + TEE_Result ret = TEE_SUCCESS; + + *p = i2c_io_read8(bid, I2DR); + ret = i2c_sync_bus(bid, &isr_active, NULL); + i2c_io_write8(bid, I2SR, 0); + + return ret; +} + +static TEE_Result i2c_write_data(uint8_t bid, const uint8_t *buf, int len) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t tmp = 0; + + if (!len) + return TEE_SUCCESS; + + tmp = i2c_io_read8(bid, I2CR) | I2CR_MTX | I2CR_TX_NO_AK; + i2c_io_write8(bid, I2CR, tmp); + + while (len--) { + ret = i2c_write_byte(bid, *buf++); + if (ret) + return ret; + } + + return ret; +} + +static TEE_Result i2c_read_data(uint8_t bid, uint8_t *buf, int len) +{ + TEE_Result ret = TEE_SUCCESS; + uint8_t dummy = 0; + uint32_t tmp = 0; + + if (!len) + return TEE_SUCCESS; + + tmp = i2c_io_read8(bid, I2CR) & ~I2CR_MTX; + tmp = (len == 1) ? tmp | I2CR_TX_NO_AK : tmp & ~I2CR_TX_NO_AK; + i2c_io_write8(bid, I2CR, tmp); + i2c_io_read8(bid, I2DR); + + ret = i2c_read_byte(bid, &dummy); + if (ret) + return ret; + + /* + * A data transfer ends when the master signals a stop; for a master + * receiver to terminate a transfer it must inform the slave transmiter + * by not acknowledging the last data byte. This is done by setting the + * transmit acknowledge bit before reading the next-to-last byte. + */ + do { + if (len == 2) { + tmp = i2c_io_read8(bid, I2CR) | I2CR_TX_NO_AK; + i2c_io_write8(bid, I2CR, tmp); + } + + ret = i2c_read_byte(bid, buf++); + if (ret) + return ret; + } while (len--); + + return ret; +} + +static TEE_Result i2c_init_transfer(uint8_t bid, uint8_t chip) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t tmp = 0; + + ret = i2c_idle_bus(bid); + if (ret) + return ret; + + /* Enable the interface */ + tmp = !(i2c_io_read8(bid, I2CR) & I2CR_IEN); + if (tmp) { + i2c_io_write8(bid, I2CR, I2CR_IEN); + udelay(50); + } + i2c_io_write8(bid, I2SR, 0); + + tmp = i2c_io_read8(bid, I2CR) | I2CR_MSTA; + i2c_io_write8(bid, I2CR, tmp); + + /* Wait until the bus is active */ + ret = i2c_sync_bus(bid, &bus_is_busy, NULL); + if (ret) + return ret; + + /* Slave address on the bus */ + return i2c_write_data(bid, &chip, 1); +} + +TEE_Result imx_i2c_read(uint8_t bid, uint8_t chip, uint8_t *buf, int len) +{ + TEE_Result ret = TEE_SUCCESS; + + if (bid >= ARRAY_SIZE(i2c_bus)) + return TEE_ERROR_BAD_PARAMETERS; + + if ((len && !buf) || chip > 0x7F) + return TEE_ERROR_BAD_PARAMETERS; + + if (!i2c_bus[bid].va) + return TEE_ERROR_BAD_PARAMETERS; + + ret = i2c_init_transfer(bid, chip << 1 | BIT(0)); + if (!ret) + ret = i2c_read_data(bid, buf, len); + + if (i2c_idle_bus(bid)) + IMSG("bus not idle"); + + return ret; +} + +TEE_Result imx_i2c_write(uint8_t bid, uint8_t chip, const uint8_t *buf, int len) +{ + TEE_Result ret = TEE_SUCCESS; + + if (bid >= ARRAY_SIZE(i2c_bus)) + return TEE_ERROR_BAD_PARAMETERS; + + if ((len && !buf) || chip > 0x7F) + return TEE_ERROR_BAD_PARAMETERS; + + if (!i2c_bus[bid].va) + return TEE_ERROR_BAD_PARAMETERS; + + ret = i2c_init_transfer(bid, chip << 1); + if (!ret) + ret = i2c_write_data(bid, buf, len); + + if (i2c_idle_bus(bid)) + IMSG("bus not idle"); + + return ret; +} + +TEE_Result imx_i2c_probe(uint8_t bid, uint8_t chip) +{ + if (bid >= ARRAY_SIZE(i2c_bus)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!i2c_bus[bid].va) + return TEE_ERROR_BAD_PARAMETERS; + + if (chip > 0x7F) + return TEE_ERROR_BAD_PARAMETERS; + + return imx_i2c_write(bid, chip, NULL, 0); +} + +/* + * I2C bus initialization: configure the IOMUX and enable the clock. + * @bid: Bus ID: (0=I2C1), (1=I2C2), (2=I2C3), (3=I2C4). + * @bps: Bus baud rate, in bits per second. + */ +TEE_Result imx_i2c_init(uint8_t bid, int bps) +{ + struct imx_i2c_mux *mux = &i2c_mux; + + if (bid >= ARRAY_SIZE(i2c_bus)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!bps) + return TEE_ERROR_BAD_PARAMETERS; + + if (!i2c_bus[bid].va) + return TEE_ERROR_BAD_PARAMETERS; + + io_write32(mux->base.va + mux->i2c[bid].scl_mux, I2C_MUX_VAL(bid)); + io_write32(mux->base.va + mux->i2c[bid].scl_cfg, I2C_CFG_VAL(bid)); + if (mux->i2c[bid].scl_inp) + io_write32(mux->base.va + mux->i2c[bid].scl_inp, + I2C_INP_VAL(bid + 1)); + + io_write32(mux->base.va + mux->i2c[bid].sda_mux, I2C_MUX_VAL(bid)); + io_write32(mux->base.va + mux->i2c[bid].sda_cfg, I2C_CFG_VAL(bid)); + if (mux->i2c[bid].sda_inp) + io_write32(mux->base.va + mux->i2c[bid].sda_inp, + I2C_INP_VAL(bid + 2)); + + /* Baud rate in bits per second */ + i2c_set_bus_speed(bid, bps); + + return TEE_SUCCESS; +} + +static TEE_Result get_va(paddr_t pa, vaddr_t *va) +{ + *va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, pa, 0x10000); + if (!*va) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +#if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY) +static const char *const dt_i2c_match_table[] = { + "fsl,imx21-i2c", +}; + +static TEE_Result i2c_mapped(const char *i2c_match) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + void *fdt = get_dt(); + size_t size = 0; + size_t i = 0; + int off = 0; + + if (!fdt) + return TEE_ERROR_NOT_SUPPORTED; + + for (i = 0; i < ARRAY_SIZE(i2c_bus); i++) { + off = fdt_node_offset_by_compatible(fdt, off, i2c_match); + if (off < 0) + break; + + if (!(fdt_get_status(fdt, off) & DT_STATUS_OK_SEC)) { + EMSG("i2c%zu not enabled", i + 1); + continue; + } + + if (dt_map_dev(fdt, off, &i2c_bus[i].va, &size, + DT_MAP_AUTO) < 0) { + EMSG("i2c%zu not enabled", i + 1); + continue; + } + + i2c_bus[i].pa = virt_to_phys((void *)i2c_bus[i].va); + ret = TEE_SUCCESS; + } + + return ret; +} + +static TEE_Result i2c_map_controller(void) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t i = 0; + + for (i = 0; i < ARRAY_SIZE(dt_i2c_match_table); i++) { + ret = i2c_mapped(dt_i2c_match_table[i]); + if (!ret || ret == TEE_ERROR_NOT_SUPPORTED) + return ret; + } + + return ret; +} +#else +static TEE_Result i2c_map_controller(void) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(i2c_bus); n++) { + if (i2c_bus[n].pa) { + if (get_va(i2c_bus[n].pa, &i2c_bus[n].va)) + EMSG("i2c%zu not enabled", n + 1); + else + ret = TEE_SUCCESS; + } else { + IMSG("i2c%zu not enabled", n + 1); + } + } + + return ret; +} +#endif + +static TEE_Result i2c_init(void) +{ + if (get_va(i2c_clk.base.pa, &i2c_clk.base.va)) + return TEE_ERROR_GENERIC; + + if (get_va(i2c_mux.base.pa, &i2c_mux.base.va)) + return TEE_ERROR_GENERIC; + + return i2c_map_controller(); +} + +early_init(i2c_init); diff --git a/optee/optee_os/core/drivers/imx_lpuart.c b/optee/optee_os/core/drivers/imx_lpuart.c new file mode 100644 index 0000000..374b1f3 --- /dev/null +++ b/optee/optee_os/core/drivers/imx_lpuart.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2019 NXP + */ + +#include +#include +#include +#include +#include +#include +#include + +#define STAT 0x14 +#define DATA 0x1C +#define UART_SIZE 0x20 +#define STAT_TDRE BIT(23) +#define STAT_RDRF BIT(21) +#define STAT_OR BIT(19) + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct imx_uart_data *pd = + container_of(chip, struct imx_uart_data, chip); + + return io_pa_or_va(&pd->base, UART_SIZE); +} + +static int imx_lpuart_getchar(struct serial_chip *chip) +{ + int ch = 0; + vaddr_t base = chip_to_base(chip); + + while (io_read32(base + STAT) & STAT_RDRF) + ; + + ch = io_read32(base + DATA) & 0x3ff; + + if (io_read32(base + STAT) & STAT_OR) + io_write32(base + STAT, STAT_OR); + + return ch; +} + +static void imx_lpuart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read32(base + STAT) & STAT_TDRE)) + ; + + io_write32(base + DATA, ch); +} + +static const struct serial_ops imx_lpuart_ops = { + .getchar = imx_lpuart_getchar, + .putc = imx_lpuart_putc, +}; +DECLARE_KEEP_PAGER(imx_lpuart_ops); + +void imx_uart_init(struct imx_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &imx_lpuart_ops; + + /* + * Do nothing, debug uart(sc lpuart) shared with normal world, + * everything for uart initialization is done in bootloader. + */ +} + +#ifdef CFG_DT +static struct serial_chip *imx_lpuart_dev_alloc(void) +{ + struct imx_uart_data *pd = calloc(1, sizeof(*pd)); + + if (!pd) + return NULL; + + return &pd->chip; +} + +static int imx_lpuart_dev_init(struct serial_chip *chip, const void *fdt, + int offs, const char *parms) +{ + struct imx_uart_data *pd = + container_of(chip, struct imx_uart_data, chip); + vaddr_t vbase = 0; + paddr_t pbase = 0; + size_t size = 0; + + if (parms && parms[0]) + IMSG("imx_lpuart: device parameters ignored (%s)", parms); + + if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) + return -1; + + pbase = virt_to_phys((void *)vbase); + imx_uart_init(pd, pbase); + + return 0; +} + +static void imx_lpuart_dev_free(struct serial_chip *chip) +{ + struct imx_uart_data *pd = + container_of(chip, struct imx_uart_data, chip); + + free(pd); +} + +static const struct serial_driver imx_lpuart_driver = { + .dev_alloc = imx_lpuart_dev_alloc, + .dev_init = imx_lpuart_dev_init, + .dev_free = imx_lpuart_dev_free, +}; + +static const struct dt_device_match imx_match_table[] = { + { .compatible = "fsl,imx7ulp-lpuart" }, + { .compatible = "fsl,imx8qm-lpuart" }, + { 0 } +}; + +DEFINE_DT_DRIVER(imx_dt_driver) = { + .name = "imx_lpuart", + .type = DT_DRIVER_UART, + .match_table = imx_match_table, + .driver = &imx_lpuart_driver, +}; + +#endif /* CFG_DT */ diff --git a/optee/optee_os/core/drivers/imx_ocotp.c b/optee/optee_os/core/drivers/imx_ocotp.c new file mode 100644 index 0000000..93d0bea --- /dev/null +++ b/optee/optee_os/core/drivers/imx_ocotp.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define OCOTP_CTRL 0x0 +#define OCOTP_CTRL_ERROR BIT32(9) +#define OCOTP_CTRL_BUSY BIT32(8) + +#if defined(CFG_MX6) || defined(CFG_MX7ULP) +#define OCOTP_SHADOW_OFFSET(_b, _w) ((_b) * (0x80) + (_w) * (0x10) + 0x400) +#else +#define OCOTP_SHADOW_OFFSET(_b, _w) ((_b) * (0x40) + (_w) * (0x10) + 0x400) +#endif + +struct ocotp_instance { + unsigned char nb_banks; + unsigned char nb_words; + TEE_Result (*get_die_id)(uint64_t *ret_uid); +}; + +static vaddr_t g_base_addr; +static struct mutex fuse_read = MUTEX_INITIALIZER; +static const struct ocotp_instance *g_ocotp; + +#if defined(CFG_MX6) +static void ocotp_clock_enable(void) +{ + vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); + + io_setbits32(va + CCM_CCGR2, BM_CCM_CCGR2_OCOTP_CTRL); +} +#elif defined(CFG_MX7) +static void ocotp_clock_enable(void) +{ + vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); + + io_setbits32(va + CCM_CCGRx_SET(CCM_CLOCK_DOMAIN_OCOTP), + CCM_CCGRx_ALWAYS_ON(0)); +} +#elif defined(CFG_MX8M) +static void ocotp_clock_enable(void) +{ + vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); + + io_setbits32(va + CCM_CCGRx_SET(CCM_CCRG_OCOTP), + CCM_CCGRx_ALWAYS_ON(0)); +} +#elif defined(CFG_MX7ULP) +/* The i.MX7ULP has the OCOTP always powered on */ +static inline void ocotp_clock_enable(void) { } +#else +#error "Platform not supported" +#endif + +static TEE_Result ocotp_ctrl_wait_for(uint32_t mask) +{ + unsigned int loop = 0; + uint32_t reg = 0; + + assert(g_base_addr); + + /* 20us delay assuming the CPU clock running at 500MHz */ + for (loop = 10000; loop > 0; loop--) { + reg = io_read32(g_base_addr + OCOTP_CTRL) & mask; + if (!reg) + return TEE_SUCCESS; + dsb(); + isb(); + } + + return TEE_ERROR_BUSY; +} + +TEE_Result imx_ocotp_read(unsigned int bank, unsigned int word, uint32_t *val) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + + if (!val) + return TEE_ERROR_BAD_PARAMETERS; + + if (bank > g_ocotp->nb_banks || word > g_ocotp->nb_words) + return TEE_ERROR_BAD_PARAMETERS; + + assert(g_base_addr && g_ocotp); + + mutex_lock(&fuse_read); + + ocotp_clock_enable(); + + /* Clear error bit */ + io_clrbits32(g_base_addr + OCOTP_CTRL, OCOTP_CTRL_ERROR); + + /* Wait for busy flag to be cleared */ + ret = ocotp_ctrl_wait_for(OCOTP_CTRL_BUSY); + if (ret) { + EMSG("OCOTP is busy"); + goto out; + } + + /* Read shadow register */ + *val = io_read32(g_base_addr + OCOTP_SHADOW_OFFSET(bank, word)); + + DMSG("OCOTP Bank %d Word %d Fuse 0x%" PRIx32, bank, word, *val); +out: + mutex_unlock(&fuse_read); + + return ret; +} + +static TEE_Result ocotp_get_die_id_mx7ulp(uint64_t *ret_uid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t val = 0; + uint64_t uid = 0; + + res = imx_ocotp_read(1, 6, &val); + if (res) + goto out; + uid = val & GENMASK_32(15, 0); + + res = imx_ocotp_read(1, 5, &val); + if (res) + goto out; + uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); + + res = imx_ocotp_read(1, 4, &val); + if (res) + goto out; + uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); + + res = imx_ocotp_read(1, 3, &val); + if (res) + goto out; + uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); + +out: + if (res == TEE_SUCCESS) + *ret_uid = uid; + + return res; +} + +static TEE_Result ocotp_get_die_id_mx(uint64_t *ret_uid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t val = 0; + uint64_t uid = 0; + + res = imx_ocotp_read(0, 2, &val); + if (res) + goto out; + uid = val; + + res = imx_ocotp_read(0, 1, &val); + if (res) + goto out; + uid = SHIFT_U64(uid, 32) | val; + +out: + if (res == TEE_SUCCESS) + *ret_uid = uid; + + return res; +} + +static const struct ocotp_instance ocotp_imx6q = { + .nb_banks = 16, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +static const struct ocotp_instance ocotp_imx6sl = { + .nb_banks = 8, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +static const struct ocotp_instance ocotp_imx6sll = { + .nb_banks = 16, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +static const struct ocotp_instance ocotp_imx6sx = { + .nb_banks = 16, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +static const struct ocotp_instance ocotp_imx6ul = { + .nb_banks = 16, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +static const struct ocotp_instance ocotp_imx6ull = { + .nb_banks = 8, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +static const struct ocotp_instance ocotp_imx7d = { + .nb_banks = 8, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +static const struct ocotp_instance ocotp_imx7ulp = { + .nb_banks = 32, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx7ulp, +}; + +static const struct ocotp_instance ocotp_imx8m = { + .nb_banks = 32, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +static const struct ocotp_instance ocotp_imx8mp = { + .nb_banks = 48, + .nb_words = 8, + .get_die_id = ocotp_get_die_id_mx, +}; + +int tee_otp_get_die_id(uint8_t *buffer, size_t len) +{ + size_t max_size_uid = IMX_UID_SIZE; + uint64_t uid = 0; + + assert(buffer); + assert(g_base_addr && g_ocotp); + + if (g_ocotp->get_die_id(&uid)) + goto err; + + memcpy(buffer, &uid, MIN(max_size_uid, len)); + return 0; + +err: + EMSG("Error while getting die ID"); + return -1; +} + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, OCOTP_BASE, CORE_MMU_PGDIR_SIZE); +static TEE_Result imx_ocotp_init(void) +{ + g_base_addr = core_mmu_get_va(OCOTP_BASE, MEM_AREA_IO_SEC, OCOTP_SIZE); + if (!g_base_addr) + return TEE_ERROR_GENERIC; + + if (soc_is_imx6sdl() || soc_is_imx6dq() || soc_is_imx6dqp()) { + g_ocotp = &ocotp_imx6q; + } else if (soc_is_imx6sl()) { + g_ocotp = &ocotp_imx6sl; + } else if (soc_is_imx6sll()) { + g_ocotp = &ocotp_imx6sll; + } else if (soc_is_imx6sx()) { + g_ocotp = &ocotp_imx6sx; + } else if (soc_is_imx6ul()) { + g_ocotp = &ocotp_imx6ul; + } else if (soc_is_imx6ull()) { + g_ocotp = &ocotp_imx6ull; + } else if (soc_is_imx7ds()) { + g_ocotp = &ocotp_imx7d; + } else if (soc_is_imx7ulp()) { + g_ocotp = &ocotp_imx7ulp; + } else if (soc_is_imx8mm() || soc_is_imx8mn() || soc_is_imx8mq()) { + g_ocotp = &ocotp_imx8m; + } else if (soc_is_imx8mp()) { + g_ocotp = &ocotp_imx8mp; + } else { + g_ocotp = NULL; + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} +service_init(imx_ocotp_init); diff --git a/optee/optee_os/core/drivers/imx_rngb.c b/optee/optee_os/core/drivers/imx_rngb.c new file mode 100644 index 0000000..3b020fc --- /dev/null +++ b/optee/optee_os/core/drivers/imx_rngb.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * (c) 2021 Jorge Ramirez , Foundries Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RNG_VER 0x00 +#define RNG_CMD 0x04 +#define RNG_CR 0x08 +#define RNG_SR 0x0C +#define RNG_ESR 0x10 +#define RNG_OUT 0x14 + +#define RNG_CMD_CLR_INT BIT(4) +#define RNG_CMD_CLR_ERR BIT(5) + +#define RNG_CR_AR BIT(4) +#define RNG_CR_MASK_DONE BIT(5) +#define RNG_CR_MASK_ERROR BIT(6) + +#define RNG_SR_ST_DONE BIT(4) +#define RNG_SR_SEED_DONE BIT(5) +#define RNG_SR_ERROR BIT(16) +#define RNG_SR_FIFO_LEVEL_SHIFT 8 +#define RNG_SR_FIFO_LEVEL_MASK GENMASK_32(11, RNG_SR_FIFO_LEVEL_SHIFT) + +#define RNG_VER_TYPE_SHIFT 28 +#define RNG_VER_TYPE_MASK GENMASK_32(31, RNG_VER_TYPE_SHIFT) + +#define RNG_ESR_STATUS_STAT_ERR BIT(3) + +#define RNG_TYPE_RNGA 0 +#define RNG_TYPE_RNGB 1 +#define RNG_TYPE_RNGC 2 + +#define SEED_TIMEOUT 2000000 +#define IRQ_TIMEOUT 1000000 + +#define WORDS_IN_FIFO(__rng_sr) \ + (((__rng_sr) & RNG_SR_FIFO_LEVEL_MASK) >> RNG_SR_FIFO_LEVEL_SHIFT) + +#define RNG_TYPE(__rng_vr) \ + (((__rng_vr) & RNG_VER_TYPE_MASK) >> RNG_VER_TYPE_SHIFT) + +static struct imx_rng { + struct io_pa_va base; + size_t size; + bool ready; + uint32_t error; +} rngb = { + .base.pa = RNGB_BASE, + .size = 0x4000, +}; + +static void wait_for_irq(struct imx_rng *rng) +{ + uint64_t tref = timeout_init_us(IRQ_TIMEOUT); + uint32_t status = 0; + + do { + rng->error = io_read32(rng->base.va + RNG_ESR); + status = io_read32(rng->base.va + RNG_SR); + + if (timeout_elapsed(tref)) + panic(); + + } while ((status & (RNG_SR_SEED_DONE | RNG_SR_ST_DONE)) == 0); +} + +static void irq_clear(struct imx_rng *rng) +{ + io_setbits32(rng->base.va + RNG_CR, + RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR); + io_setbits32(rng->base.va + RNG_CMD, + RNG_CMD_CLR_INT | RNG_CMD_CLR_ERR); +} + +static void irq_unmask(struct imx_rng *rng) +{ + io_clrbits32(rng->base.va + RNG_CR, + RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR); +} + +static void rng_seed(struct imx_rng *rng) +{ + uint64_t tref = timeout_init_us(SEED_TIMEOUT); + + irq_clear(rng); + do { + irq_unmask(rng); + /* configure continuous auto-reseed */ + io_setbits32(rng->base.va + RNG_CR, RNG_CR_AR); + wait_for_irq(rng); + irq_clear(rng); + + if (timeout_elapsed(tref)) + panic(); + } while (rng->error); +} + +static TEE_Result map_controller_static(void) +{ + rngb.base.va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + rngb.base.pa, rngb.size); + if (!rngb.base.va) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +#if !defined(CFG_DT) +static TEE_Result map_controller(void) +{ + return map_controller_static(); +} +#else +static const char *const rng_match_table[] = { + "fsl,imx25-rngb", +}; + +static TEE_Result map_controller(void) +{ + void *fdt = get_dt(); + unsigned int i = 0; + int off = -1; + + if (!fdt) + return map_controller_static(); + + for (i = 0; i < ARRAY_SIZE(rng_match_table); i++) { + off = fdt_node_offset_by_compatible(fdt, 0, rng_match_table[i]); + if (off >= 0) + break; + } + + if (off < 0) + return map_controller_static(); + + if (dt_enable_secure_status(fdt, off)) + return TEE_ERROR_NOT_SUPPORTED; + + if (dt_map_dev(fdt, off, &rngb.base.va, &rngb.size, DT_MAP_AUTO) < 0) + return TEE_ERROR_NOT_SUPPORTED; + + rngb.base.pa = virt_to_phys((void *)rngb.base.va); + + return TEE_SUCCESS; +} +#endif + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + uint32_t *rngbuf = buf; + uint32_t status = 0; + uint32_t val = 0; + + if (!rngb.ready) + return TEE_ERROR_BAD_STATE; + + while (len) { + status = io_read32(rngb.base.va + RNG_SR); + if (status & RNG_SR_ERROR) + return TEE_ERROR_BAD_STATE; + + if (WORDS_IN_FIFO(status)) { + val = io_read32(rngb.base.va + RNG_OUT); + if (len > sizeof(uint32_t)) { + len = len - sizeof(uint32_t); + memcpy(rngbuf, &val, sizeof(uint32_t)); + rngbuf++; + } else { + memcpy(rngbuf, &val, len); + len = 0; + } + } + } + + return TEE_SUCCESS; +} + +void plat_rng_init(void) +{ +} + +static TEE_Result rngb_init(void) +{ + uint32_t type = 0; + + if (map_controller()) + panic(); + + type = RNG_TYPE(io_read32(rngb.base.va + RNG_VER)); + if (type != RNG_TYPE_RNGB && type != RNG_TYPE_RNGC) + panic(); + + rng_seed(&rngb); + rngb.ready = true; + + return TEE_SUCCESS; +} + +driver_init(rngb_init); diff --git a/optee/optee_os/core/drivers/imx_sc_api.c b/optee/optee_os/core/drivers/imx_sc_api.c new file mode 100644 index 0000000..5a51252 --- /dev/null +++ b/optee/optee_os/core/drivers/imx_sc_api.c @@ -0,0 +1,309 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2022 NXP + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define RNG_INIT_RETRY 100 + +#define SC_RPC_VERSION 1 +#define SC_RPC_MAX_MSG 8 + +/* Defines for struct sc_rpc_msg svc field */ +#define SC_RPC_SVC_PM 2 +#define SC_RPC_SVC_RM 3 +#define SC_RPC_SVC_SECO 9 + +/* Define for PM function calls */ +enum sc_pm_func { + SC_PM_FUNC_SET_RESOURCE_POWER_MODE = 3 +}; + +/* Defines for RM function calls */ +enum sc_rm_func { + SC_RM_FUNC_GET_PARTITION = 5, + SC_RM_FUNC_ASSIGN_RESOURCE = 8 +}; + +/* Define for SECO function calls */ +enum sc_seco_func { + SC_SECO_FUNC_START_RNG = 22 +}; + +/* Internal SCFW API error codes */ +enum sc_error { + SC_ERR_NONE = 0, /* Success */ + SC_ERR_VERSION, /* Incompatible API version */ + SC_ERR_CONFIG, /* Configuration error */ + SC_ERR_PARM, /* Bad parameter */ + SC_ERR_NOACCESS, /* Permission error (no access) */ + SC_ERR_LOCKED, /* Permission error (locked) */ + SC_ERR_UNAVAILABLE, /* Unavailable (out of resources) */ + SC_ERR_NOTFOUND, /* Not found */ + SC_ERR_NOPOWER, /* No power */ + SC_ERR_IPC, /* Generic IPC error */ + SC_ERR_BUSY, /* Resource is currently busy/active */ + SC_ERR_FAIL, /* General I/O failure */ + SC_ERR_LAST +}; + +/* RNG SECO states */ +enum sc_seco_rng_status { + SC_SECO_RNG_STAT_UNAVAILABLE = 0, + SC_SECO_RNG_STAT_INPROGRESS, + SC_SECO_RNG_STAT_READY +}; + +/* Resources IDs */ +enum sc_resource { + SC_RES_CAAM_JR1 = 500, + SC_RES_CAAM_JR2, + SC_RES_CAAM_JR3, + SC_RES_CAAM_JR1_OUT = 514, + SC_RES_CAAM_JR2_OUT, + SC_RES_CAAM_JR3_OUT, + SC_RES_CAAM_JR0 = 519, + SC_RES_CAAM_JR0_OUT, + SC_RES_LAST = 546 +}; + +/* Power modes */ +enum sc_power_mode { + SC_PM_PW_MODE_OFF = 0, + SC_PM_PW_MODE_STBY, + SC_PM_PW_MODE_LP, + SC_PM_PW_MODE_ON +}; + +static vaddr_t secure_ipc_addr; + +register_phys_mem(MEM_AREA_IO_SEC, SC_IPC_BASE_SECURE, SC_IPC_SIZE); + +/* + * Get the partition ID of secure world + * + * @partition Partition ID + */ +static TEE_Result sc_rm_get_partition(uint8_t *partition) +{ + TEE_Result res = TEE_ERROR_GENERIC; + enum sc_error err = SC_ERR_LAST; + struct imx_mu_msg msg = { + .header.version = SC_RPC_VERSION, + .header.size = 1, + .header.tag = SC_RPC_SVC_RM, + .header.command = SC_RM_FUNC_GET_PARTITION, + }; + + res = imx_mu_call(secure_ipc_addr, &msg, true); + if (res != TEE_SUCCESS) { + EMSG("Communication error"); + return res; + } + + err = msg.header.command; + if (err != SC_ERR_NONE) { + EMSG("Unable to get partition ID, sc_error: %d", err); + return TEE_ERROR_GENERIC; + } + + *partition = IMX_MU_DATA_U8(&msg, 0); + + return TEE_SUCCESS; +} + +/* + * Set the given power mode of a resource + * + * @resource ID of the resource + * @mode Power mode to apply + */ +static TEE_Result sc_pm_set_resource_power_mode(enum sc_resource resource, + enum sc_power_mode mode) +{ + TEE_Result res = TEE_ERROR_GENERIC; + enum sc_error scu_error = SC_ERR_LAST; + struct imx_mu_msg msg = { + .header.version = SC_RPC_VERSION, + .header.size = 2, + .header.tag = SC_RPC_SVC_PM, + .header.command = SC_PM_FUNC_SET_RESOURCE_POWER_MODE, + }; + + IMX_MU_DATA_U16(&msg, 0) = (uint16_t)resource; + IMX_MU_DATA_U8(&msg, 2) = (uint8_t)mode; + + res = imx_mu_call(secure_ipc_addr, &msg, true); + if (res != TEE_SUCCESS) { + EMSG("Communication error"); + return res; + } + + scu_error = msg.header.command; + if (scu_error != SC_ERR_NONE) { + EMSG("Unable to set resource power mode sc_error: %d", + scu_error); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +/* + * Assign ownership of a resource to the secure partition + * + * @resource Resource to assign + */ +static TEE_Result sc_rm_assign_resource(enum sc_resource resource) +{ + TEE_Result res = TEE_ERROR_GENERIC; + enum sc_error err = SC_ERR_LAST; + uint8_t secure_partition = 0; + struct imx_mu_msg msg = { + .header.version = SC_RPC_VERSION, + .header.size = 2, + .header.tag = SC_RPC_SVC_RM, + .header.command = SC_RM_FUNC_ASSIGN_RESOURCE, + }; + + res = sc_rm_get_partition(&secure_partition); + if (res != TEE_SUCCESS) { + EMSG("Cannot get secure partition ID"); + return res; + } + + IMX_MU_DATA_U16(&msg, 0) = (uint16_t)resource; + IMX_MU_DATA_U8(&msg, 2) = secure_partition; + + res = imx_mu_call(secure_ipc_addr, &msg, true); + if (res != TEE_SUCCESS) { + EMSG("Communication error"); + return res; + } + + err = msg.header.command; + if (err != SC_ERR_NONE) { + EMSG("Unable to assign resource, sc_error: %d", err); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +TEE_Result imx_sc_rm_enable_jr(unsigned int jr_index) +{ + TEE_Result res = TEE_ERROR_GENERIC; + enum sc_resource jr_res = SC_RES_LAST; + enum sc_resource jr_out_res = SC_RES_LAST; + + switch (jr_index) { + case 0: + jr_res = SC_RES_CAAM_JR0; + jr_out_res = SC_RES_CAAM_JR0_OUT; + break; + + case 1: + jr_res = SC_RES_CAAM_JR1; + jr_out_res = SC_RES_CAAM_JR1_OUT; + break; + + case 2: + jr_res = SC_RES_CAAM_JR2; + jr_out_res = SC_RES_CAAM_JR2_OUT; + break; + + case 3: + jr_res = SC_RES_CAAM_JR3; + jr_out_res = SC_RES_CAAM_JR3_OUT; + break; + + default: + EMSG("Wrong JR Index, should be 0, 1, 2 or 3"); + return TEE_ERROR_GENERIC; + } + + /* Assign JR resources to secure world */ + res = sc_rm_assign_resource(jr_res); + if (res != TEE_SUCCESS) { + EMSG("Assign SC_R_CAAM_JR%u resource failed", jr_index); + return res; + } + + res = sc_rm_assign_resource(jr_out_res); + if (res != TEE_SUCCESS) { + EMSG("Assign SC_R_CAAM_JR%u_OUT resource failed", jr_index); + return res; + } + + /* Power ON JR resources */ + res = sc_pm_set_resource_power_mode(jr_res, SC_PM_PW_MODE_ON); + if (res != TEE_SUCCESS) { + EMSG("POWER ON SC_R_CAAM_JR%u resource failed", jr_index); + return res; + } + + res = sc_pm_set_resource_power_mode(jr_out_res, SC_PM_PW_MODE_ON); + if (res != TEE_SUCCESS) { + EMSG("POWER ON SC_R_CAAM_JR%u_OUT resource failed", jr_index); + return res; + } + + return TEE_SUCCESS; +} + +TEE_Result imx_sc_seco_start_rng(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + enum sc_error err = SC_ERR_LAST; + enum sc_seco_rng_status status = SC_SECO_RNG_STAT_UNAVAILABLE; + unsigned int retry = 0; + struct imx_mu_msg msg = { + .header.version = SC_RPC_VERSION, + .header.size = 1, + .header.tag = SC_RPC_SVC_SECO, + .header.command = SC_SECO_FUNC_START_RNG, + }; + + for (retry = RNG_INIT_RETRY; retry; retry--) { + res = imx_mu_call(secure_ipc_addr, &msg, true); + if (res != TEE_SUCCESS) { + EMSG("Configuration error"); + return res; + } + + err = msg.header.command; + if (err != SC_ERR_NONE) { + EMSG("RNG status: %d", err); + return TEE_ERROR_GENERIC; + } + + status = IMX_MU_DATA_U32(&msg, 0); + + if (status == SC_SECO_RNG_STAT_READY) + return TEE_SUCCESS; + } + + return TEE_ERROR_GENERIC; +} + +TEE_Result imx_sc_driver_init(void) +{ + vaddr_t va = 0; + + va = core_mmu_get_va(SC_IPC_BASE_SECURE, MEM_AREA_IO_SEC, SC_IPC_SIZE); + if (!va) + return TEE_ERROR_GENERIC; + + imx_mu_init(va); + secure_ipc_addr = va; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/imx_scu.c b/optee/optee_os/core/drivers/imx_scu.c new file mode 100644 index 0000000..738a60f --- /dev/null +++ b/optee/optee_os/core/drivers/imx_scu.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2019, 2023 NXP + * + */ + +#include +#include +#include +#include +#include + +/* Invalidate all registers */ +#define SCU_INV_CTRL_INIT 0xFFFFFFFF +/* Both secure CPU access SCU */ +#define SCU_SAC_CTRL_INIT 0x0000000F +/* Both non-secure CPU access SCU, private and global timer */ +#define SCU_NSAC_CTRL_INIT 0x00000FFF + +static TEE_Result scu_init(void) +{ + vaddr_t scu_base = core_mmu_get_va(SCU_BASE, MEM_AREA_IO_SEC, + SCU_SIZE); + + if (!scu_base) + return TEE_ERROR_GENERIC; + + /* SCU config */ + io_write32(scu_base + SCU_INV_SEC, SCU_INV_CTRL_INIT); + io_write32(scu_base + SCU_SAC, SCU_SAC_CTRL_INIT); + io_write32(scu_base + SCU_NSAC, SCU_NSAC_CTRL_INIT); + + /* SCU enable */ + io_write32(scu_base + SCU_CTRL, io_read32(scu_base + SCU_CTRL) | 0x1); + + return TEE_SUCCESS; +} +driver_init(scu_init); diff --git a/optee/optee_os/core/drivers/imx_snvs.c b/optee/optee_os/core/drivers/imx_snvs.c new file mode 100644 index 0000000..53776ae --- /dev/null +++ b/optee/optee_os/core/drivers/imx_snvs.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2020 Pengutronix + * Rouven Czerwinski + * Copyright 2022 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SNVS_HPLR 0x00 +#define SNVS_HPCOMR 0x04 +#define SNVS_HPSR 0x14 +#define SNVS_LPLR 0x34 +#define SNVS_LPMKCR 0x3C + +#define HPSR_SSM_ST_MASK GENMASK_32(11, 8) +#define HPSR_SSM_ST_SHIFT 8 + +#define SNVS_HPSR_SYS_SECURITY_CFG_OFFSET 12 +#define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(14, 12) + +#define SNVS_HPSR_OTPMK_SYND GENMASK_32(24, 16) +#define SNVS_HPSR_OTPMK_ZERO BIT(27) + +#define SNVS_HPLR_MKS_SL BIT32(9) + +#define SNVS_LPLR_MKS_HL BIT32(9) + +#define SNVS_HPCOMR_MKS_EN BIT32(13) +#define SNVS_HPCOMR_NPSWA_EN BIT32(31) + +#define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0) + +enum snvs_ssm_mode { + SNVS_SSM_MODE_INIT, + SNVS_SSM_MODE_HARD_FAIL, + SNVS_SSM_MODE_SOFT_FAIL = 3, + SNVS_SSM_MODE_INIT_INTERMEDIATE = 8, + SNVS_SSM_MODE_CHECK, + SNVS_SSM_MODE_NON_SECURE = 11, + SNVS_SSM_MODE_TRUSTED = 13, + SNVS_SSM_MODE_SECURE = 15, +}; + +enum snvs_security_cfg { + SNVS_SECURITY_CFG_FAB, + SNVS_SECURITY_CFG_OPEN, + SNVS_SECURITY_CFG_CLOSED, + SNVS_SECURITY_CFG_FIELD_RETURN, +}; + +/* + * Return true if the master key is OTPMK, false otherwise. + */ +static bool is_otpmk_selected(void) +{ + uint32_t hp_mks = 0; + vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); + + hp_mks = io_read32(base + SNVS_HPCOMR); + + /* + * The master key selection might be done by the MASTER_KEY_SEL field + * of LPMKCR instead. + */ + if (hp_mks & SNVS_HPCOMR_MKS_EN) { + uint32_t lp_mks = io_read32(base + SNVS_LPMKCR); + + if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL) + return false; + } + + return true; +} + +/* + * Return true if the master key selection is locked, false otherwise. + */ +static bool is_mks_locked(void) +{ + vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); + + return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL || + io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL; +} + +/* Set the Master key to use OTPMK and lock it. */ +static void set_mks_otpmk(void) +{ + vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); + + io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN); + io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL); + io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL); + io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL); +} + +/* + * Return true if OTPMK is valid, false otherwise. + */ +static bool is_otpmk_valid(void) +{ + vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); + uint32_t status = io_read32(base + SNVS_HPSR); + + return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND)); +} + +static enum snvs_security_cfg snvs_get_security_cfg(void) +{ + uint32_t val = 0; + vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, + SNVS_SIZE); + + val = (io_read32(base + SNVS_HPSR) & SNVS_HPSR_SYS_SECURITY_CFG) >> + SNVS_HPSR_SYS_SECURITY_CFG_OFFSET; + + switch (val) { + case 0b000: + return SNVS_SECURITY_CFG_FAB; + case 0b001: + return SNVS_SECURITY_CFG_OPEN; + case 0b011: + return SNVS_SECURITY_CFG_CLOSED; + default: + return SNVS_SECURITY_CFG_FIELD_RETURN; + } +} + +bool snvs_is_device_closed(void) +{ + return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED); +} + +#ifdef CFG_RPMB_FS +static enum snvs_ssm_mode snvs_get_ssm_mode(void) +{ + vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, + SNVS_HPSR + sizeof(uint32_t)); + uint32_t val = 0; + + val = io_read32(snvs + SNVS_HPSR); + val &= HPSR_SSM_ST_MASK; + val = val >> HPSR_SSM_ST_SHIFT; + DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val); + return val; +} + +bool plat_rpmb_key_is_ready(void) +{ + enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT; + bool ssm_secure = false; + + mode = snvs_get_ssm_mode(); + ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED || + mode == SNVS_SSM_MODE_SECURE); + + /* + * On i.MX6SDL and i.MX6DQ, the security cfg always returns + * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security + * configuration for this SoC. + */ + if (soc_is_imx6sdl() || soc_is_imx6dq()) + return ssm_secure; + + return ssm_secure && snvs_is_device_closed(); +} +#endif /* CFG_RPMB_FS */ + +TEE_Result imx_snvs_set_master_otpmk(void) +{ + if (!is_otpmk_valid()) + return TEE_ERROR_BAD_STATE; + + if (is_mks_locked()) { + if (is_otpmk_selected()) + return TEE_SUCCESS; + + return TEE_ERROR_BAD_STATE; + } + + set_mks_otpmk(); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/imx_uart.c b/optee/optee_os/core/drivers/imx_uart.c new file mode 100644 index 0000000..6d7bd29 --- /dev/null +++ b/optee/optee_os/core/drivers/imx_uart.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * All rights reserved. + * Copyright 2018-2019 NXP. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +/* Register definitions */ +#define URXD 0x0 /* Receiver Register */ +#define UTXD 0x40 /* Transmitter Register */ +#define UCR1 0x80 /* Control Register 1 */ +#define UCR2 0x84 /* Control Register 2 */ +#define UCR3 0x88 /* Control Register 3 */ +#define UCR4 0x8c /* Control Register 4 */ +#define UFCR 0x90 /* FIFO Control Register */ +#define USR1 0x94 /* Status Register 1 */ +#define USR2 0x98 /* Status Register 2 */ +#define UESC 0x9c /* Escape Character Register */ +#define UTIM 0xa0 /* Escape Timer Register */ +#define UBIR 0xa4 /* BRM Incremental Register */ +#define UBMR 0xa8 /* BRM Modulator Register */ +#define UBRC 0xac /* Baud Rate Count Register */ +#define UTS 0xb4 /* UART Test Register (mx31) */ +#define USIZE 0xb8 /* UTS + sizeof(uint32_t) */ + +/* UART Control Register Bit Fields.*/ +#define URXD_CHARRDY (1<<15) +#define URXD_ERR (1<<14) +#define URXD_OVRRUN (1<<13) +#define URXD_FRMERR (1<<12) +#define URXD_BRK (1<<11) +#define URXD_PRERR (1<<10) +#define URXD_RX_DATA (0xFF) +#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ +#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ +#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ +#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ +#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ +#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ +#define UCR1_IREN (1<<7) /* Infrared interface enable */ +#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ +#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ +#define UCR1_SNDBRK (1<<4) /* Send break */ +#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ +#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ +#define UCR1_DOZE (1<<1) /* Doze */ +#define UCR1_UARTEN (1<<0) /* UART enabled */ + +#define UTS_FRCPERR (1<<13) /* Force parity error */ +#define UTS_LOOP (1<<12) /* Loop tx and rx */ +#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ +#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ +#define UTS_TXFULL (1<<4) /* TxFIFO full */ +#define UTS_RXFULL (1<<3) /* RxFIFO full */ +#define UTS_SOFTRST (1<<0) /* Software reset */ + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct imx_uart_data *pd = + container_of(chip, struct imx_uart_data, chip); + + return io_pa_or_va(&pd->base, USIZE); +} + +static void imx_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + + while (!(io_read32(base + UTS) & UTS_TXEMPTY)) + if (!(io_read32(base + UCR1) & UCR1_UARTEN)) + return; +} + +static int imx_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (io_read32(base + UTS) & UTS_RXEMPTY) + ; + + return (io_read32(base + URXD) & URXD_RX_DATA); +} + +static void imx_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + /* Wait until there's space in the TX FIFO */ + while (io_read32(base + UTS) & UTS_TXFULL) + if (!(io_read32(base + UCR1) & UCR1_UARTEN)) + return; + + io_write32(base + UTXD, ch); +} + +static const struct serial_ops imx_uart_ops = { + .flush = imx_uart_flush, + .getchar = imx_uart_getchar, + .putc = imx_uart_putc, +}; +DECLARE_KEEP_PAGER(imx_uart_ops); + +void imx_uart_init(struct imx_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &imx_uart_ops; + + /* + * Do nothing, debug uart(uart0) share with normal world, + * everything for uart0 initialization is done in bootloader. + */ +} + +#ifdef CFG_DT +static struct serial_chip *imx_uart_dev_alloc(void) +{ + struct imx_uart_data *pd = calloc(1, sizeof(*pd)); + + if (!pd) + return NULL; + + return &pd->chip; +} + +static int imx_uart_dev_init(struct serial_chip *chip, const void *fdt, + int offs, const char *parms) +{ + struct imx_uart_data *pd = + container_of(chip, struct imx_uart_data, chip); + vaddr_t vbase = 0; + paddr_t pbase = 0; + size_t size = 0; + + if (parms && parms[0]) + IMSG("imx_uart: device parameters ignored (%s)", parms); + + if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) + return -1; + + pbase = virt_to_phys((void *)vbase); + imx_uart_init(pd, pbase); + + return 0; +} + +static void imx_uart_dev_free(struct serial_chip *chip) +{ + struct imx_uart_data *pd = + container_of(chip, struct imx_uart_data, chip); + + free(pd); +} + +static const struct serial_driver imx_uart_driver = { + .dev_alloc = imx_uart_dev_alloc, + .dev_init = imx_uart_dev_init, + .dev_free = imx_uart_dev_free, +}; + +static const struct dt_device_match imx_match_table[] = { + { .compatible = "fsl,imx6q-uart" }, + { 0 } +}; + +DEFINE_DT_DRIVER(imx_dt_driver) = { + .name = "imx_uart", + .type = DT_DRIVER_UART, + .match_table = imx_match_table, + .driver = &imx_uart_driver, +}; + +#endif /* CFG_DT */ diff --git a/optee/optee_os/core/drivers/imx_wdog.c b/optee/optee_os/core/drivers/imx_wdog.c new file mode 100644 index 0000000..f1642a2 --- /dev/null +++ b/optee/optee_os/core/drivers/imx_wdog.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2019 NXP + * + * Peng Fan + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +static bool ext_reset_output __maybe_unused; +static vaddr_t wdog_base; + +void imx_wdog_restart(bool external_reset __maybe_unused) +{ + uint32_t val = 0; + + if (!wdog_base) { + EMSG("No wdog mapped\n"); + panic(); + } + +#ifdef CFG_MX7ULP + val = io_read32(wdog_base + WDOG_CS); + + io_write32(wdog_base + WDOG_CNT, UNLOCK); + /* Enable wdog */ + io_write32(wdog_base + WDOG_CS, val | WDOG_CS_EN); + + io_write32(wdog_base + WDOG_CNT, UNLOCK); + io_write32(wdog_base + WDOG_TOVAL, 1000); + io_write32(wdog_base + WDOG_CNT, REFRESH); +#else + if (external_reset && ext_reset_output) + val = 0x14; + else + val = 0x24; + + DMSG("val %x\n", val); + + io_write16(wdog_base + WDT_WCR, val); + dsb(); + + if (io_read16(wdog_base + WDT_WCR) & WDT_WCR_WDE) { + io_write16(wdog_base + WDT_WSR, WDT_SEQ1); + io_write16(wdog_base + WDT_WSR, WDT_SEQ2); + } + + io_write16(wdog_base + WDT_WCR, val); + io_write16(wdog_base + WDT_WCR, val); +#endif + + while (1) + ; +} +DECLARE_KEEP_PAGER(imx_wdog_restart); + +#if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY) +static const char * const dt_wdog_match_table[] = { + "fsl,imx21-wdt", + "fsl,imx7ulp-wdt", +}; + +static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) +{ + const char *match = NULL; + void *fdt = NULL; + vaddr_t vbase = 0; + int found_off = 0; + size_t sz = 0; + int off = 0; + int st = 0; + uint32_t i = 0; + + fdt = get_dt(); + if (!fdt) { + EMSG("No DTB\n"); + return TEE_ERROR_NOT_SUPPORTED; + } + + /* search the first usable wdog */ + for (i = 0; i < ARRAY_SIZE(dt_wdog_match_table); i++) { + match = dt_wdog_match_table[i]; + off = 0; + while (off >= 0) { + off = fdt_node_offset_by_compatible(fdt, off, match); + if (off > 0) { + st = fdt_get_status(fdt, off); + if (st & DT_STATUS_OK_SEC) { + DMSG("Wdog found at %u", off); + found_off = off; + break; + } + } + } + if (found_off) + break; + else + DMSG("%s not found in DTB", dt_wdog_match_table[i]); + } + + if (!found_off) { + EMSG("No Watchdog found in DTB\n"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + ext_reset_output = dt_have_prop(fdt, found_off, + "fsl,ext-reset-output"); + + if (dt_map_dev(fdt, found_off, &vbase, &sz, DT_MAP_AUTO) < 0) { + EMSG("Failed to map Watchdog\n"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + *wdog_vbase = vbase; + + return TEE_SUCCESS; +} +#else +register_phys_mem_pgdir(MEM_AREA_IO_SEC, WDOG_BASE, CORE_MMU_PGDIR_SIZE); +static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) +{ + *wdog_vbase = (vaddr_t)phys_to_virt(WDOG_BASE, MEM_AREA_IO_SEC, 1); +#if defined(CFG_IMX_WDOG_EXT_RESET) + ext_reset_output = true; +#endif + return TEE_SUCCESS; +} +#endif + +static TEE_Result imx_wdog_init(void) +{ + return imx_wdog_base(&wdog_base); +} +driver_init(imx_wdog_init); diff --git a/optee/optee_os/core/drivers/lpc_uart.c b/optee/optee_os/core/drivers/lpc_uart.c new file mode 100644 index 0000000..a1e9120 --- /dev/null +++ b/optee/optee_os/core/drivers/lpc_uart.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, HiSilicon Limited + */ + +#include +#include +#include +#include +#include +#include + +static paddr_t chip_to_base(struct serial_chip *chip) +{ + struct lpc_uart_data *pd = + container_of(chip, struct lpc_uart_data, chip); + + return io_pa_or_va(&pd->base, LPC_SIZE); +} + +static void lpc_byte_read(paddr_t addr, uint8_t *data) +{ + uint32_t status = 0; + uint32_t cnt = 0; + + io_write32(LPC_CMD_REG_OFFSET + addr, LPC_SINGLE_READ); + + io_write32(LPC_OP_LEN_REG_OFFSET + addr, 1); + io_write32(LPC_ADDR_REG_OFFSET + addr, UART_BASE + UART_LSR); + + io_write32(LPC_START_REG_OFFSET + addr, 1); + + status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr); + while (!(status & LPC_IRQ_ST_ON)) { + if (cnt > UART_SEND_LOOP_MAX) + return; + cnt++; + status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr); + } + + io_write32(LPC_IRQ_ST_REG_OFFSET + addr, LPC_IRQ_ST_ON); + + if (io_read32(LPC_OP_STATUS_REG_OFFSET + addr) & LPC_IRQ_ST_ON) + *data = io_read32(LPC_RDATA_REG_OFFSET + addr); +} + +static void lpc_byte_write(paddr_t addr, uint8_t data) +{ + uint32_t status = 0; + uint32_t cnt = 0; + + io_write32(LPC_CMD_REG_OFFSET + addr, LPC_SINGLE_WRITE); + io_write32(LPC_OP_LEN_REG_OFFSET + addr, 1); + io_write32(LPC_WDATA_REG_OFFSET + addr, data); + + io_write32(LPC_ADDR_REG_OFFSET + addr, UART_BASE + UART_THR); + io_write32(LPC_START_REG_OFFSET + addr, 1); + + status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr); + while (!(status & LPC_IRQ_ST_ON)) { + if (cnt > UART_SEND_LOOP_MAX) + return; + cnt++; + status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr); + } + + io_write32(LPC_IRQ_ST_REG_OFFSET + addr, LPC_IRQ_ST_ON); +} + +static void lpc_uart_core_putc(paddr_t base, int ch) +{ + uint8_t var = '\0'; + uint32_t i = 0; + + for (i = 0; i < UART_SEND_LOOP_MAX; i++) { + lpc_byte_read(base, &var); + if ((var & LPC_RADTA_LEN) == LPC_RADTA_LEN) + break; + } + + lpc_byte_write(base, ch); + + for (i = 0; i < UART_SEND_LOOP_MAX; i++) { + lpc_byte_read(base, &var); + if ((var & LPC_RADTA_LEN) == LPC_RADTA_LEN) + break; + } +} + +static void lpc_uart_putc(struct serial_chip *chip, int ch) +{ + paddr_t base = chip_to_base(chip); + + lpc_uart_core_putc(base, ch); +} + +static const struct serial_ops lpc_uart_ops = { + .putc = lpc_uart_putc, +}; +DECLARE_KEEP_PAGER(lpc_uart_ops); + +void lpc_uart_init(struct lpc_uart_data *pd, paddr_t base, + uint32_t uart_clk __unused, uint32_t baud_rate __unused) +{ + pd->base.pa = base; + pd->chip.ops = &lpc_uart_ops; +} + diff --git a/optee/optee_os/core/drivers/ls_dspi.c b/optee/optee_os/core/drivers/ls_dspi.c new file mode 100644 index 0000000..7c24e30 --- /dev/null +++ b/optee/optee_os/core/drivers/ls_dspi.c @@ -0,0 +1,608 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + * + * Driver for DSPI Controller + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SPI register offset */ +#define DSPI_MCR 0x0 /* Module Configuration Register */ +#define DSPI_TCR 0x8 /* Transfer Count Register */ +#define DSPI_CTAR0 \ + 0xC /* Clock and Transfer Attributes Register (in Master mode) */ +#define DSPI_CTAR1 \ + 0x10 /* Clock and Transfer Attributes Register (in Master mode) */ +#define DSPI_SR 0x2C /* Status Register */ +#define DSPI_RSER 0x30 /* DMA/Interrupt Request Select and Enable Register */ +#define DSPI_PUSHR 0x34 /* PUSH TX FIFO Register In Master Mode */ +#define DSPI_POPR 0x38 /* POP RX FIFO Register */ +#define DSPI_TXFR0 0x3C /* Transmit FIFO Registers */ +#define DSPI_TXFR1 0x40 /* Transmit FIFO Registers */ +#define DSPI_TXFR2 0x44 /* Transmit FIFO Registers */ +#define DSPI_TXFR3 0x48 /* Transmit FIFO Registers */ +#define DSPI_RXFR0 0x7C /* Receive FIFO Registers */ +#define DSPI_RXFR1 0x80 /* Receive FIFO Registers */ +#define DSPI_RXFR2 0x84 /* Receive FIFO Registers */ +#define DSPI_RXFR3 0x88 /* Receive FIFO Registers */ +#define DSPI_CTARE0 0x11C /* Clock and Transfer Attributes Register Extended */ +#define DSPI_CTARE1 0x120 /* Clock and Transfer Attributes Register Extended */ +#define DSPI_SREX 0x13C /* Status Register Extended */ + +/* Module configuration */ +#define DSPI_MCR_MSTR 0x80000000 /* Master/Slave Mode Select [0] */ +#define DSPI_MCR_CSCK 0x40000000 /* Continuous SCK Enable [1] */ +#define DSPI_MCR_DCONF(x) (((x) & 0x03) << 28) /* SPI Configuration [2-3] */ +#define DSPI_MCR_ROOE \ + 0x01000000 /* Receive FIFO Overflow Overwrite Enable[7] */ +#define DSPI_MCR_PCSIS(x) \ + (1 << (16 + (x))) /* Peripheral Chip Select x Inactive State [12-15] */ +#define DSPI_MCR_PCSIS_MASK (0xff << 16) +#define DSPI_MCR_MDIS 0x00004000 /* Module Disable [17] */ +#define DSPI_MCR_DTXF 0x00002000 /* Disable Transmit FIFO [18] */ +#define DSPI_MCR_DRXF 0x00001000 /* Disable Receive FIFO [19] */ +#define DSPI_MCR_CTXF 0x00000800 /* Clear TX FIFO [20] */ +#define DSPI_MCR_CRXF 0x00000400 /* Clear RX FIFO [21] */ +#define DPSI_XSPI 0x00000008 /* Extended SPI Mode [28] */ +#define DSPI_MCR_PES 0x00000002 /* Parity Error Stop [30] */ +#define DSPI_MCR_HALT 0x00000001 /* Halt [31] */ +#define DPSI_ENABLE 0x0 +#define DSPI_DISABLE 0x1 + +/* Transfer count */ +#define DSPI_TCR_SPI_TCNT(x) (((x) & 0x0000FFFF) << 16) + +/* Status */ +#define DSPI_SR_TXRXS 0x40000000 /* TX and RX Status [1] */ +#define DSPI_SR_TXCTR(x) \ + (((x) & 0x0000F000) >> 12) /* TX FIFO Counter [16-19] */ +#define DSPI_SR_RXCTR(x) \ + (((x) & 0x000000F0) >> 4) /* RX FIFO Counter [24-27] */ + +#define DSPI_DATA_8BIT SHIFT_U32(8, 0) +#define DSPI_DATA_16BIT SHIFT_U32(0xF, 0) + +#define DSPI_TFR_CONT (0x80000000) +#define DSPI_TFR_CTAS(x) (((x) & 0x07) << 12) +#define DSPI_TFR_PCS(x) (((1 << (x)) & 0x0000003f) << 16) +#define DSPI_IDLE_DATA 0x0 + +/* tx/rx data wait timeout value, unit: us */ +#define DSPI_TXRX_WAIT_TIMEOUT 1000000 + +/* Transfer Fifo */ +#define DSPI_TFR_TXDATA(x) (((x) & 0x0000FFFF)) + +/* Bit definitions and macros for DRFR */ +#define DSPI_RFR_RXDATA(x) (((x) & 0x0000FFFF)) + +/* CTAR register pre-configure mask */ +#define DSPI_CTAR_SET_MODE_MASK \ + (DSPI_CTAR_FMSZ(15) | DSPI_CTAR_PCS_SCK(3) | DSPI_CTAR_PA_SCK(3) | \ + DSPI_CTAR_P_DT(3) | DSPI_CTAR_CS_SCK(15) | DSPI_CTAR_A_SCK(15) | \ + DSPI_CTAR_A_DT(15)) + +/* SPI mode flags */ +#define SPI_CPHA BIT(0) /* clock phase */ +#define SPI_CPOL BIT(1) /* clock polarity */ +#define SPI_CS_HIGH BIT(2) /* CS active high */ +#define SPI_LSB_FIRST BIT(3) /* per-word bits-on-wire */ +#define SPI_CONT BIT(4) /* Continuous CS mode */ + +/* default SCK frequency, unit: HZ */ +#define PLATFORM_CLK 650000000 +#define DSPI_DEFAULT_SCK_FREQ 10000000 +#define DSPI_CLK_DIV 4 /* prescaler divisor */ +#define DSPI_CLK (PLATFORM_CLK / DSPI_CLK_DIV) /* DSPI clock */ +#define CS_SPEED_MAX_HZ 1000000 /* Slave max speed */ + +/* + * Calculate the divide scaler value between expected SCK frequency + * and input clk frequency + * req_pbr: pre-scaler value of baud rate for slave + * req_br: scaler value of baud rate for slave + * speed_hz: speed value of slave + * clkrate: clock value of slave + */ +static TEE_Result dspi_convert_hz_to_baud(unsigned int *req_pbr, + unsigned int *req_br, + unsigned int speed_hz, + unsigned int clkrate) +{ + /* Valid pre-scaler values for baud rate*/ + static const unsigned int pbr_val[4] = { 2, 3, 5, 7 }; + /* Valid baud rate scaler values*/ + static const unsigned int brs_val[16] = { 2, 4, 6, 8, + 16, 32, 64, 128, + 256, 512, 1024, 2048, + 4096, 8192, 16384, 32768 }; + unsigned int tmp_val = 0; + unsigned int curr_val = 0; + unsigned int i = 0; + unsigned int j = 0; + + tmp_val = clkrate / speed_hz; + + for (i = 0; i < ARRAY_SIZE(pbr_val); i++) { + for (j = 0; j < ARRAY_SIZE(brs_val); j++) { + curr_val = pbr_val[i] * brs_val[j]; + if (curr_val >= tmp_val) { + *req_pbr = i; + *req_br = j; + return TEE_SUCCESS; + } + } + } + + EMSG("Can not find valid baud rate, speed_hz is %d, ", speed_hz); + EMSG("clkrate is %d, using max prescaler value", clkrate); + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +/* + * Configure speed of slave + * dspi_data: DSPI controller chip instance + * speed: speed of slave + */ +static void dspi_setup_speed(struct ls_dspi_data *dspi_data, + unsigned int speed) +{ + TEE_Result status = TEE_ERROR_GENERIC; + unsigned int bus_setup = 0; + unsigned int bus_clock = 0; + unsigned int req_i = 0; + unsigned int req_j = 0; + + bus_clock = dspi_data->bus_clk_hz; + + DMSG("DSPI set_speed: expected SCK speed %u, bus_clk %u", speed, + bus_clock); + + bus_setup = io_read32(dspi_data->base + DSPI_CTAR0); + bus_setup &= ~(DSPI_CTAR_BRD | DSPI_CTAR_BRP(0x3) | DSPI_CTAR_BR(0xf)); + + status = dspi_convert_hz_to_baud(&req_i, &req_j, speed, bus_clock); + + /* In case of failure scenario with max speed, setting default speed */ + if (status == TEE_ERROR_ITEM_NOT_FOUND) { + speed = dspi_data->speed_hz; + status = dspi_convert_hz_to_baud(&req_i, &req_j, + speed, bus_clock); + } + + if (status == TEE_SUCCESS) { + bus_setup |= (DSPI_CTAR_BRP(req_i) | DSPI_CTAR_BR(req_j)); + io_write32(dspi_data->base + DSPI_CTAR0, bus_setup); + dspi_data->speed_hz = speed; + } else { + EMSG("Unable to set speed"); + } +} + +/* + * Transferred data to TX FIFO + * dspi_data: DSPI controller chip instance + */ +static void dspi_tx(struct ls_dspi_data *dspi_data, uint32_t ctrl, + uint16_t data) +{ + int timeout = DSPI_TXRX_WAIT_TIMEOUT; + uint32_t dspi_val_addr = dspi_data->base + DSPI_PUSHR; + uint32_t dspi_val = ctrl | data; + + /* wait for empty entries in TXFIFO or timeout */ + while (DSPI_SR_TXCTR(io_read32(dspi_data->base + DSPI_SR)) >= 4 && + timeout--) + udelay(1); + + if (timeout >= 0) + io_write32(dspi_val_addr, dspi_val); + else + EMSG("waiting timeout!"); +} + +/* + * Read data from RX FIFO + * dspi_data: DSPI controller chip instance + */ +static uint16_t dspi_rx(struct ls_dspi_data *dspi_data) +{ + int timeout = DSPI_TXRX_WAIT_TIMEOUT; + uint32_t dspi_val_addr = dspi_data->base + DSPI_POPR; + + /* wait for valid entries in RXFIFO or timeout */ + while (DSPI_SR_RXCTR(io_read32(dspi_data->base + DSPI_SR)) == 0 && + timeout--) + udelay(1); + + if (timeout >= 0) + return (uint16_t)DSPI_RFR_RXDATA(io_read32(dspi_val_addr)); + + EMSG("waiting timeout!"); + + return 0xFFFF; +} + +/* + * Transfer and Receive 8-bit data + * chip: spi_chip instance + * wdata: TX data queue + * rdata: RX data queue + * num_pkts: number of data packets + */ +static enum spi_result ls_dspi_txrx8(struct spi_chip *chip, uint8_t *wdata, + uint8_t *rdata, size_t num_pkts) +{ + uint8_t *spi_rd = NULL; + uint8_t *spi_wr = NULL; + uint32_t ctrl = 0; + struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, + chip); + unsigned int cs = data->slave_cs; + + spi_wr = wdata; + spi_rd = rdata; + + /* + * Assert PCSn signals between transfers + * select which CTAR register and slave to be used for TX + * CTAS selects which CTAR to be used, here we are using CTAR0 + * PCS (peripheral chip select) is selecting the slave. + */ + ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs); + if (data->slave_mode & SPI_CONT) + ctrl |= DSPI_TFR_CONT; + + if (data->slave_data_size_bits != 8) { + EMSG("data_size_bits should be 8, not %u", + data->slave_data_size_bits); + return SPI_ERR_CFG; + } + + while (num_pkts) { + if (wdata && rdata) { + dspi_tx(data, ctrl, *spi_wr++); + *spi_rd++ = dspi_rx(data); + } else if (wdata) { + dspi_tx(data, ctrl, *spi_wr++); + dspi_rx(data); + } else if (rdata) { + dspi_tx(data, ctrl, DSPI_IDLE_DATA); + *spi_rd++ = dspi_rx(data); + } + num_pkts = num_pkts - 1; + } + + return SPI_OK; +} + +/* + * Transfer and Receive 16-bit data + * chip: spi_chip instance + * wdata: TX data queue + * rdata: RX data queue + * num_pkts: number of data packets + */ +static enum spi_result ls_dspi_txrx16(struct spi_chip *chip, uint16_t *wdata, + uint16_t *rdata, size_t num_pkts) +{ + uint32_t ctrl = 0; + uint16_t *spi_rd = NULL; + uint16_t *spi_wr = NULL; + struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, + chip); + unsigned int cs = data->slave_cs; + + spi_wr = wdata; + spi_rd = rdata; + + /* + * Assert PCSn signals between transfers + * select which CTAR register and slave to be used for TX + * CTAS selects which CTAR to be used, here we are using CTAR0 + * PCS (peripheral chip select) is selecting the slave. + */ + ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs); + if (data->slave_mode & SPI_CONT) + ctrl |= DSPI_TFR_CONT; + + if (data->slave_data_size_bits != 16) { + EMSG("data_size_bits should be 16, not %u", + data->slave_data_size_bits); + return SPI_ERR_CFG; + } + + while (num_pkts) { + if (wdata && rdata) { + dspi_tx(data, ctrl, *spi_wr++); + *spi_rd++ = dspi_rx(data); + } else if (wdata) { + dspi_tx(data, ctrl, *spi_wr++); + dspi_rx(data); + } else if (rdata) { + dspi_tx(data, ctrl, DSPI_IDLE_DATA); + *spi_rd++ = dspi_rx(data); + } + num_pkts = num_pkts - 1; + } + + return SPI_OK; +} + +/* + * Statrt DSPI module + * chip: spi_chip instance + */ +static void ls_dspi_start(struct spi_chip *chip) +{ + struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, + chip); + + DMSG("Start DSPI Module"); + io_clrbits32(data->base + DSPI_MCR, DSPI_MCR_HALT); +} + +/* + * Stop DSPI module + * chip: spi_chip instance + */ +static void ls_dspi_end(struct spi_chip *chip) +{ + struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, + chip); + + /* De-assert PCSn if in CONT mode */ + if (data->slave_mode & SPI_CONT) { + unsigned int cs = data->slave_cs; + unsigned int ctrl = DSPI_TFR_CTAS(data->ctar_sel) | + DSPI_TFR_PCS(cs); + + /* Dummy read to deassert */ + dspi_tx(data, ctrl, DSPI_IDLE_DATA); + dspi_rx(data); + } + + DMSG("Stop DSPI Module"); + io_setbits32(data->base + DSPI_MCR, DSPI_MCR_HALT); +} + +/* + * Clear RX and TX FIFO + * dspi_data: DSPI controller chip instance + */ +void dspi_flush_fifo(struct ls_dspi_data *dspi_data) +{ + unsigned int mcr_val = 0; + + mcr_val = io_read32(dspi_data->base + DSPI_MCR); + /* flush RX and TX FIFO */ + mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF); + + io_write32(dspi_data->base + DSPI_MCR, mcr_val); +} + +/* + * Configure active state of slave + * dspi_data: DSPI controller chip instance + * cs: chip select value of slave + * state: slave mode + */ +static void dspi_set_cs_active_state(struct ls_dspi_data *dspi_data, + unsigned int cs, unsigned int state) +{ + DMSG("Set CS active state cs=%d state=%d", cs, state); + + if (state & SPI_CS_HIGH) + /* CSx inactive state is low */ + io_clrbits32(dspi_data->base + DSPI_MCR, DSPI_MCR_PCSIS(cs)); + else + /* CSx inactive state is high */ + io_setbits32(dspi_data->base + DSPI_MCR, DSPI_MCR_PCSIS(cs)); +} + +/* + * Configure transfer state of slave + * dspi_data: DSPI controller chip instance + * state: slave mode + */ +static void dspi_set_transfer_state(struct ls_dspi_data *dspi_data, + unsigned int state) +{ + unsigned int bus_setup = 0; + + DMSG("Set transfer state=%d bits=%d", state, + dspi_data->slave_data_size_bits); + + bus_setup = io_read32(dspi_data->base + DSPI_CTAR0); + bus_setup &= ~DSPI_CTAR_SET_MODE_MASK; + bus_setup |= dspi_data->ctar_val; + bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA | DSPI_CTAR_LSBFE); + + if (state & SPI_CPOL) + bus_setup |= DSPI_CTAR_CPOL; + if (state & SPI_CPHA) + bus_setup |= DSPI_CTAR_CPHA; + if (state & SPI_LSB_FIRST) + bus_setup |= DSPI_CTAR_LSBFE; + + if (dspi_data->slave_data_size_bits == 8) + bus_setup |= DSPI_CTAR_FMSZ(7); + else if (dspi_data->slave_data_size_bits == 16) + bus_setup |= DSPI_CTAR_FMSZ(15); + + if (dspi_data->ctar_sel == 0) + io_write32(dspi_data->base + DSPI_CTAR0, bus_setup); + else + io_write32(dspi_data->base + DSPI_CTAR1, bus_setup); +} + +/* + * Configure speed of slave + * dspi_data: DSPI controller chip instance + * speed_max_hz: maximum speed for slave + */ +static void dspi_set_speed(struct ls_dspi_data *dspi_data, + unsigned int speed_max_hz) +{ + dspi_setup_speed(dspi_data, speed_max_hz); +} + +/* + * Configure slave for DSPI controller + * dspi_data: DSPI controller chip instance + * cs: chip select value of slave + * speed_max_hz: maximum speed of slave + * state: slave mode + */ +static void dspi_config_slave_state(struct ls_dspi_data *dspi_data, + unsigned int cs, unsigned int speed_max_hz, + unsigned int state) +{ + unsigned int sr_val = 0; + + /* configure speed */ + dspi_set_speed(dspi_data, speed_max_hz); + + /* configure transfer state */ + dspi_set_transfer_state(dspi_data, state); + + /* configure active state of CSX */ + dspi_set_cs_active_state(dspi_data, cs, state); + + /* clear FIFO */ + dspi_flush_fifo(dspi_data); + + /* check module TX and RX status */ + sr_val = io_read32(dspi_data->base + DSPI_SR); + if ((sr_val & DSPI_SR_TXRXS) != DSPI_SR_TXRXS) + EMSG("DSPI RX/TX not ready"); +} + +/* + * Configure master for DSPI controller + * dspi_data: DSPI controller chip instance + * mcr_val: value of master configuration register + */ +static void dspi_set_master_state(struct ls_dspi_data *dspi_data, + unsigned int mcr_val) +{ + DMSG("Set master state val=0x%x", mcr_val); + io_write32(dspi_data->base + DSPI_MCR, mcr_val); +} + +/* + * Configure DSPI controller + * chip: spi_chip instance + */ +static void ls_dspi_configure(struct spi_chip *chip) +{ + struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, + chip); + unsigned int mcr_cfg_val = 0; + + mcr_cfg_val = DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK | DSPI_MCR_CRXF | + DSPI_MCR_CTXF; + + /* Configure Master */ + dspi_set_master_state(data, mcr_cfg_val); + + /* Configure DSPI slave */ + dspi_config_slave_state(data, data->slave_cs, data->slave_speed_max_hz, + data->slave_mode); +} + +/* + * Extract information for DSPI Controller from the DTB + * dspi_data: DSPI controller chip instance + */ +static TEE_Result get_info_from_device_tree(struct ls_dspi_data *dspi_data) +{ + const fdt32_t *bus_num = NULL; + const fdt32_t *chip_select_num = NULL; + size_t size = 0; + int node = 0; + vaddr_t ctrl_base = 0; + void *fdt = NULL; + + /* + * First get the DSPI Controller base address from the DTB + * if DTB present and if the DSPI Controller defined in it. + */ + fdt = get_dt(); + if (!fdt) { + EMSG("Unable to get DTB, DSPI init failed\n"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + node = 0; + while (node != -FDT_ERR_NOTFOUND) { + node = fdt_node_offset_by_compatible(fdt, node, + "fsl,lx2160a-dspi"); + if (!(fdt_get_status(fdt, node) & DT_STATUS_OK_SEC)) + continue; + + bus_num = fdt_getprop(fdt, node, "bus-num", NULL); + if (bus_num && dspi_data->slave_bus == + (unsigned int)fdt32_to_cpu(*bus_num)) { + if (dt_map_dev(fdt, node, &ctrl_base, &size, + DT_MAP_AUTO) < 0) { + EMSG("Unable to get virtual address"); + return TEE_ERROR_GENERIC; + } + break; + } + } + + dspi_data->base = ctrl_base; + dspi_data->bus_clk_hz = DSPI_CLK; + + chip_select_num = fdt_getprop(fdt, node, "spi-num-chipselects", NULL); + if (chip_select_num) + dspi_data->num_chipselect = (int)fdt32_to_cpu(*chip_select_num); + else + return TEE_ERROR_ITEM_NOT_FOUND; + + dspi_data->speed_hz = DSPI_DEFAULT_SCK_FREQ; + + return TEE_SUCCESS; +} + +static const struct spi_ops ls_dspi_ops = { + .configure = ls_dspi_configure, + .start = ls_dspi_start, + .txrx8 = ls_dspi_txrx8, + .txrx16 = ls_dspi_txrx16, + .end = ls_dspi_end, +}; +DECLARE_KEEP_PAGER(ls_dspi_ops); + +TEE_Result ls_dspi_init(struct ls_dspi_data *dspi_data) +{ + TEE_Result status = TEE_ERROR_GENERIC; + + /* + * First get the DSPI Controller base address from the DTB, + * if DTB present and if the DSPI Controller defined in it. + */ + if (dspi_data) + status = get_info_from_device_tree(dspi_data); + if (status == TEE_SUCCESS) + /* generic DSPI chip handle */ + dspi_data->chip.ops = &ls_dspi_ops; + else + EMSG("Unable to get info from device tree"); + + return status; +} diff --git a/optee/optee_os/core/drivers/ls_gpio.c b/optee/optee_os/core/drivers/ls_gpio.c new file mode 100644 index 0000000..8d348c4 --- /dev/null +++ b/optee/optee_os/core/drivers/ls_gpio.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + * + * Driver for GPIO Controller + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static const char * const gpio_controller_map[] = { + "/soc/gpio@2300000", + "/soc/gpio@2310000", + "/soc/gpio@2320000", + "/soc/gpio@2330000" +}; + +/* + * Get value from GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin from which value needs to be read + */ +static enum gpio_level gpio_get_value(struct gpio_chip *chip, + unsigned int gpio_pin) +{ + vaddr_t gpio_data_addr = 0; + uint32_t data = 0; + struct ls_gpio_chip_data *gc_data = container_of(chip, + struct ls_gpio_chip_data, + chip); + + assert(gpio_pin <= MAX_GPIO_PINS); + + gpio_data_addr = gc_data->gpio_base + GPIODAT; + data = io_read32(gpio_data_addr); + + if (data & PIN_SHIFT(gpio_pin)) + return GPIO_LEVEL_HIGH; + else + return GPIO_LEVEL_LOW; +} + +/* + * Set value for GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin to which value needs to be write + * value: value needs to be written to the pin + */ +static void gpio_set_value(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_level value) +{ + vaddr_t gpio_data_addr = 0; + struct ls_gpio_chip_data *gc_data = container_of(chip, + struct ls_gpio_chip_data, + chip); + + assert(gpio_pin <= MAX_GPIO_PINS); + + gpio_data_addr = gc_data->gpio_base + GPIODAT; + + if (value == GPIO_LEVEL_HIGH) + /* if value is high then set pin value */ + io_setbits32(gpio_data_addr, PIN_SHIFT(gpio_pin)); + else + /* if value is low then clear pin value */ + io_clrbits32(gpio_data_addr, PIN_SHIFT(gpio_pin)); +} + +/* + * Get direction from GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin from which direction needs to be read + */ +static enum gpio_dir gpio_get_direction(struct gpio_chip *chip, + unsigned int gpio_pin) +{ + vaddr_t gpio_dir_addr = 0; + uint32_t data = 0; + struct ls_gpio_chip_data *gc_data = container_of(chip, + struct ls_gpio_chip_data, + chip); + + assert(gpio_pin <= MAX_GPIO_PINS); + + gpio_dir_addr = gc_data->gpio_base + GPIODIR; + data = io_read32(gpio_dir_addr); + + if (data & PIN_SHIFT(gpio_pin)) + return GPIO_DIR_OUT; + else + return GPIO_DIR_IN; +} + +/* + * Set direction for GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin on which direction needs to be set + * direction: direction which needs to be set on pin + */ +static void gpio_set_direction(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_dir direction) +{ + vaddr_t gpio_dir_addr = 0; + struct ls_gpio_chip_data *gc_data = container_of(chip, + struct ls_gpio_chip_data, + chip); + + assert(gpio_pin <= MAX_GPIO_PINS); + + gpio_dir_addr = gc_data->gpio_base + GPIODIR; + + if (direction == GPIO_DIR_OUT) + io_setbits32(gpio_dir_addr, PIN_SHIFT(gpio_pin)); + else + io_clrbits32(gpio_dir_addr, PIN_SHIFT(gpio_pin)); +} + +/* + * Get interrupt from GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin from which interrupt value needs to be read + */ +static enum gpio_interrupt gpio_get_interrupt(struct gpio_chip *chip, + unsigned int gpio_pin) +{ + vaddr_t gpio_ier_addr = 0; + uint32_t data = 0; + struct ls_gpio_chip_data *gc_data = container_of(chip, + struct ls_gpio_chip_data, + chip); + + assert(gpio_pin <= MAX_GPIO_PINS); + + gpio_ier_addr = gc_data->gpio_base + GPIOIER; + data = io_read32(gpio_ier_addr); + + if (data & PIN_SHIFT(gpio_pin)) + return GPIO_INTERRUPT_ENABLE; + else + return GPIO_INTERRUPT_DISABLE; +} + +/* + * Set interrupt event for GPIO controller + * chip: pointer to GPIO controller chip instance + * gpio_pin: pin on which interrupt value needs to be set + * interrupt: interrupt valie which needs to be set on pin + */ +static void gpio_set_interrupt(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_interrupt interrupt) +{ + vaddr_t gpio_ier_addr = 0; + struct ls_gpio_chip_data *gc_data = container_of(chip, + struct ls_gpio_chip_data, + chip); + + assert(gpio_pin <= MAX_GPIO_PINS); + + gpio_ier_addr = gc_data->gpio_base + GPIOIER; + + if (interrupt == GPIO_INTERRUPT_ENABLE) + io_setbits32(gpio_ier_addr, PIN_SHIFT(gpio_pin)); + else + io_clrbits32(gpio_ier_addr, PIN_SHIFT(gpio_pin)); +} + +/* + * Extract information for GPIO Controller from the DTB + * gpio_data: GPIO controller chip instance + */ +static TEE_Result get_info_from_device_tree(struct ls_gpio_chip_data *gpio_data) +{ + size_t size = 0; + int node = 0; + vaddr_t ctrl_base = 0; + void *fdt = NULL; + + /* + * First get the GPIO Controller base address from the DTB + * if DTB present and if the GPIO Controller defined in it. + */ + fdt = get_embedded_dt(); + if (!fdt) { + EMSG("Unable to get the Embedded DTB, GPIO init failed\n"); + return TEE_ERROR_GENERIC; + } + + node = fdt_path_offset(fdt, gpio_controller_map + [gpio_data->gpio_controller]); + if (node > 0) { + if (dt_map_dev(fdt, node, &ctrl_base, &size, + DT_MAP_AUTO) < 0) { + EMSG("Unable to get virtual address"); + return TEE_ERROR_GENERIC; + } + } else { + EMSG("Unable to get gpio offset node"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + gpio_data->gpio_base = ctrl_base; + + return TEE_SUCCESS; +} + +static const struct gpio_ops ls_gpio_ops = { + .get_direction = gpio_get_direction, + .set_direction = gpio_set_direction, + .get_value = gpio_get_value, + .set_value = gpio_set_value, + .get_interrupt = gpio_get_interrupt, + .set_interrupt = gpio_set_interrupt, +}; +DECLARE_KEEP_PAGER(ls_gpio_ops); + +TEE_Result ls_gpio_init(struct ls_gpio_chip_data *gpio_data) +{ + TEE_Result status = TEE_ERROR_GENERIC; + + /* + * First get the GPIO Controller base address from the DTB, + * if DTB present and if the GPIO Controller defined in it. + */ + status = get_info_from_device_tree(gpio_data); + if (status == TEE_SUCCESS) { + /* set GPIO Input Buffer Enable register */ + io_setbits32(gpio_data->gpio_base + GPIOIBE, UINT32_MAX); + + /* generic GPIO chip handle */ + gpio_data->chip.ops = &ls_gpio_ops; + } else { + EMSG("Unable to get info from device tree"); + } + + return status; +} diff --git a/optee/optee_os/core/drivers/ls_i2c.c b/optee/optee_os/core/drivers/ls_i2c.c new file mode 100644 index 0000000..87d7381 --- /dev/null +++ b/optee/optee_os/core/drivers/ls_i2c.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + * + * I2C driver for I2C Controller + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char * const i2c_controller_map[] = { + "/soc/i2c@2000000", "/soc/i2c@2010000", "/soc/i2c@2020000", + "/soc/i2c@2030000", "/soc/i2c@2040000", "/soc/i2c@2050000", + "/soc/i2c@2060000", "/soc/i2c@2070000" +}; + +/* + * I2C divisor and ibfd register values when glitch filter is enabled + * In case of duplicate SCL divisor value, the ibfd value with high MUL value + * has been selected. A higher MUL value results in a lower sampling rate of + * the I2C signals. This gives the I2C module greater immunity against glitches + * in the I2C signals. + */ +static const struct i2c_clock_divisor_pair clk_div_glitch_enabled[] = { + { 34, 0x0 }, { 36, 0x1 }, { 38, 0x2 }, { 40, 0x3 }, + { 42, 0x4 }, { 44, 0x8 }, { 48, 0x9 }, { 52, 0xA }, + { 54, 0x7 }, { 56, 0xB }, { 60, 0xC }, { 64, 0x10 }, + { 68, 0x40 }, { 72, 0x41 }, { 76, 0x42 }, { 80, 0x43 }, + { 84, 0x44 }, { 88, 0x48 }, { 96, 0x49 }, { 104, 0x4A }, + { 108, 0x47 }, { 112, 0x4B }, { 120, 0x4C }, { 128, 0x50 }, + { 136, 0x80 }, { 144, 0x81 }, { 152, 0x82 }, { 160, 0x83 }, + { 168, 0x84 }, { 176, 0x88 }, { 192, 0x89 }, { 208, 0x8A }, + { 216, 0x87 }, { 224, 0x8B }, { 240, 0x8C }, { 256, 0x90 }, + { 288, 0x91 }, { 320, 0x92 }, { 336, 0x8F }, { 352, 0x93 }, + { 384, 0x98 }, { 416, 0x95 }, { 448, 0x99 }, { 480, 0x96 }, + { 512, 0x9A }, { 576, 0x9B }, { 640, 0xA0 }, { 704, 0x9D }, + { 768, 0xA1 }, { 832, 0x9E }, { 896, 0xA2 }, { 960, 0x67 }, + { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, + { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, + { 2560, 0xB0 }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, + { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, + { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, + { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } +}; + +/* + * I2C divisor and ibfd register values when glitch filter is disabled. + * In case of duplicate SCL divisor value, the ibfd value with high MUL value + * has been selected. A higher MUL value results in a lower sampling rate of + * the I2C signals. This gives the I2C module greater immunity against glitches + * in the I2C signals. + */ +static const struct i2c_clock_divisor_pair clk_div_glitch_disabled[] = { + { 20, 0x0 }, { 22, 0x1 }, { 24, 0x2 }, { 26, 0x3 }, + { 28, 0x8 }, { 30, 0x5 }, { 32, 0x9 }, { 34, 0x6 }, + { 36, 0x0A }, { 40, 0x40 }, { 44, 0x41 }, { 48, 0x42 }, + { 52, 0x43 }, { 56, 0x48 }, { 60, 0x45 }, { 64, 0x49 }, + { 68, 0x46 }, { 72, 0x4A }, { 80, 0x80 }, { 88, 0x81 }, + { 96, 0x82 }, { 104, 0x83 }, { 112, 0x88 }, { 120, 0x85 }, + { 128, 0x89 }, { 136, 0x86 }, { 144, 0x8A }, { 160, 0x8B }, + { 176, 0x8C }, { 192, 0x90 }, { 208, 0x56 }, { 224, 0x91 }, + { 240, 0x1F }, { 256, 0x92 }, { 272, 0x8F }, { 288, 0x93 }, + { 320, 0x98 }, { 352, 0x95 }, { 384, 0x99 }, { 416, 0x96 }, + { 448, 0x9A }, { 480, 0x5F }, { 512, 0x9B }, { 576, 0x9C }, + { 640, 0xA0 }, { 768, 0xA1 }, { 896, 0xA2 }, { 960, 0x9F }, + { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, + { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, + { 2560, 0xAD }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, + { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, + { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, + { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } +}; + +void i2c_reset(vaddr_t base) +{ + struct i2c_regs *regs = (struct i2c_regs *)base; + + io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); + io_setbits8((vaddr_t)®s->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF); + io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_IBIE | I2C_IBCR_DMAEN); + io_clrbits8((vaddr_t)®s->ibic, I2C_IBIC_BIIE); +} + +/* + * Get I2c Bus Frequency Divider Register value based on clock_divisor + * and if the glitch is enabled or not in I2c controller. + * base Base address of I2C controller + * clock_divisor Clock Divisor + */ +static uint8_t i2c_get_ibfd(vaddr_t base, uint16_t clock_divisor) +{ + struct i2c_regs *regs = (struct i2c_regs *)base; + const struct i2c_clock_divisor_pair *dpair = NULL; + size_t dpair_sz = 0; + unsigned int n = 0; + + if (io_read8((vaddr_t)®s->ibdbg) & I2C_IBDBG_GLFLT_EN) { + dpair = clk_div_glitch_enabled; + dpair_sz = ARRAY_SIZE(clk_div_glitch_enabled); + } else { + dpair = clk_div_glitch_disabled; + dpair_sz = ARRAY_SIZE(clk_div_glitch_disabled); + } + + for (n = 0; n < dpair_sz - 1; n++) + if (clock_divisor < dpair[n].divisor) + break; + + return dpair[n].ibfd; +} + +TEE_Result i2c_init(struct ls_i2c_data *i2c_data) +{ + struct i2c_regs *regs = NULL; + uint16_t clock_divisor = 0; + uint8_t ibfd = 0; /* I2c Bus Frequency Divider Register */ + size_t size = 0; + int node = 0; + vaddr_t ctrl_base = 0; + void *fdt = NULL; + + /* + * First get the I2C Controller base address from the DTB + * if DTB present and if the I2C Controller defined in it. + */ + fdt = get_embedded_dt(); + if (!fdt) { + EMSG("Unable to get the Embedded DTB, I2C init failed\n"); + return TEE_ERROR_GENERIC; + } + + node = fdt_path_offset(fdt, + i2c_controller_map[i2c_data->i2c_controller]); + if (node > 0) { + if (dt_map_dev(fdt, node, &ctrl_base, &size, + DT_MAP_AUTO) < 0) { + EMSG("Unable to get virtual address"); + return TEE_ERROR_GENERIC; + } + } else { + EMSG("Unable to get I2C offset node"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + i2c_data->base = ctrl_base; + + regs = (struct i2c_regs *)ctrl_base; + + clock_divisor = (i2c_data->i2c_bus_clock + i2c_data->speed - 1) / + i2c_data->speed; + ibfd = i2c_get_ibfd(ctrl_base, clock_divisor); + + io_write8((vaddr_t)®s->ibfd, ibfd); + + i2c_reset(ctrl_base); + + return TEE_SUCCESS; +} + +/* + * Check if I2C bus is busy with previous transaction or not. + * regs pointer to I2c controller registers + * test_busy this flag tells if we need to check the busy bit in IBSR reg + */ +static TEE_Result i2c_bus_test_bus_busy(struct i2c_regs *regs, bool test_busy) +{ + unsigned int n = 0; + uint8_t reg = 0; + + for (n = 0; n < I2C_NUM_RETRIES; n++) { + reg = io_read8((vaddr_t)®s->ibsr); + + if (reg & I2C_IBSR_IBAL) { + io_write8((vaddr_t)®s->ibsr, reg); + return TEE_ERROR_BUSY; + } + + if (test_busy && (reg & I2C_IBSR_IBB)) + break; + + if (!test_busy && !(reg & I2C_IBSR_IBB)) + break; + + mdelay(1); + } + + if (n == I2C_NUM_RETRIES) + return TEE_ERROR_BUSY; + + return TEE_SUCCESS; +} + +/* + * Check if data transfer to/from i2c controller is complete. + * regs pointer to I2c controller registers + * test_rx_ack this flag tells if we need to check RXAK bit in IBSR reg + */ +static TEE_Result i2c_transfer_complete(struct i2c_regs *regs, bool test_rx_ack) +{ + unsigned int n = 0; + uint8_t reg = 0; + + for (n = 0; n < I2C_NUM_RETRIES; n++) { + reg = io_read8((vaddr_t)®s->ibsr); + + if (reg & I2C_IBSR_IBIF) { + /* Write 1 to clear the IBIF field */ + io_write8((vaddr_t)®s->ibsr, reg); + break; + } + mdelay(1); + } + + if (n == I2C_NUM_RETRIES) + return TEE_ERROR_BUSY; + + if (test_rx_ack && (reg & I2C_IBSR_RXAK)) + return TEE_ERROR_NO_DATA; + + if (reg & I2C_IBSR_TCF) + return TEE_SUCCESS; + + return TEE_ERROR_GENERIC; +} + +/* + * Read data from I2c controller. + * regs pointer to I2c controller registers + * slave_address slave address from which to read + * operation pointer to i2c_operation struct + * is_last_operation if current operation is last operation + */ +static TEE_Result i2c_read(struct i2c_regs *regs, unsigned int slave_address, + struct i2c_operation *operation, + bool is_last_operation) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int n = 0; + + /* Write Slave Address */ + io_write8((vaddr_t)®s->ibdr, (slave_address << 0x1) | BIT(0)); + res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); + if (res) + return res; + + /* select Receive mode. */ + io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX); + if (operation->length_in_bytes > 1) { + /* Set No ACK = 0 */ + io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_NOACK); + } + + /* Perform a dummy read to initiate the receive operation. */ + io_read8((vaddr_t)®s->ibdr); + + for (n = 0; n < operation->length_in_bytes; n++) { + res = i2c_transfer_complete(regs, I2C_BUS_NO_TEST_RX_ACK); + if (res) + return res; + if (n == (operation->length_in_bytes - 2)) { + /* Set No ACK = 1 */ + io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_NOACK); + } else if (n == (operation->length_in_bytes - 1)) { + if (!is_last_operation) { + /* select Transmit mode (for repeat start) */ + io_setbits8((vaddr_t)®s->ibcr, + I2C_IBCR_TXRX); + } else { + /* Generate Stop Signal */ + io_clrbits8((vaddr_t)®s->ibcr, + (I2C_IBCR_MSSL | I2C_IBCR_TXRX)); + res = i2c_bus_test_bus_busy(regs, + I2C_BUS_TEST_IDLE); + if (res) + return res; + } + } + operation->buffer[n] = io_read8((vaddr_t)®s->ibdr); + } + + return TEE_SUCCESS; +} + +/* + * Write data to I2c controller + * regs pointer to I2c controller registers + * slave_address slave address from which to read + * operation pointer to i2c_operation struct + */ +static TEE_Result i2c_write(struct i2c_regs *regs, unsigned int slave_address, + struct i2c_operation *operation) +{ + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int n = 0; + + /* Write Slave Address */ + io_write8((vaddr_t)®s->ibdr, + (slave_address << 0x1) & ~(BIT(0))); + res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); + if (res) + return res; + + /* Write Data */ + for (n = 0; n < operation->length_in_bytes; n++) { + io_write8((vaddr_t)®s->ibdr, operation->buffer[n]); + res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +/* + * Generate Stop Signal and disable I2C controller. + * regs pointer to I2c controller registers + */ +static TEE_Result i2c_stop(struct i2c_regs *regs) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t reg = 0; + + reg = io_read8((vaddr_t)®s->ibsr); + if (reg & I2C_IBSR_IBB) { + /* Generate Stop Signal */ + io_clrbits8((vaddr_t)®s->ibcr, + I2C_IBCR_MSSL | I2C_IBCR_TXRX); + res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); + if (res) + return res; + } + + /* Disable I2c Controller */ + io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); + + return TEE_SUCCESS; +} + +/* + * Generate Start Signal and set I2C controller in transmit mode. + * regs pointer to I2c controller registers + */ +static TEE_Result i2c_start(struct i2c_regs *regs) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + io_setbits8((vaddr_t)®s->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF); + io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); + + /* Wait controller to be stable */ + mdelay(1); + + /* Generate Start Signal */ + io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MSSL); + res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY); + if (res) + return res; + + /* Select Transmit Mode. set No ACK = 1 */ + io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX | I2C_IBCR_NOACK); + + return TEE_SUCCESS; +} + +TEE_Result i2c_bus_xfer(vaddr_t base, unsigned int slave_address, + struct i2c_operation *i2c_operation, + unsigned int operation_count) +{ + unsigned int n = 0; + struct i2c_regs *regs = (struct i2c_regs *)base; + struct i2c_operation *operation = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + bool is_last_operation = false; + + res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); + if (res) + goto out; + + res = i2c_start(regs); + if (res) + goto out; + + for (n = 0, operation = i2c_operation; + n < operation_count; n++, operation++) { + if (n == (operation_count - 1)) + is_last_operation = true; + + /* Send repeat start after first transmit/receive */ + if (n) { + io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_RSTA); + res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY); + if (res) + goto out; + } + + /* Read/write data */ + if (operation->flags & I2C_FLAG_READ) + res = i2c_read(regs, slave_address, operation, + is_last_operation); + else + res = i2c_write(regs, slave_address, operation); + if (res) + goto out; + } + +out: + i2c_stop(regs); + + return res; +} diff --git a/optee/optee_os/core/drivers/ls_sec_mon.c b/optee/optee_os/core/drivers/ls_sec_mon.c new file mode 100644 index 0000000..f296aac --- /dev/null +++ b/optee/optee_os/core/drivers/ls_sec_mon.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microsoft + * + * Driver for the NXP LX2160A-series Security Monitor (SecMon). + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * struct ls_sec_mon_registers - Memory map of the SecMon registers. + * hplr; HP Lock Register. + * @hpcomr: HP Command Register. + * @rsvd0: Reserved. + * @hpsicr: HP Security Interrupt Control Register. + * @hpsvcr: HP Security Violation Control Register. + * @hpsr: HP Status Register. + * @hpsvsr: HP Security Violation Status Register. + * @hphacivr: HP High Assurance Counter IV Register. + * @hphacr: HP High Assurance Counter Register. + * @rsvd1[0x4]: Reserved. + * @lplr: LP Lock Register. + * @lpcr: LP Control Register. + * @lpmkcr: LP Master Key Control Register. + * @lpsvcr: LP Security Violation Control Register. + * @rsvd2: Reserved. + * @lptdcr: LP Tamper Detectors Configuration. + * @lpsr: LP Status Register. + * @rsvd3[0x3]: Reserved. + * @lpsmcmr: LP Secure Monotonic Counter MSB Register. + * @lpsmclr: LP Secure Monotonic Counter LSB Register. + * @lppgdr: LP Power Glitch Detector Register. + * @rsvd4: Reserved. + * @lpzmkr[0x8]: LP Zeroizable Master Key Registers. + * @lpgpr[0x4]: LP General Purpose Registers. + * @rsvd5[0x2d2]: Reserved. + * @hpvidr1: HP Version ID Register 1. + * @hpvidr2: HP Version ID Register 2. + */ +static struct ls_sec_mon_registers { + uint32_t hplr; /* 0x000 */ + uint32_t hpcomr; /* 0x004 */ + uint32_t rsvd0; /* 0x008 */ + uint32_t hpsicr; /* 0x00C */ + uint32_t hpsvcr; /* 0x010 */ + uint32_t hpsr; /* 0x014 */ + uint32_t hpsvsr; /* 0x018 */ + uint32_t hphacivr; /* 0x01C */ + uint32_t hphacr; /* 0x020 */ + uint32_t rsvd1[0x4]; /* 0x024 */ + uint32_t lplr; /* 0x034 */ + uint32_t lpcr; /* 0x038 */ + uint32_t lpmkcr; /* 0x03C */ + uint32_t lpsvcr; /* 0x040 */ + uint32_t rsvd2; /* 0x044 */ + uint32_t lptdcr; /* 0x048 */ + uint32_t lpsr; /* 0x04C */ + uint32_t rsvd3[0x3]; /* 0x050 */ + uint32_t lpsmcmr; /* 0x05C */ + uint32_t lpsmclr; /* 0x060 */ + uint32_t lppgdr; /* 0x064 */ + uint32_t rsvd4; /* 0x068 */ + uint32_t lpzmkr[0x8]; /* 0x06C */ + uint32_t lpgpr[0x4]; /* 0x090 */ + uint32_t rsvd5[0x2d2]; /* 0x0B0 */ + uint32_t hpvidr1; /* 0xBF8 */ + uint32_t hpvidr2; /* 0xBFC */ +} *sec_mon_regs; + +/** + * ls_sec_mon_init() - Initialize the SecMon driver and assign the sec_mon_regs + * pointer to the SecMon base address detailed in the device + * tree. + * + * Return: 0 if successful or > 0 on error. + */ +static TEE_Result ls_sec_mon_init(void) +{ + void *fdt = NULL; + size_t size = 0; + uint32_t node = 0; + vaddr_t ctrl_base = 0; + + fdt = get_embedded_dt(); + if (!fdt) { + EMSG("Unable to find the device tree"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + node = fdt_node_offset_by_compatible(fdt, node, "fsl,lx2160a-sec-mon"); + if (node <= 0) { + EMSG("Unable to find the SecMon device tree node"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (dt_map_dev(fdt, node, &ctrl_base, &size, DT_MAP_AUTO) < 0) { + EMSG("Unable to get the SecMon virtual address"); + return TEE_ERROR_GENERIC; + } + + sec_mon_regs = (struct ls_sec_mon_registers *)ctrl_base; + + return TEE_SUCCESS; +} + +TEE_Result ls_sec_mon_read(struct ls_sec_mon_data *data) +{ + if (!sec_mon_regs) { + EMSG("SecMon driver is not initialized"); + return TEE_ERROR_GENERIC; + } + + if (!data) { + EMSG("Given buffer is uninitialized"); + return TEE_ERROR_BAD_PARAMETERS; + } + + data->hplr = io_read32((vaddr_t)&sec_mon_regs->hplr); + data->hpcomr = io_read32((vaddr_t)&sec_mon_regs->hpcomr); + data->hpsicr = io_read32((vaddr_t)&sec_mon_regs->hpsicr); + data->hpsvcr = io_read32((vaddr_t)&sec_mon_regs->hpsvcr); + data->hpsr = io_read32((vaddr_t)&sec_mon_regs->hpsr); + data->hpsvsr = io_read32((vaddr_t)&sec_mon_regs->hpsvsr); + data->hphacivr = io_read32((vaddr_t)&sec_mon_regs->hphacivr); + data->hphacr = io_read32((vaddr_t)&sec_mon_regs->hphacr); + data->lplr = io_read32((vaddr_t)&sec_mon_regs->lplr); + data->lpcr = io_read32((vaddr_t)&sec_mon_regs->lpcr); + data->lpmkcr = io_read32((vaddr_t)&sec_mon_regs->lpmkcr); + data->lpsvcr = io_read32((vaddr_t)&sec_mon_regs->lpsvcr); + data->lptdcr = io_read32((vaddr_t)&sec_mon_regs->lptdcr); + data->lpsr = io_read32((vaddr_t)&sec_mon_regs->lpsr); + data->lpsmcmr = io_read32((vaddr_t)&sec_mon_regs->lpsmcmr); + data->lpsmclr = io_read32((vaddr_t)&sec_mon_regs->lpsmclr); + data->lppgdr = io_read32((vaddr_t)&sec_mon_regs->lppgdr); + data->hpvidr1 = io_read32((vaddr_t)&sec_mon_regs->hpvidr1); + data->hpvidr2 = io_read32((vaddr_t)&sec_mon_regs->hpvidr2); + + for (uint32_t i = 0; i < ARRAY_SIZE(data->lpzmkr); ++i) + data->lpzmkr[i] = io_read32((vaddr_t)&sec_mon_regs->lpzmkr[i]); + + for (uint32_t i = 0; i < ARRAY_SIZE(data->lpgpr); ++i) + data->lpgpr[i] = io_read32((vaddr_t)&sec_mon_regs->lpgpr[i]); + + return TEE_SUCCESS; +} + +TEE_Result ls_sec_mon_status(void) +{ + if (!sec_mon_regs) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +driver_init(ls_sec_mon_init); diff --git a/optee/optee_os/core/drivers/ls_sfp.c b/optee/optee_os/core/drivers/ls_sfp.c new file mode 100644 index 0000000..e0be24b --- /dev/null +++ b/optee/optee_os/core/drivers/ls_sfp.c @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microsoft + * + * Driver for the NXP LX2160A-series Security Fuse Processor (SFP). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct ls_sfp_registers - Memory map of the SFP registers. + * @rsvd0[0x8]: Reserved. + * @ingr: Instruction Register. + * @svhesr: Secret Value Hamming Error Status Registers. + * @sfpcr: SFP Configuration Register. + * @rsvd1[0x3]: Reserved. + * @version: SFP Version Register. + * @rsvd2[0x71]: Reserved. + * @ospr0: OEM Security Policy Register 0. + * @ospr1: OEM Security Policy Register 1. + * @dcvr0: Debug Challenge Value Register 0. + * @dcvr1: Debug Challenge Value Register 1. + * @drvr0: Debug Response Value Register 0. + * @drvr1: Debug Response Value Register 1 + * @fswpr: Factory Section Write Protect Register. + * @fuidr0: Factory Unique ID Register 0. + * @fuidr1: Factory Unique ID Register 1. + * @isbccr: ISBC Configuration Register. + * @fspfr[0x3]: Factory Scratch Pad Fuse Registers. + * @otpmkr[0x8]: One Time Programmable Master Key. + * @srkhr[0x8]: Super Root Key Hash. + * @ouidr[0x5]: OEM Unique ID Scratch Pad Fuse Registers. + */ +static struct ls_sfp_registers { + uint32_t rsvd0[0x8]; /* 0x000 */ + uint32_t ingr; /* 0x020 */ + uint32_t svhesr; /* 0x024 */ + uint32_t sfpcr; /* 0x028 */ + uint32_t rsvd1[0x3]; /* 0x02C */ + uint32_t version; /* 0x038 */ + uint32_t rsvd2[0x71]; /* 0x03C */ + uint32_t ospr0; /* 0x200 */ + uint32_t ospr1; /* 0x204 */ + uint32_t dcvr0; /* 0x208 */ + uint32_t dcvr1; /* 0x20C */ + uint32_t drvr0; /* 0x210 */ + uint32_t drvr1; /* 0x214 */ + uint32_t fswpr; /* 0x218 */ + uint32_t fuidr0; /* 0x21C */ + uint32_t fuidr1; /* 0x220 */ + uint32_t isbccr; /* 0x224 */ + uint32_t fspfr[0x3]; /* 0x228 */ + uint32_t otpmkr[0x8]; /* 0x234 */ + uint32_t srkhr[0x8]; /* 0x254 */ + uint32_t ouidr[0x5]; /* 0x274 */ +} *sfp_regs; + +/** + * struct ls_gpio_info - Data struct containing GPIO specific information. + * @gpio_pin: GPIO pin number. + * @gpio_chip: GPIO controller instance data. + */ +static struct ls_gpio_info { + uint32_t gpio_pin; + struct ls_gpio_chip_data gpio_chip; +} gpio_info; + +/** + * ls_sfp_init() - Get SFP info from the embedded device tree and initialize + * sfp_regs and gpio_info. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +static TEE_Result ls_sfp_init(void) +{ + size_t size = 0; + int node = 0; + int rc = 0; + int povdd_node = 0; + int prop_len = 0; + vaddr_t ctrl_base = 0; + struct ls_gpio_chip_data *gc = NULL; + const char *fdt_prop_gpio = "povdd-gpio-controller"; + const char *fdt_prop_pin = "povdd-gpio-pin"; + const fdt32_t *gpio_val = NULL; + const fdt32_t *pin_val = NULL; + void *fdt = get_embedded_dt(); + + if (!fdt) { + EMSG("Unable to get the Embedded DTB, SFP init failed"); + return TEE_ERROR_GENERIC; + } + + node = fdt_node_offset_by_compatible(fdt, node, "fsl,lx2160a-sfp"); + if (node <= 0) { + EMSG("Unable to find SFP FDT node - rc = 0x%#"PRIx32, rc); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + rc = dt_map_dev(fdt, node, &ctrl_base, &size); + if (rc < 0) { + EMSG("Unable to get SFP virtual address - rc = 0x%#"PRIx32, rc); + return TEE_ERROR_GENERIC; + } + + povdd_node = fdt_path_offset(fdt, "/povdd"); + if (povdd_node <= 0) { + EMSG("Unable to find POVDD FDT node - rc = 0x%#"PRIx32, + povdd_node); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + sfp_regs = (struct ls_sfp_registers *)ctrl_base; + + gpio_val = fdt_getprop(fdt, povdd_node, fdt_prop_gpio, &prop_len); + if (!gpio_val) { + EMSG("Missing %s from POVDD FDT node", fdt_prop_gpio); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + pin_val = fdt_getprop(fdt, povdd_node, fdt_prop_pin, &prop_len); + if (!pin_val) { + EMSG("Missing %s from POVDD FDT node", fdt_prop_pin); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + gc = &gpio_info.gpio_chip; + gc->gpio_controller = (uint8_t)fdt32_to_cpu(*gpio_val); + gpio_info.gpio_pin = fdt32_to_cpu(*pin_val); + + return ls_gpio_init(gc); +} + +/** + * ls_sfp_program_fuses() - Write to fuses and verify that the correct value was + * written. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +static TEE_Result ls_sfp_program_fuses(void) +{ + TEE_Result ret = TEE_SUCCESS; + struct gpio_chip *gc = NULL; + uint32_t pin = gpio_info.gpio_pin; + vaddr_t sfp_ingr_va = (vaddr_t)&sfp_regs->ingr; + uint64_t timeout = 0; + + /* Enable POVDD */ + gc = &gpio_info.gpio_chip.chip; + + DMSG("Set GPIO %"PRIu32" pin %"PRIu32" to HIGH", + (uint32_t)gpio_info.gpio_chip.gpio_controller, pin); + gc->ops->set_direction(gc, pin, GPIO_DIR_OUT); + gc->ops->set_value(gc, pin, GPIO_LEVEL_HIGH); + + if (gc->ops->get_value(gc, pin) != GPIO_LEVEL_HIGH) { + EMSG("Error setting POVDD to HIGH"); + return TEE_ERROR_GENERIC; + } + + /* TA_PROG_SFP ramp rate requires up to 5ms for stability */ + mdelay(5); + + /* Send SFP write command */ + io_write32(sfp_ingr_va, SFP_INGR_PROGFB_CMD); + + /* Wait until fuse programming is successful */ + timeout = timeout_init_us(SFP_INGR_FUSE_TIMEOUT_US); + while (io_read32(sfp_ingr_va) & SFP_INGR_PROGFB_CMD) { + if (timeout_elapsed(timeout)) { + EMSG("SFP fusing timed out"); + ret = TEE_ERROR_GENERIC; + break; + } + } + + /* Disable POVDD */ + DMSG("Set GPIO %"PRIu8" pin %"PRIu32" to LOW", + gpio_info.gpio_chip.gpio_controller, pin); + gc->ops->set_value(gc, pin, GPIO_LEVEL_LOW); + gc->ops->set_direction(gc, pin, GPIO_DIR_IN); + + if (ret) + return ret; + + /* Check for SFP fuse programming error */ + if (io_read32(sfp_ingr_va) & SFP_INGR_ERROR_MASK) { + EMSG("Error writing SFP fuses"); + return TEE_ERROR_GENERIC; + } + + DMSG("Programmed fuse successfully"); + + return TEE_SUCCESS; +} + +TEE_Result ls_sfp_read(struct ls_sfp_data *data) +{ + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + if (!data) + return TEE_ERROR_BAD_PARAMETERS; + + data->ingr = io_read32((vaddr_t)&sfp_regs->ingr); + data->svhesr = io_read32((vaddr_t)&sfp_regs->svhesr); + data->sfpcr = io_read32((vaddr_t)&sfp_regs->sfpcr); + data->version = io_read32((vaddr_t)&sfp_regs->version); + data->ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0); + data->ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1); + data->dcvr0 = io_read32((vaddr_t)&sfp_regs->dcvr0); + data->dcvr1 = io_read32((vaddr_t)&sfp_regs->dcvr1); + data->drvr0 = io_read32((vaddr_t)&sfp_regs->drvr0); + data->drvr1 = io_read32((vaddr_t)&sfp_regs->drvr1); + data->fswpr = io_read32((vaddr_t)&sfp_regs->fswpr); + data->fuidr0 = io_read32((vaddr_t)&sfp_regs->fuidr0); + data->fuidr1 = io_read32((vaddr_t)&sfp_regs->fuidr1); + data->isbccr = io_read32((vaddr_t)&sfp_regs->isbccr); + + for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->fspfr); ++i) + data->fspfr[i] = io_read32((vaddr_t)&sfp_regs->fspfr[i]); + + for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->otpmkr); ++i) + data->otpmkr[i] = io_read32((vaddr_t)&sfp_regs->otpmkr[i]); + + for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->srkhr); ++i) + data->srkhr[i] = io_read32((vaddr_t)&sfp_regs->srkhr[i]); + + for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->ouidr); ++i) + data->ouidr[i] = io_read32((vaddr_t)&sfp_regs->ouidr[i]); + + return TEE_SUCCESS; +} + +TEE_Result ls_sfp_get_debug_level(uint32_t *dblev) +{ + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + if (!dblev) + return TEE_ERROR_BAD_PARAMETERS; + + *dblev = io_read32((vaddr_t)&sfp_regs->ospr1) & SFP_OSPR1_DBLEV_MASK; + + return TEE_SUCCESS; +} + +TEE_Result ls_sfp_get_its(uint32_t *its) +{ + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + if (!its) + return TEE_ERROR_BAD_PARAMETERS; + + *its = (io_read32((vaddr_t)&sfp_regs->ospr0) & SFP_OSPR0_ITS_MASK) >> + SFP_OSPR0_ITS_OFFSET; + + return TEE_SUCCESS; +} + +TEE_Result ls_sfp_get_ouid(uint32_t index, uint32_t *ouid) +{ + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + if (!ouid) + return TEE_ERROR_BAD_PARAMETERS; + + if (index >= ARRAY_SIZE(sfp_regs->ouidr)) { + DMSG("Index greater or equal to ouid: %"PRIu32" >= %zu", + index, ARRAY_SIZE(sfp_regs->ouidr)); + return TEE_ERROR_BAD_PARAMETERS; + } + + *ouid = io_read32((vaddr_t)&sfp_regs->ouidr[index]); + + return TEE_SUCCESS; +} + +TEE_Result ls_sfp_get_sb(uint32_t *sb) +{ + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + if (!sb) + return TEE_ERROR_BAD_PARAMETERS; + + *sb = (io_read32((vaddr_t)&sfp_regs->sfpcr) & SFP_SFPCR_SB_MASK) >> + SFP_SFPCR_SB_OFFSET; + + return TEE_SUCCESS; +} + +TEE_Result ls_sfp_get_srkh(uint32_t index, uint32_t *srkh) +{ + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + if (!srkh) + return TEE_ERROR_BAD_PARAMETERS; + + if (index >= ARRAY_SIZE(sfp_regs->srkhr)) { + DMSG("Index greater or equal to srkhr: %"PRIu32" >= %zu", + index, ARRAY_SIZE(sfp_regs->srkhr)); + return TEE_ERROR_BAD_PARAMETERS; + } + + *srkh = io_read32((vaddr_t)&sfp_regs->srkhr[index]); + + return TEE_SUCCESS; +} + +TEE_Result ls_sfp_set_debug_level(uint32_t dblev) +{ + uint32_t ospr1 = 0; + + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + if (!dblev) + return TEE_SUCCESS; + + ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1); + if (ospr1 & SFP_OSPR1_DBLEV_MASK) { + DMSG("Debug level has already been fused"); + return TEE_ERROR_SECURITY; + } + + io_write32((vaddr_t)&sfp_regs->ospr1, ospr1 | dblev); + + return ls_sfp_program_fuses(); +} + +TEE_Result ls_sfp_set_its_wp(void) +{ + uint32_t ospr0 = 0; + + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0); + if (ospr0 & (SFP_OSPR0_WP_MASK | SFP_OSPR0_ITS_MASK)) { + DMSG("SFP is already fused"); + return TEE_ERROR_SECURITY; + } + + ospr0 |= SFP_OSPR0_WP_MASK | SFP_OSPR0_ITS_MASK; + io_write32((vaddr_t)&sfp_regs->ospr0, ospr0); + + return ls_sfp_program_fuses(); +} + +TEE_Result ls_sfp_set_ouid(uint32_t index, uint32_t ouid) +{ + if (!sfp_regs) { + EMSG("SFP driver not initialized"); + return TEE_ERROR_GENERIC; + } + + if (index >= ARRAY_SIZE(sfp_regs->ouidr)) { + DMSG("Index greater or equal to ouid: %"PRIu32" >= %"PRIu32, + index, ARRAY_SIZE(sfp_regs->ouidr)); + return TEE_ERROR_BAD_PARAMETERS; + } + + io_write32((vaddr_t)&sfp_regs->ouidr[index], ouid); + + return ls_sfp_program_fuses(); +} + +TEE_Result ls_sfp_status(void) +{ + if (!sfp_regs) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +driver_init(ls_sfp_init); diff --git a/optee/optee_os/core/drivers/mvebu_uart.c b/optee/optee_os/core/drivers/mvebu_uart.c new file mode 100644 index 0000000..75ba73b --- /dev/null +++ b/optee/optee_os/core/drivers/mvebu_uart.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2017 Marvell International Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +/* MVEBU UART Registers */ +#define UART_RX_REG 0x00 +#define UART_TX_REG 0x04 +#define UART_CTRL_REG 0x08 +#define UART_STATUS_REG 0x0c +#define UART_BAUD_REG 0x10 +#define UART_POSSR_REG 0x14 +#define UART_SIZE 0x18 + +/* Line Status Register bits */ +#define UARTLSR_TXFIFOFULL (1 << 11) /* Tx Fifo Full */ +#define UARTLSR_TXFIFOEMPTY (1 << 13) +#define UARTLSR_TXEMPTY (1 << 6) +#define UART_RX_READY (1 << 4) + +/* UART Control Register bits */ +#define UART_CTRL_RXFIFO_RESET (1 << 14) +#define UART_CTRL_TXFIFO_RESET (1 << 15) + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct mvebu_uart_data *pd = + container_of(chip, struct mvebu_uart_data, chip); + + return io_pa_or_va(&pd->base, UART_SIZE); +} + +static void mvebu_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + /* + * Wait for the transmit FIFO to be empty. + * It can happen that Linux initializes the OP-TEE driver with the + * console UART disabled; avoid an infinite loop by checking the UART + * enabled flag. Checking it in the loop makes the code safe against + * asynchronous disable. + */ + while (!(io_read32(base + UART_STATUS_REG) & UARTLSR_TXFIFOEMPTY)) + ; +} + +static bool mvebu_uart_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + return (io_read32(base + UART_STATUS_REG) & UART_RX_READY); +} + +static int mvebu_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!mvebu_uart_have_rx_data(chip)) + ; + return io_read32(base + UART_RX_REG) & 0xff; +} + +static void mvebu_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + uint32_t tmp; + /* wait for space in tx FIFO */ + do { + tmp = io_read32(base + UART_STATUS_REG); + tmp &= UARTLSR_TXFIFOFULL; + } while (tmp == UARTLSR_TXFIFOFULL); + + io_write32(base + UART_TX_REG, ch); +} + +static const struct serial_ops mvebu_uart_ops = { + .flush = mvebu_uart_flush, + .getchar = mvebu_uart_getchar, + .have_rx_data = mvebu_uart_have_rx_data, + .putc = mvebu_uart_putc, +}; +DECLARE_KEEP_PAGER(mvebu_uart_ops); + +void mvebu_uart_init(struct mvebu_uart_data *pd, paddr_t pbase, + uint32_t uart_clk, uint32_t baud_rate) +{ + vaddr_t base; + uint32_t dll = 0; + + pd->base.pa = pbase; + pd->chip.ops = &mvebu_uart_ops; + + base = io_pa_or_va(&pd->base, UART_SIZE); + + dll = (uart_clk / (baud_rate << 4)) & 0x3FF; + + /* init UART */ + io_clrsetbits32(base + UART_BAUD_REG, 0x3FF, dll); + + /* set UART to default 16x scheme */ + io_write32(base + UART_POSSR_REG, 0); + + /* reset FIFO */ + io_write32(base + UART_CTRL_REG, + UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET); + + /* No Parity, 1 stop */ + io_write32(base + UART_CTRL_REG, 0); + + mvebu_uart_flush(&pd->chip); +} diff --git a/optee/optee_os/core/drivers/ns16550.c b/optee/optee_os/core/drivers/ns16550.c new file mode 100644 index 0000000..b69cdf8 --- /dev/null +++ b/optee/optee_os/core/drivers/ns16550.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2017, 2020, 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 +#include + +/* uart register defines */ +#define UART_RBR 0x0 +#define UART_THR 0x0 +#define UART_IER 0x1 +#define UART_FCR 0x2 +#define UART_LCR 0x3 +#define UART_MCR 0x4 +#define UART_LSR 0x5 +#define UART_MSR 0x6 +#define UART_SPR 0x7 + +/* uart status register bits */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ + +static void ns16550_flush(struct serial_chip *chip) +{ + struct ns16550_data *pd = + container_of(chip, struct ns16550_data, chip); + vaddr_t base = io_pa_or_va(&pd->base, + (UART_LSR << pd->reg_shift) + pd->io_width); + + while ((serial_in(base + (UART_LSR << pd->reg_shift), pd->io_width) & + UART_LSR_THRE) == 0) + ; +} + +static void ns16550_putc(struct serial_chip *chip, int ch) +{ + struct ns16550_data *pd = + container_of(chip, struct ns16550_data, chip); + vaddr_t base = io_pa_or_va(&pd->base, (UART_THR << pd->reg_shift) + + pd->io_width); + + ns16550_flush(chip); + + /* write out charset to Transmit-hold-register */ + serial_out(base + (UART_THR << pd->reg_shift), pd->io_width, ch); +} + +static const struct serial_ops ns16550_ops = { + .flush = ns16550_flush, + .putc = ns16550_putc, +}; +DECLARE_KEEP_PAGER(ns16550_ops); + +void ns16550_init(struct ns16550_data *pd, paddr_t base, uint8_t io_width, + uint8_t reg_shift) +{ + pd->base.pa = base; + pd->io_width = io_width; + pd->reg_shift = reg_shift; + pd->chip.ops = &ns16550_ops; + + /* + * Do nothing, uart driver shared with normal world, + * everything for uart driver initialization is done in bootloader. + */ +} diff --git a/optee/optee_os/core/drivers/pl011.c b/optee/optee_os/core/drivers/pl011.c new file mode 100644 index 0000000..0fc03d6 --- /dev/null +++ b/optee/optee_os/core/drivers/pl011.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#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_ILPR 0x20 /* IrDA low-poer */ +#define UART_IBRD 0x24 /* integer baud register */ +#define UART_FBRD 0x28 /* fractional baud register */ +#define UART_LCR_H 0x2C /* line control register */ +#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/receive 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_RTIM (1 << 6) +#define UART_IMSC_RXIM (1 << 4) + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct pl011_data *pd = + container_of(chip, struct pl011_data, chip); + + return io_pa_or_va(&pd->base, PL011_REG_SIZE); +} + +static void pl011_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + /* + * Wait for the transmit FIFO to be empty. + * It can happen that Linux initializes the OP-TEE driver with the + * console UART disabled; avoid an infinite loop by checking the UART + * enabled flag. Checking it in the loop makes the code safe against + * asynchronous disable. + */ + while ((io_read32(base + UART_CR) & UART_CR_UARTEN) && + !(io_read32(base + UART_FR) & UART_FR_TXFE)) + ; +} + +static bool pl011_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + return !(io_read32(base + UART_FR) & UART_FR_RXFE); +} + +static int pl011_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!pl011_have_rx_data(chip)) + ; + return io_read32(base + UART_DR) & 0xff; +} + +static void pl011_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + /* Wait until there is space in the FIFO or device is disabled */ + while (io_read32(base + UART_FR) & UART_FR_TXFF) + ; + + /* Send the character */ + io_write32(base + UART_DR, ch); +} + +static const struct serial_ops pl011_ops = { + .flush = pl011_flush, + .getchar = pl011_getchar, + .have_rx_data = pl011_have_rx_data, + .putc = pl011_putc, +}; +DECLARE_KEEP_PAGER(pl011_ops); + +void pl011_init(struct pl011_data *pd, paddr_t pbase, uint32_t uart_clk, + uint32_t baud_rate) +{ + vaddr_t base; + + pd->base.pa = pbase; + pd->chip.ops = &pl011_ops; + + base = io_pa_or_va(&pd->base, PL011_REG_SIZE); + + /* Clear all errors */ + io_write32(base + UART_RSR_ECR, 0); + /* Disable everything */ + io_write32(base + UART_CR, 0); + + if (baud_rate) { + uint32_t divisor = (uart_clk * 4) / baud_rate; + + io_write32(base + UART_IBRD, divisor >> 6); + io_write32(base + UART_FBRD, divisor & 0x3f); + } + + /* Configure TX to 8 bits, 1 stop bit, no parity, fifo disabled. */ + io_write32(base + UART_LCR_H, UART_LCRH_WLEN_8); + + /* Enable interrupts for receive and receive timeout */ + io_write32(base + UART_IMSC, UART_IMSC_RXIM | UART_IMSC_RTIM); + + /* Enable UART and RX/TX */ + io_write32(base + UART_CR, UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE); + + pl011_flush(&pd->chip); +} + +#ifdef CFG_DT + +static struct serial_chip *pl011_dev_alloc(void) +{ + struct pl011_data *pd = nex_calloc(1, sizeof(*pd)); + + if (!pd) + return NULL; + return &pd->chip; +} + +static int pl011_dev_init(struct serial_chip *chip, const void *fdt, int offs, + const char *parms) +{ + struct pl011_data *pd = container_of(chip, struct pl011_data, chip); + vaddr_t vbase; + paddr_t pbase; + size_t size; + + if (parms && parms[0]) + IMSG("pl011: device parameters ignored (%s)", parms); + + if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) + return -1; + + if (size != 0x1000) { + EMSG("pl011: unexpected register size: %zx", size); + return -1; + } + + pbase = virt_to_phys((void *)vbase); + pl011_init(pd, pbase, 0, 0); + + return 0; +} + +static void pl011_dev_free(struct serial_chip *chip) +{ + struct pl011_data *pd = container_of(chip, struct pl011_data, chip); + + nex_free(pd); +} + +static const struct serial_driver pl011_driver = { + .dev_alloc = pl011_dev_alloc, + .dev_init = pl011_dev_init, + .dev_free = pl011_dev_free, +}; + +static const struct dt_device_match pl011_match_table[] = { + { .compatible = "arm,pl011" }, + { 0 } +}; + +DEFINE_DT_DRIVER(pl011_dt_driver) = { + .name = "pl011", + .type = DT_DRIVER_UART, + .match_table = pl011_match_table, + .driver = &pl011_driver, +}; + +#endif /* CFG_DT */ diff --git a/optee/optee_os/core/drivers/pl022_spi.c b/optee/optee_os/core/drivers/pl022_spi.c new file mode 100644 index 0000000..91e54b2 --- /dev/null +++ b/optee/optee_os/core/drivers/pl022_spi.c @@ -0,0 +1,509 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SPI register offsets */ +#define SSPCR0 0x000 +#define SSPCR1 0x004 +#define SSPDR 0x008 +#define SSPSR 0x00C +#define SSPCPSR 0x010 +#define SSPIMSC 0x014 +#define SSPRIS 0x018 +#define SSPMIS 0x01C +#define SSPICR 0x020 +#define SSPDMACR 0x024 + +#ifdef PLATFORM_hikey +/* HiKey extensions */ +#define SSPTXFIFOCR 0x028 +#define SSPRXFIFOCR 0x02C +#define SSPB2BTRANS 0x030 +#endif + +/* test registers */ +#define SSPTCR 0x080 +#define SSPITIP 0x084 +#define SSPITOP 0x088 +#define SSPTDR 0x08C + +#define SSPPeriphID0 0xFE0 +#define SSPPeriphID1 0xFE4 +#define SSPPeriphID2 0xFE8 +#define SSPPeriphID3 0xFEC + +#define SSPPCellID0 0xFF0 +#define SSPPCellID1 0xFF4 +#define SSPPCellID2 0xFF8 +#define SSPPCellID3 0xFFC + +/* SPI register masks */ +#define SSPCR0_SCR SHIFT_U32(0xFF, 8) +#define SSPCR0_SPH SHIFT_U32(1, 7) +#define SSPCR0_SPH1 SHIFT_U32(1, 7) +#define SSPCR0_SPH0 SHIFT_U32(0, 7) +#define SSPCR0_SPO SHIFT_U32(1, 6) +#define SSPCR0_SPO1 SHIFT_U32(1, 6) +#define SSPCR0_SPO0 SHIFT_U32(0, 6) +#define SSPCR0_FRF SHIFT_U32(3, 4) +#define SSPCR0_FRF_SPI SHIFT_U32(0, 4) +#define SSPCR0_DSS SHIFT_U32(0xFF, 0) +#define SSPCR0_DSS_16BIT SHIFT_U32(0xF, 0) +#define SSPCR0_DSS_8BIT SHIFT_U32(7, 0) + +#define SSPCR1_SOD SHIFT_U32(1, 3) +#define SSPCR1_SOD_ENABLE SHIFT_U32(1, 3) +#define SSPCR1_SOD_DISABLE SHIFT_U32(0, 3) +#define SSPCR1_MS SHIFT_U32(1, 2) +#define SSPCR1_MS_SLAVE SHIFT_U32(1, 2) +#define SSPCR1_MS_MASTER SHIFT_U32(0, 2) +#define SSPCR1_SSE SHIFT_U32(1, 1) +#define SSPCR1_SSE_ENABLE SHIFT_U32(1, 1) +#define SSPCR1_SSE_DISABLE SHIFT_U32(0, 1) +#define SSPCR1_LBM SHIFT_U32(1, 0) +#define SSPCR1_LBM_YES SHIFT_U32(1, 0) +#define SSPCR1_LBM_NO SHIFT_U32(0, 0) + +#define SSPDR_DATA SHIFT_U32(0xFFFF, 0) + +#define SSPSR_BSY SHIFT_U32(1, 4) +#define SSPSR_RNF SHIFT_U32(1, 3) +#define SSPSR_RNE SHIFT_U32(1, 2) +#define SSPSR_TNF SHIFT_U32(1, 1) +#define SSPSR_TFE SHIFT_U32(1, 0) + +#define SSPCPSR_CPSDVR SHIFT_U32(0xFF, 0) + +#define SSPIMSC_TXIM SHIFT_U32(1, 3) +#define SSPIMSC_RXIM SHIFT_U32(1, 2) +#define SSPIMSC_RTIM SHIFT_U32(1, 1) +#define SSPIMSC_RORIM SHIFT_U32(1, 0) + +#define SSPRIS_TXRIS SHIFT_U32(1, 3) +#define SSPRIS_RXRIS SHIFT_U32(1, 2) +#define SSPRIS_RTRIS SHIFT_U32(1, 1) +#define SSPRIS_RORRIS SHIFT_U32(1, 0) + +#define SSPMIS_TXMIS SHIFT_U32(1, 3) +#define SSPMIS_RXMIS SHIFT_U32(1, 2) +#define SSPMIS_RTMIS SHIFT_U32(1, 1) +#define SSPMIS_RORMIS SHIFT_U32(1, 0) + +#define SSPICR_RTIC SHIFT_U32(1, 1) +#define SSPICR_RORIC SHIFT_U32(1, 0) + +#define SSPDMACR_TXDMAE SHIFT_U32(1, 1) +#define SSPDMACR_RXDMAE SHIFT_U32(1, 0) + +#define SSPPeriphID0_PartNumber0 SHIFT_U32(0xFF, 0) /* 0x22 */ +#define SSPPeriphID1_Designer0 SHIFT_U32(0xF, 4) /* 0x1 */ +#define SSPPeriphID1_PartNumber1 SHIFT_U32(0xF, 0) /* 0x0 */ +#define SSPPeriphID2_Revision SHIFT_U32(0xF, 4) +#define SSPPeriphID2_Designer1 SHIFT_U32(0xF, 0) /* 0x4 */ +#define SSPPeriphID3_Configuration SHIFT_U32(0xFF, 0) /* 0x00 */ + +#define SSPPCellID_0 SHIFT_U32(0xFF, 0) /* 0x0D */ +#define SSPPCellID_1 SHIFT_U32(0xFF, 0) /* 0xF0 */ +#define SSPPPCellID_2 SHIFT_U32(0xFF, 0) /* 0x05 */ +#define SSPPPCellID_3 SHIFT_U32(0xFF, 0) /* 0xB1 */ + +#define MASK_32 0xFFFFFFFF +#define MASK_28 0xFFFFFFF +#define MASK_24 0xFFFFFF +#define MASK_20 0xFFFFF +#define MASK_16 0xFFFF +#define MASK_12 0xFFF +#define MASK_8 0xFF +#define MASK_4 0xF +/* SPI register masks */ + +#define SSP_CPSDVR_MAX 254 +#define SSP_CPSDVR_MIN 2 +#define SSP_SCR_MAX 255 +#define SSP_SCR_MIN 0 +#define SSP_DATASIZE_MAX 16 + +static enum spi_result pl022_txrx8(struct spi_chip *chip, uint8_t *wdat, + uint8_t *rdat, size_t num_pkts) +{ + size_t i = 0; + size_t j = 0; + struct pl022_data *pd = container_of(chip, struct pl022_data, chip); + + + if (pd->data_size_bits != 8) { + EMSG("data_size_bits should be 8, not %u", + pd->data_size_bits); + return SPI_ERR_CFG; + } + + if (wdat) + while (i < num_pkts) { + if (io_read8(pd->base + SSPSR) & SSPSR_TNF) { + /* tx 1 packet */ + io_write8(pd->base + SSPDR, wdat[i++]); + } + + if (rdat) + if (io_read8(pd->base + SSPSR) & SSPSR_RNE) { + /* rx 1 packet */ + rdat[j++] = io_read8(pd->base + SSPDR); + } + } + + /* Capture remaining rdat not read above */ + if (rdat) { + while ((j < num_pkts) && + (io_read8(pd->base + SSPSR) & SSPSR_RNE)) { + /* rx 1 packet */ + rdat[j++] = io_read8(pd->base + SSPDR); + } + + if (j < num_pkts) { + EMSG("Packets requested %zu, received %zu", + num_pkts, j); + return SPI_ERR_PKTCNT; + } + } + + return SPI_OK; +} + +static enum spi_result pl022_txrx16(struct spi_chip *chip, uint16_t *wdat, + uint16_t *rdat, size_t num_pkts) +{ + size_t i = 0; + size_t j = 0; + struct pl022_data *pd = container_of(chip, struct pl022_data, chip); + + if (pd->data_size_bits != 16) { + EMSG("data_size_bits should be 16, not %u", + pd->data_size_bits); + return SPI_ERR_CFG; + } + + if (wdat) + while (i < num_pkts) { + if (io_read8(pd->base + SSPSR) & SSPSR_TNF) { + /* tx 1 packet */ + io_write16(pd->base + SSPDR, wdat[i++]); + } + + if (rdat) + if (io_read8(pd->base + SSPSR) & SSPSR_RNE) { + /* rx 1 packet */ + rdat[j++] = io_read16(pd->base + SSPDR); + } + } + + /* Capture remaining rdat not read above */ + if (rdat) { + while ((j < num_pkts) && + (io_read8(pd->base + SSPSR) & SSPSR_RNE)) { + /* rx 1 packet */ + rdat[j++] = io_read16(pd->base + SSPDR); + } + + if (j < num_pkts) { + EMSG("Packets requested %zu, received %zu", + num_pkts, j); + return SPI_ERR_PKTCNT; + } + } + + return SPI_OK; +} + +static void pl022_print_peri_id(struct pl022_data *pd __maybe_unused) +{ + DMSG("Expected: 0x 22 10 ?4 00"); + DMSG("Read: 0x %02x %02x %02x %02x", + io_read8(pd->base + SSPPeriphID0), + io_read8(pd->base + SSPPeriphID1), + io_read8(pd->base + SSPPeriphID2), + io_read8(pd->base + SSPPeriphID3)); +} + +static void pl022_print_cell_id(struct pl022_data *pd __maybe_unused) +{ + DMSG("Expected: 0x 0d f0 05 b1"); + DMSG("Read: 0x %02x %02x %02x %02x", + io_read8(pd->base + SSPPCellID0), + io_read8(pd->base + SSPPCellID1), + io_read8(pd->base + SSPPCellID2), + io_read8(pd->base + SSPPCellID3)); +} + +static void pl022_sanity_check(struct pl022_data *pd) +{ + assert(pd); + assert(pd->chip.ops); + assert(pd->cs_control <= PL022_CS_CTRL_MANUAL); + switch (pd->cs_control) { + case PL022_CS_CTRL_AUTO_GPIO: + assert(pd->cs_data.gpio_data.chip); + assert(pd->cs_data.gpio_data.chip->ops); + break; + case PL022_CS_CTRL_CB: + assert(pd->cs_data.cs_cb); + break; + default: + break; + } + assert(pd->clk_hz); + assert(pd->speed_hz && pd->speed_hz <= pd->clk_hz/2); + assert(pd->mode <= SPI_MODE3); + assert(pd->data_size_bits == 8 || pd->data_size_bits == 16); + + #ifdef PLATFORM_hikey + DMSG("SSPB2BTRANS: Expected: 0x2. Read: 0x%x", + io_read8(pd->base + SSPB2BTRANS)); + #endif + pl022_print_peri_id(pd); + pl022_print_cell_id(pd); +} + +static inline uint32_t pl022_calc_freq(struct pl022_data *pd, + uint8_t cpsdvr, uint8_t scr) +{ + return pd->clk_hz / (cpsdvr * (1 + scr)); +} + +static void pl022_control_cs(struct spi_chip *chip, enum gpio_level value) +{ + struct pl022_data *pd = container_of(chip, struct pl022_data, chip); + + switch (pd->cs_control) { + case PL022_CS_CTRL_AUTO_GPIO: + if (io_read8(pd->base + SSPSR) & SSPSR_BSY) + DMSG("pl022 busy - do NOT set CS!"); + while (io_read8(pd->base + SSPSR) & SSPSR_BSY) + ; + DMSG("pl022 done - set CS!"); + + pd->cs_data.gpio_data.chip->ops->set_value(NULL, + pd->cs_data.gpio_data.pin_num, value); + break; + case PL022_CS_CTRL_CB: + pd->cs_data.cs_cb(value); + break; + default: + break; + } +} + +static void pl022_calc_clk_divisors(struct pl022_data *pd, + uint8_t *cpsdvr, uint8_t *scr) +{ + unsigned int freq1 = 0; + unsigned int freq2 = 0; + uint8_t tmp_cpsdvr1; + uint8_t tmp_scr1; + uint8_t tmp_cpsdvr2 = 0; + uint8_t tmp_scr2 = 0; + + for (tmp_scr1 = SSP_SCR_MIN; tmp_scr1 < SSP_SCR_MAX; tmp_scr1++) { + for (tmp_cpsdvr1 = SSP_CPSDVR_MIN; tmp_cpsdvr1 < SSP_CPSDVR_MAX; + tmp_cpsdvr1++) { + freq1 = pl022_calc_freq(pd, tmp_cpsdvr1, tmp_scr1); + if (freq1 == pd->speed_hz) + goto done; + else if (freq1 < pd->speed_hz) + goto stage2; + } + } + +stage2: + for (tmp_cpsdvr2 = SSP_CPSDVR_MIN; tmp_cpsdvr2 < SSP_CPSDVR_MAX; + tmp_cpsdvr2++) { + for (tmp_scr2 = SSP_SCR_MIN; tmp_scr2 < SSP_SCR_MAX; + tmp_scr2++) { + freq2 = pl022_calc_freq(pd, tmp_cpsdvr2, tmp_scr2); + if (freq2 <= pd->speed_hz) + goto done; + } + } + +done: + if (freq1 >= freq2) { + *cpsdvr = tmp_cpsdvr1; + *scr = tmp_scr1; + DMSG("speed: requested: %u, closest1: %u", + pd->speed_hz, freq1); + } else { + *cpsdvr = tmp_cpsdvr2; + *scr = tmp_scr2; + DMSG("speed: requested: %u, closest2: %u", + pd->speed_hz, freq2); + } + DMSG("CPSDVR: %u (0x%x), SCR: %u (0x%x)", + *cpsdvr, *cpsdvr, *scr, *scr); +} + +static void pl022_flush_fifo(struct spi_chip *chip) +{ + uint32_t __maybe_unused rdat; + struct pl022_data *pd = container_of(chip, struct pl022_data, chip); + do { + while (io_read32(pd->base + SSPSR) & SSPSR_RNE) { + rdat = io_read32(pd->base + SSPDR); + DMSG("rdat: 0x%x", rdat); + } + } while (io_read32(pd->base + SSPSR) & SSPSR_BSY); +} + +static void pl022_configure(struct spi_chip *chip) +{ + uint16_t mode; + uint16_t data_size; + uint8_t cpsdvr; + uint8_t scr; + uint8_t lbm; + struct pl022_data *pd = container_of(chip, struct pl022_data, chip); + + pl022_sanity_check(pd); + + switch (pd->cs_control) { + case PL022_CS_CTRL_AUTO_GPIO: + DMSG("Use auto GPIO CS control"); + DMSG("Mask/disable interrupt for CS GPIO"); + pd->cs_data.gpio_data.chip->ops->set_interrupt(NULL, + pd->cs_data.gpio_data.pin_num, + GPIO_INTERRUPT_DISABLE); + DMSG("Set CS GPIO dir to out"); + pd->cs_data.gpio_data.chip->ops->set_direction(NULL, + pd->cs_data.gpio_data.pin_num, + GPIO_DIR_OUT); + break; + case PL022_CS_CTRL_CB: + DMSG("Use registered CS callback"); + break; + case PL022_CS_CTRL_MANUAL: + DMSG("Use manual CS control"); + break; + default: + EMSG("Invalid CS control type: %d", pd->cs_control); + panic(); + } + + DMSG("Pull CS high"); + pl022_control_cs(chip, GPIO_LEVEL_HIGH); + + pl022_calc_clk_divisors(pd, &cpsdvr, &scr); + + /* configure ssp based on platform settings */ + switch (pd->mode) { + case SPI_MODE0: + DMSG("SPI mode 0"); + mode = SSPCR0_SPO0 | SSPCR0_SPH0; + break; + case SPI_MODE1: + DMSG("SPI mode 1"); + mode = SSPCR0_SPO0 | SSPCR0_SPH1; + break; + case SPI_MODE2: + DMSG("SPI mode 2"); + mode = SSPCR0_SPO1 | SSPCR0_SPH0; + break; + case SPI_MODE3: + DMSG("SPI mode 3"); + mode = SSPCR0_SPO1 | SSPCR0_SPH1; + break; + default: + EMSG("Invalid SPI mode: %u", pd->mode); + panic(); + } + + switch (pd->data_size_bits) { + case 8: + DMSG("Data size: 8"); + data_size = SSPCR0_DSS_8BIT; + break; + case 16: + DMSG("Data size: 16"); + data_size = SSPCR0_DSS_16BIT; + break; + default: + EMSG("Unsupported data size: %u bits", pd->data_size_bits); + panic(); + } + + if (pd->loopback) { + DMSG("Starting in loopback mode!"); + lbm = SSPCR1_LBM_YES; + } else { + DMSG("Starting in regular (non-loopback) mode!"); + lbm = SSPCR1_LBM_NO; + } + + DMSG("Set Serial Clock Rate (SCR), SPI mode (phase and clock)"); + DMSG("Set frame format (SPI) and data size (8- or 16-bit)"); + io_mask16(pd->base + SSPCR0, SHIFT_U32(scr, 8) | mode | SSPCR0_FRF_SPI | + data_size, MASK_16); + + DMSG("Set master mode, disable SSP, set loopback mode"); + io_mask8(pd->base + SSPCR1, SSPCR1_SOD_DISABLE | SSPCR1_MS_MASTER | + SSPCR1_SSE_DISABLE | lbm, MASK_4); + + DMSG("Set clock prescale"); + io_mask8(pd->base + SSPCPSR, cpsdvr, SSPCPSR_CPSDVR); + + DMSG("Disable interrupts"); + io_mask8(pd->base + SSPIMSC, 0, MASK_4); + + DMSG("Clear interrupts"); + io_mask8(pd->base + SSPICR, SSPICR_RORIC | SSPICR_RTIC, + SSPICR_RORIC | SSPICR_RTIC); + + DMSG("Empty FIFO before starting"); + pl022_flush_fifo(chip); +} + +static void pl022_start(struct spi_chip *chip) +{ + struct pl022_data *pd = container_of(chip, struct pl022_data, chip); + + DMSG("Enable SSP"); + io_mask8(pd->base + SSPCR1, SSPCR1_SSE_ENABLE, SSPCR1_SSE); + + pl022_control_cs(chip, GPIO_LEVEL_LOW); +} + +static void pl022_end(struct spi_chip *chip) +{ + struct pl022_data *pd = container_of(chip, struct pl022_data, chip); + + pl022_control_cs(chip, GPIO_LEVEL_HIGH); + + DMSG("Disable SSP"); + io_mask8(pd->base + SSPCR1, SSPCR1_SSE_DISABLE, SSPCR1_SSE); +} + +static const struct spi_ops pl022_ops = { + .configure = pl022_configure, + .start = pl022_start, + .txrx8 = pl022_txrx8, + .txrx16 = pl022_txrx16, + .end = pl022_end, + .flushfifo = pl022_flush_fifo, +}; +DECLARE_KEEP_PAGER(pl022_ops); + +void pl022_init(struct pl022_data *pd) +{ + assert(pd); + pd->chip.ops = &pl022_ops; +} diff --git a/optee/optee_os/core/drivers/pl061_gpio.c b/optee/optee_os/core/drivers/pl061_gpio.c new file mode 100644 index 0000000..19c62d1 --- /dev/null +++ b/optee/optee_os/core/drivers/pl061_gpio.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#ifndef PLAT_PL061_MAX_GPIOS +# define PLAT_PL061_MAX_GPIOS 32 +#endif /* PLAT_PL061_MAX_GPIOS */ + +#define MAX_GPIO_DEVICES ((PLAT_PL061_MAX_GPIOS + \ + (GPIOS_PER_PL061 - 1)) / GPIOS_PER_PL061) + +#define GPIOS_PER_PL061 8 + +/* gpio register offsets */ +#define GPIODIR 0x400 +#define GPIOIS 0x404 +#define GPIOIBE 0x408 +#define GPIOIEV 0x40C +#define GPIOIE 0x410 +#define GPIORIS 0x414 +#define GPIOMIS 0x418 +#define GPIOIC 0x41C +#define GPIOAFSEL 0x420 + +/* gpio register masks */ +#define GPIOIE_ENABLED SHIFT_U32(1, 0) +#define GPIOIE_MASKED SHIFT_U32(0, 0) +#define GPIOAFSEL_HW SHIFT_U32(1, 0) +#define GPIOAFSEL_SW SHIFT_U32(0, 0) +#define GPIODIR_OUT SHIFT_U32(1, 0) +#define GPIODIR_IN SHIFT_U32(0, 0) + +static vaddr_t pl061_reg_base[MAX_GPIO_DEVICES]; + +static enum gpio_dir pl061_get_direction(struct gpio_chip *chip __unused, + unsigned int gpio_pin) +{ + vaddr_t base_addr; + uint8_t data; + unsigned int offset; + + assert(gpio_pin < PLAT_PL061_MAX_GPIOS); + + base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; + offset = gpio_pin % GPIOS_PER_PL061; + data = io_read8(base_addr + GPIODIR); + if (data & BIT(offset)) + return GPIO_DIR_OUT; + return GPIO_DIR_IN; +} + +static void pl061_set_direction(struct gpio_chip *chip __unused, + unsigned int gpio_pin, enum gpio_dir direction) +{ + vaddr_t base_addr; + unsigned int offset; + + assert(gpio_pin < PLAT_PL061_MAX_GPIOS); + + base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; + offset = gpio_pin % GPIOS_PER_PL061; + if (direction == GPIO_DIR_OUT) + io_setbits8(base_addr + GPIODIR, BIT(offset)); + else + io_clrbits8(base_addr + GPIODIR, BIT(offset)); +} + +/* + * The offset of GPIODATA register is 0. + * The values read from GPIODATA are determined for each bit, by the mask bit + * derived from the address used to access the data register, PADDR[9:2]. + * Bits that are 1 in the address mask cause the corresponding bits in GPIODATA + * to be read, and bits that are 0 in the address mask cause the corresponding + * bits in GPIODATA to be read as 0, regardless of their value. + */ +static enum gpio_level pl061_get_value(struct gpio_chip *chip __unused, + unsigned int gpio_pin) +{ + vaddr_t base_addr; + unsigned int offset; + + assert(gpio_pin < PLAT_PL061_MAX_GPIOS); + + base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; + offset = gpio_pin % GPIOS_PER_PL061; + if (io_read8(base_addr + BIT(offset + 2))) + return GPIO_LEVEL_HIGH; + return GPIO_LEVEL_LOW; +} + +/* + * In order to write GPIODATA, the corresponding bits in the mask, resulting + * from the address bus, PADDR[9:2], must be HIGH. Otherwise the bit values + * remain unchanged by the write. + */ +static void pl061_set_value(struct gpio_chip *chip __unused, + unsigned int gpio_pin, enum gpio_level value) +{ + vaddr_t base_addr; + unsigned int offset; + + assert(gpio_pin < PLAT_PL061_MAX_GPIOS); + + base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; + offset = gpio_pin % GPIOS_PER_PL061; + if (value == GPIO_LEVEL_HIGH) + io_write8(base_addr + BIT(offset + 2), BIT(offset)); + else + io_write8(base_addr + BIT(offset + 2), 0); +} + +static enum gpio_interrupt pl061_get_interrupt(struct gpio_chip *chip __unused, + unsigned int gpio_pin) +{ + vaddr_t base_addr; + uint8_t data; + unsigned int offset; + + assert(gpio_pin < PLAT_PL061_MAX_GPIOS); + + base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; + offset = gpio_pin % GPIOS_PER_PL061; + data = io_read8(base_addr + GPIOIE); + if (data & BIT(offset)) + return GPIO_INTERRUPT_ENABLE; + return GPIO_INTERRUPT_DISABLE; +} + +static void pl061_set_interrupt(struct gpio_chip *chip __unused, + unsigned int gpio_pin, + enum gpio_interrupt ena_dis) +{ + vaddr_t base_addr; + unsigned int offset; + + assert(gpio_pin < PLAT_PL061_MAX_GPIOS); + + base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; + offset = gpio_pin % GPIOS_PER_PL061; + if (ena_dis == GPIO_INTERRUPT_ENABLE) + io_setbits8(base_addr + GPIOIE, BIT(offset)); + else + io_clrbits8(base_addr + GPIOIE, BIT(offset)); +} + +/* + * Register the PL061 GPIO controller with a base address and the offset + * of start pin in this GPIO controller. + * This function is called after pl061_init(). + */ +void pl061_register(vaddr_t base_addr, unsigned int gpio_dev) +{ + assert(gpio_dev < MAX_GPIO_DEVICES); + + pl061_reg_base[gpio_dev] = base_addr; +} + +static const struct gpio_ops pl061_ops = { + .get_direction = pl061_get_direction, + .set_direction = pl061_set_direction, + .get_value = pl061_get_value, + .set_value = pl061_set_value, + .get_interrupt = pl061_get_interrupt, + .set_interrupt = pl061_set_interrupt, +}; +DECLARE_KEEP_PAGER(pl061_ops); + +/* + * Initialize PL061 GPIO controller + */ +void pl061_init(struct pl061_data *pd) +{ + COMPILE_TIME_ASSERT(PLAT_PL061_MAX_GPIOS > 0); + + assert(pd); + pd->chip.ops = &pl061_ops; +} + +enum pl061_mode_control pl061_get_mode_control(unsigned int gpio_pin) +{ + vaddr_t base_addr; + uint8_t data; + unsigned int offset; + + assert(gpio_pin < PLAT_PL061_MAX_GPIOS); + + base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; + offset = gpio_pin % GPIOS_PER_PL061; + data = io_read8(base_addr + GPIOAFSEL); + if (data & BIT(offset)) + return PL061_MC_HW; + return PL061_MC_SW; +} + +void pl061_set_mode_control(unsigned int gpio_pin, + enum pl061_mode_control hw_sw) +{ + vaddr_t base_addr; + unsigned int offset; + + assert(gpio_pin < PLAT_PL061_MAX_GPIOS); + + base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; + offset = gpio_pin % GPIOS_PER_PL061; + if (hw_sw == PL061_MC_HW) + io_setbits8(base_addr + GPIOAFSEL, BIT(offset)); + else + io_clrbits8(base_addr + GPIOAFSEL, BIT(offset)); +} diff --git a/optee/optee_os/core/drivers/pm/sam/at91_pm.c b/optee/optee_os/core/drivers/pm/sam/at91_pm.c new file mode 100644 index 0000000..86fb049 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/sam/at91_pm.c @@ -0,0 +1,484 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "at91_pm.h" + +#if CFG_ATMEL_PM_SUSPEND_MODE < AT91_PM_STANDBY || \ + CFG_ATMEL_PM_SUSPEND_MODE > AT91_PM_BACKUP +#error Invalid suspend mode, please check CFG_ATMEL_PM_SUSPEND_MODE +#endif + +#define AT91_SECUMOD_SYSR 0x04 +#define AT91_SECUMOD_RAMRDY 0x14 +#define AT91_SECUMOD_RAMRDY_READY BIT(0) + +static struct at91_pm_data soc_pm; + +/* Backup canary */ +static uint32_t canary = 0xA5A5A5A5; + +/* Backup mode information used by at91bootstrap */ +static struct at91bootstrap_bu { + uint32_t suspended; + uint32_t reserved; + uint32_t *canary; + uint32_t resume; +} *at91bootstrap_bu; + +static vaddr_t at91_suspend_sram_base; +static void (*at91_suspend_sram_fn)(struct at91_pm_data *); + +enum sm_handler_ret at91_pm_set_suspend_mode(struct thread_smc_args *args) +{ + unsigned int mode = args->a1; + + /* + * We don't expect this function to be called simultaneously while we + * are entering suspend/resume function. On sama5d2, this is not a + * problem since this SoC is a single core one but in order to prevent + * any other SoC support to be added without handling this concurrency, + * check that we are compiled for a single core. + */ + COMPILE_TIME_ASSERT(CFG_TEE_CORE_NB_CORE == 1); + + if (mode > AT91_PM_BACKUP) { + args->a0 = SAMA5_SMC_SIP_RETURN_EINVAL; + return SM_HANDLER_SMC_HANDLED; + } + DMSG("Setting suspend mode to %u", mode); + + args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS; + soc_pm.mode = mode; + + return SM_HANDLER_SMC_HANDLED; +} + +enum sm_handler_ret at91_pm_get_suspend_mode(struct thread_smc_args *args) +{ + args->a1 = soc_pm.mode; + args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS; + + return SM_HANDLER_SMC_HANDLED; +} + +static void at91_pm_copy_suspend_to_sram(void) +{ + memcpy((void *)at91_suspend_sram_base, &at91_pm_suspend_in_sram, + at91_pm_suspend_in_sram_sz); + + cache_op_inner(DCACHE_AREA_CLEAN, (void *)at91_suspend_sram_base, + at91_pm_suspend_in_sram_sz); + cache_op_inner(ICACHE_AREA_INVALIDATE, at91_suspend_sram_fn, + at91_pm_suspend_in_sram_sz); +} + +void atmel_pm_cpu_idle(void) +{ + uint32_t lpr0 = 0; + uint32_t saved_lpr0 = 0; + + saved_lpr0 = io_read32(soc_pm.ramc + AT91_DDRSDRC_LPR); + lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB; + lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN; + + io_write32(soc_pm.ramc + AT91_DDRSDRC_LPR, lpr0); + + cpu_idle(); + + io_write32(soc_pm.ramc + AT91_DDRSDRC_LPR, saved_lpr0); +} + +static void at91_sama5d2_config_shdwc_ws(vaddr_t shdwc, uint32_t *mode, + uint32_t *polarity) +{ + uint32_t val = 0; + + /* SHDWC.WUIR */ + val = io_read32(shdwc + AT91_SHDW_WUIR); + *mode |= val & AT91_SHDW_WKUPEN_MASK; + *polarity |= (val >> AT91_SHDW_WKUPT_SHIFT) & AT91_SHDW_WKUPT_MASK; +} + +static int at91_sama5d2_config_pmc_ws(vaddr_t pmc, uint32_t mode, + uint32_t polarity) +{ + io_write32(pmc + AT91_PMC_FSMR, mode); + io_write32(pmc + AT91_PMC_FSPR, polarity); + + return 0; +} + +struct wakeup_source_info { + unsigned int pmc_fsmr_bit; + unsigned int shdwc_mr_bit; + bool set_polarity; +}; + +static const struct wakeup_source_info ws_info[] = { + { .pmc_fsmr_bit = AT91_PMC_FSTT(10), .set_polarity = true }, + { .pmc_fsmr_bit = AT91_PMC_RTCAL, .shdwc_mr_bit = BIT(17) }, + { .pmc_fsmr_bit = AT91_PMC_USBAL }, + { .pmc_fsmr_bit = AT91_PMC_SDMMC_CD }, +}; + +struct wakeup_src { + const char *compatible; + const struct wakeup_source_info *info; +}; + +static const struct wakeup_src sama5d2_ws_ids[] = { + { .compatible = "atmel,sama5d2-gem", .info = &ws_info[0] }, + { .compatible = "atmel,at91rm9200-rtc", .info = &ws_info[1] }, + { .compatible = "atmel,sama5d3-udc", .info = &ws_info[2] }, + { .compatible = "atmel,at91rm9200-ohci", .info = &ws_info[2] }, + { .compatible = "usb-ohci", .info = &ws_info[2] }, + { .compatible = "atmel,at91sam9g45-ehci", .info = &ws_info[2] }, + { .compatible = "usb-ehci", .info = &ws_info[2] }, + { .compatible = "atmel,sama5d2-sdhci", .info = &ws_info[3] } +}; + +static bool dev_is_wakeup_source(const void *fdt, int node) +{ + return fdt_get_property(fdt, node, "wakeup-source", NULL); +} + +static int at91_pm_config_ws_ulp1(bool set) +{ + const struct wakeup_source_info *wsi = NULL; + const struct wakeup_src *wsrc = NULL; + unsigned int polarity = 0; + unsigned int mode = 0; + unsigned int val = 0; + unsigned int src = 0; + int node = 0; + + if (!set) { + io_write32(soc_pm.pmc + AT91_PMC_FSMR, mode); + return TEE_SUCCESS; + } + + at91_sama5d2_config_shdwc_ws(soc_pm.shdwc, &mode, &polarity); + + val = io_read32(soc_pm.shdwc + AT91_SHDW_MR); + + /* Loop through defined wakeup sources. */ + for (src = 0; src < ARRAY_SIZE(sama5d2_ws_ids); src++) { + wsrc = &sama5d2_ws_ids[src]; + wsi = wsrc->info; + + node = fdt_node_offset_by_compatible(soc_pm.fdt, -1, + wsrc->compatible); + while (node >= 0) { + if (dev_is_wakeup_source(soc_pm.fdt, node)) { + /* Check if enabled on SHDWC. */ + if (wsi->shdwc_mr_bit && + !(val & wsi->shdwc_mr_bit)) + goto next_node; + + mode |= wsi->pmc_fsmr_bit; + if (wsi->set_polarity) + polarity |= wsi->pmc_fsmr_bit; + } +next_node: + node = fdt_node_offset_by_compatible(soc_pm.fdt, node, + wsrc->compatible); + } + } + + if (!mode) { + EMSG("AT91: PM: no ULP1 wakeup sources found!"); + return TEE_ERROR_BAD_STATE; + } + + at91_sama5d2_config_pmc_ws(soc_pm.pmc, mode, polarity); + + return TEE_SUCCESS; +} + +/* + * Verify that all the clocks are correct before entering + * slow-clock mode. + */ +static bool at91_pm_verify_clocks(void) +{ + int i = 0; + uint32_t scsr = 0; + + scsr = io_read32(soc_pm.pmc + AT91_PMC_SCSR); + + /* USB must not be using PLLB */ + if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) { + EMSG("AT91: PM - Suspend-to-RAM with USB still active"); + return false; + } + + /* PCK0..PCK3 must be disabled, or configured to use clk32k */ + for (i = 0; i < 4; i++) { + uint32_t css = 0; + + if ((scsr & (AT91_PMC_PCK0 << i)) == 0) + continue; + css = io_read32(soc_pm.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; + if (css != AT91_PMC_CSS_SLOW) { + EMSG("AT91: PM - Suspend-to-RAM with PCK%d src %"PRId32, + i, css); + return false; + } + } + + return true; +} + +static TEE_Result at91_write_backup_data(void) +{ + uint32_t val = 0; + + while (true) { + val = io_read32(soc_pm.secumod + AT91_SECUMOD_RAMRDY); + if (val & AT91_SECUMOD_RAMRDY_READY) + break; + } + + io_write32((vaddr_t)&at91bootstrap_bu->suspended, 1); + io_write32((vaddr_t)&at91bootstrap_bu->canary, virt_to_phys(&canary)); + io_write32((vaddr_t)&at91bootstrap_bu->resume, + virt_to_phys((void *)(vaddr_t)at91_pm_cpu_resume)); + + return TEE_SUCCESS; +} + +static TEE_Result at91_enter_backup(void) +{ + int ret = -1; + TEE_Result res = TEE_ERROR_GENERIC; + + res = at91_write_backup_data(); + if (res) + return res; + + pm_change_state(PM_OP_SUSPEND, 0); + ret = sm_pm_cpu_suspend((uint32_t)&soc_pm, + (void *)at91_suspend_sram_fn); + if (ret < 0) { + DMSG("Suspend failed"); + res = TEE_ERROR_BAD_STATE; + } else { + res = TEE_SUCCESS; + } + + pm_change_state(PM_OP_RESUME, 0); + if (res) + return res; + + /* SRAM content is lost after resume */ + at91_pm_copy_suspend_to_sram(); + + return TEE_SUCCESS; +} + +TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + DMSG("Entering suspend mode %d", soc_pm.mode); + + if (soc_pm.mode >= AT91_PM_ULP0) { + if (!at91_pm_verify_clocks()) + return TEE_ERROR_BAD_STATE; + } + + if (soc_pm.mode == AT91_PM_ULP1) + at91_pm_config_ws_ulp1(true); + + sm_save_unbanked_regs(&nsec->ub_regs); + + if (soc_pm.mode == AT91_PM_BACKUP) { + res = at91_enter_backup(); + } else { + at91_suspend_sram_fn(&soc_pm); + res = TEE_SUCCESS; + } + + if (soc_pm.mode == AT91_PM_ULP1) + at91_pm_config_ws_ulp1(false); + + sm_restore_unbanked_regs(&nsec->ub_regs); + + /* + * If the system went to backup mode, register state was lost and must + * be restored by jumping to the user provided entry point + */ + if (res == TEE_SUCCESS && soc_pm.mode == AT91_PM_BACKUP) + nsec->mon_lr = entry; + + DMSG("Exiting suspend mode %d, res %"PRIx32, soc_pm.mode, res); + + return res; +} + +static TEE_Result at91_pm_dt_dram_init(const void *fdt) +{ + int node = -1; + size_t size = 0; + + node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d3-ddramc"); + if (node < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (dt_map_dev(fdt, node, &soc_pm.ramc, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result at91_pm_backup_init(const void *fdt) +{ + int node = -1; + size_t size = 0; + + node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-sfrbu"); + if (node < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (dt_map_dev(fdt, node, &soc_pm.sfrbu, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + if (fdt_get_status(fdt, node) == DT_STATUS_OK_SEC) + matrix_configure_periph_secure(AT91C_ID_SFRBU); + + return TEE_SUCCESS; +} + +static TEE_Result at91_pm_sram_init(const void *fdt) +{ + int node = -1; + size_t size = 0; + paddr_t at91_suspend_sram_pbase; + size_t suspend_sz = at91_pm_suspend_in_sram_sz; + + node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-sram"); + if (node < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_GENERIC; + + if (dt_map_dev(fdt, node, &at91_suspend_sram_base, &size, + DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + at91_suspend_sram_pbase = virt_to_phys((void *)at91_suspend_sram_base); + + /* Map the secure ram suspend code to be executable */ + at91_suspend_sram_fn = core_mmu_add_mapping(MEM_AREA_TEE_RAM, + at91_suspend_sram_pbase, + suspend_sz); + if (!at91_suspend_sram_fn) { + EMSG("Failed to remap sram as executable"); + return TEE_ERROR_GENERIC; + } + + at91_pm_copy_suspend_to_sram(); + + return TEE_SUCCESS; +} + +static TEE_Result at91_securam_init(const void *fdt) +{ + int node = -1; + size_t size = 0; + struct clk *clk = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-securam"); + if (node < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_GENERIC; + + if (dt_map_dev(fdt, node, &soc_pm.securam, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + res = clk_dt_get_by_index(fdt, node, 0, &clk); + if (res) + return res; + + if (clk_enable(clk)) + return TEE_ERROR_GENERIC; + + if (size < sizeof(struct at91bootstrap_bu)) + return TEE_ERROR_SHORT_BUFFER; + + at91bootstrap_bu = (void *)soc_pm.securam; + + node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-secumod"); + if (node < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) + return TEE_ERROR_GENERIC; + + if (dt_map_dev(fdt, node, &soc_pm.secumod, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result sama5d2_pm_init_all(const void *fdt, vaddr_t shdwc) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + soc_pm.fdt = fdt; + soc_pm.shdwc = shdwc; + soc_pm.pmc = at91_pmc_get_base(); + if (!soc_pm.pmc) + return TEE_ERROR_GENERIC; + + soc_pm.mode = CFG_ATMEL_PM_SUSPEND_MODE; + + res = at91_securam_init(fdt); + if (res) + return res; + + res = at91_pm_dt_dram_init(fdt); + if (res) + return res; + + res = at91_pm_backup_init(fdt); + if (res) + return res; + + res = at91_pm_sram_init(fdt); + if (res) + return res; + + return TEE_SUCCESS; +} + +TEE_Result sama5d2_pm_init(const void *fdt, vaddr_t shdwc) +{ + if (sama5d2_pm_init_all(fdt, shdwc)) + panic("Failed to setup PM for sama5d2"); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/pm/sam/at91_pm.h b/optee/optee_os/core/drivers/pm/sam/at91_pm.h new file mode 100644 index 0000000..47b2d72 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/sam/at91_pm.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Microchip + */ + +#ifndef AT91_PM_H +#define AT91_PM_H + +#define AT91_PM_STANDBY 0x00 +#define AT91_PM_ULP0 0x01 +#define AT91_PM_ULP0_FAST 0x02 +#define AT91_PM_ULP1 0x03 +#define AT91_PM_BACKUP 0x04 + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include + +struct at91_pm_data { + vaddr_t shdwc; + vaddr_t securam; + vaddr_t secumod; + vaddr_t sfrbu; + vaddr_t pmc; + vaddr_t ramc; + unsigned int mode; + const void *fdt; +}; + +void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data); +void at91_pm_cpu_resume(void); +extern uint32_t at91_pm_suspend_in_sram_sz; + +void at91_pm_resume(struct at91_pm_data *pm_data); + +#endif /* __ASSEMBLER__ */ + +#endif /* AT91_PM_H */ diff --git a/optee/optee_os/core/drivers/pm/sam/pm-defines.c b/optee/optee_os/core/drivers/pm/sam/pm-defines.c new file mode 100644 index 0000000..94e31b8 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/sam/pm-defines.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Microchip + */ + +#include "at91_pm.h" +#include +#include +#include + +DEFINES +{ + DEFINE(PM_DATA_PMC, offsetof(struct at91_pm_data, pmc)); + DEFINE(PM_DATA_RAMC0, offsetof(struct at91_pm_data, ramc)); + DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode)); + DEFINE(PM_DATA_SHDWC, offsetof(struct at91_pm_data, shdwc)); + DEFINE(PM_DATA_SFRBU, offsetof(struct at91_pm_data, sfrbu)); +} diff --git a/optee/optee_os/core/drivers/pm/sam/pm_resume.S b/optee/optee_os/core/drivers/pm/sam/pm_resume.S new file mode 100644 index 0000000..367fee1 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/sam/pm_resume.S @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include + +FUNC at91_pm_cpu_resume, : +UNWIND( .cantunwind) + cps #CPSR_MODE_MON + + blx plat_cpu_reset_early + + b sm_pm_cpu_resume +END_FUNC at91_pm_cpu_resume diff --git a/optee/optee_os/core/drivers/pm/sam/pm_suspend.S b/optee/optee_os/core/drivers/pm/sam/pm_suspend.S new file mode 100644 index 0000000..9367d23 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/sam/pm_suspend.S @@ -0,0 +1,520 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ +/* + * This file was imported from Linux arch/arm/mach-at91/pm_suspend.S and + * relicensed with dual GPL-2.0/BSD-2-Clause with Microchip agreement. + * + * Copyright (c) 2021, Microchip + */ + +#include +#include +#include +#include +#include +#include + +#include "at91_pm.h" + +#define SRAMC_SELF_FRESH_ACTIVE 0x01 +#define SRAMC_SELF_FRESH_EXIT 0x00 + +pmc .req r0 +tmp1 .req r4 +tmp2 .req r5 +tmp3 .req r6 + +/* + * Wait until master clock is ready (after switching master clock source) + */ +.macro wait_mckrdy +1: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_MCKRDY + beq 1b +.endm + +/* + * Wait until master oscillator has stabilized. + */ +.macro wait_moscrdy +1: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_MOSCS + beq 1b +.endm + +/* + * Wait for main oscillator selection is done + */ +.macro wait_moscsels +1: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_MOSCSELS + beq 1b +.endm + +/* + * Put the processor to enter the idle state + */ +.macro at91_cpu_idle + + mov tmp1, #AT91_PMC_PCK + str tmp1, [pmc, #AT91_PMC_SCDR] + + dsb + + wfi @ Wait For Interrupt + +.endm + +.section .text.psci.suspend + +.arm + + +#define SUSPEND_FUNC(__name) \ +__name: + +#define SUSPEND_END_FUNC(__name) \ + .size __name, .-__name + +.macro check_fit_in_sram since + .if (. - \since) > 0x10000 + .error "Suspend assembly code exceeds dedicated SRAM size" + .endif +.endm + +/* + * void at91_suspend_sram_fn(struct at91_pm_data*) + * @input param: + * @r0: base address of struct at91_pm_data + */ +.align 3 +.global at91_pm_suspend_in_sram +SUSPEND_FUNC(at91_pm_suspend_in_sram) + /* Save registers on stack */ + stmfd sp!, {r4 - r12, lr} + + /* Drain write buffer */ + mov tmp1, #0 + mcr p15, 0, tmp1, c7, c10, 4 + + ldr tmp1, [r0, #PM_DATA_PMC] + str tmp1, .pmc_base + ldr tmp1, [r0, #PM_DATA_RAMC0] + str tmp1, .sramc_base + ldr tmp1, [r0, #PM_DATA_MODE] + str tmp1, .pm_mode + /* Both ldrne below are here to preload their address in the TLB */ + ldr tmp1, [r0, #PM_DATA_SHDWC] + str tmp1, .shdwc + cmp tmp1, #0 + ldrne tmp2, [tmp1, #0] + ldr tmp1, [r0, #PM_DATA_SFRBU] + str tmp1, .sfrbu + cmp tmp1, #0 + ldrne tmp2, [tmp1, #0x10] + + /* Active the self-refresh mode */ + mov r0, #SRAMC_SELF_FRESH_ACTIVE + bl at91_sramc_self_refresh + + ldr r0, .pm_mode + cmp r0, #AT91_PM_STANDBY + beq standby + cmp r0, #AT91_PM_BACKUP + beq backup_mode + + bl at91_ulp_mode + b exit_suspend + +standby: + /* Wait for interrupt */ + ldr pmc, .pmc_base + at91_cpu_idle + b exit_suspend + +backup_mode: + bl at91_backup_mode + b exit_suspend + +exit_suspend: + /* Exit the self-refresh mode */ + mov r0, #SRAMC_SELF_FRESH_EXIT + bl at91_sramc_self_refresh + + /* Restore registers, and return */ + ldmfd sp!, {r4 - r12, pc} +SUSPEND_END_FUNC(at91_pm_suspend_in_sram) + +SUSPEND_FUNC(at91_backup_mode) + /* Switch the master clock source to slow clock. */ + ldr pmc, .pmc_base + ldr tmp1, [pmc, #AT91_PMC_MCKR] + bic tmp1, tmp1, #AT91_PMC_CSS + str tmp1, [pmc, #AT91_PMC_MCKR] + + wait_mckrdy + + /*BUMEN*/ + ldr r0, .sfrbu + mov tmp1, #0x1 + str tmp1, [r0, #0x10] + + /* Shutdown */ + ldr r0, .shdwc + mov tmp1, #0xA5000000 + add tmp1, tmp1, #0x1 + str tmp1, [r0, #0] +SUSPEND_END_FUNC(at91_backup_mode) + +.macro at91_pm_ulp0_mode + ldr pmc, .pmc_base + ldr tmp2, .pm_mode + + /* Check if ULP0 fast variant has been requested. */ + cmp tmp2, #AT91_PM_ULP0_FAST + bne 0f + + /* Set highest prescaler for power saving */ + ldr tmp1, [pmc, #AT91_PMC_MCKR] + bic tmp1, tmp1, #AT91_PMC_PRES + orr tmp1, tmp1, #AT91_PMC_PRES_64 + str tmp1, [pmc, #AT91_PMC_MCKR] + wait_mckrdy + b 1f + +0: + /* Turn off the crystal oscillator */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + bic tmp1, tmp1, #AT91_PMC_MOSCEN + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + /* Save RC oscillator state */ + ldr tmp1, [pmc, #AT91_PMC_SR] + str tmp1, .saved_osc_status + tst tmp1, #AT91_PMC_MOSCRCS + bne 1f + + /* Turn off RC oscillator */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + bic tmp1, tmp1, #AT91_PMC_MOSCRCEN + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + /* Wait main RC disabled done */ +2: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_MOSCRCS + bne 2b + + /* Wait for interrupt */ +1: at91_cpu_idle + + /* Check if ULP0 fast variant has been requested. */ + cmp tmp2, #AT91_PM_ULP0_FAST + bne 5f + + /* Set lowest prescaler for fast resume. */ + ldr tmp1, [pmc, #AT91_PMC_MCKR] + bic tmp1, tmp1, #AT91_PMC_PRES + str tmp1, [pmc, #AT91_PMC_MCKR] + wait_mckrdy + b 6f + +5: /* Restore RC oscillator state */ + ldr tmp1, .saved_osc_status + tst tmp1, #AT91_PMC_MOSCRCS + beq 4f + + /* Turn on RC oscillator */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + orr tmp1, tmp1, #AT91_PMC_MOSCRCEN + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + /* Wait main RC stabilization */ +3: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_MOSCRCS + beq 3b + + /* Turn on the crystal oscillator */ +4: ldr tmp1, [pmc, #AT91_CKGR_MOR] + orr tmp1, tmp1, #AT91_PMC_MOSCEN + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + wait_moscrdy +6: +.endm + +/** + * Note: This procedure only applies on the platform which uses + * the external crystal oscillator as a main clock source. + */ +.macro at91_pm_ulp1_mode + ldr pmc, .pmc_base + + /* Save RC oscillator state and check if it is enabled. */ + ldr tmp1, [pmc, #AT91_PMC_SR] + str tmp1, .saved_osc_status + tst tmp1, #AT91_PMC_MOSCRCS + bne 2f + + /* Enable RC oscillator */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + orr tmp1, tmp1, #AT91_PMC_MOSCRCEN + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + /* Wait main RC stabilization */ +1: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_MOSCRCS + beq 1b + + /* Switch the main clock source to 12-MHz RC oscillator */ +2: ldr tmp1, [pmc, #AT91_CKGR_MOR] + bic tmp1, tmp1, #AT91_PMC_MOSCSEL + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + wait_moscsels + + /* Disable the crystal oscillator */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + bic tmp1, tmp1, #AT91_PMC_MOSCEN + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + /* Switch the master clock source to main clock */ + ldr tmp1, [pmc, #AT91_PMC_MCKR] + bic tmp1, tmp1, #AT91_PMC_CSS + orr tmp1, tmp1, #AT91_PMC_CSS_MAIN + str tmp1, [pmc, #AT91_PMC_MCKR] + + wait_mckrdy + + /* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + orr tmp1, tmp1, #AT91_PMC_WAITMODE + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + /* Quirk for SAM9X60's PMC */ + nop + nop + + wait_mckrdy + + /* Enable the crystal oscillator */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + orr tmp1, tmp1, #AT91_PMC_MOSCEN + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + wait_moscrdy + + /* Switch the master clock source to slow clock */ + ldr tmp1, [pmc, #AT91_PMC_MCKR] + bic tmp1, tmp1, #AT91_PMC_CSS + str tmp1, [pmc, #AT91_PMC_MCKR] + + wait_mckrdy + + /* Switch main clock source to crystal oscillator */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + orr tmp1, tmp1, #AT91_PMC_MOSCSEL + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + wait_moscsels + + /* Switch the master clock source to main clock */ + ldr tmp1, [pmc, #AT91_PMC_MCKR] + bic tmp1, tmp1, #AT91_PMC_CSS + orr tmp1, tmp1, #AT91_PMC_CSS_MAIN + str tmp1, [pmc, #AT91_PMC_MCKR] + + wait_mckrdy + + /* Restore RC oscillator state */ + ldr tmp1, .saved_osc_status + tst tmp1, #AT91_PMC_MOSCRCS + bne 3f + + /* Disable RC oscillator */ + ldr tmp1, [pmc, #AT91_CKGR_MOR] + bic tmp1, tmp1, #AT91_PMC_MOSCRCEN + bic tmp1, tmp1, #AT91_PMC_KEY_MASK + orr tmp1, tmp1, #AT91_PMC_KEY + str tmp1, [pmc, #AT91_CKGR_MOR] + + /* Wait RC oscillator disable done */ +4: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_MOSCRCS + bne 4b + +3: +.endm + +.macro at91_plla_disable + /* Save PLLA setting and disable it */ + ldr tmp1, [pmc, #AT91_CKGR_PLLAR] + str tmp1, .saved_pllar + + /* Disable PLLA. */ + mov tmp1, #AT91_PMC_PLLCOUNT + orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ + str tmp1, [pmc, #AT91_CKGR_PLLAR] +2: +.endm + +.macro at91_plla_enable + ldr tmp2, .saved_pllar + + /* Restore PLLA setting */ + str tmp2, [pmc, #AT91_CKGR_PLLAR] + + /* Enable PLLA. */ + tst tmp2, #(AT91_PMC_MUL & 0xff0000) + bne 1f + tst tmp2, #(AT91_PMC_MUL & ~0xff0000) + beq 2f + +1: ldr tmp1, [pmc, #AT91_PMC_SR] + tst tmp1, #AT91_PMC_LOCKA + beq 1b +2: +.endm + +SUSPEND_FUNC(at91_ulp_mode) + ldr pmc, .pmc_base + ldr tmp3, .pm_mode + + /* Save Master clock setting */ + ldr tmp1, [pmc, #AT91_PMC_MCKR] + str tmp1, .saved_mckr + + /* + * Set master clock source to: + * - MAINCK if using ULP0 fast variant + * - slow clock, otherwise + */ + bic tmp1, tmp1, #AT91_PMC_CSS + cmp tmp3, #AT91_PM_ULP0_FAST + bne save_mck + orr tmp1, tmp1, #AT91_PMC_CSS_MAIN +save_mck: + str tmp1, [pmc, #AT91_PMC_MCKR] + + wait_mckrdy + + at91_plla_disable + + cmp tmp3, #AT91_PM_ULP1 + beq ulp1_mode + + at91_pm_ulp0_mode + b ulp_exit + +ulp1_mode: + at91_pm_ulp1_mode + b ulp_exit + +ulp_exit: + ldr pmc, .pmc_base + + at91_plla_enable + + /* + * Restore master clock setting + */ + ldr tmp2, .saved_mckr + str tmp2, [pmc, #AT91_PMC_MCKR] + + wait_mckrdy + + mov pc, lr +SUSPEND_END_FUNC(at91_ulp_mode) + +/* + * void at91_sramc_self_refresh(unsigned int is_active) + * + * @input param: + * @r0: 1 - active self-refresh mode + * 0 - exit self-refresh mode + * register usage: + * @r2: base address of the sram controller + */ + +SUSPEND_FUNC(at91_sramc_self_refresh) + ldr r2, .sramc_base + + /* + * DDR Memory controller + */ + tst r0, #SRAMC_SELF_FRESH_ACTIVE + beq ddrc_exit_sf + + /* LPDDR1 --> force DDR2 mode during self-refresh */ + ldr r3, [r2, #AT91_DDRSDRC_MDR] + str r3, .saved_sam9_mdr + bic r3, r3, #~AT91_DDRSDRC_MD + cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR + ldreq r3, [r2, #AT91_DDRSDRC_MDR] + biceq r3, r3, #AT91_DDRSDRC_MD + orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 + streq r3, [r2, #AT91_DDRSDRC_MDR] + + /* Active DDRC self-refresh mode */ + ldr r3, [r2, #AT91_DDRSDRC_LPR] + str r3, .saved_sam9_lpr + bic r3, r3, #AT91_DDRSDRC_LPCB + orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH + str r3, [r2, #AT91_DDRSDRC_LPR] + + b exit_sramc_sf + +ddrc_exit_sf: + /* Restore MDR in case of LPDDR1 */ + ldr r3, .saved_sam9_mdr + str r3, [r2, #AT91_DDRSDRC_MDR] + /* Restore LPR on AT91 with DDRAM */ + ldr r3, .saved_sam9_lpr + str r3, [r2, #AT91_DDRSDRC_LPR] + +exit_sramc_sf: + mov pc, lr +SUSPEND_END_FUNC(at91_sramc_self_refresh) + +.pmc_base: + .word 0 +.sramc_base: + .word 0 +.shdwc: + .word 0 +.sfrbu: + .word 0 +.pm_mode: + .word 0 +.saved_mckr: + .word 0 +.saved_pllar: + .word 0 +.saved_sam9_lpr: + .word 0 +.saved_sam9_mdr: + .word 0 +.saved_osc_status: + .word 0 + +.global at91_pm_suspend_in_sram_sz +at91_pm_suspend_in_sram_sz: + .word .-at91_pm_suspend_in_sram + +check_fit_in_sram at91_pm_suspend_in_sram diff --git a/optee/optee_os/core/drivers/pm/sam/sub.mk b/optee/optee_os/core/drivers/pm/sam/sub.mk new file mode 100644 index 0000000..66a5228 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/sam/sub.mk @@ -0,0 +1,2 @@ +srcs-y += at91_pm.c pm_suspend.S pm_resume.S +asm-defines-y += pm-defines.c \ No newline at end of file diff --git a/optee/optee_os/core/drivers/pm/sub.mk b/optee/optee_os/core/drivers/pm/sub.mk new file mode 100644 index 0000000..7e08e75 --- /dev/null +++ b/optee/optee_os/core/drivers/pm/sub.mk @@ -0,0 +1 @@ +subdirs-$(CFG_ATMEL_PM) += sam \ No newline at end of file diff --git a/optee/optee_os/core/drivers/rstctrl/rstctrl.c b/optee/optee_os/core/drivers/rstctrl/rstctrl.c new file mode 100644 index 0000000..fa453d4 --- /dev/null +++ b/optee/optee_os/core/drivers/rstctrl/rstctrl.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +/* Global reset controller access lock */ + +TEE_Result rstctrl_get_exclusive(struct rstctrl *rstctrl) +{ + uint32_t exceptions = 0; + TEE_Result res = TEE_ERROR_ACCESS_CONFLICT; + static unsigned int rstctrl_lock = SPINLOCK_UNLOCK; + + exceptions = cpu_spin_lock_xsave(&rstctrl_lock); + + if (!rstctrl->exclusive) { + rstctrl->exclusive = true; + res = TEE_SUCCESS; + } + + cpu_spin_unlock_xrestore(&rstctrl_lock, exceptions); + + return res; +} + +void rstctrl_put_exclusive(struct rstctrl *rstctrl) +{ + assert(rstctrl->exclusive); + + WRITE_ONCE(rstctrl->exclusive, false); +} + +TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset, + const char *name, struct rstctrl **rstctrl) +{ + int index = 0; + + index = fdt_stringlist_search(fdt, nodeoffset, "reset-names", name); + if (index < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + return rstctrl_dt_get_by_index(fdt, nodeoffset, index, rstctrl); +} diff --git a/optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c b/optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c new file mode 100644 index 0000000..ac05df4 --- /dev/null +++ b/optee/optee_os/core/drivers/rstctrl/stm32_rstctrl.c @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2022, Linaro Limited + * Copyright (c) 2018-2022, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RESET_ID_MASK GENMASK_32(31, 5) +#define RESET_ID_SHIFT 5 +#define RESET_BIT_POS_MASK GENMASK_32(4, 0) +#define RESET_OFFSET_MAX 1024 + +/* Exposed rstctrl instance */ +struct stm32_rstline { + unsigned int id; + struct rstctrl rstctrl; + SLIST_ENTRY(stm32_rstline) link; +}; + +static SLIST_HEAD(, stm32_rstline) stm32_rst_list = + SLIST_HEAD_INITIALIZER(stm32_rst_list); + +static size_t reset_id2reg_offset(unsigned int id) +{ + size_t offset = (id & RESET_ID_MASK) >> RESET_ID_SHIFT; + + assert(offset < RESET_OFFSET_MAX); + return offset * sizeof(uint32_t); +} + +static uint8_t reset_id2reg_bit_pos(unsigned int reset_id) +{ + uint8_t pos = reset_id & RESET_BIT_POS_MASK; + + assert(pos < 32); + return pos; +} + +static struct stm32_rstline *to_rstline(struct rstctrl *rstctrl) +{ + assert(rstctrl); + + return container_of(rstctrl, struct stm32_rstline, rstctrl); +} + +static TEE_Result reset_assert(struct rstctrl *rstctrl, unsigned int to_us) +{ + unsigned int id = to_rstline(rstctrl)->id; + vaddr_t rcc_base = stm32_rcc_base(); + uint32_t bit_mask = 0; + size_t offset = 0; + + switch (id) { + case MCU_HOLD_BOOT_R: + /* + * The RCC_MP_GCR is a read/write register. + * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit + */ + io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); + + return TEE_SUCCESS; + case MCU_R: + /* MCU reset can only be written */ + to_us = 0; + break; + default: + break; + } + + offset = reset_id2reg_offset(id); + bit_mask = BIT(reset_id2reg_bit_pos(id)); + + io_write32(rcc_base + offset, bit_mask); + + if (to_us) { + uint64_t timeout_ref = timeout_init_us(to_us); + + while (!(io_read32(rcc_base + offset) & bit_mask)) + if (timeout_elapsed(timeout_ref)) + break; + + if (!(io_read32(rcc_base + offset) & bit_mask)) + return TEE_ERROR_SECURITY; + } + + return TEE_SUCCESS; +} + +static TEE_Result reset_deassert(struct rstctrl *rstctrl, unsigned int to_us) +{ + unsigned int id = to_rstline(rstctrl)->id; + vaddr_t rcc_base = stm32_rcc_base(); + uint32_t bit_mask = 0; + size_t offset = 0; + + switch (id) { + case MCU_HOLD_BOOT_R: + /* + * The RCC_MP_GCR is a read/write register. + * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit + */ + io_setbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); + + return TEE_SUCCESS; + case MCU_R: + /* MCU reset deasserts by its own */ + return TEE_SUCCESS; + default: + break; + } + + offset = reset_id2reg_offset(id) + RCC_MP_RSTCLRR_OFFSET; + bit_mask = BIT(reset_id2reg_bit_pos(id)); + + io_write32(rcc_base + offset, bit_mask); + + if (to_us) { + uint64_t timeout_ref = timeout_init_us(to_us); + + while ((io_read32(rcc_base + offset) & bit_mask)) + if (timeout_elapsed(timeout_ref)) + break; + + if (io_read32(rcc_base + offset) & bit_mask) + return TEE_ERROR_SECURITY; + } + + return TEE_SUCCESS; +} + +static struct rstctrl_ops stm32_rstctrl_ops = { + .assert_level = reset_assert, + .deassert_level = reset_deassert, +}; + +static struct stm32_rstline *find_rstctrl_device(unsigned int control_id) +{ + struct stm32_rstline *stm32_rstline = NULL; + + SLIST_FOREACH(stm32_rstline, &stm32_rst_list, link) + if (stm32_rstline->id == control_id) + break; + + return stm32_rstline; +} + +static struct stm32_rstline *find_or_allocate_rstline(unsigned int binding_id) +{ + struct stm32_rstline *stm32_rstline = find_rstctrl_device(binding_id); + + if (stm32_rstline) + return stm32_rstline; + + stm32_rstline = calloc(1, sizeof(*stm32_rstline)); + if (stm32_rstline) { + stm32_rstline->rstctrl.ops = &stm32_rstctrl_ops; + stm32_rstline->id = binding_id; + SLIST_INSERT_HEAD(&stm32_rst_list, stm32_rstline, link); + } + + return stm32_rstline; +} + +struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id) +{ + struct stm32_rstline *rstline = find_or_allocate_rstline(binding_id); + + assert(rstline); + return &rstline->rstctrl; +} + +static struct rstctrl *stm32_rstctrl_get_dev(struct dt_driver_phandle_args *arg, + void *priv_data __unused, + TEE_Result *res) +{ + struct stm32_rstline *stm32_rstline = NULL; + uintptr_t control_id = 0; + + if (arg->args_count != 1) { + *res = TEE_ERROR_BAD_PARAMETERS; + return NULL; + } + control_id = arg->args[0]; + + stm32_rstline = find_or_allocate_rstline(control_id); + if (!stm32_rstline) { + *res = TEE_ERROR_OUT_OF_MEMORY; + return NULL; + } + + *res = TEE_SUCCESS; + return &stm32_rstline->rstctrl; +} + +static TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs, + const void *compat_data __unused) +{ + struct dt_node_info info = { }; + + assert(rstctrl_ops_is_valid(&stm32_rstctrl_ops)); + + fdt_fill_device_info(fdt, &info, offs); + + assert(info.reg == RCC_BASE && + info.reg_size != DT_INFO_INVALID_REG_SIZE); + + return rstctrl_register_provider(fdt, offs, stm32_rstctrl_get_dev, + NULL); +} + +static const struct dt_device_match stm32_rstctrl_match_table[] = { + { .compatible = "st,stm32mp1-rcc" }, + { .compatible = "st,stm32mp1-rcc-secure" }, + { } +}; + +DEFINE_DT_DRIVER(stm32_rstctrl_dt_driver) = { + .name = "stm32_rstctrl", + .type = DT_DRIVER_RSTCTRL, + .match_table = stm32_rstctrl_match_table, + .probe = stm32_rstctrl_provider_probe, +}; diff --git a/optee/optee_os/core/drivers/rstctrl/sub.mk b/optee/optee_os/core/drivers/rstctrl/sub.mk new file mode 100644 index 0000000..0466b62 --- /dev/null +++ b/optee/optee_os/core/drivers/rstctrl/sub.mk @@ -0,0 +1,2 @@ +srcs-y += rstctrl.c +srcs-$(CFG_STM32_RSTCTRL) += stm32_rstctrl.c diff --git a/optee/optee_os/core/drivers/rtc/rtc.c b/optee/optee_os/core/drivers/rtc/rtc.c new file mode 100644 index 0000000..97d3f83 --- /dev/null +++ b/optee/optee_os/core/drivers/rtc/rtc.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + */ + +#include +#include +#include + +struct rtc *rtc_device; + +void rtc_register(struct rtc *rtc) +{ + /* One RTC is supported only */ + assert(!rtc_device); + + /* RTC should *at least* allow to get the time */ + assert(rtc && rtc->ops && rtc->ops->get_time); + + rtc_device = rtc; +} diff --git a/optee/optee_os/core/drivers/rtc/sub.mk b/optee/optee_os/core/drivers/rtc/sub.mk new file mode 100644 index 0000000..87723ed --- /dev/null +++ b/optee/optee_os/core/drivers/rtc/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_DRIVERS_RTC) += rtc.c diff --git a/optee/optee_os/core/drivers/scif.c b/optee/optee_os/core/drivers/scif.c new file mode 100644 index 0000000..32c382d --- /dev/null +++ b/optee/optee_os/core/drivers/scif.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, GlobalLogic + * Copyright (c) 2017, 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 +#include +#include + +#define SCIF_SCSCR (0x08) +#define SCIF_SCFSR (0x10) +#define SCIF_SCFTDR (0x0C) +#define SCIF_SCFCR (0x18) +#define SCIF_SCFDR (0x1C) + +#define SCSCR_TE BIT(5) +#define SCFSR_TDFE BIT(5) +#define SCFSR_TEND BIT(6) + +#define SCFDR_T_SHIFT 8 + +#define SCIF_TX_FIFO_SIZE 16 + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct scif_uart_data *pd = + container_of(chip, struct scif_uart_data, chip); + + return io_pa_or_va(&pd->base, SCIF_REG_SIZE); +} + +static void scif_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read16(base + SCIF_SCFSR) & SCFSR_TEND)) + ; +} + +static void scif_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + /* Wait until there is space in the FIFO */ + while ((io_read16(base + SCIF_SCFDR) >> SCFDR_T_SHIFT) >= + SCIF_TX_FIFO_SIZE) + ; + io_write8(base + SCIF_SCFTDR, ch); + io_clrbits16(base + SCIF_SCFSR, SCFSR_TEND | SCFSR_TDFE); +} + +static const struct serial_ops scif_uart_ops = { + .flush = scif_uart_flush, + .putc = scif_uart_putc, +}; +DECLARE_KEEP_PAGER(scif_uart_ops); + +void scif_uart_init(struct scif_uart_data *pd, paddr_t pbase) +{ + vaddr_t base; + + pd->base.pa = pbase; + pd->chip.ops = &scif_uart_ops; + + base = io_pa_or_va(&pd->base, SCIF_REG_SIZE); + + /* Set Transmit Enable in Control register */ + io_setbits16(base + SCIF_SCSCR, SCSCR_TE); + + scif_uart_flush(&pd->chip); +} diff --git a/optee/optee_os/core/drivers/scmi-msg/base.c b/optee/optee_os/core/drivers/scmi-msg/base.c new file mode 100644 index 0000000..f43c6db --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/base.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include + +#include "base.h" +#include "common.h" + +static bool message_id_is_supported(unsigned int message_id); + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_BASE, + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + size_t protocol_count = plat_scmi_protocol_count(); + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* Null agent count since agent discovery is not supported */ + .attributes = SCMI_BASE_PROTOCOL_ATTRIBUTES(protocol_count, 0), + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_vendor(struct scmi_msg *msg) +{ + const char *name = plat_scmi_vendor_name(); + struct scmi_base_discover_vendor_p2a return_values = { + .status = SCMI_SUCCESS, + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + COPY_NAME_IDENTIFIER(return_values.vendor_identifier, name); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_sub_vendor(struct scmi_msg *msg) +{ + const char *name = plat_scmi_sub_vendor_name(); + struct scmi_base_discover_sub_vendor_p2a return_values = { + .status = SCMI_SUCCESS, + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + COPY_NAME_IDENTIFIER(return_values.sub_vendor_identifier, name); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_implementation_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_IMPL_VERSION, + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static unsigned int count_protocols_in_list(const uint8_t *protocol_list) +{ + unsigned int count = 0; + + if (protocol_list) + while (protocol_list[count]) + count++; + + return count; +} + +static void discover_list_protocols(struct scmi_msg *msg) +{ + const struct scmi_base_discover_list_protocols_a2p *a2p = NULL; + struct scmi_base_discover_list_protocols_p2a p2a = { + .status = SCMI_SUCCESS, + }; + const uint8_t *list = NULL; + unsigned int count = 0; + + if (msg->in_size != sizeof(*a2p)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + a2p = (void *)msg->in; + + list = plat_scmi_protocol_list(msg->channel_id); + count = count_protocols_in_list(list); + if (count > a2p->skip) + count = MIN(count - a2p->skip, msg->out_size - sizeof(p2a)); + else + count = 0; + + p2a.num_protocols = count; + + memcpy(msg->out, &p2a, sizeof(p2a)); + memcpy(msg->out + sizeof(p2a), list + a2p->skip, count); + msg->out_size_out = sizeof(p2a) + ROUNDUP(count, sizeof(uint32_t)); +} + +static const scmi_msg_handler_t scmi_base_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_BASE_DISCOVER_VENDOR] = discover_vendor, + [SCMI_BASE_DISCOVER_SUB_VENDOR] = discover_sub_vendor, + [SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION] = + discover_implementation_version, + [SCMI_BASE_DISCOVER_LIST_PROTOCOLS] = discover_list_protocols, +}; + +static bool message_id_is_supported(unsigned int message_id) +{ + return message_id < ARRAY_SIZE(scmi_base_handler_table) && + scmi_base_handler_table[message_id]; +} + +scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg) +{ + const size_t array_size = ARRAY_SIZE(scmi_base_handler_table); + unsigned int message_id = 0; + + if (msg->message_id >= array_size) { + DMSG("Base handle not found %u", msg->message_id); + return NULL; + } + + message_id = confine_array_index(msg->message_id, array_size); + + return scmi_base_handler_table[message_id]; +} diff --git a/optee/optee_os/core/drivers/scmi-msg/base.h b/optee/optee_os/core/drivers/scmi-msg/base.h new file mode 100644 index 0000000..731443a --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/base.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef SCMI_MSG_BASE_H +#define SCMI_MSG_BASE_H + +#include +#include + +#include "common.h" + +#define SCMI_PROTOCOL_VERSION_BASE 0x20000 + +#define SCMI_DEFAULT_STRING_LENGTH 16 + +enum scmi_base_message_id { + SCMI_BASE_DISCOVER_VENDOR = 0x003, + SCMI_BASE_DISCOVER_SUB_VENDOR = 0x004, + SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION = 0x005, + SCMI_BASE_DISCOVER_LIST_PROTOCOLS = 0x006, + SCMI_BASE_DISCOVER_AGENT = 0x007, + SCMI_BASE_NOTIFY_ERRORS = 0x008, +}; + +/* + * PROTOCOL_ATTRIBUTES + */ + +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS 0 +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS 8 + +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK 0xFF +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK 0xFF00 + +#define SCMI_BASE_PROTOCOL_ATTRIBUTES(NUM_PROTOCOLS, NUM_AGENTS) \ + ((((NUM_PROTOCOLS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS) & \ + SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK) | \ + (((NUM_AGENTS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS) & \ + SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK)) + +/* + * BASE_DISCOVER_VENDOR + */ +struct scmi_base_discover_vendor_p2a { + int32_t status; + char vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; +}; + +/* + * BASE_DISCOVER_SUB_VENDOR + */ +struct scmi_base_discover_sub_vendor_p2a { + int32_t status; + char sub_vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; +}; + +/* + * BASE_DISCOVER_IMPLEMENTATION_VERSION + * No special structure right now, see protocol_version. + */ + +/* + * BASE_DISCOVER_LIST_PROTOCOLS + */ +struct scmi_base_discover_list_protocols_a2p { + uint32_t skip; +}; + +struct scmi_base_discover_list_protocols_p2a { + int32_t status; + uint32_t num_protocols; + uint32_t protocols[]; +}; + +/* + * scmi_msg_get_base_handler - Return a handler for a base message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg); + +#endif /* SCMI_MSG_BASE_H */ diff --git a/optee/optee_os/core/drivers/scmi-msg/clock.c b/optee/optee_os/core/drivers/scmi-msg/clock.c new file mode 100644 index 0000000..dce76fa --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/clock.c @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ +#include +#include +#include +#include +#include +#include + +#include "clock.h" +#include "common.h" + +static bool message_id_is_supported(unsigned int message_id); + +size_t __weak plat_scmi_clock_count(unsigned int channel_id __unused) +{ + return 0; +} + +const char __weak *plat_scmi_clock_get_name(unsigned int channel_id __unused, + unsigned int scmi_id __unused) +{ + return NULL; +} + +int32_t __weak plat_scmi_clock_rates_array(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + size_t start_index __unused, + unsigned long *rates __unused, + size_t *nb_elts __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_clock_rates_by_step(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + unsigned long *steps __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +unsigned long __weak plat_scmi_clock_get_rate(unsigned int channel_id __unused, + unsigned int scmi_id __unused) +{ + return 0; +} + +int32_t __weak plat_scmi_clock_set_rate(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + unsigned long rate __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_clock_get_state(unsigned int channel_id __unused, + unsigned int scmi_id __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_clock_set_state(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + bool enable_not_disable __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_CLOCK, + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + size_t clk_count = plat_scmi_clock_count(msg->channel_id); + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1, clk_count), + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_attributes(struct scmi_msg *msg) +{ + const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in; + struct scmi_clock_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + }; + const char *name = NULL; + unsigned int clock_id = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + clock_id = confine_array_index(in_args->clock_id, + plat_scmi_clock_count(msg->channel_id)); + + name = plat_scmi_clock_get_name(msg->channel_id, clock_id); + if (!name) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + COPY_NAME_IDENTIFIER(return_values.clock_name, name); + + return_values.attributes = plat_scmi_clock_get_state(msg->channel_id, + clock_id); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_rate_get(struct scmi_msg *msg) +{ + const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in; + unsigned long rate = 0; + struct scmi_clock_rate_get_p2a return_values = { }; + unsigned int clock_id = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + clock_id = confine_array_index(in_args->clock_id, + plat_scmi_clock_count(msg->channel_id)); + + rate = plat_scmi_clock_get_rate(msg->channel_id, clock_id); + + reg_pair_from_64(rate, return_values.rate + 1, return_values.rate); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_rate_set(struct scmi_msg *msg) +{ + const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in; + uint64_t rate_64 = 0; + unsigned long rate = 0; + int32_t status = 0; + unsigned int clock_id = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + clock_id = confine_array_index(in_args->clock_id, + plat_scmi_clock_count(msg->channel_id)); + + rate_64 = reg_pair_to_64(in_args->rate[1], in_args->rate[0]); + rate = rate_64; + + status = plat_scmi_clock_set_rate(msg->channel_id, clock_id, rate); + + scmi_status_response(msg, status); +} + +static void scmi_clock_config_set(struct scmi_msg *msg) +{ + const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in; + int32_t status = SCMI_GENERIC_ERROR; + bool enable = false; + unsigned int clock_id = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + clock_id = confine_array_index(in_args->clock_id, + plat_scmi_clock_count(msg->channel_id)); + + enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK; + + status = plat_scmi_clock_set_state(msg->channel_id, clock_id, enable); + + scmi_status_response(msg, status); +} + +#define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \ + SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \ + SCMI_CLOCK_RATE_FORMAT_LIST, \ + (_rem_rates)) +#define SCMI_RATES_BY_STEP \ + SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3, \ + SCMI_CLOCK_RATE_FORMAT_RANGE, \ + 0) + +#define RATE_DESC_SIZE sizeof(struct scmi_clock_rate) + +static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates, + size_t nb_elt) +{ + uint32_t *out = NULL; + size_t n = 0; + + assert(IS_ALIGNED_WITH_TYPE(dest, uint32_t)); + out = (uint32_t *)(uintptr_t)dest; + + for (n = 0; n < nb_elt; n++) { + uint64_t rate = rates[n]; + + reg_pair_from_64(rate, out + 2 * n + 1, out + 2 * n); + } +} + +static void scmi_clock_describe_rates(struct scmi_msg *msg) +{ + const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in; + struct scmi_clock_describe_rates_p2a p2a = { }; + size_t nb_rates = 0; + int32_t status = SCMI_GENERIC_ERROR; + unsigned int clock_id = 0; + unsigned int out_count = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + clock_id = confine_array_index(in_args->clock_id, + plat_scmi_clock_count(msg->channel_id)); + + /* Platform may support array rate description */ + status = plat_scmi_clock_rates_array(msg->channel_id, clock_id, 0, NULL, + &nb_rates); + if (status == SCMI_SUCCESS) { + unsigned int rate_index = in_args->rate_index; + unsigned int remaining = 0; + size_t avail_sz = msg->out_size - sizeof(p2a); + char *out_rates = msg->out + sizeof(p2a); + + if (avail_sz < RATE_DESC_SIZE && nb_rates) { + status = SCMI_PROTOCOL_ERROR; + goto out; + } + + while (avail_sz >= RATE_DESC_SIZE && rate_index < nb_rates) { + unsigned long rate = 0; + size_t cnt = 1; + + status = plat_scmi_clock_rates_array(msg->channel_id, + clock_id, + rate_index, + &rate, &cnt); + if (status) + goto out; + + write_rate_desc_array_in_buffer(out_rates, &rate, cnt); + avail_sz -= RATE_DESC_SIZE; + out_rates += RATE_DESC_SIZE; + rate_index++; + } + + out_count = rate_index - in_args->rate_index; + remaining = nb_rates - in_args->rate_index; + p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(out_count, remaining); + } else if (status == SCMI_NOT_SUPPORTED) { + unsigned long triplet[3] = { 0, 0, 0 }; + + if (msg->out_size < sizeof(p2a) + 3 * RATE_DESC_SIZE) { + status = SCMI_PROTOCOL_ERROR; + goto out; + } + + /* Platform may support min/max/step triplet description */ + status = plat_scmi_clock_rates_by_step(msg->channel_id, + clock_id, triplet); + if (status) + goto out; + + write_rate_desc_array_in_buffer(msg->out + sizeof(p2a), + triplet, 3); + + out_count = 3; + p2a.num_rates_flags = SCMI_RATES_BY_STEP; + } else { + /* Fallthrough generic exit sequence below with error status */ + } + +out: + if (status) { + scmi_status_response(msg, status); + } else { + p2a.status = SCMI_SUCCESS; + memcpy(msg->out, &p2a, sizeof(p2a)); + msg->out_size_out = sizeof(p2a) + out_count * RATE_DESC_SIZE; + } +} + +static const scmi_msg_handler_t scmi_clock_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes, + [SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates, + [SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set, + [SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get, + [SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set, +}; + +static bool message_id_is_supported(unsigned int message_id) +{ + return message_id < ARRAY_SIZE(scmi_clock_handler_table) && + scmi_clock_handler_table[message_id]; +} + +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg) +{ + const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table); + unsigned int message_id = 0; + + if (msg->message_id >= array_size) { + DMSG("Clock handle not found %u", msg->message_id); + return NULL; + } + + message_id = confine_array_index(msg->message_id, array_size); + + return scmi_clock_handler_table[message_id]; +} diff --git a/optee/optee_os/core/drivers/scmi-msg/clock.h b/optee/optee_os/core/drivers/scmi-msg/clock.h new file mode 100644 index 0000000..a20678c --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/clock.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef SCMI_MSG_CLOCK_H +#define SCMI_MSG_CLOCK_H + +#include +#include + +#include "common.h" + +#define SCMI_PROTOCOL_VERSION_CLOCK 0x20000 + +/* + * Identifiers of the SCMI Clock Management Protocol commands + */ +enum scmi_clock_command_id { + SCMI_CLOCK_ATTRIBUTES = 0x003, + SCMI_CLOCK_DESCRIBE_RATES = 0x004, + SCMI_CLOCK_RATE_SET = 0x005, + SCMI_CLOCK_RATE_GET = 0x006, + SCMI_CLOCK_CONFIG_SET = 0x007, +}; + +/* Protocol attributes */ +#define SCMI_CLOCK_CLOCK_COUNT_MASK GENMASK_32(15, 0) +#define SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK GENMASK_32(23, 16) + +#define SCMI_CLOCK_PROTOCOL_ATTRIBUTES(_max_pending, _clk_count) \ + ((((_max_pending) << 16) & SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK) | \ + (((_clk_count) & SCMI_CLOCK_CLOCK_COUNT_MASK))) + +struct scmi_clock_attributes_a2p { + uint32_t clock_id; +}; + +#define SCMI_CLOCK_NAME_LENGTH_MAX 16 + +struct scmi_clock_attributes_p2a { + int32_t status; + uint32_t attributes; + char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX]; +}; + +/* + * Clock Rate Get + */ + +struct scmi_clock_rate_get_a2p { + uint32_t clock_id; +}; + +struct scmi_clock_rate_get_p2a { + int32_t status; + uint32_t rate[2]; +}; + +/* + * Clock Rate Set + */ + +/* If set, set the new clock rate asynchronously */ +#define SCMI_CLOCK_RATE_SET_ASYNC_POS 0 +/* If set, do not send a delayed asynchronous response */ +#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS 1 +/* Round up, if set, otherwise round down */ +#define SCMI_CLOCK_RATE_SET_ROUND_UP_POS 2 +/* If set, the platform chooses the appropriate rounding mode */ +#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS 3 + +#define SCMI_CLOCK_RATE_SET_ASYNC_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ASYNC_POS) +#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_MASK \ + BIT(SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS) +#define SCMI_CLOCK_RATE_SET_ROUND_UP_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ROUND_UP_POS) +#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS) + +struct scmi_clock_rate_set_a2p { + uint32_t flags; + uint32_t clock_id; + uint32_t rate[2]; +}; + +struct scmi_clock_rate_set_p2a { + int32_t status; +}; + +/* + * Clock Config Set + */ + +#define SCMI_CLOCK_CONFIG_SET_ENABLE_POS 0 + +#define SCMI_CLOCK_CONFIG_SET_ENABLE_MASK \ + BIT(SCMI_CLOCK_CONFIG_SET_ENABLE_POS) + +struct scmi_clock_config_set_a2p { + uint32_t clock_id; + uint32_t attributes; +}; + +struct scmi_clock_config_set_p2a { + int32_t status; +}; + +/* + * Clock Describe Rates + */ + +#define SCMI_CLOCK_RATE_FORMAT_RANGE 1 +#define SCMI_CLOCK_RATE_FORMAT_LIST 0 + +#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK GENMASK_32(31, 16) +#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS 16 + +#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK BIT(12) +#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS 12 + +#define SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK GENMASK_32(11, 0) + +#define SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(_count, _fmt, _rem_rates) \ + ( \ + ((_count) & SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK) | \ + (((_rem_rates) << SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS) & \ + SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK) | \ + (((_fmt) << SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS) & \ + SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK) \ + ) + +struct scmi_clock_rate { + uint32_t low; + uint32_t high; +}; + +struct scmi_clock_describe_rates_a2p { + uint32_t clock_id; + uint32_t rate_index; +}; + +struct scmi_clock_describe_rates_p2a { + int32_t status; + uint32_t num_rates_flags; + struct scmi_clock_rate rates[]; +}; + +#ifdef CFG_SCMI_MSG_CLOCK +/* + * scmi_msg_get_clock_handler - Return a handler for a clock message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg); +#else +static inline +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} +#endif +#endif /* SCMI_MSG_CLOCK_H */ diff --git a/optee/optee_os/core/drivers/scmi-msg/common.h b/optee/optee_os/core/drivers/scmi-msg/common.h new file mode 100644 index 0000000..e251e3b --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/common.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ +#ifndef SCMI_MSG_COMMON_H +#define SCMI_MSG_COMMON_H + +#include +#include +#include +#include +#include + +#define SCMI_VERSION 0x30000 +#define SCMI_IMPL_VERSION 0 + +/* + * Secure copy of input payload: we expect small messages, at most the legacy + * SMT messages that are 128 bytes (Linux kernel) including SMT header. + */ +#define SCMI_SEC_PAYLOAD_SIZE 92 + +/* + * Copy name identifier in target buffer following the SCMI specification + * that state name identifier shall be a null terminated string. + */ +#define COPY_NAME_IDENTIFIER(_dst_array, _name) \ + do { \ + assert(strlen(_name) < sizeof(_dst_array)); \ + strncpy((_dst_array), (_name), sizeof(_dst_array)); \ + } while (0) + +/* Common command identifiers shared by all procotols */ +enum scmi_common_message_id { + SCMI_PROTOCOL_VERSION = 0x000, + SCMI_PROTOCOL_ATTRIBUTES = 0x001, + SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x002 +}; + +/* Common platform-to-agent (p2a) PROTOCOL_VERSION structure */ +struct scmi_protocol_version_p2a { + int32_t status; + uint32_t version; +}; + +/* Generic platform-to-agent (p2a) PROTOCOL_ATTRIBUTES structure */ +struct scmi_protocol_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* Generic agent-to-platform (a2p) PROTOCOL_MESSAGE_ATTRIBUTES structure */ +struct scmi_protocol_message_attributes_a2p { + uint32_t message_id; +}; + +/* Generic platform-to-agent (p2a) PROTOCOL_MESSAGE_ATTRIBUTES structure */ +struct scmi_protocol_message_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* + * struct scmi_msg - SCMI message context + * + * @channel_id: SCMI channel ID, safely set from secure world + * @protocol_id: SCMI protocol ID for the related message, set by caller agent + * @message_id: SCMI message ID for the related message, set by caller agent + * @in: Address of the incoming message payload copied in secure memory + * @in_size: Byte length of the incoming message payload, set by caller agent + * @out: Address of of the output message payload message in non-secure memory + * @out_size: Byte length of the provisionned output buffer + * @out_size_out: Byte length of the output message payload + */ +struct scmi_msg { + unsigned int channel_id; + unsigned int protocol_id; + unsigned int message_id; + char *in; + size_t in_size; + char *out; + size_t out_size; + size_t out_size_out; +}; + +/* + * Type scmi_msg_handler_t is used by procotol drivers to safely find + * the handler function for the incoming message ID. + */ +typedef void (*scmi_msg_handler_t)(struct scmi_msg *msg); + +/* + * Process Read, process and write response for input SCMI message + * + * @msg: SCMI message context + */ +void scmi_process_message(struct scmi_msg *msg); + +/* + * Write SCMI response payload to output message shared memory + * + * @msg: SCMI message context + * @payload: Output message payload + * @size: Byte size of output message payload + */ +void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size); + +/* + * Write status only SCMI response payload to output message shared memory + * + * @msg: SCMI message context + * @status: SCMI status value returned to caller + */ +void scmi_status_response(struct scmi_msg *msg, int32_t status); + +/* + * Claim access to channel + * @channel: SCMI channel reference + * Return true upon success or false if the channel is already busy + */ +bool scmi_msg_claim_channel(struct scmi_msg_channel *channel); + +/* + * Release access channel + * @channel: SCMI channel reference + */ +void scmi_msg_release_channel(struct scmi_msg_channel *channel); + +/* + * Entry for processing a channel using SMT shared memory protocol + * @channel_id: SCMI channel identifier provided by client + * @payload_buf: Secure buffer where to copy input message + */ +void scmi_entry_smt(unsigned int channel_id, uint32_t *payload_buf); + +/* + * Entry for processing a channel using SMT shared memory protocol + * + * @channel_id: SCMI channel identifier provided by client + * @in_buf: Shared buffer storing input SCMI message + * @in_size: Byte size of @in_buf, including MSG header and message payload + * @out_buf: Shared buffer storing input SCMI message + * @out_size: [in] @out_buf max byte size + * [out] @out_buf output byte size (MSG header and message payload) + * @sec_buf: Secure buffer where to copy input message + */ +TEE_Result scmi_entry_msg(unsigned int channel_id, void *in_buf, size_t in_size, + void *out_buf, size_t *out_size, uint32_t *sec_buf); +#endif /* SCMI_MSG_COMMON_H */ diff --git a/optee/optee_os/core/drivers/scmi-msg/entry.c b/optee/optee_os/core/drivers/scmi-msg/entry.c new file mode 100644 index 0000000..0fd0968 --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/entry.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2022, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "base.h" +#include "clock.h" +#include "common.h" +#include "reset_domain.h" +#include "voltage_domain.h" + +/* Provision input message payload buffers for each supported entry channel */ +#define SCMI_PAYLOAD_U32_MAX (SCMI_SEC_PAYLOAD_SIZE / sizeof(uint32_t)) + +static uint32_t threaded_payload[CFG_NUM_THREADS][SCMI_PAYLOAD_U32_MAX] +__maybe_unused; + +static uint32_t interrupt_payload[CFG_TEE_CORE_NB_CORE][SCMI_PAYLOAD_U32_MAX] +__maybe_unused; + +static uint32_t fastcall_payload[CFG_TEE_CORE_NB_CORE][SCMI_PAYLOAD_U32_MAX] +__maybe_unused; + +/* SMP protection on channel->busy field */ +static unsigned int smt_channels_lock; + +/* If channel is not busy, set busy and return true, otherwise return false */ +bool scmi_msg_claim_channel(struct scmi_msg_channel *channel) +{ + uint32_t exceptions = cpu_spin_lock_xsave(&smt_channels_lock); + bool channel_is_busy = channel->busy; + + if (!channel_is_busy) + channel->busy = true; + + cpu_spin_unlock_xrestore(&smt_channels_lock, exceptions); + + return !channel_is_busy; +} + +void scmi_msg_release_channel(struct scmi_msg_channel *channel) +{ + channel->busy = false; +} + +void scmi_status_response(struct scmi_msg *msg, int32_t status) +{ + assert(msg->out && msg->out_size >= sizeof(int32_t)); + + memcpy(msg->out, &status, sizeof(int32_t)); + msg->out_size_out = sizeof(int32_t); +} + +void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size) +{ + if (msg->out_size < size) { + DMSG("SCMI resp. payload %zu > %zu bytes", size, msg->out_size); + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + } else { + memcpy(msg->out, payload, size); + msg->out_size_out = size; + } +} + +void scmi_process_message(struct scmi_msg *msg) +{ + scmi_msg_handler_t handler = NULL; + + switch (msg->protocol_id) { + case SCMI_PROTOCOL_ID_BASE: + handler = scmi_msg_get_base_handler(msg); + break; + case SCMI_PROTOCOL_ID_CLOCK: + handler = scmi_msg_get_clock_handler(msg); + break; + case SCMI_PROTOCOL_ID_RESET_DOMAIN: + handler = scmi_msg_get_rd_handler(msg); + break; + case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: + handler = scmi_msg_get_voltd_handler(msg); + break; + default: + break; + } + + if (handler) { + handler(msg); + return; + } + + DMSG("Channel %u Protocol %#x Message %#x: not supported", + msg->channel_id, msg->protocol_id, msg->message_id); + + scmi_status_response(msg, SCMI_NOT_SUPPORTED); +} + +#ifdef CFG_SCMI_MSG_SMT_FASTCALL_ENTRY +void scmi_smt_fastcall_smc_entry(unsigned int channel_id) +{ + assert(!plat_scmi_get_channel(channel_id)->threaded); + + scmi_entry_smt(channel_id, fastcall_payload[get_core_pos()]); +} +#endif + +#ifdef CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY +void scmi_smt_interrupt_entry(unsigned int channel_id) +{ + assert(!plat_scmi_get_channel(channel_id)->threaded); + + scmi_entry_smt(channel_id, interrupt_payload[get_core_pos()]); +} +#endif + +#ifdef CFG_SCMI_MSG_SMT_THREAD_ENTRY +void scmi_smt_threaded_entry(unsigned int channel_id) +{ + assert(plat_scmi_get_channel(channel_id)->threaded); + + scmi_entry_smt(channel_id, threaded_payload[thread_get_id()]); +} +#endif + +#ifdef CFG_SCMI_MSG_SHM_MSG +TEE_Result scmi_msg_threaded_entry(unsigned int channel_id, + void *in_buf, size_t in_size, + void *out_buf, size_t *out_size) +{ + assert(plat_scmi_get_channel(channel_id)->threaded); + + return scmi_entry_msg(channel_id, in_buf, in_size, out_buf, out_size, + threaded_payload[thread_get_id()]); +} +#endif diff --git a/optee/optee_os/core/drivers/scmi-msg/reset_domain.c b/optee/optee_os/core/drivers/scmi-msg/reset_domain.c new file mode 100644 index 0000000..e3999ec --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/reset_domain.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "reset_domain.h" + +static bool message_id_is_supported(unsigned int message_id); + +size_t __weak plat_scmi_rd_count(unsigned int channel_id __unused) +{ + return 0; +} + +const char __weak *plat_scmi_rd_get_name(unsigned int channel_id __unused, + unsigned int scmi_id __unused) +{ + return NULL; +} + +int32_t __weak plat_scmi_rd_autonomous(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + unsigned int state __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_rd_set_state(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + bool assert_not_deassert __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN, + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = plat_scmi_rd_count(msg->channel_id), + }; + + if (msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void reset_domain_attributes(struct scmi_msg *msg) +{ + struct scmi_reset_domain_attributes_a2p *in_args = (void *)msg->in; + struct scmi_reset_domain_attributes_p2a return_values = { }; + const char *name = NULL; + unsigned int domain_id = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->domain_id >= plat_scmi_rd_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + domain_id = confine_array_index(in_args->domain_id, + plat_scmi_rd_count(msg->channel_id)); + + name = plat_scmi_rd_get_name(msg->channel_id, domain_id); + if (!name) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + COPY_NAME_IDENTIFIER(return_values.name, name); + return_values.status = SCMI_SUCCESS; + return_values.flags = 0; /* Async and Notif are not supported */ + return_values.latency = SCMI_RESET_DOMAIN_ATTR_UNK_LAT; + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void reset_request(struct scmi_msg *msg) +{ + struct scmi_reset_domain_request_a2p *in_args = (void *)msg->in; + struct scmi_reset_domain_request_p2a out_args = { + .status = SCMI_SUCCESS, + }; + unsigned int domain_id = 0; + + domain_id = confine_array_index(in_args->domain_id, + plat_scmi_rd_count(msg->channel_id)); + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->domain_id >= plat_scmi_rd_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + if (in_args->flags & SCMI_RESET_DOMAIN_AUTO) + out_args.status = plat_scmi_rd_autonomous(msg->channel_id, + domain_id, + in_args->reset_state); + else if (in_args->flags & SCMI_RESET_DOMAIN_EXPLICIT) + out_args.status = plat_scmi_rd_set_state(msg->channel_id, + domain_id, true); + else + out_args.status = plat_scmi_rd_set_state(msg->channel_id, + domain_id, false); + + if (out_args.status) + scmi_status_response(msg, out_args.status); + else + scmi_write_response(msg, &out_args, sizeof(out_args)); +} + +static const scmi_msg_handler_t scmi_rd_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_RESET_DOMAIN_ATTRIBUTES] = reset_domain_attributes, + [SCMI_RESET_DOMAIN_REQUEST] = reset_request, +}; + +static bool message_id_is_supported(unsigned int message_id) +{ + return message_id < ARRAY_SIZE(scmi_rd_handler_table) && + scmi_rd_handler_table[message_id]; +} + +scmi_msg_handler_t scmi_msg_get_rd_handler(struct scmi_msg *msg) +{ + const size_t array_size = ARRAY_SIZE(scmi_rd_handler_table); + unsigned int message_id = 0; + + if (msg->message_id >= array_size) { + DMSG("Reset domain handle not found %u", msg->message_id); + return NULL; + } + + message_id = confine_array_index(msg->message_id, array_size); + + return scmi_rd_handler_table[message_id]; +} diff --git a/optee/optee_os/core/drivers/scmi-msg/reset_domain.h b/optee/optee_os/core/drivers/scmi-msg/reset_domain.h new file mode 100644 index 0000000..e86b9e3 --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/reset_domain.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ +#ifndef SCMI_MSG_RESET_DOMAIN_H +#define SCMI_MSG_RESET_DOMAIN_H + +#include +#include +#include +#include +#include + +#include "common.h" + +#define SCMI_PROTOCOL_VERSION_RESET_DOMAIN 0x10000 + +#define SCMI_RESET_STATE_ARCH BIT(31) +#define SCMI_RESET_STATE_IMPL 0 + +/* + * Identifiers of the SCMI Reset Domain Management Protocol commands + */ +enum scmi_reset_domain_command_id { + SCMI_RESET_DOMAIN_ATTRIBUTES = 0x03, + SCMI_RESET_DOMAIN_REQUEST = 0x04, + SCMI_RESET_DOMAIN_NOTIFY = 0x05, +}; + +/* + * Identifiers of the SCMI Reset Domain Management Protocol responses + */ +enum scmi_reset_domain_response_id { + SCMI_RESET_ISSUED = 0x00, + SCMI_RESET_COMPLETE = 0x04, +}; + +/* + * PROTOCOL_ATTRIBUTES + */ + +#define SCMI_RESET_DOMAIN_COUNT_MASK GENMASK_32(15, 0) + +struct scmi_reset_domain_protocol_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* Value for scmi_reset_domain_attributes_p2a:flags */ +#define SCMI_RESET_DOMAIN_ATTR_ASYNC BIT(31) +#define SCMI_RESET_DOMAIN_ATTR_NOTIF BIT(30) + +/* Value for scmi_reset_domain_attributes_p2a:latency */ +#define SCMI_RESET_DOMAIN_ATTR_UNK_LAT 0x7fffffff +#define SCMI_RESET_DOMAIN_ATTR_MAX_LAT 0x7ffffffe + +/* Macro for scmi_reset_domain_attributes_p2a:name */ +#define SCMI_RESET_DOMAIN_ATTR_NAME_SZ 16 + +struct scmi_reset_domain_attributes_a2p { + uint32_t domain_id; +}; + +struct scmi_reset_domain_attributes_p2a { + int32_t status; + uint32_t flags; + uint32_t latency; + char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ]; +}; + +/* + * RESET + */ + +/* Values for scmi_reset_domain_request_a2p:flags */ +#define SCMI_RESET_DOMAIN_ASYNC BIT(2) +#define SCMI_RESET_DOMAIN_EXPLICIT BIT(1) +#define SCMI_RESET_DOMAIN_AUTO BIT(0) + +struct scmi_reset_domain_request_a2p { + uint32_t domain_id; + uint32_t flags; + uint32_t reset_state; +}; + +struct scmi_reset_domain_request_p2a { + int32_t status; +}; + +/* + * RESET_NOTIFY + */ + +/* Values for scmi_reset_notify_p2a:flags */ +#define SCMI_RESET_DOMAIN_DO_NOTIFY BIT(0) + +struct scmi_reset_domain_notify_a2p { + uint32_t domain_id; + uint32_t notify_enable; +}; + +struct scmi_reset_domain_notify_p2a { + int32_t status; +}; + +/* + * RESET_COMPLETE + */ + +struct scmi_reset_domain_complete_p2a { + int32_t status; + uint32_t domain_id; +}; + +/* + * RESET_ISSUED + */ + +struct scmi_reset_domain_issued_p2a { + uint32_t domain_id; + uint32_t reset_state; +}; + +#ifdef CFG_SCMI_MSG_RESET_DOMAIN +/* + * scmi_msg_get_rd_handler - Return a handler for a reset domain message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_rd_handler(struct scmi_msg *msg); +#else +static inline +scmi_msg_handler_t scmi_msg_get_rd_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} +#endif +#endif /* SCMI_MSG_RESET_DOMAIN_H */ diff --git a/optee/optee_os/core/drivers/scmi-msg/shm_msg.c b/optee/optee_os/core/drivers/scmi-msg/shm_msg.c new file mode 100644 index 0000000..3fe8363 --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/shm_msg.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2022, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/** + * struct msg_header - MSG formatted header for MSG base shared memory transfer + * + * @message_header: 32bit header used in MSG shared memory protocol + * @payload: SCMI message payload data + */ +struct msg_header { + uint32_t message_header; + uint32_t payload[]; +}; + +/* Bit fields packed in msg_header::message_header */ +#define MSG_ID_MASK GENMASK_32(7, 0) +#define MSG_ID(_hdr) ((_hdr) & MSG_ID_MASK) + +#define MSG_TYPE_MASK GENMASK_32(9, 8) +#define MSG_TYPE(_hdr) (((_hdr) & MSG_TYPE_MASK) >> 8) + +#define MSG_PROT_ID_MASK GENMASK_32(17, 10) +#define MSG_PROT_ID(_hdr) (((_hdr) & MSG_PROT_ID_MASK) >> 10) + +/* + * Creates a SCMI message instance in secure memory and push it in the SCMI + * message drivers. Message structure contains SCMI protocol meta-data and + * references to input payload in secure memory and output message buffer + * in shared memory. + */ +TEE_Result scmi_entry_msg(unsigned int channel_id, void *in_buf, size_t in_size, + void *out_buf, size_t *out_size, uint32_t *sec_buf) +{ + struct scmi_msg_channel *channel = plat_scmi_get_channel(channel_id); + struct msg_header *hdr = NULL; + struct scmi_msg msg = { }; + uint32_t msg_header = 0; + + if (!channel) { + DMSG("Invalid channel ID %u", channel_id); + return TEE_ERROR_BAD_PARAMETERS; + } + + assert(in_buf && out_buf && out_size && sec_buf); + + if (in_size < sizeof(struct msg_header) || + in_size - sizeof(struct msg_header) > SCMI_SEC_PAYLOAD_SIZE || + !IS_ALIGNED_WITH_TYPE(in_buf, uint32_t) || + *out_size < sizeof(struct msg_header) || + !IS_ALIGNED_WITH_TYPE(out_buf, uint32_t)) { + DMSG("Invalid SCMI buffer references %zu@%p / %zu@%p", + in_size, in_buf, *out_size, out_buf); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!scmi_msg_claim_channel(channel)) { + DMSG("SCMI channel %u busy", channel_id); + return TEE_ERROR_BUSY; + } + + /* Copy SCMI protocol data and message payload in secure memory */ + hdr = (struct msg_header *)in_buf; + msg_header = READ_ONCE(hdr->message_header); + + msg.protocol_id = MSG_PROT_ID(msg_header); + msg.message_id = MSG_ID(msg_header); + msg.channel_id = channel_id; + + msg.in = (char *)sec_buf; + msg.in_size = in_size - sizeof(struct msg_header); + memcpy(msg.in, hdr->payload, msg.in_size); + + /* Prepare output message buffer references */ + hdr = (struct msg_header *)out_buf; + + msg.out = (char *)hdr->payload; + msg.out_size = *out_size - sizeof(struct msg_header); + + scmi_process_message(&msg); + + /* Update SCMI protocol data and output shared buffer size */ + hdr->message_header = msg_header; + *out_size = msg.out_size_out + sizeof(struct msg_header); + + scmi_msg_release_channel(channel); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/scmi-msg/smt.c b/optee/optee_os/core/drivers/scmi-msg/smt.c new file mode 100644 index 0000000..880212b --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/smt.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2022, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/** + * struct smt_header - SMT formatted header for SMT base shared memory transfer + * + * @status: Bit flags, see SMT_STATUS_* + * @flags: Bit flags, see SMT_FLAG_* + * @length: Byte size of message payload (variable) + ::message_header (32bit) + * payload: SCMI message payload data + */ +struct smt_header { + uint32_t reserved0; + uint32_t status; + uint64_t reserved1; + uint32_t flags; + uint32_t length; /* message_header + payload */ + uint32_t message_header; + uint32_t payload[]; +}; + +/* Flag set in smt_header::status when SMT does not contain pending message */ +#define SMT_STATUS_FREE BIT(0) +/* Flag set in smt_header::status when SMT reports an error */ +#define SMT_STATUS_ERROR BIT(1) + +/* Flag set in smt_header::flags when SMT uses interrupts */ +#define SMT_FLAG_INTR_ENABLED BIT(1) + +/* Bit fields packed in smt_header::message_header */ +#define SMT_MSG_ID_MASK GENMASK_32(7, 0) +#define SMT_HDR_MSG_ID(_hdr) ((_hdr) & SMT_MSG_ID_MASK) + +#define SMT_MSG_TYPE_MASK GENMASK_32(9, 8) +#define SMT_HDR_TYPE_ID(_hdr) (((_hdr) & SMT_MSG_TYPE_MASK) >> 8) + +#define SMT_MSG_PROT_ID_MASK GENMASK_32(17, 10) +#define SMT_HDR_PROT_ID(_hdr) (((_hdr) & SMT_MSG_PROT_ID_MASK) >> 10) + +static struct smt_header *channel_to_smt_hdr(struct scmi_msg_channel *channel) +{ + if (!channel) + return NULL; + + return (struct smt_header *)io_pa_or_va(&channel->shm_addr, + sizeof(struct smt_header)); +} + +/* + * Creates a SCMI message instance in secure memory and push it in the SCMI + * message drivers. Message structure contains SCMI protocol meta-data and + * references to input payload in secure memory and output message buffer + * in shared memory. + */ +void scmi_entry_smt(unsigned int channel_id, uint32_t *payload_buf) +{ + struct scmi_msg_channel *channel = NULL; + struct smt_header *smt_hdr = NULL; + size_t in_payload_size = 0; + uint32_t smt_status = 0; + struct scmi_msg msg = { }; + bool error = true; + + channel = plat_scmi_get_channel(channel_id); + if (!channel) { + DMSG("Invalid channel ID %u", channel_id); + return; + } + + smt_hdr = channel_to_smt_hdr(channel); + if (!smt_hdr) { + DMSG("No shared buffer for channel ID %u", channel_id); + return; + } + + if (!scmi_msg_claim_channel(channel)) { + DMSG("SCMI channel %u busy", channel_id); + goto out; + } + + smt_status = READ_ONCE(smt_hdr->status); + + in_payload_size = READ_ONCE(smt_hdr->length) - + sizeof(smt_hdr->message_header); + + if (in_payload_size > SCMI_SEC_PAYLOAD_SIZE) { + DMSG("SCMI payload too big %u", in_payload_size); + goto out; + } + + if (smt_status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)) { + DMSG("SCMI channel bad status 0x%x", + smt_hdr->status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)); + goto out; + } + + /* Fill message */ + msg.in = (char *)payload_buf; + msg.in_size = in_payload_size; + msg.out = (char *)smt_hdr->payload; + msg.out_size = channel->shm_size - sizeof(*smt_hdr); + + assert(msg.out && msg.out_size >= sizeof(int32_t)); + + /* Here the payload is copied in secure memory */ + memcpy(msg.in, smt_hdr->payload, in_payload_size); + + msg.protocol_id = SMT_HDR_PROT_ID(smt_hdr->message_header); + msg.message_id = SMT_HDR_MSG_ID(smt_hdr->message_header); + msg.channel_id = channel_id; + + scmi_process_message(&msg); + + /* Update message length with the length of the response message */ + smt_hdr->length = msg.out_size_out + sizeof(smt_hdr->message_header); + + scmi_msg_release_channel(channel); + error = false; + +out: + if (error) { + DMSG("SCMI error"); + smt_hdr->status |= SMT_STATUS_ERROR | SMT_STATUS_FREE; + } else { + smt_hdr->status |= SMT_STATUS_FREE; + } +} + +/* Init a SMT header for a shared memory buffer: state it a free/no-error */ +void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel) +{ + struct smt_header *smt_header = channel_to_smt_hdr(channel); + + static_assert(SCMI_SEC_PAYLOAD_SIZE + sizeof(struct smt_header) <= + SMT_BUF_SLOT_SIZE && + IS_ALIGNED(SCMI_SEC_PAYLOAD_SIZE, sizeof(uint32_t))); + assert(smt_header); + + memset(smt_header, 0, sizeof(*smt_header)); + smt_header->status = SMT_STATUS_FREE; +} + +void scmi_smt_set_shared_buffer(struct scmi_msg_channel *channel, void *base) +{ + paddr_t p_base = 0; + + if (base) { + assert(!channel->shm_addr.va && !channel->shm_addr.pa); + p_base = virt_to_phys(base); + assert(p_base); + } + + channel->shm_addr.va = (vaddr_t)base; + channel->shm_addr.pa = p_base; +} diff --git a/optee/optee_os/core/drivers/scmi-msg/sub.mk b/optee/optee_os/core/drivers/scmi-msg/sub.mk new file mode 100644 index 0000000..63c8bc5 --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/sub.mk @@ -0,0 +1,7 @@ +srcs-y += base.c +srcs-$(CFG_SCMI_MSG_CLOCK) += clock.c +srcs-y += entry.c +srcs-$(CFG_SCMI_MSG_RESET_DOMAIN) += reset_domain.c +srcs-$(CFG_SCMI_MSG_SHM_MSG) += shm_msg.c +srcs-$(CFG_SCMI_MSG_SMT) += smt.c +srcs-$(CFG_SCMI_MSG_VOLTAGE_DOMAIN) += voltage_domain.c diff --git a/optee/optee_os/core/drivers/scmi-msg/voltage_domain.c b/optee/optee_os/core/drivers/scmi-msg/voltage_domain.c new file mode 100644 index 0000000..a4a211e --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/voltage_domain.c @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2020, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "voltage_domain.h" + +static bool message_id_is_supported(unsigned int message_id); + +size_t __weak plat_scmi_voltd_count(unsigned int channel_id __unused) +{ + return 0; +} + +const char __weak *plat_scmi_voltd_get_name(unsigned int channel_id __unused, + unsigned int scmi_id __unused) +{ + return NULL; +} + +int32_t __weak plat_scmi_voltd_levels_array(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + size_t start_index __unused, + long *levels __unused, + size_t *nb_elts __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_voltd_levels_by_step(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + long *steps __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_voltd_get_level(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + long *level __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_voltd_set_level(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + long microvolt __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_voltd_get_config(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + uint32_t *config __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t __weak plat_scmi_voltd_set_config(unsigned int channel_id __unused, + unsigned int scmi_id __unused, + uint32_t config __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a out_args = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_VOLTAGE_DOMAIN, + }; + + if (IS_ENABLED(CFG_SCMI_MSG_STRICT_ABI) && msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &out_args, sizeof(out_args)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + size_t domain_count = plat_scmi_voltd_count(msg->channel_id); + struct scmi_protocol_attributes_p2a out_args = { + .status = SCMI_SUCCESS, + .attributes = domain_count, + }; + + assert(!(domain_count & ~SCMI_VOLTAGE_DOMAIN_COUNT_MASK)); + + if (IS_ENABLED(CFG_SCMI_MSG_STRICT_ABI) && msg->in_size) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &out_args, sizeof(out_args)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a out_args = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &out_args, sizeof(out_args)); +} + +static void scmi_voltd_domain_attributes(struct scmi_msg *msg) +{ + const struct scmi_voltd_attributes_a2p *in_args = (void *)msg->in; + struct scmi_voltd_attributes_p2a out_args = { + .status = SCMI_SUCCESS, + }; + const char *name = NULL; + unsigned int domain_id = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + domain_id = confine_array_index(in_args->domain_id, + plat_scmi_voltd_count(msg->channel_id)); + + name = plat_scmi_voltd_get_name(msg->channel_id, domain_id); + if (!name) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + COPY_NAME_IDENTIFIER(out_args.name, name); + + scmi_write_response(msg, &out_args, sizeof(out_args)); +} + +#define LEVELS_BY_ARRAY(_nb_rates, _rem_rates) \ + SCMI_VOLTAGE_DOMAIN_LEVELS_FLAGS((_nb_rates), \ + SCMI_VOLTD_LEVELS_FORMAT_LIST, \ + (_rem_rates)) + +#define LEVELS_BY_STEP \ + SCMI_VOLTAGE_DOMAIN_LEVELS_FLAGS(3, SCMI_VOLTD_LEVELS_FORMAT_RANGE, 0) + +#define LEVEL_DESC_SIZE sizeof(int32_t) + +static void scmi_voltd_describe_levels(struct scmi_msg *msg) +{ + const struct scmi_voltd_describe_levels_a2p *in_args = (void *)msg->in; + struct scmi_voltd_describe_levels_p2a out_args = { }; + int32_t status = SCMI_GENERIC_ERROR; + unsigned int out_count = 0; + unsigned int domain_id = 0; + int32_t *out_levels = NULL; + size_t nb_levels = 0; + + if (msg->in_size != sizeof(*in_args)) { + status = SCMI_PROTOCOL_ERROR; + goto out; + } + + if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { + status = SCMI_INVALID_PARAMETERS; + goto out; + } + + if (msg->out_size < sizeof(out_args)) { + status = SCMI_INVALID_PARAMETERS; + goto out; + } + assert(IS_ALIGNED_WITH_TYPE(msg->out + sizeof(out_args), int32_t)); + out_levels = (int32_t *)(uintptr_t)(msg->out + sizeof(out_args)); + + domain_id = confine_array_index(in_args->domain_id, + plat_scmi_voltd_count(msg->channel_id)); + + /* Platform may support array rate description */ + status = plat_scmi_voltd_levels_array(msg->channel_id, domain_id, 0, + NULL, &nb_levels); + if (status == SCMI_SUCCESS) { + size_t avail_sz = msg->out_size - sizeof(out_args); + unsigned int level_index = in_args->level_index; + unsigned int remaining = 0; + + if (avail_sz < LEVEL_DESC_SIZE && nb_levels) { + status = SCMI_PROTOCOL_ERROR; + goto out; + } + + while (avail_sz >= LEVEL_DESC_SIZE && level_index < nb_levels) { + long plat_level = 0; + size_t cnt = 1; + + status = plat_scmi_voltd_levels_array(msg->channel_id, + domain_id, + level_index, + &plat_level, + &cnt); + if (status) + goto out; + + *out_levels = plat_level; + + avail_sz -= LEVEL_DESC_SIZE; + out_levels++; + level_index++; + } + + remaining = nb_levels - in_args->level_index; + out_count = level_index - in_args->level_index; + out_args.flags = LEVELS_BY_ARRAY(out_count, remaining); + } else if (status == SCMI_NOT_SUPPORTED) { + long triplet[3] = { 0, 0, 0 }; + + if (msg->out_size < sizeof(out_args) + 3 * LEVEL_DESC_SIZE) { + status = SCMI_PROTOCOL_ERROR; + goto out; + } + + /* Platform may support min/max/step triplet description */ + status = plat_scmi_voltd_levels_by_step(msg->channel_id, + domain_id, triplet); + if (status) + goto out; + + out_levels[0] = triplet[0]; + out_levels[1] = triplet[1]; + out_levels[2] = triplet[2]; + + out_count = 3; + out_args.flags = LEVELS_BY_STEP; + } + +out: + if (status) { + scmi_status_response(msg, status); + } else { + out_args.status = SCMI_SUCCESS; + memcpy(msg->out, &out_args, sizeof(out_args)); + msg->out_size_out = sizeof(out_args) + + out_count * LEVEL_DESC_SIZE; + } +} + +static void scmi_voltd_config_set(struct scmi_msg *msg) +{ + const struct scmi_voltd_config_set_a2p *in_args = (void *)msg->in; + unsigned int domain_id = 0; + unsigned long config = 0; + int32_t status = SCMI_GENERIC_ERROR; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + domain_id = confine_array_index(in_args->domain_id, + plat_scmi_voltd_count(msg->channel_id)); + + config = in_args->config & SCMI_VOLTAGE_DOMAIN_CONFIG_MASK; + + status = plat_scmi_voltd_set_config(msg->channel_id, domain_id, config); + + scmi_status_response(msg, status); +} + +static void scmi_voltd_config_get(struct scmi_msg *msg) +{ + const struct scmi_voltd_config_get_a2p *in_args = (void *)msg->in; + struct scmi_voltd_config_get_p2a out_args = { }; + unsigned int domain_id = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + domain_id = confine_array_index(in_args->domain_id, + plat_scmi_voltd_count(msg->channel_id)); + + if (plat_scmi_voltd_get_config(msg->channel_id, domain_id, + &out_args.config)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + scmi_write_response(msg, &out_args, sizeof(out_args)); +} + +static void scmi_voltd_level_set(struct scmi_msg *msg) +{ + const struct scmi_voltd_level_set_a2p *in_args = (void *)msg->in; + int32_t status = SCMI_GENERIC_ERROR; + unsigned int domain_id = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + domain_id = confine_array_index(in_args->domain_id, + plat_scmi_voltd_count(msg->channel_id)); + + status = plat_scmi_voltd_set_level(msg->channel_id, domain_id, + in_args->voltage_level); + + scmi_status_response(msg, status); +} + +static void scmi_voltd_level_get(struct scmi_msg *msg) +{ + const struct scmi_voltd_level_get_a2p *in_args = (void *)msg->in; + struct scmi_voltd_level_get_p2a out_args = { + .status = SCMI_SUCCESS, + }; + unsigned int domain_id = 0; + long level = 0; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + domain_id = confine_array_index(in_args->domain_id, + plat_scmi_voltd_count(msg->channel_id)); + + out_args.status = plat_scmi_voltd_get_level(msg->channel_id, domain_id, + &level); + out_args.voltage_level = level; + + scmi_write_response(msg, &out_args, sizeof(out_args)); +} + +static const scmi_msg_handler_t handler_array[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_VOLTAGE_DOMAIN_ATTRIBUTES] = scmi_voltd_domain_attributes, + [SCMI_VOLTAGE_DESCRIBE_LEVELS] = scmi_voltd_describe_levels, + [SCMI_VOLTAGE_CONFIG_SET] = scmi_voltd_config_set, + [SCMI_VOLTAGE_CONFIG_GET] = scmi_voltd_config_get, + [SCMI_VOLTAGE_LEVEL_SET] = scmi_voltd_level_set, + [SCMI_VOLTAGE_LEVEL_GET] = scmi_voltd_level_get, +}; + +static bool message_id_is_supported(unsigned int id) +{ + return id < ARRAY_SIZE(handler_array) && handler_array[id]; +} + +scmi_msg_handler_t scmi_msg_get_voltd_handler(struct scmi_msg *msg) +{ + const size_t array_size = ARRAY_SIZE(handler_array); + unsigned int message_id = 0; + + if (msg->message_id >= array_size) { + DMSG("Voltage domain handle not found %u", msg->message_id); + return NULL; + } + + message_id = confine_array_index(msg->message_id, array_size); + + return handler_array[message_id]; +} diff --git a/optee/optee_os/core/drivers/scmi-msg/voltage_domain.h b/optee/optee_os/core/drivers/scmi-msg/voltage_domain.h new file mode 100644 index 0000000..be53cb6 --- /dev/null +++ b/optee/optee_os/core/drivers/scmi-msg/voltage_domain.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef SCMI_MSG_VOLTAGE_DOMAIN_H +#define SCMI_MSG_VOLTAGE_DOMAIN_H + +#include +#include + +#include "common.h" + +#define SCMI_PROTOCOL_VERSION_VOLTAGE_DOMAIN 0x30000 + +/* + * Identifiers of the SCMI Clock Management Protocol commands + */ +enum scmi_voltd_command_id { + SCMI_VOLTAGE_DOMAIN_ATTRIBUTES = 0x3, + SCMI_VOLTAGE_DESCRIBE_LEVELS = 0x4, + SCMI_VOLTAGE_CONFIG_SET = 0x5, + SCMI_VOLTAGE_CONFIG_GET = 0x6, + SCMI_VOLTAGE_LEVEL_SET = 0x7, + SCMI_VOLTAGE_LEVEL_GET = 0x8, +}; + +#define SCMI_VOLTAGE_DOMAIN_COUNT_MASK GENMASK_32(15, 0) + +struct scmi_voltd_protocol_attrs_p2a { + int32_t status; + uint32_t attributes; +}; + +struct scmi_voltd_attributes_a2p { + uint32_t domain_id; +}; + +#define SCMI_VOLTAGE_DOMAIN_NAME_MAX 16 + +struct scmi_voltd_attributes_p2a { + int32_t status; + uint32_t attributes; + char name[SCMI_VOLTAGE_DOMAIN_NAME_MAX]; +}; + +struct scmi_voltd_describe_levels_a2p { + uint32_t domain_id; + uint32_t level_index; +}; + +#define SCMI_VOLTD_LEVELS_REMAINING_MASK GENMASK_32(31, 16) +#define SCMI_VOLTD_LEVELS_REMAINING_POS 16 + +#define SCMI_VOLTD_LEVELS_FORMAT_RANGE 1 +#define SCMI_VOLTD_LEVELS_FORMAT_LIST 0 +#define SCMI_VOLTD_LEVELS_FORMAT_MASK BIT(12) +#define SCMI_VOLTD_LEVELS_FORMAT_POS 12 + +#define SCMI_VOLTD_LEVELS_COUNT_MASK GENMASK_32(11, 0) + +#define SCMI_VOLTAGE_DOMAIN_LEVELS_FLAGS(_count, _fmt, _rem_rates) \ + ( \ + ((_count) & SCMI_VOLTD_LEVELS_COUNT_MASK) | \ + (((_rem_rates) << SCMI_VOLTD_LEVELS_REMAINING_POS) & \ + SCMI_VOLTD_LEVELS_REMAINING_MASK) | \ + (((_fmt) << SCMI_VOLTD_LEVELS_FORMAT_POS) & \ + SCMI_VOLTD_LEVELS_FORMAT_MASK) \ + ) + +struct scmi_voltd_level { + int32_t mircovolt; +}; + +struct scmi_voltd_describe_levels_p2a { + int32_t status; + uint32_t flags; + struct scmi_voltd_level voltage[]; +}; + +struct scmi_voltd_level_set_a2p { + uint32_t domain_id; + uint32_t flags; + int32_t voltage_level; +}; + +struct scmi_voltd_level_set_p2a { + uint32_t status; +}; + +struct scmi_voltd_level_get_a2p { + uint32_t domain_id; +}; + +struct scmi_voltd_level_get_p2a { + int32_t status; + int32_t voltage_level; +}; + +#define SCMI_VOLTAGE_DOMAIN_CONFIG_MASK GENMASK_32(3, 0) + +struct scmi_voltd_config_set_a2p { + uint32_t domain_id; + uint32_t config; +}; + +struct scmi_voltd_config_set_p2a { + uint32_t status; +}; + +struct scmi_voltd_config_get_a2p { + uint32_t domain_id; +}; + +struct scmi_voltd_config_get_p2a { + int32_t status; + uint32_t config; +}; + +#ifdef CFG_SCMI_MSG_VOLTAGE_DOMAIN +/* + * scmi_msg_get_voltd_handler - Return a handler for a voltage domain message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_voltd_handler(struct scmi_msg *msg); +#else +static inline +scmi_msg_handler_t scmi_msg_get_voltd_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} +#endif +#endif /* SCMI_MSG_CLOCK_H */ diff --git a/optee/optee_os/core/drivers/serial8250_uart.c b/optee/optee_os/core/drivers/serial8250_uart.c new file mode 100644 index 0000000..dddd3e6 --- /dev/null +++ b/optee/optee_os/core/drivers/serial8250_uart.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* uart register defines */ +#define UART_RHR 0x0 +#define UART_THR 0x0 +#define UART_IER 0x4 +#define UART_ISR 0x8 +#define UART_FCR 0x8 +#define UART_LCR 0xc +#define UART_MCR 0x10 +#define UART_LSR 0x14 +#define UART_MSR 0x18 +#define UART_SPR 0x1c + +/* uart status register bits */ +#define LSR_TEMT 0x40 /* Transmitter empty */ +#define LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define LSR_EMPTY (LSR_TEMT | LSR_THRE) +#define LSR_DR 0x01 /* DATA Ready */ + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct serial8250_uart_data *pd = + container_of(chip, struct serial8250_uart_data, chip); + + return io_pa_or_va(&pd->base, SERIAL8250_UART_REG_SIZE); +} + +static void serial8250_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (1) { + uint32_t state = io_read32(base + UART_LSR); + + /* Wait until transmit FIFO is empty */ + if ((state & LSR_EMPTY) == LSR_EMPTY) + break; + } +} + +static bool serial8250_uart_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + return (io_read32(base + UART_LSR) & LSR_DR); +} + +static int serial8250_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!serial8250_uart_have_rx_data(chip)) { + /* Transmit FIFO is empty, waiting again */ + ; + } + return io_read32(base + UART_RHR) & 0xff; +} + +static void serial8250_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + serial8250_uart_flush(chip); + + /* Write out character to transmit FIFO */ + io_write32(base + UART_THR, ch); +} + +static const struct serial_ops serial8250_uart_ops = { + .flush = serial8250_uart_flush, + .getchar = serial8250_uart_getchar, + .have_rx_data = serial8250_uart_have_rx_data, + .putc = serial8250_uart_putc, +}; +DECLARE_KEEP_PAGER(serial8250_uart_ops); + +void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base, + uint32_t __unused uart_clk, + uint32_t __unused baud_rate) + +{ + pd->base.pa = base; + pd->chip.ops = &serial8250_uart_ops; + + /* + * do nothing, debug uart(uart0) share with normal world, + * everything for uart0 is ready now. + */ +} + +#ifdef CFG_DT + +static struct serial_chip *serial8250_uart_dev_alloc(void) +{ + struct serial8250_uart_data *pd = calloc(1, sizeof(*pd)); + + if (!pd) + return NULL; + return &pd->chip; +} + +static int serial8250_uart_dev_init(struct serial_chip *chip, + const void *fdt, + int offs, + const char *parms) +{ + struct serial8250_uart_data *pd = + container_of(chip, struct serial8250_uart_data, chip); + vaddr_t vbase; + paddr_t pbase; + size_t size; + + if (parms && parms[0]) + IMSG("serial8250_uart: device parameters ignored (%s)", parms); + + if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) + return -1; + + if (size < SERIAL8250_UART_REG_SIZE) { + EMSG("serial8250_uart: register size too small: %zx", size); + return -1; + } + + pbase = virt_to_phys((void *)vbase); + serial8250_uart_init(pd, pbase, 0, 0); + + return 0; +} + +static void serial8250_uart_dev_free(struct serial_chip *chip) +{ + struct serial8250_uart_data *pd = + container_of(chip, struct serial8250_uart_data, chip); + + free(pd); +} + +static const struct serial_driver serial8250_driver = { + .dev_alloc = serial8250_uart_dev_alloc, + .dev_init = serial8250_uart_dev_init, + .dev_free = serial8250_uart_dev_free, +}; + +static const struct dt_device_match serial8250_match_table[] = { + { .compatible = "snps,dw-apb-uart" }, + { 0 } +}; + +DEFINE_DT_DRIVER(serial8250_dt_driver) = { + .name = "serial8250_uart", + .type = DT_DRIVER_UART, + .match_table = serial8250_match_table, + .driver = &serial8250_driver, +}; + +#endif /* CFG_DT */ diff --git a/optee/optee_os/core/drivers/smccc_trng.c b/optee/optee_os/core/drivers/smccc_trng.c new file mode 100644 index 0000000..4d28ff0 --- /dev/null +++ b/optee/optee_os/core/drivers/smccc_trng.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022 Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Arm SMCCC TRNG firmware interface specification: + * https://developer.arm.com/documentation/den0098/ + */ +#define ARM_SMCCC_TRNG_VERSION 0x84000050 +#define ARM_SMCCC_TRNG_FEATURES 0x84000051 +#define ARM_SMCCC_TRNG_GET_UUID 0x84000052 +#define ARM_SMCCC_TRNG_RND_32 0x84000053 +#define ARM_SMCCC_TRNG_RND_64 0xc4000053 + +#define ARM_SMCCC_RET_TRNG_SUCCESS U(0) +#define ARM_SMCCC_RET_TRNG_NOT_SUPPORTED ((unsigned long)-1) +#define ARM_SMCCC_RET_TRNG_INVALID_PARAMETER ((unsigned long)-2) +#define ARM_SMCCC_RET_TRNG_NO_ENTROPY ((unsigned long)-3) + +#define TRNG_MAJOR_MASK GENMASK_32(30, 16) +#define TRNG_MAJOR_SHIFT 16 +#define TRNG_MINOR_MASK GENMASK_32(15, 0) +#define TRNG_MINOR_SHIFT 0 +#define TRNG_MAKE_VERSION(major, minor) \ + ((SHIFT_U32(major, TRNG_MAJOR_SHIFT) & TRNG_MAJOR_MASK) | \ + (SHIFT_U32(minor, TRNG_MINOR_SHIFT) & TRNG_MINOR_MASK)) + +#define TRNG_VERSION_1_0 TRNG_MAKE_VERSION(1, 0) + +#define TRNG_MAX_RND_64 (192 / 8) +#define TRNG_MAX_RND_32 (96 / 8) + +/* Function ID discovered for getting random bytes or 0 if not supported */ +static uint32_t trng_rnd_fid; + +static bool smccc_trng_is_supported(void) +{ + struct thread_smc_args args = { }; + static bool inited; + + if (inited) + return trng_rnd_fid != 0; + + inited = true; + + /* + * TRNG ABI requires caller to check that Arm SMCCC version is + * larger or equal to v1.1 + */ + args.a0 = ARM_SMCCC_VERSION; + thread_smccc(&args); + if (args.a0 & BIT32(31) || args.a0 < SMCCC_V_1_1) + return false; + + /* + * Check TRNG version, if successful we're guaranteed to have at least + * the ARM_SMCCC_TRNG_FEATURES fid. + */ + args.a0 = ARM_SMCCC_TRNG_VERSION; + thread_smccc(&args); + if (args.a0 & BIT32(31) || args.a0 < TRNG_VERSION_1_0) + return false; + +#ifdef ARM64 + args.a0 = ARM_SMCCC_TRNG_FEATURES; + args.a1 = ARM_SMCCC_TRNG_RND_64; + thread_smccc(&args); + if (args.a0 == ARM_SMCCC_RET_SUCCESS) { + trng_rnd_fid = ARM_SMCCC_TRNG_RND_64; + return true; + } +#endif + + args.a0 = ARM_SMCCC_TRNG_FEATURES; + args.a1 = ARM_SMCCC_TRNG_RND_32; + thread_smccc(&args); + if (args.a0 == ARM_SMCCC_RET_TRNG_SUCCESS) { + trng_rnd_fid = ARM_SMCCC_TRNG_RND_32; + return true; + } + + return false; +} + +static void read_bytes(unsigned long val, size_t byte_count, uint8_t **buf, + size_t *rem) +{ + size_t count = MIN(byte_count, *rem); + size_t n = 0; + + for (n = 0; n < count; n++) + (*buf)[n] = val >> (n * 8); + + *buf += count; + *rem -= count; +} + +static void read_samples(struct thread_smc_args *args, uint8_t *buf, size_t len) +{ + uint8_t *ptr = buf; + size_t rem = len; + size_t byte_count = 4; + +#ifdef ARM64 + if (trng_rnd_fid == ARM_SMCCC_TRNG_RND_64) + byte_count = 8; +#endif + + read_bytes(args->a3, byte_count, &ptr, &rem); + read_bytes(args->a2, byte_count, &ptr, &rem); + read_bytes(args->a1, byte_count, &ptr, &rem); +} + +static TEE_Result __maybe_unused smccc_trng_read(void *buf, size_t len) +{ + struct thread_smc_args args = { }; + uint8_t *ptr = buf; + size_t rem = len; + size_t max_burst = 0; + + if (!smccc_trng_is_supported()) + return TEE_ERROR_NOT_SUPPORTED; + + if (trng_rnd_fid == ARM_SMCCC_TRNG_RND_64) + max_burst = TRNG_MAX_RND_64; + else + max_burst = TRNG_MAX_RND_32; + + while (rem) { + size_t burst = MIN(rem, max_burst); + + args.a0 = trng_rnd_fid; + args.a1 = burst * 8; + + thread_smccc(&args); + + switch (args.a0) { + case ARM_SMCCC_RET_TRNG_SUCCESS: + read_samples(&args, ptr, burst); + rem -= burst; + ptr += burst; + break; + case ARM_SMCCC_RET_TRNG_NO_ENTROPY: + break; + default: + return TEE_ERROR_GENERIC; + } + } + + return TEE_SUCCESS; +} + +static void __maybe_unused smccc_trng_print_info(void) +{ + struct thread_smc_args args = { }; + unsigned int __maybe_unused major = 0; + unsigned int __maybe_unused minor = 0; + + if (!IS_ENABLED(CFG_TEE_CORE_DEBUG)) + return; + + args.a0 = ARM_SMCCC_TRNG_VERSION; + thread_smccc(&args); + assert((args.a0 & BIT32(31)) == 0); + major = (args.a0 & TRNG_MAJOR_MASK) >> TRNG_MAJOR_SHIFT; + minor = (args.a0 & TRNG_MINOR_MASK) >> TRNG_MINOR_SHIFT; + + args.a0 = ARM_SMCCC_TRNG_GET_UUID; + thread_smccc(&args); + assert(args.a0 != ARM_SMCCC_RET_TRNG_NOT_SUPPORTED); + + DMSG("SMCCC TRNG v%u.%u, UUID %08lx-%04lx-%04lx-%04lx-%04lx%08lx\n", + major, minor, (unsigned long)args.a0, (unsigned long)args.a1 >> 16, + (unsigned long)args.a1 & GENMASK_32(16, 0), + (unsigned long)args.a2 >> 16, + (unsigned long)args.a2 & GENMASK_32(16, 0), + (unsigned long)args.a3); +} + +void plat_rng_init(void) +{ + if (!smccc_trng_is_supported()) + panic("SMCCC TRNG not supported"); + + smccc_trng_print_info(); + + if (IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)) { + /* If CFG_WITH_SOFTWARE_PRNG is enabled, seed PRNG with TRNG */ + uint8_t seed[32] = { 0 }; + + if (smccc_trng_read(seed, sizeof(seed))) + panic("SMCCC TRNG not supported"); + + if (crypto_rng_init(seed, sizeof(seed))) + panic(); + } +} + +/* If CFG_WITH_SOFTWARE_PRNG is disabled, TRNG is our HW RNG */ +#ifndef CFG_WITH_SOFTWARE_PRNG +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + return smccc_trng_read(buf, len); +} +#endif diff --git a/optee/optee_os/core/drivers/sp805_wdt.c b/optee/optee_os/core/drivers/sp805_wdt.c new file mode 100644 index 0000000..048620c --- /dev/null +++ b/optee/optee_os/core/drivers/sp805_wdt.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Broadcom + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static vaddr_t chip_to_base(struct wdt_chip *chip) +{ + struct sp805_wdt_data *pd = + container_of(chip, struct sp805_wdt_data, chip); + + return io_pa_or_va(&pd->base, WDT_SIZE); +} + +static TEE_Result sp805_setload(struct wdt_chip *chip, unsigned long timeout) +{ + struct sp805_wdt_data *pd = + container_of(chip, struct sp805_wdt_data, chip); + uint32_t load = 0; + + /* + * sp805 runs counter with given value twice, after the end of first + * counter it gives an interrupt and then starts counter again. If + * interrupt already occurred then it resets the system. This is why + * load is half of what should be required. + */ + if (MUL_OVERFLOW(timeout, pd->clk_rate, &load)) + return TEE_ERROR_SECURITY; + + load = (load / 2) - 1; + if (load < WDT_LOAD_MIN) + load = WDT_LOAD_MIN; + + pd->load_val = load; + return TEE_SUCCESS; +} + +static void sp805_config(struct wdt_chip *chip, bool enable) +{ + struct sp805_wdt_data *pd = + container_of(chip, struct sp805_wdt_data, chip); + vaddr_t base = chip_to_base(chip); + + io_write32(base + WDT_LOCK_OFFSET, WDT_UNLOCK_KEY); + io_write32(base + WDT_LOAD_OFFSET, pd->load_val); + io_write32(base + WDT_INTCLR_OFFSET, WDT_INT_CLR); + + if (enable) + io_write32(base + WDT_CONTROL_OFFSET, + WDT_INT_EN | WDT_RESET_EN); + + io_write32(base + WDT_LOCK_OFFSET, WDT_LOCK_KEY); + + /* Flush posted writes. */ + (void)io_read32(base + WDT_LOCK_OFFSET); +} + +static void sp805_ping(struct wdt_chip *chip) +{ + sp805_config(chip, false); +} + +static void sp805_enable(struct wdt_chip *chip) +{ + sp805_config(chip, true); +} + +static void sp805_disable(struct wdt_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + io_write32(base + WDT_LOCK_OFFSET, WDT_UNLOCK_KEY); + io_write32(base + WDT_CONTROL_OFFSET, 0); + io_write32(base + WDT_LOCK_OFFSET, WDT_LOCK_KEY); + + /* Flush posted writes. */ + (void)io_read32(base + WDT_LOCK_OFFSET); +} + +static enum itr_return wdt_itr_cb(struct itr_handler *h) +{ + struct wdt_chip *chip = h->data; + struct sp805_wdt_data *pd = + container_of(chip, struct sp805_wdt_data, chip); + + if (pd->itr_handler) + pd->itr_handler(chip); + + return ITRR_HANDLED; +} +DECLARE_KEEP_PAGER(wdt_itr_cb); + +TEE_Result sp805_register_itr_handler(struct sp805_wdt_data *pd, + uint32_t itr_num, uint32_t itr_flags, + sp805_itr_handler_func_t itr_handler) +{ + struct itr_handler *wdt_itr; + + assert(!pd->chip.wdt_itr); + + wdt_itr = itr_alloc_add(itr_num, wdt_itr_cb, + itr_flags, &pd->chip); + if (!wdt_itr) + return TEE_ERROR_OUT_OF_MEMORY; + + pd->itr_handler = itr_handler; + pd->chip.wdt_itr = wdt_itr; + + itr_enable(wdt_itr->it); + + return TEE_SUCCESS; +} + +static const struct wdt_ops sp805_wdt_ops = { + .start = sp805_enable, + .stop = sp805_disable, + .ping = sp805_ping, + .set_timeout = sp805_setload, +}; +DECLARE_KEEP_PAGER(sp805_wdt_ops); + +TEE_Result sp805_wdt_init(struct sp805_wdt_data *pd, paddr_t base, + uint32_t clk_rate, uint32_t timeout) +{ + assert(pd); + pd->base.pa = base; + pd->clk_rate = clk_rate; + pd->chip.ops = &sp805_wdt_ops; + return sp805_setload(&pd->chip, timeout); +} diff --git a/optee/optee_os/core/drivers/sprd_uart.c b/optee/optee_os/core/drivers/sprd_uart.c new file mode 100644 index 0000000..a30fd4e --- /dev/null +++ b/optee/optee_os/core/drivers/sprd_uart.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Spreadtrum Communications Inc. + * Copyright (c) 2017, 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 +#include +#include + +/* Register definitions */ +#define UART_TXD 0x0000 +#define UART_RXD 0x0004 +#define UART_STS1 0x000C /* data number in TX and RX fifo */ +#define UART_SIZE 0x0010 + +/* Register Bit Fields*/ +#define STS1_RXF_CNT_MASK 0x00ff /* Rx FIFO data counter mask */ +#define STS1_TXF_CNT_MASK 0xff00 /* Tx FIFO data counter mask */ + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct sprd_uart_data *pd = + container_of(chip, struct sprd_uart_data, chip); + + return io_pa_or_va(&pd->base, UART_SIZE); +} + +static void sprd_uart_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (io_read32(base + UART_STS1) & STS1_TXF_CNT_MASK) + ; +} + +static bool sprd_uart_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + return !!(io_read32(base + UART_STS1) & STS1_RXF_CNT_MASK); +} + +static void sprd_uart_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + sprd_uart_flush(chip); + io_write32(base + UART_TXD, ch); +} + +static int sprd_uart_getchar(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!sprd_uart_have_rx_data(chip)) + ; + + return io_read32(base + UART_RXD) & 0xff; +} + +static const struct serial_ops sprd_uart_ops = { + .flush = sprd_uart_flush, + .getchar = sprd_uart_getchar, + .have_rx_data = sprd_uart_have_rx_data, + .putc = sprd_uart_putc, +}; +DECLARE_KEEP_PAGER(sprd_uart_ops); + +void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &sprd_uart_ops; +} diff --git a/optee/optee_os/core/drivers/stih_asc.c b/optee/optee_os/core/drivers/stih_asc.c new file mode 100644 index 0000000..72ebffc --- /dev/null +++ b/optee/optee_os/core/drivers/stih_asc.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ +#include +#include +#include +#include + +#define ASC_BAUDRATE 0x00 +#define ASC_TXBUFFER 0x04 +#define ASC_STATUS 0x14 + +#define ASC_STATUS_TX_EMPTY BIT(1) +#define ASC_STATUS_TX_HALF_EMPTY BIT(2) + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct stih_asc_pd *pd = + container_of(chip, struct stih_asc_pd, chip); + + return io_pa_or_va(&pd->base, STIH_ASC_REG_SIZE); +} + +static void stih_asc_flush(struct serial_chip *chip) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read32(base + ASC_STATUS) & ASC_STATUS_TX_EMPTY)) + ; +} + +static void stih_asc_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = chip_to_base(chip); + + while (!(io_read32(base + ASC_STATUS) & ASC_STATUS_TX_HALF_EMPTY)) + ; + + io_write32(base + ASC_TXBUFFER, ch); +} + +static const struct serial_ops stih_asc_ops = { + .flush = stih_asc_flush, + .putc = stih_asc_putc, +}; +DECLARE_KEEP_PAGER(stih_asc_ops); + +void stih_asc_init(struct stih_asc_pd *pd, vaddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &stih_asc_ops; +} diff --git a/optee/optee_os/core/drivers/stm32_bsec.c b/optee/optee_os/core/drivers/stm32_bsec.c new file mode 100644 index 0000000..cb1237e --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_bsec.c @@ -0,0 +1,894 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2021, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_STM32MP13 +#define DT_BSEC_COMPAT "st,stm32mp13-bsec" +#endif +#ifdef CFG_STM32MP15 +#define DT_BSEC_COMPAT "st,stm32mp15-bsec" +#endif + +#define BSEC_OTP_MASK GENMASK_32(4, 0) +#define BSEC_OTP_BANK_SHIFT U(5) + +/* Permanent lock bitmasks */ +#define DATA_LOWER_OTP_PERLOCK_BIT U(3) +#define DATA_UPPER_OTP_PERLOCK_BIT U(1) + +/* BSEC register offset */ +#define BSEC_OTP_CONF_OFF U(0x000) +#define BSEC_OTP_CTRL_OFF U(0x004) +#define BSEC_OTP_WRDATA_OFF U(0x008) +#define BSEC_OTP_STATUS_OFF U(0x00C) +#define BSEC_OTP_LOCK_OFF U(0x010) +#define BSEC_DEN_OFF U(0x014) +#define BSEC_FEN_OFF U(0x018) +#define BSEC_DISTURBED_OFF U(0x01C) +#define BSEC_DISTURBED1_OFF U(0x020) +#define BSEC_DISTURBED2_OFF U(0x024) +#define BSEC_ERROR_OFF U(0x034) +#define BSEC_ERROR1_OFF U(0x038) +#define BSEC_ERROR2_OFF U(0x03C) +#define BSEC_WRLOCK_OFF U(0x04C) +#define BSEC_WRLOCK1_OFF U(0x050) +#define BSEC_WRLOCK2_OFF U(0x054) +#define BSEC_SPLOCK_OFF U(0x064) +#define BSEC_SPLOCK1_OFF U(0x068) +#define BSEC_SPLOCK2_OFF U(0x06C) +#define BSEC_SWLOCK_OFF U(0x07C) +#define BSEC_SWLOCK1_OFF U(0x080) +#define BSEC_SWLOCK2_OFF U(0x084) +#define BSEC_SRLOCK_OFF U(0x094) +#define BSEC_SRLOCK1_OFF U(0x098) +#define BSEC_SRLOCK2_OFF U(0x09C) +#define BSEC_JTAG_IN_OFF U(0x0AC) +#define BSEC_JTAG_OUT_OFF U(0x0B0) +#define BSEC_SCRATCH_OFF U(0x0B4) +#define BSEC_OTP_DATA_OFF U(0x200) +#define BSEC_IPHW_CFG_OFF U(0xFF0) +#define BSEC_IPVR_OFF U(0xFF4) +#define BSEC_IP_ID_OFF U(0xFF8) +#define BSEC_IP_MAGIC_ID_OFF U(0xFFC) + +/* BSEC_CONFIGURATION Register */ +#define BSEC_CONF_POWER_UP_MASK BIT(0) +#define BSEC_CONF_POWER_UP_SHIFT U(0) +#define BSEC_CONF_FRQ_MASK GENMASK_32(2, 1) +#define BSEC_CONF_FRQ_SHIFT U(1) +#define BSEC_CONF_PRG_WIDTH_MASK GENMASK_32(6, 3) +#define BSEC_CONF_PRG_WIDTH_SHIFT U(3) +#define BSEC_CONF_TREAD_MASK GENMASK_32(8, 7) +#define BSEC_CONF_TREAD_SHIFT U(7) + +/* BSEC_CONTROL Register */ +#define BSEC_READ U(0x000) +#define BSEC_WRITE U(0x100) +#define BSEC_LOCK U(0x200) + +/* BSEC_STATUS Register */ +#define BSEC_MODE_SECURED BIT(0) +#define BSEC_MODE_INVALID BIT(2) +#define BSEC_MODE_BUSY BIT(3) +#define BSEC_MODE_PROGFAIL BIT(4) +#define BSEC_MODE_PWR BIT(5) +#define BSEC_MODE_CLOSED BIT(8) + +/* + * OTP Lock services definition + * Value must corresponding to the bit position in the register + */ +#define BSEC_LOCK_UPPER_OTP U(0x00) +#define BSEC_LOCK_DEBUG U(0x02) +#define BSEC_LOCK_PROGRAM U(0x04) + +/* Timeout when polling on status */ +#define BSEC_TIMEOUT_US U(10000) + +struct bsec_dev { + struct io_pa_va base; + unsigned int upper_base; + unsigned int max_id; + uint32_t *nsec_access; +}; + +/* Only 1 instance of BSEC is expected per platform */ +static struct bsec_dev bsec_dev; + +/* BSEC access protection */ +static unsigned int lock = SPINLOCK_UNLOCK; + +static uint32_t bsec_lock(void) +{ + return may_spin_lock(&lock); +} + +static void bsec_unlock(uint32_t exceptions) +{ + may_spin_unlock(&lock, exceptions); +} + +static uint32_t otp_max_id(void) +{ + return bsec_dev.max_id; +} + +static uint32_t otp_upper_base(void) +{ + return bsec_dev.upper_base; +} + +static uint32_t otp_bank_offset(uint32_t otp_id) +{ + assert(otp_id <= otp_max_id()); + + return ((otp_id & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) * + sizeof(uint32_t); +} + +static vaddr_t bsec_base(void) +{ + return io_pa_or_va_secure(&bsec_dev.base, BSEC_IP_MAGIC_ID_OFF + 1); +} + +static uint32_t bsec_status(void) +{ + return io_read32(bsec_base() + BSEC_OTP_STATUS_OFF); +} + +static bool state_is_invalid_mode(void) +{ + return bsec_status() & BSEC_MODE_INVALID; +} + +static bool state_is_secured_mode(void) +{ + return bsec_status() & BSEC_MODE_SECURED; +} + +static bool state_is_closed_mode(void) +{ + uint32_t otp_cfg = 0; + uint32_t close_mode = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (IS_ENABLED(CFG_STM32MP13)) + return bsec_status() & BSEC_MODE_CLOSED; + + res = stm32_bsec_find_otp_in_nvmem_layout("cfg0_otp", &otp_cfg, NULL); + if (res) + panic("CFG0 OTP not found"); + + if (stm32_bsec_read_otp(&close_mode, otp_cfg)) + panic("Unable to read OTP"); + + return close_mode & CFG0_OTP_CLOSED_DEVICE; +} + +/* + * Check that BSEC interface does not report an error + * @otp_id : OTP number + * @check_disturbed: check only error (false) or all sources (true) + * Return a TEE_Result compliant value + */ +static TEE_Result check_no_error(uint32_t otp_id, bool check_disturbed) +{ + uint32_t bit = BIT(otp_id & BSEC_OTP_MASK); + uint32_t bank = otp_bank_offset(otp_id); + + if (io_read32(bsec_base() + BSEC_ERROR_OFF + bank) & bit) + return TEE_ERROR_GENERIC; + + if (check_disturbed && + io_read32(bsec_base() + BSEC_DISTURBED_OFF + bank) & bit) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result power_up_safmem(void) +{ + uint64_t timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); + + io_mask32(bsec_base() + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP_MASK, + BSEC_CONF_POWER_UP_MASK); + + /* + * If a timeout is detected, test the condition again to consider + * cases where timeout is due to the executing TEE thread rescheduling. + */ + while (!timeout_elapsed(timeout_ref)) + if (bsec_status() & BSEC_MODE_PWR) + break; + + if (bsec_status() & BSEC_MODE_PWR) + return TEE_SUCCESS; + + return TEE_ERROR_GENERIC; +} + +static TEE_Result power_down_safmem(void) +{ + uint64_t timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); + + io_mask32(bsec_base() + BSEC_OTP_CONF_OFF, 0, BSEC_CONF_POWER_UP_MASK); + + /* + * If a timeout is detected, test the condition again to consider + * cases where timeout is due to the executing TEE thread rescheduling. + */ + while (!timeout_elapsed(timeout_ref)) + if (!(bsec_status() & BSEC_MODE_PWR)) + break; + + if (!(bsec_status() & BSEC_MODE_PWR)) + return TEE_SUCCESS; + + return TEE_ERROR_GENERIC; +} + +TEE_Result stm32_bsec_shadow_register(uint32_t otp_id) +{ + TEE_Result result = 0; + uint32_t exceptions = 0; + uint64_t timeout_ref = 0; + bool locked = false; + + /* Check if shadowing of OTP is locked, informative only */ + result = stm32_bsec_read_sr_lock(otp_id, &locked); + if (result) + return result; + + if (locked) + DMSG("BSEC shadow warning: OTP locked"); + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + exceptions = bsec_lock(); + + result = power_up_safmem(); + if (result) + goto out; + + io_write32(bsec_base() + BSEC_OTP_CTRL_OFF, otp_id | BSEC_READ); + + timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); + while (!timeout_elapsed(timeout_ref)) + if (!(bsec_status() & BSEC_MODE_BUSY)) + break; + + if (bsec_status() & BSEC_MODE_BUSY) + result = TEE_ERROR_BUSY; + else + result = check_no_error(otp_id, true /* check-disturbed */); + + power_down_safmem(); + +out: + bsec_unlock(exceptions); + + return result; +} + +TEE_Result stm32_bsec_read_otp(uint32_t *value, uint32_t otp_id) +{ + if (otp_id > otp_max_id()) + return TEE_ERROR_BAD_PARAMETERS; + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + *value = io_read32(bsec_base() + BSEC_OTP_DATA_OFF + + (otp_id * sizeof(uint32_t))); + + return TEE_SUCCESS; +} + +TEE_Result stm32_bsec_shadow_read_otp(uint32_t *otp_value, uint32_t otp_id) +{ + TEE_Result result = 0; + + result = stm32_bsec_shadow_register(otp_id); + if (result) { + EMSG("BSEC %"PRIu32" Shadowing Error %#"PRIx32, otp_id, result); + return result; + } + + result = stm32_bsec_read_otp(otp_value, otp_id); + if (result) + EMSG("BSEC %"PRIu32" Read Error %#"PRIx32, otp_id, result); + + return result; +} + +TEE_Result stm32_bsec_write_otp(uint32_t value, uint32_t otp_id) +{ + TEE_Result result = 0; + uint32_t exceptions = 0; + vaddr_t otp_data_base = bsec_base() + BSEC_OTP_DATA_OFF; + bool locked = false; + + /* Check if write of OTP is locked, informative only */ + result = stm32_bsec_read_sw_lock(otp_id, &locked); + if (result) + return result; + + if (locked) + DMSG("BSEC write warning: OTP locked"); + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + exceptions = bsec_lock(); + + io_write32(otp_data_base + (otp_id * sizeof(uint32_t)), value); + + bsec_unlock(exceptions); + + return TEE_SUCCESS; +} + +#ifdef CFG_STM32_BSEC_WRITE +TEE_Result stm32_bsec_program_otp(uint32_t value, uint32_t otp_id) +{ + TEE_Result result = 0; + uint32_t exceptions = 0; + uint64_t timeout_ref = 0; + bool locked = false; + + /* Check if shadowing of OTP is locked, informative only */ + result = stm32_bsec_read_sp_lock(otp_id, &locked); + if (result) + return result; + + if (locked) + DMSG("BSEC program warning: OTP locked"); + + if (io_read32(bsec_base() + BSEC_OTP_LOCK_OFF) & BIT(BSEC_LOCK_PROGRAM)) + DMSG("BSEC program warning: GPLOCK activated"); + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + exceptions = bsec_lock(); + + result = power_up_safmem(); + if (result) + goto out; + + io_write32(bsec_base() + BSEC_OTP_WRDATA_OFF, value); + io_write32(bsec_base() + BSEC_OTP_CTRL_OFF, otp_id | BSEC_WRITE); + + timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); + while (!timeout_elapsed(timeout_ref)) + if (!(bsec_status() & BSEC_MODE_BUSY)) + break; + + if (bsec_status() & BSEC_MODE_BUSY) + result = TEE_ERROR_BUSY; + else if (bsec_status() & BSEC_MODE_PROGFAIL) + result = TEE_ERROR_BAD_PARAMETERS; + else + result = check_no_error(otp_id, true /* check-disturbed */); + + power_down_safmem(); + +out: + bsec_unlock(exceptions); + + return result; +} +#endif /*CFG_STM32_BSEC_WRITE*/ + +TEE_Result stm32_bsec_permanent_lock_otp(uint32_t otp_id) +{ + TEE_Result result = 0; + uint32_t data = 0; + uint32_t addr = 0; + uint32_t exceptions = 0; + vaddr_t base = bsec_base(); + uint64_t timeout_ref = 0; + uint32_t upper_base = otp_upper_base(); + + if (otp_id > otp_max_id()) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * 2 bits per words for lower OTPs: 2:1 Redundancy + * 1 bit per word for upper OTPs : ECC support + * e.g with 32 lower and 64 upper OTPs: + * OTP word to be ADDR[6:0] WRDATA[31:0] + * locked + * 0 0x00 0x0000 0003 + * 1 0x00 0x0000 000C + * ... ... ... + * 7 0x00 0x0000 C000 + * 8 0x01 0x0000 0003 + * ... ... ... + * 31 0x03 0x0000 C000 + * 32 0x04 0x0000 0001 + * 33 0x04 0x0000 0002 + * 95 0x07 0x0000 8000 + */ + if (otp_id < upper_base) { + addr = otp_id / 8U; + data = DATA_LOWER_OTP_PERLOCK_BIT << ((otp_id * 2U) & 0xF); + } else { + addr = upper_base / 8U + (otp_id - upper_base) / 16U; + data = DATA_UPPER_OTP_PERLOCK_BIT << (otp_id & 0xF); + } + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + exceptions = bsec_lock(); + + result = power_up_safmem(); + if (result) + goto out; + + io_write32(base + BSEC_OTP_WRDATA_OFF, data); + io_write32(base + BSEC_OTP_CTRL_OFF, addr | BSEC_WRITE | BSEC_LOCK); + + timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); + while (!timeout_elapsed(timeout_ref)) + if (!(bsec_status() & BSEC_MODE_BUSY)) + break; + + if (bsec_status() & BSEC_MODE_BUSY) + result = TEE_ERROR_BUSY; + else if (bsec_status() & BSEC_MODE_PROGFAIL) + result = TEE_ERROR_BAD_PARAMETERS; + else + result = check_no_error(otp_id, false /* not-disturbed */); + +#ifdef CFG_STM32MP13 + io_write32(base + BSEC_OTP_CTRL_OFF, addr | BSEC_READ | BSEC_LOCK); +#endif + + power_down_safmem(); + +out: + bsec_unlock(exceptions); + + return result; +} + +TEE_Result stm32_bsec_write_debug_conf(uint32_t value) +{ + TEE_Result result = TEE_ERROR_GENERIC; + uint32_t exceptions = 0; + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + exceptions = bsec_lock(); + + io_write32(bsec_base() + BSEC_DEN_OFF, value); + + if ((io_read32(bsec_base() + BSEC_DEN_OFF) ^ value) == 0U) + result = TEE_SUCCESS; + + bsec_unlock(exceptions); + + return result; +} + +uint32_t stm32_bsec_read_debug_conf(void) +{ + return io_read32(bsec_base() + BSEC_DEN_OFF); +} + +static TEE_Result set_bsec_lock(uint32_t otp_id, size_t lock_offset) +{ + uint32_t bank = otp_bank_offset(otp_id); + uint32_t otp_mask = BIT(otp_id & BSEC_OTP_MASK); + vaddr_t lock_addr = bsec_base() + bank + lock_offset; + uint32_t exceptions = 0; + + if (otp_id > STM32MP1_OTP_MAX_ID) + return TEE_ERROR_BAD_PARAMETERS; + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + exceptions = bsec_lock(); + + io_write32(lock_addr, otp_mask); + + bsec_unlock(exceptions); + + return TEE_SUCCESS; +} + +TEE_Result stm32_bsec_set_sr_lock(uint32_t otp_id) +{ + return set_bsec_lock(otp_id, BSEC_SRLOCK_OFF); +} + +TEE_Result stm32_bsec_set_sw_lock(uint32_t otp_id) +{ + return set_bsec_lock(otp_id, BSEC_SWLOCK_OFF); +} + +TEE_Result stm32_bsec_set_sp_lock(uint32_t otp_id) +{ + return set_bsec_lock(otp_id, BSEC_SPLOCK_OFF); +} + +static TEE_Result read_bsec_lock(uint32_t otp_id, bool *locked, + size_t lock_offset) +{ + uint32_t bank = otp_bank_offset(otp_id); + uint32_t otp_mask = BIT(otp_id & BSEC_OTP_MASK); + vaddr_t lock_addr = bsec_base() + bank + lock_offset; + + if (otp_id > STM32MP1_OTP_MAX_ID) + return TEE_ERROR_BAD_PARAMETERS; + + if (state_is_invalid_mode()) + return TEE_ERROR_SECURITY; + + *locked = (io_read32(lock_addr) & otp_mask) != 0; + + return TEE_SUCCESS; +} + +TEE_Result stm32_bsec_read_sr_lock(uint32_t otp_id, bool *locked) +{ + return read_bsec_lock(otp_id, locked, BSEC_SRLOCK_OFF); +} + +TEE_Result stm32_bsec_read_sw_lock(uint32_t otp_id, bool *locked) +{ + return read_bsec_lock(otp_id, locked, BSEC_SWLOCK_OFF); +} + +TEE_Result stm32_bsec_read_sp_lock(uint32_t otp_id, bool *locked) +{ + return read_bsec_lock(otp_id, locked, BSEC_SPLOCK_OFF); +} + +TEE_Result stm32_bsec_read_permanent_lock(uint32_t otp_id, bool *locked) +{ + return read_bsec_lock(otp_id, locked, BSEC_WRLOCK_OFF); +} + +static size_t nsec_access_array_size(void) +{ + size_t upper_count = otp_max_id() - otp_upper_base() + 1; + + return ROUNDUP_DIV(upper_count, BSEC_BITS_PER_WORD); +} + +static bool nsec_access_granted(unsigned int index) +{ + uint32_t *array = bsec_dev.nsec_access; + + return array && + (index / BSEC_BITS_PER_WORD) < nsec_access_array_size() && + array[index / BSEC_BITS_PER_WORD] & + BIT(index % BSEC_BITS_PER_WORD); +} + +bool stm32_bsec_can_access_otp(uint32_t otp_id) +{ + return (otp_id <= otp_max_id()) && !state_is_invalid_mode(); +} + +bool stm32_bsec_nsec_can_access_otp(uint32_t otp_id) +{ + return otp_id < otp_upper_base() || + nsec_access_granted(otp_id - otp_upper_base()); +} + +struct nvmem_layout { + char *name; + uint32_t otp_id; + size_t bit_len; +}; + +static struct nvmem_layout *nvmem_layout; +static size_t nvmem_layout_count; + +TEE_Result stm32_bsec_find_otp_in_nvmem_layout(const char *name, + uint32_t *otp_id, + size_t *otp_bit_len) +{ + size_t i = 0; + + if (!name) + return TEE_ERROR_BAD_PARAMETERS; + + for (i = 0; i < nvmem_layout_count; i++) { + if (!nvmem_layout[i].name || strcmp(name, nvmem_layout[i].name)) + continue; + + if (otp_id) + *otp_id = nvmem_layout[i].otp_id; + + if (otp_bit_len) + *otp_bit_len = nvmem_layout[i].bit_len; + + DMSG("nvmem %s = %zu: %"PRId32" %zu", name, i, + nvmem_layout[i].otp_id, nvmem_layout[i].bit_len); + + return TEE_SUCCESS; + } + + DMSG("nvmem %s failed", name); + + return TEE_ERROR_ITEM_NOT_FOUND; +}; + +TEE_Result stm32_bsec_get_state(uint32_t *state) +{ + if (!state) + return TEE_ERROR_BAD_PARAMETERS; + + if (state_is_invalid_mode() || !state_is_secured_mode()) { + *state = BSEC_STATE_INVALID; + } else { + if (state_is_closed_mode()) + *state = BSEC_STATE_SEC_CLOSED; + else + *state = BSEC_STATE_SEC_OPEN; + } + + return TEE_SUCCESS; +} + +static void enable_nsec_access(unsigned int otp_id) +{ + unsigned int idx = (otp_id - otp_upper_base()) / BSEC_BITS_PER_WORD; + + if (otp_id < otp_upper_base()) + return; + + if (otp_id > otp_max_id() || stm32_bsec_shadow_register(otp_id)) + panic(); + + bsec_dev.nsec_access[idx] |= BIT(otp_id % BSEC_BITS_PER_WORD); +} + +static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node) +{ + int bsec_subnode = 0; + + bsec_dev.nsec_access = calloc(nsec_access_array_size(), + sizeof(*bsec_dev.nsec_access)); + if (!bsec_dev.nsec_access) + panic(); + + fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { + unsigned int reg_offset = 0; + unsigned int reg_size = 0; + unsigned int otp_id = 0; + unsigned int i = 0; + size_t size = 0; + + reg_offset = fdt_reg_base_address(fdt, bsec_subnode); + reg_size = fdt_reg_size(fdt, bsec_subnode); + + assert(reg_offset != DT_INFO_INVALID_REG && + reg_size != DT_INFO_INVALID_REG_SIZE); + + otp_id = reg_offset / sizeof(uint32_t); + + if (otp_id < STM32MP1_UPPER_OTP_START) { + unsigned int otp_end = + ROUNDUP_DIV(reg_offset + reg_size, + sizeof(uint32_t)); + + if (otp_end > STM32MP1_UPPER_OTP_START) { + /* + * OTP crosses Lower/Upper boundary, consider + * only the upper part. + */ + otp_id = STM32MP1_UPPER_OTP_START; + reg_size -= (STM32MP1_UPPER_OTP_START * + sizeof(uint32_t)) - reg_offset; + reg_offset = STM32MP1_UPPER_OTP_START * + sizeof(uint32_t); + + DMSG("OTP crosses Lower/Upper boundary"); + } else { + continue; + } + } + + /* Handle different kinds of non-secure accesses */ + if (fdt_getprop(fdt, bsec_subnode, + "st,non-secure-otp-provisioning", NULL)) { + bool locked = false; + bool locked_2 = false; + + /* Check if write of OTP is locked */ + if (stm32_bsec_read_permanent_lock(otp_id, &locked)) + panic("Cannot read permanent lock"); + + /* + * Check if fuses of the subnode + * have the same lock status + */ + for (i = 1; i < (reg_size / sizeof(uint32_t)); i++) { + if (stm32_bsec_read_permanent_lock(otp_id + i, + &locked_2)) + panic("Cannot read permanent lock"); + + if (locked != locked_2) { + EMSG("Inconsistent status OTP ID %u", + otp_id + i); + locked = true; + } + } + + if (locked) { + DMSG("BSEC: OTP locked"); + continue; + } + } else if (!fdt_getprop(fdt, bsec_subnode, "st,non-secure-otp", + NULL)) { + continue; + } + + if ((reg_offset % sizeof(uint32_t)) || + (reg_size % sizeof(uint32_t))) + panic("Unaligned non-secure OTP"); + + size = reg_size / sizeof(uint32_t); + + if (otp_id + size > OTP_MAX_SIZE) + panic("OTP range oversized"); + + for (i = otp_id; i < otp_id + size; i++) + enable_nsec_access(i); + } +} + +static void save_dt_nvmem_layout(void *fdt, int bsec_node) +{ + int cell_max = 0; + int cell_cnt = 0; + int node = 0; + + fdt_for_each_subnode(node, fdt, bsec_node) + cell_max++; + if (!cell_max) + return; + + nvmem_layout = calloc(cell_max, sizeof(*nvmem_layout)); + if (!nvmem_layout) + panic(); + + fdt_for_each_subnode(node, fdt, bsec_node) { + unsigned int reg_offset = 0; + unsigned int reg_length = 0; + const char *string = NULL; + const char *s = NULL; + int len = 0; + struct nvmem_layout *layout_cell = &nvmem_layout[cell_cnt]; + + string = fdt_get_name(fdt, node, &len); + if (!string || !len) + continue; + + reg_offset = fdt_reg_base_address(fdt, node); + reg_length = fdt_reg_size(fdt, node); + + if (reg_offset == DT_INFO_INVALID_REG || + reg_length == DT_INFO_INVALID_REG_SIZE) { + DMSG("Malformed nvmem %s: ignored", string); + continue; + } + + if (reg_offset % sizeof(uint32_t)) { + DMSG("Misaligned nvmem %s: ignored", string); + continue; + } + layout_cell->otp_id = reg_offset / sizeof(uint32_t); + layout_cell->bit_len = reg_length * CHAR_BIT; + + s = strchr(string, '@'); + if (s) + len = s - string; + + layout_cell->name = strndup(string, len); + if (!layout_cell->name) + panic(); + cell_cnt++; + DMSG("nvmem[%d] = %s %"PRId32" %zu", cell_cnt, + layout_cell->name, layout_cell->otp_id, + layout_cell->bit_len); + } + + if (cell_cnt != cell_max) { + nvmem_layout = realloc(nvmem_layout, + cell_cnt * sizeof(*nvmem_layout)); + if (!nvmem_layout) + panic(); + } + + nvmem_layout_count = cell_cnt; +} + +static void initialize_bsec_from_dt(void) +{ + void *fdt = NULL; + int node = 0; + struct dt_node_info bsec_info = { }; + + fdt = get_embedded_dt(); + node = fdt_node_offset_by_compatible(fdt, 0, DT_BSEC_COMPAT); + if (node < 0) + panic(); + + fdt_fill_device_info(fdt, &bsec_info, node); + + if (bsec_info.reg != bsec_dev.base.pa || + !(bsec_info.status & DT_STATUS_OK_SEC)) + panic(); + + bsec_dt_otp_nsec_access(fdt, node); + + save_dt_nvmem_layout(fdt, node); +} + +static TEE_Result bsec_pm(enum pm_op op, uint32_t pm_hint __unused, + const struct pm_callback_handle *hdl __unused) +{ + static uint32_t debug_conf; + + assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME); + + if (op == PM_OP_SUSPEND) + debug_conf = stm32_bsec_read_debug_conf(); + else + stm32_bsec_write_debug_conf(debug_conf); + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(bsec_pm); + +static TEE_Result initialize_bsec(void) +{ + struct stm32_bsec_static_cfg cfg = { }; + + stm32mp_get_bsec_static_cfg(&cfg); + + bsec_dev.base.pa = cfg.base; + bsec_dev.upper_base = cfg.upper_start; + bsec_dev.max_id = cfg.max_id; + + if (state_is_invalid_mode()) + panic(); + + initialize_bsec_from_dt(); + + register_pm_core_service_cb(bsec_pm, NULL, "stm32_bsec"); + + return TEE_SUCCESS; +} + +early_init(initialize_bsec); diff --git a/optee/optee_os/core/drivers/stm32_etzpc.c b/optee/optee_os/core/drivers/stm32_etzpc.c new file mode 100644 index 0000000..b8997f3 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_etzpc.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, STMicroelectronics + */ + +/* + * STM32 ETPZC acts as a firewall on stm32mp SoC peripheral interfaces and + * internal memories. The driver expects a single instance of the controller + * in the platform. + * + * The driver API is defined in header file stm32_etzpc.h. + * + * Driver registers a PM callback for restoration of the access permissions + * when it resumes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Devicetree compatibility */ +#define ETZPC_COMPAT "st,stm32-etzpc" + +/* ID Registers */ +#define ETZPC_TZMA0_SIZE 0x000U +#define ETZPC_DECPROT0 0x010U +#define ETZPC_DECPROT_LOCK0 0x030U +#define ETZPC_HWCFGR 0x3F0U +#define ETZPC_VERR 0x3F4U + +/* ID Registers fields */ +#define ETZPC_TZMA0_SIZE_LOCK BIT(31) +#define ETZPC_DECPROT0_MASK GENMASK_32(1, 0) +#define ETZPC_HWCFGR_NUM_TZMA_MASK GENMASK_32(7, 0) +#define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0 +#define ETZPC_HWCFGR_NUM_PER_SEC_MASK GENMASK_32(15, 8) +#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8 +#define ETZPC_HWCFGR_NUM_AHB_SEC_MASK GENMASK_32(23, 16) +#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16 +#define ETZPC_HWCFGR_CHUNCKS1N4_MASK GENMASK_32(31, 24) +#define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT 24 + +#define DECPROT_SHIFT 1 +#define IDS_PER_DECPROT_REGS 16U +#define IDS_PER_DECPROT_LOCK_REGS 32U + +/* + * Implementation uses uint8_t to store each securable DECPROT configuration + * and uint16_t to store each securable TZMA configuration. When resuming + * from deep suspend, the DECPROT configurations are restored. + */ +#define PERIPH_PM_LOCK_BIT BIT(7) +#define PERIPH_PM_ATTR_MASK GENMASK_32(2, 0) +#define TZMA_PM_LOCK_BIT BIT(15) +#define TZMA_PM_VALUE_MASK GENMASK_32(9, 0) + +/* + * @base - iobase for interface base address + * @num_tzma - number of TZMA zone, read from the hardware + * @num_ahb_sec - number of securable AHB master zone, read from the hardware + * @num_per_sec - number of securable AHB & APB periphs, read from the hardware + * @periph_cfg - Backup for restoring DECPROT when resuming (PERIH_PM_*) + * @tzma_cfg - Backup for restoring TZMA when resuming (TZMA_PM_*) + */ +struct etzpc_instance { + struct io_pa_va base; + unsigned int num_tzma; + unsigned int num_per_sec; + unsigned int num_ahb_sec; + uint8_t *periph_cfg; + uint16_t *tzma_cfg; +}; + +/* Only 1 instance of the ETZPC is expected per platform */ +static struct etzpc_instance etzpc_dev; + +static vaddr_t etzpc_base(void) +{ + return io_pa_or_va_secure(&etzpc_dev.base, 1); +} + +static bool __maybe_unused valid_decprot_id(unsigned int id) +{ + return id < etzpc_dev.num_per_sec; +} + +static bool __maybe_unused valid_tzma_id(unsigned int id) +{ + return id < etzpc_dev.num_tzma; +} + +void etzpc_configure_decprot(uint32_t decprot_id, + enum etzpc_decprot_attributes decprot_attr) +{ + size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); + uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; + uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK; + vaddr_t base = etzpc_base(); + + assert(valid_decprot_id(decprot_id)); + + io_clrsetbits32(base + ETZPC_DECPROT0 + offset, + ETZPC_DECPROT0_MASK << shift, + masked_decprot << shift); + + /* Save for PM */ + assert((decprot_attr & ~PERIPH_PM_ATTR_MASK) == 0); + COMPILE_TIME_ASSERT(ETZPC_DECPROT_MAX <= UINT8_MAX); + + etzpc_dev.periph_cfg[decprot_id] &= ~PERIPH_PM_ATTR_MASK; + etzpc_dev.periph_cfg[decprot_id] |= (uint8_t)decprot_attr; +} + +enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id) +{ + size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); + uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; + vaddr_t base = etzpc_base(); + uint32_t value = 0; + + assert(valid_decprot_id(decprot_id)); + + value = (io_read32(base + ETZPC_DECPROT0 + offset) >> shift) & + ETZPC_DECPROT0_MASK; + + return (enum etzpc_decprot_attributes)value; +} + +void etzpc_lock_decprot(uint32_t decprot_id) +{ + size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); + uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); + vaddr_t base = etzpc_base(); + + assert(valid_decprot_id(decprot_id)); + + io_write32(base + offset + ETZPC_DECPROT_LOCK0, mask); + + /* Save for PM */ + etzpc_dev.periph_cfg[decprot_id] |= PERIPH_PM_LOCK_BIT; +} + +bool etzpc_get_lock_decprot(uint32_t decprot_id) +{ + size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); + uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); + vaddr_t base = etzpc_base(); + + assert(valid_decprot_id(decprot_id)); + + return io_read32(base + offset + ETZPC_DECPROT_LOCK0) & mask; +} + +void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value) +{ + size_t offset = sizeof(uint32_t) * tzma_id; + vaddr_t base = etzpc_base(); + + assert(valid_tzma_id(tzma_id)); + + io_write32(base + ETZPC_TZMA0_SIZE + offset, tzma_value); + + /* Save for PM */ + assert((tzma_value & ~TZMA_PM_VALUE_MASK) == 0); + etzpc_dev.tzma_cfg[tzma_id] &= ~TZMA_PM_VALUE_MASK; + etzpc_dev.tzma_cfg[tzma_id] |= tzma_value; +} + +uint16_t etzpc_get_tzma(uint32_t tzma_id) +{ + size_t offset = sizeof(uint32_t) * tzma_id; + vaddr_t base = etzpc_base(); + + assert(valid_tzma_id(tzma_id)); + + return io_read32(base + ETZPC_TZMA0_SIZE + offset); +} + +void etzpc_lock_tzma(uint32_t tzma_id) +{ + size_t offset = sizeof(uint32_t) * tzma_id; + vaddr_t base = etzpc_base(); + + assert(valid_tzma_id(tzma_id)); + + io_setbits32(base + ETZPC_TZMA0_SIZE + offset, ETZPC_TZMA0_SIZE_LOCK); + + /* Save for PM */ + etzpc_dev.tzma_cfg[tzma_id] |= TZMA_PM_LOCK_BIT; +} + +bool etzpc_get_lock_tzma(uint32_t tzma_id) +{ + size_t offset = sizeof(uint32_t) * tzma_id; + vaddr_t base = etzpc_base(); + + assert(valid_tzma_id(tzma_id)); + + return io_read32(base + ETZPC_TZMA0_SIZE + offset) & + ETZPC_TZMA0_SIZE_LOCK; +} + +static TEE_Result etzpc_pm(enum pm_op op, unsigned int pm_hint __unused, + const struct pm_callback_handle *pm_handle) +{ + struct etzpc_instance *dev = NULL; + unsigned int n = 0; + + if (op != PM_OP_RESUME) + return TEE_SUCCESS; + + dev = (struct etzpc_instance *)PM_CALLBACK_GET_HANDLE(pm_handle); + + for (n = 0; n < dev->num_per_sec; n++) { + unsigned int attr = dev->periph_cfg[n] & PERIPH_PM_ATTR_MASK; + + etzpc_configure_decprot(n, (enum etzpc_decprot_attributes)attr); + + if (dev->periph_cfg[n] & PERIPH_PM_LOCK_BIT) + etzpc_lock_decprot(n); + } + + for (n = 0; n < dev->num_tzma; n++) { + uint16_t value = dev->tzma_cfg[n] & TZMA_PM_VALUE_MASK; + + etzpc_configure_tzma(n, value); + + if (dev->tzma_cfg[n] & TZMA_PM_LOCK_BIT) + etzpc_lock_tzma(n); + } + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(etzpc_pm); + +static void init_pm(struct etzpc_instance *dev) +{ + unsigned int n = 0; + + dev->periph_cfg = calloc(dev->num_per_sec, sizeof(*dev->periph_cfg)); + dev->tzma_cfg = calloc(dev->num_tzma, sizeof(*dev->tzma_cfg)); + if (!dev->periph_cfg || !dev->tzma_cfg) + panic(); + + for (n = 0; n < dev->num_per_sec; n++) { + dev->periph_cfg[n] = (uint8_t)etzpc_get_decprot(n); + if (etzpc_get_lock_decprot(n)) + dev->periph_cfg[n] |= PERIPH_PM_LOCK_BIT; + } + + for (n = 0; n < dev->num_tzma; n++) { + dev->tzma_cfg[n] = (uint8_t)etzpc_get_tzma(n); + if (etzpc_get_lock_tzma(n)) + dev->tzma_cfg[n] |= TZMA_PM_LOCK_BIT; + } + + register_pm_core_service_cb(etzpc_pm, dev, "stm32-etzpc"); +} + +struct etzpc_hwcfg { + unsigned int num_tzma; + unsigned int num_per_sec; + unsigned int num_ahb_sec; + unsigned int chunk_size; +}; + +static void get_hwcfg(struct etzpc_hwcfg *hwcfg) +{ + uint32_t reg = io_read32(etzpc_base() + ETZPC_HWCFGR); + + hwcfg->num_tzma = (reg & ETZPC_HWCFGR_NUM_TZMA_MASK) >> + ETZPC_HWCFGR_NUM_TZMA_SHIFT; + hwcfg->num_per_sec = (reg & ETZPC_HWCFGR_NUM_PER_SEC_MASK) >> + ETZPC_HWCFGR_NUM_PER_SEC_SHIFT; + hwcfg->num_ahb_sec = (reg & ETZPC_HWCFGR_NUM_AHB_SEC_MASK) >> + ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT; + hwcfg->chunk_size = (reg & ETZPC_HWCFGR_CHUNCKS1N4_MASK) >> + ETZPC_HWCFGR_CHUNCKS1N4_SHIFT; +} + +static void init_device_from_hw_config(struct etzpc_instance *dev, + paddr_t pbase) +{ + struct etzpc_hwcfg hwcfg = { }; + + assert(!dev->base.pa && cpu_mmu_enabled()); + dev->base.pa = pbase; + dev->base.va = (vaddr_t)phys_to_virt(dev->base.pa, MEM_AREA_IO_SEC, 1); + assert(etzpc_base()); + + get_hwcfg(&hwcfg); + dev->num_tzma = hwcfg.num_tzma; + dev->num_per_sec = hwcfg.num_per_sec; + dev->num_ahb_sec = hwcfg.num_ahb_sec; + + DMSG("ETZPC revison 0x02%" PRIu8 ", per_sec %u, ahb_sec %u, tzma %u", + io_read8(etzpc_base() + ETZPC_VERR), + hwcfg.num_per_sec, hwcfg.num_ahb_sec, hwcfg.num_tzma); + + init_pm(dev); +} + +void stm32_etzpc_init(paddr_t base) +{ + init_device_from_hw_config(&etzpc_dev, base); +} + +static TEE_Result init_etzpc_from_dt(void) +{ + void *fdt = get_embedded_dt(); + int node = fdt_node_offset_by_compatible(fdt, -1, ETZPC_COMPAT); + int status = 0; + paddr_t pbase = 0; + + /* When using DT, expect one and only one instance, secure enabled */ + + if (node < 0) + panic(); + assert(fdt_node_offset_by_compatible(fdt, node, ETZPC_COMPAT) < 0); + + status = fdt_get_status(fdt, node); + if (!(status & DT_STATUS_OK_SEC)) + panic(); + + pbase = fdt_reg_base_address(fdt, node); + if (pbase == (paddr_t)-1) + panic(); + + init_device_from_hw_config(&etzpc_dev, pbase); + + return TEE_SUCCESS; +} + +service_init(init_etzpc_from_dt); diff --git a/optee/optee_os/core/drivers/stm32_gpio.c b/optee/optee_os/core/drivers/stm32_gpio.c new file mode 100644 index 0000000..e4ec48a --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_gpio.c @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2021, STMicroelectronics + * + * STM32 GPIO driver is used as pin controller for stm32mp SoCs. + * The driver API is defined in header file stm32_gpio.h. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_PIN_MAX 15 + +#define GPIO_MODER_OFFSET 0x00 +#define GPIO_OTYPER_OFFSET 0x04 +#define GPIO_OSPEEDR_OFFSET 0x08 +#define GPIO_PUPDR_OFFSET 0x0c +#define GPIO_IDR_OFFSET 0x10 +#define GPIO_ODR_OFFSET 0x14 +#define GPIO_BSRR_OFFSET 0x18 +#define GPIO_AFRL_OFFSET 0x20 +#define GPIO_AFRH_OFFSET 0x24 +#define GPIO_SECR_OFFSET 0x30 + +#define GPIO_ALT_LOWER_LIMIT 0x8 + +#define GPIO_MODE_MASK GENMASK_32(1, 0) +#define GPIO_OSPEED_MASK GENMASK_32(1, 0) +#define GPIO_PUPD_PULL_MASK GENMASK_32(1, 0) +#define GPIO_ALTERNATE_MASK GENMASK_32(3, 0) + +#define DT_GPIO_BANK_SHIFT 12 +#define DT_GPIO_BANK_MASK GENMASK_32(16, 12) +#define DT_GPIO_PIN_SHIFT 8 +#define DT_GPIO_PIN_MASK GENMASK_32(11, 8) +#define DT_GPIO_MODE_MASK GENMASK_32(7, 0) + +static unsigned int gpio_lock; + +/* Save to output @cfg the current GPIO (@bank/@pin) configuration */ +static void get_gpio_cfg(uint32_t bank, uint32_t pin, struct gpio_cfg *cfg) +{ + vaddr_t base = stm32_get_gpio_bank_base(bank); + struct clk *clk = stm32_get_gpio_bank_clk(bank); + + clk_enable(clk); + + /* + * Save GPIO configuration bits spread over the few bank registers. + * 1bit fields are accessed at bit position being the pin index. + * 2bit fields are accessed at bit position being twice the pin index. + * 4bit fields are accessed at bit position being fourth the pin index + * but accessed from 2 32bit registers at incremental addresses. + */ + cfg->mode = (io_read32(base + GPIO_MODER_OFFSET) >> (pin << 1)) & + GPIO_MODE_MASK; + + cfg->otype = (io_read32(base + GPIO_OTYPER_OFFSET) >> pin) & 1; + + cfg->ospeed = (io_read32(base + GPIO_OSPEEDR_OFFSET) >> (pin << 1)) & + GPIO_OSPEED_MASK; + + cfg->pupd = (io_read32(base + GPIO_PUPDR_OFFSET) >> (pin << 1)) & + GPIO_PUPD_PULL_MASK; + + cfg->od = (io_read32(base + GPIO_ODR_OFFSET) >> (pin << 1)) & 1; + + if (pin < GPIO_ALT_LOWER_LIMIT) + cfg->af = (io_read32(base + GPIO_AFRL_OFFSET) >> (pin << 2)) & + GPIO_ALTERNATE_MASK; + else + cfg->af = (io_read32(base + GPIO_AFRH_OFFSET) >> + ((pin - GPIO_ALT_LOWER_LIMIT) << 2)) & + GPIO_ALTERNATE_MASK; + + clk_disable(clk); +} + +/* Apply GPIO (@bank/@pin) configuration described by @cfg */ +static void set_gpio_cfg(uint32_t bank, uint32_t pin, struct gpio_cfg *cfg) +{ + vaddr_t base = stm32_get_gpio_bank_base(bank); + struct clk *clk = stm32_get_gpio_bank_clk(bank); + uint32_t exceptions = cpu_spin_lock_xsave(&gpio_lock); + + clk_enable(clk); + + /* Load GPIO MODE value, 2bit value shifted by twice the pin number */ + io_clrsetbits32(base + GPIO_MODER_OFFSET, + GPIO_MODE_MASK << (pin << 1), + cfg->mode << (pin << 1)); + + /* Load GPIO Output TYPE value, 1bit shifted by pin number value */ + io_clrsetbits32(base + GPIO_OTYPER_OFFSET, BIT(pin), cfg->otype << pin); + + /* Load GPIO Output Speed confguration, 2bit value */ + io_clrsetbits32(base + GPIO_OSPEEDR_OFFSET, + GPIO_OSPEED_MASK << (pin << 1), + cfg->ospeed << (pin << 1)); + + /* Load GPIO pull configuration, 2bit value */ + io_clrsetbits32(base + GPIO_PUPDR_OFFSET, BIT(pin), + cfg->pupd << (pin << 1)); + + /* Load pin mux Alternate Function configuration, 4bit value */ + if (pin < GPIO_ALT_LOWER_LIMIT) { + io_clrsetbits32(base + GPIO_AFRL_OFFSET, + GPIO_ALTERNATE_MASK << (pin << 2), + cfg->af << (pin << 2)); + } else { + size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2; + + io_clrsetbits32(base + GPIO_AFRH_OFFSET, + GPIO_ALTERNATE_MASK << shift, + cfg->af << shift); + } + + /* Load GPIO Output direction confuguration, 1bit */ + io_clrsetbits32(base + GPIO_ODR_OFFSET, BIT(pin), cfg->od << pin); + + clk_disable(clk); + cpu_spin_unlock_xrestore(&gpio_lock, exceptions); +} + +void stm32_pinctrl_load_active_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) +{ + size_t n = 0; + + for (n = 0; n < cnt; n++) + set_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, + &pinctrl[n].active_cfg); +} + +void stm32_pinctrl_load_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) +{ + size_t n = 0; + + for (n = 0; n < cnt; n++) + set_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, + &pinctrl[n].standby_cfg); +} + +void stm32_pinctrl_store_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt) +{ + size_t n = 0; + + for (n = 0; n < cnt; n++) + get_gpio_cfg(pinctrl[n].bank, pinctrl[n].pin, + &pinctrl[n].standby_cfg); +} + +/* Panic if GPIO bank information from platform do not match DTB description */ +static void ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) +{ + int pinctrl_subnode = 0; + + fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { + TEE_Result res = TEE_ERROR_GENERIC; + const fdt32_t *cuint = NULL; + struct clk *clk = NULL; + + if (fdt_getprop(fdt, pinctrl_subnode, + "gpio-controller", NULL) == NULL) + continue; + + /* Check bank register offset matches platform assumptions */ + cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); + if (fdt32_to_cpu(*cuint) != stm32_get_gpio_bank_offset(bank)) + continue; + + /* Check bank clock matches platform assumptions */ + res = clk_dt_get_by_index(fdt, pinctrl_subnode, 0, &clk); + if (res || clk != stm32_get_gpio_bank_clk(bank)) + panic(); + + /* Check controller is enabled */ + if (fdt_get_status(fdt, pinctrl_subnode) == DT_STATUS_DISABLED) + panic(); + + return; + } + + panic(); +} + +/* Count pins described in the DT node and get related data if possible */ +static int get_pinctrl_from_fdt(void *fdt, int node, + struct stm32_pinctrl *pinctrl, size_t count) +{ + const fdt32_t *cuint, *slewrate; + int len = 0; + int pinctrl_node = 0; + uint32_t i = 0; + uint32_t speed = GPIO_OSPEED_LOW; + uint32_t pull = GPIO_PUPD_NO_PULL; + size_t found = 0; + + cuint = fdt_getprop(fdt, node, "pinmux", &len); + if (!cuint) + return -FDT_ERR_NOTFOUND; + + pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); + if (pinctrl_node < 0) + return -FDT_ERR_NOTFOUND; + + slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); + if (slewrate) + speed = fdt32_to_cpu(*slewrate); + + if (fdt_getprop(fdt, node, "bias-pull-up", NULL)) + pull = GPIO_PUPD_PULL_UP; + if (fdt_getprop(fdt, node, "bias-pull-down", NULL)) + pull = GPIO_PUPD_PULL_DOWN; + + for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { + uint32_t pincfg = 0; + uint32_t bank = 0; + uint32_t pin = 0; + uint32_t mode = 0; + uint32_t alternate = 0; + bool opendrain = false; + + pincfg = fdt32_to_cpu(*cuint); + cuint++; + + bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; + + pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; + + mode = pincfg & DT_GPIO_MODE_MASK; + + switch (mode) { + case 0: + mode = GPIO_MODE_INPUT; + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + alternate = mode - 1U; + mode = GPIO_MODE_ALTERNATE; + break; + case 17: + mode = GPIO_MODE_ANALOG; + break; + default: + mode = GPIO_MODE_OUTPUT; + break; + } + + if (fdt_getprop(fdt, node, "drive-open-drain", NULL)) + opendrain = true; + + /* Check GPIO bank clock/base address against platform */ + ckeck_gpio_bank(fdt, bank, pinctrl_node); + + if (found < count) { + struct stm32_pinctrl *ref = &pinctrl[found]; + + ref->bank = (uint8_t)bank; + ref->pin = (uint8_t)pin; + ref->active_cfg.mode = mode; + ref->active_cfg.otype = opendrain ? 1 : 0; + ref->active_cfg.ospeed = speed; + ref->active_cfg.pupd = pull; + ref->active_cfg.od = 0; + ref->active_cfg.af = alternate; + /* Default to analog mode for standby state */ + ref->standby_cfg.mode = GPIO_MODE_ANALOG; + ref->standby_cfg.pupd = GPIO_PUPD_NO_PULL; + } + + found++; + } + + return (int)found; +} + +int stm32_pinctrl_fdt_get_pinctrl(void *fdt, int device_node, + struct stm32_pinctrl *pinctrl, size_t count) +{ + const fdt32_t *cuint = NULL; + int lenp = 0; + int i = 0; + size_t found = 0; + + cuint = fdt_getprop(fdt, device_node, "pinctrl-0", &lenp); + if (!cuint) + return -FDT_ERR_NOTFOUND; + + for (i = 0; i < (lenp / 4); i++) { + int node = 0; + int subnode = 0; + + node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (node < 0) + return -FDT_ERR_NOTFOUND; + + fdt_for_each_subnode(subnode, fdt, node) { + size_t n = 0; + int rc = 0; + + if (count > found) + n = count - found; + else + n = 0; + + rc = get_pinctrl_from_fdt(fdt, subnode, + &pinctrl[found], n); + if (rc < 0) + return rc; + + found += (size_t)rc; + } + + cuint++; + } + + return (int)found; +} + +int stm32_get_gpio_count(void *fdt, int pinctrl_node, unsigned int bank) +{ + int node = 0; + const fdt32_t *cuint = NULL; + + fdt_for_each_subnode(node, fdt, pinctrl_node) { + if (!fdt_getprop(fdt, node, "gpio-controller", NULL)) + continue; + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (!cuint) + continue; + + if (fdt32_to_cpu(*cuint) != stm32_get_gpio_bank_offset(bank)) + continue; + + cuint = fdt_getprop(fdt, node, "ngpios", NULL); + if (!cuint) + panic(); + + return (int)fdt32_to_cpu(*cuint); + } + + return -1; +} + +static __maybe_unused bool valid_gpio_config(unsigned int bank, + unsigned int pin, bool input) +{ + vaddr_t base = stm32_get_gpio_bank_base(bank); + uint32_t mode = (io_read32(base + GPIO_MODER_OFFSET) >> (pin << 1)) & + GPIO_MODE_MASK; + + if (pin > GPIO_PIN_MAX) + return false; + + if (input) + return mode == GPIO_MODE_INPUT; + else + return mode == GPIO_MODE_OUTPUT; +} + +int stm32_gpio_get_input_level(unsigned int bank, unsigned int pin) +{ + vaddr_t base = stm32_get_gpio_bank_base(bank); + struct clk *clk = stm32_get_gpio_bank_clk(bank); + int rc = 0; + + clk_enable(clk); + + assert(valid_gpio_config(bank, pin, true)); + + if (io_read32(base + GPIO_IDR_OFFSET) == BIT(pin)) + rc = 1; + + clk_disable(clk); + + return rc; +} + +void stm32_gpio_set_output_level(unsigned int bank, unsigned int pin, int level) +{ + vaddr_t base = stm32_get_gpio_bank_base(bank); + struct clk *clk = stm32_get_gpio_bank_clk(bank); + + clk_enable(clk); + + assert(valid_gpio_config(bank, pin, false)); + + if (level) + io_write32(base + GPIO_BSRR_OFFSET, BIT(pin)); + else + io_write32(base + GPIO_BSRR_OFFSET, BIT(pin + 16)); + + clk_disable(clk); +} + +void stm32_gpio_set_secure_cfg(unsigned int bank, unsigned int pin, bool secure) +{ + vaddr_t base = stm32_get_gpio_bank_base(bank); + struct clk *clk = stm32_get_gpio_bank_clk(bank); + uint32_t exceptions = cpu_spin_lock_xsave(&gpio_lock); + + clk_enable(clk); + + if (secure) + io_setbits32(base + GPIO_SECR_OFFSET, BIT(pin)); + else + io_clrbits32(base + GPIO_SECR_OFFSET, BIT(pin)); + + clk_disable(clk); + cpu_spin_unlock_xrestore(&gpio_lock, exceptions); +} diff --git a/optee/optee_os/core/drivers/stm32_i2c.c b/optee/optee_os/core/drivers/stm32_i2c.c new file mode 100644 index 0000000..4018717 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_i2c.c @@ -0,0 +1,1558 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) +/* + * Copyright (c) 2017-2019, STMicroelectronics + * + * The driver API is defined in header file stm32_i2c.h. + * + * I2C bus driver does not register to the PM framework. It is the + * responsibility of the bus owner to call the related STM32 I2C driver + * API functions when bus suspends or resumes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* STM32 I2C registers offsets */ +#define I2C_CR1 0x00U +#define I2C_CR2 0x04U +#define I2C_OAR1 0x08U +#define I2C_OAR2 0x0CU +#define I2C_TIMINGR 0x10U +#define I2C_TIMEOUTR 0x14U +#define I2C_ISR 0x18U +#define I2C_ICR 0x1CU +#define I2C_PECR 0x20U +#define I2C_RXDR 0x24U +#define I2C_TXDR 0x28U +#define I2C_SIZE 0x2CU + +/* Bit definition for I2C_CR1 register */ +#define I2C_CR1_PE BIT(0) +#define I2C_CR1_TXIE BIT(1) +#define I2C_CR1_RXIE BIT(2) +#define I2C_CR1_ADDRIE BIT(3) +#define I2C_CR1_NACKIE BIT(4) +#define I2C_CR1_STOPIE BIT(5) +#define I2C_CR1_TCIE BIT(6) +#define I2C_CR1_ERRIE BIT(7) +#define I2C_CR1_DNF GENMASK_32(11, 8) +#define I2C_CR1_ANFOFF BIT(12) +#define I2C_CR1_SWRST BIT(13) +#define I2C_CR1_TXDMAEN BIT(14) +#define I2C_CR1_RXDMAEN BIT(15) +#define I2C_CR1_SBC BIT(16) +#define I2C_CR1_NOSTRETCH BIT(17) +#define I2C_CR1_WUPEN BIT(18) +#define I2C_CR1_GCEN BIT(19) +#define I2C_CR1_SMBHEN BIT(22) +#define I2C_CR1_SMBDEN BIT(21) +#define I2C_CR1_ALERTEN BIT(22) +#define I2C_CR1_PECEN BIT(23) + +/* Bit definition for I2C_CR2 register */ +#define I2C_CR2_SADD GENMASK_32(9, 0) +#define I2C_CR2_RD_WRN BIT(10) +#define I2C_CR2_RD_WRN_OFFSET 10U +#define I2C_CR2_ADD10 BIT(11) +#define I2C_CR2_HEAD10R BIT(12) +#define I2C_CR2_START BIT(13) +#define I2C_CR2_STOP BIT(14) +#define I2C_CR2_NACK BIT(15) +#define I2C_CR2_NBYTES GENMASK_32(23, 16) +#define I2C_CR2_NBYTES_OFFSET 16U +#define I2C_CR2_RELOAD BIT(24) +#define I2C_CR2_AUTOEND BIT(25) +#define I2C_CR2_PECBYTE BIT(26) + +/* Bit definition for I2C_OAR1 register */ +#define I2C_OAR1_OA1 GENMASK_32(9, 0) +#define I2C_OAR1_OA1MODE BIT(10) +#define I2C_OAR1_OA1EN BIT(15) + +/* Bit definition for I2C_OAR2 register */ +#define I2C_OAR2_OA2 GENMASK_32(7, 1) +#define I2C_OAR2_OA2MSK GENMASK_32(10, 8) +#define I2C_OAR2_OA2NOMASK 0 +#define I2C_OAR2_OA2MASK01 BIT(8) +#define I2C_OAR2_OA2MASK02 BIT(9) +#define I2C_OAR2_OA2MASK03 GENMASK_32(9, 8) +#define I2C_OAR2_OA2MASK04 BIT(10) +#define I2C_OAR2_OA2MASK05 (BIT(8) | BIT(10)) +#define I2C_OAR2_OA2MASK06 (BIT(9) | BIT(10)) +#define I2C_OAR2_OA2MASK07 GENMASK_32(10, 8) +#define I2C_OAR2_OA2EN BIT(15) + +/* Bit definition for I2C_TIMINGR register */ +#define I2C_TIMINGR_SCLL GENMASK_32(7, 0) +#define I2C_TIMINGR_SCLH GENMASK_32(15, 8) +#define I2C_TIMINGR_SDADEL GENMASK_32(19, 16) +#define I2C_TIMINGR_SCLDEL GENMASK_32(23, 20) +#define I2C_TIMINGR_PRESC GENMASK_32(31, 28) +#define I2C_TIMINGR_SCLL_MAX (I2C_TIMINGR_SCLL + 1) +#define I2C_TIMINGR_SCLH_MAX ((I2C_TIMINGR_SCLH >> 8) + 1) +#define I2C_TIMINGR_SDADEL_MAX ((I2C_TIMINGR_SDADEL >> 16) + 1) +#define I2C_TIMINGR_SCLDEL_MAX ((I2C_TIMINGR_SCLDEL >> 20) + 1) +#define I2C_TIMINGR_PRESC_MAX ((I2C_TIMINGR_PRESC >> 28) + 1) +#define I2C_SET_TIMINGR_SCLL(n) ((n) & \ + (I2C_TIMINGR_SCLL_MAX - 1)) +#define I2C_SET_TIMINGR_SCLH(n) (((n) & \ + (I2C_TIMINGR_SCLH_MAX - 1)) << 8) +#define I2C_SET_TIMINGR_SDADEL(n) (((n) & \ + (I2C_TIMINGR_SDADEL_MAX - 1)) << 16) +#define I2C_SET_TIMINGR_SCLDEL(n) (((n) & \ + (I2C_TIMINGR_SCLDEL_MAX - 1)) << 20) +#define I2C_SET_TIMINGR_PRESC(n) (((n) & \ + (I2C_TIMINGR_PRESC_MAX - 1)) << 28) + +/* Bit definition for I2C_TIMEOUTR register */ +#define I2C_TIMEOUTR_TIMEOUTA GENMASK_32(11, 0) +#define I2C_TIMEOUTR_TIDLE BIT(12) +#define I2C_TIMEOUTR_TIMOUTEN BIT(15) +#define I2C_TIMEOUTR_TIMEOUTB GENMASK_32(27, 16) +#define I2C_TIMEOUTR_TEXTEN BIT(31) + +/* Bit definition for I2C_ISR register */ +#define I2C_ISR_TXE BIT(0) +#define I2C_ISR_TXIS BIT(1) +#define I2C_ISR_RXNE BIT(2) +#define I2C_ISR_ADDR BIT(3) +#define I2C_ISR_NACKF BIT(4) +#define I2C_ISR_STOPF BIT(5) +#define I2C_ISR_TC BIT(6) +#define I2C_ISR_TCR BIT(7) +#define I2C_ISR_BERR BIT(8) +#define I2C_ISR_ARLO BIT(9) +#define I2C_ISR_OVR BIT(10) +#define I2C_ISR_PECERR BIT(11) +#define I2C_ISR_TIMEOUT BIT(12) +#define I2C_ISR_ALERT BIT(13) +#define I2C_ISR_BUSY BIT(15) +#define I2C_ISR_DIR BIT(16) +#define I2C_ISR_ADDCODE GENMASK_32(23, 17) + +/* Bit definition for I2C_ICR register */ +#define I2C_ICR_ADDRCF BIT(3) +#define I2C_ICR_NACKCF BIT(4) +#define I2C_ICR_STOPCF BIT(5) +#define I2C_ICR_BERRCF BIT(8) +#define I2C_ICR_ARLOCF BIT(9) +#define I2C_ICR_OVRCF BIT(10) +#define I2C_ICR_PECCF BIT(11) +#define I2C_ICR_TIMOUTCF BIT(12) +#define I2C_ICR_ALERTCF BIT(13) + +/* Max data size for a single I2C transfer */ +#define MAX_NBYTE_SIZE 255U + +#define I2C_NSEC_PER_SEC 1000000000UL +#define I2C_TIMEOUT_BUSY_MS 25 +#define I2C_TIMEOUT_BUSY_US (I2C_TIMEOUT_BUSY_MS * 1000) +#define I2C_TIMEOUT_RXNE_MS 5 + +#define CR2_RESET_MASK (I2C_CR2_SADD | I2C_CR2_HEAD10R | \ + I2C_CR2_NBYTES | I2C_CR2_RELOAD | \ + I2C_CR2_RD_WRN) + +#define TIMINGR_CLEAR_MASK (I2C_TIMINGR_SCLL | I2C_TIMINGR_SCLH | \ + I2C_TIMINGR_SDADEL | \ + I2C_TIMINGR_SCLDEL | I2C_TIMINGR_PRESC) + +/* + * I2C transfer modes + * I2C_RELOAD: Enable Reload mode + * I2C_AUTOEND_MODE: Enable automatic end mode + * I2C_SOFTEND_MODE: Enable software end mode + */ +#define I2C_RELOAD_MODE I2C_CR2_RELOAD +#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND +#define I2C_SOFTEND_MODE 0x0 + +/* + * Start/restart/stop I2C transfer requests. + * + * I2C_NO_STARTSTOP: Don't Generate stop and start condition + * I2C_GENERATE_STOP: Generate stop condition (size should be set to 0) + * I2C_GENERATE_START_READ: Generate Restart for read request. + * I2C_GENERATE_START_WRITE: Generate Restart for write request + */ +#define I2C_NO_STARTSTOP 0x0 +#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP) +#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \ + I2C_CR2_RD_WRN) +#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) + +/* Memory address byte sizes */ +#define I2C_MEMADD_SIZE_8BIT 1 +#define I2C_MEMADD_SIZE_16BIT 2 + +/* Effective rate cannot be lower than 80% target rate */ +#define RATE_MIN(rate) (((rate) * 80U) / 100U) + +/* + * struct i2c_spec_s - Private I2C timing specifications. + * @rate: I2C bus speed (Hz) + * @fall_max: Max fall time of both SDA and SCL signals (ns) + * @rise_max: Max rise time of both SDA and SCL signals (ns) + * @hddat_min: Min data hold time (ns) + * @vddat_max: Max data valid time (ns) + * @sudat_min: Min data setup time (ns) + * @l_min: Min low period of the SCL clock (ns) + * @h_min: Min high period of the SCL clock (ns) + */ +struct i2c_spec_s { + uint32_t rate; + uint32_t fall_max; + uint32_t rise_max; + uint32_t hddat_min; + uint32_t vddat_max; + uint32_t sudat_min; + uint32_t l_min; + uint32_t h_min; +}; + +/* + * struct i2c_timing_s - Private I2C output parameters. + * @scldel: Data setup time + * @sdadel: Data hold time + * @sclh: SCL high period (master mode) + * @sclh: SCL low period (master mode) + * @is_saved: True if relating to a configuration candidate + */ +struct i2c_timing_s { + uint8_t scldel; + uint8_t sdadel; + uint8_t sclh; + uint8_t scll; + bool is_saved; +}; + +/* This table must be sorted in increasing value for field @rate */ +static const struct i2c_spec_s i2c_specs[] = { + /* Standard - 100KHz */ + { + .rate = I2C_STANDARD_RATE, + .fall_max = 300, + .rise_max = 1000, + .hddat_min = 0, + .vddat_max = 3450, + .sudat_min = 250, + .l_min = 4700, + .h_min = 4000, + }, + /* Fast - 400KHz */ + { + .rate = I2C_FAST_RATE, + .fall_max = 300, + .rise_max = 300, + .hddat_min = 0, + .vddat_max = 900, + .sudat_min = 100, + .l_min = 1300, + .h_min = 600, + }, + /* FastPlus - 1MHz */ + { + .rate = I2C_FAST_PLUS_RATE, + .fall_max = 100, + .rise_max = 120, + .hddat_min = 0, + .vddat_max = 450, + .sudat_min = 50, + .l_min = 500, + .h_min = 260, + }, +}; + +/* + * I2C request parameters + * @dev_addr: I2C address of the target device + * @mode: Communication mode, one of I2C_MODE_(MASTER|MEM) + * @mem_addr: Target memory cell accessed in device (memory mode) + * @mem_addr_size: Byte size of the memory cell address (memory mode) + * @timeout_ms: Timeout in millisenconds for the request + */ +struct i2c_request { + uint32_t dev_addr; + enum i2c_mode_e mode; + uint32_t mem_addr; + uint32_t mem_addr_size; + unsigned int timeout_ms; +}; + +static vaddr_t get_base(struct i2c_handle_s *hi2c) +{ + return io_pa_or_va_secure(&hi2c->base, hi2c->reg_size); +} + +static void notif_i2c_timeout(struct i2c_handle_s *hi2c) +{ + hi2c->i2c_err |= I2C_ERROR_TIMEOUT; + hi2c->i2c_state = I2C_STATE_READY; +} + +static const struct i2c_spec_s *get_specs(uint32_t rate) +{ + size_t i = 0; + + for (i = 0; i < ARRAY_SIZE(i2c_specs); i++) + if (rate <= i2c_specs[i].rate) + return i2c_specs + i; + + return NULL; +} + +static void save_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg) +{ + vaddr_t base = get_base(hi2c); + + clk_enable(hi2c->clock); + + cfg->cr1 = io_read32(base + I2C_CR1); + cfg->cr2 = io_read32(base + I2C_CR2); + cfg->oar1 = io_read32(base + I2C_OAR1); + cfg->oar2 = io_read32(base + I2C_OAR2); + cfg->timingr = io_read32(base + I2C_TIMINGR); + + clk_disable(hi2c->clock); +} + +static void restore_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg) +{ + vaddr_t base = get_base(hi2c); + + clk_enable(hi2c->clock); + + io_clrbits32(base + I2C_CR1, I2C_CR1_PE); + io_write32(base + I2C_TIMINGR, cfg->timingr & TIMINGR_CLEAR_MASK); + io_write32(base + I2C_OAR1, cfg->oar1); + io_write32(base + I2C_CR2, cfg->cr2); + io_write32(base + I2C_OAR2, cfg->oar2); + io_write32(base + I2C_CR1, cfg->cr1 & ~I2C_CR1_PE); + io_setbits32(base + I2C_CR1, cfg->cr1 & I2C_CR1_PE); + + clk_disable(hi2c->clock); +} + +static void __maybe_unused dump_cfg(struct i2c_cfg *cfg __maybe_unused) +{ + DMSG("CR1: %#"PRIx32, cfg->cr1); + DMSG("CR2: %#"PRIx32, cfg->cr2); + DMSG("OAR1: %#"PRIx32, cfg->oar1); + DMSG("OAR2: %#"PRIx32, cfg->oar2); + DMSG("TIM: %#"PRIx32, cfg->timingr); +} + +static void __maybe_unused dump_i2c(struct i2c_handle_s *hi2c) +{ + vaddr_t __maybe_unused base = get_base(hi2c); + + clk_enable(hi2c->clock); + + DMSG("CR1: %#"PRIx32, io_read32(base + I2C_CR1)); + DMSG("CR2: %#"PRIx32, io_read32(base + I2C_CR2)); + DMSG("OAR1: %#"PRIx32, io_read32(base + I2C_OAR1)); + DMSG("OAR2: %#"PRIx32, io_read32(base + I2C_OAR2)); + DMSG("TIM: %#"PRIx32, io_read32(base + I2C_TIMINGR)); + + clk_disable(hi2c->clock); +} + +/* + * Compute the I2C device timings + * + * @init: Ref to the initialization configuration structure + * @clock_src: I2C clock source frequency (Hz) + * @timing: Pointer to the final computed timing result + * Return 0 on success or a negative value + */ +static int i2c_compute_timing(struct stm32_i2c_init_s *init, + unsigned long clock_src, uint32_t *timing) +{ + const struct i2c_spec_s *specs = NULL; + uint32_t speed_freq = 0; + uint32_t i2cbus = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, speed_freq); + uint32_t i2cclk = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, clock_src); + uint32_t p_prev = I2C_TIMINGR_PRESC_MAX; + uint32_t af_delay_min = 0; + uint32_t af_delay_max = 0; + uint32_t dnf_delay = 0; + uint32_t tsync = 0; + uint32_t clk_min = 0; + uint32_t clk_max = 0; + int clk_error_prev = 0; + uint16_t p = 0; + uint16_t l = 0; + uint16_t a = 0; + uint16_t h = 0; + unsigned int sdadel_min = 0; + unsigned int sdadel_max = 0; + unsigned int scldel_min = 0; + unsigned int delay = 0; + int s = -1; + struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX] = { 0 }; + + specs = get_specs(init->bus_rate); + if (!specs) { + DMSG("I2C speed out of bound: %"PRId32"Hz", init->bus_rate); + return -1; + } + + speed_freq = specs->rate; + i2cbus = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, speed_freq); + clk_error_prev = INT_MAX; + + if (init->rise_time > specs->rise_max || + init->fall_time > specs->fall_max) { + DMSG("I2C rise{%"PRId32">%"PRId32"}/fall{%"PRId32">%"PRId32"}", + init->rise_time, specs->rise_max, + init->fall_time, specs->fall_max); + return -1; + } + + if (init->digital_filter_coef > STM32_I2C_DIGITAL_FILTER_MAX) { + DMSG("DNF out of bound %"PRId8"/%d", + init->digital_filter_coef, STM32_I2C_DIGITAL_FILTER_MAX); + return -1; + } + + /* Analog and Digital Filters */ + if (init->analog_filter) { + af_delay_min = STM32_I2C_ANALOG_FILTER_DELAY_MIN; + af_delay_max = STM32_I2C_ANALOG_FILTER_DELAY_MAX; + } + dnf_delay = init->digital_filter_coef * i2cclk; + + sdadel_min = specs->hddat_min + init->fall_time; + delay = af_delay_min - ((init->digital_filter_coef + 3) * i2cclk); + if (SUB_OVERFLOW(sdadel_min, delay, &sdadel_min)) + sdadel_min = 0; + + sdadel_max = specs->vddat_max - init->rise_time; + delay = af_delay_max - ((init->digital_filter_coef + 4) * i2cclk); + if (SUB_OVERFLOW(sdadel_max, delay, &sdadel_max)) + sdadel_max = 0; + + scldel_min = init->rise_time + specs->sudat_min; + + DMSG("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u", + sdadel_min, sdadel_max, scldel_min); + + /* Compute possible values for PRESC, SCLDEL and SDADEL */ + for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) { + for (l = 0; l < I2C_TIMINGR_SCLDEL_MAX; l++) { + uint32_t scldel = (l + 1) * (p + 1) * i2cclk; + + if (scldel < scldel_min) + continue; + + for (a = 0; a < I2C_TIMINGR_SDADEL_MAX; a++) { + uint32_t sdadel = (a * (p + 1) + 1) * i2cclk; + + if ((sdadel >= sdadel_min) && + (sdadel <= sdadel_max) && + (p != p_prev)) { + solutions[p].scldel = l; + solutions[p].sdadel = a; + solutions[p].is_saved = true; + p_prev = p; + break; + } + } + + if (p_prev == p) + break; + } + } + + if (p_prev == I2C_TIMINGR_PRESC_MAX) { + DMSG("I2C no Prescaler solution"); + return -1; + } + + tsync = af_delay_min + dnf_delay + (2 * i2cclk); + clk_max = I2C_NSEC_PER_SEC / RATE_MIN(specs->rate); + clk_min = I2C_NSEC_PER_SEC / specs->rate; + + /* + * Among prescaler possibilities discovered above figures out SCL Low + * and High Period. Provided: + * - SCL Low Period has to be higher than Low Period of the SCL Clock + * defined by I2C Specification. I2C Clock has to be lower than + * (SCL Low Period - Analog/Digital filters) / 4. + * - SCL High Period has to be lower than High Period of the SCL Clock + * defined by I2C Specification. + * - I2C Clock has to be lower than SCL High Period. + */ + for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) { + uint32_t prescaler = (p + 1) * i2cclk; + + if (!solutions[p].is_saved) + continue; + + for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) { + uint32_t tscl_l = ((l + 1) * prescaler) + tsync; + + if (tscl_l < specs->l_min || + i2cclk >= ((tscl_l - af_delay_min - dnf_delay) / 4)) + continue; + + for (h = 0; h < I2C_TIMINGR_SCLH_MAX; h++) { + uint32_t tscl_h = ((h + 1) * prescaler) + tsync; + uint32_t tscl = tscl_l + tscl_h + + init->rise_time + + init->fall_time; + + if (tscl >= clk_min && tscl <= clk_max && + tscl_h >= specs->h_min && i2cclk < tscl_h) { + int clk_error = tscl - i2cbus; + + if (clk_error < 0) + clk_error = -clk_error; + + if (clk_error < clk_error_prev) { + clk_error_prev = clk_error; + solutions[p].scll = l; + solutions[p].sclh = h; + s = p; + } + } + } + } + } + + if (s < 0) { + DMSG("I2C no solution at all"); + return -1; + } + + /* Finalize timing settings */ + *timing = I2C_SET_TIMINGR_PRESC(s) | + I2C_SET_TIMINGR_SCLDEL(solutions[s].scldel) | + I2C_SET_TIMINGR_SDADEL(solutions[s].sdadel) | + I2C_SET_TIMINGR_SCLH(solutions[s].sclh) | + I2C_SET_TIMINGR_SCLL(solutions[s].scll); + + DMSG("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%"PRIu8"/%"PRIu8, + s, solutions[s].scldel, solutions[s].sdadel); + DMSG("I2C TIMINGR (SCLH/SCLL): %"PRIu8"/%"PRIu8, + solutions[s].sclh, solutions[s].scll); + DMSG("I2C TIMINGR: 0x%"PRIx32, *timing); + + return 0; +} + +/* i2c_specs[] must be sorted by increasing rate */ +static bool __maybe_unused i2c_specs_is_consistent(void) +{ + size_t i = 0; + + COMPILE_TIME_ASSERT(ARRAY_SIZE(i2c_specs)); + + for (i = 1; i < ARRAY_SIZE(i2c_specs); i++) + if (i2c_specs[i - 1].rate >= i2c_specs[i].rate) + return false; + + return true; +} + +/* + * @brief From requested rate, get the closest I2C rate without exceeding it, + * within I2C specification values defined in @i2c_specs. + * @param rate: The requested rate. + * @retval Found rate, else the lowest value supported by platform. + */ +static uint32_t get_lower_rate(uint32_t rate) +{ + size_t i = 0; + + for (i = ARRAY_SIZE(i2c_specs); i > 0; i--) + if (rate > i2c_specs[i - 1].rate) + return i2c_specs[i - 1].rate; + + return i2c_specs[0].rate; +} + +/* + * Setup the I2C device timings + * + * @hi2c: I2C handle structure + * @init: Ref to the initialization configuration structure + * @timing: Output TIMINGR register configuration value + * @retval 0 if OK, negative value else + */ +static int i2c_setup_timing(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init, + uint32_t *timing) +{ + int rc = 0; + unsigned long clock_src = 0; + + assert(i2c_specs_is_consistent()); + + clock_src = clk_get_rate(hi2c->clock); + if (!clock_src) { + DMSG("Null I2C clock rate"); + return -1; + } + + /* + * If the timing has already been computed, and the frequency is the + * same as when it was computed, then use the saved timing. + */ + if (clock_src == hi2c->saved_frequency) { + *timing = hi2c->saved_timing; + return 0; + } + + do { + rc = i2c_compute_timing(init, clock_src, timing); + if (rc) { + DMSG("Failed to compute I2C timings"); + if (init->bus_rate > I2C_STANDARD_RATE) { + init->bus_rate = get_lower_rate(init->bus_rate); + IMSG("Downgrade I2C speed to %"PRIu32"Hz)", + init->bus_rate); + } else { + break; + } + } + } while (rc); + + if (rc) { + DMSG("Impossible to compute I2C timings"); + return rc; + } + + DMSG("I2C Freq(%"PRIu32"Hz), Clk Source(%lu)", + init->bus_rate, clock_src); + DMSG("I2C Rise(%"PRId32") and Fall(%"PRId32") Time", + init->rise_time, init->fall_time); + DMSG("I2C Analog Filter(%s), DNF(%"PRIu8")", + init->analog_filter ? "On" : "Off", init->digital_filter_coef); + + hi2c->saved_timing = *timing; + hi2c->saved_frequency = clock_src; + + return 0; +} + +/* + * Configure I2C Analog noise filter. + * @hi2c: I2C handle structure + * @analog_filter_on: True if enabling analog filter, false otherwise + * Return 0 on success or a negative value + */ +static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, + bool analog_filter_on) +{ + vaddr_t base = get_base(hi2c); + + if (hi2c->i2c_state != I2C_STATE_READY) + return -1; + + hi2c->i2c_state = I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + io_clrbits32(base + I2C_CR1, I2C_CR1_PE); + + /* Reset I2Cx ANOFF bit */ + io_clrbits32(base + I2C_CR1, I2C_CR1_ANFOFF); + + /* Set analog filter bit if filter is disabled */ + if (!analog_filter_on) + io_setbits32(base + I2C_CR1, I2C_CR1_ANFOFF); + + /* Enable the selected I2C peripheral */ + io_setbits32(base + I2C_CR1, I2C_CR1_PE); + + hi2c->i2c_state = I2C_STATE_READY; + + return 0; +} + +TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init, + struct stm32_pinctrl **pinctrl, + size_t *pinctrl_count) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const fdt32_t *cuint = NULL; + struct dt_node_info info = { .status = 0 }; + int count = 0; + + /* Default STM32 specific configs caller may need to overwrite */ + memset(init, 0, sizeof(*init)); + + fdt_fill_device_info(fdt, &info, node); + assert(info.reg != DT_INFO_INVALID_REG && + info.reg_size != DT_INFO_INVALID_REG_SIZE); + + init->dt_status = info.status; + init->pbase = info.reg; + init->reg_size = info.reg_size; + + res = clk_dt_get_by_index(fdt, node, 0, &init->clock); + if (res) + return res; + + cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); + if (cuint) + init->rise_time = fdt32_to_cpu(*cuint); + else + init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; + + cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); + if (cuint) + init->fall_time = fdt32_to_cpu(*cuint); + else + init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; + + cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); + if (cuint) { + init->bus_rate = fdt32_to_cpu(*cuint); + + if (init->bus_rate > I2C_FAST_PLUS_RATE) { + DMSG("Invalid bus speed (%"PRIu32" > %i)", + init->bus_rate, I2C_FAST_PLUS_RATE); + return TEE_ERROR_GENERIC; + } + } else { + init->bus_rate = I2C_STANDARD_RATE; + } + + count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, NULL, 0); + if (count <= 0) { + *pinctrl = NULL; + *pinctrl_count = count; + DMSG("Failed to get pinctrl: FDT errno %d", count); + return TEE_ERROR_GENERIC; + } + + if (count > 2) { + DMSG("Too many PINCTRLs found: %zd", count); + return TEE_ERROR_GENERIC; + } + + *pinctrl = calloc(count, sizeof(**pinctrl)); + if (!*pinctrl) + return TEE_ERROR_OUT_OF_MEMORY; + + *pinctrl_count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, + *pinctrl, count); + assert(*pinctrl_count == (unsigned int)count); + + return TEE_SUCCESS; +} + +int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data) +{ + int rc = 0; + uint32_t timing = 0; + vaddr_t base = 0; + uint32_t val = 0; + + hi2c->dt_status = init_data->dt_status; + hi2c->base.pa = init_data->pbase; + hi2c->reg_size = init_data->reg_size; + hi2c->clock = init_data->clock; + + rc = i2c_setup_timing(hi2c, init_data, &timing); + if (rc) + return rc; + + clk_enable(hi2c->clock); + + base = get_base(hi2c); + hi2c->i2c_state = I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + io_clrbits32(base + I2C_CR1, I2C_CR1_PE); + + /* Configure I2Cx: Frequency range */ + io_write32(base + I2C_TIMINGR, timing & TIMINGR_CLEAR_MASK); + + /* Disable Own Address1 before set the Own Address1 configuration */ + io_write32(base + I2C_OAR1, 0); + + /* Configure I2Cx: Own Address1 and ack own address1 mode */ + if (init_data->addr_mode_10b_not_7b) + io_write32(base + I2C_OAR1, + I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | + init_data->own_address1); + else + io_write32(base + I2C_OAR1, + I2C_OAR1_OA1EN | init_data->own_address1); + + /* Configure I2Cx: Addressing Master mode */ + io_write32(base + I2C_CR2, 0); + if (init_data->addr_mode_10b_not_7b) + io_setbits32(base + I2C_CR2, I2C_CR2_ADD10); + + /* + * Enable the AUTOEND by default, and enable NACK + * (should be disabled only during Slave process). + */ + io_setbits32(base + I2C_CR2, I2C_CR2_AUTOEND | I2C_CR2_NACK); + + /* Disable Own Address2 before set the Own Address2 configuration */ + io_write32(base + I2C_OAR2, 0); + + /* Configure I2Cx: Dual mode and Own Address2 */ + if (init_data->dual_address_mode) + io_write32(base + I2C_OAR2, + I2C_OAR2_OA2EN | init_data->own_address2 | + (init_data->own_address2_masks << 8)); + + /* Configure I2Cx: Generalcall and NoStretch mode */ + val = 0; + if (init_data->general_call_mode) + val |= I2C_CR1_GCEN; + if (init_data->no_stretch_mode) + val |= I2C_CR1_NOSTRETCH; + io_write32(base + I2C_CR1, val); + + /* Enable the selected I2C peripheral */ + io_setbits32(base + I2C_CR1, I2C_CR1_PE); + + hi2c->i2c_err = I2C_ERROR_NONE; + hi2c->i2c_state = I2C_STATE_READY; + + rc = i2c_config_analog_filter(hi2c, init_data->analog_filter); + if (rc) + DMSG("I2C analog filter error %d", rc); + + if (IS_ENABLED(CFG_STM32MP13)) + stm32_gpio_set_secure_cfg(hi2c->pinctrl->bank, + hi2c->pinctrl->pin, true); + + clk_disable(hi2c->clock); + + return rc; +} + +/* I2C transmit (TX) data register flush sequence */ +static void i2c_flush_txdr(struct i2c_handle_s *hi2c) +{ + vaddr_t base = get_base(hi2c); + + /* + * If a pending TXIS flag is set, + * write a dummy data in TXDR to clear it. + */ + if (io_read32(base + I2C_ISR) & I2C_ISR_TXIS) + io_write32(base + I2C_TXDR, 0); + + /* Flush TX register if not empty */ + if ((io_read32(base + I2C_ISR) & I2C_ISR_TXE) == 0) + io_setbits32(base + I2C_ISR, I2C_ISR_TXE); +} + +/* + * Wait for a single target I2C_ISR bit to reach an awaited value (0 or 1) + * + * @hi2c: I2C handle structure + * @bit_mask: Bit mask for the target single bit position to consider + * @awaited_value: Awaited value of the target bit in I2C_ISR, 0 or 1 + * @timeout_ref: Expriation timeout reference + * Return 0 on success and a non-zero value on timeout + */ +static int wait_isr_event(struct i2c_handle_s *hi2c, uint32_t bit_mask, + unsigned int awaited_value, uint64_t timeout_ref) +{ + vaddr_t isr = get_base(hi2c) + I2C_ISR; + + assert(IS_POWER_OF_TWO(bit_mask) && !(awaited_value & ~1U)); + + /* May timeout while TEE thread is suspended */ + while (!timeout_elapsed(timeout_ref)) + if (!!(io_read32(isr) & bit_mask) == awaited_value) + break; + + if (!!(io_read32(isr) & bit_mask) == awaited_value) + return 0; + + notif_i2c_timeout(hi2c); + return -1; +} + +/* Handle Acknowledge-Failed sequence detection during an I2C Communication */ +static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + vaddr_t base = get_base(hi2c); + + if ((io_read32(base + I2C_ISR) & I2C_ISR_NACKF) == 0U) + return 0; + + /* + * Wait until STOP Flag is reset. Use polling method. + * AutoEnd should be initiate after AF. + * Timeout may elpased while TEE thread is suspended. + */ + while (!timeout_elapsed(timeout_ref)) + if (io_read32(base + I2C_ISR) & I2C_ISR_STOPF) + break; + + if ((io_read32(base + I2C_ISR) & I2C_ISR_STOPF) == 0) { + notif_i2c_timeout(hi2c); + return -1; + } + + io_write32(base + I2C_ICR, I2C_ISR_NACKF); + + io_write32(base + I2C_ICR, I2C_ISR_STOPF); + + i2c_flush_txdr(hi2c); + + io_clrbits32(base + I2C_CR2, CR2_RESET_MASK); + + hi2c->i2c_err |= I2C_ERROR_ACKF; + hi2c->i2c_state = I2C_STATE_READY; + + return -1; +} + +/* Wait TXIS bit is 1 in I2C_ISR register */ +static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + while (!timeout_elapsed(timeout_ref)) { + if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_TXIS) + break; + if (i2c_ack_failed(hi2c, timeout_ref)) + return -1; + } + + if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_TXIS) + return 0; + + if (i2c_ack_failed(hi2c, timeout_ref)) + return -1; + + notif_i2c_timeout(hi2c); + return -1; +} + +/* Wait STOPF bit is 1 in I2C_ISR register */ +static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + while (!timeout_elapsed(timeout_ref)) { + if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_STOPF) + break; + + if (i2c_ack_failed(hi2c, timeout_ref)) + return -1; + } + + if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_STOPF) + return 0; + + if (i2c_ack_failed(hi2c, timeout_ref)) + return -1; + + notif_i2c_timeout(hi2c); + return -1; +} + +/* + * Load I2C_CR2 register for a I2C transfer + * + * @hi2c: I2C handle structure + * @dev_addr: Slave address to be transferred + * @size: Number of bytes to be transferred + * @i2c_mode: One of I2C_{RELOAD|AUTOEND|SOFTEND}_MODE: Enable Reload mode. + * @startstop: One of I2C_NO_STARTSTOP, I2C_GENERATE_STOP, + * I2C_GENERATE_START_{READ|WRITE} + */ +static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint32_t size, uint32_t i2c_mode, + uint32_t startstop) +{ + uint32_t clr_value = I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | + I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP | + (I2C_CR2_RD_WRN & + (startstop >> (31U - I2C_CR2_RD_WRN_OFFSET))); + uint32_t set_value = (dev_addr & I2C_CR2_SADD) | + ((size << I2C_CR2_NBYTES_OFFSET) & + I2C_CR2_NBYTES) | + i2c_mode | startstop; + + io_clrsetbits32(get_base(hi2c) + I2C_CR2, clr_value, set_value); +} + +/* + * Master sends target device address followed by internal memory + * address for a memory write request. + * Function returns 0 on success or a negative value. + */ +static int i2c_request_mem_write(struct i2c_handle_s *hi2c, + struct i2c_request *request, + uint64_t timeout_ref) +{ + vaddr_t base = get_base(hi2c); + + i2c_transfer_config(hi2c, request->dev_addr, request->mem_addr_size, + I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); + + if (i2c_wait_txis(hi2c, timeout_ref)) + return -1; + + if (request->mem_addr_size == I2C_MEMADD_SIZE_8BIT) { + /* Send memory address */ + io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU); + } else { + /* Send MSB of memory address */ + io_write8(base + I2C_TXDR, (request->mem_addr & 0xFF00U) >> 8); + + if (i2c_wait_txis(hi2c, timeout_ref)) + return -1; + + /* Send LSB of memory address */ + io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU); + } + + if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref)) + return -1; + + return 0; +} + +/* + * Master sends target device address followed by internal memory + * address to prepare a memory read request. + * Function returns 0 on success or a negative value. + */ +static int i2c_request_mem_read(struct i2c_handle_s *hi2c, + struct i2c_request *request, + uint64_t timeout_ref) +{ + vaddr_t base = get_base(hi2c); + + i2c_transfer_config(hi2c, request->dev_addr, request->mem_addr_size, + I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); + + if (i2c_wait_txis(hi2c, timeout_ref)) + return -1; + + if (request->mem_addr_size == I2C_MEMADD_SIZE_8BIT) { + /* Send memory address */ + io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU); + } else { + /* Send MSB of memory address */ + io_write8(base + I2C_TXDR, (request->mem_addr & 0xFF00U) >> 8); + + if (i2c_wait_txis(hi2c, timeout_ref)) + return -1; + + /* Send LSB of memory address */ + io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU); + } + + if (wait_isr_event(hi2c, I2C_ISR_TC, 1, timeout_ref)) + return -1; + + return 0; +} + +/* + * Write an amount of data in blocking mode + * + * @hi2c: Reference to struct i2c_handle_s + * @request: I2C request parameters + * @p_data: Pointer to data buffer + * @size: Amount of data to be sent + * Return 0 on success or a negative value + */ +static int i2c_write(struct i2c_handle_s *hi2c, struct i2c_request *request, + uint8_t *p_data, uint16_t size) +{ + uint64_t timeout_ref = 0; + vaddr_t base = get_base(hi2c); + int rc = -1; + uint8_t *p_buff = p_data; + size_t xfer_size = 0; + size_t xfer_count = size; + + if (request->mode != I2C_MODE_MASTER && request->mode != I2C_MODE_MEM) + return -1; + + if (hi2c->i2c_state != I2C_STATE_READY) + return -1; + + if (!p_data || !size) + return -1; + + clk_enable(hi2c->clock); + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); + if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref)) + goto bail; + + hi2c->i2c_state = I2C_STATE_BUSY_TX; + hi2c->i2c_err = I2C_ERROR_NONE; + timeout_ref = timeout_init_us(request->timeout_ms * 1000); + + if (request->mode == I2C_MODE_MEM) { + /* In memory mode, send slave address and memory address */ + if (i2c_request_mem_write(hi2c, request, timeout_ref)) + goto bail; + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, request->dev_addr, xfer_size, + I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, request->dev_addr, xfer_size, + I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } else { + /* In master mode, send slave address */ + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, request->dev_addr, xfer_size, + I2C_RELOAD_MODE, + I2C_GENERATE_START_WRITE); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, request->dev_addr, xfer_size, + I2C_AUTOEND_MODE, + I2C_GENERATE_START_WRITE); + } + } + + do { + if (i2c_wait_txis(hi2c, timeout_ref)) + goto bail; + + io_write8(base + I2C_TXDR, *p_buff); + p_buff++; + xfer_count--; + xfer_size--; + + if (xfer_count && !xfer_size) { + /* Wait until TCR flag is set */ + if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref)) + goto bail; + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, request->dev_addr, + xfer_size, + I2C_RELOAD_MODE, + I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, request->dev_addr, + xfer_size, + I2C_AUTOEND_MODE, + I2C_NO_STARTSTOP); + } + } + + } while (xfer_count > 0U); + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is reset. + */ + if (i2c_wait_stop(hi2c, timeout_ref)) + goto bail; + + io_write32(base + I2C_ICR, I2C_ISR_STOPF); + + io_clrbits32(base + I2C_CR2, CR2_RESET_MASK); + + hi2c->i2c_state = I2C_STATE_READY; + + rc = 0; + +bail: + clk_disable(hi2c->clock); + + return rc; +} + +int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint32_t mem_addr, uint32_t mem_addr_size, + uint8_t *p_data, size_t size, unsigned int timeout_ms) +{ + struct i2c_request request = { + .dev_addr = dev_addr, + .mode = I2C_MODE_MEM, + .mem_addr = mem_addr, + .mem_addr_size = mem_addr_size, + .timeout_ms = timeout_ms, + }; + + return i2c_write(hi2c, &request, p_data, size); +} + +int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint8_t *p_data, size_t size, + unsigned int timeout_ms) +{ + struct i2c_request request = { + .dev_addr = dev_addr, + .mode = I2C_MODE_MASTER, + .timeout_ms = timeout_ms, + }; + + return i2c_write(hi2c, &request, p_data, size); +} + +int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr, + unsigned int mem_addr, uint8_t *p_data, + bool write) +{ + uint64_t timeout_ref = 0; + uintptr_t base = get_base(hi2c); + int rc = -1; + uint8_t *p_buff = p_data; + uint32_t event_mask = 0; + + if (hi2c->i2c_state != I2C_STATE_READY || !p_data) + return -1; + + clk_enable(hi2c->clock); + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); + if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref)) + goto bail; + + hi2c->i2c_state = write ? I2C_STATE_BUSY_TX : I2C_STATE_BUSY_RX; + hi2c->i2c_err = I2C_ERROR_NONE; + + i2c_transfer_config(hi2c, dev_addr, I2C_MEMADD_SIZE_8BIT, + write ? I2C_RELOAD_MODE : I2C_SOFTEND_MODE, + I2C_GENERATE_START_WRITE); + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); + if (i2c_wait_txis(hi2c, timeout_ref)) + goto bail; + + io_write8(base + I2C_TXDR, mem_addr); + + if (write) + event_mask = I2C_ISR_TCR; + else + event_mask = I2C_ISR_TC; + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); + if (wait_isr_event(hi2c, event_mask, 1, timeout_ref)) + goto bail; + + i2c_transfer_config(hi2c, dev_addr, I2C_MEMADD_SIZE_8BIT, + I2C_AUTOEND_MODE, + write ? I2C_NO_STARTSTOP : I2C_GENERATE_START_READ); + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); + if (write) { + if (i2c_wait_txis(hi2c, timeout_ref)) + goto bail; + + io_write8(base + I2C_TXDR, *p_buff); + } else { + if (wait_isr_event(hi2c, I2C_ISR_RXNE, 1, timeout_ref)) + goto bail; + + *p_buff = io_read8(base + I2C_RXDR); + } + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); + if (i2c_wait_stop(hi2c, timeout_ref)) + goto bail; + + io_write32(base + I2C_ICR, I2C_ISR_STOPF); + io_clrbits32(base + I2C_CR2, CR2_RESET_MASK); + + hi2c->i2c_state = I2C_STATE_READY; + + rc = 0; + +bail: + clk_disable(hi2c->clock); + + return rc; +} + +/* + * Read an amount of data in blocking mode + * + * @hi2c: Reference to struct i2c_handle_s + * @request: I2C request parameters + * @p_data: Pointer to data buffer + * @size: Amount of data to be sent + * Return 0 on success or a negative value + */ +static int i2c_read(struct i2c_handle_s *hi2c, struct i2c_request *request, + uint8_t *p_data, uint32_t size) +{ + vaddr_t base = get_base(hi2c); + uint64_t timeout_ref = 0; + int rc = -1; + uint8_t *p_buff = p_data; + size_t xfer_count = size; + size_t xfer_size = 0; + + if (request->mode != I2C_MODE_MASTER && request->mode != I2C_MODE_MEM) + return -1; + + if (hi2c->i2c_state != I2C_STATE_READY) + return -1; + + if (!p_data || !size) + return -1; + + clk_enable(hi2c->clock); + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); + if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref)) + goto bail; + + hi2c->i2c_state = I2C_STATE_BUSY_RX; + hi2c->i2c_err = I2C_ERROR_NONE; + timeout_ref = timeout_init_us(request->timeout_ms * 1000); + + if (request->mode == I2C_MODE_MEM) { + /* Send memory address */ + if (i2c_request_mem_read(hi2c, request, timeout_ref)) + goto bail; + } + + /* + * Send slave address. + * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE + * and generate RESTART. + */ + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, request->dev_addr, xfer_size, + I2C_RELOAD_MODE, I2C_GENERATE_START_READ); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, request->dev_addr, xfer_size, + I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + } + + do { + if (wait_isr_event(hi2c, I2C_ISR_RXNE, 1, + timeout_init_us(I2C_TIMEOUT_RXNE_MS * 1000))) + goto bail; + + *p_buff = io_read8(base + I2C_RXDR); + p_buff++; + xfer_size--; + xfer_count--; + + if (xfer_count && !xfer_size) { + if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref)) + goto bail; + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, request->dev_addr, + xfer_size, + I2C_RELOAD_MODE, + I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, request->dev_addr, + xfer_size, + I2C_AUTOEND_MODE, + I2C_NO_STARTSTOP); + } + } + } while (xfer_count > 0U); + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is reset. + */ + if (i2c_wait_stop(hi2c, timeout_ref)) + goto bail; + + /* Clear the NACK generated at the end of the transfer */ + if ((io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_NACKF)) + io_write32(get_base(hi2c) + I2C_ICR, I2C_ICR_NACKCF); + + io_write32(base + I2C_ICR, I2C_ISR_STOPF); + + io_clrbits32(base + I2C_CR2, CR2_RESET_MASK); + + hi2c->i2c_state = I2C_STATE_READY; + + rc = 0; + +bail: + clk_disable(hi2c->clock); + + return rc; +} + +int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint32_t mem_addr, uint32_t mem_addr_size, + uint8_t *p_data, size_t size, unsigned int timeout_ms) +{ + struct i2c_request request = { + .dev_addr = dev_addr, + .mode = I2C_MODE_MEM, + .mem_addr = mem_addr, + .mem_addr_size = mem_addr_size, + .timeout_ms = timeout_ms, + }; + + return i2c_read(hi2c, &request, p_data, size); +} + +int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint8_t *p_data, size_t size, + unsigned int timeout_ms) +{ + struct i2c_request request = { + .dev_addr = dev_addr, + .mode = I2C_MODE_MASTER, + .timeout_ms = timeout_ms, + }; + + return i2c_read(hi2c, &request, p_data, size); +} + +bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint32_t dev_addr, + unsigned int trials, unsigned int timeout_ms) +{ + vaddr_t base = get_base(hi2c); + unsigned int i2c_trials = 0U; + bool rc = false; + + if (hi2c->i2c_state != I2C_STATE_READY) + return rc; + + clk_enable(hi2c->clock); + + if (io_read32(base + I2C_ISR) & I2C_ISR_BUSY) + goto bail; + + hi2c->i2c_state = I2C_STATE_BUSY; + hi2c->i2c_err = I2C_ERROR_NONE; + + do { + uint64_t timeout_ref = 0; + vaddr_t isr = base + I2C_ISR; + + /* Generate Start */ + if ((io_read32(base + I2C_OAR1) & I2C_OAR1_OA1MODE) == 0) + io_write32(base + I2C_CR2, + ((dev_addr & I2C_CR2_SADD) | + I2C_CR2_START | I2C_CR2_AUTOEND) & + ~I2C_CR2_RD_WRN); + else + io_write32(base + I2C_CR2, + ((dev_addr & I2C_CR2_SADD) | + I2C_CR2_START | I2C_CR2_ADD10) & + ~I2C_CR2_RD_WRN); + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is set or a NACK flag is set. + */ + timeout_ref = timeout_init_us(timeout_ms * 1000); + while (!timeout_elapsed(timeout_ref)) + if (io_read32(isr) & (I2C_ISR_STOPF | I2C_ISR_NACKF)) + break; + + if ((io_read32(isr) & (I2C_ISR_STOPF | I2C_ISR_NACKF)) == 0) { + notif_i2c_timeout(hi2c); + goto bail; + } + + if ((io_read32(base + I2C_ISR) & I2C_ISR_NACKF) == 0U) { + if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref)) + goto bail; + + io_write32(base + I2C_ICR, I2C_ISR_STOPF); + + hi2c->i2c_state = I2C_STATE_READY; + + rc = true; + goto bail; + } + + if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref)) + goto bail; + + io_write32(base + I2C_ICR, I2C_ISR_NACKF); + io_write32(base + I2C_ICR, I2C_ISR_STOPF); + + if (i2c_trials == trials) { + io_setbits32(base + I2C_CR2, I2C_CR2_STOP); + + if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref)) + goto bail; + + io_write32(base + I2C_ICR, I2C_ISR_STOPF); + } + + i2c_trials++; + } while (i2c_trials < trials); + + notif_i2c_timeout(hi2c); + +bail: + clk_disable(hi2c->clock); + + return rc; +} + +void stm32_i2c_resume(struct i2c_handle_s *hi2c) +{ + if (hi2c->i2c_state == I2C_STATE_READY) + return; + + if ((hi2c->i2c_state != I2C_STATE_RESET) && + (hi2c->i2c_state != I2C_STATE_SUSPENDED)) + panic(); + + stm32_pinctrl_load_active_cfg(hi2c->pinctrl, hi2c->pinctrl_count); + + if (hi2c->i2c_state == I2C_STATE_RESET) { + /* There is no valid I2C configuration to be loaded yet */ + return; + } + + restore_cfg(hi2c, &hi2c->sec_cfg); + + if (IS_ENABLED(CFG_STM32MP13)) + stm32_gpio_set_secure_cfg(hi2c->pinctrl->bank, + hi2c->pinctrl->pin, true); + + hi2c->i2c_state = I2C_STATE_READY; +} + +void stm32_i2c_suspend(struct i2c_handle_s *hi2c) +{ + if (hi2c->i2c_state == I2C_STATE_SUSPENDED) + return; + + if (hi2c->i2c_state != I2C_STATE_READY) + panic(); + + save_cfg(hi2c, &hi2c->sec_cfg); + stm32_pinctrl_load_standby_cfg(hi2c->pinctrl, hi2c->pinctrl_count); + + hi2c->i2c_state = I2C_STATE_SUSPENDED; +} diff --git a/optee/optee_os/core/drivers/stm32_iwdg.c b/optee/optee_os/core/drivers/stm32_iwdg.c new file mode 100644 index 0000000..fd2899f --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_iwdg.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* IWDG Compatibility */ +#define IWDG_TIMEOUT_US U(1000) +#define IWDG_CNT_MASK GENMASK_32(11, 0) + +/* IWDG registers offsets */ +#define IWDG_KR_OFFSET U(0x00) +#define IWDG_PR_OFFSET U(0x04) +#define IWDG_RLR_OFFSET U(0x08) +#define IWDG_SR_OFFSET U(0x0C) +#define IWDG_EWCR_OFFSET U(0x14) + +#define IWDG_KR_ACCESS_KEY U(0x5555) +#define IWDG_KR_RELOAD_KEY U(0xAAAA) +#define IWDG_KR_START_KEY U(0xCCCC) + +/* Use a fixed prescaler divider of 256 */ +#define IWDG_PRESCALER_256 U(256) +#define IWDG_PR_DIV_256 U(0x06) +#define IWDG_PR_DIV_MASK GENMASK_32(3, 0) + +#define IWDG_SR_PVU BIT(0) +#define IWDG_SR_RVU BIT(1) +#define IWDG_SR_WVU BIT(2) +#define IWDG_SR_EWU BIT(3) +#define IWDG_SR_UPDATE_MASK (IWDG_SR_PVU | IWDG_SR_RVU | IWDG_SR_WVU | \ + IWDG_SR_EWU) + +#define IWDG_EWCR_EWIE BIT(15) +#define IWDG_EWCR_EWIC BIT(14) + +/* + * Values for struct stm32_iwdg_device::flags + * IWDG_FLAGS_HW_ENABLED Watchdog is enabled by BootROM + * IWDG_FLAGS_DISABLE_ON_STOP Watchdog is freezed in SoC STOP mode + * IWDG_FLAGS_DISABLE_ON_STANDBY Watchdog is freezed in SoC STANDBY mode + * IWDG_FLAGS_NON_SECURE Instance is assigned to non-secure world + * IWDG_FLAGS_ENABLED Watchdog has been enabled + */ +#define IWDG_FLAGS_HW_ENABLED BIT(0) +#define IWDG_FLAGS_DISABLE_ON_STOP BIT(1) +#define IWDG_FLAGS_DISABLE_ON_STANDBY BIT(2) +#define IWDG_FLAGS_NON_SECURE BIT(3) +#define IWDG_FLAGS_ENABLED BIT(4) + +/* + * IWDG watch instance data + * @base - IWDG interface IOMEM base address + * @clock - Bus clock + * @clk_lsi - IWDG source clock + * @flags - Property flags for the IWDG instance + * @timeout - Watchdog elaspure timeout + * @wdt_chip - Wathcdog chip instance + * @link - Link in registered watchdog instance list + */ +struct stm32_iwdg_device { + struct io_pa_va base; + struct clk *clock; + struct clk *clk_lsi; + uint32_t flags; + unsigned long timeout; + struct wdt_chip wdt_chip; + SLIST_ENTRY(stm32_iwdg_device) link; +}; + +static unsigned int iwdg_lock = SPINLOCK_UNLOCK; + +static SLIST_HEAD(iwdg_dev_list_head, stm32_iwdg_device) iwdg_dev_list = + SLIST_HEAD_INITIALIZER(iwdg_dev_list_head); + +static vaddr_t get_base(struct stm32_iwdg_device *iwdg) +{ + return io_pa_or_va(&iwdg->base, 1); +} + +static bool is_assigned_to_nsec(struct stm32_iwdg_device *iwdg) +{ + return iwdg->flags & IWDG_FLAGS_NON_SECURE; +} + +static bool is_enable(struct stm32_iwdg_device *iwdg) +{ + return iwdg->flags & IWDG_FLAGS_ENABLED; +} + +/* Return counter value to related to input timeout in seconds, or 0 on error */ +static uint32_t iwdg_timeout_cnt(struct stm32_iwdg_device *iwdg, + unsigned long to_sec) +{ + uint64_t reload = (uint64_t)to_sec * clk_get_rate(iwdg->clk_lsi); + uint64_t cnt = (reload / IWDG_PRESCALER_256) - 1; + + /* Be safe and expect any counter to be above 2 */ + if (cnt > IWDG_CNT_MASK || cnt < 3) + return 0; + + return cnt; +} + +/* Wait IWDG programming completes */ +static TEE_Result iwdg_wait_sync(struct stm32_iwdg_device *iwdg) +{ + uint64_t timeout_ref = timeout_init_us(IWDG_TIMEOUT_US); + vaddr_t iwdg_base = get_base(iwdg); + + while (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK) + if (timeout_elapsed(timeout_ref)) + break; + + if (!(io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg) +{ + TEE_Result res = TEE_ERROR_GENERIC; + vaddr_t iwdg_base = get_base(iwdg); + uint32_t rlr_value = 0; + + assert(is_enable(iwdg)); + + rlr_value = iwdg_timeout_cnt(iwdg, iwdg->timeout); + if (!rlr_value) + return TEE_ERROR_GENERIC; + + clk_enable(iwdg->clock); + + io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY); + io_write32(iwdg_base + IWDG_PR_OFFSET, IWDG_PR_DIV_256); + io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value); + io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); + + res = iwdg_wait_sync(iwdg); + + clk_disable(iwdg->clock); + + return res; +} + +static void iwdg_start(struct stm32_iwdg_device *iwdg) +{ + clk_enable(iwdg->clock); + io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_START_KEY); + clk_disable(iwdg->clock); + + iwdg->flags |= IWDG_FLAGS_ENABLED; +} + +static void iwdg_refresh(struct stm32_iwdg_device *iwdg) +{ + clk_enable(iwdg->clock); + io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); + clk_disable(iwdg->clock); +} + +/* Operators for watchdog OP-TEE interface */ +static struct stm32_iwdg_device *wdt_chip_to_iwdg(struct wdt_chip *chip) +{ + return container_of(chip, struct stm32_iwdg_device, wdt_chip); +} + +static void iwdg_wdt_start(struct wdt_chip *chip) +{ + struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); + + iwdg_start(iwdg); + + if (configure_timeout(iwdg)) + panic(); +} + +static void iwdg_wdt_refresh(struct wdt_chip *chip) +{ + struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); + + iwdg_refresh(iwdg); +} + +static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip, + unsigned long timeout) +{ + struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); + + if (!iwdg_timeout_cnt(iwdg, timeout)) + return TEE_ERROR_BAD_PARAMETERS; + + iwdg->timeout = timeout; + + if (is_enable(iwdg)) { + TEE_Result res = TEE_ERROR_GENERIC; + + res = configure_timeout(iwdg); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +static const struct wdt_ops stm32_iwdg_ops = { + .start = iwdg_wdt_start, + .ping = iwdg_wdt_refresh, + .set_timeout = iwdg_wdt_set_timeout, +}; +DECLARE_KEEP_PAGER(stm32_iwdg_ops); + +/* Refresh all registered watchdogs */ +void stm32_iwdg_refresh(void) +{ + struct stm32_iwdg_device *iwdg = NULL; + uint32_t exceptions = cpu_spin_lock_xsave(&iwdg_lock); + + SLIST_FOREACH(iwdg, &iwdg_dev_list, link) + iwdg_refresh(iwdg); + + cpu_spin_unlock_xrestore(&iwdg_lock, exceptions); +} + +/* Driver initialization */ +static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg, + const void *fdt, int node) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct dt_node_info dt_info = { }; + const fdt32_t *cuint = NULL; + + fdt_fill_device_info(fdt, &dt_info, node); + + if (dt_info.reg == DT_INFO_INVALID_REG || + dt_info.reg_size == DT_INFO_INVALID_REG_SIZE) + panic(); + + res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clock); + if (res) + return res; + + res = clk_dt_get_by_name(fdt, node, "lsi", &iwdg->clk_lsi); + if (res) + return res; + + if (dt_info.status == DT_STATUS_OK_NSEC) + iwdg->flags |= IWDG_FLAGS_NON_SECURE; + + /* Get IOMEM address */ + iwdg->base.pa = dt_info.reg; + + if (iwdg->flags & IWDG_FLAGS_NON_SECURE) + io_pa_or_va_nsec(&iwdg->base, dt_info.reg_size); + else + io_pa_or_va_secure(&iwdg->base, dt_info.reg_size); + + assert(iwdg->base.va); + + /* Get and check timeout value */ + cuint = fdt_getprop(fdt, node, "timeout-sec", NULL); + if (!cuint) + return TEE_ERROR_BAD_PARAMETERS; + + iwdg->timeout = (int)fdt32_to_cpu(*cuint); + if (!iwdg->timeout) + return TEE_ERROR_BAD_PARAMETERS; + + if (!iwdg_timeout_cnt(iwdg, iwdg->timeout)) { + EMSG("Timeout %lu not applicable", iwdg->timeout); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* DT can specify low power cases */ + if (!fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL)) + iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STOP; + + if (!fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL)) + iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY; + + return TEE_SUCCESS; +} + +/* Platform should override this function to provide IWDG fuses configuration */ +TEE_Result __weak stm32_get_iwdg_otp_config(paddr_t pbase __unused, + struct stm32_iwdg_otp_data *otp_d) +{ + otp_d->hw_enabled = false; + otp_d->disable_on_stop = false; + otp_d->disable_on_standby = false; + + return TEE_SUCCESS; +} + +static TEE_Result stm32_iwdg_setup(struct stm32_iwdg_device *iwdg, + const void *fdt, int node) +{ + struct stm32_iwdg_otp_data otp_data = { }; + TEE_Result res = TEE_SUCCESS; + + res = stm32_iwdg_parse_fdt(iwdg, fdt, node); + if (res) + return res; + + res = stm32_get_iwdg_otp_config(iwdg->base.pa, &otp_data); + if (res) + return res; + + if (otp_data.hw_enabled) + iwdg->flags |= IWDG_FLAGS_HW_ENABLED; + if (otp_data.disable_on_stop) + iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STOP; + if (otp_data.disable_on_standby) + iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY; + + /* Enable watchdog source clock once for all */ + clk_enable(iwdg->clk_lsi); + + if (otp_data.hw_enabled) { + iwdg->flags |= IWDG_FLAGS_ENABLED; + + /* Configure timeout if watchdog is already enabled */ + res = configure_timeout(iwdg); + if (res) + return res; + + iwdg_refresh(iwdg); + } + + return TEE_SUCCESS; +} + +static TEE_Result stm32_iwdg_register(struct stm32_iwdg_device *iwdg) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (is_assigned_to_nsec(iwdg)) { + stm32mp_register_non_secure_periph_iomem(iwdg->base.pa); + } else { + stm32mp_register_secure_periph_iomem(iwdg->base.pa); + + /* Expose watchdog runtime service only to secure IWDG */ + iwdg->wdt_chip.ops = &stm32_iwdg_ops; + + res = watchdog_register(&iwdg->wdt_chip); + if (res) + return res; + } + + SLIST_INSERT_HEAD(&iwdg_dev_list, iwdg, link); + + return TEE_SUCCESS; +} + +static TEE_Result stm32_iwdg_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + struct stm32_iwdg_device *iwdg = NULL; + TEE_Result res = TEE_SUCCESS; + + iwdg = calloc(1, sizeof(*iwdg)); + if (!iwdg) + return TEE_ERROR_OUT_OF_MEMORY; + + res = stm32_iwdg_setup(iwdg, fdt, node); + if (res) + goto err; + + res = stm32_iwdg_register(iwdg); + if (res) + goto err; + + return TEE_SUCCESS; + +err: + free(iwdg); + return res; +} + +static const struct dt_device_match stm32_iwdg_match_table[] = { + { .compatible = "st,stm32mp1-iwdg" }, + { } +}; + +DEFINE_DT_DRIVER(stm32_iwdg_dt_driver) = { + .name = "stm32-iwdg", + .match_table = stm32_iwdg_match_table, + .probe = stm32_iwdg_probe, +}; diff --git a/optee/optee_os/core/drivers/stm32_rng.c b/optee/optee_os/core/drivers/stm32_rng.c new file mode 100644 index 0000000..0dfdb9b --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_rng.c @@ -0,0 +1,549 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2018-2023, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RNG_CR U(0x00) +#define RNG_SR U(0x04) +#define RNG_DR U(0x08) + +#define RNG_CR_RNGEN BIT(2) +#define RNG_CR_IE BIT(3) +#define RNG_CR_CED BIT(5) +#define RNG_CR_CLKDIV GENMASK_32(19, 16) +#define RNG_CR_CLKDIV_SHIFT U(16) +#define RNG_CR_CONDRST BIT(30) + +#define RNG_SR_DRDY BIT(0) +#define RNG_SR_CECS BIT(1) +#define RNG_SR_SECS BIT(2) +#define RNG_SR_CEIS BIT(5) +#define RNG_SR_SEIS BIT(6) + +#if TRACE_LEVEL > TRACE_DEBUG +#define RNG_READY_TIMEOUT_US U(100000) +#else +#define RNG_READY_TIMEOUT_US U(10000) +#endif +#define RNG_RESET_TIMEOUT_US U(1000) + +#define RNG_FIFO_BYTE_DEPTH U(16) + +#define RNG_NIST_CONFIG_A U(0x0F00D00) +#define RNG_NIST_CONFIG_B U(0x1801000) +#define RNG_NIST_CONFIG_MASK GENMASK_32(25, 8) + +#define RNG_MAX_NOISE_CLK_FREQ U(3000000) + +struct stm32_rng_driver_data { + bool has_cond_reset; +}; + +struct stm32_rng_instance { + struct io_pa_va base; + struct clk *clock; + struct rstctrl *rstctrl; + const struct stm32_rng_driver_data *ddata; + unsigned int lock; + bool release_post_boot; + bool clock_error; + bool error_conceal; + uint64_t error_to_ref; +}; + +/* Expect at most a single RNG instance */ +static struct stm32_rng_instance *stm32_rng; + +static vaddr_t get_base(void) +{ + assert(stm32_rng); + + return io_pa_or_va(&stm32_rng->base, 1); +} + +/* + * Extracts from the STM32 RNG specification when RNG supports CONDRST. + * + * When a noise source (or seed) error occurs, the RNG stops generating + * random numbers and sets to “1†both SEIS and SECS bits to indicate + * that a seed error occurred. (...) + * + * 1. Software reset by writing CONDRST at 1 and at 0 (see bitfield + * description for details). This step is needed only if SECS is set. + * Indeed, when SEIS is set and SECS is cleared it means RNG performed + * the reset automatically (auto-reset). + * 2. If SECS was set in step 1 (no auto-reset) wait for CONDRST + * to be cleared in the RNG_CR register, then confirm that SEIS is + * cleared in the RNG_SR register. Otherwise just clear SEIS bit in + * the RNG_SR register. + * 3. If SECS was set in step 1 (no auto-reset) wait for SECS to be + * cleared by RNG. The random number generation is now back to normal. + */ +static void conceal_seed_error_cond_reset(void) +{ + struct stm32_rng_instance *dev = stm32_rng; + vaddr_t rng_base = get_base(); + + if (!dev->error_conceal) { + uint32_t sr = io_read32(rng_base + RNG_SR); + + if (sr & RNG_SR_SECS) { + /* Conceal by resetting the subsystem (step 1.) */ + io_setbits32(rng_base + RNG_CR, RNG_CR_CONDRST); + io_clrbits32(rng_base + RNG_CR, RNG_CR_CONDRST); + + /* Arm timeout for error_conceal sequence */ + dev->error_to_ref = + timeout_init_us(RNG_READY_TIMEOUT_US); + dev->error_conceal = true; + } else { + /* RNG auto-reset (step 2.) */ + io_clrbits32(rng_base + RNG_SR, RNG_SR_SEIS); + } + } else { + /* Measure time before possible reschedule */ + bool timed_out = timeout_elapsed(dev->error_to_ref); + + /* Wait CONDRST is cleared (step 2.) */ + if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) { + if (timed_out) + panic(); + + /* Wait subsystem reset cycle completes */ + return; + } + + /* Check SEIS is cleared (step 2.) */ + if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) + panic(); + + /* Wait SECS is cleared (step 3.) */ + if (io_read32(rng_base + RNG_SR) & RNG_SR_SECS) { + if (timed_out) + panic(); + + /* Wait subsystem reset cycle completes */ + return; + } + + dev->error_conceal = false; + } +} + +/* + * Extracts from the STM32 RNG specification, when CONDRST is not supported + * + * When a noise source (or seed) error occurs, the RNG stops generating + * random numbers and sets to “1†both SEIS and SECS bits to indicate + * that a seed error occurred. (...) + * + * The following sequence shall be used to fully recover from a seed + * error after the RNG initialization: + * 1. Clear the SEIS bit by writing it to “0â€. + * 2. Read out 12 words from the RNG_DR register, and discard each of + * them in order to clean the pipeline. + * 3. Confirm that SEIS is still cleared. Random number generation is + * back to normal. + */ +static void conceal_seed_error_sw_reset(void) +{ + vaddr_t rng_base = get_base(); + size_t i = 0; + + io_clrbits32(rng_base + RNG_SR, RNG_SR_SEIS); + + for (i = 12; i != 0; i--) + (void)io_read32(rng_base + RNG_DR); + + if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) + panic("RNG noise"); +} + +static void conceal_seed_error(void) +{ + if (stm32_rng->ddata->has_cond_reset) + conceal_seed_error_cond_reset(); + else + conceal_seed_error_sw_reset(); +} + +static TEE_Result read_available(vaddr_t rng_base, uint8_t *out, size_t *size) +{ + struct stm32_rng_instance *dev = stm32_rng; + uint8_t *buf = NULL; + size_t req_size = 0; + size_t len = 0; + + if (dev->error_conceal || io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) + conceal_seed_error(); + + if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) { + FMSG("RNG not ready"); + return TEE_ERROR_NO_DATA; + } + + if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) { + FMSG("RNG noise error"); + return TEE_ERROR_NO_DATA; + } + + buf = out; + req_size = MIN(RNG_FIFO_BYTE_DEPTH, *size); + len = req_size; + + /* RNG is ready: read up to 4 32bit words */ + while (len) { + uint32_t data32 = io_read32(rng_base + RNG_DR); + size_t sz = MIN(len, sizeof(uint32_t)); + + /* Late seed error case: DR being 0 is an error status */ + if (!data32) { + conceal_seed_error(); + return TEE_ERROR_NO_DATA; + } + + memcpy(buf, &data32, sz); + buf += sz; + len -= sz; + } + + *size = req_size; + + return TEE_SUCCESS; +} + +static uint32_t stm32_rng_clock_freq_restrain(void) +{ + struct stm32_rng_instance *dev = stm32_rng; + unsigned long clock_rate = 0; + uint32_t clock_div = 0; + + clock_rate = clk_get_rate(dev->clock); + + /* + * Get the exponent to apply on the CLKDIV field in RNG_CR register + * No need to handle the case when clock-div > 0xF as it is physically + * impossible + */ + while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ) + clock_div++; + + DMSG("RNG clk rate : %lu", clk_get_rate(dev->clock) >> clock_div); + + return clock_div; +} + +static TEE_Result init_rng(void) +{ + vaddr_t rng_base = get_base(); + uint64_t timeout_ref = 0; + uint32_t cr_ced_mask = 0; + + if (!stm32_rng->clock_error) + cr_ced_mask = RNG_CR_CED; + + /* Clean error indications */ + io_write32(rng_base + RNG_SR, 0); + + if (stm32_rng->ddata->has_cond_reset) { + uint32_t clock_div = stm32_rng_clock_freq_restrain(); + + /* Update configuration fields */ + io_clrsetbits32(rng_base + RNG_CR, RNG_NIST_CONFIG_MASK, + RNG_NIST_CONFIG_B | RNG_CR_CONDRST | + cr_ced_mask); + io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CLKDIV, + clock_div << RNG_CR_CLKDIV_SHIFT); + + /* No need to wait for RNG_CR_CONDRST toggle as we enable clk */ + io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CONDRST, + RNG_CR_RNGEN); + } else { + io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | cr_ced_mask); + } + + timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); + while (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) + if (timeout_elapsed(timeout_ref)) + break; + + if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rng_read(uint8_t *out, size_t size) +{ + TEE_Result rc = TEE_ERROR_GENERIC; + bool burst_timeout = false; + uint64_t timeout_ref = 0; + uint32_t exceptions = 0; + uint8_t *out_ptr = out; + vaddr_t rng_base = 0; + size_t out_size = 0; + + if (!stm32_rng) { + DMSG("No RNG"); + return TEE_ERROR_NOT_SUPPORTED; + } + + clk_enable(stm32_rng->clock); + rng_base = get_base(); + + /* Arm timeout */ + timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); + burst_timeout = false; + + while (out_size < size) { + /* Read by chunks of the size the RNG FIFO depth */ + size_t sz = size - out_size; + + exceptions = may_spin_lock(&stm32_rng->lock); + + rc = read_available(rng_base, out_ptr, &sz); + + /* Raise timeout only if we failed to get some samples */ + assert(!rc || rc == TEE_ERROR_NO_DATA); + if (rc) + burst_timeout = timeout_elapsed(timeout_ref); + + may_spin_unlock(&stm32_rng->lock, exceptions); + + if (burst_timeout) { + rc = TEE_ERROR_GENERIC; + goto out; + } + + if (!rc) { + out_size += sz; + out_ptr += sz; + /* Re-arm timeout */ + timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); + burst_timeout = false; + } + } + +out: + assert(!rc || rc == TEE_ERROR_GENERIC); + clk_disable(stm32_rng->clock); + + return rc; +} + +#ifdef CFG_WITH_SOFTWARE_PRNG +/* Override weak plat_rng_init with platform handler to seed PRNG */ +void plat_rng_init(void) +{ + uint8_t seed[RNG_FIFO_BYTE_DEPTH] = { }; + + if (stm32_rng_read(seed, sizeof(seed))) + panic(); + + if (crypto_rng_init(seed, sizeof(seed))) + panic(); + + DMSG("PRNG seeded with RNG"); +} +#else +TEE_Result hw_get_random_bytes(void *out, size_t size) +{ + return stm32_rng_read(out, size); +} + +void plat_rng_init(void) +{ +} +#endif + +static TEE_Result stm32_rng_pm_resume(uint32_t pm_cr) +{ + vaddr_t base = get_base(); + + /* Clean error indications */ + io_write32(base + RNG_SR, 0); + + if (stm32_rng->ddata->has_cond_reset) { + /* + * Correct configuration in bits [29:4] must be set in the same + * access that set RNG_CR_CONDRST bit. Else config setting is + * not taken into account. + */ + io_write32(base + RNG_CR, pm_cr | RNG_CR_CONDRST); + + io_clrsetbits32(base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN); + } else { + io_write32(base + RNG_CR, RNG_CR_RNGEN | pm_cr); + } + + return TEE_SUCCESS; +} + +static TEE_Result +stm32_rng_pm(enum pm_op op, unsigned int pm_hint __unused, + const struct pm_callback_handle *pm_handle __unused) +{ + static uint32_t pm_cr; + TEE_Result res = TEE_ERROR_GENERIC; + + assert(stm32_rng && (op == PM_OP_SUSPEND || op == PM_OP_RESUME)); + + res = clk_enable(stm32_rng->clock); + if (res) + return res; + + if (op == PM_OP_SUSPEND) + pm_cr = io_read32(get_base() + RNG_CR); + else + res = stm32_rng_pm_resume(pm_cr); + + clk_disable(stm32_rng->clock); + + return res; +} +DECLARE_KEEP_PAGER(stm32_rng_pm); + +static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct dt_node_info dt_rng = { }; + + fdt_fill_device_info(fdt, &dt_rng, node); + if (dt_rng.reg == DT_INFO_INVALID_REG) + return TEE_ERROR_BAD_PARAMETERS; + + stm32_rng->base.pa = dt_rng.reg; + stm32_rng->base.va = io_pa_or_va_secure(&stm32_rng->base, + dt_rng.reg_size); + assert(stm32_rng->base.va); + + res = rstctrl_dt_get_by_index(fdt, node, 0, &stm32_rng->rstctrl); + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) + return res; + + res = clk_dt_get_by_index(fdt, node, 0, &stm32_rng->clock); + if (res) + return res; + + if (fdt_getprop(fdt, node, "clock-error-detect", NULL)) + stm32_rng->clock_error = true; + + /* Release device if not used at runtime or for pm transitions */ + stm32_rng->release_post_boot = IS_ENABLED(CFG_WITH_SOFTWARE_PRNG) && + !IS_ENABLED(CFG_PM); + + return TEE_SUCCESS; +} + +static TEE_Result stm32_rng_probe(const void *fdt, int offs, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* Expect a single RNG instance */ + assert(!stm32_rng); + + stm32_rng = calloc(1, sizeof(*stm32_rng)); + if (!stm32_rng) + panic(); + + res = stm32_rng_parse_fdt(fdt, offs); + if (res) + goto err; + + stm32_rng->ddata = compat_data; + assert(stm32_rng->ddata); + + res = clk_enable(stm32_rng->clock); + if (res) + goto err; + + if (stm32_rng->rstctrl && + rstctrl_assert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) { + res = TEE_ERROR_GENERIC; + goto err_clk; + } + + if (stm32_rng->rstctrl && + rstctrl_deassert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) { + res = TEE_ERROR_GENERIC; + goto err_clk; + } + + res = init_rng(); + if (res) + goto err_clk; + + clk_disable(stm32_rng->clock); + + if (stm32_rng->release_post_boot) + stm32mp_register_non_secure_periph_iomem(stm32_rng->base.pa); + else + stm32mp_register_secure_periph_iomem(stm32_rng->base.pa); + + register_pm_core_service_cb(stm32_rng_pm, &stm32_rng, "rng-service"); + + return TEE_SUCCESS; + +err_clk: + clk_disable(stm32_rng->clock); +err: + free(stm32_rng); + stm32_rng = NULL; + + return res; +} + +static const struct stm32_rng_driver_data mp13_data[] = { + { .has_cond_reset = true }, +}; + +static const struct stm32_rng_driver_data mp15_data[] = { + { .has_cond_reset = false }, +}; +DECLARE_KEEP_PAGER(mp15_data); + +static const struct dt_device_match rng_match_table[] = { + { .compatible = "st,stm32-rng", .compat_data = &mp15_data }, + { .compatible = "st,stm32mp13-rng", .compat_data = &mp13_data }, + { } +}; + +DEFINE_DT_DRIVER(stm32_rng_dt_driver) = { + .name = "stm32_rng", + .match_table = rng_match_table, + .probe = stm32_rng_probe, +}; + +static TEE_Result stm32_rng_release(void) +{ + if (stm32_rng && stm32_rng->release_post_boot) { + DMSG("Release RNG driver"); + free(stm32_rng); + stm32_rng = NULL; + } + + return TEE_SUCCESS; +} + +release_init_resource(stm32_rng_release); diff --git a/optee/optee_os/core/drivers/stm32_shared_io.c b/optee/optee_os/core/drivers/stm32_shared_io.c new file mode 100644 index 0000000..fa20b47 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_shared_io.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2022, STMicroelectronics + */ + +#include +#include +#include +#include + +static unsigned int shregs_lock = SPINLOCK_UNLOCK; + +static uint32_t lock_stm32shregs(void) +{ + return may_spin_lock(&shregs_lock); +} + +static void unlock_stm32shregs(uint32_t exceptions) +{ + may_spin_unlock(&shregs_lock, exceptions); +} + +void io_mask32_stm32shregs(vaddr_t va, uint32_t value, uint32_t mask) +{ + uint32_t exceptions = lock_stm32shregs(); + + io_mask32(va, value, mask); + + unlock_stm32shregs(exceptions); +} + +void io_clrsetbits32_stm32shregs(vaddr_t va, uint32_t clr, uint32_t set) +{ + uint32_t exceptions = lock_stm32shregs(); + + io_clrsetbits32(va, clr, set); + + unlock_stm32shregs(exceptions); +} diff --git a/optee/optee_os/core/drivers/stm32_tamp.c b/optee/optee_os/core/drivers/stm32_tamp.c new file mode 100644 index 0000000..6a34bd1 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_tamp.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2021-2022, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* STM32 Registers */ +#define _TAMP_CR1 0x00U +#define _TAMP_CR2 0x04U +#define _TAMP_CR3 0x08U +#define _TAMP_FLTCR 0x0CU +#define _TAMP_ATCR1 0x10U +#define _TAMP_ATSEEDR 0x14U +#define _TAMP_ATOR 0x18U +#define _TAMP_ATCR2 0x1CU +#define _TAMP_SECCFGR 0x20U +#define _TAMP_SMCR 0x20U +#define _TAMP_PRIVCFGR 0x24U +#define _TAMP_IER 0x2CU +#define _TAMP_SR 0x30U +#define _TAMP_MISR 0x34U +#define _TAMP_SMISR 0x38U +#define _TAMP_SCR 0x3CU +#define _TAMP_COUNTR 0x40U +#define _TAMP_COUNT2R 0x44U +#define _TAMP_OR 0x50U +#define _TAMP_ERCFGR 0X54U +#define _TAMP_HWCFGR2 0x3ECU +#define _TAMP_HWCFGR1 0x3F0U +#define _TAMP_VERR 0x3F4U +#define _TAMP_IPIDR 0x3F8U +#define _TAMP_SIDR 0x3FCU + +/* _TAMP_SECCFGR bit fields */ +#define _TAMP_SECCFGR_BKPRWSEC_MASK GENMASK_32(7, 0) +#define _TAMP_SECCFGR_BKPRWSEC_SHIFT 0U +#define _TAMP_SECCFGR_CNT2SEC BIT(14) +#define _TAMP_SECCFGR_CNT1SEC BIT(15) +#define _TAMP_SECCFGR_BKPWSEC_MASK GENMASK_32(23, 16) +#define _TAMP_SECCFGR_BKPWSEC_SHIFT 16U +#define _TAMP_SECCFGR_BHKLOCK BIT(30) +#define _TAMP_SECCFGR_TAMPSEC BIT(31) +#define _TAMP_SECCFGR_BUT_BKP_MASK (GENMASK_32(31, 30) | \ + GENMASK_32(15, 14)) + +/* _TAMP_SMCR bit fields */ +#define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK_32(7, 0) +#define _TAMP_SMCR_BKPRWDPROT_SHIFT 0U +#define _TAMP_SMCR_BKPWDPROT_MASK GENMASK_32(23, 16) +#define _TAMP_SMCR_BKPWDPROT_SHIFT 16U +#define _TAMP_SMCR_DPROT BIT(31) +/* + * _TAMP_PRIVCFGR bit fields + */ +#define _TAMP_PRIVCFG_CNT2PRIV BIT(14) +#define _TAMP_PRIVCFG_CNT1PRIV BIT(15) +#define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) +#define _TAMP_PRIVCFG_BKPWPRIV BIT(30) +#define _TAMP_PRIVCFG_TAMPPRIV BIT(31) +#define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ + GENMASK_32(15, 14)) + +/* + * _TAMP_PRIVCFGR bit fields + */ +#define _TAMP_PRIVCFG_CNT2PRIV BIT(14) +#define _TAMP_PRIVCFG_CNT1PRIV BIT(15) +#define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) +#define _TAMP_PRIVCFG_BKPWPRIV BIT(30) +#define _TAMP_PRIVCFG_TAMPPRIV BIT(31) +#define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ + GENMASK_32(15, 14)) + +/* _TAMP_HWCFGR2 bit fields */ +#define _TAMP_HWCFGR2_TZ GENMASK_32(11, 8) +#define _TAMP_HWCFGR2_OR GENMASK_32(7, 0) + +/* _TAMP_HWCFGR1 bit fields */ +#define _TAMP_HWCFGR1_BKPREG GENMASK_32(7, 0) +#define _TAMP_HWCFGR1_TAMPER GENMASK_32(11, 8) +#define _TAMP_HWCFGR1_ACTIVE GENMASK_32(15, 12) +#define _TAMP_HWCFGR1_INTERN GENMASK_32(31, 16) +#define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U +#define _TAMP_HWCFGR1_ITAMP(id) BIT((id) - INT_TAMP1 + 16U) + +/* _TAMP_VERR bit fields */ +#define _TAMP_VERR_MINREV GENMASK_32(3, 0) +#define _TAMP_VERR_MAJREV GENMASK_32(7, 4) + +/* + * TAMP instance data + * @base - IOMEM base address + * @clock - TAMP clock + * @it - TAMP interrupt number + * @hwconf1 - Copy of TAMP HWCONF1 register content + * @hwconf2 - Copy of TAMP HWCONF2 register content + * @compat - Reference to compat data passed at driver initialization + */ +struct stm32_tamp_instance { + struct io_pa_va base; + struct clk *clock; + int it; + uint32_t hwconf1; + uint32_t hwconf2; + struct stm32_tamp_compat *compat; +}; + +/* + * Compatibility capabilities + * TAMP_HAS_REGISTER_SECCFG - Supports SECCFGR, otherwise supports SMCR register + * TAMP_HAS_REGISTER_PRIVCFG - Supports PRIVCFGR configuration register + */ +#define TAMP_HAS_REGISTER_SECCFG BIT(0) +#define TAMP_HAS_REGISTER_PRIVCFGR BIT(1) + +/* + * @nb_monotonic_counter - Number of monotic counter supported + * @tags - Bit flags TAMP_HAS_* for compatibily management + */ +struct stm32_tamp_compat { + int nb_monotonic_counter; + uint32_t tags; +}; + +/* Expects at most a single instance */ +static struct stm32_tamp_instance *stm32_tamp_device; + +TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *bkr_conf) +{ + struct stm32_tamp_instance *tamp = stm32_tamp_device; + vaddr_t base = 0; + uint32_t first_z2 = 0; + uint32_t first_z3 = 0; + + if (!tamp) + return TEE_ERROR_DEFER_DRIVER_INIT; + + if (!bkr_conf) + return TEE_ERROR_BAD_PARAMETERS; + + base = io_pa_or_va(&tamp->base, 1); + + first_z2 = bkr_conf->nb_zone1_regs; + first_z3 = bkr_conf->nb_zone1_regs + bkr_conf->nb_zone2_regs; + + if ((first_z2 > (tamp->hwconf1 & _TAMP_HWCFGR1_BKPREG)) || + (first_z3 > (tamp->hwconf1 & _TAMP_HWCFGR1_BKPREG))) + return TEE_ERROR_BAD_PARAMETERS; + + if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_SECCFG)) { + io_clrsetbits32(base + _TAMP_SECCFGR, + _TAMP_SECCFGR_BKPRWSEC_MASK, + (first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) & + _TAMP_SECCFGR_BKPRWSEC_MASK); + + io_clrsetbits32(base + _TAMP_SECCFGR, + _TAMP_SECCFGR_BKPWSEC_MASK, + (first_z3 << _TAMP_SECCFGR_BKPWSEC_SHIFT) & + _TAMP_SECCFGR_BKPWSEC_MASK); + } else { + io_clrsetbits32(base + _TAMP_SMCR, + _TAMP_SMCR_BKPRWDPROT_MASK, + (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) & + _TAMP_SMCR_BKPRWDPROT_MASK); + + io_clrsetbits32(base + _TAMP_SMCR, + _TAMP_SMCR_BKPWDPROT_MASK, + (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) & + _TAMP_SMCR_BKPWDPROT_MASK); + } + + return TEE_SUCCESS; +} + +static void stm32_tamp_set_secure(struct stm32_tamp_instance *tamp, + uint32_t mode) +{ + vaddr_t base = io_pa_or_va(&tamp->base, 1); + + if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_SECCFG)) { + io_clrsetbits32(base + _TAMP_SECCFGR, + _TAMP_SECCFGR_BUT_BKP_MASK, + mode & _TAMP_SECCFGR_BUT_BKP_MASK); + } else { + /* + * Note: MP15 doesn't use SECCFG register and + * inverts the secure bit. + */ + if (mode & _TAMP_SECCFGR_TAMPSEC) + io_clrbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); + else + io_setbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); + } +} + +static void stm32_tamp_set_privilege(struct stm32_tamp_instance *tamp, + uint32_t mode) +{ + vaddr_t base = io_pa_or_va(&tamp->base, 1); + + if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_PRIVCFGR)) + io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK, + mode & _TAMP_PRIVCFGR_MASK); +} + +static TEE_Result stm32_tamp_parse_fdt(struct stm32_tamp_instance *tamp, + const void *fdt, int node, + const void *compat) +{ + struct dt_node_info dt_tamp = { }; + + fdt_fill_device_info(fdt, &dt_tamp, node); + + if (dt_tamp.reg == DT_INFO_INVALID_REG || + dt_tamp.reg_size == DT_INFO_INVALID_REG_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + tamp->compat = (struct stm32_tamp_compat *)compat; + tamp->it = dt_tamp.interrupt; + tamp->base.pa = dt_tamp.reg; + io_pa_or_va_secure(&tamp->base, dt_tamp.reg_size); + + return clk_dt_get_by_index(fdt, node, 0, &tamp->clock); +} + +static TEE_Result stm32_tamp_probe(const void *fdt, int node, + const void *compat_data) +{ + struct stm32_tamp_instance *tamp = NULL; + uint32_t __maybe_unused revision = 0; + TEE_Result res = TEE_SUCCESS; + vaddr_t base = 0; + + tamp = calloc(1, sizeof(*tamp)); + if (!tamp) + return TEE_ERROR_OUT_OF_MEMORY; + + res = stm32_tamp_parse_fdt(tamp, fdt, node, compat_data); + if (res) + goto err; + + clk_enable(tamp->clock); + + base = io_pa_or_va(&tamp->base, 1); + + tamp->hwconf1 = io_read32(base + _TAMP_HWCFGR1); + tamp->hwconf2 = io_read32(base + _TAMP_HWCFGR2); + + revision = io_read32(base + _TAMP_VERR); + FMSG("STM32 TAMPER V%"PRIx32".%"PRIu32, + (revision & _TAMP_VERR_MAJREV) >> 4, revision & _TAMP_VERR_MINREV); + + if (!(tamp->hwconf2 & _TAMP_HWCFGR2_TZ)) { + EMSG("TAMP doesn't support TrustZone"); + res = TEE_ERROR_NOT_SUPPORTED; + goto err_clk; + } + + /* + * Enforce secure only access to protected TAMP registers. + * Allow non-secure access to monotonic counter. + */ + stm32_tamp_set_secure(tamp, _TAMP_SECCFGR_TAMPSEC); + + /* + * Enforce privilege only access to TAMP registers, backup + * registers and monotonic counter. + */ + stm32_tamp_set_privilege(tamp, _TAMP_PRIVCFG_TAMPPRIV | + _TAMP_PRIVCFG_BKPRWPRIV | + _TAMP_PRIVCFG_BKPWPRIV); + + stm32_tamp_device = tamp; + + return TEE_SUCCESS; + +err_clk: + clk_disable(tamp->clock); +err: + free(tamp); + return res; +} + +static const struct stm32_tamp_compat mp13_compat = { + .nb_monotonic_counter = 2, + .tags = TAMP_HAS_REGISTER_SECCFG | TAMP_HAS_REGISTER_PRIVCFGR, +}; + +static const struct stm32_tamp_compat mp15_compat = { + .nb_monotonic_counter = 1, + .tags = 0, +}; + +static const struct dt_device_match stm32_tamp_match_table[] = { + { .compatible = "st,stm32mp13-tamp", .compat_data = &mp13_compat }, + { .compatible = "st,stm32-tamp", .compat_data = &mp15_compat }, + { } +}; + +DEFINE_DT_DRIVER(stm32_tamp_dt_driver) = { + .name = "stm32-tamp", + .match_table = stm32_tamp_match_table, + .probe = stm32_tamp_probe, +}; diff --git a/optee/optee_os/core/drivers/stm32_uart.c b/optee/optee_os/core/drivers/stm32_uart.c new file mode 100644 index 0000000..7c1ec52 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32_uart.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2018, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define UART_REG_CR1 0x00 /* Control register 1 */ +#define UART_REG_CR2 0x04 /* Control register 2 */ +#define UART_REG_CR3 0x08 /* Control register 3 */ +#define UART_REG_BRR 0x0c /* Baud rate register */ +#define UART_REG_RQR 0x18 /* Request register */ +#define UART_REG_ISR 0x1c /* Interrupt & status reg. */ +#define UART_REG_ICR 0x20 /* Interrupt flag clear reg. */ +#define UART_REG_RDR 0x24 /* Receive data register */ +#define UART_REG_TDR 0x28 /* Transmit data register */ +#define UART_REG_PRESC 0x2c /* Prescaler register */ + +#define PUTC_TIMEOUT_US 1000 +#define FLUSH_TIMEOUT_US 16000 + +/* + * Uart Interrupt & status register bits + * + * Bit 5 RXNE: Read data register not empty/RXFIFO not empty + * Bit 6 TC: Transmission complete + * Bit 7 TXE/TXFNF: Transmit data register empty/TXFIFO not full + * Bit 27 TXFE: TXFIFO threshold reached + */ +#define USART_ISR_RXNE_RXFNE BIT(5) +#define USART_ISR_TC BIT(6) +#define USART_ISR_TXE_TXFNF BIT(7) +#define USART_ISR_TXFE BIT(27) + +static vaddr_t loc_chip_to_base(struct serial_chip *chip) +{ + struct stm32_uart_pdata *pd = NULL; + + pd = container_of(chip, struct stm32_uart_pdata, chip); + + return io_pa_or_va(&pd->base, 1); +} + +static void loc_flush(struct serial_chip *chip) +{ + vaddr_t base = loc_chip_to_base(chip); + uint64_t timeout = timeout_init_us(FLUSH_TIMEOUT_US); + + while (!(io_read32(base + UART_REG_ISR) & USART_ISR_TXFE)) + if (timeout_elapsed(timeout)) + return; +} + +static void loc_putc(struct serial_chip *chip, int ch) +{ + vaddr_t base = loc_chip_to_base(chip); + uint64_t timeout = timeout_init_us(PUTC_TIMEOUT_US); + + while (!(io_read32(base + UART_REG_ISR) & USART_ISR_TXE_TXFNF)) + if (timeout_elapsed(timeout)) + return; + + io_write32(base + UART_REG_TDR, ch); +} + +static bool loc_have_rx_data(struct serial_chip *chip) +{ + vaddr_t base = loc_chip_to_base(chip); + + return io_read32(base + UART_REG_ISR) & USART_ISR_RXNE_RXFNE; +} + +static int loc_getchar(struct serial_chip *chip) +{ + vaddr_t base = loc_chip_to_base(chip); + + while (!loc_have_rx_data(chip)) + ; + + return io_read32(base + UART_REG_RDR) & 0xff; +} + +static const struct serial_ops stm32_uart_serial_ops = { + .flush = loc_flush, + .putc = loc_putc, + .have_rx_data = loc_have_rx_data, + .getchar = loc_getchar, + +}; +DECLARE_KEEP_PAGER(stm32_uart_serial_ops); + +void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base) +{ + pd->base.pa = base; + pd->chip.ops = &stm32_uart_serial_ops; +} + +static void register_secure_uart(struct stm32_uart_pdata *pd) +{ + size_t n = 0; + + stm32mp_register_secure_periph_iomem(pd->base.pa); + for (n = 0; n < pd->pinctrl_count; n++) + stm32mp_register_secure_gpio(pd->pinctrl[n].bank, + pd->pinctrl[n].pin); +} + +static void register_non_secure_uart(struct stm32_uart_pdata *pd) +{ + size_t n = 0; + + stm32mp_register_non_secure_periph_iomem(pd->base.pa); + for (n = 0; n < pd->pinctrl_count; n++) + stm32mp_register_non_secure_gpio(pd->pinctrl[n].bank, + pd->pinctrl[n].pin); +} + +struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct stm32_uart_pdata *pd = NULL; + struct dt_node_info info = { }; + struct stm32_pinctrl *pinctrl_cfg = NULL; + int count = 0; + + fdt_fill_device_info(fdt, &info, node); + + if (info.status == DT_STATUS_DISABLED) + return NULL; + + assert(info.reg != DT_INFO_INVALID_REG && + info.reg_size != DT_INFO_INVALID_REG_SIZE); + + pd = calloc(1, sizeof(*pd)); + if (!pd) + panic(); + + pd->chip.ops = &stm32_uart_serial_ops; + pd->base.pa = info.reg; + pd->secure = (info.status == DT_STATUS_OK_SEC); + + res = clk_dt_get_by_index(fdt, node, 0, &pd->clock); + if (res) { + EMSG("Failed to get clock: %#"PRIx32, res); + panic(); + } + + res = clk_enable(pd->clock); + if (res) + panic(); + + assert(cpu_mmu_enabled()); + pd->base.va = (vaddr_t)phys_to_virt(pd->base.pa, + pd->secure ? MEM_AREA_IO_SEC : + MEM_AREA_IO_NSEC, info.reg_size); + + count = stm32_pinctrl_fdt_get_pinctrl(fdt, node, NULL, 0); + if (count < 0) + panic(); + + if (count) { + pinctrl_cfg = calloc(count, sizeof(*pinctrl_cfg)); + if (!pinctrl_cfg) + panic(); + + stm32_pinctrl_fdt_get_pinctrl(fdt, node, pinctrl_cfg, count); + stm32_pinctrl_load_active_cfg(pinctrl_cfg, count); + } + pd->pinctrl = pinctrl_cfg; + pd->pinctrl_count = count; + + if (pd->secure) + register_secure_uart(pd); + else + register_non_secure_uart(pd); + + return pd; +} diff --git a/optee/optee_os/core/drivers/stm32mp15_huk.c b/optee/optee_os/core/drivers/stm32mp15_huk.c new file mode 100644 index 0000000..7614227 --- /dev/null +++ b/optee/optee_os/core/drivers/stm32mp15_huk.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + * Copyright (c) 2022, Foundries.io Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HUK_NB_OTP (HW_UNIQUE_KEY_LENGTH / sizeof(uint32_t)) + +static bool stm32mp15_huk_init; + +static TEE_Result stm32mp15_read_uid(uint32_t *uid) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + uint32_t *q = uid; + uint32_t otp_idx = 0; + size_t __maybe_unused sz = 0; + + ret = stm32_bsec_find_otp_in_nvmem_layout("uid_otp", &otp_idx, &sz); + if (ret) + return ret; + assert(sz == 3 * 32); + + /* + * Shadow memory for UID words might not be locked: to guarante that + * the final values are read we must lock them. + */ + if (stm32_bsec_set_sw_lock(otp_idx) || + stm32_bsec_shadow_read_otp(q++, otp_idx)) + return TEE_ERROR_GENERIC; + + if (stm32_bsec_set_sw_lock(otp_idx + 1) || + stm32_bsec_shadow_read_otp(q++, otp_idx + 1)) + return TEE_ERROR_GENERIC; + + if (stm32_bsec_set_sw_lock(otp_idx + 2) || + stm32_bsec_shadow_read_otp(q++, otp_idx + 2)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result stm32mp15_read_otp(uint32_t otp, uint32_t *key, bool *locked) +{ + bool tmp = true; + uint32_t state = 0; + + if (stm32_bsec_get_state(&state)) + panic(); + + if (state != BSEC_STATE_SEC_CLOSED) { + /* + * When the device is not closed, the shadow memory for these + * words might not be locked: check and report them + */ + if (stm32_bsec_read_permanent_lock(otp, &tmp)) + return TEE_ERROR_GENERIC; + + if (tmp && stm32_bsec_read_sw_lock(otp, &tmp)) + return TEE_ERROR_GENERIC; + } + + if (stm32_bsec_shadow_read_otp(key, otp)) + return TEE_ERROR_GENERIC; + + *locked = *locked && tmp; + + return TEE_SUCCESS; +} + +/* + * AES-GCM: nonce must be unique per message and key. + * + * This function always uses the same key - once its locked - with the same + * unique message hence the nonce can be any constant. + */ +static TEE_Result aes_gcm_encrypt_uid(uint8_t *key, size_t key_len, + uint8_t *out, size_t *out_len) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + const uint8_t nonce[12] = { 0x55 }; + uint32_t uid[4] = { 0 }; + uint8_t tag[16] = { 0 }; + size_t nonce_len = sizeof(nonce); + size_t tag_len = sizeof(tag); + size_t uid_len = sizeof(uid); + void *ctx = NULL; + + ret = stm32mp15_read_uid(uid); + if (ret) + goto out; + + ret = crypto_authenc_alloc_ctx(&ctx, TEE_ALG_AES_GCM); + if (ret) + goto out; + + ret = crypto_authenc_init(ctx, TEE_MODE_ENCRYPT, key, key_len, nonce, + nonce_len, TEE_AES_BLOCK_SIZE, 0, uid_len); + if (ret) + goto out_free_ctx; + + ret = crypto_authenc_enc_final(ctx, (uint8_t *)uid, sizeof(uid), + out, out_len, tag, &tag_len); + if (ret) + goto out_free_ctx; + + crypto_authenc_final(ctx); +out_free_ctx: + crypto_authenc_free_ctx(ctx); +out: + if (ret) + memzero_explicit(out, *out_len); + + return ret; +} + +static __maybe_unused TEE_Result pos_from_dt(uint32_t otp_id[HUK_NB_OTP]) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t otp_start = 0; + size_t tmp = 0; + size_t i = 0; + + ret = stm32_bsec_find_otp_in_nvmem_layout("huk-otp", &otp_start, &tmp); + if (ret) + return ret; + + if (tmp != (HW_UNIQUE_KEY_LENGTH * CHAR_BIT)) + return TEE_ERROR_SECURITY; + + for (i = 0; i < HUK_NB_OTP; i++) + otp_id[i] = otp_start + i; + + return TEE_SUCCESS; +} + +static TEE_Result get_otp_pos(uint32_t otp_id[HUK_NB_OTP]) +{ +#ifdef CFG_STM32_HUK_FROM_DT + return pos_from_dt(otp_id); +#else /* CFG_STM32_HUK_FROM_DT */ + + static_assert(CFG_STM32MP15_HUK_BSEC_KEY_0 < STM32MP1_OTP_MAX_ID); + static_assert(CFG_STM32MP15_HUK_BSEC_KEY_1 < STM32MP1_OTP_MAX_ID); + static_assert(CFG_STM32MP15_HUK_BSEC_KEY_2 < STM32MP1_OTP_MAX_ID); + static_assert(CFG_STM32MP15_HUK_BSEC_KEY_3 < STM32MP1_OTP_MAX_ID); + + otp_id[0] = CFG_STM32MP15_HUK_BSEC_KEY_0; + otp_id[1] = CFG_STM32MP15_HUK_BSEC_KEY_1; + otp_id[2] = CFG_STM32MP15_HUK_BSEC_KEY_2; + otp_id[3] = CFG_STM32MP15_HUK_BSEC_KEY_3; + + return TEE_SUCCESS; +#endif /* CFG_STM32_HUK_FROM_DT */ +} + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + uint32_t otp_key[HUK_NB_OTP] = { }; + uint32_t otp_id[HUK_NB_OTP] = { }; + size_t len = HW_UNIQUE_KEY_LENGTH; + TEE_Result ret = TEE_SUCCESS; + uint32_t *key = otp_key; + bool lock = true; + size_t i = 0; + + ret = get_otp_pos(otp_id); + if (ret) + return ret; + + for (i = 0; i < HUK_NB_OTP; i++) { + ret = stm32mp15_read_otp(otp_id[i], key++, &lock); + if (ret) + goto out; + } + + if (IS_ENABLED(CFG_STM32MP15_HUK_BSEC_KEY)) { + static_assert(sizeof(otp_key) == HW_UNIQUE_KEY_LENGTH); + memcpy(hwkey->data, otp_key, HW_UNIQUE_KEY_LENGTH); + ret = TEE_SUCCESS; + goto out; + } + + if (IS_ENABLED(CFG_STM32MP15_HUK_BSEC_DERIVE_UID)) { + ret = aes_gcm_encrypt_uid((uint8_t *)otp_key, len, hwkey->data, + &len); + if (len != HW_UNIQUE_KEY_LENGTH) + ret = TEE_ERROR_GENERIC; + goto out; + } + + panic(); + +out: + memzero_explicit(otp_key, HW_UNIQUE_KEY_LENGTH); + + if (!ret && !stm32mp15_huk_init) { + stm32mp15_huk_init = true; + IMSG("HUK %slocked", lock ? "" : "un"); + DHEXDUMP(hwkey->data, HW_UNIQUE_KEY_LENGTH); + } + + return ret; +} + diff --git a/optee/optee_os/core/drivers/stpmic1.c b/optee/optee_os/core/drivers/stpmic1.c new file mode 100644 index 0000000..2f6eb20 --- /dev/null +++ b/optee/optee_os/core/drivers/stpmic1.c @@ -0,0 +1,1022 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VOLTAGE_INDEX_INVALID ((unsigned int)~0) + +struct regul_struct { + const char *dt_node_name; + const uint16_t *voltage_table; + uint8_t voltage_table_size; + uint8_t control_reg; + uint8_t low_power_reg; + uint8_t enable_pos; + uint8_t pull_down_reg; + uint8_t pull_down_pos; + uint8_t mask_reset_reg; + uint8_t mask_reset_pos; +}; + +static struct i2c_handle_s *pmic_i2c_handle; +static uint16_t pmic_i2c_addr; + +/* Voltage tables in mV */ +static const uint16_t buck1_voltage_table[] = { + 725, + 725, + 725, + 725, + 725, + 725, + 750, + 775, + 800, + 825, + 850, + 875, + 900, + 925, + 950, + 975, + 1000, + 1025, + 1050, + 1075, + 1100, + 1125, + 1150, + 1175, + 1200, + 1225, + 1250, + 1275, + 1300, + 1325, + 1350, + 1375, + 1400, + 1425, + 1450, + 1475, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, +}; + +static const uint16_t buck2_voltage_table[] = { + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1050, + 1050, + 1100, + 1100, + 1150, + 1150, + 1200, + 1200, + 1250, + 1250, + 1300, + 1300, + 1350, + 1350, + 1400, + 1400, + 1450, + 1450, + 1500, +}; + +static const uint16_t buck3_voltage_table[] = { + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1100, + 1100, + 1100, + 1100, + 1200, + 1200, + 1200, + 1200, + 1300, + 1300, + 1300, + 1300, + 1400, + 1400, + 1400, + 1400, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, +}; + +static const uint16_t buck4_voltage_table[] = { + 600, + 625, + 650, + 675, + 700, + 725, + 750, + 775, + 800, + 825, + 850, + 875, + 900, + 925, + 950, + 975, + 1000, + 1025, + 1050, + 1075, + 1100, + 1125, + 1150, + 1175, + 1200, + 1225, + 1250, + 1275, + 1300, + 1300, + 1350, + 1350, + 1400, + 1400, + 1450, + 1450, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, + 3500, + 3600, + 3700, + 3800, + 3900, +}; + +static const uint16_t ldo1_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo2_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo3_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3300, + 3300, + 3300, + 3300, + 3300, + 3300, + 500, /* VOUT2/2 (Sink/source mode) */ + 0xFFFF, /* VREFDDR */ +}; + +static const uint16_t ldo5_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, + 3500, + 3600, + 3700, + 3800, + 3900, +}; + +static const uint16_t ldo6_voltage_table[] = { + 900, + 1000, + 1100, + 1200, + 1300, + 1400, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo4_voltage_table[] = { + 3300, +}; + +static const uint16_t vref_ddr_voltage_table[] = { + 3300, +}; + +static const uint16_t fixed_5v_voltage_table[] = { + 5000, +}; + +/* Table of Regulators in PMIC SoC */ +static const struct regul_struct regulators_table[] = { + { + .dt_node_name = "buck1", + .voltage_table = buck1_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), + .control_reg = BUCK1_CONTROL_REG, + .low_power_reg = BUCK1_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down_pos = BUCK1_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset_pos = BUCK1_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "buck2", + .voltage_table = buck2_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), + .control_reg = BUCK2_CONTROL_REG, + .low_power_reg = BUCK2_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down_pos = BUCK2_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset_pos = BUCK2_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "buck3", + .voltage_table = buck3_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), + .control_reg = BUCK3_CONTROL_REG, + .low_power_reg = BUCK3_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down_pos = BUCK3_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset_pos = BUCK3_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "buck4", + .voltage_table = buck4_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), + .control_reg = BUCK4_CONTROL_REG, + .low_power_reg = BUCK4_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down_pos = BUCK4_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset_pos = BUCK4_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "ldo1", + .voltage_table = ldo1_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), + .control_reg = LDO1_CONTROL_REG, + .low_power_reg = LDO1_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset_pos = LDO1_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "ldo2", + .voltage_table = ldo2_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), + .control_reg = LDO2_CONTROL_REG, + .low_power_reg = LDO2_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset_pos = LDO2_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "ldo3", + .voltage_table = ldo3_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), + .control_reg = LDO3_CONTROL_REG, + .low_power_reg = LDO3_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset_pos = LDO3_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "ldo4", + .voltage_table = ldo4_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), + .control_reg = LDO4_CONTROL_REG, + .low_power_reg = LDO4_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset_pos = LDO4_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "ldo5", + .voltage_table = ldo5_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), + .control_reg = LDO5_CONTROL_REG, + .low_power_reg = LDO5_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset_pos = LDO5_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "ldo6", + .voltage_table = ldo6_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), + .control_reg = LDO6_CONTROL_REG, + .low_power_reg = LDO6_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset_pos = LDO6_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "vref_ddr", + .voltage_table = vref_ddr_voltage_table, + .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), + .control_reg = VREF_DDR_CONTROL_REG, + .low_power_reg = VREF_DDR_PWRCTRL_REG, + .enable_pos = LDO_BUCK_ENABLE_POS, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset_pos = VREF_DDR_MASK_RESET_SHIFT, + }, + { + .dt_node_name = "boost", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_pos = BOOST_ENABLED_POS, + }, + { + .dt_node_name = "pwr_sw1", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_pos = USBSW_OTG_SWITCH_ENABLED_POS, + }, + { + .dt_node_name = "pwr_sw2", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_pos = SWIN_SWOUT_ENABLED_POS, + }, +}; + +static const struct regul_struct *get_regulator_data(const char *name) +{ + unsigned int i = 0; + + for (i = 0; i < ARRAY_SIZE(regulators_table); i++) + if (strcmp(name, regulators_table[i].dt_node_name) == 0) + return ®ulators_table[i]; + + DMSG("Regulator %s not found", name); + return NULL; +} + +bool stpmic1_regulator_is_valid(const char *name) +{ + return get_regulator_data(name); +} + +void stpmic1_regulator_levels_mv(const char *name, + const uint16_t **levels, + size_t *levels_count) +{ + const struct regul_struct *regul = get_regulator_data(name); + + assert(regul); + + if (levels_count) + *levels_count = regul->voltage_table_size; + + if (levels) + *levels = regul->voltage_table; +} + +static size_t voltage_to_index(const char *name, uint16_t millivolts) +{ + const struct regul_struct *regul = get_regulator_data(name); + unsigned int i = 0; + + assert(regul->voltage_table); + for (i = 0; i < regul->voltage_table_size; i++) + if (regul->voltage_table[i] == millivolts) + return i; + + return VOLTAGE_INDEX_INVALID; +} + +int stpmic1_powerctrl_on(void) +{ + return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID, + PWRCTRL_PIN_VALID); +} + +int stpmic1_switch_off(void) +{ + return stpmic1_register_update(MAIN_CONTROL_REG, 1, + SOFTWARE_SWITCH_OFF_ENABLED); +} + +int stpmic1_regulator_enable(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + return stpmic1_register_update(regul->control_reg, + BIT(regul->enable_pos), + BIT(regul->enable_pos)); +} + +int stpmic1_regulator_disable(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + return stpmic1_register_update(regul->control_reg, 0, + BIT(regul->enable_pos)); +} + +bool stpmic1_is_regulator_enabled(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + uint8_t val = 0; + + if (stpmic1_register_read(regul->control_reg, &val)) + panic(); + + return val & BIT(regul->enable_pos); +} + +/* Voltage can be set for buck or ldo (except ldo4) regulators */ +static uint8_t find_plat_mask(const char *name) +{ + if (!strncmp(name, "buck", 4)) + return BUCK_VOLTAGE_MASK; + + if (!strncmp(name, "ldo", 3) && strcmp(name, "ldo4")) + return LDO_VOLTAGE_MASK; + + return 0; +} + +int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) +{ + size_t voltage_index = voltage_to_index(name, millivolts); + const struct regul_struct *regul = get_regulator_data(name); + uint8_t mask = 0; + + if (voltage_index == VOLTAGE_INDEX_INVALID) + return -1; + + mask = find_plat_mask(name); + if (!mask) + return 0; + + return stpmic1_register_update(regul->control_reg, + voltage_index << LDO_BUCK_VOLTAGE_SHIFT, + mask); +} + +int stpmic1_regulator_mask_reset_set(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (regul->control_reg == USB_CONTROL_REG) { + DMSG("No reset for USB control"); + return -1; + } + + return stpmic1_register_update(regul->mask_reset_reg, + BIT(regul->mask_reset_pos), + LDO_BUCK_RESET_MASK << + regul->mask_reset_pos); +} + +int stpmic1_bo_enable_cfg(const char *name, struct stpmic1_bo_cfg *cfg) +{ + const struct regul_struct *regul = get_regulator_data(name); + + cfg->ctrl_reg = regul->control_reg; + cfg->enable_pos = regul->enable_pos; + + return 0; +} + +int stpmic1_bo_enable_unpg(struct stpmic1_bo_cfg *cfg) +{ + return stpmic1_register_update(cfg->ctrl_reg, + BIT(cfg->enable_pos), + BIT(cfg->enable_pos)); +} + +/* Returns 1 if no configuration are expected applied at runtime, 0 otherwise */ +int stpmic1_bo_voltage_cfg(const char *name, uint16_t min_millivolt, + struct stpmic1_bo_cfg *cfg) +{ + size_t min_index = voltage_to_index(name, min_millivolt); + const struct regul_struct *regul = get_regulator_data(name); + uint8_t mask = 0; + + if (min_index == VOLTAGE_INDEX_INVALID) + panic(); + + mask = find_plat_mask(name); + if (!mask) + return 1; + + cfg->ctrl_reg = regul->control_reg; + cfg->min_value = min_index << LDO_BUCK_VOLTAGE_SHIFT; + cfg->mask = mask; + + return 0; +} + +int stpmic1_bo_voltage_unpg(struct stpmic1_bo_cfg *cfg) +{ + uint8_t value = 0; + + assert(cfg->ctrl_reg); + + if (stpmic1_register_read(cfg->ctrl_reg, &value)) + return -1; + + if ((value & cfg->mask) >= cfg->min_value) + return 0; + + return stpmic1_register_update(cfg->ctrl_reg, cfg->min_value, + cfg->mask); +} + +int stpmic1_bo_pull_down_cfg(const char *name, struct stpmic1_bo_cfg *cfg) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (!regul->pull_down_reg) { + DMSG("No pull down for regu %s", name); + panic(); + } + + cfg->pd_reg = regul->pull_down_reg; + cfg->pd_value = BIT(regul->pull_down_pos); + cfg->pd_mask = LDO_BUCK_PULL_DOWN_MASK << regul->pull_down_pos; + + return 0; +} + +int stpmic1_bo_pull_down_unpg(struct stpmic1_bo_cfg *cfg) +{ + assert(cfg->pd_reg); + + return stpmic1_register_update(cfg->pd_reg, cfg->pd_value, + cfg->pd_mask); +} + +int stpmic1_bo_mask_reset_cfg(const char *name, struct stpmic1_bo_cfg *cfg) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (!regul->mask_reset_reg) { + DMSG("No reset mask for regu %s", name); + panic(); + } + + cfg->mrst_reg = regul->mask_reset_reg; + cfg->mrst_value = BIT(regul->mask_reset_pos); + cfg->mrst_mask = LDO_BUCK_RESET_MASK << regul->mask_reset_pos; + + return 0; +} + +int stpmic1_bo_mask_reset_unpg(struct stpmic1_bo_cfg *cfg) +{ + assert(cfg->mrst_reg); + + return stpmic1_register_update(cfg->mrst_reg, cfg->mrst_value, + cfg->mrst_mask); +} + +int stpmic1_regulator_voltage_get(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + uint8_t value = 0; + uint8_t mask = 0; + + mask = find_plat_mask(name); + if (!mask) + return 0; + + if (stpmic1_register_read(regul->control_reg, &value)) + return -1; + + value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; + + if (value > regul->voltage_table_size) + return -1; + + return regul->voltage_table[value]; +} + +int stpmic1_lp_copy_reg(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + uint8_t val = 0; + int status = 0; + + if (!regul->low_power_reg) + return -1; + + status = stpmic1_register_read(regul->control_reg, &val); + if (status) + return status; + + return stpmic1_register_write(regul->low_power_reg, val); +} + +bool stpmic1_regu_has_lp_cfg(const char *name) +{ + return get_regulator_data(name)->low_power_reg; +} + +int stpmic1_lp_cfg(const char *name, struct stpmic1_lp_cfg *cfg) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (!regul->low_power_reg) + return -1; + + cfg->ctrl_reg = regul->control_reg; + cfg->lp_reg = regul->low_power_reg; + + return 0; +} + +int stpmic1_lp_load_unpg(struct stpmic1_lp_cfg *cfg) +{ + uint8_t val = 0; + int status = 0; + + assert(cfg->lp_reg); + + status = stpmic1_register_read(cfg->ctrl_reg, &val); + if (!status) + status = stpmic1_register_write(cfg->lp_reg, val); + + return status; +} + +int stpmic1_lp_reg_on_off(const char *name, uint8_t enable) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (!regul->low_power_reg) + return -1; + + return stpmic1_register_update(regul->low_power_reg, enable, + LDO_BUCK_ENABLE_MASK); +} + +int stpmic1_lp_on_off_unpg(struct stpmic1_lp_cfg *cfg, int enable) +{ + assert(cfg->lp_reg && (enable == 0 || enable == 1)); + + return stpmic1_register_update(cfg->lp_reg, enable, + LDO_BUCK_ENABLE_MASK); +} + +int stpmic1_lp_set_mode(const char *name, uint8_t hplp) +{ + const struct regul_struct *regul = get_regulator_data(name); + + assert(regul->low_power_reg && (hplp == 0 || hplp == 1)); + + return stpmic1_register_update(regul->low_power_reg, + hplp << LDO_BUCK_HPLP_POS, + BIT(LDO_BUCK_HPLP_POS)); +} + +int stpmic1_lp_mode_unpg(struct stpmic1_lp_cfg *cfg, unsigned int mode) +{ + assert(cfg->lp_reg && (mode == 0 || mode == 1)); + return stpmic1_register_update(cfg->lp_reg, + mode << LDO_BUCK_HPLP_POS, + BIT(LDO_BUCK_HPLP_POS)); +} + +int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts) +{ + size_t voltage_index = voltage_to_index(name, millivolts); + const struct regul_struct *regul = get_regulator_data(name); + uint8_t mask = 0; + + assert(voltage_index != VOLTAGE_INDEX_INVALID); + + mask = find_plat_mask(name); + if (!mask) + return 0; + + return stpmic1_register_update(regul->low_power_reg, voltage_index << 2, + mask); +} + +/* Returns 1 if no configuration are expected applied at runtime, 0 otherwise */ +int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts, + struct stpmic1_lp_cfg *cfg) + +{ + size_t voltage_index = voltage_to_index(name, millivolts); + uint8_t mask = 0; + + mask = find_plat_mask(name); + if (!mask) + return 1; + + assert(voltage_index != VOLTAGE_INDEX_INVALID && + cfg->lp_reg == get_regulator_data(name)->low_power_reg); + + cfg->value = voltage_index << 2; + cfg->mask = mask; + + return 0; +} + +int stpmic1_lp_voltage_unpg(struct stpmic1_lp_cfg *cfg) +{ + assert(cfg->lp_reg); + + return stpmic1_register_update(cfg->lp_reg, cfg->value, cfg->mask); +} + +int stpmic1_register_read(uint8_t register_id, uint8_t *value) +{ + struct i2c_handle_s *i2c = pmic_i2c_handle; + + return stm32_i2c_read_write_membyte(i2c, pmic_i2c_addr, + register_id, value, + false /* !write */); +} + +int stpmic1_register_write(uint8_t register_id, uint8_t value) +{ + struct i2c_handle_s *i2c = pmic_i2c_handle; + uint8_t val = value; + + return stm32_i2c_read_write_membyte(i2c, pmic_i2c_addr, + register_id, &val, + true /* write */); +} + +int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) +{ + int status = 0; + uint8_t val = 0; + + status = stpmic1_register_read(register_id, &val); + if (status) + return status; + + val = (val & ~mask) | (value & mask); + + return stpmic1_register_write(register_id, val); +} + +void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) +{ + pmic_i2c_handle = i2c_handle; + pmic_i2c_addr = i2c_addr; +} + +void stpmic1_dump_regulators(void) +{ + size_t i = 0; + char __maybe_unused const *name = NULL; + + for (i = 0; i < ARRAY_SIZE(regulators_table); i++) { + if (!regulators_table[i].control_reg) + continue; + + name = regulators_table[i].dt_node_name; + DMSG("PMIC regul %s: %sable, %dmV", + name, stpmic1_is_regulator_enabled(name) ? "en" : "dis", + stpmic1_regulator_voltage_get(name)); + } +} + +int stpmic1_get_version(unsigned long *version) +{ + uint8_t read_val = 0; + + if (stpmic1_register_read(VERSION_STATUS_REG, &read_val)) + return -1; + + *version = read_val; + return 0; +} diff --git a/optee/optee_os/core/drivers/sub.mk b/optee/optee_os/core/drivers/sub.mk new file mode 100644 index 0000000..e796a07 --- /dev/null +++ b/optee/optee_os/core/drivers/sub.mk @@ -0,0 +1,91 @@ +incdirs-$(CFG_VERSAL_SHA3_384) += crypto/versal/include + +srcs-$(CFG_CDNS_UART) += cdns_uart.c +srcs-$(CFG_PL011) += pl011.c +srcs-$(CFG_TZC400) += tzc400.c +srcs-$(CFG_TZC380) += tzc380.c +srcs-$(CFG_GIC) += gic.c +srcs-$(CFG_CORE_HAFNIUM_INTC) += hfic.c +srcs-$(CFG_PL061) += pl061_gpio.c +srcs-$(CFG_PL022) += pl022_spi.c +srcs-$(CFG_SP805_WDT) += sp805_wdt.c +srcs-$(CFG_8250_UART) += serial8250_uart.c +srcs-$(CFG_16550_UART) += ns16550.c +srcs-$(CFG_IMX_SNVS) += imx_snvs.c +srcs-$(CFG_IMX_UART) += imx_uart.c +srcs-$(CFG_IMX_I2C) += imx_i2c.c +srcs-$(CFG_IMX_LPUART) += imx_lpuart.c +srcs-$(CFG_IMX_WDOG) += imx_wdog.c +srcs-$(CFG_SPRD_UART) += sprd_uart.c +srcs-$(CFG_HI16XX_UART) += hi16xx_uart.c +srcs-$(CFG_HI16XX_RNG) += hi16xx_rng.c +srcs-$(CFG_LPC_UART) += lpc_uart.c +srcs-$(CFG_SCIF) += scif.c +srcs-$(CFG_DRA7_RNG) += dra7_rng.c +srcs-$(CFG_STIH_UART) += stih_asc.c +srcs-$(CFG_ATMEL_UART) += atmel_uart.c +srcs-$(CFG_ATMEL_TRNG) += atmel_trng.c +srcs-$(CFG_ATMEL_RSTC) += atmel_rstc.c +srcs-$(CFG_ATMEL_SHDWC) += atmel_shdwc.c atmel_shdwc_a32.S +srcs-$(CFG_ATMEL_SAIC) += atmel_saic.c +srcs-$(CFG_ATMEL_WDT) += atmel_wdt.c +srcs-$(CFG_ATMEL_RTC) += atmel_rtc.c +srcs-$(CFG_ATMEL_PIOBU) += atmel_piobu.c +srcs-$(CFG_ATMEL_TCB) += atmel_tcb.c +srcs-$(CFG_AMLOGIC_UART) += amlogic_uart.c +srcs-$(CFG_MVEBU_UART) += mvebu_uart.c +srcs-$(CFG_STM32_BSEC) += stm32_bsec.c +srcs-$(CFG_STM32_ETZPC) += stm32_etzpc.c +srcs-$(CFG_STM32_GPIO) += stm32_gpio.c +srcs-$(CFG_STM32_IWDG) += stm32_iwdg.c +srcs-$(CFG_STM32_I2C) += stm32_i2c.c +srcs-$(CFG_STM32_RNG) += stm32_rng.c +srcs-$(CFG_STM32_SHARED_IO) += stm32_shared_io.c +srcs-$(CFG_STM32_TAMP) += stm32_tamp.c +srcs-$(CFG_STM32_UART) += stm32_uart.c +srcs-$(CFG_STPMIC1) += stpmic1.c +srcs-$(CFG_BCM_HWRNG) += bcm_hwrng.c +srcs-$(CFG_BCM_SOTP) += bcm_sotp.c +srcs-$(CFG_BCM_GPIO) += bcm_gpio.c +srcs-$(CFG_LS_I2C) += ls_i2c.c +srcs-$(CFG_LS_GPIO) += ls_gpio.c +srcs-$(CFG_LS_DSPI) += ls_dspi.c +srcs-$(CFG_LS_SEC_MON) += ls_sec_mon.c +srcs-$(CFG_LS_SFP) += ls_sfp.c +srcs-$(CFG_IMX_RNGB) += imx_rngb.c +srcs-$(CFG_IMX_OCOTP) += imx_ocotp.c +srcs-$(CFG_IMX_CAAM) += imx_caam.c +srcs-$(CFG_IMX_SCU) += imx_scu.c +srcs-$(CFG_IMX_CSU) += imx_csu.c +srcs-$(CFG_XIPHERA_TRNG) += xiphera_trng.c +srcs-$(CFG_IMX_SC) += imx_sc_api.c +srcs-$(CFG_IMX_ELE) += imx_ele.c +srcs-$(CFG_ZYNQMP_CSU_PUF) += zynqmp_csu_puf.c +srcs-$(CFG_ZYNQMP_CSUDMA) += zynqmp_csudma.c +srcs-$(CFG_ZYNQMP_CSU_AES) += zynqmp_csu_aes.c +srcs-$(CFG_ZYNQMP_PM) += zynqmp_pm.c +srcs-$(CFG_ZYNQMP_HUK) += zynqmp_huk.c +srcs-$(CFG_ARM_SMCCC_TRNG) += smccc_trng.c +srcs-$(CFG_VERSAL_GPIO) += versal_gpio.c +srcs-$(CFG_VERSAL_MBOX) += versal_mbox.c +srcs-$(CFG_VERSAL_PM) += versal_pm.c +srcs-$(CFG_TEGRA_TCU) += tegra_combined_uart.c +srcs-$(CFG_STM32MP15_HUK) += stm32mp15_huk.c +srcs-$(CFG_VERSAL_RNG_DRV) += versal_trng.c +srcs-$(CFG_VERSAL_NVM) += versal_nvm.c +srcs-$(CFG_VERSAL_SHA3_384) += versal_sha3_384.c +srcs-$(CFG_VERSAL_PUF) += versal_puf.c +srcs-$(CFG_VERSAL_HUK) += versal_huk.c +srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c + +subdirs-y += crypto +subdirs-$(CFG_BNXT_FW) += bnxt +subdirs-$(CFG_DRIVERS_CLK) += clk +subdirs-$(CFG_DRIVERS_I2C) += i2c +subdirs-$(CFG_DRIVERS_RSTCTRL) += rstctrl +subdirs-$(CFG_SCMI_MSG_DRIVERS) += scmi-msg +subdirs-y += imx +subdirs-$(CFG_TEGRA_DRIVERS) += tegra +subdirs-y += pm +subdirs-y += wdt +subdirs-y += rtc diff --git a/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_common.h b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_common.h new file mode 100644 index 0000000..37139f7 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_common.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_DRIVER_COMMON_H__ +#define __TEGRA_DRIVER_COMMON_H__ + +#include +#include + +TEE_Result iomap_pa2va(paddr_t pa, paddr_size_t size, vaddr_t *va); + +#endif diff --git a/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h new file mode 100644 index 0000000..9733375 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_fuse.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_DRIVER_FUSE_H__ +#define __TEGRA_DRIVER_FUSE_H__ + +#if defined(PLATFORM_FLAVOR_t194) +#define TEGRA_FUSE_BASE 0x03820000 +#define TEGRA_FUSE_SIZE 0x600 +#endif + +#if defined(PLATFORM_FLAVOR_t234) +#define TEGRA_FUSE_BASE 0x03810000 +#define TEGRA_FUSE_SIZE 0x600 +#endif + +TEE_Result tegra_fuse_map_regs(vaddr_t *va); + +#endif diff --git a/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_rng1.h b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_rng1.h new file mode 100644 index 0000000..34bca48 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_rng1.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_DRIVER_RNG1_H__ +#define __TEGRA_DRIVER_RNG1_H__ + +#if defined(PLATFORM_FLAVOR_t194) +#define TEGRA_RNG1_BASE 0x03ae0000 +#define TEGRA_RNG1_SIZE 0x10000 +#endif + +#if defined(PLATFORM_FLAVOR_t234) +#define TEGRA_RNG1_BASE 0x03b70000 +#define TEGRA_RNG1_SIZE 0x10000 +#endif + +TEE_Result tegra_rng1_map_regs(vaddr_t *va); + +#endif diff --git a/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h new file mode 100644 index 0000000..2d5303d --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_se.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_DRIVER_SE_H__ +#define __TEGRA_DRIVER_SE_H__ + +#include +#include + +#if defined(PLATFORM_FLAVOR_t194) +#define TEGRA_SE_BASE 0x03ac0000 +#define TEGRA_SE_SIZE 0x2000 +#endif + +#if defined(PLATFORM_FLAVOR_t234) +#define TEGRA_SE_BASE 0x03b50000 +#define TEGRA_SE_SIZE 0x30000 +#endif + +/* Security Engine Operation Modes */ +typedef enum +{ + SE_AES_OP_MODE_CBC, /* Cipher Block Chaining (CBC) mode */ + SE_AES_OP_MODE_CMAC, /* Cipher-based MAC (CMAC) mode */ + SE_AES_OP_MODE_ECB, /* Electronic Codebook (ECB) mode */ +} se_aes_op_mode; + +TEE_Result tegra_se_map_regs(vaddr_t *va); + +#endif diff --git a/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h new file mode 100644 index 0000000..e36e136 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/include/tegra_driver_srv_intf.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_DRIVER_SRV_INTF_H__ +#define __TEGRA_DRIVER_SRV_INTF_H__ + +#include +#include +#include +#include +#include + +typedef struct tegra_driver_srv_intf { + /* KDF interface */ + TEE_Result (*aes_ecb_kdf)(uint8_t *derived_key, size_t derived_key_len, + uint8_t *iv, size_t iv_len, + uint32_t keyslot); + TEE_Result (*nist_sp_800_108_cmac_kdf)(se_aes_keyslot_t keyslot, + uint32_t key_len, + char const *context, + uint32_t context_len, + char const *label, + uint32_t label_len, + uint32_t dk_len, + uint8_t *out_dk); + /* keyslot interface */ + TEE_Result (*write_aes_keyslot)(uint8_t *input_key, uint32_t keylen, + uint32_t key_quad_sel, + se_aes_keyslot_t keyslot); + TEE_Result (*clear_aes_keyslots)(void); + /* RNG interface */ + TEE_Result (*rng_get_random)(void *data_buf, uint32_t data_len); + /* Fuse ECID interface */ + fuse_ecid_t* (*get_ecid)(void); + /* Fuse BSI interface */ + TEE_Result (*get_bsi)(uint32_t *val); + /* AES encryption interface */ + TEE_Result (*aes_encrypt)(uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len, se_aes_op_mode mode, + uint32_t keyslot, uint8_t *iv); +} tegra_drv_srv_intf_t; + +/* Initialize SE service interface */ +tegra_drv_srv_intf_t *tegra_drv_srv_intf_get(void); + +#endif diff --git a/optee/optee_os/core/drivers/tegra/common/sub.mk b/optee/optee_os/core/drivers/tegra/common/sub.mk new file mode 100644 index 0000000..e1524a2 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/sub.mk @@ -0,0 +1,8 @@ +incdirs-y += include + +srcs-y += tegra_driver_common.c +srcs-$(CFG_TEGRA_FUSE) += tegra_driver_fuse.c +srcs-$(CFG_TEGRA_SE_RNG1) += tegra_driver_rng1.c +srcs-$(CFG_TEGRA_SE) += tegra_driver_se.c +srcs-y += tegra_driver_srv_intf.c +srcs-y += tegra_driver_clear_keyslots.c diff --git a/optee/optee_os/core/drivers/tegra/common/tegra_driver_clear_keyslots.c b/optee/optee_os/core/drivers/tegra/common/tegra_driver_clear_keyslots.c new file mode 100644 index 0000000..dc1d7ef --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/tegra_driver_clear_keyslots.c @@ -0,0 +1,26 @@ + +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include + +static TEE_Result tegra_keyslots_clear(void) +{ + TEE_Result rc = TEE_SUCCESS; + + DMSG("Start to clear keyslots..."); + rc = tegra_se_clear_aes_keyslots(); + /* Some platforms don't support keyslot clearing so ignore it */ + if (rc != TEE_SUCCESS && rc != TEE_ERROR_NOT_SUPPORTED) { + EMSG("%s: Failed to clear SE keyslots (%x).", __func__, rc); + panic(); + } + + return rc; +} +boot_final(tegra_keyslots_clear); diff --git a/optee/optee_os/core/drivers/tegra/common/tegra_driver_common.c b/optee/optee_os/core/drivers/tegra/common/tegra_driver_common.c new file mode 100644 index 0000000..55b79ed --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/tegra_driver_common.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include + +TEE_Result iomap_pa2va(paddr_t pa, paddr_size_t size, vaddr_t *va) +{ + if (!core_mmu_add_mapping(MEM_AREA_IO_SEC, pa, size)) + return TEE_ERROR_GENERIC; + + *va = (vaddr_t)phys_to_virt(pa, MEM_AREA_IO_SEC, size); + if (*va) + return TEE_SUCCESS; + + return TEE_ERROR_GENERIC; +} diff --git a/optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c b/optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c new file mode 100644 index 0000000..776948b --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/tegra_driver_fuse.c @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_DT +static const char *const tegra_fuse_dt_match_table[] = { + "nvidia,tegra194-efuse", + "nvidia,tegra234-efuse", +}; + +static TEE_Result tegra_fuse_dt_init(vaddr_t *va) +{ + void *fdt = NULL; + int node = -1; + uint32_t i = 0; + size_t size; + enum dt_map_dev_directive mapping = DT_MAP_AUTO; + + if (va == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + fdt = get_dt(); + if (!fdt) { + EMSG("%s: DTB is not present.", __func__); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + for (i = 0; i < ARRAY_SIZE(tegra_fuse_dt_match_table); i++) { + node = fdt_node_offset_by_compatible(fdt, 0, + tegra_fuse_dt_match_table[i]); + if (node >= 0) + break; + } + + if (node < 0) { + EMSG("%s: DT not found (%x).", __func__, node); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (dt_map_dev(fdt, node, va, &size, mapping) < 0) { + EMSG("%s: DT unable to map device address.", __func__); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} +#else +static TEE_Result tegra_fuse_dt_init(vaddr_t *va) +{ + (void) va; + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +TEE_Result tegra_fuse_map_regs(vaddr_t *va) +{ + if (IS_ENABLED(CFG_DT)) + return tegra_fuse_dt_init(va); + else + return iomap_pa2va(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE, va); +} diff --git a/optee/optee_os/core/drivers/tegra/common/tegra_driver_rng1.c b/optee/optee_os/core/drivers/tegra/common/tegra_driver_rng1.c new file mode 100644 index 0000000..5f012fa --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/tegra_driver_rng1.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_DT +static const char *const tegra_se_rng1_dt_match_table[] = { + "nvidia,tegra194-se0-elp-rng1", + "nvidia,tegra234-rng1", +}; + +static TEE_Result tegra_rng1_dt_init(vaddr_t *va) +{ + void *fdt = NULL; + int node = -1; + uint32_t i = 0; + size_t size; + enum dt_map_dev_directive mapping = DT_MAP_AUTO; + + if (va == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + fdt = get_dt(); + if (!fdt) { + EMSG("%s: DTB is not present.", __func__); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + for (i = 0; i < ARRAY_SIZE(tegra_se_rng1_dt_match_table); i++) { + node = fdt_node_offset_by_compatible(fdt, 0, + tegra_se_rng1_dt_match_table[i]); + if (node >= 0) + break; + } + + if (node < 0) { + EMSG("%s: DT not found (%x).", __func__, node); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (dt_map_dev(fdt, node, va, &size, mapping) < 0) { + EMSG("%s: DT unable to map device address.", __func__); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} +#else +static TEE_Result tegra_rng1_dt_init(vaddr_t *va) +{ + (void) va; + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +TEE_Result tegra_rng1_map_regs(vaddr_t *va) +{ + if (IS_ENABLED(CFG_DT)) + return tegra_rng1_dt_init(va); + else + return iomap_pa2va(TEGRA_RNG1_BASE, TEGRA_RNG1_SIZE, va); +} + +/* Override the weak hw_get_random_bytes */ +TEE_Result hw_get_random_bytes(void *buf, size_t blen) +{ + return tegra_se_rng_get_random(buf, blen); +} diff --git a/optee/optee_os/core/drivers/tegra/common/tegra_driver_se.c b/optee/optee_os/core/drivers/tegra/common/tegra_driver_se.c new file mode 100644 index 0000000..ac15771 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/tegra_driver_se.c @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_DT +static const char *const tegra_se_dt_match_table[] = { + "nvidia,tegra194-se0", + "nvidia,tegra234-se0", +}; + +static TEE_Result tegra_se_dt_init(vaddr_t *va) +{ + void *fdt = NULL; + int node = -1; + uint32_t i = 0; + size_t size; + enum dt_map_dev_directive mapping = DT_MAP_AUTO; + + fdt = get_dt(); + if (!fdt) { + EMSG("%s: DTB is not present.", __func__); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + for (i = 0; i < ARRAY_SIZE(tegra_se_dt_match_table); i++) { + node = fdt_node_offset_by_compatible(fdt, 0, + tegra_se_dt_match_table[i]); + if (node >= 0) + break; + } + + if (node < 0) { + EMSG("%s: DT not found (%x).", __func__, node); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (dt_map_dev(fdt, node, va, &size, mapping) < 0) { + EMSG("%s: DT unable to map device address.", __func__); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} +#else +static TEE_Result tegra_se_dt_init(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +TEE_Result tegra_se_map_regs(vaddr_t *va) +{ + if (IS_ENABLED(CFG_DT)) + return tegra_se_dt_init(va); + else + return iomap_pa2va(TEGRA_SE_BASE, TEGRA_SE_SIZE, va); +} diff --git a/optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.c b/optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.c new file mode 100644 index 0000000..4b362a0 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/common/tegra_driver_srv_intf.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static tegra_drv_srv_intf_t *tegra_drv_srv_intf = NULL; + +TEE_Result tegra_se_aes_ecb_kdf(uint8_t *derived_key, size_t derived_key_len, + uint8_t *iv, size_t iv_len, + uint32_t keyslot) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->aes_ecb_kdf) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->aes_ecb_kdf(derived_key, derived_key_len, + iv, iv_len, + keyslot); +} + +TEE_Result tegra_se_aes_encrypt_cbc(uint8_t *src, size_t src_len, + uint8_t *dst, uint32_t keyslot, uint8_t *iv) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->aes_encrypt) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->aes_encrypt(src, src_len, dst, src_len, + SE_AES_OP_MODE_CBC, keyslot, iv); +} + +TEE_Result tegra_se_nist_sp_800_108_cmac_kdf(se_aes_keyslot_t keyslot, + uint32_t key_len, + char const *context, + uint32_t context_len, + char const *label, + uint32_t label_len, + uint32_t dk_len, + uint8_t *out_dk) +{ + if (!tegra_drv_srv_intf || + !tegra_drv_srv_intf->nist_sp_800_108_cmac_kdf) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->nist_sp_800_108_cmac_kdf(keyslot, key_len, + context, + context_len, + label, + label_len, + dk_len, + out_dk); +} + +TEE_Result tegra_se_write_aes_keyslot(uint8_t *input_key, uint32_t keylen, + uint32_t key_quad_sel, + se_aes_keyslot_t keyslot) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->write_aes_keyslot) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->write_aes_keyslot(input_key, keylen, + key_quad_sel, + keyslot); +} + +TEE_Result tegra_se_clear_aes_keyslots(void) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->clear_aes_keyslots) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->clear_aes_keyslots(); +} + +TEE_Result tegra_se_rng_get_random(void *data_buf, uint32_t data_len) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->rng_get_random) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->rng_get_random(data_buf, data_len); +} + +fuse_ecid_t* tegra_fuse_get_ecid(void) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->get_ecid) + return NULL; + + return tegra_drv_srv_intf->get_ecid(); +} + +TEE_Result tegra_fuse_get_bsi(uint32_t *val) +{ + if (!tegra_drv_srv_intf || !tegra_drv_srv_intf->get_bsi) + return TEE_ERROR_NOT_SUPPORTED; + + return tegra_drv_srv_intf->get_bsi(val); +} + +tegra_drv_srv_intf_t *tegra_drv_srv_intf_get(void) +{ + return tegra_drv_srv_intf; +} + +static TEE_Result tegra_drv_srv_intf_init(void) +{ + tegra_drv_srv_intf = calloc(1, sizeof(tegra_drv_srv_intf_t)); + if (tegra_drv_srv_intf == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} + +early_init_late(tegra_drv_srv_intf_init); diff --git a/optee/optee_os/core/drivers/tegra/sub.mk b/optee/optee_os/core/drivers/tegra/sub.mk new file mode 100644 index 0000000..5c8cba8 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/sub.mk @@ -0,0 +1,9 @@ +subdirs-y += common +subdirs-$(PLATFORM_FLAVOR_t194) += t194 +subdirs-$(PLATFORM_FLAVOR_t234) += t234 + +# Add source files and include header files from $(NV_OPTEE_DIR) +ifneq ("$(wildcard $(NV_OPTEE_DIR))","") +subdirs_ext-y += $(NV_OPTEE_DIR)/core/drivers/tegra +global-incdirs_ext-y += $(NV_OPTEE_DIR)/core/include +endif diff --git a/optee/optee_os/core/drivers/tegra/t194/fuse.c b/optee/optee_os/core/drivers/tegra/t194/fuse.c new file mode 100644 index 0000000..2b94a85 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t194/fuse.c @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FUSE_OPT_VENDOR_CODE_0 0x200 +#define FUSE_OPT_FAB_CODE_0 0x204 +#define FUSE_OPT_LOT_CODE_0_0 0x208 +#define FUSE_OPT_LOT_CODE_1_0 0x20c +#define FUSE_OPT_WAFER_ID_0 0x210 +#define FUSE_OPT_X_COORDINATE_0 0x214 +#define FUSE_OPT_Y_COORDINATE_0 0x218 +#define FUSE_OPT_OPS_RESERVED_0 0x220 +#define OPT_VENDOR_CODE_MASK 0xF +#define OPT_FAB_CODE_MASK 0x3F +#define OPT_LOT_CODE_1_MASK 0xfffffff +#define OPT_WAFER_ID_MASK 0x3F +#define OPT_X_COORDINATE_MASK 0x1FF +#define OPT_Y_COORDINATE_MASK 0x1FF +#define OPT_OPS_RESERVED_MASK 0x3F +#define ECID_ECID0_0_RSVD1_MASK 0x3F +#define ECID_ECID0_0_Y_MASK 0x1FF +#define ECID_ECID0_0_Y_RANGE 6 +#define ECID_ECID0_0_X_MASK 0x1FF +#define ECID_ECID0_0_X_RANGE 15 +#define ECID_ECID0_0_WAFER_MASK 0x3F +#define ECID_ECID0_0_WAFER_RANGE 24 +#define ECID_ECID0_0_LOT1_MASK 0x3 +#define ECID_ECID0_0_LOT1_RANGE 30 +#define ECID_ECID1_0_LOT1_MASK 0x3FFFFFF +#define ECID_ECID1_0_LOT0_MASK 0x3F +#define ECID_ECID1_0_LOT0_RANGE 26 +#define ECID_ECID2_0_LOT0_MASK 0x3FFFFFF +#define ECID_ECID2_0_FAB_MASK 0x3F +#define ECID_ECID2_0_FAB_RANGE 26 +#define ECID_ECID3_0_VENDOR_MASK 0xF + +static vaddr_t fuse_va_base = 0; +static fuse_ecid_t fuse_ecid; + +static TEE_Result fuse_get_bsi(uint32_t *val) +{ + (void) val; + return TEE_ERROR_NOT_SUPPORTED; +} + +static fuse_ecid_t* fuse_get_queried_ecid(void) +{ + return &fuse_ecid; +} + +static void fuse_query_ecid(void) +{ + uint32_t vendor, fab, wafer; + uint32_t lot0, lot1; + uint32_t x, y; + uint32_t rsvd1; + uint32_t reg; + + if (fuse_va_base == 0) + return; + + reg = io_read32(fuse_va_base + FUSE_OPT_VENDOR_CODE_0); + vendor = reg & OPT_VENDOR_CODE_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_FAB_CODE_0); + fab = reg & OPT_FAB_CODE_MASK; + + lot0 = io_read32(fuse_va_base + FUSE_OPT_LOT_CODE_0_0); + + lot1 = 0; + reg = io_read32(fuse_va_base + FUSE_OPT_LOT_CODE_1_0); + lot1 = reg & OPT_LOT_CODE_1_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_WAFER_ID_0); + wafer = reg & OPT_WAFER_ID_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_X_COORDINATE_0); + x = reg & OPT_X_COORDINATE_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_Y_COORDINATE_0); + y = reg & OPT_Y_COORDINATE_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_OPS_RESERVED_0); + rsvd1 = reg & OPT_OPS_RESERVED_MASK; + + reg = 0; + reg |= rsvd1 && ECID_ECID0_0_RSVD1_MASK; + reg |= (y & ECID_ECID0_0_Y_MASK) << ECID_ECID0_0_Y_RANGE; + reg |= (x & ECID_ECID0_0_X_MASK) << ECID_ECID0_0_X_RANGE; + reg |= (wafer & ECID_ECID0_0_WAFER_MASK) << ECID_ECID0_0_WAFER_RANGE; + reg |= (lot1 & ECID_ECID0_0_LOT1_MASK) << ECID_ECID0_0_LOT1_RANGE; + fuse_ecid.ecid[0] = reg; + + lot1 >>= 2; + + reg = 0; + reg |= lot1 & ECID_ECID1_0_LOT1_MASK; + reg |= (lot0 & ECID_ECID1_0_LOT0_MASK) << ECID_ECID1_0_LOT0_RANGE; + fuse_ecid.ecid[1] = reg; + + lot0 >>= 6; + + reg = 0; + reg |= lot0 & ECID_ECID2_0_LOT0_MASK; + reg |= (fab & ECID_ECID2_0_FAB_MASK) << ECID_ECID2_0_FAB_RANGE; + fuse_ecid.ecid[2] = reg; + + reg = 0; + reg |= vendor & ECID_ECID3_0_VENDOR_MASK; + fuse_ecid.ecid[3] = reg; +} + +static TEE_Result tegra_fuse_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + + rc = tegra_fuse_map_regs(&fuse_va_base); + + if (rc == TEE_SUCCESS) { + tegra_drv_srv_intf_t *drv_srv_intf; + + fuse_query_ecid(); + drv_srv_intf = tegra_drv_srv_intf_get(); + + if (drv_srv_intf != NULL) { + drv_srv_intf->get_ecid = fuse_get_queried_ecid; + drv_srv_intf->get_bsi = fuse_get_bsi; + } else { + return TEE_ERROR_NOT_SUPPORTED; + } + } + + return rc; +} + +service_init(tegra_fuse_init); diff --git a/optee/optee_os/core/drivers/tegra/t194/include/tegra_se_mgnt.h b/optee/optee_os/core/drivers/tegra/t194/include/tegra_se_mgnt.h new file mode 100644 index 0000000..de089b1 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t194/include/tegra_se_mgnt.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_SE_MGNT_H__ +#define __TEGRA_SE_MGNT_H__ + +#include +#include +#include +#include + +/* + * Acquires SE hardware mutex - + * This function should ALWAYS be called BEFORE interacting with SE. + * + * se_base [in] the virtual address of the SE base addr. + */ +TEE_Result se_mutex_acquire(vaddr_t se_base); + +/* + * Releases SE hardware mutex - + * This function should ALWAYS be called AFTER interacting with SE. + * + * se_base [in] the virtual address of the SE base addr. + */ +void se_mutex_release(vaddr_t se_base); + +/* + * Get the configuration of SE AES config register. + * + * mode [in] the SE AES operation mode. + * keylen [in] the key length. + */ +uint32_t se_aes_get_config(se_aes_op_mode mode, uint32_t keylen); + +/* + * Get the configuration of the AES crypto config register. + * + * mode [in] the SE AES operation mode. + * keylen [in] the key length. + * orig_iv [in] if this is original initial vector. + */ +uint32_t se_aes_get_crypto_config(se_aes_op_mode mode, uint32_t keyslot, + bool org_iv); + +/* + * Start the SE AES operation. + * + * se_base [in] the virtual address of the SE base addr. + * config [in] the SE AES config. + * crypto_config [in] the SE AEC crypto config. + * src [in] the pointer of the source buffer. + * src_len [in] the length of the source buffer. + * dst [out] the pointer of the destination buffer. + * dst_len [in] the length of the destination buffer. + */ +TEE_Result se_aes_start_operation(vaddr_t se_base, + uint32_t config, uint32_t crypto_config, + uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len); + +#endif diff --git a/optee/optee_os/core/drivers/tegra/t194/sub.mk b/optee/optee_os/core/drivers/tegra/t194/sub.mk new file mode 100644 index 0000000..89d69c8 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t194/sub.mk @@ -0,0 +1,8 @@ +incdirs-y += include +incdirs-y += ../common/include + +srcs-$(CFG_TEGRA_FUSE) += fuse.c +srcs-$(CFG_TEGRA_SE) += tegra_se_aes.c +srcs-$(CFG_TEGRA_SE) += tegra_se_mgnt.c +srcs-$(CFG_TEGRA_SE_RNG1) += tegra_se_rng1.c +srcs-$(CFG_RPMB_FS) += tegra_rpmb.c diff --git a/optee/optee_os/core/drivers/tegra/t194/tegra_rpmb.c b/optee/optee_os/core/drivers/tegra/t194/tegra_rpmb.c new file mode 100644 index 0000000..6281b76 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t194/tegra_rpmb.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool tegra_rpmb_key_is_ready = false; + +static uint8_t rollbackkeyiv[TEGRA_SE_AES_IV_SIZE] = { + 'n', 'v', '-', 's', 't', 'o', 'r', 'a', + 'g', 'e', '-', 'd', 'u', 'm', 'm', 'y' +}; + +static uint8_t rollbackkeysrc[TEGRA_SE_AES_BLOCK_SIZE * 2] = { + 0x81, 0x2A, 0x01, 0x43, 0x6B, 0x7C, 0x19, 0xAA, + 0xFF, 0x22, 0x38, 0x82, 0x0A, 0x67, 0x74, 0x08, + 0x30, 0x06, 0xCA, 0x11, 0x41, 0x49, 0x80, 0xED, + 0xE7, 0xBB, 0x61, 0x01, 0x2F, 0x56, 0x9D, 0xD3 +}; + +static uint8_t rollbackkey[TEGRA_SE_AES_BLOCK_SIZE * 2] = { 0 }; + +/* Override the weak tee_otp_get_rpmb_key */ +TEE_Result tee_otp_get_rpmb_key(uint8_t *key, size_t len) +{ + if (key == NULL) + return TEE_ERROR_BAD_PARAMETERS; + if (len != TEGRA_SE_AES_BLOCK_SIZE * 2) { + EMSG("Invalid RPMB key length"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (tegra_rpmb_key_is_ready) { + memcpy(key, rollbackkey, len); + return TEE_SUCCESS; + } else { + EMSG("Failed to get RPMB key"); + return TEE_ERROR_NO_DATA; + } +} + +bool plat_rpmb_key_is_ready(void) +{ + return tegra_rpmb_key_is_ready; +} + +static TEE_Result tegra_rpmb_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + se_aes_keyslot_t fuse_key_for_rpmb = SE_AES_KEYSLOT_KEK1G_128B; + + rc = tegra_se_aes_encrypt_cbc(rollbackkeysrc, sizeof(rollbackkeysrc), + rollbackkey, fuse_key_for_rpmb, rollbackkeyiv); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to derive rollback key (%x)", __func__, rc); + /* + * Do not return an error which will halt optee booting + * We have "tegra_rpmb_key_is_ready" to tell optee if the RPMB key is ready or not + */ + rc = TEE_SUCCESS; + } else { + IMSG("Tegra RPMB key generation succeeded."); + tegra_rpmb_key_is_ready = true; + } + + return rc; +} +driver_init(tegra_rpmb_init); diff --git a/optee/optee_os/core/drivers/tegra/t194/tegra_se_aes.c b/optee/optee_os/core/drivers/tegra/t194/tegra_se_aes.c new file mode 100644 index 0000000..1dcb667 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t194/tegra_se_aes.c @@ -0,0 +1,596 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WORD_SIZE sizeof(uint32_t) +#define WORD_SIZE_MASK 0x3 +#define QUAD_NUM_BYTES 16 +#define QUAD_NUM_WORDS 4 + +#define SE_KEYTABLE_SLOT_SHIFT 4 +#define SE_KEYTABLE_SLOT(x) (x << SE_KEYTABLE_SLOT_SHIFT) +#define SE_KEYTABLE_QUAD_SHIFT 2 +#define SE_KEYTABLE_WORD_SHIFT 0 +#define SE_KEYTABLE_QUAD(x) (x << SE_KEYTABLE_QUAD_SHIFT) +#define SE_KEYTABLE_WORD(x) (x << SE_KEYTABLE_WORD_SHIFT) + +#define SE_KEYTABLE_DATA0_REG_OFFSET 0x2c0 // SE0_AES0_CRYPTO_KEYTABLE_DATA_0 +#define SE_KEYTABLE_REG_OFFSET 0x2bc // SE0_AES0_CRYPTO_KEYTABLE_ADDR_0 + +struct tegra_se_cmac_context { + se_aes_keyslot_t keyslot; /* SE key slot */ + uint32_t keylen; /* key lenght */ + uint8_t k1[TEGRA_SE_AES_BLOCK_SIZE]; /* key 1 */ + uint8_t k2[TEGRA_SE_AES_BLOCK_SIZE]; /* key 2 */ + void *data; /* data for CMAC operation */ + uint32_t dlen; /* data length */ +}; +typedef struct tegra_se_cmac_context se_cmac_ctx; + +static vaddr_t se_va_base = 0; + +/* Forward declaration */ +static TEE_Result write_aes_keyslot(void *p_data, size_t data_len, + uint32_t key_quad_sel, + uint32_t key_slot_index); + +static TEE_Result se_aes_encrypt(uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len, se_aes_op_mode mode, + uint32_t keyslot, uint8_t *iv) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t crypto_cfg_value = 0, se_cfg_value = 0; + + se_cfg_value = se_aes_get_config(mode, TEGRA_SE_KEY_128_SIZE); + crypto_cfg_value = se_aes_get_crypto_config(mode, + keyslot, true); + + /* Accquire SE mutex */ + rc = se_mutex_acquire(se_va_base); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to accquire SE (%x)", __func__, rc); + return rc; + } + + if (iv) + write_aes_keyslot(iv, TEGRA_SE_AES_IV_SIZE, TEGRA_SE_AES_QUAD_ORG_IV, + keyslot); + + rc = se_aes_start_operation(se_va_base, + se_cfg_value, crypto_cfg_value, + src, src_len, dst, dst_len); + + /* Release SE mutex */ + se_mutex_release(se_va_base); + + return rc; +} + +static TEE_Result se_aes_ecb_kdf(uint8_t *derived_key, size_t derived_key_len, + uint8_t *iv, size_t iv_len, + uint32_t keyslot) +{ + if ((derived_key == NULL) || (iv == NULL)) { + EMSG("%s: Invalid arguments.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + if ((derived_key_len != TEE_AES_BLOCK_SIZE) || + (iv_len != TEE_AES_BLOCK_SIZE)) { + EMSG("%s: Invalid size arguments.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + return se_aes_encrypt(iv, iv_len, + derived_key, derived_key_len, + SE_AES_OP_MODE_ECB, keyslot, NULL); +} + +static inline void write_aes_keytable_word(vaddr_t se_base, uint32_t offset, + uint32_t val) +{ + io_write32(se_base + SE_KEYTABLE_REG_OFFSET, offset); + io_write32(se_base + SE_KEYTABLE_DATA0_REG_OFFSET, val); +} + +static TEE_Result write_aes_keyslot(void *p_data, size_t data_len, + uint32_t key_quad_sel, + uint32_t key_slot_index) +{ + uint32_t num_words, word_end; + uint32_t data_size; + uint32_t i = 0, val = 0; + uint32_t *p_key; + uint8_t quad = 0, pkt = 0; + + if (!p_data || !data_len) { + EMSG("%s: Invalid key data or length.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + p_key = p_data; + + if (key_slot_index >= SE_AES_KEYSLOT_COUNT) { + EMSG("%s: Invalid SE keyslot.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + if ((data_len & WORD_SIZE_MASK) != 0) { + EMSG("%s: Key length %ld is not a multiple of word size.", + __func__, data_len); + return TEE_ERROR_BAD_PARAMETERS; + } + + num_words = data_len / WORD_SIZE; + + /* Boundary check */ + word_end = SE_KEYTABLE_QUAD(key_quad_sel) + SE_KEYTABLE_WORD(num_words); + if (word_end > SE_KEYTABLE_SLOT(1)) { + EMSG("%s: Key range exceeds current key slot by %u words.", + __func__, word_end - SE_KEYTABLE_SLOT(1)); + return TEE_ERROR_BAD_PARAMETERS; + } + + quad = key_quad_sel; + if (key_quad_sel == TEGRA_SE_AES_QUAD_KEYS_256) + quad = TEGRA_SE_AES_QUAD_KEYS_128; + + /* Write data to the key table */ + data_size = QUAD_NUM_BYTES; + + do { + pkt = SE_KEYTABLE_SLOT(key_slot_index) | + SE_KEYTABLE_QUAD(quad); + + for (i = 0; i < data_size; i += 4, data_len -= 4) { + val = pkt | SE_KEYTABLE_WORD(i/WORD_SIZE); + write_aes_keytable_word(se_va_base, val, *p_key++); + } + + data_size = data_len; + quad = TEGRA_SE_AES_QUAD_KEYS_256; + } while(data_len); + + return TEE_SUCCESS; +} + +static TEE_Result clear_aes_keyslot(uint32_t keyslot, uint32_t slot_type) +{ + uint8_t zero_key[] = { + 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, + }; + uint32_t keylen; + + switch (slot_type) { + case TEGRA_SE_AES_QUAD_KEYS_256: + keylen = TEGRA_SE_KEY_256_SIZE; + break; + default: + keylen = TEGRA_SE_KEY_128_SIZE; + break; + }; + + return write_aes_keyslot(zero_key, keylen, slot_type, keyslot); +} + +static TEE_Result se_write_aes_keyslot(uint8_t *input_key, uint32_t keylen, + uint32_t key_quad_sel, + se_aes_keyslot_t keyslot) +{ + TEE_Result rc = TEE_SUCCESS; + + if ((keylen != TEGRA_SE_KEY_128_SIZE) && + (keylen != TEGRA_SE_KEY_256_SIZE)) { + EMSG("%s: Invalid key size.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + if ((key_quad_sel != TEGRA_SE_AES_QUAD_KEYS_128) && + (key_quad_sel != TEGRA_SE_AES_QUAD_KEYS_256) && + (key_quad_sel != TEGRA_SE_AES_QUAD_ORG_IV)) { + EMSG("%s: Invalid key QUAD selection.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Accquire SE mutex */ + rc = se_mutex_acquire(se_va_base); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to accquire SE (%x)", __func__, rc); + return rc; + } + + rc = write_aes_keyslot(input_key, keylen, key_quad_sel, keyslot); + + /* Release SE mutex */ + se_mutex_release(se_va_base); + + return rc; +} + +static TEE_Result se_clear_aes_keyslots(void) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t i; + + /* Accquire SE mutex */ + rc = se_mutex_acquire(se_va_base); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to accquire SE (%x)", __func__, rc); + return rc; + } + + for (i=0; i < TEGRA_SE_AES_QUAD_MAX; i++) { + clear_aes_keyslot(SE_AES_KEYSLOT_11, i); + clear_aes_keyslot(SE_AES_KEYSLOT_12, i); + clear_aes_keyslot(SE_AES_KEYSLOT_13, i); + + /* If the SSK is used in Kernel, don't clear it. */ + clear_aes_keyslot(SE_AES_KEYSLOT_15, i); + } + + /* Release SE mutex */ + se_mutex_release(se_va_base); + + return rc; +} + +static void make_sub_key(uint8_t *subkey, uint8_t *in, uint32_t size) +{ + uint8_t msb; + uint32_t i; + + msb = in[0] >> 7; + + /* Left shift one bit */ + subkey[0] = in[0] << 1; + for (i = 1; i < size; i++) { + subkey[i - 1] |= in[i] >> 7; + subkey[i] = in[i] << 1; + } + + if (msb) + subkey[size - 1] ^= 0x87; +} + +static se_cmac_ctx *se_cmac_new(void) +{ + se_cmac_ctx *se_cmac; + + se_cmac = calloc(1, sizeof(se_cmac_ctx)); + if (se_cmac == NULL) + EMSG("%s: Calloc failed.", __func__); + + return se_cmac; +} + +static void se_cmac_free(se_cmac_ctx *se_cmac) +{ + if (!se_cmac) + return; + + free(se_cmac); +} + +static TEE_Result se_cmac_init(se_cmac_ctx *se_cmac, se_aes_keyslot_t keyslot, + uint32_t keylen) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t config, crypto_config; + uint8_t *pbuf; + + if (se_cmac == NULL) { + EMSG("%s: Invalid SE CMAC context.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + if ((keylen != TEGRA_SE_KEY_128_SIZE) && + (keylen != TEGRA_SE_KEY_256_SIZE)) { + EMSG("%s: Invalid key size.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + pbuf = calloc(1, TEGRA_SE_AES_BLOCK_SIZE); + if (!pbuf) { + EMSG("%s: Calloc failed.", __func__); + return TEE_ERROR_OUT_OF_MEMORY; + } + + se_cmac->keyslot = keyslot; + se_cmac->keylen = keylen; + + /* + * Load the key + * + * 1. In case of using fuse key, the key should be pre-loaded into + * the dedicated keyslot before using Tegra SE AES-CMAC APIs. + * + * 2. In case of using user-defined key, please pre-load the key + * into the keyslot you want to use before using Tegra SE AES-CMAC + * APIs. + */ + + /* Accquire SE mutex */ + rc = se_mutex_acquire(se_va_base); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to accquire SE (%x)", __func__, rc); + goto se_init_fail; + } + + /* Load zero IV */ + write_aes_keyslot(pbuf, TEGRA_SE_AES_IV_SIZE, TEGRA_SE_AES_QUAD_ORG_IV, + keyslot); + + config = se_aes_get_config(SE_AES_OP_MODE_CBC, keylen); + crypto_config = se_aes_get_crypto_config(SE_AES_OP_MODE_CBC, keyslot, true); + rc = se_aes_start_operation(se_va_base, config, crypto_config, + pbuf, TEGRA_SE_AES_BLOCK_SIZE, + pbuf, TEGRA_SE_AES_BLOCK_SIZE); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to start SE operation.", __func__); + goto se_cmac_init_fail; + } + + make_sub_key(se_cmac->k1, pbuf, TEGRA_SE_AES_BLOCK_SIZE); + make_sub_key(se_cmac->k2, se_cmac->k1, TEGRA_SE_AES_BLOCK_SIZE); + +se_cmac_init_fail: + /* Release SE mutex */ + se_mutex_release(se_va_base); +se_init_fail: + free(pbuf); + + return rc; +} + +static TEE_Result se_cmac_update(se_cmac_ctx *se_cmac, void *data, + uint32_t dlen) +{ + if ((!se_cmac) || (!data) || (!dlen)) { + EMSG("%s: Invalid argument.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + se_cmac->data = data; + se_cmac->dlen = dlen; + + return TEE_SUCCESS; +} + +static TEE_Result se_cmac_final(se_cmac_ctx *se_cmac, void *out, + uint32_t *outlen) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t config, crypto_config; + uint32_t blocks_to_process, last_block_bytes = 0, i; + bool padding_needed = false, use_orig_iv = true; + uint8_t *iv, *buf, *last_block; + + if ((!se_cmac) || (!out) || (!outlen)) { + EMSG("%s: Invalid argument.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + iv = calloc(1, TEGRA_SE_AES_BLOCK_SIZE); + buf = calloc(1, TEGRA_SE_AES_BLOCK_SIZE); + last_block = calloc(1, TEGRA_SE_AES_BLOCK_SIZE); + if ((!iv) || (!buf) || (!last_block)) { + EMSG("%s: Calloc failed.", __func__); + return TEE_ERROR_OUT_OF_MEMORY; + } + + *outlen = TEGRA_SE_AES_BLOCK_SIZE; + + blocks_to_process = se_cmac->dlen / TEGRA_SE_AES_BLOCK_SIZE; + + /* Number of bytes less than block size */ + if ((se_cmac->dlen % TEGRA_SE_AES_BLOCK_SIZE) || !blocks_to_process) { + padding_needed = true; + last_block_bytes = se_cmac->dlen % TEGRA_SE_AES_BLOCK_SIZE; + } else { + blocks_to_process--; + last_block_bytes = TEGRA_SE_AES_BLOCK_SIZE; + } + + /* Accquire SE mutex */ + rc = se_mutex_acquire(se_va_base); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to accquire SE (%x)", __func__, rc); + goto se_fail; + } + + /* Processing all blocks except last block */ + if (blocks_to_process) { + uint32_t total = blocks_to_process * TEGRA_SE_AES_BLOCK_SIZE; + + /* Write zero IV */ + write_aes_keyslot(iv, TEGRA_SE_AES_IV_SIZE, + TEGRA_SE_AES_QUAD_ORG_IV, se_cmac->keyslot); + + config = se_aes_get_config(SE_AES_OP_MODE_CMAC, + se_cmac->keylen); + crypto_config = se_aes_get_crypto_config(SE_AES_OP_MODE_CMAC, + se_cmac->keyslot, + use_orig_iv); + rc = se_aes_start_operation(se_va_base, config, crypto_config, + se_cmac->data, total, + buf, TEGRA_SE_AES_BLOCK_SIZE); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to start SE operation.", __func__); + goto err_out; + } + + use_orig_iv = false; + } + + memcpy(last_block, + ((uint8_t *)se_cmac->data + se_cmac->dlen - last_block_bytes), + last_block_bytes); + + /* Processing last block */ + if (padding_needed) { + last_block[last_block_bytes] = 0x80; + + /* XOR with K2 */ + for (i = 0; i < TEGRA_SE_AES_BLOCK_SIZE; i++) + last_block[i] ^= se_cmac->k2[i]; + } else { + /* XOR with K1 */ + for (i = 0; i < TEGRA_SE_AES_BLOCK_SIZE; i++) + last_block[i] ^= se_cmac->k1[i]; + } + + if (use_orig_iv) + write_aes_keyslot(iv, TEGRA_SE_AES_IV_SIZE, + TEGRA_SE_AES_QUAD_ORG_IV, se_cmac->keyslot); + else + write_aes_keyslot(buf, TEGRA_SE_AES_IV_SIZE, + TEGRA_SE_AES_QUAD_UPDTD_IV, se_cmac->keyslot); + + config = se_aes_get_config(SE_AES_OP_MODE_CMAC, se_cmac->keylen); + crypto_config = se_aes_get_crypto_config(SE_AES_OP_MODE_CMAC, + se_cmac->keyslot, + use_orig_iv); + rc = se_aes_start_operation(se_va_base, config, crypto_config, + last_block, TEGRA_SE_AES_BLOCK_SIZE, + out, TEGRA_SE_AES_BLOCK_SIZE); + if (rc != TEE_SUCCESS) + EMSG("%s: Failed to start SE operation.", __func__); + +err_out: + /* Release SE mutex */ + se_mutex_release(se_va_base); +se_fail: + free(iv); + free(buf); + free(last_block); + + return rc; +} + +static TEE_Result se_nist_sp_800_108_cmac_kdf(se_aes_keyslot_t keyslot, + uint32_t key_len, + char const *context, + uint32_t context_len, + char const *label, + uint32_t label_len, + uint32_t dk_len, + uint8_t *out_dk) +{ + uint8_t counter[] = { 1 }, zero_byte[] = { 0 }; + uint32_t L[] = { TEE_U32_TO_BIG_ENDIAN(dk_len * 8) }; + uint8_t *message = NULL, *mptr; + uint32_t msg_len, i, n, cmac_len; + se_cmac_ctx *cmac_ctx = NULL; + TEE_Result rc = TEE_SUCCESS; + + if ((key_len != TEGRA_SE_KEY_128_SIZE) && + (key_len != TEGRA_SE_KEY_256_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + + if ((dk_len % TEE_AES_BLOCK_SIZE) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (!context || !label || !out_dk) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * Regarding to NIST-SP 800-108 + * message = counter || label || 0 || context || L + * + * A || B = The concatenation of binary strings A and B. + */ + msg_len = context_len + label_len + 2 + sizeof(L); + message = calloc(1, msg_len); + if (message == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Concatenate the messages */ + mptr = message; + memcpy(mptr, counter, sizeof(counter)); + mptr += sizeof(counter); + memcpy(mptr, label, label_len); + mptr += label_len; + memcpy(mptr, zero_byte, sizeof(zero_byte)); + mptr += sizeof(zero_byte); + memcpy(mptr, context, context_len); + mptr += context_len; + memcpy(mptr, L, sizeof(L)); + + /* SE AES-CMAC */ + cmac_ctx = se_cmac_new(); + if (cmac_ctx == NULL) { + rc = TEE_ERROR_OUT_OF_MEMORY; + goto kdf_error; + } + + /* n: iterations of the PRF count */ + n = dk_len / TEE_AES_BLOCK_SIZE; + + if (key_len == TEGRA_SE_KEY_256_SIZE) + se_cmac_init(cmac_ctx, keyslot, TEGRA_SE_KEY_256_SIZE); + else + se_cmac_init(cmac_ctx, keyslot, TEGRA_SE_KEY_128_SIZE); + + for (i = 0; i < n; i++) { + /* Update the counter */ + message[0] = i + 1; + + se_cmac_update(cmac_ctx, message, msg_len); + se_cmac_final(cmac_ctx, (out_dk + (i * TEE_AES_BLOCK_SIZE)), + &cmac_len); + } + + se_cmac_free(cmac_ctx); + +kdf_error: + free(message); + return rc; +} + +static TEE_Result tegra_se_init(void) +{ + TEE_Result rc; + + if (IS_ENABLED(CFG_DT)) + rc = tegra_se_map_regs(&se_va_base); + else + rc = iomap_pa2va(TEGRA_SE_BASE, TEGRA_SE_SIZE, &se_va_base); + + if (rc == TEE_SUCCESS) { + tegra_drv_srv_intf_t *drv_srv_intf; + + drv_srv_intf = tegra_drv_srv_intf_get(); + if (drv_srv_intf != NULL) { + drv_srv_intf->aes_ecb_kdf = se_aes_ecb_kdf; + drv_srv_intf->aes_encrypt = se_aes_encrypt; + drv_srv_intf->nist_sp_800_108_cmac_kdf = + se_nist_sp_800_108_cmac_kdf; + drv_srv_intf->write_aes_keyslot = se_write_aes_keyslot; + drv_srv_intf->clear_aes_keyslots = + se_clear_aes_keyslots; + } else { + return TEE_ERROR_NOT_SUPPORTED; + } + } + + return rc; +} + +service_init(tegra_se_init); diff --git a/optee/optee_os/core/drivers/tegra/t194/tegra_se_mgnt.c b/optee/optee_os/core/drivers/tegra/t194/tegra_se_mgnt.c new file mode 100644 index 0000000..ff49c0c --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t194/tegra_se_mgnt.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include + +#define TEGRA_SE_AES_BLOCK_SIZE 16 +#define TEGRA_SE_AES_IV_SIZE 16 +#define TEGRA_SE_KEY_128_SIZE 16 +#define TEGRA_SE_KEY_256_SIZE 32 + +#define SE_INT_STATUS_REG_OFFSET 0x2f0 // SE0_AES0_INT_STATUS_0 + +#define SE_CRYPTO_KEY_INDEX_SHIFT 24 // SE0_AES0_CRYPTO_CONFIG_0_KEY_INDEX_SHIFT +#define SE_CRYPTO_KEY_INDEX(x) (x << SE_CRYPTO_KEY_INDEX_SHIFT) + +#define SE_CRYPTO_CORE_SEL_SHIFT 9 // SE0_AES0_CRYPTO_CONFIG_0_CORE_SEL_SHIFT +#define CORE_ENCRYPT 1 +#define SE_CRYPTO_CORE_SEL(x) (x << SE_CRYPTO_CORE_SEL_SHIFT) + +#define SE_CRYPTO_IV_SEL_SHIFT 7 +#define IV_ORIGINAL 0 +#define IV_UPDATED 1 +#define SE_CRYPTO_IV_SEL(x) (x << SE_CRYPTO_IV_SEL_SHIFT) + +#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5 // SE0_AES0_CRYPTO_CONFIG_0_VCTRAM_SEL_SHIFT +#define VCTRAM_AESOUT 2 +#define SE_CRYPTO_VCTRAM_SEL(x) (x << SE_CRYPTO_VCTRAM_SEL_SHIFT) + +#define SE_CRYPTO_XOR_POS_SHIFT 1 // SE0_AES0_CRYPTO_CONFIG_0_XOR_POS_SHIFT +#define XOR_BYPASS 0 +#define XOR_TOP 2 +#define SE_CRYPTO_XOR_POS(x) (x << SE_CRYPTO_XOR_POS_SHIFT) + +#define SE_CRYPTO_HASH_SHIFT 0 // SE0_AES0_CRYPTO_CONFIG_0_HASH_ENB_SHIFT +#define HASH_DISABLE 0 +#define HASH_ENABLE 1 +#define SE_CRYPTO_HASH(x) (x << SE_CRYPTO_HASH_SHIFT) + +#define SE_CONFIG_ENC_MODE_SHIFT 24 // SE0_AES0_CONFIG_0_ENC_MODE_SHIFT +#define AES_MODE_KEY128 0 // SE_MODE_PKT_AESAES_MODE_KEY128 +#define AES_MODE_KEY256 2 // SE_MODE_PKT_AESAES_MODE_KEY256 +#define SE_CONFIG_ENC_MODE(x) (x << SE_CONFIG_ENC_MODE_SHIFT) + +#define SE_CONFIG_ENC_ALG_SHIFT 12 // SE0_AES0_CONFIG_0_ENC_ALG_SHIFT +#define SE_CONFIG_DEC_ALG_SHIFT 8 // SE0_AES0_CONFIG_0_DEC_ALG_SHIFT +#define ALG_NOP 0 +#define ALG_AES_ENC 1 +#define SE_CONFIG_ENC_ALG(x) (x << SE_CONFIG_ENC_ALG_SHIFT) +#define SE_CONFIG_DEC_ALG(x) (x << SE_CONFIG_DEC_ALG_SHIFT) + +#define SE_CONFIG_DST_SHIFT 2 // SE0_AES0_CONFIG_0_DST_SHIFT +#define DST_MEMORY 0 +#define SE_CONFIG_DST(x) (x << SE_CONFIG_DST_SHIFT) + +#define SE_CONFIG_REG_OFFSET 0x204 // SE0_AES0_CONFIG_0 +#define SE_CRYPTO_REG_OFFSET 0x208 // SE0_AES0_CRYPTO_CONFIG_0 + +#define SE0_AES0_IN_ADDR_0 0x20c +#define SE0_AES0_IN_ADDR_HI_0 0x210 +#define SE0_AES0_OUT_ADDR_0 0x214 +#define SE0_AES0_OUT_ADDR_HI_0 0x218 +#define MSB_SHIFT 24 + +#define SE_BLOCK_COUNT_REG_OFFSET 0x22c // SE0_AES0_CRYPTO_LAST_BLOCK_0 +#define SE_OPERATION_REG_OFFSET 0x238 // SE0_AES0_OPERATION_0 +#define LASTBUF_TRUE 16 +#define SE_OPERATION_SHIFT 0 +#define OP_START (1 | (1 << LASTBUF_TRUE)) +#define SE_OPERATION(x) (x << SE_OPERATION_SHIFT) + +#define SE_STATUS 0x2f4 // SE0_AES0_STATUS_0 + +#define SE0_MUTEX_REQUEST_RELEASE 0x50 +#define SE0_MUTEX_REQUEST_RELEASE_0_LOCK_TRUE 0x1 +#define SE0_MUTEX_STATUS 0x64 + +#define MAX_POLL_ATTEMPTS_NO_SLEEP 100 +#define MUTEX_POLL_WAIT_INTERVAL_ZERO 0 + +static TEE_Result acquire_sap_hw_mutex(vaddr_t se_base, uint32_t sleep_time, + uint32_t poll_attempts) +{ + uint32_t count = 0; + uint32_t data = 0; + + while (count < poll_attempts) { + /* + * When MUTEX_REQUEST_RELEASE register is 0, read the + * register will set the LOCK to be 1 (atomic), then it means + * the MUTEX had been gained by the read request. + * + * If the mutex is already locked, then any read request to this + * register will get the return value of 0, even from the MUTEX + * owner. + */ + if ((io_read32(se_base + SE0_MUTEX_REQUEST_RELEASE) & + SE0_MUTEX_REQUEST_RELEASE_0_LOCK_TRUE) == 1) + return TEE_SUCCESS; + + if (sleep_time) + udelay(sleep_time); + count++; + } + + /* Unsuccessful */ + data = io_read32(se_base + SE0_MUTEX_STATUS); + EMSG("%s: ERROR. Acquire mutex failed." + "mutex status: 0x%x\n", __func__, data); + + return TEE_ERROR_BUSY; +} + +static void release_sap_hw_mutex(vaddr_t se_base) +{ + io_write32(se_base + SE0_MUTEX_REQUEST_RELEASE, + SE0_MUTEX_REQUEST_RELEASE_0_LOCK_TRUE); +} + +TEE_Result se_mutex_acquire(vaddr_t se_base) +{ + if (!se_base) { + EMSG("%s: SE is not available.", __func__); + return TEE_ERROR_ACCESS_DENIED; + } + + return acquire_sap_hw_mutex(se_base, MUTEX_POLL_WAIT_INTERVAL_ZERO, + MAX_POLL_ATTEMPTS_NO_SLEEP); +} + +void se_mutex_release(vaddr_t se_base) +{ + uint32_t intstat; + + /* Clear SE interrupt stat after the usage */ + intstat = io_read32(se_base + SE_INT_STATUS_REG_OFFSET); + io_write32(se_base + SE_INT_STATUS_REG_OFFSET, intstat); + /* Readback to flush */ + intstat = io_read32(se_base + SE_INT_STATUS_REG_OFFSET); + + release_sap_hw_mutex(se_base); +} + +uint32_t se_aes_get_config(se_aes_op_mode mode, uint32_t keylen) +{ + uint32_t val = 0; + + switch (mode) { + case SE_AES_OP_MODE_CBC: + case SE_AES_OP_MODE_CMAC: + case SE_AES_OP_MODE_ECB: + val = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | + SE_CONFIG_DEC_ALG(ALG_NOP); + break; + default: + break; + }; + + if (keylen == TEGRA_SE_KEY_256_SIZE) + val |= SE_CONFIG_ENC_MODE(AES_MODE_KEY256); + else + val |= SE_CONFIG_ENC_MODE(AES_MODE_KEY128); + + val |= SE_CONFIG_DST(DST_MEMORY); + + return val; +} + +uint32_t se_aes_get_crypto_config(se_aes_op_mode mode, uint32_t keyslot, + bool org_iv) +{ + uint32_t val = 0; + + switch (mode) { + case SE_AES_OP_MODE_CBC: + case SE_AES_OP_MODE_CMAC: + val = SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | + SE_CRYPTO_XOR_POS(XOR_TOP) | + SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); + break; + case SE_AES_OP_MODE_ECB: + val = SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | + SE_CRYPTO_XOR_POS(XOR_BYPASS) | + SE_CRYPTO_CORE_SEL(CORE_ENCRYPT); + break; + default: + break; + }; + + val |= SE_CRYPTO_KEY_INDEX(keyslot) | + (org_iv ? SE_CRYPTO_IV_SEL(IV_ORIGINAL) : + SE_CRYPTO_IV_SEL(IV_UPDATED)); + + if (mode == SE_AES_OP_MODE_CMAC) + val |= SE_CRYPTO_HASH(HASH_ENABLE); + else + val |= SE_CRYPTO_HASH(HASH_DISABLE); + + return val; +} + +TEE_Result se_aes_start_operation(vaddr_t se_base, + uint32_t config, uint32_t crypto_config, + uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len) +{ + paddr_t phy_src, phy_dst; + + phy_src = virt_to_phys((void *)src); + phy_dst = virt_to_phys((void *)dst); + if (!phy_src || !phy_dst) { + EMSG("%s: virt_to_phys failure.", __func__); + return TEE_ERROR_GENERIC; + } + + io_write32(se_base + SE_CONFIG_REG_OFFSET, config); + io_write32(se_base + SE_CRYPTO_REG_OFFSET, crypto_config); + + io_write32(se_base + SE0_AES0_IN_ADDR_0, (uint32_t)phy_src); + io_write32(se_base + SE0_AES0_IN_ADDR_HI_0, + ((uint32_t)(phy_src >> 32) << MSB_SHIFT) | src_len); + io_write32(se_base + SE0_AES0_OUT_ADDR_0, (uint32_t)phy_dst); + io_write32(se_base + SE0_AES0_OUT_ADDR_HI_0, + ((uint32_t)(phy_dst >> 32) << MSB_SHIFT) | dst_len); + + io_write32(se_base + SE_BLOCK_COUNT_REG_OFFSET, src_len/16 - 1); + io_write32(se_base + SE_OPERATION_REG_OFFSET, SE_OPERATION(OP_START)); + + while (io_read32(se_base + SE_STATUS)) + ; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/tegra/t194/tegra_se_rng1.c b/optee/optee_os/core/drivers/tegra/t194/tegra_se_rng1.c new file mode 100644 index 0000000..1581548 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t194/tegra_se_rng1.c @@ -0,0 +1,392 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ELP_ENABLE 1 +#define ELP_DISABLE 0 +#define ELP_FALSE 0 +#define ELP_TRUE 1 + +#define SE_RNG1_CTRL_OFFSET 0xf00 + +#define SE_RNG1_MODE_OFFSET 0xf04 +#define SE_RNG1_MODE_PRED_RESIST_SHIFT 3 +#define SE_RNG1_MODE_SEC_ALG 0 +#define SE_RNG1_MODE_PRED_RESIST_EN \ + (ELP_ENABLE << SE_RNG1_MODE_PRED_RESIST_SHIFT) +#define SE_RNG1_MODE_SEC_ALG_AES_256 \ + (ELP_TRUE << SE_RNG1_MODE_SEC_ALG) + +#define SE_RNG1_SMODE_OFFSET 0xf08 +#define SE_RNG1_SMODE_MAX_REJECTS_SHIFT 2 +#define SE_RNG1_SMODE_SECURE_SHIFT 1 +#define SE_RNG1_SMODE_MAX_REJECTS_DEFAULT \ + (0xa << SE_RNG1_SMODE_MAX_REJECTS_SHIFT) +#define SE_RNG1_SMODE_SECURE_EN \ + (ELP_ENABLE << SE_RNG1_SMODE_SECURE_SHIFT) + +#define SE_RNG1_STAT_OFFSET 0xf0c +#define SE_RNG1_STAT_BUSY_SHIFT 31 +#define SE_RNG1_STAT_BUSY(x) \ + (x << SE_RNG1_STAT_BUSY_SHIFT) + +#define SE_RNG1_IE_OFFSET 0xf10 +#define SE_RNG1_INT_ENABLE_OFFSET 0xfc0 + +#define SE_RNG1_ISTAT_OFFSET 0xf14 +#define SE_RNG1_ISTAT_CLEAR 0x1f +#define SE_RNG1_ISTAT_DONE_OFFSET 4 +#define SE_RNG1_ISTAT_DONE \ + (ELP_TRUE << SE_RNG1_ISTAT_DONE_OFFSET) + +#define SE_RNG1_ALARMS_OFFSET 0xf18 +#define SE_RNG1_ALARMS_CLEAR 0x1f + +#define SE_RNG1_RAND0_OFFSET 0xf24 + +#define SE_RNG1_INT_STATUS_OFFSET 0xfc4 +#define SE_RNG1_INT_STATUS_CLEAR 0x30000 +#define SE_RNG1_INT_STATUS_MUTEX_TIMEOUT 0x20000 + +#define SE_RNG1_ECTL_OFFSET 0xfc8 +#define SE_RNG1_ECTL_RESET_SHIFT 5 +#define SE_RNG1_ECTL_RESET(x) \ + (x << SE_RNG1_ECTL_RESET_SHIFT) + +#define SE_RNG1_MUTEX_WATCHDOG_COUNTER_OFFSET 0xfd0 +#define SE_RNG1_MUTEX_TIMEOUT_ACTION_OFFSET 0xfd4 +#define SE_RNG1_MUTEX_TIMEOUT_ACTION 0xb +#define SE_RNG1_MUTEX_REQUEST_RELEASE_OFFSET 0xfd8 + +/* + * Number of bytes that are generated each time 'gen_random' is executed. + * RNG1 generates 128 random bits (16 bytes) at a time. + */ +#define RNG1_NUM_BYTES_PER_GEN 16 + +/* + * Maximum number of bytes allowed in one se_rng1_get_random() call. + */ +#define RNG1_MAX_BYTES (1024 * 32) + +#define NUM_CTS_PER_GEN (0x0150 * 4) +#define NUM_EXTRA_CTS (0x0ff000 * 4) +#define MUTEX_POLL_INTERVAL_US 10 +#define MUTEX_POLL_MAX_ATTEMPTS 20 + +typedef enum { + RNG1_CMD_NOP = 0, + RNG1_CMD_GEN_NOISE = 1, + RNG1_CMD_GEN_NONCE = 2, + RNG1_CMD_CREATE_STATE = 3, + RNG1_CMD_RENEW_STATE = 4, + RNG1_CMD_REFRESH_ADDIN = 5, + RNG1_CMD_GEN_RANDOM = 6, + RNG1_CMD_ADVANCE_STATE = 7, + RNG1_CMD_KAT = 8, + RNG1_CMD_ZEROIZE = 15 +} se_rng1_cmd_t; + +/* Internal functions */ +static TEE_Result se_rng1_accquire_mutex(uint32_t mutex_timeout); +static void se_rng1_release_mutex(void); +static TEE_Result se_rng1_check_alarms(void); +static void se_rng1_clear_alarms(void); +static TEE_Result se_rng1_wait_for_idle(void); +static TEE_Result se_rng1_write_settings(void); +static TEE_Result se_rng1_execute_cmd(se_rng1_cmd_t cmd); + +static vaddr_t rng1_va_base = 0; + +static TEE_Result se_rng1_accquire_mutex(uint32_t mutex_timeout) +{ + uint32_t i; + + if (!rng1_va_base) { + EMSG("%s: RNG1 is not available.", __func__); + return TEE_ERROR_ACCESS_DENIED; + } + + for (i = 0; i < MUTEX_POLL_MAX_ATTEMPTS; i++) { + uint32_t val; + + val = io_read32(rng1_va_base + + SE_RNG1_MUTEX_REQUEST_RELEASE_OFFSET); + + if (val == 0x01) { + io_write32(rng1_va_base + + SE_RNG1_MUTEX_TIMEOUT_ACTION_OFFSET, + SE_RNG1_MUTEX_TIMEOUT_ACTION); + io_write32(rng1_va_base + SE_RNG1_INT_STATUS_OFFSET, + SE_RNG1_INT_STATUS_CLEAR); + io_write32(rng1_va_base + + SE_RNG1_MUTEX_WATCHDOG_COUNTER_OFFSET, + mutex_timeout); + return TEE_SUCCESS; + } + + udelay(MUTEX_POLL_INTERVAL_US); + } + + EMSG("%s: ERROR: RNG1 could not acquire mutex.", __func__); + return TEE_ERROR_BUSY; +} + +static void se_rng1_release_mutex(void) +{ + io_write32(rng1_va_base + SE_RNG1_MUTEX_REQUEST_RELEASE_OFFSET, 0x01); +} + +static TEE_Result se_rng1_wait_for_idle(void) +{ + uint32_t stat; + + stat = io_read32(rng1_va_base + SE_RNG1_STAT_OFFSET); + + while (stat & SE_RNG1_STAT_BUSY(ELP_TRUE)) { + uint32_t int_stat; + + int_stat = io_read32(rng1_va_base + SE_RNG1_INT_STATUS_OFFSET); + if (int_stat & SE_RNG1_INT_STATUS_MUTEX_TIMEOUT) { + EMSG("%s: ERROR: RNG1 operation time out.", __func__); + /* Reset RNG1 */ + io_write32(rng1_va_base + SE_RNG1_ECTL_OFFSET, + SE_RNG1_ECTL_RESET(ELP_TRUE)); + + return TEE_ERROR_BUSY; + } + + stat = io_read32(rng1_va_base + SE_RNG1_STAT_OFFSET); + } + + return TEE_SUCCESS; +} + +static TEE_Result se_rng1_check_alarms(void) +{ + uint32_t val; + + val = io_read32(rng1_va_base + SE_RNG1_ALARMS_OFFSET); + if (val) { + EMSG("%s: ERROR: RNG1 ALARMS error.", __func__); + se_rng1_clear_alarms(); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static void se_rng1_clear_alarms(void) +{ + io_write32(rng1_va_base + SE_RNG1_ALARMS_OFFSET, SE_RNG1_ALARMS_CLEAR); +} + +static TEE_Result se_rng1_write_settings(void) +{ + TEE_Result rc = TEE_SUCCESS; + + /* Clear ISTAT and ALARMS */ + se_rng1_clear_alarms(); + io_write32(rng1_va_base + SE_RNG1_ISTAT_OFFSET, SE_RNG1_ISTAT_CLEAR); + + /* Disable all interrupts */ + io_write32(rng1_va_base + SE_RNG1_IE_OFFSET, 0x0); + io_write32(rng1_va_base + SE_RNG1_INT_ENABLE_OFFSET, 0x0); + + rc = se_rng1_wait_for_idle(); + if (rc != TEE_SUCCESS) + return rc; + + /* Enable secure mode */ + io_write32(rng1_va_base + SE_RNG1_SMODE_OFFSET, + SE_RNG1_SMODE_MAX_REJECTS_DEFAULT | SE_RNG1_SMODE_SECURE_EN); + + /* Configure RNG1 mode */ + io_write32(rng1_va_base + SE_RNG1_MODE_OFFSET, + SE_RNG1_MODE_PRED_RESIST_EN | SE_RNG1_MODE_SEC_ALG_AES_256); + + return TEE_SUCCESS; +} + +static TEE_Result se_rng1_execute_cmd(se_rng1_cmd_t cmd) +{ + TEE_Result rc; + + /* Write cmd to the CTRL register */ + io_write32(rng1_va_base + SE_RNG1_CTRL_OFFSET, cmd); + + rc = se_rng1_wait_for_idle(); + if (rc != TEE_SUCCESS) { + EMSG("%s: ERROR: command = %x.", __func__, cmd); + return rc; + } + + io_write32(rng1_va_base + SE_RNG1_ISTAT_OFFSET, SE_RNG1_ISTAT_DONE); + + return TEE_SUCCESS; +} + +static TEE_Result se_rng1_get_random(void *data, uint32_t data_len) +{ + TEE_Result rc = TEE_SUCCESS, err; + uint8_t *data_buf = data; + uint32_t num_gens, num_extra_bytes, mutex_timeout, i; + + if ((data_buf == NULL) || + (data_len == 0) || + (data_len > RNG1_MAX_BYTES)) + return TEE_ERROR_BAD_PARAMETERS; + + num_gens = data_len / RNG1_NUM_BYTES_PER_GEN; + num_extra_bytes = data_len % RNG1_NUM_BYTES_PER_GEN; + mutex_timeout = (num_gens * NUM_CTS_PER_GEN) + NUM_EXTRA_CTS; + + rc = se_rng1_accquire_mutex(mutex_timeout); + if (rc != TEE_SUCCESS) + return rc; + + /* Configure RNG1 */ + rc = se_rng1_write_settings(); + if (rc != TEE_SUCCESS) + goto exit; + + /* Zeroize to reset the state */ + rc = se_rng1_execute_cmd(RNG1_CMD_ZEROIZE); + if (rc != TEE_SUCCESS) + goto exit; + + /* Generate a random seed and instantiate a new state */ + rc = se_rng1_execute_cmd(RNG1_CMD_GEN_NOISE); + if (rc != TEE_SUCCESS) + goto exit; + rc = se_rng1_execute_cmd(RNG1_CMD_CREATE_STATE); + if (rc != TEE_SUCCESS) + goto exit_zeroize; + + /* Re-generate the seed then renew the stat */ + rc = se_rng1_execute_cmd(RNG1_CMD_GEN_NOISE); + if (rc != TEE_SUCCESS) + goto exit_zeroize; + rc = se_rng1_execute_cmd(RNG1_CMD_RENEW_STATE); + if (rc != TEE_SUCCESS) + goto exit_zeroize; + + /* Loop until we've generated a sufficient number of random bytes */ + for (i = 0; i < num_gens; i++) { + rc = se_rng1_execute_cmd(RNG1_CMD_GEN_RANDOM); + if (rc != TEE_SUCCESS) + goto exit_zeroize; + + memcpy((data_buf + RNG1_NUM_BYTES_PER_GEN * i), + (void*)(rng1_va_base + SE_RNG1_RAND0_OFFSET), RNG1_NUM_BYTES_PER_GEN); + + rc = se_rng1_execute_cmd(RNG1_CMD_ADVANCE_STATE); + if (rc != TEE_SUCCESS) + goto exit_zeroize; + rc = se_rng1_execute_cmd(RNG1_CMD_GEN_NOISE); + if (rc != TEE_SUCCESS) + goto exit_zeroize; + rc = se_rng1_execute_cmd(RNG1_CMD_RENEW_STATE); + if (rc != TEE_SUCCESS) + goto exit_zeroize; + } + + if (num_extra_bytes != 0) { + rc = se_rng1_execute_cmd(RNG1_CMD_GEN_RANDOM); + if (rc != TEE_SUCCESS) + goto exit_zeroize; + + memcpy((data_buf + RNG1_NUM_BYTES_PER_GEN * num_gens), + (void*)(rng1_va_base + SE_RNG1_RAND0_OFFSET), num_extra_bytes); + } + +exit_zeroize: + /* Zeroize for security purpose */ + err = se_rng1_execute_cmd(RNG1_CMD_ZEROIZE); + if (rc == TEE_SUCCESS) + rc = err; + +exit: + err = se_rng1_check_alarms(); + if (rc == TEE_SUCCESS) + rc = err; + + se_rng1_release_mutex(); + + return rc; +} + +static TEE_Result se_rng1_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + + rc = se_rng1_accquire_mutex(NUM_EXTRA_CTS); + if (rc != TEE_SUCCESS) + return rc; + + rc = se_rng1_wait_for_idle(); + if (rc != TEE_SUCCESS) + goto exit; + + rc = se_rng1_check_alarms(); + if (rc != TEE_SUCCESS) + goto exit; + + /* Clear ISTAT register */ + io_write32(rng1_va_base + SE_RNG1_ISTAT_OFFSET, SE_RNG1_ISTAT_CLEAR); + +exit: + se_rng1_release_mutex(); + + return rc; +} + +static TEE_Result tegra_se_rng1_init(void) +{ + TEE_Result rc; + + rc = tegra_rng1_map_regs(&rng1_va_base); + if (rc != TEE_SUCCESS) + return rc; + + rc = se_rng1_init(); + + return rc; +} + +/* Override the weak plat_rng_init */ +void plat_rng_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + + rc = tegra_se_rng1_init(); + + if (rc == TEE_SUCCESS) { + tegra_drv_srv_intf_t *drv_srv_intf; + + drv_srv_intf = tegra_drv_srv_intf_get(); + if (drv_srv_intf != NULL) + drv_srv_intf->rng_get_random = se_rng1_get_random; + } else { + EMSG("%s: Failed to initialize RNG (%x).", __func__, rc); + panic(); + } +} diff --git a/optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h b/optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h new file mode 100644 index 0000000..70e80a6 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc.h @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef __TEGRA_SE_CCC_H__ +#define __TEGRA_SE_CCC_H__ + +#include + +typedef int status_t; +typedef enum optee_tegra_se_cdev_id_e { + OPTEE_TEGRA_SE_CDEV_SE0 = 0, /**< SE0 device [0] */ + OPTEE_TEGRA_SE_CDEV_PKA1 = 1, /**< PKA device [1] */ + OPTEE_TEGRA_SE_CDEV_RNG1 = 2, /**< RNG1 device [2] */ +} optee_tegra_se_cdev_id_t; + +status_t tegra_init_crypto_devices(void); +status_t tegra_se_map_device(optee_tegra_se_cdev_id_t device_id, void **base_va); +status_t tegra_se_ccc_configure_se0(vaddr_t base); +status_t tegra_se_ccc_configure_rng1(vaddr_t base); +status_t tegra_se_ccc_aes_encrypt(uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len, se_aes_op_mode mode, + uint32_t keyslot, uint32_t key_len, uint8_t *iv); +status_t tegra_se_ccc_set_aes_keyslot(uint32_t keyslot, uint8_t *key, + uint32_t key_len, se_aes_op_mode mode); +status_t tegra_se_ccc_clear_aes_keyslot(uint32_t keyslot); +status_t tegra_se_ccc_aes_genrnd(uint8_t *output, uint32_t output_len); + +#if defined(CFG_TEGRA_SE_USE_TEST_KEYS) +status_t tegra_se_ccc_set_test_oem_keys(const uint8_t *oem_k1, const uint8_t *oem_k2); +#endif + +#endif diff --git a/optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc_errno.h b/optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc_errno.h new file mode 100644 index 0000000..8281fb4 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/include/tegra_se_ccc_errno.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef __TEGRA_SE_CCC_ERRNO_H__ +#define __TEGRA_SE_CCC_ERRNO_H__ + +#define NO_ERROR (0) +#define ERR_GENERIC (-1) +#define ERR_NOT_FOUND (-2) +#define ERR_NOT_READY (-3) +#define ERR_NO_MSG (-4) +#define ERR_NO_MEMORY (-5) +#define ERR_ALREADY_STARTED (-6) +#define ERR_NOT_VALID (-7) +#define ERR_INVALID_ARGS (-8) +#define ERR_NOT_ENOUGH_BUFFER (-9) +#define ERR_NOT_SUSPENDED (-10) +#define ERR_OBJECT_DESTROYED (-11) +#define ERR_NOT_BLOCKED (-12) +#define ERR_TIMED_OUT (-13) +#define ERR_ALREADY_EXISTS (-14) +#define ERR_CHANNEL_CLOSED (-15) +#define ERR_OFFLINE (-16) +#define ERR_NOT_ALLOWED (-17) +#define ERR_BAD_PATH (-18) +#define ERR_ALREADY_MOUNTED (-19) +#define ERR_IO (-20) +#define ERR_NOT_DIR (-21) +#define ERR_NOT_FILE (-22) +#define ERR_RECURSE_TOO_DEEP (-23) +#define ERR_NOT_SUPPORTED (-24) +#define ERR_TOO_BIG (-25) +#define ERR_CANCELLED (-26) +#define ERR_NOT_IMPLEMENTED (-27) +#define ERR_CHECKSUM_FAIL (-28) +#define ERR_CRC_FAIL (-29) +#define ERR_CMD_UNKNOWN (-30) +#define ERR_BAD_STATE (-31) +#define ERR_BAD_LEN (-32) +#define ERR_BUSY (-33) +#define ERR_THREAD_DETACHED (-34) +#define ERR_I2C_NACK (-35) +#define ERR_ALREADY_EXPIRED (-36) +#define ERR_OUT_OF_RANGE (-37) +#define ERR_NOT_CONFIGURED (-38) +#define ERR_NOT_MOUNTED (-39) +#define ERR_FAULT (-40) +#define ERR_NO_RESOURCES (-41) +#define ERR_BAD_HANDLE (-42) +#define ERR_ACCESS_DENIED (-43) + +#define ERR_SIGNATURE_INVALID (-50) + +#endif diff --git a/optee/optee_os/core/drivers/tegra/t234/sub.mk b/optee/optee_os/core/drivers/tegra/t234/sub.mk new file mode 100644 index 0000000..2baf1a1 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/sub.mk @@ -0,0 +1,6 @@ +incdirs-y += include +incdirs-y += ../common/include + +srcs-$(CFG_TEGRA_SE) += tegra_se_aes_rng.c +srcs-$(CFG_TEGRA_FUSE) += tegra_fuse.c +srcs-$(CFG_RPMB_FS) += tegra_rpmb.c diff --git a/optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c b/optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c new file mode 100644 index 0000000..61a1ff5 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/tegra_fuse.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static vaddr_t fuse_va_base = 0; +static fuse_ecid_t fuse_ecid; + +#define FUSE_OPT_VENDOR_CODE_0 0x200 +#define FUSE_OPT_FAB_CODE_0 0x204 +#define FUSE_OPT_LOT_CODE_0_0 0x208 +#define FUSE_OPT_LOT_CODE_1_0 0x20c +#define FUSE_OPT_WAFER_ID_0 0x210 +#define FUSE_OPT_X_COORDINATE_0 0x214 +#define FUSE_OPT_Y_COORDINATE_0 0x218 +#define FUSE_OPT_OPS_RESERVED_0 0x220 +#define FUSE_BOOT_SECURITY_INFO_0 0x268 +#define OPT_VENDOR_CODE_MASK 0xF +#define OPT_FAB_CODE_MASK 0x3F +#define OPT_LOT_CODE_1_MASK 0xfffffff +#define OPT_WAFER_ID_MASK 0x3F +#define OPT_X_COORDINATE_MASK 0x1FF +#define OPT_Y_COORDINATE_MASK 0x1FF +#define OPT_OPS_RESERVED_MASK 0x3F +#define ECID_ECID0_0_RSVD1_MASK 0x3F +#define ECID_ECID0_0_Y_MASK 0x1FF +#define ECID_ECID0_0_Y_RANGE 6 +#define ECID_ECID0_0_X_MASK 0x1FF +#define ECID_ECID0_0_X_RANGE 15 +#define ECID_ECID0_0_WAFER_MASK 0x3F +#define ECID_ECID0_0_WAFER_RANGE 24 +#define ECID_ECID0_0_LOT1_MASK 0x3 +#define ECID_ECID0_0_LOT1_RANGE 30 +#define ECID_ECID1_0_LOT1_MASK 0x3FFFFFF +#define ECID_ECID1_0_LOT0_MASK 0x3F +#define ECID_ECID1_0_LOT0_RANGE 26 +#define ECID_ECID2_0_LOT0_MASK 0x3FFFFFF +#define ECID_ECID2_0_FAB_MASK 0x3F +#define ECID_ECID2_0_FAB_RANGE 26 +#define ECID_ECID3_0_VENDOR_MASK 0xF + +static TEE_Result fuse_get_bsi(uint32_t *val) +{ + if (val == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + *val = io_read32(fuse_va_base + FUSE_BOOT_SECURITY_INFO_0); + return TEE_SUCCESS; +} + +static fuse_ecid_t* fuse_get_queried_ecid(void) +{ + return &fuse_ecid; +} + +static void fuse_query_ecid(void) +{ + uint32_t vendor, fab, wafer; + uint32_t lot0, lot1; + uint32_t x, y; + uint32_t rsvd1; + uint32_t reg; + + if (fuse_va_base == 0) + return; + + reg = io_read32(fuse_va_base + FUSE_OPT_VENDOR_CODE_0); + vendor = reg & OPT_VENDOR_CODE_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_FAB_CODE_0); + fab = reg & OPT_FAB_CODE_MASK; + + lot0 = io_read32(fuse_va_base + FUSE_OPT_LOT_CODE_0_0); + + lot1 = 0; + reg = io_read32(fuse_va_base + FUSE_OPT_LOT_CODE_1_0); + lot1 = reg & OPT_LOT_CODE_1_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_WAFER_ID_0); + wafer = reg & OPT_WAFER_ID_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_X_COORDINATE_0); + x = reg & OPT_X_COORDINATE_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_Y_COORDINATE_0); + y = reg & OPT_Y_COORDINATE_MASK; + + reg = io_read32(fuse_va_base + FUSE_OPT_OPS_RESERVED_0); + rsvd1 = reg & OPT_OPS_RESERVED_MASK; + + reg = 0; + reg |= rsvd1 && ECID_ECID0_0_RSVD1_MASK; + reg |= (y & ECID_ECID0_0_Y_MASK) << ECID_ECID0_0_Y_RANGE; + reg |= (x & ECID_ECID0_0_X_MASK) << ECID_ECID0_0_X_RANGE; + reg |= (wafer & ECID_ECID0_0_WAFER_MASK) << ECID_ECID0_0_WAFER_RANGE; + reg |= (lot1 & ECID_ECID0_0_LOT1_MASK) << ECID_ECID0_0_LOT1_RANGE; + fuse_ecid.ecid[0] = reg; + + lot1 >>= 2; + + reg = 0; + reg |= lot1 & ECID_ECID1_0_LOT1_MASK; + reg |= (lot0 & ECID_ECID1_0_LOT0_MASK) << ECID_ECID1_0_LOT0_RANGE; + fuse_ecid.ecid[1] = reg; + + lot0 >>= 6; + + reg = 0; + reg |= lot0 & ECID_ECID2_0_LOT0_MASK; + reg |= (fab & ECID_ECID2_0_FAB_MASK) << ECID_ECID2_0_FAB_RANGE; + fuse_ecid.ecid[2] = reg; + + reg = 0; + reg |= vendor & ECID_ECID3_0_VENDOR_MASK; + fuse_ecid.ecid[3] = reg; +} + +static TEE_Result tegra_fuse_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + tegra_drv_srv_intf_t *drv_srv_intf = NULL; + + rc = tegra_fuse_map_regs(&fuse_va_base); + if (rc == TEE_SUCCESS) { + fuse_query_ecid(); + + drv_srv_intf = tegra_drv_srv_intf_get(); + if (drv_srv_intf != NULL) { + drv_srv_intf->get_ecid = fuse_get_queried_ecid; + drv_srv_intf->get_bsi = fuse_get_bsi; + } else { + return TEE_ERROR_NOT_SUPPORTED; + } + } + + return rc; +} +service_init(tegra_fuse_init); diff --git a/optee/optee_os/core/drivers/tegra/t234/tegra_rpmb.c b/optee/optee_os/core/drivers/tegra/t234/tegra_rpmb.c new file mode 100644 index 0000000..106c5cc --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/tegra_rpmb.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool tegra_rpmb_key_is_ready = false; + +static uint8_t rollbackkeyiv[TEGRA_SE_AES_IV_SIZE] = { + 'n', 'v', '-', 's', 't', 'o', 'r', 'a', + 'g', 'e', '-', 'd', 'u', 'm', 'm', 'y' +}; + +static uint8_t rollbackkeysrc[TEGRA_SE_AES_BLOCK_SIZE * 2] = { + 0x81, 0x2A, 0x01, 0x43, 0x6B, 0x7C, 0x19, 0xAA, + 0xFF, 0x22, 0x38, 0x82, 0x0A, 0x67, 0x74, 0x08, + 0x30, 0x06, 0xCA, 0x11, 0x41, 0x49, 0x80, 0xED, + 0xE7, 0xBB, 0x61, 0x01, 0x2F, 0x56, 0x9D, 0xD3 +}; + +static uint8_t rollbackkey[TEGRA_SE_AES_BLOCK_SIZE * 2] = { 0 }; + +/* Override the weak tee_otp_get_rpmb_key */ +TEE_Result tee_otp_get_rpmb_key(uint8_t *key, size_t len) +{ + if (key == NULL) + return TEE_ERROR_BAD_PARAMETERS; + if (len != TEGRA_SE_AES_BLOCK_SIZE * 2) { + EMSG("Invalid RPMB key length"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (tegra_rpmb_key_is_ready) { + memcpy(key, rollbackkey, len); + return TEE_SUCCESS; + } else { + EMSG("Failed to get RPMB key"); + return TEE_ERROR_NO_DATA; + } +} + +bool plat_rpmb_key_is_ready(void) +{ + return tegra_rpmb_key_is_ready; +} + +static TEE_Result tegra_rpmb_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + se_aes_keyslot_t fuse_key_for_rpmb = SE_AES_KEYSLOT_OEM_K1; + uint32_t bsi = 0; + fuse_ecid_t *ecid = NULL; + static_assert(sizeof(fuse_ecid_t) <= TEGRA_SE_AES_IV_SIZE); + + rc = tegra_fuse_get_bsi(&bsi); + if (rc != TEE_SUCCESS) { + EMSG("Read fuse BSI failed: 0x%x", rc); + goto out; + } + + if ((bsi & BSI_OEM_KEY_VALID_MASK) == 0) { + IMSG("OEM key valid is not set. RPMB key generation is skipped."); + goto out; + } + + ecid = tegra_fuse_get_ecid(); + if (ecid == NULL) { + rc = TEE_ERROR_GENERIC; + EMSG("%s: Failed to get ecid", __func__); + goto out; + } + memcpy(rollbackkeyiv, ecid->ecid, sizeof(fuse_ecid_t)); + + rc = tegra_se_aes_encrypt_cbc(rollbackkeysrc, sizeof(rollbackkeysrc), + rollbackkey, fuse_key_for_rpmb, rollbackkeyiv); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to derive rollback key (%x)", __func__, rc); + /* + * Do not return an error which will halt optee booting + * We have "tegra_rpmb_key_is_ready" to tell optee if the RPMB key is ready or not + */ + rc = TEE_SUCCESS; + } else { + IMSG("Tegra RPMB key generation succeeded."); + tegra_rpmb_key_is_ready = true; + } + +out: + return rc; +} +driver_init(tegra_rpmb_init); diff --git a/optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c b/optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c new file mode 100644 index 0000000..a04917f --- /dev/null +++ b/optee/optee_os/core/drivers/tegra/t234/tegra_se_aes_rng.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CFG_TEGRA_SE_RNG1) +#include +#endif + +static TEE_Result se_aes_encrypt(uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len, se_aes_op_mode mode, + uint32_t keyslot, uint8_t *iv) +{ + status_t ret = NO_ERROR; + + if (src == NULL || src_len == 0 || dst == NULL || dst_len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + ret = tegra_se_ccc_aes_encrypt(src, src_len, dst, dst_len, + mode, keyslot, TEGRA_SE_KEY_256_SIZE, iv); + if (ret != NO_ERROR) { + EMSG("%s failed with: %d", __func__, ret); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static TEE_Result se_aes_ecb_kdf(uint8_t *derived_key, size_t derived_key_len, + uint8_t *iv, size_t iv_len, + uint32_t keyslot) +{ + if ((derived_key == NULL) || (iv == NULL)) { + EMSG("%s: Invalid arguments.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + if ((derived_key_len != TEE_AES_BLOCK_SIZE) || + (iv_len != TEE_AES_BLOCK_SIZE)) { + EMSG("%s: Invalid size arguments.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + return se_aes_encrypt(iv, iv_len, + derived_key, derived_key_len, + SE_AES_OP_MODE_ECB, keyslot, NULL); +} + +static TEE_Result se_nist_sp_800_108_cmac_kdf(se_aes_keyslot_t keyslot, + uint32_t key_len, + char const *context, + uint32_t context_len, + char const *label, + uint32_t label_len, + uint32_t dk_len, + uint8_t *out_dk) +{ + uint8_t counter[] = { 1 }, zero_byte[] = { 0 }; + uint32_t L[] = { TEE_U32_TO_BIG_ENDIAN(dk_len * 8) }; + uint8_t *message = NULL, *mptr; + uint32_t msg_len, i, n; + status_t ret = NO_ERROR; + TEE_Result rc = TEE_SUCCESS; + + if ((key_len != TEGRA_SE_KEY_128_SIZE) && + (key_len != TEGRA_SE_KEY_256_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + + if ((dk_len % TEE_AES_BLOCK_SIZE) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (!context || !label || !out_dk) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * Regarding to NIST-SP 800-108 + * message = counter || label || 0 || context || L + * + * A || B = The concatenation of binary strings A and B. + */ + msg_len = context_len + label_len + 2 + sizeof(L); + message = calloc(1, msg_len); + if (message == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Concatenate the messages */ + mptr = message; + memcpy(mptr, counter, sizeof(counter)); + mptr += sizeof(counter); + memcpy(mptr, label, label_len); + mptr += label_len; + memcpy(mptr, zero_byte, sizeof(zero_byte)); + mptr += sizeof(zero_byte); + memcpy(mptr, context, context_len); + mptr += context_len; + memcpy(mptr, L, sizeof(L)); + + /* SE AES-CMAC */ + /* n: iterations of the PRF count */ + n = dk_len / TEE_AES_BLOCK_SIZE; + for (i = 0; i < n; i++) { + /* Update the counter */ + message[0] = i + 1; + + ret = tegra_se_ccc_aes_encrypt(message, msg_len, + (out_dk + (i * TEE_AES_BLOCK_SIZE)), TEE_AES_BLOCK_SIZE, + SE_AES_OP_MODE_CMAC, keyslot, key_len, NULL); + if (ret != NO_ERROR) { + EMSG("CMAC-AES failed with: %d", ret); + rc = TEE_ERROR_GENERIC; + goto kdf_error; + } + } + +kdf_error: + free(message); + return rc; +} + +static TEE_Result se_write_aes_keyslot(uint8_t *input_key, uint32_t keylen, + uint32_t key_quad_sel, + se_aes_keyslot_t keyslot) +{ + status_t ret = NO_ERROR; + + if ((keylen != TEGRA_SE_KEY_128_SIZE) && + (keylen != TEGRA_SE_KEY_256_SIZE)) { + EMSG("%s: Invalid key size.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + if ((key_quad_sel != TEGRA_SE_AES_QUAD_KEYS_128) && + (key_quad_sel != TEGRA_SE_AES_QUAD_KEYS_256) && + (key_quad_sel != TEGRA_SE_AES_QUAD_ORG_IV)) { + EMSG("%s: Invalid key QUAD selection.", __func__); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* TODO: + * For T234 keyslot setting, algo is mandatory. + * On T194, the aes slot writting is only used to pass SBK to CPU-BL. + * So need to decide: + * 1. Does UEFI need SBK to be present in a keyslot? + * 2. Which encryption algo is used for kernel encryption? + * Need to change here when there is a conclusion. + */ + ret = tegra_se_ccc_set_aes_keyslot(keyslot, input_key, keylen, SE_AES_OP_MODE_CBC); + if (ret != NO_ERROR) { + EMSG("%s failed with: %d", __func__, ret); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static TEE_Result se_clear_aes_keyslots(void) +{ + status_t ret = NO_ERROR; + uint32_t i; + + for (i = SE_AES_KEYSLOT_11; i < SE_AES_KEYSLOT_COUNT; i++) { + if (i == SE_AES_KEYSLOT_11 + 2) { + /* Skip keyslot #13 since we don't use it */ + continue; + } + + ret = tegra_se_ccc_clear_aes_keyslot(i); + if (ret != NO_ERROR) { + EMSG("%s failed with: %d", __func__, ret); + return TEE_ERROR_GENERIC; + } + } + + return TEE_SUCCESS; +} + +#if defined(CFG_TEGRA_SE_RNG1) +static TEE_Result se_rng1_get_random(void *data, uint32_t data_len) +{ + status_t ret = NO_ERROR; + + ret = tegra_se_ccc_aes_genrnd(data, data_len); + if (ret != NO_ERROR) { + EMSG("%s failed with: %d", __func__, ret); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} +#endif + +/* This function is called by tegra_init_crypto_devices to map devices */ +status_t tegra_se_map_device(optee_tegra_se_cdev_id_t device_id, void **base_va) +{ + TEE_Result rc = TEE_SUCCESS; + status_t ret = NO_ERROR; + vaddr_t va = 0; + + if (base_va == NULL) { + EMSG("tegra_se_map_device: base_va is NULL."); + *base_va = NULL; + return ERR_INVALID_ARGS; + } + + switch (device_id) { + case OPTEE_TEGRA_SE_CDEV_SE0: + rc = tegra_se_map_regs(&va); + if (rc != TEE_SUCCESS) { + EMSG("Mapping SE0 regs failed: 0x%x", rc); + *base_va = NULL; + ret = ERR_GENERIC; + goto out; + } + ret = tegra_se_ccc_configure_se0(va); + if (ret != NO_ERROR) { + EMSG("Configure SE0 failed: %d", ret); + *base_va = NULL; + goto out; + } + *base_va = (void *)va; + break; +#if defined(CFG_TEGRA_SE_RNG1) + case OPTEE_TEGRA_SE_CDEV_RNG1: + /* + * Random numbers can be generated via SE engine as well, + * just mapping the RNG1 here too in case we need to use NVRNG + * in the future. + */ + rc = tegra_rng1_map_regs(&va); + if (rc != TEE_SUCCESS) { + EMSG("Mapping RNG1 regs failed: 0x%x", rc); + *base_va = NULL; + ret = ERR_GENERIC; + goto out; + } + ret = tegra_se_ccc_configure_rng1(va); + if (ret != NO_ERROR) { + EMSG("Configure RNG1 failed: %d", ret); + *base_va = NULL; + goto out; + } + *base_va = (void *)va; + break; +#endif + default: + /* CCC will disable the unsupported devices accordingly */ + DMSG("Mapping unsupported SE device: %d", device_id); + *base_va = NULL; + break; + } + +out: + return ret; +} + +static TEE_Result tegra_se_init(void) +{ + status_t ret; + tegra_drv_srv_intf_t *drv_srv_intf; + +#if defined(CFG_TEGRA_SE_USE_TEST_KEYS) + /* OEM_K1: 2d4a614e645267556b58703273357638792f423f4428472b4b6250655368566d */ + const uint8_t oem_k1_test[] = { + 0x2d, 0x4a, 0x61, 0x4e, 0x64, 0x52, 0x67, 0x55, + 0x6b, 0x58, 0x70, 0x32, 0x73, 0x35, 0x76, 0x38, + 0x79, 0x2f, 0x42, 0x3f, 0x44, 0x28, 0x47, 0x2b, + 0x4b, 0x62, 0x50, 0x65, 0x53, 0x68, 0x56, 0x6d, + }; + + /* OEM_K2: 432646294a404e635266556a586e3272357538782f413f442a472d4b61506453 */ + const uint8_t oem_k2_test[] = { + 0x43, 0x26, 0x46, 0x29, 0x4a, 0x40, 0x4e, 0x63, + 0x52, 0x66, 0x55, 0x6a, 0x58, 0x6e, 0x32, 0x72, + 0x35, 0x75, 0x38, 0x78, 0x2f, 0x41, 0x3f, 0x44, + 0x2a, 0x47, 0x2d, 0x4b, 0x61, 0x50, 0x64, 0x53, + }; + + TEE_Result err = TEE_SUCCESS; + uint32_t bsi = 0; +#endif + + ret = tegra_init_crypto_devices(); + if (ret != NO_ERROR) { + return TEE_ERROR_GENERIC; + } + +#if defined(CFG_TEGRA_SE_USE_TEST_KEYS) + err = tegra_fuse_get_bsi(&bsi); + if (err != TEE_SUCCESS) { + EMSG("Read fuse BSI failed: 0x%x", err); + return TEE_ERROR_GENERIC; + } + + if ((bsi & BSI_OEM_KEY_VALID_MASK) == 0) { + ret = tegra_se_ccc_set_test_oem_keys(oem_k1_test, oem_k2_test); + if (ret != NO_ERROR) { + EMSG("Setting test OEM keys failed: %d", ret); + return TEE_ERROR_GENERIC; + } + IMSG("Test OEM keys are being used. This is insecure for shipping products!"); + } +#endif + + drv_srv_intf = tegra_drv_srv_intf_get(); + if (drv_srv_intf != NULL) { + drv_srv_intf->aes_encrypt = se_aes_encrypt; + drv_srv_intf->aes_ecb_kdf = se_aes_ecb_kdf; + drv_srv_intf->nist_sp_800_108_cmac_kdf = se_nist_sp_800_108_cmac_kdf; + drv_srv_intf->write_aes_keyslot = se_write_aes_keyslot; + drv_srv_intf->clear_aes_keyslots = se_clear_aes_keyslots; +#if defined(CFG_TEGRA_SE_RNG1) + drv_srv_intf->rng_get_random = se_rng1_get_random; +#endif + } else { + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} +service_init_late(tegra_se_init); diff --git a/optee/optee_os/core/drivers/tegra_combined_uart.c b/optee/optee_os/core/drivers/tegra_combined_uart.c new file mode 100644 index 0000000..b9a9119 --- /dev/null +++ b/optee/optee_os/core/drivers/tegra_combined_uart.c @@ -0,0 +1,98 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + */ + +#include +#include +#include + +/* 50 ms */ +#define TX_TIMEOUT 50 + +/* + * Triggers an interrupt. Also indicates that the remote processor + * is busy when set. + */ +#define MBOX_INTR_TRIGGER (1 << 31) +/* + * Ensures that prints up to and including this packet are flushed on + * the physical uart before de-asserting MBOX_INTR_TRIGGER. + */ +#define MBOX_FLUSH (1 << 26) +/* + * Indicates that we're only sending one byte at a time. + */ +#define MBOX_BYTE_COUNT (1 << 24) + +static vaddr_t chip_to_base(struct serial_chip *chip) +{ + struct tegra_combined_uart_data *tcud = + container_of(chip, struct tegra_combined_uart_data, chip); + + return io_pa_or_va(&tcud->base, tcud->base_size); +} + +static void send_msg(vaddr_t base, uint32_t msg) +{ + int timeout = TX_TIMEOUT; + + while (io_read32(base) & (MBOX_INTR_TRIGGER)) { + if (timeout-- <= 0) + return; + udelay(300); + } + io_write32(base, msg); +} + +static void comb_uart_putc(struct serial_chip *chip, int c) +{ + uint32_t msg; + vaddr_t base = chip_to_base(chip); + + (void)chip; + if (c == '\0') + return; + msg = MBOX_INTR_TRIGGER | MBOX_BYTE_COUNT | (uint8_t)(c & 0xff); + send_msg(base, msg); +} + + +static void comb_uart_flush(struct serial_chip *chip) +{ + uint32_t msg = MBOX_INTR_TRIGGER | MBOX_FLUSH; + vaddr_t base = chip_to_base(chip); + + send_msg(base, msg); +} + +static int comb_uart_getc(struct serial_chip *chip) +{ + (void)chip; + return -1; +} + +static bool comb_uart_have_rx_data(struct serial_chip *chip) +{ + (void)chip; + return false; +} + +static const struct serial_ops comb_uart_ops = { + .flush = comb_uart_flush, + .getchar = comb_uart_getc, + .have_rx_data = comb_uart_have_rx_data, + .putc = comb_uart_putc +}; +DECLARE_KEEP_PAGER(comb_uart_ops); + +void tegra_combined_uart_init(struct tegra_combined_uart_data *tcud, + paddr_t base, size_t size) +{ + if (!tcud) + return; + tcud->base.pa = base; + tcud->base_size= size; + tcud->chip.ops = &comb_uart_ops; +} diff --git a/optee/optee_os/core/drivers/tzc380.c b/optee/optee_os/core/drivers/tzc380.c new file mode 100644 index 0000000..4403391 --- /dev/null +++ b/optee/optee_os/core/drivers/tzc380.c @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2017-2020 NXP + * All rights reserved. + * + * Peng Fan + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +/* + * Implementation defined values used to validate inputs later. + * Filters : max of 4 ; 0 to 3 + * Regions : max of 9 ; 0 to 8 + * Address width : Values between 32 to 64 + */ +struct tzc_instance { + vaddr_t base; + uint8_t addr_width; + uint8_t num_regions; +}; + +static struct tzc_instance tzc; + +static uint32_t tzc_read_build_config(vaddr_t base) +{ + return io_read32(base + BUILD_CONFIG_OFF); +} + +static void tzc_write_action(vaddr_t base, enum tzc_action action) +{ + io_write32(base + ACTION_OFF, action); +} + +static uint32_t tzc_read_action(vaddr_t base) +{ + return io_read32(base + ACTION_OFF); +} + +static void tzc_write_region_base_low(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_SETUP_LOW_OFF(region), val); +} + +static void tzc_write_region_base_high(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_SETUP_HIGH_OFF(region), val); +} + +static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_ATTRIBUTES_OFF(region)); +} + +static void tzc_write_region_attributes(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_ATTRIBUTES_OFF(region), val); +} + +void tzc_init(vaddr_t base) +{ + uint32_t tzc_build; + + assert(base); + tzc.base = base; + + /* Save values we will use later. */ + tzc_build = tzc_read_build_config(tzc.base); + tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & + BUILD_CONFIG_AW_MASK) + 1; + tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & + BUILD_CONFIG_NR_MASK) + 1; +} + +/* + * There are two modes of operation for the region security + * permissions, with or without security inversion. + * Check TZC380 "2.2.5 Region security permissions" for + * more details. + */ +void tzc_security_inversion_en(vaddr_t base) +{ + io_write32(base + SECURITY_INV_EN_OFF, 1); +} + +/* + * Enable a single region. Sometimes we could not use tzc_configure_region + * to enable the region, when security inversion is on. + * When need security inversion, we need to first configure + * region address and attribute, then configure security inversion, + * then enable the regions. + */ +void tzc_region_enable(uint8_t region) +{ + uint32_t val; + + val = tzc_read_region_attributes(tzc.base, region); + val |= TZC_ATTR_REGION_EN_MASK; + tzc_write_region_attributes(tzc.base, region, val); +} + +/* + * Dump info when TZC380 catchs an unallowed access with TZC + * interrupt enabled. + */ +void tzc_fail_dump(void) +{ + vaddr_t base __maybe_unused = core_mmu_get_va(tzc.base, + MEM_AREA_IO_SEC, + TZC400_REG_SIZE); + + EMSG("Fail address Low 0x%" PRIx32, + io_read32(base + FAIL_ADDRESS_LOW_OFF)); + EMSG("Fail address High 0x%" PRIx32, + io_read32(base + FAIL_ADDRESS_HIGH_OFF)); + EMSG("Fail Control 0x%" PRIx32, io_read32(base + FAIL_CONTROL_OFF)); + EMSG("Fail Id 0x%" PRIx32, io_read32(base + FAIL_ID)); +} + +void tzc_int_clear(void) +{ + vaddr_t base = core_mmu_get_va(tzc.base, MEM_AREA_IO_SEC, + TZC400_REG_SIZE); + + io_write32(base + INT_CLEAR, 0); +} + +static uint32_t addr_low(vaddr_t addr) +{ + return (uint32_t)addr; +} + +static uint32_t addr_high(vaddr_t addr __maybe_unused) +{ +#if (UINTPTR_MAX == UINT64_MAX) + return addr >> 32; +#else + return 0; +#endif +} + + +/* + * `tzc_configure_region` is used to program regions into the TrustZone + * controller. + */ +void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr) +{ + assert(tzc.base); + + assert(region < tzc.num_regions); + + /* + * For region 0, this high/low/size/en field is Read Only (RO). + * So should not configure those field for region 0. + */ + if (region) { + tzc_write_region_base_low(tzc.base, region, + addr_low(region_base)); + tzc_write_region_base_high(tzc.base, region, + addr_high(region_base)); + tzc_write_region_attributes(tzc.base, region, attr); + } else { + tzc_write_region_attributes(tzc.base, region, + attr & TZC_ATTR_SP_MASK); + } +} + +void tzc_set_action(enum tzc_action action) +{ + assert(tzc.base); + + /* + * - Currently no handler is provided to trap an error via interrupt + * or exception. + * - The interrupt action has not been tested. + */ + tzc_write_action(tzc.base, action); +} + +uint32_t tzc_get_action(void) +{ + assert(tzc.base); + + return tzc_read_action(tzc.base); +} + +int tzc_auto_configure(vaddr_t addr, vaddr_t size, uint32_t attr, + uint8_t region) +{ + uint64_t sub_region_size = 0; + uint64_t area = 0; + uint8_t lregion = region; + uint64_t region_size = 0; + vaddr_t sub_address = 0; + vaddr_t address = addr; + uint64_t lsize = size; + uint32_t mask = 0; + int i = 0; + uint8_t pow = 0; + + assert(tzc.base); + + /* + * TZC380 RM + * For region_attributes_ registers, region_size: + * Note: The AXI address width, that is AXI_ADDRESS_MSB+1, controls the + * upper limit value of the field. + */ + pow = tzc.addr_width; + + while (lsize != 0 && pow >= 15) { + region_size = 1ULL << pow; + + /* Case region fits alignment and covers requested area */ + if ((address % region_size == 0) && + ((address + lsize) % region_size == 0)) { + tzc_configure_region(lregion, address, + TZC_ATTR_REGION_SIZE(pow - 1) | + TZC_ATTR_REGION_EN_MASK | + attr); + lregion++; + address += region_size; + lsize -= region_size; + pow = tzc.addr_width; + continue; + } + + /* Cover area using several subregions */ + sub_region_size = region_size / 8; + if (address % sub_region_size == 0 && + lsize > 2 * sub_region_size) { + sub_address = (address / region_size) * region_size; + mask = 0; + for (i = 0; i < 8; i++) { + area = (i + 1) * sub_region_size; + if (sub_address + area <= address || + sub_address + area > address + lsize) { + mask |= TZC_ATTR_SUBREGION_DIS(i); + } else { + address += sub_region_size; + lsize -= sub_region_size; + } + } + tzc_configure_region(lregion, sub_address, + TZC_ATTR_REGION_SIZE(pow - 1) | + TZC_ATTR_REGION_EN_MASK | + mask | attr); + lregion++; + pow = tzc.addr_width; + continue; + } + pow--; + } + assert(lsize == 0); + assert(address == addr + size); + return lregion; +} + +/* + * `region_lockdown` is used to lockdown the TZC380 configuration to prevent + * unintended overwrites of the configuration. Returns TEE_ERROR_SECURITY in + * case the lockdown fails. + */ +TEE_Result tzc_regions_lockdown(void) +{ + uint32_t val = 0; + uint32_t check = 0; + + val = LOCKDOWN_RANGE_ENABLE | (tzc.num_regions - 1); + io_write32(tzc.base + LOCKDOWN_RANGE_OFF, val); + check = io_read32(tzc.base + LOCKDOWN_RANGE_OFF); + if (check != val) + return TEE_ERROR_SECURITY; + + val = LOCKDOWN_SELECT_RANGE_ENABLE; + io_write32(tzc.base + LOCKDOWN_SELECT_OFF, val); + check = io_read32(tzc.base + LOCKDOWN_SELECT_OFF); + if (check != val) + return TEE_ERROR_SECURITY; + + return TEE_SUCCESS; +} + +#if TRACE_LEVEL >= TRACE_DEBUG + +static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_SETUP_LOW_OFF(region)); +} + +static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_SETUP_HIGH_OFF(region)); +} + +#define REGION_MAX 16 +void tzc_dump_state(void) +{ + uint32_t n; + uint32_t temp_32reg, temp_32reg_h; + + DMSG("TZC380 configuration:"); + DMSG("security_inversion_en %x", + io_read32(tzc.base + SECURITY_INV_EN_OFF)); + for (n = 0; n <= REGION_MAX; n++) { + temp_32reg = tzc_read_region_attributes(tzc.base, n); + if (!(temp_32reg & TZC_ATTR_REGION_EN_MASK)) + continue; + + DMSG(""); + DMSG("region %d", n); + temp_32reg = tzc_read_region_base_low(tzc.base, n); + temp_32reg_h = tzc_read_region_base_high(tzc.base, n); + DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg); + temp_32reg = tzc_read_region_attributes(tzc.base, n); + DMSG("region sp: %x", temp_32reg >> TZC_ATTR_SP_SHIFT); + DMSG("region size: %x", (temp_32reg & TZC_REGION_SIZE_MASK) >> + TZC_REGION_SIZE_SHIFT); + } + DMSG("Lockdown select: %"PRIx32, + io_read32(tzc.base + LOCKDOWN_SELECT_OFF)); + DMSG("Lockdown range: %"PRIx32, + io_read32(tzc.base + LOCKDOWN_RANGE_OFF)); + DMSG("Action register: %"PRIx32, tzc_get_action()); + DMSG("exit"); +} + +#endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */ diff --git a/optee/optee_os/core/drivers/tzc400.c b/optee/optee_os/core/drivers/tzc400.c new file mode 100644 index 0000000..9d8c0a0 --- /dev/null +++ b/optee/optee_os/core/drivers/tzc400.c @@ -0,0 +1,490 @@ +// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) +/* + * Copyright (c) 2015, 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. + */ + /* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation defined values used to validate inputs later. + * Filters : max of 4 ; 0 to 3 + * Regions : max of 9 ; 0 to 8 + * Address width : Values between 32 to 64 + */ +struct tzc_instance { + vaddr_t base; + uint8_t addr_width; + uint8_t num_filters; + uint8_t num_regions; +}; + +static struct tzc_instance tzc; + + +static uint32_t tzc_read_build_config(vaddr_t base) +{ + return io_read32(base + BUILD_CONFIG_OFF); +} + +static uint32_t tzc_read_gate_keeper(vaddr_t base) +{ + return io_read32(base + GATE_KEEPER_OFF); +} + +static void tzc_write_gate_keeper(vaddr_t base, uint32_t val) +{ + io_write32(base + GATE_KEEPER_OFF, val); +} + +static void tzc_write_action(vaddr_t base, enum tzc_action action) +{ + io_write32(base + ACTION_OFF, action); +} + +static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region)); +} + +static void tzc_write_region_base_low(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region), val); +} + +static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region)); +} + +static void tzc_write_region_base_high(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region), val); +} + +static uint32_t tzc_read_region_top_low(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region)); +} + +static void tzc_write_region_top_low(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region), val); +} + +static uint32_t tzc_read_region_top_high(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region)); +} + +static void tzc_write_region_top_high(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region), val); +} + +static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region)); +} + +static void tzc_write_region_attributes(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region), val); +} + +static uint32_t tzc_read_region_id_access(vaddr_t base, uint32_t region) +{ + return io_read32(base + REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region)); +} + +static void tzc_write_region_id_access(vaddr_t base, uint32_t region, + uint32_t val) +{ + io_write32(base + REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region), val); +} + +static uint32_t tzc_read_component_id(vaddr_t base) +{ + uint32_t id; + + id = io_read8(base + CID0_OFF); + id |= SHIFT_U32(io_read8(base + CID1_OFF), 8); + id |= SHIFT_U32(io_read8(base + CID2_OFF), 16); + id |= SHIFT_U32(io_read8(base + CID3_OFF), 24); + + return id; +} + +static uint32_t tzc_get_gate_keeper(vaddr_t base, uint8_t filter) +{ + uint32_t tmp; + + tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & + GATE_KEEPER_OS_MASK; + + return (tmp >> filter) & GATE_KEEPER_FILTER_MASK; +} + +/* This function is not MP safe. */ +static void tzc_set_gate_keeper(vaddr_t base, uint8_t filter, uint32_t val) +{ + uint32_t tmp; + + /* Upper half is current state. Lower half is requested state. */ + tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & + GATE_KEEPER_OS_MASK; + + if (val) + tmp |= (1 << filter); + else + tmp &= ~(1 << filter); + + tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) << + GATE_KEEPER_OR_SHIFT); + + /* Wait here until we see the change reflected in the TZC status. */ + while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & + GATE_KEEPER_OS_MASK) != tmp) + ; +} + + +void tzc_init(vaddr_t base) +{ + uint32_t tzc_id, tzc_build; + + assert(base); + tzc.base = base; + + /* + * We expect to see a tzc400. Check component ID. The TZC-400 TRM shows + * component ID is expected to be "0xB105F00D". + */ + tzc_id = tzc_read_component_id(tzc.base); + if (tzc_id != TZC400_COMPONENT_ID) { + EMSG("TZC : Wrong device ID (0x%" PRIx32 ")", tzc_id); + panic(); + } + + /* Save values we will use later. */ + tzc_build = tzc_read_build_config(tzc.base); + tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) & + BUILD_CONFIG_NF_MASK) + 1; + tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & + BUILD_CONFIG_AW_MASK) + 1; + tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & + BUILD_CONFIG_NR_MASK) + 1; +} + +static uint32_t addr_low(vaddr_t addr) +{ + return (uint32_t)addr; +} + +static uint32_t addr_high(vaddr_t addr __unused) +{ +#if (UINTPTR_MAX == UINT64_MAX) + return (addr >> 32); +#else + return 0; +#endif +} + + +/* + * `tzc_configure_region` is used to program regions into the TrustZone + * controller. A region can be associated with more than one filter. The + * associated filters are passed in as a bitmap (bit0 = filter0). + * NOTE: + * The region 0 covers the whole address space and is enabled on all filters, + * this cannot be changed. It is, however, possible to change some region 0 + * permissions. + */ +void tzc_configure_region(uint8_t region, const struct tzc_region_config *cfg) +{ + assert(tzc.base && cfg); + + /* Do range checks on filters and regions. */ + assert(((cfg->filters >> tzc.num_filters) == 0) && + (region < tzc.num_regions)); + + /* + * Do address range check based on TZC configuration. A 64bit address is + * the max and expected case. + */ +#if (UINTPTR_MAX == UINT64_MAX) + assert(((cfg->top <= (UINT64_MAX >> (64 - tzc.addr_width))) && + (cfg->base < cfg->top))); +#endif + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((cfg->base | (cfg->top + 1)) & (4096 - 1)) == 0); + + assert(cfg->sec_attr <= TZC_REGION_S_RDWR); + + /* + * Inputs look ok, start programming registers. + * All the address registers are 32 bits wide and have a LOW and HIGH + * component used to construct a up to a 64bit address. + */ + tzc_write_region_base_low(tzc.base, region, addr_low(cfg->base)); + tzc_write_region_base_high(tzc.base, region, addr_high(cfg->base)); + + tzc_write_region_top_low(tzc.base, region, addr_low(cfg->top)); + tzc_write_region_top_high(tzc.base, region, addr_high(cfg->top)); + + /* Assign the region to a filter and set secure attributes */ + tzc_write_region_attributes(tzc.base, region, + (cfg->sec_attr << REG_ATTR_SEC_SHIFT) | + cfg->filters); + + /* + * Specify which non-secure devices have permission to access this + * region. + */ + tzc_write_region_id_access(tzc.base, region, cfg->ns_device_access); +} + +TEE_Result tzc_get_region_config(uint8_t region, struct tzc_region_config *cfg) +{ + uint32_t val32 = 0; + + if (region >= tzc.num_regions) + return TEE_ERROR_GENERIC; + + cfg->base = reg_pair_to_64(tzc_read_region_base_high(tzc.base, region), + tzc_read_region_base_low(tzc.base, region)); + cfg->top = reg_pair_to_64(tzc_read_region_top_high(tzc.base, region), + tzc_read_region_top_low(tzc.base, region)); + + cfg->ns_device_access = tzc_read_region_id_access(tzc.base, region); + + val32 = tzc_read_region_attributes(tzc.base, region); + cfg->sec_attr = val32 >> REG_ATTR_SEC_SHIFT; + cfg->filters = val32 & REG_ATTR_F_EN_MASK; + + return TEE_SUCCESS; +} + +void tzc_set_action(enum tzc_action action) +{ + assert(tzc.base); + + /* + * - Currently no handler is provided to trap an error via interrupt + * or exception. + * - The interrupt action has not been tested. + */ + tzc_write_action(tzc.base, action); +} + + +void tzc_enable_filters(void) +{ + uint32_t state; + uint32_t filter; + + assert(tzc.base); + + for (filter = 0; filter < tzc.num_filters; filter++) { + state = tzc_get_gate_keeper(tzc.base, filter); + if (state) { + /* + * The TZC filter is already configured. Changing the + * programmer's view in an active system can cause + * unpredictable behavior therefore panic for now rather + * than try to determine whether this is safe in this + * instance. See: + * http://infocenter.arm.com/help/index.jsp?\ + * topic=/com.arm.doc.ddi0504c/CJHHECBF.html + */ + EMSG("TZC : Filter %d Gatekeeper already enabled", + filter); + panic(); + } + tzc_set_gate_keeper(tzc.base, filter, 1); + } +} + + +void tzc_disable_filters(void) +{ + uint32_t filter; + + assert(tzc.base); + + /* + * We don't do the same state check as above as the Gatekeepers are + * disabled after reset. + */ + for (filter = 0; filter < tzc.num_filters; filter++) + tzc_set_gate_keeper(tzc.base, filter, 0); +} + +static bool __maybe_unused write_not_read(unsigned int filter) +{ + return io_read32(tzc.base + FAIL_CONTROL(filter)) & + FAIL_CONTROL_DIRECTION_WRITE; +} + +static bool __maybe_unused nonsecure_not_secure(unsigned int filter) +{ + return io_read32(tzc.base + FAIL_CONTROL(filter)) & + FAIL_CONTROL_NONSECURE; +} + +static bool __maybe_unused priv_not_unpriv(unsigned int filter) +{ + return io_read32(tzc.base + FAIL_CONTROL(filter)) & + FAIL_CONTROL_PRIVILEGED; +} + +static void dump_fail_filter(unsigned int filter) +{ + uint64_t __maybe_unused addr = 0; + uint32_t status = io_read32(tzc.base + INT_STATUS); + + if (!(status & BIT(filter + INT_STATUS_OVERLAP_SHIFT)) && + !(status & BIT(filter + INT_STATUS_OVERRUN_SHIFT)) && + !(status & BIT(filter + INT_STATUS_STATUS_SHIFT))) + return; + + if (status & BIT(filter + INT_STATUS_OVERLAP_SHIFT)) + EMSG("Overlap violation on filter %u", filter); + + if (status & BIT(filter + INT_STATUS_OVERRUN_SHIFT)) + EMSG("Overrun violation on filter %u", filter); + + if (status & BIT(filter + INT_STATUS_STATUS_SHIFT)) + EMSG("Permission violation on filter %u", filter); + + addr = reg_pair_to_64(io_read32(tzc.base + FAIL_ADDRESS_HIGH(filter)), + io_read32(tzc.base + FAIL_ADDRESS_LOW(filter))); + + EMSG("Violation @0x%"PRIx64", %ssecure %sprivileged %s, AXI ID %"PRIx32, + addr, + nonsecure_not_secure(filter) ? "non-" : "", + priv_not_unpriv(filter) ? "" : "un", + write_not_read(filter) ? "write" : "read", + io_read32(tzc.base + FAIL_ID(filter))); +} + +/* + * Dump info when TZC400 catches an unallowed access with TZC + * interrupt enabled. + */ +void tzc_fail_dump(void) +{ + unsigned int filter = 0; + + for (filter = 0; filter < tzc.num_filters; filter++) + dump_fail_filter(filter); +} + +void tzc_int_clear(void) +{ + assert(tzc.base); + + io_setbits32(tzc.base + INT_CLEAR, GENMASK_32(tzc.num_filters - 1, 0)); +} + +#if TRACE_LEVEL >= TRACE_DEBUG + +#define REGION_MAX 8 +static const __maybe_unused char * const tzc_attr_msg[] = { + "TZC_REGION_S_NONE", + "TZC_REGION_S_RD", + "TZC_REGION_S_WR", + "TZC_REGION_S_RDWR" +}; + +void tzc_dump_state(void) +{ + uint32_t n; + uint32_t temp_32reg, temp_32reg_h; + unsigned int filter = 0; + + for (n = 0; n <= REGION_MAX; n++) { + temp_32reg = tzc_read_region_attributes(tzc.base, n); + if (!(temp_32reg & REG_ATTR_F_EN_MASK)) + continue; + + DMSG("region %d", n); + temp_32reg = tzc_read_region_base_low(tzc.base, n); + temp_32reg_h = tzc_read_region_base_high(tzc.base, n); + DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg); + temp_32reg = tzc_read_region_top_low(tzc.base, n); + temp_32reg_h = tzc_read_region_top_high(tzc.base, n); + DMSG("region_top: 0x%08x%08x", temp_32reg_h, temp_32reg); + temp_32reg = tzc_read_region_attributes(tzc.base, n); + DMSG("secure rw: %s", + tzc_attr_msg[temp_32reg >> REG_ATTR_SEC_SHIFT]); + + for (filter = 0; filter < tzc.num_filters; filter++) + if (temp_32reg & BIT(filter)) + DMSG("filter %u enable", filter); + } +} + +#endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */ diff --git a/optee/optee_os/core/drivers/versal_gpio.c b/optee/optee_os/core/drivers/versal_gpio.c new file mode 100644 index 0000000..7054dbf --- /dev/null +++ b/optee/optee_os/core/drivers/versal_gpio.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved. + * Copyright (c) 2022 Foundries.io Ltd. (jorge@foundries.io) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drivers/versal_gpio.h" + +#define VERSAL_GPIO_LEN 0x10000 + +#define DATA_LSW_OFFSET(__bank) (0x000 + 0x08 * (__bank)) +#define DATA_MSW_OFFSET(__bank) (0x004 + 0x08 * (__bank)) +#define DATA_RO_OFFSET(__bank) (0x060 + 0x04 * (__bank)) +#define DIRM_OFFSET(__bank) (0x204 + 0x40 * (__bank)) +#define OUTEN_OFFSET(__bank) (0x208 + 0x40 * (__bank)) + +#define VERSAL_GPIO_MID_PIN 16 +#define VERSAL_GPIO_UPPER_MASK 0xFFFF0000 + +/* Max pins in the PMC_GPIO devices + * 00 - 025, Bank 0 + * 26 - 051, Bank 1 + * 52 - 083, Bank 3 + * 84 - 115, Bank 4 + */ +#define VERSAL_GPIO_PMC_BASE 0xf1020000 +#define VERSAL_GPIO_PMC_NR_GPIOS 116 +#define VERSAL_GPIO_PMC_MAX_BANK 5 + +static const struct versal_gpio_platform_data versal_gpio_pmc_def = { + .max_bank = VERSAL_GPIO_PMC_MAX_BANK, + .ngpio = VERSAL_GPIO_PMC_NR_GPIOS, + .label = "versal_pmc_gpio", + .bank_min[0] = 0, + .bank_max[0] = 25, + .bank_min[1] = 26, + .bank_max[1] = 51, + .bank_min[3] = 52, + .bank_max[3] = 83, + .bank_min[4] = 84, + .bank_max[4] = 115, +}; + +/* Max pins in the PS_GPIO devices + * 00 - 25, Bank 0 + * 26 - 57, Bank 3 + */ +#define VERSAL_GPIO_PS_BASE 0xff0b0000 +#define VERSAL_GPIO_PS_NR_GPIOS 58 +#define VERSAL_GPIO_PS_MAX_BANK 4 + +static const struct versal_gpio_platform_data versal_gpio_ps_def = { + .max_bank = VERSAL_GPIO_PS_MAX_BANK, + .ngpio = VERSAL_GPIO_PS_NR_GPIOS, + .label = "versal_ps_gpio", + .bank_min[0] = 0, + .bank_max[0] = 25, + .bank_min[3] = 26, + .bank_max[3] = 57, +}; + +static void versal_gpio_get_pin(struct versal_gpio_chip *chip, uint32_t gpio, + uint32_t *bank, uint32_t *pin) +{ + struct versal_gpio_platdata *platdata = &chip->plat; + uint32_t bnk = 0; + + assert(gpio < platdata->p_data->ngpio); + + for (bnk = 0; bnk < platdata->p_data->max_bank; bnk++) { + if (gpio < platdata->p_data->bank_min[bnk]) + continue; + + if (gpio > platdata->p_data->bank_max[bnk]) + continue; + + *bank = bnk; + *pin = gpio - platdata->p_data->bank_min[bnk]; + + return; + } + + EMSG("GPIO_%d not found", gpio); + panic(); +} + +static enum gpio_level gpio_get_value(struct versal_gpio_chip *chip, + uint32_t gpio) +{ + uint32_t bank = 0; + uint32_t pin = 0; + + versal_gpio_get_pin(chip, gpio, &bank, &pin); + + return (io_read32(chip->base + DATA_RO_OFFSET(bank)) >> pin) & 1; +} + +static void gpio_set_value(struct versal_gpio_chip *chip, uint32_t gpio, + enum gpio_level val) +{ + uint32_t bank = 0; + uint32_t off = 0; + uint32_t pin = 0; + + versal_gpio_get_pin(chip, gpio, &bank, &pin); + + if (bank >= VERSAL_GPIO_MID_PIN) { + bank -= VERSAL_GPIO_MID_PIN; + off = DATA_MSW_OFFSET(bank); + } else { + off = DATA_LSW_OFFSET(bank); + } + + /* + * get the 32 bit value to be written to the mask/data register where + * the upper 16 bits is the mask and lower 16 bits is the data + */ + val = !!val; + val = ~BIT32(pin + VERSAL_GPIO_MID_PIN) & + (SHIFT_U32(val, pin) | VERSAL_GPIO_UPPER_MASK); + + io_write32(chip->base + off, val); +} + +static void gpio_set_direction(struct versal_gpio_chip *chip, uint32_t gpio, + enum gpio_dir direction) +{ + uint32_t bank = 0; + uint32_t reg = 0; + uint32_t pin = 0; + + versal_gpio_get_pin(chip, gpio, &bank, &pin); + + if (direction == GPIO_DIR_OUT) { + /* set the GPIO pin as output */ + reg = io_read32(chip->base + DIRM_OFFSET(bank)); + reg |= BIT(pin); + io_write32(chip->base + DIRM_OFFSET(bank), reg); + + /* configure the output enable reg for the pin */ + reg = io_read32(chip->base + OUTEN_OFFSET(bank)); + + reg |= BIT(pin); + io_write32(chip->base + OUTEN_OFFSET(bank), reg); + + /* set the state of the pin */ + gpio_set_value(chip, gpio, GPIO_LEVEL_LOW); + } else { + /* bnk 0 pins 7 and 8 cannot be used as inputs */ + assert(!(bank == 0 && (pin == 7 || pin == 8))); + + reg = io_read32(chip->base + DIRM_OFFSET(bank)); + reg &= ~BIT(pin); + io_write32(chip->base + DIRM_OFFSET(bank), reg); + } +} + +static enum gpio_dir gpio_get_direction(struct versal_gpio_chip *chip, + uint32_t gpio) +{ + uint32_t pin = 0; + uint32_t bank = 0; + + versal_gpio_get_pin(chip, gpio, &bank, &pin); + + if (io_read32(chip->base + DIRM_OFFSET(bank)) & BIT(pin)) + return GPIO_DIR_OUT; + + return GPIO_DIR_IN; +} + +static enum gpio_level do_get_value(struct gpio_chip *chip, uint32_t gpio) +{ + struct versal_gpio_chip *p = container_of(chip, + struct versal_gpio_chip, chip); + return gpio_get_value(p, gpio); +} + +static void do_set_value(struct gpio_chip *chip, uint32_t gpio, + enum gpio_level val) +{ + struct versal_gpio_chip *p = container_of(chip, + struct versal_gpio_chip, chip); + return gpio_set_value(p, gpio, val); +} + +static void do_set_dir(struct gpio_chip *chip, uint32_t gpio, + enum gpio_dir direction) +{ + struct versal_gpio_chip *p = container_of(chip, + struct versal_gpio_chip, chip); + return gpio_set_direction(p, gpio, direction); +} + +static enum gpio_dir do_get_dir(struct gpio_chip *chip, uint32_t gpio) +{ + struct versal_gpio_chip *p = container_of(chip, + struct versal_gpio_chip, chip); + return gpio_get_direction(p, gpio); +} + +static const struct gpio_ops versal_gpio_ops = { + .get_direction = do_get_dir, + .set_direction = do_set_dir, + .get_value = do_get_value, + .set_value = do_set_value, + .get_interrupt = NULL, + .set_interrupt = NULL, +}; + +TEE_Result versal_gpio_pmc_init(struct versal_gpio_chip *chip) +{ + if (chip->base) + return TEE_SUCCESS; + + chip->plat.p_data = &versal_gpio_pmc_def; + chip->plat.base = VERSAL_GPIO_PMC_BASE; + chip->chip.ops = &versal_gpio_ops; + + chip->base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + VERSAL_GPIO_PMC_BASE, + VERSAL_GPIO_LEN); + if (!chip->base) { + EMSG("Failed to map gpio"); + chip->chip.ops = NULL; + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +TEE_Result versal_gpio_ps_init(struct versal_gpio_chip *chip) +{ + if (chip->base) + return TEE_SUCCESS; + + chip->plat.p_data = &versal_gpio_ps_def; + chip->plat.base = VERSAL_GPIO_PS_BASE; + chip->chip.ops = &versal_gpio_ops; + + chip->base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + VERSAL_GPIO_PS_BASE, + VERSAL_GPIO_LEN); + if (!chip->base) { + EMSG("Failed to map gpio"); + chip->chip.ops = NULL; + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/versal_huk.c b/optee/optee_os/core/drivers/versal_huk.c new file mode 100644 index 0000000..1260c02 --- /dev/null +++ b/optee/optee_os/core/drivers/versal_huk.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Foundries.io Ltd. + * Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct { + uint8_t key[HW_UNIQUE_KEY_LENGTH]; + bool ready; +} huk; + +#define MODULE_SHIFT 8 +#define MODULE_ID 5 +#define API_ID(__x) ((MODULE_ID << MODULE_SHIFT) | (__x)) + +#define VERSAL_AES_KEY_SIZE_256 2 +#define VERSAL_AES_GCM_ENCRYPT 0 + +enum versal_aes_key_src { + VERSAL_AES_BBRAM_KEY = 0, + VERSAL_AES_BBRAM_RED_KEY, + VERSAL_AES_BH_KEY, + VERSAL_AES_BH_RED_KEY, + VERSAL_AES_EFUSE_KEY, + VERSAL_AES_EFUSE_RED_KEY, + VERSAL_AES_EFUSE_USER_KEY_0, + VERSAL_AES_EFUSE_USER_KEY_1, + VERSAL_AES_EFUSE_USER_RED_KEY_0, + VERSAL_AES_EFUSE_USER_RED_KEY_1, + VERSAL_AES_KUP_KEY, + VERSAL_AES_PUF_KEY, + VERSAL_AES_USER_KEY_0, + VERSAL_AES_USER_KEY_1, + VERSAL_AES_USER_KEY_2, + VERSAL_AES_USER_KEY_3, + VERSAL_AES_USER_KEY_4, + VERSAL_AES_USER_KEY_5, + VERSAL_AES_USER_KEY_6, + VERSAL_AES_USER_KEY_7, + VERSAL_AES_EXPANDED_KEYS, + VERSAL_AES_ALL_KEYS, +}; + +enum versal_crypto_api { + VERSAL_AES_INIT = 96U, + VERSAL_AES_OP_INIT, + VERSAL_AES_UPDATE_AAD, + VERSAL_AES_ENCRYPT_UPDATE, + VERSAL_AES_ENCRYPT_FINAL, + VERSAL_AES_DECRYPT_UPDATE, + VERSAL_AES_DECRYPT_FINAL, + VERSAL_AES_KEY_ZERO, + VERSAL_AES_WRITE_KEY, + VERSAL_AES_LOCK_USER_KEY, + VERSAL_AES_KEK_DECRYPT, + VERSAL_AES_SET_DPA_CM, + VERSAL_AES_DECRYPT_KAT, + VERSAL_AES_DECRYPT_CM_KAT, +}; + +struct versal_aes_input_param { + uint64_t input_addr; + uint32_t input_len; + uint32_t is_last; +}; + +struct versal_aes_init { + uint64_t iv_addr; + uint32_t operation; + uint32_t key_src; + uint32_t key_len; +}; + +/* + * The PLM is little endian. When programming the keys in uint32_t the driver + * will BE swap the values. + * + * This way the test key below corresponds to the byte array 0xf8, 0x78, 0xb8, + * 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, .... + * + * NOTICE: This hardcoded value in DEVEL_KEY could have just been zeroes as done + * in the weak implementation found in otp_stubs.c. + */ +#define DEVEL_KEY { \ + 0xf878b838, 0xd8589818, 0xe868a828, 0xc8488808, \ + 0xf070b030, 0xd0509010, 0xe060a020, 0xc0408000, \ + } + +#define AAD { \ + 0x67, 0xe2, 0x1c, 0xf3, 0xcb, 0x29, 0xe0, 0xdc, 0xbc, 0x4d, \ + 0x8b, 0x1d, 0x0c, 0xc5, 0x33, 0x4b, \ + } + +#define NONCE { \ + 0xd2, 0x45, 0x0e, 0x07, 0xea, 0x5d, 0xe0, 0x42, 0x6c, 0x0f, \ + 0xa1, 0x33, \ + } + +static bool versal_persistent_key(enum versal_aes_key_src src, bool *secure) +{ + struct versal_efuse_puf_sec_ctrl_bits puf_ctrl = { }; + struct versal_efuse_sec_ctrl_bits ctrl = { }; + struct versal_puf_data puf_data = { }; + struct versal_puf_cfg cfg = { + .global_var_filter = VERSAL_PUF_GLBL_VAR_FLTR_OPTION, + .read_option = VERSAL_PUF_READ_FROM_EFUSE_CACHE, + .puf_operation = VERSAL_PUF_REGEN_ON_DEMAND, + .shutter_value = VERSAL_PUF_SHUTTER_VALUE, + .reg_mode = VERSAL_PUF_SYNDROME_MODE_4K, + }; + + switch (src) { + case VERSAL_AES_EFUSE_USER_KEY_0: + if (versal_efuse_read_sec_ctrl(&ctrl)) + panic(); + + *secure = ctrl.user_key0_wr_lk; + return true; + + case VERSAL_AES_EFUSE_USER_KEY_1: + if (versal_efuse_read_sec_ctrl(&ctrl)) + panic(); + + *secure = ctrl.user_key1_wr_lk; + return true; + + case VERSAL_AES_PUF_KEY: + if (versal_efuse_read_puf_sec_ctrl(&puf_ctrl)) + panic(); + + if (versal_puf_regenerate(&puf_data, &cfg)) + panic(); + + *secure = puf_ctrl.puf_syn_lk; + return true; + + case VERSAL_AES_USER_KEY_0: + *secure = false; + return false; + + default: + EMSG("Trying to use an invalid key for the HUK"); + panic(); + } + + return false; +} + +/* Encrypt using an AES-GCM key selectable with CFG_VERSAL_HUK_KEY */ +static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len) +{ + struct versal_aes_input_param *input = NULL; + struct versal_aes_init *init = NULL; + struct versal_mbox_mem input_cmd = { }; + struct versal_mbox_mem init_buf = { }; + struct versal_mbox_mem p = { }; + struct versal_mbox_mem q = { }; + uint32_t key_data[8] = DEVEL_KEY; + uint8_t nce_data[12] = NONCE; + uint8_t aad_data[16] = AAD; + size_t nce_len = sizeof(nce_data); + size_t key_len = sizeof(key_data); + size_t aad_len = sizeof(aad_data); + TEE_Result ret = TEE_SUCCESS; + struct versal_ipi_cmd cmd = { }; + bool secure = false; + size_t i = 0; + uint32_t key_id = CFG_VERSAL_HUK_KEY; + + if (key_id > VERSAL_AES_ALL_KEYS) + return TEE_ERROR_BAD_PARAMETERS; + + cmd.data[0] = API_ID(VERSAL_AES_INIT); + if (versal_mbox_notify(&cmd, NULL, NULL)) { + EMSG("AES_INIT error"); + return TEE_ERROR_GENERIC; + } + + if (!versal_persistent_key(key_id, &secure)) { + for (i = 0; i < ARRAY_SIZE(key_data); i++) + key_data[i] = TEE_U32_BSWAP(key_data[i]); + + versal_mbox_alloc(key_len, key_data, &p); + cmd.data[0] = API_ID(VERSAL_AES_WRITE_KEY); + cmd.data[1] = VERSAL_AES_KEY_SIZE_256; + cmd.data[2] = key_id; + reg_pair_from_64(virt_to_phys(p.buf), + &cmd.data[4], &cmd.data[3]); + cmd.ibuf[0].mem = p; + if (versal_mbox_notify(&cmd, NULL, NULL)) { + EMSG("AES_WRITE_KEY error"); + ret = TEE_ERROR_GENERIC; + } + free(p.buf); + memset(&cmd, 0, sizeof(cmd)); + if (ret) + return ret; + } + + /* Trace indication that it is safe to generate a RPMB key */ + IMSG("Using %s HUK", secure ? "Production" : "Development"); + + versal_mbox_alloc(sizeof(*init), NULL, &init_buf); + versal_mbox_alloc(nce_len, nce_data, &p); + init = init_buf.buf; + init->operation = VERSAL_AES_GCM_ENCRYPT; + init->key_len = VERSAL_AES_KEY_SIZE_256; + init->iv_addr = virt_to_phys(p.buf); + init->key_src = key_id; + cmd.data[0] = API_ID(VERSAL_AES_OP_INIT); + reg_pair_from_64(virt_to_phys(init), &cmd.data[2], &cmd.data[1]); + cmd.ibuf[0].mem = init_buf; + cmd.ibuf[1].mem = p; + if (versal_mbox_notify(&cmd, NULL, NULL)) { + EMSG("AES_OP_INIT error"); + ret = TEE_ERROR_GENERIC; + } + free(init); + free(p.buf); + memset(&cmd, 0, sizeof(cmd)); + if (ret) + return ret; + + versal_mbox_alloc(aad_len, aad_data, &p); + cmd.data[0] = API_ID(VERSAL_AES_UPDATE_AAD); + reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[2], &cmd.data[1]); + if (p.len % 16) + cmd.data[3] = p.alloc_len; + else + cmd.data[3] = p.len; + cmd.ibuf[0].mem = p; + if (versal_mbox_notify(&cmd, NULL, NULL)) { + EMSG("AES_UPDATE_AAD error"); + ret = TEE_ERROR_GENERIC; + } + free(p.buf); + memset(&cmd, 0, sizeof(cmd)); + if (ret) + return ret; + + versal_mbox_alloc(sizeof(*input), NULL, &input_cmd); + versal_mbox_alloc(src_len, src, &p); + versal_mbox_alloc(dst_len, NULL, &q); + input = input_cmd.buf; + input->input_addr = virt_to_phys(p.buf); + input->input_len = p.len; + input->is_last = true; + cmd.data[0] = API_ID(VERSAL_AES_ENCRYPT_UPDATE); + reg_pair_from_64(virt_to_phys(input), &cmd.data[2], &cmd.data[1]); + reg_pair_from_64(virt_to_phys(q.buf), &cmd.data[4], &cmd.data[3]); + cmd.ibuf[0].mem = input_cmd; + cmd.ibuf[1].mem = p; + cmd.ibuf[2].mem = q; + if (versal_mbox_notify(&cmd, NULL, NULL)) { + EMSG("AES_UPDATE_PAYLOAD error"); + ret = TEE_ERROR_GENERIC; + } + memcpy(dst, q.buf, dst_len); + free(input); + free(p.buf); + free(q.buf); + memset(&cmd, 0, sizeof(cmd)); + if (ret) + return ret; + + versal_mbox_alloc(16, NULL, &p); + cmd.data[0] = API_ID(VERSAL_AES_ENCRYPT_FINAL); + reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[2], &cmd.data[1]); + if (versal_mbox_notify(&cmd, NULL, NULL)) { + EMSG("AES_ENCRYPT_FINAL error"); + ret = TEE_ERROR_GENERIC; + } + free(p.buf); + memzero_explicit(&cmd, sizeof(cmd)); + + return ret; +} + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + uint32_t dna[EFUSE_DNA_LEN / sizeof(uint32_t)] = { }; + uint8_t enc_data[64] = { }; + uint8_t sha[48] = { }; + TEE_Result ret = TEE_SUCCESS; + + if (huk.ready) + goto out; + + if (versal_efuse_read_dna(dna, sizeof(dna))) + return TEE_ERROR_GENERIC; + + if (versal_sha3_384((uint8_t *)dna, sizeof(dna), sha, sizeof(sha))) { + ret = TEE_ERROR_GENERIC; + goto cleanup; + } + + if (aes_gcm_encrypt(sha, sizeof(sha), enc_data, sizeof(enc_data))) { + ret = TEE_ERROR_GENERIC; + goto cleanup; + } + + if (tee_hash_createdigest(TEE_ALG_SHA256, enc_data, sizeof(enc_data), + huk.key, sizeof(huk.key))) { + ret = TEE_ERROR_GENERIC; + goto cleanup; + } + +cleanup: + memzero_explicit(enc_data, sizeof(enc_data)); + memzero_explicit(dna, sizeof(dna)); + memzero_explicit(sha, sizeof(sha)); + + if (ret) + return ret; + + huk.ready = true; +out: + memcpy(hwkey->data, huk.key, HW_UNIQUE_KEY_LENGTH); + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/versal_mbox.c b/optee/optee_os/core/drivers/versal_mbox.c new file mode 100644 index 0000000..2f27627 --- /dev/null +++ b/optee/optee_os/core/drivers/versal_mbox.c @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022 Foundries.io Ltd + * Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include "drivers/versal_mbox.h" + +#define PM_SIP_SVC 0xc2000000 + +/* IPI targets */ +#define IPI_ID_PMC 1 +#define IPI_ID_0 2 +#define IPI_ID_RPU0 3 +#define IPI_ID_RPU1 4 +#define IPI_ID_3 5 +#define IPI_ID_4 6 +#define IPI_ID_5 7 + +/* Buffers */ +#define IPI_BUFFER_BASEADDR 0xFF3F0000 +#define IPI_BUFFER_APU_ID_0_BASE (IPI_BUFFER_BASEADDR + 0x400) +#define IPI_BUFFER_APU_ID_3_BASE (IPI_BUFFER_BASEADDR + 0xA00) +#define IPI_BUFFER_APU_ID_4_BASE (IPI_BUFFER_BASEADDR + 0xC00) +#define IPI_BUFFER_APU_ID_5_BASE (IPI_BUFFER_BASEADDR + 0xE00) +#define IPI_BUFFER_PMC_BASE (IPI_BUFFER_BASEADDR + 0x200) +#define IPI_BUFFER_TARGET_APU_OFFSET 0x80 +#define IPI_BUFFER_TARGET_PMC_OFFSET 0x40 +#define IPI_BUFFER_REQ_OFFSET 0x0 +#define IPI_BUFFER_RESP_OFFSET 0x20 + +#define IPI_BUFFER_LOCAL_OFFSET IPI_BUFFER_TARGET_APU_OFFSET +#define IPI_BUFFER_REMOTE_OFFSET IPI_BUFFER_TARGET_PMC_OFFSET + +#define IPI_BLOCK 1 +#define IPI_NON_BLOCK 0 + +/* Mailbox api */ +enum versal_ipi_api_id { + IPI_MAILBOX_OPEN = 0x1000, + IPI_MAILBOX_RELEASE, + IPI_MAILBOX_STATUS_ENQUIRY, + IPI_MAILBOX_NOTIFY, + IPI_MAILBOX_ACK, + IPI_MAILBOX_ENABLE_IRQ, + IPI_MAILBOX_DISABLE_IRQ +}; + +static struct versal_ipi { + uint32_t lcl; + const uint32_t rmt; + paddr_t buf; + /* Exclusive access to the IPI shared buffer */ + struct mutex lock; + void *rsp; + void *req; +} ipi = { + .buf = IPI_BUFFER_APU_ID_3_BASE, + .rmt = IPI_ID_PMC, + .lcl = IPI_ID_3, +}; + +static const char *const nvm_id[] = { + [0] = "API_FEATURES", + [1] = "BBRAM_WRITE_AES_KEY", + [2] = "BBRAM_ZEROIZE", + [3] = "BBRAM_WRITE_USER_DATA", + [4] = "BBRAM_READ_USER_DATA", + [5] = "BBRAM_LOCK_WRITE_USER_DATA", + [6] = "EFUSE_WRITE", + [7] = "EFUSE_WRITE_PUF", + [8] = "EFUSE_PUF_USER_FUSE_WRITE", + [9] = "EFUSE_READ_IV", + [10] = "EFUSE_READ_REVOCATION_ID", + [11] = "EFUSE_READ_OFFCHIP_REVOCATION_ID", + [12] = "EFUSE_READ_USER_FUSES", + [13] = "EFUSE_READ_MISC_CTRL", + [14] = "EFUSE_READ_SEC_CTRL", + [15] = "EFUSE_READ_SEC_MISC1", + [16] = "EFUSE_READ_BOOT_ENV_CTRL", + [17] = "EFUSE_READ_PUF_SEC_CTRL", + [18] = "EFUSE_READ_PPK_HASH", + [19] = "EFUSE_READ_DEC_EFUSE_ONLY", + [20] = "EFUSE_READ_DNA", + [21] = "EFUSE_READ_PUF_USER_FUSES", + [22] = "EFUSE_READ_PUF", + [23] = "EFUSE_INVALID", +}; + +static const char *const crypto_id[] = { + [0] = "FEATURES", + [1] = "RSA_SIGN_VERIFY", + [2] = "RSA_PUBLIC_ENCRYPT", + [3] = "RSA_PRIVATE_DECRYPT", + [4] = "RSA_KAT", + [32] = "SHA3_UPDATE", + [33] = "SHA3_KAT", + [64] = "ELLIPTIC_GENERATE_PUBLIC_KEY", + [65] = "ELLIPTIC_GENERATE_SIGN", + [66] = "ELLIPTIC_VALIDATE_PUBLIC_KEY", + [67] = "ELLIPTIC_VERIFY_SIGN", + [68] = "ELLIPTIC_KAT", + [96] = "AES_INIT", + [97] = "AES_OP_INIT", + [98] = "AES_UPDATE_AAD", + [99] = "AES_ENCRYPT_UPDATE", + [100] = "AES_ENCRYPT_FINAL", + [101] = "AES_DECRYPT_UPDATE", + [102] = "AES_DECRYPT_FINAL", + [103] = "AES_KEY_ZERO", + [104] = "AES_WRITE_KEY", + [105] = "AES_LOCK_USER_KEY", + [106] = "AES_KEK_DECRYPT", + [107] = "AES_SET_DPA_CM", + [108] = "AES_DECRYPT_KAT", + [109] = "AES_DECRYPT_CM_KAT", + [110] = "MAX", +}; + +static const char *const puf_id[] = { + [0] = "PUF_API_FEATURES", + [1] = "PUF_REGISTRATION", + [2] = "PUF_REGENERATION", + [3] = "PUF_CLEAR_PUF_ID", +}; + +static const char *const module[] = { + [5] = "CRYPTO", + [7] = "FPGA", + [11] = "NVM", + [12] = "PUF", +}; + +static const char *const fpga_id[] = { + [1] = "LOAD", +}; + +static void versal_mbox_call_trace(uint32_t call) +{ + uint32_t mid = call >> 8 & 0xff; + uint32_t api = call & 0xff; + const char *val = NULL; + + switch (mid) { + case 5: + if (api < ARRAY_SIZE(crypto_id)) + val = crypto_id[api]; + + break; + case 7: + if (api < ARRAY_SIZE(fpga_id)) + val = fpga_id[api]; + + break; + case 11: + if (api < ARRAY_SIZE(nvm_id)) + val = nvm_id[api]; + + break; + case 12: + if (api < ARRAY_SIZE(puf_id)) + val = puf_id[api]; + + break; + default: + break; + } + + IMSG("--- mbox: service: %s\t call: %s", module[mid], + val ? val : "Invalid"); +}; + +static TEE_Result mbox_call(enum versal_ipi_api_id id, uint32_t blocking_call) +{ + struct thread_smc_args args = { + .a0 = PM_SIP_SVC | id, + .a1 = reg_pair_to_64(0, ipi.lcl), + .a2 = reg_pair_to_64(0, ipi.rmt), + .a3 = reg_pair_to_64(0, blocking_call), + }; + + thread_smccc(&args); + + /* Give the PLM time to access the console */ + if (IS_ENABLED(CFG_VERSAL_TRACE_PLM)) + mdelay(500); + + if (args.a0) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result versal_mbox_write_req(struct versal_ipi_cmd *cmd) +{ + size_t i = 0; + + for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { + if (!cmd->ibuf[i].mem.buf) + continue; + + if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf, + CACHELINE_LEN)) { + EMSG("address not aligned: buffer %zu - %p", i, + cmd->ibuf[i].mem.buf); + return TEE_ERROR_GENERIC; + } + + if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) { + EMSG("length not aligned: buffer %zu - %zu", + i, cmd->ibuf[i].mem.alloc_len); + return TEE_ERROR_GENERIC; + } + + cache_operation(TEE_CACHEFLUSH, cmd->ibuf[i].mem.buf, + cmd->ibuf[i].mem.alloc_len); + } + + memcpy(ipi.req, cmd->data, sizeof(cmd->data)); + + /* Cache operation on the IPI buffer is safe */ + cache_operation(TEE_CACHEFLUSH, ipi.req, sizeof(cmd->data)); + + return TEE_SUCCESS; +} + +static TEE_Result versal_mbox_read_rsp(struct versal_ipi_cmd *cmd, + struct versal_ipi_cmd *rsp, + uint32_t *status) +{ + size_t i = 0; + + /* Cache operation on the IPI buffer is safe */ + cache_operation(TEE_CACHEINVALIDATE, ipi.rsp, sizeof(rsp->data)); + + *status = *(uint32_t *)ipi.rsp; + + if (*status) + return TEE_ERROR_GENERIC; + + if (rsp) + memcpy(rsp->data, ipi.rsp, sizeof(rsp->data)); + + for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { + if (!cmd->ibuf[i].mem.buf) + continue; + + if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf, + CACHELINE_LEN)) { + EMSG("address not aligned: buffer %zu - %p", + i, cmd->ibuf[i].mem.buf); + return TEE_ERROR_GENERIC; + } + + if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) { + EMSG("length not aligned: buffer %zu - %zu", + i, cmd->ibuf[i].mem.alloc_len); + return TEE_ERROR_GENERIC; + } + + cache_operation(TEE_CACHEINVALIDATE, + cmd->ibuf[i].mem.buf, + cmd->ibuf[i].mem.alloc_len); + } + + return TEE_SUCCESS; +} + +TEE_Result versal_mbox_alloc(size_t len, const void *init, + struct versal_mbox_mem *mem) +{ + mem->buf = memalign(CACHELINE_LEN, ROUNDUP(len, CACHELINE_LEN)); + if (!mem->buf) + panic(); + + memset(mem->buf, 0, ROUNDUP(len, CACHELINE_LEN)); + + if (init) + memcpy(mem->buf, init, len); + + mem->alloc_len = ROUNDUP(len, CACHELINE_LEN); + mem->len = len; + + return TEE_SUCCESS; +} + +TEE_Result versal_mbox_notify(struct versal_ipi_cmd *cmd, + struct versal_ipi_cmd *rsp, uint32_t *err) +{ + TEE_Result ret = TEE_SUCCESS; + uint32_t remote_status = 0; + + mutex_lock(&ipi.lock); + + ret = versal_mbox_write_req(cmd); + if (ret) { + EMSG("Can't write the request command"); + goto out; + } + + if (IS_ENABLED(CFG_VERSAL_TRACE_MBOX)) + versal_mbox_call_trace(cmd->data[0]); + + ret = mbox_call(IPI_MAILBOX_NOTIFY, IPI_BLOCK); + if (ret) { + EMSG("IPI error"); + goto out; + } + + ret = versal_mbox_read_rsp(cmd, rsp, &remote_status); + if (ret) + EMSG("Can't read the remote response"); + + if (remote_status) { + if (err) + *err = remote_status; + /* + * Check the remote code (FSBL repository) in xplmi_status.h + * and the relevant service error (ie, xsecure_error.h) for + * detailed information. + */ + DMSG("PLM: plm status = 0x%" PRIx32 ", lib_status = 0x%" PRIx32, + (remote_status & 0xFFFF0000) >> 16, + (remote_status & 0x0000FFFF)); + + ret = TEE_ERROR_GENERIC; + } +out: + mutex_unlock(&ipi.lock); + + return ret; +} + +static TEE_Result versal_mbox_init(void) +{ + switch (CFG_VERSAL_MBOX_IPI_ID) { + case 0: + ipi.buf = IPI_BUFFER_APU_ID_0_BASE; + ipi.lcl = IPI_ID_0; + break; + case 3: + break; + case 4: + ipi.buf = IPI_BUFFER_APU_ID_4_BASE; + ipi.lcl = IPI_ID_4; + break; + case 5: + ipi.buf = IPI_BUFFER_APU_ID_5_BASE; + ipi.lcl = IPI_ID_5; + break; + default: + EMSG("Invalid IPI requested"); + return TEE_ERROR_GENERIC; + } + + ipi.req = core_mmu_add_mapping(MEM_AREA_RAM_SEC, + ipi.buf + IPI_BUFFER_REMOTE_OFFSET + + IPI_BUFFER_REQ_OFFSET, + sizeof(struct versal_ipi_cmd)); + + ipi.rsp = core_mmu_add_mapping(MEM_AREA_RAM_SEC, + ipi.buf + IPI_BUFFER_REMOTE_OFFSET + + IPI_BUFFER_RESP_OFFSET, + sizeof(struct versal_ipi_cmd)); + if (!ipi.req || !ipi.rsp) + panic(); + + mutex_init(&ipi.lock); + + return mbox_call(IPI_MAILBOX_OPEN, IPI_BLOCK); +} +early_init(versal_mbox_init); diff --git a/optee/optee_os/core/drivers/versal_nvm.c b/optee/optee_os/core/drivers/versal_nvm.c new file mode 100644 index 0000000..b17ae63 --- /dev/null +++ b/optee/optee_os/core/drivers/versal_nvm.c @@ -0,0 +1,1005 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022 Foundries.io Ltd + * Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drivers/versal_nvm.h" + +#define NVM_WORD_LEN 4 + +/* Protocol API with the remote processor */ +#define NVM_MODULE_SHIFT 8 +#define NVM_MODULE 11 +#define NVM_API_ID(_id) ((NVM_MODULE << NVM_MODULE_SHIFT) | (_id)) + +#define __aligned_efuse __aligned(CACHELINE_LEN) + +/* Internal */ +struct versal_efuse_puf_fuse_addr { + uint64_t data_addr; + uint32_t start_row; + uint32_t num_rows; + uint8_t env_monitor_dis; + uint8_t prgm_puf_fuse; + uint8_t pad[46]; +}; + +/* + * Max size of the buffer needed for the remote processor to DMA efuse _data_ + * to/from + */ +#define EFUSE_MAX_LEN (EFUSE_MAX_USER_FUSES * sizeof(uint32_t)) + +enum versal_nvm_api_id { + API_FEATURES = 0, + BBRAM_WRITE_AES_KEY = 1, + BBRAM_ZEROIZE = 2, + BBRAM_WRITE_USER_DATA = 3, + BBRAM_READ_USER_DATA = 4, + BBRAM_LOCK_WRITE_USER_DATA = 5, + EFUSE_WRITE = 6, + EFUSE_WRITE_PUF = 7, + EFUSE_PUF_USER_FUSE_WRITE = 8, + EFUSE_READ_IV = 9, + EFUSE_READ_REVOCATION_ID = 10, + EFUSE_READ_OFFCHIP_REVOCATION_ID = 11, + EFUSE_READ_USER_FUSES = 12, + EFUSE_READ_MISC_CTRL = 13, + EFUSE_READ_SEC_CTRL = 14, + EFUSE_READ_SEC_MISC1 = 15, + EFUSE_READ_BOOT_ENV_CTRL = 16, + EFUSE_READ_PUF_SEC_CTRL = 17, + EFUSE_READ_PPK_HASH = 18, + EFUSE_READ_DEC_EFUSE_ONLY = 19, + EFUSE_READ_DNA = 20, + EFUSE_READ_PUF_USER_FUSES = 21, + EFUSE_READ_PUF = 22, + EFUSE_INVALID = 23, +}; + +/* uint64_t are memory addresses */ +struct versal_efuse_data { + uint64_t env_mon_dis_flag; + uint64_t aes_key_addr; + uint64_t ppk_hash_addr; + uint64_t dec_only_addr; + uint64_t sec_ctrl_addr; + uint64_t misc_ctrl_addr; + uint64_t revoke_id_addr; + uint64_t iv_addr; + uint64_t user_fuse_addr; + uint64_t glitch_cfg_addr; + uint64_t boot_env_ctrl_addr; + uint64_t misc1_ctrl_addr; + uint64_t offchip_id_addr; + uint8_t pad[24]; +}; + +/* Helper read and write requests (not part of the protocol) */ +struct versal_nvm_buf { + size_t len; + void *buf; +}; + +struct versal_nvm_read_req { + enum versal_nvm_api_id efuse_id; + enum versal_nvm_revocation_id revocation_id; + enum versal_nvm_offchip_id offchip_id; + enum versal_nvm_ppk_type ppk_type; + enum versal_nvm_iv_type iv_type; + struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF]; +}; + +struct versal_bbram_data { + size_t aes_key_len; + uint32_t user_data; +}; + +struct versal_nvm_write_req { + struct versal_efuse_data data; + struct versal_bbram_data bbram; + struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF]; + enum versal_nvm_api_id efuse_id; +}; + +static TEE_Result +prepare_cmd(struct versal_ipi_cmd *cmd, enum versal_nvm_api_id efuse, + struct versal_nvm_buf *ibufs, uint32_t *arg) +{ + uint32_t a = 0; + uint32_t b = 0; + size_t i = 0; + + cmd->data[i++] = NVM_API_ID(efuse); + if (arg) + cmd->data[i++] = *arg; + + if (!ibufs[0].buf) + return TEE_SUCCESS; + + reg_pair_from_64(virt_to_phys(ibufs[0].buf), &b, &a); + + cmd->data[i++] = a; + cmd->data[i++] = b; + + for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { + cmd->ibuf[i].mem.alloc_len = ibufs[i].len; + cmd->ibuf[i].mem.buf = ibufs[i].buf; + } + + return TEE_SUCCESS; +} + +static TEE_Result efuse_req(enum versal_nvm_api_id efuse, + struct versal_nvm_buf *ibufs, uint32_t *arg) +{ + struct versal_ipi_cmd cmd = { }; + TEE_Result ret = TEE_SUCCESS; + + ret = prepare_cmd(&cmd, efuse, ibufs, arg); + if (ret) + return ret; + + ret = versal_mbox_notify(&cmd, NULL, NULL); + if (ret) + EMSG("Mailbox error"); + + return ret; +} + +static TEE_Result versal_alloc_read_buffer(struct versal_nvm_read_req *req) +{ + assert(req); + req->ibuf[0].len = 1024; + req->ibuf[0].buf = alloc_cache_aligned(req->ibuf[0].len); + if (!req->ibuf[0].buf) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} + +static void versal_free_read_buffer(struct versal_nvm_read_req *req) +{ + assert(req); + free(req->ibuf[0].buf); +} + +static void *versal_get_read_buffer(struct versal_nvm_read_req *req) +{ + assert(req); + return req->ibuf[0].buf; +} + +static TEE_Result versal_nvm_read(struct versal_nvm_read_req *req) +{ + uint32_t *arg = NULL; + uint32_t val = 0; + + if (!req) + return TEE_ERROR_GENERIC; + + switch (req->efuse_id) { + case EFUSE_READ_DNA: + case EFUSE_READ_DEC_EFUSE_ONLY: + case EFUSE_READ_PUF_SEC_CTRL: + case EFUSE_READ_BOOT_ENV_CTRL: + case EFUSE_READ_SEC_CTRL: + case EFUSE_READ_MISC_CTRL: + case EFUSE_READ_SEC_MISC1: + case EFUSE_READ_USER_FUSES: + case EFUSE_READ_PUF_USER_FUSES: + case EFUSE_READ_PUF: + break; + case EFUSE_READ_OFFCHIP_REVOCATION_ID: + val = req->offchip_id; + arg = &val; + break; + case EFUSE_READ_REVOCATION_ID: + val = req->revocation_id; + arg = &val; + break; + case EFUSE_READ_IV: + val = req->iv_type; + arg = &val; + break; + case EFUSE_READ_PPK_HASH: + val = req->ppk_type; + arg = &val; + break; + case BBRAM_READ_USER_DATA: + break; + default: + return TEE_ERROR_GENERIC; + } + + return efuse_req(req->efuse_id, req->ibuf, arg); +} + +static TEE_Result versal_nvm_write(struct versal_nvm_write_req *req) +{ + uint32_t *arg = NULL; + uint32_t val = 0; + + switch (req->efuse_id) { + case BBRAM_WRITE_AES_KEY: + val = req->bbram.aes_key_len; + arg = &val; + break; + case BBRAM_WRITE_USER_DATA: + val = req->bbram.user_data; + arg = &val; + break; + case EFUSE_PUF_USER_FUSE_WRITE: + case EFUSE_WRITE_PUF: + case EFUSE_WRITE: + break; + default: + return TEE_ERROR_GENERIC; + } + + return efuse_req(req->efuse_id, req->ibuf, arg); +} + +TEE_Result versal_efuse_read_user_data(uint32_t *buf, size_t len, + uint32_t first, size_t num) +{ + struct versal_efuse_user_data cfg __aligned_efuse = { + .start = first, + .num = num, + }; + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_USER_FUSES, + }; + void *rsp = NULL; + + if (first + num > EFUSE_MAX_USER_FUSES || len < num * sizeof(uint32_t)) + return TEE_ERROR_BAD_PARAMETERS; + + rsp = alloc_cache_aligned(1024); + if (!rsp) + return TEE_ERROR_OUT_OF_MEMORY; + + req.ibuf[0].buf = &cfg; + req.ibuf[0].len = sizeof(cfg); + req.ibuf[1].buf = rsp; + req.ibuf[1].len = 1024; + + cfg.addr = virt_to_phys((void *)rsp); + + if (versal_nvm_read(&req)) { + free(rsp); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, rsp, num * sizeof(uint32_t)); + free(rsp); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_dna(uint32_t *buf, size_t len) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_DNA, + }; + + if (len < EFUSE_DNA_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), EFUSE_DNA_LEN); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_iv(uint32_t *buf, size_t len, + enum versal_nvm_iv_type type) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_IV, + .iv_type = type, + }; + + if (len < EFUSE_IV_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), EFUSE_IV_LEN); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_ppk(uint32_t *buf, size_t len, + enum versal_nvm_ppk_type type) +{ + struct versal_nvm_read_req req = { + req.efuse_id = EFUSE_READ_PPK_HASH, + .ppk_type = type, + }; + + if (len < EFUSE_PPK_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) + return TEE_ERROR_GENERIC; + + memcpy(buf, versal_get_read_buffer(&req), EFUSE_PPK_LEN); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_write_user_data(uint32_t *buf, size_t len, + uint32_t first, size_t num) +{ + uint32_t lbuf[EFUSE_MAX_USER_FUSES] __aligned_efuse = { 0 }; + struct versal_efuse_user_data cfg __aligned_efuse = { + .addr = (uintptr_t)lbuf, + .start = first, + .num = num, + }; + struct versal_nvm_write_req __aligned_efuse req = { + .data.user_fuse_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + size_t i = 0; + + if (first + num > EFUSE_MAX_USER_FUSES || len < num * sizeof(uint32_t)) + return TEE_ERROR_BAD_PARAMETERS; + + req.data.user_fuse_addr = virt_to_phys((void *)req.data.user_fuse_addr); + cfg.addr = virt_to_phys(lbuf); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + req.ibuf[2].buf = lbuf; + req.ibuf[2].len = sizeof(lbuf); + + for (i = 0; i < cfg.num; i++) + lbuf[i] = buf[i]; + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_aes_keys(struct versal_efuse_aes_keys *keys) +{ + struct versal_efuse_aes_keys cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.aes_key_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, keys, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash *hash) +{ + struct versal_efuse_ppk_hash cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.ppk_hash_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, hash, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_iv(struct versal_efuse_ivs *p) +{ + struct versal_efuse_ivs cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.iv_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, p, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_dec_only(struct versal_efuse_dec_only *p) +{ + struct versal_efuse_dec_only cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.dec_only_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, p, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits *p) +{ + struct versal_efuse_sec_ctrl_bits cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.sec_ctrl_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, p, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits *p) +{ + struct versal_efuse_misc_ctrl_bits cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.misc_ctrl_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, p, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits *p) +{ + struct versal_efuse_glitch_cfg_bits cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.glitch_cfg_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, p, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits + *p) +{ + struct versal_efuse_boot_env_ctrl_bits cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.boot_env_ctrl_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, p, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits *p) +{ + struct versal_efuse_sec_misc1_bits cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.misc1_ctrl_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, p, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids *p) +{ + struct versal_efuse_offchip_ids cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.offchip_id_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + memcpy(&cfg, p, sizeof(cfg)); + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type) +{ + struct versal_efuse_misc_ctrl_bits cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.misc_ctrl_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + + req.data.misc_ctrl_addr = virt_to_phys((void *)req.data.misc_ctrl_addr); + if (type == EFUSE_PPK0) + cfg.ppk0_invalid = 1; + else if (type == EFUSE_PPK1) + cfg.ppk1_invalid = 1; + else if (type == EFUSE_PPK2) + cfg.ppk2_invalid = 1; + else + return TEE_ERROR_BAD_PARAMETERS; + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_write_revoke_id(uint32_t id) +{ + struct versal_efuse_revoke_ids cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .data.revoke_id_addr = virt_to_phys(&cfg), + .data.env_mon_dis_flag = 1, + .efuse_id = EFUSE_WRITE, + }; + uint32_t row = 0; + uint32_t bit = 0; + + row = id >> (NVM_WORD_LEN + 1); + bit = id & (NVM_WORD_LEN - 1); + + cfg.revoke_id[row] = BIT(bit); + cfg.prgm_revoke_id = 1; + + req.ibuf[0].buf = &req.data; + req.ibuf[0].len = sizeof(req.data); + req.ibuf[1].buf = &cfg; + req.ibuf[1].len = sizeof(cfg); + + return versal_nvm_write(&req); +} + +TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len, + enum versal_nvm_revocation_id id) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_REVOCATION_ID, + .revocation_id = id, + }; + + if (len < EFUSE_REVOCATION_ID_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), EFUSE_REVOCATION_ID_LEN); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits *buf) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_MISC_CTRL, + }; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits *buf) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_SEC_CTRL, + }; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits *buf) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_SEC_MISC1, + }; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result +versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits *buf) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_BOOT_ENV_CTRL, + }; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len, + enum versal_nvm_offchip_id id) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_OFFCHIP_REVOCATION_ID, + .offchip_id = id, + }; + + if (len < EFUSE_OFFCHIP_REVOCATION_ID_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), EFUSE_REVOCATION_ID_LEN); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_dec_only(uint32_t *buf, size_t len) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_DEC_EFUSE_ONLY, + }; + + if (len < EFUSE_DEC_ONLY_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), EFUSE_DEC_ONLY_LEN); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result +versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits *buf) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_PUF_SEC_CTRL, + }; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_read_puf(struct versal_efuse_puf_header *buf) +{ + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_PUF, + }; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(versal_get_read_buffer(&req), buf, sizeof(*buf)); + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +/* + * This functionality requires building the PLM with XNVM_ACCESS_PUF_USER_DATA + * Calls will fail otherwise. + * When available, efuse_read_puf becomes unavailable. + */ +TEE_Result +versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse *p) +{ + uint32_t fuses[PUF_EFUSES_WORDS]__aligned_efuse = { 0 }; + struct versal_efuse_puf_fuse_addr lbuf __aligned_efuse = { + .env_monitor_dis = p->env_monitor_dis, + .prgm_puf_fuse = p->prgm_puf_fuse, + .start_row = p->start_row, + .num_rows = p->num_rows, + .data_addr = virt_to_phys(fuses), + }; + struct versal_nvm_read_req req = { + .efuse_id = EFUSE_READ_PUF_USER_FUSES, + }; + + req.ibuf[0].buf = &lbuf; + req.ibuf[0].len = sizeof(lbuf); + req.ibuf[1].buf = fuses; + req.ibuf[1].len = sizeof(fuses); + + if (versal_nvm_read(&req)) + return TEE_ERROR_GENERIC; + + memcpy(p->data_addr, fuses, sizeof(fuses)); + + return TEE_SUCCESS; +} + +/* + * This functionality requires building the PLM with XNVM_ACCESS_PUF_USER_DATA. + * Calls will fail otherwise. + * When available, efuse_write_puf becomes unavailable. + */ +TEE_Result +versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse *p) +{ + uint32_t fuses[PUF_EFUSES_WORDS]__aligned_efuse = { 0 }; + struct versal_efuse_puf_fuse_addr lbuf __aligned_efuse = { + .env_monitor_dis = p->env_monitor_dis, + .prgm_puf_fuse = p->prgm_puf_fuse, + .start_row = p->start_row, + .num_rows = p->num_rows, + .data_addr = virt_to_phys(fuses), + }; + struct versal_nvm_write_req req = { + .efuse_id = EFUSE_PUF_USER_FUSE_WRITE, + }; + + memcpy(fuses, p->data_addr, sizeof(p->data_addr)); + + req.ibuf[0].buf = &lbuf; + req.ibuf[0].len = sizeof(lbuf); + req.ibuf[1].buf = fuses; + req.ibuf[1].len = sizeof(fuses); + + if (versal_nvm_write(&req)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result versal_efuse_write_puf(struct versal_efuse_puf_header *buf) +{ + struct versal_efuse_puf_header cfg __aligned_efuse = { }; + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = EFUSE_WRITE_PUF, + }; + + memcpy(&cfg, buf, sizeof(*buf)); + + req.ibuf[0].buf = &cfg; + req.ibuf[0].len = sizeof(cfg); + + if (versal_nvm_write(&req)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_write_aes_key(uint8_t *key, size_t len) +{ + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = BBRAM_WRITE_AES_KEY, + .bbram.aes_key_len = len, + }; + void *buf = NULL; + + if (len != 32) + return TEE_ERROR_BAD_PARAMETERS; + + buf = alloc_cache_aligned(1024); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(buf, key, len); + + req.ibuf[0].buf = buf; + req.ibuf[0].len = 1024; + + if (versal_nvm_write(&req)) { + free(buf); + return TEE_ERROR_GENERIC; + } + free(buf); + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_zeroize(void) +{ + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = BBRAM_ZEROIZE, + }; + + if (versal_nvm_write(&req)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_write_user_data(uint32_t data) +{ + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = BBRAM_WRITE_USER_DATA, + .bbram.user_data = data, + }; + + if (versal_nvm_write(&req)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_read_user_data(uint32_t *data) +{ + struct versal_nvm_read_req req = { + .efuse_id = BBRAM_READ_USER_DATA, + }; + + if (versal_alloc_read_buffer(&req)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (versal_nvm_read(&req)) { + versal_free_read_buffer(&req); + return TEE_ERROR_GENERIC; + } + + memcpy(data, versal_get_read_buffer(&req), sizeof(*data)); + versal_free_read_buffer(&req); + + return TEE_SUCCESS; +} + +TEE_Result versal_bbram_lock_write_user_data(void) +{ + struct versal_nvm_write_req req __aligned_efuse = { + .efuse_id = BBRAM_LOCK_WRITE_USER_DATA, + }; + + if (versal_nvm_write(&req)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/versal_pm.c b/optee/optee_os/core/drivers/versal_pm.c new file mode 100644 index 0000000..84b1cbe --- /dev/null +++ b/optee/optee_os/core/drivers/versal_pm.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022 Foundries.io Ltd + * Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* VERSAL_SIP_UID: 2ab9e4ec-93b9-11e7-a019dfe0dbad0ae0 */ +#define VERSAL_SIP_UID_0 U(0xece4b92a) +#define VERSAL_SIP_UID_1 U(0xe711b993) +#define VERSAL_SIP_UID_2 U(0xe0df19a0) +#define VERSAL_SIP_UID_3 U(0xe00aaddb) +#define VERSAL_SIP_MAJOR 0 +#define VERSAL_SIP_MINOR 1 + +#define VERSAL_SIP_SVC_VERSION 0x8200ff03 +#define VERSAL_SIP_SVC_UID 0x8200ff01 +#define VERSAL_SIP_SVC 0xc2000000 + +#define PAYLOAD_ARG_CNT 8 + +/* MBOX IPI */ +#define PM_MODULE_SHIFT 8 +#define PM_MODULE 2 +#define PM_API_ID(x) ((PM_MODULE << PM_MODULE_SHIFT) | (x)) +#define VERSAL_PM_MAJOR 0 +#define VERSAL_PM_MINOR 1 + +/* PM API ids */ +#define PM_GET_API_VERSION 1 +#define PM_GET_DEVICE_STATUS 3 +#define PM_GET_OP_CHARACTERISTIC 4 +#define PM_REGISTER_NOTIFIER 5 +#define PM_REQ_SUSPEND 6 +#define PM_SELF_SUSPEND 7 +#define PM_FORCE_POWERDOWN 8 +#define PM_ABORT_SUSPEND 9 +#define PM_REQ_WAKEUP 10 +#define PM_SET_WAKEUP_SOURCE 11 +#define PM_SYSTEM_SHUTDOWN 12 +#define PM_REQUEST_DEVICE 13 +#define PM_RELEASE_DEVICE 14 +#define PM_SET_REQUIREMENT 15 +#define PM_SET_MAX_LATENCY 16 +#define PM_RESET_ASSERT 17 +#define PM_RESET_GET_STATUS 18 +#define PM_INIT_FINALIZE 21 +#define PM_GET_CHIPID 24 +#define PM_PINCTRL_REQUEST 28 +#define PM_PINCTRL_RELEASE 29 +#define PM_PINCTRL_GET_FUNCTION 30 +#define PM_PINCTRL_SET_FUNCTION 31 +#define PM_PINCTRL_CONFIG_PARAM_GET 32 +#define PM_PINCTRL_CONFIG_PARAM_SET 33 +#define PM_IOCTL 34 +#define PM_QUERY_DATA 35 +#define PM_CLOCK_ENABLE 36 +#define PM_CLOCK_DISABLE 37 +#define PM_CLOCK_GETSTATE 38 +#define PM_CLOCK_SETDIVIDER 39 +#define PM_CLOCK_GETDIVIDER 40 +#define PM_CLOCK_SETRATE 41 +#define PM_CLOCK_GETRATE 42 +#define PM_CLOCK_SETPARENT 43 +#define PM_CLOCK_GETPARENT 44 +#define PM_PLL_SET_PARAMETER 48 +#define PM_PLL_GET_PARAMETER 49 +#define PM_PLL_SET_MODE 50 +#define PM_PLL_GET_MODE 51 +#define PM_FEATURE_CHECK 63 + +/* Loader API id */ +#define PM_LOAD_PDI 0x701 + +/* PDI sources */ +#define PDI_SRC_JTAG 0x0 +#define PDI_SRC_QSPI24 0x1 +#define PDI_SRC_QSPI32 0x2 +#define PDI_SRC_SD0 0x3 +#define PDI_SRC_EMMC0 0x4 +#define PDI_SRC_SD1 0x5 +#define PDI_SRC_EMMC1 0x6 +#define PDI_SRC_USB 0x7 +#define PDI_SRC_OSPI 0x8 +#define PDI_SRC_SBI 0x9 +#define PDI_SRC_SMAP 0xA +#define PDI_SRC_PCIE 0xB +#define PDI_SRC_SD1_LS 0xE +#define PDI_SRC_DDR 0xF + +struct versal_sip_payload { + uint32_t data[PAYLOAD_ARG_CNT]; +}; + +static uint32_t versal_sip_call(uint32_t smc_fid, uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3, + struct versal_sip_payload *payload) +{ + struct thread_smc_args args = { + .a0 = smc_fid, + .a1 = reg_pair_to_64(arg1, arg0), + .a2 = reg_pair_to_64(arg3, arg2), + }; + + thread_smccc(&args); + + if (payload) { + reg_pair_from_64(args.a0, &payload->data[1], &payload->data[0]); + reg_pair_from_64(args.a1, &payload->data[3], &payload->data[2]); + reg_pair_from_64(args.a2, &payload->data[5], &payload->data[4]); + reg_pair_from_64(args.a3, &payload->data[7], &payload->data[6]); + } + + /* allow the PLM to output its debug information */ + if (IS_ENABLED(CFG_VERSAL_TRACE_PLM)) + mdelay(500); + + return args.a0; +} + +/* SIP call to program the FPGA has been obsoleted, use the PLM */ +TEE_Result versal_write_fpga(paddr_t pa) +{ + struct versal_ipi_cmd cmd = { }; + + cmd.data[0] = PM_LOAD_PDI; + cmd.data[1] = PDI_SRC_DDR; + reg_pair_from_64(pa, &cmd.data[2], &cmd.data[3]); + + if (versal_mbox_notify(&cmd, NULL, NULL)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result versal_soc_version(uint8_t *version) +{ + struct versal_sip_payload p = { }; + const uint32_t version_shift = 12; + + if (!version) + return TEE_ERROR_BAD_PARAMETERS; + + if (versal_sip_call(VERSAL_SIP_SVC | PM_GET_CHIPID, 0, 0, 0, 0, &p)) + return TEE_ERROR_GENERIC; + + *version = p.data[2] >> version_shift; + + return TEE_SUCCESS; +} + +static bool uuid_is_versal_pm(void) +{ + struct versal_sip_payload p = { }; + + versal_sip_call(VERSAL_SIP_SVC_UID, 0, 0, 0, 0, &p); + + if (p.data[0] == VERSAL_SIP_UID_0 && p.data[2] == VERSAL_SIP_UID_1 && + p.data[4] == VERSAL_SIP_UID_2 && p.data[6] == VERSAL_SIP_UID_3) + return true; + + return false; +} + +static TEE_Result versal_check_pm_abi(void) +{ + struct versal_sip_payload p = { }; + struct versal_ipi_cmd cmd = { }; + struct versal_ipi_cmd rsp = { }; + unsigned int major = 0; + unsigned int minor = 0; + + if (!uuid_is_versal_pm()) { + EMSG("Invalid SiP Service"); + return TEE_ERROR_GENERIC; + } + + if (versal_sip_call(VERSAL_SIP_SVC_VERSION, 0, 0, 0, 0, &p)) + return TEE_ERROR_GENERIC; + + major = p.data[0]; + minor = p.data[2]; + if (major != VERSAL_SIP_MAJOR || minor < VERSAL_SIP_MINOR) { + EMSG("Invalid SiP version: Major %d, Minor %d", major, minor); + return TEE_ERROR_GENERIC; + } + + cmd.data[0] = PM_API_ID(PM_GET_API_VERSION); + if (versal_mbox_notify(&cmd, &rsp, NULL)) + return TEE_ERROR_GENERIC; + + major = rsp.data[1] & 0xFFFF; + minor = rsp.data[1] >> 16; + if (major != VERSAL_PM_MAJOR || minor < VERSAL_PM_MINOR) { + EMSG("Invalid PM version: Major %d, Minor %d", major, minor); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +early_init_late(versal_check_pm_abi); diff --git a/optee/optee_os/core/drivers/versal_puf.c b/optee/optee_os/core/drivers/versal_puf.c new file mode 100644 index 0000000..d65cbe1 --- /dev/null +++ b/optee/optee_os/core/drivers/versal_puf.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022 Foundries.io Ltd + * Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Protocol API with the remote processor */ +#define VERSAL_PUF_MODULE_SHIFT 8 +#define VERSAL_PUF_MODULE 12 +#define PUF_API_ID(_id) ((VERSAL_PUF_MODULE << VERSAL_PUF_MODULE_SHIFT) | (_id)) + +enum versal_puf_error { + /* Registration */ + ERROR_INVALID_PARAM = 0x02, + ERROR_INVALID_SYNDROME_MODE = 0x03, + ERROR_SYNDROME_WORD_WAIT_TIMEOUT = 0x04, + ERROR_PUF_DONE_WAIT_TIMEOUT = 0x07, + ERROR_REGISTRATION_INVALID = 0x08, + SHUTTER_GVF_MISMATCH = 0x09, + ERROR_SYN_DATA_ERROR = 0x0A, + IRO_FREQ_WRITE_MISMATCH = 0x0B, + /* Regeneration */ + ERROR_CHASH_NOT_PROGRAMMED = 0x10, + ERROR_PUF_STATUS_DONE_TIMEOUT = 0x11, + ERROR_INVALID_REGENERATION_TYPE = 0x12, + ERROR_INVALID_PUF_OPERATION = 0x13, + ERROR_REGENERATION_INVALID = 0x14, + ERROR_REGEN_PUF_HD_INVALID = 0x15, + ERROR_INVALID_READ_HD_INPUT = 0x16, + ERROR_PUF_DONE_KEY_NT_RDY = 0x17, + ERROR_PUF_DONE_ID_NT_RDY = 0x18, + ERROR_PUF_ID_ZERO_TIMEOUT = 0x19, +}; + +#define VERSAL_PUF_ERROR(m) { .error = (m), .name = TO_STR(m) } + +static const char *versal_puf_error(uint8_t err) +{ + struct { + enum versal_puf_error error; + const char *name; + } elist[] = { + /* Registration */ + VERSAL_PUF_ERROR(ERROR_INVALID_PARAM), + VERSAL_PUF_ERROR(ERROR_INVALID_SYNDROME_MODE), + VERSAL_PUF_ERROR(ERROR_SYNDROME_WORD_WAIT_TIMEOUT), + VERSAL_PUF_ERROR(ERROR_PUF_DONE_WAIT_TIMEOUT), + VERSAL_PUF_ERROR(ERROR_REGISTRATION_INVALID), + VERSAL_PUF_ERROR(SHUTTER_GVF_MISMATCH), + VERSAL_PUF_ERROR(ERROR_SYN_DATA_ERROR), + VERSAL_PUF_ERROR(IRO_FREQ_WRITE_MISMATCH), + /* Regeneration */ + VERSAL_PUF_ERROR(ERROR_CHASH_NOT_PROGRAMMED), + VERSAL_PUF_ERROR(ERROR_PUF_STATUS_DONE_TIMEOUT), + VERSAL_PUF_ERROR(ERROR_INVALID_REGENERATION_TYPE), + VERSAL_PUF_ERROR(ERROR_INVALID_PUF_OPERATION), + VERSAL_PUF_ERROR(ERROR_REGENERATION_INVALID), + VERSAL_PUF_ERROR(ERROR_REGEN_PUF_HD_INVALID), + VERSAL_PUF_ERROR(ERROR_INVALID_READ_HD_INPUT), + VERSAL_PUF_ERROR(ERROR_PUF_DONE_KEY_NT_RDY), + VERSAL_PUF_ERROR(ERROR_PUF_DONE_ID_NT_RDY), + VERSAL_PUF_ERROR(ERROR_PUF_ID_ZERO_TIMEOUT), + }; + size_t error = 0; + size_t index = 0; + + if (err <= ERROR_PUF_ID_ZERO_TIMEOUT && err >= ERROR_INVALID_PARAM) { + index = err - ERROR_INVALID_PARAM; + + /* Spectre gadget protection: array index is external event */ + error = confine_array_index(index, ARRAY_SIZE(elist)); + if (elist[error].name) + return elist[error].name; + + return "Invalid"; + } + + return "Unknown"; +} + +/* + * Register the Physical Unclonable Function (prior operating with it) + * + * This must happen during the device provisioning phase and can be done from + * the Secure World via this interface or from an earlier firmware. + */ +TEE_Result versal_puf_register(struct versal_puf_data *buf, + struct versal_puf_cfg *cfg) +{ + struct versal_puf_data_req req __aligned_puf = { }; + struct versal_mbox_mem request = { + .alloc_len = sizeof(req), + .len = sizeof(req), + .buf = &req, + }; + struct versal_mbox_mem efuse_syn_data_addr = { }; + struct versal_mbox_mem syndrome_data_addr = { }; + struct versal_mbox_mem puf_id_addr = { }; + struct versal_mbox_mem hash_addr = { }; + struct versal_mbox_mem aux_addr = { }; + struct versal_ipi_cmd arg = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + + versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr); + versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr); + versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr); + versal_mbox_alloc(sizeof(buf->efuse_syn_data), buf->efuse_syn_data, + &efuse_syn_data_addr); + versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data, + &syndrome_data_addr); + + arg.ibuf[0].mem = request; + arg.ibuf[1].mem = syndrome_data_addr; + arg.ibuf[2].mem = hash_addr; + arg.ibuf[3].mem = aux_addr; + arg.ibuf[4].mem = puf_id_addr; + arg.ibuf[5].mem = efuse_syn_data_addr; + + req.efuse_syn_data_addr = virt_to_phys(efuse_syn_data_addr.buf); + req.syndrome_data_addr = virt_to_phys(syndrome_data_addr.buf); + req.puf_id_addr = virt_to_phys(puf_id_addr.buf); + req.hash_addr = virt_to_phys(hash_addr.buf); + req.aux_addr = virt_to_phys(aux_addr.buf); + + req.global_var_filter = cfg->global_var_filter; + req.shutter_value = cfg->shutter_value; + req.puf_operation = cfg->puf_operation; + req.read_option = cfg->read_option; + req.reg_mode = cfg->reg_mode; + + arg.data[0] = PUF_API_ID(VERSAL_PUF_REGISTER); + reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf), + &arg.data[2], &arg.data[1]); + + if (versal_mbox_notify(&arg, NULL, &err)) { + EMSG("Versal, failed to register the PUF [%s]", + versal_puf_error(err)); + + ret = TEE_ERROR_GENERIC; + } + + /* Return the generated data */ + memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id)); + memcpy(&buf->chash, hash_addr.buf, sizeof(buf->chash)); + memcpy(&buf->aux, aux_addr.buf, sizeof(buf->aux)); + memcpy(buf->efuse_syn_data, efuse_syn_data_addr.buf, + sizeof(buf->efuse_syn_data)); + memcpy(buf->syndrome_data, syndrome_data_addr.buf, + sizeof(buf->syndrome_data)); + + free(syndrome_data_addr.buf); + free(hash_addr.buf); + free(aux_addr.buf); + free(puf_id_addr.buf); + free(efuse_syn_data_addr.buf); + + return ret; +} + +/* + * Re-seed the PUF circuitry so it can re-generate the Key Encryption Key. + * + * Depending on the configuration options it might use eFused data instead of + * the helper data provided via the interface. + */ +TEE_Result versal_puf_regenerate(struct versal_puf_data *buf, + struct versal_puf_cfg *cfg) +{ + struct versal_puf_data_req req __aligned_puf = { }; + struct versal_mbox_mem request = { + .alloc_len = sizeof(req), + .len = sizeof(req), + .buf = &req, + }; + struct versal_mbox_mem efuse_syn_data_addr = { }; + struct versal_mbox_mem syndrome_data_addr = { }; + struct versal_mbox_mem puf_id_addr = { }; + struct versal_mbox_mem hash_addr = { }; + struct versal_mbox_mem aux_addr = { }; + struct versal_ipi_cmd arg = { }; + TEE_Result ret = TEE_SUCCESS; + uint32_t err = 0; + + versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr); + versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr); + versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr); + versal_mbox_alloc(sizeof(buf->efuse_syn_data), buf->efuse_syn_data, + &efuse_syn_data_addr); + versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data, + &syndrome_data_addr); + + arg.ibuf[0].mem = request; + arg.ibuf[1].mem = syndrome_data_addr; + arg.ibuf[2].mem = hash_addr; + arg.ibuf[3].mem = aux_addr; + arg.ibuf[4].mem = puf_id_addr; + arg.ibuf[5].mem = efuse_syn_data_addr; + + req.efuse_syn_data_addr = virt_to_phys(efuse_syn_data_addr.buf); + req.syndrome_addr = virt_to_phys(syndrome_data_addr.buf); + req.puf_id_addr = virt_to_phys(puf_id_addr.buf); + req.hash_addr = virt_to_phys(hash_addr.buf); + req.aux_addr = virt_to_phys(aux_addr.buf); + + req.global_var_filter = cfg->global_var_filter; + req.shutter_value = cfg->shutter_value; + req.puf_operation = cfg->puf_operation; + req.read_option = cfg->read_option; + req.reg_mode = cfg->reg_mode; + + arg.data[0] = PUF_API_ID(VERSAL_PUF_REGENERATE); + reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf), + &arg.data[2], &arg.data[1]); + + if (versal_mbox_notify(&arg, NULL, &err)) { + EMSG("Versal, failed to regenerate the PUF [%s]", + versal_puf_error(err)); + + ret = TEE_ERROR_GENERIC; + } + + /* Return the updated PUF_ID */ + memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id)); + + free(syndrome_data_addr.buf); + free(hash_addr.buf); + free(aux_addr.buf); + free(puf_id_addr.buf); + free(efuse_syn_data_addr.buf); + + return ret; +} + +/* + * Clear/Hide the PUF Unique ID + * + * The fully accessible (non-secret) Unique ID is generated from the PUF + */ +TEE_Result versal_puf_clear_id(void) +{ + struct versal_ipi_cmd arg = { }; + + arg.data[0] = PUF_API_ID(VERSAL_PUF_CLEAR_ID); + + if (versal_mbox_notify(&arg, NULL, NULL)) { + EMSG("Versal, failed to clear the PUF_ID"); + + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +/* Check that the API id is available to the client */ +TEE_Result versal_puf_check_api(enum versal_puf_api id) +{ + struct versal_ipi_cmd arg = { }; + + arg.data[0] = PUF_API_ID(VERSAL_PUF_API_FEATURES); + arg.data[1] = id; + + if (versal_mbox_notify(&arg, NULL, NULL)) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/versal_sha3_384.c b/optee/optee_os/core/drivers/versal_sha3_384.c new file mode 100644 index 0000000..3a46db0 --- /dev/null +++ b/optee/optee_os/core/drivers/versal_sha3_384.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2022 + * Author: Jorge Ramirez + */ + +#include +#include +#include +#include +#include + +#define VERSAL_SHA3_384_FIRST_PACKET BIT(30) +#define VERSAL_SHA3_384_NEXT_PACKET BIT(31) + +static struct mutex lock = MUTEX_INITIALIZER; +static bool engine_ready; + +static TEE_Result input_plaintext(const uint8_t *src, size_t src_len) +{ + uint32_t first = VERSAL_SHA3_384_FIRST_PACKET; + struct versal_cmd_args arg = { .dlen = 1, }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + size_t len = 0; + size_t i = 0; + + while (src_len && !ret) { + len = MIN(src_len, SMALL_PAGE_SIZE); + src_len -= len; + versal_mbox_alloc(len, src + i * SMALL_PAGE_SIZE, &p); + + arg.data[0] = first | VERSAL_SHA3_384_NEXT_PACKET | len; + arg.ibuf[0].mem = p; + ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL); + if (ret) + EMSG("VERSAL_SHA3_UPDATE [%ld, len = %zu]", i, len); + + free(p.buf); + first = 0; + i++; + } + + return ret; +} + +static TEE_Result get_ciphertext(uint8_t *dst, size_t dst_len) +{ + struct versal_cmd_args arg = { }; + struct versal_mbox_mem p = { }; + TEE_Result ret = TEE_SUCCESS; + + versal_mbox_alloc(TEE_SHA384_HASH_SIZE, NULL, &p); + + arg.ibuf[0].mem = p; + ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL); + if (!ret) + memcpy(dst, p.buf, MIN(dst_len, (size_t)TEE_SHA384_HASH_SIZE)); + else + EMSG("VERSAL_SHA3_UPDATE final"); + + free(p.buf); + + return ret; +} + +TEE_Result versal_sha3_384(const uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len) +{ + TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; + + if (!src_len || !dst_len || !src || !dst) + return ret; + + if (!engine_ready) + return TEE_ERROR_BAD_STATE; + + mutex_lock(&lock); + + ret = input_plaintext(src, src_len); + if (!ret) + ret = get_ciphertext(dst, dst_len); + + mutex_unlock(&lock); + + return ret; +} + +static TEE_Result versal_sha3_384_init(void) +{ + struct versal_cmd_args arg = { }; + TEE_Result ret = TEE_SUCCESS; + + ret = versal_crypto_request(VERSAL_SHA3_KAT, &arg, NULL); + if (!ret) + engine_ready = true; + + return ret; +} + +/* Be available for the HUK */ +service_init(versal_sha3_384_init); diff --git a/optee/optee_os/core/drivers/versal_trng.c b/optee/optee_os/core/drivers/versal_trng.c new file mode 100644 index 0000000..792c46a --- /dev/null +++ b/optee/optee_os/core/drivers/versal_trng.c @@ -0,0 +1,1149 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2022 Xilinx, Inc. All rights reserved. + * Copyright (C) 2022 Foundries Ltd. + * + * Driver port from Xilinx's FSBL implementation, jorge@foundries.io + * + * The Xilinx True Random Number Generator(TRNG) module in Versal - PMC TRNG + * consists of an entropy source, a deterministic random bit generator (DRBG) + * and health test logic, which tests the randomness of the generated data. + * The entropy source for the unit is an array of Ring Oscillators. + * + * The Versal PMC TRNG is envisaged to operate in three basic modes: DRNG, PTRNG + * and HRNG . Each of these can be operated with or without Derivative Function + * (DF), resulting in a total of 6 different modes of operation. + * + * NIST SP-800-90A practically requires the true random generators based on + * CTR_DRBG to include a derivation function (DF). This is expected to be + * implemented inside the Silicon (TRNG IP). However, the version of the IP used + * in Versal PMC does not have this capability. Hence, a software + * implementation of the DF is done in this driver. + * + * DRNG mode: Deterministic Random Number Generator mode. + * In this mode, the DRBG portion of the TRNG is used. User provides + * the (external) seed. + * PTRNG mode: Physical True Random Number Generator mode (aka Entropy mode). + * In this mode digitized Entropy source is output as random number. + * HRNG mode: Hybrid Random Number Generator mode. + * This is combination of above two modes in which the Entropy source + * is used to provide the seed, which is fed to the DRBG, which in + * turn generates the random number. + * + * DRNG mode with DF: It may not be common usecase to use the DF with DRNG as + * the general expectation would be that the seed would have sufficient entropy. + * However, the below guideline from section 10.2.1 of NIST SP-800-90A implies + * that need for DF for DRNG mode too: "..the DRBG mechanism is specified to + * allow an implementation tradeoff with respect to the use of this derivation + * function. The use of the derivation function is optional if either an + * approved RBG or an entropy source provides full entropy output when entropy + * input is requested by the DRBG mechanism. Otherwise, the derivation function + * shall be used". Sufficient large entropy data from user is fed to DF to + * generate the seed which will be loaded into the external seed registers. + * From here, it is similar to regular DRNG mode. + * + * PTRNG mode with DF: This mode is similar to PTRNG mode, however, the entropy + * data from the core output registers are accumulated and fed to the DF + * (instead of directly consuming it). The output of the DF would be final + * random data. In this mode, the output of DF is not seed but the random data. + * + * HRNG mode with DF: This mode is the combination of the above two modes. + * The entropy data is fed to the DF to produce seed. This seed is loaded to the + * external seed registers which provide seed to the DRBG. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TRNG_BASE 0xF1230000 +#define TRNG_SIZE 0x10000 + +#define TRNG_STATUS 0x04 +#define TRNG_STATUS_QCNT_SHIFT 9 +#define TRNG_STATUS_QCNT_MASK (BIT(9) | BIT(10) | BIT(11)) +#define TRNG_STATUS_CERTF_MASK BIT(3) +#define TRNG_STATUS_DTF_MASK BIT(1) +#define TRNG_STATUS_DONE_MASK BIT(0) +#define TRNG_CTRL 0x08 +#define TRNG_CTRL_EUMODE_MASK BIT(8) +#define TRNG_CTRL_PRNGMODE_MASK BIT(7) +#define TRNG_CTRL_PRNGSTART_MASK BIT(5) +#define TRNG_CTRL_PRNGXS_MASK BIT(3) +#define TRNG_CTRL_TRSSEN_MASK BIT(2) +#define TRNG_CTRL_PRNGSRST_MASK BIT(0) +#define TRNG_EXT_SEED_0 0x40 +/* + * Below registers are not directly referenced in driver but are accessed + * with offset from TRNG_EXT_SEED_0 + * Register: TRNG_EXT_SEED_1 0x00000044 + * Register: TRNG_EXT_SEED_2 0x00000048 + * Register: TRNG_EXT_SEED_3 0x0000004C + * Register: TRNG_EXT_SEED_4 0x00000050 + * Register: TRNG_EXT_SEED_5 0x00000054 + * Register: TRNG_EXT_SEED_6 0x00000058 + * Register: TRNG_EXT_SEED_7 0x0000005C + * Register: TRNG_EXT_SEED_8 0x00000060 + * Register: TRNG_EXT_SEED_9 0x00000064 + * Register: TRNG_EXT_SEED_10 0x00000068 + * Register: TRNG_EXT_SEED_11 0x0000006C + */ +#define TRNG_PER_STRING_0 0x80 +/* + * Below registers are not directly referenced in driver but are accessed + * with offset from TRNG_PER_STRING_0 + * Register: TRNG_PER_STRING_1 0x00000084 + * Register: TRNG_PER_STRING_2 0x00000088 + * Register: TRNG_PER_STRING_3 0x0000008C + * Register: TRNG_PER_STRING_4 0x00000090 + * Register: TRNG_PER_STRING_5 0x00000094 + * Register: TRNG_PER_STRING_6 0x00000098 + * Register: TRNG_PER_STRING_7 0x0000009C + * Register: TRNG_PER_STRING_8 0x000000A0 + * Register: TRNG_PER_STRING_9 0x000000A4 + * Register: TRNG_PER_STRING_10 0x000000A8 + * Register: TRNG_PER_STRING_11 0x000000AC + */ +#define TRNG_CORE_OUTPUT 0xC0 +#define TRNG_RESET 0xD0 +#define TRNG_RESET_VAL_MASK BIT(0) +#define TRNG_OSC_EN 0xD4 +#define TRNG_OSC_EN_VAL_MASK BIT(0) + +/* TRNG configuration */ +#define TRNG_BURST_SIZE 16 +#define TRNG_BURST_SIZE_BITS 128 +#define TRNG_NUM_INIT_REGS 12 +#define TRNG_REG_SIZE 32 +#define TRNG_BYTES_PER_REG 4 +#define TRNG_MAX_QCNT 4 +#define TRNG_RESEED_TIMEOUT 15000 +#define TRNG_GENERATE_TIMEOUT 8000 +#define TRNG_MIN_DFLENMULT 2 +#define TRNG_MAX_DFLENMULT 9 +#define PRNGMODE_RESEED 0 +#define PRNGMODE_GEN TRNG_CTRL_PRNGMODE_MASK +#define RESET_DELAY 10 +#define TRNG_SEC_STRENGTH_LEN 32 +#define TRNG_PERS_STR_REGS 12 +#define TRNG_PERS_STR_LEN 48 +#define TRNG_SEED_REGS 12 +#define TRNG_SEED_LEN 48 +#define TRNG_GEN_LEN 32 +#define RAND_BUF_LEN 4 +#define BYTES_PER_BLOCK 16 +#define ALL_A_PATTERN_32 0xAAAAAAAA +#define ALL_5_PATTERN_32 0x55555555 + +/* Derivative function helper macros */ +#define DF_SEED 0 +#define DF_RAND 1 +#define DF_IP_IV_LEN 4 +#define DF_PAD_DATA_LEN 8 +#define MAX_PRE_DF_LEN 160 +#define MAX_PRE_DF_LEN_WORDS 40 +#define DF_PERS_STR_LEN TRNG_PERS_STR_LEN +#define DF_PAD_VAL 0x80 +#define DF_KEY_LEN 32 +#define BLK_SIZE 16 +#define MAX_ROUNDS 14 + +enum trng_status { + TRNG_UNINITIALIZED = 0, + TRNG_HEALTHY, + TRNG_ERROR, + TRNG_CATASTROPHIC +}; + +enum trng_mode { + TRNG_HRNG = 0, + TRNG_DRNG, + TRNG_PTRNG +}; + +struct trng_cfg { + paddr_t base; + vaddr_t addr; + size_t len; +}; + +struct trng_usr_cfg { + enum trng_mode mode; + uint64_t seed_life; /* number of TRNG requests per seed */ + bool predict_en; /* enable prediction resistance */ + bool pstr_en; /* enable personalization string */ + uint32_t pstr[TRNG_PERS_STR_REGS]; + bool iseed_en; /* enable an initial seed */ + uint32_t init_seed[MAX_PRE_DF_LEN_WORDS]; + uint32_t df_disable; /* disable the derivative function */ + uint32_t dfmul; /* derivative function multiplier */ +}; + +struct trng_stats { + uint64_t bytes; + uint64_t bytes_reseed; + uint64_t elapsed_seed_life; +}; + +/* block cipher derivative function algorithm */ +struct trng_dfin { + uint32_t ivc[DF_IP_IV_LEN]; + uint32_t val1; + uint32_t val2; + uint8_t entropy[MAX_PRE_DF_LEN]; /* input entropy */ + uint8_t pstr[DF_PERS_STR_LEN]; /* personalization string */ + uint8_t pad_data[DF_PAD_DATA_LEN]; /* pad to multiples of 16 bytes*/ +}; + +struct versal_trng { + struct trng_cfg cfg; + struct trng_usr_cfg usr_cfg; + struct trng_stats stats; + enum trng_status status; + uint32_t buf[RAND_BUF_LEN]; /* buffer of random bits */ + size_t len; + struct trng_dfin dfin; + uint8_t dfout[TRNG_SEED_LEN]; /* output of the DF operation */ +}; + +/* Derivative function variables */ +static unsigned char sbx1[256]; +static unsigned char sbx2[256]; +static unsigned char sbx3[256]; +static unsigned char schedule[BLK_SIZE * (MAX_ROUNDS + 1)]; +static unsigned int rounds; + +static void rota4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d) +{ + uint8_t t = *a; + + *a = sbx1[*b]; + *b = sbx1[*c]; + *c = sbx1[*d]; + *d = sbx1[t]; +} + +static void rota2(uint8_t *a, uint8_t *b) +{ + uint8_t t = *a; + + *a = sbx1[*b]; + *b = sbx1[t]; +} + +static void sbox4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d) +{ + *a = sbx1[*a]; + *b = sbx1[*b]; + *c = sbx1[*c]; + *d = sbx1[*d]; +} + +static void xorb(uint8_t *res, const uint8_t *in) +{ + size_t i = 0; + + for (i = 0; i < BLK_SIZE; ++i) + res[i] ^= in[i]; +} + +static void set_key(uint8_t *res, const uint8_t *src, unsigned int roundval) +{ + memcpy(res, src, BLK_SIZE); + xorb(res, schedule + roundval * BLK_SIZE); +} + +static void mix_column_sbox(uint8_t *dst, const uint8_t *f) +{ + size_t i = 0; + size_t a = 0; + size_t b = 0; + size_t c = 0; + size_t d = 0; + + for (i = 0; i < 4; i++) { + a = 4 * i; + b = (0x5 + a) % 16; + c = (0xa + a) % 16; + d = (0xf + a) % 16; + dst[0 + a] = sbx2[f[a]] ^ sbx3[f[b]] ^ sbx1[f[c]] ^ sbx1[f[d]]; + dst[1 + a] = sbx1[f[a]] ^ sbx2[f[b]] ^ sbx3[f[c]] ^ sbx1[f[d]]; + dst[2 + a] = sbx1[f[a]] ^ sbx1[f[b]] ^ sbx2[f[c]] ^ sbx3[f[d]]; + dst[3 + a] = sbx3[f[a]] ^ sbx1[f[b]] ^ sbx1[f[c]] ^ sbx2[f[d]]; + } +} + +static void shift_row_sbox(uint8_t *f) +{ + sbox4(&f[0], &f[4], &f[8], &f[12]); + rota4(&f[1], &f[5], &f[9], &f[13]); + rota2(&f[2], &f[10]); + rota2(&f[6], &f[14]); + rota4(&f[15], &f[11], &f[7], &f[3]); +} + +static void encrypt(uint8_t *in, uint8_t *out) +{ + uint8_t fa[BLK_SIZE] = { 0 }; + uint8_t fb[BLK_SIZE] = { 0 }; + size_t roundval = 0; + + set_key(fa, in, 0); + for (roundval = 1; roundval < rounds; ++roundval) { + mix_column_sbox(fb, fa); + set_key(fa, fb, roundval); + } + + shift_row_sbox(fa); + set_key(out, fa, roundval); +} + +static void checksum(unsigned char *in, uint8_t *iv, int max_blk) +{ + while (max_blk > 0) { + xorb(iv, in); + encrypt(iv, iv); + in += BLK_SIZE; + max_blk -= 1; + } +} + +static void setup_key(const unsigned char *k, size_t klen) +{ + unsigned char rcon = 1; + size_t sch_size = 240; + size_t i = 0; + + rounds = MAX_ROUNDS; + memcpy(schedule, k, klen); + for (i = klen; i < sch_size; i += 4) { + unsigned char t0 = 0; + unsigned char t1 = 0; + unsigned char t2 = 0; + unsigned char t3 = 0; + int ik = 0; + + t0 = schedule[i - 4]; + t1 = schedule[i - 3]; + t2 = schedule[i - 2]; + t3 = schedule[i - 1]; + if (i % klen == 0) { + rota4(&t0, &t1, &t2, &t3); + t0 ^= rcon; + rcon = (rcon << 1) ^ (((rcon >> 7) & 1) * 0x1B); + } else if (i % klen == 16) { + sbox4(&t0, &t1, &t2, &t3); + } + ik = i - klen; + schedule[i + 0] = schedule[ik + 0] ^ t0; + schedule[i + 1] = schedule[ik + 1] ^ t1; + schedule[i + 2] = schedule[ik + 2] ^ t2; + schedule[i + 3] = schedule[ik + 3] ^ t3; + } +} + +static void trng_df_init(void) +{ + const uint8_t sb[] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, + 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, + 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, + 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, + 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, + 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, + 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, + 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, + 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, + 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, + 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, + 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, + 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, + 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, + 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, + 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, + 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, + 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, + }; + size_t i = 0; + + memcpy(sbx1, sb, sizeof(sb)); + for (i = 0; i < sizeof(sb); i++) { + sbx2[i] = (sb[i] << 1) ^ (((sb[i] >> 7) & 1) * 0x1B); + sbx3[i] = sbx2[i] ^ sb[i]; + } +} + +/* + * This function implements the Derivative Function by distilling the entropy + * available in its input into a smaller number of bits on the output. + * - per NIST SP80090A. + * + * The Block Cipher algorithm follows sections 10.3.2 and 10.3.3 of the + * NIST.SP.800-90Ar1 document + */ +static void trng_df_algorithm(struct versal_trng *trng, uint8_t *dfout, + uint32_t flag, const uint8_t *pstr) +{ + static bool df_init; + const uint8_t df_key[DF_KEY_LEN] = { + 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, 26, 27, 28, 29, 30, 31 + }; + size_t dfin_len = sizeof(struct trng_dfin) + trng->len; + uint8_t *inp_blk = NULL; + uint8_t *out_blk = NULL; + uintptr_t reminder = 0; + size_t xfer_len = 0; + uint32_t index = 0; + uintptr_t src = 0; + uintptr_t dst = 0; + size_t offset = 0; + + if (!df_init) { + trng_df_init(); + df_init = true; + } + + if (flag == DF_SEED) + trng->dfin.val2 = TEE_U32_TO_BIG_ENDIAN(TRNG_PERS_STR_LEN); + else + trng->dfin.val2 = TEE_U32_TO_BIG_ENDIAN(TRNG_GEN_LEN); + + trng->dfin.pad_data[0] = DF_PAD_VAL; + + if (!pstr) { + if (trng->len > (MAX_PRE_DF_LEN + TRNG_PERS_STR_LEN)) + panic(); + + dfin_len = dfin_len - TRNG_PERS_STR_LEN - MAX_PRE_DF_LEN; + trng->dfin.val1 = TEE_U32_TO_BIG_ENDIAN(trng->len); + + xfer_len = DF_PAD_DATA_LEN; + src = (uintptr_t)trng->dfin.pad_data; + offset = MAX_PRE_DF_LEN + TRNG_PERS_STR_LEN - trng->len; + } else { + if (trng->len > MAX_PRE_DF_LEN) + panic(); + + memcpy(trng->dfin.pstr, pstr, TRNG_PERS_STR_LEN); + dfin_len = dfin_len - MAX_PRE_DF_LEN; + trng->dfin.val1 = TEE_U32_TO_BIG_ENDIAN(trng->len + + TRNG_PERS_STR_LEN); + xfer_len = DF_PAD_DATA_LEN + TRNG_PERS_STR_LEN; + src = (uintptr_t)trng->dfin.pstr; + offset = MAX_PRE_DF_LEN - trng->len; + } + + /* Move back into the dfin structure */ + dst = src - offset; + reminder = (uintptr_t)&trng->dfin + sizeof(trng->dfin) - offset; + if (offset) { + if (xfer_len > offset) + panic("Overlapping data"); + + memcpy((void *)dst, (void *)src, xfer_len); + memset((void *)reminder, 0, offset); + } + + /* DF algorithm - step 1 */ + setup_key(df_key, DF_KEY_LEN); + for (index = 0; index < TRNG_SEED_LEN; index += BLK_SIZE) { + memset((void *)(trng->dfout + index), 0, BLK_SIZE); + trng->dfin.ivc[0] = TEE_U32_TO_BIG_ENDIAN(index / BLK_SIZE); + checksum((unsigned char *)&trng->dfin, + trng->dfout + index, dfin_len / BLK_SIZE); + } + + /* DF algorithm - step 2 */ + setup_key(trng->dfout, DF_KEY_LEN); + for (index = 0; index < TRNG_SEED_LEN; index += BLK_SIZE) { + if (!index) + inp_blk = &dfout[TRNG_SEC_STRENGTH_LEN]; + else + inp_blk = &dfout[index - BLK_SIZE]; + + out_blk = &dfout[index]; + encrypt(inp_blk, out_blk); + } +} + +static uint32_t trng_read32(vaddr_t addr, size_t off) +{ + return io_read32(addr + off); +} + +static void trng_write32(vaddr_t addr, size_t off, uint32_t val) +{ + io_write32(addr + off, val); +} + +static void trng_clrset32(vaddr_t addr, size_t off, uint32_t mask, uint32_t val) +{ + io_clrsetbits32(addr + off, mask, mask & val); +} + +static void trng_write32_range(const struct versal_trng *trng, uint32_t start, + uint32_t num_regs, const uint8_t *buf) +{ + size_t off = 0; + uint32_t val = 0; + size_t cnt = 0; + size_t i = 0; + + for (i = 0; i < num_regs; ++i) { + if (!buf) { + off = start + i * TRNG_BYTES_PER_REG; + trng_write32(trng->cfg.addr, off, 0); + continue; + } + + val = 0; + for (cnt = 0; cnt < TRNG_BYTES_PER_REG; ++cnt) + val = (val << 8) | buf[i * TRNG_BYTES_PER_REG + cnt]; + + off = start + (TRNG_NUM_INIT_REGS - 1 - i) * TRNG_BYTES_PER_REG; + trng_write32(trng->cfg.addr, off, val); + } +} + +static TEE_Result trng_wait_for_event(vaddr_t addr, size_t off, uint32_t mask, + uint32_t event, uint32_t time_out) +{ + uint64_t tref = timeout_init_us(time_out); + + do { + if (timeout_elapsed(tref)) + break; + } while ((io_read32(addr + off) & mask) != event); + + /* Normal world might have suspended the OP-TEE thread, check again */ + if ((io_read32(addr + off) & mask) != event) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static void trng_soft_reset(const struct versal_trng *trng) +{ + trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK, + TRNG_CTRL_PRNGSRST_MASK); + udelay(RESET_DELAY); + trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK, 0); +} + +static void trng_reset(const struct versal_trng *trng) +{ + trng_write32(trng->cfg.addr, TRNG_RESET, TRNG_RESET_VAL_MASK); + udelay(RESET_DELAY); + trng_write32(trng->cfg.addr, TRNG_RESET, 0); + trng_soft_reset(trng); +} + +static void trng_hold_reset(const struct versal_trng *trng) +{ + trng_clrset32(trng->cfg.addr, TRNG_CTRL, + TRNG_CTRL_PRNGSRST_MASK, TRNG_CTRL_PRNGSRST_MASK); + trng_write32(trng->cfg.addr, TRNG_RESET, TRNG_RESET_VAL_MASK); + udelay(RESET_DELAY); +} + +static TEE_Result trng_check_seed(uint8_t *entropy, uint32_t len) +{ + uint32_t *p = (void *)entropy; + size_t i = 0; + + for (i = 0; i < len / sizeof(*p); i++) { + if (p[i] == ALL_A_PATTERN_32) + return TEE_ERROR_GENERIC; + + if (p[i] == ALL_5_PATTERN_32) + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static TEE_Result trng_collect_random(struct versal_trng *trng, uint8_t *dst, + size_t len) +{ + const size_t bursts = len / TRNG_BURST_SIZE; + const size_t words = TRNG_BURST_SIZE_BITS / TRNG_REG_SIZE; + uint32_t *p = (void *)dst; + size_t bcnt = 0; + size_t wcnt = 0; + size_t index = 0; + uint32_t val = 0; + bool match = false; + + trng_clrset32(trng->cfg.addr, TRNG_CTRL, + TRNG_CTRL_PRNGSTART_MASK, TRNG_CTRL_PRNGSTART_MASK); + + /* + * Loop as many times based on len requested. In each burst 128 bits + * are generated, which is reflected in QCNT value of 4 by hardware. + */ + for (bcnt = 0; bcnt < bursts; bcnt++) { + if (trng_wait_for_event(trng->cfg.addr, + TRNG_STATUS, TRNG_STATUS_QCNT_MASK, + TRNG_MAX_QCNT << TRNG_STATUS_QCNT_SHIFT, + TRNG_GENERATE_TIMEOUT)) { + EMSG("Timeout waiting for randomness"); + return TEE_ERROR_GENERIC; + } + + /* + * DTF flag set during generate indicates catastrophic + * condition, which needs to be checked for every time unless we + * are in PTRNG mode + */ + if (trng->usr_cfg.mode != TRNG_PTRNG) { + val = trng_read32(trng->cfg.addr, TRNG_STATUS); + if (val & TRNG_STATUS_DTF_MASK) { + EMSG("Catastrophic DFT error"); + trng->status = TRNG_CATASTROPHIC; + + return TEE_ERROR_GENERIC; + } + } + /* + * Read the core output register 4 times to consume the random + * data generated for every burst. + */ + match = true; + for (wcnt = 0; wcnt < words; wcnt++) { + val = trng_read32(trng->cfg.addr, TRNG_CORE_OUTPUT); + + if (bcnt > 0 && trng->buf[wcnt] != val) + match = false; + + trng->buf[wcnt] = val; + + if (dst) { + p[index] = TEE_U32_TO_BIG_ENDIAN(val); + index++; + } + } + + if (bursts > 1 && bcnt > 0 && match) { + EMSG("Catastrophic software error"); + trng->status = TRNG_CATASTROPHIC; + return TEE_ERROR_GENERIC; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result trng_reseed_internal_nodf(struct versal_trng *trng, + uint8_t *eseed, uint8_t *str) +{ + uint8_t entropy[TRNG_SEED_LEN] = { 0 }; + uint8_t *seed = NULL; + + switch (trng->usr_cfg.mode) { + case TRNG_HRNG: + trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); + trng_soft_reset(trng); + trng_write32(trng->cfg.addr, TRNG_CTRL, + TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK); + + if (trng_collect_random(trng, entropy, TRNG_SEED_LEN)) + return TEE_ERROR_GENERIC; + + if (trng_check_seed(entropy, TRNG_SEED_LEN)) + return TEE_ERROR_GENERIC; + + seed = entropy; + break; + case TRNG_DRNG: + seed = eseed; + break; + default: + seed = NULL; + break; + } + + trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, seed); + if (str) + trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS, + str); + + return TEE_SUCCESS; +} + +static TEE_Result trng_reseed_internal_df(struct versal_trng *trng, + uint8_t *eseed, uint8_t *str) +{ + memset(&trng->dfin, 0, sizeof(trng->dfin)); + + switch (trng->usr_cfg.mode) { + case TRNG_HRNG: + trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); + trng_soft_reset(trng); + trng_write32(trng->cfg.addr, TRNG_CTRL, + TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK); + + if (trng_collect_random(trng, trng->dfin.entropy, trng->len)) + return TEE_ERROR_GENERIC; + + if (trng_check_seed(trng->dfin.entropy, trng->len)) + return TEE_ERROR_GENERIC; + break; + case TRNG_DRNG: + memcpy(trng->dfin.entropy, eseed, trng->len); + break; + default: + break; + } + + trng_df_algorithm(trng, trng->dfout, DF_SEED, str); + trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, trng->dfout); + + return TEE_SUCCESS; +} + +static TEE_Result trng_reseed_internal(struct versal_trng *trng, + uint8_t *eseed, uint8_t *str, + uint32_t mul) +{ + uint32_t val = 0; + + trng->stats.bytes_reseed = 0; + trng->stats.elapsed_seed_life = 0; + + if (trng->usr_cfg.df_disable) + trng->len = TRNG_SEED_LEN; + else + trng->len = (mul + 1) * BYTES_PER_BLOCK; + + if (trng->usr_cfg.df_disable) { + if (trng_reseed_internal_nodf(trng, eseed, str)) + goto error; + } else { + if (trng_reseed_internal_df(trng, eseed, str)) + goto error; + } + + trng_write32(trng->cfg.addr, TRNG_CTRL, + PRNGMODE_RESEED | TRNG_CTRL_PRNGXS_MASK); + + /* Start the reseed operation */ + trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSTART_MASK, + TRNG_CTRL_PRNGSTART_MASK); + + if (trng_wait_for_event(trng->cfg.addr, TRNG_STATUS, + TRNG_STATUS_DONE_MASK, TRNG_STATUS_DONE_MASK, + TRNG_RESEED_TIMEOUT)) + goto error; + + /* Check SP800 - 90B (entropy health test error) */ + val = trng_read32(trng->cfg.addr, TRNG_STATUS) & TRNG_STATUS_CERTF_MASK; + if (val == TRNG_STATUS_CERTF_MASK) + goto error; + + trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSTART_MASK, 0); + return TEE_SUCCESS; +error: + trng->status = TRNG_ERROR; + return TEE_ERROR_GENERIC; +} + +static TEE_Result trng_instantiate(struct versal_trng *trng, + const struct trng_usr_cfg *usr_cfg) +{ + uint8_t *seed = NULL; + uint8_t *pers = NULL; + + if (!trng) + return TEE_ERROR_GENERIC; + + if (!usr_cfg) + goto error; + + if (trng->status != TRNG_UNINITIALIZED) + goto error; + + if (usr_cfg->mode != TRNG_HRNG && usr_cfg->mode != TRNG_DRNG && + usr_cfg->mode != TRNG_PTRNG) + goto error; + + if (usr_cfg->mode != TRNG_PTRNG && !usr_cfg->seed_life) + goto error; + + if (!usr_cfg->iseed_en && usr_cfg->mode == TRNG_DRNG) + goto error; + + if (usr_cfg->iseed_en && usr_cfg->mode == TRNG_HRNG) + goto error; + + if (!usr_cfg->df_disable && + (usr_cfg->dfmul < TRNG_MIN_DFLENMULT || + usr_cfg->dfmul > TRNG_MAX_DFLENMULT)) + goto error; + + if (usr_cfg->df_disable && usr_cfg->dfmul) + goto error; + + if (usr_cfg->mode == TRNG_PTRNG && + (usr_cfg->iseed_en || usr_cfg->pstr_en || + usr_cfg->predict_en || usr_cfg->seed_life)) + goto error; + + memcpy(&trng->usr_cfg, usr_cfg, sizeof(struct trng_usr_cfg)); + trng_reset(trng); + + if (trng->usr_cfg.iseed_en) + seed = (void *)trng->usr_cfg.init_seed; + + if (trng->usr_cfg.pstr_en) + pers = (void *)trng->usr_cfg.pstr; + + if (trng->usr_cfg.mode != TRNG_PTRNG) { + if (trng_reseed_internal(trng, seed, pers, trng->usr_cfg.dfmul)) + goto error; + } + + trng->status = TRNG_HEALTHY; + return TEE_SUCCESS; +error: + trng->status = TRNG_ERROR; + return TEE_ERROR_GENERIC; +} + +static TEE_Result trng_reseed(struct versal_trng *trng, uint8_t *eseed, + uint32_t mul) +{ + if (!trng) + return TEE_ERROR_GENERIC; + + if (trng->status != TRNG_HEALTHY) + goto error; + + if (trng->usr_cfg.mode != TRNG_DRNG && trng->usr_cfg.mode != TRNG_HRNG) + goto error; + + if (trng->usr_cfg.mode == TRNG_DRNG && !eseed) + goto error; + + if (trng->usr_cfg.mode != TRNG_DRNG && eseed) + goto error; + + if (!trng->usr_cfg.df_disable) { + if (mul < TRNG_MIN_DFLENMULT || mul > TRNG_MAX_DFLENMULT) + goto error; + } + + if (trng->usr_cfg.df_disable && mul) + goto error; + + if (eseed && !memcmp(eseed, trng->usr_cfg.init_seed, trng->len)) + goto error; + + if (trng_reseed_internal(trng, eseed, NULL, mul)) + goto error; + + return TEE_SUCCESS; +error: + trng->status = TRNG_ERROR; + return TEE_ERROR_GENERIC; +} + +static TEE_Result trng_generate(struct versal_trng *trng, uint8_t *buf, + size_t blen, bool predict) +{ + uint32_t len = TRNG_SEC_STRENGTH_LEN; + uint8_t *p = buf; + + if (!trng) + return TEE_ERROR_GENERIC; + + if (!p) + goto error; + + if (blen < TRNG_SEC_STRENGTH_LEN) + goto error; + + if (trng->status != TRNG_HEALTHY) + goto error; + + if (trng->usr_cfg.mode == TRNG_PTRNG && predict) + goto error; + + if (!trng->usr_cfg.predict_en && predict) + goto error; + + switch (trng->usr_cfg.mode) { + case TRNG_HRNG: + if (trng->stats.elapsed_seed_life >= trng->usr_cfg.seed_life) { + if (trng_reseed_internal(trng, NULL, NULL, 0)) + goto error; + } + + if (predict && trng->stats.elapsed_seed_life > 0) { + if (trng_reseed_internal(trng, NULL, NULL, 0)) + goto error; + } + + trng_write32(trng->cfg.addr, TRNG_CTRL, PRNGMODE_GEN); + break; + case TRNG_DRNG: + if (trng->stats.elapsed_seed_life > trng->usr_cfg.seed_life) + goto error; + + if (predict && trng->stats.elapsed_seed_life > 0) + goto error; + + trng_write32(trng->cfg.addr, TRNG_CTRL, PRNGMODE_GEN); + break; + default: + if (!trng->usr_cfg.df_disable) { + memset(&trng->dfin, 0, sizeof(trng->dfin)); + len = (trng->usr_cfg.dfmul + 1) * BYTES_PER_BLOCK; + trng->len = len; + p = trng->dfin.entropy; + } + /* Enable the 8 ring oscillators used for entropy source */ + trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); + trng_soft_reset(trng); + trng_write32(trng->cfg.addr, TRNG_CTRL, + TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK); + break; + } + + if (trng_collect_random(trng, p, len)) + goto error; + + trng->stats.bytes_reseed += len; + trng->stats.bytes += len; + trng->stats.elapsed_seed_life++; + + if (!trng->usr_cfg.df_disable && trng->usr_cfg.mode == TRNG_PTRNG) + trng_df_algorithm(trng, buf, DF_RAND, NULL); + + return TEE_SUCCESS; +error: + if (trng->status != TRNG_CATASTROPHIC) + trng->status = TRNG_ERROR; + + return TEE_ERROR_GENERIC; +} + +static TEE_Result trng_release(struct versal_trng *trng) +{ + if (!trng) + return TEE_ERROR_GENERIC; + + if (trng->status == TRNG_UNINITIALIZED) + goto error; + + trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, NULL); + trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS, NULL); + trng_hold_reset(trng); + + /* Clear the instance */ + memset(&trng->usr_cfg, 0, sizeof(trng->usr_cfg)); + memset(trng->buf, 0, sizeof(trng->buf)); + memset(trng->dfout, 0, sizeof(trng->dfout)); + trng->status = TRNG_UNINITIALIZED; + + return TEE_SUCCESS; +error: + trng->status = TRNG_ERROR; + + return TEE_ERROR_GENERIC; +} + +/* Health tests should be run when the configured mode is of PTRNG or HRNG */ +static TEE_Result trng_health_test(struct versal_trng *trng) +{ + struct trng_usr_cfg tests = { + .mode = TRNG_HRNG, + .seed_life = 10, + .dfmul = 7, + .predict_en = false, + .iseed_en = false, + .pstr_en = false, + .df_disable = false, + }; + + if (trng_instantiate(trng, &tests)) + goto error; + + if (trng_release(trng)) + goto error; + + return TEE_SUCCESS; +error: + trng->status = TRNG_ERROR; + + return TEE_ERROR_GENERIC; +} + +/* + * The KAT test should be run when the TRNG is configured in DRNG or HRNG mode. + * If KAT fails, the driver has to be put in error state. + */ +static TEE_Result trng_kat_test(struct versal_trng *trng) +{ + struct trng_usr_cfg tests = { + .mode = TRNG_DRNG, + .seed_life = 5, + .dfmul = 2, + .predict_en = false, + .iseed_en = true, + .pstr_en = true, + .df_disable = false, + }; + const uint8_t ext_seed[TRNG_SEED_LEN] = { + 0x3BU, 0xC3U, 0xEDU, 0x64U, 0xF4U, 0x80U, 0x1CU, 0xC7U, + 0x14U, 0xCCU, 0x35U, 0xEDU, 0x57U, 0x01U, 0x2AU, 0xE4U, + 0xBCU, 0xEFU, 0xDEU, 0xF6U, 0x7CU, 0x46U, 0xA6U, 0x34U, + 0xC6U, 0x79U, 0xE8U, 0x91U, 0x5DU, 0xB1U, 0xDBU, 0xA7U, + 0x49U, 0xA5U, 0xBBU, 0x4FU, 0xEDU, 0x30U, 0xB3U, 0x7BU, + 0xA9U, 0x8BU, 0xF5U, 0x56U, 0x4DU, 0x40U, 0x18U, 0x9FU, + }; + const uint8_t pers_str[TRNG_PERS_STR_LEN] = { + 0xB2U, 0x80U, 0x7EU, 0x4CU, 0xD0U, 0xE4U, 0xE2U, 0xA9U, + 0x2FU, 0x1FU, 0x5DU, 0xC1U, 0xA2U, 0x1FU, 0x40U, 0xFCU, + 0x1FU, 0x24U, 0x5DU, 0x42U, 0x61U, 0x80U, 0xE6U, 0xE9U, + 0x71U, 0x05U, 0x17U, 0x5BU, 0xAFU, 0x70U, 0x30U, 0x18U, + 0xBCU, 0x23U, 0x18U, 0x15U, 0xCBU, 0xB8U, 0xA6U, 0x3EU, + 0x83U, 0xB8U, 0x4AU, 0xFEU, 0x38U, 0xFCU, 0x25U, 0x87U, + }; + const uint8_t expected_out[TRNG_GEN_LEN] = { + 0x91U, 0x9AU, 0x6BU, 0x99U, 0xD5U, 0xBCU, 0x2CU, 0x11U, + 0x5FU, 0x3AU, 0xFCU, 0x0BU, 0x0EU, 0x7BU, 0xC7U, 0x69U, + 0x4DU, 0xE1U, 0xE5U, 0xFEU, 0x59U, 0x9EU, 0xAAU, 0x41U, + 0xD3U, 0x48U, 0xFDU, 0x3DU, 0xD2U, 0xC4U, 0x50U, 0x1EU, + }; + uint8_t out[TRNG_GEN_LEN] = { 0 }; + + if (!trng) + return TEE_ERROR_GENERIC; + + memcpy(&tests.init_seed, ext_seed, sizeof(ext_seed)); + memcpy(tests.pstr, pers_str, sizeof(pers_str)); + + if (trng_instantiate(trng, &tests)) + goto error; + + if (trng_generate(trng, out, sizeof(out), false)) + goto error; + + if (memcmp(out, expected_out, TRNG_GEN_LEN)) { + EMSG("K.A.T mismatch"); + goto error; + } + + if (trng_release(trng)) + goto error; + + return TEE_SUCCESS; +error: + trng->status = TRNG_ERROR; + return TEE_ERROR_GENERIC; +} + +static struct versal_trng versal_trng = { + .cfg.base = TRNG_BASE, + .cfg.len = TRNG_SIZE, +}; + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + uint8_t random[TRNG_SEC_STRENGTH_LEN] = { 0 }; + uint8_t *p = buf; + size_t i = 0; + + for (i = 0; i < len / TRNG_SEC_STRENGTH_LEN; i++) { + if (trng_generate(&versal_trng, p + i * TRNG_SEC_STRENGTH_LEN, + TRNG_SEC_STRENGTH_LEN, false)) + panic(); + } + + if (len % TRNG_SEC_STRENGTH_LEN) { + if (trng_generate(&versal_trng, random, TRNG_SEC_STRENGTH_LEN, + false)) + panic(); + memcpy(p + i * TRNG_SEC_STRENGTH_LEN, random, + len % TRNG_SEC_STRENGTH_LEN); + } + + return TEE_SUCCESS; +} + +void plat_rng_init(void) +{ +} + +static TEE_Result trng_hrng_mode_init(void) +{ + const uint8_t pers_str[TRNG_PERS_STR_LEN] = { + 0xB2, 0x80, 0x7E, 0x4C, 0xD0, 0xE4, 0xE2, 0xA9, + 0x2F, 0x1F, 0x5D, 0xC1, 0xA2, 0x1F, 0x40, 0xFC, + 0x1F, 0x24, 0x5D, 0x42, 0x61, 0x80, 0xE6, 0xE9, + 0x71, 0x05, 0x17, 0x5B, 0xAF, 0x70, 0x30, 0x18, + 0xBC, 0x23, 0x18, 0x15, 0xCB, 0xB8, 0xA6, 0x3E, + 0x83, 0xB8, 0x4A, 0xFE, 0x38, 0xFC, 0x25, 0x87, + }; + /* configure in hybrid mode with derivative function enabled */ + struct trng_usr_cfg usr_cfg = { + .mode = TRNG_HRNG, + .seed_life = CFG_VERSAL_TRNG_SEED_LIFE, + .predict_en = false, + .df_disable = false, + .dfmul = CFG_VERSAL_TRNG_DF_MUL, + .iseed_en = false, + .pstr_en = true, + }; + + memcpy(usr_cfg.pstr, pers_str, TRNG_PERS_STR_LEN); + versal_trng.cfg.addr = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, + versal_trng.cfg.base, + versal_trng.cfg.len); + if (!versal_trng.cfg.addr) { + EMSG("Failed to map TRNG"); + panic(); + } + + if (trng_kat_test(&versal_trng)) { + EMSG("KAT Failed"); + panic(); + } + + if (trng_health_test(&versal_trng)) { + EMSG("RunHealthTest Failed"); + panic(); + } + + if (trng_instantiate(&versal_trng, &usr_cfg)) { + EMSG("Driver instantiation Failed"); + panic(); + } + + if (trng_reseed(&versal_trng, NULL, usr_cfg.dfmul)) { + EMSG("Reseed Failed"); + panic(); + } + + return TEE_SUCCESS; +} + +driver_init(trng_hrng_mode_init); diff --git a/optee/optee_os/core/drivers/wdt/sub.mk b/optee/optee_os/core/drivers/wdt/sub.mk new file mode 100644 index 0000000..3e20ff8 --- /dev/null +++ b/optee/optee_os/core/drivers/wdt/sub.mk @@ -0,0 +1,2 @@ +srcs-$(CFG_WDT) += watchdog.c +srcs-$(CFG_WDT_SM_HANDLER) += watchdog_sm.c diff --git a/optee/optee_os/core/drivers/wdt/watchdog.c b/optee/optee_os/core/drivers/wdt/watchdog.c new file mode 100644 index 0000000..274f4e2 --- /dev/null +++ b/optee/optee_os/core/drivers/wdt/watchdog.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + */ + +#include + +struct wdt_chip *wdt_chip; + +TEE_Result watchdog_register(struct wdt_chip *chip) +{ + if (!chip->ops->start || !chip->ops->ping || !chip->ops->set_timeout) + return TEE_ERROR_BAD_PARAMETERS; + + wdt_chip = chip; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/wdt/watchdog_sm.c b/optee/optee_os/core/drivers/wdt/watchdog_sm.c new file mode 100644 index 0000000..690a18e --- /dev/null +++ b/optee/optee_os/core/drivers/wdt/watchdog_sm.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2022 Microchip + */ + +#include +#include +#include +#include + +enum smcwd_call { + SMCWD_INIT = 0, + SMCWD_SET_TIMEOUT = 1, + SMCWD_ENABLE = 2, + SMCWD_PET = 3, + SMCWD_GET_TIMELEFT = 4, +}; + +static unsigned long wdt_min_timeout; +static unsigned long wdt_max_timeout; +/* Lock for timeout variables */ +static unsigned int wdt_lock = SPINLOCK_UNLOCK; + +enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t exceptions = 0; + unsigned long min_timeout = 0; + unsigned long max_timeout = 0; + + switch (args->a1) { + case SMCWD_INIT: + exceptions = cpu_spin_lock_xsave(&wdt_lock); + res = watchdog_init(&wdt_min_timeout, &wdt_max_timeout); + cpu_spin_unlock_xrestore(&wdt_lock, exceptions); + + if (res) { + args->a0 = PSCI_RET_INTERNAL_FAILURE; + } else { + args->a0 = PSCI_RET_SUCCESS; + args->a1 = wdt_min_timeout; + args->a2 = wdt_max_timeout; + } + break; + case SMCWD_SET_TIMEOUT: + exceptions = cpu_spin_lock_xsave(&wdt_lock); + min_timeout = wdt_min_timeout; + max_timeout = wdt_max_timeout; + cpu_spin_unlock_xrestore(&wdt_lock, exceptions); + + if (args->a2 < min_timeout || args->a2 > max_timeout) { + args->a0 = PSCI_RET_INVALID_PARAMETERS; + break; + } + + watchdog_settimeout(args->a2); + args->a0 = PSCI_RET_SUCCESS; + break; + case SMCWD_ENABLE: + if (args->a2 == 0) { + watchdog_stop(); + args->a0 = PSCI_RET_SUCCESS; + } else if (args->a2 == 1) { + watchdog_start(); + args->a0 = PSCI_RET_SUCCESS; + } else { + args->a0 = PSCI_RET_INVALID_PARAMETERS; + } + break; + case SMCWD_PET: + watchdog_ping(); + args->a0 = PSCI_RET_SUCCESS; + break; + /* SMCWD_GET_TIMELEFT is optional */ + case SMCWD_GET_TIMELEFT: + default: + args->a0 = PSCI_RET_NOT_SUPPORTED; + } + + return SM_HANDLER_SMC_HANDLED; +} diff --git a/optee/optee_os/core/drivers/xiphera_trng.c b/optee/optee_os/core/drivers/xiphera_trng.c new file mode 100644 index 0000000..9786c19 --- /dev/null +++ b/optee/optee_os/core/drivers/xiphera_trng.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Vaisala Oyj + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONTROL_REG 0x00000000 +#define STATUS_REG 0x00000004 +#define RAND_REG 0x00000000 + +#define HOST_TO_TRNG_RESET 0x00000001 +#define HOST_TO_TRNG_RELEASE_RESET 0x00000002 +#define HOST_TO_TRNG_ENABLE 0x80000000 +#define HOST_TO_TRNG_ZEROIZE 0x80000004 +#define HOST_TO_TRNG_ACK_ZEROIZE 0x80000008 +#define HOST_TO_TRNG_READ 0x8000000F + +/* trng statuses */ +#define TRNG_ACK_RESET 0x000000AC +#define TRNG_SUCCESSFUL_STARTUP 0x00000057 +#define TRNG_FAILED_STARTUP 0x000000FA +#define TRNG_NEW_RAND_AVAILABLE 0x000000ED + +static unsigned int trng_lock = SPINLOCK_UNLOCK; + +static vaddr_t xiphera_trng_base; + +static bool xiphera_trng_random_available(void) +{ + uint32_t status = 0; + + status = io_read32(xiphera_trng_base + STATUS_REG); + + return status == TRNG_NEW_RAND_AVAILABLE; +} + +static uint32_t xiphera_trng_read32(void) +{ + uint32_t value = 0; + + value = io_read32(xiphera_trng_base + RAND_REG); + + /* + * Ack that RNG value has been consumed and trigger new one to be + * generated + */ + io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_READ); + io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE); + + return value; +} + +/* This is a true RNG, no need for seeding */ +void plat_rng_init(void) +{ +} + +TEE_Result hw_get_random_bytes(void *buf, size_t len) +{ + uint8_t *rngbuf = buf; + uint32_t val = 0; + size_t len_to_copy = 0; + + assert(buf); + assert(xiphera_trng_base); + + while (len) { + uint32_t exceptions = cpu_spin_lock_xsave(&trng_lock); + + if (xiphera_trng_random_available()) { + val = xiphera_trng_read32(); + + len_to_copy = MIN(len, sizeof(uint32_t)); + memcpy(rngbuf, &val, len_to_copy); + rngbuf += len_to_copy; + len -= len_to_copy; + } + + cpu_spin_unlock_xrestore(&trng_lock, exceptions); + } + + return TEE_SUCCESS; +} + +static TEE_Result xiphera_trng_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + int dt_status = fdt_get_status(fdt, node); + uint32_t status = 0; + size_t size = 0; + + /* Skip non-secure instances */ + if (dt_status != DT_STATUS_OK_SEC) + return TEE_ERROR_NODE_DISABLED; + + if (xiphera_trng_base) { + EMSG("Only one secure instance is supported"); + return TEE_ERROR_GENERIC; + } + + if (dt_map_dev(fdt, node, &xiphera_trng_base, &size, DT_MAP_AUTO) < 0) + return TEE_ERROR_GENERIC; + + /* + * The TRNG needs to be first reset in order to provide stable + * operation. + * + * Reset of the chip should complete within 200 us but in some cases it + * could take up to 400 us. If it is not ready within 400 us assume + * there is problem. + */ + io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_RESET); + udelay(200); + + status = io_read32(xiphera_trng_base + STATUS_REG); + if (status != TRNG_ACK_RESET) { + /* + * Give it additional 200 us to allow it to reset. + * + * If still not done -> error out. + */ + udelay(200); + status = io_read32(xiphera_trng_base + STATUS_REG); + if (status != TRNG_ACK_RESET) { + EMSG("Failed to reset TRNG\n"); + return TEE_ERROR_GENERIC; + } + } + + /* + * Now TRNG should be internally stable. + * + * Clear internal random number generation engine to start in stable + * state and give it 20 ms to enable good random number entropy and + * then check that random number engine is ready. + */ + io_write32(xiphera_trng_base + CONTROL_REG, + HOST_TO_TRNG_RELEASE_RESET); + io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE); + io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ZEROIZE); + mdelay(20); + + status = io_read32(xiphera_trng_base + STATUS_REG); + if (status != TRNG_SUCCESSFUL_STARTUP) { + /* + * Check specifically if there were startup test errors to aid + * in debugging TRNG implementation in FPGA + */ + if (status == TRNG_FAILED_STARTUP) { + EMSG("Startup tests have failed\n"); + return TEE_ERROR_GENERIC; + } + + EMSG("Startup tests yielded no response -> TRNG stuck\n"); + return TEE_ERROR_GENERIC; + } + + io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE); + + DMSG("TRNG initialized\n"); + + return TEE_SUCCESS; +} + +static const struct dt_device_match xiphera_trng_match_table[] = { + { .compatible = "xiphera,xip8001b-trng" }, + { } +}; + +DEFINE_DT_DRIVER(xiphera_trng_dt_driver) = { + .name = "xiphera_trng", + .type = DT_DRIVER_NOTYPE, + .match_table = xiphera_trng_match_table, + .probe = xiphera_trng_probe, +}; diff --git a/optee/optee_os/core/drivers/zynqmp_csu_aes.c b/optee/optee_os/core/drivers/zynqmp_csu_aes.c new file mode 100644 index 0000000..ae5e686 --- /dev/null +++ b/optee/optee_os/core/drivers/zynqmp_csu_aes.c @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2021 + * Author: Jorge Ramirez + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* CSU AES registers */ +#define AES_STS_OFFSET 0x00 +#define AES_KEY_SRC_OFFSET 0x04 +#define AES_KEY_LOAD_OFFSET 0x08 +#define AES_START_MSG_OFFSET 0x0C +#define AES_RESET_OFFSET 0x10 +#define AES_KEY_CLR_OFFSET 0x14 +#define AES_CFG_OFFSET 0x18 + +#define AES_KEY_LOAD 1 +#define AES_STS_AES_BUSY BIT(0) +#define AES_STS_AES_KEY_ZEROED BIT(8) +#define AES_STS_KUP_ZEROED BIT(9) +#define AES_STS_KEY_INIT_DONE BIT(4) +#define AES_STS_GCM_TAG_OK BIT(3) +#define AES_START_MSG 1 +#define AES_CFG_ENC 1 +#define AES_CFG_DEC 0 +#define AES_RESET_SET 1 +#define AES_RESET_CLR 0 +#define AES_KEY_ZERO BIT(0) +#define AES_KUP_ZERO BIT(1) + +#define AES_TIMEOUT_USEC 2000000 + +enum aes_op { AES_DEC, AES_ENC }; + +static TEE_Result aes_wait(uint32_t event, bool set) +{ + vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC, + ZYNQMP_CSU_AES_SIZE); + uint64_t tref = timeout_init_us(AES_TIMEOUT_USEC); + uint32_t status = 0; + + if (!aes) + return TEE_ERROR_GENERIC; + + while (!timeout_elapsed(tref)) { + status = io_read32(aes + AES_STS_OFFSET) & event; + if ((set && status == event) || (!set && status != event)) + return TEE_SUCCESS; + } + + return TEE_ERROR_GENERIC; +} + +static TEE_Result aes_transfer_enc(const void *src, void *dst, size_t dst_len, + void *tag, const void *iv) +{ + void *p = (uint8_t *)dst + dst_len - ZYNQMP_GCM_TAG_SIZE; + uint8_t iv_padded[ZYNQMP_CSUDMA_MIN_SIZE] __aligned_csudma = { 0 }; + TEE_Result ret = TEE_SUCCESS; + + if (dst_len < ZYNQMP_GCM_TAG_SIZE) { + EMSG("Invalid length"); + return TEE_ERROR_GENERIC; + } + + ret = zynqmp_csudma_prepare(); + if (ret) { + EMSG("DMA can't initialize"); + return ret; + } + + /* Prepare destination */ + ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_DST_CHANNEL, dst, dst_len, + 0); + if (ret) { + EMSG("DMA transfer failed, invalid destination buffer"); + goto out; + } + + /* Inputs */ + memcpy(iv_padded, iv, ZYNQMP_GCM_IV_SIZE); + ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, + (void *)iv_padded, ZYNQMP_CSUDMA_MIN_SIZE, + 0); + if (ret) { + EMSG("DMA transfer failed, invalid IV buffer"); + goto out; + } + + ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); + if (ret) { + EMSG("DMA IV transfer timeout"); + goto out; + } + + ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, + (void *)src, dst_len - ZYNQMP_GCM_TAG_SIZE, + ZYNQMP_CSUDMA_DONE); + if (ret) { + EMSG("DMA transfer failed, invalid source buffer"); + goto out; + } + + ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); + if (ret) { + EMSG("DMA source transfer timeout"); + goto out; + } + + /* Wait for completion */ + ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_DST_CHANNEL); + if (ret) { + EMSG("DMA destination transfer timeout"); + goto out; + } + + /* Transfer the GCM tag */ + memcpy(tag, p, ZYNQMP_GCM_TAG_SIZE); +out: + zynqmp_csudma_unprepare(); + + return ret; +} + +static TEE_Result aes_transfer_dec(const void *src, void *dst, size_t len, + const void *tag, const void *iv) +{ + uint8_t iv_padded[ZYNQMP_CSUDMA_MIN_SIZE] __aligned_csudma = { 0 }; + TEE_Result ret = TEE_SUCCESS; + + ret = zynqmp_csudma_prepare(); + if (ret) { + EMSG("DMA can't initialize"); + return ret; + } + + /* Prepare destination */ + ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_DST_CHANNEL, dst, len, 0); + if (ret) { + EMSG("DMA transfer failed, invalid destination buffer"); + goto out; + } + + /* Inputs */ + memcpy(iv_padded, iv, ZYNQMP_GCM_IV_SIZE); + ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, + (void *)iv_padded, ZYNQMP_CSUDMA_MIN_SIZE, + 0); + if (ret) { + EMSG("DMA transfer failed, invalid IV buffer"); + goto out; + } + + ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); + if (ret) { + EMSG("DMA IV transfer timeout"); + goto out; + } + + ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)src, + len, ZYNQMP_CSUDMA_DONE); + if (ret) { + EMSG("DMA transfer failed, invalid source buffer"); + goto out; + } + + ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); + if (ret) { + EMSG("DMA source transfer timeout"); + goto out; + } + + ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)tag, + ZYNQMP_GCM_TAG_SIZE, ZYNQMP_CSUDMA_DONE); + if (ret) { + EMSG("DMA transfer failed, invalid tag buffer"); + goto out; + } + + ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); + if (ret) { + EMSG("DMA tag transfer timeout"); + goto out; + } + + /* Wait for completion*/ + ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_DST_CHANNEL); + if (ret) + EMSG("DMA destination transfer timeout"); +out: + zynqmp_csudma_unprepare(); + + return ret; +} + +static TEE_Result aes_prepare_op(enum aes_op op, enum zynqmp_csu_key key) +{ + vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC, + ZYNQMP_CSU_AES_SIZE); + vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); + TEE_Result ret = TEE_SUCCESS; + + if (!aes || !csu) + return TEE_ERROR_GENERIC; + + /* Connect DMA0 in/out to AES */ + io_write32(csu + ZYNQMP_CSU_SSS_CFG_OFFSET, + ZYNQMP_CSU_SSS_DMA0_STREAM_TO_AES); + + /* Reset the AES */ + io_write32(aes + AES_RESET_OFFSET, AES_RESET_SET); + io_write32(aes + AES_RESET_OFFSET, AES_RESET_CLR); + + /* Load the key */ + io_write32(aes + AES_KEY_CLR_OFFSET, 0); + io_write32(aes + AES_KEY_SRC_OFFSET, key); + io_write32(aes + AES_KEY_LOAD_OFFSET, AES_KEY_LOAD); + ret = aes_wait(AES_STS_KEY_INIT_DONE, true); + if (ret) { + EMSG("Timeout loading the key"); + return TEE_ERROR_GENERIC; + } + + /* Configure operation */ + io_write32(aes + AES_CFG_OFFSET, + op == AES_DEC ? AES_CFG_DEC : AES_CFG_ENC); + + /* Prepare the CSU for the DMA */ + io_write32(csu + ZYNQMP_CSU_DMA_RESET_OFFSET, ZYNQMP_CSU_DMA_RESET_SET); + io_write32(csu + ZYNQMP_CSU_DMA_RESET_OFFSET, ZYNQMP_CSU_DMA_RESET_CLR); + + /* Start the message */ + io_write32(aes + AES_START_MSG_OFFSET, AES_START_MSG); + + return TEE_SUCCESS; +} + +static TEE_Result aes_done_op(enum aes_op op, TEE_Result ret) +{ + vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC, + ZYNQMP_CSU_AES_SIZE); + uint32_t val = 0; + + if (!aes) + return TEE_ERROR_GENERIC; + + if (!ret && op == AES_DEC) { + /* on decompression we must validate the GCM tag */ + val = io_read32(aes + AES_STS_OFFSET) & AES_STS_GCM_TAG_OK; + if (!val) { + EMSG("AES-GCM tag mismatch"); + return TEE_ERROR_GENERIC; + } + } + + val = io_read32(aes + AES_KEY_CLR_OFFSET); + io_write32(aes + AES_KEY_CLR_OFFSET, val | AES_KEY_ZERO | AES_KUP_ZERO); + if (aes_wait(AES_STS_AES_KEY_ZEROED | AES_STS_KUP_ZEROED, true)) + EMSG("Failed to clear the AES key"); + io_write32(aes + AES_KEY_CLR_OFFSET, val); + + io_write32(aes + AES_RESET_OFFSET, AES_RESET_SET); + + return ret; +} + +TEE_Result zynqmp_csu_aes_decrypt_data(const void *src, size_t src_len, + void *dst, size_t dst_len, + const void *tag, size_t tag_len, + const void *iv, size_t iv_len, + enum zynqmp_csu_key key) +{ + TEE_Result ret = TEE_SUCCESS; + + if (key != ZYNQMP_CSU_AES_KEY_SRC_DEV) { + EMSG("Key type not supported"); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + if (src_len % 4 || dst_len != src_len) { + EMSG("Invalid source size"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (iv_len != ZYNQMP_GCM_IV_SIZE) { + EMSG("Invalid IV size"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (tag_len != ZYNQMP_GCM_TAG_SIZE) { + EMSG("Invalid tag size"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!src || !dst || !tag || !iv) { + EMSG("Invalid input value"); + return TEE_ERROR_BAD_PARAMETERS; + } + + ret = aes_prepare_op(AES_DEC, key); + if (ret) { + EMSG("Decrypt init failed"); + goto out; + } + + ret = aes_transfer_dec(src, dst, src_len, tag, iv); + if (ret) { + EMSG("DMA transfer failed"); + goto out; + } + + ret = aes_wait(AES_STS_AES_BUSY, false); + if (ret) + EMSG("AES-GCM transfer failed"); +out: + return aes_done_op(AES_DEC, ret); +} + +TEE_Result zynqmp_csu_aes_encrypt_data(const void *src, size_t src_len, + void *dst, size_t dst_len, + void *tag, size_t tag_len, + const void *iv, size_t iv_len, + enum zynqmp_csu_key key) +{ + TEE_Result ret = TEE_SUCCESS; + + if (key != ZYNQMP_CSU_AES_KEY_SRC_DEV) { + EMSG("Key type not supported"); + return TEE_ERROR_NOT_IMPLEMENTED; + } + + if (src_len % 4 || dst_len != ZYNQMP_CSU_AES_DST_LEN(src_len)) { + EMSG("Invalid source size"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (iv_len != ZYNQMP_GCM_IV_SIZE) { + EMSG("Invalid IV size"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (tag_len != ZYNQMP_GCM_TAG_SIZE) { + EMSG("Invalid tag size"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!src || !dst || !tag || !iv) { + EMSG("Invalid input value"); + return TEE_ERROR_BAD_PARAMETERS; + } + + ret = aes_prepare_op(AES_ENC, key); + if (ret) { + EMSG("Encrypt init failed"); + goto out; + } + + ret = aes_transfer_enc(src, dst, dst_len, tag, iv); + if (ret) { + EMSG("DMA transfer failed"); + goto out; + } + + ret = aes_wait(AES_STS_AES_BUSY, false); + if (ret) + EMSG("AES transfer failed"); +out: + return aes_done_op(AES_ENC, ret); +} + +static const char *const dt_ctrl_match_table[] = { + "xlnx,zynqmp-aes", +}; + +TEE_Result zynqmp_csu_aes_dt_enable_secure_status(void) +{ + unsigned int i = 0; + void *fdt = NULL; + int node = -1; + + fdt = get_external_dt(); + if (!fdt) + return TEE_SUCCESS; + + for (i = 0; i < ARRAY_SIZE(dt_ctrl_match_table); i++) { + node = fdt_node_offset_by_compatible(fdt, 0, + dt_ctrl_match_table[i]); + if (node >= 0) + break; + } + + if (node < 0) + return TEE_SUCCESS; + + if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED) + return TEE_SUCCESS; + + if (dt_enable_secure_status(fdt, node)) { + EMSG("Not able to set the AES-GCM DTB entry secure"); + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/zynqmp_csu_puf.c b/optee/optee_os/core/drivers/zynqmp_csu_puf.c new file mode 100644 index 0000000..1f8dc4f --- /dev/null +++ b/optee/optee_os/core/drivers/zynqmp_csu_puf.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 Foundries.io Ltd. + * + * Jorge Ramirez-Ortiz + */ +#include +#include +#include +#include +#include +#include +#include + +#define PUF_CMD_OFFSET 0x00 +#define PUF_CFG0_OFFSET 0x04 +#define PUF_CFG1_OFFSET 0x08 +#define PUF_SHUT_OFFSET 0x0C +#define PUF_STATUS_OFFSET 0x10 +#define PUF_WORD_OFFSET 0x18 + +#define PUF_REGENERATION 4 +#define PUF_RESET 6 + +#define PUF_CFG0_DEFAULT 0x02 +#define PUF_SHUT_DEFAULT 0x01000100 +#define PUF_REGEN_TIME_MS 6 + +TEE_Result zynqmp_csu_puf_regenerate(void) +{ + vaddr_t puf = core_mmu_get_va(ZYNQMP_CSU_PUF_BASE, MEM_AREA_IO_SEC, + ZYNQMP_CSU_PUF_SIZE); + vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); + uint32_t status = 0; + + if (!puf || !csu) + return TEE_ERROR_GENERIC; + + io_write32(puf + PUF_CFG0_OFFSET, PUF_CFG0_DEFAULT); + io_write32(puf + PUF_SHUT_OFFSET, PUF_SHUT_DEFAULT); + io_write32(puf + PUF_CMD_OFFSET, PUF_REGENERATION); + mdelay(PUF_REGEN_TIME_MS); + + status = io_read32(csu + ZYNQMP_CSU_ISR_OFFSET); + if (status & ZYNQMP_CSU_ISR_PUF_ACC_ERROR_MASK) { + EMSG("regeneration failed"); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +void zynqmp_csu_puf_reset(void) +{ + vaddr_t puf = core_mmu_get_va(ZYNQMP_CSU_PUF_BASE, MEM_AREA_IO_SEC, + ZYNQMP_CSU_PUF_SIZE); + + io_write32(puf + PUF_CMD_OFFSET, PUF_RESET); +} + +static TEE_Result zynqmp_csu_puf_init(void) +{ + vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); + uint32_t status = 0; + + /* if the bootloader has been authenticated, reserve the PUF */ + status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET); + if (status & ZYNQMP_CSU_STATUS_AUTH) + return zynqmp_csu_aes_dt_enable_secure_status(); + + return TEE_SUCCESS; +} + +driver_init(zynqmp_csu_puf_init); diff --git a/optee/optee_os/core/drivers/zynqmp_csudma.c b/optee/optee_os/core/drivers/zynqmp_csudma.c new file mode 100644 index 0000000..8809635 --- /dev/null +++ b/optee/optee_os/core/drivers/zynqmp_csudma.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 Foundries.io Ltd. + * Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include + +#define CSUDMA_ADDR_OFFSET 0x00 +#define CSUDMA_SIZE_OFFSET 0x04 +#define CSUDMA_STS_OFFSET 0x08 +#define CSUDMA_CTRL_OFFSET 0x0C +#define CSUDMA_CRC_OFFSET 0x10 +#define CSUDMA_I_STS_OFFSET 0x14 +#define CSUDMA_I_EN_OFFSET 0x18 +#define CSUDMA_I_DIS_OFFSET 0x1C +#define CSUDMA_I_MASK_OFFSET 0x20 +#define CSUDMA_CTRL2_OFFSET 0x24 +#define CSUDMA_ADDR_MSB_OFFSET 0x28 + +#define CSUDMA_OFFSET_DIFF 0x0800 + +#define CSUDMA_ADDR_MASK GENMASK_32(31, 2) +#define CSUDMA_ADDR_LSB_MASK (BIT(0) | BIT(1)) +#define CSUDMA_ADDR_MSB_MASK GENMASK_32(16, 0) +#define CSUDMA_ADDR_MSB_SHIFT 32 +#define CSUDMA_SIZE_SHIFT 2 +#define CSUDMA_STS_BUSY_MASK BIT(0) +#define CSUDMA_CTRL_ENDIAN_MASK BIT(23) +#define CSUDMA_LAST_WORD_MASK BIT(0) +#define CSUDMA_IXR_DONE_MASK BIT(1) +#define CSUDMA_IXR_SRC_MASK GENMASK_32(6, 0) +#define CSUDMA_IXR_DST_MASK GENMASK_32(7, 1) + +#define CSUDMA_DONE_TIMEOUT_USEC 3000000 + +register_phys_mem_pgdir(MEM_AREA_IO_SEC, CSUDMA_BASE, CSUDMA_SIZE); + +static void csudma_clear_intr(enum zynqmp_csudma_channel channel, uint32_t mask) +{ + vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, + CSUDMA_SIZE); + uint32_t val = CSUDMA_IXR_SRC_MASK; + + if (channel == ZYNQMP_CSUDMA_DST_CHANNEL) { + dma += CSUDMA_OFFSET_DIFF; + val = CSUDMA_IXR_DST_MASK; + } + + io_write32(dma + CSUDMA_I_STS_OFFSET, val & mask); +} + +TEE_Result zynqmp_csudma_sync(enum zynqmp_csudma_channel channel) +{ + vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, + CSUDMA_SIZE); + uint64_t tref = timeout_init_us(CSUDMA_DONE_TIMEOUT_USEC); + uint32_t status = 0; + + if (!dma) + return TEE_ERROR_GENERIC; + + if (channel == ZYNQMP_CSUDMA_DST_CHANNEL) + dma = dma + CSUDMA_OFFSET_DIFF; + + while (!timeout_elapsed(tref)) { + status = io_read32(dma + CSUDMA_I_STS_OFFSET); + if ((status & CSUDMA_IXR_DONE_MASK) == CSUDMA_IXR_DONE_MASK) { + csudma_clear_intr(channel, CSUDMA_IXR_DONE_MASK); + return TEE_SUCCESS; + } + } + + return TEE_ERROR_GENERIC; +} + +TEE_Result zynqmp_csudma_prepare(void) +{ + vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, + CSUDMA_SIZE); + + if (!dma) + return TEE_ERROR_GENERIC; + + io_setbits32(dma + CSUDMA_CTRL_OFFSET, CSUDMA_CTRL_ENDIAN_MASK); + dma = dma + CSUDMA_OFFSET_DIFF; + io_setbits32(dma + CSUDMA_CTRL_OFFSET, CSUDMA_CTRL_ENDIAN_MASK); + + return TEE_SUCCESS; +} + +void zynqmp_csudma_unprepare(void) +{ + vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, + CSUDMA_SIZE); + + io_clrbits32(dma + CSUDMA_CTRL_OFFSET, CSUDMA_CTRL_ENDIAN_MASK); + dma = dma + CSUDMA_OFFSET_DIFF; + io_clrbits32(dma + CSUDMA_CTRL_OFFSET, CSUDMA_CTRL_ENDIAN_MASK); +} + +TEE_Result zynqmp_csudma_transfer(enum zynqmp_csudma_channel channel, + void *addr, size_t len, uint8_t notify) +{ + vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, + CSUDMA_SIZE); + paddr_t phys = virt_to_phys(addr); + uint32_t addr_offset = 0; + + if (!dma) + return TEE_ERROR_GENERIC; + + if (len % sizeof(uint32_t)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!IS_ALIGNED(phys, ZYNQMP_CSUDMA_ALIGN)) { + EMSG("Invalid alignment"); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* convert to 32 bit word transfers */ + len = len / sizeof(uint32_t); + + if (channel == ZYNQMP_CSUDMA_DST_CHANNEL) { + dma = dma + CSUDMA_OFFSET_DIFF; + dcache_inv_range(addr, SHIFT_U64(len, CSUDMA_SIZE_SHIFT)); + } else { + dcache_clean_range(addr, SHIFT_U64(len, CSUDMA_SIZE_SHIFT)); + } + + addr_offset = phys & CSUDMA_ADDR_MASK; + io_write32(dma + CSUDMA_ADDR_OFFSET, addr_offset); + + addr_offset = phys >> CSUDMA_ADDR_MSB_SHIFT; + io_write32(dma + CSUDMA_ADDR_MSB_OFFSET, addr_offset); + io_write32(dma + CSUDMA_SIZE_OFFSET, + SHIFT_U32(len, CSUDMA_SIZE_SHIFT) | notify); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/drivers/zynqmp_huk.c b/optee/optee_os/core/drivers/zynqmp_huk.c new file mode 100644 index 0000000..bb6727c --- /dev/null +++ b/optee/optee_os/core/drivers/zynqmp_huk.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 Foundries.io Ltd. + * Jorge Ramirez-Ortiz + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct { + uint8_t key[HW_UNIQUE_KEY_LENGTH]; + bool ready; +} huk; + +__weak TEE_Result tee_zynqmp_get_device_dna(uint8_t *device_dna, size_t size) +{ + if (size != ZYNQMP_EFUSE_LEN(DNA)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Get Device DNA from the PS eFuses */ + return zynqmp_efuse_read(device_dna, size, DNA, false); +} + +/* + * Generate HUK source data + * + * Performs SHA256 over of data: + * - Device DNA (from PL preferably) + * - Selected user eFuses (HUK seed) + * + * HUK source data is later on AES encrypted with device key to shuffle source + * data even further with secret key. + * + * Note: Even though the device key is secret used details for HUK source data + * should not be exposed to REE environment. + * + * Note: You should not change HUK source data generation parameters after + * devices have been deployed. + * + * @device_dna: Value of Device DNA + * @device_dna_size: Size of Device DNA + * @huk_source: Output buffer for HUK source data + * @huk_source_size: Output buffer size for HUK source data + * Return a TEE_Result compliant status + */ +static TEE_Result tee_zynqmp_generate_huk_src(const uint8_t *device_dna, + size_t device_dna_size, + uint8_t *huk_source, + size_t huk_source_size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t user_efuse = 0; + void *ctx = NULL; + int i = 0; + + assert(device_dna_size == ZYNQMP_EFUSE_LEN(DNA)); + assert(huk_source_size == HW_UNIQUE_KEY_LENGTH); + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); + if (res) + return res; + + res = crypto_hash_init(ctx); + if (res) + goto out; + + res = crypto_hash_update(ctx, device_dna, device_dna_size); + if (res) + goto out; + + /* Hash selected user eFuses */ + for (i = 0; i < (USER7 - USER0 + 1); i++) { + if (CFG_ZYNQMP_HUK_USER_EFUSE_MASK & BIT(i)) { + DMSG("Use User eFuse %d for HUK source data", i); + + res = zynqmp_efuse_read((uint8_t *)&user_efuse, + sizeof(user_efuse), USER0 + i, + false); + if (res) + goto out; + + res = crypto_hash_update(ctx, (uint8_t *)&user_efuse, + sizeof(user_efuse)); + if (res) + goto out; + } + } + + res = crypto_hash_final(ctx, huk_source, huk_source_size); +out: + crypto_hash_free_ctx(ctx); + memzero_explicit(&user_efuse, sizeof(user_efuse)); + return res; +} + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); + uint8_t device_dna[ZYNQMP_EFUSE_LEN(DNA)] = { 0 }; + uint8_t src[HW_UNIQUE_KEY_LENGTH] __aligned_csuaes = { 0 }; + uint8_t iv[ZYNQMP_GCM_IV_SIZE] = { 0 }; + uint8_t tag[ZYNQMP_GCM_TAG_SIZE] __aligned_csuaes = { 0 }; + uint8_t sha[HW_UNIQUE_KEY_LENGTH] = { 0 }; + uint8_t dst[ZYNQMP_CSU_AES_DST_LEN(sizeof(src))] + __aligned_csuaes = { 0 }; + TEE_Result ret = TEE_ERROR_GENERIC; + uint32_t status = 0; + + static_assert(sizeof(device_dna) == ZYNQMP_GCM_IV_SIZE); + + if (huk.ready) + goto out; + + ret = tee_zynqmp_get_device_dna(device_dna, sizeof(device_dna)); + if (ret) { + EMSG("Can't read the Device DNA"); + goto cleanup; + } + + status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET); + if (!(status & ZYNQMP_CSU_STATUS_AUTH)) { + /* The DNA is a unique identifier valid but not secure */ + IMSG("CSU authentication disabled, using development HUK"); + + /* Use hash of device DNA for development HUK */ + ret = tee_hash_createdigest(TEE_ALG_SHA256, device_dna, + sizeof(device_dna), huk.key, + sizeof(huk.key)); + if (ret) { + EMSG("Can't generate the SHA256 for the DNA eFuse"); + goto cleanup; + } + + huk.ready = true; + goto out; + } + + /* Use device DNA for IV */ + memcpy(iv, device_dna, sizeof(device_dna)); + + /* Generate HUK source data */ + ret = tee_zynqmp_generate_huk_src(device_dna, sizeof(device_dna), src, + sizeof(src)); + if (ret) { + EMSG("Failed to generate HUK source data"); + goto cleanup; + } + +#ifdef CFG_ZYNQMP_CSU_PUF + /* + * Neither the PMUFW nor the PUF hardware provide an indication of the + * PUF KEK registration status. The verification algorithm that follows + * encrypts and then decrypts the resulting string regenerating the + * PUF KEK in between: if the outputs match, then the PUF KEK was + * registered properly and we can use it to generate the HUK. + */ + zynqmp_csu_puf_reset(); + + ret = zynqmp_csu_puf_regenerate(); + if (ret) { + EMSG("PUF regeneration error"); + goto cleanup; + } +#endif + + memcpy(sha, src, sizeof(sha)); + /* The dst buffer must be large enough to include the generated tag */ + ret = zynqmp_csu_aes_encrypt_data(src, sizeof(src), dst, sizeof(dst), + tag, sizeof(tag), iv, sizeof(iv), + ZYNQMP_CSU_AES_KEY_SRC_DEV); + if (ret) { + EMSG("Can't encrypt DNA, please make sure PUF was registered"); + goto cleanup; + } + +#ifdef CFG_ZYNQMP_CSU_PUF + /* regenerate the PUF KEK */ + ret = zynqmp_csu_puf_regenerate(); + if (ret) { + EMSG("PUF regeneration error"); + goto cleanup; + } +#endif + memset(src, 0, sizeof(src)); + /* Ignore the tag data from the dst buffer - pass a smaller size */ + ret = zynqmp_csu_aes_decrypt_data(dst, sizeof(src), src, sizeof(src), + tag, sizeof(tag), iv, + ZYNQMP_EFUSE_LEN(DNA), + ZYNQMP_CSU_AES_KEY_SRC_DEV); + if (ret) { + EMSG("Can't decrypt DNA, please make sure PUF was registered"); + goto cleanup; + } + + if (memcmp(src, sha, sizeof(sha))) { + EMSG("PUF not ready, can't create HUK"); + ret = TEE_ERROR_GENERIC; + goto cleanup; + } + + IMSG("HUK ready"); + + /* + * The HUK is the SHA-256 of Device DNA with optional User eFuses + * included and then AES-GCM encrypted with the selected Device Key + * using the Device DNA as the IV. + */ + memcpy(huk.key, dst, sizeof(huk.key)); + huk.ready = true; +out: + memcpy(hwkey->data, huk.key, HW_UNIQUE_KEY_LENGTH); + ret = TEE_SUCCESS; + +cleanup: + /* Cleanup stack memory so that there are no left overs */ + memzero_explicit(dst, sizeof(dst)); + memzero_explicit(sha, sizeof(sha)); + memzero_explicit(tag, sizeof(tag)); + memzero_explicit(iv, sizeof(iv)); + memzero_explicit(src, sizeof(src)); + memzero_explicit(device_dna, sizeof(device_dna)); + + return ret; +} diff --git a/optee/optee_os/core/drivers/zynqmp_pm.c b/optee/optee_os/core/drivers/zynqmp_pm.c new file mode 100644 index 0000000..46c8d51 --- /dev/null +++ b/optee/optee_os/core/drivers/zynqmp_pm.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2021 Foundries.io Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * For additional details about ZynqMP specific SMC ID's and PM request + * handling in TF-A check + * https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842107/Arm+Trusted+Firmware + */ +#define EFUSE_ACCESS_SMC 0xC2000035 +#define VERSION_ACCESS_SMC 0xC2000018 + +#define EFUSE_NOT_ENABLED 29 +#define VERSION_MASK GENMASK_32(3, 0) + +static uint32_t zynqmp_sip_call(uint32_t pm_api_id, uint32_t arg0, + uint32_t arg1, uint32_t arg2, uint32_t arg3, + uint32_t *payload) +{ + struct thread_smc_args args = { + .a0 = pm_api_id, + .a1 = reg_pair_to_64(arg1, arg0), + .a2 = reg_pair_to_64(arg3, arg2), + }; + + thread_smccc(&args); + + if (payload) { + switch (pm_api_id) { + case EFUSE_ACCESS_SMC: + *payload = args.a0 >> 32; + break; + case VERSION_ACCESS_SMC: + *payload = args.a1 & VERSION_MASK; + break; + default: + break; + } + } + + return args.a0; +} + +/* + * Stores all required details to read/write eFuse memory. + * @src: Physical address of the buffer to store the data to be + * written/read (in LE) + * @size: number of 32-bit words to be read/written + * @offset: offset in bytes to be read from/written to + * @flag: EFUSE_READ - represents eFuse read operation + * EFUSE_WRITE - represents eFuse write operation + * @pufuserfuse:0 - represents non-PUF eFuses, offset is used for read/write + * 1 - represents PUF user eFuse row number. + */ +struct xilinx_efuse { + uint64_t src; + uint32_t size; + uint32_t offset; + uint32_t flag; + uint32_t pufuserfuse; +}; + +enum efuse_op { EFUSE_READ = 0, EFUSE_WRITE = 1 }; + +#define EFUSE_ELT(__x) \ + [__x] = { \ + .offset = ZYNQMP_EFUSE_##__x##_OFFSET, \ + .bytes = ZYNQMP_EFUSE_##__x##_LENGTH, \ + } + +static const struct { + uint32_t offset; + uint32_t bytes; +} efuse_tbl[] = { + EFUSE_ELT(DNA), + EFUSE_ELT(IP_DISABLE), + EFUSE_ELT(USER0), + EFUSE_ELT(USER1), + EFUSE_ELT(USER2), + EFUSE_ELT(USER3), + EFUSE_ELT(USER4), + EFUSE_ELT(USER5), + EFUSE_ELT(USER6), + EFUSE_ELT(USER7), + EFUSE_ELT(MISC_USER_CTRL), + EFUSE_ELT(SEC_CTRL), +}; + +static TEE_Result efuse_op(enum efuse_op op, uint8_t *buf, size_t buf_sz, + enum zynqmp_efuse_id id, bool puf) +{ + struct xilinx_efuse *efuse_op = NULL; + uint8_t *tmpbuf = NULL; + paddr_t addr = 0; + uint32_t efuse_ret = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + if (id >= ARRAY_SIZE(efuse_tbl)) { + EMSG("Invalid efuse"); + return TEE_ERROR_BAD_PARAMETERS; + } + + efuse_op = alloc_cache_aligned(sizeof(*efuse_op)); + if (!efuse_op) { + EMSG("Failed to allocate cache aligned buffer for operation"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + tmpbuf = alloc_cache_aligned(buf_sz); + if (!tmpbuf) { + EMSG("Failed to allocate cache aligned buffer for data"); + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (op == EFUSE_WRITE) + memcpy(tmpbuf, buf, buf_sz); + + efuse_op->size = efuse_tbl[id].bytes / sizeof(uint32_t); + efuse_op->offset = efuse_tbl[id].offset; + efuse_op->src = virt_to_phys(tmpbuf); + efuse_op->pufuserfuse = puf; + efuse_op->flag = op; + + cache_operation(TEE_CACHECLEAN, tmpbuf, buf_sz); + cache_operation(TEE_CACHECLEAN, efuse_op, sizeof(*efuse_op)); + + addr = virt_to_phys(efuse_op); + + efuse_ret = zynqmp_sip_call(EFUSE_ACCESS_SMC, addr >> 32, addr, 0, 0, + NULL); + if (efuse_ret) { + if (efuse_ret == EFUSE_NOT_ENABLED) + EMSG("eFuse access is not enabled"); + else + EMSG("Error in eFuse access %#"PRIx32, efuse_ret); + res = TEE_ERROR_GENERIC; + goto out; + } + + if (op == EFUSE_READ) { + res = cache_operation(TEE_CACHEINVALIDATE, tmpbuf, buf_sz); + if (res) + goto out; + memcpy(buf, tmpbuf, buf_sz); + } + + res = TEE_SUCCESS; + +out: + free(tmpbuf); + free(efuse_op); + return res; +} + +TEE_Result zynqmp_efuse_read(uint8_t *buf, size_t sz, enum zynqmp_efuse_id id, + bool puf) +{ + return efuse_op(EFUSE_READ, buf, sz, id, puf); +} + +TEE_Result zynqmp_efuse_write(uint8_t *buf, size_t sz, enum zynqmp_efuse_id id, + bool puf) +{ + return efuse_op(EFUSE_WRITE, buf, sz, id, puf); +} + +TEE_Result zynqmp_soc_version(uint32_t *version) +{ + uint32_t res = 0; + + if (!version) + return TEE_ERROR_BAD_PARAMETERS; + + res = zynqmp_sip_call(VERSION_ACCESS_SMC, 0, 0, 0, 0, version); + if (res) { + EMSG("Failed to retrieve version"); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/include/bench.h b/optee/optee_os/core/include/bench.h new file mode 100644 index 0000000..cdff577 --- /dev/null +++ b/optee/optee_os/core/include/bench.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef BENCH_H +#define BENCH_H + +#include +#include +#include +#include + +/* + * Cycle count divider is enabled (in PMCR), + * CCNT value is incremented every 64th clock cycle + */ +#define TEE_BENCH_DIVIDER U(64) + +/* Max amount of timestamps per buffer */ +#define TEE_BENCH_MAX_STAMPS U(32) +#define TEE_BENCH_MAX_MASK (TEE_BENCH_MAX_STAMPS - 1) + +#define OPTEE_MSG_RPC_CMD_BENCH_REG_NEW U(0) +#define OPTEE_MSG_RPC_CMD_BENCH_REG_DEL U(1) + +/* OP-TEE susbsystems ids */ +#define TEE_BENCH_CLIENT U(0x10000000) +#define TEE_BENCH_KMOD U(0x20000000) +#define TEE_BENCH_CORE U(0x30000000) +#define TEE_BENCH_UTEE U(0x40000000) +#define TEE_BENCH_DUMB_TA U(0xF0000001) + +/* storing timestamp */ +struct tee_time_st { + uint64_t cnt; /* stores value from CNTPCT register */ + uint64_t addr; /* stores value from program counter register */ + uint64_t src; /* OP-TEE subsystem id */ +}; + +/* per-cpu circular buffer for timestamps */ +struct tee_ts_cpu_buf { + uint64_t head; + uint64_t tail; + struct tee_time_st stamps[TEE_BENCH_MAX_STAMPS]; +}; + +/* memory layout for shared memory, where timestamps will be stored */ +struct tee_ts_global { + uint64_t cores; + struct tee_ts_cpu_buf cpu_buf[]; +}; + +#ifdef CFG_TEE_BENCHMARK +void bm_timestamp(void); +#else +static inline void bm_timestamp(void) {} +#endif /* CFG_TEE_BENCHMARK */ + +#endif /* BENCH_H */ diff --git a/optee/optee_os/core/include/console.h b/optee/optee_os/core/include/console.h new file mode 100644 index 0000000..f2e57fb --- /dev/null +++ b/optee/optee_os/core/include/console.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#include +#include + + +void console_init(void); +void console_putc(int ch); +void console_flush(void); + +struct serial_chip; +void register_serial_console(struct serial_chip *chip); + +#ifdef CFG_DT +/* + * Get console info from a reacheable DTB. Check the embedded DTB and fall + * back to the external DTB. + * + * If the DTB does not specify a chosen (or secure-chosen) node, we assume + * DTB does not provide specific console directive. Early console may remain. + * If the DTB does not specify any console in the chosen (or secure-chosen) + * node, we assume there is no console. Early console would be disabled. + * + * @fdt_out: Output DTB address where console directive is found + * @offs_out: Output offset in the DTB where console directive is found + * @path_out: Output string configuration of the console from the DTB. + * (*path_out) shall be freed using nex_free(). + * @params_out: Output console parameters found from the DTB. + * (*params_out) shall be freed using nex_free(). + * + * Return a TEE_Result compliant return value + * + */ +TEE_Result get_console_node_from_dt(void *fdt, int *offs_out, + char **path_out, char **params_out); + +/* + * Check if the /secure-chosen or /chosen node in the DT contains an + * stdout-path value for which we have a compatible driver. If so, switch + * the console to this device. + */ +void configure_console_from_dt(void); +#else +static inline void configure_console_from_dt(void) +{} +#endif /* !CFG_DT */ + +#endif /* CONSOLE_H */ + diff --git a/optee/optee_os/core/include/crypto/crypto.h b/optee/optee_os/core/include/crypto/crypto.h new file mode 100644 index 0000000..e9c0eaf --- /dev/null +++ b/optee/optee_os/core/include/crypto/crypto.h @@ -0,0 +1,417 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2017, Linaro Limited + */ + +/* + * This is the Cryptographic Provider API (CP API). + * + * This defines how most crypto syscalls that implement the Cryptographic + * Operations API can invoke the actual providers of cryptographic algorithms + * (such as LibTomCrypt). + * + * To add a new provider, you need to provide an implementation of this + * interface. + * + * The following parameters are commonly used. + * + * @ctx: context allocated by the syscall, for later use by the algorithm + * @algo: algorithm identifier (TEE_ALG_*) + */ + +#ifndef __CRYPTO_CRYPTO_H +#define __CRYPTO_CRYPTO_H + +#include +#include + +TEE_Result crypto_init(void); + +/* Message digest functions */ +TEE_Result crypto_hash_alloc_ctx(void **ctx, uint32_t algo); +TEE_Result crypto_hash_init(void *ctx); +TEE_Result crypto_hash_update(void *ctx, const uint8_t *data, size_t len); +TEE_Result crypto_hash_final(void *ctx, uint8_t *digest, size_t len); +void crypto_hash_free_ctx(void *ctx); +void crypto_hash_copy_state(void *dst_ctx, void *src_ctx); + +/* Symmetric ciphers */ +TEE_Result crypto_cipher_alloc_ctx(void **ctx, uint32_t algo); +TEE_Result crypto_cipher_init(void *ctx, 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 crypto_cipher_update(void *ctx, TEE_OperationMode mode, + bool last_block, const uint8_t *data, + size_t len, uint8_t *dst); +void crypto_cipher_final(void *ctx); +TEE_Result crypto_cipher_get_block_size(uint32_t algo, size_t *size); +void crypto_cipher_free_ctx(void *ctx); +void crypto_cipher_copy_state(void *dst_ctx, void *src_ctx); + +/* Message Authentication Code functions */ +TEE_Result crypto_mac_alloc_ctx(void **ctx, uint32_t algo); +TEE_Result crypto_mac_init(void *ctx, const uint8_t *key, size_t len); +TEE_Result crypto_mac_update(void *ctx, const uint8_t *data, size_t len); +TEE_Result crypto_mac_final(void *ctx, uint8_t *digest, size_t digest_len); +void crypto_mac_free_ctx(void *ctx); +void crypto_mac_copy_state(void *dst_ctx, void *src_ctx); + +/* Authenticated encryption */ +TEE_Result crypto_authenc_alloc_ctx(void **ctx, uint32_t algo); +TEE_Result crypto_authenc_init(void *ctx, 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 crypto_authenc_update_aad(void *ctx, TEE_OperationMode mode, + const uint8_t *data, size_t len); +TEE_Result crypto_authenc_update_payload(void *ctx, TEE_OperationMode mode, + const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + size_t *dst_len); +TEE_Result crypto_authenc_enc_final(void *ctx, const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + size_t *dst_len, uint8_t *dst_tag, + size_t *dst_tag_len); +TEE_Result crypto_authenc_dec_final(void *ctx, const uint8_t *src_data, + size_t src_len, uint8_t *dst_data, + size_t *dst_len, const uint8_t *tag, + size_t tag_len); +void crypto_authenc_final(void *ctx); +void crypto_authenc_free_ctx(void *ctx); +void crypto_authenc_copy_state(void *dst_ctx, void *src_ctx); + +/* Informs crypto that the data in the buffer will be removed from storage */ +TEE_Result crypto_storage_obj_del(struct tee_obj *obj); + +/* Implementation-defined big numbers */ + +/* + * Allocate a bignum capable of holding an unsigned integer value of + * up to bitsize bits + */ +struct bignum *crypto_bignum_allocate(size_t size_bits); +TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize, + struct bignum *to); +size_t crypto_bignum_num_bytes(struct bignum *a); +size_t crypto_bignum_num_bits(struct bignum *a); +void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to); +void crypto_bignum_copy(struct bignum *to, const struct bignum *from); +void crypto_bignum_free(struct bignum *a); +void crypto_bignum_clear(struct bignum *a); + +/* return -1 if ab */ +int32_t crypto_bignum_compare(struct bignum *a, struct bignum *b); + +/* Asymmetric algorithms */ + +struct rsa_keypair { + struct bignum *e; /* Public exponent */ + struct bignum *d; /* Private exponent */ + struct bignum *n; /* Modulus */ + + /* Optional CRT parameters (all NULL if unused) */ + struct bignum *p; /* N = pq */ + struct bignum *q; + struct bignum *qp; /* 1/q mod p */ + struct bignum *dp; /* d mod (p-1) */ + struct bignum *dq; /* d mod (q-1) */ +}; + +struct rsa_public_key { + struct bignum *e; /* Public exponent */ + struct bignum *n; /* Modulus */ +}; + +struct dsa_keypair { + struct bignum *g; /* Generator of subgroup (public) */ + struct bignum *p; /* Prime number (public) */ + struct bignum *q; /* Order of subgroup (public) */ + struct bignum *y; /* Public key */ + struct bignum *x; /* Private key */ +}; + +struct dsa_public_key { + struct bignum *g; /* Generator of subgroup (public) */ + struct bignum *p; /* Prime number (public) */ + struct bignum *q; /* Order of subgroup (public) */ + struct bignum *y; /* Public key */ +}; + +struct dh_keypair { + struct bignum *g; /* Generator of Z_p (shared) */ + struct bignum *p; /* Prime modulus (shared) */ + struct bignum *x; /* Private key */ + struct bignum *y; /* Public key y = g^x */ + + /* + * Optional parameters used by key generation. + * When not used, q == NULL and xbits == 0 + */ + struct bignum *q; /* x must be in the range [2, q-2] */ + uint32_t xbits; /* Number of bits in the private key */ +}; + +struct ecc_public_key { + struct bignum *x; /* Public value x */ + struct bignum *y; /* Public value y */ + uint32_t curve; /* Curve type */ + const struct crypto_ecc_public_ops *ops; /* Key Operations */ +}; + +struct ecc_keypair { + struct bignum *d; /* Private value */ + struct bignum *x; /* Public value x */ + struct bignum *y; /* Public value y */ + uint32_t curve; /* Curve type */ + const struct crypto_ecc_keypair_ops *ops; /* Key Operations */ +}; + +struct x25519_keypair { + uint8_t *priv; /* Private value */ + uint8_t *pub; /* Public value */ +}; + +struct ed25519_keypair { + uint8_t *priv; + uint8_t *pub; + uint32_t curve; +}; + +struct ed25519_public_key { + uint8_t *pub; + uint32_t curve; +}; + +/* + * Key allocation functions + * Allocate the bignum's inside a key structure. + * TEE core will later use crypto_bignum_free(). + */ +TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, + size_t key_size_bits); +TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, + size_t key_size_bits); +void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s); +void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s); +TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s, + size_t key_size_bits); +TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s, + size_t key_size_bits); +TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s, + size_t key_size_bits); +TEE_Result crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *s, + uint32_t key_type, + size_t key_size_bits); +TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *s, + uint32_t key_type, + size_t key_size_bits); +void crypto_acipher_free_ecc_public_key(struct ecc_public_key *s); +TEE_Result crypto_acipher_alloc_x25519_keypair(struct x25519_keypair *s, + size_t key_size_bits); +TEE_Result crypto_acipher_alloc_ed25519_keypair(struct ed25519_keypair *s, + size_t key_size_bits); +TEE_Result +crypto_acipher_alloc_ed25519_public_key(struct ed25519_public_key *key, + size_t key_size); + +/* + * Key generation functions + */ +TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size); +TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size); +TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q, + size_t xbits, size_t key_size); +TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key, size_t key_size); +TEE_Result crypto_acipher_gen_x25519_key(struct x25519_keypair *key, + size_t key_size); +TEE_Result crypto_acipher_gen_ed25519_key(struct ed25519_keypair *key, + size_t key_size); +TEE_Result crypto_acipher_ed25519_sign(struct ed25519_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len); +TEE_Result crypto_acipher_ed25519ctx_sign(struct ed25519_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len, + bool ph_flag, + const uint8_t *ctx, size_t ctxlen); +TEE_Result crypto_acipher_ed25519_verify(struct ed25519_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len); +TEE_Result crypto_acipher_ed25519ctx_verify(struct ed25519_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len, + bool ph_flag, + const uint8_t *ctx, size_t ctxlen); + +TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, + struct bignum *public_key, + struct bignum *secret); + +TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len); +TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len); +TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *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 crypto_acipher_rsaes_encrypt(uint32_t algo, + struct rsa_public_key *key, + const uint8_t *label, size_t label_len, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len); +/* RSA SSA sign/verify: if salt_len == -1, use default value */ +TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, + int salt_len, const uint8_t *msg, + size_t msg_len, uint8_t *sig, + size_t *sig_len); +TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, + struct rsa_public_key *key, + int salt_len, const uint8_t *msg, + size_t msg_len, const uint8_t *sig, + size_t sig_len); +TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len); +TEE_Result crypto_acipher_dsa_verify(uint32_t algo, struct dsa_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len); +TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len); +TEE_Result crypto_acipher_ecc_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len); +TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, + unsigned long *secret_len); +TEE_Result crypto_acipher_sm2_pke_decrypt(struct ecc_keypair *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len); +TEE_Result crypto_acipher_sm2_pke_encrypt(struct ecc_public_key *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len); +TEE_Result crypto_acipher_x25519_shared_secret(struct x25519_keypair + *private_key, + void *public_key, void *secret, + unsigned long *secret_len); + +struct sm2_kep_parms { + uint8_t *out; + size_t out_len; + bool is_initiator; + const uint8_t *initiator_id; + size_t initiator_id_len; + const uint8_t *responder_id; + size_t responder_id_len; + const uint8_t *conf_in; + size_t conf_in_len; + uint8_t *conf_out; + size_t conf_out_len; +}; + +TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key, + struct ecc_keypair *my_eph_key, + struct ecc_public_key *peer_key, + struct ecc_public_key *peer_eph_key, + struct sm2_kep_parms *p); + +/* + * Verifies a SHA-256 hash, doesn't require crypto_init() to be called in + * advance and has as few dependencies as possible. + * + * This function is primarily used by pager and early initialization code + * where the complete crypto library isn't available. + */ +TEE_Result hash_sha256_check(const uint8_t *hash, const uint8_t *data, + size_t data_size); + +/* + * Computes a SHA-512/256 hash, vetted conditioner as per NIST.SP.800-90B. + * It doesn't require crypto_init() to be called in advance and has as few + * dependencies as possible. + * + * This function could be used inside interrupt context where the crypto + * library can't be used due to mutex handling. + */ +TEE_Result hash_sha512_256_compute(uint8_t *digest, const uint8_t *data, + size_t data_size); + +#define CRYPTO_RNG_SRC_IS_QUICK(sid) (!!((sid) & 1)) + +/* + * enum crypto_rng_src - RNG entropy source + * + * Identifiers for different RNG entropy sources. The lowest bit indicates + * if the source is to be merely queued (bit is 1) or if it's delivered + * directly to the pool. The difference is that in the latter case RPC to + * normal world can be performed and in the former it must not. + */ +enum crypto_rng_src { + CRYPTO_RNG_SRC_JITTER_SESSION = (0 << 1 | 0), + CRYPTO_RNG_SRC_JITTER_RPC = (1 << 1 | 1), + CRYPTO_RNG_SRC_NONSECURE = (1 << 1 | 0), +}; + +/* + * crypto_rng_init() - initialize the RNG + * @data: buffer with initial seed + * @dlen: length of @data + */ +TEE_Result crypto_rng_init(const void *data, size_t dlen); + +/* + * crypto_rng_add_event() - supply entropy to RNG from a source + * @sid: Source identifier, should be unique for a specific source + * @pnum: Pool number, acquired using crypto_rng_get_next_pool_num() + * @data: Data associated with the event + * @dlen: Length of @data + * + * @sid controls whether the event is merly queued in a ring buffer or if + * it's added to one of the pools directly. If CRYPTO_RNG_SRC_IS_QUICK() is + * true (lowest bit set) events are queue otherwise added to corresponding + * pool. If CRYPTO_RNG_SRC_IS_QUICK() is false, eventual queued events are + * added to their queues too. + */ +void crypto_rng_add_event(enum crypto_rng_src sid, unsigned int *pnum, + const void *data, size_t dlen); + +/* + * crypto_rng_read() - read cryptograhically secure RNG + * @buf: Buffer to hold the data + * @len: Length of buffer. + * + * Eventual queued events are also added to their pools during this + * function call. + */ +TEE_Result crypto_rng_read(void *buf, size_t len); + +/* + * crypto_aes_expand_enc_key() - Expand an AES key + * @key: AES key buffer + * @key_len: Size of the @key buffer in bytes + * @enc_key: Expanded AES encryption key buffer + * @enc_keylen: Size of the @enc_key buffer in bytes + * @rounds: Number of rounds to be used during encryption + */ +TEE_Result crypto_aes_expand_enc_key(const void *key, size_t key_len, + void *enc_key, size_t enc_keylen, + unsigned int *rounds); + +/* + * crypto_aes_enc_block() - Encrypt an AES block + * @enc_key: Expanded AES encryption key + * @enc_keylen: Size of @enc_key in bytes + * @rounds: Number of rounds + * @src: Source buffer of one AES block (16 bytes) + * @dst: Destination buffer of one AES block (16 bytes) + */ +void crypto_aes_enc_block(const void *enc_key, size_t enc_keylen, + unsigned int rounds, const void *src, void *dst); + +#endif /* __CRYPTO_CRYPTO_H */ diff --git a/optee/optee_os/core/include/crypto/crypto_accel.h b/optee/optee_os/core/include/crypto/crypto_accel.h new file mode 100644 index 0000000..c6a043f --- /dev/null +++ b/optee/optee_os/core/include/crypto/crypto_accel.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020-2023, Linaro Limited + */ + +#ifndef __CRYPTO_CRYPTO_ACCEL_H +#define __CRYPTO_CRYPTO_ACCEL_H + +#include + +TEE_Result crypto_accel_aes_expand_keys(const void *key, size_t key_len, + void *enc_key, void *dec_key, + size_t expanded_key_len, + unsigned int *round_count); + +void crypto_accel_aes_ecb_enc(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count); +void crypto_accel_aes_ecb_dec(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count); + +void crypto_accel_aes_cbc_enc(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count, void *iv); +void crypto_accel_aes_cbc_dec(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count, void *iv); + +void crypto_accel_aes_ctr_be_enc(void *out, const void *in, const void *key, + unsigned int round_count, + unsigned int block_count, void *iv); + +void crypto_accel_aes_xts_enc(void *out, const void *in, const void *key1, + unsigned int round_count, + unsigned int block_count, const void *key2, + void *tweak); +void crypto_accel_aes_xts_dec(void *out, const void *in, const void *key1, + unsigned int round_count, + unsigned int block_count, const void *key2, + void *tweak); + +void crypto_accel_sha1_compress(uint32_t state[5], const void *src, + unsigned int block_count); +void crypto_accel_sha256_compress(uint32_t state[8], const void *src, + unsigned int block_count); +void crypto_accel_sha512_compress(uint64_t state[8], const void *src, + unsigned int block_count); +void crypto_accel_sha3_compress(uint64_t state[25], const void *src, + unsigned int block_count, + unsigned int digest_size); +void crypto_accel_sm3_compress(uint32_t state[8], const void *src, + unsigned int block_count); + +void crypto_accel_sm4_setkey_enc(uint32_t sk[32], const uint8_t key[16]); +void crypto_accel_sm4_setkey_dec(uint32_t sk[32], const uint8_t key[16]); +void crypto_accel_sm4_ecb_enc(void *out, const void *in, const void *key, + unsigned int len); +void crypto_accel_sm4_cbc_enc(void *out, const void *in, const void *key, + unsigned int len, void *iv); +void crypto_accel_sm4_cbc_dec(void *out, const void *in, const void *key, + unsigned int len, void *iv); +void crypto_accel_sm4_ctr_enc(void *out, const void *in, const void *key, + unsigned int len, void *iv); +void crypto_accel_sm4_xts_enc(void *out, const void *in, const void *key1, + const void *key2, unsigned int len, void *iv); +void crypto_accel_sm4_xts_dec(void *out, const void *in, const void *key1, + const void *key2, unsigned int len, void *iv); + +#endif /*__CRYPTO_CRYPTO_ACCEL_H*/ diff --git a/optee/optee_os/core/include/crypto/crypto_impl.h b/optee/optee_os/core/include/crypto/crypto_impl.h new file mode 100644 index 0000000..ccff72c --- /dev/null +++ b/optee/optee_os/core/include/crypto/crypto_impl.h @@ -0,0 +1,556 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2021, SumUp Services GmbH + */ + +#ifndef __CRYPTO_CRYPTO_IMPL_H +#define __CRYPTO_CRYPTO_IMPL_H + +#include +#include + +/* + * The crypto context used by the crypto_hash_*() functions is defined by + * struct crypto_hash_ctx. + */ +struct crypto_hash_ctx { + const struct crypto_hash_ops *ops; +}; + +struct crypto_hash_ops { + TEE_Result (*init)(struct crypto_hash_ctx *ctx); + TEE_Result (*update)(struct crypto_hash_ctx *ctx, const uint8_t *data, + size_t len); + TEE_Result (*final)(struct crypto_hash_ctx *ctx, uint8_t *digest, + size_t len); + void (*free_ctx)(struct crypto_hash_ctx *ctx); + void (*copy_state)(struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx); +}; + +#define CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(name, type) \ + static inline TEE_Result \ + crypto_##name##_alloc_ctx(struct crypto_##type##_ctx **ctx __unused) \ + { return TEE_ERROR_NOT_IMPLEMENTED; } + +#if defined(CFG_CRYPTO_MD5) +TEE_Result crypto_md5_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(md5, hash) +#endif + +#if defined(CFG_CRYPTO_SHA1) +TEE_Result crypto_sha1_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha1, hash) +#endif + +#if defined(CFG_CRYPTO_SHA224) +TEE_Result crypto_sha224_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha224, hash) +#endif + +#if defined(CFG_CRYPTO_SHA256) +TEE_Result crypto_sha256_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha256, hash) +#endif + +#if defined(CFG_CRYPTO_SHA384) +TEE_Result crypto_sha384_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha384, hash) +#endif + +#if defined(CFG_CRYPTO_SHA512) +TEE_Result crypto_sha512_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha512, hash) +#endif + +#if defined(CFG_CRYPTO_SM3) +TEE_Result crypto_sm3_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm3, hash) +#endif + +#if defined(CFG_CRYPTO_SHA3_224) +TEE_Result crypto_sha3_224_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha3_224, hash) +#endif + +#if defined(CFG_CRYPTO_SHA3_256) +TEE_Result crypto_sha3_256_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha3_256, hash) +#endif + +#if defined(CFG_CRYPTO_SHA3_384) +TEE_Result crypto_sha3_384_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha3_384, hash) +#endif + +#if defined(CFG_CRYPTO_SHA3_512) +TEE_Result crypto_sha3_512_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha3_512, hash) +#endif + +#if defined(CFG_CRYPTO_SHAKE128) +TEE_Result crypto_shake128_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(shake128, hash) +#endif + +#if defined(CFG_CRYPTO_SHAKE256) +TEE_Result crypto_shake256_alloc_ctx(struct crypto_hash_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(shake256, hash) +#endif + +/* + * The crypto context used by the crypto_mac_*() functions is defined by + * struct crypto_mac_ctx. + */ +struct crypto_mac_ctx { + const struct crypto_mac_ops *ops; +}; + +struct crypto_mac_ops { + TEE_Result (*init)(struct crypto_mac_ctx *ctx, const uint8_t *key, + size_t len); + TEE_Result (*update)(struct crypto_mac_ctx *ctx, const uint8_t *data, + size_t len); + TEE_Result (*final)(struct crypto_mac_ctx *ctx, uint8_t *digest, + size_t len); + void (*free_ctx)(struct crypto_mac_ctx *ctx); + void (*copy_state)(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx); +}; + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_MD5) +TEE_Result crypto_hmac_md5_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_md5, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA1) +TEE_Result crypto_hmac_sha1_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha1, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA224) +TEE_Result crypto_hmac_sha224_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha224, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA256) +TEE_Result crypto_hmac_sha256_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha256, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA384) +TEE_Result crypto_hmac_sha384_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha384, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA512) +TEE_Result crypto_hmac_sha512_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha512, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA3_224) +TEE_Result crypto_hmac_sha3_224_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha3_224, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA3_256) +TEE_Result crypto_hmac_sha3_256_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha3_256, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA3_384) +TEE_Result crypto_hmac_sha3_384_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha3_384, mac) +#endif + +#if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA3_512) +TEE_Result crypto_hmac_sha3_512_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha3_512, mac) +#endif + +#if defined(CFG_CRYPTO_SM3) && defined(CFG_CRYPTO_HMAC) +TEE_Result crypto_hmac_sm3_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sm3, mac) +#endif + +#if defined(CFG_CRYPTO_CBC_MAC) +TEE_Result crypto_aes_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx); +TEE_Result crypto_aes_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx); +TEE_Result crypto_des_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx); +TEE_Result crypto_des_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx); +TEE_Result crypto_des3_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx); +TEE_Result crypto_des3_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cbc_mac_nopad, mac) +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cbc_mac_pkcs5, mac) +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_cbc_mac_nopad, mac) +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_cbc_mac_pkcs5, mac) +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cbc_mac_nopad, mac) +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cbc_mac_pkcs5, mac) +#endif + +#if defined(CFG_CRYPTO_CMAC) +TEE_Result crypto_aes_cmac_alloc_ctx(struct crypto_mac_ctx **ctx); +TEE_Result crypto_des3_cmac_alloc_ctx(struct crypto_mac_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cmac, mac) +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cmac, mac) +#endif + +/* + * The crypto context used by the crypto_cipher_*() functions is defined by + * struct crypto_cipher_ctx. + */ +struct crypto_cipher_ctx { + const struct crypto_cipher_ops *ops; +}; + +struct crypto_cipher_ops { + TEE_Result (*init)(struct crypto_cipher_ctx *ctx, + 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 (*update)(struct crypto_cipher_ctx *ctx, bool last_block, + const uint8_t *data, size_t len, uint8_t *dst); + void (*final)(struct crypto_cipher_ctx *ctx); + + void (*free_ctx)(struct crypto_cipher_ctx *ctx); + void (*copy_state)(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx); +}; + +#if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_ECB) +TEE_Result crypto_aes_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_ecb, cipher) +#endif + +#if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_CBC) +TEE_Result crypto_aes_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cbc, cipher) +#endif + +#if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_CTR) +TEE_Result crypto_aes_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_ctr, cipher) +#endif + +#if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_CTS) +TEE_Result crypto_aes_cts_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cts, cipher) +#endif + +#if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_XTS) +TEE_Result crypto_aes_xts_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_xts, cipher) +#endif + +#if defined(CFG_CRYPTO_DES) && defined(CFG_CRYPTO_ECB) +TEE_Result crypto_des_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx); +TEE_Result crypto_des3_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_ecb, cipher) +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_ecb, cipher) +#endif + +#if defined(CFG_CRYPTO_DES) && defined(CFG_CRYPTO_CBC) +TEE_Result crypto_des_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); +TEE_Result crypto_des3_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_cbc, cipher) +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cbc, cipher) +#endif + +#if defined(CFG_CRYPTO_SM4) && defined(CFG_CRYPTO_ECB) +TEE_Result crypto_sm4_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm4_ecb, cipher) +#endif + +#if defined(CFG_CRYPTO_SM4) && defined(CFG_CRYPTO_CBC) +TEE_Result crypto_sm4_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm4_cbc, cipher) +#endif + +#if defined(CFG_CRYPTO_SM4) && defined(CFG_CRYPTO_CTR) +TEE_Result crypto_sm4_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm4_ctr, cipher) +#endif + +#if defined(CFG_CRYPTO_SM4) && defined(CFG_CRYPTO_XTS) +TEE_Result crypto_sm4_xts_alloc_ctx(struct crypto_cipher_ctx **ctx); +#else +CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm4_xts, cipher) +#endif + +/* + * The crypto context used by the crypto_authen_*() functions below is + * defined by struct crypto_authenc_ctx. + */ +struct crypto_authenc_ctx { + const struct crypto_authenc_ops *ops; +}; + +struct crypto_authenc_ops { + TEE_Result (*init)(struct crypto_authenc_ctx *ctx, + 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 (*update_aad)(struct crypto_authenc_ctx *ctx, + const uint8_t *data, size_t len); + TEE_Result (*update_payload)(struct crypto_authenc_ctx *ctx, + TEE_OperationMode mode, + const uint8_t *src_data, size_t len, + uint8_t *dst_data); + TEE_Result (*enc_final)(struct crypto_authenc_ctx *ctx, + const uint8_t *src_data, size_t len, + uint8_t *dst_data, uint8_t *dst_tag, + size_t *dst_tag_len); + TEE_Result (*dec_final)(struct crypto_authenc_ctx *ctx, + const uint8_t *src_data, size_t len, + uint8_t *dst_data, const uint8_t *tag, + size_t tag_len); + void (*final)(struct crypto_authenc_ctx *ctx); + void (*free_ctx)(struct crypto_authenc_ctx *ctx); + void (*copy_state)(struct crypto_authenc_ctx *dst_ctx, + struct crypto_authenc_ctx *src_ctx); +}; + +TEE_Result crypto_aes_ccm_alloc_ctx(struct crypto_authenc_ctx **ctx); +TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx); + +#ifdef CFG_CRYPTO_DRV_HASH +TEE_Result drvcrypt_hash_alloc_ctx(struct crypto_hash_ctx **ctx, uint32_t algo); +#else +static inline TEE_Result +drvcrypt_hash_alloc_ctx(struct crypto_hash_ctx **ctx __unused, + uint32_t algo __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /* CFG_CRYPTO_DRV_HASH */ + +#ifdef CFG_CRYPTO_DRV_CIPHER +TEE_Result drvcrypt_cipher_alloc_ctx(struct crypto_cipher_ctx **ctx, + uint32_t algo); +#else +static inline TEE_Result +drvcrypt_cipher_alloc_ctx(struct crypto_cipher_ctx **ctx __unused, + uint32_t algo __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /* CFG_CRYPTO_DRV_CIPHER */ + +#ifdef CFG_CRYPTO_DRV_MAC +/* Cryptographic MAC driver context allocation */ +TEE_Result drvcrypt_mac_alloc_ctx(struct crypto_mac_ctx **ctx, uint32_t algo); +#else +static inline TEE_Result +drvcrypt_mac_alloc_ctx(struct crypto_mac_ctx **ctx __unused, + uint32_t algo __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /* CFG_CRYPTO_DRV_MAC */ + +#ifdef CFG_CRYPTO_DRV_AUTHENC +/* Cryptographic Authenticated Encryption driver context allocation */ +TEE_Result drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx **ctx, + uint32_t algo); +#else +static inline TEE_Result +drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx **ctx __unused, + uint32_t algo __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /* CFG_CRYPTO_DRV_AUTHENC */ +/* + * The ECC public key operations used by the crypto_acipher_ecc_*() and + * crypto_acipher_free_ecc_*() functions. + * Reference set in ecc_public_key when key allocated. + * + * @free is mandatory + * @verify is optional + * @encrypt is optional + */ +struct crypto_ecc_public_ops { + void (*free)(struct ecc_public_key *key); + TEE_Result (*verify)(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len); + TEE_Result (*encrypt)(struct ecc_public_key *key, const uint8_t *src, + size_t src_len, uint8_t *dst, size_t *dst_len); +}; + +/* + * The ECC keypair operations used by the crypto_acipher_ecc_*() and + * crypto_acipher_gen_ecc_*() functions. + * Reference set in ecc_keypair when key allocated. + * + * @generate is mandatory + * @sign is optional + * @shared_secret is optional + * @decrypt is optional + */ +struct crypto_ecc_keypair_ops { + TEE_Result (*generate)(struct ecc_keypair *key, size_t key_size_bits); + TEE_Result (*sign)(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, uint8_t *sig, + size_t *sig_len); + TEE_Result (*shared_secret)(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, unsigned long *secret_len); + TEE_Result (*decrypt)(struct ecc_keypair *key, const uint8_t *src, + size_t src_len, uint8_t *dst, size_t *dst_len); +}; + +#ifdef CFG_CRYPTO_ECC +const struct crypto_ecc_keypair_ops * +crypto_asym_get_ecc_keypair_ops(uint32_t key_type); + +const struct crypto_ecc_public_ops * +crypto_asym_get_ecc_public_ops(uint32_t key_type); + +TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *key, + uint32_t key_type, + size_t key_size_bits); +TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *key, + uint32_t key_type, + size_t key_size_bits); +#else +static inline TEE_Result +crypto_asym_alloc_ecc_public_key(struct ecc_public_key *key __unused, + uint32_t key_type __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline const struct crypto_ecc_keypair_ops * +crypto_asym_get_keypair_ops(uint32_t key_type __unused) +{ + return NULL; +} + +static inline const struct crypto_ecc_public_ops * +crypto_asym_get_ecc_public_ops(uint32_t key_type __unused) +{ + return NULL; +} + +static inline TEE_Result +crypto_asym_alloc_ecc_keypair(struct ecc_keypair *key __unused, + uint32_t key_type __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /* CFG_CRYPTO_ECC */ + +#ifdef CFG_CRYPTO_DRV_ECC +TEE_Result drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key *key, + uint32_t key_type, + size_t key_size_bits); +TEE_Result drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair *key, + uint32_t key_type, + size_t key_size_bits); +#else +static inline TEE_Result +drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key *key __unused, + uint32_t key_type __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline TEE_Result +drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair *key __unused, + uint32_t key_type __unused, + size_t key_size_bits __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif /* CFG_CRYPTO_DRV_ECC */ + +TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, + size_t key_size_bits); + +TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, + size_t key_size_bits); + +void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s); + +void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s); + +TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key, + size_t key_size); + +TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len); +TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len); +TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo, + struct rsa_keypair *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 sw_crypto_acipher_rsaes_encrypt(uint32_t algo, + struct rsa_public_key *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 sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, + int salt_len, const uint8_t *msg, + size_t msg_len, uint8_t *sig, + size_t *sig_len); + +TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo, + struct rsa_public_key *key, + int salt_len, const uint8_t *msg, + size_t msg_len, const uint8_t *sig, + size_t sig_len); +#endif /*__CRYPTO_CRYPTO_IMPL_H*/ diff --git a/optee/optee_os/core/include/crypto/crypto_se.h b/optee/optee_os/core/include/crypto/crypto_se.h new file mode 100644 index 0000000..eb7452f --- /dev/null +++ b/optee/optee_os/core/include/crypto/crypto_se.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2021 - All Rights Reserved + * Author: Jorge Ramirez + */ + /* + * This is the Cryptographic Secure Element API, part of the Cryptographic + * Provider API. + * + * These requests shall be handled in the secure element normally placed on + * a serial communication bus (SPI, I2C). + */ +#ifndef __CRYPTO_SE_H +#define __CRYPTO_SE_H + +#include + +/* + * Type identifier for the APDU message as described by Smart Card Standard + * ISO7816-4 about ADPU message bodies decoding convention: + * + * https://cardwerk.com/smart-card-standard-iso7816-4-section-5-basic-organizations/#chap5_3_2 + */ +enum crypto_apdu_type { + CRYPTO_APDU_CASE_NO_HINT, + CRYPTO_APDU_CASE_1, + CRYPTO_APDU_CASE_2, + CRYPTO_APDU_CASE_2E, + CRYPTO_APDU_CASE_3, + CRYPTO_APDU_CASE_3E, + CRYPTO_APDU_CASE_4, + CRYPTO_APDU_CASE_4E, +}; + +TEE_Result crypto_se_do_apdu(enum crypto_apdu_type type, + uint8_t *header, size_t hdr_len, + uint8_t *src_data, size_t src_len, + uint8_t *dst_data, size_t *dst_len); + +/* + * Enable Secure Channel Protocol 03 to communicate with the Secure Element. + * + * Since SCP03 uses symmetric encryption, this interface also allows the user to + * attempt the rotation the keys stored in the Secure Element. + * + * https://globalplatform.org/wp-content/uploads/2014/07/GPC_2.3_D_SCP03_v1.1.2_PublicRelease.pdf + */ +TEE_Result crypto_se_enable_scp03(bool rotate_keys); +#endif diff --git a/optee/optee_os/core/include/crypto/internal_aes-gcm.h b/optee/optee_os/core/include/crypto/internal_aes-gcm.h new file mode 100644 index 0000000..d8e8ec9 --- /dev/null +++ b/optee/optee_os/core/include/crypto/internal_aes-gcm.h @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + * + */ + +#ifndef __CRYPTO_INTERNAL_AES_GCM_H +#define __CRYPTO_INTERNAL_AES_GCM_H + +#include +#include +#include +#include + +#ifdef CFG_CRYPTO_WITH_CE +#include +#else +struct internal_ghash_key { +#ifdef CFG_AES_GCM_TABLE_BASED + uint64_t HL[16]; + uint64_t HH[16]; +#else + uint64_t hash_subkey[2]; +#endif +}; +#endif + +struct internal_aes_gcm_key { + /* AES (CTR) encryption key and number of rounds */ + uint64_t data[30]; + unsigned int rounds; +}; + +struct internal_aes_gcm_state { + uint64_t ctr[2]; + + struct internal_ghash_key ghash_key; + uint8_t hash_state[TEE_AES_BLOCK_SIZE]; + + uint8_t buf_tag[TEE_AES_BLOCK_SIZE]; + uint8_t buf_hash[TEE_AES_BLOCK_SIZE]; + uint8_t buf_cryp[TEE_AES_BLOCK_SIZE]; + + unsigned int tag_len; + unsigned int aad_bytes; + unsigned int payload_bytes; + unsigned int buf_pos; +}; + +struct internal_aes_gcm_ctx { + struct internal_aes_gcm_state state; + struct internal_aes_gcm_key key; +}; + +TEE_Result internal_aes_gcm_init(struct internal_aes_gcm_ctx *ctx, + TEE_OperationMode mode, const void *key, + size_t key_len, const void *nonce, + size_t nonce_len, size_t tag_len); +TEE_Result internal_aes_gcm_update_aad(struct internal_aes_gcm_ctx *ctx, + const void *data, size_t len); +TEE_Result internal_aes_gcm_update_payload(struct internal_aes_gcm_ctx *ctx, + TEE_OperationMode mode, + const void *src, size_t len, + void *dst); +TEE_Result internal_aes_gcm_enc_final(struct internal_aes_gcm_ctx *ctx, + const void *src, size_t len, void *dst, + void *tag, size_t *tag_len); +TEE_Result internal_aes_gcm_dec_final(struct internal_aes_gcm_ctx *ctx, + const void *src, size_t len, void *dst, + const void *tag, size_t tag_len); + +void internal_aes_gcm_inc_ctr(struct internal_aes_gcm_state *state); +void internal_aes_gcm_dec_ctr(struct internal_aes_gcm_state *state); + +TEE_Result internal_aes_gcm_enc(const struct internal_aes_gcm_key *enc_key, + const void *nonce, size_t nonce_len, + const void *aad, size_t aad_len, + const void *src, size_t len, void *dst, + void *tag, size_t *tag_len); + +TEE_Result internal_aes_gcm_dec(const struct internal_aes_gcm_key *enc_key, + const void *nonce, size_t nonce_len, + const void *aad, size_t aad_len, + const void *src, size_t len, void *dst, + const void *tag, size_t tag_len); + +void internal_aes_gcm_gfmul(const uint64_t X[2], const uint64_t Y[2], + uint64_t product[2]); + +static inline void internal_aes_gcm_xor_block(void *dst, const void *src) +{ + uint64_t *d = dst; + const uint64_t *s = src; + + assert(IS_ALIGNED_WITH_TYPE(dst, uint64_t)); + assert(IS_ALIGNED_WITH_TYPE(src, uint64_t)); + + d[0] ^= s[0]; + d[1] ^= s[1]; +} + +static inline bool internal_aes_gcm_ptr_is_block_aligned(const void *p) +{ + return !((vaddr_t)p & (TEE_AES_BLOCK_SIZE - 1)); +} + +#ifdef CFG_AES_GCM_TABLE_BASED +void internal_aes_gcm_ghash_gen_tbl(struct internal_ghash_key *ghash_key, + const struct internal_aes_gcm_key *enc_key); +void internal_aes_gcm_ghash_mult_tbl(struct internal_ghash_key *ghash_key, + const unsigned char x[16], + unsigned char output[16]); +#endif + +/* + * Must be implemented in core/arch/arm/crypto/ if CFG_CRYPTO_WITH_CE=y + */ +void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *enc_key); + +void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state, + const void *head, const void *data, + size_t num_blocks); +/* + * Internal weak function that can be overridden with hardware specific + * implementation. + */ +void +internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, + const struct internal_aes_gcm_key *ek, + TEE_OperationMode mode, const void *src, + size_t num_blocks, void *dst); + +#endif /*__CRYPTO_INTERNAL_AES_GCM_H*/ diff --git a/optee/optee_os/core/include/crypto/sm2-kdf.h b/optee/optee_os/core/include/crypto/sm2-kdf.h new file mode 100644 index 0000000..5a012c0 --- /dev/null +++ b/optee/optee_os/core/include/crypto/sm2-kdf.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020-2021, Huawei Technologies Co., Ltd + */ + +#ifndef CRYPTO_SM2_KDF_H +#define CRYPTO_SM2_KDF_H + +#include +#include + +TEE_Result sm2_kdf(const uint8_t *Z, size_t Z_len, uint8_t *t, size_t tlen); +#endif /* CRYPTO_SM2_KDF_H */ diff --git a/optee/optee_os/core/include/drivers/amlogic_uart.h b/optee/optee_os/core/include/drivers/amlogic_uart.h new file mode 100644 index 0000000..97b55f2 --- /dev/null +++ b/optee/optee_os/core/include/drivers/amlogic_uart.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +#ifndef AMLOGIC_UART_H +#define AMLOGIC_UART_H + +#include +#include + +struct amlogic_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void amlogic_uart_init(struct amlogic_uart_data *pd, paddr_t base); + +#endif /* AMLOGIC_UART_H */ diff --git a/optee/optee_os/core/include/drivers/atmel_rstc.h b/optee/optee_os/core/include/drivers/atmel_rstc.h new file mode 100644 index 0000000..6561d0b --- /dev/null +++ b/optee/optee_os/core/include/drivers/atmel_rstc.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Microchip + */ +#ifndef __DRIVERS_ATMEL_RSTC_H +#define __DRIVERS_ATMEL_RSTC_H + +#include +#include + +#if defined(CFG_ATMEL_RSTC) +bool atmel_rstc_available(void); + +void __noreturn atmel_rstc_reset(void); +#else +static inline bool atmel_rstc_available(void) +{ + return false; +} + +static inline void atmel_rstc_reset(void) {} +#endif + +#endif /* __DRIVERS_ATMEL_RSTC_H */ diff --git a/optee/optee_os/core/include/drivers/atmel_rtc.h b/optee/optee_os/core/include/drivers/atmel_rtc.h new file mode 100644 index 0000000..ad52186 --- /dev/null +++ b/optee/optee_os/core/include/drivers/atmel_rtc.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Microchip + */ + +#ifndef __DRIVERS_ATMEL_RTC_H +#define __DRIVERS_ATMEL_RTC_H + +#include +#include + +#ifdef CFG_ATMEL_RTC +TEE_Result atmel_rtc_get_tamper_timestamp(struct optee_rtc_time *tm); +#else +static inline +TEE_Result atmel_rtc_get_tamper_timestamp(struct optee_rtc_time *tm __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +#endif /* __DRIVERS_ATMEL_RTC_H */ diff --git a/optee/optee_os/core/include/drivers/atmel_saic.h b/optee/optee_os/core/include/drivers/atmel_saic.h new file mode 100644 index 0000000..3998ad9 --- /dev/null +++ b/optee/optee_os/core/include/drivers/atmel_saic.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Microchip + */ + +#ifndef __DRIVERS_ATMEL_SAIC_H +#define __DRIVERS_ATMEL_SAIC_H + +#include +#include + +#define AT91_AIC_WPKEY 0x414943 + +#define AT91_AIC_SSR 0x0 +#define AT91_AIC_SSR_ITSEL_MASK GENMASK_32(6, 0) + +#define AT91_AIC_SMR 0x4 +#define AT91_AIC_SMR_SRC_SHIFT 5 +#define AT91_AIC_SMR_LEVEL SHIFT_U32(0, AT91_AIC_SMR_SRC_SHIFT) +#define AT91_AIC_SMR_NEG_EDGE SHIFT_U32(1, AT91_AIC_SMR_SRC_SHIFT) +#define AT91_AIC_SMR_HIGH_LEVEL SHIFT_U32(2, AT91_AIC_SMR_SRC_SHIFT) +#define AT91_AIC_SMR_POS_EDGE SHIFT_U32(3, AT91_AIC_SMR_SRC_SHIFT) + +#define AT91_AIC_SVR 0x8 +#define AT91_AIC_IVR 0x10 +#define AT91_AIC_ISR 0x18 + +#define AT91_AIC_IPR0 0x20 +#define AT91_AIC_IPR1 0x24 +#define AT91_AIC_IPR2 0x28 +#define AT91_AIC_IPR3 0x2c +#define AT91_AIC_IMR 0x30 +#define AT91_AIC_CISR 0x34 +#define AT91_AIC_EOICR 0x38 +#define AT91_AIC_SPU 0x3c +#define AT91_AIC_IECR 0x40 +#define AT91_AIC_IDCR 0x44 +#define AT91_AIC_ICCR 0x48 +#define AT91_AIC_ISCR 0x4c +#define AT91_AIC_DCR 0x6c +#define AT91_AIC_WPMR 0xe4 +#define AT91_AIC_WPSR 0xe8 + +void atmel_saic_it_handle(void); + +TEE_Result atmel_saic_setup(void); + +#endif /*__DRIVERS_ATMEL_SAIC_H*/ diff --git a/optee/optee_os/core/include/drivers/atmel_shdwc.h b/optee/optee_os/core/include/drivers/atmel_shdwc.h new file mode 100644 index 0000000..fbc7ead --- /dev/null +++ b/optee/optee_os/core/include/drivers/atmel_shdwc.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015 Atmel Corporation, + * Nicolas Ferre + * Copyright (c) 2021, Microchip + */ + +#ifndef __DRIVERS_ATMEL_SHDWC_H +#define __DRIVERS_ATMEL_SHDWC_H + +#include +#include +#include +#include + +/* Shut Down Control Register */ +#define AT91_SHDW_CR 0x00 +/* Shut Down command */ +#define AT91_SHDW_SHDW BIT(0) +/* KEY Password */ +#define AT91_SHDW_KEY SHIFT_U32(0xa5UL, 24) + +/* Shut Down Mode Register */ +#define AT91_SHDW_MR 0x04 +#define AT91_SHDW_WKUPDBC_SHIFT 24 +#define AT91_SHDW_WKUPDBC_MASK GENMASK_32(26, 24) +#define AT91_SHDW_WKUPDBC(x) (SHIFT_U32((x), AT91_SHDW_WKUPDBC_SHIFT) & \ + AT91_SHDW_WKUPDBC_MASK) +#define AT91_SHDW_RTCWKEN BIT32(17) + +/* Shut Down Status Register */ +#define AT91_SHDW_SR 0x08 +#define AT91_SHDW_WKUPIS_SHIFT 16 +#define AT91_SHDW_WKUPIS_MASK GENMASK_32(31, 16) +#define AT91_SHDW_WKUPIS(x) (BIT32((x) + AT91_SHDW_WKUPIS_SHIFT)) + +/* Shutdown Wake-up Inputs Register */ +#define AT91_SHDW_WUIR 0x0c +#define AT91_SHDW_WKUPEN_MASK GENMASK_32(15, 0) +#define AT91_SHDW_WKUPEN(x) (BIT32(x) & AT91_SHDW_WKUPEN_MASK) +#define AT91_SHDW_WKUPT_SHIFT 16 +#define AT91_SHDW_WKUPT_MASK GENMASK_32(31, 16) +#define AT91_SHDW_WKUPT(x) (BIT32((x) + AT91_SHDW_WKUPT_SHIFT)) + +#ifndef __ASSEMBLER__ +#if defined(CFG_ATMEL_SHDWC) + +void __atmel_shdwc_shutdown(uint32_t mpddrc_base, uint32_t shdwc_base, + uint32_t pmc_base); + +bool atmel_shdwc_available(void); + +void __noreturn atmel_shdwc_shutdown(void); +#else +static inline bool atmel_shdwc_available(void) +{ + return false; +} + +static inline void atmel_shdwc_shutdown(void) {} +#endif /* defined(CFG_ATMEL_SHDWC) */ +#endif /* __ASSEMBLER__*/ + +#endif /* __DRIVERS_ATMEL_SHDWC_H */ diff --git a/optee/optee_os/core/include/drivers/atmel_uart.h b/optee/optee_os/core/include/drivers/atmel_uart.h new file mode 100644 index 0000000..aa5563f --- /dev/null +++ b/optee/optee_os/core/include/drivers/atmel_uart.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Timesys Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 ATMEL_UART_H +#define ATMEL_UART_H + +#include +#include + +struct atmel_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void atmel_uart_init(struct atmel_uart_data *pd, paddr_t base); + +#endif /* ATMEL_UART_H */ diff --git a/optee/optee_os/core/include/drivers/bcm/bnxt.h b/optee/optee_os/core/include/drivers/bcm/bnxt.h new file mode 100644 index 0000000..7136c7e --- /dev/null +++ b/optee/optee_os/core/include/drivers/bcm/bnxt.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef BNXT_H +#define BNXT_H + +#include +#include +#include +#include + +#define BNXT_SUCCESS 0 +#define BNXT_FAILURE (!BNXT_SUCCESS) + +uint32_t bnxt_write32_multiple(uintptr_t dst, + uintptr_t src, + uint32_t num_entries, + int src_4byte_increment); +void bnxt_handshake_clear(void); +void bnxt_chimp_halt(void); +void bnxt_kong_halt(void); +int bnxt_fastboot(uintptr_t addr); +uint32_t bnxt_wait_handshake(uint32_t timeout); +uint32_t bnxt_health_status(void); +TEE_Result bnxt_load_fw(int chip_type); +TEE_Result bnxt_copy_crash_dump(uint8_t *d, uint32_t offset, uint32_t len); + +struct bnxt_images_info { + vaddr_t bnxt_fw_vaddr; + uint32_t bnxt_fw_len; + vaddr_t bnxt_cfg_vaddr; + uint32_t bnxt_cfg_len; + vaddr_t bnxt_bspd_cfg_vaddr; + uint32_t bnxt_bspd_cfg_len; +}; + +/* Reserve 1K for BSPD data */ +#define BNXT_IMG_SECMEM_OFFSET 0x400 + +int get_bnxt_images_info(struct bnxt_images_info *bnxt_info, + int chip_type, vaddr_t ddr_dest); + +#endif diff --git a/optee/optee_os/core/include/drivers/bcm_gpio.h b/optee/optee_os/core/include/drivers/bcm_gpio.h new file mode 100644 index 0000000..12de82b --- /dev/null +++ b/optee/optee_os/core/include/drivers/bcm_gpio.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef BCM_GPIO_H +#define BCM_GPIO_H + +#include +#include +#include + +/** + * struct bcm_gpio_chip describes GPIO controller chip instance + * @chip: generic GPIO chip handle. + * @gpio_base: starting GPIO number managed by this GPIO controller. + * @ngpios: number of GPIOs managed by this GPIO controller. + * @base: virtual base address of the GPIO controller registers. + */ +struct bcm_gpio_chip { + struct gpio_chip chip; + unsigned int gpio_base; + unsigned int ngpios; + vaddr_t base; + + SLIST_ENTRY(bcm_gpio_chip) link; +}; + +/* Returns bcm_gpio_chip handle for a GPIO pin */ +struct bcm_gpio_chip *bcm_gpio_pin_to_chip(unsigned int pin); +/* Set gpiopin as secure */ +void iproc_gpio_set_secure(int gpiopin); +#endif /* BCM_GPIO_H */ diff --git a/optee/optee_os/core/include/drivers/bcm_hwrng.h b/optee/optee_os/core/include/drivers/bcm_hwrng.h new file mode 100644 index 0000000..abf213d --- /dev/null +++ b/optee/optee_os/core/include/drivers/bcm_hwrng.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef BCM_HWRNG_H +#define BCM_HWRNG_H + +#include + +uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read); + +#endif /* BCM_HWRNG_H */ diff --git a/optee/optee_os/core/include/drivers/bcm_sotp.h b/optee/optee_os/core/include/drivers/bcm_sotp.h new file mode 100644 index 0000000..2476004 --- /dev/null +++ b/optee/optee_os/core/include/drivers/bcm_sotp.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef BCM_SOTP_H +#define BCM_SOTP_H + +#include +#include + +#define SOTP_ECC_ERR_DETECT BIT64(63) + +/** + * Reads from sotp fuse at given row address. + * @row_addr: row address + * @sotp_add_ecc: ecc memory support flag + * @rdata: pointer to sotp data value + * @returns TEE_Result value + */ +TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, bool sotp_add_ecc, + uint64_t *rdata); + +/** + * Writes to sotp fuse at given row address. + * @row_addr: row address + * @sotp_add_ecc: ecc memory support flag + * @wdata: data to be written to sotp fuse + * @returns TEE_Result value + */ +TEE_Result bcm_iproc_sotp_mem_write(uint32_t row_addr, bool sotp_add_ecc, + uint64_t wdata); + +#endif diff --git a/optee/optee_os/core/include/drivers/caam_extension.h b/optee/optee_os/core/include/drivers/caam_extension.h new file mode 100644 index 0000000..5bc7bed --- /dev/null +++ b/optee/optee_os/core/include/drivers/caam_extension.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2023 NXP + */ +#ifndef __DRIVERS_CAAM_EXTENSION_H__ +#define __DRIVERS_CAAM_EXTENSION_H__ + +#include +#include +#include + +#ifdef CFG_NXP_CAAM_MP_DRV +/* + * Export the MPMR content. + * We assume that it is filled with message given in parameter. + * It contains 32 registers of 8 bits (32 bytes). + * + * @mpmr [out] MPMR buffer read + * @size [in/out] MPMR buffer size exported + */ +TEE_Result caam_mp_export_mpmr(uint8_t *mpmr, size_t *size); + +/* + * Export the Manufacturing Protection Public Key. + * + * @pubkey [out] Public key read + * @size [in/out] Public key size exported + */ +TEE_Result caam_mp_export_publickey(uint8_t *pubkey, size_t *size); + +/* + * MPSign function. + * This function takes the value in the MPMR if it exists + * and concatenates any additional data (certificate). + * The signature over the message is done with the private key. + * + * @data [in] Data to sign + * @data_size [in] Data size to sign + * @sig [out] Signature + * @sig_size [in/out] Signature size + */ +TEE_Result caam_mp_sign(uint8_t *data, size_t *data_size, uint8_t *sig, + size_t *sig_size); +#endif /* CFG_NXP_CAAM_MP_DRV */ +#endif /* __CAAM_EXTENSION_H__ */ diff --git a/optee/optee_os/core/include/drivers/cbmem_console.h b/optee/optee_os/core/include/drivers/cbmem_console.h new file mode 100644 index 0000000..c8234d3 --- /dev/null +++ b/optee/optee_os/core/include/drivers/cbmem_console.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023, Google Limited + */ +#ifndef DRIVERS_CBMEM_CONSOLE_H +#define DRIVERS_CBMEM_CONSOLE_H + +#include + +bool cbmem_console_init_from_dt(void *fdt); + +#endif /* DRIVERS_CBMEM_CONSOLE_H */ + diff --git a/optee/optee_os/core/include/drivers/cdns_uart.h b/optee/optee_os/core/include/drivers/cdns_uart.h new file mode 100644 index 0000000..19516ff --- /dev/null +++ b/optee/optee_os/core/include/drivers/cdns_uart.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Xilinx Inc + * Copyright (c) 2017, 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 CDNS_UART_H +#define CDNS_UART_H + +#include +#include + +struct cdns_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk, + uint32_t baud_rate); + +#endif /* CDNS_UART_H */ diff --git a/optee/optee_os/core/include/drivers/clk.h b/optee/optee_os/core/include/drivers/clk.h new file mode 100644 index 0000000..13cc9fa --- /dev/null +++ b/optee/optee_os/core/include/drivers/clk.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Bootlin + */ + +#ifndef __DRIVERS_CLK_H +#define __DRIVERS_CLK_H + +#include +#include +#include + +/* Flags for clock */ +#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */ +#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */ + +/** + * struct clk - Clock structure + * + * @name: Clock name + * @priv: Private data for the clock provider + * @ops: Clock operations + * @parent: Current parent + * @rate: Current clock rate (cached after init or rate change) + * @flags: Specific clock flags + * @enabled_count: Enable/disable reference counter + * @num_parents: Number of parents + * @parents: Array of possible parents of the clock + */ +struct clk { + const char *name; + void *priv; + const struct clk_ops *ops; + struct clk *parent; + unsigned long rate; + unsigned int flags; + struct refcount enabled_count; + size_t num_parents; + struct clk *parents[]; +}; + +/** + * struct clk_ops + * + * @enable: Enable the clock + * @disable: Disable the clock + * @set_parent: Set the clock parent based on index + * @get_parent: Get the current parent index of the clock + * @set_rate: Set the clock rate + * @get_rate: Get the clock rate + * @get_rates_array: Get the supported clock rates as array + */ +struct clk_ops { + TEE_Result (*enable)(struct clk *clk); + void (*disable)(struct clk *clk); + TEE_Result (*set_parent)(struct clk *clk, size_t index); + size_t (*get_parent)(struct clk *clk); + TEE_Result (*set_rate)(struct clk *clk, unsigned long rate, + unsigned long parent_rate); + unsigned long (*get_rate)(struct clk *clk, + unsigned long parent_rate); + TEE_Result (*get_rates_array)(struct clk *clk, size_t start_index, + unsigned long *rates, size_t *nb_elts); +}; + +/** + * Return the clock name + * + * @clk: Clock for which the name is needed + * Return a const char * pointing to the clock name + */ +static inline const char *clk_get_name(struct clk *clk) +{ + return clk->name; +} + +/** + * clk_alloc - Allocate a clock structure + * + * @name: Clock name + * @ops: Clock operations + * @parent_clks: Parents of the clock + * @parent_count: Number of parents of the clock + * + * Return a clock struct properly initialized or NULL if allocation failed + */ +struct clk *clk_alloc(const char *name, const struct clk_ops *ops, + struct clk **parent_clks, size_t parent_count); + +/** + * clk_free - Free a clock structure + * + * @clk: Clock to be freed or NULL + */ +void clk_free(struct clk *clk); + +/** + * clk_register - Register a clock within the clock framework + * + * @clk: Clock struct to be registered + * Return a TEE_Result compliant value + */ +TEE_Result clk_register(struct clk *clk); + +/** + * clk_get_rate - Get clock rate + * + * @clk: Clock for which the rate is needed + * Return the clock rate in Hz + */ +unsigned long clk_get_rate(struct clk *clk); + +/** + * clk_set_rate - Set a clock rate + * + * @clk: Clock to be set with the rate + * @rate: Rate to set in Hz + * Return a TEE_Result compliant value + */ +TEE_Result clk_set_rate(struct clk *clk, unsigned long rate); + +/** + * clk_enable - Enable a clock and its ascendance + * + * @clk: Clock to be enabled + * Return a TEE_Result compliant value + */ +TEE_Result clk_enable(struct clk *clk); + +/** + * clk_disable - Disable a clock + * + * @clk: Clock to be disabled + */ +void clk_disable(struct clk *clk); + +/** + * clk_is_enabled - Informative state on the clock + * + * This function is useful during specific system sequences where core + * executes atomically (primary core boot, some low power sequences). + * + * @clk: Clock refernece + */ +bool clk_is_enabled(struct clk *clk); + +/** + * clk_get_parent - Get the current clock parent + * + * @clk: Clock for which the parent is needed + * Return the clock parent or NULL if there is no parent + */ +struct clk *clk_get_parent(struct clk *clk); + +/** + * clk_get_num_parents - Get the number of parents for a clock + * + * @clk: Clock for which the number of parents is needed + * Return the number of parents + */ +static inline size_t clk_get_num_parents(struct clk *clk) +{ + return clk->num_parents; +} + +/** + * Get a clock parent by its index + * + * @clk: Clock for which the parent is needed + * @pidx: Parent index for the clock + * Return the clock parent at index @pidx or NULL if out of bound + */ +struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx); + +/** + * clk_set_parent - Set the current clock parent + * + * @clk: Clock for which the parent should be set + * @parent: Parent clock to set + * Return a TEE_Result compliant value + */ +TEE_Result clk_set_parent(struct clk *clk, struct clk *parent); + +/** + * clk_get_rates_array - Get supported rates as an array + * + * @clk: Clock for which the rates are requested + * @start_index: start index of requested rates + * @rates: Array of rates allocated by caller or NULL to query count of rates + * @nb_elts: Max number of elements that the array can hold as input. Contains + * the number of elements that was added in the array as output. + * Returns a TEE_Result compliant value + */ +TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index, + unsigned long *rates, size_t *nb_elts); + +#endif /* __DRIVERS_CLK_H */ diff --git a/optee/optee_os/core/include/drivers/clk_dt.h b/optee/optee_os/core/include/drivers/clk_dt.h new file mode 100644 index 0000000..018a112 --- /dev/null +++ b/optee/optee_os/core/include/drivers/clk_dt.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Bootlin + */ + +#ifndef __DRIVERS_CLK_DT_H +#define __DRIVERS_CLK_DT_H + +#include +#include +#include +#include + +/** + * CLK_DT_DECLARE - Declare a clock driver + * @__name: Clock driver name + * @__compat: Compatible string + * @__probe: Clock probe function + */ +#define CLK_DT_DECLARE(__name, __compat, __probe) \ + static const struct dt_device_match __name ## _match_table[] = { \ + { .compatible = __compat }, \ + { } \ + }; \ + DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ + .name = # __name, \ + .type = DT_DRIVER_CLK, \ + .match_table = __name ## _match_table, \ + .probe = __probe, \ + } + +/** + * clk_dt_get_by_index - Get a clock at a specific index in "clocks" property + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the subnode containing a clock property + * @clk_idx: Clock index to get + * @clk: Output clock reference upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not provide a clock reference + * Return any other TEE_Result compliant code in case of error + */ +TEE_Result clk_dt_get_by_index(const void *fdt, int nodeoffset, + unsigned int clk_idx, struct clk **clk); + +/** + * clk_dt_get_by_name - Get a clock matching a name in "clock-names" property + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the subnode containing a clock property + * @name: Clock name to get + * @clk: Output clock reference upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not provide a clock reference + * Return any other TEE_Result compliant code in case of error + */ +TEE_Result clk_dt_get_by_name(const void *fdt, int nodeoffset, + const char *name, struct clk **clk); + +/** + * clk_dt_get_func - Typedef of function to get clock from devicetree properties + * + * @args: Pointer to devicetree description of the clock to parse + * @data: Pointer to data given at clk_dt_register_clk_provider() call + * @res: Output result code of the operation: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized + * Any TEE_Result compliant code in case of error. + * + * Returns a clk struct pointer pointing to a clock matching the devicetree + * description or NULL if invalid description in which case @res provides the + * error code. + */ +typedef struct clk *(*clk_dt_get_func)(struct dt_driver_phandle_args *args, + void *data, TEE_Result *res); + +/** + * clk_dt_register_clk_provider - Register a clock provider + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the clock + * @get_dt_clk: Callback to match the devicetree clock with a clock struct + * @data: Data which will be passed to the get_dt_clk callback + * Returns TEE_Result value + */ +static inline +TEE_Result clk_dt_register_clk_provider(const void *fdt, int nodeoffset, + clk_dt_get_func get_dt_clk, void *data) +{ + return dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)get_dt_clk, + data, DT_DRIVER_CLK); +} + +/** + * clk_dt_get_simple_clk: simple clock matching function for single clock + * providers + */ +static inline +struct clk *clk_dt_get_simple_clk(struct dt_driver_phandle_args *args __unused, + void *data, TEE_Result *res) +{ + *res = TEE_SUCCESS; + + return data; +} + +#endif /* __DRIVERS_CLK_DT_H */ diff --git a/optee/optee_os/core/include/drivers/gic.h b/optee/optee_os/core/include/drivers/gic.h new file mode 100644 index 0000000..05748b2 --- /dev/null +++ b/optee/optee_os/core/include/drivers/gic.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef __DRIVERS_GIC_H +#define __DRIVERS_GIC_H +#include +#include + +#if defined(CFG_ARM_GICV3) +#define GIC_DIST_REG_SIZE 0x10000 +#define GIC_CPU_REG_SIZE 0x10000 +#else +#define GIC_DIST_REG_SIZE 0x1000 +#define GIC_CPU_REG_SIZE 0x1000 +#endif + +#define GIC_PPI_BASE U(16) +#define GIC_SPI_BASE U(32) + +#define GIC_SGI_TO_ITNUM(x) (x) +#define GIC_PPI_TO_ITNUM(x) ((x) + GIC_PPI_BASE) +#define GIC_SPI_TO_ITNUM(x) ((x) + GIC_SPI_BASE) + +struct gic_data { + vaddr_t gicc_base; + vaddr_t gicd_base; + size_t max_it; + struct itr_chip chip; +}; + +/* + * The two gic_init_* functions initializes the struct gic_data which is + * then used by the other functions. + */ + +void gic_init(struct gic_data *gd, paddr_t gicc_base_pa, paddr_t gicd_base_pa); +/* initial base address only */ +void gic_init_base_addr(struct gic_data *gd, paddr_t gicc_base_pa, + paddr_t gicd_base_pa); +/* initial cpu if only, mainly use for secondary cpu setup cpu interface */ +void gic_cpu_init(struct gic_data *gd); + +void gic_it_handle(struct gic_data *gd); + +void gic_dump_state(struct gic_data *gd); +#endif /*__DRIVERS_GIC_H*/ diff --git a/optee/optee_os/core/include/drivers/hfic.h b/optee/optee_os/core/include/drivers/hfic.h new file mode 100644 index 0000000..2ee3782 --- /dev/null +++ b/optee/optee_os/core/include/drivers/hfic.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef __DRIVERS_HFIC_H +#define __DRIVERS_HFIC_H +#include + +struct hfic_data { + struct itr_chip chip; +}; + +void hfic_init(struct hfic_data *hd); +void hfic_it_handle(struct hfic_data *hd); + +#endif /*__DRIVERS_HFIC_H*/ diff --git a/optee/optee_os/core/include/drivers/hi16xx_uart.h b/optee/optee_os/core/include/drivers/hi16xx_uart.h new file mode 100644 index 0000000..83413fc --- /dev/null +++ b/optee/optee_os/core/include/drivers/hi16xx_uart.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +/* + * UART driver for Hisilicon Hi16xx and Phosphor V660 (hip05) SoCs + */ + +#ifndef HI16XX_UART_H +#define HI16XX_UART_H + +#include +#include + +#define HI16XX_UART_REG_SIZE 0xF8 + +struct hi16xx_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base, + uint32_t uart_clk, uint32_t baud_rate); + +#endif /* HI16XX_UART_H */ diff --git a/optee/optee_os/core/include/drivers/i2c.h b/optee/optee_os/core/include/drivers/i2c.h new file mode 100644 index 0000000..32d0915 --- /dev/null +++ b/optee/optee_os/core/include/drivers/i2c.h @@ -0,0 +1,348 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Microchip + */ + +#ifndef __DRIVERS_I2C_H +#define __DRIVERS_I2C_H + +#include +#include +#include + +/** + * DEFINE_I2C_DEV_DRIVER - Declare an I2C driver + * + * @__name: I2C device driver name + * @__match_table: match table associated to the driver + * @__i2c_probe: I2C probe function with the following prototype: + * TEE_Result (*probe)(struct i2c_dev *i2c_dev, const void *fdt, + * int node, const void *compat_data); + */ +#define DEFINE_I2C_DEV_DRIVER(__name, __match_table, __i2c_probe) \ + static TEE_Result __name ## _probe_i2c_dev(const void *fdt, int node, \ + const void *compat_data) \ + { \ + struct i2c_dev *i2c_dev = NULL; \ + TEE_Result res = TEE_ERROR_GENERIC; \ + \ + res = i2c_dt_get_dev(fdt, node, &i2c_dev); \ + if (res) \ + return res; \ + return __i2c_probe(i2c_dev, fdt, node, compat_data); \ + } \ + DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ + .name = # __name, \ + .type = DT_DRIVER_I2C, \ + .match_table = __match_table, \ + .probe = __name ## _probe_i2c_dev, \ + } + +#define I2C_SMBUS_MAX_BUF_SIZE 32 + +enum i2c_smbus_dir { + I2C_SMBUS_READ, + I2C_SMBUS_WRITE, +}; + +enum i2c_smbus_protocol { + I2C_SMBUS_PROTO_BYTE, + /* + * Like block but does not insert "count" in sent data, useful for + * EEPROM read for instance which is not SMBus but requires such + * sequence. + */ + I2C_SMBUS_PROTO_BLOCK_RAW, +}; + +struct i2c_ctrl; + +/** + * struct i2c_dev - I2C device + * + * @ctrl: I2C controller associated to the device + * @addr: device address on the I2C bus + */ +struct i2c_dev { + struct i2c_ctrl *ctrl; + uint16_t addr; +}; + +/** + * struct i2c_ctrl_ops - Operations provided by I2C controller drivers + * + * @read: I2C read operation + * @write: I2C write operation + * @smbus: SMBus protocol operation + */ +struct i2c_ctrl_ops { + TEE_Result (*read)(struct i2c_dev *i2c_dev, uint8_t *buf, size_t len); + TEE_Result (*write)(struct i2c_dev *i2c_dev, const uint8_t *buf, + size_t len); + TEE_Result (*smbus)(struct i2c_dev *i2c_dev, enum i2c_smbus_dir dir, + enum i2c_smbus_protocol proto, uint8_t cmd_code, + uint8_t *buf, size_t len); +}; + +/** + * struct i2c_ctrl - I2C controller + * + * @ops: Operations associated to the I2C controller + */ +struct i2c_ctrl { + const struct i2c_ctrl_ops *ops; +}; + +#ifdef CFG_DRIVERS_I2C +/** + * i2c_create_dev - Create and i2c_dev struct from device-tree + * + * @i2c_ctrl: Controller to be used with this device + * @fdt: Device-tree to work on + * @node: Node to work on in @fdt provided device-tree + * + * Return an i2c_dev struct filled from device-tree description + */ +struct i2c_dev *i2c_create_dev(struct i2c_ctrl *i2c_ctrl, const void *fdt, + int node); + +/** + * i2c_write() - Execute an I2C write on the I2C bus + * + * @i2c_dev: I2C device used for writing + * @buf: Buffer of data to be written + * @len: Length of data to be written + * + * Return a TEE_Result compliant value + */ +static inline TEE_Result i2c_write(struct i2c_dev *i2c_dev, const uint8_t *buf, + size_t len) +{ + if (!i2c_dev->ctrl->ops->write) + return TEE_ERROR_NOT_SUPPORTED; + + return i2c_dev->ctrl->ops->write(i2c_dev, buf, len); +} + +/** + * i2c_read() - Execute an I2C read on the I2C bus + * + * @i2c_dev: I2C device used for reading + * @buf: Buffer containing the read data + * @len: Length of data to be read + * + * Return a TEE_Result compliant value + */ +static inline TEE_Result i2c_read(struct i2c_dev *i2c_dev, uint8_t *buf, + size_t len) +{ + if (!i2c_dev->ctrl->ops->read) + return TEE_ERROR_NOT_SUPPORTED; + + return i2c_dev->ctrl->ops->read(i2c_dev, buf, len); +} + +/** + * i2c_smbus_raw() - Execute a raw SMBUS request + * + * @i2c_dev: I2C device used for SMBus operation + * @dir: Direction for the SMBus transfer + * @proto: SMBus Protocol to be executed + * @cmd_code: Command code + * @buf: Buffer used for read/write operation + * @len: Length of buffer to be read/write + * + * Return a TEE_Result compliant value + */ +static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev, + enum i2c_smbus_dir dir, + enum i2c_smbus_protocol proto, + uint8_t cmd_code, uint8_t *buf, + size_t len) +{ + if (!i2c_dev->ctrl->ops->smbus) + return TEE_ERROR_NOT_SUPPORTED; + + if (len > I2C_SMBUS_MAX_BUF_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + return i2c_dev->ctrl->ops->smbus(i2c_dev, dir, proto, cmd_code, buf, + len); +} + +/** + * i2c_dt_get_dev - Get an I2C device from a DT node + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the I2C bus consumer + * @i2c_dev: Output I2C bus device upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if I2C controller is not initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the I2C controller node does not exist + * Return a TEE_Result compliant code in case of error + */ +static inline TEE_Result i2c_dt_get_dev(const void *fdt, int nodeoffset, + struct i2c_dev **i2c_dev) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + *i2c_dev = dt_driver_device_from_parent(fdt, nodeoffset, DT_DRIVER_I2C, + &res); + return res; +} +#else +static inline TEE_Result i2c_write(struct i2c_dev *i2c_dev __unused, + const uint8_t *buf __unused, + size_t len __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result i2c_read(struct i2c_dev *i2c_dev __unused, + uint8_t *buf __unused, size_t len __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev __unused, + enum i2c_smbus_dir dir __unused, + enum i2c_smbus_protocol proto __unused, + uint8_t cmd_code __unused, + uint8_t *buf __unused, + size_t len __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result i2c_dt_get_dev(const void *fdt __unused, + int nodeoffset __unused, + struct i2c_dev **i2c_dev) +{ + *i2c_dev = NULL; + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +/** + * i2c_dt_get_func - Typedef of function to get I2C bus device from + * devicetree properties + * + * @a: Pointer to devicetree description of the I2C bus device to parse + * @data: Pointer to data given at i2c_dt_register_provider() call + * @res: Output result code of the operation: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if I2C controller is not initialized + * Any TEE_Result compliant code in case of error. + * + * Returns a struct i2c pointer pointing to a I2C bus device matching + * the devicetree description or NULL if invalid description in which case + * @res provides the error code. + */ +typedef struct i2c_dev *(*i2c_dt_get_func)(struct dt_driver_phandle_args *a, + void *data, TEE_Result *res); + +/** + * i2c_dt_register_provider - Register a I2C controller provider and add all the + * child nodes of this controller in the DT probe list. + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the I2C controller + * @get_dt_i2c: Callback to match the I2C controller with a struct i2c + * @data: Data which will be passed to the get_dt_i2c callback + * Returns TEE_Result value + */ +static inline +TEE_Result i2c_register_provider(const void *fdt, int nodeoffset, + i2c_dt_get_func get_dt_i2c, void *data) +{ + int subnode = -1; + TEE_Result res = TEE_ERROR_GENERIC; + + res = dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)get_dt_i2c, + data, DT_DRIVER_I2C); + if (res) + return res; + + fdt_for_each_subnode(subnode, fdt, nodeoffset) + dt_driver_maybe_add_probe_node(fdt, subnode); + + return TEE_SUCCESS; +} + +/** + * i2c_smbus_read_byte_data() - Execute a read byte SMBus protocol operation + * + * @i2c_dev: I2C device used for SMBus operation + * @cmd_code: Command code to read + * @byte: Returned byte value read from device + * + * Return a TEE_Result compliant value + */ +static inline TEE_Result i2c_smbus_read_byte_data(struct i2c_dev *i2c_dev, + uint8_t cmd_code, + uint8_t *byte) +{ + return i2c_smbus_raw(i2c_dev, I2C_SMBUS_READ, I2C_SMBUS_PROTO_BYTE, + cmd_code, byte, 1); +} + +/** + * i2c_smbus_write_byte_data() - Execute a write byte SMBus protocol operation + * + * @i2c_dev: I2C device used for SMBus operation + * @cmd_code: Command code for write operation + * @byte: Byte to be written to the device + * + * Return a TEE_Result compliant value + */ +static inline TEE_Result i2c_smbus_write_byte_data(struct i2c_dev *i2c_dev, + uint8_t cmd_code, + uint8_t byte) +{ + return i2c_smbus_raw(i2c_dev, I2C_SMBUS_WRITE, I2C_SMBUS_PROTO_BYTE, + cmd_code, &byte, 1); +} + +/** + * i2c_bus_read_block_raw() - Execute a non-standard SMBus raw block read. + * This does not insert the "count" of byte to be written unlike the SMBus block + * read operation. + * + * @i2c_dev: I2C device used for SMBus operation + * @cmd_code: Command code for read operation + * @buf: Buffer of data read from device + * @len: Length of data to be read from the device + * + * Return a TEE_Result compliant value + */ +static inline TEE_Result i2c_bus_read_block_raw(struct i2c_dev *i2c_dev, + uint8_t cmd_code, uint8_t *buf, + size_t len) +{ + return i2c_smbus_raw(i2c_dev, I2C_SMBUS_READ, I2C_SMBUS_PROTO_BLOCK_RAW, + cmd_code, buf, len); +} + +/** + * i2c_bus_write_block_raw() - Execute a non-standard SMBus raw block write. + * This does not insert the "count" of byte to be written unlike the SMBus block + * write operation. + * + * @i2c_dev: I2C device used for SMBus operation + * @cmd_code: Command code for write operation + * @buf: Buffer of data to be written to the device + * @len: Length of data to be written to the device + * + * Return a TEE_Result compliant value + */ +static inline TEE_Result i2c_bus_write_block_raw(struct i2c_dev *i2c_dev, + uint8_t cmd_code, + uint8_t *buf, size_t len) +{ + return i2c_smbus_raw(i2c_dev, I2C_SMBUS_WRITE, + I2C_SMBUS_PROTO_BLOCK_RAW, cmd_code, buf, len); +} + +#endif diff --git a/optee/optee_os/core/include/drivers/imx/dcp.h b/optee/optee_os/core/include/drivers/imx/dcp.h new file mode 100644 index 0000000..a01ae30 --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx/dcp.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020 NXP + */ +#ifndef __IMX_DCP_H__ +#define __IMX_DCP_H__ + +#include +#include +#include +#include + +#define DCP_SHA_BLOCK_SIZE U(64) +#define DCP_AES128_BLOCK_SIZE U(16) +#define DCP_AES128_KEY_SIZE DCP_AES128_BLOCK_SIZE +#define DCP_AES128_IV_SIZE DCP_AES128_BLOCK_SIZE + +enum dcp_key_mode { + DCP_SRAM0 = 0, + DCP_SRAM1, + DCP_SRAM2, + DCP_SRAM3, + DCP_PAYLOAD, + DCP_OTP, +}; + +enum dcp_aes_mode { + DCP_ECB = 0, + DCP_CBC, +}; + +enum dcp_aes_op { + DCP_ENCRYPT = 0, + DCP_DECRYPT, +}; + +enum dcp_hash_config { + DCP_SHA1 = 0, + DCP_SHA256, +}; + +enum dcp_channel { + DCP_CHANN0 = 0, + DCP_CHANN1, + DCP_CHANN2, + DCP_CHANN3, + DCP_NB_CHANNELS, +}; + +/* DCP work packet descriptor is a hardware data structure */ +struct dcp_descriptor { + uint32_t next; + uint32_t ctrl0; + uint32_t ctrl1; + /* Source buffer physical address */ + uint32_t src_buffer; + /* Destination buffer physical address */ + uint32_t dest_buffer; + uint32_t buff_size; + /* Payload buffer physical address */ + uint32_t payload; + uint32_t status; +}; + +struct dcp_align_buf { + uint8_t *data; + paddr_t paddr; + size_t size; +}; + +struct dcp_data { + struct dcp_descriptor desc; + enum dcp_channel channel; +}; + +struct dcp_hash_data { + struct dcp_data dcp_data; + bool initialized; + enum dcp_hash_config alg; + struct dcp_align_buf ctx; + size_t ctx_size; +}; + +struct dcp_hashalg { + unsigned int type; + unsigned int size; +}; + +struct dcp_cipher_data { + struct dcp_data dcp_data; + bool initialized; + uint8_t iv[DCP_AES128_IV_SIZE]; + uint8_t key[DCP_AES128_KEY_SIZE]; + /* payload buffer holds the key and the iv */ + struct dcp_align_buf payload; + size_t payload_size; +}; + +struct dcp_cipher_init { + enum dcp_aes_op op; + enum dcp_aes_mode mode; + enum dcp_key_mode key_mode; + uint8_t *key; + uint8_t *iv; +}; + +/* + * Perform AES-CMAC operation + * + * @init Cipher operation context + * @input Input message + * @input_size Input message size + * @output Output MAC + */ +TEE_Result dcp_cmac(struct dcp_cipher_init *init, uint8_t *input, + size_t input_size, uint8_t *output); + +/* + * Store key in the SRAM + * + * @key Buffer containing the key to store (128 bit) + * @index Index of the key (0, 1, 2 or 3) + */ +TEE_Result dcp_store_key(uint32_t *key, unsigned int index); + +/* + * Initialize AES-128 operation + * + * @data Cipher operation context + * @init Data for aesdata initialization + */ +TEE_Result dcp_cipher_do_init(struct dcp_cipher_data *data, + struct dcp_cipher_init *init); + +/* + * Update AES-128 operation + * + * @data Cipher operation context + * @src Source data to encrypt/decrypt + * @dst [out] Destination buffer + * @size Size of source data in bytes, must be 16 bytes multiple + */ +TEE_Result dcp_cipher_do_update(struct dcp_cipher_data *data, + const uint8_t *src, uint8_t *dst, size_t size); + +/* + * Finalize AES-128 operation + * + * @data Cipher operation context + */ +void dcp_cipher_do_final(struct dcp_cipher_data *data); + +/* + * Initialize hash operation + * + * @hashdata Hash operation context + */ +TEE_Result dcp_sha_do_init(struct dcp_hash_data *hashdata); + +/* + * Update hash operation + * + * @hashdata Hash operation context + * @data Buffer to hash + * @len Size of the input buffer in bytes + */ +TEE_Result dcp_sha_do_update(struct dcp_hash_data *hashdata, + const uint8_t *data, size_t len); + +/* + * Finalize the hash operation + * + * @hashdata Hash operation context + * @digest [out] Result of the hash operation + * @digest_size Digest buffer size in bytes + */ +TEE_Result dcp_sha_do_final(struct dcp_hash_data *hashdata, uint8_t *digest, + size_t digest_size); + +/* + * Disable the use of the DCP unique key (0xFE in the DCP key-select field). + */ +void dcp_disable_unique_key(void); + +/* Initialize DCP */ +TEE_Result dcp_init(void); + +#ifndef CFG_DT +static inline TEE_Result dcp_vbase(vaddr_t *base __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif /* CFG_DT */ + +#endif /* __IMX_DCP_H__ */ diff --git a/optee/optee_os/core/include/drivers/imx_i2c.h b/optee/optee_os/core/include/drivers/imx_i2c.h new file mode 100644 index 0000000..7012b71 --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx_i2c.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2020 Foundries.io + * Jorge Ramirez-Ortiz + */ +#ifndef __DRIVERS_IMX_I2C_H +#define __DRIVERS_IMX_I2C_H + +#include +#include + +TEE_Result imx_i2c_write(uint8_t bid, uint8_t chip, const uint8_t *p, int l); +TEE_Result imx_i2c_read(uint8_t bid, uint8_t chip, uint8_t *p, int l); +TEE_Result imx_i2c_probe(uint8_t bid, uint8_t chip); +TEE_Result imx_i2c_init(uint8_t bid, int bps); + +#endif /*__DRIVERS_IMX_I2C_H*/ diff --git a/optee/optee_os/core/include/drivers/imx_mu.h b/optee/optee_os/core/include/drivers/imx_mu.h new file mode 100644 index 0000000..716af95 --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx_mu.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2020-2022 NXP + */ +#ifndef __DRIVERS_IMX_MU_H +#define __DRIVERS_IMX_MU_H + +#include +#include +#include + +#define IMX_MU_DATA_U32(mesg, idx) ((mesg)->data.u32[(idx)]) +#define IMX_MU_DATA_U16(mesg, idx) ((mesg)->data.u16[(idx)]) +#define IMX_MU_DATA_U8(mesg, idx) ((mesg)->data.u8[(idx)]) + +#define IMX_MU_MSG_SIZE 17 +#define IMX_MU_NB_CHANNEL 4 + +#if defined(CFG_MX8ULP) || defined(CFG_MX93) +struct imx_mu_msg_header { + uint8_t version; + uint8_t size; + uint8_t command; + uint8_t tag; +}; +#elif defined(CFG_MX8QM) || defined(CFG_MX8QX) || defined(CFG_MX8DXL) +struct imx_mu_msg_header { + uint8_t version; + uint8_t size; + uint8_t tag; + uint8_t command; +}; +#else +#error "Platform not supported" +#endif + +/* + * i.MX MU message format + * Note: the header format differs depending of the platform. + */ +struct imx_mu_msg { + struct imx_mu_msg_header header; + union { + uint32_t u32[IMX_MU_MSG_SIZE]; + uint16_t u16[IMX_MU_MSG_SIZE * 2]; + uint8_t u8[IMX_MU_MSG_SIZE * 4]; + } data; +}; + +/* + * Initialize the MU interface + * + * @base: virtual base address of the MU controller + */ +void imx_mu_init(vaddr_t base); + +/* + * Initiate a communication with the external controller. It sends a message + * and return the answer of the controller. + * + * @base: virtual base address of the MU controller + * @[in/out]msg: message sent and received + * @wait_for_answer: true if an answer from the controller is expected, false + * otherwise + */ +TEE_Result imx_mu_call(vaddr_t base, struct imx_mu_msg *msg, + bool wait_for_answer); +#endif /* __DRIVERS_IMX_MU_H */ diff --git a/optee/optee_os/core/include/drivers/imx_ocotp.h b/optee/optee_os/core/include/drivers/imx_ocotp.h new file mode 100644 index 0000000..72d4b79 --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx_ocotp.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + */ + +#ifndef _IMX_OCOTP_H +#define _IMX_OCOTP_H + +#include + +/* The i.MX UID is 64 bits long */ +#define IMX_UID_SIZE sizeof(uint64_t) + +/* + * Read OCOTP shadow register + * + * @bank Fuse bank number + * @word Fuse word number + * @[out]val Shadow register value + */ +TEE_Result imx_ocotp_read(unsigned int bank, unsigned int word, uint32_t *val); +#endif /* _IMX_OCOTP_H */ diff --git a/optee/optee_os/core/include/drivers/imx_sc_api.h b/optee/optee_os/core/include/drivers/imx_sc_api.h new file mode 100644 index 0000000..d8190ee --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx_sc_api.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2021 NXP + */ +#ifndef __DRIVERS_IMX_SC_API_H +#define __DRIVERS_IMX_SC_API_H + +#include + +/* + * Initializes the Secure Controller + */ +TEE_Result imx_sc_driver_init(void); + +/* + * Enables a CAAM Job Ring for the secure world with the following steps: + * - Assign CAAM JR resources to secure world + * - Power ON CAAM JR resources + * + * @jr_index Index of the CAAM Job Ring to enable + */ +TEE_Result imx_sc_rm_enable_jr(unsigned int jr_index); + +/* + * Starts the random number generator and returns the RNG status. + * + * Note that the RNG is started automatically after all CPUs are booted. This + * function can then be used to start the RNG earlier or to check the RNG + * status. + */ +TEE_Result imx_sc_seco_start_rng(void); +#endif /* __DRIVERS_IMX_SC_API_H */ diff --git a/optee/optee_os/core/include/drivers/imx_snvs.h b/optee/optee_os/core/include/drivers/imx_snvs.h new file mode 100644 index 0000000..2c61af9 --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx_snvs.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2020 Pengutronix + * Rouven Czerwinski + * Copyright 2022 NXP + */ +#ifndef __DRIVERS_IMX_SNVS_H +#define __DRIVERS_IMX_SNVS_H + +#include + +/* Set the OTPMK Key as Master key */ +#ifdef CFG_IMX_SNVS +TEE_Result imx_snvs_set_master_otpmk(void); +bool snvs_is_device_closed(void); +#else +static inline bool snvs_is_device_closed(void) +{ + return false; +} + +static inline TEE_Result imx_snvs_set_master_otpmk(void) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif + +#endif /* __DRIVERS_IMX_SNVS_H */ diff --git a/optee/optee_os/core/include/drivers/imx_uart.h b/optee/optee_os/core/include/drivers/imx_uart.h new file mode 100644 index 0000000..b9df517 --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx_uart.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2017, 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 IMX_UART_H +#define IMX_UART_H + +#include +#include + +struct imx_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void imx_uart_init(struct imx_uart_data *pd, paddr_t base); + +#endif /* IMX_UART_H */ diff --git a/optee/optee_os/core/include/drivers/imx_wdog.h b/optee/optee_os/core/include/drivers/imx_wdog.h new file mode 100644 index 0000000..2c76073 --- /dev/null +++ b/optee/optee_os/core/include/drivers/imx_wdog.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017-2019 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 __IMX_WDOG_H +#define __IMX_WDOG_H + +#include + +/* i.MX6/7D */ +#define WDT_WCR 0x00 +#define WDT_WCR_WDA BIT(5) +#define WDT_WCR_SRS BIT(4) +#define WDT_WCR_WRE BIT(3) +#define WDT_WCR_WDE BIT(2) +#define WDT_WCR_WDZST BIT(0) + +#define WDT_WSR 0x02 +#define WDT_SEQ1 0x5555 +#define WDT_SEQ2 0xAAAA + +/* 7ULP */ +#define WDOG_CNT 0x4 +#define WDOG_TOVAL 0x8 + +#define REFRESH_SEQ0 0xA602 +#define REFRESH_SEQ1 0xB480 +#define REFRESH ((REFRESH_SEQ1 << 16) | REFRESH_SEQ0) + +#define UNLOCK_SEQ0 0xC520 +#define UNLOCK_SEQ1 0xD928 +#define UNLOCK ((UNLOCK_SEQ1 << 16) | UNLOCK_SEQ0) + +#define WDOG_CS 0x0 +#define WDOG_CS_CMD32EN BIT(13) +#define WDOG_CS_ULK BIT(11) +#define WDOG_CS_RCS BIT(10) +#define WDOG_CS_EN BIT(7) +#define WDOG_CS_UPDATE BIT(5) + +/* Exposed for psci reset */ +void __noreturn imx_wdog_restart(bool external_reset); +#endif diff --git a/optee/optee_os/core/include/drivers/lpc_uart.h b/optee/optee_os/core/include/drivers/lpc_uart.h new file mode 100644 index 0000000..3e235b4 --- /dev/null +++ b/optee/optee_os/core/include/drivers/lpc_uart.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, HiSilicon Limited + */ + +#ifndef LPC_UART_H +#define LPC_UART_H + +#include +#include + +#define UART_SEND_LOOP_MAX 1000000 +#define UART_THR 0x00 +#define UART_LSR 0x05 + +#define UART_USR_BUS 0x01 + +#define LPC_BASE 0x201190000 +#define LPC_SIZE 0x1000000 + +#define LPC_START_REG_OFFSET (0x00) +#define LPC_OP_STATUS_REG_OFFSET (0x04) +#define LPC_IRQ_ST_REG_OFFSET (0x08) +#define LPC_OP_LEN_REG_OFFSET (0x10) +#define LPC_CMD_REG_OFFSET (0x14) +#define LPC_FWH_ID_MSIZE_REG_OFFSET (0x18) +#define LPC_ADDR_REG_OFFSET (0x20) +#define LPC_WDATA_REG_OFFSET (0x24) +#define LPC_RDATA_REG_OFFSET (0x28) +#define LPC_LONG_CNT_REG_OFFSET (0x30) +#define LPC_TX_FIFO_ST_REG_OFFSET (0x50) +#define LPC_RX_FIFO_ST_REG_OFFSET (0x54) +#define LPC_TIME_OUT_REG_OFFSET (0x58) +#define LPC_SIRQ_CTRL0_REG_OFFSET (0x80) +#define LPC_SIRQ_CTRL1_REG_OFFSET (0x84) +#define LPC_SIRQ_INT_REG_OFFSET (0x90) +#define LPC_SIRQ_INT_MASK_REG_OFFSET (0x94) +#define LPC_SIRQ_STAT_REG_OFFSET (0xa0) + +#define LPC_SINGLE_READ (0x8) +#define LPC_SINGLE_WRITE (0x9) +#define LPC_IRQ_ST_ON (0x2) +#define LPC_RADTA_LEN (0x40) + +struct lpc_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void lpc_uart_init(struct lpc_uart_data *pd, paddr_t base, + uint32_t uart_clk, uint32_t baud_rate); + +#endif /* LPC_UART_H */ diff --git a/optee/optee_os/core/include/drivers/ls_dspi.h b/optee/optee_os/core/include/drivers/ls_dspi.h new file mode 100644 index 0000000..8f3d870 --- /dev/null +++ b/optee/optee_os/core/include/drivers/ls_dspi.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + * + * Helper Code for DSPI Controller driver + */ + +#ifndef __DRIVERS_LS_DSPI_H +#define __DRIVERS_LS_DSPI_H + +#include +#include + +/* Clock and transfer attributes */ +#define DSPI_CTAR_BRD 0x80000000 /* Double Baud Rate [0] */ +#define DSPI_CTAR_FMSZ(x) (((x) & 0x0F) << 27) /* Frame Size [1-4] */ +#define DSPI_CTAR_CPOL 0x04000000 /* Clock Polarity [5] */ +#define DSPI_CTAR_CPHA 0x02000000 /* Clock Phase [6] */ +#define DSPI_CTAR_LSBFE 0x01000000 /* LSB First [7] */ +#define DSPI_CTAR_PCS_SCK(x) (((x) & 0x03) << 22) /* PCSSCK [8-9] */ +#define DSPI_CTAR_PA_SCK(x) (((x) & 0x03) << 20) /* PASC [10-11] */ +#define DSPI_CTAR_P_DT(x) (((x) & 0x03) << 18) /* PDT [12-13] */ +#define DSPI_CTAR_BRP(x) \ + (((x) & 0x03) << 16) /* Baud Rate Prescaler [14-15] */ +#define DSPI_CTAR_CS_SCK(x) (((x) & 0x0F) << 12) /* CSSCK [16-19] */ +#define DSPI_CTAR_A_SCK(x) (((x) & 0x0F) << 8) /* ASC [20-23] */ +#define DSPI_CTAR_A_DT(x) (((x) & 0x0F) << 4) /* DT [24-27] */ +#define DSPI_CTAR_BR(x) ((x) & 0x0F) /* Baud Rate Scaler [28-31] */ + +/* + * struct ls_dspi_data describes DSPI controller chip instance + * The structure contains below members: + * chip: generic spi_chip instance + * base: DSPI controller base address + * bus_clk_hz: DSPI input clk frequency + * speed_hz: Default SCK frequency=1mhz + * num_chipselect: chip/slave selection + * slave_bus: bus value of slave + * slave_cs: chip slect value of slave + * slave_speed_max_hz: max spped of slave + * slave_mode: mode of slave + * slave_data_size_bits:Data size to be transferred (8 or 16 bits) + * ctar_val: value of Clock and Transfer Attributes Register (CTAR) + * ctar_sel: CTAR0 or CTAR1 + */ +struct ls_dspi_data { + struct spi_chip chip; + vaddr_t base; + unsigned int bus_clk_hz; + unsigned int speed_hz; + unsigned int num_chipselect; + unsigned int slave_bus; + unsigned int slave_cs; + unsigned int slave_speed_max_hz; + unsigned int slave_mode; + unsigned int slave_data_size_bits; + unsigned int ctar_val; + unsigned int ctar_sel; +}; + +/* + * Initialize DSPI Controller + * dspi_data: DSPI controller chip instance + */ +TEE_Result ls_dspi_init(struct ls_dspi_data *dspi_data); + +/* Flush RX and TX FIFO */ +void dspi_flush_fifo(struct ls_dspi_data *dspi_data); + +#endif /* __DRIVERS_LS_DSPI_H */ diff --git a/optee/optee_os/core/include/drivers/ls_gpio.h b/optee/optee_os/core/include/drivers/ls_gpio.h new file mode 100644 index 0000000..0bb3aa1 --- /dev/null +++ b/optee/optee_os/core/include/drivers/ls_gpio.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + * + * Helper Code for GPIO controller driver + * + */ + +#ifndef __DRIVERS_LS_GPIO_H +#define __DRIVERS_LS_GPIO_H + +#include +#include +#include +#include + +/* supported ports for GPIO controller */ +#define MAX_GPIO_PINS U(31) + +/* map register values to LE by subtracting pin number from MAX GPIO PINS */ +#define PIN_SHIFT(x) BIT(MAX_GPIO_PINS - (x)) + +/* gpio register offsets */ +#define GPIODIR U(0x0) /* direction register */ +#define GPIOODR U(0x4) /* open drain register */ +#define GPIODAT U(0x8) /* data register */ +#define GPIOIER U(0xc) /* interrupt event register */ +#define GPIOIMR U(0x10) /* interrupt mask register */ +#define GPIOICR U(0x14) /* interrupt control register */ +#define GPIOIBE U(0x18) /* input buffer enable register */ + +/* + * struct ls_gpio_chip_data describes GPIO controller chip instance + * The structure contains below members: + * chip: generic GPIO chip handle. + * gpio_base: starting GPIO module base address managed by this GPIO + * controller. + * gpio_controller: GPIO controller to be used. + */ +struct ls_gpio_chip_data { + struct gpio_chip chip; + vaddr_t gpio_base; + uint8_t gpio_controller; +}; + +/* + * Initialize GPIO Controller + * gpio_data is a pointer of type 'struct ls_gpio_chip_data'. + */ +TEE_Result ls_gpio_init(struct ls_gpio_chip_data *gpio_data); + +#endif /* __DRIVERS_LS_GPIO_H */ diff --git a/optee/optee_os/core/include/drivers/ls_i2c.h b/optee/optee_os/core/include/drivers/ls_i2c.h new file mode 100644 index 0000000..88ef5fa --- /dev/null +++ b/optee/optee_os/core/include/drivers/ls_i2c.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + * I2C driver for I2C Controller + */ + +#ifndef __DRIVERS_LS_I2C_H +#define __DRIVERS_LS_I2C_H + +#include +#include +#include + +/* + * Module Disable + * 0b - The module is enabled. You must clear this field before any other IBCR + * fields have any effect. + * 1b - The module is reset and disabled. This is the power-on reset situation. + * When high, the interface is held in reset, but registers can still be + * accessed. Status register fields (IBSR) are not valid when the module + * is disabled. + */ +#define I2C_IBCR_MDIS U(0x80) + +/* I2c Bus Interrupt Enable */ +#define I2C_IBCR_IBIE U(0x40) + +/* + * Master / Slave Mode 0b - Slave mode 1b - Master mode + * When you change this field from 0 to 1, the module generates a START signal + * on the bus and selects the master mode. When you change this field from 1 to + * 0, the module generates a STOP signal and changes the operation mode from + * master to slave. You should generate a STOP signal only if IBSR[IBIF]=1. + * The module clears this field without generating a STOP signal when the + * master loses arbitration. + */ +#define I2C_IBCR_MSSL U(0x20) + +/* 0b - Receive 1b - Transmit */ +#define I2C_IBCR_TXRX U(0x10) + +/* + * Data acknowledge disable + * Values written to this field are only used when the I2C module is a receiver, + * not a transmitter. + * 0b - The module sends an acknowledge signal to the bus at the 9th clock bit + * after receiving one byte of data. + * 1b - The module does not send an acknowledge-signal response (that is, + * acknowledge bit = 1). + */ +#define I2C_IBCR_NOACK U(0x08) + +/* + * Repeat START + * If the I2C module is the current bus master, and you program RSTA=1, the I2C + * module generates a repeated START condition. This field always reads as a 0. + * If you attempt a repeated START at the wrong time, if the bus is owned by + * another master the result is loss of arbitration. + */ +#define I2C_IBCR_RSTA U(0x04) + +/* DMA enable */ +#define I2C_IBCR_DMAEN U(0x02) + +/* Transfer Complete */ +#define I2C_IBSR_TCF U(0x80) + +/* I2C bus Busy. 0b - Bus is idle, 1b - Bus is busy */ +#define I2C_IBSR_IBB U(0x20) + +/* Arbitration Lost. software must clear this field by writing a one to it. */ +#define I2C_IBSR_IBAL U(0x10) + +/* I2C bus interrupt flag */ +#define I2C_IBSR_IBIF U(0x02) + +/* + * Received acknowledge + * 0b - Acknowledge received + * 1b - No acknowledge received + */ +#define I2C_IBSR_RXAK U(0x01) + +/* Bus idle interrupt enable */ +#define I2C_IBIC_BIIE U(0x80) + +/* Glitch filter enable */ +#define I2C_IBDBG_GLFLT_EN U(0x08) + +#define I2C_FLAG_WRITE U(0x00000000) +#define I2C_FLAG_READ U(0x00000001) + +#define I2C_BUS_TEST_BUSY true +#define I2C_BUS_TEST_IDLE !I2C_BUS_TEST_BUSY +#define I2C_BUS_TEST_RX_ACK true +#define I2C_BUS_NO_TEST_RX_ACK !I2C_BUS_TEST_RX_ACK + +#define I2C_NUM_RETRIES U(500) + +struct i2c_regs { + uint8_t ibad; /* I2c Bus Address Register */ + uint8_t ibfd; /* I2c Bus Frequency Divider Register */ + uint8_t ibcr; /* I2c Bus Control Register */ + uint8_t ibsr; /* I2c Bus Status Register */ + uint8_t ibdr; /* I2C Bus Data I/O Register */ + uint8_t ibic; /* I2C Bus Interrupt Config Register */ + uint8_t ibdbg; /* I2C Bus Debug Register */ +}; + +/* + * sorted list of clock divisor, ibfd register value pairs + */ +struct i2c_clock_divisor_pair { + uint16_t divisor; + uint8_t ibfd; /* I2c Bus Frequency Divider Register value */ +}; + +/* + * I2C device operation + * The i2c_operation describes a subset of an I2C transaction in which + * the I2C controller is either sending or receiving bytes from the bus. + * Some transactions will consist of a single operation while others will + * be two or more. + */ +struct i2c_operation { + /* Flags to qualify the I2C operation. */ + uint32_t flags; + + /* + * Number of bytes to send to or receive from the I2C device.A ping + * is indicated by setting the length_in_bytes to zero. + */ + unsigned int length_in_bytes; + + /* + * Pointer to a buffer containing the data to send or to receive from + * the I2C device. The Buffer must be at least length_in_bytes in size. + */ + uint8_t *buffer; +}; + +/* + * Structure to initialize I2C controller. + */ +struct ls_i2c_data { + /* I2C Controller to initialize */ + uint8_t i2c_controller; + /* + * base will be filled by i2c_init() which will be used in + * subsequent calls for reading/writing data. + */ + vaddr_t base; + /* I2C bus clock frequency */ + uint64_t i2c_bus_clock; + /* I2C speed */ + uint64_t speed; +}; + +/* + * Structure to fill for I2C read/write operation + */ +struct i2c_reg_request { + /* + * Number of operations to perform. + * This will depend on peripheral for which it is used. + */ + unsigned int operation_count; + /* Operation to perform */ + struct i2c_operation *operation; +}; + +/* + * Initialize I2C Controller, based on data passed in + * i2c_data. + */ +TEE_Result i2c_init(struct ls_i2c_data *i2c_data); + +/* + * Software reset of the entire I2C module. + * The module is reset and disabled. + * Status register fields (IBSR) are cleared. + * base Base Address of I2c controller's registers + */ +void i2c_reset(vaddr_t base); + +/* + * Transfer data to/from I2c slave device + * base Base Address of I2c controller's registers + * slave_address Slave Address from which data is to be read + * i2c_operation Pointer to an i2c_operation structure + * operation_count Number of operations. + */ +TEE_Result i2c_bus_xfer(vaddr_t base, uint32_t slave_address, + struct i2c_operation *i2c_operation, + unsigned int operation_count); + +#endif /* __DRIVERS_LS_I2C_H */ diff --git a/optee/optee_os/core/include/drivers/ls_sec_mon.h b/optee/optee_os/core/include/drivers/ls_sec_mon.h new file mode 100644 index 0000000..2906e7a --- /dev/null +++ b/optee/optee_os/core/include/drivers/ls_sec_mon.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 Microsoft + * + * Definitions for the NXP LX2160A-series Security Monitor (SecMon) driver. + */ + +#ifndef __DRIVERS_LS_SEC_MON_H +#define __DRIVERS_LS_SEC_MON_H + +#include +#include + +/** + * struct ls_sec_mon_data - Compact data struct of all SecMon registers. + * @hplr: HP Lock Register. + * @hpcomr: HP Command Register. + * @hpsicr: HP Security Interrupt Control Register. + * @hpsvcr: HP Security Violation Control Register. + * @hpsr: HP Status Register. + * @hpsvsr: HP Security Violation Status Register. + * @hphacivr: HP High Assurance Counter IV Register. + * @hphacr: HP High Assurance Counter Register. + * @lplr: LP Lock Register. + * @lpcr: LP Control Register. + * @lpmkcr: LP Master Key Control Register. + * @lpsvcr: LP Security Violation Control Register. + * @lptdcr: LP Tamper Detectors Configuration Register. + * @lpsr: LP Status Register. + * @lpsmcmr: LP Secure Monotonic Counter MSB Register. + * @lpsmclr: LP Secure Monotonic Counter LSB Register. + * @lppgdr: LP Power Glitch Detector Register. + * @lpzmkr[8]: LP Zeroizable Master Key Registers. + * @lpgpr[4]: LP General Purpose Registers. + * @hpvidr1: HP Version ID Register 1. + * @hpvidr2: HP Version ID Register 2. + */ +struct ls_sec_mon_data { + uint32_t hplr; + uint32_t hpcomr; + uint32_t hpsicr; + uint32_t hpsvcr; + uint32_t hpsr; + uint32_t hpsvsr; + uint32_t hphacivr; + uint32_t hphacr; + uint32_t lplr; + uint32_t lpcr; + uint32_t lpmkcr; + uint32_t lpsvcr; + uint32_t lptdcr; + uint32_t lpsr; + uint32_t lpsmcmr; + uint32_t lpsmclr; + uint32_t lppgdr; + uint32_t lpzmkr[8]; + uint32_t lpgpr[4]; + uint32_t hpvidr1; + uint32_t hpvidr2; +}; + +/** + * ls_sec_mon_read() - Read a copy of the SecMon register data if the SecMon + * driver was successfully initialized. + * @data: Location to save SecMon data. + * + * Return: 0 if successful or > 0 on error. + */ +TEE_Result ls_sec_mon_read(struct ls_sec_mon_data *data); + +/** + * ls_sec_mon_status() - Check if the SecMon driver was initialized + * successfully. + * + * Return: 0 if init was successful or TEE_ERROR_GENERIC on init failed. + */ +TEE_Result ls_sec_mon_status(void); + +#endif /* __DRIVERS_LS_SEC_MON_H */ diff --git a/optee/optee_os/core/include/drivers/ls_sfp.h b/optee/optee_os/core/include/drivers/ls_sfp.h new file mode 100644 index 0000000..929a1fe --- /dev/null +++ b/optee/optee_os/core/include/drivers/ls_sfp.h @@ -0,0 +1,172 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 Microsoft + * + * Definitions for the NXP LX2160A-series Security Fuse Processor (SFP) driver. + */ + +#ifndef __DRIVERS_LS_SFP_H +#define __DRIVERS_LS_SFP_H + +#include +#include +#include + +/* SFP instruction register */ +/* SFP is big endian */ +#define SFP_INGR_PROGFB_CMD 0x2 +#define SFP_INGR_ERROR_MASK 0x100 +#define SFP_INGR_FUSE_TIMEOUT_US 150000 + +/* SFP configuration register */ +#define SFP_SFPCR_SB_MASK 0x20000000 +#define SFP_SFPCR_SB_OFFSET 29 + +/* SFP OEM security policy register 0 */ +#define SFP_OSPR0_WP_MASK 0x1 +#define SFP_OSPR0_ITS_MASK 0x4 +#define SFP_OSPR0_ITS_OFFSET 0x2 + +/* SFP OEM security policy register 1 */ +#define SFP_OSPR1_DBLEV_MASK 0x7 +#define SFP_OSPR1_DBLEV_OPEN 0x0 +#define SFP_OSPR1_DBLEV_CLOSED_NOTIFY 0x1 +#define SFP_OSPR1_DBLEV_CLOSED_SILENT 0x2 +#define SFP_OSPR1_DBLEV_CLOSED 0x4 + +/** + * struct ls_sfp_data - Compact data struct of all SFP registers. + * @ingr: Instruction Register. + * @svhesr: Secret Value Hamming Error Status Register. + * @sfpcr: SFP Configuration Register. + * @version: SFP Version Register. + * @ospr0: OEM Security Policy Register 0. + * @ospr1: OEM Security Policy Register 1. + * @dcvr0: Debug Challenge Value Register 0. + * @dcvr1: Debug Challenge Value Register 1. + * @drvr0: Debug Response Value Register 0. + * @drvr1: Debug Response Value Register 1. + * @fswpr: Factory Section Write Protect Register. + * @fuidr0: Factory Unique ID Register 0. + * @fuidr1: Factory Unique ID Register 1. + * @isbccr: ISBC Configuration Register. + * @fspfr[0x3]: Factory Scratch Pad Fuse Registers. + * @otpmkr[0x8]: One Time Programmable Master Key. + * @srkhr[0x8]: Super Root Key Hash Register. + * @ouidr[0x5]: OEM Unique ID/Scratch Pad Fuse Registers. + */ +struct ls_sfp_data { + uint32_t ingr; + uint32_t svhesr; + uint32_t sfpcr; + uint32_t version; + uint32_t ospr0; + uint32_t ospr1; + uint32_t dcvr0; + uint32_t dcvr1; + uint32_t drvr0; + uint32_t drvr1; + uint32_t fswpr; + uint32_t fuidr0; + uint32_t fuidr1; + uint32_t isbccr; + uint32_t fspfr[0x3]; + uint32_t otpmkr[0x8]; + uint32_t srkhr[0x8]; + uint32_t ouidr[0x5]; +}; + +/** + * ls_sfp_read() - Read a copy of the SFP register data if the SFP driver was + * successfully initialized. + * @data: Location to save SFP data. + * + * Return: TEE_SUCCESS or > 0 on error + */ +TEE_Result ls_sfp_read(struct ls_sfp_data *data); + +/** + * ls_sfp_get_debug_level() - Read the last 3 bits of the SFP OSPR1 register + * which denotes the debug level. + * @dblev: Pointer location to store the read debug level. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_get_debug_level(uint32_t *dblev); + +/** + * ls_sfp_get_its() - Read bit 29 of the SFP OSPR0 register which denotes the + * ITS flag. + * @its: Pointer location to store the ITS flag. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_get_its(uint32_t *its); + +/** + * ls_sfp_get_ouid() - Read the SFP OUID register at the given index. + * @index: Index of the OUID register to read. + * @ouid: Pointer location to store the OIUD register value. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_get_ouid(uint32_t index, uint32_t *ouid); + +/** + * ls_sfp_get_sb() - Read bit 2 of the SFP SFPCR register which denotes the + * secure boot flag. + * @sb: Pointer location to store the secure boot flag. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_get_sb(uint32_t *sb); + +/** + * ls_sfp_get_srkh() - Read the SFP SRKH register at the given index. + * @index: Index of the SRKH register to read. + * @srkh: Pointer location to store the SRKH register value. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_get_srkh(uint32_t index, uint32_t *srkh); + +/** + * ls_sfp_set_debug_level() - Set the last 3 bits of the SFP OSPR1 register + * which denotes the debug level. + * @dblev: Value to write into the SFP OSPR1 register. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_set_debug_level(uint32_t dblev); + +/** + * ls_sfp_set_its_wp() - Set bits 29 and 31 of the SFP OSPR0 register which + * denote the ITS and write protect flags respectively. + * + * WARNING - Setting the ITS and write protect flags will lock the mirror + * registers and permanently prevent any further programming of the fuse block. + * The system will also be forced to always attempt to secure boot which + * requires signature validation and the absence of any hardware security + * violations when booting. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_set_its_wp(void); + +/** + * ls_sfp_set_ouid() - Write to the SFP OUID register at the given index. + * @index: Index of the OUID register to write. + * @ouid: Value to write into the SFP OUID register. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_set_ouid(uint32_t index, uint32_t ouid); + +/** + * ls_sfp_status() - Check if the SFP driver was initialized successfully. + * + * Return: TEE_SUCCESS or > 0 on error. + */ +TEE_Result ls_sfp_status(void); + +#endif /* __DRIVERS_LS_SFP_H */ diff --git a/optee/optee_os/core/include/drivers/mvebu_uart.h b/optee/optee_os/core/include/drivers/mvebu_uart.h new file mode 100644 index 0000000..fed9ac8 --- /dev/null +++ b/optee/optee_os/core/include/drivers/mvebu_uart.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2017 Marvell International Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 MVEBU_UART_H +#define MVEBU_UART_H + +#include +#include + +struct mvebu_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void mvebu_uart_init(struct mvebu_uart_data *pd, paddr_t pbase, + uint32_t uart_clk, uint32_t baud_rate); + +#endif /* MVEBU_UART_H */ diff --git a/optee/optee_os/core/include/drivers/ns16550.h b/optee/optee_os/core/include/drivers/ns16550.h new file mode 100644 index 0000000..cbd7ede --- /dev/null +++ b/optee/optee_os/core/include/drivers/ns16550.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Copyright (c) 2020, 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 NS16550_H +#define NS16550_H + +#include +#include +#include + +#define IO_WIDTH_U8 0 +#define IO_WIDTH_U32 1 + +struct ns16550_data { + struct io_pa_va base; + struct serial_chip chip; + uint8_t io_width; + uint8_t reg_shift; +}; + +static inline unsigned int serial_in(vaddr_t addr, uint8_t io_width) +{ + if (io_width == IO_WIDTH_U32) + return io_read32(addr); + else + return io_read8(addr); +} + +static inline void serial_out(vaddr_t addr, uint8_t io_width, int ch) +{ + if (io_width == IO_WIDTH_U32) + io_write32(addr, ch); + else + io_write8(addr, ch); +} + +void ns16550_init(struct ns16550_data *pd, paddr_t base, uint8_t io_width, + uint8_t reg_shift); + +#endif /* NS16550_H */ diff --git a/optee/optee_os/core/include/drivers/pl011.h b/optee/optee_os/core/include/drivers/pl011.h new file mode 100644 index 0000000..b46880e --- /dev/null +++ b/optee/optee_os/core/include/drivers/pl011.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ +#ifndef PL011_H +#define PL011_H + +#include +#include + +#define PL011_REG_SIZE 0x1000 + +struct pl011_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void pl011_init(struct pl011_data *pd, paddr_t pbase, uint32_t uart_clk, + uint32_t baud_rate); + +#endif /* PL011_H */ diff --git a/optee/optee_os/core/include/drivers/pl022_spi.h b/optee/optee_os/core/include/drivers/pl022_spi.h new file mode 100644 index 0000000..b40ba41 --- /dev/null +++ b/optee/optee_os/core/include/drivers/pl022_spi.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * + */ + +#ifndef __PL022_SPI_H__ +#define __PL022_SPI_H__ + +#include +#include + +#define PL022_REG_SIZE 0x1000 + +enum pl022_cs_control { + PL022_CS_CTRL_AUTO_GPIO, + PL022_CS_CTRL_CB, + PL022_CS_CTRL_MANUAL +}; + +struct pl022_cs_gpio_data { + struct gpio_chip *chip; + unsigned int pin_num; +}; + +union pl022_cs_data { + struct pl022_cs_gpio_data gpio_data; + void (*cs_cb)(enum gpio_level value); +}; + +struct pl022_data { + union pl022_cs_data cs_data; + struct spi_chip chip; + vaddr_t base; + enum spi_mode mode; + enum pl022_cs_control cs_control; + unsigned int clk_hz; + unsigned int speed_hz; + unsigned int data_size_bits; + bool loopback; +}; + +void pl022_init(struct pl022_data *pd); + +#endif /* __PL022_SPI_H__ */ + diff --git a/optee/optee_os/core/include/drivers/pl061_gpio.h b/optee/optee_os/core/include/drivers/pl061_gpio.h new file mode 100644 index 0000000..ea6f521 --- /dev/null +++ b/optee/optee_os/core/include/drivers/pl061_gpio.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __PL061_GPIO_H__ +#define __PL061_GPIO_H__ + +#include +#include + +#define PL061_REG_SIZE 0x1000 + +enum pl061_mode_control { + PL061_MC_SW, + PL061_MC_HW +}; + +struct pl061_data { + struct gpio_chip chip; +}; + +void pl061_register(vaddr_t base_addr, unsigned int gpio_dev); +void pl061_init(struct pl061_data *pd); +enum pl061_mode_control pl061_get_mode_control(unsigned int gpio_pin); +void pl061_set_mode_control(unsigned int gpio_pin, + enum pl061_mode_control hw_sw); + +#endif /* __PL061_GPIO_H__ */ diff --git a/optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h b/optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h new file mode 100644 index 0000000..a9801d6 --- /dev/null +++ b/optee/optee_os/core/include/drivers/pm/sam/atmel_pm.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Microchip + */ +#ifndef __DRIVERS_PM_SAM_ATMEL_PM_H +#define __DRIVERS_PM_SAM_ATMEL_PM_H + +#include +#include +#include +#include +#include +#include + +struct sm_nsec_ctx; + +#if defined(CFG_ATMEL_PM) + +static inline bool atmel_pm_suspend_available(void) +{ + return true; +} + +void atmel_pm_cpu_idle(void); + +TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec); + +TEE_Result sama5d2_pm_init(const void *fdt, vaddr_t shdwc); + +enum sm_handler_ret at91_pm_set_suspend_mode(struct thread_smc_args *args); + +enum sm_handler_ret at91_pm_get_suspend_mode(struct thread_smc_args *args); + +#else + +static inline void atmel_pm_cpu_idle(void) {}; + +static inline bool atmel_pm_suspend_available(void) +{ + return false; +} + +static inline TEE_Result atmel_pm_suspend(uintptr_t entry __unused, + struct sm_nsec_ctx *nsec __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result sama5d2_pm_init(const void *fdt __unused, + vaddr_t shdwc __unused) +{ + return TEE_SUCCESS; +} + +static inline enum sm_handler_ret +at91_pm_set_suspend_mode(struct thread_smc_args *args __unused) +{ + return SM_HANDLER_PENDING_SMC; +} + +static inline enum sm_handler_ret +at91_pm_get_suspend_mode(struct thread_smc_args *args __unused) +{ + return SM_HANDLER_PENDING_SMC; +} + +#endif + +#endif /* __DRIVERS_PM_SAM_ATMEL_PM_H */ diff --git a/optee/optee_os/core/include/drivers/rstctrl.h b/optee/optee_os/core/include/drivers/rstctrl.h new file mode 100644 index 0000000..6fb89c3 --- /dev/null +++ b/optee/optee_os/core/include/drivers/rstctrl.h @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#ifndef __DRIVERS_RSTCTRL_H +#define __DRIVERS_RSTCTRL_H + +#include +#include +#include + +struct rstctrl; + +struct rstctrl_ops { + /* + * Operators on reset control(s) exposed by a reset controller + * + * @assert_level: Assert reset level on control with a timeout hint + * @deassert_level: Deassert reset level on control with a timeout hint + * @get_name: Get a string name for the controller, or NULL is none + * + * Operator functions @assert_level and @deassert_level use arguments: + * @rstctrl: Reset controller + * @id: Identifier for the reset level control in the reset controller + * @to_ms: Timeout in microseconds or RSTCTRL_NO_TIMEOUT, may be ignored + * by reset controller. + * Return a TEE_Result compliant code. + */ + TEE_Result (*assert_level)(struct rstctrl *rstctrl, unsigned int to_us); + TEE_Result (*deassert_level)(struct rstctrl *rstctrl, + unsigned int to_us); + const char *(*get_name)(struct rstctrl *rstctrl); +}; + +/* + * struct rstctrl - Instance of a control exposed by a reset controller + * @ops: Operators of the reset controller + * @exclusive: Set when a consumer has exclusive control on the reset level + */ +struct rstctrl { + const struct rstctrl_ops *ops; + bool exclusive; +}; + +/** + * RSTCTRL_DECLARE - Declare a reset controller driver with a single + * device tree compatible string. + * + * @__name: Reset controller driver name + * @__compat: Compatible string + * @__probe: Reset controller probe function + */ +#define RSTCTRL_DT_DECLARE(__name, __compat, __probe) \ + static const struct dt_device_match __name ## _match_table[] = { \ + { .compatible = __compat }, \ + { } \ + }; \ + DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ + .name = # __name, \ + .type = DT_DRIVER_RSTCTRL, \ + .match_table = __name ## _match_table, \ + .probe = __probe, \ + } + +/* + * Platform driver may ignore the timeout hint according to their + * capabilities. RSTCTRL_NO_TIMEOUT specifies no timeout hint. + */ +#define RSTCTRL_NO_TIMEOUT 0 + +/* + * rstctrl_assert_to - Assert reset control possibly with timeout + * rstctrl_assert - Assert reset control + * rstctrl_deassert_to - Deassert reset control possibly with timeout + * rstctrl_deassert - Deassert reset control + * + * @rstctrl: Reset controller + * @to_us: Timeout in microseconds + * Return a TEE_Result compliant code + */ +static inline TEE_Result rstctrl_assert_to(struct rstctrl *rstctrl, + unsigned int to_us) +{ + return rstctrl->ops->assert_level(rstctrl, to_us); +} + +static inline TEE_Result rstctrl_assert(struct rstctrl *rstctrl) +{ + return rstctrl_assert_to(rstctrl, RSTCTRL_NO_TIMEOUT); +} + +static inline TEE_Result rstctrl_deassert_to(struct rstctrl *rstctrl, + unsigned int to_us) +{ + return rstctrl->ops->deassert_level(rstctrl, to_us); +} + +static inline TEE_Result rstctrl_deassert(struct rstctrl *rstctrl) +{ + return rstctrl_deassert_to(rstctrl, RSTCTRL_NO_TIMEOUT); +} + +/* + * rstctrl_name - Get a name for the reset level control or NULL + * + * @rstctrl: Reset controller + * Return a pointer to controller name or NULL + */ +static inline const char *rstctrl_name(struct rstctrl *rstctrl) +{ + if (rstctrl->ops->get_name) + return rstctrl->ops->get_name(rstctrl); + + return NULL; +} + +/** + * rstctrl_dt_get_exclusive - Get exclusive access to reset controller + * + * @rstctrl: Reset controller + * Return a TEE_Result compliant value + */ +TEE_Result rstctrl_get_exclusive(struct rstctrl *rstctrl); + +/** + * rstctrl_put_exclusive - Release exclusive access to target + * + * @rstctrl: Reset controller + */ +void rstctrl_put_exclusive(struct rstctrl *rstctrl); + +/** + * rstctrl_ops_is_valid - Check reset controller ops is valid + * + * @ops: Reference to reset controller operator instance + */ +static inline bool rstctrl_ops_is_valid(const struct rstctrl_ops *ops) +{ + return ops && ops->assert_level && ops->deassert_level; +} + +#ifdef CFG_DT +/** + * rstctrl_dt_get_by_index - Get a reset controller at a specific index in + * 'resets' property + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the subnode containing a 'resets' property + * @index: Reset controller index in 'resets' property + * @rstctrl: Output reset controller reference upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the resets property does not exist + * Return a TEE_Result compliant code in case of error + */ +static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt, + int nodeoffset, + unsigned int index, + struct rstctrl **rstctrl) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + *rstctrl = dt_driver_device_from_node_idx_prop("resets", fdt, + nodeoffset, index, + DT_DRIVER_RSTCTRL, &res); + return res; +} +#else +static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt __unused, + int nodeoffset __unused, + unsigned int index __unused, + struct rstctrl **rstctrl) +{ + *rstctrl = NULL; + return TEE_ERROR_NOT_SUPPORTED; +} +#endif /*CFG_DT*/ + +/** + * rstctrl_dt_get_by_name - Get a reset controller matching a name in the + * 'reset-names' property + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the subnode containing a 'resets' property + * @name: Reset controller name to get + * @rstctrl: Output reset controller reference upon success + * + * Return TEE_SUCCESS in case of success + * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized + * Return TEE_ERROR_ITEM_NOT_FOUND if the reset-names property does not exist + * Return a TEE_Result compliant code in case of error + */ +TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset, + const char *name, struct rstctrl **rstctrl); + +/** + * rstctrl_dt_get_func - Typedef of function to get reset controller from + * devicetree properties + * + * @a: Pointer to devicetree description of the reset controller to parse + * @data: Pointer to data given at rstctrl_dt_register_provider() call + * @res: Output result code of the operation: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized + * Any TEE_Result compliant code in case of error. + * + * Returns a struct rstctrl pointer pointing to a reset controller matching + * the devicetree description or NULL if invalid description in which case + * @res provides the error code. + */ +typedef struct rstctrl *(*rstctrl_dt_get_func)(struct dt_driver_phandle_args *a, + void *data, TEE_Result *res); + +/** + * rstctrl_dt_register_provider - Register a reset controller provider + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset of the reset controller + * @get_dt_rstctrl: Callback to match the reset controller with a struct rstctrl + * @data: Data which will be passed to the get_dt_rstctrl callback + * Returns TEE_Result value + */ +static inline +TEE_Result rstctrl_register_provider(const void *fdt, int nodeoffset, + rstctrl_dt_get_func get_dt_rstctrl, + void *data) +{ + return dt_driver_register_provider(fdt, nodeoffset, + (get_of_device_func)get_dt_rstctrl, + data, DT_DRIVER_RSTCTRL); +} +#endif /* __DRIVERS_RSTCTRL_H */ + diff --git a/optee/optee_os/core/include/drivers/rtc.h b/optee/optee_os/core/include/drivers/rtc.h new file mode 100644 index 0000000..c7f05be --- /dev/null +++ b/optee/optee_os/core/include/drivers/rtc.h @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 Microchip. + */ + +#ifndef DRIVERS_RTC_H +#define DRIVERS_RTC_H + +#include +#include + +/* The RTC allows to set/get offset for correction */ +#define RTC_CORRECTION_FEATURE BIT(0) + +struct optee_rtc_time { + uint32_t tm_year; + uint32_t tm_mon; + uint32_t tm_mday; + uint32_t tm_hour; + uint32_t tm_min; + uint32_t tm_sec; + uint32_t tm_wday; +}; + +struct rtc { + const struct rtc_ops *ops; + struct optee_rtc_time range_min; + struct optee_rtc_time range_max; +}; + +/* + * struct rtc_ops - The RTC device operations + * + * @get_time: Get the RTC time. + * @set_time: Set the RTC time. + * @get_offset: Get the RTC offset. + * @set_offset: Set the RTC offset + */ +struct rtc_ops { + TEE_Result (*get_time)(struct rtc *rtc, struct optee_rtc_time *tm); + TEE_Result (*set_time)(struct rtc *rtc, struct optee_rtc_time *tm); + TEE_Result (*get_offset)(struct rtc *rtc, long *offset); + TEE_Result (*set_offset)(struct rtc *rtc, long offset); +}; + +#ifdef CFG_DRIVERS_RTC +extern struct rtc *rtc_device; + +/* Register a RTC device as the system RTC */ +void rtc_register(struct rtc *rtc); + +static inline TEE_Result rtc_get_info(uint64_t *features, + struct optee_rtc_time *range_min, + struct optee_rtc_time *range_max) +{ + if (!rtc_device) + return TEE_ERROR_NOT_SUPPORTED; + + if (rtc_device->ops->set_offset) + *features = RTC_CORRECTION_FEATURE; + *range_min = rtc_device->range_min; + *range_max = rtc_device->range_max; + + return TEE_SUCCESS; +} + +static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm) +{ + if (!rtc_device) + return TEE_ERROR_NOT_SUPPORTED; + + return rtc_device->ops->get_time(rtc_device, tm); +} + +static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm) +{ + if (!rtc_device || !rtc_device->ops->set_time) + return TEE_ERROR_NOT_SUPPORTED; + + return rtc_device->ops->set_time(rtc_device, tm); +} + +static inline TEE_Result rtc_get_offset(long *offset) +{ + if (!rtc_device || !rtc_device->ops->get_offset) + return TEE_ERROR_NOT_SUPPORTED; + + return rtc_device->ops->get_offset(rtc_device, offset); +} + +static inline TEE_Result rtc_set_offset(long offset) +{ + if (!rtc_device || !rtc_device->ops->set_offset) + return TEE_ERROR_NOT_SUPPORTED; + + return rtc_device->ops->set_offset(rtc_device, offset); +} + +#else + +static inline void rtc_register(struct rtc *rtc __unused) {} + +static inline TEE_Result rtc_get_info(uint64_t *features __unused, + struct optee_rtc_time *range_min __unused, + struct optee_rtc_time *range_max __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result rtc_get_offset(long *offset __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result rtc_set_offset(long offset __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif +#endif /* DRIVERS_RTC_H */ diff --git a/optee/optee_os/core/include/drivers/sam/at91_ddr.h b/optee/optee_os/core/include/drivers/sam/at91_ddr.h new file mode 100644 index 0000000..84e13e6 --- /dev/null +++ b/optee/optee_os/core/include/drivers/sam/at91_ddr.h @@ -0,0 +1,187 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Header file for the Atmel DDR/SDR SDRAM Controller + * + * Copyright (C) 2010 Atmel Corporation + * Nicolas Ferre + */ + +#ifndef AT91_DDRSDR_H +#define AT91_DDRSDR_H + +/* Mode Register */ +#define AT91_DDRSDRC_MR 0x00 +/* Command Mode */ +#define AT91_DDRSDRC_MODE SHIFT_U32(0x7, 0) +#define AT91_DDRSDRC_MODE_NORMAL 0 +#define AT91_DDRSDRC_MODE_NOP 1 +#define AT91_DDRSDRC_MODE_PRECHARGE 2 +#define AT91_DDRSDRC_MODE_LMR 3 +#define AT91_DDRSDRC_MODE_REFRESH 4 +#define AT91_DDRSDRC_MODE_EXT_LMR 5 +#define AT91_DDRSDRC_MODE_DEEP 6 + +/* Refresh Timer Register */ +#define AT91_DDRSDRC_RTR 0x04 +/* Refresh Timer Counter */ +#define AT91_DDRSDRC_COUNT SHIFT_U32(0xfff, 0) + +/* Configuration Register */ +#define AT91_DDRSDRC_CR 0x08 +/* Number of Column Bits */ +#define AT91_DDRSDRC_NC SHIFT_U32(3, 0) +#define AT91_DDRSDRC_NC_SDR8 SHIFT_U32(0, 0) +#define AT91_DDRSDRC_NC_SDR9 BIT(0) +#define AT91_DDRSDRC_NC_SDR10 SHIFT_U32(2, 0) +#define AT91_DDRSDRC_NC_SDR11 SHIFT_U32(3, 0) +#define AT91_DDRSDRC_NC_DDR9 SHIFT_U32(0, 0) +#define AT91_DDRSDRC_NC_DDR10 BIT(0) +#define AT91_DDRSDRC_NC_DDR11 SHIFT_U32(2, 0) +#define AT91_DDRSDRC_NC_DDR12 SHIFT_U32(3, 0) +/* Number of Row Bits */ +#define AT91_DDRSDRC_NR SHIFT_U32(3, 2) +#define AT91_DDRSDRC_NR_11 SHIFT_U32(0, 2) +#define AT91_DDRSDRC_NR_12 BIT(2) +#define AT91_DDRSDRC_NR_13 SHIFT_U32(2, 2) +#define AT91_DDRSDRC_NR_14 SHIFT_U32(3, 2) +/* CAS Latency */ +#define AT91_DDRSDRC_CAS SHIFT_U32(7, 4) +#define AT91_DDRSDRC_CAS_2 SHIFT_U32(2, 4) +#define AT91_DDRSDRC_CAS_3 SHIFT_U32(3, 4) +#define AT91_DDRSDRC_CAS_25 SHIFT_U32(6, 4) +/* Reset DLL */ +#define AT91_DDRSDRC_RST_DLL BIT(7) +/* Output impedance control */ +#define AT91_DDRSDRC_DICDS BIT(8) +/* Disable DLL [SAM9 Only] */ +#define AT91_DDRSDRC_DIS_DLL BIT(9) +/* Off-Chip Driver [SAM9 Only] */ +#define AT91_DDRSDRC_OCD BIT(12) +/* Mask Data is Shared [SAM9 Only] */ +#define AT91_DDRSDRC_DQMS BIT(16) +/* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */ +#define AT91_DDRSDRC_ACTBST BIT(18) + +/* Timing 0 Register */ +#define AT91_DDRSDRC_T0PR 0x0C +/* Active to Precharge delay */ +#define AT91_DDRSDRC_TRAS SHIFT_U32(0xf, 0) +/* Row to Column delay */ +#define AT91_DDRSDRC_TRCD SHIFT_U32(0xf, 4) +/* Write recovery delay */ +#define AT91_DDRSDRC_TWR SHIFT_U32(0xf, 8) +/* Row cycle delay */ +#define AT91_DDRSDRC_TRC SHIFT_U32(0xf, 12) +/* Row precharge delay */ +#define AT91_DDRSDRC_TRP SHIFT_U32(0xf, 16) +/* Active BankA to BankB */ +#define AT91_DDRSDRC_TRRD SHIFT_U32(0xf, 20) +/* Internal Write to Read delay */ +#define AT91_DDRSDRC_TWTR SHIFT_U32(0x7, 24) +/* Reduce Write to Read Delay [SAM9 Only] */ +#define AT91_DDRSDRC_RED_WRRD SHIFT_U32(0x1, 27) +/* Load mode to active/refresh delay */ +#define AT91_DDRSDRC_TMRD SHIFT_U32(0xf, 28) + +/* Timing 1 Register */ +#define AT91_DDRSDRC_T1PR 0x10 +/* Row Cycle Delay */ +#define AT91_DDRSDRC_TRFC SHIFT_U32(0x1f, 0) +/* Exit self-refresh to non-read */ +#define AT91_DDRSDRC_TXSNR SHIFT_U32(0xff, 8) +/* Exit self-refresh to read */ +#define AT91_DDRSDRC_TXSRD SHIFT_U32(0xff, 16) +/* Exit power-down delay */ +#define AT91_DDRSDRC_TXP SHIFT_U32(0xf, 24) + +/* Timing 2 Register [SAM9 Only] */ +#define AT91_DDRSDRC_T2PR 0x14 +/* Exit active power down delay to read command in mode "Fast Exit" */ +#define AT91_DDRSDRC_TXARD SHIFT_U32(0xf, 0) +/* Exit active power down delay to read command in mode "Slow Exit" */ +#define AT91_DDRSDRC_TXARDS SHIFT_U32(0xf, 4) +/* Row Precharge All delay */ +#define AT91_DDRSDRC_TRPA SHIFT_U32(0xf, 8) +/* Read to Precharge delay */ +#define AT91_DDRSDRC_TRTP SHIFT_U32(0x7, 12) + +/* Low Power Register */ +#define AT91_DDRSDRC_LPR 0x1C +/* Low-power Configurations */ +#define AT91_DDRSDRC_LPCB SHIFT_U32(3, 0) +#define AT91_DDRSDRC_LPCB_DISABLE 0 +#define AT91_DDRSDRC_LPCB_SELF_REFRESH 1 +#define AT91_DDRSDRC_LPCB_POWER_DOWN 2 +#define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3 +/* Clock Frozen */ +#define AT91_DDRSDRC_CLKFR BIT(2) +/* LPDDR Power Off */ +#define AT91_DDRSDRC_LPDDR2_PWOFF BIT(3) +/* Partial Array Self Refresh */ +#define AT91_DDRSDRC_PASR SHIFT_U32(7, 4) +/* Temperature Compensated Self Refresh */ +#define AT91_DDRSDRC_TCSR SHIFT_U32(3, 8) +/* Drive Strength */ +#define AT91_DDRSDRC_DS SHIFT_U32(3, 10) +/* Time to define when Low Power Mode is enabled */ +#define AT91_DDRSDRC_TIMEOUT SHIFT_U32(3, 12) +#define AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES SHIFT_U32(0, 12) +#define AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES BIT(12) +#define AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES SHIFT_U32(2, 12) +/* Active power down exit time */ +#define AT91_DDRSDRC_APDE BIT(16) +/* Update load mode register and extended mode register */ +#define AT91_DDRSDRC_UPD_MR SHIFT_U32(3, 20) + +/* Memory Device Register */ +#define AT91_DDRSDRC_MDR 0x20 +/* Memory Device Type */ +#define AT91_DDRSDRC_MD SHIFT_U32(7, 0) +#define AT91_DDRSDRC_MD_SDR 0 +#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1 +#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3 +#define AT91_DDRSDRC_MD_LPDDR3 5 +/* [SAM9 Only] */ +#define AT91_DDRSDRC_MD_DDR2 6 +#define AT91_DDRSDRC_MD_LPDDR2 7 +/* Data Bus Width */ +#define AT91_DDRSDRC_DBW BIT(4) +#define AT91_DDRSDRC_DBW_32BITS SHIFT_U32(0, 4) +#define AT91_DDRSDRC_DBW_16BITS BIT(4) + +/* DLL Information Register */ +#define AT91_DDRSDRC_DLL 0x24 +/* Master Delay increment */ +#define AT91_DDRSDRC_MDINC BIT(0) +/* Master Delay decrement */ +#define AT91_DDRSDRC_MDDEC BIT(1) +/* Master Delay Overflow */ +#define AT91_DDRSDRC_MDOVF BIT(2) +/* Master Delay value */ +#define AT91_DDRSDRC_MDVAL SHIFT_U32(0xff, 8) + +/* High Speed Register [SAM9 Only] */ +#define AT91_DDRSDRC_HS 0x2C +/* Anticip read access is disabled */ +#define AT91_DDRSDRC_DIS_ATCP_RD BIT(2) + +/* Delay I/O Register n */ +#define AT91_DDRSDRC_DELAY(n) (0x30 + (0x4 * (n))) + +/* Write Protect Mode Register [SAM9 Only] */ +#define AT91_DDRSDRC_WPMR 0xE4 +/* Write protect enable */ +#define AT91_DDRSDRC_WP BIT(0) +/* Write protect key */ +#define AT91_DDRSDRC_WPKEY SHIFT_U32(0xffffff, 8) +/* Write protect key = "DDR" */ +#define AT91_DDRSDRC_KEY SHIFT_U32(0x444452, 8) + +/* Write Protect Status Register [SAM9 Only] */ +#define AT91_DDRSDRC_WPSR 0xE8 +/* Write protect violation status */ +#define AT91_DDRSDRC_WPVS BIT(0) +/* Write protect violation source */ +#define AT91_DDRSDRC_WPVSRC SHIFT_U32(0xffff, 8) + +#endif diff --git a/optee/optee_os/core/include/drivers/scif.h b/optee/optee_os/core/include/drivers/scif.h new file mode 100644 index 0000000..fe81871 --- /dev/null +++ b/optee/optee_os/core/include/drivers/scif.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, GlobalLogic + * Copyright (c) 2017, 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 SCIF_H +#define SCIF_H + +#include +#include + +#define SCIF_REG_SIZE 0x1000 + +struct scif_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void scif_uart_init(struct scif_uart_data *pd, paddr_t base); + +#endif /* SCIF */ diff --git a/optee/optee_os/core/include/drivers/scmi-msg.h b/optee/optee_os/core/include/drivers/scmi-msg.h new file mode 100644 index 0000000..a36cc60 --- /dev/null +++ b/optee/optee_os/core/include/drivers/scmi-msg.h @@ -0,0 +1,391 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, Linaro Limited + */ + +#ifndef SCMI_MSG_H +#define SCMI_MSG_H + +#include +#include +#include +#include +#include +#include + +/* Minimum size expected for SMT based shared memory message buffers */ +#define SMT_BUF_SLOT_SIZE U(128) + +/* Standard values for SCMI voltage domain protocol configuration state */ +#define SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON U(0x7) +#define SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF U(0) + +/* A channel abstract a communication path between agent and server */ +struct scmi_msg_channel; + +/* + * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel + * + * @shm_addr: Address of the shared memory for the SCMI channel + * @shm_size: Byte size of the shared memory for the SCMI channel + * @busy: True when channel is busy, flase when channel is free + * @threaded: True is executed in a threaded context, false otherwise + */ +struct scmi_msg_channel { + struct io_pa_va shm_addr; + size_t shm_size; + bool busy; + bool threaded; +}; + +#ifdef CFG_SCMI_MSG_SMT +/* + * Initialize SMT memory buffer, called by platform at init for each + * agent channel using the SMT header format. + * This function depends on CFG_SCMI_MSG_SMT. + * + * @channel: Pointer to the channel shared memory to be initialized + */ +void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel); + +/* + * Set SMT shared buffer location + * + * @channel: SCMI channel reference + * @base: virtual address of the shared buffer or NULL to clear the reference + */ +void scmi_smt_set_shared_buffer(struct scmi_msg_channel *channel, void *base); +#else +static inline +void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel __unused) +{ + panic(); +} + +static inline +void scmi_smt_set_shared_buffer(struct scmi_msg_channel *channel __unused, + void *base __unused) +{ +} +#endif /* CFG_SCMI_MSG_SMT */ + +#ifdef CFG_SCMI_MSG_SMT_FASTCALL_ENTRY +/* + * Process SMT formatted message in a fastcall SMC execution context. + * Called by platform on SMC entry. When returning, output message is + * available in shared memory for agent to read the response. + * This function depends on CFG_SCMI_MSG_SMT_FASTCALL_ENTRY. + * + * @channel_id: SCMI channel ID the SMT belongs to + */ +void scmi_smt_fastcall_smc_entry(unsigned int channel_id); +#else +static inline void scmi_smt_fastcall_smc_entry(unsigned int channel_id __unused) +{ +} +#endif + +#ifdef CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY +/* + * Process SMT formatted message in a secure interrupt execution context. + * Called by platform interrupt handler. When returning, output message is + * available in shared memory for agent to read the response. + * This function depends on CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY. + * + * @channel_id: SCMI channel ID the SMT belongs to + */ +void scmi_smt_interrupt_entry(unsigned int channel_id); +#else +static inline void scmi_smt_interrupt_entry(unsigned int channel_id __unused) +{ +} +#endif + +#ifdef CFG_SCMI_MSG_SMT_THREAD_ENTRY +/* + * Process SMT formatted message in a TEE thread execution context. + * When returning, output message is available in shared memory for + * agent to read the response. + * This function depends on CFG_SCMI_MSG_SMT_THREAD_ENTRY. + * + * @channel_id: SCMI channel ID the SMT belongs to + */ +void scmi_smt_threaded_entry(unsigned int channel_id); +#else +static inline void scmi_smt_threaded_entry(unsigned int channel_id __unused) +{ +} +#endif + +#ifdef CFG_SCMI_MSG_SHM_MSG +/* + * Process MSG formatted message in a TEE thread execution context. + * When returning, output message is available in shared memory for + * agent to read the response. + * This function depends on CFG_SCMI_MSG_MSG_THREAD_ENTRY. + * + * @channel_id: SCMI channel ID + * @in_buf: Shared buffer storing input SCMI message + * @in_size: Byte size of @in_buf, including MSG header and message payload + * @out_buf: Shared buffer storing input SCMI message + * @out_size: [in] @out_buf max byte size + * [out] @out_buf output byte size (MSG header and message payload) + */ +TEE_Result scmi_msg_threaded_entry(unsigned int channel_id, + void *in_buf, size_t in_size, + void *out_buf, size_t *out_size); +#else +static inline TEE_Result scmi_msg_threaded_entry(unsigned int chan_id __unused, + void *in_buf __unused, + size_t in_size __unused, + void *out_buf __unused, + size_t *out_size __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +/* Platform callback functions */ + +/* + * Return the SCMI channel related to an agent + * @channel_id: SCMI channel ID + * Return a pointer to channel on success, NULL otherwise + */ +struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id); + +/* Scmi-msg uses the channel ID as handle. Must channel_id is valid */ +static inline unsigned int scmi_smt_channel_handle(unsigned int channel_id) +{ + assert(plat_scmi_get_channel(channel_id)); + + return channel_id; +} + +/* + * Return how many SCMI protocols supported by the platform + * According to the SCMI specification, this function does not target + * a specific channel ID and shall return all platform known capabilities. + */ +size_t plat_scmi_protocol_count(void); + +/* + * Get the count and list of SCMI protocols (but base) supported for an agent + * + * @channel_id: SCMI channel ID + * Return a pointer to a null terminated array supported protocol IDs. + */ +const uint8_t *plat_scmi_protocol_list(unsigned int channel_id); + +/* Get the name of the SCMI vendor for the platform */ +const char *plat_scmi_vendor_name(void); + +/* Get the name of the SCMI sub-vendor for the platform */ +const char *plat_scmi_sub_vendor_name(void); + +/* Handlers for SCMI Clock protocol services */ + +/* + * Return number of clock controllers for an agent + * @channel_id: SCMI channel ID + * Return number of clock controllers + */ +size_t plat_scmi_clock_count(unsigned int channel_id); + +/* + * Get clock controller string ID (aka name) + * @channel_id: SCMI channel ID + * @scmi_id: SCMI clock ID + * Return pointer to name or NULL + */ +const char *plat_scmi_clock_get_name(unsigned int channel_id, + unsigned int scmi_id); + +/* + * Get clock possible rate as an array of frequencies in Hertz. + * + * @channel_id: SCMI channel ID + * @scmi_id: SCMI clock ID + * @start_index: Requested start index for the exposed rates array + * @rates: Output rates array or NULL if only querying @nb_elts + * @nb_elts: [in] Array size of @rates, [out] Number of rates loaded in @rates + * Return an SCMI compliant error code + */ +int32_t plat_scmi_clock_rates_array(unsigned int channel_id, + unsigned int scmi_id, size_t start_index, + unsigned long *rates, size_t *nb_elts); + +/* + * Get clock possible rate as range with regular steps in Hertz + * + * @channel_id: SCMI channel ID + * @scmi_id: SCMI clock ID + * @min_max_step: 3 cell array for min, max and step rate data + * Return an SCMI compliant error code + */ +int32_t plat_scmi_clock_rates_by_step(unsigned int channel_id, + unsigned int scmi_id, + unsigned long *min_max_step); + +/* + * Get clock rate in Hertz + * @channel_id: SCMI channel ID + * @scmi_id: SCMI clock ID + * Return clock rate or 0 if not supported + */ +unsigned long plat_scmi_clock_get_rate(unsigned int channel_id, + unsigned int scmi_id); + +/* + * Set clock rate in Hertz + * @channel_id: SCMI channel ID + * @scmi_id: SCMI clock ID + * @rate: Target clock frequency in Hertz + * Return a compliant SCMI error code + */ +int32_t plat_scmi_clock_set_rate(unsigned int channel_id, unsigned int scmi_id, + unsigned long rate); + +/* + * Get clock state (enabled or disabled) + * @channel_id: SCMI channel ID + * @scmi_id: SCMI clock ID + * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code + */ +int32_t plat_scmi_clock_get_state(unsigned int channel_id, + unsigned int scmi_id); + +/* + * Get clock state (enabled or disabled) + * @channel_id: SCMI channel ID + * @scmi_id: SCMI clock ID + * @enable_not_disable: Enable clock if true, disable clock otherwise + * Return a compliant SCMI error code + */ +int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id, + bool enable_not_disable); + +/* Handlers for SCMI Reset Domain protocol services */ + +/* + * Return number of reset domains for the agent + * @channel_id: SCMI channel ID + * Return number of reset domains + */ +size_t plat_scmi_rd_count(unsigned int channel_id); + +/* + * Get reset domain string ID (aka name) + * @channel_id: SCMI channel ID + * @scmi_id: SCMI reset domain ID + * Return pointer to name or NULL + */ +const char *plat_scmi_rd_get_name(unsigned int channel_id, + unsigned int scmi_id); + +/* + * Perform a reset cycle on a target reset domain + * @channel_id: SCMI channel ID + * @scmi_id: SCMI reset domain ID + * @state: Target reset state (see SCMI specification, 0 means context loss) + * Return a compliant SCMI error code + */ +int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id, + unsigned int state); + +/* + * Assert or deassert target reset domain + * @channel_id: SCMI channel ID + * @scmi_id: SCMI reset domain ID + * @assert_not_deassert: Assert domain if true, otherwise deassert domain + * Return a compliant SCMI error code + */ +int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id, + bool assert_not_deassert); + +/* Handlers for SCMI Voltage Domain protocol services */ + +/* + * Return number of voltage domain for an agent + * @channel_id: SCMI channel ID + * Return number of voltage domains + */ +size_t plat_scmi_voltd_count(unsigned int channel_id); + +/* + * Get clock controller string ID (aka name) + * @channel_id: SCMI channel ID + * @scmi_id: SCMI voltage domain ID + * Return pointer to name or NULL + */ +const char *plat_scmi_voltd_get_name(unsigned int channel_id, + unsigned int scmi_id); + +/* + * Get voltage domain possible levels as an array of voltages in microvolt. + * + * @channel_id: SCMI channel ID + * @scmi_id: SCMI voltage domain ID + * @start_index: Level index to start from. + * @levels: If NULL, function returns, else output rates array + * @nb_elts: Array size of @levels. + * Return an SCMI compliant error code + */ +int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, + unsigned int scmi_id, size_t start_index, + long *levels, size_t *nb_elts); + +/* + * Get voltage domain possible levels as range with regular steps in microvolt + * + * @channel_id: SCMI channel ID + * @scmi_id: SCMI voltage domain ID + * @min_max_step: 3 cell array for min, max and step voltage data + * Return an SCMI compliant error code + */ +int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, + unsigned int scmi_id, + long *min_max_step); + +/* + * Get current voltage domain level in microvolt + * @channel_id: SCMI channel ID + * @scmi_id: SCMI voltage domain ID + * @level: Out parameter for the current voltage level + * Return an SCMI compliant error code + */ +int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id, + long *level); + +/* + * Set voltage domain level voltage domain + * @channel_id: SCMI channel ID + * @scmi_id: SCMI clock ID + * @level: Target voltage domain level in microvolt + * Return a compliant SCMI error code + */ +int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, + long level); + +/* + * Get voltage domain state configuration (enabled or disabled) + * @channel_id: SCMI channel ID + * @scmi_id: SCMI voltage domain ID + * @config: output state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_* + * Return a compliant SCMI error code + */ +int32_t plat_scmi_voltd_get_config(unsigned int channel_id, + unsigned int scmi_id, uint32_t *config); + +/* + * Get voltage domain state configuration (enabled or disabled) + * @channel_id: SCMI channel ID + * @scmi_id: SCMI voltage domain ID + * @config: Target state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_* + * Return a compliant SCMI error code + */ +int32_t plat_scmi_voltd_set_config(unsigned int channel_id, + unsigned int scmi_id, uint32_t config); + +#endif /* SCMI_MSG_H */ diff --git a/optee/optee_os/core/include/drivers/scmi.h b/optee/optee_os/core/include/drivers/scmi.h new file mode 100644 index 0000000..9497206 --- /dev/null +++ b/optee/optee_os/core/include/drivers/scmi.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + */ +#ifndef SCMI_MSG_SCMI_H +#define SCMI_MSG_SCMI_H + +#define SCMI_PROTOCOL_ID_BASE 0x10 +#define SCMI_PROTOCOL_ID_POWER_DOMAIN 0x11 +#define SCMI_PROTOCOL_ID_SYS_POWER 0x12 +#define SCMI_PROTOCOL_ID_PERF 0x13 +#define SCMI_PROTOCOL_ID_CLOCK 0x14 +#define SCMI_PROTOCOL_ID_SENSOR 0x15 +#define SCMI_PROTOCOL_ID_RESET_DOMAIN 0x16 +#define SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN 0x17 + +/* SCMI error codes reported to agent through server-to-agent messages */ +#define SCMI_SUCCESS 0 +#define SCMI_NOT_SUPPORTED (-1) +#define SCMI_INVALID_PARAMETERS (-2) +#define SCMI_DENIED (-3) +#define SCMI_NOT_FOUND (-4) +#define SCMI_OUT_OF_RANGE (-5) +#define SCMI_BUSY (-6) +#define SCMI_COMMS_ERROR (-7) +#define SCMI_GENERIC_ERROR (-8) +#define SCMI_HARDWARE_ERROR (-9) +#define SCMI_PROTOCOL_ERROR (-10) + +#endif /* SCMI_MSG_SCMI_H */ diff --git a/optee/optee_os/core/include/drivers/serial.h b/optee/optee_os/core/include/drivers/serial.h new file mode 100644 index 0000000..4c2f964 --- /dev/null +++ b/optee/optee_os/core/include/drivers/serial.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ +#ifndef __DRIVERS_SERIAL_H +#define __DRIVERS_SERIAL_H + +#include +#include +#include +#include +#include + +struct serial_chip { + const struct serial_ops *ops; +}; + +struct serial_ops { + /* Mandatory handler */ + void (*putc)(struct serial_chip *chip, int ch); + /* Optional handlers */ + void (*flush)(struct serial_chip *chip); + bool (*have_rx_data)(struct serial_chip *chip); + int (*getchar)(struct serial_chip *chip); +}; + +struct serial_driver { + /* Allocate device data and return the inner serial_chip */ + struct serial_chip *(*dev_alloc)(void); + /* + * Initialize device from FDT node. @parms is device-specific, + * its meaning is as defined by the DT bindings for the characters + * following the ":" in /chosen/stdout-path. Typically for UART + * devices this is {{{}}} where: + * baud - baud rate in decimal + * parity - 'n' (none), 'o', (odd) or 'e' (even) + * bits - number of data bits + * flow - 'r' (rts) + * For example: 115200n8r + */ + int (*dev_init)(struct serial_chip *dev, const void *fdt, + int offset, const char *parms); + void (*dev_free)(struct serial_chip *dev); +}; + +#endif /*__DRIVERS_SERIASERIAL_H*/ diff --git a/optee/optee_os/core/include/drivers/serial8250_uart.h b/optee/optee_os/core/include/drivers/serial8250_uart.h new file mode 100644 index 0000000..40816c9 --- /dev/null +++ b/optee/optee_os/core/include/drivers/serial8250_uart.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef SERIAL8250_UART_H +#define SERIAL8250_UART_H + +#include +#include + +#define SERIAL8250_UART_REG_SIZE 0x20 + +struct serial8250_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base, + uint32_t uart_clk, uint32_t baud_rate); + +#endif /* SERIAL8250_UART_H */ + diff --git a/optee/optee_os/core/include/drivers/sp805_wdt.h b/optee/optee_os/core/include/drivers/sp805_wdt.h new file mode 100644 index 0000000..0d5d313 --- /dev/null +++ b/optee/optee_os/core/include/drivers/sp805_wdt.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef SP805_WDT_H +#define SP805_WDT_H + +#include +#include +#include +#include + +/* SP805 register offset */ +#define WDT_LOAD_OFFSET 0x000 +#define WDT_CONTROL_OFFSET 0x008 +#define WDT_INTCLR_OFFSET 0x00c +#define WDT_LOCK_OFFSET 0xc00 +#define WDT_SIZE 0xc04 + +/* Magic word to unlock the wd registers */ +#define WDT_UNLOCK_KEY 0x1ACCE551 +#define WDT_LOCK_KEY 0x1 + +/* Register field definitions */ +#define WDT_INT_EN BIT(0) +#define WDT_RESET_EN BIT(1) +#define WDT_INT_CLR BIT(0) + +#define WDT_LOAD_MIN 0x1 + +typedef void (*sp805_itr_handler_func_t)(struct wdt_chip *chip); + +struct sp805_wdt_data { + struct io_pa_va base; + struct wdt_chip chip; + uint32_t clk_rate; + uint32_t load_val; + uint32_t itr_num; + sp805_itr_handler_func_t itr_handler; +}; + +/* + * Initialize sp805 watchdog timer + * + * @pd: allocated sp805 watchdog timer platform data + * @base: physical base address of sp805 watchdog timer + * @clk_rate: rate of the clock driving the watchdog timer hardware + * @timeout: watchdog timer timeout in seconds + * Return a TEE_Result compliant status + */ +TEE_Result sp805_wdt_init(struct sp805_wdt_data *pd, paddr_t base, + uint32_t clk_rate, uint32_t timeout); + +/* + * Optionally register sp805 watchdog timer interrupt handler + * + * @pd: platform data of sp805 watchdog timer for which interrupt handler + * is to be registered + * @itr_num: sp805 watchdog timer interrupt id + * @itr_flag: interrupt attributes + * @itr_handler: Optional interrupt handler callback + * Return a TEE_Result compliant status + */ +TEE_Result sp805_register_itr_handler(struct sp805_wdt_data *pd, + uint32_t itr_num, uint32_t itr_flag, + sp805_itr_handler_func_t itr_handler); + +#endif /* SP805_WDT_H */ diff --git a/optee/optee_os/core/include/drivers/sprd_uart.h b/optee/optee_os/core/include/drivers/sprd_uart.h new file mode 100644 index 0000000..6482622 --- /dev/null +++ b/optee/optee_os/core/include/drivers/sprd_uart.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Spreadtrum Communications Inc. + * Copyright (c) 2017, 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 SPRD_UART_H +#define SPRD_UART_H + +#include +#include + +struct sprd_uart_data { + struct io_pa_va base; + struct serial_chip chip; +}; + +void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base); + +#endif /* SPRD_UART_H */ + diff --git a/optee/optee_os/core/include/drivers/stih_asc.h b/optee/optee_os/core/include/drivers/stih_asc.h new file mode 100644 index 0000000..21e8297 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stih_asc.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ +#ifndef STIH_ASC_H +#define STIH_ASC_H + +#include +#include + +#define STIH_ASC_REG_SIZE 0x1000 + +struct stih_asc_pd { + struct io_pa_va base; + struct serial_chip chip; +}; + +void stih_asc_init(struct stih_asc_pd *pb, vaddr_t base); + +#endif /* STIH_ASC_H */ + diff --git a/optee/optee_os/core/include/drivers/stm32_bsec.h b/optee/optee_os/core/include/drivers/stm32_bsec.h new file mode 100644 index 0000000..1f95a54 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_bsec.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2017-2022, STMicroelectronics + */ + +#ifndef __STM32_BSEC_H +#define __STM32_BSEC_H + +#include +#include +#include + +/* BSEC_DEBUG */ +#define BSEC_HDPEN BIT(4) +#define BSEC_SPIDEN BIT(5) +#define BSEC_SPINDEN BIT(6) +#define BSEC_DBGSWGEN BIT(10) +#define BSEC_DEBUG_ALL (BSEC_HDPEN | \ + BSEC_SPIDEN | \ + BSEC_SPINDEN | \ + BSEC_DBGSWGEN) + +#define BSEC_BITS_PER_WORD (8U * sizeof(uint32_t)) +#define BSEC_BYTES_PER_WORD sizeof(uint32_t) + +/* BSEC different global states */ +enum stm32_bsec_sec_state { + BSEC_STATE_SEC_CLOSED, + BSEC_STATE_SEC_OPEN, + BSEC_STATE_INVALID +}; + +/* + * Load OTP from SAFMEM and provide its value + * @value: Output read value + * @otp_id: OTP number + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_shadow_read_otp(uint32_t *value, uint32_t otp_id); + +/* + * Copy SAFMEM OTP to BSEC data. + * @otp_id: OTP number. + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_shadow_register(uint32_t otp_id); + +/* + * Read an OTP data value + * @value: Output read value + * @otp_id: OTP number + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_read_otp(uint32_t *value, uint32_t otp_id); + +/* + * Write value in BSEC data register + * @value: Value to write + * @otp_id: OTP number + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_write_otp(uint32_t value, uint32_t otp_id); + +/* + * Program a bit in SAFMEM without BSEC data refresh + * @value: Value to program. + * @otp_id: OTP number. + * Return a TEE_Result compliant return value + */ +#ifdef CFG_STM32_BSEC_WRITE +TEE_Result stm32_bsec_program_otp(uint32_t value, uint32_t otp_id); +#else +static inline TEE_Result stm32_bsec_program_otp(uint32_t value __unused, + uint32_t otp_id __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +/* + * Permanent lock of OTP in SAFMEM + * @otp_id: OTP number + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_permanent_lock_otp(uint32_t otp_id); + +/* + * Enable/disable debug service + * @value: Value to write + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_write_debug_conf(uint32_t value); + +/* Return debug configuration read from BSEC */ +uint32_t stm32_bsec_read_debug_conf(void); + +/* + * Write shadow-read lock + * @otp_id: OTP number + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_set_sr_lock(uint32_t otp_id); + +/* + * Read shadow-read lock + * @otp_id: OTP number + * @locked: (out) true if shadow-read is locked, false if not locked. + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_read_sr_lock(uint32_t otp_id, bool *locked); + +/* + * Write shadow-write lock + * @otp_id: OTP number + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_set_sw_lock(uint32_t otp_id); + +/* + * Read shadow-write lock + * @otp_id: OTP number + * @locked: (out) true if shadow-write is locked, false if not locked. + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_read_sw_lock(uint32_t otp_id, bool *locked); + +/* + * Write shadow-program lock + * @otp_id: OTP number + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_set_sp_lock(uint32_t otp_id); + +/* + * Read shadow-program lock + * @otp_id: OTP number + * @locked: (out) true if shadow-program is locked, false if not locked. + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_read_sp_lock(uint32_t otp_id, bool *locked); + +/* + * Read permanent lock status + * @otp_id: OTP number + * @locked: (out) true if permanent lock is locked, false if not locked. + * Return a TEE_Result compliant return value + */ +TEE_Result stm32_bsec_read_permanent_lock(uint32_t otp_id, bool *locked); + +/* + * Return true if OTP can be read, false otherwise + * @otp_id: OTP number + */ +bool stm32_bsec_can_access_otp(uint32_t otp_id); + +/* + * Return true if non-secure world is allowed to read the target OTP + * @otp_id: OTP number + */ +bool stm32_bsec_nsec_can_access_otp(uint32_t otp_id); + +/* + * Find and get OTP location from its name. + * @name: sub-node name to look up. + * @otp_id: pointer to output OTP number or NULL. + * @otp_bit_len: pointer to output OTP length in bits or NULL. + * Return a TEE_Result compliant status + */ +TEE_Result stm32_bsec_find_otp_in_nvmem_layout(const char *name, + uint32_t *otp_id, + size_t *otp_bit_len); + +/* + * Get BSEC global sec state. + * @sec_state: Global BSEC current sec state + * Return a TEE_Result compliant status + */ +TEE_Result stm32_bsec_get_state(enum stm32_bsec_sec_state *sec_state); + +#endif /*__STM32_BSEC_H*/ diff --git a/optee/optee_os/core/include/drivers/stm32_etzpc.h b/optee/optee_os/core/include/drivers/stm32_etzpc.h new file mode 100644 index 0000000..50bbc40 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_etzpc.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2019, STMicroelectronics + */ + +#ifndef __STM32_ETZPC_H__ +#define __STM32_ETZPC_H__ + +#include +#include + +enum etzpc_decprot_attributes { + ETZPC_DECPROT_S_RW = 0, + ETZPC_DECPROT_NS_R_S_W = 1, + ETZPC_DECPROT_MCU_ISOLATION = 2, + ETZPC_DECPROT_NS_RW = 3, + ETZPC_DECPROT_MAX = 4, +}; + +#define ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0) +#define ETZPC_TZMA_ALL_NO_SECURE 0x0 + +/* + * Load a DECPROT configuration + * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface + * @decprot_attr: Restriction access attributes + */ +void etzpc_configure_decprot(uint32_t decprot_id, + enum etzpc_decprot_attributes decprot_attr); + +/* + * Get the DECPROT attribute + * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface + * Return attribute of this DECPROT + */ +enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id); + +/* + * Lock access to the DECPROT attributes + * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface + */ +void etzpc_lock_decprot(uint32_t decprot_id); + +/* + * Return the lock status of the target DECPROT + * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface + */ +bool etzpc_get_lock_decprot(uint32_t decprot_id); + +/* + * Configure the target TZMA read only size + * @tzma_id: ID that is the index of the TZMA in the ETZPC interface + * @tzma_value: Read-only size + */ +void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value); + +/* + * Get the target TZMA read only size + * @tzma_id: ID that is the index of the TZMA in the ETZPC interface + * Return the size of read-only area + */ +uint16_t etzpc_get_tzma(uint32_t tzma_id); + +/* + * Lock the target TZMA + * @tzma_id: ID that is the index of the TZMA in the ETZPC interface + */ +void etzpc_lock_tzma(uint32_t tzma_id); + +/* + * Return the lock status of the target TZMA + * @tzma_id: ID that is the index of the TZMA in the ETZPC interface + * Return true if TZMA is locked, false otherwise + */ +bool etzpc_get_lock_tzma(uint32_t tzma_id); + +/* + * Init the ETZPC device, nedded when not using the device tree + * @base: ETZPC interface registers physcal base address + */ +#ifdef CFG_STM32_ETZPC +void stm32_etzpc_init(paddr_t base); +#else +static inline void stm32_etzpc_init(paddr_t __unused base) {} +#endif + +#endif /*__STM32_ETZPC_H__*/ diff --git a/optee/optee_os/core/include/drivers/stm32_gpio.h b/optee/optee_os/core/include/drivers/stm32_gpio.h new file mode 100644 index 0000000..7ab12f9 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_gpio.h @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2017-2019, STMicroelectronics + * + * STM32 GPIO driver relies on platform util fiunctions to get base address + * and clock ID of the GPIO banks. The drvier API allows to retrieve pin muxing + * configuration for given nodes and load them at runtime. A pin control + * instance provide an active and a standby configuration. Pin onwer is + * responsible to load to expected configuration during PM state transitions + * as STM32 GPIO driver does no register callbacks to the PM framework. + */ + +#ifndef __STM32_GPIO_H +#define __STM32_GPIO_H + +#include +#include +#include +#include + +#define GPIO_MODE_INPUT 0x0 +#define GPIO_MODE_OUTPUT 0x1 +#define GPIO_MODE_ALTERNATE 0x2 +#define GPIO_MODE_ANALOG 0x3 + +#define GPIO_OTYPE_PUSH_PULL 0x0 +#define GPIO_OTYPE_OPEN_DRAIN 0x1 + +#define GPIO_OSPEED_LOW 0x0 +#define GPIO_OSPEED_MEDIUM 0x1 +#define GPIO_OSPEED_HIGH 0x2 +#define GPIO_OSPEED_VERY_HIGH 0x3 + +#define GPIO_PUPD_NO_PULL 0x0 +#define GPIO_PUPD_PULL_UP 0x1 +#define GPIO_PUPD_PULL_DOWN 0x2 + +#define GPIO_OD_LEVEL_LOW 0x0 +#define GPIO_OD_LEVEL_HIGH 0x1 + +/* + * GPIO configuration description structured as single 16bit word + * for efficient save/restore when GPIO pin suspends or resumes. + * + * @mode: One of GPIO_MODE_* + * @otype: One of GPIO_OTYPE_* + * @ospeed: One of GPIO_OSPEED_* + * @pupd: One of GPIO_PUPD_* + * @od: One of GPIO_OD_* + * @af: Alternate function numerical ID between 0 and 15 + */ +struct gpio_cfg { + uint16_t mode: 2; + uint16_t otype: 1; + uint16_t ospeed: 2; + uint16_t pupd: 2; + uint16_t od: 1; + uint16_t af: 4; +}; + +/* + * Descrption of a pin and its 2 states muxing + * + * @bank: GPIO bank identifier as assigned by the platform + * @pin: Pin number in the GPIO bank + * @active_cfg: Configuration in active state + * @standby_cfg: Configuration in standby state + */ +struct stm32_pinctrl { + uint8_t bank; + uint8_t pin; + struct gpio_cfg active_cfg; + struct gpio_cfg standby_cfg; +}; + +/* + * Apply series of pin muxing configuration, active state and standby state + * + * @pinctrl: array of pinctrl references + * @count: Number of entries in @pinctrl + */ +void stm32_pinctrl_load_active_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); +void stm32_pinctrl_load_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); + +/* + * Save the current pin configuration as the standby state for a pin series + * + * @pinctrl: array of pinctrl references + * @count: Number of entries in @pinctrl + */ +void stm32_pinctrl_store_standby_cfg(struct stm32_pinctrl *pinctrl, size_t cnt); + +/* + * Save pinctrl instances defined in DT node: identifiers and power states + * + * @fdt: device tree + * @node: device node in the device tree + * @pinctrl: NULL or pointer to array of struct stm32_pinctrl + * @count: number of elements pointed by argument cfg + * + * Return the number of pinctrl instances found or a negative value on error. + * + * When @count is 0, @pinctrl may be NULL. The function will return only the + * number of pinctrl instances found in the device tree for the target + * device node. + * + * If more instances than @count are found then the function returns the + * effective number of pincltr instance found in the node but fills + * output array @pinctrl only for the input @count first entries. + */ +int stm32_pinctrl_fdt_get_pinctrl(void *fdt, int node, + struct stm32_pinctrl *pinctrl, size_t count); + +/* + * Set target output GPIO pin to high or low level + * + * @bank: GPIO bank identifier as assigned by the platform + * @pin: GPIO pin position in the GPIO bank + * @high: 1 to set GPIO to high level, 0 to set to GPIO low level + */ +void stm32_gpio_set_output_level(unsigned int bank, unsigned int pin, int high); + +/* + * Set output GPIO pin referenced by @pinctrl to high or low level + * + * @pinctrl: Reference to pinctrl + * @high: 1 to set GPIO to high level, 0 to set to GPIO low level + */ +static inline void stm32_pinctrl_set_gpio_level(struct stm32_pinctrl *pinctrl, + int high) +{ + stm32_gpio_set_output_level(pinctrl->bank, pinctrl->pin, high); +} + +/* + * Get input GPIO pin current level, high or low + * + * @bank: GPIO bank identifier as assigned by the platform + * @pin: GPIO pin position in the GPIO bank + * Return 1 if GPIO level is high, 0 if it is low + */ +int stm32_gpio_get_input_level(unsigned int bank, unsigned int pin); + +/* + * Set target output GPIO pin to high or low level + * + * @pinctrl: Reference to pinctrl + * Return 1 if GPIO level is high, 0 if it is low + */ +static inline int stm32_pinctrl_get_gpio_level(struct stm32_pinctrl *pinctrl) +{ + return stm32_gpio_get_input_level(pinctrl->bank, pinctrl->pin); +} + +#ifdef CFG_STM32_GPIO +/* + * Configure pin muxing access permission: can be secure or not + * + * @bank: GPIO bank identifier as assigned by the platform + * @pin: Pin number in the GPIO bank + * @secure: True if pin is secure, false otherwise + */ +void stm32_gpio_set_secure_cfg(unsigned int bank, unsigned int pin, + bool secure); +#else +static inline void stm32_gpio_set_secure_cfg(unsigned int bank __unused, + unsigned int pin __unused, + bool secure __unused) +{ + assert(0); +} +#endif + +/* + * Get the number of GPIO pins supported by a target GPIO bank + * + * @fdt: device tree reference + * @pinctrl_node: pinctrl node which GPIO bank node belongs to + * @bank: target GPIO bank ID + * Return number of GPIO pins (>= 0) or a negative value on error + */ +int stm32_get_gpio_count(void *fdt, int pinctrl_node, unsigned int bank); + +#endif /*__STM32_GPIO_H*/ diff --git a/optee/optee_os/core/include/drivers/stm32_i2c.h b/optee/optee_os/core/include/drivers/stm32_i2c.h new file mode 100644 index 0000000..39b3244 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_i2c.h @@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Copyright (c) 2017-2019, STMicroelectronics + */ + +#ifndef __STM32_I2C_H +#define __STM32_I2C_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * I2C specification values as per version 6.0, 4th of April 2014 [1], + * table 10 page 48: Characteristics of the SDA and SCL bus lines for + * Standard, Fast, and Fast-mode Plus I2C-bus devices. + * + * [1] https://www.nxp.com/docs/en/user-guide/UM10204.pdf + */ +#define I2C_STANDARD_RATE U(100000) +#define I2C_FAST_RATE U(400000) +#define I2C_FAST_PLUS_RATE U(1000000) + +/* + * Initialization configuration structure for the STM32 I2C bus. + * Refer to the SoC Reference Manual for more details on configuration items. + * + * @dt_status: non-secure/secure status read from DT + * @pbase: I2C interface base address + * @reg_size: I2C interface register map size + * @clock: I2C bus/interface clock + * @addr_mode_10b_not_7b: True if 10bit addressing mode, otherwise 7bit mode + * @own_address1: 7-bit or 10-bit first device own address. + * @dual_address_mode: True if enabling Dual-Addressing mode + * @own_address2: 7-bit second device own address (Dual-Addressing mode) + * @own_address2_masks: Acknowledge mask address (Dual-Addressing mode) + * @general_call_mode: True if enbling General-Call mode + * @no_stretch_mode: If enabling the No-Stretch mode + * @rise_time: SCL clock pin rising time in nanoseconds + * @fall_time: SCL clock pin falling time in nanoseconds + * @bus_rate: Specifies the I2C clock frequency in Hertz + * @analog_filter: True if enabling analog filter + * @digital_filter_coef: filter coef (below STM32_I2C_DIGITAL_FILTER_MAX) + */ +struct stm32_i2c_init_s { + unsigned int dt_status; + paddr_t pbase; + size_t reg_size; + struct clk *clock; + bool addr_mode_10b_not_7b; + uint32_t own_address1; + bool dual_address_mode; + uint32_t own_address2; + uint32_t own_address2_masks; + bool general_call_mode; + bool no_stretch_mode; + uint32_t rise_time; + uint32_t fall_time; + uint32_t bus_rate; + bool analog_filter; + uint8_t digital_filter_coef; +}; + +enum i2c_state_e { + I2C_STATE_RESET, /* Not yet initialized */ + I2C_STATE_READY, /* Ready for use */ + I2C_STATE_BUSY, /* Internal process ongoing */ + I2C_STATE_BUSY_TX, /* Data Transmission ongoing */ + I2C_STATE_BUSY_RX, /* Data Reception ongoing */ + I2C_STATE_SUSPENDED, /* Bus is supended */ +}; + +enum i2c_mode_e { + I2C_MODE_NONE, /* No active communication */ + I2C_MODE_MASTER, /* Communication in Master Mode */ + I2C_MODE_SLAVE, /* Communication in Slave Mode */ + I2C_MODE_MEM, /* Communication in Memory Mode */ +}; + +#define I2C_ERROR_NONE U(0x0) +#define I2C_ERROR_BERR BIT(0) +#define I2C_ERROR_ARLO BIT(1) +#define I2C_ERROR_ACKF BIT(2) +#define I2C_ERROR_OVR BIT(3) +#define I2C_ERROR_DMA BIT(4) +#define I2C_ERROR_TIMEOUT BIT(5) +#define I2C_ERROR_SIZE BIT(6) + +/* I2C interface registers state */ +struct i2c_cfg { + uint32_t timingr; + uint32_t oar1; + uint32_t oar2; + uint32_t cr1; + uint32_t cr2; +}; + +/* + * I2C bus device + * @base: I2C SoC registers base address + * @reg_size: I2C SoC registers address map size + * @dt_status: non-secure/secure status read from DT + * @clock: clock ID + * @i2c_state: Driver state ID I2C_STATE_* + * @i2c_err: Last error code I2C_ERROR_* + * @saved_timing: Saved timing value if already computed + * @saved_frequency: Saved frequency value if already computed + * @sec_cfg: I2C registers configuration storage + * @pinctrl: PINCTRLs configuration for the I2C PINs + * @pinctrl_count: Number of PINCTRLs elements + */ +struct i2c_handle_s { + struct io_pa_va base; + size_t reg_size; + unsigned int dt_status; + struct clk *clock; + enum i2c_state_e i2c_state; + uint32_t i2c_err; + uint32_t saved_timing; + unsigned long saved_frequency; + struct i2c_cfg sec_cfg; + struct stm32_pinctrl *pinctrl; + size_t pinctrl_count; +}; + +/* STM32 specific defines */ +#define STM32_I2C_RISE_TIME_DEFAULT U(25) /* ns */ +#define STM32_I2C_FALL_TIME_DEFAULT U(10) /* ns */ +#define STM32_I2C_ANALOG_FILTER_DELAY_MIN U(50) /* ns */ +#define STM32_I2C_ANALOG_FILTER_DELAY_MAX U(260) /* ns */ +#define STM32_I2C_DIGITAL_FILTER_MAX U(16) + +/* + * Fill struct stm32_i2c_init_s from DT content for a given I2C node + * + * @fdt: Reference to DT + * @node: Target I2C node in the DT + * @init: Output stm32_i2c_init_s structure + * @pinctrl: Reference to output pinctrl array + * @pinctrl_count: Input @pinctrl array size, output expected size upon success + * Return a TEE_Result compliant value + */ +TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init, + struct stm32_pinctrl **pinctrl, + size_t *pinctrl_count); + +/* + * Initialize I2C bus handle from input configuration directives + * + * @hi2c: Reference to I2C bus handle structure + * @init_data: Input stm32_i2c_init_s structure + * Return 0 on success else a negative value + */ +int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data); + +/* + * Send a memory write request in the I2C bus + * + * @hi2c: Reference to I2C bus handle structure + * @dev_addr: Target device I2C address + * @mem_addr: Target device memory address + * @mem_addr_size: Byte size of internal memory address + * @p_data: Data to be written + * @size: Byte size of the data to be written + * @timeout_ms: Timeout value in milliseconds + * Return 0 on success else a negative value + */ +int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint32_t mem_addr, uint32_t mem_addr_size, + uint8_t *p_data, size_t size, unsigned int timeout_ms); + +/* + * Send a memory read request in the I2C bus + * + * @hi2c: Reference to I2C bus handle structure + * @dev_addr: Target device I2C address + * @mem_addr: Target device memory address + * @mem_addr_size: Byte size of internal memory address + * @p_data: Data to be read + * @size: Byte size of the data to be read + * @timeout_ms: Timeout value in milliseconds + * Return 0 on success else a negative value + */ +int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint32_t mem_addr, uint32_t mem_addr_size, + uint8_t *p_data, size_t size, unsigned int timeout_ms); + +/* + * Send a data buffer in master mode on the I2C bus + * + * @hi2c: Reference to I2C bus handle structure + * @dev_addr: Target device I2C address + * @p_data: Data to be sent + * @size: Byte size of the data to be sent + * @timeout_ms: Timeout value in milliseconds + * Return 0 on success else a negative value + */ +int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint8_t *p_data, size_t size, + unsigned int timeout_ms); + +/* + * Receive a data buffer in master mode on the I2C bus + * + * @hi2c: Reference to I2C bus handle structure + * @dev_addr: Target device I2C address + * @p_data: Buffer for the received data + * @size: Byte size of the data to be received + * @timeout_ms: Timeout value in milliseconds + * Return 0 on success else a negative value + */ +int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint32_t dev_addr, + uint8_t *p_data, size_t size, + unsigned int timeout_ms); + +/* + * Optimized 1 byte read/write function for unpaged sequences. + * 8-bit addressing mode / single byte transferred / use default I2C timeout. + * Return 0 on success else a negative value + */ +int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr, + unsigned int mem_addr, uint8_t *p_data, + bool write); + +/* + * Check link with the I2C device + * + * @hi2c: Reference to I2C bus handle structure + * @dev_addr: Target device I2C address + * @trials: Number of attempts of I2C request + * @timeout_ms: Timeout value in milliseconds for each I2C request + * Return 0 on success else a negative value + */ +bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint32_t dev_addr, + unsigned int trials, unsigned int timeout_ms); + +/* + * Suspend I2C bus. + * Bus owner is reponsible for calling stm32_i2c_suspend(). + * + * @hi2c: Reference to I2C bus handle structure + */ +void stm32_i2c_suspend(struct i2c_handle_s *hi2c); + +/* + * Resume I2C bus. + * Bus owner is reponsible for calling stm32_i2c_resume(). + * + * @hi2c: Reference to I2C bus handle structure + */ +void stm32_i2c_resume(struct i2c_handle_s *hi2c); + +/* + * Return true if I2C bus is enabled for secure world only, false otherwise + */ +static inline bool i2c_is_secure(struct i2c_handle_s *hi2c) +{ + return hi2c->dt_status == DT_STATUS_OK_SEC; +} + +#endif /* __STM32_I2C_H */ diff --git a/optee/optee_os/core/include/drivers/stm32_iwdg.h b/optee/optee_os/core/include/drivers/stm32_iwdg.h new file mode 100644 index 0000000..f1ad734 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_iwdg.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved + */ + +#ifndef DRIVERS_STM32_IWDG_H +#define DRIVERS_STM32_IWDG_H + +#include + +/* + * struct stm32_iwdg_otp_data - Fuses configuration related to an IWDG + * @hw_enabled - IWDDG instance is enabled by early hardware boot stage + * @disable_on_stop - IWDG instance freezes when SoC is in STOP mode + * @disable_on_standby - IWDG instance freezes when SoC is in STANDBY mode + */ +struct stm32_iwdg_otp_data { + bool hw_enabled; + bool disable_on_stop; + bool disable_on_standby; +}; + +/* + * Platform shall implement this function for IWDG instance to retrieve its + * OTP/fuse configuration. + */ +TEE_Result stm32_get_iwdg_otp_config(paddr_t pbase, + struct stm32_iwdg_otp_data *otp_data); + +/* Refresh all registered IWDG watchdog instance */ +void stm32_iwdg_refresh(void); + +#endif /*DRIVERS_STM32_IWDG_H*/ diff --git a/optee/optee_os/core/include/drivers/stm32_shared_io.h b/optee/optee_os/core/include/drivers/stm32_shared_io.h new file mode 100644 index 0000000..8d39119 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_shared_io.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32_SHARED_IO_H__ +#define __DRIVERS_STM32_SHARED_IO_H__ + +#include +#include + +/* + * Shared registers support: common lock for accessing SoC registers + * shared between several drivers. + */ +void io_clrsetbits32_stm32shregs(vaddr_t va, uint32_t clr, uint32_t set); +void io_mask32_stm32shregs(vaddr_t va, uint32_t value, uint32_t mask); + +static inline void io_setbits32_stm32shregs(vaddr_t va, uint32_t value) +{ + io_mask32_stm32shregs(va, value, value); +} + +static inline void io_clrbits32_stm32shregs(vaddr_t va, uint32_t value) +{ + io_mask32_stm32shregs(va, 0, value); +} + +#endif /* __DRIVERS_STM32_SHARED_IO_H__ */ diff --git a/optee/optee_os/core/include/drivers/stm32_tamp.h b/optee/optee_os/core/include/drivers/stm32_tamp.h new file mode 100644 index 0000000..88c8849 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_tamp.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2021-2022, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32_TAMP_H__ +#define __DRIVERS_STM32_TAMP_H__ + +#include +#include +#include + +/* + * struct stm32_bkpregs_conf - Interface for stm32_tamp_set_secure_bkpregs() + * @nb_zone1_regs - Number of backup registers in zone 1 + * @nb_zone2_regs - Number of backup registers in zone 2 + * + * TAMP backup registers access permissions + * + * Zone 1: read/write in secure state, no access in non-secure state + * Zone 2: read/write in secure state, read-only in non-secure state + * Zone 3: read/write in secure state, read/write in non-secure state + * + * Protection zone 1 + * If nb_zone1_regs == 0 no backup register are in zone 1. + * Otherwise backup registers from TAMP_BKP0R to TAMP_BKPR are in zone 1, + * with = (@nb_zone1_regs - 1). + * + * Protection zone 2 + * If nb_zone2_regs == 0 no backup register are in zone 2. + * Otherwise backup registers from TAMP_BKPR ro TAMP_BKPR are in zone 2, + * with = @nb_zone1_regs and = (@nb_zone1_regs1 + @nb_zone2_regs - 1). + * + * Protection zone 3 + * Backup registers from TAMP_BKPR to last backup register are in zone 3, + * with = (@nb_zone1_regs1 + @nb_zone2_regs). + */ +struct stm32_bkpregs_conf { + uint32_t nb_zone1_regs; + uint32_t nb_zone2_regs; +}; + +#ifdef CFG_STM32_TAMP +/* + * stm32_tamp_set_secure_bkprwregs() - Configure backup registers zone. + * @conf - Configuration to be programmed + */ +TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *conf); +#else +static inline +TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *c __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif +#endif /* __DRIVERS_STM32_TAMP_H__ */ diff --git a/optee/optee_os/core/include/drivers/stm32_uart.h b/optee/optee_os/core/include/drivers/stm32_uart.h new file mode 100644 index 0000000..021b2b9 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32_uart.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2018, STMicroelectronics + */ + +#ifndef __STM32_UART_H__ +#define __STM32_UART_H__ + +#include +#include +#include + +struct stm32_uart_pdata { + struct io_pa_va base; + struct serial_chip chip; + bool secure; + struct clk *clock; + struct stm32_pinctrl *pinctrl; + size_t pinctrl_count; +}; + +/* + * stm32_uart_init - Initialize a UART serial chip and base address + * @pd: Output initialized UART platform data + * @base: UART interface physical base address + */ +void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base); + +/* + * stm32_uart_init_from_dt_node - Initialize a UART instance from a DTB node + * @fdt: DTB base address + * @node: Target node offset in the DTB + * Returns an alloced (malloc) and inited UART platform data on success or NULL + * + * This function gets a STM32 UART configuration directives from a DTB node + * and initializes a UART driver instance. + * When the DTB specifies that the device is disabled, the function returns + * NULL. Other issues panic the sequence. + */ +struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node); + +#endif /*__STM32_UART_H__*/ diff --git a/optee/optee_os/core/include/drivers/stm32mp13_rcc.h b/optee/optee_os/core/include/drivers/stm32mp13_rcc.h new file mode 100644 index 0000000..3f76ef7 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32mp13_rcc.h @@ -0,0 +1,1879 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#ifndef __DRIVERS_STM32MP13_RCC_H__ +#define __DRIVERS_STM32MP13_RCC_H__ + +#include + +#define RCC_SECCFGR U(0x0) +#define RCC_MP_SREQSETR U(0x100) +#define RCC_MP_SREQCLRR U(0x104) +#define RCC_MP_APRSTCR U(0x108) +#define RCC_MP_APRSTSR U(0x10C) +#define RCC_PWRLPDLYCR U(0x110) +#define RCC_MP_GRSTCSETR U(0x114) +#define RCC_BR_RSTSCLRR U(0x118) +#define RCC_MP_RSTSSETR U(0x11C) +#define RCC_MP_RSTSCLRR U(0x120) +#define RCC_MP_IWDGFZSETR U(0x124) +#define RCC_MP_IWDGFZCLRR U(0x128) +#define RCC_MP_CIER U(0x200) +#define RCC_MP_CIFR U(0x204) +#define RCC_BDCR U(0x400) +#define RCC_RDLSICR U(0x404) +#define RCC_OCENSETR U(0x420) +#define RCC_OCENCLRR U(0x424) +#define RCC_OCRDYR U(0x428) +#define RCC_HSICFGR U(0x440) +#define RCC_CSICFGR U(0x444) +#define RCC_MCO1CFGR U(0x460) +#define RCC_MCO2CFGR U(0x464) +#define RCC_DBGCFGR U(0x468) +#define RCC_RCK12SELR U(0x480) +#define RCC_RCK3SELR U(0x484) +#define RCC_RCK4SELR U(0x488) +#define RCC_PLL1CR U(0x4A0) +#define RCC_PLL1CFGR1 U(0x4A4) +#define RCC_PLL1CFGR2 U(0x4A8) +#define RCC_PLL1FRACR U(0x4AC) +#define RCC_PLL1CSGR U(0x4B0) +#define RCC_PLL2CR U(0x4D0) +#define RCC_PLL2CFGR1 U(0x4D4) +#define RCC_PLL2CFGR2 U(0x4D8) +#define RCC_PLL2FRACR U(0x4DC) +#define RCC_PLL2CSGR U(0x4E0) +#define RCC_PLL3CR U(0x500) +#define RCC_PLL3CFGR1 U(0x504) +#define RCC_PLL3CFGR2 U(0x508) +#define RCC_PLL3FRACR U(0x50C) +#define RCC_PLL3CSGR U(0x510) +#define RCC_PLL4CR U(0x520) +#define RCC_PLL4CFGR1 U(0x524) +#define RCC_PLL4CFGR2 U(0x528) +#define RCC_PLL4FRACR U(0x52C) +#define RCC_PLL4CSGR U(0x530) +#define RCC_MPCKSELR U(0x540) +#define RCC_ASSCKSELR U(0x544) +#define RCC_MSSCKSELR U(0x548) +#define RCC_CPERCKSELR U(0x54C) +#define RCC_RTCDIVR U(0x560) +#define RCC_MPCKDIVR U(0x564) +#define RCC_AXIDIVR U(0x568) +#define RCC_MLAHBDIVR U(0x56C) +#define RCC_APB1DIVR U(0x570) +#define RCC_APB2DIVR U(0x574) +#define RCC_APB3DIVR U(0x578) +#define RCC_APB4DIVR U(0x57C) +#define RCC_APB5DIVR U(0x580) +#define RCC_APB6DIVR U(0x584) +#define RCC_TIMG1PRER U(0x5A0) +#define RCC_TIMG2PRER U(0x5A4) +#define RCC_TIMG3PRER U(0x5A8) +#define RCC_DDRITFCR U(0x5C0) +#define RCC_I2C12CKSELR U(0x600) +#define RCC_I2C345CKSELR U(0x604) +#define RCC_SPI2S1CKSELR U(0x608) +#define RCC_SPI2S23CKSELR U(0x60C) +#define RCC_SPI45CKSELR U(0x610) +#define RCC_UART12CKSELR U(0x614) +#define RCC_UART35CKSELR U(0x618) +#define RCC_UART4CKSELR U(0x61C) +#define RCC_UART6CKSELR U(0x620) +#define RCC_UART78CKSELR U(0x624) +#define RCC_LPTIM1CKSELR U(0x628) +#define RCC_LPTIM23CKSELR U(0x62C) +#define RCC_LPTIM45CKSELR U(0x630) +#define RCC_SAI1CKSELR U(0x634) +#define RCC_SAI2CKSELR U(0x638) +#define RCC_FDCANCKSELR U(0x63C) +#define RCC_SPDIFCKSELR U(0x640) +#define RCC_ADC12CKSELR U(0x644) +#define RCC_SDMMC12CKSELR U(0x648) +#define RCC_ETH12CKSELR U(0x64C) +#define RCC_USBCKSELR U(0x650) +#define RCC_QSPICKSELR U(0x654) +#define RCC_FMCCKSELR U(0x658) +#define RCC_RNG1CKSELR U(0x65C) +#define RCC_STGENCKSELR U(0x660) +#define RCC_DCMIPPCKSELR U(0x664) +#define RCC_SAESCKSELR U(0x668) +#define RCC_APB1RSTSETR U(0x6A0) +#define RCC_APB1RSTCLRR U(0x6A4) +#define RCC_APB2RSTSETR U(0x6A8) +#define RCC_APB2RSTCLRR U(0x6AC) +#define RCC_APB3RSTSETR U(0x6B0) +#define RCC_APB3RSTCLRR U(0x6B4) +#define RCC_APB4RSTSETR U(0x6B8) +#define RCC_APB4RSTCLRR U(0x6BC) +#define RCC_APB5RSTSETR U(0x6C0) +#define RCC_APB5RSTCLRR U(0x6C4) +#define RCC_APB6RSTSETR U(0x6C8) +#define RCC_APB6RSTCLRR U(0x6CC) +#define RCC_AHB2RSTSETR U(0x6D0) +#define RCC_AHB2RSTCLRR U(0x6D4) +#define RCC_AHB4RSTSETR U(0x6E0) +#define RCC_AHB4RSTCLRR U(0x6E4) +#define RCC_AHB5RSTSETR U(0x6E8) +#define RCC_AHB5RSTCLRR U(0x6EC) +#define RCC_AHB6RSTSETR U(0x6F0) +#define RCC_AHB6RSTCLRR U(0x6F4) +#define RCC_MP_APB1ENSETR U(0x700) +#define RCC_MP_APB1ENCLRR U(0x704) +#define RCC_MP_APB2ENSETR U(0x708) +#define RCC_MP_APB2ENCLRR U(0x70C) +#define RCC_MP_APB3ENSETR U(0x710) +#define RCC_MP_APB3ENCLRR U(0x714) +#define RCC_MP_S_APB3ENSETR U(0x718) +#define RCC_MP_S_APB3ENCLRR U(0x71C) +#define RCC_MP_NS_APB3ENSETR U(0x720) +#define RCC_MP_NS_APB3ENCLRR U(0x724) +#define RCC_MP_APB4ENSETR U(0x728) +#define RCC_MP_APB4ENCLRR U(0x72C) +#define RCC_MP_S_APB4ENSETR U(0x730) +#define RCC_MP_S_APB4ENCLRR U(0x734) +#define RCC_MP_NS_APB4ENSETR U(0x738) +#define RCC_MP_NS_APB4ENCLRR U(0x73C) +#define RCC_MP_APB5ENSETR U(0x740) +#define RCC_MP_APB5ENCLRR U(0x744) +#define RCC_MP_APB6ENSETR U(0x748) +#define RCC_MP_APB6ENCLRR U(0x74C) +#define RCC_MP_AHB2ENSETR U(0x750) +#define RCC_MP_AHB2ENCLRR U(0x754) +#define RCC_MP_AHB4ENSETR U(0x760) +#define RCC_MP_AHB4ENCLRR U(0x764) +#define RCC_MP_S_AHB4ENSETR U(0x768) +#define RCC_MP_S_AHB4ENCLRR U(0x76C) +#define RCC_MP_NS_AHB4ENSETR U(0x770) +#define RCC_MP_NS_AHB4ENCLRR U(0x774) +#define RCC_MP_AHB5ENSETR U(0x778) +#define RCC_MP_AHB5ENCLRR U(0x77C) +#define RCC_MP_AHB6ENSETR U(0x780) +#define RCC_MP_AHB6ENCLRR U(0x784) +#define RCC_MP_S_AHB6ENSETR U(0x788) +#define RCC_MP_S_AHB6ENCLRR U(0x78C) +#define RCC_MP_NS_AHB6ENSETR U(0x790) +#define RCC_MP_NS_AHB6ENCLRR U(0x794) +#define RCC_MP_APB1LPENSETR U(0x800) +#define RCC_MP_APB1LPENCLRR U(0x804) +#define RCC_MP_APB2LPENSETR U(0x808) +#define RCC_MP_APB2LPENCLRR U(0x80C) +#define RCC_MP_APB3LPENSETR U(0x810) +#define RCC_MP_APB3LPENCLRR U(0x814) +#define RCC_MP_S_APB3LPENSETR U(0x818) +#define RCC_MP_S_APB3LPENCLRR U(0x81C) +#define RCC_MP_NS_APB3LPENSETR U(0x820) +#define RCC_MP_NS_APB3LPENCLRR U(0x824) +#define RCC_MP_APB4LPENSETR U(0x828) +#define RCC_MP_APB4LPENCLRR U(0x82C) +#define RCC_MP_S_APB4LPENSETR U(0x830) +#define RCC_MP_S_APB4LPENCLRR U(0x834) +#define RCC_MP_NS_APB4LPENSETR U(0x838) +#define RCC_MP_NS_APB4LPENCLRR U(0x83C) +#define RCC_MP_APB5LPENSETR U(0x840) +#define RCC_MP_APB5LPENCLRR U(0x844) +#define RCC_MP_APB6LPENSETR U(0x848) +#define RCC_MP_APB6LPENCLRR U(0x84C) +#define RCC_MP_AHB2LPENSETR U(0x850) +#define RCC_MP_AHB2LPENCLRR U(0x854) +#define RCC_MP_AHB4LPENSETR U(0x858) +#define RCC_MP_AHB4LPENCLRR U(0x85C) +#define RCC_MP_S_AHB4LPENSETR U(0x868) +#define RCC_MP_S_AHB4LPENCLRR U(0x86C) +#define RCC_MP_NS_AHB4LPENSETR U(0x870) +#define RCC_MP_NS_AHB4LPENCLRR U(0x874) +#define RCC_MP_AHB5LPENSETR U(0x878) +#define RCC_MP_AHB5LPENCLRR U(0x87C) +#define RCC_MP_AHB6LPENSETR U(0x880) +#define RCC_MP_AHB6LPENCLRR U(0x884) +#define RCC_MP_S_AHB6LPENSETR U(0x888) +#define RCC_MP_S_AHB6LPENCLRR U(0x88C) +#define RCC_MP_NS_AHB6LPENSETR U(0x890) +#define RCC_MP_NS_AHB6LPENCLRR U(0x894) +#define RCC_MP_S_AXIMLPENSETR U(0x898) +#define RCC_MP_S_AXIMLPENCLRR U(0x89C) +#define RCC_MP_NS_AXIMLPENSETR U(0x8A0) +#define RCC_MP_NS_AXIMLPENCLRR U(0x8A4) +#define RCC_MP_MLAHBLPENSETR U(0x8A8) +#define RCC_MP_MLAHBLPENCLRR U(0x8AC) +#define RCC_APB3SECSR U(0x8C0) +#define RCC_APB4SECSR U(0x8C4) +#define RCC_APB5SECSR U(0x8C8) +#define RCC_APB6SECSR U(0x8CC) +#define RCC_AHB2SECSR U(0x8D0) +#define RCC_AHB4SECSR U(0x8D4) +#define RCC_AHB5SECSR U(0x8D8) +#define RCC_AHB6SECSR U(0x8DC) +#define RCC_VERR U(0xFF4) +#define RCC_IDR U(0xFF8) +#define RCC_SIDR U(0xFFC) + +/* RCC_SECCFGR register fields */ +#define RCC_SECCFGR_HSISEC BIT(0) +#define RCC_SECCFGR_CSISEC BIT(1) +#define RCC_SECCFGR_HSESEC BIT(2) +#define RCC_SECCFGR_LSISEC BIT(3) +#define RCC_SECCFGR_LSESEC BIT(4) +#define RCC_SECCFGR_PLL12SEC BIT(8) +#define RCC_SECCFGR_PLL3SEC BIT(9) +#define RCC_SECCFGR_PLL4SEC BIT(10) +#define RCC_SECCFGR_MPUSEC BIT(11) +#define RCC_SECCFGR_AXISEC BIT(12) +#define RCC_SECCFGR_MLAHBSEC BIT(13) +#define RCC_SECCFGR_APB3DIVSEC BIT(16) +#define RCC_SECCFGR_APB4DIVSEC BIT(17) +#define RCC_SECCFGR_APB5DIVSEC BIT(18) +#define RCC_SECCFGR_APB6DIVSEC BIT(19) +#define RCC_SECCFGR_TIMG3SEC BIT(20) +#define RCC_SECCFGR_CPERSEC BIT(21) +#define RCC_SECCFGR_MCO1SEC BIT(22) +#define RCC_SECCFGR_MCO2SEC BIT(23) +#define RCC_SECCFGR_STPSEC BIT(24) +#define RCC_SECCFGR_RSTSEC BIT(25) +#define RCC_SECCFGR_PWRSEC BIT(31) + +/* RCC_MP_SREQSETR register fields */ +#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) + +/* RCC_MP_SREQCLRR register fields */ +#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) + +/* RCC_MP_APRSTCR register fields */ +#define RCC_MP_APRSTCR_RDCTLEN BIT(0) +#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK_32(14, 8) +#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 + +/* RCC_MP_APRSTSR register fields */ +#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK_32(14, 8) +#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 + +/* RCC_PWRLPDLYCR register fields */ +#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK_32(21, 0) +#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 + +/* RCC_MP_GRSTCSETR register fields */ +#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) + +/* RCC_BR_RSTSCLRR register fields */ +#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) +#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) +#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) +#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_BR_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) + +/* RCC_MP_RSTSSETR register fields */ +#define RCC_MP_RSTSSETR_PORRSTF BIT(0) +#define RCC_MP_RSTSSETR_BORRSTF BIT(1) +#define RCC_MP_RSTSSETR_PADRSTF BIT(2) +#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) +#define RCC_MP_RSTSSETR_VCPURSTF BIT(5) +#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSSETR_STP2RSTF BIT(10) +#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSSETR_SPARE BIT(15) + +/* RCC_MP_RSTSCLRR register fields */ +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STP2RSTF BIT(10) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSCLRR_SPARE BIT(15) + +/* RCC_MP_IWDGFZSETR register fields */ +#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) + +/* RCC_MP_IWDGFZCLRR register fields */ +#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) + +/* RCC_MP_CIER register fields */ +#define RCC_MP_CIER_LSIRDYIE BIT(0) +#define RCC_MP_CIER_LSERDYIE BIT(1) +#define RCC_MP_CIER_HSIRDYIE BIT(2) +#define RCC_MP_CIER_HSERDYIE BIT(3) +#define RCC_MP_CIER_CSIRDYIE BIT(4) +#define RCC_MP_CIER_PLL1DYIE BIT(8) +#define RCC_MP_CIER_PLL2DYIE BIT(9) +#define RCC_MP_CIER_PLL3DYIE BIT(10) +#define RCC_MP_CIER_PLL4DYIE BIT(11) +#define RCC_MP_CIER_LSECSSIE BIT(16) +#define RCC_MP_CIER_WKUPIE BIT(20) + +/* RCC_MP_CIFR register fields */ +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) +#define RCC_MP_CIFR_LSECSSF BIT(16) +#define RCC_MP_CIFR_WKUPF BIT(20) + +/* RCC_BDCR register fields */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK_32(5, 4) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_LSECSSD BIT(9) +#define RCC_BDCR_RTCSRC_MASK GENMASK_32(17, 16) +#define RCC_BDCR_RTCSRC_SHIFT 16 +#define RCC_BDCR_RTCCKEN BIT(20) +#define RCC_BDCR_VSWRST BIT(31) + +#define RCC_BDCR_LSEBYP_BIT 1 +#define RCC_BDCR_LSERDY_BIT 2 +#define RCC_BDCR_DIGBYP_BIT 3 +#define RCC_BDCR_LSECSSON_BIT 8 + +#define RCC_BDCR_LSEDRV_WIDTH 2 + +/* RCC_RDLSICR register fields */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) +#define RCC_RDLSICR_MRD_MASK GENMASK_32(20, 16) +#define RCC_RDLSICR_MRD_SHIFT 16 +#define RCC_RDLSICR_EADLY_MASK GENMASK_32(26, 24) +#define RCC_RDLSICR_EADLY_SHIFT 24 +#define RCC_RDLSICR_SPARE_MASK GENMASK_32(31, 27) +#define RCC_RDLSICR_SPARE_SHIFT 27 + +#define RCC_RDLSICR_LSIRDY_BIT 1 + +/* RCC_OCENSETR register fields */ +#define RCC_OCENSETR_HSION BIT(0) +#define RCC_OCENSETR_HSIKERON BIT(1) +#define RCC_OCENSETR_CSION BIT(4) +#define RCC_OCENSETR_CSIKERON BIT(5) +#define RCC_OCENSETR_DIGBYP BIT(7) +#define RCC_OCENSETR_HSEON BIT(8) +#define RCC_OCENSETR_HSEKERON BIT(9) +#define RCC_OCENSETR_HSEBYP BIT(10) +#define RCC_OCENSETR_HSECSSON BIT(11) + +#define RCC_OCENR_DIGBYP_BIT 7 +#define RCC_OCENR_HSEBYP_BIT 10 +#define RCC_OCENR_HSECSSON_BIT 11 + +/* RCC_OCENCLRR register fields */ +#define RCC_OCENCLRR_HSION BIT(0) +#define RCC_OCENCLRR_HSIKERON BIT(1) +#define RCC_OCENCLRR_CSION BIT(4) +#define RCC_OCENCLRR_CSIKERON BIT(5) +#define RCC_OCENCLRR_DIGBYP BIT(7) +#define RCC_OCENCLRR_HSEON BIT(8) +#define RCC_OCENCLRR_HSEKERON BIT(9) +#define RCC_OCENCLRR_HSEBYP BIT(10) + +/* RCC_OCRDYR register fields */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) +#define RCC_OCRDYR_MPUCKRDY BIT(23) +#define RCC_OCRDYR_AXICKRDY BIT(24) + +#define RCC_OCRDYR_HSIRDY_BIT 0 +#define RCC_OCRDYR_HSIDIVRDY_BIT 2 +#define RCC_OCRDYR_CSIRDY_BIT 4 +#define RCC_OCRDYR_HSERDY_BIT 8 + +/* RCC_HSICFGR register fields */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK_32(1, 0) +#define RCC_HSICFGR_HSIDIV_SHIFT 0 +#define RCC_HSICFGR_HSITRIM_MASK GENMASK_32(14, 8) +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSICAL_MASK GENMASK_32(27, 16) +#define RCC_HSICFGR_HSICAL_SHIFT 16 + +/* RCC_CSICFGR register fields */ +#define RCC_CSICFGR_CSITRIM_MASK GENMASK_32(12, 8) +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSICAL_MASK GENMASK_32(23, 16) +#define RCC_CSICFGR_CSICAL_SHIFT 16 + +/* RCC_MCO1CFGR register fields */ +#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK_32(2, 0) +#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 +#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK_32(7, 4) +#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 +#define RCC_MCO1CFGR_MCO1ON BIT(12) + +/* RCC_MCO2CFGR register fields */ +#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK_32(2, 0) +#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 +#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK_32(7, 4) +#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 +#define RCC_MCO2CFGR_MCO2ON BIT(12) + +/* RCC_DBGCFGR register fields */ +#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK_32(2, 0) +#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 +#define RCC_DBGCFGR_DBGCKEN BIT(8) +#define RCC_DBGCFGR_TRACECKEN BIT(9) +#define RCC_DBGCFGR_DBGRST BIT(12) + +/* RCC_RCK12SELR register fields */ +#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK_32(1, 0) +#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 +#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) + +/* RCC_RCK3SELR register fields */ +#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK_32(1, 0) +#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 +#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) + +/* RCC_RCK4SELR register fields */ +#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK_32(1, 0) +#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 +#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) + +/* RCC_PLL1CR register fields */ +#define RCC_PLL1CR_PLLON BIT(0) +#define RCC_PLL1CR_PLL1RDY BIT(1) +#define RCC_PLL1CR_SSCG_CTRL BIT(2) +#define RCC_PLL1CR_DIVPEN BIT(4) +#define RCC_PLL1CR_DIVQEN BIT(5) +#define RCC_PLL1CR_DIVREN BIT(6) + +/* RCC_PLL1CFGR1 register fields */ +#define RCC_PLL1CFGR1_DIVN_MASK GENMASK_32(8, 0) +#define RCC_PLL1CFGR1_DIVN_SHIFT 0 +#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK_32(21, 16) +#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 + +/* RCC_PLL1CFGR2 register fields */ +#define RCC_PLL1CFGR2_DIVP_MASK GENMASK_32(6, 0) +#define RCC_PLL1CFGR2_DIVP_SHIFT 0 +#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK_32(14, 8) +#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL1CFGR2_DIVR_MASK GENMASK_32(22, 16) +#define RCC_PLL1CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL1FRACR register fields */ +#define RCC_PLL1FRACR_FRACV_MASK GENMASK_32(15, 3) +#define RCC_PLL1FRACR_FRACV_SHIFT 3 +#define RCC_PLL1FRACR_FRACLE BIT(16) + +/* RCC_PLL1CSGR register fields */ +#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK_32(12, 0) +#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL1CSGR_SSCG_MODE BIT(15) +#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK_32(30, 16) +#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL2CR register fields */ +#define RCC_PLL2CR_PLLON BIT(0) +#define RCC_PLL2CR_PLL2RDY BIT(1) +#define RCC_PLL2CR_SSCG_CTRL BIT(2) +#define RCC_PLL2CR_DIVPEN BIT(4) +#define RCC_PLL2CR_DIVQEN BIT(5) +#define RCC_PLL2CR_DIVREN BIT(6) + +/* RCC_PLL2CFGR1 register fields */ +#define RCC_PLL2CFGR1_DIVN_MASK GENMASK_32(8, 0) +#define RCC_PLL2CFGR1_DIVN_SHIFT 0 +#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK_32(21, 16) +#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 + +/* RCC_PLL2CFGR2 register fields */ +#define RCC_PLL2CFGR2_DIVP_MASK GENMASK_32(6, 0) +#define RCC_PLL2CFGR2_DIVP_SHIFT 0 +#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK_32(14, 8) +#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL2CFGR2_DIVR_MASK GENMASK_32(22, 16) +#define RCC_PLL2CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL2FRACR register fields */ +#define RCC_PLL2FRACR_FRACV_MASK GENMASK_32(15, 3) +#define RCC_PLL2FRACR_FRACV_SHIFT 3 +#define RCC_PLL2FRACR_FRACLE BIT(16) + +/* RCC_PLL2CSGR register fields */ +#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK_32(12, 0) +#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL2CSGR_SSCG_MODE BIT(15) +#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK_32(30, 16) +#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL3CR register fields */ +#define RCC_PLL3CR_PLLON BIT(0) +#define RCC_PLL3CR_PLL3RDY BIT(1) +#define RCC_PLL3CR_SSCG_CTRL BIT(2) +#define RCC_PLL3CR_DIVPEN BIT(4) +#define RCC_PLL3CR_DIVQEN BIT(5) +#define RCC_PLL3CR_DIVREN BIT(6) + +/* RCC_PLL3CFGR1 register fields */ +#define RCC_PLL3CFGR1_DIVN_MASK GENMASK_32(8, 0) +#define RCC_PLL3CFGR1_DIVN_SHIFT 0 +#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK_32(21, 16) +#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 +#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK_32(25, 24) +#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL3CFGR2 register fields */ +#define RCC_PLL3CFGR2_DIVP_MASK GENMASK_32(6, 0) +#define RCC_PLL3CFGR2_DIVP_SHIFT 0 +#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK_32(14, 8) +#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL3CFGR2_DIVR_MASK GENMASK_32(22, 16) +#define RCC_PLL3CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL3FRACR register fields */ +#define RCC_PLL3FRACR_FRACV_MASK GENMASK_32(15, 3) +#define RCC_PLL3FRACR_FRACV_SHIFT 3 +#define RCC_PLL3FRACR_FRACLE BIT(16) + +/* RCC_PLL3CSGR register fields */ +#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK_32(12, 0) +#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL3CSGR_SSCG_MODE BIT(15) +#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK_32(30, 16) +#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL4CR register fields */ +#define RCC_PLL4CR_PLLON BIT(0) +#define RCC_PLL4CR_PLL4RDY BIT(1) +#define RCC_PLL4CR_SSCG_CTRL BIT(2) +#define RCC_PLL4CR_DIVPEN BIT(4) +#define RCC_PLL4CR_DIVQEN BIT(5) +#define RCC_PLL4CR_DIVREN BIT(6) + +/* RCC_PLL4CFGR1 register fields */ +#define RCC_PLL4CFGR1_DIVN_MASK GENMASK_32(8, 0) +#define RCC_PLL4CFGR1_DIVN_SHIFT 0 +#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK_32(21, 16) +#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 +#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK_32(25, 24) +#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL4CFGR2 register fields */ +#define RCC_PLL4CFGR2_DIVP_MASK GENMASK_32(6, 0) +#define RCC_PLL4CFGR2_DIVP_SHIFT 0 +#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK_32(14, 8) +#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL4CFGR2_DIVR_MASK GENMASK_32(22, 16) +#define RCC_PLL4CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL4FRACR register fields */ +#define RCC_PLL4FRACR_FRACV_MASK GENMASK_32(15, 3) +#define RCC_PLL4FRACR_FRACV_SHIFT 3 +#define RCC_PLL4FRACR_FRACLE BIT(16) + +/* RCC_PLL4CSGR register fields */ +#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK_32(12, 0) +#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL4CSGR_SSCG_MODE BIT(15) +#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK_32(30, 16) +#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 + +/* RCC_MPCKSELR register fields */ +#define RCC_MPCKSELR_MPUSRC_MASK GENMASK_32(1, 0) +#define RCC_MPCKSELR_MPUSRC_SHIFT 0 +#define RCC_MPCKSELR_MPUSRCRDY BIT(31) + +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK_32(2, 0) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 +#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_MLAHBSSRC_MASK GENMASK_32(1, 0) +#define RCC_MSSCKSELR_MLAHBSSRC_SHIFT 0 +#define RCC_MSSCKSELR_MLAHBSSRCRDY BIT(31) + +/* RCC_CPERCKSELR register fields */ +#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK_32(1, 0) +#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 + +/* RCC_RTCDIVR register fields */ +#define RCC_RTCDIVR_RTCDIV_MASK GENMASK_32(5, 0) +#define RCC_RTCDIVR_RTCDIV_SHIFT 0 + +/* RCC_MPCKDIVR register fields */ +#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK_32(3, 0) +#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 +#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) + +/* RCC_AXIDIVR register fields */ +#define RCC_AXIDIVR_AXIDIV_MASK GENMASK_32(2, 0) +#define RCC_AXIDIVR_AXIDIV_SHIFT 0 +#define RCC_AXIDIVR_AXIDIVRDY BIT(31) + +/* RCC_MLAHBDIVR register fields */ +#define RCC_MLAHBDIVR_MLAHBDIV_MASK GENMASK_32(3, 0) +#define RCC_MLAHBDIVR_MLAHBDIV_SHIFT 0 +#define RCC_MLAHBDIVR_MLAHBDIVRDY BIT(31) + +/* RCC_APB1DIVR register fields */ +#define RCC_APB1DIVR_APB1DIV_MASK GENMASK_32(2, 0) +#define RCC_APB1DIVR_APB1DIV_SHIFT 0 +#define RCC_APB1DIVR_APB1DIVRDY BIT(31) + +/* RCC_APB2DIVR register fields */ +#define RCC_APB2DIVR_APB2DIV_MASK GENMASK_32(2, 0) +#define RCC_APB2DIVR_APB2DIV_SHIFT 0 +#define RCC_APB2DIVR_APB2DIVRDY BIT(31) + +/* RCC_APB3DIVR register fields */ +#define RCC_APB3DIVR_APB3DIV_MASK GENMASK_32(2, 0) +#define RCC_APB3DIVR_APB3DIV_SHIFT 0 +#define RCC_APB3DIVR_APB3DIVRDY BIT(31) + +/* RCC_APB4DIVR register fields */ +#define RCC_APB4DIVR_APB4DIV_MASK GENMASK_32(2, 0) +#define RCC_APB4DIVR_APB4DIV_SHIFT 0 +#define RCC_APB4DIVR_APB4DIVRDY BIT(31) + +/* RCC_APB5DIVR register fields */ +#define RCC_APB5DIVR_APB5DIV_MASK GENMASK_32(2, 0) +#define RCC_APB5DIVR_APB5DIV_SHIFT 0 +#define RCC_APB5DIVR_APB5DIVRDY BIT(31) + +/* RCC_APB6DIVR register fields */ +#define RCC_APB6DIVR_APB6DIV_MASK GENMASK_32(2, 0) +#define RCC_APB6DIVR_APB6DIV_SHIFT 0 +#define RCC_APB6DIVR_APB6DIVRDY BIT(31) + +/* RCC_TIMG1PRER register fields */ +#define RCC_TIMG1PRER_TIMG1PRE BIT(0) +#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) + +/* RCC_TIMG2PRER register fields */ +#define RCC_TIMG2PRER_TIMG2PRE BIT(0) +#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) + +/* RCC_TIMG3PRER register fields */ +#define RCC_TIMG3PRER_TIMG3PRE BIT(0) +#define RCC_TIMG3PRER_TIMG3PRERDY BIT(31) + +/* RCC_DDRITFCR register fields */ +#define RCC_DDRITFCR_DDRC1EN BIT(0) +#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +#define RCC_DDRITFCR_AXIDCGEN BIT(8) +#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK_32(13, 11) +#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 +#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +#define RCC_DDRITFCR_DDRCORERST BIT(16) +#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +#define RCC_DDRITFCR_DPHYRST BIT(18) +#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK_32(22, 20) +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_GSKPMOD BIT(23) +#define RCC_DDRITFCR_GSKPCTRL BIT(24) +#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK_32(27, 25) +#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 +#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK_32(31, 28) +#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK_32(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C345CKSELR register fields */ +#define RCC_I2C345CKSELR_I2C3SRC_MASK GENMASK_32(2, 0) +#define RCC_I2C345CKSELR_I2C3SRC_SHIFT 0 +#define RCC_I2C345CKSELR_I2C4SRC_MASK GENMASK_32(5, 3) +#define RCC_I2C345CKSELR_I2C4SRC_SHIFT 3 +#define RCC_I2C345CKSELR_I2C5SRC_MASK GENMASK_32(8, 6) +#define RCC_I2C345CKSELR_I2C5SRC_SHIFT 6 + +/* RCC_SPI2S1CKSELR register fields */ +#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK_32(2, 0) +#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 + +/* RCC_SPI2S23CKSELR register fields */ +#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK_32(2, 0) +#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 + +/* RCC_SPI45CKSELR register fields */ +#define RCC_SPI45CKSELR_SPI4SRC_MASK GENMASK_32(2, 0) +#define RCC_SPI45CKSELR_SPI4SRC_SHIFT 0 +#define RCC_SPI45CKSELR_SPI5SRC_MASK GENMASK_32(5, 3) +#define RCC_SPI45CKSELR_SPI5SRC_SHIFT 3 + +/* RCC_UART12CKSELR register fields */ +#define RCC_UART12CKSELR_UART1SRC_MASK GENMASK_32(2, 0) +#define RCC_UART12CKSELR_UART1SRC_SHIFT 0 +#define RCC_UART12CKSELR_UART2SRC_MASK GENMASK_32(5, 3) +#define RCC_UART12CKSELR_UART2SRC_SHIFT 3 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK_32(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART4CKSELR register fields */ +#define RCC_UART4CKSELR_UART4SRC_MASK GENMASK_32(2, 0) +#define RCC_UART4CKSELR_UART4SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK_32(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK_32(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_LPTIM1CKSELR register fields */ +#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK_32(2, 0) +#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 + +/* RCC_LPTIM23CKSELR register fields */ +#define RCC_LPTIM23CKSELR_LPTIM2SRC_MASK GENMASK_32(2, 0) +#define RCC_LPTIM23CKSELR_LPTIM2SRC_SHIFT 0 +#define RCC_LPTIM23CKSELR_LPTIM3SRC_MASK GENMASK_32(5, 3) +#define RCC_LPTIM23CKSELR_LPTIM3SRC_SHIFT 3 + +/* RCC_LPTIM45CKSELR register fields */ +#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK_32(2, 0) +#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 + +/* RCC_SAI1CKSELR register fields */ +#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK_32(2, 0) +#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 + +/* RCC_SAI2CKSELR register fields */ +#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK_32(2, 0) +#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 + +/* RCC_FDCANCKSELR register fields */ +#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK_32(1, 0) +#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 + +/* RCC_SPDIFCKSELR register fields */ +#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK_32(1, 0) +#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 + +/* RCC_ADC12CKSELR register fields */ +#define RCC_ADC12CKSELR_ADC1SRC_MASK GENMASK_32(1, 0) +#define RCC_ADC12CKSELR_ADC1SRC_SHIFT 0 +#define RCC_ADC12CKSELR_ADC2SRC_MASK GENMASK_32(3, 2) +#define RCC_ADC12CKSELR_ADC2SRC_SHIFT 2 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC1SRC_MASK GENMASK_32(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC1SRC_SHIFT 0 +#define RCC_SDMMC12CKSELR_SDMMC2SRC_MASK GENMASK_32(5, 3) +#define RCC_SDMMC12CKSELR_SDMMC2SRC_SHIFT 3 + +/* RCC_ETH12CKSELR register fields */ +#define RCC_ETH12CKSELR_ETH1SRC_MASK GENMASK_32(1, 0) +#define RCC_ETH12CKSELR_ETH1SRC_SHIFT 0 +#define RCC_ETH12CKSELR_ETH1PTPDIV_MASK GENMASK_32(7, 4) +#define RCC_ETH12CKSELR_ETH1PTPDIV_SHIFT 4 +#define RCC_ETH12CKSELR_ETH2SRC_MASK GENMASK_32(9, 8) +#define RCC_ETH12CKSELR_ETH2SRC_SHIFT 8 +#define RCC_ETH12CKSELR_ETH2PTPDIV_MASK GENMASK_32(15, 12) +#define RCC_ETH12CKSELR_ETH2PTPDIV_SHIFT 12 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK_32(1, 0) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 +#define RCC_USBCKSELR_USBOSRC BIT(4) + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK_32(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK_32(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK_32(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK_32(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_DCMIPPCKSELR register fields */ +#define RCC_DCMIPPCKSELR_DCMIPPSRC_MASK GENMASK_32(1, 0) +#define RCC_DCMIPPCKSELR_DCMIPPSRC_SHIFT 0 + +/* RCC_SAESCKSELR register fields */ +#define RCC_SAESCKSELR_SAESSRC_MASK GENMASK_32(1, 0) +#define RCC_SAESCKSELR_SAESSRC_SHIFT 0 + +/* RCC_APB1RSTSETR register fields */ +#define RCC_APB1RSTSETR_TIM2RST BIT(0) +#define RCC_APB1RSTSETR_TIM3RST BIT(1) +#define RCC_APB1RSTSETR_TIM4RST BIT(2) +#define RCC_APB1RSTSETR_TIM5RST BIT(3) +#define RCC_APB1RSTSETR_TIM6RST BIT(4) +#define RCC_APB1RSTSETR_TIM7RST BIT(5) +#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) +#define RCC_APB1RSTSETR_SPI2RST BIT(11) +#define RCC_APB1RSTSETR_SPI3RST BIT(12) +#define RCC_APB1RSTSETR_USART3RST BIT(15) +#define RCC_APB1RSTSETR_UART4RST BIT(16) +#define RCC_APB1RSTSETR_UART5RST BIT(17) +#define RCC_APB1RSTSETR_UART7RST BIT(18) +#define RCC_APB1RSTSETR_UART8RST BIT(19) +#define RCC_APB1RSTSETR_I2C1RST BIT(21) +#define RCC_APB1RSTSETR_I2C2RST BIT(22) +#define RCC_APB1RSTSETR_SPDIFRST BIT(26) + +/* RCC_APB1RSTCLRR register fields */ +#define RCC_APB1RSTCLRR_TIM2RST BIT(0) +#define RCC_APB1RSTCLRR_TIM3RST BIT(1) +#define RCC_APB1RSTCLRR_TIM4RST BIT(2) +#define RCC_APB1RSTCLRR_TIM5RST BIT(3) +#define RCC_APB1RSTCLRR_TIM6RST BIT(4) +#define RCC_APB1RSTCLRR_TIM7RST BIT(5) +#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) +#define RCC_APB1RSTCLRR_SPI2RST BIT(11) +#define RCC_APB1RSTCLRR_SPI3RST BIT(12) +#define RCC_APB1RSTCLRR_USART3RST BIT(15) +#define RCC_APB1RSTCLRR_UART4RST BIT(16) +#define RCC_APB1RSTCLRR_UART5RST BIT(17) +#define RCC_APB1RSTCLRR_UART7RST BIT(18) +#define RCC_APB1RSTCLRR_UART8RST BIT(19) +#define RCC_APB1RSTCLRR_I2C1RST BIT(21) +#define RCC_APB1RSTCLRR_I2C2RST BIT(22) +#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) + +/* RCC_APB2RSTSETR register fields */ +#define RCC_APB2RSTSETR_TIM1RST BIT(0) +#define RCC_APB2RSTSETR_TIM8RST BIT(1) +#define RCC_APB2RSTSETR_SPI1RST BIT(8) +#define RCC_APB2RSTSETR_USART6RST BIT(13) +#define RCC_APB2RSTSETR_SAI1RST BIT(16) +#define RCC_APB2RSTSETR_SAI2RST BIT(17) +#define RCC_APB2RSTSETR_DFSDMRST BIT(20) +#define RCC_APB2RSTSETR_FDCANRST BIT(24) + +/* RCC_APB2RSTCLRR register fields */ +#define RCC_APB2RSTCLRR_TIM1RST BIT(0) +#define RCC_APB2RSTCLRR_TIM8RST BIT(1) +#define RCC_APB2RSTCLRR_SPI1RST BIT(8) +#define RCC_APB2RSTCLRR_USART6RST BIT(13) +#define RCC_APB2RSTCLRR_SAI1RST BIT(16) +#define RCC_APB2RSTCLRR_SAI2RST BIT(17) +#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) +#define RCC_APB2RSTCLRR_FDCANRST BIT(24) + +/* RCC_APB3RSTSETR register fields */ +#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) +#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) +#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) +#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) +#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) +#define RCC_APB3RSTSETR_VREFRST BIT(13) +#define RCC_APB3RSTSETR_DTSRST BIT(16) +#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) + +/* RCC_APB3RSTCLRR register fields */ +#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) +#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) +#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) +#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) +#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) +#define RCC_APB3RSTCLRR_VREFRST BIT(13) +#define RCC_APB3RSTCLRR_DTSRST BIT(16) +#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) + +/* RCC_APB4RSTSETR register fields */ +#define RCC_APB4RSTSETR_LTDCRST BIT(0) +#define RCC_APB4RSTSETR_DCMIPPRST BIT(1) +#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTSETR_USBPHYRST BIT(16) + +/* RCC_APB4RSTCLRR register fields */ +#define RCC_APB4RSTCLRR_LTDCRST BIT(0) +#define RCC_APB4RSTCLRR_DCMIPPRST BIT(1) +#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) + +/* RCC_APB5RSTSETR register fields */ +#define RCC_APB5RSTSETR_STGENRST BIT(20) + +/* RCC_APB5RSTCLRR register fields */ +#define RCC_APB5RSTCLRR_STGENRST BIT(20) + +/* RCC_APB6RSTSETR register fields */ +#define RCC_APB6RSTSETR_USART1RST BIT(0) +#define RCC_APB6RSTSETR_USART2RST BIT(1) +#define RCC_APB6RSTSETR_SPI4RST BIT(2) +#define RCC_APB6RSTSETR_SPI5RST BIT(3) +#define RCC_APB6RSTSETR_I2C3RST BIT(4) +#define RCC_APB6RSTSETR_I2C4RST BIT(5) +#define RCC_APB6RSTSETR_I2C5RST BIT(6) +#define RCC_APB6RSTSETR_TIM12RST BIT(7) +#define RCC_APB6RSTSETR_TIM13RST BIT(8) +#define RCC_APB6RSTSETR_TIM14RST BIT(9) +#define RCC_APB6RSTSETR_TIM15RST BIT(10) +#define RCC_APB6RSTSETR_TIM16RST BIT(11) +#define RCC_APB6RSTSETR_TIM17RST BIT(12) + +/* RCC_APB6RSTCLRR register fields */ +#define RCC_APB6RSTCLRR_USART1RST BIT(0) +#define RCC_APB6RSTCLRR_USART2RST BIT(1) +#define RCC_APB6RSTCLRR_SPI4RST BIT(2) +#define RCC_APB6RSTCLRR_SPI5RST BIT(3) +#define RCC_APB6RSTCLRR_I2C3RST BIT(4) +#define RCC_APB6RSTCLRR_I2C4RST BIT(5) +#define RCC_APB6RSTCLRR_I2C5RST BIT(6) +#define RCC_APB6RSTCLRR_TIM12RST BIT(7) +#define RCC_APB6RSTCLRR_TIM13RST BIT(8) +#define RCC_APB6RSTCLRR_TIM14RST BIT(9) +#define RCC_APB6RSTCLRR_TIM15RST BIT(10) +#define RCC_APB6RSTCLRR_TIM16RST BIT(11) +#define RCC_APB6RSTCLRR_TIM17RST BIT(12) + +/* RCC_AHB2RSTSETR register fields */ +#define RCC_AHB2RSTSETR_DMA1RST BIT(0) +#define RCC_AHB2RSTSETR_DMA2RST BIT(1) +#define RCC_AHB2RSTSETR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTSETR_DMA3RST BIT(3) +#define RCC_AHB2RSTSETR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTSETR_ADC1RST BIT(5) +#define RCC_AHB2RSTSETR_ADC2RST BIT(6) +#define RCC_AHB2RSTSETR_USBORST BIT(8) + +/* RCC_AHB2RSTCLRR register fields */ +#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) +#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) +#define RCC_AHB2RSTCLRR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTCLRR_DMA3RST BIT(3) +#define RCC_AHB2RSTCLRR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTCLRR_ADC1RST BIT(5) +#define RCC_AHB2RSTCLRR_ADC2RST BIT(6) +#define RCC_AHB2RSTCLRR_USBORST BIT(8) + +/* RCC_AHB4RSTSETR register fields */ +#define RCC_AHB4RSTSETR_GPIOARST BIT(0) +#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) +#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) +#define RCC_AHB4RSTSETR_GPIODRST BIT(3) +#define RCC_AHB4RSTSETR_GPIOERST BIT(4) +#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) +#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) +#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) +#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) +#define RCC_AHB4RSTSETR_TSCRST BIT(15) + +/* RCC_AHB4RSTCLRR register fields */ +#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) +#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) +#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) +#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) +#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) +#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) +#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) +#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) +#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) +#define RCC_AHB4RSTCLRR_TSCRST BIT(15) + +/* RCC_AHB5RSTSETR register fields */ +#define RCC_AHB5RSTSETR_PKARST BIT(2) +#define RCC_AHB5RSTSETR_SAESRST BIT(3) +#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + +/* RCC_AHB5RSTCLRR register fields */ +#define RCC_AHB5RSTCLRR_PKARST BIT(2) +#define RCC_AHB5RSTCLRR_SAESRST BIT(3) +#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) +#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) +#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) +#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) + +/* RCC_AHB6RSTSETR register fields */ +#define RCC_AHB6RSTSETR_MDMARST BIT(0) +#define RCC_AHB6RSTSETR_MCERST BIT(1) +#define RCC_AHB6RSTSETR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTSETR_FMCRST BIT(12) +#define RCC_AHB6RSTSETR_QSPIRST BIT(14) +#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTSETR_CRC1RST BIT(20) +#define RCC_AHB6RSTSETR_USBHRST BIT(24) +#define RCC_AHB6RSTSETR_ETH2MACRST BIT(30) + +/* RCC_AHB6RSTCLRR register fields */ +#define RCC_AHB6RSTCLRR_MDMARST BIT(0) +#define RCC_AHB6RSTCLRR_MCERST BIT(1) +#define RCC_AHB6RSTCLRR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTCLRR_FMCRST BIT(12) +#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) +#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) +#define RCC_AHB6RSTCLRR_USBHRST BIT(24) +#define RCC_AHB6RSTCLRR_ETH2MACRST BIT(30) + +/* RCC_MP_APB1ENSETR register fields */ +#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MP_APB1ENSETR_USART3EN BIT(15) +#define RCC_MP_APB1ENSETR_UART4EN BIT(16) +#define RCC_MP_APB1ENSETR_UART5EN BIT(17) +#define RCC_MP_APB1ENSETR_UART7EN BIT(18) +#define RCC_MP_APB1ENSETR_UART8EN BIT(19) +#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) + +/* RCC_MP_APB1ENCLRR register fields */ +#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) + +/* RCC_MP_APB2ENSETR register fields */ +#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MP_APB2ENSETR_USART6EN BIT(13) +#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MP_APB2ENCLRR register fields */ +#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MP_APB3ENSETR register fields */ +#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENSETR_VREFEN BIT(13) +#define RCC_MP_APB3ENSETR_DTSEN BIT(16) +#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MP_APB3ENCLRR register fields */ +#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MP_APB3ENCLRR_DTSEN BIT(16) +#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MP_S_APB3ENSETR register fields */ +#define RCC_MP_S_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_S_APB3ENCLRR register fields */ +#define RCC_MP_S_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENSETR register fields */ +#define RCC_MP_NS_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENCLRR register fields */ +#define RCC_MP_NS_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_APB4ENSETR register fields */ +#define RCC_MP_APB4ENSETR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MP_APB4ENCLRR register fields */ +#define RCC_MP_APB4ENCLRR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MP_S_APB4ENSETR register fields */ +#define RCC_MP_S_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_S_APB4ENCLRR register fields */ +#define RCC_MP_S_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENSETR register fields */ +#define RCC_MP_NS_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENCLRR register fields */ +#define RCC_MP_NS_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_APB5ENSETR register fields */ +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENSETR_TZCEN BIT(11) +#define RCC_MP_APB5ENSETR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENSETR_BSECEN BIT(16) +#define RCC_MP_APB5ENSETR_STGENCEN BIT(20) + +/* RCC_MP_APB5ENCLRR register fields */ +#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENCLRR_TZCEN BIT(11) +#define RCC_MP_APB5ENCLRR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MP_APB5ENCLRR_STGENCEN BIT(20) + +/* RCC_MP_APB6ENSETR register fields */ +#define RCC_MP_APB6ENSETR_USART1EN BIT(0) +#define RCC_MP_APB6ENSETR_USART2EN BIT(1) +#define RCC_MP_APB6ENSETR_SPI4EN BIT(2) +#define RCC_MP_APB6ENSETR_SPI5EN BIT(3) +#define RCC_MP_APB6ENSETR_I2C3EN BIT(4) +#define RCC_MP_APB6ENSETR_I2C4EN BIT(5) +#define RCC_MP_APB6ENSETR_I2C5EN BIT(6) +#define RCC_MP_APB6ENSETR_TIM12EN BIT(7) +#define RCC_MP_APB6ENSETR_TIM13EN BIT(8) +#define RCC_MP_APB6ENSETR_TIM14EN BIT(9) +#define RCC_MP_APB6ENSETR_TIM15EN BIT(10) +#define RCC_MP_APB6ENSETR_TIM16EN BIT(11) +#define RCC_MP_APB6ENSETR_TIM17EN BIT(12) + +/* RCC_MP_APB6ENCLRR register fields */ +#define RCC_MP_APB6ENCLRR_USART1EN BIT(0) +#define RCC_MP_APB6ENCLRR_USART2EN BIT(1) +#define RCC_MP_APB6ENCLRR_SPI4EN BIT(2) +#define RCC_MP_APB6ENCLRR_SPI5EN BIT(3) +#define RCC_MP_APB6ENCLRR_I2C3EN BIT(4) +#define RCC_MP_APB6ENCLRR_I2C4EN BIT(5) +#define RCC_MP_APB6ENCLRR_I2C5EN BIT(6) +#define RCC_MP_APB6ENCLRR_TIM12EN BIT(7) +#define RCC_MP_APB6ENCLRR_TIM13EN BIT(8) +#define RCC_MP_APB6ENCLRR_TIM14EN BIT(9) +#define RCC_MP_APB6ENCLRR_TIM15EN BIT(10) +#define RCC_MP_APB6ENCLRR_TIM16EN BIT(11) +#define RCC_MP_APB6ENCLRR_TIM17EN BIT(12) + +/* RCC_MP_AHB2ENSETR register fields */ +#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENSETR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENSETR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENSETR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENSETR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENSETR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) + +/* RCC_MP_AHB2ENCLRR register fields */ +#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENCLRR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENCLRR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENCLRR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENCLRR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENCLRR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) + +/* RCC_MP_AHB4ENSETR register fields */ +#define RCC_MP_AHB4ENSETR_TSCEN BIT(15) + +/* RCC_MP_AHB4ENCLRR register fields */ +#define RCC_MP_AHB4ENCLRR_TSCEN BIT(15) + +/* RCC_MP_S_AHB4ENSETR register fields */ +#define RCC_MP_S_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_S_AHB4ENCLRR register fields */ +#define RCC_MP_S_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENSETR register fields */ +#define RCC_MP_NS_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENCLRR register fields */ +#define RCC_MP_NS_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_AHB5ENSETR register fields */ +#define RCC_MP_AHB5ENSETR_PKAEN BIT(2) +#define RCC_MP_AHB5ENSETR_SAESEN BIT(3) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) + +/* RCC_MP_AHB5ENCLRR register fields */ +#define RCC_MP_AHB5ENCLRR_PKAEN BIT(2) +#define RCC_MP_AHB5ENCLRR_SAESEN BIT(3) +#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) + +/* RCC_MP_AHB6ENSETR register fields */ +#define RCC_MP_AHB6ENSETR_MCEEN BIT(1) +#define RCC_MP_AHB6ENSETR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENSETR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENSETR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENSETR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) +#define RCC_MP_AHB6ENSETR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENSETR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENSETR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENSETR_ETH2MACEN BIT(30) + +/* RCC_MP_AHB6ENCLRR register fields */ +#define RCC_MP_AHB6ENCLRR_MCEEN BIT(1) +#define RCC_MP_AHB6ENCLRR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENCLRR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENCLRR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENCLRR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) +#define RCC_MP_AHB6ENCLRR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENCLRR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENCLRR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENCLRR_ETH2MACEN BIT(30) + +/* RCC_MP_S_AHB6ENSETR register fields */ +#define RCC_MP_S_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_S_AHB6ENCLRR register fields */ +#define RCC_MP_S_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENSETR register fields */ +#define RCC_MP_NS_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENCLRR register fields */ +#define RCC_MP_NS_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_APB1LPENSETR register fields */ +#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB1LPENCLRR register fields */ +#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB2LPENSETR register fields */ +#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MP_APB2LPENCLRR register fields */ +#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MP_APB3LPENSETR register fields */ +#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENSETR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_APB3LPENCLRR register fields */ +#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENCLRR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_S_APB3LPENSETR register fields */ +#define RCC_MP_S_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_S_APB3LPENCLRR register fields */ +#define RCC_MP_S_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENSETR register fields */ +#define RCC_MP_NS_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENCLRR register fields */ +#define RCC_MP_NS_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_APB4LPENSETR register fields */ +#define RCC_MP_APB4LPENSETR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB4LPENCLRR register fields */ +#define RCC_MP_APB4LPENCLRR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MP_S_APB4LPENSETR register fields */ +#define RCC_MP_S_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_S_APB4LPENCLRR register fields */ +#define RCC_MP_S_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENSETR register fields */ +#define RCC_MP_NS_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENCLRR register fields */ +#define RCC_MP_NS_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_APB5LPENSETR register fields */ +#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENSETR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENSETR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENSETR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENSETR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB5LPENCLRR register fields */ +#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENCLRR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENCLRR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENCLRR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENCLRR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB6LPENSETR register fields */ +#define RCC_MP_APB6LPENSETR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENSETR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENSETR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENSETR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENSETR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENSETR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENSETR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENSETR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENSETR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENSETR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENSETR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENSETR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENSETR_TIM17LPEN BIT(12) + +/* RCC_MP_APB6LPENCLRR register fields */ +#define RCC_MP_APB6LPENCLRR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENCLRR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENCLRR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENCLRR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENCLRR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENCLRR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENCLRR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENCLRR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENCLRR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENCLRR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENCLRR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENCLRR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENCLRR_TIM17LPEN BIT(12) + +/* RCC_MP_AHB2LPENSETR register fields */ +#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENSETR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENSETR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENSETR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENSETR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENSETR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) + +/* RCC_MP_AHB2LPENCLRR register fields */ +#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENCLRR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENCLRR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENCLRR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENCLRR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENCLRR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) + +/* RCC_MP_AHB4LPENSETR register fields */ +#define RCC_MP_AHB4LPENSETR_TSCLPEN BIT(15) + +/* RCC_MP_AHB4LPENCLRR register fields */ +#define RCC_MP_AHB4LPENCLRR_TSCLPEN BIT(15) + +/* RCC_MP_S_AHB4LPENSETR register fields */ +#define RCC_MP_S_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_S_AHB4LPENCLRR register fields */ +#define RCC_MP_S_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENSETR register fields */ +#define RCC_MP_NS_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENCLRR register fields */ +#define RCC_MP_NS_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_AHB5LPENSETR register fields */ +#define RCC_MP_AHB5LPENSETR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENSETR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB5LPENCLRR register fields */ +#define RCC_MP_AHB5LPENCLRR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENCLRR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB6LPENSETR register fields */ +#define RCC_MP_AHB6LPENSETR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENSETR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENSETR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENSETR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENSETR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENSETR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENSETR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENSETR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENSETR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENSETR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENSETR_ETH2STPEN BIT(31) + +/* RCC_MP_AHB6LPENCLRR register fields */ +#define RCC_MP_AHB6LPENCLRR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENCLRR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENCLRR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENCLRR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENCLRR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENCLRR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENCLRR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENCLRR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENCLRR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENCLRR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENCLRR_ETH2STPEN BIT(31) + +/* RCC_MP_S_AHB6LPENSETR register fields */ +#define RCC_MP_S_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_S_AHB6LPENCLRR register fields */ +#define RCC_MP_S_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENSETR register fields */ +#define RCC_MP_NS_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENCLRR register fields */ +#define RCC_MP_NS_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_S_AXIMLPENSETR register fields */ +#define RCC_MP_S_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_S_AXIMLPENCLRR register fields */ +#define RCC_MP_S_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENSETR register fields */ +#define RCC_MP_NS_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENCLRR register fields */ +#define RCC_MP_NS_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_MLAHBLPENSETR register fields */ +#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENSETR_SRAM3LPEN BIT(2) + +/* RCC_MP_MLAHBLPENCLRR register fields */ +#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENCLRR_SRAM3LPEN BIT(2) + +/* RCC_APB3SECSR register fields */ +#define RCC_APB3SECSR_LPTIM2SECF BIT(0) +#define RCC_APB3SECSR_LPTIM3SECF BIT(1) +#define RCC_APB3SECSR_VREFSECF BIT(13) + +/* RCC_APB4SECSR register fields */ +#define RCC_APB4SECSR_DCMIPPSECF BIT(1) +#define RCC_APB4SECSR_USBPHYSECF BIT(16) + +/* RCC_APB5SECSR register fields */ +#define RCC_APB5SECSR_RTCSECF BIT(8) +#define RCC_APB5SECSR_TZCSECF BIT(11) +#define RCC_APB5SECSR_ETZPCSECF BIT(13) +#define RCC_APB5SECSR_IWDG1SECF BIT(15) +#define RCC_APB5SECSR_BSECSECF BIT(16) +#define RCC_APB5SECSR_STGENCSECF_MASK GENMASK_32(21, 20) +#define RCC_APB5SECSR_STGENCSECF_SHIFT 20 + +/* RCC_APB6SECSR register fields */ +#define RCC_APB6SECSR_USART1SECF BIT(0) +#define RCC_APB6SECSR_USART2SECF BIT(1) +#define RCC_APB6SECSR_SPI4SECF BIT(2) +#define RCC_APB6SECSR_SPI5SECF BIT(3) +#define RCC_APB6SECSR_I2C3SECF BIT(4) +#define RCC_APB6SECSR_I2C4SECF BIT(5) +#define RCC_APB6SECSR_I2C5SECF BIT(6) +#define RCC_APB6SECSR_TIM12SECF BIT(7) +#define RCC_APB6SECSR_TIM13SECF BIT(8) +#define RCC_APB6SECSR_TIM14SECF BIT(9) +#define RCC_APB6SECSR_TIM15SECF BIT(10) +#define RCC_APB6SECSR_TIM16SECF BIT(11) +#define RCC_APB6SECSR_TIM17SECF BIT(12) + +/* RCC_AHB2SECSR register fields */ +#define RCC_AHB2SECSR_DMA3SECF BIT(3) +#define RCC_AHB2SECSR_DMAMUX2SECF BIT(4) +#define RCC_AHB2SECSR_ADC1SECF BIT(5) +#define RCC_AHB2SECSR_ADC2SECF BIT(6) +#define RCC_AHB2SECSR_USBOSECF BIT(8) + +/* RCC_AHB4SECSR register fields */ +#define RCC_AHB4SECSR_TSCSECF BIT(15) + +/* RCC_AHB5SECSR register fields */ +#define RCC_AHB5SECSR_PKASECF BIT(2) +#define RCC_AHB5SECSR_SAESSECF BIT(3) +#define RCC_AHB5SECSR_CRYP1SECF BIT(4) +#define RCC_AHB5SECSR_HASH1SECF BIT(5) +#define RCC_AHB5SECSR_RNG1SECF BIT(6) +#define RCC_AHB5SECSR_BKPSRAMSECF BIT(8) + +/* RCC_AHB6SECSR register fields */ +#define RCC_AHB6SECSR_MCESECF BIT(1) +#define RCC_AHB6SECSR_ETH1SECF_MASK GENMASK_32(11, 7) +#define RCC_AHB6SECSR_ETH1SECF_SHIFT 7 +#define RCC_AHB6SECSR_FMCSECF BIT(12) +#define RCC_AHB6SECSR_QSPISECF BIT(14) +#define RCC_AHB6SECSR_SDMMC1SECF BIT(16) +#define RCC_AHB6SECSR_SDMMC2SECF BIT(17) +#define RCC_AHB6SECSR_ETH2SECF_MASK GENMASK_32(31, 27) +#define RCC_AHB6SECSR_ETH2SECF_SHIFT 27 + +/* RCC_VERR register fields */ +#define RCC_VERR_MINREV_MASK GENMASK_32(3, 0) +#define RCC_VERR_MINREV_SHIFT 0 +#define RCC_VERR_MAJREV_MASK GENMASK_32(7, 4) +#define RCC_VERR_MAJREV_SHIFT 4 + +/* RCC_IDR register fields */ +#define RCC_IDR_ID_MASK GENMASK_32(31, 0) +#define RCC_IDR_ID_SHIFT 0 + +/* RCC_SIDR register fields */ +#define RCC_SIDR_SID_MASK GENMASK_32(31, 0) +#define RCC_SIDR_SID_SHIFT 0 + +/* Used for all RCC_PLLCR registers */ +#define RCC_PLLNCR_PLLON BIT(0) +#define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) +#define RCC_PLLNCR_DIVPEN BIT(4) +#define RCC_PLLNCR_DIVQEN BIT(5) +#define RCC_PLLNCR_DIVREN BIT(6) +#define RCC_PLLNCR_DIVEN_SHIFT 4 + +/* Used for all RCC_PLLCFGR1 registers */ +#define RCC_PLLNCFGR1_DIVM_SHIFT 16 +#define RCC_PLLNCFGR1_DIVM_MASK GENMASK_32(21, 16) +#define RCC_PLLNCFGR1_DIVN_SHIFT 0 +#define RCC_PLLNCFGR1_DIVN_MASK GENMASK_32(8, 0) + +/* Only for PLL3 and PLL4 */ +#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 +#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK_32(25, 24) + +/* Used for all RCC_PLLCFGR2 registers */ +#define RCC_PLLNCFGR2_DIVX_MASK GENMASK_32(6, 0) +#define RCC_PLLNCFGR2_DIVP_SHIFT 0 +#define RCC_PLLNCFGR2_DIVP_MASK GENMASK_32(6, 0) +#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 +#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK_32(14, 8) +#define RCC_PLLNCFGR2_DIVR_SHIFT 16 +#define RCC_PLLNCFGR2_DIVR_MASK GENMASK_32(22, 16) + +/* Used for all RCC_PLLFRACR registers */ +#define RCC_PLLNFRACR_FRACV_SHIFT 3 +#define RCC_PLLNFRACR_FRACV_MASK GENMASK_32(15, 3) +#define RCC_PLLNFRACR_FRACLE BIT(16) + +/* Used for all RCC_PLLCSGR registers */ +#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 +#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK_32(30, 16) +#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 +#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK_32(12, 0) +#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 +#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) + +/* Used for most of RCC_SELR registers */ +#define RCC_SELR_SRC_MASK GENMASK_32(2, 0) +#define RCC_SELR_REFCLK_SRC_MASK GENMASK_32(1, 0) +#define RCC_SELR_SRCRDY BIT(31) + +/* Values of RCC_MPCKSELR register */ +#define RCC_MPCKSELR_HSI 0x00000000 +#define RCC_MPCKSELR_HSE 0x00000001 +#define RCC_MPCKSELR_PLL 0x00000002 +#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 + +/* Values of RCC_ASSCKSELR register */ +#define RCC_ASSCKSELR_HSI 0x00000000 +#define RCC_ASSCKSELR_HSE 0x00000001 +#define RCC_ASSCKSELR_PLL 0x00000002 + +/* Values of RCC_MSSCKSELR register */ +#define RCC_MSSCKSELR_HSI 0x00000000 +#define RCC_MSSCKSELR_HSE 0x00000001 +#define RCC_MSSCKSELR_CSI 0x00000002 +#define RCC_MSSCKSELR_PLL 0x00000003 + +/* Values of RCC_CPERCKSELR register */ +#define RCC_CPERCKSELR_HSI 0x00000000 +#define RCC_CPERCKSELR_CSI 0x00000001 +#define RCC_CPERCKSELR_HSE 0x00000002 + +/* Used for most of DIVR register: max div for RTC */ +#define RCC_DIVR_DIV_MASK GENMASK_32(5, 0) +#define RCC_DIVR_DIVRDY BIT(31) + +/* Masks for specific DIVR registers */ +#define RCC_APBXDIV_MASK GENMASK_32(2, 0) +#define RCC_MPUDIV_MASK GENMASK_32(2, 0) +#define RCC_AXIDIV_MASK GENMASK_32(2, 0) +#define RCC_MLAHBDIV_MASK GENMASK_32(3, 0) + +/* Used for TIMER Prescaler */ +#define RCC_TIMGXPRER_TIMGXPRE BIT(0) + +/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ +#define RCC_MP_ENCLRR_OFFSET U(4) + +/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ +#define RCC_RSTCLRR_OFFSET U(4) + +/* RCC_OCENSETR register fields */ +#define RCC_OCENR_HSION BIT(0) +#define RCC_OCENR_HSIKERON BIT(1) +#define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_CSIKERON BIT(5) +#define RCC_OCENR_DIGBYP BIT(7) +#define RCC_OCENR_HSEON BIT(8) +#define RCC_OCENR_HSEKERON BIT(9) +#define RCC_OCENR_HSEBYP BIT(10) +#define RCC_OCENR_HSECSSON BIT(11) + +#define RCC_OCENR_DIGBYP_BIT 7 +#define RCC_OCENR_HSEBYP_BIT 10 +#define RCC_OCENR_HSECSSON_BIT 11 + +/* Used for RCC_MCO related operations */ +#define RCC_MCOCFG_MCOON BIT(12) +#define RCC_MCOCFG_MCODIV_MASK GENMASK_32(7, 4) +#define RCC_MCOCFG_MCODIV_SHIFT 4 +#define RCC_MCOCFG_MCOSRC_MASK GENMASK_32(2, 0) + +#define RCC_UART4CKSELR_HSI 0x00000002 + +#define RCC_CPERCKSELR_PERSRC_MASK GENMASK_32(1, 0) +#define RCC_CPERCKSELR_PERSRC_SHIFT 0 + +#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) +#define RCC_USBCKSELR_USBOSRC_SHIFT 4 + +#define RCC_DDRITFCR_DDRCKMOD_SSR 0 +#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) +#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) + +#define RCC_DDRITFCR_DDRC2EN BIT(0) +#define RCC_DDRITFCR_DDRC2LPEN BIT(1) + +#define RCC_MP_CIFR_MASK U(0x110F1F) +#define RCC_OFFSET_MASK GENMASK_32(11, 0) + +vaddr_t stm32_rcc_base(void); + +#endif /*__DRIVERS_STM32MP13_RCC_H__*/ diff --git a/optee/optee_os/core/include/drivers/stm32mp1_rcc.h b/optee/optee_os/core/include/drivers/stm32mp1_rcc.h new file mode 100644 index 0000000..311cea8 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32mp1_rcc.h @@ -0,0 +1,566 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2017-2018, STMicroelectronics + */ + +#ifndef __DRIVERS_STM32MP1_RCC_H__ +#define __DRIVERS_STM32MP1_RCC_H__ + +#include +#include +#include + +#define RCC_TZCR 0x00 +#define RCC_OCENSETR 0x0C +#define RCC_OCENCLRR 0x10 +#define RCC_HSICFGR 0x18 +#define RCC_CSICFGR 0x1C +#define RCC_MPCKSELR 0x20 +#define RCC_ASSCKSELR 0x24 +#define RCC_RCK12SELR 0x28 +#define RCC_MPCKDIVR 0x2C +#define RCC_AXIDIVR 0x30 +#define RCC_APB4DIVR 0x3C +#define RCC_APB5DIVR 0x40 +#define RCC_RTCDIVR 0x44 +#define RCC_MSSCKSELR 0x48 +#define RCC_PLL1CR 0x80 +#define RCC_PLL1CFGR1 0x84 +#define RCC_PLL1CFGR2 0x88 +#define RCC_PLL1FRACR 0x8C +#define RCC_PLL1CSGR 0x90 +#define RCC_PLL2CR 0x94 +#define RCC_PLL2CFGR1 0x98 +#define RCC_PLL2CFGR2 0x9C +#define RCC_PLL2FRACR 0xA0 +#define RCC_PLL2CSGR 0xA4 +#define RCC_I2C46CKSELR 0xC0 +#define RCC_SPI6CKSELR 0xC4 +#define RCC_UART1CKSELR 0xC8 +#define RCC_RNG1CKSELR 0xCC +#define RCC_CPERCKSELR 0xD0 +#define RCC_STGENCKSELR 0xD4 +#define RCC_DDRITFCR 0xD8 +#define RCC_MP_BOOTCR 0x100 +#define RCC_MP_SREQSETR 0x104 +#define RCC_MP_SREQCLRR 0x108 +#define RCC_MP_GCR 0x10C +#define RCC_MP_APRSTCR 0x110 +#define RCC_MP_APRSTSR 0x114 +#define RCC_BDCR 0x140 +#define RCC_RDLSICR 0x144 +#define RCC_APB4RSTSETR 0x180 +#define RCC_APB4RSTCLRR 0x184 +#define RCC_APB5RSTSETR 0x188 +#define RCC_APB5RSTCLRR 0x18C +#define RCC_AHB5RSTSETR 0x190 +#define RCC_AHB5RSTCLRR 0x194 +#define RCC_AHB6RSTSETR 0x198 +#define RCC_AHB6RSTCLRR 0x19C +#define RCC_TZAHB6RSTSETR 0x1A0 +#define RCC_TZAHB6RSTCLRR 0x1A4 +#define RCC_MP_APB4ENSETR 0x200 +#define RCC_MP_APB4ENCLRR 0x204 +#define RCC_MP_APB5ENSETR 0x208 +#define RCC_MP_APB5ENCLRR 0x20C +#define RCC_MP_AHB5ENSETR 0x210 +#define RCC_MP_AHB5ENCLRR 0x214 +#define RCC_MP_AHB6ENSETR 0x218 +#define RCC_MP_AHB6ENCLRR 0x21C +#define RCC_MP_TZAHB6ENSETR 0x220 +#define RCC_MP_TZAHB6ENCLRR 0x224 +#define RCC_MC_APB4ENSETR 0x280 +#define RCC_MC_APB4ENCLRR 0x284 +#define RCC_MC_APB5ENSETR 0x288 +#define RCC_MC_APB5ENCLRR 0x28C +#define RCC_MC_AHB5ENSETR 0x290 +#define RCC_MC_AHB5ENCLRR 0x294 +#define RCC_MC_AHB6ENSETR 0x298 +#define RCC_MC_AHB6ENCLRR 0x29C +#define RCC_MP_APB4LPENSETR 0x300 +#define RCC_MP_APB4LPENCLRR 0x304 +#define RCC_MP_APB5LPENSETR 0x308 +#define RCC_MP_APB5LPENCLRR 0x30C +#define RCC_MP_AHB5LPENSETR 0x310 +#define RCC_MP_AHB5LPENCLRR 0x314 +#define RCC_MP_AHB6LPENSETR 0x318 +#define RCC_MP_AHB6LPENCLRR 0x31C +#define RCC_MP_TZAHB6LPENSETR 0x320 +#define RCC_MP_TZAHB6LPENCLRR 0x324 +#define RCC_MC_APB4LPENSETR 0x380 +#define RCC_MC_APB4LPENCLRR 0x384 +#define RCC_MC_APB5LPENSETR 0x388 +#define RCC_MC_APB5LPENCLRR 0x38C +#define RCC_MC_AHB5LPENSETR 0x390 +#define RCC_MC_AHB5LPENCLRR 0x394 +#define RCC_MC_AHB6LPENSETR 0x398 +#define RCC_MC_AHB6LPENCLRR 0x39C +#define RCC_BR_RSTSCLRR 0x400 +#define RCC_MP_GRSTCSETR 0x404 +#define RCC_MP_RSTSCLRR 0x408 +#define RCC_MP_IWDGFZSETR 0x40C +#define RCC_MP_IWDGFZCLRR 0x410 +#define RCC_MP_CIER 0x414 +#define RCC_MP_CIFR 0x418 +#define RCC_PWRLPDLYCR 0x41C +#define RCC_MP_RSTSSETR 0x420 +#define RCC_MCO1CFGR 0x800 +#define RCC_MCO2CFGR 0x804 +#define RCC_OCRDYR 0x808 +#define RCC_DBGCFGR 0x80C +#define RCC_RCK3SELR 0x820 +#define RCC_RCK4SELR 0x824 +#define RCC_TIMG1PRER 0x828 +#define RCC_TIMG2PRER 0x82C +#define RCC_MCUDIVR 0x830 +#define RCC_APB1DIVR 0x834 +#define RCC_APB2DIVR 0x838 +#define RCC_APB3DIVR 0x83C +#define RCC_PLL3CR 0x880 +#define RCC_PLL3CFGR1 0x884 +#define RCC_PLL3CFGR2 0x888 +#define RCC_PLL3FRACR 0x88C +#define RCC_PLL3CSGR 0x890 +#define RCC_PLL4CR 0x894 +#define RCC_PLL4CFGR1 0x898 +#define RCC_PLL4CFGR2 0x89C +#define RCC_PLL4FRACR 0x8A0 +#define RCC_PLL4CSGR 0x8A4 +#define RCC_I2C12CKSELR 0x8C0 +#define RCC_I2C35CKSELR 0x8C4 +#define RCC_SAI1CKSELR 0x8C8 +#define RCC_SAI2CKSELR 0x8CC +#define RCC_SAI3CKSELR 0x8D0 +#define RCC_SAI4CKSELR 0x8D4 +#define RCC_SPI2S1CKSELR 0x8D8 +#define RCC_SPI2S23CKSELR 0x8DC +#define RCC_SPI45CKSELR 0x8E0 +#define RCC_UART6CKSELR 0x8E4 +#define RCC_UART24CKSELR 0x8E8 +#define RCC_UART35CKSELR 0x8EC +#define RCC_UART78CKSELR 0x8F0 +#define RCC_SDMMC12CKSELR 0x8F4 +#define RCC_SDMMC3CKSELR 0x8F8 +#define RCC_ETHCKSELR 0x8FC +#define RCC_QSPICKSELR 0x900 +#define RCC_FMCCKSELR 0x904 +#define RCC_FDCANCKSELR 0x90C +#define RCC_SPDIFCKSELR 0x914 +#define RCC_CECCKSELR 0x918 +#define RCC_USBCKSELR 0x91C +#define RCC_RNG2CKSELR 0x920 +#define RCC_DSICKSELR 0x924 +#define RCC_ADCCKSELR 0x928 +#define RCC_LPTIM45CKSELR 0x92C +#define RCC_LPTIM23CKSELR 0x930 +#define RCC_LPTIM1CKSELR 0x934 +#define RCC_APB1RSTSETR 0x980 +#define RCC_APB1RSTCLRR 0x984 +#define RCC_APB2RSTSETR 0x988 +#define RCC_APB2RSTCLRR 0x98C +#define RCC_APB3RSTSETR 0x990 +#define RCC_APB3RSTCLRR 0x994 +#define RCC_AHB2RSTSETR 0x998 +#define RCC_AHB2RSTCLRR 0x99C +#define RCC_AHB3RSTSETR 0x9A0 +#define RCC_AHB3RSTCLRR 0x9A4 +#define RCC_AHB4RSTSETR 0x9A8 +#define RCC_AHB4RSTCLRR 0x9AC +#define RCC_MP_APB1ENSETR 0xA00 +#define RCC_MP_APB1ENCLRR 0xA04 +#define RCC_MP_APB2ENSETR 0xA08 +#define RCC_MP_APB2ENCLRR 0xA0C +#define RCC_MP_APB3ENSETR 0xA10 +#define RCC_MP_APB3ENCLRR 0xA14 +#define RCC_MP_AHB2ENSETR 0xA18 +#define RCC_MP_AHB2ENCLRR 0xA1C +#define RCC_MP_AHB3ENSETR 0xA20 +#define RCC_MP_AHB3ENCLRR 0xA24 +#define RCC_MP_AHB4ENSETR 0xA28 +#define RCC_MP_AHB4ENCLRR 0xA2C +#define RCC_MP_MLAHBENSETR 0xA38 +#define RCC_MP_MLAHBENCLRR 0xA3C +#define RCC_MC_APB1ENSETR 0xA80 +#define RCC_MC_APB1ENCLRR 0xA84 +#define RCC_MC_APB2ENSETR 0xA88 +#define RCC_MC_APB2ENCLRR 0xA8C +#define RCC_MC_APB3ENSETR 0xA90 +#define RCC_MC_APB3ENCLRR 0xA94 +#define RCC_MC_AHB2ENSETR 0xA98 +#define RCC_MC_AHB2ENCLRR 0xA9C +#define RCC_MC_AHB3ENSETR 0xAA0 +#define RCC_MC_AHB3ENCLRR 0xAA4 +#define RCC_MC_AHB4ENSETR 0xAA8 +#define RCC_MC_AHB4ENCLRR 0xAAC +#define RCC_MC_AXIMENSETR 0xAB0 +#define RCC_MC_AXIMENCLRR 0xAB4 +#define RCC_MC_MLAHBENSETR 0xAB8 +#define RCC_MC_MLAHBENCLRR 0xABC +#define RCC_MP_APB1LPENSETR 0xB00 +#define RCC_MP_APB1LPENCLRR 0xB04 +#define RCC_MP_APB2LPENSETR 0xB08 +#define RCC_MP_APB2LPENCLRR 0xB0C +#define RCC_MP_APB3LPENSETR 0xB10 +#define RCC_MP_APB3LPENCLRR 0xB14 +#define RCC_MP_AHB2LPENSETR 0xB18 +#define RCC_MP_AHB2LPENCLRR 0xB1C +#define RCC_MP_AHB3LPENSETR 0xB20 +#define RCC_MP_AHB3LPENCLRR 0xB24 +#define RCC_MP_AHB4LPENSETR 0xB28 +#define RCC_MP_AHB4LPENCLRR 0xB2C +#define RCC_MP_AXIMLPENSETR 0xB30 +#define RCC_MP_AXIMLPENCLRR 0xB34 +#define RCC_MP_MLAHBLPENSETR 0xB38 +#define RCC_MP_MLAHBLPENCLRR 0xB3C +#define RCC_MC_APB1LPENSETR 0xB80 +#define RCC_MC_APB1LPENCLRR 0xB84 +#define RCC_MC_APB2LPENSETR 0xB88 +#define RCC_MC_APB2LPENCLRR 0xB8C +#define RCC_MC_APB3LPENSETR 0xB90 +#define RCC_MC_APB3LPENCLRR 0xB94 +#define RCC_MC_AHB2LPENSETR 0xB98 +#define RCC_MC_AHB2LPENCLRR 0xB9C +#define RCC_MC_AHB3LPENSETR 0xBA0 +#define RCC_MC_AHB3LPENCLRR 0xBA4 +#define RCC_MC_AHB4LPENSETR 0xBA8 +#define RCC_MC_AHB4LPENCLRR 0xBAC +#define RCC_MC_AXIMLPENSETR 0xBB0 +#define RCC_MC_AXIMLPENCLRR 0xBB4 +#define RCC_MC_MLAHBLPENSETR 0xBB8 +#define RCC_MC_MLAHBLPENCLRR 0xBBC +#define RCC_MC_RSTSCLRR 0xC00 +#define RCC_MC_CIER 0xC14 +#define RCC_MC_CIFR 0xC18 +#define RCC_VERR 0xFF4 +#define RCC_IDR 0xFF8 +#define RCC_SIDR 0xFFC + +#define RCC_OFFSET_MASK GENMASK_32(11, 0) + +/* Values for RCC_TZCR register */ +#define RCC_TZCR_TZEN BIT(0) +#define RCC_TZCR_MCKPROT BIT(1) + +/* Used for most of RCC_SELR registers */ +#define RCC_SELR_SRC_MASK GENMASK_32(2, 0) +#define RCC_SELR_REFCLK_SRC_MASK GENMASK_32(1, 0) +#define RCC_SELR_SRCRDY BIT(31) + +/* Values of RCC_MPCKSELR register */ +#define RCC_MPCKSELR_HSI 0x00000000 +#define RCC_MPCKSELR_HSE 0x00000001 +#define RCC_MPCKSELR_PLL 0x00000002 +#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 + +/* Values of RCC_ASSCKSELR register */ +#define RCC_ASSCKSELR_HSI 0x00000000 +#define RCC_ASSCKSELR_HSE 0x00000001 +#define RCC_ASSCKSELR_PLL 0x00000002 + +/* Values of RCC_MSSCKSELR register */ +#define RCC_MSSCKSELR_HSI 0x00000000 +#define RCC_MSSCKSELR_HSE 0x00000001 +#define RCC_MSSCKSELR_CSI 0x00000002 +#define RCC_MSSCKSELR_PLL 0x00000003 + +/* Values of RCC_CPERCKSELR register */ +#define RCC_CPERCKSELR_HSI 0x00000000 +#define RCC_CPERCKSELR_CSI 0x00000001 +#define RCC_CPERCKSELR_HSE 0x00000002 + +/* used for most of RCC_DIVR registers: max div for RTC */ +#define RCC_DIVR_DIV_MASK GENMASK_32(5, 0) +#define RCC_DIVR_DIVRDY BIT(31) + +/* Masks for specific DIVR registers */ +#define RCC_APBXDIV_MASK GENMASK_32(2, 0) +#define RCC_MPUDIV_MASK GENMASK_32(2, 0) +#define RCC_AXIDIV_MASK GENMASK_32(2, 0) +#define RCC_MCUDIV_MASK GENMASK_32(3, 0) + +/* Used for TIMER Prescaler */ +#define RCC_TIMGXPRER_TIMGXPRE BIT(0) + +/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ +#define RCC_MP_ENCLRR_OFFSET 4u + +/* Offset between RCC_MP_xxxRSTSETR and RCC_MP_xxxRSTCLRR registers */ +#define RCC_MP_RSTCLRR_OFFSET 4u + +/* Fields of RCC_BDCR register */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK_32(5, 4) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_RTCCKEN_POS 20 +#define RCC_BDCR_RTCCKEN BIT(RCC_BDCR_RTCCKEN_POS) +#define RCC_BDCR_RTCSRC_MASK GENMASK_32(17, 16) +#define RCC_BDCR_RTCSRC_SHIFT 16 +#define RCC_BDCR_VSWRST BIT(31) + +/* Fields of RCC_RDLSICR register */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) + +/* Used for all RCC_PLLCR registers */ +#define RCC_PLLNCR_PLLON BIT(0) +#define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) +#define RCC_PLLNCR_DIVPEN BIT(4) +#define RCC_PLLNCR_DIVQEN BIT(5) +#define RCC_PLLNCR_DIVREN BIT(6) +#define RCC_PLLNCR_DIVEN_SHIFT 4 + +/* Used for all RCC_PLLCFGR1 registers */ +#define RCC_PLLNCFGR1_DIVM_SHIFT 16 +#define RCC_PLLNCFGR1_DIVM_MASK GENMASK_32(21, 16) +#define RCC_PLLNCFGR1_DIVN_SHIFT 0 +#define RCC_PLLNCFGR1_DIVN_MASK GENMASK_32(8, 0) +/* Only for PLL3 and PLL4 */ +#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 +#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK_32(25, 24) + +/* Used for all RCC_PLLCFGR2 registers */ +#define RCC_PLLNCFGR2_DIVX_MASK GENMASK_32(6, 0) +#define RCC_PLLNCFGR2_DIVP_SHIFT 0 +#define RCC_PLLNCFGR2_DIVP_MASK GENMASK_32(6, 0) +#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 +#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK_32(14, 8) +#define RCC_PLLNCFGR2_DIVR_SHIFT 16 +#define RCC_PLLNCFGR2_DIVR_MASK GENMASK_32(22, 16) + +/* Used for all RCC_PLLFRACR registers */ +#define RCC_PLLNFRACR_FRACV_SHIFT 3 +#define RCC_PLLNFRACR_FRACV_MASK GENMASK_32(15, 3) +#define RCC_PLLNFRACR_FRACLE BIT(16) + +/* Used for all RCC_PLLCSGR registers */ +#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 +#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK_32(30, 16) +#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 +#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK_32(12, 0) +#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 +#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) + +/* Used for RCC_OCENSETR and RCC_OCENCLRR registers */ +#define RCC_OCENR_HSION BIT(0) +#define RCC_OCENR_HSIKERON BIT(1) +#define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_CSIKERON BIT(5) +#define RCC_OCENR_DIGBYP BIT(7) +#define RCC_OCENR_HSEON BIT(8) +#define RCC_OCENR_HSEKERON BIT(9) +#define RCC_OCENR_HSEBYP BIT(10) +#define RCC_OCENR_HSECSSON BIT(11) + +/* Fields of RCC_OCRDYR register */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) + +/* Fields of RCC_DDRITFCR register */ +#define RCC_DDRITFCR_DDRC1EN BIT(0) +#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +#define RCC_DDRITFCR_DDRC2EN BIT(2) +#define RCC_DDRITFCR_DDRC2LPEN BIT(3) +#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +#define RCC_DDRITFCR_AXIDCGEN BIT(8) +#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +#define RCC_DDRITFCR_DDRCORERST BIT(16) +#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +#define RCC_DDRITFCR_DPHYRST BIT(18) +#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK_32(22, 20) +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_DDRCKMOD_SSR 0 +#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) +#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) +#define RCC_DDRITFCR_GSKPCTRL BIT(24) + +/* Fields of RCC_HSICFGR register */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK_32(1, 0) +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSITRIM_MASK GENMASK_32(14, 8) +#define RCC_HSICFGR_HSICAL_SHIFT 16 +#define RCC_HSICFGR_HSICAL_MASK GENMASK_32(27, 16) + +/* Fields of RCC_CSICFGR register */ +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSITRIM_MASK GENMASK_32(12, 8) +#define RCC_CSICFGR_CSICAL_SHIFT 16 +#define RCC_CSICFGR_CSICAL_MASK GENMASK_32(23, 16) + +/* Used for RCC_MCO related operations */ +#define RCC_MCOCFG_MCOON BIT(12) +#define RCC_MCOCFG_MCODIV_MASK GENMASK_32(7, 4) +#define RCC_MCOCFG_MCODIV_SHIFT 4 +#define RCC_MCOCFG_MCOSRC_MASK GENMASK_32(2, 0) + +/* Fields of RCC_DBGCFGR register */ +#define RCC_DBGCFGR_DBGCKEN BIT(8) + +/* RCC register fields for reset reasons */ +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_MCSYSRSTF BIT(7) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) + +/* Global Reset Register */ +#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MCURST BIT(1) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) +#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5) + +/* Clock Source Interrupt Flag Register */ +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) +#define RCC_MP_CIFR_LSECSSF BIT(16) +#define RCC_MP_CIFR_WKUPF BIT(20) +#define RCC_MP_CIFR_MASK (RCC_MP_CIFR_LSIRDYF | RCC_MP_CIFR_LSERDYF | \ + RCC_MP_CIFR_HSIRDYF | RCC_MP_CIFR_HSERDYF | \ + RCC_MP_CIFR_CSIRDYF | RCC_MP_CIFR_PLL1DYF | \ + RCC_MP_CIFR_PLL2DYF | RCC_MP_CIFR_PLL3DYF | \ + RCC_MP_CIFR_PLL4DYF | RCC_MP_CIFR_LSECSSF | \ + RCC_MP_CIFR_WKUPF) + +/* Stop Request Set Register */ +#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) +#define RCC_MP_SREQSETR_STPREQ_P1 BIT(1) + +/* Stop Request Clear Register */ +#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) +#define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) + +/* Global Control Register */ +#define RCC_MP_GCR_BOOT_MCU BIT(0) + +/* RCC_MP_APB5RST(SET|CLR)R bit fields */ +#define RCC_APB5RSTSETR_SPI6RST BIT(0) +#define RCC_APB5RSTSETR_I2C4RST BIT(2) +#define RCC_APB5RSTSETR_I2C6RST BIT(3) +#define RCC_APB5RSTSETR_USART1RST BIT(4) +#define RCC_APB5RSTSETR_STGENRST BIT(20) + +/* RCC_MP_APB1EN(SET|CLR)R bit fields */ +#define RCC_MP_APB1ENSETR_I2C5EN_POS 24 + +#define RCC_MP_APB1ENSETR_I2C5EN BIT(RCC_MP_APB1ENSETR_I2C5EN_POS) + +/* RCC_MP_APB5EN(SET|CLR)R bit fields */ +#define RCC_MP_APB5ENSETR_SPI6EN_POS 0 +#define RCC_MP_APB5ENSETR_I2C4EN_POS 2 +#define RCC_MP_APB5ENSETR_I2C6EN_POS 3 +#define RCC_MP_APB5ENSETR_USART1EN_POS 4 +#define RCC_MP_APB5ENSETR_RTCAPBEN_POS 8 +#define RCC_MP_APB5ENSETR_TZC1EN_POS 11 +#define RCC_MP_APB5ENSETR_TZC2EN_POS 12 +#define RCC_MP_APB5ENSETR_TZPCEN_POS 13 +#define RCC_MP_APB5ENSETR_IWDG1APBEN_POS 15 +#define RCC_MP_APB5ENSETR_BSECEN_POS 16 +#define RCC_MP_APB5ENSETR_STGENEN_POS 20 + +#define RCC_MP_APB5ENSETR_SPI6EN BIT(RCC_MP_APB5ENSETR_SPI6EN_POS) +#define RCC_MP_APB5ENSETR_I2C4EN BIT(RCC_MP_APB5ENSETR_I2C4EN_POS) +#define RCC_MP_APB5ENSETR_I2C6EN BIT(RCC_MP_APB5ENSETR_I2C6EN_POS) +#define RCC_MP_APB5ENSETR_USART1EN BIT(RCC_MP_APB5ENSETR_USART1EN_POS) +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(RCC_MP_APB5ENSETR_RTCAPBEN_POS) +#define RCC_MP_APB5ENSETR_TZC1EN BIT(RCC_MP_APB5ENSETR_TZC1EN_POS) +#define RCC_MP_APB5ENSETR_TZC2EN BIT(RCC_MP_APB5ENSETR_TZC2EN_POS) +#define RCC_MP_APB5ENSETR_TZPCEN BIT(RCC_MP_APB5ENSETR_TZPCEN_POS) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(RCC_MP_APB5ENSETR_IWDG1APBEN_POS) +#define RCC_MP_APB5ENSETR_BSECEN BIT(RCC_MP_APB5ENSETR_BSECEN_POS) +#define RCC_MP_APB5ENSETR_STGENEN BIT(RCC_MP_APB5ENSETR_STGENEN_POS) + +/* RCC_MP_APB5LPEN(SET|CLR)R bit fields */ +#define RCC_MP_APB5LPENSETR_SPI6LPEN BIT(0) +#define RCC_MP_APB5LPENSETR_I2C4LPEN BIT(2) +#define RCC_MP_APB5LPENSETR_I2C6LPEN BIT(3) +#define RCC_MP_APB5LPENSETR_USART1LPEN BIT(4) +#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENSETR_TZC1LPEN BIT(11) +#define RCC_MP_APB5LPENSETR_TZC2LPEN BIT(12) +#define RCC_MP_APB5LPENSETR_TZPCLPEN BIT(13) +#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENSETR_STGENLPEN BIT(20) +#define RCC_MP_APB5LPENSETR_STGENSTPEN BIT(21) + +/* RCC_MP_AHB5RST(SET|CLR)R bit fields */ +#define RCC_AHB5RSTSETR_GPIOZRST BIT(0) +#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + +/* RCC_MP_AHB5EN(SET|CLR)R bit fields */ +#define RCC_MP_AHB5ENSETR_GPIOZEN_POS 0 +#define RCC_MP_AHB5ENSETR_CRYP1EN_POS 4 +#define RCC_MP_AHB5ENSETR_HASH1EN_POS 5 +#define RCC_MP_AHB5ENSETR_RNG1EN_POS 6 +#define RCC_MP_AHB5ENSETR_BKPSRAMEN_POS 8 +#define RCC_MP_AHB5ENSETR_AXIMCEN_POS 16 + +#define RCC_MP_AHB5ENSETR_GPIOZEN BIT(RCC_MP_AHB5ENSETR_GPIOZEN_POS) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(RCC_MP_AHB5ENSETR_CRYP1EN_POS) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(RCC_MP_AHB5ENSETR_HASH1EN_POS) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(RCC_MP_AHB5ENSETR_RNG1EN_POS) +#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(RCC_MP_AHB5ENSETR_BKPSRAMEN_POS) +#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(RCC_MP_AHB5ENSETR_AXIMCEN_POS) + +/* RCC_MP_AHB5LPEN(SET|CLR)R bit fields */ +#define RCC_MP_AHB5LPENSETR_GPIOZLPEN BIT(0) +#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_TZAHB6EN(SET|CLR)R bit fields */ +#define RCC_MP_TZAHB6ENSETR_MDMA_POS 0 +#define RCC_MP_TZAHB6ENSETR_MDMA BIT(RCC_MP_TZAHB6ENSETR_MDMA_POS) + +/* RCC_MP_IWDGFZ(SET|CLR)R bit fields */ +#define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_IWDG2 BIT(1) + +#define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" +#define DT_RCC_SECURE_CLK_COMPAT "st,stm32mp1-rcc-secure" + +#ifndef __ASSEMBLER__ +#include + +static inline bool stm32_rcc_is_secure(void) +{ + return io_read32(stm32_rcc_base() + RCC_TZCR) & RCC_TZCR_TZEN; +} + +static inline bool stm32_rcc_is_mckprot(void) +{ + return io_read32(stm32_rcc_base() + RCC_TZCR) & RCC_TZCR_MCKPROT; +} +#endif /*__ASSEMBLER__*/ + +#endif /*__DRIVERS_STM32MP1_RCC_H__*/ diff --git a/optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h b/optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h new file mode 100644 index 0000000..2d7a27c --- /dev/null +++ b/optee/optee_os/core/include/drivers/stm32mp_dt_bindings.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, STMicroelectronics + */ +#ifndef STM32MP_DT_BINDINGS_H +#define STM32MP_DT_BINDINGS_H + +#ifdef CFG_STM32MP13 +#include +#include +#include +#include +#endif + +#ifdef CFG_STM32MP15 +#include +#include +#include +#endif + +#endif /* STM32MP_DT_BINDINGS_H */ diff --git a/optee/optee_os/core/include/drivers/stpmic1.h b/optee/optee_os/core/include/drivers/stpmic1.h new file mode 100644 index 0000000..0d020ca --- /dev/null +++ b/optee/optee_os/core/include/drivers/stpmic1.h @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved + */ + +#ifndef __STPMIC1_H__ +#define __STPMIC1_H__ + +#include +#include + +#define TURN_ON_REG 0x1U +#define TURN_OFF_REG 0x2U +#define ICC_LDO_TURN_OFF_REG 0x3U +#define ICC_BUCK_TURN_OFF_REG 0x4U +#define RESET_STATUS_REG 0x5U +#define VERSION_STATUS_REG 0x6U +#define MAIN_CONTROL_REG 0x10U +#define PADS_PULL_REG 0x11U +#define BUCK_PULL_DOWN_REG 0x12U +#define LDO14_PULL_DOWN_REG 0x13U +#define LDO56_PULL_DOWN_REG 0x14U +#define VIN_CONTROL_REG 0x15U +#define PONKEY_TIMER_REG 0x16U +#define MASK_RANK_BUCK_REG 0x17U +#define MASK_RESET_BUCK_REG 0x18U +#define MASK_RANK_LDO_REG 0x19U +#define MASK_RESET_LDO_REG 0x1AU +#define WATCHDOG_CONTROL_REG 0x1BU +#define WATCHDOG_TIMER_REG 0x1CU +#define BUCK_ICC_TURNOFF_REG 0x1DU +#define LDO_ICC_TURNOFF_REG 0x1EU +#define BUCK_APM_CONTROL_REG 0x1FU +#define BUCK1_CONTROL_REG 0x20U +#define BUCK2_CONTROL_REG 0x21U +#define BUCK3_CONTROL_REG 0x22U +#define BUCK4_CONTROL_REG 0x23U +#define VREF_DDR_CONTROL_REG 0x24U +#define LDO1_CONTROL_REG 0x25U +#define LDO2_CONTROL_REG 0x26U +#define LDO3_CONTROL_REG 0x27U +#define LDO4_CONTROL_REG 0x28U +#define LDO5_CONTROL_REG 0x29U +#define LDO6_CONTROL_REG 0x2AU +#define BUCK1_PWRCTRL_REG 0x30U +#define BUCK2_PWRCTRL_REG 0x31U +#define BUCK3_PWRCTRL_REG 0x32U +#define BUCK4_PWRCTRL_REG 0x33U +#define VREF_DDR_PWRCTRL_REG 0x34U +#define LDO1_PWRCTRL_REG 0x35U +#define LDO2_PWRCTRL_REG 0x36U +#define LDO3_PWRCTRL_REG 0x37U +#define LDO4_PWRCTRL_REG 0x38U +#define LDO5_PWRCTRL_REG 0x39U +#define LDO6_PWRCTRL_REG 0x3AU +#define FREQUENCY_SPREADING_REG 0x3BU +#define USB_CONTROL_REG 0x40U +#define ITLATCH1_REG 0x50U +#define ITLATCH2_REG 0x51U +#define ITLATCH3_REG 0x52U +#define ITLATCH4_REG 0x53U +#define ITSETLATCH1_REG 0x60U +#define ITSETLATCH2_REG 0x61U +#define ITSETLATCH3_REG 0x62U +#define ITSETLATCH4_REG 0x63U +#define ITCLEARLATCH1_REG 0x70U +#define ITCLEARLATCH2_REG 0x71U +#define ITCLEARLATCH3_REG 0x72U +#define ITCLEARLATCH4_REG 0x73U +#define ITMASK1_REG 0x80U +#define ITMASK2_REG 0x81U +#define ITMASK3_REG 0x82U +#define ITMASK4_REG 0x83U +#define ITSETMASK1_REG 0x90U +#define ITSETMASK2_REG 0x91U +#define ITSETMASK3_REG 0x92U +#define ITSETMASK4_REG 0x93U +#define ITCLEARMASK1_REG 0xA0U +#define ITCLEARMASK2_REG 0xA1U +#define ITCLEARMASK3_REG 0xA2U +#define ITCLEARMASK4_REG 0xA3U +#define ITSOURCE1_REG 0xB0U +#define ITSOURCE2_REG 0xB1U +#define ITSOURCE3_REG 0xB2U +#define ITSOURCE4_REG 0xB3U + +/* Registers masks */ +#define LDO_VOLTAGE_MASK GENMASK_32(6, 2) +#define BUCK_VOLTAGE_MASK GENMASK_32(7, 2) +#define LDO_BUCK_VOLTAGE_SHIFT 2 +#define LDO_BUCK_ENABLE_POS 0 +#define LDO_BUCK_ENABLE_MASK BIT(LDO_BUCK_ENABLE_POS) +#define LDO_BUCK_HPLP_POS 1 +#define LDO_BUCK_RANK_MASK BIT(0) +#define LDO_BUCK_RESET_MASK BIT(0) +#define LDO_BUCK_PULL_DOWN_MASK GENMASK_32(1, 0) + +/* Pull down register */ +#define BUCK1_PULL_DOWN_SHIFT 0 +#define BUCK2_PULL_DOWN_SHIFT 2 +#define BUCK3_PULL_DOWN_SHIFT 4 +#define BUCK4_PULL_DOWN_SHIFT 6 +#define VREF_DDR_PULL_DOWN_SHIFT 4 + +/* Buck Mask reset register */ +#define BUCK1_MASK_RESET_SHIFT 0 +#define BUCK2_MASK_RESET_SHIFT 1 +#define BUCK3_MASK_RESET_SHIFT 2 +#define BUCK4_MASK_RESET_SHIFT 3 + +/* LDO Mask reset register */ +#define LDO1_MASK_RESET_SHIFT 0 +#define LDO2_MASK_RESET_SHIFT 1 +#define LDO3_MASK_RESET_SHIFT 2 +#define LDO4_MASK_RESET_SHIFT 3 +#define LDO5_MASK_RESET_SHIFT 4 +#define LDO6_MASK_RESET_SHIFT 5 +#define VREF_DDR_MASK_RESET_SHIFT 6 + +/* Main PMIC Control Register (MAIN_CONTROL_REG) */ +#define ICC_EVENT_ENABLED BIT(4) +#define PWRCTRL_POLARITY_HIGH BIT(3) +#define PWRCTRL_PIN_VALID BIT(2) +#define RESTART_REQUEST_ENABLED BIT(1) +#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0) + +/* Main PMIC PADS Control Register (PADS_PULL_REG) */ +#define WAKEUP_DETECTOR_DISABLED BIT(4) +#define PWRCTRL_PD_ACTIVE BIT(3) +#define PWRCTRL_PU_ACTIVE BIT(2) +#define WAKEUP_PD_ACTIVE BIT(1) +#define PONKEY_PU_ACTIVE BIT(0) + +/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ +#define SWIN_DETECTOR_ENABLED BIT(7) +#define SWOUT_DETECTOR_ENABLED BIT(6) +#define VINLOW_HYST_MASK GENMASK_32(5, 4) +#define VINLOW_HYST_SHIFT 4 +#define VINLOW_THRESHOLD_MASK GENMASK_32(3, 1) +#define VINLOW_THRESHOLD_SHIFT 1 +#define VINLOW_ENABLED BIT(0) +#define VINLOW_CTRL_REG_MASK GENMASK_32(7, 0) + +/* USB Control Register */ +#define BOOST_OVP_DISABLED_POS 7 +#define VBUS_OTG_DETECTION_DISABLED_POS 6 +#define OCP_LIMIT_HIGH_POS 3 +#define SWIN_SWOUT_ENABLED_POS 2 +#define USBSW_OTG_SWITCH_ENABLED_POS 1 +#define BOOST_ENABLED_POS 0 + +/* + * Bind SPMIC1 device driver with a specific I2C bus instance + * @i2c_handle: target I2C instance to use + * @i2c_addr: I2C address of the STPMIC1 device + */ +void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); + +/* Read STPMIC1 device version information */ +int stpmic1_get_version(unsigned long *version); + +/* Read STPMIC1 device internal registers content */ +void stpmic1_dump_regulators(void); + +/* Enable power control in STPMIC1 device */ +int stpmic1_powerctrl_on(void); + +/* Disable STPMIC1 device */ +int stpmic1_switch_off(void); + +/* Read/write/update STPMIC1 device internal register */ +int stpmic1_register_read(uint8_t register_id, uint8_t *value); +int stpmic1_register_write(uint8_t register_id, uint8_t value); +int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); + +int stpmic1_regulator_mask_reset_set(const char *name); + +/* API for low power configuration of regulators driven from STPMIC1 device */ +int stpmic1_lp_copy_reg(const char *name); +int stpmic1_lp_reg_on_off(const char *name, uint8_t enable); +int stpmic1_lp_set_mode(const char *name, uint8_t hplp); +int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts); + +/* + * Specific API for controlling regulators driven from STPMIC1 device + * from unpaged execution context of the STPMIC1 driver. + */ + +/* + * The STPMIC1 is accessed during low power sequence in unpaged + * execution context. To prevent adding an unpaged constraint on + * STPMIC1 regulator definitions, conversion tables and device tree + * content, the regulators configurations are read from device tree + * at boot time and saved in memory for being applied at runtime + * without needing pager support. + * + * There are 2 types of regulator configuration loaded during such + * low power and unpaged sequences: boot-on (bo) configuration and + * low power (lp) configuration. + */ +struct stpmic1_bo_cfg { + uint8_t ctrl_reg; + uint8_t min_value; + uint8_t enable_pos; + uint8_t mask; + uint8_t pd_reg; + uint8_t pd_value; + uint8_t pd_mask; + uint8_t mrst_reg; + uint8_t mrst_value; + uint8_t mrst_mask; +}; + +struct stpmic1_lp_cfg { + uint8_t ctrl_reg; + uint8_t lp_reg; + uint8_t value; + uint8_t mask; +}; + +int stpmic1_bo_enable_cfg(const char *name, struct stpmic1_bo_cfg *cfg); +int stpmic1_bo_enable_unpg(struct stpmic1_bo_cfg *cfg); +int stpmic1_bo_voltage_cfg(const char *name, uint16_t min_millivolt, + struct stpmic1_bo_cfg *cfg); +int stpmic1_bo_voltage_unpg(struct stpmic1_bo_cfg *cfg); + +int stpmic1_bo_pull_down_cfg(const char *name, + struct stpmic1_bo_cfg *cfg); +int stpmic1_bo_pull_down_unpg(struct stpmic1_bo_cfg *cfg); + +int stpmic1_bo_mask_reset_cfg(const char *name, struct stpmic1_bo_cfg *cfg); +int stpmic1_bo_mask_reset_unpg(struct stpmic1_bo_cfg *cfg); + +bool stpmic1_regu_has_lp_cfg(const char *name); +int stpmic1_lp_cfg(const char *name, struct stpmic1_lp_cfg *cfg); +int stpmic1_lp_load_unpg(struct stpmic1_lp_cfg *cfg); +int stpmic1_lp_on_off_unpg(struct stpmic1_lp_cfg *cfg, int enable); +int stpmic1_lp_mode_unpg(struct stpmic1_lp_cfg *cfg, + unsigned int mode); +int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts, + struct stpmic1_lp_cfg *cfg); +int stpmic1_lp_voltage_unpg(struct stpmic1_lp_cfg *cfg); + +#endif /*__STPMIC1_H__*/ diff --git a/optee/optee_os/core/include/drivers/stpmic1_regulator.h b/optee/optee_os/core/include/drivers/stpmic1_regulator.h new file mode 100644 index 0000000..5e0e655 --- /dev/null +++ b/optee/optee_os/core/include/drivers/stpmic1_regulator.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2022, STMicroelectronics + */ + +#ifndef __DRIVERS_STPMIC1_REGULATOR_H +#define __DRIVERS_STPMIC1_REGULATOR_H + +#include + +/* + * Return true if @name refers to a knwon regulator, return false otherwise + */ +bool stpmic1_regulator_is_valid(const char *name); + +/* + * Enable STPMIC1 regulator identified by @name. + * Return 0 on success and a non-0 value if failing + */ +int stpmic1_regulator_enable(const char *name); + +/* + * Disable STPMIC1 regulator identified by @name. + * Return 0 on success and a non-0 value if failing + */ +int stpmic1_regulator_disable(const char *name); + +/* + * Return true if regulator identified by @name is enabled and false otherwise. + * Return 0 on success and a non-0 value if failing + */ +bool stpmic1_is_regulator_enabled(const char *name); + +/* + * Retrieve regulator levels array (in millivolts) and/or levels count + * @name: regulator identifier + * @levels: output reference for an arrays of the supported levels, or NULL + * @levels_count: output reference for number of supported levels, or NULL + */ +void stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, + size_t *levels_count); + +/* + * Set voltage level @millivolt for target regulator @name + * @name: regulator identifier + * @millivot: target voltage level, in mV + */ +int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); + +/* + * Get current voltage level (in millivolt) for target regulator @name + * @name: regulator identifier + * Return a positive millivolt level on success or a negative value on error + */ +int stpmic1_regulator_voltage_get(const char *name); + +#endif /*__DRIVERS_STPMIC1_REGULATOR_H*/ diff --git a/optee/optee_os/core/include/drivers/tegra/tegra_fuse.h b/optee/optee_os/core/include/drivers/tegra/tegra_fuse.h new file mode 100644 index 0000000..da95cda --- /dev/null +++ b/optee/optee_os/core/include/drivers/tegra/tegra_fuse.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_FUSE_H__ +#define __TEGRA_FUSE_H__ + +#include + +typedef struct tegra_fuse_ecid { + uint32_t ecid[4]; +} fuse_ecid_t; + +#define BSI_OEM_KEY_VALID_MASK 0x200 + +/* + * Get ECID from fuse + */ +fuse_ecid_t* tegra_fuse_get_ecid(void); + +/* + * Get Boot Security Info from fuse + */ +TEE_Result tegra_fuse_get_bsi(uint32_t *val); + +#endif diff --git a/optee/optee_os/core/include/drivers/tegra/tegra_se_aes.h b/optee/optee_os/core/include/drivers/tegra/tegra_se_aes.h new file mode 100644 index 0000000..a5603fd --- /dev/null +++ b/optee/optee_os/core/include/drivers/tegra/tegra_se_aes.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_SE_AES_H__ +#define __TEGRA_SE_AES_H__ + +#include + +/* + * SE AES CBC - AES encryption function with CBC mode + * + * src [in] source buffer of input key + * src_len [in] buffer length of input key + * dst [out] buffer of output buffer + * keyslot [in] SE keyslot. + * iv [in] initial vector + */ + +TEE_Result tegra_se_aes_encrypt_cbc(uint8_t *src, size_t src_len, + uint8_t *dst, uint32_t keyslot, uint8_t *iv); +#endif diff --git a/optee/optee_os/core/include/drivers/tegra/tegra_se_kdf.h b/optee/optee_os/core/include/drivers/tegra/tegra_se_kdf.h new file mode 100644 index 0000000..0759b94 --- /dev/null +++ b/optee/optee_os/core/include/drivers/tegra/tegra_se_kdf.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_SE_KDF_H__ +#define __TEGRA_SE_KDF_H__ + +#include +#include + +/* + * SE AES ECB KDF - Derives root key from SE keyslot. + * + * derived_key [out] pointer of the output buffer of the derived_key. + * derived_key_len [in] the length of the derived_key. + * iv [in] pointer of the initial vector. + * iv_len [in] the length of the initial vector. + * keyslot [in] SE keyslot. + */ + +TEE_Result tegra_se_aes_ecb_kdf(uint8_t *derived_key, size_t derived_key_len, + uint8_t *iv, size_t iv_len, + uint32_t keyslot); + +/* + * A hardware-based NIST-SP 800-108 KDF; + * derives keys from the SE keyslot. + * + * Use this function only during OP-TEE initialization at boot time + * (the device boot stage). To derive keys from a key buffer at runtime, + * use nist_sp_800_108_cmac_kdf(). + * + * keyslot [in] the SE keyslot where the key stores. + * key_len [in] length in bytes of the input key. + * *context [in] a pointer to a NIST-SP 800-108 context string. + * context_len [in] length of the context string. + * *label [in] a pointer to a NIST-SP 800-108 label string. + * label_len [in] length of the label string. + * dk_len [in] length of the derived key in bytes; + * may be 16 (128 bits) or any multiple of 16. + * *out_dk [out] a pointer to the derived key. The function stores + * its result in this location. + */ +TEE_Result tegra_se_nist_sp_800_108_cmac_kdf(se_aes_keyslot_t keyslot, + uint32_t key_len, + char const *context, + uint32_t context_len, + char const *label, + uint32_t label_len, + uint32_t dk_len, + uint8_t *out_dk); + +#endif diff --git a/optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h b/optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h new file mode 100644 index 0000000..5078f24 --- /dev/null +++ b/optee/optee_os/core/include/drivers/tegra/tegra_se_keyslot.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_SE_KEYSLOT_H__ +#define __TEGRA_SE_KEYSLOT_H__ + +#include + +#define TEGRA_SE_AES_BLOCK_SIZE 16 +#define TEGRA_SE_AES_IV_SIZE 16 +#define TEGRA_SE_KEY_128_SIZE 16 +#define TEGRA_SE_KEY_256_SIZE 32 + +#define TEGRA_SE_AES_QUAD_KEYS_128 0 +#define TEGRA_SE_AES_QUAD_KEYS_256 1 +#define TEGRA_SE_AES_QUAD_ORG_IV 2 +#define TEGRA_SE_AES_QUAD_UPDTD_IV 3 +#define TEGRA_SE_AES_QUAD_MAX TEGRA_SE_AES_QUAD_UPDTD_IV + +#if defined(PLATFORM_FLAVOR_t194) +typedef enum +{ + SE_AES_KEYSLOT_11 = 11, + SE_AES_KEYSLOT_12 = 12, + SE_AES_KEYSLOT_13 = 13, + SE_AES_KEYSLOT_15 = 15, + + // SSK is loaded in keyslot 15 + SE_AES_KEYSLOT_SSK = SE_AES_KEYSLOT_15, + + // KEK fuse values are loaded in keyslots 11 through 13 + SE_AES_KEYSLOT_KEK1E_128B = SE_AES_KEYSLOT_13, + SE_AES_KEYSLOT_KEK1G_128B = SE_AES_KEYSLOT_12, + SE_AES_KEYSLOT_KEK2_128B = SE_AES_KEYSLOT_11, + + SE_AES_KEYSLOT_KEK256 = SE_AES_KEYSLOT_13, + + SE_AES_KEYSLOT_COUNT = 16, +} se_aes_keyslot_t; +#endif + +#if defined(PLATFORM_FLAVOR_t234) +typedef enum +{ + SE_AES_KEYSLOT_11 = 11, + SE_AES_KEYSLOT_12 = 12, + + // Fuse keys: OEM_K1 -> slot 12, OEM_K2 -> slot 11 + SE_AES_KEYSLOT_OEM_K1 = SE_AES_KEYSLOT_12, + SE_AES_KEYSLOT_OEM_K2 = SE_AES_KEYSLOT_11, + + SE_AES_KEYSLOT_COUNT = 16, +} se_aes_keyslot_t; +#endif + +/* + * Write key into the AES keyslot. + * + * input_key [in] the pointer of the input key buffer. + * keylen [in] the length of the input key. + * key_quad_sel [in] the quad selection of the key. + * keyslot [in] the target keyslot index. + */ +TEE_Result tegra_se_write_aes_keyslot(uint8_t *input_key, uint32_t keylen, + uint32_t key_quad_sel, + se_aes_keyslot_t keyslot); + +/* Clear the AES keyslots */ +TEE_Result tegra_se_clear_aes_keyslots(void); + +#endif diff --git a/optee/optee_os/core/include/drivers/tegra/tegra_se_rng.h b/optee/optee_os/core/include/drivers/tegra/tegra_se_rng.h new file mode 100644 index 0000000..ee1af6b --- /dev/null +++ b/optee/optee_os/core/include/drivers/tegra/tegra_se_rng.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __TEGRA_SE_RNG_H__ +#define __TEGRA_SE_RNG_H__ + +#include + +/* + * Get random bytes from the SE RNG module + * + * *data_buf [out] the output of the random data buffer + * data_len [in] the length of the random bytes + */ +TEE_Result tegra_se_rng_get_random(void *data_buf, uint32_t data_len); + +#endif diff --git a/optee/optee_os/core/include/drivers/tegra_combined_uart.h b/optee/optee_os/core/include/drivers/tegra_combined_uart.h new file mode 100644 index 0000000..38d7ce9 --- /dev/null +++ b/optee/optee_os/core/include/drivers/tegra_combined_uart.h @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef TEGRA_COMBINED_UART_H +#define TEGRA_COMBINED_UART_H + +#include +#include + +#define TEGRA_COMBUART_BASE 0x0C198000 +#define TEGRA_COMBUART_SIZE 0x1000 + +struct tegra_combined_uart_data { + struct io_pa_va base; + size_t base_size; + struct serial_chip chip; +}; + +void tegra_combined_uart_init(struct tegra_combined_uart_data *tcud, + paddr_t base, size_t size); + +#endif diff --git a/optee/optee_os/core/include/drivers/tzc380.h b/optee/optee_os/core/include/drivers/tzc380.h new file mode 100644 index 0000000..fdcad27 --- /dev/null +++ b/optee/optee_os/core/include/drivers/tzc380.h @@ -0,0 +1,231 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2017 NXP + * All rights reserved. + * + * Peng Fan + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 __DRIVERS_TZC380_H +#define __DRIVERS_TZC380_H + +#include +#include +#include +#include +#include + +#define TZC400_REG_SIZE U(0x1000) + +#define BUILD_CONFIG_OFF U(0x000) +#define ACTION_OFF U(0x004) +#define LOCKDOWN_RANGE_OFF U(0x008) +#define LOCKDOWN_SELECT_OFF U(0x00C) +#define INT_STATUS U(0x010) +#define INT_CLEAR U(0x014) + +#define FAIL_ADDRESS_LOW_OFF U(0x020) +#define FAIL_ADDRESS_HIGH_OFF U(0x024) +#define FAIL_CONTROL_OFF U(0x028) +#define FAIL_ID U(0x02c) + +#define SPECULATION_CTRL_OFF U(0x030) +#define SECURITY_INV_EN_OFF U(0x034) + +#define REGION_SETUP_LOW_OFF(n) (U(0x100) + (n) * U(0x10)) +#define REGION_SETUP_HIGH_OFF(n) (U(0x104) + (n) * U(0x10)) +#define REGION_ATTRIBUTES_OFF(n) (U(0x108) + (n) * U(0x10)) + +/* ID Registers */ +#define PID0_OFF U(0xfe0) +#define PID1_OFF U(0xfe4) +#define PID2_OFF U(0xfe8) +#define PID3_OFF U(0xfec) +#define PID4_OFF U(0xfd0) +#define CID0_OFF U(0xff0) +#define CID1_OFF U(0xff4) +#define CID2_OFF U(0xff8) +#define CID3_OFF U(0xffc) + +#define BUILD_CONFIG_AW_SHIFT U(8) +#define BUILD_CONFIG_AW_MASK U(0x3f) +#define BUILD_CONFIG_NR_SHIFT U(0) +#define BUILD_CONFIG_NR_MASK U(0xf) + +#define ACTION_RV_SHIFT U(0) +#define ACTION_RV_MASK U(0x3) +#define ACTION_RV_LOWOK U(0x0) +#define ACTION_RV_LOWERR U(0x1) +#define ACTION_RV_HIGHOK U(0x2) +#define ACTION_RV_HIGHERR U(0x3) + +/* Speculation is enabled by default. */ +#define SPECULATION_CTRL_WRITE_DISABLE BIT(1) +#define SPECULATION_CTRL_READ_DISABLE BIT(0) + +#define INT_STATUS_OVERRUN_SHIFT U(1) +#define INT_STATUS_OVERRUN_MASK U(0x1) +#define INT_STATUS_STATUS_SHIFT U(0) +#define INT_STATUS_STATUS_MASK U(0x1) + +#define INT_CLEAR_CLEAR_SHIFT U(0) +#define INT_CLEAR_CLEAR_MASK U(0x1) + +#define TZC380_COMPONENT_ID U(0xb105f00d) +#define TZC380_PERIPH_ID_LOW U(0x001bb380) +#define TZC380_PERIPH_ID_HIGH U(0x00000004) + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ + +/* + * What type of action is expected when an access violation occurs. + * The memory requested is zeroed. But we can also raise and event to + * let the system know it happened. + * We can raise an interrupt(INT) and/or cause an exception(ERR). + * TZC_ACTION_NONE - No interrupt, no Exception + * TZC_ACTION_ERR - No interrupt, raise exception -> sync external + * data abort + * TZC_ACTION_INT - Raise interrupt, no exception + * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync + * external data abort + */ +enum tzc_action { + TZC_ACTION_NONE = 0, + TZC_ACTION_ERR = 1, + TZC_ACTION_INT = 2, + TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT) +}; + + +#define TZC_SP_NS_W BIT(0) +#define TZC_SP_NS_R BIT(1) +#define TZC_SP_S_W BIT(2) +#define TZC_SP_S_R BIT(3) + +#define TZC_ATTR_SP_SHIFT U(28) +#define TZC_ATTR_SP_MASK GENMASK_32(31, 28) +#define TZC_ATTR_SP_ALL SHIFT_U32(TZC_SP_S_W | TZC_SP_S_R | \ + TZC_SP_NS_W | TZC_SP_NS_R, \ + TZC_ATTR_SP_SHIFT) +#define TZC_ATTR_SP_S_RW SHIFT_U32(TZC_SP_S_W | TZC_SP_S_R, \ + TZC_ATTR_SP_SHIFT) +#define TZC_ATTR_SP_NS_RW SHIFT_U32(TZC_SP_NS_W | TZC_SP_NS_R, \ + TZC_ATTR_SP_SHIFT) + +#define TZC_REGION_SIZE_32K U(0xe) +#define TZC_REGION_SIZE_64K U(0xf) +#define TZC_REGION_SIZE_128K U(0x10) +#define TZC_REGION_SIZE_256K U(0x11) +#define TZC_REGION_SIZE_512K U(0x12) +#define TZC_REGION_SIZE_1M U(0x13) +#define TZC_REGION_SIZE_2M U(0x14) +#define TZC_REGION_SIZE_4M U(0x15) +#define TZC_REGION_SIZE_8M U(0x16) +#define TZC_REGION_SIZE_16M U(0x17) +#define TZC_REGION_SIZE_32M U(0x18) +#define TZC_REGION_SIZE_64M U(0x19) +#define TZC_REGION_SIZE_128M U(0x1a) +#define TZC_REGION_SIZE_256M U(0x1b) +#define TZC_REGION_SIZE_512M U(0x1c) +#define TZC_REGION_SIZE_1G U(0x1d) +#define TZC_REGION_SIZE_2G U(0x1e) +#define TZC_REGION_SIZE_4G U(0x1f) +#define TZC_REGION_SIZE_8G U(0x20) +#define TZC_REGION_SIZE_16G U(0x21) +#define TZC_REGION_SIZE_32G U(0x22) +#define TZC_REGION_SIZE_64G U(0x23) +#define TZC_REGION_SIZE_128G U(0x24) +#define TZC_REGION_SIZE_256G U(0x25) +#define TZC_REGION_SIZE_512G U(0x26) +#define TZC_REGION_SIZE_1T U(0x27) +#define TZC_REGION_SIZE_2T U(0x28) +#define TZC_REGION_SIZE_4T U(0x29) +#define TZC_REGION_SIZE_8T U(0x2a) +#define TZC_REGION_SIZE_16T U(0x2b) +#define TZC_REGION_SIZE_32T U(0x2c) +#define TZC_REGION_SIZE_64T U(0x2d) +#define TZC_REGION_SIZE_128T U(0x2e) +#define TZC_REGION_SIZE_256T U(0x2f) +#define TZC_REGION_SIZE_512T U(0x30) +#define TZC_REGION_SIZE_1P U(0x31) +#define TZC_REGION_SIZE_2P U(0x32) +#define TZC_REGION_SIZE_4P U(0x33) +#define TZC_REGION_SIZE_8P U(0x34) +#define TZC_REGION_SIZE_16P U(0x35) +#define TZC_REGION_SIZE_32P U(0x36) +#define TZC_REGION_SIZE_64P U(0x37) +#define TZC_REGION_SIZE_128P U(0x38) +#define TZC_REGION_SIZE_256P U(0x39) +#define TZC_REGION_SIZE_512P U(0x3a) +#define TZC_REGION_SIZE_1E U(0x3b) +#define TZC_REGION_SIZE_2E U(0x3c) +#define TZC_REGION_SIZE_4E U(0x3d) +#define TZC_REGION_SIZE_8E U(0x3e) +#define TZC_REGION_SIZE_16E U(0x3f) + +#define TZC_REGION_SIZE_SHIFT U(0x1) +#define TZC_REGION_SIZE_MASK GENMASK_32(6, 1) +#define TZC_ATTR_REGION_SIZE(s) SHIFT_U32(s, TZC_REGION_SIZE_SHIFT) + +#define TZC_SUBREGION_DIS_SHIFT U(8) +#define TZC_SUBREGION_DIS_MASK GENMASK_32(15, 8) +#define TZC_ATTR_SUBREGION_DIS(subreg) \ + (BIT((subreg) + TZC_SUBREGION_DIS_SHIFT) & \ + TZC_SUBREGION_DIS_MASK) + +#define TZC_ATTR_REGION_EN_SHIFT U(0x0) +#define TZC_ATTR_REGION_EN_MASK U(0x1) + +#define TZC_ATTR_REGION_EN +#define TZC_ATTR_REGION_ENABLE U(0x1) +#define TZC_ATTR_REGION_DISABLE U(0x0) + +#define LOCKDOWN_RANGE_ENABLE BIT(31) + +#define LOCKDOWN_SELECT_RANGE_ENABLE BIT(0) + +void tzc_init(vaddr_t base); +void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr); +void tzc_region_enable(uint8_t region); +void tzc_security_inversion_en(vaddr_t base); +void tzc_set_action(enum tzc_action action); +uint32_t tzc_get_action(void); +void tzc_fail_dump(void); +void tzc_int_clear(void); +int tzc_auto_configure(vaddr_t addr, vaddr_t rsize, uint32_t attr, + uint8_t region); +TEE_Result tzc_regions_lockdown(void); + +#if TRACE_LEVEL >= TRACE_DEBUG +void tzc_dump_state(void); +#else +static inline void tzc_dump_state(void) +{ +} +#endif + +#endif /* __DRIVERS_TZC400_H */ diff --git a/optee/optee_os/core/include/drivers/tzc400.h b/optee/optee_os/core/include/drivers/tzc400.h new file mode 100644 index 0000000..74ba57e --- /dev/null +++ b/optee/optee_os/core/include/drivers/tzc400.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) */ +/* + * Copyright (c) 2015, 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. + */ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM 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. + */ + +#ifndef __DRIVERS_TZC400_H +#define __DRIVERS_TZC400_H + +#include +#include +#include +#include +#include + +#define TZC400_REG_SIZE U(0x1000) + +#define BUILD_CONFIG_OFF U(0x000) +#define ACTION_OFF U(0x004) +#define GATE_KEEPER_OFF U(0x008) +#define SPECULATION_CTRL_OFF U(0x00c) +#define INT_STATUS U(0x010) +#define INT_CLEAR U(0x014) + +#define FAIL_ADDRESS_LOW_OFF U(0x020) +#define FAIL_ADDRESS_HIGH_OFF U(0x024) +#define FAIL_CONTROL_OFF U(0x028) +#define FAIL_ID_OFF U(0x02c) +#define FAIL_FILTER_OFF(idx) (U(0x10) * (idx)) + +#define FAIL_ADDRESS_LOW(idx) (FAIL_ADDRESS_LOW_OFF + FAIL_FILTER_OFF(idx)) +#define FAIL_ADDRESS_HIGH(idx) (FAIL_ADDRESS_HIGH_OFF + FAIL_FILTER_OFF(idx)) +#define FAIL_CONTROL(idx) (FAIL_CONTROL_OFF + FAIL_FILTER_OFF(idx)) +#define FAIL_ID(idx) (FAIL_ID_OFF + FAIL_FILTER_OFF(idx)) + +#define REGION_BASE_LOW_OFF U(0x100) +#define REGION_BASE_HIGH_OFF U(0x104) +#define REGION_TOP_LOW_OFF U(0x108) +#define REGION_TOP_HIGH_OFF U(0x10c) +#define REGION_ATTRIBUTES_OFF U(0x110) +#define REGION_ID_ACCESS_OFF U(0x114) +#define REGION_NUM_OFF(region) (U(0x20) * (region)) + +/* ID Registers */ +#define PID0_OFF U(0xfe0) +#define PID1_OFF U(0xfe4) +#define PID2_OFF U(0xfe8) +#define PID3_OFF U(0xfec) +#define PID4_OFF U(0xfd0) +#define PID5_OFF U(0xfd4) +#define PID6_OFF U(0xfd8) +#define PID7_OFF U(0xfdc) +#define CID0_OFF U(0xff0) +#define CID1_OFF U(0xff4) +#define CID2_OFF U(0xff8) +#define CID3_OFF U(0xffc) + +#define BUILD_CONFIG_NF_SHIFT U(24) +#define BUILD_CONFIG_NF_MASK U(0x3) +#define BUILD_CONFIG_AW_SHIFT U(8) +#define BUILD_CONFIG_AW_MASK U(0x3f) +#define BUILD_CONFIG_NR_SHIFT U(0) +#define BUILD_CONFIG_NR_MASK U(0x1f) + +/* Not describing the case where regions 1 to 8 overlap */ +#define ACTION_RV_SHIFT U(0) +#define ACTION_RV_MASK U(0x3) +#define ACTION_RV_LOWOK U(0x0) +#define ACTION_RV_LOWERR U(0x1) +#define ACTION_RV_HIGHOK U(0x2) +#define ACTION_RV_HIGHERR U(0x3) + +/* + * Number of gate keepers is implementation defined. But we know the max for + * this device is 4. Get implementation details from BUILD_CONFIG. + */ +#define GATE_KEEPER_OS_SHIFT U(16) +#define GATE_KEEPER_OS_MASK U(0xf) +#define GATE_KEEPER_OR_SHIFT U(0) +#define GATE_KEEPER_OR_MASK U(0xf) +#define GATE_KEEPER_FILTER_MASK U(0x1) + +/* Speculation is enabled by default. */ +#define SPECULATION_CTRL_WRITE_DISABLE BIT(1) +#define SPECULATION_CTRL_READ_DISABLE BIT(0) + +/* Max number of filters allowed is 4. */ +#define INT_STATUS_OVERLAP_SHIFT U(16) +#define INT_STATUS_OVERLAP_MASK U(0xf) +#define INT_STATUS_OVERRUN_SHIFT U(8) +#define INT_STATUS_OVERRUN_MASK U(0xf) +#define INT_STATUS_STATUS_SHIFT U(0) +#define INT_STATUS_STATUS_MASK U(0xf) + +#define INT_CLEAR_CLEAR_SHIFT U(0) +#define INT_CLEAR_CLEAR_MASK U(0xf) + +/* If set write access, else read access */ +#define FAIL_CONTROL_DIRECTION_WRITE BIT(24) +/* If set non-secure access, else secure access */ +#define FAIL_CONTROL_NONSECURE BIT(21) +/* If set privileged access, else unprivileged access */ +#define FAIL_CONTROL_PRIVILEGED BIT(20) + +/* + * FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific. + * Platform should provide the value on initialisation. + */ +#define FAIL_ID_VNET_SHIFT U(24) +#define FAIL_ID_VNET_MASK U(0xf) +#define FAIL_ID_ID_SHIFT U(0) + +/* Used along with 'enum tzc_region_attributes' below */ +#define REG_ATTR_SEC_SHIFT U(30) +#define REG_ATTR_F_EN_SHIFT U(0) +#define REG_ATTR_F_EN_MASK U(0xf) +#define REG_ATTR_FILTER_BIT(x) SHIFT_U32(BIT(x), REG_ATTR_F_EN_SHIFT) +#define REG_ATTR_FILTER_BIT_ALL SHIFT_U32(REG_ATTR_F_EN_MASK, \ + REG_ATTR_F_EN_SHIFT) + +#define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT U(16) +#define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT U(0) +#define REGION_ID_ACCESS_NSAID_ID_MASK U(0xf) + + +/* Macros for setting Region ID access permissions based on NSAID */ +#define TZC_REGION_ACCESS_RD(id) \ + SHIFT_U32(BIT(id & REGION_ID_ACCESS_NSAID_ID_MASK), \ + REGION_ID_ACCESS_NSAID_RD_EN_SHIFT) +#define TZC_REGION_ACCESS_WR(id) \ + SHIFT_U32(BIT(id & REGION_ID_ACCESS_NSAID_ID_MASK), \ + REGION_ID_ACCESS_NSAID_WR_EN_SHIFT) +#define TZC_REGION_ACCESS_RDWR(id) \ + (TZC_REGION_ACCESS_RD(id) | TZC_REGION_ACCESS_WR(id)) + +/* Filters are bit mapped 0 to 3. */ +#define TZC400_COMPONENT_ID U(0xb105f00d) + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ + +/* + * What type of action is expected when an access violation occurs. + * The memory requested is zeroed. But we can also raise and event to + * let the system know it happened. + * We can raise an interrupt(INT) and/or cause an exception(ERR). + * TZC_ACTION_NONE - No interrupt, no Exception + * TZC_ACTION_ERR - No interrupt, raise exception -> sync external + * data abort + * TZC_ACTION_INT - Raise interrupt, no exception + * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync + * external data abort + */ +enum tzc_action { + TZC_ACTION_NONE = 0, + TZC_ACTION_ERR = 1, + TZC_ACTION_INT = 2, + TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT) +}; + +/* + * Controls secure access to a region. If not enabled secure access is not + * allowed to region. + */ +enum tzc_region_attributes { + TZC_REGION_S_NONE = 0, + TZC_REGION_S_RD = 1, + TZC_REGION_S_WR = 2, + TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR) +}; + +struct tzc_region_config { + uint32_t filters; + vaddr_t base; + vaddr_t top; + enum tzc_region_attributes sec_attr; + uint32_t ns_device_access; +}; + +void tzc_init(vaddr_t base); +void tzc_configure_region(uint8_t region, const struct tzc_region_config *cfg); +TEE_Result tzc_get_region_config(uint8_t region, struct tzc_region_config *cfg); +void tzc_enable_filters(void); +void tzc_disable_filters(void); +void tzc_set_action(enum tzc_action action); + +void tzc_fail_dump(void); +void tzc_int_clear(void); + +#if TRACE_LEVEL >= TRACE_DEBUG +void tzc_dump_state(void); +#else +static inline void tzc_dump_state(void) +{ +} +#endif + +#endif /* __DRIVERS_TZC400_H */ diff --git a/optee/optee_os/core/include/drivers/versal_gpio.h b/optee/optee_os/core/include/drivers/versal_gpio.h new file mode 100644 index 0000000..1b5ef83 --- /dev/null +++ b/optee/optee_os/core/include/drivers/versal_gpio.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022 Foundries.io Ltd + */ + +#ifndef __DRIVERS_VERSAL_GPIO_H +#define __DRIVERS_VERSAL_GPIO_H + +#include +#include +#include +#include + +#define VERSAL_GPIO_MAX_BANK 5 + +struct versal_gpio_platform_data { + const char *label; + uint16_t ngpio; + uint32_t max_bank; + uint32_t bank_min[VERSAL_GPIO_MAX_BANK]; + uint32_t bank_max[VERSAL_GPIO_MAX_BANK]; +}; + +struct versal_gpio_platdata { + paddr_t base; + const struct versal_gpio_platform_data *p_data; +}; + +struct versal_gpio_chip { + struct gpio_chip chip; + struct versal_gpio_platdata plat; + vaddr_t base; +}; + +TEE_Result versal_gpio_pmc_init(struct versal_gpio_chip *chip); +TEE_Result versal_gpio_ps_init(struct versal_gpio_chip *chip); + +#endif /* __DRIVERS_VERSAL_GPIO_H */ diff --git a/optee/optee_os/core/include/drivers/versal_mbox.h b/optee/optee_os/core/include/drivers/versal_mbox.h new file mode 100644 index 0000000..04e0c09 --- /dev/null +++ b/optee/optee_os/core/include/drivers/versal_mbox.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Foundries.io Ltd + */ +#ifndef __DRIVERS_VERSAL_MBOX_H +#define __DRIVERS_VERSAL_MBOX_H + +#include +#include +#include + +#define VERSAL_MAX_IPI_BUF 7 + +struct versal_mbox_mem { + size_t alloc_len; + size_t len; + void *buf; +}; + +struct versal_ipi_buf { + struct versal_mbox_mem mem; + bool only_cache; +}; + +struct versal_ipi_cmd { + uint32_t data[8]; + struct versal_ipi_buf ibuf[VERSAL_MAX_IPI_BUF]; +}; + +TEE_Result versal_mbox_notify(struct versal_ipi_cmd *cmd, + struct versal_ipi_cmd *rsp, uint32_t *err); +TEE_Result versal_mbox_alloc(size_t len, const void *init, + struct versal_mbox_mem *mem); +#endif /* __DRIVERS_VERSAL_MBOX_H */ diff --git a/optee/optee_os/core/include/drivers/versal_nvm.h b/optee/optee_os/core/include/drivers/versal_nvm.h new file mode 100644 index 0000000..948ebb2 --- /dev/null +++ b/optee/optee_os/core/include/drivers/versal_nvm.h @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022 Foundries.io Ltd + */ + +#ifndef __DRIVERS_VERSAL_NVM_H__ +#define __DRIVERS_VERSAL_NVM_H__ + +#include +#include +#include +#include +#include + +#define PUF_EFUSES_WORDS (128) +#define PUF_SYN_DATA_WORDS (127) +#define EFUSE_MAX_USER_FUSES (64) + +#define EFUSE_OFFCHIP_REVOCATION_ID_LEN (4) +#define EFUSE_REVOCATION_ID_LEN (4) +#define EFUSE_DEC_ONLY_LEN (4) +#define EFUSE_DNA_LEN (16) +#define EFUSE_PPK_LEN (32) +#define EFUSE_IV_LEN (12) + +enum versal_nvm_iv_type { + EFUSE_META_HEADER_IV_RANGE = 0, + EFUSE_BLACK_IV, + EFUSE_PLM_IV_RANGE, + EFUSE_DATA_PARTITION_IV_RANGE, +}; + +enum versal_nvm_ppk_type { + EFUSE_PPK0 = 0, + EFUSE_PPK1, + EFUSE_PPK2 +}; + +enum versal_nvm_revocation_id { + EFUSE_REVOCATION_ID_0 = 0, + EFUSE_REVOCATION_ID_1, + EFUSE_REVOCATION_ID_2, + EFUSE_REVOCATION_ID_3, + EFUSE_REVOCATION_ID_4, + EFUSE_REVOCATION_ID_5, + EFUSE_REVOCATION_ID_6, + EFUSE_REVOCATION_ID_7 +}; + +enum versal_nvm_offchip_id { + EFUSE_INVLD = -1, + EFUSE_OFFCHIP_REVOKE_ID_0 = 0, + EFUSE_OFFCHIP_REVOKE_ID_1, + EFUSE_OFFCHIP_REVOKE_ID_2, + EFUSE_OFFCHIP_REVOKE_ID_3, + EFUSE_OFFCHIP_REVOKE_ID_4, + EFUSE_OFFCHIP_REVOKE_ID_5, + EFUSE_OFFCHIP_REVOKE_ID_6, + EFUSE_OFFCHIP_REVOKE_ID_7 +}; + +/* + * All structures mapped to the PLM processor must be address_and_size aligned + * to the cacheline_len. + */ + +struct versal_efuse_glitch_cfg_bits { + uint8_t prgm_glitch; + uint8_t glitch_det_wr_lk; + uint32_t glitch_det_trim; + uint8_t gd_rom_monitor_en; + uint8_t gd_halt_boot_en; + uint8_t pad[53]; +}; + +struct versal_efuse_aes_keys { + uint8_t prgm_aes_key; + uint8_t prgm_user_key0; + uint8_t prgm_user_key1; + uint32_t aes_key[8]; + uint32_t user_key0[8]; + uint32_t user_key1[8]; + uint8_t pad[25]; +}; + +struct versal_efuse_ppk_hash { + uint8_t prgm_ppk0_hash; + uint8_t prgm_ppk1_hash; + uint8_t prgm_ppk2_hash; + uint32_t ppk0_hash[8]; + uint32_t ppk1_hash[8]; + uint32_t ppk2_hash[8]; + uint8_t pad[89]; +}; + +struct versal_efuse_dec_only { + uint8_t prgm_dec_only; + uint8_t pad[63]; +}; + +struct versal_efuse_revoke_ids { + uint8_t prgm_revoke_id; + uint32_t revoke_id[8]; + uint8_t pad[89]; +}; + +struct versal_efuse_offchip_ids { + uint8_t prgm_offchip_id; + uint32_t offchip_id[8]; + uint8_t pad[89]; +}; + +struct versal_efuse_user_data { + uint32_t start; + uint32_t num; + uint64_t addr; + uint8_t pad[48]; +}; + +struct versal_efuse_puf_fuse { + uint8_t env_monitor_dis; + uint8_t prgm_puf_fuse; + uint32_t start; + uint32_t num; + uint64_t addr; + uint8_t pad[104]; +}; + +struct versal_efuse_ivs { + uint8_t prgm_meta_header_iv; + uint8_t prgm_blk_obfus_iv; + uint8_t prgm_plm_iv; + uint8_t prgm_data_partition_iv; + uint32_t meta_header_iv[3]; + uint32_t blk_obfus_iv[3]; + uint32_t plm_iv[3]; + uint32_t data_partition_iv[3]; + uint8_t pad[12]; +}; + +struct versal_efuse_misc_ctrl_bits { + uint8_t glitch_det_halt_boot_en; + uint8_t glitch_det_rom_monitor_en; + uint8_t halt_boot_error; + uint8_t halt_boot_env; + uint8_t crypto_kat_en; + uint8_t lbist_en; + uint8_t safety_mission_en; + uint8_t ppk0_invalid; + uint8_t ppk1_invalid; + uint8_t ppk2_invalid; + uint8_t pad[54]; +}; + +struct versal_efuse_puf_sec_ctrl_bits { + uint8_t puf_regen_dis; + uint8_t puf_hd_invalid; + uint8_t puf_test2_dis; + uint8_t puf_dis; + uint8_t puf_syn_lk; + uint8_t pad[59]; +}; + +struct versal_efuse_sec_misc1_bits { + uint8_t lpd_mbist_en; + uint8_t pmc_mbist_en; + uint8_t lpd_noc_sc_en; + uint8_t sysmon_volt_mon_en; + uint8_t sysmon_temp_mon_en; + uint8_t pad[59]; +}; + +struct versal_efuse_boot_env_ctrl_bits { + uint8_t prgm_sysmon_temp_hot; + uint8_t prgm_sysmon_volt_pmc; + uint8_t prgm_sysmon_volt_pslp; + uint8_t prgm_sysmon_temp_cold; + uint8_t sysmon_temp_en; + uint8_t sysmon_volt_en; + uint8_t sysmon_volt_soc; + uint8_t sysmon_temp_hot; + uint8_t sysmon_volt_pmc; + uint8_t sysmon_volt_pslp; + uint8_t sysmon_temp_cold; + uint8_t pad[53]; +}; + +struct versal_efuse_sec_ctrl_bits { + uint8_t aes_dis; + uint8_t jtag_err_out_dis; + uint8_t jtag_dis; + uint8_t ppk0_wr_lk; + uint8_t ppk1_wr_lk; + uint8_t ppk2_wr_lk; + uint8_t aes_crc_lk; + uint8_t aes_wr_lk; + uint8_t user_key0_crc_lk; + uint8_t user_key0_wr_lk; + uint8_t user_key1_crc_lk; + uint8_t user_key1_wr_lk; + uint8_t sec_dbg_dis; + uint8_t sec_lock_dbg_dis; + uint8_t boot_env_wr_lk; + uint8_t reg_init_dis; + uint8_t pad[48]; +}; + +struct versal_efuse_puf_header { + struct versal_efuse_puf_sec_ctrl_bits sec_ctrl; + uint8_t prmg_puf_helper_data; + uint8_t env_monitor_dis; + uint32_t efuse_syn_data[PUF_SYN_DATA_WORDS]; + uint32_t chash; + uint32_t aux; + uint8_t pad[56]; +}; + +struct versal_efuse_puf_user_fuse { + uint32_t data_addr[PUF_EFUSES_WORDS]; + uint8_t env_monitor_dis; + uint8_t prgm_puf_fuse; + uint32_t start_row; + uint32_t num_rows; +}; + +TEE_Result versal_efuse_read_dna(uint32_t *buf, size_t len); +TEE_Result versal_efuse_read_user_data(uint32_t *buf, size_t len, + uint32_t first, size_t num); +TEE_Result versal_efuse_read_iv(uint32_t *buf, size_t len, + enum versal_nvm_iv_type type); +TEE_Result versal_efuse_read_ppk(uint32_t *buf, size_t len, + enum versal_nvm_ppk_type type); +TEE_Result versal_efuse_write_user_data(uint32_t *buf, size_t len, + uint32_t first, size_t num); +TEE_Result versal_efuse_write_aes_keys(struct versal_efuse_aes_keys *keys); +TEE_Result versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash *hash); +TEE_Result versal_efuse_write_iv(struct versal_efuse_ivs *p); +TEE_Result versal_efuse_write_dec_only(struct versal_efuse_dec_only *p); +TEE_Result versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits *p); +TEE_Result versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits *p); +TEE_Result versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits + *p); +TEE_Result versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits + *p); +TEE_Result versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits *p); +TEE_Result versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids *p); +TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type); +TEE_Result versal_efuse_write_revoke_id(uint32_t id); +TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len, + enum versal_nvm_revocation_id id); +TEE_Result versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits *buf); +TEE_Result versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits *buf); +TEE_Result versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits *buf); +TEE_Result +versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits *buf); +TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len, + enum versal_nvm_offchip_id id); +TEE_Result versal_efuse_read_dec_only(uint32_t *buf, size_t len); +TEE_Result versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits + *buf); +TEE_Result versal_efuse_read_puf(struct versal_efuse_puf_header *buf); +TEE_Result versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse + *p); +TEE_Result versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse + *p); +TEE_Result versal_efuse_write_puf(struct versal_efuse_puf_header *buf); +TEE_Result versal_bbram_write_aes_key(uint8_t *key, size_t len); +TEE_Result versal_bbram_zeroize(void); +TEE_Result versal_bbram_write_user_data(uint32_t data); +TEE_Result versal_bbram_read_user_data(uint32_t *data); +TEE_Result versal_bbram_lock_write_user_data(void); + +#endif /*__DRIVERS_VERSAL_NVM_H__*/ diff --git a/optee/optee_os/core/include/drivers/versal_pm.h b/optee/optee_os/core/include/drivers/versal_pm.h new file mode 100644 index 0000000..0a1bd5e --- /dev/null +++ b/optee/optee_os/core/include/drivers/versal_pm.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022 Foundries.io Ltd + */ + +#ifndef __DRIVERS_VERSAL_PM_H__ +#define __DRIVERS_VERSAL_PM_H__ + +#include +#include + +TEE_Result versal_soc_version(uint8_t *version); +TEE_Result versal_write_fpga(paddr_t pa); + +#endif /*__DRIVERS_VERSAL_PM_H__*/ diff --git a/optee/optee_os/core/include/drivers/versal_puf.h b/optee/optee_os/core/include/drivers/versal_puf.h new file mode 100644 index 0000000..06811b3 --- /dev/null +++ b/optee/optee_os/core/include/drivers/versal_puf.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022 Foundries.io Ltd + * Jorge Ramirez-Ortiz + */ + +#ifndef __DRIVERS_VERSAL_PUF_H +#define __DRIVERS_VERSAL_PUF_H + +#include +#include +#include +#include + +#define VERSAL_PUF_REGISTRATION 0x0 +#define VERSAL_PUF_REGEN_ON_DEMAND 0x1 +#define VERSAL_PUF_REGEN_ID_ONLY 0x2 +#define VERSAL_PUF_SHUTTER_VALUE 0x81000100 +#define VERSAL_PUF_SYNDROME_MODE_4K 0x0 +#define VERSAL_PUF_GLBL_VAR_FLTR_OPTION 1 +#define VERSAL_PUF_READ_FROM_RAM 0 +#define VERSAL_PUF_READ_FROM_EFUSE_CACHE 1 +#define VERSAL_PUF_4K_PUF_SYN_LEN_IN_WORDS 140 + +#define VERSAL_PUF_EFUSE_SYN_WORDS 127 +#define VERSAL_PUF_SYNDROME_WORDS 350 +#define VERSAL_PUF_ID_WORDS 8 +#define VERSAL_PUF_HASH_LEN 4 +#define VERSAL_PUF_AUX_LEN 4 + +struct versal_puf_data { + uint32_t syndrome_data[VERSAL_PUF_SYNDROME_WORDS]; + uint32_t chash; + uint32_t aux; + uint32_t puf_id[VERSAL_PUF_ID_WORDS]; + uint32_t efuse_syn_data[VERSAL_PUF_EFUSE_SYN_WORDS]; +}; + +struct versal_puf_cfg { + uint8_t reg_mode; + uint8_t puf_operation; + uint8_t global_var_filter; + uint8_t read_option; + uint32_t shutter_value; +}; + +struct versal_puf_data_req { + uint8_t reg_mode; + uint8_t puf_operation; + uint8_t global_var_filter; + uint8_t read_option; + uint32_t shutter_value; + uint64_t syndrome_data_addr; + uint64_t hash_addr; + uint64_t aux_addr; + uint64_t puf_id_addr; + uint64_t syndrome_addr; + uint64_t efuse_syn_data_addr; + uint8_t pad[8]; +}; + +enum versal_puf_api { + VERSAL_PUF_API_FEATURES = 0U, + VERSAL_PUF_REGISTER, + VERSAL_PUF_REGENERATE, + VERSAL_PUF_CLEAR_ID, +}; + +#define __aligned_puf __aligned(CACHELINE_LEN) + +TEE_Result versal_puf_regenerate(struct versal_puf_data *buf, + struct versal_puf_cfg *cfg); +TEE_Result versal_puf_register(struct versal_puf_data *buf, + struct versal_puf_cfg *cfg); +TEE_Result versal_puf_check_api(enum versal_puf_api id); +TEE_Result versal_puf_clear_id(void); + +#endif /* __DRIVERS_VERSAL_PUF_H */ diff --git a/optee/optee_os/core/include/drivers/versal_sha3_384.h b/optee/optee_os/core/include/drivers/versal_sha3_384.h new file mode 100644 index 0000000..8ce99e5 --- /dev/null +++ b/optee/optee_os/core/include/drivers/versal_sha3_384.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022 Foundries.io Ltd + */ + +#ifndef __DRIVERS_VERSAL_SHA3_384_H__ +#define __DRIVERS_VERSAL_SHA3_384_H__ + +#include +#include +#include +#include + +TEE_Result versal_sha3_384(const uint8_t *src, size_t src_len, + uint8_t *dst, size_t dst_len); + +#endif /*__DRIVERS_VERSAL_SHA3_384_H__*/ diff --git a/optee/optee_os/core/include/drivers/wdt.h b/optee/optee_os/core/include/drivers/wdt.h new file mode 100644 index 0000000..b07152e --- /dev/null +++ b/optee/optee_os/core/include/drivers/wdt.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2019 Broadcom. + */ + +#ifndef DRIVERS_WDT_H +#define DRIVERS_WDT_H + +#include +#include +#include +#include +#include + +struct wdt_chip { + const struct wdt_ops *ops; + struct itr_handler *wdt_itr; +}; + +/* + * struct wdt_ops - The watchdog device operations + * + * @init: The routine to initialized the watchdog resources. + * @start: The routine for starting the watchdog device. + * @stop: The routine for stopping the watchdog device. + * @ping: The routine that sends a keepalive ping to the watchdog device. + * @set_timeout:The routine that finds the load value that will reset system in + * required timeout (in seconds). + * + * The wdt_ops structure contains a list of low-level operations + * that control a watchdog device. + */ +struct wdt_ops { + TEE_Result (*init)(struct wdt_chip *chip, unsigned long *min_timeout, + unsigned long *max_timeout); + void (*start)(struct wdt_chip *chip); + void (*stop)(struct wdt_chip *chip); + void (*ping)(struct wdt_chip *chip); + TEE_Result (*set_timeout)(struct wdt_chip *chip, unsigned long timeout); +}; + +#ifdef CFG_WDT +extern struct wdt_chip *wdt_chip; + +/* Register a watchdog as the system watchdog */ +TEE_Result watchdog_register(struct wdt_chip *chip); + +static inline +TEE_Result watchdog_init(unsigned long *min_timeout, unsigned long *max_timeout) +{ + if (!wdt_chip) + return TEE_ERROR_NOT_SUPPORTED; + + if (!wdt_chip->ops->init) + return TEE_SUCCESS; + + return wdt_chip->ops->init(wdt_chip, min_timeout, max_timeout); +} + +static inline void watchdog_start(void) +{ + if (wdt_chip) + wdt_chip->ops->start(wdt_chip); +} + +static inline void watchdog_stop(void) +{ + if (wdt_chip && wdt_chip->ops->stop) + wdt_chip->ops->stop(wdt_chip); +} + +static inline void watchdog_ping(void) +{ + if (wdt_chip) + wdt_chip->ops->ping(wdt_chip); +} + +static inline void watchdog_settimeout(unsigned long timeout) +{ + if (wdt_chip) + wdt_chip->ops->set_timeout(wdt_chip, timeout); +} +#else +static inline TEE_Result watchdog_register(struct wdt_chip *chip __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result watchdog_init(unsigned long *min_timeout __unused, + unsigned long *max_timeout __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline void watchdog_start(void) {} +static inline void watchdog_stop(void) {} +static inline void watchdog_ping(void) {} +static inline void watchdog_settimeout(unsigned long timeout __unused) {} +#endif + +#ifdef CFG_WDT_SM_HANDLER +enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args); + +static inline +enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args) +{ + if (args->a0 != CFG_WDT_SM_HANDLER_ID) + return SM_HANDLER_PENDING_SMC; + + return __wdt_sm_handler(args); +} +#else +static inline +enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args __unused) +{ + return SM_HANDLER_PENDING_SMC; +} +#endif + +#endif /* DRIVERS_WDT_H */ diff --git a/optee/optee_os/core/include/drivers/zynqmp_csu.h b/optee/optee_os/core/include/drivers/zynqmp_csu.h new file mode 100644 index 0000000..985689b --- /dev/null +++ b/optee/optee_os/core/include/drivers/zynqmp_csu.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2021 + * Author: Jorge Ramirez + */ + +#ifndef __DRIVERS_ZYNQMP_CSU_H_ +#define __DRIVERS_ZYNQMP_CSU_H_ + +/* CSU registers */ +#define ZYNQMP_CSU_STATUS_OFFSET 0x00 +#define ZYNQMP_CSU_CTRL_OFFSET 0x04 +#define ZYNQMP_CSU_SSS_CFG_OFFSET 0x08 +#define ZYNQMP_CSU_DMA_RESET_OFFSET 0x0c +#define ZYNQMP_CSU_MULTI_BOOT_OFFSET 0x10 +#define ZYNQMP_CSU_TAMPER_TRIG_OFFSET 0x14 +#define ZYNQMP_CSU_FT_STATUS_OFFSET 0x18 +#define ZYNQMP_CSU_ISR_OFFSET 0x20 + +#define ZYNQMP_CSU_STATUS_AUTH BIT(0) +#define ZYNQMP_CSU_SSS_DMA0_STREAM_TO_AES 0x5A0 +#define ZYNQMP_CSU_DMA_RESET_SET 1 +#define ZYNQMP_CSU_DMA_RESET_CLR 0 +#define ZYNQMP_CSU_ISR_PUF_ACC_ERROR_MASK BIT(12) + +/* AES-GCM */ +#define ZYNQMP_CSU_AES_BASE (CSU_BASE + 0x1000) +#define ZYNQMP_CSU_AES_SIZE 0x1000 + +/* SHA */ +#define ZYNQMP_CSU_SHA_BASE (CSU_BASE + 0x2000) +#define ZYNQMP_CSU_SHA_SIZE 0x1000 + +/* PCAP */ +#define ZYNQMP_CSU_PCAP_BASE (CSU_BASE + 0x3000) +#define ZYNQMP_CSU_PCAP_SIZE 0x1000 + +/* PUF */ +#define ZYNQMP_CSU_PUF_BASE (CSU_BASE + 0x4000) +#define ZYNQMP_CSU_PUF_SIZE 0x1000 + +/* TAMPER */ +#define ZYNQMP_CSU_TAMPER_BASE (CSU_BASE + 0x5000) +#define ZYNQMP_CSU_TAMPER_SIZE 0x38 + +#endif diff --git a/optee/optee_os/core/include/drivers/zynqmp_csu_aes.h b/optee/optee_os/core/include/drivers/zynqmp_csu_aes.h new file mode 100644 index 0000000..3a1a2e5 --- /dev/null +++ b/optee/optee_os/core/include/drivers/zynqmp_csu_aes.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2021 + * Author: Jorge Ramirez + */ + +#ifndef __DRIVERS_ZYNQMP_CSU_AES_H_ +#define __DRIVERS_ZYNQMP_CSU_AES_H_ + +#include +#include +#include + +#define __aligned_csuaes __aligned_csudma + +#define ZYNQMP_GCM_TAG_SIZE 16 +#define ZYNQMP_GCM_IV_SIZE 12 + +enum zynqmp_csu_key { + ZYNQMP_CSU_AES_KEY_SRC_KUP = 0, + ZYNQMP_CSU_AES_KEY_SRC_DEV +}; + +#define ZYNQMP_CSU_AES_DST_LEN(x) ((x) + ZYNQMP_GCM_TAG_SIZE) + +TEE_Result zynqmp_csu_aes_encrypt_data(const void *src, size_t src_len, + void *dst, size_t dst_len, + void *tag, size_t tag_len, + const void *iv, size_t iv_len, + enum zynqmp_csu_key key); + +TEE_Result zynqmp_csu_aes_decrypt_data(const void *src, size_t src_len, + void *dst, size_t len, + const void *tag, size_t tag_len, + const void *iv, size_t iv_len, + enum zynqmp_csu_key key); + +TEE_Result zynqmp_csu_aes_dt_enable_secure_status(void); + +#endif diff --git a/optee/optee_os/core/include/drivers/zynqmp_csu_puf.h b/optee/optee_os/core/include/drivers/zynqmp_csu_puf.h new file mode 100644 index 0000000..0bdc0d3 --- /dev/null +++ b/optee/optee_os/core/include/drivers/zynqmp_csu_puf.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2021 + * Author: Jorge Ramirez + */ + +#ifndef __DRIVERS_ZYNQMP_CSU_PUF_H_ +#define __DRIVERS_ZYNQMP_CSU_PUF_H_ + +#include + +TEE_Result zynqmp_csu_puf_regenerate(void); +void zynqmp_csu_puf_reset(void); + +#endif diff --git a/optee/optee_os/core/include/drivers/zynqmp_csudma.h b/optee/optee_os/core/include/drivers/zynqmp_csudma.h new file mode 100644 index 0000000..afbf51c --- /dev/null +++ b/optee/optee_os/core/include/drivers/zynqmp_csudma.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) Foundries Ltd. 2021 + * Author: Jorge Ramirez + */ + +#ifndef __DRIVERS_ZYNQMP_CSUDMA_H_ +#define __DRIVERS_ZYNQMP_CSUDMA_H_ + +#include +#include +#include + +#define ZYNQMP_CSUDMA_ALIGN 64 +#define __aligned_csudma __aligned(ZYNQMP_CSUDMA_ALIGN) + +#define ZYNQMP_CSUDMA_MIN_SIZE 16 +#define ZYNQMP_CSUDMA_DONE BIT(0) + +enum zynqmp_csudma_channel { + ZYNQMP_CSUDMA_SRC_CHANNEL = 0, + ZYNQMP_CSUDMA_DST_CHANNEL +}; + +TEE_Result zynqmp_csudma_transfer(enum zynqmp_csudma_channel channel, + void *address, size_t len, uint8_t notify); +TEE_Result zynqmp_csudma_sync(enum zynqmp_csudma_channel channel); +TEE_Result zynqmp_csudma_prepare(void); +void zynqmp_csudma_unprepare(void); + +#endif diff --git a/optee/optee_os/core/include/drivers/zynqmp_efuse.h b/optee/optee_os/core/include/drivers/zynqmp_efuse.h new file mode 100644 index 0000000..4647e8b --- /dev/null +++ b/optee/optee_os/core/include/drivers/zynqmp_efuse.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2021 Foundries.io Ltd + */ + +#ifndef __DRIVERS_ZYNQMP_EFUSE_H__ +#define __DRIVERS_ZYNQMP_EFUSE_H__ + +#include + +#define ZYNQMP_EFUSE_DNA_OFFSET 0xc +#define ZYNQMP_EFUSE_DNA_LENGTH 12 + +#define ZYNQMP_EFUSE_IP_DISABLE_OFFSET 0x18 +#define ZYNQMP_EFUSE_IP_DISABLE_LENGTH 4 + +#define ZYNQMP_EFUSE_USER0_OFFSET 0x20 +#define ZYNQMP_EFUSE_USER0_LENGTH 4 + +#define ZYNQMP_EFUSE_USER1_OFFSET 0x24 +#define ZYNQMP_EFUSE_USER1_LENGTH 4 + +#define ZYNQMP_EFUSE_USER2_OFFSET 0x28 +#define ZYNQMP_EFUSE_USER2_LENGTH 4 + +#define ZYNQMP_EFUSE_USER3_OFFSET 0x2c +#define ZYNQMP_EFUSE_USER3_LENGTH 4 + +#define ZYNQMP_EFUSE_USER4_OFFSET 0x30 +#define ZYNQMP_EFUSE_USER4_LENGTH 4 + +#define ZYNQMP_EFUSE_USER5_OFFSET 0x34 +#define ZYNQMP_EFUSE_USER5_LENGTH 4 + +#define ZYNQMP_EFUSE_USER6_OFFSET 0x38 +#define ZYNQMP_EFUSE_USER6_LENGTH 4 + +#define ZYNQMP_EFUSE_USER7_OFFSET 0x3c +#define ZYNQMP_EFUSE_USER7_LENGTH 4 + +#define ZYNQMP_EFUSE_MISC_USER_CTRL_OFFSET 0x40 +#define ZYNQMP_EFUSE_MISC_USER_CTRL_LENGTH 4 + +#define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_0 BIT(0) +#define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_1 BIT(1) +#define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_2 BIT(2) +#define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_3 BIT(3) +#define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_4 BIT(4) +#define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_5 BIT(5) +#define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_6 BIT(6) +#define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_7 BIT(7) + +#define ZYNQMP_EFUSE_SEC_CTRL_OFFSET 0x58 +#define ZYNQMP_EFUSE_SEC_CTRL_LENGTH 4 + +#endif /*__DRIVERS_ZYNQMP_EFUSE_H__*/ diff --git a/optee/optee_os/core/include/drivers/zynqmp_huk.h b/optee/optee_os/core/include/drivers/zynqmp_huk.h new file mode 100644 index 0000000..44396cd --- /dev/null +++ b/optee/optee_os/core/include/drivers/zynqmp_huk.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022, Vaisala Oyj + */ + +#ifndef __DRIVERS_ZYNQMP_HUK_H__ +#define __DRIVERS_ZYNQMP_HUK_H__ + +/* + * Query Device DNA from the device + * + * Note: configured as weak so that it can be replaced with implementation to + * get read only PL Device DNA from FPGA array. This would need custom IP core + * for access. + * + * Both PS and PL Device DNA's have 96 bits. + * + * Xilinx recommends to use PL Device DNA for device identification. + * + * ref: + * + * 71342 - Zynq UltraScale+ Device - PS DNA is not write protected and is a + * different value than the PL DNA + * + * https://support.xilinx.com/s/article/71342 + * + * @device_dna: Memory buffer to receive value of Device DNA + * @size: length of device_dna buffer (requires buffer of 12 bytes) + * Return a TEE_Result compliant status + */ +TEE_Result tee_zynqmp_get_device_dna(uint8_t *device_dna, size_t size); + +#endif /* __DRIVERS_ZYNQMP_HUK_H__ */ diff --git a/optee/optee_os/core/include/drivers/zynqmp_pm.h b/optee/optee_os/core/include/drivers/zynqmp_pm.h new file mode 100644 index 0000000..62de2b1 --- /dev/null +++ b/optee/optee_os/core/include/drivers/zynqmp_pm.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2021 Foundries.io Ltd + */ + +#ifndef __DRIVERS_ZYNQMP_PM_H__ +#define __DRIVERS_ZYNQMP_PM_H__ + +#include +#include +#include +#include + +/* + * Information about accessing eFuses and the Physically Uncloneable Function + * (PUF) Support can be found at + * https://www.xilinx.com/support/documentation/application_notes/xapp1319-zynq-usp-prog-nvm.pdf + */ +#define ZYNQMP_NONPUF_EFUSE 0 +#define ZYNQMP_PUF_EFUSE 1 + +/* List of eFuse identifiers */ +enum zynqmp_efuse_id { + DNA = 0, IP_DISABLE, USER0, USER1, USER2, USER3, USER4, USER5, USER6, + USER7, MISC_USER_CTRL, SEC_CTRL, +}; + +/* Valid bytes in the eFuse */ +#define ZYNQMP_EFUSE_LEN(_id) ZYNQMP_EFUSE_##_id##_LENGTH + +/* Memory required to access the eFuse */ +#define ZYNQMP_EFUSE_MEM(_id) (ROUNDUP(ZYNQMP_EFUSE_LEN(_id), CACHELINE_LEN)) + +/* Alignment required in the buffers used to read the eFuse */ +#define __aligned_efuse __aligned(CACHELINE_LEN) + +/* + * Read eFuse memory + * @buf: buffer, where eFuse date will be stored. The data is returned + * in LE byte order. + * @buf_sz: buffer size in bytes + * @id: eFuse identifier. + * @puf: is eFuse PUF, ZYNQMP_PUF_EFUSE/ZYNQMP_NONPUF_EFUSE + * Return a TEE_Result compliant status + */ +TEE_Result zynqmp_efuse_read(uint8_t *buf, size_t buf_sz, + enum zynqmp_efuse_id id, bool puf); + +/* + * Program eFuse memory + * @buf: buffer where eFuse data are stored in LE byte order. + * @buf_sz: buffer size in bytes + * @id: eFuse identifier. + * @puf: is eFuse PUF, ZYNQMP_PUF_EFUSE/ZYNQMP_NONPUF_EFUSE + * Return a TEE_Result compliant status + */ +TEE_Result zynqmp_efuse_write(uint8_t *buf, size_t buf_sz, + enum zynqmp_efuse_id id, bool puf); + +/* + * Read the SoC version number: + * Different eFuse bitfields carry different meaning depending on this version. + */ +TEE_Result zynqmp_soc_version(uint32_t *version); + +#endif /*__DRIVERS_ZYNQMP_PM_H__*/ diff --git a/optee/optee_os/core/include/dt-bindings/clock/at91.h b/optee/optee_os/core/include/dt-bindings/clock/at91.h new file mode 100644 index 0000000..83f6e5c --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/clock/at91.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later or BSD-3-Clause */ +/* + * Copyright (C) 2021 Microchip + * + * This header provides constants for AT91 pmc status. + * + * The constants defined in this header are being used in dts. + */ + +#ifndef _DT_BINDINGS_CLK_AT91_H +#define _DT_BINDINGS_CLK_AT91_H + +#define PMC_TYPE_CORE 0 +#define PMC_TYPE_SYSTEM 1 +#define PMC_TYPE_PERIPHERAL 2 +#define PMC_TYPE_GCK 3 +#define PMC_TYPE_PROGRAMMABLE 4 + +#define PMC_SLOW 0 +#define PMC_MCK 1 +#define PMC_UTMI 2 +#define PMC_MAIN 3 +#define PMC_MCK2 4 +#define PMC_I2S0_MUX 5 +#define PMC_I2S1_MUX 6 +#define PMC_PLLACK 7 +#define PMC_PLLBCK 8 +#define PMC_AUDIOPLLCK 9 +#define PMC_MCK_PRES 10 +#define PMC_AUDIOPLL_FRACCK 11 +#define PMC_USBCK 12 +#define PMC_SAMA5D2_CORE_CLK_COUNT 13 + +/* SAMA7G5 */ +#define PMC_CPUPLL (PMC_MAIN + 1) +#define PMC_SYSPLL (PMC_MAIN + 2) +#define PMC_DDRPLL (PMC_MAIN + 3) +#define PMC_IMGPLL (PMC_MAIN + 4) +#define PMC_BAUDPLL (PMC_MAIN + 5) +#define PMC_AUDIOPMCPLL (PMC_MAIN + 6) +#define PMC_AUDIOIOPLL (PMC_MAIN + 7) +#define PMC_ETHPLL (PMC_MAIN + 8) +#define PMC_CPU (PMC_MAIN + 9) + +#endif diff --git a/optee/optee_os/core/include/dt-bindings/clock/stm32mp1-clks.h b/optee/optee_os/core/include/dt-bindings/clock/stm32mp1-clks.h new file mode 100644 index 0000000..615152e --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/clock/stm32mp1-clks.h @@ -0,0 +1,277 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_ +#define _DT_BINDINGS_STM32MP1_CLKS_H_ + +/* OSCILLATOR clocks */ +#define CK_HSE 0 +#define CK_CSI 1 +#define CK_LSI 2 +#define CK_LSE 3 +#define CK_HSI 4 +#define CK_HSE_DIV2 5 + +/* Bus clocks */ +#define TIM2 6 +#define TIM3 7 +#define TIM4 8 +#define TIM5 9 +#define TIM6 10 +#define TIM7 11 +#define TIM12 12 +#define TIM13 13 +#define TIM14 14 +#define LPTIM1 15 +#define SPI2 16 +#define SPI3 17 +#define USART2 18 +#define USART3 19 +#define UART4 20 +#define UART5 21 +#define UART7 22 +#define UART8 23 +#define I2C1 24 +#define I2C2 25 +#define I2C3 26 +#define I2C5 27 +#define SPDIF 28 +#define CEC 29 +#define DAC12 30 +#define MDIO 31 +#define TIM1 32 +#define TIM8 33 +#define TIM15 34 +#define TIM16 35 +#define TIM17 36 +#define SPI1 37 +#define SPI4 38 +#define SPI5 39 +#define USART6 40 +#define SAI1 41 +#define SAI2 42 +#define SAI3 43 +#define DFSDM 44 +#define FDCAN 45 +#define LPTIM2 46 +#define LPTIM3 47 +#define LPTIM4 48 +#define LPTIM5 49 +#define SAI4 50 +#define SYSCFG 51 +#define VREF 52 +#define TMPSENS 53 +#define PMBCTRL 54 +#define HDP 55 +#define LTDC 56 +#define DSI 57 +#define IWDG2 58 +#define USBPHY 59 +#define STGENRO 60 +#define SPI6 61 +#define I2C4 62 +#define I2C6 63 +#define USART1 64 +#define RTCAPB 65 +#define TZC1 66 +#define TZPC 67 +#define IWDG1 68 +#define BSEC 69 +#define STGEN 70 +#define DMA1 71 +#define DMA2 72 +#define DMAMUX 73 +#define ADC12 74 +#define USBO 75 +#define SDMMC3 76 +#define DCMI 77 +#define CRYP2 78 +#define HASH2 79 +#define RNG2 80 +#define CRC2 81 +#define HSEM 82 +#define IPCC 83 +#define GPIOA 84 +#define GPIOB 85 +#define GPIOC 86 +#define GPIOD 87 +#define GPIOE 88 +#define GPIOF 89 +#define GPIOG 90 +#define GPIOH 91 +#define GPIOI 92 +#define GPIOJ 93 +#define GPIOK 94 +#define GPIOZ 95 +#define CRYP1 96 +#define HASH1 97 +#define RNG1 98 +#define BKPSRAM 99 +#define MDMA 100 +#define GPU 101 +#define ETHCK 102 +#define ETHTX 103 +#define ETHRX 104 +#define ETHMAC 105 +#define FMC 106 +#define QSPI 107 +#define SDMMC1 108 +#define SDMMC2 109 +#define CRC1 110 +#define USBH 111 +#define ETHSTP 112 +#define TZC2 113 + +/* Kernel clocks */ +#define SDMMC1_K 118 +#define SDMMC2_K 119 +#define SDMMC3_K 120 +#define FMC_K 121 +#define QSPI_K 122 +#define ETHCK_K 123 +#define RNG1_K 124 +#define RNG2_K 125 +#define GPU_K 126 +#define USBPHY_K 127 +#define STGEN_K 128 +#define SPDIF_K 129 +#define SPI1_K 130 +#define SPI2_K 131 +#define SPI3_K 132 +#define SPI4_K 133 +#define SPI5_K 134 +#define SPI6_K 135 +#define CEC_K 136 +#define I2C1_K 137 +#define I2C2_K 138 +#define I2C3_K 139 +#define I2C4_K 140 +#define I2C5_K 141 +#define I2C6_K 142 +#define LPTIM1_K 143 +#define LPTIM2_K 144 +#define LPTIM3_K 145 +#define LPTIM4_K 146 +#define LPTIM5_K 147 +#define USART1_K 148 +#define USART2_K 149 +#define USART3_K 150 +#define UART4_K 151 +#define UART5_K 152 +#define USART6_K 153 +#define UART7_K 154 +#define UART8_K 155 +#define DFSDM_K 156 +#define FDCAN_K 157 +#define SAI1_K 158 +#define SAI2_K 159 +#define SAI3_K 160 +#define SAI4_K 161 +#define ADC12_K 162 +#define DSI_K 163 +#define DSI_PX 164 +#define ADFSDM_K 165 +#define USBO_K 166 +#define LTDC_PX 167 +#define DAC12_K 168 +#define ETHPTP_K 169 + +/* PLL */ +#define PLL1 176 +#define PLL2 177 +#define PLL3 178 +#define PLL4 179 + +/* ODF */ +#define PLL1_P 180 +#define PLL1_Q 181 +#define PLL1_R 182 +#define PLL2_P 183 +#define PLL2_Q 184 +#define PLL2_R 185 +#define PLL3_P 186 +#define PLL3_Q 187 +#define PLL3_R 188 +#define PLL4_P 189 +#define PLL4_Q 190 +#define PLL4_R 191 + +/* AUX */ +#define RTC 192 + +/* MCLK */ +#define CK_PER 193 +#define CK_MPU 194 +#define CK_AXI 195 +#define CK_MCU 196 + +/* Time base */ +#define TIM2_K 197 +#define TIM3_K 198 +#define TIM4_K 199 +#define TIM5_K 200 +#define TIM6_K 201 +#define TIM7_K 202 +#define TIM12_K 203 +#define TIM13_K 204 +#define TIM14_K 205 +#define TIM1_K 206 +#define TIM8_K 207 +#define TIM15_K 208 +#define TIM16_K 209 +#define TIM17_K 210 + +/* MCO clocks */ +#define CK_MCO1 211 +#define CK_MCO2 212 + +/* TRACE & DEBUG clocks */ +#define CK_DBG 214 +#define CK_TRACE 215 + +/* DDR */ +#define DDRC1 220 +#define DDRC1LP 221 +#define DDRC2 222 +#define DDRC2LP 223 +#define DDRPHYC 224 +#define DDRPHYCLP 225 +#define DDRCAPB 226 +#define DDRCAPBLP 227 +#define AXIDCG 228 +#define DDRPHYCAPB 229 +#define DDRPHYCAPBLP 230 +#define DDRPERFM 231 + +#define STM32MP1_LAST_CLK 232 + +#define LTDC_K LTDC_PX +#define ETHMAC_K ETHCK_K + +/* SCMI clock identifiers */ +#define CK_SCMI_HSE 0 +#define CK_SCMI_HSI 1 +#define CK_SCMI_CSI 2 +#define CK_SCMI_LSE 3 +#define CK_SCMI_LSI 4 +#define CK_SCMI_PLL2_Q 5 +#define CK_SCMI_PLL2_R 6 +#define CK_SCMI_MPU 7 +#define CK_SCMI_AXI 8 +#define CK_SCMI_BSEC 9 +#define CK_SCMI_CRYP1 10 +#define CK_SCMI_GPIOZ 11 +#define CK_SCMI_HASH1 12 +#define CK_SCMI_I2C4 13 +#define CK_SCMI_I2C6 14 +#define CK_SCMI_IWDG1 15 +#define CK_SCMI_RNG1 16 +#define CK_SCMI_RTC 17 +#define CK_SCMI_RTCAPB 18 +#define CK_SCMI_SPI6 19 +#define CK_SCMI_USART1 20 + +#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ diff --git a/optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h b/optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h new file mode 100644 index 0000000..c84ba2c --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clks.h @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez + */ + +#ifndef _DT_BINDINGS_STM32MP13_CLKS_H_ +#define _DT_BINDINGS_STM32MP13_CLKS_H_ + +/* OSCILLATOR clocks */ +#define CK_HSE 0 +#define CK_CSI 1 +#define CK_LSI 2 +#define CK_LSE 3 +#define CK_HSI 4 +#define CK_HSE_DIV2 5 + +/* PLL */ +#define PLL1 6 +#define PLL2 7 +#define PLL3 8 +#define PLL4 9 + +/* ODF */ +#define PLL1_P 10 +#define PLL1_Q 11 +#define PLL1_R 12 +#define PLL2_P 13 +#define PLL2_Q 14 +#define PLL2_R 15 +#define PLL3_P 16 +#define PLL3_Q 17 +#define PLL3_R 18 +#define PLL4_P 19 +#define PLL4_Q 20 +#define PLL4_R 21 + +/* SYSTEM CLOCK */ +#define CK_PER 22 +#define CK_MPU 23 +#define CK_AXI 24 +#define CK_MLAHB 25 + +#define PCLK1 26 +#define PCLK2 27 +#define PCLK3 28 +#define PCLK4 29 +#define PCLK5 30 +#define PCLK6 31 + +/* BASE TIMER */ +#define CK_TIMG1 32 +#define CK_TIMG2 33 +#define CK_TIMG3 34 + +/* AUX */ +#define RTC 35 + +/* TRACE & DEBUG clocks */ +#define CK_DBG 36 +#define CK_TRACE 37 + +/* MCO clocks */ +#define CK_MCO1 38 +#define CK_MCO2 39 + +/* IP clocks */ +#define SYSCFG 40 +#define VREF 41 +#define TMPSENS 42 +#define PMBCTRL 43 +#define HDP 44 +#define IWDG2 45 +#define STGENRO 46 +#define USART1 47 +#define RTCAPB 48 +#define TZC 49 +#define TZPC 50 +#define IWDG1 51 +#define BSEC 52 +#define DMA1 53 +#define DMA2 54 +#define DMAMUX1 55 +#define DMAMUX2 56 +#define GPIOA 57 +#define GPIOB 58 +#define GPIOC 59 +#define GPIOD 60 +#define GPIOE 61 +#define GPIOF 62 +#define GPIOG 63 +#define GPIOH 64 +#define GPIOI 65 +#define CRYP1 66 +#define HASH1 67 +#define BKPSRAM 68 +#define MDMA 69 +#define CRC1 70 +#define USBH 71 +#define DMA3 72 +#define TSC 73 +#define PKA 74 +#define AXIMC 75 +#define MCE 76 +#define ETH1TX 77 +#define ETH2TX 78 +#define ETH1RX 79 +#define ETH2RX 80 +#define ETH1MAC 81 +#define ETH2MAC 82 +#define ETH1STP 83 +#define ETH2STP 84 + +/* IP clocks with parents */ +#define SDMMC1_K 85 +#define SDMMC2_K 86 +#define ADC1_K 87 +#define ADC2_K 88 +#define FMC_K 89 +#define QSPI_K 90 +#define RNG1_K 91 +#define USBPHY_K 92 +#define STGEN_K 93 +#define SPDIF_K 94 +#define SPI1_K 95 +#define SPI2_K 96 +#define SPI3_K 97 +#define SPI4_K 98 +#define SPI5_K 99 +#define I2C1_K 100 +#define I2C2_K 101 +#define I2C3_K 102 +#define I2C4_K 103 +#define I2C5_K 104 +#define TIM2_K 105 +#define TIM3_K 106 +#define TIM4_K 107 +#define TIM5_K 108 +#define TIM6_K 109 +#define TIM7_K 110 +#define TIM12_K 111 +#define TIM13_K 112 +#define TIM14_K 113 +#define TIM1_K 114 +#define TIM8_K 115 +#define TIM15_K 116 +#define TIM16_K 117 +#define TIM17_K 118 +#define LPTIM1_K 119 +#define LPTIM2_K 120 +#define LPTIM3_K 121 +#define LPTIM4_K 122 +#define LPTIM5_K 123 +#define USART1_K 124 +#define USART2_K 125 +#define USART3_K 126 +#define UART4_K 127 +#define UART5_K 128 +#define USART6_K 129 +#define UART7_K 130 +#define UART8_K 131 +#define DFSDM_K 132 +#define FDCAN_K 133 +#define SAI1_K 134 +#define SAI2_K 135 +#define ADFSDM_K 136 +#define USBO_K 137 +#define LTDC_PX 138 +#define ETH1CK_K 139 +#define ETH1PTP_K 140 +#define ETH2CK_K 141 +#define ETH2PTP_K 142 +#define DCMIPP_K 143 +#define SAES_K 144 +#define DTS_K 145 + +/* DDR */ +#define DDRC1 146 +#define DDRC1LP 147 +#define DDRC2 148 +#define DDRC2LP 149 +#define DDRPHYC 150 +#define DDRPHYCLP 151 +#define DDRCAPB 152 +#define DDRCAPBLP 153 +#define AXIDCG 154 +#define DDRPHYCAPB 155 +#define DDRPHYCAPBLP 156 +#define DDRPERFM 157 + +#define ADC1 158 +#define ADC2 159 +#define SAI1 160 +#define SAI2 161 + +#define STM32MP1_LAST_CLK 162 + +/* SCMI clock identifiers */ +#define CK_SCMI_HSE 0 +#define CK_SCMI_HSI 1 +#define CK_SCMI_CSI 2 +#define CK_SCMI_LSE 3 +#define CK_SCMI_LSI 4 +#define CK_SCMI_HSE_DIV2 5 +#define CK_SCMI_PLL2_Q 6 +#define CK_SCMI_PLL2_R 7 +#define CK_SCMI_PLL3_P 8 +#define CK_SCMI_PLL3_Q 9 +#define CK_SCMI_PLL3_R 10 +#define CK_SCMI_PLL4_P 11 +#define CK_SCMI_PLL4_Q 12 +#define CK_SCMI_PLL4_R 13 +#define CK_SCMI_MPU 14 +#define CK_SCMI_AXI 15 +#define CK_SCMI_MLAHB 16 +#define CK_SCMI_CKPER 17 +#define CK_SCMI_PCLK1 18 +#define CK_SCMI_PCLK2 19 +#define CK_SCMI_PCLK3 20 +#define CK_SCMI_PCLK4 21 +#define CK_SCMI_PCLK5 22 +#define CK_SCMI_PCLK6 23 +#define CK_SCMI_CKTIMG1 24 +#define CK_SCMI_CKTIMG2 25 +#define CK_SCMI_CKTIMG3 26 +#define CK_SCMI_RTC 27 +#define CK_SCMI_RTCAPB 28 +#define CK_SCMI_BSEC 29 + +#endif /* _DT_BINDINGS_STM32MP13_CLKS_H_ */ diff --git a/optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clksrc.h b/optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clksrc.h new file mode 100644 index 0000000..209ad5d --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/clock/stm32mp13-clksrc.h @@ -0,0 +1,384 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez + */ + +#ifndef _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ +#define _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ + +#define CMD_DIV 0 +#define CMD_MUX 1 +#define CMD_CLK 2 + +#define CMD_SHIFT 26 +#define CMD_MASK 0xFC000000 +#define CMD_DATA_MASK 0x03FFFFFF + +#define DIV_ID_SHIFT 8 +#define DIV_ID_MASK 0x0000FF00 + +#define DIV_DIVN_SHIFT 0 +#define DIV_DIVN_MASK 0x000000FF + +#define MUX_ID_SHIFT 4 +#define MUX_ID_MASK 0x00000FF0 + +#define MUX_SEL_SHIFT 0 +#define MUX_SEL_MASK 0x0000000F + +#define CLK_ID_MASK GENMASK_32(19, 11) +#define CLK_ID_SHIFT 11 +#define CLK_ON_MASK 0x00000400 +#define CLK_ON_SHIFT 10 +#define CLK_DIV_MASK GENMASK_32(9, 4) +#define CLK_DIV_SHIFT 4 +#define CLK_SEL_MASK GENMASK_32(3, 0) +#define CLK_SEL_SHIFT 0 + +#define DIV_PLL1DIVP 0 +#define DIV_PLL2DIVP 1 +#define DIV_PLL2DIVQ 2 +#define DIV_PLL2DIVR 3 +#define DIV_PLL3DIVP 4 +#define DIV_PLL3DIVQ 5 +#define DIV_PLL3DIVR 6 +#define DIV_PLL4DIVP 7 +#define DIV_PLL4DIVQ 8 +#define DIV_PLL4DIVR 9 +#define DIV_MPU 10 +#define DIV_AXI 11 +#define DIV_MLAHB 12 +#define DIV_APB1 13 +#define DIV_APB2 14 +#define DIV_APB3 15 +#define DIV_APB4 16 +#define DIV_APB5 17 +#define DIV_APB6 18 +#define DIV_RTC 19 +#define DIV_MCO1 20 +#define DIV_MCO2 21 +#define DIV_HSI 22 +#define DIV_TRACE 23 +#define DIV_ETH1PTP 24 +#define DIV_ETH2PTP 25 +#define DIV_NB 26 + +#define DIV(div_id, div) ((CMD_DIV << CMD_SHIFT) |\ + ((div_id) << DIV_ID_SHIFT) |\ + (div)) + +#define CLKSRC(mux_id, sel) ((CMD_MUX << CMD_SHIFT) |\ + ((mux_id) << MUX_ID_SHIFT) |\ + (sel)) + +/* CLK output is enable */ +#define CLK_SRC(clk_id, sel) ((CMD_CLK << CMD_SHIFT) |\ + ((clk_id) << CLK_ID_SHIFT) |\ + (sel) | CLK_ON_MASK) + +#define CLK_DISABLED(clk_id) ((CMD_CLK << CMD_SHIFT) |\ + ((clk_id) << CLK_ID_SHIFT)) + +#define MUX_MPU 0 +#define MUX_AXI 1 +#define MUX_MLAHB 2 +#define MUX_PLL12 3 +#define MUX_PLL3 4 +#define MUX_PLL4 5 +#define MUX_RTC 6 +#define MUX_MCO1 7 +#define MUX_MCO2 8 +#define MUX_CKPER 9 +#define MUX_ADC1 10 +#define MUX_ADC2 11 +#define MUX_DCMIPP 12 +#define MUX_ETH1 13 +#define MUX_ETH2 14 +#define MUX_FDCAN 15 +#define MUX_FMC 16 +#define MUX_I2C12 17 +#define MUX_I2C3 18 +#define MUX_I2C4 19 +#define MUX_I2C5 20 +#define MUX_LPTIM1 21 +#define MUX_LPTIM2 22 +#define MUX_LPTIM3 23 +#define MUX_LPTIM45 24 +#define MUX_QSPI 25 +#define MUX_RNG1 26 +#define MUX_SAES 27 +#define MUX_SAI1 28 +#define MUX_SAI2 29 +#define MUX_SDMMC1 30 +#define MUX_SDMMC2 31 +#define MUX_SPDIF 32 +#define MUX_SPI1 33 +#define MUX_SPI23 34 +#define MUX_SPI4 35 +#define MUX_SPI5 36 +#define MUX_STGEN 37 +#define MUX_UART1 38 +#define MUX_UART2 39 +#define MUX_UART35 40 +#define MUX_UART4 41 +#define MUX_UART6 42 +#define MUX_UART78 43 +#define MUX_USBO 44 +#define MUX_USBPHY 45 +#define MUX_NB 46 + +/* ADC MUX is the first Kernel MUX */ +#define MUX_KERNEL_BEGIN MUX_ADC1 + +#define CLK_MPU_HSI CLKSRC(MUX_MPU, 0) +#define CLK_MPU_HSE CLKSRC(MUX_MPU, 1) +#define CLK_MPU_PLL1P CLKSRC(MUX_MPU, 2) +#define CLK_MPU_PLL1P_DIV CLKSRC(MUX_MPU, 3) + +#define CLK_AXI_HSI CLKSRC(MUX_AXI, 0) +#define CLK_AXI_HSE CLKSRC(MUX_AXI, 1) +#define CLK_AXI_PLL2P CLKSRC(MUX_AXI, 2) + +#define CLK_MLAHBS_HSI CLKSRC(MUX_MLAHB, 0) +#define CLK_MLAHBS_HSE CLKSRC(MUX_MLAHB, 1) +#define CLK_MLAHBS_CSI CLKSRC(MUX_MLAHB, 2) +#define CLK_MLAHBS_PLL3 CLKSRC(MUX_MLAHB, 3) + +#define CLK_PLL12_HSI CLKSRC(MUX_PLL12, 0) +#define CLK_PLL12_HSE CLKSRC(MUX_PLL12, 1) + +#define CLK_PLL3_HSI CLKSRC(MUX_PLL3, 0) +#define CLK_PLL3_HSE CLKSRC(MUX_PLL3, 1) +#define CLK_PLL3_CSI CLKSRC(MUX_PLL3, 2) + +#define CLK_PLL4_HSI CLKSRC(MUX_PLL4, 0) +#define CLK_PLL4_HSE CLKSRC(MUX_PLL4, 1) +#define CLK_PLL4_CSI CLKSRC(MUX_PLL4, 2) + +#define CLK_RTC_DISABLED CLKSRC(RTC, 0) +#define CLK_RTC_LSE CLKSRC(RTC, 1) +#define CLK_RTC_LSI CLKSRC(RTC, 2) +#define CLK_RTC_HSE CLKSRC(RTC, 3) + +#define CLK_MCO1_HSI CLK_SRC(CK_MCO1, 0) +#define CLK_MCO1_HSE CLK_SRC(CK_MCO1, 1) +#define CLK_MCO1_CSI CLK_SRC(CK_MCO1, 2) +#define CLK_MCO1_LSI CLK_SRC(CK_MCO1, 3) +#define CLK_MCO1_LSE CLK_SRC(CK_MCO1, 4) +#define CLK_MCO1_DISABLED CLK_DISABLED(CK_MCO1) + +#define CLK_MCO2_MPU CLK_SRC(CK_MCO2, 0) +#define CLK_MCO2_AXI CLK_SRC(CK_MCO2, 1) +#define CLK_MCO2_MLAHB CLK_SRC(CK_MCO2, 2) +#define CLK_MCO2_PLL4 CLK_SRC(CK_MCO2, 3) +#define CLK_MCO2_HSE CLK_SRC(CK_MCO2, 4) +#define CLK_MCO2_HSI CLK_SRC(CK_MCO2, 5) +#define CLK_MCO2_DISABLED CLK_DISABLED(CK_MCO2) + +#define CLK_CKPER_HSI CLKSRC(MUX_CKPER, 0) +#define CLK_CKPER_CSI CLKSRC(MUX_CKPER, 1) +#define CLK_CKPER_HSE CLKSRC(MUX_CKPER, 2) +#define CLK_CKPER_DISABLED CLKSRC(MUX_CKPER, 3) + +#define CLK_I2C12_PCLK1 CLKSRC(MUX_I2C12, 0) +#define CLK_I2C12_PLL4R CLKSRC(MUX_I2C12, 1) +#define CLK_I2C12_HSI CLKSRC(MUX_I2C12, 2) +#define CLK_I2C12_CSI CLKSRC(MUX_I2C12, 3) + +#define CLK_I2C3_PCLK6 CLKSRC(MUX_I2C3, 0) +#define CLK_I2C3_PLL4R CLKSRC(MUX_I2C3, 1) +#define CLK_I2C3_HSI CLKSRC(MUX_I2C3, 2) +#define CLK_I2C3_CSI CLKSRC(MUX_I2C3, 3) + +#define CLK_I2C4_PCLK6 CLKSRC(MUX_I2C4, 0) +#define CLK_I2C4_PLL4R CLKSRC(MUX_I2C4, 1) +#define CLK_I2C4_HSI CLKSRC(MUX_I2C4, 2) +#define CLK_I2C4_CSI CLKSRC(MUX_I2C4, 3) + +#define CLK_I2C5_PCLK6 CLKSRC(MUX_I2C5, 0) +#define CLK_I2C5_PLL4R CLKSRC(MUX_I2C5, 1) +#define CLK_I2C5_HSI CLKSRC(MUX_I2C5, 2) +#define CLK_I2C5_CSI CLKSRC(MUX_I2C5, 3) + +#define CLK_SPI1_PLL4P CLKSRC(MUX_SPI1, 0) +#define CLK_SPI1_PLL3Q CLKSRC(MUX_SPI1, 1) +#define CLK_SPI1_I2SCKIN CLKSRC(MUX_SPI1, 2) +#define CLK_SPI1_CKPER CLKSRC(MUX_SPI1, 3) +#define CLK_SPI1_PLL3R CLKSRC(MUX_SPI1, 4) + +#define CLK_SPI23_PLL4P CLKSRC(MUX_SPI23, 0) +#define CLK_SPI23_PLL3Q CLKSRC(MUX_SPI23, 1) +#define CLK_SPI23_I2SCKIN CLKSRC(MUX_SPI23, 2) +#define CLK_SPI23_CKPER CLKSRC(MUX_SPI23, 3) +#define CLK_SPI23_PLL3R CLKSRC(MUX_SPI23, 4) + +#define CLK_SPI4_PCLK6 CLKSRC(MUX_SPI4, 0) +#define CLK_SPI4_PLL4Q CLKSRC(MUX_SPI4, 1) +#define CLK_SPI4_HSI CLKSRC(MUX_SPI4, 2) +#define CLK_SPI4_CSI CLKSRC(MUX_SPI4, 3) +#define CLK_SPI4_HSE CLKSRC(MUX_SPI4, 4) +#define CLK_SPI4_I2SCKIN CLKSRC(MUX_SPI4, 5) + +#define CLK_SPI5_PCLK6 CLKSRC(MUX_SPI5, 0) +#define CLK_SPI5_PLL4Q CLKSRC(MUX_SPI5, 1) +#define CLK_SPI5_HSI CLKSRC(MUX_SPI5, 2) +#define CLK_SPI5_CSI CLKSRC(MUX_SPI5, 3) +#define CLK_SPI5_HSE CLKSRC(MUX_SPI5, 4) + +#define CLK_UART1_PCLK6 CLKSRC(MUX_UART1, 0) +#define CLK_UART1_PLL3Q CLKSRC(MUX_UART1, 1) +#define CLK_UART1_HSI CLKSRC(MUX_UART1, 2) +#define CLK_UART1_CSI CLKSRC(MUX_UART1, 3) +#define CLK_UART1_PLL4Q CLKSRC(MUX_UART1, 4) +#define CLK_UART1_HSE CLKSRC(MUX_UART1, 5) + +#define CLK_UART2_PCLK6 CLKSRC(MUX_UART2, 0) +#define CLK_UART2_PLL3Q CLKSRC(MUX_UART2, 1) +#define CLK_UART2_HSI CLKSRC(MUX_UART2, 2) +#define CLK_UART2_CSI CLKSRC(MUX_UART2, 3) +#define CLK_UART2_PLL4Q CLKSRC(MUX_UART2, 4) +#define CLK_UART2_HSE CLKSRC(MUX_UART2, 5) + +#define CLK_UART35_PCLK1 CLKSRC(MUX_UART35, 0) +#define CLK_UART35_PLL4Q CLKSRC(MUX_UART35, 1) +#define CLK_UART35_HSI CLKSRC(MUX_UART35, 2) +#define CLK_UART35_CSI CLKSRC(MUX_UART35, 3) +#define CLK_UART35_HSE CLKSRC(MUX_UART35, 4) + +#define CLK_UART4_PCLK1 CLKSRC(MUX_UART4, 0) +#define CLK_UART4_PLL4Q CLKSRC(MUX_UART4, 1) +#define CLK_UART4_HSI CLKSRC(MUX_UART4, 2) +#define CLK_UART4_CSI CLKSRC(MUX_UART4, 3) +#define CLK_UART4_HSE CLKSRC(MUX_UART4, 4) + +#define CLK_UART6_PCLK2 CLKSRC(MUX_UART6, 0) +#define CLK_UART6_PLL4Q CLKSRC(MUX_UART6, 1) +#define CLK_UART6_HSI CLKSRC(MUX_UART6, 2) +#define CLK_UART6_CSI CLKSRC(MUX_UART6, 3) +#define CLK_UART6_HSE CLKSRC(MUX_UART6, 4) + +#define CLK_UART78_PCLK1 CLKSRC(MUX_UART78, 0) +#define CLK_UART78_PLL4Q CLKSRC(MUX_UART78, 1) +#define CLK_UART78_HSI CLKSRC(MUX_UART78, 2) +#define CLK_UART78_CSI CLKSRC(MUX_UART78, 3) +#define CLK_UART78_HSE CLKSRC(MUX_UART78, 4) + +#define CLK_LPTIM1_PCLK1 CLKSRC(MUX_LPTIM1, 0) +#define CLK_LPTIM1_PLL4P CLKSRC(MUX_LPTIM1, 1) +#define CLK_LPTIM1_PLL3Q CLKSRC(MUX_LPTIM1, 2) +#define CLK_LPTIM1_LSE CLKSRC(MUX_LPTIM1, 3) +#define CLK_LPTIM1_LSI CLKSRC(MUX_LPTIM1, 4) +#define CLK_LPTIM1_CKPER CLKSRC(MUX_LPTIM1, 5) + +#define CLK_LPTIM2_PCLK3 CLKSRC(MUX_LPTIM2, 0) +#define CLK_LPTIM2_PLL4Q CLKSRC(MUX_LPTIM2, 1) +#define CLK_LPTIM2_CKPER CLKSRC(MUX_LPTIM2, 2) +#define CLK_LPTIM2_LSE CLKSRC(MUX_LPTIM2, 3) +#define CLK_LPTIM2_LSI CLKSRC(MUX_LPTIM2, 4) + +#define CLK_LPTIM3_PCLK3 CLKSRC(MUX_LPTIM3, 0) +#define CLK_LPTIM3_PLL4Q CLKSRC(MUX_LPTIM3, 1) +#define CLK_LPTIM3_CKPER CLKSRC(MUX_LPTIM3, 2) +#define CLK_LPTIM3_LSE CLKSRC(MUX_LPTIM3, 3) +#define CLK_LPTIM3_LSI CLKSRC(MUX_LPTIM3, 4) + +#define CLK_LPTIM45_PCLK3 CLKSRC(MUX_LPTIM45, 0) +#define CLK_LPTIM45_PLL4P CLKSRC(MUX_LPTIM45, 1) +#define CLK_LPTIM45_PLL3Q CLKSRC(MUX_LPTIM45, 2) +#define CLK_LPTIM45_LSE CLKSRC(MUX_LPTIM45, 3) +#define CLK_LPTIM45_LSI CLKSRC(MUX_LPTIM45, 4) +#define CLK_LPTIM45_CKPER CLKSRC(MUX_LPTIM45, 5) + +#define CLK_SAI1_PLL4Q CLKSRC(MUX_SAI1, 0) +#define CLK_SAI1_PLL3Q CLKSRC(MUX_SAI1, 1) +#define CLK_SAI1_I2SCKIN CLKSRC(MUX_SAI1, 2) +#define CLK_SAI1_CKPER CLKSRC(MUX_SAI1, 3) +#define CLK_SAI1_PLL3R CLKSRC(MUX_SAI1, 4) + +#define CLK_SAI2_PLL4Q CLKSRC(MUX_SAI2, 0) +#define CLK_SAI2_PLL3Q CLKSRC(MUX_SAI2, 1) +#define CLK_SAI2_I2SCKIN CLKSRC(MUX_SAI2, 2) +#define CLK_SAI2_CKPER CLKSRC(MUX_SAI2, 3) +#define CLK_SAI2_SPDIF CLKSRC(MUX_SAI2, 4) +#define CLK_SAI2_PLL3R CLKSRC(MUX_SAI2, 5) + +#define CLK_FDCAN_HSE CLKSRC(MUX_FDCAN, 0) +#define CLK_FDCAN_PLL3Q CLKSRC(MUX_FDCAN, 1) +#define CLK_FDCAN_PLL4Q CLKSRC(MUX_FDCAN, 2) +#define CLK_FDCAN_PLL4R CLKSRC(MUX_FDCAN, 3) + +#define CLK_SPDIF_PLL4P CLKSRC(MUX_SPDIF, 0) +#define CLK_SPDIF_PLL3Q CLKSRC(MUX_SPDIF, 1) +#define CLK_SPDIF_HSI CLKSRC(MUX_SPDIF, 2) + +#define CLK_ADC1_PLL4R CLKSRC(MUX_ADC1, 0) +#define CLK_ADC1_CKPER CLKSRC(MUX_ADC1, 1) +#define CLK_ADC1_PLL3Q CLKSRC(MUX_ADC1, 2) + +#define CLK_ADC2_PLL4R CLKSRC(MUX_ADC2, 0) +#define CLK_ADC2_CKPER CLKSRC(MUX_ADC2, 1) +#define CLK_ADC2_PLL3Q CLKSRC(MUX_ADC2, 2) + +#define CLK_SDMMC1_HCLK6 CLKSRC(MUX_SDMMC1, 0) +#define CLK_SDMMC1_PLL3R CLKSRC(MUX_SDMMC1, 1) +#define CLK_SDMMC1_PLL4P CLKSRC(MUX_SDMMC1, 2) +#define CLK_SDMMC1_HSI CLKSRC(MUX_SDMMC1, 3) + +#define CLK_SDMMC2_HCLK6 CLKSRC(MUX_SDMMC2, 0) +#define CLK_SDMMC2_PLL3R CLKSRC(MUX_SDMMC2, 1) +#define CLK_SDMMC2_PLL4P CLKSRC(MUX_SDMMC2, 2) +#define CLK_SDMMC2_HSI CLKSRC(MUX_SDMMC2, 3) + +#define CLK_ETH1_PLL4P CLKSRC(MUX_ETH1, 0) +#define CLK_ETH1_PLL3Q CLKSRC(MUX_ETH1, 1) + +#define CLK_ETH2_PLL4P CLKSRC(MUX_ETH2, 0) +#define CLK_ETH2_PLL3Q CLKSRC(MUX_ETH2, 1) + +#define CLK_USBPHY_HSE CLKSRC(MUX_USBPHY, 0) +#define CLK_USBPHY_PLL4R CLKSRC(MUX_USBPHY, 1) +#define CLK_USBPHY_HSE_DIV2 CLKSRC(MUX_USBPHY, 2) + +#define CLK_USBO_PLL4R CLKSRC(MUX_USBO, 0) +#define CLK_USBO_USBPHY CLKSRC(MUX_USBO, 1) + +#define CLK_QSPI_ACLK CLKSRC(MUX_QSPI, 0) +#define CLK_QSPI_PLL3R CLKSRC(MUX_QSPI, 1) +#define CLK_QSPI_PLL4P CLKSRC(MUX_QSPI, 2) +#define CLK_QSPI_CKPER CLKSRC(MUX_QSPI, 3) + +#define CLK_FMC_ACLK CLKSRC(MUX_FMC, 0) +#define CLK_FMC_PLL3R CLKSRC(MUX_FMC, 1) +#define CLK_FMC_PLL4P CLKSRC(MUX_FMC, 2) +#define CLK_FMC_CKPER CLKSRC(MUX_FMC, 3) + +#define CLK_RNG1_CSI CLKSRC(MUX_RNG1, 0) +#define CLK_RNG1_PLL4R CLKSRC(MUX_RNG1, 1) +#define CLK_RNG1_LSE CLKSRC(MUX_RNG1, 2) +#define CLK_RNG1_LSI CLKSRC(MUX_RNG1, 3) + +#define CLK_STGEN_HSI CLKSRC(MUX_STGEN, 0) +#define CLK_STGEN_HSE CLKSRC(MUX_STGEN, 1) + +#define CLK_DCMIPP_ACLK CLKSRC(MUX_DCMIPP, 0) +#define CLK_DCMIPP_PLL2Q CLKSRC(MUX_DCMIPP, 1) +#define CLK_DCMIPP_PLL4P CLKSRC(MUX_DCMIPP, 2) +#define CLK_DCMIPP_CKPER CLKSRC(MUX_DCMIPP, 3) + +#define CLK_SAES_AXI CLKSRC(MUX_SAES, 0) +#define CLK_SAES_CKPER CLKSRC(MUX_SAES, 1) +#define CLK_SAES_PLL4R CLKSRC(MUX_SAES, 2) +#define CLK_SAES_LSI CLKSRC(MUX_SAES, 3) + +/* define for st,pll /csg */ +#define SSCG_MODE_CENTER_SPREAD 0 +#define SSCG_MODE_DOWN_SPREAD 1 + +/* define for st,drive */ +#define LSEDRV_LOWEST 0 +#define LSEDRV_MEDIUM_LOW 1 +#define LSEDRV_MEDIUM_HIGH 2 +#define LSEDRV_HIGHEST 3 + +#endif /* _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ */ diff --git a/optee/optee_os/core/include/dt-bindings/dma/at91.h b/optee/optee_os/core/include/dt-bindings/dma/at91.h new file mode 100644 index 0000000..fe4bc60 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/dma/at91.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * This header provides macros for at91 dma bindings. + * + * Copyright (C) 2013 Ludovic Desroches + */ + +#ifndef __DT_BINDINGS_DMA_AT91_H__ +#define __DT_BINDINGS_DMA_AT91_H__ + +/* ---------- HDMAC ---------- */ + +/* + * Source and/or destination peripheral ID + */ +#define AT91_DMA_CFG_PER_ID_MASK (0xff) +#define AT91_DMA_CFG_PER_ID(id) ((id) & AT91_DMA_CFG_PER_ID_MASK) + +/* + * FIFO configuration: it defines when a request is serviced. + */ +#define AT91_DMA_CFG_FIFOCFG_OFFSET (8) +#define AT91_DMA_CFG_FIFOCFG_MASK (0xf << AT91_DMA_CFG_FIFOCFG_OFFSET) +/* half FIFO (default behavior) */ +#define AT91_DMA_CFG_FIFOCFG_HALF (0x0 << AT91_DMA_CFG_FIFOCFG_OFFSET) +/* largest defined AHB burst */ +#define AT91_DMA_CFG_FIFOCFG_ALAP (0x1 << AT91_DMA_CFG_FIFOCFG_OFFSET) +/* single AHB access */ +#define AT91_DMA_CFG_FIFOCFG_ASAP (0x2 << AT91_DMA_CFG_FIFOCFG_OFFSET) + +/* ---------- XDMAC ---------- */ +#define AT91_XDMAC_DT_MEM_IF_MASK (0x1) +#define AT91_XDMAC_DT_MEM_IF_OFFSET (13) +#define AT91_XDMAC_DT_MEM_IF(mem_if) \ + (((mem_if) & AT91_XDMAC_DT_MEM_IF_MASK) \ + << AT91_XDMAC_DT_MEM_IF_OFFSET) +#define AT91_XDMAC_DT_GET_MEM_IF(cfg) \ + (((cfg) >> AT91_XDMAC_DT_MEM_IF_OFFSET) \ + & AT91_XDMAC_DT_MEM_IF_MASK) + +#define AT91_XDMAC_DT_PER_IF_MASK (0x1) +#define AT91_XDMAC_DT_PER_IF_OFFSET (14) +#define AT91_XDMAC_DT_PER_IF(per_if) \ + (((per_if) & AT91_XDMAC_DT_PER_IF_MASK) \ + << AT91_XDMAC_DT_PER_IF_OFFSET) +#define AT91_XDMAC_DT_GET_PER_IF(cfg) \ + (((cfg) >> AT91_XDMAC_DT_PER_IF_OFFSET) \ + & AT91_XDMAC_DT_PER_IF_MASK) + +#define AT91_XDMAC_DT_PERID_MASK (0x7f) +#define AT91_XDMAC_DT_PERID_OFFSET (24) +#define AT91_XDMAC_DT_PERID(perid) (((perid) & AT91_XDMAC_DT_PERID_MASK) \ + << AT91_XDMAC_DT_PERID_OFFSET) +#define AT91_XDMAC_DT_GET_PERID(cfg) (((cfg) >> AT91_XDMAC_DT_PERID_OFFSET) \ + & AT91_XDMAC_DT_PERID_MASK) + +#endif /* __DT_BINDINGS_AT91_DMA_H__ */ diff --git a/optee/optee_os/core/include/dt-bindings/gpio/atmel,piobu.h b/optee/optee_os/core/include/dt-bindings/gpio/atmel,piobu.h new file mode 100644 index 0000000..d92af71 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/gpio/atmel,piobu.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ +/* + * Copyright (C) 2022 Microchip + */ + +#ifndef _DT_BINDINGS_GPIO_ATMEL_PIOBU_H +#define _DT_BINDINGS_GPIO_ATMEL_PIOBU_H + +#define PIOBU_PIN_AFV_SHIFT 0 +#define PIOBU_PIN_AFV_MASK 0xF +#define PIOBU_PIN_AFV(val) (((val) & PIOBU_PIN_AFV_MASK) >> \ + PIOBU_PIN_AFV_SHIFT) + +#define PIOBU_PIN_RFV_SHIFT 4 +#define PIOBU_PIN_RFV_MASK 0xF0 +#define PIOBU_PIN_RFV(val) (((val) & PIOBU_PIN_RFV_MASK) >> \ + PIOBU_PIN_RFV_SHIFT) + +#define PIOBU_PIN_PULL_MODE_SHIFT 8 +#define PIOBU_PIN_PULL_MODE_MASK (0x3 << PIOBU_PIN_PULL_MODE_SHIFT) +#define PIOBU_PIN_PULL_MODE(val) (((val) & PIOBU_PIN_PULL_MODE_MASK) >> \ + PIOBU_PIN_PULL_MODE_SHIFT) +#define PIOBU_PIN_PULL_NONE 0 +#define PIOBU_PIN_PULL_UP 1 +#define PIOBU_PIN_PULL_DOWN 2 + +#define PIOBU_PIN_DEF_LEVEL_SHIFT 10 +#define PIOBU_PIN_DEF_LEVEL_MASK (BIT(PIOBU_PIN_DEF_LEVEL_SHIFT)) +#define PIOBU_PIN_DEF_LEVEL(val) (((val) & PIOBU_PIN_DEF_LEVEL_MASK) >> \ + PIOBU_PIN_DEF_LEVEL_SHIFT) +#define PIOBU_PIN_DEF_LEVEL_LOW 0 +#define PIOBU_PIN_DEF_LEVEL_HIGH 1 + +#define PIOBU_PIN_WAKEUP_SHIFT 11 +#define PIOBU_PIN_WAKEUP_MASK (BIT(PIOBU_PIN_WAKEUP_SHIFT)) +#define PIOBU_PIN_WAKEUP(val) (((val) & PIOBU_PIN_WAKEUP_MASK) >> \ + PIOBU_PIN_WAKEUP_SHIFT) +#define PIOBU_PIN_WAKEUP_DISABLE 0 +#define PIOBU_PIN_WAKEUP_ENABLE 1 + +#define PIOBU_PIN_INPUT(afv, rfv, pull_mode, def_level, wakeup) \ + ((afv) | \ + ((rfv) << PIOBU_PIN_RFV_SHIFT) & PIOBU_PIN_RFV_MASK | \ + ((pull_mode) << PIOBU_PIN_PULL_MODE_SHIFT) & \ + PIOBU_PIN_PULL_MODE_MASK | \ + ((def_level) << PIOBU_PIN_DEF_LEVEL_SHIFT) & \ + PIOBU_PIN_DEF_LEVEL_MASK | \ + ((wakeup) << PIOBU_PIN_WAKEUP_SHIFT) & PIOBU_PIN_WAKEUP_MASK) + +#endif /* _DT_BINDINGS_GPIO_ATMEL_PIOBU_H */ diff --git a/optee/optee_os/core/include/dt-bindings/gpio/gpio.h b/optee/optee_os/core/include/dt-bindings/gpio/gpio.h new file mode 100644 index 0000000..a635554 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/gpio/gpio.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ +/* + * This header provides constants for most GPIO bindings. + * + * Most GPIO bindings include a flags cell as part of the GPIO specifier. + * In most cases, the format of the flags cell uses the standard values + * defined in this header. + */ + +#ifndef _DT_BINDINGS_GPIO_GPIO_H +#define _DT_BINDINGS_GPIO_GPIO_H + +/* Bit 0 express polarity */ +#define GPIO_ACTIVE_HIGH 0 +#define GPIO_ACTIVE_LOW 1 + +/* Bit 1 express single-endedness */ +#define GPIO_PUSH_PULL 0 +#define GPIO_SINGLE_ENDED 2 + +/* Bit 2 express Open drain or open source */ +#define GPIO_LINE_OPEN_SOURCE 0 +#define GPIO_LINE_OPEN_DRAIN 4 + +/* + * Open Drain/Collector is the combination of single-ended open drain interface. + * Open Source/Emitter is the combination of single-ended open source interface. + */ +#define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN) +#define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE) + +/* Bit 3 express GPIO suspend/resume and reset persistence */ +#define GPIO_PERSISTENT 0 +#define GPIO_TRANSITORY 8 + +/* Bit 4 express pull up */ +#define GPIO_PULL_UP 16 + +/* Bit 5 express pull down */ +#define GPIO_PULL_DOWN 32 + +#endif diff --git a/optee/optee_os/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h b/optee/optee_os/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h new file mode 100644 index 0000000..25060f6 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) 2021 Microchip + * + * This header provides constants for configuring the AT91 SAMA5D2 ADC + */ + +#ifndef _DT_BINDINGS_IIO_ADC_AT91_SAMA5D2_ADC_H +#define _DT_BINDINGS_IIO_ADC_AT91_SAMA5D2_ADC_H + +/* X relative position channel index */ +#define AT91_SAMA5D2_ADC_X_CHANNEL 24 +/* Y relative position channel index */ +#define AT91_SAMA5D2_ADC_Y_CHANNEL 25 +/* pressure channel index */ +#define AT91_SAMA5D2_ADC_P_CHANNEL 26 + +#endif diff --git a/optee/optee_os/core/include/dt-bindings/interrupt-controller/arm-gic.h b/optee/optee_os/core/include/dt-bindings/interrupt-controller/arm-gic.h new file mode 100644 index 0000000..35b6f69 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/interrupt-controller/arm-gic.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * This header provides constants for the ARM GIC. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H + +#include + +/* interrupt specifier cell 0 */ + +#define GIC_SPI 0 +#define GIC_PPI 1 + +/* + * Interrupt specifier cell 2. + * The flags in irq.h are valid, plus those below. + */ +#define GIC_CPU_MASK_RAW(x) ((x) << 8) +#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) + +#endif diff --git a/optee/optee_os/core/include/dt-bindings/interrupt-controller/irq.h b/optee/optee_os/core/include/dt-bindings/interrupt-controller/irq.h new file mode 100644 index 0000000..9e3d183 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/interrupt-controller/irq.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * This header provides constants for most IRQ bindings. + * + * Most IRQ bindings include a flags cell as part of the IRQ specifier. + * In most cases, the format of the flags cell uses the standard values + * defined in this header. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H + +#define IRQ_TYPE_NONE 0 +#define IRQ_TYPE_EDGE_RISING 1 +#define IRQ_TYPE_EDGE_FALLING 2 +#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) +#define IRQ_TYPE_LEVEL_HIGH 4 +#define IRQ_TYPE_LEVEL_LOW 8 + +#endif diff --git a/optee/optee_os/core/include/dt-bindings/mfd/atmel-flexcom.h b/optee/optee_os/core/include/dt-bindings/mfd/atmel-flexcom.h new file mode 100644 index 0000000..6ece63d --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/mfd/atmel-flexcom.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * This header provides macros for Atmel Flexcom DT bindings. + * + * Copyright (C) 2015 Cyrille Pitchen + */ + +#ifndef __DT_BINDINGS_MFD_ATMEL_FLEXCOM_H__ +#define __DT_BINDINGS_MFD_ATMEL_FLEXCOM_H__ + +#define ATMEL_FLEXCOM_MODE_USART 1 +#define ATMEL_FLEXCOM_MODE_SPI 2 +#define ATMEL_FLEXCOM_MODE_TWI 3 + +#endif /* __DT_BINDINGS_MFD_ATMEL_FLEXCOM_H__ */ diff --git a/optee/optee_os/core/include/dt-bindings/mfd/st,stpmic1.h b/optee/optee_os/core/include/dt-bindings/mfd/st,stpmic1.h new file mode 100644 index 0000000..321cd08 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/mfd/st,stpmic1.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Philippe Peurichard , + * Pascal Paillet for STMicroelectronics. + */ + +#ifndef __DT_BINDINGS_STPMIC1_H__ +#define __DT_BINDINGS_STPMIC1_H__ + +/* IRQ definitions */ +#define IT_PONKEY_F 0 +#define IT_PONKEY_R 1 +#define IT_WAKEUP_F 2 +#define IT_WAKEUP_R 3 +#define IT_VBUS_OTG_F 4 +#define IT_VBUS_OTG_R 5 +#define IT_SWOUT_F 6 +#define IT_SWOUT_R 7 + +#define IT_CURLIM_BUCK1 8 +#define IT_CURLIM_BUCK2 9 +#define IT_CURLIM_BUCK3 10 +#define IT_CURLIM_BUCK4 11 +#define IT_OCP_OTG 12 +#define IT_OCP_SWOUT 13 +#define IT_OCP_BOOST 14 +#define IT_OVP_BOOST 15 + +#define IT_CURLIM_LDO1 16 +#define IT_CURLIM_LDO2 17 +#define IT_CURLIM_LDO3 18 +#define IT_CURLIM_LDO4 19 +#define IT_CURLIM_LDO5 20 +#define IT_CURLIM_LDO6 21 +#define IT_SHORT_SWOTG 22 +#define IT_SHORT_SWOUT 23 + +#define IT_TWARN_F 24 +#define IT_TWARN_R 25 +#define IT_VINLOW_F 26 +#define IT_VINLOW_R 27 +#define IT_SWIN_F 30 +#define IT_SWIN_R 31 + +/* BUCK MODES definitions */ +#define STPMIC1_BUCK_MODE_NORMAL 0 +#define STPMIC1_BUCK_MODE_LP 2 + +#endif /* __DT_BINDINGS_STPMIC1_H__ */ diff --git a/optee/optee_os/core/include/dt-bindings/pinctrl/stm32-pinfunc.h b/optee/optee_os/core/include/dt-bindings/pinctrl/stm32-pinfunc.h new file mode 100644 index 0000000..370a25a --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/pinctrl/stm32-pinfunc.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved + * Author: Torgue Alexandre for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32_PINFUNC_H +#define _DT_BINDINGS_STM32_PINFUNC_H + +/* define PIN modes */ +#define GPIO 0x0 +#define AF0 0x1 +#define AF1 0x2 +#define AF2 0x3 +#define AF3 0x4 +#define AF4 0x5 +#define AF5 0x6 +#define AF6 0x7 +#define AF7 0x8 +#define AF8 0x9 +#define AF9 0xa +#define AF10 0xb +#define AF11 0xc +#define AF12 0xd +#define AF13 0xe +#define AF14 0xf +#define AF15 0x10 +#define ANALOG 0x11 +#define RSVD 0x12 + +/* define Pins number*/ +#define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) + +#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode)) + +/* package information */ +#define STM32MP_PKG_AA 0x1 +#define STM32MP_PKG_AB 0x2 +#define STM32MP_PKG_AC 0x4 +#define STM32MP_PKG_AD 0x8 + +#endif /* _DT_BINDINGS_STM32_PINFUNC_H */ + diff --git a/optee/optee_os/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h b/optee/optee_os/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h new file mode 100644 index 0000000..045e112 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (c) 2018 Microchip Technology, Inc. All rights reserved. + * + * Device Tree binding constants for the ACT8945A PMIC regulators + */ + +#ifndef _DT_BINDINGS_REGULATOR_ACT8945A_H +#define _DT_BINDINGS_REGULATOR_ACT8945A_H + +/* + * These constants should be used to specify regulator modes in device tree for + * ACT8945A regulators as follows: + * ACT8945A_REGULATOR_MODE_FIXED: It is specific to DCDC regulators and it + * specifies the usage of fixed-frequency + * PWM. + * + * ACT8945A_REGULATOR_MODE_NORMAL: It is specific to LDO regulators and it + * specifies the usage of normal mode. + * + * ACT8945A_REGULATOR_MODE_LOWPOWER: For DCDC and LDO regulators; it specify + * the usage of proprietary power-saving + * mode. + */ + +#define ACT8945A_REGULATOR_MODE_FIXED 1 +#define ACT8945A_REGULATOR_MODE_NORMAL 2 +#define ACT8945A_REGULATOR_MODE_LOWPOWER 3 + +#endif diff --git a/optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h b/optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h new file mode 100644 index 0000000..59f0674 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ +/* + * Copyright (C) 2020-2022, STMicroelectronics - All Rights Reserved + */ + +#ifndef __DT_BINDINGS_REGULATOR_ST_STM32MP13_REGULATOR_H +#define __DT_BINDINGS_REGULATOR_ST_STM32MP13_REGULATOR_H + +/* SCMI voltage domains identifiers */ + +/* SOC Internal regulators */ +#define VOLTD_SCMI_REG11 0 +#define VOLTD_SCMI_REG18 1 +#define VOLTD_SCMI_USB33 2 +#define VOLTD_SCMI_SDMMC1_IO 3 +#define VOLTD_SCMI_SDMMC2_IO 4 +#define VOLTD_SCMI_VREFBUF 5 + +/* STPMIC1 regulators */ +#define VOLTD_SCMI_STPMIC1_BUCK1 6 +#define VOLTD_SCMI_STPMIC1_BUCK2 7 +#define VOLTD_SCMI_STPMIC1_BUCK3 8 +#define VOLTD_SCMI_STPMIC1_BUCK4 9 +#define VOLTD_SCMI_STPMIC1_LDO1 10 +#define VOLTD_SCMI_STPMIC1_LDO2 11 +#define VOLTD_SCMI_STPMIC1_LDO3 12 +#define VOLTD_SCMI_STPMIC1_LDO4 13 +#define VOLTD_SCMI_STPMIC1_LDO5 14 +#define VOLTD_SCMI_STPMIC1_LDO6 15 +#define VOLTD_SCMI_STPMIC1_VREFDDR 16 +#define VOLTD_SCMI_STPMIC1_BOOST 17 +#define VOLTD_SCMI_STPMIC1_PWR_SW1 18 +#define VOLTD_SCMI_STPMIC1_PWR_SW2 19 + +#endif /*__DT_BINDINGS_REGULATOR_ST_STM32MP13_REGULATOR_H */ diff --git a/optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h b/optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h new file mode 100644 index 0000000..b3bccff --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#ifndef __DT_BINDINGS_REGULATOR_ST_STM32MP15_REGULATOR_H +#define __DT_BINDINGS_REGULATOR_ST_STM32MP15_REGULATOR_H + +/* SCMI voltage domain identifiers */ + +#define VOLTD_SCMI_REG11 0 +#define VOLTD_SCMI_REG18 1 +#define VOLTD_SCMI_USB33 2 +#define VOLTD_SCMI_STPMIC1_BUCK1 3 +#define VOLTD_SCMI_STPMIC1_BUCK2 4 +#define VOLTD_SCMI_STPMIC1_BUCK3 5 +#define VOLTD_SCMI_STPMIC1_BUCK4 6 +#define VOLTD_SCMI_STPMIC1_LDO1 7 +#define VOLTD_SCMI_STPMIC1_LDO2 8 +#define VOLTD_SCMI_STPMIC1_LDO3 9 +#define VOLTD_SCMI_STPMIC1_LDO4 10 +#define VOLTD_SCMI_STPMIC1_LDO5 11 +#define VOLTD_SCMI_STPMIC1_LDO6 12 +#define VOLTD_SCMI_STPMIC1_VREFDDR 13 +#define VOLTD_SCMI_STPMIC1_BOOST 14 +#define VOLTD_SCMI_STPMIC1_PWR_SW1 15 +#define VOLTD_SCMI_STPMIC1_PWR_SW2 16 + +#endif /*__DT_BINDINGS_REGULATOR_ST_STM32MP15_REGULATOR_H */ diff --git a/optee/optee_os/core/include/dt-bindings/reset/stm32mp1-resets.h b/optee/optee_os/core/include/dt-bindings/reset/stm32mp1-resets.h new file mode 100644 index 0000000..84ab3c7 --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/reset/stm32mp1-resets.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP1_RESET_H_ +#define _DT_BINDINGS_STM32MP1_RESET_H_ + +#define MCU_HOLD_BOOT_R 2144 +#define LTDC_R 3072 +#define DSI_R 3076 +#define DDRPERFM_R 3080 +#define USBPHY_R 3088 +#define SPI6_R 3136 +#define I2C4_R 3138 +#define I2C6_R 3139 +#define USART1_R 3140 +#define STGEN_R 3156 +#define GPIOZ_R 3200 +#define CRYP1_R 3204 +#define HASH1_R 3205 +#define RNG1_R 3206 +#define AXIM_R 3216 +#define GPU_R 3269 +#define ETHMAC_R 3274 +#define FMC_R 3276 +#define QSPI_R 3278 +#define SDMMC1_R 3280 +#define SDMMC2_R 3281 +#define CRC1_R 3284 +#define USBH_R 3288 +#define MDMA_R 3328 +#define MPSYST_R 8224 +#define MCU_R 8225 +#define TIM2_R 19456 +#define TIM3_R 19457 +#define TIM4_R 19458 +#define TIM5_R 19459 +#define TIM6_R 19460 +#define TIM7_R 19461 +#define TIM12_R 16462 +#define TIM13_R 16463 +#define TIM14_R 16464 +#define LPTIM1_R 19465 +#define SPI2_R 19467 +#define SPI3_R 19468 +#define USART2_R 19470 +#define USART3_R 19471 +#define UART4_R 19472 +#define UART5_R 19473 +#define UART7_R 19474 +#define UART8_R 19475 +#define I2C1_R 19477 +#define I2C2_R 19478 +#define I2C3_R 19479 +#define I2C5_R 19480 +#define SPDIF_R 19482 +#define CEC_R 19483 +#define DAC12_R 19485 +#define MDIO_R 19847 +#define TIM1_R 19520 +#define TIM8_R 19521 +#define TIM15_R 19522 +#define TIM16_R 19523 +#define TIM17_R 19524 +#define SPI1_R 19528 +#define SPI4_R 19529 +#define SPI5_R 19530 +#define USART6_R 19533 +#define SAI1_R 19536 +#define SAI2_R 19537 +#define SAI3_R 19538 +#define DFSDM_R 19540 +#define FDCAN_R 19544 +#define LPTIM2_R 19584 +#define LPTIM3_R 19585 +#define LPTIM4_R 19586 +#define LPTIM5_R 19587 +#define SAI4_R 19592 +#define SYSCFG_R 19595 +#define VREF_R 19597 +#define TMPSENS_R 19600 +#define PMBCTRL_R 19601 +#define DMA1_R 19648 +#define DMA2_R 19649 +#define DMAMUX_R 19650 +#define ADC12_R 19653 +#define USBO_R 19656 +#define SDMMC3_R 19664 +#define CAMITF_R 19712 +#define CRYP2_R 19716 +#define HASH2_R 19717 +#define RNG2_R 19718 +#define CRC2_R 19719 +#define HSEM_R 19723 +#define MBOX_R 19724 +#define GPIOA_R 19776 +#define GPIOB_R 19777 +#define GPIOC_R 19778 +#define GPIOD_R 19779 +#define GPIOE_R 19780 +#define GPIOF_R 19781 +#define GPIOG_R 19782 +#define GPIOH_R 19783 +#define GPIOI_R 19784 +#define GPIOJ_R 19785 +#define GPIOK_R 19786 + +/* SCMI reset domain identifiers */ +#define RST_SCMI_SPI6 0 +#define RST_SCMI_I2C4 1 +#define RST_SCMI_I2C6 2 +#define RST_SCMI_USART1 3 +#define RST_SCMI_STGEN 4 +#define RST_SCMI_GPIOZ 5 +#define RST_SCMI_CRYP1 6 +#define RST_SCMI_HASH1 7 +#define RST_SCMI_RNG1 8 +#define RST_SCMI_MDMA 9 +#define RST_SCMI_MCU 10 +#define RST_SCMI_MCU_HOLD_BOOT 11 + +#endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ diff --git a/optee/optee_os/core/include/dt-bindings/reset/stm32mp13-resets.h b/optee/optee_os/core/include/dt-bindings/reset/stm32mp13-resets.h new file mode 100644 index 0000000..14634cd --- /dev/null +++ b/optee/optee_os/core/include/dt-bindings/reset/stm32mp13-resets.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez + */ + +#ifndef _DT_BINDINGS_STM32MP13_RESET_H_ +#define _DT_BINDINGS_STM32MP13_RESET_H_ + +#define MPSYST_R 2208 +#define TIM2_R 13568 +#define TIM3_R 13569 +#define TIM4_R 13570 +#define TIM5_R 13571 +#define TIM6_R 13572 +#define TIM7_R 13573 +#define LPTIM1_R 13577 +#define SPI2_R 13579 +#define SPI3_R 13580 +#define USART3_R 13583 +#define UART4_R 13584 +#define UART5_R 13585 +#define UART7_R 13586 +#define UART8_R 13587 +#define I2C1_R 13589 +#define I2C2_R 13590 +#define SPDIF_R 13594 +#define TIM1_R 13632 +#define TIM8_R 13633 +#define SPI1_R 13640 +#define USART6_R 13645 +#define SAI1_R 13648 +#define SAI2_R 13649 +#define DFSDM_R 13652 +#define FDCAN_R 13656 +#define LPTIM2_R 13696 +#define LPTIM3_R 13697 +#define LPTIM4_R 13698 +#define LPTIM5_R 13699 +#define SYSCFG_R 13707 +#define VREF_R 13709 +#define DTS_R 13712 +#define PMBCTRL_R 13713 +#define LTDC_R 13760 +#define DCMIPP_R 13761 +#define DDRPERFM_R 13768 +#define USBPHY_R 13776 +#define STGEN_R 13844 +#define USART1_R 13888 +#define USART2_R 13889 +#define SPI4_R 13890 +#define SPI5_R 13891 +#define I2C3_R 13892 +#define I2C4_R 13893 +#define I2C5_R 13894 +#define TIM12_R 13895 +#define TIM13_R 13896 +#define TIM14_R 13897 +#define TIM15_R 13898 +#define TIM16_R 13899 +#define TIM17_R 13900 +#define DMA1_R 13952 +#define DMA2_R 13953 +#define DMAMUX1_R 13954 +#define DMA3_R 13955 +#define DMAMUX2_R 13956 +#define ADC1_R 13957 +#define ADC2_R 13958 +#define USBO_R 13960 +#define GPIOA_R 14080 +#define GPIOB_R 14081 +#define GPIOC_R 14082 +#define GPIOD_R 14083 +#define GPIOE_R 14084 +#define GPIOF_R 14085 +#define GPIOG_R 14086 +#define GPIOH_R 14087 +#define GPIOI_R 14088 +#define TSC_R 14095 +#define PKA_R 14146 +#define SAES_R 14147 +#define CRYP1_R 14148 +#define HASH1_R 14149 +#define RNG1_R 14150 +#define AXIMC_R 14160 +#define MDMA_R 14208 +#define MCE_R 14209 +#define ETH1MAC_R 14218 +#define FMC_R 14220 +#define QSPI_R 14222 +#define SDMMC1_R 14224 +#define SDMMC2_R 14225 +#define CRC1_R 14228 +#define USBH_R 14232 +#define ETH2MAC_R 14238 + +/* SCMI reset domain identifiers */ +#define RST_SCMI_LTDC 0 +#define RST_SCMI_MDMA 1 + +#endif /* _DT_BINDINGS_STM32MP13_RESET_H_ */ diff --git a/optee/optee_os/core/include/gen-asm-defines.h b/optee/optee_os/core/include/gen-asm-defines.h new file mode 100644 index 0000000..ebf330f --- /dev/null +++ b/optee/optee_os/core/include/gen-asm-defines.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited */ + +#ifndef GEN_ASM_DEFINES_H +#define GEN_ASM_DEFINES_H + +#define DEFINES void __defines(void); void __defines(void) + +#define DEFINE(def, val) \ + asm volatile("\n.ascii \"==>" #def " %c0 " #val "\"" : : "i" (val)); + +#endif /*GEN_ASM_DEFINES_H*/ diff --git a/optee/optee_os/core/include/gpio.h b/optee/optee_os/core/include/gpio.h new file mode 100644 index 0000000..2fc9a07 --- /dev/null +++ b/optee/optee_os/core/include/gpio.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __GPIO_H__ +#define __GPIO_H__ + +enum gpio_dir { + GPIO_DIR_OUT, + GPIO_DIR_IN +}; + +enum gpio_level { + GPIO_LEVEL_LOW, + GPIO_LEVEL_HIGH +}; + +enum gpio_interrupt { + GPIO_INTERRUPT_DISABLE, + GPIO_INTERRUPT_ENABLE +}; + +struct gpio_chip { + const struct gpio_ops *ops; +}; + +struct gpio_ops { + enum gpio_dir (*get_direction)(struct gpio_chip *chip, + unsigned int gpio_pin); + void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_dir direction); + enum gpio_level (*get_value)(struct gpio_chip *chip, + unsigned int gpio_pin); + void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_level value); + enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip, + unsigned int gpio_pin); + void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin, + enum gpio_interrupt ena_dis); +}; + +#endif /* __GPIO_H__ */ diff --git a/optee/optee_os/core/include/initcall.h b/optee/optee_os/core/include/initcall.h new file mode 100644 index 0000000..28aa5ea --- /dev/null +++ b/optee/optee_os/core/include/initcall.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef INITCALL_H +#define INITCALL_H + +#include +#include +#include + +struct initcall { + TEE_Result (*func)(void); +#if TRACE_LEVEL >= TRACE_DEBUG + int level; + const char *func_name; +#endif +}; + +#if TRACE_LEVEL >= TRACE_DEBUG +#define __define_initcall(type, lvl, fn) \ + SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(type ## call, lvl, \ + struct initcall) = \ + { .func = (fn), .level = (lvl), .func_name = #fn, } +#else +#define __define_initcall(type, lvl, fn) \ + SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(type ## call, lvl, \ + struct initcall) = \ + { .func = (fn), } +#endif + +#define preinitcall_begin \ + SCATTERED_ARRAY_BEGIN(preinitcall, struct initcall) +#define preinitcall_end SCATTERED_ARRAY_END(preinitcall, struct initcall) + +#define initcall_begin SCATTERED_ARRAY_BEGIN(initcall, struct initcall) +#define initcall_end SCATTERED_ARRAY_END(initcall, struct initcall) + +#define finalcall_begin SCATTERED_ARRAY_BEGIN(finalcall, struct initcall) +#define finalcall_end SCATTERED_ARRAY_END(finalcall, struct initcall) + +/* + * The preinit_*(), *_init() and boot_final() macros are used to register + * callback functions to be called at different stages during + * initialization. + * + * Functions registered with preinit_*() are always called before functions + * registered with *_init(). + * + * Functions registered with boot_final() are called before exiting to + * normal world the first time. + * + * Without virtualization this happens in the order of the defines below. + * + * However, with virtualization things are a bit different. boot_final() + * functions are called first before exiting to normal world the first + * time. Functions registered with boot_final() can only operate on the + * nexus. preinit_*() functions are called early before the first yielding + * call into the partition, in the newly created partition. *_init() + * functions are called at the first yielding call. + * + * +-------------------------------+-----------------------------------+ + * | Without virtualization | With virtualization | + * +-------------------------------+-----------------------------------+ + * | At the end of boot_init_primary_late() just before the print: | + * | "Primary CPU switching to normal world boot" | + * +-------------------------------+-----------------------------------+ + * | 1. call_preinitcalls() | In the nexus | + * | 2. call_initcalls() +-----------------------------------+ + * | 3. call_finalcalls() | 1. call_finalcalls() | + * +-------------------------------+-----------------------------------+ + * | "Primary CPU switching to normal world boot" is printed | + * +-------------------------------+-----------------------------------+ + * | A guest is created and | + * | virt_guest_created() is called. | + * | After the partition has been | + * | created and activated. | + * +-----------------------------------+ + * | 2. call_preinitcalls() | + * +-----------------------------------+ + * | When the partition is receiving | + * | the first yielding call | + * | virt_on_stdcall() is called. | + * +-----------------------------------+ + * | 3. call_initcalls() | + * +-----------------------------------+ + */ + +#define preinit_early(fn) __define_initcall(preinit, 1, fn) +#define preinit(fn) __define_initcall(preinit, 2, fn) +#define preinit_late(fn) __define_initcall(preinit, 3, fn) + +#define early_init(fn) __define_initcall(init, 1, fn) +#define early_init_late(fn) __define_initcall(init, 2, fn) +#define service_init(fn) __define_initcall(init, 3, fn) +#define service_init_late(fn) __define_initcall(init, 4, fn) +#define driver_init(fn) __define_initcall(init, 5, fn) +#define driver_init_late(fn) __define_initcall(init, 6, fn) +#define release_init_resource(fn) __define_initcall(init, 7, fn) + +#define boot_final(fn) __define_initcall(final, 1, fn) + +void call_preinitcalls(void); +void call_initcalls(void); +void call_finalcalls(void); + +#endif diff --git a/optee/optee_os/core/include/io.h b/optee/optee_os/core/include/io.h new file mode 100644 index 0000000..733f29f --- /dev/null +++ b/optee/optee_os/core/include/io.h @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2019, Linaro Limited + */ +#ifndef IO_H +#define IO_H + +#include +#include +#include +#include + +/* + * Make sure that compiler reads/writes given variable only once. This is needed + * in cases when we have normal shared memory, and this memory can be changed + * at any moment. Compiler does not knows about this, so it can optimize memory + * access in any way, including repeated accesses from the same address. + * These macro enforce compiler to access memory only once. + */ +#define READ_ONCE(p) __compiler_atomic_load(&(p)) +#define WRITE_ONCE(p, v) __compiler_atomic_store(&(p), (v)) + +static inline void io_write8(vaddr_t addr, uint8_t val) +{ + *(volatile uint8_t *)addr = val; +} + +static inline void io_write16(vaddr_t addr, uint16_t val) +{ + *(volatile uint16_t *)addr = val; +} + +static inline void io_write32(vaddr_t addr, uint32_t val) +{ + *(volatile uint32_t *)addr = val; +} + +static inline void io_write64(vaddr_t addr, uint64_t val) +{ + *(volatile uint64_t *)addr = val; +} + +static inline uint8_t io_read8(vaddr_t addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline uint16_t io_read16(vaddr_t addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline uint32_t io_read32(vaddr_t addr) +{ + return *(volatile uint32_t *)addr; +} + +static inline uint64_t io_read64(vaddr_t addr) +{ + return *(volatile uint64_t *)addr; +} + +static inline void io_mask8(vaddr_t addr, uint8_t val, uint8_t mask) +{ + io_write8(addr, (io_read8(addr) & ~mask) | (val & mask)); +} + +static inline void io_mask16(vaddr_t addr, uint16_t val, uint16_t mask) +{ + io_write16(addr, (io_read16(addr) & ~mask) | (val & mask)); +} + +static inline void io_mask32(vaddr_t addr, uint32_t val, uint32_t mask) +{ + io_write32(addr, (io_read32(addr) & ~mask) | (val & mask)); +} + +static inline uint64_t get_be64(const void *p) +{ + return TEE_U64_FROM_BIG_ENDIAN(*(const uint64_t *)p); +} + +static inline void put_be64(void *p, uint64_t val) +{ + *(uint64_t *)p = TEE_U64_TO_BIG_ENDIAN(val); +} + +static inline uint32_t get_be32(const void *p) +{ + return TEE_U32_FROM_BIG_ENDIAN(*(const uint32_t *)p); +} + +static inline void put_be32(void *p, uint32_t val) +{ + *(uint32_t *)p = TEE_U32_TO_BIG_ENDIAN(val); +} + +static inline uint16_t get_be16(const void *p) +{ + return TEE_U16_FROM_BIG_ENDIAN(*(const uint16_t *)p); +} + +static inline void put_be16(void *p, uint16_t val) +{ + *(uint16_t *)p = TEE_U16_TO_BIG_ENDIAN(val); +} + +static inline void put_le32(const void *p, uint32_t val) +{ + *(uint32_t *)p = val; +} + +static inline uint32_t get_le32(const void *p) +{ + return *(const uint32_t *)p; +} + +static inline void put_le64(const void *p, uint64_t val) +{ + *(uint64_t *)p = val; +} + +static inline uint64_t get_le64(const void *p) +{ + return *(const uint64_t *)p; +} + +/* Unaligned accesses */ + +struct __unaligned_u16_t { uint16_t x; } __packed; +struct __unaligned_u32_t { uint32_t x; } __packed; +struct __unaligned_u64_t { uint64_t x; } __packed; + +static inline uint64_t get_unaligned_be64(const void *p) +{ + const struct __unaligned_u64_t *tmp = p; + + return TEE_U64_FROM_BIG_ENDIAN(tmp->x); +} + +static inline void put_unaligned_be64(void *p, uint64_t val) +{ + struct __unaligned_u64_t *tmp = p; + + tmp->x = TEE_U64_TO_BIG_ENDIAN(val); +} + +static inline uint32_t get_unaligned_be32(const void *p) +{ + const struct __unaligned_u32_t *tmp = p; + + return TEE_U32_FROM_BIG_ENDIAN(tmp->x); +} + +static inline void put_unaligned_be32(void *p, uint32_t val) +{ + struct __unaligned_u32_t *tmp = p; + + tmp->x = TEE_U32_TO_BIG_ENDIAN(val); +} + +static inline uint16_t get_unaligned_be16(const void *p) +{ + const struct __unaligned_u16_t *tmp = p; + + return TEE_U16_FROM_BIG_ENDIAN(tmp->x); +} + +static inline void put_unaligned_be16(void *p, uint16_t val) +{ + struct __unaligned_u16_t *tmp = p; + + tmp->x = TEE_U16_TO_BIG_ENDIAN(val); +} + +static inline void put_unaligned_le64(void *p, uint64_t val) +{ + struct __unaligned_u64_t *tmp = p; + + tmp->x = val; +} + +static inline uint64_t get_unaligned_le64(const void *p) +{ + const struct __unaligned_u64_t *tmp = p; + + return tmp->x; +} + +static inline void put_unaligned_le32(void *p, uint32_t val) +{ + struct __unaligned_u32_t *tmp = p; + + tmp->x = val; +} + +static inline uint32_t get_unaligned_le32(const void *p) +{ + const struct __unaligned_u32_t *tmp = p; + + return tmp->x; +} + +static inline void put_unaligned_le16(void *p, uint16_t val) +{ + struct __unaligned_u16_t *tmp = p; + + tmp->x = val; +} + +static inline uint16_t get_unaligned_le16(const void *p) +{ + const struct __unaligned_u16_t *tmp = p; + + return tmp->x; +} + +/* + * Set and clear bits helpers. + * + * @addr is the address of the memory cell accessed + * @set_mask represents the bit mask of the bit(s) to set, aka set to 1 + * @clear_mask represents the bit mask of the bit(s) to clear, aka reset to 0 + * + * io_clrsetbits32() clears then sets the target bits in this order. If a bit + * position is defined by both @set_mask and @clear_mask, the bit will be set. + */ +static inline void io_setbits32(vaddr_t addr, uint32_t set_mask) +{ + io_write32(addr, io_read32(addr) | set_mask); +} + +static inline void io_clrbits32(vaddr_t addr, uint32_t clear_mask) +{ + io_write32(addr, io_read32(addr) & ~clear_mask); +} + +static inline void io_clrsetbits32(vaddr_t addr, uint32_t clear_mask, + uint32_t set_mask) +{ + io_write32(addr, (io_read32(addr) & ~clear_mask) | set_mask); +} + +static inline void io_setbits16(vaddr_t addr, uint16_t set_mask) +{ + io_write16(addr, io_read16(addr) | set_mask); +} + +static inline void io_clrbits16(vaddr_t addr, uint16_t clear_mask) +{ + io_write16(addr, io_read16(addr) & ~clear_mask); +} + +static inline void io_clrsetbits16(vaddr_t addr, uint16_t clear_mask, + uint16_t set_mask) +{ + io_write16(addr, (io_read16(addr) & ~clear_mask) | set_mask); +} + +static inline void io_setbits8(vaddr_t addr, uint8_t set_mask) +{ + io_write8(addr, io_read8(addr) | set_mask); +} + +static inline void io_clrbits8(vaddr_t addr, uint8_t clear_mask) +{ + io_write8(addr, io_read8(addr) & ~clear_mask); +} + +static inline void io_clrsetbits8(vaddr_t addr, uint8_t clear_mask, + uint8_t set_mask) +{ + io_write8(addr, (io_read8(addr) & ~clear_mask) | set_mask); +} + +#endif /*IO_H*/ diff --git a/optee/optee_os/core/include/keep.h b/optee/optee_os/core/include/keep.h new file mode 100644 index 0000000..0dbe910 --- /dev/null +++ b/optee/optee_os/core/include/keep.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef KEEP_H +#define KEEP_H + +#ifdef __ASSEMBLER__ + + .macro DECLARE_KEEP_PAGER sym + .pushsection __keep_meta_vars_pager, "a" + .global ____keep_pager_\sym + ____keep_pager_\sym: + .long \sym + .popsection + .endm + + .macro DECLARE_KEEP_INIT sym + .pushsection __keep_meta_vars_init, "a" + .global ____keep_init_\sym + ____keep_init_\sym: + .long \sym + .popsection + .endm + +#else + +#include + +#define __DECLARE_KEEP_PAGER2(sym, file_id) \ + extern const unsigned long ____keep_pager_##sym; \ + const unsigned long ____keep_pager_##sym##_##file_id \ + __section("__keep_meta_vars_pager") = (unsigned long)&(sym) + +#define __DECLARE_KEEP_PAGER1(sym, file_id) __DECLARE_KEEP_PAGER2(sym, file_id) +#define DECLARE_KEEP_PAGER(sym) __DECLARE_KEEP_PAGER1(sym, __FILE_ID__) + +#define __DECLARE_KEEP_INIT2(sym, file_id) \ + extern const unsigned long ____keep_init_##sym##file_id; \ + const unsigned long ____keep_init_##sym##_##file_id \ + __section("__keep_meta_vars_init") = (unsigned long)&(sym) + +#define __DECLARE_KEEP_INIT1(sym, file_id) __DECLARE_KEEP_INIT2(sym, file_id) +#define DECLARE_KEEP_INIT(sym) __DECLARE_KEEP_INIT1(sym, __FILE_ID__) + +#endif /* __ASSEMBLER__ */ + +#endif /*KEEP_H*/ diff --git a/optee/optee_os/core/include/kernel/abort.h b/optee/optee_os/core/include/kernel/abort.h new file mode 100644 index 0000000..ed0e5c0 --- /dev/null +++ b/optee/optee_os/core/include/kernel/abort.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2021, Linaro Limited + */ + +#ifndef KERNEL_ABORT_H +#define KERNEL_ABORT_H + +#define ABORT_TYPE_UNDEF 0 +#define ABORT_TYPE_PREFETCH 1 +#define ABORT_TYPE_DATA 2 +/* Dump stack on user mode panic (not an abort) */ +#define ABORT_TYPE_USER_MODE_PANIC 3 + +#ifndef __ASSEMBLER__ + +#include +#include + +struct abort_info { + uint32_t abort_type; + uint32_t fault_descr; /* only valid for data of prefetch abort */ + vaddr_t va; + uint32_t pc; + struct thread_abort_regs *regs; +}; + +/* Print abort info to the console */ +void abort_print(struct abort_info *ai); +/* Print abort info + stack dump to the console */ +void abort_print_error(struct abort_info *ai); + +void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs); + +bool abort_is_user_exception(struct abort_info *ai); + +bool abort_is_write_fault(struct abort_info *ai); + +/* Called from a normal thread */ +void abort_print_current_ts(void); + +#endif /*__ASSEMBLER__*/ +#endif /*KERNEL_ABORT_H*/ + diff --git a/optee/optee_os/core/include/kernel/asan.h b/optee/optee_os/core/include/kernel/asan.h new file mode 100644 index 0000000..567a168 --- /dev/null +++ b/optee/optee_os/core/include/kernel/asan.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ +#ifndef __KERNEL_ASAN_H +#define __KERNEL_ASAN_H + +#include + +#define ASAN_DATA_RED_ZONE -1 +#define ASAN_HEAP_RED_ZONE -2 + +#define ASAN_BLOCK_SIZE U(8) +#define ASAN_BLOCK_SHIFT U(3) +#define ASAN_BLOCK_MASK (ASAN_BLOCK_SIZE - 1) + +#ifndef __ASSEMBLER__ +#include +#include +#include + +void asan_set_shadowed(const void *va_begin, const void *va_end); +void asan_start(void); + +#ifdef CFG_CORE_SANITIZE_KADDRESS +void asan_tag_no_access(const void *begin, const void *end); +void asan_tag_access(const void *begin, const void *end); +void asan_tag_heap_free(const void *begin, const void *end); +void *asan_memset_unchecked(void *s, int c, size_t n); +void *asan_memcpy_unchecked(void *__restrict s1, const void *__restrict s2, + size_t n); +#else +static inline void asan_tag_no_access(const void *begin __unused, + const void *end __unused) +{ +} +static inline void asan_tag_access(const void *begin __unused, + const void *end __unused) +{ +} +static inline void asan_tag_heap_free(const void *begin __unused, + const void *end __unused) +{ +} + +static inline void *asan_memset_unchecked(void *s, int c, size_t n) +{ + return memset(s, c, n); +} + +static inline void *asan_memcpy_unchecked(void *__restrict s1, + const void *__restrict s2, size_t n) +{ + return memcpy(s1, s2, n); +} + +#endif + +#endif /*__ASSEMBLER__*/ +#endif /*__KERNEL_ASAN_H*/ diff --git a/optee/optee_os/core/include/kernel/boot.h b/optee/optee_os/core/include/kernel/boot.h new file mode 100644 index 0000000..0311d69 --- /dev/null +++ b/optee/optee_os/core/include/kernel/boot.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2020, Linaro Limited + * Copyright (c) 2021-2023, Arm Limited + */ +#ifndef __KERNEL_BOOT_H +#define __KERNEL_BOOT_H + +#include +#include + +/* + * struct boot_embdata - Embedded boot data + * @total_len: Total length of the embedded boot data + * @num_blobs: Number of blobs in the embedded boot data, always 2 even if + * one blob is empty + * @hashes_offset: Offset of hashes from start of this struct + * @hashes_len: Length of hashes + * @reloc_offset: Offset of reloc from start of this struct + * @reloc_len: Length of reloc + * + * This struct is initialized by scripts/gen_tee_bin.py and must be kept + * in sync with that script. The struct and the following data is loaded + * at different addresses at boot depending on CFG_WITH_PAGER. + * + * If configured with CFG_WITH_PAGER=y the struct with data is following + * init part, this is together with the init part moved by the primary CPU + * so it ends up at __init_end. Whatever need to be saved for later need to + * be copied to a safe location in init_runtime(). + * + * If configured with CFG_WITH_PAGER=n following the struct with data is + * __data_end, this is moved by the primary CPU so it ends up at __end. + */ +struct boot_embdata { + uint32_t total_len; + uint32_t num_blobs; + uint32_t hashes_offset; + uint32_t hashes_len; + uint32_t reloc_offset; + uint32_t reloc_len; +}; + +extern uint8_t embedded_secure_dtb[]; +extern const struct core_mmu_config boot_mmu_config; + +/* @nsec_entry is unused if using CFG_WITH_ARM_TRUSTED_FW */ +void boot_init_primary_early(unsigned long pageable_part, + unsigned long nsec_entry); +void boot_init_primary_late(unsigned long fdt, unsigned long tos_fw_config); +void boot_init_memtag(void); +void boot_save_boot_info(void *boot_info); +void boot_set_fixed_secmem_range(paddr_t base); + +void __panic_at_smc_return(void) __noreturn; + +#if defined(CFG_WITH_ARM_TRUSTED_FW) +unsigned long cpu_on_handler(unsigned long a0, unsigned long a1); +unsigned long boot_cpu_on_handler(unsigned long a0, unsigned long a1); +#else +void boot_init_secondary(unsigned long nsec_entry); +#endif + +void main_init_gic(void); +void main_secondary_init_gic(void); + +void init_sec_mon(unsigned long nsec_entry); +void init_tee_runtime(void); + +/* weak routines eventually overridden by platform */ +void plat_cpu_reset_early(void); +void plat_primary_init_early(void); +unsigned long plat_get_aslr_seed(void); +unsigned long plat_get_freq(void); +#if defined(_CFG_CORE_STACK_PROTECTOR) +uintptr_t plat_get_random_stack_canary(void); +#endif +void arm_cl2_config(vaddr_t pl310); +void arm_cl2_enable(vaddr_t pl310); + +#if defined(CFG_BOOT_SECONDARY_REQUEST) +void boot_set_core_ns_entry(size_t core_idx, uintptr_t entry, + uintptr_t context_id); + +int boot_core_release(size_t core_idx, paddr_t entry); +struct ns_entry_context *boot_core_hpen(void); +#endif + +/* Returns embedded DTB if present, then external DTB if found, then NULL */ +void *get_dt(void); + +/* + * get_secure_dt() - returns secure DTB for drivers + * + * Returns device tree that is considered secure for drivers to use. + * + * 1. Returns embedded DTB if available, + * 2. Secure external DTB if available, + * 3. If neither then NULL + */ +void *get_secure_dt(void); + +/* Returns embedded DTB location if present, otherwise NULL */ +void *get_embedded_dt(void); + +/* Returns external DTB if present, otherwise NULL */ +void *get_external_dt(void); + +/* Returns TOS_FW_CONFIG DTB if present, otherwise NULL */ +void *get_tos_fw_config_dt(void); + +/* + * get_aslr_seed() - return a random seed for core ASLR + * @fdt: Pointer to a device tree if CFG_DT_ADDR=y + * + * This function has a __weak default implementation. + */ +unsigned long get_aslr_seed(void *fdt); + +/* Returns true if passed DTB is same as Embedded DTB, otherwise false */ +static inline bool is_embedded_dt(void *fdt) +{ + return fdt && fdt == get_embedded_dt(); +} + +#endif /* __KERNEL_BOOT_H */ diff --git a/optee/optee_os/core/include/kernel/cache_helpers.h b/optee/optee_os/core/include/kernel/cache_helpers.h new file mode 100644 index 0000000..247b0f2 --- /dev/null +++ b/optee/optee_os/core/include/kernel/cache_helpers.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __KERNEL_CACHE_HELPERS_H +#define __KERNEL_CACHE_HELPERS_H + +#ifndef __ASSEMBLER__ +#include +#include +#endif + +/* Data Cache set/way op type defines */ +#define DCACHE_OP_INV 0x0 +#define DCACHE_OP_CLEAN_INV 0x1 +#define DCACHE_OP_CLEAN 0x2 + +#ifndef __ASSEMBLER__ +void dcache_cleaninv_range(void *addr, size_t size); +void dcache_clean_range(void *addr, size_t size); +void dcache_inv_range(void *addr, size_t size); +void dcache_clean_range_pou(void *addr, size_t size); + +void icache_inv_all(void); +void icache_inv_range(void *addr, size_t size); +void icache_inv_user_range(void *addr, size_t size); + +void dcache_op_louis(unsigned long op_type); +void dcache_op_all(unsigned long op_type); + +void dcache_op_level1(unsigned long op_type); +void dcache_op_level2(unsigned long op_type); +void dcache_op_level3(unsigned long op_type); + +/* + * Get system maximum cache line size. + */ +static inline unsigned int cache_get_max_line_size(void) +{ + return 1 << CFG_MAX_CACHE_LINE_SHIFT; +} +#endif /*!__ASSEMBLER__*/ + +#endif /*__KERNEL_CACHE_HELPERS_H*/ diff --git a/optee/optee_os/core/include/kernel/chip_services.h b/optee/optee_os/core/include/kernel/chip_services.h new file mode 100644 index 0000000..a22237c --- /dev/null +++ b/optee/optee_os/core/include/kernel/chip_services.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef CHIP_SERVICES_H +#define CHIP_SERVICES_H + +/* Die ID */ +#define FVR_DIE_ID_NUM_REGS 3 + +#endif diff --git a/optee/optee_os/core/include/kernel/delay.h b/optee/optee_os/core/include/kernel/delay.h new file mode 100644 index 0000000..6cb7268 --- /dev/null +++ b/optee/optee_os/core/include/kernel/delay.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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_DELAY_H +#define __KERNEL_DELAY_H + +#include +#include +#include + +void udelay(uint32_t us); +void mdelay(uint32_t ms); + +#endif diff --git a/optee/optee_os/core/include/kernel/dt.h b/optee/optee_os/core/include/kernel/dt.h new file mode 100644 index 0000000..e6ca702 --- /dev/null +++ b/optee/optee_os/core/include/kernel/dt.h @@ -0,0 +1,321 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2021, Linaro Limited + */ + +#ifndef KERNEL_DT_H +#define KERNEL_DT_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Bitfield to reflect status and secure-status values ("okay", "disabled" + * or not present) + */ +#define DT_STATUS_DISABLED U(0) +#define DT_STATUS_OK_NSEC BIT(0) +#define DT_STATUS_OK_SEC BIT(1) + +#define DT_INFO_INVALID_REG ((paddr_t)-1) +#define DT_INFO_INVALID_REG_SIZE ((size_t)-1) +#define DT_INFO_INVALID_CLOCK -1 +#define DT_INFO_INVALID_RESET -1 +#define DT_INFO_INVALID_INTERRUPT -1 + +/* + * @status: Bit mask for DT_STATUS_* + * @reg: Device register physical base address or DT_INFO_INVALID_REG + * @reg_size: Device register size or DT_INFO_INVALID_REG_SIZE + * @clock: Device identifier (positive value) or DT_INFO_INVALID_CLOCK + * @reset: Device reset identifier (positive value) or DT_INFO_INVALID_CLOCK + * @interrupt: Device interrupt identifier (positive value) or + * DT_INFO_INVALID_INTERRUPT + * @type: IRQ_TYPE_* value parsed from interrupts properties or IRQ_TYPE_NONE if + * not present + * @prio: interrupt priority parsed from interrupts properties or 0 if not + * present + */ +struct dt_node_info { + unsigned int status; + paddr_t reg; + size_t reg_size; + int clock; + int reset; + int interrupt; + uint32_t type; + uint32_t prio; +}; + +/* + * DT-aware drivers + */ + +struct dt_device_match { + const char *compatible; + const void *compat_data; +}; + +/* + * DT_MAP_AUTO: Uses status properties from device tree to determine mapping. + * DT_MAP_SECURE: Force mapping for device to be secure. + * DT_MAP_NON_SECURE: Force mapping for device to be non-secure. + */ +enum dt_map_dev_directive { + DT_MAP_AUTO, + DT_MAP_SECURE, + DT_MAP_NON_SECURE +}; + +/* + * dt_getprop_as_number() - get a DT property a unsigned number + * @fdt: DT base address + * @nodeoffset: node offset + * @name: property string name + * @num: output number read + * Return 0 on success and a negative FDT error value on error + * + * The size of the property determines if it is read as an unsigned 32-bit + * or 64-bit integer. + */ +int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, + uint64_t *num); + +#ifdef CFG_DT +/* + * Find a driver that is suitable for the given DT node, that is, with + * a matching "compatible" property. + * + * @fdt: pointer to the device tree + * @offs: node offset + */ +const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); + +/* + * Map a device into secure or non-secure memory and return the base VA and + * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or + * MEM_AREA_IO_NSEC, depending on the device status. + * If the mapping already exists, the function simply returns the @vbase and + * @size information. + * + * @offs is the offset of the node that describes the device in @fdt. + * @base receives the base virtual address corresponding to the base physical + * address of the "reg" property + * @size receives the size of the mapping + * @mapping what kind of mapping is done for memory. + * + * Returns 0 on success or -1 in case of error. + */ +int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, + enum dt_map_dev_directive mapping); + +/* + * Check whether the node at @offs contains the property with propname or not. + * + * @offs is the offset of the node that describes the device in @fdt. + * @propname is the property that need to check + * + * Returns true on success or false if no propname. + */ +bool dt_have_prop(const void *fdt, int offs, const char *propname); + +/* + * Modify or add "status" property to "disabled" + * + * @fdt reference to the Device Tree + * @node is the node offset to modify + * + * Returns 0 on success or -1 on failure + */ +int dt_disable_status(void *fdt, int node); + +/* + * Force secure-status = "okay" and status="disabled" for the target node. + * + * @fdt reference to the Device Tree + * @node is the node offset to modify + * + * Returns 0 on success or -1 on failure + */ +int dt_enable_secure_status(void *fdt, int node); + +/* + * FDT manipulation functions, not provided by + */ + +/* + * Return the base address for the "reg" property of the specified node or + * (paddr_t)-1 in case of error + */ +paddr_t fdt_reg_base_address(const void *fdt, int offs); + +/* + * Return the reg size for the reg property of the specified node or -1 in case + * of error + */ +size_t fdt_reg_size(const void *fdt, int offs); + +/* + * Read the status and secure-status properties into a bitfield. + * Return -1 on failure, DT_STATUS_DISABLED if the node is disabled, + * otherwise return a combination of DT_STATUS_OK_NSEC and DT_STATUS_OK_SEC. + */ +int fdt_get_status(const void *fdt, int offs); + +/* + * fdt_fill_device_info - Get generic device info from a node + * + * This function fills the generic information from a given node. + * Currently supports a single base register, a single clock, + * a single reset ID line and a single interrupt ID. + * Default DT_INFO_* macros are used when the relate property is not found. + */ +void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, + int node); +/* + * Read cells from a given property of the given node. Any number of 32-bit + * cells of the property can be read. Returns 0 on success, or a negative + * FDT error value otherwise. + */ +int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, + uint32_t *array, size_t count); + +/* + * Read one cell from a given multi-value property of the given node. + * Returns 0 on success, or a negative FDT error value otherwise. + */ +int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, + int index, uint32_t *value); + +/* + * Read one cell from a given property of the given node. + * Returns 0 on success, or a negative FDT error value otherwise. + */ +int fdt_read_uint32(const void *fdt, int node, const char *prop_name, + uint32_t *value); + +/* + * Read one cell from a property of a cell or default to a given value + * Returns the 32bit cell value or @dflt_value on failure. + */ +uint32_t fdt_read_uint32_default(const void *fdt, int node, + const char *prop_name, uint32_t dflt_value); + +/* + * This function fills reg node info (base & size) with an index. + * + * Returns 0 on success and a negative FDT error code on failure. + */ +int fdt_get_reg_props_by_index(const void *fdt, int node, int index, + paddr_t *base, size_t *size); + +/* + * This function fills reg node info (base & size) with an index found by + * checking the reg-names node. + * + * Returns 0 on success and a negative FDT error code on failure. + */ +int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, + paddr_t *base, size_t *size); + +#else /* !CFG_DT */ + +static inline const struct dt_driver *dt_find_compatible_driver( + const void *fdt __unused, + int offs __unused) +{ + return NULL; +} + +static inline int dt_map_dev(const void *fdt __unused, int offs __unused, + vaddr_t *vbase __unused, size_t *size __unused, + enum dt_map_dev_directive mapping __unused) +{ + return -1; +} + +static inline paddr_t fdt_reg_base_address(const void *fdt __unused, + int offs __unused) +{ + return (paddr_t)-1; +} + +static inline size_t fdt_reg_size(const void *fdt __unused, + int offs __unused) +{ + return (size_t)-1; +} + +static inline int fdt_get_status(const void *fdt __unused, int offs __unused) +{ + return -1; +} + +__noreturn +static inline void fdt_fill_device_info(const void *fdt __unused, + struct dt_node_info *info __unused, + int node __unused) +{ + panic(); +} + +static inline int fdt_read_uint32_array(const void *fdt __unused, + int node __unused, + const char *prop_name __unused, + uint32_t *array __unused, + size_t count __unused) +{ + return -1; +} + +static inline int fdt_read_uint32(const void *fdt __unused, + int node __unused, + const char *prop_name __unused, + uint32_t *value __unused) +{ + return -1; +} + +static inline uint32_t fdt_read_uint32_default(const void *fdt __unused, + int node __unused, + const char *prop_name __unused, + uint32_t dflt_value __unused) +{ + return dflt_value; +} + +static inline int fdt_read_uint32_index(const void *fdt __unused, + int node __unused, + const char *prop_name __unused, + int index __unused, + uint32_t *value __unused) +{ + return -1; +} + +static inline int fdt_get_reg_props_by_index(const void *fdt __unused, + int node __unused, + int index __unused, + paddr_t *base __unused, + size_t *size __unused) +{ + return -1; +} + +static inline int fdt_get_reg_props_by_name(const void *fdt __unused, + int node __unused, + const char *name __unused, + paddr_t *base __unused, + size_t *size __unused) +{ + return -1; +} + +#endif /* !CFG_DT */ +#endif /* KERNEL_DT_H */ diff --git a/optee/optee_os/core/include/kernel/dt_driver.h b/optee/optee_os/core/include/kernel/dt_driver.h new file mode 100644 index 0000000..8e59ed0 --- /dev/null +++ b/optee/optee_os/core/include/kernel/dt_driver.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + * Copyright (c) 2021, Bootlin + * Copyright (c) 2021, STMicroelectronics + */ + +#ifndef __DT_DRIVER_H +#define __DT_DRIVER_H + +#include +#include +#include +#include + +/* + * Type indentifiers for registered device drivers consumer can query + * + * DT_DRIVER_NOTYPE Generic type for when no generic FDT parsing is supported + * DT_DRIVER_UART UART driver currently designed for console means + * DT_DRIVER_CLK Clock controller using generic clock DT bindings + * DT_DRIVER_RSTCTRL Reset controller using generic reset DT bindings + * DT_DRIVER_I2C I2C bus controlle using generic I2C bus DT bindings + */ +enum dt_driver_type { + DT_DRIVER_NOTYPE, + DT_DRIVER_UART, + DT_DRIVER_CLK, + DT_DRIVER_RSTCTRL, + DT_DRIVER_I2C, +}; + +/* + * dt_driver_probe_func - Callback probe function for a driver. + * + * @fdt: FDT base address + * @nodeoffset: Offset of the node in the FDT + * @compat_data: Data registered for the compatible that probed the device + * + * Return TEE_SUCCESS on successful probe, + * TEE_ERROR_DEFER_DRIVER_INIT if probe must be deferred + * TEE_ERROR_ITEM_NOT_FOUND when no driver matched node's compatible string + * Any other TEE_ERROR_* compliant code. + */ +typedef TEE_Result (*dt_driver_probe_func)(const void *fdt, int nodeoffset, + const void *compat_data); + +/* + * Driver instance registered to be probed on compatible node found in the DT. + * + * @name: Driver name + * @type: Drive type + * @match_table: Compatible matching identifiers, null terminated + * @driver: Driver private reference or NULL + * @probe: Probe callback (see dt_driver_probe_func) or NULL + */ +struct dt_driver { + const char *name; + enum dt_driver_type type; + const struct dt_device_match *match_table; /* null-terminated */ + const void *driver; + TEE_Result (*probe)(const void *fdt, int node, const void *compat_data); +}; + +#define DEFINE_DT_DRIVER(name) \ + SCATTERED_ARRAY_DEFINE_PG_ITEM(dt_drivers, struct dt_driver) + +#define for_each_dt_driver(drv) \ + for (drv = SCATTERED_ARRAY_BEGIN(dt_drivers, struct dt_driver); \ + drv < SCATTERED_ARRAY_END(dt_drivers, struct dt_driver); \ + drv++) + +/* Opaque reference to DT driver device provider instance */ +struct dt_driver_provider; + +/** + * struct dt_driver_phandle_args - Devicetree phandle arguments + * @fdt: Device-tree to work on + * @phandle_node: Node pointed by the specifier phandle + * @args_count: Count of cells for the device + * @args: Device consumer specifiers + */ +struct dt_driver_phandle_args { + const void *fdt; + int phandle_node; + int args_count; + uint32_t args[]; +}; + +/* + * get_of_device_func - Callback function for returning a driver private + * instance based on a FDT phandle with possible arguments and the + * registered dt_driver private data reference. + * + * @parg: phandle argument(s) referencing the device in the FDT. + * @data: driver private data registered in struct dt_driver. + * @res: Output result code of the operation: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized + * Any TEE_Result compliant code in case of error. + * + * Return a device opaque reference, e.g. a struct clk pointer for a clock + * driver, or NULL if not found in which case @res provides the error code. + */ +typedef void *(*get_of_device_func)(struct dt_driver_phandle_args *parg, + void *data, TEE_Result *res); + +/** + * dt_driver_register_provider - Register a driver provider + * + * @fdt: Device tree to work on + * @nodeoffset: Node offset in the FDT + * @get_of_device: Function to match the devicetree with a device instance + * @data: Data which will be passed to the @get_of_device callback + * @type: Driver type + * + * @get_of_device returns a void *. Driver provider is expected to + * include a shim helper to cast to device reference into provider driver + * target structure reference (e.g (struct clk *) for clock devices). + */ +TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset, + get_of_device_func get_of_device, + void *data, enum dt_driver_type type); + +/* + * dt_driver_device_from_node_idx_prop - Return a device instance based on a + * property name and FDT information + * + * @prop_name: DT property name, e.g. "clocks" for clock resources + * @fdt: FDT base address + * @nodeoffset: node offset in the FDT + * @prop_idx: index of the phandle data in the property + * @type: Driver type + * @res: Output result code of the operation: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized + * TEE_ERROR_ITEM_NOT_FOUND if prop_name does not match a property's name + * Any TEE_Result compliant code in case of error. + * + * Return a device opaque reference, e.g. a struct clk pointer for a clock + * driver, or NULL if not found in which case @res provides the error code. + */ +void *dt_driver_device_from_node_idx_prop(const char *prop_name, + const void *fdt, int nodeoffset, + unsigned int prop_idx, + enum dt_driver_type type, + TEE_Result *res); + +/* + * dt_driver_device_from_parent - Return a device instance based on the parent. + * This is mainly used for the devices that are children of a controller + * such as I2C, SPI and so on. + * + * @fdt: FDT base address + * @nodeoffset: node offset in the FDT + * @type: Driver type + * @res: Output result code of the operation: + * TEE_SUCCESS in case of success + * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized + * Any TEE_Result compliant code in case of error. + * + * Return a device opaque reference, e.g. a struct i2c_dev pointer for a I2C bus + * driver, or NULL if not found in which case @res provides the error code. + */ +void *dt_driver_device_from_parent(const void *fdt, int nodeoffset, + enum dt_driver_type type, TEE_Result *res); + +/* + * dt_driver_get_crypto() - Request crypto support for driver initialization + * + * Return TEE_SUCCESS if cryptography services are initialized, otherwise return + * TEE_ERROR_DEFER_DRIVER_INIT. + */ +TEE_Result dt_driver_get_crypto(void); + +#ifdef CFG_DT +/* Inform DT driver probe sequence that core crypto support is initialized */ +void dt_driver_crypt_init_complete(void); +#else +static inline void dt_driver_crypt_init_complete(void) {} +#endif + +/* + * Return driver provider reference from its node offset value in the FDT + */ +struct dt_driver_provider * +dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type); + +/* + * Return driver provider reference from its phandle value in the FDT + */ +struct dt_driver_provider * +dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type); + +/* + * Return number cells used for phandle arguments by a driver provider + */ +unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv); + +/* + * dt_driver_probe_device_by_node - Probe matching driver to create a device + * from a FDT node + * + * @fdt: FDT base address + * @nodeoffset: Node byte offset from FDT base + * @type: Target driver to match or DT_DRIVER_ANY + * + * Read the dt_driver database. Compatible list is looked up in the order + * of the FDT "compatible" property list. @type can be used to probe only + * specific drivers. + * + */ +TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset, + enum dt_driver_type type); + +/* + * Get cells count of a device node given its dt_driver type + * + * @fdt: FDT base address + * @nodeoffset: Node offset on the FDT for the device + * @type: One of the supported DT_DRIVER_* value. + * + * Return a positive cell count value (>= 0) or a negative FDT_ error code + */ +int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset, + enum dt_driver_type type); + +/* + * Called by bus like nodes to propose a node for dt_driver probing + * + * @fdt: FDT base address + * @nodeoffset: Node offset on the FDT for the device + */ +TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int nodeoffset); + +#ifdef CFG_DT_DRIVER_EMBEDDED_TEST +/* + * Return TEE_ERROR_NOT_IMPLEMENTED if test are not implemented + * otherwise return TEE_ERROR_GENERIC if some test has failed + * otherwise return TEE_SUCCESS (tests succeed or skipped) + */ +TEE_Result dt_driver_test_status(void); +#else +static inline TEE_Result dt_driver_test_status(void) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif + +#endif /* __DT_DRIVER_H */ diff --git a/optee/optee_os/core/include/kernel/early_ta.h b/optee/optee_os/core/include/kernel/early_ta.h new file mode 100644 index 0000000..b7f9f38 --- /dev/null +++ b/optee/optee_os/core/include/kernel/early_ta.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, 2020, Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ +#ifndef KERNEL_EARLY_TA_H +#define KERNEL_EARLY_TA_H + +#include +#include +#include +#include + +#define for_each_early_ta(_ta) \ + SCATTERED_ARRAY_FOREACH(_ta, early_tas, struct embedded_ts) + +#endif /* KERNEL_EARLY_TA_H */ + diff --git a/optee/optee_os/core/include/kernel/embedded_ts.h b/optee/optee_os/core/include/kernel/embedded_ts.h new file mode 100644 index 0000000..a3d35d1 --- /dev/null +++ b/optee/optee_os/core/include/kernel/embedded_ts.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ +#ifndef KERNEL_EMBEDDED_TS_H +#define KERNEL_EMBEDDED_TS_H + +#include +#include +#include +#include +#include + +struct embedded_ts { + uint32_t flags; + TEE_UUID uuid; + uint32_t size; + uint32_t uncompressed_size; /* 0: not compressed */ + const uint8_t *ts; /* @size bytes */ +}; + +struct ts_store_handle; + +TEE_Result emb_ts_read(struct ts_store_handle *h, void *data, size_t len); +void emb_ts_close(struct ts_store_handle *h); + +TEE_Result emb_ts_open(const TEE_UUID *uuid, + struct ts_store_handle **h, + const struct embedded_ts* (*find_ts) + (const TEE_UUID *uuid)); +TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size); +TEE_Result emb_ts_get_tag(const struct ts_store_handle *h, + uint8_t *tag, unsigned int *tag_len); +#endif /* KERNEL_EMBEDDED_TS_H */ + diff --git a/optee/optee_os/core/include/kernel/handle.h b/optee/optee_os/core/include/kernel/handle.h new file mode 100644 index 0000000..eb4375d --- /dev/null +++ b/optee/optee_os/core/include/kernel/handle.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ +#ifndef KERNEL_HANDLE_H +#define KERNEL_HANDLE_H + +#include +#include + +struct handle_db { + void **ptrs; + size_t max_ptrs; +}; + +#define HANDLE_DB_INITIALIZER { NULL, 0 } + +/* + * Frees all internal data structures of the database, but does not free + * the db pointer. The database is safe to reuse after it's destroyed, it + * will just be empty again. If ptr_destructor is non-null it will be + * called for each registered pointer before the database is cleared. + */ +void handle_db_destroy(struct handle_db *db, void (*ptr_destructor)(void *ptr)); + +/* Checks if the associated pointers of all handles in the database are NULL. */ +bool handle_db_is_empty(struct handle_db *db); + +/* + * Allocates a new handle and assigns the supplied pointer to it, + * ptr must not be NULL. + * The function returns + * >= 0 on success and + * -1 on failure + */ +int handle_get(struct handle_db *db, void *ptr); + +/* + * Deallocates a handle. Returns the assiciated pointer of the handle + * if the handle was valid or NULL if it's invalid. + */ +void *handle_put(struct handle_db *db, int handle); + +/* + * Returns the assiciated pointer of the handle if the handle is a valid + * handle. + * Returns NULL on failure. + */ +void *handle_lookup(struct handle_db *db, int handle); + +#endif /*KERNEL_HANDLE_H*/ diff --git a/optee/optee_os/core/include/kernel/huk_subkey.h b/optee/optee_os/core/include/kernel/huk_subkey.h new file mode 100644 index 0000000..59bcf27 --- /dev/null +++ b/optee/optee_os/core/include/kernel/huk_subkey.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef __KERNEL_HUK_SUBKEY_H +#define __KERNEL_HUK_SUBKEY_H + +#include +#include +#include + +/* + * enum huk_subkey_usage - subkey usage identifier + * @HUK_SUBKEY_RPMB: RPMB key + * @HUK_SUBKEY_SSK: Secure Storage key + * @HUK_SUBKEY_DIE_ID: Representing the die ID + * @HUK_SUBKEY_UNIQUE_TA: TA unique key + * @HUK_SUBKEY_TA_ENC: TA encryption key + * @HUK_SUBKEY_SE050: SCP03 set of encryption keys + * + * Add more identifiers as needed, be careful to not change the already + * assigned numbers as that will affect the derived subkey. + */ +enum huk_subkey_usage { + /* + * All IDs are explicitly assigned to make it easier to keep then + * constant. + */ + HUK_SUBKEY_RPMB = 0, + HUK_SUBKEY_SSK = 1, + HUK_SUBKEY_DIE_ID = 2, + HUK_SUBKEY_UNIQUE_TA = 3, + HUK_SUBKEY_TA_ENC = 4, + HUK_SUBKEY_SE050 = 5, +}; + +#define HUK_SUBKEY_MAX_LEN TEE_SHA256_HASH_SIZE + +/* + * huk_subkey_derive() - Derive a subkey from the hardware unique key + * @usage: Intended usage of the subkey + * @const_data: Constant data to generate different subkeys with + * the same usage + * @const_data_len: Length of constant data + * @subkey: Generated subkey + * @subkey_len: Required size of the subkey, sizes larger than + * HUK_SUBKEY_MAX_LEN are not accepted. + * + * Returns a subkey derived from the hardware unique key. Given the same + * input the same subkey is returned each time. + * + * Return TEE_SUCCES on success or an error code on failure. + */ +TEE_Result huk_subkey_derive(enum huk_subkey_usage usage, + const void *const_data, size_t const_data_len, + uint8_t *subkey, size_t subkey_len); + + +#endif /*__KERNEL_HUK_SUBKEY_H*/ diff --git a/optee/optee_os/core/include/kernel/interrupt.h b/optee/optee_os/core/include/kernel/interrupt.h new file mode 100644 index 0000000..9870049 --- /dev/null +++ b/optee/optee_os/core/include/kernel/interrupt.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2019, Linaro Limited + */ +#ifndef __KERNEL_INTERRUPT_H +#define __KERNEL_INTERRUPT_H + +#include +#include +#include +#include + +#define ITRF_TRIGGER_LEVEL BIT(0) +#define ITRF_SHARED BIT(1) + +struct itr_chip { + const struct itr_ops *ops; + /* + * dt_get_irq - parse a device tree interrupt property + * + * @properties raw interrupt property from device tree + * @count number of elements in @properties + * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) + * or IRQ_TYPE_NONE if unknown + * @prio If not NULL, output interrupt priority value or 0 if unknown + */ + int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, + uint32_t *prio); +}; + +struct itr_ops { + void (*add)(struct itr_chip *chip, size_t it, uint32_t type, + uint32_t prio); + void (*enable)(struct itr_chip *chip, size_t it); + void (*disable)(struct itr_chip *chip, size_t it); + void (*raise_pi)(struct itr_chip *chip, size_t it); + void (*raise_sgi)(struct itr_chip *chip, size_t it, + uint8_t cpu_mask); + void (*set_affinity)(struct itr_chip *chip, size_t it, + uint8_t cpu_mask); +}; + +enum itr_return { + ITRR_NONE, + ITRR_HANDLED, +}; + +struct itr_handler; + +typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); + +struct itr_handler { + size_t it; + uint32_t flags; + itr_handler_t handler; + void *data; + SLIST_ENTRY(itr_handler) link; +}; + +void itr_init(struct itr_chip *data); +void itr_handle(size_t it); + +#ifdef CFG_DT +/* + * Get the DT interrupt property at @node. In the DT an interrupt property can + * specify additional information which can be retrieved with @type and @prio. + * + * @fdt reference to the Device Tree + * @node is the node offset to read the interrupt property from + * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property + * or IRQ_TYPE_NONE if not. Can be NULL if not needed + * @prio interrupt priority if specified by interrupt property or 0 if not. Can + * be NULL if not needed + * + * Returns the interrupt number if value >= 0 + * otherwise DT_INFO_INVALID_INTERRUPT + */ +int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, + uint32_t *prio); + +/* + * Get the DT interrupt property at @node + */ +static inline int dt_get_irq(const void *fdt, int node) +{ + return dt_get_irq_type_prio(fdt, node, NULL, NULL); +} +#endif + +struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, + uint32_t flags, void *data, + uint32_t type, uint32_t prio); +void itr_free(struct itr_handler *hdl); +void itr_add_type_prio(struct itr_handler *handler, uint32_t type, + uint32_t prio); +void itr_enable(size_t it); +void itr_disable(size_t it); +/* raise the Peripheral Interrupt corresponding to the interrupt ID */ +void itr_raise_pi(size_t it); +/* + * raise the Software Generated Interrupt corresponding to the interrupt ID, + * the cpu_mask represents which cpu interface to forward. + */ +void itr_raise_sgi(size_t it, uint8_t cpu_mask); +/* + * let corresponding interrupt forward to the cpu interface + * according to the cpu_mask. + */ +void itr_set_affinity(size_t it, uint8_t cpu_mask); + +/* + * __weak overridable function which is called when a secure interrupt is + * received. The default function calls panic() immediately, platforms which + * expects to receive secure interrupts should override this function. + */ +void itr_core_handler(void); + +static inline void itr_add(struct itr_handler *handler) +{ + itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); +} + +static inline struct itr_handler *itr_alloc_add(size_t it, + itr_handler_t handler, + uint32_t flags, void *data) +{ + return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, + 0); +} + +#endif /*__KERNEL_INTERRUPT_H*/ diff --git a/optee/optee_os/core/include/kernel/ldelf_loader.h b/optee/optee_os/core/include/kernel/ldelf_loader.h new file mode 100644 index 0000000..0f4b074 --- /dev/null +++ b/optee/optee_os/core/include/kernel/ldelf_loader.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Arm Limited + */ + +#include +#include +#include + +#ifndef KERNEL_LDELF_LOADER_H +#define KERNEL_LDELF_LOADER_H + +TEE_Result ldelf_load_ldelf(struct user_mode_ctx *uctx); +TEE_Result ldelf_init_with_ldelf(struct ts_session *sess, + struct user_mode_ctx *uctx); +TEE_Result ldelf_dump_state(struct user_mode_ctx *uctx); +TEE_Result ldelf_dump_ftrace(struct user_mode_ctx *uctx, + void *buf, size_t *blen); +TEE_Result ldelf_dlopen(struct user_mode_ctx *uctx, TEE_UUID *uuid, + uint32_t flags); +TEE_Result ldelf_dlsym(struct user_mode_ctx *uctx, TEE_UUID *uuid, + const char *sym, size_t maxlen, vaddr_t *val); + +#endif /* KERNEL_LDELF_LOADER_H */ diff --git a/optee/optee_os/core/include/kernel/ldelf_syscalls.h b/optee/optee_os/core/include/kernel/ldelf_syscalls.h new file mode 100644 index 0000000..5dd89a7 --- /dev/null +++ b/optee/optee_os/core/include/kernel/ldelf_syscalls.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018-2019, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include +#include +#include +#include +#include +#include + +#ifndef KERNEL_LDELF_SYSCALLS_H +#define KERNEL_LDELF_SYSCALLS_H + +struct system_ctx { + struct handle_db db; + const struct ts_store_ops *store_op; +}; + +TEE_Result ldelf_syscall_map_zi(vaddr_t *va, size_t num_bytes, size_t pad_begin, + size_t pad_end, unsigned long flags); +TEE_Result ldelf_syscall_unmap(vaddr_t va, size_t num_bytes); +TEE_Result ldelf_syscall_open_bin(const TEE_UUID *uuid, size_t uuid_size, + uint32_t *handle); +TEE_Result ldelf_syscall_close_bin(unsigned long handle); +TEE_Result ldelf_syscall_map_bin(vaddr_t *va, size_t num_bytes, + unsigned long handle, size_t offs_bytes, + size_t pad_begin, size_t pad_end, + unsigned long flags); +TEE_Result ldelf_syscall_copy_from_bin(void *dst, size_t offs, size_t num_bytes, + unsigned long handle); +TEE_Result ldelf_syscall_set_prot(unsigned long va, size_t num_bytes, + unsigned long flags); +TEE_Result ldelf_syscall_remap(unsigned long old_va, vaddr_t *new_va, + size_t num_bytes, size_t pad_begin, + size_t pad_end); +TEE_Result ldelf_syscall_gen_rnd_num(void *buf, size_t num_bytes); +void ldelf_sess_cleanup(struct ts_session *sess); + +#endif /* KERNEL_LDELF_SYSCALLS_H */ diff --git a/optee/optee_os/core/include/kernel/linker.h b/optee/optee_os/core/include/kernel/linker.h new file mode 100644 index 0000000..8b3c5ec --- /dev/null +++ b/optee/optee_os/core/include/kernel/linker.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ +#ifndef __KERNEL_LINKER_H +#define __KERNEL_LINKER_H + +#include +#include + +/* + * Symbols exported by the link script. + */ + +#ifdef __arm__ + +/* + * These addresses will be the start or end of the exception binary search + * index table (.ARM.exidx section) + */ +extern const uint8_t __exidx_start[]; +extern const uint8_t __exidx_end[]; +extern const uint8_t __extab_start[]; +extern const uint8_t __extab_end[]; + +#endif + +#define VCORE_UNPG_RX_PA ((unsigned long)__vcore_unpg_rx_start) +#define VCORE_UNPG_RX_SZ ((size_t)(__vcore_unpg_rx_end - \ + __vcore_unpg_rx_start)) +#define VCORE_UNPG_RO_PA ((unsigned long)__vcore_unpg_ro_start) +#define VCORE_UNPG_RO_SZ ((size_t)(__vcore_unpg_ro_end - \ + __vcore_unpg_ro_start)) +#define VCORE_UNPG_RW_PA ((unsigned long)__vcore_unpg_rw_start) +#define VCORE_UNPG_RW_SZ ((size_t)(__vcore_unpg_rw_end - \ + __vcore_unpg_rw_start)) +#define VCORE_NEX_RW_PA ((unsigned long)__vcore_nex_rw_start) +#define VCORE_NEX_RW_SZ ((size_t)(__vcore_nex_rw_end - \ + __vcore_nex_rw_start)) +#define VCORE_INIT_RX_PA ((unsigned long)__vcore_init_rx_start) +#define VCORE_INIT_RX_SZ ((size_t)(__vcore_init_rx_end - \ + __vcore_init_rx_start)) +#define VCORE_INIT_RO_PA ((unsigned long)__vcore_init_ro_start) +#define VCORE_INIT_RO_SZ ((size_t)(__vcore_init_ro_end - \ + __vcore_init_ro_start)) + +#define VCORE_START_VA ((vaddr_t)__text_start) + +#define EMIT_SECTION_INFO_SYMBOLS(section_name) \ + extern const uint8_t __vcore_ ## section_name ## _start[]; \ + extern const uint8_t __vcore_ ## section_name ## _end[]; \ + extern const uint8_t __vcore_ ## section_name ## _size[] + +EMIT_SECTION_INFO_SYMBOLS(unpg_rx); +EMIT_SECTION_INFO_SYMBOLS(unpg_ro); +EMIT_SECTION_INFO_SYMBOLS(unpg_rw); +EMIT_SECTION_INFO_SYMBOLS(nex_rw); +EMIT_SECTION_INFO_SYMBOLS(init_ro); +EMIT_SECTION_INFO_SYMBOLS(init_rx); + +#undef EMIT_SECTION_INFO_SYMBOLS + +extern const uint8_t __text_start[]; +extern const uint8_t __text_data_start[]; +extern const uint8_t __text_data_end[]; +extern const uint8_t __text_end[]; +extern const uint8_t __end[]; + +extern const uint8_t __identity_map_init_start[]; +extern const uint8_t __identity_map_init_end[]; + +extern uint8_t __data_start[]; +extern const uint8_t __data_end[]; +extern const uint8_t __rodata_start[]; +extern const uint8_t __rodata_end[]; +extern const uint8_t __bss_start[]; +extern const uint8_t __bss_end[]; +extern const uint8_t __nozi_start[]; +extern const uint8_t __nozi_end[]; +extern const uint8_t __nozi_stack_start[]; +extern const uint8_t __nozi_stack_end[]; +extern const uint8_t __init_start[]; +extern const uint8_t __init_end[]; + +extern uint8_t __heap1_start[]; +extern const uint8_t __heap1_end[]; +extern uint8_t __heap2_start[]; +extern const uint8_t __heap2_end[]; + +extern uint8_t __nex_heap_start[]; +extern const uint8_t __nex_heap_end[]; + +extern const uint8_t __pageable_part_start[]; +extern const uint8_t __pageable_part_end[]; +extern const uint8_t __pageable_start[]; +extern const uint8_t __pageable_end[]; + +extern const uint8_t __rodata_init_start[]; +extern const uint8_t __rodata_init_end[]; +extern const uint8_t __rodata_pageable_start[]; +extern const uint8_t __rodata_pageable_end[]; +extern const uint8_t __text_init_start[]; +extern const uint8_t __text_init_end[]; +extern const uint8_t __text_pageable_start[]; +extern const uint8_t __text_pageable_end[]; + +#define ASAN_SHADOW_PA ((paddr_t)(vaddr_t)__asan_shadow_start) +#define ASAN_SHADOW_SZ ((size_t)__asan_shadow_size) +extern const uint8_t __asan_shadow_start[]; +extern const uint8_t __asan_shadow_end[]; +extern const uint8_t __asan_shadow_size[]; + +#define ASAN_MAP_PA ((paddr_t)(vaddr_t)__asan_map_start) +#define ASAN_MAP_SZ ((size_t)__asan_map_size) +extern const uint8_t __asan_map_start[]; +extern const uint8_t __asan_map_end[]; +extern const uint8_t __asan_map_size[]; + +extern const vaddr_t __ctor_list; +extern const vaddr_t __ctor_end; + +/* Generated by core/arch/$(ARCH)/kernel/link.mk */ +extern const char core_v_str[]; + +#endif /*__KERNEL_LINKER_H*/ + diff --git a/optee/optee_os/core/include/kernel/lockdep.h b/optee/optee_os/core/include/kernel/lockdep.h new file mode 100644 index 0000000..e6d786d --- /dev/null +++ b/optee/optee_os/core/include/kernel/lockdep.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef __KERNEL_LOCKDEP_H +#define __KERNEL_LOCKDEP_H + +#include +#include +#include +#include +#include +#include + +/* + * Lock graph. If node A has an edge to node B, then A was locked before B in + * the same thread of execution. + */ + +struct lockdep_edge { + struct lockdep_node *to; + uintptr_t thread_id; + vaddr_t *call_stack_from; + vaddr_t *call_stack_to; + STAILQ_ENTRY(lockdep_edge) link; +}; + +STAILQ_HEAD(lockdep_edge_head, lockdep_edge); + +struct lockdep_node { + uintptr_t lock_id; /* For instance, address of actual lock object */ + struct lockdep_edge_head edges; + TAILQ_ENTRY(lockdep_node) link; + uint8_t flags; /* Used temporarily when walking the graph */ +}; + +TAILQ_HEAD(lockdep_node_head, lockdep_node); + +/* Per-thread queue of currently owned locks (point to nodes in the graph) */ + +struct lockdep_lock { + struct lockdep_node *node; + vaddr_t *call_stack; + TAILQ_ENTRY(lockdep_lock) link; +}; + +TAILQ_HEAD(lockdep_lock_head, lockdep_lock); + +#ifdef CFG_LOCKDEP + +/* + * Functions used internally and for testing the algorithm. Actual locking code + * should use the wrappers below (which panic in case of error). + */ +TEE_Result __lockdep_lock_acquire(struct lockdep_node_head *graph, + struct lockdep_lock_head *owned, + uintptr_t id); +TEE_Result __lockdep_lock_tryacquire(struct lockdep_node_head *graph, + struct lockdep_lock_head *owned, + uintptr_t id); +TEE_Result __lockdep_lock_release(struct lockdep_lock_head *owned, + uintptr_t id); + +/* Delete all elements in @graph */ +void lockdep_graph_delete(struct lockdep_node_head *graph); + +/* Delete all elements in @queue */ +void lockdep_queue_delete(struct lockdep_lock_head *queue); + +/* + * Acquire lock @id, while already holding the locks in @owned. + * @owned represent the caller; there should be one instance per thread of + * execution. @graph is the directed acyclic graph (DAG) to be used for + * potential deadlock detection; use the same @graph for all the locks of the + * same type as lock @id. + * + * This function will panic() if the acquire operation would result in a lock + * hierarchy violation (potential deadlock). + */ +static inline void lockdep_lock_acquire(struct lockdep_node_head *graph, + struct lockdep_lock_head *owned, + uintptr_t id) +{ + TEE_Result res = __lockdep_lock_acquire(graph, owned, id); + + if (res) { + EMSG("lockdep: error %#" PRIx32, res); + panic(); + } +} + +/* + * Non-blocking acquire lock @id, while already holding the locks in @owned. + * @owned represent the caller; there should be one instance per thread of + * execution. @graph is the directed acyclic graph (DAG) to be used for + * potential deadlock detection; use the same @graph for all the locks of the + * same type as lock @id. + */ +static inline void lockdep_lock_tryacquire(struct lockdep_node_head *graph, + struct lockdep_lock_head *owned, + uintptr_t id) +{ + TEE_Result res = __lockdep_lock_tryacquire(graph, owned, id); + + if (res) { + EMSG("lockdep: error %#" PRIx32, res); + panic(); + } +} + +/* + * Release lock @id. The lock is removed from @owned. + * + * This function will panic() if the lock is not held by the caller. + */ +static inline void lockdep_lock_release(struct lockdep_lock_head *owned, + uintptr_t id) +{ + TEE_Result res = __lockdep_lock_release(owned, id); + + if (res) { + EMSG("lockdep: error %#" PRIx32, res); + panic(); + } +} + +/* + * Destroy lock @id in @graph. The lock is freed. + */ +void lockdep_lock_destroy(struct lockdep_node_head *graph, uintptr_t id); + +/* Initialize lockdep for mutex objects (kernel/mutex.h) */ +void mutex_lockdep_init(void); + +#else /* CFG_LOCKDEP */ + +static inline void lockdep_lock_acquire(struct lockdep_node_head *g __unused, + struct lockdep_lock_head *o __unused, + uintptr_t id __unused) +{} + +static inline void lockdep_lock_release(struct lockdep_lock_head *o __unused, + uintptr_t id __unused) +{} + +static inline void +lockdep_lock_destroy(struct lockdep_node_head *graph __unused, + uintptr_t id __unused) +{} + +static inline void mutex_lockdep_init(void) +{} + +#endif /* !CFG_LOCKDEP */ + +#endif /* !__KERNEL_LOCKDEP_H */ diff --git a/optee/optee_os/core/include/kernel/misc.h b/optee/optee_os/core/include/kernel/misc.h new file mode 100644 index 0000000..35cfa5f --- /dev/null +++ b/optee/optee_os/core/include/kernel/misc.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef KERNEL_MISC_H +#define KERNEL_MISC_H + +#include +#include +#include +#include + +size_t __get_core_pos(void); + +static inline size_t __noprof get_core_pos(void) +{ + /* + * Foreign interrupts must be disabled before playing with current + * core since we otherwise may be rescheduled to a different core. + */ + assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); + return __get_core_pos(); +} + +#endif /*KERNEL_MISC_H*/ diff --git a/optee/optee_os/core/include/kernel/msg_param.h b/optee/optee_os/core/include/kernel/msg_param.h new file mode 100644 index 0000000..841c3bf --- /dev/null +++ b/optee/optee_os/core/include/kernel/msg_param.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, EPAM Systems + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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_MSG_PARAM_H +#define KERNEL_MSG_PARAM_H + +#include +#include +#include +#include +#include +#include + +/** + * msg_param_mobj_from_noncontig() - construct mobj from non-contiguous + * list of pages. + * + * @buf_ptr - optee_msg_param.u.tmem.buf_ptr value + * @size - optee_msg_param.u.tmem.size value + * @shm_ref - optee_msg_param.u.tmem.shm_ref value + * @map_buffer - true if buffer needs to be mapped into OP-TEE address space + * + * return: + * mobj or NULL on error + */ +#ifdef CFG_CORE_DYN_SHM +struct mobj *msg_param_mobj_from_noncontig(paddr_t buf_ptr, size_t size, + uint64_t shm_ref, bool map_buffer); +#else +static inline struct mobj * +msg_param_mobj_from_noncontig(paddr_t buf_ptr __unused, size_t size __unused, + uint64_t shm_ref __unused, + bool map_buffer __unused) +{ + return NULL; +} +#endif + +/** + * msg_param_attr_is_tmem - helper functions that cheks if attribute is tmem + * + * @attr - attribute to check + * + * return: + * corresponding size field + */ +static inline bool msg_param_attr_is_tmem(uint64_t attr) +{ + switch (attr & OPTEE_MSG_ATTR_TYPE_MASK) { + case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: + return true; + default: + return false; + } +} + +#endif /*KERNEL_MSG_PARAM_H*/ diff --git a/optee/optee_os/core/include/kernel/mutex.h b/optee/optee_os/core/include/kernel/mutex.h new file mode 100644 index 0000000..e4c470b --- /dev/null +++ b/optee/optee_os/core/include/kernel/mutex.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2017, Linaro Limited + */ +#ifndef KERNEL_MUTEX_H +#define KERNEL_MUTEX_H + +#include +#include +#include +#include + +struct mutex { + unsigned spin_lock; /* used when operating on this struct */ + struct wait_queue wq; + short state; /* -1: write, 0: unlocked, > 0: readers */ +}; + +#define MUTEX_INITIALIZER { .wq = WAIT_QUEUE_INITIALIZER } + +struct recursive_mutex { + struct mutex m; /* used when lock_depth goes 0 -> 1 or 1 -> 0 */ + short int owner; + struct refcount lock_depth; +}; + +#define RECURSIVE_MUTEX_INITIALIZER { .m = MUTEX_INITIALIZER, \ + .owner = THREAD_ID_INVALID } + +TAILQ_HEAD(mutex_head, mutex); + +void mutex_init(struct mutex *m); +void mutex_destroy(struct mutex *m); + +void mutex_init_recursive(struct recursive_mutex *m); +void mutex_destroy_recursive(struct recursive_mutex *m); +unsigned int mutex_get_recursive_lock_depth(struct recursive_mutex *m); + +#ifdef CFG_MUTEX_DEBUG +void mutex_unlock_debug(struct mutex *m, const char *fname, int lineno); +#define mutex_unlock(m) mutex_unlock_debug((m), __FILE__, __LINE__) + +void mutex_lock_debug(struct mutex *m, const char *fname, int lineno); +#define mutex_lock(m) mutex_lock_debug((m), __FILE__, __LINE__) + +bool mutex_trylock_debug(struct mutex *m, const char *fname, int lineno); +#define mutex_trylock(m) mutex_trylock_debug((m), __FILE__, __LINE__) + +void mutex_read_unlock_debug(struct mutex *m, const char *fname, int lineno); +#define mutex_read_unlock(m) mutex_read_unlock_debug((m), __FILE__, __LINE__) + +void mutex_read_lock_debug(struct mutex *m, const char *fname, int lineno); +#define mutex_read_lock(m) mutex_read_lock_debug((m), __FILE__, __LINE__) + +bool mutex_read_trylock_debug(struct mutex *m, const char *fname, int lineno); +#define mutex_read_trylock(m) mutex_read_trylock_debug((m), __FILE__, __LINE__) + +void mutex_unlock_recursive_debug(struct recursive_mutex *m, const char *fname, + int lineno); +#define mutex_unlock_recursive(m) mutex_unlock_recursive_debug((m), __FILE__, \ + __LINE__) + +void mutex_lock_recursive_debug(struct recursive_mutex *m, const char *fname, + int lineno); +#define mutex_lock_recursive(m) mutex_lock_recursive_debug((m), __FILE__, \ + __LINE__) +#else +void mutex_unlock(struct mutex *m); +void mutex_lock(struct mutex *m); +bool mutex_trylock(struct mutex *m); +void mutex_read_unlock(struct mutex *m); +void mutex_read_lock(struct mutex *m); +bool mutex_read_trylock(struct mutex *m); + +void mutex_unlock_recursive(struct recursive_mutex *m); +void mutex_lock_recursive(struct recursive_mutex *m); +#endif + +struct condvar { + unsigned spin_lock; + struct mutex *m; +}; +#define CONDVAR_INITIALIZER { .m = NULL } + +void condvar_init(struct condvar *cv); +void condvar_destroy(struct condvar *cv); + +#ifdef CFG_MUTEX_DEBUG +void condvar_signal_debug(struct condvar *cv, const char *fname, int lineno); +#define condvar_signal(cv) condvar_signal_debug((cv), __FILE__, __LINE__) + +void condvar_broadcast_debug(struct condvar *cv, const char *fname, int lineno); +#define condvar_broadcast(cv) condvar_broadcast_debug((cv), __FILE__, __LINE__) + +void condvar_wait_debug(struct condvar *cv, struct mutex *m, + const char *fname, int lineno); +#define condvar_wait(cv, m) condvar_wait_debug((cv), (m), __FILE__, __LINE__) +#else +void condvar_signal(struct condvar *cv); +void condvar_broadcast(struct condvar *cv); +void condvar_wait(struct condvar *cv, struct mutex *m); +#endif + +#endif /*KERNEL_MUTEX_H*/ + diff --git a/optee/optee_os/core/include/kernel/notif.h b/optee/optee_os/core/include/kernel/notif.h new file mode 100644 index 0000000..71b53d8 --- /dev/null +++ b/optee/optee_os/core/include/kernel/notif.h @@ -0,0 +1,171 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#ifndef __KERNEL_NOTIF_H +#define __KERNEL_NOTIF_H + +#include +#include +#include +#include +#include + +/* + * Notification values are divided into two kinds, asynchronous and + * synchronous, where the asynchronous has the lowest values. + * They are ordered as: + * 0 Do bottom half + * 1..NOTIF_ASYNC_MAX Free for signalling in PTAs and should be + * allocated with notif_alloc_async_value() + * NOTIF_SYNC_VALUE_BASE.. Used as NOTIF_SYNC_VALUE_BASE + thread_id + * NOTIF_VALUE_MAX for mutex and condvar wait/wakeup + * + * Any value can be signalled with notif_send_sync() while only the ones + * <= NOTIF_ASYNC_VALUE_MAX can be signalled with notif_send_async(). + */ + +#if defined(CFG_CORE_ASYNC_NOTIF) +#define NOTIF_ASYNC_VALUE_MAX U(63) +#define NOTIF_SYNC_VALUE_BASE (NOTIF_ASYNC_VALUE_MAX + U(1)) +#else +#define NOTIF_SYNC_VALUE_BASE 0 +#endif + +#define NOTIF_VALUE_MAX (NOTIF_SYNC_VALUE_BASE + \ + CFG_NUM_THREADS) + +#define NOTIF_VALUE_DO_BOTTOM_HALF 0 + +/* + * enum notif_event - Notification of an event + * @NOTIF_EVENT_STARTED: Delivered in an atomic context to inform + * drivers that normal world has enabled + * asynchronous notifications. + * @NOTIF_EVENT_DO_BOTTOM_HALF: Delivered in a yielding context to let a + * driver do bottom half processing. + * @NOTIF_EVENT_STOPPED: Delivered in a yielding contest to inform + * drivers that normal world is about to disable + * asynchronous notifications. + * + * Once a driver has received a @NOTIF_EVENT_STARTED asynchronous notifications + * driving the @NOTIF_EVENT_DO_BOTTOM_HALF deliveries is enabled. + * + * In case a @NOTIF_EVENT_STOPPED is received there will be no more + * @NOTIF_EVENT_DO_BOTTOM_HALF events delivered, until @NOTIF_EVENT_STARTED + * has been delivered again. + * + * Note that while a @NOTIF_EVENT_STOPPED is being delivered at the same + * time may a @NOTIF_EVENT_STARTED be delivered again so a driver is + * required to sychronize accesses to its internal state. + */ +enum notif_event { + NOTIF_EVENT_STARTED, + NOTIF_EVENT_DO_BOTTOM_HALF, + NOTIF_EVENT_STOPPED, +}; + +/* + * struct notif_driver - Registration of driver notification + * @atomic_cb: A callback called in an atomic context from + * notif_deliver_atomic_event(). Currently only used to + * signal @NOTIF_EVENT_STARTED. + * @yielding_cb: A callback called in a yielding context from + * notif_deliver_event(). Currently only used to signal + * @NOTIF_EVENT_DO_BOTTOM_HALF and @NOTIF_EVENT_STOPPED. + * + * A atomic context means that interrupts are masked and a common spinlock + * is held. Calls via @atomic_cb are only atomic with regards to each + * other, other CPUs may execute yielding calls or even receive interrupts. + * + * A yielding context means that the function is executing in a normal + * threaded context allowing RPC and synchronization with other thread + * using mutexes and condition variables. + */ +struct notif_driver { + void (*atomic_cb)(struct notif_driver *ndrv, enum notif_event ev); + void (*yielding_cb)(struct notif_driver *ndrv, enum notif_event ev); + SLIST_ENTRY(notif_driver) link; +}; + +#if defined(CFG_CORE_ASYNC_NOTIF) +bool notif_async_is_started(void); +#else +static inline bool notif_async_is_started(void) +{ + return false; +} +#endif + +TEE_Result notif_alloc_async_value(uint32_t *value); +void notif_free_async_value(uint32_t value); + +/* + * Wait in normal world for a value to be sent by notif_send() + */ +TEE_Result notif_wait(uint32_t value); + +/* + * Send an asynchronous value, note that it must be <= NOTIF_ASYNC_VALUE_MAX + */ +#if defined(CFG_CORE_ASYNC_NOTIF) +void notif_send_async(uint32_t value); +#else +static inline void notif_send_async(uint32_t value __unused) +{ +} +#endif + +/* + * Send a sychronous value, note that it must be <= NOTIF_VALUE_MAX. The + * notification is synchronous even if the value happens to belong in the + * asynchronous range. + */ +TEE_Result notif_send_sync(uint32_t value); + +/* + * Called by device drivers. + */ +#if defined(CFG_CORE_ASYNC_NOTIF) +void notif_register_driver(struct notif_driver *ndrv); +void notif_unregister_driver(struct notif_driver *ndrv); +#else +static inline void notif_register_driver(struct notif_driver *ndrv __unused) +{ +} + +static inline void notif_unregister_driver(struct notif_driver *ndrv __unused) +{ +} +#endif + +/* This is called from a fast call */ +#if defined(CFG_CORE_ASYNC_NOTIF) +uint32_t notif_get_value(bool *value_valid, bool *value_pending); +#else +static inline uint32_t notif_get_value(bool *value_valid, bool *value_pending) +{ + *value_valid = false; + *value_pending = false; + return UINT32_MAX; +} +#endif + +/* + * These are called from yielding calls + */ +#if defined(CFG_CORE_ASYNC_NOTIF) +void notif_deliver_atomic_event(enum notif_event ev); +void notif_deliver_event(enum notif_event ev); +#else +static inline void notif_deliver_atomic_event(enum notif_event ev __unused) +{ +} + +static inline void notif_deliver_event(enum notif_event ev __unused) +{ +} +#endif + +#endif /*__KERNEL_NOTIF_H*/ diff --git a/optee/optee_os/core/include/kernel/panic.h b/optee/optee_os/core/include/kernel/panic.h new file mode 100644 index 0000000..9dc38dc --- /dev/null +++ b/optee/optee_os/core/include/kernel/panic.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef KERNEL_PANIC_H +#define KERNEL_PANIC_H + +#include + +/* debug disabled => __FILE__, ... and panic message are not built. */ +#if defined(CFG_TEE_CORE_DEBUG) +#define __panic(str) __do_panic(__FILE__, __LINE__, __func__, str) +#else +#define __panic(str) __do_panic((void *)0, 0, (void *)0, str) +#endif + +void __do_panic(const char *file, const int line, const char *func, + const char *msg) __noreturn; + +/* + * Suppress GCC warning on expansion of the panic() macro with no argument: + * 'ISO C99 requires at least one argument for the "..." in a variadic macro' + * Occurs when '-pedantic' is combined with '-std=gnu99'. + * Suppression applies only to this file and the expansion of macros defined in + * this file. + */ +#pragma GCC system_header + +/* panic() can get a string or no argument */ +#define _panic0() __panic((void *)0) +#define _panic1(s) __panic(s) +#define _panic_fn(a, b, name, ...) name +#define panic(...) _panic_fn("", ##__VA_ARGS__, _panic1, _panic0)(__VA_ARGS__) + +/* + * Weak function used in __do_panic() to put the current CPU on hold. + * If no arch-specific override is provided, defaults to a busy loop. + */ +void cpu_idle(void); + +#endif /*KERNEL_PANIC_H*/ diff --git a/optee/optee_os/core/include/kernel/pm.h b/optee/optee_os/core/include/kernel/pm.h new file mode 100644 index 0000000..2badce9 --- /dev/null +++ b/optee/optee_os/core/include/kernel/pm.h @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef __KERNEL_PM_H +#define __KERNEL_PM_H + +#include +#include +#include + +/* + * Platform hints on targeted power state. Hints are stored in a 32bit + * unsigned value. Lower bits defines generic resource bit flags. Higher + * bits stores a platform specific value specific platform driver may + * understand. Registered callbacks may choose to use or ignore these hints. + * + * PM_HINT_CLOCK_STATE - When set clock shall be suspended/restored + * PM_HINT_POWER_STATE - When set device power shall be suspended/restored + * PM_HINT_IO_STATE - When set IO pins shall be suspended/restored + * PM_HINT_CONTEXT_STATE - When set the full context be suspended/restored + * PM_HINT_PLATFORM_STATE_MASK - Bit mask reserved for platform specific hints + * PM_HINT_PLATFORM_STATE_SHIFT - LSBit position of platform specific hints mask + */ +#define PM_HINT_CLOCK_STATE BIT(0) +#define PM_HINT_POWER_STATE BIT(1) +#define PM_HINT_IO_STATE BIT(2) +#define PM_HINT_CONTEXT_STATE BIT(3) +#define PM_HINT_PLATFORM_STATE_MASK GENMASK_32(31, 16) +#define PM_HINT_PLATFORM_STATE_SHIFT U(16) + +/* + * PM_OP_SUSPEND: platform is suspending to a target low power state + * PM_OP_RESUME: platform is resuming from low power state + */ +enum pm_op { + PM_OP_SUSPEND = 0, + PM_OP_RESUME = 1, +}; + +/* + * Registered callbacks are called the ordering directives specified + * by the PM_CB_ORDER_* value. Driver ordered callbacks at suspended + * first/resumed last. Core service ordered callbacks are suspended + * last/resumed first. + */ +enum pm_callback_order { + PM_CB_ORDER_DRIVER = 0, + PM_CB_ORDER_CORE_SERVICE, + PM_CB_ORDER_MAX +}; + +#define PM_CALLBACK_HANDLE_INITIALIZER(_callback, _handle, _order, _name)\ + ((struct pm_callback_handle){ \ + .callback = (_callback), \ + .handle = (_handle), \ + .order = (_order), \ + .name = (_name), \ + }) + +#define PM_CALLBACK_GET_HANDLE(pm_handle) ((pm_handle)->handle) + +struct pm_callback_handle; +typedef TEE_Result (*pm_callback)(enum pm_op op, uint32_t pm_hint, + const struct pm_callback_handle *pm_handle); + +/* + * Drivers and services can register a callback function for the platform + * suspend and resume sequences. A private address handle can be registered + * with the callback and retrieved from the callback. Callback can be + * registered with a specific call order as defined per PM_CB_ORDER_*. + * + * Callback shall return an error if failing to complete target transition. + * This information may be used by the platform to resume a platform on + * non-fatal failure to suspend. + * + * Callback implementations should ensure their functions belong to unpaged + * memory sections (see DECLARE_KEEP_PAGER()) since the callback is likely to + * be called from an unpaged execution context. + * + * Power Mamagement callback functions API: + * + * TEE_Result (*callback)(enum pm_op op, + * unsigned int pm_hint, + * const struct pm_callback_handle *pm_handle); + * + * @op - Target operation: either PM_SUSPEND or PM_RESUME + * @pm_hint - Hints on power state platform suspends to /resumes from. + * PM_STATE_HINT_* defines the supported values. + * @pm_handle - Reference to the struct pm_callback_handle related to to + * registered callback. Callback can retrieve the registered + * private handle with PM_CALLBACK_GET_HANDLE(). + * + * Return a TEE_Result compliant return code + */ +/* + * struct pm_callback_handle store the callback registration directives. + * + * @callback - Registered callback function + * @handle - Registered private handler for the callback + * @order - Registered callback call order priority (PM_CB_ORDER_*) + * @flags - Flags set by pm core to keep track of execution + * @name - Registered callback name + */ +struct pm_callback_handle { + /* Set by the caller when registering a callback */ + pm_callback callback; + void *handle; + uint8_t order; + /* Set by the system according to execution context */ + uint8_t flags; + const char *name; +}; + +/* + * Register a callback for suspend/resume sequence + * Refer to struct pm_callback_handle for description of the callbacks + * API and the registration directives. + * + * @pm_handle: Reference callback registration directives + */ +void register_pm_cb(struct pm_callback_handle *pm_handle); + +/* + * Register a driver callback for generic suspend/resume. + * Refer to struct pm_callback_handle for description of the callbacks + * API. + * + * @callback: Registered callback function + * @handle: Registered private handle argument for the callback + * @name: Registered callback name + */ +static inline void register_pm_driver_cb(pm_callback callback, void *handle, + const char *name) +{ + register_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle, + PM_CB_ORDER_DRIVER, + name)); +} + +/* + * Register a core service callback for generic suspend/resume. + * Refer to struct pm_callback_handle for description of the callbacks + * API. + * + * @callback: Registered callback function + * @handle: Registered private handle argument for the callback + * @name: Registered callback name + */ +static inline void register_pm_core_service_cb(pm_callback callback, + void *handle, const char *name) +{ + register_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle, + PM_CB_ORDER_CORE_SERVICE, + name)); +} + +/* + * Request call to registered PM callbacks + * + * @op: Either PM_OP_SUSPEND or PM_OP_RESUME + * @pm_hint: Hint (PM_HINT_*) on state the platform suspends to/resumes from. + * + * Return a TEE_Result compliant status + */ +TEE_Result pm_change_state(enum pm_op op, uint32_t pm_hint); + +#endif /*__KERNEL_PM_H*/ diff --git a/optee/optee_os/core/include/kernel/pseudo_ta.h b/optee/optee_os/core/include/kernel/pseudo_ta.h new file mode 100644 index 0000000..23a1458 --- /dev/null +++ b/optee/optee_os/core/include/kernel/pseudo_ta.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef KERNEL_PSEUDO_TA_H +#define KERNEL_PSEUDO_TA_H + +#include +#include +#include +#include +#include +#include +#include + +#define PTA_MANDATORY_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_MULTI_SESSION | \ + TA_FLAG_INSTANCE_KEEP_ALIVE) + +#define PTA_ALLOWED_FLAGS (PTA_MANDATORY_FLAGS | \ + TA_FLAG_SECURE_DATA_PATH | \ + TA_FLAG_CONCURRENT | \ + TA_FLAG_DEVICE_ENUM) + +#define PTA_DEFAULT_FLAGS PTA_MANDATORY_FLAGS + +struct pseudo_ta_head { + TEE_UUID uuid; + const char *name; + uint32_t flags; + + TEE_Result (*create_entry_point)(void); + void (*destroy_entry_point)(void); + TEE_Result (*open_session_entry_point)(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS], + 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[TEE_NUM_PARAMS]); +}; + +#define pseudo_ta_register(...) \ + SCATTERED_ARRAY_DEFINE_PG_ITEM(pseudo_tas, struct pseudo_ta_head) = \ + { __VA_ARGS__ } + +struct pseudo_ta_ctx { + const struct pseudo_ta_head *pseudo_ta; + struct tee_ta_ctx ctx; +}; + +bool is_pseudo_ta_ctx(struct ts_ctx *ctx); + +static inline struct pseudo_ta_ctx *to_pseudo_ta_ctx(struct ts_ctx *ctx) +{ + assert(is_pseudo_ta_ctx(ctx)); + return container_of(ctx, struct pseudo_ta_ctx, ctx.ts_ctx); +} + +TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid, + struct tee_ta_session *s); + +#endif /* KERNEL_PSEUDO_TA_H */ + diff --git a/optee/optee_os/core/include/kernel/refcount.h b/optee/optee_os/core/include/kernel/refcount.h new file mode 100644 index 0000000..6ae648e --- /dev/null +++ b/optee/optee_os/core/include/kernel/refcount.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __KERNEL_REFCOUNT_H +#define __KERNEL_REFCOUNT_H + +#include + +/* + * Reference counter + * + * When val is 0, refcount_inc() does not change the value and returns false. + * Otherwise, it increments the value and returns true. + * + * refcount_dec() decrements the value and returns true when the call + * caused the value to become 0, false otherwise. + * + * Since each call to refcount_dec() is supposed to match a call to + * refcount_inc(), refcount_dec() called for val == 0 should never happen. + * + * This behaviour makes this pattern possible: + * if (!refcount_inc(r)) { + * mutex_lock(m); + * // Some other thread may have initialized o by now so check that + * // we still need to initialize o. + * if (!o) { + * o = initialize(); + * refcount_set(r, 1); + * } + * mutex_unlock(m); + * } + * + * or + * if (refcount_dec(r)) { + * mutex_lock(m); + * // Now that we have the mutex o can't be ininialized/uninitialized + * // by any other thread, check that the refcount value is still 0 + * // to guard against the thread above already having reinitialized o + * if (!refcount_val(r) && o) + * uninitialize(o) + * mutex_unlock(m); + * } + * + * where r if the reference counter, o is the object and m the mutex + * protecting the object. + */ + +struct refcount { + unsigned int val; +}; + +/* Increases refcount by 1, return true if val > 0 else false */ +bool refcount_inc(struct refcount *r); +/* Decreases refcount by 1, return true if val == 0 else false */ +bool refcount_dec(struct refcount *r); + +static inline void refcount_set(struct refcount *r, unsigned int val) +{ + atomic_store_uint(&r->val, val); +} + +static inline unsigned int refcount_val(struct refcount *r) +{ + return atomic_load_uint(&r->val); +} + +#endif /*!__KERNEL_REFCOUNT_H*/ diff --git a/optee/optee_os/core/include/kernel/rpc_io_i2c.h b/optee/optee_os/core/include/kernel/rpc_io_i2c.h new file mode 100644 index 0000000..50ddbcd --- /dev/null +++ b/optee/optee_os/core/include/kernel/rpc_io_i2c.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020 Foundries Ltd + */ + +#ifndef __RPC_IO_I2C_H +#define __RPC_IO_I2C_H + +#include +#include + +/* I2C master transfer mode */ +enum rpc_i2c_mode { + RPC_I2C_MODE_WRITE = OPTEE_RPC_I2C_TRANSFER_WR, + RPC_I2C_MODE_READ = OPTEE_RPC_I2C_TRANSFER_RD, +}; + +/* I2C master transfer control flags */ +#define RPC_I2C_FLAGS_TEN_BIT OPTEE_RPC_I2C_FLAGS_TEN_BIT + +/* + * The bus identifier defines an implicit ABI with the REE. + * Using this service to access I2C slaves on REE dynamically assigned buses is + * not recommended unless there is a guarantee that the bus identifier will + * persist across reboots. + */ +struct rpc_i2c_request { + enum rpc_i2c_mode mode; + uint16_t bus; /* bus identifier used by the REE [0..n] */ + uint16_t chip; /* slave identifier from its data sheet */ + uint16_t flags; /* transfer flags (ie: ten bit chip address) */ + uint8_t *buffer; + size_t buffer_len; +}; + +TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *p, size_t *bytes); + +#endif /* __RPC_IO_I2C_H */ diff --git a/optee/optee_os/core/include/kernel/scall.h b/optee/optee_os/core/include/kernel/scall.h new file mode 100644 index 0000000..1bdbffd --- /dev/null +++ b/optee/optee_os/core/include/kernel/scall.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2022, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ +#ifndef __KERNEL_SCALL_H +#define __KERNEL_SCALL_H + +#include + +/* + * Generic "pointer to function" type. Actual syscalls take zero or more + * arguments and return TEE_Result. + */ +typedef void (*syscall_t)(void); + +struct thread_scall_regs; + +/* Helper function for scall_handle_user_ta() and scall_handle_ldelf() */ +uint32_t scall_do_call(struct thread_scall_regs *regs, syscall_t func); + +/* Registered as .handle_scall in struct tee_ta_ops for user TAs. */ +bool scall_handle_user_ta(struct thread_scall_regs *regs); + +/* Separate syscall handler for calls from ldelf */ +bool scall_handle_ldelf(struct thread_scall_regs *regs); + +/* + * Called from the assembly functions syscall_sys_return() and + * syscall_panic() to update the register values in the struct + * thread_scall_regs to return back to TEE Core from an earlier call to + * thread_enter_user_mode(). + */ +uint32_t scall_sys_return_helper(uint32_t ret, bool panic, uint32_t panic_code, + struct thread_scall_regs *regs); + +/* Saves TA panic stack, arch-specific implementation */ +void scall_save_panic_stack(struct thread_scall_regs *regs); + +#endif /*__KERNEL_SCALL_H*/ diff --git a/optee/optee_os/core/include/kernel/spinlock.h b/optee/optee_os/core/include/kernel/spinlock.h new file mode 100644 index 0000000..fc3e2e4 --- /dev/null +++ b/optee/optee_os/core/include/kernel/spinlock.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef KERNEL_SPINLOCK_H +#define KERNEL_SPINLOCK_H + +#define SPINLOCK_LOCK 1 +#define SPINLOCK_UNLOCK 0 + +#ifndef __ASSEMBLER__ +#include +#include +#include +#include + +#ifdef CFG_TEE_CORE_DEBUG +void spinlock_count_incr(void); +void spinlock_count_decr(void); +bool have_spinlock(void); +static inline void __nostackcheck assert_have_no_spinlock(void) +{ + assert(!have_spinlock()); +} +#else +static inline void spinlock_count_incr(void) { } +static inline void spinlock_count_decr(void) { } +static inline void __nostackcheck assert_have_no_spinlock(void) { } +#endif + +void __cpu_spin_lock(unsigned int *lock); +void __cpu_spin_unlock(unsigned int *lock); +/* returns 0 on locking success, non zero on failure */ +unsigned int __cpu_spin_trylock(unsigned int *lock); + +static inline void cpu_spin_lock_no_dldetect(unsigned int *lock) +{ + assert(thread_foreign_intr_disabled()); + __cpu_spin_lock(lock); + spinlock_count_incr(); +} + +#ifdef CFG_TEE_CORE_DEBUG +#define cpu_spin_lock(lock) \ + cpu_spin_lock_dldetect(__func__, __LINE__, lock) + +static inline void cpu_spin_lock_dldetect(const char *func, const int line, + unsigned int *lock) +{ + unsigned int retries = 0; + unsigned int reminder = 0; + + assert(thread_foreign_intr_disabled()); + + while (__cpu_spin_trylock(lock)) { + retries++; + if (!retries) { + /* wrapped, time to report */ + trace_printf(func, line, TRACE_ERROR, true, + "possible spinlock deadlock reminder %u", + reminder); + if (reminder < UINT_MAX) + reminder++; + } + } + + spinlock_count_incr(); +} +#else +static inline void cpu_spin_lock(unsigned int *lock) +{ + cpu_spin_lock_no_dldetect(lock); +} +#endif + +static inline bool cpu_spin_trylock(unsigned int *lock) +{ + unsigned int rc; + + assert(thread_foreign_intr_disabled()); + rc = __cpu_spin_trylock(lock); + if (!rc) + spinlock_count_incr(); + return !rc; +} + +static inline void cpu_spin_unlock(unsigned int *lock) +{ + assert(thread_foreign_intr_disabled()); + __cpu_spin_unlock(lock); + spinlock_count_decr(); +} + +static inline uint32_t cpu_spin_lock_xsave_no_dldetect(unsigned int *lock) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + cpu_spin_lock(lock); + return exceptions; +} + +#ifdef CFG_TEE_CORE_DEBUG +#define cpu_spin_lock_xsave(lock) \ + cpu_spin_lock_xsave_dldetect(__func__, __LINE__, lock) + +static inline uint32_t cpu_spin_lock_xsave_dldetect(const char *func, + const int line, + unsigned int *lock) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + + cpu_spin_lock_dldetect(func, line, lock); + return exceptions; +} +#else +static inline uint32_t cpu_spin_lock_xsave(unsigned int *lock) +{ + return cpu_spin_lock_xsave_no_dldetect(lock); +} +#endif + +static inline void cpu_spin_unlock_xrestore(unsigned int *lock, + uint32_t exceptions) +{ + cpu_spin_unlock(lock); + thread_unmask_exceptions(exceptions); +} +#endif /* __ASSEMBLER__ */ + +#endif /* KERNEL_SPINLOCK_H */ diff --git a/optee/optee_os/core/include/kernel/tee_common.h b/optee/optee_os/core/include/kernel/tee_common.h new file mode 100644 index 0000000..5c5da2d --- /dev/null +++ b/optee/optee_os/core/include/kernel/tee_common.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef TEE_COMMON_H +#define TEE_COMMON_H + +#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 + +#endif /* TEE_COMMON_H */ diff --git a/optee/optee_os/core/include/kernel/tee_common_otp.h b/optee/optee_os/core/include/kernel/tee_common_otp.h new file mode 100644 index 0000000..82f4538 --- /dev/null +++ b/optee/optee_os/core/include/kernel/tee_common_otp.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef TEE_COMMON_OTP_H +#define TEE_COMMON_OTP_H + +#include +#include +#include +#include +#include + +struct tee_hw_unique_key { + uint8_t data[HW_UNIQUE_KEY_LENGTH]; +}; + +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey); +int tee_otp_get_die_id(uint8_t *buffer, size_t len); +TEE_Result tee_otp_get_ta_enc_key(uint32_t key_type, uint8_t *buffer, + size_t len); +TEE_Result tee_otp_get_rpmb_key(uint8_t *key, size_t len); + +#endif /* TEE_COMMON_OTP_H */ diff --git a/optee/optee_os/core/include/kernel/tee_misc.h b/optee/optee_os/core/include/kernel/tee_misc.h new file mode 100644 index 0000000..035acd3 --- /dev/null +++ b/optee/optee_os/core/include/kernel/tee_misc.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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); + +/* + * Is buffer 'b' inside/outside/overlapping area 'a'? + * + * core_is_buffer_inside() - return true if buffer is inside memory area + * core_is_buffer_outside() - return true if buffer is outside area + * core_is_buffer_intersect() - return true if buffer overlaps area + * + * Warning: core_is_buffer_inside(x,x,x,x)==false does NOT mean + * core_is_buffer_outside(x,x,x,x)==true. + * + * Arguments use by each of these routines: + * @b - buffer start address (handled has an unsigned offset) + * @bl - length (in bytes) of the target buffer + * @a - memory area start address (handled has an unsigned offset) + * @al - memory area length (in byte) + */ +bool core_is_buffer_inside(paddr_t b, paddr_size_t bl, + paddr_t a, paddr_size_t al); +bool core_is_buffer_outside(paddr_t b, paddr_size_t bl, + paddr_t a, paddr_size_t al); +bool core_is_buffer_intersect(paddr_t b, paddr_size_t bl, + paddr_t a, paddr_size_t al); + +/** + * Allocate maximum cache line aligned memory buffer. + * + * Both size and base address of the memory buffer will be maximum cache line + * aligned to make it safe to perform cache maintenance operations over the + * allocated area. + * + * This is needed when non-cache coherent peripherals are used and memory area + * is shared between CPU and peripheral. + * + * Allocated memory is zeroed. + * + * Release memory with free(). + * + * @size Size in bytes to allocate + * @return NULL on failure or a pointer to allocated memory on success. + */ +void *alloc_cache_aligned(size_t size); + +#endif /* TEE_MISC_H */ diff --git a/optee/optee_os/core/include/kernel/tee_ta_manager.h b/optee/optee_os/core/include/kernel/tee_ta_manager.h new file mode 100644 index 0000000..4b213dd --- /dev/null +++ b/optee/optee_os/core/include/kernel/tee_ta_manager.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2017, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#ifndef TEE_TA_MANAGER_H +#define TEE_TA_MANAGER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Magic TEE identity pointer: set when teecore requests a TA close */ +#define KERN_IDENTITY ((TEE_Identity *)-1) +/* Operation is initiated by a client (non-secure) app */ +#define NSAPP_IDENTITY (NULL) + +TAILQ_HEAD(tee_ta_session_head, tee_ta_session); +TAILQ_HEAD(tee_ta_ctx_head, tee_ta_ctx); + +struct mobj; + +struct param_val { + uint32_t a; + uint32_t b; +}; + +struct param_mem { + struct mobj *mobj; + size_t size; + size_t offs; +}; + +struct tee_ta_param { + uint32_t types; + union { + struct param_val val; + struct param_mem mem; + } u[TEE_NUM_PARAMS]; +}; + +struct user_ta_ctx; + +#if defined(CFG_TA_GPROF_SUPPORT) +struct sample_buf { + uint32_t nsamples; /* Size of @samples array in uint16_t */ + uint32_t offset; /* Passed from user mode */ + uint32_t scale; /* Passed from user mode */ + uint32_t count; /* Number of samples taken */ + bool enabled; /* Sampling enabled? */ + uint16_t *samples; + uint64_t usr; /* Total user CPU time for this session */ + uint64_t usr_entered; /* When this session last entered user mode */ + uint32_t freq; /* @usr divided by @freq is in seconds */ +}; +#endif + +/* Context of a loaded TA */ +struct tee_ta_ctx { + uint32_t flags; /* TA_FLAGS from TA header */ + TAILQ_ENTRY(tee_ta_ctx) link; + struct ts_ctx ts_ctx; + 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 busy; /* Context is busy and cannot be entered */ + struct condvar busy_cv; /* CV used when context is busy */ +}; + +struct tee_ta_session { + TAILQ_ENTRY(tee_ta_session) link; + struct ts_session ts_sess; + uint32_t id; /* Session handle (0 is invalid) */ + TEE_Identity clnt_id; /* Identify of client */ + struct tee_ta_param *param; + TEE_ErrorOrigin err_origin; + bool cancel; /* True if TA invocation is cancelled */ + bool cancel_mask; /* True if cancel is masked */ + TEE_Time cancel_time; /* Time when to cancel the TA invocation */ + uint32_t ref_count; /* reference counter */ + struct condvar refc_cv; /* CV used to wait for ref_count to be 0 */ + struct condvar lock_cv; /* CV used to wait for lock */ + short int lock_thread; /* Id of thread holding the lock */ + bool unlink; /* True if session is to be unlinked */ +}; + +/* Registered contexts */ +extern struct tee_ta_ctx_head tee_ctxes; + +extern struct mutex tee_ta_mutex; +extern struct condvar tee_ta_init_cv; + +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 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); + +bool tee_ta_session_is_cancelled(struct tee_ta_session *s, TEE_Time *curr_time); + +/*----------------------------------------------------------------------------- + * Function called to close a TA. + * Parameters: + * id - The session id (in) + * Returns: + * TEE_Result + *---------------------------------------------------------------------------*/ +TEE_Result tee_ta_close_session(struct tee_ta_session *sess, + struct tee_ta_session_head *open_sessions, + const TEE_Identity *clnt_id); + + + +struct tee_ta_session *tee_ta_find_session(uint32_t id, + struct tee_ta_session_head *open_sessions); + +struct tee_ta_session *tee_ta_get_session(uint32_t id, bool exclusive, + struct tee_ta_session_head *open_sessions); + +void tee_ta_put_session(struct tee_ta_session *sess); + +#if defined(CFG_TA_GPROF_SUPPORT) +void tee_ta_update_session_utime_suspend(void); +void tee_ta_update_session_utime_resume(void); +void tee_ta_gprof_sample_pc(vaddr_t pc); +#else +static inline void tee_ta_update_session_utime_suspend(void) {} +static inline void tee_ta_update_session_utime_resume(void) {} +static inline void tee_ta_gprof_sample_pc(vaddr_t pc __unused) {} +#endif +#if defined(CFG_FTRACE_SUPPORT) +void tee_ta_ftrace_update_times_suspend(void); +void tee_ta_ftrace_update_times_resume(void); +#else +static inline void tee_ta_ftrace_update_times_suspend(void) {} +static inline void tee_ta_ftrace_update_times_resume(void) {} +#endif + +bool is_ta_ctx(struct ts_ctx *ctx); + +struct tee_ta_session *to_ta_session(struct ts_session *sess); + +static inline struct tee_ta_ctx *to_ta_ctx(struct ts_ctx *ctx) +{ + assert(is_ta_ctx(ctx)); + return container_of(ctx, struct tee_ta_ctx, ts_ctx); +} + +#if defined(CFG_TA_STATS) +TEE_Result tee_ta_instance_stats(void *buff, size_t *buff_size); +#endif + +#endif diff --git a/optee/optee_os/core/include/kernel/tee_time.h b/optee/optee_os/core/include/kernel/tee_time.h new file mode 100644 index 0000000..3961551 --- /dev/null +++ b/optee/optee_os/core/include/kernel/tee_time.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TEE_TIME_H +#define TEE_TIME_H + +#include "tee_api_types.h" + +TEE_Result tee_time_get_sys_time(TEE_Time *time); +uint32_t tee_time_get_sys_time_protection_level(void); +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); +/* Releases CPU through OP-TEE RPC which switches to Normal World */ +void tee_time_wait(uint32_t milliseconds_delay); +/* Busy wait */ +void tee_time_busy_wait(uint32_t milliseconds_delay); + +#endif diff --git a/optee/optee_os/core/include/kernel/thread.h b/optee/optee_os/core/include/kernel/thread.h new file mode 100644 index 0000000..d0d0995 --- /dev/null +++ b/optee/optee_os/core/include/kernel/thread.h @@ -0,0 +1,392 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2016-2017, Linaro Limited + * Copyright (c) 2020-2021, Arm Limited + */ + +#ifndef KERNEL_THREAD_H +#define KERNEL_THREAD_H + +#ifndef __ASSEMBLER__ +#include +#include +#include +#endif +#include +#include + +#define THREAD_FLAGS_COPY_ARGS_ON_RETURN BIT(0) +#define THREAD_FLAGS_FOREIGN_INTR_ENABLE BIT(1) +#define THREAD_FLAGS_EXIT_ON_FOREIGN_INTR BIT(2) + +#define THREAD_ID_0 0 +#define THREAD_ID_INVALID -1 + +#define THREAD_RPC_MAX_NUM_PARAMS U(4) + +#ifndef __ASSEMBLER__ + +struct thread_specific_data { + TAILQ_HEAD(, ts_session) sess_stack; + struct ts_ctx *ctx; +#ifdef CFG_CORE_FFA + uint32_t rpc_target_info; +#endif + uint32_t abort_type; + uint32_t abort_descr; + vaddr_t abort_va; + unsigned int abort_core; + struct thread_abort_regs abort_regs; +#ifdef CFG_CORE_DEBUG_CHECK_STACKS + bool stackcheck_recursion; +#endif + unsigned int syscall_recursion; +#ifdef CFG_FAULT_MITIGATION + struct ftmn_func_arg *ftmn_arg; +#endif +}; + +void thread_init_canaries(void); +void thread_init_primary(void); +void thread_init_per_cpu(void); + +struct thread_core_local *thread_get_core_local(void); + +/* + * 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. + * + * Returns true on success and false on errors. + */ +bool thread_init_stack(uint32_t stack_id, vaddr_t sp); + +/* + * Initializes thread contexts. Called in thread_init_boot_thread() if + * virtualization is disabled. Virtualization subsystem calls it for + * every new guest otherwise. + */ +void thread_init_threads(void); + +/* + * Called by the init CPU. Sets temporary stack mode for all CPUs + * (curr_thread = -1 and THREAD_CLF_TMP) and sets the temporary stack limit for + * the init CPU. + */ +void thread_init_thread_core_local(void); +void thread_init_core_local_stacks(void); + +#if defined(CFG_CORE_PAUTH) +void thread_init_thread_pauth_keys(void); +void thread_init_core_local_pauth_keys(void); +#else +static inline void thread_init_thread_pauth_keys(void) { } +static inline void thread_init_core_local_pauth_keys(void) { } +#endif + +/* + * Initializes a thread to be used during boot + */ +void thread_init_boot_thread(void); + +/* + * Clears the current thread id + * Only supposed to be used during initialization. + */ +void thread_clr_boot_thread(void); + +/* + * Returns current thread id. + */ +short int thread_get_id(void); + +/* + * Returns current thread id, return -1 on failure. + */ +short int thread_get_id_may_fail(void); + +/* Returns Thread Specific Data (TSD) pointer. */ +struct thread_specific_data *thread_get_tsd(void); + +/* + * Sets foreign interrupts status for current thread, must only be called + * from an active thread context. + * + * enable == true -> enable foreign interrupts + * enable == false -> disable foreign interrupts + */ +void thread_set_foreign_intr(bool enable); + +/* + * Restores the foreign interrupts status (in CPSR) for current thread, must + * only be called from an active thread context. + */ +void thread_restore_foreign_intr(void); + +/* + * thread_get_exceptions() - return current exception mask + */ +uint32_t thread_get_exceptions(void); + +/* + * thread_set_exceptions() - set exception mask + * @exceptions: exception mask to set + * + * Any previous exception mask is replaced by this exception mask, that is, + * old bits are cleared and replaced by these. + */ +void thread_set_exceptions(uint32_t exceptions); + +/* + * thread_mask_exceptions() - Masks (disables) specified asynchronous exceptions + * @exceptions exceptions to mask + * @returns old exception state + */ +uint32_t thread_mask_exceptions(uint32_t exceptions); + +/* + * thread_unmask_exceptions() - Unmasks asynchronous exceptions + * @state Old asynchronous exception state to restore (returned by + * thread_mask_exceptions()) + */ +void thread_unmask_exceptions(uint32_t state); + + +static inline bool __nostackcheck thread_foreign_intr_disabled(void) +{ + return !!(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); +} + +/* + * thread_enter_user_mode() - Enters user mode + * @a0: Passed in r/x0 for user_func + * @a1: Passed in r/x1 for user_func + * @a2: Passed in r/x2 for user_func + * @a3: Passed in r/x3 for user_func + * @user_sp: Assigned sp value in user mode + * @user_func: Function to execute in user mode + * @is_32bit: True if TA should execute in Aarch32, false if Aarch64 + * @exit_status0: Pointer to opaque exit staus 0 + * @exit_status1: Pointer to opaque exit staus 1 + * + * This functions enters user mode with the argument described above, + * @exit_status0 and @exit_status1 are filled in by thread_unwind_user_mode() + * when returning back to the caller of this function through an exception + * handler. + * + * @Returns what's passed in "ret" to thread_unwind_user_mode() + */ +uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, unsigned long user_sp, + unsigned long entry_func, bool is_32bit, + uint32_t *exit_status0, uint32_t *exit_status1); + +/* + * thread_unwind_user_mode() - Unwinds kernel stack from user entry + * @ret: Value to return from thread_enter_user_mode() + * @exit_status0: Exit status 0 + * @exit_status1: Exit status 1 + * + * This is the function that exception handlers can return into + * to resume execution in kernel mode instead of user mode. + * + * This function is closely coupled with thread_enter_user_mode() since it + * need to restore registers saved by thread_enter_user_mode() and when it + * returns make it look like thread_enter_user_mode() just returned. It is + * expected that the stack pointer is where thread_enter_user_mode() left + * it. The stack will be unwound and the function will return to where + * thread_enter_user_mode() was called from. Exit_status0 and exit_status1 + * are filled in the corresponding pointers supplied to + * thread_enter_user_mode(). + */ +void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, + uint32_t exit_status1); + +/* + * Returns the start address (bottom) of the stack for the current thread, + * zero if there is no current thread. + */ +vaddr_t thread_stack_start(void); + + +/* Returns the stack size for the current thread */ +size_t thread_stack_size(void); + +/* + * Returns the start (top, lowest address) and end (bottom, highest address) of + * the current stack (thread, temporary or abort stack). + * When CFG_CORE_DEBUG_CHECK_STACKS=y, the @hard parameter tells if the hard or + * soft limits are queried. The difference between soft and hard is that for the + * latter, the stack start includes some additional space to let any function + * overflow the soft limit and still be able to print a stack dump in this case. + */ +bool get_stack_limits(vaddr_t *start, vaddr_t *end, bool hard); + +static inline bool __nostackcheck get_stack_soft_limits(vaddr_t *start, + vaddr_t *end) +{ + return get_stack_limits(start, end, false); +} + +static inline bool __nostackcheck get_stack_hard_limits(vaddr_t *start, + vaddr_t *end) +{ + return get_stack_limits(start, end, true); +} + +bool thread_is_in_normal_mode(void); + +/* + * Returns true if previous exeception also was in abort mode. + * + * Note: it's only valid to call this function from an abort exception + * handler before interrupts has been re-enabled. + */ +bool thread_is_from_abort_mode(void); + +/** + * Allocates data for payload buffers. + * + * @size: size in bytes of payload buffer + * + * @returns mobj that describes allocated buffer or NULL on error + */ +struct mobj *thread_rpc_alloc_payload(size_t size); + +/** + * Free physical memory previously allocated with thread_rpc_alloc_payload() + * + * @mobj: mobj that describes the buffer + */ +void thread_rpc_free_payload(struct mobj *mobj); + +/** + * Allocate data for payload buffers only shared with the non-secure kernel + * + * @size: size in bytes of payload buffer + * + * @returns mobj that describes allocated buffer or NULL on error + */ +struct mobj *thread_rpc_alloc_kernel_payload(size_t size); + +/** + * Free physical memory previously allocated with + * thread_rpc_alloc_kernel_payload() + * + * @mobj: mobj that describes the buffer + */ +void thread_rpc_free_kernel_payload(struct mobj *mobj); + +struct thread_param_memref { + size_t offs; + size_t size; + struct mobj *mobj; +}; + +struct thread_param_value { + uint64_t a; + uint64_t b; + uint64_t c; +}; + +/* + * Note that there's some arithmetics done on the value so it's important + * to keep in IN, OUT, INOUT order. + */ +enum thread_param_attr { + THREAD_PARAM_ATTR_NONE = 0, + THREAD_PARAM_ATTR_VALUE_IN, + THREAD_PARAM_ATTR_VALUE_OUT, + THREAD_PARAM_ATTR_VALUE_INOUT, + THREAD_PARAM_ATTR_MEMREF_IN, + THREAD_PARAM_ATTR_MEMREF_OUT, + THREAD_PARAM_ATTR_MEMREF_INOUT, +}; + +struct thread_param { + enum thread_param_attr attr; + union { + struct thread_param_memref memref; + struct thread_param_value value; + } u; +}; + +#define THREAD_PARAM_MEMREF(_direction, _mobj, _offs, _size) \ + (struct thread_param){ \ + .attr = THREAD_PARAM_ATTR_MEMREF_ ## _direction, .u.memref = { \ + .mobj = (_mobj), .offs = (_offs), .size = (_size) } \ + } + +#define THREAD_PARAM_VALUE(_direction, _a, _b, _c) \ + (struct thread_param){ \ + .attr = THREAD_PARAM_ATTR_VALUE_ ## _direction, .u.value = { \ + .a = (_a), .b = (_b), .c = (_c) } \ + } + +/** + * Does an RPC using a preallocated argument buffer + * @cmd: RPC cmd + * @num_params: number of parameters + * @params: RPC parameters + * @returns RPC return value + */ +uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params, + struct thread_param *params); + +/** + * Allocate data for payload buffers. + * Buffer is exported to user mode applications. + * + * @size: size in bytes of payload buffer + * + * @returns mobj that describes allocated buffer or NULL on error + */ +struct mobj *thread_rpc_alloc_global_payload(size_t size); + +/** + * Free physical memory previously allocated with + * thread_rpc_alloc_global_payload() + * + * @mobj: mobj that describes the buffer + */ +void thread_rpc_free_global_payload(struct mobj *mobj); + +/* + * enum thread_shm_type - type of non-secure shared memory + * @THREAD_SHM_TYPE_APPLICATION - user space application shared memory + * @THREAD_SHM_TYPE_KERNEL_PRIVATE - kernel private shared memory + * @THREAD_SHM_TYPE_GLOBAL - user space and kernel shared memory + */ +enum thread_shm_type { + THREAD_SHM_TYPE_APPLICATION, + THREAD_SHM_TYPE_KERNEL_PRIVATE, + THREAD_SHM_TYPE_GLOBAL, +}; + +/* + * enum thread_shm_cache_user - user of a cache allocation + * @THREAD_SHM_CACHE_USER_SOCKET - socket communication + * @THREAD_SHM_CACHE_USER_FS - filesystem access + * @THREAD_SHM_CACHE_USER_I2C - I2C communication + * + * To ensure that each user of the shared memory cache doesn't interfere + * with each other a unique ID per user is used. + */ +enum thread_shm_cache_user { + THREAD_SHM_CACHE_USER_SOCKET, + THREAD_SHM_CACHE_USER_FS, + THREAD_SHM_CACHE_USER_I2C, +}; + +/* + * Returns a pointer to the cached RPC memory. Each thread and @user tuple + * has a unique cache. The pointer is guaranteed to point to a large enough + * area or to be NULL. + */ +void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user, + enum thread_shm_type shm_type, + size_t size, struct mobj **mobj); + +#endif /*__ASSEMBLER__*/ + +#endif /*KERNEL_THREAD_H*/ diff --git a/optee/optee_os/core/include/kernel/thread_private.h b/optee/optee_os/core/include/kernel/thread_private.h new file mode 100644 index 0000000..1d83dd5 --- /dev/null +++ b/optee/optee_os/core/include/kernel/thread_private.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef __KERNEL_THREAD_PRIVATE_H +#define __KERNEL_THREAD_PRIVATE_H + +#include +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include +#include + +enum thread_state { + THREAD_STATE_FREE, + THREAD_STATE_SUSPENDED, + THREAD_STATE_ACTIVE, +}; + +struct thread_shm_cache_entry { + struct mobj *mobj; + size_t size; + enum thread_shm_type type; + enum thread_shm_cache_user user; + SLIST_ENTRY(thread_shm_cache_entry) link; +}; + +SLIST_HEAD(thread_shm_cache, thread_shm_cache_entry); + +struct thread_ctx { + struct thread_ctx_regs regs; + enum thread_state state; + vaddr_t stack_va_end; + uint32_t flags; + struct core_mmu_user_map user_map; + bool have_user_map; +#if defined(ARM64) || defined(RV64) + vaddr_t kern_sp; /* Saved kernel SP during user TA execution */ +#endif +#ifdef CFG_CORE_PAUTH + struct thread_pauth_keys keys; +#endif +#ifdef CFG_WITH_VFP + struct thread_vfp_state vfp_state; +#endif + void *rpc_arg; + struct mobj *rpc_mobj; + struct thread_shm_cache shm_cache; + struct thread_specific_data tsd; +}; +#endif /*__ASSEMBLER__*/ + +/* Describes the flags field of struct thread_core_local */ +#define THREAD_CLF_SAVED_SHIFT 4 +#define THREAD_CLF_CURR_SHIFT 0 +#define THREAD_CLF_MASK 0xf +#define THREAD_CLF_TMP_SHIFT 0 +#define THREAD_CLF_ABORT_SHIFT 1 +#define THREAD_CLF_IRQ_SHIFT 2 +#define THREAD_CLF_FIQ_SHIFT 3 + +#define THREAD_CLF_TMP BIT(THREAD_CLF_TMP_SHIFT) +#define THREAD_CLF_ABORT BIT(THREAD_CLF_ABORT_SHIFT) +#define THREAD_CLF_IRQ BIT(THREAD_CLF_IRQ_SHIFT) +#define THREAD_CLF_FIQ BIT(THREAD_CLF_FIQ_SHIFT) + +#ifndef __ASSEMBLER__ +extern const void *stack_tmp_export; +extern const uint32_t stack_tmp_stride; +extern struct thread_ctx threads[]; +extern struct thread_core_local thread_core_local[]; + +#ifdef CFG_WITH_STACK_CANARIES +#define STACK_CANARY_SIZE (4 * sizeof(long)) +#else +#define STACK_CANARY_SIZE 0 +#endif + +/* Checks stack canaries */ +void thread_check_canaries(void); + +void thread_lock_global(void); +void thread_unlock_global(void); + +/* Frees the cache of allocated FS RPC memory */ +void thread_rpc_shm_cache_clear(struct thread_shm_cache *cache); +#endif /*__ASSEMBLER__*/ +#endif /*__KERNEL_THREAD_PRIVATE_H*/ diff --git a/optee/optee_os/core/include/kernel/time_source.h b/optee/optee_os/core/include/kernel/time_source.h new file mode 100644 index 0000000..fce5391 --- /dev/null +++ b/optee/optee_os/core/include/kernel/time_source.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#include + +struct time_source { + const char *name; + uint32_t protection_level; + TEE_Result (*get_sys_time)(TEE_Time *time); +}; +void time_source_init(void); + +#define REGISTER_TIME_SOURCE(source) \ + void time_source_init(void) { \ + _time_source = source; \ + } + +extern struct time_source _time_source; diff --git a/optee/optee_os/core/include/kernel/timer.h b/optee/optee_os/core/include/kernel/timer.h new file mode 100644 index 0000000..8aaca44 --- /dev/null +++ b/optee/optee_os/core/include/kernel/timer.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2018, Linaro Limited + */ + +#ifndef __TIMER_H +#define __TIMER_H + +void generic_timer_start(uint32_t time_ms); +void generic_timer_stop(void); + +/* Handler for timer expiry interrupt */ +void generic_timer_handler(uint32_t time_ms); + +#endif /* __TIMER_H */ diff --git a/optee/optee_os/core/include/kernel/tpm.h b/optee/optee_os/core/include/kernel/tpm.h new file mode 100644 index 0000000..6e053b3 --- /dev/null +++ b/optee/optee_os/core/include/kernel/tpm.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2020-2022, ARM Limited. All rights reserved. + */ + +#ifndef __KERNEL_TPM_H__ +#define __KERNEL_TPM_H__ + +#include + +#ifdef CFG_CORE_TPM_EVENT_LOG + +/* + * Returns the TPM Event Log information previously retrieved + * by @tpm_map_log_area. + * + * @buf Pointer to a buffer where to store a copy of the TPM Event log. + */ +TEE_Result tpm_get_event_log(void *buf, size_t *size); + +TEE_Result tpm_get_event_log_size(size_t *size); + +/* + * Reads the TPM Event log information and store it internally. + * If support for DTB is enabled, it will read the parameters there. + * Otherwise, it will use the constant parameters hardcoded in conf.mk. + * + * @fdt Pointer to the DTB blob where the TPM Event log information + * is expected to be. + */ +void tpm_map_log_area(void *fdt); + +#else + +static inline TEE_Result tpm_get_event_log(void *buf __unused, + size_t *size __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result tpm_get_event_log_size(size_t *size __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline void tpm_map_log_area(void *fdt __unused) +{} + +#endif /* CFG_CORE_TPM_EVENT_LOG */ + +#endif /* __KERNEL_TPM_H__ */ diff --git a/optee/optee_os/core/include/kernel/trace_ta.h b/optee/optee_os/core/include/kernel/trace_ta.h new file mode 100644 index 0000000..44644e6 --- /dev/null +++ b/optee/optee_os/core/include/kernel/trace_ta.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ +#ifndef TRACE_TA_H +#define TRACE_TA_H + +#include + +/* Macros to trace TA related events, logs, TA crash info etc */ +#ifdef CFG_TEE_CORE_TA_TRACE +#define TAMSG(...) EMSG(__VA_ARGS__) +#define TAMSG_RAW(...) EMSG_RAW(__VA_ARGS__) +#else +#define TAMSG(...) +#define TAMSG_RAW(...) +#endif + +#endif /*TRACE_TA_H*/ + diff --git a/optee/optee_os/core/include/kernel/ts_manager.h b/optee/optee_os/core/include/kernel/ts_manager.h new file mode 100644 index 0000000..e12b177 --- /dev/null +++ b/optee/optee_os/core/include/kernel/ts_manager.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2017-2020, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#ifndef __KERNEL_TS_MANAGER_H +#define __KERNEL_TS_MANAGER_H + +#include +#include + +struct ts_ctx { + TEE_UUID uuid; + const struct ts_ops *ops; +}; + +struct thread_scall_regs; +struct ts_session { + TAILQ_ENTRY(ts_session) link_tsd; + struct ts_ctx *ctx; /* Generic TS context */ +#if defined(CFG_TA_GPROF_SUPPORT) + struct sample_buf *sbuf; /* Profiling data (PC sampling) */ +#endif +#if defined(CFG_FTRACE_SUPPORT) + struct ftrace_buf *fbuf; /* ftrace buffer */ +#endif + /* + * Used by PTAs to store session specific information, or used by ldelf + * syscalls to store handlers of opened TA/SP binaries. + */ + void *user_ctx; + bool (*handle_scall)(struct thread_scall_regs *regs); +}; + +enum ts_gprof_status { + TS_GPROF_SUSPEND, + TS_GPROF_RESUME, +}; + +struct ts_ops { + TEE_Result (*enter_open_session)(struct ts_session *s); + TEE_Result (*enter_invoke_cmd)(struct ts_session *s, uint32_t cmd); + void (*enter_close_session)(struct ts_session *s); +#if defined(CFG_TA_STATS) + TEE_Result (*dump_mem_stats)(struct ts_session *s); +#endif + void (*dump_state)(struct ts_ctx *ctx); + void (*dump_ftrace)(struct ts_ctx *ctx); + void (*destroy)(struct ts_ctx *ctx); + uint32_t (*get_instance_id)(struct ts_ctx *ctx); + bool (*handle_scall)(struct thread_scall_regs *regs); +#ifdef CFG_TA_GPROF_SUPPORT + void (*gprof_set_status)(enum ts_gprof_status status); +#endif +}; + +struct ts_session *ts_get_current_session(void); +struct ts_session *ts_get_current_session_may_fail(void); + +void ts_push_current_session(struct ts_session *sess); +struct ts_session *ts_pop_current_session(void); +struct ts_session *ts_get_calling_session(void); + +#endif /*__KERNEL_TS_MANAGER_H*/ diff --git a/optee/optee_os/core/include/kernel/ts_store.h b/optee/optee_os/core/include/kernel/ts_store.h new file mode 100644 index 0000000..49c62c3 --- /dev/null +++ b/optee/optee_os/core/include/kernel/ts_store.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2019, Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ +#ifndef __KERNEL_TS_STORE_H +#define __KERNEL_TS_STORE_H + +#include + +struct ts_store_handle; +struct ts_store_ops { + /* + * Human-readable string to describe where the TS comes from. + * For debug purposes only. + */ + const char *description; + /* + * Open a TS. Does not guarantee that the TS is valid or even exists. + */ + TEE_Result (*open)(const TEE_UUID *uuid, + struct ts_store_handle **h); + /* + * Return the size of the unencrypted TS binary, that is: the TS + * header (struct ta_head or sp_head) plus the ELF data. + */ + TEE_Result (*get_size)(const struct ts_store_handle *h, + size_t *size); + + /* + * Return the tag or hash of the TS binary. Used to uniquely + * identify the binary also if the binary happens to be updated. + */ + TEE_Result (*get_tag)(const struct ts_store_handle *h, + uint8_t *tag, unsigned int *tag_len); + /* + * Read the TS sequentially, from the start of the TS header (struct + * ta_head or sp_head) up to the end of the ELF. + * The TEE core is expected to read *exactly* get_size() bytes in total + * unless an error occurs. Therefore, an implementation may rely on the + * condition (current offset == total size) to detect the last call to + * this function. + * @data: pointer to secure memory where the TS bytes should be copied. + * If @data == NULL and @len != 0, the function should just skip @len + * bytes. + */ + TEE_Result (*read)(struct ts_store_handle *h, void *data, + size_t len); + /* + * Close a TS handle. Do nothing if @h == NULL. + */ + void (*close)(struct ts_store_handle *h); +}; + +/* + * Registers a TA storage. + * + * A TA is loaded from the first TA storage in which the TA can be found. + * TA storage is searched in order of priority, where lower values are + * tried first. + * + * Note prio must be unique per storage in order to avoid dependency on + * registration order. This is enforced by a deliberate linker error in + * case of conflict. + * + * Also note that TA storage is sorted lexicographically instead of + * numerically. + */ +#define REGISTER_TA_STORE(prio) \ + int __tee_ta_store_##prio __unused; \ + SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(ta_stores, prio, \ + struct ts_store_ops) + +/* + * Registers a SP storage. + * + * The SP store is separate from the TA store. The user of the stores knows if + * it needs to access the TA store or if it needs to access the SP one. + */ +#define REGISTER_SP_STORE(prio) \ + int __tee_sp_store_##prio __unused; \ + SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(sp_stores, prio, \ + struct ts_store_ops) +#endif /*__KERNEL_TS_STORE_H*/ diff --git a/optee/optee_os/core/include/kernel/unwind.h b/optee/optee_os/core/include/kernel/unwind.h new file mode 100644 index 0000000..9a01b46 --- /dev/null +++ b/optee/optee_os/core/include/kernel/unwind.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/*- + * Copyright (c) 2015-2019 Linaro Limited + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ + +#ifndef KERNEL_UNWIND +#define KERNEL_UNWIND + +#include + +#if defined(CFG_UNWIND) && (TRACE_LEVEL > 0) +void print_kernel_stack(void); +#else +static inline void print_kernel_stack(void) +{ +} +#endif + +#ifdef CFG_UNWIND +/* Get current call stack as an array allocated on the heap */ +vaddr_t *unw_get_kernel_stack(void); +#else +static inline void *unw_get_kernel_stack(void) +{ + return NULL; +} +#endif /* CFG_UNWIND */ + +#endif /*KERNEL_UNWIND*/ diff --git a/optee/optee_os/core/include/kernel/user_access.h b/optee/optee_os/core/include/kernel/user_access.h new file mode 100644 index 0000000..ad20bac --- /dev/null +++ b/optee/optee_os/core/include/kernel/user_access.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ +#ifndef __KERNEL_USER_ACCESS_H +#define __KERNEL_USER_ACCESS_H + +#include +#include +#include + +#ifdef CFG_WITH_USER_TA +TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len); +TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len); +#else +static inline TEE_Result copy_from_user_private(void *kaddr __unused, + const void *uaddr __unused, + size_t len __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +static inline TEE_Result copy_from_user(void *kaddr __unused, + const void *uaddr __unused, + size_t len __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +#endif + +TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len); +TEE_Result copy_to_user(void *uaddr, const void *kaddr, size_t len); + +TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr); + +uint32_t kaddr_to_uref(void *kaddr); +vaddr_t uref_to_vaddr(uint32_t uref); +static inline void *uref_to_kaddr(uint32_t uref) +{ + return (void *)uref_to_vaddr(uref); +} + +#endif /*__KERNEL_USER_ACCESS_H*/ diff --git a/optee/optee_os/core/include/kernel/user_mode_ctx.h b/optee/optee_os/core/include/kernel/user_mode_ctx.h new file mode 100644 index 0000000..6d65d14 --- /dev/null +++ b/optee/optee_os/core/include/kernel/user_mode_ctx.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2021, Arm Limited + */ + +#ifndef __KERNEL_USER_MODE_CTX_H +#define __KERNEL_USER_MODE_CTX_H + +#include +#include +#include +#include +#include +#include + +static inline bool is_user_mode_ctx(struct ts_ctx *ctx) +{ + return is_user_ta_ctx(ctx) || is_stmm_ctx(ctx) || is_sp_ctx(ctx); +} + +static inline struct user_mode_ctx *to_user_mode_ctx(struct ts_ctx *ctx) +{ + if (is_user_ta_ctx(ctx)) + return &to_user_ta_ctx(ctx)->uctx; + else if (is_sp_ctx(ctx)) + return &to_sp_ctx(ctx)->uctx; + else + return &to_stmm_ctx(ctx)->uctx; +} + +void user_mode_ctx_print_mappings(struct user_mode_ctx *umctx); + +#endif /*__KERNEL_USER_MODE_CTX_H*/ diff --git a/optee/optee_os/core/include/kernel/user_mode_ctx_struct.h b/optee/optee_os/core/include/kernel/user_mode_ctx_struct.h new file mode 100644 index 0000000..e2c7ca0 --- /dev/null +++ b/optee/optee_os/core/include/kernel/user_mode_ctx_struct.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2021, Linaro Limited + * Copyright (c) 2020-2023, Arm Limited + */ + +#ifndef __KERNEL_USER_MODE_CTX_STRUCT_H +#define __KERNEL_USER_MODE_CTX_STRUCT_H + +#include +#include +#include + +/* + * struct user_mode_ctx - user mode context + * @vm_info: Virtual memory map of this context + * @regions: Memory regions registered by pager + * @vfp: State of VFP registers + * @keys: Pointer authentication keys + * @ts_ctx: Generic TS context + * @entry_func: Entry address in TS + * @dump_entry_func: Entry address in TS for dumping address mappings + * and stack trace + * @ftrace_entry_func: Entry address in ldelf for dumping ftrace data + * @dl_entry_func: Entry address in ldelf for dynamic linking + * @ldelf_stack_ptr: Stack pointer used for dumping address mappings and + * stack trace + * @is_32bit: True if 32-bit TS, false if 64-bit TS + * @is_initializing: True if TS is not fully loaded + * @stack_ptr: Stack pointer + */ +struct user_mode_ctx { + struct vm_info vm_info; + struct vm_paged_region_head *regions; + struct pgt_cache pgt_cache; +#if defined(CFG_WITH_VFP) + struct thread_user_vfp_state vfp; +#endif +#if defined(CFG_TA_PAUTH) + struct thread_pauth_keys keys; +#endif + struct ts_ctx *ts_ctx; + uaddr_t entry_func; + uaddr_t load_addr; + uaddr_t dump_entry_func; +#ifdef CFG_FTRACE_SUPPORT + uaddr_t ftrace_entry_func; +#endif + uaddr_t dl_entry_func; + uaddr_t ldelf_stack_ptr; + bool is_32bit; + bool is_initializing; + vaddr_t stack_ptr; +}; +#endif /*__KERNEL_USER_MODE_CTX_STRUCT_H*/ + diff --git a/optee/optee_os/core/include/kernel/user_ta.h b/optee/optee_os/core/include/kernel/user_ta.h new file mode 100644 index 0000000..eaff2fc --- /dev/null +++ b/optee/optee_os/core/include/kernel/user_ta.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ +#ifndef KERNEL_USER_TA_H +#define KERNEL_USER_TA_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); +SLIST_HEAD(load_seg_head, load_seg); + +/* + * struct user_ta_ctx - user TA context + * @open_sessions: List of sessions opened by this TA + * @cryp_states: List of cryp states created by this TA + * @objects: List of storage objects opened by this TA + * @storage_enums: List of storage enumerators opened by this TA + * @ta_time_offs: Time reference used by the TA + * @uctx: Generic user mode context + * @ctx: Generic TA context + */ +struct user_ta_ctx { + struct tee_ta_session_head open_sessions; + struct tee_cryp_state_head cryp_states; + struct tee_obj_head objects; + struct tee_storage_enum_head storage_enums; + void *ta_time_offs; + struct user_mode_ctx uctx; + struct tee_ta_ctx ta_ctx; +}; + +#ifdef CFG_WITH_USER_TA +bool is_user_ta_ctx(struct ts_ctx *ctx); +#else +static inline bool is_user_ta_ctx(struct ts_ctx *ctx __unused) +{ + return false; +} +#endif + +static inline struct user_ta_ctx *to_user_ta_ctx(struct ts_ctx *ctx) +{ + assert(is_user_ta_ctx(ctx)); + return container_of(ctx, struct user_ta_ctx, ta_ctx.ts_ctx); +} + +#ifdef CFG_WITH_USER_TA +TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid, + struct tee_ta_session *s); +#else +static inline TEE_Result tee_ta_init_user_ta_session( + const TEE_UUID *uuid __unused, + struct tee_ta_session *s __unused) +{ + return TEE_ERROR_ITEM_NOT_FOUND; +} +#endif + + +#endif /*KERNEL_USER_TA_H*/ diff --git a/optee/optee_os/core/include/kernel/virtualization.h b/optee/optee_os/core/include/kernel/virtualization.h new file mode 100644 index 0000000..6ae9511 --- /dev/null +++ b/optee/optee_os/core/include/kernel/virtualization.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, EPAM Systems. All rights reserved. */ + +#ifndef KERNEL_VIRTUALIZATION_H +#define KERNEL_VIRTUALIZATION_H + +#include +#include +#include +#include + +#define HYP_CLNT_ID 0 + +#if defined(CFG_NS_VIRTUALIZATION) +/** + * virt_guest_created() - create new VM partition + * @guest_id: VM id provided by hypervisor + * + * This function is called by hypervisor (via fast SMC) + * when hypervisor creates new guest VM, so OP-TEE + * can prepare partition for that VM + */ +TEE_Result virt_guest_created(uint16_t guest_id); + +/** + * virt_guest_destroyed() - destroy existing VM partition + * @guest_id: VM id provided by hypervisor + * + * This function is called by hypervisor (via fast SMC) + * when hypervisor is ready to destroy guest VM. Hypervisor + * must ensure that there are no ongoing calls from this + * VM right now. + */ +TEE_Result virt_guest_destroyed(uint16_t guest_id); + +/** + * virt_set_guest() - set guest VM context for current core + * @guest_id: VM id provided by hypervisor + * + * This function switches memory partitions, so TEE part of + * OP-TEE will see memory associated with current guest. + * It should be called on entry to OP-TEE + */ +TEE_Result virt_set_guest(uint16_t guest_id); + +/** + * virt_unset_guest() - set default memory partition + * + * This function should be called upon leaving OP-TEE, + * to switch to default memory partition, so all TEE-specific + * memory will be unmapped. This is safety measure to ensure + * that TEE memory is untouched when there is no active VM. + */ +void virt_unset_guest(void); + +/** + * virt_on_stdcall() - std call hook + * + * This hook is called on every std call, but really is needed + * only once: to initialize TEE runtime for current guest VM + */ +void virt_on_stdcall(void); + +/* + * Next function are needed because virtualization subsystem manages + * memory in own way. There is no one static memory map, instead + * every guest gets own memory map. + */ + +/** + * virt_init_memory() - initialize memory for virtualization subsystem + * @memory_map: current OP-TEE memory map + * @secmem0_base: base of first secure memory range + * @secmem0_size: size of first secure memory range + * @secmem1_base: base of an eventual second secure memory range, 0 if unused + * @secmem1_size: size of an eventual second secure memory range, 0 if unused + */ +void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base, + paddr_size_t secmem0_size, paddr_t secmem1_base, + paddr_size_t secmem1_size); + +/** + * virt_get_memory_map() - get current memory map + */ +struct tee_mmap_region *virt_get_memory_map(void); + +/** + * virt_get_ta_ram() - get TA RAM mapping for current VM + * @start: beginning of TA RAM returned here + * @end: end of TA RAM returned here + */ +void virt_get_ta_ram(vaddr_t *start, vaddr_t *end); + +#else +static inline TEE_Result virt_guest_created(uint16_t guest_id __unused) +{ return TEE_ERROR_NOT_SUPPORTED; } + +static inline TEE_Result virt_guest_destroyed(uint16_t guest_id __unused) +{ return TEE_ERROR_NOT_SUPPORTED; } + +static inline TEE_Result virt_set_guest(uint16_t guest_id __unused) +{ return TEE_ERROR_NOT_SUPPORTED; } + +static inline void virt_unset_guest(void) { } +static inline void virt_on_stdcall(void) { } +static inline struct tee_mmap_region *virt_get_memory_map(void) { return NULL; } +static inline void +virt_get_ta_ram(vaddr_t *start __unused, vaddr_t *end __unused) { } +static inline void virt_init_memory(struct tee_mmap_region *memory_map __unused, + paddr_t secmem0_base __unused, + paddr_size_t secmem0_size __unused, + paddr_t secmem1_base __unused, + paddr_size_t secmem1_size __unused) { } +#endif /*CFG_NS_VIRTUALIZATION*/ + +#endif /* KERNEL_VIRTUALIZATION_H */ diff --git a/optee/optee_os/core/include/kernel/wait_queue.h b/optee/optee_os/core/include/kernel/wait_queue.h new file mode 100644 index 0000000..a13c02b --- /dev/null +++ b/optee/optee_os/core/include/kernel/wait_queue.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef KERNEL_WAIT_QUEUE_H +#define KERNEL_WAIT_QUEUE_H + +#include +#include + +struct wait_queue_elem; +SLIST_HEAD(wait_queue, wait_queue_elem); + +#define WAIT_QUEUE_INITIALIZER { .slh_first = NULL } + +struct condvar; +struct wait_queue_elem { + short handle; + bool done; + bool wait_read; + struct condvar *cv; + SLIST_ENTRY(wait_queue_elem) link; +}; + +/* + * Initializes a wait queue + */ +void wq_init(struct wait_queue *wq); + +/* + * Initializes a wait queue element and adds it to the wait queue. This + * function is supposed to be called before the lock that protects the + * resource we need to wait for is released. + * + * One call to this function must be followed by one call to wq_wait_final() + * on the same wait queue element. + */ +void wq_wait_init_condvar(struct wait_queue *wq, struct wait_queue_elem *wqe, + struct condvar *cv, bool wait_read); + +static inline void wq_wait_init(struct wait_queue *wq, + struct wait_queue_elem *wqe, bool wait_read) +{ + wq_wait_init_condvar(wq, wqe, NULL, wait_read); +} + +/* Waits for the wait queue element to the awakened. */ +void wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe, + const void *sync_obj, const char *fname, int lineno); + +/* Wakes up the first wait queue element in the wait queue, if there is one */ +void wq_wake_next(struct wait_queue *wq, const void *sync_obj, + const char *fname, int lineno); + +/* Returns true if the wait queue doesn't contain any elements */ +bool wq_is_empty(struct wait_queue *wq); + +void wq_promote_condvar(struct wait_queue *wq, struct condvar *cv, + bool only_one, const void *sync_obj, const char *fname, + int lineno); +bool wq_have_condvar(struct wait_queue *wq, struct condvar *cv); + +#endif /*KERNEL_WAIT_QUEUE_H*/ + diff --git a/optee/optee_os/core/include/mm/core_memprot.h b/optee/optee_os/core/include/mm/core_memprot.h new file mode 100644 index 0000000..5f52237 --- /dev/null +++ b/optee/optee_os/core/include/mm/core_memprot.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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_CACHED, + CORE_MEM_NSEC_SHM, + CORE_MEM_NON_SEC, + CORE_MEM_SEC, + CORE_MEM_TEE_RAM, + CORE_MEM_TA_RAM, + CORE_MEM_SDP_MEM, + CORE_MEM_REG_SHM, + CORE_MEM_DEVICE +}; + +/* 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, (paddr_t)(buf), (len)) + +#define tee_pbuf_is_sec(buf, len) \ + core_pbuf_is(CORE_MEM_SEC, (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)) + +/* + * 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, 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); + +/* + * Translate physical address to virtual address using specified mapping. + * Also tries to find proper mapping which have counterpart translation + * for specified length of data starting from given physical address. + * Len parameter can be set to 1 if caller knows that requested (pa + len) + * doesn`t cross mapping granule boundary. + * Returns NULL on failure or a valid virtual address on success. + */ +void *phys_to_virt(paddr_t pa, enum teecore_memtypes m, size_t len); + +/* + * Translate physical address to virtual address trying MEM_AREA_IO_SEC + * first then MEM_AREA_IO_NSEC if not found. Like phys_to_virt() tries + * to find proper mapping relying on length parameter. + * Returns NULL on failure or a valid virtual address on success. + */ +void *phys_to_virt_io(paddr_t pa, size_t len); + +/* + * Translate virtual address to physical address + * Returns 0 on failure or a valid physical address on success. + */ +paddr_t virt_to_phys(void *va); + +/* + * Return runtime usable address, irrespective of whether + * the MMU is enabled or not. In case of MMU enabled also will be performed + * check for requested amount of data is present in found mapping. + */ +vaddr_t core_mmu_get_va(paddr_t pa, enum teecore_memtypes type, size_t len); + +/* Return true if @va relates to a unpaged section else false */ +bool is_unpaged(void *va); + +struct io_pa_va { + paddr_t pa; + vaddr_t va; +}; + +/* + * Helper function to return a physical or virtual address for a device, + * depending on whether the MMU is enabled or not + * io_pa_or_va() uses secure mapped IO memory if found or fallback to + * non-secure mapped IO memory. + */ +vaddr_t io_pa_or_va_secure(struct io_pa_va *p, size_t len); +vaddr_t io_pa_or_va_nsec(struct io_pa_va *p, size_t len); +vaddr_t io_pa_or_va(struct io_pa_va *p, size_t len); + +#endif /* CORE_MEMPROT_H */ diff --git a/optee/optee_os/core/include/mm/core_mmu.h b/optee/optee_os/core/include/mm/core_mmu.h new file mode 100644 index 0000000..bc1c032 --- /dev/null +++ b/optee/optee_os/core/include/mm/core_mmu.h @@ -0,0 +1,686 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef CORE_MMU_H +#define CORE_MMU_H + +#ifndef __ASSEMBLER__ +#include +#include +#include +#include +#include +#include +#endif + +#include +#include + +/* A small page is the smallest unit of memory that can be mapped */ +#define SMALL_PAGE_SIZE BIT(SMALL_PAGE_SHIFT) +#define SMALL_PAGE_MASK ((paddr_t)SMALL_PAGE_SIZE - 1) + +/* + * PGDIR is the translation table above the translation table that holds + * the pages. + */ +#define CORE_MMU_PGDIR_SIZE BIT(CORE_MMU_PGDIR_SHIFT) +#define CORE_MMU_PGDIR_MASK ((paddr_t)CORE_MMU_PGDIR_SIZE - 1) + +/* TA user space code, data, stack and heap are mapped using this granularity */ +#define CORE_MMU_USER_CODE_SIZE BIT(CORE_MMU_USER_CODE_SHIFT) +#define CORE_MMU_USER_CODE_MASK ((paddr_t)CORE_MMU_USER_CODE_SIZE - 1) + +/* TA user space parameters are mapped using this granularity */ +#define CORE_MMU_USER_PARAM_SIZE BIT(CORE_MMU_USER_PARAM_SHIFT) +#define CORE_MMU_USER_PARAM_MASK ((paddr_t)CORE_MMU_USER_PARAM_SIZE - 1) + +/* + * Identify mapping constraint: virtual base address is the physical start addr. + * If platform did not set some macros, some get default value. + */ +#ifndef TEE_RAM_VA_SIZE +#define TEE_RAM_VA_SIZE CORE_MMU_PGDIR_SIZE +#endif + +#ifndef TEE_LOAD_ADDR +#define TEE_LOAD_ADDR TEE_RAM_START +#endif + +#ifndef STACK_ALIGNMENT +#define STACK_ALIGNMENT (sizeof(long) * U(2)) +#endif + +#ifndef __ASSEMBLER__ +/* + * Memory area type: + * MEM_AREA_END: Reserved, marks the end of a table of mapping areas. + * MEM_AREA_TEE_RAM: core RAM (read/write/executable, secure, reserved to TEE) + * MEM_AREA_TEE_RAM_RX: core private read-only/executable memory (secure) + * MEM_AREA_TEE_RAM_RO: core private read-only/non-executable memory (secure) + * MEM_AREA_TEE_RAM_RW: core private read/write/non-executable memory (secure) + * MEM_AREA_INIT_RAM_RO: init private read-only/non-executable memory (secure) + * MEM_AREA_INIT_RAM_RX: init private read-only/executable memory (secure) + * MEM_AREA_NEX_RAM_RO: nexus private read-only/non-executable memory (secure) + * MEM_AREA_NEX_RAM_RW: nexus private r/w/non-executable memory (secure) + * MEM_AREA_TEE_COHERENT: teecore coherent RAM (secure, reserved to TEE) + * MEM_AREA_TEE_ASAN: core address sanitizer RAM (secure, reserved to TEE) + * MEM_AREA_IDENTITY_MAP_RX: core identity mapped r/o executable memory (secure) + * MEM_AREA_TA_RAM: Secure RAM where teecore loads/exec TA instances. + * MEM_AREA_NSEC_SHM: NonSecure shared RAM between NSec and TEE. + * MEM_AREA_RAM_NSEC: NonSecure RAM storing data + * MEM_AREA_RAM_SEC: Secure RAM storing some secrets + * MEM_AREA_IO_NSEC: NonSecure HW mapped registers + * MEM_AREA_IO_SEC: Secure HW mapped registers + * MEM_AREA_EXT_DT: Memory loads external device tree + * MEM_AREA_RES_VASPACE: Reserved virtual memory space + * MEM_AREA_SHM_VASPACE: Virtual memory space for dynamic shared memory buffers + * MEM_AREA_TS_VASPACE: TS va space, only used with phys_to_virt() + * MEM_AREA_DDR_OVERALL: Overall DDR address range, candidate to dynamic shm. + * MEM_AREA_SEC_RAM_OVERALL: Whole secure RAM + * MEM_AREA_MAXTYPE: lower invalid 'type' value + */ +enum teecore_memtypes { + MEM_AREA_END = 0, + MEM_AREA_TEE_RAM, + MEM_AREA_TEE_RAM_RX, + MEM_AREA_TEE_RAM_RO, + MEM_AREA_TEE_RAM_RW, + MEM_AREA_INIT_RAM_RO, + MEM_AREA_INIT_RAM_RX, + MEM_AREA_NEX_RAM_RO, + MEM_AREA_NEX_RAM_RW, + MEM_AREA_TEE_COHERENT, + MEM_AREA_TEE_ASAN, + MEM_AREA_IDENTITY_MAP_RX, + MEM_AREA_TA_RAM, + MEM_AREA_NSEC_SHM, + MEM_AREA_RAM_NSEC, + MEM_AREA_RAM_SEC, + MEM_AREA_IO_NSEC, + MEM_AREA_IO_SEC, + MEM_AREA_EXT_DT, + MEM_AREA_RES_VASPACE, + MEM_AREA_SHM_VASPACE, + MEM_AREA_TS_VASPACE, + MEM_AREA_PAGER_VASPACE, + MEM_AREA_SDP_MEM, + MEM_AREA_DDR_OVERALL, + MEM_AREA_SEC_RAM_OVERALL, + MEM_AREA_MAXTYPE +}; + +static inline const char *teecore_memtype_name(enum teecore_memtypes type) +{ + static const char * const names[] = { + [MEM_AREA_END] = "END", + [MEM_AREA_TEE_RAM] = "TEE_RAM_RWX", + [MEM_AREA_TEE_RAM_RX] = "TEE_RAM_RX", + [MEM_AREA_TEE_RAM_RO] = "TEE_RAM_RO", + [MEM_AREA_TEE_RAM_RW] = "TEE_RAM_RW", + [MEM_AREA_INIT_RAM_RO] = "INIT_RAM_RO", + [MEM_AREA_INIT_RAM_RX] = "INIT_RAM_RX", + [MEM_AREA_NEX_RAM_RO] = "NEX_RAM_RO", + [MEM_AREA_NEX_RAM_RW] = "NEX_RAM_RW", + [MEM_AREA_TEE_ASAN] = "TEE_ASAN", + [MEM_AREA_IDENTITY_MAP_RX] = "IDENTITY_MAP_RX", + [MEM_AREA_TEE_COHERENT] = "TEE_COHERENT", + [MEM_AREA_TA_RAM] = "TA_RAM", + [MEM_AREA_NSEC_SHM] = "NSEC_SHM", + [MEM_AREA_RAM_NSEC] = "RAM_NSEC", + [MEM_AREA_RAM_SEC] = "RAM_SEC", + [MEM_AREA_IO_NSEC] = "IO_NSEC", + [MEM_AREA_IO_SEC] = "IO_SEC", + [MEM_AREA_EXT_DT] = "EXT_DT", + [MEM_AREA_RES_VASPACE] = "RES_VASPACE", + [MEM_AREA_SHM_VASPACE] = "SHM_VASPACE", + [MEM_AREA_TS_VASPACE] = "TS_VASPACE", + [MEM_AREA_PAGER_VASPACE] = "PAGER_VASPACE", + [MEM_AREA_SDP_MEM] = "SDP_MEM", + [MEM_AREA_DDR_OVERALL] = "DDR_OVERALL", + [MEM_AREA_SEC_RAM_OVERALL] = "SEC_RAM_OVERALL", + }; + + COMPILE_TIME_ASSERT(ARRAY_SIZE(names) == MEM_AREA_MAXTYPE); + return names[type]; +} + +#ifdef CFG_CORE_RWDATA_NOEXEC +#define MEM_AREA_TEE_RAM_RW_DATA MEM_AREA_TEE_RAM_RW +#else +#define MEM_AREA_TEE_RAM_RW_DATA MEM_AREA_TEE_RAM +#endif + +struct core_mmu_phys_mem { + const char *name; + enum teecore_memtypes type; + __extension__ union { +#if __SIZEOF_LONG__ != __SIZEOF_PADDR__ + struct { + uint32_t lo_addr; + uint32_t hi_addr; + }; +#endif + paddr_t addr; + }; + __extension__ union { +#if __SIZEOF_LONG__ != __SIZEOF_PADDR__ + struct { + uint32_t lo_size; + uint32_t hi_size; + }; +#endif + paddr_size_t size; + }; +}; + +#define __register_memory(_name, _type, _addr, _size, _section) \ + SCATTERED_ARRAY_DEFINE_ITEM(_section, struct core_mmu_phys_mem) = \ + { .name = (_name), .type = (_type), .addr = (_addr), \ + .size = (_size) } + +#if __SIZEOF_LONG__ != __SIZEOF_PADDR__ +#define __register_memory_ul(_name, _type, _addr, _size, _section) \ + SCATTERED_ARRAY_DEFINE_ITEM(_section, struct core_mmu_phys_mem) = \ + { .name = (_name), .type = (_type), .lo_addr = (_addr), \ + .lo_size = (_size) } +#else +#define __register_memory_ul(_name, _type, _addr, _size, _section) \ + __register_memory(_name, _type, _addr, _size, _section) +#endif + +#define register_phys_mem(type, addr, size) \ + __register_memory(#addr, (type), (addr), (size), \ + phys_mem_map) + +#define register_phys_mem_ul(type, addr, size) \ + __register_memory_ul(#addr, (type), (addr), (size), \ + phys_mem_map) + +/* Same as register_phys_mem() but with PGDIR_SIZE granularity */ +#define register_phys_mem_pgdir(type, addr, size) \ + __register_memory(#addr, type, ROUNDDOWN(addr, CORE_MMU_PGDIR_SIZE), \ + ROUNDUP(size + addr - \ + ROUNDDOWN(addr, CORE_MMU_PGDIR_SIZE), \ + CORE_MMU_PGDIR_SIZE), phys_mem_map) + +#ifdef CFG_SECURE_DATA_PATH +#define register_sdp_mem(addr, size) \ + __register_memory(#addr, MEM_AREA_SDP_MEM, (addr), (size), \ + phys_sdp_mem) +#else +#define register_sdp_mem(addr, size) \ + static int CONCAT(__register_sdp_mem_unused, __COUNTER__) \ + __unused +#endif + +/* register_dynamic_shm() is deprecated, please use register_ddr() instead */ +#define register_dynamic_shm(addr, size) \ + __register_memory(#addr, MEM_AREA_DDR_OVERALL, (addr), (size), \ + phys_ddr_overall_compat) + +/* + * register_ddr() - Define a memory range + * @addr: Base address + * @size: Length + * + * This macro can be used multiple times to define disjoint ranges. While + * initializing holes are carved out of these ranges where it overlaps with + * special memory, for instance memory registered with register_sdp_mem(). + * + * The memory that remains is accepted as non-secure shared memory when + * communicating with normal world. + * + * This macro is an alternative to supply the memory description with a + * devicetree blob. + */ +#define register_ddr(addr, size) \ + __register_memory(#addr, MEM_AREA_DDR_OVERALL, (addr), \ + (size), phys_ddr_overall) + +#define phys_ddr_overall_begin \ + SCATTERED_ARRAY_BEGIN(phys_ddr_overall, struct core_mmu_phys_mem) + +#define phys_ddr_overall_end \ + SCATTERED_ARRAY_END(phys_ddr_overall, struct core_mmu_phys_mem) + +#define phys_ddr_overall_compat_begin \ + SCATTERED_ARRAY_BEGIN(phys_ddr_overall_compat, struct core_mmu_phys_mem) + +#define phys_ddr_overall_compat_end \ + SCATTERED_ARRAY_END(phys_ddr_overall_compat, struct core_mmu_phys_mem) + +#define phys_sdp_mem_begin \ + SCATTERED_ARRAY_BEGIN(phys_sdp_mem, struct core_mmu_phys_mem) + +#define phys_sdp_mem_end \ + SCATTERED_ARRAY_END(phys_sdp_mem, struct core_mmu_phys_mem) + +#define phys_mem_map_begin \ + SCATTERED_ARRAY_BEGIN(phys_mem_map, struct core_mmu_phys_mem) + +#define phys_mem_map_end \ + SCATTERED_ARRAY_END(phys_mem_map, struct core_mmu_phys_mem) + +#ifdef CFG_CORE_RESERVED_SHM +/* Default NSec shared memory allocated from NSec world */ +extern unsigned long default_nsec_shm_paddr; +extern unsigned long default_nsec_shm_size; +#endif + +/* + * Physical load address of OP-TEE updated during boot if needed to reflect + * the value used. + */ +#ifdef CFG_CORE_PHYS_RELOCATABLE +extern unsigned long core_mmu_tee_load_pa; +#else +extern const unsigned long core_mmu_tee_load_pa; +#endif + +void core_init_mmu_map(unsigned long seed, struct core_mmu_config *cfg); +void core_init_mmu_regs(struct core_mmu_config *cfg); + +/* Arch specific function to help optimizing 1 MMU xlat table */ +bool core_mmu_prefer_tee_ram_at_top(paddr_t paddr); + +/* + * struct mmu_partition - stores MMU partition. + * + * Basically it represent whole MMU mapping. It is possible + * to create multiple partitions, and change them in runtime, + * effectively changing how OP-TEE sees memory. + * This is opaque struct which is defined differently for + * v7 and LPAE MMUs + * + * This structure used mostly when virtualization is enabled. + * When CFG_NS_VIRTUALIZATION==n only default partition exists. + */ +struct mmu_partition; + +/* + * core_mmu_get_user_va_range() - Return range of user va space + * @base: Lowest user virtual address + * @size: Size in bytes of user address space + */ +void core_mmu_get_user_va_range(vaddr_t *base, size_t *size); + +/* + * enum core_mmu_fault - different kinds of faults + * @CORE_MMU_FAULT_ALIGNMENT: alignment fault + * @CORE_MMU_FAULT_DEBUG_EVENT: debug event + * @CORE_MMU_FAULT_TRANSLATION: translation fault + * @CORE_MMU_FAULT_WRITE_PERMISSION: Permission fault during write + * @CORE_MMU_FAULT_READ_PERMISSION: Permission fault during read + * @CORE_MMU_FAULT_ASYNC_EXTERNAL: asynchronous external abort + * @CORE_MMU_FAULT_ACCESS_BIT: access bit fault + * @CORE_MMU_FAULT_TAG_CHECK: tag check fault + * @CORE_MMU_FAULT_OTHER: Other/unknown fault + */ +enum core_mmu_fault { + CORE_MMU_FAULT_ALIGNMENT, + CORE_MMU_FAULT_DEBUG_EVENT, + CORE_MMU_FAULT_TRANSLATION, + CORE_MMU_FAULT_WRITE_PERMISSION, + CORE_MMU_FAULT_READ_PERMISSION, + CORE_MMU_FAULT_ASYNC_EXTERNAL, + CORE_MMU_FAULT_ACCESS_BIT, + CORE_MMU_FAULT_TAG_CHECK, + CORE_MMU_FAULT_OTHER, +}; + +/* + * core_mmu_get_fault_type() - get fault type + * @fault_descr: Content of fault status or exception syndrome register + * @returns an enum describing the content of fault status register. + */ +enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr); + +/* + * core_mm_type_to_attr() - convert memory type to attribute + * @t: memory type + * @returns an attribute that can be passed to core_mm_set_entry() and friends + */ +uint32_t core_mmu_type_to_attr(enum teecore_memtypes t); + +/* + * core_mmu_create_user_map() - Create user mode mapping + * @uctx: Pointer to user mode context + * @map: MMU configuration to use when activating this VA space + */ +void core_mmu_create_user_map(struct user_mode_ctx *uctx, + struct core_mmu_user_map *map); +/* + * core_mmu_get_user_map() - Reads current MMU configuration for user VA space + * @map: MMU configuration for current user VA space. + */ +void core_mmu_get_user_map(struct core_mmu_user_map *map); + +/* + * core_mmu_set_user_map() - Set new MMU configuration for user VA space + * @map: User context MMU configuration or NULL to set core VA space + * + * Activate user VA space mapping and set its ASID if @map is not NULL, + * otherwise activate core mapping and set ASID to 0. + */ +void core_mmu_set_user_map(struct core_mmu_user_map *map); + +/* + * struct core_mmu_table_info - Properties for a translation table + * @table: Pointer to translation table + * @va_base: VA base address of the transaltion table + * @level: Translation table level + * @shift: The shift of each entry in the table + * @num_entries: Number of entries in this table. + */ +struct core_mmu_table_info { + void *table; + vaddr_t va_base; + unsigned level; + unsigned shift; + unsigned num_entries; +#ifdef CFG_NS_VIRTUALIZATION + struct mmu_partition *prtn; +#endif +}; + +/* + * core_mmu_find_table() - Locates a translation table + * @prtn: MMU partition where search should be performed + * @va: Virtual address for the table to cover + * @max_level: Don't traverse beyond this level + * @tbl_info: Pointer to where to store properties. + * @return true if a translation table was found, false on error + */ +bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va, + unsigned max_level, + struct core_mmu_table_info *tbl_info); + +/* + * core_mmu_entry_to_finer_grained() - divide mapping at current level into + * smaller ones so memory can be mapped with finer granularity + * @tbl_info: table where target record located + * @idx: index of record for which a pdgir must be setup. + * @secure: true/false if pgdir maps secure/non-secure memory (32bit mmu) + * @return true on successful, false on error + */ +bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info, + unsigned int idx, bool secure); + +void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx, + paddr_t pa, uint32_t attr); + +void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info); + +/* + * core_mmu_set_entry() - Set entry in translation table + * @tbl_info: Translation table properties + * @idx: Index of entry to update + * @pa: Physical address to assign entry + * @attr: Attributes to assign entry + */ +void core_mmu_set_entry(struct core_mmu_table_info *tbl_info, unsigned idx, + paddr_t pa, uint32_t attr); + +void core_mmu_get_entry_primitive(const void *table, size_t level, size_t idx, + paddr_t *pa, uint32_t *attr); + +/* + * core_mmu_get_entry() - Get entry from translation table + * @tbl_info: Translation table properties + * @idx: Index of entry to read + * @pa: Physical address is returned here if pa is not NULL + * @attr: Attributues are returned here if attr is not NULL + */ +void core_mmu_get_entry(struct core_mmu_table_info *tbl_info, unsigned idx, + paddr_t *pa, uint32_t *attr); + +/* + * core_mmu_va2idx() - Translate from virtual address to table index + * @tbl_info: Translation table properties + * @va: Virtual address to translate + * @returns index in transaltion table + */ +static inline unsigned core_mmu_va2idx(struct core_mmu_table_info *tbl_info, + vaddr_t va) +{ + return (va - tbl_info->va_base) >> tbl_info->shift; +} + +/* + * core_mmu_idx2va() - Translate from table index to virtual address + * @tbl_info: Translation table properties + * @idx: Index to translate + * @returns Virtual address + */ +static inline vaddr_t core_mmu_idx2va(struct core_mmu_table_info *tbl_info, + unsigned idx) +{ + return (idx << tbl_info->shift) + tbl_info->va_base; +} + +/* + * core_mmu_get_block_offset() - Get offset inside a block/page + * @tbl_info: Translation table properties + * @pa: Physical address + * @returns offset within one block of the translation table + */ +static inline size_t core_mmu_get_block_offset( + struct core_mmu_table_info *tbl_info, paddr_t pa) +{ + return pa & ((1 << tbl_info->shift) - 1); +} + +/* + * core_mmu_is_dynamic_vaspace() - Check if memory region belongs to + * empty virtual address space that is used for dymanic mappings + * @mm: memory region to be checked + * @returns result of the check + */ +static inline bool core_mmu_is_dynamic_vaspace(struct tee_mmap_region *mm) +{ + return mm->type == MEM_AREA_RES_VASPACE || + mm->type == MEM_AREA_SHM_VASPACE; +} + +/* + * core_mmu_map_pages() - map list of pages at given virtual address + * @vstart: Virtual address where mapping begins + * @pages: Array of page addresses + * @num_pages: Number of pages + * @memtype: Type of memmory to be mapped + * + * Note: This function asserts that pages are not mapped executeable for + * kernel (privileged) mode. + * + * @returns: TEE_SUCCESS on success, TEE_ERROR_XXX on error + */ +TEE_Result core_mmu_map_pages(vaddr_t vstart, paddr_t *pages, size_t num_pages, + enum teecore_memtypes memtype); + +/* + * core_mmu_map_contiguous_pages() - map range of pages at given virtual address + * @vstart: Virtual address where mapping begins + * @pstart: Physical address of the first page + * @num_pages: Number of pages + * @memtype: Type of memmory to be mapped + * + * Note: This function asserts that pages are not mapped executeable for + * kernel (privileged) mode. + * + * @returns: TEE_SUCCESS on success, TEE_ERROR_XXX on error + */ +TEE_Result core_mmu_map_contiguous_pages(vaddr_t vstart, paddr_t pstart, + size_t num_pages, + enum teecore_memtypes memtype); + +/* + * core_mmu_unmap_pages() - remove mapping at given virtual address + * @vstart: Virtual address where mapping begins + * @num_pages: Number of pages to unmap + */ +void core_mmu_unmap_pages(vaddr_t vstart, size_t num_pages); + +/* + * core_mmu_user_mapping_is_active() - Report if user mapping is active + * @returns true if a user VA space is active, false if user VA space is + * inactive. + */ +bool core_mmu_user_mapping_is_active(void); + +/* + * core_mmu_mattr_is_ok() - Check that supplied mem attributes can be used + * @returns true if the attributes can be used, false if not. + */ +bool core_mmu_mattr_is_ok(uint32_t mattr); + +void core_mmu_get_mem_by_type(enum teecore_memtypes type, vaddr_t *s, + vaddr_t *e); + +enum teecore_memtypes core_mmu_get_type_by_pa(paddr_t pa); + +/* routines to retreive shared mem configuration */ +static inline bool core_mmu_is_shm_cached(void) +{ + return mattr_is_cached(core_mmu_type_to_attr(MEM_AREA_NSEC_SHM)); +} + +TEE_Result core_mmu_remove_mapping(enum teecore_memtypes type, void *addr, + size_t len); +void *core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, + size_t len); + +/* + * core_mmu_find_mapping_exclusive() - Find mapping of specified type and + * length. If more than one mapping of + * specified type is present, NULL will be + * returned. + * @type: memory type + * @len: length in bytes + */ +struct tee_mmap_region * +core_mmu_find_mapping_exclusive(enum teecore_memtypes type, size_t len); + +/* + * tlbi_mva_range() - Invalidate TLB for virtual address range + * @va: start virtual address, must be a multiple of @granule + * @len: length in bytes of range, must be a multiple of @granule + * @granule: granularity of mapping, supported values are + * CORE_MMU_PGDIR_SIZE or SMALL_PAGE_SIZE. This value must + * match the actual mappings. + */ +void tlbi_mva_range(vaddr_t va, size_t len, size_t granule); + +/* + * tlbi_mva_range_asid() - Invalidate TLB for virtual address range for + * a specific ASID + * @va: start virtual address, must be a multiple of @granule + * @len: length in bytes of range, must be a multiple of @granule + * @granule: granularity of mapping, supported values are + * CORE_MMU_PGDIR_SIZE or SMALL_PAGE_SIZE. This value must + * match the actual mappings. + * @asid: Address space identifier + */ +void tlbi_mva_range_asid(vaddr_t va, size_t len, size_t granule, uint32_t asid); + +/* Check cpu mmu enabled or not */ +bool cpu_mmu_enabled(void); + +#ifdef CFG_CORE_DYN_SHM +/* + * Check if platform defines nsec DDR range(s). + * Static SHM (MEM_AREA_NSEC_SHM) is not covered by this API as it is + * always present. + */ +bool core_mmu_nsec_ddr_is_defined(void); + +void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start, + size_t nelems); +#endif + +/* Initialize MMU partition */ +void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm); + +unsigned int asid_alloc(void); +void asid_free(unsigned int asid); + +#ifdef CFG_SECURE_DATA_PATH +/* Alloc and fill SDP memory objects table - table is NULL terminated */ +struct mobj **core_sdp_mem_create_mobjs(void); +#endif + +#ifdef CFG_NS_VIRTUALIZATION +size_t core_mmu_get_total_pages_size(void); +struct mmu_partition *core_alloc_mmu_prtn(void *tables); +void core_free_mmu_prtn(struct mmu_partition *prtn); +void core_mmu_set_prtn(struct mmu_partition *prtn); +void core_mmu_set_default_prtn(void); +void core_mmu_set_default_prtn_tbl(void); +#endif + +void core_mmu_init_virtualization(void); + +/* init some allocation pools */ +void core_mmu_init_ta_ram(void); + +void core_init_mmu(struct tee_mmap_region *mm); + +void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info, + unsigned int level, vaddr_t va_base, void *table); +void core_mmu_populate_user_map(struct core_mmu_table_info *dir_info, + struct user_mode_ctx *uctx); +void core_mmu_map_region(struct mmu_partition *prtn, + struct tee_mmap_region *mm); + +bool arch_va2pa_helper(void *va, paddr_t *pa); + +static inline bool core_mmap_is_end_of_table(const struct tee_mmap_region *mm) +{ + return mm->type == MEM_AREA_END; +} + +static inline bool core_mmu_check_end_pa(paddr_t pa, size_t len) +{ + paddr_t end_pa = 0; + + if (ADD_OVERFLOW(pa, len - 1, &end_pa)) + return false; + return core_mmu_check_max_pa(end_pa); +} + +#ifdef CFG_CORE_PHYS_RELOCATABLE +/* + * core_mmu_set_secure_memory() - set physical secure memory range + * @base: base address of secure memory + * @size: size of secure memory + * + * The physical secure memory range is not known in advance when OP-TEE is + * relocatable, this information must be supplied once during boot before + * the translation tables can be initialized and the MMU enabled. + */ +void core_mmu_set_secure_memory(paddr_t base, size_t size); +#endif + +/* + * core_mmu_get_secure_memory() - get physical secure memory range + * @base: base address of secure memory + * @size: size of secure memory + * + * The physical secure memory range returned covers at least the memory + * range used by OP-TEE Core, but may cover more memory depending on the + * configuration. + */ +void core_mmu_get_secure_memory(paddr_t *base, paddr_size_t *size); + +/* + * core_mmu_get_ta_range() - get physical memory range reserved for TAs + * @base: [out] range base address ref or NULL + * @size: [out] range size ref or NULL + */ +void core_mmu_get_ta_range(paddr_t *base, size_t *size); + +#endif /*__ASSEMBLER__*/ + +#endif /* CORE_MMU_H */ diff --git a/optee/optee_os/core/include/mm/file.h b/optee/optee_os/core/include/mm/file.h new file mode 100644 index 0000000..1879507 --- /dev/null +++ b/optee/optee_os/core/include/mm/file.h @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef __MM_FILE_H +#define __MM_FILE_H + +#include +#include +#include + +/* This is supposed to be large enough to hold any hash or tag used */ +#define FILE_TAG_SIZE TEE_SHA256_HASH_SIZE + +/* + * struct file_slice - one slice of a file + * @fobj: Fobj holding the data of this slice + * @page_offset: Offset in pages into the file where the @fobj is + * located. + */ +struct file_slice { + struct fobj *fobj; + unsigned int page_offset; +}; + +struct file; + +/* + * file_lock() - Lock the file + * @f: File pointer + * + * Waits until the file can be locked and with the file put in locked state. + */ +void file_lock(struct file *f); + +/* + * file_lock() - Try to lock the file without blocking + * @f: File pointer + * + * Returns false if file cannot be locked without blocking. + * Returns true if the file has been put in locked state. + */ +bool file_trylock(struct file *f); + +/* + * file_unlock() - Unlock the file + * @f: File pointer + * + * File must be in locked state. Releases the previous lock and returns. + */ +void file_unlock(struct file *f); + +/* + * file_add_slice() - Add a slice to a file + * @f: File pointer + * @fobj: Fobj holding the data of this slice + * @page_offset: Offset in pages into the file (@f) where the @fobj is + * located. + * + * File must be in locked state. + * + * Returns TEE_SUCCESS on success or a TEE_ERROR_* code on failure. + */ +TEE_Result file_add_slice(struct file *f, struct fobj *fobj, + unsigned int page_offset); + +/* + * file_get() - Increase file reference counter + * @f: File pointer + * + * Returns @f, if @f isn't NULL its reference counter is first increased. + */ +struct file *file_get(struct file *f); + +/* + * file_get_by_tag() - Finds a file based on tag and increase reference counter + * @tag: Tag of the file + * @taglen: Length of @tag + * + * If a file doesn't exist it's created with the supplied tag. + * + * Returns a file with an increased reference counter, or NULL on failure. + */ +struct file *file_get_by_tag(const uint8_t *tag, unsigned int taglen); + +/* + * file_put() - Decrease reference counter of file + * @f: File pointer + * + * If reference counter reaches 0, matching the numbers of file_new() + + * file_get() + file_get_by_tag(), the file is removed with reference + * counters for all contained fobjs decreased. + */ +void file_put(struct file *f); + +/* + * file_find_slice() - Find a slice covering the @page_offset + * @f: File pointer + * @page_offset: Offset that must be covered + * + * File must be in locked state. + * + * If a matching file slice is found it is returned, else NULL is returned. + */ +struct file_slice *file_find_slice(struct file *f, unsigned int page_offset); + +#endif /*__MM_FILE_H*/ + diff --git a/optee/optee_os/core/include/mm/fobj.h b/optee/optee_os/core/include/mm/fobj.h new file mode 100644 index 0000000..1428660 --- /dev/null +++ b/optee/optee_os/core/include/mm/fobj.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2021, Linaro Limited + */ + +#ifndef __MM_FOBJ_H +#define __MM_FOBJ_H + +#include +#include +#include +#include +#include +#include + +/* + * struct fobj - file object storage abstraction + * @ops: Operations pointer + * @num_pages: Number of pages covered + * @refc: Reference counter + */ +struct fobj { + const struct fobj_ops *ops; + unsigned int num_pages; + struct refcount refc; +#ifdef CFG_WITH_PAGER + struct vm_paged_region_head regions; +#endif +}; + +/* + * struct fobj_ops - operations struct for struct fobj + * @free: Frees the @fobj + * @load_page: Loads page with index @page_idx at address @va + * @save_page: Saves page with index @page_idx from address @va + * @get_iv_vaddr: Returns virtual address of tag and IV for the page at + * @page_idx if tag and IV are paged for this fobj + * @get_pa: Returns physical address of page at @page_idx if not paged + */ +struct fobj_ops { + void (*free)(struct fobj *fobj); +#ifdef CFG_WITH_PAGER + TEE_Result (*load_page)(struct fobj *fobj, unsigned int page_idx, + void *va); + TEE_Result (*save_page)(struct fobj *fobj, unsigned int page_idx, + const void *va); + vaddr_t (*get_iv_vaddr)(struct fobj *fobj, unsigned int page_idx); +#endif + paddr_t (*get_pa)(struct fobj *fobj, unsigned int page_idx); +}; + +#ifdef CFG_WITH_PAGER +/* + * fobj_locked_paged_alloc() - Allocate storage which is locked in memory + * @num_pages: Number of pages covered + * + * This object only supports loading pages zero initialized. Saving a page + * will result in an error. + * + * Returns a valid pointer on success or NULL on failure. + */ +struct fobj *fobj_locked_paged_alloc(unsigned int num_pages); + +/* + * fobj_rw_paged_alloc() - Allocate read/write storage + * @num_pages: Number of pages covered + * + * This object supports both load and saving of pages. Pages are zero + * initialized the first time they are loaded. + * + * Returns a valid pointer on success or NULL on failure. + */ +struct fobj *fobj_rw_paged_alloc(unsigned int num_pages); + +/* + * fobj_ro_paged_alloc() - Allocate initialized read-only storage + * @num_pages: Number of pages covered + * @hashes: Hashes to verify the pages + * @store: Clear text data for all pages + * + * This object only support loading pages with an already provided content + * in @store. When a page is loaded it will be verified against an hash in + * @hash. Saving a page will result in an error. + * + * Returns a valid pointer on success or NULL on failure. + */ +struct fobj *fobj_ro_paged_alloc(unsigned int num_pages, void *hashes, + void *store); + +/* + * fobj_ro_reloc_paged_alloc() - Allocate initialized read-only storage with + * relocation + * @num_pages: Number of pages covered + * @hashes: Hashes to verify the pages + * @reloc_offs: Offset from the base address in the relocations in @reloc + * @reloc: Relocation data + * @reloc_len: Length of relocation data + * @store: Clear text data for all pages + * + * This object is like fobj_ro_paged_alloc() above, but in addition the + * relocation information is applied to a populated page. This makes sure + * the offset to which all pages are relocated doesn't leak out to storage. + * + * Returns a valid pointer on success or NULL on failure. + */ +struct fobj *fobj_ro_reloc_paged_alloc(unsigned int num_pages, void *hashes, + unsigned int reloc_offs, + const void *reloc, + unsigned int reloc_len, void *store); + +/* + * fobj_load_page() - Load a page into memory + * @fobj: Fobj pointer + * @page_index: Index of page in @fobj + * @va: Address where content should be stored and verified + * + * Returns TEE_SUCCESS on success or TEE_ERROR_* on failure. + */ +static inline TEE_Result fobj_load_page(struct fobj *fobj, + unsigned int page_idx, void *va) +{ + if (fobj) + return fobj->ops->load_page(fobj, page_idx, va); + + return TEE_ERROR_GENERIC; +} + +/* + * fobj_save_page() - Save a page into storage + * @fobj: Fobj pointer + * @page_index: Index of page in @fobj + * @va: Address of the page to store. + * + * Returns TEE_SUCCESS on success or TEE_ERROR_* on failure. + */ +static inline TEE_Result fobj_save_page(struct fobj *fobj, + unsigned int page_idx, const void *va) +{ + if (fobj) + return fobj->ops->save_page(fobj, page_idx, va); + + return TEE_ERROR_GENERIC; +} + +static inline vaddr_t fobj_get_iv_vaddr(struct fobj *fobj, + unsigned int page_idx) +{ + if (fobj && fobj->ops->get_iv_vaddr) + return fobj->ops->get_iv_vaddr(fobj, page_idx); + + return 0; +} +#endif + +/* + * fobj_ta_mem_alloc() - Allocates TA memory + * @num_pages: Number of pages + * + * If paging of user TAs read/write paged fobj is allocated otherwise a + * fobj which uses unpaged secure memory directly. + * + * Returns a valid pointer on success or NULL on failure. + */ +#ifdef CFG_PAGED_USER_TA +#define fobj_ta_mem_alloc(num_pages) fobj_rw_paged_alloc(num_pages) +#else +/* + * fobj_sec_mem_alloc() - Allocates storage directly in secure memory + * @num_pages: Number of pages + * + * Returns a valid pointer on success or NULL on failure. + */ +struct fobj *fobj_sec_mem_alloc(unsigned int num_pages); + +#define fobj_ta_mem_alloc(num_pages) fobj_sec_mem_alloc(num_pages) +#endif + +/* + * fobj_get() - Increase fobj reference count + * @fobj: Fobj pointer + * + * Returns @fobj, if @fobj isn't NULL its reference counter is first + * increased. + */ +static inline struct fobj *fobj_get(struct fobj *fobj) +{ + if (fobj && !refcount_inc(&fobj->refc)) + panic(); + + return fobj; +} + +/* + * fobj_put() - Decrease reference counter of fobj + * @fobj: Fobj pointer + * + * If reference counter reaches 0, matching the numbers of fobj_alloc_*() + + * fobj_get(), the fobj is freed. + */ +static inline void fobj_put(struct fobj *fobj) +{ + if (fobj && refcount_dec(&fobj->refc)) + fobj->ops->free(fobj); +} + +#endif /*__MM_FOBJ_H*/ diff --git a/optee/optee_os/core/include/mm/mobj.h b/optee/optee_os/core/include/mm/mobj.h new file mode 100644 index 0000000..b7d1f70 --- /dev/null +++ b/optee/optee_os/core/include/mm/mobj.h @@ -0,0 +1,325 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, 2022 Linaro Limited + */ + +#ifndef __MM_MOBJ_H +#define __MM_MOBJ_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct mobj { + const struct mobj_ops *ops; + size_t size; + size_t phys_granule; + struct refcount refc; +}; + +struct mobj_ops { + void *(*get_va)(struct mobj *mobj, size_t offs, size_t len); + TEE_Result (*get_pa)(struct mobj *mobj, size_t offs, size_t granule, + paddr_t *pa); + size_t (*get_phys_offs)(struct mobj *mobj, size_t granule); + TEE_Result (*get_mem_type)(struct mobj *mobj, uint32_t *mt); + bool (*matches)(struct mobj *mobj, enum buf_is_attr attr); + void (*free)(struct mobj *mobj); + uint64_t (*get_cookie)(struct mobj *mobj); + struct fobj *(*get_fobj)(struct mobj *mobj); + TEE_Result (*inc_map)(struct mobj *mobj); + TEE_Result (*dec_map)(struct mobj *mobj); +}; + +extern struct mobj mobj_virt; +extern struct mobj *mobj_sec_ddr; +extern struct mobj *mobj_tee_ram_rx; +extern struct mobj *mobj_tee_ram_rw; + +/* + * mobj_get_va() - get virtual address of a mapped mobj + * @mobj: memory object + * @offset: find the va of this offset into @mobj + * @len: how many bytes after @offset that must be valid, can be 1 if + * the caller knows by other means that the expected buffer is + * available. + * + * return a virtual address on success or NULL on error + */ +static inline void *mobj_get_va(struct mobj *mobj, size_t offset, size_t len) +{ + if (mobj && mobj->ops && mobj->ops->get_va) + return mobj->ops->get_va(mobj, offset, len); + return NULL; +} + +static inline TEE_Result mobj_get_pa(struct mobj *mobj, size_t offs, + size_t granule, paddr_t *pa) +{ + if (mobj && mobj->ops && mobj->ops->get_pa) + return mobj->ops->get_pa(mobj, offs, granule, pa); + return TEE_ERROR_GENERIC; +} + +static inline size_t mobj_get_phys_offs(struct mobj *mobj, size_t granule) +{ + if (mobj && mobj->ops && mobj->ops->get_phys_offs) + return mobj->ops->get_phys_offs(mobj, granule); + return 0; +} + +static inline TEE_Result mobj_get_mem_type(struct mobj *mobj, uint32_t *mt) +{ + if (mobj && mobj->ops && mobj->ops->get_mem_type) + return mobj->ops->get_mem_type(mobj, mt); + return TEE_ERROR_GENERIC; +} + +static inline bool mobj_matches(struct mobj *mobj, enum buf_is_attr attr) +{ + if (mobj && mobj->ops && mobj->ops->matches) + return mobj->ops->matches(mobj, attr); + return false; +} + +/** + * mobj_inc_map() - increase map count + * @mobj: pointer to a MOBJ + * + * Maps the MOBJ if it isn't mapped already and increases the map count + * Each call to mobj_inc_map() is supposed to be matches by a call to + * mobj_dec_map(). + * + * Returns TEE_SUCCESS on success or an error code on failure + */ +static inline TEE_Result mobj_inc_map(struct mobj *mobj) +{ + if (mobj && mobj->ops) { + if (mobj->ops->inc_map) + return mobj->ops->inc_map(mobj); + return TEE_SUCCESS; + } + return TEE_ERROR_GENERIC; +} + +/** + * mobj_dec_map() - decrease map count + * @mobj: pointer to a MOBJ + * + * Decreases the map count and also unmaps the MOBJ if the map count + * reaches 0. Each call to mobj_inc_map() is supposed to be matched by a + * call to mobj_dec_map(). + * + * Returns TEE_SUCCESS on success or an error code on failure + */ +static inline TEE_Result mobj_dec_map(struct mobj *mobj) +{ + if (mobj && mobj->ops) { + if (mobj->ops->dec_map) + return mobj->ops->dec_map(mobj); + return TEE_SUCCESS; + } + return TEE_ERROR_GENERIC; +} + +/** + * mobj_get() - get a MOBJ + * @mobj: Pointer to a MOBJ or NULL + * + * Increases reference counter of the @mobj + * + * Returns @mobj with reference counter increased or NULL if @mobj was NULL + */ +static inline struct mobj *mobj_get(struct mobj *mobj) +{ + if (mobj && !refcount_inc(&mobj->refc)) + panic(); + + return mobj; +} + +/** + * mobj_put() - put a MOBJ + * @mobj: Pointer to a MOBJ or NULL + * + * Decreases reference counter of the @mobj and frees it if the counter + * reaches 0. + */ +static inline void mobj_put(struct mobj *mobj) +{ + if (mobj && refcount_dec(&mobj->refc)) + mobj->ops->free(mobj); +} + +/** + * mobj_put_wipe() - wipe and put a MOBJ + * @mobj: Pointer to a MOBJ or NULL + * + * Clears the memory represented by the mobj and then puts it. + */ +static inline void mobj_put_wipe(struct mobj *mobj) +{ + if (mobj) { + void *buf = mobj_get_va(mobj, 0, mobj->size); + + if (buf) + memzero_explicit(buf, mobj->size); + mobj_put(mobj); + } +} + +static inline uint64_t mobj_get_cookie(struct mobj *mobj) +{ + if (mobj && mobj->ops && mobj->ops->get_cookie) + return mobj->ops->get_cookie(mobj); + +#if defined(CFG_CORE_FFA) + return OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; +#else + return 0; +#endif +} + +static inline struct fobj *mobj_get_fobj(struct mobj *mobj) +{ + if (mobj && mobj->ops && mobj->ops->get_fobj) + return mobj->ops->get_fobj(mobj); + + return NULL; +} + +static inline bool mobj_is_nonsec(struct mobj *mobj) +{ + return mobj_matches(mobj, CORE_MEM_NON_SEC); +} + +static inline bool mobj_is_secure(struct mobj *mobj) +{ + return mobj_matches(mobj, CORE_MEM_SEC); +} + +static inline bool mobj_is_sdp_mem(struct mobj *mobj) +{ + return mobj_matches(mobj, CORE_MEM_SDP_MEM); +} + +static inline size_t mobj_get_phys_granule(struct mobj *mobj) +{ + if (mobj->phys_granule) + return mobj->phys_granule; + return mobj->size; +} + +static inline bool mobj_check_offset_and_len(struct mobj *mobj, size_t offset, + size_t len) +{ + size_t end_offs = 0; + + return len && !ADD_OVERFLOW(offset, len - 1, &end_offs) && + end_offs < mobj->size; +} + +struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size, + tee_mm_pool_t *pool); + +struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr, + enum buf_is_attr battr); + +#if defined(CFG_CORE_FFA) +struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, + unsigned int internal_offs); + +TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie); + +/* Functions for SPMC */ +#ifdef CFG_CORE_SEL1_SPMC +struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages); +void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj); +TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie); +#else +struct mobj_ffa *mobj_ffa_spmc_new(uint64_t cookie, unsigned int num_pages); +void mobj_ffa_spmc_delete(struct mobj_ffa *mobj); +#endif + +uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj); +TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx, + paddr_t pa, unsigned int num_pages); +uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mobj); + +#elif defined(CFG_CORE_DYN_SHM) +/* reg_shm represents TEE shared memory */ +struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages, + paddr_t page_offset, uint64_t cookie); + +/** + * mobj_reg_shm_get_by_cookie() - get a MOBJ based on cookie + * @cookie: Cookie used by normal world when suppling the shared memory + * + * Searches for a registered shared memory MOBJ and if one with a matching + * @cookie is found its reference counter is increased before returning + * the MOBJ. + * + * Returns a valid pointer on success or NULL on failure. + */ +struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie); + +TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie); + +/** + * mobj_reg_shm_unguard() - unguards a reg_shm + * @mobj: pointer to a registered shared memory mobj + * + * A registered shared memory mobj is normally guarded against being + * released with mobj_reg_shm_try_release_by_cookie(). After this function + * has returned the mobj can be released by a call to + * mobj_reg_shm_try_release_by_cookie() if the reference counter allows it. + */ +void mobj_reg_shm_unguard(struct mobj *mobj); + +/* + * mapped_shm represents registered shared buffer + * which is mapped into OPTEE va space + */ +struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages, + paddr_t page_offset, uint64_t cookie); +#endif /*CFG_CORE_DYN_SHM*/ + +#if !defined(CFG_CORE_DYN_SHM) +static inline struct mobj *mobj_mapped_shm_alloc(paddr_t *pages __unused, + size_t num_pages __unused, + paddr_t page_offset __unused, + uint64_t cookie __unused) +{ + return NULL; +} + +static inline struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie __unused) +{ + return NULL; +} +#endif + +struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie); + +#ifdef CFG_PAGED_USER_TA +bool mobj_is_paged(struct mobj *mobj); +#else +static inline bool mobj_is_paged(struct mobj *mobj __unused) +{ + return false; +} +#endif + +struct mobj *mobj_seccpy_shm_alloc(size_t size); + +struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file, + uint32_t mem_type); + +#endif /*__MM_MOBJ_H*/ diff --git a/optee/optee_os/core/include/mm/pgt_cache.h b/optee/optee_os/core/include/mm/pgt_cache.h new file mode 100644 index 0000000..13cd9b2 --- /dev/null +++ b/optee/optee_os/core/include/mm/pgt_cache.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ +#ifndef MM_PGT_CACHE_H +#define MM_PGT_CACHE_H + +#ifdef CFG_WITH_LPAE +#define PGT_SIZE (4 * 1024) +#define PGT_NUM_PGT_PER_PAGE 1 +#else +#define PGT_SIZE (1 * 1024) +#define PGT_NUM_PGT_PER_PAGE 4 +#endif + +#include +#include +#include +#include +#include + +struct ts_ctx; + +struct pgt { + void *tbl; + vaddr_t vabase; +#if !defined(CFG_CORE_PREALLOC_EL0_TBLS) + struct ts_ctx *ctx; +#endif + bool populated; +#if defined(CFG_PAGED_USER_TA) + uint16_t num_used_entries; +#endif +#if defined(CFG_CORE_PREALLOC_EL0_TBLS) || \ + (defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE)) + struct pgt_parent *parent; +#endif + SLIST_ENTRY(pgt) link; +}; + +/* + * A proper value for PGT_CACHE_SIZE depends on many factors: CFG_WITH_LPAE, + * CFG_TA_ASLR, size of TA, size of memrefs passed to TA, CFG_ULIBS_SHARED and + * possibly others. The value is based on the number of threads as an indicator + * on how large the system might be. + */ +#if CFG_NUM_THREADS < 2 +#define PGT_CACHE_SIZE 4 +#elif (CFG_NUM_THREADS == 2 && !defined(CFG_WITH_LPAE)) +#define PGT_CACHE_SIZE 8 +#else +#define PGT_CACHE_SIZE ROUNDUP(CFG_NUM_THREADS * 2, PGT_NUM_PGT_PER_PAGE) +#endif + +SLIST_HEAD(pgt_cache, pgt); +struct user_mode_ctx; + +bool pgt_check_avail(struct user_mode_ctx *uctx); + +/* + * pgt_get_all() - makes all needed translation tables available + * @uctx: the context to own the tables + * + * Guaranteed to succeed, but may need to sleep for a while to get all the + * needed translation tables. + */ +#if defined(CFG_CORE_PREALLOC_EL0_TBLS) +static inline void pgt_get_all(struct user_mode_ctx *uctx __unused) { } +#else +void pgt_get_all(struct user_mode_ctx *uctx); +#endif + +/* + * pgt_put_all() - informs the translation table manager that these tables + * will not be needed for a while + * @uctx: the context owning the tables to make inactive + */ +#if defined(CFG_CORE_PREALLOC_EL0_TBLS) +static inline void pgt_put_all(struct user_mode_ctx *uctx __unused) { } +#else +void pgt_put_all(struct user_mode_ctx *uctx); +#endif + +void pgt_clear_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t end); +void pgt_flush_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t last); + +#if defined(CFG_CORE_PREALLOC_EL0_TBLS) +static inline struct pgt *pgt_pop_from_cache_list(vaddr_t vabase __unused, + struct ts_ctx *ctx __unused) +{ return NULL; } +static inline void pgt_push_to_cache_list(struct pgt *pgt __unused) { } +#else +struct pgt *pgt_pop_from_cache_list(vaddr_t vabase, struct ts_ctx *ctx); +void pgt_push_to_cache_list(struct pgt *pgt); +#endif + +#if defined(CFG_CORE_PREALLOC_EL0_TBLS) +static inline void pgt_init(void) { } +#else +void pgt_init(void); +#endif + +void pgt_flush(struct user_mode_ctx *uctx); + +#if defined(CFG_PAGED_USER_TA) +static inline void pgt_inc_used_entries(struct pgt *pgt) +{ + pgt->num_used_entries++; + assert(pgt->num_used_entries); +} + +static inline void pgt_dec_used_entries(struct pgt *pgt) +{ + assert(pgt->num_used_entries); + pgt->num_used_entries--; +} + +static inline void pgt_set_used_entries(struct pgt *pgt, size_t val) +{ + pgt->num_used_entries = val; +} + +#else +static inline void pgt_inc_used_entries(struct pgt *pgt __unused) +{ +} + +static inline void pgt_dec_used_entries(struct pgt *pgt __unused) +{ +} + +static inline void pgt_set_used_entries(struct pgt *pgt __unused, + size_t val __unused) +{ +} + +#endif + +#endif /*MM_PGT_CACHE_H*/ diff --git a/optee/optee_os/core/include/mm/sp_mem.h b/optee/optee_os/core/include/mm/sp_mem.h new file mode 100644 index 0000000..957db36 --- /dev/null +++ b/optee/optee_os/core/include/mm/sp_mem.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2022, Arm Limited. + */ + +#ifndef __MM_SP_MEM_H +#define __MM_SP_MEM_H + +#include +#include +#include + +struct sp_mem; + +/* + * struct sp_mem_receiver - Memory object instance for a FF-A receiver endpoint + * + * @perm: Receiver permission on the shared memory + * @ref_count: Count retrieve requests from endpoint + * @smem: Shared memory reference + * @link: Link in related list + */ +struct sp_mem_receiver { + struct ffa_mem_access_perm perm; + uint8_t ref_count; + struct sp_mem *smem; + + SLIST_ENTRY(sp_mem_receiver) link; +}; + +/* + * sp_mem_map_region represents the memory address when using FF-A shares. + * Instead of storing the physical addresses and the size of the region, we use + * the mobj's which were already used by the SPs. The offset is used to point + * to the specific location inside the mobj memory range. + */ +struct sp_mem_map_region { + struct mobj *mobj; + /* + * Offset (in pages) inside the mobj which is used to retrieve the + * location. + */ + uint32_t page_offset; + uint32_t page_count; + + SLIST_ENTRY(sp_mem_map_region) link; +}; + +SLIST_HEAD(sp_mem_receiver_head, sp_mem_receiver); +SLIST_HEAD(sp_mem_regions_head, sp_mem_map_region); + +/* + * sp_mem is used as the main place to store the FF-A shares information. + * For each FFA_SHARE message a new sp_mem object is created. + * The receivers field is used to store all receiver specific information. + * The regions field is used to store all data needed for retrieving the + * shared addresses. + */ +struct sp_mem { + struct sp_mem_regions_head regions; + struct sp_mem_receiver_head receivers; + /* Data which was passed inside struct ffa_mem_transaction */ + uint16_t sender_id; + uint8_t mem_reg_attr; + uint32_t flags; + uint64_t global_handle; + uint64_t tag; + + SLIST_ENTRY(sp_mem) link; +}; + +struct sp_mem *sp_mem_new(void); +struct sp_mem_receiver *sp_mem_get_receiver(uint32_t s_id, struct sp_mem *smem); +struct sp_mem *sp_mem_get(uint64_t handle); + +bool sp_mem_is_shared(struct sp_mem_map_region *new_reg); +void *sp_mem_get_va(const struct user_mode_ctx *uctx, size_t offset, + struct mobj *mobj); +void sp_mem_remove(struct sp_mem *s_mem); +void sp_mem_add(struct sp_mem *smem); +struct mobj *sp_mem_new_mobj(uint64_t pages, uint32_t mem_type, bool is_secure); +int sp_mem_add_pages(struct mobj *mobj, unsigned int *idx, + paddr_t pa, unsigned int num_pages); +#endif /*__MM_SP_MEM_H*/ diff --git a/optee/optee_os/core/include/mm/tee_mm.h b/optee/optee_os/core/include/mm/tee_mm.h new file mode 100644 index 0000000..481f583 --- /dev/null +++ b/optee/optee_os/core/include/mm/tee_mm.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TEE_MM_H +#define TEE_MM_H + +#include +#include + +/* Define to indicate default pool initiation */ +#define TEE_MM_POOL_NO_FLAGS 0 +/* Flag to indicate that memory is allocated from hi address to low address */ +#define TEE_MM_POOL_HI_ALLOC (1u << 0) +/* Flag to indicate that pool should use nex_malloc instead of malloc */ +#define TEE_MM_POOL_NEX_MALLOC (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; + paddr_t lo; /* low boundary of the pool */ + paddr_size_t size; /* pool size */ + uint32_t flags; /* Config flags for the pool */ + uint8_t shift; /* size shift */ + unsigned int lock; +#ifdef CFG_WITH_STATS + size_t max_allocated; +#endif +}; +typedef struct _tee_mm_pool_t tee_mm_pool_t; + +/* Physical Secure DDR pool */ +extern tee_mm_pool_t tee_mm_sec_ddr; + +/* Virtual eSRAM pool */ +extern tee_mm_pool_t tee_mm_vcore; + +/* Shared memory pool */ +extern tee_mm_pool_t tee_mm_shm; + +/* + * 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, paddr_t addr); + +/* + * Validates that an 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. + * Please take care of stack usage + */ +static inline bool tee_mm_validate(const tee_mm_pool_t *pool, paddr_t addr) +{ + return tee_mm_find(pool, addr) != 0; +} + +/* + * Returns a virtual address to the start of the allocated memory + * for the mm entry. + */ +uintptr_t tee_mm_get_smem(const tee_mm_entry_t *mm); + +/* Init managed memory area */ +bool tee_mm_init(tee_mm_pool_t *pool, paddr_t lo, paddr_size_t size, + 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, size_t size); + +/* Allocate supplied memory range if it's free */ +tee_mm_entry_t *tee_mm_alloc2(tee_mm_pool_t *pool, paddr_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 size_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(const tee_mm_pool_t *pool, paddr_t addr); + +bool tee_mm_is_empty(tee_mm_pool_t *pool); + +#ifdef CFG_WITH_STATS +void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct malloc_stats *stats, + bool reset); +#endif + +#endif diff --git a/optee/optee_os/core/include/mm/tee_mmu_types.h b/optee/optee_os/core/include/mm/tee_mmu_types.h new file mode 100644 index 0000000..9f14100 --- /dev/null +++ b/optee/optee_os/core/include/mm/tee_mmu_types.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2021, Linaro Limited + * Copyright (c) 2022, Arm Limited. + */ +#ifndef TEE_MMU_TYPES_H +#define TEE_MMU_TYPES_H + +#include +#include +#include + +#define TEE_MATTR_VALID_BLOCK BIT(0) +#define TEE_MATTR_TABLE BIT(3) +#define TEE_MATTR_PR BIT(4) +#define TEE_MATTR_PW BIT(5) +#define TEE_MATTR_PX BIT(6) +#define TEE_MATTR_PRW (TEE_MATTR_PR | TEE_MATTR_PW) +#define TEE_MATTR_PRX (TEE_MATTR_PR | TEE_MATTR_PX) +#define TEE_MATTR_PRWX (TEE_MATTR_PRW | TEE_MATTR_PX) +#define TEE_MATTR_UR BIT(7) +#define TEE_MATTR_UW BIT(8) +#define TEE_MATTR_UX BIT(9) +#define TEE_MATTR_URW (TEE_MATTR_UR | TEE_MATTR_UW) +#define TEE_MATTR_URX (TEE_MATTR_UR | TEE_MATTR_UX) +#define TEE_MATTR_URWX (TEE_MATTR_URW | TEE_MATTR_UX) +#define TEE_MATTR_PROT_MASK \ + (TEE_MATTR_PRWX | TEE_MATTR_URWX | TEE_MATTR_GUARDED) +#define TEE_MATTR_DEVICE_PROT_MASK (TEE_MATTR_SECURE | TEE_MATTR_PRW | \ + TEE_MATTR_URW | TEE_MATTR_DEVICE | \ + (TEE_MATTR_MEM_TYPE_DEV << TEE_MATTR_MEM_TYPE_SHIFT)) + +#define TEE_MATTR_GLOBAL BIT(10) +#define TEE_MATTR_SECURE BIT(11) + +#define TEE_MATTR_MEM_TYPE_MASK U(0x7) +#define TEE_MATTR_MEM_TYPE_SHIFT U(12) +/* These are shifted TEE_MATTR_MEM_TYPE_SHIFT */ + +/* + * Device-nGnRnE most restrictive (equivalent to Strongly Ordered memory + * in the ARMv7 architecture). + * https://developer.arm.com/documentation/den0024/a/Memory-Ordering/Memory-types/Device-memory + * + * If an ARMv7 architecture operating system runs on a Cortex-A53 processor, + * the Device memory type matches the nGnRE encoding and the Strongly-Ordered + * memory type matches the nGnRnE memory type. + * https://developer.arm.com/documentation/den0024/a/Memory-Ordering/Memory-types/Device-memory + */ +#define TEE_MATTR_MEM_TYPE_DEV U(0) /* Device-nGnRE */ +#define TEE_MATTR_MEM_TYPE_CACHED U(1) +#define TEE_MATTR_MEM_TYPE_STRONGLY_O U(2) /* Device-nGnRnE */ +#define TEE_MATTR_MEM_TYPE_TAGGED U(3) + +#define TEE_MATTR_GUARDED BIT(15) +#define TEE_MATTR_DEVICE BIT(16) + +/* + * Tags TA mappings which are only used during a single call (open session + * or invoke command parameters). + */ +#define VM_FLAG_EPHEMERAL BIT(0) +/* + * Tags TA mappings that must not be removed (kernel mappings while in user + * mode). + */ +#define VM_FLAG_PERMANENT BIT(1) +/* Tags TA mappings that may be shared with other TAs. */ +#define VM_FLAG_SHAREABLE BIT(2) +/* Tags temporary mappings added to load the ldelf binary */ +#define VM_FLAG_LDELF BIT(3) +/* + * The mapping should only be mapped read-only, not enforced by the vm_* + * functions. + */ +#define VM_FLAG_READONLY BIT(4) + +/* + * Set of flags used by tee_mmu_is_vbuf_inside_ta_private() and + * tee_mmu_is_vbuf_intersect_ta_private() to tell if a certain region is + * mapping TA internal memory or not. + */ +#define VM_FLAGS_NONPRIV (VM_FLAG_EPHEMERAL | \ + VM_FLAG_PERMANENT | \ + VM_FLAG_SHAREABLE) + +struct tee_mmap_region { + unsigned int type; /* enum teecore_memtypes */ + unsigned int region_size; + paddr_t pa; + vaddr_t va; + size_t size; + uint32_t attr; /* TEE_MATTR_* above */ +}; + +struct vm_region { + struct mobj *mobj; + size_t offset; + vaddr_t va; + size_t size; + uint16_t attr; /* TEE_MATTR_* above */ + uint16_t flags; /* VM_FLAGS_* above */ + TAILQ_ENTRY(vm_region) link; +}; + +enum vm_paged_region_type { + PAGED_REGION_TYPE_RO, + PAGED_REGION_TYPE_RW, + PAGED_REGION_TYPE_LOCK, +}; + +struct vm_paged_region { + struct fobj *fobj; + size_t fobj_pgoffs; + enum vm_paged_region_type type; + uint32_t flags; + vaddr_t base; + size_t size; + struct pgt **pgt_array; + TAILQ_ENTRY(vm_paged_region) link; + TAILQ_ENTRY(vm_paged_region) fobj_link; +}; + +TAILQ_HEAD(vm_paged_region_head, vm_paged_region); +TAILQ_HEAD(vm_region_head, vm_region); + +struct vm_info { + struct vm_region_head regions; + unsigned int asid; +}; + +static inline void mattr_perm_to_str(char *str, size_t size, uint32_t attr) +{ + if (size < 7) + return; + + str[0] = (attr & TEE_MATTR_UR) ? 'r' : '-'; + str[1] = (attr & TEE_MATTR_UW) ? 'w' : '-'; + str[2] = (attr & TEE_MATTR_UX) ? 'x' : '-'; + str[3] = (attr & TEE_MATTR_PR) ? 'R' : '-'; + str[4] = (attr & TEE_MATTR_PW) ? 'W' : '-'; + str[5] = (attr & TEE_MATTR_PX) ? 'X' : '-'; + str[6] = '\0'; +} + +static inline bool mattr_is_cached(uint32_t mattr) +{ + uint32_t mem_type = (mattr >> TEE_MATTR_MEM_TYPE_SHIFT) & + TEE_MATTR_MEM_TYPE_MASK; + + return mem_type == TEE_MATTR_MEM_TYPE_CACHED || + mem_type == TEE_MATTR_MEM_TYPE_TAGGED; +} +#endif diff --git a/optee/optee_os/core/include/mm/tee_pager.h b/optee/optee_os/core/include/mm/tee_pager.h new file mode 100644 index 0000000..4e42e64 --- /dev/null +++ b/optee/optee_os/core/include/mm/tee_pager.h @@ -0,0 +1,285 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2021, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef MM_TEE_PAGER_H +#define MM_TEE_PAGER_H + +#include +#include +#include +#include +#include +#include +#include + +/* + * tee_pager_early_init() - Perform early initialization of pager + * + * Panics if some error occurs + */ +void tee_pager_early_init(void); + +/* + * tee_pager_get_table_info() - Fills in table info for address mapped in + * translation table managed by the pager. + * @va: address to look up + * @ti: filled in table info + * + * Returns true if address is in the pager translation tables else false + */ +bool tee_pager_get_table_info(vaddr_t va, struct core_mmu_table_info *ti); + +/* + * tee_pager_phys_to_virt() - Translate physical address to virtual address + * looking in the pager page tables + * @pa: address to translate + * @len: check for length is mapped linearly in CORE_MMU_PGDIR_SIZE range + * + * Returns found virtual address or NULL on error + */ +void *tee_pager_phys_to_virt(paddr_t pa, size_t len); + +/* + * tee_pager_set_alias_area() - Initialize pager alias area + * @mm_alias: The alias area where all physical pages managed by the + * pager are aliased + * + * Panics if called twice or some other error occurs. + */ +void tee_pager_set_alias_area(tee_mm_entry_t *mm_alias); + +/* + * tee_pager_init_iv_region() - Initialized pager region for tags IVs used by RW + * paged fobjs + * @fobj: fobj backing the region + * + * Panics if called twice or some other error occurs. + * + * Returns virtual address of start of IV region. + */ +vaddr_t tee_pager_init_iv_region(struct fobj *fobj); + +/* + * tee_pager_generate_authenc_key() - Generates authenc key for r/w paging + * + * Needs to draw random from RNG, panics if some error occurs. + */ +#ifdef CFG_WITH_PAGER +void tee_pager_generate_authenc_key(void); +#else +static inline void tee_pager_generate_authenc_key(void) +{ +} +#endif + +/* + * tee_pager_add_core_region() - Adds a pageable core region + * @base: base of covered memory region + * @type: type of memory region + * @fobj: fobj backing the region + * + * Non-page aligned base or size will cause a panic. + */ +void tee_pager_add_core_region(vaddr_t base, enum vm_paged_region_type type, + struct fobj *fobj); + +/* + * tee_pager_add_um_region() - Adds a pageable user TA region + * @uctx: user mode context of the region + * @base: base of covered memory region + * @fobj: fobj of the store backing the memory region + * + * The mapping is created suitable to initialize the memory content while + * loading the TA. Once the TA is properly loaded the regions should be + * finalized with tee_pager_set_um_region_attr() to get more strict settings. + * + * Return TEE_SUCCESS on success, anything else if the region can't be added + */ +#ifdef CFG_PAGED_USER_TA +TEE_Result tee_pager_add_um_region(struct user_mode_ctx *uctx, vaddr_t base, + struct fobj *fobj, uint32_t prot); +#else +static inline TEE_Result +tee_pager_add_um_region(struct user_mode_ctx *uctx __unused, + vaddr_t base __unused, struct fobj *fobj __unused, + uint32_t prot __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +/* + * tee_pager_set_um_region_attr() - Set attributes of a initialized memory + * region + * @uctx: user mode context of the region + * @base: base of covered memory region + * @size: size of covered memory region + * @flags: TEE_MATTR_U* flags describing permissions of the region + * + * Return true on success of false if the region can't be updated + */ +#ifdef CFG_PAGED_USER_TA +bool tee_pager_set_um_region_attr(struct user_mode_ctx *uctx, vaddr_t base, + size_t size, uint32_t flags); +#else +static inline bool +tee_pager_set_um_region_attr(struct user_mode_ctx *uctx __unused, + vaddr_t base __unused, size_t size __unused, + uint32_t flags __unused) +{ + return false; +} +#endif + +#ifdef CFG_PAGED_USER_TA +void tee_pager_rem_um_region(struct user_mode_ctx *uctx, vaddr_t base, + size_t size); +#else +static inline void tee_pager_rem_um_region(struct user_mode_ctx *uctx __unused, + vaddr_t base __unused, + size_t size __unused) +{ +} +#endif + +#ifdef CFG_PAGED_USER_TA +TEE_Result tee_pager_split_um_region(struct user_mode_ctx *uctx, vaddr_t va); +#else +static inline TEE_Result +tee_pager_split_um_region(struct user_mode_ctx *uctx __unused, + vaddr_t va __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +#endif +#ifdef CFG_PAGED_USER_TA +void tee_pager_merge_um_region(struct user_mode_ctx *uctx, vaddr_t va, + size_t len); +#else +static inline void +tee_pager_merge_um_region(struct user_mode_ctx *uctx __unused, + vaddr_t va __unused, size_t len __unused) +{ +} +#endif + +/* + * tee_pager_rem_uma_regions() - Remove all user TA regions + * @uctx: user mode context + * + * This function is called when a user mode context is teared down. + */ +#ifdef CFG_PAGED_USER_TA +void tee_pager_rem_um_regions(struct user_mode_ctx *uctx); +#else +static inline void tee_pager_rem_um_regions(struct user_mode_ctx *uctx __unused) +{ +} +#endif + +/* + * tee_pager_assign_um_tables() - Assigns translation table to a user ta + * @uctx: user mode context + * + * This function is called to assign translation tables for the pageable + * regions of a user TA. + */ +#ifdef CFG_PAGED_USER_TA +void tee_pager_assign_um_tables(struct user_mode_ctx *uctx); +#else +static inline void +tee_pager_assign_um_tables(struct user_mode_ctx *uctx __unused) +{ +} +#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(vaddr_t vaddr, size_t npages, bool unmap); + +/* + * tee_pager_alloc() - Allocate read-write virtual memory from pager. + * @size: size of memory in bytes + * + * @return NULL on failure or a pointer to the virtual memory on success. + */ +void *tee_pager_alloc(size_t size); + +#ifdef CFG_PAGED_USER_TA +/* + * tee_pager_pgt_save_and_release_entries() - Save dirty pages to backing store + * and remove physical page from translation table + * @pgt: page table descriptor + * + * This function is called when a translation table needs to be recycled + */ +void tee_pager_pgt_save_and_release_entries(struct pgt *pgt); +#else +static inline void +tee_pager_pgt_save_and_release_entries(struct pgt *pgt __unused) +{ +} +#endif + +/* + * tee_pager_release_phys() - Release physical pages used for mapping + * @addr: virtual address of first page to release + * @size: number of bytes to release + * + * Only pages completely covered by the supplied range are affected. This + * function only supplies a hint to the pager that the physical page can be + * reused. The caller can't expect a released memory range to hold a + * specific bit pattern when used next time. + * + * Note that the virtual memory allocation is still valid after this + * function has returned, it's just the content that may or may not have + * changed. + */ +#ifdef CFG_WITH_PAGER +void tee_pager_release_phys(void *addr, size_t size); +#else +static inline void tee_pager_release_phys(void *addr __unused, + size_t size __unused) +{ +} +#endif + +/* + * Statistics on the pager + */ +struct tee_pager_stats { + size_t hidden_hits; + size_t ro_hits; + size_t rw_hits; + size_t zi_released; + size_t npages; /* number of load pages */ + size_t npages_all; /* number of pages */ +}; + +#ifdef CFG_WITH_PAGER +void tee_pager_get_stats(struct tee_pager_stats *stats); +bool tee_pager_handle_fault(struct abort_info *ai); +#else /*CFG_WITH_PAGER*/ +static inline bool tee_pager_handle_fault(struct abort_info *ai __unused) +{ + return false; +} + +static inline void tee_pager_get_stats(struct tee_pager_stats *stats) +{ + memset(stats, 0, sizeof(struct tee_pager_stats)); +} +#endif /*CFG_WITH_PAGER*/ + +void tee_pager_invalidate_fobj(struct fobj *fobj); + +#endif /*MM_TEE_PAGER_H*/ diff --git a/optee/optee_os/core/include/mm/vm.h b/optee/optee_os/core/include/mm/vm.h new file mode 100644 index 0000000..873c1bd --- /dev/null +++ b/optee/optee_os/core/include/mm/vm.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef TEE_MMU_H +#define TEE_MMU_H + +#include +#include +#include + +/* Allocate context resources like ASID and MMU table information */ +TEE_Result vm_info_init(struct user_mode_ctx *uctx, struct ts_ctx *ts_ctx); + +/* Release context resources like ASID */ +void vm_info_final(struct user_mode_ctx *uctx); + +/* + * Creates a memory map of a mobj. + * Desired virtual address can be specified in @va otherwise @va must be + * initialized to 0 if the next available can be chosen. + * + * @pad_begin and @pad_end specify how much extra free space should be kept + * when establishing the map. This allows mapping the first part of for + * instance an ELF file while knowing that the next part which has to be of + * a certain offset from the first part also will succeed. + */ + +TEE_Result vm_map_pad(struct user_mode_ctx *uctx, vaddr_t *va, size_t len, + uint32_t prot, uint32_t flags, struct mobj *mobj, + size_t offs, size_t pad_begin, size_t pad_end, + size_t align); + +/* + * Creates a memory map of a mobj. + * Desired virtual address can be specified in @va otherwise @va must be + * initialized to 0 if the next available can be chosen. + */ +static inline TEE_Result vm_map(struct user_mode_ctx *uctx, vaddr_t *va, + size_t len, uint32_t prot, uint32_t flags, + struct mobj *mobj, size_t offs) +{ + return vm_map_pad(uctx, va, len, prot, flags, mobj, offs, 0, 0, 0); +} + +TEE_Result vm_remap(struct user_mode_ctx *uctx, vaddr_t *new_va, vaddr_t old_va, + size_t len, size_t pad_begin, size_t pad_end); + +TEE_Result vm_get_flags(struct user_mode_ctx *uctx, vaddr_t va, size_t len, + uint32_t *flags); + +TEE_Result vm_get_prot(struct user_mode_ctx *uctx, vaddr_t va, size_t len, + uint16_t *prot); + +TEE_Result vm_set_prot(struct user_mode_ctx *uctx, vaddr_t va, size_t len, + uint32_t prot); + +TEE_Result vm_unmap(struct user_mode_ctx *uctx, vaddr_t va, size_t len); + +/* Map parameters for a user TA */ +TEE_Result vm_map_param(struct user_mode_ctx *uctx, struct tee_ta_param *param, + void *param_va[TEE_NUM_PARAMS]); +void vm_clean_param(struct user_mode_ctx *uctx); + +/* + * These two functions are deprecated and should only be called from + * mobj_seccpy_shm_alloc() and mobj_seccpy_shm_free(). + */ +TEE_Result vm_add_rwmem(struct user_mode_ctx *uctx, struct mobj *mobj, + vaddr_t *va); +void vm_rem_rwmem(struct user_mode_ctx *uctx, struct mobj *mobj, vaddr_t va); + +/* + * User mode private memory is defined as user mode image static segment + * (code, ro/rw static data, heap, stack). The sole other virtual memory + * mapped to user mode are memref parameters. These later are considered + * outside user mode private memory as it might be accessed by the user + * mode context and its client(s). + */ +bool vm_buf_is_inside_um_private(const struct user_mode_ctx *uctx, + const void *va, size_t size); + +bool vm_buf_intersects_um_private(const struct user_mode_ctx *uctx, + const void *va, size_t size); + +TEE_Result vm_buf_to_mboj_offs(const struct user_mode_ctx *uctx, + const void *va, size_t size, + struct mobj **mobj, size_t *offs); + +/* Helper function for virt_to_phys(), shouldn't be used directly elsewhere */ +TEE_Result vm_va2pa(const struct user_mode_ctx *uctx, void *ua, paddr_t *pa); + +/* Helper function for phys_to_virt(), shouldn't be used directly elsewhere */ +void *vm_pa2va(const struct user_mode_ctx *uctx, paddr_t pa, size_t pa_size); + +/* + * Return TEE_SUCCESS or TEE_ERROR_ACCESS_DENIED when buffer exists or return + * another TEE_Result code. + */ +TEE_Result vm_check_access_rights(const struct user_mode_ctx *uctx, + uint32_t flags, uaddr_t uaddr, size_t len); + +/* Set user context @ctx or core privileged context if @ctx is NULL */ +void vm_set_ctx(struct ts_ctx *ctx); + +struct mobj *vm_get_mobj(struct user_mode_ctx *uctx, vaddr_t va, size_t *len, + uint16_t *prot, size_t *offs); +#endif /*TEE_MMU_H*/ diff --git a/optee/optee_os/core/include/optee_msg.h b/optee/optee_os/core/include/optee_msg.h new file mode 100644 index 0000000..7cc795d --- /dev/null +++ b/optee/optee_os/core/include/optee_msg.h @@ -0,0 +1,345 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2020, Linaro Limited + */ +#ifndef _OPTEE_MSG_H +#define _OPTEE_MSG_H + +#include +#include +#include + +/* + * This file defines the OP-TEE message protocol used to communicate + * with an instance of OP-TEE running in secure world. + */ + +/***************************************************************************** + * Part 1 - formatting of messages + *****************************************************************************/ + +#define OPTEE_MSG_ATTR_TYPE_NONE U(0x0) +#define OPTEE_MSG_ATTR_TYPE_VALUE_INPUT U(0x1) +#define OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT U(0x2) +#define OPTEE_MSG_ATTR_TYPE_VALUE_INOUT U(0x3) +#define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT U(0x5) +#define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT U(0x6) +#define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT U(0x7) +#define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT +#define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT +#define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT +#define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT U(0x9) +#define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT U(0xa) +#define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT U(0xb) + +#define OPTEE_MSG_ATTR_TYPE_MASK GENMASK_32(7, 0) + +/* + * Meta parameter to be absorbed by the Secure OS and not passed + * to the Trusted Application. + * + * Currently only used with OPTEE_MSG_CMD_OPEN_SESSION. + */ +#define OPTEE_MSG_ATTR_META BIT(8) + +/* + * Pointer to a list of pages used to register user-defined SHM buffer. + * Used with OPTEE_MSG_ATTR_TYPE_TMEM_*. + * buf_ptr should point to the beginning of the buffer. Buffer will contain + * list of page addresses. OP-TEE core can reconstruct contiguous buffer from + * that page addresses list. Page addresses are stored as 64 bit values. + * Last entry on a page should point to the next page of buffer. + * Every entry in buffer should point to a 4k page beginning (12 least + * significant bits must be equal to zero). + * + * 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold + * page offset of user buffer. + * + * So, entries should be placed like members of this structure: + * + * struct page_data { + * uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1]; + * uint64_t next_page_data; + * }; + * + * Structure is designed to exactly fit into the page size + * OPTEE_MSG_NONCONTIG_PAGE_SIZE which is a standard 4KB page. + * + * The size of 4KB is chosen because this is the smallest page size for ARM + * architectures. If REE uses larger pages, it should divide them to 4KB ones. + */ +#define OPTEE_MSG_ATTR_NONCONTIG BIT(9) + +/* + * Memory attributes for caching passed with temp memrefs. The actual value + * used is defined outside the message protocol with the exception of + * OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already + * defined for the memory range should be used. If optee_smc.h is used as + * bearer of this protocol OPTEE_SMC_SHM_* is used for values. + */ +#define OPTEE_MSG_ATTR_CACHE_SHIFT U(16) +#define OPTEE_MSG_ATTR_CACHE_MASK GENMASK_32(2, 0) +#define OPTEE_MSG_ATTR_CACHE_PREDEFINED U(0) + +/* + * Same values as TEE_LOGIN_* from TEE Internal API + */ +#define OPTEE_MSG_LOGIN_PUBLIC U(0x00000000) +#define OPTEE_MSG_LOGIN_USER U(0x00000001) +#define OPTEE_MSG_LOGIN_GROUP U(0x00000002) +#define OPTEE_MSG_LOGIN_APPLICATION U(0x00000004) +#define OPTEE_MSG_LOGIN_APPLICATION_USER U(0x00000005) +#define OPTEE_MSG_LOGIN_APPLICATION_GROUP U(0x00000006) + +/* + * Page size used in non-contiguous buffer entries + */ +#define OPTEE_MSG_NONCONTIG_PAGE_SIZE U(4096) + +#define OPTEE_MSG_FMEM_INVALID_GLOBAL_ID 0xffffffffffffffff + +#ifndef __ASSEMBLER__ +/** + * struct optee_msg_param_tmem - temporary memory reference parameter + * @buf_ptr: Address of the buffer + * @size: Size of the buffer + * @shm_ref: Temporary shared memory reference, pointer to a struct tee_shm + * + * Secure and normal world communicates pointers as physical address + * instead of the virtual address. This is because secure and normal world + * have completely independent memory mapping. Normal world can even have a + * hypervisor which need to translate the guest physical address (AKA IPA + * in ARM documentation) to a real physical address before passing the + * structure to secure world. + */ +struct optee_msg_param_tmem { + uint64_t buf_ptr; + uint64_t size; + uint64_t shm_ref; +}; + +/** + * struct optee_msg_param_rmem - registered memory reference parameter + * @offs: Offset into shared memory reference + * @size: Size of the buffer + * @shm_ref: Shared memory reference, pointer to a struct tee_shm + */ +struct optee_msg_param_rmem { + uint64_t offs; + uint64_t size; + uint64_t shm_ref; +}; + +/** + * struct optee_msg_param_fmem - FF-A memory reference parameter + * @offs_lower: Lower bits of offset into shared memory reference + * @offs_upper: Upper bits of offset into shared memory reference + * @internal_offs: Internal offset into the first page of shared memory + * reference + * @size: Size of the buffer + * @global_id: Global identifier of the shared memory + */ +struct optee_msg_param_fmem { + uint32_t offs_low; + uint16_t offs_high; + uint16_t internal_offs; + uint64_t size; + uint64_t global_id; +}; + +/** + * struct optee_msg_param_value - opaque value parameter + * + * Value parameters are passed unchecked between normal and secure world. + */ +struct optee_msg_param_value { + uint64_t a; + uint64_t b; + uint64_t c; +}; + +/** + * struct optee_msg_param - parameter used together with struct optee_msg_arg + * @attr: attributes + * @tmem: parameter by temporary memory reference + * @rmem: parameter by registered memory reference + * @fmem: parameter by FF-A registered memory reference + * @value: parameter by opaque value + * + * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in + * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value, + * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and + * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_FMEM_* indicates + * @rmem or @fmem depending on the conduit. + * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used. + */ +struct optee_msg_param { + uint64_t attr; + union { + struct optee_msg_param_tmem tmem; + struct optee_msg_param_rmem rmem; + struct optee_msg_param_fmem fmem; + struct optee_msg_param_value value; + } u; +}; + +/** + * struct optee_msg_arg - call argument + * @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_* + * @func: Trusted Application function, specific to the Trusted Application, + * used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND + * @session: In parameter for all OPTEE_MSG_CMD_* except + * OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter instead + * @cancel_id: Cancellation id, a unique value to identify this request + * @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 calls to Trusted OS uses this struct. If cmd requires further + * information than what these fields hold it can be passed as a parameter + * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding + * attrs field). All parameters tagged as meta have to come first. + */ +struct optee_msg_arg { + uint32_t cmd; + uint32_t func; + uint32_t session; + uint32_t cancel_id; + uint32_t pad; + uint32_t ret; + uint32_t ret_origin; + uint32_t num_params; + + /* num_params tells the actual number of element in params */ + struct optee_msg_param params[]; +}; + +/** + * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg + * + * @num_params: Number of parameters embedded in the struct optee_msg_arg + * + * Returns the size of the struct optee_msg_arg together with the number + * of embedded parameters. + */ +#define OPTEE_MSG_GET_ARG_SIZE(num_params) \ + (sizeof(struct optee_msg_arg) + \ + sizeof(struct optee_msg_param) * (num_params)) + +/* + * Defines the maximum value of @num_params that can be passed to + * OPTEE_MSG_GET_ARG_SIZE without a risk of crossing page boundary. + */ +#define OPTEE_MSG_MAX_NUM_PARAMS \ + ((OPTEE_MSG_NONCONTIG_PAGE_SIZE - sizeof(struct optee_msg_arg)) / \ + sizeof(struct optee_msg_param)) + +#endif /*__ASSEMBLER__*/ + +/***************************************************************************** + * Part 2 - requests from normal world + *****************************************************************************/ + +/* + * Return the following UID if using API specified in this file without + * further extensions: + * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. + * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1, + * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3. + */ +#define OPTEE_MSG_UID_0 U(0x384fb3e0) +#define OPTEE_MSG_UID_1 U(0xe7f811e3) +#define OPTEE_MSG_UID_2 U(0xaf630002) +#define OPTEE_MSG_UID_3 U(0xa5d5c51b) +#define OPTEE_MSG_FUNCID_CALLS_UID U(0xFF01) + +/* + * Returns 2.0 if using API specified in this file without further + * extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR + * and OPTEE_MSG_REVISION_MINOR + */ +#define OPTEE_MSG_REVISION_MAJOR U(2) +#define OPTEE_MSG_REVISION_MINOR U(0) +#define OPTEE_MSG_FUNCID_CALLS_REVISION U(0xFF03) + +/* + * 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 4 32-bit words in the same way as + * OPTEE_MSG_FUNCID_CALLS_UID described above. + */ +#define OPTEE_MSG_OS_OPTEE_UUID_0 U(0x486178e0) +#define OPTEE_MSG_OS_OPTEE_UUID_1 U(0xe7f811e3) +#define OPTEE_MSG_OS_OPTEE_UUID_2 U(0xbc5e0002) +#define OPTEE_MSG_OS_OPTEE_UUID_3 U(0xa5d5c51b) +#define OPTEE_MSG_FUNCID_GET_OS_UUID U(0x0000) + +/* + * 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 2 32-bit words in the same way as + * OPTEE_MSG_CALLS_REVISION described above. + */ +#define OPTEE_MSG_FUNCID_GET_OS_REVISION U(0x0001) + +/* + * Do a secure call with struct optee_msg_arg as argument + * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd + * + * OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application. + * The first two parameters are tagged as meta, holding two value + * parameters to pass the following information: + * param[0].u.value.a-b uuid of Trusted Application + * param[1].u.value.a-b uuid of Client + * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_* + * + * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened + * session to a Trusted Application. struct optee_msg_arg::func is Trusted + * Application function, specific to the Trusted Application. + * + * OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to + * Trusted Application. + * + * OPTEE_MSG_CMD_CANCEL cancels a currently invoked command. + * + * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The + * information is passed as: + * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + * [| OPTEE_MSG_ATTR_NONCONTIG] + * [in] param[0].u.tmem.buf_ptr physical address (of first fragment) + * [in] param[0].u.tmem.size size (of first fragment) + * [in] param[0].u.tmem.shm_ref holds shared memory reference + * + * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared + * memory reference. The information is passed as: + * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + * [in] param[0].u.rmem.shm_ref holds shared memory reference + * [in] param[0].u.rmem.offs 0 + * [in] param[0].u.rmem.size 0 + * + * OPTEE_MSG_CMD_DO_BOTTOM_HALF does the scheduled bottom half processing + * of a driver. + * + * OPTEE_MSG_CMD_STOP_ASYNC_NOTIF informs secure world that from now is + * normal world unable to process asynchronous notifications. Typically + * used when the driver is shut down. + */ +#define OPTEE_MSG_CMD_OPEN_SESSION U(0) +#define OPTEE_MSG_CMD_INVOKE_COMMAND U(1) +#define OPTEE_MSG_CMD_CLOSE_SESSION U(2) +#define OPTEE_MSG_CMD_CANCEL U(3) +#define OPTEE_MSG_CMD_REGISTER_SHM U(4) +#define OPTEE_MSG_CMD_UNREGISTER_SHM U(5) +#define OPTEE_MSG_CMD_DO_BOTTOM_HALF U(6) +#define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF U(7) +#define OPTEE_MSG_FUNCID_CALL_WITH_ARG U(0x0004) + +#endif /* _OPTEE_MSG_H */ diff --git a/optee/optee_os/core/include/optee_rpc_cmd.h b/optee/optee_os/core/include/optee_rpc_cmd.h new file mode 100644 index 0000000..4e6ce8f --- /dev/null +++ b/optee/optee_os/core/include/optee_rpc_cmd.h @@ -0,0 +1,400 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2021, Linaro Limited + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __OPTEE_RPC_CMD_H +#define __OPTEE_RPC_CMD_H + +/* + * All RPC is done with a struct optee_msg_arg as bearer of information, + * struct optee_msg_arg::arg holds values defined by OPTEE_RPC_CMD_* below. + * Only the commands handled by the kernel driver are defined here. + * + * RPC communication with tee-supplicant is reversed compared to normal + * client communication described above. The supplicant receives requests + * and sends responses. + */ + +/* + * Load a TA into memory + * + * Since the size of the TA isn't known in advance the size of the TA is + * can be queried with a NULL buffer. + * + * [in] value[0].a-b UUID + * [out] memref[1] Buffer with TA + */ +#define OPTEE_RPC_CMD_LOAD_TA U(0) + +/* + * Replay Protected Memory Block access + * + * [in] memref[0] Frames to device + * [out] memref[1] Frames from device + */ +#define OPTEE_RPC_CMD_RPMB U(1) + +/* + * File system access, see definition of protocol below + */ +#define OPTEE_RPC_CMD_FS U(2) + +/* + * Get time + * + * Returns number of seconds and nano seconds since the Epoch, + * 1970-01-01 00:00:00 +0000 (UTC). + * + * [out] value[0].a Number of seconds + * [out] value[0].b Number of nano seconds. + */ +#define OPTEE_RPC_CMD_GET_TIME U(3) + +/* + * Notification from/to secure world. + * + * If secure world needs to wait for something, for instance a mutex, it + * does a notification wait request instead of spinning in secure world. + * Conversely a synchronous notification can be sent when a secure + * world mutex with a thread waiting thread is unlocked. + * + * This interface can also be used to wait for a asynchronous notification + * which instead is sent via a non-secure interrupt. + * + * Waiting on notification + * [in] value[0].a OPTEE_RPC_NOTIFICATION_WAIT + * [in] value[0].b notification value + * + * Sending a synchronous notification + * [in] value[0].a OPTEE_RPC_NOTIFICATION_SEND + * [in] value[0].b notification value + */ +#define OPTEE_RPC_CMD_NOTIFICATION U(4) +#define OPTEE_RPC_NOTIFICATION_WAIT U(0) +#define OPTEE_RPC_NOTIFICATION_SEND U(1) + +/* + * Suspend execution + * + * [in] value[0].a Number of milliseconds to suspend + */ +#define OPTEE_RPC_CMD_SUSPEND U(5) + +/* + * Allocate a piece of shared memory + * + * [in] value[0].a Type of memory one of + * OPTEE_RPC_SHM_TYPE_* below + * [in] value[0].b Requested size + * [in] value[0].c Required alignment + * [out] memref[0] Buffer + */ +#define OPTEE_RPC_CMD_SHM_ALLOC U(6) +/* Memory that can be shared with a non-secure user space application */ +#define OPTEE_RPC_SHM_TYPE_APPL U(0) +/* Memory only shared with non-secure kernel */ +#define OPTEE_RPC_SHM_TYPE_KERNEL U(1) +/* + * Memory shared with non-secure kernel and exported to a non-secure user + * space application + */ +#define OPTEE_RPC_SHM_TYPE_GLOBAL U(2) + +/* + * Free shared memory previously allocated with OPTEE_RPC_CMD_SHM_ALLOC + * + * [in] value[0].a Type of memory one of + * OPTEE_RPC_SHM_TYPE_* above + * [in] value[0].b Value of shared memory reference or cookie + */ +#define OPTEE_RPC_CMD_SHM_FREE U(7) + +/* Was OPTEE_RPC_CMD_SQL_FS, which isn't supported any longer */ +#define OPTEE_RPC_CMD_SQL_FS_RESERVED U(8) + +/* + * Send TA profiling information to normal world + * + * [in/out] value[0].a File identifier. Must be set to 0 on + * first call. A value >= 1 will be + * returned on success. Re-use this value + * to append data to the same file. + * [in] memref[1] TA UUID + * [in] memref[2] Profile data + */ +#define OPTEE_RPC_CMD_GPROF U(9) + +/* + * Socket command, see definition of protocol below + */ +#define OPTEE_RPC_CMD_SOCKET U(10) + +/* + * Send TA function graph data to normal world + * + * [in/out] value[0].a File identifier. Must be set to 0 on + * first call. A value >= 1 will be + * returned on success. Re-use this value + * to append data to the same file. + * [in] memref[1] TA UUID + * [in] memref[2] function graph data + */ +#define OPTEE_RPC_CMD_FTRACE U(11) + +/* + * tee-supplicant plugin command, see definition of protocol below + */ +#define OPTEE_RPC_CMD_SUPP_PLUGIN U(12) + +/* + * NVMe Replay Protected Memory Block access + * + * [in] memref[0] Frames to device + * [out] memref[1] Frames from device + */ +#define OPTEE_RPC_CMD_NVME_RPMB U(13) + +/* + * Register timestamp buffer in the linux kernel optee driver + * + * [in] value[0].a Subcommand (register buffer, unregister buffer) + * [in] value[0].b Physical address of timestamp buffer + * [in] value[0].c Size of buffer + */ +#define OPTEE_RPC_CMD_BENCH_REG U(20) + +/* + * Issue master requests (read and write operations) to an I2C chip. + * + * [in] value[0].a Transfer mode (OPTEE_RPC_I2C_TRANSFER_*) + * [in] value[0].b The I2C bus (a.k.a adapter). + * 16 bit field. + * [in] value[0].c The I2C chip (a.k.a address). + * 16 bit field (either 7 or 10 bit effective). + * [in] value[1].a The I2C master control flags (ie, 10 bit address). + * 16 bit field. + * [in/out] memref[2] Buffer used for data transfers. + * [out] value[3].a Number of bytes transferred by the REE. + */ +#define OPTEE_RPC_CMD_I2C_TRANSFER U(21) + +/* I2C master transfer modes */ +#define OPTEE_RPC_I2C_TRANSFER_RD U(0) +#define OPTEE_RPC_I2C_TRANSFER_WR U(1) + +/* I2C master control flags */ +#define OPTEE_RPC_I2C_FLAGS_TEN_BIT BIT(0) + +/* + * Definition of protocol for command OPTEE_RPC_CMD_FS + */ + +/* + * Open a file + * + * [in] value[0].a OPTEE_RPC_FS_OPEN + * [in] memref[1] A string holding the file name + * [out] value[2].a File descriptor of open file + */ +#define OPTEE_RPC_FS_OPEN U(0) + +/* + * Create a file + * + * [in] value[0].a OPTEE_RPC_FS_CREATE + * [in] memref[1] A string holding the file name + * [out] value[2].a File descriptor of open file + */ +#define OPTEE_RPC_FS_CREATE U(1) + +/* + * Close a file + * + * [in] value[0].a OPTEE_RPC_FS_CLOSE + * [in] value[0].b File descriptor of open file. + */ +#define OPTEE_RPC_FS_CLOSE U(2) + +/* + * Read from a file + * + * [in] value[0].a OPTEE_RPC_FS_READ + * [in] value[0].b File descriptor of open file + * [in] value[0].c Offset into file + * [out] memref[1] Buffer to hold returned data + */ +#define OPTEE_RPC_FS_READ U(3) + +/* + * Write to a file + * + * [in] value[0].a OPTEE_RPC_FS_WRITE + * [in] value[0].b File descriptor of open file + * [in] value[0].c Offset into file + * [in] memref[1] Buffer holding data to be written + */ +#define OPTEE_RPC_FS_WRITE U(4) + +/* + * Truncate a file + * + * [in] value[0].a OPTEE_RPC_FS_TRUNCATE + * [in] value[0].b File descriptor of open file + * [in] value[0].c Length of file. + */ +#define OPTEE_RPC_FS_TRUNCATE U(5) + +/* + * Remove a file + * + * [in] value[0].a OPTEE_RPC_FS_REMOVE + * [in] memref[1] A string holding the file name + */ +#define OPTEE_RPC_FS_REMOVE U(6) + +/* + * Rename a file + * + * [in] value[0].a OPTEE_RPC_FS_RENAME + * [in] value[0].b True if existing target should be removed + * [in] memref[1] A string holding the old file name + * [in] memref[2] A string holding the new file name + */ +#define OPTEE_RPC_FS_RENAME U(7) + +/* + * Opens a directory for file listing + * + * [in] value[0].a OPTEE_RPC_FS_OPENDIR + * [in] memref[1] A string holding the name of the directory + * [out] value[2].a Handle to open directory + */ +#define OPTEE_RPC_FS_OPENDIR U(8) + +/* + * Closes a directory handle + * + * [in] value[0].a OPTEE_RPC_FS_CLOSEDIR + * [in] value[0].b Handle to open directory + */ +#define OPTEE_RPC_FS_CLOSEDIR U(9) + +/* + * Read next file name of directory + * + * + * [in] value[0].a OPTEE_RPC_FS_READDIR + * [in] value[0].b Handle to open directory + * [out] memref[1] A string holding the file name + */ +#define OPTEE_RPC_FS_READDIR U(10) + +/* End of definition of protocol for command OPTEE_RPC_CMD_FS */ + +/* + * Definition of protocol for command OPTEE_RPC_CMD_SOCKET + */ + +#define OPTEE_RPC_SOCKET_TIMEOUT_NONBLOCKING U(0) +#define OPTEE_RPC_SOCKET_TIMEOUT_BLOCKING U(0xffffffff) + +/* + * Open socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_OPEN + * [in] value[0].b TA instance id + * [in] value[1].a Server port number + * [in] value[1].b Protocol, TEE_ISOCKET_PROTOCOLID_* + * [in] value[1].c Ip version TEE_IP_VERSION_* from tee_ipsocket.h + * [in] memref[2] Server address + * [out] value[3].a Socket handle (32-bit) + */ +#define OPTEE_RPC_SOCKET_OPEN U(0) + +/* + * Close socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_CLOSE + * [in] value[0].b TA instance id + * [in] value[0].c Socket handle + */ +#define OPTEE_RPC_SOCKET_CLOSE U(1) + +/* + * Close all sockets + * + * [in] value[0].a OPTEE_RPC_SOCKET_CLOSE_ALL + * [in] value[0].b TA instance id + */ +#define OPTEE_RPC_SOCKET_CLOSE_ALL U(2) + +/* + * Send data on socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_SEND + * [in] value[0].b TA instance id + * [in] value[0].c Socket handle + * [in] memref[1] Buffer to transmit + * [in] value[2].a Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_* + * [out] value[2].b Number of transmitted bytes + */ +#define OPTEE_RPC_SOCKET_SEND U(3) + +/* + * Receive data on socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_RECV + * [in] value[0].b TA instance id + * [in] value[0].c Socket handle + * [out] memref[1] Buffer to receive + * [in] value[2].a Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_* + */ +#define OPTEE_RPC_SOCKET_RECV U(4) + +/* + * Perform IOCTL on socket + * + * [in] value[0].a OPTEE_RPC_SOCKET_IOCTL + * [in] value[0].b TA instance id + * [in] value[0].c Socket handle + * [in/out] memref[1] Buffer + * [in] value[2].a Ioctl command + */ +#define OPTEE_RPC_SOCKET_IOCTL U(5) + +/* End of definition of protocol for command OPTEE_RPC_CMD_SOCKET */ + +/* + * Definition of protocol for command OPTEE_RPC_CMD_SUPP_PLUGIN + */ + +/* + * Invoke tee-supplicant's plugin. + * + * [in] value[0].a OPTEE_RPC_SUPP_PLUGIN_INVOKE + * [in] value[0].b uuid.d1 + * [in] value[0].c uuid.d2 + * [in] value[1].a uuid.d3 + * [in] value[1].b uuid.d4 + * [in] value[1].c cmd for plugin + * [in] value[2].a sub_cmd for plugin + * [out] value[2].b length of the outbuf (memref[3]), if out is needed. + * [in/out] memref[3] buffer holding data for plugin + * + * UUID serialized into octets: + * b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 + * d1 | d2 | d3 | d4 + * + * The endianness of words d1, d2, d3 and d4 must be little-endian. + * d1 word contains [b3 b2 b1 b0] + * d2 word contains [b7 b6 b5 b4] + * d3 word contains [b11 b10 b9 b8] + * d4 word contains [b15 b14 b13 b12] + */ +#define OPTEE_RPC_SUPP_PLUGIN_INVOKE U(0) + +/* End of definition of protocol for command OPTEE_RPC_CMD_SUPP_PLUGIN */ + +#endif /*__OPTEE_RPC_CMD_H*/ diff --git a/optee/optee_os/core/include/rng_support.h b/optee/optee_os/core/include/rng_support.h new file mode 100644 index 0000000..1dc4d89 --- /dev/null +++ b/optee/optee_os/core/include/rng_support.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __RNG_SUPPORT_H__ +#define __RNG_SUPPORT_H__ + +#include + +TEE_Result hw_get_random_bytes(void *buf, size_t blen); + +#endif /* __RNG_SUPPORT_H__ */ diff --git a/optee/optee_os/core/include/scattered_array.h b/optee/optee_os/core/include/scattered_array.h new file mode 100644 index 0000000..1b337de --- /dev/null +++ b/optee/optee_os/core/include/scattered_array.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ +#ifndef __SCATTERED_ARRAY_H +#define __SCATTERED_ARRAY_H + +#include +#include + +/* + * A scattered array is assembled from items declared in different source + * files depending on something like "SORT(.scattered_array*)" in the link + * script to get everything assembled in the right order. + * + * Whenever a new scattered array is created with the macros below there's + * no need to update the link script. + */ + +#define __SCT_ARRAY_DEF_ITEM3(element_type, element_name, section_name) \ + static const element_type element_name; \ + DECLARE_KEEP_INIT(element_name); \ + static const element_type element_name __used \ + __section(section_name) + +#define __SCT_ARRAY_DEF_PG_ITEM3(element_type, element_name, section_name) \ + static const element_type element_name __used \ + __section(section_name) + +#define __SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type) \ + __SCT_ARRAY_DEF_ITEM3(element_type, \ + __scattered_array_ ## id ## array_name, \ + ".scattered_array_" #array_name "_1_" #order) + +#define __SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type) \ + __SCT_ARRAY_DEF_PG_ITEM3(element_type, \ + __scattered_array_ ## id ## array_name, \ + ".scattered_array_" #array_name "_1_" #order) + +#define __SCT_ARRAY_DEF_ITEM1(array_name, order, id, element_type) \ + __SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type) + +#define __SCT_ARRAY_DEF_PG_ITEM1(array_name, order, id, element_type) \ + __SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type) + +/* + * Defines an item in a scattered array, sorted based on @order. + * @array_name: Name of the scattered array + * @order: Tag on which this item is sorted in the array + * @element_type: The type of the elemenet + */ +#define SCATTERED_ARRAY_DEFINE_ITEM_ORDERED(array_name, order, element_type) \ + __SCT_ARRAY_DEF_ITEM1(array_name, order, __COUNTER__, element_type) + +/* + * Same as SCATTERED_ARRAY_DEFINE_ITEM_ORDERED except that references + * to other objects (for instance null terminated strings) are allowed + * to reside in the paged area without residing in the init area + */ +#define SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(array_name, order, \ + element_type) \ + __SCT_ARRAY_DEF_PG_ITEM1(array_name, order, __COUNTER__, element_type) + +/* + * Defines an item in a scattered array + * @array_name: Name of the scattered array + * @element_type: The type of the elemenet + */ +#define SCATTERED_ARRAY_DEFINE_ITEM(array_name, element_type) \ + __SCT_ARRAY_DEF_ITEM1(array_name, 0, __COUNTER__, element_type) + +/* + * Same as SCATTERED_ARRAY_DEFINE_ITEM except that references to other + * objects (for instance null terminated strings) are allowed to reside in + * the paged area without residing in the init area + */ +#define SCATTERED_ARRAY_DEFINE_PG_ITEM(array_name, element_type) \ + __SCT_ARRAY_DEF_PG_ITEM1(array_name, 0, __COUNTER__, element_type) + +/* + * Returns the first element in a scattered array + * @array_name: Name of the scattered array + * @element_type: The type of the elemenet + */ +#define SCATTERED_ARRAY_BEGIN(array_name, element_type) (__extension__({ \ + static const element_type __scattered_array_begin[0] __unused \ + __section(".scattered_array_" #array_name "_0"); \ + \ + (const element_type *)scattered_array_relax_ptr( \ + __scattered_array_begin); \ + })) + +/* + * Returns one entry past the last element in a scattered array + * @array_name: Name of the scattered array + * @element_type: The type of the elemenet + */ +#define SCATTERED_ARRAY_END(array_name, element_type) (__extension__({ \ + static const element_type __scattered_array_end[0] __unused \ + __section(".scattered_array_" #array_name "_2"); \ + \ + __scattered_array_end; \ + })) + +/* + * Loop over all elements in the scattered array + * @elem: Iterator + * @array_name: Name of the scattered array + * @element_type: The type of the elemenet + */ +#define SCATTERED_ARRAY_FOREACH(elem, array_name, element_type) \ + for ((elem) = SCATTERED_ARRAY_BEGIN(array_name, element_type); \ + (elem) < SCATTERED_ARRAY_END(array_name, element_type); (elem)++) + +/* + * scattered_array_relax_ptr() - relax pointer attributes + * @p pointer to return + * + * If the pointer returned from the array __scattered_array_begin[] in + * SCATTERED_ARRAY_BEGIN() is passed directly the compiler may notice that + * it's an empty array and emit warnings. With the address passed via this + * function the compiler will have no such knowledge about the pointer. + * + * Returns supplied pointer. + */ +const void *scattered_array_relax_ptr(const void *p) __attr_const; + +#endif /*__SCATTERED_ARRAY_H*/ + diff --git a/optee/optee_os/core/include/signed_hdr.h b/optee/optee_os/core/include/signed_hdr.h new file mode 100644 index 0000000..edeb446 --- /dev/null +++ b/optee/optee_os/core/include/signed_hdr.h @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef SIGNED_HDR_H +#define SIGNED_HDR_H + +#include +#include +#include +#include + +enum shdr_img_type { + SHDR_TA = 0, + SHDR_BOOTSTRAP_TA = 1, + SHDR_ENCRYPTED_TA = 2, + SHDR_SUBKEY = 3, +}; + +#define SHDR_MAGIC 0x4f545348 + +/** + * struct shdr - signed header + * @magic: magic number must match SHDR_MAGIC + * @img_type: image type, values defined by enum shdr_img_type + * @img_size: image size in bytes + * @algo: algorithm, defined by public key algorithms TEE_ALG_* + * from TEE Internal API specification + * @hash_size: size of the signed hash + * @sig_size: size of the signature + * @hash: hash of an image + * @sig: signature of @hash + */ +struct shdr { + uint32_t magic; + uint32_t img_type; + uint32_t img_size; + uint32_t algo; + uint16_t hash_size; + uint16_t sig_size; + /* + * Commented out element used to visualize the layout dynamic part + * of the struct. + * + * hash is accessed through the macro SHDR_GET_HASH and + * signature is accessed through the macro SHDR_GET_SIG + * + * uint8_t hash[hash_size]; + * uint8_t sig[sig_size]; + */ +}; + +static inline size_t shdr_get_size(const struct shdr *shdr) +{ + size_t s = sizeof(*shdr); + + if (ADD_OVERFLOW(s, shdr->hash_size, &s) || + ADD_OVERFLOW(s, shdr->sig_size, &s)) + return 0; + + return s; +} + +#define SHDR_GET_SIZE(x) shdr_get_size((x)) +#define SHDR_GET_HASH(x) (uint8_t *)(((struct shdr *)(x)) + 1) +#define SHDR_GET_SIG(x) (SHDR_GET_HASH(x) + (x)->hash_size) + +/** + * struct shdr_subkey - subkey header + * @uuid: UUID of the subkey + * @name_size: The size of a name field that follows right + * after this header, before the next signed header. + * @subkey_version: Version of the subkey + * @max_depth: Maximum depth supported below this subkey + * @algo: Algorithm, defined by public key algorithms TEE_ALG_* + * from TEE Internal API specification + * @attr_count: Number of attributes for the public key matching + * @algo. + * @attrs: Attributes for the public key matching @algo. + * @attrs[].id: Attribute ID TEE_ATTR_* from GlobalPlatform + * @attrs[].offs: Offset of the attribute value from start of + * struct shdr_subkey + * @attrs[].size: Attribute size + * + * The @uuid defines UUID URN Namespace (RFC4122), the next UUID after this + * header (another subkey or a TA) must be in the namespace of this UUID. + * This means that further subkeys or TAs have their UUID fixed in the + * hierarchy and cannot be moved up or below another subkey. + * + * If @name_size is non-zero it indicates that a name field of this size + * exists and is used to generate the UUID of the following TA or subkey. + * If it's zero the following TA or subkey must have a matching UUID. + * + * The @subkey_version field is used as a rollback measure. The version is + * checked against earlier saved values of this subkey. If the latest known + * version is less than this the stored value is updated. If the latest + * known version is larger than this then the subkey is refused. + * + * The @max_depth defines how many levels are allowed below this subkey, + * the value 0 means only TAs are allowed below. The value 1 means that + * eventual subkeys below must have the value 0 in their @max_depth field. + * + * Each attribute of @attrs must be within range of the image size of this + * header defined in the preceding struct shdr. + * + * The next struct shdr is found right after the indicated end of the + * previous struct shdr. Signature verification starts over with the + * next struct shdr using this subkey instead of the root key. + */ +struct shdr_subkey { + uint8_t uuid[sizeof(TEE_UUID)]; + uint32_t name_size; + uint32_t subkey_version; + uint32_t max_depth; + uint32_t algo; + uint32_t attr_count; + struct shdr_subkey_attr { + uint32_t id; + uint32_t offs; + uint32_t size; + } attrs[]; +}; + +/** + * struct shdr_bootstrap_ta - bootstrap TA subheader + * @uuid: UUID of the TA + * @ta_version: Version of the TA + */ +struct shdr_bootstrap_ta { + uint8_t uuid[sizeof(TEE_UUID)]; + uint32_t ta_version; +}; + +/** + * struct shdr_encrypted_ta - encrypted TA header + * @enc_algo: authenticated encyption algorithm, defined by symmetric key + * algorithms TEE_ALG_* from TEE Internal API + * specification + * @flags: authenticated encyption flags + * @iv_size: size of the initialization vector + * @tag_size: size of the authentication tag + * @iv: initialization vector + * @tag: authentication tag + */ +struct shdr_encrypted_ta { + uint32_t enc_algo; + uint32_t flags; + uint16_t iv_size; + uint16_t tag_size; + /* + * Commented out element used to visualize the layout dynamic part + * of the struct. + * + * iv is accessed through the macro SHDR_ENC_GET_IV and + * tag is accessed through the macro SHDR_ENC_GET_TAG + * + * uint8_t iv[iv_size]; + * uint8_t tag[tag_size]; + */ +}; + +#define SHDR_ENC_KEY_TYPE_MASK 0x1 + +enum shdr_enc_key_type { + SHDR_ENC_KEY_DEV_SPECIFIC = 0, + SHDR_ENC_KEY_CLASS_WIDE = 1, +}; + +static inline size_t shdr_enc_get_size(const struct shdr_encrypted_ta *ehdr) +{ + size_t s = sizeof(*ehdr); + + if (ADD_OVERFLOW(s, ehdr->iv_size, &s) || + ADD_OVERFLOW(s, ehdr->tag_size, &s)) + return 0; + + return s; +} + +#define SHDR_ENC_GET_SIZE(x) shdr_enc_get_size((x)) +#define SHDR_ENC_GET_IV(x) ((uint8_t *) \ + (((struct shdr_encrypted_ta *)(x)) + 1)) +#define SHDR_ENC_GET_TAG(x) ({ typeof(x) _x = (x); \ + (SHDR_ENC_GET_IV(_x) + _x->iv_size); }) + +/* + * Allocates a struct shdr large enough to hold the entire header, + * excluding a subheader like struct shdr_bootstrap_ta. + */ +struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size); + +/* Frees a previously allocated struct shdr */ +static inline void shdr_free(struct shdr *shdr) +{ + free(shdr); +} + +struct shdr_pub_key { + uint32_t main_algo; + uint8_t uuid[sizeof(TEE_UUID)]; + uint8_t next_uuid[sizeof(TEE_UUID)]; + uint32_t max_depth; + uint32_t name_size; + uint32_t version; + union { + struct rsa_public_key *rsa; + } pub_key; +}; + +TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs, + const uint8_t *ns_img, size_t ns_img_size, + const uint8_t next_uuid[sizeof(TEE_UUID)], + uint32_t max_depth, struct shdr_pub_key *key); +void shdr_free_pub_key(struct shdr_pub_key *key); +TEE_Result shdr_verify_signature2(struct shdr_pub_key *key, + const struct shdr *shdr); + +/* + * Verifies the signature in the @shdr. + * + * Note that the static part of struct shdr and payload still need to be + * checked against the hash contained in the header. + * + * Returns TEE_SUCCESS on success or TEE_ERROR_SECURITY on failure + */ +TEE_Result shdr_verify_signature(const struct shdr *shdr); + +#endif /*SIGNED_HDR_H*/ diff --git a/optee/optee_os/core/include/spi.h b/optee/optee_os/core/include/spi.h new file mode 100644 index 0000000..334b5ed --- /dev/null +++ b/optee/optee_os/core/include/spi.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __SPI_H__ +#define __SPI_H__ + +#include + +enum spi_mode { + SPI_MODE0, + SPI_MODE1, + SPI_MODE2, + SPI_MODE3 +}; + +enum spi_result { + SPI_OK, + SPI_ERR_CFG, + SPI_ERR_PKTCNT, + SPI_ERR_GENERIC +}; + +struct spi_chip { + const struct spi_ops *ops; +}; + +struct spi_ops { + void (*configure)(struct spi_chip *chip); + void (*start)(struct spi_chip *chip); + enum spi_result (*txrx8)(struct spi_chip *chip, uint8_t *wdat, + uint8_t *rdat, size_t num_pkts); + enum spi_result (*txrx16)(struct spi_chip *chip, uint16_t *wdat, + uint16_t *rdat, size_t num_pkts); + void (*end)(struct spi_chip *chip); + void (*flushfifo)(struct spi_chip *chip); +}; + +#endif /* __SPI_H__ */ + diff --git a/optee/optee_os/core/include/ta_pub_key.h b/optee/optee_os/core/include/ta_pub_key.h new file mode 100644 index 0000000..1259e01 --- /dev/null +++ b/optee/optee_os/core/include/ta_pub_key.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef KERNEL_TA_PUB_KEY_H +#define KERNEL_TA_PUB_KEY_H + +#include + +extern const uint32_t ta_pub_key_exponent; +extern const uint8_t ta_pub_key_modulus[]; +extern const size_t ta_pub_key_modulus_size; + +#endif /*KERNEL_TA_PUB_KEY_H*/ + diff --git a/optee/optee_os/core/include/tee/cache.h b/optee/optee_os/core/include/tee/cache.h new file mode 100644 index 0000000..568b251 --- /dev/null +++ b/optee/optee_os/core/include/tee/cache.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef TEE_CACHE_H +#define TEE_CACHE_H + +#include + +TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len); + +#endif /* TEE_CACHE_H */ diff --git a/optee/optee_os/core/include/tee/entry_std.h b/optee/optee_os/core/include/tee/entry_std.h new file mode 100644 index 0000000..d228bad --- /dev/null +++ b/optee/optee_os/core/include/tee/entry_std.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TEE_ENTRY_STD_H +#define TEE_ENTRY_STD_H + +#include +#include +#include + +/* + * Standard call entry, __weak, overridable. If overridden should call + * __tee_entry_std() at the end in order to handle the standard functions. + * + * These functions are called in a normal thread context. + */ +TEE_Result tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params); +TEE_Result __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params); + +/* Get list head for sessions opened from non-secure */ +void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions); + +#endif /* TEE_ENTRY_STD_H */ diff --git a/optee/optee_os/core/include/tee/fs_dirfile.h b/optee/optee_os/core/include/tee/fs_dirfile.h new file mode 100644 index 0000000..a116860 --- /dev/null +++ b/optee/optee_os/core/include/tee/fs_dirfile.h @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __TEE_FS_DIRFILE_H +#define __TEE_FS_DIRFILE_H + +#include +#include + +struct tee_fs_dirfile_dirh; + +/** + * struct tee_fs_dirfile_fileh - file handle + * @file_number: sequence number of a file + * @hash: hash of file, to be supplied to tee_fs_htree_open() + * @idx: index of the file handle in the dirfile + */ +struct tee_fs_dirfile_fileh { + uint32_t file_number; + uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; + int idx; +}; + +/** + * struct tee_fs_dirfile_operations - file interface supplied by user of this + * interface + * @open: opens a file + * @close: closes a file, changes are discarded unless + * @commit_writes is called before + * @read: reads from an open file + * @write: writes to an open file + * @commit_writes: commits changes since the file was opened + */ +struct tee_fs_dirfile_operations { + TEE_Result (*open)(bool create, uint8_t *hash, const TEE_UUID *uuid, + struct tee_fs_dirfile_fileh *dfh, + struct tee_file_handle **fh); + void (*close)(struct tee_file_handle *fh); + TEE_Result (*read)(struct tee_file_handle *fh, size_t pos, + void *buf, size_t *len); + TEE_Result (*write)(struct tee_file_handle *fh, size_t pos, + const void *buf, size_t len); + TEE_Result (*commit_writes)(struct tee_file_handle *fh, uint8_t *hash); +}; + +/** + * tee_fs_dirfile_open() - opens a dirfile handle + * @create: true if a new dirfile is to be created, else the dirfile + * is read opened and verified + * @hash: hash of underlying file + * @fops: file interface + * @dirh: returned dirfile handle + */ +TEE_Result tee_fs_dirfile_open(bool create, uint8_t *hash, + const struct tee_fs_dirfile_operations *fops, + struct tee_fs_dirfile_dirh **dirh); +/** + * tee_fs_dirfile_close() - closes a dirfile handle + * @dirh: dirfile handle + * + * All changes since last call to tee_fs_dirfile_commit_writes() are + * discarded. + */ +void tee_fs_dirfile_close(struct tee_fs_dirfile_dirh *dirh); + +/** + * tee_fs_dirfile_commit_writes() - commit updates of dirfile + * @dirh: dirfile handle + * @hash: hash of underlying file is copied here if not NULL + */ +TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh, + uint8_t *hash); + +/** + * tee_fs_dirfile_get_tmp() - get a temporary file handle + * @dirh: dirfile handle + * @dfh: returned temporary file handle + * + * Note, nothing is queued up as changes to the dirfile with this function. + */ +TEE_Result tee_fs_dirfile_get_tmp(struct tee_fs_dirfile_dirh *dirh, + struct tee_fs_dirfile_fileh *dfh); + +/** + * tee_fs_dirfile_find() - find a file handle + * @dirh: dirfile handle + * @uuid: uuid of requesting TA + * @oid: object id + * @oidlen: length of object id + * @dfh: returned file handle + */ +TEE_Result tee_fs_dirfile_find(struct tee_fs_dirfile_dirh *dirh, + const TEE_UUID *uuid, const void *oid, + size_t oidlen, struct tee_fs_dirfile_fileh *dfh); + +/** + * tee_fs_dirfile_fileh_to_fname() - get string representation of file handle + * @dfh: file handle + * @fname: buffer + * @fnlen: length of buffer, updated to used length + */ +TEE_Result tee_fs_dirfile_fileh_to_fname(const struct tee_fs_dirfile_fileh *dfh, + char *fname, size_t *fnlen); + +/** + * tee_fs_dirfile_rename() - changes/supplies file handle object id + * @dirh: dirfile handle + * @uuid: uuid of requesting TA + * @dfh: file handle + * @oid: object id + * @oidlen: length of object id + * + * If the supplied object id already is used by another file is that file + * removed from the dirfile. + */ +TEE_Result tee_fs_dirfile_rename(struct tee_fs_dirfile_dirh *dirh, + const TEE_UUID *uuid, + struct tee_fs_dirfile_fileh *dfh, + const void *oid, size_t oidlen); + +/** + * tee_fs_dirfile_remove() - remove file + * @dirh: dirfile handle + * @dfh: file handle + */ +TEE_Result tee_fs_dirfile_remove(struct tee_fs_dirfile_dirh *dirh, + const struct tee_fs_dirfile_fileh *dfh); + +/** + * tee_fs_dirfile_update_hash() - update hash of file handle + * @dirh: filefile handle + * @dfh: file handle + */ +TEE_Result tee_fs_dirfile_update_hash(struct tee_fs_dirfile_dirh *dirh, + const struct tee_fs_dirfile_fileh *dfh); + +/** + * tee_fs_dirfile_get_next() - get object id of next file + * @dirh: dirfile handle + * @uuid: uuid of requesting TA + * @idx: pointer to index + * @oid: object id + * @oidlen: length of object id + * + * If @idx contains -1 the first object id is returned, *@idx is updated + * with the index of the file. + */ +TEE_Result tee_fs_dirfile_get_next(struct tee_fs_dirfile_dirh *dirh, + const TEE_UUID *uuid, int *idx, void *oid, + size_t *oidlen); + +#endif /*__TEE_FS_DIRFILE_H*/ diff --git a/optee/optee_os/core/include/tee/fs_htree.h b/optee/optee_os/core/include/tee/fs_htree.h new file mode 100644 index 0000000..1d3b914 --- /dev/null +++ b/optee/optee_os/core/include/tee/fs_htree.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __TEE_FS_HTREE_H +#define __TEE_FS_HTREE_H + +/* + * The purpose of this API is to provide file integrity and confidentiality + * in order to implement secure storage. On-disk data structures are + * duplicated to make updates atomic, an update is finalized to disk with + * tee_fs_htree_sync_to_storage(). + * + * This implementation doesn't provide rollback protection, it only + * guarantees the integrity and confidentiality of the file. + */ + +#include +#include +#include + +#define TEE_FS_HTREE_HASH_SIZE TEE_SHA256_HASH_SIZE +#define TEE_FS_HTREE_IV_SIZE U(16) +#define TEE_FS_HTREE_FEK_SIZE U(16) +#define TEE_FS_HTREE_TAG_SIZE U(16) + +/* Internal struct provided to let the rpc callbacks know the size if needed */ +struct tee_fs_htree_node_image { + /* Note that calc_node_hash() depends on hash first in struct */ + uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; + uint8_t iv[TEE_FS_HTREE_IV_SIZE]; + uint8_t tag[TEE_FS_HTREE_TAG_SIZE]; + uint16_t flags; +}; + +/* + * This struct is not interpreted by the hash tree, it's up to the user of + * the interface to update etc if needed. + */ +struct tee_fs_htree_meta { + uint64_t length; +}; + +/* Internal struct needed by struct tee_fs_htree_image */ +struct tee_fs_htree_imeta { + struct tee_fs_htree_meta meta; + uint32_t max_node_id; +}; + +/* Internal struct provided to let the rpc callbacks know the size if needed */ +struct tee_fs_htree_image { + uint8_t iv[TEE_FS_HTREE_IV_SIZE]; + uint8_t tag[TEE_FS_HTREE_TAG_SIZE]; + uint8_t enc_fek[TEE_FS_HTREE_FEK_SIZE]; + uint8_t imeta[sizeof(struct tee_fs_htree_imeta)]; + uint32_t counter; +}; + +/** + * enum tee_fs_htree_type - type of hash tree element + * @TEE_FS_HTREE_TYPE_HEAD: indicates a struct tee_fs_htree_image + * @TEE_FS_HTREE_TYPE_NODE: indicates a struct tee_fs_htree_node_image + * @TEE_FS_HTREE_TYPE_BLOCK: indicates a data block + */ +enum tee_fs_htree_type { + TEE_FS_HTREE_TYPE_HEAD, + TEE_FS_HTREE_TYPE_NODE, + TEE_FS_HTREE_TYPE_BLOCK, +}; + +struct tee_fs_rpc_operation; + +/** + * struct tee_fs_htree_storage - storage description supplied by user of + * this interface + * @block_size: size of data blocks + * @rpc_read_init: initialize a struct tee_fs_rpc_operation for an RPC read + * operation + * @rpc_write_init: initialize a struct tee_fs_rpc_operation for an RPC + * write operation + * + * The @idx arguments starts counting from 0. The @vers arguments are either + * 0 or 1. The @data arguments is a pointer to a buffer in non-secure shared + * memory where the encrypted data is stored. + */ +struct tee_fs_htree_storage { + size_t block_size; + TEE_Result (*rpc_read_init)(void *aux, struct tee_fs_rpc_operation *op, + enum tee_fs_htree_type type, size_t idx, + uint8_t vers, void **data); + TEE_Result (*rpc_read_final)(struct tee_fs_rpc_operation *op, + size_t *bytes); + TEE_Result (*rpc_write_init)(void *aux, struct tee_fs_rpc_operation *op, + enum tee_fs_htree_type type, size_t idx, + uint8_t vers, void **data); + TEE_Result (*rpc_write_final)(struct tee_fs_rpc_operation *op); +}; + +struct tee_fs_htree; + +/** + * tee_fs_htree_open() - opens/creates a hash tree + * @create: true if a new hash tree is to be created, else the hash tree + * is read in and verified + * @hash: hash of root node, ignored if NULL + * @uuid: uuid of requesting TA, may be NULL if not from a TA + * @stor: storage description + * @stor_aux: auxilary pointer supplied to callbacks in struct + * tee_fs_htree_storage + * @ht: returned hash tree on success + */ +TEE_Result tee_fs_htree_open(bool create, uint8_t *hash, const TEE_UUID *uuid, + const struct tee_fs_htree_storage *stor, + void *stor_aux, struct tee_fs_htree **ht); +/** + * tee_fs_htree_close() - close a hash tree + * @ht: hash tree + */ +void tee_fs_htree_close(struct tee_fs_htree **ht); + +/** + * tee_fs_htree_get_meta() - get a pointer to associated struct + * tee_fs_htree_meta + * @ht: hash tree + */ +struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht); + +/** + * tee_fs_htree_meta_set_dirty() - tell hash tree that meta were modified + */ +void tee_fs_htree_meta_set_dirty(struct tee_fs_htree *ht); + +/** + * tee_fs_htree_sync_to_storage() - synchronize hash tree to storage + * @ht: hash tree + * @hash: hash of root node is copied to this if not NULL + * + * Frees the hash tree and sets *ht to NULL on failure and returns an error code + */ +TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht, + uint8_t *hash); + +/** + * tee_fs_htree_truncate() - truncate a hash tree + * @ht: hash tree + * @block_num: the number of nodes to truncate to + * + * Frees the hash tree and sets *ht to NULL on failure and returns an error code + */ +TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht, size_t block_num); + +/** + * tee_fs_htree_write_block() - encrypt and write a data block to storage + * @ht: hash tree + * @block_num: block number + * @block: pointer to a block of stor->block_size size + * + * Frees the hash tree and sets *ht to NULL on failure and returns an error code + */ +TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht, size_t block_num, + const void *block); +/** + * tee_fs_htree_write_block() - read and decrypt a data block from storage + * @ht: hash tree + * @block_num: block number + * @block: pointer to a block of stor->block_size size + * + * Frees the hash tree and sets *ht to NULL on failure and returns an error code + */ +TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht, size_t block_num, + void *block); + +#endif /*__TEE_FS_HTREE_H*/ diff --git a/optee/optee_os/core/include/tee/svc_cache.h b/optee/optee_os/core/include/tee/svc_cache.h new file mode 100644 index 0000000..a2bccde --- /dev/null +++ b/optee/optee_os/core/include/tee/svc_cache.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef SVC_CACHE_H +#define SVC_CACHE_H + +#include +#include + +#ifdef CFG_CACHE_API +TEE_Result syscall_cache_operation(void *va, size_t len, unsigned long op); +#else +#define syscall_cache_operation syscall_not_supported +#endif + +#endif /*SVC_CACHE_H*/ diff --git a/optee/optee_os/core/include/tee/tadb.h b/optee/optee_os/core/include/tee/tadb.h new file mode 100644 index 0000000..db49193 --- /dev/null +++ b/optee/optee_os/core/include/tee/tadb.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __TEE_TADB_H +#define __TEE_TADB_H + +#include + +struct tee_tadb_ta_write; +struct tee_tadb_ta_read; + +/* + * struct tee_tadb_property + * @uuid: UUID of Trusted Application (TA) or Security Domain (SD) + * @version: Version of TA or SD + * @custom_size:Size of customized properties, prepended to the encrypted + * TA binary + * @bin_size: Size of the binary TA + */ +struct tee_tadb_property { + TEE_UUID uuid; + uint32_t version; + uint32_t custom_size; + uint32_t bin_size; +}; + +struct tee_fs_rpc_operation; + +struct tee_tadb_file_operations { + TEE_Result (*open)(uint32_t file_number, int *fd); + TEE_Result (*create)(uint32_t file_number, int *fd); + void (*close)(int fd); + TEE_Result (*remove)(uint32_t file_number); + + TEE_Result (*read_init)(struct tee_fs_rpc_operation *op, int fd, + size_t pos, uint8_t **data, size_t bytes); + TEE_Result (*read_final)(struct tee_fs_rpc_operation *op, + size_t *bytes); + + TEE_Result (*write_init)(struct tee_fs_rpc_operation *op, int fd, + size_t pos, uint8_t **data, size_t len); + TEE_Result (*write_final)(struct tee_fs_rpc_operation *op); +}; + +TEE_Result tee_tadb_ta_create(const struct tee_tadb_property *property, + struct tee_tadb_ta_write **ta); +TEE_Result tee_tadb_ta_write(struct tee_tadb_ta_write *ta, const void *buf, + size_t len); +void tee_tadb_ta_close_and_delete(struct tee_tadb_ta_write *ta); +TEE_Result tee_tadb_ta_close_and_commit(struct tee_tadb_ta_write *ta); + +TEE_Result tee_tadb_ta_delete(const TEE_UUID *uuid); + +TEE_Result tee_tadb_ta_open(const TEE_UUID *uuid, struct tee_tadb_ta_read **ta); +const struct tee_tadb_property * +tee_tadb_ta_get_property(struct tee_tadb_ta_read *ta); +TEE_Result tee_tadb_get_tag(struct tee_tadb_ta_read *ta, uint8_t *tag, + unsigned int *tag_len); +TEE_Result tee_tadb_ta_read(struct tee_tadb_ta_read *ta, void *buf, + size_t *len); +void tee_tadb_ta_close(struct tee_tadb_ta_read *ta); + + +#endif /*__TEE_TADB_H*/ diff --git a/optee/optee_os/core/include/tee/tee_cryp_concat_kdf.h b/optee/optee_os/core/include/tee/tee_cryp_concat_kdf.h new file mode 100644 index 0000000..49d3348 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_cryp_concat_kdf.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef TEE_CRYP_CONCAT_KDF_H +#define TEE_CRYP_CONCAT_KDF_H + +#include + +TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret, + size_t shared_secret_len, + const uint8_t *other_info, + size_t other_info_len, uint8_t *derived_key, + size_t derived_key_len); + +#endif /* TEE_CRYP_CONCAT_KDF_H */ diff --git a/optee/optee_os/core/include/tee/tee_cryp_hkdf.h b/optee/optee_os/core/include/tee/tee_cryp_hkdf.h new file mode 100644 index 0000000..be0703e --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_cryp_hkdf.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef TEE_CRYP_HKDF_H +#define TEE_CRYP_HKDF_H + +#include + +TEE_Result tee_cryp_hkdf(uint32_t hash_id, const uint8_t *ikm, size_t ikm_len, + const uint8_t *salt, size_t salt_len, + const uint8_t *info, size_t info_len, uint8_t *okm, + size_t okm_len); + +#endif /* TEE_CRYP_HKDF_H */ diff --git a/optee/optee_os/core/include/tee/tee_cryp_pbkdf2.h b/optee/optee_os/core/include/tee/tee_cryp_pbkdf2.h new file mode 100644 index 0000000..81b7beb --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_cryp_pbkdf2.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef TEE_CRYP_PBKDF2_H +#define TEE_CRYP_PBKDF2_H + +#include + +TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password, + size_t password_len, const uint8_t *salt, + size_t salt_len, uint32_t iteration_count, + uint8_t *derived_key, size_t derived_key_len); + +#endif /* TEE_CRYP_PBKDF2_H */ diff --git a/optee/optee_os/core/include/tee/tee_cryp_utl.h b/optee/optee_os/core/include/tee/tee_cryp_utl.h new file mode 100644 index 0000000..98a694a --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_cryp_utl.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ + +#ifndef TEE_CRYP_UTL_H +#define TEE_CRYP_UTL_H + +#include +#include + +TEE_Result tee_alg_get_digest_size(uint32_t algo, size_t *size); +TEE_Result tee_hash_createdigest(uint32_t algo, const uint8_t *data, + size_t datalen, uint8_t *digest, + size_t digestlen); +TEE_Result tee_cipher_get_block_size(uint32_t algo, size_t *size); +TEE_Result tee_do_cipher_update(void *ctx, uint32_t algo, + TEE_OperationMode mode, bool last_block, + const uint8_t *data, size_t len, uint8_t *dst); + +/* + * plat_prng_add_jitter_entropy() - Adds jitter to RNG entropy pool + * @sid: source ID, normally unique per location of the call + * @pnum: pointer where the pool number for this @sid is stored + * + * Note that the supplied @sid controls (CRYPTO_RNG_SRC_IS_QUICK()) whether + * RPC is allowed to be performed or the event just will be queued for later + * consumption. + */ +void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, unsigned int *pnum); + +void plat_rng_init(void); + +#endif diff --git a/optee/optee_os/core/include/tee/tee_fs.h b/optee/optee_os/core/include/tee/tee_fs.h new file mode 100644 index 0000000..14cbd9d --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_fs.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef TEE_FS_H +#define TEE_FS_H + +#include +#include +#include +#include + +#define TEE_FS_NAME_MAX U(350) + +typedef int64_t tee_fs_off_t; +typedef uint32_t tee_fs_mode_t; + +struct tee_fs_dirent { + uint8_t oid[TEE_OBJECT_ID_MAX_LEN]; + size_t oidlen; +}; + +struct tee_fs_dir; +struct tee_file_handle; +struct tee_pobj; + +/* + * tee_fs implements a POSIX like secure file system with GP extension + */ +struct tee_file_operations { + TEE_Result (*open)(struct tee_pobj *po, size_t *size, + struct tee_file_handle **fh); + TEE_Result (*create)(struct tee_pobj *po, bool overwrite, + const void *head, size_t head_size, + const void *attr, size_t attr_size, + const void *data, size_t data_size, + struct tee_file_handle **fh); + void (*close)(struct tee_file_handle **fh); + TEE_Result (*read)(struct tee_file_handle *fh, size_t pos, + void *buf, size_t *len); + TEE_Result (*write)(struct tee_file_handle *fh, size_t pos, + const void *buf, size_t len); + TEE_Result (*rename)(struct tee_pobj *old_po, struct tee_pobj *new_po, + bool overwrite); + TEE_Result (*remove)(struct tee_pobj *po); + TEE_Result (*truncate)(struct tee_file_handle *fh, size_t size); + + TEE_Result (*opendir)(const TEE_UUID *uuid, struct tee_fs_dir **d); + TEE_Result (*readdir)(struct tee_fs_dir *d, struct tee_fs_dirent **ent); + void (*closedir)(struct tee_fs_dir *d); +}; + +#ifdef CFG_REE_FS +extern const struct tee_file_operations ree_fs_ops; +#endif +#ifdef CFG_RPMB_FS +extern const struct tee_file_operations rpmb_fs_ops; + +TEE_Result tee_rpmb_fs_raw_open(const char *fname, bool create, + struct tee_file_handle **fh); + +/** + * Weak function which can be overridden by platforms to indicate that the RPMB + * key is ready to be written. Defaults to true, platforms can return false to + * prevent a RPMB key write in the wrong state. + */ +bool plat_rpmb_key_is_ready(void); +#endif +#ifdef CFG_NVME_RPMB_FS +extern const struct tee_file_operations nvme_rpmb_fs_ops; + +TEE_Result tee_nvme_rpmb_fs_raw_open(const char *fname, bool create, + struct tee_file_handle **fh); + +/** + * Weak function which can be overridden by platforms to indicate that the NVME-RPMB + * key is ready to be written. Defaults to true, platforms can return false to + * prevent a RPMB key write in the wrong state. + */ +bool plat_nvme_rpmb_key_is_ready(void); +#endif + +/* + * Returns the appropriate tee_file_operations for the specified storage ID. + * The value TEE_STORAGE_PRIVATE will select the REE FS if available, otherwise + * RPMB. + */ +static inline const struct tee_file_operations * +tee_svc_storage_file_ops(uint32_t storage_id) +{ + switch (storage_id) { + case TEE_STORAGE_PRIVATE: +#if defined(CFG_REE_FS) + return &ree_fs_ops; +#elif defined(CFG_RPMB_FS) + return &rpmb_fs_ops; +#elif defined(CFG_NVME_RPMB_FS) + return &nvme_rpmb_fs_ops; +#else + return NULL; +#endif +#ifdef CFG_REE_FS + case TEE_STORAGE_PRIVATE_REE: + return &ree_fs_ops; +#endif +#ifdef CFG_RPMB_FS + case TEE_STORAGE_PRIVATE_RPMB: + return &rpmb_fs_ops; +#endif +#ifdef CFG_NVME_RPMB_FS + case TEE_STORAGE_PRIVATE_NVME_RPMB: + return &nvme_rpmb_fs_ops; +#endif + default: + return NULL; + } +} + +#endif /*TEE_FS_H*/ diff --git a/optee/optee_os/core/include/tee/tee_fs_key_manager.h b/optee/optee_os/core/include/tee/tee_fs_key_manager.h new file mode 100644 index 0000000..ac57630 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_fs_key_manager.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef TEE_FS_KEY_MANAGER_H +#define TEE_FS_KEY_MANAGER_H + +#include +#include + +#define TEE_FS_KM_CHIP_ID_LENGTH U(32) +#define TEE_FS_KM_HMAC_ALG TEE_ALG_HMAC_SHA256 +#define TEE_FS_KM_ENC_FEK_ALG TEE_ALG_AES_ECB_NOPAD +#define TEE_FS_KM_SSK_SIZE TEE_SHA256_HASH_SIZE +#define TEE_FS_KM_TSK_SIZE TEE_SHA256_HASH_SIZE +#define TEE_FS_KM_FEK_SIZE U(16) /* bytes */ + +TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *encrypted_fek, + size_t fek_size); +TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out, + const uint8_t *in, size_t size, + uint16_t blk_idx, const uint8_t *encrypted_fek, + TEE_OperationMode mode); + +TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode, + const uint8_t *in_key, size_t size, + uint8_t *out_key); + +#endif diff --git a/optee/optee_os/core/include/tee/tee_fs_rpc.h b/optee/optee_os/core/include/tee/tee_fs_rpc.h new file mode 100644 index 0000000..ae49682 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_fs_rpc.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +/* + * Interface with tee-supplicant for file operations + */ + +#ifndef TEE_FS_RPC_H +#define TEE_FS_RPC_H + +#include +#include +#include +#include +#include + +struct tee_fs_rpc_operation { + uint32_t id; + struct thread_param params[THREAD_RPC_MAX_NUM_PARAMS]; + size_t num_params; +}; + +struct tee_fs_dirfile_fileh; + +TEE_Result tee_fs_rpc_open_dfh(uint32_t id, + const struct tee_fs_dirfile_fileh *dfh, int *fd); +TEE_Result tee_fs_rpc_create_dfh(uint32_t id, + const struct tee_fs_dirfile_fileh *dfh, + int *fd); +TEE_Result tee_fs_rpc_close(uint32_t id, int fd); + +TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op, + uint32_t id, int fd, tee_fs_off_t offset, + size_t data_len, void **out_data); +TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op, + size_t *data_len); + +TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op, + uint32_t id, int fd, tee_fs_off_t offset, + size_t data_len, void **data); +TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op); + + +TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len); +TEE_Result tee_fs_rpc_remove_dfh(uint32_t id, + const struct tee_fs_dirfile_fileh *dfh); +#endif /* TEE_FS_RPC_H */ diff --git a/optee/optee_os/core/include/tee/tee_obj.h b/optee/optee_os/core/include/tee/tee_obj.h new file mode 100644 index 0000000..adbe543 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_obj.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TEE_OBJ_H +#define TEE_OBJ_H + +#include +#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 *attr; + size_t ds_pos; + struct tee_pobj *pobj; /* ptr to persistant object */ + struct tee_file_handle *fh; +}; + +void tee_obj_add(struct user_ta_ctx *utc, struct tee_obj *o); + +TEE_Result tee_obj_get(struct user_ta_ctx *utc, vaddr_t obj_id, + struct tee_obj **obj); + +void tee_obj_close(struct user_ta_ctx *utc, struct tee_obj *o); + +void tee_obj_close_all(struct user_ta_ctx *utc); + +TEE_Result tee_obj_verify(struct tee_ta_session *sess, struct tee_obj *o); + +struct tee_obj *tee_obj_alloc(void); +void tee_obj_free(struct tee_obj *o); + +#endif diff --git a/optee/optee_os/core/include/tee/tee_pobj.h b/optee/optee_os/core/include/tee/tee_pobj.h new file mode 100644 index 0000000..bd05da4 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_pobj.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TEE_POBJ_H +#define TEE_POBJ_H + +#include +#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; + bool temporary; /* can be changed while creating == true */ + bool creating; /* can only be changed with mutex held */ + /* Filesystem handling this object */ + const struct tee_file_operations *fops; +}; + +enum tee_pobj_usage { + TEE_POBJ_USAGE_OPEN, + TEE_POBJ_USAGE_RENAME, + TEE_POBJ_USAGE_CREATE, + TEE_POBJ_USAGE_ENUM, +}; + +TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len, + uint32_t flags, enum tee_pobj_usage usage, + const struct tee_file_operations *fops, + struct tee_pobj **obj); + +void tee_pobj_create_final(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); + +#endif diff --git a/optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h b/optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h new file mode 100644 index 0000000..996e00f --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_supp_plugin_rpc.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#ifndef TEE_SUPP_PLUGIN_RPC_H +#define TEE_SUPP_PLUGIN_RPC_H + +#include +#include +#include + +TEE_Result tee_invoke_supp_plugin_rpc(const TEE_UUID *uuid, uint32_t cmd, + uint32_t sub_cmd, void *buf, size_t len, + size_t *outlen); + +#endif /* TEE_SUPP_PLUGIN_RPC_H */ diff --git a/optee/optee_os/core/include/tee/tee_svc.h b/optee/optee_os/core/include/tee/tee_svc.h new file mode 100644 index 0000000..27a04c0 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_svc.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef TEE_SVC_H +#define TEE_SVC_H + +#include +#include +#include +#include +#include + +struct tee_ta_session; + +/* TA Properties */ +struct tee_props { + const char *name; + + /* prop_type is of type enum user_ta_prop_type*/ + const uint32_t prop_type; + + /* either get_prop_func or both data and len */ + TEE_Result (*get_prop_func)(struct ts_session *sess, + void *buf, size_t *blen); + const void *data; + const size_t len; +}; + +struct tee_vendor_props { + const struct tee_props *props; + size_t len; +}; +void syscall_sys_return(unsigned long ret); + +void syscall_log(const void *buf, size_t len); + +void syscall_panic(unsigned long code); + +TEE_Result syscall_not_supported(void); + +/* prop_set defined by enum utee_property */ +TEE_Result syscall_get_property(unsigned long prop_set, + unsigned long index, + void *name, uint32_t *name_len, + void *buf, uint32_t *blen, + uint32_t *prop_type); +TEE_Result syscall_get_property_name_to_index(unsigned long prop_set, + void *name, + unsigned long name_len, + uint32_t *index); + +TEE_Result syscall_open_ta_session(const TEE_UUID *dest, + unsigned long cancel_req_to, struct utee_params *params, + uint32_t *sess, uint32_t *ret_orig); + +TEE_Result syscall_close_ta_session(unsigned long sess); + +TEE_Result syscall_invoke_ta_command(unsigned long sess, + unsigned long cancel_req_to, unsigned long cmd_id, + struct utee_params *params, uint32_t *ret_orig); + +TEE_Result syscall_check_access_rights(unsigned long flags, const void *buf, + size_t len); + +TEE_Result syscall_get_cancellation_flag(uint32_t *cancel); + +TEE_Result syscall_unmask_cancellation(uint32_t *old_mask); + +TEE_Result syscall_mask_cancellation(uint32_t *old_mask); + +TEE_Result syscall_wait(unsigned long timeout); + +TEE_Result syscall_get_time(unsigned long cat, TEE_Time *time); +TEE_Result syscall_set_ta_time(const TEE_Time *time); + +#endif /* TEE_SVC_H */ diff --git a/optee/optee_os/core/include/tee/tee_svc_cryp.h b/optee/optee_os/core/include/tee/tee_svc_cryp.h new file mode 100644 index 0000000..3932cdf --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_svc_cryp.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* +* Copyright (c) 2014, STMicroelectronics International N.V. +*/ +#ifndef TEE_SVC_CRYP_H +#define TEE_SVC_CRYP_H + +#include +#include +#include + +struct user_ta_ctx; + +TEE_Result syscall_cryp_obj_get_info(unsigned long obj, + struct utee_object_info *info); +TEE_Result syscall_cryp_obj_restrict_usage(unsigned long obj, + unsigned long usage); +TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id, + void *buffer, uint64_t *size); + +TEE_Result syscall_cryp_obj_alloc(unsigned long obj_type, + unsigned long max_key_size, uint32_t *obj); +TEE_Result syscall_cryp_obj_close(unsigned long obj); +TEE_Result syscall_cryp_obj_reset(unsigned long obj); +TEE_Result syscall_cryp_obj_populate(unsigned long obj, + struct utee_attribute *attrs, unsigned long attr_count); +TEE_Result syscall_cryp_obj_copy(unsigned long dst_obj, + unsigned long src_obj); +TEE_Result syscall_obj_generate_key(unsigned long obj, unsigned long key_size, + const struct utee_attribute *params, + unsigned long param_count); + +TEE_Result syscall_cryp_state_alloc(unsigned long algo, unsigned long op_mode, + unsigned long key1, unsigned long key2, + uint32_t *state); +TEE_Result syscall_cryp_state_copy(unsigned long dst, unsigned long src); +TEE_Result syscall_cryp_state_free(unsigned long state); +void tee_svc_cryp_free_states(struct user_ta_ctx *utc); + +/* iv and iv_len are ignored for hash algorithms */ +TEE_Result syscall_hash_init(unsigned long state, const void *iv, + size_t iv_len); +TEE_Result syscall_hash_update(unsigned long state, const void *chunk, + size_t chunk_size); +TEE_Result syscall_hash_final(unsigned long state, const void *chunk, + size_t chunk_size, void *hash, uint64_t *hash_len); + +TEE_Result syscall_cipher_init(unsigned long state, const void *iv, + size_t iv_len); +TEE_Result syscall_cipher_update(unsigned long state, const void *src, + size_t src_len, void *dest, uint64_t *dest_len); +TEE_Result syscall_cipher_final(unsigned long state, const void *src, + size_t src_len, void *dest, uint64_t *dest_len); + +TEE_Result syscall_cryp_derive_key(unsigned long state, + const struct utee_attribute *params, + unsigned long param_count, unsigned long derived_key); + +TEE_Result syscall_cryp_random_number_generate(void *buf, size_t blen); + +TEE_Result syscall_authenc_init(unsigned long state, const void *nonce, + size_t nonce_len, size_t tag_len, + size_t aad_len, size_t payload_len); +TEE_Result syscall_authenc_update_aad(unsigned long state, + const void *aad_data, size_t aad_data_len); +TEE_Result syscall_authenc_update_payload(unsigned long state, + const void *src_data, size_t src_len, void *dest_data, + uint64_t *dest_len); +TEE_Result syscall_authenc_enc_final(unsigned long state, + const void *src_data, size_t src_len, void *dest_data, + uint64_t *dest_len, void *tag, uint64_t *tag_len); +TEE_Result syscall_authenc_dec_final(unsigned long state, + const void *src_data, size_t src_len, void *dest_data, + uint64_t *dest_len, const void *tag, size_t tag_len); + +TEE_Result syscall_asymm_operate(unsigned long state, + const struct utee_attribute *usr_params, + size_t num_params, const void *src_data, + size_t src_len, void *dest_data, uint64_t *dest_len); +TEE_Result syscall_asymm_verify(unsigned long state, + const struct utee_attribute *usr_params, + size_t num_params, const void *data, size_t data_len, + const void *sig, size_t sig_len); + +TEE_Result tee_obj_set_type(struct tee_obj *o, uint32_t obj_type, + size_t max_key_size); + +void tee_obj_attr_free(struct tee_obj *o); +void tee_obj_attr_clear(struct tee_obj *o); +TEE_Result tee_obj_attr_to_binary(struct tee_obj *o, void *data, + size_t *data_len); +TEE_Result tee_obj_attr_from_binary(struct tee_obj *o, const void *data, + size_t data_len); +TEE_Result tee_obj_attr_copy_from(struct tee_obj *o, const struct tee_obj *src); + +#endif /* TEE_SVC_CRYP_H */ diff --git a/optee/optee_os/core/include/tee/tee_svc_storage.h b/optee/optee_os/core/include/tee/tee_svc_storage.h new file mode 100644 index 0000000..c5d763a --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_svc_storage.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TEE_SVC_STORAGE_H +#define TEE_SVC_STORAGE_H + +#include +#include +#include + +/* + * Persistant Object Functions + */ +TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, + size_t object_id_len, unsigned long flags, + uint32_t *obj); + +TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, + size_t object_id_len, unsigned long flags, + unsigned long attr, void *data, size_t len, + uint32_t *obj); + +TEE_Result syscall_storage_obj_del(unsigned long obj); + +TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, + size_t object_id_len); + +/* + * Persistent Object Enumeration Functions + */ +TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum); + +TEE_Result syscall_storage_free_enum(unsigned long obj_enum); + +TEE_Result syscall_storage_reset_enum(unsigned long obj_enum); + +TEE_Result syscall_storage_start_enum(unsigned long obj_enum, + unsigned long storage_id); + +TEE_Result syscall_storage_next_enum(unsigned long obj_enum, + struct utee_object_info *info, + void *obj_id, uint64_t *len); + +/* + * Data Stream Access Functions + */ +TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, + uint64_t *count); + +TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, + size_t len); + +TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len); + +TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, + unsigned long whence); + +void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc); + +void tee_svc_storage_init(void); + +#endif /* TEE_SVC_STORAGE_H */ diff --git a/optee/optee_os/core/include/tee/tee_ta_enc_manager.h b/optee/optee_os/core/include/tee/tee_ta_enc_manager.h new file mode 100644 index 0000000..5e1b2e5 --- /dev/null +++ b/optee/optee_os/core/include/tee/tee_ta_enc_manager.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef TEE_TA_ENC_MANAGER_H +#define TEE_TA_ENC_MANAGER_H + +#include +#include +#include + +#define TEE_TA_ENC_KEY_SIZE TEE_SHA256_HASH_SIZE + +TEE_Result tee_ta_decrypt_init(void **enc_ctx, struct shdr_encrypted_ta *ehdr, + size_t len); +TEE_Result tee_ta_decrypt_update(void *enc_ctx, uint8_t *dst, uint8_t *src, + size_t len); +TEE_Result tee_ta_decrypt_final(void *enc_ctx, struct shdr_encrypted_ta *ehdr, + uint8_t *dst, uint8_t *src, size_t len); + +#endif diff --git a/optee/optee_os/core/include/tee/uuid.h b/optee/optee_os/core/include/tee/uuid.h new file mode 100644 index 0000000..9c95e13 --- /dev/null +++ b/optee/optee_os/core/include/tee/uuid.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __TEE_UUID +#define __TEE_UUID + +#include +#include + +/** + * tee_uuid_to_octets() - serialize a TEE_UUID into an octet string + * @dst: pointer to octet string + * @src: pointer TEE_UUID + */ +void tee_uuid_to_octets(uint8_t *dst, const TEE_UUID *src); + +/** + * tee_uuid_from_octets() - de-serialize an octet string into a TEE_UUID + * @dst: pointer TEE_UUID + * @src: pointer to octet string + */ +void tee_uuid_from_octets(TEE_UUID *dst, const uint8_t *src); + +/** + * tee_uuid_from_uint32_t() - de-serialize an uint32_t array into a TEE_UUID + * An array consisting of 4 values, The UUID format is described in + * RFC 4122. + * @dst: pointer TEE_UUID + * @src: uint32_t elements + */ +void tee_uuid_from_uint32_t(TEE_UUID *d, uint32_t s0, uint32_t s1, uint32_t s2, + uint32_t s3); +#endif /*__TEE_UUID*/ diff --git a/optee/optee_os/core/kernel/asan.c b/optee/optee_os/core/kernel/asan.c new file mode 100644 index 0000000..0cb954f --- /dev/null +++ b/optee/optee_os/core/kernel/asan.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __GCC_VERSION >= 70000 +#define ASAN_ABI_VERSION 7 +#else +#define ASAN_ABI_VERSION 6 +#endif + +struct asan_source_location { + const char *file_name; + int line_no; + int column_no; +}; + +struct asan_global { + uintptr_t beg; + uintptr_t size; + uintptr_t size_with_redzone; + const char *name; + const char *module_name; + uintptr_t has_dynamic_init; + struct asan_source_location *location; +#if ASAN_ABI_VERSION >= 7 + uintptr_t odr_indicator; +#endif +}; + +static vaddr_t asan_va_base; +static size_t asan_va_size; +static bool asan_active; + +static int8_t *va_to_shadow(const void *va) +{ + vaddr_t sa = ((vaddr_t)va / ASAN_BLOCK_SIZE) + CFG_ASAN_SHADOW_OFFSET; + + return (int8_t *)sa; +} + +static size_t va_range_to_shadow_size(const void *begin, const void *end) +{ + return ((vaddr_t)end - (vaddr_t)begin) / ASAN_BLOCK_SIZE; +} + +static bool va_range_inside_shadow(const void *begin, const void *end) +{ + vaddr_t b = (vaddr_t)begin; + vaddr_t e = (vaddr_t)end; + + if (b >= e) + return false; + return (b >= asan_va_base) && (e <= (asan_va_base + asan_va_size)); +} + +static bool va_range_outside_shadow(const void *begin, const void *end) +{ + vaddr_t b = (vaddr_t)begin; + vaddr_t e = (vaddr_t)end; + + if (b >= e) + return false; + return (e <= asan_va_base) || (b >= (asan_va_base + asan_va_size)); +} + +static size_t va_misalignment(const void *va) +{ + return (vaddr_t)va & ASAN_BLOCK_MASK; +} + +static bool va_is_well_aligned(const void *va) +{ + return !va_misalignment(va); +} + +void asan_set_shadowed(const void *begin, const void *end) +{ + vaddr_t b = (vaddr_t)begin; + vaddr_t e = (vaddr_t)end; + + assert(!asan_va_base); + assert(va_is_well_aligned(begin)); + assert(va_is_well_aligned(end)); + assert(b < e); + + asan_va_base = b; + asan_va_size = e - b; +} + +void asan_tag_no_access(const void *begin, const void *end) +{ + assert(va_is_well_aligned(begin)); + assert(va_is_well_aligned(end)); + assert(va_range_inside_shadow(begin, end)); + + asan_memset_unchecked(va_to_shadow(begin), ASAN_DATA_RED_ZONE, + va_range_to_shadow_size(begin, end)); +} + +void asan_tag_access(const void *begin, const void *end) +{ + if (!asan_va_base || (begin == end)) + return; + + assert(va_range_inside_shadow(begin, end)); + assert(va_is_well_aligned(begin)); + + asan_memset_unchecked(va_to_shadow(begin), 0, + va_range_to_shadow_size(begin, end)); + if (!va_is_well_aligned(end)) + *va_to_shadow(end) = ASAN_BLOCK_SIZE - va_misalignment(end); +} + +void asan_tag_heap_free(const void *begin, const void *end) +{ + if (!asan_va_base) + return; + + assert(va_range_inside_shadow(begin, end)); + assert(va_is_well_aligned(begin)); + assert(va_is_well_aligned(end)); + + asan_memset_unchecked(va_to_shadow(begin), ASAN_HEAP_RED_ZONE, + va_range_to_shadow_size(begin, end)); +} + +void *asan_memset_unchecked(void *s, int c, size_t n) +{ + uint8_t *b = s; + size_t m; + + for (m = 0; m < n; m++) + b[m] = c; + + return s; +} + +void *asan_memcpy_unchecked(void *__restrict dst, const void *__restrict src, + size_t len) +{ + uint8_t *__restrict d = dst; + const uint8_t *__restrict s = src; + size_t n; + + for (n = 0; n < len; n++) + d[n] = s[n]; + + return dst; +} + +void asan_start(void) +{ + assert(asan_va_base && !asan_active); + asan_active = true; +} + +static void check_access(vaddr_t addr, size_t size) +{ + void *begin = (void *)addr; + void *end = (void *)(addr + size); + int8_t *a; + int8_t *e; + + if (!asan_active || !size) + return; + if (va_range_outside_shadow(begin, end)) + return; + /* + * If it isn't outside it has to be completely inside or there's a + * problem. + */ + if (!va_range_inside_shadow(begin, end)) + panic(); + + e = va_to_shadow((void *)(addr + size - 1)); + for (a = va_to_shadow(begin); a <= e; a++) + if (*a < 0) + panic(); + + if (!va_is_well_aligned(end) && + va_misalignment(end) > (size_t)(*e - ASAN_BLOCK_SIZE)) + panic(); +} + +static void check_load(vaddr_t addr, size_t size) +{ + check_access(addr, size); +} + +static void check_store(vaddr_t addr, size_t size) +{ + check_access(addr, size); +} + +static void __noreturn report_load(vaddr_t addr __unused, size_t size __unused) +{ + panic(); +} + +static void __noreturn report_store(vaddr_t addr __unused, size_t size __unused) +{ + panic(); +} + + + +#define DEFINE_ASAN_FUNC(type, size) \ + void __asan_##type##size(vaddr_t addr); \ + void __asan_##type##size(vaddr_t addr) \ + { check_##type(addr, size); } \ + void __asan_##type##size##_noabort(vaddr_t addr); \ + void __asan_##type##size##_noabort(vaddr_t addr) \ + { check_##type(addr, size); } \ + void __asan_report_##type##size##_noabort(vaddr_t addr);\ + void __noreturn __asan_report_##type##size##_noabort(vaddr_t addr) \ + { report_##type(addr, size); } + +DEFINE_ASAN_FUNC(load, 1) +DEFINE_ASAN_FUNC(load, 2) +DEFINE_ASAN_FUNC(load, 4) +DEFINE_ASAN_FUNC(load, 8) +DEFINE_ASAN_FUNC(load, 16) +DEFINE_ASAN_FUNC(store, 1) +DEFINE_ASAN_FUNC(store, 2) +DEFINE_ASAN_FUNC(store, 4) +DEFINE_ASAN_FUNC(store, 8) +DEFINE_ASAN_FUNC(store, 16) + +void __asan_loadN_noabort(vaddr_t addr, size_t size); +void __asan_loadN_noabort(vaddr_t addr, size_t size) +{ + check_load(addr, size); +} + +void __asan_storeN_noabort(vaddr_t addr, size_t size); +void __asan_storeN_noabort(vaddr_t addr, size_t size) +{ + check_store(addr, size); +} + +void __asan_report_load_n_noabort(vaddr_t addr, size_t size); +void __noreturn __asan_report_load_n_noabort(vaddr_t addr, size_t size) +{ + report_load(addr, size); +} + +void __asan_report_store_n_noabort(vaddr_t addr, size_t size); +void __noreturn __asan_report_store_n_noabort(vaddr_t addr, size_t size) +{ + report_store(addr, size); +} + +void __asan_handle_no_return(void); +void __asan_handle_no_return(void) +{ +} + +void __asan_register_globals(struct asan_global *globals, size_t size); +void __asan_register_globals(struct asan_global *globals, size_t size) +{ + size_t n; + + for (n = 0; n < size; n++) + asan_tag_access((void *)globals[n].beg, + (void *)(globals[n].beg + globals[n].size)); +} +DECLARE_KEEP_INIT(__asan_register_globals); + +void __asan_unregister_globals(struct asan_global *globals, size_t size); +void __asan_unregister_globals(struct asan_global *globals __unused, + size_t size __unused) +{ +} diff --git a/optee/optee_os/core/kernel/assert.c b/optee/optee_os/core/kernel/assert.c new file mode 100644 index 0000000..1d2e3c9 --- /dev/null +++ b/optee/optee_os/core/kernel/assert.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include + +/* assert log and break for the optee kernel */ + +void __nostackcheck _assert_log(const char *expr __maybe_unused, + const char *file __maybe_unused, + const int line __maybe_unused, + const char *func __maybe_unused) +{ +#if defined(CFG_TEE_CORE_DEBUG) + EMSG_RAW("assertion '%s' failed at %s:%d <%s>", + expr, file, line, func); +#else + EMSG_RAW("assertion failed"); +#endif +} + +void __noreturn _assert_break(void) +{ + panic(); +} diff --git a/optee/optee_os/core/kernel/console.c b/optee/optee_os/core/kernel/console.c new file mode 100644 index 0000000..6291b2c --- /dev/null +++ b/optee/optee_os/core/kernel/console.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct serial_chip *serial_console __nex_bss; + +void __weak console_putc(int ch) +{ + if (!serial_console) + return; + + if (ch == '\n') + serial_console->ops->putc(serial_console, '\r'); + serial_console->ops->putc(serial_console, ch); +} + +void __weak console_flush(void) +{ + if (!serial_console || !serial_console->ops->flush) + return; + + serial_console->ops->flush(serial_console); +} + +void register_serial_console(struct serial_chip *chip) +{ + serial_console = chip; +} + +#ifdef CFG_DT +static int find_chosen_node(void *fdt) +{ + int offset = 0; + + if (!fdt) + return -1; + + offset = fdt_path_offset(fdt, "/secure-chosen"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/chosen"); + + return offset; +} + +TEE_Result get_console_node_from_dt(void *fdt, int *offs_out, + char **path_out, char **params_out) +{ + const struct fdt_property *prop; + const char *uart; + const char *parms = NULL; + int offs; + char *stdout_data; + char *p; + TEE_Result rc = TEE_ERROR_GENERIC; + + /* Probe console from secure DT and fallback to non-secure DT */ + offs = find_chosen_node(fdt); + if (offs < 0) { + DMSG("No console directive from DTB"); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + prop = fdt_get_property(fdt, offs, "stdout-path", NULL); + if (!prop) { + /* + * A secure-chosen or chosen node is present but defined + * no stdout-path property: no console expected + */ + IMSG("Switching off console"); + register_serial_console(NULL); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + stdout_data = nex_strdup(prop->data); + if (!stdout_data) + panic(); + p = strchr(stdout_data, ':'); + if (p) { + *p = '\0'; + parms = p + 1; + } + + /* stdout-path may refer to an alias */ + uart = fdt_get_alias(fdt, stdout_data); + if (!uart) { + /* Not an alias, assume we have a node path */ + uart = stdout_data; + } + offs = fdt_path_offset(fdt, uart); + if (offs >= 0) { + if (offs_out) + *offs_out = offs; + if (params_out) + *params_out = parms ? nex_strdup(parms) : NULL; + if (path_out) + *path_out = uart ? nex_strdup(uart) : NULL; + + rc = TEE_SUCCESS; + } + + nex_free(stdout_data); + + return rc; +} + +void configure_console_from_dt(void) +{ + const struct dt_driver *dt_drv; + const struct serial_driver *sdrv; + struct serial_chip *dev; + char *uart = NULL; + char *parms = NULL; + void *fdt; + int offs; + + fdt = get_dt(); + + if (IS_ENABLED(CFG_CBMEM_CONSOLE) && cbmem_console_init_from_dt(fdt)) + return; + + if (get_console_node_from_dt(fdt, &offs, &uart, &parms)) + return; + + dt_drv = dt_find_compatible_driver(fdt, offs); + if (!dt_drv || dt_drv->type != DT_DRIVER_UART) + goto out; + + sdrv = (const struct serial_driver *)dt_drv->driver; + if (!sdrv) + goto out; + + dev = sdrv->dev_alloc(); + if (!dev) + goto out; + + /* + * If the console is the same as the early console, dev_init() might + * clear pending data. Flush to avoid that. + */ + console_flush(); + if (sdrv->dev_init(dev, fdt, offs, parms) < 0) { + sdrv->dev_free(dev); + goto out; + } + + IMSG("Switching console to device: %s", uart); + register_serial_console(dev); +out: + nex_free(uart); + nex_free(parms); +} + +#endif /* CFG_DT */ diff --git a/optee/optee_os/core/kernel/delay.c b/optee/optee_os/core/kernel/delay.c new file mode 100644 index 0000000..1c404f9 --- /dev/null +++ b/optee/optee_os/core/kernel/delay.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +#ifdef CFG_CORE_HAS_GENERIC_TIMER +void udelay(uint32_t us) +{ + uint64_t target = timeout_init_us(us); + + while (!timeout_elapsed(target)) + ; +} +#else + +void udelay(uint32_t us) +{ + uint64_t cycles = 0; + uint32_t cycles_to_wait = 0; + + cycles = (uint64_t)us * ((uint64_t)plat_get_freq() / 1000000ULL); + + while (cycles) { + cycles_to_wait = MIN(cycles, UINT32_MAX); + wait_cycles(cycles_to_wait); + cycles -= cycles_to_wait; + } +} +#endif + +void mdelay(uint32_t ms) +{ + udelay(1000 * ms); +} diff --git a/optee/optee_os/core/kernel/dt.c b/optee/optee_os/core/kernel/dt.c new file mode 100644 index 0000000..0aa1fae --- /dev/null +++ b/optee/optee_os/core/kernel/dt.c @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs) +{ + const struct dt_device_match *dm; + const struct dt_driver *drv; + + for_each_dt_driver(drv) { + for (dm = drv->match_table; dm; dm++) { + if (!dm->compatible) { + break; + } + if (!fdt_node_check_compatible(fdt, offs, + dm->compatible)) { + return drv; + } + } + } + + return NULL; +} + +bool dt_have_prop(const void *fdt, int offs, const char *propname) +{ + const void *prop; + + prop = fdt_getprop(fdt, offs, propname, NULL); + + return prop; +} + +int dt_disable_status(void *fdt, int node) +{ + const char *prop = NULL; + int len = 0; + + prop = fdt_getprop(fdt, node, "status", &len); + if (!prop) { + if (fdt_setprop_string(fdt, node, "status", "disabled")) + return -1; + } else { + /* + * Status is there, modify it. + * Ask to set "disabled" value to the property. The value + * will be automatically truncated with "len" size by the + * fdt_setprop_inplace function. + * Setting a value different from "ok" or "okay" will disable + * the property. + * Setting a truncated value of "disabled" with the original + * property "len" is preferred to not increase the DT size and + * losing time in recalculating the overall DT offsets. + * If original length of the status property is larger than + * "disabled", the property will start with "disabled" and be + * completed with the rest of the original property. + */ + if (fdt_setprop_inplace(fdt, node, "status", "disabled", len)) + return -1; + } + + return 0; +} + +int dt_enable_secure_status(void *fdt, int node) +{ + if (dt_disable_status(fdt, node)) { + EMSG("Unable to disable Normal Status"); + return -1; + } + + if (fdt_setprop_string(fdt, node, "secure-status", "okay")) + return -1; + + return 0; +} + +int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, + enum dt_map_dev_directive mapping) +{ + enum teecore_memtypes mtype; + paddr_t pbase; + vaddr_t vbase; + size_t sz; + int st; + + assert(cpu_mmu_enabled()); + + st = fdt_get_status(fdt, offs); + if (st == DT_STATUS_DISABLED) + return -1; + + pbase = fdt_reg_base_address(fdt, offs); + if (pbase == DT_INFO_INVALID_REG) + return -1; + sz = fdt_reg_size(fdt, offs); + if (sz == DT_INFO_INVALID_REG_SIZE) + return -1; + + switch (mapping) { + case DT_MAP_AUTO: + if ((st & DT_STATUS_OK_SEC) && !(st & DT_STATUS_OK_NSEC)) + mtype = MEM_AREA_IO_SEC; + else + mtype = MEM_AREA_IO_NSEC; + break; + case DT_MAP_SECURE: + mtype = MEM_AREA_IO_SEC; + break; + case DT_MAP_NON_SECURE: + mtype = MEM_AREA_IO_NSEC; + break; + default: + panic("Invalid mapping specified"); + break; + } + + /* Check if we have a mapping, create one if needed */ + vbase = (vaddr_t)core_mmu_add_mapping(mtype, pbase, sz); + if (!vbase) { + EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA, + (size_t)sz, pbase); + return -1; + } + + *base = vbase; + *size = sz; + return 0; +} + +/* Read a physical address (n=1 or 2 cells) */ +static paddr_t fdt_read_paddr(const uint32_t *cell, int n) +{ + paddr_t addr; + + if (n < 1 || n > 2) + goto bad; + + addr = fdt32_to_cpu(*cell); + cell++; + if (n == 2) { +#ifdef ARM32 + if (addr) { + /* High order 32 bits can't be nonzero */ + goto bad; + } + addr = fdt32_to_cpu(*cell); +#else + addr = (addr << 32) | fdt32_to_cpu(*cell); +#endif + } + + return addr; +bad: + return DT_INFO_INVALID_REG; + +} + +paddr_t fdt_reg_base_address(const void *fdt, int offs) +{ + const void *reg; + int ncells; + int len; + int parent; + + parent = fdt_parent_offset(fdt, offs); + if (parent < 0) + return DT_INFO_INVALID_REG; + + reg = fdt_getprop(fdt, offs, "reg", &len); + if (!reg) + return DT_INFO_INVALID_REG; + + ncells = fdt_address_cells(fdt, parent); + if (ncells < 0) + return DT_INFO_INVALID_REG; + + return fdt_read_paddr(reg, ncells); +} + +static size_t fdt_read_size(const uint32_t *cell, int n) +{ + uint32_t sz = 0; + + sz = fdt32_to_cpu(*cell); + if (n == 2) { + if (sz) + return DT_INFO_INVALID_REG_SIZE; + + cell++; + sz = fdt32_to_cpu(*cell); + } + + return sz; +} + +size_t fdt_reg_size(const void *fdt, int offs) +{ + const uint32_t *reg; + int n; + int len; + int parent; + + parent = fdt_parent_offset(fdt, offs); + if (parent < 0) + return DT_INFO_INVALID_REG_SIZE; + + reg = (const uint32_t *)fdt_getprop(fdt, offs, "reg", &len); + if (!reg) + return DT_INFO_INVALID_REG_SIZE; + + n = fdt_address_cells(fdt, parent); + if (n < 1 || n > 2) + return DT_INFO_INVALID_REG_SIZE; + + reg += n; + + n = fdt_size_cells(fdt, parent); + if (n < 1 || n > 2) + return DT_INFO_INVALID_REG_SIZE; + + return fdt_read_size(reg, n); +} + +static bool is_okay(const char *st, int len) +{ + return !strncmp(st, "ok", len) || !strncmp(st, "okay", len); +} + +int fdt_get_status(const void *fdt, int offs) +{ + const char *prop; + int st = 0; + int len; + + prop = fdt_getprop(fdt, offs, "status", &len); + if (!prop || is_okay(prop, len)) { + /* If status is not specified, it defaults to "okay" */ + st |= DT_STATUS_OK_NSEC; + } + + prop = fdt_getprop(fdt, offs, "secure-status", &len); + if (!prop) { + /* + * When secure-status is not specified it defaults to the same + * value as status + */ + if (st & DT_STATUS_OK_NSEC) + st |= DT_STATUS_OK_SEC; + } else { + if (is_okay(prop, len)) + st |= DT_STATUS_OK_SEC; + } + + return st; +} + +void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, int offs) +{ + struct dt_node_info dinfo = { + .reg = DT_INFO_INVALID_REG, + .reg_size = DT_INFO_INVALID_REG_SIZE, + .clock = DT_INFO_INVALID_CLOCK, + .reset = DT_INFO_INVALID_RESET, + .interrupt = DT_INFO_INVALID_INTERRUPT, + }; + const fdt32_t *cuint; + + dinfo.reg = fdt_reg_base_address(fdt, offs); + dinfo.reg_size = fdt_reg_size(fdt, offs); + + cuint = fdt_getprop(fdt, offs, "clocks", NULL); + if (cuint) { + cuint++; + dinfo.clock = (int)fdt32_to_cpu(*cuint); + } + + cuint = fdt_getprop(fdt, offs, "resets", NULL); + if (cuint) { + cuint++; + dinfo.reset = (int)fdt32_to_cpu(*cuint); + } + + dinfo.interrupt = dt_get_irq_type_prio(fdt, offs, &dinfo.type, + &dinfo.prio); + + dinfo.status = fdt_get_status(fdt, offs); + + *info = dinfo; +} + +int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, + uint32_t *array, size_t count) +{ + const fdt32_t *cuint = NULL; + int len = 0; + uint32_t i = 0; + + cuint = fdt_getprop(fdt, node, prop_name, &len); + if (!cuint) + return len; + + if ((uint32_t)len != (count * sizeof(uint32_t))) + return -FDT_ERR_BADLAYOUT; + + for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { + *array = fdt32_to_cpu(*cuint); + array++; + cuint++; + } + + return 0; +} + +int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, + int index, uint32_t *value) +{ + const fdt32_t *cuint = NULL; + int len = 0; + + cuint = fdt_getprop(fdt, node, prop_name, &len); + if (!cuint) + return len; + + if ((uint32_t)len < (sizeof(uint32_t) * (index + 1))) + return -FDT_ERR_BADLAYOUT; + + *value = fdt32_to_cpu(cuint[index]); + + return 0; +} + +int fdt_read_uint32(const void *fdt, int node, const char *prop_name, + uint32_t *value) +{ + return fdt_read_uint32_array(fdt, node, prop_name, value, 1); +} + +uint32_t fdt_read_uint32_default(const void *fdt, int node, + const char *prop_name, uint32_t dflt_value) +{ + uint32_t ret = dflt_value; + + fdt_read_uint32_index(fdt, node, prop_name, 0, &ret); + + return ret; +} + +int fdt_get_reg_props_by_index(const void *fdt, int node, int index, + paddr_t *base, size_t *size) +{ + const fdt32_t *prop = NULL; + int parent = 0; + int len = 0; + int address_cells = 0; + int size_cells = 0; + int cell = 0; + + parent = fdt_parent_offset(fdt, node); + if (parent < 0) + return parent; + + address_cells = fdt_address_cells(fdt, parent); + if (address_cells < 0) + return address_cells; + + size_cells = fdt_size_cells(fdt, parent); + if (size_cells < 0) + return size_cells; + + cell = index * (address_cells + size_cells); + + prop = fdt_getprop(fdt, node, "reg", &len); + if (!prop) + return len; + + if (((cell + address_cells + size_cells) * (int)sizeof(uint32_t)) > len) + return -FDT_ERR_BADVALUE; + + if (base) { + *base = fdt_read_paddr(&prop[cell], address_cells); + if (*base == DT_INFO_INVALID_REG) + return -FDT_ERR_BADVALUE; + } + + if (size) { + *size = fdt_read_size(&prop[cell + address_cells], size_cells); + if (*size == DT_INFO_INVALID_REG_SIZE) + return -FDT_ERR_BADVALUE; + } + + return 0; +} + +int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, + paddr_t *base, size_t *size) +{ + int index = 0; + + index = fdt_stringlist_search(fdt, node, "reg-names", name); + if (index < 0) + return index; + + return fdt_get_reg_props_by_index(fdt, node, index, base, size); +} + +int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, + uint64_t *num) +{ + const void *prop = NULL; + int len = 0; + + prop = fdt_getprop(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + switch (len) { + case sizeof(uint32_t): + *num = fdt32_ld(prop); + return 0; + case sizeof(uint64_t): + *num = fdt64_ld(prop); + return 0; + default: + return -FDT_ERR_BADVALUE; + } +} diff --git a/optee/optee_os/core/kernel/dt_driver.c b/optee/optee_os/core/kernel/dt_driver.c new file mode 100644 index 0000000..ae6102d --- /dev/null +++ b/optee/optee_os/core/kernel/dt_driver.c @@ -0,0 +1,805 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Linaro Limited + * Copyright (c) 2021, Bootlin + * Copyright (c) 2021, Linaro Limited + * Copyright (c) 2021, STMicroelectronics + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * struct dt_driver_probe - Node instance in secure FDT to probe a driver for + * + * @link: List hook + * @nodeoffset: Node offset of device referenced in the FDT + * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE. + * @deferrals: Driver probe deferrals count + * @dt_drv: Matching driver to probe if found or NULL + * @dm: Matching reference if applicable or NULL + */ +struct dt_driver_probe { + int nodeoffset; + enum dt_driver_type type; + unsigned int deferrals; + const struct dt_driver *dt_drv; + const struct dt_device_match *dm; + TAILQ_ENTRY(dt_driver_probe) link; +}; + +/* + * struct dt_driver_provider - DT related info on probed device + * + * Saves information on the probed device so that device + * drivers can get resources from DT phandle and related arguments. + * + * @nodeoffset: Node offset of device referenced in the FDT + * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE. + * @provider_cells: Cells count in the FDT used by the driver's references + * @get_of_device: Function to get driver's device ref from phandle data + * @priv_data: Driver private data passed as @get_of_device argument + * @link: Reference in DT driver providers list + */ +struct dt_driver_provider { + int nodeoffset; + enum dt_driver_type type; + unsigned int provider_cells; + uint32_t phandle; + get_of_device_func get_of_device; + void *priv_data; + SLIST_ENTRY(dt_driver_provider) link; +}; + +/* + * Device driver providers are able to provide a driver specific instance + * related to device phandle arguments found in the secure embedded FDT. + */ +static SLIST_HEAD(, dt_driver_provider) dt_driver_provider_list = + SLIST_HEAD_INITIALIZER(dt_driver_provider_list); + +/* FDT nodes for which a matching driver is to be probed */ +static TAILQ_HEAD(dt_driver_probe_head, dt_driver_probe) dt_driver_probe_list = + TAILQ_HEAD_INITIALIZER(dt_driver_probe_list); + +/* FDT nodes for which a matching driver has been successfully probed */ +static TAILQ_HEAD(, dt_driver_probe) dt_driver_ready_list = + TAILQ_HEAD_INITIALIZER(dt_driver_ready_list); + +/* List of the nodes for which a compatible driver but reported a failure */ +static TAILQ_HEAD(, dt_driver_probe) dt_driver_failed_list = + TAILQ_HEAD_INITIALIZER(dt_driver_failed_list); + +/* Flag enabled when a new node (possibly typed) is added in the probe list */ +static bool added_node; + +/* Resolve drivers dependencies on core crypto layer */ +static bool tee_crypt_is_ready; + +void dt_driver_crypt_init_complete(void) +{ + assert(!tee_crypt_is_ready); + tee_crypt_is_ready = true; +} + +TEE_Result dt_driver_get_crypto(void) +{ + if (tee_crypt_is_ready) + return TEE_SUCCESS; + else + return TEE_ERROR_DEFER_DRIVER_INIT; +} + +static void assert_type_is_valid(enum dt_driver_type type) +{ + switch (type) { + case DT_DRIVER_NOTYPE: + case DT_DRIVER_CLK: + case DT_DRIVER_RSTCTRL: + case DT_DRIVER_UART: + case DT_DRIVER_I2C: + return; + default: + assert(0); + } +} + +/* + * Driver provider registering API functions + */ + +TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset, + get_of_device_func get_of_device, + void *priv, enum dt_driver_type type) +{ + struct dt_driver_provider *prv = NULL; + int provider_cells = 0; + uint32_t phandle = 0; + + assert_type_is_valid(type); + + provider_cells = fdt_get_dt_driver_cells(fdt, nodeoffset, type); + if (provider_cells < 0) { + DMSG("Failed to find provider cells: %d", provider_cells); + return TEE_ERROR_GENERIC; + } + + phandle = fdt_get_phandle(fdt, nodeoffset); + if (phandle == (uint32_t)-1) { + DMSG("Failed to find provide phandle"); + return TEE_ERROR_GENERIC; + } + + prv = calloc(1, sizeof(*prv)); + if (!prv) + return TEE_ERROR_OUT_OF_MEMORY; + + prv->nodeoffset = nodeoffset; + prv->type = type; + prv->provider_cells = provider_cells; + prv->phandle = phandle; + prv->get_of_device = get_of_device; + prv->priv_data = priv; + + SLIST_INSERT_HEAD(&dt_driver_provider_list, prv, link); + + return TEE_SUCCESS; +} + +/* + * Helper functions for dt_drivers querying driver provider information + */ + +int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset, + enum dt_driver_type type) +{ + const char *cells_name = NULL; + const fdt32_t *c = NULL; + int len = 0; + + switch (type) { + case DT_DRIVER_CLK: + cells_name = "#clock-cells"; + break; + case DT_DRIVER_RSTCTRL: + cells_name = "#reset-cells"; + break; + case DT_DRIVER_I2C: + return 0; + default: + panic(); + } + + c = fdt_getprop(fdt, nodeoffset, cells_name, &len); + if (!c) + return len; + + if (len != sizeof(*c)) + return -FDT_ERR_BADNCELLS; + + return fdt32_to_cpu(*c); +} + +unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv) +{ + return prv->provider_cells; +} + +struct dt_driver_provider * +dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type) +{ + struct dt_driver_provider *prv = NULL; + + SLIST_FOREACH(prv, &dt_driver_provider_list, link) + if (prv->nodeoffset == nodeoffset && prv->type == type) + return prv; + + return NULL; +} + +struct dt_driver_provider * +dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type) +{ + struct dt_driver_provider *prv = NULL; + + SLIST_FOREACH(prv, &dt_driver_provider_list, link) + if (prv->phandle == phandle && prv->type == type) + return prv; + + return NULL; +} + +static void *device_from_provider_prop(struct dt_driver_provider *prv, + const void *fdt, int phandle_node, + const uint32_t *prop, TEE_Result *res) +{ + struct dt_driver_phandle_args *pargs = NULL; + unsigned int n = 0; + void *device = NULL; + + pargs = calloc(1, prv->provider_cells * sizeof(uint32_t *) + + sizeof(*pargs)); + if (!pargs) { + *res = TEE_ERROR_OUT_OF_MEMORY; + return NULL; + } + + pargs->fdt = fdt; + pargs->phandle_node = phandle_node; + pargs->args_count = prv->provider_cells; + for (n = 0; n < prv->provider_cells; n++) + pargs->args[n] = fdt32_to_cpu(prop[n + 1]); + + device = prv->get_of_device(pargs, prv->priv_data, res); + + free(pargs); + + return device; +} + +void *dt_driver_device_from_parent(const void *fdt, int nodeoffset, + enum dt_driver_type type, TEE_Result *res) +{ + int parent = -1; + struct dt_driver_provider *prv = NULL; + + assert(fdt == get_secure_dt()); + + parent = fdt_parent_offset(fdt, nodeoffset); + if (parent < 0) { + *res = TEE_ERROR_GENERIC; + return NULL; + } + + prv = dt_driver_get_provider_by_node(parent, type); + if (!prv) { + /* No provider registered yet */ + *res = TEE_ERROR_DEFER_DRIVER_INIT; + return NULL; + } + + return device_from_provider_prop(prv, fdt, nodeoffset, NULL, res); +} + +void *dt_driver_device_from_node_idx_prop(const char *prop_name, + const void *fdt, int nodeoffset, + unsigned int prop_idx, + enum dt_driver_type type, + TEE_Result *res) +{ + int len = 0; + int idx = 0; + int idx32 = 0; + int prv_cells = 0; + int phandle_node = -1; + uint32_t phandle = 0; + const uint32_t *prop = NULL; + struct dt_driver_provider *prv = NULL; + + prop = fdt_getprop(fdt, nodeoffset, prop_name, &len); + if (!prop) { + DMSG("Property %s missing in node %s", prop_name, + fdt_get_name(fdt, nodeoffset, NULL)); + *res = TEE_ERROR_ITEM_NOT_FOUND; + return NULL; + } + + while (idx < len) { + idx32 = idx / sizeof(uint32_t); + phandle = fdt32_to_cpu(prop[idx32]); + if (!phandle) { + if (!prop_idx) + break; + idx += sizeof(phandle); + prop_idx--; + continue; + } + + prv = dt_driver_get_provider_by_phandle(phandle, type); + if (!prv) { + /* No provider registered yet */ + *res = TEE_ERROR_DEFER_DRIVER_INIT; + return NULL; + } + + prv_cells = dt_driver_provider_cells(prv); + if (prop_idx) { + prop_idx--; + idx += sizeof(phandle) + prv_cells * sizeof(uint32_t); + continue; + } + + return device_from_provider_prop(prv, fdt, phandle_node, + prop + idx32, res); + } + + *res = TEE_ERROR_ITEM_NOT_FOUND; + return NULL; +} + +static void __maybe_unused print_probe_list(const void *fdt __maybe_unused) +{ + struct dt_driver_probe *elt = NULL; + unsigned int count = 0; + + TAILQ_FOREACH(elt, &dt_driver_probe_list, link) + count++; + + DMSG("Probe list: %u elements", count); + TAILQ_FOREACH(elt, &dt_driver_probe_list, link) + DMSG("|- Driver %s probes on node %s", + elt->dt_drv->name, + fdt_get_name(fdt, elt->nodeoffset, NULL)); + + DMSG("`- Probe list end"); + + count = 0; + TAILQ_FOREACH(elt, &dt_driver_failed_list, link) + count++; + + DMSG("Failed list: %u elements", count); + TAILQ_FOREACH(elt, &dt_driver_failed_list, link) + EMSG("|- Driver %s on node %s failed", elt->dt_drv->name, + fdt_get_name(fdt, elt->nodeoffset, NULL)); + + DMSG("`- Failed list end"); +} + +/* + * Probe element: push to ready list if succeeds, push to probe list if probe + * if deferred, panic with an error trace otherwise. + */ +static TEE_Result probe_driver_node(const void *fdt, + struct dt_driver_probe *elt) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const char __maybe_unused *drv_name = NULL; + const char __maybe_unused *node_name = NULL; + + node_name = fdt_get_name(fdt, elt->nodeoffset, NULL); + drv_name = elt->dt_drv->name; + + if (!elt->dt_drv->probe) { + DMSG("No probe operator for driver %s, skipped", drv_name); + return TEE_SUCCESS; + } + + FMSG("Probing %s on node %s", drv_name, node_name); + + res = elt->dt_drv->probe(fdt, elt->nodeoffset, elt->dm->compat_data); + switch (res) { + case TEE_SUCCESS: + TAILQ_INSERT_HEAD(&dt_driver_ready_list, elt, link); + + DMSG("element: %s on node %s initialized", drv_name, node_name); + break; + case TEE_ERROR_DEFER_DRIVER_INIT: + elt->deferrals++; + TAILQ_INSERT_TAIL(&dt_driver_probe_list, elt, link); + + DMSG("element: %s on node %s deferred %u time(s)", drv_name, + node_name, elt->deferrals); + break; + case TEE_ERROR_NODE_DISABLED: + DMSG("element: %s on node %s is disabled", drv_name, node_name); + break; + default: + TAILQ_INSERT_HEAD(&dt_driver_failed_list, elt, link); + + EMSG("Failed to probe %s on node %s: %#"PRIx32, + drv_name, node_name, res); + break; + } + + return res; +} + +static TEE_Result alloc_elt_and_probe(const void *fdt, int node, + const struct dt_driver *dt_drv, + const struct dt_device_match *dm) +{ + struct dt_driver_probe *elt = NULL; + + /* Will be freed when lists are released */ + elt = calloc(1, sizeof(*elt)); + if (!elt) + return TEE_ERROR_OUT_OF_MEMORY; + + elt->nodeoffset = node; + elt->dt_drv = dt_drv; + elt->dm = dm; + elt->type = dt_drv->type; + + return probe_driver_node(fdt, elt); +} + +/* Lookup a compatible driver, possibly of a specific @type, for the FDT node */ +static TEE_Result probe_device_by_compat(const void *fdt, int node, + const char *compat, + enum dt_driver_type type) +{ + const struct dt_driver *drv = NULL; + const struct dt_device_match *dm = NULL; + + for_each_dt_driver(drv) { + if (drv->type != type) + continue; + + for (dm = drv->match_table; dm && dm->compatible; dm++) + if (strcmp(dm->compatible, compat) == 0) + return alloc_elt_and_probe(fdt, node, drv, dm); + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +/* + * Lookup the best matching compatible driver, possibly of a specific @type, + * for the FDT node. + */ +TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset, + enum dt_driver_type type) +{ + int idx = 0; + int len = 0; + int count = 0; + const char *compat = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + assert_type_is_valid(type); + + count = fdt_stringlist_count(fdt, nodeoffset, "compatible"); + if (count < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + for (idx = 0; idx < count; idx++) { + compat = fdt_stringlist_get(fdt, nodeoffset, "compatible", + idx, &len); + if (!compat) + return TEE_ERROR_GENERIC; + + res = probe_device_by_compat(fdt, nodeoffset, compat, type); + + if (res != TEE_ERROR_ITEM_NOT_FOUND) + return res; + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +static TEE_Result process_probe_list(const void *fdt) +{ + struct dt_driver_probe *elt = NULL; + struct dt_driver_probe *prev = NULL; + static unsigned int __maybe_unused loop_count; + static unsigned int __maybe_unused deferral_loop_count; + bool __maybe_unused one_deferred = false; + bool one_probed_ok = false; + + do { + loop_count++; + FMSG("Probe loop %u after %u for deferral(s)", loop_count, + deferral_loop_count); + + /* Hack here for TRACE_DEBUG messages on probe list elements */ + if (TRACE_LEVEL >= TRACE_FLOW) + print_probe_list(fdt); + + if (TAILQ_EMPTY(&dt_driver_probe_list)) + return TEE_SUCCESS; + + /* + * Probe from current end to top. Deferred probed node are + * pushed back after current tail for the next probe round. + * Reset probe result flags and see status after probe round. + */ + one_deferred = false; + one_probed_ok = false; + added_node = false; + + TAILQ_FOREACH_REVERSE_SAFE(elt, &dt_driver_probe_list, + dt_driver_probe_head, link, prev) { + TAILQ_REMOVE(&dt_driver_probe_list, elt, link); + + switch (probe_driver_node(fdt, elt)) { + case TEE_SUCCESS: + one_probed_ok = true; + break; + case TEE_ERROR_DEFER_DRIVER_INIT: + one_deferred = true; + break; + default: + break; + } + } + + if (one_deferred) + deferral_loop_count++; + + } while (added_node || one_probed_ok); + + DMSG("Unresolved dependencies after %u rounds, %u deferred", + loop_count, deferral_loop_count); + + if (one_deferred) + return TEE_ERROR_DEFER_DRIVER_INIT; + else + return TEE_ERROR_GENERIC; +} + +static int driver_probe_compare(struct dt_driver_probe *candidate, + struct dt_driver_probe *elt) +{ + if (candidate->nodeoffset != elt->nodeoffset || + candidate->type != elt->type) + return 1; + + assert(elt->dt_drv == candidate->dt_drv); + return 0; +} + +/* + * Return TEE_SUCCESS if compatible found + * TEE_ERROR_OUT_OF_MEMORY if heap is exhausted + */ +static TEE_Result add_node_to_probe(const void *fdt, int node, + const struct dt_driver *dt_drv, + const struct dt_device_match *dm) +{ + const char __maybe_unused *node_name = fdt_get_name(fdt, node, NULL); + const char __maybe_unused *drv_name = dt_drv->name; + struct dt_driver_probe *elt = NULL; + struct dt_driver_probe elt_new = { + .dm = dm, + .dt_drv = dt_drv, + .nodeoffset = node, + .type = dt_drv->type, + }; + + /* If node/type found in probe list or ready list, nothing to do */ + TAILQ_FOREACH(elt, &dt_driver_probe_list, link) + if (!driver_probe_compare(&elt_new, elt)) + return TEE_SUCCESS; + + TAILQ_FOREACH(elt, &dt_driver_ready_list, link) + if (!driver_probe_compare(&elt_new, elt)) + return TEE_SUCCESS; + + elt = malloc(sizeof(*elt)); + if (!elt) + return TEE_ERROR_OUT_OF_MEMORY; + + DMSG("element: %s on node %s", node_name, drv_name); + + memcpy(elt, &elt_new, sizeof(*elt)); + + added_node = true; + + TAILQ_INSERT_TAIL(&dt_driver_probe_list, elt, link); + + /* Hack here for TRACE_DEBUG messages on current probe list elements */ + if (TRACE_LEVEL >= TRACE_FLOW) + print_probe_list(fdt); + + return TEE_SUCCESS; +} + +/* + * Add a node to the probe list if a dt_driver matches target compatible. + * + * If @type is DT_DRIVER_ANY, probe list can hold only 1 driver to probe for + * the node. A node may probe several drivers if have a unique driver type. + * + * Return TEE_SUCCESS if compatible found + * TEE_ERROR_ITEM_NOT_FOUND if no matching driver + * TEE_ERROR_OUT_OF_MEMORY if heap is exhausted + */ +static TEE_Result add_probe_node_by_compat(const void *fdt, int node, + const char *compat) +{ + TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; + const struct dt_driver *dt_drv = NULL; + const struct dt_device_match *dm = NULL; + uint32_t found_types = 0; + + for_each_dt_driver(dt_drv) { + for (dm = dt_drv->match_table; dm && dm->compatible; dm++) { + if (strcmp(dm->compatible, compat) == 0) { + assert(dt_drv->type < 32); + + res = add_node_to_probe(fdt, node, dt_drv, dm); + if (res) + return res; + + if (found_types & BIT(dt_drv->type)) { + EMSG("Driver %s multi hit on type %u", + dt_drv->name, dt_drv->type); + panic(); + } + found_types |= BIT(dt_drv->type); + + /* Matching found for this driver, try next */ + break; + } + } + } + + return res; +} + +/* + * Add the node to the probe list if matching compatible drivers are found. + * Follow node's compatible property list ordering to find matching driver. + */ +TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int node) +{ + int idx = 0; + int len = 0; + int count = 0; + const char *compat = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED) + return TEE_SUCCESS; + + count = fdt_stringlist_count(fdt, node, "compatible"); + if (count < 0) + return TEE_SUCCESS; + + for (idx = 0; idx < count; idx++) { + compat = fdt_stringlist_get(fdt, node, "compatible", idx, &len); + assert(compat && len > 0); + + res = add_probe_node_by_compat(fdt, node, compat); + + /* Stop lookup if something was found */ + if (res != TEE_ERROR_ITEM_NOT_FOUND) + return res; + } + + return TEE_SUCCESS; +} + +static void parse_node(const void *fdt, int node) +{ + TEE_Result __maybe_unused res = TEE_ERROR_GENERIC; + int subnode = 0; + + fdt_for_each_subnode(subnode, fdt, node) { + res = dt_driver_maybe_add_probe_node(fdt, subnode); + if (res) { + EMSG("Failed on node %s with %#"PRIx32, + fdt_get_name(fdt, subnode, NULL), res); + panic(); + } + + /* + * Rescursively parse the FDT, skipping disabled nodes. + * FDT is expected reliable and core shall have sufficient + * stack depth to possibly parse all DT nodes. + */ + if (IS_ENABLED(CFG_DRIVERS_DT_RECURSIVE_PROBE)) { + if (fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) + continue; + + parse_node(fdt, subnode); + } + } +} + +/* + * Parse FDT for nodes and save in probe list the node for which a dt_driver + * matches node's compatible property. + */ +static TEE_Result probe_dt_drivers_early(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const void *fdt = NULL; + + fdt = get_secure_dt(); + if (!fdt) + return TEE_SUCCESS; + + parse_node(fdt, fdt_path_offset(fdt, "/")); + + res = process_probe_list(fdt); + if (res == TEE_ERROR_DEFER_DRIVER_INIT) { + DMSG("Deferred drivers probing"); + print_probe_list(fdt); + res = TEE_SUCCESS; + } + + return res; +} + +static TEE_Result probe_dt_drivers(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const void *fdt = NULL; + + fdt = get_secure_dt(); + if (!fdt) + return TEE_SUCCESS; + + res = process_probe_list(fdt); + if (res || !TAILQ_EMPTY(&dt_driver_failed_list)) { + EMSG("Probe sequence result: %#"PRIx32, res); + print_probe_list(fdt); + } + if (res) + panic(); + + return TEE_SUCCESS; +} + +early_init_late(probe_dt_drivers_early); +driver_init(probe_dt_drivers); + +static TEE_Result release_probe_lists(void) +{ + struct dt_driver_probe *elt = NULL; + struct dt_driver_probe *next = NULL; + struct dt_driver_provider *prov = NULL; + struct dt_driver_provider *next_prov = NULL; + const void *fdt = NULL; + + fdt = get_secure_dt(); + if (!fdt) + return TEE_SUCCESS; + + assert(fdt && TAILQ_EMPTY(&dt_driver_probe_list)); + + TAILQ_FOREACH_SAFE(elt, &dt_driver_ready_list, link, next) + free(elt); + + TAILQ_FOREACH_SAFE(elt, &dt_driver_failed_list, link, next) + free(elt); + + SLIST_FOREACH_SAFE(prov, &dt_driver_provider_list, link, next_prov) + free(prov); + + return TEE_SUCCESS; +} + +release_init_resource(release_probe_lists); + +/* + * Simple bus support: handy to parse subnodes + */ +static TEE_Result simple_bus_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int subnode = 0; + + fdt_for_each_subnode(subnode, fdt, node) { + res = dt_driver_maybe_add_probe_node(fdt, subnode); + if (res) { + EMSG("Failed on node %s with %#"PRIx32, + fdt_get_name(fdt, subnode, NULL), res); + panic(); + } + } + + return TEE_SUCCESS; +} + +static const struct dt_device_match simple_bus_match_table[] = { + { .compatible = "simple-bus" }, + { } +}; + +DEFINE_DT_DRIVER(simple_bus_dt_driver) = { + .name = "simple-bus", + .match_table = simple_bus_match_table, + .probe = simple_bus_probe, +}; diff --git a/optee/optee_os/core/kernel/dt_driver_test.c b/optee/optee_os/core/kernel/dt_driver_test.c new file mode 100644 index 0000000..2979d71 --- /dev/null +++ b/optee/optee_os/core/kernel/dt_driver_test.c @@ -0,0 +1,524 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + * + * Tests introduce dummy test drivers and assiciated devices defined in + * dt_driver_test.dtsi file with device resource dependencies. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DT_TEST_MSG(...) FMSG("(dt-driver-test) " __VA_ARGS__) + +/* Test state IDs */ +enum dt_test_sid { DEFAULT = 0, IN_PROGRESS, SUCCESS, FAILED }; + +/* + * DT tests state to be reported from PTA_INVOKE_TESTS_CMD_DT_TEST_STATUS + * possibly printed to console. A test can be skipped (DEFAULT) or be + * successful (SUCCESS) orthewise it has failed (IN_PROGRESS, FAILED). + */ +struct dt_test_state { + enum dt_test_sid probe_deferral; + enum dt_test_sid probe_clocks; + enum dt_test_sid probe_resets; + enum dt_test_sid crypto_dependencies; +}; + +/* + * References allocated from heap to be free once test completed + * dt_test_alloc(), dt_test_free(), dt_test_free_all() + */ +struct dt_test_free_ref { + void *p; + SLIST_ENTRY(dt_test_free_ref) link; +}; + +static struct dt_test_state dt_test_state; + +static const char __maybe_unused * const dt_test_str_sid[] = { + [DEFAULT] = "not passed", + [IN_PROGRESS] = "in-progress", + [SUCCESS] = "successful", + [FAILED] = "failed", +}; + +/* Reference allocations during test for release_init_resource initcall level */ +static SLIST_HEAD(dt_test_free_refs, dt_test_free_ref) dt_test_free_list = + SLIST_HEAD_INITIALIZER(dt_test_free_list); + +static void __maybe_unused *dt_test_alloc(size_t size) +{ + struct dt_test_free_ref *ref = NULL; + + ref = calloc(1, sizeof(*ref) + size); + if (!ref) + return NULL; + + ref->p = ref + 1; + SLIST_INSERT_HEAD(&dt_test_free_list, ref, link); + + return ref->p; +} + +static void __maybe_unused dt_test_free(void *p) +{ + struct dt_test_free_ref *ref = NULL; + struct dt_test_free_ref *t_ref = NULL; + + if (!p) + return; + + SLIST_FOREACH_SAFE(ref, &dt_test_free_list, link, t_ref) { + if (ref->p == p) { + SLIST_REMOVE(&dt_test_free_list, ref, + dt_test_free_ref, link); + free(ref); + return; + } + } + + panic(); +} + +static void dt_test_free_all(void) +{ + while (!SLIST_EMPTY(&dt_test_free_list)) { + struct dt_test_free_ref *ref = SLIST_FIRST(&dt_test_free_list); + + SLIST_REMOVE(&dt_test_free_list, ref, dt_test_free_ref, link); + free(ref); + } +} + +static TEE_Result dt_test_release(void) +{ + dt_test_free_all(); + + DT_TEST_MSG("Probe deferral: %s", + dt_test_str_sid[dt_test_state.probe_deferral]); + DT_TEST_MSG("Clocks probe: %s", + dt_test_str_sid[dt_test_state.probe_clocks]); + DT_TEST_MSG("Reset ctrl probe: %s", + dt_test_str_sid[dt_test_state.probe_resets]); + DT_TEST_MSG("Crypto deps.: %s", + dt_test_str_sid[dt_test_state.crypto_dependencies]); + + return dt_driver_test_status(); +} + +release_init_resource(dt_test_release); + +TEE_Result dt_driver_test_status(void) +{ + TEE_Result res = TEE_SUCCESS; + + if (dt_test_state.probe_deferral != SUCCESS) { + EMSG("Probe deferral test failed"); + res = TEE_ERROR_GENERIC; + } + if (IS_ENABLED(CFG_DRIVERS_CLK) && + dt_test_state.probe_clocks != SUCCESS) { + EMSG("Clocks probing test failed"); + res = TEE_ERROR_GENERIC; + } + if (IS_ENABLED(CFG_DRIVERS_RSTCTRL) && + dt_test_state.probe_resets != SUCCESS) { + EMSG("Reset controllers probing test failed"); + res = TEE_ERROR_GENERIC; + } + if (dt_test_state.crypto_dependencies != SUCCESS) { + EMSG("Probe deferral on crypto dependencies test failed"); + res = TEE_ERROR_GENERIC; + } + + return res; +} + +/* + * Consumer test driver: instance probed from the compatible + * node parsed in the DT. It consumes emulated resource obtained + * from DT references. Probe shall succeed only once all resources + * are found. + */ +static TEE_Result dt_test_consumer_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (IS_ENABLED(CFG_DRIVERS_CLK)) { + struct clk *clk0 = NULL; + struct clk *clk1 = NULL; + struct clk *clk = NULL; + + DT_TEST_MSG("Probe clocks"); + + res = clk_dt_get_by_index(fdt, node, 0, &clk0); + if (res) + goto err_probe; + res = clk_dt_get_by_index(fdt, node, 1, &clk1); + if (res) + goto err_probe; + + DT_TEST_MSG("Check valid clock references"); + + if (clk_enable(clk0)) { + DT_TEST_MSG("Can't enable %s", clk_get_name(clk0)); + return TEE_ERROR_GENERIC; + } + clk_disable(clk0); + + res = clk_dt_get_by_name(fdt, node, "clk0", &clk); + if (res || clk != clk0) { + DT_TEST_MSG("Unexpected clock reference"); + return TEE_ERROR_GENERIC; + } + + res = clk_dt_get_by_name(fdt, node, "clk1", &clk); + if (res || clk != clk1) { + DT_TEST_MSG("Unexpected clock reference"); + return TEE_ERROR_GENERIC; + } + + DT_TEST_MSG("Bad clock reference"); + + res = clk_dt_get_by_index(fdt, node, 3, &clk); + if (!res) { + DT_TEST_MSG("Unexpected clock found on invalid index"); + return TEE_ERROR_GENERIC; + } + + res = clk_dt_get_by_name(fdt, node, "clk2", &clk); + if (!res) { + DT_TEST_MSG("Unexpected clock found on invalid name"); + return TEE_ERROR_GENERIC; + } + + dt_test_state.probe_clocks = SUCCESS; + } + + if (IS_ENABLED(CFG_DRIVERS_RSTCTRL)) { + struct rstctrl *rstctrl0 = NULL; + struct rstctrl *rstctrl1 = NULL; + struct rstctrl *rstctrl = NULL; + + DT_TEST_MSG("Probe reset controllers"); + + res = rstctrl_dt_get_by_index(fdt, node, 0, &rstctrl0); + if (res) + goto err_probe; + + DT_TEST_MSG("Check valid reset controller"); + + if (rstctrl_assert(rstctrl0)) { + EMSG("Can't assert rstctrl %s", rstctrl_name(rstctrl0)); + return TEE_ERROR_GENERIC; + } + + res = rstctrl_dt_get_by_name(fdt, node, "rst0", &rstctrl); + if (res) + return res; + + if (rstctrl != rstctrl0) { + EMSG("Unexpected reset controller reference"); + return TEE_ERROR_GENERIC; + } + + res = rstctrl_dt_get_by_name(fdt, node, "rst1", &rstctrl1); + if (res) + goto err_probe; + + if (!rstctrl1 || rstctrl1 == rstctrl0) { + EMSG("Unexpected reset controller reference"); + return TEE_ERROR_GENERIC; + } + + dt_test_state.probe_resets = SUCCESS; + } + + if (dt_test_state.probe_deferral != IN_PROGRESS) { + dt_test_state.probe_deferral = FAILED; + return TEE_ERROR_GENERIC; + } + + dt_test_state.probe_deferral = SUCCESS; + + return TEE_SUCCESS; + +err_probe: + assert(res); + + if (res == TEE_ERROR_DEFER_DRIVER_INIT && + dt_test_state.probe_deferral == DEFAULT) { + /* We expect at least a probe deferral */ + dt_test_state.probe_deferral = IN_PROGRESS; + } + + return res; +} + +static const struct dt_device_match dt_test_consumer_match_table[] = { + { .compatible = "linaro,dt-test-consumer", }, + { } +}; + +DEFINE_DT_DRIVER(dt_test_consumer_driver) = { + .name = "dt-test-consumer", + .match_table = dt_test_consumer_match_table, + .probe = dt_test_consumer_probe, +}; + +static TEE_Result dt_test_crypt_consumer_probe(const void *fdt __unused, + int node __unused, + const void *compat_data __unused) +{ + TEE_Result res = dt_driver_get_crypto(); + uint8_t __maybe_unused byte = 0; + + if (res == TEE_ERROR_DEFER_DRIVER_INIT && + dt_test_state.crypto_dependencies == DEFAULT) { + /* We expect to be deferred */ + dt_test_state.crypto_dependencies = IN_PROGRESS; + } + + if (res) + return res; + + if (dt_test_state.crypto_dependencies == DEFAULT) { + EMSG("Test expects at least a driver probe deferral"); + dt_test_state.crypto_dependencies = FAILED; + return TEE_ERROR_GENERIC; + } + + if (crypto_rng_read(&byte, sizeof(byte))) { + dt_test_state.crypto_dependencies = FAILED; + return TEE_ERROR_GENERIC; + } + + dt_test_state.crypto_dependencies = SUCCESS; + return TEE_SUCCESS; +} + +static const struct dt_device_match dt_test_crypt_consumer_match_table[] = { + { .compatible = "linaro,dt-test-crypt-consumer", }, + { } +}; + +DEFINE_DT_DRIVER(dt_test_consumer_driver) = { + .name = "dt-test-crypt-consumer", + .match_table = dt_test_crypt_consumer_match_table, + .probe = dt_test_crypt_consumer_probe, +}; + +#ifdef CFG_DRIVERS_CLK +#define DT_TEST_CLK_COUNT 2 + +#define DT_TEST_CLK0_BINDING_ID 3 +#define DT_TEST_CLK1_BINDING_ID 7 + +static const char *dt_test_clk_name[DT_TEST_CLK_COUNT] = { + "dt_test-clk3", + "dt_test-clk7", +}; + +/* Emulating a clock does not require operators */ +static const struct clk_ops dt_test_clock_provider_ops; + +static struct clk *dt_test_get_clk(struct dt_driver_phandle_args *args, + void *data, TEE_Result *res) +{ + struct clk *clk_ref = data; + struct clk *clk = NULL; + + if (args->args_count != 1) { + *res = TEE_ERROR_BAD_PARAMETERS; + return NULL; + } + + switch (args->args[0]) { + case DT_TEST_CLK0_BINDING_ID: + clk = clk_ref; + break; + case DT_TEST_CLK1_BINDING_ID: + clk = clk_ref + 1; + break; + default: + EMSG("Unexpected binding ID %"PRIu32, args->args[0]); + *res = TEE_ERROR_BAD_PARAMETERS; + return NULL; + } + + DT_TEST_MSG("Providing clock %s", clk_get_name(clk)); + + *res = TEE_SUCCESS; + return clk; +} + +static TEE_Result dt_test_clock_provider_probe(const void *fdt, int node, + const void *compat_data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct clk *clk = NULL; + size_t n = 0; + + DT_TEST_MSG("Register clocks"); + + clk = dt_test_alloc(DT_TEST_CLK_COUNT * sizeof(*clk)); + if (!clk) + return TEE_ERROR_OUT_OF_MEMORY; + + for (n = 0; n < DT_TEST_CLK_COUNT; n++) { + clk[n].ops = &dt_test_clock_provider_ops; + clk[n].name = dt_test_clk_name[n]; + + res = clk_register(clk + n); + if (res) + goto err; + } + + res = clk_dt_register_clk_provider(fdt, node, dt_test_get_clk, clk); + if (res) + goto err; + + return TEE_SUCCESS; + +err: + dt_test_free(clk); + return res; +} + +CLK_DT_DECLARE(dt_test_clock_provider, "linaro,dt-test-provider", + dt_test_clock_provider_probe); +#endif /* CFG_DRIVERS_CLK */ + +#ifdef CFG_DRIVERS_RSTCTRL +#define DT_TEST_RSTCTRL_COUNT 2 + +#define DT_TEST_RSTCTRL0_BINDING_ID 5 +#define DT_TEST_RSTCTRL1_BINDING_ID 35 + +struct dt_test_rstctrl { + unsigned int dt_binding; + struct rstctrl rstctrl; +}; + +static struct dt_test_rstctrl *to_test_rstctrl(struct rstctrl *rstctrl) +{ + return container_of(rstctrl, struct dt_test_rstctrl, rstctrl); +} + +static TEE_Result dt_test_rstctrl_stub(struct rstctrl *rstctrl __maybe_unused, + unsigned int to_us __unused) +{ + struct dt_test_rstctrl *dev = to_test_rstctrl(rstctrl); + + switch (dev->dt_binding) { + case DT_TEST_RSTCTRL0_BINDING_ID: + case DT_TEST_RSTCTRL1_BINDING_ID: + return TEE_SUCCESS; + default: + EMSG("Unexpected rstctrl reference"); + return TEE_ERROR_GENERIC; + } +} + +static const char *dt_test_rstctrl_name(struct rstctrl *rstctrl __maybe_unused) +{ + static const char *rstctrl_name[DT_TEST_RSTCTRL_COUNT] = { + "dt_test-rstctrl5", + "dt_test-rstctrl35", + }; + struct dt_test_rstctrl *dev = to_test_rstctrl(rstctrl); + + switch (dev->dt_binding) { + case DT_TEST_RSTCTRL0_BINDING_ID: + return rstctrl_name[0]; + case DT_TEST_RSTCTRL1_BINDING_ID: + return rstctrl_name[1]; + default: + EMSG("Unexpected rstctrl reference"); + return NULL; + } +} + +const struct rstctrl_ops dt_test_rstctrl_ops = { + .assert_level = dt_test_rstctrl_stub, + .deassert_level = dt_test_rstctrl_stub, + .get_name = dt_test_rstctrl_name, +}; + +static struct rstctrl *dt_test_get_rstctrl(struct dt_driver_phandle_args *args, + void *data, TEE_Result *res) +{ + struct dt_test_rstctrl *ref = data; + struct rstctrl *rstctrl = NULL; + + if (args->args_count != 1) { + *res = TEE_ERROR_BAD_PARAMETERS; + return NULL; + } + + switch (args->args[0]) { + case DT_TEST_RSTCTRL0_BINDING_ID: + rstctrl = &ref[0].rstctrl; + break; + case DT_TEST_RSTCTRL1_BINDING_ID: + rstctrl = &ref[1].rstctrl; + break; + default: + EMSG("Unexpected binding ID %"PRIu32, args->args[0]); + *res = TEE_ERROR_BAD_PARAMETERS; + return NULL; + } + + DT_TEST_MSG("Providing reset controller %s", rstctrl_name(rstctrl)); + + *res = TEE_SUCCESS; + return rstctrl; +} + +static TEE_Result dt_test_rstctrl_provider_probe(const void *fdt, int offs, + const void *data __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct dt_test_rstctrl *devices = NULL; + + DT_TEST_MSG("Register reset controllers"); + + assert(rstctrl_ops_is_valid(&dt_test_rstctrl_ops)); + + devices = dt_test_alloc(DT_TEST_RSTCTRL_COUNT * sizeof(*devices)); + if (!devices) + return TEE_ERROR_OUT_OF_MEMORY; + + devices[0].rstctrl.ops = &dt_test_rstctrl_ops; + devices[0].dt_binding = DT_TEST_RSTCTRL0_BINDING_ID; + + devices[1].rstctrl.ops = &dt_test_rstctrl_ops; + devices[1].dt_binding = DT_TEST_RSTCTRL1_BINDING_ID; + + res = rstctrl_register_provider(fdt, offs, dt_test_get_rstctrl, + devices); + if (res) { + dt_test_free(devices); + return res; + } + + return TEE_SUCCESS; +} + +RSTCTRL_DT_DECLARE(dt_test_rstctrl_provider, "linaro,dt-test-provider", + dt_test_rstctrl_provider_probe); +#endif /* CFG_DRIVERS_RSTCTRL */ diff --git a/optee/optee_os/core/kernel/early_ta.c b/optee/optee_os/core/kernel/early_ta.c new file mode 100644 index 0000000..94f6c75 --- /dev/null +++ b/optee/optee_os/core/kernel/early_ta.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct embedded_ts *find_early_ta(const TEE_UUID *uuid) +{ + const struct embedded_ts *ta = NULL; + + for_each_early_ta(ta) + if (!memcmp(&ta->uuid, uuid, sizeof(*uuid))) + return ta; + + return NULL; +} + +static TEE_Result early_ta_open(const TEE_UUID *uuid, + struct ts_store_handle **h) +{ + return emb_ts_open(uuid, h, find_early_ta); +} + +REGISTER_TA_STORE(2) = { + .description = "early TA", + .open = early_ta_open, + .get_size = emb_ts_get_size, + .get_tag = emb_ts_get_tag, + .read = emb_ts_read, + .close = emb_ts_close, +}; + +static TEE_Result early_ta_init(void) +{ + const struct embedded_ts *ta = NULL; + char __maybe_unused msg[60] = { '\0', }; + + for_each_early_ta(ta) { + if (ta->uncompressed_size) + snprintf(msg, sizeof(msg), + " (compressed, uncompressed %u)", + ta->uncompressed_size); + else + msg[0] = '\0'; + DMSG("Early TA %pUl size %u%s", (void *)&ta->uuid, ta->size, + msg); + } + + return TEE_SUCCESS; +} + +service_init(early_ta_init); diff --git a/optee/optee_os/core/kernel/embedded_ts.c b/optee/optee_os/core/kernel/embedded_ts.c new file mode 100644 index 0000000..2f4a7c8 --- /dev/null +++ b/optee/optee_os/core/kernel/embedded_ts.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ts_store_handle { + const struct embedded_ts *ts; + size_t offs; + z_stream strm; +}; + +static void *zalloc(void *opaque __unused, unsigned int items, + unsigned int size) +{ + return mempool_alloc(mempool_default, items * size); +} + +static void zfree(void *opaque __unused, void *address) +{ + mempool_free(mempool_default, address); +} + +static bool decompression_init(z_stream *strm, + const struct embedded_ts *ts) +{ + int st = Z_OK; + + strm->next_in = ts->ts; + strm->avail_in = ts->size; + strm->zalloc = zalloc; + strm->zfree = zfree; + st = inflateInit(strm); + if (st != Z_OK) { + EMSG("Decompression initialization error (%d)", st); + return false; + } + + return true; +} + +TEE_Result emb_ts_open(const TEE_UUID *uuid, + struct ts_store_handle **h, + const struct embedded_ts* + (*find_ts) (const TEE_UUID *uuid)) +{ + struct ts_store_handle *handle = NULL; + const struct embedded_ts *ts = NULL; + + ts = find_ts(uuid); + if (!ts) + return TEE_ERROR_ITEM_NOT_FOUND; + + handle = calloc(1, sizeof(*handle)); + if (!handle) + return TEE_ERROR_OUT_OF_MEMORY; + + if (ts->uncompressed_size) { + if (!decompression_init(&handle->strm, ts)) { + free(handle); + return TEE_ERROR_BAD_FORMAT; + } + } + handle->ts = ts; + *h = handle; + + return TEE_SUCCESS; +} + +TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size) +{ + const struct embedded_ts *ts = h->ts; + + if (ts->uncompressed_size) + *size = ts->uncompressed_size; + else + *size = ts->size; + + return TEE_SUCCESS; +} + +TEE_Result emb_ts_get_tag(const struct ts_store_handle *h, + uint8_t *tag, unsigned int *tag_len) +{ + TEE_Result res = TEE_SUCCESS; + void *ctx = NULL; + + if (!tag || *tag_len < TEE_SHA256_HASH_SIZE) { + *tag_len = TEE_SHA256_HASH_SIZE; + return TEE_ERROR_SHORT_BUFFER; + } + *tag_len = TEE_SHA256_HASH_SIZE; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); + if (res) + return res; + res = crypto_hash_init(ctx); + if (res) + goto out; + res = crypto_hash_update(ctx, h->ts->ts, h->ts->size); + if (res) + goto out; + res = crypto_hash_final(ctx, tag, *tag_len); +out: + crypto_hash_free_ctx(ctx); + return res; +} + +static TEE_Result read_uncompressed(struct ts_store_handle *h, void *data, + size_t len) +{ + uint8_t *src = (uint8_t *)h->ts->ts + h->offs; + size_t next_offs = 0; + + if (ADD_OVERFLOW(h->offs, len, &next_offs) || + next_offs > h->ts->size) + return TEE_ERROR_BAD_PARAMETERS; + if (data) + memcpy(data, src, len); + h->offs = next_offs; + + return TEE_SUCCESS; +} + +static TEE_Result read_compressed(struct ts_store_handle *h, void *data, + size_t len) +{ + z_stream *strm = &h->strm; + size_t total = 0; + uint8_t *tmpbuf = NULL; + TEE_Result ret = TEE_SUCCESS; + size_t out = 0; + int st = Z_OK; + + if (data) { + strm->next_out = data; + strm->avail_out = len; + } else { + /* + * inflate() does not support a NULL strm->next_out. So, to + * discard data, we have to allocate a temporary buffer. 1K + * seems reasonable. + */ + strm->avail_out = MIN(len, 1024U); + tmpbuf = malloc(strm->avail_out); + if (!tmpbuf) { + EMSG("Out of memory"); + return TEE_ERROR_OUT_OF_MEMORY; + } + strm->next_out = tmpbuf; + } + /* + * Loop until we get as many bytes as requested, or an error occurs. + * inflate() returns: + * - Z_OK when progress was made, but neither the end of the input + * stream nor the end of the output buffer were met. + * - Z_STREAM_END when the end of the intput stream was reached. + * - Z_BUF_ERROR when there is still input to process but the output + * buffer is full (not a "hard" error, decompression can proceeed + * later). + */ + do { + out = strm->total_out; + st = inflate(strm, Z_SYNC_FLUSH); + out = strm->total_out - out; + total += out; + FMSG("%zu bytes", out); + if (!data) { + /* + * Reset the pointer to throw away what we've just read + * and read again as much as possible. + */ + strm->next_out = tmpbuf; + strm->avail_out = MIN(len - total, 1024U); + } + } while ((st == Z_OK || st == Z_BUF_ERROR) && (total != len)); + + if (st != Z_OK && st != Z_STREAM_END) { + EMSG("Decompression error (%d)", st); + ret = TEE_ERROR_GENERIC; + goto out; + } + ret = TEE_SUCCESS; +out: + free(tmpbuf); + + return ret; +} + +TEE_Result emb_ts_read(struct ts_store_handle *h, void *data, size_t len) +{ + if (h->ts->uncompressed_size) + return read_compressed(h, data, len); + else + return read_uncompressed(h, data, len); +} + +void emb_ts_close(struct ts_store_handle *h) +{ + if (h->ts->uncompressed_size) + inflateEnd(&h->strm); + free(h); +} + diff --git a/optee/optee_os/core/kernel/handle.c b/optee/optee_os/core/kernel/handle.c new file mode 100644 index 0000000..96f01cb --- /dev/null +++ b/optee/optee_os/core/kernel/handle.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ +#include +#include +#include + +/* + * Define the initial capacity of the database. It should be a low number + * multiple of 2 since some databases a likely to only use a few handles. + * Since the algorithm is to doubles up when growing it shouldn't cause a + * noticable overhead on large databases. + */ +#define HANDLE_DB_INITIAL_MAX_PTRS 4 + +void handle_db_destroy(struct handle_db *db, void (*ptr_destructor)(void *ptr)) +{ + if (db) { + if (ptr_destructor) { + size_t n = 0; + + for (n = 0; n < db->max_ptrs; n++) + if (db->ptrs[n]) + ptr_destructor(db->ptrs[n]); + } + free(db->ptrs); + db->ptrs = NULL; + db->max_ptrs = 0; + } +} + +bool handle_db_is_empty(struct handle_db *db) +{ + size_t n = 0; + + if (db) { + for (n = 0; n < db->max_ptrs; n++) { + if (db->ptrs[n]) + return false; + } + } + return true; +} + +int handle_get(struct handle_db *db, void *ptr) +{ + size_t n; + void *p; + size_t new_max_ptrs; + + if (!db || !ptr) + return -1; + + /* Try to find an empty location */ + for (n = 0; n < db->max_ptrs; n++) { + if (!db->ptrs[n]) { + db->ptrs[n] = ptr; + return n; + } + } + + /* No location available, grow the ptrs array */ + if (db->max_ptrs) + new_max_ptrs = db->max_ptrs * 2; + else + new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; + p = realloc(db->ptrs, new_max_ptrs * sizeof(void *)); + if (!p) + return -1; + db->ptrs = p; + memset(db->ptrs + db->max_ptrs, 0, + (new_max_ptrs - db->max_ptrs) * sizeof(void *)); + db->max_ptrs = new_max_ptrs; + + /* Since n stopped at db->max_ptrs there is an empty location there */ + db->ptrs[n] = ptr; + return n; +} + +void *handle_put(struct handle_db *db, int handle) +{ + void *p; + + if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) + return NULL; + + p = db->ptrs[handle]; + db->ptrs[handle] = NULL; + return p; +} + +void *handle_lookup(struct handle_db *db, int handle) +{ + if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) + return NULL; + + return db->ptrs[handle]; +} diff --git a/optee/optee_os/core/kernel/huk_subkey.c b/optee/optee_os/core/kernel/huk_subkey.c new file mode 100644 index 0000000..03088c9 --- /dev/null +++ b/optee/optee_os/core/kernel/huk_subkey.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +static TEE_Result mac_usage(void *ctx, uint32_t usage) +{ + return crypto_mac_update(ctx, (const void *)&usage, sizeof(usage)); +} + +#ifdef CFG_CORE_HUK_SUBKEY_COMPAT +static TEE_Result get_otp_die_id(uint8_t *buffer, size_t len) +{ + static const char pattern[4] = { 'B', 'E', 'E', 'F' }; + size_t i; + + if (IS_ENABLED(CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID)) + return tee_otp_get_die_id(buffer, len); + + for (i = 0; i < len; i++) + buffer[i] = pattern[i % 4]; + + return TEE_SUCCESS; +} + +/* + * This does special treatment for RPMB and SSK key derivations to give + * the same result as when huk_subkey_derive() wasn't used. + */ +static TEE_Result huk_compat(void *ctx, enum huk_subkey_usage usage) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH] = { 0 }; + static uint8_t ssk_str[] = "ONLY_FOR_tee_fs_ssk"; + + switch (usage) { + case HUK_SUBKEY_RPMB: + return TEE_SUCCESS; + case HUK_SUBKEY_SSK: + res = get_otp_die_id(chip_id, sizeof(chip_id)); + if (res) + return res; + res = crypto_mac_update(ctx, chip_id, sizeof(chip_id)); + if (res) + return res; + return crypto_mac_update(ctx, ssk_str, sizeof(ssk_str)); + default: + return mac_usage(ctx, usage); + } + +} +#endif /*CFG_CORE_HUK_SUBKEY_COMPAT*/ + +TEE_Result huk_subkey_derive(enum huk_subkey_usage usage, + const void *const_data, size_t const_data_len, + uint8_t *subkey, size_t subkey_len) +{ + void *ctx = NULL; + struct tee_hw_unique_key huk = { }; + TEE_Result res = TEE_SUCCESS; + + if (subkey_len > HUK_SUBKEY_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + if (!const_data && const_data_len) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); + if (res) + return res; + + res = tee_otp_get_hw_unique_key(&huk); + if (res) + goto out; + + res = crypto_mac_init(ctx, huk.data, sizeof(huk.data)); + if (res) + goto out; + +#ifdef CFG_CORE_HUK_SUBKEY_COMPAT + res = huk_compat(ctx, usage); +#else + res = mac_usage(ctx, usage); +#endif + if (res) + goto out; + + if (const_data) { + res = crypto_mac_update(ctx, const_data, const_data_len); + if (res) + goto out; + } + + res = crypto_mac_final(ctx, subkey, subkey_len); +out: + if (res) + memzero_explicit(subkey, subkey_len); + memzero_explicit(&huk, sizeof(huk)); + crypto_mac_free_ctx(ctx); + return res; +} diff --git a/optee/optee_os/core/kernel/initcall.c b/optee/optee_os/core/kernel/initcall.c new file mode 100644 index 0000000..148a178 --- /dev/null +++ b/optee/optee_os/core/kernel/initcall.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include + +/* + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area. + */ +void __weak call_preinitcalls(void) +{ + const struct initcall *call = NULL; + TEE_Result ret = TEE_SUCCESS; + + for (call = preinitcall_begin; call < preinitcall_end; call++) { + DMSG("level %d %s()", call->level, call->func_name); + ret = call->func(); + if (ret != TEE_SUCCESS) { + EMSG("Preinitcall __text_start + 0x%08" PRIxVA + " failed", (vaddr_t)call - VCORE_START_VA); + } + } +} + +/* + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area. + */ +void __weak call_initcalls(void) +{ + const struct initcall *call = NULL; + TEE_Result ret = TEE_SUCCESS; + + for (call = initcall_begin; call < initcall_end; call++) { + DMSG("level %d %s()", call->level, call->func_name); + ret = call->func(); + if (ret != TEE_SUCCESS) { + EMSG("Initcall __text_start + 0x%08" PRIxVA + " failed", (vaddr_t)call - VCORE_START_VA); + } + } +} + +/* + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area. + */ +void __weak call_finalcalls(void) +{ + const struct initcall *call = NULL; + TEE_Result ret = TEE_SUCCESS; + + for (call = finalcall_begin; call < finalcall_end; call++) { + DMSG("level %d %s()", call->level, call->func_name); + ret = call->func(); + if (ret != TEE_SUCCESS) { + EMSG("Finalcall __text_start + 0x%08" PRIxVA + " failed", (vaddr_t)call - VCORE_START_VA); + } + } +} diff --git a/optee/optee_os/core/kernel/interrupt.c b/optee/optee_os/core/kernel/interrupt.c new file mode 100644 index 0000000..0986edd --- /dev/null +++ b/optee/optee_os/core/kernel/interrupt.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * NOTE! + * + * We're assuming that there's no concurrent use of this interface, except + * delivery of interrupts in parallel. Synchronization will be needed when + * we begin to modify settings after boot initialization. + */ + +static struct itr_chip *itr_chip __nex_bss; +static SLIST_HEAD(, itr_handler) handlers __nex_data = + SLIST_HEAD_INITIALIZER(handlers); + +void itr_init(struct itr_chip *chip) +{ + itr_chip = chip; +} + +#ifdef CFG_DT +int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, + uint32_t *prio) +{ + const uint32_t *prop = NULL; + int count = 0; + int it_num = DT_INFO_INVALID_INTERRUPT; + + if (!itr_chip || !itr_chip->dt_get_irq) + return it_num; + + prop = fdt_getprop(fdt, node, "interrupts", &count); + if (!prop) + return it_num; + + return itr_chip->dt_get_irq(prop, count, type, prio); +} +#endif + +void itr_handle(size_t it) +{ + struct itr_handler *h = NULL; + bool was_handled = false; + + SLIST_FOREACH(h, &handlers, link) { + if (h->it == it) { + if (h->handler(h) == ITRR_HANDLED) + was_handled = true; + else if (!(h->flags & ITRF_SHARED)) + break; + } + } + + if (!was_handled) { + EMSG("Disabling unhandled interrupt %zu", it); + itr_chip->ops->disable(itr_chip, it); + } +} + +struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, + uint32_t flags, void *data, + uint32_t type, uint32_t prio) +{ + struct itr_handler *hdl = calloc(1, sizeof(*hdl)); + + if (hdl) { + hdl->it = it; + hdl->handler = handler; + hdl->flags = flags; + hdl->data = data; + itr_add_type_prio(hdl, type, prio); + } + + return hdl; +} + +void itr_free(struct itr_handler *hdl) +{ + if (!hdl) + return; + + itr_chip->ops->disable(itr_chip, hdl->it); + + SLIST_REMOVE(&handlers, hdl, itr_handler, link); + free(hdl); +} + +void itr_add_type_prio(struct itr_handler *h, uint32_t type, uint32_t prio) +{ + struct itr_handler __maybe_unused *hdl = NULL; + + SLIST_FOREACH(hdl, &handlers, link) + if (hdl->it == h->it) + assert((hdl->flags & ITRF_SHARED) && + (h->flags & ITRF_SHARED)); + + itr_chip->ops->add(itr_chip, h->it, type, prio); + SLIST_INSERT_HEAD(&handlers, h, link); +} + +void itr_enable(size_t it) +{ + itr_chip->ops->enable(itr_chip, it); +} + +void itr_disable(size_t it) +{ + itr_chip->ops->disable(itr_chip, it); +} + +void itr_raise_pi(size_t it) +{ + itr_chip->ops->raise_pi(itr_chip, it); +} + +void itr_raise_sgi(size_t it, uint8_t cpu_mask) +{ + itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask); +} + +void itr_set_affinity(size_t it, uint8_t cpu_mask) +{ + itr_chip->ops->set_affinity(itr_chip, it, cpu_mask); +} + +/* This function is supposed to be overridden in platform specific code */ +void __weak __noreturn itr_core_handler(void) +{ + panic("Secure interrupt handler not defined"); +} diff --git a/optee/optee_os/core/kernel/ldelf_loader.c b/optee/optee_os/core/kernel/ldelf_loader.c new file mode 100644 index 0000000..cb82e2c --- /dev/null +++ b/optee/optee_os/core/kernel/ldelf_loader.c @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015-2020, 2022 Linaro Limited + * Copyright (c) 2020-2023, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +extern uint8_t ldelf_data[]; +extern const unsigned int ldelf_code_size; +extern const unsigned int ldelf_data_size; +extern const unsigned int ldelf_entry; + +/* ldelf has the same architecture/register width as the kernel */ +#if defined(ARM32) || defined(RV32) +static const bool is_32bit = true; +#else +static const bool is_32bit; +#endif + +static TEE_Result alloc_and_map_ldelf_fobj(struct user_mode_ctx *uctx, + size_t sz, uint32_t prot, + vaddr_t *va) +{ + size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; + struct fobj *fobj = fobj_ta_mem_alloc(num_pgs); + struct mobj *mobj = mobj_with_fobj_alloc(fobj, NULL, + TEE_MATTR_MEM_TYPE_TAGGED); + TEE_Result res = TEE_SUCCESS; + + fobj_put(fobj); + if (!mobj) + return TEE_ERROR_OUT_OF_MEMORY; + res = vm_map(uctx, va, num_pgs * SMALL_PAGE_SIZE, + prot, VM_FLAG_LDELF, mobj, 0); + mobj_put(mobj); + + return res; +} + +/* + * This function may leave a few mappings behind on error, but that's taken + * care of by tee_ta_init_user_ta_session() since the entire context is + * removed then. + */ +TEE_Result ldelf_load_ldelf(struct user_mode_ctx *uctx) +{ + TEE_Result res = TEE_SUCCESS; + vaddr_t stack_addr = 0; + vaddr_t code_addr = 0; + vaddr_t rw_addr = 0; + uint32_t prot = 0; + + uctx->is_32bit = is_32bit; + + res = alloc_and_map_ldelf_fobj(uctx, LDELF_STACK_SIZE, + TEE_MATTR_URW | TEE_MATTR_PRW, + &stack_addr); + if (res) + return res; + uctx->ldelf_stack_ptr = stack_addr + LDELF_STACK_SIZE; + + res = alloc_and_map_ldelf_fobj(uctx, ldelf_code_size, TEE_MATTR_PRW, + &code_addr); + if (res) + return res; + uctx->entry_func = code_addr + ldelf_entry; + + rw_addr = ROUNDUP(code_addr + ldelf_code_size, SMALL_PAGE_SIZE); + res = alloc_and_map_ldelf_fobj(uctx, ldelf_data_size, + TEE_MATTR_URW | TEE_MATTR_PRW, &rw_addr); + if (res) + return res; + + vm_set_ctx(uctx->ts_ctx); + + memcpy((void *)code_addr, ldelf_data, ldelf_code_size); + memcpy((void *)rw_addr, ldelf_data + ldelf_code_size, ldelf_data_size); + + prot = TEE_MATTR_URX; + if (IS_ENABLED(CFG_CORE_BTI)) + prot |= TEE_MATTR_GUARDED; + + res = vm_set_prot(uctx, code_addr, + ROUNDUP(ldelf_code_size, SMALL_PAGE_SIZE), prot); + if (res) + return res; + + DMSG("ldelf load address %#"PRIxVA, code_addr); + + return TEE_SUCCESS; +} + +TEE_Result ldelf_init_with_ldelf(struct ts_session *sess, + struct user_mode_ctx *uctx) +{ + TEE_Result res = TEE_SUCCESS; + struct ldelf_arg *arg = NULL; + uint32_t panic_code = 0; + uint32_t panicked = 0; + uaddr_t usr_stack = 0; + + usr_stack = uctx->ldelf_stack_ptr; + usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); + arg = (struct ldelf_arg *)usr_stack; + memset(arg, 0, sizeof(*arg)); + arg->uuid = uctx->ts_ctx->uuid; + sess->handle_scall = scall_handle_ldelf; + + res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, + usr_stack, uctx->entry_func, + is_32bit, &panicked, &panic_code); + + sess->handle_scall = sess->ctx->ops->handle_scall; + thread_user_clear_vfp(uctx); + ldelf_sess_cleanup(sess); + + if (panicked) { + abort_print_current_ts(); + EMSG("ldelf panicked"); + return TEE_ERROR_GENERIC; + } + if (res) { + EMSG("ldelf failed with res: %#"PRIx32, res); + return res; + } + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)arg, sizeof(*arg)); + if (res) + return res; + + if (is_user_ta_ctx(uctx->ts_ctx)) { + /* + * This is already checked by the elf loader, but since it runs + * in user mode we're not trusting it entirely. + */ + if (arg->flags & ~TA_FLAGS_MASK) + return TEE_ERROR_BAD_FORMAT; + + to_user_ta_ctx(uctx->ts_ctx)->ta_ctx.flags = arg->flags; + } + + uctx->is_32bit = arg->is_32bit; + uctx->entry_func = arg->entry_func; + uctx->load_addr = arg->load_addr; + uctx->stack_ptr = arg->stack_ptr; + uctx->dump_entry_func = arg->dump_entry; +#ifdef CFG_FTRACE_SUPPORT + uctx->ftrace_entry_func = arg->ftrace_entry; + sess->fbuf = arg->fbuf; +#endif + uctx->dl_entry_func = arg->dl_entry; + + return TEE_SUCCESS; +} + +TEE_Result ldelf_dump_state(struct user_mode_ctx *uctx) +{ + TEE_Result res = TEE_SUCCESS; + uaddr_t usr_stack = uctx->ldelf_stack_ptr; + struct dump_entry_arg *arg = NULL; + uint32_t panic_code = 0; + uint32_t panicked = 0; + struct thread_specific_data *tsd = thread_get_tsd(); + struct ts_session *sess = NULL; + struct vm_region *r = NULL; + size_t n = 0; + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) + if (r->attr & TEE_MATTR_URWX) + n++; + + usr_stack = uctx->ldelf_stack_ptr; + usr_stack -= ROUNDUP(sizeof(*arg) + n * sizeof(struct dump_map), + STACK_ALIGNMENT); + arg = (struct dump_entry_arg *)usr_stack; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)arg, sizeof(*arg)); + if (res) { + EMSG("ldelf stack is inaccessible!"); + return res; + } + + memset(arg, 0, sizeof(*arg) + n * sizeof(struct dump_map)); + + arg->num_maps = n; + n = 0; + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { + if (r->attr & TEE_MATTR_URWX) { + if (r->mobj) + mobj_get_pa(r->mobj, r->offset, 0, + &arg->maps[n].pa); + arg->maps[n].va = r->va; + arg->maps[n].sz = r->size; + if (r->attr & TEE_MATTR_UR) + arg->maps[n].flags |= DUMP_MAP_READ; + if (r->attr & TEE_MATTR_UW) + arg->maps[n].flags |= DUMP_MAP_WRITE; + if (r->attr & TEE_MATTR_UX) + arg->maps[n].flags |= DUMP_MAP_EXEC; + if (r->attr & TEE_MATTR_SECURE) + arg->maps[n].flags |= DUMP_MAP_SECURE; + if (r->flags & VM_FLAG_EPHEMERAL) + arg->maps[n].flags |= DUMP_MAP_EPHEM; + if (r->flags & VM_FLAG_LDELF) + arg->maps[n].flags |= DUMP_MAP_LDELF; + n++; + } + } + + arg->is_32bit = uctx->is_32bit; +#ifdef ARM32 + arg->arm32.regs[0] = tsd->abort_regs.r0; + arg->arm32.regs[1] = tsd->abort_regs.r1; + arg->arm32.regs[2] = tsd->abort_regs.r2; + arg->arm32.regs[3] = tsd->abort_regs.r3; + arg->arm32.regs[4] = tsd->abort_regs.r4; + arg->arm32.regs[5] = tsd->abort_regs.r5; + arg->arm32.regs[6] = tsd->abort_regs.r6; + arg->arm32.regs[7] = tsd->abort_regs.r7; + arg->arm32.regs[8] = tsd->abort_regs.r8; + arg->arm32.regs[9] = tsd->abort_regs.r9; + arg->arm32.regs[10] = tsd->abort_regs.r10; + arg->arm32.regs[11] = tsd->abort_regs.r11; + arg->arm32.regs[12] = tsd->abort_regs.ip; + arg->arm32.regs[13] = tsd->abort_regs.usr_sp; /*SP*/ + arg->arm32.regs[14] = tsd->abort_regs.usr_lr; /*LR*/ + arg->arm32.regs[15] = tsd->abort_regs.elr; /*PC*/ +#endif /*ARM32*/ +#ifdef ARM64 + if (uctx->is_32bit) { + arg->arm32.regs[0] = tsd->abort_regs.x0; + arg->arm32.regs[1] = tsd->abort_regs.x1; + arg->arm32.regs[2] = tsd->abort_regs.x2; + arg->arm32.regs[3] = tsd->abort_regs.x3; + arg->arm32.regs[4] = tsd->abort_regs.x4; + arg->arm32.regs[5] = tsd->abort_regs.x5; + arg->arm32.regs[6] = tsd->abort_regs.x6; + arg->arm32.regs[7] = tsd->abort_regs.x7; + arg->arm32.regs[8] = tsd->abort_regs.x8; + arg->arm32.regs[9] = tsd->abort_regs.x9; + arg->arm32.regs[10] = tsd->abort_regs.x10; + arg->arm32.regs[11] = tsd->abort_regs.x11; + arg->arm32.regs[12] = tsd->abort_regs.x12; + arg->arm32.regs[13] = tsd->abort_regs.x13; /*SP*/ + arg->arm32.regs[14] = tsd->abort_regs.x14; /*LR*/ + arg->arm32.regs[15] = tsd->abort_regs.elr; /*PC*/ + } else { + arg->arm64.fp = tsd->abort_regs.x29; + arg->arm64.pc = tsd->abort_regs.elr; + arg->arm64.sp = tsd->abort_regs.sp_el0; + } +#endif /*ARM64*/ +#if defined(RV64) || defined(RV32) + arg->rv.fp = tsd->abort_regs.s0; + arg->rv.pc = tsd->abort_regs.epc; + arg->rv.sp = tsd->abort_regs.sp; +#endif /*RV64||RV32*/ + + sess = ts_get_current_session(); + sess->handle_scall = scall_handle_ldelf; + + res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, + usr_stack, uctx->dump_entry_func, + is_32bit, &panicked, &panic_code); + + sess->handle_scall = sess->ctx->ops->handle_scall; + thread_user_clear_vfp(uctx); + ldelf_sess_cleanup(sess); + + if (panicked) { + uctx->dump_entry_func = 0; + EMSG("ldelf dump function panicked"); + abort_print_current_ts(); + res = TEE_ERROR_TARGET_DEAD; + } + + return res; +} + +#ifdef CFG_FTRACE_SUPPORT +TEE_Result ldelf_dump_ftrace(struct user_mode_ctx *uctx, + void *buf, size_t *blen) +{ + uaddr_t usr_stack = uctx->ldelf_stack_ptr; + TEE_Result res = TEE_SUCCESS; + uint32_t panic_code = 0; + uint32_t panicked = 0; + size_t *arg = NULL; + struct ts_session *sess = NULL; + + if (!uctx->ftrace_entry_func) + return TEE_ERROR_NOT_SUPPORTED; + + usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); + arg = (size_t *)usr_stack; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)arg, sizeof(*arg)); + if (res) { + EMSG("ldelf stack is inaccessible!"); + return res; + } + + *arg = *blen; + + sess = ts_get_current_session(); + sess->handle_scall = scall_handle_ldelf; + + res = thread_enter_user_mode((vaddr_t)buf, (vaddr_t)arg, 0, 0, + usr_stack, uctx->ftrace_entry_func, + is_32bit, &panicked, &panic_code); + + sess->handle_scall = sess->ctx->ops->handle_scall; + thread_user_clear_vfp(uctx); + ldelf_sess_cleanup(sess); + + if (panicked) { + uctx->ftrace_entry_func = 0; + EMSG("ldelf ftrace function panicked"); + abort_print_current_ts(); + res = TEE_ERROR_TARGET_DEAD; + } + + if (!res) { + if (*arg > *blen) + res = TEE_ERROR_SHORT_BUFFER; + *blen = *arg; + } + + return res; +} +#endif /*CFG_FTRACE_SUPPORT*/ + +TEE_Result ldelf_dlopen(struct user_mode_ctx *uctx, TEE_UUID *uuid, + uint32_t flags) +{ + uaddr_t usr_stack = uctx->ldelf_stack_ptr; + TEE_Result res = TEE_ERROR_GENERIC; + struct dl_entry_arg *arg = NULL; + uint32_t panic_code = 0; + uint32_t panicked = 0; + struct ts_session *sess = NULL; + + assert(uuid); + + usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); + arg = (struct dl_entry_arg *)usr_stack; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)arg, sizeof(*arg)); + if (res) { + EMSG("ldelf stack is inaccessible!"); + return res; + } + + memset(arg, 0, sizeof(*arg)); + arg->cmd = LDELF_DL_ENTRY_DLOPEN; + arg->dlopen.uuid = *uuid; + arg->dlopen.flags = flags; + + sess = ts_get_current_session(); + sess->handle_scall = scall_handle_ldelf; + + res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, + usr_stack, uctx->dl_entry_func, + is_32bit, &panicked, &panic_code); + + sess->handle_scall = sess->ctx->ops->handle_scall; + ldelf_sess_cleanup(sess); + + if (panicked) { + EMSG("ldelf dl_entry function panicked"); + abort_print_current_ts(); + res = TEE_ERROR_TARGET_DEAD; + } + if (!res) + res = arg->ret; + + return res; +} + +TEE_Result ldelf_dlsym(struct user_mode_ctx *uctx, TEE_UUID *uuid, + const char *sym, size_t maxlen, vaddr_t *val) +{ + uaddr_t usr_stack = uctx->ldelf_stack_ptr; + TEE_Result res = TEE_ERROR_GENERIC; + struct dl_entry_arg *arg = NULL; + uint32_t panic_code = 0; + uint32_t panicked = 0; + size_t len = strnlen(sym, maxlen); + struct ts_session *sess = NULL; + + if (len == maxlen) + return TEE_ERROR_BAD_PARAMETERS; + + usr_stack -= ROUNDUP(sizeof(*arg) + len + 1, STACK_ALIGNMENT); + arg = (struct dl_entry_arg *)usr_stack; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)arg, sizeof(*arg) + len + 1); + if (res) { + EMSG("ldelf stack is inaccessible!"); + return res; + } + + memset(arg, 0, sizeof(*arg)); + arg->cmd = LDELF_DL_ENTRY_DLSYM; + arg->dlsym.uuid = *uuid; + memcpy(arg->dlsym.symbol, sym, len); + arg->dlsym.symbol[len] = '\0'; + + sess = ts_get_current_session(); + sess->handle_scall = scall_handle_ldelf; + + res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, + usr_stack, uctx->dl_entry_func, + is_32bit, &panicked, &panic_code); + + sess->handle_scall = sess->ctx->ops->handle_scall; + ldelf_sess_cleanup(sess); + + if (panicked) { + EMSG("ldelf dl_entry function panicked"); + abort_print_current_ts(); + res = TEE_ERROR_TARGET_DEAD; + } + if (!res) { + res = arg->ret; + if (!res) + *val = arg->dlsym.val; + } + + return res; +} diff --git a/optee/optee_os/core/kernel/ldelf_syscalls.c b/optee/optee_os/core/kernel/ldelf_syscalls.c new file mode 100644 index 0000000..9c9fa35 --- /dev/null +++ b/optee/optee_os/core/kernel/ldelf_syscalls.c @@ -0,0 +1,549 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2019, 2022 Linaro Limited + * Copyright (c) 2020-2021, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct bin_handle { + const struct ts_store_ops *op; + struct ts_store_handle *h; + struct file *f; + size_t offs_bytes; + size_t size_bytes; +}; + +TEE_Result ldelf_syscall_map_zi(vaddr_t *va, size_t num_bytes, size_t pad_begin, + size_t pad_end, unsigned long flags) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); + struct fobj *f = NULL; + struct mobj *mobj = NULL; + uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW; + uint32_t vm_flags = 0; + + if (flags & ~LDELF_MAP_FLAG_SHAREABLE) + return TEE_ERROR_BAD_PARAMETERS; + + if (flags & LDELF_MAP_FLAG_SHAREABLE) + vm_flags |= VM_FLAG_SHAREABLE; + + f = fobj_ta_mem_alloc(ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE)); + if (!f) + return TEE_ERROR_OUT_OF_MEMORY; + mobj = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); + fobj_put(f); + if (!mobj) + return TEE_ERROR_OUT_OF_MEMORY; + res = vm_map_pad(uctx, va, num_bytes, prot, vm_flags, + mobj, 0, pad_begin, pad_end, 0); + mobj_put(mobj); + + return res; +} + +TEE_Result ldelf_syscall_unmap(vaddr_t va, size_t num_bytes) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); + size_t sz = ROUNDUP(num_bytes, SMALL_PAGE_SIZE); + uint32_t vm_flags = 0; + vaddr_t end_va = 0; + + /* + * The vm_get_flags() and vm_unmap() are supposed to detect or handle + * overflow directly or indirectly. However, since this function is an + * API function it's worth having an extra guard here. If nothing else, + * to increase code clarity. + */ + if (ADD_OVERFLOW(va, sz, &end_va)) + return TEE_ERROR_BAD_PARAMETERS; + + res = vm_get_flags(uctx, va, sz, &vm_flags); + if (res) + return res; + if (vm_flags & VM_FLAG_PERMANENT) + return TEE_ERROR_ACCESS_DENIED; + + return vm_unmap(uctx, va, sz); +} + +static void bin_close(void *ptr) +{ + struct bin_handle *binh = ptr; + + if (binh) { + if (binh->op && binh->h) + binh->op->close(binh->h); + file_put(binh->f); + } + free(binh); +} + +TEE_Result ldelf_syscall_open_bin(const TEE_UUID *uuid, size_t uuid_size, + uint32_t *handle) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); + struct system_ctx *sys_ctx = sess->user_ctx; + struct bin_handle *binh = NULL; + uint8_t tag[FILE_TAG_SIZE] = { 0 }; + unsigned int tag_len = sizeof(tag); + int h = 0; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)uuid, sizeof(TEE_UUID)); + if (res) + return res; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)handle, sizeof(uint32_t)); + if (res) + return res; + + if (uuid_size != sizeof(*uuid)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!sys_ctx) { + sys_ctx = calloc(1, sizeof(*sys_ctx)); + if (!sys_ctx) + return TEE_ERROR_OUT_OF_MEMORY; + sess->user_ctx = sys_ctx; + } + + binh = calloc(1, sizeof(*binh)); + if (!binh) + return TEE_ERROR_OUT_OF_MEMORY; + + if (is_user_ta_ctx(sess->ctx) || is_stmm_ctx(sess->ctx)) { + SCATTERED_ARRAY_FOREACH(binh->op, ta_stores, + struct ts_store_ops) { + DMSG("Lookup user TA ELF %pUl (%s)", + (void *)uuid, binh->op->description); + + res = binh->op->open(uuid, &binh->h); + DMSG("res=%#"PRIx32, res); + if (res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + break; + } + } else if (is_sp_ctx(sess->ctx)) { + SCATTERED_ARRAY_FOREACH(binh->op, sp_stores, + struct ts_store_ops) { + DMSG("Lookup user SP ELF %pUl (%s)", + (void *)uuid, binh->op->description); + + res = binh->op->open(uuid, &binh->h); + DMSG("res=%#"PRIx32, res); + if (res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + break; + } + } else { + res = TEE_ERROR_ITEM_NOT_FOUND; + } + + if (res) + goto err; + + res = binh->op->get_size(binh->h, &binh->size_bytes); + if (res) + goto err; + res = binh->op->get_tag(binh->h, tag, &tag_len); + if (res) + goto err; + binh->f = file_get_by_tag(tag, tag_len); + if (!binh->f) + goto err_oom; + + h = handle_get(&sys_ctx->db, binh); + if (h < 0) + goto err_oom; + *handle = h; + + return TEE_SUCCESS; + +err_oom: + res = TEE_ERROR_OUT_OF_MEMORY; +err: + bin_close(binh); + return res; +} + +TEE_Result ldelf_syscall_close_bin(unsigned long handle) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct system_ctx *sys_ctx = sess->user_ctx; + struct bin_handle *binh = NULL; + + if (!sys_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + binh = handle_put(&sys_ctx->db, handle); + if (!binh) + return TEE_ERROR_BAD_PARAMETERS; + + if (binh->offs_bytes < binh->size_bytes) + res = binh->op->read(binh->h, NULL, + binh->size_bytes - binh->offs_bytes); + + bin_close(binh); + if (handle_db_is_empty(&sys_ctx->db)) { + handle_db_destroy(&sys_ctx->db, bin_close); + free(sys_ctx); + sess->user_ctx = NULL; + } + + return res; +} + +static TEE_Result binh_copy_to(struct bin_handle *binh, vaddr_t va, + size_t offs_bytes, size_t num_bytes) +{ + TEE_Result res = TEE_SUCCESS; + size_t next_offs = 0; + + if (offs_bytes < binh->offs_bytes) + return TEE_ERROR_BAD_STATE; + + if (ADD_OVERFLOW(offs_bytes, num_bytes, &next_offs)) + return TEE_ERROR_BAD_PARAMETERS; + + if (offs_bytes > binh->offs_bytes) { + res = binh->op->read(binh->h, NULL, + offs_bytes - binh->offs_bytes); + if (res) + return res; + binh->offs_bytes = offs_bytes; + } + + if (next_offs > binh->size_bytes) { + size_t rb = binh->size_bytes - binh->offs_bytes; + + res = binh->op->read(binh->h, (void *)va, rb); + if (res) + return res; + memset((uint8_t *)va + rb, 0, num_bytes - rb); + binh->offs_bytes = binh->size_bytes; + } else { + res = binh->op->read(binh->h, (void *)va, num_bytes); + if (res) + return res; + binh->offs_bytes = next_offs; + } + + return TEE_SUCCESS; +} + +TEE_Result ldelf_syscall_map_bin(vaddr_t *va, size_t num_bytes, + unsigned long handle, size_t offs_bytes, + size_t pad_begin, size_t pad_end, + unsigned long flags) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); + struct system_ctx *sys_ctx = sess->user_ctx; + struct bin_handle *binh = NULL; + uint32_t num_rounded_bytes = 0; + struct file_slice *fs = NULL; + bool file_is_locked = false; + struct mobj *mobj = NULL; + uint32_t offs_pages = 0; + size_t num_pages = 0; + uint32_t prot = 0; + const uint32_t accept_flags = LDELF_MAP_FLAG_SHAREABLE | + LDELF_MAP_FLAG_WRITEABLE | + LDELF_MAP_FLAG_BTI | + LDELF_MAP_FLAG_EXECUTABLE; + + if (!sys_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + binh = handle_lookup(&sys_ctx->db, handle); + if (!binh) + return TEE_ERROR_BAD_PARAMETERS; + + if ((flags & accept_flags) != flags) + return TEE_ERROR_BAD_PARAMETERS; + + if ((flags & LDELF_MAP_FLAG_SHAREABLE) && + (flags & LDELF_MAP_FLAG_WRITEABLE)) + return TEE_ERROR_BAD_PARAMETERS; + + if ((flags & LDELF_MAP_FLAG_EXECUTABLE) && + (flags & LDELF_MAP_FLAG_WRITEABLE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (offs_bytes & SMALL_PAGE_MASK) + return TEE_ERROR_BAD_PARAMETERS; + + prot = TEE_MATTR_UR | TEE_MATTR_PR; + if (flags & LDELF_MAP_FLAG_WRITEABLE) + prot |= TEE_MATTR_UW | TEE_MATTR_PW; + if (flags & LDELF_MAP_FLAG_EXECUTABLE) + prot |= TEE_MATTR_UX; + if (flags & LDELF_MAP_FLAG_BTI) + prot |= TEE_MATTR_GUARDED; + + offs_pages = offs_bytes >> SMALL_PAGE_SHIFT; + if (ROUNDUP_OVERFLOW(num_bytes, SMALL_PAGE_SIZE, &num_rounded_bytes)) + return TEE_ERROR_BAD_PARAMETERS; + num_pages = num_rounded_bytes / SMALL_PAGE_SIZE; + + if (!file_trylock(binh->f)) { + /* + * Before we can block on the file lock we must make all + * our page tables available for reclaiming in order to + * avoid a dead-lock with the other thread (which already + * is holding the file lock) mapping lots of memory below. + */ + vm_set_ctx(NULL); + file_lock(binh->f); + vm_set_ctx(uctx->ts_ctx); + } + file_is_locked = true; + fs = file_find_slice(binh->f, offs_pages); + if (fs) { + /* If there's registered slice it has to match */ + if (fs->page_offset != offs_pages || + num_pages > fs->fobj->num_pages) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + /* If there's a slice we must be mapping shareable */ + if (!(flags & LDELF_MAP_FLAG_SHAREABLE)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + mobj = mobj_with_fobj_alloc(fs->fobj, binh->f, + TEE_MATTR_MEM_TYPE_TAGGED); + if (!mobj) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + res = vm_map_pad(uctx, va, num_rounded_bytes, + prot, VM_FLAG_READONLY, + mobj, 0, pad_begin, pad_end, 0); + mobj_put(mobj); + if (res) + goto err; + } else { + struct fobj *f = fobj_ta_mem_alloc(num_pages); + struct file *file = NULL; + uint32_t vm_flags = 0; + + if (!f) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + if (!(flags & LDELF_MAP_FLAG_WRITEABLE)) { + file = binh->f; + vm_flags |= VM_FLAG_READONLY; + } + + mobj = mobj_with_fobj_alloc(f, file, TEE_MATTR_MEM_TYPE_TAGGED); + fobj_put(f); + if (!mobj) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + res = vm_map_pad(uctx, va, num_rounded_bytes, + TEE_MATTR_PRW, vm_flags, mobj, 0, + pad_begin, pad_end, 0); + mobj_put(mobj); + if (res) + goto err; + res = binh_copy_to(binh, *va, offs_bytes, num_bytes); + if (res) + goto err_unmap_va; + res = vm_set_prot(uctx, *va, num_rounded_bytes, + prot); + if (res) + goto err_unmap_va; + + /* + * The context currently is active set it again to update + * the mapping. + */ + vm_set_ctx(uctx->ts_ctx); + + if (!(flags & LDELF_MAP_FLAG_WRITEABLE)) { + res = file_add_slice(binh->f, f, offs_pages); + if (res) + goto err_unmap_va; + } + } + + file_unlock(binh->f); + + return TEE_SUCCESS; + +err_unmap_va: + if (vm_unmap(uctx, *va, num_rounded_bytes)) + panic(); + + /* + * The context currently is active set it again to update + * the mapping. + */ + vm_set_ctx(uctx->ts_ctx); + +err: + if (file_is_locked) + file_unlock(binh->f); + + return res; +} + +TEE_Result ldelf_syscall_copy_from_bin(void *dst, size_t offs, size_t num_bytes, + unsigned long handle) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); + struct system_ctx *sys_ctx = sess->user_ctx; + struct bin_handle *binh = NULL; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)dst, num_bytes); + if (res) + return res; + + if (!sys_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + binh = handle_lookup(&sys_ctx->db, handle); + if (!binh) + return TEE_ERROR_BAD_PARAMETERS; + + return binh_copy_to(binh, (vaddr_t)dst, offs, num_bytes); +} + +TEE_Result ldelf_syscall_set_prot(unsigned long va, size_t num_bytes, + unsigned long flags) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); + size_t sz = ROUNDUP(num_bytes, SMALL_PAGE_SIZE); + uint32_t prot = TEE_MATTR_UR | TEE_MATTR_PR; + uint32_t vm_flags = 0; + vaddr_t end_va = 0; + const uint32_t accept_flags = LDELF_MAP_FLAG_WRITEABLE | + LDELF_MAP_FLAG_BTI | + LDELF_MAP_FLAG_EXECUTABLE; + + if ((flags & accept_flags) != flags) + return TEE_ERROR_BAD_PARAMETERS; + if (flags & LDELF_MAP_FLAG_WRITEABLE) + prot |= TEE_MATTR_UW | TEE_MATTR_PW; + if (flags & LDELF_MAP_FLAG_EXECUTABLE) + prot |= TEE_MATTR_UX; + if (flags & LDELF_MAP_FLAG_BTI) + prot |= TEE_MATTR_GUARDED; + + /* + * The vm_get_flags() and vm_unmap() are supposed to detect or handle + * overflow directly or indirectly. However, since this function is an + * API function it's worth having an extra guard here. If nothing else, + * to increase code clarity. + */ + if (ADD_OVERFLOW(va, sz, &end_va)) + return TEE_ERROR_BAD_PARAMETERS; + + res = vm_get_flags(uctx, va, sz, &vm_flags); + if (res) + return res; + if (vm_flags & VM_FLAG_PERMANENT) + return TEE_ERROR_ACCESS_DENIED; + + /* + * If the segment is a mapping of a part of a file (vm_flags & + * VM_FLAG_READONLY) it cannot be made writeable as all mapped + * files are mapped read-only. + */ + if ((vm_flags & VM_FLAG_READONLY) && + (prot & (TEE_MATTR_UW | TEE_MATTR_PW))) + return TEE_ERROR_ACCESS_DENIED; + + return vm_set_prot(uctx, va, sz, prot); +} + +TEE_Result ldelf_syscall_remap(unsigned long old_va, vaddr_t *new_va, + size_t num_bytes, size_t pad_begin, + size_t pad_end) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); + uint32_t vm_flags = 0; + + res = vm_get_flags(uctx, old_va, num_bytes, &vm_flags); + if (res) + return res; + if (vm_flags & VM_FLAG_PERMANENT) + return TEE_ERROR_ACCESS_DENIED; + + res = vm_remap(uctx, new_va, old_va, num_bytes, pad_begin, pad_end); + + return res; +} + +TEE_Result ldelf_syscall_gen_rnd_num(void *buf, size_t num_bytes) +{ + TEE_Result res = TEE_SUCCESS; + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)buf, num_bytes); + if (res) + return res; + + return crypto_rng_read(buf, num_bytes); +} + +/* + * Should be called after returning from ldelf. If user_ctx is not NULL means + * that ldelf crashed or otherwise didn't complete properly. This function will + * close the remaining handles and free the context structs allocated by ldelf. + */ +void ldelf_sess_cleanup(struct ts_session *sess) +{ + struct system_ctx *sys_ctx = sess->user_ctx; + + if (sys_ctx) { + handle_db_destroy(&sys_ctx->db, bin_close); + free(sys_ctx); + sess->user_ctx = NULL; + } +} diff --git a/optee/optee_os/core/kernel/lockdep.c b/optee/optee_os/core/kernel/lockdep.c new file mode 100644 index 0000000..5952e5d --- /dev/null +++ b/optee/optee_os/core/kernel/lockdep.c @@ -0,0 +1,513 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* lockdep_node::flags values */ +/* Flags used for depth-first topological sorting */ +#define LOCKDEP_NODE_TEMP_MARK BIT(0) +#define LOCKDEP_NODE_PERM_MARK BIT(1) +/* Flag used during breadth-first search (print shortest cycle) */ +#define LOCKDEP_NODE_BFS_VISITED BIT(2) + +/* Find node in graph or add it */ +static struct lockdep_node *lockdep_add_to_graph( + struct lockdep_node_head *graph, + uintptr_t lock_id) +{ + struct lockdep_node *node = NULL; + + assert(graph); + TAILQ_FOREACH(node, graph, link) + if (node->lock_id == lock_id) + return node; + + node = calloc(1, sizeof(*node)); + if (!node) + return NULL; + + node->lock_id = lock_id; + STAILQ_INIT(&node->edges); + TAILQ_INSERT_TAIL(graph, node, link); + + return node; +} + +static vaddr_t *dup_call_stack(vaddr_t *stack) +{ + vaddr_t *nstack = NULL; + int n = 0; + + if (!stack) + return NULL; + + while (stack[n]) + n++; + + nstack = malloc((n + 1) * sizeof(vaddr_t)); + if (!nstack) + return NULL; + + memcpy(nstack, stack, (n + 1) * sizeof(vaddr_t)); + + return nstack; +} + +static void lockdep_print_call_stack(vaddr_t *stack) +{ + vaddr_t *p = NULL; + + if (!IS_ENABLED(CFG_LOCKDEP_RECORD_STACK)) + return; + + EMSG_RAW("Call stack:"); + for (p = stack; p && *p; p++) + EMSG_RAW(" %#" PRIxPTR, *p); +} + +static TEE_Result lockdep_add_edge(struct lockdep_node *from, + struct lockdep_node *to, + vaddr_t *call_stack_from, + vaddr_t *call_stack_to, + uintptr_t thread_id) +{ + struct lockdep_edge *edge = NULL; + + STAILQ_FOREACH(edge, &from->edges, link) + if (edge->to == to) + return TEE_SUCCESS; + + edge = calloc(1, sizeof(*edge)); + if (!edge) + return TEE_ERROR_OUT_OF_MEMORY; + edge->to = to; + edge->call_stack_from = dup_call_stack(call_stack_from); + edge->call_stack_to = dup_call_stack(call_stack_to); + edge->thread_id = thread_id; + STAILQ_INSERT_TAIL(&from->edges, edge, link); + + return TEE_SUCCESS; +} + +struct lockdep_bfs { + struct lockdep_node *node; + uintptr_t *path; + int pathlen; + TAILQ_ENTRY(lockdep_bfs) link; +}; + +TAILQ_HEAD(lockdep_bfs_head, lockdep_bfs); + +static void lockdep_bfs_queue_delete(struct lockdep_bfs_head *queue) +{ + struct lockdep_bfs *cur = NULL; + struct lockdep_bfs *next = NULL; + + TAILQ_FOREACH_SAFE(cur, queue, link, next) { + TAILQ_REMOVE(queue, cur, link); + free(cur->path); + free(cur); + } +} + +/* + * Print shortest cycle in @graph that contains @node. + * This function performs an iterative breadth-first search starting from @node, + * and stops when it reaches @node again. In each node we're tracking the path + * from the start node. + */ +static uintptr_t *lockdep_graph_get_shortest_cycle(struct lockdep_node *node) +{ + struct lockdep_bfs_head queue; + struct lockdep_bfs *qe = NULL; + uintptr_t *ret = NULL; + + TAILQ_INIT(&queue); + node->flags |= LOCKDEP_NODE_BFS_VISITED; + + qe = calloc(1, sizeof(*qe)); + if (!qe) + goto out; + qe->node = node; + qe->path = malloc(sizeof(uintptr_t)); + if (!qe->path) + goto out; + qe->path[0] = node->lock_id; + qe->pathlen = 1; + TAILQ_INSERT_TAIL(&queue, qe, link); + + while (!TAILQ_EMPTY(&queue)) { + struct lockdep_node *n = NULL; + struct lockdep_edge *e = NULL; + + qe = TAILQ_FIRST(&queue); + n = qe->node; + TAILQ_REMOVE(&queue, qe, link); + + STAILQ_FOREACH(e, &n->edges, link) { + if (e->to->lock_id == node->lock_id) { + uintptr_t *tmp = NULL; + size_t nlen = qe->pathlen + 1; + + /* + * Cycle found. Terminate cycle path with NULL + * and return it. + */ + tmp = realloc(qe->path, + nlen * sizeof(uintptr_t)); + if (!tmp) { + EMSG("Out of memory"); + free(qe->path); + ret = NULL; + goto out; + } + qe->path = tmp; + qe->path[nlen - 1] = 0; + ret = qe->path; + goto out; + } + + if (!(e->to->flags & LOCKDEP_NODE_BFS_VISITED)) { + size_t nlen = 0; + struct lockdep_bfs *nqe = NULL; + + e->to->flags |= LOCKDEP_NODE_BFS_VISITED; + + nlen = qe->pathlen + 1; + nqe = calloc(1, sizeof(*nqe)); + if (!nqe) + goto out; + nqe->node = e->to; + nqe->path = malloc(nlen * sizeof(uintptr_t)); + if (!nqe->path) + goto out; + nqe->pathlen = nlen; + memcpy(nqe->path, qe->path, + qe->pathlen * sizeof(uintptr_t)); + nqe->path[nlen - 1] = e->to->lock_id; + TAILQ_INSERT_TAIL(&queue, nqe, link); + } + } + free(qe->path); + free(qe); + qe = NULL; + } + +out: + free(qe); + lockdep_bfs_queue_delete(&queue); + return ret; +} + +static TEE_Result lockdep_visit(struct lockdep_node *node) +{ + struct lockdep_edge *e = NULL; + + if (node->flags & LOCKDEP_NODE_PERM_MARK) + return TEE_SUCCESS; + + if (node->flags & LOCKDEP_NODE_TEMP_MARK) + return TEE_ERROR_BAD_STATE; /* Not a DAG! */ + + node->flags |= LOCKDEP_NODE_TEMP_MARK; + + STAILQ_FOREACH(e, &node->edges, link) { + TEE_Result res = lockdep_visit(e->to); + + if (res) + return res; + } + + node->flags |= LOCKDEP_NODE_PERM_MARK; + return TEE_SUCCESS; +} + +static TEE_Result lockdep_graph_sort(struct lockdep_node_head *graph) +{ + struct lockdep_node *node = NULL; + + TAILQ_FOREACH(node, graph, link) { + if (!node->flags) { + /* Unmarked node */ + TEE_Result res = lockdep_visit(node); + + if (res) + return res; + } + } + + TAILQ_FOREACH(node, graph, link) + node->flags = 0; + + return TEE_SUCCESS; +} + +static struct lockdep_edge *lockdep_find_edge(struct lockdep_node_head *graph, + uintptr_t from, uintptr_t to) +{ + struct lockdep_node *node = NULL; + struct lockdep_edge *edge = NULL; + + TAILQ_FOREACH(node, graph, link) + if (node->lock_id == from) + STAILQ_FOREACH(edge, &node->edges, link) + if (edge->to->lock_id == to) + return edge; + return NULL; +} + +static void lockdep_print_edge_info(uintptr_t from __maybe_unused, + struct lockdep_edge *edge) +{ + uintptr_t __maybe_unused to = edge->to->lock_id; + const char __maybe_unused *at_msg = ""; + const char __maybe_unused *acq_msg = ""; + + if (IS_ENABLED(CFG_LOCKDEP_RECORD_STACK)) { + at_msg = " at:"; + acq_msg = " acquired at:"; + } + + EMSG_RAW("-> Thread %#" PRIxPTR " acquired lock %#" PRIxPTR "%s", + edge->thread_id, to, at_msg); + lockdep_print_call_stack(edge->call_stack_to); + EMSG_RAW("...while holding lock %#" PRIxPTR "%s", + from, acq_msg); + lockdep_print_call_stack(edge->call_stack_from); +} + +/* + * Find cycle containing @node in the lock graph, then print full debug + * information about each edge (thread that acquired the locks and call stacks) + */ +static void lockdep_print_cycle_info(struct lockdep_node_head *graph, + struct lockdep_node *node) +{ + struct lockdep_edge *edge = NULL; + uintptr_t *cycle = NULL; + uintptr_t *p = NULL; + uintptr_t from = 0; + uintptr_t to = 0; + + cycle = lockdep_graph_get_shortest_cycle(node); + assert(cycle && cycle[0]); + EMSG_RAW("-> Shortest cycle:"); + for (p = cycle; *p; p++) + EMSG_RAW(" Lock %#" PRIxPTR, *p); + for (p = cycle; ; p++) { + if (!*p) { + assert(p != cycle); + from = to; + to = cycle[0]; + edge = lockdep_find_edge(graph, from, to); + lockdep_print_edge_info(from, edge); + break; + } + if (p != cycle) + from = to; + to = *p; + if (p != cycle) { + edge = lockdep_find_edge(graph, from, to); + lockdep_print_edge_info(from, edge); + } + } + free(cycle); +} + +static vaddr_t *lockdep_get_kernel_stack(void) +{ + if (IS_ENABLED(CFG_LOCKDEP_RECORD_STACK)) + return unw_get_kernel_stack(); + + return NULL; +} + +TEE_Result __lockdep_lock_acquire(struct lockdep_node_head *graph, + struct lockdep_lock_head *owned, + uintptr_t id) +{ + struct lockdep_node *node = lockdep_add_to_graph(graph, id); + struct lockdep_lock *lock = NULL; + TEE_Result res = TEE_SUCCESS; + vaddr_t *acq_stack = NULL; + + if (!node) + return TEE_ERROR_OUT_OF_MEMORY; + + acq_stack = lockdep_get_kernel_stack(); + + TAILQ_FOREACH(lock, owned, link) { + res = lockdep_add_edge(lock->node, node, lock->call_stack, + acq_stack, (uintptr_t)owned); + if (res) + return res; + } + + res = lockdep_graph_sort(graph); + if (res) { + EMSG_RAW("Potential deadlock detected!"); + EMSG_RAW("When trying to acquire lock %#" PRIxPTR, id); + lockdep_print_cycle_info(graph, node); + return res; + } + + lock = calloc(1, sizeof(*lock)); + if (!lock) + return TEE_ERROR_OUT_OF_MEMORY; + + lock->node = node; + lock->call_stack = acq_stack; + TAILQ_INSERT_TAIL(owned, lock, link); + + return TEE_SUCCESS; +} + +/* + * Call this when it is known that the thread has been able to acquire the lock. + * Similar to __lockdep_lock_acquire(), but since the operation is non-blocking, + * no dependency to currently owned locks are created. + */ +TEE_Result __lockdep_lock_tryacquire(struct lockdep_node_head *graph, + struct lockdep_lock_head *owned, + uintptr_t id) +{ + struct lockdep_node *node = lockdep_add_to_graph(graph, id); + struct lockdep_lock *lock = NULL; + vaddr_t *acq_stack = NULL; + + if (!node) + return TEE_ERROR_OUT_OF_MEMORY; + + acq_stack = lockdep_get_kernel_stack(); + + lock = calloc(1, sizeof(*lock)); + if (!lock) + return TEE_ERROR_OUT_OF_MEMORY; + + lock->node = node; + lock->call_stack = acq_stack; + TAILQ_INSERT_TAIL(owned, lock, link); + + return TEE_SUCCESS; +} + +TEE_Result __lockdep_lock_release(struct lockdep_lock_head *owned, uintptr_t id) +{ + struct lockdep_lock *lock = NULL; + + TAILQ_FOREACH_REVERSE(lock, owned, lockdep_lock_head, link) { + if (lock->node->lock_id == id) { + TAILQ_REMOVE(owned, lock, link); + free(lock->call_stack); + free(lock); + return TEE_SUCCESS; + } + } + + EMSG_RAW("Thread %p does not own lock %#" PRIxPTR, (void *)owned, id); + return TEE_ERROR_ITEM_NOT_FOUND; +} + +static void lockdep_free_edge(struct lockdep_edge *edge) +{ + free(edge->call_stack_from); + free(edge->call_stack_to); + free(edge); +} + +static void lockdep_node_delete(struct lockdep_node *node) +{ + struct lockdep_edge *edge = NULL; + struct lockdep_edge *next = NULL; + + STAILQ_FOREACH_SAFE(edge, &node->edges, link, next) + lockdep_free_edge(edge); + + free(node); +} + +void lockdep_graph_delete(struct lockdep_node_head *graph) +{ + struct lockdep_node *node = NULL; + struct lockdep_node *next = NULL; + + TAILQ_FOREACH_SAFE(node, graph, link, next) { + TAILQ_REMOVE(graph, node, link); + lockdep_node_delete(node); + } +} + +void lockdep_queue_delete(struct lockdep_lock_head *owned) +{ + struct lockdep_lock *lock = NULL; + struct lockdep_lock *next = NULL; + + TAILQ_FOREACH_SAFE(lock, owned, link, next) { + TAILQ_REMOVE(owned, lock, link); + free(lock); + } +} + +static void lockdep_node_destroy(struct lockdep_node_head *graph, + struct lockdep_node *node) +{ + struct lockdep_edge *edge = NULL; + struct lockdep_edge *next = NULL; + struct lockdep_node *from = NULL; + + TAILQ_REMOVE(graph, node, link); + + /* + * Loop over all nodes in the graph to remove all edges with the + * node to remove in the "to" field. + */ + TAILQ_FOREACH(from, graph, link) { + edge = STAILQ_FIRST(&from->edges); + while (edge && edge->to == node) { + STAILQ_REMOVE_HEAD(&from->edges, link); + lockdep_free_edge(edge); + edge = STAILQ_FIRST(&from->edges); + } + + if (!edge) + continue; + + next = STAILQ_NEXT(edge, link); + while (next) { + if (next->to == node) { + STAILQ_REMOVE_AFTER(&from->edges, edge, link); + lockdep_free_edge(next); + } else { + edge = next; + } + next = STAILQ_NEXT(edge, link); + } + } + + STAILQ_FOREACH_SAFE(edge, &node->edges, link, next) + lockdep_free_edge(edge); + + free(node); +} + +void lockdep_lock_destroy(struct lockdep_node_head *graph, uintptr_t lock_id) +{ + struct lockdep_node *node = NULL; + + assert(graph); + TAILQ_FOREACH(node, graph, link) { + if (node->lock_id == lock_id) { + lockdep_node_destroy(graph, node); + break; + } + } +} diff --git a/optee/optee_os/core/kernel/msg_param.c b/optee/optee_os/core/kernel/msg_param.c new file mode 100644 index 0000000..5b7fec8 --- /dev/null +++ b/optee/optee_os/core/kernel/msg_param.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, EPAM Systems + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 + +/** + * msg_param_extract_pages() - extract list of pages from + * OPTEE_MSG_ATTR_NONCONTIG buffer. + * + * @buffer: pointer to parameters array + * @pages: output array of page addresses + * @num_pages: number of pages in array + * + * return: + * true on success, false otherwise + * + * @buffer points to the physical address of a structure that can be viewed as + * + * struct page_data { + * uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1]; + * uint64_t next_page_data; + * }; + * + * So, it is a linked list of arrays, where each element of linked list fits + * exactly into one 4K page. + * + * This function extracts data from arrays into one array pointed by @pages + * + * @buffer points to data shared with normal world, so some precautions + * should be taken. + */ +static bool msg_param_extract_pages(paddr_t buffer, paddr_t *pages, + size_t num_pages) +{ + size_t cnt; + struct mobj *mobj; + paddr_t page; + uint64_t *va; + bool ret = false; + + if (buffer & SMALL_PAGE_MASK) + return false; + + /* + * There we map first page of array. + * mobj_mapped_shm_alloc() will check if page resides in nonsec ddr + */ + mobj = mobj_mapped_shm_alloc(&buffer, 1, 0, 0); + if (!mobj) + return false; + + va = mobj_get_va(mobj, 0, SMALL_PAGE_SIZE); + assert(va); + + for (cnt = 0; cnt < num_pages; cnt++, va++) { + /* + * If we about to roll over page boundary, then last entry holds + * address of next page of array. Unmap current page and map + * next one + */ + if (!((vaddr_t)(va + 1) & SMALL_PAGE_MASK)) { + page = *va; + if (page & SMALL_PAGE_MASK) + goto out; + + mobj_put(mobj); + mobj = mobj_mapped_shm_alloc(&page, 1, 0, 0); + if (!mobj) + goto out; + + va = mobj_get_va(mobj, 0, SMALL_PAGE_SIZE); + assert(va); + } + pages[cnt] = *va; + if (pages[cnt] & SMALL_PAGE_MASK) + goto out; + } + + ret = true; +out: + mobj_put(mobj); + return ret; +} + +struct mobj *msg_param_mobj_from_noncontig(paddr_t buf_ptr, size_t size, + uint64_t shm_ref, bool map_buffer) +{ + struct mobj *mobj = NULL; + paddr_t *pages = NULL; + paddr_t page_offset = 0; + size_t num_pages = 0; + size_t size_plus_offs = 0; + size_t msize = 0; + + page_offset = buf_ptr & SMALL_PAGE_MASK; + if (ADD_OVERFLOW(size, page_offset, &size_plus_offs)) + return NULL; + num_pages = (size_plus_offs - 1) / SMALL_PAGE_SIZE + 1; + if (MUL_OVERFLOW(num_pages, sizeof(paddr_t), &msize)) + return NULL; + + pages = malloc(msize); + if (!pages) + return NULL; + + if (!msg_param_extract_pages(buf_ptr & ~SMALL_PAGE_MASK, + pages, num_pages)) + goto out; + + if (map_buffer) + mobj = mobj_mapped_shm_alloc(pages, num_pages, page_offset, + shm_ref); + else + mobj = mobj_reg_shm_alloc(pages, num_pages, page_offset, + shm_ref); +out: + free(pages); + return mobj; +} diff --git a/optee/optee_os/core/kernel/mutex.c b/optee/optee_os/core/kernel/mutex.c new file mode 100644 index 0000000..45028c4 --- /dev/null +++ b/optee/optee_os/core/kernel/mutex.c @@ -0,0 +1,456 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "mutex_lockdep.h" + +void mutex_init(struct mutex *m) +{ + *m = (struct mutex)MUTEX_INITIALIZER; +} + +void mutex_init_recursive(struct recursive_mutex *m) +{ + *m = (struct recursive_mutex)RECURSIVE_MUTEX_INITIALIZER; +} + +static void __mutex_lock(struct mutex *m, const char *fname, int lineno) +{ + assert_have_no_spinlock(); + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + assert(thread_is_in_normal_mode()); + + mutex_lock_check(m); + + while (true) { + uint32_t old_itr_status; + bool can_lock; + struct wait_queue_elem wqe; + + /* + * If the mutex is locked we need to initialize the wqe + * before releasing the spinlock to guarantee that we don't + * miss the wakeup from mutex_unlock(). + * + * If the mutex is unlocked we don't need to use the wqe at + * all. + */ + + old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); + + can_lock = !m->state; + if (!can_lock) { + wq_wait_init(&m->wq, &wqe, false /* wait_read */); + } else { + m->state = -1; /* write locked */ + } + + cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); + + if (!can_lock) { + /* + * Someone else is holding the lock, wait in normal + * world for the lock to become available. + */ + wq_wait_final(&m->wq, &wqe, m, fname, lineno); + } else + return; + } +} + +static void __mutex_lock_recursive(struct recursive_mutex *m, const char *fname, + int lineno) +{ + short int ct = thread_get_id(); + + assert_have_no_spinlock(); + assert(thread_is_in_normal_mode()); + + if (atomic_load_short(&m->owner) == ct) { + if (!refcount_inc(&m->lock_depth)) + panic(); + return; + } + + __mutex_lock(&m->m, fname, lineno); + + assert(m->owner == THREAD_ID_INVALID); + atomic_store_short(&m->owner, ct); + refcount_set(&m->lock_depth, 1); +} + +static void __mutex_unlock(struct mutex *m, const char *fname, int lineno) +{ + uint32_t old_itr_status; + + assert_have_no_spinlock(); + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + + mutex_unlock_check(m); + + old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); + + if (!m->state) + panic(); + + m->state = 0; + + cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); + + wq_wake_next(&m->wq, m, fname, lineno); +} + +static void __mutex_unlock_recursive(struct recursive_mutex *m, + const char *fname, int lineno) +{ + assert_have_no_spinlock(); + assert(m->owner == thread_get_id()); + + if (refcount_dec(&m->lock_depth)) { + /* + * Do an atomic store to match the atomic load in + * __mutex_lock_recursive() + */ + atomic_store_short(&m->owner, THREAD_ID_INVALID); + __mutex_unlock(&m->m, fname, lineno); + } +} + +static bool __mutex_trylock(struct mutex *m, const char *fname __unused, + int lineno __unused) +{ + uint32_t old_itr_status; + bool can_lock_write; + + assert_have_no_spinlock(); + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + + old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); + + can_lock_write = !m->state; + if (can_lock_write) + m->state = -1; + + cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); + + if (can_lock_write) + mutex_trylock_check(m); + + return can_lock_write; +} + +static void __mutex_read_unlock(struct mutex *m, const char *fname, int lineno) +{ + uint32_t old_itr_status; + short new_state; + + assert_have_no_spinlock(); + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + + old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); + + if (m->state <= 0) + panic(); + m->state--; + new_state = m->state; + + cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); + + /* Wake eventual waiters if the mutex was unlocked */ + if (!new_state) + wq_wake_next(&m->wq, m, fname, lineno); +} + +static void __mutex_read_lock(struct mutex *m, const char *fname, int lineno) +{ + assert_have_no_spinlock(); + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + assert(thread_is_in_normal_mode()); + + while (true) { + uint32_t old_itr_status; + bool can_lock; + struct wait_queue_elem wqe; + + /* + * If the mutex is locked we need to initialize the wqe + * before releasing the spinlock to guarantee that we don't + * miss the wakeup from mutex_unlock(). + * + * If the mutex is unlocked we don't need to use the wqe at + * all. + */ + + old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); + + can_lock = m->state != -1; + if (!can_lock) { + wq_wait_init(&m->wq, &wqe, true /* wait_read */); + } else { + m->state++; /* read_locked */ + } + + cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); + + if (!can_lock) { + /* + * Someone else is holding the lock, wait in normal + * world for the lock to become available. + */ + wq_wait_final(&m->wq, &wqe, m, fname, lineno); + } else + return; + } +} + +static bool __mutex_read_trylock(struct mutex *m, const char *fname __unused, + int lineno __unused) +{ + uint32_t old_itr_status; + bool can_lock; + + assert_have_no_spinlock(); + assert(thread_get_id_may_fail() != THREAD_ID_INVALID); + assert(thread_is_in_normal_mode()); + + old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); + + can_lock = m->state != -1; + if (can_lock) + m->state++; + + cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); + + return can_lock; +} + +#ifdef CFG_MUTEX_DEBUG +void mutex_unlock_debug(struct mutex *m, const char *fname, int lineno) +{ + __mutex_unlock(m, fname, lineno); +} + +void mutex_lock_debug(struct mutex *m, const char *fname, int lineno) +{ + __mutex_lock(m, fname, lineno); +} + +bool mutex_trylock_debug(struct mutex *m, const char *fname, int lineno) +{ + return __mutex_trylock(m, fname, lineno); +} + +void mutex_read_unlock_debug(struct mutex *m, const char *fname, int lineno) +{ + __mutex_read_unlock(m, fname, lineno); +} + +void mutex_read_lock_debug(struct mutex *m, const char *fname, int lineno) +{ + __mutex_read_lock(m, fname, lineno); +} + +bool mutex_read_trylock_debug(struct mutex *m, const char *fname, int lineno) +{ + return __mutex_read_trylock(m, fname, lineno); +} + +void mutex_unlock_recursive_debug(struct recursive_mutex *m, const char *fname, + int lineno) +{ + __mutex_unlock_recursive(m, fname, lineno); +} + +void mutex_lock_recursive_debug(struct recursive_mutex *m, const char *fname, + int lineno) +{ + __mutex_lock_recursive(m, fname, lineno); +} +#else +void mutex_unlock(struct mutex *m) +{ + __mutex_unlock(m, NULL, -1); +} + +void mutex_unlock_recursive(struct recursive_mutex *m) +{ + __mutex_unlock_recursive(m, NULL, -1); +} + +void mutex_lock(struct mutex *m) +{ + __mutex_lock(m, NULL, -1); +} + +void mutex_lock_recursive(struct recursive_mutex *m) +{ + __mutex_lock_recursive(m, NULL, -1); +} + +bool mutex_trylock(struct mutex *m) +{ + return __mutex_trylock(m, NULL, -1); +} + +void mutex_read_unlock(struct mutex *m) +{ + __mutex_read_unlock(m, NULL, -1); +} + +void mutex_read_lock(struct mutex *m) +{ + __mutex_read_lock(m, NULL, -1); +} + +bool mutex_read_trylock(struct mutex *m) +{ + return __mutex_read_trylock(m, NULL, -1); +} +#endif + +void mutex_destroy(struct mutex *m) +{ + /* + * Caller guarantees that no one will try to take the mutex so + * there's no need to take the spinlock before accessing it. + */ + if (m->state) + panic(); + if (!wq_is_empty(&m->wq)) + panic("waitqueue not empty"); + mutex_destroy_check(m); +} + +void mutex_destroy_recursive(struct recursive_mutex *m) +{ + mutex_destroy(&m->m); +} + +unsigned int mutex_get_recursive_lock_depth(struct recursive_mutex *m) +{ + assert_have_no_spinlock(); + assert(m->owner == thread_get_id()); + + return refcount_val(&m->lock_depth); +} + +void condvar_init(struct condvar *cv) +{ + *cv = (struct condvar)CONDVAR_INITIALIZER; +} + +void condvar_destroy(struct condvar *cv) +{ + if (cv->m && wq_have_condvar(&cv->m->wq, cv)) + panic(); + + condvar_init(cv); +} + +static void cv_signal(struct condvar *cv, bool only_one, const char *fname, + int lineno) +{ + uint32_t old_itr_status; + struct mutex *m; + + old_itr_status = cpu_spin_lock_xsave(&cv->spin_lock); + m = cv->m; + cpu_spin_unlock_xrestore(&cv->spin_lock, old_itr_status); + + if (m) + wq_promote_condvar(&m->wq, cv, only_one, m, fname, lineno); + +} + +#ifdef CFG_MUTEX_DEBUG +void condvar_signal_debug(struct condvar *cv, const char *fname, int lineno) +{ + cv_signal(cv, true /* only one */, fname, lineno); +} + +void condvar_broadcast_debug(struct condvar *cv, const char *fname, int lineno) +{ + cv_signal(cv, false /* all */, fname, lineno); +} + +#else +void condvar_signal(struct condvar *cv) +{ + cv_signal(cv, true /* only one */, NULL, -1); +} + +void condvar_broadcast(struct condvar *cv) +{ + cv_signal(cv, false /* all */, NULL, -1); +} +#endif /*CFG_MUTEX_DEBUG*/ + +static void __condvar_wait(struct condvar *cv, struct mutex *m, + const char *fname, int lineno) +{ + uint32_t old_itr_status; + struct wait_queue_elem wqe; + short old_state; + short new_state; + + mutex_unlock_check(m); + + /* Link this condvar to this mutex until reinitialized */ + old_itr_status = cpu_spin_lock_xsave(&cv->spin_lock); + if (cv->m && cv->m != m) + panic("invalid mutex"); + + cv->m = m; + cpu_spin_unlock(&cv->spin_lock); + + cpu_spin_lock(&m->spin_lock); + + if (!m->state) + panic(); + old_state = m->state; + /* Add to mutex wait queue as a condvar waiter */ + wq_wait_init_condvar(&m->wq, &wqe, cv, m->state > 0); + + if (m->state > 1) { + /* Multiple read locks, remove one */ + m->state--; + } else { + /* Only one lock (read or write), unlock the mutex */ + m->state = 0; + } + new_state = m->state; + + cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); + + /* Wake eventual waiters if the mutex was unlocked */ + if (!new_state) + wq_wake_next(&m->wq, m, fname, lineno); + + wq_wait_final(&m->wq, &wqe, m, fname, lineno); + + if (old_state > 0) + mutex_read_lock(m); + else + mutex_lock(m); +} + +#ifdef CFG_MUTEX_DEBUG +void condvar_wait_debug(struct condvar *cv, struct mutex *m, + const char *fname, int lineno) +{ + __condvar_wait(cv, m, fname, lineno); +} +#else +void condvar_wait(struct condvar *cv, struct mutex *m) +{ + __condvar_wait(cv, m, NULL, -1); +} +#endif diff --git a/optee/optee_os/core/kernel/mutex_lockdep.c b/optee/optee_os/core/kernel/mutex_lockdep.c new file mode 100644 index 0000000..2095c86 --- /dev/null +++ b/optee/optee_os/core/kernel/mutex_lockdep.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "mutex_lockdep.h" + +/* Global graph of all mutexes used in the code */ +static struct lockdep_node_head graph = TAILQ_HEAD_INITIALIZER(graph); + +/* Protects @graph */ +static unsigned int graph_lock = SPINLOCK_UNLOCK; + +/* + * One queue per thread, contains the mutexes the thread owns at any point in + * time (in aquire order) + */ +static struct lockdep_lock_head owned[CFG_NUM_THREADS]; + +void mutex_lockdep_init(void) +{ + int n = 0; + + for (n = 0; n < CFG_NUM_THREADS; n++) + TAILQ_INIT(&owned[n]); + + DMSG("lockdep is enabled for mutexes"); +} + +void mutex_lock_check(struct mutex *m) +{ + short int thread = thread_get_id(); + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&graph_lock); + lockdep_lock_acquire(&graph, &owned[thread], (uintptr_t)m); + cpu_spin_unlock_xrestore(&graph_lock, exceptions); +} + +void mutex_trylock_check(struct mutex *m) +{ + short int thread = thread_get_id(); + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&graph_lock); + lockdep_lock_tryacquire(&graph, &owned[thread], (uintptr_t)m); + cpu_spin_unlock_xrestore(&graph_lock, exceptions); +} + +void mutex_unlock_check(struct mutex *m) +{ + short int thread = thread_get_id(); + uint32_t exceptions = 0; + + exceptions = cpu_spin_lock_xsave(&graph_lock); + lockdep_lock_release(&owned[thread], (uintptr_t)m); + cpu_spin_unlock_xrestore(&graph_lock, exceptions); +} + +void mutex_destroy_check(struct mutex *m) +{ + uint32_t exceptions = cpu_spin_lock_xsave(&graph_lock); + + lockdep_lock_destroy(&graph, (uintptr_t)m); + cpu_spin_unlock_xrestore(&graph_lock, exceptions); +} diff --git a/optee/optee_os/core/kernel/mutex_lockdep.h b/optee/optee_os/core/kernel/mutex_lockdep.h new file mode 100644 index 0000000..119551d --- /dev/null +++ b/optee/optee_os/core/kernel/mutex_lockdep.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ +#ifndef MUTEX_LOCKDEP_H +#define MUTEX_LOCKDEP_H + +#include +#include + +#ifdef CFG_LOCKDEP + +void mutex_lock_check(struct mutex *m); + +void mutex_trylock_check(struct mutex *m); + +void mutex_unlock_check(struct mutex *m); + +void mutex_destroy_check(struct mutex *m); + +#else + +static inline void mutex_lock_check(struct mutex *m __unused) +{} + +static inline void mutex_trylock_check(struct mutex *m __unused) +{} + +static inline void mutex_unlock_check(struct mutex *m __unused) +{} + +static inline void mutex_destroy_check(struct mutex *m __unused) +{} + +#endif /* !CFG_LOCKDEP */ + +#endif /* MUTEX_LOCKDEP_H */ diff --git a/optee/optee_os/core/kernel/notif.c b/optee/optee_os/core/kernel/notif.c new file mode 100644 index 0000000..7ecc246 --- /dev/null +++ b/optee/optee_os/core/kernel/notif.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CFG_CORE_ASYNC_NOTIF) +static struct mutex notif_mutex = MUTEX_INITIALIZER; +static unsigned int notif_lock = SPINLOCK_UNLOCK; + +SLIST_HEAD(notif_driver_head, notif_driver); +static struct notif_driver_head notif_driver_head = + SLIST_HEAD_INITIALIZER(¬if_driver_head); + +static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1); +static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1); +static bool notif_started; + +TEE_Result notif_alloc_async_value(uint32_t *val) +{ + static bool alloc_values_inited; + uint32_t old_itr_status = 0; + int bit = 0; + + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + if (!alloc_values_inited) { + bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF); + alloc_values_inited = true; + } + + bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); + if (bit >= 0) { + *val = bit; + bit_set(notif_alloc_values, bit); + } + + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); + + if (bit < 0) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} + +void notif_free_async_value(uint32_t val) +{ + uint32_t old_itr_status = 0; + + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + assert(val < NOTIF_ASYNC_VALUE_MAX); + assert(bit_test(notif_alloc_values, val)); + bit_clear(notif_alloc_values, val); + + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); +} + +uint32_t notif_get_value(bool *value_valid, bool *value_pending) +{ + uint32_t old_itr_status = 0; + uint32_t res = 0; + int bit = 0; + + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); + *value_valid = (bit >= 0); + if (!*value_valid) { + *value_pending = false; + goto out; + } + + res = bit; + bit_clear(notif_values, res); + bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); + *value_pending = (bit >= 0); +out: + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); + + return res; +} + +void notif_send_async(uint32_t value) +{ + uint32_t old_itr_status = 0; + + static_assert(CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_PPI_BASE); + + assert(value <= NOTIF_ASYNC_VALUE_MAX); + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + DMSG("0x%"PRIx32, value); + bit_set(notif_values, value); + itr_raise_pi(CFG_CORE_ASYNC_NOTIF_GIC_INTID); + + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); +} + +bool notif_async_is_started(void) +{ + uint32_t old_itr_status = 0; + bool ret = false; + + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + ret = notif_started; + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); + + return ret; +} + +void notif_register_driver(struct notif_driver *ndrv) +{ + uint32_t old_itr_status = 0; + + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + SLIST_INSERT_HEAD(¬if_driver_head, ndrv, link); + + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); +} + +void notif_unregister_driver(struct notif_driver *ndrv) +{ + uint32_t old_itr_status = 0; + + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + SLIST_REMOVE(¬if_driver_head, ndrv, notif_driver, link); + + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); +} + +void notif_deliver_atomic_event(enum notif_event ev) +{ + uint32_t old_itr_status = 0; + struct notif_driver *nd = NULL; + + assert(ev == NOTIF_EVENT_STARTED); + + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + if (notif_started) { + DMSG("Already started"); + goto out; + } + notif_started = true; + + SLIST_FOREACH(nd, ¬if_driver_head, link) + if (nd->atomic_cb) + nd->atomic_cb(nd, ev); + +out: + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); +} + +void notif_deliver_event(enum notif_event ev) +{ + uint32_t old_itr_status = 0; + struct notif_driver *nd = NULL; + struct notif_driver *nd_tmp = NULL; + + assert(ev == NOTIF_EVENT_DO_BOTTOM_HALF || ev == NOTIF_EVENT_STOPPED); + + /* Serialize all yielding notifications */ + mutex_lock(¬if_mutex); + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + if (!notif_started) { + DMSG("Not started ev %d", (int)ev); + goto out; + } + + if (ev == NOTIF_EVENT_STOPPED) + notif_started = false; + + SLIST_FOREACH_SAFE(nd, ¬if_driver_head, link, nd_tmp) { + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); + + if (nd->yielding_cb) + nd->yielding_cb(nd, ev); + + old_itr_status = cpu_spin_lock_xsave(¬if_lock); + + if (ev == NOTIF_EVENT_STOPPED && notif_started) { + DMSG("Started again while stopping"); + goto out; + } + } + +out: + cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); + mutex_unlock(¬if_mutex); +} +#endif /*CFG_CORE_ASYNC_NOTIF*/ + +static TEE_Result notif_rpc(uint32_t func, uint32_t value) +{ + struct thread_param params = THREAD_PARAM_VALUE(IN, func, value, 0); + + return thread_rpc_cmd(OPTEE_RPC_CMD_NOTIFICATION, 1, ¶ms); +} + +TEE_Result notif_wait(uint32_t value) +{ + return notif_rpc(OPTEE_RPC_NOTIFICATION_WAIT, value); +} + +TEE_Result notif_send_sync(uint32_t value) +{ + return notif_rpc(OPTEE_RPC_NOTIFICATION_SEND, value); +} diff --git a/optee/optee_os/core/kernel/otp_stubs.c b/optee/optee_os/core/kernel/otp_stubs.c new file mode 100644 index 0000000..8bbda12 --- /dev/null +++ b/optee/optee_os/core/kernel/otp_stubs.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +/* + * Override these in your platform code to really fetch device-unique + * bits from e-fuses or whatever. + * + * The default implementation just sets it to a constant. + */ + +__weak TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + memset(&hwkey->data[0], 0, sizeof(hwkey->data)); + return TEE_SUCCESS; +} + +__weak int tee_otp_get_die_id(uint8_t *buffer, size_t len) +{ + if (huk_subkey_derive(HUK_SUBKEY_DIE_ID, NULL, 0, buffer, len)) + return -1; + + return 0; +} + +__weak TEE_Result tee_otp_get_rpmb_key(uint8_t *key, size_t len) +{ + memset(key, 0, len); + return TEE_SUCCESS; +} + +#ifdef CFG_WITH_USER_TA +/* + * Override this API on your platform to provide TA encryption key as + * per your security requirements. There can be two options for this key: + * + * 1) Unique per device encryption key. + * 2) Class wide encryption key. + * + * The default implementation chooses option (1). + */ +__weak TEE_Result tee_otp_get_ta_enc_key(uint32_t key_type __maybe_unused, + uint8_t *buffer, size_t len) +{ + assert(key_type == SHDR_ENC_KEY_DEV_SPECIFIC); + + if (huk_subkey_derive(HUK_SUBKEY_TA_ENC, ta_pub_key_modulus, + ta_pub_key_modulus_size, buffer, len)) + return TEE_ERROR_SECURITY; + + return TEE_SUCCESS; +} +#endif diff --git a/optee/optee_os/core/kernel/panic.c b/optee/optee_os/core/kernel/panic.c new file mode 100644 index 0000000..18028fb --- /dev/null +++ b/optee/optee_os/core/kernel/panic.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include + +void __do_panic(const char *file __maybe_unused, + const int line __maybe_unused, + const char *func __maybe_unused, + const char *msg __maybe_unused) +{ + /* disable prehemption */ + (void)thread_mask_exceptions(THREAD_EXCP_ALL); + + /* TODO: notify other cores */ + + /* trace: Panic ['panic-string-message' ]at FILE:LINE []" */ + if (!file && !func && !msg) + EMSG_RAW("Panic"); + else + EMSG_RAW("Panic %s%s%sat %s:%d %s%s%s", + msg ? "'" : "", msg ? msg : "", msg ? "' " : "", + file ? file : "?", file ? line : 0, + func ? "<" : "", func ? func : "", func ? ">" : ""); + + print_kernel_stack(); + /* abort current execution */ + while (1) + cpu_idle(); +} + +void __weak cpu_idle(void) +{ +} diff --git a/optee/optee_os/core/kernel/pm.c b/optee/optee_os/core/kernel/pm.c new file mode 100644 index 0000000..4146464 --- /dev/null +++ b/optee/optee_os/core/kernel/pm.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PM_FLAG_SUSPENDED BIT(0) + +static struct pm_callback_handle *pm_cb_ref; +static size_t pm_cb_count; + +static const char no_name[] = "no-name"; +DECLARE_KEEP_PAGER(no_name); + +static void verify_cb_args(struct pm_callback_handle *pm_hdl) +{ + if (is_unpaged((void *)(vaddr_t)pm_change_state) && + (!is_unpaged((void *)(vaddr_t)pm_hdl->callback) || + (pm_hdl->handle && !is_unpaged(pm_hdl->handle)))) { + EMSG("PM callbacks mandates unpaged arguments: %p %p", + (void *)(vaddr_t)pm_hdl->callback, pm_hdl->handle); + panic(); + } +} + +void register_pm_cb(struct pm_callback_handle *pm_hdl) +{ + struct pm_callback_handle *ref = NULL; + const char *name = pm_hdl->name; + size_t count = pm_cb_count; + + verify_cb_args(pm_hdl); + + if (!name) + name = no_name; + + if (!is_unpaged((void *)name)) { + name = strdup(name); + if (!name) + panic(); + } + + ref = realloc(pm_cb_ref, sizeof(*ref) * (count + 1)); + if (!ref) + panic(); + + ref[count] = *pm_hdl; + ref[count].flags = 0; + ref[count].name = name; + + pm_cb_count = count + 1; + pm_cb_ref = ref; +} + +static TEE_Result do_pm_callback(enum pm_op op, uint32_t pm_hint, + struct pm_callback_handle *hdl) +{ + TEE_Result res = TEE_ERROR_GENERIC; + bool suspending = op == PM_OP_SUSPEND; + + if (suspending == (bool)(hdl->flags & PM_FLAG_SUSPENDED)) + return TEE_SUCCESS; + + DMSG("%s %s", suspending ? "Suspend" : "Resume", hdl->name); + + res = hdl->callback(op, pm_hint, hdl); + if (res) { + EMSG("%s %s (%p) failed: %#"PRIx32, suspending ? "Suspend" : + "Resume", hdl->name, (void *)(vaddr_t)hdl->callback, res); + return res; + } + + if (suspending) + hdl->flags |= PM_FLAG_SUSPENDED; + else + hdl->flags &= ~PM_FLAG_SUSPENDED; + + return TEE_SUCCESS; +} + +static TEE_Result call_callbacks(enum pm_op op, uint32_t pm_hint, + enum pm_callback_order order) +{ + struct pm_callback_handle *hdl = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + size_t n = 0; + + /* + * Suspend first the last registered instances. + * Resume first the first registered instances. + */ + if (op == PM_OP_SUSPEND) + hdl = pm_cb_ref + pm_cb_count - 1; + else + hdl = pm_cb_ref; + + for (n = 0; n < pm_cb_count; n++) { + if (hdl->order == order) { + res = do_pm_callback(op, pm_hint, hdl); + if (res) + return res; + } + + if (op == PM_OP_SUSPEND) + hdl--; + else + hdl++; + } + + return TEE_SUCCESS; +} + +TEE_Result pm_change_state(enum pm_op op, uint32_t pm_hint) +{ + enum pm_callback_order cnt = PM_CB_ORDER_DRIVER; + TEE_Result res = TEE_ERROR_GENERIC; + + switch (op) { + case PM_OP_SUSPEND: + for (cnt = PM_CB_ORDER_DRIVER; cnt < PM_CB_ORDER_MAX; cnt++) { + res = call_callbacks(op, pm_hint, cnt); + if (res) + return res; + } + break; + case PM_OP_RESUME: + for (cnt = PM_CB_ORDER_MAX; cnt > PM_CB_ORDER_DRIVER; cnt--) { + res = call_callbacks(op, pm_hint, cnt - 1); + if (res) + return res; + } + break; + default: + panic(); + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/kernel/pseudo_ta.c b/optee/optee_os/core/kernel/pseudo_ta.c new file mode 100644 index 0000000..0a85eda --- /dev/null +++ b/optee/optee_os/core/kernel/pseudo_ta.c @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_SECURE_DATA_PATH +static bool client_is_secure(struct ts_session *s) +{ + /* rely on core entry to have constrained client IDs */ + if (to_ta_session(s)->clnt_id.login == TEE_LOGIN_TRUSTED_APP) + return true; + + return false; +} + +static bool validate_in_param(struct ts_session *s, struct mobj *mobj) +{ + /* Supplying NULL to query buffer size is OK */ + if (!mobj) + return true; + + /* for secure clients, core entry always holds valid memref objects */ + if (client_is_secure(s)) + return true; + + /* all non-secure memory references are handled by PTAs */ + if (mobj_is_nonsec(mobj)) + return true; + + return false; +} +#else +static bool validate_in_param(struct ts_session *s __unused, + struct mobj *mobj __unused) +{ + /* At this point, core has filled only valid accessible memref mobj */ + return true; +} +#endif + +/* Maps pseudo TA params */ +static TEE_Result copy_in_param(struct ts_session *s __maybe_unused, + struct tee_ta_param *param, + TEE_Param tee_param[TEE_NUM_PARAMS], + bool did_map[TEE_NUM_PARAMS]) +{ + size_t n; + void *va; + struct param_mem *mem; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + tee_param[n].value.a = param->u[n].val.a; + tee_param[n].value.b = param->u[n].val.b; + break; + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + mem = ¶m->u[n].mem; + if (!validate_in_param(s, mem->mobj)) + return TEE_ERROR_BAD_PARAMETERS; + if (mem->size) { + TEE_Result res = mobj_inc_map(mem->mobj); + + if (res) + return res; + did_map[n] = true; + va = mobj_get_va(mem->mobj, mem->offs, + mem->size); + if (!va) + return TEE_ERROR_BAD_PARAMETERS; + } else { + va = NULL; + } + + tee_param[n].memref.buffer = va; + tee_param[n].memref.size = mem->size; + break; + default: + memset(tee_param + n, 0, sizeof(TEE_Param)); + break; + } + } + + return TEE_SUCCESS; +} + +static void update_out_param(TEE_Param tee_param[TEE_NUM_PARAMS], + struct tee_ta_param *param) +{ + size_t n; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + param->u[n].val.a = tee_param[n].value.a; + param->u[n].val.b = tee_param[n].value.b; + break; + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + param->u[n].mem.size = tee_param[n].memref.size; + break; + default: + break; + } + } +} + +static void unmap_mapped_param(struct tee_ta_param *param, + bool did_map[TEE_NUM_PARAMS]) +{ + size_t n; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + if (did_map[n]) { + TEE_Result res __maybe_unused; + + res = mobj_dec_map(param->u[n].mem.mobj); + assert(!res); + } + } +} + +static TEE_Result pseudo_ta_enter_open_session(struct ts_session *s) +{ + TEE_Result res = TEE_SUCCESS; + struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); + struct tee_ta_session *ta_sess = to_ta_session(s); + TEE_Param tee_param[TEE_NUM_PARAMS] = { }; + bool did_map[TEE_NUM_PARAMS] = { false }; + + ts_push_current_session(s); + ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; + + if (stc->ctx.ref_count == 1 && stc->pseudo_ta->create_entry_point) { + res = stc->pseudo_ta->create_entry_point(); + if (res != TEE_SUCCESS) + goto out; + } + + if (stc->pseudo_ta->open_session_entry_point) { + void **user_ctx = &s->user_ctx; + uint32_t param_types = 0; + + if (ta_sess->param) { + res = copy_in_param(s, ta_sess->param, tee_param, + did_map); + if (res != TEE_SUCCESS) { + unmap_mapped_param(ta_sess->param, did_map); + ta_sess->err_origin = TEE_ORIGIN_TEE; + goto out; + } + param_types = ta_sess->param->types; + } + + res = stc->pseudo_ta->open_session_entry_point(param_types, + tee_param, + user_ctx); + if (ta_sess->param) { + update_out_param(tee_param, ta_sess->param); + unmap_mapped_param(ta_sess->param, did_map); + } + } + +out: + ts_pop_current_session(); + return res; +} + +static TEE_Result pseudo_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) +{ + TEE_Result res = TEE_SUCCESS; + struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); + struct tee_ta_session *ta_sess = to_ta_session(s); + uint32_t param_types = 0; + TEE_Param tee_param[TEE_NUM_PARAMS] = { }; + bool did_map[TEE_NUM_PARAMS] = { false }; + + ts_push_current_session(s); + if (ta_sess->param) { + res = copy_in_param(s, ta_sess->param, tee_param, did_map); + if (res != TEE_SUCCESS) { + unmap_mapped_param(ta_sess->param, did_map); + ta_sess->err_origin = TEE_ORIGIN_TEE; + goto out; + } + param_types = ta_sess->param->types; + } + + ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; + res = stc->pseudo_ta->invoke_command_entry_point(s->user_ctx, cmd, + param_types, + tee_param); + if (ta_sess->param) { + update_out_param(tee_param, ta_sess->param); + unmap_mapped_param(ta_sess->param, did_map); + } +out: + ts_pop_current_session(); + return res; +} + +static void pseudo_ta_enter_close_session(struct ts_session *s) +{ + struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); + void *user_ctx = s->user_ctx; + + ts_push_current_session(s); + + if (stc->pseudo_ta->close_session_entry_point) + stc->pseudo_ta->close_session_entry_point(user_ctx); + + if (stc->ctx.ref_count == 1 && stc->pseudo_ta->destroy_entry_point) + stc->pseudo_ta->destroy_entry_point(); + + ts_pop_current_session(); +} + +static void pseudo_ta_destroy(struct ts_ctx *ctx) +{ + free(to_pseudo_ta_ctx(ctx)); +} + +static const struct ts_ops pseudo_ta_ops = { + .enter_open_session = pseudo_ta_enter_open_session, + .enter_invoke_cmd = pseudo_ta_enter_invoke_cmd, + .enter_close_session = pseudo_ta_enter_close_session, + .destroy = pseudo_ta_destroy, +}; + +bool is_pseudo_ta_ctx(struct ts_ctx *ctx) +{ + return ctx->ops == &pseudo_ta_ops; +} + +/* Insures declared pseudo TAs conforms with core expectations */ +static TEE_Result verify_pseudo_tas_conformance(void) +{ + const struct pseudo_ta_head *start = + SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); + const struct pseudo_ta_head *end = + SCATTERED_ARRAY_END(pseudo_tas, struct pseudo_ta_head); + const struct pseudo_ta_head *pta; + + for (pta = start; pta < end; pta++) { + const struct pseudo_ta_head *pta2; + + /* PTAs must all have a specific UUID */ + for (pta2 = pta + 1; pta2 < end; pta2++) { + if (!memcmp(&pta->uuid, &pta2->uuid, sizeof(TEE_UUID))) + goto err; + } + + if (!pta->name || + (pta->flags & PTA_MANDATORY_FLAGS) != PTA_MANDATORY_FLAGS || + pta->flags & ~PTA_ALLOWED_FLAGS || + !pta->invoke_command_entry_point) + goto err; + } + return TEE_SUCCESS; +err: + DMSG("pseudo TA error at %p", (void *)pta); + panic("PTA"); +} + +service_init(verify_pseudo_tas_conformance); + +/*----------------------------------------------------------------------------- + * Initialises a session based on the UUID or ptr to the ta + * Returns ptr to the session (ta_session) and a TEE_Result + *---------------------------------------------------------------------------*/ +TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid, + struct tee_ta_session *s) +{ + struct pseudo_ta_ctx *stc = NULL; + struct tee_ta_ctx *ctx; + const struct pseudo_ta_head *ta; + + DMSG("Lookup pseudo TA %pUl", (void *)uuid); + + ta = SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); + while (true) { + if (ta >= SCATTERED_ARRAY_END(pseudo_tas, + struct pseudo_ta_head)) + return TEE_ERROR_ITEM_NOT_FOUND; + if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0) + break; + ta++; + } + + /* Load a new TA and create a session */ + DMSG("Open %s", ta->name); + stc = calloc(1, sizeof(struct pseudo_ta_ctx)); + if (!stc) + return TEE_ERROR_OUT_OF_MEMORY; + ctx = &stc->ctx; + + ctx->ref_count = 1; + ctx->flags = ta->flags; + stc->pseudo_ta = ta; + ctx->ts_ctx.uuid = ta->uuid; + ctx->ts_ctx.ops = &pseudo_ta_ops; + + mutex_lock(&tee_ta_mutex); + s->ts_sess.ctx = &ctx->ts_ctx; + TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); + mutex_unlock(&tee_ta_mutex); + + DMSG("%s : %pUl", stc->pseudo_ta->name, (void *)&ctx->ts_ctx.uuid); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/kernel/ree_fs_ta.c b/optee/optee_os/core/kernel/ree_fs_ta.c new file mode 100644 index 0000000..17b17b6 --- /dev/null +++ b/optee/optee_os/core/kernel/ree_fs_ta.c @@ -0,0 +1,807 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, 2019, Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ + +/* + * Security properties of REE-FS TAs + * ================================= + * + * Authentication only + * ------------------- + * + * Required security properties: + * 1. Authentication and non-repudiation of a TA to Service Provider (SP). + * 2. Integrity of a TA. + * + * To satisfy (1) and (2), SP needs to sign TA and OP-TEE core needs to verify + * the signature using SP public key with computed hash of the TA. + * + * Authentication along with Confidentiality + * ----------------------------------------- + * + * Required security properties: + * 1. Authentication and non-repudiation of a TA to Service Provider (SP). + * 2. Confidentiality of a TA. + * 3. Integrity of an encrypted TA blob. + * + * To satisfy (1), SP needs to sign plain TA and OP-TEE core needs to verify the + * signature using SP public key with computed hash of the TA. + * + * To satisfy (2) and (3), SP needs to do authenticated encryption of TA and + * OP-TEE core needs to do authenticated decryption of TA to retrieve its + * contents. Here encryption provides the confidentiality of TA and MAC tag + * provides the integrity of encrypted TA blob. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ree_fs_ta_handle { + struct shdr *nw_ta; /* Non-secure (shared memory) */ + size_t nw_ta_size; + struct mobj *mobj; + size_t offs; + struct shdr *shdr; /* Verified secure copy of @nw_ta's signed header */ + void *hash_ctx; + void *enc_ctx; + struct shdr_bootstrap_ta *bs_hdr; + struct shdr_encrypted_ta *ehdr; +}; + +struct ver_db_entry { + uint8_t uuid[sizeof(TEE_UUID)]; + uint32_t version; +}; + +struct ver_db_hdr { + uint32_t db_version; + uint32_t nb_entries; +}; + +static const char ta_ver_db[] = "ta_ver.db"; +static const char subkey_ver_db[] = "subkey_ver.db"; +static struct mutex ver_db_mutex = MUTEX_INITIALIZER; + +static TEE_Result check_update_version(const char *db_name, + const uint8_t uuid[sizeof(TEE_UUID)], + uint32_t version) +{ + struct ver_db_entry db_entry = { }; + const struct tee_file_operations *ops = NULL; + struct tee_file_handle *fh = NULL; + TEE_Result res = TEE_SUCCESS; + bool entry_found = false; + size_t len = 0; + unsigned int i = 0; + struct ver_db_hdr db_hdr = { }; + struct tee_pobj pobj = { + .obj_id = (void *)db_name, + .obj_id_len = strlen(db_name) + 1, + }; + + ops = tee_svc_storage_file_ops(TEE_STORAGE_PRIVATE); + if (!ops) + return TEE_SUCCESS; /* Compiled with no secure storage */ + + mutex_lock(&ver_db_mutex); + + res = ops->open(&pobj, NULL, &fh); + if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) + goto out; + + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + res = ops->create(&pobj, false, NULL, 0, NULL, 0, NULL, 0, &fh); + if (res != TEE_SUCCESS) + goto out; + + res = ops->write(fh, 0, &db_hdr, sizeof(db_hdr)); + if (res != TEE_SUCCESS) + goto out; + } else { + len = sizeof(db_hdr); + + res = ops->read(fh, 0, &db_hdr, &len); + if (res != TEE_SUCCESS) { + goto out; + } else if (len != sizeof(db_hdr)) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + } + + for (i = 0; i < db_hdr.nb_entries; i++) { + len = sizeof(db_entry); + + res = ops->read(fh, sizeof(db_hdr) + (i * len), &db_entry, + &len); + if (res != TEE_SUCCESS) { + goto out; + } else if (len != sizeof(db_entry)) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + if (!memcmp(uuid, db_entry.uuid, sizeof(TEE_UUID))) { + entry_found = true; + break; + } + } + + if (entry_found) { + if (db_entry.version > version) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto out; + } else if (db_entry.version < version) { + memcpy(db_entry.uuid, uuid, sizeof(TEE_UUID)); + db_entry.version = version; + len = sizeof(db_entry); + res = ops->write(fh, sizeof(db_hdr) + (i * len), + &db_entry, len); + if (res != TEE_SUCCESS) + goto out; + } + } else { + memcpy(db_entry.uuid, uuid, sizeof(TEE_UUID)); + db_entry.version = version; + len = sizeof(db_entry); + res = ops->write(fh, sizeof(db_hdr) + (db_hdr.nb_entries * len), + &db_entry, len); + if (res != TEE_SUCCESS) + goto out; + + db_hdr.nb_entries++; + res = ops->write(fh, 0, &db_hdr, sizeof(db_hdr)); + if (res != TEE_SUCCESS) + goto out; + } + +out: + ops->close(&fh); + mutex_unlock(&ver_db_mutex); + return res; +} + +/* + * Load a TA via RPC with UUID defined by input param @uuid. The virtual + * address of the raw TA binary is received in out parameter @ta. + */ +static TEE_Result rpc_load(const TEE_UUID *uuid, struct shdr **ta, + size_t *ta_size, struct mobj **mobj) +{ + TEE_Result res; + struct thread_param params[2]; + + if (!uuid || !ta || !mobj || !ta_size) + return TEE_ERROR_BAD_PARAMETERS; + + memset(params, 0, sizeof(params)); + params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; + tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); + params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; + + res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); + if (res != TEE_SUCCESS) + return res; + + *mobj = thread_rpc_alloc_payload(params[1].u.memref.size); + if (!*mobj) + return TEE_ERROR_OUT_OF_MEMORY; + + *ta = mobj_get_va(*mobj, 0, params[1].u.memref.size); + if (!*ta) { + res = TEE_ERROR_SHORT_BUFFER; + goto exit; + } + /* We don't expect NULL as thread_rpc_alloc_payload() was successful */ + assert(*ta); + *ta_size = params[1].u.memref.size; + + params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; + tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); + params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; + params[1].u.memref.offs = 0; + params[1].u.memref.mobj = *mobj; + + res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); +exit: + if (res != TEE_SUCCESS) + thread_rpc_free_payload(*mobj); + + return res; +} + +static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, + struct ts_store_handle **h) +{ + uint8_t next_uuid[sizeof(TEE_UUID)] = { }; + struct ree_fs_ta_handle *handle; + uint8_t *next_uuid_ptr = NULL; + struct shdr *shdr = NULL; + struct mobj *mobj = NULL; + void *hash_ctx = NULL; + struct shdr *ta = NULL; + size_t ta_size = 0; + TEE_Result res = TEE_SUCCESS; + size_t offs = 0; + struct shdr_bootstrap_ta *bs_hdr = NULL; + struct shdr_encrypted_ta *ehdr = NULL; + size_t shdr_sz = 0; + uint32_t max_depth = UINT32_MAX; + struct ftmn ftmn = { }; + unsigned int incr0_count = 0; + + handle = calloc(1, sizeof(*handle)); + if (!handle) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Request TA from tee-supplicant */ + res = rpc_load(uuid, &ta, &ta_size, &mobj); + if (res != TEE_SUCCESS) + goto error; + + /* Make secure copy of signed header */ + shdr = shdr_alloc_and_copy(0, ta, ta_size); + if (!shdr) { + res = TEE_ERROR_SECURITY; + goto error_free_payload; + } + + /* Validate header signature */ + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, shdr_verify_signature, shdr); + incr0_count++; + if (res != TEE_SUCCESS) + goto error_free_payload; + + shdr_sz = SHDR_GET_SIZE(shdr); + if (!shdr_sz) { + res = TEE_ERROR_SECURITY; + goto error_free_payload; + } + offs = shdr_sz; + + while (shdr->img_type == SHDR_SUBKEY) { + struct shdr_pub_key pub_key = { }; + + if (offs > ta_size) { + res = TEE_ERROR_SECURITY; + goto error_free_payload; + } + + res = shdr_load_pub_key(shdr, offs, (const void *)ta, + ta_size, next_uuid_ptr, max_depth, + &pub_key); + if (res) + goto error_free_payload; + + if (ADD_OVERFLOW(offs, shdr->img_size, &offs) || + ADD_OVERFLOW(offs, pub_key.name_size, &offs) || + offs > ta_size) { + res = TEE_ERROR_SECURITY; + goto error_free_payload; + } + max_depth = pub_key.max_depth; + memcpy(next_uuid, pub_key.next_uuid, sizeof(TEE_UUID)); + next_uuid_ptr = next_uuid; + + res = check_update_version(subkey_ver_db, pub_key.uuid, + pub_key.version); + if (res) { + res = TEE_ERROR_SECURITY; + shdr_free_pub_key(&pub_key); + goto error_free_payload; + } + + shdr_free(shdr); + shdr = shdr_alloc_and_copy(offs, ta, ta_size); + res = TEE_ERROR_SECURITY; + if (shdr) { + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, + shdr_verify_signature2, &pub_key, shdr); + incr0_count++; + } + shdr_free_pub_key(&pub_key); + if (res) + goto error_free_payload; + + shdr_sz = SHDR_GET_SIZE(shdr); + if (!shdr_sz) { + res = TEE_ERROR_SECURITY; + goto error_free_payload; + } + offs += shdr_sz; + if (offs > ta_size) { + res = TEE_ERROR_SECURITY; + goto error_free_payload; + } + } + + if (shdr->img_type != SHDR_TA && shdr->img_type != SHDR_BOOTSTRAP_TA && + shdr->img_type != SHDR_ENCRYPTED_TA) { + res = TEE_ERROR_SECURITY; + goto error_free_payload; + } + + /* + * If we're verifying this TA using a subkey, make sure that + * the UUID of the TA belongs to the namespace defined by the subkey. + * The namespace is defined as in RFC4122, that is, valid UUID + * is calculated as a V5 UUID SHA-512(subkey UUID, "name string"). + */ + if (next_uuid_ptr) { + TEE_UUID check_uuid = { }; + + tee_uuid_from_octets(&check_uuid, next_uuid_ptr); + if (memcmp(&check_uuid, uuid, sizeof(*uuid))) { + res = TEE_ERROR_SECURITY; + goto error_free_payload; + } + } + + /* + * Initialize a hash context and run the algorithm over the signed + * header (less the final file hash and its signature of course) + */ + res = crypto_hash_alloc_ctx(&hash_ctx, + TEE_DIGEST_HASH_TO_ALGO(shdr->algo)); + if (res != TEE_SUCCESS) + goto error_free_payload; + res = crypto_hash_init(hash_ctx); + if (res != TEE_SUCCESS) + goto error_free_hash; + res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr)); + if (res != TEE_SUCCESS) + goto error_free_hash; + + if (shdr->img_type == SHDR_BOOTSTRAP_TA || + shdr->img_type == SHDR_ENCRYPTED_TA) { + TEE_UUID bs_uuid = { }; + size_t sz = shdr_sz; + + if (ADD_OVERFLOW(sz, sizeof(*bs_hdr), &sz) || ta_size < sz) { + res = TEE_ERROR_SECURITY; + goto error_free_hash; + } + + bs_hdr = malloc(sizeof(*bs_hdr)); + if (!bs_hdr) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_free_hash; + } + + memcpy(bs_hdr, (uint8_t *)ta + offs, sizeof(*bs_hdr)); + + /* + * There's a check later that the UUID embedded inside the + * ELF is matching, but since we now have easy access to + * the expected uuid of the TA we check it a bit earlier + * here. + */ + tee_uuid_from_octets(&bs_uuid, bs_hdr->uuid); + if (memcmp(&bs_uuid, uuid, sizeof(TEE_UUID))) { + res = TEE_ERROR_SECURITY; + goto error_free_hash; + } + + res = crypto_hash_update(hash_ctx, (uint8_t *)bs_hdr, + sizeof(*bs_hdr)); + if (res != TEE_SUCCESS) + goto error_free_hash; + offs += sizeof(*bs_hdr); + handle->bs_hdr = bs_hdr; + } + + if (shdr->img_type == SHDR_ENCRYPTED_TA) { + struct shdr_encrypted_ta img_ehdr = { }; + size_t sz = shdr_sz; + size_t ehdr_sz = 0; + + if (ADD_OVERFLOW(sz, sizeof(struct shdr_bootstrap_ta), &sz) || + ADD_OVERFLOW(sz, sizeof(img_ehdr), &sz) || + ta_size < sz) { + res = TEE_ERROR_SECURITY; + goto error_free_hash; + } + + memcpy(&img_ehdr, ((uint8_t *)ta + offs), sizeof(img_ehdr)); + ehdr_sz = SHDR_ENC_GET_SIZE(&img_ehdr); + sz -= sizeof(img_ehdr); + if (!ehdr_sz || ADD_OVERFLOW(sz, ehdr_sz, &sz) || + ta_size < sz) { + res = TEE_ERROR_SECURITY; + goto error_free_hash; + } + + /* + * This is checked further down too, but we must sanity + * check shdr->img_size before it's used below. + */ + if (ta_size != offs + ehdr_sz + shdr->img_size) { + res = TEE_ERROR_SECURITY; + goto error_free_hash; + } + + ehdr = malloc(ehdr_sz); + if (!ehdr) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto error_free_hash; + } + + *ehdr = img_ehdr; + memcpy((uint8_t *)ehdr + sizeof(img_ehdr), + (uint8_t *)ta + offs + sizeof(img_ehdr), + ehdr_sz - sizeof(img_ehdr)); + + res = crypto_hash_update(hash_ctx, (uint8_t *)ehdr, ehdr_sz); + if (res != TEE_SUCCESS) + goto error_free_hash; + + res = tee_ta_decrypt_init(&handle->enc_ctx, ehdr, + shdr->img_size); + if (res != TEE_SUCCESS) + goto error_free_hash; + + offs += ehdr_sz; + handle->ehdr = ehdr; + } + + if (ta_size != offs + shdr->img_size) { + res = TEE_ERROR_SECURITY; + goto error_free_hash; + } + + handle->nw_ta = ta; + handle->nw_ta_size = ta_size; + handle->offs = offs; + handle->hash_ctx = hash_ctx; + handle->shdr = shdr; + handle->mobj = mobj; + *h = (struct ts_store_handle *)handle; + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR1, + FTMN_STEP_COUNT(incr0_count), TEE_SUCCESS); + return TEE_SUCCESS; + +error_free_hash: + crypto_hash_free_ctx(hash_ctx); +error_free_payload: + thread_rpc_free_payload(mobj); +error: + free(ehdr); + free(bs_hdr); + shdr_free(shdr); + free(handle); + FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR1, res); + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR1, + FTMN_STEP_COUNT(incr0_count, 1), res); + return res; +} + +static TEE_Result ree_fs_ta_get_size(const struct ts_store_handle *h, + size_t *size) +{ + struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; + + *size = handle->shdr->img_size; + return TEE_SUCCESS; +} + +static TEE_Result ree_fs_ta_get_tag(const struct ts_store_handle *h, + uint8_t *tag, unsigned int *tag_len) +{ + struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; + + if (!tag || *tag_len < handle->shdr->hash_size) { + *tag_len = handle->shdr->hash_size; + return TEE_ERROR_SHORT_BUFFER; + } + *tag_len = handle->shdr->hash_size; + + memcpy(tag, SHDR_GET_HASH(handle->shdr), handle->shdr->hash_size); + + return TEE_SUCCESS; +} + +static TEE_Result check_digest(struct ree_fs_ta_handle *h) +{ + void *digest = NULL; + TEE_Result res; + + digest = malloc(h->shdr->hash_size); + if (!digest) + return TEE_ERROR_OUT_OF_MEMORY; + res = crypto_hash_final(h->hash_ctx, digest, h->shdr->hash_size); + if (res != TEE_SUCCESS) { + res = TEE_ERROR_SECURITY; + goto out; + } + if (FTMN_CALLEE_DONE_MEMCMP(memcmp, digest, SHDR_GET_HASH(h->shdr), + h->shdr->hash_size)) + res = TEE_ERROR_SECURITY; +out: + free(digest); + return res; +} + +static TEE_Result ree_fs_ta_read(struct ts_store_handle *h, void *data, + size_t len) +{ + struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; + + uint8_t *src = (uint8_t *)handle->nw_ta + handle->offs; + size_t next_offs = 0; + uint8_t *dst = src; + TEE_Result res = TEE_SUCCESS; + + if (ADD_OVERFLOW(handle->offs, len, &next_offs) || + next_offs > handle->nw_ta_size) + return TEE_ERROR_BAD_PARAMETERS; + + if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) { + if (data) { + dst = data; /* Hash secure buffer */ + res = tee_ta_decrypt_update(handle->enc_ctx, dst, src, + len); + if (res != TEE_SUCCESS) + return TEE_ERROR_SECURITY; + } else { + size_t num_bytes = 0; + size_t b_size = MIN(1024U, len); + uint8_t *b = malloc(b_size); + + if (!b) + return TEE_ERROR_OUT_OF_MEMORY; + + dst = NULL; + while (num_bytes < len) { + size_t n = MIN(b_size, len - num_bytes); + + res = tee_ta_decrypt_update(handle->enc_ctx, b, + src + num_bytes, n); + if (res) + break; + num_bytes += n; + + res = crypto_hash_update(handle->hash_ctx, b, + n); + if (res) + break; + } + + free(b); + if (res != TEE_SUCCESS) + return TEE_ERROR_SECURITY; + } + } else if (data) { + dst = data; /* Hash secure buffer (shm might be modified) */ + memcpy(dst, src, len); + } + + if (dst) { + res = crypto_hash_update(handle->hash_ctx, dst, len); + if (res != TEE_SUCCESS) + return TEE_ERROR_SECURITY; + } + + handle->offs = next_offs; + if (handle->offs == handle->nw_ta_size) { + if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) { + /* + * Last read: time to finalize authenticated + * decryption. + */ + res = tee_ta_decrypt_final(handle->enc_ctx, + handle->ehdr, NULL, NULL, 0); + if (res != TEE_SUCCESS) + return TEE_ERROR_SECURITY; + } + /* + * Last read: time to check if our digest matches the expected + * one (from the signed header) + */ + res = check_digest(handle); + if (res != TEE_SUCCESS) + return res; + + if (handle->bs_hdr) + res = check_update_version(ta_ver_db, + handle->bs_hdr->uuid, + handle->bs_hdr->ta_version); + } + return res; +} + +static void ree_fs_ta_close(struct ts_store_handle *h) +{ + struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; + + if (!handle) + return; + thread_rpc_free_payload(handle->mobj); + crypto_hash_free_ctx(handle->hash_ctx); + free(handle->shdr); + free(handle->ehdr); + free(handle->bs_hdr); + free(handle); +} + +#ifndef CFG_REE_FS_TA_BUFFERED +REGISTER_TA_STORE(9) = { + .description = "REE", + .open = ree_fs_ta_open, + .get_size = ree_fs_ta_get_size, + .get_tag = ree_fs_ta_get_tag, + .read = ree_fs_ta_read, + .close = ree_fs_ta_close, +}; +#endif + +#ifdef CFG_REE_FS_TA_BUFFERED + +/* + * This is a wrapper around the "REE FS" TA store. + * The whole TA/library is read into a temporary buffer during .open(). This + * allows the binary to be authenticated before any data is read and processed + * by the upper layer (ELF loader). + */ + +struct buf_ree_fs_ta_handle { + struct ts_store_handle *h; /* Note: a REE FS TA store handle */ + size_t ta_size; + tee_mm_entry_t *mm; + uint8_t *buf; + size_t offs; + uint8_t *tag; + unsigned int tag_len; +}; + +static TEE_Result buf_ta_open(const TEE_UUID *uuid, + struct ts_store_handle **h) +{ + struct buf_ree_fs_ta_handle *handle = NULL; + struct ftmn ftmn = { }; + TEE_Result res = TEE_SUCCESS; + + handle = calloc(1, sizeof(*handle)); + if (!handle) + return TEE_ERROR_OUT_OF_MEMORY; + FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("ree_fs_ta_open")); + res = ree_fs_ta_open(uuid, &handle->h); + if (!res) + FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, res); + FTMN_POP_LINKED_CALL(&ftmn); + if (res) + goto err_free_handle; + ftmn_checkpoint(&ftmn, FTMN_INCR1); + + res = ree_fs_ta_get_size(handle->h, &handle->ta_size); + if (res) + goto err; + + res = ree_fs_ta_get_tag(handle->h, NULL, &handle->tag_len); + if (res != TEE_ERROR_SHORT_BUFFER) { + res = TEE_ERROR_GENERIC; + goto err; + } + handle->tag = malloc(handle->tag_len); + if (!handle->tag) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + res = ree_fs_ta_get_tag(handle->h, handle->tag, &handle->tag_len); + if (res) + goto err; + + handle->mm = tee_mm_alloc(&tee_mm_sec_ddr, handle->ta_size); + if (!handle->mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + handle->buf = phys_to_virt(tee_mm_get_smem(handle->mm), + MEM_AREA_TA_RAM, handle->ta_size); + if (!handle->buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("check_digest")); + res = ree_fs_ta_read(handle->h, handle->buf, handle->ta_size); + if (!res) + FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, res); + FTMN_POP_LINKED_CALL(&ftmn); + if (res) + goto err; + ftmn_checkpoint(&ftmn, FTMN_INCR1); + + *h = (struct ts_store_handle *)handle; + ree_fs_ta_close(handle->h); + return ftmn_return_res(&ftmn, FTMN_STEP_COUNT(2, 2), TEE_SUCCESS); + +err: + ree_fs_ta_close(handle->h); + tee_mm_free(handle->mm); + free(handle->tag); +err_free_handle: + free(handle); + return res; +} + +static TEE_Result buf_ta_get_size(const struct ts_store_handle *h, + size_t *size) +{ + struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; + + *size = handle->ta_size; + return TEE_SUCCESS; +} + +static TEE_Result buf_ta_read(struct ts_store_handle *h, void *data, + size_t len) +{ + struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; + uint8_t *src = handle->buf + handle->offs; + size_t next_offs = 0; + + if (ADD_OVERFLOW(handle->offs, len, &next_offs) || + next_offs > handle->ta_size) + return TEE_ERROR_BAD_PARAMETERS; + + if (data) + memcpy(data, src, len); + handle->offs = next_offs; + return TEE_SUCCESS; +} + +static TEE_Result buf_ta_get_tag(const struct ts_store_handle *h, + uint8_t *tag, unsigned int *tag_len) +{ + struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; + + *tag_len = handle->tag_len; + if (!tag || *tag_len < handle->tag_len) + return TEE_ERROR_SHORT_BUFFER; + + memcpy(tag, handle->tag, handle->tag_len); + + return TEE_SUCCESS; +} + +static void buf_ta_close(struct ts_store_handle *h) +{ + struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; + + if (!handle) + return; + tee_mm_free(handle->mm); + free(handle->tag); + free(handle); +} + +REGISTER_TA_STORE(9) = { + .description = "REE [buffered]", + .open = buf_ta_open, + .get_size = buf_ta_get_size, + .get_tag = buf_ta_get_tag, + .read = buf_ta_read, + .close = buf_ta_close, +}; + +#endif /* CFG_REE_FS_TA_BUFFERED */ diff --git a/optee/optee_os/core/kernel/refcount.c b/optee/optee_os/core/kernel/refcount.c new file mode 100644 index 0000000..64b08a6 --- /dev/null +++ b/optee/optee_os/core/kernel/refcount.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include + +bool refcount_inc(struct refcount *r) +{ + unsigned int nval; + unsigned int oval = atomic_load_uint(&r->val); + + while (true) { + nval = oval + 1; + + /* r->val is 0, we can't do anything more. */ + if (!oval) + return false; + + if (atomic_cas_uint(&r->val, &oval, nval)) + return true; + /* + * At this point atomic_cas_uint() has updated oval to the + * current r->val. + */ + } +} + +bool refcount_dec(struct refcount *r) +{ + unsigned int nval; + unsigned int oval = atomic_load_uint(&r->val); + + while (true) { + assert(oval); + nval = oval - 1; + + if (atomic_cas_uint(&r->val, &oval, nval)) { + /* + * Value has been updated, if value was set to 0 + * return true to indicate that. + */ + return !nval; + } + /* + * At this point atomic_cas_uint() has updated oval to the + * current r->val. + */ + } +} diff --git a/optee/optee_os/core/kernel/scall.c b/optee/optee_os/core/kernel/scall.c new file mode 100644 index 0000000..454cabc --- /dev/null +++ b/optee/optee_os/core/kernel/scall.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2022, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if (TRACE_LEVEL == TRACE_FLOW) && defined(CFG_TEE_CORE_TA_TRACE) +#define TRACE_SYSCALLS +#endif + +struct syscall_entry { + syscall_t fn; +#ifdef TRACE_SYSCALLS + const char *name; +#endif +}; + +#ifdef TRACE_SYSCALLS +#define SYSCALL_ENTRY(_fn) { .fn = (syscall_t)_fn, .name = #_fn } +#else +#define SYSCALL_ENTRY(_fn) { .fn = (syscall_t)_fn } +#endif + +/* + * This array is ordered according to the SYSCALL ids TEE_SCN_xxx + */ +static const struct syscall_entry tee_syscall_table[] = { + SYSCALL_ENTRY(syscall_sys_return), + SYSCALL_ENTRY(syscall_log), + SYSCALL_ENTRY(syscall_panic), + SYSCALL_ENTRY(syscall_get_property), + SYSCALL_ENTRY(syscall_get_property_name_to_index), + SYSCALL_ENTRY(syscall_open_ta_session), + SYSCALL_ENTRY(syscall_close_ta_session), + SYSCALL_ENTRY(syscall_invoke_ta_command), + SYSCALL_ENTRY(syscall_check_access_rights), + SYSCALL_ENTRY(syscall_get_cancellation_flag), + SYSCALL_ENTRY(syscall_unmask_cancellation), + SYSCALL_ENTRY(syscall_mask_cancellation), + SYSCALL_ENTRY(syscall_wait), + SYSCALL_ENTRY(syscall_get_time), + SYSCALL_ENTRY(syscall_set_ta_time), + SYSCALL_ENTRY(syscall_cryp_state_alloc), + SYSCALL_ENTRY(syscall_cryp_state_copy), + SYSCALL_ENTRY(syscall_cryp_state_free), + SYSCALL_ENTRY(syscall_hash_init), + SYSCALL_ENTRY(syscall_hash_update), + SYSCALL_ENTRY(syscall_hash_final), + SYSCALL_ENTRY(syscall_cipher_init), + SYSCALL_ENTRY(syscall_cipher_update), + SYSCALL_ENTRY(syscall_cipher_final), + SYSCALL_ENTRY(syscall_cryp_obj_get_info), + SYSCALL_ENTRY(syscall_cryp_obj_restrict_usage), + SYSCALL_ENTRY(syscall_cryp_obj_get_attr), + SYSCALL_ENTRY(syscall_cryp_obj_alloc), + SYSCALL_ENTRY(syscall_cryp_obj_close), + SYSCALL_ENTRY(syscall_cryp_obj_reset), + SYSCALL_ENTRY(syscall_cryp_obj_populate), + SYSCALL_ENTRY(syscall_cryp_obj_copy), + SYSCALL_ENTRY(syscall_cryp_derive_key), + SYSCALL_ENTRY(syscall_cryp_random_number_generate), + SYSCALL_ENTRY(syscall_authenc_init), + SYSCALL_ENTRY(syscall_authenc_update_aad), + SYSCALL_ENTRY(syscall_authenc_update_payload), + SYSCALL_ENTRY(syscall_authenc_enc_final), + SYSCALL_ENTRY(syscall_authenc_dec_final), + SYSCALL_ENTRY(syscall_asymm_operate), + SYSCALL_ENTRY(syscall_asymm_verify), + SYSCALL_ENTRY(syscall_storage_obj_open), + SYSCALL_ENTRY(syscall_storage_obj_create), + SYSCALL_ENTRY(syscall_storage_obj_del), + SYSCALL_ENTRY(syscall_storage_obj_rename), + SYSCALL_ENTRY(syscall_storage_alloc_enum), + SYSCALL_ENTRY(syscall_storage_free_enum), + SYSCALL_ENTRY(syscall_storage_reset_enum), + SYSCALL_ENTRY(syscall_storage_start_enum), + SYSCALL_ENTRY(syscall_storage_next_enum), + SYSCALL_ENTRY(syscall_storage_obj_read), + SYSCALL_ENTRY(syscall_storage_obj_write), + SYSCALL_ENTRY(syscall_storage_obj_trunc), + SYSCALL_ENTRY(syscall_storage_obj_seek), + SYSCALL_ENTRY(syscall_obj_generate_key), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_not_supported), + SYSCALL_ENTRY(syscall_cache_operation), +}; + +/* + * The ldelf return, log, panic syscalls have the same functionality and syscall + * number as the user TAs'. To avoid unnecessary code duplication, the ldelf SVC + * handler doesn't implement separate functions for these. + */ +static const struct syscall_entry ldelf_syscall_table[] = { + SYSCALL_ENTRY(syscall_sys_return), + SYSCALL_ENTRY(syscall_log), + SYSCALL_ENTRY(syscall_panic), + SYSCALL_ENTRY(ldelf_syscall_map_zi), + SYSCALL_ENTRY(ldelf_syscall_unmap), + SYSCALL_ENTRY(ldelf_syscall_open_bin), + SYSCALL_ENTRY(ldelf_syscall_close_bin), + SYSCALL_ENTRY(ldelf_syscall_map_bin), + SYSCALL_ENTRY(ldelf_syscall_copy_from_bin), + SYSCALL_ENTRY(ldelf_syscall_set_prot), + SYSCALL_ENTRY(ldelf_syscall_remap), + SYSCALL_ENTRY(ldelf_syscall_gen_rnd_num), +}; + +#ifdef TRACE_SYSCALLS +static void trace_syscall(size_t num) +{ + if (num == TEE_SCN_RETURN || num == TEE_SCN_LOG || num > TEE_SCN_MAX) + return; + FMSG("syscall #%zu (%s)", num, tee_syscall_table[num].name); +} +#else +static void trace_syscall(size_t num __unused) +{ +} +#endif + +#ifdef CFG_SYSCALL_FTRACE +static void __noprof ftrace_syscall_enter(size_t num) +{ + struct ts_session *s = NULL; + + /* + * Syscalls related to inter-TA communication can't be traced in the + * caller TA's ftrace buffer as it involves context switching to callee + * TA's context. Moreover, user can enable ftrace for callee TA to dump + * function trace in corresponding ftrace buffer. + */ + if (num == TEE_SCN_OPEN_TA_SESSION || num == TEE_SCN_CLOSE_TA_SESSION || + num == TEE_SCN_INVOKE_TA_COMMAND) + return; + + s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); + if (s && s->fbuf) + s->fbuf->syscall_trace_enabled = true; +} + +static void __noprof ftrace_syscall_leave(void) +{ + struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); + + if (s && s->fbuf) + s->fbuf->syscall_trace_enabled = false; +} +#else +static void __noprof ftrace_syscall_enter(size_t num __unused) +{ +} + +static void __noprof ftrace_syscall_leave(void) +{ +} +#endif + +static syscall_t get_tee_syscall_func(size_t num) +{ + /* Cast away const */ + struct syscall_entry *sc_table = (void *)tee_syscall_table; + + static_assert(ARRAY_SIZE(tee_syscall_table) == (TEE_SCN_MAX + 1)); + + if (num > TEE_SCN_MAX) + return (syscall_t)syscall_not_supported; + + return load_no_speculate(&sc_table[num].fn, &sc_table[0].fn, + &sc_table[TEE_SCN_MAX].fn + 1); +} + +bool scall_handle_user_ta(struct thread_scall_regs *regs) +{ + size_t scn = 0; + size_t max_args = 0; + syscall_t scf = NULL; + + scall_get_max_args(regs, &scn, &max_args); + + trace_syscall(scn); + + if (max_args > TEE_SVC_MAX_ARGS) { + DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args); + scall_set_retval(regs, TEE_ERROR_GENERIC); + return true; /* return to user mode */ + } + + scf = get_tee_syscall_func(scn); + + ftrace_syscall_enter(scn); + + scall_set_retval(regs, scall_do_call(regs, scf)); + + ftrace_syscall_leave(); + + /* + * Return true if we're to return to user mode, + * thread_scall_handler() will take care of the rest. + */ + return scn != TEE_SCN_RETURN && scn != TEE_SCN_PANIC; +} + +static syscall_t get_ldelf_syscall_func(size_t num) +{ + /* Cast away const */ + struct syscall_entry *sc_table = (void *)ldelf_syscall_table; + + COMPILE_TIME_ASSERT(ARRAY_SIZE(ldelf_syscall_table) == + (LDELF_SCN_MAX + 1)); + + if (num > LDELF_SCN_MAX) + return (syscall_t)syscall_not_supported; + + return load_no_speculate(&sc_table[num].fn, &sc_table[0].fn, + &sc_table[LDELF_SCN_MAX].fn + 1); +} + +bool scall_handle_ldelf(struct thread_scall_regs *regs) +{ + size_t scn = 0; + size_t max_args = 0; + syscall_t scf = NULL; + + scall_get_max_args(regs, &scn, &max_args); + + trace_syscall(scn); + + if (max_args > TEE_SVC_MAX_ARGS) { + DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args); + scall_set_retval(regs, TEE_ERROR_GENERIC); + return true; /* return to user mode */ + } + + scf = get_ldelf_syscall_func(scn); + + ftrace_syscall_enter(scn); + + scall_set_retval(regs, scall_do_call(regs, scf)); + + ftrace_syscall_leave(); + + /* + * Return true if we're to return to user mode, + * thread_scall_handler() will take care of the rest. + */ + return scn != LDELF_RETURN && scn != LDELF_PANIC; +} + +uint32_t scall_sys_return_helper(uint32_t ret, bool panic, uint32_t panic_code, + struct thread_scall_regs *regs) +{ + if (panic) { + TAMSG_RAW(""); + TAMSG_RAW("TA panicked with code 0x%" PRIx32, panic_code); + scall_save_panic_stack(regs); + } + + scall_set_sys_return_regs(regs, panic, panic_code); + + return ret; +} diff --git a/optee/optee_os/core/kernel/scattered_array.c b/optee/optee_os/core/kernel/scattered_array.c new file mode 100644 index 0000000..9cb1f6f --- /dev/null +++ b/optee/optee_os/core/kernel/scattered_array.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include + +const void *scattered_array_relax_ptr(const void *p) +{ + return p; +} diff --git a/optee/optee_os/core/kernel/secstor_ta.c b/optee/optee_os/core/kernel/secstor_ta.c new file mode 100644 index 0000000..f3deeb4 --- /dev/null +++ b/optee/optee_os/core/kernel/secstor_ta.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include + +static TEE_Result secstor_ta_open(const TEE_UUID *uuid, + struct ts_store_handle **handle) +{ + TEE_Result res; + struct tee_tadb_ta_read *ta; + size_t l; + const struct tee_tadb_property *prop; + + res = tee_tadb_ta_open(uuid, &ta); + if (res) + return res; + prop = tee_tadb_ta_get_property(ta); + + l = prop->custom_size; + res = tee_tadb_ta_read(ta, NULL, &l); + if (res) + goto err; + if (l != prop->custom_size) { + res = TEE_ERROR_CORRUPT_OBJECT; + goto err; + } + + *handle = (struct ts_store_handle *)ta; + + return TEE_SUCCESS; +err: + tee_tadb_ta_close(ta); + return res; +} + +static TEE_Result secstor_ta_get_size(const struct ts_store_handle *h, + size_t *size) +{ + struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h; + const struct tee_tadb_property *prop = tee_tadb_ta_get_property(ta); + + *size = prop->bin_size; + + return TEE_SUCCESS; +} + +static TEE_Result secstor_ta_get_tag(const struct ts_store_handle *h, + uint8_t *tag, unsigned int *tag_len) +{ + return tee_tadb_get_tag((struct tee_tadb_ta_read *)h, tag, tag_len); +} + +static TEE_Result secstor_ta_read(struct ts_store_handle *h, void *data, + size_t len) +{ + struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h; + size_t l = len; + TEE_Result res = tee_tadb_ta_read(ta, data, &l); + + if (res) + return res; + if (l != len) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +static void secstor_ta_close(struct ts_store_handle *h) +{ + struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h; + + tee_tadb_ta_close(ta); +} + +REGISTER_TA_STORE(4) = { + .description = "Secure Storage TA", + .open = secstor_ta_open, + .get_size = secstor_ta_get_size, + .get_tag = secstor_ta_get_tag, + .read = secstor_ta_read, + .close = secstor_ta_close, +}; diff --git a/optee/optee_os/core/kernel/show_conf.c b/optee/optee_os/core/kernel/show_conf.c new file mode 100644 index 0000000..c6495ed --- /dev/null +++ b/optee/optee_os/core/kernel/show_conf.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 1019 Huawei Technologies Co., Ltd + */ + +#include +#include + +extern const char conf_str[]; + +static TEE_Result show_conf(void) +{ +#if (TRACE_LEVEL >= TRACE_INFO) + IMSG("Contents of conf.mk (decode with 'base64 -d | xz -d'):"); + trace_ext_puts(conf_str); +#endif + return TEE_SUCCESS; +} +service_init(show_conf); diff --git a/optee/optee_os/core/kernel/spin_lock_debug.c b/optee/optee_os/core/kernel/spin_lock_debug.c new file mode 100644 index 0000000..b7b7c3d --- /dev/null +++ b/optee/optee_os/core/kernel/spin_lock_debug.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include + +void spinlock_count_incr(void) +{ + struct thread_core_local *l = thread_get_core_local(); + + l->locked_count++; + assert(l->locked_count); +} + +void spinlock_count_decr(void) +{ + struct thread_core_local *l = thread_get_core_local(); + + assert(l->locked_count); + l->locked_count--; +} + +bool __nostackcheck have_spinlock(void) +{ + struct thread_core_local *l; + + if (!thread_foreign_intr_disabled()) { + /* + * Normally we can't be holding a spinlock since doing so would + * imply foreign interrupts are disabled (or the spinlock + * logic is flawed). + */ + return false; + } + + l = thread_get_core_local(); + + return !!l->locked_count; +} diff --git a/optee/optee_os/core/kernel/sub.mk b/optee/optee_os/core/kernel/sub.mk new file mode 100644 index 0000000..f05265a --- /dev/null +++ b/optee/optee_os/core/kernel/sub.mk @@ -0,0 +1,60 @@ +srcs-$(CFG_CORE_SANITIZE_KADDRESS) += asan.c +cflags-remove-asan.c-y += $(cflags_kasan) +srcs-$(CFG_TEE_CORE_DEBUG) += spin_lock_debug.c +srcs-y += assert.c +srcs-y += console.c +srcs-$(CFG_DT) += dt.c +srcs-$(CFG_DT) += dt_driver.c +srcs-$(CFG_DT_DRIVER_EMBEDDED_TEST) += dt_driver_test.c +srcs-y += pm.c +srcs-y += handle.c +srcs-y += interrupt.c +ifeq ($(CFG_WITH_USER_TA),y) +srcs-y += ldelf_loader.c +srcs-y += ldelf_syscalls.c +srcs-y += scall.c +endif +srcs-$(CFG_LOCKDEP) += lockdep.c +ifneq ($(CFG_CORE_FFA),y) +srcs-$(CFG_CORE_DYN_SHM) += msg_param.c +endif +srcs-y += panic.c +srcs-y += trace_ext.c +srcs-y += refcount.c +srcs-y += delay.c +srcs-y += tee_time.c +srcs-$(CFG_SECURE_TIME_SOURCE_REE) += tee_time_ree.c +srcs-y += otp_stubs.c +srcs-y += tee_misc.c +srcs-y += tee_ta_manager.c +srcs-y += ts_manager.c +srcs-$(CFG_CORE_SANITIZE_UNDEFINED) += ubsan.c +srcs-y += scattered_array.c +srcs-y += huk_subkey.c +srcs-$(CFG_SHOW_CONF_ON_BOOT) += show_conf.c +srcs-y += user_mode_ctx.c +srcs-$(CFG_CORE_TPM_EVENT_LOG) += tpm.c +srcs-y += initcall.c +srcs-$(CFG_WITH_USER_TA) += user_access.c +srcs-y += mutex.c +srcs-$(CFG_LOCKDEP) += mutex_lockdep.c +srcs-y += wait_queue.c +srcs-y += notif.c +srcs-y += thread.c + +ifeq ($(CFG_WITH_USER_TA),y) +srcs-y += user_ta.c +srcs-$(CFG_REE_FS_TA) += ree_fs_ta.c +srcs-$(CFG_EARLY_TA) += early_ta.c +srcs-$(CFG_SECSTOR_TA) += secstor_ta.c +endif + +srcs-$(CFG_EMBEDDED_TS) += embedded_ts.c +srcs-y += pseudo_ta.c + +ifeq ($(CFG_SYSCALL_FTRACE),y) +# We would not like to profile spin_lock_debug.c file as it provides +# common APIs that are needed for ftrace framework to trace syscalls. +# So profiling this file could create an incorrect cyclic behaviour. +cflags-remove-spin_lock_debug.c-$(CFG_TEE_CORE_DEBUG) += -pg +endif diff --git a/optee/optee_os/core/kernel/tee_misc.c b/optee/optee_os/core/kernel/tee_misc.c new file mode 100644 index 0000000..240e702 --- /dev/null +++ b/optee/optee_os/core/kernel/tee_misc.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include +#include +#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; +} + +static bool is_valid_conf_and_notnull_size(paddr_t b, paddr_size_t bl, + paddr_t a, paddr_size_t al) +{ + /* invalid config return false */ + if ((b - 1 + bl < b) || (a - 1 + al < a)) + return false; + /* null sized areas are never inside / outside / overlap */ + if (!bl || !al) + return false; + return true; +} + +/* Returns true when buffer 'b' is fully contained in area 'a' */ +bool core_is_buffer_inside(paddr_t b, paddr_size_t bl, + paddr_t a, paddr_size_t al) +{ + /* invalid config or "null size" return false */ + if (!is_valid_conf_and_notnull_size(b, bl, a, al)) + return false; + + if ((b >= a) && (b - 1 + bl <= a - 1 + al)) + return true; + return false; +} + +/* Returns true when buffer 'b' is fully outside area 'a' */ +bool core_is_buffer_outside(paddr_t b, paddr_size_t bl, + paddr_t a, paddr_size_t al) +{ + /* invalid config or "null size" return false */ + if (!is_valid_conf_and_notnull_size(b, bl, a, al)) + return false; + + if ((b + bl - 1 < a) || (b > a + al - 1)) + return true; + return false; +} + +/* Returns true when buffer 'b' intersects area 'a' */ +bool core_is_buffer_intersect(paddr_t b, paddr_size_t bl, + paddr_t a, paddr_size_t al) +{ + /* invalid config or "null size" return false */ + if (!is_valid_conf_and_notnull_size(b, bl, a, al)) + return false; + + if ((b + bl - 1 < a) || (b > a + al - 1)) + return false; + return true; +} + +void *alloc_cache_aligned(size_t size) +{ + void *ptr = NULL; + size_t alloc_size = 0; + uint32_t cacheline_size = 0; + + cacheline_size = cache_get_max_line_size(); + if (ROUNDUP_OVERFLOW(size, cacheline_size, &alloc_size)) + return NULL; + + ptr = memalign(cacheline_size, alloc_size); + if (!ptr) + return NULL; + + memset(ptr, 0, size); + + return ptr; +} diff --git a/optee/optee_os/core/kernel/tee_ta_manager.c b/optee/optee_os/core/kernel/tee_ta_manager.c new file mode 100644 index 0000000..f526a12 --- /dev/null +++ b/optee/optee_os/core/kernel/tee_ta_manager.c @@ -0,0 +1,1178 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Arm Limited + */ + +#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 +#include +#include +#include +#include + +#if defined(CFG_TA_STATS) +#define MAX_DUMP_SESS_NUM (16) +struct tee_ta_dump_stats { + TEE_UUID uuid; + uint32_t panicked; /* True if TA has panicked */ + uint32_t sess_num; /* Number of opened session */ + struct malloc_stats heap; +}; + +struct tee_ta_dump_ctx { + TEE_UUID uuid; + uint32_t panicked; + bool is_user_ta; + uint32_t sess_num; + uint32_t sess_id[MAX_DUMP_SESS_NUM]; +}; +#endif + +/* This mutex protects the critical section in tee_ta_init_session */ +struct mutex tee_ta_mutex = MUTEX_INITIALIZER; +/* This condvar is used when waiting for a TA context to become initialized */ +struct condvar tee_ta_init_cv = CONDVAR_INITIALIZER; +struct tee_ta_ctx_head tee_ctxes = TAILQ_HEAD_INITIALIZER(tee_ctxes); + +#ifndef CFG_CONCURRENT_SINGLE_INSTANCE_TA +static struct condvar tee_ta_cv = CONDVAR_INITIALIZER; +static short int tee_ta_single_instance_thread = THREAD_ID_INVALID; +static size_t tee_ta_single_instance_count; +#endif + +#ifdef CFG_CONCURRENT_SINGLE_INSTANCE_TA +static void lock_single_instance(void) +{ +} + +static void unlock_single_instance(void) +{ +} + +static bool has_single_instance_lock(void) +{ + return false; +} +#else +static void lock_single_instance(void) +{ + /* Requires tee_ta_mutex to be held */ + if (tee_ta_single_instance_thread != thread_get_id()) { + /* Wait until the single-instance lock is available. */ + while (tee_ta_single_instance_thread != THREAD_ID_INVALID) + condvar_wait(&tee_ta_cv, &tee_ta_mutex); + + tee_ta_single_instance_thread = thread_get_id(); + assert(tee_ta_single_instance_count == 0); + } + + tee_ta_single_instance_count++; +} + +static void unlock_single_instance(void) +{ + /* Requires tee_ta_mutex to be held */ + assert(tee_ta_single_instance_thread == thread_get_id()); + assert(tee_ta_single_instance_count > 0); + + tee_ta_single_instance_count--; + if (tee_ta_single_instance_count == 0) { + tee_ta_single_instance_thread = THREAD_ID_INVALID; + condvar_signal(&tee_ta_cv); + } +} + +static bool has_single_instance_lock(void) +{ + /* Requires tee_ta_mutex to be held */ + return tee_ta_single_instance_thread == thread_get_id(); +} +#endif + +struct tee_ta_session *__noprof to_ta_session(struct ts_session *sess) +{ + assert(is_ta_ctx(sess->ctx) || is_stmm_ctx(sess->ctx)); + return container_of(sess, struct tee_ta_session, ts_sess); +} + +static struct tee_ta_ctx *ts_to_ta_ctx(struct ts_ctx *ctx) +{ + if (is_ta_ctx(ctx)) + return to_ta_ctx(ctx); + + if (is_stmm_ctx(ctx)) + return &(to_stmm_ctx(ctx)->ta_ctx); + + panic("bad context"); +} + +static bool tee_ta_try_set_busy(struct tee_ta_ctx *ctx) +{ + bool rc = true; + + if (ctx->flags & TA_FLAG_CONCURRENT) + return true; + + mutex_lock(&tee_ta_mutex); + + if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) + lock_single_instance(); + + if (has_single_instance_lock()) { + if (ctx->busy) { + /* + * We're holding the single-instance lock and the + * TA is busy, as waiting now would only cause a + * dead-lock, we release the lock and return false. + */ + rc = false; + if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) + unlock_single_instance(); + } + } else { + /* + * We're not holding the single-instance lock, we're free to + * wait for the TA to become available. + */ + while (ctx->busy) + condvar_wait(&ctx->busy_cv, &tee_ta_mutex); + } + + /* Either it's already true or we should set it to true */ + ctx->busy = true; + + mutex_unlock(&tee_ta_mutex); + return rc; +} + +static void tee_ta_set_busy(struct tee_ta_ctx *ctx) +{ + if (!tee_ta_try_set_busy(ctx)) + panic(); +} + +static void tee_ta_clear_busy(struct tee_ta_ctx *ctx) +{ + if (ctx->flags & TA_FLAG_CONCURRENT) + return; + + mutex_lock(&tee_ta_mutex); + + assert(ctx->busy); + ctx->busy = false; + condvar_signal(&ctx->busy_cv); + + if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) + unlock_single_instance(); + + mutex_unlock(&tee_ta_mutex); +} + +static void dec_session_ref_count(struct tee_ta_session *s) +{ + assert(s->ref_count > 0); + s->ref_count--; + if (s->ref_count == 1) + condvar_signal(&s->refc_cv); +} + +void tee_ta_put_session(struct tee_ta_session *s) +{ + mutex_lock(&tee_ta_mutex); + + if (s->lock_thread == thread_get_id()) { + s->lock_thread = THREAD_ID_INVALID; + condvar_signal(&s->lock_cv); + } + dec_session_ref_count(s); + + mutex_unlock(&tee_ta_mutex); +} + +static struct tee_ta_session *tee_ta_find_session_nolock(uint32_t id, + struct tee_ta_session_head *open_sessions) +{ + struct tee_ta_session *s = NULL; + struct tee_ta_session *found = NULL; + + TAILQ_FOREACH(s, open_sessions, link) { + if (s->id == id) { + found = s; + break; + } + } + + return found; +} + +struct tee_ta_session *tee_ta_find_session(uint32_t id, + struct tee_ta_session_head *open_sessions) +{ + struct tee_ta_session *s = NULL; + + mutex_lock(&tee_ta_mutex); + + s = tee_ta_find_session_nolock(id, open_sessions); + + mutex_unlock(&tee_ta_mutex); + + return s; +} + +struct tee_ta_session *tee_ta_get_session(uint32_t id, bool exclusive, + struct tee_ta_session_head *open_sessions) +{ + struct tee_ta_session *s; + + mutex_lock(&tee_ta_mutex); + + while (true) { + s = tee_ta_find_session_nolock(id, open_sessions); + if (!s) + break; + if (s->unlink) { + s = NULL; + break; + } + s->ref_count++; + if (!exclusive) + break; + + assert(s->lock_thread != thread_get_id()); + + while (s->lock_thread != THREAD_ID_INVALID && !s->unlink) + condvar_wait(&s->lock_cv, &tee_ta_mutex); + + if (s->unlink) { + dec_session_ref_count(s); + s = NULL; + break; + } + + s->lock_thread = thread_get_id(); + break; + } + + mutex_unlock(&tee_ta_mutex); + return s; +} + +static void tee_ta_unlink_session(struct tee_ta_session *s, + struct tee_ta_session_head *open_sessions) +{ + mutex_lock(&tee_ta_mutex); + + assert(s->ref_count >= 1); + assert(s->lock_thread == thread_get_id()); + assert(!s->unlink); + + s->unlink = true; + condvar_broadcast(&s->lock_cv); + + while (s->ref_count != 1) + condvar_wait(&s->refc_cv, &tee_ta_mutex); + + TAILQ_REMOVE(open_sessions, s, link); + + mutex_unlock(&tee_ta_mutex); +} + +static void destroy_session(struct tee_ta_session *s, + struct tee_ta_session_head *open_sessions) +{ +#if defined(CFG_FTRACE_SUPPORT) + if (s->ts_sess.ctx && s->ts_sess.ctx->ops->dump_ftrace) { + ts_push_current_session(&s->ts_sess); + s->ts_sess.fbuf = NULL; + s->ts_sess.ctx->ops->dump_ftrace(s->ts_sess.ctx); + ts_pop_current_session(); + } +#endif + + tee_ta_unlink_session(s, open_sessions); +#if defined(CFG_TA_GPROF_SUPPORT) + free(s->ts_sess.sbuf); +#endif + free(s); +} + +static void destroy_context(struct tee_ta_ctx *ctx) +{ + DMSG("Destroy TA ctx (0x%" PRIxVA ")", (vaddr_t)ctx); + + condvar_destroy(&ctx->busy_cv); + ctx->ts_ctx.ops->destroy(&ctx->ts_ctx); +} + +static void destroy_ta_ctx_from_session(struct tee_ta_session *s) +{ + struct tee_ta_session *sess = NULL; + struct tee_ta_session_head *open_sessions = NULL; + struct tee_ta_ctx *ctx = NULL; + struct user_ta_ctx *utc = NULL; + struct ts_ctx *ts_ctx = s->ts_sess.ctx; + size_t count = 1; /* start counting the references to the context */ + + DMSG("Remove references to context (%#"PRIxVA")", (vaddr_t)ts_ctx); + + mutex_lock(&tee_ta_mutex); + nsec_sessions_list_head(&open_sessions); + + /* + * Next two loops will remove all references to the context which is + * about to be destroyed, but avoiding such operation to the current + * session. That will be done later in this function, only after + * the context will be properly destroyed. + */ + + /* + * Scan the entire list of opened sessions by the clients from + * non-secure world. + */ + TAILQ_FOREACH(sess, open_sessions, link) { + if (sess->ts_sess.ctx == ts_ctx && sess != s) { + sess->ts_sess.ctx = NULL; + count++; + } + } + + /* + * Scan all sessions opened from secure side by searching through + * all available TA instances and for each context, scan all opened + * sessions. + */ + TAILQ_FOREACH(ctx, &tee_ctxes, link) { + if (is_user_ta_ctx(&ctx->ts_ctx)) { + utc = to_user_ta_ctx(&ctx->ts_ctx); + + TAILQ_FOREACH(sess, &utc->open_sessions, link) { + if (sess->ts_sess.ctx == ts_ctx && + sess != s) { + sess->ts_sess.ctx = NULL; + count++; + } + } + } + } + + ctx = ts_to_ta_ctx(ts_ctx); + assert(count == ctx->ref_count); + + TAILQ_REMOVE(&tee_ctxes, ctx, link); + mutex_unlock(&tee_ta_mutex); + + destroy_context(ctx); + s->ts_sess.ctx = NULL; +} + +/* + * tee_ta_context_find - 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->ts_ctx.uuid, uuid, sizeof(TEE_UUID)) == 0) + return ctx; + } + + return NULL; +} + +/* check if requester (client ID) matches session initial client */ +static TEE_Result check_client(struct tee_ta_session *s, const TEE_Identity *id) +{ + if (id == KERN_IDENTITY) + return TEE_SUCCESS; + + if (id == NSAPP_IDENTITY) { + if (s->clnt_id.login == TEE_LOGIN_TRUSTED_APP) { + DMSG("nsec tries to hijack TA session"); + return TEE_ERROR_ACCESS_DENIED; + } + return TEE_SUCCESS; + } + + if (memcmp(&s->clnt_id, id, sizeof(TEE_Identity)) != 0) { + DMSG("client id mismatch"); + return TEE_ERROR_ACCESS_DENIED; + } + return TEE_SUCCESS; +} + +/* + * Check if invocation parameters matches TA properties + * + * @s - current session handle + * @param - already identified memory references hold a valid 'mobj'. + * + * Policy: + * - All TAs can access 'non-secure' shared memory. + * - All TAs can access TEE private memory (seccpy) + * - Only SDP flagged TAs can accept SDP memory references. + */ +#ifndef CFG_SECURE_DATA_PATH +static bool check_params(struct tee_ta_session *sess __unused, + struct tee_ta_param *param __unused) +{ + /* + * When CFG_SECURE_DATA_PATH is not enabled, SDP memory references + * are rejected at OP-TEE core entry. Hence here all TAs have same + * permissions regarding memory reference parameters. + */ + return true; +} +#else +static bool check_params(struct tee_ta_session *sess, + struct tee_ta_param *param) +{ + int n; + + /* + * When CFG_SECURE_DATA_PATH is enabled, OP-TEE entry allows SHM and + * SDP memory references. Only TAs flagged SDP can access SDP memory. + */ + if (sess->ts_sess.ctx && + ts_to_ta_ctx(sess->ts_sess.ctx)->flags & TA_FLAG_SECURE_DATA_PATH) + return true; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); + struct param_mem *mem = ¶m->u[n].mem; + + if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && + param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && + param_type != TEE_PARAM_TYPE_MEMREF_INOUT) + continue; + if (!mem->size) + continue; + if (mobj_is_sdp_mem(mem->mobj)) + return false; + } + return true; +} +#endif + +static void set_invoke_timeout(struct tee_ta_session *sess, + uint32_t cancel_req_to) +{ + TEE_Time current_time; + TEE_Time cancel_time; + + if (cancel_req_to == TEE_TIMEOUT_INFINITE) + goto infinite; + + if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) + goto infinite; + + if (ADD_OVERFLOW(current_time.seconds, cancel_req_to / 1000, + &cancel_time.seconds)) + goto infinite; + + cancel_time.millis = current_time.millis + cancel_req_to % 1000; + if (cancel_time.millis > 1000) { + if (ADD_OVERFLOW(current_time.seconds, 1, + &cancel_time.seconds)) + goto infinite; + + cancel_time.seconds++; + cancel_time.millis -= 1000; + } + + sess->cancel_time = cancel_time; + return; + +infinite: + sess->cancel_time.seconds = UINT32_MAX; + sess->cancel_time.millis = UINT32_MAX; +} + +/*----------------------------------------------------------------------------- + * Close a Trusted Application and free available resources + *---------------------------------------------------------------------------*/ +TEE_Result tee_ta_close_session(struct tee_ta_session *csess, + struct tee_ta_session_head *open_sessions, + const TEE_Identity *clnt_id) +{ + struct tee_ta_session *sess = NULL; + struct tee_ta_ctx *ctx = NULL; + struct ts_ctx *ts_ctx = NULL; + bool keep_alive = false; + + DMSG("csess 0x%" PRIxVA " id %u", + (vaddr_t)csess, csess ? csess->id : UINT_MAX); + + if (!csess) + return TEE_ERROR_ITEM_NOT_FOUND; + + sess = tee_ta_get_session(csess->id, true, open_sessions); + + if (!sess) { + EMSG("session 0x%" PRIxVA " to be removed is not found", + (vaddr_t)csess); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + if (check_client(sess, clnt_id) != TEE_SUCCESS) { + tee_ta_put_session(sess); + return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ + } + + DMSG("Destroy session"); + + ts_ctx = sess->ts_sess.ctx; + if (!ts_ctx) { + destroy_session(sess, open_sessions); + return TEE_SUCCESS; + } + + ctx = ts_to_ta_ctx(ts_ctx); + if (ctx->panicked) { + destroy_session(sess, open_sessions); + } else { + tee_ta_set_busy(ctx); + set_invoke_timeout(sess, TEE_TIMEOUT_INFINITE); + ts_ctx->ops->enter_close_session(&sess->ts_sess); + destroy_session(sess, open_sessions); + tee_ta_clear_busy(ctx); + } + + mutex_lock(&tee_ta_mutex); + + if (ctx->ref_count <= 0) + panic(); + + ctx->ref_count--; + keep_alive = (ctx->flags & TA_FLAG_INSTANCE_KEEP_ALIVE) && + (ctx->flags & TA_FLAG_SINGLE_INSTANCE); + if (!ctx->ref_count && !keep_alive) { + TAILQ_REMOVE(&tee_ctxes, ctx, link); + mutex_unlock(&tee_ta_mutex); + + destroy_context(ctx); + } else + mutex_unlock(&tee_ta_mutex); + + return TEE_SUCCESS; +} + +static TEE_Result tee_ta_init_session_with_context(struct tee_ta_session *s, + const TEE_UUID *uuid) +{ + struct tee_ta_ctx *ctx = NULL; + + while (true) { + ctx = tee_ta_context_find(uuid); + if (!ctx) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (!is_user_ta_ctx(&ctx->ts_ctx) || + !to_user_ta_ctx(&ctx->ts_ctx)->uctx.is_initializing) + break; + /* + * Context is still initializing, wait here until it's + * fully initialized. Note that we're searching for the + * context again since it may have been removed while we + * where sleeping. + */ + condvar_wait(&tee_ta_init_cv, &tee_ta_mutex); + } + + /* + * If TA isn't single instance it should be loaded as new + * instance instead of doing anything with this instance. + * So tell the caller that we didn't find the TA it the + * caller will load a new instance. + */ + if ((ctx->flags & TA_FLAG_SINGLE_INSTANCE) == 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* + * The TA is single instance, if it isn't multi session we + * can't create another session unless its reference is zero + */ + if (!(ctx->flags & TA_FLAG_MULTI_SESSION) && ctx->ref_count) + return TEE_ERROR_BUSY; + + DMSG("Re-open TA %pUl", (void *)&ctx->ts_ctx.uuid); + + ctx->ref_count++; + s->ts_sess.ctx = &ctx->ts_ctx; + s->ts_sess.handle_scall = s->ts_sess.ctx->ops->handle_scall; + return TEE_SUCCESS; +} + +static uint32_t new_session_id(struct tee_ta_session_head *open_sessions) +{ + struct tee_ta_session *last = NULL; + uint32_t saved = 0; + uint32_t id = 1; + + last = TAILQ_LAST(open_sessions, tee_ta_session_head); + if (last) { + /* This value is less likely to be already used */ + id = last->id + 1; + if (!id) + id++; /* 0 is not valid */ + } + + saved = id; + do { + if (!tee_ta_find_session_nolock(id, open_sessions)) + return id; + id++; + if (!id) + id++; + } while (id != saved); + + return 0; +} + +static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err, + struct tee_ta_session_head *open_sessions, + const TEE_UUID *uuid, + struct tee_ta_session **sess) +{ + TEE_Result res; + struct tee_ta_session *s = calloc(1, sizeof(struct tee_ta_session)); + + *err = TEE_ORIGIN_TEE; + if (!s) + return TEE_ERROR_OUT_OF_MEMORY; + + s->cancel_mask = true; + condvar_init(&s->refc_cv); + condvar_init(&s->lock_cv); + s->lock_thread = THREAD_ID_INVALID; + s->ref_count = 1; + + mutex_lock(&tee_ta_mutex); + s->id = new_session_id(open_sessions); + if (!s->id) { + res = TEE_ERROR_OVERFLOW; + goto err_mutex_unlock; + } + + TAILQ_INSERT_TAIL(open_sessions, s, link); + + /* Look for already loaded TA */ + res = tee_ta_init_session_with_context(s, uuid); + mutex_unlock(&tee_ta_mutex); + if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) + goto out; + + /* Look for secure partition */ + res = stmm_init_session(uuid, s); + if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) + goto out; + + /* Look for pseudo TA */ + res = tee_ta_init_pseudo_ta_session(uuid, s); + if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) + goto out; + + /* Look for user TA */ + res = tee_ta_init_user_ta_session(uuid, s); + +out: + if (!res) { + *sess = s; + return TEE_SUCCESS; + } + + mutex_lock(&tee_ta_mutex); + TAILQ_REMOVE(open_sessions, s, link); +err_mutex_unlock: + mutex_unlock(&tee_ta_mutex); + free(s); + return res; +} + +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 TEE_Identity *clnt_id, + uint32_t cancel_req_to, + struct tee_ta_param *param) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_ta_session *s = NULL; + struct tee_ta_ctx *ctx = NULL; + struct ts_ctx *ts_ctx = NULL; + bool panicked = false; + bool was_busy = false; + + res = tee_ta_init_session(err, open_sessions, uuid, &s); + if (res != TEE_SUCCESS) { + DMSG("init session failed 0x%x", res); + return res; + } + + if (!check_params(s, param)) + return TEE_ERROR_BAD_PARAMETERS; + + ts_ctx = s->ts_sess.ctx; + if (ts_ctx) + ctx = ts_to_ta_ctx(ts_ctx); + + if (!ctx || ctx->panicked) { + DMSG("panicked, call tee_ta_close_session()"); + tee_ta_close_session(s, open_sessions, KERN_IDENTITY); + *err = TEE_ORIGIN_TEE; + return TEE_ERROR_TARGET_DEAD; + } + + *sess = s; + /* Save identity of the owner of the session */ + s->clnt_id = *clnt_id; + + if (tee_ta_try_set_busy(ctx)) { + s->param = param; + set_invoke_timeout(s, cancel_req_to); + res = ts_ctx->ops->enter_open_session(&s->ts_sess); + tee_ta_clear_busy(ctx); + } else { + /* Deadlock avoided */ + res = TEE_ERROR_BUSY; + was_busy = true; + } + + panicked = ctx->panicked; + s->param = NULL; + + /* + * Origin error equal to TEE_ORIGIN_TRUSTED_APP for "regular" error, + * apart from panicking. + */ + if (panicked || was_busy) + *err = TEE_ORIGIN_TEE; + else + *err = s->err_origin; + + tee_ta_put_session(s); + if (panicked || res != TEE_SUCCESS) + tee_ta_close_session(s, open_sessions, KERN_IDENTITY); + + if (res != TEE_SUCCESS) + EMSG("Failed. Return error 0x%x", 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) +{ + struct tee_ta_ctx *ta_ctx = NULL; + struct ts_ctx *ts_ctx = NULL; + TEE_Result res = TEE_SUCCESS; + + if (check_client(sess, clnt_id) != TEE_SUCCESS) + return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ + + if (!check_params(sess, param)) + return TEE_ERROR_BAD_PARAMETERS; + + ts_ctx = sess->ts_sess.ctx; + if (!ts_ctx) { + /* The context has been already destroyed */ + *err = TEE_ORIGIN_TEE; + return TEE_ERROR_TARGET_DEAD; + } + + ta_ctx = ts_to_ta_ctx(ts_ctx); + if (ta_ctx->panicked) { + DMSG("Panicked !"); + destroy_ta_ctx_from_session(sess); + *err = TEE_ORIGIN_TEE; + return TEE_ERROR_TARGET_DEAD; + } + + tee_ta_set_busy(ta_ctx); + + sess->param = param; + set_invoke_timeout(sess, cancel_req_to); + res = ts_ctx->ops->enter_invoke_cmd(&sess->ts_sess, cmd); + + sess->param = NULL; + tee_ta_clear_busy(ta_ctx); + + if (ta_ctx->panicked) { + destroy_ta_ctx_from_session(sess); + *err = TEE_ORIGIN_TEE; + return TEE_ERROR_TARGET_DEAD; + } + + *err = sess->err_origin; + + /* Short buffer is not an effective error case */ + if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) + DMSG("Error: %x of %d", res, *err); + + return res; +} + +#if defined(CFG_TA_STATS) +static TEE_Result dump_ta_memstats(struct tee_ta_session *s, + struct tee_ta_param *param) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_ta_ctx *ctx = NULL; + struct ts_ctx *ts_ctx = NULL; + + ts_ctx = s->ts_sess.ctx; + if (!ts_ctx) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (is_user_ta_ctx(ts_ctx) && + to_user_ta_ctx(ts_ctx)->uctx.is_initializing) + return TEE_ERROR_BAD_STATE; + + ctx = ts_to_ta_ctx(ts_ctx); + + if (ctx->panicked) + return TEE_ERROR_TARGET_DEAD; + + if (tee_ta_try_set_busy(ctx)) { + s->param = param; + set_invoke_timeout(s, TEE_TIMEOUT_INFINITE); + res = ts_ctx->ops->dump_mem_stats(&s->ts_sess); + s->param = NULL; + tee_ta_clear_busy(ctx); + } else { + /* Deadlock avoided */ + res = TEE_ERROR_BUSY; + } + + return res; +} + +static void init_dump_ctx(struct tee_ta_dump_ctx *dump_ctx) +{ + struct tee_ta_session *sess = NULL; + struct tee_ta_session_head *open_sessions = NULL; + struct tee_ta_ctx *ctx = NULL; + unsigned int n = 0; + + nsec_sessions_list_head(&open_sessions); + /* + * Scan all sessions opened from secure side by searching through + * all available TA instances and for each context, scan all opened + * sessions. + */ + TAILQ_FOREACH(ctx, &tee_ctxes, link) { + unsigned int cnt = 0; + + if (!is_user_ta_ctx(&ctx->ts_ctx)) + continue; + + memcpy(&dump_ctx[n].uuid, &ctx->ts_ctx.uuid, + sizeof(ctx->ts_ctx.uuid)); + dump_ctx[n].panicked = ctx->panicked; + dump_ctx[n].is_user_ta = is_user_ta_ctx(&ctx->ts_ctx); + TAILQ_FOREACH(sess, open_sessions, link) { + if (sess->ts_sess.ctx == &ctx->ts_ctx) { + if (cnt == MAX_DUMP_SESS_NUM) + break; + + dump_ctx[n].sess_id[cnt] = sess->id; + cnt++; + } + } + + dump_ctx[n].sess_num = cnt; + n++; + } +} + +static TEE_Result dump_ta_stats(struct tee_ta_dump_ctx *dump_ctx, + struct tee_ta_dump_stats *dump_stats, + size_t ta_count) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_ta_session *sess = NULL; + struct tee_ta_session_head *open_sessions = NULL; + struct tee_ta_param param = { }; + unsigned int i = 0; + unsigned int j = 0; + + nsec_sessions_list_head(&open_sessions); + + for (i = 0; i < ta_count; i++) { + struct tee_ta_dump_stats *stats = &dump_stats[i]; + + memcpy(&stats->uuid, &dump_ctx[i].uuid, + sizeof(dump_ctx[i].uuid)); + stats->panicked = dump_ctx[i].panicked; + stats->sess_num = dump_ctx[i].sess_num; + + /* Find a session from dump context */ + for (j = 0, sess = NULL; j < dump_ctx[i].sess_num && !sess; j++) + sess = tee_ta_get_session(dump_ctx[i].sess_id[j], true, + open_sessions); + + if (!sess) + continue; + /* If session is existing, get its heap stats */ + memset(¶m, 0, sizeof(struct tee_ta_param)); + param.types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + res = dump_ta_memstats(sess, ¶m); + if (res == TEE_SUCCESS) { + stats->heap.allocated = param.u[0].val.a; + stats->heap.max_allocated = param.u[0].val.b; + stats->heap.size = param.u[1].val.a; + stats->heap.num_alloc_fail = param.u[1].val.b; + stats->heap.biggest_alloc_fail = param.u[2].val.a; + stats->heap.biggest_alloc_fail_used = param.u[2].val.b; + } else { + memset(&stats->heap, 0, sizeof(stats->heap)); + } + tee_ta_put_session(sess); + } + + return TEE_SUCCESS; +} + +TEE_Result tee_ta_instance_stats(void *buf, size_t *buf_size) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_ta_dump_stats *dump_stats = NULL; + struct tee_ta_dump_ctx *dump_ctx = NULL; + struct tee_ta_ctx *ctx = NULL; + size_t sz = 0; + size_t ta_count = 0; + + if (!buf_size) + return TEE_ERROR_BAD_PARAMETERS; + + mutex_lock(&tee_ta_mutex); + + /* Go through all available TA and calc out the actual buffer size. */ + TAILQ_FOREACH(ctx, &tee_ctxes, link) + if (is_user_ta_ctx(&ctx->ts_ctx)) + ta_count++; + + sz = sizeof(struct tee_ta_dump_stats) * ta_count; + if (!sz) { + /* sz = 0 means there is no UTA, return no item found. */ + res = TEE_ERROR_ITEM_NOT_FOUND; + } else if (!buf || *buf_size < sz) { + /* + * buf is null or pass size less than actual size + * means caller try to query the buffer size. + * update *buf_size. + */ + *buf_size = sz; + res = TEE_ERROR_SHORT_BUFFER; + } else if (!IS_ALIGNED_WITH_TYPE(buf, uint32_t)) { + DMSG("Data alignment"); + res = TEE_ERROR_BAD_PARAMETERS; + } else { + dump_stats = (struct tee_ta_dump_stats *)buf; + dump_ctx = malloc(sizeof(struct tee_ta_dump_ctx) * ta_count); + if (!dump_ctx) + res = TEE_ERROR_OUT_OF_MEMORY; + else + init_dump_ctx(dump_ctx); + } + mutex_unlock(&tee_ta_mutex); + + if (res != TEE_SUCCESS) + return res; + + /* Dump user ta stats by iterating dump_ctx[] */ + res = dump_ta_stats(dump_ctx, dump_stats, ta_count); + if (res == TEE_SUCCESS) + *buf_size = sz; + + free(dump_ctx); + return res; +} +#endif + +TEE_Result tee_ta_cancel_command(TEE_ErrorOrigin *err, + struct tee_ta_session *sess, + const TEE_Identity *clnt_id) +{ + *err = TEE_ORIGIN_TEE; + + if (check_client(sess, clnt_id) != TEE_SUCCESS) + return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ + + sess->cancel = true; + return TEE_SUCCESS; +} + +bool tee_ta_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; +} + +#if defined(CFG_TA_GPROF_SUPPORT) +void tee_ta_gprof_sample_pc(vaddr_t pc) +{ + struct ts_session *s = ts_get_current_session(); + struct user_ta_ctx *utc = NULL; + struct sample_buf *sbuf = NULL; + TEE_Result res = 0; + size_t idx = 0; + + sbuf = s->sbuf; + if (!sbuf || !sbuf->enabled) + return; /* PC sampling is not enabled */ + + idx = (((uint64_t)pc - sbuf->offset)/2 * sbuf->scale)/65536; + if (idx < sbuf->nsamples) { + utc = to_user_ta_ctx(s->ctx); + res = vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)&sbuf->samples[idx], + sizeof(*sbuf->samples)); + if (res != TEE_SUCCESS) + return; + sbuf->samples[idx]++; + } + sbuf->count++; +} + +static void gprof_update_session_utime(bool suspend, struct ts_session *s, + uint64_t now) +{ + struct sample_buf *sbuf = s->sbuf; + + if (!sbuf) + return; + + if (suspend) { + assert(sbuf->usr_entered); + sbuf->usr += now - sbuf->usr_entered; + sbuf->usr_entered = 0; + } else { + assert(!sbuf->usr_entered); + if (!now) + now++; /* 0 is reserved */ + sbuf->usr_entered = now; + } +} + +/* + * Update user-mode CPU time for the current session + * @suspend: true if session is being suspended (leaving user mode), false if + * it is resumed (entering user mode) + */ +static void tee_ta_update_session_utime(bool suspend) +{ + struct ts_session *s = ts_get_current_session(); + uint64_t now = barrier_read_counter_timer(); + + gprof_update_session_utime(suspend, s, now); +} + +void tee_ta_update_session_utime_suspend(void) +{ + tee_ta_update_session_utime(true); +} + +void tee_ta_update_session_utime_resume(void) +{ + tee_ta_update_session_utime(false); +} +#endif + +#if defined(CFG_FTRACE_SUPPORT) +static void ftrace_update_times(bool suspend) +{ + struct ts_session *s = ts_get_current_session_may_fail(); + struct ftrace_buf *fbuf = NULL; + uint64_t now = 0; + uint32_t i = 0; + + if (!s) + return; + + now = barrier_read_counter_timer(); + + fbuf = s->fbuf; + if (!fbuf) + return; + + if (suspend) { + fbuf->suspend_time = now; + } else { + for (i = 0; i <= fbuf->ret_idx; i++) + fbuf->begin_time[i] += now - fbuf->suspend_time; + } +} + +void tee_ta_ftrace_update_times_suspend(void) +{ + ftrace_update_times(true); +} + +void tee_ta_ftrace_update_times_resume(void) +{ + ftrace_update_times(false); +} +#endif + +bool is_ta_ctx(struct ts_ctx *ctx) +{ + return is_user_ta_ctx(ctx) || is_pseudo_ta_ctx(ctx); +} diff --git a/optee/optee_os/core/kernel/tee_time.c b/optee/optee_os/core/kernel/tee_time.c new file mode 100644 index 0000000..e1a462b --- /dev/null +++ b/optee/optee_os/core/kernel/tee_time.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2020, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct time_source _time_source; + +static TEE_Result register_time_source(void) +{ + time_source_init(); + + return TEE_SUCCESS; +} +early_init(register_time_source); + +TEE_Result tee_time_get_sys_time(TEE_Time *time) +{ + return _time_source.get_sys_time(time); +} + +uint32_t tee_time_get_sys_time_protection_level(void) +{ + return _time_source.protection_level; +} + +void tee_time_wait(uint32_t milliseconds_delay) +{ + struct thread_param params = + THREAD_PARAM_VALUE(IN, milliseconds_delay, 0, 0); + + thread_rpc_cmd(OPTEE_RPC_CMD_SUSPEND, 1, ¶ms); +} + +/* + * 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) +{ + struct thread_param params = THREAD_PARAM_VALUE(OUT, 0, 0, 0); + TEE_Result res = TEE_SUCCESS; + + if (!time) + return TEE_ERROR_BAD_PARAMETERS; + + res = thread_rpc_cmd(OPTEE_RPC_CMD_GET_TIME, 1, ¶ms); + if (res == TEE_SUCCESS) { + time->seconds = params.u.value.a; + time->millis = params.u.value.b / 1000000; + } + + return res; +} diff --git a/optee/optee_os/core/kernel/tee_time_ree.c b/optee/optee_os/core/kernel/tee_time_ree.c new file mode 100644 index 0000000..5e744ad --- /dev/null +++ b/optee/optee_os/core/kernel/tee_time_ree.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ + +#include +#include +#include + +static TEE_Time prev; + +static struct mutex time_mu = MUTEX_INITIALIZER; + +static TEE_Result get_monotonic_ree_time(TEE_Time *time) +{ + TEE_Result res; + + res = tee_time_get_ree_time(time); + if (res != TEE_SUCCESS) + return res; + + mutex_lock(&time_mu); + if (time->seconds < prev.seconds || + (time->seconds == prev.seconds && + time->millis < prev.millis)) + *time = prev; /* REE time was rolled back */ + else + prev = *time; + mutex_unlock(&time_mu); + + return res; +} + +static const struct time_source ree_time_source = { + .name = "ree", + .protection_level = 100, + .get_sys_time = get_monotonic_ree_time, +}; + +REGISTER_TIME_SOURCE(ree_time_source) diff --git a/optee/optee_os/core/kernel/thread.c b/optee/optee_os/core/kernel/thread.c new file mode 100644 index 0000000..c49ec8e --- /dev/null +++ b/optee/optee_os/core/kernel/thread.c @@ -0,0 +1,673 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2022, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020-2021, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct thread_ctx threads[CFG_NUM_THREADS]; + +struct thread_core_local thread_core_local[CFG_TEE_CORE_NB_CORE] __nex_bss; + +/* + * Stacks + * + * [Lower addresses on the left] + * + * [ STACK_CANARY_SIZE/2 | STACK_CHECK_EXTRA | STACK_XXX_SIZE | STACK_CANARY_SIZE/2 ] + * ^ ^ ^ ^ + * stack_xxx[n] "hard" top "soft" top bottom + */ + +#ifdef CFG_WITH_STACK_CANARIES +#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] +#endif + +#define DECLARE_STACK(name, num_stacks, stack_size, linkage) \ +linkage uint32_t name[num_stacks] \ + [ROUNDUP(stack_size + STACK_CANARY_SIZE + STACK_CHECK_EXTRA, \ + STACK_ALIGNMENT) / sizeof(uint32_t)] \ + __attribute__((section(".nozi_stack." # name), \ + aligned(STACK_ALIGNMENT))) + +#define GET_STACK(stack) ((vaddr_t)(stack) + STACK_SIZE(stack)) + +DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE, + /* global linkage */); +DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE, static); +#ifndef CFG_WITH_PAGER +DECLARE_STACK(stack_thread, CFG_NUM_THREADS, STACK_THREAD_SIZE, static); +#endif + +#define GET_STACK_TOP_HARD(stack, n) \ + ((vaddr_t)&(stack)[n] + STACK_CANARY_SIZE / 2) +#define GET_STACK_TOP_SOFT(stack, n) \ + (GET_STACK_TOP_HARD(stack, n) + STACK_CHECK_EXTRA) +#define GET_STACK_BOTTOM(stack, n) ((vaddr_t)&(stack)[n] + sizeof(stack[n]) - \ + STACK_CANARY_SIZE / 2) + +const uint32_t stack_tmp_stride __section(".identity_map.stack_tmp_stride") = + sizeof(stack_tmp[0]); + +/* + * This stack setup info is required by secondary boot cores before they + * each locally enable the pager (the mmu). Hence kept in pager sections. + */ +DECLARE_KEEP_PAGER(stack_tmp_stride); + +static unsigned int thread_global_lock __nex_bss = SPINLOCK_UNLOCK; + +void thread_init_canaries(void) +{ +#ifdef CFG_WITH_STACK_CANARIES + 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); +#if !defined(CFG_WITH_PAGER) && !defined(CFG_NS_VIRTUALIZATION) + INIT_CANARY(stack_thread); +#endif +#endif/*CFG_WITH_STACK_CANARIES*/ +} + +#define CANARY_DIED(stack, loc, n, addr) \ + do { \ + EMSG_RAW("Dead canary at %s of '%s[%zu]' (%p)", #loc, #stack, \ + n, (void *)addr); \ + panic(); \ + } while (0) + +void thread_check_canaries(void) +{ +#ifdef CFG_WITH_STACK_CANARIES + uint32_t *canary = NULL; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(stack_tmp); n++) { + canary = &GET_START_CANARY(stack_tmp, n); + if (*canary != START_CANARY_VALUE) + CANARY_DIED(stack_tmp, start, n, canary); + canary = &GET_END_CANARY(stack_tmp, n); + if (*canary != END_CANARY_VALUE) + CANARY_DIED(stack_tmp, end, n, canary); + } + + for (n = 0; n < ARRAY_SIZE(stack_abt); n++) { + canary = &GET_START_CANARY(stack_abt, n); + if (*canary != START_CANARY_VALUE) + CANARY_DIED(stack_abt, start, n, canary); + canary = &GET_END_CANARY(stack_abt, n); + if (*canary != END_CANARY_VALUE) + CANARY_DIED(stack_abt, end, n, canary); + } +#if !defined(CFG_WITH_PAGER) && !defined(CFG_NS_VIRTUALIZATION) + for (n = 0; n < ARRAY_SIZE(stack_thread); n++) { + canary = &GET_START_CANARY(stack_thread, n); + if (*canary != START_CANARY_VALUE) + CANARY_DIED(stack_thread, start, n, canary); + canary = &GET_END_CANARY(stack_thread, n); + if (*canary != END_CANARY_VALUE) + CANARY_DIED(stack_thread, end, n, canary); + } +#endif +#endif/*CFG_WITH_STACK_CANARIES*/ +} + +void thread_lock_global(void) +{ + cpu_spin_lock(&thread_global_lock); +} + +void thread_unlock_global(void) +{ + cpu_spin_unlock(&thread_global_lock); +} + +static struct thread_core_local * __nostackcheck +get_core_local(unsigned int pos) +{ + /* + * Foreign interrupts must be disabled before playing with core_local + * since we otherwise may be rescheduled to a different core in the + * middle of this function. + */ + assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); + + assert(pos < CFG_TEE_CORE_NB_CORE); + return &thread_core_local[pos]; +} + +struct thread_core_local * __nostackcheck thread_get_core_local(void) +{ + unsigned int pos = get_core_pos(); + + return get_core_local(pos); +} + +#ifdef CFG_CORE_DEBUG_CHECK_STACKS +static void print_stack_limits(void) +{ + size_t n = 0; + vaddr_t __maybe_unused start = 0; + vaddr_t __maybe_unused end = 0; + + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { + start = GET_STACK_TOP_SOFT(stack_tmp, n); + end = GET_STACK_BOTTOM(stack_tmp, n); + DMSG("tmp [%zu] 0x%" PRIxVA "..0x%" PRIxVA, n, start, end); + } + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { + start = GET_STACK_TOP_SOFT(stack_abt, n); + end = GET_STACK_BOTTOM(stack_abt, n); + DMSG("abt [%zu] 0x%" PRIxVA "..0x%" PRIxVA, n, start, end); + } + for (n = 0; n < CFG_NUM_THREADS; n++) { + end = threads[n].stack_va_end; + start = end - STACK_THREAD_SIZE + STACK_CHECK_EXTRA; + DMSG("thr [%zu] 0x%" PRIxVA "..0x%" PRIxVA, n, start, end); + } +} + +static void check_stack_limits(void) +{ + vaddr_t stack_start = 0; + vaddr_t stack_end = 0; + /* Any value in the current stack frame will do */ + vaddr_t current_sp = (vaddr_t)&stack_start; + + if (!get_stack_soft_limits(&stack_start, &stack_end)) + panic("Unknown stack limits"); + if (current_sp < stack_start || current_sp > stack_end) { + EMSG("Stack pointer out of range: 0x%" PRIxVA " not in [0x%" + PRIxVA " .. 0x%" PRIxVA "]", current_sp, stack_start, + stack_end); + print_stack_limits(); + panic(); + } +} + +static bool * __nostackcheck get_stackcheck_recursion_flag(void) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + unsigned int pos = get_core_pos(); + struct thread_core_local *l = get_core_local(pos); + int ct = l->curr_thread; + bool *p = NULL; + + if (l->flags & (THREAD_CLF_ABORT | THREAD_CLF_TMP)) + p = &l->stackcheck_recursion; + else if (!l->flags) + p = &threads[ct].tsd.stackcheck_recursion; + + thread_unmask_exceptions(exceptions); + return p; +} + +void __cyg_profile_func_enter(void *this_fn, void *call_site); +void __nostackcheck __cyg_profile_func_enter(void *this_fn __unused, + void *call_site __unused) +{ + bool *p = get_stackcheck_recursion_flag(); + + assert(p); + if (*p) + return; + *p = true; + check_stack_limits(); + *p = false; +} + +void __cyg_profile_func_exit(void *this_fn, void *call_site); +void __nostackcheck __cyg_profile_func_exit(void *this_fn __unused, + void *call_site __unused) +{ +} +#else +static void print_stack_limits(void) +{ +} +#endif + +void thread_init_boot_thread(void) +{ + struct thread_core_local *l = thread_get_core_local(); + + thread_init_threads(); + + l->curr_thread = 0; + threads[0].state = THREAD_STATE_ACTIVE; +} + +void __nostackcheck thread_clr_boot_thread(void) +{ + struct thread_core_local *l = thread_get_core_local(); + + assert(l->curr_thread >= 0 && l->curr_thread < CFG_NUM_THREADS); + assert(threads[l->curr_thread].state == THREAD_STATE_ACTIVE); + threads[l->curr_thread].state = THREAD_STATE_FREE; + l->curr_thread = THREAD_ID_INVALID; +} + +void __nostackcheck *thread_get_tmp_sp(void) +{ + struct thread_core_local *l = thread_get_core_local(); + + /* + * Called from assembly when switching to the temporary stack, so flags + * need updating + */ + l->flags |= THREAD_CLF_TMP; + + return (void *)l->tmp_stack_va_end; +} + +vaddr_t thread_stack_start(void) +{ + struct thread_ctx *thr; + int ct = thread_get_id_may_fail(); + + if (ct == THREAD_ID_INVALID) + return 0; + + thr = threads + ct; + return thr->stack_va_end - STACK_THREAD_SIZE; +} + +size_t thread_stack_size(void) +{ + return STACK_THREAD_SIZE; +} + +bool get_stack_limits(vaddr_t *start, vaddr_t *end, bool hard) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + unsigned int pos = get_core_pos(); + struct thread_core_local *l = get_core_local(pos); + int ct = l->curr_thread; + bool ret = false; + + if (l->flags & THREAD_CLF_TMP) { + if (hard) + *start = GET_STACK_TOP_HARD(stack_tmp, pos); + else + *start = GET_STACK_TOP_SOFT(stack_tmp, pos); + *end = GET_STACK_BOTTOM(stack_tmp, pos); + ret = true; + } else if (l->flags & THREAD_CLF_ABORT) { + if (hard) + *start = GET_STACK_TOP_HARD(stack_abt, pos); + else + *start = GET_STACK_TOP_SOFT(stack_abt, pos); + *end = GET_STACK_BOTTOM(stack_abt, pos); + ret = true; + } else if (!l->flags) { + if (ct < 0 || ct >= CFG_NUM_THREADS) + goto out; + + *end = threads[ct].stack_va_end; + *start = *end - STACK_THREAD_SIZE; + if (!hard) + *start += STACK_CHECK_EXTRA; + ret = true; + } +out: + thread_unmask_exceptions(exceptions); + return ret; +} + +bool thread_is_from_abort_mode(void) +{ + struct thread_core_local *l = thread_get_core_local(); + + return (l->flags >> THREAD_CLF_SAVED_SHIFT) & THREAD_CLF_ABORT; +} + +/* + * This function should always be accurate, but it might be possible to + * implement a more efficient depending on cpu architecture. + */ +bool __weak thread_is_in_normal_mode(void) +{ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + struct thread_core_local *l = thread_get_core_local(); + bool ret; + + /* + * If any bit in l->flags is set aside from THREAD_CLF_TMP we're + * handling some exception. + */ + ret = (l->curr_thread != THREAD_ID_INVALID) && + !(l->flags & ~THREAD_CLF_TMP); + thread_unmask_exceptions(exceptions); + + return ret; +} + +short int __noprof thread_get_id_may_fail(void) +{ + /* + * thread_get_core_local() requires foreign interrupts to be disabled + */ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + struct thread_core_local *l = thread_get_core_local(); + short int ct = l->curr_thread; + + thread_unmask_exceptions(exceptions); + return ct; +} + +short int __noprof thread_get_id(void) +{ + short int ct = thread_get_id_may_fail(); + + /* Thread ID has to fit in a short int */ + COMPILE_TIME_ASSERT(CFG_NUM_THREADS <= SHRT_MAX); + assert(ct >= 0 && ct < CFG_NUM_THREADS); + return ct; +} + +#ifdef CFG_WITH_PAGER +static void init_thread_stacks(void) +{ + size_t n = 0; + + /* + * Allocate virtual memory for thread stacks. + */ + for (n = 0; n < CFG_NUM_THREADS; n++) { + tee_mm_entry_t *mm = NULL; + vaddr_t sp = 0; + size_t num_pages = 0; + struct fobj *fobj = NULL; + + /* Find vmem for thread stack and its protection gap */ + mm = tee_mm_alloc(&tee_mm_vcore, + SMALL_PAGE_SIZE + STACK_THREAD_SIZE); + assert(mm); + + /* Claim eventual physical page */ + tee_pager_add_pages(tee_mm_get_smem(mm), tee_mm_get_size(mm), + true); + + num_pages = tee_mm_get_bytes(mm) / SMALL_PAGE_SIZE - 1; + fobj = fobj_locked_paged_alloc(num_pages); + + /* Add the region to the pager */ + tee_pager_add_core_region(tee_mm_get_smem(mm) + SMALL_PAGE_SIZE, + PAGED_REGION_TYPE_LOCK, fobj); + fobj_put(fobj); + + /* init effective stack */ + sp = tee_mm_get_smem(mm) + tee_mm_get_bytes(mm); + asan_tag_access((void *)tee_mm_get_smem(mm), (void *)sp); + if (!thread_init_stack(n, sp)) + panic("init stack failed"); + } +} +#else +static void init_thread_stacks(void) +{ + size_t n; + + /* Assign the thread stacks */ + for (n = 0; n < CFG_NUM_THREADS; n++) { + if (!thread_init_stack(n, GET_STACK_BOTTOM(stack_thread, n))) + panic("thread_init_stack failed"); + } +} +#endif /*CFG_WITH_PAGER*/ + +void thread_init_threads(void) +{ + size_t n = 0; + + init_thread_stacks(); + print_stack_limits(); + pgt_init(); + + mutex_lockdep_init(); + + for (n = 0; n < CFG_NUM_THREADS; n++) + TAILQ_INIT(&threads[n].tsd.sess_stack); +} + +void __nostackcheck thread_init_thread_core_local(void) +{ + size_t n = 0; + struct thread_core_local *tcl = thread_core_local; + + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { + tcl[n].curr_thread = THREAD_ID_INVALID; + tcl[n].flags = THREAD_CLF_TMP; + } + tcl[0].tmp_stack_va_end = GET_STACK_BOTTOM(stack_tmp, 0); +} + +void __nostackcheck thread_init_core_local_stacks(void) +{ + size_t n = 0; + struct thread_core_local *tcl = thread_core_local; + + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { + tcl[n].tmp_stack_va_end = GET_STACK_BOTTOM(stack_tmp, n) - + STACK_TMP_OFFS; + tcl[n].abt_stack_va_end = GET_STACK_BOTTOM(stack_abt, n); + } +} + +#if defined(CFG_CORE_PAUTH) +void thread_init_thread_pauth_keys(void) +{ + size_t n = 0; + + for (n = 0; n < CFG_NUM_THREADS; n++) + if (crypto_rng_read(&threads[n].keys, sizeof(threads[n].keys))) + panic("Failed to init thread pauth keys"); +} + +void thread_init_core_local_pauth_keys(void) +{ + struct thread_core_local *tcl = thread_core_local; + size_t n = 0; + + for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) + if (crypto_rng_read(&tcl[n].keys, sizeof(tcl[n].keys))) + panic("Failed to init core local pauth keys"); +} +#endif + +struct thread_specific_data * __noprof thread_get_tsd(void) +{ + return &threads[thread_get_id()].tsd; +} + +struct thread_ctx_regs * __nostackcheck thread_get_ctx_regs(void) +{ + struct thread_core_local *l = thread_get_core_local(); + + assert(l->curr_thread != THREAD_ID_INVALID); + return &threads[l->curr_thread].regs; +} + +void thread_set_foreign_intr(bool enable) +{ + /* thread_get_core_local() requires foreign interrupts to be disabled */ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + struct thread_core_local *l; + + l = thread_get_core_local(); + + assert(l->curr_thread != THREAD_ID_INVALID); + + if (enable) { + threads[l->curr_thread].flags |= + THREAD_FLAGS_FOREIGN_INTR_ENABLE; + thread_set_exceptions(exceptions & ~THREAD_EXCP_FOREIGN_INTR); + } else { + /* + * No need to disable foreign interrupts here since they're + * already disabled above. + */ + threads[l->curr_thread].flags &= + ~THREAD_FLAGS_FOREIGN_INTR_ENABLE; + } +} + +void thread_restore_foreign_intr(void) +{ + /* thread_get_core_local() requires foreign interrupts to be disabled */ + uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); + struct thread_core_local *l; + + l = thread_get_core_local(); + + assert(l->curr_thread != THREAD_ID_INVALID); + + if (threads[l->curr_thread].flags & THREAD_FLAGS_FOREIGN_INTR_ENABLE) + thread_set_exceptions(exceptions & ~THREAD_EXCP_FOREIGN_INTR); +} + +static struct mobj *alloc_shm(enum thread_shm_type shm_type, size_t size) +{ + switch (shm_type) { + case THREAD_SHM_TYPE_APPLICATION: + return thread_rpc_alloc_payload(size); + case THREAD_SHM_TYPE_KERNEL_PRIVATE: + return thread_rpc_alloc_kernel_payload(size); + case THREAD_SHM_TYPE_GLOBAL: + return thread_rpc_alloc_global_payload(size); + default: + return NULL; + } +} + +static void clear_shm_cache_entry(struct thread_shm_cache_entry *ce) +{ + if (ce->mobj) { + switch (ce->type) { + case THREAD_SHM_TYPE_APPLICATION: + thread_rpc_free_payload(ce->mobj); + break; + case THREAD_SHM_TYPE_KERNEL_PRIVATE: + thread_rpc_free_kernel_payload(ce->mobj); + break; + case THREAD_SHM_TYPE_GLOBAL: + thread_rpc_free_global_payload(ce->mobj); + break; + default: + assert(0); /* "can't happen" */ + break; + } + } + ce->mobj = NULL; + ce->size = 0; +} + +static struct thread_shm_cache_entry * +get_shm_cache_entry(enum thread_shm_cache_user user) +{ + struct thread_shm_cache *cache = &threads[thread_get_id()].shm_cache; + struct thread_shm_cache_entry *ce = NULL; + + SLIST_FOREACH(ce, cache, link) + if (ce->user == user) + return ce; + + ce = calloc(1, sizeof(*ce)); + if (ce) { + ce->user = user; + SLIST_INSERT_HEAD(cache, ce, link); + } + + return ce; +} + +void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user, + enum thread_shm_type shm_type, + size_t size, struct mobj **mobj) +{ + struct thread_shm_cache_entry *ce = NULL; + size_t sz = size; + paddr_t p = 0; + void *va = NULL; + + if (!size) + return NULL; + + ce = get_shm_cache_entry(user); + if (!ce) + return NULL; + + /* + * Always allocate in page chunks as normal world allocates payload + * memory as complete pages. + */ + sz = ROUNDUP(size, SMALL_PAGE_SIZE); + + if (ce->type != shm_type || sz > ce->size) { + clear_shm_cache_entry(ce); + + ce->mobj = alloc_shm(shm_type, sz); + if (!ce->mobj) + return NULL; + + if (mobj_get_pa(ce->mobj, 0, 0, &p)) + goto err; + + if (!IS_ALIGNED_WITH_TYPE(p, uint64_t)) + goto err; + + va = mobj_get_va(ce->mobj, 0, sz); + if (!va) + goto err; + + ce->size = sz; + ce->type = shm_type; + } else { + va = mobj_get_va(ce->mobj, 0, sz); + if (!va) + goto err; + } + *mobj = ce->mobj; + + return va; +err: + clear_shm_cache_entry(ce); + return NULL; +} + +void thread_rpc_shm_cache_clear(struct thread_shm_cache *cache) +{ + while (true) { + struct thread_shm_cache_entry *ce = SLIST_FIRST(cache); + + if (!ce) + break; + SLIST_REMOVE_HEAD(cache, link); + clear_shm_cache_entry(ce); + free(ce); + } +} diff --git a/optee/optee_os/core/kernel/tpm.c b/optee/optee_os/core/kernel/tpm.c new file mode 100644 index 0000000..7b0df9e --- /dev/null +++ b/optee/optee_os/core/kernel/tpm.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020-2022, ARM Limited. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +static void *tpm_log_addr; +static size_t tpm_log_size; + +/* + * Check whether the node at @offs contains TPM Event Log information or not. + * + * @offs is the offset of the node that describes the device in @fdt. + * @buf will contain the phy address of the TPM Event log. + * @size will contain the size of the mapped area. + * + * Returns the size of the mapped area or < 0 on failure. + */ +#ifdef CFG_DT +static int read_dt_tpm_log_info(void *fdt, int node, paddr_t *buf, + size_t *size) +{ + const uint32_t *property = NULL; + const uint64_t zero_addr = 0; + int len_prop = 0; + paddr_t log_addr = 0; + int err = 0; +#ifdef CFG_MAP_EXT_DT_SECURE + const char *dt_tpm_event_log_addr = "tpm_event_log_addr"; +#else + const char *dt_tpm_event_log_addr = "tpm_event_log_sm_addr"; +#endif + + /* + * Get the TPM Log address. + */ + property = fdt_getprop(fdt, node, dt_tpm_event_log_addr, &len_prop); + + if (!property || len_prop != sizeof(uint32_t) * 2) + return -1; + + log_addr = fdt32_to_cpu(property[1]); + + err = fdt_setprop(fdt, node, dt_tpm_event_log_addr, &zero_addr, + sizeof(uint32_t) * 2); + if (err < 0) { + EMSG("Error setting property DTB to zero\n"); + return err; + } + + /* + * Get the TPM Log size. + */ + property = fdt_getprop(fdt, node, "tpm_event_log_size", &len_prop); + + if (!property || len_prop != sizeof(uint32_t)) + return -1; + + *size = fdt32_to_cpu(property[0]); + *buf = log_addr; + + return *size; +} +#endif + +static void get_tpm_phys_params(void *fdt __maybe_unused, + paddr_t *addr, size_t *size) +{ +#ifdef CFG_DT + int node = 0; + const char *dt_tpm_match_table = { + "arm,tpm_event_log", + }; + + if (!fdt) { + EMSG("TPM: No DTB found"); + return; + } + + node = fdt_node_offset_by_compatible(fdt, -1, dt_tpm_match_table); + + if (node < 0) { + EMSG("TPM: Fail to find TPM node %i", node); + return; + } + + if (read_dt_tpm_log_info((void *)fdt, node, addr, size) < 0) { + EMSG("TPM: Fail to retrieve DTB properties from node %i", + node); + return; + } +#else + *size = CFG_TPM_MAX_LOG_SIZE; + *addr = CFG_TPM_LOG_BASE_ADDR; +#endif /* CFG_DT */ +} + +TEE_Result tpm_get_event_log(void *buf, size_t *size) +{ + const size_t buf_size = *size; + + *size = tpm_log_size; + if (!buf) { + EMSG("TPM: Invalid buffer"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (buf_size < tpm_log_size) { + EMSG("TPM: Not enough space for the log: %zu, %zu", + buf_size, tpm_log_size); + return TEE_ERROR_SHORT_BUFFER; + } + + memcpy(buf, tpm_log_addr, tpm_log_size); + + return TEE_SUCCESS; +} + +TEE_Result tpm_get_event_log_size(size_t *size) +{ + *size = tpm_log_size; + + return TEE_SUCCESS; +} + +void tpm_map_log_area(void *fdt) +{ + paddr_t log_addr = 0; + unsigned int rounded_size = 0; + + get_tpm_phys_params(fdt, &log_addr, &tpm_log_size); + + DMSG("TPM Event log PA: %#" PRIxPA, log_addr); + DMSG("TPM Event log size: %zu Bytes", tpm_log_size); + + rounded_size = ROUNDUP(tpm_log_size, SMALL_PAGE_SIZE); + + tpm_log_addr = core_mmu_add_mapping(MEM_AREA_RAM_SEC, log_addr, + rounded_size); + if (!tpm_log_addr) { + EMSG("TPM: Failed to map TPM log memory"); + return; + } +} diff --git a/optee/optee_os/core/kernel/trace_ext.c b/optee/optee_os/core/kernel/trace_ext.c new file mode 100644 index 0000000..6ed3bf9 --- /dev/null +++ b/optee/optee_os/core/kernel/trace_ext.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include + +const char trace_ext_prefix[] = "TC"; +int trace_level __nex_data = TRACE_LEVEL; +static unsigned int puts_lock __nex_bss = SPINLOCK_UNLOCK; + +void __weak plat_trace_ext_puts(const char *str __unused) +{ +} + +void trace_ext_puts(const char *str) +{ + uint32_t itr_status = thread_mask_exceptions(THREAD_EXCP_ALL); + bool mmu_enabled = cpu_mmu_enabled(); + bool was_contended = false; + const char *p; + + if (mmu_enabled && !cpu_spin_trylock(&puts_lock)) { + was_contended = true; + cpu_spin_lock_no_dldetect(&puts_lock); + } + + plat_trace_ext_puts(str); + + console_flush(); + + if (was_contended) + console_putc('*'); + + for (p = str; *p; p++) + console_putc(*p); + + console_flush(); + + if (mmu_enabled) + cpu_spin_unlock(&puts_lock); + + thread_unmask_exceptions(itr_status); +} + +int trace_ext_get_thread_id(void) +{ + return thread_get_id_may_fail(); +} + +int trace_ext_get_core_id(void) +{ + /* If foreign interrupts aren't masked we report invalid core ID */ + if (thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR) + return get_core_pos(); + else + return -1; +} diff --git a/optee/optee_os/core/kernel/ts_manager.c b/optee/optee_os/core/kernel/ts_manager.c new file mode 100644 index 0000000..b279463 --- /dev/null +++ b/optee/optee_os/core/kernel/ts_manager.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static void update_current_ctx(struct thread_specific_data *tsd) +{ + struct ts_ctx *ctx = NULL; + struct ts_session *s = TAILQ_FIRST(&tsd->sess_stack); + + if (s) { + if (is_pseudo_ta_ctx(s->ctx)) + s = TAILQ_NEXT(s, link_tsd); + + if (s) + ctx = s->ctx; + } + + if (tsd->ctx != ctx) + vm_set_ctx(ctx); + /* + * If current context is of user mode, then it has to be active too. + */ + if (is_user_mode_ctx(ctx) != core_mmu_user_mapping_is_active()) + panic("unexpected active mapping"); +} + +void ts_push_current_session(struct ts_session *s) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + + TAILQ_INSERT_HEAD(&tsd->sess_stack, s, link_tsd); + update_current_ctx(tsd); +} + +struct ts_session *ts_pop_current_session(void) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + struct ts_session *s = TAILQ_FIRST(&tsd->sess_stack); + + if (s) { + TAILQ_REMOVE(&tsd->sess_stack, s, link_tsd); + update_current_ctx(tsd); + } + return s; +} + +struct ts_session *ts_get_calling_session(void) +{ + return TAILQ_NEXT(ts_get_current_session(), link_tsd); +} + +struct ts_session *ts_get_current_session_may_fail(void) +{ + return TAILQ_FIRST(&thread_get_tsd()->sess_stack); +} + +struct ts_session *ts_get_current_session(void) +{ + struct ts_session *s = ts_get_current_session_may_fail(); + + if (!s) + panic(); + return s; +} diff --git a/optee/optee_os/core/kernel/ubsan.c b/optee/optee_os/core/kernel/ubsan.c new file mode 100644 index 0000000..04b0163 --- /dev/null +++ b/optee/optee_os/core/kernel/ubsan.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include + +struct source_location { + const char *file_name; + uint32_t line; + uint32_t column; +}; + +struct type_descriptor { + uint16_t type_kind; + uint16_t type_info; + char type_name[1]; +}; + +struct type_mismatch_data { + struct source_location loc; + struct type_descriptor *type; + unsigned long alignment; + unsigned char type_check_kind; +}; + +struct overflow_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct shift_out_of_bounds_data { + struct source_location loc; + struct type_descriptor *lhs_type; + struct type_descriptor *rhs_type; +}; + +struct out_of_bounds_data { + struct source_location loc; + struct type_descriptor *array_type; + struct type_descriptor *index_type; +}; + +struct unreachable_data { + struct source_location loc; +}; + +struct vla_bound_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct invalid_value_data { + struct source_location loc; + struct type_descriptor *type; +}; + +struct nonnull_arg_data { + struct source_location loc; +}; + +/* + * When compiling with -fsanitize=undefined the compiler expects functions + * with the following signatures. The functions are never called directly, + * only when undefined behavior is detected in instrumented code. + */ +void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, + unsigned long ptr); +void __ubsan_handle_add_overflow(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_sub_overflow(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_mul_overflow(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_negate_overflow(struct overflow_data *data, + unsigned long old_val); +void __ubsan_handle_divrem_overflow(struct overflow_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, + unsigned long lhs, unsigned long rhs); +void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, + unsigned long idx); +void __ubsan_handle_unreachable(struct unreachable_data *data); +void __ubsan_handle_missing_return(struct unreachable_data *data); +void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, + unsigned long bound); +void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, + unsigned long val); +void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data +#if __GCC_VERSION < 60000 + , size_t arg_no +#endif + ); + +static void print_loc(const char *func, struct source_location *loc) +{ + const char *f = func; + const char func_prefix[] = "__ubsan_handle"; + + if (!memcmp(f, func_prefix, sizeof(func_prefix) - 1)) + f += sizeof(func_prefix); + + EMSG_RAW("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32, + f, loc->file_name, loc->line, loc->column); +} + + +static volatile bool ubsan_panic = true; + +void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, + unsigned long ptr __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_add_overflow(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_sub_overflow(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_mul_overflow(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_negate_overflow(struct overflow_data *data, + unsigned long old_val __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_divrem_overflow(struct overflow_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, + unsigned long lhs __unused, + unsigned long rhs __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, + unsigned long idx __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_unreachable(struct unreachable_data *data) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __noreturn __ubsan_handle_missing_return(struct unreachable_data *data) +{ + print_loc(__func__, &data->loc); + panic(); +} + +void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, + unsigned long bound __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, + unsigned long val __unused) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} + +void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data +#if __GCC_VERSION < 60000 + , size_t arg_no __unused +#endif + ) +{ + print_loc(__func__, &data->loc); + if (ubsan_panic) + panic(); +} diff --git a/optee/optee_os/core/kernel/user_access.c b/optee/optee_os/core/kernel/user_access.c new file mode 100644 index 0000000..fb30a80 --- /dev/null +++ b/optee/optee_os/core/kernel/user_access.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015-2020, 2022 Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result check_access(uint32_t flags, const void *uaddr, size_t len) +{ + struct ts_session *s = ts_get_current_session(); + + return vm_check_access_rights(to_user_mode_ctx(s->ctx), flags, + (vaddr_t)uaddr, len); +} + +TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len) +{ + uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; + TEE_Result res = TEE_SUCCESS; + + uaddr = memtag_strip_tag_const(uaddr); + res = check_access(flags, uaddr, len); + if (!res) + memcpy(kaddr, uaddr, len); + + return res; +} + +TEE_Result copy_to_user(void *uaddr, const void *kaddr, size_t len) +{ + uint32_t flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; + TEE_Result res = TEE_SUCCESS; + + uaddr = memtag_strip_tag(uaddr); + res = check_access(flags, uaddr, len); + if (!res) + memcpy(uaddr, kaddr, len); + + return res; +} + +TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len) +{ + uint32_t flags = TEE_MEMORY_ACCESS_READ; + TEE_Result res = TEE_SUCCESS; + + uaddr = memtag_strip_tag_const(uaddr); + res = check_access(flags, uaddr, len); + if (!res) + memcpy(kaddr, uaddr, len); + + return res; +} + +TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len) +{ + uint32_t flags = TEE_MEMORY_ACCESS_WRITE; + TEE_Result res = TEE_SUCCESS; + + uaddr = memtag_strip_tag(uaddr); + res = check_access(flags, uaddr, len); + if (!res) + memcpy(uaddr, kaddr, len); + + return res; +} + +TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr) +{ + uint32_t ref = kaddr_to_uref(kaddr); + + return copy_to_user_private(uref, &ref, sizeof(ref)); +} + +uint32_t kaddr_to_uref(void *kaddr) +{ + if (MEMTAG_IS_ENABLED) { + unsigned int uref_tag_shift = 32 - MEMTAG_TAG_WIDTH; + vaddr_t uref = memtag_strip_tag_vaddr(kaddr); + + uref -= VCORE_START_VA; + assert(uref < (UINT32_MAX >> MEMTAG_TAG_WIDTH)); + uref |= memtag_get_tag(kaddr) << uref_tag_shift; + return uref; + } + + assert(((vaddr_t)kaddr - VCORE_START_VA) < UINT32_MAX); + return (vaddr_t)kaddr - VCORE_START_VA; +} + +vaddr_t uref_to_vaddr(uint32_t uref) +{ + if (MEMTAG_IS_ENABLED) { + vaddr_t u = uref & (UINT32_MAX >> MEMTAG_TAG_WIDTH); + unsigned int uref_tag_shift = 32 - MEMTAG_TAG_WIDTH; + uint8_t tag = uref >> uref_tag_shift; + + return memtag_insert_tag_vaddr(VCORE_START_VA + u, tag); + } + + return VCORE_START_VA + uref; +} diff --git a/optee/optee_os/core/kernel/user_mode_ctx.c b/optee/optee_os/core/kernel/user_mode_ctx.c new file mode 100644 index 0000000..12906f3 --- /dev/null +++ b/optee/optee_os/core/kernel/user_mode_ctx.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include + +void user_mode_ctx_print_mappings(struct user_mode_ctx *uctx) +{ + struct vm_region *r = NULL; + char flags[7] = { '\0', }; + size_t n = 0; + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { + paddr_t pa = 0; + + if (r->mobj) + mobj_get_pa(r->mobj, r->offset, 0, &pa); + + mattr_perm_to_str(flags, sizeof(flags), r->attr); + EMSG_RAW(" region %2zu: va 0x%0*" PRIxVA " pa 0x%0*" PRIxPA + " size 0x%06zx flags %s", + n, PRIxVA_WIDTH, r->va, PRIxPA_WIDTH, pa, r->size, + flags); + n++; + } +} diff --git a/optee/optee_os/core/kernel/user_ta.c b/optee/optee_os/core/kernel/user_ta.c new file mode 100644 index 0000000..720c067 --- /dev/null +++ b/optee/optee_os/core/kernel/user_ta.c @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015-2022 Linaro Limited + * Copyright (c) 2020, Arm Limited. + */ + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void init_utee_param(struct utee_params *up, + const struct tee_ta_param *p, void *va[TEE_NUM_PARAMS]) +{ + size_t n; + + up->types = p->types; + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uintptr_t a; + uintptr_t b; + + switch (TEE_PARAM_TYPE_GET(p->types, n)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + a = (uintptr_t)va[n]; + b = p->u[n].mem.size; + break; + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + a = p->u[n].val.a; + b = p->u[n].val.b; + break; + default: + a = 0; + b = 0; + break; + } + /* See comment for struct utee_params in utee_types.h */ + up->vals[n * 2] = a; + up->vals[n * 2 + 1] = b; + } +} + +static void update_from_utee_param(struct tee_ta_param *p, + const struct utee_params *up) +{ + size_t n; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(p->types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + /* See comment for struct utee_params in utee_types.h */ + p->u[n].mem.size = up->vals[n * 2 + 1]; + break; + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + /* See comment for struct utee_params in utee_types.h */ + p->u[n].val.a = up->vals[n * 2]; + p->u[n].val.b = up->vals[n * 2 + 1]; + break; + default: + break; + } + } +} + +static bool inc_recursion(void) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + + if (tsd->syscall_recursion >= CFG_CORE_MAX_SYSCALL_RECURSION) { + DMSG("Maximum allowed recursion depth reached (%u)", + CFG_CORE_MAX_SYSCALL_RECURSION); + return false; + } + + tsd->syscall_recursion++; + return true; +} + +static void dec_recursion(void) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + + assert(tsd->syscall_recursion); + tsd->syscall_recursion--; +} + +static TEE_Result user_ta_enter(struct ts_session *session, + enum utee_entry_func func, uint32_t cmd) +{ + TEE_Result res = TEE_SUCCESS; + struct utee_params *usr_params = NULL; + uaddr_t usr_stack = 0; + struct user_ta_ctx *utc = to_user_ta_ctx(session->ctx); + struct tee_ta_session *ta_sess = to_ta_session(session); + struct ts_session *ts_sess __maybe_unused = NULL; + void *param_va[TEE_NUM_PARAMS] = { NULL }; + + if (!inc_recursion()) { + /* Using this error code since we've run out of resources. */ + res = TEE_ERROR_OUT_OF_MEMORY; + goto out_clr_cancel; + } + if (ta_sess->param) { + /* Map user space memory */ + res = vm_map_param(&utc->uctx, ta_sess->param, param_va); + if (res != TEE_SUCCESS) + goto out; + } + + /* Switch to user ctx */ + ts_push_current_session(session); + + /* Make room for usr_params at top of stack */ + usr_stack = utc->uctx.stack_ptr; + usr_stack -= ROUNDUP(sizeof(struct utee_params), STACK_ALIGNMENT); + usr_params = (struct utee_params *)usr_stack; + if (ta_sess->param) + init_utee_param(usr_params, ta_sess->param, param_va); + else + memset(usr_params, 0, sizeof(*usr_params)); + + res = thread_enter_user_mode(func, kaddr_to_uref(session), + (vaddr_t)usr_params, cmd, usr_stack, + utc->uctx.entry_func, utc->uctx.is_32bit, + &utc->ta_ctx.panicked, + &utc->ta_ctx.panic_code); + + thread_user_clear_vfp(&utc->uctx); + + if (utc->ta_ctx.panicked) { + abort_print_current_ts(); + DMSG("tee_user_ta_enter: TA panicked with code 0x%x", + utc->ta_ctx.panic_code); + res = TEE_ERROR_TARGET_DEAD; + } else { + /* + * According to GP spec the origin should allways be set to + * the TA after TA execution + */ + ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; + } + + if (ta_sess->param) { + /* Copy out value results */ + update_from_utee_param(ta_sess->param, usr_params); + + /* + * Clear out the parameter mappings added with + * vm_clean_param() above. + */ + vm_clean_param(&utc->uctx); + } + + + ts_sess = ts_pop_current_session(); + assert(ts_sess == session); + +out: + dec_recursion(); +out_clr_cancel: + /* + * 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. + */ + ta_sess->cancel = false; + + return res; +} + +static TEE_Result user_ta_enter_open_session(struct ts_session *s) +{ + return user_ta_enter(s, UTEE_ENTRY_FUNC_OPEN_SESSION, 0); +} + +static TEE_Result user_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) +{ + return user_ta_enter(s, UTEE_ENTRY_FUNC_INVOKE_COMMAND, cmd); +} + +static void user_ta_enter_close_session(struct ts_session *s) +{ + /* Only if the TA was fully initialized by ldelf */ + if (!to_user_ta_ctx(s->ctx)->uctx.is_initializing) + user_ta_enter(s, UTEE_ENTRY_FUNC_CLOSE_SESSION, 0); +} + +#if defined(CFG_TA_STATS) +static TEE_Result user_ta_enter_dump_memstats(struct ts_session *s) +{ + return user_ta_enter(s, UTEE_ENTRY_FUNC_DUMP_MEMSTATS, 0); +} +#endif + +static void dump_state_no_ldelf_dbg(struct user_ta_ctx *utc) +{ + user_mode_ctx_print_mappings(&utc->uctx); +} + +static void user_ta_dump_state(struct ts_ctx *ctx) +{ + struct user_ta_ctx *utc = to_user_ta_ctx(ctx); + + if (utc->uctx.dump_entry_func) { + TEE_Result res = ldelf_dump_state(&utc->uctx); + + if (!res || res == TEE_ERROR_TARGET_DEAD) + return; + /* + * Fall back to dump_state_no_ldelf_dbg() if + * ldelf_dump_state() fails for some reason. + * + * If ldelf_dump_state() failed with panic + * we are done since abort_print_current_ts() will be + * called which will dump the memory map. + */ + } + + dump_state_no_ldelf_dbg(utc); +} + +#ifdef CFG_FTRACE_SUPPORT +static void user_ta_dump_ftrace(struct ts_ctx *ctx) +{ + uint32_t prot = TEE_MATTR_URW; + struct user_ta_ctx *utc = to_user_ta_ctx(ctx); + struct thread_param params[3] = { }; + TEE_Result res = TEE_SUCCESS; + struct mobj *mobj = NULL; + uint8_t *ubuf = NULL; + void *buf = NULL; + size_t pl_sz = 0; + size_t blen = 0, ld_addr_len = 0; + vaddr_t va = 0; + + res = ldelf_dump_ftrace(&utc->uctx, NULL, &blen); + if (res != TEE_ERROR_SHORT_BUFFER) + return; + +#define LOAD_ADDR_DUMP_SIZE 64 + pl_sz = ROUNDUP(blen + sizeof(TEE_UUID) + LOAD_ADDR_DUMP_SIZE, + SMALL_PAGE_SIZE); + + mobj = thread_rpc_alloc_payload(pl_sz); + if (!mobj) { + EMSG("Ftrace thread_rpc_alloc_payload failed"); + return; + } + + buf = mobj_get_va(mobj, 0, pl_sz); + if (!buf) + goto out_free_pl; + + res = vm_map(&utc->uctx, &va, mobj->size, prot, VM_FLAG_EPHEMERAL, + mobj, 0); + if (res) + goto out_free_pl; + + ubuf = (uint8_t *)va + mobj_get_phys_offs(mobj, mobj->phys_granule); + memcpy(ubuf, &ctx->uuid, sizeof(TEE_UUID)); + ubuf += sizeof(TEE_UUID); + + ld_addr_len = snprintk((char *)ubuf, LOAD_ADDR_DUMP_SIZE, + "TEE load address @ %#"PRIxVA"\n", + VCORE_START_VA); + ubuf += ld_addr_len; + + res = ldelf_dump_ftrace(&utc->uctx, ubuf, &blen); + if (res) { + EMSG("Ftrace dump failed: %#"PRIx32, res); + goto out_unmap_pl; + } + + params[0] = THREAD_PARAM_VALUE(INOUT, 0, 0, 0); + params[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, sizeof(TEE_UUID)); + params[2] = THREAD_PARAM_MEMREF(IN, mobj, sizeof(TEE_UUID), + blen + ld_addr_len); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_FTRACE, 3, params); + if (res) + EMSG("Ftrace thread_rpc_cmd res: %#"PRIx32, res); + +out_unmap_pl: + res = vm_unmap(&utc->uctx, va, mobj->size); + assert(!res); +out_free_pl: + thread_rpc_free_payload(mobj); +} +#endif /*CFG_FTRACE_SUPPORT*/ + +#ifdef CFG_TA_GPROF_SUPPORT +static void user_ta_gprof_set_status(enum ts_gprof_status status) +{ + if (status == TS_GPROF_SUSPEND) + tee_ta_update_session_utime_suspend(); + else + tee_ta_update_session_utime_resume(); +} +#endif /*CFG_TA_GPROF_SUPPORT*/ + +static void free_utc(struct user_ta_ctx *utc) +{ + + /* + * Close sessions opened by this TA + * Note that tee_ta_close_session() removes the item + * from the utc->open_sessions list. + */ + while (!TAILQ_EMPTY(&utc->open_sessions)) { + tee_ta_close_session(TAILQ_FIRST(&utc->open_sessions), + &utc->open_sessions, KERN_IDENTITY); + } + + vm_info_final(&utc->uctx); + + /* Free cryp states created by this TA */ + tee_svc_cryp_free_states(utc); + /* Close cryp objects opened by this TA */ + tee_obj_close_all(utc); + /* Free emums created by this TA */ + tee_svc_storage_close_all_enum(utc); + free(utc); +} + +static void user_ta_ctx_destroy(struct ts_ctx *ctx) +{ + free_utc(to_user_ta_ctx(ctx)); +} + +static uint32_t user_ta_get_instance_id(struct ts_ctx *ctx) +{ + return to_user_ta_ctx(ctx)->uctx.vm_info.asid; +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct ts_ops user_ta_ops __weak __relrodata_unpaged("user_ta_ops") = { + .enter_open_session = user_ta_enter_open_session, + .enter_invoke_cmd = user_ta_enter_invoke_cmd, + .enter_close_session = user_ta_enter_close_session, +#if defined(CFG_TA_STATS) + .dump_mem_stats = user_ta_enter_dump_memstats, +#endif + .dump_state = user_ta_dump_state, +#ifdef CFG_FTRACE_SUPPORT + .dump_ftrace = user_ta_dump_ftrace, +#endif + .destroy = user_ta_ctx_destroy, + .get_instance_id = user_ta_get_instance_id, + .handle_scall = scall_handle_user_ta, +#ifdef CFG_TA_GPROF_SUPPORT + .gprof_set_status = user_ta_gprof_set_status, +#endif +}; + +static void set_ta_ctx_ops(struct tee_ta_ctx *ctx) +{ + ctx->ts_ctx.ops = &user_ta_ops; +} + +bool is_user_ta_ctx(struct ts_ctx *ctx) +{ + return ctx && ctx->ops == &user_ta_ops; +} + +static TEE_Result check_ta_store(void) +{ + const struct ts_store_ops *op = NULL; + + SCATTERED_ARRAY_FOREACH(op, ta_stores, struct ts_store_ops) + DMSG("TA store: \"%s\"", op->description); + + return TEE_SUCCESS; +} +service_init(check_ta_store); + +TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid, + struct tee_ta_session *s) +{ + TEE_Result res = TEE_SUCCESS; + struct user_ta_ctx *utc = NULL; + + utc = calloc(1, sizeof(struct user_ta_ctx)); + if (!utc) + return TEE_ERROR_OUT_OF_MEMORY; + + TAILQ_INIT(&utc->open_sessions); + TAILQ_INIT(&utc->cryp_states); + TAILQ_INIT(&utc->objects); + TAILQ_INIT(&utc->storage_enums); + condvar_init(&utc->ta_ctx.busy_cv); + utc->ta_ctx.ref_count = 1; + + /* + * Set context TA operation structure. It is required by generic + * implementation to identify userland TA versus pseudo TA contexts. + */ + set_ta_ctx_ops(&utc->ta_ctx); + + utc->ta_ctx.ts_ctx.uuid = *uuid; + res = vm_info_init(&utc->uctx, &utc->ta_ctx.ts_ctx); + if (res) + goto out; + utc->uctx.is_initializing = true; + +#ifdef CFG_TA_PAUTH + crypto_rng_read(&utc->uctx.keys, sizeof(utc->uctx.keys)); +#endif + + mutex_lock(&tee_ta_mutex); + s->ts_sess.ctx = &utc->ta_ctx.ts_ctx; + s->ts_sess.handle_scall = s->ts_sess.ctx->ops->handle_scall; + /* + * Another thread trying to load this same TA may need to wait + * until this context is fully initialized. This is needed to + * handle single instance TAs. + */ + TAILQ_INSERT_TAIL(&tee_ctxes, &utc->ta_ctx, link); + mutex_unlock(&tee_ta_mutex); + + /* + * We must not hold tee_ta_mutex while allocating page tables as + * that may otherwise lead to a deadlock. + */ + ts_push_current_session(&s->ts_sess); + + res = ldelf_load_ldelf(&utc->uctx); + if (!res) + res = ldelf_init_with_ldelf(&s->ts_sess, &utc->uctx); + + ts_pop_current_session(); + + mutex_lock(&tee_ta_mutex); + + if (!res) { + utc->uctx.is_initializing = false; + } else { + s->ts_sess.ctx = NULL; + TAILQ_REMOVE(&tee_ctxes, &utc->ta_ctx, link); + } + + /* The state has changed for the context, notify eventual waiters. */ + condvar_broadcast(&tee_ta_init_cv); + + mutex_unlock(&tee_ta_mutex); + +out: + if (res) { + condvar_destroy(&utc->ta_ctx.busy_cv); + free_utc(utc); + } + + return res; +} diff --git a/optee/optee_os/core/kernel/wait_queue.c b/optee/optee_os/core/kernel/wait_queue.c new file mode 100644 index 0000000..1326ef8 --- /dev/null +++ b/optee/optee_os/core/kernel/wait_queue.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2021, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned wq_spin_lock; + + +void wq_init(struct wait_queue *wq) +{ + *wq = (struct wait_queue)WAIT_QUEUE_INITIALIZER; +} + +static void do_notif(TEE_Result (*fn)(uint32_t), int id, + const char *cmd_str __maybe_unused, + const void *sync_obj __maybe_unused, + const char *fname, int lineno __maybe_unused) +{ + TEE_Result res = TEE_SUCCESS; + + if (fname) + DMSG("%s thread %d %p %s:%d", cmd_str, id, + sync_obj, fname, lineno); + else + DMSG("%s thread %d %p", cmd_str, id, sync_obj); + + res = fn(id + NOTIF_SYNC_VALUE_BASE); + if (res) + DMSG("%s thread %d res %#"PRIx32, cmd_str, id, res); +} + +static void slist_add_tail(struct wait_queue *wq, struct wait_queue_elem *wqe) +{ + struct wait_queue_elem *wqe_iter; + + /* Add elem to end of wait queue */ + wqe_iter = SLIST_FIRST(wq); + if (wqe_iter) { + while (SLIST_NEXT(wqe_iter, link)) + wqe_iter = SLIST_NEXT(wqe_iter, link); + SLIST_INSERT_AFTER(wqe_iter, wqe, link); + } else + SLIST_INSERT_HEAD(wq, wqe, link); +} + +void wq_wait_init_condvar(struct wait_queue *wq, struct wait_queue_elem *wqe, + struct condvar *cv, bool wait_read) +{ + uint32_t old_itr_status; + + wqe->handle = thread_get_id(); + wqe->done = false; + wqe->wait_read = wait_read; + wqe->cv = cv; + + old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); + + slist_add_tail(wq, wqe); + + cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); +} + +void wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe, + const void *sync_obj, const char *fname, int lineno) +{ + uint32_t old_itr_status; + unsigned done; + + do { + do_notif(notif_wait, wqe->handle, + "sleep", sync_obj, fname, lineno); + + old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); + + done = wqe->done; + if (done) + SLIST_REMOVE(wq, wqe, wait_queue_elem, link); + + cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); + } while (!done); +} + +void wq_wake_next(struct wait_queue *wq, const void *sync_obj, + const char *fname, int lineno) +{ + uint32_t old_itr_status; + struct wait_queue_elem *wqe; + int handle = -1; + bool do_wakeup = false; + bool wake_type_assigned = false; + bool wake_read = false; /* avoid gcc warning */ + + /* + * If next type is wait_read wakeup all wqe with wait_read true. + * If next type isn't wait_read wakeup only the first wqe which isn't + * done. + */ + + while (true) { + old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); + + SLIST_FOREACH(wqe, wq, link) { + if (wqe->cv) + continue; + if (wqe->done) + continue; + if (!wake_type_assigned) { + wake_read = wqe->wait_read; + wake_type_assigned = true; + } + + if (wqe->wait_read != wake_read) + continue; + + wqe->done = true; + handle = wqe->handle; + do_wakeup = true; + break; + } + + cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); + + if (do_wakeup) + do_notif(notif_send_sync, handle, + "wake ", sync_obj, fname, lineno); + + if (!do_wakeup || !wake_read) + break; + do_wakeup = false; + } +} + +void wq_promote_condvar(struct wait_queue *wq, struct condvar *cv, + bool only_one, const void *sync_obj __unused, + const char *fname, int lineno __maybe_unused) +{ + uint32_t old_itr_status; + struct wait_queue_elem *wqe; + + if (!cv) + return; + + old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); + + /* + * Find condvar waiter(s) and promote each to an active waiter. + * This is a bit unfair to eventual other active waiters as a + * condvar waiter is added to the queue when waiting for the + * condvar. + */ + SLIST_FOREACH(wqe, wq, link) { + if (wqe->cv == cv) { + if (fname) + FMSG("promote thread %u %p %s:%d", + wqe->handle, (void *)cv->m, fname, lineno); + else + FMSG("promote thread %u %p", + wqe->handle, (void *)cv->m); + + wqe->cv = NULL; + if (only_one) + break; + } + } + + cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); +} + +bool wq_have_condvar(struct wait_queue *wq, struct condvar *cv) +{ + uint32_t old_itr_status; + struct wait_queue_elem *wqe; + bool rc = false; + + old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); + + SLIST_FOREACH(wqe, wq, link) { + if (wqe->cv == cv) { + rc = true; + break; + } + } + + cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); + + return rc; +} + +bool wq_is_empty(struct wait_queue *wq) +{ + uint32_t old_itr_status; + bool ret; + + old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); + + ret = SLIST_EMPTY(wq); + + cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); + + return ret; +} diff --git a/optee/optee_os/core/lib/libfdt/README.license b/optee/optee_os/core/lib/libfdt/README.license new file mode 100644 index 0000000..102b004 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/README.license @@ -0,0 +1,56 @@ +Licensing and contribution policy of dtc and libfdt +=================================================== + +This dtc package contains two pieces of software: dtc itself, and +libfdt which comprises the files in the libfdt/ subdirectory. These +two pieces of software, although closely related, are quite distinct. +dtc does not incorporate or rely on libfdt for its operation, nor vice +versa. It is important that these two pieces of software have +different license conditions. + +As SPDX license tags in each source file attest, dtc is licensed +under the GNU GPL. The full text of the GPL can be found in the file +entitled 'GPL' which should be included in this package. dtc code, +therefore, may not be incorporated into works which do not have a GPL +compatible license. + +libfdt, however, is GPL/BSD dual-licensed. That is, it may be used +either under the terms of the GPL, or under the terms of the 2-clause +BSD license (aka the ISC license). The full terms of that license can +be found are in the file entitled 'BSD-2-Clause'. This is, in +practice, equivalent to being BSD licensed, since the terms of the BSD +license are strictly more permissive than the GPL. + +I made the decision to license libfdt in this way because I want to +encourage widespread and correct usage of flattened device trees, +including by proprietary or otherwise GPL-incompatible firmware or +tools. Allowing libfdt to be used under the terms of the BSD license +makes that it easier for vendors or authors of such software to do so. + +This does mean that libfdt code could be "stolen" - say, included in a +proprietary fimware and extended without contributing those extensions +back to the libfdt mainline. While I hope that doesn't happen, I +believe the goal of allowing libfdt to be widely used is more +important than avoiding that. libfdt is quite small, and hardly +rocket science; so the incentive for such impolite behaviour is small, +and the inconvenience caused thereby is not dire. + +Licenses such as the LGPL which would allow code to be used in non-GPL +software, but also require contributions to be returned were +considered. However, libfdt is designed to be used in firmwares and +other environments with unusual technical constraints. It's difficult +to anticipate all possible changes which might be needed to meld +libfdt into such environments and so difficult to suitably word a +license that puts the boundary between what is and isn't permitted in +the intended place. Again, I judged encouraging widespread use of +libfdt by keeping the license terms simple and familiar to be the more +important goal. + +**IMPORTANT** It's intended that all of libfdt as released remain +permissively licensed this way. Therefore only contributions which +are released under these terms can be merged into the libfdt mainline. + + +David Gibson +(principal original author of dtc and libfdt) +2 November 2007 diff --git a/optee/optee_os/core/lib/libfdt/fdt.c b/optee/optee_os/core/lib/libfdt/fdt.c new file mode 100644 index 0000000..d6ce7c0 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +/* + * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks + * that the given buffer contains what appears to be a flattened + * device tree with sane information in its header. + */ +int32_t fdt_ro_probe_(const void *fdt) +{ + uint32_t totalsize = fdt_totalsize(fdt); + + if (fdt_magic(fdt) == FDT_MAGIC) { + /* Complete tree */ + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + /* Unfinished sequential-write blob */ + if (fdt_size_dt_struct(fdt) == 0) + return -FDT_ERR_BADSTATE; + } else { + return -FDT_ERR_BADMAGIC; + } + + if (totalsize < INT32_MAX) + return totalsize; + else + return -FDT_ERR_TRUNCATED; +} + +static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) +{ + return (off >= hdrsize) && (off <= totalsize); +} + +static int check_block_(uint32_t hdrsize, uint32_t totalsize, + uint32_t base, uint32_t size) +{ + if (!check_off_(hdrsize, totalsize, base)) + return 0; /* block start out of bounds */ + if ((base + size) < base) + return 0; /* overflow */ + if (!check_off_(hdrsize, totalsize, base + size)) + return 0; /* block end out of bounds */ + return 1; +} + +size_t fdt_header_size_(uint32_t version) +{ + if (version <= 1) + return FDT_V1_SIZE; + else if (version <= 2) + return FDT_V2_SIZE; + else if (version <= 3) + return FDT_V3_SIZE; + else if (version <= 16) + return FDT_V16_SIZE; + else + return FDT_V17_SIZE; +} + +int fdt_check_header(const void *fdt) +{ + size_t hdrsize; + + if (fdt_magic(fdt) != FDT_MAGIC) + return -FDT_ERR_BADMAGIC; + hdrsize = fdt_header_size(fdt); + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)) + return -FDT_ERR_BADVERSION; + if (fdt_version(fdt) < fdt_last_comp_version(fdt)) + return -FDT_ERR_BADVERSION; + + if ((fdt_totalsize(fdt) < hdrsize) + || (fdt_totalsize(fdt) > INT_MAX)) + return -FDT_ERR_TRUNCATED; + + /* Bounds check memrsv block */ + if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) + return -FDT_ERR_TRUNCATED; + + /* Bounds check structure block */ + if (fdt_version(fdt) < 17) { + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } else { + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } + + /* Bounds check strings block */ + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt))) + return -FDT_ERR_TRUNCATED; + + return 0; +} + +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) +{ + unsigned absoffset = offset + fdt_off_dt_struct(fdt); + + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; + + if (fdt_version(fdt) >= 0x11) + if (((offset + len) < offset) + || ((offset + len) > fdt_size_dt_struct(fdt))) + return NULL; + + return fdt_offset_ptr_(fdt, offset); +} + +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) +{ + const fdt32_t *tagp, *lenp; + uint32_t tag; + int offset = startoffset; + const char *p; + + *nextoffset = -FDT_ERR_TRUNCATED; + tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); + if (!tagp) + return FDT_END; /* premature end */ + tag = fdt32_to_cpu(*tagp); + offset += FDT_TAGSIZE; + + *nextoffset = -FDT_ERR_BADSTRUCTURE; + switch (tag) { + case FDT_BEGIN_NODE: + /* skip name */ + do { + p = fdt_offset_ptr(fdt, offset++, 1); + } while (p && (*p != '\0')); + if (!p) + return FDT_END; /* premature end */ + break; + + case FDT_PROP: + lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); + if (!lenp) + return FDT_END; /* premature end */ + /* skip-name offset, length and value */ + offset += sizeof(struct fdt_property) - FDT_TAGSIZE + + fdt32_to_cpu(*lenp); + if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && + ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) + offset += 4; + break; + + case FDT_END: + case FDT_END_NODE: + case FDT_NOP: + break; + + default: + return FDT_END; + } + + if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) + return FDT_END; /* premature end */ + + *nextoffset = FDT_TAGALIGN(offset); + return tag; +} + +int fdt_check_node_offset_(const void *fdt, int offset) +{ + if ((offset < 0) || (offset % FDT_TAGSIZE) + || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int fdt_check_prop_offset_(const void *fdt, int offset) +{ + if ((offset < 0) || (offset % FDT_TAGSIZE) + || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int fdt_next_node(const void *fdt, int offset, int *depth) +{ + int nextoffset = 0; + uint32_t tag; + + if (offset >= 0) + if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0) + return nextoffset; + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_PROP: + case FDT_NOP: + break; + + case FDT_BEGIN_NODE: + if (depth) + (*depth)++; + break; + + case FDT_END_NODE: + if (depth && ((--(*depth)) < 0)) + return nextoffset; + break; + + case FDT_END: + if ((nextoffset >= 0) + || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) + return -FDT_ERR_NOTFOUND; + else + return nextoffset; + } + } while (tag != FDT_BEGIN_NODE); + + return offset; +} + +int fdt_first_subnode(const void *fdt, int offset) +{ + int depth = 0; + + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth != 1) + return -FDT_ERR_NOTFOUND; + + return offset; +} + +int fdt_next_subnode(const void *fdt, int offset) +{ + int depth = 1; + + /* + * With respect to the parent, the depth of the next subnode will be + * the same as the last. + */ + do { + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth < 1) + return -FDT_ERR_NOTFOUND; + } while (depth > 1); + + return offset; +} + +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) +{ + int len = strlen(s) + 1; + const char *last = strtab + tabsize - len; + const char *p; + + for (p = strtab; p <= last; p++) + if (memcmp(p, s, len) == 0) + return p; + return NULL; +} + +int fdt_move(const void *fdt, void *buf, int bufsize) +{ + FDT_RO_PROBE(fdt); + + if (fdt_totalsize(fdt) > bufsize) + return -FDT_ERR_NOSPACE; + + memmove(buf, fdt, fdt_totalsize(fdt)); + return 0; +} diff --git a/optee/optee_os/core/lib/libfdt/fdt_addresses.c b/optee/optee_os/core/lib/libfdt/fdt_addresses.c new file mode 100644 index 0000000..9a82cd0 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt_addresses.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2014 David Gibson + * Copyright (C) 2018 embedded brains GmbH + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_cells(const void *fdt, int nodeoffset, const char *name) +{ + const fdt32_t *c; + uint32_t val; + int len; + + c = fdt_getprop(fdt, nodeoffset, name, &len); + if (!c) + return len; + + if (len != sizeof(*c)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*c); + if (val > FDT_MAX_NCELLS) + return -FDT_ERR_BADNCELLS; + + return (int)val; +} + +int fdt_address_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == 0) + return -FDT_ERR_BADNCELLS; + if (val == -FDT_ERR_NOTFOUND) + return 2; + return val; +} + +int fdt_size_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#size-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 1; + return val; +} + +/* This function assumes that [address|size]_cells is 1 or 2 */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size) +{ + int addr_cells, size_cells, ret; + uint8_t data[sizeof(fdt64_t) * 2], *prop; + + ret = fdt_address_cells(fdt, parent); + if (ret < 0) + return ret; + addr_cells = ret; + + ret = fdt_size_cells(fdt, parent); + if (ret < 0) + return ret; + size_cells = ret; + + /* check validity of address */ + prop = data; + if (addr_cells == 1) { + if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)addr); + } else if (addr_cells == 2) { + fdt64_st(prop, addr); + } else { + return -FDT_ERR_BADNCELLS; + } + + /* check validity of size */ + prop += addr_cells * sizeof(fdt32_t); + if (size_cells == 1) { + if (size > UINT32_MAX) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)size); + } else if (size_cells == 2) { + fdt64_st(prop, size); + } else { + return -FDT_ERR_BADNCELLS; + } + + return fdt_appendprop(fdt, nodeoffset, name, data, + (addr_cells + size_cells) * sizeof(fdt32_t)); +} diff --git a/optee/optee_os/core/lib/libfdt/fdt_empty_tree.c b/optee/optee_os/core/lib/libfdt/fdt_empty_tree.c new file mode 100644 index 0000000..49d54d4 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt_empty_tree.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2012 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_create_empty_tree(void *buf, int bufsize) +{ + int err; + + err = fdt_create(buf, bufsize); + if (err) + return err; + + err = fdt_finish_reservemap(buf); + if (err) + return err; + + err = fdt_begin_node(buf, ""); + if (err) + return err; + + err = fdt_end_node(buf); + if (err) + return err; + + err = fdt_finish(buf); + if (err) + return err; + + return fdt_open_into(buf, buf, bufsize); +} diff --git a/optee/optee_os/core/lib/libfdt/fdt_overlay.c b/optee/optee_os/core/lib/libfdt/fdt_overlay.c new file mode 100644 index 0000000..e74fe92 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt_overlay.c @@ -0,0 +1,881 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2016 Free Electrons + * Copyright (C) 2016 NextThing Co. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +/** + * overlay_get_target_phandle - retrieves the target phandle of a fragment + * @fdto: pointer to the device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * + * overlay_get_target_phandle() retrieves the target phandle of an + * overlay fragment when that fragment uses a phandle (target + * property) instead of a path (target-path property). + * + * returns: + * the phandle pointed by the target property + * 0, if the phandle was not found + * -1, if the phandle was malformed + */ +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) +{ + const fdt32_t *val; + int len; + + val = fdt_getprop(fdto, fragment, "target", &len); + if (!val) + return 0; + + if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) + return (uint32_t)-1; + + return fdt32_to_cpu(*val); +} + +/** + * overlay_get_target - retrieves the offset of a fragment's target + * @fdt: Base device tree blob + * @fdto: Device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL) + * + * overlay_get_target() retrieves the target offset in the base + * device tree of a fragment, no matter how the actual targeting is + * done (through a phandle or a path) + * + * returns: + * the targeted node offset in the base device tree + * Negative error code on error + */ +static int overlay_get_target(const void *fdt, const void *fdto, + int fragment, char const **pathp) +{ + uint32_t phandle; + const char *path = NULL; + int path_len = 0, ret; + + /* Try first to do a phandle based lookup */ + phandle = overlay_get_target_phandle(fdto, fragment); + if (phandle == (uint32_t)-1) + return -FDT_ERR_BADPHANDLE; + + /* no phandle, try path */ + if (!phandle) { + /* And then a path based lookup */ + path = fdt_getprop(fdto, fragment, "target-path", &path_len); + if (path) + ret = fdt_path_offset(fdt, path); + else + ret = path_len; + } else + ret = fdt_node_offset_by_phandle(fdt, phandle); + + /* + * If we haven't found either a target or a + * target-path property in a node that contains a + * __overlay__ subnode (we wouldn't be called + * otherwise), consider it a improperly written + * overlay + */ + if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) + ret = -FDT_ERR_BADOVERLAY; + + /* return on error */ + if (ret < 0) + return ret; + + /* return pointer to path (if available) */ + if (pathp) + *pathp = path ? path : NULL; + + return ret; +} + +/** + * overlay_phandle_add_offset - Increases a phandle by an offset + * @fdt: Base device tree blob + * @node: Device tree overlay blob + * @name: Name of the property to modify (phandle or linux,phandle) + * @delta: offset to apply + * + * overlay_phandle_add_offset() increments a node phandle by a given + * offset. + * + * returns: + * 0 on success. + * Negative error code on error + */ +static int overlay_phandle_add_offset(void *fdt, int node, + const char *name, uint32_t delta) +{ + const fdt32_t *val; + uint32_t adj_val; + int len; + + val = fdt_getprop(fdt, node, name, &len); + if (!val) + return len; + + if (len != sizeof(*val)) + return -FDT_ERR_BADPHANDLE; + + adj_val = fdt32_to_cpu(*val); + if ((adj_val + delta) < adj_val) + return -FDT_ERR_NOPHANDLES; + + adj_val += delta; + if (adj_val == (uint32_t)-1) + return -FDT_ERR_NOPHANDLES; + + return fdt_setprop_inplace_u32(fdt, node, name, adj_val); +} + +/** + * overlay_adjust_node_phandles - Offsets the phandles of a node + * @fdto: Device tree overlay blob + * @node: Offset of the node we want to adjust + * @delta: Offset to shift the phandles of + * + * overlay_adjust_node_phandles() adds a constant to all the phandles + * of a given node. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_node_phandles(void *fdto, int node, + uint32_t delta) +{ + int child; + int ret; + + ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + fdt_for_each_subnode(child, fdto, node) { + ret = overlay_adjust_node_phandles(fdto, child, delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_adjust_local_phandles() adds a constant to all the + * phandles of an overlay. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) +{ + /* + * Start adjusting the phandles from the overlay root + */ + return overlay_adjust_node_phandles(fdto, 0, delta); +} + +/** + * overlay_update_local_node_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @tree_node: Node offset of the node to operate on + * @fixup_node: Node offset of the matching local fixups node + * @delta: Offset to shift the phandles of + * + * overlay_update_local_nodes_references() update the phandles + * pointing to a node within the device tree overlay by adding a + * constant delta. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_node_references(void *fdto, + int tree_node, + int fixup_node, + uint32_t delta) +{ + int fixup_prop; + int fixup_child; + int ret; + + fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { + const fdt32_t *fixup_val; + const char *tree_val; + const char *name; + int fixup_len; + int tree_len; + int i; + + fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, + &name, &fixup_len); + if (!fixup_val) + return fixup_len; + + if (fixup_len % sizeof(uint32_t)) + return -FDT_ERR_BADOVERLAY; + + tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); + if (!tree_val) { + if (tree_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + + return tree_len; + } + + for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { + fdt32_t adj_val; + uint32_t poffset; + + poffset = fdt32_to_cpu(fixup_val[i]); + + /* + * phandles to fixup can be unaligned. + * + * Use a memcpy for the architectures that do + * not support unaligned accesses. + */ + memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); + + adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); + + ret = fdt_setprop_inplace_namelen_partial(fdto, + tree_node, + name, + strlen(name), + poffset, + &adj_val, + sizeof(adj_val)); + if (ret == -FDT_ERR_NOSPACE) + return -FDT_ERR_BADOVERLAY; + + if (ret) + return ret; + } + } + + fdt_for_each_subnode(fixup_child, fdto, fixup_node) { + const char *fixup_child_name = fdt_get_name(fdto, fixup_child, + NULL); + int tree_child; + + tree_child = fdt_subnode_offset(fdto, tree_node, + fixup_child_name); + if (tree_child == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (tree_child < 0) + return tree_child; + + ret = overlay_update_local_node_references(fdto, + tree_child, + fixup_child, + delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_update_local_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_update_local_references() update all the phandles pointing + * to a node within the device tree overlay by adding a constant + * delta to not conflict with the base overlay. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_references(void *fdto, uint32_t delta) +{ + int fixups; + + fixups = fdt_path_offset(fdto, "/__local_fixups__"); + if (fixups < 0) { + /* There's no local phandles to adjust, bail out */ + if (fixups == -FDT_ERR_NOTFOUND) + return 0; + + return fixups; + } + + /* + * Update our local references from the root of the tree + */ + return overlay_update_local_node_references(fdto, 0, fixups, + delta); +} + +/** + * overlay_fixup_one_phandle - Set an overlay phandle to the base one + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * @symbols_off: Node offset of the symbols node in the base device tree + * @path: Path to a node holding a phandle in the overlay + * @path_len: number of path characters to consider + * @name: Name of the property holding the phandle reference in the overlay + * @name_len: number of name characters to consider + * @poffset: Offset within the overlay property where the phandle is stored + * @label: Label of the node referenced by the phandle + * + * overlay_fixup_one_phandle() resolves an overlay phandle pointing to + * a node in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_one_phandle(void *fdt, void *fdto, + int symbols_off, + const char *path, uint32_t path_len, + const char *name, uint32_t name_len, + int poffset, const char *label) +{ + const char *symbol_path; + uint32_t phandle; + fdt32_t phandle_prop; + int symbol_off, fixup_off; + int prop_len; + + if (symbols_off < 0) + return symbols_off; + + symbol_path = fdt_getprop(fdt, symbols_off, label, + &prop_len); + if (!symbol_path) + return prop_len; + + symbol_off = fdt_path_offset(fdt, symbol_path); + if (symbol_off < 0) + return symbol_off; + + phandle = fdt_get_phandle(fdt, symbol_off); + if (!phandle) + return -FDT_ERR_NOTFOUND; + + fixup_off = fdt_path_offset_namelen(fdto, path, path_len); + if (fixup_off == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (fixup_off < 0) + return fixup_off; + + phandle_prop = cpu_to_fdt32(phandle); + return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, + name, name_len, poffset, + &phandle_prop, + sizeof(phandle_prop)); +} + +/** + * overlay_fixup_phandle - Set an overlay phandle to the base one + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * @symbols_off: Node offset of the symbols node in the base device tree + * @property: Property offset in the overlay holding the list of fixups + * + * overlay_fixup_phandle() resolves all the overlay phandles pointed + * to in a __fixups__ property, and updates them to match the phandles + * in use in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, + int property) +{ + const char *value; + const char *label; + int len; + + value = fdt_getprop_by_offset(fdto, property, + &label, &len); + if (!value) { + if (len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + + return len; + } + + do { + const char *path, *name, *fixup_end; + const char *fixup_str = value; + uint32_t path_len, name_len; + uint32_t fixup_len; + char *sep, *endptr; + int poffset, ret; + + fixup_end = memchr(value, '\0', len); + if (!fixup_end) + return -FDT_ERR_BADOVERLAY; + fixup_len = fixup_end - fixup_str; + + len -= fixup_len + 1; + value += fixup_len + 1; + + path = fixup_str; + sep = memchr(fixup_str, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + path_len = sep - path; + if (path_len == (fixup_len - 1)) + return -FDT_ERR_BADOVERLAY; + + fixup_len -= path_len + 1; + name = sep + 1; + sep = memchr(name, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + name_len = sep - name; + if (!name_len) + return -FDT_ERR_BADOVERLAY; + + poffset = strtoul(sep + 1, &endptr, 10); + if ((*endptr != '\0') || (endptr <= (sep + 1))) + return -FDT_ERR_BADOVERLAY; + + ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, + path, path_len, name, name_len, + poffset, label); + if (ret) + return ret; + } while (len > 0); + + return 0; +} + +/** + * overlay_fixup_phandles - Resolve the overlay phandles to the base + * device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_fixup_phandles() resolves all the overlay phandles pointing + * to nodes in the base device tree. + * + * This is one of the steps of the device tree overlay application + * process, when you want all the phandles in the overlay to point to + * the actual base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandles(void *fdt, void *fdto) +{ + int fixups_off, symbols_off; + int property; + + /* We can have overlays without any fixups */ + fixups_off = fdt_path_offset(fdto, "/__fixups__"); + if (fixups_off == -FDT_ERR_NOTFOUND) + return 0; /* nothing to do */ + if (fixups_off < 0) + return fixups_off; + + /* And base DTs without symbols */ + symbols_off = fdt_path_offset(fdt, "/__symbols__"); + if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) + return symbols_off; + + fdt_for_each_property_offset(property, fdto, fixups_off) { + int ret; + + ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_apply_node - Merges a node into the base device tree + * @fdt: Base Device Tree blob + * @target: Node offset in the base device tree to apply the fragment to + * @fdto: Device tree overlay blob + * @node: Node offset in the overlay holding the changes to merge + * + * overlay_apply_node() merges a node into a target base device tree + * node pointed. + * + * This is part of the final step in the device tree overlay + * application process, when all the phandles have been adjusted and + * resolved and you just have to merge overlay into the base device + * tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_apply_node(void *fdt, int target, + void *fdto, int node) +{ + int property; + int subnode; + + fdt_for_each_property_offset(property, fdto, node) { + const char *name; + const void *prop; + int prop_len; + int ret; + + prop = fdt_getprop_by_offset(fdto, property, &name, + &prop_len); + if (prop_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + if (prop_len < 0) + return prop_len; + + ret = fdt_setprop(fdt, target, name, prop, prop_len); + if (ret) + return ret; + } + + fdt_for_each_subnode(subnode, fdto, node) { + const char *name = fdt_get_name(fdto, subnode, NULL); + int nnode; + int ret; + + nnode = fdt_add_subnode(fdt, target, name); + if (nnode == -FDT_ERR_EXISTS) { + nnode = fdt_subnode_offset(fdt, target, name); + if (nnode == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + } + + if (nnode < 0) + return nnode; + + ret = overlay_apply_node(fdt, nnode, fdto, subnode); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_merge - Merge an overlay into its base device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_merge() merges an overlay into its base device tree. + * + * This is the next to last step in the device tree overlay application + * process, when all the phandles have been adjusted and resolved and + * you just have to merge overlay into the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_merge(void *fdt, void *fdto) +{ + int fragment; + + fdt_for_each_subnode(fragment, fdto, 0) { + int overlay; + int target; + int ret; + + /* + * Each fragments will have an __overlay__ node. If + * they don't, it's not supposed to be merged + */ + overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (overlay == -FDT_ERR_NOTFOUND) + continue; + + if (overlay < 0) + return overlay; + + target = overlay_get_target(fdt, fdto, fragment, NULL); + if (target < 0) + return target; + + ret = overlay_apply_node(fdt, target, fdto, overlay); + if (ret) + return ret; + } + + return 0; +} + +static int get_path_len(const void *fdt, int nodeoffset) +{ + int len = 0, namelen; + const char *name; + + FDT_RO_PROBE(fdt); + + for (;;) { + name = fdt_get_name(fdt, nodeoffset, &namelen); + if (!name) + return namelen; + + /* root? we're done */ + if (namelen == 0) + break; + + nodeoffset = fdt_parent_offset(fdt, nodeoffset); + if (nodeoffset < 0) + return nodeoffset; + len += namelen + 1; + } + + /* in case of root pretend it's "/" */ + if (len == 0) + len++; + return len; +} + +/** + * overlay_symbol_update - Update the symbols of base tree after a merge + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_symbol_update() updates the symbols of the base tree with the + * symbols of the applied overlay + * + * This is the last step in the device tree overlay application + * process, allowing the reference of overlay symbols by subsequent + * overlay operations. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_symbol_update(void *fdt, void *fdto) +{ + int root_sym, ov_sym, prop, path_len, fragment, target; + int len, frag_name_len, ret, rel_path_len; + const char *s, *e; + const char *path; + const char *name; + const char *frag_name; + const char *rel_path; + const char *target_path; + char *buf; + void *p; + + ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); + + /* if no overlay symbols exist no problem */ + if (ov_sym < 0) + return 0; + + root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); + + /* it no root symbols exist we should create them */ + if (root_sym == -FDT_ERR_NOTFOUND) + root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); + + /* any error is fatal now */ + if (root_sym < 0) + return root_sym; + + /* iterate over each overlay symbol */ + fdt_for_each_property_offset(prop, fdto, ov_sym) { + path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); + if (!path) + return path_len; + + /* verify it's a string property (terminated by a single \0) */ + if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) + return -FDT_ERR_BADVALUE; + + /* keep end marker to avoid strlen() */ + e = path + path_len; + + if (*path != '/') + return -FDT_ERR_BADVALUE; + + /* get fragment name first */ + s = strchr(path + 1, '/'); + if (!s) { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } + + frag_name = path + 1; + frag_name_len = s - path - 1; + + /* verify format; safe since "s" lies in \0 terminated prop */ + len = sizeof("/__overlay__/") - 1; + if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { + /* //__overlay__/ */ + rel_path = s + len; + rel_path_len = e - rel_path; + } else if ((e - s) == len + && (memcmp(s, "/__overlay__", len - 1) == 0)) { + /* //__overlay__ */ + rel_path = ""; + rel_path_len = 0; + } else { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } + + /* find the fragment index in which the symbol lies */ + ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, + frag_name_len); + /* not found? */ + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + fragment = ret; + + /* an __overlay__ subnode must exist */ + ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + + /* get the target of the fragment */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + + /* if we have a target path use */ + if (!target_path) { + ret = get_path_len(fdt, target); + if (ret < 0) + return ret; + len = ret; + } else { + len = strlen(target_path); + } + + ret = fdt_setprop_placeholder(fdt, root_sym, name, + len + (len > 1) + rel_path_len + 1, &p); + if (ret < 0) + return ret; + + if (!target_path) { + /* again in case setprop_placeholder changed it */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + } + + buf = p; + if (len > 1) { /* target is not root */ + if (!target_path) { + ret = fdt_get_path(fdt, target, buf, len + 1); + if (ret < 0) + return ret; + } else + memcpy(buf, target_path, len + 1); + + } else + len--; + + buf[len] = '/'; + memcpy(buf + len + 1, rel_path, rel_path_len); + buf[len + 1 + rel_path_len] = '\0'; + } + + return 0; +} + +int fdt_overlay_apply(void *fdt, void *fdto) +{ + uint32_t delta; + int ret; + + FDT_RO_PROBE(fdt); + FDT_RO_PROBE(fdto); + + ret = fdt_find_max_phandle(fdt, &delta); + if (ret) + goto err; + + ret = overlay_adjust_local_phandles(fdto, delta); + if (ret) + goto err; + + ret = overlay_update_local_references(fdto, delta); + if (ret) + goto err; + + ret = overlay_fixup_phandles(fdt, fdto); + if (ret) + goto err; + + ret = overlay_merge(fdt, fdto); + if (ret) + goto err; + + ret = overlay_symbol_update(fdt, fdto); + if (ret) + goto err; + + /* + * The overlay has been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + return 0; + +err: + /* + * The overlay might have been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + /* + * The base device tree might have been damaged, erase its + * magic. + */ + fdt_set_magic(fdt, ~0); + + return ret; +} diff --git a/optee/optee_os/core/lib/libfdt/fdt_ro.c b/optee/optee_os/core/lib/libfdt/fdt_ro.c new file mode 100644 index 0000000..a5c2797 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt_ro.c @@ -0,0 +1,898 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_nodename_eq_(const void *fdt, int offset, + const char *s, int len) +{ + int olen; + const char *p = fdt_get_name(fdt, offset, &olen); + + if (!p || olen < len) + /* short match */ + return 0; + + if (memcmp(p, s, len) != 0) + return 0; + + if (p[len] == '\0') + return 1; + else if (!memchr(s, '@', len) && (p[len] == '@')) + return 1; + else + return 0; +} + +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) +{ + int32_t totalsize = fdt_ro_probe_(fdt); + uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); + size_t len; + int err; + const char *s, *n; + + err = totalsize; + if (totalsize < 0) + goto fail; + + err = -FDT_ERR_BADOFFSET; + if (absoffset >= totalsize) + goto fail; + len = totalsize - absoffset; + + if (fdt_magic(fdt) == FDT_MAGIC) { + if (stroffset < 0) + goto fail; + if (fdt_version(fdt) >= 17) { + if (stroffset >= fdt_size_dt_strings(fdt)) + goto fail; + if ((fdt_size_dt_strings(fdt) - stroffset) < len) + len = fdt_size_dt_strings(fdt) - stroffset; + } + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + if ((stroffset >= 0) + || (stroffset < -fdt_size_dt_strings(fdt))) + goto fail; + if ((-stroffset) < len) + len = -stroffset; + } else { + err = -FDT_ERR_INTERNAL; + goto fail; + } + + s = (const char *)fdt + absoffset; + n = memchr(s, '\0', len); + if (!n) { + /* missing terminating NULL */ + err = -FDT_ERR_TRUNCATED; + goto fail; + } + + if (lenp) + *lenp = n - s; + return s; + +fail: + if (lenp) + *lenp = err; + return NULL; +} + +const char *fdt_string(const void *fdt, int stroffset) +{ + return fdt_get_string(fdt, stroffset, NULL); +} + +static int fdt_string_eq_(const void *fdt, int stroffset, + const char *s, int len) +{ + int slen; + const char *p = fdt_get_string(fdt, stroffset, &slen); + + return p && (slen == len) && (memcmp(p, s, len) == 0); +} + +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max = 0; + int offset = -1; + + while (true) { + uint32_t value; + + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + return offset; + } + + value = fdt_get_phandle(fdt, offset); + + if (value > max) + max = value; + } + + if (phandle) + *phandle = max; + + return 0; +} + +int fdt_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max; + int err; + + err = fdt_find_max_phandle(fdt, &max); + if (err < 0) + return err; + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + +static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) +{ + int offset = n * sizeof(struct fdt_reserve_entry); + int absoffset = fdt_off_mem_rsvmap(fdt) + offset; + + if (absoffset < fdt_off_mem_rsvmap(fdt)) + return NULL; + if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry)) + return NULL; + return fdt_mem_rsv_(fdt, n); +} + +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) +{ + const struct fdt_reserve_entry *re; + + FDT_RO_PROBE(fdt); + re = fdt_mem_rsv(fdt, n); + if (!re) + return -FDT_ERR_BADOFFSET; + + *address = fdt64_ld(&re->address); + *size = fdt64_ld(&re->size); + return 0; +} + +int fdt_num_mem_rsv(const void *fdt) +{ + int i; + const struct fdt_reserve_entry *re; + + for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { + if (fdt64_ld(&re->size) == 0) + return i; + } + return -FDT_ERR_TRUNCATED; +} + +static int nextprop_(const void *fdt, int offset) +{ + uint32_t tag; + int nextoffset; + + do { + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_END: + if (nextoffset >= 0) + return -FDT_ERR_BADSTRUCTURE; + else + return nextoffset; + + case FDT_PROP: + return offset; + } + offset = nextoffset; + } while (tag == FDT_NOP); + + return -FDT_ERR_NOTFOUND; +} + +int fdt_subnode_offset_namelen(const void *fdt, int offset, + const char *name, int namelen) +{ + int depth; + + FDT_RO_PROBE(fdt); + + for (depth = 0; + (offset >= 0) && (depth >= 0); + offset = fdt_next_node(fdt, offset, &depth)) + if ((depth == 1) + && fdt_nodename_eq_(fdt, offset, name, namelen)) + return offset; + + if (depth < 0) + return -FDT_ERR_NOTFOUND; + return offset; /* error */ +} + +int fdt_subnode_offset(const void *fdt, int parentoffset, + const char *name) +{ + return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) +{ + const char *end = path + namelen; + const char *p = path; + int offset = 0; + + FDT_RO_PROBE(fdt); + + /* see if we have an alias */ + if (*path != '/') { + const char *q = memchr(path, '/', end - p); + + if (!q) + q = end; + + p = fdt_get_alias_namelen(fdt, p, q - p); + if (!p) + return -FDT_ERR_BADPATH; + offset = fdt_path_offset(fdt, p); + + p = q; + } + + while (p < end) { + const char *q; + + while (*p == '/') { + p++; + if (p == end) + return offset; + } + q = memchr(p, '/', end - p); + if (! q) + q = end; + + offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); + if (offset < 0) + return offset; + + p = q; + } + + return offset; +} + +int fdt_path_offset(const void *fdt, const char *path) +{ + return fdt_path_offset_namelen(fdt, path, strlen(path)); +} + +const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) +{ + const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); + const char *nameptr; + int err; + + if (((err = fdt_ro_probe_(fdt)) < 0) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) + goto fail; + + nameptr = nh->name; + + if (fdt_version(fdt) < 0x10) { + /* + * For old FDT versions, match the naming conventions of V16: + * give only the leaf name (after all /). The actual tree + * contents are loosely checked. + */ + const char *leaf; + leaf = strrchr(nameptr, '/'); + if (leaf == NULL) { + err = -FDT_ERR_BADSTRUCTURE; + goto fail; + } + nameptr = leaf+1; + } + + if (len) + *len = strlen(nameptr); + + return nameptr; + + fail: + if (len) + *len = err; + return NULL; +} + +int fdt_first_property_offset(const void *fdt, int nodeoffset) +{ + int offset; + + if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) + return offset; + + return nextprop_(fdt, offset); +} + +int fdt_next_property_offset(const void *fdt, int offset) +{ + if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) + return offset; + + return nextprop_(fdt, offset); +} + +static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, + int offset, + int *lenp) +{ + int err; + const struct fdt_property *prop; + + if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { + if (lenp) + *lenp = err; + return NULL; + } + + prop = fdt_offset_ptr_(fdt, offset); + + if (lenp) + *lenp = fdt32_ld(&prop->len); + + return prop; +} + +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp) +{ + /* Prior to version 16, properties may need realignment + * and this API does not work. fdt_getprop_*() will, however. */ + + if (fdt_version(fdt) < 0x10) { + if (lenp) + *lenp = -FDT_ERR_BADVERSION; + return NULL; + } + + return fdt_get_property_by_offset_(fdt, offset, lenp); +} + +static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, + int offset, + const char *name, + int namelen, + int *lenp, + int *poffset) +{ + for (offset = fdt_first_property_offset(fdt, offset); + (offset >= 0); + (offset = fdt_next_property_offset(fdt, offset))) { + const struct fdt_property *prop; + + if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { + offset = -FDT_ERR_INTERNAL; + break; + } + if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), + name, namelen)) { + if (poffset) + *poffset = offset; + return prop; + } + } + + if (lenp) + *lenp = offset; + return NULL; +} + + +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int offset, + const char *name, + int namelen, int *lenp) +{ + /* Prior to version 16, properties may need realignment + * and this API does not work. fdt_getprop_*() will, however. */ + if (fdt_version(fdt) < 0x10) { + if (lenp) + *lenp = -FDT_ERR_BADVERSION; + return NULL; + } + + return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp, + NULL); +} + + +const struct fdt_property *fdt_get_property(const void *fdt, + int nodeoffset, + const char *name, int *lenp) +{ + return fdt_get_property_namelen(fdt, nodeoffset, name, + strlen(name), lenp); +} + +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp) +{ + int poffset; + const struct fdt_property *prop; + + prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp, + &poffset); + if (!prop) + return NULL; + + /* Handle realignment */ + if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && + fdt32_ld(&prop->len) >= 8) + return prop->data + 4; + return prop->data; +} + +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!prop) + return NULL; + if (namep) { + const char *name; + int namelen; + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), + &namelen); + if (!name) { + if (lenp) + *lenp = namelen; + return NULL; + } + *namep = name; + } + + /* Handle realignment */ + if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && + fdt32_ld(&prop->len) >= 8) + return prop->data + 4; + return prop->data; +} + +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); +} + +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) +{ + const fdt32_t *php; + int len; + + /* FIXME: This is a bit sub-optimal, since we potentially scan + * over all the properties twice. */ + php = fdt_getprop(fdt, nodeoffset, "phandle", &len); + if (!php || (len != sizeof(*php))) { + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); + if (!php || (len != sizeof(*php))) + return 0; + } + + return fdt32_ld(php); +} + +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen) +{ + int aliasoffset; + + aliasoffset = fdt_path_offset(fdt, "/aliases"); + if (aliasoffset < 0) + return NULL; + + return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); +} + +const char *fdt_get_alias(const void *fdt, const char *name) +{ + return fdt_get_alias_namelen(fdt, name, strlen(name)); +} + +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) +{ + int pdepth = 0, p = 0; + int offset, depth, namelen; + const char *name; + + FDT_RO_PROBE(fdt); + + if (buflen < 2) + return -FDT_ERR_NOSPACE; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + while (pdepth > depth) { + do { + p--; + } while (buf[p-1] != '/'); + pdepth--; + } + + if (pdepth >= depth) { + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { + memcpy(buf + p, name, namelen); + p += namelen; + buf[p++] = '/'; + pdepth++; + } + } + + if (offset == nodeoffset) { + if (pdepth < (depth + 1)) + return -FDT_ERR_NOSPACE; + + if (p > 1) /* special case so that root path is "/", not "" */ + p--; + buf[p] = '\0'; + return 0; + } + } + + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + + return offset; /* error from fdt_next_node() */ +} + +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth) +{ + int offset, depth; + int supernodeoffset = -FDT_ERR_INTERNAL; + + FDT_RO_PROBE(fdt); + + if (supernodedepth < 0) + return -FDT_ERR_NOTFOUND; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth == supernodedepth) + supernodeoffset = offset; + + if (offset == nodeoffset) { + if (nodedepth) + *nodedepth = depth; + + if (supernodedepth > depth) + return -FDT_ERR_NOTFOUND; + else + return supernodeoffset; + } + } + + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_depth(const void *fdt, int nodeoffset) +{ + int nodedepth; + int err; + + err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); + if (err) + return (err < 0) ? err : -FDT_ERR_INTERNAL; + return nodedepth; +} + +int fdt_parent_offset(const void *fdt, int nodeoffset) +{ + int nodedepth = fdt_node_depth(fdt, nodeoffset); + + if (nodedepth < 0) + return nodedepth; + return fdt_supernode_atdepth_offset(fdt, nodeoffset, + nodedepth - 1, NULL); +} + +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen) +{ + int offset; + const void *val; + int len; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_getprop(), then if that didn't + * find what we want, we scan over them again making our way + * to the next node. Still it's the easiest to implement + * approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + val = fdt_getprop(fdt, offset, propname, &len); + if (val && (len == proplen) + && (memcmp(val, propval, len) == 0)) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) +{ + int offset; + + if ((phandle == 0) || (phandle == -1)) + return -FDT_ERR_BADPHANDLE; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we + * potentially scan each property of a node in + * fdt_get_phandle(), then if that didn't find what + * we want, we scan over them again making our way to the next + * node. Still it's the easiest to implement approach; + * performance can come later. */ + for (offset = fdt_next_node(fdt, -1, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + if (fdt_get_phandle(fdt, offset) == phandle) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) +{ + int len = strlen(str); + const char *p; + + while (listlen >= len) { + if (memcmp(str, strlist, len+1) == 0) + return 1; + p = memchr(strlist, '\0', listlen); + if (!p) + return 0; /* malformed strlist.. */ + listlen -= (p-strlist) + 1; + strlist = p + 1; + } + return 0; +} + +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) +{ + const char *list, *end; + int length, count = 0; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + list += length; + count++; + } + + return count; +} + +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) +{ + int length, len, idx = 0; + const char *list, *end; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + len = strlen(string) + 1; + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; + } + + return -FDT_ERR_NOTFOUND; +} + +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) +{ + const char *list, *end; + int length; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; + + return NULL; + } + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) { + if (lenp) + *lenp = -FDT_ERR_BADVALUE; + + return NULL; + } + + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; + } + + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; + + return NULL; +} + +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible) +{ + const void *prop; + int len; + + prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); + if (!prop) + return len; + + return !fdt_stringlist_contains(prop, len, compatible); +} + +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible) +{ + int offset, err; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_node_check_compatible(), then if + * that didn't find what we want, we scan over them again + * making our way to the next node. Still it's the easiest to + * implement approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + err = fdt_node_check_compatible(fdt, offset, compatible); + if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) + return err; + else if (err == 0) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_check_full(const void *fdt, size_t bufsize) +{ + int err; + int num_memrsv; + int offset, nextoffset = 0; + uint32_t tag; + unsigned depth = 0; + const void *prop; + const char *propname; + + if (bufsize < FDT_V1_SIZE) + return -FDT_ERR_TRUNCATED; + err = fdt_check_header(fdt); + if (err != 0) + return err; + if (bufsize < fdt_totalsize(fdt)) + return -FDT_ERR_TRUNCATED; + + num_memrsv = fdt_num_mem_rsv(fdt); + if (num_memrsv < 0) + return num_memrsv; + + while (1) { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + if (nextoffset < 0) + return nextoffset; + + switch (tag) { + case FDT_NOP: + break; + + case FDT_END: + if (depth != 0) + return -FDT_ERR_BADSTRUCTURE; + return 0; + + case FDT_BEGIN_NODE: + depth++; + if (depth > INT_MAX) + return -FDT_ERR_BADSTRUCTURE; + break; + + case FDT_END_NODE: + if (depth == 0) + return -FDT_ERR_BADSTRUCTURE; + depth--; + break; + + case FDT_PROP: + prop = fdt_getprop_by_offset(fdt, offset, &propname, + &err); + if (!prop) + return err; + break; + + default: + return -FDT_ERR_INTERNAL; + } + } +} diff --git a/optee/optee_os/core/lib/libfdt/fdt_rw.c b/optee/optee_os/core/lib/libfdt/fdt_rw.c new file mode 100644 index 0000000..8795947 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt_rw.c @@ -0,0 +1,476 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_blocks_misordered_(const void *fdt, + int mem_rsv_size, int struct_size) +{ + return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) + || (fdt_off_dt_struct(fdt) < + (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) + || (fdt_off_dt_strings(fdt) < + (fdt_off_dt_struct(fdt) + struct_size)) + || (fdt_totalsize(fdt) < + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); +} + +static int fdt_rw_probe_(void *fdt) +{ + FDT_RO_PROBE(fdt); + + if (fdt_version(fdt) < 17) + return -FDT_ERR_BADVERSION; + if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_BADLAYOUT; + if (fdt_version(fdt) > 17) + fdt_set_version(fdt, 17); + + return 0; +} + +#define FDT_RW_PROBE(fdt) \ + { \ + int err_; \ + if ((err_ = fdt_rw_probe_(fdt)) != 0) \ + return err_; \ + } + +static inline int fdt_data_size_(void *fdt) +{ + return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); +} + +static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) +{ + char *p = splicepoint; + char *end = (char *)fdt + fdt_data_size_(fdt); + + if (((p + oldlen) < p) || ((p + oldlen) > end)) + return -FDT_ERR_BADOFFSET; + if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) + return -FDT_ERR_BADOFFSET; + if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) + return -FDT_ERR_NOSPACE; + memmove(p + newlen, p + oldlen, end - p - oldlen); + return 0; +} + +static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p, + int oldn, int newn) +{ + int delta = (newn - oldn) * sizeof(*p); + int err; + err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + if (err) + return err; + fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int fdt_splice_struct_(void *fdt, void *p, + int oldlen, int newlen) +{ + int delta = newlen - oldlen; + int err; + + if ((err = fdt_splice_(fdt, p, oldlen, newlen))) + return err; + + fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int newlen = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen); +} + +static int fdt_splice_string_(void *fdt, int newlen) +{ + void *p = (char *)fdt + + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + int err; + + if ((err = fdt_splice_(fdt, p, 0, newlen))) + return err; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); + return 0; +} + +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) +{ + char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); + const char *p; + char *new; + int len = strlen(s) + 1; + int err; + + *allocated = 0; + + p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); + if (p) + /* found it */ + return (p - strtab); + + new = strtab + fdt_size_dt_strings(fdt); + err = fdt_splice_string_(fdt, len); + if (err) + return err; + + *allocated = 1; + + memcpy(new, s, len); + return (new - strtab); +} + +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) +{ + struct fdt_reserve_entry *re; + int err; + + FDT_RW_PROBE(fdt); + + re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); + err = fdt_splice_mem_rsv_(fdt, re, 0, 1); + if (err) + return err; + + re->address = cpu_to_fdt64(address); + re->size = cpu_to_fdt64(size); + return 0; +} + +int fdt_del_mem_rsv(void *fdt, int n) +{ + struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); + + FDT_RW_PROBE(fdt); + + if (n >= fdt_num_mem_rsv(fdt)) + return -FDT_ERR_NOTFOUND; + + return fdt_splice_mem_rsv_(fdt, re, 1, 0); +} + +static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int oldlen; + int err; + + *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (!*prop) + return oldlen; + + if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(len)))) + return err; + + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int proplen; + int nextoffset; + int namestroff; + int err; + int allocated; + + if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) + return nextoffset; + + namestroff = fdt_find_add_string_(fdt, name, &allocated); + if (namestroff < 0) + return namestroff; + + *prop = fdt_offset_ptr_w_(fdt, nextoffset); + proplen = sizeof(**prop) + FDT_TAGALIGN(len); + + err = fdt_splice_struct_(fdt, *prop, 0, proplen); + if (err) { + if (allocated) + fdt_del_last_string_(fdt, name); + return err; + } + + (*prop)->tag = cpu_to_fdt32(FDT_PROP); + (*prop)->nameoff = cpu_to_fdt32(namestroff); + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +int fdt_set_name(void *fdt, int nodeoffset, const char *name) +{ + char *namep; + int oldlen, newlen; + int err; + + FDT_RW_PROBE(fdt); + + namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); + if (!namep) + return oldlen; + + newlen = strlen(name); + + err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1), + FDT_TAGALIGN(newlen+1)); + if (err) + return err; + + memcpy(namep, name, newlen+1); + return 0; +} + +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data) +{ + struct fdt_property *prop; + int err; + + FDT_RW_PROBE(fdt); + + err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); + if (err == -FDT_ERR_NOTFOUND) + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + + *prop_data = prop->data; + return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + void *prop_data; + int err; + + err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); + if (err) + return err; + + if (len) + memcpy(prop_data, val, len); + return 0; +} + +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err, oldlen, newlen; + + FDT_RW_PROBE(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (prop) { + newlen = len + oldlen; + err = fdt_splice_struct_(fdt, prop->data, + FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(newlen)); + if (err) + return err; + prop->len = cpu_to_fdt32(newlen); + memcpy(prop->data + oldlen, val, len); + } else { + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + memcpy(prop->data, val, len); + } + return 0; +} + +int fdt_delprop(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len, proplen; + + FDT_RW_PROBE(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + proplen = sizeof(*prop) + FDT_TAGALIGN(len); + return fdt_splice_struct_(fdt, prop, proplen, 0); +} + +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen) +{ + struct fdt_node_header *nh; + int offset, nextoffset; + int nodelen; + int err; + uint32_t tag; + fdt32_t *endtag; + + FDT_RW_PROBE(fdt); + + offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); + if (offset >= 0) + return -FDT_ERR_EXISTS; + else if (offset != -FDT_ERR_NOTFOUND) + return offset; + + /* Try to place the new node after the parent's properties */ + fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); + + nh = fdt_offset_ptr_w_(fdt, offset); + nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; + + err = fdt_splice_struct_(fdt, nh, 0, nodelen); + if (err) + return err; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); + memcpy(nh->name, name, namelen); + endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); + *endtag = cpu_to_fdt32(FDT_END_NODE); + + return offset; +} + +int fdt_add_subnode(void *fdt, int parentoffset, const char *name) +{ + return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_del_node(void *fdt, int nodeoffset) +{ + int endoffset; + + FDT_RW_PROBE(fdt); + + endoffset = fdt_node_end_offset_(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset), + endoffset - nodeoffset, 0); +} + +static void fdt_packblocks_(const char *old, char *new, + int mem_rsv_size, int struct_size) +{ + int mem_rsv_off, struct_off, strings_off; + + mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); + struct_off = mem_rsv_off + mem_rsv_size; + strings_off = struct_off + struct_size; + + memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); + fdt_set_off_mem_rsvmap(new, mem_rsv_off); + + memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); + fdt_set_off_dt_struct(new, struct_off); + fdt_set_size_dt_struct(new, struct_size); + + memmove(new + strings_off, old + fdt_off_dt_strings(old), + fdt_size_dt_strings(old)); + fdt_set_off_dt_strings(new, strings_off); + fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); +} + +int fdt_open_into(const void *fdt, void *buf, int bufsize) +{ + int err; + int mem_rsv_size, struct_size; + int newsize; + const char *fdtstart = fdt; + const char *fdtend = fdtstart + fdt_totalsize(fdt); + char *tmp; + + FDT_RO_PROBE(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + + if (fdt_version(fdt) >= 17) { + struct_size = fdt_size_dt_struct(fdt); + } else { + struct_size = 0; + while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) + ; + if (struct_size < 0) + return struct_size; + } + + if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { + /* no further work necessary */ + err = fdt_move(fdt, buf, bufsize); + if (err) + return err; + fdt_set_version(buf, 17); + fdt_set_size_dt_struct(buf, struct_size); + fdt_set_totalsize(buf, bufsize); + return 0; + } + + /* Need to reorder */ + newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + + struct_size + fdt_size_dt_strings(fdt); + + if (bufsize < newsize) + return -FDT_ERR_NOSPACE; + + /* First attempt to build converted tree at beginning of buffer */ + tmp = buf; + /* But if that overlaps with the old tree... */ + if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { + /* Try right after the old tree instead */ + tmp = (char *)(uintptr_t)fdtend; + if ((tmp + newsize) > ((char *)buf + bufsize)) + return -FDT_ERR_NOSPACE; + } + + fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size); + memmove(buf, tmp, newsize); + + fdt_set_magic(buf, FDT_MAGIC); + fdt_set_totalsize(buf, bufsize); + fdt_set_version(buf, 17); + fdt_set_last_comp_version(buf, 16); + fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); + + return 0; +} + +int fdt_pack(void *fdt) +{ + int mem_rsv_size; + + FDT_RW_PROBE(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_set_totalsize(fdt, fdt_data_size_(fdt)); + + return 0; +} diff --git a/optee/optee_os/core/lib/libfdt/fdt_strerror.c b/optee/optee_os/core/lib/libfdt/fdt_strerror.c new file mode 100644 index 0000000..768db66 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt_strerror.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +struct fdt_errtabent { + const char *str; +}; + +#define FDT_ERRTABENT(val) \ + [(val)] = { .str = #val, } + +static struct fdt_errtabent fdt_errtable[] = { + FDT_ERRTABENT(FDT_ERR_NOTFOUND), + FDT_ERRTABENT(FDT_ERR_EXISTS), + FDT_ERRTABENT(FDT_ERR_NOSPACE), + + FDT_ERRTABENT(FDT_ERR_BADOFFSET), + FDT_ERRTABENT(FDT_ERR_BADPATH), + FDT_ERRTABENT(FDT_ERR_BADPHANDLE), + FDT_ERRTABENT(FDT_ERR_BADSTATE), + + FDT_ERRTABENT(FDT_ERR_TRUNCATED), + FDT_ERRTABENT(FDT_ERR_BADMAGIC), + FDT_ERRTABENT(FDT_ERR_BADVERSION), + FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), + FDT_ERRTABENT(FDT_ERR_BADLAYOUT), + FDT_ERRTABENT(FDT_ERR_INTERNAL), + FDT_ERRTABENT(FDT_ERR_BADNCELLS), + FDT_ERRTABENT(FDT_ERR_BADVALUE), + FDT_ERRTABENT(FDT_ERR_BADOVERLAY), + FDT_ERRTABENT(FDT_ERR_NOPHANDLES), + FDT_ERRTABENT(FDT_ERR_BADFLAGS), +}; +#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) + +const char *fdt_strerror(int errval) +{ + if (errval > 0) + return ""; + else if (errval == 0) + return ""; + else if (errval > -FDT_ERRTABSIZE) { + const char *s = fdt_errtable[-errval].str; + + if (s) + return s; + } + + return ""; +} diff --git a/optee/optee_os/core/lib/libfdt/fdt_sw.c b/optee/optee_os/core/lib/libfdt/fdt_sw.c new file mode 100644 index 0000000..76bea22 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt_sw.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_sw_probe_(void *fdt) +{ + if (fdt_magic(fdt) == FDT_MAGIC) + return -FDT_ERR_BADSTATE; + else if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + return 0; +} + +#define FDT_SW_PROBE(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_(fdt)) != 0) \ + return err; \ + } + +/* 'memrsv' state: Initial state after fdt_create() + * + * Allowed functions: + * fdt_add_reservmap_entry() + * fdt_finish_reservemap() [moves to 'struct' state] + */ +static int fdt_sw_probe_memrsv_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (fdt_off_dt_strings(fdt) != 0) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_MEMRSV(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ + return err; \ + } + +/* 'struct' state: Enter this state after fdt_finish_reservemap() + * + * Allowed functions: + * fdt_begin_node() + * fdt_end_node() + * fdt_property*() + * fdt_finish() [moves to 'complete' state] + */ +static int fdt_sw_probe_struct_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_STRUCT(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ + return err; \ + } + +static inline uint32_t sw_flags(void *fdt) +{ + /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ + return fdt_last_comp_version(fdt); +} + +/* 'complete' state: Enter this state after fdt_finish() + * + * Allowed functions: none + */ + +static void *fdt_grab_space_(void *fdt, size_t len) +{ + int offset = fdt_size_dt_struct(fdt); + int spaceleft; + + spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) + - fdt_size_dt_strings(fdt); + + if ((offset + len < offset) || (offset + len > spaceleft)) + return NULL; + + fdt_set_size_dt_struct(fdt, offset + len); + return fdt_offset_ptr_w_(fdt, offset); +} + +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) +{ + const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry)); + void *fdt = buf; + + if (bufsize < hdrsize) + return -FDT_ERR_NOSPACE; + + if (flags & ~FDT_CREATE_FLAGS_ALL) + return -FDT_ERR_BADFLAGS; + + memset(buf, 0, bufsize); + + /* + * magic and last_comp_version keep intermediate state during the fdt + * creation process, which is replaced with the proper FDT format by + * fdt_finish(). + * + * flags should be accessed with sw_flags(). + */ + fdt_set_magic(fdt, FDT_SW_MAGIC); + fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, flags); + + fdt_set_totalsize(fdt, bufsize); + + fdt_set_off_mem_rsvmap(fdt, hdrsize); + fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); + fdt_set_off_dt_strings(fdt, 0); + + return 0; +} + +int fdt_create(void *buf, int bufsize) +{ + return fdt_create_with_flags(buf, bufsize, 0); +} + +int fdt_resize(void *fdt, void *buf, int bufsize) +{ + size_t headsize, tailsize; + char *oldtail, *newtail; + + FDT_SW_PROBE(fdt); + + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + tailsize = fdt_size_dt_strings(fdt); + + if ((headsize + tailsize) > fdt_totalsize(fdt)) + return -FDT_ERR_INTERNAL; + + if ((headsize + tailsize) > bufsize) + return -FDT_ERR_NOSPACE; + + oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; + newtail = (char *)buf + bufsize - tailsize; + + /* Two cases to avoid clobbering data if the old and new + * buffers partially overlap */ + if (buf <= fdt) { + memmove(buf, fdt, headsize); + memmove(newtail, oldtail, tailsize); + } else { + memmove(newtail, oldtail, tailsize); + memmove(buf, fdt, headsize); + } + + fdt_set_totalsize(buf, bufsize); + if (fdt_off_dt_strings(buf)) + fdt_set_off_dt_strings(buf, bufsize); + + return 0; +} + +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) +{ + struct fdt_reserve_entry *re; + int offset; + + FDT_SW_PROBE_MEMRSV(fdt); + + offset = fdt_off_dt_struct(fdt); + if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) + return -FDT_ERR_NOSPACE; + + re = (struct fdt_reserve_entry *)((char *)fdt + offset); + re->address = cpu_to_fdt64(addr); + re->size = cpu_to_fdt64(size); + + fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); + + return 0; +} + +int fdt_finish_reservemap(void *fdt) +{ + int err = fdt_add_reservemap_entry(fdt, 0, 0); + + if (err) + return err; + + fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); + return 0; +} + +int fdt_begin_node(void *fdt, const char *name) +{ + struct fdt_node_header *nh; + int namelen; + + FDT_SW_PROBE_STRUCT(fdt); + + namelen = strlen(name) + 1; + nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); + if (! nh) + return -FDT_ERR_NOSPACE; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memcpy(nh->name, name, namelen); + return 0; +} + +int fdt_end_node(void *fdt) +{ + fdt32_t *en; + + FDT_SW_PROBE_STRUCT(fdt); + + en = fdt_grab_space_(fdt, FDT_TAGSIZE); + if (! en) + return -FDT_ERR_NOSPACE; + + *en = cpu_to_fdt32(FDT_END_NODE); + return 0; +} + +static int fdt_add_string_(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + int struct_top, offset; + + offset = -strtabsize - len; + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + if (fdt_totalsize(fdt) + offset < struct_top) + return 0; /* no more room :( */ + + memcpy(strtab + offset, s, len); + fdt_set_size_dt_strings(fdt, strtabsize + len); + return offset; +} + +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, strtabsize - len); +} + +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + int strtabsize = fdt_size_dt_strings(fdt); + const char *p; + + *allocated = 0; + + p = fdt_find_string_(strtab - strtabsize, strtabsize, s); + if (p) + return p - strtab; + + *allocated = 1; + + return fdt_add_string_(fdt, s); +} + +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) +{ + struct fdt_property *prop; + int nameoff; + int allocated; + + FDT_SW_PROBE_STRUCT(fdt); + + /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ + if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { + allocated = 1; + nameoff = fdt_add_string_(fdt, name); + } else { + nameoff = fdt_find_add_string_(fdt, name, &allocated); + } + if (nameoff == 0) + return -FDT_ERR_NOSPACE; + + prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); + if (! prop) { + if (allocated) + fdt_del_last_string_(fdt, name); + return -FDT_ERR_NOSPACE; + } + + prop->tag = cpu_to_fdt32(FDT_PROP); + prop->nameoff = cpu_to_fdt32(nameoff); + prop->len = cpu_to_fdt32(len); + *valp = prop->data; + return 0; +} + +int fdt_property(void *fdt, const char *name, const void *val, int len) +{ + void *ptr; + int ret; + + ret = fdt_property_placeholder(fdt, name, len, &ptr); + if (ret) + return ret; + memcpy(ptr, val, len); + return 0; +} + +int fdt_finish(void *fdt) +{ + char *p = (char *)fdt; + fdt32_t *end; + int oldstroffset, newstroffset; + uint32_t tag; + int offset, nextoffset; + + FDT_SW_PROBE_STRUCT(fdt); + + /* Add terminator */ + end = fdt_grab_space_(fdt, sizeof(*end)); + if (! end) + return -FDT_ERR_NOSPACE; + *end = cpu_to_fdt32(FDT_END); + + /* Relocate the string table */ + oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); + newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); + fdt_set_off_dt_strings(fdt, newstroffset); + + /* Walk the structure, correcting string offsets */ + offset = 0; + while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { + if (tag == FDT_PROP) { + struct fdt_property *prop = + fdt_offset_ptr_w_(fdt, offset); + int nameoff; + + nameoff = fdt32_to_cpu(prop->nameoff); + nameoff += fdt_size_dt_strings(fdt); + prop->nameoff = cpu_to_fdt32(nameoff); + } + offset = nextoffset; + } + if (nextoffset < 0) + return nextoffset; + + /* Finally, adjust the header */ + fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); + + /* And fix up fields that were keeping intermediate state. */ + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_magic(fdt, FDT_MAGIC); + + return 0; +} diff --git a/optee/optee_os/core/lib/libfdt/fdt_wip.c b/optee/optee_os/core/lib/libfdt/fdt_wip.c new file mode 100644 index 0000000..f64139e --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/fdt_wip.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len) +{ + void *propval; + int proplen; + + propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, + &proplen); + if (!propval) + return proplen; + + if (proplen < (len + idx)) + return -FDT_ERR_NOSPACE; + + memcpy((char *)propval + idx, val, len); + return 0; +} + +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + const void *propval; + int proplen; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + if (!propval) + return proplen; + + if (proplen != len) + return -FDT_ERR_NOSPACE; + + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, + strlen(name), 0, + val, len); +} + +static void fdt_nop_region_(void *start, int len) +{ + fdt32_t *p; + + for (p = start; (char *)p < ((char *)start + len); p++) + *p = cpu_to_fdt32(FDT_NOP); +} + +int fdt_nop_property(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len; + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + fdt_nop_region_(prop, len + sizeof(*prop)); + + return 0; +} + +int fdt_node_end_offset_(void *fdt, int offset) +{ + int depth = 0; + + while ((offset >= 0) && (depth >= 0)) + offset = fdt_next_node(fdt, offset, &depth); + + return offset; +} + +int fdt_nop_node(void *fdt, int nodeoffset) +{ + int endoffset; + + endoffset = fdt_node_end_offset_(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0), + endoffset - nodeoffset); + return 0; +} diff --git a/optee/optee_os/core/lib/libfdt/include/fdt.h b/optee/optee_os/core/lib/libfdt/include/fdt.h new file mode 100644 index 0000000..0c91aa7 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/include/fdt.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef FDT_H +#define FDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + */ + +#ifndef __ASSEMBLY__ + +struct fdt_header { + fdt32_t magic; /* magic word FDT_MAGIC */ + fdt32_t totalsize; /* total size of DT block */ + fdt32_t off_dt_struct; /* offset to structure */ + fdt32_t off_dt_strings; /* offset to strings */ + fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ + fdt32_t version; /* format version */ + fdt32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + fdt32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + fdt32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + fdt32_t size_dt_struct; /* size of the structure block */ +}; + +struct fdt_reserve_entry { + fdt64_t address; + fdt64_t size; +}; + +struct fdt_node_header { + fdt32_t tag; + char name[]; +}; + +struct fdt_property { + fdt32_t tag; + fdt32_t len; + fdt32_t nameoff; + char data[]; +}; + +#endif /* !__ASSEMBLY */ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(fdt32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, + size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(fdt32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) + +#endif /* FDT_H */ diff --git a/optee/optee_os/core/lib/libfdt/include/libfdt.h b/optee/optee_os/core/lib/libfdt/include/libfdt.h new file mode 100644 index 0000000..8037f39 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/include/libfdt.h @@ -0,0 +1,2071 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_H +#define LIBFDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ + +#include +#include + +#define FDT_FIRST_SUPPORTED_VERSION 0x02 +#define FDT_LAST_SUPPORTED_VERSION 0x11 + +/* Error codes: informative error codes */ +#define FDT_ERR_NOTFOUND 1 + /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ +#define FDT_ERR_EXISTS 2 + /* FDT_ERR_EXISTS: Attempted to create a node or property which + * already exists */ +#define FDT_ERR_NOSPACE 3 + /* FDT_ERR_NOSPACE: Operation needed to expand the device + * tree, but its buffer did not have sufficient space to + * contain the expanded tree. Use fdt_open_into() to move the + * device tree to a buffer with more space. */ + +/* Error codes: codes for bad parameters */ +#define FDT_ERR_BADOFFSET 4 + /* FDT_ERR_BADOFFSET: Function was passed a structure block + * offset which is out-of-bounds, or which points to an + * unsuitable part of the structure for the operation. */ +#define FDT_ERR_BADPATH 5 + /* FDT_ERR_BADPATH: Function was passed a badly formatted path + * (e.g. missing a leading / for a function which requires an + * absolute path) */ +#define FDT_ERR_BADPHANDLE 6 + /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. + * This can be caused either by an invalid phandle property + * length, or the phandle value was either 0 or -1, which are + * not permitted. */ +#define FDT_ERR_BADSTATE 7 + /* FDT_ERR_BADSTATE: Function was passed an incomplete device + * tree created by the sequential-write functions, which is + * not sufficiently complete for the requested operation. */ + +/* Error codes: codes for bad device tree blobs */ +#define FDT_ERR_TRUNCATED 8 + /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly + * terminated (overflows, goes outside allowed bounds, or + * isn't properly terminated). */ +#define FDT_ERR_BADMAGIC 9 + /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a + * device tree at all - it is missing the flattened device + * tree magic number. */ +#define FDT_ERR_BADVERSION 10 + /* FDT_ERR_BADVERSION: Given device tree has a version which + * can't be handled by the requested operation. For + * read-write functions, this may mean that fdt_open_into() is + * required to convert the tree to the expected version. */ +#define FDT_ERR_BADSTRUCTURE 11 + /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt + * structure block or other serious error (e.g. misnested + * nodes, or subnodes preceding properties). */ +#define FDT_ERR_BADLAYOUT 12 + /* FDT_ERR_BADLAYOUT: For read-write functions, the given + * device tree has it's sub-blocks in an order that the + * function can't handle (memory reserve map, then structure, + * then strings). Use fdt_open_into() to reorganize the tree + * into a form suitable for the read-write operations. */ + +/* "Can't happen" error indicating a bug in libfdt */ +#define FDT_ERR_INTERNAL 13 + /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. + * Should never be returned, if it is, it indicates a bug in + * libfdt itself. */ + +/* Errors in device tree content */ +#define FDT_ERR_BADNCELLS 14 + /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells + * or similar property with a bad format or value */ + +#define FDT_ERR_BADVALUE 15 + /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected + * value. For example: a property expected to contain a string list + * is not NUL-terminated within the length of its value. */ + +#define FDT_ERR_BADOVERLAY 16 + /* FDT_ERR_BADOVERLAY: The device tree overlay, while + * correctly structured, cannot be applied due to some + * unexpected or missing value, property or node. */ + +#define FDT_ERR_NOPHANDLES 17 + /* FDT_ERR_NOPHANDLES: The device tree doesn't have any + * phandle available anymore without causing an overflow */ + +#define FDT_ERR_BADFLAGS 18 + /* FDT_ERR_BADFLAGS: The function was passed a flags field that + * contains invalid flags or an invalid combination of flags. */ + +#define FDT_ERR_MAX 18 + +/* constants */ +#define FDT_MAX_PHANDLE 0xfffffffe + /* Valid values for phandles range from 1 to 2^32-2. */ + +/**********************************************************************/ +/* Low-level functions (you probably don't need these) */ +/**********************************************************************/ + +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); +#endif +static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) +{ + return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); +} + +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); + +/* + * Alignment helpers: + * These helpers access words from a device tree blob. They're + * built to work even with unaligned pointers on platforms (ike + * ARM) that don't like unaligned loads and stores + */ + +static inline uint32_t fdt32_ld(const fdt32_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; +} + +static inline void fdt32_st(void *property, uint32_t value) +{ + uint8_t *bp = property; + + bp[0] = value >> 24; + bp[1] = (value >> 16) & 0xff; + bp[2] = (value >> 8) & 0xff; + bp[3] = value & 0xff; +} + +static inline uint64_t fdt64_ld(const fdt64_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint64_t)bp[0] << 56) + | ((uint64_t)bp[1] << 48) + | ((uint64_t)bp[2] << 40) + | ((uint64_t)bp[3] << 32) + | ((uint64_t)bp[4] << 24) + | ((uint64_t)bp[5] << 16) + | ((uint64_t)bp[6] << 8) + | bp[7]; +} + +static inline void fdt64_st(void *property, uint64_t value) +{ + uint8_t *bp = property; + + bp[0] = value >> 56; + bp[1] = (value >> 48) & 0xff; + bp[2] = (value >> 40) & 0xff; + bp[3] = (value >> 32) & 0xff; + bp[4] = (value >> 24) & 0xff; + bp[5] = (value >> 16) & 0xff; + bp[6] = (value >> 8) & 0xff; + bp[7] = value & 0xff; +} + +/**********************************************************************/ +/* Traversal functions */ +/**********************************************************************/ + +int fdt_next_node(const void *fdt, int offset, int *depth); + +/** + * fdt_first_subnode() - get offset of first direct subnode + * + * @fdt: FDT blob + * @offset: Offset of node to check + * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none + */ +int fdt_first_subnode(const void *fdt, int offset); + +/** + * fdt_next_subnode() - get offset of next direct subnode + * + * After first calling fdt_first_subnode(), call this function repeatedly to + * get direct subnodes of a parent node. + * + * @fdt: FDT blob + * @offset: Offset of previous subnode + * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more + * subnodes + */ +int fdt_next_subnode(const void *fdt, int offset); + +/** + * fdt_for_each_subnode - iterate over all subnodes of a parent + * + * @node: child node (int, lvalue) + * @fdt: FDT blob (const void *) + * @parent: parent node (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_subnode(node, fdt, parent) { + * Use node + * ... + * } + * + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and @node is used as + * iterator in the loop. The parent variable be constant or even a + * literal. + * + */ +#define fdt_for_each_subnode(node, fdt, parent) \ + for (node = fdt_first_subnode(fdt, parent); \ + node >= 0; \ + node = fdt_next_subnode(fdt, node)) + +/**********************************************************************/ +/* General functions */ +/**********************************************************************/ +#define fdt_get_header(fdt, field) \ + (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) + +#define fdt_set_hdr_(name) \ + static inline void fdt_set_##name(void *fdt, uint32_t val) \ + { \ + struct fdt_header *fdth = (struct fdt_header *)fdt; \ + fdth->name = cpu_to_fdt32(val); \ + } +fdt_set_hdr_(magic); +fdt_set_hdr_(totalsize); +fdt_set_hdr_(off_dt_struct); +fdt_set_hdr_(off_dt_strings); +fdt_set_hdr_(off_mem_rsvmap); +fdt_set_hdr_(version); +fdt_set_hdr_(last_comp_version); +fdt_set_hdr_(boot_cpuid_phys); +fdt_set_hdr_(size_dt_strings); +fdt_set_hdr_(size_dt_struct); +#undef fdt_set_hdr_ + +/** + * fdt_header_size - return the size of the tree's header + * @fdt: pointer to a flattened device tree + */ +size_t fdt_header_size_(uint32_t version); +static inline size_t fdt_header_size(const void *fdt) +{ + return fdt_header_size_(fdt_version(fdt)); +} + +/** + * fdt_check_header - sanity check a device tree header + + * @fdt: pointer to data which might be a flattened device tree + * + * fdt_check_header() checks that the given buffer contains what + * appears to be a flattened device tree, and that the header contains + * valid information (to the extent that can be determined from the + * header alone). + * + * returns: + * 0, if the buffer appears to contain a valid device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings, as above + */ +int fdt_check_header(const void *fdt); + +/** + * fdt_move - move a device tree around in memory + * @fdt: pointer to the device tree to move + * @buf: pointer to memory where the device is to be moved + * @bufsize: size of the memory space at buf + * + * fdt_move() relocates, if possible, the device tree blob located at + * fdt to the buffer at buf of size bufsize. The buffer may overlap + * with the existing device tree blob at fdt. Therefore, + * fdt_move(fdt, fdt, fdt_totalsize(fdt)) + * should always succeed. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_move(const void *fdt, void *buf, int bufsize); + +/**********************************************************************/ +/* Read-only functions */ +/**********************************************************************/ + +int fdt_check_full(const void *fdt, size_t bufsize); + +/** + * fdt_get_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * @lenp: optional pointer to return the string's length + * + * fdt_get_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt, and optionally also + * returns the string's length in *lenp. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds, or doesn't point to a valid string + */ +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); + +/** + * fdt_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * + * fdt_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds, or doesn't point to a valid string + */ +const char *fdt_string(const void *fdt, int stroffset); + +/** + * fdt_find_max_phandle - find and return the highest phandle in a tree + * @fdt: pointer to the device tree blob + * @phandle: return location for the highest phandle value found in the tree + * + * fdt_find_max_phandle() finds the highest phandle value in the given device + * tree. The value returned in @phandle is only valid if the function returns + * success. + * + * returns: + * 0 on success or a negative error code on failure + */ +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); + +/** + * fdt_get_max_phandle - retrieves the highest phandle in a tree + * @fdt: pointer to the device tree blob + * + * fdt_get_max_phandle retrieves the highest phandle in the given + * device tree. This will ignore badly formatted phandles, or phandles + * with a value of 0 or -1. + * + * This function is deprecated in favour of fdt_find_max_phandle(). + * + * returns: + * the highest phandle on success + * 0, if no phandle was found in the device tree + * -1, if an error occurred + */ +static inline uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t phandle; + int err; + + err = fdt_find_max_phandle(fdt, &phandle); + if (err < 0) + return (uint32_t)-1; + + return phandle; +} + +/** + * fdt_generate_phandle - return a new, unused phandle for a device tree blob + * @fdt: pointer to the device tree blob + * @phandle: return location for the new phandle + * + * Walks the device tree blob and looks for the highest phandle value. On + * success, the new, unused phandle value (one higher than the previously + * highest phandle value in the device tree blob) will be returned in the + * @phandle parameter. + * + * Returns: + * 0 on success or a negative error-code on failure + */ +int fdt_generate_phandle(const void *fdt, uint32_t *phandle); + +/** + * fdt_num_mem_rsv - retrieve the number of memory reserve map entries + * @fdt: pointer to the device tree blob + * + * Returns the number of entries in the device tree blob's memory + * reservation map. This does not include the terminating 0,0 entry + * or any other (0,0) entries reserved for expansion. + * + * returns: + * the number of entries + */ +int fdt_num_mem_rsv(const void *fdt); + +/** + * fdt_get_mem_rsv - retrieve one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: pointers to 64-bit variables + * + * On success, *address and *size will contain the address and size of + * the n-th reserve map entry from the device tree blob, in + * native-endian format. + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); + +/** + * fdt_subnode_offset_namelen - find a subnode based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_subnode_offset(), but only examine the first + * namelen characters of name for matching the subnode name. This is + * useful for finding subnodes based on a portion of a larger string, + * such as a full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, + const char *name, int namelen); +#endif +/** + * fdt_subnode_offset - find a subnode of a given node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_subnode_offset() finds a subnode of the node at structure block + * offset parentoffset with the given name. name may include a unit + * address, in which case fdt_subnode_offset() will find the subnode + * with that unit address, or the unit address may be omitted, in + * which case fdt_subnode_offset() will find an arbitrary subnode + * whose name excluding unit address matches the given name. + * + * returns: + * structure block offset of the requested subnode (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); + +/** + * fdt_path_offset_namelen - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * @namelen: number of characters of path to consider + * + * Identical to fdt_path_offset(), but only consider the first namelen + * characters of path as the path name. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); +#endif + +/** + * fdt_path_offset - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * + * fdt_path_offset() finds a node of a given path in the device tree. + * Each path component may omit the unit address portion, but the + * results of this are undefined if any such path component is + * ambiguous (that is if there are multiple nodes at the relevant + * level matching the given component, differentiated only by unit + * address). + * + * returns: + * structure block offset of the node with the requested path (>=0), on + * success + * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid + * -FDT_ERR_NOTFOUND, if the requested node does not exist + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_path_offset(const void *fdt, const char *path); + +/** + * fdt_get_name - retrieve the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the starting node + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_name() retrieves the name (including unit address) of the + * device tree node at structure block offset nodeoffset. If lenp is + * non-NULL, the length of this name is also returned, in the integer + * pointed to by lenp. + * + * returns: + * pointer to the node's name, on success + * If lenp is non-NULL, *lenp contains the length of that name + * (>=0) + * NULL, on error + * if lenp is non-NULL *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); + +/** + * fdt_first_property_offset - find the offset of a node's first property + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * + * fdt_first_property_offset() finds the first property of the node at + * the given structure block offset. + * + * returns: + * structure block offset of the property (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested node has no properties + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_first_property_offset(const void *fdt, int nodeoffset); + +/** + * fdt_next_property_offset - step through a node's properties + * @fdt: pointer to the device tree blob + * @offset: structure block offset of a property + * + * fdt_next_property_offset() finds the property immediately after the + * one at the given structure block offset. This will be a property + * of the same node as the given property. + * + * returns: + * structure block offset of the next property (>=0), on success + * -FDT_ERR_NOTFOUND, if the given property is the last in its node + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_next_property_offset(const void *fdt, int offset); + +/** + * fdt_for_each_property_offset - iterate over all properties of a node + * + * @property_offset: property offset (int, lvalue) + * @fdt: FDT blob (const void *) + * @node: node offset (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_property_offset(property, fdt, node) { + * Use property + * ... + * } + * + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and property is used as + * iterator in the loop. The node variable can be constant or even a + * literal. + */ +#define fdt_for_each_property_offset(property, fdt, node) \ + for (property = fdt_first_property_offset(fdt, node); \ + property >= 0; \ + property = fdt_next_property_offset(fdt, property)) + +/** + * fdt_get_property_by_offset - retrieve the property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to retrieve + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property_by_offset() retrieves a pointer to the + * fdt_property structure within the device tree blob at the given + * offset. If lenp is non-NULL, the length of the property value is + * also returned, in the integer pointed to by lenp. + * + * Note that this code only works on device tree versions >= 16. fdt_getprop() + * works on all versions. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp); + +/** + * fdt_get_property_namelen - find a property based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_get_property(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int nodeoffset, + const char *name, + int namelen, int *lenp); +#endif + +/** + * fdt_get_property - find a given property in a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property() retrieves a pointer to the fdt_property + * structure within the device tree blob corresponding to the property + * named 'name' of the node at offset nodeoffset. If lenp is + * non-NULL, the length of the property value is also returned, in the + * integer pointed to by lenp. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, + const char *name, + int *lenp) +{ + return (struct fdt_property *)(uintptr_t) + fdt_get_property(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_getprop_by_offset - retrieve the value of a property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to read + * @namep: pointer to a string variable (will be overwritten) or NULL + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop_by_offset() retrieves a pointer to the value of the + * property at structure block offset 'offset' (this will be a pointer + * to within the device blob itself, not a copy of the value). If + * lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. If namep is non-NULL, + * the property's namne will also be returned in the char * pointed to + * by namep (this will be a pointer to within the device tree's string + * block, not a new copy of the name). + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * if namep is non-NULL *namep contiains a pointer to the property + * name. + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp); +#endif + +/** + * fdt_getprop_namelen - get property value based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_getprop(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp); +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, + const char *name, int namelen, + int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, + namelen, lenp); +} +#endif + +/** + * fdt_getprop - retrieve the value of a given property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop() retrieves a pointer to the value of the property + * named 'name' of the node at offset nodeoffset (this will be a + * pointer to within the device blob itself, not a copy of the value). + * If lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline void *fdt_getprop_w(void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_get_phandle - retrieve the phandle of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the node + * + * fdt_get_phandle() retrieves the phandle of the device tree node at + * structure block offset nodeoffset. + * + * returns: + * the phandle of the node at nodeoffset, on success (!= 0, != -1) + * 0, if the node has no phandle, or another error occurs + */ +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); + +/** + * fdt_get_alias_namelen - get alias based on substring + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_alias(), but only examine the first namelen + * characters of name for matching the alias name. + */ +#ifndef SWIG /* Not available in Python */ +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen); +#endif + +/** + * fdt_get_alias - retrieve the path referenced by a given alias + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * + * fdt_get_alias() retrieves the value of a given alias. That is, the + * value of the property named 'name' in the node /aliases. + * + * returns: + * a pointer to the expansion of the alias named 'name', if it exists + * NULL, if the given alias or the /aliases node does not exist + */ +const char *fdt_get_alias(const void *fdt, const char *name); + +/** + * fdt_get_path - determine the full path of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose path to find + * @buf: character buffer to contain the returned path (will be overwritten) + * @buflen: size of the character buffer at buf + * + * fdt_get_path() computes the full path of the node at offset + * nodeoffset, and records that path in the buffer at buf. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * 0, on success + * buf contains the absolute path of the node at + * nodeoffset, as a NUL-terminated string. + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) + * characters and will not fit in the given buffer. + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); + +/** + * fdt_supernode_atdepth_offset - find a specific ancestor of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * @supernodedepth: depth of the ancestor to find + * @nodedepth: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_supernode_atdepth_offset() finds an ancestor of the given node + * at a specific depth from the root (where the root itself has depth + * 0, its immediate subnodes depth 1 and so forth). So + * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); + * will always return 0, the offset of the root node. If the node at + * nodeoffset has depth D, then: + * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); + * will return nodeoffset itself. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * structure block offset of the node at node offset's ancestor + * of depth supernodedepth (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of + * nodeoffset + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth); + +/** + * fdt_node_depth - find the depth of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_node_depth() finds the depth of a given node. The root node + * has depth 0, its immediate subnodes depth 1 and so forth. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * depth of the node at nodeoffset (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_depth(const void *fdt, int nodeoffset); + +/** + * fdt_parent_offset - find the parent of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_parent_offset() locates the parent node of a given node (that + * is, it finds the offset of the node which contains the node at + * nodeoffset as a subnode). + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset, *twice*. + * + * returns: + * structure block offset of the parent of the node at nodeoffset + * (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_parent_offset(const void *fdt, int nodeoffset); + +/** + * fdt_node_offset_by_prop_value - find nodes with a given property value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @propname: property name to check + * @propval: property value to search for + * @proplen: length of the value in propval + * + * fdt_node_offset_by_prop_value() returns the offset of the first + * node after startoffset, which has a property named propname whose + * value is of length proplen and has value equal to propval; or if + * startoffset is -1, the very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, + * propval, proplen); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, + * propval, proplen); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen); + +/** + * fdt_node_offset_by_phandle - find the node with a given phandle + * @fdt: pointer to the device tree blob + * @phandle: phandle value + * + * fdt_node_offset_by_phandle() returns the offset of the node + * which has the given phandle value. If there is more than one node + * in the tree with the given phandle (an invalid tree), results are + * undefined. + * + * returns: + * structure block offset of the located node (>= 0), on success + * -FDT_ERR_NOTFOUND, no node with that phandle exists + * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); + +/** + * fdt_node_check_compatible: check a node's compatible property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @compatible: string to match against + * + * + * fdt_node_check_compatible() returns 0 if the given node contains a + * 'compatible' property with the given string as one of its elements, + * it returns non-zero otherwise, or on error. + * + * returns: + * 0, if the node has a 'compatible' property listing the given string + * 1, if the node has a 'compatible' property, but it does not list + * the given string + * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property + * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible); + +/** + * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @compatible: 'compatible' string to match against + * + * fdt_node_offset_by_compatible() returns the offset of the first + * node after startoffset, which has a 'compatible' property which + * lists the given compatible string; or if startoffset is -1, the + * very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible); + +/** + * fdt_stringlist_contains - check a string list property for a string + * @strlist: Property containing a list of strings to check + * @listlen: Length of property + * @str: String to search for + * + * This is a utility function provided for convenience. The list contains + * one or more strings, each terminated by \0, as is found in a device tree + * "compatible" property. + * + * @return: 1 if the string is found in the list, 0 not found, or invalid list + */ +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); + +/** + * fdt_stringlist_count - count the number of strings in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @return: + * the number of strings in the given property + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); + +/** + * fdt_stringlist_search - find a string in a string list and return its index + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @string: string to look up in the string list + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @return: + * the index of the string in the list of strings + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist or does not contain + * the given string + */ +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string); + +/** + * fdt_stringlist_get() - obtain the string at a given index in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @index: index of the string to return + * @lenp: return location for the string length or an error code on failure + * + * Note that this will successfully extract strings from properties with + * non-NUL-terminated values. For example on small-valued cell properties + * this function will return the empty string. + * + * If non-NULL, the length of the string (on success) or a negative error-code + * (on failure) will be stored in the integer pointer to by lenp. + * + * @return: + * A pointer to the string at the given index in the string list or NULL on + * failure. On success the length of the string will be stored in the memory + * location pointed to by the lenp parameter, if non-NULL. On failure one of + * the following negative error codes will be returned in the lenp parameter + * (if non-NULL): + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int index, + int *lenp); + +/**********************************************************************/ +/* Read-only functions (addressing related) */ +/**********************************************************************/ + +/** + * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells + * + * This is the maximum value for #address-cells, #size-cells and + * similar properties that will be processed by libfdt. IEE1275 + * requires that OF implementations handle values up to 4. + * Implementations may support larger values, but in practice higher + * values aren't used. + */ +#define FDT_MAX_NCELLS 4 + +/** + * fdt_address_cells - retrieve address size for a bus represented in the tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address size for + * + * When the node has a valid #address-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_address_cells(const void *fdt, int nodeoffset); + +/** + * fdt_size_cells - retrieve address range size for a bus represented in the + * tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address range size for + * + * When the node has a valid #size-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 1, if the node has no #size-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #size-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_size_cells(const void *fdt, int nodeoffset); + + +/**********************************************************************/ +/* Write-in-place functions */ +/**********************************************************************/ + +/** + * fdt_setprop_inplace_namelen_partial - change a property's value, + * but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @namelen: number of characters of name to consider + * @idx: index of the property to change in the array + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * Identical to fdt_setprop_inplace(), but modifies the given property + * starting from the given index, and using only the first characters + * of the name. It is useful when you want to manipulate only one value of + * an array and you have a string that doesn't end with \0. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len); +#endif + +/** + * fdt_setprop_inplace - change a property's value, but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * fdt_setprop_inplace() replaces the value of a given property with + * the data in val, of length len. This function cannot change the + * size of a property, and so will only work if len is equal to the + * current length of the property. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if len is not equal to the property's current length + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len); +#endif + +/** + * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to replace the property with + * + * fdt_setprop_inplace_u32() replaces the value of a given property + * with the 32-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 4. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to replace the property with + * + * fdt_setprop_inplace_u64() replaces the value of a given property + * with the 64-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 8. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell property + * + * This is an alternative name for fdt_setprop_inplace_u32() + */ +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_nop_property - replace a property with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_nop_property() will replace a given property's representation + * in the blob with FDT_NOP tags, effectively removing it from the + * tree. + * + * This function will alter only the bytes in the blob which contain + * the property, and will not alter or move any other part of the + * tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_property(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_nop_node - replace a node (subtree) with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_nop_node() will replace a given node's representation in the + * blob, including all its subnodes, if any, with FDT_NOP tags, + * effectively removing it from the tree. + * + * This function will alter only the bytes in the blob which contain + * the node and its properties and subnodes, and will not alter or + * move any other part of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_node(void *fdt, int nodeoffset); + +/**********************************************************************/ +/* Sequential write functions */ +/**********************************************************************/ + +/* fdt_create_with_flags flags */ +#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1 + /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property + * names in the fdt. This can result in faster creation times, but + * a larger fdt. */ + +#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP) + +/** + * fdt_create_with_flags - begin creation of a new fdt + * @fdt: pointer to memory allocated where fdt will be created + * @bufsize: size of the memory space at fdt + * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0. + * + * fdt_create_with_flags() begins the process of creating a new fdt with + * the sequential write interface. + * + * fdt creation process must end with fdt_finished() to produce a valid fdt. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + * -FDT_ERR_BADFLAGS, flags is not valid + */ +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); + +/** + * fdt_create - begin creation of a new fdt + * @fdt: pointer to memory allocated where fdt will be created + * @bufsize: size of the memory space at fdt + * + * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + */ +int fdt_create(void *buf, int bufsize); + +int fdt_resize(void *fdt, void *buf, int bufsize); +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); +int fdt_finish_reservemap(void *fdt); +int fdt_begin_node(void *fdt, const char *name); +int fdt_property(void *fdt, const char *name, const void *val, int len); +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} +static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} + +#ifndef SWIG /* Not available in Python */ +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ + return fdt_property_u32(fdt, name, val); +} +#endif + +/** + * fdt_property_placeholder - add a new property and return a ptr to its value + * + * @fdt: pointer to the device tree blob + * @name: name of property to add + * @len: length of property value in bytes + * @valp: returns a pointer to where where the value should be placed + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_NOSPACE, standard meanings + */ +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); + +#define fdt_property_string(fdt, name, str) \ + fdt_property(fdt, name, str, strlen(str)+1) +int fdt_end_node(void *fdt); +int fdt_finish(void *fdt); + +/**********************************************************************/ +/* Read-write functions */ +/**********************************************************************/ + +int fdt_create_empty_tree(void *buf, int bufsize); +int fdt_open_into(const void *fdt, void *buf, int bufsize); +int fdt_pack(void *fdt); + +/** + * fdt_add_mem_rsv - add one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: 64-bit values (native endian) + * + * Adds a reserve map entry to the given blob reserving a region at + * address address of length size. + * + * This function will insert data into the reserve map and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new reservation entry + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); + +/** + * fdt_del_mem_rsv - remove a memory reserve map entry + * @fdt: pointer to the device tree blob + * @n: entry to remove + * + * fdt_del_mem_rsv() removes the n-th memory reserve map entry from + * the blob. + * + * This function will delete data from the reservation table and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there + * are less than n+1 reserve map entries) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_mem_rsv(void *fdt, int n); + +/** + * fdt_set_name - change the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * @name: name to give the node + * + * fdt_set_name() replaces the name (including unit address, if any) + * of the given node with the given string. NOTE: this function can't + * efficiently check if the new name is unique amongst the given + * node's siblings; results are undefined if this function is invoked + * with a name equal to one of the given node's siblings. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob + * to contain the new name + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_set_name(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_setprop - create or change a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to set the property value to + * @len: length of the property value + * + * fdt_setprop() sets the value of the named property in the given + * node to the given value and length, creating the property if it + * does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_setprop_placeholder - allocate space for a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @len: length of the property value + * @prop_data: return pointer to property data + * + * fdt_setprop_placeholer() allocates the named property in the given node. + * If the property exists it is resized. In either case a pointer to the + * property data is returned. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data); + +/** + * fdt_setprop_u32 - set a property to a 32-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value for the property (native endian) + * + * fdt_setprop_u32() sets the value of the named property in the given + * node to the given 32-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_u64 - set a property to a 64-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value for the property (native endian) + * + * fdt_setprop_u64() sets the value of the named property in the given + * node to the given 64-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, + uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_cell - set a property to a single cell value + * + * This is an alternative name for fdt_setprop_u32() + */ +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + return fdt_setprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_setprop_string - set a property to a string value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value for the property + * + * fdt_setprop_string() sets the value of the named property in the + * given node to the given string value (using the length of the + * string to determine the new length of the property), or creates a + * new property with that value if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_string(fdt, nodeoffset, name, str) \ + fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + + +/** + * fdt_setprop_empty - set a property to an empty value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * + * fdt_setprop_empty() sets the value of the named property in the + * given node to an empty (zero length) value, or creates a new empty + * property if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_empty(fdt, nodeoffset, name) \ + fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) + +/** + * fdt_appendprop - append to or create a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to append to + * @val: pointer to data to append to the property value + * @len: length of the data to append to the property value + * + * fdt_appendprop() appends the value to the named property in the + * given node, creating the property if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_appendprop_u32 - append a 32-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u32() appends the given 32-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_u64 - append a 64-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u64() appends the given 64-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_cell - append a single cell value to a property + * + * This is an alternative name for fdt_appendprop_u32() + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_appendprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_appendprop_string - append a string to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value to append to the property + * + * fdt_appendprop_string() appends the given string to the value of + * the named property in the given node, or creates a new property + * with that value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ + fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/** + * fdt_appendprop_addrrange - append a address range property + * @fdt: pointer to the device tree blob + * @parent: offset of the parent node + * @nodeoffset: offset of the node to add a property at + * @name: name of property + * @addr: start address of a given range + * @size: size of a given range + * + * fdt_appendprop_addrrange() appends an address range value (start + * address and size) to the value of the named property in the given + * node, or creates a new property with that value if it does not + * already exist. + * If "name" is not specified, a default "reg" is used. + * Cell sizes are determined by parent's #address-cells and #size-cells. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain a new property + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size); + +/** + * fdt_delprop - delete a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_del_property() will delete the given property. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_delprop(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_add_subnode_namelen - creates a new node based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_add_subnode(), but use only the first namelen + * characters of name as the name of the new node. This is useful for + * creating subnodes based on a portion of a larger string, such as a + * full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen); +#endif + +/** + * fdt_add_subnode - creates a new node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_add_subnode() creates a new node as a subnode of the node at + * structure block offset parentoffset, with the given name (which + * should include the unit address, if any). + * + * This function will insert data into the blob, and will therefore + * change the offsets of some existing nodes. + + * returns: + * structure block offset of the created nodeequested subnode (>=0), on + * success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of + * the given name + * -FDT_ERR_NOSPACE, if there is insufficient free space in the + * blob to contain the new node + * -FDT_ERR_NOSPACE + * -FDT_ERR_BADLAYOUT + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_add_subnode(void *fdt, int parentoffset, const char *name); + +/** + * fdt_del_node - delete a node (subtree) + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_del_node() will remove the given node, including all its + * subnodes if any, from the blob. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_node(void *fdt, int nodeoffset); + +/** + * fdt_overlay_apply - Applies a DT overlay on a base DT + * @fdt: pointer to the base device tree blob + * @fdto: pointer to the device tree overlay blob + * + * fdt_overlay_apply() will apply the given device tree overlay on the + * given base device tree. + * + * Expect the base device tree to be modified, even if the function + * returns an error. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there's not enough space in the base device tree + * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or + * properties in the base DT + * -FDT_ERR_BADPHANDLE, + * -FDT_ERR_BADOVERLAY, + * -FDT_ERR_NOPHANDLES, + * -FDT_ERR_INTERNAL, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADOFFSET, + * -FDT_ERR_BADPATH, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_overlay_apply(void *fdt, void *fdto); + +/**********************************************************************/ +/* Debugging / informational functions */ +/**********************************************************************/ + +const char *fdt_strerror(int errval); + +#endif /* LIBFDT_H */ diff --git a/optee/optee_os/core/lib/libfdt/include/libfdt_env.h b/optee/optee_os/core/lib/libfdt/include/libfdt_env.h new file mode 100644 index 0000000..73b6d40 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/include/libfdt_env.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_ENV_H +#define LIBFDT_ENV_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef __CHECKER__ +#define FDT_FORCE __attribute__((force)) +#define FDT_BITWISE __attribute__((bitwise)) +#else +#define FDT_FORCE +#define FDT_BITWISE +#endif + +typedef uint16_t FDT_BITWISE fdt16_t; +typedef uint32_t FDT_BITWISE fdt32_t; +typedef uint64_t FDT_BITWISE fdt64_t; + +#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) +#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) +#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ + (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) +#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ + (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ + (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ + (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) + +static inline uint16_t fdt16_to_cpu(fdt16_t x) +{ + return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); +} +static inline fdt16_t cpu_to_fdt16(uint16_t x) +{ + return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); +} + +static inline uint32_t fdt32_to_cpu(fdt32_t x) +{ + return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); +} +static inline fdt32_t cpu_to_fdt32(uint32_t x) +{ + return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); +} + +static inline uint64_t fdt64_to_cpu(fdt64_t x) +{ + return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); +} +static inline fdt64_t cpu_to_fdt64(uint64_t x) +{ + return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); +} +#undef CPU_TO_FDT64 +#undef CPU_TO_FDT32 +#undef CPU_TO_FDT16 +#undef EXTRACT_BYTE + +#ifdef __APPLE__ +#include + +/* strnlen() is not available on Mac OS < 10.7 */ +# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ + MAC_OS_X_VERSION_10_7) + +#define strnlen fdt_strnlen + +/* + * fdt_strnlen: returns the length of a string or max_count - which ever is + * smallest. + * Input 1 string: the string whose size is to be determined + * Input 2 max_count: the maximum value returned by this function + * Output: length of the string or max_count (the smallest of the two) + */ +static inline size_t fdt_strnlen(const char *string, size_t max_count) +{ + const char *p = memchr(string, 0, max_count); + return p ? p - string : max_count; +} + +#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < + MAC_OS_X_VERSION_10_7) */ + +#endif /* __APPLE__ */ + +#endif /* LIBFDT_ENV_H */ diff --git a/optee/optee_os/core/lib/libfdt/libfdt_internal.h b/optee/optee_os/core/lib/libfdt/libfdt_internal.h new file mode 100644 index 0000000..741eeb3 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/libfdt_internal.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_INTERNAL_H +#define LIBFDT_INTERNAL_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include + +#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) + +int fdt_ro_probe_(const void *fdt); +#define FDT_RO_PROBE(fdt) \ + { \ + int totalsize_; \ + if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ + return totalsize_; \ + } + +int fdt_check_node_offset_(const void *fdt, int offset); +int fdt_check_prop_offset_(const void *fdt, int offset); +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); +int fdt_node_end_offset_(void *fdt, int nodeoffset); + +static inline const void *fdt_offset_ptr_(const void *fdt, int offset) +{ + return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; +} + +static inline void *fdt_offset_ptr_w_(void *fdt, int offset) +{ + return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); +} + +static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n) +{ + const struct fdt_reserve_entry *rsv_table = + (const struct fdt_reserve_entry *) + ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); + + return rsv_table + n; +} +static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) +{ + return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); +} + +#define FDT_SW_MAGIC (~FDT_MAGIC) + +#endif /* LIBFDT_INTERNAL_H */ diff --git a/optee/optee_os/core/lib/libfdt/sub.mk b/optee/optee_os/core/lib/libfdt/sub.mk new file mode 100644 index 0000000..3ea4b35 --- /dev/null +++ b/optee/optee_os/core/lib/libfdt/sub.mk @@ -0,0 +1,6 @@ +global-incdirs-y += include +cflags-y += -Wno-cast-align +cflags-y += -Wno-sign-compare +cflags-y += -Wno-switch-default +srcs-y += fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c +srcs-y += fdt_empty_tree.c fdt_addresses.c fdt_overlay.c diff --git a/optee/optee_os/core/lib/libtomcrypt/acipher_helpers.h b/optee/optee_os/core/lib/libtomcrypt/acipher_helpers.h new file mode 100644 index 0000000..de3210f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/acipher_helpers.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#ifndef ACIPHER_HELPERS_H +#define ACIPHER_HELPERS_H + +#include +#include +#include +#include +#include + +static inline bool bn_alloc_max(struct bignum **s) +{ + *s = crypto_bignum_allocate(_CFG_CORE_LTC_BIGNUM_MAX_BITS); + + return *s; +} + +static inline TEE_Result convert_ltc_verify_status(int ltc_res, int ltc_stat) +{ + switch (ltc_res) { + case CRYPT_OK: + if (ltc_stat == 1) + return TEE_SUCCESS; + else + return TEE_ERROR_SIGNATURE_INVALID; + case CRYPT_INVALID_PACKET: + case CRYPT_PK_INVALID_SIZE: + return TEE_ERROR_SIGNATURE_INVALID; + default: + return TEE_ERROR_GENERIC; + } +} + +#ifdef _CFG_CORE_LTC_ECC +TEE_Result ecc_populate_ltc_private_key(ecc_key *ltc_key, + struct ecc_keypair *key, + uint32_t algo, size_t *key_size_bytes); +TEE_Result ecc_populate_ltc_public_key(ecc_key *ltc_key, + struct ecc_public_key *key, + uint32_t algo, size_t *key_size_bytes); +#endif + +/* Write bignum to fixed size buffer in big endian order */ +#define mp_to_unsigned_bin2(a, b, c) \ + do { \ + void *_a = (a); \ + mp_to_unsigned_bin(_a, (b) + (c) - mp_unsigned_bin_size(_a)); \ + } while(0) + +#ifdef _CFG_CORE_LTC_SM2_DSA +TEE_Result sm2_ltc_dsa_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, uint8_t *sig, + size_t *sig_len); + +TEE_Result sm2_ltc_dsa_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len); +#else +static inline TEE_Result +sm2_ltc_dsa_sign(uint32_t algo __unused, struct ecc_keypair *key __unused, + const uint8_t *msg __unused, size_t msg_len __unused, + uint8_t *sig __unused, size_t *sig_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline TEE_Result +sm2_ltc_dsa_verify(uint32_t algo __unused, struct ecc_public_key *key __unused, + const uint8_t *msg __unused, size_t msg_len __unused, + const uint8_t *sig __unused, size_t sig_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif + +#ifdef _CFG_CORE_LTC_SM2_PKE +TEE_Result sm2_ltc_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, + size_t src_len, uint8_t *dst, size_t *dst_len); + +TEE_Result sm2_ltc_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, + size_t src_len, uint8_t *dst, size_t *dst_len); + +#else +static inline TEE_Result sm2_ltc_pke_decrypt(struct ecc_keypair *key __unused, + const uint8_t *src __unused, + size_t src_len __unused, + uint8_t *dst __unused, + size_t *dst_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static inline TEE_Result +sm2_ltc_pke_encrypt(struct ecc_public_key *key __unused, + const uint8_t *src __unused, size_t src_len __unused, + uint8_t *dst __unused, size_t *dst_len __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} +#endif +#endif /* ACIPHER_HELPERS_H */ diff --git a/optee/optee_os/core/lib/libtomcrypt/aes.c b/optee/optee_os/core/lib/libtomcrypt/aes.c new file mode 100644 index 0000000..3989140 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/aes.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +TEE_Result crypto_aes_expand_enc_key(const void *key, size_t key_len, + void *enc_key, size_t enc_keylen, + unsigned int *rounds) +{ +#ifdef _CFG_CORE_LTC_AES_ACCEL + return crypto_accel_aes_expand_keys(key, key_len, enc_key, NULL, + enc_keylen, rounds); +#else + symmetric_key skey; + + if (enc_keylen < sizeof(skey.rijndael.eK)) + return TEE_ERROR_BAD_PARAMETERS; + + if (aes_setup(key, key_len, 0, &skey)) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(enc_key, skey.rijndael.eK, sizeof(skey.rijndael.eK)); + *rounds = skey.rijndael.Nr; +#endif + return TEE_SUCCESS; +} + +void crypto_aes_enc_block(const void *enc_key, size_t enc_keylen __maybe_unused, + unsigned int rounds, const void *src, void *dst) +{ +#ifdef _CFG_CORE_LTC_AES_ACCEL + crypto_accel_aes_ecb_enc(dst, src, enc_key, rounds, 1); +#else + symmetric_key skey; + + assert(enc_keylen >= sizeof(skey.rijndael.eK)); + memcpy(skey.rijndael.eK, enc_key, sizeof(skey.rijndael.eK)); + skey.rijndael.Nr = rounds; + if (aes_ecb_encrypt(src, dst, &skey)) + panic(); +#endif +} diff --git a/optee/optee_os/core/lib/libtomcrypt/aes_accel.c b/optee/optee_os/core/lib/libtomcrypt/aes_accel.c new file mode 100644 index 0000000..0fb4bfc --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/aes_accel.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 cipher for ARMv8 with Crypto Extensions + * + * Copyright (C) 2013 Linaro Ltd + */ + +#include +#include +#include + +int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, + symmetric_key *skey) +{ + unsigned int round_count = 0; + + LTC_ARGCHK(key); + LTC_ARGCHK(skey); + + if (keylen != 16 && keylen != 24 && keylen != 32) + return CRYPT_INVALID_KEYSIZE; + + if (crypto_accel_aes_expand_keys(key, keylen, skey->rijndael.eK, + skey->rijndael.dK, + sizeof(skey->rijndael.eK), + &round_count)) + return CRYPT_INVALID_ARG; + + if (num_rounds && (unsigned int)num_rounds != round_count) + return CRYPT_INVALID_ROUNDS; + + skey->rijndael.Nr = round_count; + + return CRYPT_OK; +} + +void rijndael_done(symmetric_key *skey __unused) +{ +} + +int rijndael_keysize(int *keysize) +{ + LTC_ARGCHK(keysize); + + if (*keysize < 16) + return CRYPT_INVALID_KEYSIZE; + else if (*keysize < 24) + *keysize = 16; + else if (*keysize < 32) + *keysize = 24; + else + *keysize = 32; + + return CRYPT_OK; +} + +static int aes_ecb_encrypt_nblocks(const unsigned char *pt, unsigned char *ct, + unsigned long blocks, + const symmetric_key *skey) +{ + LTC_ARGCHK(pt); + LTC_ARGCHK(ct); + LTC_ARGCHK(skey); + + crypto_accel_aes_ecb_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr, + blocks); + return CRYPT_OK; +} + +static int aes_ecb_decrypt_nblocks(const unsigned char *ct, unsigned char *pt, + unsigned long blocks, + const symmetric_key *skey) +{ + LTC_ARGCHK(pt); + LTC_ARGCHK(ct); + LTC_ARGCHK(skey); + + crypto_accel_aes_ecb_dec(pt, ct, skey->rijndael.dK, skey->rijndael.Nr, + blocks); + + return CRYPT_OK; +} + +int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, + const symmetric_key *skey) +{ + return aes_ecb_encrypt_nblocks(pt, ct, 1, skey); +} + +int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, + const symmetric_key *skey) +{ + return aes_ecb_decrypt_nblocks(ct, pt, 1, skey); +} + +static int aes_cbc_encrypt_nblocks(const unsigned char *pt, unsigned char *ct, + unsigned long blocks, unsigned char *IV, + symmetric_key *skey) +{ + LTC_ARGCHK(pt); + LTC_ARGCHK(ct); + LTC_ARGCHK(IV); + LTC_ARGCHK(skey); + + crypto_accel_aes_cbc_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr, + blocks, IV); + + return CRYPT_OK; +} + +static int aes_cbc_decrypt_nblocks(const unsigned char *ct, unsigned char *pt, + unsigned long blocks, unsigned char *IV, + symmetric_key *skey) +{ + LTC_ARGCHK(pt); + LTC_ARGCHK(ct); + LTC_ARGCHK(IV); + LTC_ARGCHK(skey); + + crypto_accel_aes_cbc_dec(pt, ct, skey->rijndael.dK, skey->rijndael.Nr, + blocks, IV); + + return CRYPT_OK; +} + +static int aes_ctr_encrypt_nblocks(const unsigned char *pt, unsigned char *ct, + unsigned long blocks, unsigned char *IV, + int mode, symmetric_key *skey) +{ + LTC_ARGCHK(pt); + LTC_ARGCHK(ct); + LTC_ARGCHK(IV); + LTC_ARGCHK(skey); + + if (mode == CTR_COUNTER_LITTLE_ENDIAN) { + /* Accelerated algorithm supports big endian only */ + return CRYPT_ERROR; + } + + crypto_accel_aes_ctr_be_enc(ct, pt, skey->rijndael.eK, + skey->rijndael.Nr, blocks, IV); + + return CRYPT_OK; +} + +static int aes_xts_encrypt_nblocks(const unsigned char *pt, unsigned char *ct, + unsigned long blocks, unsigned char *tweak, + const symmetric_key *skey1, + const symmetric_key *skey2) +{ + LTC_ARGCHK(pt); + LTC_ARGCHK(ct); + LTC_ARGCHK(tweak); + LTC_ARGCHK(skey1); + LTC_ARGCHK(skey2); + LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr); + + + crypto_accel_aes_xts_enc(ct, pt, skey1->rijndael.eK, + skey1->rijndael.Nr, blocks, + skey2->rijndael.eK, tweak); + + return CRYPT_OK; +} + +static int aes_xts_decrypt_nblocks(const unsigned char *ct, unsigned char *pt, + unsigned long blocks, unsigned char *tweak, + const symmetric_key *skey1, + const symmetric_key *skey2) +{ + LTC_ARGCHK(pt); + LTC_ARGCHK(ct); + LTC_ARGCHK(tweak); + LTC_ARGCHK(skey1); + LTC_ARGCHK(skey2); + LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr); + + crypto_accel_aes_xts_dec(pt, ct, skey1->rijndael.dK, + skey1->rijndael.Nr, blocks, + skey2->rijndael.eK, tweak); + + return CRYPT_OK; +} + +const struct ltc_cipher_descriptor aes_desc = { + .name = "aes", + .ID = 6, + .min_key_length = 16, + .max_key_length = 32, + .block_length = 16, + .default_rounds = 10, + .setup = rijndael_setup, + .ecb_encrypt = rijndael_ecb_encrypt, + .ecb_decrypt = rijndael_ecb_decrypt, + .done = rijndael_done, + .keysize = rijndael_keysize, + .accel_ecb_encrypt = aes_ecb_encrypt_nblocks, + .accel_ecb_decrypt = aes_ecb_decrypt_nblocks, + .accel_cbc_encrypt = aes_cbc_encrypt_nblocks, + .accel_cbc_decrypt = aes_cbc_decrypt_nblocks, + .accel_ctr_encrypt = aes_ctr_encrypt_nblocks, + .accel_xts_encrypt = aes_xts_encrypt_nblocks, + .accel_xts_decrypt = aes_xts_decrypt_nblocks, +}; diff --git a/optee/optee_os/core/lib/libtomcrypt/cbc.c b/optee/optee_os/core/lib/libtomcrypt/cbc.c new file mode 100644 index 0000000..3a3b458 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/cbc.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "des2_key.h" + +struct ltc_cbc_ctx { + struct crypto_cipher_ctx ctx; + int cipher_idx; + bool des3; + int (*update)(const unsigned char *src, unsigned char *dst, + unsigned long len, symmetric_CBC *cbc); + symmetric_CBC state; +}; + +static const struct crypto_cipher_ops ltc_cbc_ops; + +static struct ltc_cbc_ctx *to_cbc_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == <c_cbc_ops); + + return container_of(ctx, struct ltc_cbc_ctx, ctx); +} + +static TEE_Result ltc_cbc_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv, size_t iv_len) +{ + struct ltc_cbc_ctx *c = to_cbc_ctx(ctx); + uint8_t tmp[24] = { 0 }; + const uint8_t *k = key1; + size_t kl = key1_len; + + if ((int)iv_len != cipher_descriptor[c->cipher_idx]->block_length) + return TEE_ERROR_BAD_PARAMETERS; + + if (mode == TEE_MODE_ENCRYPT) + c->update = cbc_encrypt; + else + c->update = cbc_decrypt; + + if (c->des3) + get_des2_key(&k, &kl, tmp); + + if (cbc_start(c->cipher_idx, iv, k, kl, 0, &c->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_cbc_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, uint8_t *dst) +{ + struct ltc_cbc_ctx *c = to_cbc_ctx(ctx); + + if (c->update && c->update(data, dst, len, &c->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static void ltc_cbc_final(struct crypto_cipher_ctx *ctx) +{ + cbc_done(&to_cbc_ctx(ctx)->state); +} + +static void ltc_cbc_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_cbc_ctx(ctx)); +} + +static void ltc_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct ltc_cbc_ctx *src = to_cbc_ctx(src_ctx); + struct ltc_cbc_ctx *dst = to_cbc_ctx(dst_ctx); + + assert(src->cipher_idx == dst->cipher_idx); + dst->update = src->update; + dst->state = src->state; +} + +static const struct crypto_cipher_ops ltc_cbc_ops = { + .init = ltc_cbc_init, + .update = ltc_cbc_update, + .final = ltc_cbc_final, + .free_ctx = ltc_cbc_free_ctx, + .copy_state = ltc_cbc_copy_state, +}; + +static TEE_Result ltc_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret, + int cipher_idx, bool des3) +{ + struct ltc_cbc_ctx *c = NULL; + + if (cipher_idx < 0) + return TEE_ERROR_NOT_SUPPORTED; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = <c_cbc_ops; + c->cipher_idx = cipher_idx; + c->des3 = des3; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} + +#if defined(_CFG_CORE_LTC_AES) +TEE_Result crypto_aes_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx) +{ + return ltc_cbc_alloc_ctx(ctx, find_cipher("aes"), false); +} +#endif + +#if defined(_CFG_CORE_LTC_DES) +TEE_Result crypto_des_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx) +{ + return ltc_cbc_alloc_ctx(ctx, find_cipher("des"), false); +} + +TEE_Result crypto_des3_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx) +{ + return ltc_cbc_alloc_ctx(ctx, find_cipher("3des"), true); +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/ccm.c b/optee/optee_os/core/lib/libtomcrypt/ccm.c new file mode 100644 index 0000000..17f3898 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/ccm.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEE_CCM_KEY_MAX_LENGTH 32 +#define TEE_CCM_NONCE_MAX_LENGTH 13 +#define TEE_CCM_TAG_MAX_LENGTH 16 + +struct tee_ccm_state { + struct crypto_authenc_ctx aectx; + ccm_state ctx; /* the ccm state as defined by LTC */ + size_t tag_len; /* tag length */ +}; + +static const struct crypto_authenc_ops aes_ccm_ops; + +TEE_Result crypto_aes_ccm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret) +{ + struct tee_ccm_state *ctx = calloc(1, sizeof(*ctx)); + + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + ctx->aectx.ops = &aes_ccm_ops; + + *ctx_ret = &ctx->aectx; + return TEE_SUCCESS; +} + +static struct tee_ccm_state *to_tee_ccm_state(struct crypto_authenc_ctx *aectx) +{ + assert(aectx && aectx->ops == &aes_ccm_ops); + + return container_of(aectx, struct tee_ccm_state, aectx); +} + +static void crypto_aes_ccm_free_ctx(struct crypto_authenc_ctx *aectx) +{ + free(to_tee_ccm_state(aectx)); +} + +static void crypto_aes_ccm_copy_state(struct crypto_authenc_ctx *dst_aectx, + struct crypto_authenc_ctx *src_aectx) +{ + struct tee_ccm_state *dst_ctx = to_tee_ccm_state(dst_aectx); + struct tee_ccm_state *src_ctx = to_tee_ccm_state(src_aectx); + + dst_ctx->ctx = src_ctx->ctx; + dst_ctx->tag_len = src_ctx->tag_len; +} + +static TEE_Result crypto_aes_ccm_init(struct crypto_authenc_ctx *aectx, + TEE_OperationMode mode __unused, + 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) +{ + int ltc_res = 0; + int ltc_cipherindex = find_cipher("aes"); + struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); + + if (ltc_cipherindex < 0) + return TEE_ERROR_NOT_SUPPORTED; + + /* reset the state */ + memset(&ccm->ctx, 0, sizeof(ccm->ctx)); + ccm->tag_len = tag_len; + + /* 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 that payload_len and aad_len will fit into ints */ + if (payload_len > INT_MAX || aad_len > INT_MAX) + 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; + + ltc_res = ccm_init(&ccm->ctx, ltc_cipherindex, key, key_len, + payload_len, tag_len, aad_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + /* Add the IV */ + ltc_res = ccm_add_nonce(&ccm->ctx, nonce, nonce_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result crypto_aes_ccm_update_aad(struct crypto_authenc_ctx *aectx, + const uint8_t *data, size_t len) +{ + struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); + int ltc_res = 0; + + /* Add the AAD (note: aad can be NULL if aadlen == 0) */ + ltc_res = ccm_add_aad(&ccm->ctx, data, len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result +crypto_aes_ccm_update_payload(struct crypto_authenc_ctx *aectx, + TEE_OperationMode mode, const uint8_t *src_data, + size_t len, uint8_t *dst_data) +{ + int ltc_res = 0; + int dir = 0; + struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); + unsigned char *pt = NULL; + unsigned char *ct = NULL; + + if (mode == TEE_MODE_ENCRYPT) { + pt = (unsigned char *)src_data; + ct = dst_data; + dir = CCM_ENCRYPT; + } else { + pt = dst_data; + ct = (unsigned char *)src_data; + dir = CCM_DECRYPT; + } + ltc_res = ccm_process(&ccm->ctx, pt, len, ct, dir); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result crypto_aes_ccm_enc_final(struct crypto_authenc_ctx *aectx, + const uint8_t *src_data, + size_t len, uint8_t *dst_data, + uint8_t *dst_tag, + size_t *dst_tag_len) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); + int ltc_res = 0; + + /* Finalize the remaining buffer */ + res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data, + len, dst_data); + if (res != TEE_SUCCESS) + return res; + + /* Check the tag length */ + if (*dst_tag_len < ccm->tag_len) { + *dst_tag_len = ccm->tag_len; + return TEE_ERROR_SHORT_BUFFER; + } + *dst_tag_len = ccm->tag_len; + + /* Compute the tag */ + ltc_res = ccm_done(&ccm->ctx, dst_tag, + (unsigned long *)dst_tag_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result crypto_aes_ccm_dec_final(struct crypto_authenc_ctx *aectx, + const uint8_t *src_data, size_t len, + uint8_t *dst_data, + const uint8_t *tag, size_t tag_len) +{ + TEE_Result res = TEE_ERROR_BAD_STATE; + struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); + int ltc_res = 0; + uint8_t dst_tag[TEE_CCM_TAG_MAX_LENGTH] = { 0 }; + unsigned long ltc_tag_len = tag_len; + + if (tag_len == 0) + return TEE_ERROR_SHORT_BUFFER; + if (tag_len > TEE_CCM_TAG_MAX_LENGTH) + return TEE_ERROR_BAD_STATE; + + /* Process the last buffer, if any */ + res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_DECRYPT, src_data, + len, dst_data); + if (res != TEE_SUCCESS) + return res; + + /* Finalize the authentication */ + ltc_res = ccm_done(&ccm->ctx, dst_tag, <c_tag_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + if (consttime_memcmp(dst_tag, tag, tag_len) != 0) + res = TEE_ERROR_MAC_INVALID; + else + res = TEE_SUCCESS; + return res; +} + +static void crypto_aes_ccm_final(struct crypto_authenc_ctx *aectx) +{ + ccm_reset(&to_tee_ccm_state(aectx)->ctx); +} + +static const struct crypto_authenc_ops aes_ccm_ops = { + .init = crypto_aes_ccm_init, + .update_aad = crypto_aes_ccm_update_aad, + .update_payload = crypto_aes_ccm_update_payload, + .enc_final = crypto_aes_ccm_enc_final, + .dec_final = crypto_aes_ccm_dec_final, + .final = crypto_aes_ccm_final, + .free_ctx = crypto_aes_ccm_free_ctx, + .copy_state = crypto_aes_ccm_copy_state, +}; diff --git a/optee/optee_os/core/lib/libtomcrypt/cmac.c b/optee/optee_os/core/lib/libtomcrypt/cmac.c new file mode 100644 index 0000000..e8cad3c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/cmac.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + * Copyright (c) 2021, SumUp Services GmbH + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ltc_omac_ctx { + struct crypto_mac_ctx ctx; + int cipher_idx; + omac_state state; +}; + +static const struct crypto_mac_ops ltc_omac_ops; + +static struct ltc_omac_ctx *to_omac_ctx(struct crypto_mac_ctx *ctx) +{ + assert(ctx && ctx->ops == <c_omac_ops); + + return container_of(ctx, struct ltc_omac_ctx, ctx); +} + +static TEE_Result ltc_omac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, + size_t len) +{ + struct ltc_omac_ctx *hc = to_omac_ctx(ctx); + + if (omac_init(&hc->state, hc->cipher_idx, key, len) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_omac_update(struct crypto_mac_ctx *ctx, + const uint8_t *data, size_t len) +{ + if (omac_process(&to_omac_ctx(ctx)->state, data, len) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_omac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, + size_t len) +{ + unsigned long l = len; + + if (omac_done(&to_omac_ctx(ctx)->state, digest, &l) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static void ltc_omac_free_ctx(struct crypto_mac_ctx *ctx) +{ + free(to_omac_ctx(ctx)); +} + +static void ltc_omac_copy_state(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx) +{ + struct ltc_omac_ctx *src = to_omac_ctx(src_ctx); + struct ltc_omac_ctx *dst = to_omac_ctx(dst_ctx); + + assert(src->cipher_idx == dst->cipher_idx); + dst->state = src->state; +} + +static const struct crypto_mac_ops ltc_omac_ops = { + .init = ltc_omac_init, + .update = ltc_omac_update, + .final = ltc_omac_final, + .free_ctx = ltc_omac_free_ctx, + .copy_state = ltc_omac_copy_state, +}; + +static TEE_Result crypto_common_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, + const char *cipher) +{ + struct ltc_omac_ctx *ctx = NULL; + int cipher_idx = find_cipher(cipher); + + if (!ctx_ret) + return TEE_ERROR_BAD_PARAMETERS; + + if (cipher_idx < 0) + return TEE_ERROR_NOT_SUPPORTED; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + ctx->ctx.ops = <c_omac_ops; + ctx->cipher_idx = cipher_idx; + *ctx_ret = &ctx->ctx; + + return TEE_SUCCESS; +} + +TEE_Result crypto_aes_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) +{ + return crypto_common_cmac_alloc_ctx(ctx_ret, "aes"); +} + +TEE_Result crypto_des3_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) +{ + return crypto_common_cmac_alloc_ctx(ctx_ret, "3des"); +} diff --git a/optee/optee_os/core/lib/libtomcrypt/ctr.c b/optee/optee_os/core/lib/libtomcrypt/ctr.c new file mode 100644 index 0000000..1462f23 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/ctr.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +struct ltc_ctr_ctx { + struct crypto_cipher_ctx ctx; + int cipher_idx; + int (*update)(const unsigned char *src, unsigned char *dst, + unsigned long len, symmetric_CTR *ctr); + symmetric_CTR state; +}; + +static const struct crypto_cipher_ops ltc_ctr_ops; + +static struct ltc_ctr_ctx *to_ctr_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == <c_ctr_ops); + + return container_of(ctx, struct ltc_ctr_ctx, ctx); +} + +static TEE_Result ltc_ctr_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct ltc_ctr_ctx *c = to_ctr_ctx(ctx); + + if ((int)iv_len != cipher_descriptor[c->cipher_idx]->block_length) + return TEE_ERROR_BAD_PARAMETERS; + + if (mode == TEE_MODE_ENCRYPT) + c->update = ctr_encrypt; + else + c->update = ctr_decrypt; + + if (ctr_start(c->cipher_idx, iv, key1, key1_len, 0, + CTR_COUNTER_BIG_ENDIAN, &c->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_ctr_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, uint8_t *dst) +{ + struct ltc_ctr_ctx *c = to_ctr_ctx(ctx); + + if (c->update && c->update(data, dst, len, &c->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static void ltc_ctr_final(struct crypto_cipher_ctx *ctx) +{ + ctr_done(&to_ctr_ctx(ctx)->state); +} + +static void ltc_ctr_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_ctr_ctx(ctx)); +} + +static void ltc_ctr_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct ltc_ctr_ctx *src = to_ctr_ctx(src_ctx); + struct ltc_ctr_ctx *dst = to_ctr_ctx(dst_ctx); + + assert(src->cipher_idx == dst->cipher_idx); + dst->update = src->update; + dst->state = src->state; +} + +static const struct crypto_cipher_ops ltc_ctr_ops = { + .init = ltc_ctr_init, + .update = ltc_ctr_update, + .final = ltc_ctr_final, + .free_ctx = ltc_ctr_free_ctx, + .copy_state = ltc_ctr_copy_state, +}; + +TEE_Result crypto_aes_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct ltc_ctr_ctx *c = NULL; + int cipher_idx = find_cipher("aes"); + + if (cipher_idx < 0) + return TEE_ERROR_NOT_SUPPORTED; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = <c_ctr_ops; + c->cipher_idx = cipher_idx; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/des2_key.h b/optee/optee_os/core/lib/libtomcrypt/des2_key.h new file mode 100644 index 0000000..1835a27 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/des2_key.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +static inline void get_des2_key(const uint8_t **key, size_t *key_len, + uint8_t *tmp) +{ + 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(tmp, *key, 16); + memcpy(tmp + 16, *key, 8); + *key = tmp; + *key_len = 24; + } +} diff --git a/optee/optee_os/core/lib/libtomcrypt/dh.c b/optee/optee_os/core/lib/libtomcrypt/dh.c new file mode 100644 index 0000000..4eb9916 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/dh.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + +TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->g)) + return TEE_ERROR_OUT_OF_MEMORY; + if (!bn_alloc_max(&s->p)) + goto err; + if (!bn_alloc_max(&s->y)) + goto err; + if (!bn_alloc_max(&s->x)) + goto err; + if (!bn_alloc_max(&s->q)) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->g); + crypto_bignum_free(s->p); + crypto_bignum_free(s->y); + crypto_bignum_free(s->x); + return TEE_ERROR_OUT_OF_MEMORY; +} + +TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q, + size_t xbits, size_t key_size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + dh_key ltc_tmp_key = { }; + int ltc_res = 0; + + if (key_size != 8 * mp_unsigned_bin_size(key->p)) + return TEE_ERROR_BAD_PARAMETERS; + + ltc_res = mp_init_multi(<c_tmp_key.base, <c_tmp_key.prime, NULL); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Generate the DH key */ + mp_copy(key->g, ltc_tmp_key.base); + mp_copy(key->p, ltc_tmp_key.prime); + ltc_res = dh_make_key(NULL, find_prng("prng_crypto"), q, xbits, + <c_tmp_key); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + ltc_mp.copy(ltc_tmp_key.y, key->y); + ltc_mp.copy(ltc_tmp_key.x, key->x); + res = TEE_SUCCESS; + } + + dh_free(<c_tmp_key); + return res; +} + +TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, + struct bignum *public_key, + struct bignum *secret) +{ + int err; + + if (!private_key || !public_key || !secret) + return TEE_ERROR_BAD_PARAMETERS; + + err = mp_exptmod(public_key, private_key->x, private_key->p, secret); + return ((err == CRYPT_OK) ? TEE_SUCCESS : TEE_ERROR_BAD_PARAMETERS); + +} diff --git a/optee/optee_os/core/lib/libtomcrypt/dsa.c b/optee/optee_os/core/lib/libtomcrypt/dsa.c new file mode 100644 index 0000000..a2dc720 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/dsa.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + +TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->g)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (!bn_alloc_max(&s->p)) + goto err; + if (!bn_alloc_max(&s->q)) + goto err; + if (!bn_alloc_max(&s->y)) + goto err; + if (!bn_alloc_max(&s->x)) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->g); + crypto_bignum_free(s->p); + crypto_bignum_free(s->q); + crypto_bignum_free(s->y); + return TEE_ERROR_OUT_OF_MEMORY; +} + +TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->g)) + return TEE_ERROR_OUT_OF_MEMORY; + + if (!bn_alloc_max(&s->p)) + goto err; + if (!bn_alloc_max(&s->q)) + goto err; + if (!bn_alloc_max(&s->y)) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->g); + crypto_bignum_free(s->p); + crypto_bignum_free(s->q); + return TEE_ERROR_OUT_OF_MEMORY; +} + +TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size) +{ + dsa_key ltc_tmp_key = { }; + int ltc_res = 0; + + if (key_size != 8 * mp_unsigned_bin_size(key->p)) + return TEE_ERROR_BAD_PARAMETERS; + + ltc_res = mp_init_multi(<c_tmp_key.g, <c_tmp_key.p, <c_tmp_key.q, + <c_tmp_key.x, <c_tmp_key.y, NULL); + if (ltc_res) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Copy the key parameters */ + mp_copy(key->g, ltc_tmp_key.g); + mp_copy(key->p, ltc_tmp_key.p); + mp_copy(key->q, ltc_tmp_key.q); + + /* Generate the DSA key */ + ltc_res = dsa_generate_key(NULL, find_prng("prng_crypto"), + <c_tmp_key); + if (ltc_res) + return TEE_ERROR_BAD_PARAMETERS; + + /* Copy the key */ + mp_copy(ltc_tmp_key.y, key->y); + mp_copy(ltc_tmp_key.x, key->x); + + /* Free the temporary key */ + dsa_free(<c_tmp_key); + + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + TEE_Result res; + size_t hash_size; + int ltc_res; + void *r, *s; + dsa_key ltc_key = { + .type = PK_PRIVATE, + .qord = mp_unsigned_bin_size(key->q), + .g = key->g, + .p = key->p, + .q = key->q, + .y = key->y, + .x = key->x, + }; + + if (algo != TEE_ALG_DSA_SHA1 && + algo != TEE_ALG_DSA_SHA224 && + algo != TEE_ALG_DSA_SHA256) { + res = TEE_ERROR_NOT_IMPLEMENTED; + goto err; + } + + res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), + &hash_size); + if (res != TEE_SUCCESS) + goto err; + if (mp_unsigned_bin_size(ltc_key.q) < hash_size) + hash_size = mp_unsigned_bin_size(ltc_key.q); + if (msg_len != hash_size) { + res = TEE_ERROR_SECURITY; + goto err; + } + + if (*sig_len < 2 * mp_unsigned_bin_size(ltc_key.q)) { + *sig_len = 2 * mp_unsigned_bin_size(ltc_key.q); + res = TEE_ERROR_SHORT_BUFFER; + goto err; + } + + ltc_res = mp_init_multi(&r, &s, NULL); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + ltc_res = dsa_sign_hash_raw(msg, msg_len, r, s, NULL, + find_prng("prng_crypto"), <c_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); + +err: + return res; +} + +TEE_Result crypto_acipher_dsa_verify(uint32_t algo, struct dsa_public_key *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; + dsa_key ltc_key = { + .type = PK_PUBLIC, + .qord = mp_unsigned_bin_size(key->q), + .g = key->g, + .p = key->p, + .q = key->q, + .y = key->y + }; + + if (algo != TEE_ALG_DSA_SHA1 && + algo != TEE_ALG_DSA_SHA224 && + algo != TEE_ALG_DSA_SHA256) { + res = TEE_ERROR_NOT_IMPLEMENTED; + goto err; + } + + ltc_res = mp_init_multi(&r, &s, NULL); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + 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, <c_key); + mp_clear_multi(r, s, NULL); + res = convert_ltc_verify_status(ltc_res, ltc_stat); +err: + return res; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/ecb.c b/optee/optee_os/core/lib/libtomcrypt/ecb.c new file mode 100644 index 0000000..c57f502 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/ecb.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "des2_key.h" + +struct ltc_ecb_ctx { + struct crypto_cipher_ctx ctx; + int cipher_idx; + bool des3; + int (*update)(const unsigned char *src, unsigned char *dst, + unsigned long len, symmetric_ECB *ecb); + symmetric_ECB state; +}; + +static const struct crypto_cipher_ops ltc_ecb_ops; + +static struct ltc_ecb_ctx *to_ecb_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == <c_ecb_ops); + + return container_of(ctx, struct ltc_ecb_ctx, ctx); +} + +static TEE_Result ltc_ecb_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct ltc_ecb_ctx *c = to_ecb_ctx(ctx); + uint8_t tmp[24] = { 0 }; + const uint8_t *k = key1; + size_t kl = key1_len; + + if (mode == TEE_MODE_ENCRYPT) + c->update = ecb_encrypt; + else + c->update = ecb_decrypt; + + if (c->des3) + get_des2_key(&k, &kl, tmp); + + if (ecb_start(c->cipher_idx, k, kl, 0, &c->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_ecb_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, uint8_t *dst) +{ + struct ltc_ecb_ctx *c = to_ecb_ctx(ctx); + + if (c->update && c->update(data, dst, len, &c->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static void ltc_ecb_final(struct crypto_cipher_ctx *ctx) +{ + ecb_done(&to_ecb_ctx(ctx)->state); +} + +static void ltc_ecb_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_ecb_ctx(ctx)); +} + +static void ltc_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct ltc_ecb_ctx *src = to_ecb_ctx(src_ctx); + struct ltc_ecb_ctx *dst = to_ecb_ctx(dst_ctx); + + assert(src->cipher_idx == dst->cipher_idx); + dst->update = src->update; + dst->state = src->state; +} + +static const struct crypto_cipher_ops ltc_ecb_ops = { + .init = ltc_ecb_init, + .update = ltc_ecb_update, + .final = ltc_ecb_final, + .free_ctx = ltc_ecb_free_ctx, + .copy_state = ltc_ecb_copy_state, +}; + +static TEE_Result ltc_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret, + int cipher_idx, bool des3) +{ + struct ltc_ecb_ctx *c = NULL; + + if (cipher_idx < 0) + return TEE_ERROR_NOT_SUPPORTED; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = <c_ecb_ops; + c->cipher_idx = cipher_idx; + c->des3 = des3; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} + +#if defined(_CFG_CORE_LTC_AES) +TEE_Result crypto_aes_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx) +{ + return ltc_ecb_alloc_ctx(ctx, find_cipher("aes"), false); +} +#endif + +#if defined(_CFG_CORE_LTC_DES) +TEE_Result crypto_des_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx) +{ + return ltc_ecb_alloc_ctx(ctx, find_cipher("des"), false); +} + +TEE_Result crypto_des3_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx) +{ + return ltc_ecb_alloc_ctx(ctx, find_cipher("3des"), true); +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/ecc.c b/optee/optee_os/core/lib/libtomcrypt/ecc.c new file mode 100644 index 0000000..529b477 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/ecc.c @@ -0,0 +1,542 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + +static void _ltc_ecc_free_public_key(struct ecc_public_key *s) +{ + if (!s) + return; + + crypto_bignum_free(s->x); + crypto_bignum_free(s->y); +} + +/* + * For a given TEE @curve, return key size and LTC curve name. Also check that + * @algo is compatible with this curve. + * @curve: TEE_ECC_CURVE_NIST_P192, ... + * @algo: TEE_ALG_ECDSA_SHA1, ... + */ +static TEE_Result ecc_get_curve_info(uint32_t curve, uint32_t algo, + size_t *key_size_bytes, + size_t *key_size_bits, + const char **curve_name) +{ + size_t size_bytes = 0; + size_t size_bits = 0; + const char *name = NULL; + + /* + * Excerpt of libtomcrypt documentation: + * ecc_make_key(... key_size ...): The keysize is the size of the + * modulus in bytes desired. Currently directly supported values + * are 12, 16, 20, 24, 28, 32, 48, and 65 bytes which correspond + * to key sizes of 112, 128, 160, 192, 224, 256, 384, and 521 bits + * respectively. + */ + + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + size_bits = 192; + size_bytes = 24; + name = "NISTP192"; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA1) && + (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_NIST_P224: + size_bits = 224; + size_bytes = 28; + name = "NISTP224"; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA224) && + (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_NIST_P256: + size_bits = 256; + size_bytes = 32; + name = "NISTP256"; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA256) && + (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_NIST_P384: + size_bits = 384; + size_bytes = 48; + name = "NISTP384"; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA384) && + (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_NIST_P521: + size_bits = 521; + size_bytes = 66; + name = "NISTP521"; + if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA512) && + (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) + return TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_ECC_CURVE_SM2: + size_bits = 256; + size_bytes = 32; + name = "SM2"; + if ((algo != 0) && (algo != TEE_ALG_SM2_PKE) && + (algo != TEE_ALG_SM2_DSA_SM3) && + (algo != TEE_ALG_SM2_KEP)) + return TEE_ERROR_BAD_PARAMETERS; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + if (key_size_bytes) + *key_size_bytes = size_bytes; + if (key_size_bits) + *key_size_bits = size_bits; + if (curve_name) + *curve_name = name; + return TEE_SUCCESS; +} + +/* Note: this function clears the key before setting the curve */ +static TEE_Result ecc_set_curve_from_name(ecc_key *ltc_key, + const char *curve_name) +{ + const ltc_ecc_curve *curve = NULL; + int ltc_res = 0; + + ltc_res = ecc_find_curve(curve_name, &curve); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_NOT_SUPPORTED; + + ltc_res = ecc_set_curve(curve, ltc_key); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result _ltc_ecc_generate_keypair(struct ecc_keypair *key, + size_t key_size) +{ + TEE_Result res; + ecc_key ltc_tmp_key; + int ltc_res; + size_t key_size_bytes = 0; + size_t key_size_bits = 0; + const char *name = NULL; + + res = ecc_get_curve_info(key->curve, 0, &key_size_bytes, &key_size_bits, + &name); + if (res != TEE_SUCCESS) + return res; + + if (key_size != key_size_bits) + return TEE_ERROR_BAD_PARAMETERS; + + res = ecc_set_curve_from_name(<c_tmp_key, name); + if (res) + return res; + + /* Generate the ECC key */ + ltc_res = ecc_generate_key(NULL, find_prng("prng_crypto"), + <c_tmp_key); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + /* check the size of the keys */ + if (((size_t)mp_count_bits(ltc_tmp_key.pubkey.x) > key_size_bits) || + ((size_t)mp_count_bits(ltc_tmp_key.pubkey.y) > key_size_bits) || + ((size_t)mp_count_bits(ltc_tmp_key.k) > key_size_bits)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + /* check LTC is returning z==1 */ + if (mp_count_bits(ltc_tmp_key.pubkey.z) != 1) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + /* Copy the key */ + ltc_mp.copy(ltc_tmp_key.k, key->d); + ltc_mp.copy(ltc_tmp_key.pubkey.x, key->x); + ltc_mp.copy(ltc_tmp_key.pubkey.y, key->y); + + res = TEE_SUCCESS; + +exit: + ecc_free(<c_tmp_key); /* Free the temporary key */ + return res; +} + +/* + * Given a keypair "key", populate the Libtomcrypt private key "ltc_key" + * It also returns the key size, in bytes + */ +TEE_Result ecc_populate_ltc_private_key(ecc_key *ltc_key, + struct ecc_keypair *key, + uint32_t algo, size_t *key_size_bytes) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const char *name = NULL; + + res = ecc_get_curve_info(key->curve, algo, key_size_bytes, NULL, &name); + if (res) + return res; + + memset(ltc_key, 0, sizeof(*ltc_key)); + + res = ecc_set_curve_from_name(ltc_key, name); + if (res) + return res; + + ltc_key->type = PK_PRIVATE; + mp_copy(key->d, ltc_key->k); + mp_copy(key->x, ltc_key->pubkey.x); + mp_copy(key->y, ltc_key->pubkey.y); + mp_set_int(ltc_key->pubkey.z, 1); + + return TEE_SUCCESS; +} + +/* + * Given a public "key", populate the Libtomcrypt public key "ltc_key" + * It also returns the key size, in bytes + */ +TEE_Result ecc_populate_ltc_public_key(ecc_key *ltc_key, + struct ecc_public_key *key, + uint32_t algo, size_t *key_size_bytes) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const char *name = NULL; + uint8_t one[1] = { 1 }; + + res = ecc_get_curve_info(key->curve, algo, key_size_bytes, NULL, &name); + if (res) + return res; + + memset(ltc_key, 0, sizeof(*ltc_key)); + + res = ecc_set_curve_from_name(ltc_key, name); + if (res) + return res; + + ltc_key->type = PK_PUBLIC; + + mp_copy(key->x, ltc_key->pubkey.x); + mp_copy(key->y, ltc_key->pubkey.y); + mp_read_unsigned_bin(ltc_key->pubkey.z, one, sizeof(one)); + + return TEE_SUCCESS; +} + +static TEE_Result _ltc_ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int ltc_res = 0; + size_t key_size_bytes = 0; + ecc_key ltc_key = { }; + unsigned long ltc_sig_len = 0; + + if (algo == 0) + return TEE_ERROR_BAD_PARAMETERS; + + res = ecc_populate_ltc_private_key(<c_key, key, algo, + &key_size_bytes); + if (res != TEE_SUCCESS) + return res; + + if (*sig_len < 2 * key_size_bytes) { + *sig_len = 2 * key_size_bytes; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + ltc_sig_len = *sig_len; + ltc_res = ecc_sign_hash_rfc7518(msg, msg_len, sig, <c_sig_len, + NULL, find_prng("prng_crypto"), <c_key); + if (ltc_res == CRYPT_OK) { + res = TEE_SUCCESS; + } else { + res = TEE_ERROR_GENERIC; + } + *sig_len = ltc_sig_len; + +out: + ecc_free(<c_key); + return res; +} + +static TEE_Result _ltc_ecc_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int ltc_stat = 0; + int ltc_res = 0; + size_t key_size_bytes = 0; + ecc_key ltc_key = { }; + + if (algo == 0) + return TEE_ERROR_BAD_PARAMETERS; + + res = ecc_populate_ltc_public_key(<c_key, key, algo, &key_size_bytes); + if (res != TEE_SUCCESS) + goto out; + + /* check keysize vs sig_len */ + if ((key_size_bytes * 2) != sig_len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + ltc_res = ecc_verify_hash_rfc7518(sig, sig_len, msg, msg_len, <c_stat, + <c_key); + res = convert_ltc_verify_status(ltc_res, ltc_stat); +out: + ecc_free(<c_key); + return res; +} + +static TEE_Result _ltc_ecc_shared_secret(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, + unsigned long *secret_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int ltc_res = 0; + ecc_key ltc_private_key = { }; + ecc_key ltc_public_key = { }; + size_t key_size_bytes = 0; + + /* Check the curves are the same */ + if (private_key->curve != public_key->curve) + return TEE_ERROR_BAD_PARAMETERS; + + res = ecc_populate_ltc_private_key(<c_private_key, private_key, + 0, &key_size_bytes); + if (res != TEE_SUCCESS) + goto out; + res = ecc_populate_ltc_public_key(<c_public_key, public_key, + 0, &key_size_bytes); + if (res != TEE_SUCCESS) + goto out; + + ltc_res = ecc_shared_secret(<c_private_key, <c_public_key, + secret, secret_len); + if (ltc_res == CRYPT_OK) + res = TEE_SUCCESS; + else + res = TEE_ERROR_BAD_PARAMETERS; + +out: + ecc_free(<c_private_key); + ecc_free(<c_public_key); + return res; +} + +static const struct crypto_ecc_keypair_ops ecc_keypair_ops = { + .generate = _ltc_ecc_generate_keypair, + .sign = _ltc_ecc_sign, + .shared_secret = _ltc_ecc_shared_secret, +}; + +static const struct crypto_ecc_public_ops ecc_public_key_ops = { + .free = _ltc_ecc_free_public_key, + .verify = _ltc_ecc_verify, +}; + +static const struct crypto_ecc_keypair_ops sm2_dsa_keypair_ops = { + .generate = _ltc_ecc_generate_keypair, + .sign = sm2_ltc_dsa_sign, +}; + +static const struct crypto_ecc_public_ops sm2_dsa_public_key_ops = { + .free = _ltc_ecc_free_public_key, + .verify = sm2_ltc_dsa_verify, +}; + +static const struct crypto_ecc_keypair_ops sm2_pke_keypair_ops = { + .generate = _ltc_ecc_generate_keypair, + .decrypt = sm2_ltc_pke_decrypt, +}; + +static const struct crypto_ecc_public_ops sm2_pke_public_key_ops = { + .free = _ltc_ecc_free_public_key, + .encrypt = sm2_ltc_pke_encrypt, +}; + +static const struct crypto_ecc_keypair_ops sm2_kep_keypair_ops = { + .generate = _ltc_ecc_generate_keypair, +}; + +static const struct crypto_ecc_public_ops sm2_kep_public_key_ops = { + .free = _ltc_ecc_free_public_key, +}; + +const struct crypto_ecc_keypair_ops * +crypto_asym_get_ecc_keypair_ops( uint32_t key_type) +{ + switch (key_type) { + case TEE_TYPE_ECDSA_KEYPAIR: + case TEE_TYPE_ECDH_KEYPAIR: + return &ecc_keypair_ops; + case TEE_TYPE_SM2_DSA_KEYPAIR: + if (!IS_ENABLED(_CFG_CORE_LTC_SM2_DSA)) + return NULL; + return &sm2_dsa_keypair_ops; + case TEE_TYPE_SM2_PKE_KEYPAIR: + if (!IS_ENABLED(_CFG_CORE_LTC_SM2_PKE)) + return NULL; + return &sm2_pke_keypair_ops; + case TEE_TYPE_SM2_KEP_KEYPAIR: + if (!IS_ENABLED(_CFG_CORE_LTC_SM2_KEP)) + return NULL; + return &sm2_kep_keypair_ops; + default: + return NULL; + } +} + +TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *s, + uint32_t key_type, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + + switch (key_type) { + case TEE_TYPE_ECDSA_KEYPAIR: + case TEE_TYPE_ECDH_KEYPAIR: + s->ops = &ecc_keypair_ops; + break; + case TEE_TYPE_SM2_DSA_KEYPAIR: + if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_DSA)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_dsa_keypair_ops; + break; + case TEE_TYPE_SM2_PKE_KEYPAIR: + if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_PKE)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_pke_keypair_ops; + break; + case TEE_TYPE_SM2_KEP_KEYPAIR: + if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_KEP)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_kep_keypair_ops; + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + + if (!bn_alloc_max(&s->d)) + goto err; + if (!bn_alloc_max(&s->x)) + goto err; + if (!bn_alloc_max(&s->y)) + goto err; + + return TEE_SUCCESS; + +err: + s->ops = NULL; + + crypto_bignum_free(s->d); + crypto_bignum_free(s->x); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +const struct crypto_ecc_public_ops* +crypto_asym_get_ecc_public_ops(uint32_t key_type) +{ + switch (key_type) { + case TEE_TYPE_ECDSA_PUBLIC_KEY: + case TEE_TYPE_ECDH_PUBLIC_KEY: + return &ecc_public_key_ops; + case TEE_TYPE_SM2_DSA_PUBLIC_KEY: + if (!IS_ENABLED(_CFG_CORE_LTC_SM2_DSA)) + return NULL; + return &sm2_dsa_public_key_ops; + case TEE_TYPE_SM2_PKE_PUBLIC_KEY: + if (!IS_ENABLED(_CFG_CORE_LTC_SM2_PKE)) + return NULL; + return &sm2_pke_public_key_ops; + case TEE_TYPE_SM2_KEP_PUBLIC_KEY: + if (!IS_ENABLED(_CFG_CORE_LTC_SM2_KEP)) + return NULL; + return &sm2_kep_public_key_ops; + default: + return NULL; + } +} + +TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *s, + uint32_t key_type, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + + switch (key_type) { + case TEE_TYPE_ECDSA_PUBLIC_KEY: + case TEE_TYPE_ECDH_PUBLIC_KEY: + s->ops = &ecc_public_key_ops; + break; + case TEE_TYPE_SM2_DSA_PUBLIC_KEY: + if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_DSA)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_dsa_public_key_ops; + break; + case TEE_TYPE_SM2_PKE_PUBLIC_KEY: + if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_PKE)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_pke_public_key_ops; + break; + case TEE_TYPE_SM2_KEP_PUBLIC_KEY: + if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_KEP)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_kep_public_key_ops; + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + + if (!bn_alloc_max(&s->x)) + goto err; + if (!bn_alloc_max(&s->y)) + goto err; + + return TEE_SUCCESS; + +err: + s->ops = NULL; + + crypto_bignum_free(s->x); + + return TEE_ERROR_OUT_OF_MEMORY; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/ed25519.c b/optee/optee_os/core/lib/libtomcrypt/ed25519.c new file mode 100644 index 0000000..763c097 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/ed25519.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Technology Innovation Institute (TII) + * Copyright (c) 2022, EPAM Systems + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + +#define ED25519_KEY_SIZE UL(256) + +TEE_Result crypto_acipher_alloc_ed25519_keypair(struct ed25519_keypair *key, + size_t key_size) +{ + if (!key || key_size != ED25519_KEY_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + memset(key, 0, sizeof(*key)); + + key->priv = calloc(1, key_size >> 3); + key->pub = calloc(1, key_size >> 3); + + if (!key->priv || !key->pub) { + free(key->priv); + free(key->pub); + return TEE_ERROR_OUT_OF_MEMORY; + } + + return TEE_SUCCESS; +} + +TEE_Result +crypto_acipher_alloc_ed25519_public_key(struct ed25519_public_key *key, + size_t key_size) +{ + if (!key || key_size != ED25519_KEY_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + memset(key, 0, sizeof(*key)); + + key->pub = calloc(1, key_size >> 3); + + if (!key->pub) + return TEE_ERROR_OUT_OF_MEMORY; + + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_gen_ed25519_key(struct ed25519_keypair *key, + size_t key_size) +{ + curve25519_key ltc_tmp_key = { }; + + if (key_size != ED25519_KEY_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + if (ed25519_make_key(NULL, find_prng("prng_crypto"), + <c_tmp_key) != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + assert(key_size >= sizeof(ltc_tmp_key.pub) && + key_size >= sizeof(ltc_tmp_key.priv)); + + memcpy(key->pub, ltc_tmp_key.pub, sizeof(ltc_tmp_key.pub)); + memcpy(key->priv, ltc_tmp_key.priv, sizeof(ltc_tmp_key.priv)); + memzero_explicit(<c_tmp_key, sizeof(ltc_tmp_key)); + + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_ed25519_sign(struct ed25519_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + int err; + unsigned long siglen = 0; + curve25519_key private_key = { + .type = PK_PRIVATE, + .algo = LTC_OID_ED25519, + }; + + if (!key || !sig_len) + return TEE_ERROR_BAD_PARAMETERS; + + siglen = *sig_len; + + memcpy(private_key.priv, key->priv, sizeof(private_key.priv)); + memcpy(private_key.pub, key->pub, sizeof(private_key.pub)); + + err = ed25519_sign(msg, msg_len, sig, &siglen, &private_key); + + memzero_explicit(&private_key, sizeof(private_key)); + + if (err != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + *sig_len = siglen; + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_ed25519ctx_sign(struct ed25519_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len, + bool ph_flag, + const uint8_t *ctx, size_t ctxlen) +{ + int err = CRYPT_ERROR; + unsigned long siglen = 0; + curve25519_key private_key = { + .type = PK_PRIVATE, + .algo = LTC_OID_ED25519, + }; + + if (!key || !sig_len) + return TEE_ERROR_BAD_PARAMETERS; + + siglen = *sig_len; + + memcpy(private_key.priv, key->priv, sizeof(private_key.priv)); + memcpy(private_key.pub, key->pub, sizeof(private_key.pub)); + + if (ph_flag) { + err = ed25519ph_sign(msg, msg_len, sig, &siglen, + ctx, ctxlen, &private_key); + } else { + err = ed25519ctx_sign(msg, msg_len, sig, &siglen, + ctx, ctxlen, &private_key); + } + + memzero_explicit(&private_key, sizeof(private_key)); + + if (err != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + *sig_len = siglen; + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_ed25519_verify(struct ed25519_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + int stat = 0; + curve25519_key public_key = { + .type = PK_PUBLIC, + .algo = LTC_OID_ED25519, + }; + + if (!key) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(public_key.pub, key->pub, sizeof(public_key.pub)); + + if (ed25519_verify(msg, msg_len, sig, sig_len, &stat, + &public_key) != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + if (stat != 1) + return TEE_ERROR_SIGNATURE_INVALID; + + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_ed25519ctx_verify(struct ed25519_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len, + bool ph_flag, + const uint8_t *ctx, size_t ctxlen) +{ + int stat = 0; + curve25519_key public_key = { + .type = PK_PUBLIC, + .algo = LTC_OID_ED25519, + }; + + if (!key) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(public_key.pub, key->pub, sizeof(public_key.pub)); + + if (ph_flag) { + if (ed25519ph_verify(msg, msg_len, sig, sig_len, ctx, ctxlen, + &stat, &public_key) != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + } else { + if (ed25519ctx_verify(msg, msg_len, sig, sig_len, ctx, ctxlen, + &stat, &public_key) != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + } + + if (stat != 1) + return TEE_ERROR_SIGNATURE_INVALID; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/gcm.c b/optee/optee_os/core/lib/libtomcrypt/gcm.c new file mode 100644 index 0000000..b6848c7 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/gcm.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEE_GCM_TAG_MAX_LENGTH 16 + +struct tee_gcm_state { + struct crypto_authenc_ctx aectx; + gcm_state ctx; /* the gcm state as defined by LTC */ + size_t tag_len; /* tag length */ +}; + +static const struct crypto_authenc_ops aes_gcm_ops; + +static struct tee_gcm_state *to_tee_gcm_state(struct crypto_authenc_ctx *aectx) +{ + assert(aectx && aectx->ops == &aes_gcm_ops); + + return container_of(aectx, struct tee_gcm_state, aectx); +} + +TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret) +{ + struct tee_gcm_state *ctx = calloc(1, sizeof(*ctx)); + + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + ctx->aectx.ops = &aes_gcm_ops; + + *ctx_ret = &ctx->aectx; + + return TEE_SUCCESS; +} + +static void crypto_aes_gcm_free_ctx(struct crypto_authenc_ctx *aectx) +{ + free(to_tee_gcm_state(aectx)); +} + +static void crypto_aes_gcm_copy_state(struct crypto_authenc_ctx *dst_aectx, + struct crypto_authenc_ctx *src_aectx) +{ + struct tee_gcm_state *dst_ctx = to_tee_gcm_state(dst_aectx); + struct tee_gcm_state *src_ctx = to_tee_gcm_state(src_aectx); + + dst_ctx->ctx = src_ctx->ctx; + dst_ctx->tag_len = src_ctx->tag_len; +} + +static TEE_Result crypto_aes_gcm_init(struct crypto_authenc_ctx *aectx, + TEE_OperationMode mode __unused, + const uint8_t *key, size_t key_len, + const uint8_t *nonce, size_t nonce_len, + size_t tag_len, size_t aad_len __unused, + size_t payload_len __unused) +{ + int ltc_res = 0; + int ltc_cipherindex = find_cipher("aes"); + struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); + + if (ltc_cipherindex < 0) + return TEE_ERROR_NOT_SUPPORTED; + + /* reset the state */ + memset(&gcm->ctx, 0, sizeof(gcm->ctx)); + gcm->tag_len = tag_len; + + ltc_res = gcm_init(&gcm->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->ctx, nonce, nonce_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result crypto_aes_gcm_update_aad(struct crypto_authenc_ctx *aectx, + const uint8_t *data, size_t len) +{ + struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); + int ltc_res = 0; + + /* Add the AAD (note: aad can be NULL if aadlen == 0) */ + ltc_res = gcm_add_aad(&gcm->ctx, data, len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result +crypto_aes_gcm_update_payload(struct crypto_authenc_ctx *aectx, + TEE_OperationMode mode, const uint8_t *src_data, + size_t len, uint8_t *dst_data) +{ + TEE_Result res = TEE_SUCCESS; + int ltc_res = 0; + int dir = 0; + struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); + unsigned char *pt = NULL; + unsigned char *ct = NULL; + + if (mode == TEE_MODE_ENCRYPT) { + pt = (unsigned char *)src_data; + ct = dst_data; + dir = GCM_ENCRYPT; + } else { + pt = dst_data; + ct = (unsigned char *)src_data; + dir = GCM_DECRYPT; + } + + /* aad is optional ==> add one without length */ + if (gcm->ctx.mode == LTC_GCM_MODE_IV) { + res = crypto_aes_gcm_update_aad(aectx, NULL, 0); + if (res != TEE_SUCCESS) + return res; + } + + /* process the data */ + ltc_res = gcm_process(&gcm->ctx, pt, len, ct, dir); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result crypto_aes_gcm_enc_final(struct crypto_authenc_ctx *aectx, + const uint8_t *src_data, size_t len, + uint8_t *dst_data, uint8_t *dst_tag, + size_t *dst_tag_len) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); + int ltc_res = 0; + + /* Finalize the remaining buffer */ + res = crypto_aes_gcm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data, + len, dst_data); + if (res != TEE_SUCCESS) + return res; + + /* Check the tag length */ + if (*dst_tag_len < gcm->tag_len) { + *dst_tag_len = gcm->tag_len; + return TEE_ERROR_SHORT_BUFFER; + } + *dst_tag_len = gcm->tag_len; + + /* Compute the tag */ + ltc_res = gcm_done(&gcm->ctx, dst_tag, (unsigned long *)dst_tag_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result crypto_aes_gcm_dec_final(struct crypto_authenc_ctx *aectx, + const uint8_t *src_data, size_t len, + uint8_t *dst_data, + const uint8_t *tag, size_t tag_len) +{ + TEE_Result res = TEE_ERROR_BAD_STATE; + struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); + int ltc_res = 0; + uint8_t dst_tag[TEE_GCM_TAG_MAX_LENGTH] = { 0 }; + unsigned long ltc_tag_len = tag_len; + + if (tag_len == 0) + return TEE_ERROR_SHORT_BUFFER; + if (tag_len > TEE_GCM_TAG_MAX_LENGTH) + return TEE_ERROR_BAD_STATE; + + /* Process the last buffer, if any */ + res = crypto_aes_gcm_update_payload(aectx, TEE_MODE_DECRYPT, src_data, + len, dst_data); + if (res != TEE_SUCCESS) + return res; + + /* Finalize the authentication */ + ltc_res = gcm_done(&gcm->ctx, dst_tag, <c_tag_len); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_STATE; + + if (consttime_memcmp(dst_tag, tag, tag_len) != 0) + res = TEE_ERROR_MAC_INVALID; + else + res = TEE_SUCCESS; + return res; +} + +static void crypto_aes_gcm_final(struct crypto_authenc_ctx *aectx) +{ + gcm_reset(&to_tee_gcm_state(aectx)->ctx); +} + +static const struct crypto_authenc_ops aes_gcm_ops = { + .init = crypto_aes_gcm_init, + .update_aad = crypto_aes_gcm_update_aad, + .update_payload = crypto_aes_gcm_update_payload, + .enc_final = crypto_aes_gcm_enc_final, + .dec_final = crypto_aes_gcm_dec_final, + .final = crypto_aes_gcm_final, + .free_ctx = crypto_aes_gcm_free_ctx, + .copy_state = crypto_aes_gcm_copy_state, +}; diff --git a/optee/optee_os/core/lib/libtomcrypt/hash.c b/optee/optee_os/core/lib/libtomcrypt/hash.c new file mode 100644 index 0000000..d948eb6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/hash.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * Message digest functions + ******************************************************************************/ + +struct ltc_hash_ctx { + struct crypto_hash_ctx ctx; + const struct ltc_hash_descriptor *descr; + hash_state state; +}; + +static const struct crypto_hash_ops ltc_hash_ops; + +static struct ltc_hash_ctx *to_hash_ctx(struct crypto_hash_ctx *ctx) +{ + assert(ctx && ctx->ops == <c_hash_ops); + + return container_of(ctx, struct ltc_hash_ctx, ctx); +} + +static TEE_Result ltc_hash_init(struct crypto_hash_ctx *ctx) +{ + struct ltc_hash_ctx *hc = to_hash_ctx(ctx); + + if (hc->descr->init(&hc->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_hash_update(struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len) +{ + struct ltc_hash_ctx *hc = to_hash_ctx(ctx); + + if (hc->descr->process(&hc->state, data, len) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_hash_final(struct crypto_hash_ctx *ctx, uint8_t *digest, + size_t len) +{ + struct ltc_hash_ctx *hc = to_hash_ctx(ctx); + size_t hash_size = hc->descr->hashsize; + uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 }; + uint8_t *tmp_digest = NULL; + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (hash_size > len) { + if (hash_size > sizeof(block_digest)) + return TEE_ERROR_BAD_STATE; + tmp_digest = block_digest; /* use a tempory buffer */ + } else { + tmp_digest = digest; + } + + if (hc->descr->done(&hc->state, tmp_digest) == CRYPT_OK) { + if (hash_size > len) + memcpy(digest, tmp_digest, len); + } else { + return TEE_ERROR_BAD_STATE; + } + + return TEE_SUCCESS; +} + +static void ltc_hash_free_ctx(struct crypto_hash_ctx *ctx) +{ + free(to_hash_ctx(ctx)); +} + +static void ltc_hash_copy_state(struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx) +{ + struct ltc_hash_ctx *src = to_hash_ctx(src_ctx); + struct ltc_hash_ctx *dst = to_hash_ctx(dst_ctx); + + assert(src->descr == dst->descr); + dst->state = src->state; +} + +static const struct crypto_hash_ops ltc_hash_ops = { + .init = ltc_hash_init, + .update = ltc_hash_update, + .final = ltc_hash_final, + .free_ctx = ltc_hash_free_ctx, + .copy_state = ltc_hash_copy_state, +}; + +static TEE_Result ltc_hash_alloc_ctx(struct crypto_hash_ctx **ctx_ret, + int ltc_hash_idx) +{ + struct ltc_hash_ctx *ctx = NULL; + + if (ltc_hash_idx < 0) + return TEE_ERROR_NOT_SUPPORTED; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + ctx->ctx.ops = <c_hash_ops; + ctx->descr = hash_descriptor[ltc_hash_idx]; + + *ctx_ret = &ctx->ctx; + + return TEE_SUCCESS; +} + +#if defined(_CFG_CORE_LTC_MD5) +TEE_Result crypto_md5_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("md5")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA1) +TEE_Result crypto_sha1_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha1")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA224) +TEE_Result crypto_sha224_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha224")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA256) +TEE_Result crypto_sha256_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha256")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA384) +TEE_Result crypto_sha384_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha384")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA512) +TEE_Result crypto_sha512_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha512")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA256) +TEE_Result hash_sha256_check(const uint8_t *hash, const uint8_t *data, + size_t data_size) +{ + hash_state hs; + uint8_t digest[TEE_SHA256_HASH_SIZE]; + + if (sha256_init(&hs) != CRYPT_OK) + return TEE_ERROR_GENERIC; + if (sha256_process(&hs, data, data_size) != CRYPT_OK) + return TEE_ERROR_GENERIC; + if (sha256_done(&hs, digest) != CRYPT_OK) + return TEE_ERROR_GENERIC; + if (consttime_memcmp(digest, hash, sizeof(digest)) != 0) + return TEE_ERROR_SECURITY; + return TEE_SUCCESS; +} +#endif + +#if defined(_CFG_CORE_LTC_SHA512_256) +TEE_Result hash_sha512_256_compute(uint8_t *digest, const uint8_t *data, + size_t data_size) +{ + hash_state hs; + + if (sha512_256_init(&hs) != CRYPT_OK) + return TEE_ERROR_GENERIC; + if (sha512_256_process(&hs, data, data_size) != CRYPT_OK) + return TEE_ERROR_GENERIC; + if (sha512_256_done(&hs, digest) != CRYPT_OK) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} +#endif + +#if defined(_CFG_CORE_LTC_SHA3_224) +TEE_Result crypto_sha3_224_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha3-224")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA3_256) +TEE_Result crypto_sha3_256_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha3-256")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA3_384) +TEE_Result crypto_sha3_384_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha3-384")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA3_512) +TEE_Result crypto_sha3_512_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return ltc_hash_alloc_ctx(ctx, find_hash("sha3-512")); +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/hmac.c b/optee/optee_os/core/lib/libtomcrypt/hmac.c new file mode 100644 index 0000000..3aafb0c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/hmac.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ltc_hmac_ctx { + struct crypto_mac_ctx ctx; + int hash_idx; + hmac_state state; +}; + +static const struct crypto_mac_ops ltc_hmac_ops; + +static struct ltc_hmac_ctx *to_hmac_ctx(struct crypto_mac_ctx *ctx) +{ + assert(ctx && ctx->ops == <c_hmac_ops); + + return container_of(ctx, struct ltc_hmac_ctx, ctx); +} + +static TEE_Result ltc_hmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, + size_t len) +{ + struct ltc_hmac_ctx *hc = to_hmac_ctx(ctx); + + if (hmac_init(&hc->state, hc->hash_idx, key, len) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_hmac_update(struct crypto_mac_ctx *ctx, + const uint8_t *data, size_t len) +{ + if (hmac_process(&to_hmac_ctx(ctx)->state, data, len) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, + size_t len) +{ + unsigned long l = len; + + if (hmac_done(&to_hmac_ctx(ctx)->state, digest, &l) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static void ltc_hmac_free_ctx(struct crypto_mac_ctx *ctx) +{ + free(to_hmac_ctx(ctx)); +} + +static void ltc_hmac_copy_state(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx) +{ + struct ltc_hmac_ctx *src = to_hmac_ctx(src_ctx); + struct ltc_hmac_ctx *dst = to_hmac_ctx(dst_ctx); + + assert(src->hash_idx == dst->hash_idx); + dst->state = src->state; +} + +static const struct crypto_mac_ops ltc_hmac_ops = { + .init = ltc_hmac_init, + .update = ltc_hmac_update, + .final = ltc_hmac_final, + .free_ctx = ltc_hmac_free_ctx, + .copy_state = ltc_hmac_copy_state, +}; + +static TEE_Result ltc_hmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, + int hash_idx) +{ + struct ltc_hmac_ctx *ctx = NULL; + + if (hash_idx < 0) + return TEE_ERROR_NOT_SUPPORTED; + + ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + ctx->ctx.ops = <c_hmac_ops; + ctx->hash_idx = hash_idx; + *ctx_ret = &ctx->ctx; + + return TEE_SUCCESS; +} + +#if defined(_CFG_CORE_LTC_MD5) +TEE_Result crypto_hmac_md5_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("md5")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA1) +TEE_Result crypto_hmac_sha1_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha1")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA224) +TEE_Result crypto_hmac_sha224_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha224")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA256) +TEE_Result crypto_hmac_sha256_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha256")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA384) +TEE_Result crypto_hmac_sha384_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha384")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA512) +TEE_Result crypto_hmac_sha512_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha512")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA3_224) +TEE_Result crypto_hmac_sha3_224_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha3-224")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA3_256) +TEE_Result crypto_hmac_sha3_256_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha3-256")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA3_384) +TEE_Result crypto_hmac_sha3_384_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha3-384")); +} +#endif + +#if defined(_CFG_CORE_LTC_SHA3_512) +TEE_Result crypto_hmac_sha3_512_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return ltc_hmac_alloc_ctx(ctx, find_hash("sha3-512")); +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_init.h b/optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_init.h new file mode 100644 index 0000000..ca12322 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_init.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#ifndef __TOMCRYPT_INIT_H +#define __TOMCRYPT_INIT_H + +void tomcrypt_init(void); + +#endif /*__TOMCRYPT_INIT_H*/ diff --git a/optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_mp.h b/optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_mp.h new file mode 100644 index 0000000..fd4df63 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/include/tomcrypt_mp.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TOMCRYPT_MP_H_ +#define TOMCRYPT_MP_H_ + +#if defined(_CFG_CORE_LTC_ACIPHER) +void init_mp_tomcrypt(void); +#else +static inline void init_mp_tomcrypt(void) { } +#endif + +#endif /* TOMCRYPT_MP_H_ */ diff --git a/optee/optee_os/core/lib/libtomcrypt/mpi_desc.c b/optee/optee_os/core/lib/libtomcrypt/mpi_desc.c new file mode 100644 index 0000000..235fbe6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/mpi_desc.c @@ -0,0 +1,779 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_CFG_CORE_LTC_PAGER) +#include +#include +#endif + +/* Size needed for xtest to pass reliably on both ARM32 and ARM64 */ +#define MPI_MEMPOOL_SIZE (46 * 1024) + +/* From mbedtls/library/bignum.c */ +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0)) + +#if defined(_CFG_CORE_LTC_PAGER) +/* allocate pageable_zi vmem for mp scratch memory pool */ +static struct mempool *get_mp_scratch_memory_pool(void) +{ + size_t size; + void *data; + + size = ROUNDUP(MPI_MEMPOOL_SIZE, SMALL_PAGE_SIZE); + data = tee_pager_alloc(size); + if (!data) + panic(); + + return mempool_alloc_pool(data, size, tee_pager_release_phys); +} +#else /* _CFG_CORE_LTC_PAGER */ +static struct mempool *get_mp_scratch_memory_pool(void) +{ + static uint8_t data[MPI_MEMPOOL_SIZE] __aligned(MEMPOOL_ALIGN); + + return mempool_alloc_pool(data, sizeof(data), NULL); +} +#endif + +void init_mp_tomcrypt(void) +{ + struct mempool *p = get_mp_scratch_memory_pool(); + + if (!p) + panic(); + mbedtls_mpi_mempool = p; + assert(!mempool_default); + mempool_default = p; +} + +static int init(void **a) +{ + mbedtls_mpi *bn = mempool_alloc(mbedtls_mpi_mempool, sizeof(*bn)); + + if (!bn) + return CRYPT_MEM; + + mbedtls_mpi_init_mempool(bn); + *a = bn; + return CRYPT_OK; +} + +static int init_size(int size_bits __unused, void **a) +{ + return init(a); +} + +static void deinit(void *a) +{ + mbedtls_mpi_free((mbedtls_mpi *)a); + mempool_free(mbedtls_mpi_mempool, a); +} + +static int neg(void *a, void *b) +{ + if (mbedtls_mpi_copy(b, a)) + return CRYPT_MEM; + ((mbedtls_mpi *)b)->s *= -1; + return CRYPT_OK; +} + +static int copy(void *a, void *b) +{ + if (mbedtls_mpi_copy(b, a)) + return CRYPT_MEM; + 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, ltc_mp_digit b) +{ + uint32_t b32 = b; + + if (b32 != b) + return CRYPT_INVALID_ARG; + + mbedtls_mpi_uint p = b32; + mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p }; + + if (mbedtls_mpi_copy(a, &bn)) + return CRYPT_MEM; + return CRYPT_OK; +} + +static unsigned long get_int(void *a) +{ + mbedtls_mpi *bn = a; + + if (!bn->n) + return 0; + + return bn->p[bn->n - 1]; +} + +static ltc_mp_digit get_digit(void *a, int n) +{ + mbedtls_mpi *bn = a; + + COMPILE_TIME_ASSERT(sizeof(ltc_mp_digit) >= sizeof(mbedtls_mpi_uint)); + + if (n < 0 || (size_t)n >= bn->n) + return 0; + + return bn->p[n]; +} + +static int get_digit_count(void *a) +{ + return ROUNDUP(mbedtls_mpi_size(a), sizeof(mbedtls_mpi_uint)) / + sizeof(mbedtls_mpi_uint); +} + +static int compare(void *a, void *b) +{ + int ret = mbedtls_mpi_cmp_mpi(a, b); + + if (ret < 0) + return LTC_MP_LT; + + if (ret > 0) + return LTC_MP_GT; + + return LTC_MP_EQ; +} + +static int compare_d(void *a, ltc_mp_digit b) +{ + unsigned long v = b; + unsigned int shift = 31; + uint32_t mask = BIT(shift) - 1; + mbedtls_mpi bn; + + mbedtls_mpi_init_mempool(&bn); + while (true) { + mbedtls_mpi_add_int(&bn, &bn, v & mask); + v >>= shift; + if (!v) + break; + mbedtls_mpi_shift_l(&bn, shift); + } + + int ret = compare(a, &bn); + + mbedtls_mpi_free(&bn); + + return ret; +} + +static int count_bits(void *a) +{ + return mbedtls_mpi_bitlen(a); +} + +static int count_lsb_bits(void *a) +{ + return mbedtls_mpi_lsb(a); +} + + +static int twoexpt(void *a, int n) +{ + if (mbedtls_mpi_set_bit(a, n, 1)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +/* ---- conversions ---- */ + +/* read ascii string */ +static int read_radix(void *a, const char *b, int radix) +{ + int res = mbedtls_mpi_read_string(a, radix, b); + + if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) + return CRYPT_MEM; + if (res) + return CRYPT_ERROR; + + return CRYPT_OK; +} + +/* write one */ +static int write_radix(void *a, char *b, int radix) +{ + size_t ol = SIZE_MAX; + int res = mbedtls_mpi_write_string(a, radix, b, ol, &ol); + + if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) + return CRYPT_MEM; + if (res) + return CRYPT_ERROR; + + return CRYPT_OK; +} + +/* get size as unsigned char string */ +static unsigned long unsigned_size(void *a) +{ + return mbedtls_mpi_size(a); +} + +/* store */ +static int unsigned_write(void *a, unsigned char *b) +{ + int res = mbedtls_mpi_write_binary(a, b, unsigned_size(a)); + + if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) + return CRYPT_MEM; + if (res) + return CRYPT_ERROR; + + return CRYPT_OK; +} + +/* read */ +static int unsigned_read(void *a, unsigned char *b, unsigned long len) +{ + int res = mbedtls_mpi_read_binary(a, b, len); + + if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) + return CRYPT_MEM; + if (res) + return CRYPT_ERROR; + + return CRYPT_OK; +} + +/* add */ +static int add(void *a, void *b, void *c) +{ + if (mbedtls_mpi_add_mpi(c, a, b)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +static int addi(void *a, ltc_mp_digit b, void *c) +{ + uint32_t b32 = b; + + if (b32 != b) + return CRYPT_INVALID_ARG; + + mbedtls_mpi_uint p = b32; + mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p }; + + return add(a, &bn, c); +} + +/* sub */ +static int sub(void *a, void *b, void *c) +{ + if (mbedtls_mpi_sub_mpi(c, a, b)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +static int subi(void *a, ltc_mp_digit b, void *c) +{ + uint32_t b32 = b; + + if (b32 != b) + return CRYPT_INVALID_ARG; + + mbedtls_mpi_uint p = b32; + mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p }; + + return sub(a, &bn, c); +} + +/* mul */ +static int mul(void *a, void *b, void *c) +{ + if (mbedtls_mpi_mul_mpi(c, a, b)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +static int muli(void *a, ltc_mp_digit b, void *c) +{ + if (b > (unsigned long) UINT32_MAX) + return CRYPT_INVALID_ARG; + + if (mbedtls_mpi_mul_int(c, a, b)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +/* sqr */ +static int sqr(void *a, void *b) +{ + return mul(a, a, b); +} + +/* div */ +static int divide(void *a, void *b, void *c, void *d) +{ + int res = mbedtls_mpi_div_mpi(c, d, a, b); + + if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) + return CRYPT_MEM; + if (res) + return CRYPT_ERROR; + + return CRYPT_OK; +} + +static int div_2(void *a, void *b) +{ + if (mbedtls_mpi_copy(b, a)) + return CRYPT_MEM; + + if (mbedtls_mpi_shift_r(b, 1)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +/* modi */ +static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) +{ + mbedtls_mpi bn_b; + mbedtls_mpi bn_c; + int res = 0; + + mbedtls_mpi_init_mempool(&bn_b); + mbedtls_mpi_init_mempool(&bn_c); + + res = set_int(&bn_b, b); + if (res) + return res; + + res = mbedtls_mpi_mod_mpi(&bn_c, &bn_b, a); + if (!res) + *c = get_int(&bn_c); + + mbedtls_mpi_free(&bn_b); + mbedtls_mpi_free(&bn_c); + + if (res) + return CRYPT_MEM; + + return CRYPT_OK; +} + +/* gcd */ +static int gcd(void *a, void *b, void *c) +{ + if (mbedtls_mpi_gcd(c, a, b)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +/* lcm */ +static int lcm(void *a, void *b, void *c) +{ + int res = CRYPT_MEM; + mbedtls_mpi tmp; + + mbedtls_mpi_init_mempool(&tmp); + if (mbedtls_mpi_mul_mpi(&tmp, a, b)) + goto out; + + if (mbedtls_mpi_gcd(c, a, b)) + goto out; + + /* We use the following equality: gcd(a, b) * lcm(a, b) = a * b */ + res = divide(&tmp, c, c, NULL); +out: + mbedtls_mpi_free(&tmp); + return res; +} + +static int mod(void *a, void *b, void *c) +{ + int res = mbedtls_mpi_mod_mpi(c, a, b); + + if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) + return CRYPT_MEM; + if (res) + return CRYPT_ERROR; + + return CRYPT_OK; +} + +static int addmod(void *a, void *b, void *c, void *d) +{ + int res = add(a, b, d); + + if (res) + return res; + + return mod(d, c, d); +} + +static int submod(void *a, void *b, void *c, void *d) +{ + int res = sub(a, b, d); + + if (res) + return res; + + return mod(d, c, d); +} + +static int mulmod(void *a, void *b, void *c, void *d) +{ + int res; + mbedtls_mpi ta; + mbedtls_mpi tb; + + mbedtls_mpi_init_mempool(&ta); + mbedtls_mpi_init_mempool(&tb); + + res = mod(a, c, &ta); + if (res) + goto out; + res = mod(b, c, &tb); + if (res) + goto out; + res = mul(&ta, &tb, d); + if (res) + goto out; + res = mod(d, c, d); +out: + mbedtls_mpi_free(&ta); + mbedtls_mpi_free(&tb); + return res; +} + +static int sqrmod(void *a, void *b, void *c) +{ + return mulmod(a, a, b, c); +} + +/* invmod */ +static int invmod(void *a, void *b, void *c) +{ + int res = mbedtls_mpi_inv_mod(c, a, b); + + if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) + return CRYPT_MEM; + if (res) + return CRYPT_ERROR; + + return CRYPT_OK; +} + + +/* setup */ +static int montgomery_setup(void *a, void **b) +{ + *b = mempool_alloc(mbedtls_mpi_mempool, sizeof(mbedtls_mpi_uint)); + if (!*b) + return CRYPT_MEM; + + mbedtls_mpi_montg_init(*b, a); + + return CRYPT_OK; +} + +/* get normalization value */ +static int montgomery_normalization(void *a, void *b) +{ + size_t c = ROUNDUP(mbedtls_mpi_size(b), sizeof(mbedtls_mpi_uint)) * 8; + + if (mbedtls_mpi_lset(a, 1)) + return CRYPT_MEM; + if (mbedtls_mpi_shift_l(a, c)) + return CRYPT_MEM; + if (mbedtls_mpi_mod_mpi(a, a, b)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +/* reduce */ +static int montgomery_reduce(void *a, void *b, void *c) +{ + mbedtls_mpi A; + mbedtls_mpi *N = b; + mbedtls_mpi_uint *mm = c; + mbedtls_mpi T; + int ret = CRYPT_MEM; + + mbedtls_mpi_init_mempool(&T); + mbedtls_mpi_init_mempool(&A); + + if (mbedtls_mpi_grow(&T, (N->n + 1) * 2)) + goto out; + + if (mbedtls_mpi_cmp_mpi(a, N) > 0) { + if (mbedtls_mpi_mod_mpi(&A, a, N)) + goto out; + } else { + if (mbedtls_mpi_copy(&A, a)) + goto out; + } + + if (mbedtls_mpi_grow(&A, N->n + 1)) + goto out; + + mbedtls_mpi_montred(&A, N, *mm, &T); + + if (mbedtls_mpi_copy(a, &A)) + goto out; + + ret = CRYPT_OK; +out: + mbedtls_mpi_free(&A); + mbedtls_mpi_free(&T); + + return ret; +} + +/* clean up */ +static void montgomery_deinit(void *a) +{ + mempool_free(mbedtls_mpi_mempool, a); +} + +/* + * This function calculates: + * d = a^b mod c + * + * @a: base + * @b: exponent + * @c: modulus + * @d: destination + */ +static int exptmod(void *a, void *b, void *c, void *d) +{ + int res; + + if (d == a || d == b || d == c) { + mbedtls_mpi dest; + + mbedtls_mpi_init_mempool(&dest); + res = mbedtls_mpi_exp_mod(&dest, a, b, c, NULL); + if (!res) + res = mbedtls_mpi_copy(d, &dest); + mbedtls_mpi_free(&dest); + } else { + res = mbedtls_mpi_exp_mod(d, a, b, c, NULL); + } + + if (res) + return CRYPT_MEM; + else + return CRYPT_OK; +} + +static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen) +{ + if (crypto_rng_read(buf, blen)) + return MBEDTLS_ERR_MPI_FILE_IO_ERROR; + return 0; +} + +static int isprime(void *a, int b __unused, int *c) +{ + int res = mbedtls_mpi_is_prime(a, rng_read, NULL); + + if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) + return CRYPT_MEM; + + if (res) + *c = LTC_MP_NO; + else + *c = LTC_MP_YES; + + return CRYPT_OK; +} + +static int mpi_rand(void *a, int size) +{ + if (mbedtls_mpi_fill_random(a, size, rng_read, NULL)) + return CRYPT_MEM; + + return CRYPT_OK; +} + +ltc_math_descriptor ltc_mp = { + .name = "MPI", + .bits_per_digit = sizeof(mbedtls_mpi_uint) * 8, + + .init = init, + .init_size = init_size, + .init_copy = init_copy, + .deinit = deinit, + + .neg = neg, + .copy = 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 = divide, + .div_2 = div_2, + .modi = modi, + .gcd = gcd, + .lcm = lcm, + + .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 = ltc_ecc_fp_mulmod, +#else + .ecc_ptmul = ltc_ecc_mulmod, +#endif /* LTC_MECC_FP */ + .ecc_ptadd = ltc_ecc_projective_add_point, + .ecc_ptdbl = ltc_ecc_projective_dbl_point, + .ecc_map = ltc_ecc_map, +#ifdef LTC_ECC_SHAMIR +#ifdef LTC_MECC_FP + .ecc_mul2add = ltc_ecc_fp_mul2add, +#else + .ecc_mul2add = ltc_ecc_mul2add, +#endif /* LTC_MECC_FP */ +#endif /* LTC_ECC_SHAMIR */ +#endif /* LTC_MECC */ + +#ifdef LTC_MRSA + .rsa_keygen = rsa_make_key, + .rsa_me = rsa_exptmod, +#endif + .addmod = addmod, + .submod = submod, + .rand = mpi_rand, + +}; + +size_t crypto_bignum_num_bytes(struct bignum *a) +{ + return mbedtls_mpi_size((mbedtls_mpi *)a); +} + +size_t crypto_bignum_num_bits(struct bignum *a) +{ + return mbedtls_mpi_bitlen((mbedtls_mpi *)a); +} + +int32_t crypto_bignum_compare(struct bignum *a, struct bignum *b) +{ + return mbedtls_mpi_cmp_mpi((mbedtls_mpi *)a, (mbedtls_mpi *)b); +} + +void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to) +{ + const mbedtls_mpi *f = (const mbedtls_mpi *)from; + int rc __maybe_unused = 0; + + rc = mbedtls_mpi_write_binary(f, (void *)to, mbedtls_mpi_size(f)); + assert(!rc); +} + +TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize, + struct bignum *to) +{ + if (mbedtls_mpi_read_binary((mbedtls_mpi *)to, (const void *)from, + fromsize)) + return TEE_ERROR_BAD_PARAMETERS; + return TEE_SUCCESS; +} + +void crypto_bignum_copy(struct bignum *to, const struct bignum *from) +{ + int rc __maybe_unused = 0; + + rc = mbedtls_mpi_copy((mbedtls_mpi *)to, (const mbedtls_mpi *)from); + assert(!rc); +} + +struct bignum *crypto_bignum_allocate(size_t size_bits) +{ + mbedtls_mpi *bn = malloc(sizeof(*bn)); + + if (!bn) + return NULL; + + mbedtls_mpi_init(bn); + if (mbedtls_mpi_grow(bn, BITS_TO_LIMBS(size_bits))) { + free(bn); + return NULL; + } + + return (struct bignum *)bn; +} + +void crypto_bignum_free(struct bignum *s) +{ + mbedtls_mpi_free((mbedtls_mpi *)s); + free(s); +} + +void crypto_bignum_clear(struct bignum *s) +{ + mbedtls_mpi *bn = (mbedtls_mpi *)s; + + bn->s = 1; + if (bn->p) + memset(bn->p, 0, sizeof(*bn->p) * bn->n); +} diff --git a/optee/optee_os/core/lib/libtomcrypt/rsa.c b/optee/optee_os/core/lib/libtomcrypt/rsa.c new file mode 100644 index 0000000..22e6d47 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/rsa.c @@ -0,0 +1,682 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, 2022 Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + + +/* + * 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 + */ +static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex) +{ + switch (algo) { +#if defined(_CFG_CORE_LTC_SHA1) + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: + *ltc_hashindex = find_hash("sha1"); + break; +#endif +#if defined(_CFG_CORE_LTC_MD5) + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5: + *ltc_hashindex = find_hash("md5"); + break; +#endif +#if defined(_CFG_CORE_LTC_SHA224) + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: + *ltc_hashindex = find_hash("sha224"); + break; +#endif +#if defined(_CFG_CORE_LTC_SHA256) + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: + *ltc_hashindex = find_hash("sha256"); + break; +#endif +#if defined(_CFG_CORE_LTC_SHA384) + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: + *ltc_hashindex = find_hash("sha384"); + break; +#endif +#if defined(_CFG_CORE_LTC_SHA512) + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: + *ltc_hashindex = find_hash("sha512"); + break; +#endif + case TEE_ALG_RSASSA_PKCS1_V1_5: + case TEE_ALG_RSAES_PKCS1_V1_5: + /* invalid one. but it should not be used anyway */ + *ltc_hashindex = -1; + return TEE_SUCCESS; + + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (*ltc_hashindex < 0) + return TEE_ERROR_NOT_SUPPORTED; + else + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, + size_t key_size_bits __unused) +__weak __alias("sw_crypto_acipher_alloc_rsa_keypair"); + +TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->e)) + return TEE_ERROR_OUT_OF_MEMORY; + if (!bn_alloc_max(&s->d)) + goto err; + if (!bn_alloc_max(&s->n)) + goto err; + if (!bn_alloc_max(&s->p)) + goto err; + if (!bn_alloc_max(&s->q)) + goto err; + if (!bn_alloc_max(&s->qp)) + goto err; + if (!bn_alloc_max(&s->dp)) + goto err; + if (!bn_alloc_max(&s->dq)) + goto err; + + return TEE_SUCCESS; +err: + crypto_acipher_free_rsa_keypair(s); + return TEE_ERROR_OUT_OF_MEMORY; +} + + +TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, + size_t key_size_bits __unused) +__weak __alias("sw_crypto_acipher_alloc_rsa_public_key"); + +TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, + size_t key_size_bits __unused) +{ + memset(s, 0, sizeof(*s)); + if (!bn_alloc_max(&s->e)) + return TEE_ERROR_OUT_OF_MEMORY; + if (!bn_alloc_max(&s->n)) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->e); + return TEE_ERROR_OUT_OF_MEMORY; +} + + +void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) +__weak __alias("sw_crypto_acipher_free_rsa_public_key"); + +void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) +{ + if (!s) + return; + crypto_bignum_free(s->n); + crypto_bignum_free(s->e); +} + + +void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) +__weak __alias("sw_crypto_acipher_free_rsa_keypair"); + +void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) +{ + if (!s) + return; + crypto_bignum_free(s->e); + crypto_bignum_free(s->d); + crypto_bignum_free(s->n); + crypto_bignum_free(s->p); + crypto_bignum_free(s->q); + crypto_bignum_free(s->qp); + crypto_bignum_free(s->dp); + crypto_bignum_free(s->dq); +} + +TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, + size_t key_size) +__weak __alias("sw_crypto_acipher_gen_rsa_key"); + +TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key, + size_t key_size) +{ + TEE_Result res; + rsa_key ltc_tmp_key; + int ltc_res; + + /* Generate a temporary RSA key */ + ltc_res = rsa_make_key_bn_e(NULL, find_prng("prng_crypto"), + key_size / 8, key->e, <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.d, key->d); + ltc_mp.copy(ltc_tmp_key.N, key->n); + ltc_mp.copy(ltc_tmp_key.p, key->p); + ltc_mp.copy(ltc_tmp_key.q, key->q); + ltc_mp.copy(ltc_tmp_key.qP, key->qp); + ltc_mp.copy(ltc_tmp_key.dP, key->dp); + ltc_mp.copy(ltc_tmp_key.dQ, key->dq); + + /* Free the temporary key */ + rsa_free(<c_tmp_key); + res = TEE_SUCCESS; + } + + return res; +} + +static TEE_Result 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; + unsigned long 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 = _CFG_CORE_LTC_BIGNUM_MAX_BITS / sizeof(uint8_t); + buf = mempool_alloc(mempool_default, blen); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = rsa_exptmod(src, src_len, buf, &blen, ltc_key->type, + ltc_key); + switch (ltc_res) { + case CRYPT_PK_NOT_PRIVATE: + case CRYPT_PK_INVALID_TYPE: + case CRYPT_PK_INVALID_SIZE: + case CRYPT_INVALID_PACKET: + EMSG("rsa_exptmod() returned %d", ltc_res); + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + case CRYPT_OK: + break; + default: + /* This will result in a panic */ + EMSG("rsa_exptmod() returned %d", ltc_res); + res = TEE_ERROR_GENERIC; + goto out; + } + + /* Remove the zero-padding (leave one zero if buff is all zeroes) */ + offset = 0; + while ((offset < blen - 1) && (buf[offset] == 0)) + offset++; + + if (*dst_len < blen - offset) { + *dst_len = blen - offset; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = TEE_SUCCESS; + *dst_len = blen - offset; + memcpy(dst, (char *)buf + offset, *dst_len); + +out: + mempool_free(mempool_default, buf); + + return res; +} + +TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +__weak __alias("sw_crypto_acipher_rsanopad_encrypt"); + +TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +{ + TEE_Result res; + rsa_key ltc_key = { 0, }; + + ltc_key.type = PK_PUBLIC; + ltc_key.e = key->e; + ltc_key.N = key->n; + + res = rsadorep(<c_key, src, src_len, dst, dst_len); + return res; +} + +TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +__weak __alias("sw_crypto_acipher_rsanopad_decrypt"); + +TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +{ + TEE_Result res; + rsa_key ltc_key = { 0, }; + + ltc_key.type = PK_PRIVATE; + ltc_key.e = key->e; + ltc_key.N = key->n; + ltc_key.d = key->d; + if (key->p && crypto_bignum_num_bytes(key->p)) { + ltc_key.p = key->p; + ltc_key.q = key->q; + ltc_key.qP = key->qp; + ltc_key.dP = key->dp; + ltc_key.dQ = key->dq; + } + + res = rsadorep(<c_key, src, src_len, dst, dst_len); + return res; +} + +TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, + struct rsa_keypair *key, + const uint8_t *label, + size_t label_len, const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +__weak __alias("sw_crypto_acipher_rsaes_decrypt"); + +TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo, + struct rsa_keypair *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; + unsigned long blen; + int ltc_hashindex, ltc_res, ltc_stat, ltc_rsa_algo; + size_t mod_size; + rsa_key ltc_key = { 0, }; + + ltc_key.type = PK_PRIVATE; + ltc_key.e = key->e; + ltc_key.d = key->d; + ltc_key.N = key->n; + if (key->p && crypto_bignum_num_bytes(key->p)) { + ltc_key.p = key->p; + ltc_key.q = key->q; + ltc_key.qP = key->qp; + ltc_key.dP = key->dp; + ltc_key.dQ = key->dq; + } + + /* Get the algorithm */ + res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (res != TEE_SUCCESS) { + EMSG("tee_algo_to_ltc_hashindex() returned %d", (int)res); + goto out; + } + + /* + * 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. + */ + if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { + mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); + blen = mod_size - 11; + ltc_rsa_algo = LTC_PKCS_1_V1_5; + } else { + /* Decoded message is always shorter than encrypted message */ + blen = src_len; + ltc_rsa_algo = LTC_PKCS_1_OAEP; + } + + buf = mempool_alloc(mempool_default, blen); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = rsa_decrypt_key_ex(src, src_len, buf, &blen, + ((label_len == 0) ? 0 : label), label_len, + ltc_hashindex, ltc_rsa_algo, <c_stat, + <c_key); + switch (ltc_res) { + case CRYPT_PK_INVALID_PADDING: + case CRYPT_INVALID_PACKET: + case CRYPT_PK_INVALID_SIZE: + EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + case CRYPT_OK: + break; + default: + /* This will result in a panic */ + EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); + res = TEE_ERROR_GENERIC; + goto out; + } + if (ltc_stat != 1) { + /* This will result in a panic */ + EMSG("rsa_decrypt_key_ex() returned %d and %d", + ltc_res, ltc_stat); + res = TEE_ERROR_GENERIC; + 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: + mempool_free(mempool_default, buf); + + return res; +} + +TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, + struct rsa_public_key *key, + const uint8_t *label, + size_t label_len, const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +__weak __alias("sw_crypto_acipher_rsaes_encrypt"); + +TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo, + struct rsa_public_key *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; + rsa_key ltc_key = { + .type = PK_PUBLIC, + .e = key->e, + .N = key->n + }; + + mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); + if (*dst_len < mod_size) { + *dst_len = mod_size; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + *dst_len = mod_size; + + /* Get the algorithm */ + res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (res != TEE_SUCCESS) + goto out; + + if (algo == TEE_ALG_RSAES_PKCS1_V1_5) + ltc_rsa_algo = LTC_PKCS_1_V1_5; + else + ltc_rsa_algo = LTC_PKCS_1_OAEP; + + ltc_res = rsa_encrypt_key_ex(src, src_len, dst, + (unsigned long *)(dst_len), label, + label_len, NULL, find_prng("prng_crypto"), + ltc_hashindex, ltc_rsa_algo, <c_key); + switch (ltc_res) { + case CRYPT_PK_INVALID_PADDING: + case CRYPT_INVALID_PACKET: + case CRYPT_PK_INVALID_SIZE: + EMSG("rsa_encrypt_key_ex() returned %d", ltc_res); + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + case CRYPT_OK: + break; + default: + /* This will result in a panic */ + res = TEE_ERROR_GENERIC; + goto out; + } + res = TEE_SUCCESS; + +out: + return res; +} + +TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, + int salt_len, const uint8_t *msg, + size_t msg_len, uint8_t *sig, + size_t *sig_len) +__weak __alias("sw_crypto_acipher_rsassa_sign"); + +TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *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, mod_size; + int ltc_res, ltc_rsa_algo, ltc_hashindex; + unsigned long ltc_sig_len; + rsa_key ltc_key = { 0, }; + + ltc_key.type = PK_PRIVATE; + ltc_key.e = key->e; + ltc_key.N = key->n; + ltc_key.d = key->d; + if (key->p && crypto_bignum_num_bytes(key->p)) { + ltc_key.p = key->p; + ltc_key.q = key->q; + ltc_key.qP = key->qp; + ltc_key.dP = key->dp; + ltc_key.dQ = key->dq; + } + + switch (algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5: + ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; + 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: + ltc_rsa_algo = LTC_PKCS_1_V1_5; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: + 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_PKCS_1_PSS; + break; + default: + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + if (ltc_rsa_algo != LTC_PKCS_1_V1_5_NA1) { + ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), + &hash_size); + if (res != TEE_SUCCESS) + goto err; + + if (msg_len != hash_size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + } + + mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); + + if (*sig_len < mod_size) { + *sig_len = mod_size; + res = TEE_ERROR_SHORT_BUFFER; + goto err; + } + + ltc_sig_len = mod_size; + + ltc_res = rsa_sign_hash_ex(msg, msg_len, sig, <c_sig_len, + ltc_rsa_algo, NULL, find_prng("prng_crypto"), + ltc_hashindex, salt_len, <c_key); + + *sig_len = ltc_sig_len; + + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + res = TEE_SUCCESS; + +err: + return res; +} + +TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, + struct rsa_public_key *key, + int salt_len, const uint8_t *msg, + size_t msg_len, const uint8_t *sig, + size_t sig_len) +__weak __alias("sw_crypto_acipher_rsassa_verify"); + +TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo, + struct rsa_public_key *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; + size_t hash_size; + int stat, ltc_hashindex, ltc_res, ltc_rsa_algo; + rsa_key ltc_key = { + .type = PK_PUBLIC, + .e = key->e, + .N = key->n + }; + struct ftmn ftmn = { }; + + /* + * The caller expects to call crypto_acipher_rsassa_verify(), + * update the hash as needed. + */ + FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify")); + + if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { + res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), + &hash_size); + if (res != TEE_SUCCESS) + goto err; + + if (msg_len != hash_size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + } + + bigint_size = ltc_mp.unsigned_size(ltc_key.N); + if (sig_len < bigint_size) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto err; + } + + /* Get the algorithm */ + if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { + res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); + if (res != TEE_SUCCESS) + goto err; + } + + switch (algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5: + ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; + 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: + ltc_rsa_algo = LTC_PKCS_1_V1_5; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: + 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_PKCS_1_PSS; + break; + default: + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("rsa_verify_hash_ex")); + ltc_res = rsa_verify_hash_ex(sig, sig_len, msg, msg_len, ltc_rsa_algo, + ltc_hashindex, salt_len, &stat, <c_key); + res = convert_ltc_verify_status(ltc_res, stat); + if (res) + FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR0, res); + else + FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, 0); + FTMN_POP_LINKED_CALL(&ftmn); + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res); + return res; +err: + FTMN_CALLEE_DONE_NOT_ZERO(res); + return res; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/sha1_accel.c b/optee/optee_os/core/lib/libtomcrypt/sha1_accel.c new file mode 100644 index 0000000..b4e3cec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sha1_accel.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, 2020, Linaro Limited + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 +#include +/** + @file sha1.c + LTC_SHA1 code by Tom St Denis +*/ + + +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 +}; + +static int sha1_compress_nblocks(hash_state *md, const unsigned char *buf, + int blocks) +{ + void *state = md->sha1.state; + + COMPILE_TIME_ASSERT(sizeof(md->sha1.state[0]) == sizeof(uint32_t)); + + crypto_accel_sha1_compress(state, buf, blocks); + return CRYPT_OK; +} + +static int sha1_compress(hash_state *md, const unsigned char *buf) +{ + return sha1_compress_nblocks(md, buf, 1); +} + +/** + 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_NBLOCKS(sha1_process, sha1_compress_nblocks, sha1, 64) + +/** + 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; +} + +/** + 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 +} diff --git a/optee/optee_os/core/lib/libtomcrypt/sha256_accel.c b/optee/optee_os/core/lib/libtomcrypt/sha256_accel.c new file mode 100644 index 0000000..7e491b1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sha256_accel.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + * Copyright (c) 2001-2007, Tom St Denis + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (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 +#include + +#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 +}; + + +/* Implemented in assembly */ +int sha256_ce_transform(ulong32 *state, const unsigned char *buf, int blocks); + +static int sha256_compress_nblocks(hash_state *md, const unsigned char *buf, + int blocks) +{ + void *state = md->sha256.state; + + COMPILE_TIME_ASSERT(sizeof(md->sha256.state[0]) == sizeof(uint32_t)); + + crypto_accel_sha256_compress(state, buf, blocks); + return CRYPT_OK; +} + +static int sha256_compress(hash_state *md, const unsigned char *buf) +{ + return sha256_compress_nblocks(md, buf, 1); +} + +/** + 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_NBLOCKS(sha256_process, sha256_compress_nblocks, 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 /*LTC_SHA256*/ diff --git a/optee/optee_os/core/lib/libtomcrypt/sha3_accel.c b/optee/optee_os/core/lib/libtomcrypt/sha3_accel.c new file mode 100644 index 0000000..10dbe34 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sha3_accel.c @@ -0,0 +1,245 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +/* based on https://github.com/brainhub/SHA3IUF (public domain) */ + +#include +#include +#include + +#ifdef LTC_SHA3 + +const struct ltc_hash_descriptor sha3_224_desc = +{ + "sha3-224", /* name of hash */ + 17, /* internal ID */ + 28, /* Size of digest in octets */ + 144, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_224_init, + &sha3_process, + &sha3_done, + &sha3_224_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_256_desc = +{ + "sha3-256", /* name of hash */ + 18, /* internal ID */ + 32, /* Size of digest in octets */ + 136, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_256_init, + &sha3_process, + &sha3_done, + &sha3_256_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_384_desc = +{ + "sha3-384", /* name of hash */ + 19, /* internal ID */ + 48, /* Size of digest in octets */ + 104, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_384_init, + &sha3_process, + &sha3_done, + &sha3_384_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_512_desc = +{ + "sha3-512", /* name of hash */ + 20, /* internal ID */ + 64, /* Size of digest in octets */ + 72, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_512_init, + &sha3_process, + &sha3_done, + &sha3_512_test, + NULL +}; + +/* Public Inteface */ + +int sha3_224_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_256_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_384_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_512_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_shake_init(hash_state *md, int num) +{ + LTC_ARGCHK(md != NULL); + if (num != 128 && num != 256) return CRYPT_INVALID_ARG; + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64))); + return CRYPT_OK; +} + +int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + unsigned int digest_size = 0; + unsigned int block_count = 0; + unsigned int block_size = 0; + void *state = NULL; + unsigned int l = 0; + + if (!inlen) + return CRYPT_OK; + LTC_ARGCHK(md); + LTC_ARGCHK(in); + + block_size = 200 - md->sha3.capacity_words * 8; + digest_size = md->sha3.capacity_words * 8 / 2; + state = md->sha3.s; + + if (md->sha3.byte_index) { + l = MIN(block_size - md->sha3.byte_index, inlen); + memcpy(md->sha3.sb + md->sha3.byte_index, in, l); + in += l; + inlen -= l; + md->sha3.byte_index += l; + if (md->sha3.byte_index == block_size) { + crypto_accel_sha3_compress(state, md->sha3.sb, 1, + digest_size); + md->sha3.byte_index = 0; + } + + if (!inlen) + return CRYPT_OK; + } + + if (inlen > block_size) { + block_count = inlen / block_size; + crypto_accel_sha3_compress(state, in, block_count, + digest_size); + in += block_count * block_size; + inlen -= block_count * block_size; + } + + memcpy(md->sha3.sb + md->sha3.byte_index, in, inlen); + md->sha3.byte_index += inlen; + + return CRYPT_OK; +} + +static void copy_out_digest(ulong64 *s, unsigned int digest_size, + unsigned char *out) +{ + unsigned int n = 0; + + for (n = 0; n < digest_size / sizeof(uint64_t); n++) { + put_unaligned_le64(out, s[n]); + out += sizeof(uint64_t); + } + + if (digest_size % sizeof(uint64_t)) + put_unaligned_le32(out, s[n]); +} + +int sha3_done(hash_state *md, unsigned char *out) +{ + unsigned int digest_size = 0; + unsigned int block_size = 0; + void *state = NULL; + uint8_t *buf = NULL; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + block_size = 200 - md->sha3.capacity_words * 8; + digest_size = md->sha3.capacity_words * 8 / 2; + state = md->sha3.s; + buf = md->sha3.sb; + + buf[md->sha3.byte_index++] = 0x06; + memset(buf + md->sha3.byte_index, 0, block_size - md->sha3.byte_index); + buf[block_size - 1] |= 0x80; + crypto_accel_sha3_compress(state, buf, 1, digest_size); + + copy_out_digest(state, digest_size, out); + + return CRYPT_OK; +} + + +int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen) +{ + unsigned int digest_size = 0; + unsigned int block_size = 0; + void *state = NULL; + uint8_t *buf = NULL; + unsigned int n = 0; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + block_size = 200 - md->sha3.capacity_words * 8; + digest_size = md->sha3.capacity_words * 8 / 2; + state = md->sha3.s; + buf = md->sha3.sb; + + if (!md->sha3.xof_flag) { + buf[md->sha3.byte_index++] = 0x1f; + memset(buf + md->sha3.byte_index, 0, + block_size - md->sha3.byte_index); + buf[block_size - 1] |= 0x80; + crypto_accel_sha3_compress(state, buf, 1, digest_size); + md->sha3.byte_index = 0; + copy_out_digest(state, block_size, buf); + md->sha3.xof_flag = 1; + } + + for (n = 0; n < outlen; n++) { + if (md->sha3.byte_index >= block_size) { + memset(buf, 0, block_size); + crypto_accel_sha3_compress(state, buf, 1, digest_size); + md->sha3.byte_index = 0; + copy_out_digest(state, block_size, buf); + } + out[n] = buf[md->sha3.byte_index]; + md->sha3.byte_index++; + } + + return CRYPT_OK; +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/sha512_accel.c b/optee/optee_os/core/lib/libtomcrypt/sha512_accel.c new file mode 100644 index 0000000..948bbec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sha512_accel.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: Unlicense AND BSD-2-Clause +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* Copyright (c) 2023 Linaro Limited */ +#include +#include + +/** + @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 +}; + + +/* Implemented in assembly */ +int sha512_ce_transform(ulong64 *state, const unsigned char *buf, int blocks); + +static int sha512_compress_nblocks(hash_state *md, const unsigned char *buf, + int blocks) +{ + void *state = md->sha512.state; + + COMPILE_TIME_ASSERT(sizeof(md->sha512.state[0]) == sizeof(uint64_t)); + + crypto_accel_sha512_compress(state, buf, blocks); + + return CRYPT_OK; +} + +static int sha512_compress(hash_state *md, const unsigned char *buf) +{ + return sha512_compress_nblocks(md, buf, 1); +} + +/** + 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; +} + +HASH_PROCESS_NBLOCKS(sha512_process, sha512_compress_nblocks, 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)XSTRLEN(tests[i].msg)); + sha512_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /*LTC_SHA512*/ diff --git a/optee/optee_os/core/lib/libtomcrypt/shake.c b/optee/optee_os/core/lib/libtomcrypt/shake.c new file mode 100644 index 0000000..50ce545 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/shake.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +struct shake_ctx { + struct crypto_hash_ctx ctx; + struct sha3_state sha3; +}; + +static struct shake_ctx *to_shake_ctx(struct crypto_hash_ctx *ctx) +{ + return container_of(ctx, struct shake_ctx, ctx); +} + +static TEE_Result do_shake_init(struct crypto_hash_ctx *ctx, unsigned int num) +{ + struct shake_ctx *c = to_shake_ctx(ctx); + + if (sha3_shake_init((void *)&c->sha3, num) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result do_sha3_update(struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len) +{ + struct shake_ctx *c = to_shake_ctx(ctx); + + if (sha3_process((void *)&c->sha3, data, len) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result do_shake_final(struct crypto_hash_ctx *ctx, + uint8_t *digest, size_t len) +{ + struct shake_ctx *c = to_shake_ctx(ctx); + + if (sha3_shake_done((void *)&c->sha3, digest, len) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result do_shake_alloc_ctx(struct crypto_hash_ctx **ctx_ret, + const struct crypto_hash_ops *ops) +{ + struct shake_ctx *ctx = calloc(1, sizeof(*ctx)); + + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + ctx->ctx.ops = ops; + *ctx_ret = &ctx->ctx; + + return TEE_SUCCESS; +} + +static void do_sha3_free_ctx(struct crypto_hash_ctx *ctx) +{ + struct shake_ctx *c = to_shake_ctx(ctx); + + free(c); +} +static void do_sha3_copy_state(struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx) +{ + struct shake_ctx *dc = to_shake_ctx(dst_ctx); + struct shake_ctx *sc = to_shake_ctx(src_ctx); + + assert(sc->ctx.ops == dc->ctx.ops); + dc->sha3 = sc->sha3; +} + +#if defined(_CFG_CORE_LTC_SHAKE128) +static TEE_Result do_shake128_init(struct crypto_hash_ctx *ctx) +{ + return do_shake_init(ctx, 128); +} + +static const struct crypto_hash_ops shake128_ops = { + .init = do_shake128_init, + .update = do_sha3_update, + .final = do_shake_final, + .free_ctx = do_sha3_free_ctx, + .copy_state = do_sha3_copy_state, +}; + +TEE_Result crypto_shake128_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return do_shake_alloc_ctx(ctx, &shake128_ops); +} +#endif + +#if defined(_CFG_CORE_LTC_SHAKE256) +static TEE_Result do_shake256_init(struct crypto_hash_ctx *ctx) +{ + return do_shake_init(ctx, 256); +} + +static const struct crypto_hash_ops shake256_ops = { + .init = do_shake256_init, + .update = do_sha3_update, + .final = do_shake_final, + .free_ctx = do_sha3_free_ctx, + .copy_state = do_sha3_copy_state, +}; + +TEE_Result crypto_shake256_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return do_shake_alloc_ctx(ctx, &shake256_ops); +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c b/optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c new file mode 100644 index 0000000..3652569 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sm2-dsa.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + +/* SM2 uses 256 bit unsigned integers in big endian format */ +#define SM2_INT_SIZE_BYTES 32 + +/* + * GM/T 0003.1‒2012 Part1 2 Section 6.1 + */ +TEE_Result sm2_ltc_dsa_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, uint8_t *sig, + size_t *sig_len) +{ + TEE_Result res = TEE_SUCCESS; + ecc_point *x1y1p = NULL; + ecc_key ltc_key = { }; + int ltc_res = 0; + void *k = NULL; + void *e = NULL; + void *r = NULL; + void *s = NULL; + void *tmp = NULL; + + if (*sig_len < 2 * SM2_INT_SIZE_BYTES) { + *sig_len = 64; + return TEE_ERROR_SHORT_BUFFER; + } + + ltc_res = mp_init_multi(&k, &e, &r, &s, &tmp, NULL); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_OUT_OF_MEMORY; + + x1y1p = ltc_ecc_new_point(); + if (!x1y1p) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = ecc_populate_ltc_private_key(<c_key, key, algo, NULL); + if (res) + goto out; + + /* + * Steps A1 and A2 are the generation of the hash value e from user + * information (ZA) and the message to be signed (M). There are not done + * here since @msg is expected to be the hash value e already. + */ + + /* Step A3: generate random number 1 <= k < n */ +A3: + ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL, + find_prng("prng_crypto")); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step A4: compute (x1, y1) = [k]G */ + + ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, x1y1p, ltc_key.dp.A, + ltc_key.dp.prime, 1); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step A5: compute r = (e + x1) mod n */ + + mp_read_unsigned_bin(e, (unsigned char *)msg, msg_len); + ltc_res = mp_addmod(e, x1y1p->x, ltc_key.dp.order, r); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + ltc_res = mp_add(r, k, tmp); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + if (mp_cmp_d(r, 0) == LTC_MP_EQ || + mp_cmp(tmp, ltc_key.dp.order) == LTC_MP_EQ) + goto A3; + + /* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */ + + ltc_res = mp_add_d(ltc_key.k, 1, s); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + ltc_res = mp_invmod(s, ltc_key.dp.order, s); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + ltc_res = mp_mul(r, ltc_key.k, tmp); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + ltc_res = mp_sub(k, tmp, tmp); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + ltc_res = mp_mulmod(s, tmp, ltc_key.dp.order, s); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step A7: convert (r, s) to binary for output */ + + *sig_len = 2 * SM2_INT_SIZE_BYTES; + memset(sig, 0, *sig_len); + mp_to_unsigned_bin2(r, sig, SM2_INT_SIZE_BYTES); + mp_to_unsigned_bin2(s, sig + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); +out: + ecc_free(<c_key); + ltc_ecc_del_point(x1y1p); + mp_clear_multi(k, e, r, s, tmp, NULL); + return res; +} + +/* + * GM/T 0003.1‒2012 Part1 2 Section 7.1 + */ +TEE_Result sm2_ltc_dsa_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result res = TEE_SUCCESS; + ecc_key ltc_key = { }; + int ltc_res = 0; + void *rprime = NULL; + void *sprime = NULL; + void *t = NULL; + void *mp = NULL; + void *mu = NULL; + void *ma = NULL; + void *eprime = NULL; + void *R = NULL; + ecc_point *x1y1p = NULL; + + if (sig_len != 64) + return TEE_ERROR_BAD_PARAMETERS; + + ltc_res = mp_init_multi(&rprime, &sprime, &t, &mu, &ma, &eprime, &R, + NULL); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_OUT_OF_MEMORY; + + mp_read_unsigned_bin(rprime, (unsigned char *)sig, 32); + mp_read_unsigned_bin(sprime, (unsigned char *)sig + 32, 32); + + res = ecc_populate_ltc_public_key(<c_key, key, algo, NULL); + if (res) + goto out; + + /* Step B1: verify r' in [1, n - 1] */ + + if (mp_cmp_d(rprime, 1) == LTC_MP_LT || + mp_cmp(rprime, ltc_key.dp.order) != LTC_MP_LT) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto out; + } + + /* Step B2: verify s' in [1, n - 1] */ + + if (mp_cmp_d(sprime, 1) == LTC_MP_LT || + mp_cmp(sprime, ltc_key.dp.order) != LTC_MP_LT) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto out; + } + + /* + * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here + * because @msg is supposed to contain the hash value e' already. + */ + + /* Step B5: t = (r' + s') mod n and check t != 0 */ + + ltc_res = mp_addmod(rprime, sprime, ltc_key.dp.order, t); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + if (mp_cmp_d(t, 0) == LTC_MP_EQ) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto out; + } + + /* Step B6: (x1', y1') = [s']G + [t]PA */ + + x1y1p = ltc_ecc_new_point(); + if (!x1y1p) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + ltc_res = mp_montgomery_setup(ltc_key.dp.prime, &mp); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + ltc_res = mp_montgomery_normalization(mu, ltc_key.dp.prime); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + ltc_res = mp_mulmod(ltc_key.dp.A, mu, ltc_key.dp.prime, ma); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + ltc_res = ltc_ecc_mul2add(<c_key.dp.base, sprime, <c_key.pubkey, t, + x1y1p, ma, ltc_key.dp.prime); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step B7: compute R = (e' + x1') mod n and verify R == r' */ + + mp_read_unsigned_bin(eprime, (unsigned char *)msg, msg_len); + ltc_res = mp_addmod(eprime, x1y1p->x, ltc_key.dp.order, R); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + if (mp_cmp(R, rprime) != LTC_MP_EQ) + res = TEE_ERROR_SIGNATURE_INVALID; +out: + mp_montgomery_free(mp); + ltc_ecc_del_point(x1y1p); + ecc_free(<c_key); + mp_clear_multi(rprime, sprime, t, mu, ma, eprime, R, NULL); + return res; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/sm2-kep.c b/optee/optee_os/core/lib/libtomcrypt/sm2-kep.c new file mode 100644 index 0000000..7bddb5f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sm2-kep.c @@ -0,0 +1,443 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + +/* SM2 uses 256 bit unsigned integers in big endian format */ +#define SM2_INT_SIZE_BYTES 32 + +/* + * Compute a hash of a user's identity and public key + * For user A: ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) + */ +static TEE_Result sm2_kep_compute_Z(uint8_t *Z, size_t Zlen, const uint8_t *id, + size_t idlen, const ecc_key *key) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t ENTLEN[2] = { }; + uint8_t buf[SM2_INT_SIZE_BYTES]; + void *ctx = NULL; + + if (Zlen < TEE_SM3_HASH_SIZE) + return TEE_ERROR_SHORT_BUFFER; + + /* + * ENTLEN is the length in bits if the user's distinguished identifier + * encoded over 16 bits in big endian format. + */ + ENTLEN[0] = (idlen * 8) >> 8; + ENTLEN[1] = idlen * 8; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + goto out; + + res = crypto_hash_init(ctx); + if (res) + goto out; + + res = crypto_hash_update(ctx, ENTLEN, sizeof(ENTLEN)); + if (res) + goto out; + + res = crypto_hash_update(ctx, id, idlen); + if (res) + goto out; + + mp_to_unsigned_bin2(key->dp.A, buf, SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mp_to_unsigned_bin2(key->dp.B, buf, SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mp_to_unsigned_bin2(key->dp.base.x, buf, SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mp_to_unsigned_bin2(key->dp.base.y, buf, SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mp_to_unsigned_bin2(key->pubkey.x, buf, SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mp_to_unsigned_bin2(key->pubkey.y, buf, SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + res = crypto_hash_final(ctx, Z, TEE_SM3_HASH_SIZE); +out: + crypto_hash_free_ctx(ctx); + return res; +} + +/* + * Compute a verification value, to be checked against the value sent by the + * peer. + * On the initiator's side: + * S1 = SM3(0x02 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2)) + * On the responder's side: + * S2 = SM3(0x03 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2)) + */ +static TEE_Result sm2_kep_compute_S(uint8_t *S, size_t S_len, uint8_t flag, + ecc_point *UV, const uint8_t *ZAZB, + size_t ZAZB_len, ecc_key *initiator_eph_key, + ecc_key *responder_eph_key) +{ + uint8_t hash[TEE_SM3_HASH_SIZE] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t buf[SM2_INT_SIZE_BYTES]; + void *ctx = NULL; + + if (S_len < TEE_SM3_HASH_SIZE) + return TEE_ERROR_SHORT_BUFFER; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + goto out; + + /* Compute the inner hash */ + + res = crypto_hash_init(ctx); + if (res) + goto out; + + /* xU or xV */ + mp_to_unsigned_bin2(UV->x, buf, SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* ZA || ZB */ + res = crypto_hash_update(ctx, ZAZB, ZAZB_len); + if (res) + goto out; + + /* x1 */ + mp_to_unsigned_bin2(initiator_eph_key->pubkey.x, buf, + SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* y1 */ + mp_to_unsigned_bin2(initiator_eph_key->pubkey.y, buf, + SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* x2 */ + mp_to_unsigned_bin2(responder_eph_key->pubkey.x, buf, + SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* y2 */ + mp_to_unsigned_bin2(responder_eph_key->pubkey.y, buf, + SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + res = crypto_hash_final(ctx, hash, sizeof(hash)); + if (res) + goto out; + + /* Now compute S */ + + res = crypto_hash_init(ctx); + if (res) + goto out; + + /* 0x02 or 0x03 */ + res = crypto_hash_update(ctx, &flag, sizeof(flag)); + if (res) + goto out; + + /* yU or yV */ + mp_to_unsigned_bin2(UV->y, buf, SM2_INT_SIZE_BYTES); + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* Inner SM3(...) */ + res = crypto_hash_update(ctx, hash, sizeof(hash)); + if (res) + goto out; + + res = crypto_hash_final(ctx, S, TEE_SM3_HASH_SIZE); + +out: + crypto_hash_free_ctx(ctx); + return res; + +} + +/* + * GM/T 0003.1‒2012 Part 3 Section 6.1 + * Key exchange protocol + */ +static TEE_Result sm2_kep_derive(ecc_key *my_key, ecc_key *my_eph_key, + ecc_key *peer_key, ecc_key *peer_eph_key, + struct sm2_kep_parms *p) +{ + /* + * Variable names and documented steps reflect the initator side (user A + * in the spec), but the other side is quite similar hence only one + * function. + */ + uint8_t xUyUZAZB[2 * SM2_INT_SIZE_BYTES + 2 * TEE_SM3_HASH_SIZE] = { }; + ecc_key *initiator_eph_key = p->is_initiator ? my_eph_key : + peer_eph_key; + ecc_key *responder_eph_key = p->is_initiator ? peer_eph_key : + my_eph_key; + ecc_key *initiator_key = p->is_initiator ? my_key : peer_key; + ecc_key *responder_key = p->is_initiator ? peer_key : my_key; + TEE_Result res = TEE_ERROR_BAD_STATE; + uint8_t tmp[SM2_INT_SIZE_BYTES]; + void *n = my_key->dp.order; + ecc_point *U = NULL; + void *x1bar = NULL; + void *x2bar = NULL; + void *tA = NULL; + void *h = NULL; + void *htA = NULL; + void *mp = NULL; + void *mu = NULL; + void *ma = NULL; + void *one = NULL; + int ltc_res = 0; + int inf = 0; + + ltc_res = mp_init_multi(&x1bar, &x2bar, &tA, &h, &htA, &mu, &ma, &one, + NULL); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + U = ltc_ecc_new_point(); + if (!U) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + /* + * Steps A1-A3 are supposedly done already (generate ephemeral key, send + * it to peer). + * Step A4: (x1, y1) = RA; x1bar = 2^w + (x1 & (2^w - 1)) + */ + + mp_to_unsigned_bin2(my_eph_key->pubkey.x, tmp, SM2_INT_SIZE_BYTES); + tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80; + mp_read_unsigned_bin(x1bar, tmp + SM2_INT_SIZE_BYTES / 2, + SM2_INT_SIZE_BYTES / 2); + + /* Step A5: tA = (dA + x1bar * rA) mod n */ + + ltc_res = mp_mulmod(x1bar, my_eph_key->k, n, tA); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = mp_addmod(tA, my_key->k, n, tA); + if (ltc_res != CRYPT_OK) + goto out; + + /* Step A6: verify whether RB verifies the curve equation */ + + ltc_res = ltc_ecc_is_point(&peer_eph_key->dp, peer_eph_key->pubkey.x, + peer_eph_key->pubkey.y); + if (ltc_res != CRYPT_OK) + goto out; + + /* Step A6 (continued): (x2, y2) = RB; x2bar = 2^w + (x2 & (2^w - 1)) */ + + mp_to_unsigned_bin2(peer_eph_key->pubkey.x, tmp, SM2_INT_SIZE_BYTES); + tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80; + mp_read_unsigned_bin(x2bar, tmp + SM2_INT_SIZE_BYTES / 2, + SM2_INT_SIZE_BYTES / 2); + + + /* Step A7: compute U = [h.tA](PB + [x2bar]RB) and check for infinity */ + + ltc_res = mp_montgomery_setup(peer_key->dp.prime, &mp); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = mp_montgomery_normalization(mu, peer_key->dp.prime); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = mp_mulmod(peer_key->dp.A, mu, peer_key->dp.prime, ma); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = mp_set_int(one, 1); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = ltc_ecc_mul2add(&peer_key->pubkey, one, &peer_eph_key->pubkey, + x2bar, U, ma, peer_key->dp.prime); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = mp_set_int(h, peer_key->dp.cofactor); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = mp_mul(h, tA, htA); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = ltc_ecc_mulmod(htA, U, U, peer_key->dp.A, peer_key->dp.prime, + 1); + if (ltc_res != CRYPT_OK) + goto out; + + ltc_res = ltc_ecc_is_point_at_infinity(U, peer_key->dp.prime, &inf); + if (ltc_res != CRYPT_OK) + goto out; + + if (inf) + goto out; + + /* Step A8: compute KA = KDF(xU || yU || ZA || ZB, klen) */ + + /* xU */ + mp_to_unsigned_bin2(U->x, xUyUZAZB, SM2_INT_SIZE_BYTES); + + /* yU */ + mp_to_unsigned_bin2(U->y, xUyUZAZB + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + + /* ZA */ + res = sm2_kep_compute_Z(xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, + TEE_SM3_HASH_SIZE, p->initiator_id, + p->initiator_id_len, initiator_key); + if (res) + goto out; + + /* ZB */ + res = sm2_kep_compute_Z(xUyUZAZB + 2 * SM2_INT_SIZE_BYTES + + TEE_SM3_HASH_SIZE, + TEE_SM3_HASH_SIZE, p->responder_id, + p->responder_id_len, responder_key); + if (res) + goto out; + + res = sm2_kdf(xUyUZAZB, sizeof(xUyUZAZB), p->out, p->out_len); + if (res) + goto out; + + /* Step A9: compute S1 and check S1 == SB */ + + if (p->conf_in) { + uint8_t S1[TEE_SM3_HASH_SIZE]; + uint8_t flag = p->is_initiator ? 0x02 : 0x03; + + if (p->conf_in_len < TEE_SM3_HASH_SIZE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + res = sm2_kep_compute_S(S1, sizeof(S1), flag, U, + xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, + 2 * SM2_INT_SIZE_BYTES, + initiator_eph_key, responder_eph_key); + if (res) + goto out; + + if (consttime_memcmp(S1, p->conf_in, sizeof(S1))) { + /* Verification failed */ + res = TEE_ERROR_BAD_STATE; + goto out; + } + } + + /* Step A10: compute SA */ + + if (p->conf_out) { + uint8_t flag = p->is_initiator ? 0x03 : 0x02; + + if (p->conf_out_len < TEE_SM3_HASH_SIZE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = sm2_kep_compute_S(p->conf_out, TEE_SM3_HASH_SIZE, flag, U, + xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, + 2 * SM2_INT_SIZE_BYTES, + initiator_eph_key, responder_eph_key); + if (res) + goto out; + } +out: + mp_montgomery_free(mp); + ltc_ecc_del_point(U); + mp_clear_multi(x1bar, x2bar, tA, h, htA, mu, ma, one, NULL); + return res; +} + +TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key, + struct ecc_keypair *my_eph_key, + struct ecc_public_key *peer_key, + struct ecc_public_key *peer_eph_key, + struct sm2_kep_parms *p) +{ + TEE_Result res = TEE_SUCCESS; + ecc_key ltc_my_key = { }; + ecc_key ltc_my_eph_key = { }; + ecc_key ltc_peer_key = { }; + ecc_key ltc_peer_eph_key = { }; + + res = ecc_populate_ltc_private_key(<c_my_key, my_key, + TEE_ALG_SM2_KEP, NULL); + if (res) + goto out; + + res = ecc_populate_ltc_private_key(<c_my_eph_key, my_eph_key, + TEE_ALG_SM2_KEP, NULL); + if (res) + goto out; + + res = ecc_populate_ltc_public_key(<c_peer_key, peer_key, + TEE_ALG_SM2_KEP, NULL); + if (res) + goto out; + + res = ecc_populate_ltc_public_key(<c_peer_eph_key, peer_eph_key, + TEE_ALG_SM2_KEP, NULL); + if (res) + goto out; + + res = sm2_kep_derive(<c_my_key, <c_my_eph_key, <c_peer_key, + <c_peer_eph_key, p); +out: + ecc_free(<c_peer_eph_key); + ecc_free(<c_peer_key); + ecc_free(<c_my_eph_key); + ecc_free(<c_my_key); + return res; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/sm2-pke.c b/optee/optee_os/core/lib/libtomcrypt/sm2-pke.c new file mode 100644 index 0000000..56a3cc5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sm2-pke.c @@ -0,0 +1,515 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + +/* SM2 uses 256 bit unsigned integers in big endian format */ +#define SM2_INT_SIZE_BYTES 32 + +static TEE_Result +sm2_uncompressed_bytes_to_point(ecc_point *p, const ltc_ecc_dp *dp, + const uint8_t *x1y1, size_t max_size, + size_t *consumed) +{ + uint8_t *ptr = (uint8_t *)x1y1; + uint8_t one[] = { 1 }; + int ltc_res = 0; + + if (max_size < (size_t)(2 * SM2_INT_SIZE_BYTES)) + return TEE_ERROR_BAD_PARAMETERS; + + ltc_res = mp_read_unsigned_bin(p->x, ptr, SM2_INT_SIZE_BYTES); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + ptr += SM2_INT_SIZE_BYTES; + + ltc_res = mp_read_unsigned_bin(p->y, ptr, SM2_INT_SIZE_BYTES); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + ltc_res = ltc_ecc_is_point(dp, p->x, p->y); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + mp_read_unsigned_bin(p->z, one, sizeof(one)); + + *consumed = 2 * SM2_INT_SIZE_BYTES + 1; /* PC */ + + return TEE_SUCCESS; +} + +/* + * GM/T 0003.1‒2012 Part 1 Section 4.2.9 + * Conversion of a byte string @buf to a point @p. Makes sure @p is on the curve + * defined by domain parameters @dp. + * Note: only the uncompressed form is supported. Uncompressed and hybrid forms + * are TBD. + */ +static TEE_Result sm2_bytes_to_point(ecc_point *p, const ltc_ecc_dp *dp, + const uint8_t *buf, size_t max_size, + size_t *consumed) +{ + uint8_t PC = 0; + + if (!max_size) + return TEE_ERROR_BAD_PARAMETERS; + + PC = buf[0]; + + switch (PC) { + case 0x02: + case 0x03: + /* Compressed form */ + return TEE_ERROR_NOT_SUPPORTED; + case 0x04: + /* UNcompressed form */ + return sm2_uncompressed_bytes_to_point(p, dp, buf + 1, + max_size - 1, consumed); + case 0x06: + case 0x07: + /* Hybrid form */ + return TEE_ERROR_NOT_SUPPORTED; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_ERROR_GENERIC; +} + +static bool is_zero(const uint8_t *buf, size_t size) +{ + uint8_t v = 0; + size_t i = 0; + + for (i = 0; i < size; i++) + v |= buf[i]; + + return !v; +} + +/* + * GM/T 0003.1‒2012 Part 4 Section 7.1 + * Decryption algorithm + */ +TEE_Result sm2_ltc_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, + size_t src_len, uint8_t *dst, size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t x2y2[64] = { }; + ecc_key ltc_key = { }; + ecc_point *C1 = NULL; + size_t C1_len = 0; + ecc_point *S = NULL; + ecc_point *x2y2p = NULL; + void *ctx = NULL; + int ltc_res = 0; + void *h = NULL; + int inf = 0; + uint8_t *t = NULL; + size_t C2_len = 0; + size_t i = 0; + size_t out_len = 0; + uint8_t *eom = NULL; + uint8_t u[TEE_SM3_HASH_SIZE] = { }; + + /* + * Input buffer src is (C1 || C2 || C3) + * - C1 represents a point (should be on the curve) + * - C2 is the encrypted message + * - C3 is a SM3 hash + */ + + res = ecc_populate_ltc_private_key(<c_key, key, TEE_ALG_SM2_PKE, + NULL); + if (res) + goto out; + + /* Step B1: read and validate point C1 from encrypted message */ + + C1 = ltc_ecc_new_point(); + if (!C1) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = sm2_bytes_to_point(C1, <c_key.dp, src, src_len, &C1_len); + if (res) + goto out; + + /* Step B2: S = [h]C1 */ + + if (ltc_key.dp.cofactor != 1) { + S = ltc_ecc_new_point(); + if (!S) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = mp_init_multi(&h, NULL); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = mp_set_int(h, ltc_key.dp.cofactor); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + ltc_res = ltc_ecc_mulmod(h, C1, S, ltc_key.dp.A, + ltc_key.dp.prime, 1); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, + &inf); + } else { + ltc_res = ltc_ecc_is_point_at_infinity(C1, ltc_key.dp.prime, + &inf); + } + if (ltc_res != CRYPT_OK || inf) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step B3: (x2, y2) = [dB]C1 */ + + x2y2p = ltc_ecc_new_point(); + if (!x2y2p) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = ltc_ecc_mulmod(ltc_key.k, C1, x2y2p, ltc_key.dp.A, + ltc_key.dp.prime, 1); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES || + mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES); + mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + + /* Step B4: t = KDF(x2 || y2, klen) */ + + /* C = C1 || C2 || C3 */ + if (src_len <= C1_len + TEE_SM3_HASH_SIZE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + C2_len = src_len - C1_len - TEE_SM3_HASH_SIZE; + + t = calloc(1, C2_len); + if (!t) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = sm2_kdf(x2y2, sizeof(x2y2), t, C2_len); + if (res) + goto out; + + if (is_zero(t, C2_len)) { + res = TEE_ERROR_CIPHERTEXT_INVALID; + goto out; + } + + /* Step B5: get C2 from C and compute Mprime = C2 (+) t */ + + out_len = MIN(*dst_len, C2_len); + for (i = 0; i < out_len; i++) + dst[i] = src[C1_len + i] ^ t[i]; + *dst_len = out_len; + if (out_len < C2_len) { + eom = calloc(1, C2_len - out_len); + if (!eom) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + for (i = out_len; i < C2_len; i++) + eom[i - out_len] = src[C1_len + i] ^ t[i]; + } + + /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */ + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + goto out; + res = crypto_hash_init(ctx); + if (res) + goto out; + res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); + if (res) + goto out; + res = crypto_hash_update(ctx, dst, out_len); + if (res) + goto out; + if (out_len < C2_len) { + res = crypto_hash_update(ctx, eom, C2_len - out_len); + if (res) + goto out; + } + res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (res) + goto out; + res = crypto_hash_final(ctx, u, sizeof(u)); + if (res) + goto out; + + if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) { + res = TEE_ERROR_CIPHERTEXT_INVALID; + goto out; + } +out: + free(eom); + free(t); + crypto_hash_free_ctx(ctx); + ltc_ecc_del_point(x2y2p); + ltc_ecc_del_point(S); + ltc_ecc_del_point(C1); + mp_clear_multi(h, NULL); + ecc_free(<c_key); + return res; +} + +/* + * GM/T 0003.1‒2012 Part 1 Section 4.2.8 + * Conversion of point @p to a byte string @buf (uncompressed form). + */ +static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size, + const ecc_point *p) +{ + size_t xsize = mp_unsigned_bin_size(p->x); + size_t ysize = mp_unsigned_bin_size(p->y); + size_t sz = 2 * SM2_INT_SIZE_BYTES + 1; + + if (xsize > SM2_INT_SIZE_BYTES || ysize > SM2_INT_SIZE_BYTES || + *size < sz) + return TEE_ERROR_BAD_STATE; + + memset(buf, 0, sz); + buf[0] = 0x04; /* Uncompressed form indicator */ + mp_to_unsigned_bin2(p->x, buf + 1, SM2_INT_SIZE_BYTES); + mp_to_unsigned_bin2(p->y, buf + 1 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + + *size = sz; + + return TEE_SUCCESS; +} + +/* + * GM/T 0003.1‒2012 Part 4 Section 6.1 + * Encryption algorithm + */ +TEE_Result sm2_ltc_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, + size_t src_len, uint8_t *dst, size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + ecc_key ltc_key = { }; + ecc_point *x2y2p = NULL; + ecc_point *C1 = NULL; + ecc_point *S = NULL; + uint8_t x2y2[64] = { }; + uint8_t *t = NULL; + int ltc_res = 0; + void *k = NULL; + void *h = NULL; + int inf = 0; + size_t C1_len = 0; + void *ctx = NULL; + size_t i = 0; + + ltc_res = mp_init_multi(&k, &h, NULL); + if (ltc_res != CRYPT_OK) + return TEE_ERROR_OUT_OF_MEMORY; + + res = ecc_populate_ltc_public_key(<c_key, key, TEE_ALG_SM2_PKE, NULL); + if (res) + goto out; + + /* Step A1: generate random number 1 <= k < n */ + + ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL, + find_prng("prng_crypto")); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step A2: compute C1 = [k]G */ + + C1 = ltc_ecc_new_point(); + if (!C1) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, C1, ltc_key.dp.A, + ltc_key.dp.prime, 1); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step A3: compute S = [h]PB and check for infinity */ + + if (ltc_key.dp.cofactor != 1) { + S = ltc_ecc_new_point(); + if (!S) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = mp_set_int(h, ltc_key.dp.cofactor); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + ltc_res = ltc_ecc_mulmod(h, <c_key.pubkey, S, ltc_key.dp.A, + ltc_key.dp.prime, 1); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, + &inf); + } else { + ltc_res = ltc_ecc_is_point_at_infinity(<c_key.pubkey, + ltc_key.dp.prime, &inf); + } + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + if (inf) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step A4: compute (x2, y2) = [k]PB */ + + x2y2p = ltc_ecc_new_point(); + if (!x2y2p) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + ltc_res = ltc_ecc_mulmod(k, <c_key.pubkey, x2y2p, ltc_key.dp.A, + ltc_key.dp.prime, 1); + if (ltc_res != CRYPT_OK) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES || + mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES); + mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + + /* Step A5: compute t = KDF(x2 || y2, klen) */ + + t = calloc(1, src_len); + if (!t) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = sm2_kdf(x2y2, sizeof(x2y2), t, src_len); + if (res) + goto out; + + if (is_zero(t, src_len)) { + res = TEE_ERROR_CIPHERTEXT_INVALID; + goto out; + } + + /* + * Steps A6, A7, A8: + * Compute C2 = M (+) t + * Compute C3 = Hash(x2 || M || y2) + * Output C = C1 || C2 || C3 + */ + + /* C1 */ + C1_len = *dst_len; + res = sm2_point_to_bytes(dst, &C1_len, C1); + if (res) + goto out; + + if (*dst_len < C1_len + src_len + TEE_SM3_HASH_SIZE) { + *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + /* C2 */ + for (i = 0; i < src_len; i++) + dst[i + C1_len] = src[i] ^ t[i]; + + /* C3 */ + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + goto out; + res = crypto_hash_init(ctx); + if (res) + goto out; + res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); + if (res) + goto out; + res = crypto_hash_update(ctx, src, src_len); + if (res) + goto out; + res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (res) + goto out; + res = crypto_hash_final(ctx, dst + C1_len + src_len, TEE_SM3_HASH_SIZE); + if (res) + goto out; + + *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; +out: + crypto_hash_free_ctx(ctx); + free(t); + ltc_ecc_del_point(x2y2p); + ltc_ecc_del_point(S); + ltc_ecc_del_point(C1); + ecc_free(<c_key); + mp_clear_multi(k, h, NULL); + return res; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes.c new file mode 100644 index 0000000..dd6f14e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes.c @@ -0,0 +1,744 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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_private.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, 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, 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, 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, NULL, NULL +}; + +#endif + +#define LTC_AES_TAB_C +#include "aes_tab.c" + +static ulong32 setup_mix(ulong32 temp) +{ + return (Te4_3[LTC_BYTE(temp, 2)]) ^ + (Te4_2[LTC_BYTE(temp, 1)]) ^ + (Te4_1[LTC_BYTE(temp, 0)]) ^ + (Te4_0[LTC_BYTE(temp, 3)]); +} + +#ifndef ENCRYPT_ONLY +#ifdef LTC_SMALL_CODE +static ulong32 setup_mix2(ulong32 temp) +{ + return Td0(255 & Te4[LTC_BYTE(temp, 3)]) ^ + Td1(255 & Te4[LTC_BYTE(temp, 2)]) ^ + Td2(255 & Te4[LTC_BYTE(temp, 1)]) ^ + Td3(255 & Te4[LTC_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; + 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) { + 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) { + 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) { + 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 */ + /* coverity[dead_error_line] */ + return CRYPT_ERROR; + } + +#ifndef ENCRYPT_ONLY + /* setup the inverse key now */ + rk = skey->rijndael.dK; + rrk = skey->rijndael.eK + (28 + keylen) - 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[LTC_BYTE(temp, 3)] ^ + Tks1[LTC_BYTE(temp, 2)] ^ + Tks2[LTC_BYTE(temp, 1)] ^ + Tks3[LTC_BYTE(temp, 0)]; + temp = rrk[1]; + rk[1] = + Tks0[LTC_BYTE(temp, 3)] ^ + Tks1[LTC_BYTE(temp, 2)] ^ + Tks2[LTC_BYTE(temp, 1)] ^ + Tks3[LTC_BYTE(temp, 0)]; + temp = rrk[2]; + rk[2] = + Tks0[LTC_BYTE(temp, 3)] ^ + Tks1[LTC_BYTE(temp, 2)] ^ + Tks2[LTC_BYTE(temp, 1)] ^ + Tks3[LTC_BYTE(temp, 0)]; + temp = rrk[3]; + rk[3] = + Tks0[LTC_BYTE(temp, 3)] ^ + Tks1[LTC_BYTE(temp, 2)] ^ + Tks2[LTC_BYTE(temp, 1)] ^ + Tks3[LTC_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 s_rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 s0, s1, s2, s3, t0, t1, t2, t3; + const ulong32 *rk; + int Nr, r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + Nr = skey->rijndael.Nr; + + if (Nr < 2 || Nr > 16) + return CRYPT_INVALID_ROUNDS; + + 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(LTC_BYTE(s0, 3)) ^ + Te1(LTC_BYTE(s1, 2)) ^ + Te2(LTC_BYTE(s2, 1)) ^ + Te3(LTC_BYTE(s3, 0)) ^ + rk[0]; + t1 = + Te0(LTC_BYTE(s1, 3)) ^ + Te1(LTC_BYTE(s2, 2)) ^ + Te2(LTC_BYTE(s3, 1)) ^ + Te3(LTC_BYTE(s0, 0)) ^ + rk[1]; + t2 = + Te0(LTC_BYTE(s2, 3)) ^ + Te1(LTC_BYTE(s3, 2)) ^ + Te2(LTC_BYTE(s0, 1)) ^ + Te3(LTC_BYTE(s1, 0)) ^ + rk[2]; + t3 = + Te0(LTC_BYTE(s3, 3)) ^ + Te1(LTC_BYTE(s0, 2)) ^ + Te2(LTC_BYTE(s1, 1)) ^ + Te3(LTC_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(LTC_BYTE(s0, 3)) ^ + Te1(LTC_BYTE(s1, 2)) ^ + Te2(LTC_BYTE(s2, 1)) ^ + Te3(LTC_BYTE(s3, 0)) ^ + rk[4]; + t1 = + Te0(LTC_BYTE(s1, 3)) ^ + Te1(LTC_BYTE(s2, 2)) ^ + Te2(LTC_BYTE(s3, 1)) ^ + Te3(LTC_BYTE(s0, 0)) ^ + rk[5]; + t2 = + Te0(LTC_BYTE(s2, 3)) ^ + Te1(LTC_BYTE(s3, 2)) ^ + Te2(LTC_BYTE(s0, 1)) ^ + Te3(LTC_BYTE(s1, 0)) ^ + rk[6]; + t3 = + Te0(LTC_BYTE(s3, 3)) ^ + Te1(LTC_BYTE(s0, 2)) ^ + Te2(LTC_BYTE(s1, 1)) ^ + Te3(LTC_BYTE(s2, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0(LTC_BYTE(t0, 3)) ^ + Te1(LTC_BYTE(t1, 2)) ^ + Te2(LTC_BYTE(t2, 1)) ^ + Te3(LTC_BYTE(t3, 0)) ^ + rk[0]; + s1 = + Te0(LTC_BYTE(t1, 3)) ^ + Te1(LTC_BYTE(t2, 2)) ^ + Te2(LTC_BYTE(t3, 1)) ^ + Te3(LTC_BYTE(t0, 0)) ^ + rk[1]; + s2 = + Te0(LTC_BYTE(t2, 3)) ^ + Te1(LTC_BYTE(t3, 2)) ^ + Te2(LTC_BYTE(t0, 1)) ^ + Te3(LTC_BYTE(t1, 0)) ^ + rk[2]; + s3 = + Te0(LTC_BYTE(t3, 3)) ^ + Te1(LTC_BYTE(t0, 2)) ^ + Te2(LTC_BYTE(t1, 1)) ^ + Te3(LTC_BYTE(t2, 0)) ^ + rk[3]; + } + +#endif + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4_3[LTC_BYTE(t0, 3)]) ^ + (Te4_2[LTC_BYTE(t1, 2)]) ^ + (Te4_1[LTC_BYTE(t2, 1)]) ^ + (Te4_0[LTC_BYTE(t3, 0)]) ^ + rk[0]; + STORE32H(s0, ct); + s1 = + (Te4_3[LTC_BYTE(t1, 3)]) ^ + (Te4_2[LTC_BYTE(t2, 2)]) ^ + (Te4_1[LTC_BYTE(t3, 1)]) ^ + (Te4_0[LTC_BYTE(t0, 0)]) ^ + rk[1]; + STORE32H(s1, ct+4); + s2 = + (Te4_3[LTC_BYTE(t2, 3)]) ^ + (Te4_2[LTC_BYTE(t3, 2)]) ^ + (Te4_1[LTC_BYTE(t0, 1)]) ^ + (Te4_0[LTC_BYTE(t1, 0)]) ^ + rk[2]; + STORE32H(s2, ct+8); + s3 = + (Te4_3[LTC_BYTE(t3, 3)]) ^ + (Te4_2[LTC_BYTE(t0, 2)]) ^ + (Te4_1[LTC_BYTE(t1, 1)]) ^ + (Te4_0[LTC_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, const symmetric_key *skey) +{ + int err = s_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 s_rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 s0, s1, s2, s3, t0, t1, t2, t3; + const ulong32 *rk; + int Nr, r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + Nr = skey->rijndael.Nr; + + if (Nr < 2 || Nr > 16) + return CRYPT_INVALID_ROUNDS; + + 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(LTC_BYTE(s0, 3)) ^ + Td1(LTC_BYTE(s3, 2)) ^ + Td2(LTC_BYTE(s2, 1)) ^ + Td3(LTC_BYTE(s1, 0)) ^ + rk[0]; + t1 = + Td0(LTC_BYTE(s1, 3)) ^ + Td1(LTC_BYTE(s0, 2)) ^ + Td2(LTC_BYTE(s3, 1)) ^ + Td3(LTC_BYTE(s2, 0)) ^ + rk[1]; + t2 = + Td0(LTC_BYTE(s2, 3)) ^ + Td1(LTC_BYTE(s1, 2)) ^ + Td2(LTC_BYTE(s0, 1)) ^ + Td3(LTC_BYTE(s3, 0)) ^ + rk[2]; + t3 = + Td0(LTC_BYTE(s3, 3)) ^ + Td1(LTC_BYTE(s2, 2)) ^ + Td2(LTC_BYTE(s1, 1)) ^ + Td3(LTC_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(LTC_BYTE(s0, 3)) ^ + Td1(LTC_BYTE(s3, 2)) ^ + Td2(LTC_BYTE(s2, 1)) ^ + Td3(LTC_BYTE(s1, 0)) ^ + rk[4]; + t1 = + Td0(LTC_BYTE(s1, 3)) ^ + Td1(LTC_BYTE(s0, 2)) ^ + Td2(LTC_BYTE(s3, 1)) ^ + Td3(LTC_BYTE(s2, 0)) ^ + rk[5]; + t2 = + Td0(LTC_BYTE(s2, 3)) ^ + Td1(LTC_BYTE(s1, 2)) ^ + Td2(LTC_BYTE(s0, 1)) ^ + Td3(LTC_BYTE(s3, 0)) ^ + rk[6]; + t3 = + Td0(LTC_BYTE(s3, 3)) ^ + Td1(LTC_BYTE(s2, 2)) ^ + Td2(LTC_BYTE(s1, 1)) ^ + Td3(LTC_BYTE(s0, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + + s0 = + Td0(LTC_BYTE(t0, 3)) ^ + Td1(LTC_BYTE(t3, 2)) ^ + Td2(LTC_BYTE(t2, 1)) ^ + Td3(LTC_BYTE(t1, 0)) ^ + rk[0]; + s1 = + Td0(LTC_BYTE(t1, 3)) ^ + Td1(LTC_BYTE(t0, 2)) ^ + Td2(LTC_BYTE(t3, 1)) ^ + Td3(LTC_BYTE(t2, 0)) ^ + rk[1]; + s2 = + Td0(LTC_BYTE(t2, 3)) ^ + Td1(LTC_BYTE(t1, 2)) ^ + Td2(LTC_BYTE(t0, 1)) ^ + Td3(LTC_BYTE(t3, 0)) ^ + rk[2]; + s3 = + Td0(LTC_BYTE(t3, 3)) ^ + Td1(LTC_BYTE(t2, 2)) ^ + Td2(LTC_BYTE(t1, 1)) ^ + Td3(LTC_BYTE(t0, 0)) ^ + rk[3]; + } +#endif + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[LTC_BYTE(t0, 3)] & 0xff000000) ^ + (Td4[LTC_BYTE(t3, 2)] & 0x00ff0000) ^ + (Td4[LTC_BYTE(t2, 1)] & 0x0000ff00) ^ + (Td4[LTC_BYTE(t1, 0)] & 0x000000ff) ^ + rk[0]; + STORE32H(s0, pt); + s1 = + (Td4[LTC_BYTE(t1, 3)] & 0xff000000) ^ + (Td4[LTC_BYTE(t0, 2)] & 0x00ff0000) ^ + (Td4[LTC_BYTE(t3, 1)] & 0x0000ff00) ^ + (Td4[LTC_BYTE(t2, 0)] & 0x000000ff) ^ + rk[1]; + STORE32H(s1, pt+4); + s2 = + (Td4[LTC_BYTE(t2, 3)] & 0xff000000) ^ + (Td4[LTC_BYTE(t1, 2)] & 0x00ff0000) ^ + (Td4[LTC_BYTE(t0, 1)] & 0x0000ff00) ^ + (Td4[LTC_BYTE(t3, 0)] & 0x000000ff) ^ + rk[2]; + STORE32H(s2, pt+8); + s3 = + (Td4[LTC_BYTE(t3, 3)] & 0xff000000) ^ + (Td4[LTC_BYTE(t2, 2)] & 0x00ff0000) ^ + (Td4[LTC_BYTE(t1, 1)] & 0x0000ff00) ^ + (Td4[LTC_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, const symmetric_key *skey) +{ + int err = s_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 (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i) || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { + 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) +{ + LTC_UNUSED_PARAM(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; + } + if (*keysize < 32) { + *keysize = 24; + return CRYPT_OK; + } + *keysize = 32; + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c new file mode 100644 index 0000000..5e59004 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c @@ -0,0 +1,1022 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* 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]; +*/ + +#ifdef LTC_AES_TAB_C + +/** + @file aes_tab.c + AES tables +*/ +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, +}; + +#if !defined(PELI_TAB) && defined(LTC_SMALL_CODE) +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 */ + +#ifndef PELI_TAB +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 */ +}; +#endif + +#endif /* LTC_AES_TAB_C */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/sub.mk new file mode 100644 index 0000000..ac7b507 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/aes/sub.mk @@ -0,0 +1,5 @@ +cflags-y += -Wno-unused-parameter + +ifneq ($(_CFG_CORE_LTC_AES_ACCEL),y) +srcs-$(_CFG_CORE_LTC_AES_DESC) += aes.c +endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/anubis.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/anubis.c new file mode 100644 index 0000000..f6a1c58 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/anubis.c @@ -0,0 +1,1550 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file anubis.c + Anubis implementation derived from public domain source + Authors: Paulo S.L.M. Barreto and Vincent Rijmen. +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_ANUBIS + +const struct ltc_cipher_descriptor anubis_desc = { + "anubis", + 19, + 16, 40, 16, 12, + &anubis_setup, + &anubis_ecb_encrypt, + &anubis_ecb_decrypt, + &anubis_test, + &anubis_done, + &anubis_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#define MAX_N 10 + +/* + * Though Anubis is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ +#if defined(LTC_ANUBIS_TWEAK) + +static const ulong32 T0[256] = { + 0xba69d2bbU, 0x54a84de5U, 0x2f5ebce2U, 0x74e8cd25U, + 0x53a651f7U, 0xd3bb6bd0U, 0xd2b96fd6U, 0x4d9a29b3U, + 0x50a05dfdU, 0xac458acfU, 0x8d070e09U, 0xbf63c6a5U, + 0x70e0dd3dU, 0x52a455f1U, 0x9a29527bU, 0x4c982db5U, + 0xeac98f46U, 0xd5b773c4U, 0x97336655U, 0xd1bf63dcU, + 0x3366ccaaU, 0x51a259fbU, 0x5bb671c7U, 0xa651a2f3U, + 0xdea15ffeU, 0x48903dadU, 0xa84d9ad7U, 0x992f5e71U, + 0xdbab4be0U, 0x3264c8acU, 0xb773e695U, 0xfce5d732U, + 0xe3dbab70U, 0x9e214263U, 0x913f7e41U, 0x9b2b567dU, + 0xe2d9af76U, 0xbb6bd6bdU, 0x4182199bU, 0x6edca579U, + 0xa557aef9U, 0xcb8b0b80U, 0x6bd6b167U, 0x95376e59U, + 0xa15fbee1U, 0xf3fbeb10U, 0xb17ffe81U, 0x0204080cU, + 0xcc851792U, 0xc49537a2U, 0x1d3a744eU, 0x14285078U, + 0xc39b2bb0U, 0x63c69157U, 0xdaa94fe6U, 0x5dba69d3U, + 0x5fbe61dfU, 0xdca557f2U, 0x7dfae913U, 0xcd871394U, + 0x7ffee11fU, 0x5ab475c1U, 0x6cd8ad75U, 0x5cb86dd5U, + 0xf7f3fb08U, 0x264c98d4U, 0xffe3db38U, 0xedc79354U, + 0xe8cd874aU, 0x9d274e69U, 0x6fdea17fU, 0x8e010203U, + 0x19326456U, 0xa05dbae7U, 0xf0fde71aU, 0x890f1e11U, + 0x0f1e3c22U, 0x070e1c12U, 0xaf4386c5U, 0xfbebcb20U, + 0x08102030U, 0x152a547eU, 0x0d1a342eU, 0x04081018U, + 0x01020406U, 0x64c88d45U, 0xdfa35bf8U, 0x76ecc529U, + 0x79f2f90bU, 0xdda753f4U, 0x3d7af48eU, 0x162c5874U, + 0x3f7efc82U, 0x376edcb2U, 0x6ddaa973U, 0x3870e090U, + 0xb96fdeb1U, 0x73e6d137U, 0xe9cf834cU, 0x356ad4beU, + 0x55aa49e3U, 0x71e2d93bU, 0x7bf6f107U, 0x8c050a0fU, + 0x72e4d531U, 0x880d1a17U, 0xf6f1ff0eU, 0x2a54a8fcU, + 0x3e7cf884U, 0x5ebc65d9U, 0x274e9cd2U, 0x468c0589U, + 0x0c183028U, 0x65ca8943U, 0x68d0bd6dU, 0x61c2995bU, + 0x03060c0aU, 0xc19f23bcU, 0x57ae41efU, 0xd6b17fceU, + 0xd9af43ecU, 0x58b07dcdU, 0xd8ad47eaU, 0x66cc8549U, + 0xd7b37bc8U, 0x3a74e89cU, 0xc88d078aU, 0x3c78f088U, + 0xfae9cf26U, 0x96316253U, 0xa753a6f5U, 0x982d5a77U, + 0xecc59752U, 0xb86ddab7U, 0xc7933ba8U, 0xae4182c3U, + 0x69d2b96bU, 0x4b9631a7U, 0xab4b96ddU, 0xa94f9ed1U, + 0x67ce814fU, 0x0a14283cU, 0x478e018fU, 0xf2f9ef16U, + 0xb577ee99U, 0x224488ccU, 0xe5d7b364U, 0xeec19f5eU, + 0xbe61c2a3U, 0x2b56acfaU, 0x811f3e21U, 0x1224486cU, + 0x831b362dU, 0x1b366c5aU, 0x0e1c3824U, 0x23468ccaU, + 0xf5f7f304U, 0x458a0983U, 0x214284c6U, 0xce811f9eU, + 0x499239abU, 0x2c58b0e8U, 0xf9efc32cU, 0xe6d1bf6eU, + 0xb671e293U, 0x2850a0f0U, 0x172e5c72U, 0x8219322bU, + 0x1a34685cU, 0x8b0b161dU, 0xfee1df3eU, 0x8a09121bU, + 0x09122436U, 0xc98f038cU, 0x87132635U, 0x4e9c25b9U, + 0xe1dfa37cU, 0x2e5cb8e4U, 0xe4d5b762U, 0xe0dda77aU, + 0xebcb8b40U, 0x903d7a47U, 0xa455aaffU, 0x1e3c7844U, + 0x85172e39U, 0x60c09d5dU, 0x00000000U, 0x254a94deU, + 0xf4f5f702U, 0xf1ffe31cU, 0x94356a5fU, 0x0b162c3aU, + 0xe7d3bb68U, 0x75eac923U, 0xefc39b58U, 0x3468d0b8U, + 0x3162c4a6U, 0xd4b577c2U, 0xd0bd67daU, 0x86112233U, + 0x7efce519U, 0xad478ec9U, 0xfde7d334U, 0x2952a4f6U, + 0x3060c0a0U, 0x3b76ec9aU, 0x9f234665U, 0xf8edc72aU, + 0xc6913faeU, 0x13264c6aU, 0x060c1814U, 0x050a141eU, + 0xc59733a4U, 0x11224466U, 0x77eec12fU, 0x7cf8ed15U, + 0x7af4f501U, 0x78f0fd0dU, 0x366cd8b4U, 0x1c387048U, + 0x3972e496U, 0x59b279cbU, 0x18306050U, 0x56ac45e9U, + 0xb37bf68dU, 0xb07dfa87U, 0x244890d8U, 0x204080c0U, + 0xb279f28bU, 0x9239724bU, 0xa35bb6edU, 0xc09d27baU, + 0x44880d85U, 0x62c49551U, 0x10204060U, 0xb475ea9fU, + 0x84152a3fU, 0x43861197U, 0x933b764dU, 0xc2992fb6U, + 0x4a9435a1U, 0xbd67cea9U, 0x8f030605U, 0x2d5ab4eeU, + 0xbc65caafU, 0x9c254a6fU, 0x6ad4b561U, 0x40801d9dU, + 0xcf831b98U, 0xa259b2ebU, 0x801d3a27U, 0x4f9e21bfU, + 0x1f3e7c42U, 0xca890f86U, 0xaa4992dbU, 0x42841591U, +}; + +static const ulong32 T1[256] = { + 0x69babbd2U, 0xa854e54dU, 0x5e2fe2bcU, 0xe87425cdU, + 0xa653f751U, 0xbbd3d06bU, 0xb9d2d66fU, 0x9a4db329U, + 0xa050fd5dU, 0x45accf8aU, 0x078d090eU, 0x63bfa5c6U, + 0xe0703dddU, 0xa452f155U, 0x299a7b52U, 0x984cb52dU, + 0xc9ea468fU, 0xb7d5c473U, 0x33975566U, 0xbfd1dc63U, + 0x6633aaccU, 0xa251fb59U, 0xb65bc771U, 0x51a6f3a2U, + 0xa1defe5fU, 0x9048ad3dU, 0x4da8d79aU, 0x2f99715eU, + 0xabdbe04bU, 0x6432acc8U, 0x73b795e6U, 0xe5fc32d7U, + 0xdbe370abU, 0x219e6342U, 0x3f91417eU, 0x2b9b7d56U, + 0xd9e276afU, 0x6bbbbdd6U, 0x82419b19U, 0xdc6e79a5U, + 0x57a5f9aeU, 0x8bcb800bU, 0xd66b67b1U, 0x3795596eU, + 0x5fa1e1beU, 0xfbf310ebU, 0x7fb181feU, 0x04020c08U, + 0x85cc9217U, 0x95c4a237U, 0x3a1d4e74U, 0x28147850U, + 0x9bc3b02bU, 0xc6635791U, 0xa9dae64fU, 0xba5dd369U, + 0xbe5fdf61U, 0xa5dcf257U, 0xfa7d13e9U, 0x87cd9413U, + 0xfe7f1fe1U, 0xb45ac175U, 0xd86c75adU, 0xb85cd56dU, + 0xf3f708fbU, 0x4c26d498U, 0xe3ff38dbU, 0xc7ed5493U, + 0xcde84a87U, 0x279d694eU, 0xde6f7fa1U, 0x018e0302U, + 0x32195664U, 0x5da0e7baU, 0xfdf01ae7U, 0x0f89111eU, + 0x1e0f223cU, 0x0e07121cU, 0x43afc586U, 0xebfb20cbU, + 0x10083020U, 0x2a157e54U, 0x1a0d2e34U, 0x08041810U, + 0x02010604U, 0xc864458dU, 0xa3dff85bU, 0xec7629c5U, + 0xf2790bf9U, 0xa7ddf453U, 0x7a3d8ef4U, 0x2c167458U, + 0x7e3f82fcU, 0x6e37b2dcU, 0xda6d73a9U, 0x703890e0U, + 0x6fb9b1deU, 0xe67337d1U, 0xcfe94c83U, 0x6a35bed4U, + 0xaa55e349U, 0xe2713bd9U, 0xf67b07f1U, 0x058c0f0aU, + 0xe47231d5U, 0x0d88171aU, 0xf1f60effU, 0x542afca8U, + 0x7c3e84f8U, 0xbc5ed965U, 0x4e27d29cU, 0x8c468905U, + 0x180c2830U, 0xca654389U, 0xd0686dbdU, 0xc2615b99U, + 0x06030a0cU, 0x9fc1bc23U, 0xae57ef41U, 0xb1d6ce7fU, + 0xafd9ec43U, 0xb058cd7dU, 0xadd8ea47U, 0xcc664985U, + 0xb3d7c87bU, 0x743a9ce8U, 0x8dc88a07U, 0x783c88f0U, + 0xe9fa26cfU, 0x31965362U, 0x53a7f5a6U, 0x2d98775aU, + 0xc5ec5297U, 0x6db8b7daU, 0x93c7a83bU, 0x41aec382U, + 0xd2696bb9U, 0x964ba731U, 0x4babdd96U, 0x4fa9d19eU, + 0xce674f81U, 0x140a3c28U, 0x8e478f01U, 0xf9f216efU, + 0x77b599eeU, 0x4422cc88U, 0xd7e564b3U, 0xc1ee5e9fU, + 0x61bea3c2U, 0x562bfaacU, 0x1f81213eU, 0x24126c48U, + 0x1b832d36U, 0x361b5a6cU, 0x1c0e2438U, 0x4623ca8cU, + 0xf7f504f3U, 0x8a458309U, 0x4221c684U, 0x81ce9e1fU, + 0x9249ab39U, 0x582ce8b0U, 0xeff92cc3U, 0xd1e66ebfU, + 0x71b693e2U, 0x5028f0a0U, 0x2e17725cU, 0x19822b32U, + 0x341a5c68U, 0x0b8b1d16U, 0xe1fe3edfU, 0x098a1b12U, + 0x12093624U, 0x8fc98c03U, 0x13873526U, 0x9c4eb925U, + 0xdfe17ca3U, 0x5c2ee4b8U, 0xd5e462b7U, 0xdde07aa7U, + 0xcbeb408bU, 0x3d90477aU, 0x55a4ffaaU, 0x3c1e4478U, + 0x1785392eU, 0xc0605d9dU, 0x00000000U, 0x4a25de94U, + 0xf5f402f7U, 0xfff11ce3U, 0x35945f6aU, 0x160b3a2cU, + 0xd3e768bbU, 0xea7523c9U, 0xc3ef589bU, 0x6834b8d0U, + 0x6231a6c4U, 0xb5d4c277U, 0xbdd0da67U, 0x11863322U, + 0xfc7e19e5U, 0x47adc98eU, 0xe7fd34d3U, 0x5229f6a4U, + 0x6030a0c0U, 0x763b9aecU, 0x239f6546U, 0xedf82ac7U, + 0x91c6ae3fU, 0x26136a4cU, 0x0c061418U, 0x0a051e14U, + 0x97c5a433U, 0x22116644U, 0xee772fc1U, 0xf87c15edU, + 0xf47a01f5U, 0xf0780dfdU, 0x6c36b4d8U, 0x381c4870U, + 0x723996e4U, 0xb259cb79U, 0x30185060U, 0xac56e945U, + 0x7bb38df6U, 0x7db087faU, 0x4824d890U, 0x4020c080U, + 0x79b28bf2U, 0x39924b72U, 0x5ba3edb6U, 0x9dc0ba27U, + 0x8844850dU, 0xc4625195U, 0x20106040U, 0x75b49feaU, + 0x15843f2aU, 0x86439711U, 0x3b934d76U, 0x99c2b62fU, + 0x944aa135U, 0x67bda9ceU, 0x038f0506U, 0x5a2deeb4U, + 0x65bcafcaU, 0x259c6f4aU, 0xd46a61b5U, 0x80409d1dU, + 0x83cf981bU, 0x59a2ebb2U, 0x1d80273aU, 0x9e4fbf21U, + 0x3e1f427cU, 0x89ca860fU, 0x49aadb92U, 0x84429115U, +}; + +static const ulong32 T2[256] = { + 0xd2bbba69U, 0x4de554a8U, 0xbce22f5eU, 0xcd2574e8U, + 0x51f753a6U, 0x6bd0d3bbU, 0x6fd6d2b9U, 0x29b34d9aU, + 0x5dfd50a0U, 0x8acfac45U, 0x0e098d07U, 0xc6a5bf63U, + 0xdd3d70e0U, 0x55f152a4U, 0x527b9a29U, 0x2db54c98U, + 0x8f46eac9U, 0x73c4d5b7U, 0x66559733U, 0x63dcd1bfU, + 0xccaa3366U, 0x59fb51a2U, 0x71c75bb6U, 0xa2f3a651U, + 0x5ffedea1U, 0x3dad4890U, 0x9ad7a84dU, 0x5e71992fU, + 0x4be0dbabU, 0xc8ac3264U, 0xe695b773U, 0xd732fce5U, + 0xab70e3dbU, 0x42639e21U, 0x7e41913fU, 0x567d9b2bU, + 0xaf76e2d9U, 0xd6bdbb6bU, 0x199b4182U, 0xa5796edcU, + 0xaef9a557U, 0x0b80cb8bU, 0xb1676bd6U, 0x6e599537U, + 0xbee1a15fU, 0xeb10f3fbU, 0xfe81b17fU, 0x080c0204U, + 0x1792cc85U, 0x37a2c495U, 0x744e1d3aU, 0x50781428U, + 0x2bb0c39bU, 0x915763c6U, 0x4fe6daa9U, 0x69d35dbaU, + 0x61df5fbeU, 0x57f2dca5U, 0xe9137dfaU, 0x1394cd87U, + 0xe11f7ffeU, 0x75c15ab4U, 0xad756cd8U, 0x6dd55cb8U, + 0xfb08f7f3U, 0x98d4264cU, 0xdb38ffe3U, 0x9354edc7U, + 0x874ae8cdU, 0x4e699d27U, 0xa17f6fdeU, 0x02038e01U, + 0x64561932U, 0xbae7a05dU, 0xe71af0fdU, 0x1e11890fU, + 0x3c220f1eU, 0x1c12070eU, 0x86c5af43U, 0xcb20fbebU, + 0x20300810U, 0x547e152aU, 0x342e0d1aU, 0x10180408U, + 0x04060102U, 0x8d4564c8U, 0x5bf8dfa3U, 0xc52976ecU, + 0xf90b79f2U, 0x53f4dda7U, 0xf48e3d7aU, 0x5874162cU, + 0xfc823f7eU, 0xdcb2376eU, 0xa9736ddaU, 0xe0903870U, + 0xdeb1b96fU, 0xd13773e6U, 0x834ce9cfU, 0xd4be356aU, + 0x49e355aaU, 0xd93b71e2U, 0xf1077bf6U, 0x0a0f8c05U, + 0xd53172e4U, 0x1a17880dU, 0xff0ef6f1U, 0xa8fc2a54U, + 0xf8843e7cU, 0x65d95ebcU, 0x9cd2274eU, 0x0589468cU, + 0x30280c18U, 0x894365caU, 0xbd6d68d0U, 0x995b61c2U, + 0x0c0a0306U, 0x23bcc19fU, 0x41ef57aeU, 0x7fced6b1U, + 0x43ecd9afU, 0x7dcd58b0U, 0x47ead8adU, 0x854966ccU, + 0x7bc8d7b3U, 0xe89c3a74U, 0x078ac88dU, 0xf0883c78U, + 0xcf26fae9U, 0x62539631U, 0xa6f5a753U, 0x5a77982dU, + 0x9752ecc5U, 0xdab7b86dU, 0x3ba8c793U, 0x82c3ae41U, + 0xb96b69d2U, 0x31a74b96U, 0x96ddab4bU, 0x9ed1a94fU, + 0x814f67ceU, 0x283c0a14U, 0x018f478eU, 0xef16f2f9U, + 0xee99b577U, 0x88cc2244U, 0xb364e5d7U, 0x9f5eeec1U, + 0xc2a3be61U, 0xacfa2b56U, 0x3e21811fU, 0x486c1224U, + 0x362d831bU, 0x6c5a1b36U, 0x38240e1cU, 0x8cca2346U, + 0xf304f5f7U, 0x0983458aU, 0x84c62142U, 0x1f9ece81U, + 0x39ab4992U, 0xb0e82c58U, 0xc32cf9efU, 0xbf6ee6d1U, + 0xe293b671U, 0xa0f02850U, 0x5c72172eU, 0x322b8219U, + 0x685c1a34U, 0x161d8b0bU, 0xdf3efee1U, 0x121b8a09U, + 0x24360912U, 0x038cc98fU, 0x26358713U, 0x25b94e9cU, + 0xa37ce1dfU, 0xb8e42e5cU, 0xb762e4d5U, 0xa77ae0ddU, + 0x8b40ebcbU, 0x7a47903dU, 0xaaffa455U, 0x78441e3cU, + 0x2e398517U, 0x9d5d60c0U, 0x00000000U, 0x94de254aU, + 0xf702f4f5U, 0xe31cf1ffU, 0x6a5f9435U, 0x2c3a0b16U, + 0xbb68e7d3U, 0xc92375eaU, 0x9b58efc3U, 0xd0b83468U, + 0xc4a63162U, 0x77c2d4b5U, 0x67dad0bdU, 0x22338611U, + 0xe5197efcU, 0x8ec9ad47U, 0xd334fde7U, 0xa4f62952U, + 0xc0a03060U, 0xec9a3b76U, 0x46659f23U, 0xc72af8edU, + 0x3faec691U, 0x4c6a1326U, 0x1814060cU, 0x141e050aU, + 0x33a4c597U, 0x44661122U, 0xc12f77eeU, 0xed157cf8U, + 0xf5017af4U, 0xfd0d78f0U, 0xd8b4366cU, 0x70481c38U, + 0xe4963972U, 0x79cb59b2U, 0x60501830U, 0x45e956acU, + 0xf68db37bU, 0xfa87b07dU, 0x90d82448U, 0x80c02040U, + 0xf28bb279U, 0x724b9239U, 0xb6eda35bU, 0x27bac09dU, + 0x0d854488U, 0x955162c4U, 0x40601020U, 0xea9fb475U, + 0x2a3f8415U, 0x11974386U, 0x764d933bU, 0x2fb6c299U, + 0x35a14a94U, 0xcea9bd67U, 0x06058f03U, 0xb4ee2d5aU, + 0xcaafbc65U, 0x4a6f9c25U, 0xb5616ad4U, 0x1d9d4080U, + 0x1b98cf83U, 0xb2eba259U, 0x3a27801dU, 0x21bf4f9eU, + 0x7c421f3eU, 0x0f86ca89U, 0x92dbaa49U, 0x15914284U, +}; + +static const ulong32 T3[256] = { + 0xbbd269baU, 0xe54da854U, 0xe2bc5e2fU, 0x25cde874U, + 0xf751a653U, 0xd06bbbd3U, 0xd66fb9d2U, 0xb3299a4dU, + 0xfd5da050U, 0xcf8a45acU, 0x090e078dU, 0xa5c663bfU, + 0x3ddde070U, 0xf155a452U, 0x7b52299aU, 0xb52d984cU, + 0x468fc9eaU, 0xc473b7d5U, 0x55663397U, 0xdc63bfd1U, + 0xaacc6633U, 0xfb59a251U, 0xc771b65bU, 0xf3a251a6U, + 0xfe5fa1deU, 0xad3d9048U, 0xd79a4da8U, 0x715e2f99U, + 0xe04babdbU, 0xacc86432U, 0x95e673b7U, 0x32d7e5fcU, + 0x70abdbe3U, 0x6342219eU, 0x417e3f91U, 0x7d562b9bU, + 0x76afd9e2U, 0xbdd66bbbU, 0x9b198241U, 0x79a5dc6eU, + 0xf9ae57a5U, 0x800b8bcbU, 0x67b1d66bU, 0x596e3795U, + 0xe1be5fa1U, 0x10ebfbf3U, 0x81fe7fb1U, 0x0c080402U, + 0x921785ccU, 0xa23795c4U, 0x4e743a1dU, 0x78502814U, + 0xb02b9bc3U, 0x5791c663U, 0xe64fa9daU, 0xd369ba5dU, + 0xdf61be5fU, 0xf257a5dcU, 0x13e9fa7dU, 0x941387cdU, + 0x1fe1fe7fU, 0xc175b45aU, 0x75add86cU, 0xd56db85cU, + 0x08fbf3f7U, 0xd4984c26U, 0x38dbe3ffU, 0x5493c7edU, + 0x4a87cde8U, 0x694e279dU, 0x7fa1de6fU, 0x0302018eU, + 0x56643219U, 0xe7ba5da0U, 0x1ae7fdf0U, 0x111e0f89U, + 0x223c1e0fU, 0x121c0e07U, 0xc58643afU, 0x20cbebfbU, + 0x30201008U, 0x7e542a15U, 0x2e341a0dU, 0x18100804U, + 0x06040201U, 0x458dc864U, 0xf85ba3dfU, 0x29c5ec76U, + 0x0bf9f279U, 0xf453a7ddU, 0x8ef47a3dU, 0x74582c16U, + 0x82fc7e3fU, 0xb2dc6e37U, 0x73a9da6dU, 0x90e07038U, + 0xb1de6fb9U, 0x37d1e673U, 0x4c83cfe9U, 0xbed46a35U, + 0xe349aa55U, 0x3bd9e271U, 0x07f1f67bU, 0x0f0a058cU, + 0x31d5e472U, 0x171a0d88U, 0x0efff1f6U, 0xfca8542aU, + 0x84f87c3eU, 0xd965bc5eU, 0xd29c4e27U, 0x89058c46U, + 0x2830180cU, 0x4389ca65U, 0x6dbdd068U, 0x5b99c261U, + 0x0a0c0603U, 0xbc239fc1U, 0xef41ae57U, 0xce7fb1d6U, + 0xec43afd9U, 0xcd7db058U, 0xea47add8U, 0x4985cc66U, + 0xc87bb3d7U, 0x9ce8743aU, 0x8a078dc8U, 0x88f0783cU, + 0x26cfe9faU, 0x53623196U, 0xf5a653a7U, 0x775a2d98U, + 0x5297c5ecU, 0xb7da6db8U, 0xa83b93c7U, 0xc38241aeU, + 0x6bb9d269U, 0xa731964bU, 0xdd964babU, 0xd19e4fa9U, + 0x4f81ce67U, 0x3c28140aU, 0x8f018e47U, 0x16eff9f2U, + 0x99ee77b5U, 0xcc884422U, 0x64b3d7e5U, 0x5e9fc1eeU, + 0xa3c261beU, 0xfaac562bU, 0x213e1f81U, 0x6c482412U, + 0x2d361b83U, 0x5a6c361bU, 0x24381c0eU, 0xca8c4623U, + 0x04f3f7f5U, 0x83098a45U, 0xc6844221U, 0x9e1f81ceU, + 0xab399249U, 0xe8b0582cU, 0x2cc3eff9U, 0x6ebfd1e6U, + 0x93e271b6U, 0xf0a05028U, 0x725c2e17U, 0x2b321982U, + 0x5c68341aU, 0x1d160b8bU, 0x3edfe1feU, 0x1b12098aU, + 0x36241209U, 0x8c038fc9U, 0x35261387U, 0xb9259c4eU, + 0x7ca3dfe1U, 0xe4b85c2eU, 0x62b7d5e4U, 0x7aa7dde0U, + 0x408bcbebU, 0x477a3d90U, 0xffaa55a4U, 0x44783c1eU, + 0x392e1785U, 0x5d9dc060U, 0x00000000U, 0xde944a25U, + 0x02f7f5f4U, 0x1ce3fff1U, 0x5f6a3594U, 0x3a2c160bU, + 0x68bbd3e7U, 0x23c9ea75U, 0x589bc3efU, 0xb8d06834U, + 0xa6c46231U, 0xc277b5d4U, 0xda67bdd0U, 0x33221186U, + 0x19e5fc7eU, 0xc98e47adU, 0x34d3e7fdU, 0xf6a45229U, + 0xa0c06030U, 0x9aec763bU, 0x6546239fU, 0x2ac7edf8U, + 0xae3f91c6U, 0x6a4c2613U, 0x14180c06U, 0x1e140a05U, + 0xa43397c5U, 0x66442211U, 0x2fc1ee77U, 0x15edf87cU, + 0x01f5f47aU, 0x0dfdf078U, 0xb4d86c36U, 0x4870381cU, + 0x96e47239U, 0xcb79b259U, 0x50603018U, 0xe945ac56U, + 0x8df67bb3U, 0x87fa7db0U, 0xd8904824U, 0xc0804020U, + 0x8bf279b2U, 0x4b723992U, 0xedb65ba3U, 0xba279dc0U, + 0x850d8844U, 0x5195c462U, 0x60402010U, 0x9fea75b4U, + 0x3f2a1584U, 0x97118643U, 0x4d763b93U, 0xb62f99c2U, + 0xa135944aU, 0xa9ce67bdU, 0x0506038fU, 0xeeb45a2dU, + 0xafca65bcU, 0x6f4a259cU, 0x61b5d46aU, 0x9d1d8040U, + 0x981b83cfU, 0xebb259a2U, 0x273a1d80U, 0xbf219e4fU, + 0x427c3e1fU, 0x860f89caU, 0xdb9249aaU, 0x91158442U, +}; + +static const ulong32 T4[256] = { + 0xbabababaU, 0x54545454U, 0x2f2f2f2fU, 0x74747474U, + 0x53535353U, 0xd3d3d3d3U, 0xd2d2d2d2U, 0x4d4d4d4dU, + 0x50505050U, 0xacacacacU, 0x8d8d8d8dU, 0xbfbfbfbfU, + 0x70707070U, 0x52525252U, 0x9a9a9a9aU, 0x4c4c4c4cU, + 0xeaeaeaeaU, 0xd5d5d5d5U, 0x97979797U, 0xd1d1d1d1U, + 0x33333333U, 0x51515151U, 0x5b5b5b5bU, 0xa6a6a6a6U, + 0xdedededeU, 0x48484848U, 0xa8a8a8a8U, 0x99999999U, + 0xdbdbdbdbU, 0x32323232U, 0xb7b7b7b7U, 0xfcfcfcfcU, + 0xe3e3e3e3U, 0x9e9e9e9eU, 0x91919191U, 0x9b9b9b9bU, + 0xe2e2e2e2U, 0xbbbbbbbbU, 0x41414141U, 0x6e6e6e6eU, + 0xa5a5a5a5U, 0xcbcbcbcbU, 0x6b6b6b6bU, 0x95959595U, + 0xa1a1a1a1U, 0xf3f3f3f3U, 0xb1b1b1b1U, 0x02020202U, + 0xccccccccU, 0xc4c4c4c4U, 0x1d1d1d1dU, 0x14141414U, + 0xc3c3c3c3U, 0x63636363U, 0xdadadadaU, 0x5d5d5d5dU, + 0x5f5f5f5fU, 0xdcdcdcdcU, 0x7d7d7d7dU, 0xcdcdcdcdU, + 0x7f7f7f7fU, 0x5a5a5a5aU, 0x6c6c6c6cU, 0x5c5c5c5cU, + 0xf7f7f7f7U, 0x26262626U, 0xffffffffU, 0xededededU, + 0xe8e8e8e8U, 0x9d9d9d9dU, 0x6f6f6f6fU, 0x8e8e8e8eU, + 0x19191919U, 0xa0a0a0a0U, 0xf0f0f0f0U, 0x89898989U, + 0x0f0f0f0fU, 0x07070707U, 0xafafafafU, 0xfbfbfbfbU, + 0x08080808U, 0x15151515U, 0x0d0d0d0dU, 0x04040404U, + 0x01010101U, 0x64646464U, 0xdfdfdfdfU, 0x76767676U, + 0x79797979U, 0xddddddddU, 0x3d3d3d3dU, 0x16161616U, + 0x3f3f3f3fU, 0x37373737U, 0x6d6d6d6dU, 0x38383838U, + 0xb9b9b9b9U, 0x73737373U, 0xe9e9e9e9U, 0x35353535U, + 0x55555555U, 0x71717171U, 0x7b7b7b7bU, 0x8c8c8c8cU, + 0x72727272U, 0x88888888U, 0xf6f6f6f6U, 0x2a2a2a2aU, + 0x3e3e3e3eU, 0x5e5e5e5eU, 0x27272727U, 0x46464646U, + 0x0c0c0c0cU, 0x65656565U, 0x68686868U, 0x61616161U, + 0x03030303U, 0xc1c1c1c1U, 0x57575757U, 0xd6d6d6d6U, + 0xd9d9d9d9U, 0x58585858U, 0xd8d8d8d8U, 0x66666666U, + 0xd7d7d7d7U, 0x3a3a3a3aU, 0xc8c8c8c8U, 0x3c3c3c3cU, + 0xfafafafaU, 0x96969696U, 0xa7a7a7a7U, 0x98989898U, + 0xececececU, 0xb8b8b8b8U, 0xc7c7c7c7U, 0xaeaeaeaeU, + 0x69696969U, 0x4b4b4b4bU, 0xababababU, 0xa9a9a9a9U, + 0x67676767U, 0x0a0a0a0aU, 0x47474747U, 0xf2f2f2f2U, + 0xb5b5b5b5U, 0x22222222U, 0xe5e5e5e5U, 0xeeeeeeeeU, + 0xbebebebeU, 0x2b2b2b2bU, 0x81818181U, 0x12121212U, + 0x83838383U, 0x1b1b1b1bU, 0x0e0e0e0eU, 0x23232323U, + 0xf5f5f5f5U, 0x45454545U, 0x21212121U, 0xcecececeU, + 0x49494949U, 0x2c2c2c2cU, 0xf9f9f9f9U, 0xe6e6e6e6U, + 0xb6b6b6b6U, 0x28282828U, 0x17171717U, 0x82828282U, + 0x1a1a1a1aU, 0x8b8b8b8bU, 0xfefefefeU, 0x8a8a8a8aU, + 0x09090909U, 0xc9c9c9c9U, 0x87878787U, 0x4e4e4e4eU, + 0xe1e1e1e1U, 0x2e2e2e2eU, 0xe4e4e4e4U, 0xe0e0e0e0U, + 0xebebebebU, 0x90909090U, 0xa4a4a4a4U, 0x1e1e1e1eU, + 0x85858585U, 0x60606060U, 0x00000000U, 0x25252525U, + 0xf4f4f4f4U, 0xf1f1f1f1U, 0x94949494U, 0x0b0b0b0bU, + 0xe7e7e7e7U, 0x75757575U, 0xefefefefU, 0x34343434U, + 0x31313131U, 0xd4d4d4d4U, 0xd0d0d0d0U, 0x86868686U, + 0x7e7e7e7eU, 0xadadadadU, 0xfdfdfdfdU, 0x29292929U, + 0x30303030U, 0x3b3b3b3bU, 0x9f9f9f9fU, 0xf8f8f8f8U, + 0xc6c6c6c6U, 0x13131313U, 0x06060606U, 0x05050505U, + 0xc5c5c5c5U, 0x11111111U, 0x77777777U, 0x7c7c7c7cU, + 0x7a7a7a7aU, 0x78787878U, 0x36363636U, 0x1c1c1c1cU, + 0x39393939U, 0x59595959U, 0x18181818U, 0x56565656U, + 0xb3b3b3b3U, 0xb0b0b0b0U, 0x24242424U, 0x20202020U, + 0xb2b2b2b2U, 0x92929292U, 0xa3a3a3a3U, 0xc0c0c0c0U, + 0x44444444U, 0x62626262U, 0x10101010U, 0xb4b4b4b4U, + 0x84848484U, 0x43434343U, 0x93939393U, 0xc2c2c2c2U, + 0x4a4a4a4aU, 0xbdbdbdbdU, 0x8f8f8f8fU, 0x2d2d2d2dU, + 0xbcbcbcbcU, 0x9c9c9c9cU, 0x6a6a6a6aU, 0x40404040U, + 0xcfcfcfcfU, 0xa2a2a2a2U, 0x80808080U, 0x4f4f4f4fU, + 0x1f1f1f1fU, 0xcacacacaU, 0xaaaaaaaaU, 0x42424242U, +}; + +static const ulong32 T5[256] = { + 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U, + 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U, + 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U, + 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U, + 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U, + 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U, + 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U, + 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U, + 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U, + 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U, + 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U, + 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U, + 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U, + 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U, + 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U, + 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U, + 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U, + 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U, + 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U, + 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U, + 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U, + 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U, + 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U, + 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U, + 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU, + 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU, + 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU, + 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU, + 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU, + 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU, + 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU, + 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU, + 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU, + 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU, + 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU, + 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU, + 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU, + 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU, + 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU, + 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU, + 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U, + 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U, + 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U, + 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U, + 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U, + 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U, + 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U, + 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U, + 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U, + 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U, + 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U, + 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U, + 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U, + 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U, + 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U, + 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U, + 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU, + 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU, + 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU, + 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU, + 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU, + 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU, + 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU, + 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU, +}; + +/** + * The round constants. + */ +static const ulong32 rc[] = { + 0xba542f74U, 0x53d3d24dU, 0x50ac8dbfU, 0x70529a4cU, + 0xead597d1U, 0x33515ba6U, 0xde48a899U, 0xdb32b7fcU, + 0xe39e919bU, 0xe2bb416eU, 0xa5cb6b95U, 0xa1f3b102U, + 0xccc41d14U, 0xc363da5dU, 0x5fdc7dcdU, 0x7f5a6c5cU, + 0xf726ffedU, 0xe89d6f8eU, 0x19a0f089U, +}; + + + +#else + + +static const ulong32 T0[256] = { + 0xa753a6f5U, 0xd3bb6bd0U, 0xe6d1bf6eU, 0x71e2d93bU, + 0xd0bd67daU, 0xac458acfU, 0x4d9a29b3U, 0x79f2f90bU, + 0x3a74e89cU, 0xc98f038cU, 0x913f7e41U, 0xfce5d732U, + 0x1e3c7844U, 0x478e018fU, 0x54a84de5U, 0xbd67cea9U, + 0x8c050a0fU, 0xa557aef9U, 0x7af4f501U, 0xfbebcb20U, + 0x63c69157U, 0xb86ddab7U, 0xdda753f4U, 0xd4b577c2U, + 0xe5d7b364U, 0xb37bf68dU, 0xc59733a4U, 0xbe61c2a3U, + 0xa94f9ed1U, 0x880d1a17U, 0x0c183028U, 0xa259b2ebU, + 0x3972e496U, 0xdfa35bf8U, 0x2952a4f6U, 0xdaa94fe6U, + 0x2b56acfaU, 0xa84d9ad7U, 0xcb8b0b80U, 0x4c982db5U, + 0x4b9631a7U, 0x224488ccU, 0xaa4992dbU, 0x244890d8U, + 0x4182199bU, 0x70e0dd3dU, 0xa651a2f3U, 0xf9efc32cU, + 0x5ab475c1U, 0xe2d9af76U, 0xb07dfa87U, 0x366cd8b4U, + 0x7dfae913U, 0xe4d5b762U, 0x3366ccaaU, 0xffe3db38U, + 0x60c09d5dU, 0x204080c0U, 0x08102030U, 0x8b0b161dU, + 0x5ebc65d9U, 0xab4b96ddU, 0x7ffee11fU, 0x78f0fd0dU, + 0x7cf8ed15U, 0x2c58b0e8U, 0x57ae41efU, 0xd2b96fd6U, + 0xdca557f2U, 0x6ddaa973U, 0x7efce519U, 0x0d1a342eU, + 0x53a651f7U, 0x94356a5fU, 0xc39b2bb0U, 0x2850a0f0U, + 0x274e9cd2U, 0x060c1814U, 0x5fbe61dfU, 0xad478ec9U, + 0x67ce814fU, 0x5cb86dd5U, 0x55aa49e3U, 0x48903dadU, + 0x0e1c3824U, 0x52a455f1U, 0xeac98f46U, 0x42841591U, + 0x5bb671c7U, 0x5dba69d3U, 0x3060c0a0U, 0x58b07dcdU, + 0x51a259fbU, 0x59b279cbU, 0x3c78f088U, 0x4e9c25b9U, + 0x3870e090U, 0x8a09121bU, 0x72e4d531U, 0x14285078U, + 0xe7d3bb68U, 0xc6913faeU, 0xdea15ffeU, 0x50a05dfdU, + 0x8e010203U, 0x9239724bU, 0xd1bf63dcU, 0x77eec12fU, + 0x933b764dU, 0x458a0983U, 0x9a29527bU, 0xce811f9eU, + 0x2d5ab4eeU, 0x03060c0aU, 0x62c49551U, 0xb671e293U, + 0xb96fdeb1U, 0xbf63c6a5U, 0x96316253U, 0x6bd6b167U, + 0x3f7efc82U, 0x070e1c12U, 0x1224486cU, 0xae4182c3U, + 0x40801d9dU, 0x3468d0b8U, 0x468c0589U, 0x3e7cf884U, + 0xdbab4be0U, 0xcf831b98U, 0xecc59752U, 0xcc851792U, + 0xc19f23bcU, 0xa15fbee1U, 0xc09d27baU, 0xd6b17fceU, + 0x1d3a744eU, 0xf4f5f702U, 0x61c2995bU, 0x3b76ec9aU, + 0x10204060U, 0xd8ad47eaU, 0x68d0bd6dU, 0xa05dbae7U, + 0xb17ffe81U, 0x0a14283cU, 0x69d2b96bU, 0x6cd8ad75U, + 0x499239abU, 0xfae9cf26U, 0x76ecc529U, 0xc49537a2U, + 0x9e214263U, 0x9b2b567dU, 0x6edca579U, 0x992f5e71U, + 0xc2992fb6U, 0xb773e695U, 0x982d5a77U, 0xbc65caafU, + 0x8f030605U, 0x85172e39U, 0x1f3e7c42U, 0xb475ea9fU, + 0xf8edc72aU, 0x11224466U, 0x2e5cb8e4U, 0x00000000U, + 0x254a94deU, 0x1c387048U, 0x2a54a8fcU, 0x3d7af48eU, + 0x050a141eU, 0x4f9e21bfU, 0x7bf6f107U, 0xb279f28bU, + 0x3264c8acU, 0x903d7a47U, 0xaf4386c5U, 0x19326456U, + 0xa35bb6edU, 0xf7f3fb08U, 0x73e6d137U, 0x9d274e69U, + 0x152a547eU, 0x74e8cd25U, 0xeec19f5eU, 0xca890f86U, + 0x9f234665U, 0x0f1e3c22U, 0x1b366c5aU, 0x75eac923U, + 0x86112233U, 0x84152a3fU, 0x9c254a6fU, 0x4a9435a1U, + 0x97336655U, 0x1a34685cU, 0x65ca8943U, 0xf6f1ff0eU, + 0xedc79354U, 0x09122436U, 0xbb6bd6bdU, 0x264c98d4U, + 0x831b362dU, 0xebcb8b40U, 0x6fdea17fU, 0x811f3e21U, + 0x04081018U, 0x6ad4b561U, 0x43861197U, 0x01020406U, + 0x172e5c72U, 0xe1dfa37cU, 0x87132635U, 0xf5f7f304U, + 0x8d070e09U, 0xe3dbab70U, 0x23468ccaU, 0x801d3a27U, + 0x44880d85U, 0x162c5874U, 0x66cc8549U, 0x214284c6U, + 0xfee1df3eU, 0xd5b773c4U, 0x3162c4a6U, 0xd9af43ecU, + 0x356ad4beU, 0x18306050U, 0x0204080cU, 0x64c88d45U, + 0xf2f9ef16U, 0xf1ffe31cU, 0x56ac45e9U, 0xcd871394U, + 0x8219322bU, 0xc88d078aU, 0xba69d2bbU, 0xf0fde71aU, + 0xefc39b58U, 0xe9cf834cU, 0xe8cd874aU, 0xfde7d334U, + 0x890f1e11U, 0xd7b37bc8U, 0xc7933ba8U, 0xb577ee99U, + 0xa455aaffU, 0x2f5ebce2U, 0x95376e59U, 0x13264c6aU, + 0x0b162c3aU, 0xf3fbeb10U, 0xe0dda77aU, 0x376edcb2U, +}; + +static const ulong32 T1[256] = { + 0x53a7f5a6U, 0xbbd3d06bU, 0xd1e66ebfU, 0xe2713bd9U, + 0xbdd0da67U, 0x45accf8aU, 0x9a4db329U, 0xf2790bf9U, + 0x743a9ce8U, 0x8fc98c03U, 0x3f91417eU, 0xe5fc32d7U, + 0x3c1e4478U, 0x8e478f01U, 0xa854e54dU, 0x67bda9ceU, + 0x058c0f0aU, 0x57a5f9aeU, 0xf47a01f5U, 0xebfb20cbU, + 0xc6635791U, 0x6db8b7daU, 0xa7ddf453U, 0xb5d4c277U, + 0xd7e564b3U, 0x7bb38df6U, 0x97c5a433U, 0x61bea3c2U, + 0x4fa9d19eU, 0x0d88171aU, 0x180c2830U, 0x59a2ebb2U, + 0x723996e4U, 0xa3dff85bU, 0x5229f6a4U, 0xa9dae64fU, + 0x562bfaacU, 0x4da8d79aU, 0x8bcb800bU, 0x984cb52dU, + 0x964ba731U, 0x4422cc88U, 0x49aadb92U, 0x4824d890U, + 0x82419b19U, 0xe0703dddU, 0x51a6f3a2U, 0xeff92cc3U, + 0xb45ac175U, 0xd9e276afU, 0x7db087faU, 0x6c36b4d8U, + 0xfa7d13e9U, 0xd5e462b7U, 0x6633aaccU, 0xe3ff38dbU, + 0xc0605d9dU, 0x4020c080U, 0x10083020U, 0x0b8b1d16U, + 0xbc5ed965U, 0x4babdd96U, 0xfe7f1fe1U, 0xf0780dfdU, + 0xf87c15edU, 0x582ce8b0U, 0xae57ef41U, 0xb9d2d66fU, + 0xa5dcf257U, 0xda6d73a9U, 0xfc7e19e5U, 0x1a0d2e34U, + 0xa653f751U, 0x35945f6aU, 0x9bc3b02bU, 0x5028f0a0U, + 0x4e27d29cU, 0x0c061418U, 0xbe5fdf61U, 0x47adc98eU, + 0xce674f81U, 0xb85cd56dU, 0xaa55e349U, 0x9048ad3dU, + 0x1c0e2438U, 0xa452f155U, 0xc9ea468fU, 0x84429115U, + 0xb65bc771U, 0xba5dd369U, 0x6030a0c0U, 0xb058cd7dU, + 0xa251fb59U, 0xb259cb79U, 0x783c88f0U, 0x9c4eb925U, + 0x703890e0U, 0x098a1b12U, 0xe47231d5U, 0x28147850U, + 0xd3e768bbU, 0x91c6ae3fU, 0xa1defe5fU, 0xa050fd5dU, + 0x018e0302U, 0x39924b72U, 0xbfd1dc63U, 0xee772fc1U, + 0x3b934d76U, 0x8a458309U, 0x299a7b52U, 0x81ce9e1fU, + 0x5a2deeb4U, 0x06030a0cU, 0xc4625195U, 0x71b693e2U, + 0x6fb9b1deU, 0x63bfa5c6U, 0x31965362U, 0xd66b67b1U, + 0x7e3f82fcU, 0x0e07121cU, 0x24126c48U, 0x41aec382U, + 0x80409d1dU, 0x6834b8d0U, 0x8c468905U, 0x7c3e84f8U, + 0xabdbe04bU, 0x83cf981bU, 0xc5ec5297U, 0x85cc9217U, + 0x9fc1bc23U, 0x5fa1e1beU, 0x9dc0ba27U, 0xb1d6ce7fU, + 0x3a1d4e74U, 0xf5f402f7U, 0xc2615b99U, 0x763b9aecU, + 0x20106040U, 0xadd8ea47U, 0xd0686dbdU, 0x5da0e7baU, + 0x7fb181feU, 0x140a3c28U, 0xd2696bb9U, 0xd86c75adU, + 0x9249ab39U, 0xe9fa26cfU, 0xec7629c5U, 0x95c4a237U, + 0x219e6342U, 0x2b9b7d56U, 0xdc6e79a5U, 0x2f99715eU, + 0x99c2b62fU, 0x73b795e6U, 0x2d98775aU, 0x65bcafcaU, + 0x038f0506U, 0x1785392eU, 0x3e1f427cU, 0x75b49feaU, + 0xedf82ac7U, 0x22116644U, 0x5c2ee4b8U, 0x00000000U, + 0x4a25de94U, 0x381c4870U, 0x542afca8U, 0x7a3d8ef4U, + 0x0a051e14U, 0x9e4fbf21U, 0xf67b07f1U, 0x79b28bf2U, + 0x6432acc8U, 0x3d90477aU, 0x43afc586U, 0x32195664U, + 0x5ba3edb6U, 0xf3f708fbU, 0xe67337d1U, 0x279d694eU, + 0x2a157e54U, 0xe87425cdU, 0xc1ee5e9fU, 0x89ca860fU, + 0x239f6546U, 0x1e0f223cU, 0x361b5a6cU, 0xea7523c9U, + 0x11863322U, 0x15843f2aU, 0x259c6f4aU, 0x944aa135U, + 0x33975566U, 0x341a5c68U, 0xca654389U, 0xf1f60effU, + 0xc7ed5493U, 0x12093624U, 0x6bbbbdd6U, 0x4c26d498U, + 0x1b832d36U, 0xcbeb408bU, 0xde6f7fa1U, 0x1f81213eU, + 0x08041810U, 0xd46a61b5U, 0x86439711U, 0x02010604U, + 0x2e17725cU, 0xdfe17ca3U, 0x13873526U, 0xf7f504f3U, + 0x078d090eU, 0xdbe370abU, 0x4623ca8cU, 0x1d80273aU, + 0x8844850dU, 0x2c167458U, 0xcc664985U, 0x4221c684U, + 0xe1fe3edfU, 0xb7d5c473U, 0x6231a6c4U, 0xafd9ec43U, + 0x6a35bed4U, 0x30185060U, 0x04020c08U, 0xc864458dU, + 0xf9f216efU, 0xfff11ce3U, 0xac56e945U, 0x87cd9413U, + 0x19822b32U, 0x8dc88a07U, 0x69babbd2U, 0xfdf01ae7U, + 0xc3ef589bU, 0xcfe94c83U, 0xcde84a87U, 0xe7fd34d3U, + 0x0f89111eU, 0xb3d7c87bU, 0x93c7a83bU, 0x77b599eeU, + 0x55a4ffaaU, 0x5e2fe2bcU, 0x3795596eU, 0x26136a4cU, + 0x160b3a2cU, 0xfbf310ebU, 0xdde07aa7U, 0x6e37b2dcU, +}; + +static const ulong32 T2[256] = { + 0xa6f5a753U, 0x6bd0d3bbU, 0xbf6ee6d1U, 0xd93b71e2U, + 0x67dad0bdU, 0x8acfac45U, 0x29b34d9aU, 0xf90b79f2U, + 0xe89c3a74U, 0x038cc98fU, 0x7e41913fU, 0xd732fce5U, + 0x78441e3cU, 0x018f478eU, 0x4de554a8U, 0xcea9bd67U, + 0x0a0f8c05U, 0xaef9a557U, 0xf5017af4U, 0xcb20fbebU, + 0x915763c6U, 0xdab7b86dU, 0x53f4dda7U, 0x77c2d4b5U, + 0xb364e5d7U, 0xf68db37bU, 0x33a4c597U, 0xc2a3be61U, + 0x9ed1a94fU, 0x1a17880dU, 0x30280c18U, 0xb2eba259U, + 0xe4963972U, 0x5bf8dfa3U, 0xa4f62952U, 0x4fe6daa9U, + 0xacfa2b56U, 0x9ad7a84dU, 0x0b80cb8bU, 0x2db54c98U, + 0x31a74b96U, 0x88cc2244U, 0x92dbaa49U, 0x90d82448U, + 0x199b4182U, 0xdd3d70e0U, 0xa2f3a651U, 0xc32cf9efU, + 0x75c15ab4U, 0xaf76e2d9U, 0xfa87b07dU, 0xd8b4366cU, + 0xe9137dfaU, 0xb762e4d5U, 0xccaa3366U, 0xdb38ffe3U, + 0x9d5d60c0U, 0x80c02040U, 0x20300810U, 0x161d8b0bU, + 0x65d95ebcU, 0x96ddab4bU, 0xe11f7ffeU, 0xfd0d78f0U, + 0xed157cf8U, 0xb0e82c58U, 0x41ef57aeU, 0x6fd6d2b9U, + 0x57f2dca5U, 0xa9736ddaU, 0xe5197efcU, 0x342e0d1aU, + 0x51f753a6U, 0x6a5f9435U, 0x2bb0c39bU, 0xa0f02850U, + 0x9cd2274eU, 0x1814060cU, 0x61df5fbeU, 0x8ec9ad47U, + 0x814f67ceU, 0x6dd55cb8U, 0x49e355aaU, 0x3dad4890U, + 0x38240e1cU, 0x55f152a4U, 0x8f46eac9U, 0x15914284U, + 0x71c75bb6U, 0x69d35dbaU, 0xc0a03060U, 0x7dcd58b0U, + 0x59fb51a2U, 0x79cb59b2U, 0xf0883c78U, 0x25b94e9cU, + 0xe0903870U, 0x121b8a09U, 0xd53172e4U, 0x50781428U, + 0xbb68e7d3U, 0x3faec691U, 0x5ffedea1U, 0x5dfd50a0U, + 0x02038e01U, 0x724b9239U, 0x63dcd1bfU, 0xc12f77eeU, + 0x764d933bU, 0x0983458aU, 0x527b9a29U, 0x1f9ece81U, + 0xb4ee2d5aU, 0x0c0a0306U, 0x955162c4U, 0xe293b671U, + 0xdeb1b96fU, 0xc6a5bf63U, 0x62539631U, 0xb1676bd6U, + 0xfc823f7eU, 0x1c12070eU, 0x486c1224U, 0x82c3ae41U, + 0x1d9d4080U, 0xd0b83468U, 0x0589468cU, 0xf8843e7cU, + 0x4be0dbabU, 0x1b98cf83U, 0x9752ecc5U, 0x1792cc85U, + 0x23bcc19fU, 0xbee1a15fU, 0x27bac09dU, 0x7fced6b1U, + 0x744e1d3aU, 0xf702f4f5U, 0x995b61c2U, 0xec9a3b76U, + 0x40601020U, 0x47ead8adU, 0xbd6d68d0U, 0xbae7a05dU, + 0xfe81b17fU, 0x283c0a14U, 0xb96b69d2U, 0xad756cd8U, + 0x39ab4992U, 0xcf26fae9U, 0xc52976ecU, 0x37a2c495U, + 0x42639e21U, 0x567d9b2bU, 0xa5796edcU, 0x5e71992fU, + 0x2fb6c299U, 0xe695b773U, 0x5a77982dU, 0xcaafbc65U, + 0x06058f03U, 0x2e398517U, 0x7c421f3eU, 0xea9fb475U, + 0xc72af8edU, 0x44661122U, 0xb8e42e5cU, 0x00000000U, + 0x94de254aU, 0x70481c38U, 0xa8fc2a54U, 0xf48e3d7aU, + 0x141e050aU, 0x21bf4f9eU, 0xf1077bf6U, 0xf28bb279U, + 0xc8ac3264U, 0x7a47903dU, 0x86c5af43U, 0x64561932U, + 0xb6eda35bU, 0xfb08f7f3U, 0xd13773e6U, 0x4e699d27U, + 0x547e152aU, 0xcd2574e8U, 0x9f5eeec1U, 0x0f86ca89U, + 0x46659f23U, 0x3c220f1eU, 0x6c5a1b36U, 0xc92375eaU, + 0x22338611U, 0x2a3f8415U, 0x4a6f9c25U, 0x35a14a94U, + 0x66559733U, 0x685c1a34U, 0x894365caU, 0xff0ef6f1U, + 0x9354edc7U, 0x24360912U, 0xd6bdbb6bU, 0x98d4264cU, + 0x362d831bU, 0x8b40ebcbU, 0xa17f6fdeU, 0x3e21811fU, + 0x10180408U, 0xb5616ad4U, 0x11974386U, 0x04060102U, + 0x5c72172eU, 0xa37ce1dfU, 0x26358713U, 0xf304f5f7U, + 0x0e098d07U, 0xab70e3dbU, 0x8cca2346U, 0x3a27801dU, + 0x0d854488U, 0x5874162cU, 0x854966ccU, 0x84c62142U, + 0xdf3efee1U, 0x73c4d5b7U, 0xc4a63162U, 0x43ecd9afU, + 0xd4be356aU, 0x60501830U, 0x080c0204U, 0x8d4564c8U, + 0xef16f2f9U, 0xe31cf1ffU, 0x45e956acU, 0x1394cd87U, + 0x322b8219U, 0x078ac88dU, 0xd2bbba69U, 0xe71af0fdU, + 0x9b58efc3U, 0x834ce9cfU, 0x874ae8cdU, 0xd334fde7U, + 0x1e11890fU, 0x7bc8d7b3U, 0x3ba8c793U, 0xee99b577U, + 0xaaffa455U, 0xbce22f5eU, 0x6e599537U, 0x4c6a1326U, + 0x2c3a0b16U, 0xeb10f3fbU, 0xa77ae0ddU, 0xdcb2376eU, +}; + +static const ulong32 T3[256] = { + 0xf5a653a7U, 0xd06bbbd3U, 0x6ebfd1e6U, 0x3bd9e271U, + 0xda67bdd0U, 0xcf8a45acU, 0xb3299a4dU, 0x0bf9f279U, + 0x9ce8743aU, 0x8c038fc9U, 0x417e3f91U, 0x32d7e5fcU, + 0x44783c1eU, 0x8f018e47U, 0xe54da854U, 0xa9ce67bdU, + 0x0f0a058cU, 0xf9ae57a5U, 0x01f5f47aU, 0x20cbebfbU, + 0x5791c663U, 0xb7da6db8U, 0xf453a7ddU, 0xc277b5d4U, + 0x64b3d7e5U, 0x8df67bb3U, 0xa43397c5U, 0xa3c261beU, + 0xd19e4fa9U, 0x171a0d88U, 0x2830180cU, 0xebb259a2U, + 0x96e47239U, 0xf85ba3dfU, 0xf6a45229U, 0xe64fa9daU, + 0xfaac562bU, 0xd79a4da8U, 0x800b8bcbU, 0xb52d984cU, + 0xa731964bU, 0xcc884422U, 0xdb9249aaU, 0xd8904824U, + 0x9b198241U, 0x3ddde070U, 0xf3a251a6U, 0x2cc3eff9U, + 0xc175b45aU, 0x76afd9e2U, 0x87fa7db0U, 0xb4d86c36U, + 0x13e9fa7dU, 0x62b7d5e4U, 0xaacc6633U, 0x38dbe3ffU, + 0x5d9dc060U, 0xc0804020U, 0x30201008U, 0x1d160b8bU, + 0xd965bc5eU, 0xdd964babU, 0x1fe1fe7fU, 0x0dfdf078U, + 0x15edf87cU, 0xe8b0582cU, 0xef41ae57U, 0xd66fb9d2U, + 0xf257a5dcU, 0x73a9da6dU, 0x19e5fc7eU, 0x2e341a0dU, + 0xf751a653U, 0x5f6a3594U, 0xb02b9bc3U, 0xf0a05028U, + 0xd29c4e27U, 0x14180c06U, 0xdf61be5fU, 0xc98e47adU, + 0x4f81ce67U, 0xd56db85cU, 0xe349aa55U, 0xad3d9048U, + 0x24381c0eU, 0xf155a452U, 0x468fc9eaU, 0x91158442U, + 0xc771b65bU, 0xd369ba5dU, 0xa0c06030U, 0xcd7db058U, + 0xfb59a251U, 0xcb79b259U, 0x88f0783cU, 0xb9259c4eU, + 0x90e07038U, 0x1b12098aU, 0x31d5e472U, 0x78502814U, + 0x68bbd3e7U, 0xae3f91c6U, 0xfe5fa1deU, 0xfd5da050U, + 0x0302018eU, 0x4b723992U, 0xdc63bfd1U, 0x2fc1ee77U, + 0x4d763b93U, 0x83098a45U, 0x7b52299aU, 0x9e1f81ceU, + 0xeeb45a2dU, 0x0a0c0603U, 0x5195c462U, 0x93e271b6U, + 0xb1de6fb9U, 0xa5c663bfU, 0x53623196U, 0x67b1d66bU, + 0x82fc7e3fU, 0x121c0e07U, 0x6c482412U, 0xc38241aeU, + 0x9d1d8040U, 0xb8d06834U, 0x89058c46U, 0x84f87c3eU, + 0xe04babdbU, 0x981b83cfU, 0x5297c5ecU, 0x921785ccU, + 0xbc239fc1U, 0xe1be5fa1U, 0xba279dc0U, 0xce7fb1d6U, + 0x4e743a1dU, 0x02f7f5f4U, 0x5b99c261U, 0x9aec763bU, + 0x60402010U, 0xea47add8U, 0x6dbdd068U, 0xe7ba5da0U, + 0x81fe7fb1U, 0x3c28140aU, 0x6bb9d269U, 0x75add86cU, + 0xab399249U, 0x26cfe9faU, 0x29c5ec76U, 0xa23795c4U, + 0x6342219eU, 0x7d562b9bU, 0x79a5dc6eU, 0x715e2f99U, + 0xb62f99c2U, 0x95e673b7U, 0x775a2d98U, 0xafca65bcU, + 0x0506038fU, 0x392e1785U, 0x427c3e1fU, 0x9fea75b4U, + 0x2ac7edf8U, 0x66442211U, 0xe4b85c2eU, 0x00000000U, + 0xde944a25U, 0x4870381cU, 0xfca8542aU, 0x8ef47a3dU, + 0x1e140a05U, 0xbf219e4fU, 0x07f1f67bU, 0x8bf279b2U, + 0xacc86432U, 0x477a3d90U, 0xc58643afU, 0x56643219U, + 0xedb65ba3U, 0x08fbf3f7U, 0x37d1e673U, 0x694e279dU, + 0x7e542a15U, 0x25cde874U, 0x5e9fc1eeU, 0x860f89caU, + 0x6546239fU, 0x223c1e0fU, 0x5a6c361bU, 0x23c9ea75U, + 0x33221186U, 0x3f2a1584U, 0x6f4a259cU, 0xa135944aU, + 0x55663397U, 0x5c68341aU, 0x4389ca65U, 0x0efff1f6U, + 0x5493c7edU, 0x36241209U, 0xbdd66bbbU, 0xd4984c26U, + 0x2d361b83U, 0x408bcbebU, 0x7fa1de6fU, 0x213e1f81U, + 0x18100804U, 0x61b5d46aU, 0x97118643U, 0x06040201U, + 0x725c2e17U, 0x7ca3dfe1U, 0x35261387U, 0x04f3f7f5U, + 0x090e078dU, 0x70abdbe3U, 0xca8c4623U, 0x273a1d80U, + 0x850d8844U, 0x74582c16U, 0x4985cc66U, 0xc6844221U, + 0x3edfe1feU, 0xc473b7d5U, 0xa6c46231U, 0xec43afd9U, + 0xbed46a35U, 0x50603018U, 0x0c080402U, 0x458dc864U, + 0x16eff9f2U, 0x1ce3fff1U, 0xe945ac56U, 0x941387cdU, + 0x2b321982U, 0x8a078dc8U, 0xbbd269baU, 0x1ae7fdf0U, + 0x589bc3efU, 0x4c83cfe9U, 0x4a87cde8U, 0x34d3e7fdU, + 0x111e0f89U, 0xc87bb3d7U, 0xa83b93c7U, 0x99ee77b5U, + 0xffaa55a4U, 0xe2bc5e2fU, 0x596e3795U, 0x6a4c2613U, + 0x3a2c160bU, 0x10ebfbf3U, 0x7aa7dde0U, 0xb2dc6e37U, +}; + +static const ulong32 T4[256] = { + 0xa7a7a7a7U, 0xd3d3d3d3U, 0xe6e6e6e6U, 0x71717171U, + 0xd0d0d0d0U, 0xacacacacU, 0x4d4d4d4dU, 0x79797979U, + 0x3a3a3a3aU, 0xc9c9c9c9U, 0x91919191U, 0xfcfcfcfcU, + 0x1e1e1e1eU, 0x47474747U, 0x54545454U, 0xbdbdbdbdU, + 0x8c8c8c8cU, 0xa5a5a5a5U, 0x7a7a7a7aU, 0xfbfbfbfbU, + 0x63636363U, 0xb8b8b8b8U, 0xddddddddU, 0xd4d4d4d4U, + 0xe5e5e5e5U, 0xb3b3b3b3U, 0xc5c5c5c5U, 0xbebebebeU, + 0xa9a9a9a9U, 0x88888888U, 0x0c0c0c0cU, 0xa2a2a2a2U, + 0x39393939U, 0xdfdfdfdfU, 0x29292929U, 0xdadadadaU, + 0x2b2b2b2bU, 0xa8a8a8a8U, 0xcbcbcbcbU, 0x4c4c4c4cU, + 0x4b4b4b4bU, 0x22222222U, 0xaaaaaaaaU, 0x24242424U, + 0x41414141U, 0x70707070U, 0xa6a6a6a6U, 0xf9f9f9f9U, + 0x5a5a5a5aU, 0xe2e2e2e2U, 0xb0b0b0b0U, 0x36363636U, + 0x7d7d7d7dU, 0xe4e4e4e4U, 0x33333333U, 0xffffffffU, + 0x60606060U, 0x20202020U, 0x08080808U, 0x8b8b8b8bU, + 0x5e5e5e5eU, 0xababababU, 0x7f7f7f7fU, 0x78787878U, + 0x7c7c7c7cU, 0x2c2c2c2cU, 0x57575757U, 0xd2d2d2d2U, + 0xdcdcdcdcU, 0x6d6d6d6dU, 0x7e7e7e7eU, 0x0d0d0d0dU, + 0x53535353U, 0x94949494U, 0xc3c3c3c3U, 0x28282828U, + 0x27272727U, 0x06060606U, 0x5f5f5f5fU, 0xadadadadU, + 0x67676767U, 0x5c5c5c5cU, 0x55555555U, 0x48484848U, + 0x0e0e0e0eU, 0x52525252U, 0xeaeaeaeaU, 0x42424242U, + 0x5b5b5b5bU, 0x5d5d5d5dU, 0x30303030U, 0x58585858U, + 0x51515151U, 0x59595959U, 0x3c3c3c3cU, 0x4e4e4e4eU, + 0x38383838U, 0x8a8a8a8aU, 0x72727272U, 0x14141414U, + 0xe7e7e7e7U, 0xc6c6c6c6U, 0xdedededeU, 0x50505050U, + 0x8e8e8e8eU, 0x92929292U, 0xd1d1d1d1U, 0x77777777U, + 0x93939393U, 0x45454545U, 0x9a9a9a9aU, 0xcecececeU, + 0x2d2d2d2dU, 0x03030303U, 0x62626262U, 0xb6b6b6b6U, + 0xb9b9b9b9U, 0xbfbfbfbfU, 0x96969696U, 0x6b6b6b6bU, + 0x3f3f3f3fU, 0x07070707U, 0x12121212U, 0xaeaeaeaeU, + 0x40404040U, 0x34343434U, 0x46464646U, 0x3e3e3e3eU, + 0xdbdbdbdbU, 0xcfcfcfcfU, 0xececececU, 0xccccccccU, + 0xc1c1c1c1U, 0xa1a1a1a1U, 0xc0c0c0c0U, 0xd6d6d6d6U, + 0x1d1d1d1dU, 0xf4f4f4f4U, 0x61616161U, 0x3b3b3b3bU, + 0x10101010U, 0xd8d8d8d8U, 0x68686868U, 0xa0a0a0a0U, + 0xb1b1b1b1U, 0x0a0a0a0aU, 0x69696969U, 0x6c6c6c6cU, + 0x49494949U, 0xfafafafaU, 0x76767676U, 0xc4c4c4c4U, + 0x9e9e9e9eU, 0x9b9b9b9bU, 0x6e6e6e6eU, 0x99999999U, + 0xc2c2c2c2U, 0xb7b7b7b7U, 0x98989898U, 0xbcbcbcbcU, + 0x8f8f8f8fU, 0x85858585U, 0x1f1f1f1fU, 0xb4b4b4b4U, + 0xf8f8f8f8U, 0x11111111U, 0x2e2e2e2eU, 0x00000000U, + 0x25252525U, 0x1c1c1c1cU, 0x2a2a2a2aU, 0x3d3d3d3dU, + 0x05050505U, 0x4f4f4f4fU, 0x7b7b7b7bU, 0xb2b2b2b2U, + 0x32323232U, 0x90909090U, 0xafafafafU, 0x19191919U, + 0xa3a3a3a3U, 0xf7f7f7f7U, 0x73737373U, 0x9d9d9d9dU, + 0x15151515U, 0x74747474U, 0xeeeeeeeeU, 0xcacacacaU, + 0x9f9f9f9fU, 0x0f0f0f0fU, 0x1b1b1b1bU, 0x75757575U, + 0x86868686U, 0x84848484U, 0x9c9c9c9cU, 0x4a4a4a4aU, + 0x97979797U, 0x1a1a1a1aU, 0x65656565U, 0xf6f6f6f6U, + 0xededededU, 0x09090909U, 0xbbbbbbbbU, 0x26262626U, + 0x83838383U, 0xebebebebU, 0x6f6f6f6fU, 0x81818181U, + 0x04040404U, 0x6a6a6a6aU, 0x43434343U, 0x01010101U, + 0x17171717U, 0xe1e1e1e1U, 0x87878787U, 0xf5f5f5f5U, + 0x8d8d8d8dU, 0xe3e3e3e3U, 0x23232323U, 0x80808080U, + 0x44444444U, 0x16161616U, 0x66666666U, 0x21212121U, + 0xfefefefeU, 0xd5d5d5d5U, 0x31313131U, 0xd9d9d9d9U, + 0x35353535U, 0x18181818U, 0x02020202U, 0x64646464U, + 0xf2f2f2f2U, 0xf1f1f1f1U, 0x56565656U, 0xcdcdcdcdU, + 0x82828282U, 0xc8c8c8c8U, 0xbabababaU, 0xf0f0f0f0U, + 0xefefefefU, 0xe9e9e9e9U, 0xe8e8e8e8U, 0xfdfdfdfdU, + 0x89898989U, 0xd7d7d7d7U, 0xc7c7c7c7U, 0xb5b5b5b5U, + 0xa4a4a4a4U, 0x2f2f2f2fU, 0x95959595U, 0x13131313U, + 0x0b0b0b0bU, 0xf3f3f3f3U, 0xe0e0e0e0U, 0x37373737U, +}; + +static const ulong32 T5[256] = { + 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U, + 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U, + 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U, + 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U, + 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U, + 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U, + 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U, + 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U, + 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U, + 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U, + 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U, + 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U, + 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U, + 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U, + 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U, + 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U, + 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U, + 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U, + 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U, + 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U, + 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U, + 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U, + 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U, + 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U, + 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU, + 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU, + 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU, + 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU, + 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU, + 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU, + 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU, + 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU, + 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU, + 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU, + 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU, + 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU, + 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU, + 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU, + 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU, + 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU, + 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U, + 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U, + 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U, + 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U, + 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U, + 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U, + 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U, + 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U, + 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U, + 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U, + 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U, + 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U, + 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U, + 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U, + 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U, + 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U, + 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU, + 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU, + 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU, + 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU, + 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU, + 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU, + 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU, + 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU, +}; + +/** + * The round constants. + */ +static const ulong32 rc[] = { + 0xa7d3e671U, 0xd0ac4d79U, 0x3ac991fcU, 0x1e4754bdU, + 0x8ca57afbU, 0x63b8ddd4U, 0xe5b3c5beU, 0xa9880ca2U, + 0x39df29daU, 0x2ba8cb4cU, 0x4b22aa24U, 0x4170a6f9U, + 0x5ae2b036U, 0x7de433ffU, 0x6020088bU, 0x5eab7f78U, + 0x7c2c57d2U, 0xdc6d7e0dU, 0x5394c328U, +}; + +#endif + + /** + Initialize the Anubis 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 + */ +#ifdef LTC_CLEAN_STACK +static int s_anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + int N, R, i, pos, r; + ulong32 kappa[MAX_N]; + ulong32 inter[MAX_N] = { 0 }; /* initialize as all zeroes */ + ulong32 v, K0, K1, K2, K3; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* Valid sizes (in bytes) are 16, 20, 24, 28, 32, 36, and 40. */ + if ((keylen & 3) || (keylen < 16) || (keylen > 40)) { + return CRYPT_INVALID_KEYSIZE; + } + skey->anubis.keyBits = keylen*8; + + /* + * determine the N length parameter: + * (N.B. it is assumed that the key length is valid!) + */ + N = skey->anubis.keyBits >> 5; + + /* + * determine number of rounds from key size: + */ + skey->anubis.R = R = 8 + N; + + if (num_rounds != 0 && num_rounds != skey->anubis.R) { + return CRYPT_INVALID_ROUNDS; + } + + /* + * map cipher key to initial key state (mu): + */ + for (i = 0, pos = 0; i < N; i++, pos += 4) { + kappa[i] = + (((ulong32)key[pos ]) << 24) ^ + (((ulong32)key[pos + 1]) << 16) ^ + (((ulong32)key[pos + 2]) << 8) ^ + (((ulong32)key[pos + 3]) ); + } + + /* + * generate R + 1 round keys: + */ + for (r = 0; r <= R; r++) { + /* + * generate r-th round key K^r: + */ + K0 = T4[(kappa[N - 1] >> 24) & 0xff]; + K1 = T4[(kappa[N - 1] >> 16) & 0xff]; + K2 = T4[(kappa[N - 1] >> 8) & 0xff]; + K3 = T4[(kappa[N - 1] ) & 0xff]; + for (i = N - 2; i >= 0; i--) { + K0 = T4[(kappa[i] >> 24) & 0xff] ^ + (T5[(K0 >> 24) & 0xff] & 0xff000000U) ^ + (T5[(K0 >> 16) & 0xff] & 0x00ff0000U) ^ + (T5[(K0 >> 8) & 0xff] & 0x0000ff00U) ^ + (T5[(K0 ) & 0xff] & 0x000000ffU); + K1 = T4[(kappa[i] >> 16) & 0xff] ^ + (T5[(K1 >> 24) & 0xff] & 0xff000000U) ^ + (T5[(K1 >> 16) & 0xff] & 0x00ff0000U) ^ + (T5[(K1 >> 8) & 0xff] & 0x0000ff00U) ^ + (T5[(K1 ) & 0xff] & 0x000000ffU); + K2 = T4[(kappa[i] >> 8) & 0xff] ^ + (T5[(K2 >> 24) & 0xff] & 0xff000000U) ^ + (T5[(K2 >> 16) & 0xff] & 0x00ff0000U) ^ + (T5[(K2 >> 8) & 0xff] & 0x0000ff00U) ^ + (T5[(K2 ) & 0xff] & 0x000000ffU); + K3 = T4[(kappa[i] ) & 0xff] ^ + (T5[(K3 >> 24) & 0xff] & 0xff000000U) ^ + (T5[(K3 >> 16) & 0xff] & 0x00ff0000U) ^ + (T5[(K3 >> 8) & 0xff] & 0x0000ff00U) ^ + (T5[(K3 ) & 0xff] & 0x000000ffU); + } + /* + -- this is the code to use with the large U tables: + K0 = K1 = K2 = K3 = 0; + for (i = 0; i < N; i++) { + K0 ^= U[i][(kappa[i] >> 24) & 0xff]; + K1 ^= U[i][(kappa[i] >> 16) & 0xff]; + K2 ^= U[i][(kappa[i] >> 8) & 0xff]; + K3 ^= U[i][(kappa[i] ) & 0xff]; + } + */ + skey->anubis.roundKeyEnc[r][0] = K0; + skey->anubis.roundKeyEnc[r][1] = K1; + skey->anubis.roundKeyEnc[r][2] = K2; + skey->anubis.roundKeyEnc[r][3] = K3; + + /* + * compute kappa^{r+1} from kappa^r: + */ + if (r == R) { + break; + } + for (i = 0; i < N; i++) { + int j = i; + inter[i] = T0[(kappa[j--] >> 24) & 0xff]; if (j < 0) j = N - 1; + inter[i] ^= T1[(kappa[j--] >> 16) & 0xff]; if (j < 0) j = N - 1; + inter[i] ^= T2[(kappa[j--] >> 8) & 0xff]; if (j < 0) j = N - 1; + inter[i] ^= T3[(kappa[j ] ) & 0xff]; + } + kappa[0] = inter[0] ^ rc[r]; + for (i = 1; i < N; i++) { + kappa[i] = inter[i]; + } + } + + /* + * generate inverse key schedule: K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}): + */ + for (i = 0; i < 4; i++) { + skey->anubis.roundKeyDec[0][i] = skey->anubis.roundKeyEnc[R][i]; + skey->anubis.roundKeyDec[R][i] = skey->anubis.roundKeyEnc[0][i]; + } + for (r = 1; r < R; r++) { + for (i = 0; i < 4; i++) { + v = skey->anubis.roundKeyEnc[R - r][i]; + skey->anubis.roundKeyDec[r][i] = + T0[T4[(v >> 24) & 0xff] & 0xff] ^ + T1[T4[(v >> 16) & 0xff] & 0xff] ^ + T2[T4[(v >> 8) & 0xff] & 0xff] ^ + T3[T4[(v ) & 0xff] & 0xff]; + } + } + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int err; + err = s_anubis_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(int) * 5 + sizeof(ulong32) * (MAX_N + MAX_N + 5)); + return err; +} +#endif + + +static void anubis_crypt(const unsigned char *plaintext, unsigned char *ciphertext, + const ulong32 roundKey[18 + 1][4], int R) { + int i, pos, r; + ulong32 state[4]; + ulong32 inter[4]; + + /* + * map plaintext block to cipher state (mu) + * and add initial round key (sigma[K^0]): + */ + for (i = 0, pos = 0; i < 4; i++, pos += 4) { + state[i] = + (((ulong32)plaintext[pos ]) << 24) ^ + (((ulong32)plaintext[pos + 1]) << 16) ^ + (((ulong32)plaintext[pos + 2]) << 8) ^ + (((ulong32)plaintext[pos + 3]) ) ^ + roundKey[0][i]; + } + + /* + * R - 1 full rounds: + */ + for (r = 1; r < R; r++) { + inter[0] = + T0[(state[0] >> 24) & 0xff] ^ + T1[(state[1] >> 24) & 0xff] ^ + T2[(state[2] >> 24) & 0xff] ^ + T3[(state[3] >> 24) & 0xff] ^ + roundKey[r][0]; + inter[1] = + T0[(state[0] >> 16) & 0xff] ^ + T1[(state[1] >> 16) & 0xff] ^ + T2[(state[2] >> 16) & 0xff] ^ + T3[(state[3] >> 16) & 0xff] ^ + roundKey[r][1]; + inter[2] = + T0[(state[0] >> 8) & 0xff] ^ + T1[(state[1] >> 8) & 0xff] ^ + T2[(state[2] >> 8) & 0xff] ^ + T3[(state[3] >> 8) & 0xff] ^ + roundKey[r][2]; + inter[3] = + T0[(state[0] ) & 0xff] ^ + T1[(state[1] ) & 0xff] ^ + T2[(state[2] ) & 0xff] ^ + T3[(state[3] ) & 0xff] ^ + roundKey[r][3]; + state[0] = inter[0]; + state[1] = inter[1]; + state[2] = inter[2]; + state[3] = inter[3]; + } + + /* + * last round: + */ + inter[0] = + (T0[(state[0] >> 24) & 0xff] & 0xff000000U) ^ + (T1[(state[1] >> 24) & 0xff] & 0x00ff0000U) ^ + (T2[(state[2] >> 24) & 0xff] & 0x0000ff00U) ^ + (T3[(state[3] >> 24) & 0xff] & 0x000000ffU) ^ + roundKey[R][0]; + inter[1] = + (T0[(state[0] >> 16) & 0xff] & 0xff000000U) ^ + (T1[(state[1] >> 16) & 0xff] & 0x00ff0000U) ^ + (T2[(state[2] >> 16) & 0xff] & 0x0000ff00U) ^ + (T3[(state[3] >> 16) & 0xff] & 0x000000ffU) ^ + roundKey[R][1]; + inter[2] = + (T0[(state[0] >> 8) & 0xff] & 0xff000000U) ^ + (T1[(state[1] >> 8) & 0xff] & 0x00ff0000U) ^ + (T2[(state[2] >> 8) & 0xff] & 0x0000ff00U) ^ + (T3[(state[3] >> 8) & 0xff] & 0x000000ffU) ^ + roundKey[R][2]; + inter[3] = + (T0[(state[0] ) & 0xff] & 0xff000000U) ^ + (T1[(state[1] ) & 0xff] & 0x00ff0000U) ^ + (T2[(state[2] ) & 0xff] & 0x0000ff00U) ^ + (T3[(state[3] ) & 0xff] & 0x000000ffU) ^ + roundKey[R][3]; + + /* + * map cipher state to ciphertext block (mu^{-1}): + */ + for (i = 0, pos = 0; i < 4; i++, pos += 4) { + ulong32 w = inter[i]; + ciphertext[pos ] = (unsigned char)(w >> 24); + ciphertext[pos + 1] = (unsigned char)(w >> 16); + ciphertext[pos + 2] = (unsigned char)(w >> 8); + ciphertext[pos + 3] = (unsigned char)(w ); + } +} + +/** + Encrypts a block of text with Anubis + @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 +*/ +int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + if (skey->anubis.R < 12 || skey->anubis.R > 18) { + return CRYPT_INVALID_ROUNDS; + } + + anubis_crypt(pt, ct, skey->anubis.roundKeyEnc, skey->anubis.R); + return CRYPT_OK; +} + +/** + Decrypts a block of text with Anubis + @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 +*/ +int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + if (skey->anubis.R < 12 || skey->anubis.R > 18) { + return CRYPT_INVALID_ROUNDS; + } + + anubis_crypt(ct, pt, skey->anubis.roundKeyDec, skey->anubis.R); + return CRYPT_OK; +} + +/** + Performs a self-test of the Anubis block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int anubis_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct test { + int keylen; + unsigned char pt[16], ct[16], key[40]; + } tests[] = { +#ifndef LTC_ANUBIS_TWEAK + /**** ORIGINAL LTC_ANUBIS ****/ + /* 128 bit keys */ +{ + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xF0, 0x68, 0x60, 0xFC, 0x67, 0x30, 0xE8, 0x18, + 0xF1, 0x32, 0xC7, 0x8A, 0xF4, 0x13, 0x2A, 0xFE }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA8, 0x66, 0x84, 0x80, 0x07, 0x74, 0x5C, 0x89, + 0xFC, 0x5E, 0xB5, 0xBA, 0xD4, 0xFE, 0x32, 0x6D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 160-bit keys */ +{ + 20, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xBD, 0x5E, 0x32, 0xBE, 0x51, 0x67, 0xA8, 0xE2, + 0x72, 0xD7, 0x95, 0x0F, 0x83, 0xC6, 0x8C, 0x31 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}, { + 20, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4C, 0x1F, 0x86, 0x2E, 0x11, 0xEB, 0xCE, 0xEB, + 0xFE, 0xB9, 0x73, 0xC9, 0xDF, 0xEF, 0x7A, 0xDB }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 192-bit keys */ +{ + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x17, 0xAC, 0x57, 0x44, 0x9D, 0x59, 0x61, 0x66, + 0xD0, 0xC7, 0x9E, 0x04, 0x7C, 0xC7, 0x58, 0xF0 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x71, 0x52, 0xB4, 0xEB, 0x1D, 0xAA, 0x36, 0xFD, + 0x57, 0x14, 0x5F, 0x57, 0x04, 0x9F, 0x70, 0x74 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 224-bit keys */ +{ + 28, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA2, 0xF0, 0xA6, 0xB9, 0x17, 0x93, 0x2A, 0x3B, + 0xEF, 0x08, 0xE8, 0x7A, 0x58, 0xD6, 0xF8, 0x53 }, + { 0x80, 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 } +}, { + 28, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xF0, 0xCA, 0xFC, 0x78, 0x8B, 0x4B, 0x4E, 0x53, + 0x8B, 0xC4, 0x32, 0x6A, 0xF5, 0xB9, 0x1B, 0x5F }, + { 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, 0x01 } +}, + + /* 256-bit keys */ +{ + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE0, 0x86, 0xAC, 0x45, 0x6B, 0x3C, 0xE5, 0x13, + 0xED, 0xF5, 0xDF, 0xDD, 0xD6, 0x3B, 0x71, 0x93 }, + { 0x80, 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 } +}, { + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x50, 0x01, 0xB9, 0xF5, 0x21, 0xC1, 0xC1, 0x29, + 0x00, 0xD5, 0xEC, 0x98, 0x2B, 0x9E, 0xE8, 0x21 }, + { 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, 0x01 } +}, + + /* 288-bit keys */ +{ + 36, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE8, 0xF4, 0xAF, 0x2B, 0x21, 0xA0, 0x87, 0x9B, + 0x41, 0x95, 0xB9, 0x71, 0x75, 0x79, 0x04, 0x7C }, + { 0x80, 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, 0x00, 0x00, 0x00 } +}, { + 36, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE6, 0xA6, 0xA5, 0xBC, 0x8B, 0x63, 0x6F, 0xE2, + 0xBD, 0xA7, 0xA7, 0x53, 0xAB, 0x40, 0x22, 0xE0 }, + { 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, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 320-bit keys */ +{ + 40, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x17, 0x04, 0xD7, 0x2C, 0xC6, 0x85, 0x76, 0x02, + 0x4B, 0xCC, 0x39, 0x80, 0xD8, 0x22, 0xEA, 0xA4 }, + { 0x80, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 40, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7A, 0x41, 0xE6, 0x7D, 0x4F, 0xD8, 0x64, 0xF0, + 0x44, 0xA8, 0x3C, 0x73, 0x81, 0x7E, 0x53, 0xD8 }, + { 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +} +#else + /**** Tweaked LTC_ANUBIS ****/ + /* 128 bit keys */ +{ + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB8, 0x35, 0xBD, 0xC3, 0x34, 0x82, 0x9D, 0x83, + 0x71, 0xBF, 0xA3, 0x71, 0xE4, 0xB3, 0xC4, 0xFD }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE6, 0x14, 0x1E, 0xAF, 0xEB, 0xE0, 0x59, 0x3C, + 0x48, 0xE1, 0xCD, 0xF2, 0x1B, 0xBA, 0xA1, 0x89 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 160-bit keys */ +{ + 20, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x97, 0x59, 0x79, 0x4B, 0x5C, 0xA0, 0x70, 0x73, + 0x24, 0xEF, 0xB3, 0x58, 0x67, 0xCA, 0xD4, 0xB3 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}, { + 20, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB8, 0x0D, 0xFB, 0x9B, 0xE4, 0xA1, 0x58, 0x87, + 0xB3, 0x76, 0xD5, 0x02, 0x18, 0x95, 0xC1, 0x2E }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 192-bit keys */ +{ + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7D, 0x62, 0x3B, 0x52, 0xC7, 0x4C, 0x64, 0xD8, + 0xEB, 0xC7, 0x2D, 0x57, 0x97, 0x85, 0x43, 0x8F }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB1, 0x0A, 0x59, 0xDD, 0x5D, 0x5D, 0x8D, 0x67, + 0xEC, 0xEE, 0x4A, 0xC4, 0xBE, 0x4F, 0xA8, 0x4F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 224-bit keys */ +{ + 28, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x68, 0x9E, 0x05, 0x94, 0x6A, 0x94, 0x43, 0x8F, + 0xE7, 0x8E, 0x37, 0x3D, 0x24, 0x97, 0x92, 0xF5 }, + { 0x80, 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 } +}, { + 28, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDD, 0xB7, 0xB0, 0xB4, 0xE9, 0xB4, 0x9B, 0x9C, + 0x38, 0x20, 0x25, 0x0B, 0x47, 0xC2, 0x1F, 0x89 }, + { 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, 0x01 } +}, + + /* 256-bit keys */ +{ + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x96, 0x00, 0xF0, 0x76, 0x91, 0x69, 0x29, 0x87, + 0xF5, 0xE5, 0x97, 0xDB, 0xDB, 0xAF, 0x1B, 0x0A }, + { 0x80, 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 } +}, { + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x69, 0x9C, 0xAF, 0xDD, 0x94, 0xC7, 0xBC, 0x60, + 0x44, 0xFE, 0x02, 0x05, 0x8A, 0x6E, 0xEF, 0xBD }, + { 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, 0x01 } +}, + + /* 288-bit keys */ +{ + 36, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0F, 0xC7, 0xA2, 0xC0, 0x11, 0x17, 0xAC, 0x43, + 0x52, 0x5E, 0xDF, 0x6C, 0xF3, 0x96, 0x33, 0x6C }, + { 0x80, 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, 0x00, 0x00, 0x00 } +}, { + 36, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAD, 0x08, 0x4F, 0xED, 0x55, 0xA6, 0x94, 0x3E, + 0x7E, 0x5E, 0xED, 0x05, 0xA1, 0x9D, 0x41, 0xB4 }, + { 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, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 320-bit keys */ +{ + 40, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFE, 0xE2, 0x0E, 0x2A, 0x9D, 0xC5, 0x83, 0xBA, + 0xA3, 0xA6, 0xD6, 0xA6, 0xF2, 0xE8, 0x06, 0xA5 }, + { 0x80, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 40, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x86, 0x3D, 0xCC, 0x4A, 0x60, 0x34, 0x9C, 0x28, + 0xA7, 0xDA, 0xA4, 0x3B, 0x0A, 0xD7, 0xFD, 0xC7 }, + { 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +} +#endif +}; + int x, y; + unsigned char buf[2][16]; + symmetric_key skey; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + anubis_setup(tests[x].key, tests[x].keylen, 0, &skey); + anubis_ecb_encrypt(tests[x].pt, buf[0], &skey); + anubis_ecb_decrypt(buf[0], buf[1], &skey); + if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis Encrypt", x) || + compare_testvector(buf[1], 16, tests[x].pt, 16, "Anubis Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + for (y = 0; y < 1000; y++) anubis_ecb_encrypt(buf[0], buf[0], &skey); + for (y = 0; y < 1000; y++) anubis_ecb_decrypt(buf[0], buf[0], &skey); + if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis 1000", 1000)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void anubis_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 anubis_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 40) { + *keysize = 40; + } else if (*keysize >= 36) { + *keysize = 36; + } else if (*keysize >= 32) { + *keysize = 32; + } else if (*keysize >= 28) { + *keysize = 28; + } else if (*keysize >= 24) { + *keysize = 24; + } else if (*keysize >= 20) { + *keysize = 20; + } else if (*keysize >= 16) { + *keysize = 16; + } else { + return CRYPT_INVALID_KEYSIZE; + } + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/blowfish.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/blowfish.c new file mode 100644 index 0000000..35efc13 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/blowfish.c @@ -0,0 +1,658 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @file blowfish.c + Implementation of the Blowfish block cipher, Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_BLOWFISH + +const struct ltc_cipher_descriptor blowfish_desc = +{ + "blowfish", + 0, + 8, 56, 8, 16, + &blowfish_setup, + &blowfish_ecb_encrypt, + &blowfish_ecb_decrypt, + &blowfish_test, + &blowfish_done, + &blowfish_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 ORIG_P[16 + 2] = { + 0x243F6A88UL, 0x85A308D3UL, 0x13198A2EUL, 0x03707344UL, + 0xA4093822UL, 0x299F31D0UL, 0x082EFA98UL, 0xEC4E6C89UL, + 0x452821E6UL, 0x38D01377UL, 0xBE5466CFUL, 0x34E90C6CUL, + 0xC0AC29B7UL, 0xC97C50DDUL, 0x3F84D5B5UL, 0xB5470917UL, + 0x9216D5D9UL, 0x8979FB1BUL +}; + +static const ulong32 ORIG_S[4][256] = { + { 0xD1310BA6UL, 0x98DFB5ACUL, 0x2FFD72DBUL, 0xD01ADFB7UL, + 0xB8E1AFEDUL, 0x6A267E96UL, 0xBA7C9045UL, 0xF12C7F99UL, + 0x24A19947UL, 0xB3916CF7UL, 0x0801F2E2UL, 0x858EFC16UL, + 0x636920D8UL, 0x71574E69UL, 0xA458FEA3UL, 0xF4933D7EUL, + 0x0D95748FUL, 0x728EB658UL, 0x718BCD58UL, 0x82154AEEUL, + 0x7B54A41DUL, 0xC25A59B5UL, 0x9C30D539UL, 0x2AF26013UL, + 0xC5D1B023UL, 0x286085F0UL, 0xCA417918UL, 0xB8DB38EFUL, + 0x8E79DCB0UL, 0x603A180EUL, 0x6C9E0E8BUL, 0xB01E8A3EUL, + 0xD71577C1UL, 0xBD314B27UL, 0x78AF2FDAUL, 0x55605C60UL, + 0xE65525F3UL, 0xAA55AB94UL, 0x57489862UL, 0x63E81440UL, + 0x55CA396AUL, 0x2AAB10B6UL, 0xB4CC5C34UL, 0x1141E8CEUL, + 0xA15486AFUL, 0x7C72E993UL, 0xB3EE1411UL, 0x636FBC2AUL, + 0x2BA9C55DUL, 0x741831F6UL, 0xCE5C3E16UL, 0x9B87931EUL, + 0xAFD6BA33UL, 0x6C24CF5CUL, 0x7A325381UL, 0x28958677UL, + 0x3B8F4898UL, 0x6B4BB9AFUL, 0xC4BFE81BUL, 0x66282193UL, + 0x61D809CCUL, 0xFB21A991UL, 0x487CAC60UL, 0x5DEC8032UL, + 0xEF845D5DUL, 0xE98575B1UL, 0xDC262302UL, 0xEB651B88UL, + 0x23893E81UL, 0xD396ACC5UL, 0x0F6D6FF3UL, 0x83F44239UL, + 0x2E0B4482UL, 0xA4842004UL, 0x69C8F04AUL, 0x9E1F9B5EUL, + 0x21C66842UL, 0xF6E96C9AUL, 0x670C9C61UL, 0xABD388F0UL, + 0x6A51A0D2UL, 0xD8542F68UL, 0x960FA728UL, 0xAB5133A3UL, + 0x6EEF0B6CUL, 0x137A3BE4UL, 0xBA3BF050UL, 0x7EFB2A98UL, + 0xA1F1651DUL, 0x39AF0176UL, 0x66CA593EUL, 0x82430E88UL, + 0x8CEE8619UL, 0x456F9FB4UL, 0x7D84A5C3UL, 0x3B8B5EBEUL, + 0xE06F75D8UL, 0x85C12073UL, 0x401A449FUL, 0x56C16AA6UL, + 0x4ED3AA62UL, 0x363F7706UL, 0x1BFEDF72UL, 0x429B023DUL, + 0x37D0D724UL, 0xD00A1248UL, 0xDB0FEAD3UL, 0x49F1C09BUL, + 0x075372C9UL, 0x80991B7BUL, 0x25D479D8UL, 0xF6E8DEF7UL, + 0xE3FE501AUL, 0xB6794C3BUL, 0x976CE0BDUL, 0x04C006BAUL, + 0xC1A94FB6UL, 0x409F60C4UL, 0x5E5C9EC2UL, 0x196A2463UL, + 0x68FB6FAFUL, 0x3E6C53B5UL, 0x1339B2EBUL, 0x3B52EC6FUL, + 0x6DFC511FUL, 0x9B30952CUL, 0xCC814544UL, 0xAF5EBD09UL, + 0xBEE3D004UL, 0xDE334AFDUL, 0x660F2807UL, 0x192E4BB3UL, + 0xC0CBA857UL, 0x45C8740FUL, 0xD20B5F39UL, 0xB9D3FBDBUL, + 0x5579C0BDUL, 0x1A60320AUL, 0xD6A100C6UL, 0x402C7279UL, + 0x679F25FEUL, 0xFB1FA3CCUL, 0x8EA5E9F8UL, 0xDB3222F8UL, + 0x3C7516DFUL, 0xFD616B15UL, 0x2F501EC8UL, 0xAD0552ABUL, + 0x323DB5FAUL, 0xFD238760UL, 0x53317B48UL, 0x3E00DF82UL, + 0x9E5C57BBUL, 0xCA6F8CA0UL, 0x1A87562EUL, 0xDF1769DBUL, + 0xD542A8F6UL, 0x287EFFC3UL, 0xAC6732C6UL, 0x8C4F5573UL, + 0x695B27B0UL, 0xBBCA58C8UL, 0xE1FFA35DUL, 0xB8F011A0UL, + 0x10FA3D98UL, 0xFD2183B8UL, 0x4AFCB56CUL, 0x2DD1D35BUL, + 0x9A53E479UL, 0xB6F84565UL, 0xD28E49BCUL, 0x4BFB9790UL, + 0xE1DDF2DAUL, 0xA4CB7E33UL, 0x62FB1341UL, 0xCEE4C6E8UL, + 0xEF20CADAUL, 0x36774C01UL, 0xD07E9EFEUL, 0x2BF11FB4UL, + 0x95DBDA4DUL, 0xAE909198UL, 0xEAAD8E71UL, 0x6B93D5A0UL, + 0xD08ED1D0UL, 0xAFC725E0UL, 0x8E3C5B2FUL, 0x8E7594B7UL, + 0x8FF6E2FBUL, 0xF2122B64UL, 0x8888B812UL, 0x900DF01CUL, + 0x4FAD5EA0UL, 0x688FC31CUL, 0xD1CFF191UL, 0xB3A8C1ADUL, + 0x2F2F2218UL, 0xBE0E1777UL, 0xEA752DFEUL, 0x8B021FA1UL, + 0xE5A0CC0FUL, 0xB56F74E8UL, 0x18ACF3D6UL, 0xCE89E299UL, + 0xB4A84FE0UL, 0xFD13E0B7UL, 0x7CC43B81UL, 0xD2ADA8D9UL, + 0x165FA266UL, 0x80957705UL, 0x93CC7314UL, 0x211A1477UL, + 0xE6AD2065UL, 0x77B5FA86UL, 0xC75442F5UL, 0xFB9D35CFUL, + 0xEBCDAF0CUL, 0x7B3E89A0UL, 0xD6411BD3UL, 0xAE1E7E49UL, + 0x00250E2DUL, 0x2071B35EUL, 0x226800BBUL, 0x57B8E0AFUL, + 0x2464369BUL, 0xF009B91EUL, 0x5563911DUL, 0x59DFA6AAUL, + 0x78C14389UL, 0xD95A537FUL, 0x207D5BA2UL, 0x02E5B9C5UL, + 0x83260376UL, 0x6295CFA9UL, 0x11C81968UL, 0x4E734A41UL, + 0xB3472DCAUL, 0x7B14A94AUL, 0x1B510052UL, 0x9A532915UL, + 0xD60F573FUL, 0xBC9BC6E4UL, 0x2B60A476UL, 0x81E67400UL, + 0x08BA6FB5UL, 0x571BE91FUL, 0xF296EC6BUL, 0x2A0DD915UL, + 0xB6636521UL, 0xE7B9F9B6UL, 0xFF34052EUL, 0xC5855664UL, + 0x53B02D5DUL, 0xA99F8FA1UL, 0x08BA4799UL, 0x6E85076AUL }, + { 0x4B7A70E9UL, 0xB5B32944UL, 0xDB75092EUL, 0xC4192623UL, + 0xAD6EA6B0UL, 0x49A7DF7DUL, 0x9CEE60B8UL, 0x8FEDB266UL, + 0xECAA8C71UL, 0x699A17FFUL, 0x5664526CUL, 0xC2B19EE1UL, + 0x193602A5UL, 0x75094C29UL, 0xA0591340UL, 0xE4183A3EUL, + 0x3F54989AUL, 0x5B429D65UL, 0x6B8FE4D6UL, 0x99F73FD6UL, + 0xA1D29C07UL, 0xEFE830F5UL, 0x4D2D38E6UL, 0xF0255DC1UL, + 0x4CDD2086UL, 0x8470EB26UL, 0x6382E9C6UL, 0x021ECC5EUL, + 0x09686B3FUL, 0x3EBAEFC9UL, 0x3C971814UL, 0x6B6A70A1UL, + 0x687F3584UL, 0x52A0E286UL, 0xB79C5305UL, 0xAA500737UL, + 0x3E07841CUL, 0x7FDEAE5CUL, 0x8E7D44ECUL, 0x5716F2B8UL, + 0xB03ADA37UL, 0xF0500C0DUL, 0xF01C1F04UL, 0x0200B3FFUL, + 0xAE0CF51AUL, 0x3CB574B2UL, 0x25837A58UL, 0xDC0921BDUL, + 0xD19113F9UL, 0x7CA92FF6UL, 0x94324773UL, 0x22F54701UL, + 0x3AE5E581UL, 0x37C2DADCUL, 0xC8B57634UL, 0x9AF3DDA7UL, + 0xA9446146UL, 0x0FD0030EUL, 0xECC8C73EUL, 0xA4751E41UL, + 0xE238CD99UL, 0x3BEA0E2FUL, 0x3280BBA1UL, 0x183EB331UL, + 0x4E548B38UL, 0x4F6DB908UL, 0x6F420D03UL, 0xF60A04BFUL, + 0x2CB81290UL, 0x24977C79UL, 0x5679B072UL, 0xBCAF89AFUL, + 0xDE9A771FUL, 0xD9930810UL, 0xB38BAE12UL, 0xDCCF3F2EUL, + 0x5512721FUL, 0x2E6B7124UL, 0x501ADDE6UL, 0x9F84CD87UL, + 0x7A584718UL, 0x7408DA17UL, 0xBC9F9ABCUL, 0xE94B7D8CUL, + 0xEC7AEC3AUL, 0xDB851DFAUL, 0x63094366UL, 0xC464C3D2UL, + 0xEF1C1847UL, 0x3215D908UL, 0xDD433B37UL, 0x24C2BA16UL, + 0x12A14D43UL, 0x2A65C451UL, 0x50940002UL, 0x133AE4DDUL, + 0x71DFF89EUL, 0x10314E55UL, 0x81AC77D6UL, 0x5F11199BUL, + 0x043556F1UL, 0xD7A3C76BUL, 0x3C11183BUL, 0x5924A509UL, + 0xF28FE6EDUL, 0x97F1FBFAUL, 0x9EBABF2CUL, 0x1E153C6EUL, + 0x86E34570UL, 0xEAE96FB1UL, 0x860E5E0AUL, 0x5A3E2AB3UL, + 0x771FE71CUL, 0x4E3D06FAUL, 0x2965DCB9UL, 0x99E71D0FUL, + 0x803E89D6UL, 0x5266C825UL, 0x2E4CC978UL, 0x9C10B36AUL, + 0xC6150EBAUL, 0x94E2EA78UL, 0xA5FC3C53UL, 0x1E0A2DF4UL, + 0xF2F74EA7UL, 0x361D2B3DUL, 0x1939260FUL, 0x19C27960UL, + 0x5223A708UL, 0xF71312B6UL, 0xEBADFE6EUL, 0xEAC31F66UL, + 0xE3BC4595UL, 0xA67BC883UL, 0xB17F37D1UL, 0x018CFF28UL, + 0xC332DDEFUL, 0xBE6C5AA5UL, 0x65582185UL, 0x68AB9802UL, + 0xEECEA50FUL, 0xDB2F953BUL, 0x2AEF7DADUL, 0x5B6E2F84UL, + 0x1521B628UL, 0x29076170UL, 0xECDD4775UL, 0x619F1510UL, + 0x13CCA830UL, 0xEB61BD96UL, 0x0334FE1EUL, 0xAA0363CFUL, + 0xB5735C90UL, 0x4C70A239UL, 0xD59E9E0BUL, 0xCBAADE14UL, + 0xEECC86BCUL, 0x60622CA7UL, 0x9CAB5CABUL, 0xB2F3846EUL, + 0x648B1EAFUL, 0x19BDF0CAUL, 0xA02369B9UL, 0x655ABB50UL, + 0x40685A32UL, 0x3C2AB4B3UL, 0x319EE9D5UL, 0xC021B8F7UL, + 0x9B540B19UL, 0x875FA099UL, 0x95F7997EUL, 0x623D7DA8UL, + 0xF837889AUL, 0x97E32D77UL, 0x11ED935FUL, 0x16681281UL, + 0x0E358829UL, 0xC7E61FD6UL, 0x96DEDFA1UL, 0x7858BA99UL, + 0x57F584A5UL, 0x1B227263UL, 0x9B83C3FFUL, 0x1AC24696UL, + 0xCDB30AEBUL, 0x532E3054UL, 0x8FD948E4UL, 0x6DBC3128UL, + 0x58EBF2EFUL, 0x34C6FFEAUL, 0xFE28ED61UL, 0xEE7C3C73UL, + 0x5D4A14D9UL, 0xE864B7E3UL, 0x42105D14UL, 0x203E13E0UL, + 0x45EEE2B6UL, 0xA3AAABEAUL, 0xDB6C4F15UL, 0xFACB4FD0UL, + 0xC742F442UL, 0xEF6ABBB5UL, 0x654F3B1DUL, 0x41CD2105UL, + 0xD81E799EUL, 0x86854DC7UL, 0xE44B476AUL, 0x3D816250UL, + 0xCF62A1F2UL, 0x5B8D2646UL, 0xFC8883A0UL, 0xC1C7B6A3UL, + 0x7F1524C3UL, 0x69CB7492UL, 0x47848A0BUL, 0x5692B285UL, + 0x095BBF00UL, 0xAD19489DUL, 0x1462B174UL, 0x23820E00UL, + 0x58428D2AUL, 0x0C55F5EAUL, 0x1DADF43EUL, 0x233F7061UL, + 0x3372F092UL, 0x8D937E41UL, 0xD65FECF1UL, 0x6C223BDBUL, + 0x7CDE3759UL, 0xCBEE7460UL, 0x4085F2A7UL, 0xCE77326EUL, + 0xA6078084UL, 0x19F8509EUL, 0xE8EFD855UL, 0x61D99735UL, + 0xA969A7AAUL, 0xC50C06C2UL, 0x5A04ABFCUL, 0x800BCADCUL, + 0x9E447A2EUL, 0xC3453484UL, 0xFDD56705UL, 0x0E1E9EC9UL, + 0xDB73DBD3UL, 0x105588CDUL, 0x675FDA79UL, 0xE3674340UL, + 0xC5C43465UL, 0x713E38D8UL, 0x3D28F89EUL, 0xF16DFF20UL, + 0x153E21E7UL, 0x8FB03D4AUL, 0xE6E39F2BUL, 0xDB83ADF7UL }, + { 0xE93D5A68UL, 0x948140F7UL, 0xF64C261CUL, 0x94692934UL, + 0x411520F7UL, 0x7602D4F7UL, 0xBCF46B2EUL, 0xD4A20068UL, + 0xD4082471UL, 0x3320F46AUL, 0x43B7D4B7UL, 0x500061AFUL, + 0x1E39F62EUL, 0x97244546UL, 0x14214F74UL, 0xBF8B8840UL, + 0x4D95FC1DUL, 0x96B591AFUL, 0x70F4DDD3UL, 0x66A02F45UL, + 0xBFBC09ECUL, 0x03BD9785UL, 0x7FAC6DD0UL, 0x31CB8504UL, + 0x96EB27B3UL, 0x55FD3941UL, 0xDA2547E6UL, 0xABCA0A9AUL, + 0x28507825UL, 0x530429F4UL, 0x0A2C86DAUL, 0xE9B66DFBUL, + 0x68DC1462UL, 0xD7486900UL, 0x680EC0A4UL, 0x27A18DEEUL, + 0x4F3FFEA2UL, 0xE887AD8CUL, 0xB58CE006UL, 0x7AF4D6B6UL, + 0xAACE1E7CUL, 0xD3375FECUL, 0xCE78A399UL, 0x406B2A42UL, + 0x20FE9E35UL, 0xD9F385B9UL, 0xEE39D7ABUL, 0x3B124E8BUL, + 0x1DC9FAF7UL, 0x4B6D1856UL, 0x26A36631UL, 0xEAE397B2UL, + 0x3A6EFA74UL, 0xDD5B4332UL, 0x6841E7F7UL, 0xCA7820FBUL, + 0xFB0AF54EUL, 0xD8FEB397UL, 0x454056ACUL, 0xBA489527UL, + 0x55533A3AUL, 0x20838D87UL, 0xFE6BA9B7UL, 0xD096954BUL, + 0x55A867BCUL, 0xA1159A58UL, 0xCCA92963UL, 0x99E1DB33UL, + 0xA62A4A56UL, 0x3F3125F9UL, 0x5EF47E1CUL, 0x9029317CUL, + 0xFDF8E802UL, 0x04272F70UL, 0x80BB155CUL, 0x05282CE3UL, + 0x95C11548UL, 0xE4C66D22UL, 0x48C1133FUL, 0xC70F86DCUL, + 0x07F9C9EEUL, 0x41041F0FUL, 0x404779A4UL, 0x5D886E17UL, + 0x325F51EBUL, 0xD59BC0D1UL, 0xF2BCC18FUL, 0x41113564UL, + 0x257B7834UL, 0x602A9C60UL, 0xDFF8E8A3UL, 0x1F636C1BUL, + 0x0E12B4C2UL, 0x02E1329EUL, 0xAF664FD1UL, 0xCAD18115UL, + 0x6B2395E0UL, 0x333E92E1UL, 0x3B240B62UL, 0xEEBEB922UL, + 0x85B2A20EUL, 0xE6BA0D99UL, 0xDE720C8CUL, 0x2DA2F728UL, + 0xD0127845UL, 0x95B794FDUL, 0x647D0862UL, 0xE7CCF5F0UL, + 0x5449A36FUL, 0x877D48FAUL, 0xC39DFD27UL, 0xF33E8D1EUL, + 0x0A476341UL, 0x992EFF74UL, 0x3A6F6EABUL, 0xF4F8FD37UL, + 0xA812DC60UL, 0xA1EBDDF8UL, 0x991BE14CUL, 0xDB6E6B0DUL, + 0xC67B5510UL, 0x6D672C37UL, 0x2765D43BUL, 0xDCD0E804UL, + 0xF1290DC7UL, 0xCC00FFA3UL, 0xB5390F92UL, 0x690FED0BUL, + 0x667B9FFBUL, 0xCEDB7D9CUL, 0xA091CF0BUL, 0xD9155EA3UL, + 0xBB132F88UL, 0x515BAD24UL, 0x7B9479BFUL, 0x763BD6EBUL, + 0x37392EB3UL, 0xCC115979UL, 0x8026E297UL, 0xF42E312DUL, + 0x6842ADA7UL, 0xC66A2B3BUL, 0x12754CCCUL, 0x782EF11CUL, + 0x6A124237UL, 0xB79251E7UL, 0x06A1BBE6UL, 0x4BFB6350UL, + 0x1A6B1018UL, 0x11CAEDFAUL, 0x3D25BDD8UL, 0xE2E1C3C9UL, + 0x44421659UL, 0x0A121386UL, 0xD90CEC6EUL, 0xD5ABEA2AUL, + 0x64AF674EUL, 0xDA86A85FUL, 0xBEBFE988UL, 0x64E4C3FEUL, + 0x9DBC8057UL, 0xF0F7C086UL, 0x60787BF8UL, 0x6003604DUL, + 0xD1FD8346UL, 0xF6381FB0UL, 0x7745AE04UL, 0xD736FCCCUL, + 0x83426B33UL, 0xF01EAB71UL, 0xB0804187UL, 0x3C005E5FUL, + 0x77A057BEUL, 0xBDE8AE24UL, 0x55464299UL, 0xBF582E61UL, + 0x4E58F48FUL, 0xF2DDFDA2UL, 0xF474EF38UL, 0x8789BDC2UL, + 0x5366F9C3UL, 0xC8B38E74UL, 0xB475F255UL, 0x46FCD9B9UL, + 0x7AEB2661UL, 0x8B1DDF84UL, 0x846A0E79UL, 0x915F95E2UL, + 0x466E598EUL, 0x20B45770UL, 0x8CD55591UL, 0xC902DE4CUL, + 0xB90BACE1UL, 0xBB8205D0UL, 0x11A86248UL, 0x7574A99EUL, + 0xB77F19B6UL, 0xE0A9DC09UL, 0x662D09A1UL, 0xC4324633UL, + 0xE85A1F02UL, 0x09F0BE8CUL, 0x4A99A025UL, 0x1D6EFE10UL, + 0x1AB93D1DUL, 0x0BA5A4DFUL, 0xA186F20FUL, 0x2868F169UL, + 0xDCB7DA83UL, 0x573906FEUL, 0xA1E2CE9BUL, 0x4FCD7F52UL, + 0x50115E01UL, 0xA70683FAUL, 0xA002B5C4UL, 0x0DE6D027UL, + 0x9AF88C27UL, 0x773F8641UL, 0xC3604C06UL, 0x61A806B5UL, + 0xF0177A28UL, 0xC0F586E0UL, 0x006058AAUL, 0x30DC7D62UL, + 0x11E69ED7UL, 0x2338EA63UL, 0x53C2DD94UL, 0xC2C21634UL, + 0xBBCBEE56UL, 0x90BCB6DEUL, 0xEBFC7DA1UL, 0xCE591D76UL, + 0x6F05E409UL, 0x4B7C0188UL, 0x39720A3DUL, 0x7C927C24UL, + 0x86E3725FUL, 0x724D9DB9UL, 0x1AC15BB4UL, 0xD39EB8FCUL, + 0xED545578UL, 0x08FCA5B5UL, 0xD83D7CD3UL, 0x4DAD0FC4UL, + 0x1E50EF5EUL, 0xB161E6F8UL, 0xA28514D9UL, 0x6C51133CUL, + 0x6FD5C7E7UL, 0x56E14EC4UL, 0x362ABFCEUL, 0xDDC6C837UL, + 0xD79A3234UL, 0x92638212UL, 0x670EFA8EUL, 0x406000E0UL }, + { 0x3A39CE37UL, 0xD3FAF5CFUL, 0xABC27737UL, 0x5AC52D1BUL, + 0x5CB0679EUL, 0x4FA33742UL, 0xD3822740UL, 0x99BC9BBEUL, + 0xD5118E9DUL, 0xBF0F7315UL, 0xD62D1C7EUL, 0xC700C47BUL, + 0xB78C1B6BUL, 0x21A19045UL, 0xB26EB1BEUL, 0x6A366EB4UL, + 0x5748AB2FUL, 0xBC946E79UL, 0xC6A376D2UL, 0x6549C2C8UL, + 0x530FF8EEUL, 0x468DDE7DUL, 0xD5730A1DUL, 0x4CD04DC6UL, + 0x2939BBDBUL, 0xA9BA4650UL, 0xAC9526E8UL, 0xBE5EE304UL, + 0xA1FAD5F0UL, 0x6A2D519AUL, 0x63EF8CE2UL, 0x9A86EE22UL, + 0xC089C2B8UL, 0x43242EF6UL, 0xA51E03AAUL, 0x9CF2D0A4UL, + 0x83C061BAUL, 0x9BE96A4DUL, 0x8FE51550UL, 0xBA645BD6UL, + 0x2826A2F9UL, 0xA73A3AE1UL, 0x4BA99586UL, 0xEF5562E9UL, + 0xC72FEFD3UL, 0xF752F7DAUL, 0x3F046F69UL, 0x77FA0A59UL, + 0x80E4A915UL, 0x87B08601UL, 0x9B09E6ADUL, 0x3B3EE593UL, + 0xE990FD5AUL, 0x9E34D797UL, 0x2CF0B7D9UL, 0x022B8B51UL, + 0x96D5AC3AUL, 0x017DA67DUL, 0xD1CF3ED6UL, 0x7C7D2D28UL, + 0x1F9F25CFUL, 0xADF2B89BUL, 0x5AD6B472UL, 0x5A88F54CUL, + 0xE029AC71UL, 0xE019A5E6UL, 0x47B0ACFDUL, 0xED93FA9BUL, + 0xE8D3C48DUL, 0x283B57CCUL, 0xF8D56629UL, 0x79132E28UL, + 0x785F0191UL, 0xED756055UL, 0xF7960E44UL, 0xE3D35E8CUL, + 0x15056DD4UL, 0x88F46DBAUL, 0x03A16125UL, 0x0564F0BDUL, + 0xC3EB9E15UL, 0x3C9057A2UL, 0x97271AECUL, 0xA93A072AUL, + 0x1B3F6D9BUL, 0x1E6321F5UL, 0xF59C66FBUL, 0x26DCF319UL, + 0x7533D928UL, 0xB155FDF5UL, 0x03563482UL, 0x8ABA3CBBUL, + 0x28517711UL, 0xC20AD9F8UL, 0xABCC5167UL, 0xCCAD925FUL, + 0x4DE81751UL, 0x3830DC8EUL, 0x379D5862UL, 0x9320F991UL, + 0xEA7A90C2UL, 0xFB3E7BCEUL, 0x5121CE64UL, 0x774FBE32UL, + 0xA8B6E37EUL, 0xC3293D46UL, 0x48DE5369UL, 0x6413E680UL, + 0xA2AE0810UL, 0xDD6DB224UL, 0x69852DFDUL, 0x09072166UL, + 0xB39A460AUL, 0x6445C0DDUL, 0x586CDECFUL, 0x1C20C8AEUL, + 0x5BBEF7DDUL, 0x1B588D40UL, 0xCCD2017FUL, 0x6BB4E3BBUL, + 0xDDA26A7EUL, 0x3A59FF45UL, 0x3E350A44UL, 0xBCB4CDD5UL, + 0x72EACEA8UL, 0xFA6484BBUL, 0x8D6612AEUL, 0xBF3C6F47UL, + 0xD29BE463UL, 0x542F5D9EUL, 0xAEC2771BUL, 0xF64E6370UL, + 0x740E0D8DUL, 0xE75B1357UL, 0xF8721671UL, 0xAF537D5DUL, + 0x4040CB08UL, 0x4EB4E2CCUL, 0x34D2466AUL, 0x0115AF84UL, + 0xE1B00428UL, 0x95983A1DUL, 0x06B89FB4UL, 0xCE6EA048UL, + 0x6F3F3B82UL, 0x3520AB82UL, 0x011A1D4BUL, 0x277227F8UL, + 0x611560B1UL, 0xE7933FDCUL, 0xBB3A792BUL, 0x344525BDUL, + 0xA08839E1UL, 0x51CE794BUL, 0x2F32C9B7UL, 0xA01FBAC9UL, + 0xE01CC87EUL, 0xBCC7D1F6UL, 0xCF0111C3UL, 0xA1E8AAC7UL, + 0x1A908749UL, 0xD44FBD9AUL, 0xD0DADECBUL, 0xD50ADA38UL, + 0x0339C32AUL, 0xC6913667UL, 0x8DF9317CUL, 0xE0B12B4FUL, + 0xF79E59B7UL, 0x43F5BB3AUL, 0xF2D519FFUL, 0x27D9459CUL, + 0xBF97222CUL, 0x15E6FC2AUL, 0x0F91FC71UL, 0x9B941525UL, + 0xFAE59361UL, 0xCEB69CEBUL, 0xC2A86459UL, 0x12BAA8D1UL, + 0xB6C1075EUL, 0xE3056A0CUL, 0x10D25065UL, 0xCB03A442UL, + 0xE0EC6E0EUL, 0x1698DB3BUL, 0x4C98A0BEUL, 0x3278E964UL, + 0x9F1F9532UL, 0xE0D392DFUL, 0xD3A0342BUL, 0x8971F21EUL, + 0x1B0A7441UL, 0x4BA3348CUL, 0xC5BE7120UL, 0xC37632D8UL, + 0xDF359F8DUL, 0x9B992F2EUL, 0xE60B6F47UL, 0x0FE3F11DUL, + 0xE54CDA54UL, 0x1EDAD891UL, 0xCE6279CFUL, 0xCD3E7E6FUL, + 0x1618B166UL, 0xFD2C1D05UL, 0x848FD2C5UL, 0xF6FB2299UL, + 0xF523F357UL, 0xA6327623UL, 0x93A83531UL, 0x56CCCD02UL, + 0xACF08162UL, 0x5A75EBB5UL, 0x6E163697UL, 0x88D273CCUL, + 0xDE966292UL, 0x81B949D0UL, 0x4C50901BUL, 0x71C65614UL, + 0xE6C6C7BDUL, 0x327A140AUL, 0x45E1D006UL, 0xC3F27B9AUL, + 0xC9AA53FDUL, 0x62A80F00UL, 0xBB25BFE2UL, 0x35BDD2F6UL, + 0x71126905UL, 0xB2040222UL, 0xB6CBCF7CUL, 0xCD769C2BUL, + 0x53113EC0UL, 0x1640E3D3UL, 0x38ABBD60UL, 0x2547ADF0UL, + 0xBA38209CUL, 0xF746CE76UL, 0x77AFA1C5UL, 0x20756060UL, + 0x85CBFE4EUL, 0x8AE88DD8UL, 0x7AAAF9B0UL, 0x4CF9AA7EUL, + 0x1948C25CUL, 0x02FB8A8CUL, 0x01C36AE4UL, 0xD6EBE1F9UL, + 0x90D4F869UL, 0xA65CDEA0UL, 0x3F09252DUL, 0xC208E69FUL, + 0xB74E6132UL, 0xCE77E25BUL, 0x578FDFE3UL, 0x3AC372E6UL } +}; + +#ifndef __GNUC__ +#define F(x) ((S1[LTC_BYTE(x,3)] + S2[LTC_BYTE(x,2)]) ^ S3[LTC_BYTE(x,1)]) + S4[LTC_BYTE(x,0)] +#else +#define F(x) ((skey->blowfish.S[0][LTC_BYTE(x,3)] + skey->blowfish.S[1][LTC_BYTE(x,2)]) ^ skey->blowfish.S[2][LTC_BYTE(x,1)]) + skey->blowfish.S[3][LTC_BYTE(x,0)] +#endif + +static void s_blowfish_encipher(ulong32 *L, ulong32 *R, const symmetric_key *skey) +{ + int rounds; + + ulong32 l, r; +#ifndef __GNUC__ + const ulong32 *S1, *S2, *S3, *S4; + + S1 = skey->blowfish.S[0]; + S2 = skey->blowfish.S[1]; + S3 = skey->blowfish.S[2]; + S4 = skey->blowfish.S[3]; +#endif + + l = *L; + r = *R; + + /* do 16 rounds */ + for (rounds = 0; rounds < 16; ) { + l ^= skey->blowfish.K[rounds++]; r ^= F(l); + r ^= skey->blowfish.K[rounds++]; l ^= F(r); + l ^= skey->blowfish.K[rounds++]; r ^= F(l); + r ^= skey->blowfish.K[rounds++]; l ^= F(r); + } + + /* last keying */ + l ^= skey->blowfish.K[16]; + r ^= skey->blowfish.K[17]; + + *L = r; + *R = l; +} + +void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey) +{ + unsigned long i; + ulong32 *d = data; + + for (i = 0; i < blocks; ++i) { + s_blowfish_encipher(d, d + 1, skey); + d += 2; + } +} + +static ulong32 s_blowfish_stream2word(const unsigned char *d, int dlen, int *cur) +{ + unsigned int z; + int y = *cur; + ulong32 ret = 0; + + for (z = 0; z < 4; z++) { + ret = (ret << 8) | ((ulong32)d[y++] & 255); + if (y == dlen) { + y = 0; + } + } + + *cur = y; + return ret; +} + + /** + Expand the Blowfish internal state + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param data The additional data you wish to pass (can be NULL) + @param datalen The additional data 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 blowfish_expand(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey) +{ + ulong32 x, y, A, B[2]; + int i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* load in key bytes (Supplied by David Hopwood) */ + i = 0; + for (x = 0; x < 18; x++) { + A = s_blowfish_stream2word(key, keylen, &i); + skey->blowfish.K[x] ^= A; + } + + + i = 0; + B[0] = 0; + B[1] = 0; + for (x = 0; x < 18; x += 2) { + if (data != NULL) { + B[0] ^= s_blowfish_stream2word(data, datalen, &i); + B[1] ^= s_blowfish_stream2word(data, datalen, &i); + } + /* encrypt it */ + s_blowfish_encipher(&B[0], &B[1], skey); + /* copy it */ + skey->blowfish.K[x] = B[0]; + skey->blowfish.K[x+1] = B[1]; + } + + /* encrypt S array */ + for (x = 0; x < 4; x++) { + for (y = 0; y < 256; y += 2) { + if (data != NULL) { + B[0] ^= s_blowfish_stream2word(data, datalen, &i); + B[1] ^= s_blowfish_stream2word(data, datalen, &i); + } + /* encrypt it */ + s_blowfish_encipher(&B[0], &B[1], skey); + /* copy it */ + skey->blowfish.S[x][y] = B[0]; + skey->blowfish.S[x][y+1] = B[1]; + } + } + +#ifdef LTC_CLEAN_STACK + zeromem(B, sizeof(B)); +#endif + + return CRYPT_OK; +} + +/** + Initialize the Blowfish 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 blowfish_setup(const unsigned char *key, int keylen, int num_rounds, + symmetric_key *skey) +{ + /* check key length */ + if (keylen < 8 || keylen > 56) { + return CRYPT_INVALID_KEYSIZE; + } + /* check rounds */ + if (num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + return blowfish_setup_with_data(key, keylen, NULL, 0, skey); +} + +/** + Alternative initialize of the Blowfish block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param data The additional data you wish to pass (can be NULL) + @param datalen The additional data 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 blowfish_setup_with_data(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey) +{ + XMEMCPY(skey->blowfish.K, ORIG_P, sizeof(ORIG_P)); + XMEMCPY(skey->blowfish.S, ORIG_S, sizeof(ORIG_S)); + return blowfish_expand(key, keylen, data, datalen, skey); +} + +/** + Encrypts a block of text with Blowfish + @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 +*/ +#ifdef LTC_CLEAN_STACK +static int s_blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 L, R; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + /* load it */ + LOAD32H(L, &pt[0]); + LOAD32H(R, &pt[4]); + + s_blowfish_encipher(&L, &R, skey); + + /* store */ + STORE32H(L, &ct[0]); + STORE32H(R, &ct[4]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_blowfish_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 2 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with Blowfish + @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 +*/ +#ifdef LTC_CLEAN_STACK +static int s_blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 L, R; + int r; +#ifndef __GNUC__ + const ulong32 *S1, *S2, *S3, *S4; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + +#ifndef __GNUC__ + S1 = skey->blowfish.S[0]; + S2 = skey->blowfish.S[1]; + S3 = skey->blowfish.S[2]; + S4 = skey->blowfish.S[3]; +#endif + + /* load it */ + LOAD32H(R, &ct[0]); + LOAD32H(L, &ct[4]); + + /* undo last keying */ + R ^= skey->blowfish.K[17]; + L ^= skey->blowfish.K[16]; + + /* do 16 rounds */ + for (r = 15; r > 0; ) { + L ^= F(R); R ^= skey->blowfish.K[r--]; + R ^= F(L); L ^= skey->blowfish.K[r--]; + L ^= F(R); R ^= skey->blowfish.K[r--]; + R ^= F(L); L ^= skey->blowfish.K[r--]; + } + + /* store */ + STORE32H(L, &pt[0]); + STORE32H(R, &pt[4]); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_blowfish_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 2 + sizeof(int)); + return err; +} +#endif + + +/** + Performs a self-test of the Blowfish block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int blowfish_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + int err; + symmetric_key key; + static const struct { + unsigned char key[8], pt[8], ct[8]; + } tests[] = { + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78} + }, + { + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A} + }, + { + { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + { 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2} + } + }; + unsigned char tmp[2][8]; + int x, y; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = blowfish_setup(tests[x].key, 8, 16, &key)) != CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + blowfish_ecb_encrypt(tests[x].pt, tmp[0], &key); + blowfish_ecb_decrypt(tmp[0], tmp[1], &key); + + /* compare */ + if ((compare_testvector(tmp[0], 8, tests[x].ct, 8, "Blowfish Encrypt", x) != 0) || + (compare_testvector(tmp[1], 8, tests[x].pt, 8, "Blowfish Decrypt", x) != 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[0][y] = 0; + for (y = 0; y < 1000; y++) blowfish_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) blowfish_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void blowfish_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 blowfish_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 56) { + *keysize = 56; + } + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/camellia.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/camellia.c new file mode 100644 index 0000000..733e963 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/camellia.c @@ -0,0 +1,720 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file camellia.c + Implementation by Tom St Denis of Elliptic Semiconductor +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_CAMELLIA + +const struct ltc_cipher_descriptor camellia_desc = { + "camellia", + 23, + 16, 32, 16, 18, + &camellia_setup, + &camellia_ecb_encrypt, + &camellia_ecb_decrypt, + &camellia_test, + &camellia_done, + &camellia_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 SP1110[] = { +0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700, 0xc0c0c000, 0xe5e5e500, +0xe4e4e400, 0x85858500, 0x57575700, 0x35353500, 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, +0x23232300, 0xefefef00, 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100, +0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500, 0x92929200, 0xbdbdbd00, +0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00, 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, +0x3e3e3e00, 0x30303000, 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00, +0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700, 0x5d5d5d00, 0x3d3d3d00, +0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600, 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, +0x8b8b8b00, 0x0d0d0d00, 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00, +0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100, 0x84848400, 0x99999900, +0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200, 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, +0x6d6d6d00, 0xb7b7b700, 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700, +0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00, 0x11111100, 0x1c1c1c00, +0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600, 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, +0xfefefe00, 0x44444400, 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100, +0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00, 0x69696900, 0x50505000, +0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00, 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, +0x54545400, 0x5b5b5b00, 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200, +0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700, 0x75757500, 0xdbdbdb00, +0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00, 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, +0x87878700, 0x5c5c5c00, 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300, +0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00, 0xbfbfbf00, 0xe2e2e200, +0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600, 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, +0x81818100, 0x96969600, 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00, +0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00, 0xbcbcbc00, 0x8e8e8e00, +0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600, 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, +0x78787800, 0x98989800, 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00, +0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200, 0x8d8d8d00, 0xfafafa00, +0x72727200, 0x07070700, 0xb9b9b900, 0x55555500, 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, +0x36363600, 0x49494900, 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400, +0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900, 0x43434300, 0xc1c1c100, +0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400, 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00, +}; + +static const ulong32 SP0222[] = { +0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e, 0x00818181, 0x00cbcbcb, +0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a, 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, +0x00464646, 0x00dfdfdf, 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242, +0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca, 0x00252525, 0x007b7b7b, +0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f, 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, +0x007c7c7c, 0x00606060, 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434, +0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e, 0x00bababa, 0x007a7a7a, +0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad, 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, +0x00171717, 0x001a1a1a, 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a, +0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363, 0x00090909, 0x00333333, +0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585, 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, +0x00dadada, 0x006f6f6f, 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf, +0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636, 0x00222222, 0x00383838, +0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c, 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, +0x00fdfdfd, 0x00888888, 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323, +0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9, 0x00d2d2d2, 0x00a0a0a0, +0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa, 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, +0x00a8a8a8, 0x00b6b6b6, 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5, +0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef, 0x00eaeaea, 0x00b7b7b7, +0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5, 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, +0x000f0f0f, 0x00b8b8b8, 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666, +0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe, 0x007f7f7f, 0x00c5c5c5, +0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c, 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, +0x00030303, 0x002d2d2d, 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c, +0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc, 0x00797979, 0x001d1d1d, +0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d, 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, +0x00f0f0f0, 0x00313131, 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575, +0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545, 0x001b1b1b, 0x00f5f5f5, +0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa, 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, +0x006c6c6c, 0x00929292, 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949, +0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393, 0x00868686, 0x00838383, +0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9, 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d, +}; + +static const ulong32 SP3033[] = { +0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393, 0x60006060, 0xf200f2f2, +0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a, 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, +0x91009191, 0xf700f7f7, 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090, +0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2, 0x49004949, 0xde00dede, +0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7, 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, +0x1f001f1f, 0x18001818, 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d, +0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3, 0xae00aeae, 0x9e009e9e, +0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b, 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, +0xc500c5c5, 0x86008686, 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696, +0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8, 0x42004242, 0xcc00cccc, +0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161, 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, +0xb600b6b6, 0xdb00dbdb, 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb, +0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d, 0x88008888, 0x0e000e0e, +0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b, 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, +0x7f007f7f, 0x22002222, 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8, +0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e, 0xb400b4b4, 0x28002828, +0x55005555, 0x68006868, 0x50005050, 0xbe00bebe, 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, +0x2a002a2a, 0xad00adad, 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969, +0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb, 0xba00baba, 0xed00eded, +0x45004545, 0x81008181, 0x73007373, 0x6d006d6d, 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, +0xc300c3c3, 0x2e002e2e, 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999, +0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf, 0xdf00dfdf, 0x71007171, +0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313, 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, +0xc000c0c0, 0x4b004b4b, 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717, +0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737, 0x5e005e5e, 0x47004747, +0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b, 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, +0x3c003c3c, 0x4c004c4c, 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d, +0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151, 0xc600c6c6, 0x7d007d7d, +0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa, 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, +0x1b001b1b, 0xa400a4a4, 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252, +0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4, 0xa100a1a1, 0xe000e0e0, +0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a, 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f, +}; + +static const ulong32 SP4404[] = { +0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057, 0xeaea00ea, 0xaeae00ae, +0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5, 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, +0x86860086, 0xafaf00af, 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b, +0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a, 0x51510051, 0x6c6c006c, +0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0, 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, +0xdfdf00df, 0xcbcb00cb, 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004, +0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c, 0x53530053, 0xf2f200f2, +0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a, 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, +0xaaaa00aa, 0xa0a000a0, 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064, +0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6, 0x09090009, 0xdddd00dd, +0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090, 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, +0x52520052, 0xd8d800d8, 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063, +0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9, 0x2f2f002f, 0xb4b400b4, +0x78780078, 0x06060006, 0xe7e700e7, 0x71710071, 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, +0x72720072, 0xb9b900b9, 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1, +0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad, 0x77770077, 0x80800080, +0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5, 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, +0xefef00ef, 0x93930093, 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd, +0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f, 0xc5c500c5, 0x1a1a001a, +0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d, 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, +0x0d0d000d, 0x66660066, 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099, +0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031, 0x17170017, 0xd7d700d7, +0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c, 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, +0x44440044, 0xb2b200b2, 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050, +0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095, 0xffff00ff, 0xd2d200d2, +0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db, 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, +0x5c5c005c, 0x02020002, 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2, +0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b, 0xbebe00be, 0x2e2e002e, +0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e, 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, +0x98980098, 0x6a6a006a, 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa, +0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068, 0x38380038, 0xa4a400a4, +0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1, 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e, +}; + +static const ulong64 key_sigma[] = { + CONST64(0xA09E667F3BCC908B), + CONST64(0xB67AE8584CAA73B2), + CONST64(0xC6EF372FE94F82BE), + CONST64(0x54FF53A5F1D36F1C), + CONST64(0x10E527FADE682D1D), + CONST64(0xB05688C2B3E6C1FD) +}; + +static ulong64 F(ulong64 x) +{ + ulong32 D, U; + +#define loc(i) ((8-i)*8) + + D = SP1110[(x >> loc(8)) & 0xFF] ^ SP0222[(x >> loc(5)) & 0xFF] ^ SP3033[(x >> loc(6)) & 0xFF] ^ SP4404[(x >> loc(7)) & 0xFF]; + U = SP1110[(x >> loc(1)) & 0xFF] ^ SP0222[(x >> loc(2)) & 0xFF] ^ SP3033[(x >> loc(3)) & 0xFF] ^ SP4404[(x >> loc(4)) & 0xFF]; + + D ^= U; + U = D ^ RORc(U, 8); + + return ((ulong64)U) | (((ulong64)D) << CONST64(32)); +} + +static void rot_128(const unsigned char *in, unsigned count, unsigned char *out) +{ + unsigned x, w, b; + + w = count >> 3; + b = count & 7; + + for (x = 0; x < 16; x++) { + out[x] = (in[(x+w)&15] << b) | (in[(x+w+1)&15] >> (8 - b)); + } +} + +int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + unsigned char T[48], kA[16], kB[16], kR[16], kL[16]; + int x; + ulong64 A, B; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* Valid sizes (in bytes) are 16, 24, 32 */ + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + /* number of rounds */ + skey->camellia.R = (keylen == 16) ? 18 : 24; + + if (num_rounds != 0 && num_rounds != skey->camellia.R) { + return CRYPT_INVALID_ROUNDS; + } + + /* expand key */ + if (keylen == 16) { + for (x = 0; x < 16; x++) { + T[x] = key[x]; + T[x + 16] = 0; + } + } else if (keylen == 24) { + for (x = 0; x < 24; x++) { + T[x] = key[x]; + } + for (x = 24; x < 32; x++) { + T[x] = key[x-8] ^ 0xFF; + } + } else { + for (x = 0; x < 32; x++) { + T[x] = key[x]; + } + } + + for (x = 0; x < 16; x++) { + kL[x] = T[x]; + kR[x] = T[x + 16]; + } + + for (x = 32; x < 48; x++) { + T[x] = T[x - 32] ^ T[x - 16]; + } + + /* first two rounds */ + LOAD64H(A, T+32); LOAD64H(B, T+40); + B ^= F(A ^ key_sigma[0]); + A ^= F(B ^ key_sigma[1]); + STORE64H(A, T+32); STORE64H(B, T+40); + + /* xor kL in */ + for (x = 0; x < 16; x++) { T[x+32] ^= kL[x]; } + + /* next two rounds */ + LOAD64H(A, T+32); LOAD64H(B, T+40); + B ^= F(A ^ key_sigma[2]); + A ^= F(B ^ key_sigma[3]); + STORE64H(A, T+32); STORE64H(B, T+40); + + /* grab KA */ + for (x = 0; x < 16; x++) { kA[x] = T[x+32]; } + + /* xor kR in */ + for (x = 0; x < 16; x++) { T[x+32] ^= kR[x]; } + + if (keylen == 16) { + /* grab whitening keys kw1 and kw2 */ + LOAD64H(skey->camellia.kw[0], kL); + LOAD64H(skey->camellia.kw[1], kL+8); + + /* k1-k2 */ + LOAD64H(skey->camellia.k[0], kA); + LOAD64H(skey->camellia.k[1], kA+8); + + /* rotate kL by 15, k3/k4 */ + rot_128(kL, 15, T+32); + LOAD64H(skey->camellia.k[2], T+32); + LOAD64H(skey->camellia.k[3], T+40); + + /* rotate kA by 15, k5/k6 */ + rot_128(kA, 15, T+32); + LOAD64H(skey->camellia.k[4], T+32); + LOAD64H(skey->camellia.k[5], T+40); + + /* rotate kA by 30, kl1, kl2 */ + rot_128(kA, 30, T+32); + LOAD64H(skey->camellia.kl[0], T+32); + LOAD64H(skey->camellia.kl[1], T+40); + + /* rotate kL by 45, k7/k8 */ + rot_128(kL, 45, T+32); + LOAD64H(skey->camellia.k[6], T+32); + LOAD64H(skey->camellia.k[7], T+40); + + /* rotate kA by 45, k9/k10 */ + rot_128(kA, 45, T+32); + LOAD64H(skey->camellia.k[8], T+32); + rot_128(kL, 60, T+32); + LOAD64H(skey->camellia.k[9], T+40); + + /* rotate kA by 60, k11/k12 */ + rot_128(kA, 60, T+32); + LOAD64H(skey->camellia.k[10], T+32); + LOAD64H(skey->camellia.k[11], T+40); + + /* rotate kL by 77, kl3, kl4 */ + rot_128(kL, 77, T+32); + LOAD64H(skey->camellia.kl[2], T+32); + LOAD64H(skey->camellia.kl[3], T+40); + + /* rotate kL by 94, k13/k14 */ + rot_128(kL, 94, T+32); + LOAD64H(skey->camellia.k[12], T+32); + LOAD64H(skey->camellia.k[13], T+40); + + /* rotate kA by 94, k15/k16 */ + rot_128(kA, 94, T+32); + LOAD64H(skey->camellia.k[14], T+32); + LOAD64H(skey->camellia.k[15], T+40); + + /* rotate kL by 111, k17/k18 */ + rot_128(kL, 111, T+32); + LOAD64H(skey->camellia.k[16], T+32); + LOAD64H(skey->camellia.k[17], T+40); + + /* rotate kA by 111, kw3/kw4 */ + rot_128(kA, 111, T+32); + LOAD64H(skey->camellia.kw[2], T+32); + LOAD64H(skey->camellia.kw[3], T+40); + } else { + /* last two rounds */ + LOAD64H(A, T+32); LOAD64H(B, T+40); + B ^= F(A ^ key_sigma[4]); + A ^= F(B ^ key_sigma[5]); + STORE64H(A, T+32); STORE64H(B, T+40); + + /* grab kB */ + for (x = 0; x < 16; x++) { kB[x] = T[x+32]; } + + /* kw1/2 from kL*/ + LOAD64H(skey->camellia.kw[0], kL); + LOAD64H(skey->camellia.kw[1], kL+8); + + /* k1/k2 = kB */ + LOAD64H(skey->camellia.k[0], kB); + LOAD64H(skey->camellia.k[1], kB+8); + + /* k3/k4 = kR by 15 */ + rot_128(kR, 15, T+32); + LOAD64H(skey->camellia.k[2], T+32); + LOAD64H(skey->camellia.k[3], T+40); + + /* k5/k7 = kA by 15 */ + rot_128(kA, 15, T+32); + LOAD64H(skey->camellia.k[4], T+32); + LOAD64H(skey->camellia.k[5], T+40); + + /* kl1/2 = kR by 30 */ + rot_128(kR, 30, T+32); + LOAD64H(skey->camellia.kl[0], T+32); + LOAD64H(skey->camellia.kl[1], T+40); + + /* k7/k8 = kB by 30 */ + rot_128(kB, 30, T+32); + LOAD64H(skey->camellia.k[6], T+32); + LOAD64H(skey->camellia.k[7], T+40); + + /* k9/k10 = kL by 45 */ + rot_128(kL, 45, T+32); + LOAD64H(skey->camellia.k[8], T+32); + LOAD64H(skey->camellia.k[9], T+40); + + /* k11/k12 = kA by 45 */ + rot_128(kA, 45, T+32); + LOAD64H(skey->camellia.k[10], T+32); + LOAD64H(skey->camellia.k[11], T+40); + + /* kl3/4 = kL by 60 */ + rot_128(kL, 60, T+32); + LOAD64H(skey->camellia.kl[2], T+32); + LOAD64H(skey->camellia.kl[3], T+40); + + /* k13/k14 = kR by 60 */ + rot_128(kR, 60, T+32); + LOAD64H(skey->camellia.k[12], T+32); + LOAD64H(skey->camellia.k[13], T+40); + + /* k15/k16 = kB by 15 */ + rot_128(kB, 60, T+32); + LOAD64H(skey->camellia.k[14], T+32); + LOAD64H(skey->camellia.k[15], T+40); + + /* k17/k18 = kL by 77 */ + rot_128(kL, 77, T+32); + LOAD64H(skey->camellia.k[16], T+32); + LOAD64H(skey->camellia.k[17], T+40); + + /* kl5/6 = kA by 77 */ + rot_128(kA, 77, T+32); + LOAD64H(skey->camellia.kl[4], T+32); + LOAD64H(skey->camellia.kl[5], T+40); + + /* k19/k20 = kR by 94 */ + rot_128(kR, 94, T+32); + LOAD64H(skey->camellia.k[18], T+32); + LOAD64H(skey->camellia.k[19], T+40); + + /* k21/k22 = kA by 94 */ + rot_128(kA, 94, T+32); + LOAD64H(skey->camellia.k[20], T+32); + LOAD64H(skey->camellia.k[21], T+40); + + /* k23/k24 = kL by 111 */ + rot_128(kL, 111, T+32); + LOAD64H(skey->camellia.k[22], T+32); + LOAD64H(skey->camellia.k[23], T+40); + + /* kw2/kw3 = kB by 111 */ + rot_128(kB, 111, T+32); + LOAD64H(skey->camellia.kw[2], T+32); + LOAD64H(skey->camellia.kw[3], T+40); + } + + return CRYPT_OK; +} + +int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong64 L, R; + ulong32 a, b; + + LOAD64H(L, pt+0); LOAD64H(R, pt+8); + L ^= skey->camellia.kw[0]; + R ^= skey->camellia.kw[1]; + + /* first 6 rounds */ + R ^= F(L ^ skey->camellia.k[0]); + L ^= F(R ^ skey->camellia.k[1]); + R ^= F(L ^ skey->camellia.k[2]); + L ^= F(R ^ skey->camellia.k[3]); + R ^= F(L ^ skey->camellia.k[4]); + L ^= F(R ^ skey->camellia.k[5]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1); + a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1); + R = (((ulong64)a) << 32) | b; + + /* second 6 rounds */ + R ^= F(L ^ skey->camellia.k[6]); + L ^= F(R ^ skey->camellia.k[7]); + R ^= F(L ^ skey->camellia.k[8]); + L ^= F(R ^ skey->camellia.k[9]); + R ^= F(L ^ skey->camellia.k[10]); + L ^= F(R ^ skey->camellia.k[11]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1); + a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1); + R = (((ulong64)a) << 32) | b; + + /* third 6 rounds */ + R ^= F(L ^ skey->camellia.k[12]); + L ^= F(R ^ skey->camellia.k[13]); + R ^= F(L ^ skey->camellia.k[14]); + L ^= F(R ^ skey->camellia.k[15]); + R ^= F(L ^ skey->camellia.k[16]); + L ^= F(R ^ skey->camellia.k[17]); + + /* next FL */ + if (skey->camellia.R == 24) { + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1); + a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1); + R = (((ulong64)a) << 32) | b; + + /* fourth 6 rounds */ + R ^= F(L ^ skey->camellia.k[18]); + L ^= F(R ^ skey->camellia.k[19]); + R ^= F(L ^ skey->camellia.k[20]); + L ^= F(R ^ skey->camellia.k[21]); + R ^= F(L ^ skey->camellia.k[22]); + L ^= F(R ^ skey->camellia.k[23]); + } + + L ^= skey->camellia.kw[3]; + R ^= skey->camellia.kw[2]; + + STORE64H(R, ct+0); STORE64H(L, ct+8); + + return CRYPT_OK; +} + +int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong64 L, R; + ulong32 a, b; + + LOAD64H(R, ct+0); LOAD64H(L, ct+8); + L ^= skey->camellia.kw[3]; + R ^= skey->camellia.kw[2]; + + /* next FL */ + if (skey->camellia.R == 24) { + /* fourth 6 rounds */ + L ^= F(R ^ skey->camellia.k[23]); + R ^= F(L ^ skey->camellia.k[22]); + L ^= F(R ^ skey->camellia.k[21]); + R ^= F(L ^ skey->camellia.k[20]); + L ^= F(R ^ skey->camellia.k[19]); + R ^= F(L ^ skey->camellia.k[18]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1); + a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU); + R = (((ulong64)a) << 32) | b; + + } + + /* third 6 rounds */ + L ^= F(R ^ skey->camellia.k[17]); + R ^= F(L ^ skey->camellia.k[16]); + L ^= F(R ^ skey->camellia.k[15]); + R ^= F(L ^ skey->camellia.k[14]); + L ^= F(R ^ skey->camellia.k[13]); + R ^= F(L ^ skey->camellia.k[12]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1); + a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU); + R = (((ulong64)a) << 32) | b; + + /* second 6 rounds */ + L ^= F(R ^ skey->camellia.k[11]); + R ^= F(L ^ skey->camellia.k[10]); + L ^= F(R ^ skey->camellia.k[9]); + R ^= F(L ^ skey->camellia.k[8]); + L ^= F(R ^ skey->camellia.k[7]); + R ^= F(L ^ skey->camellia.k[6]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1); + a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU); + R = (((ulong64)a) << 32) | b; + + /* first 6 rounds */ + L ^= F(R ^ skey->camellia.k[5]); + R ^= F(L ^ skey->camellia.k[4]); + L ^= F(R ^ skey->camellia.k[3]); + R ^= F(L ^ skey->camellia.k[2]); + L ^= F(R ^ skey->camellia.k[1]); + R ^= F(L ^ skey->camellia.k[0]); + + R ^= skey->camellia.kw[1]; + L ^= skey->camellia.kw[0]; + + STORE64H(R, pt+8); STORE64H(L, pt+0); + + return CRYPT_OK; +} + +int camellia_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + +{ + 16, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 } +}, + +{ + 24, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 } +}, + + +{ + 32, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 } +}, + +{ + 32, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }, + { 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }, + { 0x79, 0x60, 0x10, 0x9F, 0xB6, 0xDC, 0x42, 0x94, + 0x7F, 0xCF, 0xE5, 0x9E, 0xA3, 0xC5, 0xEB, 0x6B } +} +}; + unsigned char buf[2][16]; + symmetric_key skey; + int err; + unsigned int x; + + for (x = 0; x < sizeof(tests)/sizeof(tests[0]); x++) { + zeromem(&skey, sizeof(skey)); + if ((err = camellia_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) { + return err; + } + if ((err = camellia_ecb_encrypt(tests[x].pt, buf[0], &skey)) != CRYPT_OK) { + camellia_done(&skey); + return err; + } + if ((err = camellia_ecb_decrypt(tests[x].ct, buf[1], &skey)) != CRYPT_OK) { + camellia_done(&skey); + return err; + } + camellia_done(&skey); + if (compare_testvector(tests[x].ct, 16, buf[0], 16, "Camellia Encrypt", x) || + compare_testvector(tests[x].pt, 16, buf[1], 16, "Camellia Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +void camellia_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int camellia_keysize(int *keysize) +{ + if (*keysize >= 32) { *keysize = 32; } + else if (*keysize >= 24) { *keysize = 24; } + else if (*keysize >= 16) { *keysize = 16; } + else return CRYPT_INVALID_KEYSIZE; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/cast5.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/cast5.c new file mode 100644 index 0000000..3b401a5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/cast5.c @@ -0,0 +1,705 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + + /** + @file cast5.c + Implementation of LTC_CAST5 (RFC 2144) by Tom St Denis + */ +#include "tomcrypt_private.h" + +#ifdef LTC_CAST5 + +const struct ltc_cipher_descriptor cast5_desc = { + "cast5", + 15, + 5, 16, 8, 16, + &cast5_setup, + &cast5_ecb_encrypt, + &cast5_ecb_decrypt, + &cast5_test, + &cast5_done, + &cast5_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 S1[256] = { +0x30fb40d4UL, 0x9fa0ff0bUL, 0x6beccd2fUL, 0x3f258c7aUL, 0x1e213f2fUL, 0x9c004dd3UL, +0x6003e540UL, 0xcf9fc949UL, 0xbfd4af27UL, 0x88bbbdb5UL, 0xe2034090UL, 0x98d09675UL, +0x6e63a0e0UL, 0x15c361d2UL, 0xc2e7661dUL, 0x22d4ff8eUL, 0x28683b6fUL, 0xc07fd059UL, +0xff2379c8UL, 0x775f50e2UL, 0x43c340d3UL, 0xdf2f8656UL, 0x887ca41aUL, 0xa2d2bd2dUL, +0xa1c9e0d6UL, 0x346c4819UL, 0x61b76d87UL, 0x22540f2fUL, 0x2abe32e1UL, 0xaa54166bUL, +0x22568e3aUL, 0xa2d341d0UL, 0x66db40c8UL, 0xa784392fUL, 0x004dff2fUL, 0x2db9d2deUL, +0x97943facUL, 0x4a97c1d8UL, 0x527644b7UL, 0xb5f437a7UL, 0xb82cbaefUL, 0xd751d159UL, +0x6ff7f0edUL, 0x5a097a1fUL, 0x827b68d0UL, 0x90ecf52eUL, 0x22b0c054UL, 0xbc8e5935UL, +0x4b6d2f7fUL, 0x50bb64a2UL, 0xd2664910UL, 0xbee5812dUL, 0xb7332290UL, 0xe93b159fUL, +0xb48ee411UL, 0x4bff345dUL, 0xfd45c240UL, 0xad31973fUL, 0xc4f6d02eUL, 0x55fc8165UL, +0xd5b1caadUL, 0xa1ac2daeUL, 0xa2d4b76dUL, 0xc19b0c50UL, 0x882240f2UL, 0x0c6e4f38UL, +0xa4e4bfd7UL, 0x4f5ba272UL, 0x564c1d2fUL, 0xc59c5319UL, 0xb949e354UL, 0xb04669feUL, +0xb1b6ab8aUL, 0xc71358ddUL, 0x6385c545UL, 0x110f935dUL, 0x57538ad5UL, 0x6a390493UL, +0xe63d37e0UL, 0x2a54f6b3UL, 0x3a787d5fUL, 0x6276a0b5UL, 0x19a6fcdfUL, 0x7a42206aUL, +0x29f9d4d5UL, 0xf61b1891UL, 0xbb72275eUL, 0xaa508167UL, 0x38901091UL, 0xc6b505ebUL, +0x84c7cb8cUL, 0x2ad75a0fUL, 0x874a1427UL, 0xa2d1936bUL, 0x2ad286afUL, 0xaa56d291UL, +0xd7894360UL, 0x425c750dUL, 0x93b39e26UL, 0x187184c9UL, 0x6c00b32dUL, 0x73e2bb14UL, +0xa0bebc3cUL, 0x54623779UL, 0x64459eabUL, 0x3f328b82UL, 0x7718cf82UL, 0x59a2cea6UL, +0x04ee002eUL, 0x89fe78e6UL, 0x3fab0950UL, 0x325ff6c2UL, 0x81383f05UL, 0x6963c5c8UL, +0x76cb5ad6UL, 0xd49974c9UL, 0xca180dcfUL, 0x380782d5UL, 0xc7fa5cf6UL, 0x8ac31511UL, +0x35e79e13UL, 0x47da91d0UL, 0xf40f9086UL, 0xa7e2419eUL, 0x31366241UL, 0x051ef495UL, +0xaa573b04UL, 0x4a805d8dUL, 0x548300d0UL, 0x00322a3cUL, 0xbf64cddfUL, 0xba57a68eUL, +0x75c6372bUL, 0x50afd341UL, 0xa7c13275UL, 0x915a0bf5UL, 0x6b54bfabUL, 0x2b0b1426UL, +0xab4cc9d7UL, 0x449ccd82UL, 0xf7fbf265UL, 0xab85c5f3UL, 0x1b55db94UL, 0xaad4e324UL, +0xcfa4bd3fUL, 0x2deaa3e2UL, 0x9e204d02UL, 0xc8bd25acUL, 0xeadf55b3UL, 0xd5bd9e98UL, +0xe31231b2UL, 0x2ad5ad6cUL, 0x954329deUL, 0xadbe4528UL, 0xd8710f69UL, 0xaa51c90fUL, +0xaa786bf6UL, 0x22513f1eUL, 0xaa51a79bUL, 0x2ad344ccUL, 0x7b5a41f0UL, 0xd37cfbadUL, +0x1b069505UL, 0x41ece491UL, 0xb4c332e6UL, 0x032268d4UL, 0xc9600accUL, 0xce387e6dUL, +0xbf6bb16cUL, 0x6a70fb78UL, 0x0d03d9c9UL, 0xd4df39deUL, 0xe01063daUL, 0x4736f464UL, +0x5ad328d8UL, 0xb347cc96UL, 0x75bb0fc3UL, 0x98511bfbUL, 0x4ffbcc35UL, 0xb58bcf6aUL, +0xe11f0abcUL, 0xbfc5fe4aUL, 0xa70aec10UL, 0xac39570aUL, 0x3f04442fUL, 0x6188b153UL, +0xe0397a2eUL, 0x5727cb79UL, 0x9ceb418fUL, 0x1cacd68dUL, 0x2ad37c96UL, 0x0175cb9dUL, +0xc69dff09UL, 0xc75b65f0UL, 0xd9db40d8UL, 0xec0e7779UL, 0x4744ead4UL, 0xb11c3274UL, +0xdd24cb9eUL, 0x7e1c54bdUL, 0xf01144f9UL, 0xd2240eb1UL, 0x9675b3fdUL, 0xa3ac3755UL, +0xd47c27afUL, 0x51c85f4dUL, 0x56907596UL, 0xa5bb15e6UL, 0x580304f0UL, 0xca042cf1UL, +0x011a37eaUL, 0x8dbfaadbUL, 0x35ba3e4aUL, 0x3526ffa0UL, 0xc37b4d09UL, 0xbc306ed9UL, +0x98a52666UL, 0x5648f725UL, 0xff5e569dUL, 0x0ced63d0UL, 0x7c63b2cfUL, 0x700b45e1UL, +0xd5ea50f1UL, 0x85a92872UL, 0xaf1fbda7UL, 0xd4234870UL, 0xa7870bf3UL, 0x2d3b4d79UL, +0x42e04198UL, 0x0cd0ede7UL, 0x26470db8UL, 0xf881814cUL, 0x474d6ad7UL, 0x7c0c5e5cUL, +0xd1231959UL, 0x381b7298UL, 0xf5d2f4dbUL, 0xab838653UL, 0x6e2f1e23UL, 0x83719c9eUL, +0xbd91e046UL, 0x9a56456eUL, 0xdc39200cUL, 0x20c8c571UL, 0x962bda1cUL, 0xe1e696ffUL, +0xb141ab08UL, 0x7cca89b9UL, 0x1a69e783UL, 0x02cc4843UL, 0xa2f7c579UL, 0x429ef47dUL, +0x427b169cUL, 0x5ac9f049UL, 0xdd8f0f00UL, 0x5c8165bfUL}; + +static const ulong32 S2[256] = { +0x1f201094UL, 0xef0ba75bUL, 0x69e3cf7eUL, 0x393f4380UL, 0xfe61cf7aUL, 0xeec5207aUL, +0x55889c94UL, 0x72fc0651UL, 0xada7ef79UL, 0x4e1d7235UL, 0xd55a63ceUL, 0xde0436baUL, +0x99c430efUL, 0x5f0c0794UL, 0x18dcdb7dUL, 0xa1d6eff3UL, 0xa0b52f7bUL, 0x59e83605UL, +0xee15b094UL, 0xe9ffd909UL, 0xdc440086UL, 0xef944459UL, 0xba83ccb3UL, 0xe0c3cdfbUL, +0xd1da4181UL, 0x3b092ab1UL, 0xf997f1c1UL, 0xa5e6cf7bUL, 0x01420ddbUL, 0xe4e7ef5bUL, +0x25a1ff41UL, 0xe180f806UL, 0x1fc41080UL, 0x179bee7aUL, 0xd37ac6a9UL, 0xfe5830a4UL, +0x98de8b7fUL, 0x77e83f4eUL, 0x79929269UL, 0x24fa9f7bUL, 0xe113c85bUL, 0xacc40083UL, +0xd7503525UL, 0xf7ea615fUL, 0x62143154UL, 0x0d554b63UL, 0x5d681121UL, 0xc866c359UL, +0x3d63cf73UL, 0xcee234c0UL, 0xd4d87e87UL, 0x5c672b21UL, 0x071f6181UL, 0x39f7627fUL, +0x361e3084UL, 0xe4eb573bUL, 0x602f64a4UL, 0xd63acd9cUL, 0x1bbc4635UL, 0x9e81032dUL, +0x2701f50cUL, 0x99847ab4UL, 0xa0e3df79UL, 0xba6cf38cUL, 0x10843094UL, 0x2537a95eUL, +0xf46f6ffeUL, 0xa1ff3b1fUL, 0x208cfb6aUL, 0x8f458c74UL, 0xd9e0a227UL, 0x4ec73a34UL, +0xfc884f69UL, 0x3e4de8dfUL, 0xef0e0088UL, 0x3559648dUL, 0x8a45388cUL, 0x1d804366UL, +0x721d9bfdUL, 0xa58684bbUL, 0xe8256333UL, 0x844e8212UL, 0x128d8098UL, 0xfed33fb4UL, +0xce280ae1UL, 0x27e19ba5UL, 0xd5a6c252UL, 0xe49754bdUL, 0xc5d655ddUL, 0xeb667064UL, +0x77840b4dUL, 0xa1b6a801UL, 0x84db26a9UL, 0xe0b56714UL, 0x21f043b7UL, 0xe5d05860UL, +0x54f03084UL, 0x066ff472UL, 0xa31aa153UL, 0xdadc4755UL, 0xb5625dbfUL, 0x68561be6UL, +0x83ca6b94UL, 0x2d6ed23bUL, 0xeccf01dbUL, 0xa6d3d0baUL, 0xb6803d5cUL, 0xaf77a709UL, +0x33b4a34cUL, 0x397bc8d6UL, 0x5ee22b95UL, 0x5f0e5304UL, 0x81ed6f61UL, 0x20e74364UL, +0xb45e1378UL, 0xde18639bUL, 0x881ca122UL, 0xb96726d1UL, 0x8049a7e8UL, 0x22b7da7bUL, +0x5e552d25UL, 0x5272d237UL, 0x79d2951cUL, 0xc60d894cUL, 0x488cb402UL, 0x1ba4fe5bUL, +0xa4b09f6bUL, 0x1ca815cfUL, 0xa20c3005UL, 0x8871df63UL, 0xb9de2fcbUL, 0x0cc6c9e9UL, +0x0beeff53UL, 0xe3214517UL, 0xb4542835UL, 0x9f63293cUL, 0xee41e729UL, 0x6e1d2d7cUL, +0x50045286UL, 0x1e6685f3UL, 0xf33401c6UL, 0x30a22c95UL, 0x31a70850UL, 0x60930f13UL, +0x73f98417UL, 0xa1269859UL, 0xec645c44UL, 0x52c877a9UL, 0xcdff33a6UL, 0xa02b1741UL, +0x7cbad9a2UL, 0x2180036fUL, 0x50d99c08UL, 0xcb3f4861UL, 0xc26bd765UL, 0x64a3f6abUL, +0x80342676UL, 0x25a75e7bUL, 0xe4e6d1fcUL, 0x20c710e6UL, 0xcdf0b680UL, 0x17844d3bUL, +0x31eef84dUL, 0x7e0824e4UL, 0x2ccb49ebUL, 0x846a3baeUL, 0x8ff77888UL, 0xee5d60f6UL, +0x7af75673UL, 0x2fdd5cdbUL, 0xa11631c1UL, 0x30f66f43UL, 0xb3faec54UL, 0x157fd7faUL, +0xef8579ccUL, 0xd152de58UL, 0xdb2ffd5eUL, 0x8f32ce19UL, 0x306af97aUL, 0x02f03ef8UL, +0x99319ad5UL, 0xc242fa0fUL, 0xa7e3ebb0UL, 0xc68e4906UL, 0xb8da230cUL, 0x80823028UL, +0xdcdef3c8UL, 0xd35fb171UL, 0x088a1bc8UL, 0xbec0c560UL, 0x61a3c9e8UL, 0xbca8f54dUL, +0xc72feffaUL, 0x22822e99UL, 0x82c570b4UL, 0xd8d94e89UL, 0x8b1c34bcUL, 0x301e16e6UL, +0x273be979UL, 0xb0ffeaa6UL, 0x61d9b8c6UL, 0x00b24869UL, 0xb7ffce3fUL, 0x08dc283bUL, +0x43daf65aUL, 0xf7e19798UL, 0x7619b72fUL, 0x8f1c9ba4UL, 0xdc8637a0UL, 0x16a7d3b1UL, +0x9fc393b7UL, 0xa7136eebUL, 0xc6bcc63eUL, 0x1a513742UL, 0xef6828bcUL, 0x520365d6UL, +0x2d6a77abUL, 0x3527ed4bUL, 0x821fd216UL, 0x095c6e2eUL, 0xdb92f2fbUL, 0x5eea29cbUL, +0x145892f5UL, 0x91584f7fUL, 0x5483697bUL, 0x2667a8ccUL, 0x85196048UL, 0x8c4baceaUL, +0x833860d4UL, 0x0d23e0f9UL, 0x6c387e8aUL, 0x0ae6d249UL, 0xb284600cUL, 0xd835731dUL, +0xdcb1c647UL, 0xac4c56eaUL, 0x3ebd81b3UL, 0x230eabb0UL, 0x6438bc87UL, 0xf0b5b1faUL, +0x8f5ea2b3UL, 0xfc184642UL, 0x0a036b7aUL, 0x4fb089bdUL, 0x649da589UL, 0xa345415eUL, +0x5c038323UL, 0x3e5d3bb9UL, 0x43d79572UL, 0x7e6dd07cUL, 0x06dfdf1eUL, 0x6c6cc4efUL, +0x7160a539UL, 0x73bfbe70UL, 0x83877605UL, 0x4523ecf1UL}; + +static const ulong32 S3[256] = { +0x8defc240UL, 0x25fa5d9fUL, 0xeb903dbfUL, 0xe810c907UL, 0x47607fffUL, 0x369fe44bUL, +0x8c1fc644UL, 0xaececa90UL, 0xbeb1f9bfUL, 0xeefbcaeaUL, 0xe8cf1950UL, 0x51df07aeUL, +0x920e8806UL, 0xf0ad0548UL, 0xe13c8d83UL, 0x927010d5UL, 0x11107d9fUL, 0x07647db9UL, +0xb2e3e4d4UL, 0x3d4f285eUL, 0xb9afa820UL, 0xfade82e0UL, 0xa067268bUL, 0x8272792eUL, +0x553fb2c0UL, 0x489ae22bUL, 0xd4ef9794UL, 0x125e3fbcUL, 0x21fffceeUL, 0x825b1bfdUL, +0x9255c5edUL, 0x1257a240UL, 0x4e1a8302UL, 0xbae07fffUL, 0x528246e7UL, 0x8e57140eUL, +0x3373f7bfUL, 0x8c9f8188UL, 0xa6fc4ee8UL, 0xc982b5a5UL, 0xa8c01db7UL, 0x579fc264UL, +0x67094f31UL, 0xf2bd3f5fUL, 0x40fff7c1UL, 0x1fb78dfcUL, 0x8e6bd2c1UL, 0x437be59bUL, +0x99b03dbfUL, 0xb5dbc64bUL, 0x638dc0e6UL, 0x55819d99UL, 0xa197c81cUL, 0x4a012d6eUL, +0xc5884a28UL, 0xccc36f71UL, 0xb843c213UL, 0x6c0743f1UL, 0x8309893cUL, 0x0feddd5fUL, +0x2f7fe850UL, 0xd7c07f7eUL, 0x02507fbfUL, 0x5afb9a04UL, 0xa747d2d0UL, 0x1651192eUL, +0xaf70bf3eUL, 0x58c31380UL, 0x5f98302eUL, 0x727cc3c4UL, 0x0a0fb402UL, 0x0f7fef82UL, +0x8c96fdadUL, 0x5d2c2aaeUL, 0x8ee99a49UL, 0x50da88b8UL, 0x8427f4a0UL, 0x1eac5790UL, +0x796fb449UL, 0x8252dc15UL, 0xefbd7d9bUL, 0xa672597dUL, 0xada840d8UL, 0x45f54504UL, +0xfa5d7403UL, 0xe83ec305UL, 0x4f91751aUL, 0x925669c2UL, 0x23efe941UL, 0xa903f12eUL, +0x60270df2UL, 0x0276e4b6UL, 0x94fd6574UL, 0x927985b2UL, 0x8276dbcbUL, 0x02778176UL, +0xf8af918dUL, 0x4e48f79eUL, 0x8f616ddfUL, 0xe29d840eUL, 0x842f7d83UL, 0x340ce5c8UL, +0x96bbb682UL, 0x93b4b148UL, 0xef303cabUL, 0x984faf28UL, 0x779faf9bUL, 0x92dc560dUL, +0x224d1e20UL, 0x8437aa88UL, 0x7d29dc96UL, 0x2756d3dcUL, 0x8b907ceeUL, 0xb51fd240UL, +0xe7c07ce3UL, 0xe566b4a1UL, 0xc3e9615eUL, 0x3cf8209dUL, 0x6094d1e3UL, 0xcd9ca341UL, +0x5c76460eUL, 0x00ea983bUL, 0xd4d67881UL, 0xfd47572cUL, 0xf76cedd9UL, 0xbda8229cUL, +0x127dadaaUL, 0x438a074eUL, 0x1f97c090UL, 0x081bdb8aUL, 0x93a07ebeUL, 0xb938ca15UL, +0x97b03cffUL, 0x3dc2c0f8UL, 0x8d1ab2ecUL, 0x64380e51UL, 0x68cc7bfbUL, 0xd90f2788UL, +0x12490181UL, 0x5de5ffd4UL, 0xdd7ef86aUL, 0x76a2e214UL, 0xb9a40368UL, 0x925d958fUL, +0x4b39fffaUL, 0xba39aee9UL, 0xa4ffd30bUL, 0xfaf7933bUL, 0x6d498623UL, 0x193cbcfaUL, +0x27627545UL, 0x825cf47aUL, 0x61bd8ba0UL, 0xd11e42d1UL, 0xcead04f4UL, 0x127ea392UL, +0x10428db7UL, 0x8272a972UL, 0x9270c4a8UL, 0x127de50bUL, 0x285ba1c8UL, 0x3c62f44fUL, +0x35c0eaa5UL, 0xe805d231UL, 0x428929fbUL, 0xb4fcdf82UL, 0x4fb66a53UL, 0x0e7dc15bUL, +0x1f081fabUL, 0x108618aeUL, 0xfcfd086dUL, 0xf9ff2889UL, 0x694bcc11UL, 0x236a5caeUL, +0x12deca4dUL, 0x2c3f8cc5UL, 0xd2d02dfeUL, 0xf8ef5896UL, 0xe4cf52daUL, 0x95155b67UL, +0x494a488cUL, 0xb9b6a80cUL, 0x5c8f82bcUL, 0x89d36b45UL, 0x3a609437UL, 0xec00c9a9UL, +0x44715253UL, 0x0a874b49UL, 0xd773bc40UL, 0x7c34671cUL, 0x02717ef6UL, 0x4feb5536UL, +0xa2d02fffUL, 0xd2bf60c4UL, 0xd43f03c0UL, 0x50b4ef6dUL, 0x07478cd1UL, 0x006e1888UL, +0xa2e53f55UL, 0xb9e6d4bcUL, 0xa2048016UL, 0x97573833UL, 0xd7207d67UL, 0xde0f8f3dUL, +0x72f87b33UL, 0xabcc4f33UL, 0x7688c55dUL, 0x7b00a6b0UL, 0x947b0001UL, 0x570075d2UL, +0xf9bb88f8UL, 0x8942019eUL, 0x4264a5ffUL, 0x856302e0UL, 0x72dbd92bUL, 0xee971b69UL, +0x6ea22fdeUL, 0x5f08ae2bUL, 0xaf7a616dUL, 0xe5c98767UL, 0xcf1febd2UL, 0x61efc8c2UL, +0xf1ac2571UL, 0xcc8239c2UL, 0x67214cb8UL, 0xb1e583d1UL, 0xb7dc3e62UL, 0x7f10bdceUL, +0xf90a5c38UL, 0x0ff0443dUL, 0x606e6dc6UL, 0x60543a49UL, 0x5727c148UL, 0x2be98a1dUL, +0x8ab41738UL, 0x20e1be24UL, 0xaf96da0fUL, 0x68458425UL, 0x99833be5UL, 0x600d457dUL, +0x282f9350UL, 0x8334b362UL, 0xd91d1120UL, 0x2b6d8da0UL, 0x642b1e31UL, 0x9c305a00UL, +0x52bce688UL, 0x1b03588aUL, 0xf7baefd5UL, 0x4142ed9cUL, 0xa4315c11UL, 0x83323ec5UL, +0xdfef4636UL, 0xa133c501UL, 0xe9d3531cUL, 0xee353783UL}; + +static const ulong32 S4[256] = { +0x9db30420UL, 0x1fb6e9deUL, 0xa7be7befUL, 0xd273a298UL, 0x4a4f7bdbUL, 0x64ad8c57UL, +0x85510443UL, 0xfa020ed1UL, 0x7e287affUL, 0xe60fb663UL, 0x095f35a1UL, 0x79ebf120UL, +0xfd059d43UL, 0x6497b7b1UL, 0xf3641f63UL, 0x241e4adfUL, 0x28147f5fUL, 0x4fa2b8cdUL, +0xc9430040UL, 0x0cc32220UL, 0xfdd30b30UL, 0xc0a5374fUL, 0x1d2d00d9UL, 0x24147b15UL, +0xee4d111aUL, 0x0fca5167UL, 0x71ff904cUL, 0x2d195ffeUL, 0x1a05645fUL, 0x0c13fefeUL, +0x081b08caUL, 0x05170121UL, 0x80530100UL, 0xe83e5efeUL, 0xac9af4f8UL, 0x7fe72701UL, +0xd2b8ee5fUL, 0x06df4261UL, 0xbb9e9b8aUL, 0x7293ea25UL, 0xce84ffdfUL, 0xf5718801UL, +0x3dd64b04UL, 0xa26f263bUL, 0x7ed48400UL, 0x547eebe6UL, 0x446d4ca0UL, 0x6cf3d6f5UL, +0x2649abdfUL, 0xaea0c7f5UL, 0x36338cc1UL, 0x503f7e93UL, 0xd3772061UL, 0x11b638e1UL, +0x72500e03UL, 0xf80eb2bbUL, 0xabe0502eUL, 0xec8d77deUL, 0x57971e81UL, 0xe14f6746UL, +0xc9335400UL, 0x6920318fUL, 0x081dbb99UL, 0xffc304a5UL, 0x4d351805UL, 0x7f3d5ce3UL, +0xa6c866c6UL, 0x5d5bcca9UL, 0xdaec6feaUL, 0x9f926f91UL, 0x9f46222fUL, 0x3991467dUL, +0xa5bf6d8eUL, 0x1143c44fUL, 0x43958302UL, 0xd0214eebUL, 0x022083b8UL, 0x3fb6180cUL, +0x18f8931eUL, 0x281658e6UL, 0x26486e3eUL, 0x8bd78a70UL, 0x7477e4c1UL, 0xb506e07cUL, +0xf32d0a25UL, 0x79098b02UL, 0xe4eabb81UL, 0x28123b23UL, 0x69dead38UL, 0x1574ca16UL, +0xdf871b62UL, 0x211c40b7UL, 0xa51a9ef9UL, 0x0014377bUL, 0x041e8ac8UL, 0x09114003UL, +0xbd59e4d2UL, 0xe3d156d5UL, 0x4fe876d5UL, 0x2f91a340UL, 0x557be8deUL, 0x00eae4a7UL, +0x0ce5c2ecUL, 0x4db4bba6UL, 0xe756bdffUL, 0xdd3369acUL, 0xec17b035UL, 0x06572327UL, +0x99afc8b0UL, 0x56c8c391UL, 0x6b65811cUL, 0x5e146119UL, 0x6e85cb75UL, 0xbe07c002UL, +0xc2325577UL, 0x893ff4ecUL, 0x5bbfc92dUL, 0xd0ec3b25UL, 0xb7801ab7UL, 0x8d6d3b24UL, +0x20c763efUL, 0xc366a5fcUL, 0x9c382880UL, 0x0ace3205UL, 0xaac9548aUL, 0xeca1d7c7UL, +0x041afa32UL, 0x1d16625aUL, 0x6701902cUL, 0x9b757a54UL, 0x31d477f7UL, 0x9126b031UL, +0x36cc6fdbUL, 0xc70b8b46UL, 0xd9e66a48UL, 0x56e55a79UL, 0x026a4cebUL, 0x52437effUL, +0x2f8f76b4UL, 0x0df980a5UL, 0x8674cde3UL, 0xedda04ebUL, 0x17a9be04UL, 0x2c18f4dfUL, +0xb7747f9dUL, 0xab2af7b4UL, 0xefc34d20UL, 0x2e096b7cUL, 0x1741a254UL, 0xe5b6a035UL, +0x213d42f6UL, 0x2c1c7c26UL, 0x61c2f50fUL, 0x6552daf9UL, 0xd2c231f8UL, 0x25130f69UL, +0xd8167fa2UL, 0x0418f2c8UL, 0x001a96a6UL, 0x0d1526abUL, 0x63315c21UL, 0x5e0a72ecUL, +0x49bafefdUL, 0x187908d9UL, 0x8d0dbd86UL, 0x311170a7UL, 0x3e9b640cUL, 0xcc3e10d7UL, +0xd5cad3b6UL, 0x0caec388UL, 0xf73001e1UL, 0x6c728affUL, 0x71eae2a1UL, 0x1f9af36eUL, +0xcfcbd12fUL, 0xc1de8417UL, 0xac07be6bUL, 0xcb44a1d8UL, 0x8b9b0f56UL, 0x013988c3UL, +0xb1c52fcaUL, 0xb4be31cdUL, 0xd8782806UL, 0x12a3a4e2UL, 0x6f7de532UL, 0x58fd7eb6UL, +0xd01ee900UL, 0x24adffc2UL, 0xf4990fc5UL, 0x9711aac5UL, 0x001d7b95UL, 0x82e5e7d2UL, +0x109873f6UL, 0x00613096UL, 0xc32d9521UL, 0xada121ffUL, 0x29908415UL, 0x7fbb977fUL, +0xaf9eb3dbUL, 0x29c9ed2aUL, 0x5ce2a465UL, 0xa730f32cUL, 0xd0aa3fe8UL, 0x8a5cc091UL, +0xd49e2ce7UL, 0x0ce454a9UL, 0xd60acd86UL, 0x015f1919UL, 0x77079103UL, 0xdea03af6UL, +0x78a8565eUL, 0xdee356dfUL, 0x21f05cbeUL, 0x8b75e387UL, 0xb3c50651UL, 0xb8a5c3efUL, +0xd8eeb6d2UL, 0xe523be77UL, 0xc2154529UL, 0x2f69efdfUL, 0xafe67afbUL, 0xf470c4b2UL, +0xf3e0eb5bUL, 0xd6cc9876UL, 0x39e4460cUL, 0x1fda8538UL, 0x1987832fUL, 0xca007367UL, +0xa99144f8UL, 0x296b299eUL, 0x492fc295UL, 0x9266beabUL, 0xb5676e69UL, 0x9bd3dddaUL, +0xdf7e052fUL, 0xdb25701cUL, 0x1b5e51eeUL, 0xf65324e6UL, 0x6afce36cUL, 0x0316cc04UL, +0x8644213eUL, 0xb7dc59d0UL, 0x7965291fUL, 0xccd6fd43UL, 0x41823979UL, 0x932bcdf6UL, +0xb657c34dUL, 0x4edfd282UL, 0x7ae5290cUL, 0x3cb9536bUL, 0x851e20feUL, 0x9833557eUL, +0x13ecf0b0UL, 0xd3ffb372UL, 0x3f85c5c1UL, 0x0aef7ed2UL}; + +static const ulong32 S5[256] = { +0x7ec90c04UL, 0x2c6e74b9UL, 0x9b0e66dfUL, 0xa6337911UL, 0xb86a7fffUL, 0x1dd358f5UL, +0x44dd9d44UL, 0x1731167fUL, 0x08fbf1faUL, 0xe7f511ccUL, 0xd2051b00UL, 0x735aba00UL, +0x2ab722d8UL, 0x386381cbUL, 0xacf6243aUL, 0x69befd7aUL, 0xe6a2e77fUL, 0xf0c720cdUL, +0xc4494816UL, 0xccf5c180UL, 0x38851640UL, 0x15b0a848UL, 0xe68b18cbUL, 0x4caadeffUL, +0x5f480a01UL, 0x0412b2aaUL, 0x259814fcUL, 0x41d0efe2UL, 0x4e40b48dUL, 0x248eb6fbUL, +0x8dba1cfeUL, 0x41a99b02UL, 0x1a550a04UL, 0xba8f65cbUL, 0x7251f4e7UL, 0x95a51725UL, +0xc106ecd7UL, 0x97a5980aUL, 0xc539b9aaUL, 0x4d79fe6aUL, 0xf2f3f763UL, 0x68af8040UL, +0xed0c9e56UL, 0x11b4958bUL, 0xe1eb5a88UL, 0x8709e6b0UL, 0xd7e07156UL, 0x4e29fea7UL, +0x6366e52dUL, 0x02d1c000UL, 0xc4ac8e05UL, 0x9377f571UL, 0x0c05372aUL, 0x578535f2UL, +0x2261be02UL, 0xd642a0c9UL, 0xdf13a280UL, 0x74b55bd2UL, 0x682199c0UL, 0xd421e5ecUL, +0x53fb3ce8UL, 0xc8adedb3UL, 0x28a87fc9UL, 0x3d959981UL, 0x5c1ff900UL, 0xfe38d399UL, +0x0c4eff0bUL, 0x062407eaUL, 0xaa2f4fb1UL, 0x4fb96976UL, 0x90c79505UL, 0xb0a8a774UL, +0xef55a1ffUL, 0xe59ca2c2UL, 0xa6b62d27UL, 0xe66a4263UL, 0xdf65001fUL, 0x0ec50966UL, +0xdfdd55bcUL, 0x29de0655UL, 0x911e739aUL, 0x17af8975UL, 0x32c7911cUL, 0x89f89468UL, +0x0d01e980UL, 0x524755f4UL, 0x03b63cc9UL, 0x0cc844b2UL, 0xbcf3f0aaUL, 0x87ac36e9UL, +0xe53a7426UL, 0x01b3d82bUL, 0x1a9e7449UL, 0x64ee2d7eUL, 0xcddbb1daUL, 0x01c94910UL, +0xb868bf80UL, 0x0d26f3fdUL, 0x9342ede7UL, 0x04a5c284UL, 0x636737b6UL, 0x50f5b616UL, +0xf24766e3UL, 0x8eca36c1UL, 0x136e05dbUL, 0xfef18391UL, 0xfb887a37UL, 0xd6e7f7d4UL, +0xc7fb7dc9UL, 0x3063fcdfUL, 0xb6f589deUL, 0xec2941daUL, 0x26e46695UL, 0xb7566419UL, +0xf654efc5UL, 0xd08d58b7UL, 0x48925401UL, 0xc1bacb7fUL, 0xe5ff550fUL, 0xb6083049UL, +0x5bb5d0e8UL, 0x87d72e5aUL, 0xab6a6ee1UL, 0x223a66ceUL, 0xc62bf3cdUL, 0x9e0885f9UL, +0x68cb3e47UL, 0x086c010fUL, 0xa21de820UL, 0xd18b69deUL, 0xf3f65777UL, 0xfa02c3f6UL, +0x407edac3UL, 0xcbb3d550UL, 0x1793084dUL, 0xb0d70ebaUL, 0x0ab378d5UL, 0xd951fb0cUL, +0xded7da56UL, 0x4124bbe4UL, 0x94ca0b56UL, 0x0f5755d1UL, 0xe0e1e56eUL, 0x6184b5beUL, +0x580a249fUL, 0x94f74bc0UL, 0xe327888eUL, 0x9f7b5561UL, 0xc3dc0280UL, 0x05687715UL, +0x646c6bd7UL, 0x44904db3UL, 0x66b4f0a3UL, 0xc0f1648aUL, 0x697ed5afUL, 0x49e92ff6UL, +0x309e374fUL, 0x2cb6356aUL, 0x85808573UL, 0x4991f840UL, 0x76f0ae02UL, 0x083be84dUL, +0x28421c9aUL, 0x44489406UL, 0x736e4cb8UL, 0xc1092910UL, 0x8bc95fc6UL, 0x7d869cf4UL, +0x134f616fUL, 0x2e77118dUL, 0xb31b2be1UL, 0xaa90b472UL, 0x3ca5d717UL, 0x7d161bbaUL, +0x9cad9010UL, 0xaf462ba2UL, 0x9fe459d2UL, 0x45d34559UL, 0xd9f2da13UL, 0xdbc65487UL, +0xf3e4f94eUL, 0x176d486fUL, 0x097c13eaUL, 0x631da5c7UL, 0x445f7382UL, 0x175683f4UL, +0xcdc66a97UL, 0x70be0288UL, 0xb3cdcf72UL, 0x6e5dd2f3UL, 0x20936079UL, 0x459b80a5UL, +0xbe60e2dbUL, 0xa9c23101UL, 0xeba5315cUL, 0x224e42f2UL, 0x1c5c1572UL, 0xf6721b2cUL, +0x1ad2fff3UL, 0x8c25404eUL, 0x324ed72fUL, 0x4067b7fdUL, 0x0523138eUL, 0x5ca3bc78UL, +0xdc0fd66eUL, 0x75922283UL, 0x784d6b17UL, 0x58ebb16eUL, 0x44094f85UL, 0x3f481d87UL, +0xfcfeae7bUL, 0x77b5ff76UL, 0x8c2302bfUL, 0xaaf47556UL, 0x5f46b02aUL, 0x2b092801UL, +0x3d38f5f7UL, 0x0ca81f36UL, 0x52af4a8aUL, 0x66d5e7c0UL, 0xdf3b0874UL, 0x95055110UL, +0x1b5ad7a8UL, 0xf61ed5adUL, 0x6cf6e479UL, 0x20758184UL, 0xd0cefa65UL, 0x88f7be58UL, +0x4a046826UL, 0x0ff6f8f3UL, 0xa09c7f70UL, 0x5346aba0UL, 0x5ce96c28UL, 0xe176eda3UL, +0x6bac307fUL, 0x376829d2UL, 0x85360fa9UL, 0x17e3fe2aUL, 0x24b79767UL, 0xf5a96b20UL, +0xd6cd2595UL, 0x68ff1ebfUL, 0x7555442cUL, 0xf19f06beUL, 0xf9e0659aUL, 0xeeb9491dUL, +0x34010718UL, 0xbb30cab8UL, 0xe822fe15UL, 0x88570983UL, 0x750e6249UL, 0xda627e55UL, +0x5e76ffa8UL, 0xb1534546UL, 0x6d47de08UL, 0xefe9e7d4UL}; + +static const ulong32 S6[256] = { +0xf6fa8f9dUL, 0x2cac6ce1UL, 0x4ca34867UL, 0xe2337f7cUL, 0x95db08e7UL, 0x016843b4UL, +0xeced5cbcUL, 0x325553acUL, 0xbf9f0960UL, 0xdfa1e2edUL, 0x83f0579dUL, 0x63ed86b9UL, +0x1ab6a6b8UL, 0xde5ebe39UL, 0xf38ff732UL, 0x8989b138UL, 0x33f14961UL, 0xc01937bdUL, +0xf506c6daUL, 0xe4625e7eUL, 0xa308ea99UL, 0x4e23e33cUL, 0x79cbd7ccUL, 0x48a14367UL, +0xa3149619UL, 0xfec94bd5UL, 0xa114174aUL, 0xeaa01866UL, 0xa084db2dUL, 0x09a8486fUL, +0xa888614aUL, 0x2900af98UL, 0x01665991UL, 0xe1992863UL, 0xc8f30c60UL, 0x2e78ef3cUL, +0xd0d51932UL, 0xcf0fec14UL, 0xf7ca07d2UL, 0xd0a82072UL, 0xfd41197eUL, 0x9305a6b0UL, +0xe86be3daUL, 0x74bed3cdUL, 0x372da53cUL, 0x4c7f4448UL, 0xdab5d440UL, 0x6dba0ec3UL, +0x083919a7UL, 0x9fbaeed9UL, 0x49dbcfb0UL, 0x4e670c53UL, 0x5c3d9c01UL, 0x64bdb941UL, +0x2c0e636aUL, 0xba7dd9cdUL, 0xea6f7388UL, 0xe70bc762UL, 0x35f29adbUL, 0x5c4cdd8dUL, +0xf0d48d8cUL, 0xb88153e2UL, 0x08a19866UL, 0x1ae2eac8UL, 0x284caf89UL, 0xaa928223UL, +0x9334be53UL, 0x3b3a21bfUL, 0x16434be3UL, 0x9aea3906UL, 0xefe8c36eUL, 0xf890cdd9UL, +0x80226daeUL, 0xc340a4a3UL, 0xdf7e9c09UL, 0xa694a807UL, 0x5b7c5eccUL, 0x221db3a6UL, +0x9a69a02fUL, 0x68818a54UL, 0xceb2296fUL, 0x53c0843aUL, 0xfe893655UL, 0x25bfe68aUL, +0xb4628abcUL, 0xcf222ebfUL, 0x25ac6f48UL, 0xa9a99387UL, 0x53bddb65UL, 0xe76ffbe7UL, +0xe967fd78UL, 0x0ba93563UL, 0x8e342bc1UL, 0xe8a11be9UL, 0x4980740dUL, 0xc8087dfcUL, +0x8de4bf99UL, 0xa11101a0UL, 0x7fd37975UL, 0xda5a26c0UL, 0xe81f994fUL, 0x9528cd89UL, +0xfd339fedUL, 0xb87834bfUL, 0x5f04456dUL, 0x22258698UL, 0xc9c4c83bUL, 0x2dc156beUL, +0x4f628daaUL, 0x57f55ec5UL, 0xe2220abeUL, 0xd2916ebfUL, 0x4ec75b95UL, 0x24f2c3c0UL, +0x42d15d99UL, 0xcd0d7fa0UL, 0x7b6e27ffUL, 0xa8dc8af0UL, 0x7345c106UL, 0xf41e232fUL, +0x35162386UL, 0xe6ea8926UL, 0x3333b094UL, 0x157ec6f2UL, 0x372b74afUL, 0x692573e4UL, +0xe9a9d848UL, 0xf3160289UL, 0x3a62ef1dUL, 0xa787e238UL, 0xf3a5f676UL, 0x74364853UL, +0x20951063UL, 0x4576698dUL, 0xb6fad407UL, 0x592af950UL, 0x36f73523UL, 0x4cfb6e87UL, +0x7da4cec0UL, 0x6c152daaUL, 0xcb0396a8UL, 0xc50dfe5dUL, 0xfcd707abUL, 0x0921c42fUL, +0x89dff0bbUL, 0x5fe2be78UL, 0x448f4f33UL, 0x754613c9UL, 0x2b05d08dUL, 0x48b9d585UL, +0xdc049441UL, 0xc8098f9bUL, 0x7dede786UL, 0xc39a3373UL, 0x42410005UL, 0x6a091751UL, +0x0ef3c8a6UL, 0x890072d6UL, 0x28207682UL, 0xa9a9f7beUL, 0xbf32679dUL, 0xd45b5b75UL, +0xb353fd00UL, 0xcbb0e358UL, 0x830f220aUL, 0x1f8fb214UL, 0xd372cf08UL, 0xcc3c4a13UL, +0x8cf63166UL, 0x061c87beUL, 0x88c98f88UL, 0x6062e397UL, 0x47cf8e7aUL, 0xb6c85283UL, +0x3cc2acfbUL, 0x3fc06976UL, 0x4e8f0252UL, 0x64d8314dUL, 0xda3870e3UL, 0x1e665459UL, +0xc10908f0UL, 0x513021a5UL, 0x6c5b68b7UL, 0x822f8aa0UL, 0x3007cd3eUL, 0x74719eefUL, +0xdc872681UL, 0x073340d4UL, 0x7e432fd9UL, 0x0c5ec241UL, 0x8809286cUL, 0xf592d891UL, +0x08a930f6UL, 0x957ef305UL, 0xb7fbffbdUL, 0xc266e96fUL, 0x6fe4ac98UL, 0xb173ecc0UL, +0xbc60b42aUL, 0x953498daUL, 0xfba1ae12UL, 0x2d4bd736UL, 0x0f25faabUL, 0xa4f3fcebUL, +0xe2969123UL, 0x257f0c3dUL, 0x9348af49UL, 0x361400bcUL, 0xe8816f4aUL, 0x3814f200UL, +0xa3f94043UL, 0x9c7a54c2UL, 0xbc704f57UL, 0xda41e7f9UL, 0xc25ad33aUL, 0x54f4a084UL, +0xb17f5505UL, 0x59357cbeUL, 0xedbd15c8UL, 0x7f97c5abUL, 0xba5ac7b5UL, 0xb6f6deafUL, +0x3a479c3aUL, 0x5302da25UL, 0x653d7e6aUL, 0x54268d49UL, 0x51a477eaUL, 0x5017d55bUL, +0xd7d25d88UL, 0x44136c76UL, 0x0404a8c8UL, 0xb8e5a121UL, 0xb81a928aUL, 0x60ed5869UL, +0x97c55b96UL, 0xeaec991bUL, 0x29935913UL, 0x01fdb7f1UL, 0x088e8dfaUL, 0x9ab6f6f5UL, +0x3b4cbf9fUL, 0x4a5de3abUL, 0xe6051d35UL, 0xa0e1d855UL, 0xd36b4cf1UL, 0xf544edebUL, +0xb0e93524UL, 0xbebb8fbdUL, 0xa2d762cfUL, 0x49c92f54UL, 0x38b5f331UL, 0x7128a454UL, +0x48392905UL, 0xa65b1db8UL, 0x851c97bdUL, 0xd675cf2fUL}; + +static const ulong32 S7[256] = { +0x85e04019UL, 0x332bf567UL, 0x662dbfffUL, 0xcfc65693UL, 0x2a8d7f6fUL, 0xab9bc912UL, +0xde6008a1UL, 0x2028da1fUL, 0x0227bce7UL, 0x4d642916UL, 0x18fac300UL, 0x50f18b82UL, +0x2cb2cb11UL, 0xb232e75cUL, 0x4b3695f2UL, 0xb28707deUL, 0xa05fbcf6UL, 0xcd4181e9UL, +0xe150210cUL, 0xe24ef1bdUL, 0xb168c381UL, 0xfde4e789UL, 0x5c79b0d8UL, 0x1e8bfd43UL, +0x4d495001UL, 0x38be4341UL, 0x913cee1dUL, 0x92a79c3fUL, 0x089766beUL, 0xbaeeadf4UL, +0x1286becfUL, 0xb6eacb19UL, 0x2660c200UL, 0x7565bde4UL, 0x64241f7aUL, 0x8248dca9UL, +0xc3b3ad66UL, 0x28136086UL, 0x0bd8dfa8UL, 0x356d1cf2UL, 0x107789beUL, 0xb3b2e9ceUL, +0x0502aa8fUL, 0x0bc0351eUL, 0x166bf52aUL, 0xeb12ff82UL, 0xe3486911UL, 0xd34d7516UL, +0x4e7b3affUL, 0x5f43671bUL, 0x9cf6e037UL, 0x4981ac83UL, 0x334266ceUL, 0x8c9341b7UL, +0xd0d854c0UL, 0xcb3a6c88UL, 0x47bc2829UL, 0x4725ba37UL, 0xa66ad22bUL, 0x7ad61f1eUL, +0x0c5cbafaUL, 0x4437f107UL, 0xb6e79962UL, 0x42d2d816UL, 0x0a961288UL, 0xe1a5c06eUL, +0x13749e67UL, 0x72fc081aUL, 0xb1d139f7UL, 0xf9583745UL, 0xcf19df58UL, 0xbec3f756UL, +0xc06eba30UL, 0x07211b24UL, 0x45c28829UL, 0xc95e317fUL, 0xbc8ec511UL, 0x38bc46e9UL, +0xc6e6fa14UL, 0xbae8584aUL, 0xad4ebc46UL, 0x468f508bUL, 0x7829435fUL, 0xf124183bUL, +0x821dba9fUL, 0xaff60ff4UL, 0xea2c4e6dUL, 0x16e39264UL, 0x92544a8bUL, 0x009b4fc3UL, +0xaba68cedUL, 0x9ac96f78UL, 0x06a5b79aUL, 0xb2856e6eUL, 0x1aec3ca9UL, 0xbe838688UL, +0x0e0804e9UL, 0x55f1be56UL, 0xe7e5363bUL, 0xb3a1f25dUL, 0xf7debb85UL, 0x61fe033cUL, +0x16746233UL, 0x3c034c28UL, 0xda6d0c74UL, 0x79aac56cUL, 0x3ce4e1adUL, 0x51f0c802UL, +0x98f8f35aUL, 0x1626a49fUL, 0xeed82b29UL, 0x1d382fe3UL, 0x0c4fb99aUL, 0xbb325778UL, +0x3ec6d97bUL, 0x6e77a6a9UL, 0xcb658b5cUL, 0xd45230c7UL, 0x2bd1408bUL, 0x60c03eb7UL, +0xb9068d78UL, 0xa33754f4UL, 0xf430c87dUL, 0xc8a71302UL, 0xb96d8c32UL, 0xebd4e7beUL, +0xbe8b9d2dUL, 0x7979fb06UL, 0xe7225308UL, 0x8b75cf77UL, 0x11ef8da4UL, 0xe083c858UL, +0x8d6b786fUL, 0x5a6317a6UL, 0xfa5cf7a0UL, 0x5dda0033UL, 0xf28ebfb0UL, 0xf5b9c310UL, +0xa0eac280UL, 0x08b9767aUL, 0xa3d9d2b0UL, 0x79d34217UL, 0x021a718dUL, 0x9ac6336aUL, +0x2711fd60UL, 0x438050e3UL, 0x069908a8UL, 0x3d7fedc4UL, 0x826d2befUL, 0x4eeb8476UL, +0x488dcf25UL, 0x36c9d566UL, 0x28e74e41UL, 0xc2610acaUL, 0x3d49a9cfUL, 0xbae3b9dfUL, +0xb65f8de6UL, 0x92aeaf64UL, 0x3ac7d5e6UL, 0x9ea80509UL, 0xf22b017dUL, 0xa4173f70UL, +0xdd1e16c3UL, 0x15e0d7f9UL, 0x50b1b887UL, 0x2b9f4fd5UL, 0x625aba82UL, 0x6a017962UL, +0x2ec01b9cUL, 0x15488aa9UL, 0xd716e740UL, 0x40055a2cUL, 0x93d29a22UL, 0xe32dbf9aUL, +0x058745b9UL, 0x3453dc1eUL, 0xd699296eUL, 0x496cff6fUL, 0x1c9f4986UL, 0xdfe2ed07UL, +0xb87242d1UL, 0x19de7eaeUL, 0x053e561aUL, 0x15ad6f8cUL, 0x66626c1cUL, 0x7154c24cUL, +0xea082b2aUL, 0x93eb2939UL, 0x17dcb0f0UL, 0x58d4f2aeUL, 0x9ea294fbUL, 0x52cf564cUL, +0x9883fe66UL, 0x2ec40581UL, 0x763953c3UL, 0x01d6692eUL, 0xd3a0c108UL, 0xa1e7160eUL, +0xe4f2dfa6UL, 0x693ed285UL, 0x74904698UL, 0x4c2b0eddUL, 0x4f757656UL, 0x5d393378UL, +0xa132234fUL, 0x3d321c5dUL, 0xc3f5e194UL, 0x4b269301UL, 0xc79f022fUL, 0x3c997e7eUL, +0x5e4f9504UL, 0x3ffafbbdUL, 0x76f7ad0eUL, 0x296693f4UL, 0x3d1fce6fUL, 0xc61e45beUL, +0xd3b5ab34UL, 0xf72bf9b7UL, 0x1b0434c0UL, 0x4e72b567UL, 0x5592a33dUL, 0xb5229301UL, +0xcfd2a87fUL, 0x60aeb767UL, 0x1814386bUL, 0x30bcc33dUL, 0x38a0c07dUL, 0xfd1606f2UL, +0xc363519bUL, 0x589dd390UL, 0x5479f8e6UL, 0x1cb8d647UL, 0x97fd61a9UL, 0xea7759f4UL, +0x2d57539dUL, 0x569a58cfUL, 0xe84e63adUL, 0x462e1b78UL, 0x6580f87eUL, 0xf3817914UL, +0x91da55f4UL, 0x40a230f3UL, 0xd1988f35UL, 0xb6e318d2UL, 0x3ffa50bcUL, 0x3d40f021UL, +0xc3c0bdaeUL, 0x4958c24cUL, 0x518f36b2UL, 0x84b1d370UL, 0x0fedce83UL, 0x878ddadaUL, +0xf2a279c7UL, 0x94e01be8UL, 0x90716f4bUL, 0x954b8aa3UL}; + +static const ulong32 S8[256] = { +0xe216300dUL, 0xbbddfffcUL, 0xa7ebdabdUL, 0x35648095UL, 0x7789f8b7UL, 0xe6c1121bUL, +0x0e241600UL, 0x052ce8b5UL, 0x11a9cfb0UL, 0xe5952f11UL, 0xece7990aUL, 0x9386d174UL, +0x2a42931cUL, 0x76e38111UL, 0xb12def3aUL, 0x37ddddfcUL, 0xde9adeb1UL, 0x0a0cc32cUL, +0xbe197029UL, 0x84a00940UL, 0xbb243a0fUL, 0xb4d137cfUL, 0xb44e79f0UL, 0x049eedfdUL, +0x0b15a15dUL, 0x480d3168UL, 0x8bbbde5aUL, 0x669ded42UL, 0xc7ece831UL, 0x3f8f95e7UL, +0x72df191bUL, 0x7580330dUL, 0x94074251UL, 0x5c7dcdfaUL, 0xabbe6d63UL, 0xaa402164UL, +0xb301d40aUL, 0x02e7d1caUL, 0x53571daeUL, 0x7a3182a2UL, 0x12a8ddecUL, 0xfdaa335dUL, +0x176f43e8UL, 0x71fb46d4UL, 0x38129022UL, 0xce949ad4UL, 0xb84769adUL, 0x965bd862UL, +0x82f3d055UL, 0x66fb9767UL, 0x15b80b4eUL, 0x1d5b47a0UL, 0x4cfde06fUL, 0xc28ec4b8UL, +0x57e8726eUL, 0x647a78fcUL, 0x99865d44UL, 0x608bd593UL, 0x6c200e03UL, 0x39dc5ff6UL, +0x5d0b00a3UL, 0xae63aff2UL, 0x7e8bd632UL, 0x70108c0cUL, 0xbbd35049UL, 0x2998df04UL, +0x980cf42aUL, 0x9b6df491UL, 0x9e7edd53UL, 0x06918548UL, 0x58cb7e07UL, 0x3b74ef2eUL, +0x522fffb1UL, 0xd24708ccUL, 0x1c7e27cdUL, 0xa4eb215bUL, 0x3cf1d2e2UL, 0x19b47a38UL, +0x424f7618UL, 0x35856039UL, 0x9d17dee7UL, 0x27eb35e6UL, 0xc9aff67bUL, 0x36baf5b8UL, +0x09c467cdUL, 0xc18910b1UL, 0xe11dbf7bUL, 0x06cd1af8UL, 0x7170c608UL, 0x2d5e3354UL, +0xd4de495aUL, 0x64c6d006UL, 0xbcc0c62cUL, 0x3dd00db3UL, 0x708f8f34UL, 0x77d51b42UL, +0x264f620fUL, 0x24b8d2bfUL, 0x15c1b79eUL, 0x46a52564UL, 0xf8d7e54eUL, 0x3e378160UL, +0x7895cda5UL, 0x859c15a5UL, 0xe6459788UL, 0xc37bc75fUL, 0xdb07ba0cUL, 0x0676a3abUL, +0x7f229b1eUL, 0x31842e7bUL, 0x24259fd7UL, 0xf8bef472UL, 0x835ffcb8UL, 0x6df4c1f2UL, +0x96f5b195UL, 0xfd0af0fcUL, 0xb0fe134cUL, 0xe2506d3dUL, 0x4f9b12eaUL, 0xf215f225UL, +0xa223736fUL, 0x9fb4c428UL, 0x25d04979UL, 0x34c713f8UL, 0xc4618187UL, 0xea7a6e98UL, +0x7cd16efcUL, 0x1436876cUL, 0xf1544107UL, 0xbedeee14UL, 0x56e9af27UL, 0xa04aa441UL, +0x3cf7c899UL, 0x92ecbae6UL, 0xdd67016dUL, 0x151682ebUL, 0xa842eedfUL, 0xfdba60b4UL, +0xf1907b75UL, 0x20e3030fUL, 0x24d8c29eUL, 0xe139673bUL, 0xefa63fb8UL, 0x71873054UL, +0xb6f2cf3bUL, 0x9f326442UL, 0xcb15a4ccUL, 0xb01a4504UL, 0xf1e47d8dUL, 0x844a1be5UL, +0xbae7dfdcUL, 0x42cbda70UL, 0xcd7dae0aUL, 0x57e85b7aUL, 0xd53f5af6UL, 0x20cf4d8cUL, +0xcea4d428UL, 0x79d130a4UL, 0x3486ebfbUL, 0x33d3cddcUL, 0x77853b53UL, 0x37effcb5UL, +0xc5068778UL, 0xe580b3e6UL, 0x4e68b8f4UL, 0xc5c8b37eUL, 0x0d809ea2UL, 0x398feb7cUL, +0x132a4f94UL, 0x43b7950eUL, 0x2fee7d1cUL, 0x223613bdUL, 0xdd06caa2UL, 0x37df932bUL, +0xc4248289UL, 0xacf3ebc3UL, 0x5715f6b7UL, 0xef3478ddUL, 0xf267616fUL, 0xc148cbe4UL, +0x9052815eUL, 0x5e410fabUL, 0xb48a2465UL, 0x2eda7fa4UL, 0xe87b40e4UL, 0xe98ea084UL, +0x5889e9e1UL, 0xefd390fcUL, 0xdd07d35bUL, 0xdb485694UL, 0x38d7e5b2UL, 0x57720101UL, +0x730edebcUL, 0x5b643113UL, 0x94917e4fUL, 0x503c2fbaUL, 0x646f1282UL, 0x7523d24aUL, +0xe0779695UL, 0xf9c17a8fUL, 0x7a5b2121UL, 0xd187b896UL, 0x29263a4dUL, 0xba510cdfUL, +0x81f47c9fUL, 0xad1163edUL, 0xea7b5965UL, 0x1a00726eUL, 0x11403092UL, 0x00da6d77UL, +0x4a0cdd61UL, 0xad1f4603UL, 0x605bdfb0UL, 0x9eedc364UL, 0x22ebe6a8UL, 0xcee7d28aUL, +0xa0e736a0UL, 0x5564a6b9UL, 0x10853209UL, 0xc7eb8f37UL, 0x2de705caUL, 0x8951570fUL, +0xdf09822bUL, 0xbd691a6cUL, 0xaa12e4f2UL, 0x87451c0fUL, 0xe0f6a27aUL, 0x3ada4819UL, +0x4cf1764fUL, 0x0d771c2bUL, 0x67cdb156UL, 0x350d8384UL, 0x5938fa0fUL, 0x42399ef3UL, +0x36997b07UL, 0x0e84093dUL, 0x4aa93e61UL, 0x8360d87bUL, 0x1fa98b0cUL, 0x1149382cUL, +0xe97625a5UL, 0x0614d1b7UL, 0x0e25244bUL, 0x0c768347UL, 0x589e8d82UL, 0x0d2059d1UL, +0xa466bb1eUL, 0xf8da0a82UL, 0x04f19130UL, 0xba6e4ec0UL, 0x99265164UL, 0x1ee7230dUL, +0x50b2ad80UL, 0xeaee6801UL, 0x8db2a283UL, 0xea8bf59eUL}; + +/* returns the i'th byte of a variable */ +#ifdef _MSC_VER + #define GB(x, i) ((unsigned char)((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))) +#else + #define GB(x, i) (((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))&255) +#endif + + /** + Initialize the LTC_CAST5 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 + */ +#ifdef LTC_CLEAN_STACK +static int s_cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + ulong32 x[4], z[4]; + unsigned char buf[16]; + int y, i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 12 && num_rounds != 16 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + if (num_rounds == 12 && keylen > 10) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen < 5 || keylen > 16) { + return CRYPT_INVALID_KEYSIZE; + } + + /* extend the key as required */ + zeromem(buf, sizeof(buf)); + XMEMCPY(buf, key, (size_t)keylen); + + /* load and start the awful looking network */ + for (y = 0; y < 4; y++) { + LOAD32H(x[3-y],buf+4*y); + } + + for (i = y = 0; y < 2; y++) { + z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)]; + z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)]; + z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)]; + z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)]; + skey->cast5.K[i++] = S5[GB(z, 0x8)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0x7)] ^ S8[GB(z, 0x6)] ^ S5[GB(z, 0x2)]; + skey->cast5.K[i++] = S5[GB(z, 0xA)] ^ S6[GB(z, 0xB)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S6[GB(z, 0x6)]; + skey->cast5.K[i++] = S5[GB(z, 0xC)] ^ S6[GB(z, 0xd)] ^ S7[GB(z, 0x3)] ^ S8[GB(z, 0x2)] ^ S7[GB(z, 0x9)]; + skey->cast5.K[i++] = S5[GB(z, 0xE)] ^ S6[GB(z, 0xF)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x0)] ^ S8[GB(z, 0xc)]; + + x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)]; + x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)]; + x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)]; + x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)]; + skey->cast5.K[i++] = S5[GB(x, 0x3)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0xc)] ^ S8[GB(x, 0xd)] ^ S5[GB(x, 0x8)]; + skey->cast5.K[i++] = S5[GB(x, 0x1)] ^ S6[GB(x, 0x0)] ^ S7[GB(x, 0xe)] ^ S8[GB(x, 0xf)] ^ S6[GB(x, 0xd)]; + skey->cast5.K[i++] = S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x8)] ^ S8[GB(x, 0x9)] ^ S7[GB(x, 0x3)]; + skey->cast5.K[i++] = S5[GB(x, 0x5)] ^ S6[GB(x, 0x4)] ^ S7[GB(x, 0xa)] ^ S8[GB(x, 0xb)] ^ S8[GB(x, 0x7)]; + + /* second half */ + z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)]; + z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)]; + z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)]; + z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)]; + skey->cast5.K[i++] = S5[GB(z, 0x3)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0xc)] ^ S8[GB(z, 0xd)] ^ S5[GB(z, 0x9)]; + skey->cast5.K[i++] = S5[GB(z, 0x1)] ^ S6[GB(z, 0x0)] ^ S7[GB(z, 0xe)] ^ S8[GB(z, 0xf)] ^ S6[GB(z, 0xc)]; + skey->cast5.K[i++] = S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x8)] ^ S8[GB(z, 0x9)] ^ S7[GB(z, 0x2)]; + skey->cast5.K[i++] = S5[GB(z, 0x5)] ^ S6[GB(z, 0x4)] ^ S7[GB(z, 0xa)] ^ S8[GB(z, 0xb)] ^ S8[GB(z, 0x6)]; + + x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)]; + x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)]; + x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)]; + x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)]; + skey->cast5.K[i++] = S5[GB(x, 0x8)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0x7)] ^ S8[GB(x, 0x6)] ^ S5[GB(x, 0x3)]; + skey->cast5.K[i++] = S5[GB(x, 0xa)] ^ S6[GB(x, 0xb)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S6[GB(x, 0x7)]; + skey->cast5.K[i++] = S5[GB(x, 0xc)] ^ S6[GB(x, 0xd)] ^ S7[GB(x, 0x3)] ^ S8[GB(x, 0x2)] ^ S7[GB(x, 0x8)]; + skey->cast5.K[i++] = S5[GB(x, 0xe)] ^ S6[GB(x, 0xf)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x0)] ^ S8[GB(x, 0xd)]; + } + + skey->cast5.keylen = keylen; + +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); + zeromem(x, sizeof(x)); + zeromem(z, sizeof(z)); +#endif + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int z; + z = s_cast5_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(ulong32)*8 + 16 + sizeof(int)*2); + return z; +} +#endif + +LTC_INLINE static ulong32 FI(ulong32 R, ulong32 Km, ulong32 Kr) +{ + ulong32 I; + I = (Km + R); + I = ROL(I, Kr); + return ((S1[LTC_BYTE(I, 3)] ^ S2[LTC_BYTE(I,2)]) - S3[LTC_BYTE(I,1)]) + S4[LTC_BYTE(I,0)]; +} + +LTC_INLINE static ulong32 FII(ulong32 R, ulong32 Km, ulong32 Kr) +{ + ulong32 I; + I = (Km ^ R); + I = ROL(I, Kr); + return ((S1[LTC_BYTE(I, 3)] - S2[LTC_BYTE(I,2)]) + S3[LTC_BYTE(I,1)]) ^ S4[LTC_BYTE(I,0)]; +} + +LTC_INLINE static ulong32 FIII(ulong32 R, ulong32 Km, ulong32 Kr) +{ + ulong32 I; + I = (Km - R); + I = ROL(I, Kr); + return ((S1[LTC_BYTE(I, 3)] + S2[LTC_BYTE(I,2)]) ^ S3[LTC_BYTE(I,1)]) - S4[LTC_BYTE(I,0)]; +} + +/** + Encrypts a block of text with LTC_CAST5 + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled +*/ +#ifdef LTC_CLEAN_STACK +static int s_cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 R, L; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(L,&pt[0]); + LOAD32H(R,&pt[4]); + L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]); + R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]); + L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]); + R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]); + L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]); + R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]); + L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]); + R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]); + L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]); + R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]); + L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]); + R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]); + if (skey->cast5.keylen > 10) { + L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]); + R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]); + L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]); + R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]); + } + STORE32H(R,&ct[0]); + STORE32H(L,&ct[4]); + return CRYPT_OK; +} + + +#ifdef LTC_CLEAN_STACK +int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_cast5_ecb_encrypt(pt,ct,skey); + burn_stack(sizeof(ulong32)*3); + return err; +} +#endif + +/** + Decrypts a block of text with LTC_CAST5 + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled +*/ +#ifdef LTC_CLEAN_STACK +static int s_cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 R, L; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(R,&ct[0]); + LOAD32H(L,&ct[4]); + if (skey->cast5.keylen > 10) { + R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]); + L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]); + R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]); + L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]); + } + R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]); + L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]); + R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]); + L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]); + R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]); + L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]); + R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]); + L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]); + R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]); + L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]); + R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]); + L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]); + STORE32H(L,&pt[0]); + STORE32H(R,&pt[4]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_cast5_ecb_decrypt(ct,pt,skey); + burn_stack(sizeof(ulong32)*3); + return err; +} +#endif + +/** + Performs a self-test of the LTC_CAST5 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int cast5_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[16]; + unsigned char pt[8]; + unsigned char ct[8]; + } tests[] = { + { 16, + {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, + {0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2} + }, + { 10, + {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, + {0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B}, + }, + { 5, + {0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, + {0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E} + } + }; + int i, y, err; + symmetric_key key; + unsigned char tmp[2][8]; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + if ((err = cast5_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + cast5_ecb_encrypt(tests[i].pt, tmp[0], &key); + cast5_ecb_decrypt(tmp[0], tmp[1], &key); + if ((compare_testvector(tmp[0], 8, tests[i].ct, 8, "CAST5 Encrypt", i) != 0) || + (compare_testvector(tmp[1], 8, tests[i].pt, 8, "CAST5 Decrypt", i) != 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[0][y] = 0; + for (y = 0; y < 1000; y++) cast5_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) cast5_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + + } + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void cast5_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 cast5_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 5) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 16) { + *keysize = 16; + } + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/des.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/des.c new file mode 100644 index 0000000..5d00720 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/des.c @@ -0,0 +1,2093 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file des.c + 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, NULL, NULL +}; + +const struct ltc_cipher_descriptor des3_desc = +{ + "3des", + 14, + 16, 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, 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 s_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) +{ + s_deskey(key, edf, keyout); + burn_stack(sizeof(int)*5 + sizeof(ulong32)*32 + sizeof(unsigned char)*112); +} +#endif + +#ifdef LTC_CLEAN_STACK +static void s_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) +{ + s_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 s_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][LTC_BYTE(leftt, 0)] ^ + des_ip[1][LTC_BYTE(leftt, 1)] ^ + des_ip[2][LTC_BYTE(leftt, 2)] ^ + des_ip[3][LTC_BYTE(leftt, 3)] ^ + des_ip[4][LTC_BYTE(right, 0)] ^ + des_ip[5][LTC_BYTE(right, 1)] ^ + des_ip[6][LTC_BYTE(right, 2)] ^ + des_ip[7][LTC_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][LTC_BYTE(leftt, 0)] ^ + des_fp[1][LTC_BYTE(leftt, 1)] ^ + des_fp[2][LTC_BYTE(leftt, 2)] ^ + des_fp[3][LTC_BYTE(leftt, 3)] ^ + des_fp[4][LTC_BYTE(right, 0)] ^ + des_fp[5][LTC_BYTE(right, 1)] ^ + des_fp[6][LTC_BYTE(right, 2)] ^ + des_fp[7][LTC_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) +{ + s_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 && keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + deskey(key, EN0, skey->des3.ek[0]); + deskey(key+8, DE1, skey->des3.ek[1]); + if (keylen == 24) { + deskey(key+16, EN0, skey->des3.ek[2]); + } else { + /* two-key 3DES: K3=K1 */ + deskey(key, EN0, skey->des3.ek[2]); + } + + deskey(key, DE1, skey->des3.dk[2]); + deskey(key+8, EN0, skey->des3.dk[1]); + if (keylen == 24) { + deskey(key+16, DE1, skey->des3.dk[0]); + } else { + /* two-key 3DES: K3=K1 */ + deskey(key, 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, const 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, const 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, const 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, const 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 + static const struct des_test_case { + unsigned char key[8], txt[8], out[8]; + } cases[] = { + { { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA }, + { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 }, + { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF }, + { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A }, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + + { { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D } }, + { { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 } }, + { { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 } }, + { { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 } }, + { { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 } }, + { { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC } }, + { { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 } }, + { { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 } }, + { { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 } }, + { { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 } }, + { { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 } }, + { { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 } }, + { { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 } }, + { { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D } }, + { { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 } }, + { { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 } }, + { { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 } }, + { { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 } }, + { { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 } }, + { { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 } }, + { { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 } }, + { { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 } }, + { { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F } }, + { { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA } }, + { { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F } }, + { { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED } }, + { { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE } }, + { { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B } }, + { { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC } }, + { { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 } }, + + /*** 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 + ***/ + }; + unsigned char key[8], pt[8], ct[8], tmp[8]; + symmetric_key skey; + int i, err; + + for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) + { + if ((err = des_setup(cases[i].key, 8, 0, &skey)) != CRYPT_OK) { + return err; + } + + des_ecb_encrypt(cases[i].txt, ct, &skey); + + if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "DES Encrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + des_ecb_decrypt(ct, pt, &skey); + + if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "DES Decrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ + + for (i = 0; i < 8; i++) key[i] = i; + + if ((err = des_setup(key, 8, 0, &skey)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; + for (i = 0; i < 1000; i++) des_ecb_encrypt(tmp, tmp, &skey); + for (i = 0; i < 1000; i++) des_ecb_decrypt(tmp, tmp, &skey); + + if (compare_testvector(tmp, 8, pt, 8, "DES", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +int des3_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct des3_test_case { + unsigned char key[16], txt[8], out[8]; + } cases[] = { + /* + https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/des/Triple-Des-2-Key-128-64.unverified.test-vectors + */ + { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFA, 0xFD, 0x50, 0x84, 0x37, 0x4F, 0xCE, 0x34 } }, + { { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x60, 0xCC, 0x37, 0xB7, 0xB5, 0x37, 0xA1, 0xDC } }, + { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xBE, 0x3E, 0x73, 0x04, 0xFE, 0x92, 0xC2, 0xBC } }, + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, + { 0xE5, 0xA9, 0xE3, 0x80, 0x03, 0xA5, 0xA0, 0xFD }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0xE4, 0xFC, 0x19, 0xD6, 0x94, 0x63, 0xB7, 0x83 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 } }, + }; + unsigned char key[24], pt[8], ct[8], tmp[8]; + symmetric_key skey; + int i, err; + + if ((err = des_test()) != CRYPT_OK) { + return err; + } + + for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) + { + if ((err = des3_setup(cases[i].key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + + des3_ecb_encrypt(cases[i].txt, ct, &skey); + + if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "3DES Encrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + des3_ecb_decrypt(ct, pt, &skey); + + if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "3DES Decrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ + + for (i = 0; i < 24; i++) key[i] = i; + + if ((err = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; + for (i = 0; i < 1000; i++) des3_ecb_encrypt(tmp, tmp, &skey); + for (i = 0; i < 1000; i++) des3_ecb_decrypt(tmp, tmp, &skey); + + if (compare_testvector(tmp, 8, pt, 8, "3DES", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void des_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** Terminate the context + @param skey The scheduled key +*/ +void des3_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + return CRYPT_OK; + } + *keysize = 24; + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/idea.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/idea.c new file mode 100644 index 0000000..b195a4c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/idea.c @@ -0,0 +1,250 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Based on idea.cpp - originally written and placed in the public domain by Wei Dai + https://github.com/weidai11/cryptopp/blob/master/idea.cpp + + Patents should be expired. On 2017-10-16 wikipedia says: + https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm + + A patent application for IDEA was first filed in Switzerland (CH A 1690/90) on May 18, 1990, + then an international patent application was filed under the Patent Cooperation Treaty on + May 16, 1991. Patents were eventually granted in Austria, France, Germany, Italy, the Netherlands, + Spain, Sweden, Switzerland, the United Kingdom, (European Patent Register entry for European + patent no. 0482154, filed May 16, 1991, issued June 22, 1994 and expired May 16, 2011), + the United States (U.S. Patent 5,214,703, issued May 25, 1993 and expired January 7, 2012) + and Japan (JP 3225440) (expired May 16, 2011). + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_IDEA + +const struct ltc_cipher_descriptor idea_desc = { + "idea", + 24, /* cipher_ID */ + 16, 16, 8, 8, /* min_key_len, max_key_len, block_len, default_rounds */ + &idea_setup, + &idea_ecb_encrypt, + &idea_ecb_decrypt, + &idea_test, + &idea_done, + &idea_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +typedef unsigned short int ushort16; + +#define LOW16(x) ((x)&0xffff) /* compiler should be able to optimize this away if x is 16 bits */ +#define HIGH16(x) ((x)>>16) +#define MUL(a,b) { \ + ulong32 p = (ulong32)LOW16(a) * b; \ + if (p) { \ + p = LOW16(p) - HIGH16(p); \ + a = (ushort16)p - (ushort16)HIGH16(p); \ + } \ + else \ + a = 1 - a - b; \ + } +#define STORE16(x,y) { (y)[0] = (unsigned char)(((x)>>8)&255); (y)[1] = (unsigned char)((x)&255); } +#define LOAD16(x,y) { x = ((ushort16)((y)[0] & 255)<<8) | ((ushort16)((y)[1] & 255)); } + +static ushort16 s_mul_inv(ushort16 x) +{ + ushort16 y = x; + unsigned i; + + for (i = 0; i < 15; i++) { + MUL(y, LOW16(y)); + MUL(y, x); + } + return LOW16(y); +} + +static ushort16 s_add_inv(ushort16 x) +{ + return LOW16(0 - x); +} + +static int s_setup_key(const unsigned char *key, symmetric_key *skey) +{ + int i, j; + ushort16 *e_key = skey->idea.ek; + ushort16 *d_key = skey->idea.dk; + + /* prepare enc key */ + for (i = 0; i < 8; i++) { + LOAD16(e_key[i], key + 2 * i); + } + for (; i < LTC_IDEA_KEYLEN; i++) { + j = (i - i % 8) - 8; + e_key[i] = LOW16((e_key[j+(i+1)%8] << 9) | (e_key[j+(i+2)%8] >> 7)); + } + + /* prepare dec key */ + for (i = 0; i < LTC_IDEA_ROUNDS; i++) { + d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); + d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1+(i>0 ? 1 : 0)]); + d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2-(i>0 ? 1 : 0)]); + d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); + d_key[i*6+4] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+4]; + d_key[i*6+5] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+5]; + } + d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); + d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1]); + d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2]); + d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); + + return CRYPT_OK; +} + +static int s_process_block(const unsigned char *in, unsigned char *out, const ushort16 *m_key) +{ + int i; + ushort16 x0, x1, x2, x3, t0, t1; + + LOAD16(x0, in + 0); + LOAD16(x1, in + 2); + LOAD16(x2, in + 4); + LOAD16(x3, in + 6); + + for (i = 0; i < LTC_IDEA_ROUNDS; i++) { + MUL(x0, m_key[i*6+0]); + x1 += m_key[i*6+1]; + x2 += m_key[i*6+2]; + MUL(x3, m_key[i*6+3]); + t0 = x0^x2; + MUL(t0, m_key[i*6+4]); + t1 = t0 + (x1^x3); + MUL(t1, m_key[i*6+5]); + t0 += t1; + x0 ^= t1; + x3 ^= t0; + t0 ^= x1; + x1 = x2^t1; + x2 = t0; + } + + MUL(x0, m_key[LTC_IDEA_ROUNDS*6+0]); + x2 += m_key[LTC_IDEA_ROUNDS*6+1]; + x1 += m_key[LTC_IDEA_ROUNDS*6+2]; + MUL(x3, m_key[LTC_IDEA_ROUNDS*6+3]); + + STORE16(x0, out + 0); + STORE16(x2, out + 2); + STORE16(x1, out + 4); + STORE16(x3, out + 6); + + return CRYPT_OK; +} + +int idea_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 != 8) return CRYPT_INVALID_ROUNDS; + if (keylen != 16) return CRYPT_INVALID_KEYSIZE; + + return s_setup_key(key, skey); +} + +int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_process_block(pt, ct, skey->idea.ek); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ushort16) * 6 + sizeof(int)); +#endif + return err; +} + +int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_process_block(ct, pt, skey->idea.dk); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ushort16) * 6 + sizeof(int)); +#endif + return err; +} + +void idea_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int idea_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + +int idea_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + { + /* key */ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0xB1, 0xF5, 0xF7, 0xF8, 0x79, 0x01, 0x37, 0x0F } + }, + { + /* key */ { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0xB3, 0x92, 0x7D, 0xFF, 0xB6, 0x35, 0x86, 0x26 } + }, + { + /* key */ { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0xE9, 0x87, 0xE0, 0x02, 0x9F, 0xB9, 0x97, 0x85 } + }, + { + /* key */ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0x75, 0x4A, 0x03, 0xCE, 0x08, 0xDB, 0x7D, 0xAA } + }, + { + /* key */ { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0xF0, 0x15, 0xF9, 0xFB, 0x0C, 0xFC, 0x7E, 0x1C } + }, + }; + + unsigned char buf[2][8]; + symmetric_key key; + int err, x; + + if (sizeof(ushort16) != 2) { + return CRYPT_FAIL_TESTVECTOR; + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = idea_setup(tests[x].key, 16, 8, &key)) != CRYPT_OK) { + return err; + } + if ((err = idea_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[0], 8, tests[x].ct, 8, "IDEA Encrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = idea_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[1], 8, tests[x].pt, 8, "IDEA Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/kasumi.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/kasumi.c new file mode 100644 index 0000000..1ade9d6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/kasumi.c @@ -0,0 +1,307 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file kasumi.c + Implementation of the 3GPP Kasumi block cipher + Derived from the 3GPP standard source code +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_KASUMI + +typedef unsigned u16; + +#define ROL16(x, y) ((((x)<<(y)) | ((x)>>(16-(y)))) & 0xFFFF) + +const struct ltc_cipher_descriptor kasumi_desc = { + "kasumi", + 21, + 16, 16, 8, 8, + &kasumi_setup, + &kasumi_ecb_encrypt, + &kasumi_ecb_decrypt, + &kasumi_test, + &kasumi_done, + &kasumi_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static u16 FI( u16 in, u16 subkey ) +{ + u16 nine, seven; + static const u16 S7[128] = { + 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18,123, 33, + 55,113, 39,114, 21, 67, 65, 12, 47, 73, 46, 27, 25,111,124, 81, + 53, 9,121, 79, 52, 60, 58, 48,101,127, 40,120,104, 70, 71, 43, + 20,122, 72, 61, 23,109, 13,100, 77, 1, 16, 7, 82, 10,105, 98, + 117,116, 76, 11, 89,106, 0,125,118, 99, 86, 69, 30, 57,126, 87, + 112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66, + 102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29,115, 44, + 64,107,108, 24,110, 83, 36, 78, 42, 19, 15, 41, 88,119, 59, 3 }; + static const u16 S9[512] = { + 167,239,161,379,391,334, 9,338, 38,226, 48,358,452,385, 90,397, + 183,253,147,331,415,340, 51,362,306,500,262, 82,216,159,356,177, + 175,241,489, 37,206, 17, 0,333, 44,254,378, 58,143,220, 81,400, + 95, 3,315,245, 54,235,218,405,472,264,172,494,371,290,399, 76, + 165,197,395,121,257,480,423,212,240, 28,462,176,406,507,288,223, + 501,407,249,265, 89,186,221,428,164, 74,440,196,458,421,350,163, + 232,158,134,354, 13,250,491,142,191, 69,193,425,152,227,366,135, + 344,300,276,242,437,320,113,278, 11,243, 87,317, 36, 93,496, 27, + 487,446,482, 41, 68,156,457,131,326,403,339, 20, 39,115,442,124, + 475,384,508, 53,112,170,479,151,126,169, 73,268,279,321,168,364, + 363,292, 46,499,393,327,324, 24,456,267,157,460,488,426,309,229, + 439,506,208,271,349,401,434,236, 16,209,359, 52, 56,120,199,277, + 465,416,252,287,246, 6, 83,305,420,345,153,502, 65, 61,244,282, + 173,222,418, 67,386,368,261,101,476,291,195,430, 49, 79,166,330, + 280,383,373,128,382,408,155,495,367,388,274,107,459,417, 62,454, + 132,225,203,316,234, 14,301, 91,503,286,424,211,347,307,140,374, + 35,103,125,427, 19,214,453,146,498,314,444,230,256,329,198,285, + 50,116, 78,410, 10,205,510,171,231, 45,139,467, 29, 86,505, 32, + 72, 26,342,150,313,490,431,238,411,325,149,473, 40,119,174,355, + 185,233,389, 71,448,273,372, 55,110,178,322, 12,469,392,369,190, + 1,109,375,137,181, 88, 75,308,260,484, 98,272,370,275,412,111, + 336,318, 4,504,492,259,304, 77,337,435, 21,357,303,332,483, 18, + 47, 85, 25,497,474,289,100,269,296,478,270,106, 31,104,433, 84, + 414,486,394, 96, 99,154,511,148,413,361,409,255,162,215,302,201, + 266,351,343,144,441,365,108,298,251, 34,182,509,138,210,335,133, + 311,352,328,141,396,346,123,319,450,281,429,228,443,481, 92,404, + 485,422,248,297, 23,213,130,466, 22,217,283, 70,294,360,419,127, + 312,377, 7,468,194, 2,117,295,463,258,224,447,247,187, 80,398, + 284,353,105,390,299,471,470,184, 57,200,348, 63,204,188, 33,451, + 97, 30,310,219, 94,160,129,493, 64,179,263,102,189,207,114,402, + 438,477,387,122,192, 42,381, 5,145,118,180,449,293,323,136,380, + 43, 66, 60,455,341,445,202,432, 8,237, 15,376,436,464, 59,461}; + + /* The sixteen bit input is split into two unequal halves, * + * nine bits and seven bits - as is the subkey */ + + nine = (u16)(in>>7)&0x1FF; + seven = (u16)(in&0x7F); + + /* Now run the various operations */ + nine = (u16)(S9[nine] ^ seven); + seven = (u16)(S7[seven] ^ (nine & 0x7F)); + seven ^= (subkey>>9); + nine ^= (subkey&0x1FF); + nine = (u16)(S9[nine] ^ seven); + seven = (u16)(S7[seven] ^ (nine & 0x7F)); + return (u16)(seven<<9) + nine; +} + +static ulong32 FO( ulong32 in, int round_no, const symmetric_key *key) +{ + u16 left, right; + + /* Split the input into two 16-bit words */ + left = (u16)(in>>16); + right = (u16) in&0xFFFF; + + /* Now apply the same basic transformation three times */ + left ^= key->kasumi.KOi1[round_no]; + left = FI( left, key->kasumi.KIi1[round_no] ); + left ^= right; + + right ^= key->kasumi.KOi2[round_no]; + right = FI( right, key->kasumi.KIi2[round_no] ); + right ^= left; + + left ^= key->kasumi.KOi3[round_no]; + left = FI( left, key->kasumi.KIi3[round_no] ); + left ^= right; + + return (((ulong32)right)<<16)+left; +} + +static ulong32 FL( ulong32 in, int round_no, const symmetric_key *key ) +{ + u16 l, r, a, b; + /* split out the left and right halves */ + l = (u16)(in>>16); + r = (u16)(in)&0xFFFF; + /* do the FL() operations */ + a = (u16) (l & key->kasumi.KLi1[round_no]); + r ^= ROL16(a,1); + b = (u16)(r | key->kasumi.KLi2[round_no]); + l ^= ROL16(b,1); + /* put the two halves back together */ + + return (((ulong32)l)<<16) + r; +} + +int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 left, right, temp; + int n; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(left, pt); + LOAD32H(right, pt+4); + + for (n = 0; n <= 7; ) { + temp = FL(left, n, skey); + temp = FO(temp, n++, skey); + right ^= temp; + temp = FO(right, n, skey); + temp = FL(temp, n++, skey); + left ^= temp; + } + + STORE32H(left, ct); + STORE32H(right, ct+4); + + return CRYPT_OK; +} + +int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 left, right, temp; + int n; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(left, ct); + LOAD32H(right, ct+4); + + for (n = 7; n >= 0; ) { + temp = FO(right, n, skey); + temp = FL(temp, n--, skey); + left ^= temp; + temp = FL(left, n, skey); + temp = FO(temp, n--, skey); + right ^= temp; + } + + STORE32H(left, pt); + STORE32H(right, pt+4); + + return CRYPT_OK; +} + +int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + static const u16 C[8] = { 0x0123,0x4567,0x89AB,0xCDEF, 0xFEDC,0xBA98,0x7654,0x3210 }; + u16 ukey[8], Kprime[8]; + int n; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != 8) { + return CRYPT_INVALID_ROUNDS; + } + + /* Start by ensuring the subkeys are endian correct on a 16-bit basis */ + for (n = 0; n < 8; n++ ) { + ukey[n] = (((u16)key[2*n]) << 8) | key[2*n+1]; + } + + /* Now build the K'[] keys */ + for (n = 0; n < 8; n++) { + Kprime[n] = ukey[n] ^ C[n]; + } + + /* Finally construct the various sub keys */ + for(n = 0; n < 8; n++) { + skey->kasumi.KLi1[n] = ROL16(ukey[n],1); + skey->kasumi.KLi2[n] = Kprime[(n+2)&0x7]; + skey->kasumi.KOi1[n] = ROL16(ukey[(n+1)&0x7],5); + skey->kasumi.KOi2[n] = ROL16(ukey[(n+5)&0x7],8); + skey->kasumi.KOi3[n] = ROL16(ukey[(n+6)&0x7],13); + skey->kasumi.KIi1[n] = Kprime[(n+4)&0x7]; + skey->kasumi.KIi2[n] = Kprime[(n+3)&0x7]; + skey->kasumi.KIi3[n] = Kprime[(n+7)&0x7]; + } + + return CRYPT_OK; +} + +void kasumi_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int kasumi_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 16) { + *keysize = 16; + return CRYPT_OK; + } + return CRYPT_INVALID_KEYSIZE; +} + +int kasumi_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + +{ + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4B, 0x58, 0xA7, 0x71, 0xAF, 0xC7, 0xE5, 0xE8 } +}, + +{ + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7E, 0xEF, 0x11, 0x3C, 0x95, 0xBB, 0x5A, 0x77 } +}, + +{ + { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x5F, 0x14, 0x06, 0x86, 0xD7, 0xAD, 0x5A, 0x39 }, +}, + +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2E, 0x14, 0x91, 0xCF, 0x70, 0xAA, 0x46, 0x5D } +}, + +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB5, 0x45, 0x86, 0xF4, 0xAB, 0x9A, 0xE5, 0x46 } +}, + +}; + unsigned char buf[2][8]; + symmetric_key key; + int err, x; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = kasumi_setup(tests[x].key, 16, 0, &key)) != CRYPT_OK) { + return err; + } + if ((err = kasumi_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { + return err; + } + if ((err = kasumi_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[1], 8, tests[x].pt, 8, "Kasumi Decrypt", x) || + compare_testvector(buf[0], 8, tests[x].ct, 8, "Kasumi Encrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/khazad.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/khazad.c new file mode 100644 index 0000000..72cbda8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/khazad.c @@ -0,0 +1,840 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file khazad.c + Khazad implementation derived from public domain source + Authors: Paulo S.L.M. Barreto and Vincent Rijmen. +*/ + +#ifdef LTC_KHAZAD + +const struct ltc_cipher_descriptor khazad_desc = { + "khazad", + 18, + 16, 16, 8, 8, + &khazad_setup, + &khazad_ecb_encrypt, + &khazad_ecb_decrypt, + &khazad_test, + &khazad_done, + &khazad_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#define R 8 + +static const ulong64 T0[256] = { + CONST64(0xbad3d268bbb96a01), CONST64(0x54fc4d19e59a66b1), CONST64(0x2f71bc93e26514cd), CONST64(0x749ccdb925871b51), + CONST64(0x53f55102f7a257a4), CONST64(0xd3686bb8d0d6be03), CONST64(0xd26b6fbdd6deb504), CONST64(0x4dd72964b35285fe), + CONST64(0x50f05d0dfdba4aad), CONST64(0xace98a26cf09e063), CONST64(0x8d8a0e83091c9684), CONST64(0xbfdcc679a5914d1a), + CONST64(0x7090ddad3da7374d), CONST64(0x52f65507f1aa5ca3), CONST64(0x9ab352c87ba417e1), CONST64(0x4cd42d61b55a8ef9), + CONST64(0xea238f65460320ac), CONST64(0xd56273a6c4e68411), CONST64(0x97a466f155cc68c2), CONST64(0xd16e63b2dcc6a80d), + CONST64(0x3355ccffaa85d099), CONST64(0x51f35908fbb241aa), CONST64(0x5bed712ac7e20f9c), CONST64(0xa6f7a204f359ae55), + CONST64(0xde7f5f81febec120), CONST64(0x48d83d75ad7aa2e5), CONST64(0xa8e59a32d729cc7f), CONST64(0x99b65ec771bc0ae8), + CONST64(0xdb704b90e096e63b), CONST64(0x3256c8faac8ddb9e), CONST64(0xb7c4e65195d11522), CONST64(0xfc19d72b32b3aace), + CONST64(0xe338ab48704b7393), CONST64(0x9ebf42dc63843bfd), CONST64(0x91ae7eef41fc52d0), CONST64(0x9bb056cd7dac1ce6), + CONST64(0xe23baf4d76437894), CONST64(0xbbd0d66dbdb16106), CONST64(0x41c319589b32f1da), CONST64(0x6eb2a5cb7957e517), + CONST64(0xa5f2ae0bf941b35c), CONST64(0xcb400bc08016564b), CONST64(0x6bbdb1da677fc20c), CONST64(0x95a26efb59dc7ecc), + CONST64(0xa1febe1fe1619f40), CONST64(0xf308eb1810cbc3e3), CONST64(0xb1cefe4f81e12f30), CONST64(0x0206080a0c10160e), + CONST64(0xcc4917db922e675e), CONST64(0xc45137f3a26e3f66), CONST64(0x1d2774694ee8cf53), CONST64(0x143c504478a09c6c), + CONST64(0xc3582be8b0560e73), CONST64(0x63a591f2573f9a34), CONST64(0xda734f95e69eed3c), CONST64(0x5de76934d3d2358e), + CONST64(0x5fe1613edfc22380), CONST64(0xdc79578bf2aed72e), CONST64(0x7d87e99413cf486e), CONST64(0xcd4a13de94266c59), + CONST64(0x7f81e19e1fdf5e60), CONST64(0x5aee752fc1ea049b), CONST64(0x6cb4adc17547f319), CONST64(0x5ce46d31d5da3e89), + CONST64(0xf704fb0c08ebefff), CONST64(0x266a98bed42d47f2), CONST64(0xff1cdb2438abb7c7), CONST64(0xed2a937e543b11b9), + CONST64(0xe825876f4a1336a2), CONST64(0x9dba4ed3699c26f4), CONST64(0x6fb1a1ce7f5fee10), CONST64(0x8e8f028c03048b8d), + CONST64(0x192b647d56c8e34f), CONST64(0xa0fdba1ae7699447), CONST64(0xf00de7171ad3deea), CONST64(0x89861e97113cba98), + CONST64(0x0f113c332278692d), CONST64(0x07091c1b12383115), CONST64(0xafec8629c511fd6a), CONST64(0xfb10cb30208b9bdb), + CONST64(0x0818202830405838), CONST64(0x153f54417ea8976b), CONST64(0x0d1734392e687f23), CONST64(0x040c101418202c1c), + CONST64(0x0103040506080b07), CONST64(0x64ac8de94507ab21), CONST64(0xdf7c5b84f8b6ca27), CONST64(0x769ac5b329970d5f), + CONST64(0x798bf9800bef6472), CONST64(0xdd7a538ef4a6dc29), CONST64(0x3d47f4c98ef5b2b3), CONST64(0x163a584e74b08a62), + CONST64(0x3f41fcc382e5a4bd), CONST64(0x3759dcebb2a5fc85), CONST64(0x6db7a9c4734ff81e), CONST64(0x3848e0d890dd95a8), + CONST64(0xb9d6de67b1a17708), CONST64(0x7395d1a237bf2a44), CONST64(0xe926836a4c1b3da5), CONST64(0x355fd4e1beb5ea8b), + CONST64(0x55ff491ce3926db6), CONST64(0x7193d9a83baf3c4a), CONST64(0x7b8df18a07ff727c), CONST64(0x8c890a860f149d83), + CONST64(0x7296d5a731b72143), CONST64(0x88851a921734b19f), CONST64(0xf607ff090ee3e4f8), CONST64(0x2a7ea882fc4d33d6), + CONST64(0x3e42f8c684edafba), CONST64(0x5ee2653bd9ca2887), CONST64(0x27699cbbd2254cf5), CONST64(0x46ca0543890ac0cf), + CONST64(0x0c14303c28607424), CONST64(0x65af89ec430fa026), CONST64(0x68b8bdd56d67df05), CONST64(0x61a399f85b2f8c3a), + CONST64(0x03050c0f0a181d09), CONST64(0xc15e23e2bc46187d), CONST64(0x57f94116ef827bb8), CONST64(0xd6677fa9cefe9918), + CONST64(0xd976439aec86f035), CONST64(0x58e87d25cdfa1295), CONST64(0xd875479fea8efb32), CONST64(0x66aa85e34917bd2f), + CONST64(0xd7647bacc8f6921f), CONST64(0x3a4ee8d29ccd83a6), CONST64(0xc84507cf8a0e4b42), CONST64(0x3c44f0cc88fdb9b4), + CONST64(0xfa13cf35268390dc), CONST64(0x96a762f453c463c5), CONST64(0xa7f4a601f551a552), CONST64(0x98b55ac277b401ef), + CONST64(0xec29977b52331abe), CONST64(0xb8d5da62b7a97c0f), CONST64(0xc7543bfca876226f), CONST64(0xaeef822cc319f66d), + CONST64(0x69bbb9d06b6fd402), CONST64(0x4bdd317aa762bfec), CONST64(0xabe0963ddd31d176), CONST64(0xa9e69e37d121c778), + CONST64(0x67a981e64f1fb628), CONST64(0x0a1e28223c504e36), CONST64(0x47c901468f02cbc8), CONST64(0xf20bef1d16c3c8e4), + CONST64(0xb5c2ee5b99c1032c), CONST64(0x226688aacc0d6bee), CONST64(0xe532b356647b4981), CONST64(0xee2f9f715e230cb0), + CONST64(0xbedfc27ca399461d), CONST64(0x2b7dac87fa4538d1), CONST64(0x819e3ebf217ce2a0), CONST64(0x1236485a6c90a67e), + CONST64(0x839836b52d6cf4ae), CONST64(0x1b2d6c775ad8f541), CONST64(0x0e1238362470622a), CONST64(0x23658cafca0560e9), + CONST64(0xf502f30604fbf9f1), CONST64(0x45cf094c8312ddc6), CONST64(0x216384a5c61576e7), CONST64(0xce4f1fd19e3e7150), + CONST64(0x49db3970ab72a9e2), CONST64(0x2c74b09ce87d09c4), CONST64(0xf916c33a2c9b8dd5), CONST64(0xe637bf596e635488), + CONST64(0xb6c7e25493d91e25), CONST64(0x2878a088f05d25d8), CONST64(0x17395c4b72b88165), CONST64(0x829b32b02b64ffa9), + CONST64(0x1a2e68725cd0fe46), CONST64(0x8b80169d1d2cac96), CONST64(0xfe1fdf213ea3bcc0), CONST64(0x8a8312981b24a791), + CONST64(0x091b242d3648533f), CONST64(0xc94603ca8c064045), CONST64(0x879426a1354cd8b2), CONST64(0x4ed2256bb94a98f7), + CONST64(0xe13ea3427c5b659d), CONST64(0x2e72b896e46d1fca), CONST64(0xe431b75362734286), CONST64(0xe03da7477a536e9a), + CONST64(0xeb208b60400b2bab), CONST64(0x90ad7aea47f459d7), CONST64(0xa4f1aa0eff49b85b), CONST64(0x1e22786644f0d25a), + CONST64(0x85922eab395ccebc), CONST64(0x60a09dfd5d27873d), CONST64(0x0000000000000000), CONST64(0x256f94b1de355afb), + CONST64(0xf401f70302f3f2f6), CONST64(0xf10ee3121cdbd5ed), CONST64(0x94a16afe5fd475cb), CONST64(0x0b1d2c273a584531), + CONST64(0xe734bb5c686b5f8f), CONST64(0x759fc9bc238f1056), CONST64(0xef2c9b74582b07b7), CONST64(0x345cd0e4b8bde18c), + CONST64(0x3153c4f5a695c697), CONST64(0xd46177a3c2ee8f16), CONST64(0xd06d67b7dacea30a), CONST64(0x869722a43344d3b5), + CONST64(0x7e82e59b19d75567), CONST64(0xadea8e23c901eb64), CONST64(0xfd1ad32e34bba1c9), CONST64(0x297ba48df6552edf), + CONST64(0x3050c0f0a09dcd90), CONST64(0x3b4decd79ac588a1), CONST64(0x9fbc46d9658c30fa), CONST64(0xf815c73f2a9386d2), + CONST64(0xc6573ff9ae7e2968), CONST64(0x13354c5f6a98ad79), CONST64(0x060a181e14303a12), CONST64(0x050f14111e28271b), + CONST64(0xc55233f6a4663461), CONST64(0x113344556688bb77), CONST64(0x7799c1b62f9f0658), CONST64(0x7c84ed9115c74369), + CONST64(0x7a8ef58f01f7797b), CONST64(0x7888fd850de76f75), CONST64(0x365ad8eeb4adf782), CONST64(0x1c24706c48e0c454), + CONST64(0x394be4dd96d59eaf), CONST64(0x59eb7920cbf21992), CONST64(0x1828607850c0e848), CONST64(0x56fa4513e98a70bf), + CONST64(0xb3c8f6458df1393e), CONST64(0xb0cdfa4a87e92437), CONST64(0x246c90b4d83d51fc), CONST64(0x206080a0c01d7de0), + CONST64(0xb2cbf2408bf93239), CONST64(0x92ab72e04be44fd9), CONST64(0xa3f8b615ed71894e), CONST64(0xc05d27e7ba4e137a), + CONST64(0x44cc0d49851ad6c1), CONST64(0x62a695f751379133), CONST64(0x103040506080b070), CONST64(0xb4c1ea5e9fc9082b), + CONST64(0x84912aae3f54c5bb), CONST64(0x43c511529722e7d4), CONST64(0x93a876e54dec44de), CONST64(0xc25b2fedb65e0574), + CONST64(0x4ade357fa16ab4eb), CONST64(0xbddace73a9815b14), CONST64(0x8f8c0689050c808a), CONST64(0x2d77b499ee7502c3), + CONST64(0xbcd9ca76af895013), CONST64(0x9cb94ad66f942df3), CONST64(0x6abeb5df6177c90b), CONST64(0x40c01d5d9d3afadd), + CONST64(0xcf4c1bd498367a57), CONST64(0xa2fbb210eb798249), CONST64(0x809d3aba2774e9a7), CONST64(0x4fd1216ebf4293f0), + CONST64(0x1f217c6342f8d95d), CONST64(0xca430fc5861e5d4c), CONST64(0xaae39238db39da71), CONST64(0x42c61557912aecd3), +}; + +static const ulong64 T1[256] = { + CONST64(0xd3ba68d2b9bb016a), CONST64(0xfc54194d9ae5b166), CONST64(0x712f93bc65e2cd14), CONST64(0x9c74b9cd8725511b), + CONST64(0xf5530251a2f7a457), CONST64(0x68d3b86bd6d003be), CONST64(0x6bd2bd6fded604b5), CONST64(0xd74d642952b3fe85), + CONST64(0xf0500d5dbafdad4a), CONST64(0xe9ac268a09cf63e0), CONST64(0x8a8d830e1c098496), CONST64(0xdcbf79c691a51a4d), + CONST64(0x9070addda73d4d37), CONST64(0xf6520755aaf1a35c), CONST64(0xb39ac852a47be117), CONST64(0xd44c612d5ab5f98e), + CONST64(0x23ea658f0346ac20), CONST64(0x62d5a673e6c41184), CONST64(0xa497f166cc55c268), CONST64(0x6ed1b263c6dc0da8), + CONST64(0x5533ffcc85aa99d0), CONST64(0xf3510859b2fbaa41), CONST64(0xed5b2a71e2c79c0f), CONST64(0xf7a604a259f355ae), + CONST64(0x7fde815fbefe20c1), CONST64(0xd848753d7aade5a2), CONST64(0xe5a8329a29d77fcc), CONST64(0xb699c75ebc71e80a), + CONST64(0x70db904b96e03be6), CONST64(0x5632fac88dac9edb), CONST64(0xc4b751e6d1952215), CONST64(0x19fc2bd7b332ceaa), + CONST64(0x38e348ab4b709373), CONST64(0xbf9edc428463fd3b), CONST64(0xae91ef7efc41d052), CONST64(0xb09bcd56ac7de61c), + CONST64(0x3be24daf43769478), CONST64(0xd0bb6dd6b1bd0661), CONST64(0xc3415819329bdaf1), CONST64(0xb26ecba5577917e5), + CONST64(0xf2a50bae41f95cb3), CONST64(0x40cbc00b16804b56), CONST64(0xbd6bdab17f670cc2), CONST64(0xa295fb6edc59cc7e), + CONST64(0xfea11fbe61e1409f), CONST64(0x08f318ebcb10e3c3), CONST64(0xceb14ffee181302f), CONST64(0x06020a08100c0e16), + CONST64(0x49ccdb172e925e67), CONST64(0x51c4f3376ea2663f), CONST64(0x271d6974e84e53cf), CONST64(0x3c144450a0786c9c), + CONST64(0x58c3e82b56b0730e), CONST64(0xa563f2913f57349a), CONST64(0x73da954f9ee63ced), CONST64(0xe75d3469d2d38e35), + CONST64(0xe15f3e61c2df8023), CONST64(0x79dc8b57aef22ed7), CONST64(0x877d94e9cf136e48), CONST64(0x4acdde132694596c), + CONST64(0x817f9ee1df1f605e), CONST64(0xee5a2f75eac19b04), CONST64(0xb46cc1ad477519f3), CONST64(0xe45c316ddad5893e), + CONST64(0x04f70cfbeb08ffef), CONST64(0x6a26be982dd4f247), CONST64(0x1cff24dbab38c7b7), CONST64(0x2aed7e933b54b911), + CONST64(0x25e86f87134aa236), CONST64(0xba9dd34e9c69f426), CONST64(0xb16fcea15f7f10ee), CONST64(0x8f8e8c0204038d8b), + CONST64(0x2b197d64c8564fe3), CONST64(0xfda01aba69e74794), CONST64(0x0df017e7d31aeade), CONST64(0x8689971e3c1198ba), + CONST64(0x110f333c78222d69), CONST64(0x09071b1c38121531), CONST64(0xecaf298611c56afd), CONST64(0x10fb30cb8b20db9b), + CONST64(0x1808282040303858), CONST64(0x3f154154a87e6b97), CONST64(0x170d3934682e237f), CONST64(0x0c04141020181c2c), + CONST64(0x030105040806070b), CONST64(0xac64e98d074521ab), CONST64(0x7cdf845bb6f827ca), CONST64(0x9a76b3c597295f0d), + CONST64(0x8b7980f9ef0b7264), CONST64(0x7add8e53a6f429dc), CONST64(0x473dc9f4f58eb3b2), CONST64(0x3a164e58b074628a), + CONST64(0x413fc3fce582bda4), CONST64(0x5937ebdca5b285fc), CONST64(0xb76dc4a94f731ef8), CONST64(0x4838d8e0dd90a895), + CONST64(0xd6b967dea1b10877), CONST64(0x9573a2d1bf37442a), CONST64(0x26e96a831b4ca53d), CONST64(0x5f35e1d4b5be8bea), + CONST64(0xff551c4992e3b66d), CONST64(0x9371a8d9af3b4a3c), CONST64(0x8d7b8af1ff077c72), CONST64(0x898c860a140f839d), + CONST64(0x9672a7d5b7314321), CONST64(0x8588921a34179fb1), CONST64(0x07f609ffe30ef8e4), CONST64(0x7e2a82a84dfcd633), + CONST64(0x423ec6f8ed84baaf), CONST64(0xe25e3b65cad98728), CONST64(0x6927bb9c25d2f54c), CONST64(0xca4643050a89cfc0), + CONST64(0x140c3c3060282474), CONST64(0xaf65ec890f4326a0), CONST64(0xb868d5bd676d05df), CONST64(0xa361f8992f5b3a8c), + CONST64(0x05030f0c180a091d), CONST64(0x5ec1e22346bc7d18), CONST64(0xf957164182efb87b), CONST64(0x67d6a97ffece1899), + CONST64(0x76d99a4386ec35f0), CONST64(0xe858257dfacd9512), CONST64(0x75d89f478eea32fb), CONST64(0xaa66e38517492fbd), + CONST64(0x64d7ac7bf6c81f92), CONST64(0x4e3ad2e8cd9ca683), CONST64(0x45c8cf070e8a424b), CONST64(0x443cccf0fd88b4b9), + CONST64(0x13fa35cf8326dc90), CONST64(0xa796f462c453c563), CONST64(0xf4a701a651f552a5), CONST64(0xb598c25ab477ef01), + CONST64(0x29ec7b973352be1a), CONST64(0xd5b862daa9b70f7c), CONST64(0x54c7fc3b76a86f22), CONST64(0xefae2c8219c36df6), + CONST64(0xbb69d0b96f6b02d4), CONST64(0xdd4b7a3162a7ecbf), CONST64(0xe0ab3d9631dd76d1), CONST64(0xe6a9379e21d178c7), + CONST64(0xa967e6811f4f28b6), CONST64(0x1e0a2228503c364e), CONST64(0xc9474601028fc8cb), CONST64(0x0bf21defc316e4c8), + CONST64(0xc2b55beec1992c03), CONST64(0x6622aa880dccee6b), CONST64(0x32e556b37b648149), CONST64(0x2fee719f235eb00c), + CONST64(0xdfbe7cc299a31d46), CONST64(0x7d2b87ac45fad138), CONST64(0x9e81bf3e7c21a0e2), CONST64(0x36125a48906c7ea6), + CONST64(0x9883b5366c2daef4), CONST64(0x2d1b776cd85a41f5), CONST64(0x120e363870242a62), CONST64(0x6523af8c05cae960), + CONST64(0x02f506f3fb04f1f9), CONST64(0xcf454c091283c6dd), CONST64(0x6321a58415c6e776), CONST64(0x4fced11f3e9e5071), + CONST64(0xdb49703972abe2a9), CONST64(0x742c9cb07de8c409), CONST64(0x16f93ac39b2cd58d), CONST64(0x37e659bf636e8854), + CONST64(0xc7b654e2d993251e), CONST64(0x782888a05df0d825), CONST64(0x39174b5cb8726581), CONST64(0x9b82b032642ba9ff), + CONST64(0x2e1a7268d05c46fe), CONST64(0x808b9d162c1d96ac), CONST64(0x1ffe21dfa33ec0bc), CONST64(0x838a9812241b91a7), + CONST64(0x1b092d2448363f53), CONST64(0x46c9ca03068c4540), CONST64(0x9487a1264c35b2d8), CONST64(0xd24e6b254ab9f798), + CONST64(0x3ee142a35b7c9d65), CONST64(0x722e96b86de4ca1f), CONST64(0x31e453b773628642), CONST64(0x3de047a7537a9a6e), + CONST64(0x20eb608b0b40ab2b), CONST64(0xad90ea7af447d759), CONST64(0xf1a40eaa49ff5bb8), CONST64(0x221e6678f0445ad2), + CONST64(0x9285ab2e5c39bcce), CONST64(0xa060fd9d275d3d87), CONST64(0x0000000000000000), CONST64(0x6f25b19435defb5a), + CONST64(0x01f403f7f302f6f2), CONST64(0x0ef112e3db1cedd5), CONST64(0xa194fe6ad45fcb75), CONST64(0x1d0b272c583a3145), + CONST64(0x34e75cbb6b688f5f), CONST64(0x9f75bcc98f235610), CONST64(0x2cef749b2b58b707), CONST64(0x5c34e4d0bdb88ce1), + CONST64(0x5331f5c495a697c6), CONST64(0x61d4a377eec2168f), CONST64(0x6dd0b767ceda0aa3), CONST64(0x9786a4224433b5d3), + CONST64(0x827e9be5d7196755), CONST64(0xeaad238e01c964eb), CONST64(0x1afd2ed3bb34c9a1), CONST64(0x7b298da455f6df2e), + CONST64(0x5030f0c09da090cd), CONST64(0x4d3bd7ecc59aa188), CONST64(0xbc9fd9468c65fa30), CONST64(0x15f83fc7932ad286), + CONST64(0x57c6f93f7eae6829), CONST64(0x35135f4c986a79ad), CONST64(0x0a061e183014123a), CONST64(0x0f051114281e1b27), + CONST64(0x52c5f63366a46134), CONST64(0x33115544886677bb), CONST64(0x9977b6c19f2f5806), CONST64(0x847c91edc7156943), + CONST64(0x8e7a8ff5f7017b79), CONST64(0x887885fde70d756f), CONST64(0x5a36eed8adb482f7), CONST64(0x241c6c70e04854c4), + CONST64(0x4b39dde4d596af9e), CONST64(0xeb592079f2cb9219), CONST64(0x28187860c05048e8), CONST64(0xfa5613458ae9bf70), + CONST64(0xc8b345f6f18d3e39), CONST64(0xcdb04afae9873724), CONST64(0x6c24b4903dd8fc51), CONST64(0x6020a0801dc0e07d), + CONST64(0xcbb240f2f98b3932), CONST64(0xab92e072e44bd94f), CONST64(0xf8a315b671ed4e89), CONST64(0x5dc0e7274eba7a13), + CONST64(0xcc44490d1a85c1d6), CONST64(0xa662f79537513391), CONST64(0x30105040806070b0), CONST64(0xc1b45eeac99f2b08), + CONST64(0x9184ae2a543fbbc5), CONST64(0xc54352112297d4e7), CONST64(0xa893e576ec4dde44), CONST64(0x5bc2ed2f5eb67405), + CONST64(0xde4a7f356aa1ebb4), CONST64(0xdabd73ce81a9145b), CONST64(0x8c8f89060c058a80), CONST64(0x772d99b475eec302), + CONST64(0xd9bc76ca89af1350), CONST64(0xb99cd64a946ff32d), CONST64(0xbe6adfb577610bc9), CONST64(0xc0405d1d3a9dddfa), + CONST64(0x4ccfd41b3698577a), CONST64(0xfba210b279eb4982), CONST64(0x9d80ba3a7427a7e9), CONST64(0xd14f6e2142bff093), + CONST64(0x211f637cf8425dd9), CONST64(0x43cac50f1e864c5d), CONST64(0xe3aa389239db71da), CONST64(0xc64257152a91d3ec), +}; + +static const ulong64 T2[256] = { + CONST64(0xd268bad36a01bbb9), CONST64(0x4d1954fc66b1e59a), CONST64(0xbc932f7114cde265), CONST64(0xcdb9749c1b512587), + CONST64(0x510253f557a4f7a2), CONST64(0x6bb8d368be03d0d6), CONST64(0x6fbdd26bb504d6de), CONST64(0x29644dd785feb352), + CONST64(0x5d0d50f04aadfdba), CONST64(0x8a26ace9e063cf09), CONST64(0x0e838d8a9684091c), CONST64(0xc679bfdc4d1aa591), + CONST64(0xddad7090374d3da7), CONST64(0x550752f65ca3f1aa), CONST64(0x52c89ab317e17ba4), CONST64(0x2d614cd48ef9b55a), + CONST64(0x8f65ea2320ac4603), CONST64(0x73a6d5628411c4e6), CONST64(0x66f197a468c255cc), CONST64(0x63b2d16ea80ddcc6), + CONST64(0xccff3355d099aa85), CONST64(0x590851f341aafbb2), CONST64(0x712a5bed0f9cc7e2), CONST64(0xa204a6f7ae55f359), + CONST64(0x5f81de7fc120febe), CONST64(0x3d7548d8a2e5ad7a), CONST64(0x9a32a8e5cc7fd729), CONST64(0x5ec799b60ae871bc), + CONST64(0x4b90db70e63be096), CONST64(0xc8fa3256db9eac8d), CONST64(0xe651b7c4152295d1), CONST64(0xd72bfc19aace32b3), + CONST64(0xab48e3387393704b), CONST64(0x42dc9ebf3bfd6384), CONST64(0x7eef91ae52d041fc), CONST64(0x56cd9bb01ce67dac), + CONST64(0xaf4de23b78947643), CONST64(0xd66dbbd06106bdb1), CONST64(0x195841c3f1da9b32), CONST64(0xa5cb6eb2e5177957), + CONST64(0xae0ba5f2b35cf941), CONST64(0x0bc0cb40564b8016), CONST64(0xb1da6bbdc20c677f), CONST64(0x6efb95a27ecc59dc), + CONST64(0xbe1fa1fe9f40e161), CONST64(0xeb18f308c3e310cb), CONST64(0xfe4fb1ce2f3081e1), CONST64(0x080a0206160e0c10), + CONST64(0x17dbcc49675e922e), CONST64(0x37f3c4513f66a26e), CONST64(0x74691d27cf534ee8), CONST64(0x5044143c9c6c78a0), + CONST64(0x2be8c3580e73b056), CONST64(0x91f263a59a34573f), CONST64(0x4f95da73ed3ce69e), CONST64(0x69345de7358ed3d2), + CONST64(0x613e5fe12380dfc2), CONST64(0x578bdc79d72ef2ae), CONST64(0xe9947d87486e13cf), CONST64(0x13decd4a6c599426), + CONST64(0xe19e7f815e601fdf), CONST64(0x752f5aee049bc1ea), CONST64(0xadc16cb4f3197547), CONST64(0x6d315ce43e89d5da), + CONST64(0xfb0cf704efff08eb), CONST64(0x98be266a47f2d42d), CONST64(0xdb24ff1cb7c738ab), CONST64(0x937eed2a11b9543b), + CONST64(0x876fe82536a24a13), CONST64(0x4ed39dba26f4699c), CONST64(0xa1ce6fb1ee107f5f), CONST64(0x028c8e8f8b8d0304), + CONST64(0x647d192be34f56c8), CONST64(0xba1aa0fd9447e769), CONST64(0xe717f00ddeea1ad3), CONST64(0x1e978986ba98113c), + CONST64(0x3c330f11692d2278), CONST64(0x1c1b070931151238), CONST64(0x8629afecfd6ac511), CONST64(0xcb30fb109bdb208b), + CONST64(0x2028081858383040), CONST64(0x5441153f976b7ea8), CONST64(0x34390d177f232e68), CONST64(0x1014040c2c1c1820), + CONST64(0x040501030b070608), CONST64(0x8de964acab214507), CONST64(0x5b84df7cca27f8b6), CONST64(0xc5b3769a0d5f2997), + CONST64(0xf980798b64720bef), CONST64(0x538edd7adc29f4a6), CONST64(0xf4c93d47b2b38ef5), CONST64(0x584e163a8a6274b0), + CONST64(0xfcc33f41a4bd82e5), CONST64(0xdceb3759fc85b2a5), CONST64(0xa9c46db7f81e734f), CONST64(0xe0d8384895a890dd), + CONST64(0xde67b9d67708b1a1), CONST64(0xd1a273952a4437bf), CONST64(0x836ae9263da54c1b), CONST64(0xd4e1355fea8bbeb5), + CONST64(0x491c55ff6db6e392), CONST64(0xd9a871933c4a3baf), CONST64(0xf18a7b8d727c07ff), CONST64(0x0a868c899d830f14), + CONST64(0xd5a77296214331b7), CONST64(0x1a928885b19f1734), CONST64(0xff09f607e4f80ee3), CONST64(0xa8822a7e33d6fc4d), + CONST64(0xf8c63e42afba84ed), CONST64(0x653b5ee22887d9ca), CONST64(0x9cbb27694cf5d225), CONST64(0x054346cac0cf890a), + CONST64(0x303c0c1474242860), CONST64(0x89ec65afa026430f), CONST64(0xbdd568b8df056d67), CONST64(0x99f861a38c3a5b2f), + CONST64(0x0c0f03051d090a18), CONST64(0x23e2c15e187dbc46), CONST64(0x411657f97bb8ef82), CONST64(0x7fa9d6679918cefe), + CONST64(0x439ad976f035ec86), CONST64(0x7d2558e81295cdfa), CONST64(0x479fd875fb32ea8e), CONST64(0x85e366aabd2f4917), + CONST64(0x7bacd764921fc8f6), CONST64(0xe8d23a4e83a69ccd), CONST64(0x07cfc8454b428a0e), CONST64(0xf0cc3c44b9b488fd), + CONST64(0xcf35fa1390dc2683), CONST64(0x62f496a763c553c4), CONST64(0xa601a7f4a552f551), CONST64(0x5ac298b501ef77b4), + CONST64(0x977bec291abe5233), CONST64(0xda62b8d57c0fb7a9), CONST64(0x3bfcc754226fa876), CONST64(0x822caeeff66dc319), + CONST64(0xb9d069bbd4026b6f), CONST64(0x317a4bddbfeca762), CONST64(0x963dabe0d176dd31), CONST64(0x9e37a9e6c778d121), + CONST64(0x81e667a9b6284f1f), CONST64(0x28220a1e4e363c50), CONST64(0x014647c9cbc88f02), CONST64(0xef1df20bc8e416c3), + CONST64(0xee5bb5c2032c99c1), CONST64(0x88aa22666beecc0d), CONST64(0xb356e5324981647b), CONST64(0x9f71ee2f0cb05e23), + CONST64(0xc27cbedf461da399), CONST64(0xac872b7d38d1fa45), CONST64(0x3ebf819ee2a0217c), CONST64(0x485a1236a67e6c90), + CONST64(0x36b58398f4ae2d6c), CONST64(0x6c771b2df5415ad8), CONST64(0x38360e12622a2470), CONST64(0x8caf236560e9ca05), + CONST64(0xf306f502f9f104fb), CONST64(0x094c45cfddc68312), CONST64(0x84a5216376e7c615), CONST64(0x1fd1ce4f71509e3e), + CONST64(0x397049dba9e2ab72), CONST64(0xb09c2c7409c4e87d), CONST64(0xc33af9168dd52c9b), CONST64(0xbf59e63754886e63), + CONST64(0xe254b6c71e2593d9), CONST64(0xa088287825d8f05d), CONST64(0x5c4b1739816572b8), CONST64(0x32b0829bffa92b64), + CONST64(0x68721a2efe465cd0), CONST64(0x169d8b80ac961d2c), CONST64(0xdf21fe1fbcc03ea3), CONST64(0x12988a83a7911b24), + CONST64(0x242d091b533f3648), CONST64(0x03cac94640458c06), CONST64(0x26a18794d8b2354c), CONST64(0x256b4ed298f7b94a), + CONST64(0xa342e13e659d7c5b), CONST64(0xb8962e721fcae46d), CONST64(0xb753e43142866273), CONST64(0xa747e03d6e9a7a53), + CONST64(0x8b60eb202bab400b), CONST64(0x7aea90ad59d747f4), CONST64(0xaa0ea4f1b85bff49), CONST64(0x78661e22d25a44f0), + CONST64(0x2eab8592cebc395c), CONST64(0x9dfd60a0873d5d27), CONST64(0x0000000000000000), CONST64(0x94b1256f5afbde35), + CONST64(0xf703f401f2f602f3), CONST64(0xe312f10ed5ed1cdb), CONST64(0x6afe94a175cb5fd4), CONST64(0x2c270b1d45313a58), + CONST64(0xbb5ce7345f8f686b), CONST64(0xc9bc759f1056238f), CONST64(0x9b74ef2c07b7582b), CONST64(0xd0e4345ce18cb8bd), + CONST64(0xc4f53153c697a695), CONST64(0x77a3d4618f16c2ee), CONST64(0x67b7d06da30adace), CONST64(0x22a48697d3b53344), + CONST64(0xe59b7e82556719d7), CONST64(0x8e23adeaeb64c901), CONST64(0xd32efd1aa1c934bb), CONST64(0xa48d297b2edff655), + CONST64(0xc0f03050cd90a09d), CONST64(0xecd73b4d88a19ac5), CONST64(0x46d99fbc30fa658c), CONST64(0xc73ff81586d22a93), + CONST64(0x3ff9c6572968ae7e), CONST64(0x4c5f1335ad796a98), CONST64(0x181e060a3a121430), CONST64(0x1411050f271b1e28), + CONST64(0x33f6c5523461a466), CONST64(0x44551133bb776688), CONST64(0xc1b6779906582f9f), CONST64(0xed917c84436915c7), + CONST64(0xf58f7a8e797b01f7), CONST64(0xfd8578886f750de7), CONST64(0xd8ee365af782b4ad), CONST64(0x706c1c24c45448e0), + CONST64(0xe4dd394b9eaf96d5), CONST64(0x792059eb1992cbf2), CONST64(0x60781828e84850c0), CONST64(0x451356fa70bfe98a), + CONST64(0xf645b3c8393e8df1), CONST64(0xfa4ab0cd243787e9), CONST64(0x90b4246c51fcd83d), CONST64(0x80a020607de0c01d), + CONST64(0xf240b2cb32398bf9), CONST64(0x72e092ab4fd94be4), CONST64(0xb615a3f8894eed71), CONST64(0x27e7c05d137aba4e), + CONST64(0x0d4944ccd6c1851a), CONST64(0x95f762a691335137), CONST64(0x40501030b0706080), CONST64(0xea5eb4c1082b9fc9), + CONST64(0x2aae8491c5bb3f54), CONST64(0x115243c5e7d49722), CONST64(0x76e593a844de4dec), CONST64(0x2fedc25b0574b65e), + CONST64(0x357f4adeb4eba16a), CONST64(0xce73bdda5b14a981), CONST64(0x06898f8c808a050c), CONST64(0xb4992d7702c3ee75), + CONST64(0xca76bcd95013af89), CONST64(0x4ad69cb92df36f94), CONST64(0xb5df6abec90b6177), CONST64(0x1d5d40c0fadd9d3a), + CONST64(0x1bd4cf4c7a579836), CONST64(0xb210a2fb8249eb79), CONST64(0x3aba809de9a72774), CONST64(0x216e4fd193f0bf42), + CONST64(0x7c631f21d95d42f8), CONST64(0x0fc5ca435d4c861e), CONST64(0x9238aae3da71db39), CONST64(0x155742c6ecd3912a), +}; + +static const ulong64 T3[256] = { + CONST64(0x68d2d3ba016ab9bb), CONST64(0x194dfc54b1669ae5), CONST64(0x93bc712fcd1465e2), CONST64(0xb9cd9c74511b8725), + CONST64(0x0251f553a457a2f7), CONST64(0xb86b68d303bed6d0), CONST64(0xbd6f6bd204b5ded6), CONST64(0x6429d74dfe8552b3), + CONST64(0x0d5df050ad4abafd), CONST64(0x268ae9ac63e009cf), CONST64(0x830e8a8d84961c09), CONST64(0x79c6dcbf1a4d91a5), + CONST64(0xaddd90704d37a73d), CONST64(0x0755f652a35caaf1), CONST64(0xc852b39ae117a47b), CONST64(0x612dd44cf98e5ab5), + CONST64(0x658f23eaac200346), CONST64(0xa67362d51184e6c4), CONST64(0xf166a497c268cc55), CONST64(0xb2636ed10da8c6dc), + CONST64(0xffcc553399d085aa), CONST64(0x0859f351aa41b2fb), CONST64(0x2a71ed5b9c0fe2c7), CONST64(0x04a2f7a655ae59f3), + CONST64(0x815f7fde20c1befe), CONST64(0x753dd848e5a27aad), CONST64(0x329ae5a87fcc29d7), CONST64(0xc75eb699e80abc71), + CONST64(0x904b70db3be696e0), CONST64(0xfac856329edb8dac), CONST64(0x51e6c4b72215d195), CONST64(0x2bd719fcceaab332), + CONST64(0x48ab38e393734b70), CONST64(0xdc42bf9efd3b8463), CONST64(0xef7eae91d052fc41), CONST64(0xcd56b09be61cac7d), + CONST64(0x4daf3be294784376), CONST64(0x6dd6d0bb0661b1bd), CONST64(0x5819c341daf1329b), CONST64(0xcba5b26e17e55779), + CONST64(0x0baef2a55cb341f9), CONST64(0xc00b40cb4b561680), CONST64(0xdab1bd6b0cc27f67), CONST64(0xfb6ea295cc7edc59), + CONST64(0x1fbefea1409f61e1), CONST64(0x18eb08f3e3c3cb10), CONST64(0x4ffeceb1302fe181), CONST64(0x0a0806020e16100c), + CONST64(0xdb1749cc5e672e92), CONST64(0xf33751c4663f6ea2), CONST64(0x6974271d53cfe84e), CONST64(0x44503c146c9ca078), + CONST64(0xe82b58c3730e56b0), CONST64(0xf291a563349a3f57), CONST64(0x954f73da3ced9ee6), CONST64(0x3469e75d8e35d2d3), + CONST64(0x3e61e15f8023c2df), CONST64(0x8b5779dc2ed7aef2), CONST64(0x94e9877d6e48cf13), CONST64(0xde134acd596c2694), + CONST64(0x9ee1817f605edf1f), CONST64(0x2f75ee5a9b04eac1), CONST64(0xc1adb46c19f34775), CONST64(0x316de45c893edad5), + CONST64(0x0cfb04f7ffefeb08), CONST64(0xbe986a26f2472dd4), CONST64(0x24db1cffc7b7ab38), CONST64(0x7e932aedb9113b54), + CONST64(0x6f8725e8a236134a), CONST64(0xd34eba9df4269c69), CONST64(0xcea1b16f10ee5f7f), CONST64(0x8c028f8e8d8b0403), + CONST64(0x7d642b194fe3c856), CONST64(0x1abafda0479469e7), CONST64(0x17e70df0eaded31a), CONST64(0x971e868998ba3c11), + CONST64(0x333c110f2d697822), CONST64(0x1b1c090715313812), CONST64(0x2986ecaf6afd11c5), CONST64(0x30cb10fbdb9b8b20), + CONST64(0x2820180838584030), CONST64(0x41543f156b97a87e), CONST64(0x3934170d237f682e), CONST64(0x14100c041c2c2018), + CONST64(0x05040301070b0806), CONST64(0xe98dac6421ab0745), CONST64(0x845b7cdf27cab6f8), CONST64(0xb3c59a765f0d9729), + CONST64(0x80f98b797264ef0b), CONST64(0x8e537add29dca6f4), CONST64(0xc9f4473db3b2f58e), CONST64(0x4e583a16628ab074), + CONST64(0xc3fc413fbda4e582), CONST64(0xebdc593785fca5b2), CONST64(0xc4a9b76d1ef84f73), CONST64(0xd8e04838a895dd90), + CONST64(0x67ded6b90877a1b1), CONST64(0xa2d19573442abf37), CONST64(0x6a8326e9a53d1b4c), CONST64(0xe1d45f358beab5be), + CONST64(0x1c49ff55b66d92e3), CONST64(0xa8d993714a3caf3b), CONST64(0x8af18d7b7c72ff07), CONST64(0x860a898c839d140f), + CONST64(0xa7d596724321b731), CONST64(0x921a85889fb13417), CONST64(0x09ff07f6f8e4e30e), CONST64(0x82a87e2ad6334dfc), + CONST64(0xc6f8423ebaafed84), CONST64(0x3b65e25e8728cad9), CONST64(0xbb9c6927f54c25d2), CONST64(0x4305ca46cfc00a89), + CONST64(0x3c30140c24746028), CONST64(0xec89af6526a00f43), CONST64(0xd5bdb86805df676d), CONST64(0xf899a3613a8c2f5b), + CONST64(0x0f0c0503091d180a), CONST64(0xe2235ec17d1846bc), CONST64(0x1641f957b87b82ef), CONST64(0xa97f67d61899fece), + CONST64(0x9a4376d935f086ec), CONST64(0x257de8589512facd), CONST64(0x9f4775d832fb8eea), CONST64(0xe385aa662fbd1749), + CONST64(0xac7b64d71f92f6c8), CONST64(0xd2e84e3aa683cd9c), CONST64(0xcf0745c8424b0e8a), CONST64(0xccf0443cb4b9fd88), + CONST64(0x35cf13fadc908326), CONST64(0xf462a796c563c453), CONST64(0x01a6f4a752a551f5), CONST64(0xc25ab598ef01b477), + CONST64(0x7b9729ecbe1a3352), CONST64(0x62dad5b80f7ca9b7), CONST64(0xfc3b54c76f2276a8), CONST64(0x2c82efae6df619c3), + CONST64(0xd0b9bb6902d46f6b), CONST64(0x7a31dd4becbf62a7), CONST64(0x3d96e0ab76d131dd), CONST64(0x379ee6a978c721d1), + CONST64(0xe681a96728b61f4f), CONST64(0x22281e0a364e503c), CONST64(0x4601c947c8cb028f), CONST64(0x1def0bf2e4c8c316), + CONST64(0x5beec2b52c03c199), CONST64(0xaa886622ee6b0dcc), CONST64(0x56b332e581497b64), CONST64(0x719f2feeb00c235e), + CONST64(0x7cc2dfbe1d4699a3), CONST64(0x87ac7d2bd13845fa), CONST64(0xbf3e9e81a0e27c21), CONST64(0x5a4836127ea6906c), + CONST64(0xb5369883aef46c2d), CONST64(0x776c2d1b41f5d85a), CONST64(0x3638120e2a627024), CONST64(0xaf8c6523e96005ca), + CONST64(0x06f302f5f1f9fb04), CONST64(0x4c09cf45c6dd1283), CONST64(0xa5846321e77615c6), CONST64(0xd11f4fce50713e9e), + CONST64(0x7039db49e2a972ab), CONST64(0x9cb0742cc4097de8), CONST64(0x3ac316f9d58d9b2c), CONST64(0x59bf37e68854636e), + CONST64(0x54e2c7b6251ed993), CONST64(0x88a07828d8255df0), CONST64(0x4b5c39176581b872), CONST64(0xb0329b82a9ff642b), + CONST64(0x72682e1a46fed05c), CONST64(0x9d16808b96ac2c1d), CONST64(0x21df1ffec0bca33e), CONST64(0x9812838a91a7241b), + CONST64(0x2d241b093f534836), CONST64(0xca0346c94540068c), CONST64(0xa1269487b2d84c35), CONST64(0x6b25d24ef7984ab9), + CONST64(0x42a33ee19d655b7c), CONST64(0x96b8722eca1f6de4), CONST64(0x53b731e486427362), CONST64(0x47a73de09a6e537a), + CONST64(0x608b20ebab2b0b40), CONST64(0xea7aad90d759f447), CONST64(0x0eaaf1a45bb849ff), CONST64(0x6678221e5ad2f044), + CONST64(0xab2e9285bcce5c39), CONST64(0xfd9da0603d87275d), CONST64(0x0000000000000000), CONST64(0xb1946f25fb5a35de), + CONST64(0x03f701f4f6f2f302), CONST64(0x12e30ef1edd5db1c), CONST64(0xfe6aa194cb75d45f), CONST64(0x272c1d0b3145583a), + CONST64(0x5cbb34e78f5f6b68), CONST64(0xbcc99f7556108f23), CONST64(0x749b2cefb7072b58), CONST64(0xe4d05c348ce1bdb8), + CONST64(0xf5c4533197c695a6), CONST64(0xa37761d4168feec2), CONST64(0xb7676dd00aa3ceda), CONST64(0xa4229786b5d34433), + CONST64(0x9be5827e6755d719), CONST64(0x238eeaad64eb01c9), CONST64(0x2ed31afdc9a1bb34), CONST64(0x8da47b29df2e55f6), + CONST64(0xf0c0503090cd9da0), CONST64(0xd7ec4d3ba188c59a), CONST64(0xd946bc9ffa308c65), CONST64(0x3fc715f8d286932a), + CONST64(0xf93f57c668297eae), CONST64(0x5f4c351379ad986a), CONST64(0x1e180a06123a3014), CONST64(0x11140f051b27281e), + CONST64(0xf63352c5613466a4), CONST64(0x5544331177bb8866), CONST64(0xb6c1997758069f2f), CONST64(0x91ed847c6943c715), + CONST64(0x8ff58e7a7b79f701), CONST64(0x85fd8878756fe70d), CONST64(0xeed85a3682f7adb4), CONST64(0x6c70241c54c4e048), + CONST64(0xdde44b39af9ed596), CONST64(0x2079eb599219f2cb), CONST64(0x7860281848e8c050), CONST64(0x1345fa56bf708ae9), + CONST64(0x45f6c8b33e39f18d), CONST64(0x4afacdb03724e987), CONST64(0xb4906c24fc513dd8), CONST64(0xa0806020e07d1dc0), + CONST64(0x40f2cbb23932f98b), CONST64(0xe072ab92d94fe44b), CONST64(0x15b6f8a34e8971ed), CONST64(0xe7275dc07a134eba), + CONST64(0x490dcc44c1d61a85), CONST64(0xf795a66233913751), CONST64(0x5040301070b08060), CONST64(0x5eeac1b42b08c99f), + CONST64(0xae2a9184bbc5543f), CONST64(0x5211c543d4e72297), CONST64(0xe576a893de44ec4d), CONST64(0xed2f5bc274055eb6), + CONST64(0x7f35de4aebb46aa1), CONST64(0x73cedabd145b81a9), CONST64(0x89068c8f8a800c05), CONST64(0x99b4772dc30275ee), + CONST64(0x76cad9bc135089af), CONST64(0xd64ab99cf32d946f), CONST64(0xdfb5be6a0bc97761), CONST64(0x5d1dc040ddfa3a9d), + CONST64(0xd41b4ccf577a3698), CONST64(0x10b2fba2498279eb), CONST64(0xba3a9d80a7e97427), CONST64(0x6e21d14ff09342bf), + CONST64(0x637c211f5dd9f842), CONST64(0xc50f43ca4c5d1e86), CONST64(0x3892e3aa71da39db), CONST64(0x5715c642d3ec2a91), +}; + +static const ulong64 T4[256] = { + CONST64(0xbbb96a01bad3d268), CONST64(0xe59a66b154fc4d19), CONST64(0xe26514cd2f71bc93), CONST64(0x25871b51749ccdb9), + CONST64(0xf7a257a453f55102), CONST64(0xd0d6be03d3686bb8), CONST64(0xd6deb504d26b6fbd), CONST64(0xb35285fe4dd72964), + CONST64(0xfdba4aad50f05d0d), CONST64(0xcf09e063ace98a26), CONST64(0x091c96848d8a0e83), CONST64(0xa5914d1abfdcc679), + CONST64(0x3da7374d7090ddad), CONST64(0xf1aa5ca352f65507), CONST64(0x7ba417e19ab352c8), CONST64(0xb55a8ef94cd42d61), + CONST64(0x460320acea238f65), CONST64(0xc4e68411d56273a6), CONST64(0x55cc68c297a466f1), CONST64(0xdcc6a80dd16e63b2), + CONST64(0xaa85d0993355ccff), CONST64(0xfbb241aa51f35908), CONST64(0xc7e20f9c5bed712a), CONST64(0xf359ae55a6f7a204), + CONST64(0xfebec120de7f5f81), CONST64(0xad7aa2e548d83d75), CONST64(0xd729cc7fa8e59a32), CONST64(0x71bc0ae899b65ec7), + CONST64(0xe096e63bdb704b90), CONST64(0xac8ddb9e3256c8fa), CONST64(0x95d11522b7c4e651), CONST64(0x32b3aacefc19d72b), + CONST64(0x704b7393e338ab48), CONST64(0x63843bfd9ebf42dc), CONST64(0x41fc52d091ae7eef), CONST64(0x7dac1ce69bb056cd), + CONST64(0x76437894e23baf4d), CONST64(0xbdb16106bbd0d66d), CONST64(0x9b32f1da41c31958), CONST64(0x7957e5176eb2a5cb), + CONST64(0xf941b35ca5f2ae0b), CONST64(0x8016564bcb400bc0), CONST64(0x677fc20c6bbdb1da), CONST64(0x59dc7ecc95a26efb), + CONST64(0xe1619f40a1febe1f), CONST64(0x10cbc3e3f308eb18), CONST64(0x81e12f30b1cefe4f), CONST64(0x0c10160e0206080a), + CONST64(0x922e675ecc4917db), CONST64(0xa26e3f66c45137f3), CONST64(0x4ee8cf531d277469), CONST64(0x78a09c6c143c5044), + CONST64(0xb0560e73c3582be8), CONST64(0x573f9a3463a591f2), CONST64(0xe69eed3cda734f95), CONST64(0xd3d2358e5de76934), + CONST64(0xdfc223805fe1613e), CONST64(0xf2aed72edc79578b), CONST64(0x13cf486e7d87e994), CONST64(0x94266c59cd4a13de), + CONST64(0x1fdf5e607f81e19e), CONST64(0xc1ea049b5aee752f), CONST64(0x7547f3196cb4adc1), CONST64(0xd5da3e895ce46d31), + CONST64(0x08ebeffff704fb0c), CONST64(0xd42d47f2266a98be), CONST64(0x38abb7c7ff1cdb24), CONST64(0x543b11b9ed2a937e), + CONST64(0x4a1336a2e825876f), CONST64(0x699c26f49dba4ed3), CONST64(0x7f5fee106fb1a1ce), CONST64(0x03048b8d8e8f028c), + CONST64(0x56c8e34f192b647d), CONST64(0xe7699447a0fdba1a), CONST64(0x1ad3deeaf00de717), CONST64(0x113cba9889861e97), + CONST64(0x2278692d0f113c33), CONST64(0x1238311507091c1b), CONST64(0xc511fd6aafec8629), CONST64(0x208b9bdbfb10cb30), + CONST64(0x3040583808182028), CONST64(0x7ea8976b153f5441), CONST64(0x2e687f230d173439), CONST64(0x18202c1c040c1014), + CONST64(0x06080b0701030405), CONST64(0x4507ab2164ac8de9), CONST64(0xf8b6ca27df7c5b84), CONST64(0x29970d5f769ac5b3), + CONST64(0x0bef6472798bf980), CONST64(0xf4a6dc29dd7a538e), CONST64(0x8ef5b2b33d47f4c9), CONST64(0x74b08a62163a584e), + CONST64(0x82e5a4bd3f41fcc3), CONST64(0xb2a5fc853759dceb), CONST64(0x734ff81e6db7a9c4), CONST64(0x90dd95a83848e0d8), + CONST64(0xb1a17708b9d6de67), CONST64(0x37bf2a447395d1a2), CONST64(0x4c1b3da5e926836a), CONST64(0xbeb5ea8b355fd4e1), + CONST64(0xe3926db655ff491c), CONST64(0x3baf3c4a7193d9a8), CONST64(0x07ff727c7b8df18a), CONST64(0x0f149d838c890a86), + CONST64(0x31b721437296d5a7), CONST64(0x1734b19f88851a92), CONST64(0x0ee3e4f8f607ff09), CONST64(0xfc4d33d62a7ea882), + CONST64(0x84edafba3e42f8c6), CONST64(0xd9ca28875ee2653b), CONST64(0xd2254cf527699cbb), CONST64(0x890ac0cf46ca0543), + CONST64(0x286074240c14303c), CONST64(0x430fa02665af89ec), CONST64(0x6d67df0568b8bdd5), CONST64(0x5b2f8c3a61a399f8), + CONST64(0x0a181d0903050c0f), CONST64(0xbc46187dc15e23e2), CONST64(0xef827bb857f94116), CONST64(0xcefe9918d6677fa9), + CONST64(0xec86f035d976439a), CONST64(0xcdfa129558e87d25), CONST64(0xea8efb32d875479f), CONST64(0x4917bd2f66aa85e3), + CONST64(0xc8f6921fd7647bac), CONST64(0x9ccd83a63a4ee8d2), CONST64(0x8a0e4b42c84507cf), CONST64(0x88fdb9b43c44f0cc), + CONST64(0x268390dcfa13cf35), CONST64(0x53c463c596a762f4), CONST64(0xf551a552a7f4a601), CONST64(0x77b401ef98b55ac2), + CONST64(0x52331abeec29977b), CONST64(0xb7a97c0fb8d5da62), CONST64(0xa876226fc7543bfc), CONST64(0xc319f66daeef822c), + CONST64(0x6b6fd40269bbb9d0), CONST64(0xa762bfec4bdd317a), CONST64(0xdd31d176abe0963d), CONST64(0xd121c778a9e69e37), + CONST64(0x4f1fb62867a981e6), CONST64(0x3c504e360a1e2822), CONST64(0x8f02cbc847c90146), CONST64(0x16c3c8e4f20bef1d), + CONST64(0x99c1032cb5c2ee5b), CONST64(0xcc0d6bee226688aa), CONST64(0x647b4981e532b356), CONST64(0x5e230cb0ee2f9f71), + CONST64(0xa399461dbedfc27c), CONST64(0xfa4538d12b7dac87), CONST64(0x217ce2a0819e3ebf), CONST64(0x6c90a67e1236485a), + CONST64(0x2d6cf4ae839836b5), CONST64(0x5ad8f5411b2d6c77), CONST64(0x2470622a0e123836), CONST64(0xca0560e923658caf), + CONST64(0x04fbf9f1f502f306), CONST64(0x8312ddc645cf094c), CONST64(0xc61576e7216384a5), CONST64(0x9e3e7150ce4f1fd1), + CONST64(0xab72a9e249db3970), CONST64(0xe87d09c42c74b09c), CONST64(0x2c9b8dd5f916c33a), CONST64(0x6e635488e637bf59), + CONST64(0x93d91e25b6c7e254), CONST64(0xf05d25d82878a088), CONST64(0x72b8816517395c4b), CONST64(0x2b64ffa9829b32b0), + CONST64(0x5cd0fe461a2e6872), CONST64(0x1d2cac968b80169d), CONST64(0x3ea3bcc0fe1fdf21), CONST64(0x1b24a7918a831298), + CONST64(0x3648533f091b242d), CONST64(0x8c064045c94603ca), CONST64(0x354cd8b2879426a1), CONST64(0xb94a98f74ed2256b), + CONST64(0x7c5b659de13ea342), CONST64(0xe46d1fca2e72b896), CONST64(0x62734286e431b753), CONST64(0x7a536e9ae03da747), + CONST64(0x400b2babeb208b60), CONST64(0x47f459d790ad7aea), CONST64(0xff49b85ba4f1aa0e), CONST64(0x44f0d25a1e227866), + CONST64(0x395ccebc85922eab), CONST64(0x5d27873d60a09dfd), CONST64(0x0000000000000000), CONST64(0xde355afb256f94b1), + CONST64(0x02f3f2f6f401f703), CONST64(0x1cdbd5edf10ee312), CONST64(0x5fd475cb94a16afe), CONST64(0x3a5845310b1d2c27), + CONST64(0x686b5f8fe734bb5c), CONST64(0x238f1056759fc9bc), CONST64(0x582b07b7ef2c9b74), CONST64(0xb8bde18c345cd0e4), + CONST64(0xa695c6973153c4f5), CONST64(0xc2ee8f16d46177a3), CONST64(0xdacea30ad06d67b7), CONST64(0x3344d3b5869722a4), + CONST64(0x19d755677e82e59b), CONST64(0xc901eb64adea8e23), CONST64(0x34bba1c9fd1ad32e), CONST64(0xf6552edf297ba48d), + CONST64(0xa09dcd903050c0f0), CONST64(0x9ac588a13b4decd7), CONST64(0x658c30fa9fbc46d9), CONST64(0x2a9386d2f815c73f), + CONST64(0xae7e2968c6573ff9), CONST64(0x6a98ad7913354c5f), CONST64(0x14303a12060a181e), CONST64(0x1e28271b050f1411), + CONST64(0xa4663461c55233f6), CONST64(0x6688bb7711334455), CONST64(0x2f9f06587799c1b6), CONST64(0x15c743697c84ed91), + CONST64(0x01f7797b7a8ef58f), CONST64(0x0de76f757888fd85), CONST64(0xb4adf782365ad8ee), CONST64(0x48e0c4541c24706c), + CONST64(0x96d59eaf394be4dd), CONST64(0xcbf2199259eb7920), CONST64(0x50c0e84818286078), CONST64(0xe98a70bf56fa4513), + CONST64(0x8df1393eb3c8f645), CONST64(0x87e92437b0cdfa4a), CONST64(0xd83d51fc246c90b4), CONST64(0xc01d7de0206080a0), + CONST64(0x8bf93239b2cbf240), CONST64(0x4be44fd992ab72e0), CONST64(0xed71894ea3f8b615), CONST64(0xba4e137ac05d27e7), + CONST64(0x851ad6c144cc0d49), CONST64(0x5137913362a695f7), CONST64(0x6080b07010304050), CONST64(0x9fc9082bb4c1ea5e), + CONST64(0x3f54c5bb84912aae), CONST64(0x9722e7d443c51152), CONST64(0x4dec44de93a876e5), CONST64(0xb65e0574c25b2fed), + CONST64(0xa16ab4eb4ade357f), CONST64(0xa9815b14bddace73), CONST64(0x050c808a8f8c0689), CONST64(0xee7502c32d77b499), + CONST64(0xaf895013bcd9ca76), CONST64(0x6f942df39cb94ad6), CONST64(0x6177c90b6abeb5df), CONST64(0x9d3afadd40c01d5d), + CONST64(0x98367a57cf4c1bd4), CONST64(0xeb798249a2fbb210), CONST64(0x2774e9a7809d3aba), CONST64(0xbf4293f04fd1216e), + CONST64(0x42f8d95d1f217c63), CONST64(0x861e5d4cca430fc5), CONST64(0xdb39da71aae39238), CONST64(0x912aecd342c61557), +}; + +static const ulong64 T5[256] = { + CONST64(0xb9bb016ad3ba68d2), CONST64(0x9ae5b166fc54194d), CONST64(0x65e2cd14712f93bc), CONST64(0x8725511b9c74b9cd), + CONST64(0xa2f7a457f5530251), CONST64(0xd6d003be68d3b86b), CONST64(0xded604b56bd2bd6f), CONST64(0x52b3fe85d74d6429), + CONST64(0xbafdad4af0500d5d), CONST64(0x09cf63e0e9ac268a), CONST64(0x1c0984968a8d830e), CONST64(0x91a51a4ddcbf79c6), + CONST64(0xa73d4d379070addd), CONST64(0xaaf1a35cf6520755), CONST64(0xa47be117b39ac852), CONST64(0x5ab5f98ed44c612d), + CONST64(0x0346ac2023ea658f), CONST64(0xe6c4118462d5a673), CONST64(0xcc55c268a497f166), CONST64(0xc6dc0da86ed1b263), + CONST64(0x85aa99d05533ffcc), CONST64(0xb2fbaa41f3510859), CONST64(0xe2c79c0fed5b2a71), CONST64(0x59f355aef7a604a2), + CONST64(0xbefe20c17fde815f), CONST64(0x7aade5a2d848753d), CONST64(0x29d77fcce5a8329a), CONST64(0xbc71e80ab699c75e), + CONST64(0x96e03be670db904b), CONST64(0x8dac9edb5632fac8), CONST64(0xd1952215c4b751e6), CONST64(0xb332ceaa19fc2bd7), + CONST64(0x4b70937338e348ab), CONST64(0x8463fd3bbf9edc42), CONST64(0xfc41d052ae91ef7e), CONST64(0xac7de61cb09bcd56), + CONST64(0x437694783be24daf), CONST64(0xb1bd0661d0bb6dd6), CONST64(0x329bdaf1c3415819), CONST64(0x577917e5b26ecba5), + CONST64(0x41f95cb3f2a50bae), CONST64(0x16804b5640cbc00b), CONST64(0x7f670cc2bd6bdab1), CONST64(0xdc59cc7ea295fb6e), + CONST64(0x61e1409ffea11fbe), CONST64(0xcb10e3c308f318eb), CONST64(0xe181302fceb14ffe), CONST64(0x100c0e1606020a08), + CONST64(0x2e925e6749ccdb17), CONST64(0x6ea2663f51c4f337), CONST64(0xe84e53cf271d6974), CONST64(0xa0786c9c3c144450), + CONST64(0x56b0730e58c3e82b), CONST64(0x3f57349aa563f291), CONST64(0x9ee63ced73da954f), CONST64(0xd2d38e35e75d3469), + CONST64(0xc2df8023e15f3e61), CONST64(0xaef22ed779dc8b57), CONST64(0xcf136e48877d94e9), CONST64(0x2694596c4acdde13), + CONST64(0xdf1f605e817f9ee1), CONST64(0xeac19b04ee5a2f75), CONST64(0x477519f3b46cc1ad), CONST64(0xdad5893ee45c316d), + CONST64(0xeb08ffef04f70cfb), CONST64(0x2dd4f2476a26be98), CONST64(0xab38c7b71cff24db), CONST64(0x3b54b9112aed7e93), + CONST64(0x134aa23625e86f87), CONST64(0x9c69f426ba9dd34e), CONST64(0x5f7f10eeb16fcea1), CONST64(0x04038d8b8f8e8c02), + CONST64(0xc8564fe32b197d64), CONST64(0x69e74794fda01aba), CONST64(0xd31aeade0df017e7), CONST64(0x3c1198ba8689971e), + CONST64(0x78222d69110f333c), CONST64(0x3812153109071b1c), CONST64(0x11c56afdecaf2986), CONST64(0x8b20db9b10fb30cb), + CONST64(0x4030385818082820), CONST64(0xa87e6b973f154154), CONST64(0x682e237f170d3934), CONST64(0x20181c2c0c041410), + CONST64(0x0806070b03010504), CONST64(0x074521abac64e98d), CONST64(0xb6f827ca7cdf845b), CONST64(0x97295f0d9a76b3c5), + CONST64(0xef0b72648b7980f9), CONST64(0xa6f429dc7add8e53), CONST64(0xf58eb3b2473dc9f4), CONST64(0xb074628a3a164e58), + CONST64(0xe582bda4413fc3fc), CONST64(0xa5b285fc5937ebdc), CONST64(0x4f731ef8b76dc4a9), CONST64(0xdd90a8954838d8e0), + CONST64(0xa1b10877d6b967de), CONST64(0xbf37442a9573a2d1), CONST64(0x1b4ca53d26e96a83), CONST64(0xb5be8bea5f35e1d4), + CONST64(0x92e3b66dff551c49), CONST64(0xaf3b4a3c9371a8d9), CONST64(0xff077c728d7b8af1), CONST64(0x140f839d898c860a), + CONST64(0xb73143219672a7d5), CONST64(0x34179fb18588921a), CONST64(0xe30ef8e407f609ff), CONST64(0x4dfcd6337e2a82a8), + CONST64(0xed84baaf423ec6f8), CONST64(0xcad98728e25e3b65), CONST64(0x25d2f54c6927bb9c), CONST64(0x0a89cfc0ca464305), + CONST64(0x60282474140c3c30), CONST64(0x0f4326a0af65ec89), CONST64(0x676d05dfb868d5bd), CONST64(0x2f5b3a8ca361f899), + CONST64(0x180a091d05030f0c), CONST64(0x46bc7d185ec1e223), CONST64(0x82efb87bf9571641), CONST64(0xfece189967d6a97f), + CONST64(0x86ec35f076d99a43), CONST64(0xfacd9512e858257d), CONST64(0x8eea32fb75d89f47), CONST64(0x17492fbdaa66e385), + CONST64(0xf6c81f9264d7ac7b), CONST64(0xcd9ca6834e3ad2e8), CONST64(0x0e8a424b45c8cf07), CONST64(0xfd88b4b9443cccf0), + CONST64(0x8326dc9013fa35cf), CONST64(0xc453c563a796f462), CONST64(0x51f552a5f4a701a6), CONST64(0xb477ef01b598c25a), + CONST64(0x3352be1a29ec7b97), CONST64(0xa9b70f7cd5b862da), CONST64(0x76a86f2254c7fc3b), CONST64(0x19c36df6efae2c82), + CONST64(0x6f6b02d4bb69d0b9), CONST64(0x62a7ecbfdd4b7a31), CONST64(0x31dd76d1e0ab3d96), CONST64(0x21d178c7e6a9379e), + CONST64(0x1f4f28b6a967e681), CONST64(0x503c364e1e0a2228), CONST64(0x028fc8cbc9474601), CONST64(0xc316e4c80bf21def), + CONST64(0xc1992c03c2b55bee), CONST64(0x0dccee6b6622aa88), CONST64(0x7b64814932e556b3), CONST64(0x235eb00c2fee719f), + CONST64(0x99a31d46dfbe7cc2), CONST64(0x45fad1387d2b87ac), CONST64(0x7c21a0e29e81bf3e), CONST64(0x906c7ea636125a48), + CONST64(0x6c2daef49883b536), CONST64(0xd85a41f52d1b776c), CONST64(0x70242a62120e3638), CONST64(0x05cae9606523af8c), + CONST64(0xfb04f1f902f506f3), CONST64(0x1283c6ddcf454c09), CONST64(0x15c6e7766321a584), CONST64(0x3e9e50714fced11f), + CONST64(0x72abe2a9db497039), CONST64(0x7de8c409742c9cb0), CONST64(0x9b2cd58d16f93ac3), CONST64(0x636e885437e659bf), + CONST64(0xd993251ec7b654e2), CONST64(0x5df0d825782888a0), CONST64(0xb872658139174b5c), CONST64(0x642ba9ff9b82b032), + CONST64(0xd05c46fe2e1a7268), CONST64(0x2c1d96ac808b9d16), CONST64(0xa33ec0bc1ffe21df), CONST64(0x241b91a7838a9812), + CONST64(0x48363f531b092d24), CONST64(0x068c454046c9ca03), CONST64(0x4c35b2d89487a126), CONST64(0x4ab9f798d24e6b25), + CONST64(0x5b7c9d653ee142a3), CONST64(0x6de4ca1f722e96b8), CONST64(0x7362864231e453b7), CONST64(0x537a9a6e3de047a7), + CONST64(0x0b40ab2b20eb608b), CONST64(0xf447d759ad90ea7a), CONST64(0x49ff5bb8f1a40eaa), CONST64(0xf0445ad2221e6678), + CONST64(0x5c39bcce9285ab2e), CONST64(0x275d3d87a060fd9d), CONST64(0x0000000000000000), CONST64(0x35defb5a6f25b194), + CONST64(0xf302f6f201f403f7), CONST64(0xdb1cedd50ef112e3), CONST64(0xd45fcb75a194fe6a), CONST64(0x583a31451d0b272c), + CONST64(0x6b688f5f34e75cbb), CONST64(0x8f2356109f75bcc9), CONST64(0x2b58b7072cef749b), CONST64(0xbdb88ce15c34e4d0), + CONST64(0x95a697c65331f5c4), CONST64(0xeec2168f61d4a377), CONST64(0xceda0aa36dd0b767), CONST64(0x4433b5d39786a422), + CONST64(0xd7196755827e9be5), CONST64(0x01c964ebeaad238e), CONST64(0xbb34c9a11afd2ed3), CONST64(0x55f6df2e7b298da4), + CONST64(0x9da090cd5030f0c0), CONST64(0xc59aa1884d3bd7ec), CONST64(0x8c65fa30bc9fd946), CONST64(0x932ad28615f83fc7), + CONST64(0x7eae682957c6f93f), CONST64(0x986a79ad35135f4c), CONST64(0x3014123a0a061e18), CONST64(0x281e1b270f051114), + CONST64(0x66a4613452c5f633), CONST64(0x886677bb33115544), CONST64(0x9f2f58069977b6c1), CONST64(0xc7156943847c91ed), + CONST64(0xf7017b798e7a8ff5), CONST64(0xe70d756f887885fd), CONST64(0xadb482f75a36eed8), CONST64(0xe04854c4241c6c70), + CONST64(0xd596af9e4b39dde4), CONST64(0xf2cb9219eb592079), CONST64(0xc05048e828187860), CONST64(0x8ae9bf70fa561345), + CONST64(0xf18d3e39c8b345f6), CONST64(0xe9873724cdb04afa), CONST64(0x3dd8fc516c24b490), CONST64(0x1dc0e07d6020a080), + CONST64(0xf98b3932cbb240f2), CONST64(0xe44bd94fab92e072), CONST64(0x71ed4e89f8a315b6), CONST64(0x4eba7a135dc0e727), + CONST64(0x1a85c1d6cc44490d), CONST64(0x37513391a662f795), CONST64(0x806070b030105040), CONST64(0xc99f2b08c1b45eea), + CONST64(0x543fbbc59184ae2a), CONST64(0x2297d4e7c5435211), CONST64(0xec4dde44a893e576), CONST64(0x5eb674055bc2ed2f), + CONST64(0x6aa1ebb4de4a7f35), CONST64(0x81a9145bdabd73ce), CONST64(0x0c058a808c8f8906), CONST64(0x75eec302772d99b4), + CONST64(0x89af1350d9bc76ca), CONST64(0x946ff32db99cd64a), CONST64(0x77610bc9be6adfb5), CONST64(0x3a9dddfac0405d1d), + CONST64(0x3698577a4ccfd41b), CONST64(0x79eb4982fba210b2), CONST64(0x7427a7e99d80ba3a), CONST64(0x42bff093d14f6e21), + CONST64(0xf8425dd9211f637c), CONST64(0x1e864c5d43cac50f), CONST64(0x39db71dae3aa3892), CONST64(0x2a91d3ecc6425715), +}; + +static const ulong64 T6[256] = { + CONST64(0x6a01bbb9d268bad3), CONST64(0x66b1e59a4d1954fc), CONST64(0x14cde265bc932f71), CONST64(0x1b512587cdb9749c), + CONST64(0x57a4f7a2510253f5), CONST64(0xbe03d0d66bb8d368), CONST64(0xb504d6de6fbdd26b), CONST64(0x85feb35229644dd7), + CONST64(0x4aadfdba5d0d50f0), CONST64(0xe063cf098a26ace9), CONST64(0x9684091c0e838d8a), CONST64(0x4d1aa591c679bfdc), + CONST64(0x374d3da7ddad7090), CONST64(0x5ca3f1aa550752f6), CONST64(0x17e17ba452c89ab3), CONST64(0x8ef9b55a2d614cd4), + CONST64(0x20ac46038f65ea23), CONST64(0x8411c4e673a6d562), CONST64(0x68c255cc66f197a4), CONST64(0xa80ddcc663b2d16e), + CONST64(0xd099aa85ccff3355), CONST64(0x41aafbb2590851f3), CONST64(0x0f9cc7e2712a5bed), CONST64(0xae55f359a204a6f7), + CONST64(0xc120febe5f81de7f), CONST64(0xa2e5ad7a3d7548d8), CONST64(0xcc7fd7299a32a8e5), CONST64(0x0ae871bc5ec799b6), + CONST64(0xe63be0964b90db70), CONST64(0xdb9eac8dc8fa3256), CONST64(0x152295d1e651b7c4), CONST64(0xaace32b3d72bfc19), + CONST64(0x7393704bab48e338), CONST64(0x3bfd638442dc9ebf), CONST64(0x52d041fc7eef91ae), CONST64(0x1ce67dac56cd9bb0), + CONST64(0x78947643af4de23b), CONST64(0x6106bdb1d66dbbd0), CONST64(0xf1da9b32195841c3), CONST64(0xe5177957a5cb6eb2), + CONST64(0xb35cf941ae0ba5f2), CONST64(0x564b80160bc0cb40), CONST64(0xc20c677fb1da6bbd), CONST64(0x7ecc59dc6efb95a2), + CONST64(0x9f40e161be1fa1fe), CONST64(0xc3e310cbeb18f308), CONST64(0x2f3081e1fe4fb1ce), CONST64(0x160e0c10080a0206), + CONST64(0x675e922e17dbcc49), CONST64(0x3f66a26e37f3c451), CONST64(0xcf534ee874691d27), CONST64(0x9c6c78a05044143c), + CONST64(0x0e73b0562be8c358), CONST64(0x9a34573f91f263a5), CONST64(0xed3ce69e4f95da73), CONST64(0x358ed3d269345de7), + CONST64(0x2380dfc2613e5fe1), CONST64(0xd72ef2ae578bdc79), CONST64(0x486e13cfe9947d87), CONST64(0x6c59942613decd4a), + CONST64(0x5e601fdfe19e7f81), CONST64(0x049bc1ea752f5aee), CONST64(0xf3197547adc16cb4), CONST64(0x3e89d5da6d315ce4), + CONST64(0xefff08ebfb0cf704), CONST64(0x47f2d42d98be266a), CONST64(0xb7c738abdb24ff1c), CONST64(0x11b9543b937eed2a), + CONST64(0x36a24a13876fe825), CONST64(0x26f4699c4ed39dba), CONST64(0xee107f5fa1ce6fb1), CONST64(0x8b8d0304028c8e8f), + CONST64(0xe34f56c8647d192b), CONST64(0x9447e769ba1aa0fd), CONST64(0xdeea1ad3e717f00d), CONST64(0xba98113c1e978986), + CONST64(0x692d22783c330f11), CONST64(0x311512381c1b0709), CONST64(0xfd6ac5118629afec), CONST64(0x9bdb208bcb30fb10), + CONST64(0x5838304020280818), CONST64(0x976b7ea85441153f), CONST64(0x7f232e6834390d17), CONST64(0x2c1c18201014040c), + CONST64(0x0b07060804050103), CONST64(0xab2145078de964ac), CONST64(0xca27f8b65b84df7c), CONST64(0x0d5f2997c5b3769a), + CONST64(0x64720beff980798b), CONST64(0xdc29f4a6538edd7a), CONST64(0xb2b38ef5f4c93d47), CONST64(0x8a6274b0584e163a), + CONST64(0xa4bd82e5fcc33f41), CONST64(0xfc85b2a5dceb3759), CONST64(0xf81e734fa9c46db7), CONST64(0x95a890dde0d83848), + CONST64(0x7708b1a1de67b9d6), CONST64(0x2a4437bfd1a27395), CONST64(0x3da54c1b836ae926), CONST64(0xea8bbeb5d4e1355f), + CONST64(0x6db6e392491c55ff), CONST64(0x3c4a3bafd9a87193), CONST64(0x727c07fff18a7b8d), CONST64(0x9d830f140a868c89), + CONST64(0x214331b7d5a77296), CONST64(0xb19f17341a928885), CONST64(0xe4f80ee3ff09f607), CONST64(0x33d6fc4da8822a7e), + CONST64(0xafba84edf8c63e42), CONST64(0x2887d9ca653b5ee2), CONST64(0x4cf5d2259cbb2769), CONST64(0xc0cf890a054346ca), + CONST64(0x74242860303c0c14), CONST64(0xa026430f89ec65af), CONST64(0xdf056d67bdd568b8), CONST64(0x8c3a5b2f99f861a3), + CONST64(0x1d090a180c0f0305), CONST64(0x187dbc4623e2c15e), CONST64(0x7bb8ef82411657f9), CONST64(0x9918cefe7fa9d667), + CONST64(0xf035ec86439ad976), CONST64(0x1295cdfa7d2558e8), CONST64(0xfb32ea8e479fd875), CONST64(0xbd2f491785e366aa), + CONST64(0x921fc8f67bacd764), CONST64(0x83a69ccde8d23a4e), CONST64(0x4b428a0e07cfc845), CONST64(0xb9b488fdf0cc3c44), + CONST64(0x90dc2683cf35fa13), CONST64(0x63c553c462f496a7), CONST64(0xa552f551a601a7f4), CONST64(0x01ef77b45ac298b5), + CONST64(0x1abe5233977bec29), CONST64(0x7c0fb7a9da62b8d5), CONST64(0x226fa8763bfcc754), CONST64(0xf66dc319822caeef), + CONST64(0xd4026b6fb9d069bb), CONST64(0xbfeca762317a4bdd), CONST64(0xd176dd31963dabe0), CONST64(0xc778d1219e37a9e6), + CONST64(0xb6284f1f81e667a9), CONST64(0x4e363c5028220a1e), CONST64(0xcbc88f02014647c9), CONST64(0xc8e416c3ef1df20b), + CONST64(0x032c99c1ee5bb5c2), CONST64(0x6beecc0d88aa2266), CONST64(0x4981647bb356e532), CONST64(0x0cb05e239f71ee2f), + CONST64(0x461da399c27cbedf), CONST64(0x38d1fa45ac872b7d), CONST64(0xe2a0217c3ebf819e), CONST64(0xa67e6c90485a1236), + CONST64(0xf4ae2d6c36b58398), CONST64(0xf5415ad86c771b2d), CONST64(0x622a247038360e12), CONST64(0x60e9ca058caf2365), + CONST64(0xf9f104fbf306f502), CONST64(0xddc68312094c45cf), CONST64(0x76e7c61584a52163), CONST64(0x71509e3e1fd1ce4f), + CONST64(0xa9e2ab72397049db), CONST64(0x09c4e87db09c2c74), CONST64(0x8dd52c9bc33af916), CONST64(0x54886e63bf59e637), + CONST64(0x1e2593d9e254b6c7), CONST64(0x25d8f05da0882878), CONST64(0x816572b85c4b1739), CONST64(0xffa92b6432b0829b), + CONST64(0xfe465cd068721a2e), CONST64(0xac961d2c169d8b80), CONST64(0xbcc03ea3df21fe1f), CONST64(0xa7911b2412988a83), + CONST64(0x533f3648242d091b), CONST64(0x40458c0603cac946), CONST64(0xd8b2354c26a18794), CONST64(0x98f7b94a256b4ed2), + CONST64(0x659d7c5ba342e13e), CONST64(0x1fcae46db8962e72), CONST64(0x42866273b753e431), CONST64(0x6e9a7a53a747e03d), + CONST64(0x2bab400b8b60eb20), CONST64(0x59d747f47aea90ad), CONST64(0xb85bff49aa0ea4f1), CONST64(0xd25a44f078661e22), + CONST64(0xcebc395c2eab8592), CONST64(0x873d5d279dfd60a0), CONST64(0x0000000000000000), CONST64(0x5afbde3594b1256f), + CONST64(0xf2f602f3f703f401), CONST64(0xd5ed1cdbe312f10e), CONST64(0x75cb5fd46afe94a1), CONST64(0x45313a582c270b1d), + CONST64(0x5f8f686bbb5ce734), CONST64(0x1056238fc9bc759f), CONST64(0x07b7582b9b74ef2c), CONST64(0xe18cb8bdd0e4345c), + CONST64(0xc697a695c4f53153), CONST64(0x8f16c2ee77a3d461), CONST64(0xa30adace67b7d06d), CONST64(0xd3b5334422a48697), + CONST64(0x556719d7e59b7e82), CONST64(0xeb64c9018e23adea), CONST64(0xa1c934bbd32efd1a), CONST64(0x2edff655a48d297b), + CONST64(0xcd90a09dc0f03050), CONST64(0x88a19ac5ecd73b4d), CONST64(0x30fa658c46d99fbc), CONST64(0x86d22a93c73ff815), + CONST64(0x2968ae7e3ff9c657), CONST64(0xad796a984c5f1335), CONST64(0x3a121430181e060a), CONST64(0x271b1e281411050f), + CONST64(0x3461a46633f6c552), CONST64(0xbb77668844551133), CONST64(0x06582f9fc1b67799), CONST64(0x436915c7ed917c84), + CONST64(0x797b01f7f58f7a8e), CONST64(0x6f750de7fd857888), CONST64(0xf782b4add8ee365a), CONST64(0xc45448e0706c1c24), + CONST64(0x9eaf96d5e4dd394b), CONST64(0x1992cbf2792059eb), CONST64(0xe84850c060781828), CONST64(0x70bfe98a451356fa), + CONST64(0x393e8df1f645b3c8), CONST64(0x243787e9fa4ab0cd), CONST64(0x51fcd83d90b4246c), CONST64(0x7de0c01d80a02060), + CONST64(0x32398bf9f240b2cb), CONST64(0x4fd94be472e092ab), CONST64(0x894eed71b615a3f8), CONST64(0x137aba4e27e7c05d), + CONST64(0xd6c1851a0d4944cc), CONST64(0x9133513795f762a6), CONST64(0xb070608040501030), CONST64(0x082b9fc9ea5eb4c1), + CONST64(0xc5bb3f542aae8491), CONST64(0xe7d49722115243c5), CONST64(0x44de4dec76e593a8), CONST64(0x0574b65e2fedc25b), + CONST64(0xb4eba16a357f4ade), CONST64(0x5b14a981ce73bdda), CONST64(0x808a050c06898f8c), CONST64(0x02c3ee75b4992d77), + CONST64(0x5013af89ca76bcd9), CONST64(0x2df36f944ad69cb9), CONST64(0xc90b6177b5df6abe), CONST64(0xfadd9d3a1d5d40c0), + CONST64(0x7a5798361bd4cf4c), CONST64(0x8249eb79b210a2fb), CONST64(0xe9a727743aba809d), CONST64(0x93f0bf42216e4fd1), + CONST64(0xd95d42f87c631f21), CONST64(0x5d4c861e0fc5ca43), CONST64(0xda71db399238aae3), CONST64(0xecd3912a155742c6), +}; + +static const ulong64 T7[256] = { + CONST64(0x016ab9bb68d2d3ba), CONST64(0xb1669ae5194dfc54), CONST64(0xcd1465e293bc712f), CONST64(0x511b8725b9cd9c74), + CONST64(0xa457a2f70251f553), CONST64(0x03bed6d0b86b68d3), CONST64(0x04b5ded6bd6f6bd2), CONST64(0xfe8552b36429d74d), + CONST64(0xad4abafd0d5df050), CONST64(0x63e009cf268ae9ac), CONST64(0x84961c09830e8a8d), CONST64(0x1a4d91a579c6dcbf), + CONST64(0x4d37a73daddd9070), CONST64(0xa35caaf10755f652), CONST64(0xe117a47bc852b39a), CONST64(0xf98e5ab5612dd44c), + CONST64(0xac200346658f23ea), CONST64(0x1184e6c4a67362d5), CONST64(0xc268cc55f166a497), CONST64(0x0da8c6dcb2636ed1), + CONST64(0x99d085aaffcc5533), CONST64(0xaa41b2fb0859f351), CONST64(0x9c0fe2c72a71ed5b), CONST64(0x55ae59f304a2f7a6), + CONST64(0x20c1befe815f7fde), CONST64(0xe5a27aad753dd848), CONST64(0x7fcc29d7329ae5a8), CONST64(0xe80abc71c75eb699), + CONST64(0x3be696e0904b70db), CONST64(0x9edb8dacfac85632), CONST64(0x2215d19551e6c4b7), CONST64(0xceaab3322bd719fc), + CONST64(0x93734b7048ab38e3), CONST64(0xfd3b8463dc42bf9e), CONST64(0xd052fc41ef7eae91), CONST64(0xe61cac7dcd56b09b), + CONST64(0x947843764daf3be2), CONST64(0x0661b1bd6dd6d0bb), CONST64(0xdaf1329b5819c341), CONST64(0x17e55779cba5b26e), + CONST64(0x5cb341f90baef2a5), CONST64(0x4b561680c00b40cb), CONST64(0x0cc27f67dab1bd6b), CONST64(0xcc7edc59fb6ea295), + CONST64(0x409f61e11fbefea1), CONST64(0xe3c3cb1018eb08f3), CONST64(0x302fe1814ffeceb1), CONST64(0x0e16100c0a080602), + CONST64(0x5e672e92db1749cc), CONST64(0x663f6ea2f33751c4), CONST64(0x53cfe84e6974271d), CONST64(0x6c9ca07844503c14), + CONST64(0x730e56b0e82b58c3), CONST64(0x349a3f57f291a563), CONST64(0x3ced9ee6954f73da), CONST64(0x8e35d2d33469e75d), + CONST64(0x8023c2df3e61e15f), CONST64(0x2ed7aef28b5779dc), CONST64(0x6e48cf1394e9877d), CONST64(0x596c2694de134acd), + CONST64(0x605edf1f9ee1817f), CONST64(0x9b04eac12f75ee5a), CONST64(0x19f34775c1adb46c), CONST64(0x893edad5316de45c), + CONST64(0xffefeb080cfb04f7), CONST64(0xf2472dd4be986a26), CONST64(0xc7b7ab3824db1cff), CONST64(0xb9113b547e932aed), + CONST64(0xa236134a6f8725e8), CONST64(0xf4269c69d34eba9d), CONST64(0x10ee5f7fcea1b16f), CONST64(0x8d8b04038c028f8e), + CONST64(0x4fe3c8567d642b19), CONST64(0x479469e71abafda0), CONST64(0xeaded31a17e70df0), CONST64(0x98ba3c11971e8689), + CONST64(0x2d697822333c110f), CONST64(0x153138121b1c0907), CONST64(0x6afd11c52986ecaf), CONST64(0xdb9b8b2030cb10fb), + CONST64(0x3858403028201808), CONST64(0x6b97a87e41543f15), CONST64(0x237f682e3934170d), CONST64(0x1c2c201814100c04), + CONST64(0x070b080605040301), CONST64(0x21ab0745e98dac64), CONST64(0x27cab6f8845b7cdf), CONST64(0x5f0d9729b3c59a76), + CONST64(0x7264ef0b80f98b79), CONST64(0x29dca6f48e537add), CONST64(0xb3b2f58ec9f4473d), CONST64(0x628ab0744e583a16), + CONST64(0xbda4e582c3fc413f), CONST64(0x85fca5b2ebdc5937), CONST64(0x1ef84f73c4a9b76d), CONST64(0xa895dd90d8e04838), + CONST64(0x0877a1b167ded6b9), CONST64(0x442abf37a2d19573), CONST64(0xa53d1b4c6a8326e9), CONST64(0x8beab5bee1d45f35), + CONST64(0xb66d92e31c49ff55), CONST64(0x4a3caf3ba8d99371), CONST64(0x7c72ff078af18d7b), CONST64(0x839d140f860a898c), + CONST64(0x4321b731a7d59672), CONST64(0x9fb13417921a8588), CONST64(0xf8e4e30e09ff07f6), CONST64(0xd6334dfc82a87e2a), + CONST64(0xbaafed84c6f8423e), CONST64(0x8728cad93b65e25e), CONST64(0xf54c25d2bb9c6927), CONST64(0xcfc00a894305ca46), + CONST64(0x247460283c30140c), CONST64(0x26a00f43ec89af65), CONST64(0x05df676dd5bdb868), CONST64(0x3a8c2f5bf899a361), + CONST64(0x091d180a0f0c0503), CONST64(0x7d1846bce2235ec1), CONST64(0xb87b82ef1641f957), CONST64(0x1899fecea97f67d6), + CONST64(0x35f086ec9a4376d9), CONST64(0x9512facd257de858), CONST64(0x32fb8eea9f4775d8), CONST64(0x2fbd1749e385aa66), + CONST64(0x1f92f6c8ac7b64d7), CONST64(0xa683cd9cd2e84e3a), CONST64(0x424b0e8acf0745c8), CONST64(0xb4b9fd88ccf0443c), + CONST64(0xdc90832635cf13fa), CONST64(0xc563c453f462a796), CONST64(0x52a551f501a6f4a7), CONST64(0xef01b477c25ab598), + CONST64(0xbe1a33527b9729ec), CONST64(0x0f7ca9b762dad5b8), CONST64(0x6f2276a8fc3b54c7), CONST64(0x6df619c32c82efae), + CONST64(0x02d46f6bd0b9bb69), CONST64(0xecbf62a77a31dd4b), CONST64(0x76d131dd3d96e0ab), CONST64(0x78c721d1379ee6a9), + CONST64(0x28b61f4fe681a967), CONST64(0x364e503c22281e0a), CONST64(0xc8cb028f4601c947), CONST64(0xe4c8c3161def0bf2), + CONST64(0x2c03c1995beec2b5), CONST64(0xee6b0dccaa886622), CONST64(0x81497b6456b332e5), CONST64(0xb00c235e719f2fee), + CONST64(0x1d4699a37cc2dfbe), CONST64(0xd13845fa87ac7d2b), CONST64(0xa0e27c21bf3e9e81), CONST64(0x7ea6906c5a483612), + CONST64(0xaef46c2db5369883), CONST64(0x41f5d85a776c2d1b), CONST64(0x2a6270243638120e), CONST64(0xe96005caaf8c6523), + CONST64(0xf1f9fb0406f302f5), CONST64(0xc6dd12834c09cf45), CONST64(0xe77615c6a5846321), CONST64(0x50713e9ed11f4fce), + CONST64(0xe2a972ab7039db49), CONST64(0xc4097de89cb0742c), CONST64(0xd58d9b2c3ac316f9), CONST64(0x8854636e59bf37e6), + CONST64(0x251ed99354e2c7b6), CONST64(0xd8255df088a07828), CONST64(0x6581b8724b5c3917), CONST64(0xa9ff642bb0329b82), + CONST64(0x46fed05c72682e1a), CONST64(0x96ac2c1d9d16808b), CONST64(0xc0bca33e21df1ffe), CONST64(0x91a7241b9812838a), + CONST64(0x3f5348362d241b09), CONST64(0x4540068cca0346c9), CONST64(0xb2d84c35a1269487), CONST64(0xf7984ab96b25d24e), + CONST64(0x9d655b7c42a33ee1), CONST64(0xca1f6de496b8722e), CONST64(0x8642736253b731e4), CONST64(0x9a6e537a47a73de0), + CONST64(0xab2b0b40608b20eb), CONST64(0xd759f447ea7aad90), CONST64(0x5bb849ff0eaaf1a4), CONST64(0x5ad2f0446678221e), + CONST64(0xbcce5c39ab2e9285), CONST64(0x3d87275dfd9da060), CONST64(0x0000000000000000), CONST64(0xfb5a35deb1946f25), + CONST64(0xf6f2f30203f701f4), CONST64(0xedd5db1c12e30ef1), CONST64(0xcb75d45ffe6aa194), CONST64(0x3145583a272c1d0b), + CONST64(0x8f5f6b685cbb34e7), CONST64(0x56108f23bcc99f75), CONST64(0xb7072b58749b2cef), CONST64(0x8ce1bdb8e4d05c34), + CONST64(0x97c695a6f5c45331), CONST64(0x168feec2a37761d4), CONST64(0x0aa3cedab7676dd0), CONST64(0xb5d34433a4229786), + CONST64(0x6755d7199be5827e), CONST64(0x64eb01c9238eeaad), CONST64(0xc9a1bb342ed31afd), CONST64(0xdf2e55f68da47b29), + CONST64(0x90cd9da0f0c05030), CONST64(0xa188c59ad7ec4d3b), CONST64(0xfa308c65d946bc9f), CONST64(0xd286932a3fc715f8), + CONST64(0x68297eaef93f57c6), CONST64(0x79ad986a5f4c3513), CONST64(0x123a30141e180a06), CONST64(0x1b27281e11140f05), + CONST64(0x613466a4f63352c5), CONST64(0x77bb886655443311), CONST64(0x58069f2fb6c19977), CONST64(0x6943c71591ed847c), + CONST64(0x7b79f7018ff58e7a), CONST64(0x756fe70d85fd8878), CONST64(0x82f7adb4eed85a36), CONST64(0x54c4e0486c70241c), + CONST64(0xaf9ed596dde44b39), CONST64(0x9219f2cb2079eb59), CONST64(0x48e8c05078602818), CONST64(0xbf708ae91345fa56), + CONST64(0x3e39f18d45f6c8b3), CONST64(0x3724e9874afacdb0), CONST64(0xfc513dd8b4906c24), CONST64(0xe07d1dc0a0806020), + CONST64(0x3932f98b40f2cbb2), CONST64(0xd94fe44be072ab92), CONST64(0x4e8971ed15b6f8a3), CONST64(0x7a134ebae7275dc0), + CONST64(0xc1d61a85490dcc44), CONST64(0x33913751f795a662), CONST64(0x70b0806050403010), CONST64(0x2b08c99f5eeac1b4), + CONST64(0xbbc5543fae2a9184), CONST64(0xd4e722975211c543), CONST64(0xde44ec4de576a893), CONST64(0x74055eb6ed2f5bc2), + CONST64(0xebb46aa17f35de4a), CONST64(0x145b81a973cedabd), CONST64(0x8a800c0589068c8f), CONST64(0xc30275ee99b4772d), + CONST64(0x135089af76cad9bc), CONST64(0xf32d946fd64ab99c), CONST64(0x0bc97761dfb5be6a), CONST64(0xddfa3a9d5d1dc040), + CONST64(0x577a3698d41b4ccf), CONST64(0x498279eb10b2fba2), CONST64(0xa7e97427ba3a9d80), CONST64(0xf09342bf6e21d14f), + CONST64(0x5dd9f842637c211f), CONST64(0x4c5d1e86c50f43ca), CONST64(0x71da39db3892e3aa), CONST64(0xd3ec2a915715c642), +}; + +static const ulong64 c[R + 1] = { + CONST64(0xba542f7453d3d24d), + CONST64(0x50ac8dbf70529a4c), + CONST64(0xead597d133515ba6), + CONST64(0xde48a899db32b7fc), + CONST64(0xe39e919be2bb416e), + CONST64(0xa5cb6b95a1f3b102), + CONST64(0xccc41d14c363da5d), + CONST64(0x5fdc7dcd7f5a6c5c), + CONST64(0xf726ffede89d6f8e), +}; + + /** + Initialize the Khazad 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 khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int r; + const ulong64 *S; + ulong64 K2, K1; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (num_rounds != 8 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + /* use 7th table */ + S = T7; + + /* + * map unsigned char array cipher key to initial key state (mu): + */ + K2 = + ((ulong64)key[ 0] << 56) ^ + ((ulong64)key[ 1] << 48) ^ + ((ulong64)key[ 2] << 40) ^ + ((ulong64)key[ 3] << 32) ^ + ((ulong64)key[ 4] << 24) ^ + ((ulong64)key[ 5] << 16) ^ + ((ulong64)key[ 6] << 8) ^ + ((ulong64)key[ 7] ); + K1 = + ((ulong64)key[ 8] << 56) ^ + ((ulong64)key[ 9] << 48) ^ + ((ulong64)key[10] << 40) ^ + ((ulong64)key[11] << 32) ^ + ((ulong64)key[12] << 24) ^ + ((ulong64)key[13] << 16) ^ + ((ulong64)key[14] << 8) ^ + ((ulong64)key[15] ); + + /* + * compute the round keys: + */ + for (r = 0; r <= R; r++) { + /* + * K[r] = rho(c[r], K1) ^ K2; + */ + skey->khazad.roundKeyEnc[r] = + T0[(int)(K1 >> 56) ] ^ + T1[(int)(K1 >> 48) & 0xff] ^ + T2[(int)(K1 >> 40) & 0xff] ^ + T3[(int)(K1 >> 32) & 0xff] ^ + T4[(int)(K1 >> 24) & 0xff] ^ + T5[(int)(K1 >> 16) & 0xff] ^ + T6[(int)(K1 >> 8) & 0xff] ^ + T7[(int)(K1 ) & 0xff] ^ + c[r] ^ K2; + K2 = K1; K1 = skey->khazad.roundKeyEnc[r]; + } + /* + * compute the inverse key schedule: + * K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}) + */ + skey->khazad.roundKeyDec[0] = skey->khazad.roundKeyEnc[R]; + for (r = 1; r < R; r++) { + K1 = skey->khazad.roundKeyEnc[R - r]; + skey->khazad.roundKeyDec[r] = + T0[(int)S[(int)(K1 >> 56) ] & 0xff] ^ + T1[(int)S[(int)(K1 >> 48) & 0xff] & 0xff] ^ + T2[(int)S[(int)(K1 >> 40) & 0xff] & 0xff] ^ + T3[(int)S[(int)(K1 >> 32) & 0xff] & 0xff] ^ + T4[(int)S[(int)(K1 >> 24) & 0xff] & 0xff] ^ + T5[(int)S[(int)(K1 >> 16) & 0xff] & 0xff] ^ + T6[(int)S[(int)(K1 >> 8) & 0xff] & 0xff] ^ + T7[(int)S[(int)(K1 ) & 0xff] & 0xff]; + } + skey->khazad.roundKeyDec[R] = skey->khazad.roundKeyEnc[0]; + + return CRYPT_OK; +} + +static void khazad_crypt(const unsigned char *plaintext, unsigned char *ciphertext, + const ulong64 *roundKey) { + int r; + ulong64 state; + /* + * map plaintext block to cipher state (mu) + * and add initial round key (sigma[K^0]): + */ + state = + ((ulong64)plaintext[0] << 56) ^ + ((ulong64)plaintext[1] << 48) ^ + ((ulong64)plaintext[2] << 40) ^ + ((ulong64)plaintext[3] << 32) ^ + ((ulong64)plaintext[4] << 24) ^ + ((ulong64)plaintext[5] << 16) ^ + ((ulong64)plaintext[6] << 8) ^ + ((ulong64)plaintext[7] ) ^ + roundKey[0]; + + /* + * R - 1 full rounds: + */ + for (r = 1; r < R; r++) { + state = + T0[(int)(state >> 56) ] ^ + T1[(int)(state >> 48) & 0xff] ^ + T2[(int)(state >> 40) & 0xff] ^ + T3[(int)(state >> 32) & 0xff] ^ + T4[(int)(state >> 24) & 0xff] ^ + T5[(int)(state >> 16) & 0xff] ^ + T6[(int)(state >> 8) & 0xff] ^ + T7[(int)(state ) & 0xff] ^ + roundKey[r]; + } + + /* + * last round: + */ + state = + (T0[(int)(state >> 56) ] & CONST64(0xff00000000000000)) ^ + (T1[(int)(state >> 48) & 0xff] & CONST64(0x00ff000000000000)) ^ + (T2[(int)(state >> 40) & 0xff] & CONST64(0x0000ff0000000000)) ^ + (T3[(int)(state >> 32) & 0xff] & CONST64(0x000000ff00000000)) ^ + (T4[(int)(state >> 24) & 0xff] & CONST64(0x00000000ff000000)) ^ + (T5[(int)(state >> 16) & 0xff] & CONST64(0x0000000000ff0000)) ^ + (T6[(int)(state >> 8) & 0xff] & CONST64(0x000000000000ff00)) ^ + (T7[(int)(state ) & 0xff] & CONST64(0x00000000000000ff)) ^ + roundKey[R]; + + /* + * map cipher state to ciphertext block (mu^{-1}): + */ + ciphertext[0] = (unsigned char)(state >> 56); + ciphertext[1] = (unsigned char)(state >> 48); + ciphertext[2] = (unsigned char)(state >> 40); + ciphertext[3] = (unsigned char)(state >> 32); + ciphertext[4] = (unsigned char)(state >> 24); + ciphertext[5] = (unsigned char)(state >> 16); + ciphertext[6] = (unsigned char)(state >> 8); + ciphertext[7] = (unsigned char)(state ); +} + +/** + Encrypts a block of text with Khazad + @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 khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + khazad_crypt(pt, ct, skey->khazad.roundKeyEnc); + return CRYPT_OK; +} + +/** + Decrypts a block of text with Khazad + @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 khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + khazad_crypt(ct, pt, skey->khazad.roundKeyDec); + return CRYPT_OK; +} + +/** + Performs a self-test of the Khazad block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int khazad_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct test { + unsigned char pt[8], ct[8], key[16]; + } tests[] = { +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x49, 0xA4, 0xCE, 0x32, 0xAC, 0x19, 0x0E, 0x3F }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x64, 0x5D, 0x77, 0x3E, 0x40, 0xAB, 0xDD, 0x53 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, { + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9E, 0x39, 0x98, 0x64, 0xF7, 0x8E, 0xCA, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0xA9, 0xDF, 0x3D, 0x2C, 0x64, 0xD3, 0xEA, 0x28 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +} +}; + int x, y; + unsigned char buf[2][8]; + symmetric_key skey; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + khazad_setup(tests[x].key, 16, 0, &skey); + khazad_ecb_encrypt(tests[x].pt, buf[0], &skey); + khazad_ecb_decrypt(buf[0], buf[1], &skey); + if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad Encrypt", x) || + compare_testvector(buf[1], 8, tests[x].pt, 8, "Khazad Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + for (y = 0; y < 1000; y++) khazad_ecb_encrypt(buf[0], buf[0], &skey); + for (y = 0; y < 1000; y++) khazad_ecb_decrypt(buf[0], buf[0], &skey); + if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad 1000", 1000)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void khazad_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 khazad_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 16) { + *keysize = 16; + return CRYPT_OK; + } + return CRYPT_INVALID_KEYSIZE; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/kseed.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/kseed.c new file mode 100644 index 0000000..1e63aec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/kseed.c @@ -0,0 +1,366 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file kseed.c + seed implementation of SEED derived from RFC4269 + Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_KSEED + +const struct ltc_cipher_descriptor kseed_desc = { + "seed", + 20, + 16, 16, 16, 16, + &kseed_setup, + &kseed_ecb_encrypt, + &kseed_ecb_decrypt, + &kseed_test, + &kseed_done, + &kseed_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 SS0[256] = { +0x2989A1A8UL,0x05858184UL,0x16C6D2D4UL,0x13C3D3D0UL,0x14445054UL,0x1D0D111CUL,0x2C8CA0ACUL,0x25052124UL, +0x1D4D515CUL,0x03434340UL,0x18081018UL,0x1E0E121CUL,0x11415150UL,0x3CCCF0FCUL,0x0ACAC2C8UL,0x23436360UL, +0x28082028UL,0x04444044UL,0x20002020UL,0x1D8D919CUL,0x20C0E0E0UL,0x22C2E2E0UL,0x08C8C0C8UL,0x17071314UL, +0x2585A1A4UL,0x0F8F838CUL,0x03030300UL,0x3B4B7378UL,0x3B8BB3B8UL,0x13031310UL,0x12C2D2D0UL,0x2ECEE2ECUL, +0x30407070UL,0x0C8C808CUL,0x3F0F333CUL,0x2888A0A8UL,0x32023230UL,0x1DCDD1DCUL,0x36C6F2F4UL,0x34447074UL, +0x2CCCE0ECUL,0x15859194UL,0x0B0B0308UL,0x17475354UL,0x1C4C505CUL,0x1B4B5358UL,0x3D8DB1BCUL,0x01010100UL, +0x24042024UL,0x1C0C101CUL,0x33437370UL,0x18889098UL,0x10001010UL,0x0CCCC0CCUL,0x32C2F2F0UL,0x19C9D1D8UL, +0x2C0C202CUL,0x27C7E3E4UL,0x32427270UL,0x03838380UL,0x1B8B9398UL,0x11C1D1D0UL,0x06868284UL,0x09C9C1C8UL, +0x20406060UL,0x10405050UL,0x2383A3A0UL,0x2BCBE3E8UL,0x0D0D010CUL,0x3686B2B4UL,0x1E8E929CUL,0x0F4F434CUL, +0x3787B3B4UL,0x1A4A5258UL,0x06C6C2C4UL,0x38487078UL,0x2686A2A4UL,0x12021210UL,0x2F8FA3ACUL,0x15C5D1D4UL, +0x21416160UL,0x03C3C3C0UL,0x3484B0B4UL,0x01414140UL,0x12425250UL,0x3D4D717CUL,0x0D8D818CUL,0x08080008UL, +0x1F0F131CUL,0x19899198UL,0x00000000UL,0x19091118UL,0x04040004UL,0x13435350UL,0x37C7F3F4UL,0x21C1E1E0UL, +0x3DCDF1FCUL,0x36467274UL,0x2F0F232CUL,0x27072324UL,0x3080B0B0UL,0x0B8B8388UL,0x0E0E020CUL,0x2B8BA3A8UL, +0x2282A2A0UL,0x2E4E626CUL,0x13839390UL,0x0D4D414CUL,0x29496168UL,0x3C4C707CUL,0x09090108UL,0x0A0A0208UL, +0x3F8FB3BCUL,0x2FCFE3ECUL,0x33C3F3F0UL,0x05C5C1C4UL,0x07878384UL,0x14041014UL,0x3ECEF2FCUL,0x24446064UL, +0x1ECED2DCUL,0x2E0E222CUL,0x0B4B4348UL,0x1A0A1218UL,0x06060204UL,0x21012120UL,0x2B4B6368UL,0x26466264UL, +0x02020200UL,0x35C5F1F4UL,0x12829290UL,0x0A8A8288UL,0x0C0C000CUL,0x3383B3B0UL,0x3E4E727CUL,0x10C0D0D0UL, +0x3A4A7278UL,0x07474344UL,0x16869294UL,0x25C5E1E4UL,0x26062224UL,0x00808080UL,0x2D8DA1ACUL,0x1FCFD3DCUL, +0x2181A1A0UL,0x30003030UL,0x37073334UL,0x2E8EA2ACUL,0x36063234UL,0x15051114UL,0x22022220UL,0x38083038UL, +0x34C4F0F4UL,0x2787A3A4UL,0x05454144UL,0x0C4C404CUL,0x01818180UL,0x29C9E1E8UL,0x04848084UL,0x17879394UL, +0x35053134UL,0x0BCBC3C8UL,0x0ECEC2CCUL,0x3C0C303CUL,0x31417170UL,0x11011110UL,0x07C7C3C4UL,0x09898188UL, +0x35457174UL,0x3BCBF3F8UL,0x1ACAD2D8UL,0x38C8F0F8UL,0x14849094UL,0x19495158UL,0x02828280UL,0x04C4C0C4UL, +0x3FCFF3FCUL,0x09494148UL,0x39093138UL,0x27476364UL,0x00C0C0C0UL,0x0FCFC3CCUL,0x17C7D3D4UL,0x3888B0B8UL, +0x0F0F030CUL,0x0E8E828CUL,0x02424240UL,0x23032320UL,0x11819190UL,0x2C4C606CUL,0x1BCBD3D8UL,0x2484A0A4UL, +0x34043034UL,0x31C1F1F0UL,0x08484048UL,0x02C2C2C0UL,0x2F4F636CUL,0x3D0D313CUL,0x2D0D212CUL,0x00404040UL, +0x3E8EB2BCUL,0x3E0E323CUL,0x3C8CB0BCUL,0x01C1C1C0UL,0x2A8AA2A8UL,0x3A8AB2B8UL,0x0E4E424CUL,0x15455154UL, +0x3B0B3338UL,0x1CCCD0DCUL,0x28486068UL,0x3F4F737CUL,0x1C8C909CUL,0x18C8D0D8UL,0x0A4A4248UL,0x16465254UL, +0x37477374UL,0x2080A0A0UL,0x2DCDE1ECUL,0x06464244UL,0x3585B1B4UL,0x2B0B2328UL,0x25456164UL,0x3ACAF2F8UL, +0x23C3E3E0UL,0x3989B1B8UL,0x3181B1B0UL,0x1F8F939CUL,0x1E4E525CUL,0x39C9F1F8UL,0x26C6E2E4UL,0x3282B2B0UL, +0x31013130UL,0x2ACAE2E8UL,0x2D4D616CUL,0x1F4F535CUL,0x24C4E0E4UL,0x30C0F0F0UL,0x0DCDC1CCUL,0x08888088UL, +0x16061214UL,0x3A0A3238UL,0x18485058UL,0x14C4D0D4UL,0x22426260UL,0x29092128UL,0x07070304UL,0x33033330UL, +0x28C8E0E8UL,0x1B0B1318UL,0x05050104UL,0x39497178UL,0x10809090UL,0x2A4A6268UL,0x2A0A2228UL,0x1A8A9298UL +}; + +static const ulong32 SS1[256] = { +0x38380830UL,0xE828C8E0UL,0x2C2D0D21UL,0xA42686A2UL,0xCC0FCFC3UL,0xDC1ECED2UL,0xB03383B3UL,0xB83888B0UL, +0xAC2F8FA3UL,0x60204060UL,0x54154551UL,0xC407C7C3UL,0x44044440UL,0x6C2F4F63UL,0x682B4B63UL,0x581B4B53UL, +0xC003C3C3UL,0x60224262UL,0x30330333UL,0xB43585B1UL,0x28290921UL,0xA02080A0UL,0xE022C2E2UL,0xA42787A3UL, +0xD013C3D3UL,0x90118191UL,0x10110111UL,0x04060602UL,0x1C1C0C10UL,0xBC3C8CB0UL,0x34360632UL,0x480B4B43UL, +0xEC2FCFE3UL,0x88088880UL,0x6C2C4C60UL,0xA82888A0UL,0x14170713UL,0xC404C4C0UL,0x14160612UL,0xF434C4F0UL, +0xC002C2C2UL,0x44054541UL,0xE021C1E1UL,0xD416C6D2UL,0x3C3F0F33UL,0x3C3D0D31UL,0x8C0E8E82UL,0x98188890UL, +0x28280820UL,0x4C0E4E42UL,0xF436C6F2UL,0x3C3E0E32UL,0xA42585A1UL,0xF839C9F1UL,0x0C0D0D01UL,0xDC1FCFD3UL, +0xD818C8D0UL,0x282B0B23UL,0x64264662UL,0x783A4A72UL,0x24270723UL,0x2C2F0F23UL,0xF031C1F1UL,0x70324272UL, +0x40024242UL,0xD414C4D0UL,0x40014141UL,0xC000C0C0UL,0x70334373UL,0x64274763UL,0xAC2C8CA0UL,0x880B8B83UL, +0xF437C7F3UL,0xAC2D8DA1UL,0x80008080UL,0x1C1F0F13UL,0xC80ACAC2UL,0x2C2C0C20UL,0xA82A8AA2UL,0x34340430UL, +0xD012C2D2UL,0x080B0B03UL,0xEC2ECEE2UL,0xE829C9E1UL,0x5C1D4D51UL,0x94148490UL,0x18180810UL,0xF838C8F0UL, +0x54174753UL,0xAC2E8EA2UL,0x08080800UL,0xC405C5C1UL,0x10130313UL,0xCC0DCDC1UL,0x84068682UL,0xB83989B1UL, +0xFC3FCFF3UL,0x7C3D4D71UL,0xC001C1C1UL,0x30310131UL,0xF435C5F1UL,0x880A8A82UL,0x682A4A62UL,0xB03181B1UL, +0xD011C1D1UL,0x20200020UL,0xD417C7D3UL,0x00020202UL,0x20220222UL,0x04040400UL,0x68284860UL,0x70314171UL, +0x04070703UL,0xD81BCBD3UL,0x9C1D8D91UL,0x98198991UL,0x60214161UL,0xBC3E8EB2UL,0xE426C6E2UL,0x58194951UL, +0xDC1DCDD1UL,0x50114151UL,0x90108090UL,0xDC1CCCD0UL,0x981A8A92UL,0xA02383A3UL,0xA82B8BA3UL,0xD010C0D0UL, +0x80018181UL,0x0C0F0F03UL,0x44074743UL,0x181A0A12UL,0xE023C3E3UL,0xEC2CCCE0UL,0x8C0D8D81UL,0xBC3F8FB3UL, +0x94168692UL,0x783B4B73UL,0x5C1C4C50UL,0xA02282A2UL,0xA02181A1UL,0x60234363UL,0x20230323UL,0x4C0D4D41UL, +0xC808C8C0UL,0x9C1E8E92UL,0x9C1C8C90UL,0x383A0A32UL,0x0C0C0C00UL,0x2C2E0E22UL,0xB83A8AB2UL,0x6C2E4E62UL, +0x9C1F8F93UL,0x581A4A52UL,0xF032C2F2UL,0x90128292UL,0xF033C3F3UL,0x48094941UL,0x78384870UL,0xCC0CCCC0UL, +0x14150511UL,0xF83BCBF3UL,0x70304070UL,0x74354571UL,0x7C3F4F73UL,0x34350531UL,0x10100010UL,0x00030303UL, +0x64244460UL,0x6C2D4D61UL,0xC406C6C2UL,0x74344470UL,0xD415C5D1UL,0xB43484B0UL,0xE82ACAE2UL,0x08090901UL, +0x74364672UL,0x18190911UL,0xFC3ECEF2UL,0x40004040UL,0x10120212UL,0xE020C0E0UL,0xBC3D8DB1UL,0x04050501UL, +0xF83ACAF2UL,0x00010101UL,0xF030C0F0UL,0x282A0A22UL,0x5C1E4E52UL,0xA82989A1UL,0x54164652UL,0x40034343UL, +0x84058581UL,0x14140410UL,0x88098981UL,0x981B8B93UL,0xB03080B0UL,0xE425C5E1UL,0x48084840UL,0x78394971UL, +0x94178793UL,0xFC3CCCF0UL,0x1C1E0E12UL,0x80028282UL,0x20210121UL,0x8C0C8C80UL,0x181B0B13UL,0x5C1F4F53UL, +0x74374773UL,0x54144450UL,0xB03282B2UL,0x1C1D0D11UL,0x24250521UL,0x4C0F4F43UL,0x00000000UL,0x44064642UL, +0xEC2DCDE1UL,0x58184850UL,0x50124252UL,0xE82BCBE3UL,0x7C3E4E72UL,0xD81ACAD2UL,0xC809C9C1UL,0xFC3DCDF1UL, +0x30300030UL,0x94158591UL,0x64254561UL,0x3C3C0C30UL,0xB43686B2UL,0xE424C4E0UL,0xB83B8BB3UL,0x7C3C4C70UL, +0x0C0E0E02UL,0x50104050UL,0x38390931UL,0x24260622UL,0x30320232UL,0x84048480UL,0x68294961UL,0x90138393UL, +0x34370733UL,0xE427C7E3UL,0x24240420UL,0xA42484A0UL,0xC80BCBC3UL,0x50134353UL,0x080A0A02UL,0x84078783UL, +0xD819C9D1UL,0x4C0C4C40UL,0x80038383UL,0x8C0F8F83UL,0xCC0ECEC2UL,0x383B0B33UL,0x480A4A42UL,0xB43787B3UL +}; + +static const ulong32 SS2[256] = { +0xA1A82989UL,0x81840585UL,0xD2D416C6UL,0xD3D013C3UL,0x50541444UL,0x111C1D0DUL,0xA0AC2C8CUL,0x21242505UL, +0x515C1D4DUL,0x43400343UL,0x10181808UL,0x121C1E0EUL,0x51501141UL,0xF0FC3CCCUL,0xC2C80ACAUL,0x63602343UL, +0x20282808UL,0x40440444UL,0x20202000UL,0x919C1D8DUL,0xE0E020C0UL,0xE2E022C2UL,0xC0C808C8UL,0x13141707UL, +0xA1A42585UL,0x838C0F8FUL,0x03000303UL,0x73783B4BUL,0xB3B83B8BUL,0x13101303UL,0xD2D012C2UL,0xE2EC2ECEUL, +0x70703040UL,0x808C0C8CUL,0x333C3F0FUL,0xA0A82888UL,0x32303202UL,0xD1DC1DCDUL,0xF2F436C6UL,0x70743444UL, +0xE0EC2CCCUL,0x91941585UL,0x03080B0BUL,0x53541747UL,0x505C1C4CUL,0x53581B4BUL,0xB1BC3D8DUL,0x01000101UL, +0x20242404UL,0x101C1C0CUL,0x73703343UL,0x90981888UL,0x10101000UL,0xC0CC0CCCUL,0xF2F032C2UL,0xD1D819C9UL, +0x202C2C0CUL,0xE3E427C7UL,0x72703242UL,0x83800383UL,0x93981B8BUL,0xD1D011C1UL,0x82840686UL,0xC1C809C9UL, +0x60602040UL,0x50501040UL,0xA3A02383UL,0xE3E82BCBUL,0x010C0D0DUL,0xB2B43686UL,0x929C1E8EUL,0x434C0F4FUL, +0xB3B43787UL,0x52581A4AUL,0xC2C406C6UL,0x70783848UL,0xA2A42686UL,0x12101202UL,0xA3AC2F8FUL,0xD1D415C5UL, +0x61602141UL,0xC3C003C3UL,0xB0B43484UL,0x41400141UL,0x52501242UL,0x717C3D4DUL,0x818C0D8DUL,0x00080808UL, +0x131C1F0FUL,0x91981989UL,0x00000000UL,0x11181909UL,0x00040404UL,0x53501343UL,0xF3F437C7UL,0xE1E021C1UL, +0xF1FC3DCDUL,0x72743646UL,0x232C2F0FUL,0x23242707UL,0xB0B03080UL,0x83880B8BUL,0x020C0E0EUL,0xA3A82B8BUL, +0xA2A02282UL,0x626C2E4EUL,0x93901383UL,0x414C0D4DUL,0x61682949UL,0x707C3C4CUL,0x01080909UL,0x02080A0AUL, +0xB3BC3F8FUL,0xE3EC2FCFUL,0xF3F033C3UL,0xC1C405C5UL,0x83840787UL,0x10141404UL,0xF2FC3ECEUL,0x60642444UL, +0xD2DC1ECEUL,0x222C2E0EUL,0x43480B4BUL,0x12181A0AUL,0x02040606UL,0x21202101UL,0x63682B4BUL,0x62642646UL, +0x02000202UL,0xF1F435C5UL,0x92901282UL,0x82880A8AUL,0x000C0C0CUL,0xB3B03383UL,0x727C3E4EUL,0xD0D010C0UL, +0x72783A4AUL,0x43440747UL,0x92941686UL,0xE1E425C5UL,0x22242606UL,0x80800080UL,0xA1AC2D8DUL,0xD3DC1FCFUL, +0xA1A02181UL,0x30303000UL,0x33343707UL,0xA2AC2E8EUL,0x32343606UL,0x11141505UL,0x22202202UL,0x30383808UL, +0xF0F434C4UL,0xA3A42787UL,0x41440545UL,0x404C0C4CUL,0x81800181UL,0xE1E829C9UL,0x80840484UL,0x93941787UL, +0x31343505UL,0xC3C80BCBUL,0xC2CC0ECEUL,0x303C3C0CUL,0x71703141UL,0x11101101UL,0xC3C407C7UL,0x81880989UL, +0x71743545UL,0xF3F83BCBUL,0xD2D81ACAUL,0xF0F838C8UL,0x90941484UL,0x51581949UL,0x82800282UL,0xC0C404C4UL, +0xF3FC3FCFUL,0x41480949UL,0x31383909UL,0x63642747UL,0xC0C000C0UL,0xC3CC0FCFUL,0xD3D417C7UL,0xB0B83888UL, +0x030C0F0FUL,0x828C0E8EUL,0x42400242UL,0x23202303UL,0x91901181UL,0x606C2C4CUL,0xD3D81BCBUL,0xA0A42484UL, +0x30343404UL,0xF1F031C1UL,0x40480848UL,0xC2C002C2UL,0x636C2F4FUL,0x313C3D0DUL,0x212C2D0DUL,0x40400040UL, +0xB2BC3E8EUL,0x323C3E0EUL,0xB0BC3C8CUL,0xC1C001C1UL,0xA2A82A8AUL,0xB2B83A8AUL,0x424C0E4EUL,0x51541545UL, +0x33383B0BUL,0xD0DC1CCCUL,0x60682848UL,0x737C3F4FUL,0x909C1C8CUL,0xD0D818C8UL,0x42480A4AUL,0x52541646UL, +0x73743747UL,0xA0A02080UL,0xE1EC2DCDUL,0x42440646UL,0xB1B43585UL,0x23282B0BUL,0x61642545UL,0xF2F83ACAUL, +0xE3E023C3UL,0xB1B83989UL,0xB1B03181UL,0x939C1F8FUL,0x525C1E4EUL,0xF1F839C9UL,0xE2E426C6UL,0xB2B03282UL, +0x31303101UL,0xE2E82ACAUL,0x616C2D4DUL,0x535C1F4FUL,0xE0E424C4UL,0xF0F030C0UL,0xC1CC0DCDUL,0x80880888UL, +0x12141606UL,0x32383A0AUL,0x50581848UL,0xD0D414C4UL,0x62602242UL,0x21282909UL,0x03040707UL,0x33303303UL, +0xE0E828C8UL,0x13181B0BUL,0x01040505UL,0x71783949UL,0x90901080UL,0x62682A4AUL,0x22282A0AUL,0x92981A8AUL +}; + +static const ulong32 SS3[256] = { +0x08303838UL,0xC8E0E828UL,0x0D212C2DUL,0x86A2A426UL,0xCFC3CC0FUL,0xCED2DC1EUL,0x83B3B033UL,0x88B0B838UL, +0x8FA3AC2FUL,0x40606020UL,0x45515415UL,0xC7C3C407UL,0x44404404UL,0x4F636C2FUL,0x4B63682BUL,0x4B53581BUL, +0xC3C3C003UL,0x42626022UL,0x03333033UL,0x85B1B435UL,0x09212829UL,0x80A0A020UL,0xC2E2E022UL,0x87A3A427UL, +0xC3D3D013UL,0x81919011UL,0x01111011UL,0x06020406UL,0x0C101C1CUL,0x8CB0BC3CUL,0x06323436UL,0x4B43480BUL, +0xCFE3EC2FUL,0x88808808UL,0x4C606C2CUL,0x88A0A828UL,0x07131417UL,0xC4C0C404UL,0x06121416UL,0xC4F0F434UL, +0xC2C2C002UL,0x45414405UL,0xC1E1E021UL,0xC6D2D416UL,0x0F333C3FUL,0x0D313C3DUL,0x8E828C0EUL,0x88909818UL, +0x08202828UL,0x4E424C0EUL,0xC6F2F436UL,0x0E323C3EUL,0x85A1A425UL,0xC9F1F839UL,0x0D010C0DUL,0xCFD3DC1FUL, +0xC8D0D818UL,0x0B23282BUL,0x46626426UL,0x4A72783AUL,0x07232427UL,0x0F232C2FUL,0xC1F1F031UL,0x42727032UL, +0x42424002UL,0xC4D0D414UL,0x41414001UL,0xC0C0C000UL,0x43737033UL,0x47636427UL,0x8CA0AC2CUL,0x8B83880BUL, +0xC7F3F437UL,0x8DA1AC2DUL,0x80808000UL,0x0F131C1FUL,0xCAC2C80AUL,0x0C202C2CUL,0x8AA2A82AUL,0x04303434UL, +0xC2D2D012UL,0x0B03080BUL,0xCEE2EC2EUL,0xC9E1E829UL,0x4D515C1DUL,0x84909414UL,0x08101818UL,0xC8F0F838UL, +0x47535417UL,0x8EA2AC2EUL,0x08000808UL,0xC5C1C405UL,0x03131013UL,0xCDC1CC0DUL,0x86828406UL,0x89B1B839UL, +0xCFF3FC3FUL,0x4D717C3DUL,0xC1C1C001UL,0x01313031UL,0xC5F1F435UL,0x8A82880AUL,0x4A62682AUL,0x81B1B031UL, +0xC1D1D011UL,0x00202020UL,0xC7D3D417UL,0x02020002UL,0x02222022UL,0x04000404UL,0x48606828UL,0x41717031UL, +0x07030407UL,0xCBD3D81BUL,0x8D919C1DUL,0x89919819UL,0x41616021UL,0x8EB2BC3EUL,0xC6E2E426UL,0x49515819UL, +0xCDD1DC1DUL,0x41515011UL,0x80909010UL,0xCCD0DC1CUL,0x8A92981AUL,0x83A3A023UL,0x8BA3A82BUL,0xC0D0D010UL, +0x81818001UL,0x0F030C0FUL,0x47434407UL,0x0A12181AUL,0xC3E3E023UL,0xCCE0EC2CUL,0x8D818C0DUL,0x8FB3BC3FUL, +0x86929416UL,0x4B73783BUL,0x4C505C1CUL,0x82A2A022UL,0x81A1A021UL,0x43636023UL,0x03232023UL,0x4D414C0DUL, +0xC8C0C808UL,0x8E929C1EUL,0x8C909C1CUL,0x0A32383AUL,0x0C000C0CUL,0x0E222C2EUL,0x8AB2B83AUL,0x4E626C2EUL, +0x8F939C1FUL,0x4A52581AUL,0xC2F2F032UL,0x82929012UL,0xC3F3F033UL,0x49414809UL,0x48707838UL,0xCCC0CC0CUL, +0x05111415UL,0xCBF3F83BUL,0x40707030UL,0x45717435UL,0x4F737C3FUL,0x05313435UL,0x00101010UL,0x03030003UL, +0x44606424UL,0x4D616C2DUL,0xC6C2C406UL,0x44707434UL,0xC5D1D415UL,0x84B0B434UL,0xCAE2E82AUL,0x09010809UL, +0x46727436UL,0x09111819UL,0xCEF2FC3EUL,0x40404000UL,0x02121012UL,0xC0E0E020UL,0x8DB1BC3DUL,0x05010405UL, +0xCAF2F83AUL,0x01010001UL,0xC0F0F030UL,0x0A22282AUL,0x4E525C1EUL,0x89A1A829UL,0x46525416UL,0x43434003UL, +0x85818405UL,0x04101414UL,0x89818809UL,0x8B93981BUL,0x80B0B030UL,0xC5E1E425UL,0x48404808UL,0x49717839UL, +0x87939417UL,0xCCF0FC3CUL,0x0E121C1EUL,0x82828002UL,0x01212021UL,0x8C808C0CUL,0x0B13181BUL,0x4F535C1FUL, +0x47737437UL,0x44505414UL,0x82B2B032UL,0x0D111C1DUL,0x05212425UL,0x4F434C0FUL,0x00000000UL,0x46424406UL, +0xCDE1EC2DUL,0x48505818UL,0x42525012UL,0xCBE3E82BUL,0x4E727C3EUL,0xCAD2D81AUL,0xC9C1C809UL,0xCDF1FC3DUL, +0x00303030UL,0x85919415UL,0x45616425UL,0x0C303C3CUL,0x86B2B436UL,0xC4E0E424UL,0x8BB3B83BUL,0x4C707C3CUL, +0x0E020C0EUL,0x40505010UL,0x09313839UL,0x06222426UL,0x02323032UL,0x84808404UL,0x49616829UL,0x83939013UL, +0x07333437UL,0xC7E3E427UL,0x04202424UL,0x84A0A424UL,0xCBC3C80BUL,0x43535013UL,0x0A02080AUL,0x87838407UL, +0xC9D1D819UL,0x4C404C0CUL,0x83838003UL,0x8F838C0FUL,0xCEC2CC0EUL,0x0B33383BUL,0x4A42480AUL,0x87B3B437UL +}; + +static const ulong32 KCi[16] = { +0x9E3779B9,0x3C6EF373, +0x78DDE6E6,0xF1BBCDCC, +0xE3779B99,0xC6EF3733, +0x8DDE6E67,0x1BBCDCCF, +0x3779B99E,0x6EF3733C, +0xDDE6E678,0xBBCDCCF1, +0x779B99E3,0xEF3733C6, +0xDE6E678D,0xBCDCCF1B +}; + +#define G(x) (SS3[((x)>>24)&255] ^ SS2[((x)>>16)&255] ^ SS1[((x)>>8)&255] ^ SS0[(x)&255]) + +#define F(L1, L2, R1, R2, K1, K2) \ + T2 = G((R1 ^ K1) ^ (R2 ^ K2)); \ + T = G( G(T2 + (R1 ^ K1)) + T2); \ + L2 ^= T; \ + L1 ^= (T + G(T2 + (R1 ^ K1))); \ + + /** + Initialize the SEED 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 kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int i; + ulong32 tmp, k1, k2, k3, k4; + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 16 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + /* load key */ + LOAD32H(k1, key); + LOAD32H(k2, key+4); + LOAD32H(k3, key+8); + LOAD32H(k4, key+12); + + for (i = 0; i < 16; i++) { + skey->kseed.K[2*i+0] = G(k1 + k3 - KCi[i]); + skey->kseed.K[2*i+1] = G(k2 - k4 + KCi[i]); + if (i&1) { + tmp = k3; + k3 = ((k3 << 8) | (k4 >> 24)) & 0xFFFFFFFF; + k4 = ((k4 << 8) | (tmp >> 24)) & 0xFFFFFFFF; + } else { + tmp = k1; + k1 = ((k1 >> 8) | (k2 << 24)) & 0xFFFFFFFF; + k2 = ((k2 >> 8) | (tmp << 24)) & 0xFFFFFFFF; + } + /* reverse keys for decrypt */ + skey->kseed.dK[2*(15-i)+0] = skey->kseed.K[2*i+0]; + skey->kseed.dK[2*(15-i)+1] = skey->kseed.K[2*i+1]; + } + + return CRYPT_OK; +} + +static void rounds(ulong32 *P, const ulong32 *K) +{ + ulong32 T, T2; + int i; + for (i = 0; i < 16; i += 2) { + F(P[0], P[1], P[2], P[3], K[0], K[1]); + F(P[2], P[3], P[0], P[1], K[2], K[3]); + K += 4; + } +} + +/** + Encrypts a block of text with SEED + @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 +*/ +int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 P[4]; + LOAD32H(P[0], pt); + LOAD32H(P[1], pt+4); + LOAD32H(P[2], pt+8); + LOAD32H(P[3], pt+12); + rounds(P, skey->kseed.K); + STORE32H(P[2], ct); + STORE32H(P[3], ct+4); + STORE32H(P[0], ct+8); + STORE32H(P[1], ct+12); + return CRYPT_OK; +} + +/** + Decrypts a block of text with SEED + @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 +*/ +int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 P[4]; + LOAD32H(P[0], ct); + LOAD32H(P[1], ct+4); + LOAD32H(P[2], ct+8); + LOAD32H(P[3], ct+12); + rounds(P, skey->kseed.dK); + STORE32H(P[2], pt); + STORE32H(P[3], pt+4); + STORE32H(P[0], pt+8); + STORE32H(P[1], pt+12); + return CRYPT_OK; +} + +/** Terminate the context + @param skey The scheduled key +*/ +void kseed_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Performs a self-test of the SEED block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int kseed_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct test { + unsigned char pt[16], ct[16], key[16]; + } tests[] = { + +{ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, + { 0x5E,0xBA,0xC6,0xE0,0x05,0x4E,0x16,0x68,0x19,0xAF,0xF1,0xCC,0x6D,0x34,0x6C,0xDB }, + { 0 }, +}, + +{ + { 0 }, + { 0xC1,0x1F,0x22,0xF2,0x01,0x40,0x50,0x50,0x84,0x48,0x35,0x97,0xE4,0x37,0x0F,0x43 }, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, +}, + +{ + { 0x83,0xA2,0xF8,0xA2,0x88,0x64,0x1F,0xB9,0xA4,0xE9,0xA5,0xCC,0x2F,0x13,0x1C,0x7D }, + { 0xEE,0x54,0xD1,0x3E,0xBC,0xAE,0x70,0x6D,0x22,0x6B,0xC3,0x14,0x2C,0xD4,0x0D,0x4A }, + { 0x47,0x06,0x48,0x08,0x51,0xE6,0x1B,0xE8,0x5D,0x74,0xBF,0xB3,0xFD,0x95,0x61,0x85 }, +}, + +{ + { 0xB4,0x1E,0x6B,0xE2,0xEB,0xA8,0x4A,0x14,0x8E,0x2E,0xED,0x84,0x59,0x3C,0x5E,0xC7 }, + { 0x9B,0x9B,0x7B,0xFC,0xD1,0x81,0x3C,0xB9,0x5D,0x0B,0x36,0x18,0xF4,0x0F,0x51,0x22 }, + { 0x28,0xDB,0xC3,0xBC,0x49,0xFF,0xD8,0x7D,0xCF,0xA5,0x09,0xB1,0x1D,0x42,0x2B,0xE7 }, +} +}; + int x; + unsigned char buf[2][16]; + symmetric_key skey; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + kseed_setup(tests[x].key, 16, 0, &skey); + kseed_ecb_encrypt(tests[x].pt, buf[0], &skey); + kseed_ecb_decrypt(buf[0], buf[1], &skey); + if (compare_testvector(buf[0], 16, tests[x].ct, 16, "KSEED Encrypt", x) || + compare_testvector(buf[1], 16, tests[x].pt, 16, "KSEED Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +/** + 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 kseed_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 16) { + *keysize = 16; + } else { + return CRYPT_INVALID_KEYSIZE; + } + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/multi2.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/multi2.c new file mode 100644 index 0000000..e1a84ac --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/multi2.c @@ -0,0 +1,309 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file multi2.c + Multi-2 implementation (not public domain, hence the default disable) +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_MULTI2 + +static void s_pi1(ulong32 *p) +{ + p[1] ^= p[0]; +} + +static void s_pi2(ulong32 *p, const ulong32 *k) +{ + ulong32 t; + t = (p[1] + k[0]) & 0xFFFFFFFFUL; + t = (ROL(t, 1) + t - 1) & 0xFFFFFFFFUL; + t = (ROL(t, 4) ^ t) & 0xFFFFFFFFUL; + p[0] ^= t; +} + +static void s_pi3(ulong32 *p, const ulong32 *k) +{ + ulong32 t; + t = p[0] + k[1]; + t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; + t = (ROL(t, 8) ^ t) & 0xFFFFFFFFUL; + t = (t + k[2]) & 0xFFFFFFFFUL; + t = (ROL(t, 1) - t) & 0xFFFFFFFFUL; + t = ROL(t, 16) ^ (p[0] | t); + p[1] ^= t; +} + +static void s_pi4(ulong32 *p, const ulong32 *k) +{ + ulong32 t; + t = (p[1] + k[3]) & 0xFFFFFFFFUL; + t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; + p[0] ^= t; +} + +static void s_setup(const ulong32 *dk, const ulong32 *k, ulong32 *uk) +{ + int n, t; + ulong32 p[2]; + + p[0] = dk[0]; p[1] = dk[1]; + + t = 4; + n = 0; + s_pi1(p); + s_pi2(p, k); + uk[n++] = p[0]; + s_pi3(p, k); + uk[n++] = p[1]; + s_pi4(p, k); + uk[n++] = p[0]; + s_pi1(p); + uk[n++] = p[1]; + s_pi2(p, k+t); + uk[n++] = p[0]; + s_pi3(p, k+t); + uk[n++] = p[1]; + s_pi4(p, k+t); + uk[n++] = p[0]; + s_pi1(p); + uk[n++] = p[1]; +} + +static void s_encrypt(ulong32 *p, int N, const ulong32 *uk) +{ + int n, t; + for (t = n = 0; ; ) { + s_pi1(p); if (++n == N) break; + s_pi2(p, uk+t); if (++n == N) break; + s_pi3(p, uk+t); if (++n == N) break; + s_pi4(p, uk+t); if (++n == N) break; + t ^= 4; + } +} + +static void s_decrypt(ulong32 *p, int N, const ulong32 *uk) +{ + int n, t; + for (t = 4*(((N-1)>>2)&1), n = N; ; ) { + switch (n<=4 ? n : ((n-1)%4)+1) { + case 4: s_pi4(p, uk+t); --n; /* FALLTHROUGH */ + case 3: s_pi3(p, uk+t); --n; /* FALLTHROUGH */ + case 2: s_pi2(p, uk+t); --n; /* FALLTHROUGH */ + case 1: s_pi1(p); --n; break; + case 0: return; + } + t ^= 4; + } +} + +const struct ltc_cipher_descriptor multi2_desc = { + "multi2", + 22, + 40, 40, 8, 128, + &multi2_setup, + &multi2_ecb_encrypt, + &multi2_ecb_decrypt, + &multi2_test, + &multi2_done, + &multi2_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + ulong32 sk[8], dk[2]; + int x; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 40) return CRYPT_INVALID_KEYSIZE; + if (num_rounds == 0) num_rounds = 128; + + skey->multi2.N = num_rounds; + for (x = 0; x < 8; x++) { + LOAD32H(sk[x], key + x*4); + } + LOAD32H(dk[0], key + 32); + LOAD32H(dk[1], key + 36); + s_setup(dk, sk, skey->multi2.uk); + + zeromem(sk, sizeof(sk)); + zeromem(dk, sizeof(dk)); + return CRYPT_OK; +} + +/** + Encrypts a block of text with multi2 + @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 multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 p[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(p[0], pt); + LOAD32H(p[1], pt+4); + s_encrypt(p, skey->multi2.N, skey->multi2.uk); + STORE32H(p[0], ct); + STORE32H(p[1], ct+4); + return CRYPT_OK; +} + +/** + Decrypts a block of text with multi2 + @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 multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 p[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(p[0], ct); + LOAD32H(p[1], ct+4); + s_decrypt(p, skey->multi2.N, skey->multi2.uk); + STORE32H(p[0], pt); + STORE32H(p[1], pt+4); + return CRYPT_OK; +} + +/** + Performs a self-test of the multi2 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int multi2_test(void) +{ + static const struct { + unsigned char key[40]; + unsigned char pt[8], ct[8]; + int rounds; + } tests[] = { +{ + { + 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, + + 0x01, 0x23, 0x45, 0x67, + 0x89, 0xAB, 0xCD, 0xEF + }, + { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + }, + { + 0xf8, 0x94, 0x40, 0x84, + 0x5e, 0x11, 0xcf, 0x89 + }, + 128, +}, +{ + { + 0x35, 0x91, 0x9d, 0x96, + 0x07, 0x02, 0xe2, 0xce, + 0x8d, 0x0b, 0x58, 0x3c, + 0xc9, 0xc8, 0x9d, 0x59, + 0xa2, 0xae, 0x96, 0x4e, + 0x87, 0x82, 0x45, 0xed, + 0x3f, 0x2e, 0x62, 0xd6, + 0x36, 0x35, 0xd0, 0x67, + + 0xb1, 0x27, 0xb9, 0x06, + 0xe7, 0x56, 0x22, 0x38, + }, + { + 0x1f, 0xb4, 0x60, 0x60, + 0xd0, 0xb3, 0x4f, 0xa5 + }, + { + 0xca, 0x84, 0xa9, 0x34, + 0x75, 0xc8, 0x60, 0xe5 + }, + 216, +} +}; + unsigned char buf[8]; + symmetric_key skey; + int err, x; + + for (x = 1; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = multi2_setup(tests[x].key, 40, tests[x].rounds, &skey)) != CRYPT_OK) { + return err; + } + if ((err = multi2_ecb_encrypt(tests[x].pt, buf, &skey)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(buf, 8, tests[x].ct, 8, "Multi2 Encrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = multi2_ecb_decrypt(buf, buf, &skey)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf, 8, tests[x].pt, 8, "Multi2 Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + for (x = 128; x < 256; ++x) { + unsigned char ct[8]; + + if ((err = multi2_setup(tests[0].key, 40, x, &skey)) != CRYPT_OK) { + return err; + } + if ((err = multi2_ecb_encrypt(tests[0].pt, ct, &skey)) != CRYPT_OK) { + return err; + } + if ((err = multi2_ecb_decrypt(ct, buf, &skey)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf, 8, tests[0].pt, 8, "Multi2 Rounds", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +} + +/** Terminate the context + @param skey The scheduled key +*/ +void multi2_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 multi2_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 40) { + *keysize = 40; + } else { + return CRYPT_INVALID_KEYSIZE; + } + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/noekeon.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/noekeon.c new file mode 100644 index 0000000..58d73ae --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/noekeon.c @@ -0,0 +1,317 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @file noekeon.c + Implementation of the Noekeon block cipher by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_NOEKEON + +const struct ltc_cipher_descriptor noekeon_desc = +{ + "noekeon", + 16, + 16, 16, 16, 16, + &noekeon_setup, + &noekeon_ecb_encrypt, + &noekeon_ecb_decrypt, + &noekeon_test, + &noekeon_done, + &noekeon_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 RC[] = { + 0x00000080UL, 0x0000001bUL, 0x00000036UL, 0x0000006cUL, + 0x000000d8UL, 0x000000abUL, 0x0000004dUL, 0x0000009aUL, + 0x0000002fUL, 0x0000005eUL, 0x000000bcUL, 0x00000063UL, + 0x000000c6UL, 0x00000097UL, 0x00000035UL, 0x0000006aUL, + 0x000000d4UL +}; + +#define kTHETA(a, b, c, d) \ + temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ + b ^= temp; d ^= temp; \ + temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ + a ^= temp; c ^= temp; + +#define THETA(k, a, b, c, d) \ + temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ + b ^= temp ^ k[1]; d ^= temp ^ k[3]; \ + temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ + a ^= temp ^ k[0]; c ^= temp ^ k[2]; + +#define GAMMA(a, b, c, d) \ + b ^= ~(d|c); \ + a ^= c&b; \ + temp = d; d = a; a = temp;\ + c ^= a ^ b ^ d; \ + b ^= ~(d|c); \ + a ^= c&b; + +#define PI1(a, b, c, d) \ + b = ROLc(b, 1); c = ROLc(c, 5); d = ROLc(d, 2); + +#define PI2(a, b, c, d) \ + b = RORc(b, 1); c = RORc(c, 5); d = RORc(d, 2); + + /** + Initialize the Noekeon 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 noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + ulong32 temp; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 16 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + LOAD32H(skey->noekeon.K[0],&key[0]); + LOAD32H(skey->noekeon.K[1],&key[4]); + LOAD32H(skey->noekeon.K[2],&key[8]); + LOAD32H(skey->noekeon.K[3],&key[12]); + + LOAD32H(skey->noekeon.dK[0],&key[0]); + LOAD32H(skey->noekeon.dK[1],&key[4]); + LOAD32H(skey->noekeon.dK[2],&key[8]); + LOAD32H(skey->noekeon.dK[3],&key[12]); + + kTHETA(skey->noekeon.dK[0], skey->noekeon.dK[1], skey->noekeon.dK[2], skey->noekeon.dK[3]); + + return CRYPT_OK; +} + +/** + Encrypts a block of text with Noekeon + @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 s_noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,temp; + int r; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + LOAD32H(a,&pt[0]); LOAD32H(b,&pt[4]); + LOAD32H(c,&pt[8]); LOAD32H(d,&pt[12]); + +#define ROUND(i) \ + a ^= RC[i]; \ + THETA(skey->noekeon.K, a,b,c,d); \ + PI1(a,b,c,d); \ + GAMMA(a,b,c,d); \ + PI2(a,b,c,d); + + for (r = 0; r < 16; ++r) { + ROUND(r); + } + +#undef ROUND + + a ^= RC[16]; + THETA(skey->noekeon.K, a, b, c, d); + + STORE32H(a,&ct[0]); STORE32H(b,&ct[4]); + STORE32H(c,&ct[8]); STORE32H(d,&ct[12]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_noekeon_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 5 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with Noekeon + @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 s_noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d, temp; + int r; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + LOAD32H(a,&ct[0]); LOAD32H(b,&ct[4]); + LOAD32H(c,&ct[8]); LOAD32H(d,&ct[12]); + + +#define ROUND(i) \ + THETA(skey->noekeon.dK, a,b,c,d); \ + a ^= RC[i]; \ + PI1(a,b,c,d); \ + GAMMA(a,b,c,d); \ + PI2(a,b,c,d); + + for (r = 16; r > 0; --r) { + ROUND(r); + } + +#undef ROUND + + THETA(skey->noekeon.dK, a,b,c,d); + a ^= RC[0]; + STORE32H(a,&pt[0]); STORE32H(b, &pt[4]); + STORE32H(c,&pt[8]); STORE32H(d, &pt[12]); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_noekeon_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 5 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the Noekeon block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int noekeon_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[16], pt[16], ct[16]; + } tests[] = { + { + 16, + { 0xAA, 0x3C, 0x8C, 0x86, 0xD9, 0x8B, 0xF8, 0xBE, 0x21, 0xE0, 0x36, 0x09, 0x78, 0xFB, 0xE4, 0x90 }, + { 0xE4, 0x96, 0x6C, 0xD3, 0x13, 0xA0, 0x6C, 0xAF, 0xD0, 0x23, 0xC9, 0xFD, 0x45, 0x32, 0x23, 0x16 }, + { 0xA6, 0xEC, 0xB8, 0xA8, 0x61, 0xFD, 0x62, 0xD9, 0x13, 0x02, 0xFE, 0x9E, 0x47, 0x01, 0x3F, 0xC3 } + }, + { + 16, + { 0xED, 0x43, 0xD1, 0x87, 0x21, 0x7E, 0xE0, 0x97, 0x3D, 0x76, 0xC3, 0x37, 0x2E, 0x7D, 0xAE, 0xD3 }, + { 0xE3, 0x38, 0x32, 0xCC, 0xF2, 0x2F, 0x2F, 0x0A, 0x4A, 0x8B, 0x8F, 0x18, 0x12, 0x20, 0x17, 0xD3 }, + { 0x94, 0xA5, 0xDF, 0xF5, 0xAE, 0x1C, 0xBB, 0x22, 0xAD, 0xEB, 0xA7, 0x0D, 0xB7, 0x82, 0x90, 0xA0 } + }, + { + 16, + { 0x6F, 0xDC, 0x23, 0x38, 0xF2, 0x10, 0xFB, 0xD3, 0xC1, 0x8C, 0x02, 0xF6, 0xB4, 0x6A, 0xD5, 0xA8 }, + { 0xDB, 0x29, 0xED, 0xB5, 0x5F, 0xB3, 0x60, 0x3A, 0x92, 0xA8, 0xEB, 0x9C, 0x6D, 0x9D, 0x3E, 0x8F }, + { 0x78, 0xF3, 0x6F, 0xF8, 0x9E, 0xBB, 0x8C, 0x6A, 0xE8, 0x10, 0xF7, 0x00, 0x22, 0x15, 0x30, 0x3D } + }, + { + 16, + { 0x2C, 0x0C, 0x02, 0xEF, 0x6B, 0xC4, 0xF2, 0x0B, 0x2E, 0xB9, 0xE0, 0xBF, 0xD9, 0x36, 0xC2, 0x4E }, + { 0x84, 0xE2, 0xFE, 0x64, 0xB1, 0xB9, 0xFE, 0x76, 0xA8, 0x3F, 0x45, 0xC7, 0x40, 0x7A, 0xAF, 0xEE }, + { 0x2A, 0x08, 0xD6, 0xA2, 0x1C, 0x63, 0x08, 0xB0, 0xF8, 0xBC, 0xB3, 0xA1, 0x66, 0xF7, 0xAE, 0xCF } + }, + { + 16, + { 0x6F, 0x30, 0xF8, 0x9F, 0xDA, 0x6E, 0xA0, 0x91, 0x04, 0x0F, 0x6C, 0x8B, 0x7D, 0xF7, 0x2A, 0x4B }, + { 0x65, 0xB6, 0xA6, 0xD0, 0x42, 0x14, 0x08, 0x60, 0x34, 0x8D, 0x37, 0x2F, 0x01, 0xF0, 0x46, 0xBE }, + { 0x66, 0xAC, 0x0B, 0x62, 0x1D, 0x68, 0x11, 0xF5, 0x27, 0xB1, 0x13, 0x5D, 0xF3, 0x2A, 0xE9, 0x18 } + }, + { + 16, + { 0xCA, 0xA4, 0x16, 0xB7, 0x1C, 0x92, 0x2E, 0xAD, 0xEB, 0xA7, 0xDB, 0x69, 0x92, 0xCB, 0x35, 0xEF }, + { 0x81, 0x6F, 0x8E, 0x4D, 0x96, 0xC6, 0xB3, 0x67, 0x83, 0xF5, 0x63, 0xC7, 0x20, 0x6D, 0x40, 0x23 }, + { 0x44, 0xF7, 0x63, 0x62, 0xF0, 0x43, 0xBB, 0x67, 0x4A, 0x75, 0x12, 0x42, 0x46, 0x29, 0x28, 0x19 } + }, + { + 16, + { 0x6B, 0xCF, 0x22, 0x2F, 0xE0, 0x1B, 0xB0, 0xAA, 0xD8, 0x3C, 0x91, 0x99, 0x18, 0xB2, 0x28, 0xE8 }, + { 0x7C, 0x37, 0xC7, 0xD0, 0xAC, 0x92, 0x29, 0xF1, 0x60, 0x82, 0x93, 0x89, 0xAA, 0x61, 0xAA, 0xA9 }, + { 0xE5, 0x89, 0x1B, 0xB3, 0xFE, 0x8B, 0x0C, 0xA1, 0xA6, 0xC7, 0xBE, 0x12, 0x73, 0x0F, 0xC1, 0x19 } + }, + { + 16, + { 0xE6, 0xD0, 0xF1, 0x03, 0x2E, 0xDE, 0x70, 0x8D, 0xD8, 0x9E, 0x36, 0x5C, 0x05, 0x52, 0xE7, 0x0D }, + { 0xE2, 0x42, 0xE7, 0x92, 0x0E, 0xF7, 0x82, 0xA2, 0xB8, 0x21, 0x8D, 0x26, 0xBA, 0x2D, 0xE6, 0x32 }, + { 0x1E, 0xDD, 0x75, 0x22, 0xB9, 0x36, 0x8A, 0x0F, 0x32, 0xFD, 0xD4, 0x48, 0x65, 0x12, 0x5A, 0x2F } + } + }; + symmetric_key key; + unsigned char tmp[2][16]; + int err, i, y; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + zeromem(&key, sizeof(key)); + if ((err = noekeon_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + + noekeon_ecb_encrypt(tests[i].pt, tmp[0], &key); + noekeon_ecb_decrypt(tmp[0], tmp[1], &key); + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Noekeon Encrypt", i) || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "Noekeon Decrypt", i)) { + 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++) noekeon_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) noekeon_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 +} + +/** Terminate the context + @param skey The scheduled key +*/ +void noekeon_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 noekeon_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc2.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc2.c new file mode 100644 index 0000000..4832424 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc2.c @@ -0,0 +1,408 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/**********************************************************************\ +* To commemorate the 1996 RSA Data Security Conference, the following * +* code is released into the public domain by its author. Prost! * +* * +* This cipher uses 16-bit words and little-endian byte ordering. * +* I wonder which processor it was optimized for? * +* * +* Thanks to CodeView, SoftIce, and D86 for helping bring this code to * +* the public. * +\**********************************************************************/ +#include "tomcrypt_private.h" + +/** + @file rc2.c + Implementation of RC2 with fixed effective key length of 64bits +*/ + +#ifdef LTC_RC2 + +const struct ltc_cipher_descriptor rc2_desc = { + "rc2", + 12, 8, 128, 8, 16, + &rc2_setup, + &rc2_ecb_encrypt, + &rc2_ecb_decrypt, + &rc2_test, + &rc2_done, + &rc2_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* 256-entry permutation table, probably derived somehow from pi */ +static const unsigned char permute[256] = { + 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, + 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, + 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, + 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, + 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, + 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, + 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, + 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, + 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, + 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, + 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, + 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, + 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, + 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, + 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, + 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 +}; + + /** + Initialize the RC2 block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param bits The effective key length in bits + @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 rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey) +{ + unsigned *xkey = skey->rc2.xkey; + unsigned char tmp[128]; + unsigned T8, TM; + int i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen == 0 || keylen > 128 || bits > 1024) { + return CRYPT_INVALID_KEYSIZE; + } + if (bits == 0) { + bits = 1024; + } + + if (num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + for (i = 0; i < keylen; i++) { + tmp[i] = key[i] & 255; + } + + /* Phase 1: Expand input key to 128 bytes */ + if (keylen < 128) { + for (i = keylen; i < 128; i++) { + tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255]; + } + } + + /* Phase 2 - reduce effective key size to "bits" */ + T8 = (unsigned)(bits+7)>>3; + TM = (255 >> (unsigned)(7 & -bits)); + tmp[128 - T8] = permute[tmp[128 - T8] & TM]; + for (i = 127 - T8; i >= 0; i--) { + tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]]; + } + + /* Phase 3 - copy to xkey in little-endian order */ + for (i = 0; i < 64; i++) { + xkey[i] = (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8); + } + +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + + return CRYPT_OK; +} + +/** + Initialize the RC2 block cipher + + The effective key length is here always keylen * 8 + + @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 rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + return rc2_setup_ex(key, keylen, keylen * 8, num_rounds, skey); +} + +/**********************************************************************\ +* Encrypt an 8-byte block of plaintext using the given key. * +\**********************************************************************/ +/** + Encrypts a block of text with RC2 + @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 +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc2_ecb_encrypt( const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +#else +int rc2_ecb_encrypt( const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +#endif +{ + const unsigned *xkey; + unsigned x76, x54, x32, x10, i; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + xkey = skey->rc2.xkey; + + x76 = ((unsigned)pt[7] << 8) + (unsigned)pt[6]; + x54 = ((unsigned)pt[5] << 8) + (unsigned)pt[4]; + x32 = ((unsigned)pt[3] << 8) + (unsigned)pt[2]; + x10 = ((unsigned)pt[1] << 8) + (unsigned)pt[0]; + + for (i = 0; i < 16; i++) { + x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF; + x10 = ((x10 << 1) | (x10 >> 15)); + + x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF; + x32 = ((x32 << 2) | (x32 >> 14)); + + x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF; + x54 = ((x54 << 3) | (x54 >> 13)); + + x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF; + x76 = ((x76 << 5) | (x76 >> 11)); + + if (i == 4 || i == 10) { + x10 = (x10 + xkey[x76 & 63]) & 0xFFFF; + x32 = (x32 + xkey[x10 & 63]) & 0xFFFF; + x54 = (x54 + xkey[x32 & 63]) & 0xFFFF; + x76 = (x76 + xkey[x54 & 63]) & 0xFFFF; + } + } + + ct[0] = (unsigned char)x10; + ct[1] = (unsigned char)(x10 >> 8); + ct[2] = (unsigned char)x32; + ct[3] = (unsigned char)(x32 >> 8); + ct[4] = (unsigned char)x54; + ct[5] = (unsigned char)(x54 >> 8); + ct[6] = (unsigned char)x76; + ct[7] = (unsigned char)(x76 >> 8); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc2_ecb_encrypt( const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +{ + int err = s_rc2_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5); + return err; +} +#endif + +/**********************************************************************\ +* Decrypt an 8-byte block of ciphertext using the given key. * +\**********************************************************************/ +/** + Decrypts a block of text with RC2 + @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 +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc2_ecb_decrypt( const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +#else +int rc2_ecb_decrypt( const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +#endif +{ + unsigned x76, x54, x32, x10; + const unsigned *xkey; + int i; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + xkey = skey->rc2.xkey; + + x76 = ((unsigned)ct[7] << 8) + (unsigned)ct[6]; + x54 = ((unsigned)ct[5] << 8) + (unsigned)ct[4]; + x32 = ((unsigned)ct[3] << 8) + (unsigned)ct[2]; + x10 = ((unsigned)ct[1] << 8) + (unsigned)ct[0]; + + for (i = 15; i >= 0; i--) { + if (i == 4 || i == 10) { + x76 = (x76 - xkey[x54 & 63]) & 0xFFFF; + x54 = (x54 - xkey[x32 & 63]) & 0xFFFF; + x32 = (x32 - xkey[x10 & 63]) & 0xFFFF; + x10 = (x10 - xkey[x76 & 63]) & 0xFFFF; + } + + x76 = ((x76 << 11) | (x76 >> 5)); + x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF; + + x54 = ((x54 << 13) | (x54 >> 3)); + x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF; + + x32 = ((x32 << 14) | (x32 >> 2)); + x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF; + + x10 = ((x10 << 15) | (x10 >> 1)); + x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF; + } + + pt[0] = (unsigned char)x10; + pt[1] = (unsigned char)(x10 >> 8); + pt[2] = (unsigned char)x32; + pt[3] = (unsigned char)(x32 >> 8); + pt[4] = (unsigned char)x54; + pt[5] = (unsigned char)(x54 >> 8); + pt[6] = (unsigned char)x76; + pt[7] = (unsigned char)(x76 >> 8); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc2_ecb_decrypt( const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +{ + int err = s_rc2_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the RC2 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int rc2_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen, bits; + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + + { 8, 63, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff } + }, + { 8, 64, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0x27, 0x8b, 0x27, 0xe4, 0x2e, 0x2f, 0x0d, 0x49 } + }, + { 8, 64, + { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 } + }, + { 1, 64, + { 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x61, 0xa8, 0xa2, 0x44, 0xad, 0xac, 0xcc, 0xf0 } + }, + { 7, 64, + { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6c, 0xcf, 0x43, 0x08, 0x97, 0x4c, 0x26, 0x7f } + }, + { 16, 64, + { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, + 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1a, 0x80, 0x7d, 0x27, 0x2b, 0xbe, 0x5d, 0xb1 } + }, + { 16, 128, + { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, + 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 } + } + }; + int x, y, err; + symmetric_key skey; + unsigned char tmp[2][8]; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + zeromem(tmp, sizeof(tmp)); + if (tests[x].bits == (tests[x].keylen * 8)) { + if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) { + return err; + } + } + else { + if ((err = rc2_setup_ex(tests[x].key, tests[x].keylen, tests[x].bits, 0, &skey)) != CRYPT_OK) { + return err; + } + } + + rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey); + rc2_ecb_decrypt(tmp[0], tmp[1], &skey); + + if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC2 CT", x) || + compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC2 PT", x)) { + 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[0][y] = 0; + for (y = 0; y < 1000; y++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void rc2_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 rc2_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 1) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 128) { + *keysize = 128; + } + return CRYPT_OK; +} + +#endif + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc5.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc5.c new file mode 100644 index 0000000..f21ba4f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc5.c @@ -0,0 +1,323 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file rc5.c + LTC_RC5 code by Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC5 + +const struct ltc_cipher_descriptor rc5_desc = +{ + "rc5", + 2, + 8, 128, 8, 12, + &rc5_setup, + &rc5_ecb_encrypt, + &rc5_ecb_decrypt, + &rc5_test, + &rc5_done, + &rc5_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 stab[50] = { +0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, +0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, +0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, +0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, +0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, +0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL, 0xe96a3d2fUL, 0x87a1b6e8UL, 0x25d930a1UL, 0xc410aa5aUL, +0x62482413UL, 0x007f9dccUL +}; + + /** + Initialize the LTC_RC5 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 + */ +#ifdef LTC_CLEAN_STACK +static int s_rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + ulong32 L[64], *S, A, B, i, j, v, s, t, l; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(key != NULL); + + /* test parameters */ + if (num_rounds == 0) { + num_rounds = rc5_desc.default_rounds; + } + + if (num_rounds < 12 || num_rounds > 24) { + return CRYPT_INVALID_ROUNDS; + } + + /* key must be between 64 and 1024 bits */ + if (keylen < 8 || keylen > 128) { + return CRYPT_INVALID_KEYSIZE; + } + + skey->rc5.rounds = num_rounds; + S = skey->rc5.K; + + /* copy the key into the L array */ + for (A = i = j = 0; i < (ulong32)keylen; ) { + A = (A << 8) | ((ulong32)(key[i++] & 255)); + if ((i & 3) == 0) { + L[j++] = BSWAP(A); + A = 0; + } + } + + if ((keylen & 3) != 0) { + A <<= (ulong32)((8 * (4 - (keylen&3)))); + L[j++] = BSWAP(A); + } + + /* setup the S array */ + t = (ulong32)(2 * (num_rounds + 1)); + XMEMCPY(S, stab, t * sizeof(*S)); + + /* mix buffer */ + s = 3 * MAX(t, j); + l = j; + for (A = B = i = j = v = 0; v < s; v++) { + A = S[i] = ROLc(S[i] + A + B, 3); + B = L[j] = ROL(L[j] + A + B, (A+B)); + if (++i == t) { i = 0; } + if (++j == l) { j = 0; } + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + x = s_rc5_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(ulong32) * 122 + sizeof(int)); + return x; +} +#endif + +/** + Encrypts a block of text with LTC_RC5 + @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 +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 A, B; + const ulong32 *K; + int r; + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) { + return CRYPT_INVALID_ROUNDS; + } + + LOAD32L(A, &pt[0]); + LOAD32L(B, &pt[4]); + A += skey->rc5.K[0]; + B += skey->rc5.K[1]; + K = skey->rc5.K + 2; + + if ((skey->rc5.rounds & 1) == 0) { + for (r = 0; r < skey->rc5.rounds; r += 2) { + A = ROL(A ^ B, B) + K[0]; + B = ROL(B ^ A, A) + K[1]; + A = ROL(A ^ B, B) + K[2]; + B = ROL(B ^ A, A) + K[3]; + K += 4; + } + } else { + for (r = 0; r < skey->rc5.rounds; r++) { + A = ROL(A ^ B, B) + K[0]; + B = ROL(B ^ A, A) + K[1]; + K += 2; + } + } + STORE32L(A, &ct[0]); + STORE32L(B, &ct[4]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_rc5_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 2 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with LTC_RC5 + @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 +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 A, B; + const ulong32 *K; + int r; + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) { + return CRYPT_INVALID_ROUNDS; + } + + LOAD32L(A, &ct[0]); + LOAD32L(B, &ct[4]); + K = skey->rc5.K + (skey->rc5.rounds << 1); + + if ((skey->rc5.rounds & 1) == 0) { + K -= 2; + for (r = skey->rc5.rounds - 1; r >= 0; r -= 2) { + B = ROR(B - K[3], A) ^ A; + A = ROR(A - K[2], B) ^ B; + B = ROR(B - K[1], A) ^ A; + A = ROR(A - K[0], B) ^ B; + K -= 4; + } + } else { + for (r = skey->rc5.rounds - 1; r >= 0; r--) { + B = ROR(B - K[1], A) ^ A; + A = ROR(A - K[0], B) ^ B; + K -= 2; + } + } + A -= skey->rc5.K[0]; + B -= skey->rc5.K[1]; + STORE32L(A, &pt[0]); + STORE32L(B, &pt[4]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_rc5_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 2 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the LTC_RC5 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int rc5_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + { + { 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51, + 0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 }, + { 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d }, + { 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 } + }, + { + { 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f, + 0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 }, + { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 }, + { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 } + }, + { + { 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f, + 0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf }, + { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }, + { 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc } + } + }; + unsigned char tmp[2][8]; + int x, y, err; + symmetric_key key; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + rc5_ecb_encrypt(tests[x].pt, tmp[0], &key); + rc5_ecb_decrypt(tmp[0], tmp[1], &key); + + /* compare */ + if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC5 Encrypt", x) != 0 || + compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC5 Decrypt", x) != 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[0][y] = 0; + for (y = 0; y < 1000; y++) rc5_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) rc5_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void rc5_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 rc5_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 128) { + *keysize = 128; + } + return CRYPT_OK; +} + +#endif + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc6.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc6.c new file mode 100644 index 0000000..d1341d3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/rc6.c @@ -0,0 +1,324 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file rc6.c + LTC_RC6 code by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_RC6 + +const struct ltc_cipher_descriptor rc6_desc = +{ + "rc6", + 3, + 8, 128, 16, 20, + &rc6_setup, + &rc6_ecb_encrypt, + &rc6_ecb_decrypt, + &rc6_test, + &rc6_done, + &rc6_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 stab[44] = { +0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, +0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, +0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, +0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, +0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, +0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL }; + + /** + Initialize the LTC_RC6 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 + */ +#ifdef LTC_CLEAN_STACK +static int s_rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + ulong32 L[64], S[50], A, B, i, j, v, s, l; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* test parameters */ + if (num_rounds != 0 && num_rounds != 20) { + return CRYPT_INVALID_ROUNDS; + } + + /* key must be between 64 and 1024 bits */ + if (keylen < 8 || keylen > 128) { + return CRYPT_INVALID_KEYSIZE; + } + + /* copy the key into the L array */ + for (A = i = j = 0; i < (ulong32)keylen; ) { + A = (A << 8) | ((ulong32)(key[i++] & 255)); + if (!(i & 3)) { + L[j++] = BSWAP(A); + A = 0; + } + } + + /* handle odd sized keys */ + if (keylen & 3) { + A <<= (8 * (4 - (keylen&3))); + L[j++] = BSWAP(A); + } + + /* setup the S array */ + XMEMCPY(S, stab, 44 * sizeof(stab[0])); + + /* mix buffer */ + s = 3 * MAX(44, j); + l = j; + for (A = B = i = j = v = 0; v < s; v++) { + A = S[i] = ROLc(S[i] + A + B, 3); + B = L[j] = ROL(L[j] + A + B, (A+B)); + if (++i == 44) { i = 0; } + if (++j == l) { j = 0; } + } + + /* copy to key */ + for (i = 0; i < 44; i++) { + skey->rc6.K[i] = S[i]; + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + x = s_rc6_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(ulong32) * 122); + return x; +} +#endif + +/** + Encrypts a block of text with LTC_RC6 + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,t,u; + const ulong32 *K; + int r; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]); + + b += skey->rc6.K[0]; + d += skey->rc6.K[1]; + +#define RND(a,b,c,d) \ + t = (b * (b + b + 1)); t = ROLc(t, 5); \ + u = (d * (d + d + 1)); u = ROLc(u, 5); \ + a = ROL(a^t,u) + K[0]; \ + c = ROL(c^u,t) + K[1]; K += 2; + + K = skey->rc6.K + 2; + for (r = 0; r < 20; r += 4) { + RND(a,b,c,d); + RND(b,c,d,a); + RND(c,d,a,b); + RND(d,a,b,c); + } + +#undef RND + + a += skey->rc6.K[42]; + c += skey->rc6.K[43]; + STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_rc6_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 6 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with LTC_RC6 + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,t,u; + const ulong32 *K; + int r; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]); + a -= skey->rc6.K[42]; + c -= skey->rc6.K[43]; + +#define RND(a,b,c,d) \ + t = (b * (b + b + 1)); t = ROLc(t, 5); \ + u = (d * (d + d + 1)); u = ROLc(u, 5); \ + c = ROR(c - K[1], t) ^ u; \ + a = ROR(a - K[0], u) ^ t; K -= 2; + + K = skey->rc6.K + 40; + + for (r = 0; r < 20; r += 4) { + RND(d,a,b,c); + RND(c,d,a,b); + RND(b,c,d,a); + RND(a,b,c,d); + } + +#undef RND + + b -= skey->rc6.K[0]; + d -= skey->rc6.K[1]; + STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_rc6_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 6 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the LTC_RC6 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int rc6_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { + 16, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, + 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, + { 0x52, 0x4e, 0x19, 0x2f, 0x47, 0x15, 0xc6, 0x23, + 0x1f, 0x51, 0xf6, 0x36, 0x7e, 0xa4, 0x3f, 0x18 } + }, + { + 24, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, + 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, + { 0x68, 0x83, 0x29, 0xd0, 0x19, 0xe5, 0x05, 0x04, + 0x1e, 0x52, 0xe9, 0x2a, 0xf9, 0x52, 0x91, 0xd4 } + }, + { + 32, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, + 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }, + { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, + 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, + { 0xc8, 0x24, 0x18, 0x16, 0xf0, 0xd7, 0xe4, 0x89, + 0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48 } + } + }; + unsigned char tmp[2][16]; + int x, y, err; + symmetric_key key; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = rc6_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + rc6_ecb_encrypt(tests[x].pt, tmp[0], &key); + rc6_ecb_decrypt(tmp[0], tmp[1], &key); + + /* compare */ + if (compare_testvector(tmp[0], 16, tests[x].ct, 16, "RC6 Encrypt", x) || + compare_testvector(tmp[1], 16, tests[x].pt, 16, "RC6 Decrypt", x)) { + 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++) rc6_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) rc6_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 +} + +/** Terminate the context + @param skey The scheduled key +*/ +void rc6_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 rc6_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 128) { + *keysize = 128; + } + return CRYPT_OK; +} + +#endif /*LTC_RC6*/ + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer.c new file mode 100644 index 0000000..84cc2d0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer.c @@ -0,0 +1,484 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/******************************************************************************* +* +* FILE: safer.c +* +* LTC_DESCRIPTION: block-cipher algorithm LTC_SAFER (Secure And Fast Encryption +* Routine) in its four versions: LTC_SAFER K-64, LTC_SAFER K-128, +* LTC_SAFER SK-64 and LTC_SAFER SK-128. +* +* AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch) +* Signal and Information Processing Laboratory +* Swiss Federal Institute of Technology +* CH-8092 Zuerich, Switzerland +* +* DATE: September 9, 1995 +* +* CHANGE HISTORY: +* +*******************************************************************************/ + +#include "tomcrypt_private.h" + +#ifdef LTC_SAFER + +#define LTC_SAFER_TAB_C +#include "safer_tab.c" + +const struct ltc_cipher_descriptor safer_k64_desc = { + "safer-k64", + 8, 8, 8, 8, LTC_SAFER_K64_DEFAULT_NOF_ROUNDS, + &safer_k64_setup, + &safer_ecb_encrypt, + &safer_ecb_decrypt, + &safer_k64_test, + &safer_done, + &safer_64_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, + + safer_sk64_desc = { + "safer-sk64", + 9, 8, 8, 8, LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS, + &safer_sk64_setup, + &safer_ecb_encrypt, + &safer_ecb_decrypt, + &safer_sk64_test, + &safer_done, + &safer_64_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, + + safer_k128_desc = { + "safer-k128", + 10, 16, 16, 8, LTC_SAFER_K128_DEFAULT_NOF_ROUNDS, + &safer_k128_setup, + &safer_ecb_encrypt, + &safer_ecb_decrypt, + &safer_sk128_test, + &safer_done, + &safer_128_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, + + safer_sk128_desc = { + "safer-sk128", + 11, 16, 16, 8, LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS, + &safer_sk128_setup, + &safer_ecb_encrypt, + &safer_ecb_decrypt, + &safer_sk128_test, + &safer_done, + &safer_128_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }; + +/******************* Constants ************************************************/ +/* #define TAB_LEN 256 */ + +/******************* Assertions ***********************************************/ + +/******************* Macros ***************************************************/ +#define ROL8(x, n) ((unsigned char)((unsigned int)(x) << (n)\ + |(unsigned int)((x) & 0xFF) >> (8 - (n)))) +#define EXP(x) safer_ebox[(x) & 0xFF] +#define LOG(x) safer_lbox[(x) & 0xFF] +#define PHT(x, y) { y += x; x += y; } +#define IPHT(x, y) { x -= y; y -= x; } + +/******************* Types ****************************************************/ + +#ifdef LTC_CLEAN_STACK +static void s_safer_expand_userkey(const unsigned char *userkey_1, + const unsigned char *userkey_2, + unsigned int nof_rounds, + int strengthened, + safer_key_t key) +#else +static void safer_expand_userkey(const unsigned char *userkey_1, + const unsigned char *userkey_2, + unsigned int nof_rounds, + int strengthened, + safer_key_t key) +#endif +{ unsigned int i, j, k; + unsigned char ka[LTC_SAFER_BLOCK_LEN + 1]; + unsigned char kb[LTC_SAFER_BLOCK_LEN + 1]; + + if (LTC_SAFER_MAX_NOF_ROUNDS < nof_rounds) { + nof_rounds = LTC_SAFER_MAX_NOF_ROUNDS; + } + *key++ = (unsigned char)nof_rounds; + ka[LTC_SAFER_BLOCK_LEN] = (unsigned char)0; + kb[LTC_SAFER_BLOCK_LEN] = (unsigned char)0; + k = 0; + for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { + ka[j] = ROL8(userkey_1[j], 5); + ka[LTC_SAFER_BLOCK_LEN] ^= ka[j]; + kb[j] = *key++ = userkey_2[j]; + kb[LTC_SAFER_BLOCK_LEN] ^= kb[j]; + } + for (i = 1; i <= nof_rounds; i++) { + for (j = 0; j < LTC_SAFER_BLOCK_LEN + 1; j++) { + ka[j] = ROL8(ka[j], 6); + kb[j] = ROL8(kb[j], 6); + } + if (strengthened) { + k = 2 * i - 1; + while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; } + } + for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { + if (strengthened) { + *key++ = (ka[k] + + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF; + if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; } + } else { + *key++ = (ka[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF; + } + } + if (strengthened) { + k = 2 * i; + while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; } + } + for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { + if (strengthened) { + *key++ = (kb[k] + + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF; + if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; } + } else { + *key++ = (kb[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF; + } + } + } + +#ifdef LTC_CLEAN_STACK + zeromem(ka, sizeof(ka)); + zeromem(kb, sizeof(kb)); +#endif +} + +#ifdef LTC_CLEAN_STACK +static void safer_expand_userkey(const unsigned char *userkey_1, + const unsigned char *userkey_2, + unsigned int nof_rounds, + int strengthened, + safer_key_t key) +{ + s_safer_expand_userkey(userkey_1, userkey_2, nof_rounds, strengthened, key); + burn_stack(sizeof(unsigned char) * (2 * (LTC_SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2); +} +#endif + +int safer_k64_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 < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 8) { + return CRYPT_INVALID_KEYSIZE; + } + + safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K64_DEFAULT_NOF_ROUNDS), 0, skey->safer.key); + return CRYPT_OK; +} + +int safer_sk64_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 < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 8) { + return CRYPT_INVALID_KEYSIZE; + } + + safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS), 1, skey->safer.key); + return CRYPT_OK; +} + +int safer_k128_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 < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K128_DEFAULT_NOF_ROUNDS), 0, skey->safer.key); + return CRYPT_OK; +} + +int safer_sk128_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 < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0?num_rounds:LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS), 1, skey->safer.key); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_safer_ecb_encrypt(const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +#else +int safer_ecb_encrypt(const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +#endif +{ unsigned char a, b, c, d, e, f, g, h, t; + unsigned int round; + const unsigned char *key; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + key = skey->safer.key; + a = pt[0]; b = pt[1]; c = pt[2]; d = pt[3]; + e = pt[4]; f = pt[5]; g = pt[6]; h = pt[7]; + if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS; + while(round-- > 0) + { + a ^= *++key; b += *++key; c += *++key; d ^= *++key; + e ^= *++key; f += *++key; g += *++key; h ^= *++key; + a = EXP(a) + *++key; b = LOG(b) ^ *++key; + c = LOG(c) ^ *++key; d = EXP(d) + *++key; + e = EXP(e) + *++key; f = LOG(f) ^ *++key; + g = LOG(g) ^ *++key; h = EXP(h) + *++key; + PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h); + PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h); + PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h); + t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t; + } + a ^= *++key; b += *++key; c += *++key; d ^= *++key; + e ^= *++key; f += *++key; g += *++key; h ^= *++key; + ct[0] = a & 0xFF; ct[1] = b & 0xFF; + ct[2] = c & 0xFF; ct[3] = d & 0xFF; + ct[4] = e & 0xFF; ct[5] = f & 0xFF; + ct[6] = g & 0xFF; ct[7] = h & 0xFF; + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int safer_ecb_encrypt(const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +{ + int err = s_safer_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *)); + return err; +} +#endif + +#ifdef LTC_CLEAN_STACK +static int s_safer_ecb_decrypt(const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +#else +int safer_ecb_decrypt(const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +#endif +{ unsigned char a, b, c, d, e, f, g, h, t; + unsigned int round; + const unsigned char *key; + + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(skey != NULL); + + key = skey->safer.key; + a = ct[0]; b = ct[1]; c = ct[2]; d = ct[3]; + e = ct[4]; f = ct[5]; g = ct[6]; h = ct[7]; + if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS; + key += LTC_SAFER_BLOCK_LEN * (1 + 2 * round); + h ^= *key; g -= *--key; f -= *--key; e ^= *--key; + d ^= *--key; c -= *--key; b -= *--key; a ^= *--key; + while (round--) + { + t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t; + IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h); + IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h); + IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h); + h -= *--key; g ^= *--key; f ^= *--key; e -= *--key; + d -= *--key; c ^= *--key; b ^= *--key; a -= *--key; + h = LOG(h) ^ *--key; g = EXP(g) - *--key; + f = EXP(f) - *--key; e = LOG(e) ^ *--key; + d = LOG(d) ^ *--key; c = EXP(c) - *--key; + b = EXP(b) - *--key; a = LOG(a) ^ *--key; + } + pt[0] = a & 0xFF; pt[1] = b & 0xFF; + pt[2] = c & 0xFF; pt[3] = d & 0xFF; + pt[4] = e & 0xFF; pt[5] = f & 0xFF; + pt[6] = g & 0xFF; pt[7] = h & 0xFF; + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int safer_ecb_decrypt(const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +{ + int err = s_safer_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *)); + return err; +} +#endif + +int safer_64_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 8; + return CRYPT_OK; +} + +int safer_128_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + +int safer_k64_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, + k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 }, + k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 }; + + symmetric_key skey; + unsigned char buf[2][8]; + int err; + + /* test K64 */ + if ((err = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) { + return err; + } + safer_ecb_encrypt(k64_pt, buf[0], &skey); + safer_ecb_decrypt(buf[0], buf[1], &skey); + + if (compare_testvector(buf[0], 8, k64_ct, 8, "Safer K64 Encrypt", 0) != 0 || + compare_testvector(buf[1], 8, k64_pt, 8, "Safer K64 Decrypt", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + + +int safer_sk64_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, + sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, + sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 }; + + symmetric_key skey; + unsigned char buf[2][8]; + int err, y; + + /* test SK64 */ + if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) { + return err; + } + + safer_ecb_encrypt(sk64_pt, buf[0], &skey); + safer_ecb_decrypt(buf[0], buf[1], &skey); + + if (compare_testvector(buf[0], 8, sk64_ct, 8, "Safer SK64 Encrypt", 0) != 0 || + compare_testvector(buf[1], 8, sk64_pt, 8, "Safer SK64 Decrypt", 0) != 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++) buf[0][y] = 0; + for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey); + for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey); + for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void safer_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int safer_sk128_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, + sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8, + 0, 0, 0, 0, 0, 0, 0, 0 }, + sk128_ct[] = { 255, 120, 17, 228, 179, 167, 46, 113 }; + + symmetric_key skey; + unsigned char buf[2][8]; + int err, y; + + /* test SK128 */ + if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + safer_ecb_encrypt(sk128_pt, buf[0], &skey); + safer_ecb_decrypt(buf[0], buf[1], &skey); + + if (compare_testvector(buf[0], 8, sk128_ct, 8, "Safer SK128 Encrypt", 0) != 0 || + compare_testvector(buf[1], 8, sk128_pt, 8, "Safer SK128 Decrypt", 0) != 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++) buf[0][y] = 0; + for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey); + for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey); + for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; + #endif +} + +#endif + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer_tab.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer_tab.c new file mode 100644 index 0000000..4cc0e47 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/safer_tab.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file safer_tab.c + Tables for LTC_SAFER block ciphers +*/ + +#ifdef LTC_SAFER_TAB_C + +/* This is the box defined by ebox[x] = 45^x mod 257. + * Its assumed that the value "256" corresponds to zero. */ +static const unsigned char safer_ebox[256] = { + 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63, + 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247, + 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, +255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, +241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, +129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, + 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, + 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217, + 0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194, +249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10, +193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80, + 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126, + 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237, +128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97, +253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5, +225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40 +}; + +/* This is the inverse of ebox or the base 45 logarithm */ +static const unsigned char safer_lbox[256] = { +128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248, +192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130, +112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37, +201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15, + 32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198, +175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84, +121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188, +189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217, +208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158, +210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42, + 95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219, +164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29, + 41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14, +122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104, +109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66, +184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48 +}; + +#endif /* LTC_SAFER_TAB_C */ + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/saferp.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/saferp.c new file mode 100644 index 0000000..86cc708 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/safer/saferp.c @@ -0,0 +1,567 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file saferp.c + LTC_SAFER+ Implementation by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_SAFERP + +#define LTC_SAFER_TAB_C +#include "safer_tab.c" + +const struct ltc_cipher_descriptor saferp_desc = +{ + "safer+", + 4, + 16, 32, 16, 8, + &saferp_setup, + &saferp_ecb_encrypt, + &saferp_ecb_decrypt, + &saferp_test, + &saferp_done, + &saferp_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* ROUND(b,i) + * + * This is one forward key application. Note the basic form is + * key addition, substitution, key addition. The safer_ebox and safer_lbox + * are the exponentiation box and logarithm boxes respectively. + * The value of 'i' is the current round number which allows this + * function to be unrolled massively. Most of LTC_SAFER+'s speed + * comes from not having to compute indirect accesses into the + * array of 16 bytes b[0..15] which is the block of data +*/ + +#define ROUND(b, i) do { \ + b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \ + b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \ + b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \ + b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \ + b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \ + b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \ + b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \ + b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \ + b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \ + b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \ + b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \ + b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \ + b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \ + b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \ + b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \ + b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255; \ +} while (0) + +/* This is one inverse key application */ +#define iROUND(b, i) do { \ + b[0] = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0]; \ + b[1] = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255; \ + b[2] = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255; \ + b[3] = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3]; \ + b[4] = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4]; \ + b[5] = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255; \ + b[6] = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255; \ + b[7] = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7]; \ + b[8] = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8]; \ + b[9] = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255; \ + b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \ + b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11]; \ + b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12]; \ + b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \ + b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \ + b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15]; \ +} while (0) + +/* This is a forward single layer PHT transform. */ +#define PHT(b) do { \ + b[0] = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255; \ + b[2] = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255; \ + b[4] = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255; \ + b[6] = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255; \ + b[8] = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255; \ + b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \ + b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \ + b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255; \ +} while (0) + +/* This is an inverse single layer PHT transform */ +#define iPHT(b) do { \ + b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255; \ + b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255; \ + b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255; \ + b[9] = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255; \ + b[7] = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255; \ + b[5] = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255; \ + b[3] = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255; \ + b[1] = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255; \ + } while (0) + +/* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */ +#define SHUF(b, b2) do { \ + b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \ + b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \ + b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \ + b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3]; \ +} while (0) + +/* This is the inverse shuffle. It takes from b and gives to b2 */ +#define iSHUF(b, b2) do { \ + b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \ + b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \ + b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \ + b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3]; \ +} while (0) + +/* The complete forward Linear Transform layer. + * Note that alternating usage of b and b2. + * Each round of LT starts in 'b' and ends in 'b2'. + */ +#define LT(b, b2) do { \ + PHT(b); SHUF(b, b2); \ + PHT(b2); SHUF(b2, b); \ + PHT(b); SHUF(b, b2); \ + PHT(b2); \ +} while (0) + +/* This is the inverse linear transform layer. */ +#define iLT(b, b2) do { \ + iPHT(b); \ + iSHUF(b, b2); iPHT(b2); \ + iSHUF(b2, b); iPHT(b); \ + iSHUF(b, b2); iPHT(b2); \ +} while (0) + +#ifdef LTC_SMALL_CODE + +static void s_round(unsigned char *b, int i, const symmetric_key *skey) +{ + ROUND(b, i); +} + +static void s_iround(unsigned char *b, int i, const symmetric_key *skey) +{ + iROUND(b, i); +} + +static void s_lt(unsigned char *b, unsigned char *b2) +{ + LT(b, b2); +} + +static void s_ilt(unsigned char *b, unsigned char *b2) +{ + iLT(b, b2); +} + +#undef ROUND +#define ROUND(b, i) s_round(b, i, skey) + +#undef iROUND +#define iROUND(b, i) s_iround(b, i, skey) + +#undef LT +#define LT(b, b2) s_lt(b, b2) + +#undef iLT +#define iLT(b, b2) s_ilt(b, b2) + +#endif + +/* These are the 33, 128-bit bias words for the key schedule */ +static const unsigned char safer_bias[33][16] = { +{ 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172, 100}, +{ 236, 171, 170, 198, 103, 149, 88, 13, 248, 154, 246, 110, 102, 220, 5, 61}, +{ 138, 195, 216, 137, 106, 233, 54, 73, 67, 191, 235, 212, 150, 155, 104, 160}, +{ 93, 87, 146, 31, 213, 113, 92, 187, 34, 193, 190, 123, 188, 153, 99, 148}, +{ 42, 97, 184, 52, 50, 25, 253, 251, 23, 64, 230, 81, 29, 65, 68, 143}, +{ 221, 4, 128, 222, 231, 49, 214, 127, 1, 162, 247, 57, 218, 111, 35, 202}, +{ 58, 208, 28, 209, 48, 62, 18, 161, 205, 15, 224, 168, 175, 130, 89, 44}, +{ 125, 173, 178, 239, 194, 135, 206, 117, 6, 19, 2, 144, 79, 46, 114, 51}, +{ 192, 141, 207, 169, 129, 226, 196, 39, 47, 108, 122, 159, 82, 225, 21, 56}, +{ 252, 32, 66, 199, 8, 228, 9, 85, 94, 140, 20, 118, 96, 255, 223, 215}, +{ 250, 11, 33, 0, 26, 249, 166, 185, 232, 158, 98, 76, 217, 145, 80, 210}, +{ 24, 180, 7, 132, 234, 91, 164, 200, 14, 203, 72, 105, 75, 78, 156, 53}, +{ 69, 77, 84, 229, 37, 60, 12, 74, 139, 63, 204, 167, 219, 107, 174, 244}, +{ 45, 243, 124, 109, 157, 181, 38, 116, 242, 147, 83, 176, 240, 17, 237, 131}, +{ 182, 3, 22, 115, 59, 30, 142, 112, 189, 134, 27, 71, 126, 36, 86, 241}, +{ 136, 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172}, +{ 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239}, +{ 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202}, +{ 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246}, +{ 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152}, +{ 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236}, +{ 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150}, +{ 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30}, +{ 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6}, +{ 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104}, +{ 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175}, +{ 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35}, +{ 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7}, +{ 40, 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207}, +{ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247}, +{ 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255}, +{ 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51}}; + + /** + Initialize the LTC_SAFER+ 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 saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + unsigned x, y, z; + unsigned char t[33]; + static const int rounds[3] = { 8, 12, 16 }; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* check arguments */ + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + /* Is the number of rounds valid? Either use zero for default or + * 8,12,16 rounds for 16,24,32 byte keys + */ + if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) { + return CRYPT_INVALID_ROUNDS; + } + + /* 128 bit key version */ + if (keylen == 16) { + /* copy key into t */ + for (x = y = 0; x < 16; x++) { + t[x] = key[x]; + y ^= key[x]; + } + t[16] = y; + + /* make round keys */ + for (x = 0; x < 16; x++) { + skey->saferp.K[0][x] = t[x]; + } + + /* make the 16 other keys as a transformation of the first key */ + for (x = 1; x < 17; x++) { + /* rotate 3 bits each */ + for (y = 0; y < 17; y++) { + t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; + } + + /* select and add */ + z = x; + for (y = 0; y < 16; y++) { + skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; + if (++z == 17) { z = 0; } + } + } + skey->saferp.rounds = 8; + } else if (keylen == 24) { + /* copy key into t */ + for (x = y = 0; x < 24; x++) { + t[x] = key[x]; + y ^= key[x]; + } + t[24] = y; + + /* make round keys */ + for (x = 0; x < 16; x++) { + skey->saferp.K[0][x] = t[x]; + } + + for (x = 1; x < 25; x++) { + /* rotate 3 bits each */ + for (y = 0; y < 25; y++) { + t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; + } + + /* select and add */ + z = x; + for (y = 0; y < 16; y++) { + skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; + if (++z == 25) { z = 0; } + } + } + skey->saferp.rounds = 12; + } else { + /* copy key into t */ + for (x = y = 0; x < 32; x++) { + t[x] = key[x]; + y ^= key[x]; + } + t[32] = y; + + /* make round keys */ + for (x = 0; x < 16; x++) { + skey->saferp.K[0][x] = t[x]; + } + + for (x = 1; x < 33; x++) { + /* rotate 3 bits each */ + for (y = 0; y < 33; y++) { + t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; + } + + /* select and add */ + z = x; + for (y = 0; y < 16; y++) { + skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; + if (++z == 33) { z = 0; } + } + } + skey->saferp.rounds = 16; + } +#ifdef LTC_CLEAN_STACK + zeromem(t, sizeof(t)); +#endif + return CRYPT_OK; +} + +/** + Encrypts a block of text with LTC_SAFER+ + @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 +*/ +int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + unsigned char b[16]; + int x; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) { + return CRYPT_INVALID_ROUNDS; + } + + /* do eight rounds */ + for (x = 0; x < 16; x++) { + b[x] = pt[x]; + } + ROUND(b, 0); LT(b, ct); + ROUND(ct, 2); LT(ct, b); + ROUND(b, 4); LT(b, ct); + ROUND(ct, 6); LT(ct, b); + ROUND(b, 8); LT(b, ct); + ROUND(ct, 10); LT(ct, b); + ROUND(b, 12); LT(b, ct); + ROUND(ct, 14); LT(ct, b); + /* 192-bit key? */ + if (skey->saferp.rounds > 8) { + ROUND(b, 16); LT(b, ct); + ROUND(ct, 18); LT(ct, b); + ROUND(b, 20); LT(b, ct); + ROUND(ct, 22); LT(ct, b); + } + /* 256-bit key? */ + if (skey->saferp.rounds > 12) { + ROUND(b, 24); LT(b, ct); + ROUND(ct, 26); LT(ct, b); + ROUND(b, 28); LT(b, ct); + ROUND(ct, 30); LT(ct, b); + } + ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; + ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255; + ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255; + ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; + ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; + ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255; + ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255; + ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; + ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; + ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255; + ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255; + ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; + ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; + ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255; + ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255; + ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; +#ifdef LTC_CLEAN_STACK + zeromem(b, sizeof(b)); +#endif + return CRYPT_OK; +} + +/** + Decrypts a block of text with LTC_SAFER+ + @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 +*/ +int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + unsigned char b[16]; + int x; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) { + return CRYPT_INVALID_ROUNDS; + } + + /* do eight rounds */ + b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; + b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255; + b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255; + b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; + b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; + b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255; + b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255; + b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; + b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; + b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255; + b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255; + b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; + b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; + b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255; + b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255; + b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; + /* 256-bit key? */ + if (skey->saferp.rounds > 12) { + iLT(b, pt); iROUND(pt, 30); + iLT(pt, b); iROUND(b, 28); + iLT(b, pt); iROUND(pt, 26); + iLT(pt, b); iROUND(b, 24); + } + /* 192-bit key? */ + if (skey->saferp.rounds > 8) { + iLT(b, pt); iROUND(pt, 22); + iLT(pt, b); iROUND(b, 20); + iLT(b, pt); iROUND(pt, 18); + iLT(pt, b); iROUND(b, 16); + } + iLT(b, pt); iROUND(pt, 14); + iLT(pt, b); iROUND(b, 12); + iLT(b, pt); iROUND(pt,10); + iLT(pt, b); iROUND(b, 8); + iLT(b, pt); iROUND(pt,6); + iLT(pt, b); iROUND(b, 4); + iLT(b, pt); iROUND(pt,2); + iLT(pt, b); iROUND(b, 0); + for (x = 0; x < 16; x++) { + pt[x] = b[x]; + } +#ifdef LTC_CLEAN_STACK + zeromem(b, sizeof(b)); +#endif + return CRYPT_OK; +} + +/** + Performs a self-test of the LTC_SAFER+ block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int saferp_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { + 16, + { 41, 35, 190, 132, 225, 108, 214, 174, + 82, 144, 73, 241, 241, 187, 233, 235 }, + { 179, 166, 219, 60, 135, 12, 62, 153, + 36, 94, 13, 28, 6, 183, 71, 222 }, + { 224, 31, 182, 10, 12, 255, 84, 70, + 127, 13, 89, 249, 9, 57, 165, 220 } + }, { + 24, + { 72, 211, 143, 117, 230, 217, 29, 42, + 229, 192, 247, 43, 120, 129, 135, 68, + 14, 95, 80, 0, 212, 97, 141, 190 }, + { 123, 5, 21, 7, 59, 51, 130, 31, + 24, 112, 146, 218, 100, 84, 206, 177 }, + { 92, 136, 4, 63, 57, 95, 100, 0, + 150, 130, 130, 16, 193, 111, 219, 133 } + }, { + 32, + { 243, 168, 141, 254, 190, 242, 235, 113, + 255, 160, 208, 59, 117, 6, 140, 126, + 135, 120, 115, 77, 208, 190, 130, 190, + 219, 194, 70, 65, 43, 140, 250, 48 }, + { 127, 112, 240, 167, 84, 134, 50, 149, + 170, 91, 104, 19, 11, 230, 252, 245 }, + { 88, 11, 25, 36, 172, 229, 202, 213, + 170, 65, 105, 153, 220, 104, 153, 138 } + } + }; + + unsigned char tmp[2][16]; + symmetric_key skey; + int err, i, y; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) { + return err; + } + saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey); + saferp_ecb_decrypt(tmp[0], tmp[1], &skey); + + /* compare */ + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Safer+ Encrypt", i) || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "Safer+ Decrypt", i)) { + 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++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void saferp_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 saferp_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + } else if (*keysize < 32) { + *keysize = 24; + } else { + *keysize = 32; + } + return CRYPT_OK; +} + +#endif + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/serpent.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/serpent.c new file mode 100644 index 0000000..dbb999e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/serpent.c @@ -0,0 +1,717 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Based on serpent.cpp - originally written and placed in the public domain by Wei Dai + https://github.com/weidai11/cryptopp/blob/master/serpent.cpp + + On 2017-10-16 wikipedia says: + "The Serpent cipher algorithm is in the public domain and has not been patented." + https://en.wikipedia.org/wiki/Serpent_(cipher) + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SERPENT + +const struct ltc_cipher_descriptor serpent_desc = { + "serpent", + 25, /* cipher_ID */ + 16, 32, 16, 32, /* min_key_len, max_key_len, block_len, default_rounds */ + &serpent_setup, + &serpent_ecb_encrypt, + &serpent_ecb_decrypt, + &serpent_test, + &serpent_done, + &serpent_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* linear transformation */ +#define s_lt(i,a,b,c,d,e) { \ + a = ROLc(a, 13); \ + c = ROLc(c, 3); \ + d = ROLc(d ^ c ^ (a << 3), 7); \ + b = ROLc(b ^ a ^ c, 1); \ + a = ROLc(a ^ b ^ d, 5); \ + c = ROLc(c ^ d ^ (b << 7), 22); \ + } + +/* inverse linear transformation */ +#define s_ilt(i,a,b,c,d,e) { \ + c = RORc(c, 22); \ + a = RORc(a, 5); \ + c ^= d ^ (b << 7); \ + a ^= b ^ d; \ + b = RORc(b, 1); \ + d = RORc(d, 7) ^ c ^ (a << 3); \ + b ^= a ^ c; \ + c = RORc(c, 3); \ + a = RORc(a, 13); \ + } + +/* order of output from S-box functions */ +#define s_beforeS0(f) f(0,a,b,c,d,e) +#define s_afterS0(f) f(1,b,e,c,a,d) +#define s_afterS1(f) f(2,c,b,a,e,d) +#define s_afterS2(f) f(3,a,e,b,d,c) +#define s_afterS3(f) f(4,e,b,d,c,a) +#define s_afterS4(f) f(5,b,a,e,c,d) +#define s_afterS5(f) f(6,a,c,b,e,d) +#define s_afterS6(f) f(7,a,c,d,b,e) +#define s_afterS7(f) f(8,d,e,b,a,c) + +/* order of output from inverse S-box functions */ +#define s_beforeI7(f) f(8,a,b,c,d,e) +#define s_afterI7(f) f(7,d,a,b,e,c) +#define s_afterI6(f) f(6,a,b,c,e,d) +#define s_afterI5(f) f(5,b,d,e,c,a) +#define s_afterI4(f) f(4,b,c,e,a,d) +#define s_afterI3(f) f(3,a,b,e,c,d) +#define s_afterI2(f) f(2,b,d,e,c,a) +#define s_afterI1(f) f(1,a,b,c,e,d) +#define s_afterI0(f) f(0,a,d,b,e,c) + +/* The instruction sequences for the S-box functions + * come from Dag Arne Osvik's paper "Speeding up Serpent". + */ + +#define s_s0(i, r0, r1, r2, r3, r4) { \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r4 ^= r2; \ + r1 ^= r0; \ + r0 |= r3; \ + r0 ^= r4; \ + r4 ^= r3; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 ^= r4; \ + r4 = ~r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r1 ^= r4; \ + r3 |= r0; \ + r1 ^= r3; \ + r4 ^= r3; \ +} + +#define s_i0(i, r0, r1, r2, r3, r4) { \ + r2 = ~r2; \ + r4 = r1; \ + r1 |= r0; \ + r4 = ~r4; \ + r1 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 &= r3; \ + r4 ^= r0; \ + r0 |= r1; \ + r0 ^= r2; \ + r3 ^= r4; \ + r2 ^= r1; \ + r3 ^= r0; \ + r3 ^= r1; \ + r2 &= r3; \ + r4 ^= r2; \ +} + +#define s_s1(i, r0, r1, r2, r3, r4) { \ + r0 = ~r0; \ + r2 = ~r2; \ + r4 = r0; \ + r0 &= r1; \ + r2 ^= r0; \ + r0 |= r3; \ + r3 ^= r2; \ + r1 ^= r0; \ + r0 ^= r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r2 |= r0; \ + r2 &= r4; \ + r0 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r2; \ + r0 ^= r4; \ +} + +#define s_i1(i, r0, r1, r2, r3, r4) { \ + r4 = r1; \ + r1 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r3 ^= r0; \ + r0 |= r1; \ + r2 ^= r3; \ + r0 ^= r4; \ + r0 |= r2; \ + r1 ^= r3; \ + r0 ^= r1; \ + r1 |= r3; \ + r1 ^= r0; \ + r4 = ~r4; \ + r4 ^= r1; \ + r1 |= r0; \ + r1 ^= r0; \ + r1 |= r4; \ + r3 ^= r1; \ +} + +#define s_s2(i, r0, r1, r2, r3, r4) { \ + r4 = r0; \ + r0 &= r2; \ + r0 ^= r3; \ + r2 ^= r1; \ + r2 ^= r0; \ + r3 |= r4; \ + r3 ^= r1; \ + r4 ^= r2; \ + r1 = r3; \ + r3 |= r4; \ + r3 ^= r0; \ + r0 &= r1; \ + r4 ^= r0; \ + r1 ^= r3; \ + r1 ^= r4; \ + r4 = ~r4; \ +} + +#define s_i2(i, r0, r1, r2, r3, r4) { \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r3; \ + r3 &= r2; \ + r3 ^= r1; \ + r1 |= r2; \ + r1 ^= r4; \ + r4 &= r3; \ + r2 ^= r3; \ + r4 &= r0; \ + r4 ^= r2; \ + r2 &= r1; \ + r2 |= r0; \ + r3 = ~r3; \ + r2 ^= r3; \ + r0 ^= r3; \ + r0 &= r1; \ + r3 ^= r4; \ + r3 ^= r0; \ +} + +#define s_s3(i, r0, r1, r2, r3, r4) { \ + r4 = r0; \ + r0 |= r3; \ + r3 ^= r1; \ + r1 &= r4; \ + r4 ^= r2; \ + r2 ^= r3; \ + r3 &= r0; \ + r4 |= r1; \ + r3 ^= r4; \ + r0 ^= r1; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r2; \ + r1 |= r0; \ + r1 ^= r2; \ + r0 ^= r3; \ + r2 = r1; \ + r1 |= r3; \ + r1 ^= r0; \ +} + +#define s_i3(i, r0, r1, r2, r3, r4) { \ + r4 = r2; \ + r2 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r4; \ + r4 ^= r3; \ + r3 |= r1; \ + r3 ^= r2; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 |= r3; \ + r0 ^= r1; \ + r4 ^= r2; \ + r2 &= r3; \ + r1 |= r3; \ + r1 ^= r2; \ + r4 ^= r0; \ + r2 ^= r4; \ +} + +#define s_s4(i, r0, r1, r2, r3, r4) { \ + r1 ^= r3; \ + r3 = ~r3; \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r1 ^= r2; \ + r4 ^= r3; \ + r0 ^= r4; \ + r2 &= r4; \ + r2 ^= r0; \ + r0 &= r1; \ + r3 ^= r0; \ + r4 |= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r2 &= r3; \ + r0 = ~r0; \ + r4 ^= r2; \ +} + +#define s_i4(i, r0, r1, r2, r3, r4) { \ + r4 = r2; \ + r2 &= r3; \ + r2 ^= r1; \ + r1 |= r3; \ + r1 &= r0; \ + r4 ^= r2; \ + r4 ^= r1; \ + r1 &= r2; \ + r0 = ~r0; \ + r3 ^= r4; \ + r1 ^= r3; \ + r3 &= r0; \ + r3 ^= r2; \ + r0 ^= r1; \ + r2 &= r0; \ + r3 ^= r0; \ + r2 ^= r4; \ + r2 |= r3; \ + r3 ^= r0; \ + r2 ^= r1; \ +} + +#define s_s5(i, r0, r1, r2, r3, r4) { \ + r0 ^= r1; \ + r1 ^= r3; \ + r3 = ~r3; \ + r4 = r1; \ + r1 &= r0; \ + r2 ^= r3; \ + r1 ^= r2; \ + r2 |= r4; \ + r4 ^= r3; \ + r3 &= r1; \ + r3 ^= r0; \ + r4 ^= r1; \ + r4 ^= r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r0 ^= r4; \ + r4 |= r3; \ + r2 ^= r4; \ +} + +#define s_i5(i, r0, r1, r2, r3, r4) { \ + r1 = ~r1; \ + r4 = r3; \ + r2 ^= r1; \ + r3 |= r0; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 ^= r4; \ + r4 |= r0; \ + r4 ^= r1; \ + r1 &= r2; \ + r1 ^= r3; \ + r4 ^= r2; \ + r3 &= r4; \ + r4 ^= r1; \ + r3 ^= r0; \ + r3 ^= r4; \ + r4 = ~r4; \ +} + +#define s_s6(i, r0, r1, r2, r3, r4) { \ + r2 = ~r2; \ + r4 = r3; \ + r3 &= r0; \ + r0 ^= r4; \ + r3 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r2 ^= r0; \ + r0 |= r1; \ + r2 ^= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r4 ^= r3; \ + r4 ^= r0; \ + r3 = ~r3; \ + r2 &= r4; \ + r2 ^= r3; \ +} + +#define s_i6(i, r0, r1, r2, r3, r4) { \ + r0 ^= r2; \ + r4 = r2; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 = ~r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r4 |= r0; \ + r0 ^= r2; \ + r3 ^= r4; \ + r4 ^= r1; \ + r1 &= r3; \ + r1 ^= r0; \ + r0 ^= r3; \ + r0 |= r2; \ + r3 ^= r1; \ + r4 ^= r0; \ +} + +#define s_s7(i, r0, r1, r2, r3, r4) { \ + r4 = r2; \ + r2 &= r1; \ + r2 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r2 ^= r1; \ + r1 ^= r0; \ + r0 |= r4; \ + r0 ^= r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r3 &= r0; \ + r3 ^= r4; \ + r4 ^= r2; \ + r2 &= r0; \ + r4 = ~r4; \ + r2 ^= r4; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r1; \ +} + +#define s_i7(i, r0, r1, r2, r3, r4) { \ + r4 = r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r4 |= r3; \ + r3 ^= r1; \ + r1 |= r0; \ + r0 ^= r2; \ + r2 &= r4; \ + r1 ^= r2; \ + r2 ^= r0; \ + r0 |= r2; \ + r3 &= r4; \ + r0 ^= r3; \ + r4 ^= r1; \ + r3 ^= r4; \ + r4 |= r0; \ + r3 ^= r2; \ + r4 ^= r2; \ +} + +/* key xor */ +#define s_kx(r, a, b, c, d, e) { \ + a ^= k[4 * r + 0]; \ + b ^= k[4 * r + 1]; \ + c ^= k[4 * r + 2]; \ + d ^= k[4 * r + 3]; \ +} + +#define s_lk(r, a, b, c, d, e) { \ + a = k[(8-r)*4 + 0]; \ + b = k[(8-r)*4 + 1]; \ + c = k[(8-r)*4 + 2]; \ + d = k[(8-r)*4 + 3]; \ +} + +#define s_sk(r, a, b, c, d, e) { \ + k[(8-r)*4 + 4] = a; \ + k[(8-r)*4 + 5] = b; \ + k[(8-r)*4 + 6] = c; \ + k[(8-r)*4 + 7] = d; \ +} + +static int s_setup_key(const unsigned char *key, int keylen, int rounds, ulong32 *k) +{ + int i; + ulong32 t; + ulong32 k0[8] = { 0 }; /* zero-initialize */ + ulong32 a, b, c, d, e; + + for (i = 0; i < 8 && i < keylen/4; ++i) { + LOAD32L(k0[i], key + i * 4); + } + if (keylen < 32) { + k0[keylen/4] |= (ulong32)1 << ((keylen%4)*8); + } + + t = k0[7]; + for (i = 0; i < 8; ++i) { + k[i] = k0[i] = t = ROLc(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11); + } + for (i = 8; i < 4*(rounds+1); ++i) { + k[i] = t = ROLc(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); + } + k -= 20; + + for (i = 0; i < rounds/8; i++) { + s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk); + s_afterS1(s_lk); s_afterS1(s_s2); s_afterS2(s_sk); + s_afterS0(s_lk); s_afterS0(s_s1); s_afterS1(s_sk); + s_beforeS0(s_lk); s_beforeS0(s_s0); s_afterS0(s_sk); + k += 8*4; + s_afterS6(s_lk); s_afterS6(s_s7); s_afterS7(s_sk); + s_afterS5(s_lk); s_afterS5(s_s6); s_afterS6(s_sk); + s_afterS4(s_lk); s_afterS4(s_s5); s_afterS5(s_sk); + s_afterS3(s_lk); s_afterS3(s_s4); s_afterS4(s_sk); + } + s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk); + + return CRYPT_OK; +} + +static int s_enc_block(const unsigned char *in, unsigned char *out, const ulong32 *k) +{ + ulong32 a, b, c, d, e; + unsigned int i = 1; + + LOAD32L(a, in + 0); + LOAD32L(b, in + 4); + LOAD32L(c, in + 8); + LOAD32L(d, in + 12); + + do { + s_beforeS0(s_kx); s_beforeS0(s_s0); s_afterS0(s_lt); + s_afterS0(s_kx); s_afterS0(s_s1); s_afterS1(s_lt); + s_afterS1(s_kx); s_afterS1(s_s2); s_afterS2(s_lt); + s_afterS2(s_kx); s_afterS2(s_s3); s_afterS3(s_lt); + s_afterS3(s_kx); s_afterS3(s_s4); s_afterS4(s_lt); + s_afterS4(s_kx); s_afterS4(s_s5); s_afterS5(s_lt); + s_afterS5(s_kx); s_afterS5(s_s6); s_afterS6(s_lt); + s_afterS6(s_kx); s_afterS6(s_s7); + + if (i == 4) break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + s_beforeS0(s_lt); + } while (1); + + s_afterS7(s_kx); + + STORE32L(d, out + 0); + STORE32L(e, out + 4); + STORE32L(b, out + 8); + STORE32L(a, out + 12); + + return CRYPT_OK; +} + +static int s_dec_block(const unsigned char *in, unsigned char *out, const ulong32 *k) +{ + ulong32 a, b, c, d, e; + unsigned int i; + + LOAD32L(a, in + 0); + LOAD32L(b, in + 4); + LOAD32L(c, in + 8); + LOAD32L(d, in + 12); + e = 0; LTC_UNUSED_PARAM(e); /* avoid scan-build warning */ + i = 4; + k += 96; + + s_beforeI7(s_kx); + goto start; + + do { + c = b; + b = d; + d = e; + k -= 32; + s_beforeI7(s_ilt); +start: + s_beforeI7(s_i7); s_afterI7(s_kx); + s_afterI7(s_ilt); s_afterI7(s_i6); s_afterI6(s_kx); + s_afterI6(s_ilt); s_afterI6(s_i5); s_afterI5(s_kx); + s_afterI5(s_ilt); s_afterI5(s_i4); s_afterI4(s_kx); + s_afterI4(s_ilt); s_afterI4(s_i3); s_afterI3(s_kx); + s_afterI3(s_ilt); s_afterI3(s_i2); s_afterI2(s_kx); + s_afterI2(s_ilt); s_afterI2(s_i1); s_afterI1(s_kx); + s_afterI1(s_ilt); s_afterI1(s_i0); s_afterI0(s_kx); + } while (--i != 0); + + STORE32L(a, out + 0); + STORE32L(d, out + 4); + STORE32L(b, out + 8); + STORE32L(e, out + 12); + + return CRYPT_OK; +} + +int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && num_rounds != 32) return CRYPT_INVALID_ROUNDS; + if (keylen != 16 && keylen != 24 && keylen != 32) return CRYPT_INVALID_KEYSIZE; + + err = s_setup_key(key, keylen, 32, skey->serpent.k); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ulong32) * 14 + sizeof(int)); +#endif + return err; +} + +int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_enc_block(pt, ct, skey->serpent.k); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ulong32) * 5 + sizeof(int)); +#endif + return err; +} + +int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_dec_block(ct, pt, skey->serpent.k); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ulong32) * 5 + sizeof(int)); +#endif + return err; +} + +void serpent_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int serpent_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize >= 32) { *keysize = 32; } + else if (*keysize >= 24) { *keysize = 24; } + else if (*keysize >= 16) { *keysize = 16; } + else return CRYPT_INVALID_KEYSIZE; + return CRYPT_OK; +} + +int serpent_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[32]; + int keylen; + unsigned char pt[16], ct[16]; + } tests[] = { + { + /* key */ {0x80,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}, + /* keylen */ 32, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0xA2,0x23,0xAA,0x12,0x88,0x46,0x3C,0x0E,0x2B,0xE3,0x8E,0xBD,0x82,0x56,0x16,0xC0} + }, + { + /* key */ {0x40,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}, + /* keylen */ 32, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0xEA,0xE1,0xD4,0x05,0x57,0x01,0x74,0xDF,0x7D,0xF2,0xF9,0x96,0x6D,0x50,0x91,0x59} + }, + { + /* key */ {0x20,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}, + /* keylen */ 32, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x65,0xF3,0x76,0x84,0x47,0x1E,0x92,0x1D,0xC8,0xA3,0x0F,0x45,0xB4,0x3C,0x44,0x99} + }, + { + /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 24, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x9E,0x27,0x4E,0xAD,0x9B,0x73,0x7B,0xB2,0x1E,0xFC,0xFC,0xA5,0x48,0x60,0x26,0x89} + }, + { + /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 24, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x92,0xFC,0x8E,0x51,0x03,0x99,0xE4,0x6A,0x04,0x1B,0xF3,0x65,0xE7,0xB3,0xAE,0x82} + }, + { + /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 24, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x5E,0x0D,0xA3,0x86,0xC4,0x6A,0xD4,0x93,0xDE,0xA2,0x03,0xFD,0xC6,0xF5,0x7D,0x70} + }, + { + /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 16, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x26,0x4E,0x54,0x81,0xEF,0xF4,0x2A,0x46,0x06,0xAB,0xDA,0x06,0xC0,0xBF,0xDA,0x3D} + }, + { + /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 16, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x4A,0x23,0x1B,0x3B,0xC7,0x27,0x99,0x34,0x07,0xAC,0x6E,0xC8,0x35,0x0E,0x85,0x24} + }, + { + /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 16, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0xE0,0x32,0x69,0xF9,0xE9,0xFD,0x85,0x3C,0x7D,0x81,0x56,0xDF,0x14,0xB9,0x8D,0x56} + } + }; + + unsigned char buf[2][16]; + symmetric_key key; + int err, x; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = serpent_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + if ((err = serpent_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[0], 16, tests[x].ct, 16, "SERPENT Encrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = serpent_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[1], 16, tests[x].pt, 16, "SERPENT Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/skipjack.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/skipjack.c new file mode 100644 index 0000000..0251946 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/skipjack.c @@ -0,0 +1,334 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file skipjack.c + Skipjack Implementation by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_SKIPJACK + +const struct ltc_cipher_descriptor skipjack_desc = +{ + "skipjack", + 17, + 10, 10, 8, 32, + &skipjack_setup, + &skipjack_ecb_encrypt, + &skipjack_ecb_decrypt, + &skipjack_test, + &skipjack_done, + &skipjack_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const unsigned char sbox[256] = { + 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9, + 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28, + 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53, + 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2, + 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8, + 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90, + 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76, + 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d, + 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18, + 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4, + 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40, + 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5, + 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2, + 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8, + 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac, + 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46 +}; + +/* simple x + 1 (mod 10) in one step. */ +static const int keystep[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + +/* simple x - 1 (mod 10) in one step */ +static const int ikeystep[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + + /** + Initialize the Skipjack 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 skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 10) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 32 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + /* make sure the key is in range for platforms where CHAR_BIT != 8 */ + for (x = 0; x < 10; x++) { + skey->skipjack.key[x] = key[x] & 255; + } + + return CRYPT_OK; +} + +#define RULE_A \ + tmp = g_func(w1, &kp, skey->skipjack.key); \ + w1 = tmp ^ w4 ^ x; \ + w4 = w3; w3 = w2; \ + w2 = tmp; + +#define RULE_B \ + tmp = g_func(w1, &kp, skey->skipjack.key); \ + tmp1 = w4; w4 = w3; \ + w3 = w1 ^ w2 ^ x; \ + w1 = tmp1; w2 = tmp; + +#define RULE_A1 \ + tmp = w1 ^ w2 ^ x; \ + w1 = ig_func(w2, &kp, skey->skipjack.key); \ + w2 = w3; w3 = w4; w4 = tmp; + +#define RULE_B1 \ + tmp = ig_func(w2, &kp, skey->skipjack.key); \ + w2 = tmp ^ w3 ^ x; \ + w3 = w4; w4 = w1; w1 = tmp; + +static unsigned g_func(unsigned w, int *kp, const unsigned char *key) +{ + unsigned char g1,g2; + + g1 = (w >> 8) & 255; g2 = w & 255; + g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; + g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; + g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; + g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; + return ((unsigned)g1<<8)|(unsigned)g2; +} + +static unsigned ig_func(unsigned w, int *kp, const unsigned char *key) +{ + unsigned char g1,g2; + + g1 = (w >> 8) & 255; g2 = w & 255; + *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; + *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; + *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; + *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; + return ((unsigned)g1<<8)|(unsigned)g2; +} + +/** + Encrypts a block of text with Skipjack + @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 +*/ +#ifdef LTC_CLEAN_STACK +static int s_skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + unsigned w1,w2,w3,w4,tmp,tmp1; + int x, kp; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + /* load block */ + w1 = ((unsigned)pt[0]<<8)|pt[1]; + w2 = ((unsigned)pt[2]<<8)|pt[3]; + w3 = ((unsigned)pt[4]<<8)|pt[5]; + w4 = ((unsigned)pt[6]<<8)|pt[7]; + + /* 8 rounds of RULE A */ + for (x = 1, kp = 0; x < 9; x++) { + RULE_A; + } + + /* 8 rounds of RULE B */ + for (; x < 17; x++) { + RULE_B; + } + + /* 8 rounds of RULE A */ + for (; x < 25; x++) { + RULE_A; + } + + /* 8 rounds of RULE B */ + for (; x < 33; x++) { + RULE_B; + } + + /* store block */ + ct[0] = (w1>>8)&255; ct[1] = w1&255; + ct[2] = (w2>>8)&255; ct[3] = w2&255; + ct[4] = (w3>>8)&255; ct[5] = w3&255; + ct[6] = (w4>>8)&255; ct[7] = w4&255; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_skipjack_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned) * 8 + sizeof(int) * 2); + return err; +} +#endif + +/** + Decrypts a block of text with Skipjack + @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 +*/ +#ifdef LTC_CLEAN_STACK +static int s_skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + unsigned w1,w2,w3,w4,tmp; + int x, kp; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + /* load block */ + w1 = ((unsigned)ct[0]<<8)|ct[1]; + w2 = ((unsigned)ct[2]<<8)|ct[3]; + w3 = ((unsigned)ct[4]<<8)|ct[5]; + w4 = ((unsigned)ct[6]<<8)|ct[7]; + + /* 8 rounds of RULE B^-1 + + Note the value "kp = 8" comes from "kp = (32 * 4) mod 10" where 32*4 is 128 which mod 10 is 8 + */ + for (x = 32, kp = 8; x > 24; x--) { + RULE_B1; + } + + /* 8 rounds of RULE A^-1 */ + for (; x > 16; x--) { + RULE_A1; + } + + + /* 8 rounds of RULE B^-1 */ + for (; x > 8; x--) { + RULE_B1; + } + + /* 8 rounds of RULE A^-1 */ + for (; x > 0; x--) { + RULE_A1; + } + + /* store block */ + pt[0] = (w1>>8)&255; pt[1] = w1&255; + pt[2] = (w2>>8)&255; pt[3] = w2&255; + pt[4] = (w3>>8)&255; pt[5] = w3&255; + pt[6] = (w4>>8)&255; pt[7] = w4&255; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_skipjack_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned) * 7 + sizeof(int) * 2); + return err; +} +#endif + +/** + Performs a self-test of the Skipjack block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int skipjack_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + unsigned char key[10], pt[8], ct[8]; + } tests[] = { + { + { 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, + { 0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa }, + { 0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00 } + } + }; + unsigned char buf[2][8]; + int x, y, err; + symmetric_key key; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = skipjack_setup(tests[x].key, 10, 0, &key)) != CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + skipjack_ecb_encrypt(tests[x].pt, buf[0], &key); + skipjack_ecb_decrypt(buf[0], buf[1], &key); + + /* compare */ + if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Skipjack Encrypt", x) != 0 || + compare_testvector(buf[1], 8, tests[x].pt, 8, "Skipjack Decrypt", x) != 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++) buf[0][y] = 0; + for (y = 0; y < 1000; y++) skipjack_ecb_encrypt(buf[0], buf[0], &key); + for (y = 0; y < 1000; y++) skipjack_ecb_decrypt(buf[0], buf[0], &key); + for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void skipjack_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 skipjack_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 10) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 10) { + *keysize = 10; + } + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/sub.mk new file mode 100644 index 0000000..78cf037 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/sub.mk @@ -0,0 +1,2 @@ +subdirs-$(call cfg-one-enabled, _CFG_CORE_LTC_AES _CFG_CORE_LTC_AES_DESC) += aes +srcs-$(_CFG_CORE_LTC_DES) += des.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/tea.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/tea.c new file mode 100644 index 0000000..fc413d4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/tea.c @@ -0,0 +1,209 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file tea.c + Implementation of TEA, Steffen Jaeckel +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_TEA + +const struct ltc_cipher_descriptor tea_desc = +{ + "tea", + 26, + 16, 16, 8, 32, + &tea_setup, + &tea_ecb_encrypt, + &tea_ecb_decrypt, + &tea_test, + &tea_done, + &tea_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#define DELTA 0x9E3779B9uL +#define SUM 0xC6EF3720uL + +int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* check arguments */ + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != 32) { + return CRYPT_INVALID_ROUNDS; + } + + /* load key */ + LOAD32H(skey->tea.k[0], key+0); + LOAD32H(skey->tea.k[1], key+4); + LOAD32H(skey->tea.k[2], key+8); + LOAD32H(skey->tea.k[3], key+12); + + return CRYPT_OK; +} + +/** + Encrypts a block of text with TEA + @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 tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 y, z, sum = 0; + const ulong32 delta = DELTA; + int r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(y, &pt[0]); + LOAD32H(z, &pt[4]); + for (r = 0; r < 32; r++) { + sum += delta; + y += ((z<<4) + skey->tea.k[0]) ^ (z + sum) ^ ((z>>5) + skey->tea.k[1]); + z += ((y<<4) + skey->tea.k[2]) ^ (y + sum) ^ ((y>>5) + skey->tea.k[3]); + } + STORE32H(y, &ct[0]); + STORE32H(z, &ct[4]); + return CRYPT_OK; +} + +/** + Decrypts a block of text with TEA + @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 tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 v0, v1, sum = SUM; + const ulong32 delta = DELTA; + int r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(v0, &ct[0]); + LOAD32H(v1, &ct[4]); + + for (r = 0; r < 32; r++) { + v1 -= ((v0 << 4) + skey->tea.k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + skey->tea.k[3]); + v0 -= ((v1 << 4) + skey->tea.k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + skey->tea.k[1]); + sum -= delta; + } + + STORE32H(v0, &pt[0]); + STORE32H(v1, &pt[4]); + return CRYPT_OK; +} + +/** + Performs a self-test of the TEA block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int tea_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *key, *pt, *ct; + } tests[] = { + { + "00000000000000000000000000000000", + "0000000000000000", + "41ea3a0a94baa940" + }, { + "32a1e65408b63bb9214105744ec5d2e2", + "5ada1d89a9c3801a", + "dd46249e28aa0b4b" + }, { + "60388adadf70a1f5d9cb4e097d2c6c57", + "7a6adb4d69c53e0f", + "44b71215cf25368a" + }, { + "4368d2249bd0321eb7c56d5b63a1bfac", + "5a5d7ca2e186c41a", + "91f56dff7281794f" + }, { + "5c60bff27072d01c4513c5eb8f3a38ab", + "80d9c4adcf899635", + "2bb0f1b3c023ed11" + } + }; + unsigned char ptct[2][8]; + unsigned char tmp[2][8]; + unsigned char key[16]; + unsigned long l; + symmetric_key skey; + size_t i; + int err, y; + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + zeromem(&skey, sizeof(skey)); + + l = sizeof(key); + if ((err = base16_decode(tests[i].key, XSTRLEN(tests[i].key), key, &l)) != CRYPT_OK) return err; + l = sizeof(ptct[0]); + if ((err = base16_decode(tests[i].pt, XSTRLEN(tests[i].pt), ptct[0], &l)) != CRYPT_OK) return err; + l = sizeof(ptct[1]); + if ((err = base16_decode(tests[i].ct, XSTRLEN(tests[i].ct), ptct[1], &l)) != CRYPT_OK) return err; + + if ((err = tea_setup(key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + tea_ecb_encrypt(ptct[0], tmp[0], &skey); + tea_ecb_decrypt(tmp[0], tmp[1], &skey); + + if (compare_testvector(tmp[0], 8, ptct[1], 8, "TEA Encrypt", i) != 0 || + compare_testvector(tmp[1], 8, ptct[0], 8, "TEA Decrypt", i) != 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[0][y] = 0; + for (y = 0; y < 1000; y++) tea_ecb_encrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 1000; y++) tea_ecb_decrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } /* for */ + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void tea_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 tea_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c new file mode 100644 index 0000000..c006361 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c @@ -0,0 +1,706 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + + /** + @file twofish.c + Implementation of Twofish by Tom St Denis + */ +#include "tomcrypt_private.h" + +#ifdef LTC_TWOFISH + +/* first LTC_TWOFISH_ALL_TABLES must ensure LTC_TWOFISH_TABLES is defined */ +#ifdef LTC_TWOFISH_ALL_TABLES +#ifndef LTC_TWOFISH_TABLES +#define LTC_TWOFISH_TABLES +#endif +#endif + +const struct ltc_cipher_descriptor twofish_desc = +{ + "twofish", + 7, + 16, 32, 16, 16, + &twofish_setup, + &twofish_ecb_encrypt, + &twofish_ecb_decrypt, + &twofish_test, + &twofish_done, + &twofish_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* the two polynomials */ +#ifndef LTC_TWOFISH_TABLES +#define MDS_POLY 0x169 +#endif +#ifndef LTC_TWOFISH_ALL_TABLES +#define RS_POLY 0x14D +#endif + +/* The 4x8 RS Linear Transform */ +static const unsigned char RS[4][8] = { + { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E }, + { 0xA4, 0x56, 0x82, 0xF3, 0X1E, 0XC6, 0X68, 0XE5 }, + { 0X02, 0XA1, 0XFC, 0XC1, 0X47, 0XAE, 0X3D, 0X19 }, + { 0XA4, 0X55, 0X87, 0X5A, 0X58, 0XDB, 0X9E, 0X03 } +}; + +#ifdef LTC_TWOFISH_SMALL +/* sbox usage orderings */ +static const unsigned char qord[4][5] = { + { 1, 1, 0, 0, 1 }, + { 0, 1, 1, 0, 0 }, + { 0, 0, 0, 1, 1 }, + { 1, 0, 1, 1, 0 } +}; +#endif /* LTC_TWOFISH_SMALL */ + +#ifdef LTC_TWOFISH_TABLES + +#define LTC_TWOFISH_TAB_C +#include "twofish_tab.c" + +#define sbox(i, x) ((ulong32)SBOX[i][(x)&255]) + +#else + +/* The Q-box tables */ +static const unsigned char qbox[2][4][16] = { +{ + { 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 }, + { 0xE, 0XC, 0XB, 0X8, 0X1, 0X2, 0X3, 0X5, 0XF, 0X4, 0XA, 0X6, 0X7, 0X0, 0X9, 0XD }, + { 0XB, 0XA, 0X5, 0XE, 0X6, 0XD, 0X9, 0X0, 0XC, 0X8, 0XF, 0X3, 0X2, 0X4, 0X7, 0X1 }, + { 0XD, 0X7, 0XF, 0X4, 0X1, 0X2, 0X6, 0XE, 0X9, 0XB, 0X3, 0X0, 0X8, 0X5, 0XC, 0XA } +}, +{ + { 0X2, 0X8, 0XB, 0XD, 0XF, 0X7, 0X6, 0XE, 0X3, 0X1, 0X9, 0X4, 0X0, 0XA, 0XC, 0X5 }, + { 0X1, 0XE, 0X2, 0XB, 0X4, 0XC, 0X3, 0X7, 0X6, 0XD, 0XA, 0X5, 0XF, 0X9, 0X0, 0X8 }, + { 0X4, 0XC, 0X7, 0X5, 0X1, 0X6, 0X9, 0XA, 0X0, 0XE, 0XD, 0X8, 0X2, 0XB, 0X3, 0XF }, + { 0xB, 0X9, 0X5, 0X1, 0XC, 0X3, 0XD, 0XE, 0X6, 0X4, 0X7, 0XF, 0X2, 0X0, 0X8, 0XA } +} +}; + +/* computes S_i[x] */ +#ifdef LTC_CLEAN_STACK +static ulong32 s_sbox(int i, ulong32 x) +#else +static ulong32 sbox(int i, ulong32 x) +#endif +{ + unsigned char a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,y; + + /* a0,b0 = [x/16], x mod 16 */ + a0 = (unsigned char)((x>>4)&15); + b0 = (unsigned char)((x)&15); + + /* a1 = a0 ^ b0 */ + a1 = a0 ^ b0; + + /* b1 = a0 ^ ROR(b0, 1) ^ 8a0 */ + b1 = (a0 ^ ((b0<<3)|(b0>>1)) ^ (a0<<3)) & 15; + + /* a2,b2 = t0[a1], t1[b1] */ + a2 = qbox[i][0][(int)a1]; + b2 = qbox[i][1][(int)b1]; + + /* a3 = a2 ^ b2 */ + a3 = a2 ^ b2; + + /* b3 = a2 ^ ROR(b2, 1) ^ 8a2 */ + b3 = (a2 ^ ((b2<<3)|(b2>>1)) ^ (a2<<3)) & 15; + + /* a4,b4 = t2[a3], t3[b3] */ + a4 = qbox[i][2][(int)a3]; + b4 = qbox[i][3][(int)b3]; + + /* y = 16b4 + a4 */ + y = (b4 << 4) + a4; + + /* return result */ + return (ulong32)y; +} + +#ifdef LTC_CLEAN_STACK +static ulong32 sbox(int i, ulong32 x) +{ + ulong32 y; + y = s_sbox(i, x); + burn_stack(sizeof(unsigned char) * 11); + return y; +} +#endif /* LTC_CLEAN_STACK */ + +#endif /* LTC_TWOFISH_TABLES */ + +/* computes ab mod p */ +static ulong32 gf_mult(ulong32 a, ulong32 b, ulong32 p) +{ + ulong32 result, B[2], P[2]; + + P[1] = p; + B[1] = b; + result = P[0] = B[0] = 0; + + /* unrolled branchless GF multiplier */ + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; + + return result; +} + +/* computes [y0 y1 y2 y3] = MDS . [x0] */ +#ifndef LTC_TWOFISH_TABLES +static ulong32 mds_column_mult(unsigned char in, int col) +{ + ulong32 x01, x5B, xEF; + + x01 = in; + x5B = gf_mult(in, 0x5B, MDS_POLY); + xEF = gf_mult(in, 0xEF, MDS_POLY); + + switch (col) { + case 0: + return (x01 << 0 ) | + (x5B << 8 ) | + (xEF << 16) | + (xEF << 24); + case 1: + return (xEF << 0 ) | + (xEF << 8 ) | + (x5B << 16) | + (x01 << 24); + case 2: + return (x5B << 0 ) | + (xEF << 8 ) | + (x01 << 16) | + (xEF << 24); + case 3: + return (x5B << 0 ) | + (x01 << 8 ) | + (xEF << 16) | + (x5B << 24); + } + /* avoid warnings, we'd never get here normally but just to calm compiler warnings... */ + return 0; +} + +#else /* !LTC_TWOFISH_TABLES */ + +#define mds_column_mult(x, i) mds_tab[i][x] + +#endif /* LTC_TWOFISH_TABLES */ + +/* Computes [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] */ +static void mds_mult(const unsigned char *in, unsigned char *out) +{ + int x; + ulong32 tmp; + for (tmp = x = 0; x < 4; x++) { + tmp ^= mds_column_mult(in[x], x); + } + STORE32L(tmp, out); +} + +#ifdef LTC_TWOFISH_ALL_TABLES +/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */ +static void rs_mult(const unsigned char *in, unsigned char *out) +{ + ulong32 tmp; + tmp = rs_tab0[in[0]] ^ rs_tab1[in[1]] ^ rs_tab2[in[2]] ^ rs_tab3[in[3]] ^ + rs_tab4[in[4]] ^ rs_tab5[in[5]] ^ rs_tab6[in[6]] ^ rs_tab7[in[7]]; + STORE32L(tmp, out); +} + +#else /* !LTC_TWOFISH_ALL_TABLES */ + +/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */ +static void rs_mult(const unsigned char *in, unsigned char *out) +{ + int x, y; + for (x = 0; x < 4; x++) { + out[x] = 0; + for (y = 0; y < 8; y++) { + out[x] ^= gf_mult(in[y], RS[x][y], RS_POLY); + } + } +} + +#endif + +/* computes h(x) */ +static void h_func(const unsigned char *in, unsigned char *out, const unsigned char *M, int k, int offset) +{ + int x; + unsigned char y[4]; + for (x = 0; x < 4; x++) { + y[x] = in[x]; + } + switch (k) { + case 4: + y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (6 + offset) + 0]); + y[1] = (unsigned char)(sbox(0, (ulong32)y[1]) ^ M[4 * (6 + offset) + 1]); + y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (6 + offset) + 2]); + y[3] = (unsigned char)(sbox(1, (ulong32)y[3]) ^ M[4 * (6 + offset) + 3]); + /* FALLTHROUGH */ + case 3: + y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (4 + offset) + 0]); + y[1] = (unsigned char)(sbox(1, (ulong32)y[1]) ^ M[4 * (4 + offset) + 1]); + y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (4 + offset) + 2]); + y[3] = (unsigned char)(sbox(0, (ulong32)y[3]) ^ M[4 * (4 + offset) + 3]); + /* FALLTHROUGH */ + case 2: + y[0] = (unsigned char)(sbox(1, sbox(0, sbox(0, (ulong32)y[0]) ^ M[4 * (2 + offset) + 0]) ^ M[4 * (0 + offset) + 0])); + y[1] = (unsigned char)(sbox(0, sbox(0, sbox(1, (ulong32)y[1]) ^ M[4 * (2 + offset) + 1]) ^ M[4 * (0 + offset) + 1])); + y[2] = (unsigned char)(sbox(1, sbox(1, sbox(0, (ulong32)y[2]) ^ M[4 * (2 + offset) + 2]) ^ M[4 * (0 + offset) + 2])); + y[3] = (unsigned char)(sbox(0, sbox(1, sbox(1, (ulong32)y[3]) ^ M[4 * (2 + offset) + 3]) ^ M[4 * (0 + offset) + 3])); + /* FALLTHROUGH */ + } + mds_mult(y, out); +} + +#ifndef LTC_TWOFISH_SMALL + +/* for GCC we don't use pointer aliases */ +#if defined(__GNUC__) + #define S1 skey->twofish.S[0] + #define S2 skey->twofish.S[1] + #define S3 skey->twofish.S[2] + #define S4 skey->twofish.S[3] +#endif + +/* the G function */ +#define g_func(x, dum) (S1[LTC_BYTE(x,0)] ^ S2[LTC_BYTE(x,1)] ^ S3[LTC_BYTE(x,2)] ^ S4[LTC_BYTE(x,3)]) +#define g1_func(x, dum) (S2[LTC_BYTE(x,0)] ^ S3[LTC_BYTE(x,1)] ^ S4[LTC_BYTE(x,2)] ^ S1[LTC_BYTE(x,3)]) + +#else + +#ifdef LTC_CLEAN_STACK +static ulong32 s_g_func(ulong32 x, const symmetric_key *key) +#else +static ulong32 g_func(ulong32 x, const symmetric_key *key) +#endif +{ + unsigned char g, i, y, z; + ulong32 res; + + res = 0; + for (y = 0; y < 4; y++) { + z = key->twofish.start; + + /* do unkeyed substitution */ + g = sbox(qord[y][z++], (x >> (8*y)) & 255); + + /* first subkey */ + i = 0; + + /* do key mixing+sbox until z==5 */ + while (z != 5) { + g = g ^ key->twofish.S[4*i++ + y]; + g = sbox(qord[y][z++], g); + } + + /* multiply g by a column of the MDS */ + res ^= mds_column_mult(g, y); + } + return res; +} + +#define g1_func(x, key) g_func(ROLc(x, 8), key) + +#ifdef LTC_CLEAN_STACK +static ulong32 g_func(ulong32 x, const symmetric_key *key) +{ + ulong32 y; + y = s_g_func(x, key); + burn_stack(sizeof(unsigned char) * 4 + sizeof(ulong32)); + return y; +} +#endif /* LTC_CLEAN_STACK */ + +#endif /* LTC_TWOFISH_SMALL */ + + /** + Initialize the Twofish 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 + */ +#ifdef LTC_CLEAN_STACK +static int s_twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ +#ifndef LTC_TWOFISH_SMALL + unsigned char S[4*4], tmpx0, tmpx1; +#endif + int k, x, y; + unsigned char tmp[4], tmp2[4], M[8*4]; + ulong32 A, B; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* invalid arguments? */ + if (num_rounds != 16 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + /* k = keysize/64 [but since our keysize is in bytes...] */ + k = keylen / 8; + + /* copy the key into M */ + for (x = 0; x < keylen; x++) { + M[x] = key[x] & 255; + } + + /* create the S[..] words */ +#ifndef LTC_TWOFISH_SMALL + for (x = 0; x < k; x++) { + rs_mult(M+(x*8), S+(x*4)); + } +#else + for (x = 0; x < k; x++) { + rs_mult(M+(x*8), skey->twofish.S+(x*4)); + } +#endif + + /* make subkeys */ + for (x = 0; x < 20; x++) { + /* A = h(p * 2x, Me) */ + for (y = 0; y < 4; y++) { + tmp[y] = x+x; + } + h_func(tmp, tmp2, M, k, 0); + LOAD32L(A, tmp2); + + /* B = ROL(h(p * (2x + 1), Mo), 8) */ + for (y = 0; y < 4; y++) { + tmp[y] = (unsigned char)(x+x+1); + } + h_func(tmp, tmp2, M, k, 1); + LOAD32L(B, tmp2); + B = ROLc(B, 8); + + /* K[2i] = A + B */ + skey->twofish.K[x+x] = (A + B) & 0xFFFFFFFFUL; + + /* K[2i+1] = (A + 2B) <<< 9 */ + skey->twofish.K[x+x+1] = ROLc(B + B + A, 9); + } + +#ifndef LTC_TWOFISH_SMALL + /* make the sboxes (large ram variant) */ + if (k == 2) { + for (x = 0; x < 256; x++) { + tmpx0 = (unsigned char)sbox(0, x); + tmpx1 = (unsigned char)sbox(1, x); + skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, tmpx0 ^ S[0]) ^ S[4])),0); + skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, tmpx1 ^ S[1]) ^ S[5])),1); + skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, tmpx0 ^ S[2]) ^ S[6])),2); + skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, tmpx1 ^ S[3]) ^ S[7])),3); + } + } else if (k == 3) { + for (x = 0; x < 256; x++) { + tmpx0 = (unsigned char)sbox(0, x); + tmpx1 = (unsigned char)sbox(1, x); + skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, tmpx1 ^ S[0]) ^ S[4]) ^ S[8])),0); + skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, tmpx1 ^ S[1]) ^ S[5]) ^ S[9])),1); + skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10])),2); + skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, tmpx0 ^ S[3]) ^ S[7]) ^ S[11])),3); + } + } else { + for (x = 0; x < 256; x++) { + tmpx0 = (unsigned char)sbox(0, x); + tmpx1 = (unsigned char)sbox(1, x); + skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, sbox(1, tmpx1 ^ S[0]) ^ S[4]) ^ S[8]) ^ S[12])),0); + skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, sbox(1, tmpx0 ^ S[1]) ^ S[5]) ^ S[9]) ^ S[13])),1); + skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10]) ^ S[14])),2); + skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, sbox(0, tmpx1 ^ S[3]) ^ S[7]) ^ S[11]) ^ S[15])),3); + } + } +#else + /* where to start in the sbox layers */ + /* small ram variant */ + switch (k) { + case 4 : skey->twofish.start = 0; break; + case 3 : skey->twofish.start = 1; break; + default: skey->twofish.start = 2; break; + } +#endif + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + x = s_twofish_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(int) * 7 + sizeof(unsigned char) * 56 + sizeof(ulong32) * 2); + return x; +} +#endif + +/** + Encrypts a block of text with Twofish + @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 s_twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,ta,tb,tc,td,t1,t2; + const ulong32 *k; + int r; +#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) + const ulong32 *S1, *S2, *S3, *S4; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + +#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) + S1 = skey->twofish.S[0]; + S2 = skey->twofish.S[1]; + S3 = skey->twofish.S[2]; + S4 = skey->twofish.S[3]; +#endif + + LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]); + LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]); + a ^= skey->twofish.K[0]; + b ^= skey->twofish.K[1]; + c ^= skey->twofish.K[2]; + d ^= skey->twofish.K[3]; + + k = skey->twofish.K + 8; + for (r = 8; r != 0; --r) { + t2 = g1_func(b, skey); + t1 = g_func(a, skey) + t2; + c = RORc(c ^ (t1 + k[0]), 1); + d = ROLc(d, 1) ^ (t2 + t1 + k[1]); + + t2 = g1_func(d, skey); + t1 = g_func(c, skey) + t2; + a = RORc(a ^ (t1 + k[2]), 1); + b = ROLc(b, 1) ^ (t2 + t1 + k[3]); + k += 4; + } + + /* output with "undo last swap" */ + ta = c ^ skey->twofish.K[4]; + tb = d ^ skey->twofish.K[5]; + tc = a ^ skey->twofish.K[6]; + td = b ^ skey->twofish.K[7]; + + /* store output */ + STORE32L(ta,&ct[0]); STORE32L(tb,&ct[4]); + STORE32L(tc,&ct[8]); STORE32L(td,&ct[12]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_twofish_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 10 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with Twofish + @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 s_twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,ta,tb,tc,td,t1,t2; + const ulong32 *k; + int r; +#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) + const ulong32 *S1, *S2, *S3, *S4; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + +#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) + S1 = skey->twofish.S[0]; + S2 = skey->twofish.S[1]; + S3 = skey->twofish.S[2]; + S4 = skey->twofish.S[3]; +#endif + + /* load input */ + LOAD32L(ta,&ct[0]); LOAD32L(tb,&ct[4]); + LOAD32L(tc,&ct[8]); LOAD32L(td,&ct[12]); + + /* undo undo final swap */ + a = tc ^ skey->twofish.K[6]; + b = td ^ skey->twofish.K[7]; + c = ta ^ skey->twofish.K[4]; + d = tb ^ skey->twofish.K[5]; + + k = skey->twofish.K + 36; + for (r = 8; r != 0; --r) { + t2 = g1_func(d, skey); + t1 = g_func(c, skey) + t2; + a = ROLc(a, 1) ^ (t1 + k[2]); + b = RORc(b ^ (t2 + t1 + k[3]), 1); + + t2 = g1_func(b, skey); + t1 = g_func(a, skey) + t2; + c = ROLc(c, 1) ^ (t1 + k[0]); + d = RORc(d ^ (t2 + t1 + k[1]), 1); + k -= 4; + } + + /* pre-white */ + a ^= skey->twofish.K[0]; + b ^= skey->twofish.K[1]; + c ^= skey->twofish.K[2]; + d ^= skey->twofish.K[3]; + + /* store */ + STORE32L(a, &pt[0]); STORE32L(b, &pt[4]); + STORE32L(c, &pt[8]); STORE32L(d, &pt[12]); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_twofish_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 10 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the Twofish block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int twofish_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { 16, + { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, + 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }, + { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, + 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 }, + { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, + 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 } + }, { + 24, + { 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, + 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, + 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 }, + { 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, + 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 }, + { 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, + 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 } + }, { + 32, + { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, + 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, + 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, + 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F }, + { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, + 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 }, + { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, + 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA } + } +}; + + + symmetric_key key; + unsigned char tmp[2][16]; + int err, i, y; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + if ((err = twofish_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + twofish_ecb_encrypt(tests[i].pt, tmp[0], &key); + twofish_ecb_decrypt(tmp[0], tmp[1], &key); + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Twofish Encrypt", i) != 0 || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "Twofish Decrypt", i) != 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 < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) twofish_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) twofish_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 +} + +/** Terminate the context + @param skey The scheduled key +*/ +void twofish_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 twofish_keysize(int *keysize) +{ + LTC_ARGCHK(keysize); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + return CRYPT_OK; + } + if (*keysize < 32) { + *keysize = 24; + return CRYPT_OK; + } + *keysize = 32; + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c new file mode 100644 index 0000000..e52d284 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c @@ -0,0 +1,486 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + + /** + @file twofish_tab.c + Twofish tables, Tom St Denis + */ +#ifdef LTC_TWOFISH_TABLES +#ifdef LTC_TWOFISH_TAB_C + +/* pre generated 8x8 tables from the four 4x4s */ +static const unsigned char SBOX[2][256] = { +{ + 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, + 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98, + 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, + 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, + 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01, + 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, + 0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, + 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, + 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, + 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5, + 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, + 0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, + 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d, + 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, + 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, + 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, + 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, + 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f, + 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, + 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, + 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7, + 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, + 0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, + 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, + 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, + 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0}, +{ + 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, + 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd, + 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, + 0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, + 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84, + 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, + 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, + 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, + 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff, + 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, + 0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, + 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94, + 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, + 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, + 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, + 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, + 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e, + 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, + 0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, + 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e, + 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, + 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, + 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, + 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, + 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91} +}; + +/* the 4x4 MDS in a nicer format */ +static const ulong32 mds_tab[4][256] = { +{ +0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL, +0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL, +0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL, +0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL, +0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL, +0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL, +0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL, +0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL, +0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL, +0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL, +0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL, +0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL, +0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL, +0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL, +0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL, +0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL, +0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL, +0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL, +0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL, +0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL, +0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL, +0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL, +0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL, +0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL, +0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL, +0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL, +0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL, +0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL, +0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL, +0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL, +0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL, +0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL +}, +{ +0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL, +0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL, +0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL, +0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL, +0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL, +0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL, +0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL, +0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL, +0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL, +0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL, +0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL, +0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL, +0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL, +0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL, +0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL, +0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL, +0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL, +0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL, +0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL, +0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL, +0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL, +0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL, +0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL, +0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL, +0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL, +0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL, +0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL, +0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL, +0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL, +0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL, +0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL, +0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL +}, +{ +0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL, +0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL, +0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL, +0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL, +0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL, +0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL, +0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL, +0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL, +0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL, +0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL, +0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL, +0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL, +0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL, +0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL, +0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL, +0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL, +0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL, +0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL, +0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL, +0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL, +0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL, +0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL, +0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL, +0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL, +0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL, +0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL, +0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL, +0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL, +0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL, +0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL, +0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL, +0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL +}, +{ +0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL, +0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL, +0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL, +0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL, +0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL, +0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL, +0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL, +0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL, +0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL, +0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL, +0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL, +0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL, +0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL, +0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL, +0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL, +0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL, +0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL, +0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL, +0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL, +0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL, +0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL, +0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL, +0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL, +0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL, +0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL, +0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL, +0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL, +0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL, +0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL, +0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL, +0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL, +0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL +}}; + +#ifdef LTC_TWOFISH_ALL_TABLES + +/* the 4x8 RS transform */ +static const ulong32 rs_tab0[256] = { +0x00000000LU, 0xa402a401LU, 0x05040502LU, 0xa106a103LU, 0x0a080a04LU, 0xae0aae05LU, 0x0f0c0f06LU, 0xab0eab07LU, +0x14101408LU, 0xb012b009LU, 0x1114110aLU, 0xb516b50bLU, 0x1e181e0cLU, 0xba1aba0dLU, 0x1b1c1b0eLU, 0xbf1ebf0fLU, +0x28202810LU, 0x8c228c11LU, 0x2d242d12LU, 0x89268913LU, 0x22282214LU, 0x862a8615LU, 0x272c2716LU, 0x832e8317LU, +0x3c303c18LU, 0x98329819LU, 0x3934391aLU, 0x9d369d1bLU, 0x3638361cLU, 0x923a921dLU, 0x333c331eLU, 0x973e971fLU, +0x50405020LU, 0xf442f421LU, 0x55445522LU, 0xf146f123LU, 0x5a485a24LU, 0xfe4afe25LU, 0x5f4c5f26LU, 0xfb4efb27LU, +0x44504428LU, 0xe052e029LU, 0x4154412aLU, 0xe556e52bLU, 0x4e584e2cLU, 0xea5aea2dLU, 0x4b5c4b2eLU, 0xef5eef2fLU, +0x78607830LU, 0xdc62dc31LU, 0x7d647d32LU, 0xd966d933LU, 0x72687234LU, 0xd66ad635LU, 0x776c7736LU, 0xd36ed337LU, +0x6c706c38LU, 0xc872c839LU, 0x6974693aLU, 0xcd76cd3bLU, 0x6678663cLU, 0xc27ac23dLU, 0x637c633eLU, 0xc77ec73fLU, +0xa080a040LU, 0x04820441LU, 0xa584a542LU, 0x01860143LU, 0xaa88aa44LU, 0x0e8a0e45LU, 0xaf8caf46LU, 0x0b8e0b47LU, +0xb490b448LU, 0x10921049LU, 0xb194b14aLU, 0x1596154bLU, 0xbe98be4cLU, 0x1a9a1a4dLU, 0xbb9cbb4eLU, 0x1f9e1f4fLU, +0x88a08850LU, 0x2ca22c51LU, 0x8da48d52LU, 0x29a62953LU, 0x82a88254LU, 0x26aa2655LU, 0x87ac8756LU, 0x23ae2357LU, +0x9cb09c58LU, 0x38b23859LU, 0x99b4995aLU, 0x3db63d5bLU, 0x96b8965cLU, 0x32ba325dLU, 0x93bc935eLU, 0x37be375fLU, +0xf0c0f060LU, 0x54c25461LU, 0xf5c4f562LU, 0x51c65163LU, 0xfac8fa64LU, 0x5eca5e65LU, 0xffccff66LU, 0x5bce5b67LU, +0xe4d0e468LU, 0x40d24069LU, 0xe1d4e16aLU, 0x45d6456bLU, 0xeed8ee6cLU, 0x4ada4a6dLU, 0xebdceb6eLU, 0x4fde4f6fLU, +0xd8e0d870LU, 0x7ce27c71LU, 0xdde4dd72LU, 0x79e67973LU, 0xd2e8d274LU, 0x76ea7675LU, 0xd7ecd776LU, 0x73ee7377LU, +0xccf0cc78LU, 0x68f26879LU, 0xc9f4c97aLU, 0x6df66d7bLU, 0xc6f8c67cLU, 0x62fa627dLU, 0xc3fcc37eLU, 0x67fe677fLU, +0x0d4d0d80LU, 0xa94fa981LU, 0x08490882LU, 0xac4bac83LU, 0x07450784LU, 0xa347a385LU, 0x02410286LU, 0xa643a687LU, +0x195d1988LU, 0xbd5fbd89LU, 0x1c591c8aLU, 0xb85bb88bLU, 0x1355138cLU, 0xb757b78dLU, 0x1651168eLU, 0xb253b28fLU, +0x256d2590LU, 0x816f8191LU, 0x20692092LU, 0x846b8493LU, 0x2f652f94LU, 0x8b678b95LU, 0x2a612a96LU, 0x8e638e97LU, +0x317d3198LU, 0x957f9599LU, 0x3479349aLU, 0x907b909bLU, 0x3b753b9cLU, 0x9f779f9dLU, 0x3e713e9eLU, 0x9a739a9fLU, +0x5d0d5da0LU, 0xf90ff9a1LU, 0x580958a2LU, 0xfc0bfca3LU, 0x570557a4LU, 0xf307f3a5LU, 0x520152a6LU, 0xf603f6a7LU, +0x491d49a8LU, 0xed1feda9LU, 0x4c194caaLU, 0xe81be8abLU, 0x431543acLU, 0xe717e7adLU, 0x461146aeLU, 0xe213e2afLU, +0x752d75b0LU, 0xd12fd1b1LU, 0x702970b2LU, 0xd42bd4b3LU, 0x7f257fb4LU, 0xdb27dbb5LU, 0x7a217ab6LU, 0xde23deb7LU, +0x613d61b8LU, 0xc53fc5b9LU, 0x643964baLU, 0xc03bc0bbLU, 0x6b356bbcLU, 0xcf37cfbdLU, 0x6e316ebeLU, 0xca33cabfLU, +0xadcdadc0LU, 0x09cf09c1LU, 0xa8c9a8c2LU, 0x0ccb0cc3LU, 0xa7c5a7c4LU, 0x03c703c5LU, 0xa2c1a2c6LU, 0x06c306c7LU, +0xb9ddb9c8LU, 0x1ddf1dc9LU, 0xbcd9bccaLU, 0x18db18cbLU, 0xb3d5b3ccLU, 0x17d717cdLU, 0xb6d1b6ceLU, 0x12d312cfLU, +0x85ed85d0LU, 0x21ef21d1LU, 0x80e980d2LU, 0x24eb24d3LU, 0x8fe58fd4LU, 0x2be72bd5LU, 0x8ae18ad6LU, 0x2ee32ed7LU, +0x91fd91d8LU, 0x35ff35d9LU, 0x94f994daLU, 0x30fb30dbLU, 0x9bf59bdcLU, 0x3ff73fddLU, 0x9ef19edeLU, 0x3af33adfLU, +0xfd8dfde0LU, 0x598f59e1LU, 0xf889f8e2LU, 0x5c8b5ce3LU, 0xf785f7e4LU, 0x538753e5LU, 0xf281f2e6LU, 0x568356e7LU, +0xe99de9e8LU, 0x4d9f4de9LU, 0xec99eceaLU, 0x489b48ebLU, 0xe395e3ecLU, 0x479747edLU, 0xe691e6eeLU, 0x429342efLU, +0xd5add5f0LU, 0x71af71f1LU, 0xd0a9d0f2LU, 0x74ab74f3LU, 0xdfa5dff4LU, 0x7ba77bf5LU, 0xdaa1daf6LU, 0x7ea37ef7LU, +0xc1bdc1f8LU, 0x65bf65f9LU, 0xc4b9c4faLU, 0x60bb60fbLU, 0xcbb5cbfcLU, 0x6fb76ffdLU, 0xceb1cefeLU, 0x6ab36affLU }; + +static const ulong32 rs_tab1[256] = { +0x00000000LU, 0x55a156a4LU, 0xaa0fac05LU, 0xffaefaa1LU, 0x191e150aLU, 0x4cbf43aeLU, 0xb311b90fLU, 0xe6b0efabLU, +0x323c2a14LU, 0x679d7cb0LU, 0x98338611LU, 0xcd92d0b5LU, 0x2b223f1eLU, 0x7e8369baLU, 0x812d931bLU, 0xd48cc5bfLU, +0x64785428LU, 0x31d9028cLU, 0xce77f82dLU, 0x9bd6ae89LU, 0x7d664122LU, 0x28c71786LU, 0xd769ed27LU, 0x82c8bb83LU, +0x56447e3cLU, 0x03e52898LU, 0xfc4bd239LU, 0xa9ea849dLU, 0x4f5a6b36LU, 0x1afb3d92LU, 0xe555c733LU, 0xb0f49197LU, +0xc8f0a850LU, 0x9d51fef4LU, 0x62ff0455LU, 0x375e52f1LU, 0xd1eebd5aLU, 0x844febfeLU, 0x7be1115fLU, 0x2e4047fbLU, +0xfacc8244LU, 0xaf6dd4e0LU, 0x50c32e41LU, 0x056278e5LU, 0xe3d2974eLU, 0xb673c1eaLU, 0x49dd3b4bLU, 0x1c7c6defLU, +0xac88fc78LU, 0xf929aadcLU, 0x0687507dLU, 0x532606d9LU, 0xb596e972LU, 0xe037bfd6LU, 0x1f994577LU, 0x4a3813d3LU, +0x9eb4d66cLU, 0xcb1580c8LU, 0x34bb7a69LU, 0x611a2ccdLU, 0x87aac366LU, 0xd20b95c2LU, 0x2da56f63LU, 0x780439c7LU, +0xddad1da0LU, 0x880c4b04LU, 0x77a2b1a5LU, 0x2203e701LU, 0xc4b308aaLU, 0x91125e0eLU, 0x6ebca4afLU, 0x3b1df20bLU, +0xef9137b4LU, 0xba306110LU, 0x459e9bb1LU, 0x103fcd15LU, 0xf68f22beLU, 0xa32e741aLU, 0x5c808ebbLU, 0x0921d81fLU, +0xb9d54988LU, 0xec741f2cLU, 0x13dae58dLU, 0x467bb329LU, 0xa0cb5c82LU, 0xf56a0a26LU, 0x0ac4f087LU, 0x5f65a623LU, +0x8be9639cLU, 0xde483538LU, 0x21e6cf99LU, 0x7447993dLU, 0x92f77696LU, 0xc7562032LU, 0x38f8da93LU, 0x6d598c37LU, +0x155db5f0LU, 0x40fce354LU, 0xbf5219f5LU, 0xeaf34f51LU, 0x0c43a0faLU, 0x59e2f65eLU, 0xa64c0cffLU, 0xf3ed5a5bLU, +0x27619fe4LU, 0x72c0c940LU, 0x8d6e33e1LU, 0xd8cf6545LU, 0x3e7f8aeeLU, 0x6bdedc4aLU, 0x947026ebLU, 0xc1d1704fLU, +0x7125e1d8LU, 0x2484b77cLU, 0xdb2a4dddLU, 0x8e8b1b79LU, 0x683bf4d2LU, 0x3d9aa276LU, 0xc23458d7LU, 0x97950e73LU, +0x4319cbccLU, 0x16b89d68LU, 0xe91667c9LU, 0xbcb7316dLU, 0x5a07dec6LU, 0x0fa68862LU, 0xf00872c3LU, 0xa5a92467LU, +0xf7173a0dLU, 0xa2b66ca9LU, 0x5d189608LU, 0x08b9c0acLU, 0xee092f07LU, 0xbba879a3LU, 0x44068302LU, 0x11a7d5a6LU, +0xc52b1019LU, 0x908a46bdLU, 0x6f24bc1cLU, 0x3a85eab8LU, 0xdc350513LU, 0x899453b7LU, 0x763aa916LU, 0x239bffb2LU, +0x936f6e25LU, 0xc6ce3881LU, 0x3960c220LU, 0x6cc19484LU, 0x8a717b2fLU, 0xdfd02d8bLU, 0x207ed72aLU, 0x75df818eLU, +0xa1534431LU, 0xf4f21295LU, 0x0b5ce834LU, 0x5efdbe90LU, 0xb84d513bLU, 0xedec079fLU, 0x1242fd3eLU, 0x47e3ab9aLU, +0x3fe7925dLU, 0x6a46c4f9LU, 0x95e83e58LU, 0xc04968fcLU, 0x26f98757LU, 0x7358d1f3LU, 0x8cf62b52LU, 0xd9577df6LU, +0x0ddbb849LU, 0x587aeeedLU, 0xa7d4144cLU, 0xf27542e8LU, 0x14c5ad43LU, 0x4164fbe7LU, 0xbeca0146LU, 0xeb6b57e2LU, +0x5b9fc675LU, 0x0e3e90d1LU, 0xf1906a70LU, 0xa4313cd4LU, 0x4281d37fLU, 0x172085dbLU, 0xe88e7f7aLU, 0xbd2f29deLU, +0x69a3ec61LU, 0x3c02bac5LU, 0xc3ac4064LU, 0x960d16c0LU, 0x70bdf96bLU, 0x251cafcfLU, 0xdab2556eLU, 0x8f1303caLU, +0x2aba27adLU, 0x7f1b7109LU, 0x80b58ba8LU, 0xd514dd0cLU, 0x33a432a7LU, 0x66056403LU, 0x99ab9ea2LU, 0xcc0ac806LU, +0x18860db9LU, 0x4d275b1dLU, 0xb289a1bcLU, 0xe728f718LU, 0x019818b3LU, 0x54394e17LU, 0xab97b4b6LU, 0xfe36e212LU, +0x4ec27385LU, 0x1b632521LU, 0xe4cddf80LU, 0xb16c8924LU, 0x57dc668fLU, 0x027d302bLU, 0xfdd3ca8aLU, 0xa8729c2eLU, +0x7cfe5991LU, 0x295f0f35LU, 0xd6f1f594LU, 0x8350a330LU, 0x65e04c9bLU, 0x30411a3fLU, 0xcfefe09eLU, 0x9a4eb63aLU, +0xe24a8ffdLU, 0xb7ebd959LU, 0x484523f8LU, 0x1de4755cLU, 0xfb549af7LU, 0xaef5cc53LU, 0x515b36f2LU, 0x04fa6056LU, +0xd076a5e9LU, 0x85d7f34dLU, 0x7a7909ecLU, 0x2fd85f48LU, 0xc968b0e3LU, 0x9cc9e647LU, 0x63671ce6LU, 0x36c64a42LU, +0x8632dbd5LU, 0xd3938d71LU, 0x2c3d77d0LU, 0x799c2174LU, 0x9f2ccedfLU, 0xca8d987bLU, 0x352362daLU, 0x6082347eLU, +0xb40ef1c1LU, 0xe1afa765LU, 0x1e015dc4LU, 0x4ba00b60LU, 0xad10e4cbLU, 0xf8b1b26fLU, 0x071f48ceLU, 0x52be1e6aLU }; + +static const ulong32 rs_tab2[256] = { +0x00000000LU, 0x87fc8255LU, 0x43b549aaLU, 0xc449cbffLU, 0x86279219LU, 0x01db104cLU, 0xc592dbb3LU, 0x426e59e6LU, +0x414e6932LU, 0xc6b2eb67LU, 0x02fb2098LU, 0x8507a2cdLU, 0xc769fb2bLU, 0x4095797eLU, 0x84dcb281LU, 0x032030d4LU, +0x829cd264LU, 0x05605031LU, 0xc1299bceLU, 0x46d5199bLU, 0x04bb407dLU, 0x8347c228LU, 0x470e09d7LU, 0xc0f28b82LU, +0xc3d2bb56LU, 0x442e3903LU, 0x8067f2fcLU, 0x079b70a9LU, 0x45f5294fLU, 0xc209ab1aLU, 0x064060e5LU, 0x81bce2b0LU, +0x4975e9c8LU, 0xce896b9dLU, 0x0ac0a062LU, 0x8d3c2237LU, 0xcf527bd1LU, 0x48aef984LU, 0x8ce7327bLU, 0x0b1bb02eLU, +0x083b80faLU, 0x8fc702afLU, 0x4b8ec950LU, 0xcc724b05LU, 0x8e1c12e3LU, 0x09e090b6LU, 0xcda95b49LU, 0x4a55d91cLU, +0xcbe93bacLU, 0x4c15b9f9LU, 0x885c7206LU, 0x0fa0f053LU, 0x4dcea9b5LU, 0xca322be0LU, 0x0e7be01fLU, 0x8987624aLU, +0x8aa7529eLU, 0x0d5bd0cbLU, 0xc9121b34LU, 0x4eee9961LU, 0x0c80c087LU, 0x8b7c42d2LU, 0x4f35892dLU, 0xc8c90b78LU, +0x92ea9fddLU, 0x15161d88LU, 0xd15fd677LU, 0x56a35422LU, 0x14cd0dc4LU, 0x93318f91LU, 0x5778446eLU, 0xd084c63bLU, +0xd3a4f6efLU, 0x545874baLU, 0x9011bf45LU, 0x17ed3d10LU, 0x558364f6LU, 0xd27fe6a3LU, 0x16362d5cLU, 0x91caaf09LU, +0x10764db9LU, 0x978acfecLU, 0x53c30413LU, 0xd43f8646LU, 0x9651dfa0LU, 0x11ad5df5LU, 0xd5e4960aLU, 0x5218145fLU, +0x5138248bLU, 0xd6c4a6deLU, 0x128d6d21LU, 0x9571ef74LU, 0xd71fb692LU, 0x50e334c7LU, 0x94aaff38LU, 0x13567d6dLU, +0xdb9f7615LU, 0x5c63f440LU, 0x982a3fbfLU, 0x1fd6bdeaLU, 0x5db8e40cLU, 0xda446659LU, 0x1e0dada6LU, 0x99f12ff3LU, +0x9ad11f27LU, 0x1d2d9d72LU, 0xd964568dLU, 0x5e98d4d8LU, 0x1cf68d3eLU, 0x9b0a0f6bLU, 0x5f43c494LU, 0xd8bf46c1LU, +0x5903a471LU, 0xdeff2624LU, 0x1ab6eddbLU, 0x9d4a6f8eLU, 0xdf243668LU, 0x58d8b43dLU, 0x9c917fc2LU, 0x1b6dfd97LU, +0x184dcd43LU, 0x9fb14f16LU, 0x5bf884e9LU, 0xdc0406bcLU, 0x9e6a5f5aLU, 0x1996dd0fLU, 0xdddf16f0LU, 0x5a2394a5LU, +0x699973f7LU, 0xee65f1a2LU, 0x2a2c3a5dLU, 0xadd0b808LU, 0xefbee1eeLU, 0x684263bbLU, 0xac0ba844LU, 0x2bf72a11LU, +0x28d71ac5LU, 0xaf2b9890LU, 0x6b62536fLU, 0xec9ed13aLU, 0xaef088dcLU, 0x290c0a89LU, 0xed45c176LU, 0x6ab94323LU, +0xeb05a193LU, 0x6cf923c6LU, 0xa8b0e839LU, 0x2f4c6a6cLU, 0x6d22338aLU, 0xeadeb1dfLU, 0x2e977a20LU, 0xa96bf875LU, +0xaa4bc8a1LU, 0x2db74af4LU, 0xe9fe810bLU, 0x6e02035eLU, 0x2c6c5ab8LU, 0xab90d8edLU, 0x6fd91312LU, 0xe8259147LU, +0x20ec9a3fLU, 0xa710186aLU, 0x6359d395LU, 0xe4a551c0LU, 0xa6cb0826LU, 0x21378a73LU, 0xe57e418cLU, 0x6282c3d9LU, +0x61a2f30dLU, 0xe65e7158LU, 0x2217baa7LU, 0xa5eb38f2LU, 0xe7856114LU, 0x6079e341LU, 0xa43028beLU, 0x23ccaaebLU, +0xa270485bLU, 0x258cca0eLU, 0xe1c501f1LU, 0x663983a4LU, 0x2457da42LU, 0xa3ab5817LU, 0x67e293e8LU, 0xe01e11bdLU, +0xe33e2169LU, 0x64c2a33cLU, 0xa08b68c3LU, 0x2777ea96LU, 0x6519b370LU, 0xe2e53125LU, 0x26acfadaLU, 0xa150788fLU, +0xfb73ec2aLU, 0x7c8f6e7fLU, 0xb8c6a580LU, 0x3f3a27d5LU, 0x7d547e33LU, 0xfaa8fc66LU, 0x3ee13799LU, 0xb91db5ccLU, +0xba3d8518LU, 0x3dc1074dLU, 0xf988ccb2LU, 0x7e744ee7LU, 0x3c1a1701LU, 0xbbe69554LU, 0x7faf5eabLU, 0xf853dcfeLU, +0x79ef3e4eLU, 0xfe13bc1bLU, 0x3a5a77e4LU, 0xbda6f5b1LU, 0xffc8ac57LU, 0x78342e02LU, 0xbc7de5fdLU, 0x3b8167a8LU, +0x38a1577cLU, 0xbf5dd529LU, 0x7b141ed6LU, 0xfce89c83LU, 0xbe86c565LU, 0x397a4730LU, 0xfd338ccfLU, 0x7acf0e9aLU, +0xb20605e2LU, 0x35fa87b7LU, 0xf1b34c48LU, 0x764fce1dLU, 0x342197fbLU, 0xb3dd15aeLU, 0x7794de51LU, 0xf0685c04LU, +0xf3486cd0LU, 0x74b4ee85LU, 0xb0fd257aLU, 0x3701a72fLU, 0x756ffec9LU, 0xf2937c9cLU, 0x36dab763LU, 0xb1263536LU, +0x309ad786LU, 0xb76655d3LU, 0x732f9e2cLU, 0xf4d31c79LU, 0xb6bd459fLU, 0x3141c7caLU, 0xf5080c35LU, 0x72f48e60LU, +0x71d4beb4LU, 0xf6283ce1LU, 0x3261f71eLU, 0xb59d754bLU, 0xf7f32cadLU, 0x700faef8LU, 0xb4466507LU, 0x33bae752LU }; + +static const ulong32 rs_tab3[256] = { +0x00000000LU, 0x5ac1f387LU, 0xb4cfab43LU, 0xee0e58c4LU, 0x25d31b86LU, 0x7f12e801LU, 0x911cb0c5LU, 0xcbdd4342LU, +0x4aeb3641LU, 0x102ac5c6LU, 0xfe249d02LU, 0xa4e56e85LU, 0x6f382dc7LU, 0x35f9de40LU, 0xdbf78684LU, 0x81367503LU, +0x949b6c82LU, 0xce5a9f05LU, 0x2054c7c1LU, 0x7a953446LU, 0xb1487704LU, 0xeb898483LU, 0x0587dc47LU, 0x5f462fc0LU, +0xde705ac3LU, 0x84b1a944LU, 0x6abff180LU, 0x307e0207LU, 0xfba34145LU, 0xa162b2c2LU, 0x4f6cea06LU, 0x15ad1981LU, +0x657bd849LU, 0x3fba2bceLU, 0xd1b4730aLU, 0x8b75808dLU, 0x40a8c3cfLU, 0x1a693048LU, 0xf467688cLU, 0xaea69b0bLU, +0x2f90ee08LU, 0x75511d8fLU, 0x9b5f454bLU, 0xc19eb6ccLU, 0x0a43f58eLU, 0x50820609LU, 0xbe8c5ecdLU, 0xe44dad4aLU, +0xf1e0b4cbLU, 0xab21474cLU, 0x452f1f88LU, 0x1feeec0fLU, 0xd433af4dLU, 0x8ef25ccaLU, 0x60fc040eLU, 0x3a3df789LU, +0xbb0b828aLU, 0xe1ca710dLU, 0x0fc429c9LU, 0x5505da4eLU, 0x9ed8990cLU, 0xc4196a8bLU, 0x2a17324fLU, 0x70d6c1c8LU, +0xcaf6fd92LU, 0x90370e15LU, 0x7e3956d1LU, 0x24f8a556LU, 0xef25e614LU, 0xb5e41593LU, 0x5bea4d57LU, 0x012bbed0LU, +0x801dcbd3LU, 0xdadc3854LU, 0x34d26090LU, 0x6e139317LU, 0xa5ced055LU, 0xff0f23d2LU, 0x11017b16LU, 0x4bc08891LU, +0x5e6d9110LU, 0x04ac6297LU, 0xeaa23a53LU, 0xb063c9d4LU, 0x7bbe8a96LU, 0x217f7911LU, 0xcf7121d5LU, 0x95b0d252LU, +0x1486a751LU, 0x4e4754d6LU, 0xa0490c12LU, 0xfa88ff95LU, 0x3155bcd7LU, 0x6b944f50LU, 0x859a1794LU, 0xdf5be413LU, +0xaf8d25dbLU, 0xf54cd65cLU, 0x1b428e98LU, 0x41837d1fLU, 0x8a5e3e5dLU, 0xd09fcddaLU, 0x3e91951eLU, 0x64506699LU, +0xe566139aLU, 0xbfa7e01dLU, 0x51a9b8d9LU, 0x0b684b5eLU, 0xc0b5081cLU, 0x9a74fb9bLU, 0x747aa35fLU, 0x2ebb50d8LU, +0x3b164959LU, 0x61d7badeLU, 0x8fd9e21aLU, 0xd518119dLU, 0x1ec552dfLU, 0x4404a158LU, 0xaa0af99cLU, 0xf0cb0a1bLU, +0x71fd7f18LU, 0x2b3c8c9fLU, 0xc532d45bLU, 0x9ff327dcLU, 0x542e649eLU, 0x0eef9719LU, 0xe0e1cfddLU, 0xba203c5aLU, +0xd9a1b769LU, 0x836044eeLU, 0x6d6e1c2aLU, 0x37afefadLU, 0xfc72acefLU, 0xa6b35f68LU, 0x48bd07acLU, 0x127cf42bLU, +0x934a8128LU, 0xc98b72afLU, 0x27852a6bLU, 0x7d44d9ecLU, 0xb6999aaeLU, 0xec586929LU, 0x025631edLU, 0x5897c26aLU, +0x4d3adbebLU, 0x17fb286cLU, 0xf9f570a8LU, 0xa334832fLU, 0x68e9c06dLU, 0x322833eaLU, 0xdc266b2eLU, 0x86e798a9LU, +0x07d1edaaLU, 0x5d101e2dLU, 0xb31e46e9LU, 0xe9dfb56eLU, 0x2202f62cLU, 0x78c305abLU, 0x96cd5d6fLU, 0xcc0caee8LU, +0xbcda6f20LU, 0xe61b9ca7LU, 0x0815c463LU, 0x52d437e4LU, 0x990974a6LU, 0xc3c88721LU, 0x2dc6dfe5LU, 0x77072c62LU, +0xf6315961LU, 0xacf0aae6LU, 0x42fef222LU, 0x183f01a5LU, 0xd3e242e7LU, 0x8923b160LU, 0x672de9a4LU, 0x3dec1a23LU, +0x284103a2LU, 0x7280f025LU, 0x9c8ea8e1LU, 0xc64f5b66LU, 0x0d921824LU, 0x5753eba3LU, 0xb95db367LU, 0xe39c40e0LU, +0x62aa35e3LU, 0x386bc664LU, 0xd6659ea0LU, 0x8ca46d27LU, 0x47792e65LU, 0x1db8dde2LU, 0xf3b68526LU, 0xa97776a1LU, +0x13574afbLU, 0x4996b97cLU, 0xa798e1b8LU, 0xfd59123fLU, 0x3684517dLU, 0x6c45a2faLU, 0x824bfa3eLU, 0xd88a09b9LU, +0x59bc7cbaLU, 0x037d8f3dLU, 0xed73d7f9LU, 0xb7b2247eLU, 0x7c6f673cLU, 0x26ae94bbLU, 0xc8a0cc7fLU, 0x92613ff8LU, +0x87cc2679LU, 0xdd0dd5feLU, 0x33038d3aLU, 0x69c27ebdLU, 0xa21f3dffLU, 0xf8dece78LU, 0x16d096bcLU, 0x4c11653bLU, +0xcd271038LU, 0x97e6e3bfLU, 0x79e8bb7bLU, 0x232948fcLU, 0xe8f40bbeLU, 0xb235f839LU, 0x5c3ba0fdLU, 0x06fa537aLU, +0x762c92b2LU, 0x2ced6135LU, 0xc2e339f1LU, 0x9822ca76LU, 0x53ff8934LU, 0x093e7ab3LU, 0xe7302277LU, 0xbdf1d1f0LU, +0x3cc7a4f3LU, 0x66065774LU, 0x88080fb0LU, 0xd2c9fc37LU, 0x1914bf75LU, 0x43d54cf2LU, 0xaddb1436LU, 0xf71ae7b1LU, +0xe2b7fe30LU, 0xb8760db7LU, 0x56785573LU, 0x0cb9a6f4LU, 0xc764e5b6LU, 0x9da51631LU, 0x73ab4ef5LU, 0x296abd72LU, +0xa85cc871LU, 0xf29d3bf6LU, 0x1c936332LU, 0x465290b5LU, 0x8d8fd3f7LU, 0xd74e2070LU, 0x394078b4LU, 0x63818b33LU }; + +static const ulong32 rs_tab4[256] = { +0x00000000LU, 0x58471e5aLU, 0xb08e3cb4LU, 0xe8c922eeLU, 0x2d517825LU, 0x7516667fLU, 0x9ddf4491LU, 0xc5985acbLU, +0x5aa2f04aLU, 0x02e5ee10LU, 0xea2cccfeLU, 0xb26bd2a4LU, 0x77f3886fLU, 0x2fb49635LU, 0xc77db4dbLU, 0x9f3aaa81LU, +0xb409ad94LU, 0xec4eb3ceLU, 0x04879120LU, 0x5cc08f7aLU, 0x9958d5b1LU, 0xc11fcbebLU, 0x29d6e905LU, 0x7191f75fLU, +0xeeab5ddeLU, 0xb6ec4384LU, 0x5e25616aLU, 0x06627f30LU, 0xc3fa25fbLU, 0x9bbd3ba1LU, 0x7374194fLU, 0x2b330715LU, +0x25121765LU, 0x7d55093fLU, 0x959c2bd1LU, 0xcddb358bLU, 0x08436f40LU, 0x5004711aLU, 0xb8cd53f4LU, 0xe08a4daeLU, +0x7fb0e72fLU, 0x27f7f975LU, 0xcf3edb9bLU, 0x9779c5c1LU, 0x52e19f0aLU, 0x0aa68150LU, 0xe26fa3beLU, 0xba28bde4LU, +0x911bbaf1LU, 0xc95ca4abLU, 0x21958645LU, 0x79d2981fLU, 0xbc4ac2d4LU, 0xe40ddc8eLU, 0x0cc4fe60LU, 0x5483e03aLU, +0xcbb94abbLU, 0x93fe54e1LU, 0x7b37760fLU, 0x23706855LU, 0xe6e8329eLU, 0xbeaf2cc4LU, 0x56660e2aLU, 0x0e211070LU, +0x4a242ecaLU, 0x12633090LU, 0xfaaa127eLU, 0xa2ed0c24LU, 0x677556efLU, 0x3f3248b5LU, 0xd7fb6a5bLU, 0x8fbc7401LU, +0x1086de80LU, 0x48c1c0daLU, 0xa008e234LU, 0xf84ffc6eLU, 0x3dd7a6a5LU, 0x6590b8ffLU, 0x8d599a11LU, 0xd51e844bLU, +0xfe2d835eLU, 0xa66a9d04LU, 0x4ea3bfeaLU, 0x16e4a1b0LU, 0xd37cfb7bLU, 0x8b3be521LU, 0x63f2c7cfLU, 0x3bb5d995LU, +0xa48f7314LU, 0xfcc86d4eLU, 0x14014fa0LU, 0x4c4651faLU, 0x89de0b31LU, 0xd199156bLU, 0x39503785LU, 0x611729dfLU, +0x6f3639afLU, 0x377127f5LU, 0xdfb8051bLU, 0x87ff1b41LU, 0x4267418aLU, 0x1a205fd0LU, 0xf2e97d3eLU, 0xaaae6364LU, +0x3594c9e5LU, 0x6dd3d7bfLU, 0x851af551LU, 0xdd5deb0bLU, 0x18c5b1c0LU, 0x4082af9aLU, 0xa84b8d74LU, 0xf00c932eLU, +0xdb3f943bLU, 0x83788a61LU, 0x6bb1a88fLU, 0x33f6b6d5LU, 0xf66eec1eLU, 0xae29f244LU, 0x46e0d0aaLU, 0x1ea7cef0LU, +0x819d6471LU, 0xd9da7a2bLU, 0x311358c5LU, 0x6954469fLU, 0xaccc1c54LU, 0xf48b020eLU, 0x1c4220e0LU, 0x44053ebaLU, +0x94485cd9LU, 0xcc0f4283LU, 0x24c6606dLU, 0x7c817e37LU, 0xb91924fcLU, 0xe15e3aa6LU, 0x09971848LU, 0x51d00612LU, +0xceeaac93LU, 0x96adb2c9LU, 0x7e649027LU, 0x26238e7dLU, 0xe3bbd4b6LU, 0xbbfccaecLU, 0x5335e802LU, 0x0b72f658LU, +0x2041f14dLU, 0x7806ef17LU, 0x90cfcdf9LU, 0xc888d3a3LU, 0x0d108968LU, 0x55579732LU, 0xbd9eb5dcLU, 0xe5d9ab86LU, +0x7ae30107LU, 0x22a41f5dLU, 0xca6d3db3LU, 0x922a23e9LU, 0x57b27922LU, 0x0ff56778LU, 0xe73c4596LU, 0xbf7b5bccLU, +0xb15a4bbcLU, 0xe91d55e6LU, 0x01d47708LU, 0x59936952LU, 0x9c0b3399LU, 0xc44c2dc3LU, 0x2c850f2dLU, 0x74c21177LU, +0xebf8bbf6LU, 0xb3bfa5acLU, 0x5b768742LU, 0x03319918LU, 0xc6a9c3d3LU, 0x9eeedd89LU, 0x7627ff67LU, 0x2e60e13dLU, +0x0553e628LU, 0x5d14f872LU, 0xb5ddda9cLU, 0xed9ac4c6LU, 0x28029e0dLU, 0x70458057LU, 0x988ca2b9LU, 0xc0cbbce3LU, +0x5ff11662LU, 0x07b60838LU, 0xef7f2ad6LU, 0xb738348cLU, 0x72a06e47LU, 0x2ae7701dLU, 0xc22e52f3LU, 0x9a694ca9LU, +0xde6c7213LU, 0x862b6c49LU, 0x6ee24ea7LU, 0x36a550fdLU, 0xf33d0a36LU, 0xab7a146cLU, 0x43b33682LU, 0x1bf428d8LU, +0x84ce8259LU, 0xdc899c03LU, 0x3440beedLU, 0x6c07a0b7LU, 0xa99ffa7cLU, 0xf1d8e426LU, 0x1911c6c8LU, 0x4156d892LU, +0x6a65df87LU, 0x3222c1ddLU, 0xdaebe333LU, 0x82acfd69LU, 0x4734a7a2LU, 0x1f73b9f8LU, 0xf7ba9b16LU, 0xaffd854cLU, +0x30c72fcdLU, 0x68803197LU, 0x80491379LU, 0xd80e0d23LU, 0x1d9657e8LU, 0x45d149b2LU, 0xad186b5cLU, 0xf55f7506LU, +0xfb7e6576LU, 0xa3397b2cLU, 0x4bf059c2LU, 0x13b74798LU, 0xd62f1d53LU, 0x8e680309LU, 0x66a121e7LU, 0x3ee63fbdLU, +0xa1dc953cLU, 0xf99b8b66LU, 0x1152a988LU, 0x4915b7d2LU, 0x8c8ded19LU, 0xd4caf343LU, 0x3c03d1adLU, 0x6444cff7LU, +0x4f77c8e2LU, 0x1730d6b8LU, 0xfff9f456LU, 0xa7beea0cLU, 0x6226b0c7LU, 0x3a61ae9dLU, 0xd2a88c73LU, 0x8aef9229LU, +0x15d538a8LU, 0x4d9226f2LU, 0xa55b041cLU, 0xfd1c1a46LU, 0x3884408dLU, 0x60c35ed7LU, 0x880a7c39LU, 0xd04d6263LU }; + +static const ulong32 rs_tab5[256] = { +0x00000000LU, 0xdbaec658LU, 0xfb11c1b0LU, 0x20bf07e8LU, 0xbb22cf2dLU, 0x608c0975LU, 0x40330e9dLU, 0x9b9dc8c5LU, +0x3b44d35aLU, 0xe0ea1502LU, 0xc05512eaLU, 0x1bfbd4b2LU, 0x80661c77LU, 0x5bc8da2fLU, 0x7b77ddc7LU, 0xa0d91b9fLU, +0x7688ebb4LU, 0xad262decLU, 0x8d992a04LU, 0x5637ec5cLU, 0xcdaa2499LU, 0x1604e2c1LU, 0x36bbe529LU, 0xed152371LU, +0x4dcc38eeLU, 0x9662feb6LU, 0xb6ddf95eLU, 0x6d733f06LU, 0xf6eef7c3LU, 0x2d40319bLU, 0x0dff3673LU, 0xd651f02bLU, +0xec5d9b25LU, 0x37f35d7dLU, 0x174c5a95LU, 0xcce29ccdLU, 0x577f5408LU, 0x8cd19250LU, 0xac6e95b8LU, 0x77c053e0LU, +0xd719487fLU, 0x0cb78e27LU, 0x2c0889cfLU, 0xf7a64f97LU, 0x6c3b8752LU, 0xb795410aLU, 0x972a46e2LU, 0x4c8480baLU, +0x9ad57091LU, 0x417bb6c9LU, 0x61c4b121LU, 0xba6a7779LU, 0x21f7bfbcLU, 0xfa5979e4LU, 0xdae67e0cLU, 0x0148b854LU, +0xa191a3cbLU, 0x7a3f6593LU, 0x5a80627bLU, 0x812ea423LU, 0x1ab36ce6LU, 0xc11daabeLU, 0xe1a2ad56LU, 0x3a0c6b0eLU, +0x95ba7b4aLU, 0x4e14bd12LU, 0x6eabbafaLU, 0xb5057ca2LU, 0x2e98b467LU, 0xf536723fLU, 0xd58975d7LU, 0x0e27b38fLU, +0xaefea810LU, 0x75506e48LU, 0x55ef69a0LU, 0x8e41aff8LU, 0x15dc673dLU, 0xce72a165LU, 0xeecda68dLU, 0x356360d5LU, +0xe33290feLU, 0x389c56a6LU, 0x1823514eLU, 0xc38d9716LU, 0x58105fd3LU, 0x83be998bLU, 0xa3019e63LU, 0x78af583bLU, +0xd87643a4LU, 0x03d885fcLU, 0x23678214LU, 0xf8c9444cLU, 0x63548c89LU, 0xb8fa4ad1LU, 0x98454d39LU, 0x43eb8b61LU, +0x79e7e06fLU, 0xa2492637LU, 0x82f621dfLU, 0x5958e787LU, 0xc2c52f42LU, 0x196be91aLU, 0x39d4eef2LU, 0xe27a28aaLU, +0x42a33335LU, 0x990df56dLU, 0xb9b2f285LU, 0x621c34ddLU, 0xf981fc18LU, 0x222f3a40LU, 0x02903da8LU, 0xd93efbf0LU, +0x0f6f0bdbLU, 0xd4c1cd83LU, 0xf47eca6bLU, 0x2fd00c33LU, 0xb44dc4f6LU, 0x6fe302aeLU, 0x4f5c0546LU, 0x94f2c31eLU, +0x342bd881LU, 0xef851ed9LU, 0xcf3a1931LU, 0x1494df69LU, 0x8f0917acLU, 0x54a7d1f4LU, 0x7418d61cLU, 0xafb61044LU, +0x6739f694LU, 0xbc9730ccLU, 0x9c283724LU, 0x4786f17cLU, 0xdc1b39b9LU, 0x07b5ffe1LU, 0x270af809LU, 0xfca43e51LU, +0x5c7d25ceLU, 0x87d3e396LU, 0xa76ce47eLU, 0x7cc22226LU, 0xe75feae3LU, 0x3cf12cbbLU, 0x1c4e2b53LU, 0xc7e0ed0bLU, +0x11b11d20LU, 0xca1fdb78LU, 0xeaa0dc90LU, 0x310e1ac8LU, 0xaa93d20dLU, 0x713d1455LU, 0x518213bdLU, 0x8a2cd5e5LU, +0x2af5ce7aLU, 0xf15b0822LU, 0xd1e40fcaLU, 0x0a4ac992LU, 0x91d70157LU, 0x4a79c70fLU, 0x6ac6c0e7LU, 0xb16806bfLU, +0x8b646db1LU, 0x50caabe9LU, 0x7075ac01LU, 0xabdb6a59LU, 0x3046a29cLU, 0xebe864c4LU, 0xcb57632cLU, 0x10f9a574LU, +0xb020beebLU, 0x6b8e78b3LU, 0x4b317f5bLU, 0x909fb903LU, 0x0b0271c6LU, 0xd0acb79eLU, 0xf013b076LU, 0x2bbd762eLU, +0xfdec8605LU, 0x2642405dLU, 0x06fd47b5LU, 0xdd5381edLU, 0x46ce4928LU, 0x9d608f70LU, 0xbddf8898LU, 0x66714ec0LU, +0xc6a8555fLU, 0x1d069307LU, 0x3db994efLU, 0xe61752b7LU, 0x7d8a9a72LU, 0xa6245c2aLU, 0x869b5bc2LU, 0x5d359d9aLU, +0xf2838ddeLU, 0x292d4b86LU, 0x09924c6eLU, 0xd23c8a36LU, 0x49a142f3LU, 0x920f84abLU, 0xb2b08343LU, 0x691e451bLU, +0xc9c75e84LU, 0x126998dcLU, 0x32d69f34LU, 0xe978596cLU, 0x72e591a9LU, 0xa94b57f1LU, 0x89f45019LU, 0x525a9641LU, +0x840b666aLU, 0x5fa5a032LU, 0x7f1aa7daLU, 0xa4b46182LU, 0x3f29a947LU, 0xe4876f1fLU, 0xc43868f7LU, 0x1f96aeafLU, +0xbf4fb530LU, 0x64e17368LU, 0x445e7480LU, 0x9ff0b2d8LU, 0x046d7a1dLU, 0xdfc3bc45LU, 0xff7cbbadLU, 0x24d27df5LU, +0x1ede16fbLU, 0xc570d0a3LU, 0xe5cfd74bLU, 0x3e611113LU, 0xa5fcd9d6LU, 0x7e521f8eLU, 0x5eed1866LU, 0x8543de3eLU, +0x259ac5a1LU, 0xfe3403f9LU, 0xde8b0411LU, 0x0525c249LU, 0x9eb80a8cLU, 0x4516ccd4LU, 0x65a9cb3cLU, 0xbe070d64LU, +0x6856fd4fLU, 0xb3f83b17LU, 0x93473cffLU, 0x48e9faa7LU, 0xd3743262LU, 0x08daf43aLU, 0x2865f3d2LU, 0xf3cb358aLU, +0x53122e15LU, 0x88bce84dLU, 0xa803efa5LU, 0x73ad29fdLU, 0xe830e138LU, 0x339e2760LU, 0x13212088LU, 0xc88fe6d0LU }; + +static const ulong32 rs_tab6[256] = { +0x00000000LU, 0x9e3d68dbLU, 0x717ad0fbLU, 0xef47b820LU, 0xe2f4edbbLU, 0x7cc98560LU, 0x938e3d40LU, 0x0db3559bLU, +0x89a5973bLU, 0x1798ffe0LU, 0xf8df47c0LU, 0x66e22f1bLU, 0x6b517a80LU, 0xf56c125bLU, 0x1a2baa7bLU, 0x8416c2a0LU, +0x5f076376LU, 0xc13a0badLU, 0x2e7db38dLU, 0xb040db56LU, 0xbdf38ecdLU, 0x23cee616LU, 0xcc895e36LU, 0x52b436edLU, +0xd6a2f44dLU, 0x489f9c96LU, 0xa7d824b6LU, 0x39e54c6dLU, 0x345619f6LU, 0xaa6b712dLU, 0x452cc90dLU, 0xdb11a1d6LU, +0xbe0ec6ecLU, 0x2033ae37LU, 0xcf741617LU, 0x51497eccLU, 0x5cfa2b57LU, 0xc2c7438cLU, 0x2d80fbacLU, 0xb3bd9377LU, +0x37ab51d7LU, 0xa996390cLU, 0x46d1812cLU, 0xd8ece9f7LU, 0xd55fbc6cLU, 0x4b62d4b7LU, 0xa4256c97LU, 0x3a18044cLU, +0xe109a59aLU, 0x7f34cd41LU, 0x90737561LU, 0x0e4e1dbaLU, 0x03fd4821LU, 0x9dc020faLU, 0x728798daLU, 0xecbaf001LU, +0x68ac32a1LU, 0xf6915a7aLU, 0x19d6e25aLU, 0x87eb8a81LU, 0x8a58df1aLU, 0x1465b7c1LU, 0xfb220fe1LU, 0x651f673aLU, +0x311cc195LU, 0xaf21a94eLU, 0x4066116eLU, 0xde5b79b5LU, 0xd3e82c2eLU, 0x4dd544f5LU, 0xa292fcd5LU, 0x3caf940eLU, +0xb8b956aeLU, 0x26843e75LU, 0xc9c38655LU, 0x57feee8eLU, 0x5a4dbb15LU, 0xc470d3ceLU, 0x2b376beeLU, 0xb50a0335LU, +0x6e1ba2e3LU, 0xf026ca38LU, 0x1f617218LU, 0x815c1ac3LU, 0x8cef4f58LU, 0x12d22783LU, 0xfd959fa3LU, 0x63a8f778LU, +0xe7be35d8LU, 0x79835d03LU, 0x96c4e523LU, 0x08f98df8LU, 0x054ad863LU, 0x9b77b0b8LU, 0x74300898LU, 0xea0d6043LU, +0x8f120779LU, 0x112f6fa2LU, 0xfe68d782LU, 0x6055bf59LU, 0x6de6eac2LU, 0xf3db8219LU, 0x1c9c3a39LU, 0x82a152e2LU, +0x06b79042LU, 0x988af899LU, 0x77cd40b9LU, 0xe9f02862LU, 0xe4437df9LU, 0x7a7e1522LU, 0x9539ad02LU, 0x0b04c5d9LU, +0xd015640fLU, 0x4e280cd4LU, 0xa16fb4f4LU, 0x3f52dc2fLU, 0x32e189b4LU, 0xacdce16fLU, 0x439b594fLU, 0xdda63194LU, +0x59b0f334LU, 0xc78d9befLU, 0x28ca23cfLU, 0xb6f74b14LU, 0xbb441e8fLU, 0x25797654LU, 0xca3ece74LU, 0x5403a6afLU, +0x6238cf67LU, 0xfc05a7bcLU, 0x13421f9cLU, 0x8d7f7747LU, 0x80cc22dcLU, 0x1ef14a07LU, 0xf1b6f227LU, 0x6f8b9afcLU, +0xeb9d585cLU, 0x75a03087LU, 0x9ae788a7LU, 0x04dae07cLU, 0x0969b5e7LU, 0x9754dd3cLU, 0x7813651cLU, 0xe62e0dc7LU, +0x3d3fac11LU, 0xa302c4caLU, 0x4c457ceaLU, 0xd2781431LU, 0xdfcb41aaLU, 0x41f62971LU, 0xaeb19151LU, 0x308cf98aLU, +0xb49a3b2aLU, 0x2aa753f1LU, 0xc5e0ebd1LU, 0x5bdd830aLU, 0x566ed691LU, 0xc853be4aLU, 0x2714066aLU, 0xb9296eb1LU, +0xdc36098bLU, 0x420b6150LU, 0xad4cd970LU, 0x3371b1abLU, 0x3ec2e430LU, 0xa0ff8cebLU, 0x4fb834cbLU, 0xd1855c10LU, +0x55939eb0LU, 0xcbaef66bLU, 0x24e94e4bLU, 0xbad42690LU, 0xb767730bLU, 0x295a1bd0LU, 0xc61da3f0LU, 0x5820cb2bLU, +0x83316afdLU, 0x1d0c0226LU, 0xf24bba06LU, 0x6c76d2ddLU, 0x61c58746LU, 0xfff8ef9dLU, 0x10bf57bdLU, 0x8e823f66LU, +0x0a94fdc6LU, 0x94a9951dLU, 0x7bee2d3dLU, 0xe5d345e6LU, 0xe860107dLU, 0x765d78a6LU, 0x991ac086LU, 0x0727a85dLU, +0x53240ef2LU, 0xcd196629LU, 0x225ede09LU, 0xbc63b6d2LU, 0xb1d0e349LU, 0x2fed8b92LU, 0xc0aa33b2LU, 0x5e975b69LU, +0xda8199c9LU, 0x44bcf112LU, 0xabfb4932LU, 0x35c621e9LU, 0x38757472LU, 0xa6481ca9LU, 0x490fa489LU, 0xd732cc52LU, +0x0c236d84LU, 0x921e055fLU, 0x7d59bd7fLU, 0xe364d5a4LU, 0xeed7803fLU, 0x70eae8e4LU, 0x9fad50c4LU, 0x0190381fLU, +0x8586fabfLU, 0x1bbb9264LU, 0xf4fc2a44LU, 0x6ac1429fLU, 0x67721704LU, 0xf94f7fdfLU, 0x1608c7ffLU, 0x8835af24LU, +0xed2ac81eLU, 0x7317a0c5LU, 0x9c5018e5LU, 0x026d703eLU, 0x0fde25a5LU, 0x91e34d7eLU, 0x7ea4f55eLU, 0xe0999d85LU, +0x648f5f25LU, 0xfab237feLU, 0x15f58fdeLU, 0x8bc8e705LU, 0x867bb29eLU, 0x1846da45LU, 0xf7016265LU, 0x693c0abeLU, +0xb22dab68LU, 0x2c10c3b3LU, 0xc3577b93LU, 0x5d6a1348LU, 0x50d946d3LU, 0xcee42e08LU, 0x21a39628LU, 0xbf9efef3LU, +0x3b883c53LU, 0xa5b55488LU, 0x4af2eca8LU, 0xd4cf8473LU, 0xd97cd1e8LU, 0x4741b933LU, 0xa8060113LU, 0x363b69c8LU }; + +static const ulong32 rs_tab7[256] = { +0x00000000LU, 0x0319e59eLU, 0x06328771LU, 0x052b62efLU, 0x0c6443e2LU, 0x0f7da67cLU, 0x0a56c493LU, 0x094f210dLU, +0x18c88689LU, 0x1bd16317LU, 0x1efa01f8LU, 0x1de3e466LU, 0x14acc56bLU, 0x17b520f5LU, 0x129e421aLU, 0x1187a784LU, +0x30dd415fLU, 0x33c4a4c1LU, 0x36efc62eLU, 0x35f623b0LU, 0x3cb902bdLU, 0x3fa0e723LU, 0x3a8b85ccLU, 0x39926052LU, +0x2815c7d6LU, 0x2b0c2248LU, 0x2e2740a7LU, 0x2d3ea539LU, 0x24718434LU, 0x276861aaLU, 0x22430345LU, 0x215ae6dbLU, +0x60f782beLU, 0x63ee6720LU, 0x66c505cfLU, 0x65dce051LU, 0x6c93c15cLU, 0x6f8a24c2LU, 0x6aa1462dLU, 0x69b8a3b3LU, +0x783f0437LU, 0x7b26e1a9LU, 0x7e0d8346LU, 0x7d1466d8LU, 0x745b47d5LU, 0x7742a24bLU, 0x7269c0a4LU, 0x7170253aLU, +0x502ac3e1LU, 0x5333267fLU, 0x56184490LU, 0x5501a10eLU, 0x5c4e8003LU, 0x5f57659dLU, 0x5a7c0772LU, 0x5965e2ecLU, +0x48e24568LU, 0x4bfba0f6LU, 0x4ed0c219LU, 0x4dc92787LU, 0x4486068aLU, 0x479fe314LU, 0x42b481fbLU, 0x41ad6465LU, +0xc0a34931LU, 0xc3baacafLU, 0xc691ce40LU, 0xc5882bdeLU, 0xccc70ad3LU, 0xcfdeef4dLU, 0xcaf58da2LU, 0xc9ec683cLU, +0xd86bcfb8LU, 0xdb722a26LU, 0xde5948c9LU, 0xdd40ad57LU, 0xd40f8c5aLU, 0xd71669c4LU, 0xd23d0b2bLU, 0xd124eeb5LU, +0xf07e086eLU, 0xf367edf0LU, 0xf64c8f1fLU, 0xf5556a81LU, 0xfc1a4b8cLU, 0xff03ae12LU, 0xfa28ccfdLU, 0xf9312963LU, +0xe8b68ee7LU, 0xebaf6b79LU, 0xee840996LU, 0xed9dec08LU, 0xe4d2cd05LU, 0xe7cb289bLU, 0xe2e04a74LU, 0xe1f9afeaLU, +0xa054cb8fLU, 0xa34d2e11LU, 0xa6664cfeLU, 0xa57fa960LU, 0xac30886dLU, 0xaf296df3LU, 0xaa020f1cLU, 0xa91bea82LU, +0xb89c4d06LU, 0xbb85a898LU, 0xbeaeca77LU, 0xbdb72fe9LU, 0xb4f80ee4LU, 0xb7e1eb7aLU, 0xb2ca8995LU, 0xb1d36c0bLU, +0x90898ad0LU, 0x93906f4eLU, 0x96bb0da1LU, 0x95a2e83fLU, 0x9cedc932LU, 0x9ff42cacLU, 0x9adf4e43LU, 0x99c6abddLU, +0x88410c59LU, 0x8b58e9c7LU, 0x8e738b28LU, 0x8d6a6eb6LU, 0x84254fbbLU, 0x873caa25LU, 0x8217c8caLU, 0x810e2d54LU, +0xcd0b9262LU, 0xce1277fcLU, 0xcb391513LU, 0xc820f08dLU, 0xc16fd180LU, 0xc276341eLU, 0xc75d56f1LU, 0xc444b36fLU, +0xd5c314ebLU, 0xd6daf175LU, 0xd3f1939aLU, 0xd0e87604LU, 0xd9a75709LU, 0xdabeb297LU, 0xdf95d078LU, 0xdc8c35e6LU, +0xfdd6d33dLU, 0xfecf36a3LU, 0xfbe4544cLU, 0xf8fdb1d2LU, 0xf1b290dfLU, 0xf2ab7541LU, 0xf78017aeLU, 0xf499f230LU, +0xe51e55b4LU, 0xe607b02aLU, 0xe32cd2c5LU, 0xe035375bLU, 0xe97a1656LU, 0xea63f3c8LU, 0xef489127LU, 0xec5174b9LU, +0xadfc10dcLU, 0xaee5f542LU, 0xabce97adLU, 0xa8d77233LU, 0xa198533eLU, 0xa281b6a0LU, 0xa7aad44fLU, 0xa4b331d1LU, +0xb5349655LU, 0xb62d73cbLU, 0xb3061124LU, 0xb01ff4baLU, 0xb950d5b7LU, 0xba493029LU, 0xbf6252c6LU, 0xbc7bb758LU, +0x9d215183LU, 0x9e38b41dLU, 0x9b13d6f2LU, 0x980a336cLU, 0x91451261LU, 0x925cf7ffLU, 0x97779510LU, 0x946e708eLU, +0x85e9d70aLU, 0x86f03294LU, 0x83db507bLU, 0x80c2b5e5LU, 0x898d94e8LU, 0x8a947176LU, 0x8fbf1399LU, 0x8ca6f607LU, +0x0da8db53LU, 0x0eb13ecdLU, 0x0b9a5c22LU, 0x0883b9bcLU, 0x01cc98b1LU, 0x02d57d2fLU, 0x07fe1fc0LU, 0x04e7fa5eLU, +0x15605ddaLU, 0x1679b844LU, 0x1352daabLU, 0x104b3f35LU, 0x19041e38LU, 0x1a1dfba6LU, 0x1f369949LU, 0x1c2f7cd7LU, +0x3d759a0cLU, 0x3e6c7f92LU, 0x3b471d7dLU, 0x385ef8e3LU, 0x3111d9eeLU, 0x32083c70LU, 0x37235e9fLU, 0x343abb01LU, +0x25bd1c85LU, 0x26a4f91bLU, 0x238f9bf4LU, 0x20967e6aLU, 0x29d95f67LU, 0x2ac0baf9LU, 0x2febd816LU, 0x2cf23d88LU, +0x6d5f59edLU, 0x6e46bc73LU, 0x6b6dde9cLU, 0x68743b02LU, 0x613b1a0fLU, 0x6222ff91LU, 0x67099d7eLU, 0x641078e0LU, +0x7597df64LU, 0x768e3afaLU, 0x73a55815LU, 0x70bcbd8bLU, 0x79f39c86LU, 0x7aea7918LU, 0x7fc11bf7LU, 0x7cd8fe69LU, +0x5d8218b2LU, 0x5e9bfd2cLU, 0x5bb09fc3LU, 0x58a97a5dLU, 0x51e65b50LU, 0x52ffbeceLU, 0x57d4dc21LU, 0x54cd39bfLU, +0x454a9e3bLU, 0x46537ba5LU, 0x4378194aLU, 0x4061fcd4LU, 0x492eddd9LU, 0x4a373847LU, 0x4f1c5aa8LU, 0x4c05bf36LU }; + +#endif /* LTC_TWOFISH_ALL_TABLES */ + +#endif /* LTC_TWOFISH_TAB_C */ +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/ciphers/xtea.c b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/xtea.c new file mode 100644 index 0000000..95aaa1a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/ciphers/xtea.c @@ -0,0 +1,251 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file xtea.c + Implementation of eXtended TEA, Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_XTEA + +const struct ltc_cipher_descriptor xtea_desc = +{ + "xtea", + 1, + 16, 16, 8, 32, + &xtea_setup, + &xtea_ecb_encrypt, + &xtea_ecb_decrypt, + &xtea_test, + &xtea_done, + &xtea_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + ulong32 x, sum, K[4]; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* check arguments */ + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != 32) { + return CRYPT_INVALID_ROUNDS; + } + + /* load key */ + LOAD32H(K[0], key+0); + LOAD32H(K[1], key+4); + LOAD32H(K[2], key+8); + LOAD32H(K[3], key+12); + + for (x = sum = 0; x < 32; x++) { + skey->xtea.A[x] = (sum + K[sum&3]) & 0xFFFFFFFFUL; + sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL; + skey->xtea.B[x] = (sum + K[(sum>>11)&3]) & 0xFFFFFFFFUL; + } + +#ifdef LTC_CLEAN_STACK + zeromem(&K, sizeof(K)); +#endif + + return CRYPT_OK; +} + +/** + Encrypts a block of text with LTC_XTEA + @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 xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 y, z; + int r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(y, &pt[0]); + LOAD32H(z, &pt[4]); + for (r = 0; r < 32; r += 4) { + y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; + z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; + + y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+1])) & 0xFFFFFFFFUL; + z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+1])) & 0xFFFFFFFFUL; + + y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+2])) & 0xFFFFFFFFUL; + z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+2])) & 0xFFFFFFFFUL; + + y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+3])) & 0xFFFFFFFFUL; + z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+3])) & 0xFFFFFFFFUL; + } + STORE32H(y, &ct[0]); + STORE32H(z, &ct[4]); + return CRYPT_OK; +} + +/** + Decrypts a block of text with LTC_XTEA + @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 xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 y, z; + int r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(y, &ct[0]); + LOAD32H(z, &ct[4]); + for (r = 31; r >= 0; r -= 4) { + z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; + y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; + + z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-1])) & 0xFFFFFFFFUL; + y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-1])) & 0xFFFFFFFFUL; + + z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-2])) & 0xFFFFFFFFUL; + y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-2])) & 0xFFFFFFFFUL; + + z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-3])) & 0xFFFFFFFFUL; + y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-3])) & 0xFFFFFFFFUL; + } + STORE32H(y, &pt[0]); + STORE32H(z, &pt[4]); + return CRYPT_OK; +} + +/** + Performs a self-test of the LTC_XTEA block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int xtea_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xde, 0xe9, 0xd4, 0xd8, 0xf7, 0x13, 0x1e, 0xd9 } + }, { + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xa5, 0x97, 0xab, 0x41, 0x76, 0x01, 0x4d, 0x72 } + }, { + { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06 }, + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 }, + { 0xb1, 0xfd, 0x5d, 0xa9, 0xcc, 0x6d, 0xc9, 0xdc } + }, { + { 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, + 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, + { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, + { 0x70, 0x4b, 0x31, 0x34, 0x47, 0x44, 0xdf, 0xab } + }, { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 } + }, { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 } + }, { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } + }, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 } + }, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d } + }, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } + } + }; + unsigned char tmp[2][8]; + symmetric_key skey; + int i, err, y; + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + zeromem(&skey, sizeof(skey)); + if ((err = xtea_setup(tests[i].key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + xtea_ecb_encrypt(tests[i].pt, tmp[0], &skey); + xtea_ecb_decrypt(tmp[0], tmp[1], &skey); + + if (compare_testvector(tmp[0], 8, tests[i].ct, 8, "XTEA Encrypt", i) != 0 || + compare_testvector(tmp[1], 8, tests[i].pt, 8, "XTEA Decrypt", i) != 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[0][y] = 0; + for (y = 0; y < 1000; y++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } /* for */ + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void xtea_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(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 xtea_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + + +#endif + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c new file mode 100644 index 0000000..2bb9e0b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Add AAD to the CCM state + @param ccm The CCM state + @param adata The additional authentication data to add to the CCM state + @param adatalen The length of the AAD data. + @return CRYPT_OK on success + */ +int ccm_add_aad(ccm_state *ccm, + const unsigned char *adata, unsigned long adatalen) +{ + unsigned long y; + int err; + + LTC_ARGCHK(ccm != NULL); + LTC_ARGCHK(adata != NULL); + + if (ccm->aadlen < ccm->current_aadlen + adatalen) { + return CRYPT_INVALID_ARG; + } + ccm->current_aadlen += adatalen; + + /* now add the data */ + for (y = 0; y < adatalen; y++) { + if (ccm->x == 16) { + /* full block so let's encrypt it */ + if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + ccm->x = 0; + } + ccm->PAD[ccm->x++] ^= adata[y]; + } + + /* remainder? */ + if (ccm->aadlen == ccm->current_aadlen) { + if (ccm->x != 0) { + if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + } + ccm->x = 0; + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c new file mode 100644 index 0000000..b2c9219 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c @@ -0,0 +1,106 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Add nonce data to the CCM state + @param ccm The CCM state + @param nonce The nonce data to add + @param noncelen The length of the nonce + @return CRYPT_OK on success + */ +int ccm_add_nonce(ccm_state *ccm, + const unsigned char *nonce, unsigned long noncelen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(ccm != NULL); + LTC_ARGCHK(nonce != NULL); + + /* increase L to match the nonce len */ + ccm->noncelen = (noncelen > 13) ? 13 : noncelen; + if ((15 - ccm->noncelen) > ccm->L) { + ccm->L = 15 - ccm->noncelen; + } + if (ccm->L > 8) { + return CRYPT_INVALID_ARG; + } + + /* decrease noncelen to match L */ + if ((ccm->noncelen + ccm->L) > 15) { + ccm->noncelen = 15 - ccm->L; + } + + /* form B_0 == flags | Nonce N | l(m) */ + x = 0; + ccm->PAD[x++] = (unsigned char)(((ccm->aadlen > 0) ? (1<<6) : 0) | + (((ccm->taglen - 2)>>1)<<3) | + (ccm->L-1)); + + /* nonce */ + for (y = 0; y < 15 - ccm->L; y++) { + ccm->PAD[x++] = nonce[y]; + } + + /* store len */ + len = ccm->ptlen; + + /* shift len so the upper bytes of len are the contents of the length */ + for (y = ccm->L; y < 4; y++) { + len <<= 8; + } + + /* store l(m) (only store 32-bits) */ + for (y = 0; ccm->L > 4 && (ccm->L-y)>4; y++) { + ccm->PAD[x++] = 0; + } + for (; y < ccm->L; y++) { + ccm->PAD[x++] = (unsigned char)((len >> 24) & 255); + len <<= 8; + } + + /* encrypt PAD */ + if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + + /* handle header */ + ccm->x = 0; + if (ccm->aadlen > 0) { + /* store length */ + if (ccm->aadlen < ((1UL<<16) - (1UL<<8))) { + ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255; + ccm->PAD[ccm->x++] ^= ccm->aadlen & 255; + } else { + ccm->PAD[ccm->x++] ^= 0xFF; + ccm->PAD[ccm->x++] ^= 0xFE; + ccm->PAD[ccm->x++] ^= (ccm->aadlen>>24) & 255; + ccm->PAD[ccm->x++] ^= (ccm->aadlen>>16) & 255; + ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255; + ccm->PAD[ccm->x++] ^= ccm->aadlen & 255; + } + } + + /* setup the ctr counter */ + x = 0; + + /* flags */ + ccm->ctr[x++] = (unsigned char)ccm->L-1; + + /* nonce */ + for (y = 0; y < (16 - (ccm->L+1)); ++y) { + ccm->ctr[x++] = nonce[y]; + } + /* offset */ + while (x < 16) { + ccm->ctr[x++] = 0; + } + + ccm->CTRlen = 16; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.c new file mode 100644 index 0000000..8eeffe8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.c @@ -0,0 +1,55 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Terminate a CCM stream + @param ccm The CCM 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 ccm_done(ccm_state *ccm, + unsigned char *tag, unsigned long *taglen) +{ + unsigned long x, y; + int err; + + LTC_ARGCHK(ccm != NULL); + + /* Check all data have been processed */ + if (ccm->ptlen != ccm->current_ptlen) { + return CRYPT_ERROR; + } + + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + if (ccm->x != 0) { + if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + } + + /* setup CTR for the TAG (zero the count) */ + for (y = 15; y > 15 - ccm->L; y--) { + ccm->ctr[y] = 0x00; + } + if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) { + return err; + } + + cipher_descriptor[ccm->cipher]->done(&ccm->K); + + /* store the TAG */ + for (x = 0; x < 16 && x < *taglen; x++) { + tag[x] = ccm->PAD[x] ^ ccm->CTRPAD[x]; + } + *taglen = x; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_init.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_init.c new file mode 100644 index 0000000..a913ed4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_init.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Initialize a CCM state + @param ccm The CCM 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 + @param ptlen The length of the plain/cipher text that will be processed + @param taglen The max length of the MAC tag + @param aadlen The length of the AAD + + @return CRYPT_OK on success + */ +int ccm_init(ccm_state *ccm, int cipher, + const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen) +{ + int err; + + LTC_ARGCHK(ccm != NULL); + LTC_ARGCHK(key != NULL); + + XMEMSET(ccm, 0, sizeof(ccm_state)); + + /* 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 valid */ + if (taglen < 4 || taglen > 16 || (taglen % 2) == 1 || aadlen < 0 || ptlen < 0) { + return CRYPT_INVALID_ARG; + } + ccm->taglen = taglen; + + /* schedule key */ + if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &ccm->K)) != CRYPT_OK) { + return err; + } + ccm->cipher = cipher; + + /* let's get the L value */ + ccm->ptlen = ptlen; + ccm->L = 0; + while (ptlen) { + ++ccm->L; + ptlen >>= 8; + } + if (ccm->L <= 1) { + ccm->L = 2; + } + + ccm->aadlen = aadlen; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c new file mode 100644 index 0000000..be8133d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c @@ -0,0 +1,372 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + + *1 'pt', 'ct' and 'tag' can both be 'in' or 'out', depending on 'direction' + + @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 [*1] The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [*1] The ciphertext + @param tag [*1] The destination tag + @param taglen 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], ptTag[16], b, *pt_real; + unsigned char *pt_work = NULL; + 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); + + pt_real = pt; + +#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 valid */ + if (*taglen < 4 || *taglen > 16 || (*taglen % 2) == 1 || headerlen > 0x7fffffffu) { + 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; + } + if (L > 8) { + return CRYPT_INVALID_ARG; + } + + /* 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; + } + + /* initialize buffer for pt */ + if (direction == CCM_DECRYPT && ptlen > 0) { + pt_work = XMALLOC(ptlen); + if (pt_work == NULL) { + goto error; + } + pt = pt_work; + } + + /* 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 < 15 - L; 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 ((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_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); + *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); + } + if ((err = cipher_descriptor[cipher]->ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + } else { /* direction == CCM_DECRYPT */ + 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_PTR_CAST(&pt[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); + *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&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); +#ifdef LTC_CLEAN_STACK + zeromem(skey, sizeof(*skey)); +#endif + } + + if (direction == CCM_ENCRYPT) { + /* store the TAG */ + for (x = 0; x < 16 && x < *taglen; x++) { + tag[x] = PAD[x] ^ CTRPAD[x]; + } + *taglen = x; + } else { /* direction == CCM_DECRYPT */ + /* decrypt the tag */ + for (x = 0; x < 16 && x < *taglen; x++) { + ptTag[x] = tag[x] ^ CTRPAD[x]; + } + *taglen = x; + + /* check validity of the decrypted tag against the computed PAD (in constant time) */ + /* HACK: the boolean value of XMEM_NEQ becomes either 0 (CRYPT_OK) or 1 (CRYPT_ERR). + * there should be a better way of setting the correct error code in constant + * time. + */ + err = XMEM_NEQ(ptTag, PAD, *taglen); + + /* Zero the plaintext if the tag was invalid (in constant time) */ + if (ptlen > 0) { + copy_or_zeromem(pt, pt_real, ptlen, err); + } + } + +#ifdef LTC_CLEAN_STACK + zeromem(PAD, sizeof(PAD)); + zeromem(CTRPAD, sizeof(CTRPAD)); + if (pt_work != NULL) { + zeromem(pt_work, ptlen); + } +#endif +error: + if (pt_work) { + XFREE(pt_work); + } + if (skey != uskey) { + XFREE(skey); + } + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_process.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_process.c new file mode 100644 index 0000000..41bfc2c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_process.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Process plaintext/ciphertext through CCM + @param ccm The CCM 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 (CCM_ENCRYPT or CCM_DECRYPT) + @return CRYPT_OK on success + */ +int ccm_process(ccm_state *ccm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction) +{ + unsigned char z, b; + unsigned long y; + int err; + + LTC_ARGCHK(ccm != NULL); + + /* Check aad has been correctly added */ + if (ccm->aadlen != ccm->current_aadlen) { + return CRYPT_ERROR; + } + + /* Check we do not process too much data */ + if (ccm->ptlen < ccm->current_ptlen + ptlen) { + return CRYPT_ERROR; + } + ccm->current_ptlen += ptlen; + + /* now handle the PT */ + if (ptlen > 0) { + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + for (y = 0; y < ptlen; y++) { + /* increment the ctr? */ + if (ccm->CTRlen == 16) { + for (z = 15; z > 15-ccm->L; z--) { + ccm->ctr[z] = (ccm->ctr[z] + 1) & 255; + if (ccm->ctr[z]) break; + } + if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) { + return err; + } + ccm->CTRlen = 0; + } + + /* if we encrypt we add the bytes to the MAC first */ + if (direction == CCM_ENCRYPT) { + b = pt[y]; + ct[y] = b ^ ccm->CTRPAD[ccm->CTRlen++]; + } else { + b = ct[y] ^ ccm->CTRPAD[ccm->CTRlen++]; + pt[y] = b; + } + + if (ccm->x == 16) { + if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + ccm->x = 0; + } + ccm->PAD[ccm->x++] ^= b; + } + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.c new file mode 100644 index 0000000..93b8fec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.c @@ -0,0 +1,25 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Reset a CCM state to as if you just called ccm_init(). This saves the initialization time. + @param ccm The CCM state to reset + @return CRYPT_OK on success +*/ +int ccm_reset(ccm_state *ccm) +{ + LTC_ARGCHK(ccm != NULL); + zeromem(ccm->PAD, sizeof(ccm->PAD)); + zeromem(ccm->ctr, sizeof(ccm->ctr)); + zeromem(ccm->CTRPAD, sizeof(ccm->CTRPAD)); + ccm->CTRlen = 0; + ccm->current_ptlen = 0; + ccm->current_aadlen = 0; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c new file mode 100644 index 0000000..fee2c6b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c @@ -0,0 +1,274 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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]; + unsigned long 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, y; + unsigned char buf[64], buf2[64], tag[16], tag2[16], tag3[16], zero[64]; + int err, idx; + symmetric_key skey; + ccm_state ccm; + + zeromem(zero, 64); + + 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++) { + for (y = 0; y < 2; y++) { + taglen = tests[x].taglen; + if (y == 0) { + 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; + } + /* run a second time to make sure skey is not touched */ + 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; + } + } else { + if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_process(&ccm, (unsigned char*)tests[x].pt, tests[x].ptlen, buf, CCM_ENCRYPT)) != CRYPT_OK) { + return err; + } + if ((err = ccm_done(&ccm, tag, &taglen)) != CRYPT_OK) { + return err; + } + } + + if (compare_testvector(buf, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "CCM encrypt data", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + if (compare_testvector(tag, taglen, tests[x].tag, tests[x].taglen, "CCM encrypt tag", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if (y == 0) { + XMEMCPY(tag3, tests[x].tag, tests[x].taglen); + taglen = tests[x].taglen; + 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, + tag3, &taglen, 1 )) != CRYPT_OK) { + return err; + } + } else { + if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_process(&ccm, buf2, tests[x].ptlen, buf, CCM_DECRYPT)) != CRYPT_OK) { + return err; + } + if ((err = ccm_done(&ccm, tag2, &taglen)) != CRYPT_OK) { + return err; + } + } + + + if (compare_testvector(buf2, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "CCM decrypt data", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + if (y == 0) { + /* check if decryption with the wrong tag does not reveal the plaintext */ + XMEMCPY(tag3, tests[x].tag, tests[x].taglen); + tag3[0] ^= 0xff; /* set the tag to the wrong value */ + taglen = tests[x].taglen; + 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, + tag3, &taglen, 1 )) != CRYPT_ERROR) { + return CRYPT_FAIL_TESTVECTOR; + } + if (compare_testvector(buf2, tests[x].ptlen, zero, tests[x].ptlen, "CCM decrypt wrong tag", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } else { + if (compare_testvector(tag2, taglen, tests[x].tag, tests[x].taglen, "CCM decrypt tag", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + if (y == 0) { + cipher_descriptor[idx]->done(&skey); + } + } + } + + /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/452 */ + { + unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; + unsigned char iv[] = { 0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51 }; + unsigned char valid_tag[] = { 0x23,0x1a,0x2d,0x8f }; + unsigned char invalid_tag[] = { 0x23,0x1a,0x2d,0x8f,0x6a }; + unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f }; + unsigned char ct[] = { 0xd3,0xda,0xb1,0xee,0x49,0x4c,0xc2,0x29,0x09,0x9d,0x6c,0xac,0x7d,0xf1,0x4a,0xdd }; + unsigned char pt[20] = { 0 }; + + /* VALID tag */ + taglen = sizeof(valid_tag); + err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0, + pt, sizeof(ct), ct, valid_tag, &taglen, CCM_DECRYPT); + if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* INVALID tag */ + taglen = sizeof(invalid_tag); + err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0, + pt, sizeof(ct), ct, invalid_tag, &taglen, CCM_DECRYPT); + if (err == CRYPT_OK) { + return CRYPT_FAIL_TESTVECTOR; /* should fail */ + } + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/sub.mk new file mode 100644 index 0000000..8f43060 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ccm/sub.mk @@ -0,0 +1,6 @@ +srcs-y += ccm_init.c +srcs-y += ccm_add_nonce.c +srcs-y += ccm_add_aad.c +srcs-y += ccm_process.c +srcs-y += ccm_done.c +srcs-y += ccm_reset.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c new file mode 100644 index 0000000..dc6b5bb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Add AAD to the ChaCha20Poly1305 state + @param st The ChaCha20Poly1305 state + @param in The additional authentication data to add to the ChaCha20Poly1305 state + @param inlen The length of the ChaCha20Poly1305 data. + @return CRYPT_OK on success + */ +int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen) +{ + int err; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(st != NULL); + + if (st->aadflg == 0) return CRYPT_ERROR; + if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err; + st->aadlen += (ulong64)inlen; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c new file mode 100644 index 0000000..e51322a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Decrypt bytes of ciphertext with ChaCha20Poly1305 + @param st The ChaCha20Poly1305 state + @param in The ciphertext + @param inlen The length of the input (octets) + @param out [out] The plaintext (length inlen) + @return CRYPT_OK if successful +*/ +int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char padzero[16] = { 0 }; + unsigned long padlen; + int err; + + LTC_ARGCHK(st != NULL); + + if (st->aadflg) { + padlen = 16 - (unsigned long)(st->aadlen % 16); + if (padlen < 16) { + if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; + } + st->aadflg = 0; /* no more AAD */ + } + if (st->aadflg) st->aadflg = 0; /* no more AAD */ + if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err; + st->ctlen += (ulong64)inlen; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c new file mode 100644 index 0000000..19d1640 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Terminate a ChaCha20Poly1305 stream + @param st The ChaCha20Poly1305 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 chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen) +{ + unsigned char padzero[16] = { 0 }; + unsigned long padlen; + unsigned char buf[16]; + int err; + + LTC_ARGCHK(st != NULL); + + padlen = 16 - (unsigned long)(st->ctlen % 16); + if (padlen < 16) { + if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; + } + STORE64L(st->aadlen, buf); + STORE64L(st->ctlen, buf + 8); + if ((err = poly1305_process(&st->poly, buf, 16)) != CRYPT_OK) return err; + if ((err = poly1305_done(&st->poly, tag, taglen)) != CRYPT_OK) return err; + if ((err = chacha_done(&st->chacha)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c new file mode 100644 index 0000000..2a4208e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Encrypt bytes of ciphertext with ChaCha20Poly1305 + @param st The ChaCha20Poly1305 state + @param in The plaintext + @param inlen The length of the input (octets) + @param out [out] The ciphertext (length inlen) + @return CRYPT_OK if successful +*/ +int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char padzero[16] = { 0 }; + unsigned long padlen; + int err; + + LTC_ARGCHK(st != NULL); + + if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err; + if (st->aadflg) { + padlen = 16 - (unsigned long)(st->aadlen % 16); + if (padlen < 16) { + if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; + } + st->aadflg = 0; /* no more AAD */ + } + if ((err = poly1305_process(&st->poly, out, inlen)) != CRYPT_OK) return err; + st->ctlen += (ulong64)inlen; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c new file mode 100644 index 0000000..2654f4d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c @@ -0,0 +1,20 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Initialize an ChaCha20Poly1305 context (only the key) + @param st [out] The destination of the ChaCha20Poly1305 state + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen) +{ + return chacha_setup(&st->chacha, key, keylen, 20); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c new file mode 100644 index 0000000..6e3bf24 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Process an entire GCM packet in one call. + @param key The secret key + @param keylen The length of the secret key + @param iv The initialization vector + @param ivlen The length of the initialization vector + @param aad The additional authentication data (header) + @param aadlen The length of the aad + @param in The plaintext + @param inlen The length of the plaintext (ciphertext length is the same) + @param out The ciphertext + @param tag [out] The MAC tag + @param taglen [in/out] The MAC tag length + @param direction Encrypt or Decrypt mode (CHACHA20POLY1305_ENCRYPT or CHACHA20POLY1305_DECRYPT) + @return CRYPT_OK on success + */ +int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *aad, unsigned long aadlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, + unsigned char *tag, unsigned long *taglen, + int direction) +{ + chacha20poly1305_state st; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + if ((err = chacha20poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = chacha20poly1305_setiv(&st, iv, ivlen)) != CRYPT_OK) { goto LBL_ERR; } + if (aad && aadlen > 0) { + if ((err = chacha20poly1305_add_aad(&st, aad, aadlen)) != CRYPT_OK) { goto LBL_ERR; } + } + if (direction == CHACHA20POLY1305_ENCRYPT) { + if ((err = chacha20poly1305_encrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = chacha20poly1305_done(&st, tag, taglen)) != CRYPT_OK) { goto LBL_ERR; } + } + else if (direction == CHACHA20POLY1305_DECRYPT) { + unsigned char buf[MAXBLOCKSIZE]; + unsigned long buflen = sizeof(buf); + if ((err = chacha20poly1305_decrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = chacha20poly1305_done(&st, buf, &buflen)) != CRYPT_OK) { goto LBL_ERR; } + if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) { + err = CRYPT_ERROR; + goto LBL_ERR; + } + } + else { + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(chacha20poly1305_state)); +#endif + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c new file mode 100644 index 0000000..d5ec3e6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c @@ -0,0 +1,58 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Set IV + counter data to the ChaCha20Poly1305 state and reset the context + @param st The ChaCha20Poly1305 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12 or 8) + @return CRYPT_OK on success + */ +int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen) +{ + chacha_state tmp_st; + int i, err; + unsigned char polykey[32]; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(ivlen == 12 || ivlen == 8); + + /* set IV for chacha20 */ + if (ivlen == 12) { + /* IV 96bit */ + if ((err = chacha_ivctr32(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err; + } + else { + /* IV 64bit */ + if ((err = chacha_ivctr64(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err; + } + + /* copy chacha20 key to temporary state */ + for(i = 0; i < 12; i++) tmp_st.input[i] = st->chacha.input[i]; + tmp_st.rounds = 20; + /* set IV */ + if (ivlen == 12) { + /* IV 32bit */ + if ((err = chacha_ivctr32(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err; + } + else { + /* IV 64bit */ + if ((err = chacha_ivctr64(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err; + } + /* (re)generate new poly1305 key */ + if ((err = chacha_keystream(&tmp_st, polykey, 32)) != CRYPT_OK) return err; + /* (re)initialise poly1305 */ + if ((err = poly1305_init(&st->poly, polykey, 32)) != CRYPT_OK) return err; + st->ctlen = 0; + st->aadlen = 0; + st->aadflg = 1; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c new file mode 100644 index 0000000..75da634 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Set IV + counter data (with RFC7905-magic) to the ChaCha20Poly1305 state and reset the context + @param st The ChaCha20Poly1305 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12 or 8) + @param sequence_number 64bit sequence number which is incorporated into IV as described in RFC7905 + @return CRYPT_OK on success + */ +int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number) +{ + int i; + unsigned char combined_iv[12] = { 0 }; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(ivlen == 12); + + STORE64L(sequence_number, combined_iv + 4); + for (i = 0; i < 12; i++) combined_iv[i] = iv[i] ^ combined_iv[i]; + return chacha20poly1305_setiv(st, combined_iv, 12); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c new file mode 100644 index 0000000..30d4973 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c @@ -0,0 +1,159 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +int chacha20poly1305_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + chacha20poly1305_state st1, st2; + unsigned char k[] = { 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 }; + unsigned char i12[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }; + unsigned char i8[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43 }; + unsigned char aad[] = { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }; + unsigned char enc[] = { 0xD3, 0x1A, 0x8D, 0x34, 0x64, 0x8E, 0x60, 0xDB, 0x7B, 0x86, 0xAF, 0xBC, 0x53, 0xEF, 0x7E, 0xC2, + 0xA4, 0xAD, 0xED, 0x51, 0x29, 0x6E, 0x08, 0xFE, 0xA9, 0xE2, 0xB5, 0xA7, 0x36, 0xEE, 0x62, 0xD6, + 0x3D, 0xBE, 0xA4, 0x5E, 0x8C, 0xA9, 0x67, 0x12, 0x82, 0xFA, 0xFB, 0x69, 0xDA, 0x92, 0x72, 0x8B, + 0x1A, 0x71, 0xDE, 0x0A, 0x9E, 0x06, 0x0B, 0x29, 0x05, 0xD6, 0xA5, 0xB6, 0x7E, 0xCD, 0x3B, 0x36, + 0x92, 0xDD, 0xBD, 0x7F, 0x2D, 0x77, 0x8B, 0x8C, 0x98, 0x03, 0xAE, 0xE3, 0x28, 0x09, 0x1B, 0x58, + 0xFA, 0xB3, 0x24, 0xE4, 0xFA, 0xD6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8B, 0x48, 0x31, 0xD7, 0xBC, + 0x3F, 0xF4, 0xDE, 0xF0, 0x8E, 0x4B, 0x7A, 0x9D, 0xE5, 0x76, 0xD2, 0x65, 0x86, 0xCE, 0xC6, 0x4B, + 0x61, 0x16 }; + unsigned char tag[] = { 0x1A, 0xE1, 0x0B, 0x59, 0x4F, 0x09, 0xE2, 0x6A, 0x7E, 0x90, 0x2E, 0xCB, 0xD0, 0x60, 0x06, 0x91 }; + char m[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + unsigned long mlen = XSTRLEN(m); + unsigned long len; + unsigned char rfc7905_pt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; + unsigned char rfc7905_enc[] = { 0xE4, 0x62, 0x85, 0xB4, 0x29, 0x95, 0x34, 0x96, 0xAB, 0xFB, 0x67, 0xCD, 0xAE, 0xAC, 0x94, 0x1E }; + unsigned char rfc7905_tag[] = { 0x16, 0x2C, 0x92, 0x48, 0x2A, 0xDB, 0xD3, 0x5D, 0x48, 0xBE, 0xC6, 0xFF, 0x10, 0x9C, 0xBA, 0xE4 }; + unsigned char ct[1000], pt[1000], emac[16], dmac[16]; + int err; + + /* encrypt IV 96bit */ + if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv(&st1, i12, sizeof(i12))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; + /* encrypt piece by piece */ + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, 25, ct)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 25, 10, ct + 25)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 35, 35, ct + 35)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 70, 5, ct + 70)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 75, 5, ct + 75)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 80, mlen - 80, ct + 80)) != CRYPT_OK) return err; + len = sizeof(emac); + if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* decrypt IV 96bit */ + if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv(&st2, i12, sizeof(i12))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_decrypt(&st2, ct, 21, pt)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_decrypt(&st2, ct + 21, mlen - 21, pt + 21)) != CRYPT_OK) return err; + len = sizeof(dmac); + if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(pt, mlen, m, mlen, "DEC-PT", 3) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(dmac, len, tag, sizeof(tag), "DEC-TAG", 4) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* chacha20poly1305_memory - encrypt */ + len = sizeof(emac); + if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), (unsigned char *)m, + mlen, ct, emac, &len, CHACHA20POLY1305_ENCRYPT)) != CRYPT_OK) return err; + if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT2", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG2", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* chacha20poly1305_memory - decrypt */ + len = sizeof(dmac); + XMEMCPY(dmac, tag, sizeof(tag)); + if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), + ct, mlen, pt, dmac, &len, CHACHA20POLY1305_DECRYPT)) != CRYPT_OK) return err; + if (compare_testvector(pt, mlen, m, mlen, "DEC-PT2", 3) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* encrypt - rfc7905 */ + if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, rfc7905_pt, 16, ct)) != CRYPT_OK) return err; + len = sizeof(emac); + if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(ct, 16, rfc7905_enc, 16, "ENC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(emac, len, rfc7905_tag, 16, "ENC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* decrypt - rfc7905 */ + if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_decrypt(&st1, ct, 16, pt)) != CRYPT_OK) return err; + len = sizeof(dmac); + if ((err = chacha20poly1305_done(&st1, dmac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(pt, 16, rfc7905_pt, 16, "DEC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(dmac, len, rfc7905_tag, 16, "DEC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* encrypt IV 64bit */ + if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv(&st1, i8, sizeof(i8))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, mlen, ct)) != CRYPT_OK) return err; + len = sizeof(emac); + if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; + + /* decrypt IV 64bit */ + if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv(&st2, i8, sizeof(i8))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_decrypt(&st2, ct, mlen, pt)) != CRYPT_OK) return err; + len = sizeof(dmac); + if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(pt, mlen, m, mlen, "DEC-PT4", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(dmac, len, emac, len, "DEC-TAG4", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */ + { + unsigned char key[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff, + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; + unsigned char iv[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b }; + unsigned char valid_tag[] = { 0xa3,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 }; + unsigned char invalid_tag[] = { 0xa2,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 }; + unsigned char waad[] = { 0x61,0x61,0x64 }; + unsigned char wct[] = { 0x00 }; + unsigned char wpt[20] = { 0 }; + unsigned char wtag[20] = { 0 }; + unsigned long taglen; + + /* encrypt */ + taglen = sizeof(wtag); + err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), + wpt, 0, wct, wtag, &taglen, CHACHA20POLY1305_ENCRYPT); + if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(wtag, taglen, valid_tag, sizeof(valid_tag), "WYCH", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* VALID tag */ + taglen = sizeof(valid_tag); + err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), + wpt, 0, wct, valid_tag, &taglen, CHACHA20POLY1305_DECRYPT); + if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; + + /* INVALID tag */ + taglen = sizeof(invalid_tag); + err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), + wpt, 0, wct, invalid_tag, &taglen, CHACHA20POLY1305_DECRYPT); + if (err == CRYPT_OK) { + return CRYPT_FAIL_TESTVECTOR; /* should fail */ + } + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c new file mode 100644 index 0000000..a6b8f76 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c @@ -0,0 +1,26 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @file eax_addheader.c + EAX implementation, add meta-data, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c new file mode 100644 index 0000000..cc03c5c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_decrypt.c + EAX implementation, decrypt block, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c new file mode 100644 index 0000000..5429d4a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c @@ -0,0 +1,99 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_decrypt_verify_memory.c + EAX implementation, decrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.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, + const 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; + + /* limit taglen */ + taglen = MIN(taglen, MAXBLOCKSIZE); + + /* 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 && XMEM_NEQ(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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_done.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_done.c new file mode 100644 index 0000000..f2362cf --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_done.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_done.c + EAX implementation, terminate session, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c new file mode 100644 index 0000000..dba3239 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_encrypt.c + EAX implementation, encrypt block by Tom St Denis +*/ +#include "tomcrypt_private.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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c new file mode 100644 index 0000000..76aeec2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c @@ -0,0 +1,70 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_encrypt_authenticate_memory.c + EAX implementation, encrypt a block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_init.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_init.c new file mode 100644 index 0000000..6a74c3c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_init.c @@ -0,0 +1,132 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_init.c + EAX implementation, initialized EAX state, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_test.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_test.c new file mode 100644 index 0000000..c613e0d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/eax/eax_test.c @@ -0,0 +1,249 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_test.c + EAX implementation, self-test, by Tom St Denis +*/ +#include "tomcrypt_private.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 (compare_testvector(outtag, len, tests[x].tag, len, "EAX Tag", x) || + compare_testvector(outct, tests[x].msglen, tests[x].ciphertext, tests[x].msglen, "EAX CT", x)) { + 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) || compare_testvector(outct, tests[x].msglen, tests[x].plaintext, tests[x].msglen, "EAX", x)) { +#ifdef LTC_TEST_DBG + printf("\n\nEAX: Failure-decrypt - res = %d\n", res); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* LTC_EAX_MODE */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c new file mode 100644 index 0000000..5c3793e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c @@ -0,0 +1,114 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_add_aad.c + GCM implementation, Add AAD data to the stream, by Tom St Denis +*/ +#include "tomcrypt_private.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) { + /* IV length must be > 0 */ + if (gcm->buflen == 0 && gcm->totlen == 0) return CRYPT_ERROR; + /* 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 && adatalen > 15) { + for (x = 0; x < (adatalen & ~15); x += 16) { + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c new file mode 100644 index 0000000..33a2444 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_add_iv.c + GCM implementation, add IV data to the state, by Tom St Denis +*/ +#include "tomcrypt_private.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_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c new file mode 100644 index 0000000..ee16d38 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_done.c + GCM implementation, Terminate the stream, by Tom St Denis +*/ +#include "tomcrypt_private.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_IV) { + /* let's process the IV */ + if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err; + } + + if (gcm->mode == LTC_GCM_MODE_AAD) { + /* let's process the AAD */ + if ((err = gcm_process(gcm, NULL, 0, NULL, 0)) != 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c new file mode 100644 index 0000000..10cd3c9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c @@ -0,0 +1,209 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_gf_mult.c + GCM implementation, do the GF mult, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || (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 s_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 char 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; + s_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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c new file mode 100644 index 0000000..5a32d07 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c @@ -0,0 +1,95 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_init.c + GCM implementation, initialize state, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c new file mode 100644 index 0000000..4ae0960 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c @@ -0,0 +1,113 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_memory.c + GCM implementation, process a packet, by Tom St Denis +*/ +#include "tomcrypt_private.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 initialization vector + @param IVlen The length of the initialization 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; + } + if (direction == GCM_ENCRYPT) { + if ((err = gcm_done(gcm, tag, taglen)) != CRYPT_OK) { + goto LTC_ERR; + } + } + else if (direction == GCM_DECRYPT) { + unsigned char buf[MAXBLOCKSIZE]; + unsigned long buflen = sizeof(buf); + if ((err = gcm_done(gcm, buf, &buflen)) != CRYPT_OK) { + goto LTC_ERR; + } + if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) { + err = CRYPT_ERROR; + } + } + else { + err = CRYPT_INVALID_ARG; + } +LTC_ERR: + XFREE(orig); + return err; +} +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c new file mode 100644 index 0000000..fcf3226 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c @@ -0,0 +1,47 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_mult_h.c + GCM implementation, do the GF mult, by Tom St Denis +*/ +#include "tomcrypt_private.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(const gcm_state *gcm, unsigned char *I) +{ + unsigned char T[16]; +#ifdef LTC_GCM_TABLES + int x; +#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 + int y; + 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_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c new file mode 100644 index 0000000..895a924 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include +#include + +/** + 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) +{ + struct tomcrypt_arm_neon_state state; + const uint8_t zeroes[TEE_AES_BLOCK_SIZE] = { 0 }; + uint64_t k[2]; + uint64_t a; + uint64_t b; + uint64_t dg[2]; + + b = get_be64(gcm->H); + a = get_be64(gcm->H + 8); + + k[0] = (a << 1) | (b >> 63); + k[1] = (b << 1) | (a >> 63); + if (b >> 63) + k[1] ^= 0xc200000000000000UL; + + dg[1] = get_be64(I); + dg[0] = get_be64(I + 8); + + tomcrypt_arm_neon_enable(&state); +#ifdef _CFG_CORE_LTC_HWSUPP_PMULL + pmull_ghash_update_p64(1, dg, zeroes, k, NULL); +#else + pmull_ghash_update_p8(1, dg, zeroes, k, NULL); +#endif + tomcrypt_arm_neon_disable(&state); + + put_be64(I, dg[1]); + put_be64(I + 8, dg[0]); +} + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c new file mode 100644 index 0000000..2031c8f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c @@ -0,0 +1,150 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_process.c + GCM implementation, process message data, by Tom St Denis +*/ +#include "tomcrypt_private.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; + } + + /* 0xFFFFFFFE0 = ((2^39)-256)/8 */ + if (gcm->pttotlen / 8 + (ulong64)gcm->buflen + (ulong64)ptlen >= CONST64(0xFFFFFFFE0)) { + return CRYPT_INVALID_ARG; + } + + if (gcm->mode == LTC_GCM_MODE_IV) { + /* let's process the IV */ + if ((err = gcm_add_aad(gcm, NULL, 0)) != 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_PTR_CAST(&ct[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y])); + *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&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_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])); + *(LTC_FAST_TYPE_PTR_CAST(&pt[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c new file mode 100644 index 0000000..a071dcd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_reset.c + GCM implementation, reset a used state so it can accept IV data, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c new file mode 100644 index 0000000..228db57 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c @@ -0,0 +1,407 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_test.c + GCM implementation, testing, by Tom St Denis +*/ +#include "tomcrypt_private.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]; + gcm_state gcm; + + /* find aes */ + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) { + return CRYPT_NOP; + } + } + + /* Special test case for empty AAD + empty PT */ + y = sizeof(T[0]); + if ((err = gcm_init(&gcm, idx, tests[0].K, tests[0].keylen)) != CRYPT_OK) return err; + if ((err = gcm_add_iv(&gcm, tests[0].IV, tests[0].IVlen)) != CRYPT_OK) return err; + /* intentionally skip gcm_add_aad + gcm_process */ + if ((err = gcm_done(&gcm, T[0], &y)) != CRYPT_OK) return err; + if (compare_testvector(T[0], y, tests[0].T, 16, "GCM Encrypt Tag-special", 0)) return CRYPT_FAIL_TESTVECTOR; + + 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 (compare_testvector(out[0], tests[x].ptlen, tests[x].C, tests[x].ptlen, "GCM CT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if (compare_testvector(T[0], y, tests[x].T, 16, "GCM Encrypt Tag", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + y = sizeof(T[1]); + XMEMCPY(T[1], tests[x].T, 16); + 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 (compare_testvector(out[1], tests[x].ptlen, tests[x].P, tests[x].ptlen, "GCM PT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */ + { + unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; + unsigned char iv[] = { 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b }; + unsigned char valid_tag[] = { 0xd8,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 }; + unsigned char invalid_tag[] = { 0xd9,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 }; + unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f }; + unsigned char ct[] = { 0xeb,0x15,0x6d,0x08,0x1e,0xd6,0xb6,0xb5,0x5f,0x46,0x12,0xf0,0x21,0xd8,0x7b,0x39 }; + unsigned char pt[20] = { 0 }; + unsigned long taglen; + + /* VALID tag */ + taglen = sizeof(valid_tag); + err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0, + pt, sizeof(ct), ct, valid_tag, &taglen, GCM_DECRYPT); + if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* INVALID tag */ + taglen = sizeof(invalid_tag); + err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0, + pt, sizeof(ct), ct, invalid_tag, &taglen, GCM_DECRYPT); + if (err == CRYPT_OK) { + return CRYPT_FAIL_TESTVECTOR; /* should fail */ + } + } + + return CRYPT_OK; +#endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/sub.mk new file mode 100644 index 0000000..6720c3f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/gcm/sub.mk @@ -0,0 +1,13 @@ +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 +ifeq ($(_CFG_CORE_LTC_CE),y) +srcs-y += gcm_mult_h_arm_ce.c +else +srcs-y += gcm_mult_h.c +endif +srcs-y += gcm_process.c +srcs-y += gcm_reset.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c new file mode 100644 index 0000000..6837427 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c @@ -0,0 +1,67 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_decrypt.c + OCB implementation, decrypt data, by Tom St Denis +*/ +#include "tomcrypt_private.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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c new file mode 100644 index 0000000..0f4dcb7 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c @@ -0,0 +1,74 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_decrypt_verify_memory.c + OCB implementation, helper to decrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c new file mode 100644 index 0000000..3d516c9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_done_decrypt.c + OCB implementation, terminate decryption, by Tom St Denis +*/ +#include "tomcrypt_private.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 && XMEM_NEQ(tagbuf, tag, taglen) == 0) { + *stat = 1; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tagbuf, MAXBLOCKSIZE); +#endif + + XFREE(tagbuf); + + return err; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c new file mode 100644 index 0000000..5cd39ad --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_done_encrypt.c + OCB implementation, terminate encryption, by Tom St Denis +*/ +#include "tomcrypt_private.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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c new file mode 100644 index 0000000..ad6260f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c @@ -0,0 +1,60 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_encrypt.c + OCB implementation, encrypt data, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c new file mode 100644 index 0000000..7560a6e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_encrypt_authenticate_memory.c + OCB implementation, encrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c new file mode 100644 index 0000000..80321de --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c @@ -0,0 +1,129 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_init.c + OCB implementation, initialize state, by Tom St Denis +*/ +#include "tomcrypt_private.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; + x = (int)(sizeof(polys)/sizeof(polys[0])); + for (poly = 0; poly < x; poly++) { + if (polys[poly].len == ocb->block_len) { + break; + } + } + if (poly == x) { + return CRYPT_INVALID_ARG; /* block_len not found in polys */ + } + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c new file mode 100644 index 0000000..b0f5570 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_ntz.c + OCB implementation, internal function, by Tom St Denis +*/ + +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c new file mode 100644 index 0000000..2f7bb3b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_shift_xor.c + OCB implementation, internal function, by Tom St Denis +*/ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c new file mode 100644 index 0000000..b03c2fd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c @@ -0,0 +1,205 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_test.c + OCB implementation, self-test by Tom St Denis +*/ +#include "tomcrypt_private.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 (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB Tag", x) || + compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB CT", x)) { + 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) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB", x)) { +#ifdef LTC_TEST_DBG + printf("\n\nOCB: Failure-decrypt - res = %d\n", res); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + 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... +*/ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c new file mode 100644 index 0000000..b708dfd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c @@ -0,0 +1,136 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file s_ocb_done.c + OCB implementation, internal helper, by Tom St Denis +*/ +#include "tomcrypt_private.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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c new file mode 100644 index 0000000..9a3811a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_add_aad.c + OCB implementation, add AAD data, by Karel Miko +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Add one block of AAD data (internal function) + @param ocb The OCB state + @param aad_block [in] AAD data (block_len size) + @return CRYPT_OK if successful +*/ +static int s_ocb3_int_aad_add_block(ocb3_state *ocb, const unsigned char *aad_block) +{ + unsigned char tmp[MAXBLOCKSIZE]; + int err; + + /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ + ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_[ocb3_int_ntz(ocb->ablock_index)], ocb->block_len); + + /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ + ocb3_int_xor_blocks(tmp, aad_block, ocb->aOffset_current, ocb->block_len); + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { + return err; + } + ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len); + + ocb->ablock_index++; + + return CRYPT_OK; +} + +/** + Add AAD - additional associated data + @param ocb The OCB state + @param aad The AAD data + @param aadlen The size of AAD data (octets) + @return CRYPT_OK if successful +*/ +int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen) +{ + int err, x, full_blocks, full_blocks_len, last_block_len; + unsigned char *data; + unsigned long datalen, l; + + LTC_ARGCHK(ocb != NULL); + if (aadlen == 0) return CRYPT_OK; + LTC_ARGCHK(aad != NULL); + + if (ocb->adata_buffer_bytes > 0) { + l = ocb->block_len - ocb->adata_buffer_bytes; + if (l > aadlen) l = aadlen; + XMEMCPY(ocb->adata_buffer+ocb->adata_buffer_bytes, aad, l); + ocb->adata_buffer_bytes += l; + + if (ocb->adata_buffer_bytes == ocb->block_len) { + if ((err = s_ocb3_int_aad_add_block(ocb, ocb->adata_buffer)) != CRYPT_OK) { + return err; + } + ocb->adata_buffer_bytes = 0; + } + + data = (unsigned char *)aad + l; + datalen = aadlen - l; + } + else { + data = (unsigned char *)aad; + datalen = aadlen; + } + + if (datalen == 0) return CRYPT_OK; + + full_blocks = datalen/ocb->block_len; + full_blocks_len = full_blocks * ocb->block_len; + last_block_len = datalen - full_blocks_len; + + for (x=0; xblock_len)) != CRYPT_OK) { + return err; + } + } + + if (last_block_len>0) { + XMEMCPY(ocb->adata_buffer, data+full_blocks_len, last_block_len); + ocb->adata_buffer_bytes = last_block_len; + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c new file mode 100644 index 0000000..068a53e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_decrypt.c + OCB implementation, decrypt data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Decrypt blocks of ciphertext with OCB + @param ocb The OCB state + @param ct The ciphertext (length multiple of the block size of the block cipher) + @param ctlen The length of the input (octets) + @param pt [out] The plaintext (length of ct) + @return CRYPT_OK if successful +*/ +int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt) +{ + unsigned char tmp[MAXBLOCKSIZE]; + int err, i, full_blocks; + unsigned char *pt_b, *ct_b; + + LTC_ARGCHK(ocb != NULL); + if (ctlen == 0) return CRYPT_OK; /* no data, nothing to do */ + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(pt != 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; + } + + if (ctlen % ocb->block_len) { /* ctlen has to bu multiple of block_len */ + return CRYPT_INVALID_ARG; + } + + full_blocks = ctlen/ocb->block_len; + for(i=0; iblock_len; + ct_b = (unsigned char *)ct+i*ocb->block_len; + + /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */ + ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len); + + /* tmp[] = ct[] XOR ocb->Offset_current[] */ + ocb3_int_xor_blocks(tmp, ct_b, ocb->Offset_current, ocb->block_len); + + /* decrypt */ + if ((err = cipher_descriptor[ocb->cipher]->ecb_decrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* pt[] = tmp[] XOR ocb->Offset_current[] */ + ocb3_int_xor_blocks(pt_b, tmp, ocb->Offset_current, ocb->block_len); + + /* ocb->checksum[] = ocb->checksum[] XOR pt[] */ + ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len); + + ocb->block_index++; + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c new file mode 100644 index 0000000..49bc5e8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c @@ -0,0 +1,101 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_decrypt_last.c + OCB implementation, internal helper, by Karel Miko +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Finish an OCB (decryption) stream + @param ocb The OCB state + @param ct The remaining ciphertext + @param ctlen The length of the ciphertext (octets) + @param pt [out] The output buffer + @return CRYPT_OK if successful +*/ +int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt) +{ + unsigned char iOffset_star[MAXBLOCKSIZE]; + unsigned char iPad[MAXBLOCKSIZE]; + int err, x, full_blocks, full_blocks_len, last_block_len; + + LTC_ARGCHK(ocb != NULL); + if (ct == NULL) LTC_ARGCHK(ctlen == 0); + if (ctlen != 0) { + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(pt != NULL); + } + + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + goto LBL_ERR; + } + + full_blocks = ctlen/ocb->block_len; + full_blocks_len = full_blocks * ocb->block_len; + last_block_len = ctlen - full_blocks_len; + + /* process full blocks first */ + if (full_blocks>0) { + if ((err = ocb3_decrypt(ocb, ct, full_blocks_len, pt)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + if (last_block_len>0) { + /* Offset_* = Offset_m xor L_* */ + ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len); + + /* Pad = ENCIPHER(K, Offset_*) */ + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* P_* = C_* xor Pad[1..bitlen(C_*)] */ + ocb3_int_xor_blocks(pt+full_blocks_len, (unsigned char *)ct+full_blocks_len, iPad, last_block_len); + + /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ + ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len); + for(x=last_block_len; xblock_len; x++) { + if (x == last_block_len) { + ocb->checksum[x] ^= 0x80; + } else { + ocb->checksum[x] ^= 0x00; + } + } + + /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */ + /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */ + for(x=0; xblock_len; x++) { + ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x]; + } + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + } + else { + /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */ + /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */ + for(x=0; xblock_len; x++) { + ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x]; + } + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(iOffset_star, MAXBLOCKSIZE); + zeromem(iPad, MAXBLOCKSIZE); +#endif + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c new file mode 100644 index 0000000..03d33b2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c @@ -0,0 +1,100 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_decrypt_verify_memory.c + OCB implementation, helper to decrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_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 noncelen The length of the nonce (octets) + @param adata The AAD - additional associated data + @param adatalen The length of AAD (octets) + @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 ocb3_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *adata, unsigned long adatalen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat) +{ + int err; + ocb3_state *ocb; + unsigned char *buf; + unsigned long buflen; + + LTC_ARGCHK(stat != NULL); + + /* default to zero */ + *stat = 0; + + /* limit taglen */ + taglen = MIN(taglen, MAXBLOCKSIZE); + + /* allocate memory */ + buf = XMALLOC(taglen); + ocb = XMALLOC(sizeof(ocb3_state)); + if (ocb == NULL || buf == NULL) { + if (ocb != NULL) { + XFREE(ocb); + } + if (buf != NULL) { + XFREE(buf); + } + return CRYPT_MEM; + } + + if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, taglen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (adata != NULL || adatalen != 0) { + if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + if ((err = ocb3_decrypt_last(ocb, ct, ctlen, pt)) != CRYPT_OK) { + goto LBL_ERR; + } + + buflen = taglen; + if ((err = ocb3_done(ocb, buf, &buflen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compare tags */ + if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) { + *stat = 1; + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ocb, sizeof(ocb3_state)); +#endif + + XFREE(ocb); + XFREE(buf); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_done.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_done.c new file mode 100644 index 0000000..074d4c1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_done.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_done.c + OCB implementation, INTERNAL ONLY helper, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Finish OCB processing and compute the tag + @param ocb The OCB state + @param tag [out] The destination for the authentication tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen) +{ + unsigned char tmp[MAXBLOCKSIZE]; + int err, x; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* check taglen */ + if ((int)*taglen < ocb->tag_len) { + *taglen = (unsigned long)ocb->tag_len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* finalize AAD processing */ + + if (ocb->adata_buffer_bytes>0) { + /* Offset_* = Offset_m xor L_* */ + ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_star, ocb->block_len); + + /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */ + ocb3_int_xor_blocks(tmp, ocb->adata_buffer, ocb->aOffset_current, ocb->adata_buffer_bytes); + for(x=ocb->adata_buffer_bytes; xblock_len; x++) { + if (x == ocb->adata_buffer_bytes) { + tmp[x] = 0x80 ^ ocb->aOffset_current[x]; + } + else { + tmp[x] = 0x00 ^ ocb->aOffset_current[x]; + } + } + + /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len); + } + + /* finalize TAG computing */ + + /* at this point ocb->aSum_current = HASH(K, A) */ + /* tag = tag ^ HASH(K, A) */ + ocb3_int_xor_blocks(tmp, ocb->tag_part, ocb->aSum_current, ocb->block_len); + + /* copy tag bytes */ + for(x = 0; x < ocb->tag_len; x++) tag[x] = tmp[x]; + *taglen = (unsigned long)ocb->tag_len; + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, MAXBLOCKSIZE); + zeromem(ocb, sizeof(*ocb)); +#endif + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c new file mode 100644 index 0000000..317f6f3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_encrypt.c + OCB implementation, encrypt data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Encrypt blocks of data with OCB + @param ocb The OCB state + @param pt The plaintext (length multiple of the block size of the block cipher) + @param ptlen The length of the input (octets) + @param ct [out] The ciphertext (same size as the pt) + @return CRYPT_OK if successful +*/ +int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct) +{ + unsigned char tmp[MAXBLOCKSIZE]; + int err, i, full_blocks; + unsigned char *pt_b, *ct_b; + + LTC_ARGCHK(ocb != NULL); + if (ptlen == 0) return CRYPT_OK; /* no data, nothing to do */ + 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; + } + + if (ptlen % ocb->block_len) { /* ptlen has to bu multiple of block_len */ + return CRYPT_INVALID_ARG; + } + + full_blocks = ptlen/ocb->block_len; + for(i=0; iblock_len; + ct_b = (unsigned char *)ct+i*ocb->block_len; + + /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */ + ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len); + + /* tmp[] = pt[] XOR ocb->Offset_current[] */ + ocb3_int_xor_blocks(tmp, pt_b, ocb->Offset_current, ocb->block_len); + + /* encrypt */ + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* ct[] = tmp[] XOR ocb->Offset_current[] */ + ocb3_int_xor_blocks(ct_b, tmp, ocb->Offset_current, ocb->block_len); + + /* ocb->checksum[] = ocb->checksum[] XOR pt[] */ + ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len); + + ocb->block_index++; + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c new file mode 100644 index 0000000..b118925 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_encrypt_authenticate_memory.c + OCB implementation, encrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_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 noncelen The length of the nonce (octets) + @param adata The AAD - additional associated data + @param adatalen The length of AAD (octets) + @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 ocb3_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *adata, unsigned long adatalen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen) +{ + int err; + ocb3_state *ocb; + + LTC_ARGCHK(taglen != NULL); + + /* allocate memory */ + ocb = XMALLOC(sizeof(ocb3_state)); + if (ocb == NULL) { + return CRYPT_MEM; + } + + if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, *taglen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (adata != NULL || adatalen != 0) { + if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + if ((err = ocb3_encrypt_last(ocb, pt, ptlen, ct)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = ocb3_done(ocb, tag, taglen); + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ocb, sizeof(ocb3_state)); +#endif + + XFREE(ocb); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c new file mode 100644 index 0000000..5aab93b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c @@ -0,0 +1,102 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_encrypt_last.c + OCB implementation, internal helper, by Karel Miko +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Finish an OCB (encryption) stream + @param ocb The OCB state + @param pt The remaining plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The output buffer + @return CRYPT_OK if successful +*/ +int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct) +{ + unsigned char iOffset_star[MAXBLOCKSIZE]; + unsigned char iPad[MAXBLOCKSIZE]; + int err, x, full_blocks, full_blocks_len, last_block_len; + + LTC_ARGCHK(ocb != NULL); + if (pt == NULL) LTC_ARGCHK(ptlen == 0); + if (ptlen != 0) { + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + } + + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + goto LBL_ERR; + } + + full_blocks = ptlen/ocb->block_len; + full_blocks_len = full_blocks * ocb->block_len; + last_block_len = ptlen - full_blocks_len; + + /* process full blocks first */ + if (full_blocks>0) { + if ((err = ocb3_encrypt(ocb, pt, full_blocks_len, ct)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* at this point: m = ocb->block_index (last block index), Offset_m = ocb->Offset_current */ + + if (last_block_len>0) { + /* Offset_* = Offset_m xor L_* */ + ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len); + + /* Pad = ENCIPHER(K, Offset_*) */ + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* C_* = P_* xor Pad[1..bitlen(P_*)] */ + ocb3_int_xor_blocks(ct+full_blocks_len, pt+full_blocks_len, iPad, last_block_len); + + /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ + ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len); + for(x=last_block_len; xblock_len; x++) { + if (x == last_block_len) { + ocb->checksum[x] ^= 0x80; + } else { + ocb->checksum[x] ^= 0x00; + } + } + + /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */ + /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */ + for(x=0; xblock_len; x++) { + ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x]; + } + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + } else { + /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */ + /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */ + for(x=0; xblock_len; x++) { + ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x]; + } + if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(iOffset_star, MAXBLOCKSIZE); + zeromem(iPad, MAXBLOCKSIZE); +#endif + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_init.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_init.c new file mode 100644 index 0000000..4882d64 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_init.c @@ -0,0 +1,186 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_init.c + OCB implementation, initialize state, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +static void s_ocb3_int_calc_offset_zero(ocb3_state *ocb, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen) +{ + int x, y, bottom; + int idx, shift; + unsigned char iNonce[MAXBLOCKSIZE]; + unsigned char iKtop[MAXBLOCKSIZE]; + unsigned char iStretch[MAXBLOCKSIZE+8]; + + /* Nonce = zeros(127-bitlen(N)) || 1 || N */ + zeromem(iNonce, sizeof(iNonce)); + for (x = ocb->block_len-1, y=0; y<(int)noncelen; x--, y++) { + iNonce[x] = nonce[noncelen-y-1]; + } + iNonce[x] = 0x01; + iNonce[0] |= ((taglen*8) % 128) << 1; + + /* bottom = str2num(Nonce[123..128]) */ + bottom = iNonce[ocb->block_len-1] & 0x3F; + + /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */ + iNonce[ocb->block_len-1] = iNonce[ocb->block_len-1] & 0xC0; + if ((cipher_descriptor[ocb->cipher]->ecb_encrypt(iNonce, iKtop, &ocb->key)) != CRYPT_OK) { + zeromem(ocb->Offset_current, ocb->block_len); + return; + } + + /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */ + for (x = 0; x < ocb->block_len; x++) { + iStretch[x] = iKtop[x]; + } + for (y = 0; y < 8; y++) { + iStretch[x+y] = iKtop[y] ^ iKtop[y+1]; + } + + /* Offset_0 = Stretch[1+bottom..128+bottom] */ + idx = bottom / 8; + shift = (bottom % 8); + for (x = 0; x < ocb->block_len; x++) { + ocb->Offset_current[x] = iStretch[idx+x] << shift; + if (shift > 0) { + ocb->Offset_current[x] |= iStretch[idx+x+1] >> (8-shift); + } + } +} + +static const struct { + int len; + unsigned char poly_mul[MAXBLOCKSIZE]; +} polys[] = { +{ + 8, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } +}, { + 16, + { 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 + @param noncelen The length of the session nonce (octets, up to 15) + @param taglen The length of the tag (octets, up to 16) + @return CRYPT_OK if successful +*/ +int ocb3_init(ocb3_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + unsigned long taglen) +{ + int poly, x, y, m, err; + unsigned char *previous, *current; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + + /* valid cipher? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + ocb->cipher = cipher; + + /* Valid Nonce? + * As of RFC7253: "string of no more than 120 bits" */ + if (noncelen > (120/8)) { + return CRYPT_INVALID_ARG; + } + + /* The blockcipher must have a 128-bit blocksize */ + if (cipher_descriptor[cipher]->block_length != 16) { + return CRYPT_INVALID_ARG; + } + + /* The TAGLEN may be any value up to 128 (bits) */ + if (taglen > 16) { + return CRYPT_INVALID_ARG; + } + ocb->tag_len = taglen; + + /* determine which polys to use */ + ocb->block_len = cipher_descriptor[cipher]->block_length; + x = (int)(sizeof(polys)/sizeof(polys[0])); + for (poly = 0; poly < x; poly++) { + if (polys[poly].len == ocb->block_len) { + break; + } + } + if (poly == x) { + return CRYPT_INVALID_ARG; /* block_len not found in polys */ + } + 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; + } + + /* L_* = ENCIPHER(K, zeros(128)) */ + zeromem(ocb->L_star, ocb->block_len); + if ((err = cipher_descriptor[cipher]->ecb_encrypt(ocb->L_star, ocb->L_star, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* compute L_$, L_0, L_1, ... */ + for (x = -1; x < 32; x++) { + if (x == -1) { /* gonna compute: L_$ = double(L_*) */ + current = ocb->L_dollar; + previous = ocb->L_star; + } + else if (x == 0) { /* gonna compute: L_0 = double(L_$) */ + current = ocb->L_[0]; + previous = ocb->L_dollar; + } + else { /* gonna compute: L_i = double(L_{i-1}) for every integer i > 0 */ + current = ocb->L_[x]; + previous = ocb->L_[x-1]; + } + m = previous[0] >> 7; + for (y = 0; y < ocb->block_len-1; y++) { + current[y] = ((previous[y] << 1) | (previous[y+1] >> 7)) & 255; + } + current[ocb->block_len-1] = (previous[ocb->block_len-1] << 1) & 255; + if (m == 1) { + /* current[] = current[] XOR polys[poly].poly_mul[]*/ + ocb3_int_xor_blocks(current, current, polys[poly].poly_mul, ocb->block_len); + } + } + + /* initialize ocb->Offset_current = Offset_0 */ + s_ocb3_int_calc_offset_zero(ocb, nonce, noncelen, taglen); + + /* initialize checksum to all zeros */ + zeromem(ocb->checksum, ocb->block_len); + + /* set block index */ + ocb->block_index = 1; + + /* initialize AAD related stuff */ + ocb->ablock_index = 1; + ocb->adata_buffer_bytes = 0; + zeromem(ocb->aOffset_current, ocb->block_len); + zeromem(ocb->aSum_current, ocb->block_len); + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c new file mode 100644 index 0000000..86942ce --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_int_ntz.c + OCB implementation, INTERNAL ONLY helper, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Returns the number of leading zero bits [from lsb up] (internal function) + @param x The 32-bit value to observe + @return The number of bits [from the lsb up] that are zero +*/ +int ocb3_int_ntz(unsigned long x) +{ + int c; + x &= 0xFFFFFFFFUL; + c = 0; + while ((x & 1) == 0) { + ++c; + x >>= 1; + } + return c; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c new file mode 100644 index 0000000..f9f342a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_int_xor_blocks.c + OCB implementation, INTERNAL ONLY helper, by Karel Miko +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Compute xor for two blocks of bytes 'out = block_a XOR block_b' (internal function) + @param out The block of bytes (output) + @param block_a The block of bytes (input) + @param block_b The block of bytes (input) + @param block_len The size of block_a, block_b, out +*/ +void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len) +{ + int x; + if (out == block_a) { + for (x = 0; x < (int)block_len; x++) out[x] ^= block_b[x]; + } + else { + for (x = 0; x < (int)block_len; x++) out[x] = block_a[x] ^ block_b[x]; + } +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c new file mode 100644 index 0000000..3a9816e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c @@ -0,0 +1,299 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_test.c + OCB implementation, self-test by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Test the OCB protocol + @return CRYPT_OK if successful +*/ +int ocb3_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + /* test vectors from: http://tools.ietf.org/html/draft-krovetz-ocb-03 */ + unsigned char key[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; + unsigned char nonce[12] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B }; + const struct { + int ptlen; + int aadlen; + unsigned char pt[64], aad[64], ct[64], tag[16]; + } tests[] = { + + { /* index:0 */ + 0, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x19,0x7b,0x9c,0x3c,0x44,0x1d,0x3c,0x83,0xea,0xfb,0x2b,0xef,0x63,0x3b,0x91,0x82 }, /* TAG */ + }, + { /* index:1 */ + 8, /* PLAINTEXT length */ + 8, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */ + { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */ + { 0x16,0xdc,0x76,0xa4,0x6d,0x47,0xe1,0xea,0xd5,0x37,0x20,0x9e,0x8a,0x96,0xd1,0x4e }, /* TAG */ + }, + { /* index:2 */ + 0, /* PLAINTEXT length */ + 8, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x98,0xb9,0x15,0x52,0xc8,0xc0,0x09,0x18,0x50,0x44,0xe3,0x0a,0x6e,0xb2,0xfe,0x21 }, /* TAG */ + }, + { /* index:3 */ + 8, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */ + { 0x97,0x1e,0xff,0xca,0xe1,0x9a,0xd4,0x71,0x6f,0x88,0xe8,0x7b,0x87,0x1f,0xbe,0xed }, /* TAG */ + }, + { /* index:4 */ + 16, /* PLAINTEXT length */ + 16, /* AAD length */ + { 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 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */ + { 0x77,0x6c,0x99,0x24,0xd6,0x72,0x3a,0x1f,0xc4,0x52,0x45,0x32,0xac,0x3e,0x5b,0xeb }, /* TAG */ + }, + { /* index:5 */ + 0, /* PLAINTEXT length */ + 16, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x7d,0xdb,0x8e,0x6c,0xea,0x68,0x14,0x86,0x62,0x12,0x50,0x96,0x19,0xb1,0x9c,0xc6 }, /* TAG */ + }, + { /* index:6 */ + 16, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */ + { 0x13,0xcc,0x8b,0x74,0x78,0x07,0x12,0x1a,0x4c,0xbb,0x3e,0x4b,0xd6,0xb4,0x56,0xaf }, /* TAG */ + }, + { /* index:7 */ + 24, /* PLAINTEXT length */ + 24, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* 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 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */ + { 0x5f,0xa9,0x4f,0xc3,0xf3,0x88,0x20,0xf1,0xdc,0x3f,0x3d,0x1f,0xd4,0xe5,0x5e,0x1c }, /* TAG */ + }, + { /* index:8 */ + 0, /* PLAINTEXT length */ + 24, /* AAD length */ + { 0 }, /* 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 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x28,0x20,0x26,0xda,0x30,0x68,0xbc,0x9f,0xa1,0x18,0x68,0x1d,0x55,0x9f,0x10,0xf6 }, /* TAG */ + }, + { /* index:9 */ + 24, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */ + { 0x6e,0xf2,0xf5,0x25,0x87,0xfd,0xa0,0xed,0x97,0xdc,0x7e,0xed,0xe2,0x41,0xdf,0x68 }, /* TAG */ + }, + { /* index:10 */ + 32, /* PLAINTEXT length */ + 32, /* AAD length */ + { 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 }, /* 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 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */ + { 0xb2,0xa0,0x40,0xdd,0x3b,0xd5,0x16,0x43,0x72,0xd7,0x6d,0x7b,0xb6,0x82,0x42,0x40 }, /* TAG */ + }, + { /* index:11 */ + 0, /* PLAINTEXT length */ + 32, /* AAD length */ + { 0 }, /* 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 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0xe1,0xe0,0x72,0x63,0x3b,0xad,0xe5,0x1a,0x60,0xe8,0x59,0x51,0xd9,0xc4,0x2a,0x1b }, /* TAG */ + }, + { /* index:12 */ + 32, /* PLAINTEXT length */ + 0, /* AAD length */ + { 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 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */ + { 0x4a,0x3b,0xae,0x82,0x44,0x65,0xcf,0xda,0xf8,0xc4,0x1f,0xc5,0x0c,0x7d,0xf9,0xd9 }, /* TAG */ + }, + { /* index:13 */ + 40, /* PLAINTEXT length */ + 40, /* AAD length */ + { 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 }, /* 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,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */ + { 0x65,0x9c,0x62,0x32,0x11,0xde,0xea,0x0d,0xe3,0x0d,0x2c,0x38,0x18,0x79,0xf4,0xc8 }, /* TAG */ + }, + { /* index:14 */ + 0, /* PLAINTEXT length */ + 40, /* AAD length */ + { 0 }, /* 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,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x7a,0xeb,0x7a,0x69,0xa1,0x68,0x7d,0xd0,0x82,0xca,0x27,0xb0,0xd9,0xa3,0x70,0x96 }, /* TAG */ + }, + { /* index:15 */ + 40, /* PLAINTEXT length */ + 0, /* AAD length */ + { 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 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */ + { 0x06,0x0c,0x84,0x67,0xf4,0xab,0xab,0x5e,0x8b,0x3c,0x20,0x67,0xa2,0xe1,0x15,0xdc }, /* TAG */ + }, + +}; + /* As of RFC 7253 - 'Appendix A. Sample Results' + * The next tuple shows a result with a tag length of 96 bits and a + different key. + + K: 0F0E0D0C0B0A09080706050403020100 + + N: BBAA9988776655443322110D + A: 000102030405060708090A0B0C0D0E0F1011121314151617 + 18191A1B1C1D1E1F2021222324252627 + P: 000102030405060708090A0B0C0D0E0F1011121314151617 + 18191A1B1C1D1E1F2021222324252627 + C: 1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1 + A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD + AC4F02AA + + The C has been split up in C and T (tag) + */ + const unsigned char K[] = { 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08, + 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 }; + const unsigned char N[] = { 0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44, + 0x33,0x22,0x11,0x0D }; + const unsigned char A[] = { 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 }; + const unsigned char P[] = { 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 }; + const unsigned char C[] = { 0x17,0x92,0xA4,0xE3,0x1E,0x07,0x55,0xFB, + 0x03,0xE3,0x1B,0x22,0x11,0x6E,0x6C,0x2D, + 0xDF,0x9E,0xFD,0x6E,0x33,0xD5,0x36,0xF1, + 0xA0,0x12,0x4B,0x0A,0x55,0xBA,0xE8,0x84, + 0xED,0x93,0x48,0x15,0x29,0xC7,0x6B,0x6A }; + const unsigned char T[] = { 0xD0,0xC5,0x15,0xF4,0xD1,0xCD,0xD4,0xFD, + 0xAC,0x4F,0x02,0xAA }; + + int err, x, idx, res; + unsigned long len; + unsigned char outct[MAXBLOCKSIZE] = { 0 }; + unsigned char outtag[MAXBLOCKSIZE] = { 0 }; + ocb3_state ocb; + + /* 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 = 16; /* must be the same as the required taglen */ + if ((err = ocb3_encrypt_authenticate_memory(idx, + key, sizeof(key), + nonce, sizeof(nonce), + tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen, + tests[x].ptlen != 0 ? tests[x].pt : NULL, tests[x].ptlen, + tests[x].ptlen != 0 ? outct : NULL, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB3 Tag", x) || + compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB3 CT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = ocb3_decrypt_verify_memory(idx, + key, sizeof(key), + nonce, sizeof(nonce), + tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen, + tests[x].ptlen != 0 ? outct : NULL, tests[x].ptlen, + tests[x].ptlen != 0 ? outct : NULL, tests[x].tag, len, &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB3", x)) { +#ifdef LTC_TEST_DBG + printf("\n\nOCB3: Failure-decrypt - res = %d\n", res); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + + /* RFC 7253 - test vector with a tag length of 96 bits - part 1 */ + x = 99; + len = 12; + if ((err = ocb3_encrypt_authenticate_memory(idx, + K, sizeof(K), + N, sizeof(N), + A, sizeof(A), + P, sizeof(P), + outct, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag", x) || + compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = ocb3_decrypt_verify_memory(idx, + K, sizeof(K), + N, sizeof(N), + A, sizeof(A), + C, sizeof(C), + outct, T, sizeof(T), &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3", x)) { +#ifdef LTC_TEST_DBG + printf("\n\nOCB3: Failure-decrypt - res = %d\n", res); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + /* RFC 7253 - test vector with a tag length of 96 bits - part 2 */ + x = 100; + if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err; + if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err; + if ((err = ocb3_encrypt(&ocb, P, 32, outct)) != CRYPT_OK) return err; + if ((err = ocb3_encrypt_last(&ocb, P+32, sizeof(P)-32, outct+32)) != CRYPT_OK) return err; + len = sizeof(outtag); /* intentionally more than 12 */ + if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err; + if (compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.enc", x)) return CRYPT_FAIL_TESTVECTOR; + if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err; + if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err; + if ((err = ocb3_decrypt(&ocb, C, 32, outct)) != CRYPT_OK) return err; + if ((err = ocb3_decrypt_last(&ocb, C+32, sizeof(C)-32, outct+32)) != CRYPT_OK) return err; + len = sizeof(outtag); /* intentionally more than 12 */ + if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err; + if (compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3 PT", x)) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.dec", x)) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* LTC_OCB3_MODE */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/encauth/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/encauth/sub.mk new file mode 100644 index 0000000..6ef9405 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/encauth/sub.mk @@ -0,0 +1,2 @@ +subdirs-$(_CFG_CORE_LTC_CCM) += ccm +subdirs-$(_CFG_CORE_LTC_GCM) += gcm diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2b.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2b.c new file mode 100644 index 0000000..8cbeac2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2b.c @@ -0,0 +1,628 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ +/* see also https://www.ietf.org/rfc/rfc7693.txt */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2B + +enum blake2b_constant { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16, + BLAKE2B_PARAM_SIZE = 64 +}; + +/* param offsets */ +enum { + O_DIGEST_LENGTH = 0, + O_KEY_LENGTH = 1, + O_FANOUT = 2, + O_DEPTH = 3, + O_LEAF_LENGTH = 4, + O_NODE_OFFSET = 8, + O_XOF_LENGTH = 12, + O_NODE_DEPTH = 16, + O_INNER_LENGTH = 17, + O_RESERVED = 18, + O_SALT = 32, + O_PERSONAL = 48 +}; + +/* +struct blake2b_param { + unsigned char digest_length; + unsigned char key_length; + unsigned char fanout; + unsigned char depth; + ulong32 leaf_length; + ulong32 node_offset; + ulong32 xof_length; + unsigned char node_depth; + unsigned char inner_length; + unsigned char reserved[14]; + unsigned char salt[BLAKE2B_SALTBYTES]; + unsigned char personal[BLAKE2B_PERSONALBYTES]; +}; +*/ + +const struct ltc_hash_descriptor blake2b_160_desc = +{ + "blake2b-160", + 25, + 20, + 128, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 5 }, + 11, + &blake2b_160_init, + &blake2b_process, + &blake2b_done, + &blake2b_160_test, + NULL +}; + +const struct ltc_hash_descriptor blake2b_256_desc = +{ + "blake2b-256", + 26, + 32, + 128, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 8 }, + 11, + &blake2b_256_init, + &blake2b_process, + &blake2b_done, + &blake2b_256_test, + NULL +}; + +const struct ltc_hash_descriptor blake2b_384_desc = +{ + "blake2b-384", + 27, + 48, + 128, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 12 }, + 11, + &blake2b_384_init, + &blake2b_process, + &blake2b_done, + &blake2b_384_test, + NULL +}; + +const struct ltc_hash_descriptor blake2b_512_desc = +{ + "blake2b-512", + 28, + 64, + 128, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 16 }, + 11, + &blake2b_512_init, + &blake2b_process, + &blake2b_done, + &blake2b_512_test, + NULL +}; + +static const ulong64 blake2b_IV[8] = +{ + CONST64(0x6a09e667f3bcc908), CONST64(0xbb67ae8584caa73b), + CONST64(0x3c6ef372fe94f82b), CONST64(0xa54ff53a5f1d36f1), + CONST64(0x510e527fade682d1), CONST64(0x9b05688c2b3e6c1f), + CONST64(0x1f83d9abfb41bd6b), CONST64(0x5be0cd19137e2179) +}; + +static const unsigned char blake2b_sigma[12][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + +static void s_blake2b_set_lastnode(hash_state *md) { md->blake2b.f[1] = CONST64(0xffffffffffffffff); } + +/* Some helper functions, not necessarily useful */ +static int s_blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; } + +static void s_blake2b_set_lastblock(hash_state *md) +{ + if (md->blake2b.last_node) { + s_blake2b_set_lastnode(md); + } + md->blake2b.f[0] = CONST64(0xffffffffffffffff); +} + +static void s_blake2b_increment_counter(hash_state *md, ulong64 inc) +{ + md->blake2b.t[0] += inc; + if (md->blake2b.t[0] < inc) md->blake2b.t[1]++; +} + +static void s_blake2b_init0(hash_state *md) +{ + unsigned long i; + XMEMSET(&md->blake2b, 0, sizeof(md->blake2b)); + + for (i = 0; i < 8; ++i) { + md->blake2b.h[i] = blake2b_IV[i]; + } +} + +/* init xors IV with input parameter block */ +static int s_blake2b_init_param(hash_state *md, const unsigned char *P) +{ + unsigned long i; + + s_blake2b_init0(md); + + /* IV XOR ParamBlock */ + for (i = 0; i < 8; ++i) { + ulong64 tmp; + LOAD64L(tmp, P + i * 8); + md->blake2b.h[i] ^= tmp; + } + + md->blake2b.outlen = P[O_DIGEST_LENGTH]; + return CRYPT_OK; +} + +/** + Initialize the hash/MAC state + + Use this function to init for arbitrary sizes. + + Give a key and keylen to init for MAC mode. + + @param md The hash state you wish to initialize + @param outlen The desired output-length + @param key The key of the MAC + @param keylen The length of the key + @return CRYPT_OK if successful +*/ +int blake2b_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) +{ + unsigned char P[BLAKE2B_PARAM_SIZE]; + int err; + + LTC_ARGCHK(md != NULL); + + if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) { + return CRYPT_INVALID_ARG; + } + if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2B_KEYBYTES)) { + return CRYPT_INVALID_ARG; + } + + XMEMSET(P, 0, sizeof(P)); + + P[O_DIGEST_LENGTH] = (unsigned char)outlen; + P[O_KEY_LENGTH] = (unsigned char)keylen; + P[O_FANOUT] = 1; + P[O_DEPTH] = 1; + + err = s_blake2b_init_param(md, P); + if (err != CRYPT_OK) return err; + + if (key) { + unsigned char block[BLAKE2B_BLOCKBYTES]; + + XMEMSET(block, 0, BLAKE2B_BLOCKBYTES); + XMEMCPY(block, key, keylen); + blake2b_process(md, block, BLAKE2B_BLOCKBYTES); + +#ifdef LTC_CLEAN_STACK + zeromem(block, sizeof(block)); +#endif + } + + return CRYPT_OK; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2b_160_init(hash_state *md) { return blake2b_init(md, 20, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2b_256_init(hash_state *md) { return blake2b_init(md, 32, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2b_384_init(hash_state *md) { return blake2b_init(md, 48, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2b_512_init(hash_state *md) { return blake2b_init(md, 64, NULL, 0); } + +#define G(r, i, a, b, c, d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ + d = ROR64(d ^ a, 32); \ + c = c + d; \ + b = ROR64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ + d = ROR64(d ^ a, 16); \ + c = c + d; \ + b = ROR64(b ^ c, 63); \ + } while (0) + +#define ROUND(r) \ + do { \ + G(r, 0, v[0], v[4], v[8], v[12]); \ + G(r, 1, v[1], v[5], v[9], v[13]); \ + G(r, 2, v[2], v[6], v[10], v[14]); \ + G(r, 3, v[3], v[7], v[11], v[15]); \ + G(r, 4, v[0], v[5], v[10], v[15]); \ + G(r, 5, v[1], v[6], v[11], v[12]); \ + G(r, 6, v[2], v[7], v[8], v[13]); \ + G(r, 7, v[3], v[4], v[9], v[14]); \ + } while (0) + +#ifdef LTC_CLEAN_STACK +static int ss_blake2b_compress(hash_state *md, const unsigned char *buf) +#else +static int s_blake2b_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong64 m[16]; + ulong64 v[16]; + unsigned long i; + + for (i = 0; i < 16; ++i) { + LOAD64L(m[i], buf + i * sizeof(m[i])); + } + + for (i = 0; i < 8; ++i) { + v[i] = md->blake2b.h[i]; + } + + v[8] = blake2b_IV[0]; + v[9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = blake2b_IV[4] ^ md->blake2b.t[0]; + v[13] = blake2b_IV[5] ^ md->blake2b.t[1]; + v[14] = blake2b_IV[6] ^ md->blake2b.f[0]; + v[15] = blake2b_IV[7] ^ md->blake2b.f[1]; + + ROUND(0); + ROUND(1); + ROUND(2); + ROUND(3); + ROUND(4); + ROUND(5); + ROUND(6); + ROUND(7); + ROUND(8); + ROUND(9); + ROUND(10); + ROUND(11); + + for (i = 0; i < 8; ++i) { + md->blake2b.h[i] = md->blake2b.h[i] ^ v[i] ^ v[i + 8]; + } + return CRYPT_OK; +} + +#undef G +#undef ROUND + +#ifdef LTC_CLEAN_STACK +static int s_blake2b_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_blake2b_compress(md, buf); + burn_stack(sizeof(ulong64) * 32 + sizeof(unsigned long)); + return err; +} +#endif + +/** + Process a block of memory through 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 +*/ +int blake2b_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + if (md->blake2b.curlen > sizeof(md->blake2b.buf)) { + return CRYPT_INVALID_ARG; + } + + if (inlen > 0) { + unsigned long left = md->blake2b.curlen; + unsigned long fill = BLAKE2B_BLOCKBYTES - left; + if (inlen > fill) { + md->blake2b.curlen = 0; + XMEMCPY(md->blake2b.buf + (left % sizeof(md->blake2b.buf)), in, fill); /* Fill buffer */ + s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); + s_blake2b_compress(md, md->blake2b.buf); /* Compress */ + in += fill; + inlen -= fill; + while (inlen > BLAKE2B_BLOCKBYTES) { + s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); + s_blake2b_compress(md, in); + in += BLAKE2B_BLOCKBYTES; + inlen -= BLAKE2B_BLOCKBYTES; + } + } + XMEMCPY(md->blake2b.buf + md->blake2b.curlen, in, inlen); + md->blake2b.curlen += inlen; + } + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (size depending on the length used on init) + @return CRYPT_OK if successful +*/ +int blake2b_done(hash_state *md, unsigned char *out) +{ + unsigned char buffer[BLAKE2B_OUTBYTES] = { 0 }; + unsigned long i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + /* if(md->blakebs.outlen != outlen) return CRYPT_INVALID_ARG; */ + + if (s_blake2b_is_lastblock(md)) { + return CRYPT_ERROR; + } + + s_blake2b_increment_counter(md, md->blake2b.curlen); + s_blake2b_set_lastblock(md); + XMEMSET(md->blake2b.buf + md->blake2b.curlen, 0, BLAKE2B_BLOCKBYTES - md->blake2b.curlen); /* Padding */ + s_blake2b_compress(md, md->blake2b.buf); + + for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ + STORE64L(md->blake2b.h[i], buffer + i * 8); + } + + XMEMCPY(out, buffer, md->blake2b.outlen); + zeromem(md, sizeof(hash_state)); +#ifdef LTC_CLEAN_STACK + zeromem(buffer, sizeof(buffer)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2b_512_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[64]; + } tests[] = { + { "", + { 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03, + 0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72, + 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61, + 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19, + 0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53, + 0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b, + 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55, + 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce } }, + { "abc", + { 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, + 0x6a, 0x27, 0x97, 0xb6, 0x9f, 0x12, 0xf6, 0xe9, + 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 0xc4, 0xb7, + 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1, + 0x7d, 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d, + 0xc2, 0x52, 0xd5, 0xde, 0x45, 0x33, 0xcc, 0x95, + 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a, + 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[64]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2b_512_init(&md); + blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2b_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_512", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2b_384_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[48]; + } tests[] = { + { "", + { 0xb3, 0x28, 0x11, 0x42, 0x33, 0x77, 0xf5, 0x2d, + 0x78, 0x62, 0x28, 0x6e, 0xe1, 0xa7, 0x2e, 0xe5, + 0x40, 0x52, 0x43, 0x80, 0xfd, 0xa1, 0x72, 0x4a, + 0x6f, 0x25, 0xd7, 0x97, 0x8c, 0x6f, 0xd3, 0x24, + 0x4a, 0x6c, 0xaf, 0x04, 0x98, 0x81, 0x26, 0x73, + 0xc5, 0xe0, 0x5e, 0xf5, 0x83, 0x82, 0x51, 0x00 } }, + { "abc", + { 0x6f, 0x56, 0xa8, 0x2c, 0x8e, 0x7e, 0xf5, 0x26, + 0xdf, 0xe1, 0x82, 0xeb, 0x52, 0x12, 0xf7, 0xdb, + 0x9d, 0xf1, 0x31, 0x7e, 0x57, 0x81, 0x5d, 0xbd, + 0xa4, 0x60, 0x83, 0xfc, 0x30, 0xf5, 0x4e, 0xe6, + 0xc6, 0x6b, 0xa8, 0x3b, 0xe6, 0x4b, 0x30, 0x2d, + 0x7c, 0xba, 0x6c, 0xe1, 0x5b, 0xb5, 0x56, 0xf4 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[48]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2b_384_init(&md); + blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2b_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_384", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2b_256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "", + { 0x0e, 0x57, 0x51, 0xc0, 0x26, 0xe5, 0x43, 0xb2, + 0xe8, 0xab, 0x2e, 0xb0, 0x60, 0x99, 0xda, 0xa1, + 0xd1, 0xe5, 0xdf, 0x47, 0x77, 0x8f, 0x77, 0x87, + 0xfa, 0xab, 0x45, 0xcd, 0xf1, 0x2f, 0xe3, 0xa8 } }, + { "abc", + { 0xbd, 0xdd, 0x81, 0x3c, 0x63, 0x42, 0x39, 0x72, + 0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b, + 0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42, + 0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } }, + { "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890", + { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08, + 0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41, + 0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3, + 0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2b_256_init(&md); + blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2b_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_256", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2b_160_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[20]; + } tests[] = { + { "", + { 0x33, 0x45, 0x52, 0x4a, 0xbf, 0x6b, 0xbe, 0x18, + 0x09, 0x44, 0x92, 0x24, 0xb5, 0x97, 0x2c, 0x41, + 0x79, 0x0b, 0x6c, 0xf2 } }, + { "abc", + { 0x38, 0x42, 0x64, 0xf6, 0x76, 0xf3, 0x95, 0x36, + 0x84, 0x05, 0x23, 0xf2, 0x84, 0x92, 0x1c, 0xdc, + 0x68, 0xb6, 0x84, 0x6b } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2b_160_init(&md); + blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2b_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_160", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c new file mode 100644 index 0000000..e8cd6eb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/blake2s.c @@ -0,0 +1,603 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ +/* see also https://www.ietf.org/rfc/rfc7693.txt */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2S + +enum blake2s_constant { + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, + BLAKE2S_PERSONALBYTES = 8, + BLAKE2S_PARAM_SIZE = 32 +}; + +/* param offsets */ +enum { + O_DIGEST_LENGTH = 0, + O_KEY_LENGTH = 1, + O_FANOUT = 2, + O_DEPTH = 3, + O_LEAF_LENGTH = 4, + O_NODE_OFFSET = 8, + O_XOF_LENGTH = 12, + O_NODE_DEPTH = 14, + O_INNER_LENGTH = 15, + O_SALT = 16, + O_PERSONAL = 24 +}; + +/* +struct blake2s_param { + unsigned char digest_length; + unsigned char key_length; + unsigned char fanout; + unsigned char depth; + ulong32 leaf_length; + ulong32 node_offset; + ushort16 xof_length; + unsigned char node_depth; + unsigned char inner_length; + unsigned char salt[BLAKE2S_SALTBYTES]; + unsigned char personal[BLAKE2S_PERSONALBYTES]; +}; +*/ + +const struct ltc_hash_descriptor blake2s_128_desc = +{ + "blake2s-128", + 21, + 16, + 64, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 }, + 11, + &blake2s_128_init, + &blake2s_process, + &blake2s_done, + &blake2s_128_test, + NULL +}; + +const struct ltc_hash_descriptor blake2s_160_desc = +{ + "blake2s-160", + 22, + 20, + 64, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 }, + 11, + &blake2s_160_init, + &blake2s_process, + &blake2s_done, + &blake2s_160_test, + NULL +}; + +const struct ltc_hash_descriptor blake2s_224_desc = +{ + "blake2s-224", + 23, + 28, + 64, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 }, + 11, + &blake2s_224_init, + &blake2s_process, + &blake2s_done, + &blake2s_224_test, + NULL +}; + +const struct ltc_hash_descriptor blake2s_256_desc = +{ + "blake2s-256", + 24, + 32, + 64, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 }, + 11, + &blake2s_256_init, + &blake2s_process, + &blake2s_done, + &blake2s_256_test, + NULL +}; + +static const ulong32 blake2s_IV[8] = { + 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, + 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL +}; + +static const unsigned char blake2s_sigma[10][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, +}; + +static void s_blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; } + +/* Some helper functions, not necessarily useful */ +static int s_blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; } + +static void s_blake2s_set_lastblock(hash_state *md) +{ + if (md->blake2s.last_node) { + s_blake2s_set_lastnode(md); + } + md->blake2s.f[0] = 0xffffffffUL; +} + +static void s_blake2s_increment_counter(hash_state *md, const ulong32 inc) +{ + md->blake2s.t[0] += inc; + if (md->blake2s.t[0] < inc) md->blake2s.t[1]++; +} + +static int s_blake2s_init0(hash_state *md) +{ + int i; + XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state)); + + for (i = 0; i < 8; ++i) { + md->blake2s.h[i] = blake2s_IV[i]; + } + + return CRYPT_OK; +} + +/* init2 xors IV with input parameter block */ +static int s_blake2s_init_param(hash_state *md, const unsigned char *P) +{ + unsigned long i; + + s_blake2s_init0(md); + + /* IV XOR ParamBlock */ + for (i = 0; i < 8; ++i) { + ulong32 tmp; + LOAD32L(tmp, P + i * 4); + md->blake2s.h[i] ^= tmp; + } + + md->blake2s.outlen = P[O_DIGEST_LENGTH]; + return CRYPT_OK; +} + +/** + Initialize the hash/MAC state + + Use this function to init for arbitrary sizes. + + Give a key and keylen to init for MAC mode. + + @param md The hash state you wish to initialize + @param outlen The desired output-length + @param key The key of the MAC + @param keylen The length of the key + @return CRYPT_OK if successful +*/ +int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) +{ + unsigned char P[BLAKE2S_PARAM_SIZE]; + int err; + + LTC_ARGCHK(md != NULL); + + if ((!outlen) || (outlen > BLAKE2S_OUTBYTES)) { + return CRYPT_INVALID_ARG; + } + if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES)) { + return CRYPT_INVALID_ARG; + } + + XMEMSET(P, 0, sizeof(P)); + + P[O_DIGEST_LENGTH] = (unsigned char)outlen; + P[O_KEY_LENGTH] = (unsigned char)keylen; + P[O_FANOUT] = 1; + P[O_DEPTH] = 1; + + err = s_blake2s_init_param(md, P); + if (err != CRYPT_OK) return err; + + if (key) { + unsigned char block[BLAKE2S_BLOCKBYTES]; + + XMEMSET(block, 0, BLAKE2S_BLOCKBYTES); + XMEMCPY(block, key, keylen); + blake2s_process(md, block, BLAKE2S_BLOCKBYTES); + +#ifdef LTC_CLEAN_STACK + zeromem(block, sizeof(block)); +#endif + } + return CRYPT_OK; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); } + +#define G(r, i, a, b, c, d) \ + do { \ + a = a + b + m[blake2s_sigma[r][2 * i + 0]]; \ + d = ROR(d ^ a, 16); \ + c = c + d; \ + b = ROR(b ^ c, 12); \ + a = a + b + m[blake2s_sigma[r][2 * i + 1]]; \ + d = ROR(d ^ a, 8); \ + c = c + d; \ + b = ROR(b ^ c, 7); \ + } while (0) +#define ROUND(r) \ + do { \ + G(r, 0, v[0], v[4], v[8], v[12]); \ + G(r, 1, v[1], v[5], v[9], v[13]); \ + G(r, 2, v[2], v[6], v[10], v[14]); \ + G(r, 3, v[3], v[7], v[11], v[15]); \ + G(r, 4, v[0], v[5], v[10], v[15]); \ + G(r, 5, v[1], v[6], v[11], v[12]); \ + G(r, 6, v[2], v[7], v[8], v[13]); \ + G(r, 7, v[3], v[4], v[9], v[14]); \ + } while (0) + +#ifdef LTC_CLEAN_STACK +static int ss_blake2s_compress(hash_state *md, const unsigned char *buf) +#else +static int s_blake2s_compress(hash_state *md, const unsigned char *buf) +#endif +{ + unsigned long i; + ulong32 m[16]; + ulong32 v[16]; + + for (i = 0; i < 16; ++i) { + LOAD32L(m[i], buf + i * sizeof(m[i])); + } + + for (i = 0; i < 8; ++i) { + v[i] = md->blake2s.h[i]; + } + + v[8] = blake2s_IV[0]; + v[9] = blake2s_IV[1]; + v[10] = blake2s_IV[2]; + v[11] = blake2s_IV[3]; + v[12] = md->blake2s.t[0] ^ blake2s_IV[4]; + v[13] = md->blake2s.t[1] ^ blake2s_IV[5]; + v[14] = md->blake2s.f[0] ^ blake2s_IV[6]; + v[15] = md->blake2s.f[1] ^ blake2s_IV[7]; + + ROUND(0); + ROUND(1); + ROUND(2); + ROUND(3); + ROUND(4); + ROUND(5); + ROUND(6); + ROUND(7); + ROUND(8); + ROUND(9); + + for (i = 0; i < 8; ++i) { + md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8]; + } + return CRYPT_OK; +} +#undef G +#undef ROUND + +#ifdef LTC_CLEAN_STACK +static int s_blake2s_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_blake2s_compress(md, buf); + burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long)); + return err; +} +#endif + +/** + Process a block of memory through 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 +*/ +int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + if (md->blake2s.curlen > sizeof(md->blake2s.buf)) { + return CRYPT_INVALID_ARG; + } + + if (inlen > 0) { + unsigned long left = md->blake2s.curlen; + unsigned long fill = BLAKE2S_BLOCKBYTES - left; + if (inlen > fill) { + md->blake2s.curlen = 0; + XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */ + s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES); + s_blake2s_compress(md, md->blake2s.buf); /* Compress */ + in += fill; + inlen -= fill; + while (inlen > BLAKE2S_BLOCKBYTES) { + s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES); + s_blake2s_compress(md, in); + in += BLAKE2S_BLOCKBYTES; + inlen -= BLAKE2S_BLOCKBYTES; + } + } + XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen); + md->blake2s.curlen += inlen; + } + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (size depending on the length used on init) + @return CRYPT_OK if successful +*/ +int blake2s_done(hash_state *md, unsigned char *out) +{ + unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 }; + unsigned long i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */ + + if (s_blake2s_is_lastblock(md)) { + return CRYPT_ERROR; + } + s_blake2s_increment_counter(md, md->blake2s.curlen); + s_blake2s_set_lastblock(md); + XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */ + s_blake2s_compress(md, md->blake2s.buf); + + for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ + STORE32L(md->blake2s.h[i], buffer + i * 4); + } + + XMEMCPY(out, buffer, md->blake2s.outlen); + zeromem(md, sizeof(hash_state)); +#ifdef LTC_CLEAN_STACK + zeromem(buffer, sizeof(buffer)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2s_256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "", + { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94, + 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c, + 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e, + 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } }, + { "abc", + { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2, + 0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f, + 0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29, + 0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } }, + { "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890", + { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41, + 0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41, + 0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70, + 0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2s_256_init(&md); + blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2s_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2s_224_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[28]; + } tests[] = { + { "", + { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37, + 0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63, + 0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34, + 0xe7, 0xbc, 0x1e, 0xf4 } }, + { "abc", + { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd, + 0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c, + 0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87, + 0x40, 0x7f, 0xbd, 0x55 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[28]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2s_224_init(&md); + blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2s_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2s_160_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[20]; + } tests[] = { + { "", + { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24, + 0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42, + 0x9c, 0x34, 0x91, 0x6f} }, + { "abc", + { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83, + 0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04, + 0x38, 0xf8, 0xde, 0x17 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2s_160_init(&md); + blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2s_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2s_128_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01, + 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } }, + { "abc", + { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8, + 0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2s_128_init(&md); + blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2s_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/chc/chc.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/chc/chc.c new file mode 100644 index 0000000..7de59a2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/chc/chc.c @@ -0,0 +1,302 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file chc.c + CHC support. (Tom St Denis) +*/ + +#ifdef LTC_CHC_HASH + +#define UNDEFED_HASH -17 + +/* chc settings */ +static int cipher_idx=UNDEFED_HASH, /* which cipher */ + cipher_blocksize; /* blocksize of cipher */ + + +const struct ltc_hash_descriptor chc_desc = { + "chc_hash", 12, 0, 0, { 0 }, 0, + &chc_init, + &chc_process, + &chc_done, + &chc_test, + NULL +}; + +/** + Initialize the CHC state with a given cipher + @param cipher The index of the cipher you wish to bind + @return CRYPT_OK if successful +*/ +int chc_register(int cipher) +{ + int err, kl, idx; + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* will it be valid? */ + kl = cipher_descriptor[cipher]->block_length; + + /* must be >64 bit block */ + if (kl <= 8) { + return CRYPT_INVALID_CIPHER; + } + + /* can we use the ideal keysize? */ + if ((err = cipher_descriptor[cipher]->keysize(&kl)) != CRYPT_OK) { + return err; + } + /* we require that key size == block size be a valid choice */ + if (kl != cipher_descriptor[cipher]->block_length) { + return CRYPT_INVALID_CIPHER; + } + + /* determine if chc_hash has been register_hash'ed already */ + if ((err = hash_is_valid(idx = find_hash("chc_hash"))) != CRYPT_OK) { + return err; + } + + /* store into descriptor */ + hash_descriptor[idx]->hashsize = + hash_descriptor[idx]->blocksize = cipher_descriptor[cipher]->block_length; + + /* store the idx and block size */ + cipher_idx = cipher; + cipher_blocksize = cipher_descriptor[cipher]->block_length; + return CRYPT_OK; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int chc_init(hash_state *md) +{ + symmetric_key *key; + unsigned char buf[MAXBLOCKSIZE]; + int err; + + LTC_ARGCHK(md != NULL); + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { + return err; + } + + if (cipher_blocksize != cipher_descriptor[cipher_idx]->block_length) { + return CRYPT_INVALID_CIPHER; + } + + if ((key = XMALLOC(sizeof(*key))) == NULL) { + return CRYPT_MEM; + } + + /* zero key and what not */ + zeromem(buf, cipher_blocksize); + if ((err = cipher_descriptor[cipher_idx]->setup(buf, cipher_blocksize, 0, key)) != CRYPT_OK) { + XFREE(key); + return err; + } + + /* encrypt zero block */ + cipher_descriptor[cipher_idx]->ecb_encrypt(buf, md->chc.state, key); + + /* zero other members */ + md->chc.length = 0; + md->chc.curlen = 0; + zeromem(md->chc.buf, sizeof(md->chc.buf)); + XFREE(key); + return CRYPT_OK; +} + +/* + key <= state + T0,T1 <= block + T0 <= encrypt T0 + state <= state xor T0 xor T1 +*/ +static int s_chc_compress(hash_state *md, const unsigned char *buf) +{ + unsigned char T[2][MAXBLOCKSIZE]; + symmetric_key *key; + int err, x; + + if ((key = XMALLOC(sizeof(*key))) == NULL) { + return CRYPT_MEM; + } + if ((err = cipher_descriptor[cipher_idx]->setup(md->chc.state, cipher_blocksize, 0, key)) != CRYPT_OK) { + XFREE(key); + return err; + } + XMEMCPY(T[1], buf, cipher_blocksize); + cipher_descriptor[cipher_idx]->ecb_encrypt(buf, T[0], key); + for (x = 0; x < cipher_blocksize; x++) { + md->chc.state[x] ^= T[0][x] ^ T[1][x]; + } +#ifdef LTC_CLEAN_STACK + zeromem(T, sizeof(T)); + zeromem(key, sizeof(*key)); +#endif + XFREE(key); + return CRYPT_OK; +} + +/** + Function for processing blocks + @param md The hash state + @param buf The data to hash + @param len The length of the data (octets) + @return CRYPT_OK if successful +*/ +static int ss_chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); +static HASH_PROCESS(ss_chc_process, s_chc_compress, chc, (unsigned long)cipher_blocksize) + +/** + 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 +*/ +int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen) +{ + int err; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { + return err; + } + if (cipher_blocksize != cipher_descriptor[cipher_idx]->block_length) { + return CRYPT_INVALID_CIPHER; + } + + return ss_chc_process(md, in, inlen); +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (length of the block size of the block cipher) + @return CRYPT_OK if successful +*/ +int chc_done(hash_state *md, unsigned char *out) +{ + int err; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { + return err; + } + if (cipher_blocksize != cipher_descriptor[cipher_idx]->block_length) { + return CRYPT_INVALID_CIPHER; + } + + if (md->chc.curlen >= sizeof(md->chc.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->chc.length += md->chc.curlen * 8; + + /* append the '1' bit */ + md->chc.buf[md->chc.curlen++] = (unsigned char)0x80; + + /* if the length is currently above l-8 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->chc.curlen > (unsigned long)(cipher_blocksize - 8)) { + while (md->chc.curlen < (unsigned long)cipher_blocksize) { + md->chc.buf[md->chc.curlen++] = (unsigned char)0; + } + s_chc_compress(md, md->chc.buf); + md->chc.curlen = 0; + } + + /* pad upto l-8 bytes of zeroes */ + while (md->chc.curlen < (unsigned long)(cipher_blocksize - 8)) { + md->chc.buf[md->chc.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->chc.length, md->chc.buf+(cipher_blocksize-8)); + s_chc_compress(md, md->chc.buf); + + /* copy output */ + XMEMCPY(out, md->chc.state, cipher_blocksize); + +#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 chc_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char *msg, + hash[MAXBLOCKSIZE]; + int len; + } tests[] = { +{ + (unsigned char *)"hello world", + { 0xcf, 0x57, 0x9d, 0xc3, 0x0a, 0x0e, 0xea, 0x61, + 0x0d, 0x54, 0x47, 0xc4, 0x3c, 0x06, 0xf5, 0x4e }, + 16 +} +}; + int i, oldhashidx, idx, err; + unsigned char tmp[MAXBLOCKSIZE]; + hash_state md; + + /* 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; + } + } + oldhashidx = cipher_idx; + chc_register(idx); + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + if ((err = chc_init(&md)) != CRYPT_OK) { + return err; + } + if ((err = chc_process(&md, tests[i].msg, XSTRLEN((char *)tests[i].msg))) != CRYPT_OK) { + return err; + } + if ((err = chc_done(&md, tmp)) != CRYPT_OK) { + return err; + } + if (compare_testvector(tmp, tests[i].len, tests[i].hash, tests[i].len, "CHC", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + if (oldhashidx != UNDEFED_HASH) { + chc_register(oldhashidx); + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_file.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_file.c new file mode 100644 index 0000000..d2711db --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_file.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifndef LTC_NO_FILE +/** + @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) +{ + 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 /* #ifndef LTC_NO_FILE */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c new file mode 100644 index 0000000..8ebf52a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifndef LTC_NO_FILE +/** + @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) +{ + hash_state md; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(in != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (*outlen < hash_descriptor[hash]->hashsize) { + *outlen = hash_descriptor[hash]->hashsize; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + if ((err = hash_descriptor[hash]->init(&md)) != CRYPT_OK) { + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = hash_descriptor[hash]->process(&md, buf, (unsigned long)x)) != CRYPT_OK) { + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + if ((err = hash_descriptor[hash]->done(&md, out)) == CRYPT_OK) { + *outlen = hash_descriptor[hash]->hashsize; + } + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: + XFREE(buf); + return err; +} +#endif /* #ifndef LTC_NO_FILE */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c new file mode 100644 index 0000000..1dfd6f6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_HASH_HELPERS +/** + @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; +} +#endif /* #ifdef LTC_HASH_HELPERS */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c new file mode 100644 index 0000000..e58b3c5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +#ifdef LTC_HASH_HELPERS +/** + @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; +} +#endif /* #ifdef LTC_HASH_HELPERS */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/sub.mk new file mode 100644 index 0000000..c01be6d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/helper/sub.mk @@ -0,0 +1,4 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += hash_memory.c +srcs-y += hash_memory_multi.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/md2.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/md2.c new file mode 100644 index 0000000..6cf0a65 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/md2.c @@ -0,0 +1,240 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param md2.c + LTC_MD2 (RFC 1319) hash function implementation by Tom St Denis +*/ + +#ifdef LTC_MD2 + +const struct ltc_hash_descriptor md2_desc = +{ + "md2", + 7, + 16, + 16, + + /* OID */ + { 1, 2, 840, 113549, 2, 2, }, + 6, + + &md2_init, + &md2_process, + &md2_done, + &md2_test, + NULL +}; + +static const unsigned char PI_SUBST[256] = { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 +}; + +/* adds 16 bytes to the checksum */ +static void s_md2_update_chksum(hash_state *md) +{ + int j; + unsigned char L; + L = md->md2.chksum[15]; + for (j = 0; j < 16; j++) { + +/* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say + otherwise. +*/ + L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255); + } +} + +static void s_md2_compress(hash_state *md) +{ + int j, k; + unsigned char t; + + /* copy block */ + for (j = 0; j < 16; j++) { + md->md2.X[16+j] = md->md2.buf[j]; + md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j]; + } + + t = (unsigned char)0; + + /* do 18 rounds */ + for (j = 0; j < 18; j++) { + for (k = 0; k < 48; k++) { + t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]); + } + t = (t + (unsigned char)j) & 255; + } +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int md2_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + + /* LTC_MD2 uses a zero'ed state... */ + zeromem(md->md2.X, sizeof(md->md2.X)); + zeromem(md->md2.chksum, sizeof(md->md2.chksum)); + zeromem(md->md2.buf, sizeof(md->md2.buf)); + md->md2.curlen = 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 +*/ +int md2_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + unsigned long n; + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + if (md-> md2 .curlen > sizeof(md-> md2 .buf)) { + return CRYPT_INVALID_ARG; + } + while (inlen > 0) { + n = MIN(inlen, (16 - md->md2.curlen)); + XMEMCPY(md->md2.buf + md->md2.curlen, in, (size_t)n); + md->md2.curlen += n; + in += n; + inlen -= n; + + /* is 16 bytes full? */ + if (md->md2.curlen == 16) { + s_md2_compress(md); + s_md2_update_chksum(md); + md->md2.curlen = 0; + } + } + return CRYPT_OK; +} + +/** + 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 md2_done(hash_state * md, unsigned char *out) +{ + unsigned long i, k; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->md2.curlen >= sizeof(md->md2.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* pad the message */ + k = 16 - md->md2.curlen; + for (i = md->md2.curlen; i < 16; i++) { + md->md2.buf[i] = (unsigned char)k; + } + + /* hash and update */ + s_md2_compress(md); + s_md2_update_chksum(md); + + /* hash checksum */ + XMEMCPY(md->md2.buf, md->md2.chksum, 16); + s_md2_compress(md); + + /* output is lower 16 bytes of X */ + XMEMCPY(out, md->md2.X, 16); + +#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 md2_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d, + 0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73 + } + }, + { "a", + {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72, + 0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1 + } + }, + { "message digest", + {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b, + 0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0 + } + }, + { "abcdefghijklmnopqrstuvwxyz", + {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab, + 0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b + } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39, + 0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd + } + }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d, + 0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8 + } + } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + md2_init(&md); + md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + md2_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD2", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/md4.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/md4.c new file mode 100644 index 0000000..aadad5f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/md4.c @@ -0,0 +1,296 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param md4.c + Submitted by Dobes Vandermeer (dobes@smartt.com) +*/ + +#ifdef LTC_MD4 + +const struct ltc_hash_descriptor md4_desc = +{ + "md4", + 6, + 16, + 64, + + /* OID */ + { 1, 2, 840, 113549, 2, 4, }, + 6, + + &md4_init, + &md4_process, + &md4_done, + &md4_test, + NULL +}; + +#define S11 3 +#define S12 7 +#define S13 11 +#define S14 19 +#define S21 3 +#define S22 5 +#define S23 9 +#define S24 13 +#define S31 3 +#define S32 9 +#define S33 11 +#define S34 15 + +/* F, G and H are basic LTC_MD4 functions. */ +#define F(x, y, z) (z ^ (x & (y ^ z))) +#define G(x, y, z) ((x & y) | (z & (x | y))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) ROLc(x, n) + +/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ + +#define FF(a, b, c, d, x, s) { \ + (a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define GG(a, b, c, d, x, s) { \ + (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define HH(a, b, c, d, x, s) { \ + (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } + +#ifdef LTC_CLEAN_STACK +static int ss_md4_compress(hash_state *md, const unsigned char *buf) +#else +static int s_md4_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 x[16], a, b, c, d; + int i; + + /* copy state */ + a = md->md4.state[0]; + b = md->md4.state[1]; + c = md->md4.state[2]; + d = md->md4.state[3]; + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32L(x[i], buf + (4*i)); + } + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11); /* 1 */ + FF (d, a, b, c, x[ 1], S12); /* 2 */ + FF (c, d, a, b, x[ 2], S13); /* 3 */ + FF (b, c, d, a, x[ 3], S14); /* 4 */ + FF (a, b, c, d, x[ 4], S11); /* 5 */ + FF (d, a, b, c, x[ 5], S12); /* 6 */ + FF (c, d, a, b, x[ 6], S13); /* 7 */ + FF (b, c, d, a, x[ 7], S14); /* 8 */ + FF (a, b, c, d, x[ 8], S11); /* 9 */ + FF (d, a, b, c, x[ 9], S12); /* 10 */ + FF (c, d, a, b, x[10], S13); /* 11 */ + FF (b, c, d, a, x[11], S14); /* 12 */ + FF (a, b, c, d, x[12], S11); /* 13 */ + FF (d, a, b, c, x[13], S12); /* 14 */ + FF (c, d, a, b, x[14], S13); /* 15 */ + FF (b, c, d, a, x[15], S14); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 0], S21); /* 17 */ + GG (d, a, b, c, x[ 4], S22); /* 18 */ + GG (c, d, a, b, x[ 8], S23); /* 19 */ + GG (b, c, d, a, x[12], S24); /* 20 */ + GG (a, b, c, d, x[ 1], S21); /* 21 */ + GG (d, a, b, c, x[ 5], S22); /* 22 */ + GG (c, d, a, b, x[ 9], S23); /* 23 */ + GG (b, c, d, a, x[13], S24); /* 24 */ + GG (a, b, c, d, x[ 2], S21); /* 25 */ + GG (d, a, b, c, x[ 6], S22); /* 26 */ + GG (c, d, a, b, x[10], S23); /* 27 */ + GG (b, c, d, a, x[14], S24); /* 28 */ + GG (a, b, c, d, x[ 3], S21); /* 29 */ + GG (d, a, b, c, x[ 7], S22); /* 30 */ + GG (c, d, a, b, x[11], S23); /* 31 */ + GG (b, c, d, a, x[15], S24); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 0], S31); /* 33 */ + HH (d, a, b, c, x[ 8], S32); /* 34 */ + HH (c, d, a, b, x[ 4], S33); /* 35 */ + HH (b, c, d, a, x[12], S34); /* 36 */ + HH (a, b, c, d, x[ 2], S31); /* 37 */ + HH (d, a, b, c, x[10], S32); /* 38 */ + HH (c, d, a, b, x[ 6], S33); /* 39 */ + HH (b, c, d, a, x[14], S34); /* 40 */ + HH (a, b, c, d, x[ 1], S31); /* 41 */ + HH (d, a, b, c, x[ 9], S32); /* 42 */ + HH (c, d, a, b, x[ 5], S33); /* 43 */ + HH (b, c, d, a, x[13], S34); /* 44 */ + HH (a, b, c, d, x[ 3], S31); /* 45 */ + HH (d, a, b, c, x[11], S32); /* 46 */ + HH (c, d, a, b, x[ 7], S33); /* 47 */ + HH (b, c, d, a, x[15], S34); /* 48 */ + + + /* Update our state */ + md->md4.state[0] = md->md4.state[0] + a; + md->md4.state[1] = md->md4.state[1] + b; + md->md4.state[2] = md->md4.state[2] + c; + md->md4.state[3] = md->md4.state[3] + d; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_md4_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_md4_compress(md, buf); + burn_stack(sizeof(ulong32) * 20 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int md4_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->md4.state[0] = 0x67452301UL; + md->md4.state[1] = 0xefcdab89UL; + md->md4.state[2] = 0x98badcfeUL; + md->md4.state[3] = 0x10325476UL; + md->md4.length = 0; + md->md4.curlen = 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(md4_process, s_md4_compress, md4, 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 md4_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->md4.curlen >= sizeof(md->md4.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->md4.length += md->md4.curlen * 8; + + /* append the '1' bit */ + md->md4.buf[md->md4.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->md4.curlen > 56) { + while (md->md4.curlen < 64) { + md->md4.buf[md->md4.curlen++] = (unsigned char)0; + } + s_md4_compress(md, md->md4.buf); + md->md4.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->md4.curlen < 56) { + md->md4.buf[md->md4.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->md4.length, md->md4.buf+56); + s_md4_compress(md, md->md4.buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->md4.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 md4_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct md4_test_case { + const char *input; + unsigned char hash[16]; + } tests[] = { + { "", + {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, + 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} }, + { "a", + {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, + 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} }, + { "abc", + {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, + 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} }, + { "message digest", + {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, + 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} }, + { "abcdefghijklmnopqrstuvwxyz", + {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, + 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, + 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, + 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} }, + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for(i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + md4_init(&md); + md4_process(&md, (unsigned char *)tests[i].input, (unsigned long)XSTRLEN(tests[i].input)); + md4_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD4", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; + #endif +} + +#endif + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/md5.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/md5.c new file mode 100644 index 0000000..ad404e1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/md5.c @@ -0,0 +1,356 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 ss_md5_compress(hash_state *md, const unsigned char *buf) +#else +static int s_md5_compress(hash_state *md, const 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 s_md5_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_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, s_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; + } + s_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); + s_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)XSTRLEN(tests[i].msg)); + md5_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD5", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd128.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd128.c new file mode 100644 index 0000000..e8f63e1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd128.c @@ -0,0 +1,396 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param rmd128.c + RMD128 Hash function +*/ + +/* Implementation of LTC_RIPEMD-128 based on the source by Antoon Bosselaers, ESAT-COSIC + * + * This source has been radically overhauled to be portable and work within + * the LibTomCrypt API by Tom St Denis + */ + +#ifdef LTC_RIPEMD128 + +const struct ltc_hash_descriptor rmd128_desc = +{ + "rmd128", + 8, + 16, + 64, + + /* OID */ + { 1, 0, 10118, 3, 0, 50 }, + 6, + + &rmd128_init, + &rmd128_process, + &rmd128_done, + &rmd128_test, + NULL +}; + +/* the four basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) + +/* the eight basic operations FF() through III() */ +#define FF(a, b, c, d, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)); + +#define GG(a, b, c, d, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)); + +#define HH(a, b, c, d, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)); + +#define II(a, b, c, d, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)); + +#define FFF(a, b, c, d, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)); + +#define GGG(a, b, c, d, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)); + +#define HHH(a, b, c, d, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)); + +#define III(a, b, c, d, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)); + +#ifdef LTC_CLEAN_STACK +static int ss_rmd128_compress(hash_state *md, const unsigned char *buf) +#else +static int s_rmd128_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = aaa = md->rmd128.state[0]; + bb = bbb = md->rmd128.state[1]; + cc = ccc = md->rmd128.state[2]; + dd = ddd = md->rmd128.state[3]; + + /* round 1 */ + FF(aa, bb, cc, dd, X[ 0], 11); + FF(dd, aa, bb, cc, X[ 1], 14); + FF(cc, dd, aa, bb, X[ 2], 15); + FF(bb, cc, dd, aa, X[ 3], 12); + FF(aa, bb, cc, dd, X[ 4], 5); + FF(dd, aa, bb, cc, X[ 5], 8); + FF(cc, dd, aa, bb, X[ 6], 7); + FF(bb, cc, dd, aa, X[ 7], 9); + FF(aa, bb, cc, dd, X[ 8], 11); + FF(dd, aa, bb, cc, X[ 9], 13); + FF(cc, dd, aa, bb, X[10], 14); + FF(bb, cc, dd, aa, X[11], 15); + FF(aa, bb, cc, dd, X[12], 6); + FF(dd, aa, bb, cc, X[13], 7); + FF(cc, dd, aa, bb, X[14], 9); + FF(bb, cc, dd, aa, X[15], 8); + + /* round 2 */ + GG(aa, bb, cc, dd, X[ 7], 7); + GG(dd, aa, bb, cc, X[ 4], 6); + GG(cc, dd, aa, bb, X[13], 8); + GG(bb, cc, dd, aa, X[ 1], 13); + GG(aa, bb, cc, dd, X[10], 11); + GG(dd, aa, bb, cc, X[ 6], 9); + GG(cc, dd, aa, bb, X[15], 7); + GG(bb, cc, dd, aa, X[ 3], 15); + GG(aa, bb, cc, dd, X[12], 7); + GG(dd, aa, bb, cc, X[ 0], 12); + GG(cc, dd, aa, bb, X[ 9], 15); + GG(bb, cc, dd, aa, X[ 5], 9); + GG(aa, bb, cc, dd, X[ 2], 11); + GG(dd, aa, bb, cc, X[14], 7); + GG(cc, dd, aa, bb, X[11], 13); + GG(bb, cc, dd, aa, X[ 8], 12); + + /* round 3 */ + HH(aa, bb, cc, dd, X[ 3], 11); + HH(dd, aa, bb, cc, X[10], 13); + HH(cc, dd, aa, bb, X[14], 6); + HH(bb, cc, dd, aa, X[ 4], 7); + HH(aa, bb, cc, dd, X[ 9], 14); + HH(dd, aa, bb, cc, X[15], 9); + HH(cc, dd, aa, bb, X[ 8], 13); + HH(bb, cc, dd, aa, X[ 1], 15); + HH(aa, bb, cc, dd, X[ 2], 14); + HH(dd, aa, bb, cc, X[ 7], 8); + HH(cc, dd, aa, bb, X[ 0], 13); + HH(bb, cc, dd, aa, X[ 6], 6); + HH(aa, bb, cc, dd, X[13], 5); + HH(dd, aa, bb, cc, X[11], 12); + HH(cc, dd, aa, bb, X[ 5], 7); + HH(bb, cc, dd, aa, X[12], 5); + + /* round 4 */ + II(aa, bb, cc, dd, X[ 1], 11); + II(dd, aa, bb, cc, X[ 9], 12); + II(cc, dd, aa, bb, X[11], 14); + II(bb, cc, dd, aa, X[10], 15); + II(aa, bb, cc, dd, X[ 0], 14); + II(dd, aa, bb, cc, X[ 8], 15); + II(cc, dd, aa, bb, X[12], 9); + II(bb, cc, dd, aa, X[ 4], 8); + II(aa, bb, cc, dd, X[13], 9); + II(dd, aa, bb, cc, X[ 3], 14); + II(cc, dd, aa, bb, X[ 7], 5); + II(bb, cc, dd, aa, X[15], 6); + II(aa, bb, cc, dd, X[14], 8); + II(dd, aa, bb, cc, X[ 5], 6); + II(cc, dd, aa, bb, X[ 6], 5); + II(bb, cc, dd, aa, X[ 2], 12); + + /* parallel round 1 */ + III(aaa, bbb, ccc, ddd, X[ 5], 8); + III(ddd, aaa, bbb, ccc, X[14], 9); + III(ccc, ddd, aaa, bbb, X[ 7], 9); + III(bbb, ccc, ddd, aaa, X[ 0], 11); + III(aaa, bbb, ccc, ddd, X[ 9], 13); + III(ddd, aaa, bbb, ccc, X[ 2], 15); + III(ccc, ddd, aaa, bbb, X[11], 15); + III(bbb, ccc, ddd, aaa, X[ 4], 5); + III(aaa, bbb, ccc, ddd, X[13], 7); + III(ddd, aaa, bbb, ccc, X[ 6], 7); + III(ccc, ddd, aaa, bbb, X[15], 8); + III(bbb, ccc, ddd, aaa, X[ 8], 11); + III(aaa, bbb, ccc, ddd, X[ 1], 14); + III(ddd, aaa, bbb, ccc, X[10], 14); + III(ccc, ddd, aaa, bbb, X[ 3], 12); + III(bbb, ccc, ddd, aaa, X[12], 6); + + /* parallel round 2 */ + HHH(aaa, bbb, ccc, ddd, X[ 6], 9); + HHH(ddd, aaa, bbb, ccc, X[11], 13); + HHH(ccc, ddd, aaa, bbb, X[ 3], 15); + HHH(bbb, ccc, ddd, aaa, X[ 7], 7); + HHH(aaa, bbb, ccc, ddd, X[ 0], 12); + HHH(ddd, aaa, bbb, ccc, X[13], 8); + HHH(ccc, ddd, aaa, bbb, X[ 5], 9); + HHH(bbb, ccc, ddd, aaa, X[10], 11); + HHH(aaa, bbb, ccc, ddd, X[14], 7); + HHH(ddd, aaa, bbb, ccc, X[15], 7); + HHH(ccc, ddd, aaa, bbb, X[ 8], 12); + HHH(bbb, ccc, ddd, aaa, X[12], 7); + HHH(aaa, bbb, ccc, ddd, X[ 4], 6); + HHH(ddd, aaa, bbb, ccc, X[ 9], 15); + HHH(ccc, ddd, aaa, bbb, X[ 1], 13); + HHH(bbb, ccc, ddd, aaa, X[ 2], 11); + + /* parallel round 3 */ + GGG(aaa, bbb, ccc, ddd, X[15], 9); + GGG(ddd, aaa, bbb, ccc, X[ 5], 7); + GGG(ccc, ddd, aaa, bbb, X[ 1], 15); + GGG(bbb, ccc, ddd, aaa, X[ 3], 11); + GGG(aaa, bbb, ccc, ddd, X[ 7], 8); + GGG(ddd, aaa, bbb, ccc, X[14], 6); + GGG(ccc, ddd, aaa, bbb, X[ 6], 6); + GGG(bbb, ccc, ddd, aaa, X[ 9], 14); + GGG(aaa, bbb, ccc, ddd, X[11], 12); + GGG(ddd, aaa, bbb, ccc, X[ 8], 13); + GGG(ccc, ddd, aaa, bbb, X[12], 5); + GGG(bbb, ccc, ddd, aaa, X[ 2], 14); + GGG(aaa, bbb, ccc, ddd, X[10], 13); + GGG(ddd, aaa, bbb, ccc, X[ 0], 13); + GGG(ccc, ddd, aaa, bbb, X[ 4], 7); + GGG(bbb, ccc, ddd, aaa, X[13], 5); + + /* parallel round 4 */ + FFF(aaa, bbb, ccc, ddd, X[ 8], 15); + FFF(ddd, aaa, bbb, ccc, X[ 6], 5); + FFF(ccc, ddd, aaa, bbb, X[ 4], 8); + FFF(bbb, ccc, ddd, aaa, X[ 1], 11); + FFF(aaa, bbb, ccc, ddd, X[ 3], 14); + FFF(ddd, aaa, bbb, ccc, X[11], 14); + FFF(ccc, ddd, aaa, bbb, X[15], 6); + FFF(bbb, ccc, ddd, aaa, X[ 0], 14); + FFF(aaa, bbb, ccc, ddd, X[ 5], 6); + FFF(ddd, aaa, bbb, ccc, X[12], 9); + FFF(ccc, ddd, aaa, bbb, X[ 2], 12); + FFF(bbb, ccc, ddd, aaa, X[13], 9); + FFF(aaa, bbb, ccc, ddd, X[ 9], 12); + FFF(ddd, aaa, bbb, ccc, X[ 7], 5); + FFF(ccc, ddd, aaa, bbb, X[10], 15); + FFF(bbb, ccc, ddd, aaa, X[14], 8); + + /* combine results */ + ddd += cc + md->rmd128.state[1]; /* final result for MDbuf[0] */ + md->rmd128.state[1] = md->rmd128.state[2] + dd + aaa; + md->rmd128.state[2] = md->rmd128.state[3] + aa + bbb; + md->rmd128.state[3] = md->rmd128.state[0] + bb + ccc; + md->rmd128.state[0] = ddd; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_rmd128_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_rmd128_compress(md, buf); + burn_stack(sizeof(ulong32) * 24 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int rmd128_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->rmd128.state[0] = 0x67452301UL; + md->rmd128.state[1] = 0xefcdab89UL; + md->rmd128.state[2] = 0x98badcfeUL; + md->rmd128.state[3] = 0x10325476UL; + md->rmd128.curlen = 0; + md->rmd128.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(rmd128_process, s_rmd128_compress, rmd128, 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 rmd128_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->rmd128.curlen >= sizeof(md->rmd128.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->rmd128.length += md->rmd128.curlen * 8; + + /* append the '1' bit */ + md->rmd128.buf[md->rmd128.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->rmd128.curlen > 56) { + while (md->rmd128.curlen < 64) { + md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; + } + s_rmd128_compress(md, md->rmd128.buf); + md->rmd128.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->rmd128.curlen < 56) { + md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->rmd128.length, md->rmd128.buf+56); + s_rmd128_compress(md, md->rmd128.buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->rmd128.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 rmd128_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0xcd, 0xf2, 0x62, 0x13, 0xa1, 0x50, 0xdc, 0x3e, + 0xcb, 0x61, 0x0f, 0x18, 0xf6, 0xb3, 0x8b, 0x46 } + }, + { "a", + { 0x86, 0xbe, 0x7a, 0xfa, 0x33, 0x9d, 0x0f, 0xc7, + 0xcf, 0xc7, 0x85, 0xe7, 0x2f, 0x57, 0x8d, 0x33 } + }, + { "abc", + { 0xc1, 0x4a, 0x12, 0x19, 0x9c, 0x66, 0xe4, 0xba, + 0x84, 0x63, 0x6b, 0x0f, 0x69, 0x14, 0x4c, 0x77 } + }, + { "message digest", + { 0x9e, 0x32, 0x7b, 0x3d, 0x6e, 0x52, 0x30, 0x62, + 0xaf, 0xc1, 0x13, 0x2d, 0x7d, 0xf9, 0xd1, 0xb8 } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xfd, 0x2a, 0xa6, 0x07, 0xf7, 0x1d, 0xc8, 0xf5, + 0x10, 0x71, 0x49, 0x22, 0xb3, 0x71, 0x83, 0x4e } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0xe9, 0x59, 0xeb, 0x17, 0x9c, 0x91, 0x1f, + 0xae, 0xa4, 0x62, 0x4c, 0x60, 0xc5, 0xc7, 0x02 } + } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + rmd128_init(&md); + rmd128_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + rmd128_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD128", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd160.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd160.c new file mode 100644 index 0000000..1eba20a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd160.c @@ -0,0 +1,455 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rmd160.c + RMD160 hash function +*/ + +/* Implementation of LTC_RIPEMD-160 based on the source by Antoon Bosselaers, ESAT-COSIC + * + * This source has been radically overhauled to be portable and work within + * the LibTomCrypt API by Tom St Denis + */ + +#ifdef LTC_RIPEMD160 + +const struct ltc_hash_descriptor rmd160_desc = +{ + "rmd160", + 9, + 20, + 64, + + /* OID */ + { 1, 3, 36, 3, 2, 1, }, + 6, + + &rmd160_init, + &rmd160_process, + &rmd160_done, + &rmd160_test, + NULL +}; + +/* the five basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define GG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define HH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define II(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define JJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define FFF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define GGG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define HHH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define III(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define JJJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + +#ifdef LTC_CLEAN_STACK +static int ss_rmd160_compress(hash_state *md, const unsigned char *buf) +#else +static int s_rmd160_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = aaa = md->rmd160.state[0]; + bb = bbb = md->rmd160.state[1]; + cc = ccc = md->rmd160.state[2]; + dd = ddd = md->rmd160.state[3]; + ee = eee = md->rmd160.state[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results */ + ddd += cc + md->rmd160.state[1]; /* final result for md->rmd160.state[0] */ + md->rmd160.state[1] = md->rmd160.state[2] + dd + eee; + md->rmd160.state[2] = md->rmd160.state[3] + ee + aaa; + md->rmd160.state[3] = md->rmd160.state[4] + aa + bbb; + md->rmd160.state[4] = md->rmd160.state[0] + bb + ccc; + md->rmd160.state[0] = ddd; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_rmd160_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_rmd160_compress(md, buf); + burn_stack(sizeof(ulong32) * 26 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int rmd160_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->rmd160.state[0] = 0x67452301UL; + md->rmd160.state[1] = 0xefcdab89UL; + md->rmd160.state[2] = 0x98badcfeUL; + md->rmd160.state[3] = 0x10325476UL; + md->rmd160.state[4] = 0xc3d2e1f0UL; + md->rmd160.curlen = 0; + md->rmd160.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(rmd160_process, s_rmd160_compress, rmd160, 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 rmd160_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->rmd160.curlen >= sizeof(md->rmd160.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->rmd160.length += md->rmd160.curlen * 8; + + /* append the '1' bit */ + md->rmd160.buf[md->rmd160.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->rmd160.curlen > 56) { + while (md->rmd160.curlen < 64) { + md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0; + } + s_rmd160_compress(md, md->rmd160.buf); + md->rmd160.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->rmd160.curlen < 56) { + md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->rmd160.length, md->rmd160.buf+56); + s_rmd160_compress(md, md->rmd160.buf); + + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32L(md->rmd160.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 rmd160_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[20]; + } tests[] = { + { "", + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 } + }, + { "a", + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe } + }, + { "abc", + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc } + }, + { "message digest", + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b } + } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + rmd160_init(&md); + rmd160_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + rmd160_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD160", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd256.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd256.c new file mode 100644 index 0000000..0097198 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd256.c @@ -0,0 +1,420 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param rmd256.c + RLTC_MD256 Hash function +*/ + +#ifdef LTC_RIPEMD256 + +const struct ltc_hash_descriptor rmd256_desc = +{ + "rmd256", + 13, + 32, + 64, + + /* OID */ + { 1, 3, 36, 3, 2, 3 }, + 6, + + &rmd256_init, + &rmd256_process, + &rmd256_done, + &rmd256_test, + NULL +}; + +/* the four basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) + +/* the eight basic operations FF() through III() */ +#define FF(a, b, c, d, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)); + +#define GG(a, b, c, d, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)); + +#define HH(a, b, c, d, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)); + +#define II(a, b, c, d, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)); + +#define FFF(a, b, c, d, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)); + +#define GGG(a, b, c, d, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)); + +#define HHH(a, b, c, d, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)); + +#define III(a, b, c, d, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)); + +#ifdef LTC_CLEAN_STACK +static int ss_rmd256_compress(hash_state *md, const unsigned char *buf) +#else +static int s_rmd256_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,tmp,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = md->rmd256.state[0]; + bb = md->rmd256.state[1]; + cc = md->rmd256.state[2]; + dd = md->rmd256.state[3]; + aaa = md->rmd256.state[4]; + bbb = md->rmd256.state[5]; + ccc = md->rmd256.state[6]; + ddd = md->rmd256.state[7]; + + /* round 1 */ + FF(aa, bb, cc, dd, X[ 0], 11); + FF(dd, aa, bb, cc, X[ 1], 14); + FF(cc, dd, aa, bb, X[ 2], 15); + FF(bb, cc, dd, aa, X[ 3], 12); + FF(aa, bb, cc, dd, X[ 4], 5); + FF(dd, aa, bb, cc, X[ 5], 8); + FF(cc, dd, aa, bb, X[ 6], 7); + FF(bb, cc, dd, aa, X[ 7], 9); + FF(aa, bb, cc, dd, X[ 8], 11); + FF(dd, aa, bb, cc, X[ 9], 13); + FF(cc, dd, aa, bb, X[10], 14); + FF(bb, cc, dd, aa, X[11], 15); + FF(aa, bb, cc, dd, X[12], 6); + FF(dd, aa, bb, cc, X[13], 7); + FF(cc, dd, aa, bb, X[14], 9); + FF(bb, cc, dd, aa, X[15], 8); + + /* parallel round 1 */ + III(aaa, bbb, ccc, ddd, X[ 5], 8); + III(ddd, aaa, bbb, ccc, X[14], 9); + III(ccc, ddd, aaa, bbb, X[ 7], 9); + III(bbb, ccc, ddd, aaa, X[ 0], 11); + III(aaa, bbb, ccc, ddd, X[ 9], 13); + III(ddd, aaa, bbb, ccc, X[ 2], 15); + III(ccc, ddd, aaa, bbb, X[11], 15); + III(bbb, ccc, ddd, aaa, X[ 4], 5); + III(aaa, bbb, ccc, ddd, X[13], 7); + III(ddd, aaa, bbb, ccc, X[ 6], 7); + III(ccc, ddd, aaa, bbb, X[15], 8); + III(bbb, ccc, ddd, aaa, X[ 8], 11); + III(aaa, bbb, ccc, ddd, X[ 1], 14); + III(ddd, aaa, bbb, ccc, X[10], 14); + III(ccc, ddd, aaa, bbb, X[ 3], 12); + III(bbb, ccc, ddd, aaa, X[12], 6); + + tmp = aa; aa = aaa; aaa = tmp; + + /* round 2 */ + GG(aa, bb, cc, dd, X[ 7], 7); + GG(dd, aa, bb, cc, X[ 4], 6); + GG(cc, dd, aa, bb, X[13], 8); + GG(bb, cc, dd, aa, X[ 1], 13); + GG(aa, bb, cc, dd, X[10], 11); + GG(dd, aa, bb, cc, X[ 6], 9); + GG(cc, dd, aa, bb, X[15], 7); + GG(bb, cc, dd, aa, X[ 3], 15); + GG(aa, bb, cc, dd, X[12], 7); + GG(dd, aa, bb, cc, X[ 0], 12); + GG(cc, dd, aa, bb, X[ 9], 15); + GG(bb, cc, dd, aa, X[ 5], 9); + GG(aa, bb, cc, dd, X[ 2], 11); + GG(dd, aa, bb, cc, X[14], 7); + GG(cc, dd, aa, bb, X[11], 13); + GG(bb, cc, dd, aa, X[ 8], 12); + + /* parallel round 2 */ + HHH(aaa, bbb, ccc, ddd, X[ 6], 9); + HHH(ddd, aaa, bbb, ccc, X[11], 13); + HHH(ccc, ddd, aaa, bbb, X[ 3], 15); + HHH(bbb, ccc, ddd, aaa, X[ 7], 7); + HHH(aaa, bbb, ccc, ddd, X[ 0], 12); + HHH(ddd, aaa, bbb, ccc, X[13], 8); + HHH(ccc, ddd, aaa, bbb, X[ 5], 9); + HHH(bbb, ccc, ddd, aaa, X[10], 11); + HHH(aaa, bbb, ccc, ddd, X[14], 7); + HHH(ddd, aaa, bbb, ccc, X[15], 7); + HHH(ccc, ddd, aaa, bbb, X[ 8], 12); + HHH(bbb, ccc, ddd, aaa, X[12], 7); + HHH(aaa, bbb, ccc, ddd, X[ 4], 6); + HHH(ddd, aaa, bbb, ccc, X[ 9], 15); + HHH(ccc, ddd, aaa, bbb, X[ 1], 13); + HHH(bbb, ccc, ddd, aaa, X[ 2], 11); + + tmp = bb; bb = bbb; bbb = tmp; + + /* round 3 */ + HH(aa, bb, cc, dd, X[ 3], 11); + HH(dd, aa, bb, cc, X[10], 13); + HH(cc, dd, aa, bb, X[14], 6); + HH(bb, cc, dd, aa, X[ 4], 7); + HH(aa, bb, cc, dd, X[ 9], 14); + HH(dd, aa, bb, cc, X[15], 9); + HH(cc, dd, aa, bb, X[ 8], 13); + HH(bb, cc, dd, aa, X[ 1], 15); + HH(aa, bb, cc, dd, X[ 2], 14); + HH(dd, aa, bb, cc, X[ 7], 8); + HH(cc, dd, aa, bb, X[ 0], 13); + HH(bb, cc, dd, aa, X[ 6], 6); + HH(aa, bb, cc, dd, X[13], 5); + HH(dd, aa, bb, cc, X[11], 12); + HH(cc, dd, aa, bb, X[ 5], 7); + HH(bb, cc, dd, aa, X[12], 5); + + /* parallel round 3 */ + GGG(aaa, bbb, ccc, ddd, X[15], 9); + GGG(ddd, aaa, bbb, ccc, X[ 5], 7); + GGG(ccc, ddd, aaa, bbb, X[ 1], 15); + GGG(bbb, ccc, ddd, aaa, X[ 3], 11); + GGG(aaa, bbb, ccc, ddd, X[ 7], 8); + GGG(ddd, aaa, bbb, ccc, X[14], 6); + GGG(ccc, ddd, aaa, bbb, X[ 6], 6); + GGG(bbb, ccc, ddd, aaa, X[ 9], 14); + GGG(aaa, bbb, ccc, ddd, X[11], 12); + GGG(ddd, aaa, bbb, ccc, X[ 8], 13); + GGG(ccc, ddd, aaa, bbb, X[12], 5); + GGG(bbb, ccc, ddd, aaa, X[ 2], 14); + GGG(aaa, bbb, ccc, ddd, X[10], 13); + GGG(ddd, aaa, bbb, ccc, X[ 0], 13); + GGG(ccc, ddd, aaa, bbb, X[ 4], 7); + GGG(bbb, ccc, ddd, aaa, X[13], 5); + + tmp = cc; cc = ccc; ccc = tmp; + + /* round 4 */ + II(aa, bb, cc, dd, X[ 1], 11); + II(dd, aa, bb, cc, X[ 9], 12); + II(cc, dd, aa, bb, X[11], 14); + II(bb, cc, dd, aa, X[10], 15); + II(aa, bb, cc, dd, X[ 0], 14); + II(dd, aa, bb, cc, X[ 8], 15); + II(cc, dd, aa, bb, X[12], 9); + II(bb, cc, dd, aa, X[ 4], 8); + II(aa, bb, cc, dd, X[13], 9); + II(dd, aa, bb, cc, X[ 3], 14); + II(cc, dd, aa, bb, X[ 7], 5); + II(bb, cc, dd, aa, X[15], 6); + II(aa, bb, cc, dd, X[14], 8); + II(dd, aa, bb, cc, X[ 5], 6); + II(cc, dd, aa, bb, X[ 6], 5); + II(bb, cc, dd, aa, X[ 2], 12); + + /* parallel round 4 */ + FFF(aaa, bbb, ccc, ddd, X[ 8], 15); + FFF(ddd, aaa, bbb, ccc, X[ 6], 5); + FFF(ccc, ddd, aaa, bbb, X[ 4], 8); + FFF(bbb, ccc, ddd, aaa, X[ 1], 11); + FFF(aaa, bbb, ccc, ddd, X[ 3], 14); + FFF(ddd, aaa, bbb, ccc, X[11], 14); + FFF(ccc, ddd, aaa, bbb, X[15], 6); + FFF(bbb, ccc, ddd, aaa, X[ 0], 14); + FFF(aaa, bbb, ccc, ddd, X[ 5], 6); + FFF(ddd, aaa, bbb, ccc, X[12], 9); + FFF(ccc, ddd, aaa, bbb, X[ 2], 12); + FFF(bbb, ccc, ddd, aaa, X[13], 9); + FFF(aaa, bbb, ccc, ddd, X[ 9], 12); + FFF(ddd, aaa, bbb, ccc, X[ 7], 5); + FFF(ccc, ddd, aaa, bbb, X[10], 15); + FFF(bbb, ccc, ddd, aaa, X[14], 8); + + tmp = dd; dd = ddd; ddd = tmp; + + /* combine results */ + md->rmd256.state[0] += aa; + md->rmd256.state[1] += bb; + md->rmd256.state[2] += cc; + md->rmd256.state[3] += dd; + md->rmd256.state[4] += aaa; + md->rmd256.state[5] += bbb; + md->rmd256.state[6] += ccc; + md->rmd256.state[7] += ddd; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_rmd256_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_rmd256_compress(md, buf); + burn_stack(sizeof(ulong32) * 25 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int rmd256_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->rmd256.state[0] = 0x67452301UL; + md->rmd256.state[1] = 0xefcdab89UL; + md->rmd256.state[2] = 0x98badcfeUL; + md->rmd256.state[3] = 0x10325476UL; + md->rmd256.state[4] = 0x76543210UL; + md->rmd256.state[5] = 0xfedcba98UL; + md->rmd256.state[6] = 0x89abcdefUL; + md->rmd256.state[7] = 0x01234567UL; + md->rmd256.curlen = 0; + md->rmd256.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(rmd256_process, s_rmd256_compress, rmd256, 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 rmd256_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->rmd256.curlen >= sizeof(md->rmd256.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->rmd256.length += md->rmd256.curlen * 8; + + /* append the '1' bit */ + md->rmd256.buf[md->rmd256.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->rmd256.curlen > 56) { + while (md->rmd256.curlen < 64) { + md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0; + } + s_rmd256_compress(md, md->rmd256.buf); + md->rmd256.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->rmd256.curlen < 56) { + md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->rmd256.length, md->rmd256.buf+56); + s_rmd256_compress(md, md->rmd256.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32L(md->rmd256.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 rmd256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "", + { 0x02, 0xba, 0x4c, 0x4e, 0x5f, 0x8e, 0xcd, 0x18, + 0x77, 0xfc, 0x52, 0xd6, 0x4d, 0x30, 0xe3, 0x7a, + 0x2d, 0x97, 0x74, 0xfb, 0x1e, 0x5d, 0x02, 0x63, + 0x80, 0xae, 0x01, 0x68, 0xe3, 0xc5, 0x52, 0x2d } + }, + { "a", + { 0xf9, 0x33, 0x3e, 0x45, 0xd8, 0x57, 0xf5, 0xd9, + 0x0a, 0x91, 0xba, 0xb7, 0x0a, 0x1e, 0xba, 0x0c, + 0xfb, 0x1b, 0xe4, 0xb0, 0x78, 0x3c, 0x9a, 0xcf, + 0xcd, 0x88, 0x3a, 0x91, 0x34, 0x69, 0x29, 0x25 } + }, + { "abc", + { 0xaf, 0xbd, 0x6e, 0x22, 0x8b, 0x9d, 0x8c, 0xbb, + 0xce, 0xf5, 0xca, 0x2d, 0x03, 0xe6, 0xdb, 0xa1, + 0x0a, 0xc0, 0xbc, 0x7d, 0xcb, 0xe4, 0x68, 0x0e, + 0x1e, 0x42, 0xd2, 0xe9, 0x75, 0x45, 0x9b, 0x65 } + }, + { "message digest", + { 0x87, 0xe9, 0x71, 0x75, 0x9a, 0x1c, 0xe4, 0x7a, + 0x51, 0x4d, 0x5c, 0x91, 0x4c, 0x39, 0x2c, 0x90, + 0x18, 0xc7, 0xc4, 0x6b, 0xc1, 0x44, 0x65, 0x55, + 0x4a, 0xfc, 0xdf, 0x54, 0xa5, 0x07, 0x0c, 0x0e } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0x64, 0x9d, 0x30, 0x34, 0x75, 0x1e, 0xa2, 0x16, + 0x77, 0x6b, 0xf9, 0xa1, 0x8a, 0xcc, 0x81, 0xbc, + 0x78, 0x96, 0x11, 0x8a, 0x51, 0x97, 0x96, 0x87, + 0x82, 0xdd, 0x1f, 0xd9, 0x7d, 0x8d, 0x51, 0x33 } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0x57, 0x40, 0xa4, 0x08, 0xac, 0x16, 0xb7, 0x20, + 0xb8, 0x44, 0x24, 0xae, 0x93, 0x1c, 0xbb, 0x1f, + 0xe3, 0x63, 0xd1, 0xd0, 0xbf, 0x40, 0x17, 0xf1, + 0xa8, 0x9f, 0x7e, 0xa6, 0xde, 0x77, 0xa0, 0xb8 } + } + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + rmd256_init(&md); + rmd256_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + rmd256_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD256", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd320.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd320.c new file mode 100644 index 0000000..0021d67 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/rmd320.c @@ -0,0 +1,485 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rmd320.c + RMD320 hash function +*/ + +#ifdef LTC_RIPEMD320 + +const struct ltc_hash_descriptor rmd320_desc = +{ + "rmd320", + 14, + 40, + 64, + + /* OID ... does not exist + * http://oid-info.com/get/1.3.36.3.2 */ + { 0 }, + 0, + + &rmd320_init, + &rmd320_process, + &rmd320_done, + &rmd320_test, + NULL +}; + +/* the five basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define GG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define HH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define II(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define JJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define FFF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define GGG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define HHH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define III(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define JJJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + +#ifdef LTC_CLEAN_STACK +static int ss_rmd320_compress(hash_state *md, const unsigned char *buf) +#else +static int s_rmd320_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,tmp,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = md->rmd320.state[0]; + bb = md->rmd320.state[1]; + cc = md->rmd320.state[2]; + dd = md->rmd320.state[3]; + ee = md->rmd320.state[4]; + aaa = md->rmd320.state[5]; + bbb = md->rmd320.state[6]; + ccc = md->rmd320.state[7]; + ddd = md->rmd320.state[8]; + eee = md->rmd320.state[9]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + tmp = aa; aa = aaa; aaa = tmp; + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + tmp = bb; bb = bbb; bbb = tmp; + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + tmp = cc; cc = ccc; ccc = tmp; + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + tmp = dd; dd = ddd; ddd = tmp; + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + tmp = ee; ee = eee; eee = tmp; + + /* combine results */ + md->rmd320.state[0] += aa; + md->rmd320.state[1] += bb; + md->rmd320.state[2] += cc; + md->rmd320.state[3] += dd; + md->rmd320.state[4] += ee; + md->rmd320.state[5] += aaa; + md->rmd320.state[6] += bbb; + md->rmd320.state[7] += ccc; + md->rmd320.state[8] += ddd; + md->rmd320.state[9] += eee; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_rmd320_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_rmd320_compress(md, buf); + burn_stack(sizeof(ulong32) * 27 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int rmd320_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->rmd320.state[0] = 0x67452301UL; + md->rmd320.state[1] = 0xefcdab89UL; + md->rmd320.state[2] = 0x98badcfeUL; + md->rmd320.state[3] = 0x10325476UL; + md->rmd320.state[4] = 0xc3d2e1f0UL; + md->rmd320.state[5] = 0x76543210UL; + md->rmd320.state[6] = 0xfedcba98UL; + md->rmd320.state[7] = 0x89abcdefUL; + md->rmd320.state[8] = 0x01234567UL; + md->rmd320.state[9] = 0x3c2d1e0fUL; + md->rmd320.curlen = 0; + md->rmd320.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(rmd320_process, s_rmd320_compress, rmd320, 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 rmd320_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->rmd320.curlen >= sizeof(md->rmd320.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->rmd320.length += md->rmd320.curlen * 8; + + /* append the '1' bit */ + md->rmd320.buf[md->rmd320.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->rmd320.curlen > 56) { + while (md->rmd320.curlen < 64) { + md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0; + } + s_rmd320_compress(md, md->rmd320.buf); + md->rmd320.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->rmd320.curlen < 56) { + md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->rmd320.length, md->rmd320.buf+56); + s_rmd320_compress(md, md->rmd320.buf); + + /* copy output */ + for (i = 0; i < 10; i++) { + STORE32L(md->rmd320.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 rmd320_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[40]; + } tests[] = { + { "", + { 0x22, 0xd6, 0x5d, 0x56, 0x61, 0x53, 0x6c, 0xdc, 0x75, 0xc1, + 0xfd, 0xf5, 0xc6, 0xde, 0x7b, 0x41, 0xb9, 0xf2, 0x73, 0x25, + 0xeb, 0xc6, 0x1e, 0x85, 0x57, 0x17, 0x7d, 0x70, 0x5a, 0x0e, + 0xc8, 0x80, 0x15, 0x1c, 0x3a, 0x32, 0xa0, 0x08, 0x99, 0xb8 } + }, + { "a", + { 0xce, 0x78, 0x85, 0x06, 0x38, 0xf9, 0x26, 0x58, 0xa5, 0xa5, + 0x85, 0x09, 0x75, 0x79, 0x92, 0x6d, 0xda, 0x66, 0x7a, 0x57, + 0x16, 0x56, 0x2c, 0xfc, 0xf6, 0xfb, 0xe7, 0x7f, 0x63, 0x54, + 0x2f, 0x99, 0xb0, 0x47, 0x05, 0xd6, 0x97, 0x0d, 0xff, 0x5d } + }, + { "abc", + { 0xde, 0x4c, 0x01, 0xb3, 0x05, 0x4f, 0x89, 0x30, 0xa7, 0x9d, + 0x09, 0xae, 0x73, 0x8e, 0x92, 0x30, 0x1e, 0x5a, 0x17, 0x08, + 0x5b, 0xef, 0xfd, 0xc1, 0xb8, 0xd1, 0x16, 0x71, 0x3e, 0x74, + 0xf8, 0x2f, 0xa9, 0x42, 0xd6, 0x4c, 0xdb, 0xc4, 0x68, 0x2d } + }, + { "message digest", + { 0x3a, 0x8e, 0x28, 0x50, 0x2e, 0xd4, 0x5d, 0x42, 0x2f, 0x68, + 0x84, 0x4f, 0x9d, 0xd3, 0x16, 0xe7, 0xb9, 0x85, 0x33, 0xfa, + 0x3f, 0x2a, 0x91, 0xd2, 0x9f, 0x84, 0xd4, 0x25, 0xc8, 0x8d, + 0x6b, 0x4e, 0xff, 0x72, 0x7d, 0xf6, 0x6a, 0x7c, 0x01, 0x97 } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xca, 0xbd, 0xb1, 0x81, 0x0b, 0x92, 0x47, 0x0a, 0x20, 0x93, + 0xaa, 0x6b, 0xce, 0x05, 0x95, 0x2c, 0x28, 0x34, 0x8c, 0xf4, + 0x3f, 0xf6, 0x08, 0x41, 0x97, 0x51, 0x66, 0xbb, 0x40, 0xed, + 0x23, 0x40, 0x04, 0xb8, 0x82, 0x44, 0x63, 0xe6, 0xb0, 0x09 } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0xd0, 0x34, 0xa7, 0x95, 0x0c, 0xf7, 0x22, 0x02, 0x1b, 0xa4, + 0xb8, 0x4d, 0xf7, 0x69, 0xa5, 0xde, 0x20, 0x60, 0xe2, 0x59, + 0xdf, 0x4c, 0x9b, 0xb4, 0xa4, 0x26, 0x8c, 0x0e, 0x93, 0x5b, + 0xbc, 0x74, 0x70, 0xa9, 0x69, 0xc9, 0xd0, 0x72, 0xa1, 0xac } + } + }; + + int i; + unsigned char tmp[40]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + rmd320_init(&md); + rmd320_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + rmd320_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD320", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha1.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha1.c new file mode 100644 index 0000000..40709db --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha1.c @@ -0,0 +1,276 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 ss_sha1_compress(hash_state *md, const unsigned char *buf) +#else +static int s_sha1_compress(hash_state *md, const 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 s_sha1_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_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, s_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; + } + s_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); + s_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)XSTRLEN(tests[i].msg)); + sha1_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA1", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha224.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha224.c new file mode 100644 index 0000000..1e2f295 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha224.c @@ -0,0 +1,119 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @param sha224.c + LTC_SHA-224 new NIST standard based off of LTC_SHA-256 truncated to 224 bits (Tom St Denis) +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_SHA224) && defined(LTC_SHA256) + +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)XSTRLEN(tests[i].msg)); + sha224_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA224", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /* defined(LTC_SHA224) && defined(LTC_SHA256) */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha256.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha256.c new file mode 100644 index 0000000..ff20068 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha256.c @@ -0,0 +1,322 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 ss_sha256_compress(hash_state * md, const unsigned char *buf) +#else +static int s_sha256_compress(hash_state * md, const 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); +#endif +#undef RND + + /* 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 s_sha256_compress(hash_state * md, const unsigned char *buf) +{ + int err; + err = ss_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,s_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; + } + s_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); + s_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)XSTRLEN(tests[i].msg)); + sha256_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA256", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha384.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha384.c new file mode 100644 index 0000000..cb3391a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha384.c @@ -0,0 +1,124 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @param sha384.c + LTC_SHA384 hash included in sha512.c, Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_SHA384) && defined(LTC_SHA512) + +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)XSTRLEN(tests[i].msg)); + sha384_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA384", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512.c new file mode 100644 index 0000000..ef3a8c8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512.c @@ -0,0 +1,303 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 ss_sha512_compress(hash_state * md, const unsigned char *buf) +#else +static int s_sha512_compress(hash_state * md, const 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 s_sha512_compress(hash_state * md, const unsigned char *buf) +{ + int err; + err = ss_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, s_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; + } + s_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); + s_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)XSTRLEN(tests[i].msg)); + sha512_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c new file mode 100644 index 0000000..861852e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @param sha512_224.c + SHA512/224 hash included in sha512.c +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_SHA512_224) && defined(LTC_SHA512) + +const struct ltc_hash_descriptor sha512_224_desc = +{ + "sha512-224", + 15, + 28, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 5, }, + 9, + + &sha512_224_init, + &sha512_process, + &sha512_224_done, + &sha512_224_test, + NULL +}; + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha512_224_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0x8C3D37C819544DA2); + md->sha512.state[1] = CONST64(0x73E1996689DCD4D6); + md->sha512.state[2] = CONST64(0x1DFAB7AE32FF9C82); + md->sha512.state[3] = CONST64(0x679DD514582F9FCF); + md->sha512.state[4] = CONST64(0x0F6D2B697BD44DA8); + md->sha512.state[5] = CONST64(0x77E36F7304C48942); + md->sha512.state[6] = CONST64(0x3F9D85A86A1D36C8); + md->sha512.state[7] = CONST64(0x1112E6AD91D692A1); + 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 sha512_224_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, 28); +#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 sha512_224_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[28]; + } tests[] = { + { "abc", + { 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54, + 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2, + 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4, + 0x3E, 0x89, 0x24, 0xAA } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23, + 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33, + 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72, + 0x68, 0x67, 0x4A, 0xF9 } + }, + }; + + int i; + unsigned char tmp[28]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha512_224_init(&md); + sha512_224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha512_224_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-224", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c new file mode 100644 index 0000000..1f04154 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @param sha512_256.c + SHA512/256 hash included in sha512.c +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_SHA512_256) && defined(LTC_SHA512) + +const struct ltc_hash_descriptor sha512_256_desc = +{ + "sha512-256", + 16, + 32, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 6, }, + 9, + + &sha512_256_init, + &sha512_process, + &sha512_256_done, + &sha512_256_test, + NULL +}; + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha512_256_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0x22312194FC2BF72C); + md->sha512.state[1] = CONST64(0x9F555FA3C84C64C2); + md->sha512.state[2] = CONST64(0x2393B86B6F53B151); + md->sha512.state[3] = CONST64(0x963877195940EABD); + md->sha512.state[4] = CONST64(0x96283EE2A88EFFE3); + md->sha512.state[5] = CONST64(0xBE5E1E2553863992); + md->sha512.state[6] = CONST64(0x2B0199FC2C85B8AA); + md->sha512.state[7] = CONST64(0x0EB72DDC81C52CA2); + 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 sha512_256_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, 32); +#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 sha512_256_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "abc", + { 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, + 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB, + 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, + 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, + 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE, + 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, + 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A } + }, + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha512_256_init(&md); + sha512_256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha512_256_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-265", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sub.mk new file mode 100644 index 0000000..2a497be --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha2/sub.mk @@ -0,0 +1,13 @@ +srcs-$(_CFG_CORE_LTC_SHA224) += sha224.c + +ifneq ($(_CFG_CORE_LTC_SHA256_ACCEL),y) +srcs-$(_CFG_CORE_LTC_SHA256_DESC) += sha256.c +endif + +srcs-$(_CFG_CORE_LTC_SHA384_DESC) += sha384.c + +ifneq ($(_CFG_CORE_LTC_SHA512_ACCEL),y) +srcs-$(_CFG_CORE_LTC_SHA512_DESC) += sha512.c +endif + +srcs-$(_CFG_CORE_LTC_SHA512_256) += sha512_256.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3.c new file mode 100644 index 0000000..4758e34 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3.c @@ -0,0 +1,378 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on https://github.com/brainhub/SHA3IUF (public domain) */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SHA3 + +const struct ltc_hash_descriptor sha3_224_desc = +{ + "sha3-224", /* name of hash */ + 17, /* internal ID */ + 28, /* Size of digest in octets */ + 144, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_224_init, + &sha3_process, + &sha3_done, + &sha3_224_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_256_desc = +{ + "sha3-256", /* name of hash */ + 18, /* internal ID */ + 32, /* Size of digest in octets */ + 136, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_256_init, + &sha3_process, + &sha3_done, + &sha3_256_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_384_desc = +{ + "sha3-384", /* name of hash */ + 19, /* internal ID */ + 48, /* Size of digest in octets */ + 104, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_384_init, + &sha3_process, + &sha3_done, + &sha3_384_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_512_desc = +{ + "sha3-512", /* name of hash */ + 20, /* internal ID */ + 64, /* Size of digest in octets */ + 72, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_512_init, + &sha3_process, + &sha3_done, + &sha3_512_test, + NULL +}; +#endif + +#ifdef LTC_KECCAK +const struct ltc_hash_descriptor keccak_224_desc = +{ + "keccak224", /* name of hash */ + 29, /* internal ID */ + 28, /* Size of digest in octets */ + 144, /* Input block size in octets */ + { 0 }, 0, /* no ASN.1 OID */ + &sha3_224_init, + &sha3_process, + &keccak_done, + &keccak_224_test, + NULL +}; + +const struct ltc_hash_descriptor keccak_256_desc = +{ + "keccak256", /* name of hash */ + 30, /* internal ID */ + 32, /* Size of digest in octets */ + 136, /* Input block size in octets */ + { 0 }, 0, /* no ASN.1 OID */ + &sha3_256_init, + &sha3_process, + &keccak_done, + &keccak_256_test, + NULL +}; + +const struct ltc_hash_descriptor keccak_384_desc = +{ + "keccak384", /* name of hash */ + 31, /* internal ID */ + 48, /* Size of digest in octets */ + 104, /* Input block size in octets */ + { 0 }, 0, /* no ASN.1 OID */ + &sha3_384_init, + &sha3_process, + &keccak_done, + &keccak_384_test, + NULL +}; + +const struct ltc_hash_descriptor keccak_512_desc = +{ + "keccak512", /* name of hash */ + 32, /* internal ID */ + 64, /* Size of digest in octets */ + 72, /* Input block size in octets */ + { 0 }, 0, /* no ASN.1 OID */ + &sha3_512_init, + &sha3_process, + &keccak_done, + &keccak_512_test, + NULL +}; +#endif + +#if defined(LTC_SHA3) || defined(LTC_KECCAK) + +#define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */ +#define SHA3_KECCAK_ROUNDS 24 + +static const ulong64 s_keccakf_rndc[24] = { + CONST64(0x0000000000000001), CONST64(0x0000000000008082), + CONST64(0x800000000000808a), CONST64(0x8000000080008000), + CONST64(0x000000000000808b), CONST64(0x0000000080000001), + CONST64(0x8000000080008081), CONST64(0x8000000000008009), + CONST64(0x000000000000008a), CONST64(0x0000000000000088), + CONST64(0x0000000080008009), CONST64(0x000000008000000a), + CONST64(0x000000008000808b), CONST64(0x800000000000008b), + CONST64(0x8000000000008089), CONST64(0x8000000000008003), + CONST64(0x8000000000008002), CONST64(0x8000000000000080), + CONST64(0x000000000000800a), CONST64(0x800000008000000a), + CONST64(0x8000000080008081), CONST64(0x8000000000008080), + CONST64(0x0000000080000001), CONST64(0x8000000080008008) +}; + +static const unsigned s_keccakf_rotc[24] = { + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 +}; + +static const unsigned s_keccakf_piln[24] = { + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 +}; + +static void s_keccakf(ulong64 s[25]) +{ + int i, j, round; + ulong64 t, bc[5]; + + for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) { + /* Theta */ + for(i = 0; i < 5; i++) { + bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; + } + for(i = 0; i < 5; i++) { + t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1); + for(j = 0; j < 25; j += 5) { + s[j + i] ^= t; + } + } + /* Rho Pi */ + t = s[1]; + for(i = 0; i < 24; i++) { + j = s_keccakf_piln[i]; + bc[0] = s[j]; + s[j] = ROL64(t, s_keccakf_rotc[i]); + t = bc[0]; + } + /* Chi */ + for(j = 0; j < 25; j += 5) { + for(i = 0; i < 5; i++) { + bc[i] = s[j + i]; + } + for(i = 0; i < 5; i++) { + s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; + } + } + /* Iota */ + s[0] ^= s_keccakf_rndc[round]; + } +} + +static LTC_INLINE int ss_done(hash_state *md, unsigned char *hash, ulong64 pad) +{ + unsigned i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(hash != NULL); + + md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8))); + md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000); + s_keccakf(md->sha3.s); + + /* store sha3.s[] as little-endian bytes into sha3.sb */ + for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { + STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); + } + + XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4); + return CRYPT_OK; +} + +/* Public Inteface */ + +int sha3_224_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_256_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_384_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_512_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +#ifdef LTC_SHA3 +int sha3_shake_init(hash_state *md, int num) +{ + LTC_ARGCHK(md != NULL); + if (num != 128 && num != 256) return CRYPT_INVALID_ARG; + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64))); + return CRYPT_OK; +} +#endif + +int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + /* 0...7 -- how much is needed to have a word */ + unsigned old_tail = (8 - md->sha3.byte_index) & 7; + + unsigned long words; + unsigned tail; + unsigned long i; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + if(inlen < old_tail) { /* have no complete word or haven't started the word yet */ + while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); + return CRYPT_OK; + } + + if(old_tail) { /* will have one word to process */ + inlen -= old_tail; + while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); + /* now ready to add saved to the sponge */ + md->sha3.s[md->sha3.word_index] ^= md->sha3.saved; + md->sha3.byte_index = 0; + md->sha3.saved = 0; + if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) { + s_keccakf(md->sha3.s); + md->sha3.word_index = 0; + } + } + + /* now work in full words directly from input */ + words = inlen / sizeof(ulong64); + tail = inlen - words * sizeof(ulong64); + + for(i = 0; i < words; i++, in += sizeof(ulong64)) { + ulong64 t; + LOAD64L(t, in); + md->sha3.s[md->sha3.word_index] ^= t; + if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) { + s_keccakf(md->sha3.s); + md->sha3.word_index = 0; + } + } + + /* finally, save the partial word */ + while (tail--) { + md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); + } + return CRYPT_OK; +} + +#ifdef LTC_SHA3 +int sha3_done(hash_state *md, unsigned char *out) +{ + return ss_done(md, out, CONST64(0x06)); +} +#endif + +#ifdef LTC_KECCAK +int keccak_done(hash_state *md, unsigned char *out) +{ + return ss_done(md, out, CONST64(0x01)); +} +#endif + +#ifdef LTC_SHA3 +int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen) +{ + /* IMPORTANT NOTE: sha3_shake_done can be called many times */ + unsigned long idx; + unsigned i; + + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (!md->sha3.xof_flag) { + /* shake_xof operation must be done only once */ + md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8))); + md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000); + s_keccakf(md->sha3.s); + /* store sha3.s[] as little-endian bytes into sha3.sb */ + for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { + STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); + } + md->sha3.byte_index = 0; + md->sha3.xof_flag = 1; + } + + for (idx = 0; idx < outlen; idx++) { + if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) { + s_keccakf(md->sha3.s); + /* store sha3.s[] as little-endian bytes into sha3.sb */ + for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { + STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); + } + md->sha3.byte_index = 0; + } + out[idx] = md->sha3.sb[md->sha3.byte_index++]; + } + return CRYPT_OK; +} + +int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen) +{ + hash_state md; + int err; + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err; + return CRYPT_OK; +} +#endif + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3_test.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3_test.c new file mode 100644 index 0000000..95fcfcb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sha3_test.c @@ -0,0 +1,719 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on https://github.com/brainhub/SHA3IUF (public domain) */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SHA3 + +int sha3_224_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[224 / 8]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + + const unsigned char sha3_224_empty[224 / 8] = { + 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, + 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, + 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, + 0x5b, 0x5a, 0x6b, 0xc7 + }; + + const unsigned char sha3_224_0xa3_200_times[224 / 8] = { + 0x93, 0x76, 0x81, 0x6a, 0xba, 0x50, 0x3f, 0x72, + 0xf9, 0x6c, 0xe7, 0xeb, 0x65, 0xac, 0x09, 0x5d, + 0xee, 0xe3, 0xbe, 0x4b, 0xf9, 0xbb, 0xc2, 0xa1, + 0xcb, 0x7e, 0x11, 0xe0 + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHA3-224 on an empty buffer */ + sha3_224_init(&c); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_224_empty, sizeof(sha3_224_empty), "SHA3-224", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-224 in two steps. [FIPS 202] */ + sha3_224_init(&c); + sha3_process(&c, buf, sizeof(buf) / 2); + sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-224 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_224_init(&c); + while (i--) { + sha3_process(&c, &c1, 1); + } + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int sha3_256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[256 / 8]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + + const unsigned char sha3_256_empty[256 / 8] = { + 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, + 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, + 0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, + 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a + }; + const unsigned char sha3_256_0xa3_200_times[256 / 8] = { + 0x79, 0xf3, 0x8a, 0xde, 0xc5, 0xc2, 0x03, 0x07, + 0xa9, 0x8e, 0xf7, 0x6e, 0x83, 0x24, 0xaf, 0xbf, + 0xd4, 0x6c, 0xfd, 0x81, 0xb2, 0x2e, 0x39, 0x73, + 0xc6, 0x5f, 0xa1, 0xbd, 0x9d, 0xe3, 0x17, 0x87 + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHA3-256 on an empty buffer */ + sha3_256_init(&c); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_256_empty, sizeof(sha3_256_empty), "SHA3-256", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-256 as a single buffer. [FIPS 202] */ + sha3_256_init(&c); + sha3_process(&c, buf, sizeof(buf)); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-256 in two steps. [FIPS 202] */ + sha3_256_init(&c); + sha3_process(&c, buf, sizeof(buf) / 2); + sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-256 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_256_init(&c); + while (i--) { + sha3_process(&c, &c1, 1); + } + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 3)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-256 byte-by-byte: 135 bytes. Input from [Keccak]. Output + * matched with sha3sum. */ + sha3_256_init(&c); + sha3_process(&c, (unsigned char*) + "\xb7\x71\xd5\xce\xf5\xd1\xa4\x1a" + "\x93\xd1\x56\x43\xd7\x18\x1d\x2a" + "\x2e\xf0\xa8\xe8\x4d\x91\x81\x2f" + "\x20\xed\x21\xf1\x47\xbe\xf7\x32" + "\xbf\x3a\x60\xef\x40\x67\xc3\x73" + "\x4b\x85\xbc\x8c\xd4\x71\x78\x0f" + "\x10\xdc\x9e\x82\x91\xb5\x83\x39" + "\xa6\x77\xb9\x60\x21\x8f\x71\xe7" + "\x93\xf2\x79\x7a\xea\x34\x94\x06" + "\x51\x28\x29\x06\x5d\x37\xbb\x55" + "\xea\x79\x6f\xa4\xf5\x6f\xd8\x89" + "\x6b\x49\xb2\xcd\x19\xb4\x32\x15" + "\xad\x96\x7c\x71\x2b\x24\xe5\x03" + "\x2d\x06\x52\x32\xe0\x2c\x12\x74" + "\x09\xd2\xed\x41\x46\xb9\xd7\x5d" + "\x76\x3d\x52\xdb\x98\xd9\x49\xd3" + "\xb0\xfe\xd6\xa8\x05\x2f\xbb", 1080 / 8); + sha3_done(&c, hash); + if(compare_testvector(hash, sizeof(hash), + "\xa1\x9e\xee\x92\xbb\x20\x97\xb6" + "\x4e\x82\x3d\x59\x77\x98\xaa\x18" + "\xbe\x9b\x7c\x73\x6b\x80\x59\xab" + "\xfd\x67\x79\xac\x35\xac\x81\xb5", 256 / 8, "SHA3-256", 4)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int sha3_384_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[384 / 8]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + + const unsigned char sha3_384_0xa3_200_times[384 / 8] = { + 0x18, 0x81, 0xde, 0x2c, 0xa7, 0xe4, 0x1e, 0xf9, + 0x5d, 0xc4, 0x73, 0x2b, 0x8f, 0x5f, 0x00, 0x2b, + 0x18, 0x9c, 0xc1, 0xe4, 0x2b, 0x74, 0x16, 0x8e, + 0xd1, 0x73, 0x26, 0x49, 0xce, 0x1d, 0xbc, 0xdd, + 0x76, 0x19, 0x7a, 0x31, 0xfd, 0x55, 0xee, 0x98, + 0x9f, 0x2d, 0x70, 0x50, 0xdd, 0x47, 0x3e, 0x8f + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHA3-384 as a single buffer. [FIPS 202] */ + sha3_384_init(&c); + sha3_process(&c, buf, sizeof(buf)); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-384 in two steps. [FIPS 202] */ + sha3_384_init(&c); + sha3_process(&c, buf, sizeof(buf) / 2); + sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-384 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_384_init(&c); + while (i--) { + sha3_process(&c, &c1, 1); + } + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int sha3_512_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[512 / 8]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + + const unsigned char sha3_512_0xa3_200_times[512 / 8] = { + 0xe7, 0x6d, 0xfa, 0xd2, 0x20, 0x84, 0xa8, 0xb1, + 0x46, 0x7f, 0xcf, 0x2f, 0xfa, 0x58, 0x36, 0x1b, + 0xec, 0x76, 0x28, 0xed, 0xf5, 0xf3, 0xfd, 0xc0, + 0xe4, 0x80, 0x5d, 0xc4, 0x8c, 0xae, 0xec, 0xa8, + 0x1b, 0x7c, 0x13, 0xc3, 0x0a, 0xdf, 0x52, 0xa3, + 0x65, 0x95, 0x84, 0x73, 0x9a, 0x2d, 0xf4, 0x6b, + 0xe5, 0x89, 0xc5, 0x1c, 0xa1, 0xa4, 0xa8, 0x41, + 0x6d, 0xf6, 0x54, 0x5a, 0x1c, 0xe8, 0xba, 0x00 + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHA3-512 as a single buffer. [FIPS 202] */ + sha3_512_init(&c); + sha3_process(&c, buf, sizeof(buf)); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-512 in two steps. [FIPS 202] */ + sha3_512_init(&c); + sha3_process(&c, buf, sizeof(buf) / 2); + sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-512 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_512_init(&c); + while (i--) { + sha3_process(&c, &c1, 1); + } + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int sha3_shake_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[512]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + unsigned long len; + + const unsigned char shake256_empty[32] = { + 0xab, 0x0b, 0xae, 0x31, 0x63, 0x39, 0x89, 0x43, + 0x04, 0xe3, 0x58, 0x77, 0xb0, 0xc2, 0x8a, 0x9b, + 0x1f, 0xd1, 0x66, 0xc7, 0x96, 0xb9, 0xcc, 0x25, + 0x8a, 0x06, 0x4a, 0x8f, 0x57, 0xe2, 0x7f, 0x2a + }; + const unsigned char shake256_0xa3_200_times[32] = { + 0x6a, 0x1a, 0x9d, 0x78, 0x46, 0x43, 0x6e, 0x4d, + 0xca, 0x57, 0x28, 0xb6, 0xf7, 0x60, 0xee, 0xf0, + 0xca, 0x92, 0xbf, 0x0b, 0xe5, 0x61, 0x5e, 0x96, + 0x95, 0x9d, 0x76, 0x71, 0x97, 0xa0, 0xbe, 0xeb + }; + const unsigned char shake128_empty[32] = { + 0x43, 0xe4, 0x1b, 0x45, 0xa6, 0x53, 0xf2, 0xa5, + 0xc4, 0x49, 0x2c, 0x1a, 0xdd, 0x54, 0x45, 0x12, + 0xdd, 0xa2, 0x52, 0x98, 0x33, 0x46, 0x2b, 0x71, + 0xa4, 0x1a, 0x45, 0xbe, 0x97, 0x29, 0x0b, 0x6f + }; + const unsigned char shake128_0xa3_200_times[32] = { + 0x44, 0xc9, 0xfb, 0x35, 0x9f, 0xd5, 0x6a, 0xc0, + 0xa9, 0xa7, 0x5a, 0x74, 0x3c, 0xff, 0x68, 0x62, + 0xf1, 0x7d, 0x72, 0x59, 0xab, 0x07, 0x52, 0x16, + 0xc0, 0x69, 0x95, 0x11, 0x64, 0x3b, 0x64, 0x39 + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHAKE256 on an empty buffer */ + sha3_shake_init(&c, 256); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake256_empty), shake256_empty, sizeof(shake256_empty), "SHAKE256", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE256 via sha3_shake_memory [FIPS 202] */ + len = 512; + sha3_shake_memory(256, buf, sizeof(buf), hash, &len); + if (compare_testvector(hash + 480, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE256 as a single buffer. [FIPS 202] */ + sha3_shake_init(&c, 256); + sha3_shake_process(&c, buf, sizeof(buf)); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE256 in two steps. [FIPS 202] */ + sha3_shake_init(&c, 256); + sha3_shake_process(&c, buf, sizeof(buf) / 2); + sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 3)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE256 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_shake_init(&c, 256); + while (i--) sha3_shake_process(&c, &c1, 1); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 4)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 on an empty buffer */ + sha3_shake_init(&c, 128); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake128_empty), shake128_empty, sizeof(shake128_empty), "SHAKE128", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 via sha3_shake_memory [FIPS 202] */ + len = 512; + sha3_shake_memory(128, buf, sizeof(buf), hash, &len); + if (compare_testvector(hash + 480, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 as a single buffer. [FIPS 202] */ + sha3_shake_init(&c, 128); + sha3_shake_process(&c, buf, sizeof(buf)); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 in two steps. [FIPS 202] */ + sha3_shake_init(&c, 128); + sha3_shake_process(&c, buf, sizeof(buf) / 2); + sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 3)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_shake_init(&c, 128); + while (i--) sha3_shake_process(&c, &c1, 1); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 4)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif + +#ifdef LTC_KECCAK + +int keccak_224_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + hash_state c; + unsigned char hash[MAXBLOCKSIZE]; + + keccak_224_init(&c); + keccak_process(&c, (unsigned char*) "\xcc", 1); + keccak_done(&c, hash); + if(compare_testvector(hash, 28, + "\xa9\xca\xb5\x9e\xb4\x0a\x10\xb2" + "\x46\x29\x0f\x2d\x60\x86\xe3\x2e" + "\x36\x89\xfa\xf1\xd2\x6b\x47\x0c" + "\x89\x9f\x28\x02", 28, + "KECCAK-224", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_224_init(&c); + keccak_process(&c, (unsigned char*)"\x41\xfb", 2); + keccak_done(&c, hash); + if(compare_testvector(hash, 28, + "\x61\x5b\xa3\x67\xaf\xdc\x35\xaa" + "\xc3\x97\xbc\x7e\xb5\xd5\x8d\x10" + "\x6a\x73\x4b\x24\x98\x6d\x5d\x97" + "\x8f\xef\xd6\x2c", 28, + "KECCAK-224", 1) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_224_init(&c); + keccak_process(&c, (unsigned char*) + "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" + "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); + keccak_done(&c, hash); + if(compare_testvector(hash, 28, + "\x56\x79\xcd\x50\x9c\x51\x20\xaf" + "\x54\x79\x5c\xf4\x77\x14\x96\x41" + "\xcf\x27\xb2\xeb\xb6\xa5\xf9\x03" + "\x40\x70\x4e\x57", 28, + "KECCAK-224", 2) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_224_init(&c); + keccak_process(&c, (unsigned char*) + "\x43\x3c\x53\x03\x13\x16\x24\xc0" + "\x02\x1d\x86\x8a\x30\x82\x54\x75" + "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" + "\x03\x98\xf4\xca\x44\x23\xb9\x82" + "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" + "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" + "\x92\xcc\x1b\x06\xce\xdf\x32\x24" + "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" + "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" + "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" + "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" + "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" + "\x6d\xcb\xb4\xce", 100); + keccak_done(&c, hash); + if(compare_testvector(hash, 28, + "\x62\xb1\x0f\x1b\x62\x36\xeb\xc2" + "\xda\x72\x95\x77\x42\xa8\xd4\xe4" + "\x8e\x21\x3b\x5f\x89\x34\x60\x4b" + "\xfd\x4d\x2c\x3a", 28, + "KECCAK-224", 3) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int keccak_256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + hash_state c; + unsigned char hash[MAXBLOCKSIZE]; + + keccak_256_init(&c); + keccak_process(&c, (unsigned char*) "\xcc", 1); + keccak_done(&c, hash); + if(compare_testvector(hash, 32, + "\xee\xad\x6d\xbf\xc7\x34\x0a\x56" + "\xca\xed\xc0\x44\x69\x6a\x16\x88" + "\x70\x54\x9a\x6a\x7f\x6f\x56\x96" + "\x1e\x84\xa5\x4b\xd9\x97\x0b\x8a", 32, + "KECCAK-256", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_256_init(&c); + keccak_process(&c, (unsigned char*)"\x41\xfb", 2); + keccak_done(&c, hash); + if(compare_testvector(hash, 32, + "\xa8\xea\xce\xda\x4d\x47\xb3\x28" + "\x1a\x79\x5a\xd9\xe1\xea\x21\x22" + "\xb4\x07\xba\xf9\xaa\xbc\xb9\xe1" + "\x8b\x57\x17\xb7\x87\x35\x37\xd2", 32, + "KECCAK-256", 1) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_256_init(&c); + keccak_process(&c, (unsigned char*) + "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" + "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); + keccak_done(&c, hash); + if(compare_testvector(hash, 32, + "\x0e\x32\xde\xfa\x20\x71\xf0\xb5" + "\xac\x0e\x6a\x10\x8b\x84\x2e\xd0" + "\xf1\xd3\x24\x97\x12\xf5\x8e\xe0" + "\xdd\xf9\x56\xfe\x33\x2a\x5f\x95", 32, + "KECCAK-256", 2) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_256_init(&c); + keccak_process(&c, (unsigned char*) + "\x43\x3c\x53\x03\x13\x16\x24\xc0" + "\x02\x1d\x86\x8a\x30\x82\x54\x75" + "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" + "\x03\x98\xf4\xca\x44\x23\xb9\x82" + "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" + "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" + "\x92\xcc\x1b\x06\xce\xdf\x32\x24" + "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" + "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" + "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" + "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" + "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" + "\x6d\xcb\xb4\xce", 100); + keccak_done(&c, hash); + if(compare_testvector(hash, 32, + "\xce\x87\xa5\x17\x3b\xff\xd9\x23" + "\x99\x22\x16\x58\xf8\x01\xd4\x5c" + "\x29\x4d\x90\x06\xee\x9f\x3f\x9d" + "\x41\x9c\x8d\x42\x77\x48\xdc\x41", 32, + "KECCAK-256", 3) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int keccak_384_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + hash_state c; + unsigned char hash[MAXBLOCKSIZE]; + + keccak_384_init(&c); + keccak_process(&c, (unsigned char*) "\xcc", 1); + keccak_done(&c, hash); + if(compare_testvector(hash, 48, + "\x1b\x84\xe6\x2a\x46\xe5\xa2\x01" + "\x86\x17\x54\xaf\x5d\xc9\x5c\x4a" + "\x1a\x69\xca\xf4\xa7\x96\xae\x40" + "\x56\x80\x16\x1e\x29\x57\x26\x41" + "\xf5\xfa\x1e\x86\x41\xd7\x95\x83" + "\x36\xee\x7b\x11\xc5\x8f\x73\xe9", 48, + "KECCAK-384", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_384_init(&c); + keccak_process(&c, (unsigned char*)"\x41\xfb", 2); + keccak_done(&c, hash); + if(compare_testvector(hash, 48, + "\x49\x5c\xce\x27\x14\xcd\x72\xc8" + "\xc5\x3c\x33\x63\xd2\x2c\x58\xb5" + "\x59\x60\xfe\x26\xbe\x0b\xf3\xbb" + "\xc7\xa3\x31\x6d\xd5\x63\xad\x1d" + "\xb8\x41\x0e\x75\xee\xfe\xa6\x55" + "\xe3\x9d\x46\x70\xec\x0b\x17\x92", 48, + "KECCAK-384", 1) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_384_init(&c); + keccak_process(&c, (unsigned char*) + "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" + "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); + keccak_done(&c, hash); + if(compare_testvector(hash, 48, + "\x18\x42\x2a\xc1\xd3\xa1\xe5\x4b" + "\xad\x87\x68\x83\xd2\xd6\xdd\x65" + "\xf6\x5c\x1d\x5f\x33\xa7\x12\x5c" + "\xc4\xc1\x86\x40\x5a\x12\xed\x64" + "\xba\x96\x67\x2e\xed\xda\x8c\x5a" + "\x63\x31\xd2\x86\x83\xf4\x88\xeb", 48, + "KECCAK-384", 2) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_384_init(&c); + keccak_process(&c, (unsigned char*) + "\x43\x3c\x53\x03\x13\x16\x24\xc0" + "\x02\x1d\x86\x8a\x30\x82\x54\x75" + "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" + "\x03\x98\xf4\xca\x44\x23\xb9\x82" + "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" + "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" + "\x92\xcc\x1b\x06\xce\xdf\x32\x24" + "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" + "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" + "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" + "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" + "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" + "\x6d\xcb\xb4\xce", 100); + keccak_done(&c, hash); + if(compare_testvector(hash, 48, + "\x13\x51\x14\x50\x8d\xd6\x3e\x27" + "\x9e\x70\x9c\x26\xf7\x81\x7c\x04" + "\x82\x76\x6c\xde\x49\x13\x2e\x3e" + "\xdf\x2e\xed\xd8\x99\x6f\x4e\x35" + "\x96\xd1\x84\x10\x0b\x38\x48\x68" + "\x24\x9f\x1d\x8b\x8f\xda\xa2\xc9", 48, + "KECCAK-384", 3) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int keccak_512_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + hash_state c; + unsigned char hash[MAXBLOCKSIZE]; + + keccak_512_init(&c); + keccak_process(&c, (unsigned char*) "\xcc", 1); + keccak_done(&c, hash); + if(compare_testvector(hash, 64, + "\x86\x30\xc1\x3c\xbd\x06\x6e\xa7" + "\x4b\xbe\x7f\xe4\x68\xfe\xc1\xde" + "\xe1\x0e\xdc\x12\x54\xfb\x4c\x1b" + "\x7c\x5f\xd6\x9b\x64\x6e\x44\x16" + "\x0b\x8c\xe0\x1d\x05\xa0\x90\x8c" + "\xa7\x90\xdf\xb0\x80\xf4\xb5\x13" + "\xbc\x3b\x62\x25\xec\xe7\xa8\x10" + "\x37\x14\x41\xa5\xac\x66\x6e\xb9", 64, + "KECCAK-512", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_512_init(&c); + keccak_process(&c, (unsigned char*)"\x41\xfb", 2); + keccak_done(&c, hash); + if(compare_testvector(hash, 64, + "\x55\x1d\xa6\x23\x6f\x8b\x96\xfc" + "\xe9\xf9\x7f\x11\x90\xe9\x01\x32" + "\x4f\x0b\x45\xe0\x6d\xbb\xb5\xcd" + "\xb8\x35\x5d\x6e\xd1\xdc\x34\xb3" + "\xf0\xea\xe7\xdc\xb6\x86\x22\xff" + "\x23\x2f\xa3\xce\xce\x0d\x46\x16" + "\xcd\xeb\x39\x31\xf9\x38\x03\x66" + "\x2a\x28\xdf\x1c\xd5\x35\xb7\x31", 64, + "KECCAK-512", 1) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_512_init(&c); + keccak_process(&c, (unsigned char*) + "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" + "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); + keccak_done(&c, hash); + if(compare_testvector(hash, 64, + "\x4b\x39\xd3\xda\x5b\xcd\xf4\xd9" + "\xb7\x69\x01\x59\x95\x64\x43\x11" + "\xc1\x4c\x43\x5b\xf7\x2b\x10\x09" + "\xd6\xdd\x71\xb0\x1a\x63\xb9\x7c" + "\xfb\x59\x64\x18\xe8\xe4\x23\x42" + "\xd1\x17\xe0\x74\x71\xa8\x91\x43" + "\x14\xba\x7b\x0e\x26\x4d\xad\xf0" + "\xce\xa3\x81\x86\x8c\xbd\x43\xd1", 64, + "KECCAK-512", 2) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_512_init(&c); + keccak_process(&c, (unsigned char*) + "\x43\x3c\x53\x03\x13\x16\x24\xc0" + "\x02\x1d\x86\x8a\x30\x82\x54\x75" + "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" + "\x03\x98\xf4\xca\x44\x23\xb9\x82" + "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" + "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" + "\x92\xcc\x1b\x06\xce\xdf\x32\x24" + "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" + "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" + "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" + "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" + "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" + "\x6d\xcb\xb4\xce", 100); + keccak_done(&c, hash); + if(compare_testvector(hash, 64, + "\x52\x7d\x28\xe3\x41\xe6\xb1\x4f" + "\x46\x84\xad\xb4\xb8\x24\xc4\x96" + "\xc6\x48\x2e\x51\x14\x95\x65\xd3" + "\xd1\x72\x26\x82\x88\x84\x30\x6b" + "\x51\xd6\x14\x8a\x72\x62\x2c\x2b" + "\x75\xf5\xd3\x51\x0b\x79\x9d\x8b" + "\xdc\x03\xea\xed\xe4\x53\x67\x6a" + "\x6e\xc8\xfe\x03\xa1\xad\x0e\xab", 64, + "KECCAK-512", 3) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sub.mk new file mode 100644 index 0000000..4a9b66e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/sub.mk @@ -0,0 +1,14 @@ +srcs-$(_CFG_CORE_LTC_MD5) += md5.c + +ifeq ($(_CFG_CORE_LTC_SHA1),y) +ifneq ($(_CFG_CORE_LTC_SHA1_ACCEL),y) +srcs-y += sha1.c +endif +endif + +ifneq ($(_CFG_CORE_LTC_SHA3_ACCEL),y) +srcs-$(_CFG_CORE_LTC_SHA3_DESC) += sha3.c +endif +srcs-$(_CFG_CORE_LTC_SHA3_DESC) += sha3_test.c +subdirs-y += helper +subdirs-y += sha2 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/tiger.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/tiger.c new file mode 100644 index 0000000..8ca2d54 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/tiger.c @@ -0,0 +1,796 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file tiger.c + Tiger hash function, Tom St Denis +*/ + +#ifdef LTC_TIGER + +const struct ltc_hash_descriptor tiger_desc = +{ + "tiger", + 1, + 24, + 64, + + /* OID */ + { 1, 3, 6, 1, 4, 1, 11591, 12, 2, }, + 9, + + &tiger_init, + &tiger_process, + &tiger_done, + &tiger_test, + NULL +}; + +#define t1 (table) +#define t2 (table+256) +#define t3 (table+256*2) +#define t4 (table+256*3) + +static const ulong64 table[4*256] = { + CONST64(0x02AAB17CF7E90C5E) /* 0 */, CONST64(0xAC424B03E243A8EC) /* 1 */, + CONST64(0x72CD5BE30DD5FCD3) /* 2 */, CONST64(0x6D019B93F6F97F3A) /* 3 */, + CONST64(0xCD9978FFD21F9193) /* 4 */, CONST64(0x7573A1C9708029E2) /* 5 */, + CONST64(0xB164326B922A83C3) /* 6 */, CONST64(0x46883EEE04915870) /* 7 */, + CONST64(0xEAACE3057103ECE6) /* 8 */, CONST64(0xC54169B808A3535C) /* 9 */, + CONST64(0x4CE754918DDEC47C) /* 10 */, CONST64(0x0AA2F4DFDC0DF40C) /* 11 */, + CONST64(0x10B76F18A74DBEFA) /* 12 */, CONST64(0xC6CCB6235AD1AB6A) /* 13 */, + CONST64(0x13726121572FE2FF) /* 14 */, CONST64(0x1A488C6F199D921E) /* 15 */, + CONST64(0x4BC9F9F4DA0007CA) /* 16 */, CONST64(0x26F5E6F6E85241C7) /* 17 */, + CONST64(0x859079DBEA5947B6) /* 18 */, CONST64(0x4F1885C5C99E8C92) /* 19 */, + CONST64(0xD78E761EA96F864B) /* 20 */, CONST64(0x8E36428C52B5C17D) /* 21 */, + CONST64(0x69CF6827373063C1) /* 22 */, CONST64(0xB607C93D9BB4C56E) /* 23 */, + CONST64(0x7D820E760E76B5EA) /* 24 */, CONST64(0x645C9CC6F07FDC42) /* 25 */, + CONST64(0xBF38A078243342E0) /* 26 */, CONST64(0x5F6B343C9D2E7D04) /* 27 */, + CONST64(0xF2C28AEB600B0EC6) /* 28 */, CONST64(0x6C0ED85F7254BCAC) /* 29 */, + CONST64(0x71592281A4DB4FE5) /* 30 */, CONST64(0x1967FA69CE0FED9F) /* 31 */, + CONST64(0xFD5293F8B96545DB) /* 32 */, CONST64(0xC879E9D7F2A7600B) /* 33 */, + CONST64(0x860248920193194E) /* 34 */, CONST64(0xA4F9533B2D9CC0B3) /* 35 */, + CONST64(0x9053836C15957613) /* 36 */, CONST64(0xDB6DCF8AFC357BF1) /* 37 */, + CONST64(0x18BEEA7A7A370F57) /* 38 */, CONST64(0x037117CA50B99066) /* 39 */, + CONST64(0x6AB30A9774424A35) /* 40 */, CONST64(0xF4E92F02E325249B) /* 41 */, + CONST64(0x7739DB07061CCAE1) /* 42 */, CONST64(0xD8F3B49CECA42A05) /* 43 */, + CONST64(0xBD56BE3F51382F73) /* 44 */, CONST64(0x45FAED5843B0BB28) /* 45 */, + CONST64(0x1C813D5C11BF1F83) /* 46 */, CONST64(0x8AF0E4B6D75FA169) /* 47 */, + CONST64(0x33EE18A487AD9999) /* 48 */, CONST64(0x3C26E8EAB1C94410) /* 49 */, + CONST64(0xB510102BC0A822F9) /* 50 */, CONST64(0x141EEF310CE6123B) /* 51 */, + CONST64(0xFC65B90059DDB154) /* 52 */, CONST64(0xE0158640C5E0E607) /* 53 */, + CONST64(0x884E079826C3A3CF) /* 54 */, CONST64(0x930D0D9523C535FD) /* 55 */, + CONST64(0x35638D754E9A2B00) /* 56 */, CONST64(0x4085FCCF40469DD5) /* 57 */, + CONST64(0xC4B17AD28BE23A4C) /* 58 */, CONST64(0xCAB2F0FC6A3E6A2E) /* 59 */, + CONST64(0x2860971A6B943FCD) /* 60 */, CONST64(0x3DDE6EE212E30446) /* 61 */, + CONST64(0x6222F32AE01765AE) /* 62 */, CONST64(0x5D550BB5478308FE) /* 63 */, + CONST64(0xA9EFA98DA0EDA22A) /* 64 */, CONST64(0xC351A71686C40DA7) /* 65 */, + CONST64(0x1105586D9C867C84) /* 66 */, CONST64(0xDCFFEE85FDA22853) /* 67 */, + CONST64(0xCCFBD0262C5EEF76) /* 68 */, CONST64(0xBAF294CB8990D201) /* 69 */, + CONST64(0xE69464F52AFAD975) /* 70 */, CONST64(0x94B013AFDF133E14) /* 71 */, + CONST64(0x06A7D1A32823C958) /* 72 */, CONST64(0x6F95FE5130F61119) /* 73 */, + CONST64(0xD92AB34E462C06C0) /* 74 */, CONST64(0xED7BDE33887C71D2) /* 75 */, + CONST64(0x79746D6E6518393E) /* 76 */, CONST64(0x5BA419385D713329) /* 77 */, + CONST64(0x7C1BA6B948A97564) /* 78 */, CONST64(0x31987C197BFDAC67) /* 79 */, + CONST64(0xDE6C23C44B053D02) /* 80 */, CONST64(0x581C49FED002D64D) /* 81 */, + CONST64(0xDD474D6338261571) /* 82 */, CONST64(0xAA4546C3E473D062) /* 83 */, + CONST64(0x928FCE349455F860) /* 84 */, CONST64(0x48161BBACAAB94D9) /* 85 */, + CONST64(0x63912430770E6F68) /* 86 */, CONST64(0x6EC8A5E602C6641C) /* 87 */, + CONST64(0x87282515337DDD2B) /* 88 */, CONST64(0x2CDA6B42034B701B) /* 89 */, + CONST64(0xB03D37C181CB096D) /* 90 */, CONST64(0xE108438266C71C6F) /* 91 */, + CONST64(0x2B3180C7EB51B255) /* 92 */, CONST64(0xDF92B82F96C08BBC) /* 93 */, + CONST64(0x5C68C8C0A632F3BA) /* 94 */, CONST64(0x5504CC861C3D0556) /* 95 */, + CONST64(0xABBFA4E55FB26B8F) /* 96 */, CONST64(0x41848B0AB3BACEB4) /* 97 */, + CONST64(0xB334A273AA445D32) /* 98 */, CONST64(0xBCA696F0A85AD881) /* 99 */, + CONST64(0x24F6EC65B528D56C) /* 100 */, CONST64(0x0CE1512E90F4524A) /* 101 */, + CONST64(0x4E9DD79D5506D35A) /* 102 */, CONST64(0x258905FAC6CE9779) /* 103 */, + CONST64(0x2019295B3E109B33) /* 104 */, CONST64(0xF8A9478B73A054CC) /* 105 */, + CONST64(0x2924F2F934417EB0) /* 106 */, CONST64(0x3993357D536D1BC4) /* 107 */, + CONST64(0x38A81AC21DB6FF8B) /* 108 */, CONST64(0x47C4FBF17D6016BF) /* 109 */, + CONST64(0x1E0FAADD7667E3F5) /* 110 */, CONST64(0x7ABCFF62938BEB96) /* 111 */, + CONST64(0xA78DAD948FC179C9) /* 112 */, CONST64(0x8F1F98B72911E50D) /* 113 */, + CONST64(0x61E48EAE27121A91) /* 114 */, CONST64(0x4D62F7AD31859808) /* 115 */, + CONST64(0xECEBA345EF5CEAEB) /* 116 */, CONST64(0xF5CEB25EBC9684CE) /* 117 */, + CONST64(0xF633E20CB7F76221) /* 118 */, CONST64(0xA32CDF06AB8293E4) /* 119 */, + CONST64(0x985A202CA5EE2CA4) /* 120 */, CONST64(0xCF0B8447CC8A8FB1) /* 121 */, + CONST64(0x9F765244979859A3) /* 122 */, CONST64(0xA8D516B1A1240017) /* 123 */, + CONST64(0x0BD7BA3EBB5DC726) /* 124 */, CONST64(0xE54BCA55B86ADB39) /* 125 */, + CONST64(0x1D7A3AFD6C478063) /* 126 */, CONST64(0x519EC608E7669EDD) /* 127 */, + CONST64(0x0E5715A2D149AA23) /* 128 */, CONST64(0x177D4571848FF194) /* 129 */, + CONST64(0xEEB55F3241014C22) /* 130 */, CONST64(0x0F5E5CA13A6E2EC2) /* 131 */, + CONST64(0x8029927B75F5C361) /* 132 */, CONST64(0xAD139FABC3D6E436) /* 133 */, + CONST64(0x0D5DF1A94CCF402F) /* 134 */, CONST64(0x3E8BD948BEA5DFC8) /* 135 */, + CONST64(0xA5A0D357BD3FF77E) /* 136 */, CONST64(0xA2D12E251F74F645) /* 137 */, + CONST64(0x66FD9E525E81A082) /* 138 */, CONST64(0x2E0C90CE7F687A49) /* 139 */, + CONST64(0xC2E8BCBEBA973BC5) /* 140 */, CONST64(0x000001BCE509745F) /* 141 */, + CONST64(0x423777BBE6DAB3D6) /* 142 */, CONST64(0xD1661C7EAEF06EB5) /* 143 */, + CONST64(0xA1781F354DAACFD8) /* 144 */, CONST64(0x2D11284A2B16AFFC) /* 145 */, + CONST64(0xF1FC4F67FA891D1F) /* 146 */, CONST64(0x73ECC25DCB920ADA) /* 147 */, + CONST64(0xAE610C22C2A12651) /* 148 */, CONST64(0x96E0A810D356B78A) /* 149 */, + CONST64(0x5A9A381F2FE7870F) /* 150 */, CONST64(0xD5AD62EDE94E5530) /* 151 */, + CONST64(0xD225E5E8368D1427) /* 152 */, CONST64(0x65977B70C7AF4631) /* 153 */, + CONST64(0x99F889B2DE39D74F) /* 154 */, CONST64(0x233F30BF54E1D143) /* 155 */, + CONST64(0x9A9675D3D9A63C97) /* 156 */, CONST64(0x5470554FF334F9A8) /* 157 */, + CONST64(0x166ACB744A4F5688) /* 158 */, CONST64(0x70C74CAAB2E4AEAD) /* 159 */, + CONST64(0xF0D091646F294D12) /* 160 */, CONST64(0x57B82A89684031D1) /* 161 */, + CONST64(0xEFD95A5A61BE0B6B) /* 162 */, CONST64(0x2FBD12E969F2F29A) /* 163 */, + CONST64(0x9BD37013FEFF9FE8) /* 164 */, CONST64(0x3F9B0404D6085A06) /* 165 */, + CONST64(0x4940C1F3166CFE15) /* 166 */, CONST64(0x09542C4DCDF3DEFB) /* 167 */, + CONST64(0xB4C5218385CD5CE3) /* 168 */, CONST64(0xC935B7DC4462A641) /* 169 */, + CONST64(0x3417F8A68ED3B63F) /* 170 */, CONST64(0xB80959295B215B40) /* 171 */, + CONST64(0xF99CDAEF3B8C8572) /* 172 */, CONST64(0x018C0614F8FCB95D) /* 173 */, + CONST64(0x1B14ACCD1A3ACDF3) /* 174 */, CONST64(0x84D471F200BB732D) /* 175 */, + CONST64(0xC1A3110E95E8DA16) /* 176 */, CONST64(0x430A7220BF1A82B8) /* 177 */, + CONST64(0xB77E090D39DF210E) /* 178 */, CONST64(0x5EF4BD9F3CD05E9D) /* 179 */, + CONST64(0x9D4FF6DA7E57A444) /* 180 */, CONST64(0xDA1D60E183D4A5F8) /* 181 */, + CONST64(0xB287C38417998E47) /* 182 */, CONST64(0xFE3EDC121BB31886) /* 183 */, + CONST64(0xC7FE3CCC980CCBEF) /* 184 */, CONST64(0xE46FB590189BFD03) /* 185 */, + CONST64(0x3732FD469A4C57DC) /* 186 */, CONST64(0x7EF700A07CF1AD65) /* 187 */, + CONST64(0x59C64468A31D8859) /* 188 */, CONST64(0x762FB0B4D45B61F6) /* 189 */, + CONST64(0x155BAED099047718) /* 190 */, CONST64(0x68755E4C3D50BAA6) /* 191 */, + CONST64(0xE9214E7F22D8B4DF) /* 192 */, CONST64(0x2ADDBF532EAC95F4) /* 193 */, + CONST64(0x32AE3909B4BD0109) /* 194 */, CONST64(0x834DF537B08E3450) /* 195 */, + CONST64(0xFA209DA84220728D) /* 196 */, CONST64(0x9E691D9B9EFE23F7) /* 197 */, + CONST64(0x0446D288C4AE8D7F) /* 198 */, CONST64(0x7B4CC524E169785B) /* 199 */, + CONST64(0x21D87F0135CA1385) /* 200 */, CONST64(0xCEBB400F137B8AA5) /* 201 */, + CONST64(0x272E2B66580796BE) /* 202 */, CONST64(0x3612264125C2B0DE) /* 203 */, + CONST64(0x057702BDAD1EFBB2) /* 204 */, CONST64(0xD4BABB8EACF84BE9) /* 205 */, + CONST64(0x91583139641BC67B) /* 206 */, CONST64(0x8BDC2DE08036E024) /* 207 */, + CONST64(0x603C8156F49F68ED) /* 208 */, CONST64(0xF7D236F7DBEF5111) /* 209 */, + CONST64(0x9727C4598AD21E80) /* 210 */, CONST64(0xA08A0896670A5FD7) /* 211 */, + CONST64(0xCB4A8F4309EBA9CB) /* 212 */, CONST64(0x81AF564B0F7036A1) /* 213 */, + CONST64(0xC0B99AA778199ABD) /* 214 */, CONST64(0x959F1EC83FC8E952) /* 215 */, + CONST64(0x8C505077794A81B9) /* 216 */, CONST64(0x3ACAAF8F056338F0) /* 217 */, + CONST64(0x07B43F50627A6778) /* 218 */, CONST64(0x4A44AB49F5ECCC77) /* 219 */, + CONST64(0x3BC3D6E4B679EE98) /* 220 */, CONST64(0x9CC0D4D1CF14108C) /* 221 */, + CONST64(0x4406C00B206BC8A0) /* 222 */, CONST64(0x82A18854C8D72D89) /* 223 */, + CONST64(0x67E366B35C3C432C) /* 224 */, CONST64(0xB923DD61102B37F2) /* 225 */, + CONST64(0x56AB2779D884271D) /* 226 */, CONST64(0xBE83E1B0FF1525AF) /* 227 */, + CONST64(0xFB7C65D4217E49A9) /* 228 */, CONST64(0x6BDBE0E76D48E7D4) /* 229 */, + CONST64(0x08DF828745D9179E) /* 230 */, CONST64(0x22EA6A9ADD53BD34) /* 231 */, + CONST64(0xE36E141C5622200A) /* 232 */, CONST64(0x7F805D1B8CB750EE) /* 233 */, + CONST64(0xAFE5C7A59F58E837) /* 234 */, CONST64(0xE27F996A4FB1C23C) /* 235 */, + CONST64(0xD3867DFB0775F0D0) /* 236 */, CONST64(0xD0E673DE6E88891A) /* 237 */, + CONST64(0x123AEB9EAFB86C25) /* 238 */, CONST64(0x30F1D5D5C145B895) /* 239 */, + CONST64(0xBB434A2DEE7269E7) /* 240 */, CONST64(0x78CB67ECF931FA38) /* 241 */, + CONST64(0xF33B0372323BBF9C) /* 242 */, CONST64(0x52D66336FB279C74) /* 243 */, + CONST64(0x505F33AC0AFB4EAA) /* 244 */, CONST64(0xE8A5CD99A2CCE187) /* 245 */, + CONST64(0x534974801E2D30BB) /* 246 */, CONST64(0x8D2D5711D5876D90) /* 247 */, + CONST64(0x1F1A412891BC038E) /* 248 */, CONST64(0xD6E2E71D82E56648) /* 249 */, + CONST64(0x74036C3A497732B7) /* 250 */, CONST64(0x89B67ED96361F5AB) /* 251 */, + CONST64(0xFFED95D8F1EA02A2) /* 252 */, CONST64(0xE72B3BD61464D43D) /* 253 */, + CONST64(0xA6300F170BDC4820) /* 254 */, CONST64(0xEBC18760ED78A77A) /* 255 */, + CONST64(0xE6A6BE5A05A12138) /* 256 */, CONST64(0xB5A122A5B4F87C98) /* 257 */, + CONST64(0x563C6089140B6990) /* 258 */, CONST64(0x4C46CB2E391F5DD5) /* 259 */, + CONST64(0xD932ADDBC9B79434) /* 260 */, CONST64(0x08EA70E42015AFF5) /* 261 */, + CONST64(0xD765A6673E478CF1) /* 262 */, CONST64(0xC4FB757EAB278D99) /* 263 */, + CONST64(0xDF11C6862D6E0692) /* 264 */, CONST64(0xDDEB84F10D7F3B16) /* 265 */, + CONST64(0x6F2EF604A665EA04) /* 266 */, CONST64(0x4A8E0F0FF0E0DFB3) /* 267 */, + CONST64(0xA5EDEEF83DBCBA51) /* 268 */, CONST64(0xFC4F0A2A0EA4371E) /* 269 */, + CONST64(0xE83E1DA85CB38429) /* 270 */, CONST64(0xDC8FF882BA1B1CE2) /* 271 */, + CONST64(0xCD45505E8353E80D) /* 272 */, CONST64(0x18D19A00D4DB0717) /* 273 */, + CONST64(0x34A0CFEDA5F38101) /* 274 */, CONST64(0x0BE77E518887CAF2) /* 275 */, + CONST64(0x1E341438B3C45136) /* 276 */, CONST64(0xE05797F49089CCF9) /* 277 */, + CONST64(0xFFD23F9DF2591D14) /* 278 */, CONST64(0x543DDA228595C5CD) /* 279 */, + CONST64(0x661F81FD99052A33) /* 280 */, CONST64(0x8736E641DB0F7B76) /* 281 */, + CONST64(0x15227725418E5307) /* 282 */, CONST64(0xE25F7F46162EB2FA) /* 283 */, + CONST64(0x48A8B2126C13D9FE) /* 284 */, CONST64(0xAFDC541792E76EEA) /* 285 */, + CONST64(0x03D912BFC6D1898F) /* 286 */, CONST64(0x31B1AAFA1B83F51B) /* 287 */, + CONST64(0xF1AC2796E42AB7D9) /* 288 */, CONST64(0x40A3A7D7FCD2EBAC) /* 289 */, + CONST64(0x1056136D0AFBBCC5) /* 290 */, CONST64(0x7889E1DD9A6D0C85) /* 291 */, + CONST64(0xD33525782A7974AA) /* 292 */, CONST64(0xA7E25D09078AC09B) /* 293 */, + CONST64(0xBD4138B3EAC6EDD0) /* 294 */, CONST64(0x920ABFBE71EB9E70) /* 295 */, + CONST64(0xA2A5D0F54FC2625C) /* 296 */, CONST64(0xC054E36B0B1290A3) /* 297 */, + CONST64(0xF6DD59FF62FE932B) /* 298 */, CONST64(0x3537354511A8AC7D) /* 299 */, + CONST64(0xCA845E9172FADCD4) /* 300 */, CONST64(0x84F82B60329D20DC) /* 301 */, + CONST64(0x79C62CE1CD672F18) /* 302 */, CONST64(0x8B09A2ADD124642C) /* 303 */, + CONST64(0xD0C1E96A19D9E726) /* 304 */, CONST64(0x5A786A9B4BA9500C) /* 305 */, + CONST64(0x0E020336634C43F3) /* 306 */, CONST64(0xC17B474AEB66D822) /* 307 */, + CONST64(0x6A731AE3EC9BAAC2) /* 308 */, CONST64(0x8226667AE0840258) /* 309 */, + CONST64(0x67D4567691CAECA5) /* 310 */, CONST64(0x1D94155C4875ADB5) /* 311 */, + CONST64(0x6D00FD985B813FDF) /* 312 */, CONST64(0x51286EFCB774CD06) /* 313 */, + CONST64(0x5E8834471FA744AF) /* 314 */, CONST64(0xF72CA0AEE761AE2E) /* 315 */, + CONST64(0xBE40E4CDAEE8E09A) /* 316 */, CONST64(0xE9970BBB5118F665) /* 317 */, + CONST64(0x726E4BEB33DF1964) /* 318 */, CONST64(0x703B000729199762) /* 319 */, + CONST64(0x4631D816F5EF30A7) /* 320 */, CONST64(0xB880B5B51504A6BE) /* 321 */, + CONST64(0x641793C37ED84B6C) /* 322 */, CONST64(0x7B21ED77F6E97D96) /* 323 */, + CONST64(0x776306312EF96B73) /* 324 */, CONST64(0xAE528948E86FF3F4) /* 325 */, + CONST64(0x53DBD7F286A3F8F8) /* 326 */, CONST64(0x16CADCE74CFC1063) /* 327 */, + CONST64(0x005C19BDFA52C6DD) /* 328 */, CONST64(0x68868F5D64D46AD3) /* 329 */, + CONST64(0x3A9D512CCF1E186A) /* 330 */, CONST64(0x367E62C2385660AE) /* 331 */, + CONST64(0xE359E7EA77DCB1D7) /* 332 */, CONST64(0x526C0773749ABE6E) /* 333 */, + CONST64(0x735AE5F9D09F734B) /* 334 */, CONST64(0x493FC7CC8A558BA8) /* 335 */, + CONST64(0xB0B9C1533041AB45) /* 336 */, CONST64(0x321958BA470A59BD) /* 337 */, + CONST64(0x852DB00B5F46C393) /* 338 */, CONST64(0x91209B2BD336B0E5) /* 339 */, + CONST64(0x6E604F7D659EF19F) /* 340 */, CONST64(0xB99A8AE2782CCB24) /* 341 */, + CONST64(0xCCF52AB6C814C4C7) /* 342 */, CONST64(0x4727D9AFBE11727B) /* 343 */, + CONST64(0x7E950D0C0121B34D) /* 344 */, CONST64(0x756F435670AD471F) /* 345 */, + CONST64(0xF5ADD442615A6849) /* 346 */, CONST64(0x4E87E09980B9957A) /* 347 */, + CONST64(0x2ACFA1DF50AEE355) /* 348 */, CONST64(0xD898263AFD2FD556) /* 349 */, + CONST64(0xC8F4924DD80C8FD6) /* 350 */, CONST64(0xCF99CA3D754A173A) /* 351 */, + CONST64(0xFE477BACAF91BF3C) /* 352 */, CONST64(0xED5371F6D690C12D) /* 353 */, + CONST64(0x831A5C285E687094) /* 354 */, CONST64(0xC5D3C90A3708A0A4) /* 355 */, + CONST64(0x0F7F903717D06580) /* 356 */, CONST64(0x19F9BB13B8FDF27F) /* 357 */, + CONST64(0xB1BD6F1B4D502843) /* 358 */, CONST64(0x1C761BA38FFF4012) /* 359 */, + CONST64(0x0D1530C4E2E21F3B) /* 360 */, CONST64(0x8943CE69A7372C8A) /* 361 */, + CONST64(0xE5184E11FEB5CE66) /* 362 */, CONST64(0x618BDB80BD736621) /* 363 */, + CONST64(0x7D29BAD68B574D0B) /* 364 */, CONST64(0x81BB613E25E6FE5B) /* 365 */, + CONST64(0x071C9C10BC07913F) /* 366 */, CONST64(0xC7BEEB7909AC2D97) /* 367 */, + CONST64(0xC3E58D353BC5D757) /* 368 */, CONST64(0xEB017892F38F61E8) /* 369 */, + CONST64(0xD4EFFB9C9B1CC21A) /* 370 */, CONST64(0x99727D26F494F7AB) /* 371 */, + CONST64(0xA3E063A2956B3E03) /* 372 */, CONST64(0x9D4A8B9A4AA09C30) /* 373 */, + CONST64(0x3F6AB7D500090FB4) /* 374 */, CONST64(0x9CC0F2A057268AC0) /* 375 */, + CONST64(0x3DEE9D2DEDBF42D1) /* 376 */, CONST64(0x330F49C87960A972) /* 377 */, + CONST64(0xC6B2720287421B41) /* 378 */, CONST64(0x0AC59EC07C00369C) /* 379 */, + CONST64(0xEF4EAC49CB353425) /* 380 */, CONST64(0xF450244EEF0129D8) /* 381 */, + CONST64(0x8ACC46E5CAF4DEB6) /* 382 */, CONST64(0x2FFEAB63989263F7) /* 383 */, + CONST64(0x8F7CB9FE5D7A4578) /* 384 */, CONST64(0x5BD8F7644E634635) /* 385 */, + CONST64(0x427A7315BF2DC900) /* 386 */, CONST64(0x17D0C4AA2125261C) /* 387 */, + CONST64(0x3992486C93518E50) /* 388 */, CONST64(0xB4CBFEE0A2D7D4C3) /* 389 */, + CONST64(0x7C75D6202C5DDD8D) /* 390 */, CONST64(0xDBC295D8E35B6C61) /* 391 */, + CONST64(0x60B369D302032B19) /* 392 */, CONST64(0xCE42685FDCE44132) /* 393 */, + CONST64(0x06F3DDB9DDF65610) /* 394 */, CONST64(0x8EA4D21DB5E148F0) /* 395 */, + CONST64(0x20B0FCE62FCD496F) /* 396 */, CONST64(0x2C1B912358B0EE31) /* 397 */, + CONST64(0xB28317B818F5A308) /* 398 */, CONST64(0xA89C1E189CA6D2CF) /* 399 */, + CONST64(0x0C6B18576AAADBC8) /* 400 */, CONST64(0xB65DEAA91299FAE3) /* 401 */, + CONST64(0xFB2B794B7F1027E7) /* 402 */, CONST64(0x04E4317F443B5BEB) /* 403 */, + CONST64(0x4B852D325939D0A6) /* 404 */, CONST64(0xD5AE6BEEFB207FFC) /* 405 */, + CONST64(0x309682B281C7D374) /* 406 */, CONST64(0xBAE309A194C3B475) /* 407 */, + CONST64(0x8CC3F97B13B49F05) /* 408 */, CONST64(0x98A9422FF8293967) /* 409 */, + CONST64(0x244B16B01076FF7C) /* 410 */, CONST64(0xF8BF571C663D67EE) /* 411 */, + CONST64(0x1F0D6758EEE30DA1) /* 412 */, CONST64(0xC9B611D97ADEB9B7) /* 413 */, + CONST64(0xB7AFD5887B6C57A2) /* 414 */, CONST64(0x6290AE846B984FE1) /* 415 */, + CONST64(0x94DF4CDEACC1A5FD) /* 416 */, CONST64(0x058A5BD1C5483AFF) /* 417 */, + CONST64(0x63166CC142BA3C37) /* 418 */, CONST64(0x8DB8526EB2F76F40) /* 419 */, + CONST64(0xE10880036F0D6D4E) /* 420 */, CONST64(0x9E0523C9971D311D) /* 421 */, + CONST64(0x45EC2824CC7CD691) /* 422 */, CONST64(0x575B8359E62382C9) /* 423 */, + CONST64(0xFA9E400DC4889995) /* 424 */, CONST64(0xD1823ECB45721568) /* 425 */, + CONST64(0xDAFD983B8206082F) /* 426 */, CONST64(0xAA7D29082386A8CB) /* 427 */, + CONST64(0x269FCD4403B87588) /* 428 */, CONST64(0x1B91F5F728BDD1E0) /* 429 */, + CONST64(0xE4669F39040201F6) /* 430 */, CONST64(0x7A1D7C218CF04ADE) /* 431 */, + CONST64(0x65623C29D79CE5CE) /* 432 */, CONST64(0x2368449096C00BB1) /* 433 */, + CONST64(0xAB9BF1879DA503BA) /* 434 */, CONST64(0xBC23ECB1A458058E) /* 435 */, + CONST64(0x9A58DF01BB401ECC) /* 436 */, CONST64(0xA070E868A85F143D) /* 437 */, + CONST64(0x4FF188307DF2239E) /* 438 */, CONST64(0x14D565B41A641183) /* 439 */, + CONST64(0xEE13337452701602) /* 440 */, CONST64(0x950E3DCF3F285E09) /* 441 */, + CONST64(0x59930254B9C80953) /* 442 */, CONST64(0x3BF299408930DA6D) /* 443 */, + CONST64(0xA955943F53691387) /* 444 */, CONST64(0xA15EDECAA9CB8784) /* 445 */, + CONST64(0x29142127352BE9A0) /* 446 */, CONST64(0x76F0371FFF4E7AFB) /* 447 */, + CONST64(0x0239F450274F2228) /* 448 */, CONST64(0xBB073AF01D5E868B) /* 449 */, + CONST64(0xBFC80571C10E96C1) /* 450 */, CONST64(0xD267088568222E23) /* 451 */, + CONST64(0x9671A3D48E80B5B0) /* 452 */, CONST64(0x55B5D38AE193BB81) /* 453 */, + CONST64(0x693AE2D0A18B04B8) /* 454 */, CONST64(0x5C48B4ECADD5335F) /* 455 */, + CONST64(0xFD743B194916A1CA) /* 456 */, CONST64(0x2577018134BE98C4) /* 457 */, + CONST64(0xE77987E83C54A4AD) /* 458 */, CONST64(0x28E11014DA33E1B9) /* 459 */, + CONST64(0x270CC59E226AA213) /* 460 */, CONST64(0x71495F756D1A5F60) /* 461 */, + CONST64(0x9BE853FB60AFEF77) /* 462 */, CONST64(0xADC786A7F7443DBF) /* 463 */, + CONST64(0x0904456173B29A82) /* 464 */, CONST64(0x58BC7A66C232BD5E) /* 465 */, + CONST64(0xF306558C673AC8B2) /* 466 */, CONST64(0x41F639C6B6C9772A) /* 467 */, + CONST64(0x216DEFE99FDA35DA) /* 468 */, CONST64(0x11640CC71C7BE615) /* 469 */, + CONST64(0x93C43694565C5527) /* 470 */, CONST64(0xEA038E6246777839) /* 471 */, + CONST64(0xF9ABF3CE5A3E2469) /* 472 */, CONST64(0x741E768D0FD312D2) /* 473 */, + CONST64(0x0144B883CED652C6) /* 474 */, CONST64(0xC20B5A5BA33F8552) /* 475 */, + CONST64(0x1AE69633C3435A9D) /* 476 */, CONST64(0x97A28CA4088CFDEC) /* 477 */, + CONST64(0x8824A43C1E96F420) /* 478 */, CONST64(0x37612FA66EEEA746) /* 479 */, + CONST64(0x6B4CB165F9CF0E5A) /* 480 */, CONST64(0x43AA1C06A0ABFB4A) /* 481 */, + CONST64(0x7F4DC26FF162796B) /* 482 */, CONST64(0x6CBACC8E54ED9B0F) /* 483 */, + CONST64(0xA6B7FFEFD2BB253E) /* 484 */, CONST64(0x2E25BC95B0A29D4F) /* 485 */, + CONST64(0x86D6A58BDEF1388C) /* 486 */, CONST64(0xDED74AC576B6F054) /* 487 */, + CONST64(0x8030BDBC2B45805D) /* 488 */, CONST64(0x3C81AF70E94D9289) /* 489 */, + CONST64(0x3EFF6DDA9E3100DB) /* 490 */, CONST64(0xB38DC39FDFCC8847) /* 491 */, + CONST64(0x123885528D17B87E) /* 492 */, CONST64(0xF2DA0ED240B1B642) /* 493 */, + CONST64(0x44CEFADCD54BF9A9) /* 494 */, CONST64(0x1312200E433C7EE6) /* 495 */, + CONST64(0x9FFCC84F3A78C748) /* 496 */, CONST64(0xF0CD1F72248576BB) /* 497 */, + CONST64(0xEC6974053638CFE4) /* 498 */, CONST64(0x2BA7B67C0CEC4E4C) /* 499 */, + CONST64(0xAC2F4DF3E5CE32ED) /* 500 */, CONST64(0xCB33D14326EA4C11) /* 501 */, + CONST64(0xA4E9044CC77E58BC) /* 502 */, CONST64(0x5F513293D934FCEF) /* 503 */, + CONST64(0x5DC9645506E55444) /* 504 */, CONST64(0x50DE418F317DE40A) /* 505 */, + CONST64(0x388CB31A69DDE259) /* 506 */, CONST64(0x2DB4A83455820A86) /* 507 */, + CONST64(0x9010A91E84711AE9) /* 508 */, CONST64(0x4DF7F0B7B1498371) /* 509 */, + CONST64(0xD62A2EABC0977179) /* 510 */, CONST64(0x22FAC097AA8D5C0E) /* 511 */, + CONST64(0xF49FCC2FF1DAF39B) /* 512 */, CONST64(0x487FD5C66FF29281) /* 513 */, + CONST64(0xE8A30667FCDCA83F) /* 514 */, CONST64(0x2C9B4BE3D2FCCE63) /* 515 */, + CONST64(0xDA3FF74B93FBBBC2) /* 516 */, CONST64(0x2FA165D2FE70BA66) /* 517 */, + CONST64(0xA103E279970E93D4) /* 518 */, CONST64(0xBECDEC77B0E45E71) /* 519 */, + CONST64(0xCFB41E723985E497) /* 520 */, CONST64(0xB70AAA025EF75017) /* 521 */, + CONST64(0xD42309F03840B8E0) /* 522 */, CONST64(0x8EFC1AD035898579) /* 523 */, + CONST64(0x96C6920BE2B2ABC5) /* 524 */, CONST64(0x66AF4163375A9172) /* 525 */, + CONST64(0x2174ABDCCA7127FB) /* 526 */, CONST64(0xB33CCEA64A72FF41) /* 527 */, + CONST64(0xF04A4933083066A5) /* 528 */, CONST64(0x8D970ACDD7289AF5) /* 529 */, + CONST64(0x8F96E8E031C8C25E) /* 530 */, CONST64(0xF3FEC02276875D47) /* 531 */, + CONST64(0xEC7BF310056190DD) /* 532 */, CONST64(0xF5ADB0AEBB0F1491) /* 533 */, + CONST64(0x9B50F8850FD58892) /* 534 */, CONST64(0x4975488358B74DE8) /* 535 */, + CONST64(0xA3354FF691531C61) /* 536 */, CONST64(0x0702BBE481D2C6EE) /* 537 */, + CONST64(0x89FB24057DEDED98) /* 538 */, CONST64(0xAC3075138596E902) /* 539 */, + CONST64(0x1D2D3580172772ED) /* 540 */, CONST64(0xEB738FC28E6BC30D) /* 541 */, + CONST64(0x5854EF8F63044326) /* 542 */, CONST64(0x9E5C52325ADD3BBE) /* 543 */, + CONST64(0x90AA53CF325C4623) /* 544 */, CONST64(0xC1D24D51349DD067) /* 545 */, + CONST64(0x2051CFEEA69EA624) /* 546 */, CONST64(0x13220F0A862E7E4F) /* 547 */, + CONST64(0xCE39399404E04864) /* 548 */, CONST64(0xD9C42CA47086FCB7) /* 549 */, + CONST64(0x685AD2238A03E7CC) /* 550 */, CONST64(0x066484B2AB2FF1DB) /* 551 */, + CONST64(0xFE9D5D70EFBF79EC) /* 552 */, CONST64(0x5B13B9DD9C481854) /* 553 */, + CONST64(0x15F0D475ED1509AD) /* 554 */, CONST64(0x0BEBCD060EC79851) /* 555 */, + CONST64(0xD58C6791183AB7F8) /* 556 */, CONST64(0xD1187C5052F3EEE4) /* 557 */, + CONST64(0xC95D1192E54E82FF) /* 558 */, CONST64(0x86EEA14CB9AC6CA2) /* 559 */, + CONST64(0x3485BEB153677D5D) /* 560 */, CONST64(0xDD191D781F8C492A) /* 561 */, + CONST64(0xF60866BAA784EBF9) /* 562 */, CONST64(0x518F643BA2D08C74) /* 563 */, + CONST64(0x8852E956E1087C22) /* 564 */, CONST64(0xA768CB8DC410AE8D) /* 565 */, + CONST64(0x38047726BFEC8E1A) /* 566 */, CONST64(0xA67738B4CD3B45AA) /* 567 */, + CONST64(0xAD16691CEC0DDE19) /* 568 */, CONST64(0xC6D4319380462E07) /* 569 */, + CONST64(0xC5A5876D0BA61938) /* 570 */, CONST64(0x16B9FA1FA58FD840) /* 571 */, + CONST64(0x188AB1173CA74F18) /* 572 */, CONST64(0xABDA2F98C99C021F) /* 573 */, + CONST64(0x3E0580AB134AE816) /* 574 */, CONST64(0x5F3B05B773645ABB) /* 575 */, + CONST64(0x2501A2BE5575F2F6) /* 576 */, CONST64(0x1B2F74004E7E8BA9) /* 577 */, + CONST64(0x1CD7580371E8D953) /* 578 */, CONST64(0x7F6ED89562764E30) /* 579 */, + CONST64(0xB15926FF596F003D) /* 580 */, CONST64(0x9F65293DA8C5D6B9) /* 581 */, + CONST64(0x6ECEF04DD690F84C) /* 582 */, CONST64(0x4782275FFF33AF88) /* 583 */, + CONST64(0xE41433083F820801) /* 584 */, CONST64(0xFD0DFE409A1AF9B5) /* 585 */, + CONST64(0x4325A3342CDB396B) /* 586 */, CONST64(0x8AE77E62B301B252) /* 587 */, + CONST64(0xC36F9E9F6655615A) /* 588 */, CONST64(0x85455A2D92D32C09) /* 589 */, + CONST64(0xF2C7DEA949477485) /* 590 */, CONST64(0x63CFB4C133A39EBA) /* 591 */, + CONST64(0x83B040CC6EBC5462) /* 592 */, CONST64(0x3B9454C8FDB326B0) /* 593 */, + CONST64(0x56F56A9E87FFD78C) /* 594 */, CONST64(0x2DC2940D99F42BC6) /* 595 */, + CONST64(0x98F7DF096B096E2D) /* 596 */, CONST64(0x19A6E01E3AD852BF) /* 597 */, + CONST64(0x42A99CCBDBD4B40B) /* 598 */, CONST64(0xA59998AF45E9C559) /* 599 */, + CONST64(0x366295E807D93186) /* 600 */, CONST64(0x6B48181BFAA1F773) /* 601 */, + CONST64(0x1FEC57E2157A0A1D) /* 602 */, CONST64(0x4667446AF6201AD5) /* 603 */, + CONST64(0xE615EBCACFB0F075) /* 604 */, CONST64(0xB8F31F4F68290778) /* 605 */, + CONST64(0x22713ED6CE22D11E) /* 606 */, CONST64(0x3057C1A72EC3C93B) /* 607 */, + CONST64(0xCB46ACC37C3F1F2F) /* 608 */, CONST64(0xDBB893FD02AAF50E) /* 609 */, + CONST64(0x331FD92E600B9FCF) /* 610 */, CONST64(0xA498F96148EA3AD6) /* 611 */, + CONST64(0xA8D8426E8B6A83EA) /* 612 */, CONST64(0xA089B274B7735CDC) /* 613 */, + CONST64(0x87F6B3731E524A11) /* 614 */, CONST64(0x118808E5CBC96749) /* 615 */, + CONST64(0x9906E4C7B19BD394) /* 616 */, CONST64(0xAFED7F7E9B24A20C) /* 617 */, + CONST64(0x6509EADEEB3644A7) /* 618 */, CONST64(0x6C1EF1D3E8EF0EDE) /* 619 */, + CONST64(0xB9C97D43E9798FB4) /* 620 */, CONST64(0xA2F2D784740C28A3) /* 621 */, + CONST64(0x7B8496476197566F) /* 622 */, CONST64(0x7A5BE3E6B65F069D) /* 623 */, + CONST64(0xF96330ED78BE6F10) /* 624 */, CONST64(0xEEE60DE77A076A15) /* 625 */, + CONST64(0x2B4BEE4AA08B9BD0) /* 626 */, CONST64(0x6A56A63EC7B8894E) /* 627 */, + CONST64(0x02121359BA34FEF4) /* 628 */, CONST64(0x4CBF99F8283703FC) /* 629 */, + CONST64(0x398071350CAF30C8) /* 630 */, CONST64(0xD0A77A89F017687A) /* 631 */, + CONST64(0xF1C1A9EB9E423569) /* 632 */, CONST64(0x8C7976282DEE8199) /* 633 */, + CONST64(0x5D1737A5DD1F7ABD) /* 634 */, CONST64(0x4F53433C09A9FA80) /* 635 */, + CONST64(0xFA8B0C53DF7CA1D9) /* 636 */, CONST64(0x3FD9DCBC886CCB77) /* 637 */, + CONST64(0xC040917CA91B4720) /* 638 */, CONST64(0x7DD00142F9D1DCDF) /* 639 */, + CONST64(0x8476FC1D4F387B58) /* 640 */, CONST64(0x23F8E7C5F3316503) /* 641 */, + CONST64(0x032A2244E7E37339) /* 642 */, CONST64(0x5C87A5D750F5A74B) /* 643 */, + CONST64(0x082B4CC43698992E) /* 644 */, CONST64(0xDF917BECB858F63C) /* 645 */, + CONST64(0x3270B8FC5BF86DDA) /* 646 */, CONST64(0x10AE72BB29B5DD76) /* 647 */, + CONST64(0x576AC94E7700362B) /* 648 */, CONST64(0x1AD112DAC61EFB8F) /* 649 */, + CONST64(0x691BC30EC5FAA427) /* 650 */, CONST64(0xFF246311CC327143) /* 651 */, + CONST64(0x3142368E30E53206) /* 652 */, CONST64(0x71380E31E02CA396) /* 653 */, + CONST64(0x958D5C960AAD76F1) /* 654 */, CONST64(0xF8D6F430C16DA536) /* 655 */, + CONST64(0xC8FFD13F1BE7E1D2) /* 656 */, CONST64(0x7578AE66004DDBE1) /* 657 */, + CONST64(0x05833F01067BE646) /* 658 */, CONST64(0xBB34B5AD3BFE586D) /* 659 */, + CONST64(0x095F34C9A12B97F0) /* 660 */, CONST64(0x247AB64525D60CA8) /* 661 */, + CONST64(0xDCDBC6F3017477D1) /* 662 */, CONST64(0x4A2E14D4DECAD24D) /* 663 */, + CONST64(0xBDB5E6D9BE0A1EEB) /* 664 */, CONST64(0x2A7E70F7794301AB) /* 665 */, + CONST64(0xDEF42D8A270540FD) /* 666 */, CONST64(0x01078EC0A34C22C1) /* 667 */, + CONST64(0xE5DE511AF4C16387) /* 668 */, CONST64(0x7EBB3A52BD9A330A) /* 669 */, + CONST64(0x77697857AA7D6435) /* 670 */, CONST64(0x004E831603AE4C32) /* 671 */, + CONST64(0xE7A21020AD78E312) /* 672 */, CONST64(0x9D41A70C6AB420F2) /* 673 */, + CONST64(0x28E06C18EA1141E6) /* 674 */, CONST64(0xD2B28CBD984F6B28) /* 675 */, + CONST64(0x26B75F6C446E9D83) /* 676 */, CONST64(0xBA47568C4D418D7F) /* 677 */, + CONST64(0xD80BADBFE6183D8E) /* 678 */, CONST64(0x0E206D7F5F166044) /* 679 */, + CONST64(0xE258A43911CBCA3E) /* 680 */, CONST64(0x723A1746B21DC0BC) /* 681 */, + CONST64(0xC7CAA854F5D7CDD3) /* 682 */, CONST64(0x7CAC32883D261D9C) /* 683 */, + CONST64(0x7690C26423BA942C) /* 684 */, CONST64(0x17E55524478042B8) /* 685 */, + CONST64(0xE0BE477656A2389F) /* 686 */, CONST64(0x4D289B5E67AB2DA0) /* 687 */, + CONST64(0x44862B9C8FBBFD31) /* 688 */, CONST64(0xB47CC8049D141365) /* 689 */, + CONST64(0x822C1B362B91C793) /* 690 */, CONST64(0x4EB14655FB13DFD8) /* 691 */, + CONST64(0x1ECBBA0714E2A97B) /* 692 */, CONST64(0x6143459D5CDE5F14) /* 693 */, + CONST64(0x53A8FBF1D5F0AC89) /* 694 */, CONST64(0x97EA04D81C5E5B00) /* 695 */, + CONST64(0x622181A8D4FDB3F3) /* 696 */, CONST64(0xE9BCD341572A1208) /* 697 */, + CONST64(0x1411258643CCE58A) /* 698 */, CONST64(0x9144C5FEA4C6E0A4) /* 699 */, + CONST64(0x0D33D06565CF620F) /* 700 */, CONST64(0x54A48D489F219CA1) /* 701 */, + CONST64(0xC43E5EAC6D63C821) /* 702 */, CONST64(0xA9728B3A72770DAF) /* 703 */, + CONST64(0xD7934E7B20DF87EF) /* 704 */, CONST64(0xE35503B61A3E86E5) /* 705 */, + CONST64(0xCAE321FBC819D504) /* 706 */, CONST64(0x129A50B3AC60BFA6) /* 707 */, + CONST64(0xCD5E68EA7E9FB6C3) /* 708 */, CONST64(0xB01C90199483B1C7) /* 709 */, + CONST64(0x3DE93CD5C295376C) /* 710 */, CONST64(0xAED52EDF2AB9AD13) /* 711 */, + CONST64(0x2E60F512C0A07884) /* 712 */, CONST64(0xBC3D86A3E36210C9) /* 713 */, + CONST64(0x35269D9B163951CE) /* 714 */, CONST64(0x0C7D6E2AD0CDB5FA) /* 715 */, + CONST64(0x59E86297D87F5733) /* 716 */, CONST64(0x298EF221898DB0E7) /* 717 */, + CONST64(0x55000029D1A5AA7E) /* 718 */, CONST64(0x8BC08AE1B5061B45) /* 719 */, + CONST64(0xC2C31C2B6C92703A) /* 720 */, CONST64(0x94CC596BAF25EF42) /* 721 */, + CONST64(0x0A1D73DB22540456) /* 722 */, CONST64(0x04B6A0F9D9C4179A) /* 723 */, + CONST64(0xEFFDAFA2AE3D3C60) /* 724 */, CONST64(0xF7C8075BB49496C4) /* 725 */, + CONST64(0x9CC5C7141D1CD4E3) /* 726 */, CONST64(0x78BD1638218E5534) /* 727 */, + CONST64(0xB2F11568F850246A) /* 728 */, CONST64(0xEDFABCFA9502BC29) /* 729 */, + CONST64(0x796CE5F2DA23051B) /* 730 */, CONST64(0xAAE128B0DC93537C) /* 731 */, + CONST64(0x3A493DA0EE4B29AE) /* 732 */, CONST64(0xB5DF6B2C416895D7) /* 733 */, + CONST64(0xFCABBD25122D7F37) /* 734 */, CONST64(0x70810B58105DC4B1) /* 735 */, + CONST64(0xE10FDD37F7882A90) /* 736 */, CONST64(0x524DCAB5518A3F5C) /* 737 */, + CONST64(0x3C9E85878451255B) /* 738 */, CONST64(0x4029828119BD34E2) /* 739 */, + CONST64(0x74A05B6F5D3CECCB) /* 740 */, CONST64(0xB610021542E13ECA) /* 741 */, + CONST64(0x0FF979D12F59E2AC) /* 742 */, CONST64(0x6037DA27E4F9CC50) /* 743 */, + CONST64(0x5E92975A0DF1847D) /* 744 */, CONST64(0xD66DE190D3E623FE) /* 745 */, + CONST64(0x5032D6B87B568048) /* 746 */, CONST64(0x9A36B7CE8235216E) /* 747 */, + CONST64(0x80272A7A24F64B4A) /* 748 */, CONST64(0x93EFED8B8C6916F7) /* 749 */, + CONST64(0x37DDBFF44CCE1555) /* 750 */, CONST64(0x4B95DB5D4B99BD25) /* 751 */, + CONST64(0x92D3FDA169812FC0) /* 752 */, CONST64(0xFB1A4A9A90660BB6) /* 753 */, + CONST64(0x730C196946A4B9B2) /* 754 */, CONST64(0x81E289AA7F49DA68) /* 755 */, + CONST64(0x64669A0F83B1A05F) /* 756 */, CONST64(0x27B3FF7D9644F48B) /* 757 */, + CONST64(0xCC6B615C8DB675B3) /* 758 */, CONST64(0x674F20B9BCEBBE95) /* 759 */, + CONST64(0x6F31238275655982) /* 760 */, CONST64(0x5AE488713E45CF05) /* 761 */, + CONST64(0xBF619F9954C21157) /* 762 */, CONST64(0xEABAC46040A8EAE9) /* 763 */, + CONST64(0x454C6FE9F2C0C1CD) /* 764 */, CONST64(0x419CF6496412691C) /* 765 */, + CONST64(0xD3DC3BEF265B0F70) /* 766 */, CONST64(0x6D0E60F5C3578A9E) /* 767 */, + CONST64(0x5B0E608526323C55) /* 768 */, CONST64(0x1A46C1A9FA1B59F5) /* 769 */, + CONST64(0xA9E245A17C4C8FFA) /* 770 */, CONST64(0x65CA5159DB2955D7) /* 771 */, + CONST64(0x05DB0A76CE35AFC2) /* 772 */, CONST64(0x81EAC77EA9113D45) /* 773 */, + CONST64(0x528EF88AB6AC0A0D) /* 774 */, CONST64(0xA09EA253597BE3FF) /* 775 */, + CONST64(0x430DDFB3AC48CD56) /* 776 */, CONST64(0xC4B3A67AF45CE46F) /* 777 */, + CONST64(0x4ECECFD8FBE2D05E) /* 778 */, CONST64(0x3EF56F10B39935F0) /* 779 */, + CONST64(0x0B22D6829CD619C6) /* 780 */, CONST64(0x17FD460A74DF2069) /* 781 */, + CONST64(0x6CF8CC8E8510ED40) /* 782 */, CONST64(0xD6C824BF3A6ECAA7) /* 783 */, + CONST64(0x61243D581A817049) /* 784 */, CONST64(0x048BACB6BBC163A2) /* 785 */, + CONST64(0xD9A38AC27D44CC32) /* 786 */, CONST64(0x7FDDFF5BAAF410AB) /* 787 */, + CONST64(0xAD6D495AA804824B) /* 788 */, CONST64(0xE1A6A74F2D8C9F94) /* 789 */, + CONST64(0xD4F7851235DEE8E3) /* 790 */, CONST64(0xFD4B7F886540D893) /* 791 */, + CONST64(0x247C20042AA4BFDA) /* 792 */, CONST64(0x096EA1C517D1327C) /* 793 */, + CONST64(0xD56966B4361A6685) /* 794 */, CONST64(0x277DA5C31221057D) /* 795 */, + CONST64(0x94D59893A43ACFF7) /* 796 */, CONST64(0x64F0C51CCDC02281) /* 797 */, + CONST64(0x3D33BCC4FF6189DB) /* 798 */, CONST64(0xE005CB184CE66AF1) /* 799 */, + CONST64(0xFF5CCD1D1DB99BEA) /* 800 */, CONST64(0xB0B854A7FE42980F) /* 801 */, + CONST64(0x7BD46A6A718D4B9F) /* 802 */, CONST64(0xD10FA8CC22A5FD8C) /* 803 */, + CONST64(0xD31484952BE4BD31) /* 804 */, CONST64(0xC7FA975FCB243847) /* 805 */, + CONST64(0x4886ED1E5846C407) /* 806 */, CONST64(0x28CDDB791EB70B04) /* 807 */, + CONST64(0xC2B00BE2F573417F) /* 808 */, CONST64(0x5C9590452180F877) /* 809 */, + CONST64(0x7A6BDDFFF370EB00) /* 810 */, CONST64(0xCE509E38D6D9D6A4) /* 811 */, + CONST64(0xEBEB0F00647FA702) /* 812 */, CONST64(0x1DCC06CF76606F06) /* 813 */, + CONST64(0xE4D9F28BA286FF0A) /* 814 */, CONST64(0xD85A305DC918C262) /* 815 */, + CONST64(0x475B1D8732225F54) /* 816 */, CONST64(0x2D4FB51668CCB5FE) /* 817 */, + CONST64(0xA679B9D9D72BBA20) /* 818 */, CONST64(0x53841C0D912D43A5) /* 819 */, + CONST64(0x3B7EAA48BF12A4E8) /* 820 */, CONST64(0x781E0E47F22F1DDF) /* 821 */, + CONST64(0xEFF20CE60AB50973) /* 822 */, CONST64(0x20D261D19DFFB742) /* 823 */, + CONST64(0x16A12B03062A2E39) /* 824 */, CONST64(0x1960EB2239650495) /* 825 */, + CONST64(0x251C16FED50EB8B8) /* 826 */, CONST64(0x9AC0C330F826016E) /* 827 */, + CONST64(0xED152665953E7671) /* 828 */, CONST64(0x02D63194A6369570) /* 829 */, + CONST64(0x5074F08394B1C987) /* 830 */, CONST64(0x70BA598C90B25CE1) /* 831 */, + CONST64(0x794A15810B9742F6) /* 832 */, CONST64(0x0D5925E9FCAF8C6C) /* 833 */, + CONST64(0x3067716CD868744E) /* 834 */, CONST64(0x910AB077E8D7731B) /* 835 */, + CONST64(0x6A61BBDB5AC42F61) /* 836 */, CONST64(0x93513EFBF0851567) /* 837 */, + CONST64(0xF494724B9E83E9D5) /* 838 */, CONST64(0xE887E1985C09648D) /* 839 */, + CONST64(0x34B1D3C675370CFD) /* 840 */, CONST64(0xDC35E433BC0D255D) /* 841 */, + CONST64(0xD0AAB84234131BE0) /* 842 */, CONST64(0x08042A50B48B7EAF) /* 843 */, + CONST64(0x9997C4EE44A3AB35) /* 844 */, CONST64(0x829A7B49201799D0) /* 845 */, + CONST64(0x263B8307B7C54441) /* 846 */, CONST64(0x752F95F4FD6A6CA6) /* 847 */, + CONST64(0x927217402C08C6E5) /* 848 */, CONST64(0x2A8AB754A795D9EE) /* 849 */, + CONST64(0xA442F7552F72943D) /* 850 */, CONST64(0x2C31334E19781208) /* 851 */, + CONST64(0x4FA98D7CEAEE6291) /* 852 */, CONST64(0x55C3862F665DB309) /* 853 */, + CONST64(0xBD0610175D53B1F3) /* 854 */, CONST64(0x46FE6CB840413F27) /* 855 */, + CONST64(0x3FE03792DF0CFA59) /* 856 */, CONST64(0xCFE700372EB85E8F) /* 857 */, + CONST64(0xA7BE29E7ADBCE118) /* 858 */, CONST64(0xE544EE5CDE8431DD) /* 859 */, + CONST64(0x8A781B1B41F1873E) /* 860 */, CONST64(0xA5C94C78A0D2F0E7) /* 861 */, + CONST64(0x39412E2877B60728) /* 862 */, CONST64(0xA1265EF3AFC9A62C) /* 863 */, + CONST64(0xBCC2770C6A2506C5) /* 864 */, CONST64(0x3AB66DD5DCE1CE12) /* 865 */, + CONST64(0xE65499D04A675B37) /* 866 */, CONST64(0x7D8F523481BFD216) /* 867 */, + CONST64(0x0F6F64FCEC15F389) /* 868 */, CONST64(0x74EFBE618B5B13C8) /* 869 */, + CONST64(0xACDC82B714273E1D) /* 870 */, CONST64(0xDD40BFE003199D17) /* 871 */, + CONST64(0x37E99257E7E061F8) /* 872 */, CONST64(0xFA52626904775AAA) /* 873 */, + CONST64(0x8BBBF63A463D56F9) /* 874 */, CONST64(0xF0013F1543A26E64) /* 875 */, + CONST64(0xA8307E9F879EC898) /* 876 */, CONST64(0xCC4C27A4150177CC) /* 877 */, + CONST64(0x1B432F2CCA1D3348) /* 878 */, CONST64(0xDE1D1F8F9F6FA013) /* 879 */, + CONST64(0x606602A047A7DDD6) /* 880 */, CONST64(0xD237AB64CC1CB2C7) /* 881 */, + CONST64(0x9B938E7225FCD1D3) /* 882 */, CONST64(0xEC4E03708E0FF476) /* 883 */, + CONST64(0xFEB2FBDA3D03C12D) /* 884 */, CONST64(0xAE0BCED2EE43889A) /* 885 */, + CONST64(0x22CB8923EBFB4F43) /* 886 */, CONST64(0x69360D013CF7396D) /* 887 */, + CONST64(0x855E3602D2D4E022) /* 888 */, CONST64(0x073805BAD01F784C) /* 889 */, + CONST64(0x33E17A133852F546) /* 890 */, CONST64(0xDF4874058AC7B638) /* 891 */, + CONST64(0xBA92B29C678AA14A) /* 892 */, CONST64(0x0CE89FC76CFAADCD) /* 893 */, + CONST64(0x5F9D4E0908339E34) /* 894 */, CONST64(0xF1AFE9291F5923B9) /* 895 */, + CONST64(0x6E3480F60F4A265F) /* 896 */, CONST64(0xEEBF3A2AB29B841C) /* 897 */, + CONST64(0xE21938A88F91B4AD) /* 898 */, CONST64(0x57DFEFF845C6D3C3) /* 899 */, + CONST64(0x2F006B0BF62CAAF2) /* 900 */, CONST64(0x62F479EF6F75EE78) /* 901 */, + CONST64(0x11A55AD41C8916A9) /* 902 */, CONST64(0xF229D29084FED453) /* 903 */, + CONST64(0x42F1C27B16B000E6) /* 904 */, CONST64(0x2B1F76749823C074) /* 905 */, + CONST64(0x4B76ECA3C2745360) /* 906 */, CONST64(0x8C98F463B91691BD) /* 907 */, + CONST64(0x14BCC93CF1ADE66A) /* 908 */, CONST64(0x8885213E6D458397) /* 909 */, + CONST64(0x8E177DF0274D4711) /* 910 */, CONST64(0xB49B73B5503F2951) /* 911 */, + CONST64(0x10168168C3F96B6B) /* 912 */, CONST64(0x0E3D963B63CAB0AE) /* 913 */, + CONST64(0x8DFC4B5655A1DB14) /* 914 */, CONST64(0xF789F1356E14DE5C) /* 915 */, + CONST64(0x683E68AF4E51DAC1) /* 916 */, CONST64(0xC9A84F9D8D4B0FD9) /* 917 */, + CONST64(0x3691E03F52A0F9D1) /* 918 */, CONST64(0x5ED86E46E1878E80) /* 919 */, + CONST64(0x3C711A0E99D07150) /* 920 */, CONST64(0x5A0865B20C4E9310) /* 921 */, + CONST64(0x56FBFC1FE4F0682E) /* 922 */, CONST64(0xEA8D5DE3105EDF9B) /* 923 */, + CONST64(0x71ABFDB12379187A) /* 924 */, CONST64(0x2EB99DE1BEE77B9C) /* 925 */, + CONST64(0x21ECC0EA33CF4523) /* 926 */, CONST64(0x59A4D7521805C7A1) /* 927 */, + CONST64(0x3896F5EB56AE7C72) /* 928 */, CONST64(0xAA638F3DB18F75DC) /* 929 */, + CONST64(0x9F39358DABE9808E) /* 930 */, CONST64(0xB7DEFA91C00B72AC) /* 931 */, + CONST64(0x6B5541FD62492D92) /* 932 */, CONST64(0x6DC6DEE8F92E4D5B) /* 933 */, + CONST64(0x353F57ABC4BEEA7E) /* 934 */, CONST64(0x735769D6DA5690CE) /* 935 */, + CONST64(0x0A234AA642391484) /* 936 */, CONST64(0xF6F9508028F80D9D) /* 937 */, + CONST64(0xB8E319A27AB3F215) /* 938 */, CONST64(0x31AD9C1151341A4D) /* 939 */, + CONST64(0x773C22A57BEF5805) /* 940 */, CONST64(0x45C7561A07968633) /* 941 */, + CONST64(0xF913DA9E249DBE36) /* 942 */, CONST64(0xDA652D9B78A64C68) /* 943 */, + CONST64(0x4C27A97F3BC334EF) /* 944 */, CONST64(0x76621220E66B17F4) /* 945 */, + CONST64(0x967743899ACD7D0B) /* 946 */, CONST64(0xF3EE5BCAE0ED6782) /* 947 */, + CONST64(0x409F753600C879FC) /* 948 */, CONST64(0x06D09A39B5926DB6) /* 949 */, + CONST64(0x6F83AEB0317AC588) /* 950 */, CONST64(0x01E6CA4A86381F21) /* 951 */, + CONST64(0x66FF3462D19F3025) /* 952 */, CONST64(0x72207C24DDFD3BFB) /* 953 */, + CONST64(0x4AF6B6D3E2ECE2EB) /* 954 */, CONST64(0x9C994DBEC7EA08DE) /* 955 */, + CONST64(0x49ACE597B09A8BC4) /* 956 */, CONST64(0xB38C4766CF0797BA) /* 957 */, + CONST64(0x131B9373C57C2A75) /* 958 */, CONST64(0xB1822CCE61931E58) /* 959 */, + CONST64(0x9D7555B909BA1C0C) /* 960 */, CONST64(0x127FAFDD937D11D2) /* 961 */, + CONST64(0x29DA3BADC66D92E4) /* 962 */, CONST64(0xA2C1D57154C2ECBC) /* 963 */, + CONST64(0x58C5134D82F6FE24) /* 964 */, CONST64(0x1C3AE3515B62274F) /* 965 */, + CONST64(0xE907C82E01CB8126) /* 966 */, CONST64(0xF8ED091913E37FCB) /* 967 */, + CONST64(0x3249D8F9C80046C9) /* 968 */, CONST64(0x80CF9BEDE388FB63) /* 969 */, + CONST64(0x1881539A116CF19E) /* 970 */, CONST64(0x5103F3F76BD52457) /* 971 */, + CONST64(0x15B7E6F5AE47F7A8) /* 972 */, CONST64(0xDBD7C6DED47E9CCF) /* 973 */, + CONST64(0x44E55C410228BB1A) /* 974 */, CONST64(0xB647D4255EDB4E99) /* 975 */, + CONST64(0x5D11882BB8AAFC30) /* 976 */, CONST64(0xF5098BBB29D3212A) /* 977 */, + CONST64(0x8FB5EA14E90296B3) /* 978 */, CONST64(0x677B942157DD025A) /* 979 */, + CONST64(0xFB58E7C0A390ACB5) /* 980 */, CONST64(0x89D3674C83BD4A01) /* 981 */, + CONST64(0x9E2DA4DF4BF3B93B) /* 982 */, CONST64(0xFCC41E328CAB4829) /* 983 */, + CONST64(0x03F38C96BA582C52) /* 984 */, CONST64(0xCAD1BDBD7FD85DB2) /* 985 */, + CONST64(0xBBB442C16082AE83) /* 986 */, CONST64(0xB95FE86BA5DA9AB0) /* 987 */, + CONST64(0xB22E04673771A93F) /* 988 */, CONST64(0x845358C9493152D8) /* 989 */, + CONST64(0xBE2A488697B4541E) /* 990 */, CONST64(0x95A2DC2DD38E6966) /* 991 */, + CONST64(0xC02C11AC923C852B) /* 992 */, CONST64(0x2388B1990DF2A87B) /* 993 */, + CONST64(0x7C8008FA1B4F37BE) /* 994 */, CONST64(0x1F70D0C84D54E503) /* 995 */, + CONST64(0x5490ADEC7ECE57D4) /* 996 */, CONST64(0x002B3C27D9063A3A) /* 997 */, + CONST64(0x7EAEA3848030A2BF) /* 998 */, CONST64(0xC602326DED2003C0) /* 999 */, + CONST64(0x83A7287D69A94086) /* 1000 */, CONST64(0xC57A5FCB30F57A8A) /* 1001 */, + CONST64(0xB56844E479EBE779) /* 1002 */, CONST64(0xA373B40F05DCBCE9) /* 1003 */, + CONST64(0xD71A786E88570EE2) /* 1004 */, CONST64(0x879CBACDBDE8F6A0) /* 1005 */, + CONST64(0x976AD1BCC164A32F) /* 1006 */, CONST64(0xAB21E25E9666D78B) /* 1007 */, + CONST64(0x901063AAE5E5C33C) /* 1008 */, CONST64(0x9818B34448698D90) /* 1009 */, + CONST64(0xE36487AE3E1E8ABB) /* 1010 */, CONST64(0xAFBDF931893BDCB4) /* 1011 */, + CONST64(0x6345A0DC5FBBD519) /* 1012 */, CONST64(0x8628FE269B9465CA) /* 1013 */, + CONST64(0x1E5D01603F9C51EC) /* 1014 */, CONST64(0x4DE44006A15049B7) /* 1015 */, + CONST64(0xBF6C70E5F776CBB1) /* 1016 */, CONST64(0x411218F2EF552BED) /* 1017 */, + CONST64(0xCB0C0708705A36A3) /* 1018 */, CONST64(0xE74D14754F986044) /* 1019 */, + CONST64(0xCD56D9430EA8280E) /* 1020 */, CONST64(0xC12591D7535F5065) /* 1021 */, + CONST64(0xC83223F1720AEF96) /* 1022 */, CONST64(0xC3A0396F7363A51F) /* 1023 */}; + +/* one round of the hash function */ +LTC_INLINE static void tiger_round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, int mul) +{ + ulong64 tmp; + tmp = (*c ^= x); + *a -= t1[LTC_BYTE(tmp, 0)] ^ t2[LTC_BYTE(tmp, 2)] ^ t3[LTC_BYTE(tmp, 4)] ^ t4[LTC_BYTE(tmp, 6)]; + tmp = (*b += t4[LTC_BYTE(tmp, 1)] ^ t3[LTC_BYTE(tmp, 3)] ^ t2[LTC_BYTE(tmp,5)] ^ t1[LTC_BYTE(tmp,7)]); + switch (mul) { + case 5: *b = (tmp << 2) + tmp; break; + case 7: *b = (tmp << 3) - tmp; break; + case 9: *b = (tmp << 3) + tmp; break; + } +} + +/* one complete pass */ +static void s_pass(ulong64 *a, ulong64 *b, ulong64 *c, const ulong64 *x, int mul) +{ + tiger_round(a,b,c,x[0],mul); + tiger_round(b,c,a,x[1],mul); + tiger_round(c,a,b,x[2],mul); + tiger_round(a,b,c,x[3],mul); + tiger_round(b,c,a,x[4],mul); + tiger_round(c,a,b,x[5],mul); + tiger_round(a,b,c,x[6],mul); + tiger_round(b,c,a,x[7],mul); +} + +/* The key mixing schedule */ +static void s_key_schedule(ulong64 *x) +{ + x[0] -= x[7] ^ CONST64(0xA5A5A5A5A5A5A5A5); + x[1] ^= x[0]; + x[2] += x[1]; + x[3] -= x[2] ^ ((~x[1])<<19); + x[4] ^= x[3]; + x[5] += x[4]; + x[6] -= x[5] ^ ((~x[4])>>23); + x[7] ^= x[6]; + x[0] += x[7]; + x[1] -= x[0] ^ ((~x[7])<<19); + x[2] ^= x[1]; + x[3] += x[2]; + x[4] -= x[3] ^ ((~x[2])>>23); + x[5] ^= x[4]; + x[6] += x[5]; + x[7] -= x[6] ^ CONST64(0x0123456789ABCDEF); +} + +#ifdef LTC_CLEAN_STACK +static int ss_tiger_compress(hash_state *md, const unsigned char *buf) +#else +static int s_tiger_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong64 a, b, c, x[8]; + unsigned long i; + + /* load words */ + for (i = 0; i < 8; i++) { + LOAD64L(x[i],&buf[8*i]); + } + a = md->tiger.state[0]; + b = md->tiger.state[1]; + c = md->tiger.state[2]; + + s_pass(&a,&b,&c,x,5); + s_key_schedule(x); + s_pass(&c,&a,&b,x,7); + s_key_schedule(x); + s_pass(&b,&c,&a,x,9); + + /* store state */ + md->tiger.state[0] = a ^ md->tiger.state[0]; + md->tiger.state[1] = b - md->tiger.state[1]; + md->tiger.state[2] = c + md->tiger.state[2]; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_tiger_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_tiger_compress(md, buf); + burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int tiger_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + md->tiger.state[0] = CONST64(0x0123456789ABCDEF); + md->tiger.state[1] = CONST64(0xFEDCBA9876543210); + md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187); + md->tiger.curlen = 0; + md->tiger.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(tiger_process, s_tiger_compress, tiger, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (24 bytes) + @return CRYPT_OK if successful +*/ +int tiger_done(hash_state * md, unsigned char *out) +{ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->tiger.curlen >= sizeof(md->tiger.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->tiger.length += md->tiger.curlen * 8; + + /* append the '1' bit */ + md->tiger.buf[md->tiger.curlen++] = (unsigned char)0x01; + + /* 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->tiger.curlen > 56) { + while (md->tiger.curlen < 64) { + md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; + } + s_tiger_compress(md, md->tiger.buf); + md->tiger.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->tiger.curlen < 56) { + md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->tiger.length, md->tiger.buf+56); + s_tiger_compress(md, md->tiger.buf); + + /* copy output */ + STORE64L(md->tiger.state[0], &out[0]); + STORE64L(md->tiger.state[1], &out[8]); + STORE64L(md->tiger.state[2], &out[16]); +#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 tiger_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[24]; + } tests[] = { + { "", + { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24, + 0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16, + 0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 } + }, + { "abc", + { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2, + 0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52, + 0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 } + }, + { "Tiger", + { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f, + 0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27, + 0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87, + 0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47, + 0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00, + 0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76, + 0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 } + }, + }; + + int i; + unsigned char tmp[24]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + tiger_init(&md); + tiger_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + tiger_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "TIGER", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + +/* +Hash of "": + 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A +Hash of "abc": + F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 +Hash of "Tiger": + 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF +Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-": + 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 +Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789": + 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 +Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham": + 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 +Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.": + EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 +Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.": + 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC +Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-": + 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 +*/ + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirl.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirl.c new file mode 100644 index 0000000..da7db9c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirl.c @@ -0,0 +1,296 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file whirl.c + LTC_WHIRLPOOL (using their new sbox) hash function by Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_WHIRLPOOL + +const struct ltc_hash_descriptor whirlpool_desc = +{ + "whirlpool", + 11, + 64, + 64, + + /* OID */ + { 1, 0, 10118, 3, 0, 55 }, + 6, + + &whirlpool_init, + &whirlpool_process, + &whirlpool_done, + &whirlpool_test, + NULL +}; + +/* the sboxes */ +#define LTC_WHIRLTAB_C +#include "whirltab.c" + +/* get a_{i,j} */ +#define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255) + +/* shortcut macro to perform three functions at once */ +#define theta_pi_gamma(a, i) \ + (SB0(GB(a, i-0, 7)) ^ \ + SB1(GB(a, i-1, 6)) ^ \ + SB2(GB(a, i-2, 5)) ^ \ + SB3(GB(a, i-3, 4)) ^ \ + SB4(GB(a, i-4, 3)) ^ \ + SB5(GB(a, i-5, 2)) ^ \ + SB6(GB(a, i-6, 1)) ^ \ + SB7(GB(a, i-7, 0))) + +#ifdef LTC_CLEAN_STACK +static int ss_whirlpool_compress(hash_state *md, const unsigned char *buf) +#else +static int s_whirlpool_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong64 K[2][8], T[3][8]; + int x, y; + + /* load the block/state */ + for (x = 0; x < 8; x++) { + K[0][x] = md->whirlpool.state[x]; + + LOAD64H(T[0][x], buf + (8 * x)); + T[2][x] = T[0][x]; + T[0][x] ^= K[0][x]; + } + + /* do rounds 1..10 */ + for (x = 0; x < 10; x += 2) { + /* odd round */ + /* apply main transform to K[0] into K[1] */ + for (y = 0; y < 8; y++) { + K[1][y] = theta_pi_gamma(K[0], y); + } + /* xor the constant */ + K[1][0] ^= cont[x]; + + /* apply main transform to T[0] into T[1] */ + for (y = 0; y < 8; y++) { + T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y]; + } + + /* even round */ + /* apply main transform to K[1] into K[0] */ + for (y = 0; y < 8; y++) { + K[0][y] = theta_pi_gamma(K[1], y); + } + /* xor the constant */ + K[0][0] ^= cont[x+1]; + + /* apply main transform to T[1] into T[0] */ + for (y = 0; y < 8; y++) { + T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y]; + } + } + + /* store state */ + for (x = 0; x < 8; x++) { + md->whirlpool.state[x] ^= T[0][x] ^ T[2][x]; + } + + return CRYPT_OK; +} + + +#ifdef LTC_CLEAN_STACK +static int s_whirlpool_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_whirlpool_compress(md, buf); + burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int))); + return err; +} +#endif + + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int whirlpool_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + zeromem(&md->whirlpool, sizeof(md->whirlpool)); + 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(whirlpool_process, s_whirlpool_compress, whirlpool, 64) + +/** + 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 whirlpool_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->whirlpool.length += md->whirlpool.curlen * 8; + + /* append the '1' bit */ + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 32 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->whirlpool.curlen > 32) { + while (md->whirlpool.curlen < 64) { + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; + } + s_whirlpool_compress(md, md->whirlpool.buf); + md->whirlpool.curlen = 0; + } + + /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths) */ + while (md->whirlpool.curlen < 56) { + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->whirlpool.length, md->whirlpool.buf+56); + s_whirlpool_compress(md, md->whirlpool.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE64H(md->whirlpool.state[i], out+(8*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(*md)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int whirlpool_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int len; + unsigned char msg[128], hash[64]; + } tests[] = { + + /* NULL Message */ +{ + 0, + { 0x00 }, + { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, + 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, + 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, + 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 } +}, + + + /* 448-bits of 0 bits */ +{ + + 56, + { 0x00 }, + { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03, + 0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70, + 0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61, + 0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 } +}, + + /* 520-bits of 0 bits */ +{ + 65, + { 0x00 }, + { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D, + 0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4, + 0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF, + 0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 } +}, + + /* 512-bits, leading set */ +{ + 64, + { 0x80, 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, 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 }, + { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A, + 0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94, + 0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6, + 0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB } +}, + + /* 512-bits, leading set of second byte */ +{ + 64, + { 0x00, 0x80, 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, 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 }, + { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E, + 0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F, + 0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35, + 0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 } +}, + + /* 512-bits, leading set of last byte */ +{ + 64, + { 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, + 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, 0x80 }, + { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6, + 0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F, + 0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B, + 0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 } +}, + +}; + + int i; + unsigned char tmp[64]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + whirlpool_init(&md); + whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len); + whirlpool_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "WHIRLPOOL", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c b/optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c new file mode 100644 index 0000000..42ecae4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c @@ -0,0 +1,586 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file whirltab.c + LTC_WHIRLPOOL tables, Tom St Denis +*/ + +#ifdef LTC_WHIRLTAB_C + +static const ulong64 sbox0[] = { +CONST64(0x18186018c07830d8), CONST64(0x23238c2305af4626), CONST64(0xc6c63fc67ef991b8), CONST64(0xe8e887e8136fcdfb), +CONST64(0x878726874ca113cb), CONST64(0xb8b8dab8a9626d11), CONST64(0x0101040108050209), CONST64(0x4f4f214f426e9e0d), +CONST64(0x3636d836adee6c9b), CONST64(0xa6a6a2a6590451ff), CONST64(0xd2d26fd2debdb90c), CONST64(0xf5f5f3f5fb06f70e), +CONST64(0x7979f979ef80f296), CONST64(0x6f6fa16f5fcede30), CONST64(0x91917e91fcef3f6d), CONST64(0x52525552aa07a4f8), +CONST64(0x60609d6027fdc047), CONST64(0xbcbccabc89766535), CONST64(0x9b9b569baccd2b37), CONST64(0x8e8e028e048c018a), +CONST64(0xa3a3b6a371155bd2), CONST64(0x0c0c300c603c186c), CONST64(0x7b7bf17bff8af684), CONST64(0x3535d435b5e16a80), +CONST64(0x1d1d741de8693af5), CONST64(0xe0e0a7e05347ddb3), CONST64(0xd7d77bd7f6acb321), CONST64(0xc2c22fc25eed999c), +CONST64(0x2e2eb82e6d965c43), CONST64(0x4b4b314b627a9629), CONST64(0xfefedffea321e15d), CONST64(0x575741578216aed5), +CONST64(0x15155415a8412abd), CONST64(0x7777c1779fb6eee8), CONST64(0x3737dc37a5eb6e92), CONST64(0xe5e5b3e57b56d79e), +CONST64(0x9f9f469f8cd92313), CONST64(0xf0f0e7f0d317fd23), CONST64(0x4a4a354a6a7f9420), CONST64(0xdada4fda9e95a944), +CONST64(0x58587d58fa25b0a2), CONST64(0xc9c903c906ca8fcf), CONST64(0x2929a429558d527c), CONST64(0x0a0a280a5022145a), +CONST64(0xb1b1feb1e14f7f50), CONST64(0xa0a0baa0691a5dc9), CONST64(0x6b6bb16b7fdad614), CONST64(0x85852e855cab17d9), +CONST64(0xbdbdcebd8173673c), CONST64(0x5d5d695dd234ba8f), CONST64(0x1010401080502090), CONST64(0xf4f4f7f4f303f507), +CONST64(0xcbcb0bcb16c08bdd), CONST64(0x3e3ef83eedc67cd3), CONST64(0x0505140528110a2d), CONST64(0x676781671fe6ce78), +CONST64(0xe4e4b7e47353d597), CONST64(0x27279c2725bb4e02), CONST64(0x4141194132588273), CONST64(0x8b8b168b2c9d0ba7), +CONST64(0xa7a7a6a7510153f6), CONST64(0x7d7de97dcf94fab2), CONST64(0x95956e95dcfb3749), CONST64(0xd8d847d88e9fad56), +CONST64(0xfbfbcbfb8b30eb70), CONST64(0xeeee9fee2371c1cd), CONST64(0x7c7ced7cc791f8bb), CONST64(0x6666856617e3cc71), +CONST64(0xdddd53dda68ea77b), CONST64(0x17175c17b84b2eaf), CONST64(0x4747014702468e45), CONST64(0x9e9e429e84dc211a), +CONST64(0xcaca0fca1ec589d4), CONST64(0x2d2db42d75995a58), CONST64(0xbfbfc6bf9179632e), CONST64(0x07071c07381b0e3f), +CONST64(0xadad8ead012347ac), CONST64(0x5a5a755aea2fb4b0), CONST64(0x838336836cb51bef), CONST64(0x3333cc3385ff66b6), +CONST64(0x636391633ff2c65c), CONST64(0x02020802100a0412), CONST64(0xaaaa92aa39384993), CONST64(0x7171d971afa8e2de), +CONST64(0xc8c807c80ecf8dc6), CONST64(0x19196419c87d32d1), CONST64(0x494939497270923b), CONST64(0xd9d943d9869aaf5f), +CONST64(0xf2f2eff2c31df931), CONST64(0xe3e3abe34b48dba8), CONST64(0x5b5b715be22ab6b9), CONST64(0x88881a8834920dbc), +CONST64(0x9a9a529aa4c8293e), CONST64(0x262698262dbe4c0b), CONST64(0x3232c8328dfa64bf), CONST64(0xb0b0fab0e94a7d59), +CONST64(0xe9e983e91b6acff2), CONST64(0x0f0f3c0f78331e77), CONST64(0xd5d573d5e6a6b733), CONST64(0x80803a8074ba1df4), +CONST64(0xbebec2be997c6127), CONST64(0xcdcd13cd26de87eb), CONST64(0x3434d034bde46889), CONST64(0x48483d487a759032), +CONST64(0xffffdbffab24e354), CONST64(0x7a7af57af78ff48d), CONST64(0x90907a90f4ea3d64), CONST64(0x5f5f615fc23ebe9d), +CONST64(0x202080201da0403d), CONST64(0x6868bd6867d5d00f), CONST64(0x1a1a681ad07234ca), CONST64(0xaeae82ae192c41b7), +CONST64(0xb4b4eab4c95e757d), CONST64(0x54544d549a19a8ce), CONST64(0x93937693ece53b7f), CONST64(0x222288220daa442f), +CONST64(0x64648d6407e9c863), CONST64(0xf1f1e3f1db12ff2a), CONST64(0x7373d173bfa2e6cc), CONST64(0x12124812905a2482), +CONST64(0x40401d403a5d807a), CONST64(0x0808200840281048), CONST64(0xc3c32bc356e89b95), CONST64(0xecec97ec337bc5df), +CONST64(0xdbdb4bdb9690ab4d), CONST64(0xa1a1bea1611f5fc0), CONST64(0x8d8d0e8d1c830791), CONST64(0x3d3df43df5c97ac8), +CONST64(0x97976697ccf1335b), CONST64(0x0000000000000000), CONST64(0xcfcf1bcf36d483f9), CONST64(0x2b2bac2b4587566e), +CONST64(0x7676c57697b3ece1), CONST64(0x8282328264b019e6), CONST64(0xd6d67fd6fea9b128), CONST64(0x1b1b6c1bd87736c3), +CONST64(0xb5b5eeb5c15b7774), CONST64(0xafaf86af112943be), CONST64(0x6a6ab56a77dfd41d), CONST64(0x50505d50ba0da0ea), +CONST64(0x45450945124c8a57), CONST64(0xf3f3ebf3cb18fb38), CONST64(0x3030c0309df060ad), CONST64(0xefef9bef2b74c3c4), +CONST64(0x3f3ffc3fe5c37eda), CONST64(0x55554955921caac7), CONST64(0xa2a2b2a2791059db), CONST64(0xeaea8fea0365c9e9), +CONST64(0x656589650fecca6a), CONST64(0xbabad2bab9686903), CONST64(0x2f2fbc2f65935e4a), CONST64(0xc0c027c04ee79d8e), +CONST64(0xdede5fdebe81a160), CONST64(0x1c1c701ce06c38fc), CONST64(0xfdfdd3fdbb2ee746), CONST64(0x4d4d294d52649a1f), +CONST64(0x92927292e4e03976), CONST64(0x7575c9758fbceafa), CONST64(0x06061806301e0c36), CONST64(0x8a8a128a249809ae), +CONST64(0xb2b2f2b2f940794b), CONST64(0xe6e6bfe66359d185), CONST64(0x0e0e380e70361c7e), CONST64(0x1f1f7c1ff8633ee7), +CONST64(0x6262956237f7c455), CONST64(0xd4d477d4eea3b53a), CONST64(0xa8a89aa829324d81), CONST64(0x96966296c4f43152), +CONST64(0xf9f9c3f99b3aef62), CONST64(0xc5c533c566f697a3), CONST64(0x2525942535b14a10), CONST64(0x59597959f220b2ab), +CONST64(0x84842a8454ae15d0), CONST64(0x7272d572b7a7e4c5), CONST64(0x3939e439d5dd72ec), CONST64(0x4c4c2d4c5a619816), +CONST64(0x5e5e655eca3bbc94), CONST64(0x7878fd78e785f09f), CONST64(0x3838e038ddd870e5), CONST64(0x8c8c0a8c14860598), +CONST64(0xd1d163d1c6b2bf17), CONST64(0xa5a5aea5410b57e4), CONST64(0xe2e2afe2434dd9a1), CONST64(0x616199612ff8c24e), +CONST64(0xb3b3f6b3f1457b42), CONST64(0x2121842115a54234), CONST64(0x9c9c4a9c94d62508), CONST64(0x1e1e781ef0663cee), +CONST64(0x4343114322528661), CONST64(0xc7c73bc776fc93b1), CONST64(0xfcfcd7fcb32be54f), CONST64(0x0404100420140824), +CONST64(0x51515951b208a2e3), CONST64(0x99995e99bcc72f25), CONST64(0x6d6da96d4fc4da22), CONST64(0x0d0d340d68391a65), +CONST64(0xfafacffa8335e979), CONST64(0xdfdf5bdfb684a369), CONST64(0x7e7ee57ed79bfca9), CONST64(0x242490243db44819), +CONST64(0x3b3bec3bc5d776fe), CONST64(0xabab96ab313d4b9a), CONST64(0xcece1fce3ed181f0), CONST64(0x1111441188552299), +CONST64(0x8f8f068f0c890383), CONST64(0x4e4e254e4a6b9c04), CONST64(0xb7b7e6b7d1517366), CONST64(0xebeb8beb0b60cbe0), +CONST64(0x3c3cf03cfdcc78c1), CONST64(0x81813e817cbf1ffd), CONST64(0x94946a94d4fe3540), CONST64(0xf7f7fbf7eb0cf31c), +CONST64(0xb9b9deb9a1676f18), CONST64(0x13134c13985f268b), CONST64(0x2c2cb02c7d9c5851), CONST64(0xd3d36bd3d6b8bb05), +CONST64(0xe7e7bbe76b5cd38c), CONST64(0x6e6ea56e57cbdc39), CONST64(0xc4c437c46ef395aa), CONST64(0x03030c03180f061b), +CONST64(0x565645568a13acdc), CONST64(0x44440d441a49885e), CONST64(0x7f7fe17fdf9efea0), CONST64(0xa9a99ea921374f88), +CONST64(0x2a2aa82a4d825467), CONST64(0xbbbbd6bbb16d6b0a), CONST64(0xc1c123c146e29f87), CONST64(0x53535153a202a6f1), +CONST64(0xdcdc57dcae8ba572), CONST64(0x0b0b2c0b58271653), CONST64(0x9d9d4e9d9cd32701), CONST64(0x6c6cad6c47c1d82b), +CONST64(0x3131c43195f562a4), CONST64(0x7474cd7487b9e8f3), CONST64(0xf6f6fff6e309f115), CONST64(0x464605460a438c4c), +CONST64(0xacac8aac092645a5), CONST64(0x89891e893c970fb5), CONST64(0x14145014a04428b4), CONST64(0xe1e1a3e15b42dfba), +CONST64(0x16165816b04e2ca6), CONST64(0x3a3ae83acdd274f7), CONST64(0x6969b9696fd0d206), CONST64(0x09092409482d1241), +CONST64(0x7070dd70a7ade0d7), CONST64(0xb6b6e2b6d954716f), CONST64(0xd0d067d0ceb7bd1e), CONST64(0xeded93ed3b7ec7d6), +CONST64(0xcccc17cc2edb85e2), CONST64(0x424215422a578468), CONST64(0x98985a98b4c22d2c), CONST64(0xa4a4aaa4490e55ed), +CONST64(0x2828a0285d885075), CONST64(0x5c5c6d5cda31b886), CONST64(0xf8f8c7f8933fed6b), CONST64(0x8686228644a411c2) +}; + +#ifdef LTC_SMALL_CODE + +#define SB0(x) sbox0[x] +#define SB1(x) ROR64c(sbox0[x], 8) +#define SB2(x) ROR64c(sbox0[x], 16) +#define SB3(x) ROR64c(sbox0[x], 24) +#define SB4(x) ROR64c(sbox0[x], 32) +#define SB5(x) ROR64c(sbox0[x], 40) +#define SB6(x) ROR64c(sbox0[x], 48) +#define SB7(x) ROR64c(sbox0[x], 56) + +#else + +#define SB0(x) sbox0[x] +#define SB1(x) sbox1[x] +#define SB2(x) sbox2[x] +#define SB3(x) sbox3[x] +#define SB4(x) sbox4[x] +#define SB5(x) sbox5[x] +#define SB6(x) sbox6[x] +#define SB7(x) sbox7[x] + + +static const ulong64 sbox1[] = { +CONST64(0xd818186018c07830), CONST64(0x2623238c2305af46), CONST64(0xb8c6c63fc67ef991), CONST64(0xfbe8e887e8136fcd), +CONST64(0xcb878726874ca113), CONST64(0x11b8b8dab8a9626d), CONST64(0x0901010401080502), CONST64(0x0d4f4f214f426e9e), +CONST64(0x9b3636d836adee6c), CONST64(0xffa6a6a2a6590451), CONST64(0x0cd2d26fd2debdb9), CONST64(0x0ef5f5f3f5fb06f7), +CONST64(0x967979f979ef80f2), CONST64(0x306f6fa16f5fcede), CONST64(0x6d91917e91fcef3f), CONST64(0xf852525552aa07a4), +CONST64(0x4760609d6027fdc0), CONST64(0x35bcbccabc897665), CONST64(0x379b9b569baccd2b), CONST64(0x8a8e8e028e048c01), +CONST64(0xd2a3a3b6a371155b), CONST64(0x6c0c0c300c603c18), CONST64(0x847b7bf17bff8af6), CONST64(0x803535d435b5e16a), +CONST64(0xf51d1d741de8693a), CONST64(0xb3e0e0a7e05347dd), CONST64(0x21d7d77bd7f6acb3), CONST64(0x9cc2c22fc25eed99), +CONST64(0x432e2eb82e6d965c), CONST64(0x294b4b314b627a96), CONST64(0x5dfefedffea321e1), CONST64(0xd5575741578216ae), +CONST64(0xbd15155415a8412a), CONST64(0xe87777c1779fb6ee), CONST64(0x923737dc37a5eb6e), CONST64(0x9ee5e5b3e57b56d7), +CONST64(0x139f9f469f8cd923), CONST64(0x23f0f0e7f0d317fd), CONST64(0x204a4a354a6a7f94), CONST64(0x44dada4fda9e95a9), +CONST64(0xa258587d58fa25b0), CONST64(0xcfc9c903c906ca8f), CONST64(0x7c2929a429558d52), CONST64(0x5a0a0a280a502214), +CONST64(0x50b1b1feb1e14f7f), CONST64(0xc9a0a0baa0691a5d), CONST64(0x146b6bb16b7fdad6), CONST64(0xd985852e855cab17), +CONST64(0x3cbdbdcebd817367), CONST64(0x8f5d5d695dd234ba), CONST64(0x9010104010805020), CONST64(0x07f4f4f7f4f303f5), +CONST64(0xddcbcb0bcb16c08b), CONST64(0xd33e3ef83eedc67c), CONST64(0x2d0505140528110a), CONST64(0x78676781671fe6ce), +CONST64(0x97e4e4b7e47353d5), CONST64(0x0227279c2725bb4e), CONST64(0x7341411941325882), CONST64(0xa78b8b168b2c9d0b), +CONST64(0xf6a7a7a6a7510153), CONST64(0xb27d7de97dcf94fa), CONST64(0x4995956e95dcfb37), CONST64(0x56d8d847d88e9fad), +CONST64(0x70fbfbcbfb8b30eb), CONST64(0xcdeeee9fee2371c1), CONST64(0xbb7c7ced7cc791f8), CONST64(0x716666856617e3cc), +CONST64(0x7bdddd53dda68ea7), CONST64(0xaf17175c17b84b2e), CONST64(0x454747014702468e), CONST64(0x1a9e9e429e84dc21), +CONST64(0xd4caca0fca1ec589), CONST64(0x582d2db42d75995a), CONST64(0x2ebfbfc6bf917963), CONST64(0x3f07071c07381b0e), +CONST64(0xacadad8ead012347), CONST64(0xb05a5a755aea2fb4), CONST64(0xef838336836cb51b), CONST64(0xb63333cc3385ff66), +CONST64(0x5c636391633ff2c6), CONST64(0x1202020802100a04), CONST64(0x93aaaa92aa393849), CONST64(0xde7171d971afa8e2), +CONST64(0xc6c8c807c80ecf8d), CONST64(0xd119196419c87d32), CONST64(0x3b49493949727092), CONST64(0x5fd9d943d9869aaf), +CONST64(0x31f2f2eff2c31df9), CONST64(0xa8e3e3abe34b48db), CONST64(0xb95b5b715be22ab6), CONST64(0xbc88881a8834920d), +CONST64(0x3e9a9a529aa4c829), CONST64(0x0b262698262dbe4c), CONST64(0xbf3232c8328dfa64), CONST64(0x59b0b0fab0e94a7d), +CONST64(0xf2e9e983e91b6acf), CONST64(0x770f0f3c0f78331e), CONST64(0x33d5d573d5e6a6b7), CONST64(0xf480803a8074ba1d), +CONST64(0x27bebec2be997c61), CONST64(0xebcdcd13cd26de87), CONST64(0x893434d034bde468), CONST64(0x3248483d487a7590), +CONST64(0x54ffffdbffab24e3), CONST64(0x8d7a7af57af78ff4), CONST64(0x6490907a90f4ea3d), CONST64(0x9d5f5f615fc23ebe), +CONST64(0x3d202080201da040), CONST64(0x0f6868bd6867d5d0), CONST64(0xca1a1a681ad07234), CONST64(0xb7aeae82ae192c41), +CONST64(0x7db4b4eab4c95e75), CONST64(0xce54544d549a19a8), CONST64(0x7f93937693ece53b), CONST64(0x2f222288220daa44), +CONST64(0x6364648d6407e9c8), CONST64(0x2af1f1e3f1db12ff), CONST64(0xcc7373d173bfa2e6), CONST64(0x8212124812905a24), +CONST64(0x7a40401d403a5d80), CONST64(0x4808082008402810), CONST64(0x95c3c32bc356e89b), CONST64(0xdfecec97ec337bc5), +CONST64(0x4ddbdb4bdb9690ab), CONST64(0xc0a1a1bea1611f5f), CONST64(0x918d8d0e8d1c8307), CONST64(0xc83d3df43df5c97a), +CONST64(0x5b97976697ccf133), CONST64(0x0000000000000000), CONST64(0xf9cfcf1bcf36d483), CONST64(0x6e2b2bac2b458756), +CONST64(0xe17676c57697b3ec), CONST64(0xe68282328264b019), CONST64(0x28d6d67fd6fea9b1), CONST64(0xc31b1b6c1bd87736), +CONST64(0x74b5b5eeb5c15b77), CONST64(0xbeafaf86af112943), CONST64(0x1d6a6ab56a77dfd4), CONST64(0xea50505d50ba0da0), +CONST64(0x5745450945124c8a), CONST64(0x38f3f3ebf3cb18fb), CONST64(0xad3030c0309df060), CONST64(0xc4efef9bef2b74c3), +CONST64(0xda3f3ffc3fe5c37e), CONST64(0xc755554955921caa), CONST64(0xdba2a2b2a2791059), CONST64(0xe9eaea8fea0365c9), +CONST64(0x6a656589650fecca), CONST64(0x03babad2bab96869), CONST64(0x4a2f2fbc2f65935e), CONST64(0x8ec0c027c04ee79d), +CONST64(0x60dede5fdebe81a1), CONST64(0xfc1c1c701ce06c38), CONST64(0x46fdfdd3fdbb2ee7), CONST64(0x1f4d4d294d52649a), +CONST64(0x7692927292e4e039), CONST64(0xfa7575c9758fbcea), CONST64(0x3606061806301e0c), CONST64(0xae8a8a128a249809), +CONST64(0x4bb2b2f2b2f94079), CONST64(0x85e6e6bfe66359d1), CONST64(0x7e0e0e380e70361c), CONST64(0xe71f1f7c1ff8633e), +CONST64(0x556262956237f7c4), CONST64(0x3ad4d477d4eea3b5), CONST64(0x81a8a89aa829324d), CONST64(0x5296966296c4f431), +CONST64(0x62f9f9c3f99b3aef), CONST64(0xa3c5c533c566f697), CONST64(0x102525942535b14a), CONST64(0xab59597959f220b2), +CONST64(0xd084842a8454ae15), CONST64(0xc57272d572b7a7e4), CONST64(0xec3939e439d5dd72), CONST64(0x164c4c2d4c5a6198), +CONST64(0x945e5e655eca3bbc), CONST64(0x9f7878fd78e785f0), CONST64(0xe53838e038ddd870), CONST64(0x988c8c0a8c148605), +CONST64(0x17d1d163d1c6b2bf), CONST64(0xe4a5a5aea5410b57), CONST64(0xa1e2e2afe2434dd9), CONST64(0x4e616199612ff8c2), +CONST64(0x42b3b3f6b3f1457b), CONST64(0x342121842115a542), CONST64(0x089c9c4a9c94d625), CONST64(0xee1e1e781ef0663c), +CONST64(0x6143431143225286), CONST64(0xb1c7c73bc776fc93), CONST64(0x4ffcfcd7fcb32be5), CONST64(0x2404041004201408), +CONST64(0xe351515951b208a2), CONST64(0x2599995e99bcc72f), CONST64(0x226d6da96d4fc4da), CONST64(0x650d0d340d68391a), +CONST64(0x79fafacffa8335e9), CONST64(0x69dfdf5bdfb684a3), CONST64(0xa97e7ee57ed79bfc), CONST64(0x19242490243db448), +CONST64(0xfe3b3bec3bc5d776), CONST64(0x9aabab96ab313d4b), CONST64(0xf0cece1fce3ed181), CONST64(0x9911114411885522), +CONST64(0x838f8f068f0c8903), CONST64(0x044e4e254e4a6b9c), CONST64(0x66b7b7e6b7d15173), CONST64(0xe0ebeb8beb0b60cb), +CONST64(0xc13c3cf03cfdcc78), CONST64(0xfd81813e817cbf1f), CONST64(0x4094946a94d4fe35), CONST64(0x1cf7f7fbf7eb0cf3), +CONST64(0x18b9b9deb9a1676f), CONST64(0x8b13134c13985f26), CONST64(0x512c2cb02c7d9c58), CONST64(0x05d3d36bd3d6b8bb), +CONST64(0x8ce7e7bbe76b5cd3), CONST64(0x396e6ea56e57cbdc), CONST64(0xaac4c437c46ef395), CONST64(0x1b03030c03180f06), +CONST64(0xdc565645568a13ac), CONST64(0x5e44440d441a4988), CONST64(0xa07f7fe17fdf9efe), CONST64(0x88a9a99ea921374f), +CONST64(0x672a2aa82a4d8254), CONST64(0x0abbbbd6bbb16d6b), CONST64(0x87c1c123c146e29f), CONST64(0xf153535153a202a6), +CONST64(0x72dcdc57dcae8ba5), CONST64(0x530b0b2c0b582716), CONST64(0x019d9d4e9d9cd327), CONST64(0x2b6c6cad6c47c1d8), +CONST64(0xa43131c43195f562), CONST64(0xf37474cd7487b9e8), CONST64(0x15f6f6fff6e309f1), CONST64(0x4c464605460a438c), +CONST64(0xa5acac8aac092645), CONST64(0xb589891e893c970f), CONST64(0xb414145014a04428), CONST64(0xbae1e1a3e15b42df), +CONST64(0xa616165816b04e2c), CONST64(0xf73a3ae83acdd274), CONST64(0x066969b9696fd0d2), CONST64(0x4109092409482d12), +CONST64(0xd77070dd70a7ade0), CONST64(0x6fb6b6e2b6d95471), CONST64(0x1ed0d067d0ceb7bd), CONST64(0xd6eded93ed3b7ec7), +CONST64(0xe2cccc17cc2edb85), CONST64(0x68424215422a5784), CONST64(0x2c98985a98b4c22d), CONST64(0xeda4a4aaa4490e55), +CONST64(0x752828a0285d8850), CONST64(0x865c5c6d5cda31b8), CONST64(0x6bf8f8c7f8933fed), CONST64(0xc28686228644a411) +}; + +static const ulong64 sbox2[] = { +CONST64(0x30d818186018c078), CONST64(0x462623238c2305af), CONST64(0x91b8c6c63fc67ef9), CONST64(0xcdfbe8e887e8136f), +CONST64(0x13cb878726874ca1), CONST64(0x6d11b8b8dab8a962), CONST64(0x0209010104010805), CONST64(0x9e0d4f4f214f426e), +CONST64(0x6c9b3636d836adee), CONST64(0x51ffa6a6a2a65904), CONST64(0xb90cd2d26fd2debd), CONST64(0xf70ef5f5f3f5fb06), +CONST64(0xf2967979f979ef80), CONST64(0xde306f6fa16f5fce), CONST64(0x3f6d91917e91fcef), CONST64(0xa4f852525552aa07), +CONST64(0xc04760609d6027fd), CONST64(0x6535bcbccabc8976), CONST64(0x2b379b9b569baccd), CONST64(0x018a8e8e028e048c), +CONST64(0x5bd2a3a3b6a37115), CONST64(0x186c0c0c300c603c), CONST64(0xf6847b7bf17bff8a), CONST64(0x6a803535d435b5e1), +CONST64(0x3af51d1d741de869), CONST64(0xddb3e0e0a7e05347), CONST64(0xb321d7d77bd7f6ac), CONST64(0x999cc2c22fc25eed), +CONST64(0x5c432e2eb82e6d96), CONST64(0x96294b4b314b627a), CONST64(0xe15dfefedffea321), CONST64(0xaed5575741578216), +CONST64(0x2abd15155415a841), CONST64(0xeee87777c1779fb6), CONST64(0x6e923737dc37a5eb), CONST64(0xd79ee5e5b3e57b56), +CONST64(0x23139f9f469f8cd9), CONST64(0xfd23f0f0e7f0d317), CONST64(0x94204a4a354a6a7f), CONST64(0xa944dada4fda9e95), +CONST64(0xb0a258587d58fa25), CONST64(0x8fcfc9c903c906ca), CONST64(0x527c2929a429558d), CONST64(0x145a0a0a280a5022), +CONST64(0x7f50b1b1feb1e14f), CONST64(0x5dc9a0a0baa0691a), CONST64(0xd6146b6bb16b7fda), CONST64(0x17d985852e855cab), +CONST64(0x673cbdbdcebd8173), CONST64(0xba8f5d5d695dd234), CONST64(0x2090101040108050), CONST64(0xf507f4f4f7f4f303), +CONST64(0x8bddcbcb0bcb16c0), CONST64(0x7cd33e3ef83eedc6), CONST64(0x0a2d050514052811), CONST64(0xce78676781671fe6), +CONST64(0xd597e4e4b7e47353), CONST64(0x4e0227279c2725bb), CONST64(0x8273414119413258), CONST64(0x0ba78b8b168b2c9d), +CONST64(0x53f6a7a7a6a75101), CONST64(0xfab27d7de97dcf94), CONST64(0x374995956e95dcfb), CONST64(0xad56d8d847d88e9f), +CONST64(0xeb70fbfbcbfb8b30), CONST64(0xc1cdeeee9fee2371), CONST64(0xf8bb7c7ced7cc791), CONST64(0xcc716666856617e3), +CONST64(0xa77bdddd53dda68e), CONST64(0x2eaf17175c17b84b), CONST64(0x8e45474701470246), CONST64(0x211a9e9e429e84dc), +CONST64(0x89d4caca0fca1ec5), CONST64(0x5a582d2db42d7599), CONST64(0x632ebfbfc6bf9179), CONST64(0x0e3f07071c07381b), +CONST64(0x47acadad8ead0123), CONST64(0xb4b05a5a755aea2f), CONST64(0x1bef838336836cb5), CONST64(0x66b63333cc3385ff), +CONST64(0xc65c636391633ff2), CONST64(0x041202020802100a), CONST64(0x4993aaaa92aa3938), CONST64(0xe2de7171d971afa8), +CONST64(0x8dc6c8c807c80ecf), CONST64(0x32d119196419c87d), CONST64(0x923b494939497270), CONST64(0xaf5fd9d943d9869a), +CONST64(0xf931f2f2eff2c31d), CONST64(0xdba8e3e3abe34b48), CONST64(0xb6b95b5b715be22a), CONST64(0x0dbc88881a883492), +CONST64(0x293e9a9a529aa4c8), CONST64(0x4c0b262698262dbe), CONST64(0x64bf3232c8328dfa), CONST64(0x7d59b0b0fab0e94a), +CONST64(0xcff2e9e983e91b6a), CONST64(0x1e770f0f3c0f7833), CONST64(0xb733d5d573d5e6a6), CONST64(0x1df480803a8074ba), +CONST64(0x6127bebec2be997c), CONST64(0x87ebcdcd13cd26de), CONST64(0x68893434d034bde4), CONST64(0x903248483d487a75), +CONST64(0xe354ffffdbffab24), CONST64(0xf48d7a7af57af78f), CONST64(0x3d6490907a90f4ea), CONST64(0xbe9d5f5f615fc23e), +CONST64(0x403d202080201da0), CONST64(0xd00f6868bd6867d5), CONST64(0x34ca1a1a681ad072), CONST64(0x41b7aeae82ae192c), +CONST64(0x757db4b4eab4c95e), CONST64(0xa8ce54544d549a19), CONST64(0x3b7f93937693ece5), CONST64(0x442f222288220daa), +CONST64(0xc86364648d6407e9), CONST64(0xff2af1f1e3f1db12), CONST64(0xe6cc7373d173bfa2), CONST64(0x248212124812905a), +CONST64(0x807a40401d403a5d), CONST64(0x1048080820084028), CONST64(0x9b95c3c32bc356e8), CONST64(0xc5dfecec97ec337b), +CONST64(0xab4ddbdb4bdb9690), CONST64(0x5fc0a1a1bea1611f), CONST64(0x07918d8d0e8d1c83), CONST64(0x7ac83d3df43df5c9), +CONST64(0x335b97976697ccf1), CONST64(0x0000000000000000), CONST64(0x83f9cfcf1bcf36d4), CONST64(0x566e2b2bac2b4587), +CONST64(0xece17676c57697b3), CONST64(0x19e68282328264b0), CONST64(0xb128d6d67fd6fea9), CONST64(0x36c31b1b6c1bd877), +CONST64(0x7774b5b5eeb5c15b), CONST64(0x43beafaf86af1129), CONST64(0xd41d6a6ab56a77df), CONST64(0xa0ea50505d50ba0d), +CONST64(0x8a5745450945124c), CONST64(0xfb38f3f3ebf3cb18), CONST64(0x60ad3030c0309df0), CONST64(0xc3c4efef9bef2b74), +CONST64(0x7eda3f3ffc3fe5c3), CONST64(0xaac755554955921c), CONST64(0x59dba2a2b2a27910), CONST64(0xc9e9eaea8fea0365), +CONST64(0xca6a656589650fec), CONST64(0x6903babad2bab968), CONST64(0x5e4a2f2fbc2f6593), CONST64(0x9d8ec0c027c04ee7), +CONST64(0xa160dede5fdebe81), CONST64(0x38fc1c1c701ce06c), CONST64(0xe746fdfdd3fdbb2e), CONST64(0x9a1f4d4d294d5264), +CONST64(0x397692927292e4e0), CONST64(0xeafa7575c9758fbc), CONST64(0x0c3606061806301e), CONST64(0x09ae8a8a128a2498), +CONST64(0x794bb2b2f2b2f940), CONST64(0xd185e6e6bfe66359), CONST64(0x1c7e0e0e380e7036), CONST64(0x3ee71f1f7c1ff863), +CONST64(0xc4556262956237f7), CONST64(0xb53ad4d477d4eea3), CONST64(0x4d81a8a89aa82932), CONST64(0x315296966296c4f4), +CONST64(0xef62f9f9c3f99b3a), CONST64(0x97a3c5c533c566f6), CONST64(0x4a102525942535b1), CONST64(0xb2ab59597959f220), +CONST64(0x15d084842a8454ae), CONST64(0xe4c57272d572b7a7), CONST64(0x72ec3939e439d5dd), CONST64(0x98164c4c2d4c5a61), +CONST64(0xbc945e5e655eca3b), CONST64(0xf09f7878fd78e785), CONST64(0x70e53838e038ddd8), CONST64(0x05988c8c0a8c1486), +CONST64(0xbf17d1d163d1c6b2), CONST64(0x57e4a5a5aea5410b), CONST64(0xd9a1e2e2afe2434d), CONST64(0xc24e616199612ff8), +CONST64(0x7b42b3b3f6b3f145), CONST64(0x42342121842115a5), CONST64(0x25089c9c4a9c94d6), CONST64(0x3cee1e1e781ef066), +CONST64(0x8661434311432252), CONST64(0x93b1c7c73bc776fc), CONST64(0xe54ffcfcd7fcb32b), CONST64(0x0824040410042014), +CONST64(0xa2e351515951b208), CONST64(0x2f2599995e99bcc7), CONST64(0xda226d6da96d4fc4), CONST64(0x1a650d0d340d6839), +CONST64(0xe979fafacffa8335), CONST64(0xa369dfdf5bdfb684), CONST64(0xfca97e7ee57ed79b), CONST64(0x4819242490243db4), +CONST64(0x76fe3b3bec3bc5d7), CONST64(0x4b9aabab96ab313d), CONST64(0x81f0cece1fce3ed1), CONST64(0x2299111144118855), +CONST64(0x03838f8f068f0c89), CONST64(0x9c044e4e254e4a6b), CONST64(0x7366b7b7e6b7d151), CONST64(0xcbe0ebeb8beb0b60), +CONST64(0x78c13c3cf03cfdcc), CONST64(0x1ffd81813e817cbf), CONST64(0x354094946a94d4fe), CONST64(0xf31cf7f7fbf7eb0c), +CONST64(0x6f18b9b9deb9a167), CONST64(0x268b13134c13985f), CONST64(0x58512c2cb02c7d9c), CONST64(0xbb05d3d36bd3d6b8), +CONST64(0xd38ce7e7bbe76b5c), CONST64(0xdc396e6ea56e57cb), CONST64(0x95aac4c437c46ef3), CONST64(0x061b03030c03180f), +CONST64(0xacdc565645568a13), CONST64(0x885e44440d441a49), CONST64(0xfea07f7fe17fdf9e), CONST64(0x4f88a9a99ea92137), +CONST64(0x54672a2aa82a4d82), CONST64(0x6b0abbbbd6bbb16d), CONST64(0x9f87c1c123c146e2), CONST64(0xa6f153535153a202), +CONST64(0xa572dcdc57dcae8b), CONST64(0x16530b0b2c0b5827), CONST64(0x27019d9d4e9d9cd3), CONST64(0xd82b6c6cad6c47c1), +CONST64(0x62a43131c43195f5), CONST64(0xe8f37474cd7487b9), CONST64(0xf115f6f6fff6e309), CONST64(0x8c4c464605460a43), +CONST64(0x45a5acac8aac0926), CONST64(0x0fb589891e893c97), CONST64(0x28b414145014a044), CONST64(0xdfbae1e1a3e15b42), +CONST64(0x2ca616165816b04e), CONST64(0x74f73a3ae83acdd2), CONST64(0xd2066969b9696fd0), CONST64(0x124109092409482d), +CONST64(0xe0d77070dd70a7ad), CONST64(0x716fb6b6e2b6d954), CONST64(0xbd1ed0d067d0ceb7), CONST64(0xc7d6eded93ed3b7e), +CONST64(0x85e2cccc17cc2edb), CONST64(0x8468424215422a57), CONST64(0x2d2c98985a98b4c2), CONST64(0x55eda4a4aaa4490e), +CONST64(0x50752828a0285d88), CONST64(0xb8865c5c6d5cda31), CONST64(0xed6bf8f8c7f8933f), CONST64(0x11c28686228644a4) +}; + +static const ulong64 sbox3[] = { +CONST64(0x7830d818186018c0), CONST64(0xaf462623238c2305), CONST64(0xf991b8c6c63fc67e), CONST64(0x6fcdfbe8e887e813), +CONST64(0xa113cb878726874c), CONST64(0x626d11b8b8dab8a9), CONST64(0x0502090101040108), CONST64(0x6e9e0d4f4f214f42), +CONST64(0xee6c9b3636d836ad), CONST64(0x0451ffa6a6a2a659), CONST64(0xbdb90cd2d26fd2de), CONST64(0x06f70ef5f5f3f5fb), +CONST64(0x80f2967979f979ef), CONST64(0xcede306f6fa16f5f), CONST64(0xef3f6d91917e91fc), CONST64(0x07a4f852525552aa), +CONST64(0xfdc04760609d6027), CONST64(0x766535bcbccabc89), CONST64(0xcd2b379b9b569bac), CONST64(0x8c018a8e8e028e04), +CONST64(0x155bd2a3a3b6a371), CONST64(0x3c186c0c0c300c60), CONST64(0x8af6847b7bf17bff), CONST64(0xe16a803535d435b5), +CONST64(0x693af51d1d741de8), CONST64(0x47ddb3e0e0a7e053), CONST64(0xacb321d7d77bd7f6), CONST64(0xed999cc2c22fc25e), +CONST64(0x965c432e2eb82e6d), CONST64(0x7a96294b4b314b62), CONST64(0x21e15dfefedffea3), CONST64(0x16aed55757415782), +CONST64(0x412abd15155415a8), CONST64(0xb6eee87777c1779f), CONST64(0xeb6e923737dc37a5), CONST64(0x56d79ee5e5b3e57b), +CONST64(0xd923139f9f469f8c), CONST64(0x17fd23f0f0e7f0d3), CONST64(0x7f94204a4a354a6a), CONST64(0x95a944dada4fda9e), +CONST64(0x25b0a258587d58fa), CONST64(0xca8fcfc9c903c906), CONST64(0x8d527c2929a42955), CONST64(0x22145a0a0a280a50), +CONST64(0x4f7f50b1b1feb1e1), CONST64(0x1a5dc9a0a0baa069), CONST64(0xdad6146b6bb16b7f), CONST64(0xab17d985852e855c), +CONST64(0x73673cbdbdcebd81), CONST64(0x34ba8f5d5d695dd2), CONST64(0x5020901010401080), CONST64(0x03f507f4f4f7f4f3), +CONST64(0xc08bddcbcb0bcb16), CONST64(0xc67cd33e3ef83eed), CONST64(0x110a2d0505140528), CONST64(0xe6ce78676781671f), +CONST64(0x53d597e4e4b7e473), CONST64(0xbb4e0227279c2725), CONST64(0x5882734141194132), CONST64(0x9d0ba78b8b168b2c), +CONST64(0x0153f6a7a7a6a751), CONST64(0x94fab27d7de97dcf), CONST64(0xfb374995956e95dc), CONST64(0x9fad56d8d847d88e), +CONST64(0x30eb70fbfbcbfb8b), CONST64(0x71c1cdeeee9fee23), CONST64(0x91f8bb7c7ced7cc7), CONST64(0xe3cc716666856617), +CONST64(0x8ea77bdddd53dda6), CONST64(0x4b2eaf17175c17b8), CONST64(0x468e454747014702), CONST64(0xdc211a9e9e429e84), +CONST64(0xc589d4caca0fca1e), CONST64(0x995a582d2db42d75), CONST64(0x79632ebfbfc6bf91), CONST64(0x1b0e3f07071c0738), +CONST64(0x2347acadad8ead01), CONST64(0x2fb4b05a5a755aea), CONST64(0xb51bef838336836c), CONST64(0xff66b63333cc3385), +CONST64(0xf2c65c636391633f), CONST64(0x0a04120202080210), CONST64(0x384993aaaa92aa39), CONST64(0xa8e2de7171d971af), +CONST64(0xcf8dc6c8c807c80e), CONST64(0x7d32d119196419c8), CONST64(0x70923b4949394972), CONST64(0x9aaf5fd9d943d986), +CONST64(0x1df931f2f2eff2c3), CONST64(0x48dba8e3e3abe34b), CONST64(0x2ab6b95b5b715be2), CONST64(0x920dbc88881a8834), +CONST64(0xc8293e9a9a529aa4), CONST64(0xbe4c0b262698262d), CONST64(0xfa64bf3232c8328d), CONST64(0x4a7d59b0b0fab0e9), +CONST64(0x6acff2e9e983e91b), CONST64(0x331e770f0f3c0f78), CONST64(0xa6b733d5d573d5e6), CONST64(0xba1df480803a8074), +CONST64(0x7c6127bebec2be99), CONST64(0xde87ebcdcd13cd26), CONST64(0xe468893434d034bd), CONST64(0x75903248483d487a), +CONST64(0x24e354ffffdbffab), CONST64(0x8ff48d7a7af57af7), CONST64(0xea3d6490907a90f4), CONST64(0x3ebe9d5f5f615fc2), +CONST64(0xa0403d202080201d), CONST64(0xd5d00f6868bd6867), CONST64(0x7234ca1a1a681ad0), CONST64(0x2c41b7aeae82ae19), +CONST64(0x5e757db4b4eab4c9), CONST64(0x19a8ce54544d549a), CONST64(0xe53b7f93937693ec), CONST64(0xaa442f222288220d), +CONST64(0xe9c86364648d6407), CONST64(0x12ff2af1f1e3f1db), CONST64(0xa2e6cc7373d173bf), CONST64(0x5a24821212481290), +CONST64(0x5d807a40401d403a), CONST64(0x2810480808200840), CONST64(0xe89b95c3c32bc356), CONST64(0x7bc5dfecec97ec33), +CONST64(0x90ab4ddbdb4bdb96), CONST64(0x1f5fc0a1a1bea161), CONST64(0x8307918d8d0e8d1c), CONST64(0xc97ac83d3df43df5), +CONST64(0xf1335b97976697cc), CONST64(0x0000000000000000), CONST64(0xd483f9cfcf1bcf36), CONST64(0x87566e2b2bac2b45), +CONST64(0xb3ece17676c57697), CONST64(0xb019e68282328264), CONST64(0xa9b128d6d67fd6fe), CONST64(0x7736c31b1b6c1bd8), +CONST64(0x5b7774b5b5eeb5c1), CONST64(0x2943beafaf86af11), CONST64(0xdfd41d6a6ab56a77), CONST64(0x0da0ea50505d50ba), +CONST64(0x4c8a574545094512), CONST64(0x18fb38f3f3ebf3cb), CONST64(0xf060ad3030c0309d), CONST64(0x74c3c4efef9bef2b), +CONST64(0xc37eda3f3ffc3fe5), CONST64(0x1caac75555495592), CONST64(0x1059dba2a2b2a279), CONST64(0x65c9e9eaea8fea03), +CONST64(0xecca6a656589650f), CONST64(0x686903babad2bab9), CONST64(0x935e4a2f2fbc2f65), CONST64(0xe79d8ec0c027c04e), +CONST64(0x81a160dede5fdebe), CONST64(0x6c38fc1c1c701ce0), CONST64(0x2ee746fdfdd3fdbb), CONST64(0x649a1f4d4d294d52), +CONST64(0xe0397692927292e4), CONST64(0xbceafa7575c9758f), CONST64(0x1e0c360606180630), CONST64(0x9809ae8a8a128a24), +CONST64(0x40794bb2b2f2b2f9), CONST64(0x59d185e6e6bfe663), CONST64(0x361c7e0e0e380e70), CONST64(0x633ee71f1f7c1ff8), +CONST64(0xf7c4556262956237), CONST64(0xa3b53ad4d477d4ee), CONST64(0x324d81a8a89aa829), CONST64(0xf4315296966296c4), +CONST64(0x3aef62f9f9c3f99b), CONST64(0xf697a3c5c533c566), CONST64(0xb14a102525942535), CONST64(0x20b2ab59597959f2), +CONST64(0xae15d084842a8454), CONST64(0xa7e4c57272d572b7), CONST64(0xdd72ec3939e439d5), CONST64(0x6198164c4c2d4c5a), +CONST64(0x3bbc945e5e655eca), CONST64(0x85f09f7878fd78e7), CONST64(0xd870e53838e038dd), CONST64(0x8605988c8c0a8c14), +CONST64(0xb2bf17d1d163d1c6), CONST64(0x0b57e4a5a5aea541), CONST64(0x4dd9a1e2e2afe243), CONST64(0xf8c24e616199612f), +CONST64(0x457b42b3b3f6b3f1), CONST64(0xa542342121842115), CONST64(0xd625089c9c4a9c94), CONST64(0x663cee1e1e781ef0), +CONST64(0x5286614343114322), CONST64(0xfc93b1c7c73bc776), CONST64(0x2be54ffcfcd7fcb3), CONST64(0x1408240404100420), +CONST64(0x08a2e351515951b2), CONST64(0xc72f2599995e99bc), CONST64(0xc4da226d6da96d4f), CONST64(0x391a650d0d340d68), +CONST64(0x35e979fafacffa83), CONST64(0x84a369dfdf5bdfb6), CONST64(0x9bfca97e7ee57ed7), CONST64(0xb44819242490243d), +CONST64(0xd776fe3b3bec3bc5), CONST64(0x3d4b9aabab96ab31), CONST64(0xd181f0cece1fce3e), CONST64(0x5522991111441188), +CONST64(0x8903838f8f068f0c), CONST64(0x6b9c044e4e254e4a), CONST64(0x517366b7b7e6b7d1), CONST64(0x60cbe0ebeb8beb0b), +CONST64(0xcc78c13c3cf03cfd), CONST64(0xbf1ffd81813e817c), CONST64(0xfe354094946a94d4), CONST64(0x0cf31cf7f7fbf7eb), +CONST64(0x676f18b9b9deb9a1), CONST64(0x5f268b13134c1398), CONST64(0x9c58512c2cb02c7d), CONST64(0xb8bb05d3d36bd3d6), +CONST64(0x5cd38ce7e7bbe76b), CONST64(0xcbdc396e6ea56e57), CONST64(0xf395aac4c437c46e), CONST64(0x0f061b03030c0318), +CONST64(0x13acdc565645568a), CONST64(0x49885e44440d441a), CONST64(0x9efea07f7fe17fdf), CONST64(0x374f88a9a99ea921), +CONST64(0x8254672a2aa82a4d), CONST64(0x6d6b0abbbbd6bbb1), CONST64(0xe29f87c1c123c146), CONST64(0x02a6f153535153a2), +CONST64(0x8ba572dcdc57dcae), CONST64(0x2716530b0b2c0b58), CONST64(0xd327019d9d4e9d9c), CONST64(0xc1d82b6c6cad6c47), +CONST64(0xf562a43131c43195), CONST64(0xb9e8f37474cd7487), CONST64(0x09f115f6f6fff6e3), CONST64(0x438c4c464605460a), +CONST64(0x2645a5acac8aac09), CONST64(0x970fb589891e893c), CONST64(0x4428b414145014a0), CONST64(0x42dfbae1e1a3e15b), +CONST64(0x4e2ca616165816b0), CONST64(0xd274f73a3ae83acd), CONST64(0xd0d2066969b9696f), CONST64(0x2d12410909240948), +CONST64(0xade0d77070dd70a7), CONST64(0x54716fb6b6e2b6d9), CONST64(0xb7bd1ed0d067d0ce), CONST64(0x7ec7d6eded93ed3b), +CONST64(0xdb85e2cccc17cc2e), CONST64(0x578468424215422a), CONST64(0xc22d2c98985a98b4), CONST64(0x0e55eda4a4aaa449), +CONST64(0x8850752828a0285d), CONST64(0x31b8865c5c6d5cda), CONST64(0x3fed6bf8f8c7f893), CONST64(0xa411c28686228644) +}; + +static const ulong64 sbox4[] = { +CONST64(0xc07830d818186018), CONST64(0x05af462623238c23), CONST64(0x7ef991b8c6c63fc6), CONST64(0x136fcdfbe8e887e8), +CONST64(0x4ca113cb87872687), CONST64(0xa9626d11b8b8dab8), CONST64(0x0805020901010401), CONST64(0x426e9e0d4f4f214f), +CONST64(0xadee6c9b3636d836), CONST64(0x590451ffa6a6a2a6), CONST64(0xdebdb90cd2d26fd2), CONST64(0xfb06f70ef5f5f3f5), +CONST64(0xef80f2967979f979), CONST64(0x5fcede306f6fa16f), CONST64(0xfcef3f6d91917e91), CONST64(0xaa07a4f852525552), +CONST64(0x27fdc04760609d60), CONST64(0x89766535bcbccabc), CONST64(0xaccd2b379b9b569b), CONST64(0x048c018a8e8e028e), +CONST64(0x71155bd2a3a3b6a3), CONST64(0x603c186c0c0c300c), CONST64(0xff8af6847b7bf17b), CONST64(0xb5e16a803535d435), +CONST64(0xe8693af51d1d741d), CONST64(0x5347ddb3e0e0a7e0), CONST64(0xf6acb321d7d77bd7), CONST64(0x5eed999cc2c22fc2), +CONST64(0x6d965c432e2eb82e), CONST64(0x627a96294b4b314b), CONST64(0xa321e15dfefedffe), CONST64(0x8216aed557574157), +CONST64(0xa8412abd15155415), CONST64(0x9fb6eee87777c177), CONST64(0xa5eb6e923737dc37), CONST64(0x7b56d79ee5e5b3e5), +CONST64(0x8cd923139f9f469f), CONST64(0xd317fd23f0f0e7f0), CONST64(0x6a7f94204a4a354a), CONST64(0x9e95a944dada4fda), +CONST64(0xfa25b0a258587d58), CONST64(0x06ca8fcfc9c903c9), CONST64(0x558d527c2929a429), CONST64(0x5022145a0a0a280a), +CONST64(0xe14f7f50b1b1feb1), CONST64(0x691a5dc9a0a0baa0), CONST64(0x7fdad6146b6bb16b), CONST64(0x5cab17d985852e85), +CONST64(0x8173673cbdbdcebd), CONST64(0xd234ba8f5d5d695d), CONST64(0x8050209010104010), CONST64(0xf303f507f4f4f7f4), +CONST64(0x16c08bddcbcb0bcb), CONST64(0xedc67cd33e3ef83e), CONST64(0x28110a2d05051405), CONST64(0x1fe6ce7867678167), +CONST64(0x7353d597e4e4b7e4), CONST64(0x25bb4e0227279c27), CONST64(0x3258827341411941), CONST64(0x2c9d0ba78b8b168b), +CONST64(0x510153f6a7a7a6a7), CONST64(0xcf94fab27d7de97d), CONST64(0xdcfb374995956e95), CONST64(0x8e9fad56d8d847d8), +CONST64(0x8b30eb70fbfbcbfb), CONST64(0x2371c1cdeeee9fee), CONST64(0xc791f8bb7c7ced7c), CONST64(0x17e3cc7166668566), +CONST64(0xa68ea77bdddd53dd), CONST64(0xb84b2eaf17175c17), CONST64(0x02468e4547470147), CONST64(0x84dc211a9e9e429e), +CONST64(0x1ec589d4caca0fca), CONST64(0x75995a582d2db42d), CONST64(0x9179632ebfbfc6bf), CONST64(0x381b0e3f07071c07), +CONST64(0x012347acadad8ead), CONST64(0xea2fb4b05a5a755a), CONST64(0x6cb51bef83833683), CONST64(0x85ff66b63333cc33), +CONST64(0x3ff2c65c63639163), CONST64(0x100a041202020802), CONST64(0x39384993aaaa92aa), CONST64(0xafa8e2de7171d971), +CONST64(0x0ecf8dc6c8c807c8), CONST64(0xc87d32d119196419), CONST64(0x7270923b49493949), CONST64(0x869aaf5fd9d943d9), +CONST64(0xc31df931f2f2eff2), CONST64(0x4b48dba8e3e3abe3), CONST64(0xe22ab6b95b5b715b), CONST64(0x34920dbc88881a88), +CONST64(0xa4c8293e9a9a529a), CONST64(0x2dbe4c0b26269826), CONST64(0x8dfa64bf3232c832), CONST64(0xe94a7d59b0b0fab0), +CONST64(0x1b6acff2e9e983e9), CONST64(0x78331e770f0f3c0f), CONST64(0xe6a6b733d5d573d5), CONST64(0x74ba1df480803a80), +CONST64(0x997c6127bebec2be), CONST64(0x26de87ebcdcd13cd), CONST64(0xbde468893434d034), CONST64(0x7a75903248483d48), +CONST64(0xab24e354ffffdbff), CONST64(0xf78ff48d7a7af57a), CONST64(0xf4ea3d6490907a90), CONST64(0xc23ebe9d5f5f615f), +CONST64(0x1da0403d20208020), CONST64(0x67d5d00f6868bd68), CONST64(0xd07234ca1a1a681a), CONST64(0x192c41b7aeae82ae), +CONST64(0xc95e757db4b4eab4), CONST64(0x9a19a8ce54544d54), CONST64(0xece53b7f93937693), CONST64(0x0daa442f22228822), +CONST64(0x07e9c86364648d64), CONST64(0xdb12ff2af1f1e3f1), CONST64(0xbfa2e6cc7373d173), CONST64(0x905a248212124812), +CONST64(0x3a5d807a40401d40), CONST64(0x4028104808082008), CONST64(0x56e89b95c3c32bc3), CONST64(0x337bc5dfecec97ec), +CONST64(0x9690ab4ddbdb4bdb), CONST64(0x611f5fc0a1a1bea1), CONST64(0x1c8307918d8d0e8d), CONST64(0xf5c97ac83d3df43d), +CONST64(0xccf1335b97976697), CONST64(0x0000000000000000), CONST64(0x36d483f9cfcf1bcf), CONST64(0x4587566e2b2bac2b), +CONST64(0x97b3ece17676c576), CONST64(0x64b019e682823282), CONST64(0xfea9b128d6d67fd6), CONST64(0xd87736c31b1b6c1b), +CONST64(0xc15b7774b5b5eeb5), CONST64(0x112943beafaf86af), CONST64(0x77dfd41d6a6ab56a), CONST64(0xba0da0ea50505d50), +CONST64(0x124c8a5745450945), CONST64(0xcb18fb38f3f3ebf3), CONST64(0x9df060ad3030c030), CONST64(0x2b74c3c4efef9bef), +CONST64(0xe5c37eda3f3ffc3f), CONST64(0x921caac755554955), CONST64(0x791059dba2a2b2a2), CONST64(0x0365c9e9eaea8fea), +CONST64(0x0fecca6a65658965), CONST64(0xb9686903babad2ba), CONST64(0x65935e4a2f2fbc2f), CONST64(0x4ee79d8ec0c027c0), +CONST64(0xbe81a160dede5fde), CONST64(0xe06c38fc1c1c701c), CONST64(0xbb2ee746fdfdd3fd), CONST64(0x52649a1f4d4d294d), +CONST64(0xe4e0397692927292), CONST64(0x8fbceafa7575c975), CONST64(0x301e0c3606061806), CONST64(0x249809ae8a8a128a), +CONST64(0xf940794bb2b2f2b2), CONST64(0x6359d185e6e6bfe6), CONST64(0x70361c7e0e0e380e), CONST64(0xf8633ee71f1f7c1f), +CONST64(0x37f7c45562629562), CONST64(0xeea3b53ad4d477d4), CONST64(0x29324d81a8a89aa8), CONST64(0xc4f4315296966296), +CONST64(0x9b3aef62f9f9c3f9), CONST64(0x66f697a3c5c533c5), CONST64(0x35b14a1025259425), CONST64(0xf220b2ab59597959), +CONST64(0x54ae15d084842a84), CONST64(0xb7a7e4c57272d572), CONST64(0xd5dd72ec3939e439), CONST64(0x5a6198164c4c2d4c), +CONST64(0xca3bbc945e5e655e), CONST64(0xe785f09f7878fd78), CONST64(0xddd870e53838e038), CONST64(0x148605988c8c0a8c), +CONST64(0xc6b2bf17d1d163d1), CONST64(0x410b57e4a5a5aea5), CONST64(0x434dd9a1e2e2afe2), CONST64(0x2ff8c24e61619961), +CONST64(0xf1457b42b3b3f6b3), CONST64(0x15a5423421218421), CONST64(0x94d625089c9c4a9c), CONST64(0xf0663cee1e1e781e), +CONST64(0x2252866143431143), CONST64(0x76fc93b1c7c73bc7), CONST64(0xb32be54ffcfcd7fc), CONST64(0x2014082404041004), +CONST64(0xb208a2e351515951), CONST64(0xbcc72f2599995e99), CONST64(0x4fc4da226d6da96d), CONST64(0x68391a650d0d340d), +CONST64(0x8335e979fafacffa), CONST64(0xb684a369dfdf5bdf), CONST64(0xd79bfca97e7ee57e), CONST64(0x3db4481924249024), +CONST64(0xc5d776fe3b3bec3b), CONST64(0x313d4b9aabab96ab), CONST64(0x3ed181f0cece1fce), CONST64(0x8855229911114411), +CONST64(0x0c8903838f8f068f), CONST64(0x4a6b9c044e4e254e), CONST64(0xd1517366b7b7e6b7), CONST64(0x0b60cbe0ebeb8beb), +CONST64(0xfdcc78c13c3cf03c), CONST64(0x7cbf1ffd81813e81), CONST64(0xd4fe354094946a94), CONST64(0xeb0cf31cf7f7fbf7), +CONST64(0xa1676f18b9b9deb9), CONST64(0x985f268b13134c13), CONST64(0x7d9c58512c2cb02c), CONST64(0xd6b8bb05d3d36bd3), +CONST64(0x6b5cd38ce7e7bbe7), CONST64(0x57cbdc396e6ea56e), CONST64(0x6ef395aac4c437c4), CONST64(0x180f061b03030c03), +CONST64(0x8a13acdc56564556), CONST64(0x1a49885e44440d44), CONST64(0xdf9efea07f7fe17f), CONST64(0x21374f88a9a99ea9), +CONST64(0x4d8254672a2aa82a), CONST64(0xb16d6b0abbbbd6bb), CONST64(0x46e29f87c1c123c1), CONST64(0xa202a6f153535153), +CONST64(0xae8ba572dcdc57dc), CONST64(0x582716530b0b2c0b), CONST64(0x9cd327019d9d4e9d), CONST64(0x47c1d82b6c6cad6c), +CONST64(0x95f562a43131c431), CONST64(0x87b9e8f37474cd74), CONST64(0xe309f115f6f6fff6), CONST64(0x0a438c4c46460546), +CONST64(0x092645a5acac8aac), CONST64(0x3c970fb589891e89), CONST64(0xa04428b414145014), CONST64(0x5b42dfbae1e1a3e1), +CONST64(0xb04e2ca616165816), CONST64(0xcdd274f73a3ae83a), CONST64(0x6fd0d2066969b969), CONST64(0x482d124109092409), +CONST64(0xa7ade0d77070dd70), CONST64(0xd954716fb6b6e2b6), CONST64(0xceb7bd1ed0d067d0), CONST64(0x3b7ec7d6eded93ed), +CONST64(0x2edb85e2cccc17cc), CONST64(0x2a57846842421542), CONST64(0xb4c22d2c98985a98), CONST64(0x490e55eda4a4aaa4), +CONST64(0x5d8850752828a028), CONST64(0xda31b8865c5c6d5c), CONST64(0x933fed6bf8f8c7f8), CONST64(0x44a411c286862286) +}; + +static const ulong64 sbox5[] = { +CONST64(0x18c07830d8181860), CONST64(0x2305af462623238c), CONST64(0xc67ef991b8c6c63f), CONST64(0xe8136fcdfbe8e887), +CONST64(0x874ca113cb878726), CONST64(0xb8a9626d11b8b8da), CONST64(0x0108050209010104), CONST64(0x4f426e9e0d4f4f21), +CONST64(0x36adee6c9b3636d8), CONST64(0xa6590451ffa6a6a2), CONST64(0xd2debdb90cd2d26f), CONST64(0xf5fb06f70ef5f5f3), +CONST64(0x79ef80f2967979f9), CONST64(0x6f5fcede306f6fa1), CONST64(0x91fcef3f6d91917e), CONST64(0x52aa07a4f8525255), +CONST64(0x6027fdc04760609d), CONST64(0xbc89766535bcbcca), CONST64(0x9baccd2b379b9b56), CONST64(0x8e048c018a8e8e02), +CONST64(0xa371155bd2a3a3b6), CONST64(0x0c603c186c0c0c30), CONST64(0x7bff8af6847b7bf1), CONST64(0x35b5e16a803535d4), +CONST64(0x1de8693af51d1d74), CONST64(0xe05347ddb3e0e0a7), CONST64(0xd7f6acb321d7d77b), CONST64(0xc25eed999cc2c22f), +CONST64(0x2e6d965c432e2eb8), CONST64(0x4b627a96294b4b31), CONST64(0xfea321e15dfefedf), CONST64(0x578216aed5575741), +CONST64(0x15a8412abd151554), CONST64(0x779fb6eee87777c1), CONST64(0x37a5eb6e923737dc), CONST64(0xe57b56d79ee5e5b3), +CONST64(0x9f8cd923139f9f46), CONST64(0xf0d317fd23f0f0e7), CONST64(0x4a6a7f94204a4a35), CONST64(0xda9e95a944dada4f), +CONST64(0x58fa25b0a258587d), CONST64(0xc906ca8fcfc9c903), CONST64(0x29558d527c2929a4), CONST64(0x0a5022145a0a0a28), +CONST64(0xb1e14f7f50b1b1fe), CONST64(0xa0691a5dc9a0a0ba), CONST64(0x6b7fdad6146b6bb1), CONST64(0x855cab17d985852e), +CONST64(0xbd8173673cbdbdce), CONST64(0x5dd234ba8f5d5d69), CONST64(0x1080502090101040), CONST64(0xf4f303f507f4f4f7), +CONST64(0xcb16c08bddcbcb0b), CONST64(0x3eedc67cd33e3ef8), CONST64(0x0528110a2d050514), CONST64(0x671fe6ce78676781), +CONST64(0xe47353d597e4e4b7), CONST64(0x2725bb4e0227279c), CONST64(0x4132588273414119), CONST64(0x8b2c9d0ba78b8b16), +CONST64(0xa7510153f6a7a7a6), CONST64(0x7dcf94fab27d7de9), CONST64(0x95dcfb374995956e), CONST64(0xd88e9fad56d8d847), +CONST64(0xfb8b30eb70fbfbcb), CONST64(0xee2371c1cdeeee9f), CONST64(0x7cc791f8bb7c7ced), CONST64(0x6617e3cc71666685), +CONST64(0xdda68ea77bdddd53), CONST64(0x17b84b2eaf17175c), CONST64(0x4702468e45474701), CONST64(0x9e84dc211a9e9e42), +CONST64(0xca1ec589d4caca0f), CONST64(0x2d75995a582d2db4), CONST64(0xbf9179632ebfbfc6), CONST64(0x07381b0e3f07071c), +CONST64(0xad012347acadad8e), CONST64(0x5aea2fb4b05a5a75), CONST64(0x836cb51bef838336), CONST64(0x3385ff66b63333cc), +CONST64(0x633ff2c65c636391), CONST64(0x02100a0412020208), CONST64(0xaa39384993aaaa92), CONST64(0x71afa8e2de7171d9), +CONST64(0xc80ecf8dc6c8c807), CONST64(0x19c87d32d1191964), CONST64(0x497270923b494939), CONST64(0xd9869aaf5fd9d943), +CONST64(0xf2c31df931f2f2ef), CONST64(0xe34b48dba8e3e3ab), CONST64(0x5be22ab6b95b5b71), CONST64(0x8834920dbc88881a), +CONST64(0x9aa4c8293e9a9a52), CONST64(0x262dbe4c0b262698), CONST64(0x328dfa64bf3232c8), CONST64(0xb0e94a7d59b0b0fa), +CONST64(0xe91b6acff2e9e983), CONST64(0x0f78331e770f0f3c), CONST64(0xd5e6a6b733d5d573), CONST64(0x8074ba1df480803a), +CONST64(0xbe997c6127bebec2), CONST64(0xcd26de87ebcdcd13), CONST64(0x34bde468893434d0), CONST64(0x487a75903248483d), +CONST64(0xffab24e354ffffdb), CONST64(0x7af78ff48d7a7af5), CONST64(0x90f4ea3d6490907a), CONST64(0x5fc23ebe9d5f5f61), +CONST64(0x201da0403d202080), CONST64(0x6867d5d00f6868bd), CONST64(0x1ad07234ca1a1a68), CONST64(0xae192c41b7aeae82), +CONST64(0xb4c95e757db4b4ea), CONST64(0x549a19a8ce54544d), CONST64(0x93ece53b7f939376), CONST64(0x220daa442f222288), +CONST64(0x6407e9c86364648d), CONST64(0xf1db12ff2af1f1e3), CONST64(0x73bfa2e6cc7373d1), CONST64(0x12905a2482121248), +CONST64(0x403a5d807a40401d), CONST64(0x0840281048080820), CONST64(0xc356e89b95c3c32b), CONST64(0xec337bc5dfecec97), +CONST64(0xdb9690ab4ddbdb4b), CONST64(0xa1611f5fc0a1a1be), CONST64(0x8d1c8307918d8d0e), CONST64(0x3df5c97ac83d3df4), +CONST64(0x97ccf1335b979766), CONST64(0x0000000000000000), CONST64(0xcf36d483f9cfcf1b), CONST64(0x2b4587566e2b2bac), +CONST64(0x7697b3ece17676c5), CONST64(0x8264b019e6828232), CONST64(0xd6fea9b128d6d67f), CONST64(0x1bd87736c31b1b6c), +CONST64(0xb5c15b7774b5b5ee), CONST64(0xaf112943beafaf86), CONST64(0x6a77dfd41d6a6ab5), CONST64(0x50ba0da0ea50505d), +CONST64(0x45124c8a57454509), CONST64(0xf3cb18fb38f3f3eb), CONST64(0x309df060ad3030c0), CONST64(0xef2b74c3c4efef9b), +CONST64(0x3fe5c37eda3f3ffc), CONST64(0x55921caac7555549), CONST64(0xa2791059dba2a2b2), CONST64(0xea0365c9e9eaea8f), +CONST64(0x650fecca6a656589), CONST64(0xbab9686903babad2), CONST64(0x2f65935e4a2f2fbc), CONST64(0xc04ee79d8ec0c027), +CONST64(0xdebe81a160dede5f), CONST64(0x1ce06c38fc1c1c70), CONST64(0xfdbb2ee746fdfdd3), CONST64(0x4d52649a1f4d4d29), +CONST64(0x92e4e03976929272), CONST64(0x758fbceafa7575c9), CONST64(0x06301e0c36060618), CONST64(0x8a249809ae8a8a12), +CONST64(0xb2f940794bb2b2f2), CONST64(0xe66359d185e6e6bf), CONST64(0x0e70361c7e0e0e38), CONST64(0x1ff8633ee71f1f7c), +CONST64(0x6237f7c455626295), CONST64(0xd4eea3b53ad4d477), CONST64(0xa829324d81a8a89a), CONST64(0x96c4f43152969662), +CONST64(0xf99b3aef62f9f9c3), CONST64(0xc566f697a3c5c533), CONST64(0x2535b14a10252594), CONST64(0x59f220b2ab595979), +CONST64(0x8454ae15d084842a), CONST64(0x72b7a7e4c57272d5), CONST64(0x39d5dd72ec3939e4), CONST64(0x4c5a6198164c4c2d), +CONST64(0x5eca3bbc945e5e65), CONST64(0x78e785f09f7878fd), CONST64(0x38ddd870e53838e0), CONST64(0x8c148605988c8c0a), +CONST64(0xd1c6b2bf17d1d163), CONST64(0xa5410b57e4a5a5ae), CONST64(0xe2434dd9a1e2e2af), CONST64(0x612ff8c24e616199), +CONST64(0xb3f1457b42b3b3f6), CONST64(0x2115a54234212184), CONST64(0x9c94d625089c9c4a), CONST64(0x1ef0663cee1e1e78), +CONST64(0x4322528661434311), CONST64(0xc776fc93b1c7c73b), CONST64(0xfcb32be54ffcfcd7), CONST64(0x0420140824040410), +CONST64(0x51b208a2e3515159), CONST64(0x99bcc72f2599995e), CONST64(0x6d4fc4da226d6da9), CONST64(0x0d68391a650d0d34), +CONST64(0xfa8335e979fafacf), CONST64(0xdfb684a369dfdf5b), CONST64(0x7ed79bfca97e7ee5), CONST64(0x243db44819242490), +CONST64(0x3bc5d776fe3b3bec), CONST64(0xab313d4b9aabab96), CONST64(0xce3ed181f0cece1f), CONST64(0x1188552299111144), +CONST64(0x8f0c8903838f8f06), CONST64(0x4e4a6b9c044e4e25), CONST64(0xb7d1517366b7b7e6), CONST64(0xeb0b60cbe0ebeb8b), +CONST64(0x3cfdcc78c13c3cf0), CONST64(0x817cbf1ffd81813e), CONST64(0x94d4fe354094946a), CONST64(0xf7eb0cf31cf7f7fb), +CONST64(0xb9a1676f18b9b9de), CONST64(0x13985f268b13134c), CONST64(0x2c7d9c58512c2cb0), CONST64(0xd3d6b8bb05d3d36b), +CONST64(0xe76b5cd38ce7e7bb), CONST64(0x6e57cbdc396e6ea5), CONST64(0xc46ef395aac4c437), CONST64(0x03180f061b03030c), +CONST64(0x568a13acdc565645), CONST64(0x441a49885e44440d), CONST64(0x7fdf9efea07f7fe1), CONST64(0xa921374f88a9a99e), +CONST64(0x2a4d8254672a2aa8), CONST64(0xbbb16d6b0abbbbd6), CONST64(0xc146e29f87c1c123), CONST64(0x53a202a6f1535351), +CONST64(0xdcae8ba572dcdc57), CONST64(0x0b582716530b0b2c), CONST64(0x9d9cd327019d9d4e), CONST64(0x6c47c1d82b6c6cad), +CONST64(0x3195f562a43131c4), CONST64(0x7487b9e8f37474cd), CONST64(0xf6e309f115f6f6ff), CONST64(0x460a438c4c464605), +CONST64(0xac092645a5acac8a), CONST64(0x893c970fb589891e), CONST64(0x14a04428b4141450), CONST64(0xe15b42dfbae1e1a3), +CONST64(0x16b04e2ca6161658), CONST64(0x3acdd274f73a3ae8), CONST64(0x696fd0d2066969b9), CONST64(0x09482d1241090924), +CONST64(0x70a7ade0d77070dd), CONST64(0xb6d954716fb6b6e2), CONST64(0xd0ceb7bd1ed0d067), CONST64(0xed3b7ec7d6eded93), +CONST64(0xcc2edb85e2cccc17), CONST64(0x422a578468424215), CONST64(0x98b4c22d2c98985a), CONST64(0xa4490e55eda4a4aa), +CONST64(0x285d8850752828a0), CONST64(0x5cda31b8865c5c6d), CONST64(0xf8933fed6bf8f8c7), CONST64(0x8644a411c2868622) +}; + +static const ulong64 sbox6[] = { +CONST64(0x6018c07830d81818), CONST64(0x8c2305af46262323), CONST64(0x3fc67ef991b8c6c6), CONST64(0x87e8136fcdfbe8e8), +CONST64(0x26874ca113cb8787), CONST64(0xdab8a9626d11b8b8), CONST64(0x0401080502090101), CONST64(0x214f426e9e0d4f4f), +CONST64(0xd836adee6c9b3636), CONST64(0xa2a6590451ffa6a6), CONST64(0x6fd2debdb90cd2d2), CONST64(0xf3f5fb06f70ef5f5), +CONST64(0xf979ef80f2967979), CONST64(0xa16f5fcede306f6f), CONST64(0x7e91fcef3f6d9191), CONST64(0x5552aa07a4f85252), +CONST64(0x9d6027fdc0476060), CONST64(0xcabc89766535bcbc), CONST64(0x569baccd2b379b9b), CONST64(0x028e048c018a8e8e), +CONST64(0xb6a371155bd2a3a3), CONST64(0x300c603c186c0c0c), CONST64(0xf17bff8af6847b7b), CONST64(0xd435b5e16a803535), +CONST64(0x741de8693af51d1d), CONST64(0xa7e05347ddb3e0e0), CONST64(0x7bd7f6acb321d7d7), CONST64(0x2fc25eed999cc2c2), +CONST64(0xb82e6d965c432e2e), CONST64(0x314b627a96294b4b), CONST64(0xdffea321e15dfefe), CONST64(0x41578216aed55757), +CONST64(0x5415a8412abd1515), CONST64(0xc1779fb6eee87777), CONST64(0xdc37a5eb6e923737), CONST64(0xb3e57b56d79ee5e5), +CONST64(0x469f8cd923139f9f), CONST64(0xe7f0d317fd23f0f0), CONST64(0x354a6a7f94204a4a), CONST64(0x4fda9e95a944dada), +CONST64(0x7d58fa25b0a25858), CONST64(0x03c906ca8fcfc9c9), CONST64(0xa429558d527c2929), CONST64(0x280a5022145a0a0a), +CONST64(0xfeb1e14f7f50b1b1), CONST64(0xbaa0691a5dc9a0a0), CONST64(0xb16b7fdad6146b6b), CONST64(0x2e855cab17d98585), +CONST64(0xcebd8173673cbdbd), CONST64(0x695dd234ba8f5d5d), CONST64(0x4010805020901010), CONST64(0xf7f4f303f507f4f4), +CONST64(0x0bcb16c08bddcbcb), CONST64(0xf83eedc67cd33e3e), CONST64(0x140528110a2d0505), CONST64(0x81671fe6ce786767), +CONST64(0xb7e47353d597e4e4), CONST64(0x9c2725bb4e022727), CONST64(0x1941325882734141), CONST64(0x168b2c9d0ba78b8b), +CONST64(0xa6a7510153f6a7a7), CONST64(0xe97dcf94fab27d7d), CONST64(0x6e95dcfb37499595), CONST64(0x47d88e9fad56d8d8), +CONST64(0xcbfb8b30eb70fbfb), CONST64(0x9fee2371c1cdeeee), CONST64(0xed7cc791f8bb7c7c), CONST64(0x856617e3cc716666), +CONST64(0x53dda68ea77bdddd), CONST64(0x5c17b84b2eaf1717), CONST64(0x014702468e454747), CONST64(0x429e84dc211a9e9e), +CONST64(0x0fca1ec589d4caca), CONST64(0xb42d75995a582d2d), CONST64(0xc6bf9179632ebfbf), CONST64(0x1c07381b0e3f0707), +CONST64(0x8ead012347acadad), CONST64(0x755aea2fb4b05a5a), CONST64(0x36836cb51bef8383), CONST64(0xcc3385ff66b63333), +CONST64(0x91633ff2c65c6363), CONST64(0x0802100a04120202), CONST64(0x92aa39384993aaaa), CONST64(0xd971afa8e2de7171), +CONST64(0x07c80ecf8dc6c8c8), CONST64(0x6419c87d32d11919), CONST64(0x39497270923b4949), CONST64(0x43d9869aaf5fd9d9), +CONST64(0xeff2c31df931f2f2), CONST64(0xabe34b48dba8e3e3), CONST64(0x715be22ab6b95b5b), CONST64(0x1a8834920dbc8888), +CONST64(0x529aa4c8293e9a9a), CONST64(0x98262dbe4c0b2626), CONST64(0xc8328dfa64bf3232), CONST64(0xfab0e94a7d59b0b0), +CONST64(0x83e91b6acff2e9e9), CONST64(0x3c0f78331e770f0f), CONST64(0x73d5e6a6b733d5d5), CONST64(0x3a8074ba1df48080), +CONST64(0xc2be997c6127bebe), CONST64(0x13cd26de87ebcdcd), CONST64(0xd034bde468893434), CONST64(0x3d487a7590324848), +CONST64(0xdbffab24e354ffff), CONST64(0xf57af78ff48d7a7a), CONST64(0x7a90f4ea3d649090), CONST64(0x615fc23ebe9d5f5f), +CONST64(0x80201da0403d2020), CONST64(0xbd6867d5d00f6868), CONST64(0x681ad07234ca1a1a), CONST64(0x82ae192c41b7aeae), +CONST64(0xeab4c95e757db4b4), CONST64(0x4d549a19a8ce5454), CONST64(0x7693ece53b7f9393), CONST64(0x88220daa442f2222), +CONST64(0x8d6407e9c8636464), CONST64(0xe3f1db12ff2af1f1), CONST64(0xd173bfa2e6cc7373), CONST64(0x4812905a24821212), +CONST64(0x1d403a5d807a4040), CONST64(0x2008402810480808), CONST64(0x2bc356e89b95c3c3), CONST64(0x97ec337bc5dfecec), +CONST64(0x4bdb9690ab4ddbdb), CONST64(0xbea1611f5fc0a1a1), CONST64(0x0e8d1c8307918d8d), CONST64(0xf43df5c97ac83d3d), +CONST64(0x6697ccf1335b9797), CONST64(0x0000000000000000), CONST64(0x1bcf36d483f9cfcf), CONST64(0xac2b4587566e2b2b), +CONST64(0xc57697b3ece17676), CONST64(0x328264b019e68282), CONST64(0x7fd6fea9b128d6d6), CONST64(0x6c1bd87736c31b1b), +CONST64(0xeeb5c15b7774b5b5), CONST64(0x86af112943beafaf), CONST64(0xb56a77dfd41d6a6a), CONST64(0x5d50ba0da0ea5050), +CONST64(0x0945124c8a574545), CONST64(0xebf3cb18fb38f3f3), CONST64(0xc0309df060ad3030), CONST64(0x9bef2b74c3c4efef), +CONST64(0xfc3fe5c37eda3f3f), CONST64(0x4955921caac75555), CONST64(0xb2a2791059dba2a2), CONST64(0x8fea0365c9e9eaea), +CONST64(0x89650fecca6a6565), CONST64(0xd2bab9686903baba), CONST64(0xbc2f65935e4a2f2f), CONST64(0x27c04ee79d8ec0c0), +CONST64(0x5fdebe81a160dede), CONST64(0x701ce06c38fc1c1c), CONST64(0xd3fdbb2ee746fdfd), CONST64(0x294d52649a1f4d4d), +CONST64(0x7292e4e039769292), CONST64(0xc9758fbceafa7575), CONST64(0x1806301e0c360606), CONST64(0x128a249809ae8a8a), +CONST64(0xf2b2f940794bb2b2), CONST64(0xbfe66359d185e6e6), CONST64(0x380e70361c7e0e0e), CONST64(0x7c1ff8633ee71f1f), +CONST64(0x956237f7c4556262), CONST64(0x77d4eea3b53ad4d4), CONST64(0x9aa829324d81a8a8), CONST64(0x6296c4f431529696), +CONST64(0xc3f99b3aef62f9f9), CONST64(0x33c566f697a3c5c5), CONST64(0x942535b14a102525), CONST64(0x7959f220b2ab5959), +CONST64(0x2a8454ae15d08484), CONST64(0xd572b7a7e4c57272), CONST64(0xe439d5dd72ec3939), CONST64(0x2d4c5a6198164c4c), +CONST64(0x655eca3bbc945e5e), CONST64(0xfd78e785f09f7878), CONST64(0xe038ddd870e53838), CONST64(0x0a8c148605988c8c), +CONST64(0x63d1c6b2bf17d1d1), CONST64(0xaea5410b57e4a5a5), CONST64(0xafe2434dd9a1e2e2), CONST64(0x99612ff8c24e6161), +CONST64(0xf6b3f1457b42b3b3), CONST64(0x842115a542342121), CONST64(0x4a9c94d625089c9c), CONST64(0x781ef0663cee1e1e), +CONST64(0x1143225286614343), CONST64(0x3bc776fc93b1c7c7), CONST64(0xd7fcb32be54ffcfc), CONST64(0x1004201408240404), +CONST64(0x5951b208a2e35151), CONST64(0x5e99bcc72f259999), CONST64(0xa96d4fc4da226d6d), CONST64(0x340d68391a650d0d), +CONST64(0xcffa8335e979fafa), CONST64(0x5bdfb684a369dfdf), CONST64(0xe57ed79bfca97e7e), CONST64(0x90243db448192424), +CONST64(0xec3bc5d776fe3b3b), CONST64(0x96ab313d4b9aabab), CONST64(0x1fce3ed181f0cece), CONST64(0x4411885522991111), +CONST64(0x068f0c8903838f8f), CONST64(0x254e4a6b9c044e4e), CONST64(0xe6b7d1517366b7b7), CONST64(0x8beb0b60cbe0ebeb), +CONST64(0xf03cfdcc78c13c3c), CONST64(0x3e817cbf1ffd8181), CONST64(0x6a94d4fe35409494), CONST64(0xfbf7eb0cf31cf7f7), +CONST64(0xdeb9a1676f18b9b9), CONST64(0x4c13985f268b1313), CONST64(0xb02c7d9c58512c2c), CONST64(0x6bd3d6b8bb05d3d3), +CONST64(0xbbe76b5cd38ce7e7), CONST64(0xa56e57cbdc396e6e), CONST64(0x37c46ef395aac4c4), CONST64(0x0c03180f061b0303), +CONST64(0x45568a13acdc5656), CONST64(0x0d441a49885e4444), CONST64(0xe17fdf9efea07f7f), CONST64(0x9ea921374f88a9a9), +CONST64(0xa82a4d8254672a2a), CONST64(0xd6bbb16d6b0abbbb), CONST64(0x23c146e29f87c1c1), CONST64(0x5153a202a6f15353), +CONST64(0x57dcae8ba572dcdc), CONST64(0x2c0b582716530b0b), CONST64(0x4e9d9cd327019d9d), CONST64(0xad6c47c1d82b6c6c), +CONST64(0xc43195f562a43131), CONST64(0xcd7487b9e8f37474), CONST64(0xfff6e309f115f6f6), CONST64(0x05460a438c4c4646), +CONST64(0x8aac092645a5acac), CONST64(0x1e893c970fb58989), CONST64(0x5014a04428b41414), CONST64(0xa3e15b42dfbae1e1), +CONST64(0x5816b04e2ca61616), CONST64(0xe83acdd274f73a3a), CONST64(0xb9696fd0d2066969), CONST64(0x2409482d12410909), +CONST64(0xdd70a7ade0d77070), CONST64(0xe2b6d954716fb6b6), CONST64(0x67d0ceb7bd1ed0d0), CONST64(0x93ed3b7ec7d6eded), +CONST64(0x17cc2edb85e2cccc), CONST64(0x15422a5784684242), CONST64(0x5a98b4c22d2c9898), CONST64(0xaaa4490e55eda4a4), +CONST64(0xa0285d8850752828), CONST64(0x6d5cda31b8865c5c), CONST64(0xc7f8933fed6bf8f8), CONST64(0x228644a411c28686) +}; + +static const ulong64 sbox7[] = { +CONST64(0x186018c07830d818), CONST64(0x238c2305af462623), CONST64(0xc63fc67ef991b8c6), CONST64(0xe887e8136fcdfbe8), +CONST64(0x8726874ca113cb87), CONST64(0xb8dab8a9626d11b8), CONST64(0x0104010805020901), CONST64(0x4f214f426e9e0d4f), +CONST64(0x36d836adee6c9b36), CONST64(0xa6a2a6590451ffa6), CONST64(0xd26fd2debdb90cd2), CONST64(0xf5f3f5fb06f70ef5), +CONST64(0x79f979ef80f29679), CONST64(0x6fa16f5fcede306f), CONST64(0x917e91fcef3f6d91), CONST64(0x525552aa07a4f852), +CONST64(0x609d6027fdc04760), CONST64(0xbccabc89766535bc), CONST64(0x9b569baccd2b379b), CONST64(0x8e028e048c018a8e), +CONST64(0xa3b6a371155bd2a3), CONST64(0x0c300c603c186c0c), CONST64(0x7bf17bff8af6847b), CONST64(0x35d435b5e16a8035), +CONST64(0x1d741de8693af51d), CONST64(0xe0a7e05347ddb3e0), CONST64(0xd77bd7f6acb321d7), CONST64(0xc22fc25eed999cc2), +CONST64(0x2eb82e6d965c432e), CONST64(0x4b314b627a96294b), CONST64(0xfedffea321e15dfe), CONST64(0x5741578216aed557), +CONST64(0x155415a8412abd15), CONST64(0x77c1779fb6eee877), CONST64(0x37dc37a5eb6e9237), CONST64(0xe5b3e57b56d79ee5), +CONST64(0x9f469f8cd923139f), CONST64(0xf0e7f0d317fd23f0), CONST64(0x4a354a6a7f94204a), CONST64(0xda4fda9e95a944da), +CONST64(0x587d58fa25b0a258), CONST64(0xc903c906ca8fcfc9), CONST64(0x29a429558d527c29), CONST64(0x0a280a5022145a0a), +CONST64(0xb1feb1e14f7f50b1), CONST64(0xa0baa0691a5dc9a0), CONST64(0x6bb16b7fdad6146b), CONST64(0x852e855cab17d985), +CONST64(0xbdcebd8173673cbd), CONST64(0x5d695dd234ba8f5d), CONST64(0x1040108050209010), CONST64(0xf4f7f4f303f507f4), +CONST64(0xcb0bcb16c08bddcb), CONST64(0x3ef83eedc67cd33e), CONST64(0x05140528110a2d05), CONST64(0x6781671fe6ce7867), +CONST64(0xe4b7e47353d597e4), CONST64(0x279c2725bb4e0227), CONST64(0x4119413258827341), CONST64(0x8b168b2c9d0ba78b), +CONST64(0xa7a6a7510153f6a7), CONST64(0x7de97dcf94fab27d), CONST64(0x956e95dcfb374995), CONST64(0xd847d88e9fad56d8), +CONST64(0xfbcbfb8b30eb70fb), CONST64(0xee9fee2371c1cdee), CONST64(0x7ced7cc791f8bb7c), CONST64(0x66856617e3cc7166), +CONST64(0xdd53dda68ea77bdd), CONST64(0x175c17b84b2eaf17), CONST64(0x47014702468e4547), CONST64(0x9e429e84dc211a9e), +CONST64(0xca0fca1ec589d4ca), CONST64(0x2db42d75995a582d), CONST64(0xbfc6bf9179632ebf), CONST64(0x071c07381b0e3f07), +CONST64(0xad8ead012347acad), CONST64(0x5a755aea2fb4b05a), CONST64(0x8336836cb51bef83), CONST64(0x33cc3385ff66b633), +CONST64(0x6391633ff2c65c63), CONST64(0x020802100a041202), CONST64(0xaa92aa39384993aa), CONST64(0x71d971afa8e2de71), +CONST64(0xc807c80ecf8dc6c8), CONST64(0x196419c87d32d119), CONST64(0x4939497270923b49), CONST64(0xd943d9869aaf5fd9), +CONST64(0xf2eff2c31df931f2), CONST64(0xe3abe34b48dba8e3), CONST64(0x5b715be22ab6b95b), CONST64(0x881a8834920dbc88), +CONST64(0x9a529aa4c8293e9a), CONST64(0x2698262dbe4c0b26), CONST64(0x32c8328dfa64bf32), CONST64(0xb0fab0e94a7d59b0), +CONST64(0xe983e91b6acff2e9), CONST64(0x0f3c0f78331e770f), CONST64(0xd573d5e6a6b733d5), CONST64(0x803a8074ba1df480), +CONST64(0xbec2be997c6127be), CONST64(0xcd13cd26de87ebcd), CONST64(0x34d034bde4688934), CONST64(0x483d487a75903248), +CONST64(0xffdbffab24e354ff), CONST64(0x7af57af78ff48d7a), CONST64(0x907a90f4ea3d6490), CONST64(0x5f615fc23ebe9d5f), +CONST64(0x2080201da0403d20), CONST64(0x68bd6867d5d00f68), CONST64(0x1a681ad07234ca1a), CONST64(0xae82ae192c41b7ae), +CONST64(0xb4eab4c95e757db4), CONST64(0x544d549a19a8ce54), CONST64(0x937693ece53b7f93), CONST64(0x2288220daa442f22), +CONST64(0x648d6407e9c86364), CONST64(0xf1e3f1db12ff2af1), CONST64(0x73d173bfa2e6cc73), CONST64(0x124812905a248212), +CONST64(0x401d403a5d807a40), CONST64(0x0820084028104808), CONST64(0xc32bc356e89b95c3), CONST64(0xec97ec337bc5dfec), +CONST64(0xdb4bdb9690ab4ddb), CONST64(0xa1bea1611f5fc0a1), CONST64(0x8d0e8d1c8307918d), CONST64(0x3df43df5c97ac83d), +CONST64(0x976697ccf1335b97), CONST64(0x0000000000000000), CONST64(0xcf1bcf36d483f9cf), CONST64(0x2bac2b4587566e2b), +CONST64(0x76c57697b3ece176), CONST64(0x82328264b019e682), CONST64(0xd67fd6fea9b128d6), CONST64(0x1b6c1bd87736c31b), +CONST64(0xb5eeb5c15b7774b5), CONST64(0xaf86af112943beaf), CONST64(0x6ab56a77dfd41d6a), CONST64(0x505d50ba0da0ea50), +CONST64(0x450945124c8a5745), CONST64(0xf3ebf3cb18fb38f3), CONST64(0x30c0309df060ad30), CONST64(0xef9bef2b74c3c4ef), +CONST64(0x3ffc3fe5c37eda3f), CONST64(0x554955921caac755), CONST64(0xa2b2a2791059dba2), CONST64(0xea8fea0365c9e9ea), +CONST64(0x6589650fecca6a65), CONST64(0xbad2bab9686903ba), CONST64(0x2fbc2f65935e4a2f), CONST64(0xc027c04ee79d8ec0), +CONST64(0xde5fdebe81a160de), CONST64(0x1c701ce06c38fc1c), CONST64(0xfdd3fdbb2ee746fd), CONST64(0x4d294d52649a1f4d), +CONST64(0x927292e4e0397692), CONST64(0x75c9758fbceafa75), CONST64(0x061806301e0c3606), CONST64(0x8a128a249809ae8a), +CONST64(0xb2f2b2f940794bb2), CONST64(0xe6bfe66359d185e6), CONST64(0x0e380e70361c7e0e), CONST64(0x1f7c1ff8633ee71f), +CONST64(0x62956237f7c45562), CONST64(0xd477d4eea3b53ad4), CONST64(0xa89aa829324d81a8), CONST64(0x966296c4f4315296), +CONST64(0xf9c3f99b3aef62f9), CONST64(0xc533c566f697a3c5), CONST64(0x25942535b14a1025), CONST64(0x597959f220b2ab59), +CONST64(0x842a8454ae15d084), CONST64(0x72d572b7a7e4c572), CONST64(0x39e439d5dd72ec39), CONST64(0x4c2d4c5a6198164c), +CONST64(0x5e655eca3bbc945e), CONST64(0x78fd78e785f09f78), CONST64(0x38e038ddd870e538), CONST64(0x8c0a8c148605988c), +CONST64(0xd163d1c6b2bf17d1), CONST64(0xa5aea5410b57e4a5), CONST64(0xe2afe2434dd9a1e2), CONST64(0x6199612ff8c24e61), +CONST64(0xb3f6b3f1457b42b3), CONST64(0x21842115a5423421), CONST64(0x9c4a9c94d625089c), CONST64(0x1e781ef0663cee1e), +CONST64(0x4311432252866143), CONST64(0xc73bc776fc93b1c7), CONST64(0xfcd7fcb32be54ffc), CONST64(0x0410042014082404), +CONST64(0x515951b208a2e351), CONST64(0x995e99bcc72f2599), CONST64(0x6da96d4fc4da226d), CONST64(0x0d340d68391a650d), +CONST64(0xfacffa8335e979fa), CONST64(0xdf5bdfb684a369df), CONST64(0x7ee57ed79bfca97e), CONST64(0x2490243db4481924), +CONST64(0x3bec3bc5d776fe3b), CONST64(0xab96ab313d4b9aab), CONST64(0xce1fce3ed181f0ce), CONST64(0x1144118855229911), +CONST64(0x8f068f0c8903838f), CONST64(0x4e254e4a6b9c044e), CONST64(0xb7e6b7d1517366b7), CONST64(0xeb8beb0b60cbe0eb), +CONST64(0x3cf03cfdcc78c13c), CONST64(0x813e817cbf1ffd81), CONST64(0x946a94d4fe354094), CONST64(0xf7fbf7eb0cf31cf7), +CONST64(0xb9deb9a1676f18b9), CONST64(0x134c13985f268b13), CONST64(0x2cb02c7d9c58512c), CONST64(0xd36bd3d6b8bb05d3), +CONST64(0xe7bbe76b5cd38ce7), CONST64(0x6ea56e57cbdc396e), CONST64(0xc437c46ef395aac4), CONST64(0x030c03180f061b03), +CONST64(0x5645568a13acdc56), CONST64(0x440d441a49885e44), CONST64(0x7fe17fdf9efea07f), CONST64(0xa99ea921374f88a9), +CONST64(0x2aa82a4d8254672a), CONST64(0xbbd6bbb16d6b0abb), CONST64(0xc123c146e29f87c1), CONST64(0x535153a202a6f153), +CONST64(0xdc57dcae8ba572dc), CONST64(0x0b2c0b582716530b), CONST64(0x9d4e9d9cd327019d), CONST64(0x6cad6c47c1d82b6c), +CONST64(0x31c43195f562a431), CONST64(0x74cd7487b9e8f374), CONST64(0xf6fff6e309f115f6), CONST64(0x4605460a438c4c46), +CONST64(0xac8aac092645a5ac), CONST64(0x891e893c970fb589), CONST64(0x145014a04428b414), CONST64(0xe1a3e15b42dfbae1), +CONST64(0x165816b04e2ca616), CONST64(0x3ae83acdd274f73a), CONST64(0x69b9696fd0d20669), CONST64(0x092409482d124109), +CONST64(0x70dd70a7ade0d770), CONST64(0xb6e2b6d954716fb6), CONST64(0xd067d0ceb7bd1ed0), CONST64(0xed93ed3b7ec7d6ed), +CONST64(0xcc17cc2edb85e2cc), CONST64(0x4215422a57846842), CONST64(0x985a98b4c22d2c98), CONST64(0xa4aaa4490e55eda4), +CONST64(0x28a0285d88507528), CONST64(0x5c6d5cda31b8865c), CONST64(0xf8c7f8933fed6bf8), CONST64(0x86228644a411c286) +}; + +#endif + +static const ulong64 cont[] = { +CONST64(0x1823c6e887b8014f), +CONST64(0x36a6d2f5796f9152), +CONST64(0x60bc9b8ea30c7b35), +CONST64(0x1de0d7c22e4bfe57), +CONST64(0x157737e59ff04ada), +CONST64(0x58c9290ab1a06b85), +CONST64(0xbd5d10f4cb3e0567), +CONST64(0xe427418ba77d95d8), +CONST64(0xfbee7c66dd17479e), +CONST64(0xca2dbf07ad5a8333), +CONST64(0x6302aa71c81949d9), +}; + +#endif /* LTC_WHIRLTAB_C */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt.h new file mode 100644 index 0000000..c310a8c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt.h @@ -0,0 +1,95 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMCRYPT_H_ +#define TOMCRYPT_H_ +#include +#include +#include +#include +#include +#include +#include +#include + +/* use configuration data */ +#include "tomcrypt_custom.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* version */ +#define CRYPT 0x0118 +#define SCRYPT "1.18.2-develop" + +/* max size of either a cipher/hash block or symmetric key [largest of the two] */ +#define MAXBLOCKSIZE 144 + +#ifndef TAB_SIZE +/* descriptor table size */ +#define TAB_SIZE 34 +#endif + +/* 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_OVERFLOW, /* An overflow of a value was detected/prevented */ + + CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */ + + CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */ + + 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 */ + + CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */ +}; + +#include "tomcrypt_cfg.h" +#include "tomcrypt_macros.h" +#include "tomcrypt_cipher.h" +#include "tomcrypt_hash.h" +#include "tomcrypt_mac.h" +#include "tomcrypt_prng.h" +#include "tomcrypt_pk.h" +#include "tomcrypt_math.h" +#include "tomcrypt_misc.h" +#include "tomcrypt_argchk.h" +#include "tomcrypt_pkcs.h" + +#ifdef __cplusplus + } +#endif + +#endif /* TOMCRYPT_H_ */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h new file mode 100644 index 0000000..f3884e9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Defines the LTC_ARGCHK macro used within the library */ +/* ARGTYPE is defined in tomcrypt_cfg.h */ + +/* ARGTYPE is per default defined to 0 */ +#if ARGTYPE == 0 + +#include + +LTC_NORETURN void crypt_argchk(const char *v, const char *s, int d); +#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) +#define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) + +#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) LTC_UNUSED_PARAM(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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h new file mode 100644 index 0000000..1b50266 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ +#ifndef TOMCRYPT_ARM_NEON_H +#define TOMCRYPT_ARM_NEON_H + +#include + +struct tomcrypt_arm_neon_state { + ulong32 state; +}; + +/* Temporarily enables neon instructions */ +void tomcrypt_arm_neon_enable(struct tomcrypt_arm_neon_state *state); +/* Disables neon instructions after a call to tomcrypt_arm_neon_enable() */ +void tomcrypt_arm_neon_disable(struct tomcrypt_arm_neon_state *state); + +#endif /*TOMCRYPT_ARM_NEON_H*/ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h new file mode 100644 index 0000000..3dad466 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h @@ -0,0 +1,323 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* This is the build config file. + * + * With this you can setup what to include/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 +#elif !defined(LTC_CALL) + #define LTC_CALL +#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 + +/* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */ +#if defined(__GNUC__) || defined(__xlc__) + #define LTC_INLINE __inline__ +#elif defined(_MSC_VER) || defined(__HP_cc) + #define LTC_INLINE __inline +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define LTC_INLINE inline +#else + #define LTC_INLINE +#endif + +#if defined(__clang__) || defined(__GNUC_MINOR__) +#define LTC_NORETURN __attribute__ ((noreturn)) +#elif defined(_MSC_VER) +#define LTC_NORETURN __declspec(noreturn) +#else +#define LTC_NORETURN +#endif + +/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ +#ifndef ARGTYPE + #define ARGTYPE 0 +#endif + +#undef LTC_ENCRYPT +#define LTC_ENCRYPT 0 +#undef LTC_DECRYPT +#define LTC_DECRYPT 1 + +/* 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/i386 32bit */ +#if defined(__i386__) || defined(__i386) || defined(_M_IX86) + #define ENDIAN_LITTLE + #define ENDIAN_32BITWORD + #define LTC_FAST +#endif + +/* detect amd64/x64 */ +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) + #define ENDIAN_LITTLE + #define ENDIAN_64BITWORD + #define LTC_FAST +#endif + +/* detect PPC32 */ +#if defined(LTC_PPC32) + #define ENDIAN_BIG + #define ENDIAN_32BITWORD + #define LTC_FAST +#endif + +/* detects MIPS R5900 processors (PS2) */ +#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips)) + #define ENDIAN_64BITWORD + #if defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) + #define ENDIAN_BIG + #else + #define ENDIAN_LITTLE + #endif +#endif + +/* detect AIX */ +#if defined(_AIX) && defined(_BIG_ENDIAN) + #define ENDIAN_BIG + #if defined(__LP64__) || defined(_ARCH_PPC64) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect HP-UX */ +#if defined(__hpux) || defined(__hpux__) + #define ENDIAN_BIG + #if defined(__ia64) || defined(__ia64__) || defined(__LP64__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect Apple OS X */ +#if defined(__APPLE__) && defined(__MACH__) + #if defined(__LITTLE_ENDIAN__) || defined(__x86_64__) + #define ENDIAN_LITTLE + #else + #define ENDIAN_BIG + #endif + #if defined(__LP64__) || defined(__x86_64__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect SPARC and SPARC64 */ +#if defined(__sparc__) || defined(__sparc) + #define ENDIAN_BIG + #if defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect IBM S390(x) */ +#if defined(__s390x__) || defined(__s390__) + #define ENDIAN_BIG + #if defined(__s390x__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect PPC64 */ +#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) + #define ENDIAN_64BITWORD + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define ENDIAN_BIG + #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define ENDIAN_LITTLE + #endif + #define LTC_FAST +#endif + +/* endianness fallback */ +#if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE) + #if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN || \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ + defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \ + defined(__BIG_ENDIAN__) || \ + defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ + defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ + defined(__m68k__) + #define ENDIAN_BIG + #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN || \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ + defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \ + defined(__LITTLE_ENDIAN__) || \ + defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ + defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) + #define ENDIAN_LITTLE + #else + #error Cannot detect endianness + #endif +#endif + +/* ulong64: 64-bit data type */ +#ifdef _MSC_VER + #define CONST64(n) n ## ui64 + typedef unsigned __int64 ulong64; + typedef __int64 long64; +#else + #define CONST64(n) n ## ULL + typedef unsigned long long ulong64; + typedef long long long64; +#endif + +/* ulong32: "32-bit at least" data type */ +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ + defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ + defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ + defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ + defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ + defined(__LP64__) || defined(_LP64) || defined(__64BIT__) + typedef unsigned ulong32; + #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) + #define ENDIAN_64BITWORD + #endif +#else + typedef unsigned long ulong32; + #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) + #define ENDIAN_32BITWORD + #endif +#endif + +#if defined(ENDIAN_64BITWORD) && !defined(_MSC_VER) +typedef unsigned long long ltc_mp_digit; +#else +typedef unsigned long ltc_mp_digit; +#endif + +/* No asm is a quick way to disable anything "not portable" */ +#ifdef LTC_NO_ASM + #define ENDIAN_NEUTRAL + #undef ENDIAN_32BITWORD + #undef ENDIAN_64BITWORD + #undef LTC_FAST + #define LTC_NO_BSWAP + #define LTC_NO_ROLC + #define LTC_NO_ROTATE +#endif + +/* No LTC_FAST if: explicitly disabled OR non-gcc/non-clang compiler OR old gcc OR using -ansi -std=c99 */ +#if defined(LTC_NO_FAST) || (__GNUC__ < 4) || defined(__STRICT_ANSI__) + #undef LTC_FAST +#endif + +#ifdef LTC_FAST + #define LTC_FAST_TYPE_PTR_CAST(x) ((LTC_FAST_TYPE*)(void*)(x)) + #ifdef ENDIAN_64BITWORD + typedef ulong64 __attribute__((__may_alias__)) LTC_FAST_TYPE; + #else + typedef ulong32 __attribute__((__may_alias__)) LTC_FAST_TYPE; + #endif +#endif + +#if !defined(ENDIAN_NEUTRAL) && (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 + +#if (defined(ENDIAN_32BITWORD) && defined(ENDIAN_64BITWORD)) + #error Cannot be 32 and 64 bit words... +#endif + +/* gcc 4.3 and up has a bswap builtin; detect it by gcc version. + * clang also supports the bswap builtin, and although clang pretends + * to be gcc (macro-wise, anyway), clang pretends to be a version + * prior to gcc 4.3, so we can't detect bswap that way. Instead, + * clang has a __has_builtin mechanism that can be used to check + * for builtins: + * http://clang.llvm.org/docs/LanguageExtensions.html#feature_check */ +#ifndef __has_builtin + #define __has_builtin(x) 0 +#endif +#if !defined(LTC_NO_BSWAP) && defined(__GNUC__) && \ + ((__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \ + (__has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64))) + #define LTC_HAVE_BSWAP_BUILTIN +#endif + +#if !defined(LTC_NO_ROTATE) && (__has_builtin(__builtin_rotateleft32) && __has_builtin(__builtin_rotateright32)) + #define LTC_HAVE_ROTATE_BUILTIN +#endif + +#if defined(__GNUC__) + #define LTC_ALIGN(n) __attribute__((aligned(n))) +#else + #define LTC_ALIGN(n) +#endif + +/* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code + * before including `tomcrypt.h` to disable this functionality. + */ +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(LTC_NO_NULL_TERMINATION_CHECK) +# define LTC_NULL_TERMINATED __attribute__((sentinel)) +#else +# define LTC_NULL_TERMINATED +#endif + +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) +# define LTC_DEPRECATED(s) __attribute__((deprecated("replaced by " #s))) +# define PRIVATE_LTC_DEPRECATED_PRAGMA(s) _Pragma(#s) +# define LTC_DEPRECATED_PRAGMA(s) PRIVATE_LTC_DEPRECATED_PRAGMA(GCC warning s) +#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301) +# define LTC_DEPRECATED(s) __attribute__((deprecated)) +# define LTC_DEPRECATED_PRAGMA(s) +#elif defined(_MSC_VER) && _MSC_VER >= 1500 + /* supported since Visual Studio 2008 */ +# define LTC_DEPRECATED(s) __declspec(deprecated("replaced by " #s)) +# define LTC_DEPRECATED_PRAGMA(s) __pragma(message(s)) +#else +# define LTC_DEPRECATED(s) +# define LTC_DEPRECATED_PRAGMA(s) +#endif + +#endif /* TOMCRYPT_CFG_H */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h new file mode 100644 index 0000000..17a0994 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h @@ -0,0 +1,1160 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- 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_BLOWFISH +struct blowfish_key { + ulong32 S[4][256]; + ulong32 K[18]; +}; +#endif + +#ifdef LTC_RC5 +struct rc5_key { + int rounds; + ulong32 K[50]; +}; +#endif + +#ifdef LTC_RC6 +struct rc6_key { + ulong32 K[44]; +}; +#endif + +#ifdef LTC_SAFERP +struct saferp_key { + unsigned char K[33][16]; + long rounds; +}; +#endif + +#ifdef LTC_RIJNDAEL +struct rijndael_key { + ulong32 eK[60], dK[60]; + int Nr; +}; +#endif + +#ifdef LTC_KSEED +struct kseed_key { + ulong32 K[32], dK[32]; +}; +#endif + +#ifdef LTC_KASUMI +struct kasumi_key { + ulong32 KLi1[8], KLi2[8], + KOi1[8], KOi2[8], KOi3[8], + KIi1[8], KIi2[8], KIi3[8]; +}; +#endif + +#ifdef LTC_XTEA +struct xtea_key { + unsigned long A[32], B[32]; +}; +#endif + +#ifdef LTC_TWOFISH +#ifndef LTC_TWOFISH_SMALL + struct twofish_key { + ulong32 S[4][256], K[40]; + }; +#else + struct twofish_key { + ulong32 K[40]; + unsigned char S[32], start; + }; +#endif +#endif + +#ifdef LTC_SAFER +#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6 +#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10 +#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8 +#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10 +#define LTC_SAFER_MAX_NOF_ROUNDS 13 +#define LTC_SAFER_BLOCK_LEN 8 +#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS)) +typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN]; +typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN]; +struct safer_key { safer_key_t key; }; +#endif + +#ifdef LTC_RC2 +struct rc2_key { unsigned xkey[64]; }; +#endif + +#ifdef LTC_DES +struct des_key { + ulong32 ek[32], dk[32]; +}; + +struct des3_key { + ulong32 ek[3][32], dk[3][32]; +}; +#endif + +#ifdef LTC_CAST5 +struct cast5_key { + ulong32 K[32], keylen; +}; +#endif + +#ifdef LTC_NOEKEON +struct noekeon_key { + ulong32 K[4], dK[4]; +}; +#endif + +#ifdef LTC_SKIPJACK +struct skipjack_key { + unsigned char key[10]; +}; +#endif + +#ifdef LTC_KHAZAD +struct khazad_key { + ulong64 roundKeyEnc[8 + 1]; + ulong64 roundKeyDec[8 + 1]; +}; +#endif + +#ifdef LTC_ANUBIS +struct anubis_key { + int keyBits; + int R; + ulong32 roundKeyEnc[18 + 1][4]; + ulong32 roundKeyDec[18 + 1][4]; +}; +#endif + +#ifdef LTC_MULTI2 +struct multi2_key { + int N; + ulong32 uk[8]; +}; +#endif + +#ifdef LTC_CAMELLIA +struct camellia_key { + int R; + ulong64 kw[4], k[24], kl[6]; +}; +#endif + +#ifdef LTC_IDEA +/* rounds */ +#define LTC_IDEA_ROUNDS 8 +/* key schedule length in # of unsigned shorts */ +#define LTC_IDEA_KEYLEN 6*LTC_IDEA_ROUNDS+4 +struct idea_key { + unsigned short int ek[LTC_IDEA_KEYLEN]; /* enc key */ + unsigned short int dk[LTC_IDEA_KEYLEN]; /* dec key */ +}; +#endif + +#ifdef LTC_SERPENT +struct serpent_key { + ulong32 k[33*4]; +}; +#endif + +#ifdef LTC_TEA +struct tea_key { + ulong32 k[4]; +}; +#endif + +typedef union Symmetric_key { +#ifdef LTC_DES + struct des_key des; + struct des3_key des3; +#endif +#ifdef LTC_RC2 + struct rc2_key rc2; +#endif +#ifdef LTC_SAFER + struct safer_key safer; +#endif +#ifdef LTC_TWOFISH + struct twofish_key twofish; +#endif +#ifdef LTC_BLOWFISH + struct blowfish_key blowfish; +#endif +#ifdef LTC_RC5 + struct rc5_key rc5; +#endif +#ifdef LTC_RC6 + struct rc6_key rc6; +#endif +#ifdef LTC_SAFERP + struct saferp_key saferp; +#endif +#ifdef LTC_RIJNDAEL + struct rijndael_key rijndael; +#endif +#ifdef LTC_XTEA + struct xtea_key xtea; +#endif +#ifdef LTC_CAST5 + struct cast5_key cast5; +#endif +#ifdef LTC_NOEKEON + struct noekeon_key noekeon; +#endif +#ifdef LTC_SKIPJACK + struct skipjack_key skipjack; +#endif +#ifdef LTC_KHAZAD + struct khazad_key khazad; +#endif +#ifdef LTC_ANUBIS + struct anubis_key anubis; +#endif +#ifdef LTC_KSEED + struct kseed_key kseed; +#endif +#ifdef LTC_KASUMI + struct kasumi_key kasumi; +#endif +#ifdef LTC_MULTI2 + struct multi2_key multi2; +#endif +#ifdef LTC_CAMELLIA + struct camellia_key camellia; +#endif +#ifdef LTC_IDEA + struct idea_key idea; +#endif +#ifdef LTC_SERPENT + struct serpent_key serpent; +#endif +#ifdef LTC_TEA + struct tea_key tea; +#endif + 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 */ + unsigned char pad[MAXBLOCKSIZE] LTC_ALIGN(16); + /** 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 LTC_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 const 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, const 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, const 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, const 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, const 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 initialization vector + @param IVlen The length of the initialization 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); + + /** Accelerated XTS encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param tweak The 128-bit encryption tweak (input/output). + The tweak should not be encrypted on input, but + next tweak will be copied encrypted on output. + @param skey1 The first scheduled key context + @param skey2 The second scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_xts_encrypt)(const unsigned char *pt, unsigned char *ct, + unsigned long blocks, unsigned char *tweak, + const symmetric_key *skey1, const symmetric_key *skey2); + + /** Accelerated XTS decryption + @param ct Ciphertext + @param pt Plaintext + @param blocks The number of complete blocks to process + @param tweak The 128-bit encryption tweak (input/output). + The tweak should not be encrypted on input, but + next tweak will be copied encrypted on output. + @param skey1 The first scheduled key context + @param skey2 The second scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_xts_decrypt)(const unsigned char *ct, unsigned char *pt, + unsigned long blocks, unsigned char *tweak, + const symmetric_key *skey1, const symmetric_key *skey2); +} *cipher_descriptor[]; + +#ifdef LTC_BLOWFISH +int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int blowfish_test(void); +void blowfish_done(symmetric_key *skey); +int blowfish_keysize(int *keysize); +extern const struct ltc_cipher_descriptor blowfish_desc; +#endif + +#ifdef LTC_RC5 +int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int rc5_test(void); +void rc5_done(symmetric_key *skey); +int rc5_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc5_desc; +#endif + +#ifdef LTC_RC6 +int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int rc6_test(void); +void rc6_done(symmetric_key *skey); +int rc6_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc6_desc; +#endif + +#ifdef LTC_RC2 +int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey); +int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int rc2_test(void); +void rc2_done(symmetric_key *skey); +int rc2_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc2_desc; +#endif + +#ifdef LTC_SAFERP +int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int saferp_test(void); +void saferp_done(symmetric_key *skey); +int saferp_keysize(int *keysize); +extern const struct ltc_cipher_descriptor saferp_desc; +#endif + +#ifdef LTC_SAFER +int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int safer_k64_test(void); +int safer_sk64_test(void); +int safer_sk128_test(void); +void safer_done(symmetric_key *skey); +int safer_64_keysize(int *keysize); +int safer_128_keysize(int *keysize); +extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc; +#endif + +#ifdef LTC_RIJNDAEL + +/* 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, const symmetric_key *skey); +int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const 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, const 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; +#endif + +#ifdef LTC_XTEA +int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int xtea_test(void); +void xtea_done(symmetric_key *skey); +int xtea_keysize(int *keysize); +extern const struct ltc_cipher_descriptor xtea_desc; +#endif + +#ifdef LTC_TWOFISH +int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int twofish_test(void); +void twofish_done(symmetric_key *skey); +int twofish_keysize(int *keysize); +extern const struct ltc_cipher_descriptor twofish_desc; +#endif + +#ifdef LTC_DES +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, const symmetric_key *skey); +int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const 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, const symmetric_key *skey); +int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const 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; +#endif + +#ifdef LTC_CAST5 +int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int cast5_test(void); +void cast5_done(symmetric_key *skey); +int cast5_keysize(int *keysize); +extern const struct ltc_cipher_descriptor cast5_desc; +#endif + +#ifdef LTC_NOEKEON +int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int noekeon_test(void); +void noekeon_done(symmetric_key *skey); +int noekeon_keysize(int *keysize); +extern const struct ltc_cipher_descriptor noekeon_desc; +#endif + +#ifdef LTC_SKIPJACK +int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int skipjack_test(void); +void skipjack_done(symmetric_key *skey); +int skipjack_keysize(int *keysize); +extern const struct ltc_cipher_descriptor skipjack_desc; +#endif + +#ifdef LTC_KHAZAD +int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int khazad_test(void); +void khazad_done(symmetric_key *skey); +int khazad_keysize(int *keysize); +extern const struct ltc_cipher_descriptor khazad_desc; +#endif + +#ifdef LTC_ANUBIS +int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int anubis_test(void); +void anubis_done(symmetric_key *skey); +int anubis_keysize(int *keysize); +extern const struct ltc_cipher_descriptor anubis_desc; +#endif + +#ifdef LTC_KSEED +int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int kseed_test(void); +void kseed_done(symmetric_key *skey); +int kseed_keysize(int *keysize); +extern const struct ltc_cipher_descriptor kseed_desc; +#endif + +#ifdef LTC_KASUMI +int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int kasumi_test(void); +void kasumi_done(symmetric_key *skey); +int kasumi_keysize(int *keysize); +extern const struct ltc_cipher_descriptor kasumi_desc; +#endif + + +#ifdef LTC_MULTI2 +int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int multi2_test(void); +void multi2_done(symmetric_key *skey); +int multi2_keysize(int *keysize); +extern const struct ltc_cipher_descriptor multi2_desc; +#endif + +#ifdef LTC_CAMELLIA +int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int camellia_test(void); +void camellia_done(symmetric_key *skey); +int camellia_keysize(int *keysize); +extern const struct ltc_cipher_descriptor camellia_desc; +#endif + +#ifdef LTC_IDEA +int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int idea_test(void); +void idea_done(symmetric_key *skey); +int idea_keysize(int *keysize); +extern const struct ltc_cipher_descriptor idea_desc; +#endif + +#ifdef LTC_SERPENT +int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int serpent_test(void); +void serpent_done(symmetric_key *skey); +int serpent_keysize(int *keysize); +extern const struct ltc_cipher_descriptor serpent_desc; +#endif + +#ifdef LTC_TEA +int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int tea_test(void); +void tea_done(symmetric_key *skey); +int tea_keysize(int *keysize); +extern const struct ltc_cipher_descriptor tea_desc; +#endif + +#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, const 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, const 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, const 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, const 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 LTC_ENCRYPT +#define LRW_DECRYPT LTC_DECRYPT + +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, const 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, const 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, + unsigned char *tweak, + const symmetric_xts *xts); +int xts_decrypt( + const unsigned char *ct, unsigned long ptlen, + unsigned char *pt, + unsigned char *tweak, + const 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 register_all_ciphers(void); +int cipher_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_cipher_mutex) + +/* ---- stream ciphers ---- */ + +#ifdef LTC_CHACHA + +typedef struct { + ulong32 input[16]; + unsigned char kstream[64]; + unsigned long ksleft; + unsigned long ivlen; + int rounds; +} chacha_state; + +int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds); +int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter); +int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter); +int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen); +int chacha_done(chacha_state *st); +int chacha_test(void); +int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *iv, unsigned long ivlen, ulong64 counter, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout); + +#endif /* LTC_CHACHA */ + +#ifdef LTC_SALSA20 + +typedef struct { + ulong32 input[16]; + unsigned char kstream[64]; + unsigned long ksleft; + unsigned long ivlen; + int rounds; +} salsa20_state; + +int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds); +int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter); +int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen); +int salsa20_done(salsa20_state *st); +int salsa20_test(void); +int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *iv, unsigned long ivlen, ulong64 counter, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout); + +#endif /* LTC_SALSA20 */ + +#ifdef LTC_XSALSA20 + +int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + int rounds); +int xsalsa20_test(void); +int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout); + +#endif /* LTC_XSALSA20 */ + +#ifdef LTC_SOSEMANUK + +typedef struct { + ulong32 kc[100]; /* key_context */ + ulong32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09; + ulong32 r1, r2; + /* + * Buffering: the stream cipher produces output data by + * blocks of 640 bits. buf[] contains such a block, and + * "ptr" is the index of the next output byte. + */ + unsigned char buf[80]; + unsigned ptr; +} sosemanuk_state; + +int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen); +int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen); +int sosemanuk_crypt(sosemanuk_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen); +int sosemanuk_done(sosemanuk_state *st); +int sosemanuk_test(void); +int sosemanuk_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout); + +#endif /* LTC_SOSEMANUK */ + +#ifdef LTC_RABBIT + +typedef struct { + ulong32 x[8]; + ulong32 c[8]; + ulong32 carry; +} rabbit_ctx; + +typedef struct { + rabbit_ctx master_ctx; + rabbit_ctx work_ctx; + unsigned char block[16]; /* last keystream block containing unused bytes */ + ulong32 unused; /* count fm right */ +} rabbit_state; + +int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen); +int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen); +int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int rabbit_keystream(rabbit_state* st, unsigned char *out, unsigned long outlen); +int rabbit_done(rabbit_state *st); +int rabbit_test(void); +int rabbit_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout); + +#endif /* LTC_RABBIT */ + +#ifdef LTC_RC4_STREAM + +typedef struct { + unsigned int x, y; + unsigned char buf[256]; +} rc4_state; + +int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen); +int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen); +int rc4_stream_done(rc4_state *st); +int rc4_stream_test(void); +int rc4_stream_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout); + +#endif /* LTC_RC4_STREAM */ + +#ifdef LTC_SOBER128_STREAM + +typedef struct { + 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 */ +} sober128_state; + +int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen); +int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen); +int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen); +int sober128_stream_done(sober128_state *st); +int sober128_stream_test(void); +int sober128_stream_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout); + +#endif /* LTC_SOBER128_STREAM */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h new file mode 100644 index 0000000..62eab00 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h @@ -0,0 +1,751 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMCRYPT_CUSTOM_H_ +#define TOMCRYPT_CUSTOM_H_ + +/* macros for various libc functions you can change for embedded targets */ +#ifndef XMALLOC +#define XMALLOC malloc +#endif +#ifndef XREALLOC +#define XREALLOC realloc +#endif +#ifndef XCALLOC +#define XCALLOC calloc +#endif +#ifndef XFREE +#define XFREE free +#endif + +#ifndef XMEMSET +#define XMEMSET memset +#endif +#ifndef XMEMCPY +#define XMEMCPY memcpy +#endif +#ifndef XMEMMOVE +#define XMEMMOVE memmove +#endif +#ifndef XMEMCMP +#define XMEMCMP memcmp +#endif +/* A memory compare function that has to run in constant time, + * c.f. mem_neq() API summary. + */ +#ifndef XMEM_NEQ +#define XMEM_NEQ mem_neq +#endif +#ifndef XSTRCMP +#define XSTRCMP strcmp +#endif +#ifndef XSTRLEN +#define XSTRLEN strlen +#endif +#ifndef XSTRNCPY +#define XSTRNCPY strncpy +#endif + +#ifndef XCLOCK +#define XCLOCK clock +#endif + +#ifndef XQSORT +#define XQSORT qsort +#endif + +#if ( defined(malloc) || defined(realloc) || defined(calloc) || defined(free) || \ + defined(memset) || defined(memcpy) || defined(memcmp) || defined(strcmp) || \ + defined(strlen) || defined(strncpy) || defined(clock) || defined(qsort) ) \ + && !defined(LTC_NO_PROTOTYPES) +#define LTC_NO_PROTOTYPES +#endif + +/* shortcut to disable automatic inclusion */ +#if defined LTC_NOTHING && !defined LTC_EASY + #define LTC_NO_CIPHERS + #define LTC_NO_MODES + #define LTC_NO_HASHES + #define LTC_NO_MACS + #define LTC_NO_PRNGS + #define LTC_NO_PK + #define LTC_NO_PKCS + #define LTC_NO_MISC +#endif /* LTC_NOTHING */ + +/* 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_SHA3 + #define LTC_SHA512 + #define LTC_SHA384 + #define LTC_SHA256 + #define LTC_SHA224 + #define LTC_HASH_HELPERS + + #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 LTC_TRY_URANDOM_FIRST + #define LTC_RNG_GET_BYTES + #define LTC_RNG_MAKE_PRNG + + #define LTC_NO_PK + #define LTC_MRSA + #define LTC_MECC + + #define LTC_NO_MISC + #define LTC_BASE64 +#endif /* LTC_EASY */ + +/* The minimal set of functionality to run the tests */ +#ifdef LTC_MINIMAL + #define LTC_RIJNDAEL + #define LTC_SHA256 + #define LTC_YARROW + #define LTC_CTR_MODE + + #define LTC_RNG_MAKE_PRNG + #define LTC_RNG_GET_BYTES + #define LTC_DEVRANDOM + #define LTC_TRY_URANDOM_FIRST + + #undef LTC_NO_FILE +#endif /* LTC_MINIMAL */ + +/* Enable self-test test vector checking */ +#ifndef LTC_NO_TEST + #define LTC_TEST +#endif +/* Enable extended self-tests */ +/* #define LTC_TEST_EXT */ + +/* Use small code where possible */ +/* #define LTC_SMALL_CODE */ + +/* 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 */ + +/* ---> math provider? <--- */ +#ifndef LTC_NO_MATH + +/* LibTomMath */ +/* #define LTM_DESC */ + +/* TomsFastMath */ +/* #define TFM_DESC */ + +/* GNU Multiple Precision Arithmetic Library */ +/* #define GMP_DESC */ + +#endif /* LTC_NO_MATH */ + +/* ---> Symmetric Block Ciphers <--- */ +#ifndef LTC_NO_CIPHERS + +#define LTC_BLOWFISH +#define LTC_RC2 +#define LTC_RC5 +#define LTC_RC6 +#define LTC_SAFERP +#define LTC_RIJNDAEL +#define LTC_XTEA +/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format + * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ +#define LTC_TWOFISH +#ifndef LTC_NO_TABLES + #define LTC_TWOFISH_TABLES + /* #define LTC_TWOFISH_ALL_TABLES */ +#else + #define LTC_TWOFISH_SMALL +#endif +/* #define LTC_TWOFISH_SMALL */ +/* LTC_DES includes EDE triple-DES */ +#define LTC_DES +#define LTC_CAST5 +#define LTC_NOEKEON +#define LTC_SKIPJACK +#define LTC_SAFER +#define LTC_KHAZAD +#define LTC_ANUBIS +#define LTC_ANUBIS_TWEAK +#define LTC_KSEED +#define LTC_KASUMI +#define LTC_MULTI2 +#define LTC_CAMELLIA +#define LTC_IDEA +#define LTC_SERPENT +#define LTC_TEA + +/* stream ciphers */ +#define LTC_CHACHA +#define LTC_SALSA20 +#define LTC_XSALSA20 +#define LTC_SOSEMANUK +#define LTC_RABBIT +#define LTC_RC4_STREAM +#define LTC_SOBER128_STREAM + +#endif /* LTC_NO_CIPHERS */ + + +/* ---> 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 LTC_LRW_TABLES +#endif + +/* XTS mode */ +#define LTC_XTS_MODE + +#endif /* LTC_NO_MODES */ + +/* ---> One-Way Hash Functions <--- */ +#ifndef LTC_NO_HASHES + +#define LTC_CHC_HASH +#define LTC_WHIRLPOOL +#define LTC_SHA3 +#define LTC_KECCAK +#define LTC_SHA512 +#define LTC_SHA512_256 +#define LTC_SHA512_224 +#define LTC_SHA384 +#define LTC_SHA256 +#define LTC_SHA224 +#define LTC_TIGER +#define LTC_SHA1 +#define LTC_MD5 +#define LTC_MD4 +#define LTC_MD2 +#define LTC_RIPEMD128 +#define LTC_RIPEMD160 +#define LTC_RIPEMD256 +#define LTC_RIPEMD320 +#define LTC_BLAKE2S +#define LTC_BLAKE2B + +#define LTC_HASH_HELPERS + +#endif /* LTC_NO_HASHES */ + + +/* ---> MAC functions <--- */ +#ifndef LTC_NO_MACS + +#define LTC_HMAC +#define LTC_OMAC +#define LTC_PMAC +#define LTC_XCBC +#define LTC_F9_MODE +#define LTC_PELICAN +#define LTC_POLY1305 +#define LTC_BLAKE2SMAC +#define LTC_BLAKE2BMAC + +/* ---> Encrypt + Authenticate Modes <--- */ + +#define LTC_EAX_MODE + +#define LTC_OCB_MODE +#define LTC_OCB3_MODE +#define LTC_CCM_MODE +#define LTC_GCM_MODE +#define LTC_CHACHA20POLY1305_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 */ + + +/* --> Pseudo Random Number Generators <--- */ +#ifndef LTC_NO_PRNGS + +/* Yarrow */ +#define LTC_YARROW + +/* a PRNG that simply reads from an available system source */ +#define LTC_SPRNG + +/* The RC4 stream cipher based PRNG */ +#define LTC_RC4 + +/* The ChaCha20 stream cipher based PRNG */ +#define LTC_CHACHA20_PRNG + +/* Fortuna PRNG */ +#define LTC_FORTUNA + +/* Greg's SOBER128 stream cipher based PRNG */ +#define LTC_SOBER128 + +/* the *nix style /dev/random device */ +#define LTC_DEVRANDOM +/* try /dev/urandom before trying /dev/random + * are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */ +#define LTC_TRY_URANDOM_FIRST +/* rng_get_bytes() */ +#define LTC_RNG_GET_BYTES +/* rng_make_prng() */ +#define LTC_RNG_MAKE_PRNG + +/* enable the ltc_rng hook to integrate e.g. embedded hardware RNG's easily */ +/* #define LTC_PRNG_ENABLE_LTC_RNG */ + +#endif /* LTC_NO_PRNGS */ + +#ifdef LTC_YARROW + +/* which descriptor of AES to use? */ +/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */ +#ifdef ENCRYPT_ONLY + #define LTC_YARROW_AES 0 +#else + #define LTC_YARROW_AES 2 +#endif + +#endif /* LTC_YARROW */ + +#ifdef LTC_FORTUNA + +#if !defined(LTC_FORTUNA_RESEED_RATELIMIT_STATIC) && \ + ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || defined(_WIN32)) + +/* time-based rate limit of the reseeding */ +#define LTC_FORTUNA_RESEED_RATELIMIT_TIMED + +/* with non-glibc or glibc 2.17+ prefer clock_gettime over gettimeofday */ +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 17) + #define LTC_CLOCK_GETTIME +#endif +#elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L + #define LTC_CLOCK_GETTIME +#endif + +#else + +#ifndef LTC_FORTUNA_WD +/* reseed every N calls to the read function */ +#define LTC_FORTUNA_WD 10 +#endif + +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED +/* make sure only one of + * LTC_FORTUNA_RESEED_RATELIMIT_STATIC + * and + * LTC_FORTUNA_RESEED_RATELIMIT_TIMED + * is defined. + */ +#undef LTC_FORTUNA_RESEED_RATELIMIT_TIMED +#warning "undef'ed LTC_FORTUNA_RESEED_RATELIMIT_TIMED, looks like your architecture doesn't support it" +#endif + +#endif + +#ifndef LTC_FORTUNA_POOLS +/* number of pools (4..32) can save a bit of ram by lowering the count */ +#define LTC_FORTUNA_POOLS 32 +#endif + +#endif /* LTC_FORTUNA */ + + +/* ---> Public Key Crypto <--- */ +#ifndef LTC_NO_PK + +/* Include RSA support */ +#define LTC_MRSA + +/* Include Diffie-Hellman support */ +/* is_prime fails for GMP */ +#define LTC_MDH +/* Supported Key Sizes */ +#define LTC_DH768 +#define LTC_DH1024 +#define LTC_DH1536 +#define LTC_DH2048 + +#if defined(LTM_DESC) || defined(GMP_DESC) +/* tfm has a problem in fp_isprime for larger key sizes */ +#define LTC_DH3072 +#define LTC_DH4096 +#define LTC_DH6144 +#define LTC_DH8192 +#endif + +/* Digital Signature Algorithm */ +#define LTC_MDSA + +/* Ed25519 & X25519 */ +#define LTC_CURVE25519 + +/* ECC */ +#define LTC_MECC + +/* use Shamir's trick for point mul (speeds up signature verification) */ +#define LTC_ECC_SHAMIR + +#if defined(TFM_DESC) && defined(LTC_MECC) + #define LTC_MECC_ACCEL +#endif + +/* do we want fixed point ECC */ +/* #define LTC_MECC_FP */ + +#endif /* LTC_NO_PK */ + +#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_BLINDING) +/* Enable RSA blinding when doing private key operations by default */ +#define LTC_RSA_BLINDING +#endif /* LTC_NO_RSA_BLINDING */ + +#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_CRT_HARDENING) +/* Enable RSA CRT hardening when doing private key operations by default */ +#define LTC_RSA_CRT_HARDENING +#endif /* LTC_NO_RSA_CRT_HARDENING */ + +#if defined(LTC_MECC) && !defined(LTC_NO_ECC_TIMING_RESISTANT) +/* Enable ECC timing resistant version by default */ +#define LTC_ECC_TIMING_RESISTANT +#endif + +/* PKCS #1 (RSA) and #5 (Password Handling) stuff */ +#ifndef LTC_NO_PKCS + +#define LTC_PKCS_1 +#define LTC_PKCS_5 +#define LTC_PKCS_8 +#define LTC_PKCS_12 + +/* Include ASN.1 DER (required by DSA/RSA) */ +#define LTC_DER + +#define LTC_MPI + +#endif /* LTC_NO_PKCS */ + +/* misc stuff */ +#ifndef LTC_NO_MISC + +/* Various tidbits of modern neatoness */ +#define LTC_BASE64 +/* ... and it's URL safe version */ +#define LTC_BASE64_URL +/* Base32 encoding/decoding */ +#define LTC_BASE32 +/* Base16/hex encoding/decoding */ +#define LTC_BASE16 + +#define LTC_BCRYPT + +#ifndef LTC_BCRYPT_DEFAULT_ROUNDS +#define LTC_BCRYPT_DEFAULT_ROUNDS 10 +#endif + +/* Keep LTC_NO_HKDF for compatibility reasons + * superseeded by LTC_NO_MISC*/ +#ifndef LTC_NO_HKDF +/* HKDF Key Derivation/Expansion stuff */ +#define LTC_HKDF +#endif /* LTC_NO_HKDF */ + +#define LTC_ADLER32 + +#define LTC_CRC32 + +#define LTC_SSH + +#define LTC_PADDING + +#define LTC_PBES + +#endif /* LTC_NO_MISC */ + +/* cleanup */ + +#ifdef LTC_MECC +/* Supported ECC Key Sizes */ +#ifndef LTC_NO_CURVES + #define LTC_ECC_BRAINPOOLP160R1 + #define LTC_ECC_BRAINPOOLP160T1 + #define LTC_ECC_BRAINPOOLP192R1 + #define LTC_ECC_BRAINPOOLP192T1 + #define LTC_ECC_BRAINPOOLP224R1 + #define LTC_ECC_BRAINPOOLP224T1 + #define LTC_ECC_BRAINPOOLP256R1 + #define LTC_ECC_BRAINPOOLP256T1 + #define LTC_ECC_BRAINPOOLP320R1 + #define LTC_ECC_BRAINPOOLP320T1 + #define LTC_ECC_BRAINPOOLP384R1 + #define LTC_ECC_BRAINPOOLP384T1 + #define LTC_ECC_BRAINPOOLP512R1 + #define LTC_ECC_BRAINPOOLP512T1 + #define LTC_ECC_PRIME192V2 + #define LTC_ECC_PRIME192V3 + #define LTC_ECC_PRIME239V1 + #define LTC_ECC_PRIME239V2 + #define LTC_ECC_PRIME239V3 + #define LTC_ECC_SECP112R1 + #define LTC_ECC_SECP112R2 + #define LTC_ECC_SECP128R1 + #define LTC_ECC_SECP128R2 + #define LTC_ECC_SECP160K1 + #define LTC_ECC_SECP160R1 + #define LTC_ECC_SECP160R2 + #define LTC_ECC_SECP192K1 + #define LTC_ECC_SECP192R1 + #define LTC_ECC_SECP224K1 + #define LTC_ECC_SECP224R1 + #define LTC_ECC_SECP256K1 + #define LTC_ECC_SECP256R1 + #define LTC_ECC_SECP384R1 + #define LTC_ECC_SECP521R1 +#endif +#endif /* LTC_MECC */ + +#if defined(LTC_DER) + #ifndef LTC_DER_MAX_RECURSION + /* Maximum recursion limit when processing nested ASN.1 types. */ + #define LTC_DER_MAX_RECURSION 30 + #endif +#endif + +#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH) + #ifndef LTC_PK_MAX_RETRIES + /* iterations limit for retry-loops */ + #define LTC_PK_MAX_RETRIES 20 + #endif +#endif + +#ifdef LTC_MRSA + #define LTC_PKCS_1 +#endif + +#if defined(LTC_MRSA) || defined(LTC_MECC) + #define LTC_PKCS_8 +#endif + +#ifdef LTC_PKCS_8 + #define LTC_PADDING + #define LTC_PBES +#endif + +#if defined(LTC_CLEAN_STACK) +/* if you're sure that you want to use it, remove the line below */ + #error LTC_CLEAN_STACK is considered as broken +#endif + +#if defined(LTC_PBES) && !defined(LTC_PKCS_5) + #error LTC_PBES requires LTC_PKCS_5 +#endif + +#if defined(LTC_PBES) && !defined(LTC_PKCS_12) + #error LTC_PBES requires LTC_PKCS_12 +#endif + +#if defined(LTC_PKCS_5) && !defined(LTC_HMAC) + #error LTC_PKCS_5 requires LTC_HMAC +#endif + +#if defined(LTC_PKCS_5) && !defined(LTC_HASH_HELPERS) + #error LTC_PKCS_5 requires LTC_HASH_HELPERS +#endif + +#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL) + #error Pelican-MAC requires LTC_RIJNDAEL +#endif + +#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC)) + #error LTC_EAX_MODE requires CTR and LTC_OMAC mode +#endif + +#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE) + #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined! +#endif + +#if defined(LTC_DER) && !defined(LTC_MPI) + #error ASN.1 DER requires MPI functionality +#endif + +#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC)) && !defined(LTC_DER) + #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled +#endif + +#if defined(LTC_BCRYPT) && !defined(LTC_BLOWFISH) + #error LTC_BCRYPT requires LTC_BLOWFISH +#endif + +#if defined(LTC_CHACHA20POLY1305_MODE) && (!defined(LTC_CHACHA) || !defined(LTC_POLY1305)) + #error LTC_CHACHA20POLY1305_MODE requires LTC_CHACHA + LTC_POLY1305 +#endif + +#if defined(LTC_CHACHA20_PRNG) && !defined(LTC_CHACHA) + #error LTC_CHACHA20_PRNG requires LTC_CHACHA +#endif + +#if defined(LTC_XSALSA20) && !defined(LTC_SALSA20) + #error LTC_XSALSA20 requires LTC_SALSA20 +#endif + +#if defined(LTC_RC4) && !defined(LTC_RC4_STREAM) + #error LTC_RC4 requires LTC_RC4_STREAM +#endif + +#if defined(LTC_SOBER128) && !defined(LTC_SOBER128_STREAM) + #error LTC_SOBER128 requires LTC_SOBER128_STREAM +#endif + +#if defined(LTC_BLAKE2SMAC) && !defined(LTC_BLAKE2S) + #error LTC_BLAKE2SMAC requires LTC_BLAKE2S +#endif + +#if defined(LTC_BLAKE2BMAC) && !defined(LTC_BLAKE2B) + #error LTC_BLAKE2BMAC requires LTC_BLAKE2B +#endif + +#if defined(LTC_SPRNG) && !defined(LTC_RNG_GET_BYTES) + #error LTC_SPRNG requires LTC_RNG_GET_BYTES +#endif + +#if defined(LTC_NO_MATH) && (defined(LTM_DESC) || defined(TFM_DESC) || defined(GMP_DESC)) + #error LTC_NO_MATH defined, but also a math descriptor +#endif + +/* THREAD management */ +#if defined(_CFG_CORE_LTC_OPTEE_THREAD) + +#include + +#define LTC_MUTEX_GLOBAL(x) struct mutex x = MUTEX_INITIALIZER; +#define LTC_MUTEX_PROTO(x) extern struct mutex x; +#define LTC_MUTEX_TYPE(x) struct mutex x; +#define LTC_MUTEX_INIT(x) mutex_init(x); +#define LTC_MUTEX_LOCK(x) mutex_lock(x); +#define LTC_MUTEX_UNLOCK(x) mutex_unlock(x); + +#elif defined(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) LTC_ARGCHK(pthread_mutex_init(x, NULL) == 0); +#define LTC_MUTEX_LOCK(x) LTC_ARGCHK(pthread_mutex_lock(x) == 0); +#define LTC_MUTEX_UNLOCK(x) LTC_ARGCHK(pthread_mutex_unlock(x) == 0); +#define LTC_MUTEX_DESTROY(x) LTC_ARGCHK(pthread_mutex_destroy(x) == 0); + +#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) +#define LTC_MUTEX_DESTROY(x) + +#endif /* LTC_PTHREAD */ + +/* Debuggers */ + +/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */ +/* #define LTC_VALGRIND */ + +#ifndef LTC_NO_FILE + /* buffer size for reading from a file via fread(..) */ + #ifndef LTC_FILE_READ_BUFSIZE + #define LTC_FILE_READ_BUFSIZE 8192 + #endif +#endif + +/* ECC backwards compatibility */ +#if !defined(LTC_ECC_SECP112R1) && defined(LTC_ECC112) +#define LTC_ECC_SECP112R1 +#undef LTC_ECC112 +#endif +#if !defined(LTC_ECC_SECP128R1) && defined(LTC_ECC128) +#define LTC_ECC_SECP128R1 +#undef LTC_ECC128 +#endif +#if !defined(LTC_ECC_SECP160R1) && defined(LTC_ECC160) +#define LTC_ECC_SECP160R1 +#undef LTC_ECC160 +#endif +#if !defined(LTC_ECC_SECP192R1) && defined(LTC_ECC192) +#define LTC_ECC_SECP192R1 +#undef LTC_ECC192 +#endif +#if !defined(LTC_ECC_SECP224R1) && defined(LTC_ECC224) +#define LTC_ECC_SECP224R1 +#undef LTC_ECC224 +#endif +#if !defined(LTC_ECC_SECP256R1) && defined(LTC_ECC256) +#define LTC_ECC_SECP256R1 +#undef LTC_ECC256 +#endif +#if !defined(LTC_ECC_SECP384R1) && defined(LTC_ECC384) +#define LTC_ECC_SECP384R1 +#undef LTC_ECC384 +#endif +#if !defined(LTC_ECC_SECP512R1) && defined(LTC_ECC521) +#define LTC_ECC_SECP521R1 +#undef LTC_ECC521 +#endif + +#endif /* TOMCRYPT_CUSTOM_H_ */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h new file mode 100644 index 0000000..bc18b63 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h @@ -0,0 +1,503 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- HASH FUNCTIONS ---- */ +#if defined(LTC_SHA3) || defined(LTC_KECCAK) +struct sha3_state { + ulong64 saved; /* the portion of the input message that we didn't consume yet */ + ulong64 s[25]; + unsigned char sb[25 * 8]; /* used for storing `ulong64 s[25]` as little-endian bytes */ + unsigned short byte_index; /* 0..7--the next byte after the set one (starts from 0; 0--none are buffered) */ + unsigned short word_index; /* 0..24--the next word to integrate input (starts from 0) */ + unsigned short capacity_words; /* the double size of the hash output in words (e.g. 16 for Keccak 512) */ + unsigned short xof_flag; +}; +#endif + +#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 + +#ifdef LTC_BLAKE2S +struct blake2s_state { + ulong32 h[8]; + ulong32 t[2]; + ulong32 f[2]; + unsigned char buf[64]; + unsigned long curlen; + unsigned long outlen; + unsigned char last_node; +}; +#endif + +#ifdef LTC_BLAKE2B +struct blake2b_state { + ulong64 h[8]; + ulong64 t[2]; + ulong64 f[2]; + unsigned char buf[128]; + unsigned long curlen; + unsigned long outlen; + unsigned char last_node; +}; +#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 +#if defined(LTC_SHA3) || defined(LTC_KECCAK) + struct sha3_state sha3; +#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 +#ifdef LTC_BLAKE2S + struct blake2s_state blake2s; +#endif +#ifdef LTC_BLAKE2B + struct blake2b_state blake2b; +#endif + + void *data; +} hash_state; + +/** hash descriptor */ +extern const 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 *out); +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 *out); +int whirlpool_test(void); +extern const struct ltc_hash_descriptor whirlpool_desc; +#endif + +#if defined(LTC_SHA3) || defined(LTC_KECCAK) +/* sha3_NNN_init are shared by SHA3 and KECCAK */ +int sha3_512_init(hash_state * md); +int sha3_384_init(hash_state * md); +int sha3_256_init(hash_state * md); +int sha3_224_init(hash_state * md); +/* sha3_process is the same for all variants of SHA3 + KECCAK */ +int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen); +#endif + +#ifdef LTC_SHA3 +int sha3_512_test(void); +extern const struct ltc_hash_descriptor sha3_512_desc; +int sha3_384_test(void); +extern const struct ltc_hash_descriptor sha3_384_desc; +int sha3_256_test(void); +extern const struct ltc_hash_descriptor sha3_256_desc; +int sha3_224_test(void); +extern const struct ltc_hash_descriptor sha3_224_desc; +int sha3_done(hash_state *md, unsigned char *out); +/* SHAKE128 + SHAKE256 */ +int sha3_shake_init(hash_state *md, int num); +#define sha3_shake_process(a,b,c) sha3_process(a,b,c) +int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen); +int sha3_shake_test(void); +int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen); +#endif + +#ifdef LTC_KECCAK +#define keccak_512_init(a) sha3_512_init(a) +#define keccak_384_init(a) sha3_384_init(a) +#define keccak_256_init(a) sha3_256_init(a) +#define keccak_224_init(a) sha3_224_init(a) +#define keccak_process(a,b,c) sha3_process(a,b,c) +extern const struct ltc_hash_descriptor keccak_512_desc; +int keccak_512_test(void); +extern const struct ltc_hash_descriptor keccak_384_desc; +int keccak_384_test(void); +extern const struct ltc_hash_descriptor keccak_256_desc; +int keccak_256_test(void); +extern const struct ltc_hash_descriptor keccak_224_desc; +int keccak_224_test(void); +int keccak_done(hash_state *md, unsigned char *out); +#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 *out); +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 *out); +int sha384_test(void); +extern const struct ltc_hash_descriptor sha384_desc; +#endif + +#ifdef LTC_SHA512_256 +#ifndef LTC_SHA512 + #error LTC_SHA512 is required for LTC_SHA512_256 +#endif +int sha512_256_init(hash_state * md); +#define sha512_256_process sha512_process +int sha512_256_done(hash_state * md, unsigned char *out); +int sha512_256_test(void); +extern const struct ltc_hash_descriptor sha512_256_desc; +#endif + +#ifdef LTC_SHA512_224 +#ifndef LTC_SHA512 + #error LTC_SHA512 is required for LTC_SHA512_224 +#endif +int sha512_224_init(hash_state * md); +#define sha512_224_process sha512_process +int sha512_224_done(hash_state * md, unsigned char *out); +int sha512_224_test(void); +extern const struct ltc_hash_descriptor sha512_224_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 *out); +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 *out); +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 *out); +int sha1_test(void); +extern const struct ltc_hash_descriptor sha1_desc; +#endif + +#ifdef LTC_BLAKE2S +extern const struct ltc_hash_descriptor blake2s_256_desc; +int blake2s_256_init(hash_state * md); +int blake2s_256_test(void); + +extern const struct ltc_hash_descriptor blake2s_224_desc; +int blake2s_224_init(hash_state * md); +int blake2s_224_test(void); + +extern const struct ltc_hash_descriptor blake2s_160_desc; +int blake2s_160_init(hash_state * md); +int blake2s_160_test(void); + +extern const struct ltc_hash_descriptor blake2s_128_desc; +int blake2s_128_init(hash_state * md); +int blake2s_128_test(void); + +int blake2s_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen); +int blake2s_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int blake2s_done(hash_state * md, unsigned char *out); +#endif + +#ifdef LTC_BLAKE2B +extern const struct ltc_hash_descriptor blake2b_512_desc; +int blake2b_512_init(hash_state * md); +int blake2b_512_test(void); + +extern const struct ltc_hash_descriptor blake2b_384_desc; +int blake2b_384_init(hash_state * md); +int blake2b_384_test(void); + +extern const struct ltc_hash_descriptor blake2b_256_desc; +int blake2b_256_init(hash_state * md); +int blake2b_256_test(void); + +extern const struct ltc_hash_descriptor blake2b_160_desc; +int blake2b_160_init(hash_state * md); +int blake2b_160_test(void); + +int blake2b_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen); +int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int blake2b_done(hash_state * md, unsigned char *out); +#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 *out); +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 *out); +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 *out); +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 *out); +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 *out); +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 *out); +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 *out); +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 *out); +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 register_all_hashes(void); +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, ...) + LTC_NULL_TERMINATED; + +#ifndef LTC_NO_FILE +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); +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h new file mode 100644 index 0000000..c8f4a32 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h @@ -0,0 +1,567 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef LTC_HMAC +typedef struct Hmac_state { + hash_state md; + int hash; + unsigned char key[MAXBLOCKSIZE]; +} 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, ...) + LTC_NULL_TERMINATED; +int hmac_file(int hash, const char *fname, const unsigned char *key, + unsigned long keylen, + unsigned char *out, unsigned long *outlen); +#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, ...) + LTC_NULL_TERMINATED; +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 *in, unsigned long inlen, + 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, ...) + LTC_NULL_TERMINATED; + +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_POLY1305 +typedef struct { + ulong32 r[5]; + ulong32 h[5]; + ulong32 pad[4]; + unsigned long leftover; + unsigned char buffer[16]; + int final; +} poly1305_state; + +int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen); +int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen); +int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen); +int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); +int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); +int poly1305_test(void); +#endif /* LTC_POLY1305 */ + +#ifdef LTC_BLAKE2SMAC +typedef hash_state blake2smac_state; +int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen); +int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen); +int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen); +int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); +int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); +int blake2smac_test(void); +#endif /* LTC_BLAKE2SMAC */ + +#ifdef LTC_BLAKE2BMAC +typedef hash_state blake2bmac_state; +int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen); +int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen); +int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen); +int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); +int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); +int blake2bmac_test(void); +#endif /* LTC_BLAKE2BMAC */ + + +#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, ...) + LTC_NULL_TERMINATED; +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, ...) + LTC_NULL_TERMINATED; +int f9_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *fname, + unsigned char *out, unsigned long *outlen); +int f9_test(void); + +#endif + +/* + * ENC+AUTH modes + */ + +#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, + const 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_OCB3_MODE +typedef struct { + unsigned char Offset_0[MAXBLOCKSIZE], /* Offset_0 value */ + Offset_current[MAXBLOCKSIZE], /* Offset_{current_block_index} value */ + L_dollar[MAXBLOCKSIZE], /* L_$ value */ + L_star[MAXBLOCKSIZE], /* L_* value */ + L_[32][MAXBLOCKSIZE], /* L_{i} values */ + tag_part[MAXBLOCKSIZE], /* intermediate result of tag calculation */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + /* AAD related members */ + unsigned char aSum_current[MAXBLOCKSIZE], /* AAD related helper variable */ + aOffset_current[MAXBLOCKSIZE], /* AAD related helper variable */ + adata_buffer[MAXBLOCKSIZE]; /* AAD buffer */ + int adata_buffer_bytes; /* bytes in AAD buffer */ + unsigned long ablock_index; /* index # for current adata (AAD) block */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current data block */ + int cipher, /* cipher idx */ + tag_len, /* length of tag */ + block_len; /* length of block */ +} ocb3_state; + +int ocb3_init(ocb3_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + unsigned long taglen); + +int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct); +int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt); +int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct); +int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt); +int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen); +int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen); + +int ocb3_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *adata, unsigned long adatalen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb3_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *adata, unsigned long adatalen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat); + +int ocb3_test(void); + +#endif /* LTC_OCB3_MODE */ + +#ifdef LTC_CCM_MODE + +#define CCM_ENCRYPT LTC_ENCRYPT +#define CCM_DECRYPT LTC_DECRYPT + +typedef struct { + symmetric_key K; + int cipher, /* which cipher */ + taglen, /* length of the tag (encoded in M value) */ + x; /* index in PAD */ + + unsigned long L, /* L value */ + ptlen, /* length that will be enc / dec */ + current_ptlen, /* current processed length */ + aadlen, /* length of the aad */ + current_aadlen, /* length of the currently provided add */ + noncelen; /* length of the nonce */ + + unsigned char PAD[16], /* flags | Nonce N | l(m) */ + ctr[16], + CTRPAD[16], + CTRlen; +} ccm_state; + +int ccm_init(ccm_state *ccm, int cipher, + const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen); + +int ccm_reset(ccm_state *ccm); + +int ccm_add_nonce(ccm_state *ccm, + const unsigned char *nonce, unsigned long noncelen); + +int ccm_add_aad(ccm_state *ccm, + const unsigned char *adata, unsigned long adatalen); + +int ccm_process(ccm_state *ccm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction); + +int ccm_done(ccm_state *ccm, + unsigned char *tag, unsigned long *taglen); + +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(LTC_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 LTC_ENCRYPT +#define GCM_DECRYPT LTC_DECRYPT + +#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 +LTC_ALIGN(16) +#endif +; +#endif +} gcm_state; + +void gcm_mult_h(const 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_CHACHA20POLY1305_MODE + +typedef struct { + poly1305_state poly; + chacha_state chacha; + ulong64 aadlen; + ulong64 ctlen; + int aadflg; +} chacha20poly1305_state; + +#define CHACHA20POLY1305_ENCRYPT LTC_ENCRYPT +#define CHACHA20POLY1305_DECRYPT LTC_DECRYPT + +int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen); +int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen); +int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number); +int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen); +int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen); +int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *aad, unsigned long aadlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, + unsigned char *tag, unsigned long *taglen, + int direction); +int chacha20poly1305_test(void); + +#endif /* LTC_CHACHA20POLY1305_MODE */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h new file mode 100644 index 0000000..94aa7c3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h @@ -0,0 +1,454 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- HELPER MACROS ---- */ +#ifdef ENDIAN_NEUTRAL + +#define STORE32L(x, y) \ + do { (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); } while(0) + +#define LOAD32L(x, y) \ + do { x = ((ulong32)((y)[3] & 255)<<24) | \ + ((ulong32)((y)[2] & 255)<<16) | \ + ((ulong32)((y)[1] & 255)<<8) | \ + ((ulong32)((y)[0] & 255)); } while(0) + +#define STORE64L(x, y) \ + do { (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); } while(0) + +#define LOAD64L(x, y) \ + do { 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))); } while(0) + +#define STORE32H(x, y) \ + do { (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); } while(0) + +#define LOAD32H(x, y) \ + do { x = ((ulong32)((y)[0] & 255)<<24) | \ + ((ulong32)((y)[1] & 255)<<16) | \ + ((ulong32)((y)[2] & 255)<<8) | \ + ((ulong32)((y)[3] & 255)); } while(0) + +#define STORE64H(x, y) \ +do { (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); } while(0) + +#define LOAD64H(x, y) \ +do { 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))); } while(0) + + +#elif defined(ENDIAN_LITTLE) + +#ifdef LTC_HAVE_BSWAP_BUILTIN + +#define STORE32H(x, y) \ +do { ulong32 ttt = __builtin_bswap32 ((x)); \ + XMEMCPY ((y), &ttt, 4); } while(0) + +#define LOAD32H(x, y) \ +do { XMEMCPY (&(x), (y), 4); \ + (x) = __builtin_bswap32 ((x)); } while(0) + +#elif !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): "memory"); + +#define LOAD32H(x, y) \ +asm __volatile__ ( \ + "movl (%1),%0\n\t" \ + "bswapl %0\n\t" \ + :"=r"(x): "r"(y): "memory"); + +#else + +#define STORE32H(x, y) \ + do { (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); } while(0) + +#define LOAD32H(x, y) \ + do { x = ((ulong32)((y)[0] & 255)<<24) | \ + ((ulong32)((y)[1] & 255)<<16) | \ + ((ulong32)((y)[2] & 255)<<8) | \ + ((ulong32)((y)[3] & 255)); } while(0) + +#endif + +#ifdef LTC_HAVE_BSWAP_BUILTIN + +#define STORE64H(x, y) \ +do { ulong64 ttt = __builtin_bswap64 ((x)); \ + XMEMCPY ((y), &ttt, 8); } while(0) + +#define LOAD64H(x, y) \ +do { XMEMCPY (&(x), (y), 8); \ + (x) = __builtin_bswap64 ((x)); } while(0) + +/* x86_64 processor */ +#elif !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): "memory"); + +#define LOAD64H(x, y) \ +asm __volatile__ ( \ + "movq (%1),%0\n\t" \ + "bswapq %0\n\t" \ + :"=r"(x): "r"(y): "memory"); + +#else + +#define STORE64H(x, y) \ +do { (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); } while(0) + +#define LOAD64H(x, y) \ +do { 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))); } while(0) + +#endif + +#ifdef ENDIAN_32BITWORD + +#define STORE32L(x, y) \ + do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) + +#define LOAD32L(x, y) \ + do { XMEMCPY(&(x), y, 4); } while(0) + +#define STORE64L(x, y) \ + do { (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); } while(0) + +#define LOAD64L(x, y) \ + do { 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))); } while(0) + +#else /* 64-bit words then */ + +#define STORE32L(x, y) \ + do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) + +#define LOAD32L(x, y) \ + do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0) + +#define STORE64L(x, y) \ + do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0) + +#define LOAD64L(x, y) \ + do { XMEMCPY(&(x), y, 8); } while(0) + +#endif /* ENDIAN_64BITWORD */ + +#elif defined(ENDIAN_BIG) + +#define STORE32L(x, y) \ + do { (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); } while(0) + +#define LOAD32L(x, y) \ + do { x = ((ulong32)((y)[3] & 255)<<24) | \ + ((ulong32)((y)[2] & 255)<<16) | \ + ((ulong32)((y)[1] & 255)<<8) | \ + ((ulong32)((y)[0] & 255)); } while(0) + +#define STORE64L(x, y) \ +do { (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); } while(0) + +#define LOAD64L(x, y) \ +do { 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))); } while(0) + +#ifdef ENDIAN_32BITWORD + +#define STORE32H(x, y) \ + do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) + +#define LOAD32H(x, y) \ + do { XMEMCPY(&(x), y, 4); } while(0) + +#define STORE64H(x, y) \ + do { (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); } while(0) + +#define LOAD64H(x, y) \ + do { 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))); } while(0) + +#else /* 64-bit words then */ + +#define STORE32H(x, y) \ + do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) + +#define LOAD32H(x, y) \ + do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0) + +#define STORE64H(x, y) \ + do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0) + +#define LOAD64H(x, y) \ + do { XMEMCPY(&(x), y, 8); } while(0) + +#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) +#define LTC_ROx_BUILTIN + +/* instrinsic rotate */ +#include +#pragma intrinsic(_rotr,_rotl) +#define ROR(x,n) _rotr(x,n) +#define ROL(x,n) _rotl(x,n) +#define RORc(x,n) ROR(x,n) +#define ROLc(x,n) ROL(x,n) + +#elif defined(LTC_HAVE_ROTATE_BUILTIN) +#define LTC_ROx_BUILTIN + +#define ROR(x,n) __builtin_rotateright32(x,n) +#define ROL(x,n) __builtin_rotateleft32(x,n) +#define ROLc(x,n) ROL(x,n) +#define RORc(x,n) ROR(x,n) + +#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) +#define LTC_ROx_ASM + +static inline ulong32 ROL(ulong32 word, int i) +{ + asm ("roll %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline ulong32 ROR(ulong32 word, int i) +{ + asm ("rorl %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +#define ROLc(word,i) ({ \ + ulong32 ROLc_tmp = (word); \ + __asm__ ("roll %2, %0" : \ + "=r" (ROLc_tmp) : \ + "0" (ROLc_tmp), \ + "I" (i)); \ + ROLc_tmp; \ + }) +#define RORc(word,i) ({ \ + ulong32 RORc_tmp = (word); \ + __asm__ ("rorl %2, %0" : \ + "=r" (RORc_tmp) : \ + "0" (RORc_tmp), \ + "I" (i)); \ + RORc_tmp; \ + }) + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + +#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32) +#define LTC_ROx_ASM + +static inline ulong32 ROL(ulong32 word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (i)); + return word; +} + +static inline ulong32 ROR(ulong32 word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (32-i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline ulong32 ROLc(ulong32 word, const int i) +{ + asm ("rotlwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +static inline ulong32 RORc(ulong32 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) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define ROR(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define ROLc(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define RORc(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) + +#endif + + +/* 64-bit Rotates */ +#if defined(_MSC_VER) + +/* instrinsic rotate */ +#include +#pragma intrinsic(_rotr64,_rotr64) +#define ROR64(x,n) _rotr64(x,n) +#define ROL64(x,n) _rotl64(x,n) +#define ROR64c(x,n) ROR64(x,n) +#define ROL64c(x,n) ROL64(x,n) + +#elif defined(LTC_HAVE_ROTATE_BUILTIN) + +#define ROR64(x,n) __builtin_rotateright64(x,n) +#define ROL64(x,n) __builtin_rotateleft64(x,n) +#define ROR64c(x,n) ROR64(x,n) +#define ROL64c(x,n) ROL64(x,n) + +#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) + +static inline ulong64 ROL64(ulong64 word, int i) +{ + asm("rolq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline ulong64 ROR64(ulong64 word, int i) +{ + asm("rorq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +#define ROL64c(word,i) ({ \ + ulong64 ROL64c_tmp = word; \ + __asm__ ("rolq %2, %0" : \ + "=r" (ROL64c_tmp) : \ + "0" (ROL64c_tmp), \ + "J" (i)); \ + ROL64c_tmp; \ + }) +#define ROR64c(word,i) ({ \ + ulong64 ROR64c_tmp = word; \ + __asm__ ("rorq %2, %0" : \ + "=r" (ROR64c_tmp) : \ + "0" (ROR64c_tmp), \ + "J" (i)); \ + ROR64c_tmp; \ + }) + +#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))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROL64c(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64c(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<(((ulong64)64-((y)&63))&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 + +#ifndef LTC_UNUSED_PARAM + #define LTC_UNUSED_PARAM(x) (void)(x) +#endif + +/* there is no snprintf before Visual C++ 2015 */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_math.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_math.h new file mode 100644 index 0000000..49fa660 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_math.h @@ -0,0 +1,527 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** 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 + +#ifndef LTC_MILLER_RABIN_REPS + /* Number of rounds of the Miller-Rabin test + * "Reasonable values of reps are between 15 and 50." c.f. gmp doc of mpz_probab_prime_p() + * As of https://security.stackexchange.com/a/4546 we should use 40 rounds */ + #define LTC_MILLER_RABIN_REPS 40 +#endif + +int radix_to_bin(const void *in, int radix, void *out, unsigned long *len); + +/** 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); + + /** initialize a bignum + @param size_bits The size of the number we compute on + @param a The number to initialize + @return CRYPT_OK on success + */ + int (*init_size)(int size_bits, 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 success + */ + int (*set_int)(void *a, ltc_mp_digit n); + + /** get small constant + @param a Small number to read, + only fetches up to 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 + */ + ltc_mp_digit (*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, ltc_mp_digit 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 in octets + */ + 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, ltc_mp_digit 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, ltc_mp_digit 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, ltc_mp_digit 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); + + /** Square root (mod prime) + @param a The integer to compute square root mod prime from + @param b The prime + @param c The destination + @return CRYPT_OK on success + */ + int (*sqrtmod_prime)(void *a, void *b, void *c); + + /** 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, ltc_mp_digit b, ltc_mp_digit *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 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 number of Miller-Rabin tests that shall be executed + @param c The destination of the result (FP_YES if prime) + @return CRYPT_OK on success + */ + int (*isprime)(void *a, int b, int *c); + +/* ---- (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 a ECC curve parameter a + @param modulus The modulus for the field + @param map Boolean indicated whether to map back to affine or not + (can be ignored if you work in affine only) + @return CRYPT_OK on success + */ + int (*ecc_ptmul)( void *k, + const ecc_point *G, + ecc_point *R, + void *a, + void *modulus, + int map); + + /** ECC GF(p) point addition + @param P The first point + @param Q The second point + @param R The destination of P + Q + @param ma The curve parameter "a" in montgomery form + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + */ + int (*ecc_ptadd)(const ecc_point *P, + const ecc_point *Q, + ecc_point *R, + void *ma, + void *modulus, + void *mp); + + /** ECC GF(p) point double + @param P The first point + @param R The destination of 2P + @param ma The curve parameter "a" in montgomery form + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + */ + int (*ecc_ptdbl)(const ecc_point *P, + ecc_point *R, + void *ma, + void *modulus, + void *mp); + + /** ECC mapping from projective to affine, + currently uses (x,y,z) => (x/z^2, y/z^3, 1) + @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 ma The curve parameter "a" in montgomery form + @param modulus Modulus for curve + @return CRYPT_OK on success + */ + int (*ecc_mul2add)(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus); + +/* ---- (optional) rsa optimized math (for internal CRT) ---- */ + + /** RSA Key Generation + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the key in 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, + const rsa_key *key); + +/* ---- basic math continued ---- */ + + /** Modular addition + @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 (*addmod)(void *a, void *b, void *c, void *d); + + /** Modular substraction + @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 (*submod)(void *a, void *b, void *c, void *d); + +/* ---- misc stuff ---- */ + + /** Make a pseudo-random mpi + @param a The mpi to make random + @param size The desired length + @return CRYPT_OK on success + */ + int (*rand)(void *a, int size); +} ltc_math_descriptor; + +extern ltc_math_descriptor ltc_mp; + +int ltc_init_multi(void **a, ...) LTC_NULL_TERMINATED; +int ltc_init_multi_size(int size_bits, void **a, ...) LTC_NULL_TERMINATED; +void ltc_deinit_multi(void *a, ...) LTC_NULL_TERMINATED; +void ltc_cleanup_multi(void **a, ...) LTC_NULL_TERMINATED; + +#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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h new file mode 100644 index 0000000..3a2b7b1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h @@ -0,0 +1,179 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- LTC_BASE64 Routines ---- */ +#ifdef LTC_BASE64 +int base64_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen); + +int base64_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int base64_strict_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int base64_sane_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +#endif + +#ifdef LTC_BASE64_URL +int base64url_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen); +int base64url_strict_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen); + +int base64url_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int base64url_strict_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int base64url_sane_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +#endif + +/* ---- BASE32 Routines ---- */ +#ifdef LTC_BASE32 +typedef enum { + BASE32_RFC4648 = 0, + BASE32_BASE32HEX = 1, + BASE32_ZBASE32 = 2, + BASE32_CROCKFORD = 3 +} base32_alphabet; +int base32_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + base32_alphabet id); +int base32_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + base32_alphabet id); +#endif + +/* ---- BASE16 Routines ---- */ +#ifdef LTC_BASE16 +int base16_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int options); +int base16_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +#endif + +#ifdef LTC_BCRYPT +int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, + const unsigned char *salt, unsigned long salt_len, + unsigned int rounds, int hash_idx, + unsigned char *out, unsigned long *outlen); +#endif + +/* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ +#ifdef LTC_HKDF + +int hkdf_test(void); + +int hkdf_extract(int hash_idx, + const unsigned char *salt, unsigned long saltlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int hkdf_expand(int hash_idx, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen); + +int hkdf(int hash_idx, + const unsigned char *salt, unsigned long saltlen, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen); + +#endif /* LTC_HKDF */ + +/* ---- MEM routines ---- */ +int mem_neq(const void *a, const void *b, size_t len); +void zeromem(volatile void *out, size_t outlen); +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, ...) LTC_NULL_TERMINATED; + +/* ---- Dynamic language support ---- */ +int crypt_get_constant(const char* namein, int *valueout); +int crypt_list_all_constants(char *names_list, unsigned int *names_list_size); + +int crypt_get_size(const char* namein, unsigned int *sizeout); +int crypt_list_all_sizes(char *names_list, unsigned int *names_list_size); + +#ifdef LTM_DESC +LTC_DEPRECATED(crypt_mp_init) void init_LTM(void); +#endif +#ifdef TFM_DESC +LTC_DEPRECATED(crypt_mp_init) void init_TFM(void); +#endif +#ifdef GMP_DESC +LTC_DEPRECATED(crypt_mp_init) void init_GMP(void); +#endif +int crypt_mp_init(const char* mpi); + +#ifdef LTC_ADLER32 +typedef struct adler32_state_s +{ + unsigned short s[2]; +} adler32_state; + +void adler32_init(adler32_state *ctx); +void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length); +void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size); +int adler32_test(void); +#endif + +#ifdef LTC_CRC32 +typedef struct crc32_state_s +{ + ulong32 crc; +} crc32_state; + +void crc32_init(crc32_state *ctx); +void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length); +void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size); +int crc32_test(void); +#endif + + +#ifdef LTC_PADDING + +enum padding_type { + LTC_PAD_PKCS7 = 0x0000U, +#ifdef LTC_RNG_GET_BYTES + LTC_PAD_ISO_10126 = 0x1000U, +#endif + LTC_PAD_ANSI_X923 = 0x2000U, + LTC_PAD_SSH = 0x3000U, + /* The following padding modes don't contain the padding + * length as last byte of the padding. + */ + LTC_PAD_ONE_AND_ZERO = 0x8000U, + LTC_PAD_ZERO = 0x9000U, + LTC_PAD_ZERO_ALWAYS = 0xA000U, +}; + +int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode); +int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode); +#endif /* LTC_PADDING */ + +#ifdef LTC_SSH +typedef enum ssh_data_type_ { + LTC_SSHDATA_EOL, + LTC_SSHDATA_BYTE, + LTC_SSHDATA_BOOLEAN, + LTC_SSHDATA_UINT32, + LTC_SSHDATA_UINT64, + LTC_SSHDATA_STRING, + LTC_SSHDATA_MPINT, + LTC_SSHDATA_NAMELIST, +} ssh_data_type; + +/* VA list handy helpers with tuples of */ +int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; +int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) LTC_NULL_TERMINATED; +#endif /* LTC_SSH */ + +int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which); diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h new file mode 100644 index 0000000..0ee3ac8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h @@ -0,0 +1,803 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- NUMBER THEORY ---- */ + +enum public_key_type { + /* Refers to the public key */ + PK_PUBLIC = 0x0000, + /* Refers to the private key */ + PK_PRIVATE = 0x0001, + + /* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */ + PK_STD = 0x1000, + /* Indicates compressed public ECC key */ + PK_COMPRESSED = 0x2000, + /* Indicates ECC key with the curve specified by OID */ + PK_CURVEOID = 0x4000 +}; + +int rand_prime(void *N, long len, prng_state *prng, int wprng); + +/* ---- RSA ---- */ +#ifdef LTC_MRSA + +/** RSA 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_make_key_ubin_e(prng_state *prng, int wprng, int size, + const unsigned char *e, unsigned long elen, rsa_key *key); +int rsa_get_size(const rsa_key *key); + +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + const rsa_key *key); + +void rsa_free(rsa_key *key); + +/* These use 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_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_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_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_PKCS_1_PSS, hash_idx, saltlen, stat, key) + +#define rsa_sign_saltlen_get_max(hash_idx, key) \ + rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key) + +/* These can be switched between PKCS #1 v2.x and 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, + const 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, const 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, + const 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, const rsa_key *key); + +int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key); + +/* PKCS #1 import/export */ +int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key); +int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); + +int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key); +int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *passwd, unsigned long passwdlen, rsa_key *key); + +int rsa_set_key(const unsigned char *N, unsigned long Nlen, + const unsigned char *e, unsigned long elen, + const unsigned char *d, unsigned long dlen, + rsa_key *key); +int rsa_set_factors(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + rsa_key *key); +int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, + const unsigned char *dQ, unsigned long dQlen, + const unsigned char *qP, unsigned long qPlen, + rsa_key *key); +#endif + +/* ---- DH Routines ---- */ +#ifdef LTC_MDH + +typedef struct { + int type; + void *x; + void *y; + void *base; + void *prime; +} dh_key; + +int dh_get_groupsize(const dh_key *key); + +int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key); +int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key); + +int dh_set_pg(const unsigned char *p, unsigned long plen, + const unsigned char *g, unsigned long glen, + dh_key *key); +int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key); +int dh_set_pg_groupsize(int groupsize, dh_key *key); + +int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key); +int dh_generate_key(prng_state *prng, int wprng, dh_key *key); +int dh_make_key(prng_state *prng, int wprng, void *q, int xbits, dh_key *key); /* OP-TEE */ +int dh_shared_secret(const dh_key *private_key, const dh_key *public_key, + unsigned char *out, unsigned long *outlen); + +void dh_free(dh_key *key); + +int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key); +#endif /* LTC_MDH */ + + +/* ---- 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 GF(p) curve */ +typedef struct { + /** The prime that defines the field the curve is in (encoded in hex) */ + const char *prime; + + /** The fields A param (hex) */ + const char *A; + + /** 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; + + /** The co-factor */ + unsigned long cofactor; + + /** The OID */ + const char *OID; +} ltc_ecc_curve; + +/** 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; + +/** ECC key's domain parameters */ +typedef struct { + /** The size of the curve in octets */ + int size; + /** The prime that defines the field the curve is in */ + void *prime; + /** The fields A param */ + void *A; + /** The fields B param */ + void *B; + /** The order of the curve */ + void *order; + /** The base point G on the curve */ + ecc_point base; + /** The co-factor */ + unsigned long cofactor; + /** The OID */ + unsigned long oid[16]; + unsigned long oidlen; +} ltc_ecc_dp; + +/** An ECC key */ +typedef struct { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + + /** Structure with domain parameters */ + ltc_ecc_dp dp; + + /** Structure with the public key */ + ecc_point pubkey; + + /** The private key */ + void *k; +} ecc_key; + +/** Formats of ECC signatures */ +typedef enum ecc_signature_type_ { + /* ASN.1 encoded, ANSI X9.62 */ + LTC_ECCSIG_ANSIX962 = 0x0, + /* raw R, S values */ + LTC_ECCSIG_RFC7518 = 0x1, + /* raw R, S, V (+27) values */ + LTC_ECCSIG_ETH27 = 0x2, + /* SSH + ECDSA signature format defined by RFC5656 */ + LTC_ECCSIG_RFC5656 = 0x3, +} ecc_signature_type; + +/** the ECC params provided */ +extern const ltc_ecc_curve ltc_ecc_curves[]; + +void ecc_sizes(int *low, int *high); +int ecc_get_size(const ecc_key *key); + +int ecc_find_curve(const char* name_or_oid, const ltc_ecc_curve** cu); +int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key); +int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key); +int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key); +int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); +int ecc_get_oid_str(char *out, unsigned long *outlen, const 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_curve *cu); +void ecc_free(ecc_key *key); + +int ecc_export(unsigned char *out, unsigned long *outlen, int type, const 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_curve *cu); + +int ecc_ansi_x963_export(const 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, const ltc_ecc_curve *cu); + +int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); +int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ecc_key *key); +int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key); + +int ecc_shared_secret(const ecc_key *private_key, const 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, + const ecc_key *key); + +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const ecc_key *key); + +#define ecc_sign_hash_rfc7518(in_, inlen_, out_, outlen_, prng_, wprng_, key_) \ + ecc_sign_hash_ex(in_, inlen_, out_, outlen_, prng_, wprng_, LTC_ECCSIG_RFC7518, NULL, key_) + +#define ecc_sign_hash(in_, inlen_, out_, outlen_, prng_, wprng_, key_) \ + ecc_sign_hash_ex(in_, inlen_, out_, outlen_, prng_, wprng_, LTC_ECCSIG_ANSIX962, NULL, key_) + +#define ecc_verify_hash_rfc7518(sig_, siglen_, hash_, hashlen_, stat_, key_) \ + ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_RFC7518, stat_, key_) + +#define ecc_verify_hash(sig_, siglen_, hash_, hashlen_, stat_, key_) \ + ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_ANSIX962, stat_, key_) + +int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, ecc_signature_type sigformat, + int *recid, const ecc_key *key); + +int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + ecc_signature_type sigformat, int *stat, const ecc_key *key); + +int ecc_recover_key(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int recid, ecc_signature_type sigformat, ecc_key *key); + +#endif + +#ifdef LTC_CURVE25519 + +typedef struct { + /** The key type, PK_PRIVATE or PK_PUBLIC */ + enum public_key_type type; + + /** The PK-algorithm, PKA_ED25519 or PKA_X25519 */ + /** This was supposed to be: + * enum public_key_algorithms algo; + * but that enum is now in tomcrypt_private.h + */ + int algo; + + /** The private key */ + unsigned char priv[32]; + + /** The public key */ + unsigned char pub[32]; +} curve25519_key; + + +/** Ed25519 Signature API */ +int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key); + +int ed25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key); + +int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); +int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + curve25519_key *key); + +int ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const curve25519_key *private_key); +int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key); +int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key); +int ed25519_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + int *stat, + const curve25519_key *public_key); +int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key); +int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key); + +/** X25519 Key-Exchange API */ +int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key); + +int x25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key); + +int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); +int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + curve25519_key *key); + +int x25519_shared_secret(const curve25519_key *private_key, + const curve25519_key *public_key, + unsigned char *out, unsigned long *outlen); + +#endif /* LTC_CURVE25519 */ + +#ifdef LTC_MDSA + +/* Max diff between group and modulus size in bytes (max case: L=8192bits, N=256bits) */ +#define LTC_MDSA_DELTA 992 + +/* Max DSA group size in bytes */ +#define LTC_MDSA_MAX_GROUP 64 + +/* Max DSA modulus size in bytes (the actual DSA size, max 8192 bits) */ +#define LTC_MDSA_MAX_MODULUS 1024 + +/** 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); + +int dsa_set_pqg(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + const unsigned char *g, unsigned long glen, + dsa_key *key); +int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, dsa_key *key); +int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); + +int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key); +int dsa_generate_key(prng_state *prng, int wprng, 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, const 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, const dsa_key *key); + +int dsa_verify_hash_raw( void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, const dsa_key *key); + +int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const 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, + const dsa_key *key); + +int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const 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, const dsa_key *key); +int dsa_verify_key(const dsa_key *key, int *stat); +int dsa_shared_secret(void *private_key, void *base, + const dsa_key *public_key, + unsigned char *out, unsigned long *outlen); +#endif /* LTC_MDSA */ + +#ifdef LTC_DER +/* DER handling */ + +typedef enum ltc_asn1_type_ { + /* 0 */ + LTC_ASN1_EOL, + LTC_ASN1_BOOLEAN, + LTC_ASN1_INTEGER, + LTC_ASN1_SHORT_INTEGER, + LTC_ASN1_BIT_STRING, + /* 5 */ + LTC_ASN1_OCTET_STRING, + LTC_ASN1_NULL, + LTC_ASN1_OBJECT_IDENTIFIER, + LTC_ASN1_IA5_STRING, + LTC_ASN1_PRINTABLE_STRING, + /* 10 */ + LTC_ASN1_UTF8_STRING, + LTC_ASN1_UTCTIME, + LTC_ASN1_CHOICE, + LTC_ASN1_SEQUENCE, + LTC_ASN1_SET, + /* 15 */ + LTC_ASN1_SETOF, + LTC_ASN1_RAW_BIT_STRING, + LTC_ASN1_TELETEX_STRING, + LTC_ASN1_GENERALIZEDTIME, + LTC_ASN1_CUSTOM_TYPE, +} ltc_asn1_type; + +typedef enum { + LTC_ASN1_CL_UNIVERSAL = 0x0, + LTC_ASN1_CL_APPLICATION = 0x1, + LTC_ASN1_CL_CONTEXT_SPECIFIC = 0x2, + LTC_ASN1_CL_PRIVATE = 0x3, +} ltc_asn1_class; + +typedef enum { + LTC_ASN1_PC_PRIMITIVE = 0x0, + LTC_ASN1_PC_CONSTRUCTED = 0x1, +} ltc_asn1_pc; + +/** A LTC ASN.1 list type */ +typedef struct ltc_asn1_list_ { + /** The LTC ASN.1 enumerated type identifier */ + ltc_asn1_type 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 + * 1. This is used by the CHOICE ASN.1 type to indicate which choice was made + * 2. This is used by the ASN.1 decoder to indicate if an element is used + * 3. This is used by the flexi-decoder to indicate the first byte of the identifier */ + int used; + /** Flag used to indicate optional items in ASN.1 sequences */ + int optional; + /** ASN.1 identifier */ + ltc_asn1_class klass; + ltc_asn1_pc pc; + ulong64 tag; + /** 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; \ + LTC_MACRO_list[LTC_MACRO_temp].optional = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].klass = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].pc = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \ + } while (0) + +#define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \ + do { \ + int LTC_MACRO_temp = (index); \ + ltc_asn1_list *LTC_MACRO_list = (list); \ + LTC_MACRO_list[LTC_MACRO_temp].type = LTC_ASN1_CUSTOM_TYPE; \ + LTC_MACRO_list[LTC_MACRO_temp].klass = (Class); \ + LTC_MACRO_list[LTC_MACRO_temp].pc = (Pc); \ + LTC_MACRO_list[LTC_MACRO_temp].tag = (Tag); \ + } while (0) + +#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \ + do { \ + int LTC_MACRO_temp##__LINE__ = (index); \ + LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, 1); \ + LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \ + } while (0) + +#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \ + do { \ + int LTC_MACRO_temp##__LINE__ = (index); \ + LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, Size); \ + LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_PRIMITIVE, Tag); \ + list[LTC_MACRO_temp##__LINE__].used = (int)(Type); \ + } while (0) + +extern const char* der_asn1_class_to_string_map[]; +extern const unsigned long der_asn1_class_to_string_map_sz; + +extern const char* der_asn1_pc_to_string_map[]; +extern const unsigned long der_asn1_pc_to_string_map_sz; + +extern const char* der_asn1_tag_to_string_map[]; +extern const unsigned long der_asn1_tag_to_string_map_sz; + +/* SEQUENCE */ +int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int type_of); + +#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE) + +/** The supported bitmap for all the + * decoders with a `flags` argument. + */ +enum ltc_der_seq { + LTC_DER_SEQ_ZERO = 0x0u, + + /** Bit0 - [0]=Unordered (SET or SETOF) + * [1]=Ordered (SEQUENCE) */ + LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO, + LTC_DER_SEQ_ORDERED = 0x1u, + + /** Bit1 - [0]=Relaxed + * [1]=Strict */ + LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO, + LTC_DER_SEQ_STRICT = 0x2u, + + /** Alternative naming */ + LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED, + LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED, +}; + +int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen, unsigned int flags); + +#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED) +#define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT) + +int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen); + + +/* Custom-types */ +int der_encode_custom_type(const ltc_asn1_list *root, + unsigned char *out, unsigned long *outlen); + +int der_decode_custom_type(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root); + +int der_length_custom_type(const ltc_asn1_list *root, + unsigned long *outlen, + unsigned long *payloadlen); + +/* SET */ +#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET) +#define der_length_set der_length_sequence +int der_encode_set(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_encode_setof(const 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, ...) LTC_NULL_TERMINATED; +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; + +/* FLEXI DECODER handle unknown list decoder */ +int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); +#define der_free_sequence_flexi der_sequence_free +void der_sequence_free(ltc_asn1_list *in); +void der_sequence_shrink(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 *outlen); + +/* 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_encode_raw_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_raw_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(const 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(const 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); + +/* TELETEX STRING */ +int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +/* 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_MAX__) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR) + #if defined(__WCHAR_MAX__) + #define LTC_WCHAR_MAX __WCHAR_MAX__ + #else + #include + #define LTC_WCHAR_MAX WCHAR_MAX + #endif +/* please note that it might happen that LTC_WCHAR_MAX is undefined */ +#else + typedef ulong32 wchar_t; + #define LTC_WCHAR_MAX 0xFFFFFFFF +#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(const 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(const ltc_utctime *utctime, unsigned long *outlen); + +/* GeneralizedTime */ +typedef struct { + unsigned YYYY, /* year */ + MM, /* month */ + DD, /* day */ + hh, /* hour */ + mm, /* minute */ + ss, /* second */ + fs, /* fractional seconds */ + off_dir, /* timezone offset direction 0 == +, 1 == - */ + off_hh, /* timezone offset hours */ + off_mm; /* timezone offset minutes */ +} ltc_generalizedtime; + +int der_encode_generalizedtime(const ltc_generalizedtime *gtime, + unsigned char *out, unsigned long *outlen); + +int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, + ltc_generalizedtime *out); + +int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen); + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h new file mode 100644 index 0000000..a0aa892 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h @@ -0,0 +1,99 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* PKCS Header Info */ + +/* ===> PKCS #1 -- RSA Cryptography <=== */ +#ifdef LTC_PKCS_1 + +enum ltc_pkcs_1_v1_5_blocks +{ + LTC_PKCS_1_EMSA = 1, /* Block type 1 (PKCS #1 v1.5 signature padding) */ + LTC_PKCS_1_EME = 2 /* Block type 2 (PKCS #1 v1.5 encryption padding) */ +}; + +enum ltc_pkcs_1_paddings +{ + LTC_PKCS_1_V1_5 = 1, /* PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */ + LTC_PKCS_1_OAEP = 2, /* PKCS #1 v2.0 encryption padding */ + LTC_PKCS_1_PSS = 3, /* PKCS #1 v2.1 signature padding */ + LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */ +}; + +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 */ + +/* ===> PKCS #5 -- Password Based Cryptography <=== */ +#ifdef LTC_PKCS_5 + +/* Algorithm #1 (PBKDF1) */ +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 #1 (PBKDF1) - OpenSSL-compatible variant for arbitrarily-long keys. + Compatible with EVP_BytesToKey() */ +int pkcs_5_alg1_openssl(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 (PBKDF2) */ +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 pkcs_5_test (void); +#endif /* LTC_PKCS_5 */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_private.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_private.h new file mode 100644 index 0000000..a65c83e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_private.h @@ -0,0 +1,500 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt.h" + +/* + * Internal Macros + */ + +#define LTC_PAD_MASK (0xF000U) + +/* `NULL` as defined by the standard is not guaranteed to be of a pointer + * type. In order to make sure that in vararg API's a pointer type is used, + * define our own version and use that one internally. + */ +#ifndef LTC_NULL + #define LTC_NULL ((void *)0) +#endif + +/* + * Internal Enums + */ + +enum ltc_oid_id { + LTC_OID_RSA, + LTC_OID_DSA, + LTC_OID_EC, + LTC_OID_EC_PRIMEF, + LTC_OID_X25519, + LTC_OID_ED25519, +}; + +/* + * Internal Types + */ + +typedef struct { + int size; + const char *name, *base, *prime; +} ltc_dh_set_type; + + +typedef int (*fn_kdf_t)(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); + +typedef struct { + /* KDF */ + fn_kdf_t kdf; + /* Hash or HMAC */ + const char* h; + /* cipher */ + const char* c; + unsigned long keylen; + /* not used for pbkdf2 */ + unsigned long blocklen; +} pbes_properties; + +typedef struct +{ + pbes_properties type; + const void *pwd; + unsigned long pwdlen; + ltc_asn1_list *enc_data; + ltc_asn1_list *salt; + ltc_asn1_list *iv; + unsigned long iterations; + /* only used for RC2 */ + unsigned long key_bits; +} pbes_arg; + +/* + * Internal functions + */ + + +/* tomcrypt_cipher.h */ + +void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey); +int blowfish_expand(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey); +int blowfish_setup_with_data(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey); + +/* tomcrypt_hash.h */ + +/* a macro for making hash "process" functions */ +#define HASH_PROCESS_(func_name, compress_name, compress_n_name, state_var, block_size) \ +int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ +{ \ + unsigned long n, blocks; \ + int err; \ + int (*compress)(hash_state *, const unsigned char *) = compress_name; \ + int (*compress_n)(hash_state *, const unsigned char *, int) = compress_n_name;\ + LTC_ARGCHK(md != NULL); \ + LTC_ARGCHK(in != NULL); \ + if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ + return CRYPT_INVALID_ARG; \ + } \ + if (((md-> state_var .length + inlen * 8) < md-> state_var .length) \ + || ((inlen * 8) < inlen)) { \ + return CRYPT_HASH_OVERFLOW; \ + } \ + while (inlen > 0) { \ + if (md-> state_var .curlen == 0 && inlen >= block_size) { \ + if (compress_n) { \ + blocks = inlen / block_size; \ + err = compress_n (md, in, blocks); \ + } else { \ + blocks = 1; \ + err = compress (md, in); \ + } \ + if (err != CRYPT_OK) \ + return err; \ + md-> state_var .length += blocks * block_size * 8; \ + in += blocks * block_size; \ + inlen -= blocks * block_size; \ + } else { \ + n = MIN(inlen, (block_size - md-> state_var .curlen)); \ + XMEMCPY(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 (compress_n) { \ + err = compress_n (md, md-> state_var .buf, 1); \ + } else { \ + err = compress (md, md-> state_var .buf); \ + } \ + if (err != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += 8*block_size; \ + md-> state_var .curlen = 0; \ + } \ + } \ + } \ + return CRYPT_OK; \ +} + +/* define a hash "process" function based on a 1-block compress function */ +#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ + HASH_PROCESS_(func_name, compress_name, NULL, state_var, block_size) + +/* define a hash "process" function based on a n-block compress function */ +#define HASH_PROCESS_NBLOCKS(func_name, compress_n_name, state_var, block_size) \ + HASH_PROCESS_(func_name, NULL, compress_n_name, state_var, block_size) + + +/* tomcrypt_mac.h */ + +int ocb3_int_ntz(unsigned long x); +void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len); + + +/* tomcrypt_math.h */ + +#if !defined(DESC_DEF_ONLY) + +#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_init_size(a, b) ltc_mp.init_size(a, b) +#define mp_init_multi_size ltc_init_multi_size +#define mp_clear(a) ltc_mp.deinit(a) +#define mp_clear_multi ltc_deinit_multi +#define mp_cleanup_multi ltc_cleanup_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_sqrtmod_prime(a, b, c) ltc_mp.sqrtmod_prime(a, b, c) +#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.mpdiv(a, b, NULL, 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_addmod(a, b, c, d) ltc_mp.addmod(a, b, c, d) +#define mp_submod(a, b, c, d) ltc_mp.submod(a, b, c, d) +#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, b, 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) + +#define mp_rand(a, b) ltc_mp.rand(a, b) + +#endif + + +/* tomcrypt_misc.h */ + +typedef enum { + /** Use `\r\n` as line separator */ + BASE64_PEM_CRLF = 1, + /** Create output with 72 chars line length */ + BASE64_PEM_SSH = 2, +} base64_pem_flags; + +int base64_encode_pem(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int flags); + +void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz); + +int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size); + +int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res); +int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res); + + +/* tomcrypt_pk.h */ + +int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng); +int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng); + +int pk_get_oid(enum ltc_oid_id id, const char **st); +int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen); +int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen); + +/* ---- DH Routines ---- */ +#ifdef LTC_MRSA +int rsa_init(rsa_key *key); +void rsa_shrink_key(rsa_key *key); +int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, + rsa_key *key); /* used by op-tee */ +int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key); +#endif /* LTC_MRSA */ + +/* ---- DH Routines ---- */ +#ifdef LTC_MDH +extern const ltc_dh_set_type ltc_dh_sets[]; + +int dh_check_pubkey(const dh_key *key); +#endif /* LTC_MDH */ + +/* ---- ECC Routines ---- */ +#ifdef LTC_MECC +int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key); +int ecc_copy_curve(const ecc_key *srckey, ecc_key *key); +int ecc_set_curve_by_size(int size, ecc_key *key); +int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key); + +#ifdef LTC_SSH +int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key); +#endif + +/* low level functions */ +ecc_point *ltc_ecc_new_point(void); +void ltc_ecc_del_point(ecc_point *p); +int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p); +int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst); +int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y); +int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval); +int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y); +int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed); +int ltc_ecc_verify_key(const ecc_key *key); + +/* point ops (mp == montgomery digit) */ +#if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC) +/* R = 2P */ +int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp); + +/* R = P + Q */ +int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp); +#endif + +#if defined(LTC_MECC_FP) +/* 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 *a, 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, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map); + +#ifdef LTC_ECC_SHAMIR +/* kA*A + kB*B = C */ +int ltc_ecc_mul2add(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus); + +#ifdef LTC_MECC_FP +/* Shamir's trick with optimized point multiplication using fixed point cache */ +int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus); +#endif + +#endif + + +/* map P to affine from projective */ +int ltc_ecc_map(ecc_point *P, void *modulus, void *mp); +#endif /* LTC_MECC */ + +#ifdef LTC_MDSA +int dsa_int_validate_xy(const dsa_key *key, int *stat); +int dsa_int_validate_pqg(const dsa_key *key, int *stat); +int dsa_int_validate_primes(const dsa_key *key, int *stat); +#endif /* LTC_MDSA */ + + +#ifdef LTC_CURVE25519 + +int tweetnacl_crypto_sign( + unsigned char *sm,unsigned long long *smlen, + const unsigned char *m,unsigned long long mlen, + const unsigned char *sk,const unsigned char *pk, + const unsigned char *ctx,unsigned long long cs); +int tweetnacl_crypto_sign_open( + int *stat, + unsigned char *m,unsigned long long *mlen, + const unsigned char *sm,unsigned long long smlen, + const unsigned char *ctx, unsigned long long cs, + const unsigned char *pk); +int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, unsigned char *pk,unsigned char *sk); +int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk); +int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p); +int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n); +int tweetnacl_crypto_ph(unsigned char *out, const unsigned char *msg, unsigned long long msglen); + +typedef int (*sk_to_pk)(unsigned char *pk ,const unsigned char *sk); +int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + enum ltc_oid_id id, sk_to_pk fp, + curve25519_key *key); +int ec25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key); +int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen, + unsigned char flag, + const unsigned char *ctx, unsigned long ctxlen); +#endif /* LTC_CURVE25519 */ + +#ifdef LTC_DER + +#define LTC_ASN1_IS_TYPE(e, t) (((e) != NULL) && ((e)->type == (t))) + +/* DER handling */ +int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root, + ltc_asn1_list *list, unsigned long outlen, unsigned int flags); + +int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen); +int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id); +int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen); + +int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen); +int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen); +int der_length_asn1_length(unsigned long len, unsigned long *outlen); + +int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen, unsigned long *payloadlen); + +extern const ltc_asn1_type der_asn1_tag_to_type_map[]; +extern const unsigned long der_asn1_tag_to_type_map_sz; + +extern const int der_asn1_type_to_identifier_map[]; +extern const unsigned long der_asn1_type_to_identifier_map_sz; + +int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) + LTC_NULL_TERMINATED; + +int der_teletex_char_encode(int c); +int der_teletex_value_decode(int v); + +int der_utf8_valid_char(const wchar_t c); + +typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *ctx); + +int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, + enum ltc_oid_id algorithm, ltc_asn1_type param_type, + ltc_asn1_list* parameters, unsigned long *parameters_len, + public_key_decode_cb callback, void *ctx); + +/* SUBJECT PUBLIC KEY INFO */ +int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, + unsigned int algorithm, const void* public_key, unsigned long public_key_len, + ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len); + +int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, + unsigned int algorithm, void* public_key, unsigned long* public_key_len, + ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len); + +int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size); +int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); + +#endif /* LTC_DER */ + +/* tomcrypt_pkcs.h */ + +#ifdef LTC_PKCS_8 + +int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + ltc_asn1_list **decoded_list); + +#endif /* LTC_PKCS_8 */ + + +#ifdef LTC_PKCS_12 + +int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int pkcs12_kdf( int hash_id, + const unsigned char *pw, unsigned long pwlen, + const unsigned char *salt, unsigned long saltlen, + unsigned int iterations, unsigned char purpose, + unsigned char *out, unsigned long outlen); + +#endif /* LTC_PKCS_12 */ + +/* tomcrypt_prng.h */ + +#define LTC_PRNG_EXPORT(which) \ +int which ## _export(unsigned char *out, unsigned long *outlen, prng_state *prng) \ +{ \ + unsigned long len = which ## _desc.export_size; \ + \ + LTC_ARGCHK(prng != NULL); \ + LTC_ARGCHK(out != NULL); \ + LTC_ARGCHK(outlen != NULL); \ + \ + if (*outlen < len) { \ + *outlen = len; \ + return CRYPT_BUFFER_OVERFLOW; \ + } \ + \ + if (which ## _read(out, len, prng) != len) { \ + return CRYPT_ERROR_READPRNG; \ + } \ + \ + *outlen = len; \ + return CRYPT_OK; \ +} + +/* extract a byte portably */ +#ifdef _MSC_VER + #define LTC_BYTE(x, n) ((unsigned char)((x) >> (8 * (n)))) +#else + #define LTC_BYTE(x, n) (((x) >> (8 * (n))) & 255) +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h new file mode 100644 index 0000000..e7e1716 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h @@ -0,0 +1,223 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- PRNG Stuff ---- */ +#ifdef LTC_YARROW +struct yarrow_prng { + int cipher, hash; + unsigned char pool[MAXBLOCKSIZE]; + symmetric_CTR ctr; +}; +#endif + +#ifdef LTC_RC4 +struct rc4_prng { + rc4_state s; +}; +#endif + +#ifdef LTC_CHACHA20_PRNG +struct chacha20_prng { + chacha_state s; /* chacha state */ + unsigned char ent[40]; /* entropy buffer */ + unsigned long idx; /* entropy counter */ +}; +#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 */ + ulong64 wd; + ulong64 reset_cnt; /* number of times we have reseeded */ +}; +#endif + +#ifdef LTC_SOBER128 +struct sober128_prng { + sober128_state s; /* sober128 state */ + unsigned char ent[40]; /* entropy buffer */ + unsigned long idx; /* entropy counter */ +}; +#endif + +typedef struct { + union { + char dummy[1]; +#ifdef LTC_YARROW + struct yarrow_prng yarrow; +#endif +#ifdef LTC_RC4 + struct rc4_prng rc4; +#endif +#ifdef LTC_CHACHA20_PRNG + struct chacha20_prng chacha; +#endif +#ifdef LTC_FORTUNA + struct fortuna_prng fortuna; +#endif +#ifdef LTC_SOBER128 + struct sober128_prng sober128; +#endif + } u; + short ready; /* ready flag 0-1 */ + LTC_MUTEX_TYPE(lock) /* lock */ +} prng_state; + +/** PRNG descriptor */ +extern const 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_add_random_event(unsigned long source, unsigned long pool, 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_update_seed(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_CHACHA20_PRNG +int chacha20_prng_start(prng_state *prng); +int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int chacha20_prng_ready(prng_state *prng); +unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int chacha20_prng_done(prng_state *prng); +int chacha20_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int chacha20_prng_test(void); +extern const struct ltc_prng_descriptor chacha20_prng_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 register_all_prngs(void); +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)); + +#ifdef LTC_PRNG_ENABLE_LTC_RNG +extern unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, + void (*callback)(void)); +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c new file mode 100644 index 0000000..ac26e10 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2BMAC + +/** + Initialize an BLAKE2B MAC context. + @param st The BLAKE2B MAC state + @param outlen The size of the MAC output (octets) + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + return blake2b_init(st, outlen, key, keylen); +} + +/** + Process data through BLAKE2B MAC + @param st The BLAKE2B MAC state + @param in The data to send through HMAC + @param inlen The length of the data to HMAC (octets) + @return CRYPT_OK if successful +*/ +int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen) +{ + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + return blake2b_process(st, in, inlen); +} + +/** + Terminate a BLAKE2B MAC session + @param st The BLAKE2B MAC state + @param mac [out] The destination of the BLAKE2B MAC authentication tag + @param maclen [in/out] The max size and resulting size of the BLAKE2B MAC authentication tag + @return CRYPT_OK if successful +*/ +int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + LTC_ARGCHK(*maclen >= st->blake2b.outlen); + + *maclen = st->blake2b.outlen; + return blake2b_done(st, mac); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c new file mode 100644 index 0000000..831e845 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2BMAC + +/** + BLAKE2B MAC a file + @param fname The name of the file you wish to BLAKE2B MAC + @param key The secret key + @param keylen The length of the secret key + @param mac [out] The BLAKE2B MAC authentication tag + @param maclen [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 blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); + return CRYPT_NOP; +#else + blake2bmac_state st; + FILE *in; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = blake2bmac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = blake2bmac_done(&st, mac, maclen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2bmac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c new file mode 100644 index 0000000..3f5e309 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2BMAC + +/** + BLAKE2B MAC a block of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to BLAKE2B MAC + @param inlen The length of the data to BLAKE2B MAC (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) +{ + blake2bmac_state st; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = blake2bmac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + err = blake2bmac_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2bmac_state)); +#endif + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c new file mode 100644 index 0000000..403fba3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" +#include + +#ifdef LTC_BLAKE2BMAC + +/** + BLAKE2B MAC multiple blocks of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @param in The data to BLAKE2B MAC + @param inlen The length of the data to BLAKE2B MAC (octets) + @param ... tuples of (data,len) pairs to BLAKE2B MAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) +{ + blake2bmac_state st; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + va_start(args, inlen); + curptr = in; + curlen = inlen; + if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + for (;;) { + if ((err = blake2bmac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) break; + curlen = va_arg(args, unsigned long); + } + err = blake2bmac_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2bmac_state)); +#endif + va_end(args); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c new file mode 100644 index 0000000..b2651cc --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c @@ -0,0 +1,304 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2BMAC + +int blake2bmac_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const unsigned char tests[256][64] = { + /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt */ + { 0x10, 0xeb, 0xb6, 0x77, 0x00, 0xb1, 0x86, 0x8e, 0xfb, 0x44, 0x17, 0x98, 0x7a, 0xcf, 0x46, 0x90, 0xae, 0x9d, 0x97, 0x2f, 0xb7, 0xa5, 0x90, 0xc2, 0xf0, 0x28, 0x71, 0x79, 0x9a, 0xaa, 0x47, 0x86, 0xb5, 0xe9, 0x96, 0xe8, 0xf0, 0xf4, 0xeb, 0x98, 0x1f, 0xc2, 0x14, 0xb0, 0x05, 0xf4, 0x2d, 0x2f, 0xf4, 0x23, 0x34, 0x99, 0x39, 0x16, 0x53, 0xdf, 0x7a, 0xef, 0xcb, 0xc1, 0x3f, 0xc5, 0x15, 0x68 }, + { 0x96, 0x1f, 0x6d, 0xd1, 0xe4, 0xdd, 0x30, 0xf6, 0x39, 0x01, 0x69, 0x0c, 0x51, 0x2e, 0x78, 0xe4, 0xb4, 0x5e, 0x47, 0x42, 0xed, 0x19, 0x7c, 0x3c, 0x5e, 0x45, 0xc5, 0x49, 0xfd, 0x25, 0xf2, 0xe4, 0x18, 0x7b, 0x0b, 0xc9, 0xfe, 0x30, 0x49, 0x2b, 0x16, 0xb0, 0xd0, 0xbc, 0x4e, 0xf9, 0xb0, 0xf3, 0x4c, 0x70, 0x03, 0xfa, 0xc0, 0x9a, 0x5e, 0xf1, 0x53, 0x2e, 0x69, 0x43, 0x02, 0x34, 0xce, 0xbd }, + { 0xda, 0x2c, 0xfb, 0xe2, 0xd8, 0x40, 0x9a, 0x0f, 0x38, 0x02, 0x61, 0x13, 0x88, 0x4f, 0x84, 0xb5, 0x01, 0x56, 0x37, 0x1a, 0xe3, 0x04, 0xc4, 0x43, 0x01, 0x73, 0xd0, 0x8a, 0x99, 0xd9, 0xfb, 0x1b, 0x98, 0x31, 0x64, 0xa3, 0x77, 0x07, 0x06, 0xd5, 0x37, 0xf4, 0x9e, 0x0c, 0x91, 0x6d, 0x9f, 0x32, 0xb9, 0x5c, 0xc3, 0x7a, 0x95, 0xb9, 0x9d, 0x85, 0x74, 0x36, 0xf0, 0x23, 0x2c, 0x88, 0xa9, 0x65 }, + { 0x33, 0xd0, 0x82, 0x5d, 0xdd, 0xf7, 0xad, 0xa9, 0x9b, 0x0e, 0x7e, 0x30, 0x71, 0x04, 0xad, 0x07, 0xca, 0x9c, 0xfd, 0x96, 0x92, 0x21, 0x4f, 0x15, 0x61, 0x35, 0x63, 0x15, 0xe7, 0x84, 0xf3, 0xe5, 0xa1, 0x7e, 0x36, 0x4a, 0xe9, 0xdb, 0xb1, 0x4c, 0xb2, 0x03, 0x6d, 0xf9, 0x32, 0xb7, 0x7f, 0x4b, 0x29, 0x27, 0x61, 0x36, 0x5f, 0xb3, 0x28, 0xde, 0x7a, 0xfd, 0xc6, 0xd8, 0x99, 0x8f, 0x5f, 0xc1 }, + { 0xbe, 0xaa, 0x5a, 0x3d, 0x08, 0xf3, 0x80, 0x71, 0x43, 0xcf, 0x62, 0x1d, 0x95, 0xcd, 0x69, 0x05, 0x14, 0xd0, 0xb4, 0x9e, 0xff, 0xf9, 0xc9, 0x1d, 0x24, 0xb5, 0x92, 0x41, 0xec, 0x0e, 0xef, 0xa5, 0xf6, 0x01, 0x96, 0xd4, 0x07, 0x04, 0x8b, 0xba, 0x8d, 0x21, 0x46, 0x82, 0x8e, 0xbc, 0xb0, 0x48, 0x8d, 0x88, 0x42, 0xfd, 0x56, 0xbb, 0x4f, 0x6d, 0xf8, 0xe1, 0x9c, 0x4b, 0x4d, 0xaa, 0xb8, 0xac }, + { 0x09, 0x80, 0x84, 0xb5, 0x1f, 0xd1, 0x3d, 0xea, 0xe5, 0xf4, 0x32, 0x0d, 0xe9, 0x4a, 0x68, 0x8e, 0xe0, 0x7b, 0xae, 0xa2, 0x80, 0x04, 0x86, 0x68, 0x9a, 0x86, 0x36, 0x11, 0x7b, 0x46, 0xc1, 0xf4, 0xc1, 0xf6, 0xaf, 0x7f, 0x74, 0xae, 0x7c, 0x85, 0x76, 0x00, 0x45, 0x6a, 0x58, 0xa3, 0xaf, 0x25, 0x1d, 0xc4, 0x72, 0x3a, 0x64, 0xcc, 0x7c, 0x0a, 0x5a, 0xb6, 0xd9, 0xca, 0xc9, 0x1c, 0x20, 0xbb }, + { 0x60, 0x44, 0x54, 0x0d, 0x56, 0x08, 0x53, 0xeb, 0x1c, 0x57, 0xdf, 0x00, 0x77, 0xdd, 0x38, 0x10, 0x94, 0x78, 0x1c, 0xdb, 0x90, 0x73, 0xe5, 0xb1, 0xb3, 0xd3, 0xf6, 0xc7, 0x82, 0x9e, 0x12, 0x06, 0x6b, 0xba, 0xca, 0x96, 0xd9, 0x89, 0xa6, 0x90, 0xde, 0x72, 0xca, 0x31, 0x33, 0xa8, 0x36, 0x52, 0xba, 0x28, 0x4a, 0x6d, 0x62, 0x94, 0x2b, 0x27, 0x1f, 0xfa, 0x26, 0x20, 0xc9, 0xe7, 0x5b, 0x1f }, + { 0x7a, 0x8c, 0xfe, 0x9b, 0x90, 0xf7, 0x5f, 0x7e, 0xcb, 0x3a, 0xcc, 0x05, 0x3a, 0xae, 0xd6, 0x19, 0x31, 0x12, 0xb6, 0xf6, 0xa4, 0xae, 0xeb, 0x3f, 0x65, 0xd3, 0xde, 0x54, 0x19, 0x42, 0xde, 0xb9, 0xe2, 0x22, 0x81, 0x52, 0xa3, 0xc4, 0xbb, 0xbe, 0x72, 0xfc, 0x3b, 0x12, 0x62, 0x95, 0x28, 0xcf, 0xbb, 0x09, 0xfe, 0x63, 0x0f, 0x04, 0x74, 0x33, 0x9f, 0x54, 0xab, 0xf4, 0x53, 0xe2, 0xed, 0x52 }, + { 0x38, 0x0b, 0xea, 0xf6, 0xea, 0x7c, 0xc9, 0x36, 0x5e, 0x27, 0x0e, 0xf0, 0xe6, 0xf3, 0xa6, 0x4f, 0xb9, 0x02, 0xac, 0xae, 0x51, 0xdd, 0x55, 0x12, 0xf8, 0x42, 0x59, 0xad, 0x2c, 0x91, 0xf4, 0xbc, 0x41, 0x08, 0xdb, 0x73, 0x19, 0x2a, 0x5b, 0xbf, 0xb0, 0xcb, 0xcf, 0x71, 0xe4, 0x6c, 0x3e, 0x21, 0xae, 0xe1, 0xc5, 0xe8, 0x60, 0xdc, 0x96, 0xe8, 0xeb, 0x0b, 0x7b, 0x84, 0x26, 0xe6, 0xab, 0xe9 }, + { 0x60, 0xfe, 0x3c, 0x45, 0x35, 0xe1, 0xb5, 0x9d, 0x9a, 0x61, 0xea, 0x85, 0x00, 0xbf, 0xac, 0x41, 0xa6, 0x9d, 0xff, 0xb1, 0xce, 0xad, 0xd9, 0xac, 0xa3, 0x23, 0xe9, 0xa6, 0x25, 0xb6, 0x4d, 0xa5, 0x76, 0x3b, 0xad, 0x72, 0x26, 0xda, 0x02, 0xb9, 0xc8, 0xc4, 0xf1, 0xa5, 0xde, 0x14, 0x0a, 0xc5, 0xa6, 0xc1, 0x12, 0x4e, 0x4f, 0x71, 0x8c, 0xe0, 0xb2, 0x8e, 0xa4, 0x73, 0x93, 0xaa, 0x66, 0x37 }, + { 0x4f, 0xe1, 0x81, 0xf5, 0x4a, 0xd6, 0x3a, 0x29, 0x83, 0xfe, 0xaa, 0xf7, 0x7d, 0x1e, 0x72, 0x35, 0xc2, 0xbe, 0xb1, 0x7f, 0xa3, 0x28, 0xb6, 0xd9, 0x50, 0x5b, 0xda, 0x32, 0x7d, 0xf1, 0x9f, 0xc3, 0x7f, 0x02, 0xc4, 0xb6, 0xf0, 0x36, 0x8c, 0xe2, 0x31, 0x47, 0x31, 0x3a, 0x8e, 0x57, 0x38, 0xb5, 0xfa, 0x2a, 0x95, 0xb2, 0x9d, 0xe1, 0xc7, 0xf8, 0x26, 0x4e, 0xb7, 0x7b, 0x69, 0xf5, 0x85, 0xcd }, + { 0xf2, 0x28, 0x77, 0x3c, 0xe3, 0xf3, 0xa4, 0x2b, 0x5f, 0x14, 0x4d, 0x63, 0x23, 0x7a, 0x72, 0xd9, 0x96, 0x93, 0xad, 0xb8, 0x83, 0x7d, 0x0e, 0x11, 0x2a, 0x8a, 0x0f, 0x8f, 0xff, 0xf2, 0xc3, 0x62, 0x85, 0x7a, 0xc4, 0x9c, 0x11, 0xec, 0x74, 0x0d, 0x15, 0x00, 0x74, 0x9d, 0xac, 0x9b, 0x1f, 0x45, 0x48, 0x10, 0x8b, 0xf3, 0x15, 0x57, 0x94, 0xdc, 0xc9, 0xe4, 0x08, 0x28, 0x49, 0xe2, 0xb8, 0x5b }, + { 0x96, 0x24, 0x52, 0xa8, 0x45, 0x5c, 0xc5, 0x6c, 0x85, 0x11, 0x31, 0x7e, 0x3b, 0x1f, 0x3b, 0x2c, 0x37, 0xdf, 0x75, 0xf5, 0x88, 0xe9, 0x43, 0x25, 0xfd, 0xd7, 0x70, 0x70, 0x35, 0x9c, 0xf6, 0x3a, 0x9a, 0xe6, 0xe9, 0x30, 0x93, 0x6f, 0xdf, 0x8e, 0x1e, 0x08, 0xff, 0xca, 0x44, 0x0c, 0xfb, 0x72, 0xc2, 0x8f, 0x06, 0xd8, 0x9a, 0x21, 0x51, 0xd1, 0xc4, 0x6c, 0xd5, 0xb2, 0x68, 0xef, 0x85, 0x63 }, + { 0x43, 0xd4, 0x4b, 0xfa, 0x18, 0x76, 0x8c, 0x59, 0x89, 0x6b, 0xf7, 0xed, 0x17, 0x65, 0xcb, 0x2d, 0x14, 0xaf, 0x8c, 0x26, 0x02, 0x66, 0x03, 0x90, 0x99, 0xb2, 0x5a, 0x60, 0x3e, 0x4d, 0xdc, 0x50, 0x39, 0xd6, 0xef, 0x3a, 0x91, 0x84, 0x7d, 0x10, 0x88, 0xd4, 0x01, 0xc0, 0xc7, 0xe8, 0x47, 0x78, 0x1a, 0x8a, 0x59, 0x0d, 0x33, 0xa3, 0xc6, 0xcb, 0x4d, 0xf0, 0xfa, 0xb1, 0xc2, 0xf2, 0x23, 0x55 }, + { 0xdc, 0xff, 0xa9, 0xd5, 0x8c, 0x2a, 0x4c, 0xa2, 0xcd, 0xbb, 0x0c, 0x7a, 0xa4, 0xc4, 0xc1, 0xd4, 0x51, 0x65, 0x19, 0x00, 0x89, 0xf4, 0xe9, 0x83, 0xbb, 0x1c, 0x2c, 0xab, 0x4a, 0xae, 0xff, 0x1f, 0xa2, 0xb5, 0xee, 0x51, 0x6f, 0xec, 0xd7, 0x80, 0x54, 0x02, 0x40, 0xbf, 0x37, 0xe5, 0x6c, 0x8b, 0xcc, 0xa7, 0xfa, 0xb9, 0x80, 0xe1, 0xe6, 0x1c, 0x94, 0x00, 0xd8, 0xa9, 0xa5, 0xb1, 0x4a, 0xc6 }, + { 0x6f, 0xbf, 0x31, 0xb4, 0x5a, 0xb0, 0xc0, 0xb8, 0xda, 0xd1, 0xc0, 0xf5, 0xf4, 0x06, 0x13, 0x79, 0x91, 0x2d, 0xde, 0x5a, 0xa9, 0x22, 0x09, 0x9a, 0x03, 0x0b, 0x72, 0x5c, 0x73, 0x34, 0x6c, 0x52, 0x42, 0x91, 0xad, 0xef, 0x89, 0xd2, 0xf6, 0xfd, 0x8d, 0xfc, 0xda, 0x6d, 0x07, 0xda, 0xd8, 0x11, 0xa9, 0x31, 0x45, 0x36, 0xc2, 0x91, 0x5e, 0xd4, 0x5d, 0xa3, 0x49, 0x47, 0xe8, 0x3d, 0xe3, 0x4e }, + { 0xa0, 0xc6, 0x5b, 0xdd, 0xde, 0x8a, 0xde, 0xf5, 0x72, 0x82, 0xb0, 0x4b, 0x11, 0xe7, 0xbc, 0x8a, 0xab, 0x10, 0x5b, 0x99, 0x23, 0x1b, 0x75, 0x0c, 0x02, 0x1f, 0x4a, 0x73, 0x5c, 0xb1, 0xbc, 0xfa, 0xb8, 0x75, 0x53, 0xbb, 0xa3, 0xab, 0xb0, 0xc3, 0xe6, 0x4a, 0x0b, 0x69, 0x55, 0x28, 0x51, 0x85, 0xa0, 0xbd, 0x35, 0xfb, 0x8c, 0xfd, 0xe5, 0x57, 0x32, 0x9b, 0xeb, 0xb1, 0xf6, 0x29, 0xee, 0x93 }, + { 0xf9, 0x9d, 0x81, 0x55, 0x50, 0x55, 0x8e, 0x81, 0xec, 0xa2, 0xf9, 0x67, 0x18, 0xae, 0xd1, 0x0d, 0x86, 0xf3, 0xf1, 0xcf, 0xb6, 0x75, 0xcc, 0xe0, 0x6b, 0x0e, 0xff, 0x02, 0xf6, 0x17, 0xc5, 0xa4, 0x2c, 0x5a, 0xa7, 0x60, 0x27, 0x0f, 0x26, 0x79, 0xda, 0x26, 0x77, 0xc5, 0xae, 0xb9, 0x4f, 0x11, 0x42, 0x27, 0x7f, 0x21, 0xc7, 0xf7, 0x9f, 0x3c, 0x4f, 0x0c, 0xce, 0x4e, 0xd8, 0xee, 0x62, 0xb1 }, + { 0x95, 0x39, 0x1d, 0xa8, 0xfc, 0x7b, 0x91, 0x7a, 0x20, 0x44, 0xb3, 0xd6, 0xf5, 0x37, 0x4e, 0x1c, 0xa0, 0x72, 0xb4, 0x14, 0x54, 0xd5, 0x72, 0xc7, 0x35, 0x6c, 0x05, 0xfd, 0x4b, 0xc1, 0xe0, 0xf4, 0x0b, 0x8b, 0xb8, 0xb4, 0xa9, 0xf6, 0xbc, 0xe9, 0xbe, 0x2c, 0x46, 0x23, 0xc3, 0x99, 0xb0, 0xdc, 0xa0, 0xda, 0xb0, 0x5c, 0xb7, 0x28, 0x1b, 0x71, 0xa2, 0x1b, 0x0e, 0xbc, 0xd9, 0xe5, 0x56, 0x70 }, + { 0x04, 0xb9, 0xcd, 0x3d, 0x20, 0xd2, 0x21, 0xc0, 0x9a, 0xc8, 0x69, 0x13, 0xd3, 0xdc, 0x63, 0x04, 0x19, 0x89, 0xa9, 0xa1, 0xe6, 0x94, 0xf1, 0xe6, 0x39, 0xa3, 0xba, 0x7e, 0x45, 0x18, 0x40, 0xf7, 0x50, 0xc2, 0xfc, 0x19, 0x1d, 0x56, 0xad, 0x61, 0xf2, 0xe7, 0x93, 0x6b, 0xc0, 0xac, 0x8e, 0x09, 0x4b, 0x60, 0xca, 0xee, 0xd8, 0x78, 0xc1, 0x87, 0x99, 0x04, 0x54, 0x02, 0xd6, 0x1c, 0xea, 0xf9 }, + { 0xec, 0x0e, 0x0e, 0xf7, 0x07, 0xe4, 0xed, 0x6c, 0x0c, 0x66, 0xf9, 0xe0, 0x89, 0xe4, 0x95, 0x4b, 0x05, 0x80, 0x30, 0xd2, 0xdd, 0x86, 0x39, 0x8f, 0xe8, 0x40, 0x59, 0x63, 0x1f, 0x9e, 0xe5, 0x91, 0xd9, 0xd7, 0x73, 0x75, 0x35, 0x51, 0x49, 0x17, 0x8c, 0x0c, 0xf8, 0xf8, 0xe7, 0xc4, 0x9e, 0xd2, 0xa5, 0xe4, 0xf9, 0x54, 0x88, 0xa2, 0x24, 0x70, 0x67, 0xc2, 0x08, 0x51, 0x0f, 0xad, 0xc4, 0x4c }, + { 0x9a, 0x37, 0xcc, 0xe2, 0x73, 0xb7, 0x9c, 0x09, 0x91, 0x36, 0x77, 0x51, 0x0e, 0xaf, 0x76, 0x88, 0xe8, 0x9b, 0x33, 0x14, 0xd3, 0x53, 0x2f, 0xd2, 0x76, 0x4c, 0x39, 0xde, 0x02, 0x2a, 0x29, 0x45, 0xb5, 0x71, 0x0d, 0x13, 0x51, 0x7a, 0xf8, 0xdd, 0xc0, 0x31, 0x66, 0x24, 0xe7, 0x3b, 0xec, 0x1c, 0xe6, 0x7d, 0xf1, 0x52, 0x28, 0x30, 0x20, 0x36, 0xf3, 0x30, 0xab, 0x0c, 0xb4, 0xd2, 0x18, 0xdd }, + { 0x4c, 0xf9, 0xbb, 0x8f, 0xb3, 0xd4, 0xde, 0x8b, 0x38, 0xb2, 0xf2, 0x62, 0xd3, 0xc4, 0x0f, 0x46, 0xdf, 0xe7, 0x47, 0xe8, 0xfc, 0x0a, 0x41, 0x4c, 0x19, 0x3d, 0x9f, 0xcf, 0x75, 0x31, 0x06, 0xce, 0x47, 0xa1, 0x8f, 0x17, 0x2f, 0x12, 0xe8, 0xa2, 0xf1, 0xc2, 0x67, 0x26, 0x54, 0x53, 0x58, 0xe5, 0xee, 0x28, 0xc9, 0xe2, 0x21, 0x3a, 0x87, 0x87, 0xaa, 0xfb, 0xc5, 0x16, 0xd2, 0x34, 0x31, 0x52 }, + { 0x64, 0xe0, 0xc6, 0x3a, 0xf9, 0xc8, 0x08, 0xfd, 0x89, 0x31, 0x37, 0x12, 0x98, 0x67, 0xfd, 0x91, 0x93, 0x9d, 0x53, 0xf2, 0xaf, 0x04, 0xbe, 0x4f, 0xa2, 0x68, 0x00, 0x61, 0x00, 0x06, 0x9b, 0x2d, 0x69, 0xda, 0xa5, 0xc5, 0xd8, 0xed, 0x7f, 0xdd, 0xcb, 0x2a, 0x70, 0xee, 0xec, 0xdf, 0x2b, 0x10, 0x5d, 0xd4, 0x6a, 0x1e, 0x3b, 0x73, 0x11, 0x72, 0x8f, 0x63, 0x9a, 0xb4, 0x89, 0x32, 0x6b, 0xc9 }, + { 0x5e, 0x9c, 0x93, 0x15, 0x8d, 0x65, 0x9b, 0x2d, 0xef, 0x06, 0xb0, 0xc3, 0xc7, 0x56, 0x50, 0x45, 0x54, 0x26, 0x62, 0xd6, 0xee, 0xe8, 0xa9, 0x6a, 0x89, 0xb7, 0x8a, 0xde, 0x09, 0xfe, 0x8b, 0x3d, 0xcc, 0x09, 0x6d, 0x4f, 0xe4, 0x88, 0x15, 0xd8, 0x8d, 0x8f, 0x82, 0x62, 0x01, 0x56, 0x60, 0x2a, 0xf5, 0x41, 0x95, 0x5e, 0x1f, 0x6c, 0xa3, 0x0d, 0xce, 0x14, 0xe2, 0x54, 0xc3, 0x26, 0xb8, 0x8f }, + { 0x77, 0x75, 0xdf, 0xf8, 0x89, 0x45, 0x8d, 0xd1, 0x1a, 0xef, 0x41, 0x72, 0x76, 0x85, 0x3e, 0x21, 0x33, 0x5e, 0xb8, 0x8e, 0x4d, 0xec, 0x9c, 0xfb, 0x4e, 0x9e, 0xdb, 0x49, 0x82, 0x00, 0x88, 0x55, 0x1a, 0x2c, 0xa6, 0x03, 0x39, 0xf1, 0x20, 0x66, 0x10, 0x11, 0x69, 0xf0, 0xdf, 0xe8, 0x4b, 0x09, 0x8f, 0xdd, 0xb1, 0x48, 0xd9, 0xda, 0x6b, 0x3d, 0x61, 0x3d, 0xf2, 0x63, 0x88, 0x9a, 0xd6, 0x4b }, + { 0xf0, 0xd2, 0x80, 0x5a, 0xfb, 0xb9, 0x1f, 0x74, 0x39, 0x51, 0x35, 0x1a, 0x6d, 0x02, 0x4f, 0x93, 0x53, 0xa2, 0x3c, 0x7c, 0xe1, 0xfc, 0x2b, 0x05, 0x1b, 0x3a, 0x8b, 0x96, 0x8c, 0x23, 0x3f, 0x46, 0xf5, 0x0f, 0x80, 0x6e, 0xcb, 0x15, 0x68, 0xff, 0xaa, 0x0b, 0x60, 0x66, 0x1e, 0x33, 0x4b, 0x21, 0xdd, 0xe0, 0x4f, 0x8f, 0xa1, 0x55, 0xac, 0x74, 0x0e, 0xeb, 0x42, 0xe2, 0x0b, 0x60, 0xd7, 0x64 }, + { 0x86, 0xa2, 0xaf, 0x31, 0x6e, 0x7d, 0x77, 0x54, 0x20, 0x1b, 0x94, 0x2e, 0x27, 0x53, 0x64, 0xac, 0x12, 0xea, 0x89, 0x62, 0xab, 0x5b, 0xd8, 0xd7, 0xfb, 0x27, 0x6d, 0xc5, 0xfb, 0xff, 0xc8, 0xf9, 0xa2, 0x8c, 0xae, 0x4e, 0x48, 0x67, 0xdf, 0x67, 0x80, 0xd9, 0xb7, 0x25, 0x24, 0x16, 0x09, 0x27, 0xc8, 0x55, 0xda, 0x5b, 0x60, 0x78, 0xe0, 0xb5, 0x54, 0xaa, 0x91, 0xe3, 0x1c, 0xb9, 0xca, 0x1d }, + { 0x10, 0xbd, 0xf0, 0xca, 0xa0, 0x80, 0x27, 0x05, 0xe7, 0x06, 0x36, 0x9b, 0xaf, 0x8a, 0x3f, 0x79, 0xd7, 0x2c, 0x0a, 0x03, 0xa8, 0x06, 0x75, 0xa7, 0xbb, 0xb0, 0x0b, 0xe3, 0xa4, 0x5e, 0x51, 0x64, 0x24, 0xd1, 0xee, 0x88, 0xef, 0xb5, 0x6f, 0x6d, 0x57, 0x77, 0x54, 0x5a, 0xe6, 0xe2, 0x77, 0x65, 0xc3, 0xa8, 0xf5, 0xe4, 0x93, 0xfc, 0x30, 0x89, 0x15, 0x63, 0x89, 0x33, 0xa1, 0xdf, 0xee, 0x55 }, + { 0xb0, 0x17, 0x81, 0x09, 0x2b, 0x17, 0x48, 0x45, 0x9e, 0x2e, 0x4e, 0xc1, 0x78, 0x69, 0x66, 0x27, 0xbf, 0x4e, 0xba, 0xfe, 0xbb, 0xa7, 0x74, 0xec, 0xf0, 0x18, 0xb7, 0x9a, 0x68, 0xae, 0xb8, 0x49, 0x17, 0xbf, 0x0b, 0x84, 0xbb, 0x79, 0xd1, 0x7b, 0x74, 0x31, 0x51, 0x14, 0x4c, 0xd6, 0x6b, 0x7b, 0x33, 0xa4, 0xb9, 0xe5, 0x2c, 0x76, 0xc4, 0xe1, 0x12, 0x05, 0x0f, 0xf5, 0x38, 0x5b, 0x7f, 0x0b }, + { 0xc6, 0xdb, 0xc6, 0x1d, 0xec, 0x6e, 0xae, 0xac, 0x81, 0xe3, 0xd5, 0xf7, 0x55, 0x20, 0x3c, 0x8e, 0x22, 0x05, 0x51, 0x53, 0x4a, 0x0b, 0x2f, 0xd1, 0x05, 0xa9, 0x18, 0x89, 0x94, 0x5a, 0x63, 0x85, 0x50, 0x20, 0x4f, 0x44, 0x09, 0x3d, 0xd9, 0x98, 0xc0, 0x76, 0x20, 0x5d, 0xff, 0xad, 0x70, 0x3a, 0x0e, 0x5c, 0xd3, 0xc7, 0xf4, 0x38, 0xa7, 0xe6, 0x34, 0xcd, 0x59, 0xfe, 0xde, 0xdb, 0x53, 0x9e }, + { 0xeb, 0xa5, 0x1a, 0xcf, 0xfb, 0x4c, 0xea, 0x31, 0xdb, 0x4b, 0x8d, 0x87, 0xe9, 0xbf, 0x7d, 0xd4, 0x8f, 0xe9, 0x7b, 0x02, 0x53, 0xae, 0x67, 0xaa, 0x58, 0x0f, 0x9a, 0xc4, 0xa9, 0xd9, 0x41, 0xf2, 0xbe, 0xa5, 0x18, 0xee, 0x28, 0x68, 0x18, 0xcc, 0x9f, 0x63, 0x3f, 0x2a, 0x3b, 0x9f, 0xb6, 0x8e, 0x59, 0x4b, 0x48, 0xcd, 0xd6, 0xd5, 0x15, 0xbf, 0x1d, 0x52, 0xba, 0x6c, 0x85, 0xa2, 0x03, 0xa7 }, + { 0x86, 0x22, 0x1f, 0x3a, 0xda, 0x52, 0x03, 0x7b, 0x72, 0x22, 0x4f, 0x10, 0x5d, 0x79, 0x99, 0x23, 0x1c, 0x5e, 0x55, 0x34, 0xd0, 0x3d, 0xa9, 0xd9, 0xc0, 0xa1, 0x2a, 0xcb, 0x68, 0x46, 0x0c, 0xd3, 0x75, 0xda, 0xf8, 0xe2, 0x43, 0x86, 0x28, 0x6f, 0x96, 0x68, 0xf7, 0x23, 0x26, 0xdb, 0xf9, 0x9b, 0xa0, 0x94, 0x39, 0x24, 0x37, 0xd3, 0x98, 0xe9, 0x5b, 0xb8, 0x16, 0x1d, 0x71, 0x7f, 0x89, 0x91 }, + { 0x55, 0x95, 0xe0, 0x5c, 0x13, 0xa7, 0xec, 0x4d, 0xc8, 0xf4, 0x1f, 0xb7, 0x0c, 0xb5, 0x0a, 0x71, 0xbc, 0xe1, 0x7c, 0x02, 0x4f, 0xf6, 0xde, 0x7a, 0xf6, 0x18, 0xd0, 0xcc, 0x4e, 0x9c, 0x32, 0xd9, 0x57, 0x0d, 0x6d, 0x3e, 0xa4, 0x5b, 0x86, 0x52, 0x54, 0x91, 0x03, 0x0c, 0x0d, 0x8f, 0x2b, 0x18, 0x36, 0xd5, 0x77, 0x8c, 0x1c, 0xe7, 0x35, 0xc1, 0x77, 0x07, 0xdf, 0x36, 0x4d, 0x05, 0x43, 0x47 }, + { 0xce, 0x0f, 0x4f, 0x6a, 0xca, 0x89, 0x59, 0x0a, 0x37, 0xfe, 0x03, 0x4d, 0xd7, 0x4d, 0xd5, 0xfa, 0x65, 0xeb, 0x1c, 0xbd, 0x0a, 0x41, 0x50, 0x8a, 0xad, 0xdc, 0x09, 0x35, 0x1a, 0x3c, 0xea, 0x6d, 0x18, 0xcb, 0x21, 0x89, 0xc5, 0x4b, 0x70, 0x0c, 0x00, 0x9f, 0x4c, 0xbf, 0x05, 0x21, 0xc7, 0xea, 0x01, 0xbe, 0x61, 0xc5, 0xae, 0x09, 0xcb, 0x54, 0xf2, 0x7b, 0xc1, 0xb4, 0x4d, 0x65, 0x8c, 0x82 }, + { 0x7e, 0xe8, 0x0b, 0x06, 0xa2, 0x15, 0xa3, 0xbc, 0xa9, 0x70, 0xc7, 0x7c, 0xda, 0x87, 0x61, 0x82, 0x2b, 0xc1, 0x03, 0xd4, 0x4f, 0xa4, 0xb3, 0x3f, 0x4d, 0x07, 0xdc, 0xb9, 0x97, 0xe3, 0x6d, 0x55, 0x29, 0x8b, 0xce, 0xae, 0x12, 0x24, 0x1b, 0x3f, 0xa0, 0x7f, 0xa6, 0x3b, 0xe5, 0x57, 0x60, 0x68, 0xda, 0x38, 0x7b, 0x8d, 0x58, 0x59, 0xae, 0xab, 0x70, 0x13, 0x69, 0x84, 0x8b, 0x17, 0x6d, 0x42 }, + { 0x94, 0x0a, 0x84, 0xb6, 0xa8, 0x4d, 0x10, 0x9a, 0xab, 0x20, 0x8c, 0x02, 0x4c, 0x6c, 0xe9, 0x64, 0x76, 0x76, 0xba, 0x0a, 0xaa, 0x11, 0xf8, 0x6d, 0xbb, 0x70, 0x18, 0xf9, 0xfd, 0x22, 0x20, 0xa6, 0xd9, 0x01, 0xa9, 0x02, 0x7f, 0x9a, 0xbc, 0xf9, 0x35, 0x37, 0x27, 0x27, 0xcb, 0xf0, 0x9e, 0xbd, 0x61, 0xa2, 0xa2, 0xee, 0xb8, 0x76, 0x53, 0xe8, 0xec, 0xad, 0x1b, 0xab, 0x85, 0xdc, 0x83, 0x27 }, + { 0x20, 0x20, 0xb7, 0x82, 0x64, 0xa8, 0x2d, 0x9f, 0x41, 0x51, 0x14, 0x1a, 0xdb, 0xa8, 0xd4, 0x4b, 0xf2, 0x0c, 0x5e, 0xc0, 0x62, 0xee, 0xe9, 0xb5, 0x95, 0xa1, 0x1f, 0x9e, 0x84, 0x90, 0x1b, 0xf1, 0x48, 0xf2, 0x98, 0xe0, 0xc9, 0xf8, 0x77, 0x7d, 0xcd, 0xbc, 0x7c, 0xc4, 0x67, 0x0a, 0xac, 0x35, 0x6c, 0xc2, 0xad, 0x8c, 0xcb, 0x16, 0x29, 0xf1, 0x6f, 0x6a, 0x76, 0xbc, 0xef, 0xbe, 0xe7, 0x60 }, + { 0xd1, 0xb8, 0x97, 0xb0, 0xe0, 0x75, 0xba, 0x68, 0xab, 0x57, 0x2a, 0xdf, 0x9d, 0x9c, 0x43, 0x66, 0x63, 0xe4, 0x3e, 0xb3, 0xd8, 0xe6, 0x2d, 0x92, 0xfc, 0x49, 0xc9, 0xbe, 0x21, 0x4e, 0x6f, 0x27, 0x87, 0x3f, 0xe2, 0x15, 0xa6, 0x51, 0x70, 0xe6, 0xbe, 0xa9, 0x02, 0x40, 0x8a, 0x25, 0xb4, 0x95, 0x06, 0xf4, 0x7b, 0xab, 0xd0, 0x7c, 0xec, 0xf7, 0x11, 0x3e, 0xc1, 0x0c, 0x5d, 0xd3, 0x12, 0x52 }, + { 0xb1, 0x4d, 0x0c, 0x62, 0xab, 0xfa, 0x46, 0x9a, 0x35, 0x71, 0x77, 0xe5, 0x94, 0xc1, 0x0c, 0x19, 0x42, 0x43, 0xed, 0x20, 0x25, 0xab, 0x8a, 0xa5, 0xad, 0x2f, 0xa4, 0x1a, 0xd3, 0x18, 0xe0, 0xff, 0x48, 0xcd, 0x5e, 0x60, 0xbe, 0xc0, 0x7b, 0x13, 0x63, 0x4a, 0x71, 0x1d, 0x23, 0x26, 0xe4, 0x88, 0xa9, 0x85, 0xf3, 0x1e, 0x31, 0x15, 0x33, 0x99, 0xe7, 0x30, 0x88, 0xef, 0xc8, 0x6a, 0x5c, 0x55 }, + { 0x41, 0x69, 0xc5, 0xcc, 0x80, 0x8d, 0x26, 0x97, 0xdc, 0x2a, 0x82, 0x43, 0x0d, 0xc2, 0x3e, 0x3c, 0xd3, 0x56, 0xdc, 0x70, 0xa9, 0x45, 0x66, 0x81, 0x05, 0x02, 0xb8, 0xd6, 0x55, 0xb3, 0x9a, 0xbf, 0x9e, 0x7f, 0x90, 0x2f, 0xe7, 0x17, 0xe0, 0x38, 0x92, 0x19, 0x85, 0x9e, 0x19, 0x45, 0xdf, 0x1a, 0xf6, 0xad, 0xa4, 0x2e, 0x4c, 0xcd, 0xa5, 0x5a, 0x19, 0x7b, 0x71, 0x00, 0xa3, 0x0c, 0x30, 0xa1 }, + { 0x25, 0x8a, 0x4e, 0xdb, 0x11, 0x3d, 0x66, 0xc8, 0x39, 0xc8, 0xb1, 0xc9, 0x1f, 0x15, 0xf3, 0x5a, 0xde, 0x60, 0x9f, 0x11, 0xcd, 0x7f, 0x86, 0x81, 0xa4, 0x04, 0x5b, 0x9f, 0xef, 0x7b, 0x0b, 0x24, 0xc8, 0x2c, 0xda, 0x06, 0xa5, 0xf2, 0x06, 0x7b, 0x36, 0x88, 0x25, 0xe3, 0x91, 0x4e, 0x53, 0xd6, 0x94, 0x8e, 0xde, 0x92, 0xef, 0xd6, 0xe8, 0x38, 0x7f, 0xa2, 0xe5, 0x37, 0x23, 0x9b, 0x5b, 0xee }, + { 0x79, 0xd2, 0xd8, 0x69, 0x6d, 0x30, 0xf3, 0x0f, 0xb3, 0x46, 0x57, 0x76, 0x11, 0x71, 0xa1, 0x1e, 0x6c, 0x3f, 0x1e, 0x64, 0xcb, 0xe7, 0xbe, 0xbe, 0xe1, 0x59, 0xcb, 0x95, 0xbf, 0xaf, 0x81, 0x2b, 0x4f, 0x41, 0x1e, 0x2f, 0x26, 0xd9, 0xc4, 0x21, 0xdc, 0x2c, 0x28, 0x4a, 0x33, 0x42, 0xd8, 0x23, 0xec, 0x29, 0x38, 0x49, 0xe4, 0x2d, 0x1e, 0x46, 0xb0, 0xa4, 0xac, 0x1e, 0x3c, 0x86, 0xab, 0xaa }, + { 0x8b, 0x94, 0x36, 0x01, 0x0d, 0xc5, 0xde, 0xe9, 0x92, 0xae, 0x38, 0xae, 0xa9, 0x7f, 0x2c, 0xd6, 0x3b, 0x94, 0x6d, 0x94, 0xfe, 0xdd, 0x2e, 0xc9, 0x67, 0x1d, 0xcd, 0xe3, 0xbd, 0x4c, 0xe9, 0x56, 0x4d, 0x55, 0x5c, 0x66, 0xc1, 0x5b, 0xb2, 0xb9, 0x00, 0xdf, 0x72, 0xed, 0xb6, 0xb8, 0x91, 0xeb, 0xca, 0xdf, 0xef, 0xf6, 0x3c, 0x9e, 0xa4, 0x03, 0x6a, 0x99, 0x8b, 0xe7, 0x97, 0x39, 0x81, 0xe7 }, + { 0xc8, 0xf6, 0x8e, 0x69, 0x6e, 0xd2, 0x82, 0x42, 0xbf, 0x99, 0x7f, 0x5b, 0x3b, 0x34, 0x95, 0x95, 0x08, 0xe4, 0x2d, 0x61, 0x38, 0x10, 0xf1, 0xe2, 0xa4, 0x35, 0xc9, 0x6e, 0xd2, 0xff, 0x56, 0x0c, 0x70, 0x22, 0xf3, 0x61, 0xa9, 0x23, 0x4b, 0x98, 0x37, 0xfe, 0xee, 0x90, 0xbf, 0x47, 0x92, 0x2e, 0xe0, 0xfd, 0x5f, 0x8d, 0xdf, 0x82, 0x37, 0x18, 0xd8, 0x6d, 0x1e, 0x16, 0xc6, 0x09, 0x00, 0x71 }, + { 0xb0, 0x2d, 0x3e, 0xee, 0x48, 0x60, 0xd5, 0x86, 0x8b, 0x2c, 0x39, 0xce, 0x39, 0xbf, 0xe8, 0x10, 0x11, 0x29, 0x05, 0x64, 0xdd, 0x67, 0x8c, 0x85, 0xe8, 0x78, 0x3f, 0x29, 0x30, 0x2d, 0xfc, 0x13, 0x99, 0xba, 0x95, 0xb6, 0xb5, 0x3c, 0xd9, 0xeb, 0xbf, 0x40, 0x0c, 0xca, 0x1d, 0xb0, 0xab, 0x67, 0xe1, 0x9a, 0x32, 0x5f, 0x2d, 0x11, 0x58, 0x12, 0xd2, 0x5d, 0x00, 0x97, 0x8a, 0xd1, 0xbc, 0xa4 }, + { 0x76, 0x93, 0xea, 0x73, 0xaf, 0x3a, 0xc4, 0xda, 0xd2, 0x1c, 0xa0, 0xd8, 0xda, 0x85, 0xb3, 0x11, 0x8a, 0x7d, 0x1c, 0x60, 0x24, 0xcf, 0xaf, 0x55, 0x76, 0x99, 0x86, 0x82, 0x17, 0xbc, 0x0c, 0x2f, 0x44, 0xa1, 0x99, 0xbc, 0x6c, 0x0e, 0xdd, 0x51, 0x97, 0x98, 0xba, 0x05, 0xbd, 0x5b, 0x1b, 0x44, 0x84, 0x34, 0x6a, 0x47, 0xc2, 0xca, 0xdf, 0x6b, 0xf3, 0x0b, 0x78, 0x5c, 0xc8, 0x8b, 0x2b, 0xaf }, + { 0xa0, 0xe5, 0xc1, 0xc0, 0x03, 0x1c, 0x02, 0xe4, 0x8b, 0x7f, 0x09, 0xa5, 0xe8, 0x96, 0xee, 0x9a, 0xef, 0x2f, 0x17, 0xfc, 0x9e, 0x18, 0xe9, 0x97, 0xd7, 0xf6, 0xca, 0xc7, 0xae, 0x31, 0x64, 0x22, 0xc2, 0xb1, 0xe7, 0x79, 0x84, 0xe5, 0xf3, 0xa7, 0x3c, 0xb4, 0x5d, 0xee, 0xd5, 0xd3, 0xf8, 0x46, 0x00, 0x10, 0x5e, 0x6e, 0xe3, 0x8f, 0x2d, 0x09, 0x0c, 0x7d, 0x04, 0x42, 0xea, 0x34, 0xc4, 0x6d }, + { 0x41, 0xda, 0xa6, 0xad, 0xcf, 0xdb, 0x69, 0xf1, 0x44, 0x0c, 0x37, 0xb5, 0x96, 0x44, 0x01, 0x65, 0xc1, 0x5a, 0xda, 0x59, 0x68, 0x13, 0xe2, 0xe2, 0x2f, 0x06, 0x0f, 0xcd, 0x55, 0x1f, 0x24, 0xde, 0xe8, 0xe0, 0x4b, 0xa6, 0x89, 0x03, 0x87, 0x88, 0x6c, 0xee, 0xc4, 0xa7, 0xa0, 0xd7, 0xfc, 0x6b, 0x44, 0x50, 0x63, 0x92, 0xec, 0x38, 0x22, 0xc0, 0xd8, 0xc1, 0xac, 0xfc, 0x7d, 0x5a, 0xeb, 0xe8 }, + { 0x14, 0xd4, 0xd4, 0x0d, 0x59, 0x84, 0xd8, 0x4c, 0x5c, 0xf7, 0x52, 0x3b, 0x77, 0x98, 0xb2, 0x54, 0xe2, 0x75, 0xa3, 0xa8, 0xcc, 0x0a, 0x1b, 0xd0, 0x6e, 0xbc, 0x0b, 0xee, 0x72, 0x68, 0x56, 0xac, 0xc3, 0xcb, 0xf5, 0x16, 0xff, 0x66, 0x7c, 0xda, 0x20, 0x58, 0xad, 0x5c, 0x34, 0x12, 0x25, 0x44, 0x60, 0xa8, 0x2c, 0x92, 0x18, 0x70, 0x41, 0x36, 0x3c, 0xc7, 0x7a, 0x4d, 0xc2, 0x15, 0xe4, 0x87 }, + { 0xd0, 0xe7, 0xa1, 0xe2, 0xb9, 0xa4, 0x47, 0xfe, 0xe8, 0x3e, 0x22, 0x77, 0xe9, 0xff, 0x80, 0x10, 0xc2, 0xf3, 0x75, 0xae, 0x12, 0xfa, 0x7a, 0xaa, 0x8c, 0xa5, 0xa6, 0x31, 0x78, 0x68, 0xa2, 0x6a, 0x36, 0x7a, 0x0b, 0x69, 0xfb, 0xc1, 0xcf, 0x32, 0xa5, 0x5d, 0x34, 0xeb, 0x37, 0x06, 0x63, 0x01, 0x6f, 0x3d, 0x21, 0x10, 0x23, 0x0e, 0xba, 0x75, 0x40, 0x28, 0xa5, 0x6f, 0x54, 0xac, 0xf5, 0x7c }, + { 0xe7, 0x71, 0xaa, 0x8d, 0xb5, 0xa3, 0xe0, 0x43, 0xe8, 0x17, 0x8f, 0x39, 0xa0, 0x85, 0x7b, 0xa0, 0x4a, 0x3f, 0x18, 0xe4, 0xaa, 0x05, 0x74, 0x3c, 0xf8, 0xd2, 0x22, 0xb0, 0xb0, 0x95, 0x82, 0x53, 0x50, 0xba, 0x42, 0x2f, 0x63, 0x38, 0x2a, 0x23, 0xd9, 0x2e, 0x41, 0x49, 0x07, 0x4e, 0x81, 0x6a, 0x36, 0xc1, 0xcd, 0x28, 0x28, 0x4d, 0x14, 0x62, 0x67, 0x94, 0x0b, 0x31, 0xf8, 0x81, 0x8e, 0xa2 }, + { 0xfe, 0xb4, 0xfd, 0x6f, 0x9e, 0x87, 0xa5, 0x6b, 0xef, 0x39, 0x8b, 0x32, 0x84, 0xd2, 0xbd, 0xa5, 0xb5, 0xb0, 0xe1, 0x66, 0x58, 0x3a, 0x66, 0xb6, 0x1e, 0x53, 0x84, 0x57, 0xff, 0x05, 0x84, 0x87, 0x2c, 0x21, 0xa3, 0x29, 0x62, 0xb9, 0x92, 0x8f, 0xfa, 0xb5, 0x8d, 0xe4, 0xaf, 0x2e, 0xdd, 0x4e, 0x15, 0xd8, 0xb3, 0x55, 0x70, 0x52, 0x32, 0x07, 0xff, 0x4e, 0x2a, 0x5a, 0xa7, 0x75, 0x4c, 0xaa }, + { 0x46, 0x2f, 0x17, 0xbf, 0x00, 0x5f, 0xb1, 0xc1, 0xb9, 0xe6, 0x71, 0x77, 0x9f, 0x66, 0x52, 0x09, 0xec, 0x28, 0x73, 0xe3, 0xe4, 0x11, 0xf9, 0x8d, 0xab, 0xf2, 0x40, 0xa1, 0xd5, 0xec, 0x3f, 0x95, 0xce, 0x67, 0x96, 0xb6, 0xfc, 0x23, 0xfe, 0x17, 0x19, 0x03, 0xb5, 0x02, 0x02, 0x34, 0x67, 0xde, 0xc7, 0x27, 0x3f, 0xf7, 0x48, 0x79, 0xb9, 0x29, 0x67, 0xa2, 0xa4, 0x3a, 0x5a, 0x18, 0x3d, 0x33 }, + { 0xd3, 0x33, 0x81, 0x93, 0xb6, 0x45, 0x53, 0xdb, 0xd3, 0x8d, 0x14, 0x4b, 0xea, 0x71, 0xc5, 0x91, 0x5b, 0xb1, 0x10, 0xe2, 0xd8, 0x81, 0x80, 0xdb, 0xc5, 0xdb, 0x36, 0x4f, 0xd6, 0x17, 0x1d, 0xf3, 0x17, 0xfc, 0x72, 0x68, 0x83, 0x1b, 0x5a, 0xef, 0x75, 0xe4, 0x34, 0x2b, 0x2f, 0xad, 0x87, 0x97, 0xba, 0x39, 0xed, 0xdc, 0xef, 0x80, 0xe6, 0xec, 0x08, 0x15, 0x93, 0x50, 0xb1, 0xad, 0x69, 0x6d }, + { 0xe1, 0x59, 0x0d, 0x58, 0x5a, 0x3d, 0x39, 0xf7, 0xcb, 0x59, 0x9a, 0xbd, 0x47, 0x90, 0x70, 0x96, 0x64, 0x09, 0xa6, 0x84, 0x6d, 0x43, 0x77, 0xac, 0xf4, 0x47, 0x1d, 0x06, 0x5d, 0x5d, 0xb9, 0x41, 0x29, 0xcc, 0x9b, 0xe9, 0x25, 0x73, 0xb0, 0x5e, 0xd2, 0x26, 0xbe, 0x1e, 0x9b, 0x7c, 0xb0, 0xca, 0xbe, 0x87, 0x91, 0x85, 0x89, 0xf8, 0x0d, 0xad, 0xd4, 0xef, 0x5e, 0xf2, 0x5a, 0x93, 0xd2, 0x8e }, + { 0xf8, 0xf3, 0x72, 0x6a, 0xc5, 0xa2, 0x6c, 0xc8, 0x01, 0x32, 0x49, 0x3a, 0x6f, 0xed, 0xcb, 0x0e, 0x60, 0x76, 0x0c, 0x09, 0xcf, 0xc8, 0x4c, 0xad, 0x17, 0x81, 0x75, 0x98, 0x68, 0x19, 0x66, 0x5e, 0x76, 0x84, 0x2d, 0x7b, 0x9f, 0xed, 0xf7, 0x6d, 0xdd, 0xeb, 0xf5, 0xd3, 0xf5, 0x6f, 0xaa, 0xad, 0x44, 0x77, 0x58, 0x7a, 0xf2, 0x16, 0x06, 0xd3, 0x96, 0xae, 0x57, 0x0d, 0x8e, 0x71, 0x9a, 0xf2 }, + { 0x30, 0x18, 0x60, 0x55, 0xc0, 0x79, 0x49, 0x94, 0x81, 0x83, 0xc8, 0x50, 0xe9, 0xa7, 0x56, 0xcc, 0x09, 0x93, 0x7e, 0x24, 0x7d, 0x9d, 0x92, 0x8e, 0x86, 0x9e, 0x20, 0xba, 0xfc, 0x3c, 0xd9, 0x72, 0x17, 0x19, 0xd3, 0x4e, 0x04, 0xa0, 0x89, 0x9b, 0x92, 0xc7, 0x36, 0x08, 0x45, 0x50, 0x18, 0x68, 0x86, 0xef, 0xba, 0x2e, 0x79, 0x0d, 0x8b, 0xe6, 0xeb, 0xf0, 0x40, 0xb2, 0x09, 0xc4, 0x39, 0xa4 }, + { 0xf3, 0xc4, 0x27, 0x6c, 0xb8, 0x63, 0x63, 0x77, 0x12, 0xc2, 0x41, 0xc4, 0x44, 0xc5, 0xcc, 0x1e, 0x35, 0x54, 0xe0, 0xfd, 0xdb, 0x17, 0x4d, 0x03, 0x58, 0x19, 0xdd, 0x83, 0xeb, 0x70, 0x0b, 0x4c, 0xe8, 0x8d, 0xf3, 0xab, 0x38, 0x41, 0xba, 0x02, 0x08, 0x5e, 0x1a, 0x99, 0xb4, 0xe1, 0x73, 0x10, 0xc5, 0x34, 0x10, 0x75, 0xc0, 0x45, 0x8b, 0xa3, 0x76, 0xc9, 0x5a, 0x68, 0x18, 0xfb, 0xb3, 0xe2 }, + { 0x0a, 0xa0, 0x07, 0xc4, 0xdd, 0x9d, 0x58, 0x32, 0x39, 0x30, 0x40, 0xa1, 0x58, 0x3c, 0x93, 0x0b, 0xca, 0x7d, 0xc5, 0xe7, 0x7e, 0xa5, 0x3a, 0xdd, 0x7e, 0x2b, 0x3f, 0x7c, 0x8e, 0x23, 0x13, 0x68, 0x04, 0x35, 0x20, 0xd4, 0xa3, 0xef, 0x53, 0xc9, 0x69, 0xb6, 0xbb, 0xfd, 0x02, 0x59, 0x46, 0xf6, 0x32, 0xbd, 0x7f, 0x76, 0x5d, 0x53, 0xc2, 0x10, 0x03, 0xb8, 0xf9, 0x83, 0xf7, 0x5e, 0x2a, 0x6a }, + { 0x08, 0xe9, 0x46, 0x47, 0x20, 0x53, 0x3b, 0x23, 0xa0, 0x4e, 0xc2, 0x4f, 0x7a, 0xe8, 0xc1, 0x03, 0x14, 0x5f, 0x76, 0x53, 0x87, 0xd7, 0x38, 0x77, 0x7d, 0x3d, 0x34, 0x34, 0x77, 0xfd, 0x1c, 0x58, 0xdb, 0x05, 0x21, 0x42, 0xca, 0xb7, 0x54, 0xea, 0x67, 0x43, 0x78, 0xe1, 0x87, 0x66, 0xc5, 0x35, 0x42, 0xf7, 0x19, 0x70, 0x17, 0x1c, 0xc4, 0xf8, 0x16, 0x94, 0x24, 0x6b, 0x71, 0x7d, 0x75, 0x64 }, + { 0xd3, 0x7f, 0xf7, 0xad, 0x29, 0x79, 0x93, 0xe7, 0xec, 0x21, 0xe0, 0xf1, 0xb4, 0xb5, 0xae, 0x71, 0x9c, 0xdc, 0x83, 0xc5, 0xdb, 0x68, 0x75, 0x27, 0xf2, 0x75, 0x16, 0xcb, 0xff, 0xa8, 0x22, 0x88, 0x8a, 0x68, 0x10, 0xee, 0x5c, 0x1c, 0xa7, 0xbf, 0xe3, 0x32, 0x11, 0x19, 0xbe, 0x1a, 0xb7, 0xbf, 0xa0, 0xa5, 0x02, 0x67, 0x1c, 0x83, 0x29, 0x49, 0x4d, 0xf7, 0xad, 0x6f, 0x52, 0x2d, 0x44, 0x0f }, + { 0xdd, 0x90, 0x42, 0xf6, 0xe4, 0x64, 0xdc, 0xf8, 0x6b, 0x12, 0x62, 0xf6, 0xac, 0xcf, 0xaf, 0xbd, 0x8c, 0xfd, 0x90, 0x2e, 0xd3, 0xed, 0x89, 0xab, 0xf7, 0x8f, 0xfa, 0x48, 0x2d, 0xbd, 0xee, 0xb6, 0x96, 0x98, 0x42, 0x39, 0x4c, 0x9a, 0x11, 0x68, 0xae, 0x3d, 0x48, 0x1a, 0x01, 0x78, 0x42, 0xf6, 0x60, 0x00, 0x2d, 0x42, 0x44, 0x7c, 0x6b, 0x22, 0xf7, 0xb7, 0x2f, 0x21, 0xaa, 0xe0, 0x21, 0xc9 }, + { 0xbd, 0x96, 0x5b, 0xf3, 0x1e, 0x87, 0xd7, 0x03, 0x27, 0x53, 0x6f, 0x2a, 0x34, 0x1c, 0xeb, 0xc4, 0x76, 0x8e, 0xca, 0x27, 0x5f, 0xa0, 0x5e, 0xf9, 0x8f, 0x7f, 0x1b, 0x71, 0xa0, 0x35, 0x12, 0x98, 0xde, 0x00, 0x6f, 0xba, 0x73, 0xfe, 0x67, 0x33, 0xed, 0x01, 0xd7, 0x58, 0x01, 0xb4, 0xa9, 0x28, 0xe5, 0x42, 0x31, 0xb3, 0x8e, 0x38, 0xc5, 0x62, 0xb2, 0xe3, 0x3e, 0xa1, 0x28, 0x49, 0x92, 0xfa }, + { 0x65, 0x67, 0x6d, 0x80, 0x06, 0x17, 0x97, 0x2f, 0xbd, 0x87, 0xe4, 0xb9, 0x51, 0x4e, 0x1c, 0x67, 0x40, 0x2b, 0x7a, 0x33, 0x10, 0x96, 0xd3, 0xbf, 0xac, 0x22, 0xf1, 0xab, 0xb9, 0x53, 0x74, 0xab, 0xc9, 0x42, 0xf1, 0x6e, 0x9a, 0xb0, 0xea, 0xd3, 0x3b, 0x87, 0xc9, 0x19, 0x68, 0xa6, 0xe5, 0x09, 0xe1, 0x19, 0xff, 0x07, 0x78, 0x7b, 0x3e, 0xf4, 0x83, 0xe1, 0xdc, 0xdc, 0xcf, 0x6e, 0x30, 0x22 }, + { 0x93, 0x9f, 0xa1, 0x89, 0x69, 0x9c, 0x5d, 0x2c, 0x81, 0xdd, 0xd1, 0xff, 0xc1, 0xfa, 0x20, 0x7c, 0x97, 0x0b, 0x6a, 0x36, 0x85, 0xbb, 0x29, 0xce, 0x1d, 0x3e, 0x99, 0xd4, 0x2f, 0x2f, 0x74, 0x42, 0xda, 0x53, 0xe9, 0x5a, 0x72, 0x90, 0x73, 0x14, 0xf4, 0x58, 0x83, 0x99, 0xa3, 0xff, 0x5b, 0x0a, 0x92, 0xbe, 0xb3, 0xf6, 0xbe, 0x26, 0x94, 0xf9, 0xf8, 0x6e, 0xcf, 0x29, 0x52, 0xd5, 0xb4, 0x1c }, + { 0xc5, 0x16, 0x54, 0x17, 0x01, 0x86, 0x3f, 0x91, 0x00, 0x5f, 0x31, 0x41, 0x08, 0xce, 0xec, 0xe3, 0xc6, 0x43, 0xe0, 0x4f, 0xc8, 0xc4, 0x2f, 0xd2, 0xff, 0x55, 0x62, 0x20, 0xe6, 0x16, 0xaa, 0xa6, 0xa4, 0x8a, 0xeb, 0x97, 0xa8, 0x4b, 0xad, 0x74, 0x78, 0x2e, 0x8d, 0xff, 0x96, 0xa1, 0xa2, 0xfa, 0x94, 0x93, 0x39, 0xd7, 0x22, 0xed, 0xca, 0xa3, 0x2b, 0x57, 0x06, 0x70, 0x41, 0xdf, 0x88, 0xcc }, + { 0x98, 0x7f, 0xd6, 0xe0, 0xd6, 0x85, 0x7c, 0x55, 0x3e, 0xae, 0xbb, 0x3d, 0x34, 0x97, 0x0a, 0x2c, 0x2f, 0x6e, 0x89, 0xa3, 0x54, 0x8f, 0x49, 0x25, 0x21, 0x72, 0x2b, 0x80, 0xa1, 0xc2, 0x1a, 0x15, 0x38, 0x92, 0x34, 0x6d, 0x2c, 0xba, 0x64, 0x44, 0x21, 0x2d, 0x56, 0xda, 0x9a, 0x26, 0xe3, 0x24, 0xdc, 0xcb, 0xc0, 0xdc, 0xde, 0x85, 0xd4, 0xd2, 0xee, 0x43, 0x99, 0xee, 0xc5, 0xa6, 0x4e, 0x8f }, + { 0xae, 0x56, 0xde, 0xb1, 0xc2, 0x32, 0x8d, 0x9c, 0x40, 0x17, 0x70, 0x6b, 0xce, 0x6e, 0x99, 0xd4, 0x13, 0x49, 0x05, 0x3b, 0xa9, 0xd3, 0x36, 0xd6, 0x77, 0xc4, 0xc2, 0x7d, 0x9f, 0xd5, 0x0a, 0xe6, 0xae, 0xe1, 0x7e, 0x85, 0x31, 0x54, 0xe1, 0xf4, 0xfe, 0x76, 0x72, 0x34, 0x6d, 0xa2, 0xea, 0xa3, 0x1e, 0xea, 0x53, 0xfc, 0xf2, 0x4a, 0x22, 0x80, 0x4f, 0x11, 0xd0, 0x3d, 0xa6, 0xab, 0xfc, 0x2b }, + { 0x49, 0xd6, 0xa6, 0x08, 0xc9, 0xbd, 0xe4, 0x49, 0x18, 0x70, 0x49, 0x85, 0x72, 0xac, 0x31, 0xaa, 0xc3, 0xfa, 0x40, 0x93, 0x8b, 0x38, 0xa7, 0x81, 0x8f, 0x72, 0x38, 0x3e, 0xb0, 0x40, 0xad, 0x39, 0x53, 0x2b, 0xc0, 0x65, 0x71, 0xe1, 0x3d, 0x76, 0x7e, 0x69, 0x45, 0xab, 0x77, 0xc0, 0xbd, 0xc3, 0xb0, 0x28, 0x42, 0x53, 0x34, 0x3f, 0x9f, 0x6c, 0x12, 0x44, 0xeb, 0xf2, 0xff, 0x0d, 0xf8, 0x66 }, + { 0xda, 0x58, 0x2a, 0xd8, 0xc5, 0x37, 0x0b, 0x44, 0x69, 0xaf, 0x86, 0x2a, 0xa6, 0x46, 0x7a, 0x22, 0x93, 0xb2, 0xb2, 0x8b, 0xd8, 0x0a, 0xe0, 0xe9, 0x1f, 0x42, 0x5a, 0xd3, 0xd4, 0x72, 0x49, 0xfd, 0xf9, 0x88, 0x25, 0xcc, 0x86, 0xf1, 0x40, 0x28, 0xc3, 0x30, 0x8c, 0x98, 0x04, 0xc7, 0x8b, 0xfe, 0xee, 0xee, 0x46, 0x14, 0x44, 0xce, 0x24, 0x36, 0x87, 0xe1, 0xa5, 0x05, 0x22, 0x45, 0x6a, 0x1d }, + { 0xd5, 0x26, 0x6a, 0xa3, 0x33, 0x11, 0x94, 0xae, 0xf8, 0x52, 0xee, 0xd8, 0x6d, 0x7b, 0x5b, 0x26, 0x33, 0xa0, 0xaf, 0x1c, 0x73, 0x59, 0x06, 0xf2, 0xe1, 0x32, 0x79, 0xf1, 0x49, 0x31, 0xa9, 0xfc, 0x3b, 0x0e, 0xac, 0x5c, 0xe9, 0x24, 0x52, 0x73, 0xbd, 0x1a, 0xa9, 0x29, 0x05, 0xab, 0xe1, 0x62, 0x78, 0xef, 0x7e, 0xfd, 0x47, 0x69, 0x47, 0x89, 0xa7, 0x28, 0x3b, 0x77, 0xda, 0x3c, 0x70, 0xf8 }, + { 0x29, 0x62, 0x73, 0x4c, 0x28, 0x25, 0x21, 0x86, 0xa9, 0xa1, 0x11, 0x1c, 0x73, 0x2a, 0xd4, 0xde, 0x45, 0x06, 0xd4, 0xb4, 0x48, 0x09, 0x16, 0x30, 0x3e, 0xb7, 0x99, 0x1d, 0x65, 0x9c, 0xcd, 0xa0, 0x7a, 0x99, 0x11, 0x91, 0x4b, 0xc7, 0x5c, 0x41, 0x8a, 0xb7, 0xa4, 0x54, 0x17, 0x57, 0xad, 0x05, 0x47, 0x96, 0xe2, 0x67, 0x97, 0xfe, 0xaf, 0x36, 0xe9, 0xf6, 0xad, 0x43, 0xf1, 0x4b, 0x35, 0xa4 }, + { 0xe8, 0xb7, 0x9e, 0xc5, 0xd0, 0x6e, 0x11, 0x1b, 0xdf, 0xaf, 0xd7, 0x1e, 0x9f, 0x57, 0x60, 0xf0, 0x0a, 0xc8, 0xac, 0x5d, 0x8b, 0xf7, 0x68, 0xf9, 0xff, 0x6f, 0x08, 0xb8, 0xf0, 0x26, 0x09, 0x6b, 0x1c, 0xc3, 0xa4, 0xc9, 0x73, 0x33, 0x30, 0x19, 0xf1, 0xe3, 0x55, 0x3e, 0x77, 0xda, 0x3f, 0x98, 0xcb, 0x9f, 0x54, 0x2e, 0x0a, 0x90, 0xe5, 0xf8, 0xa9, 0x40, 0xcc, 0x58, 0xe5, 0x98, 0x44, 0xb3 }, + { 0xdf, 0xb3, 0x20, 0xc4, 0x4f, 0x9d, 0x41, 0xd1, 0xef, 0xdc, 0xc0, 0x15, 0xf0, 0x8d, 0xd5, 0x53, 0x9e, 0x52, 0x6e, 0x39, 0xc8, 0x7d, 0x50, 0x9a, 0xe6, 0x81, 0x2a, 0x96, 0x9e, 0x54, 0x31, 0xbf, 0x4f, 0xa7, 0xd9, 0x1f, 0xfd, 0x03, 0xb9, 0x81, 0xe0, 0xd5, 0x44, 0xcf, 0x72, 0xd7, 0xb1, 0xc0, 0x37, 0x4f, 0x88, 0x01, 0x48, 0x2e, 0x6d, 0xea, 0x2e, 0xf9, 0x03, 0x87, 0x7e, 0xba, 0x67, 0x5e }, + { 0xd8, 0x86, 0x75, 0x11, 0x8f, 0xdb, 0x55, 0xa5, 0xfb, 0x36, 0x5a, 0xc2, 0xaf, 0x1d, 0x21, 0x7b, 0xf5, 0x26, 0xce, 0x1e, 0xe9, 0xc9, 0x4b, 0x2f, 0x00, 0x90, 0xb2, 0xc5, 0x8a, 0x06, 0xca, 0x58, 0x18, 0x7d, 0x7f, 0xe5, 0x7c, 0x7b, 0xed, 0x9d, 0x26, 0xfc, 0xa0, 0x67, 0xb4, 0x11, 0x0e, 0xef, 0xcd, 0x9a, 0x0a, 0x34, 0x5d, 0xe8, 0x72, 0xab, 0xe2, 0x0d, 0xe3, 0x68, 0x00, 0x1b, 0x07, 0x45 }, + { 0xb8, 0x93, 0xf2, 0xfc, 0x41, 0xf7, 0xb0, 0xdd, 0x6e, 0x2f, 0x6a, 0xa2, 0xe0, 0x37, 0x0c, 0x0c, 0xff, 0x7d, 0xf0, 0x9e, 0x3a, 0xcf, 0xcc, 0x0e, 0x92, 0x0b, 0x6e, 0x6f, 0xad, 0x0e, 0xf7, 0x47, 0xc4, 0x06, 0x68, 0x41, 0x7d, 0x34, 0x2b, 0x80, 0xd2, 0x35, 0x1e, 0x8c, 0x17, 0x5f, 0x20, 0x89, 0x7a, 0x06, 0x2e, 0x97, 0x65, 0xe6, 0xc6, 0x7b, 0x53, 0x9b, 0x6b, 0xa8, 0xb9, 0x17, 0x05, 0x45 }, + { 0x6c, 0x67, 0xec, 0x56, 0x97, 0xac, 0xcd, 0x23, 0x5c, 0x59, 0xb4, 0x86, 0xd7, 0xb7, 0x0b, 0xae, 0xed, 0xcb, 0xd4, 0xaa, 0x64, 0xeb, 0xd4, 0xee, 0xf3, 0xc7, 0xea, 0xc1, 0x89, 0x56, 0x1a, 0x72, 0x62, 0x50, 0xae, 0xc4, 0xd4, 0x8c, 0xad, 0xca, 0xfb, 0xbe, 0x2c, 0xe3, 0xc1, 0x6c, 0xe2, 0xd6, 0x91, 0xa8, 0xcc, 0xe0, 0x6e, 0x88, 0x79, 0x55, 0x6d, 0x44, 0x83, 0xed, 0x71, 0x65, 0xc0, 0x63 }, + { 0xf1, 0xaa, 0x2b, 0x04, 0x4f, 0x8f, 0x0c, 0x63, 0x8a, 0x3f, 0x36, 0x2e, 0x67, 0x7b, 0x5d, 0x89, 0x1d, 0x6f, 0xd2, 0xab, 0x07, 0x65, 0xf6, 0xee, 0x1e, 0x49, 0x87, 0xde, 0x05, 0x7e, 0xad, 0x35, 0x78, 0x83, 0xd9, 0xb4, 0x05, 0xb9, 0xd6, 0x09, 0xee, 0xa1, 0xb8, 0x69, 0xd9, 0x7f, 0xb1, 0x6d, 0x9b, 0x51, 0x01, 0x7c, 0x55, 0x3f, 0x3b, 0x93, 0xc0, 0xa1, 0xe0, 0xf1, 0x29, 0x6f, 0xed, 0xcd }, + { 0xcb, 0xaa, 0x25, 0x95, 0x72, 0xd4, 0xae, 0xbf, 0xc1, 0x91, 0x7a, 0xcd, 0xdc, 0x58, 0x2b, 0x9f, 0x8d, 0xfa, 0xa9, 0x28, 0xa1, 0x98, 0xca, 0x7a, 0xcd, 0x0f, 0x2a, 0xa7, 0x6a, 0x13, 0x4a, 0x90, 0x25, 0x2e, 0x62, 0x98, 0xa6, 0x5b, 0x08, 0x18, 0x6a, 0x35, 0x0d, 0x5b, 0x76, 0x26, 0x69, 0x9f, 0x8c, 0xb7, 0x21, 0xa3, 0xea, 0x59, 0x21, 0xb7, 0x53, 0xae, 0x3a, 0x2d, 0xce, 0x24, 0xba, 0x3a }, + { 0xfa, 0x15, 0x49, 0xc9, 0x79, 0x6c, 0xd4, 0xd3, 0x03, 0xdc, 0xf4, 0x52, 0xc1, 0xfb, 0xd5, 0x74, 0x4f, 0xd9, 0xb9, 0xb4, 0x70, 0x03, 0xd9, 0x20, 0xb9, 0x2d, 0xe3, 0x48, 0x39, 0xd0, 0x7e, 0xf2, 0xa2, 0x9d, 0xed, 0x68, 0xf6, 0xfc, 0x9e, 0x6c, 0x45, 0xe0, 0x71, 0xa2, 0xe4, 0x8b, 0xd5, 0x0c, 0x50, 0x84, 0xe9, 0x6b, 0x65, 0x7d, 0xd0, 0x40, 0x40, 0x45, 0xa1, 0xdd, 0xef, 0xe2, 0x82, 0xed }, + { 0x5c, 0xf2, 0xac, 0x89, 0x7a, 0xb4, 0x44, 0xdc, 0xb5, 0xc8, 0xd8, 0x7c, 0x49, 0x5d, 0xbd, 0xb3, 0x4e, 0x18, 0x38, 0xb6, 0xb6, 0x29, 0x42, 0x7c, 0xaa, 0x51, 0x70, 0x2a, 0xd0, 0xf9, 0x68, 0x85, 0x25, 0xf1, 0x3b, 0xec, 0x50, 0x3a, 0x3c, 0x3a, 0x2c, 0x80, 0xa6, 0x5e, 0x0b, 0x57, 0x15, 0xe8, 0xaf, 0xab, 0x00, 0xff, 0xa5, 0x6e, 0xc4, 0x55, 0xa4, 0x9a, 0x1a, 0xd3, 0x0a, 0xa2, 0x4f, 0xcd }, + { 0x9a, 0xaf, 0x80, 0x20, 0x7b, 0xac, 0xe1, 0x7b, 0xb7, 0xab, 0x14, 0x57, 0x57, 0xd5, 0x69, 0x6b, 0xde, 0x32, 0x40, 0x6e, 0xf2, 0x2b, 0x44, 0x29, 0x2e, 0xf6, 0x5d, 0x45, 0x19, 0xc3, 0xbb, 0x2a, 0xd4, 0x1a, 0x59, 0xb6, 0x2c, 0xc3, 0xe9, 0x4b, 0x6f, 0xa9, 0x6d, 0x32, 0xa7, 0xfa, 0xad, 0xae, 0x28, 0xaf, 0x7d, 0x35, 0x09, 0x72, 0x19, 0xaa, 0x3f, 0xd8, 0xcd, 0xa3, 0x1e, 0x40, 0xc2, 0x75 }, + { 0xaf, 0x88, 0xb1, 0x63, 0x40, 0x2c, 0x86, 0x74, 0x5c, 0xb6, 0x50, 0xc2, 0x98, 0x8f, 0xb9, 0x52, 0x11, 0xb9, 0x4b, 0x03, 0xef, 0x29, 0x0e, 0xed, 0x96, 0x62, 0x03, 0x42, 0x41, 0xfd, 0x51, 0xcf, 0x39, 0x8f, 0x80, 0x73, 0xe3, 0x69, 0x35, 0x4c, 0x43, 0xea, 0xe1, 0x05, 0x2f, 0x9b, 0x63, 0xb0, 0x81, 0x91, 0xca, 0xa1, 0x38, 0xaa, 0x54, 0xfe, 0xa8, 0x89, 0xcc, 0x70, 0x24, 0x23, 0x68, 0x97 }, + { 0x48, 0xfa, 0x7d, 0x64, 0xe1, 0xce, 0xee, 0x27, 0xb9, 0x86, 0x4d, 0xb5, 0xad, 0xa4, 0xb5, 0x3d, 0x00, 0xc9, 0xbc, 0x76, 0x26, 0x55, 0x58, 0x13, 0xd3, 0xcd, 0x67, 0x30, 0xab, 0x3c, 0xc0, 0x6f, 0xf3, 0x42, 0xd7, 0x27, 0x90, 0x5e, 0x33, 0x17, 0x1b, 0xde, 0x6e, 0x84, 0x76, 0xe7, 0x7f, 0xb1, 0x72, 0x08, 0x61, 0xe9, 0x4b, 0x73, 0xa2, 0xc5, 0x38, 0xd2, 0x54, 0x74, 0x62, 0x85, 0xf4, 0x30 }, + { 0x0e, 0x6f, 0xd9, 0x7a, 0x85, 0xe9, 0x04, 0xf8, 0x7b, 0xfe, 0x85, 0xbb, 0xeb, 0x34, 0xf6, 0x9e, 0x1f, 0x18, 0x10, 0x5c, 0xf4, 0xed, 0x4f, 0x87, 0xae, 0xc3, 0x6c, 0x6e, 0x8b, 0x5f, 0x68, 0xbd, 0x2a, 0x6f, 0x3d, 0xc8, 0xa9, 0xec, 0xb2, 0xb6, 0x1d, 0xb4, 0xee, 0xdb, 0x6b, 0x2e, 0xa1, 0x0b, 0xf9, 0xcb, 0x02, 0x51, 0xfb, 0x0f, 0x8b, 0x34, 0x4a, 0xbf, 0x7f, 0x36, 0x6b, 0x6d, 0xe5, 0xab }, + { 0x06, 0x62, 0x2d, 0xa5, 0x78, 0x71, 0x76, 0x28, 0x7f, 0xdc, 0x8f, 0xed, 0x44, 0x0b, 0xad, 0x18, 0x7d, 0x83, 0x00, 0x99, 0xc9, 0x4e, 0x6d, 0x04, 0xc8, 0xe9, 0xc9, 0x54, 0xcd, 0xa7, 0x0c, 0x8b, 0xb9, 0xe1, 0xfc, 0x4a, 0x6d, 0x0b, 0xaa, 0x83, 0x1b, 0x9b, 0x78, 0xef, 0x66, 0x48, 0x68, 0x1a, 0x48, 0x67, 0xa1, 0x1d, 0xa9, 0x3e, 0xe3, 0x6e, 0x5e, 0x6a, 0x37, 0xd8, 0x7f, 0xc6, 0x3f, 0x6f }, + { 0x1d, 0xa6, 0x77, 0x2b, 0x58, 0xfa, 0xbf, 0x9c, 0x61, 0xf6, 0x8d, 0x41, 0x2c, 0x82, 0xf1, 0x82, 0xc0, 0x23, 0x6d, 0x7d, 0x57, 0x5e, 0xf0, 0xb5, 0x8d, 0xd2, 0x24, 0x58, 0xd6, 0x43, 0xcd, 0x1d, 0xfc, 0x93, 0xb0, 0x38, 0x71, 0xc3, 0x16, 0xd8, 0x43, 0x0d, 0x31, 0x29, 0x95, 0xd4, 0x19, 0x7f, 0x08, 0x74, 0xc9, 0x91, 0x72, 0xba, 0x00, 0x4a, 0x01, 0xee, 0x29, 0x5a, 0xba, 0xc2, 0x4e, 0x46 }, + { 0x3c, 0xd2, 0xd9, 0x32, 0x0b, 0x7b, 0x1d, 0x5f, 0xb9, 0xaa, 0xb9, 0x51, 0xa7, 0x60, 0x23, 0xfa, 0x66, 0x7b, 0xe1, 0x4a, 0x91, 0x24, 0xe3, 0x94, 0x51, 0x39, 0x18, 0xa3, 0xf4, 0x40, 0x96, 0xae, 0x49, 0x04, 0xba, 0x0f, 0xfc, 0x15, 0x0b, 0x63, 0xbc, 0x7a, 0xb1, 0xee, 0xb9, 0xa6, 0xe2, 0x57, 0xe5, 0xc8, 0xf0, 0x00, 0xa7, 0x03, 0x94, 0xa5, 0xaf, 0xd8, 0x42, 0x71, 0x5d, 0xe1, 0x5f, 0x29 }, + { 0x04, 0xcd, 0xc1, 0x4f, 0x74, 0x34, 0xe0, 0xb4, 0xbe, 0x70, 0xcb, 0x41, 0xdb, 0x4c, 0x77, 0x9a, 0x88, 0xea, 0xef, 0x6a, 0xcc, 0xeb, 0xcb, 0x41, 0xf2, 0xd4, 0x2f, 0xff, 0xe7, 0xf3, 0x2a, 0x8e, 0x28, 0x1b, 0x5c, 0x10, 0x3a, 0x27, 0x02, 0x1d, 0x0d, 0x08, 0x36, 0x22, 0x50, 0x75, 0x3c, 0xdf, 0x70, 0x29, 0x21, 0x95, 0xa5, 0x3a, 0x48, 0x72, 0x8c, 0xeb, 0x58, 0x44, 0xc2, 0xd9, 0x8b, 0xab }, + { 0x90, 0x71, 0xb7, 0xa8, 0xa0, 0x75, 0xd0, 0x09, 0x5b, 0x8f, 0xb3, 0xae, 0x51, 0x13, 0x78, 0x57, 0x35, 0xab, 0x98, 0xe2, 0xb5, 0x2f, 0xaf, 0x91, 0xd5, 0xb8, 0x9e, 0x44, 0xaa, 0xc5, 0xb5, 0xd4, 0xeb, 0xbf, 0x91, 0x22, 0x3b, 0x0f, 0xf4, 0xc7, 0x19, 0x05, 0xda, 0x55, 0x34, 0x2e, 0x64, 0x65, 0x5d, 0x6e, 0xf8, 0xc8, 0x9a, 0x47, 0x68, 0xc3, 0xf9, 0x3a, 0x6d, 0xc0, 0x36, 0x6b, 0x5b, 0xc8 }, + { 0xeb, 0xb3, 0x02, 0x40, 0xdd, 0x96, 0xc7, 0xbc, 0x8d, 0x0a, 0xbe, 0x49, 0xaa, 0x4e, 0xdc, 0xbb, 0x4a, 0xfd, 0xc5, 0x1f, 0xf9, 0xaa, 0xf7, 0x20, 0xd3, 0xf9, 0xe7, 0xfb, 0xb0, 0xf9, 0xc6, 0xd6, 0x57, 0x13, 0x50, 0x50, 0x17, 0x69, 0xfc, 0x4e, 0xbd, 0x0b, 0x21, 0x41, 0x24, 0x7f, 0xf4, 0x00, 0xd4, 0xfd, 0x4b, 0xe4, 0x14, 0xed, 0xf3, 0x77, 0x57, 0xbb, 0x90, 0xa3, 0x2a, 0xc5, 0xc6, 0x5a }, + { 0x85, 0x32, 0xc5, 0x8b, 0xf3, 0xc8, 0x01, 0x5d, 0x9d, 0x1c, 0xbe, 0x00, 0xee, 0xf1, 0xf5, 0x08, 0x2f, 0x8f, 0x36, 0x32, 0xfb, 0xe9, 0xf1, 0xed, 0x4f, 0x9d, 0xfb, 0x1f, 0xa7, 0x9e, 0x82, 0x83, 0x06, 0x6d, 0x77, 0xc4, 0x4c, 0x4a, 0xf9, 0x43, 0xd7, 0x6b, 0x30, 0x03, 0x64, 0xae, 0xcb, 0xd0, 0x64, 0x8c, 0x8a, 0x89, 0x39, 0xbd, 0x20, 0x41, 0x23, 0xf4, 0xb5, 0x62, 0x60, 0x42, 0x2d, 0xec }, + { 0xfe, 0x98, 0x46, 0xd6, 0x4f, 0x7c, 0x77, 0x08, 0x69, 0x6f, 0x84, 0x0e, 0x2d, 0x76, 0xcb, 0x44, 0x08, 0xb6, 0x59, 0x5c, 0x2f, 0x81, 0xec, 0x6a, 0x28, 0xa7, 0xf2, 0xf2, 0x0c, 0xb8, 0x8c, 0xfe, 0x6a, 0xc0, 0xb9, 0xe9, 0xb8, 0x24, 0x4f, 0x08, 0xbd, 0x70, 0x95, 0xc3, 0x50, 0xc1, 0xd0, 0x84, 0x2f, 0x64, 0xfb, 0x01, 0xbb, 0x7f, 0x53, 0x2d, 0xfc, 0xd4, 0x73, 0x71, 0xb0, 0xae, 0xeb, 0x79 }, + { 0x28, 0xf1, 0x7e, 0xa6, 0xfb, 0x6c, 0x42, 0x09, 0x2d, 0xc2, 0x64, 0x25, 0x7e, 0x29, 0x74, 0x63, 0x21, 0xfb, 0x5b, 0xda, 0xea, 0x98, 0x73, 0xc2, 0xa7, 0xfa, 0x9d, 0x8f, 0x53, 0x81, 0x8e, 0x89, 0x9e, 0x16, 0x1b, 0xc7, 0x7d, 0xfe, 0x80, 0x90, 0xaf, 0xd8, 0x2b, 0xf2, 0x26, 0x6c, 0x5c, 0x1b, 0xc9, 0x30, 0xa8, 0xd1, 0x54, 0x76, 0x24, 0x43, 0x9e, 0x66, 0x2e, 0xf6, 0x95, 0xf2, 0x6f, 0x24 }, + { 0xec, 0x6b, 0x7d, 0x7f, 0x03, 0x0d, 0x48, 0x50, 0xac, 0xae, 0x3c, 0xb6, 0x15, 0xc2, 0x1d, 0xd2, 0x52, 0x06, 0xd6, 0x3e, 0x84, 0xd1, 0xdb, 0x8d, 0x95, 0x73, 0x70, 0x73, 0x7b, 0xa0, 0xe9, 0x84, 0x67, 0xea, 0x0c, 0xe2, 0x74, 0xc6, 0x61, 0x99, 0x90, 0x1e, 0xae, 0xc1, 0x8a, 0x08, 0x52, 0x57, 0x15, 0xf5, 0x3b, 0xfd, 0xb0, 0xaa, 0xcb, 0x61, 0x3d, 0x34, 0x2e, 0xbd, 0xce, 0xed, 0xdc, 0x3b }, + { 0xb4, 0x03, 0xd3, 0x69, 0x1c, 0x03, 0xb0, 0xd3, 0x41, 0x8d, 0xf3, 0x27, 0xd5, 0x86, 0x0d, 0x34, 0xbb, 0xfc, 0xc4, 0x51, 0x9b, 0xfb, 0xce, 0x36, 0xbf, 0x33, 0xb2, 0x08, 0x38, 0x5f, 0xad, 0xb9, 0x18, 0x6b, 0xc7, 0x8a, 0x76, 0xc4, 0x89, 0xd8, 0x9f, 0xd5, 0x7e, 0x7d, 0xc7, 0x54, 0x12, 0xd2, 0x3b, 0xcd, 0x1d, 0xae, 0x84, 0x70, 0xce, 0x92, 0x74, 0x75, 0x4b, 0xb8, 0x58, 0x5b, 0x13, 0xc5 }, + { 0x31, 0xfc, 0x79, 0x73, 0x8b, 0x87, 0x72, 0xb3, 0xf5, 0x5c, 0xd8, 0x17, 0x88, 0x13, 0xb3, 0xb5, 0x2d, 0x0d, 0xb5, 0xa4, 0x19, 0xd3, 0x0b, 0xa9, 0x49, 0x5c, 0x4b, 0x9d, 0xa0, 0x21, 0x9f, 0xac, 0x6d, 0xf8, 0xe7, 0xc2, 0x3a, 0x81, 0x15, 0x51, 0xa6, 0x2b, 0x82, 0x7f, 0x25, 0x6e, 0xcd, 0xb8, 0x12, 0x4a, 0xc8, 0xa6, 0x79, 0x2c, 0xcf, 0xec, 0xc3, 0xb3, 0x01, 0x27, 0x22, 0xe9, 0x44, 0x63 }, + { 0xbb, 0x20, 0x39, 0xec, 0x28, 0x70, 0x91, 0xbc, 0xc9, 0x64, 0x2f, 0xc9, 0x00, 0x49, 0xe7, 0x37, 0x32, 0xe0, 0x2e, 0x57, 0x7e, 0x28, 0x62, 0xb3, 0x22, 0x16, 0xae, 0x9b, 0xed, 0xcd, 0x73, 0x0c, 0x4c, 0x28, 0x4e, 0xf3, 0x96, 0x8c, 0x36, 0x8b, 0x7d, 0x37, 0x58, 0x4f, 0x97, 0xbd, 0x4b, 0x4d, 0xc6, 0xef, 0x61, 0x27, 0xac, 0xfe, 0x2e, 0x6a, 0xe2, 0x50, 0x91, 0x24, 0xe6, 0x6c, 0x8a, 0xf4 }, + { 0xf5, 0x3d, 0x68, 0xd1, 0x3f, 0x45, 0xed, 0xfc, 0xb9, 0xbd, 0x41, 0x5e, 0x28, 0x31, 0xe9, 0x38, 0x35, 0x0d, 0x53, 0x80, 0xd3, 0x43, 0x22, 0x78, 0xfc, 0x1c, 0x0c, 0x38, 0x1f, 0xcb, 0x7c, 0x65, 0xc8, 0x2d, 0xaf, 0xe0, 0x51, 0xd8, 0xc8, 0xb0, 0xd4, 0x4e, 0x09, 0x74, 0xa0, 0xe5, 0x9e, 0xc7, 0xbf, 0x7e, 0xd0, 0x45, 0x9f, 0x86, 0xe9, 0x6f, 0x32, 0x9f, 0xc7, 0x97, 0x52, 0x51, 0x0f, 0xd3 }, + { 0x8d, 0x56, 0x8c, 0x79, 0x84, 0xf0, 0xec, 0xdf, 0x76, 0x40, 0xfb, 0xc4, 0x83, 0xb5, 0xd8, 0xc9, 0xf8, 0x66, 0x34, 0xf6, 0xf4, 0x32, 0x91, 0x84, 0x1b, 0x30, 0x9a, 0x35, 0x0a, 0xb9, 0xc1, 0x13, 0x7d, 0x24, 0x06, 0x6b, 0x09, 0xda, 0x99, 0x44, 0xba, 0xc5, 0x4d, 0x5b, 0xb6, 0x58, 0x0d, 0x83, 0x60, 0x47, 0xaa, 0xc7, 0x4a, 0xb7, 0x24, 0xb8, 0x87, 0xeb, 0xf9, 0x3d, 0x4b, 0x32, 0xec, 0xa9 }, + { 0xc0, 0xb6, 0x5c, 0xe5, 0xa9, 0x6f, 0xf7, 0x74, 0xc4, 0x56, 0xca, 0xc3, 0xb5, 0xf2, 0xc4, 0xcd, 0x35, 0x9b, 0x4f, 0xf5, 0x3e, 0xf9, 0x3a, 0x3d, 0xa0, 0x77, 0x8b, 0xe4, 0x90, 0x0d, 0x1e, 0x8d, 0xa1, 0x60, 0x1e, 0x76, 0x9e, 0x8f, 0x1b, 0x02, 0xd2, 0xa2, 0xf8, 0xc5, 0xb9, 0xfa, 0x10, 0xb4, 0x4f, 0x1c, 0x18, 0x69, 0x85, 0x46, 0x8f, 0xee, 0xb0, 0x08, 0x73, 0x02, 0x83, 0xa6, 0x65, 0x7d }, + { 0x49, 0x00, 0xbb, 0xa6, 0xf5, 0xfb, 0x10, 0x3e, 0xce, 0x8e, 0xc9, 0x6a, 0xda, 0x13, 0xa5, 0xc3, 0xc8, 0x54, 0x88, 0xe0, 0x55, 0x51, 0xda, 0x6b, 0x6b, 0x33, 0xd9, 0x88, 0xe6, 0x11, 0xec, 0x0f, 0xe2, 0xe3, 0xc2, 0xaa, 0x48, 0xea, 0x6a, 0xe8, 0x98, 0x6a, 0x3a, 0x23, 0x1b, 0x22, 0x3c, 0x5d, 0x27, 0xce, 0xc2, 0xea, 0xdd, 0xe9, 0x1c, 0xe0, 0x79, 0x81, 0xee, 0x65, 0x28, 0x62, 0xd1, 0xe4 }, + { 0xc7, 0xf5, 0xc3, 0x7c, 0x72, 0x85, 0xf9, 0x27, 0xf7, 0x64, 0x43, 0x41, 0x4d, 0x43, 0x57, 0xff, 0x78, 0x96, 0x47, 0xd7, 0xa0, 0x05, 0xa5, 0xa7, 0x87, 0xe0, 0x3c, 0x34, 0x6b, 0x57, 0xf4, 0x9f, 0x21, 0xb6, 0x4f, 0xa9, 0xcf, 0x4b, 0x7e, 0x45, 0x57, 0x3e, 0x23, 0x04, 0x90, 0x17, 0x56, 0x71, 0x21, 0xa9, 0xc3, 0xd4, 0xb2, 0xb7, 0x3e, 0xc5, 0xe9, 0x41, 0x35, 0x77, 0x52, 0x5d, 0xb4, 0x5a }, + { 0xec, 0x70, 0x96, 0x33, 0x07, 0x36, 0xfd, 0xb2, 0xd6, 0x4b, 0x56, 0x53, 0xe7, 0x47, 0x5d, 0xa7, 0x46, 0xc2, 0x3a, 0x46, 0x13, 0xa8, 0x26, 0x87, 0xa2, 0x80, 0x62, 0xd3, 0x23, 0x63, 0x64, 0x28, 0x4a, 0xc0, 0x17, 0x20, 0xff, 0xb4, 0x06, 0xcf, 0xe2, 0x65, 0xc0, 0xdf, 0x62, 0x6a, 0x18, 0x8c, 0x9e, 0x59, 0x63, 0xac, 0xe5, 0xd3, 0xd5, 0xbb, 0x36, 0x3e, 0x32, 0xc3, 0x8c, 0x21, 0x90, 0xa6 }, + { 0x82, 0xe7, 0x44, 0xc7, 0x5f, 0x46, 0x49, 0xec, 0x52, 0xb8, 0x07, 0x71, 0xa7, 0x7d, 0x47, 0x5a, 0x3b, 0xc0, 0x91, 0x98, 0x95, 0x56, 0x96, 0x0e, 0x27, 0x6a, 0x5f, 0x9e, 0xad, 0x92, 0xa0, 0x3f, 0x71, 0x87, 0x42, 0xcd, 0xcf, 0xea, 0xee, 0x5c, 0xb8, 0x5c, 0x44, 0xaf, 0x19, 0x8a, 0xdc, 0x43, 0xa4, 0xa4, 0x28, 0xf5, 0xf0, 0xc2, 0xdd, 0xb0, 0xbe, 0x36, 0x05, 0x9f, 0x06, 0xd7, 0xdf, 0x73 }, + { 0x28, 0x34, 0xb7, 0xa7, 0x17, 0x0f, 0x1f, 0x5b, 0x68, 0x55, 0x9a, 0xb7, 0x8c, 0x10, 0x50, 0xec, 0x21, 0xc9, 0x19, 0x74, 0x0b, 0x78, 0x4a, 0x90, 0x72, 0xf6, 0xe5, 0xd6, 0x9f, 0x82, 0x8d, 0x70, 0xc9, 0x19, 0xc5, 0x03, 0x9f, 0xb1, 0x48, 0xe3, 0x9e, 0x2c, 0x8a, 0x52, 0x11, 0x83, 0x78, 0xb0, 0x64, 0xca, 0x8d, 0x50, 0x01, 0xcd, 0x10, 0xa5, 0x47, 0x83, 0x87, 0xb9, 0x66, 0x71, 0x5e, 0xd6 }, + { 0x16, 0xb4, 0xad, 0xa8, 0x83, 0xf7, 0x2f, 0x85, 0x3b, 0xb7, 0xef, 0x25, 0x3e, 0xfc, 0xab, 0x0c, 0x3e, 0x21, 0x61, 0x68, 0x7a, 0xd6, 0x15, 0x43, 0xa0, 0xd2, 0x82, 0x4f, 0x91, 0xc1, 0xf8, 0x13, 0x47, 0xd8, 0x6b, 0xe7, 0x09, 0xb1, 0x69, 0x96, 0xe1, 0x7f, 0x2d, 0xd4, 0x86, 0x92, 0x7b, 0x02, 0x88, 0xad, 0x38, 0xd1, 0x30, 0x63, 0xc4, 0xa9, 0x67, 0x2c, 0x39, 0x39, 0x7d, 0x37, 0x89, 0xb6 }, + { 0x78, 0xd0, 0x48, 0xf3, 0xa6, 0x9d, 0x8b, 0x54, 0xae, 0x0e, 0xd6, 0x3a, 0x57, 0x3a, 0xe3, 0x50, 0xd8, 0x9f, 0x7c, 0x6c, 0xf1, 0xf3, 0x68, 0x89, 0x30, 0xde, 0x89, 0x9a, 0xfa, 0x03, 0x76, 0x97, 0x62, 0x9b, 0x31, 0x4e, 0x5c, 0xd3, 0x03, 0xaa, 0x62, 0xfe, 0xea, 0x72, 0xa2, 0x5b, 0xf4, 0x2b, 0x30, 0x4b, 0x6c, 0x6b, 0xcb, 0x27, 0xfa, 0xe2, 0x1c, 0x16, 0xd9, 0x25, 0xe1, 0xfb, 0xda, 0xc3 }, + { 0x0f, 0x74, 0x6a, 0x48, 0x74, 0x92, 0x87, 0xad, 0xa7, 0x7a, 0x82, 0x96, 0x1f, 0x05, 0xa4, 0xda, 0x4a, 0xbd, 0xb7, 0xd7, 0x7b, 0x12, 0x20, 0xf8, 0x36, 0xd0, 0x9e, 0xc8, 0x14, 0x35, 0x9c, 0x0e, 0xc0, 0x23, 0x9b, 0x8c, 0x7b, 0x9f, 0xf9, 0xe0, 0x2f, 0x56, 0x9d, 0x1b, 0x30, 0x1e, 0xf6, 0x7c, 0x46, 0x12, 0xd1, 0xde, 0x4f, 0x73, 0x0f, 0x81, 0xc1, 0x2c, 0x40, 0xcc, 0x06, 0x3c, 0x5c, 0xaa }, + { 0xf0, 0xfc, 0x85, 0x9d, 0x3b, 0xd1, 0x95, 0xfb, 0xdc, 0x2d, 0x59, 0x1e, 0x4c, 0xda, 0xc1, 0x51, 0x79, 0xec, 0x0f, 0x1d, 0xc8, 0x21, 0xc1, 0x1d, 0xf1, 0xf0, 0xc1, 0xd2, 0x6e, 0x62, 0x60, 0xaa, 0xa6, 0x5b, 0x79, 0xfa, 0xfa, 0xca, 0xfd, 0x7d, 0x3a, 0xd6, 0x1e, 0x60, 0x0f, 0x25, 0x09, 0x05, 0xf5, 0x87, 0x8c, 0x87, 0x45, 0x28, 0x97, 0x64, 0x7a, 0x35, 0xb9, 0x95, 0xbc, 0xad, 0xc3, 0xa3 }, + { 0x26, 0x20, 0xf6, 0x87, 0xe8, 0x62, 0x5f, 0x6a, 0x41, 0x24, 0x60, 0xb4, 0x2e, 0x2c, 0xef, 0x67, 0x63, 0x42, 0x08, 0xce, 0x10, 0xa0, 0xcb, 0xd4, 0xdf, 0xf7, 0x04, 0x4a, 0x41, 0xb7, 0x88, 0x00, 0x77, 0xe9, 0xf8, 0xdc, 0x3b, 0x8d, 0x12, 0x16, 0xd3, 0x37, 0x6a, 0x21, 0xe0, 0x15, 0xb5, 0x8f, 0xb2, 0x79, 0xb5, 0x21, 0xd8, 0x3f, 0x93, 0x88, 0xc7, 0x38, 0x2c, 0x85, 0x05, 0x59, 0x0b, 0x9b }, + { 0x22, 0x7e, 0x3a, 0xed, 0x8d, 0x2c, 0xb1, 0x0b, 0x91, 0x8f, 0xcb, 0x04, 0xf9, 0xde, 0x3e, 0x6d, 0x0a, 0x57, 0xe0, 0x84, 0x76, 0xd9, 0x37, 0x59, 0xcd, 0x7b, 0x2e, 0xd5, 0x4a, 0x1c, 0xbf, 0x02, 0x39, 0xc5, 0x28, 0xfb, 0x04, 0xbb, 0xf2, 0x88, 0x25, 0x3e, 0x60, 0x1d, 0x3b, 0xc3, 0x8b, 0x21, 0x79, 0x4a, 0xfe, 0xf9, 0x0b, 0x17, 0x09, 0x4a, 0x18, 0x2c, 0xac, 0x55, 0x77, 0x45, 0xe7, 0x5f }, + { 0x1a, 0x92, 0x99, 0x01, 0xb0, 0x9c, 0x25, 0xf2, 0x7d, 0x6b, 0x35, 0xbe, 0x7b, 0x2f, 0x1c, 0x47, 0x45, 0x13, 0x1f, 0xde, 0xbc, 0xa7, 0xf3, 0xe2, 0x45, 0x19, 0x26, 0x72, 0x04, 0x34, 0xe0, 0xdb, 0x6e, 0x74, 0xfd, 0x69, 0x3a, 0xd2, 0x9b, 0x77, 0x7d, 0xc3, 0x35, 0x5c, 0x59, 0x2a, 0x36, 0x1c, 0x48, 0x73, 0xb0, 0x11, 0x33, 0xa5, 0x7c, 0x2e, 0x3b, 0x70, 0x75, 0xcb, 0xdb, 0x86, 0xf4, 0xfc }, + { 0x5f, 0xd7, 0x96, 0x8b, 0xc2, 0xfe, 0x34, 0xf2, 0x20, 0xb5, 0xe3, 0xdc, 0x5a, 0xf9, 0x57, 0x17, 0x42, 0xd7, 0x3b, 0x7d, 0x60, 0x81, 0x9f, 0x28, 0x88, 0xb6, 0x29, 0x07, 0x2b, 0x96, 0xa9, 0xd8, 0xab, 0x2d, 0x91, 0xb8, 0x2d, 0x0a, 0x9a, 0xab, 0xa6, 0x1b, 0xbd, 0x39, 0x95, 0x81, 0x32, 0xfc, 0xc4, 0x25, 0x70, 0x23, 0xd1, 0xec, 0xa5, 0x91, 0xb3, 0x05, 0x4e, 0x2d, 0xc8, 0x1c, 0x82, 0x00 }, + { 0xdf, 0xcc, 0xe8, 0xcf, 0x32, 0x87, 0x0c, 0xc6, 0xa5, 0x03, 0xea, 0xda, 0xfc, 0x87, 0xfd, 0x6f, 0x78, 0x91, 0x8b, 0x9b, 0x4d, 0x07, 0x37, 0xdb, 0x68, 0x10, 0xbe, 0x99, 0x6b, 0x54, 0x97, 0xe7, 0xe5, 0xcc, 0x80, 0xe3, 0x12, 0xf6, 0x1e, 0x71, 0xff, 0x3e, 0x96, 0x24, 0x43, 0x60, 0x73, 0x15, 0x64, 0x03, 0xf7, 0x35, 0xf5, 0x6b, 0x0b, 0x01, 0x84, 0x5c, 0x18, 0xf6, 0xca, 0xf7, 0x72, 0xe6 }, + { 0x02, 0xf7, 0xef, 0x3a, 0x9c, 0xe0, 0xff, 0xf9, 0x60, 0xf6, 0x70, 0x32, 0xb2, 0x96, 0xef, 0xca, 0x30, 0x61, 0xf4, 0x93, 0x4d, 0x69, 0x07, 0x49, 0xf2, 0xd0, 0x1c, 0x35, 0xc8, 0x1c, 0x14, 0xf3, 0x9a, 0x67, 0xfa, 0x35, 0x0b, 0xc8, 0xa0, 0x35, 0x9b, 0xf1, 0x72, 0x4b, 0xff, 0xc3, 0xbc, 0xa6, 0xd7, 0xc7, 0xbb, 0xa4, 0x79, 0x1f, 0xd5, 0x22, 0xa3, 0xad, 0x35, 0x3c, 0x02, 0xec, 0x5a, 0xa8 }, + { 0x64, 0xbe, 0x5c, 0x6a, 0xba, 0x65, 0xd5, 0x94, 0x84, 0x4a, 0xe7, 0x8b, 0xb0, 0x22, 0xe5, 0xbe, 0xbe, 0x12, 0x7f, 0xd6, 0xb6, 0xff, 0xa5, 0xa1, 0x37, 0x03, 0x85, 0x5a, 0xb6, 0x3b, 0x62, 0x4d, 0xcd, 0x1a, 0x36, 0x3f, 0x99, 0x20, 0x3f, 0x63, 0x2e, 0xc3, 0x86, 0xf3, 0xea, 0x76, 0x7f, 0xc9, 0x92, 0xe8, 0xed, 0x96, 0x86, 0x58, 0x6a, 0xa2, 0x75, 0x55, 0xa8, 0x59, 0x9d, 0x5b, 0x80, 0x8f }, + { 0xf7, 0x85, 0x85, 0x50, 0x5c, 0x4e, 0xaa, 0x54, 0xa8, 0xb5, 0xbe, 0x70, 0xa6, 0x1e, 0x73, 0x5e, 0x0f, 0xf9, 0x7a, 0xf9, 0x44, 0xdd, 0xb3, 0x00, 0x1e, 0x35, 0xd8, 0x6c, 0x4e, 0x21, 0x99, 0xd9, 0x76, 0x10, 0x4b, 0x6a, 0xe3, 0x17, 0x50, 0xa3, 0x6a, 0x72, 0x6e, 0xd2, 0x85, 0x06, 0x4f, 0x59, 0x81, 0xb5, 0x03, 0x88, 0x9f, 0xef, 0x82, 0x2f, 0xcd, 0xc2, 0x89, 0x8d, 0xdd, 0xb7, 0x88, 0x9a }, + { 0xe4, 0xb5, 0x56, 0x60, 0x33, 0x86, 0x95, 0x72, 0xed, 0xfd, 0x87, 0x47, 0x9a, 0x5b, 0xb7, 0x3c, 0x80, 0xe8, 0x75, 0x9b, 0x91, 0x23, 0x28, 0x79, 0xd9, 0x6b, 0x1d, 0xda, 0x36, 0xc0, 0x12, 0x07, 0x6e, 0xe5, 0xa2, 0xed, 0x7a, 0xe2, 0xde, 0x63, 0xef, 0x84, 0x06, 0xa0, 0x6a, 0xea, 0x82, 0xc1, 0x88, 0x03, 0x1b, 0x56, 0x0b, 0xea, 0xfb, 0x58, 0x3f, 0xb3, 0xde, 0x9e, 0x57, 0x95, 0x2a, 0x7e }, + { 0xe1, 0xb3, 0xe7, 0xed, 0x86, 0x7f, 0x6c, 0x94, 0x84, 0xa2, 0xa9, 0x7f, 0x77, 0x15, 0xf2, 0x5e, 0x25, 0x29, 0x4e, 0x99, 0x2e, 0x41, 0xf6, 0xa7, 0xc1, 0x61, 0xff, 0xc2, 0xad, 0xc6, 0xda, 0xae, 0xb7, 0x11, 0x31, 0x02, 0xd5, 0xe6, 0x09, 0x02, 0x87, 0xfe, 0x6a, 0xd9, 0x4c, 0xe5, 0xd6, 0xb7, 0x39, 0xc6, 0xca, 0x24, 0x0b, 0x05, 0xc7, 0x6f, 0xb7, 0x3f, 0x25, 0xdd, 0x02, 0x4b, 0xf9, 0x35 }, + { 0x85, 0xfd, 0x08, 0x5f, 0xdc, 0x12, 0xa0, 0x80, 0x98, 0x3d, 0xf0, 0x7b, 0xd7, 0x01, 0x2b, 0x0d, 0x40, 0x2a, 0x0f, 0x40, 0x43, 0xfc, 0xb2, 0x77, 0x5a, 0xdf, 0x0b, 0xad, 0x17, 0x4f, 0x9b, 0x08, 0xd1, 0x67, 0x6e, 0x47, 0x69, 0x85, 0x78, 0x5c, 0x0a, 0x5d, 0xcc, 0x41, 0xdb, 0xff, 0x6d, 0x95, 0xef, 0x4d, 0x66, 0xa3, 0xfb, 0xdc, 0x4a, 0x74, 0xb8, 0x2b, 0xa5, 0x2d, 0xa0, 0x51, 0x2b, 0x74 }, + { 0xae, 0xd8, 0xfa, 0x76, 0x4b, 0x0f, 0xbf, 0xf8, 0x21, 0xe0, 0x52, 0x33, 0xd2, 0xf7, 0xb0, 0x90, 0x0e, 0xc4, 0x4d, 0x82, 0x6f, 0x95, 0xe9, 0x3c, 0x34, 0x3c, 0x1b, 0xc3, 0xba, 0x5a, 0x24, 0x37, 0x4b, 0x1d, 0x61, 0x6e, 0x7e, 0x7a, 0xba, 0x45, 0x3a, 0x0a, 0xda, 0x5e, 0x4f, 0xab, 0x53, 0x82, 0x40, 0x9e, 0x0d, 0x42, 0xce, 0x9c, 0x2b, 0xc7, 0xfb, 0x39, 0xa9, 0x9c, 0x34, 0x0c, 0x20, 0xf0 }, + { 0x7b, 0xa3, 0xb2, 0xe2, 0x97, 0x23, 0x35, 0x22, 0xee, 0xb3, 0x43, 0xbd, 0x3e, 0xbc, 0xfd, 0x83, 0x5a, 0x04, 0x00, 0x77, 0x35, 0xe8, 0x7f, 0x0c, 0xa3, 0x00, 0xcb, 0xee, 0x6d, 0x41, 0x65, 0x65, 0x16, 0x21, 0x71, 0x58, 0x1e, 0x40, 0x20, 0xff, 0x4c, 0xf1, 0x76, 0x45, 0x0f, 0x12, 0x91, 0xea, 0x22, 0x85, 0xcb, 0x9e, 0xbf, 0xfe, 0x4c, 0x56, 0x66, 0x06, 0x27, 0x68, 0x51, 0x45, 0x05, 0x1c }, + { 0xde, 0x74, 0x8b, 0xcf, 0x89, 0xec, 0x88, 0x08, 0x47, 0x21, 0xe1, 0x6b, 0x85, 0xf3, 0x0a, 0xdb, 0x1a, 0x61, 0x34, 0xd6, 0x64, 0xb5, 0x84, 0x35, 0x69, 0xba, 0xbc, 0x5b, 0xbd, 0x1a, 0x15, 0xca, 0x9b, 0x61, 0x80, 0x3c, 0x90, 0x1a, 0x4f, 0xef, 0x32, 0x96, 0x5a, 0x17, 0x49, 0xc9, 0xf3, 0xa4, 0xe2, 0x43, 0xe1, 0x73, 0x93, 0x9d, 0xc5, 0xa8, 0xdc, 0x49, 0x5c, 0x67, 0x1a, 0xb5, 0x21, 0x45 }, + { 0xaa, 0xf4, 0xd2, 0xbd, 0xf2, 0x00, 0xa9, 0x19, 0x70, 0x6d, 0x98, 0x42, 0xdc, 0xe1, 0x6c, 0x98, 0x14, 0x0d, 0x34, 0xbc, 0x43, 0x3d, 0xf3, 0x20, 0xab, 0xa9, 0xbd, 0x42, 0x9e, 0x54, 0x9a, 0xa7, 0xa3, 0x39, 0x76, 0x52, 0xa4, 0xd7, 0x68, 0x27, 0x77, 0x86, 0xcf, 0x99, 0x3c, 0xde, 0x23, 0x38, 0x67, 0x3e, 0xd2, 0xe6, 0xb6, 0x6c, 0x96, 0x1f, 0xef, 0xb8, 0x2c, 0xd2, 0x0c, 0x93, 0x33, 0x8f }, + { 0xc4, 0x08, 0x21, 0x89, 0x68, 0xb7, 0x88, 0xbf, 0x86, 0x4f, 0x09, 0x97, 0xe6, 0xbc, 0x4c, 0x3d, 0xba, 0x68, 0xb2, 0x76, 0xe2, 0x12, 0x5a, 0x48, 0x43, 0x29, 0x60, 0x52, 0xff, 0x93, 0xbf, 0x57, 0x67, 0xb8, 0xcd, 0xce, 0x71, 0x31, 0xf0, 0x87, 0x64, 0x30, 0xc1, 0x16, 0x5f, 0xec, 0x6c, 0x4f, 0x47, 0xad, 0xaa, 0x4f, 0xd8, 0xbc, 0xfa, 0xce, 0xf4, 0x63, 0xb5, 0xd3, 0xd0, 0xfa, 0x61, 0xa0 }, + { 0x76, 0xd2, 0xd8, 0x19, 0xc9, 0x2b, 0xce, 0x55, 0xfa, 0x8e, 0x09, 0x2a, 0xb1, 0xbf, 0x9b, 0x9e, 0xab, 0x23, 0x7a, 0x25, 0x26, 0x79, 0x86, 0xca, 0xcf, 0x2b, 0x8e, 0xe1, 0x4d, 0x21, 0x4d, 0x73, 0x0d, 0xc9, 0xa5, 0xaa, 0x2d, 0x7b, 0x59, 0x6e, 0x86, 0xa1, 0xfd, 0x8f, 0xa0, 0x80, 0x4c, 0x77, 0x40, 0x2d, 0x2f, 0xcd, 0x45, 0x08, 0x36, 0x88, 0xb2, 0x18, 0xb1, 0xcd, 0xfa, 0x0d, 0xcb, 0xcb }, + { 0x72, 0x06, 0x5e, 0xe4, 0xdd, 0x91, 0xc2, 0xd8, 0x50, 0x9f, 0xa1, 0xfc, 0x28, 0xa3, 0x7c, 0x7f, 0xc9, 0xfa, 0x7d, 0x5b, 0x3f, 0x8a, 0xd3, 0xd0, 0xd7, 0xa2, 0x56, 0x26, 0xb5, 0x7b, 0x1b, 0x44, 0x78, 0x8d, 0x4c, 0xaf, 0x80, 0x62, 0x90, 0x42, 0x5f, 0x98, 0x90, 0xa3, 0xa2, 0xa3, 0x5a, 0x90, 0x5a, 0xb4, 0xb3, 0x7a, 0xcf, 0xd0, 0xda, 0x6e, 0x45, 0x17, 0xb2, 0x52, 0x5c, 0x96, 0x51, 0xe4 }, + { 0x64, 0x47, 0x5d, 0xfe, 0x76, 0x00, 0xd7, 0x17, 0x1b, 0xea, 0x0b, 0x39, 0x4e, 0x27, 0xc9, 0xb0, 0x0d, 0x8e, 0x74, 0xdd, 0x1e, 0x41, 0x6a, 0x79, 0x47, 0x36, 0x82, 0xad, 0x3d, 0xfd, 0xbb, 0x70, 0x66, 0x31, 0x55, 0x80, 0x55, 0xcf, 0xc8, 0xa4, 0x0e, 0x07, 0xbd, 0x01, 0x5a, 0x45, 0x40, 0xdc, 0xde, 0xa1, 0x58, 0x83, 0xcb, 0xbf, 0x31, 0x41, 0x2d, 0xf1, 0xde, 0x1c, 0xd4, 0x15, 0x2b, 0x91 }, + { 0x12, 0xcd, 0x16, 0x74, 0xa4, 0x48, 0x8a, 0x5d, 0x7c, 0x2b, 0x31, 0x60, 0xd2, 0xe2, 0xc4, 0xb5, 0x83, 0x71, 0xbe, 0xda, 0xd7, 0x93, 0x41, 0x8d, 0x6f, 0x19, 0xc6, 0xee, 0x38, 0x5d, 0x70, 0xb3, 0xe0, 0x67, 0x39, 0x36, 0x9d, 0x4d, 0xf9, 0x10, 0xed, 0xb0, 0xb0, 0xa5, 0x4c, 0xbf, 0xf4, 0x3d, 0x54, 0x54, 0x4c, 0xd3, 0x7a, 0xb3, 0xa0, 0x6c, 0xfa, 0x0a, 0x3d, 0xda, 0xc8, 0xb6, 0x6c, 0x89 }, + { 0x60, 0x75, 0x69, 0x66, 0x47, 0x9d, 0xed, 0xc6, 0xdd, 0x4b, 0xcf, 0xf8, 0xea, 0x7d, 0x1d, 0x4c, 0xe4, 0xd4, 0xaf, 0x2e, 0x7b, 0x09, 0x7e, 0x32, 0xe3, 0x76, 0x35, 0x18, 0x44, 0x11, 0x47, 0xcc, 0x12, 0xb3, 0xc0, 0xee, 0x6d, 0x2e, 0xca, 0xbf, 0x11, 0x98, 0xce, 0xc9, 0x2e, 0x86, 0xa3, 0x61, 0x6f, 0xba, 0x4f, 0x4e, 0x87, 0x2f, 0x58, 0x25, 0x33, 0x0a, 0xdb, 0xb4, 0xc1, 0xde, 0xe4, 0x44 }, + { 0xa7, 0x80, 0x3b, 0xcb, 0x71, 0xbc, 0x1d, 0x0f, 0x43, 0x83, 0xdd, 0xe1, 0xe0, 0x61, 0x2e, 0x04, 0xf8, 0x72, 0xb7, 0x15, 0xad, 0x30, 0x81, 0x5c, 0x22, 0x49, 0xcf, 0x34, 0xab, 0xb8, 0xb0, 0x24, 0x91, 0x5c, 0xb2, 0xfc, 0x9f, 0x4e, 0x7c, 0xc4, 0xc8, 0xcf, 0xd4, 0x5b, 0xe2, 0xd5, 0xa9, 0x1e, 0xab, 0x09, 0x41, 0xc7, 0xd2, 0x70, 0xe2, 0xda, 0x4c, 0xa4, 0xa9, 0xf7, 0xac, 0x68, 0x66, 0x3a }, + { 0xb8, 0x4e, 0xf6, 0xa7, 0x22, 0x9a, 0x34, 0xa7, 0x50, 0xd9, 0xa9, 0x8e, 0xe2, 0x52, 0x98, 0x71, 0x81, 0x6b, 0x87, 0xfb, 0xe3, 0xbc, 0x45, 0xb4, 0x5f, 0xa5, 0xae, 0x82, 0xd5, 0x14, 0x15, 0x40, 0x21, 0x11, 0x65, 0xc3, 0xc5, 0xd7, 0xa7, 0x47, 0x6b, 0xa5, 0xa4, 0xaa, 0x06, 0xd6, 0x64, 0x76, 0xf0, 0xd9, 0xdc, 0x49, 0xa3, 0xf1, 0xee, 0x72, 0xc3, 0xac, 0xab, 0xd4, 0x98, 0x96, 0x74, 0x14 }, + { 0xfa, 0xe4, 0xb6, 0xd8, 0xef, 0xc3, 0xf8, 0xc8, 0xe6, 0x4d, 0x00, 0x1d, 0xab, 0xec, 0x3a, 0x21, 0xf5, 0x44, 0xe8, 0x27, 0x14, 0x74, 0x52, 0x51, 0xb2, 0xb4, 0xb3, 0x93, 0xf2, 0xf4, 0x3e, 0x0d, 0xa3, 0xd4, 0x03, 0xc6, 0x4d, 0xb9, 0x5a, 0x2c, 0xb6, 0xe2, 0x3e, 0xbb, 0x7b, 0x9e, 0x94, 0xcd, 0xd5, 0xdd, 0xac, 0x54, 0xf0, 0x7c, 0x4a, 0x61, 0xbd, 0x3c, 0xb1, 0x0a, 0xa6, 0xf9, 0x3b, 0x49 }, + { 0x34, 0xf7, 0x28, 0x66, 0x05, 0xa1, 0x22, 0x36, 0x95, 0x40, 0x14, 0x1d, 0xed, 0x79, 0xb8, 0x95, 0x72, 0x55, 0xda, 0x2d, 0x41, 0x55, 0xab, 0xbf, 0x5a, 0x8d, 0xbb, 0x89, 0xc8, 0xeb, 0x7e, 0xde, 0x8e, 0xee, 0xf1, 0xda, 0xa4, 0x6d, 0xc2, 0x9d, 0x75, 0x1d, 0x04, 0x5d, 0xc3, 0xb1, 0xd6, 0x58, 0xbb, 0x64, 0xb8, 0x0f, 0xf8, 0x58, 0x9e, 0xdd, 0xb3, 0x82, 0x4b, 0x13, 0xda, 0x23, 0x5a, 0x6b }, + { 0x3b, 0x3b, 0x48, 0x43, 0x4b, 0xe2, 0x7b, 0x9e, 0xab, 0xab, 0xba, 0x43, 0xbf, 0x6b, 0x35, 0xf1, 0x4b, 0x30, 0xf6, 0xa8, 0x8d, 0xc2, 0xe7, 0x50, 0xc3, 0x58, 0x47, 0x0d, 0x6b, 0x3a, 0xa3, 0xc1, 0x8e, 0x47, 0xdb, 0x40, 0x17, 0xfa, 0x55, 0x10, 0x6d, 0x82, 0x52, 0xf0, 0x16, 0x37, 0x1a, 0x00, 0xf5, 0xf8, 0xb0, 0x70, 0xb7, 0x4b, 0xa5, 0xf2, 0x3c, 0xff, 0xc5, 0x51, 0x1c, 0x9f, 0x09, 0xf0 }, + { 0xba, 0x28, 0x9e, 0xbd, 0x65, 0x62, 0xc4, 0x8c, 0x3e, 0x10, 0xa8, 0xad, 0x6c, 0xe0, 0x2e, 0x73, 0x43, 0x3d, 0x1e, 0x93, 0xd7, 0xc9, 0x27, 0x9d, 0x4d, 0x60, 0xa7, 0xe8, 0x79, 0xee, 0x11, 0xf4, 0x41, 0xa0, 0x00, 0xf4, 0x8e, 0xd9, 0xf7, 0xc4, 0xed, 0x87, 0xa4, 0x51, 0x36, 0xd7, 0xdc, 0xcd, 0xca, 0x48, 0x21, 0x09, 0xc7, 0x8a, 0x51, 0x06, 0x2b, 0x3b, 0xa4, 0x04, 0x4a, 0xda, 0x24, 0x69 }, + { 0x02, 0x29, 0x39, 0xe2, 0x38, 0x6c, 0x5a, 0x37, 0x04, 0x98, 0x56, 0xc8, 0x50, 0xa2, 0xbb, 0x10, 0xa1, 0x3d, 0xfe, 0xa4, 0x21, 0x2b, 0x4c, 0x73, 0x2a, 0x88, 0x40, 0xa9, 0xff, 0xa5, 0xfa, 0xf5, 0x48, 0x75, 0xc5, 0x44, 0x88, 0x16, 0xb2, 0x78, 0x5a, 0x00, 0x7d, 0xa8, 0xa8, 0xd2, 0xbc, 0x7d, 0x71, 0xa5, 0x4e, 0x4e, 0x65, 0x71, 0xf1, 0x0b, 0x60, 0x0c, 0xbd, 0xb2, 0x5d, 0x13, 0xed, 0xe3 }, + { 0xe6, 0xfe, 0xc1, 0x9d, 0x89, 0xce, 0x87, 0x17, 0xb1, 0xa0, 0x87, 0x02, 0x46, 0x70, 0xfe, 0x02, 0x6f, 0x6c, 0x7c, 0xbd, 0xa1, 0x1c, 0xae, 0xf9, 0x59, 0xbb, 0x2d, 0x35, 0x1b, 0xf8, 0x56, 0xf8, 0x05, 0x5d, 0x1c, 0x0e, 0xbd, 0xaa, 0xa9, 0xd1, 0xb1, 0x78, 0x86, 0xfc, 0x2c, 0x56, 0x2b, 0x5e, 0x99, 0x64, 0x2f, 0xc0, 0x64, 0x71, 0x0c, 0x0d, 0x34, 0x88, 0xa0, 0x2b, 0x5e, 0xd7, 0xf6, 0xfd }, + { 0x94, 0xc9, 0x6f, 0x02, 0xa8, 0xf5, 0x76, 0xac, 0xa3, 0x2b, 0xa6, 0x1c, 0x2b, 0x20, 0x6f, 0x90, 0x72, 0x85, 0xd9, 0x29, 0x9b, 0x83, 0xac, 0x17, 0x5c, 0x20, 0x9a, 0x8d, 0x43, 0xd5, 0x3b, 0xfe, 0x68, 0x3d, 0xd1, 0xd8, 0x3e, 0x75, 0x49, 0xcb, 0x90, 0x6c, 0x28, 0xf5, 0x9a, 0xb7, 0xc4, 0x6f, 0x87, 0x51, 0x36, 0x6a, 0x28, 0xc3, 0x9d, 0xd5, 0xfe, 0x26, 0x93, 0xc9, 0x01, 0x96, 0x66, 0xc8 }, + { 0x31, 0xa0, 0xcd, 0x21, 0x5e, 0xbd, 0x2c, 0xb6, 0x1d, 0xe5, 0xb9, 0xed, 0xc9, 0x1e, 0x61, 0x95, 0xe3, 0x1c, 0x59, 0xa5, 0x64, 0x8d, 0x5c, 0x9f, 0x73, 0x7e, 0x12, 0x5b, 0x26, 0x05, 0x70, 0x8f, 0x2e, 0x32, 0x5a, 0xb3, 0x38, 0x1c, 0x8d, 0xce, 0x1a, 0x3e, 0x95, 0x88, 0x86, 0xf1, 0xec, 0xdc, 0x60, 0x31, 0x8f, 0x88, 0x2c, 0xfe, 0x20, 0xa2, 0x41, 0x91, 0x35, 0x2e, 0x61, 0x7b, 0x0f, 0x21 }, + { 0x91, 0xab, 0x50, 0x4a, 0x52, 0x2d, 0xce, 0x78, 0x77, 0x9f, 0x4c, 0x6c, 0x6b, 0xa2, 0xe6, 0xb6, 0xdb, 0x55, 0x65, 0xc7, 0x6d, 0x3e, 0x7e, 0x7c, 0x92, 0x0c, 0xaf, 0x7f, 0x75, 0x7e, 0xf9, 0xdb, 0x7c, 0x8f, 0xcf, 0x10, 0xe5, 0x7f, 0x03, 0x37, 0x9e, 0xa9, 0xbf, 0x75, 0xeb, 0x59, 0x89, 0x5d, 0x96, 0xe1, 0x49, 0x80, 0x0b, 0x6a, 0xae, 0x01, 0xdb, 0x77, 0x8b, 0xb9, 0x0a, 0xfb, 0xc9, 0x89 }, + { 0xd8, 0x5c, 0xab, 0xc6, 0xbd, 0x5b, 0x1a, 0x01, 0xa5, 0xaf, 0xd8, 0xc6, 0x73, 0x47, 0x40, 0xda, 0x9f, 0xd1, 0xc1, 0xac, 0xc6, 0xdb, 0x29, 0xbf, 0xc8, 0xa2, 0xe5, 0xb6, 0x68, 0xb0, 0x28, 0xb6, 0xb3, 0x15, 0x4b, 0xfb, 0x87, 0x03, 0xfa, 0x31, 0x80, 0x25, 0x1d, 0x58, 0x9a, 0xd3, 0x80, 0x40, 0xce, 0xb7, 0x07, 0xc4, 0xba, 0xd1, 0xb5, 0x34, 0x3c, 0xb4, 0x26, 0xb6, 0x1e, 0xaa, 0x49, 0xc1 }, + { 0xd6, 0x2e, 0xfb, 0xec, 0x2c, 0xa9, 0xc1, 0xf8, 0xbd, 0x66, 0xce, 0x8b, 0x3f, 0x6a, 0x89, 0x8c, 0xb3, 0xf7, 0x56, 0x6b, 0xa6, 0x56, 0x8c, 0x61, 0x8a, 0xd1, 0xfe, 0xb2, 0xb6, 0x5b, 0x76, 0xc3, 0xce, 0x1d, 0xd2, 0x0f, 0x73, 0x95, 0x37, 0x2f, 0xaf, 0x28, 0x42, 0x7f, 0x61, 0xc9, 0x27, 0x80, 0x49, 0xcf, 0x01, 0x40, 0xdf, 0x43, 0x4f, 0x56, 0x33, 0x04, 0x8c, 0x86, 0xb8, 0x1e, 0x03, 0x99 }, + { 0x7c, 0x8f, 0xdc, 0x61, 0x75, 0x43, 0x9e, 0x2c, 0x3d, 0xb1, 0x5b, 0xaf, 0xa7, 0xfb, 0x06, 0x14, 0x3a, 0x6a, 0x23, 0xbc, 0x90, 0xf4, 0x49, 0xe7, 0x9d, 0xee, 0xf7, 0x3c, 0x3d, 0x49, 0x2a, 0x67, 0x17, 0x15, 0xc1, 0x93, 0xb6, 0xfe, 0xa9, 0xf0, 0x36, 0x05, 0x0b, 0x94, 0x60, 0x69, 0x85, 0x6b, 0x89, 0x7e, 0x08, 0xc0, 0x07, 0x68, 0xf5, 0xee, 0x5d, 0xdc, 0xf7, 0x0b, 0x7c, 0xd6, 0xd0, 0xe0 }, + { 0x58, 0x60, 0x2e, 0xe7, 0x46, 0x8e, 0x6b, 0xc9, 0xdf, 0x21, 0xbd, 0x51, 0xb2, 0x3c, 0x00, 0x5f, 0x72, 0xd6, 0xcb, 0x01, 0x3f, 0x0a, 0x1b, 0x48, 0xcb, 0xec, 0x5e, 0xca, 0x29, 0x92, 0x99, 0xf9, 0x7f, 0x09, 0xf5, 0x4a, 0x9a, 0x01, 0x48, 0x3e, 0xae, 0xb3, 0x15, 0xa6, 0x47, 0x8b, 0xad, 0x37, 0xba, 0x47, 0xca, 0x13, 0x47, 0xc7, 0xc8, 0xfc, 0x9e, 0x66, 0x95, 0x59, 0x2c, 0x91, 0xd7, 0x23 }, + { 0x27, 0xf5, 0xb7, 0x9e, 0xd2, 0x56, 0xb0, 0x50, 0x99, 0x3d, 0x79, 0x34, 0x96, 0xed, 0xf4, 0x80, 0x7c, 0x1d, 0x85, 0xa7, 0xb0, 0xa6, 0x7c, 0x9c, 0x4f, 0xa9, 0x98, 0x60, 0x75, 0x0b, 0x0a, 0xe6, 0x69, 0x89, 0x67, 0x0a, 0x8f, 0xfd, 0x78, 0x56, 0xd7, 0xce, 0x41, 0x15, 0x99, 0xe5, 0x8c, 0x4d, 0x77, 0xb2, 0x32, 0xa6, 0x2b, 0xef, 0x64, 0xd1, 0x52, 0x75, 0xbe, 0x46, 0xa6, 0x82, 0x35, 0xff }, + { 0x39, 0x57, 0xa9, 0x76, 0xb9, 0xf1, 0x88, 0x7b, 0xf0, 0x04, 0xa8, 0xdc, 0xa9, 0x42, 0xc9, 0x2d, 0x2b, 0x37, 0xea, 0x52, 0x60, 0x0f, 0x25, 0xe0, 0xc9, 0xbc, 0x57, 0x07, 0xd0, 0x27, 0x9c, 0x00, 0xc6, 0xe8, 0x5a, 0x83, 0x9b, 0x0d, 0x2d, 0x8e, 0xb5, 0x9c, 0x51, 0xd9, 0x47, 0x88, 0xeb, 0xe6, 0x24, 0x74, 0xa7, 0x91, 0xca, 0xdf, 0x52, 0xcc, 0xcf, 0x20, 0xf5, 0x07, 0x0b, 0x65, 0x73, 0xfc }, + { 0xea, 0xa2, 0x37, 0x6d, 0x55, 0x38, 0x0b, 0xf7, 0x72, 0xec, 0xca, 0x9c, 0xb0, 0xaa, 0x46, 0x68, 0xc9, 0x5c, 0x70, 0x71, 0x62, 0xfa, 0x86, 0xd5, 0x18, 0xc8, 0xce, 0x0c, 0xa9, 0xbf, 0x73, 0x62, 0xb9, 0xf2, 0xa0, 0xad, 0xc3, 0xff, 0x59, 0x92, 0x2d, 0xf9, 0x21, 0xb9, 0x45, 0x67, 0xe8, 0x1e, 0x45, 0x2f, 0x6c, 0x1a, 0x07, 0xfc, 0x81, 0x7c, 0xeb, 0xe9, 0x96, 0x04, 0xb3, 0x50, 0x5d, 0x38 }, + { 0xc1, 0xe2, 0xc7, 0x8b, 0x6b, 0x27, 0x34, 0xe2, 0x48, 0x0e, 0xc5, 0x50, 0x43, 0x4c, 0xb5, 0xd6, 0x13, 0x11, 0x1a, 0xdc, 0xc2, 0x1d, 0x47, 0x55, 0x45, 0xc3, 0xb1, 0xb7, 0xe6, 0xff, 0x12, 0x44, 0x44, 0x76, 0xe5, 0xc0, 0x55, 0x13, 0x2e, 0x22, 0x29, 0xdc, 0x0f, 0x80, 0x70, 0x44, 0xbb, 0x91, 0x9b, 0x1a, 0x56, 0x62, 0xdd, 0x38, 0xa9, 0xee, 0x65, 0xe2, 0x43, 0xa3, 0x91, 0x1a, 0xed, 0x1a }, + { 0x8a, 0xb4, 0x87, 0x13, 0x38, 0x9d, 0xd0, 0xfc, 0xf9, 0xf9, 0x65, 0xd3, 0xce, 0x66, 0xb1, 0xe5, 0x59, 0xa1, 0xf8, 0xc5, 0x87, 0x41, 0xd6, 0x76, 0x83, 0xcd, 0x97, 0x13, 0x54, 0xf4, 0x52, 0xe6, 0x2d, 0x02, 0x07, 0xa6, 0x5e, 0x43, 0x6c, 0x5d, 0x5d, 0x8f, 0x8e, 0xe7, 0x1c, 0x6a, 0xbf, 0xe5, 0x0e, 0x66, 0x90, 0x04, 0xc3, 0x02, 0xb3, 0x1a, 0x7e, 0xa8, 0x31, 0x1d, 0x4a, 0x91, 0x60, 0x51 }, + { 0x24, 0xce, 0x0a, 0xdd, 0xaa, 0x4c, 0x65, 0x03, 0x8b, 0xd1, 0xb1, 0xc0, 0xf1, 0x45, 0x2a, 0x0b, 0x12, 0x87, 0x77, 0xaa, 0xbc, 0x94, 0xa2, 0x9d, 0xf2, 0xfd, 0x6c, 0x7e, 0x2f, 0x85, 0xf8, 0xab, 0x9a, 0xc7, 0xef, 0xf5, 0x16, 0xb0, 0xe0, 0xa8, 0x25, 0xc8, 0x4a, 0x24, 0xcf, 0xe4, 0x92, 0xea, 0xad, 0x0a, 0x63, 0x08, 0xe4, 0x6d, 0xd4, 0x2f, 0xe8, 0x33, 0x3a, 0xb9, 0x71, 0xbb, 0x30, 0xca }, + { 0x51, 0x54, 0xf9, 0x29, 0xee, 0x03, 0x04, 0x5b, 0x6b, 0x0c, 0x00, 0x04, 0xfa, 0x77, 0x8e, 0xde, 0xe1, 0xd1, 0x39, 0x89, 0x32, 0x67, 0xcc, 0x84, 0x82, 0x5a, 0xd7, 0xb3, 0x6c, 0x63, 0xde, 0x32, 0x79, 0x8e, 0x4a, 0x16, 0x6d, 0x24, 0x68, 0x65, 0x61, 0x35, 0x4f, 0x63, 0xb0, 0x07, 0x09, 0xa1, 0x36, 0x4b, 0x3c, 0x24, 0x1d, 0xe3, 0xfe, 0xbf, 0x07, 0x54, 0x04, 0x58, 0x97, 0x46, 0x7c, 0xd4 }, + { 0xe7, 0x4e, 0x90, 0x79, 0x20, 0xfd, 0x87, 0xbd, 0x5a, 0xd6, 0x36, 0xdd, 0x11, 0x08, 0x5e, 0x50, 0xee, 0x70, 0x45, 0x9c, 0x44, 0x3e, 0x1c, 0xe5, 0x80, 0x9a, 0xf2, 0xbc, 0x2e, 0xba, 0x39, 0xf9, 0xe6, 0xd7, 0x12, 0x8e, 0x0e, 0x37, 0x12, 0xc3, 0x16, 0xda, 0x06, 0xf4, 0x70, 0x5d, 0x78, 0xa4, 0x83, 0x8e, 0x28, 0x12, 0x1d, 0x43, 0x44, 0xa2, 0xc7, 0x9c, 0x5e, 0x0d, 0xb3, 0x07, 0xa6, 0x77 }, + { 0xbf, 0x91, 0xa2, 0x23, 0x34, 0xba, 0xc2, 0x0f, 0x3f, 0xd8, 0x06, 0x63, 0xb3, 0xcd, 0x06, 0xc4, 0xe8, 0x80, 0x2f, 0x30, 0xe6, 0xb5, 0x9f, 0x90, 0xd3, 0x03, 0x5c, 0xc9, 0x79, 0x8a, 0x21, 0x7e, 0xd5, 0xa3, 0x1a, 0xbb, 0xda, 0x7f, 0xa6, 0x84, 0x28, 0x27, 0xbd, 0xf2, 0xa7, 0xa1, 0xc2, 0x1f, 0x6f, 0xcf, 0xcc, 0xbb, 0x54, 0xc6, 0xc5, 0x29, 0x26, 0xf3, 0x2d, 0xa8, 0x16, 0x26, 0x9b, 0xe1 }, + { 0xd9, 0xd5, 0xc7, 0x4b, 0xe5, 0x12, 0x1b, 0x0b, 0xd7, 0x42, 0xf2, 0x6b, 0xff, 0xb8, 0xc8, 0x9f, 0x89, 0x17, 0x1f, 0x3f, 0x93, 0x49, 0x13, 0x49, 0x2b, 0x09, 0x03, 0xc2, 0x71, 0xbb, 0xe2, 0xb3, 0x39, 0x5e, 0xf2, 0x59, 0x66, 0x9b, 0xef, 0x43, 0xb5, 0x7f, 0x7f, 0xcc, 0x30, 0x27, 0xdb, 0x01, 0x82, 0x3f, 0x6b, 0xae, 0xe6, 0x6e, 0x4f, 0x9f, 0xea, 0xd4, 0xd6, 0x72, 0x6c, 0x74, 0x1f, 0xce }, + { 0x50, 0xc8, 0xb8, 0xcf, 0x34, 0xcd, 0x87, 0x9f, 0x80, 0xe2, 0xfa, 0xab, 0x32, 0x30, 0xb0, 0xc0, 0xe1, 0xcc, 0x3e, 0x9d, 0xca, 0xde, 0xb1, 0xb9, 0xd9, 0x7a, 0xb9, 0x23, 0x41, 0x5d, 0xd9, 0xa1, 0xfe, 0x38, 0xad, 0xdd, 0x5c, 0x11, 0x75, 0x6c, 0x67, 0x99, 0x0b, 0x25, 0x6e, 0x95, 0xad, 0x6d, 0x8f, 0x9f, 0xed, 0xce, 0x10, 0xbf, 0x1c, 0x90, 0x67, 0x9c, 0xde, 0x0e, 0xcf, 0x1b, 0xe3, 0x47 }, + { 0x0a, 0x38, 0x6e, 0x7c, 0xd5, 0xdd, 0x9b, 0x77, 0xa0, 0x35, 0xe0, 0x9f, 0xe6, 0xfe, 0xe2, 0xc8, 0xce, 0x61, 0xb5, 0x38, 0x3c, 0x87, 0xea, 0x43, 0x20, 0x50, 0x59, 0xc5, 0xe4, 0xcd, 0x4f, 0x44, 0x08, 0x31, 0x9b, 0xb0, 0xa8, 0x23, 0x60, 0xf6, 0xa5, 0x8e, 0x6c, 0x9c, 0xe3, 0xf4, 0x87, 0xc4, 0x46, 0x06, 0x3b, 0xf8, 0x13, 0xbc, 0x6b, 0xa5, 0x35, 0xe1, 0x7f, 0xc1, 0x82, 0x6c, 0xfc, 0x91 }, + { 0x1f, 0x14, 0x59, 0xcb, 0x6b, 0x61, 0xcb, 0xac, 0x5f, 0x0e, 0xfe, 0x8f, 0xc4, 0x87, 0x53, 0x8f, 0x42, 0x54, 0x89, 0x87, 0xfc, 0xd5, 0x62, 0x21, 0xcf, 0xa7, 0xbe, 0xb2, 0x25, 0x04, 0x76, 0x9e, 0x79, 0x2c, 0x45, 0xad, 0xfb, 0x1d, 0x6b, 0x3d, 0x60, 0xd7, 0xb7, 0x49, 0xc8, 0xa7, 0x5b, 0x0b, 0xdf, 0x14, 0xe8, 0xea, 0x72, 0x1b, 0x95, 0xdc, 0xa5, 0x38, 0xca, 0x6e, 0x25, 0x71, 0x12, 0x09 }, + { 0xe5, 0x8b, 0x38, 0x36, 0xb7, 0xd8, 0xfe, 0xdb, 0xb5, 0x0c, 0xa5, 0x72, 0x5c, 0x65, 0x71, 0xe7, 0x4c, 0x07, 0x85, 0xe9, 0x78, 0x21, 0xda, 0xb8, 0xb6, 0x29, 0x8c, 0x10, 0xe4, 0xc0, 0x79, 0xd4, 0xa6, 0xcd, 0xf2, 0x2f, 0x0f, 0xed, 0xb5, 0x50, 0x32, 0x92, 0x5c, 0x16, 0x74, 0x81, 0x15, 0xf0, 0x1a, 0x10, 0x5e, 0x77, 0xe0, 0x0c, 0xee, 0x3d, 0x07, 0x92, 0x4d, 0xc0, 0xd8, 0xf9, 0x06, 0x59 }, + { 0xb9, 0x29, 0xcc, 0x65, 0x05, 0xf0, 0x20, 0x15, 0x86, 0x72, 0xde, 0xda, 0x56, 0xd0, 0xdb, 0x08, 0x1a, 0x2e, 0xe3, 0x4c, 0x00, 0xc1, 0x10, 0x00, 0x29, 0xbd, 0xf8, 0xea, 0x98, 0x03, 0x4f, 0xa4, 0xbf, 0x3e, 0x86, 0x55, 0xec, 0x69, 0x7f, 0xe3, 0x6f, 0x40, 0x55, 0x3c, 0x5b, 0xb4, 0x68, 0x01, 0x64, 0x4a, 0x62, 0x7d, 0x33, 0x42, 0xf4, 0xfc, 0x92, 0xb6, 0x1f, 0x03, 0x29, 0x0f, 0xb3, 0x81 }, + { 0x72, 0xd3, 0x53, 0x99, 0x4b, 0x49, 0xd3, 0xe0, 0x31, 0x53, 0x92, 0x9a, 0x1e, 0x4d, 0x4f, 0x18, 0x8e, 0xe5, 0x8a, 0xb9, 0xe7, 0x2e, 0xe8, 0xe5, 0x12, 0xf2, 0x9b, 0xc7, 0x73, 0x91, 0x38, 0x19, 0xce, 0x05, 0x7d, 0xdd, 0x70, 0x02, 0xc0, 0x43, 0x3e, 0xe0, 0xa1, 0x61, 0x14, 0xe3, 0xd1, 0x56, 0xdd, 0x2c, 0x4a, 0x7e, 0x80, 0xee, 0x53, 0x37, 0x8b, 0x86, 0x70, 0xf2, 0x3e, 0x33, 0xef, 0x56 }, + { 0xc7, 0x0e, 0xf9, 0xbf, 0xd7, 0x75, 0xd4, 0x08, 0x17, 0x67, 0x37, 0xa0, 0x73, 0x6d, 0x68, 0x51, 0x7c, 0xe1, 0xaa, 0xad, 0x7e, 0x81, 0xa9, 0x3c, 0x8c, 0x1e, 0xd9, 0x67, 0xea, 0x21, 0x4f, 0x56, 0xc8, 0xa3, 0x77, 0xb1, 0x76, 0x3e, 0x67, 0x66, 0x15, 0xb6, 0x0f, 0x39, 0x88, 0x24, 0x1e, 0xae, 0x6e, 0xab, 0x96, 0x85, 0xa5, 0x12, 0x49, 0x29, 0xd2, 0x81, 0x88, 0xf2, 0x9e, 0xab, 0x06, 0xf7 }, + { 0xc2, 0x30, 0xf0, 0x80, 0x26, 0x79, 0xcb, 0x33, 0x82, 0x2e, 0xf8, 0xb3, 0xb2, 0x1b, 0xf7, 0xa9, 0xa2, 0x89, 0x42, 0x09, 0x29, 0x01, 0xd7, 0xda, 0xc3, 0x76, 0x03, 0x00, 0x83, 0x10, 0x26, 0xcf, 0x35, 0x4c, 0x92, 0x32, 0xdf, 0x3e, 0x08, 0x4d, 0x99, 0x03, 0x13, 0x0c, 0x60, 0x1f, 0x63, 0xc1, 0xf4, 0xa4, 0xa4, 0xb8, 0x10, 0x6e, 0x46, 0x8c, 0xd4, 0x43, 0xbb, 0xe5, 0xa7, 0x34, 0xf4, 0x5f }, + { 0x6f, 0x43, 0x09, 0x4c, 0xaf, 0xb5, 0xeb, 0xf1, 0xf7, 0xa4, 0x93, 0x7e, 0xc5, 0x0f, 0x56, 0xa4, 0xc9, 0xda, 0x30, 0x3c, 0xbb, 0x55, 0xac, 0x1f, 0x27, 0xf1, 0xf1, 0x97, 0x6c, 0xd9, 0x6b, 0xed, 0xa9, 0x46, 0x4f, 0x0e, 0x7b, 0x9c, 0x54, 0x62, 0x0b, 0x8a, 0x9f, 0xba, 0x98, 0x31, 0x64, 0xb8, 0xbe, 0x35, 0x78, 0x42, 0x5a, 0x02, 0x4f, 0x5f, 0xe1, 0x99, 0xc3, 0x63, 0x56, 0xb8, 0x89, 0x72 }, + { 0x37, 0x45, 0x27, 0x3f, 0x4c, 0x38, 0x22, 0x5d, 0xb2, 0x33, 0x73, 0x81, 0x87, 0x1a, 0x0c, 0x6a, 0xaf, 0xd3, 0xaf, 0x9b, 0x01, 0x8c, 0x88, 0xaa, 0x02, 0x02, 0x58, 0x50, 0xa5, 0xdc, 0x3a, 0x42, 0xa1, 0xa3, 0xe0, 0x3e, 0x56, 0xcb, 0xf1, 0xb0, 0x87, 0x6d, 0x63, 0xa4, 0x41, 0xf1, 0xd2, 0x85, 0x6a, 0x39, 0xb8, 0x80, 0x1e, 0xb5, 0xaf, 0x32, 0x52, 0x01, 0xc4, 0x15, 0xd6, 0x5e, 0x97, 0xfe }, + { 0xc5, 0x0c, 0x44, 0xcc, 0xa3, 0xec, 0x3e, 0xda, 0xae, 0x77, 0x9a, 0x7e, 0x17, 0x94, 0x50, 0xeb, 0xdd, 0xa2, 0xf9, 0x70, 0x67, 0xc6, 0x90, 0xaa, 0x6c, 0x5a, 0x4a, 0xc7, 0xc3, 0x01, 0x39, 0xbb, 0x27, 0xc0, 0xdf, 0x4d, 0xb3, 0x22, 0x0e, 0x63, 0xcb, 0x11, 0x0d, 0x64, 0xf3, 0x7f, 0xfe, 0x07, 0x8d, 0xb7, 0x26, 0x53, 0xe2, 0xda, 0xac, 0xf9, 0x3a, 0xe3, 0xf0, 0xa2, 0xd1, 0xa7, 0xeb, 0x2e }, + { 0x8a, 0xef, 0x26, 0x3e, 0x38, 0x5c, 0xbc, 0x61, 0xe1, 0x9b, 0x28, 0x91, 0x42, 0x43, 0x26, 0x2a, 0xf5, 0xaf, 0xe8, 0x72, 0x6a, 0xf3, 0xce, 0x39, 0xa7, 0x9c, 0x27, 0x02, 0x8c, 0xf3, 0xec, 0xd3, 0xf8, 0xd2, 0xdf, 0xd9, 0xcf, 0xc9, 0xad, 0x91, 0xb5, 0x8f, 0x6f, 0x20, 0x77, 0x8f, 0xd5, 0xf0, 0x28, 0x94, 0xa3, 0xd9, 0x1c, 0x7d, 0x57, 0xd1, 0xe4, 0xb8, 0x66, 0xa7, 0xf3, 0x64, 0xb6, 0xbe }, + { 0x28, 0x69, 0x61, 0x41, 0xde, 0x6e, 0x2d, 0x9b, 0xcb, 0x32, 0x35, 0x57, 0x8a, 0x66, 0x16, 0x6c, 0x14, 0x48, 0xd3, 0xe9, 0x05, 0xa1, 0xb4, 0x82, 0xd4, 0x23, 0xbe, 0x4b, 0xc5, 0x36, 0x9b, 0xc8, 0xc7, 0x4d, 0xae, 0x0a, 0xcc, 0x9c, 0xc1, 0x23, 0xe1, 0xd8, 0xdd, 0xce, 0x9f, 0x97, 0x91, 0x7e, 0x8c, 0x01, 0x9c, 0x55, 0x2d, 0xa3, 0x2d, 0x39, 0xd2, 0x21, 0x9b, 0x9a, 0xbf, 0x0f, 0xa8, 0xc8 }, + { 0x2f, 0xb9, 0xeb, 0x20, 0x85, 0x83, 0x01, 0x81, 0x90, 0x3a, 0x9d, 0xaf, 0xe3, 0xdb, 0x42, 0x8e, 0xe1, 0x5b, 0xe7, 0x66, 0x22, 0x24, 0xef, 0xd6, 0x43, 0x37, 0x1f, 0xb2, 0x56, 0x46, 0xae, 0xe7, 0x16, 0xe5, 0x31, 0xec, 0xa6, 0x9b, 0x2b, 0xdc, 0x82, 0x33, 0xf1, 0xa8, 0x08, 0x1f, 0xa4, 0x3d, 0xa1, 0x50, 0x03, 0x02, 0x97, 0x5a, 0x77, 0xf4, 0x2f, 0xa5, 0x92, 0x13, 0x67, 0x10, 0xe9, 0xdc }, + { 0x66, 0xf9, 0xa7, 0x14, 0x3f, 0x7a, 0x33, 0x14, 0xa6, 0x69, 0xbf, 0x2e, 0x24, 0xbb, 0xb3, 0x50, 0x14, 0x26, 0x1d, 0x63, 0x9f, 0x49, 0x5b, 0x6c, 0x9c, 0x1f, 0x10, 0x4f, 0xe8, 0xe3, 0x20, 0xac, 0xa6, 0x0d, 0x45, 0x50, 0xd6, 0x9d, 0x52, 0xed, 0xbd, 0x5a, 0x3c, 0xde, 0xb4, 0x01, 0x4a, 0xe6, 0x5b, 0x1d, 0x87, 0xaa, 0x77, 0x0b, 0x69, 0xae, 0x5c, 0x15, 0xf4, 0x33, 0x0b, 0x0b, 0x0a, 0xd8 }, + { 0xf4, 0xc4, 0xdd, 0x1d, 0x59, 0x4c, 0x35, 0x65, 0xe3, 0xe2, 0x5c, 0xa4, 0x3d, 0xad, 0x82, 0xf6, 0x2a, 0xbe, 0xa4, 0x83, 0x5e, 0xd4, 0xcd, 0x81, 0x1b, 0xcd, 0x97, 0x5e, 0x46, 0x27, 0x98, 0x28, 0xd4, 0x4d, 0x4c, 0x62, 0xc3, 0x67, 0x9f, 0x1b, 0x7f, 0x7b, 0x9d, 0xd4, 0x57, 0x1d, 0x7b, 0x49, 0x55, 0x73, 0x47, 0xb8, 0xc5, 0x46, 0x0c, 0xbd, 0xc1, 0xbe, 0xf6, 0x90, 0xfb, 0x2a, 0x08, 0xc0 }, + { 0x8f, 0x1d, 0xc9, 0x64, 0x9c, 0x3a, 0x84, 0x55, 0x1f, 0x8f, 0x6e, 0x91, 0xca, 0xc6, 0x82, 0x42, 0xa4, 0x3b, 0x1f, 0x8f, 0x32, 0x8e, 0xe9, 0x22, 0x80, 0x25, 0x73, 0x87, 0xfa, 0x75, 0x59, 0xaa, 0x6d, 0xb1, 0x2e, 0x4a, 0xea, 0xdc, 0x2d, 0x26, 0x09, 0x91, 0x78, 0x74, 0x9c, 0x68, 0x64, 0xb3, 0x57, 0xf3, 0xf8, 0x3b, 0x2f, 0xb3, 0xef, 0xa8, 0xd2, 0xa8, 0xdb, 0x05, 0x6b, 0xed, 0x6b, 0xcc }, + { 0x31, 0x39, 0xc1, 0xa7, 0xf9, 0x7a, 0xfd, 0x16, 0x75, 0xd4, 0x60, 0xeb, 0xbc, 0x07, 0xf2, 0x72, 0x8a, 0xa1, 0x50, 0xdf, 0x84, 0x96, 0x24, 0x51, 0x1e, 0xe0, 0x4b, 0x74, 0x3b, 0xa0, 0xa8, 0x33, 0x09, 0x2f, 0x18, 0xc1, 0x2d, 0xc9, 0x1b, 0x4d, 0xd2, 0x43, 0xf3, 0x33, 0x40, 0x2f, 0x59, 0xfe, 0x28, 0xab, 0xdb, 0xbb, 0xae, 0x30, 0x1e, 0x7b, 0x65, 0x9c, 0x7a, 0x26, 0xd5, 0xc0, 0xf9, 0x79 }, + { 0x06, 0xf9, 0x4a, 0x29, 0x96, 0x15, 0x8a, 0x81, 0x9f, 0xe3, 0x4c, 0x40, 0xde, 0x3c, 0xf0, 0x37, 0x9f, 0xd9, 0xfb, 0x85, 0xb3, 0xe3, 0x63, 0xba, 0x39, 0x26, 0xa0, 0xe7, 0xd9, 0x60, 0xe3, 0xf4, 0xc2, 0xe0, 0xc7, 0x0c, 0x7c, 0xe0, 0xcc, 0xb2, 0xa6, 0x4f, 0xc2, 0x98, 0x69, 0xf6, 0xe7, 0xab, 0x12, 0xbd, 0x4d, 0x3f, 0x14, 0xfc, 0xe9, 0x43, 0x27, 0x90, 0x27, 0xe7, 0x85, 0xfb, 0x5c, 0x29 }, + { 0xc2, 0x9c, 0x39, 0x9e, 0xf3, 0xee, 0xe8, 0x96, 0x1e, 0x87, 0x56, 0x5c, 0x1c, 0xe2, 0x63, 0x92, 0x5f, 0xc3, 0xd0, 0xce, 0x26, 0x7d, 0x13, 0xe4, 0x8d, 0xd9, 0xe7, 0x32, 0xee, 0x67, 0xb0, 0xf6, 0x9f, 0xad, 0x56, 0x40, 0x1b, 0x0f, 0x10, 0xfc, 0xaa, 0xc1, 0x19, 0x20, 0x10, 0x46, 0xcc, 0xa2, 0x8c, 0x5b, 0x14, 0xab, 0xde, 0xa3, 0x21, 0x2a, 0xe6, 0x55, 0x62, 0xf7, 0xf1, 0x38, 0xdb, 0x3d }, + { 0x4c, 0xec, 0x4c, 0x9d, 0xf5, 0x2e, 0xef, 0x05, 0xc3, 0xf6, 0xfa, 0xaa, 0x97, 0x91, 0xbc, 0x74, 0x45, 0x93, 0x71, 0x83, 0x22, 0x4e, 0xcc, 0x37, 0xa1, 0xe5, 0x8d, 0x01, 0x32, 0xd3, 0x56, 0x17, 0x53, 0x1d, 0x7e, 0x79, 0x5f, 0x52, 0xaf, 0x7b, 0x1e, 0xb9, 0xd1, 0x47, 0xde, 0x12, 0x92, 0xd3, 0x45, 0xfe, 0x34, 0x18, 0x23, 0xf8, 0xe6, 0xbc, 0x1e, 0x5b, 0xad, 0xca, 0x5c, 0x65, 0x61, 0x08 }, + { 0x89, 0x8b, 0xfb, 0xae, 0x93, 0xb3, 0xe1, 0x8d, 0x00, 0x69, 0x7e, 0xab, 0x7d, 0x97, 0x04, 0xfa, 0x36, 0xec, 0x33, 0x9d, 0x07, 0x61, 0x31, 0xce, 0xfd, 0xf3, 0x0e, 0xdb, 0xe8, 0xd9, 0xcc, 0x81, 0xc3, 0xa8, 0x0b, 0x12, 0x96, 0x59, 0xb1, 0x63, 0xa3, 0x23, 0xba, 0xb9, 0x79, 0x3d, 0x4f, 0xee, 0xd9, 0x2d, 0x54, 0xda, 0xe9, 0x66, 0xc7, 0x75, 0x29, 0x76, 0x4a, 0x09, 0xbe, 0x88, 0xdb, 0x45 }, + { 0xee, 0x9b, 0xd0, 0x46, 0x9d, 0x3a, 0xaf, 0x4f, 0x14, 0x03, 0x5b, 0xe4, 0x8a, 0x2c, 0x3b, 0x84, 0xd9, 0xb4, 0xb1, 0xff, 0xf1, 0xd9, 0x45, 0xe1, 0xf1, 0xc1, 0xd3, 0x89, 0x80, 0xa9, 0x51, 0xbe, 0x19, 0x7b, 0x25, 0xfe, 0x22, 0xc7, 0x31, 0xf2, 0x0a, 0xea, 0xcc, 0x93, 0x0b, 0xa9, 0xc4, 0xa1, 0xf4, 0x76, 0x22, 0x27, 0x61, 0x7a, 0xd3, 0x50, 0xfd, 0xab, 0xb4, 0xe8, 0x02, 0x73, 0xa0, 0xf4 }, + { 0x3d, 0x4d, 0x31, 0x13, 0x30, 0x05, 0x81, 0xcd, 0x96, 0xac, 0xbf, 0x09, 0x1c, 0x3d, 0x0f, 0x3c, 0x31, 0x01, 0x38, 0xcd, 0x69, 0x79, 0xe6, 0x02, 0x6c, 0xde, 0x62, 0x3e, 0x2d, 0xd1, 0xb2, 0x4d, 0x4a, 0x86, 0x38, 0xbe, 0xd1, 0x07, 0x33, 0x44, 0x78, 0x3a, 0xd0, 0x64, 0x9c, 0xc6, 0x30, 0x5c, 0xce, 0xc0, 0x4b, 0xeb, 0x49, 0xf3, 0x1c, 0x63, 0x30, 0x88, 0xa9, 0x9b, 0x65, 0x13, 0x02, 0x67 }, + { 0x95, 0xc0, 0x59, 0x1a, 0xd9, 0x1f, 0x92, 0x1a, 0xc7, 0xbe, 0x6d, 0x9c, 0xe3, 0x7e, 0x06, 0x63, 0xed, 0x80, 0x11, 0xc1, 0xcf, 0xd6, 0xd0, 0x16, 0x2a, 0x55, 0x72, 0xe9, 0x43, 0x68, 0xba, 0xc0, 0x20, 0x24, 0x48, 0x5e, 0x6a, 0x39, 0x85, 0x4a, 0xa4, 0x6f, 0xe3, 0x8e, 0x97, 0xd6, 0xc6, 0xb1, 0x94, 0x7c, 0xd2, 0x72, 0xd8, 0x6b, 0x06, 0xbb, 0x5b, 0x2f, 0x78, 0xb9, 0xb6, 0x8d, 0x55, 0x9d }, + { 0x22, 0x7b, 0x79, 0xde, 0xd3, 0x68, 0x15, 0x3b, 0xf4, 0x6c, 0x0a, 0x3c, 0xa9, 0x78, 0xbf, 0xdb, 0xef, 0x31, 0xf3, 0x02, 0x4a, 0x56, 0x65, 0x84, 0x24, 0x68, 0x49, 0x0b, 0x0f, 0xf7, 0x48, 0xae, 0x04, 0xe7, 0x83, 0x2e, 0xd4, 0xc9, 0xf4, 0x9d, 0xe9, 0xb1, 0x70, 0x67, 0x09, 0xd6, 0x23, 0xe5, 0xc8, 0xc1, 0x5e, 0x3c, 0xae, 0xca, 0xe8, 0xd5, 0xe4, 0x33, 0x43, 0x0f, 0xf7, 0x2f, 0x20, 0xeb }, + { 0x5d, 0x34, 0xf3, 0x95, 0x2f, 0x01, 0x05, 0xee, 0xf8, 0x8a, 0xe8, 0xb6, 0x4c, 0x6c, 0xe9, 0x5e, 0xbf, 0xad, 0xe0, 0xe0, 0x2c, 0x69, 0xb0, 0x87, 0x62, 0xa8, 0x71, 0x2d, 0x2e, 0x49, 0x11, 0xad, 0x3f, 0x94, 0x1f, 0xc4, 0x03, 0x4d, 0xc9, 0xb2, 0xe4, 0x79, 0xfd, 0xbc, 0xd2, 0x79, 0xb9, 0x02, 0xfa, 0xf5, 0xd8, 0x38, 0xbb, 0x2e, 0x0c, 0x64, 0x95, 0xd3, 0x72, 0xb5, 0xb7, 0x02, 0x98, 0x13 }, + { 0x7f, 0x93, 0x9b, 0xf8, 0x35, 0x3a, 0xbc, 0xe4, 0x9e, 0x77, 0xf1, 0x4f, 0x37, 0x50, 0xaf, 0x20, 0xb7, 0xb0, 0x39, 0x02, 0xe1, 0xa1, 0xe7, 0xfb, 0x6a, 0xaf, 0x76, 0xd0, 0x25, 0x9c, 0xd4, 0x01, 0xa8, 0x31, 0x90, 0xf1, 0x56, 0x40, 0xe7, 0x4f, 0x3e, 0x6c, 0x5a, 0x90, 0xe8, 0x39, 0xc7, 0x82, 0x1f, 0x64, 0x74, 0x75, 0x7f, 0x75, 0xc7, 0xbf, 0x90, 0x02, 0x08, 0x4d, 0xdc, 0x7a, 0x62, 0xdc }, + { 0x06, 0x2b, 0x61, 0xa2, 0xf9, 0xa3, 0x3a, 0x71, 0xd7, 0xd0, 0xa0, 0x61, 0x19, 0x64, 0x4c, 0x70, 0xb0, 0x71, 0x6a, 0x50, 0x4d, 0xe7, 0xe5, 0xe1, 0xbe, 0x49, 0xbd, 0x7b, 0x86, 0xe7, 0xed, 0x68, 0x17, 0x71, 0x4f, 0x9f, 0x0f, 0xc3, 0x13, 0xd0, 0x61, 0x29, 0x59, 0x7e, 0x9a, 0x22, 0x35, 0xec, 0x85, 0x21, 0xde, 0x36, 0xf7, 0x29, 0x0a, 0x90, 0xcc, 0xfc, 0x1f, 0xfa, 0x6d, 0x0a, 0xee, 0x29 }, + { 0xf2, 0x9e, 0x01, 0xee, 0xae, 0x64, 0x31, 0x1e, 0xb7, 0xf1, 0xc6, 0x42, 0x2f, 0x94, 0x6b, 0xf7, 0xbe, 0xa3, 0x63, 0x79, 0x52, 0x3e, 0x7b, 0x2b, 0xba, 0xba, 0x7d, 0x1d, 0x34, 0xa2, 0x2d, 0x5e, 0xa5, 0xf1, 0xc5, 0xa0, 0x9d, 0x5c, 0xe1, 0xfe, 0x68, 0x2c, 0xce, 0xd9, 0xa4, 0x79, 0x8d, 0x1a, 0x05, 0xb4, 0x6c, 0xd7, 0x2d, 0xff, 0x5c, 0x1b, 0x35, 0x54, 0x40, 0xb2, 0xa2, 0xd4, 0x76, 0xbc }, + { 0xec, 0x38, 0xcd, 0x3b, 0xba, 0xb3, 0xef, 0x35, 0xd7, 0xcb, 0x6d, 0x5c, 0x91, 0x42, 0x98, 0x35, 0x1d, 0x8a, 0x9d, 0xc9, 0x7f, 0xce, 0xe0, 0x51, 0xa8, 0xa0, 0x2f, 0x58, 0xe3, 0xed, 0x61, 0x84, 0xd0, 0xb7, 0x81, 0x0a, 0x56, 0x15, 0x41, 0x1a, 0xb1, 0xb9, 0x52, 0x09, 0xc3, 0xc8, 0x10, 0x11, 0x4f, 0xde, 0xb2, 0x24, 0x52, 0x08, 0x4e, 0x77, 0xf3, 0xf8, 0x47, 0xc6, 0xdb, 0xaa, 0xfe, 0x16 }, + { 0xc2, 0xae, 0xf5, 0xe0, 0xca, 0x43, 0xe8, 0x26, 0x41, 0x56, 0x5b, 0x8c, 0xb9, 0x43, 0xaa, 0x8b, 0xa5, 0x35, 0x50, 0xca, 0xef, 0x79, 0x3b, 0x65, 0x32, 0xfa, 0xfa, 0xd9, 0x4b, 0x81, 0x60, 0x82, 0xf0, 0x11, 0x3a, 0x3e, 0xa2, 0xf6, 0x36, 0x08, 0xab, 0x40, 0x43, 0x7e, 0xcc, 0x0f, 0x02, 0x29, 0xcb, 0x8f, 0xa2, 0x24, 0xdc, 0xf1, 0xc4, 0x78, 0xa6, 0x7d, 0x9b, 0x64, 0x16, 0x2b, 0x92, 0xd1 }, + { 0x15, 0xf5, 0x34, 0xef, 0xff, 0x71, 0x05, 0xcd, 0x1c, 0x25, 0x4d, 0x07, 0x4e, 0x27, 0xd5, 0x89, 0x8b, 0x89, 0x31, 0x3b, 0x7d, 0x36, 0x6d, 0xc2, 0xd7, 0xd8, 0x71, 0x13, 0xfa, 0x7d, 0x53, 0xaa, 0xe1, 0x3f, 0x6d, 0xba, 0x48, 0x7a, 0xd8, 0x10, 0x3d, 0x5e, 0x85, 0x4c, 0x91, 0xfd, 0xb6, 0xe1, 0xe7, 0x4b, 0x2e, 0xf6, 0xd1, 0x43, 0x17, 0x69, 0xc3, 0x07, 0x67, 0xdd, 0xe0, 0x67, 0xa3, 0x5c }, + { 0x89, 0xac, 0xbc, 0xa0, 0xb1, 0x69, 0x89, 0x7a, 0x0a, 0x27, 0x14, 0xc2, 0xdf, 0x8c, 0x95, 0xb5, 0xb7, 0x9c, 0xb6, 0x93, 0x90, 0x14, 0x2b, 0x7d, 0x60, 0x18, 0xbb, 0x3e, 0x30, 0x76, 0xb0, 0x99, 0xb7, 0x9a, 0x96, 0x41, 0x52, 0xa9, 0xd9, 0x12, 0xb1, 0xb8, 0x64, 0x12, 0xb7, 0xe3, 0x72, 0xe9, 0xce, 0xca, 0xd7, 0xf2, 0x5d, 0x4c, 0xba, 0xb8, 0xa3, 0x17, 0xbe, 0x36, 0x49, 0x2a, 0x67, 0xd7 }, + { 0xe3, 0xc0, 0x73, 0x91, 0x90, 0xed, 0x84, 0x9c, 0x9c, 0x96, 0x2f, 0xd9, 0xdb, 0xb5, 0x5e, 0x20, 0x7e, 0x62, 0x4f, 0xca, 0xc1, 0xeb, 0x41, 0x76, 0x91, 0x51, 0x54, 0x99, 0xee, 0xa8, 0xd8, 0x26, 0x7b, 0x7e, 0x8f, 0x12, 0x87, 0xa6, 0x36, 0x33, 0xaf, 0x50, 0x11, 0xfd, 0xe8, 0xc4, 0xdd, 0xf5, 0x5b, 0xfd, 0xf7, 0x22, 0xed, 0xf8, 0x88, 0x31, 0x41, 0x4f, 0x2c, 0xfa, 0xed, 0x59, 0xcb, 0x9a }, + { 0x8d, 0x6c, 0xf8, 0x7c, 0x08, 0x38, 0x0d, 0x2d, 0x15, 0x06, 0xee, 0xe4, 0x6f, 0xd4, 0x22, 0x2d, 0x21, 0xd8, 0xc0, 0x4e, 0x58, 0x5f, 0xbf, 0xd0, 0x82, 0x69, 0xc9, 0x8f, 0x70, 0x28, 0x33, 0xa1, 0x56, 0x32, 0x6a, 0x07, 0x24, 0x65, 0x64, 0x00, 0xee, 0x09, 0x35, 0x1d, 0x57, 0xb4, 0x40, 0x17, 0x5e, 0x2a, 0x5d, 0xe9, 0x3c, 0xc5, 0xf8, 0x0d, 0xb6, 0xda, 0xf8, 0x35, 0x76, 0xcf, 0x75, 0xfa }, + { 0xda, 0x24, 0xbe, 0xde, 0x38, 0x36, 0x66, 0xd5, 0x63, 0xee, 0xed, 0x37, 0xf6, 0x31, 0x9b, 0xaf, 0x20, 0xd5, 0xc7, 0x5d, 0x16, 0x35, 0xa6, 0xba, 0x5e, 0xf4, 0xcf, 0xa1, 0xac, 0x95, 0x48, 0x7e, 0x96, 0xf8, 0xc0, 0x8a, 0xf6, 0x00, 0xaa, 0xb8, 0x7c, 0x98, 0x6e, 0xba, 0xd4, 0x9f, 0xc7, 0x0a, 0x58, 0xb4, 0x89, 0x0b, 0x9c, 0x87, 0x6e, 0x09, 0x10, 0x16, 0xda, 0xf4, 0x9e, 0x1d, 0x32, 0x2e }, + { 0xf9, 0xd1, 0xd1, 0xb1, 0xe8, 0x7e, 0xa7, 0xae, 0x75, 0x3a, 0x02, 0x97, 0x50, 0xcc, 0x1c, 0xf3, 0xd0, 0x15, 0x7d, 0x41, 0x80, 0x5e, 0x24, 0x5c, 0x56, 0x17, 0xbb, 0x93, 0x4e, 0x73, 0x2f, 0x0a, 0xe3, 0x18, 0x0b, 0x78, 0xe0, 0x5b, 0xfe, 0x76, 0xc7, 0xc3, 0x05, 0x1e, 0x3e, 0x3a, 0xc7, 0x8b, 0x9b, 0x50, 0xc0, 0x51, 0x42, 0x65, 0x7e, 0x1e, 0x03, 0x21, 0x5d, 0x6e, 0xc7, 0xbf, 0xd0, 0xfc }, + { 0x11, 0xb7, 0xbc, 0x16, 0x68, 0x03, 0x20, 0x48, 0xaa, 0x43, 0x34, 0x3d, 0xe4, 0x76, 0x39, 0x5e, 0x81, 0x4b, 0xbb, 0xc2, 0x23, 0x67, 0x8d, 0xb9, 0x51, 0xa1, 0xb0, 0x3a, 0x02, 0x1e, 0xfa, 0xc9, 0x48, 0xcf, 0xbe, 0x21, 0x5f, 0x97, 0xfe, 0x9a, 0x72, 0xa2, 0xf6, 0xbc, 0x03, 0x9e, 0x39, 0x56, 0xbf, 0xa4, 0x17, 0xc1, 0xa9, 0xf1, 0x0d, 0x6d, 0x7b, 0xa5, 0xd3, 0xd3, 0x2f, 0xf3, 0x23, 0xe5 }, + { 0xb8, 0xd9, 0x00, 0x0e, 0x4f, 0xc2, 0xb0, 0x66, 0xed, 0xb9, 0x1a, 0xfe, 0xe8, 0xe7, 0xeb, 0x0f, 0x24, 0xe3, 0xa2, 0x01, 0xdb, 0x8b, 0x67, 0x93, 0xc0, 0x60, 0x85, 0x81, 0xe6, 0x28, 0xed, 0x0b, 0xcc, 0x4e, 0x5a, 0xa6, 0x78, 0x79, 0x92, 0xa4, 0xbc, 0xc4, 0x4e, 0x28, 0x80, 0x93, 0xe6, 0x3e, 0xe8, 0x3a, 0xbd, 0x0b, 0xc3, 0xec, 0x6d, 0x09, 0x34, 0xa6, 0x74, 0xa4, 0xda, 0x13, 0x83, 0x8a }, + { 0xce, 0x32, 0x5e, 0x29, 0x4f, 0x9b, 0x67, 0x19, 0xd6, 0xb6, 0x12, 0x78, 0x27, 0x6a, 0xe0, 0x6a, 0x25, 0x64, 0xc0, 0x3b, 0xb0, 0xb7, 0x83, 0xfa, 0xfe, 0x78, 0x5b, 0xdf, 0x89, 0xc7, 0xd5, 0xac, 0xd8, 0x3e, 0x78, 0x75, 0x6d, 0x30, 0x1b, 0x44, 0x56, 0x99, 0x02, 0x4e, 0xae, 0xb7, 0x7b, 0x54, 0xd4, 0x77, 0x33, 0x6e, 0xc2, 0xa4, 0xf3, 0x32, 0xf2, 0xb3, 0xf8, 0x87, 0x65, 0xdd, 0xb0, 0xc3 }, + { 0x29, 0xac, 0xc3, 0x0e, 0x96, 0x03, 0xae, 0x2f, 0xcc, 0xf9, 0x0b, 0xf9, 0x7e, 0x6c, 0xc4, 0x63, 0xeb, 0xe2, 0x8c, 0x1b, 0x2f, 0x9b, 0x4b, 0x76, 0x5e, 0x70, 0x53, 0x7c, 0x25, 0xc7, 0x02, 0xa2, 0x9d, 0xcb, 0xfb, 0xf1, 0x4c, 0x99, 0xc5, 0x43, 0x45, 0xba, 0x2b, 0x51, 0xf1, 0x7b, 0x77, 0xb5, 0xf1, 0x5d, 0xb9, 0x2b, 0xba, 0xd8, 0xfa, 0x95, 0xc4, 0x71, 0xf5, 0xd0, 0x70, 0xa1, 0x37, 0xcc }, + { 0x33, 0x79, 0xcb, 0xaa, 0xe5, 0x62, 0xa8, 0x7b, 0x4c, 0x04, 0x25, 0x55, 0x0f, 0xfd, 0xd6, 0xbf, 0xe1, 0x20, 0x3f, 0x0d, 0x66, 0x6c, 0xc7, 0xea, 0x09, 0x5b, 0xe4, 0x07, 0xa5, 0xdf, 0xe6, 0x1e, 0xe9, 0x14, 0x41, 0xcd, 0x51, 0x54, 0xb3, 0xe5, 0x3b, 0x4f, 0x5f, 0xb3, 0x1a, 0xd4, 0xc7, 0xa9, 0xad, 0x5c, 0x7a, 0xf4, 0xae, 0x67, 0x9a, 0xa5, 0x1a, 0x54, 0x00, 0x3a, 0x54, 0xca, 0x6b, 0x2d }, + { 0x30, 0x95, 0xa3, 0x49, 0xd2, 0x45, 0x70, 0x8c, 0x7c, 0xf5, 0x50, 0x11, 0x87, 0x03, 0xd7, 0x30, 0x2c, 0x27, 0xb6, 0x0a, 0xf5, 0xd4, 0xe6, 0x7f, 0xc9, 0x78, 0xf8, 0xa4, 0xe6, 0x09, 0x53, 0xc7, 0xa0, 0x4f, 0x92, 0xfc, 0xf4, 0x1a, 0xee, 0x64, 0x32, 0x1c, 0xcb, 0x70, 0x7a, 0x89, 0x58, 0x51, 0x55, 0x2b, 0x1e, 0x37, 0xb0, 0x0b, 0xc5, 0xe6, 0xb7, 0x2f, 0xa5, 0xbc, 0xef, 0x9e, 0x3f, 0xff }, + { 0x07, 0x26, 0x2d, 0x73, 0x8b, 0x09, 0x32, 0x1f, 0x4d, 0xbc, 0xce, 0xc4, 0xbb, 0x26, 0xf4, 0x8c, 0xb0, 0xf0, 0xed, 0x24, 0x6c, 0xe0, 0xb3, 0x1b, 0x9a, 0x6e, 0x7b, 0xc6, 0x83, 0x04, 0x9f, 0x1f, 0x3e, 0x55, 0x45, 0xf2, 0x8c, 0xe9, 0x32, 0xdd, 0x98, 0x5c, 0x5a, 0xb0, 0xf4, 0x3b, 0xd6, 0xde, 0x07, 0x70, 0x56, 0x0a, 0xf3, 0x29, 0x06, 0x5e, 0xd2, 0xe4, 0x9d, 0x34, 0x62, 0x4c, 0x2c, 0xbb }, + { 0xb6, 0x40, 0x5e, 0xca, 0x8e, 0xe3, 0x31, 0x6c, 0x87, 0x06, 0x1c, 0xc6, 0xec, 0x18, 0xdb, 0xa5, 0x3e, 0x6c, 0x25, 0x0c, 0x63, 0xba, 0x1f, 0x3b, 0xae, 0x9e, 0x55, 0xdd, 0x34, 0x98, 0x03, 0x6a, 0xf0, 0x8c, 0xd2, 0x72, 0xaa, 0x24, 0xd7, 0x13, 0xc6, 0x02, 0x0d, 0x77, 0xab, 0x2f, 0x39, 0x19, 0xaf, 0x1a, 0x32, 0xf3, 0x07, 0x42, 0x06, 0x18, 0xab, 0x97, 0xe7, 0x39, 0x53, 0x99, 0x4f, 0xb4 }, + { 0x7e, 0xe6, 0x82, 0xf6, 0x31, 0x48, 0xee, 0x45, 0xf6, 0xe5, 0x31, 0x5d, 0xa8, 0x1e, 0x5c, 0x6e, 0x55, 0x7c, 0x2c, 0x34, 0x64, 0x1f, 0xc5, 0x09, 0xc7, 0xa5, 0x70, 0x10, 0x88, 0xc3, 0x8a, 0x74, 0x75, 0x61, 0x68, 0xe2, 0xcd, 0x8d, 0x35, 0x1e, 0x88, 0xfd, 0x1a, 0x45, 0x1f, 0x36, 0x0a, 0x01, 0xf5, 0xb2, 0x58, 0x0f, 0x9b, 0x5a, 0x2e, 0x8c, 0xfc, 0x13, 0x8f, 0x3d, 0xd5, 0x9a, 0x3f, 0xfc }, + { 0x1d, 0x26, 0x3c, 0x17, 0x9d, 0x6b, 0x26, 0x8f, 0x6f, 0xa0, 0x16, 0xf3, 0xa4, 0xf2, 0x9e, 0x94, 0x38, 0x91, 0x12, 0x5e, 0xd8, 0x59, 0x3c, 0x81, 0x25, 0x60, 0x59, 0xf5, 0xa7, 0xb4, 0x4a, 0xf2, 0xdc, 0xb2, 0x03, 0x0d, 0x17, 0x5c, 0x00, 0xe6, 0x2e, 0xca, 0xf7, 0xee, 0x96, 0x68, 0x2a, 0xa0, 0x7a, 0xb2, 0x0a, 0x61, 0x10, 0x24, 0xa2, 0x85, 0x32, 0xb1, 0xc2, 0x5b, 0x86, 0x65, 0x79, 0x02 }, + { 0x10, 0x6d, 0x13, 0x2c, 0xbd, 0xb4, 0xcd, 0x25, 0x97, 0x81, 0x28, 0x46, 0xe2, 0xbc, 0x1b, 0xf7, 0x32, 0xfe, 0xc5, 0xf0, 0xa5, 0xf6, 0x5d, 0xbb, 0x39, 0xec, 0x4e, 0x6d, 0xc6, 0x4a, 0xb2, 0xce, 0x6d, 0x24, 0x63, 0x0d, 0x0f, 0x15, 0xa8, 0x05, 0xc3, 0x54, 0x00, 0x25, 0xd8, 0x4a, 0xfa, 0x98, 0xe3, 0x67, 0x03, 0xc3, 0xdb, 0xee, 0x71, 0x3e, 0x72, 0xdd, 0xe8, 0x46, 0x5b, 0xc1, 0xbe, 0x7e }, + { 0x0e, 0x79, 0x96, 0x82, 0x26, 0x65, 0x06, 0x67, 0xa8, 0xd8, 0x62, 0xea, 0x8d, 0xa4, 0x89, 0x1a, 0xf5, 0x6a, 0x4e, 0x3a, 0x8b, 0x6d, 0x17, 0x50, 0xe3, 0x94, 0xf0, 0xde, 0xa7, 0x6d, 0x64, 0x0d, 0x85, 0x07, 0x7b, 0xce, 0xc2, 0xcc, 0x86, 0x88, 0x6e, 0x50, 0x67, 0x51, 0xb4, 0xf6, 0xa5, 0x83, 0x8f, 0x7f, 0x0b, 0x5f, 0xef, 0x76, 0x5d, 0x9d, 0xc9, 0x0d, 0xcd, 0xcb, 0xaf, 0x07, 0x9f, 0x08 }, + { 0x52, 0x11, 0x56, 0xa8, 0x2a, 0xb0, 0xc4, 0xe5, 0x66, 0xe5, 0x84, 0x4d, 0x5e, 0x31, 0xad, 0x9a, 0xaf, 0x14, 0x4b, 0xbd, 0x5a, 0x46, 0x4f, 0xdc, 0xa3, 0x4d, 0xbd, 0x57, 0x17, 0xe8, 0xff, 0x71, 0x1d, 0x3f, 0xfe, 0xbb, 0xfa, 0x08, 0x5d, 0x67, 0xfe, 0x99, 0x6a, 0x34, 0xf6, 0xd3, 0xe4, 0xe6, 0x0b, 0x13, 0x96, 0xbf, 0x4b, 0x16, 0x10, 0xc2, 0x63, 0xbd, 0xbb, 0x83, 0x4d, 0x56, 0x08, 0x16 }, + { 0x1a, 0xba, 0x88, 0xbe, 0xfc, 0x55, 0xbc, 0x25, 0xef, 0xbc, 0xe0, 0x2d, 0xb8, 0xb9, 0x93, 0x3e, 0x46, 0xf5, 0x76, 0x61, 0xba, 0xea, 0xbe, 0xb2, 0x1c, 0xc2, 0x57, 0x4d, 0x2a, 0x51, 0x8a, 0x3c, 0xba, 0x5d, 0xc5, 0xa3, 0x8e, 0x49, 0x71, 0x34, 0x40, 0xb2, 0x5f, 0x9c, 0x74, 0x4e, 0x75, 0xf6, 0xb8, 0x5c, 0x9d, 0x8f, 0x46, 0x81, 0xf6, 0x76, 0x16, 0x0f, 0x61, 0x05, 0x35, 0x7b, 0x84, 0x06 }, + { 0x5a, 0x99, 0x49, 0xfc, 0xb2, 0xc4, 0x73, 0xcd, 0xa9, 0x68, 0xac, 0x1b, 0x5d, 0x08, 0x56, 0x6d, 0xc2, 0xd8, 0x16, 0xd9, 0x60, 0xf5, 0x7e, 0x63, 0xb8, 0x98, 0xfa, 0x70, 0x1c, 0xf8, 0xeb, 0xd3, 0xf5, 0x9b, 0x12, 0x4d, 0x95, 0xbf, 0xbb, 0xed, 0xc5, 0xf1, 0xcf, 0x0e, 0x17, 0xd5, 0xea, 0xed, 0x0c, 0x02, 0xc5, 0x0b, 0x69, 0xd8, 0xa4, 0x02, 0xca, 0xbc, 0xca, 0x44, 0x33, 0xb5, 0x1f, 0xd4 }, + { 0xb0, 0xce, 0xad, 0x09, 0x80, 0x7c, 0x67, 0x2a, 0xf2, 0xeb, 0x2b, 0x0f, 0x06, 0xdd, 0xe4, 0x6c, 0xf5, 0x37, 0x0e, 0x15, 0xa4, 0x09, 0x6b, 0x1a, 0x7d, 0x7c, 0xbb, 0x36, 0xec, 0x31, 0xc2, 0x05, 0xfb, 0xef, 0xca, 0x00, 0xb7, 0xa4, 0x16, 0x2f, 0xa8, 0x9f, 0xb4, 0xfb, 0x3e, 0xb7, 0x8d, 0x79, 0x77, 0x0c, 0x23, 0xf4, 0x4e, 0x72, 0x06, 0x66, 0x4c, 0xe3, 0xcd, 0x93, 0x1c, 0x29, 0x1e, 0x5d }, + { 0xbb, 0x66, 0x64, 0x93, 0x1e, 0xc9, 0x70, 0x44, 0xe4, 0x5b, 0x2a, 0xe4, 0x20, 0xae, 0x1c, 0x55, 0x1a, 0x88, 0x74, 0xbc, 0x93, 0x7d, 0x08, 0xe9, 0x69, 0x39, 0x9c, 0x39, 0x64, 0xeb, 0xdb, 0xa8, 0x34, 0x6c, 0xdd, 0x5d, 0x09, 0xca, 0xaf, 0xe4, 0xc2, 0x8b, 0xa7, 0xec, 0x78, 0x81, 0x91, 0xce, 0xca, 0x65, 0xdd, 0xd6, 0xf9, 0x5f, 0x18, 0x58, 0x3e, 0x04, 0x0d, 0x0f, 0x30, 0xd0, 0x36, 0x4d }, + { 0x65, 0xbc, 0x77, 0x0a, 0x5f, 0xaa, 0x37, 0x92, 0x36, 0x98, 0x03, 0x68, 0x3e, 0x84, 0x4b, 0x0b, 0xe7, 0xee, 0x96, 0xf2, 0x9f, 0x6d, 0x6a, 0x35, 0x56, 0x80, 0x06, 0xbd, 0x55, 0x90, 0xf9, 0xa4, 0xef, 0x63, 0x9b, 0x7a, 0x80, 0x61, 0xc7, 0xb0, 0x42, 0x4b, 0x66, 0xb6, 0x0a, 0xc3, 0x4a, 0xf3, 0x11, 0x99, 0x05, 0xf3, 0x3a, 0x9d, 0x8c, 0x3a, 0xe1, 0x83, 0x82, 0xca, 0x9b, 0x68, 0x99, 0x00 }, + { 0xea, 0x9b, 0x4d, 0xca, 0x33, 0x33, 0x36, 0xaa, 0xf8, 0x39, 0xa4, 0x5c, 0x6e, 0xaa, 0x48, 0xb8, 0xcb, 0x4c, 0x7d, 0xda, 0xbf, 0xfe, 0xa4, 0xf6, 0x43, 0xd6, 0x35, 0x7e, 0xa6, 0x62, 0x8a, 0x48, 0x0a, 0x5b, 0x45, 0xf2, 0xb0, 0x52, 0xc1, 0xb0, 0x7d, 0x1f, 0xed, 0xca, 0x91, 0x8b, 0x6f, 0x11, 0x39, 0xd8, 0x0f, 0x74, 0xc2, 0x45, 0x10, 0xdc, 0xba, 0xa4, 0xbe, 0x70, 0xea, 0xcc, 0x1b, 0x06 }, + { 0xe6, 0x34, 0x2f, 0xb4, 0xa7, 0x80, 0xad, 0x97, 0x5d, 0x0e, 0x24, 0xbc, 0xe1, 0x49, 0x98, 0x9b, 0x91, 0xd3, 0x60, 0x55, 0x7e, 0x87, 0x99, 0x4f, 0x6b, 0x45, 0x7b, 0x89, 0x55, 0x75, 0xcc, 0x02, 0xd0, 0xc1, 0x5b, 0xad, 0x3c, 0xe7, 0x57, 0x7f, 0x4c, 0x63, 0x92, 0x7f, 0xf1, 0x3f, 0x3e, 0x38, 0x1f, 0xf7, 0xe7, 0x2b, 0xdb, 0xe7, 0x45, 0x32, 0x48, 0x44, 0xa9, 0xd2, 0x7e, 0x3f, 0x1c, 0x01 }, + { 0x3e, 0x20, 0x9c, 0x9b, 0x33, 0xe8, 0xe4, 0x61, 0x17, 0x8a, 0xb4, 0x6b, 0x1c, 0x64, 0xb4, 0x9a, 0x07, 0xfb, 0x74, 0x5f, 0x1c, 0x8b, 0xc9, 0x5f, 0xbf, 0xb9, 0x4c, 0x6b, 0x87, 0xc6, 0x95, 0x16, 0x65, 0x1b, 0x26, 0x4e, 0xf9, 0x80, 0x93, 0x7f, 0xad, 0x41, 0x23, 0x8b, 0x91, 0xdd, 0xc0, 0x11, 0xa5, 0xdd, 0x77, 0x7c, 0x7e, 0xfd, 0x44, 0x94, 0xb4, 0xb6, 0xec, 0xd3, 0xa9, 0xc2, 0x2a, 0xc0 }, + { 0xfd, 0x6a, 0x3d, 0x5b, 0x18, 0x75, 0xd8, 0x04, 0x86, 0xd6, 0xe6, 0x96, 0x94, 0xa5, 0x6d, 0xbb, 0x04, 0xa9, 0x9a, 0x4d, 0x05, 0x1f, 0x15, 0xdb, 0x26, 0x89, 0x77, 0x6b, 0xa1, 0xc4, 0x88, 0x2e, 0x6d, 0x46, 0x2a, 0x60, 0x3b, 0x70, 0x15, 0xdc, 0x9f, 0x4b, 0x74, 0x50, 0xf0, 0x53, 0x94, 0x30, 0x3b, 0x86, 0x52, 0xcf, 0xb4, 0x04, 0xa2, 0x66, 0x96, 0x2c, 0x41, 0xba, 0xe6, 0xe1, 0x8a, 0x94 }, + { 0x95, 0x1e, 0x27, 0x51, 0x7e, 0x6b, 0xad, 0x9e, 0x41, 0x95, 0xfc, 0x86, 0x71, 0xde, 0xe3, 0xe7, 0xe9, 0xbe, 0x69, 0xce, 0xe1, 0x42, 0x2c, 0xb9, 0xfe, 0xcf, 0xce, 0x0d, 0xba, 0x87, 0x5f, 0x7b, 0x31, 0x0b, 0x93, 0xee, 0x3a, 0x3d, 0x55, 0x8f, 0x94, 0x1f, 0x63, 0x5f, 0x66, 0x8f, 0xf8, 0x32, 0xd2, 0xc1, 0xd0, 0x33, 0xc5, 0xe2, 0xf0, 0x99, 0x7e, 0x4c, 0x66, 0xf1, 0x47, 0x34, 0x4e, 0x02 }, + { 0x8e, 0xba, 0x2f, 0x87, 0x4f, 0x1a, 0xe8, 0x40, 0x41, 0x90, 0x3c, 0x7c, 0x42, 0x53, 0xc8, 0x22, 0x92, 0x53, 0x0f, 0xc8, 0x50, 0x95, 0x50, 0xbf, 0xdc, 0x34, 0xc9, 0x5c, 0x7e, 0x28, 0x89, 0xd5, 0x65, 0x0b, 0x0a, 0xd8, 0xcb, 0x98, 0x8e, 0x5c, 0x48, 0x94, 0xcb, 0x87, 0xfb, 0xfb, 0xb1, 0x96, 0x12, 0xea, 0x93, 0xcc, 0xc4, 0xc5, 0xca, 0xd1, 0x71, 0x58, 0xb9, 0x76, 0x34, 0x64, 0xb4, 0x92 }, + { 0x16, 0xf7, 0x12, 0xea, 0xa1, 0xb7, 0xc6, 0x35, 0x47, 0x19, 0xa8, 0xe7, 0xdb, 0xdf, 0xaf, 0x55, 0xe4, 0x06, 0x3a, 0x4d, 0x27, 0x7d, 0x94, 0x75, 0x50, 0x01, 0x9b, 0x38, 0xdf, 0xb5, 0x64, 0x83, 0x09, 0x11, 0x05, 0x7d, 0x50, 0x50, 0x61, 0x36, 0xe2, 0x39, 0x4c, 0x3b, 0x28, 0x94, 0x5c, 0xc9, 0x64, 0x96, 0x7d, 0x54, 0xe3, 0x00, 0x0c, 0x21, 0x81, 0x62, 0x6c, 0xfb, 0x9b, 0x73, 0xef, 0xd2 }, + { 0xc3, 0x96, 0x39, 0xe7, 0xd5, 0xc7, 0xfb, 0x8c, 0xdd, 0x0f, 0xd3, 0xe6, 0xa5, 0x20, 0x96, 0x03, 0x94, 0x37, 0x12, 0x2f, 0x21, 0xc7, 0x8f, 0x16, 0x79, 0xce, 0xa9, 0xd7, 0x8a, 0x73, 0x4c, 0x56, 0xec, 0xbe, 0xb2, 0x86, 0x54, 0xb4, 0xf1, 0x8e, 0x34, 0x2c, 0x33, 0x1f, 0x6f, 0x72, 0x29, 0xec, 0x4b, 0x4b, 0xc2, 0x81, 0xb2, 0xd8, 0x0a, 0x6e, 0xb5, 0x00, 0x43, 0xf3, 0x17, 0x96, 0xc8, 0x8c }, + { 0x72, 0xd0, 0x81, 0xaf, 0x99, 0xf8, 0xa1, 0x73, 0xdc, 0xc9, 0xa0, 0xac, 0x4e, 0xb3, 0x55, 0x74, 0x05, 0x63, 0x9a, 0x29, 0x08, 0x4b, 0x54, 0xa4, 0x01, 0x72, 0x91, 0x2a, 0x2f, 0x8a, 0x39, 0x51, 0x29, 0xd5, 0x53, 0x6f, 0x09, 0x18, 0xe9, 0x02, 0xf9, 0xe8, 0xfa, 0x60, 0x00, 0x99, 0x5f, 0x41, 0x68, 0xdd, 0xc5, 0xf8, 0x93, 0x01, 0x1b, 0xe6, 0xa0, 0xdb, 0xc9, 0xb8, 0xa1, 0xa3, 0xf5, 0xbb }, + { 0xc1, 0x1a, 0xa8, 0x1e, 0x5e, 0xfd, 0x24, 0xd5, 0xfc, 0x27, 0xee, 0x58, 0x6c, 0xfd, 0x88, 0x47, 0xfb, 0xb0, 0xe2, 0x76, 0x01, 0xcc, 0xec, 0xe5, 0xec, 0xca, 0x01, 0x98, 0xe3, 0xc7, 0x76, 0x53, 0x93, 0xbb, 0x74, 0x45, 0x7c, 0x7e, 0x7a, 0x27, 0xeb, 0x91, 0x70, 0x35, 0x0e, 0x1f, 0xb5, 0x38, 0x57, 0x17, 0x75, 0x06, 0xbe, 0x3e, 0x76, 0x2c, 0xc0, 0xf1, 0x4d, 0x8c, 0x3a, 0xfe, 0x90, 0x77 }, + { 0xc2, 0x8f, 0x21, 0x50, 0xb4, 0x52, 0xe6, 0xc0, 0xc4, 0x24, 0xbc, 0xde, 0x6f, 0x8d, 0x72, 0x00, 0x7f, 0x93, 0x10, 0xfe, 0xd7, 0xf2, 0xf8, 0x7d, 0xe0, 0xdb, 0xb6, 0x4f, 0x44, 0x79, 0xd6, 0xc1, 0x44, 0x1b, 0xa6, 0x6f, 0x44, 0xb2, 0xac, 0xce, 0xe6, 0x16, 0x09, 0x17, 0x7e, 0xd3, 0x40, 0x12, 0x8b, 0x40, 0x7e, 0xce, 0xc7, 0xc6, 0x4b, 0xbe, 0x50, 0xd6, 0x3d, 0x22, 0xd8, 0x62, 0x77, 0x27 }, + { 0xf6, 0x3d, 0x88, 0x12, 0x28, 0x77, 0xec, 0x30, 0xb8, 0xc8, 0xb0, 0x0d, 0x22, 0xe8, 0x90, 0x00, 0xa9, 0x66, 0x42, 0x61, 0x12, 0xbd, 0x44, 0x16, 0x6e, 0x2f, 0x52, 0x5b, 0x76, 0x9c, 0xcb, 0xe9, 0xb2, 0x86, 0xd4, 0x37, 0xa0, 0x12, 0x91, 0x30, 0xdd, 0xe1, 0xa8, 0x6c, 0x43, 0xe0, 0x4b, 0xed, 0xb5, 0x94, 0xe6, 0x71, 0xd9, 0x82, 0x83, 0xaf, 0xe6, 0x4c, 0xe3, 0x31, 0xde, 0x98, 0x28, 0xfd }, + { 0x34, 0x8b, 0x05, 0x32, 0x88, 0x0b, 0x88, 0xa6, 0x61, 0x4a, 0x8d, 0x74, 0x08, 0xc3, 0xf9, 0x13, 0x35, 0x7f, 0xbb, 0x60, 0xe9, 0x95, 0xc6, 0x02, 0x05, 0xbe, 0x91, 0x39, 0xe7, 0x49, 0x98, 0xae, 0xde, 0x7f, 0x45, 0x81, 0xe4, 0x2f, 0x6b, 0x52, 0x69, 0x8f, 0x7f, 0xa1, 0x21, 0x97, 0x08, 0xc1, 0x44, 0x98, 0x06, 0x7f, 0xd1, 0xe0, 0x95, 0x02, 0xde, 0x83, 0xa7, 0x7d, 0xd2, 0x81, 0x15, 0x0c }, + { 0x51, 0x33, 0xdc, 0x8b, 0xef, 0x72, 0x53, 0x59, 0xdf, 0xf5, 0x97, 0x92, 0xd8, 0x5e, 0xaf, 0x75, 0xb7, 0xe1, 0xdc, 0xd1, 0x97, 0x8b, 0x01, 0xc3, 0x5b, 0x1b, 0x85, 0xfc, 0xeb, 0xc6, 0x33, 0x88, 0xad, 0x99, 0xa1, 0x7b, 0x63, 0x46, 0xa2, 0x17, 0xdc, 0x1a, 0x96, 0x22, 0xeb, 0xd1, 0x22, 0xec, 0xf6, 0x91, 0x3c, 0x4d, 0x31, 0xa6, 0xb5, 0x2a, 0x69, 0x5b, 0x86, 0xaf, 0x00, 0xd7, 0x41, 0xa0 }, + { 0x27, 0x53, 0xc4, 0xc0, 0xe9, 0x8e, 0xca, 0xd8, 0x06, 0xe8, 0x87, 0x80, 0xec, 0x27, 0xfc, 0xcd, 0x0f, 0x5c, 0x1a, 0xb5, 0x47, 0xf9, 0xe4, 0xbf, 0x16, 0x59, 0xd1, 0x92, 0xc2, 0x3a, 0xa2, 0xcc, 0x97, 0x1b, 0x58, 0xb6, 0x80, 0x25, 0x80, 0xba, 0xef, 0x8a, 0xdc, 0x3b, 0x77, 0x6e, 0xf7, 0x08, 0x6b, 0x25, 0x45, 0xc2, 0x98, 0x7f, 0x34, 0x8e, 0xe3, 0x71, 0x9c, 0xde, 0xf2, 0x58, 0xc4, 0x03 }, + { 0xb1, 0x66, 0x35, 0x73, 0xce, 0x4b, 0x9d, 0x8c, 0xae, 0xfc, 0x86, 0x50, 0x12, 0xf3, 0xe3, 0x97, 0x14, 0xb9, 0x89, 0x8a, 0x5d, 0xa6, 0xce, 0x17, 0xc2, 0x5a, 0x6a, 0x47, 0x93, 0x1a, 0x9d, 0xdb, 0x9b, 0xbe, 0x98, 0xad, 0xaa, 0x55, 0x3b, 0xee, 0xd4, 0x36, 0xe8, 0x95, 0x78, 0x45, 0x54, 0x16, 0xc2, 0xa5, 0x2a, 0x52, 0x5c, 0xf2, 0x86, 0x2b, 0x8d, 0x1d, 0x49, 0xa2, 0x53, 0x1b, 0x73, 0x91 }, + { 0x64, 0xf5, 0x8b, 0xd6, 0xbf, 0xc8, 0x56, 0xf5, 0xe8, 0x73, 0xb2, 0xa2, 0x95, 0x6e, 0xa0, 0xed, 0xa0, 0xd6, 0xdb, 0x0d, 0xa3, 0x9c, 0x8c, 0x7f, 0xc6, 0x7c, 0x9f, 0x9f, 0xee, 0xfc, 0xff, 0x30, 0x72, 0xcd, 0xf9, 0xe6, 0xea, 0x37, 0xf6, 0x9a, 0x44, 0xf0, 0xc6, 0x1a, 0xa0, 0xda, 0x36, 0x93, 0xc2, 0xdb, 0x5b, 0x54, 0x96, 0x0c, 0x02, 0x81, 0xa0, 0x88, 0x15, 0x1d, 0xb4, 0x2b, 0x11, 0xe8 }, + { 0x07, 0x64, 0xc7, 0xbe, 0x28, 0x12, 0x5d, 0x90, 0x65, 0xc4, 0xb9, 0x8a, 0x69, 0xd6, 0x0a, 0xed, 0xe7, 0x03, 0x54, 0x7c, 0x66, 0xa1, 0x2e, 0x17, 0xe1, 0xc6, 0x18, 0x99, 0x41, 0x32, 0xf5, 0xef, 0x82, 0x48, 0x2c, 0x1e, 0x3f, 0xe3, 0x14, 0x6c, 0xc6, 0x53, 0x76, 0xcc, 0x10, 0x9f, 0x01, 0x38, 0xed, 0x9a, 0x80, 0xe4, 0x9f, 0x1f, 0x3c, 0x7d, 0x61, 0x0d, 0x2f, 0x24, 0x32, 0xf2, 0x06, 0x05 }, + { 0xf7, 0x48, 0x78, 0x43, 0x98, 0xa2, 0xff, 0x03, 0xeb, 0xeb, 0x07, 0xe1, 0x55, 0xe6, 0x61, 0x16, 0xa8, 0x39, 0x74, 0x1a, 0x33, 0x6e, 0x32, 0xda, 0x71, 0xec, 0x69, 0x60, 0x01, 0xf0, 0xad, 0x1b, 0x25, 0xcd, 0x48, 0xc6, 0x9c, 0xfc, 0xa7, 0x26, 0x5e, 0xca, 0x1d, 0xd7, 0x19, 0x04, 0xa0, 0xce, 0x74, 0x8a, 0xc4, 0x12, 0x4f, 0x35, 0x71, 0x07, 0x6d, 0xfa, 0x71, 0x16, 0xa9, 0xcf, 0x00, 0xe9 }, + { 0x3f, 0x0d, 0xbc, 0x01, 0x86, 0xbc, 0xeb, 0x6b, 0x78, 0x5b, 0xa7, 0x8d, 0x2a, 0x2a, 0x01, 0x3c, 0x91, 0x0b, 0xe1, 0x57, 0xbd, 0xaf, 0xfa, 0xe8, 0x1b, 0xb6, 0x66, 0x3b, 0x1a, 0x73, 0x72, 0x2f, 0x7f, 0x12, 0x28, 0x79, 0x5f, 0x3e, 0xca, 0xda, 0x87, 0xcf, 0x6e, 0xf0, 0x07, 0x84, 0x74, 0xaf, 0x73, 0xf3, 0x1e, 0xca, 0x0c, 0xc2, 0x00, 0xed, 0x97, 0x5b, 0x68, 0x93, 0xf7, 0x61, 0xcb, 0x6d }, + { 0xd4, 0x76, 0x2c, 0xd4, 0x59, 0x98, 0x76, 0xca, 0x75, 0xb2, 0xb8, 0xfe, 0x24, 0x99, 0x44, 0xdb, 0xd2, 0x7a, 0xce, 0x74, 0x1f, 0xda, 0xb9, 0x36, 0x16, 0xcb, 0xc6, 0xe4, 0x25, 0x46, 0x0f, 0xeb, 0x51, 0xd4, 0xe7, 0xad, 0xcc, 0x38, 0x18, 0x0e, 0x7f, 0xc4, 0x7c, 0x89, 0x02, 0x4a, 0x7f, 0x56, 0x19, 0x1a, 0xdb, 0x87, 0x8d, 0xfd, 0xe4, 0xea, 0xd6, 0x22, 0x23, 0xf5, 0xa2, 0x61, 0x0e, 0xfe }, + { 0xcd, 0x36, 0xb3, 0xd5, 0xb4, 0xc9, 0x1b, 0x90, 0xfc, 0xbb, 0xa7, 0x95, 0x13, 0xcf, 0xee, 0x19, 0x07, 0xd8, 0x64, 0x5a, 0x16, 0x2a, 0xfd, 0x0c, 0xd4, 0xcf, 0x41, 0x92, 0xd4, 0xa5, 0xf4, 0xc8, 0x92, 0x18, 0x3a, 0x8e, 0xac, 0xdb, 0x2b, 0x6b, 0x6a, 0x9d, 0x9a, 0xa8, 0xc1, 0x1a, 0xc1, 0xb2, 0x61, 0xb3, 0x80, 0xdb, 0xee, 0x24, 0xca, 0x46, 0x8f, 0x1b, 0xfd, 0x04, 0x3c, 0x58, 0xee, 0xfe }, + { 0x98, 0x59, 0x34, 0x52, 0x28, 0x16, 0x61, 0xa5, 0x3c, 0x48, 0xa9, 0xd8, 0xcd, 0x79, 0x08, 0x26, 0xc1, 0xa1, 0xce, 0x56, 0x77, 0x38, 0x05, 0x3d, 0x0b, 0xee, 0x4a, 0x91, 0xa3, 0xd5, 0xbd, 0x92, 0xee, 0xfd, 0xba, 0xbe, 0xbe, 0x32, 0x04, 0xf2, 0x03, 0x1c, 0xa5, 0xf7, 0x81, 0xbd, 0xa9, 0x9e, 0xf5, 0xd8, 0xae, 0x56, 0xe5, 0xb0, 0x4a, 0x9e, 0x1e, 0xcd, 0x21, 0xb0, 0xeb, 0x05, 0xd3, 0xe1 }, + { 0x77, 0x1f, 0x57, 0xdd, 0x27, 0x75, 0xcc, 0xda, 0xb5, 0x59, 0x21, 0xd3, 0xe8, 0xe3, 0x0c, 0xcf, 0x48, 0x4d, 0x61, 0xfe, 0x1c, 0x1b, 0x9c, 0x2a, 0xe8, 0x19, 0xd0, 0xfb, 0x2a, 0x12, 0xfa, 0xb9, 0xbe, 0x70, 0xc4, 0xa7, 0xa1, 0x38, 0xda, 0x84, 0xe8, 0x28, 0x04, 0x35, 0xda, 0xad, 0xe5, 0xbb, 0xe6, 0x6a, 0xf0, 0x83, 0x6a, 0x15, 0x4f, 0x81, 0x7f, 0xb1, 0x7f, 0x33, 0x97, 0xe7, 0x25, 0xa3 }, + { 0xc6, 0x08, 0x97, 0xc6, 0xf8, 0x28, 0xe2, 0x1f, 0x16, 0xfb, 0xb5, 0xf1, 0x5b, 0x32, 0x3f, 0x87, 0xb6, 0xc8, 0x95, 0x5e, 0xab, 0xf1, 0xd3, 0x80, 0x61, 0xf7, 0x07, 0xf6, 0x08, 0xab, 0xdd, 0x99, 0x3f, 0xac, 0x30, 0x70, 0x63, 0x3e, 0x28, 0x6c, 0xf8, 0x33, 0x9c, 0xe2, 0x95, 0xdd, 0x35, 0x2d, 0xf4, 0xb4, 0xb4, 0x0b, 0x2f, 0x29, 0xda, 0x1d, 0xd5, 0x0b, 0x3a, 0x05, 0xd0, 0x79, 0xe6, 0xbb }, + { 0x82, 0x10, 0xcd, 0x2c, 0x2d, 0x3b, 0x13, 0x5c, 0x2c, 0xf0, 0x7f, 0xa0, 0xd1, 0x43, 0x3c, 0xd7, 0x71, 0xf3, 0x25, 0xd0, 0x75, 0xc6, 0x46, 0x9d, 0x9c, 0x7f, 0x1b, 0xa0, 0x94, 0x3c, 0xd4, 0xab, 0x09, 0x80, 0x8c, 0xab, 0xf4, 0xac, 0xb9, 0xce, 0x5b, 0xb8, 0x8b, 0x49, 0x89, 0x29, 0xb4, 0xb8, 0x47, 0xf6, 0x81, 0xad, 0x2c, 0x49, 0x0d, 0x04, 0x2d, 0xb2, 0xae, 0xc9, 0x42, 0x14, 0xb0, 0x6b }, + { 0x1d, 0x4e, 0xdf, 0xff, 0xd8, 0xfd, 0x80, 0xf7, 0xe4, 0x10, 0x78, 0x40, 0xfa, 0x3a, 0xa3, 0x1e, 0x32, 0x59, 0x84, 0x91, 0xe4, 0xaf, 0x70, 0x13, 0xc1, 0x97, 0xa6, 0x5b, 0x7f, 0x36, 0xdd, 0x3a, 0xc4, 0xb4, 0x78, 0x45, 0x61, 0x11, 0xcd, 0x43, 0x09, 0xd9, 0x24, 0x35, 0x10, 0x78, 0x2f, 0xa3, 0x1b, 0x7c, 0x4c, 0x95, 0xfa, 0x95, 0x15, 0x20, 0xd0, 0x20, 0xeb, 0x7e, 0x5c, 0x36, 0xe4, 0xef }, + { 0xaf, 0x8e, 0x6e, 0x91, 0xfa, 0xb4, 0x6c, 0xe4, 0x87, 0x3e, 0x1a, 0x50, 0xa8, 0xef, 0x44, 0x8c, 0xc2, 0x91, 0x21, 0xf7, 0xf7, 0x4d, 0xee, 0xf3, 0x4a, 0x71, 0xef, 0x89, 0xcc, 0x00, 0xd9, 0x27, 0x4b, 0xc6, 0xc2, 0x45, 0x4b, 0xbb, 0x32, 0x30, 0xd8, 0xb2, 0xec, 0x94, 0xc6, 0x2b, 0x1d, 0xec, 0x85, 0xf3, 0x59, 0x3b, 0xfa, 0x30, 0xea, 0x6f, 0x7a, 0x44, 0xd7, 0xc0, 0x94, 0x65, 0xa2, 0x53 }, + { 0x29, 0xfd, 0x38, 0x4e, 0xd4, 0x90, 0x6f, 0x2d, 0x13, 0xaa, 0x9f, 0xe7, 0xaf, 0x90, 0x59, 0x90, 0x93, 0x8b, 0xed, 0x80, 0x7f, 0x18, 0x32, 0x45, 0x4a, 0x37, 0x2a, 0xb4, 0x12, 0xee, 0xa1, 0xf5, 0x62, 0x5a, 0x1f, 0xcc, 0x9a, 0xc8, 0x34, 0x3b, 0x7c, 0x67, 0xc5, 0xab, 0xa6, 0xe0, 0xb1, 0xcc, 0x46, 0x44, 0x65, 0x49, 0x13, 0x69, 0x2c, 0x6b, 0x39, 0xeb, 0x91, 0x87, 0xce, 0xac, 0xd3, 0xec }, + { 0xa2, 0x68, 0xc7, 0x88, 0x5d, 0x98, 0x74, 0xa5, 0x1c, 0x44, 0xdf, 0xfe, 0xd8, 0xea, 0x53, 0xe9, 0x4f, 0x78, 0x45, 0x6e, 0x0b, 0x2e, 0xd9, 0x9f, 0xf5, 0xa3, 0x92, 0x47, 0x60, 0x81, 0x38, 0x26, 0xd9, 0x60, 0xa1, 0x5e, 0xdb, 0xed, 0xbb, 0x5d, 0xe5, 0x22, 0x6b, 0xa4, 0xb0, 0x74, 0xe7, 0x1b, 0x05, 0xc5, 0x5b, 0x97, 0x56, 0xbb, 0x79, 0xe5, 0x5c, 0x02, 0x75, 0x4c, 0x2c, 0x7b, 0x6c, 0x8a }, + { 0x0c, 0xf8, 0x54, 0x54, 0x88, 0xd5, 0x6a, 0x86, 0x81, 0x7c, 0xd7, 0xec, 0xb1, 0x0f, 0x71, 0x16, 0xb7, 0xea, 0x53, 0x0a, 0x45, 0xb6, 0xea, 0x49, 0x7b, 0x6c, 0x72, 0xc9, 0x97, 0xe0, 0x9e, 0x3d, 0x0d, 0xa8, 0x69, 0x8f, 0x46, 0xbb, 0x00, 0x6f, 0xc9, 0x77, 0xc2, 0xcd, 0x3d, 0x11, 0x77, 0x46, 0x3a, 0xc9, 0x05, 0x7f, 0xdd, 0x16, 0x62, 0xc8, 0x5d, 0x0c, 0x12, 0x64, 0x43, 0xc1, 0x04, 0x73 }, + { 0xb3, 0x96, 0x14, 0x26, 0x8f, 0xdd, 0x87, 0x81, 0x51, 0x5e, 0x2c, 0xfe, 0xbf, 0x89, 0xb4, 0xd5, 0x40, 0x2b, 0xab, 0x10, 0xc2, 0x26, 0xe6, 0x34, 0x4e, 0x6b, 0x9a, 0xe0, 0x00, 0xfb, 0x0d, 0x6c, 0x79, 0xcb, 0x2f, 0x3e, 0xc8, 0x0e, 0x80, 0xea, 0xeb, 0x19, 0x80, 0xd2, 0xf8, 0x69, 0x89, 0x16, 0xbd, 0x2e, 0x9f, 0x74, 0x72, 0x36, 0x65, 0x51, 0x16, 0x64, 0x9c, 0xd3, 0xca, 0x23, 0xa8, 0x37 }, + { 0x74, 0xbe, 0xf0, 0x92, 0xfc, 0x6f, 0x1e, 0x5d, 0xba, 0x36, 0x63, 0xa3, 0xfb, 0x00, 0x3b, 0x2a, 0x5b, 0xa2, 0x57, 0x49, 0x65, 0x36, 0xd9, 0x9f, 0x62, 0xb9, 0xd7, 0x3f, 0x8f, 0x9e, 0xb3, 0xce, 0x9f, 0xf3, 0xee, 0xc7, 0x09, 0xeb, 0x88, 0x36, 0x55, 0xec, 0x9e, 0xb8, 0x96, 0xb9, 0x12, 0x8f, 0x2a, 0xfc, 0x89, 0xcf, 0x7d, 0x1a, 0xb5, 0x8a, 0x72, 0xf4, 0xa3, 0xbf, 0x03, 0x4d, 0x2b, 0x4a }, + { 0x3a, 0x98, 0x8d, 0x38, 0xd7, 0x56, 0x11, 0xf3, 0xef, 0x38, 0xb8, 0x77, 0x49, 0x80, 0xb3, 0x3e, 0x57, 0x3b, 0x6c, 0x57, 0xbe, 0xe0, 0x46, 0x9b, 0xa5, 0xee, 0xd9, 0xb4, 0x4f, 0x29, 0x94, 0x5e, 0x73, 0x47, 0x96, 0x7f, 0xba, 0x2c, 0x16, 0x2e, 0x1c, 0x3b, 0xe7, 0xf3, 0x10, 0xf2, 0xf7, 0x5e, 0xe2, 0x38, 0x1e, 0x7b, 0xfd, 0x6b, 0x3f, 0x0b, 0xae, 0xa8, 0xd9, 0x5d, 0xfb, 0x1d, 0xaf, 0xb1 }, + { 0x58, 0xae, 0xdf, 0xce, 0x6f, 0x67, 0xdd, 0xc8, 0x5a, 0x28, 0xc9, 0x92, 0xf1, 0xc0, 0xbd, 0x09, 0x69, 0xf0, 0x41, 0xe6, 0x6f, 0x1e, 0xe8, 0x80, 0x20, 0xa1, 0x25, 0xcb, 0xfc, 0xfe, 0xbc, 0xd6, 0x17, 0x09, 0xc9, 0xc4, 0xeb, 0xa1, 0x92, 0xc1, 0x5e, 0x69, 0xf0, 0x20, 0xd4, 0x62, 0x48, 0x60, 0x19, 0xfa, 0x8d, 0xea, 0x0c, 0xd7, 0xa4, 0x29, 0x21, 0xa1, 0x9d, 0x2f, 0xe5, 0x46, 0xd4, 0x3d }, + { 0x93, 0x47, 0xbd, 0x29, 0x14, 0x73, 0xe6, 0xb4, 0xe3, 0x68, 0x43, 0x7b, 0x8e, 0x56, 0x1e, 0x06, 0x5f, 0x64, 0x9a, 0x6d, 0x8a, 0xda, 0x47, 0x9a, 0xd0, 0x9b, 0x19, 0x99, 0xa8, 0xf2, 0x6b, 0x91, 0xcf, 0x61, 0x20, 0xfd, 0x3b, 0xfe, 0x01, 0x4e, 0x83, 0xf2, 0x3a, 0xcf, 0xa4, 0xc0, 0xad, 0x7b, 0x37, 0x12, 0xb2, 0xc3, 0xc0, 0x73, 0x32, 0x70, 0x66, 0x31, 0x12, 0xcc, 0xd9, 0x28, 0x5c, 0xd9 }, + { 0xb3, 0x21, 0x63, 0xe7, 0xc5, 0xdb, 0xb5, 0xf5, 0x1f, 0xdc, 0x11, 0xd2, 0xea, 0xc8, 0x75, 0xef, 0xbb, 0xcb, 0x7e, 0x76, 0x99, 0x09, 0x0a, 0x7e, 0x7f, 0xf8, 0xa8, 0xd5, 0x07, 0x95, 0xaf, 0x5d, 0x74, 0xd9, 0xff, 0x98, 0x54, 0x3e, 0xf8, 0xcd, 0xf8, 0x9a, 0xc1, 0x3d, 0x04, 0x85, 0x27, 0x87, 0x56, 0xe0, 0xef, 0x00, 0xc8, 0x17, 0x74, 0x56, 0x61, 0xe1, 0xd5, 0x9f, 0xe3, 0x8e, 0x75, 0x37 }, + { 0x10, 0x85, 0xd7, 0x83, 0x07, 0xb1, 0xc4, 0xb0, 0x08, 0xc5, 0x7a, 0x2e, 0x7e, 0x5b, 0x23, 0x46, 0x58, 0xa0, 0xa8, 0x2e, 0x4f, 0xf1, 0xe4, 0xaa, 0xac, 0x72, 0xb3, 0x12, 0xfd, 0xa0, 0xfe, 0x27, 0xd2, 0x33, 0xbc, 0x5b, 0x10, 0xe9, 0xcc, 0x17, 0xfd, 0xc7, 0x69, 0x7b, 0x54, 0x0c, 0x7d, 0x95, 0xeb, 0x21, 0x5a, 0x19, 0xa1, 0xa0, 0xe2, 0x0e, 0x1a, 0xbf, 0xa1, 0x26, 0xef, 0xd5, 0x68, 0xc7 }, + { 0x4e, 0x5c, 0x73, 0x4c, 0x7d, 0xde, 0x01, 0x1d, 0x83, 0xea, 0xc2, 0xb7, 0x34, 0x7b, 0x37, 0x35, 0x94, 0xf9, 0x2d, 0x70, 0x91, 0xb9, 0xca, 0x34, 0xcb, 0x9c, 0x6f, 0x39, 0xbd, 0xf5, 0xa8, 0xd2, 0xf1, 0x34, 0x37, 0x9e, 0x16, 0xd8, 0x22, 0xf6, 0x52, 0x21, 0x70, 0xcc, 0xf2, 0xdd, 0xd5, 0x5c, 0x84, 0xb9, 0xe6, 0xc6, 0x4f, 0xc9, 0x27, 0xac, 0x4c, 0xf8, 0xdf, 0xb2, 0xa1, 0x77, 0x01, 0xf2 }, + { 0x69, 0x5d, 0x83, 0xbd, 0x99, 0x0a, 0x11, 0x17, 0xb3, 0xd0, 0xce, 0x06, 0xcc, 0x88, 0x80, 0x27, 0xd1, 0x2a, 0x05, 0x4c, 0x26, 0x77, 0xfd, 0x82, 0xf0, 0xd4, 0xfb, 0xfc, 0x93, 0x57, 0x55, 0x23, 0xe7, 0x99, 0x1a, 0x5e, 0x35, 0xa3, 0x75, 0x2e, 0x9b, 0x70, 0xce, 0x62, 0x99, 0x2e, 0x26, 0x8a, 0x87, 0x77, 0x44, 0xcd, 0xd4, 0x35, 0xf5, 0xf1, 0x30, 0x86, 0x9c, 0x9a, 0x20, 0x74, 0xb3, 0x38 }, + { 0xa6, 0x21, 0x37, 0x43, 0x56, 0x8e, 0x3b, 0x31, 0x58, 0xb9, 0x18, 0x43, 0x01, 0xf3, 0x69, 0x08, 0x47, 0x55, 0x4c, 0x68, 0x45, 0x7c, 0xb4, 0x0f, 0xc9, 0xa4, 0xb8, 0xcf, 0xd8, 0xd4, 0xa1, 0x18, 0xc3, 0x01, 0xa0, 0x77, 0x37, 0xae, 0xda, 0x0f, 0x92, 0x9c, 0x68, 0x91, 0x3c, 0x5f, 0x51, 0xc8, 0x03, 0x94, 0xf5, 0x3b, 0xff, 0x1c, 0x3e, 0x83, 0xb2, 0xe4, 0x0c, 0xa9, 0x7e, 0xba, 0x9e, 0x15 }, + { 0xd4, 0x44, 0xbf, 0xa2, 0x36, 0x2a, 0x96, 0xdf, 0x21, 0x3d, 0x07, 0x0e, 0x33, 0xfa, 0x84, 0x1f, 0x51, 0x33, 0x4e, 0x4e, 0x76, 0x86, 0x6b, 0x81, 0x39, 0xe8, 0xaf, 0x3b, 0xb3, 0x39, 0x8b, 0xe2, 0xdf, 0xad, 0xdc, 0xbc, 0x56, 0xb9, 0x14, 0x6d, 0xe9, 0xf6, 0x81, 0x18, 0xdc, 0x58, 0x29, 0xe7, 0x4b, 0x0c, 0x28, 0xd7, 0x71, 0x19, 0x07, 0xb1, 0x21, 0xf9, 0x16, 0x1c, 0xb9, 0x2b, 0x69, 0xa9 }, + { 0x14, 0x27, 0x09, 0xd6, 0x2e, 0x28, 0xfc, 0xcc, 0xd0, 0xaf, 0x97, 0xfa, 0xd0, 0xf8, 0x46, 0x5b, 0x97, 0x1e, 0x82, 0x20, 0x1d, 0xc5, 0x10, 0x70, 0xfa, 0xa0, 0x37, 0x2a, 0xa4, 0x3e, 0x92, 0x48, 0x4b, 0xe1, 0xc1, 0xe7, 0x3b, 0xa1, 0x09, 0x06, 0xd5, 0xd1, 0x85, 0x3d, 0xb6, 0xa4, 0x10, 0x6e, 0x0a, 0x7b, 0xf9, 0x80, 0x0d, 0x37, 0x3d, 0x6d, 0xee, 0x2d, 0x46, 0xd6, 0x2e, 0xf2, 0xa4, 0x61 }, + }; + unsigned char inp[1000], out[1000]; + unsigned char key[] = { 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 }; + unsigned long ilen, klen = sizeof(key), mlen = 64; + blake2bmac_state st; + + for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen; + + for (ilen = 0; ilen < 256; ilen++) { + const unsigned char *mac = tests[ilen]; + unsigned long olen = mlen; + /* process piece by piece */ + if (ilen > 15) { + blake2bmac_init(&st, olen, key, klen); + blake2bmac_process(&st, (unsigned char*)inp, 5); + blake2bmac_process(&st, (unsigned char*)inp + 5, 4); + blake2bmac_process(&st, (unsigned char*)inp + 9, 3); + blake2bmac_process(&st, (unsigned char*)inp + 12, 2); + blake2bmac_process(&st, (unsigned char*)inp + 14, 1); + blake2bmac_process(&st, (unsigned char*)inp + 15, ilen - 15); + blake2bmac_done(&st, out, &olen); + if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; + } + /* process in one go */ + blake2bmac_init(&st, olen, key, klen); + blake2bmac_process(&st, (unsigned char*)inp, ilen); + blake2bmac_done(&st, out, &olen); + if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c new file mode 100644 index 0000000..f42c7ae --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2SMAC + +/** + Initialize an BLAKE2S MAC context. + @param st The BLAKE2S MAC state + @param outlen The size of the MAC output (octets) + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + return blake2s_init(st, outlen, key, keylen); +} + +/** + Process data through BLAKE2S MAC + @param st The BLAKE2S MAC state + @param in The data to send through HMAC + @param inlen The length of the data to HMAC (octets) + @return CRYPT_OK if successful +*/ +int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen) +{ + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + return blake2s_process(st, in, inlen); +} + +/** + Terminate a BLAKE2S MAC session + @param st The BLAKE2S MAC state + @param mac [out] The destination of the BLAKE2S MAC authentication tag + @param maclen [in/out] The max size and resulting size of the BLAKE2S MAC authentication tag + @return CRYPT_OK if successful +*/ +int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + LTC_ARGCHK(*maclen >= st->blake2s.outlen); + + *maclen = st->blake2s.outlen; + return blake2s_done(st, mac); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_file.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_file.c new file mode 100644 index 0000000..bcfbe06 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_file.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2SMAC + +/** + BLAKE2S MAC a file + @param fname The name of the file you wish to BLAKE2S MAC + @param key The secret key + @param keylen The length of the secret key + @param mac [out] The BLAKE2S MAC authentication tag + @param maclen [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 blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); + return CRYPT_NOP; +#else + blake2smac_state st; + FILE *in; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = blake2smac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = blake2smac_done(&st, mac, maclen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2smac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c new file mode 100644 index 0000000..755267b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2SMAC + +/** + BLAKE2S MAC a block of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to BLAKE2S MAC + @param inlen The length of the data to BLAKE2S MAC (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) +{ + blake2smac_state st; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = blake2smac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + err = blake2smac_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2smac_state)); +#endif + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c new file mode 100644 index 0000000..34fb5e1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" +#include + +#ifdef LTC_BLAKE2SMAC + +/** + BLAKE2S MAC multiple blocks of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @param in The data to BLAKE2S MAC + @param inlen The length of the data to BLAKE2S MAC (octets) + @param ... tuples of (data,len) pairs to BLAKE2S MAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) +{ + blake2smac_state st; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + va_start(args, inlen); + curptr = in; + curlen = inlen; + if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + for (;;) { + if ((err = blake2smac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) break; + curlen = va_arg(args, unsigned long); + } + err = blake2smac_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2smac_state)); +#endif + va_end(args); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c new file mode 100644 index 0000000..acfb030 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c @@ -0,0 +1,304 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2SMAC + +int blake2smac_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const unsigned char tests[256][32] = { + /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2s-kat.txt */ + { 0x48, 0xa8, 0x99, 0x7d, 0xa4, 0x07, 0x87, 0x6b, 0x3d, 0x79, 0xc0, 0xd9, 0x23, 0x25, 0xad, 0x3b, 0x89, 0xcb, 0xb7, 0x54, 0xd8, 0x6a, 0xb7, 0x1a, 0xee, 0x04, 0x7a, 0xd3, 0x45, 0xfd, 0x2c, 0x49 }, + { 0x40, 0xd1, 0x5f, 0xee, 0x7c, 0x32, 0x88, 0x30, 0x16, 0x6a, 0xc3, 0xf9, 0x18, 0x65, 0x0f, 0x80, 0x7e, 0x7e, 0x01, 0xe1, 0x77, 0x25, 0x8c, 0xdc, 0x0a, 0x39, 0xb1, 0x1f, 0x59, 0x80, 0x66, 0xf1 }, + { 0x6b, 0xb7, 0x13, 0x00, 0x64, 0x4c, 0xd3, 0x99, 0x1b, 0x26, 0xcc, 0xd4, 0xd2, 0x74, 0xac, 0xd1, 0xad, 0xea, 0xb8, 0xb1, 0xd7, 0x91, 0x45, 0x46, 0xc1, 0x19, 0x8b, 0xbe, 0x9f, 0xc9, 0xd8, 0x03 }, + { 0x1d, 0x22, 0x0d, 0xbe, 0x2e, 0xe1, 0x34, 0x66, 0x1f, 0xdf, 0x6d, 0x9e, 0x74, 0xb4, 0x17, 0x04, 0x71, 0x05, 0x56, 0xf2, 0xf6, 0xe5, 0xa0, 0x91, 0xb2, 0x27, 0x69, 0x74, 0x45, 0xdb, 0xea, 0x6b }, + { 0xf6, 0xc3, 0xfb, 0xad, 0xb4, 0xcc, 0x68, 0x7a, 0x00, 0x64, 0xa5, 0xbe, 0x6e, 0x79, 0x1b, 0xec, 0x63, 0xb8, 0x68, 0xad, 0x62, 0xfb, 0xa6, 0x1b, 0x37, 0x57, 0xef, 0x9c, 0xa5, 0x2e, 0x05, 0xb2 }, + { 0x49, 0xc1, 0xf2, 0x11, 0x88, 0xdf, 0xd7, 0x69, 0xae, 0xa0, 0xe9, 0x11, 0xdd, 0x6b, 0x41, 0xf1, 0x4d, 0xab, 0x10, 0x9d, 0x2b, 0x85, 0x97, 0x7a, 0xa3, 0x08, 0x8b, 0x5c, 0x70, 0x7e, 0x85, 0x98 }, + { 0xfd, 0xd8, 0x99, 0x3d, 0xcd, 0x43, 0xf6, 0x96, 0xd4, 0x4f, 0x3c, 0xea, 0x0f, 0xf3, 0x53, 0x45, 0x23, 0x4e, 0xc8, 0xee, 0x08, 0x3e, 0xb3, 0xca, 0xda, 0x01, 0x7c, 0x7f, 0x78, 0xc1, 0x71, 0x43 }, + { 0xe6, 0xc8, 0x12, 0x56, 0x37, 0x43, 0x8d, 0x09, 0x05, 0xb7, 0x49, 0xf4, 0x65, 0x60, 0xac, 0x89, 0xfd, 0x47, 0x1c, 0xf8, 0x69, 0x2e, 0x28, 0xfa, 0xb9, 0x82, 0xf7, 0x3f, 0x01, 0x9b, 0x83, 0xa9 }, + { 0x19, 0xfc, 0x8c, 0xa6, 0x97, 0x9d, 0x60, 0xe6, 0xed, 0xd3, 0xb4, 0x54, 0x1e, 0x2f, 0x96, 0x7c, 0xed, 0x74, 0x0d, 0xf6, 0xec, 0x1e, 0xae, 0xbb, 0xfe, 0x81, 0x38, 0x32, 0xe9, 0x6b, 0x29, 0x74 }, + { 0xa6, 0xad, 0x77, 0x7c, 0xe8, 0x81, 0xb5, 0x2b, 0xb5, 0xa4, 0x42, 0x1a, 0xb6, 0xcd, 0xd2, 0xdf, 0xba, 0x13, 0xe9, 0x63, 0x65, 0x2d, 0x4d, 0x6d, 0x12, 0x2a, 0xee, 0x46, 0x54, 0x8c, 0x14, 0xa7 }, + { 0xf5, 0xc4, 0xb2, 0xba, 0x1a, 0x00, 0x78, 0x1b, 0x13, 0xab, 0xa0, 0x42, 0x52, 0x42, 0xc6, 0x9c, 0xb1, 0x55, 0x2f, 0x3f, 0x71, 0xa9, 0xa3, 0xbb, 0x22, 0xb4, 0xa6, 0xb4, 0x27, 0x7b, 0x46, 0xdd }, + { 0xe3, 0x3c, 0x4c, 0x9b, 0xd0, 0xcc, 0x7e, 0x45, 0xc8, 0x0e, 0x65, 0xc7, 0x7f, 0xa5, 0x99, 0x7f, 0xec, 0x70, 0x02, 0x73, 0x85, 0x41, 0x50, 0x9e, 0x68, 0xa9, 0x42, 0x38, 0x91, 0xe8, 0x22, 0xa3 }, + { 0xfb, 0xa1, 0x61, 0x69, 0xb2, 0xc3, 0xee, 0x10, 0x5b, 0xe6, 0xe1, 0xe6, 0x50, 0xe5, 0xcb, 0xf4, 0x07, 0x46, 0xb6, 0x75, 0x3d, 0x03, 0x6a, 0xb5, 0x51, 0x79, 0x01, 0x4a, 0xd7, 0xef, 0x66, 0x51 }, + { 0xf5, 0xc4, 0xbe, 0xc6, 0xd6, 0x2f, 0xc6, 0x08, 0xbf, 0x41, 0xcc, 0x11, 0x5f, 0x16, 0xd6, 0x1c, 0x7e, 0xfd, 0x3f, 0xf6, 0xc6, 0x56, 0x92, 0xbb, 0xe0, 0xaf, 0xff, 0xb1, 0xfe, 0xde, 0x74, 0x75 }, + { 0xa4, 0x86, 0x2e, 0x76, 0xdb, 0x84, 0x7f, 0x05, 0xba, 0x17, 0xed, 0xe5, 0xda, 0x4e, 0x7f, 0x91, 0xb5, 0x92, 0x5c, 0xf1, 0xad, 0x4b, 0xa1, 0x27, 0x32, 0xc3, 0x99, 0x57, 0x42, 0xa5, 0xcd, 0x6e }, + { 0x65, 0xf4, 0xb8, 0x60, 0xcd, 0x15, 0xb3, 0x8e, 0xf8, 0x14, 0xa1, 0xa8, 0x04, 0x31, 0x4a, 0x55, 0xbe, 0x95, 0x3c, 0xaa, 0x65, 0xfd, 0x75, 0x8a, 0xd9, 0x89, 0xff, 0x34, 0xa4, 0x1c, 0x1e, 0xea }, + { 0x19, 0xba, 0x23, 0x4f, 0x0a, 0x4f, 0x38, 0x63, 0x7d, 0x18, 0x39, 0xf9, 0xd9, 0xf7, 0x6a, 0xd9, 0x1c, 0x85, 0x22, 0x30, 0x71, 0x43, 0xc9, 0x7d, 0x5f, 0x93, 0xf6, 0x92, 0x74, 0xce, 0xc9, 0xa7 }, + { 0x1a, 0x67, 0x18, 0x6c, 0xa4, 0xa5, 0xcb, 0x8e, 0x65, 0xfc, 0xa0, 0xe2, 0xec, 0xbc, 0x5d, 0xdc, 0x14, 0xae, 0x38, 0x1b, 0xb8, 0xbf, 0xfe, 0xb9, 0xe0, 0xa1, 0x03, 0x44, 0x9e, 0x3e, 0xf0, 0x3c }, + { 0xaf, 0xbe, 0xa3, 0x17, 0xb5, 0xa2, 0xe8, 0x9c, 0x0b, 0xd9, 0x0c, 0xcf, 0x5d, 0x7f, 0xd0, 0xed, 0x57, 0xfe, 0x58, 0x5e, 0x4b, 0xe3, 0x27, 0x1b, 0x0a, 0x6b, 0xf0, 0xf5, 0x78, 0x6b, 0x0f, 0x26 }, + { 0xf1, 0xb0, 0x15, 0x58, 0xce, 0x54, 0x12, 0x62, 0xf5, 0xec, 0x34, 0x29, 0x9d, 0x6f, 0xb4, 0x09, 0x00, 0x09, 0xe3, 0x43, 0x4b, 0xe2, 0xf4, 0x91, 0x05, 0xcf, 0x46, 0xaf, 0x4d, 0x2d, 0x41, 0x24 }, + { 0x13, 0xa0, 0xa0, 0xc8, 0x63, 0x35, 0x63, 0x5e, 0xaa, 0x74, 0xca, 0x2d, 0x5d, 0x48, 0x8c, 0x79, 0x7b, 0xbb, 0x4f, 0x47, 0xdc, 0x07, 0x10, 0x50, 0x15, 0xed, 0x6a, 0x1f, 0x33, 0x09, 0xef, 0xce }, + { 0x15, 0x80, 0xaf, 0xee, 0xbe, 0xbb, 0x34, 0x6f, 0x94, 0xd5, 0x9f, 0xe6, 0x2d, 0xa0, 0xb7, 0x92, 0x37, 0xea, 0xd7, 0xb1, 0x49, 0x1f, 0x56, 0x67, 0xa9, 0x0e, 0x45, 0xed, 0xf6, 0xca, 0x8b, 0x03 }, + { 0x20, 0xbe, 0x1a, 0x87, 0x5b, 0x38, 0xc5, 0x73, 0xdd, 0x7f, 0xaa, 0xa0, 0xde, 0x48, 0x9d, 0x65, 0x5c, 0x11, 0xef, 0xb6, 0xa5, 0x52, 0x69, 0x8e, 0x07, 0xa2, 0xd3, 0x31, 0xb5, 0xf6, 0x55, 0xc3 }, + { 0xbe, 0x1f, 0xe3, 0xc4, 0xc0, 0x40, 0x18, 0xc5, 0x4c, 0x4a, 0x0f, 0x6b, 0x9a, 0x2e, 0xd3, 0xc5, 0x3a, 0xbe, 0x3a, 0x9f, 0x76, 0xb4, 0xd2, 0x6d, 0xe5, 0x6f, 0xc9, 0xae, 0x95, 0x05, 0x9a, 0x99 }, + { 0xe3, 0xe3, 0xac, 0xe5, 0x37, 0xeb, 0x3e, 0xdd, 0x84, 0x63, 0xd9, 0xad, 0x35, 0x82, 0xe1, 0x3c, 0xf8, 0x65, 0x33, 0xff, 0xde, 0x43, 0xd6, 0x68, 0xdd, 0x2e, 0x93, 0xbb, 0xdb, 0xd7, 0x19, 0x5a }, + { 0x11, 0x0c, 0x50, 0xc0, 0xbf, 0x2c, 0x6e, 0x7a, 0xeb, 0x7e, 0x43, 0x5d, 0x92, 0xd1, 0x32, 0xab, 0x66, 0x55, 0x16, 0x8e, 0x78, 0xa2, 0xde, 0xcd, 0xec, 0x33, 0x30, 0x77, 0x76, 0x84, 0xd9, 0xc1 }, + { 0xe9, 0xba, 0x8f, 0x50, 0x5c, 0x9c, 0x80, 0xc0, 0x86, 0x66, 0xa7, 0x01, 0xf3, 0x36, 0x7e, 0x6c, 0xc6, 0x65, 0xf3, 0x4b, 0x22, 0xe7, 0x3c, 0x3c, 0x04, 0x17, 0xeb, 0x1c, 0x22, 0x06, 0x08, 0x2f }, + { 0x26, 0xcd, 0x66, 0xfc, 0xa0, 0x23, 0x79, 0xc7, 0x6d, 0xf1, 0x23, 0x17, 0x05, 0x2b, 0xca, 0xfd, 0x6c, 0xd8, 0xc3, 0xa7, 0xb8, 0x90, 0xd8, 0x05, 0xf3, 0x6c, 0x49, 0x98, 0x97, 0x82, 0x43, 0x3a }, + { 0x21, 0x3f, 0x35, 0x96, 0xd6, 0xe3, 0xa5, 0xd0, 0xe9, 0x93, 0x2c, 0xd2, 0x15, 0x91, 0x46, 0x01, 0x5e, 0x2a, 0xbc, 0x94, 0x9f, 0x47, 0x29, 0xee, 0x26, 0x32, 0xfe, 0x1e, 0xdb, 0x78, 0xd3, 0x37 }, + { 0x10, 0x15, 0xd7, 0x01, 0x08, 0xe0, 0x3b, 0xe1, 0xc7, 0x02, 0xfe, 0x97, 0x25, 0x36, 0x07, 0xd1, 0x4a, 0xee, 0x59, 0x1f, 0x24, 0x13, 0xea, 0x67, 0x87, 0x42, 0x7b, 0x64, 0x59, 0xff, 0x21, 0x9a }, + { 0x3c, 0xa9, 0x89, 0xde, 0x10, 0xcf, 0xe6, 0x09, 0x90, 0x94, 0x72, 0xc8, 0xd3, 0x56, 0x10, 0x80, 0x5b, 0x2f, 0x97, 0x77, 0x34, 0xcf, 0x65, 0x2c, 0xc6, 0x4b, 0x3b, 0xfc, 0x88, 0x2d, 0x5d, 0x89 }, + { 0xb6, 0x15, 0x6f, 0x72, 0xd3, 0x80, 0xee, 0x9e, 0xa6, 0xac, 0xd1, 0x90, 0x46, 0x4f, 0x23, 0x07, 0xa5, 0xc1, 0x79, 0xef, 0x01, 0xfd, 0x71, 0xf9, 0x9f, 0x2d, 0x0f, 0x7a, 0x57, 0x36, 0x0a, 0xea }, + { 0xc0, 0x3b, 0xc6, 0x42, 0xb2, 0x09, 0x59, 0xcb, 0xe1, 0x33, 0xa0, 0x30, 0x3e, 0x0c, 0x1a, 0xbf, 0xf3, 0xe3, 0x1e, 0xc8, 0xe1, 0xa3, 0x28, 0xec, 0x85, 0x65, 0xc3, 0x6d, 0xec, 0xff, 0x52, 0x65 }, + { 0x2c, 0x3e, 0x08, 0x17, 0x6f, 0x76, 0x0c, 0x62, 0x64, 0xc3, 0xa2, 0xcd, 0x66, 0xfe, 0xc6, 0xc3, 0xd7, 0x8d, 0xe4, 0x3f, 0xc1, 0x92, 0x45, 0x7b, 0x2a, 0x4a, 0x66, 0x0a, 0x1e, 0x0e, 0xb2, 0x2b }, + { 0xf7, 0x38, 0xc0, 0x2f, 0x3c, 0x1b, 0x19, 0x0c, 0x51, 0x2b, 0x1a, 0x32, 0xde, 0xab, 0xf3, 0x53, 0x72, 0x8e, 0x0e, 0x9a, 0xb0, 0x34, 0x49, 0x0e, 0x3c, 0x34, 0x09, 0x94, 0x6a, 0x97, 0xae, 0xec }, + { 0x8b, 0x18, 0x80, 0xdf, 0x30, 0x1c, 0xc9, 0x63, 0x41, 0x88, 0x11, 0x08, 0x89, 0x64, 0x83, 0x92, 0x87, 0xff, 0x7f, 0xe3, 0x1c, 0x49, 0xea, 0x6e, 0xbd, 0x9e, 0x48, 0xbd, 0xee, 0xe4, 0x97, 0xc5 }, + { 0x1e, 0x75, 0xcb, 0x21, 0xc6, 0x09, 0x89, 0x02, 0x03, 0x75, 0xf1, 0xa7, 0xa2, 0x42, 0x83, 0x9f, 0x0b, 0x0b, 0x68, 0x97, 0x3a, 0x4c, 0x2a, 0x05, 0xcf, 0x75, 0x55, 0xed, 0x5a, 0xae, 0xc4, 0xc1 }, + { 0x62, 0xbf, 0x8a, 0x9c, 0x32, 0xa5, 0xbc, 0xcf, 0x29, 0x0b, 0x6c, 0x47, 0x4d, 0x75, 0xb2, 0xa2, 0xa4, 0x09, 0x3f, 0x1a, 0x9e, 0x27, 0x13, 0x94, 0x33, 0xa8, 0xf2, 0xb3, 0xbc, 0xe7, 0xb8, 0xd7 }, + { 0x16, 0x6c, 0x83, 0x50, 0xd3, 0x17, 0x3b, 0x5e, 0x70, 0x2b, 0x78, 0x3d, 0xfd, 0x33, 0xc6, 0x6e, 0xe0, 0x43, 0x27, 0x42, 0xe9, 0xb9, 0x2b, 0x99, 0x7f, 0xd2, 0x3c, 0x60, 0xdc, 0x67, 0x56, 0xca }, + { 0x04, 0x4a, 0x14, 0xd8, 0x22, 0xa9, 0x0c, 0xac, 0xf2, 0xf5, 0xa1, 0x01, 0x42, 0x8a, 0xdc, 0x8f, 0x41, 0x09, 0x38, 0x6c, 0xcb, 0x15, 0x8b, 0xf9, 0x05, 0xc8, 0x61, 0x8b, 0x8e, 0xe2, 0x4e, 0xc3 }, + { 0x38, 0x7d, 0x39, 0x7e, 0xa4, 0x3a, 0x99, 0x4b, 0xe8, 0x4d, 0x2d, 0x54, 0x4a, 0xfb, 0xe4, 0x81, 0xa2, 0x00, 0x0f, 0x55, 0x25, 0x26, 0x96, 0xbb, 0xa2, 0xc5, 0x0c, 0x8e, 0xbd, 0x10, 0x13, 0x47 }, + { 0x56, 0xf8, 0xcc, 0xf1, 0xf8, 0x64, 0x09, 0xb4, 0x6c, 0xe3, 0x61, 0x66, 0xae, 0x91, 0x65, 0x13, 0x84, 0x41, 0x57, 0x75, 0x89, 0xdb, 0x08, 0xcb, 0xc5, 0xf6, 0x6c, 0xa2, 0x97, 0x43, 0xb9, 0xfd }, + { 0x97, 0x06, 0xc0, 0x92, 0xb0, 0x4d, 0x91, 0xf5, 0x3d, 0xff, 0x91, 0xfa, 0x37, 0xb7, 0x49, 0x3d, 0x28, 0xb5, 0x76, 0xb5, 0xd7, 0x10, 0x46, 0x9d, 0xf7, 0x94, 0x01, 0x66, 0x22, 0x36, 0xfc, 0x03 }, + { 0x87, 0x79, 0x68, 0x68, 0x6c, 0x06, 0x8c, 0xe2, 0xf7, 0xe2, 0xad, 0xcf, 0xf6, 0x8b, 0xf8, 0x74, 0x8e, 0xdf, 0x3c, 0xf8, 0x62, 0xcf, 0xb4, 0xd3, 0x94, 0x7a, 0x31, 0x06, 0x95, 0x80, 0x54, 0xe3 }, + { 0x88, 0x17, 0xe5, 0x71, 0x98, 0x79, 0xac, 0xf7, 0x02, 0x47, 0x87, 0xec, 0xcd, 0xb2, 0x71, 0x03, 0x55, 0x66, 0xcf, 0xa3, 0x33, 0xe0, 0x49, 0x40, 0x7c, 0x01, 0x78, 0xcc, 0xc5, 0x7a, 0x5b, 0x9f }, + { 0x89, 0x38, 0x24, 0x9e, 0x4b, 0x50, 0xca, 0xda, 0xcc, 0xdf, 0x5b, 0x18, 0x62, 0x13, 0x26, 0xcb, 0xb1, 0x52, 0x53, 0xe3, 0x3a, 0x20, 0xf5, 0x63, 0x6e, 0x99, 0x5d, 0x72, 0x47, 0x8d, 0xe4, 0x72 }, + { 0xf1, 0x64, 0xab, 0xba, 0x49, 0x63, 0xa4, 0x4d, 0x10, 0x72, 0x57, 0xe3, 0x23, 0x2d, 0x90, 0xac, 0xa5, 0xe6, 0x6a, 0x14, 0x08, 0x24, 0x8c, 0x51, 0x74, 0x1e, 0x99, 0x1d, 0xb5, 0x22, 0x77, 0x56 }, + { 0xd0, 0x55, 0x63, 0xe2, 0xb1, 0xcb, 0xa0, 0xc4, 0xa2, 0xa1, 0xe8, 0xbd, 0xe3, 0xa1, 0xa0, 0xd9, 0xf5, 0xb4, 0x0c, 0x85, 0xa0, 0x70, 0xd6, 0xf5, 0xfb, 0x21, 0x06, 0x6e, 0xad, 0x5d, 0x06, 0x01 }, + { 0x03, 0xfb, 0xb1, 0x63, 0x84, 0xf0, 0xa3, 0x86, 0x6f, 0x4c, 0x31, 0x17, 0x87, 0x76, 0x66, 0xef, 0xbf, 0x12, 0x45, 0x97, 0x56, 0x4b, 0x29, 0x3d, 0x4a, 0xab, 0x0d, 0x26, 0x9f, 0xab, 0xdd, 0xfa }, + { 0x5f, 0xa8, 0x48, 0x6a, 0xc0, 0xe5, 0x29, 0x64, 0xd1, 0x88, 0x1b, 0xbe, 0x33, 0x8e, 0xb5, 0x4b, 0xe2, 0xf7, 0x19, 0x54, 0x92, 0x24, 0x89, 0x20, 0x57, 0xb4, 0xda, 0x04, 0xba, 0x8b, 0x34, 0x75 }, + { 0xcd, 0xfa, 0xbc, 0xee, 0x46, 0x91, 0x11, 0x11, 0x23, 0x6a, 0x31, 0x70, 0x8b, 0x25, 0x39, 0xd7, 0x1f, 0xc2, 0x11, 0xd9, 0xb0, 0x9c, 0x0d, 0x85, 0x30, 0xa1, 0x1e, 0x1d, 0xbf, 0x6e, 0xed, 0x01 }, + { 0x4f, 0x82, 0xde, 0x03, 0xb9, 0x50, 0x47, 0x93, 0xb8, 0x2a, 0x07, 0xa0, 0xbd, 0xcd, 0xff, 0x31, 0x4d, 0x75, 0x9e, 0x7b, 0x62, 0xd2, 0x6b, 0x78, 0x49, 0x46, 0xb0, 0xd3, 0x6f, 0x91, 0x6f, 0x52 }, + { 0x25, 0x9e, 0xc7, 0xf1, 0x73, 0xbc, 0xc7, 0x6a, 0x09, 0x94, 0xc9, 0x67, 0xb4, 0xf5, 0xf0, 0x24, 0xc5, 0x60, 0x57, 0xfb, 0x79, 0xc9, 0x65, 0xc4, 0xfa, 0xe4, 0x18, 0x75, 0xf0, 0x6a, 0x0e, 0x4c }, + { 0x19, 0x3c, 0xc8, 0xe7, 0xc3, 0xe0, 0x8b, 0xb3, 0x0f, 0x54, 0x37, 0xaa, 0x27, 0xad, 0xe1, 0xf1, 0x42, 0x36, 0x9b, 0x24, 0x6a, 0x67, 0x5b, 0x23, 0x83, 0xe6, 0xda, 0x9b, 0x49, 0xa9, 0x80, 0x9e }, + { 0x5c, 0x10, 0x89, 0x6f, 0x0e, 0x28, 0x56, 0xb2, 0xa2, 0xee, 0xe0, 0xfe, 0x4a, 0x2c, 0x16, 0x33, 0x56, 0x5d, 0x18, 0xf0, 0xe9, 0x3e, 0x1f, 0xab, 0x26, 0xc3, 0x73, 0xe8, 0xf8, 0x29, 0x65, 0x4d }, + { 0xf1, 0x60, 0x12, 0xd9, 0x3f, 0x28, 0x85, 0x1a, 0x1e, 0xb9, 0x89, 0xf5, 0xd0, 0xb4, 0x3f, 0x3f, 0x39, 0xca, 0x73, 0xc9, 0xa6, 0x2d, 0x51, 0x81, 0xbf, 0xf2, 0x37, 0x53, 0x6b, 0xd3, 0x48, 0xc3 }, + { 0x29, 0x66, 0xb3, 0xcf, 0xae, 0x1e, 0x44, 0xea, 0x99, 0x6d, 0xc5, 0xd6, 0x86, 0xcf, 0x25, 0xfa, 0x05, 0x3f, 0xb6, 0xf6, 0x72, 0x01, 0xb9, 0xe4, 0x6e, 0xad, 0xe8, 0x5d, 0x0a, 0xd6, 0xb8, 0x06 }, + { 0xdd, 0xb8, 0x78, 0x24, 0x85, 0xe9, 0x00, 0xbc, 0x60, 0xbc, 0xf4, 0xc3, 0x3a, 0x6f, 0xd5, 0x85, 0x68, 0x0c, 0xc6, 0x83, 0xd5, 0x16, 0xef, 0xa0, 0x3e, 0xb9, 0x98, 0x5f, 0xad, 0x87, 0x15, 0xfb }, + { 0x4c, 0x4d, 0x6e, 0x71, 0xae, 0xa0, 0x57, 0x86, 0x41, 0x31, 0x48, 0xfc, 0x7a, 0x78, 0x6b, 0x0e, 0xca, 0xf5, 0x82, 0xcf, 0xf1, 0x20, 0x9f, 0x5a, 0x80, 0x9f, 0xba, 0x85, 0x04, 0xce, 0x66, 0x2c }, + { 0xfb, 0x4c, 0x5e, 0x86, 0xd7, 0xb2, 0x22, 0x9b, 0x99, 0xb8, 0xba, 0x6d, 0x94, 0xc2, 0x47, 0xef, 0x96, 0x4a, 0xa3, 0xa2, 0xba, 0xe8, 0xed, 0xc7, 0x75, 0x69, 0xf2, 0x8d, 0xbb, 0xff, 0x2d, 0x4e }, + { 0xe9, 0x4f, 0x52, 0x6d, 0xe9, 0x01, 0x96, 0x33, 0xec, 0xd5, 0x4a, 0xc6, 0x12, 0x0f, 0x23, 0x95, 0x8d, 0x77, 0x18, 0xf1, 0xe7, 0x71, 0x7b, 0xf3, 0x29, 0x21, 0x1a, 0x4f, 0xae, 0xed, 0x4e, 0x6d }, + { 0xcb, 0xd6, 0x66, 0x0a, 0x10, 0xdb, 0x3f, 0x23, 0xf7, 0xa0, 0x3d, 0x4b, 0x9d, 0x40, 0x44, 0xc7, 0x93, 0x2b, 0x28, 0x01, 0xac, 0x89, 0xd6, 0x0b, 0xc9, 0xeb, 0x92, 0xd6, 0x5a, 0x46, 0xc2, 0xa0 }, + { 0x88, 0x18, 0xbb, 0xd3, 0xdb, 0x4d, 0xc1, 0x23, 0xb2, 0x5c, 0xbb, 0xa5, 0xf5, 0x4c, 0x2b, 0xc4, 0xb3, 0xfc, 0xf9, 0xbf, 0x7d, 0x7a, 0x77, 0x09, 0xf4, 0xae, 0x58, 0x8b, 0x26, 0x7c, 0x4e, 0xce }, + { 0xc6, 0x53, 0x82, 0x51, 0x3f, 0x07, 0x46, 0x0d, 0xa3, 0x98, 0x33, 0xcb, 0x66, 0x6c, 0x5e, 0xd8, 0x2e, 0x61, 0xb9, 0xe9, 0x98, 0xf4, 0xb0, 0xc4, 0x28, 0x7c, 0xee, 0x56, 0xc3, 0xcc, 0x9b, 0xcd }, + { 0x89, 0x75, 0xb0, 0x57, 0x7f, 0xd3, 0x55, 0x66, 0xd7, 0x50, 0xb3, 0x62, 0xb0, 0x89, 0x7a, 0x26, 0xc3, 0x99, 0x13, 0x6d, 0xf0, 0x7b, 0xab, 0xab, 0xbd, 0xe6, 0x20, 0x3f, 0xf2, 0x95, 0x4e, 0xd4 }, + { 0x21, 0xfe, 0x0c, 0xeb, 0x00, 0x52, 0xbe, 0x7f, 0xb0, 0xf0, 0x04, 0x18, 0x7c, 0xac, 0xd7, 0xde, 0x67, 0xfa, 0x6e, 0xb0, 0x93, 0x8d, 0x92, 0x76, 0x77, 0xf2, 0x39, 0x8c, 0x13, 0x23, 0x17, 0xa8 }, + { 0x2e, 0xf7, 0x3f, 0x3c, 0x26, 0xf1, 0x2d, 0x93, 0x88, 0x9f, 0x3c, 0x78, 0xb6, 0xa6, 0x6c, 0x1d, 0x52, 0xb6, 0x49, 0xdc, 0x9e, 0x85, 0x6e, 0x2c, 0x17, 0x2e, 0xa7, 0xc5, 0x8a, 0xc2, 0xb5, 0xe3 }, + { 0x38, 0x8a, 0x3c, 0xd5, 0x6d, 0x73, 0x86, 0x7a, 0xbb, 0x5f, 0x84, 0x01, 0x49, 0x2b, 0x6e, 0x26, 0x81, 0xeb, 0x69, 0x85, 0x1e, 0x76, 0x7f, 0xd8, 0x42, 0x10, 0xa5, 0x60, 0x76, 0xfb, 0x3d, 0xd3 }, + { 0xaf, 0x53, 0x3e, 0x02, 0x2f, 0xc9, 0x43, 0x9e, 0x4e, 0x3c, 0xb8, 0x38, 0xec, 0xd1, 0x86, 0x92, 0x23, 0x2a, 0xdf, 0x6f, 0xe9, 0x83, 0x95, 0x26, 0xd3, 0xc3, 0xdd, 0x1b, 0x71, 0x91, 0x0b, 0x1a }, + { 0x75, 0x1c, 0x09, 0xd4, 0x1a, 0x93, 0x43, 0x88, 0x2a, 0x81, 0xcd, 0x13, 0xee, 0x40, 0x81, 0x8d, 0x12, 0xeb, 0x44, 0xc6, 0xc7, 0xf4, 0x0d, 0xf1, 0x6e, 0x4a, 0xea, 0x8f, 0xab, 0x91, 0x97, 0x2a }, + { 0x5b, 0x73, 0xdd, 0xb6, 0x8d, 0x9d, 0x2b, 0x0a, 0xa2, 0x65, 0xa0, 0x79, 0x88, 0xd6, 0xb8, 0x8a, 0xe9, 0xaa, 0xc5, 0x82, 0xaf, 0x83, 0x03, 0x2f, 0x8a, 0x9b, 0x21, 0xa2, 0xe1, 0xb7, 0xbf, 0x18 }, + { 0x3d, 0xa2, 0x91, 0x26, 0xc7, 0xc5, 0xd7, 0xf4, 0x3e, 0x64, 0x24, 0x2a, 0x79, 0xfe, 0xaa, 0x4e, 0xf3, 0x45, 0x9c, 0xde, 0xcc, 0xc8, 0x98, 0xed, 0x59, 0xa9, 0x7f, 0x6e, 0xc9, 0x3b, 0x9d, 0xab }, + { 0x56, 0x6d, 0xc9, 0x20, 0x29, 0x3d, 0xa5, 0xcb, 0x4f, 0xe0, 0xaa, 0x8a, 0xbd, 0xa8, 0xbb, 0xf5, 0x6f, 0x55, 0x23, 0x13, 0xbf, 0xf1, 0x90, 0x46, 0x64, 0x1e, 0x36, 0x15, 0xc1, 0xe3, 0xed, 0x3f }, + { 0x41, 0x15, 0xbe, 0xa0, 0x2f, 0x73, 0xf9, 0x7f, 0x62, 0x9e, 0x5c, 0x55, 0x90, 0x72, 0x0c, 0x01, 0xe7, 0xe4, 0x49, 0xae, 0x2a, 0x66, 0x97, 0xd4, 0xd2, 0x78, 0x33, 0x21, 0x30, 0x36, 0x92, 0xf9 }, + { 0x4c, 0xe0, 0x8f, 0x47, 0x62, 0x46, 0x8a, 0x76, 0x70, 0x01, 0x21, 0x64, 0x87, 0x8d, 0x68, 0x34, 0x0c, 0x52, 0xa3, 0x5e, 0x66, 0xc1, 0x88, 0x4d, 0x5c, 0x86, 0x48, 0x89, 0xab, 0xc9, 0x66, 0x77 }, + { 0x81, 0xea, 0x0b, 0x78, 0x04, 0x12, 0x4e, 0x0c, 0x22, 0xea, 0x5f, 0xc7, 0x11, 0x04, 0xa2, 0xaf, 0xcb, 0x52, 0xa1, 0xfa, 0x81, 0x6f, 0x3e, 0xcb, 0x7d, 0xcb, 0x5d, 0x9d, 0xea, 0x17, 0x86, 0xd0 }, + { 0xfe, 0x36, 0x27, 0x33, 0xb0, 0x5f, 0x6b, 0xed, 0xaf, 0x93, 0x79, 0xd7, 0xf7, 0x93, 0x6e, 0xde, 0x20, 0x9b, 0x1f, 0x83, 0x23, 0xc3, 0x92, 0x25, 0x49, 0xd9, 0xe7, 0x36, 0x81, 0xb5, 0xdb, 0x7b }, + { 0xef, 0xf3, 0x7d, 0x30, 0xdf, 0xd2, 0x03, 0x59, 0xbe, 0x4e, 0x73, 0xfd, 0xf4, 0x0d, 0x27, 0x73, 0x4b, 0x3d, 0xf9, 0x0a, 0x97, 0xa5, 0x5e, 0xd7, 0x45, 0x29, 0x72, 0x94, 0xca, 0x85, 0xd0, 0x9f }, + { 0x17, 0x2f, 0xfc, 0x67, 0x15, 0x3d, 0x12, 0xe0, 0xca, 0x76, 0xa8, 0xb6, 0xcd, 0x5d, 0x47, 0x31, 0x88, 0x5b, 0x39, 0xce, 0x0c, 0xac, 0x93, 0xa8, 0x97, 0x2a, 0x18, 0x00, 0x6c, 0x8b, 0x8b, 0xaf }, + { 0xc4, 0x79, 0x57, 0xf1, 0xcc, 0x88, 0xe8, 0x3e, 0xf9, 0x44, 0x58, 0x39, 0x70, 0x9a, 0x48, 0x0a, 0x03, 0x6b, 0xed, 0x5f, 0x88, 0xac, 0x0f, 0xcc, 0x8e, 0x1e, 0x70, 0x3f, 0xfa, 0xac, 0x13, 0x2c }, + { 0x30, 0xf3, 0x54, 0x83, 0x70, 0xcf, 0xdc, 0xed, 0xa5, 0xc3, 0x7b, 0x56, 0x9b, 0x61, 0x75, 0xe7, 0x99, 0xee, 0xf1, 0xa6, 0x2a, 0xaa, 0x94, 0x32, 0x45, 0xae, 0x76, 0x69, 0xc2, 0x27, 0xa7, 0xb5 }, + { 0xc9, 0x5d, 0xcb, 0x3c, 0xf1, 0xf2, 0x7d, 0x0e, 0xef, 0x2f, 0x25, 0xd2, 0x41, 0x38, 0x70, 0x90, 0x4a, 0x87, 0x7c, 0x4a, 0x56, 0xc2, 0xde, 0x1e, 0x83, 0xe2, 0xbc, 0x2a, 0xe2, 0xe4, 0x68, 0x21 }, + { 0xd5, 0xd0, 0xb5, 0xd7, 0x05, 0x43, 0x4c, 0xd4, 0x6b, 0x18, 0x57, 0x49, 0xf6, 0x6b, 0xfb, 0x58, 0x36, 0xdc, 0xdf, 0x6e, 0xe5, 0x49, 0xa2, 0xb7, 0xa4, 0xae, 0xe7, 0xf5, 0x80, 0x07, 0xca, 0xaf }, + { 0xbb, 0xc1, 0x24, 0xa7, 0x12, 0xf1, 0x5d, 0x07, 0xc3, 0x00, 0xe0, 0x5b, 0x66, 0x83, 0x89, 0xa4, 0x39, 0xc9, 0x17, 0x77, 0xf7, 0x21, 0xf8, 0x32, 0x0c, 0x1c, 0x90, 0x78, 0x06, 0x6d, 0x2c, 0x7e }, + { 0xa4, 0x51, 0xb4, 0x8c, 0x35, 0xa6, 0xc7, 0x85, 0x4c, 0xfa, 0xae, 0x60, 0x26, 0x2e, 0x76, 0x99, 0x08, 0x16, 0x38, 0x2a, 0xc0, 0x66, 0x7e, 0x5a, 0x5c, 0x9e, 0x1b, 0x46, 0xc4, 0x34, 0x2d, 0xdf }, + { 0xb0, 0xd1, 0x50, 0xfb, 0x55, 0xe7, 0x78, 0xd0, 0x11, 0x47, 0xf0, 0xb5, 0xd8, 0x9d, 0x99, 0xec, 0xb2, 0x0f, 0xf0, 0x7e, 0x5e, 0x67, 0x60, 0xd6, 0xb6, 0x45, 0xeb, 0x5b, 0x65, 0x4c, 0x62, 0x2b }, + { 0x34, 0xf7, 0x37, 0xc0, 0xab, 0x21, 0x99, 0x51, 0xee, 0xe8, 0x9a, 0x9f, 0x8d, 0xac, 0x29, 0x9c, 0x9d, 0x4c, 0x38, 0xf3, 0x3f, 0xa4, 0x94, 0xc5, 0xc6, 0xee, 0xfc, 0x92, 0xb6, 0xdb, 0x08, 0xbc }, + { 0x1a, 0x62, 0xcc, 0x3a, 0x00, 0x80, 0x0d, 0xcb, 0xd9, 0x98, 0x91, 0x08, 0x0c, 0x1e, 0x09, 0x84, 0x58, 0x19, 0x3a, 0x8c, 0xc9, 0xf9, 0x70, 0xea, 0x99, 0xfb, 0xef, 0xf0, 0x03, 0x18, 0xc2, 0x89 }, + { 0xcf, 0xce, 0x55, 0xeb, 0xaf, 0xc8, 0x40, 0xd7, 0xae, 0x48, 0x28, 0x1c, 0x7f, 0xd5, 0x7e, 0xc8, 0xb4, 0x82, 0xd4, 0xb7, 0x04, 0x43, 0x74, 0x95, 0x49, 0x5a, 0xc4, 0x14, 0xcf, 0x4a, 0x37, 0x4b }, + { 0x67, 0x46, 0xfa, 0xcf, 0x71, 0x14, 0x6d, 0x99, 0x9d, 0xab, 0xd0, 0x5d, 0x09, 0x3a, 0xe5, 0x86, 0x64, 0x8d, 0x1e, 0xe2, 0x8e, 0x72, 0x61, 0x7b, 0x99, 0xd0, 0xf0, 0x08, 0x6e, 0x1e, 0x45, 0xbf }, + { 0x57, 0x1c, 0xed, 0x28, 0x3b, 0x3f, 0x23, 0xb4, 0xe7, 0x50, 0xbf, 0x12, 0xa2, 0xca, 0xf1, 0x78, 0x18, 0x47, 0xbd, 0x89, 0x0e, 0x43, 0x60, 0x3c, 0xdc, 0x59, 0x76, 0x10, 0x2b, 0x7b, 0xb1, 0x1b }, + { 0xcf, 0xcb, 0x76, 0x5b, 0x04, 0x8e, 0x35, 0x02, 0x2c, 0x5d, 0x08, 0x9d, 0x26, 0xe8, 0x5a, 0x36, 0xb0, 0x05, 0xa2, 0xb8, 0x04, 0x93, 0xd0, 0x3a, 0x14, 0x4e, 0x09, 0xf4, 0x09, 0xb6, 0xaf, 0xd1 }, + { 0x40, 0x50, 0xc7, 0xa2, 0x77, 0x05, 0xbb, 0x27, 0xf4, 0x20, 0x89, 0xb2, 0x99, 0xf3, 0xcb, 0xe5, 0x05, 0x4e, 0xad, 0x68, 0x72, 0x7e, 0x8e, 0xf9, 0x31, 0x8c, 0xe6, 0xf2, 0x5c, 0xd6, 0xf3, 0x1d }, + { 0x18, 0x40, 0x70, 0xbd, 0x5d, 0x26, 0x5f, 0xbd, 0xc1, 0x42, 0xcd, 0x1c, 0x5c, 0xd0, 0xd7, 0xe4, 0x14, 0xe7, 0x03, 0x69, 0xa2, 0x66, 0xd6, 0x27, 0xc8, 0xfb, 0xa8, 0x4f, 0xa5, 0xe8, 0x4c, 0x34 }, + { 0x9e, 0xdd, 0xa9, 0xa4, 0x44, 0x39, 0x02, 0xa9, 0x58, 0x8c, 0x0d, 0x0c, 0xcc, 0x62, 0xb9, 0x30, 0x21, 0x84, 0x79, 0xa6, 0x84, 0x1e, 0x6f, 0xe7, 0xd4, 0x30, 0x03, 0xf0, 0x4b, 0x1f, 0xd6, 0x43 }, + { 0xe4, 0x12, 0xfe, 0xef, 0x79, 0x08, 0x32, 0x4a, 0x6d, 0xa1, 0x84, 0x16, 0x29, 0xf3, 0x5d, 0x3d, 0x35, 0x86, 0x42, 0x01, 0x93, 0x10, 0xec, 0x57, 0xc6, 0x14, 0x83, 0x6b, 0x63, 0xd3, 0x07, 0x63 }, + { 0x1a, 0x2b, 0x8e, 0xdf, 0xf3, 0xf9, 0xac, 0xc1, 0x55, 0x4f, 0xcb, 0xae, 0x3c, 0xf1, 0xd6, 0x29, 0x8c, 0x64, 0x62, 0xe2, 0x2e, 0x5e, 0xb0, 0x25, 0x96, 0x84, 0xf8, 0x35, 0x01, 0x2b, 0xd1, 0x3f }, + { 0x28, 0x8c, 0x4a, 0xd9, 0xb9, 0x40, 0x97, 0x62, 0xea, 0x07, 0xc2, 0x4a, 0x41, 0xf0, 0x4f, 0x69, 0xa7, 0xd7, 0x4b, 0xee, 0x2d, 0x95, 0x43, 0x53, 0x74, 0xbd, 0xe9, 0x46, 0xd7, 0x24, 0x1c, 0x7b }, + { 0x80, 0x56, 0x91, 0xbb, 0x28, 0x67, 0x48, 0xcf, 0xb5, 0x91, 0xd3, 0xae, 0xbe, 0x7e, 0x6f, 0x4e, 0x4d, 0xc6, 0xe2, 0x80, 0x8c, 0x65, 0x14, 0x3c, 0xc0, 0x04, 0xe4, 0xeb, 0x6f, 0xd0, 0x9d, 0x43 }, + { 0xd4, 0xac, 0x8d, 0x3a, 0x0a, 0xfc, 0x6c, 0xfa, 0x7b, 0x46, 0x0a, 0xe3, 0x00, 0x1b, 0xae, 0xb3, 0x6d, 0xad, 0xb3, 0x7d, 0xa0, 0x7d, 0x2e, 0x8a, 0xc9, 0x18, 0x22, 0xdf, 0x34, 0x8a, 0xed, 0x3d }, + { 0xc3, 0x76, 0x61, 0x70, 0x14, 0xd2, 0x01, 0x58, 0xbc, 0xed, 0x3d, 0x3b, 0xa5, 0x52, 0xb6, 0xec, 0xcf, 0x84, 0xe6, 0x2a, 0xa3, 0xeb, 0x65, 0x0e, 0x90, 0x02, 0x9c, 0x84, 0xd1, 0x3e, 0xea, 0x69 }, + { 0xc4, 0x1f, 0x09, 0xf4, 0x3c, 0xec, 0xae, 0x72, 0x93, 0xd6, 0x00, 0x7c, 0xa0, 0xa3, 0x57, 0x08, 0x7d, 0x5a, 0xe5, 0x9b, 0xe5, 0x00, 0xc1, 0xcd, 0x5b, 0x28, 0x9e, 0xe8, 0x10, 0xc7, 0xb0, 0x82 }, + { 0x03, 0xd1, 0xce, 0xd1, 0xfb, 0xa5, 0xc3, 0x91, 0x55, 0xc4, 0x4b, 0x77, 0x65, 0xcb, 0x76, 0x0c, 0x78, 0x70, 0x8d, 0xcf, 0xc8, 0x0b, 0x0b, 0xd8, 0xad, 0xe3, 0xa5, 0x6d, 0xa8, 0x83, 0x0b, 0x29 }, + { 0x09, 0xbd, 0xe6, 0xf1, 0x52, 0x21, 0x8d, 0xc9, 0x2c, 0x41, 0xd7, 0xf4, 0x53, 0x87, 0xe6, 0x3e, 0x58, 0x69, 0xd8, 0x07, 0xec, 0x70, 0xb8, 0x21, 0x40, 0x5d, 0xbd, 0x88, 0x4b, 0x7f, 0xcf, 0x4b }, + { 0x71, 0xc9, 0x03, 0x6e, 0x18, 0x17, 0x9b, 0x90, 0xb3, 0x7d, 0x39, 0xe9, 0xf0, 0x5e, 0xb8, 0x9c, 0xc5, 0xfc, 0x34, 0x1f, 0xd7, 0xc4, 0x77, 0xd0, 0xd7, 0x49, 0x32, 0x85, 0xfa, 0xca, 0x08, 0xa4 }, + { 0x59, 0x16, 0x83, 0x3e, 0xbb, 0x05, 0xcd, 0x91, 0x9c, 0xa7, 0xfe, 0x83, 0xb6, 0x92, 0xd3, 0x20, 0x5b, 0xef, 0x72, 0x39, 0x2b, 0x2c, 0xf6, 0xbb, 0x0a, 0x6d, 0x43, 0xf9, 0x94, 0xf9, 0x5f, 0x11 }, + { 0xf6, 0x3a, 0xab, 0x3e, 0xc6, 0x41, 0xb3, 0xb0, 0x24, 0x96, 0x4c, 0x2b, 0x43, 0x7c, 0x04, 0xf6, 0x04, 0x3c, 0x4c, 0x7e, 0x02, 0x79, 0x23, 0x99, 0x95, 0x40, 0x19, 0x58, 0xf8, 0x6b, 0xbe, 0x54 }, + { 0xf1, 0x72, 0xb1, 0x80, 0xbf, 0xb0, 0x97, 0x40, 0x49, 0x31, 0x20, 0xb6, 0x32, 0x6c, 0xbd, 0xc5, 0x61, 0xe4, 0x77, 0xde, 0xf9, 0xbb, 0xcf, 0xd2, 0x8c, 0xc8, 0xc1, 0xc5, 0xe3, 0x37, 0x9a, 0x31 }, + { 0xcb, 0x9b, 0x89, 0xcc, 0x18, 0x38, 0x1d, 0xd9, 0x14, 0x1a, 0xde, 0x58, 0x86, 0x54, 0xd4, 0xe6, 0xa2, 0x31, 0xd5, 0xbf, 0x49, 0xd4, 0xd5, 0x9a, 0xc2, 0x7d, 0x86, 0x9c, 0xbe, 0x10, 0x0c, 0xf3 }, + { 0x7b, 0xd8, 0x81, 0x50, 0x46, 0xfd, 0xd8, 0x10, 0xa9, 0x23, 0xe1, 0x98, 0x4a, 0xae, 0xbd, 0xcd, 0xf8, 0x4d, 0x87, 0xc8, 0x99, 0x2d, 0x68, 0xb5, 0xee, 0xb4, 0x60, 0xf9, 0x3e, 0xb3, 0xc8, 0xd7 }, + { 0x60, 0x7b, 0xe6, 0x68, 0x62, 0xfd, 0x08, 0xee, 0x5b, 0x19, 0xfa, 0xca, 0xc0, 0x9d, 0xfd, 0xbc, 0xd4, 0x0c, 0x31, 0x21, 0x01, 0xd6, 0x6e, 0x6e, 0xbd, 0x2b, 0x84, 0x1f, 0x1b, 0x9a, 0x93, 0x25 }, + { 0x9f, 0xe0, 0x3b, 0xbe, 0x69, 0xab, 0x18, 0x34, 0xf5, 0x21, 0x9b, 0x0d, 0xa8, 0x8a, 0x08, 0xb3, 0x0a, 0x66, 0xc5, 0x91, 0x3f, 0x01, 0x51, 0x96, 0x3c, 0x36, 0x05, 0x60, 0xdb, 0x03, 0x87, 0xb3 }, + { 0x90, 0xa8, 0x35, 0x85, 0x71, 0x7b, 0x75, 0xf0, 0xe9, 0xb7, 0x25, 0xe0, 0x55, 0xee, 0xee, 0xb9, 0xe7, 0xa0, 0x28, 0xea, 0x7e, 0x6c, 0xbc, 0x07, 0xb2, 0x09, 0x17, 0xec, 0x03, 0x63, 0xe3, 0x8c }, + { 0x33, 0x6e, 0xa0, 0x53, 0x0f, 0x4a, 0x74, 0x69, 0x12, 0x6e, 0x02, 0x18, 0x58, 0x7e, 0xbb, 0xde, 0x33, 0x58, 0xa0, 0xb3, 0x1c, 0x29, 0xd2, 0x00, 0xf7, 0xdc, 0x7e, 0xb1, 0x5c, 0x6a, 0xad, 0xd8 }, + { 0xa7, 0x9e, 0x76, 0xdc, 0x0a, 0xbc, 0xa4, 0x39, 0x6f, 0x07, 0x47, 0xcd, 0x7b, 0x74, 0x8d, 0xf9, 0x13, 0x00, 0x76, 0x26, 0xb1, 0xd6, 0x59, 0xda, 0x0c, 0x1f, 0x78, 0xb9, 0x30, 0x3d, 0x01, 0xa3 }, + { 0x44, 0xe7, 0x8a, 0x77, 0x37, 0x56, 0xe0, 0x95, 0x15, 0x19, 0x50, 0x4d, 0x70, 0x38, 0xd2, 0x8d, 0x02, 0x13, 0xa3, 0x7e, 0x0c, 0xe3, 0x75, 0x37, 0x17, 0x57, 0xbc, 0x99, 0x63, 0x11, 0xe3, 0xb8 }, + { 0x77, 0xac, 0x01, 0x2a, 0x3f, 0x75, 0x4d, 0xcf, 0xea, 0xb5, 0xeb, 0x99, 0x6b, 0xe9, 0xcd, 0x2d, 0x1f, 0x96, 0x11, 0x1b, 0x6e, 0x49, 0xf3, 0x99, 0x4d, 0xf1, 0x81, 0xf2, 0x85, 0x69, 0xd8, 0x25 }, + { 0xce, 0x5a, 0x10, 0xdb, 0x6f, 0xcc, 0xda, 0xf1, 0x40, 0xaa, 0xa4, 0xde, 0xd6, 0x25, 0x0a, 0x9c, 0x06, 0xe9, 0x22, 0x2b, 0xc9, 0xf9, 0xf3, 0x65, 0x8a, 0x4a, 0xff, 0x93, 0x5f, 0x2b, 0x9f, 0x3a }, + { 0xec, 0xc2, 0x03, 0xa7, 0xfe, 0x2b, 0xe4, 0xab, 0xd5, 0x5b, 0xb5, 0x3e, 0x6e, 0x67, 0x35, 0x72, 0xe0, 0x07, 0x8d, 0xa8, 0xcd, 0x37, 0x5e, 0xf4, 0x30, 0xcc, 0x97, 0xf9, 0xf8, 0x00, 0x83, 0xaf }, + { 0x14, 0xa5, 0x18, 0x6d, 0xe9, 0xd7, 0xa1, 0x8b, 0x04, 0x12, 0xb8, 0x56, 0x3e, 0x51, 0xcc, 0x54, 0x33, 0x84, 0x0b, 0x4a, 0x12, 0x9a, 0x8f, 0xf9, 0x63, 0xb3, 0x3a, 0x3c, 0x4a, 0xfe, 0x8e, 0xbb }, + { 0x13, 0xf8, 0xef, 0x95, 0xcb, 0x86, 0xe6, 0xa6, 0x38, 0x93, 0x1c, 0x8e, 0x10, 0x76, 0x73, 0xeb, 0x76, 0xba, 0x10, 0xd7, 0xc2, 0xcd, 0x70, 0xb9, 0xd9, 0x92, 0x0b, 0xbe, 0xed, 0x92, 0x94, 0x09 }, + { 0x0b, 0x33, 0x8f, 0x4e, 0xe1, 0x2f, 0x2d, 0xfc, 0xb7, 0x87, 0x13, 0x37, 0x79, 0x41, 0xe0, 0xb0, 0x63, 0x21, 0x52, 0x58, 0x1d, 0x13, 0x32, 0x51, 0x6e, 0x4a, 0x2c, 0xab, 0x19, 0x42, 0xcc, 0xa4 }, + { 0xea, 0xab, 0x0e, 0xc3, 0x7b, 0x3b, 0x8a, 0xb7, 0x96, 0xe9, 0xf5, 0x72, 0x38, 0xde, 0x14, 0xa2, 0x64, 0xa0, 0x76, 0xf3, 0x88, 0x7d, 0x86, 0xe2, 0x9b, 0xb5, 0x90, 0x6d, 0xb5, 0xa0, 0x0e, 0x02 }, + { 0x23, 0xcb, 0x68, 0xb8, 0xc0, 0xe6, 0xdc, 0x26, 0xdc, 0x27, 0x76, 0x6d, 0xdc, 0x0a, 0x13, 0xa9, 0x94, 0x38, 0xfd, 0x55, 0x61, 0x7a, 0xa4, 0x09, 0x5d, 0x8f, 0x96, 0x97, 0x20, 0xc8, 0x72, 0xdf }, + { 0x09, 0x1d, 0x8e, 0xe3, 0x0d, 0x6f, 0x29, 0x68, 0xd4, 0x6b, 0x68, 0x7d, 0xd6, 0x52, 0x92, 0x66, 0x57, 0x42, 0xde, 0x0b, 0xb8, 0x3d, 0xcc, 0x00, 0x04, 0xc7, 0x2c, 0xe1, 0x00, 0x07, 0xa5, 0x49 }, + { 0x7f, 0x50, 0x7a, 0xbc, 0x6d, 0x19, 0xba, 0x00, 0xc0, 0x65, 0xa8, 0x76, 0xec, 0x56, 0x57, 0x86, 0x88, 0x82, 0xd1, 0x8a, 0x22, 0x1b, 0xc4, 0x6c, 0x7a, 0x69, 0x12, 0x54, 0x1f, 0x5b, 0xc7, 0xba }, + { 0xa0, 0x60, 0x7c, 0x24, 0xe1, 0x4e, 0x8c, 0x22, 0x3d, 0xb0, 0xd7, 0x0b, 0x4d, 0x30, 0xee, 0x88, 0x01, 0x4d, 0x60, 0x3f, 0x43, 0x7e, 0x9e, 0x02, 0xaa, 0x7d, 0xaf, 0xa3, 0xcd, 0xfb, 0xad, 0x94 }, + { 0xdd, 0xbf, 0xea, 0x75, 0xcc, 0x46, 0x78, 0x82, 0xeb, 0x34, 0x83, 0xce, 0x5e, 0x2e, 0x75, 0x6a, 0x4f, 0x47, 0x01, 0xb7, 0x6b, 0x44, 0x55, 0x19, 0xe8, 0x9f, 0x22, 0xd6, 0x0f, 0xa8, 0x6e, 0x06 }, + { 0x0c, 0x31, 0x1f, 0x38, 0xc3, 0x5a, 0x4f, 0xb9, 0x0d, 0x65, 0x1c, 0x28, 0x9d, 0x48, 0x68, 0x56, 0xcd, 0x14, 0x13, 0xdf, 0x9b, 0x06, 0x77, 0xf5, 0x3e, 0xce, 0x2c, 0xd9, 0xe4, 0x77, 0xc6, 0x0a }, + { 0x46, 0xa7, 0x3a, 0x8d, 0xd3, 0xe7, 0x0f, 0x59, 0xd3, 0x94, 0x2c, 0x01, 0xdf, 0x59, 0x9d, 0xef, 0x78, 0x3c, 0x9d, 0xa8, 0x2f, 0xd8, 0x32, 0x22, 0xcd, 0x66, 0x2b, 0x53, 0xdc, 0xe7, 0xdb, 0xdf }, + { 0xad, 0x03, 0x8f, 0xf9, 0xb1, 0x4d, 0xe8, 0x4a, 0x80, 0x1e, 0x4e, 0x62, 0x1c, 0xe5, 0xdf, 0x02, 0x9d, 0xd9, 0x35, 0x20, 0xd0, 0xc2, 0xfa, 0x38, 0xbf, 0xf1, 0x76, 0xa8, 0xb1, 0xd1, 0x69, 0x8c }, + { 0xab, 0x70, 0xc5, 0xdf, 0xbd, 0x1e, 0xa8, 0x17, 0xfe, 0xd0, 0xcd, 0x06, 0x72, 0x93, 0xab, 0xf3, 0x19, 0xe5, 0xd7, 0x90, 0x1c, 0x21, 0x41, 0xd5, 0xd9, 0x9b, 0x23, 0xf0, 0x3a, 0x38, 0xe7, 0x48 }, + { 0x1f, 0xff, 0xda, 0x67, 0x93, 0x2b, 0x73, 0xc8, 0xec, 0xaf, 0x00, 0x9a, 0x34, 0x91, 0xa0, 0x26, 0x95, 0x3b, 0xab, 0xfe, 0x1f, 0x66, 0x3b, 0x06, 0x97, 0xc3, 0xc4, 0xae, 0x8b, 0x2e, 0x7d, 0xcb }, + { 0xb0, 0xd2, 0xcc, 0x19, 0x47, 0x2d, 0xd5, 0x7f, 0x2b, 0x17, 0xef, 0xc0, 0x3c, 0x8d, 0x58, 0xc2, 0x28, 0x3d, 0xbb, 0x19, 0xda, 0x57, 0x2f, 0x77, 0x55, 0x85, 0x5a, 0xa9, 0x79, 0x43, 0x17, 0xa0 }, + { 0xa0, 0xd1, 0x9a, 0x6e, 0xe3, 0x39, 0x79, 0xc3, 0x25, 0x51, 0x0e, 0x27, 0x66, 0x22, 0xdf, 0x41, 0xf7, 0x15, 0x83, 0xd0, 0x75, 0x01, 0xb8, 0x70, 0x71, 0x12, 0x9a, 0x0a, 0xd9, 0x47, 0x32, 0xa5 }, + { 0x72, 0x46, 0x42, 0xa7, 0x03, 0x2d, 0x10, 0x62, 0xb8, 0x9e, 0x52, 0xbe, 0xa3, 0x4b, 0x75, 0xdf, 0x7d, 0x8f, 0xe7, 0x72, 0xd9, 0xfe, 0x3c, 0x93, 0xdd, 0xf3, 0xc4, 0x54, 0x5a, 0xb5, 0xa9, 0x9b }, + { 0xad, 0xe5, 0xea, 0xa7, 0xe6, 0x1f, 0x67, 0x2d, 0x58, 0x7e, 0xa0, 0x3d, 0xae, 0x7d, 0x7b, 0x55, 0x22, 0x9c, 0x01, 0xd0, 0x6b, 0xc0, 0xa5, 0x70, 0x14, 0x36, 0xcb, 0xd1, 0x83, 0x66, 0xa6, 0x26 }, + { 0x01, 0x3b, 0x31, 0xeb, 0xd2, 0x28, 0xfc, 0xdd, 0xa5, 0x1f, 0xab, 0xb0, 0x3b, 0xb0, 0x2d, 0x60, 0xac, 0x20, 0xca, 0x21, 0x5a, 0xaf, 0xa8, 0x3b, 0xdd, 0x85, 0x5e, 0x37, 0x55, 0xa3, 0x5f, 0x0b }, + { 0x33, 0x2e, 0xd4, 0x0b, 0xb1, 0x0d, 0xde, 0x3c, 0x95, 0x4a, 0x75, 0xd7, 0xb8, 0x99, 0x9d, 0x4b, 0x26, 0xa1, 0xc0, 0x63, 0xc1, 0xdc, 0x6e, 0x32, 0xc1, 0xd9, 0x1b, 0xab, 0x7b, 0xbb, 0x7d, 0x16 }, + { 0xc7, 0xa1, 0x97, 0xb3, 0xa0, 0x5b, 0x56, 0x6b, 0xcc, 0x9f, 0xac, 0xd2, 0x0e, 0x44, 0x1d, 0x6f, 0x6c, 0x28, 0x60, 0xac, 0x96, 0x51, 0xcd, 0x51, 0xd6, 0xb9, 0xd2, 0xcd, 0xee, 0xea, 0x03, 0x90 }, + { 0xbd, 0x9c, 0xf6, 0x4e, 0xa8, 0x95, 0x3c, 0x03, 0x71, 0x08, 0xe6, 0xf6, 0x54, 0x91, 0x4f, 0x39, 0x58, 0xb6, 0x8e, 0x29, 0xc1, 0x67, 0x00, 0xdc, 0x18, 0x4d, 0x94, 0xa2, 0x17, 0x08, 0xff, 0x60 }, + { 0x88, 0x35, 0xb0, 0xac, 0x02, 0x11, 0x51, 0xdf, 0x71, 0x64, 0x74, 0xce, 0x27, 0xce, 0x4d, 0x3c, 0x15, 0xf0, 0xb2, 0xda, 0xb4, 0x80, 0x03, 0xcf, 0x3f, 0x3e, 0xfd, 0x09, 0x45, 0x10, 0x6b, 0x9a }, + { 0x3b, 0xfe, 0xfa, 0x33, 0x01, 0xaa, 0x55, 0xc0, 0x80, 0x19, 0x0c, 0xff, 0xda, 0x8e, 0xae, 0x51, 0xd9, 0xaf, 0x48, 0x8b, 0x4c, 0x1f, 0x24, 0xc3, 0xd9, 0xa7, 0x52, 0x42, 0xfd, 0x8e, 0xa0, 0x1d }, + { 0x08, 0x28, 0x4d, 0x14, 0x99, 0x3c, 0xd4, 0x7d, 0x53, 0xeb, 0xae, 0xcf, 0x0d, 0xf0, 0x47, 0x8c, 0xc1, 0x82, 0xc8, 0x9c, 0x00, 0xe1, 0x85, 0x9c, 0x84, 0x85, 0x16, 0x86, 0xdd, 0xf2, 0xc1, 0xb7 }, + { 0x1e, 0xd7, 0xef, 0x9f, 0x04, 0xc2, 0xac, 0x8d, 0xb6, 0xa8, 0x64, 0xdb, 0x13, 0x10, 0x87, 0xf2, 0x70, 0x65, 0x09, 0x8e, 0x69, 0xc3, 0xfe, 0x78, 0x71, 0x8d, 0x9b, 0x94, 0x7f, 0x4a, 0x39, 0xd0 }, + { 0xc1, 0x61, 0xf2, 0xdc, 0xd5, 0x7e, 0x9c, 0x14, 0x39, 0xb3, 0x1a, 0x9d, 0xd4, 0x3d, 0x8f, 0x3d, 0x7d, 0xd8, 0xf0, 0xeb, 0x7c, 0xfa, 0xc6, 0xfb, 0x25, 0xa0, 0xf2, 0x8e, 0x30, 0x6f, 0x06, 0x61 }, + { 0xc0, 0x19, 0x69, 0xad, 0x34, 0xc5, 0x2c, 0xaf, 0x3d, 0xc4, 0xd8, 0x0d, 0x19, 0x73, 0x5c, 0x29, 0x73, 0x1a, 0xc6, 0xe7, 0xa9, 0x20, 0x85, 0xab, 0x92, 0x50, 0xc4, 0x8d, 0xea, 0x48, 0xa3, 0xfc }, + { 0x17, 0x20, 0xb3, 0x65, 0x56, 0x19, 0xd2, 0xa5, 0x2b, 0x35, 0x21, 0xae, 0x0e, 0x49, 0xe3, 0x45, 0xcb, 0x33, 0x89, 0xeb, 0xd6, 0x20, 0x8a, 0xca, 0xf9, 0xf1, 0x3f, 0xda, 0xcc, 0xa8, 0xbe, 0x49 }, + { 0x75, 0x62, 0x88, 0x36, 0x1c, 0x83, 0xe2, 0x4c, 0x61, 0x7c, 0xf9, 0x5c, 0x90, 0x5b, 0x22, 0xd0, 0x17, 0xcd, 0xc8, 0x6f, 0x0b, 0xf1, 0xd6, 0x58, 0xf4, 0x75, 0x6c, 0x73, 0x79, 0x87, 0x3b, 0x7f }, + { 0xe7, 0xd0, 0xed, 0xa3, 0x45, 0x26, 0x93, 0xb7, 0x52, 0xab, 0xcd, 0xa1, 0xb5, 0x5e, 0x27, 0x6f, 0x82, 0x69, 0x8f, 0x5f, 0x16, 0x05, 0x40, 0x3e, 0xff, 0x83, 0x0b, 0xea, 0x00, 0x71, 0xa3, 0x94 }, + { 0x2c, 0x82, 0xec, 0xaa, 0x6b, 0x84, 0x80, 0x3e, 0x04, 0x4a, 0xf6, 0x31, 0x18, 0xaf, 0xe5, 0x44, 0x68, 0x7c, 0xb6, 0xe6, 0xc7, 0xdf, 0x49, 0xed, 0x76, 0x2d, 0xfd, 0x7c, 0x86, 0x93, 0xa1, 0xbc }, + { 0x61, 0x36, 0xcb, 0xf4, 0xb4, 0x41, 0x05, 0x6f, 0xa1, 0xe2, 0x72, 0x24, 0x98, 0x12, 0x5d, 0x6d, 0xed, 0x45, 0xe1, 0x7b, 0x52, 0x14, 0x39, 0x59, 0xc7, 0xf4, 0xd4, 0xe3, 0x95, 0x21, 0x8a, 0xc2 }, + { 0x72, 0x1d, 0x32, 0x45, 0xaa, 0xfe, 0xf2, 0x7f, 0x6a, 0x62, 0x4f, 0x47, 0x95, 0x4b, 0x6c, 0x25, 0x50, 0x79, 0x52, 0x6f, 0xfa, 0x25, 0xe9, 0xff, 0x77, 0xe5, 0xdc, 0xff, 0x47, 0x3b, 0x15, 0x97 }, + { 0x9d, 0xd2, 0xfb, 0xd8, 0xce, 0xf1, 0x6c, 0x35, 0x3c, 0x0a, 0xc2, 0x11, 0x91, 0xd5, 0x09, 0xeb, 0x28, 0xdd, 0x9e, 0x3e, 0x0d, 0x8c, 0xea, 0x5d, 0x26, 0xca, 0x83, 0x93, 0x93, 0x85, 0x1c, 0x3a }, + { 0xb2, 0x39, 0x4c, 0xea, 0xcd, 0xeb, 0xf2, 0x1b, 0xf9, 0xdf, 0x2c, 0xed, 0x98, 0xe5, 0x8f, 0x1c, 0x3a, 0x4b, 0xbb, 0xff, 0x66, 0x0d, 0xd9, 0x00, 0xf6, 0x22, 0x02, 0xd6, 0x78, 0x5c, 0xc4, 0x6e }, + { 0x57, 0x08, 0x9f, 0x22, 0x27, 0x49, 0xad, 0x78, 0x71, 0x76, 0x5f, 0x06, 0x2b, 0x11, 0x4f, 0x43, 0xba, 0x20, 0xec, 0x56, 0x42, 0x2a, 0x8b, 0x1e, 0x3f, 0x87, 0x19, 0x2c, 0x0e, 0xa7, 0x18, 0xc6 }, + { 0xe4, 0x9a, 0x94, 0x59, 0x96, 0x1c, 0xd3, 0x3c, 0xdf, 0x4a, 0xae, 0x1b, 0x10, 0x78, 0xa5, 0xde, 0xa7, 0xc0, 0x40, 0xe0, 0xfe, 0xa3, 0x40, 0xc9, 0x3a, 0x72, 0x48, 0x72, 0xfc, 0x4a, 0xf8, 0x06 }, + { 0xed, 0xe6, 0x7f, 0x72, 0x0e, 0xff, 0xd2, 0xca, 0x9c, 0x88, 0x99, 0x41, 0x52, 0xd0, 0x20, 0x1d, 0xee, 0x6b, 0x0a, 0x2d, 0x2c, 0x07, 0x7a, 0xca, 0x6d, 0xae, 0x29, 0xf7, 0x3f, 0x8b, 0x63, 0x09 }, + { 0xe0, 0xf4, 0x34, 0xbf, 0x22, 0xe3, 0x08, 0x80, 0x39, 0xc2, 0x1f, 0x71, 0x9f, 0xfc, 0x67, 0xf0, 0xf2, 0xcb, 0x5e, 0x98, 0xa7, 0xa0, 0x19, 0x4c, 0x76, 0xe9, 0x6b, 0xf4, 0xe8, 0xe1, 0x7e, 0x61 }, + { 0x27, 0x7c, 0x04, 0xe2, 0x85, 0x34, 0x84, 0xa4, 0xeb, 0xa9, 0x10, 0xad, 0x33, 0x6d, 0x01, 0xb4, 0x77, 0xb6, 0x7c, 0xc2, 0x00, 0xc5, 0x9f, 0x3c, 0x8d, 0x77, 0xee, 0xf8, 0x49, 0x4f, 0x29, 0xcd }, + { 0x15, 0x6d, 0x57, 0x47, 0xd0, 0xc9, 0x9c, 0x7f, 0x27, 0x09, 0x7d, 0x7b, 0x7e, 0x00, 0x2b, 0x2e, 0x18, 0x5c, 0xb7, 0x2d, 0x8d, 0xd7, 0xeb, 0x42, 0x4a, 0x03, 0x21, 0x52, 0x81, 0x61, 0x21, 0x9f }, + { 0x20, 0xdd, 0xd1, 0xed, 0x9b, 0x1c, 0xa8, 0x03, 0x94, 0x6d, 0x64, 0xa8, 0x3a, 0xe4, 0x65, 0x9d, 0xa6, 0x7f, 0xba, 0x7a, 0x1a, 0x3e, 0xdd, 0xb1, 0xe1, 0x03, 0xc0, 0xf5, 0xe0, 0x3e, 0x3a, 0x2c }, + { 0xf0, 0xaf, 0x60, 0x4d, 0x3d, 0xab, 0xbf, 0x9a, 0x0f, 0x2a, 0x7d, 0x3d, 0xda, 0x6b, 0xd3, 0x8b, 0xba, 0x72, 0xc6, 0xd0, 0x9b, 0xe4, 0x94, 0xfc, 0xef, 0x71, 0x3f, 0xf1, 0x01, 0x89, 0xb6, 0xe6 }, + { 0x98, 0x02, 0xbb, 0x87, 0xde, 0xf4, 0xcc, 0x10, 0xc4, 0xa5, 0xfd, 0x49, 0xaa, 0x58, 0xdf, 0xe2, 0xf3, 0xfd, 0xdb, 0x46, 0xb4, 0x70, 0x88, 0x14, 0xea, 0xd8, 0x1d, 0x23, 0xba, 0x95, 0x13, 0x9b }, + { 0x4f, 0x8c, 0xe1, 0xe5, 0x1d, 0x2f, 0xe7, 0xf2, 0x40, 0x43, 0xa9, 0x04, 0xd8, 0x98, 0xeb, 0xfc, 0x91, 0x97, 0x54, 0x18, 0x75, 0x34, 0x13, 0xaa, 0x09, 0x9b, 0x79, 0x5e, 0xcb, 0x35, 0xce, 0xdb }, + { 0xbd, 0xdc, 0x65, 0x14, 0xd7, 0xee, 0x6a, 0xce, 0x0a, 0x4a, 0xc1, 0xd0, 0xe0, 0x68, 0x11, 0x22, 0x88, 0xcb, 0xcf, 0x56, 0x04, 0x54, 0x64, 0x27, 0x05, 0x63, 0x01, 0x77, 0xcb, 0xa6, 0x08, 0xbd }, + { 0xd6, 0x35, 0x99, 0x4f, 0x62, 0x91, 0x51, 0x7b, 0x02, 0x81, 0xff, 0xdd, 0x49, 0x6a, 0xfa, 0x86, 0x27, 0x12, 0xe5, 0xb3, 0xc4, 0xe5, 0x2e, 0x4c, 0xd5, 0xfd, 0xae, 0x8c, 0x0e, 0x72, 0xfb, 0x08 }, + { 0x87, 0x8d, 0x9c, 0xa6, 0x00, 0xcf, 0x87, 0xe7, 0x69, 0xcc, 0x30, 0x5c, 0x1b, 0x35, 0x25, 0x51, 0x86, 0x61, 0x5a, 0x73, 0xa0, 0xda, 0x61, 0x3b, 0x5f, 0x1c, 0x98, 0xdb, 0xf8, 0x12, 0x83, 0xea }, + { 0xa6, 0x4e, 0xbe, 0x5d, 0xc1, 0x85, 0xde, 0x9f, 0xdd, 0xe7, 0x60, 0x7b, 0x69, 0x98, 0x70, 0x2e, 0xb2, 0x34, 0x56, 0x18, 0x49, 0x57, 0x30, 0x7d, 0x2f, 0xa7, 0x2e, 0x87, 0xa4, 0x77, 0x02, 0xd6 }, + { 0xce, 0x50, 0xea, 0xb7, 0xb5, 0xeb, 0x52, 0xbd, 0xc9, 0xad, 0x8e, 0x5a, 0x48, 0x0a, 0xb7, 0x80, 0xca, 0x93, 0x20, 0xe4, 0x43, 0x60, 0xb1, 0xfe, 0x37, 0xe0, 0x3f, 0x2f, 0x7a, 0xd7, 0xde, 0x01 }, + { 0xee, 0xdd, 0xb7, 0xc0, 0xdb, 0x6e, 0x30, 0xab, 0xe6, 0x6d, 0x79, 0xe3, 0x27, 0x51, 0x1e, 0x61, 0xfc, 0xeb, 0xbc, 0x29, 0xf1, 0x59, 0xb4, 0x0a, 0x86, 0xb0, 0x46, 0xec, 0xf0, 0x51, 0x38, 0x23 }, + { 0x78, 0x7f, 0xc9, 0x34, 0x40, 0xc1, 0xec, 0x96, 0xb5, 0xad, 0x01, 0xc1, 0x6c, 0xf7, 0x79, 0x16, 0xa1, 0x40, 0x5f, 0x94, 0x26, 0x35, 0x6e, 0xc9, 0x21, 0xd8, 0xdf, 0xf3, 0xea, 0x63, 0xb7, 0xe0 }, + { 0x7f, 0x0d, 0x5e, 0xab, 0x47, 0xee, 0xfd, 0xa6, 0x96, 0xc0, 0xbf, 0x0f, 0xbf, 0x86, 0xab, 0x21, 0x6f, 0xce, 0x46, 0x1e, 0x93, 0x03, 0xab, 0xa6, 0xac, 0x37, 0x41, 0x20, 0xe8, 0x90, 0xe8, 0xdf }, + { 0xb6, 0x80, 0x04, 0xb4, 0x2f, 0x14, 0xad, 0x02, 0x9f, 0x4c, 0x2e, 0x03, 0xb1, 0xd5, 0xeb, 0x76, 0xd5, 0x71, 0x60, 0xe2, 0x64, 0x76, 0xd2, 0x11, 0x31, 0xbe, 0xf2, 0x0a, 0xda, 0x7d, 0x27, 0xf4 }, + { 0xb0, 0xc4, 0xeb, 0x18, 0xae, 0x25, 0x0b, 0x51, 0xa4, 0x13, 0x82, 0xea, 0xd9, 0x2d, 0x0d, 0xc7, 0x45, 0x5f, 0x93, 0x79, 0xfc, 0x98, 0x84, 0x42, 0x8e, 0x47, 0x70, 0x60, 0x8d, 0xb0, 0xfa, 0xec }, + { 0xf9, 0x2b, 0x7a, 0x87, 0x0c, 0x05, 0x9f, 0x4d, 0x46, 0x46, 0x4c, 0x82, 0x4e, 0xc9, 0x63, 0x55, 0x14, 0x0b, 0xdc, 0xe6, 0x81, 0x32, 0x2c, 0xc3, 0xa9, 0x92, 0xff, 0x10, 0x3e, 0x3f, 0xea, 0x52 }, + { 0x53, 0x64, 0x31, 0x26, 0x14, 0x81, 0x33, 0x98, 0xcc, 0x52, 0x5d, 0x4c, 0x4e, 0x14, 0x6e, 0xde, 0xb3, 0x71, 0x26, 0x5f, 0xba, 0x19, 0x13, 0x3a, 0x2c, 0x3d, 0x21, 0x59, 0x29, 0x8a, 0x17, 0x42 }, + { 0xf6, 0x62, 0x0e, 0x68, 0xd3, 0x7f, 0xb2, 0xaf, 0x50, 0x00, 0xfc, 0x28, 0xe2, 0x3b, 0x83, 0x22, 0x97, 0xec, 0xd8, 0xbc, 0xe9, 0x9e, 0x8b, 0xe4, 0xd0, 0x4e, 0x85, 0x30, 0x9e, 0x3d, 0x33, 0x74 }, + { 0x53, 0x16, 0xa2, 0x79, 0x69, 0xd7, 0xfe, 0x04, 0xff, 0x27, 0xb2, 0x83, 0x96, 0x1b, 0xff, 0xc3, 0xbf, 0x5d, 0xfb, 0x32, 0xfb, 0x6a, 0x89, 0xd1, 0x01, 0xc6, 0xc3, 0xb1, 0x93, 0x7c, 0x28, 0x71 }, + { 0x81, 0xd1, 0x66, 0x4f, 0xdf, 0x3c, 0xb3, 0x3c, 0x24, 0xee, 0xba, 0xc0, 0xbd, 0x64, 0x24, 0x4b, 0x77, 0xc4, 0xab, 0xea, 0x90, 0xbb, 0xe8, 0xb5, 0xee, 0x0b, 0x2a, 0xaf, 0xcf, 0x2d, 0x6a, 0x53 }, + { 0x34, 0x57, 0x82, 0xf2, 0x95, 0xb0, 0x88, 0x03, 0x52, 0xe9, 0x24, 0xa0, 0x46, 0x7b, 0x5f, 0xbc, 0x3e, 0x8f, 0x3b, 0xfb, 0xc3, 0xc7, 0xe4, 0x8b, 0x67, 0x09, 0x1f, 0xb5, 0xe8, 0x0a, 0x94, 0x42 }, + { 0x79, 0x41, 0x11, 0xea, 0x6c, 0xd6, 0x5e, 0x31, 0x1f, 0x74, 0xee, 0x41, 0xd4, 0x76, 0xcb, 0x63, 0x2c, 0xe1, 0xe4, 0xb0, 0x51, 0xdc, 0x1d, 0x9e, 0x9d, 0x06, 0x1a, 0x19, 0xe1, 0xd0, 0xbb, 0x49 }, + { 0x2a, 0x85, 0xda, 0xf6, 0x13, 0x88, 0x16, 0xb9, 0x9b, 0xf8, 0xd0, 0x8b, 0xa2, 0x11, 0x4b, 0x7a, 0xb0, 0x79, 0x75, 0xa7, 0x84, 0x20, 0xc1, 0xa3, 0xb0, 0x6a, 0x77, 0x7c, 0x22, 0xdd, 0x8b, 0xcb }, + { 0x89, 0xb0, 0xd5, 0xf2, 0x89, 0xec, 0x16, 0x40, 0x1a, 0x06, 0x9a, 0x96, 0x0d, 0x0b, 0x09, 0x3e, 0x62, 0x5d, 0xa3, 0xcf, 0x41, 0xee, 0x29, 0xb5, 0x9b, 0x93, 0x0c, 0x58, 0x20, 0x14, 0x54, 0x55 }, + { 0xd0, 0xfd, 0xcb, 0x54, 0x39, 0x43, 0xfc, 0x27, 0xd2, 0x08, 0x64, 0xf5, 0x21, 0x81, 0x47, 0x1b, 0x94, 0x2c, 0xc7, 0x7c, 0xa6, 0x75, 0xbc, 0xb3, 0x0d, 0xf3, 0x1d, 0x35, 0x8e, 0xf7, 0xb1, 0xeb }, + { 0xb1, 0x7e, 0xa8, 0xd7, 0x70, 0x63, 0xc7, 0x09, 0xd4, 0xdc, 0x6b, 0x87, 0x94, 0x13, 0xc3, 0x43, 0xe3, 0x79, 0x0e, 0x9e, 0x62, 0xca, 0x85, 0xb7, 0x90, 0x0b, 0x08, 0x6f, 0x6b, 0x75, 0xc6, 0x72 }, + { 0xe7, 0x1a, 0x3e, 0x2c, 0x27, 0x4d, 0xb8, 0x42, 0xd9, 0x21, 0x14, 0xf2, 0x17, 0xe2, 0xc0, 0xea, 0xc8, 0xb4, 0x50, 0x93, 0xfd, 0xfd, 0x9d, 0xf4, 0xca, 0x71, 0x62, 0x39, 0x48, 0x62, 0xd5, 0x01 }, + { 0xc0, 0x47, 0x67, 0x59, 0xab, 0x7a, 0xa3, 0x33, 0x23, 0x4f, 0x6b, 0x44, 0xf5, 0xfd, 0x85, 0x83, 0x90, 0xec, 0x23, 0x69, 0x4c, 0x62, 0x2c, 0xb9, 0x86, 0xe7, 0x69, 0xc7, 0x8e, 0xdd, 0x73, 0x3e }, + { 0x9a, 0xb8, 0xea, 0xbb, 0x14, 0x16, 0x43, 0x4d, 0x85, 0x39, 0x13, 0x41, 0xd5, 0x69, 0x93, 0xc5, 0x54, 0x58, 0x16, 0x7d, 0x44, 0x18, 0xb1, 0x9a, 0x0f, 0x2a, 0xd8, 0xb7, 0x9a, 0x83, 0xa7, 0x5b }, + { 0x79, 0x92, 0xd0, 0xbb, 0xb1, 0x5e, 0x23, 0x82, 0x6f, 0x44, 0x3e, 0x00, 0x50, 0x5d, 0x68, 0xd3, 0xed, 0x73, 0x72, 0x99, 0x5a, 0x5c, 0x3e, 0x49, 0x86, 0x54, 0x10, 0x2f, 0xbc, 0xd0, 0x96, 0x4e }, + { 0xc0, 0x21, 0xb3, 0x00, 0x85, 0x15, 0x14, 0x35, 0xdf, 0x33, 0xb0, 0x07, 0xcc, 0xec, 0xc6, 0x9d, 0xf1, 0x26, 0x9f, 0x39, 0xba, 0x25, 0x09, 0x2b, 0xed, 0x59, 0xd9, 0x32, 0xac, 0x0f, 0xdc, 0x28 }, + { 0x91, 0xa2, 0x5e, 0xc0, 0xec, 0x0d, 0x9a, 0x56, 0x7f, 0x89, 0xc4, 0xbf, 0xe1, 0xa6, 0x5a, 0x0e, 0x43, 0x2d, 0x07, 0x06, 0x4b, 0x41, 0x90, 0xe2, 0x7d, 0xfb, 0x81, 0x90, 0x1f, 0xd3, 0x13, 0x9b }, + { 0x59, 0x50, 0xd3, 0x9a, 0x23, 0xe1, 0x54, 0x5f, 0x30, 0x12, 0x70, 0xaa, 0x1a, 0x12, 0xf2, 0xe6, 0xc4, 0x53, 0x77, 0x6e, 0x4d, 0x63, 0x55, 0xde, 0x42, 0x5c, 0xc1, 0x53, 0xf9, 0x81, 0x88, 0x67 }, + { 0xd7, 0x9f, 0x14, 0x72, 0x0c, 0x61, 0x0a, 0xf1, 0x79, 0xa3, 0x76, 0x5d, 0x4b, 0x7c, 0x09, 0x68, 0xf9, 0x77, 0x96, 0x2d, 0xbf, 0x65, 0x5b, 0x52, 0x12, 0x72, 0xb6, 0xf1, 0xe1, 0x94, 0x48, 0x8e }, + { 0xe9, 0x53, 0x1b, 0xfc, 0x8b, 0x02, 0x99, 0x5a, 0xea, 0xa7, 0x5b, 0xa2, 0x70, 0x31, 0xfa, 0xdb, 0xcb, 0xf4, 0xa0, 0xda, 0xb8, 0x96, 0x1d, 0x92, 0x96, 0xcd, 0x7e, 0x84, 0xd2, 0x5d, 0x60, 0x06 }, + { 0x34, 0xe9, 0xc2, 0x6a, 0x01, 0xd7, 0xf1, 0x61, 0x81, 0xb4, 0x54, 0xa9, 0xd1, 0x62, 0x3c, 0x23, 0x3c, 0xb9, 0x9d, 0x31, 0xc6, 0x94, 0x65, 0x6e, 0x94, 0x13, 0xac, 0xa3, 0xe9, 0x18, 0x69, 0x2f }, + { 0xd9, 0xd7, 0x42, 0x2f, 0x43, 0x7b, 0xd4, 0x39, 0xdd, 0xd4, 0xd8, 0x83, 0xda, 0xe2, 0xa0, 0x83, 0x50, 0x17, 0x34, 0x14, 0xbe, 0x78, 0x15, 0x51, 0x33, 0xff, 0xf1, 0x96, 0x4c, 0x3d, 0x79, 0x72 }, + { 0x4a, 0xee, 0x0c, 0x7a, 0xaf, 0x07, 0x54, 0x14, 0xff, 0x17, 0x93, 0xea, 0xd7, 0xea, 0xca, 0x60, 0x17, 0x75, 0xc6, 0x15, 0xdb, 0xd6, 0x0b, 0x64, 0x0b, 0x0a, 0x9f, 0x0c, 0xe5, 0x05, 0xd4, 0x35 }, + { 0x6b, 0xfd, 0xd1, 0x54, 0x59, 0xc8, 0x3b, 0x99, 0xf0, 0x96, 0xbf, 0xb4, 0x9e, 0xe8, 0x7b, 0x06, 0x3d, 0x69, 0xc1, 0x97, 0x4c, 0x69, 0x28, 0xac, 0xfc, 0xfb, 0x40, 0x99, 0xf8, 0xc4, 0xef, 0x67 }, + { 0x9f, 0xd1, 0xc4, 0x08, 0xfd, 0x75, 0xc3, 0x36, 0x19, 0x3a, 0x2a, 0x14, 0xd9, 0x4f, 0x6a, 0xf5, 0xad, 0xf0, 0x50, 0xb8, 0x03, 0x87, 0xb4, 0xb0, 0x10, 0xfb, 0x29, 0xf4, 0xcc, 0x72, 0x70, 0x7c }, + { 0x13, 0xc8, 0x84, 0x80, 0xa5, 0xd0, 0x0d, 0x6c, 0x8c, 0x7a, 0xd2, 0x11, 0x0d, 0x76, 0xa8, 0x2d, 0x9b, 0x70, 0xf4, 0xfa, 0x66, 0x96, 0xd4, 0xe5, 0xdd, 0x42, 0xa0, 0x66, 0xdc, 0xaf, 0x99, 0x20 }, + { 0x82, 0x0e, 0x72, 0x5e, 0xe2, 0x5f, 0xe8, 0xfd, 0x3a, 0x8d, 0x5a, 0xbe, 0x4c, 0x46, 0xc3, 0xba, 0x88, 0x9d, 0xe6, 0xfa, 0x91, 0x91, 0xaa, 0x22, 0xba, 0x67, 0xd5, 0x70, 0x54, 0x21, 0x54, 0x2b }, + { 0x32, 0xd9, 0x3a, 0x0e, 0xb0, 0x2f, 0x42, 0xfb, 0xbc, 0xaf, 0x2b, 0xad, 0x00, 0x85, 0xb2, 0x82, 0xe4, 0x60, 0x46, 0xa4, 0xdf, 0x7a, 0xd1, 0x06, 0x57, 0xc9, 0xd6, 0x47, 0x63, 0x75, 0xb9, 0x3e }, + { 0xad, 0xc5, 0x18, 0x79, 0x05, 0xb1, 0x66, 0x9c, 0xd8, 0xec, 0x9c, 0x72, 0x1e, 0x19, 0x53, 0x78, 0x6b, 0x9d, 0x89, 0xa9, 0xba, 0xe3, 0x07, 0x80, 0xf1, 0xe1, 0xea, 0xb2, 0x4a, 0x00, 0x52, 0x3c }, + { 0xe9, 0x07, 0x56, 0xff, 0x7f, 0x9a, 0xd8, 0x10, 0xb2, 0x39, 0xa1, 0x0c, 0xed, 0x2c, 0xf9, 0xb2, 0x28, 0x43, 0x54, 0xc1, 0xf8, 0xc7, 0xe0, 0xac, 0xcc, 0x24, 0x61, 0xdc, 0x79, 0x6d, 0x6e, 0x89 }, + { 0x12, 0x51, 0xf7, 0x6e, 0x56, 0x97, 0x84, 0x81, 0x87, 0x53, 0x59, 0x80, 0x1d, 0xb5, 0x89, 0xa0, 0xb2, 0x2f, 0x86, 0xd8, 0xd6, 0x34, 0xdc, 0x04, 0x50, 0x6f, 0x32, 0x2e, 0xd7, 0x8f, 0x17, 0xe8 }, + { 0x3a, 0xfa, 0x89, 0x9f, 0xd9, 0x80, 0xe7, 0x3e, 0xcb, 0x7f, 0x4d, 0x8b, 0x8f, 0x29, 0x1d, 0xc9, 0xaf, 0x79, 0x6b, 0xc6, 0x5d, 0x27, 0xf9, 0x74, 0xc6, 0xf1, 0x93, 0xc9, 0x19, 0x1a, 0x09, 0xfd }, + { 0xaa, 0x30, 0x5b, 0xe2, 0x6e, 0x5d, 0xed, 0xdc, 0x3c, 0x10, 0x10, 0xcb, 0xc2, 0x13, 0xf9, 0x5f, 0x05, 0x1c, 0x78, 0x5c, 0x5b, 0x43, 0x1e, 0x6a, 0x7c, 0xd0, 0x48, 0xf1, 0x61, 0x78, 0x75, 0x28 }, + { 0x8e, 0xa1, 0x88, 0x4f, 0xf3, 0x2e, 0x9d, 0x10, 0xf0, 0x39, 0xb4, 0x07, 0xd0, 0xd4, 0x4e, 0x7e, 0x67, 0x0a, 0xbd, 0x88, 0x4a, 0xee, 0xe0, 0xfb, 0x75, 0x7a, 0xe9, 0x4e, 0xaa, 0x97, 0x37, 0x3d }, + { 0xd4, 0x82, 0xb2, 0x15, 0x5d, 0x4d, 0xec, 0x6b, 0x47, 0x36, 0xa1, 0xf1, 0x61, 0x7b, 0x53, 0xaa, 0xa3, 0x73, 0x10, 0x27, 0x7d, 0x3f, 0xef, 0x0c, 0x37, 0xad, 0x41, 0x76, 0x8f, 0xc2, 0x35, 0xb4 }, + { 0x4d, 0x41, 0x39, 0x71, 0x38, 0x7e, 0x7a, 0x88, 0x98, 0xa8, 0xdc, 0x2a, 0x27, 0x50, 0x07, 0x78, 0x53, 0x9e, 0xa2, 0x14, 0xa2, 0xdf, 0xe9, 0xb3, 0xd7, 0xe8, 0xeb, 0xdc, 0xe5, 0xcf, 0x3d, 0xb3 }, + { 0x69, 0x6e, 0x5d, 0x46, 0xe6, 0xc5, 0x7e, 0x87, 0x96, 0xe4, 0x73, 0x5d, 0x08, 0x91, 0x6e, 0x0b, 0x79, 0x29, 0xb3, 0xcf, 0x29, 0x8c, 0x29, 0x6d, 0x22, 0xe9, 0xd3, 0x01, 0x96, 0x53, 0x37, 0x1c }, + { 0x1f, 0x56, 0x47, 0xc1, 0xd3, 0xb0, 0x88, 0x22, 0x88, 0x85, 0x86, 0x5c, 0x89, 0x40, 0x90, 0x8b, 0xf4, 0x0d, 0x1a, 0x82, 0x72, 0x82, 0x19, 0x73, 0xb1, 0x60, 0x00, 0x8e, 0x7a, 0x3c, 0xe2, 0xeb }, + { 0xb6, 0xe7, 0x6c, 0x33, 0x0f, 0x02, 0x1a, 0x5b, 0xda, 0x65, 0x87, 0x50, 0x10, 0xb0, 0xed, 0xf0, 0x91, 0x26, 0xc0, 0xf5, 0x10, 0xea, 0x84, 0x90, 0x48, 0x19, 0x20, 0x03, 0xae, 0xf4, 0xc6, 0x1c }, + { 0x3c, 0xd9, 0x52, 0xa0, 0xbe, 0xad, 0xa4, 0x1a, 0xbb, 0x42, 0x4c, 0xe4, 0x7f, 0x94, 0xb4, 0x2b, 0xe6, 0x4e, 0x1f, 0xfb, 0x0f, 0xd0, 0x78, 0x22, 0x76, 0x80, 0x79, 0x46, 0xd0, 0xd0, 0xbc, 0x55 }, + { 0x98, 0xd9, 0x26, 0x77, 0x43, 0x9b, 0x41, 0xb7, 0xbb, 0x51, 0x33, 0x12, 0xaf, 0xb9, 0x2b, 0xcc, 0x8e, 0xe9, 0x68, 0xb2, 0xe3, 0xb2, 0x38, 0xce, 0xcb, 0x9b, 0x0f, 0x34, 0xc9, 0xbb, 0x63, 0xd0 }, + { 0xec, 0xbc, 0xa2, 0xcf, 0x08, 0xae, 0x57, 0xd5, 0x17, 0xad, 0x16, 0x15, 0x8a, 0x32, 0xbf, 0xa7, 0xdc, 0x03, 0x82, 0xea, 0xed, 0xa1, 0x28, 0xe9, 0x18, 0x86, 0x73, 0x4c, 0x24, 0xa0, 0xb2, 0x9d }, + { 0x94, 0x2c, 0xc7, 0xc0, 0xb5, 0x2e, 0x2b, 0x16, 0xa4, 0xb8, 0x9f, 0xa4, 0xfc, 0x7e, 0x0b, 0xf6, 0x09, 0xe2, 0x9a, 0x08, 0xc1, 0xa8, 0x54, 0x34, 0x52, 0xb7, 0x7c, 0x7b, 0xfd, 0x11, 0xbb, 0x28 }, + { 0x8a, 0x06, 0x5d, 0x8b, 0x61, 0xa0, 0xdf, 0xfb, 0x17, 0x0d, 0x56, 0x27, 0x73, 0x5a, 0x76, 0xb0, 0xe9, 0x50, 0x60, 0x37, 0x80, 0x8c, 0xba, 0x16, 0xc3, 0x45, 0x00, 0x7c, 0x9f, 0x79, 0xcf, 0x8f }, + { 0x1b, 0x9f, 0xa1, 0x97, 0x14, 0x65, 0x9c, 0x78, 0xff, 0x41, 0x38, 0x71, 0x84, 0x92, 0x15, 0x36, 0x10, 0x29, 0xac, 0x80, 0x2b, 0x1c, 0xbc, 0xd5, 0x4e, 0x40, 0x8b, 0xd8, 0x72, 0x87, 0xf8, 0x1f }, + { 0x8d, 0xab, 0x07, 0x1b, 0xcd, 0x6c, 0x72, 0x92, 0xa9, 0xef, 0x72, 0x7b, 0x4a, 0xe0, 0xd8, 0x67, 0x13, 0x30, 0x1d, 0xa8, 0x61, 0x8d, 0x9a, 0x48, 0xad, 0xce, 0x55, 0xf3, 0x03, 0xa8, 0x69, 0xa1 }, + { 0x82, 0x53, 0xe3, 0xe7, 0xc7, 0xb6, 0x84, 0xb9, 0xcb, 0x2b, 0xeb, 0x01, 0x4c, 0xe3, 0x30, 0xff, 0x3d, 0x99, 0xd1, 0x7a, 0xbb, 0xdb, 0xab, 0xe4, 0xf4, 0xd6, 0x74, 0xde, 0xd5, 0x3f, 0xfc, 0x6b }, + { 0xf1, 0x95, 0xf3, 0x21, 0xe9, 0xe3, 0xd6, 0xbd, 0x7d, 0x07, 0x45, 0x04, 0xdd, 0x2a, 0xb0, 0xe6, 0x24, 0x1f, 0x92, 0xe7, 0x84, 0xb1, 0xaa, 0x27, 0x1f, 0xf6, 0x48, 0xb1, 0xca, 0xb6, 0xd7, 0xf6 }, + { 0x27, 0xe4, 0xcc, 0x72, 0x09, 0x0f, 0x24, 0x12, 0x66, 0x47, 0x6a, 0x7c, 0x09, 0x49, 0x5f, 0x2d, 0xb1, 0x53, 0xd5, 0xbc, 0xbd, 0x76, 0x19, 0x03, 0xef, 0x79, 0x27, 0x5e, 0xc5, 0x6b, 0x2e, 0xd8 }, + { 0x89, 0x9c, 0x24, 0x05, 0x78, 0x8e, 0x25, 0xb9, 0x9a, 0x18, 0x46, 0x35, 0x5e, 0x64, 0x6d, 0x77, 0xcf, 0x40, 0x00, 0x83, 0x41, 0x5f, 0x7d, 0xc5, 0xaf, 0xe6, 0x9d, 0x6e, 0x17, 0xc0, 0x00, 0x23 }, + { 0xa5, 0x9b, 0x78, 0xc4, 0x90, 0x57, 0x44, 0x07, 0x6b, 0xfe, 0xe8, 0x94, 0xde, 0x70, 0x7d, 0x4f, 0x12, 0x0b, 0x5c, 0x68, 0x93, 0xea, 0x04, 0x00, 0x29, 0x7d, 0x0b, 0xb8, 0x34, 0x72, 0x76, 0x32 }, + { 0x59, 0xdc, 0x78, 0xb1, 0x05, 0x64, 0x97, 0x07, 0xa2, 0xbb, 0x44, 0x19, 0xc4, 0x8f, 0x00, 0x54, 0x00, 0xd3, 0x97, 0x3d, 0xe3, 0x73, 0x66, 0x10, 0x23, 0x04, 0x35, 0xb1, 0x04, 0x24, 0xb2, 0x4f }, + { 0xc0, 0x14, 0x9d, 0x1d, 0x7e, 0x7a, 0x63, 0x53, 0xa6, 0xd9, 0x06, 0xef, 0xe7, 0x28, 0xf2, 0xf3, 0x29, 0xfe, 0x14, 0xa4, 0x14, 0x9a, 0x3e, 0xa7, 0x76, 0x09, 0xbc, 0x42, 0xb9, 0x75, 0xdd, 0xfa }, + { 0xa3, 0x2f, 0x24, 0x14, 0x74, 0xa6, 0xc1, 0x69, 0x32, 0xe9, 0x24, 0x3b, 0xe0, 0xcf, 0x09, 0xbc, 0xdc, 0x7e, 0x0c, 0xa0, 0xe7, 0xa6, 0xa1, 0xb9, 0xb1, 0xa0, 0xf0, 0x1e, 0x41, 0x50, 0x23, 0x77 }, + { 0xb2, 0x39, 0xb2, 0xe4, 0xf8, 0x18, 0x41, 0x36, 0x1c, 0x13, 0x39, 0xf6, 0x8e, 0x2c, 0x35, 0x9f, 0x92, 0x9a, 0xf9, 0xad, 0x9f, 0x34, 0xe0, 0x1a, 0xab, 0x46, 0x31, 0xad, 0x6d, 0x55, 0x00, 0xb0 }, + { 0x85, 0xfb, 0x41, 0x9c, 0x70, 0x02, 0xa3, 0xe0, 0xb4, 0xb6, 0xea, 0x09, 0x3b, 0x4c, 0x1a, 0xc6, 0x93, 0x66, 0x45, 0xb6, 0x5d, 0xac, 0x5a, 0xc1, 0x5a, 0x85, 0x28, 0xb7, 0xb9, 0x4c, 0x17, 0x54 }, + { 0x96, 0x19, 0x72, 0x06, 0x25, 0xf1, 0x90, 0xb9, 0x3a, 0x3f, 0xad, 0x18, 0x6a, 0xb3, 0x14, 0x18, 0x96, 0x33, 0xc0, 0xd3, 0xa0, 0x1e, 0x6f, 0x9b, 0xc8, 0xc4, 0xa8, 0xf8, 0x2f, 0x38, 0x3d, 0xbf }, + { 0x7d, 0x62, 0x0d, 0x90, 0xfe, 0x69, 0xfa, 0x46, 0x9a, 0x65, 0x38, 0x38, 0x89, 0x70, 0xa1, 0xaa, 0x09, 0xbb, 0x48, 0xa2, 0xd5, 0x9b, 0x34, 0x7b, 0x97, 0xe8, 0xce, 0x71, 0xf4, 0x8c, 0x7f, 0x46 }, + { 0x29, 0x43, 0x83, 0x56, 0x85, 0x96, 0xfb, 0x37, 0xc7, 0x5b, 0xba, 0xcd, 0x97, 0x9c, 0x5f, 0xf6, 0xf2, 0x0a, 0x55, 0x6b, 0xf8, 0x87, 0x9c, 0xc7, 0x29, 0x24, 0x85, 0x5d, 0xf9, 0xb8, 0x24, 0x0e }, + { 0x16, 0xb1, 0x8a, 0xb3, 0x14, 0x35, 0x9c, 0x2b, 0x83, 0x3c, 0x1c, 0x69, 0x86, 0xd4, 0x8c, 0x55, 0xa9, 0xfc, 0x97, 0xcd, 0xe9, 0xa3, 0xc1, 0xf1, 0x0a, 0x31, 0x77, 0x14, 0x0f, 0x73, 0xf7, 0x38 }, + { 0x8c, 0xbb, 0xdd, 0x14, 0xbc, 0x33, 0xf0, 0x4c, 0xf4, 0x58, 0x13, 0xe4, 0xa1, 0x53, 0xa2, 0x73, 0xd3, 0x6a, 0xda, 0xd5, 0xce, 0x71, 0xf4, 0x99, 0xee, 0xb8, 0x7f, 0xb8, 0xac, 0x63, 0xb7, 0x29 }, + { 0x69, 0xc9, 0xa4, 0x98, 0xdb, 0x17, 0x4e, 0xca, 0xef, 0xcc, 0x5a, 0x3a, 0xc9, 0xfd, 0xed, 0xf0, 0xf8, 0x13, 0xa5, 0xbe, 0xc7, 0x27, 0xf1, 0xe7, 0x75, 0xba, 0xbd, 0xec, 0x77, 0x18, 0x81, 0x6e }, + { 0xb4, 0x62, 0xc3, 0xbe, 0x40, 0x44, 0x8f, 0x1d, 0x4f, 0x80, 0x62, 0x62, 0x54, 0xe5, 0x35, 0xb0, 0x8b, 0xc9, 0xcd, 0xcf, 0xf5, 0x99, 0xa7, 0x68, 0x57, 0x8d, 0x4b, 0x28, 0x81, 0xa8, 0xe3, 0xf0 }, + { 0x55, 0x3e, 0x9d, 0x9c, 0x5f, 0x36, 0x0a, 0xc0, 0xb7, 0x4a, 0x7d, 0x44, 0xe5, 0xa3, 0x91, 0xda, 0xd4, 0xce, 0xd0, 0x3e, 0x0c, 0x24, 0x18, 0x3b, 0x7e, 0x8e, 0xca, 0xbd, 0xf1, 0x71, 0x5a, 0x64 }, + { 0x7a, 0x7c, 0x55, 0xa5, 0x6f, 0xa9, 0xae, 0x51, 0xe6, 0x55, 0xe0, 0x19, 0x75, 0xd8, 0xa6, 0xff, 0x4a, 0xe9, 0xe4, 0xb4, 0x86, 0xfc, 0xbe, 0x4e, 0xac, 0x04, 0x45, 0x88, 0xf2, 0x45, 0xeb, 0xea }, + { 0x2a, 0xfd, 0xf3, 0xc8, 0x2a, 0xbc, 0x48, 0x67, 0xf5, 0xde, 0x11, 0x12, 0x86, 0xc2, 0xb3, 0xbe, 0x7d, 0x6e, 0x48, 0x65, 0x7b, 0xa9, 0x23, 0xcf, 0xbf, 0x10, 0x1a, 0x6d, 0xfc, 0xf9, 0xdb, 0x9a }, + { 0x41, 0x03, 0x7d, 0x2e, 0xdc, 0xdc, 0xe0, 0xc4, 0x9b, 0x7f, 0xb4, 0xa6, 0xaa, 0x09, 0x99, 0xca, 0x66, 0x97, 0x6c, 0x74, 0x83, 0xaf, 0xe6, 0x31, 0xd4, 0xed, 0xa2, 0x83, 0x14, 0x4f, 0x6d, 0xfc }, + { 0xc4, 0x46, 0x6f, 0x84, 0x97, 0xca, 0x2e, 0xeb, 0x45, 0x83, 0xa0, 0xb0, 0x8e, 0x9d, 0x9a, 0xc7, 0x43, 0x95, 0x70, 0x9f, 0xda, 0x10, 0x9d, 0x24, 0xf2, 0xe4, 0x46, 0x21, 0x96, 0x77, 0x9c, 0x5d }, + { 0x75, 0xf6, 0x09, 0x33, 0x8a, 0xa6, 0x7d, 0x96, 0x9a, 0x2a, 0xe2, 0xa2, 0x36, 0x2b, 0x2d, 0xa9, 0xd7, 0x7c, 0x69, 0x5d, 0xfd, 0x1d, 0xf7, 0x22, 0x4a, 0x69, 0x01, 0xdb, 0x93, 0x2c, 0x33, 0x64 }, + { 0x68, 0x60, 0x6c, 0xeb, 0x98, 0x9d, 0x54, 0x88, 0xfc, 0x7c, 0xf6, 0x49, 0xf3, 0xd7, 0xc2, 0x72, 0xef, 0x05, 0x5d, 0xa1, 0xa9, 0x3f, 0xae, 0xcd, 0x55, 0xfe, 0x06, 0xf6, 0x96, 0x70, 0x98, 0xca }, + { 0x44, 0x34, 0x6b, 0xde, 0xb7, 0xe0, 0x52, 0xf6, 0x25, 0x50, 0x48, 0xf0, 0xd9, 0xb4, 0x2c, 0x42, 0x5b, 0xab, 0x9c, 0x3d, 0xd2, 0x41, 0x68, 0x21, 0x2c, 0x3e, 0xcf, 0x1e, 0xbf, 0x34, 0xe6, 0xae }, + { 0x8e, 0x9c, 0xf6, 0xe1, 0xf3, 0x66, 0x47, 0x1f, 0x2a, 0xc7, 0xd2, 0xee, 0x9b, 0x5e, 0x62, 0x66, 0xfd, 0xa7, 0x1f, 0x8f, 0x2e, 0x41, 0x09, 0xf2, 0x23, 0x7e, 0xd5, 0xf8, 0x81, 0x3f, 0xc7, 0x18 }, + { 0x84, 0xbb, 0xeb, 0x84, 0x06, 0xd2, 0x50, 0x95, 0x1f, 0x8c, 0x1b, 0x3e, 0x86, 0xa7, 0xc0, 0x10, 0x08, 0x29, 0x21, 0x83, 0x3d, 0xfd, 0x95, 0x55, 0xa2, 0xf9, 0x09, 0xb1, 0x08, 0x6e, 0xb4, 0xb8 }, + { 0xee, 0x66, 0x6f, 0x3e, 0xef, 0x0f, 0x7e, 0x2a, 0x9c, 0x22, 0x29, 0x58, 0xc9, 0x7e, 0xaf, 0x35, 0xf5, 0x1c, 0xed, 0x39, 0x3d, 0x71, 0x44, 0x85, 0xab, 0x09, 0xa0, 0x69, 0x34, 0x0f, 0xdf, 0x88 }, + { 0xc1, 0x53, 0xd3, 0x4a, 0x65, 0xc4, 0x7b, 0x4a, 0x62, 0xc5, 0xca, 0xcf, 0x24, 0x01, 0x09, 0x75, 0xd0, 0x35, 0x6b, 0x2f, 0x32, 0xc8, 0xf5, 0xda, 0x53, 0x0d, 0x33, 0x88, 0x16, 0xad, 0x5d, 0xe6 }, + { 0x9f, 0xc5, 0x45, 0x01, 0x09, 0xe1, 0xb7, 0x79, 0xf6, 0xc7, 0xae, 0x79, 0xd5, 0x6c, 0x27, 0x63, 0x5c, 0x8d, 0xd4, 0x26, 0xc5, 0xa9, 0xd5, 0x4e, 0x25, 0x78, 0xdb, 0x98, 0x9b, 0x8c, 0x3b, 0x4e }, + { 0xd1, 0x2b, 0xf3, 0x73, 0x2e, 0xf4, 0xaf, 0x5c, 0x22, 0xfa, 0x90, 0x35, 0x6a, 0xf8, 0xfc, 0x50, 0xfc, 0xb4, 0x0f, 0x8f, 0x2e, 0xa5, 0xc8, 0x59, 0x47, 0x37, 0xa3, 0xb3, 0xd5, 0xab, 0xdb, 0xd7 }, + { 0x11, 0x03, 0x0b, 0x92, 0x89, 0xbb, 0xa5, 0xaf, 0x65, 0x26, 0x06, 0x72, 0xab, 0x6f, 0xee, 0x88, 0xb8, 0x74, 0x20, 0xac, 0xef, 0x4a, 0x17, 0x89, 0xa2, 0x07, 0x3b, 0x7e, 0xc2, 0xf2, 0xa0, 0x9e }, + { 0x69, 0xcb, 0x19, 0x2b, 0x84, 0x44, 0x00, 0x5c, 0x8c, 0x0c, 0xeb, 0x12, 0xc8, 0x46, 0x86, 0x07, 0x68, 0x18, 0x8c, 0xda, 0x0a, 0xec, 0x27, 0xa9, 0xc8, 0xa5, 0x5c, 0xde, 0xe2, 0x12, 0x36, 0x32 }, + { 0xdb, 0x44, 0x4c, 0x15, 0x59, 0x7b, 0x5f, 0x1a, 0x03, 0xd1, 0xf9, 0xed, 0xd1, 0x6e, 0x4a, 0x9f, 0x43, 0xa6, 0x67, 0xcc, 0x27, 0x51, 0x75, 0xdf, 0xa2, 0xb7, 0x04, 0xe3, 0xbb, 0x1a, 0x9b, 0x83 }, + { 0x3f, 0xb7, 0x35, 0x06, 0x1a, 0xbc, 0x51, 0x9d, 0xfe, 0x97, 0x9e, 0x54, 0xc1, 0xee, 0x5b, 0xfa, 0xd0, 0xa9, 0xd8, 0x58, 0xb3, 0x31, 0x5b, 0xad, 0x34, 0xbd, 0xe9, 0x99, 0xef, 0xd7, 0x24, 0xdd }, + }; + unsigned char inp[1000], out[1000]; + unsigned char key[] = { 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 }; + unsigned long ilen, klen = sizeof(key), mlen = 32; + blake2smac_state st; + + for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen; + + for (ilen = 0; ilen < 256; ilen++) { + const unsigned char *mac = tests[ilen]; + unsigned long olen = mlen; + /* process piece by piece */ + if (ilen > 15) { + blake2smac_init(&st, olen, key, klen); + blake2smac_process(&st, (unsigned char*)inp, 5); + blake2smac_process(&st, (unsigned char*)inp + 5, 4); + blake2smac_process(&st, (unsigned char*)inp + 9, 3); + blake2smac_process(&st, (unsigned char*)inp + 12, 2); + blake2smac_process(&st, (unsigned char*)inp + 14, 1); + blake2smac_process(&st, (unsigned char*)inp + 15, ilen - 15); + blake2smac_done(&st, out, &olen); + if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; + } + /* process in one go */ + blake2smac_init(&st, olen, key, klen); + blake2smac_process(&st, (unsigned char*)inp, ilen); + blake2smac_done(&st, out, &olen); + if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_done.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_done.c new file mode 100644 index 0000000..53ed13f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_done.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_done.c + f9 Support, terminate the state +*/ + +#ifdef LTC_F9_MODE + +/** Terminate the f9-MAC state + @param f9 f9 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 f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen) +{ + int err, x; + LTC_ARGCHK(f9 != NULL); + LTC_ARGCHK(out != NULL); + + /* check structure */ + if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) { + return err; + } + + if ((f9->blocksize > cipher_descriptor[f9->cipher]->block_length) || (f9->blocksize < 0) || + (f9->buflen > f9->blocksize) || (f9->buflen < 0)) { + return CRYPT_INVALID_ARG; + } + + if (f9->buflen != 0) { + /* encrypt */ + cipher_descriptor[f9->cipher]->ecb_encrypt(f9->IV, f9->IV, &f9->key); + f9->buflen = 0; + for (x = 0; x < f9->blocksize; x++) { + f9->ACC[x] ^= f9->IV[x]; + } + } + + /* schedule modified key */ + if ((err = cipher_descriptor[f9->cipher]->setup(f9->akey, f9->keylen, 0, &f9->key)) != CRYPT_OK) { + return err; + } + + /* encrypt the ACC */ + cipher_descriptor[f9->cipher]->ecb_encrypt(f9->ACC, f9->ACC, &f9->key); + cipher_descriptor[f9->cipher]->done(&f9->key); + + /* extract tag */ + for (x = 0; x < f9->blocksize && (unsigned long)x < *outlen; x++) { + out[x] = f9->ACC[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(f9, sizeof(*f9)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_file.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_file.c new file mode 100644 index 0000000..c06f548 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_file.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_file.c + f9 support, process a file, Tom St Denis +*/ + +#ifdef LTC_F9_MODE + +/** + f9 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 fname The name of the file you wish to f9 + @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 f9_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *fname, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + size_t x; + int err; + f9_state f9; + FILE *in; + unsigned char *buf; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = f9_init(&f9, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = f9_process(&f9, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = f9_done(&f9, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&f9, sizeof(f9_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_init.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_init.c new file mode 100644 index 0000000..7a9ed55 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_init.c @@ -0,0 +1,58 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_init.c + F9 Support, start an F9 state +*/ + +#ifdef LTC_F9_MODE + +/** Initialize F9-MAC state + @param f9 [out] f9 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 f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen) +{ + int x, err; + + LTC_ARGCHK(f9 != 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 + + if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &f9->key)) != CRYPT_OK) { + goto done; + } + + /* make the second key */ + for (x = 0; (unsigned)x < keylen; x++) { + f9->akey[x] = key[x] ^ 0xAA; + } + + /* setup struct */ + zeromem(f9->IV, cipher_descriptor[cipher]->block_length); + zeromem(f9->ACC, cipher_descriptor[cipher]->block_length); + f9->blocksize = cipher_descriptor[cipher]->block_length; + f9->cipher = cipher; + f9->buflen = 0; + f9->keylen = keylen; +done: + return err; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory.c new file mode 100644 index 0000000..e55efcd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_process.c + f9 Support, Process a block through F9-MAC +*/ + +#ifdef LTC_F9_MODE + +/** f9-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 f9_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + f9_state *f9; + int err; + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* Use accelerator if found */ + if (cipher_descriptor[cipher]->f9_memory != NULL) { + return cipher_descriptor[cipher]->f9_memory(key, keylen, in, inlen, out, outlen); + } + + f9 = XCALLOC(1, sizeof(*f9)); + if (f9 == NULL) { + return CRYPT_MEM; + } + + if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) { + goto done; + } + + if ((err = f9_process(f9, in, inlen)) != CRYPT_OK) { + goto done; + } + + err = f9_done(f9, out, outlen); +done: + XFREE(f9); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c new file mode 100644 index 0000000..c97ffd3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file f9_memory_multi.c + f9 support, process multiple blocks of memory, Tom St Denis +*/ + +#ifdef LTC_F9_MODE + +/** + f9 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 f9 + @param inlen The length of the data to send through f9 (octets) + @param ... tuples of (data,len) pairs to f9, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +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 err; + f9_state *f9; + 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 f9 state */ + f9 = XMALLOC(sizeof(f9_state)); + if (f9 == NULL) { + return CRYPT_MEM; + } + + /* f9 process the message */ + if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = f9_process(f9, 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 = f9_done(f9, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(f9, sizeof(f9_state)); +#endif + XFREE(f9); + va_end(args); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_process.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_process.c new file mode 100644 index 0000000..c6ad743 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_process.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_process.c + f9 Support, process blocks with f9 +*/ + +#ifdef LTC_F9_MODE + +/** Process data through f9-MAC + @param f9 The f9-MAC state + @param in Input data to process + @param inlen Length of input in octets + Return CRYPT_OK on success +*/ +int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen) +{ + int err, x; + + LTC_ARGCHK(f9 != NULL); + LTC_ARGCHK(in != NULL); + + /* check structure */ + if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) { + return err; + } + + if ((f9->blocksize > cipher_descriptor[f9->cipher]->block_length) || (f9->blocksize < 0) || + (f9->buflen > f9->blocksize) || (f9->buflen < 0)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (f9->buflen == 0) { + while (inlen >= (unsigned long)f9->blocksize) { + for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x]))); + } + cipher_descriptor[f9->cipher]->ecb_encrypt(f9->IV, f9->IV, &f9->key); + for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&(f9->ACC[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))); + } + in += f9->blocksize; + inlen -= f9->blocksize; + } + } +#endif + + while (inlen) { + if (f9->buflen == f9->blocksize) { + cipher_descriptor[f9->cipher]->ecb_encrypt(f9->IV, f9->IV, &f9->key); + for (x = 0; x < f9->blocksize; x++) { + f9->ACC[x] ^= f9->IV[x]; + } + f9->buflen = 0; + } + f9->IV[f9->buflen++] ^= *in++; + --inlen; + } + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_test.c new file mode 100644 index 0000000..779fdf1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/f9/f9_test.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_test.c + f9 Support, Test F9 mode +*/ + +#ifdef LTC_F9_MODE + +/** Test f9-MAC mode + Return CRYPT_OK on success +*/ +int f9_test(void) +{ +#ifdef LTC_NO_TEST + return CRYPT_NOP; +#else + static const struct { + int msglen; + unsigned char K[16], M[128], T[4]; + } tests[] = { +{ + 20, + { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 }, + { 0x38, 0xA6, 0xF0, 0x56, 0xB8, 0xAE, 0xFD, 0xA9, 0x33, 0x32, 0x34, 0x62, 0x63, 0x39, 0x38, 0x61, 0x37, 0x34, 0x79, 0x40 }, + { 0x46, 0xE0, 0x0D, 0x4B } +}, + +{ + 105, + { 0x83, 0xFD, 0x23, 0xA2, 0x44, 0xA7, 0x4C, 0xF3, 0x58, 0xDA, 0x30, 0x19, 0xF1, 0x72, 0x26, 0x35 }, + { 0x36, 0xAF, 0x61, 0x44, 0x4F, 0x30, 0x2A, 0xD2, + 0x35, 0xC6, 0x87, 0x16, 0x63, 0x3C, 0x66, 0xFB, 0x75, 0x0C, 0x26, 0x68, 0x65, 0xD5, 0x3C, 0x11, 0xEA, 0x05, 0xB1, 0xE9, 0xFA, 0x49, 0xC8, 0x39, 0x8D, 0x48, 0xE1, 0xEF, 0xA5, 0x90, 0x9D, 0x39, + 0x47, 0x90, 0x28, 0x37, 0xF5, 0xAE, 0x96, 0xD5, 0xA0, 0x5B, 0xC8, 0xD6, 0x1C, 0xA8, 0xDB, 0xEF, 0x1B, 0x13, 0xA4, 0xB4, 0xAB, 0xFE, 0x4F, 0xB1, 0x00, 0x60, 0x45, 0xB6, 0x74, 0xBB, 0x54, 0x72, + 0x93, 0x04, 0xC3, 0x82, 0xBE, 0x53, 0xA5, 0xAF, 0x05, 0x55, 0x61, 0x76, 0xF6, 0xEA, 0xA2, 0xEF, 0x1D, 0x05, 0xE4, 0xB0, 0x83, 0x18, 0x1E, 0xE6, 0x74, 0xCD, 0xA5, 0xA4, 0x85, 0xF7, 0x4D, 0x7A, + 0x40|0x80 }, + { 0x95, 0xAE, 0x41, 0xBA }, +} +}; + unsigned char T[16]; + unsigned long taglen; + int err, x, idx; + + /* find kasumi */ + if ((idx = find_cipher("kasumi")) == -1) { + return CRYPT_NOP; + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + taglen = 4; + if ((err = f9_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) { + return err; + } + if (compare_testvector(T, taglen, tests[x].T, 4, "F9", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c new file mode 100644 index 0000000..60df551 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_done.c + HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash]->blocksize + +/** + Terminate an HMAC session + @param hmac The HMAC state + @param out [out] The destination of the HMAC authentication tag + @param outlen [in/out] The max size and resulting size of the 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 HMAC vector plus the data */ + if ((err = hash_descriptor[hash]->done(&hmac->md, isha)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* Create the second 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: +#ifdef LTC_CLEAN_STACK + zeromem(isha, hashsize); + zeromem(buf, hashsize); + zeromem(hmac, sizeof(*hmac)); +#endif + + XFREE(isha); + XFREE(buf); + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c new file mode 100644 index 0000000..c944a28 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_file.c + HMAC support, process a file, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + HMAC a file + @param hash The index of the hash you wish to use + @param fname The name of the file you wish to HMAC + @param key The secret key + @param keylen The length of the secret key + @param out [out] The 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 + LTC_UNUSED_PARAM(hash); + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + hmac_state hmac; + FILE *in; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); /* we don't trap this error since we're already returning an error! */ + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = hmac_done(&hmac, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&hmac, sizeof(hmac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c new file mode 100644 index 0000000..2904299 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c @@ -0,0 +1,94 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_init.c + HMAC support, initialize state, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash]->blocksize + +/** + Initialize an HMAC context. + @param hmac The 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; + } + + /* check hash block fits */ + if (sizeof(hmac->key) < LTC_HMAC_BLOCKSIZE) { + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* (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; + } + 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 initialization 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; + } + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, LTC_HMAC_BLOCKSIZE); +#endif + + XFREE(buf); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c new file mode 100644 index 0000000..5e7b847 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_memory.c + HMAC support, process a block of memory, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + 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 HMAC + @param inlen The length of the data to 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c new file mode 100644 index 0000000..2809d71 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file hmac_memory_multi.c + HMAC support, process multiple blocks of memory, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + 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 HMAC + @param inlen The length of the data to HMAC (octets) + @param ... tuples of (data,len) pairs to 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c new file mode 100644 index 0000000..85dda20 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_process.c + HMAC support, process data, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + Process data through HMAC + @param hmac The hmac state + @param in The data to send through HMAC + @param inlen The length of the data to 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c new file mode 100644 index 0000000..1226590 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c @@ -0,0 +1,618 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_test.c + HMAC support, self-test, Tom St Denis/Dobes Vandermeer/Steffen Jaeckel +*/ + +#ifdef LTC_HMAC + +/* + TEST CASES SOURCE: + +Network Working Group P. Cheng +Request for Comments: 2202 IBM +Category: Informational R. Glenn + NIST + September 1997 + + Test Cases for HMAC-MD5 and HMAC-SHA-1 + +******************************************************************************* + +Network Working Group J. Kapp +Request for Comments: 2286 Reaper Technologies +Category: Informational February 1998 + + Test Cases for HMAC-RIPEMD160 and HMAC-RIPEMD128 + +******************************************************************************* + +Network Working Group M. Nystrom +Request for Comments: 4231 RSA Security +Category: Standards Track December 2005 + + Identifiers and Test Vectors for HMAC-SHA-224, HMAC-SHA-256, + HMAC-SHA-384, and HMAC-SHA-512 +*/ + +/** + 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 unsigned char hmac_test_case_keys[][136] = { + { /* 1 */ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b + }, +#ifdef LTC_TEST_EXT + { /* 2 */ + 0x4a, 0x65, 0x66, 0x65 + }, + { /* 4 */ + 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 + }, + { /* 5 */ + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c + }, + { /* 3, 6, 7 */ + 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, + + 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 + } +#endif /* LTC_TEST_EXT */ + }; + + + static const unsigned char hmac_test_case_data[][153] = { + { + "Hi There" + }, +#ifdef LTC_TEST_EXT + { + "what do ya want for nothing?" + }, + { + 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 + }, + { + 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 + }, + { + "Test With Truncation" + }, + { + "Test Using Larger Than Block-Size Key - Hash Key First" + }, + { + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + }, + { + "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm." + } +#endif /* LTC_TEST_EXT */ + }; + + static const struct hmac_test_case { + const char *num; + const char *algo; + const unsigned char *key; + unsigned long keylen; + const unsigned char *data; + unsigned long datalen; + unsigned char digest[MAXBLOCKSIZE]; + } cases[] = { + /* + RFC 2202 3. Test Cases for HMAC-SHA-1 + */ + { "rfc2202 3.1", "sha1", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, + 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, + 0xf1, 0x46, 0xbe, 0x00} }, + +#ifdef LTC_TEST_EXT + { "rfc2202 3.2", "sha1", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, + 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, + 0x25, 0x9a, 0x7c, 0x79} }, + + { "rfc2202 3.3", "sha1", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, + 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, + 0x63, 0xf1, 0x75, 0xd3} }, + + { "rfc2202 3.4", "sha1", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, + 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, + 0x2d, 0x72, 0x35, 0xda} }, + + { "rfc2202 3.5", "sha1", + hmac_test_case_keys[3], 20, + hmac_test_case_data[4], 20, + {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, + 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} }, + + { "rfc2202 3.6", "sha1", + hmac_test_case_keys[4], 80, + hmac_test_case_data[5], 54, + {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, + 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, + 0xed, 0x40, 0x21, 0x12} }, + + { "rfc2202 3.7", "sha1", + hmac_test_case_keys[4], 80, + hmac_test_case_data[6], 73, + {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, + 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} }, +#endif /* LTC_TEST_EXT */ + + /* + RFC 2202 2. Test Cases for HMAC-MD5 + */ + { "rfc2202 2.1", "md5", + hmac_test_case_keys[0], 16, + hmac_test_case_data[0], 8, + {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} }, + +#ifdef LTC_TEST_EXT + { "rfc2202 2.2", "md5", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} }, + + { "rfc2202 2.3", "md5", + hmac_test_case_keys[4], 16, + hmac_test_case_data[2], 50, + {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} }, + + { "rfc2202 2.4", "md5", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, + 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} }, + + { "rfc2202 2.5", "md5", + hmac_test_case_keys[3], 16, + hmac_test_case_data[4], 20, + {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, + 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} }, + + { "rfc2202 2.6", "md5", + hmac_test_case_keys[4], 80, + hmac_test_case_data[5], 54, + {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, + 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} }, + + { "rfc2202 2.7", "md5", + hmac_test_case_keys[4], 80, + hmac_test_case_data[6], 73, + {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, + 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} }, +#endif /* LTC_TEST_EXT */ + + /* + RFC 2286 2. Test Cases for HMAC-RIPEMD160 + */ + { "rfc2286 2.1", "rmd160", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0x24, 0xcb, 0x4b, 0xd6, 0x7d, 0x20, 0xfc, 0x1a, + 0x5d, 0x2e, 0xd7, 0x73, 0x2d, 0xcc, 0x39, 0x37, + 0x7f, 0x0a, 0x56, 0x68} }, + +#ifdef LTC_TEST_EXT + { "rfc2286 2.2", "rmd160", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0xdd, 0xa6, 0xc0, 0x21, 0x3a, 0x48, 0x5a, 0x9e, + 0x24, 0xf4, 0x74, 0x20, 0x64, 0xa7, 0xf0, 0x33, + 0xb4, 0x3c, 0x40, 0x69} }, + + { "rfc2286 2.3", "rmd160", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0xb0, 0xb1, 0x05, 0x36, 0x0d, 0xe7, 0x59, 0x96, + 0x0a, 0xb4, 0xf3, 0x52, 0x98, 0xe1, 0x16, 0xe2, + 0x95, 0xd8, 0xe7, 0xc1} }, + + { "rfc2286 2.4", "rmd160", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0xd5, 0xca, 0x86, 0x2f, 0x4d, 0x21, 0xd5, 0xe6, + 0x10, 0xe1, 0x8b, 0x4c, 0xf1, 0xbe, 0xb9, 0x7a, + 0x43, 0x65, 0xec, 0xf4} }, + + { "rfc2286 2.5", "rmd160", + hmac_test_case_keys[3], 20, + hmac_test_case_data[4], 20, + {0x76, 0x19, 0x69, 0x39, 0x78, 0xf9, 0x1d, 0x90, + 0x53, 0x9a, 0xe7, 0x86, 0x50, 0x0f, 0xf3, 0xd8, + 0xe0, 0x51, 0x8e, 0x39} }, + + { "rfc2286 2.6", "rmd160", + hmac_test_case_keys[4], 80, + hmac_test_case_data[5], 54, + {0x64, 0x66, 0xca, 0x07, 0xac, 0x5e, 0xac, 0x29, + 0xe1, 0xbd, 0x52, 0x3e, 0x5a, 0xda, 0x76, 0x05, + 0xb7, 0x91, 0xfd, 0x8b} }, + + { "rfc2286 2.7", "rmd160", + hmac_test_case_keys[4], 80, + hmac_test_case_data[6], 73, + {0x69, 0xea, 0x60, 0x79, 0x8d, 0x71, 0x61, 0x6c, + 0xce, 0x5f, 0xd0, 0x87, 0x1e, 0x23, 0x75, 0x4c, + 0xd7, 0x5d, 0x5a, 0x0a} }, +#endif /* LTC_TEST_EXT */ + + /* + RFC 2286 3. Test Cases for HMAC-RIPEMD128 + */ + { "rfc2286 3.1", "rmd128", + hmac_test_case_keys[0], 16, + hmac_test_case_data[0], 8, + {0xfb, 0xf6, 0x1f, 0x94, 0x92, 0xaa, 0x4b, 0xbf, + 0x81, 0xc1, 0x72, 0xe8, 0x4e, 0x07, 0x34, 0xdb} }, + +#ifdef LTC_TEST_EXT + { "rfc2286 3.2", "rmd128", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x87, 0x5f, 0x82, 0x88, 0x62, 0xb6, 0xb3, 0x34, + 0xb4, 0x27, 0xc5, 0x5f, 0x9f, 0x7f, 0xf0, 0x9b} }, + + { "rfc2286 3.3", "rmd128", + hmac_test_case_keys[4], 16, + hmac_test_case_data[2], 50, + {0x09, 0xf0, 0xb2, 0x84, 0x6d, 0x2f, 0x54, 0x3d, + 0xa3, 0x63, 0xcb, 0xec, 0x8d, 0x62, 0xa3, 0x8d} }, + + { "rfc2286 3.4", "rmd128", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0xbd, 0xbb, 0xd7, 0xcf, 0x03, 0xe4, 0x4b, 0x5a, + 0xa6, 0x0a, 0xf8, 0x15, 0xbe, 0x4d, 0x22, 0x94} }, + + { "rfc2286 3.5", "rmd128", + hmac_test_case_keys[3], 16, + hmac_test_case_data[4], 20, + {0xe7, 0x98, 0x08, 0xf2, 0x4b, 0x25, 0xfd, 0x03, + 0x1c, 0x15, 0x5f, 0x0d, 0x55, 0x1d, 0x9a, 0x3a} }, + + { "rfc2286 3.6", "rmd128", + hmac_test_case_keys[4], 80, + hmac_test_case_data[5], 54, + {0xdc, 0x73, 0x29, 0x28, 0xde, 0x98, 0x10, 0x4a, + 0x1f, 0x59, 0xd3, 0x73, 0xc1, 0x50, 0xac, 0xbb} }, + + { "rfc2286 3.7", "rmd128", + hmac_test_case_keys[4], 80, + hmac_test_case_data[6], 73, + {0x5c, 0x6b, 0xec, 0x96, 0x79, 0x3e, 0x16, 0xd4, + 0x06, 0x90, 0xc2, 0x37, 0x63, 0x5f, 0x30, 0xc5} }, +#endif /* LTC_TEST_EXT */ + + /* + RFC 4231 4. Test Vectors + Ch. 4.6 with truncated output left out to simplify tests + */ + { "rfc4231 4.2", "sha224", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, + 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f, + 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, + 0x53, 0x68, 0x4b, 0x22} }, + +#ifdef LTC_TEST_EXT + { "rfc4231 4.3", "sha224", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, + 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, + 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, + 0x8f, 0xd0, 0x5e, 0x44} }, + + { "rfc4231 4.4", "sha224", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, + 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64, + 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, + 0xec, 0x83, 0x33, 0xea} }, + + { "rfc4231 4.5", "sha224", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, + 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c, + 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, + 0xe7, 0xaf, 0xec, 0x5a} }, + + { "rfc4231 4.7", "sha224", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, + 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2, + 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, + 0x3f, 0xa6, 0x87, 0x0e} }, + + { "rfc4231 4.8", "sha224", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, + 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd, + 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, + 0xf6, 0xf5, 0x65, 0xd1} }, +#endif /* LTC_TEST_EXT */ + + { "rfc4231 4.2", "sha256", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, + 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, + 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, + 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7} }, + +#ifdef LTC_TEST_EXT + { "rfc4231 4.3", "sha256", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, + 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, + 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, + 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43} }, + + { "rfc4231 4.4", "sha256", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, + 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, + 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, + 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe} }, + + { "rfc4231 4.5", "sha256", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, + 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, + 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, + 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b} }, + + { "rfc4231 4.7", "sha256", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, + 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, + 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, + 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54} }, + + { "rfc4231 4.8", "sha256", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, + 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, + 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, + 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} }, +#endif /* LTC_TEST_EXT */ + + { "rfc4231 4.2", "sha384", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, + 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f, + 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, + 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, + 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, + 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6} }, + +#ifdef LTC_TEST_EXT + { "rfc4231 4.3", "sha384", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, + 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, + 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, + 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, + 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, + 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49} }, + + { "rfc4231 4.4", "sha384", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, + 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f, + 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, + 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, + 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, + 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27} }, + + { "rfc4231 4.5", "sha384", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, + 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7, + 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c, + 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, + 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79, + 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb} }, + + { "rfc4231 4.7", "sha384", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, + 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4, + 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, + 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, + 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, + 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52} }, + + { "rfc4231 4.8", "sha384", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, + 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c, + 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a, + 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, + 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d, + 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e} }, +#endif /* LTC_TEST_EXT */ + + { "rfc4231 4.2", "sha512", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, + 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, + 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, + 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, + 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, + 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, + 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, + 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54} }, + +#ifdef LTC_TEST_EXT + { "rfc4231 4.3", "sha512", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, + 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, + 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, + 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, + 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, + 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, + 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, + 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37} }, + + { "rfc4231 4.4", "sha512", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, + 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, + 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, + 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, + 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, + 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, + 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, + 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb} }, + + { "rfc4231 4.5", "sha512", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, + 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, + 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, + 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, + 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, + 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63, + 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, + 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd} }, + + { "rfc4231 4.7", "sha512", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, + 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4, + 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, + 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, + 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, + 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, + 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, + 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98} }, + + { "rfc4231 4.8", "sha512", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, + 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd, + 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, + 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, + 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1, + 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, + 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, + 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58} }, +#endif /* LTC_TEST_EXT */ + + }; + + 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) { +#ifdef LTC_TEST_DBG + printf("HMAC-%s test %s, %s\n", cases[i].algo, cases[i].num, error_to_string(err)); +#endif + return err; + } + + if(compare_testvector(digest, outlen, cases[i].digest, (size_t)hash_descriptor[hash]->hashsize, cases[i].num, i)) { + failed++; + } + } + + if (failed != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + if (tested == 0) { + return CRYPT_NOP; + } + return CRYPT_OK; + #endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/sub.mk new file mode 100644 index 0000000..2b8702f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/hmac/sub.mk @@ -0,0 +1,7 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += hmac_done.c +srcs-y += hmac_init.c +srcs-y += hmac_memory.c +srcs-y += hmac_memory_multi.c +srcs-y += hmac_process.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_done.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_done.c new file mode 100644 index 0000000..2f36a88 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_done.c @@ -0,0 +1,74 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_done.c + OMAC1 support, terminate a stream, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + Terminate an OMAC stream + @param omac The 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_file.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_file.c new file mode 100644 index 0000000..012958a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_file.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_file.c + OMAC1 support, process a file, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + 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 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 + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + size_t x; + int err; + omac_state omac; + FILE *in; + unsigned char *buf; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(filename, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = omac_process(&omac, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = omac_done(&omac, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&omac, sizeof(omac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_init.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_init.c new file mode 100644 index 0000000..a287a5e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_init.c @@ -0,0 +1,89 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_init.c + OMAC1 support, initialize state, by Tom St Denis +*/ + + +#ifdef LTC_OMAC + +/** + Initialize an OMAC state + @param omac The 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory.c new file mode 100644 index 0000000..c3ae9f9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_memory.c + OMAC1 support, process a block of memory, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + 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 OMAC + @param inlen The length of the data to send through 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c new file mode 100644 index 0000000..4f3b708 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file omac_memory_multi.c + OMAC1 support, process multiple blocks of memory, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + 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 OMAC + @param inlen The length of the data to send through OMAC (octets) + @param ... tuples of (data,len) pairs to 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_process.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_process.c new file mode 100644 index 0000000..e065eb4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_process.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_process.c + OMAC1 support, process data, Tom St Denis +*/ + + +#ifdef LTC_OMAC + +/** + Process data through OMAC + @param omac The OMAC state + @param in The input data to send through 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_PTR_CAST(&omac->prev[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_test.c new file mode 100644 index 0000000..bca6d9c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/omac_test.c @@ -0,0 +1,93 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_test.c + OMAC1 support, self-test, by Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + Test the 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 (compare_testvector(out, len, tests[x].tag, sizeof(tests[x].tag), "OMAC", x) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/sub.mk new file mode 100644 index 0000000..c0de70b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/omac/sub.mk @@ -0,0 +1,7 @@ +cflags-y += -Wno-unused-parameter + +srcs-y += omac_done.c +srcs-y += omac_init.c +srcs-y += omac_memory.c +srcs-y += omac_memory_multi.c +srcs-y += omac_process.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican.c new file mode 100644 index 0000000..25592cc --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican.c @@ -0,0 +1,154 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pelican.c + Pelican MAC, initialize state, by Tom St Denis +*/ + +#ifdef LTC_PELICAN + +#define LTC_AES_TAB_C +#define ENCRYPT_ONLY +#define PELI_TAB +#include "../../ciphers/aes/aes_tab.c" + +/** + Initialize a Pelican state + @param pelmac The Pelican state to initialize + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen) +{ + int err; + + LTC_ARGCHK(pelmac != NULL); + LTC_ARGCHK(key != NULL); + +#ifdef LTC_FAST + if (16 % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + if ((err = aes_setup(key, keylen, 0, &pelmac->K)) != CRYPT_OK) { + return err; + } + + zeromem(pelmac->state, 16); + aes_ecb_encrypt(pelmac->state, pelmac->state, &pelmac->K); + pelmac->buflen = 0; + + return CRYPT_OK; +} + +static void s_four_rounds(pelican_state *pelmac) +{ + ulong32 s0, s1, s2, s3, t0, t1, t2, t3; + int r; + + LOAD32H(s0, pelmac->state ); + LOAD32H(s1, pelmac->state + 4); + LOAD32H(s2, pelmac->state + 8); + LOAD32H(s3, pelmac->state + 12); + for (r = 0; r < 4; r++) { + t0 = + Te0(LTC_BYTE(s0, 3)) ^ + Te1(LTC_BYTE(s1, 2)) ^ + Te2(LTC_BYTE(s2, 1)) ^ + Te3(LTC_BYTE(s3, 0)); + t1 = + Te0(LTC_BYTE(s1, 3)) ^ + Te1(LTC_BYTE(s2, 2)) ^ + Te2(LTC_BYTE(s3, 1)) ^ + Te3(LTC_BYTE(s0, 0)); + t2 = + Te0(LTC_BYTE(s2, 3)) ^ + Te1(LTC_BYTE(s3, 2)) ^ + Te2(LTC_BYTE(s0, 1)) ^ + Te3(LTC_BYTE(s1, 0)); + t3 = + Te0(LTC_BYTE(s3, 3)) ^ + Te1(LTC_BYTE(s0, 2)) ^ + Te2(LTC_BYTE(s1, 1)) ^ + Te3(LTC_BYTE(s2, 0)); + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + STORE32H(s0, pelmac->state ); + STORE32H(s1, pelmac->state + 4); + STORE32H(s2, pelmac->state + 8); + STORE32H(s3, pelmac->state + 12); +} + +/** + Process a block of text through Pelican + @param pelmac The Pelican MAC state + @param in The input + @param inlen The length input (octets) + @return CRYPT_OK on success + */ +int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen) +{ + + LTC_ARGCHK(pelmac != NULL); + LTC_ARGCHK(in != NULL); + + /* check range */ + if (pelmac->buflen < 0 || pelmac->buflen > 15) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (pelmac->buflen == 0) { + while (inlen & ~15) { + int x; + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pelmac->state + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)in + x)); + } + s_four_rounds(pelmac); + in += 16; + inlen -= 16; + } + } +#endif + + while (inlen--) { + pelmac->state[pelmac->buflen++] ^= *in++; + if (pelmac->buflen == 16) { + s_four_rounds(pelmac); + pelmac->buflen = 0; + } + } + return CRYPT_OK; +} + +/** + Terminate Pelican MAC + @param pelmac The Pelican MAC state + @param out [out] The TAG + @return CRYPT_OK on sucess +*/ +int pelican_done(pelican_state *pelmac, unsigned char *out) +{ + LTC_ARGCHK(pelmac != NULL); + LTC_ARGCHK(out != NULL); + + /* check range */ + if (pelmac->buflen < 0 || pelmac->buflen > 16) { + return CRYPT_INVALID_ARG; + } + + if (pelmac->buflen == 16) { + s_four_rounds(pelmac); + pelmac->buflen = 0; + } + pelmac->state[pelmac->buflen++] ^= 0x80; + aes_ecb_encrypt(pelmac->state, out, &pelmac->K); + aes_done(&pelmac->K); + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_memory.c new file mode 100644 index 0000000..f67eaee --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_memory.c @@ -0,0 +1,47 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pelican_memory.c + Pelican MAC, MAC a block of memory, by Tom St Denis +*/ + +#ifdef LTC_PELICAN + +/** + Pelican block of memory + @param key The key for the MAC + @param keylen The length of the key (octets) + @param in The input to MAC + @param inlen The length of the input (octets) + @param out [out] The output TAG + @return CRYPT_OK on success +*/ +int pelican_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out) +{ + pelican_state *pel; + int err; + + pel = XMALLOC(sizeof(*pel)); + if (pel == NULL) { + return CRYPT_MEM; + } + + if ((err = pelican_init(pel, key, keylen)) != CRYPT_OK) { + XFREE(pel); + return err; + } + if ((err = pelican_process(pel, in ,inlen)) != CRYPT_OK) { + XFREE(pel); + return err; + } + err = pelican_done(pel, out); + XFREE(pel); + return err; +} + + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_test.c new file mode 100644 index 0000000..2ec696a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pelican/pelican_test.c @@ -0,0 +1,103 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pelican_test.c + Pelican MAC, test, by Tom St Denis +*/ + +#ifdef LTC_PELICAN + +int pelican_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char K[32], MSG[64], T[16]; + int keylen, ptlen; + } tests[] = { +/* K=16, M=0 */ +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0 }, + { 0xeb, 0x58, 0x37, 0x15, 0xf8, 0x34, 0xde, 0xe5, + 0xa4, 0xd1, 0x6e, 0xe4, 0xb9, 0xd7, 0x76, 0x0e, }, + 16, 0 +}, + +/* K=16, M=3 */ +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x00, 0x01, 0x02 }, + { 0x1c, 0x97, 0x40, 0x60, 0x6c, 0x58, 0x17, 0x2d, + 0x03, 0x94, 0x19, 0x70, 0x81, 0xc4, 0x38, 0x54, }, + 16, 3 +}, + +/* K=16, M=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 }, + { 0x03, 0xcc, 0x46, 0xb8, 0xac, 0xa7, 0x9c, 0x36, + 0x1e, 0x8c, 0x6e, 0xa6, 0x7b, 0x89, 0x32, 0x49, }, + 16, 16 +}, + +/* K=16, M=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 }, + { 0x89, 0xcc, 0x36, 0x58, 0x1b, 0xdd, 0x4d, 0xb5, + 0x78, 0xbb, 0xac, 0xf0, 0xff, 0x8b, 0x08, 0x15, }, + 16, 32 +}, + +/* K=16, M=35 */ +{ + { 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, 0x23 }, + { 0x4a, 0x7d, 0x45, 0x4d, 0xcd, 0xb5, 0xda, 0x8d, + 0x48, 0x78, 0x16, 0x48, 0x5d, 0x45, 0x95, 0x99, }, + 16, 35 +}, +}; + int x, err; + unsigned char out[16]; + pelican_state pel; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = pelican_init(&pel, tests[x].K, tests[x].keylen)) != CRYPT_OK) { + return err; + } + if ((err = pelican_process(&pel, tests[x].MSG, tests[x].ptlen)) != CRYPT_OK) { + return err; + } + if ((err = pelican_done(&pel, out)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(out, 16, tests[x].T, 16, "PELICAN", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c new file mode 100644 index 0000000..bdccc4e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_done.c + PMAC implementation, terminate a session, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen) +{ + int err, x; + + LTC_ARGCHK(pmac != NULL); + LTC_ARGCHK(out != 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; + } + + + /* handle padding. If multiple xor in L/x */ + + if (pmac->buflen == pmac->block_len) { + /* xor Lr against the checksum */ + for (x = 0; x < pmac->block_len; x++) { + pmac->checksum[x] ^= pmac->block[x] ^ pmac->Lr[x]; + } + } else { + /* otherwise xor message bytes then the 0x80 byte */ + for (x = 0; x < pmac->buflen; x++) { + pmac->checksum[x] ^= pmac->block[x]; + } + pmac->checksum[x] ^= 0x80; + } + + /* encrypt it */ + if ((err = cipher_descriptor[pmac->cipher_idx]->ecb_encrypt(pmac->checksum, pmac->checksum, &pmac->key)) != CRYPT_OK) { + return err; + } + cipher_descriptor[pmac->cipher_idx]->done(&pmac->key); + + /* store it */ + for (x = 0; x < pmac->block_len && x < (int)*outlen; x++) { + out[x] = pmac->checksum[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(pmac, sizeof(*pmac)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c new file mode 100644 index 0000000..fca9b00 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c @@ -0,0 +1,88 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + size_t x; + int err; + pmac_state pmac; + FILE *in; + unsigned char *buf; + + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(filename, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = pmac_process(&pmac, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = pmac_done(&pmac, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&pmac, sizeof(pmac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c new file mode 100644 index 0000000..fd91292 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c @@ -0,0 +1,138 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (poly >= (int)(sizeof(polys)/sizeof(polys[0]))) { + return CRYPT_INVALID_ARG; + } + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c new file mode 100644 index 0000000..4671547 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c new file mode 100644 index 0000000..94d450c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c @@ -0,0 +1,77 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c new file mode 100644 index 0000000..ed71f33 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c new file mode 100644 index 0000000..c277afa --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c @@ -0,0 +1,88 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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_PTR_CAST(&Z[y])) = *(LTC_FAST_TYPE_PTR_CAST(&in[y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&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_PTR_CAST(&pmac->checksum[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c new file mode 100644 index 0000000..ad97fa8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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_PTR_CAST((unsigned char *)pmac->Li + x)) ^= + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Ls[y] + x)); + } +#else + for (x = 0; x < pmac->block_len; x++) { + pmac->Li[x] ^= pmac->Ls[y][x]; + } +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c new file mode 100644 index 0000000..3ccf06e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c @@ -0,0 +1,144 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "PMAC", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* PMAC_MODE */ + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305.c new file mode 100644 index 0000000..32cdb55 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305.c @@ -0,0 +1,258 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_POLY1305 + +/* internal only */ +static void s_poly1305_block(poly1305_state *st, const unsigned char *in, unsigned long inlen) +{ + const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */ + ulong32 r0,r1,r2,r3,r4; + ulong32 s1,s2,s3,s4; + ulong32 h0,h1,h2,h3,h4; + ulong32 tmp; + ulong64 d0,d1,d2,d3,d4; + ulong32 c; + + r0 = st->r[0]; + r1 = st->r[1]; + r2 = st->r[2]; + r3 = st->r[3]; + r4 = st->r[4]; + + s1 = r1 * 5; + s2 = r2 * 5; + s3 = r3 * 5; + s4 = r4 * 5; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + h3 = st->h[3]; + h4 = st->h[4]; + + while (inlen >= 16) { + /* h += in[i] */ + LOAD32L(tmp, in+ 0); h0 += (tmp ) & 0x3ffffff; + LOAD32L(tmp, in+ 3); h1 += (tmp >> 2) & 0x3ffffff; + LOAD32L(tmp, in+ 6); h2 += (tmp >> 4) & 0x3ffffff; + LOAD32L(tmp, in+ 9); h3 += (tmp >> 6) & 0x3ffffff; + LOAD32L(tmp, in+12); h4 += (tmp >> 8) | hibit; + + /* h *= r */ + d0 = ((ulong64)h0 * r0) + ((ulong64)h1 * s4) + ((ulong64)h2 * s3) + ((ulong64)h3 * s2) + ((ulong64)h4 * s1); + d1 = ((ulong64)h0 * r1) + ((ulong64)h1 * r0) + ((ulong64)h2 * s4) + ((ulong64)h3 * s3) + ((ulong64)h4 * s2); + d2 = ((ulong64)h0 * r2) + ((ulong64)h1 * r1) + ((ulong64)h2 * r0) + ((ulong64)h3 * s4) + ((ulong64)h4 * s3); + d3 = ((ulong64)h0 * r3) + ((ulong64)h1 * r2) + ((ulong64)h2 * r1) + ((ulong64)h3 * r0) + ((ulong64)h4 * s4); + d4 = ((ulong64)h0 * r4) + ((ulong64)h1 * r3) + ((ulong64)h2 * r2) + ((ulong64)h3 * r1) + ((ulong64)h4 * r0); + + /* (partial) h %= p */ + c = (ulong32)(d0 >> 26); h0 = (ulong32)d0 & 0x3ffffff; + d1 += c; c = (ulong32)(d1 >> 26); h1 = (ulong32)d1 & 0x3ffffff; + d2 += c; c = (ulong32)(d2 >> 26); h2 = (ulong32)d2 & 0x3ffffff; + d3 += c; c = (ulong32)(d3 >> 26); h3 = (ulong32)d3 & 0x3ffffff; + d4 += c; c = (ulong32)(d4 >> 26); h4 = (ulong32)d4 & 0x3ffffff; + h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; + h1 += c; + + in += 16; + inlen -= 16; + } + + st->h[0] = h0; + st->h[1] = h1; + st->h[2] = h2; + st->h[3] = h3; + st->h[4] = h4; +} + +/** + Initialize an POLY1305 context. + @param st The POLY1305 state + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen == 32); + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + LOAD32L(st->r[0], key + 0); st->r[0] = (st->r[0] ) & 0x3ffffff; + LOAD32L(st->r[1], key + 3); st->r[1] = (st->r[1] >> 2) & 0x3ffff03; + LOAD32L(st->r[2], key + 6); st->r[2] = (st->r[2] >> 4) & 0x3ffc0ff; + LOAD32L(st->r[3], key + 9); st->r[3] = (st->r[3] >> 6) & 0x3f03fff; + LOAD32L(st->r[4], key + 12); st->r[4] = (st->r[4] >> 8) & 0x00fffff; + + /* h = 0 */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + st->h[3] = 0; + st->h[4] = 0; + + /* save pad for later */ + LOAD32L(st->pad[0], key + 16); + LOAD32L(st->pad[1], key + 20); + LOAD32L(st->pad[2], key + 24); + LOAD32L(st->pad[3], key + 28); + + st->leftover = 0; + st->final = 0; + return CRYPT_OK; +} + +/** + Process data through POLY1305 + @param st The POLY1305 state + @param in The data to send through HMAC + @param inlen The length of the data to HMAC (octets) + @return CRYPT_OK if successful +*/ +int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen) +{ + unsigned long i; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + + /* handle leftover */ + if (st->leftover) { + unsigned long want = (16 - st->leftover); + if (want > inlen) want = inlen; + for (i = 0; i < want; i++) st->buffer[st->leftover + i] = in[i]; + inlen -= want; + in += want; + st->leftover += want; + if (st->leftover < 16) return CRYPT_OK; + s_poly1305_block(st, st->buffer, 16); + st->leftover = 0; + } + + /* process full blocks */ + if (inlen >= 16) { + unsigned long want = (inlen & ~(16 - 1)); + s_poly1305_block(st, in, want); + in += want; + inlen -= want; + } + + /* store leftover */ + if (inlen) { + for (i = 0; i < inlen; i++) st->buffer[st->leftover + i] = in[i]; + st->leftover += inlen; + } + return CRYPT_OK; +} + +/** + Terminate a POLY1305 session + @param st The POLY1305 state + @param mac [out] The destination of the POLY1305 authentication tag + @param maclen [in/out] The max size and resulting size of the POLY1305 authentication tag + @return CRYPT_OK if successful +*/ +int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen) +{ + ulong32 h0,h1,h2,h3,h4,c; + ulong32 g0,g1,g2,g3,g4; + ulong64 f; + ulong32 mask; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + LTC_ARGCHK(*maclen >= 16); + + /* process the remaining block */ + if (st->leftover) { + unsigned long i = st->leftover; + st->buffer[i++] = 1; + for (; i < 16; i++) st->buffer[i] = 0; + st->final = 1; + s_poly1305_block(st, st->buffer, 16); + } + + /* fully carry h */ + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + h3 = st->h[3]; + h4 = st->h[4]; + + c = h1 >> 26; h1 = h1 & 0x3ffffff; + h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; + h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; + h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; + h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; + h1 += c; + + /* compute h + -p */ + g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; + g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; + g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; + g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; + g4 = h4 + c - (1UL << 26); + + /* select h if h < p, or h + -p if h >= p */ + mask = (g4 >> 31) - 1; + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + g4 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; + h3 = (h3 & mask) | g3; + h4 = (h4 & mask) | g4; + + /* h = h % (2^128) */ + h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; + h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; + h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; + h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; + + /* mac = (h + pad) % (2^128) */ + f = (ulong64)h0 + st->pad[0] ; h0 = (ulong32)f; + f = (ulong64)h1 + st->pad[1] + (f >> 32); h1 = (ulong32)f; + f = (ulong64)h2 + st->pad[2] + (f >> 32); h2 = (ulong32)f; + f = (ulong64)h3 + st->pad[3] + (f >> 32); h3 = (ulong32)f; + + STORE32L(h0, mac + 0); + STORE32L(h1, mac + 4); + STORE32L(h2, mac + 8); + STORE32L(h3, mac + 12); + + /* zero out the state */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + st->h[3] = 0; + st->h[4] = 0; + st->r[0] = 0; + st->r[1] = 0; + st->r[2] = 0; + st->r[3] = 0; + st->r[4] = 0; + st->pad[0] = 0; + st->pad[1] = 0; + st->pad[2] = 0; + st->pad[3] = 0; + + *maclen = 16; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_file.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_file.c new file mode 100644 index 0000000..e09c994 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_file.c @@ -0,0 +1,83 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_POLY1305 + +/** + POLY1305 a file + @param fname The name of the file you wish to POLY1305 + @param key The secret key + @param keylen The length of the secret key + @param mac [out] The POLY1305 authentication tag + @param maclen [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 poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); + return CRYPT_NOP; +#else + poly1305_state st; + FILE *in; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = poly1305_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = poly1305_done(&st, mac, maclen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(poly1305_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory.c new file mode 100644 index 0000000..8a9fea6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_POLY1305 + +/** + POLY1305 a block of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to POLY1305 + @param inlen The length of the data to POLY1305 (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) +{ + poly1305_state st; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = poly1305_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + err = poly1305_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(poly1305_state)); +#endif + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c new file mode 100644 index 0000000..6bd61df --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c @@ -0,0 +1,57 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" +#include + +#ifdef LTC_POLY1305 + +/** + POLY1305 multiple blocks of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @param in The data to POLY1305 + @param inlen The length of the data to POLY1305 (octets) + @param ... tuples of (data,len) pairs to POLY1305, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) +{ + poly1305_state st; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + va_start(args, inlen); + curptr = in; + curlen = inlen; + if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + for (;;) { + if ((err = poly1305_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) break; + curlen = va_arg(args, unsigned long); + } + err = poly1305_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(poly1305_state)); +#endif + va_end(args); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.c new file mode 100644 index 0000000..f9b3f75 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.c @@ -0,0 +1,46 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_POLY1305 + +int poly1305_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + /* https://tools.ietf.org/html/rfc7539#section-2.5.2 */ + unsigned char k[] = { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b }; + unsigned char tag[] = { 0xA8, 0x06, 0x1D, 0xC1, 0x30, 0x51, 0x36, 0xC6, 0xC2, 0x2B, 0x8B, 0xAF, 0x0C, 0x01, 0x27, 0xA9 }; + char m[] = "Cryptographic Forum Research Group"; + unsigned long len = 16, mlen = XSTRLEN(m); + unsigned char out[1000]; + poly1305_state st; + int err; + + /* process piece by piece */ + if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m, 5)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 5, 4)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 9, 3)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 12, 2)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 14, 1)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 15, mlen - 15)) != CRYPT_OK) return err; + if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err; + if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV1", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + /* process in one go */ + if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m, mlen)) != CRYPT_OK) return err; + if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err; + if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV2", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/mac/sub.mk new file mode 100644 index 0000000..e8690ab --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/sub.mk @@ -0,0 +1,2 @@ +subdirs-$(_CFG_CORE_LTC_HMAC) += hmac +subdirs-$(_CFG_CORE_LTC_CMAC) += omac diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c new file mode 100644 index 0000000..8f60bba --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c new file mode 100644 index 0000000..d8612df --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + size_t x; + int err; + xcbc_state xcbc; + FILE *in; + unsigned char *buf; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = xcbc_init(&xcbc, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(filename, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = xcbc_process(&xcbc, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = xcbc_done(&xcbc, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&xcbc, sizeof(xcbc_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c new file mode 100644 index 0000000..6eca4a4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c new file mode 100644 index 0000000..73f78d2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c new file mode 100644 index 0000000..d9e48d9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c new file mode 100644 index 0000000..be7c617 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c @@ -0,0 +1,63 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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_PTR_CAST(&(xcbc->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c new file mode 100644 index 0000000..23555de --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c @@ -0,0 +1,116 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file xcbc_test.c + XCBC Support, Test XCBC-MAC mode +*/ + +#ifdef LTC_XCBC + +/** Test XCBC-MAC mode + Return CRYPT_OK on success +*/ +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 (compare_testvector(T, taglen, tests[x].T, 16, "XCBC", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c b/optee/optee_os/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c new file mode 100644 index 0000000..37cee9f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c @@ -0,0 +1,1580 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_fp_mulmod.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && defined(LTC_MECC_FP) +#include + +/* number of entries in the cache */ +#ifndef FP_ENTRIES +#define FP_ENTRIES 16 +#endif + +/* number of bits in LUT */ +#ifndef FP_LUT +#define FP_LUT 8U +#endif + +#if (FP_LUT > 12) || (FP_LUT < 2) + #error FP_LUT must be between 2 and 12 inclusively +#endif + +/** Our FP cache */ +static struct { + ecc_point *g, /* cached COPY of base point */ + *LUT[1U< 6 + { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 }, + { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 }, + { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 }, + { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 }, + { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 }, + { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 }, + { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 }, + { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 }, +#if FP_LUT > 7 + { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 }, + { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 }, + { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 }, + { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 }, + { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 }, + { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 }, + { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 }, + { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 }, + { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 }, + { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 }, + { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 }, + { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 }, + { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 }, + { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 }, + { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 }, + { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 }, +#if FP_LUT > 8 + { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 }, + { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 }, + { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 }, + { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 }, + { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 }, + { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 }, + { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 }, + { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 }, + { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 }, + { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 }, + { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 }, + { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 }, + { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 }, + { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 }, + { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 }, + { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 }, + { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 }, + { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 }, + { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 }, + { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 }, + { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 }, + { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 }, + { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 }, + { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 }, + { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 }, + { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 }, + { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 }, + { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 }, + { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 }, + { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 }, + { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 }, + { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 }, +#if FP_LUT > 9 + { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 }, + { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 }, + { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 }, + { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 }, + { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 }, + { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 }, + { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 }, + { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 }, + { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 }, + { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 }, + { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 }, + { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 }, + { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 }, + { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 }, + { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 }, + { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 }, + { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 }, + { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 }, + { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 }, + { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 }, + { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 }, + { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 }, + { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 }, + { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 }, + { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 }, + { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 }, + { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 }, + { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 }, + { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 }, + { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 }, + { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 }, + { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 }, + { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 }, + { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 }, + { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 }, + { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 }, + { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 }, + { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 }, + { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 }, + { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 }, + { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 }, + { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 }, + { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 }, + { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 }, + { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 }, + { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 }, + { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 }, + { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 }, + { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 }, + { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 }, + { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 }, + { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 }, + { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 }, + { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 }, + { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 }, + { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 }, + { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 }, + { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 }, + { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 }, + { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 }, + { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 }, + { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 }, + { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 }, + { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 }, +#if FP_LUT > 10 + { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 }, + { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 }, + { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 }, + { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 }, + { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 }, + { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 }, + { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 }, + { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 }, + { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 }, + { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 }, + { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 }, + { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 }, + { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 }, + { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 }, + { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 }, + { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 }, + { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 }, + { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 }, + { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 }, + { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 }, + { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 }, + { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 }, + { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 }, + { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 }, + { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 }, + { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 }, + { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 }, + { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 }, + { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 }, + { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 }, + { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 }, + { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 }, + { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 }, + { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 }, + { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 }, + { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 }, + { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 }, + { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 }, + { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 }, + { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 }, + { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 }, + { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 }, + { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 }, + { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 }, + { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 }, + { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 }, + { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 }, + { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 }, + { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 }, + { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 }, + { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 }, + { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 }, + { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 }, + { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 }, + { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 }, + { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 }, + { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 }, + { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 }, + { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 }, + { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 }, + { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 }, + { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 }, + { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 }, + { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 }, + { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 }, + { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 }, + { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 }, + { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 }, + { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 }, + { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 }, + { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 }, + { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 }, + { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 }, + { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 }, + { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 }, + { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 }, + { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 }, + { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 }, + { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 }, + { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 }, + { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 }, + { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 }, + { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 }, + { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 }, + { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 }, + { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 }, + { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 }, + { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 }, + { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 }, + { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 }, + { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 }, + { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 }, + { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 }, + { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 }, + { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 }, + { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 }, + { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 }, + { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 }, + { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 }, + { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 }, + { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 }, + { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 }, + { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 }, + { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 }, + { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 }, + { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 }, + { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 }, + { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 }, + { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 }, + { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 }, + { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 }, + { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 }, + { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 }, + { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 }, + { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 }, + { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 }, + { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 }, + { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 }, + { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 }, + { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 }, + { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 }, + { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 }, + { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 }, + { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 }, + { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 }, + { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 }, + { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 }, + { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 }, +#if FP_LUT > 11 + { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 }, + { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 }, + { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 }, + { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 }, + { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 }, + { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 }, + { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 }, + { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 }, + { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 }, + { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 }, + { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 }, + { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 }, + { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 }, + { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 }, + { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 }, + { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 }, + { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 }, + { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 }, + { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 }, + { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 }, + { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 }, + { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 }, + { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 }, + { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 }, + { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 }, + { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 }, + { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 }, + { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 }, + { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 }, + { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 }, + { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 }, + { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 }, + { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 }, + { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 }, + { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 }, + { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 }, + { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 }, + { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 }, + { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 }, + { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 }, + { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 }, + { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 }, + { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 }, + { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 }, + { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 }, + { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 }, + { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 }, + { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 }, + { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 }, + { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 }, + { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 }, + { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 }, + { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 }, + { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 }, + { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 }, + { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 }, + { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 }, + { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 }, + { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 }, + { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 }, + { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 }, + { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 }, + { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 }, + { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 }, + { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 }, + { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 }, + { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 }, + { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 }, + { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 }, + { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 }, + { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 }, + { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 }, + { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 }, + { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 }, + { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 }, + { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 }, + { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 }, + { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 }, + { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 }, + { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 }, + { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 }, + { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 }, + { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 }, + { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 }, + { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 }, + { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 }, + { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 }, + { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 }, + { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 }, + { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 }, + { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 }, + { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 }, + { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 }, + { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 }, + { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 }, + { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 }, + { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 }, + { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 }, + { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 }, + { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 }, + { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 }, + { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 }, + { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 }, + { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 }, + { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 }, + { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 }, + { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 }, + { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 }, + { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 }, + { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 }, + { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 }, + { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 }, + { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 }, + { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 }, + { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 }, + { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 }, + { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 }, + { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 }, + { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 }, + { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 }, + { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 }, + { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 }, + { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 }, + { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 }, + { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 }, + { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 }, + { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 }, + { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 }, + { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 }, + { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 }, + { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 }, + { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 }, + { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 }, + { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 }, + { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 }, + { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 }, + { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 }, + { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 }, + { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 }, + { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 }, + { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 }, + { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 }, + { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 }, + { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 }, + { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 }, + { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 }, + { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 }, + { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 }, + { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 }, + { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 }, + { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 }, + { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 }, + { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 }, + { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 }, + { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 }, + { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 }, + { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 }, + { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 }, + { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 }, + { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 }, + { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 }, + { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 }, + { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 }, + { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 }, + { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 }, + { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 }, + { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 }, + { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 }, + { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 }, + { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 }, + { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 }, + { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 }, + { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 }, + { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 }, + { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 }, + { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 }, + { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 }, + { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 }, + { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 }, + { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 }, + { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 }, + { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 }, + { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 }, + { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 }, + { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 }, + { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 }, + { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 }, + { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 }, + { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 }, + { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 }, + { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 }, + { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 }, + { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 }, + { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 }, + { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 }, + { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 }, + { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 }, + { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 }, + { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 }, + { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 }, + { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 }, + { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 }, + { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 }, + { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 }, + { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 }, + { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 }, + { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 }, + { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 }, + { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 }, + { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 }, + { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 }, + { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 }, + { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 }, + { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 }, + { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 }, + { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 }, + { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 }, + { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 }, + { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 }, + { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 }, + { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 }, + { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 }, + { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 }, + { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 }, + { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 }, + { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 }, + { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 }, + { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 }, + { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 }, + { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 }, + { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 }, + { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 }, + { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 }, + { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 }, + { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 }, + { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 }, + { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 }, + { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 }, + { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 }, + { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 }, + { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 }, + { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 }, + { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 }, + { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 }, + { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 }, + { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 }, + { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 }, + { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 }, + { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 }, + { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 }, + { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 }, + { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 }, + { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 }, + { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 }, + { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 }, + { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 }, +#endif +#endif +#endif +#endif +#endif +#endif +}; + +/* find a hole and free as required, return -1 if no hole found */ +static int s_find_hole(void) +{ + unsigned x; + int y, z; + for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) { + z = x; + y = fp_cache[x].lru_count; + } + } + + /* decrease all */ + for (x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].lru_count > 3) { + --(fp_cache[x].lru_count); + } + } + + /* free entry z */ + if (z >= 0 && fp_cache[z].g) { + if (fp_cache[z].mu != NULL) { + mp_clear(fp_cache[z].mu); + fp_cache[z].mu = NULL; + } + ltc_ecc_del_point(fp_cache[z].g); + fp_cache[z].g = NULL; + for (x = 0; x < (1U<x, g->x) == LTC_MP_EQ && + mp_cmp(fp_cache[x].g->y, g->y) == LTC_MP_EQ && + mp_cmp(fp_cache[x].g->z, g->z) == LTC_MP_EQ) { + break; + } + } + if (x == FP_ENTRIES) { + x = -1; + } + return x; +} + +/* add a new base to the cache */ +static int s_add_entry(int idx, ecc_point *g) +{ + unsigned x, y; + + /* allocate base and LUT */ + fp_cache[idx].g = ltc_ecc_new_point(); + if (fp_cache[idx].g == NULL) { + return CRYPT_MEM; + } + + /* copy x and y */ + if ((mp_copy(g->x, fp_cache[idx].g->x) != CRYPT_OK) || + (mp_copy(g->y, fp_cache[idx].g->y) != CRYPT_OK) || + (mp_copy(g->z, fp_cache[idx].g->z) != CRYPT_OK)) { + ltc_ecc_del_point(fp_cache[idx].g); + fp_cache[idx].g = NULL; + return CRYPT_MEM; + } + + for (x = 0; x < (1U<x, mu, modulus, fp_cache[idx].LUT[1]->x) != CRYPT_OK) || + (mp_mulmod(fp_cache[idx].g->y, mu, modulus, fp_cache[idx].LUT[1]->y) != CRYPT_OK) || + (mp_mulmod(fp_cache[idx].g->z, mu, modulus, fp_cache[idx].LUT[1]->z) != CRYPT_OK)) { goto ERR; } + + /* make all single bit entries */ + for (x = 1; x < FP_LUT; x++) { + if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x, fp_cache[idx].LUT[1<x) != CRYPT_OK) || + (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y, fp_cache[idx].LUT[1<y) != CRYPT_OK) || + (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, fp_cache[idx].LUT[1<z) != CRYPT_OK)) { goto ERR; } + + /* now double it bitlen/FP_LUT times */ + for (y = 0; y < lut_gap; y++) { + if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<z, modulus, mp)) != CRYPT_OK) { goto ERR; } + + /* invert it */ + if ((err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus, fp_cache[idx].LUT[x]->z)) != CRYPT_OK) { goto ERR; } + + /* now square it */ + if ((err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } + + /* fix x */ + if ((err = mp_mulmod(fp_cache[idx].LUT[x]->x, tmp, modulus, fp_cache[idx].LUT[x]->x)) != CRYPT_OK) { goto ERR; } + + /* get 1/z^3 */ + if ((err = mp_mulmod(tmp, fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } + + /* fix y */ + if ((err = mp_mulmod(fp_cache[idx].LUT[x]->y, tmp, modulus, fp_cache[idx].LUT[x]->y)) != CRYPT_OK) { goto ERR; } + + /* free z */ + mp_clear(fp_cache[idx].LUT[x]->z); + fp_cache[idx].LUT[x]->z = NULL; + } + mp_clear(tmp); + + return CRYPT_OK; +ERR: + err = CRYPT_MEM; +DONE: + for (y = 0; y < (1U< mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ltc_ecc_sets[x].size; x++) { + if (y <= (unsigned)ltc_ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_init(&order)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { + mp_clear(&order); + return err; + } + + /* k must be less than modulus */ + if (mp_cmp(k, order) != LTC_MP_LT) { + if ((err = mp_init(&tk)) != CRYPT_OK) { + mp_clear(order); + return err; + } + if ((err = mp_mod(k, order, tk)) != CRYPT_OK) { + mp_clear(tk); + mp_clear(order); + return err; + } + } else { + tk = k; + } + mp_clear(order); + } else { + tk = k; + } + + /* get bitlen and round up to next multiple of FP_LUT */ + bitlen = mp_unsigned_bin_size(modulus) << 3; + x = bitlen % FP_LUT; + if (x) { + bitlen += FP_LUT - x; + } + lut_gap = bitlen / FP_LUT; + + /* get the k value */ + if (mp_unsigned_bin_size(tk) > (sizeof(kb) - 2)) { + if (tk != k) { + mp_clear(tk); + } + return CRYPT_BUFFER_OVERFLOW; + } + + /* store k */ + zeromem(kb, sizeof(kb)); + if ((err = mp_to_unsigned_bin(tk, kb)) != CRYPT_OK) { + if (tk != k) { + mp_clear(tk); + } + return err; + } + + /* let's reverse kb so it's little endian */ + x = 0; + y = mp_unsigned_bin_size(tk) - 1; + if (tk != k) { + mp_clear(tk); + } + while ((unsigned)x < y) { + z = kb[x]; kb[x] = kb[y]; kb[y] = z; + ++x; --y; + } + + /* at this point we can start, yipee */ + first = 1; + for (x = lut_gap-1; x >= 0; x--) { + /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */ + bitpos = x; + for (y = z = 0; y < FP_LUT; y++) { + z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y; + bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */ + } + + /* double if not first */ + if (!first) { + if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + + /* add if not first, otherwise copy */ + if (!first && z) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } else if (z) { + if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != CRYPT_OK) || + (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != CRYPT_OK) || + (mp_copy(fp_cache[idx].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } + first = 0; + } + } + z = 0; + zeromem(kb, sizeof(kb)); + /* map R back from projective space */ + if (map) { + err = ltc_ecc_map(R, modulus, mp); + } else { + err = CRYPT_OK; + } + return err; +} + +#ifdef LTC_ECC_SHAMIR +/* perform a fixed point ECC mulmod */ +static int ss_accel_fp_mul2add(int idx1, int idx2, + void *kA, void *kB, + ecc_point *R, void *a, void *modulus, void *mp) +{ + unsigned char kb[2][128]; + int x; + unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB; + void *tka, *tkb, *order; + + /* if it's smaller than modulus we fine */ + if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ltc_ecc_sets[x].size; x++) { + if (y <= (unsigned)ltc_ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_init(&order)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { + mp_clear(&order); + return err; + } + + /* kA must be less than modulus */ + if (mp_cmp(kA, order) != LTC_MP_LT) { + if ((err = mp_init(&tka)) != CRYPT_OK) { + mp_clear(order); + return err; + } + if ((err = mp_mod(kA, order, tka)) != CRYPT_OK) { + mp_clear(tka); + mp_clear(order); + return err; + } + } else { + tka = kA; + } + mp_clear(order); + } else { + tka = kA; + } + + /* if it's smaller than modulus we fine */ + if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ltc_ecc_sets[x].size; x++) { + if (y <= (unsigned)ltc_ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_init(&order)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { + mp_clear(&order); + return err; + } + + /* kB must be less than modulus */ + if (mp_cmp(kB, order) != LTC_MP_LT) { + if ((err = mp_init(&tkb)) != CRYPT_OK) { + mp_clear(order); + return err; + } + if ((err = mp_mod(kB, order, tkb)) != CRYPT_OK) { + mp_clear(tkb); + mp_clear(order); + return err; + } + } else { + tkb = kB; + } + mp_clear(order); + } else { + tkb = kB; + } + + /* get bitlen and round up to next multiple of FP_LUT */ + bitlen = mp_unsigned_bin_size(modulus) << 3; + x = bitlen % FP_LUT; + if (x) { + bitlen += FP_LUT - x; + } + lut_gap = bitlen / FP_LUT; + + /* get the k value */ + if ((mp_unsigned_bin_size(tka) > (sizeof(kb[0]) - 2)) || (mp_unsigned_bin_size(tkb) > (sizeof(kb[0]) - 2)) ) { + if (tka != kA) { + mp_clear(tka); + } + if (tkb != kB) { + mp_clear(tkb); + } + return CRYPT_BUFFER_OVERFLOW; + } + + /* store k */ + zeromem(kb, sizeof(kb)); + if ((err = mp_to_unsigned_bin(tka, kb[0])) != CRYPT_OK) { + if (tka != kA) { + mp_clear(tka); + } + if (tkb != kB) { + mp_clear(tkb); + } + return err; + } + + /* let's reverse kb so it's little endian */ + x = 0; + y = mp_unsigned_bin_size(tka) - 1; + if (tka != kA) { + mp_clear(tka); + } + while ((unsigned)x < y) { + z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z; + ++x; --y; + } + + /* store b */ + if ((err = mp_to_unsigned_bin(tkb, kb[1])) != CRYPT_OK) { + if (tkb != kB) { + mp_clear(tkb); + } + return err; + } + + x = 0; + y = mp_unsigned_bin_size(tkb) - 1; + if (tkb != kB) { + mp_clear(tkb); + } + while ((unsigned)x < y) { + z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z; + ++x; --y; + } + + /* at this point we can start, yipee */ + first = 1; + for (x = lut_gap-1; x >= 0; x--) { + /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */ + bitpos = x; + for (y = zA = zB = 0; y < FP_LUT; y++) { + zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y; + zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y; + bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */ + } + + /* double if not first */ + if (!first) { + if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + + /* add if not first, otherwise copy */ + if (!first) { + if (zA) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + if (zB) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + } else { + if (zA) { + if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != CRYPT_OK) || + (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != CRYPT_OK) || + (mp_copy(fp_cache[idx1].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } + first = 0; + } + if (zB && first == 0) { + if (zB) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + } else if (zB && first == 1) { + if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != CRYPT_OK) || + (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != CRYPT_OK) || + (mp_copy(fp_cache[idx2].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } + first = 0; + } + } + } + zeromem(kb, sizeof(kb)); + return ltc_ecc_map(R, modulus, mp); +} + +/** ECC Fixed Point mulmod global + 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_fp_mul2add(ecc_point *A, void *kA, + ecc_point *B, void *kB, + ecc_point *C, + void *a, + void *modulus) +{ + int idx1, idx2, err; + void *mp, *mu; + + mp = NULL; + mu = NULL; + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + /* find point */ + idx1 = s_find_base(A); + + /* no entry? */ + if (idx1 == -1) { + /* find hole and add it */ + if ((idx1 = s_find_hole()) >= 0) { + if ((err = s_add_entry(idx1, A)) != CRYPT_OK) { + goto LBL_ERR; + } + } + } + if (idx1 != -1) { + /* increment LRU */ + ++(fp_cache[idx1].lru_count); + } + + /* find point */ + idx2 = s_find_base(B); + + /* no entry? */ + if (idx2 == -1) { + /* find hole and add it */ + if ((idx2 = s_find_hole()) >= 0) { + if ((err = s_add_entry(idx2, B)) != CRYPT_OK) { + goto LBL_ERR; + } + } + } + if (idx2 != -1) { + /* increment LRU */ + ++(fp_cache[idx2].lru_count); + } + + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + + /* compute mu */ + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* build the LUT */ + if ((err = s_build_lut(idx1, a, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR;; + } + } + + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) { + if (mp == NULL) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + + /* compute mu */ + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* build the LUT */ + if ((err = s_build_lut(idx2, a, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR;; + } + } + + + if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 && fp_cache[idx2].lru_count >= 2) { + if (mp == NULL) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + } + err = ss_accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); + } else { + err = ltc_ecc_mul2add(A, kA, B, kB, C, a, modulus); + } +LBL_ERR: + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + if (mp != NULL) { + mp_montgomery_free(mp); + } + if (mu != NULL) { + mp_clear(mu); + } + return err; +} +#endif + +/** ECC Fixed Point mulmod global + @param k The multiplicand + @param G Base point to multiply + @param R [out] Destination of product + @param a ECC curve parameter a + @param modulus The modulus for the curve + @param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form + @return CRYPT_OK if successful +*/ +int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map) +{ + int idx, err; + void *mp, *mu; + + mp = NULL; + mu = NULL; + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + /* find point */ + idx = s_find_base(G); + + /* no entry? */ + if (idx == -1) { + /* find hole and add it */ + idx = s_find_hole(); + + if (idx >= 0) { + if ((err = s_add_entry(idx, G)) != CRYPT_OK) { + goto LBL_ERR; + } + } + } + if (idx != -1) { + /* increment LRU */ + ++(fp_cache[idx].lru_count); + } + + + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx >= 0 && fp_cache[idx].lru_count == 2) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + + /* compute mu */ + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* build the LUT */ + if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR;; + } + } + + if (idx >= 0 && fp_cache[idx].lru_count >= 2) { + if (mp == NULL) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + } + err = s_accel_fp_mul(idx, k, R, a, modulus, mp, map); + } else { + err = ltc_ecc_mulmod(k, G, R, a, modulus, map); + } +LBL_ERR: + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + if (mp != NULL) { + mp_montgomery_free(mp); + } + if (mu != NULL) { + mp_clear(mu); + } + return err; +} + +/* helper function for freeing the cache ... must be called with the cache mutex locked */ +static void s_ltc_ecc_fp_free_cache(void) +{ + unsigned x, y; + for (x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].g != NULL) { + for (y = 0; y < (1U<= 0) { + /* it is already in the cache ... just check that the LUT is initialized */ + if(fp_cache[idx].lru_count >= 2) { + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + return CRYPT_OK; + } + } + + if(idx == -1 && (idx = s_find_hole()) == -1) { + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + if ((err = s_add_entry(idx, g)) != CRYPT_OK) { + goto LBL_ERR; + } + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compute mu */ + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* build the LUT */ + if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR; + } + fp_cache[idx].lru_count = 2; + fp_cache[idx].lock = lock; +LBL_ERR: + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + if (mp != NULL) { + mp_montgomery_free(mp); + } + if (mu != NULL) { + mp_clear(mu); + } + return err; +} + +/** Prevent/permit the FP cache from being updated + @param flag If flag is 0, remove cache lock (unlock), otherwise lock it +*/ +void ltc_ecc_fp_tablelock(int lock) +{ + int i; + + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + for (i = 0; i < FP_ENTRIES; i++) { + fp_cache[i].lock = lock; + } + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); +} + +/** Export the current cache as a binary packet + @param out [out] pointer to malloc'ed space containing the packet + @param outlen [out] size of exported packet + @return CRYPT_OK if successful +*/ +int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen) +{ + ltc_asn1_list *cache_entry; + unsigned int i, j, k; + unsigned long fp_entries, fp_lut, num_entries; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + fp_entries = FP_ENTRIES; + fp_lut = FP_LUT; + num_entries = 0; + + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + /* + * build the list; + Cache DEFINITIONS ::= + BEGIN + CacheDump ::= SEQUENCE { + numEntries SHORTINTEGER, + maxEntries SHORTINTEGER, + numLUT SHORTINTEGER, + cache SEQUENCE OF INTEGER + } + END + * + */ + /* + * The cache itself is a point (3 INTEGERS), + * the LUT as pairs of INTEGERS (2 * 1<x, 1); + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); + for (k = 0; k < (1U<x, 1); + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].LUT[k]->y, 1); + } + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); + } + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_EOL, 0, 0); + + LTC_SET_ASN1(cache_entry, 0, LTC_ASN1_SHORT_INTEGER, &num_entries, 1); + + if ((err = der_length_sequence(cache_entry, j, outlen)) != CRYPT_OK) { + goto save_err; + } + if ((*out = XMALLOC(*outlen)) == NULL) { + err = CRYPT_MEM; + goto save_err; + } + err = der_encode_sequence(cache_entry, j, *out, outlen); +save_err: + XFREE(cache_entry); + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + return err; +} + +/** Import a binary packet into the current cache + @param in [in] pointer to packet + @param inlen [in] size of packet (bytes) + @return CRYPT_OK if successful +*/ +int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen) +{ + int err; + ltc_asn1_list *asn1_list; + unsigned long num_entries, fp_entries, fp_lut; + unsigned long i, j; + unsigned int x; + + LTC_ARGCHK(in != NULL); + if (inlen == 0) { + return CRYPT_INVALID_ARG; + } + + /* zero indecies */ + i = 0; + j = 0; + asn1_list = NULL; + + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + /* + * start with an empty cache + */ + s_ltc_ecc_fp_free_cache(); + + /* + * decode the input packet: It consists of a sequence with a few + * integers (including the FP_ENTRIES and FP_LUT sizes), followed by a + * SEQUENCE which is the cache itself. + * + * use standard decoding for the first part, then flexible for the second + */ + if((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1, &num_entries, + LTC_ASN1_SHORT_INTEGER, 1, &fp_entries, + LTC_ASN1_SHORT_INTEGER, 1, &fp_lut, + LTC_ASN1_EOL, 0, 0)) != CRYPT_OK) { + goto ERR_OUT; + } + if (fp_entries != FP_ENTRIES || fp_lut != FP_LUT || num_entries > fp_entries) { + err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + if ((asn1_list = XCALLOC(3+num_entries*(4+2*(1<x, 1); + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); + for (x = 0; x < (1U<x, &p->y, LTC_NULL)) != CRYPT_OK) { + goto ERR_OUT; + } + p->z = NULL; + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->x, 1); + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->y, 1); + } + if((err = mp_init(&fp_cache[i].mu)) != CRYPT_OK) { + goto ERR_OUT; + } + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); + fp_cache[i].lru_count = 3; + fp_cache[i].lock = 1; + } + + if ((err = der_decode_sequence(in, inlen, asn1_list, j)) != CRYPT_OK) { + goto ERR_OUT; + } + XFREE(asn1_list); + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + return CRYPT_OK; +ERR_OUT: + if(asn1_list) + XFREE(asn1_list); + s_ltc_ecc_fp_free_cache(); + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + return err; +} + +#endif + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/fp/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/math/fp/sub.mk new file mode 100644 index 0000000..fe79656 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/fp/sub.mk @@ -0,0 +1 @@ +srcs-$(_CFG_CORE_LTC_ECC) += ltc_ecc_fp_mulmod.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/gmp_desc.c b/optee/optee_os/core/lib/libtomcrypt/src/math/gmp_desc.c new file mode 100644 index 0000000..2db699d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/gmp_desc.c @@ -0,0 +1,658 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define DESC_DEF_ONLY +#include "tomcrypt_private.h" + +#ifdef GMP_DESC + +#include +#include + +static int init(void **a) +{ + LTC_ARGCHK(a != NULL); + + *a = XCALLOC(1, sizeof(__mpz_struct)); + if (*a == NULL) { + return CRYPT_MEM; + } + mpz_init(((__mpz_struct *)*a)); + return CRYPT_OK; +} + +static void deinit(void *a) +{ + LTC_ARGCHKVD(a != NULL); + mpz_clear(a); + XFREE(a); +} + +static int neg(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_neg(b, a); + return CRYPT_OK; +} + +static int copy(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_set(b, 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, ltc_mp_digit b) +{ + LTC_ARGCHK(a != NULL); + mpz_set_ui(((__mpz_struct *)a), b); + return CRYPT_OK; +} + +static unsigned long get_int(void *a) +{ + LTC_ARGCHK(a != NULL); + return mpz_get_ui(a); +} + +static ltc_mp_digit get_digit(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + return mpz_getlimbn(a, n); +} + +static int get_digit_count(void *a) +{ + LTC_ARGCHK(a != NULL); + return mpz_size(a); +} + +static int compare(void *a, void *b) +{ + int ret; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + ret = mpz_cmp(a, 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, ltc_mp_digit b) +{ + int ret; + LTC_ARGCHK(a != NULL); + ret = mpz_cmp_ui(((__mpz_struct *)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); + return mpz_sizeinbase(a, 2); +} + +static int count_lsb_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return mpz_scan1(a, 0); +} + + +static int twoexpt(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + mpz_set_ui(a, 0); + mpz_setbit(a, n); + return CRYPT_OK; +} + +/* ---- conversions ---- */ + +static const char rmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; + +/* read ascii string */ +static int read_radix(void *a, const char *b, int radix) +{ + int ret; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if (radix == 64) { + /* Sadly, GMP only supports radixes up to 62, but we need 64. + * So, although this is not the most elegant or efficient way, + * let's just convert the base 64 string (6 bits per digit) to + * an octal string (3 bits per digit) that's twice as long. */ + char c, *tmp, *q; + const char *p; + int i; + tmp = XMALLOC (1 + 2 * XSTRLEN (b)); + if (tmp == NULL) { + return CRYPT_MEM; + } + p = b; + q = tmp; + while ((c = *p++) != 0) { + for (i = 0; i < 64; i++) { + if (c == rmap[i]) + break; + } + if (i == 64) { + XFREE (tmp); + /* printf ("c = '%c'\n", c); */ + return CRYPT_ERROR; + } + *q++ = '0' + (i / 8); + *q++ = '0' + (i % 8); + } + *q = 0; + ret = mpz_set_str(a, tmp, 8); + /* printf ("ret = %d for '%s'\n", ret, tmp); */ + XFREE (tmp); + } else { + ret = mpz_set_str(a, b, radix); + } + return (ret == 0 ? CRYPT_OK : CRYPT_ERROR); +} + +/* write one */ +static int write_radix(void *a, char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if (radix >= 11 && radix <= 36) + /* If radix is positive, GMP uses lowercase, and if negative, uppercase. + * We want it to use uppercase, to match the test vectors (presumably + * generated with LibTomMath). */ + radix = -radix; + mpz_get_str(b, radix, a); + return CRYPT_OK; +} + +/* get size as unsigned char string */ +static unsigned long unsigned_size(void *a) +{ + unsigned long t; + LTC_ARGCHK(a != NULL); + t = mpz_sizeinbase(a, 2); + if (mpz_cmp_ui(((__mpz_struct *)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); + mpz_export(b, NULL, 1, 1, 1, 0, ((__mpz_struct*)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); + mpz_import(a, len, 1, 1, 1, 0, b); + 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); + mpz_add(c, a, b); + return CRYPT_OK; +} + +static int addi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + mpz_add_ui(c, a, b); + 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); + mpz_sub(c, a, b); + return CRYPT_OK; +} + +static int subi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + mpz_sub_ui(c, a, b); + 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); + mpz_mul(c, a, b); + return CRYPT_OK; +} + +static int muli(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + mpz_mul_ui(c, a, b); + return CRYPT_OK; +} + +/* sqr */ +static int sqr(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_mul(b, a, a); + return CRYPT_OK; +} + +/* sqrtmod_prime */ +static int sqrtmod_prime(void *n, void *prime, void *ret) +{ + int res, legendre, i; + mpz_t t1, C, Q, S, Z, M, T, R, two; + + LTC_ARGCHK(n != NULL); + LTC_ARGCHK(prime != NULL); + LTC_ARGCHK(ret != NULL); + + /* first handle the simple cases */ + if (mpz_cmp_ui(((__mpz_struct *)n), 0) == 0) { + mpz_set_ui(ret, 0); + return CRYPT_OK; + } + if (mpz_cmp_ui(((__mpz_struct *)prime), 2) == 0) return CRYPT_ERROR; /* prime must be odd */ + legendre = mpz_legendre(n, prime); + if (legendre == -1) return CRYPT_ERROR; /* quadratic non-residue mod prime */ + + mpz_init(t1); mpz_init(C); mpz_init(Q); + mpz_init(S); mpz_init(Z); mpz_init(M); + mpz_init(T); mpz_init(R); mpz_init(two); + + /* SPECIAL CASE: if prime mod 4 == 3 + * compute directly: res = n^(prime+1)/4 mod prime + * Handbook of Applied Cryptography algorithm 3.36 + */ + i = mpz_mod_ui(t1, prime, 4); /* t1 is ignored here */ + if (i == 3) { + mpz_add_ui(t1, prime, 1); + mpz_fdiv_q_2exp(t1, t1, 2); + mpz_powm(ret, n, t1, prime); + res = CRYPT_OK; + goto cleanup; + } + + /* NOW: Tonelli-Shanks algorithm */ + + /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ + mpz_set(Q, prime); + mpz_sub_ui(Q, Q, 1); + /* Q = prime - 1 */ + mpz_set_ui(S, 0); + /* S = 0 */ + while (mpz_even_p(Q)) { + mpz_fdiv_q_2exp(Q, Q, 1); + /* Q = Q / 2 */ + mpz_add_ui(S, S, 1); + /* S = S + 1 */ + } + + /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + mpz_set_ui(Z, 2); + /* Z = 2 */ + while(1) { + legendre = mpz_legendre(Z, prime); + if (legendre == -1) break; + mpz_add_ui(Z, Z, 1); + /* Z = Z + 1 */ + } + + mpz_powm(C, Z, Q, prime); + /* C = Z ^ Q mod prime */ + mpz_add_ui(t1, Q, 1); + mpz_fdiv_q_2exp(t1, t1, 1); + /* t1 = (Q + 1) / 2 */ + mpz_powm(R, n, t1, prime); + /* R = n ^ ((Q + 1) / 2) mod prime */ + mpz_powm(T, n, Q, prime); + /* T = n ^ Q mod prime */ + mpz_set(M, S); + /* M = S */ + mpz_set_ui(two, 2); + + while (1) { + mpz_set(t1, T); + i = 0; + while (1) { + if (mpz_cmp_ui(((__mpz_struct *)t1), 1) == 0) break; + mpz_powm(t1, t1, two, prime); + i++; + } + if (i == 0) { + mpz_set(ret, R); + res = CRYPT_OK; + goto cleanup; + } + mpz_sub_ui(t1, M, i); + mpz_sub_ui(t1, t1, 1); + mpz_powm(t1, two, t1, prime); + /* t1 = 2 ^ (M - i - 1) */ + mpz_powm(t1, C, t1, prime); + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ + mpz_mul(C, t1, t1); + mpz_mod(C, C, prime); + /* C = (t1 * t1) mod prime */ + mpz_mul(R, R, t1); + mpz_mod(R, R, prime); + /* R = (R * t1) mod prime */ + mpz_mul(T, T, C); + mpz_mod(T, T, prime); + /* T = (T * C) mod prime */ + mpz_set_ui(M, i); + /* M = i */ + } + +cleanup: + mpz_clear(t1); mpz_clear(C); mpz_clear(Q); + mpz_clear(S); mpz_clear(Z); mpz_clear(M); + mpz_clear(T); mpz_clear(R); mpz_clear(two); + return res; +} + +/* div */ +static int divide(void *a, void *b, void *c, void *d) +{ + mpz_t tmp; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if (c != NULL) { + mpz_init(tmp); + mpz_divexact(tmp, a, b); + } + if (d != NULL) { + mpz_mod(d, a, b); + } + if (c != NULL) { + mpz_set(c, tmp); + mpz_clear(tmp); + } + return CRYPT_OK; +} + +static int div_2(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_divexact_ui(b, a, 2); + return CRYPT_OK; +} + +/* modi */ +static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + + *c = mpz_fdiv_ui(a, b); + 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); + mpz_gcd(c, a, b); + 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); + mpz_lcm(c, a, b); + return CRYPT_OK; +} + +static int addmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + mpz_add(d, a, b); + mpz_mod(d, d, c); + return CRYPT_OK; +} + +static int submod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + mpz_sub(d, a, b); + mpz_mod(d, d, c); + return CRYPT_OK; +} + +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); + mpz_mul(d, a, b); + mpz_mod(d, d, c); + return CRYPT_OK; +} + +static int sqrmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_mul(c, a, a); + mpz_mod(c, c, b); + return CRYPT_OK; +} + +/* invmod */ +static int invmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_invert(c, a, b); + return CRYPT_OK; +} + +/* setup */ +static int montgomery_setup(void *a, void **b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + *b = (void *)1; + return CRYPT_OK; +} + +/* get normalization value */ +static int montgomery_normalization(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_set_ui(a, 1); + 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); + mpz_mod(a, a, b); + return CRYPT_OK; +} + +/* clean up */ +static void montgomery_deinit(void *a) +{ + LTC_UNUSED_PARAM(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); + mpz_powm(d, a, b, c); + return CRYPT_OK; +} + +static int isprime(void *a, int b, int *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + if (b == 0) { + b = LTC_MILLER_RABIN_REPS; + } /* if */ + *c = mpz_probab_prime_p(a, b) > 0 ? LTC_MP_YES : LTC_MP_NO; + return CRYPT_OK; +} + +static int set_rand(void *a, int size) +{ + LTC_ARGCHK(a != NULL); + mpz_random(a, size); + return CRYPT_OK; +} + +const ltc_math_descriptor gmp_desc = { + "GNU MP", + sizeof(mp_limb_t) * CHAR_BIT - GMP_NAIL_BITS, + + &init, + &init_copy, + &deinit, + + &neg, + ©, + + &set_int, + &get_int, + &get_digit, + &get_digit_count, + &compare, + &compare_d, + &count_bits, + &count_lsb_bits, + &twoexpt, + + &read_radix, + &write_radix, + &unsigned_size, + &unsigned_write, + &unsigned_read, + + &add, + &addi, + &sub, + &subi, + &mul, + &muli, + &sqr, + &sqrtmod_prime, + ÷, + &div_2, + &modi, + &gcd, + &lcm, + + &mulmod, + &sqrmod, + &invmod, + + &montgomery_setup, + &montgomery_normalization, + &montgomery_reduce, + &montgomery_deinit, + + &exptmod, + &isprime, + +#ifdef LTC_MECC +#ifdef LTC_MECC_FP + <c_ecc_fp_mulmod, +#else + <c_ecc_mulmod, +#endif /* LTC_MECC_FP */ + <c_ecc_projective_add_point, + <c_ecc_projective_dbl_point, + <c_ecc_map, +#ifdef LTC_ECC_SHAMIR +#ifdef LTC_MECC_FP + <c_ecc_fp_mul2add, +#else + <c_ecc_mul2add, +#endif /* LTC_MECC_FP */ +#else + NULL, +#endif /* LTC_ECC_SHAMIR */ +#else + NULL, NULL, NULL, NULL, NULL, +#endif /* LTC_MECC */ + +#ifdef LTC_MRSA + &rsa_make_key, + &rsa_exptmod, +#else + NULL, NULL, +#endif + &addmod, + &submod, + + &set_rand, + +}; + + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/ltm_desc.c b/optee/optee_os/core/lib/libtomcrypt/src/math/ltm_desc.c new file mode 100644 index 0000000..b49b30e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/ltm_desc.c @@ -0,0 +1,560 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define DESC_DEF_ONLY +#include "tomcrypt_private.h" + +#ifdef LTM_DESC + +#include +#if !defined(PRIVATE_MP_WARRAY) && !defined(BN_MP_PRIME_IS_PRIME_C) +#include +#endif + +static const struct { + mp_err mpi_code; + int ltc_code; +} mpi_to_ltc_codes[] = { + { MP_OKAY , CRYPT_OK}, + { MP_MEM , CRYPT_MEM}, + { MP_VAL , CRYPT_INVALID_ARG}, +#if defined(MP_BUF) || defined(MP_USE_ENUMS) + { MP_ITER , CRYPT_INVALID_PACKET}, + { MP_BUF , CRYPT_BUFFER_OVERFLOW}, +#endif +}; + +/** + Convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) + @param err The error to convert + @return The equivalent LTC error code or CRYPT_ERROR if none found +*/ +static int mpi_to_ltc_error(mp_err err) +{ + size_t x; + + for (x = 0; x < sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0]); x++) { + if (err == mpi_to_ltc_codes[x].mpi_code) { + return mpi_to_ltc_codes[x].ltc_code; + } + } + return CRYPT_ERROR; +} + +static int init_mpi(void **a) +{ + LTC_ARGCHK(a != NULL); + + *a = XCALLOC(1, sizeof(mp_int)); + if (*a == NULL) { + return CRYPT_MEM; + } else { + return CRYPT_OK; + } +} + +static int init(void **a) +{ + int err; + + LTC_ARGCHK(a != NULL); + + if ((err = init_mpi(a)) != CRYPT_OK) { + return err; + } + if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) { + XFREE(*a); + } + return err; +} + +static void deinit(void *a) +{ + LTC_ARGCHKVD(a != NULL); + mp_clear(a); + XFREE(a); +} + +static int neg(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_neg(a, b)); +} + +static int copy(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_copy(a, b)); +} + +static int init_copy(void **a, void *b) +{ + int err; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if ((err = init_mpi(a)) != CRYPT_OK) return err; + return mpi_to_ltc_error(mp_init_copy(*a, b)); +} + +/* ---- trivial ---- */ +static int set_int(void *a, ltc_mp_digit b) +{ + LTC_ARGCHK(a != NULL); +#ifdef BN_MP_SET_INT_C + return mpi_to_ltc_error(mp_set_int(a, b)); +#else + mp_set_u32(a, b); + return CRYPT_OK; +#endif +} + +static unsigned long get_int(void *a) +{ + LTC_ARGCHK(a != NULL); +#ifdef BN_MP_GET_INT_C + return mp_get_int(a); +#else + return mp_get_ul(a); +#endif +} + +static ltc_mp_digit get_digit(void *a, int n) +{ + mp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return (n >= A->used || n < 0) ? 0 : A->dp[n]; +} + +static int get_digit_count(void *a) +{ + mp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return A->used; +} + +static int compare(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + switch (mp_cmp(a, b)) { + case MP_LT: return LTC_MP_LT; + case MP_EQ: return LTC_MP_EQ; + case MP_GT: return LTC_MP_GT; + default: return 0; + } +} + +static int compare_d(void *a, ltc_mp_digit b) +{ + LTC_ARGCHK(a != NULL); + switch (mp_cmp_d(a, b)) { + case MP_LT: return LTC_MP_LT; + case MP_EQ: return LTC_MP_EQ; + case MP_GT: return LTC_MP_GT; + default: return 0; + } +} + +static int count_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return mp_count_bits(a); +} + +static int count_lsb_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return mp_cnt_lsb(a); +} + + +static int twoexpt(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + return mpi_to_ltc_error(mp_2expt(a, n)); +} + +/* ---- conversions ---- */ + +/* read ascii string */ +static int read_radix(void *a, const char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_read_radix(a, b, radix)); +} + +/* write one */ +static int write_radix(void *a, char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); +#ifdef BN_MP_TORADIX_C + return mpi_to_ltc_error(mp_toradix(a, b, radix)); +#else + return mpi_to_ltc_error(mp_to_radix(a, b, SIZE_MAX, NULL, radix)); +#endif +} + +/* get size as unsigned char string */ +static unsigned long unsigned_size(void *a) +{ + LTC_ARGCHK(a != NULL); +#ifdef BN_MP_UNSIGNED_BIN_SIZE_C + return mp_unsigned_bin_size(a); +#else + return (unsigned long)mp_ubin_size(a); +#endif +} + +/* store */ +static int unsigned_write(void *a, unsigned char *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); +#ifdef BN_MP_TO_UNSIGNED_BIN_C + return mpi_to_ltc_error(mp_to_unsigned_bin(a, b)); +#else + return mpi_to_ltc_error(mp_to_ubin(a, b, SIZE_MAX, NULL)); +#endif +} + +/* read */ +static int unsigned_read(void *a, unsigned char *b, unsigned long len) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); +#ifdef BN_MP_READ_UNSIGNED_BIN_C + return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len)); +#else + return mpi_to_ltc_error(mp_from_ubin(a, b, (size_t)len)); +#endif +} + +/* add */ +static int add(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_add(a, b, c)); +} + +static int addi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_add_d(a, b, c)); +} + +/* sub */ +static int sub(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_sub(a, b, c)); +} + +static int subi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_sub_d(a, b, c)); +} + +/* mul */ +static int mul(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_mul(a, b, c)); +} + +static int muli(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_mul_d(a, b, c)); +} + +/* sqr */ +static int sqr(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_sqr(a, b)); +} + +/* sqrtmod_prime */ +static int sqrtmod_prime(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_sqrtmod_prime(a, b, c)); +} + +/* div */ +static int divide(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_div(a, b, c, d)); +} + +static int div_2(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_div_2(a, b)); +} + +/* modi */ +static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) +{ + mp_digit tmp; + int err; + + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + + if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) { + return err; + } + *c = 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); + return mpi_to_ltc_error(mp_gcd(a, b, c)); +} + +/* lcm */ +static int lcm(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_lcm(a, b, c)); +} + +static int addmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return mpi_to_ltc_error(mp_addmod(a,b,c,d)); +} + +static int submod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return mpi_to_ltc_error(mp_submod(a,b,c,d)); +} + +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); + return mpi_to_ltc_error(mp_mulmod(a,b,c,d)); +} + +static int sqrmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_sqrmod(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); + return mpi_to_ltc_error(mp_invmod(a, b, c)); +} + +/* setup */ +static int montgomery_setup(void *a, void **b) +{ + int err; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + *b = XCALLOC(1, sizeof(mp_digit)); + if (*b == NULL) { + return CRYPT_MEM; + } + if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) { + XFREE(*b); + } + return err; +} + +/* get normalization value */ +static int montgomery_normalization(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b)); +} + +/* reduce */ +static int montgomery_reduce(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c))); +} + +/* clean up */ +static void montgomery_deinit(void *a) +{ + XFREE(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); + return mpi_to_ltc_error(mp_exptmod(a,b,c,d)); +} + +static int isprime(void *a, int b, int *c) +{ + int err; +#if defined(PRIVATE_MP_WARRAY) || defined(BN_MP_PRIME_IS_PRIME_C) + int res; +#else + bool res; +#endif + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + b = mp_prime_rabin_miller_trials(mp_count_bits(a)); + err = mpi_to_ltc_error(mp_prime_is_prime(a, b, &res)); + *c = res ? LTC_MP_YES : LTC_MP_NO; + return err; +} + +static int set_rand(void *a, int size) +{ + LTC_ARGCHK(a != NULL); + return mpi_to_ltc_error(mp_rand(a, size)); +} + +#ifndef MP_DIGIT_BIT +#define MP_DIGIT_BIT DIGIT_BIT +#endif + +const ltc_math_descriptor ltm_desc = { + + "LibTomMath", + (int)MP_DIGIT_BIT, + + &init, + &init_copy, + &deinit, + + &neg, + ©, + + &set_int, + &get_int, + &get_digit, + &get_digit_count, + &compare, + &compare_d, + &count_bits, + &count_lsb_bits, + &twoexpt, + + &read_radix, + &write_radix, + &unsigned_size, + &unsigned_write, + &unsigned_read, + + &add, + &addi, + &sub, + &subi, + &mul, + &muli, + &sqr, + &sqrtmod_prime, + ÷, + &div_2, + &modi, + &gcd, + &lcm, + + &mulmod, + &sqrmod, + &invmod, + + &montgomery_setup, + &montgomery_normalization, + &montgomery_reduce, + &montgomery_deinit, + + &exptmod, + &isprime, + +#ifdef LTC_MECC +#ifdef LTC_MECC_FP + <c_ecc_fp_mulmod, +#else + <c_ecc_mulmod, +#endif + <c_ecc_projective_add_point, + <c_ecc_projective_dbl_point, + <c_ecc_map, +#ifdef LTC_ECC_SHAMIR +#ifdef LTC_MECC_FP + <c_ecc_fp_mul2add, +#else + <c_ecc_mul2add, +#endif /* LTC_MECC_FP */ +#else + NULL, +#endif /* LTC_ECC_SHAMIR */ +#else + NULL, NULL, NULL, NULL, NULL, +#endif /* LTC_MECC */ + +#ifdef LTC_MRSA + &rsa_make_key, + &rsa_exptmod, +#else + NULL, NULL, +#endif + &addmod, + &submod, + + &set_rand, + +}; + + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/multi.c b/optee/optee_os/core/lib/libtomcrypt/src/math/multi.c new file mode 100644 index 0000000..cf2ea4d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/multi.c @@ -0,0 +1,94 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_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); + va_end(args); + return CRYPT_MEM; + } + ++np; + cur = va_arg(args, void**); + } + va_end(args); + return CRYPT_OK; +} + +int ltc_init_multi_size(int size_bits, void **a, ...) +{ + void **cur = a; + int np = 0; + va_list args; + + va_start(args, a); + while (cur != NULL) { + if (mp_init_size(size_bits, 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); +} + +void ltc_cleanup_multi(void **a, ...) +{ + void **cur = a; + va_list args; + + va_start(args, a); + while (cur != NULL) { + if (*cur != NULL) { + mp_clear(*cur); + *cur = NULL; + } + cur = va_arg(args, void**); + } + va_end(args); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/radix_to_bin.c b/optee/optee_os/core/lib/libtomcrypt/src/math/radix_to_bin.c new file mode 100644 index 0000000..5c17f0d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/radix_to_bin.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file radix_to_bin.c + Convert data from a specific radix to binary. + Steffen Jaeckel +*/ + +/** + Convert data from a specific radix to binary + + The default MPI descriptors #ltm_desc, #tfm_desc and #gmp_desc + have the following restrictions on parameters: + + \p in - NUL-terminated char buffer + + \p radix - 2..64 + + @param in The input + @param radix The radix of the input + @param out The output buffer + @param len [in/out] The length of the output buffer + + @return CRYPT_OK on success. +*/ +int radix_to_bin(const void *in, int radix, void *out, unsigned long *len) +{ + unsigned long l; + void* mpi; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(len != NULL); + + if ((err = mp_init(&mpi)) != CRYPT_OK) return err; + if ((err = mp_read_radix(mpi, in, radix)) != CRYPT_OK) goto LBL_ERR; + + if ((l = mp_unsigned_bin_size(mpi)) > *len) { + *len = l; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + *len = l; + + if ((err = mp_to_unsigned_bin(mpi, out)) != CRYPT_OK) goto LBL_ERR; + +LBL_ERR: + mp_clear(mpi); + return err; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/rand_bn.c b/optee/optee_os/core/lib/libtomcrypt/src/math/rand_bn.c new file mode 100644 index 0000000..137586c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/rand_bn.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#if defined(LTC_MDSA) || defined(LTC_MECC) +/** + Generate a random number N with given bitlength (note: MSB can be 0) +*/ + +int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng) +{ + int res, bytes; + unsigned char *buf, mask; + + LTC_ARGCHK(N != NULL); + LTC_ARGCHK(bits > 1); + + /* check PRNG */ + if ((res = prng_is_valid(wprng)) != CRYPT_OK) return res; + + bytes = (bits+7) >> 3; + mask = 0xff >> (bits % 8 == 0 ? 0 : 8 - bits % 8); + + /* allocate buffer */ + if ((buf = XCALLOC(1, bytes)) == NULL) return CRYPT_MEM; + + /* generate random bytes */ + if (prng_descriptor[wprng]->read(buf, bytes, prng) != (unsigned long)bytes) { + res = CRYPT_ERROR_READPRNG; + goto cleanup; + } + /* mask bits */ + buf[0] &= mask; + /* load value */ + if ((res = mp_read_unsigned_bin(N, buf, bytes)) != CRYPT_OK) goto cleanup; + + res = CRYPT_OK; + +cleanup: +#ifdef LTC_CLEAN_STACK + zeromem(buf, bytes); +#endif + XFREE(buf); + return res; +} + +/** + Generate a random number N in a range: 1 <= N < limit +*/ +int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng) +{ + int res, bits; + + LTC_ARGCHK(N != NULL); + LTC_ARGCHK(limit != NULL); + + bits = mp_count_bits(limit); + do { + res = rand_bn_bits(N, bits, prng, wprng); + if (res != CRYPT_OK) return res; + } while (mp_cmp_d(N, 0) != LTC_MP_GT || mp_cmp(N, limit) != LTC_MP_LT); + + return CRYPT_OK; +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/rand_prime.c b/optee/optee_os/core/lib/libtomcrypt/src/math/rand_prime.c new file mode 100644 index 0000000..b50ac8c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/rand_prime.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#if defined(LTC_MRSA) || (!defined(LTC_NO_MATH) && !defined(LTC_NO_PRNGS)) + +/** + @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, LTC_MILLER_RABIN_REPS, &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; +} + +#endif /* LTC_NO_MATH */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/math/sub.mk new file mode 100644 index 0000000..4a38a32 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/sub.mk @@ -0,0 +1,4 @@ +subdirs-y += fp +srcs-y += multi.c +srcs-y += rand_prime.c +srcs-y += rand_bn.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/math/tfm_desc.c b/optee/optee_os/core/lib/libtomcrypt/src/math/tfm_desc.c new file mode 100644 index 0000000..cee753a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/math/tfm_desc.c @@ -0,0 +1,857 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define DESC_DEF_ONLY +#include "tomcrypt_private.h" + +#ifdef TFM_DESC + +#include + +static const struct { + int tfm_code, ltc_code; +} tfm_to_ltc_codes[] = { + { FP_OKAY , CRYPT_OK}, + { FP_MEM , CRYPT_MEM}, + { FP_VAL , CRYPT_INVALID_ARG}, +}; + +/** + Convert a tfm error to a LTC error (Possibly the most powerful function ever! Oh wait... no) + @param err The error to convert + @return The equivalent LTC error code or CRYPT_ERROR if none found +*/ +static int tfm_to_ltc_error(int err) +{ + int x; + + for (x = 0; x < (int)(sizeof(tfm_to_ltc_codes)/sizeof(tfm_to_ltc_codes[0])); x++) { + if (err == tfm_to_ltc_codes[x].tfm_code) { + return tfm_to_ltc_codes[x].ltc_code; + } + } + return CRYPT_ERROR; +} + +static int init(void **a) +{ + LTC_ARGCHK(a != NULL); + + *a = XCALLOC(1, sizeof(fp_int)); + if (*a == NULL) { + return CRYPT_MEM; + } + fp_init(*a); + return CRYPT_OK; +} + +static void deinit(void *a) +{ + LTC_ARGCHKVD(a != NULL); + XFREE(a); +} + +static int neg(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_neg(((fp_int*)a), ((fp_int*)b)); + return CRYPT_OK; +} + +static int copy(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_copy(a, b); + 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, ltc_mp_digit b) +{ + LTC_ARGCHK(a != NULL); + fp_set(a, b); + return CRYPT_OK; +} + +static unsigned long get_int(void *a) +{ + fp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return A->used > 0 ? A->dp[0] : 0; +} + +static ltc_mp_digit get_digit(void *a, int n) +{ + fp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return (n >= A->used || n < 0) ? 0 : A->dp[n]; +} + +static int get_digit_count(void *a) +{ + fp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return A->used; +} + +static int compare(void *a, void *b) +{ + int ret; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + ret = fp_cmp(a, b); + switch (ret) { + case FP_LT: return LTC_MP_LT; + case FP_EQ: return LTC_MP_EQ; + case FP_GT: return LTC_MP_GT; + } + return 0; +} + +static int compare_d(void *a, ltc_mp_digit b) +{ + int ret; + LTC_ARGCHK(a != NULL); + ret = fp_cmp_d(a, b); + switch (ret) { + case FP_LT: return LTC_MP_LT; + case FP_EQ: return LTC_MP_EQ; + case FP_GT: return LTC_MP_GT; + } + return 0; +} + +static int count_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return fp_count_bits(a); +} + +static int count_lsb_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return fp_cnt_lsb(a); +} + +static int twoexpt(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + fp_2expt(a, n); + 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); + return tfm_to_ltc_error(fp_read_radix(a, (char *)b, radix)); +} + +/* write one */ +static int write_radix(void *a, char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return tfm_to_ltc_error(fp_toradix(a, b, radix)); +} + +/* get size as unsigned char string */ +static unsigned long unsigned_size(void *a) +{ + LTC_ARGCHK(a != NULL); + return fp_unsigned_bin_size(a); +} + +/* store */ +static int unsigned_write(void *a, unsigned char *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_to_unsigned_bin(a, b); + return CRYPT_OK; +} + +/* read */ +static int unsigned_read(void *a, unsigned char *b, unsigned long len) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_read_unsigned_bin(a, b, len); + 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); + fp_add(a, b, c); + return CRYPT_OK; +} + +static int addi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + fp_add_d(a, b, c); + 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); + fp_sub(a, b, c); + return CRYPT_OK; +} + +static int subi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + fp_sub_d(a, b, c); + 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); + fp_mul(a, b, c); + return CRYPT_OK; +} + +static int muli(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + fp_mul_d(a, b, c); + return CRYPT_OK; +} + +/* sqr */ +static int sqr(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_sqr(a, b); + return CRYPT_OK; +} + +/* sqrtmod_prime - NOT SUPPORTED */ + +/* div */ +static int divide(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return tfm_to_ltc_error(fp_div(a, b, c, d)); +} + +static int div_2(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_div_2(a, b); + return CRYPT_OK; +} + +/* modi */ +static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) +{ + fp_digit tmp; + int err; + + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + + if ((err = tfm_to_ltc_error(fp_mod_d(a, b, &tmp))) != CRYPT_OK) { + return err; + } + *c = 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); + fp_gcd(a, b, c); + 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); + fp_lcm(a, b, c); + return CRYPT_OK; +} + +static int addmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return tfm_to_ltc_error(fp_addmod(a,b,c,d)); +} + +static int submod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return tfm_to_ltc_error(fp_submod(a,b,c,d)); +} + +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); + return tfm_to_ltc_error(fp_mulmod(a,b,c,d)); +} + +static int sqrmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return tfm_to_ltc_error(fp_sqrmod(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); + return tfm_to_ltc_error(fp_invmod(a, b, c)); +} + +/* setup */ +static int montgomery_setup(void *a, void **b) +{ + int err; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + *b = XCALLOC(1, sizeof(fp_digit)); + if (*b == NULL) { + return CRYPT_MEM; + } + if ((err = tfm_to_ltc_error(fp_montgomery_setup(a, (fp_digit *)*b))) != CRYPT_OK) { + XFREE(*b); + } + return err; +} + +/* get normalization value */ +static int montgomery_normalization(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_montgomery_calc_normalization(a, b); + 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); + fp_montgomery_reduce(a, b, *((fp_digit *)c)); + return CRYPT_OK; +} + +/* clean up */ +static void montgomery_deinit(void *a) +{ + XFREE(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); + return tfm_to_ltc_error(fp_exptmod(a,b,c,d)); +} + +static int isprime(void *a, int b, int *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + if (b == 0) { + b = LTC_MILLER_RABIN_REPS; + } /* if */ + *c = (fp_isprime_ex(a, b) == FP_YES) ? LTC_MP_YES : LTC_MP_NO; + return CRYPT_OK; +} + +#if defined(LTC_MECC) && defined(LTC_MECC_ACCEL) + +static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *Mp) +{ + fp_int t1, t2; + fp_digit mp; + int err, inf; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(Mp != NULL); + + mp = *((fp_digit*)Mp); + + fp_init(&t1); + fp_init(&t2); + + if (P != R) { + fp_copy(P->x, R->x); + fp_copy(P->y, R->y); + fp_copy(P->z, R->z); + } + + if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* if P is point at infinity >> Result = point at infinity */ + ltc_mp.set_int(R->x, 1); + ltc_mp.set_int(R->y, 1); + ltc_mp.set_int(R->z, 0); + return CRYPT_OK; + } + + /* t1 = Z * Z */ + fp_sqr(R->z, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* Z = Y * Z */ + fp_mul(R->z, R->y, R->z); + fp_montgomery_reduce(R->z, modulus, mp); + /* Z = 2Z */ + fp_add(R->z, R->z, R->z); + if (fp_cmp(R->z, modulus) != FP_LT) { + fp_sub(R->z, modulus, R->z); + } + + if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ + /* T2 = X - T1 */ + fp_sub(R->x, &t1, &t2); + if (fp_cmp_d(&t2, 0) == LTC_MP_LT) { + fp_add(&t2, modulus, &t2); + } + /* T1 = X + T1 */ + fp_add(&t1, R->x, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T2 = T1 * T2 */ + fp_mul(&t1, &t2, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = 2T2 */ + fp_add(&t2, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + } + else { + /* T2 = T1 * T1 */ + fp_sqr(&t1, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T2 * a */ + fp_mul(&t2, ma, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* T2 = X * X */ + fp_sqr(R->x, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + } + + /* Y = 2Y */ + fp_add(R->y, R->y, R->y); + if (fp_cmp(R->y, modulus) != FP_LT) { + fp_sub(R->y, modulus, R->y); + } + /* Y = Y * Y */ + fp_sqr(R->y, R->y); + fp_montgomery_reduce(R->y, modulus, mp); + /* T2 = Y * Y */ + fp_sqr(R->y, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T2 = T2/2 */ + if (fp_isodd(&t2)) { + fp_add(&t2, modulus, &t2); + } + fp_div_2(&t2, &t2); + /* Y = Y * X */ + fp_mul(R->y, R->x, R->y); + fp_montgomery_reduce(R->y, modulus, mp); + + /* X = T1 * T1 */ + fp_sqr(&t1, R->x); + fp_montgomery_reduce(R->x, modulus, mp); + /* X = X - Y */ + fp_sub(R->x, R->y, R->x); + if (fp_cmp_d(R->x, 0) == FP_LT) { + fp_add(R->x, modulus, R->x); + } + /* X = X - Y */ + fp_sub(R->x, R->y, R->x); + if (fp_cmp_d(R->x, 0) == FP_LT) { + fp_add(R->x, modulus, R->x); + } + + /* Y = Y - X */ + fp_sub(R->y, R->x, R->y); + if (fp_cmp_d(R->y, 0) == FP_LT) { + fp_add(R->y, modulus, R->y); + } + /* Y = Y * T1 */ + fp_mul(R->y, &t1, R->y); + fp_montgomery_reduce(R->y, modulus, mp); + /* Y = Y - T2 */ + fp_sub(R->y, &t2, R->y); + if (fp_cmp_d(R->y, 0) == FP_LT) { + fp_add(R->y, modulus, R->y); + } + + return CRYPT_OK; +} + +/** + 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 +*/ +static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *Mp) +{ + fp_int t1, t2, x, y, z; + fp_digit mp; + int err, inf; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(Q != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(Mp != NULL); + + mp = *((fp_digit*)Mp); + + fp_init(&t1); + fp_init(&t2); + fp_init(&x); + fp_init(&y); + fp_init(&z); + + if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* P is point at infinity >> Result = Q */ + ltc_mp.copy(Q->x, R->x); + ltc_mp.copy(Q->y, R->y); + ltc_mp.copy(Q->z, R->z); + return CRYPT_OK; + } + + if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* Q is point at infinity >> Result = P */ + ltc_mp.copy(P->x, R->x); + ltc_mp.copy(P->y, R->y); + ltc_mp.copy(P->z, R->z); + return CRYPT_OK; + } + + /* should we dbl instead? */ + fp_sub(modulus, Q->y, &t1); + if ( (fp_cmp(P->x, Q->x) == FP_EQ) && + (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) && + (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) { + return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp); + } + + fp_copy(P->x, &x); + fp_copy(P->y, &y); + fp_copy(P->z, &z); + + /* if Z is one then these are no-operations */ + if (Q->z != NULL) { + /* T1 = Z' * Z' */ + fp_sqr(Q->z, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* X = X * T1 */ + fp_mul(&t1, &x, &x); + fp_montgomery_reduce(&x, modulus, mp); + /* T1 = Z' * T1 */ + fp_mul(Q->z, &t1, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* Y = Y * T1 */ + fp_mul(&t1, &y, &y); + fp_montgomery_reduce(&y, modulus, mp); + } + + /* T1 = Z*Z */ + fp_sqr(&z, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* T2 = X' * T1 */ + fp_mul(Q->x, &t1, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = Z * T1 */ + fp_mul(&z, &t1, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* T1 = Y' * T1 */ + fp_mul(Q->y, &t1, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + + /* Y = Y - T1 */ + fp_sub(&y, &t1, &y); + if (fp_cmp_d(&y, 0) == FP_LT) { + fp_add(&y, modulus, &y); + } + /* T1 = 2T1 */ + fp_add(&t1, &t1, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = Y + T1 */ + fp_add(&t1, &y, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* X = X - T2 */ + fp_sub(&x, &t2, &x); + if (fp_cmp_d(&x, 0) == FP_LT) { + fp_add(&x, modulus, &x); + } + /* T2 = 2T2 */ + fp_add(&t2, &t2, &t2); + if (fp_cmp(&t2, modulus) != FP_LT) { + fp_sub(&t2, modulus, &t2); + } + /* T2 = X + T2 */ + fp_add(&t2, &x, &t2); + if (fp_cmp(&t2, modulus) != FP_LT) { + fp_sub(&t2, modulus, &t2); + } + + /* if Z' != 1 */ + if (Q->z != NULL) { + /* Z = Z * Z' */ + fp_mul(&z, Q->z, &z); + fp_montgomery_reduce(&z, modulus, mp); + } + + /* Z = Z * X */ + fp_mul(&z, &x, &z); + fp_montgomery_reduce(&z, modulus, mp); + + /* T1 = T1 * X */ + fp_mul(&t1, &x, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* X = X * X */ + fp_sqr(&x, &x); + fp_montgomery_reduce(&x, modulus, mp); + /* T2 = T2 * x */ + fp_mul(&t2, &x, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T1 * X */ + fp_mul(&t1, &x, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + + /* X = Y*Y */ + fp_sqr(&y, &x); + fp_montgomery_reduce(&x, modulus, mp); + /* X = X - T2 */ + fp_sub(&x, &t2, &x); + if (fp_cmp_d(&x, 0) == FP_LT) { + fp_add(&x, modulus, &x); + } + + /* T2 = T2 - X */ + fp_sub(&t2, &x, &t2); + if (fp_cmp_d(&t2, 0) == FP_LT) { + fp_add(&t2, modulus, &t2); + } + /* T2 = T2 - X */ + fp_sub(&t2, &x, &t2); + if (fp_cmp_d(&t2, 0) == FP_LT) { + fp_add(&t2, modulus, &t2); + } + /* T2 = T2 * Y */ + fp_mul(&t2, &y, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* Y = T2 - T1 */ + fp_sub(&t2, &t1, &y); + if (fp_cmp_d(&y, 0) == FP_LT) { + fp_add(&y, modulus, &y); + } + /* Y = Y/2 */ + if (fp_isodd(&y)) { + fp_add(&y, modulus, &y); + } + fp_div_2(&y, &y); + + fp_copy(&x, R->x); + fp_copy(&y, R->y); + fp_copy(&z, R->z); + + return CRYPT_OK; +} + + +#endif + +static int set_rand(void *a, int size) +{ + LTC_ARGCHK(a != NULL); + fp_rand(a, size); + return CRYPT_OK; +} + +const ltc_math_descriptor tfm_desc = { + + "TomsFastMath", + (int)DIGIT_BIT, + + &init, + &init_copy, + &deinit, + + &neg, + ©, + + &set_int, + &get_int, + &get_digit, + &get_digit_count, + &compare, + &compare_d, + &count_bits, + &count_lsb_bits, + &twoexpt, + + &read_radix, + &write_radix, + &unsigned_size, + &unsigned_write, + &unsigned_read, + + &add, + &addi, + &sub, + &subi, + &mul, + &muli, + &sqr, + NULL, /* TODO: &sqrtmod_prime */ + ÷, + &div_2, + &modi, + &gcd, + &lcm, + + &mulmod, + &sqrmod, + &invmod, + + &montgomery_setup, + &montgomery_normalization, + &montgomery_reduce, + &montgomery_deinit, + + &exptmod, + &isprime, + +#ifdef LTC_MECC +#ifdef LTC_MECC_FP + <c_ecc_fp_mulmod, +#else + <c_ecc_mulmod, +#endif /* LTC_MECC_FP */ +#ifdef LTC_MECC_ACCEL + &tfm_ecc_projective_add_point, + &tfm_ecc_projective_dbl_point, +#else + <c_ecc_projective_add_point, + <c_ecc_projective_dbl_point, +#endif /* LTC_MECC_ACCEL */ + <c_ecc_map, +#ifdef LTC_ECC_SHAMIR +#ifdef LTC_MECC_FP + <c_ecc_fp_mul2add, +#else + <c_ecc_mul2add, +#endif /* LTC_MECC_FP */ +#else + NULL, +#endif /* LTC_ECC_SHAMIR */ +#else + NULL, NULL, NULL, NULL, NULL, +#endif /* LTC_MECC */ + +#ifdef LTC_MRSA + &rsa_make_key, + &rsa_exptmod, +#else + NULL, NULL, +#endif + &addmod, + &submod, + + set_rand, + +}; + + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/adler32.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/adler32.c new file mode 100644 index 0000000..8c2953d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/adler32.c @@ -0,0 +1,123 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file adler32.c + Adler-32 checksum algorithm + Written and placed in the public domain by Wei Dai + Adapted for libtomcrypt by Steffen Jaeckel +*/ +#ifdef LTC_ADLER32 + +static const unsigned long s_adler32_base = 65521; + +void adler32_init(adler32_state *ctx) +{ + LTC_ARGCHKVD(ctx != NULL); + ctx->s[0] = 1; + ctx->s[1] = 0; +} + +void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length) +{ + unsigned long s1, s2; + + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(input != NULL); + s1 = ctx->s[0]; + s2 = ctx->s[1]; + + if (length % 8 != 0) { + do { + s1 += *input++; + s2 += s1; + length--; + } while (length % 8 != 0); + + if (s1 >= s_adler32_base) { + s1 -= s_adler32_base; + } + s2 %= s_adler32_base; + } + + while (length > 0) { + s1 += input[0]; + s2 += s1; + s1 += input[1]; + s2 += s1; + s1 += input[2]; + s2 += s1; + s1 += input[3]; + s2 += s1; + s1 += input[4]; + s2 += s1; + s1 += input[5]; + s2 += s1; + s1 += input[6]; + s2 += s1; + s1 += input[7]; + s2 += s1; + + length -= 8; + input += 8; + + if (s1 >= s_adler32_base) { + s1 -= s_adler32_base; + } + s2 %= s_adler32_base; + } + + LTC_ARGCHKVD(s1 < s_adler32_base); + LTC_ARGCHKVD(s2 < s_adler32_base); + + ctx->s[0] = (unsigned short)s1; + ctx->s[1] = (unsigned short)s2; +} + +void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size) +{ + unsigned char* h; + + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(hash != NULL); + + h = hash; + + switch (size) { + default: + h[3] = ctx->s[0] & 0x0ff; + /* FALLTHROUGH */ + case 3: + h[2] = (ctx->s[0] >> 8) & 0x0ff; + /* FALLTHROUGH */ + case 2: + h[1] = ctx->s[1] & 0x0ff; + /* FALLTHROUGH */ + case 1: + h[0] = (ctx->s[1] >> 8) & 0x0ff; + /* FALLTHROUGH */ + case 0: + ; + } +} + +int adler32_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + const void* in = "libtomcrypt"; + const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba }; + unsigned char out[4]; + adler32_state ctx; + adler32_init(&ctx); + adler32_update(&ctx, in, XSTRLEN(in)); + adler32_finish(&ctx, out, 4); + if (compare_testvector(adler32, 4, out, 4, "adler32", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_decode.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_decode.c new file mode 100644 index 0000000..8ebc9ea --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_decode.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file base16_decode.c + Base16/Hex decode a string. + Based on https://stackoverflow.com/a/23898449 + Adapted for libtomcrypt by Steffen Jaeckel +*/ + +#ifdef LTC_BASE16 + +/** + Base16 decode a string + @param in The Base16 string to decode + @param inlen The length of the Base16 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 base16_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long pos, out_len; + unsigned char idx0, idx1; + char in0, in1; + + const unsigned char hashmap[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ + 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */ + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */ + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `abcdefg */ + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((inlen % 2) == 1) return CRYPT_INVALID_PACKET; + out_len = *outlen * 2; + for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) { + in0 = in[pos + 0]; + in1 = in[pos + 1]; + + if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET; + if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET; + + idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10; + idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10; + + if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET; + if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET; + + out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1]; + } + *outlen = pos / 2; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_encode.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_encode.c new file mode 100644 index 0000000..649a4d8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/base16/base16_encode.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file base16_encode.c + Base16/Hex encode a string, Steffen Jaeckel +*/ + +#ifdef LTC_BASE16 + +/** + Base16 encode a buffer + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the Base16 encoded data + @param outlen [in/out] The max size and resulting size of the encoded data + @param options Output 'a-f' on 0 and 'A-F' otherwise. + @return CRYPT_OK if successful +*/ +int base16_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int options) +{ + unsigned long i, x; + const char *alphabet; + const char *alphabets[2] = { + "0123456789abcdef", + "0123456789ABCDEF", + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* check the sizes */ + x = inlen * 2 + 1; + + if (x < inlen) return CRYPT_OVERFLOW; + + if (*outlen < x) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + x--; + *outlen = x; /* returning the length without terminating NUL */ + + if (options == 0) { + alphabet = alphabets[0]; + } else { + alphabet = alphabets[1]; + } + + for (i = 0; i < x; i += 2) { + out[i] = alphabet[(in[i/2] >> 4) & 0x0f]; + out[i+1] = alphabet[in[i/2] & 0x0f]; + } + out[x] = '\0'; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_decode.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_decode.c new file mode 100644 index 0000000..fc98cce --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_decode.c @@ -0,0 +1,111 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BASE32 + +/** + Base32 decode a buffer + @param in The Base32 data to decode + @param inlen The length of the Base32 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 + @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD + @return CRYPT_OK if successful +*/ +int base32_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + base32_alphabet id) +{ + unsigned long x; + int y = 0; + ulong64 t = 0; + char c; + const unsigned char *map; + const unsigned char tables[4][43] = { + { /* id = BASE32_RFC4648 : ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 */ + 99/*0*/,99/*1*/,26/*2*/,27/*3*/,28/*4*/,29/*5*/,30/*6*/,31/*7*/,99/*8*/,99/*9*/, + 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, + 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, 7/*H*/, 8/*I*/, 9/*J*/,10/*K*/,11/*L*/,12/*M*/, + 13/*N*/,14/*O*/,15/*P*/,16/*Q*/,17/*R*/,18/*S*/,19/*T*/,20/*U*/,21/*V*/,22/*W*/,23/*X*/,24/*Y*/,25/*Z*/ + }, + { /* id = BASE32_BASE32HEX : 0123456789ABCDEFGHIJKLMNOPQRSTUV */ + 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/, + 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, + 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/,18/*I*/,19/*J*/,20/*K*/,21/*L*/,22/*M*/, + 23/*N*/,24/*O*/,25/*P*/,26/*Q*/,27/*R*/,28/*S*/,29/*T*/,30/*U*/,31/*V*/,99/*W*/,99/*X*/,99/*Y*/,99/*Z*/ + }, + { /* id = BASE32_ZBASE32 : YBNDRFG8EJKMCPQXOT1UWISZA345H769 */ + 99/*0*/,18/*1*/,99/*2*/,25/*3*/,26/*4*/,27/*5*/,30/*6*/,29/*7*/, 7/*8*/,31/*9*/, + 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, + 24/*A*/, 1/*B*/,12/*C*/, 3/*D*/, 8/*E*/, 5/*F*/, 6/*G*/,28/*H*/,21/*I*/, 9/*J*/,10/*K*/,99/*L*/,11/*M*/, + 2/*N*/,16/*O*/,13/*P*/,14/*Q*/, 4/*R*/,22/*S*/,17/*T*/,19/*U*/,99/*V*/,20/*W*/,15/*X*/, 0/*Y*/,23/*Z*/ + }, + { /* id = BASE32_CROCKFORD : 0123456789ABCDEFGHJKMNPQRSTVWXYZ + O=>0 + IL=>1 */ + 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/, + 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, + 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/, 1/*I*/,18/*J*/,19/*K*/, 1/*L*/,20/*M*/, + 21/*N*/, 0/*O*/,22/*P*/,23/*Q*/,24/*R*/,25/*S*/,26/*T*/,99/*U*/,27/*V*/,28/*W*/,29/*X*/,30/*Y*/,31/*Z*/ + } + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(id >= BASE32_RFC4648); + LTC_ARGCHK(id <= BASE32_CROCKFORD); + + /* ignore all trailing = */ + while (inlen > 0 && in[inlen-1] == '=') inlen--; + + /* no input, nothing to do */ + if (inlen == 0) { + *outlen = 0; + return CRYPT_OK; + } + + /* check the size of output buffer */ + x = (inlen * 5) / 8; + if (*outlen < x) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = x; + + /* check input data length */ + x = inlen % 8; + if (x == 1 || x == 3 || x == 6) { + return CRYPT_INVALID_PACKET; + } + + map = tables[id]; + for (x = 0; x < inlen; x++) { + c = in[x]; + /* convert to upper case */ + if ((c >= 'a') && (c <= 'z')) c -= 32; + if (c < '0' || c > 'Z' || map[c-'0'] > 31) { + return CRYPT_INVALID_PACKET; + } + t = (t<<5) | map[c-'0']; + if (++y == 8) { + *out++ = (unsigned char)((t>>32) & 255); + *out++ = (unsigned char)((t>>24) & 255); + *out++ = (unsigned char)((t>>16) & 255); + *out++ = (unsigned char)((t>> 8) & 255); + *out++ = (unsigned char)( t & 255); + y = 0; + t = 0; + } + } + if (y > 0) { + t = t << (5 * (8 - y)); + if (y >= 2) *out++ = (unsigned char)((t>>32) & 255); + if (y >= 4) *out++ = (unsigned char)((t>>24) & 255); + if (y >= 5) *out++ = (unsigned char)((t>>16) & 255); + if (y >= 7) *out++ = (unsigned char)((t>> 8) & 255); + } + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_encode.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_encode.c new file mode 100644 index 0000000..29519bf --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/base32/base32_encode.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BASE32 + +/** + Base32 encode a buffer + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the Base32 encoded data + @param outlen [in/out] The max size and resulting size of the encoded data + @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD + @return CRYPT_OK if successful +*/ +int base32_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + base32_alphabet id) +{ + unsigned long i, x; + const char *codes; + const char *alphabet[4] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", /* id = BASE32_RFC4648 */ + "0123456789ABCDEFGHIJKLMNOPQRSTUV", /* id = BASE32_BASE32HEX */ + "ybndrfg8ejkmcpqxot1uwisza345h769", /* id = BASE32_ZBASE32 */ + "0123456789ABCDEFGHJKMNPQRSTVWXYZ" /* id = BASE32_CROCKFORD */ + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(id >= BASE32_RFC4648); + LTC_ARGCHK(id <= BASE32_CROCKFORD); + + /* check the size of output buffer +1 byte for terminating NUL */ + x = (8 * inlen + 4) / 5 + 1; + if (*outlen < x) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = x - 1; /* returning the length without terminating NUL */ + + /* no input, nothing to do */ + if (inlen == 0) { + *out = '\0'; + return CRYPT_OK; + } + + codes = alphabet[id]; + x = 5 * (inlen / 5); + for (i = 0; i < x; i += 5) { + *out++ = codes[(in[0] >> 3) & 0x1F]; + *out++ = codes[(((in[0] & 0x7) << 2) + (in[1] >> 6)) & 0x1F]; + *out++ = codes[(in[1] >> 1) & 0x1F]; + *out++ = codes[(((in[1] & 0x1) << 4) + (in[2] >> 4)) & 0x1F]; + *out++ = codes[(((in[2] & 0xF) << 1) + (in[3] >> 7)) & 0x1F]; + *out++ = codes[(in[3] >> 2) & 0x1F]; + *out++ = codes[(((in[3] & 0x3) << 3) + (in[4] >> 5)) & 0x1F]; + *out++ = codes[in[4] & 0x1F]; + in += 5; + } + if (i < inlen) { + unsigned a = in[0]; + unsigned b = (i+1 < inlen) ? in[1] : 0; + unsigned c = (i+2 < inlen) ? in[2] : 0; + unsigned d = (i+3 < inlen) ? in[3] : 0; + *out++ = codes[(a >> 3) & 0x1F]; + *out++ = codes[(((a & 0x7) << 2) + (b >> 6)) & 0x1F]; + if (i+1 < inlen) { + *out++ = codes[(b >> 1) & 0x1F]; + *out++ = codes[(((b & 0x1) << 4) + (c >> 4)) & 0x1F]; + } + if (i+2 < inlen) { + *out++ = codes[(((c & 0xF) << 1) + (d >> 7)) & 0x1F]; + } + if (i+3 < inlen) { + *out++ = codes[(d >> 2) & 0x1F]; + *out++ = codes[((d & 0x3) << 3) & 0x1F]; + } + } + *out = '\0'; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_decode.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_decode.c new file mode 100644 index 0000000..5859111 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_decode.c @@ -0,0 +1,229 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file base64_decode.c + Compliant base64 code donated by Wayne Scott (wscott@bitmover.com) + base64 URL Safe variant (RFC 4648 section 5) by Karel Miko +*/ + + +#if defined(LTC_BASE64) || defined (LTC_BASE64_URL) + +/* 253 - ignored in "relaxed" + "insane" mode: TAB(9), CR(13), LF(10), space(32) + * 254 - padding character '=' (allowed only at the end) + * 255 - ignored in "insane" mode, but not allowed in "relaxed" + "strict" mode + */ + +#if defined(LTC_BASE64) +static const unsigned char map_base64[256] = { +255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, +255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 253, 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 }; +#endif /* LTC_BASE64 */ + +static const unsigned char map_base64url[] = { +#if defined(LTC_BASE64_URL) +255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, +255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, + 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, 63, +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 +#endif /* LTC_BASE64_URL */ +}; + +enum { + insane = 0, + strict = 1, + relaxed = 2 +}; + +static int s_base64_decode_internal(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *map, int mode) +{ + unsigned long t, x, y, z; + unsigned char c; + int g; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + g = 0; /* '=' counter */ + for (x = y = z = t = 0; x < inlen; x++) { + if ((in[x] == 0) && (x == (inlen - 1)) && (mode != strict)) { + continue; /* allow the last byte to be NUL (relaxed+insane) */ + } + c = map[(unsigned char)in[x]&0xFF]; + if (c == 254) { + g++; + continue; + } + if (c == 253) { + if (mode == strict) { + return CRYPT_INVALID_PACKET; + } + continue; /* allow to ignore white-spaces (relaxed+insane) */ + } + if (c == 255) { + if (mode == insane) { + continue; /* allow to ignore invalid garbage (insane) */ + } + return CRYPT_INVALID_PACKET; + } + if ((g > 0) && (mode != insane)) { + /* we only allow '=' to be at the end (strict+relaxed) */ + return CRYPT_INVALID_PACKET; + } + + t = (t<<6)|c; + + if (++y == 4) { + if (z + 3 > *outlen) return CRYPT_BUFFER_OVERFLOW; + out[z++] = (unsigned char)((t>>16)&255); + out[z++] = (unsigned char)((t>>8)&255); + out[z++] = (unsigned char)(t&255); + y = t = 0; + } + } + + if (y != 0) { + if (y == 1) return CRYPT_INVALID_PACKET; + if (((y + g) != 4) && (mode == strict) && (map != map_base64url)) return CRYPT_INVALID_PACKET; + t = t << (6 * (4 - y)); + if (z + y - 1 > *outlen) return CRYPT_BUFFER_OVERFLOW; + if (y >= 2) out[z++] = (unsigned char) ((t >> 16) & 255); + if (y == 3) out[z++] = (unsigned char) ((t >> 8) & 255); + } + *outlen = z; + return CRYPT_OK; +} + +#if defined(LTC_BASE64) +/** + Dangerously relaxed 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 char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64, insane); +} + +/** + Strict 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_strict_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64, strict); +} + +/** + Sane 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_sane_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64, relaxed); +} +#endif /* LTC_BASE64 */ + +#if defined(LTC_BASE64_URL) +/** + Dangerously relaxed base64 (URL Safe, RFC 4648 section 5) 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 base64url_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, insane); +} + +/** + Strict base64 (URL Safe, RFC 4648 section 5) 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 base64url_strict_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, strict); +} + +/** + Sane base64 (URL Safe, RFC 4648 section 5) 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 base64url_sane_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, relaxed); +} +#endif /* LTC_BASE64_URL */ + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_encode.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_encode.c new file mode 100644 index 0000000..ef8aee9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/base64/base64_encode.c @@ -0,0 +1,159 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file base64_encode.c + Compliant base64 encoder donated by Wayne Scott (wscott@bitmover.com) + base64 URL Safe variant (RFC 4648 section 5) by Karel Miko +*/ + + +#if defined(LTC_BASE64) || defined (LTC_BASE64_URL) + +#if defined(LTC_BASE64) +static const char * const codes_base64 = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +#endif /* LTC_BASE64 */ + +#if defined(LTC_BASE64_URL) +static const char * const codes_base64url = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +#endif /* LTC_BASE64_URL */ + +enum mode { + nopad = 0, + pad = 1, + lf = 2, + cr = 4, + ssh = 8, + crlf = lf | cr, +}; + +static int s_base64_encode_internal(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + const char *codes, unsigned int mode) +{ + unsigned long i, len2, leven, linelen; + char *p; + + LTC_ARGCHK(outlen != NULL); + + linelen = (mode & ssh) ? 72 : 64; + + /* valid output size ? */ + len2 = 4 * ((inlen + 2) / 3); + if ((mode & crlf) == lf) { + len2 += len2 / linelen; + } else if ((mode & crlf) == crlf) { + len2 += (len2 / linelen) * 2; + } + if (*outlen < len2 + 1) { + *outlen = len2 + 1; + return CRYPT_BUFFER_OVERFLOW; + } + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if ((void*)in == out) { + return CRYPT_INVALID_ARG; + } + + 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; + if ((p - out) % linelen == 0) { + if (mode & cr) *p++ = '\r'; + if (mode & lf) *p++ = '\n'; + } + } + /* 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]; + if (mode & pad) { + *p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '='; + *p++ = '='; + } + else { + if (i+1 < inlen) *p++ = codes[(((b & 0xf) << 2)) & 0x3F]; + } + } + + /* append a NULL byte */ + *p = '\0'; + + /* return ok */ + *outlen = (unsigned long)(p - out); /* the length without terminating NUL */ + return CRYPT_OK; +} + +#if defined(LTC_BASE64) +/** + 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, + char *out, unsigned long *outlen) +{ + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, pad); +} + +/** + base64 Encode a buffer for PEM output + (NUL terminated with line-break at 64 chars) + @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 + @param flags \ref base64_pem_flags + @return CRYPT_OK if successful +*/ +int base64_encode_pem(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int flags) +{ + int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf; + int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0; + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, ssh_style | use_crlf); +} +#endif /* LTC_BASE64 */ + + +#if defined(LTC_BASE64_URL) +/** + base64 (URL Safe, RFC 4648 section 5) 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 base64url_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen) +{ + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, nopad); +} + +int base64url_strict_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen) +{ + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, pad); +} +#endif /* LTC_BASE64_URL */ + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/base64/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/misc/base64/sub.mk new file mode 100644 index 0000000..9191690 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c new file mode 100644 index 0000000..1bebdff --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c @@ -0,0 +1,191 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file bcrypt.c + bcrypt pbkdf, Steffen Jaeckel +*/ +#ifdef LTC_BCRYPT + +#define BCRYPT_WORDS 8 +#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4) + +static int s_bcrypt_hash(const unsigned char *pt, + const unsigned char *pass, unsigned long passlen, + const unsigned char *salt, unsigned long saltlen, + unsigned char *out, unsigned long *outlen) +{ + symmetric_key key; + int err, n; + ulong32 ct[BCRYPT_WORDS]; + + if ((err = blowfish_setup_with_data(pass, passlen, salt, saltlen, &key)) != CRYPT_OK) { + return err; + } + for (n = 0; n < 64; ++n) { + if ((err = blowfish_expand(salt, saltlen, NULL, 0, &key)) != CRYPT_OK) { + return err; + } + if ((err = blowfish_expand(pass, passlen, NULL, 0, &key)) != CRYPT_OK) { + return err; + } + } + + for (n = 0; n < BCRYPT_WORDS; ++n) { + LOAD32H(ct[n], &pt[n*4]); + } + + for (n = 0; n < 64; ++n) { + blowfish_enc(ct, BCRYPT_WORDS/2, &key); + } + + for (n = 0; n < BCRYPT_WORDS; ++n) { + STORE32L(ct[n], &out[4 * n]); + } + *outlen = sizeof(ct); +#ifdef LTC_CLEAN_STACK + zeromem(&key, sizeof(key)); + zeromem(ct, sizeof(ct)); +#endif + + return CRYPT_OK; +} + +static int s_bcrypt_pbkdf_hash(const unsigned char *pass, unsigned long passlen, + const unsigned char *salt, unsigned long saltlen, + unsigned char *out, unsigned long *outlen) +{ + const unsigned char pt[] = "OxychromaticBlowfishSwatDynamite"; + return s_bcrypt_hash(pt, pass, passlen, salt, saltlen, out, outlen); +} + +/** + Compatible to bcrypt_pbkdf() as provided in OpenBSD + @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 rounds # of iterations desired [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 desired size of the algorithm output + @return CRYPT_OK if successful +*/ +int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, + const unsigned char *salt, unsigned long salt_len, + unsigned int rounds, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err; + ulong32 blkno; + unsigned long left, itts, x, y, hashed_pass_len, step_size, steps, dest, used_rounds; + unsigned char *buf[3], blkbuf[4]; + unsigned char *hashed_pass; + + LTC_ARGCHK(secret != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((secret_len == 0) || (salt_len == 0) || (*outlen == 0)) { + return CRYPT_INVALID_ARG; + } + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + /* set default value for rounds if not given */ + if (rounds == 0) { + used_rounds = LTC_BCRYPT_DEFAULT_ROUNDS; + } else { + used_rounds = rounds; + } + + buf[0] = XMALLOC(MAXBLOCKSIZE * 3); + hashed_pass = XMALLOC(MAXBLOCKSIZE); + if (buf[0] == NULL || hashed_pass == NULL) { + if (hashed_pass != NULL) { + XFREE(hashed_pass); + } + 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; + buf[2] = buf[1] + MAXBLOCKSIZE; + + step_size = (*outlen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE; + steps = (*outlen + step_size - 1) / step_size; + + hashed_pass_len = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, (unsigned char*)secret, secret_len, hashed_pass, &hashed_pass_len)) != CRYPT_OK) { + goto LBL_ERR; + } + + left = *outlen; + blkno = 0; + while (left != 0) { + /* increment and store current block number */ + ++blkno; + STORE32H(blkno, blkbuf); + + /* process block number blkno */ + zeromem(buf[0], MAXBLOCKSIZE*2); + + x = MAXBLOCKSIZE; + if ((err = hash_memory_multi(hash_idx, buf[0], &x, + salt, salt_len, + blkbuf, 4uL, + LTC_NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + y = MAXBLOCKSIZE; + if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + XMEMCPY(buf[2], buf[1], y); + + /* now compute repeated and XOR it in buf[2] */ + for (itts = 1; itts < used_rounds; ++itts) { + x = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, buf[1], y, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y = MAXBLOCKSIZE; + if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + for (x = 0; x < y; x++) { + buf[2][x] ^= buf[1][x]; + } + } + + /* now emit upto `steps` bytes of buf[2] to output */ + steps = MIN(steps, left); + for (y = 0; y < steps; ++y) { + dest = y * step_size + (blkno - 1); + if (dest >= *outlen) + break; + out[dest] = buf[2][y]; + } + left -= y; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf[0], MAXBLOCKSIZE*3); + zeromem(hashed_pass, MAXBLOCKSIZE); +#endif + + XFREE(hashed_pass); + XFREE(buf[0]); + + return err; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/burn_stack.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/burn_stack.c new file mode 100644 index 0000000..5d276a4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/burn_stack.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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)); + } +} + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/compare_testvector.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/compare_testvector.c new file mode 100644 index 0000000..bb3c8cb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/compare_testvector.c @@ -0,0 +1,81 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file compare_testvector.c + Function to compare two testvectors and print a (detailed) error-message if required, Steffen Jaeckel +*/ + +#if defined(LTC_TEST) && defined(LTC_TEST_DBG) +static void s_print_hex(const char* what, const void* v, const unsigned long l) +{ + const unsigned char* p = v; + unsigned long x, y = 0, z; + fprintf(stderr, "%s contents: \n", what); + for (x = 0; x < l; ) { + fprintf(stderr, "%02X ", p[x]); + if (!(++x % 16) || x == l) { + if((x % 16) != 0) { + z = 16 - (x % 16); + if(z >= 8) + fprintf(stderr, " "); + for (; z != 0; --z) { + fprintf(stderr, " "); + } + } + fprintf(stderr, " | "); + for(; y < x; y++) { + if((y % 8) == 0) + fprintf(stderr, " "); + if(isgraph(p[y])) + fprintf(stderr, "%c", p[y]); + else + fprintf(stderr, "."); + } + fprintf(stderr, "\n"); + } + else if((x % 8) == 0) { + fprintf(stderr, " "); + } + } +} +#endif + +/** + Compare two test-vectors + + @param is The data as it is + @param is_len The length of is + @param should The data as it should + @param should_len The length of should + @param what The type of the data + @param which The iteration count + @return 0 on equality, -1 or 1 on difference +*/ +int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which) +{ + int res = 0; + if(is_len != should_len) { + res = is_len > should_len ? -1 : 1; + } else { + res = XMEMCMP(is, should, is_len); + } +#if defined(LTC_TEST) && defined(LTC_TEST_DBG) + if (res != 0) { + fprintf(stderr, "Testvector #%i(0x%x) of %s failed:\n", which, which, what); + s_print_hex("SHOULD", should, should_len); + s_print_hex("IS ", is, is_len); +#if LTC_TEST_DBG > 1 + } else { + fprintf(stderr, "Testvector #%i(0x%x) of %s passed!\n", which, which, what); +#endif + } +#else + LTC_UNUSED_PARAM(which); + LTC_UNUSED_PARAM(what); +#endif + + return res; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/copy_or_zeromem.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/copy_or_zeromem.c new file mode 100644 index 0000000..a05eac6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/copy_or_zeromem.c @@ -0,0 +1,51 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file copy_or_zeromem.c + Either copy or zero a block of memory in constant time, Steffen Jaeckel +*/ + +/** + Either copy or zero a block of memory in constant time + @param src The source where to read from + @param dest The destination where to write to + @param len The length of the area to process (octets) + @param coz Copy (on 0) Or Zero (> 0) +*/ +void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz) +{ + unsigned long y; +#ifdef LTC_FAST + unsigned long z; + LTC_FAST_TYPE fastMask = ~(LTC_FAST_TYPE)0; /* initialize fastMask at all ones */ +#endif + unsigned char mask = 0xff; /* initialize mask at all ones */ + + LTC_ARGCHKVD(src != NULL); + LTC_ARGCHKVD(dest != NULL); + + if (coz != 0) coz = 1; + y = 0; + mask *= 1 - coz; /* mask = ( coz ? 0 : 0xff ) */ +#ifdef LTC_FAST + fastMask *= 1 - coz; + if (len & ~15) { + for (; y < (len & ~15); y += 16) { + for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&dest[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&src[y+z])) & fastMask; + } + } + } +#endif + for (; y < len; y++) { + dest[y] = src[y] & mask; + } +#ifdef LTC_CLEAN_STACK +#ifdef LTC_FAST + fastMask = 0; +#endif + mask = 0; +#endif +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crc32.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crc32.c new file mode 100644 index 0000000..d90e830 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crc32.c @@ -0,0 +1,193 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crc32.c + CRC-32 checksum algorithm + Written and placed in the public domain by Wei Dai + Adapted for libtomcrypt by Steffen Jaeckel +*/ +#ifdef LTC_CRC32 + +static const ulong32 CRC32_NEGL = 0xffffffffUL; + +#if defined(ENDIAN_LITTLE) +#define CRC32_INDEX(c) (c & 0xff) +#define CRC32_SHIFTED(c) (c >> 8) +#elif defined(ENDIAN_BIG) +#define CRC32_INDEX(c) (c >> 24) +#define CRC32_SHIFTED(c) (c << 8) +#else +#error The existing CRC32 implementation only works properly when the endianness of the target platform is known. +#endif + +/* Table of CRC-32's of all single byte values (made by makecrc.c) */ +static const ulong32 crc32_m_tab[] = +{ +#if defined(ENDIAN_LITTLE) + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +#else + 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, + 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, + 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, + 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, + 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, + 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, + 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, + 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, + 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, + 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, + 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, + 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, + 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, + 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, + 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, + 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, + 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, + 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, + 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, + 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, + 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, + 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, + 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, + 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, + 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, + 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, + 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, + 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, + 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, + 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, + 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, + 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, + 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, + 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, + 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, + 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, + 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, + 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, + 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, + 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, + 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, + 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, + 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, + 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, + 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, + 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, + 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, + 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, + 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, + 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, + 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, + 0x8def022dL +#endif +}; + +void crc32_init(crc32_state *ctx) +{ + LTC_ARGCHKVD(ctx != NULL); + ctx->crc = CRC32_NEGL; +} + +void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length) +{ + ulong32 crc; + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(input != NULL); + crc = ctx->crc; + + while (length--) { + crc = crc32_m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc); + } + + ctx->crc = crc; +} + +void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size) +{ + unsigned long i; + unsigned char* h; + ulong32 crc; + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(hash != NULL); + + h = hash; + crc = ctx->crc; + crc ^= CRC32_NEGL; + + if (size > 4) size = 4; + for (i = 0; i < size; i++) { + h[i] = ((unsigned char*)&(crc))[size-i-1]; + } +} + +int crc32_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + const void* in = "libtomcrypt"; + const unsigned char crc32[] = { 0xb3, 0x73, 0x76, 0xef }; + unsigned char out[4]; + crc32_state ctx; + crc32_init(&ctx); + crc32_update(&ctx, in, XSTRLEN(in)); + crc32_finish(&ctx, out, 4); + if (compare_testvector(crc32, 4, out, 4, "CRC32", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt.c new file mode 100644 index 0000000..14576fa --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt.c @@ -0,0 +1,552 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt.c + Build strings, Tom St Denis +*/ +#define NAME_VALUE(s) #s"="NAME(s) +#define NAME(s) #s + +const char *crypt_build_settings = + "LibTomCrypt " SCRYPT " (www.libtom.net)\n" + "LibTomCrypt is public domain software.\n" +#if defined(INCLUDE_BUILD_DATE) + "Built on " __DATE__ " at " __TIME__ "\n" +#endif + "\n\nEndianness: " +#if defined(ENDIAN_NEUTRAL) + "neutral/" +#endif +#if defined(ENDIAN_LITTLE) + "little" +#elif defined(ENDIAN_BIG) + "big" +#endif + #if defined(ENDIAN_32BITWORD) + " (32-bit words)\n" + #elif defined(ENDIAN_64BITWORD) + " (64-bit words)\n" + #else + " (no wordsize defined)\n" + #endif + "Clean stack: " +#if defined(LTC_CLEAN_STACK) + "enabled\n" +#else + "disabled\n" +#endif + "\nCiphers built-in:\n" +#if defined(LTC_BLOWFISH) + " Blowfish\n" +#endif +#if defined(LTC_RC2) + " RC2\n" +#endif +#if defined(LTC_RC5) + " RC5\n" +#endif +#if defined(LTC_RC6) + " 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) + " 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) + " DES\n" +#endif +#if defined(LTC_CAST5) + " 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) + " KSEED\n" +#endif +#if defined(LTC_KASUMI) + " KASUMI\n" +#endif +#if defined(LTC_MULTI2) + " MULTI2\n" +#endif +#if defined(LTC_CAMELLIA) + " Camellia\n" +#endif +#if defined(LTC_IDEA) + " IDEA\n" +#endif +#if defined(LTC_SERPENT) + " Serpent\n" +#endif +#if defined(LTC_TEA) + " TEA\n" +#endif + "Stream ciphers built-in:\n" +#if defined(LTC_CHACHA) + " ChaCha\n" +#endif +#if defined(LTC_SALSA20) + " Salsa20\n" +#endif +#if defined(LTC_XSALSA20) + " XSalsa20\n" +#endif +#if defined(LTC_SOSEMANUK) + " Sosemanuk\n" +#endif +#if defined(LTC_RABBIT) + " Rabbit\n" +#endif +#if defined(LTC_RC4_STREAM) + " RC4\n" +#endif +#if defined(LTC_SOBER128_STREAM) + " SOBER128\n" +#endif + + "\nHashes built-in:\n" +#if defined(LTC_SHA3) + " SHA3\n" +#endif +#if defined(LTC_KECCAK) + " KECCAK\n" +#endif +#if defined(LTC_SHA512) + " SHA-512\n" +#endif +#if defined(LTC_SHA384) + " SHA-384\n" +#endif +#if defined(LTC_SHA512_256) + " SHA-512/256\n" +#endif +#if defined(LTC_SHA256) + " SHA-256\n" +#endif +#if defined(LTC_SHA512_224) + " SHA-512/224\n" +#endif +#if defined(LTC_SHA224) + " SHA-224\n" +#endif +#if defined(LTC_TIGER) + " TIGER\n" +#endif +#if defined(LTC_SHA1) + " SHA1\n" +#endif +#if defined(LTC_MD5) + " MD5\n" +#endif +#if defined(LTC_MD4) + " MD4\n" +#endif +#if defined(LTC_MD2) + " MD2\n" +#endif +#if defined(LTC_RIPEMD128) + " RIPEMD128\n" +#endif +#if defined(LTC_RIPEMD160) + " RIPEMD160\n" +#endif +#if defined(LTC_RIPEMD256) + " RIPEMD256\n" +#endif +#if defined(LTC_RIPEMD320) + " RIPEMD320\n" +#endif +#if defined(LTC_WHIRLPOOL) + " WHIRLPOOL\n" +#endif +#if defined(LTC_BLAKE2S) + " BLAKE2S\n" +#endif +#if defined(LTC_BLAKE2B) + " BLAKE2B\n" +#endif +#if defined(LTC_CHC_HASH) + " 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\n" +#endif +#if defined(LTC_LRW_MODE) + " LRW" +#if defined(LTC_LRW_TABLES) + " (tables) " +#endif + "\n" +#endif +#if defined(LTC_F8_MODE) + " F8\n" +#endif +#if defined(LTC_XTS_MODE) + " XTS\n" +#endif + + "\nMACs:\n" +#if defined(LTC_HMAC) + " HMAC\n" +#endif +#if defined(LTC_OMAC) + " OMAC\n" +#endif +#if defined(LTC_PMAC) + " PMAC\n" +#endif +#if defined(LTC_PELICAN) + " PELICAN\n" +#endif +#if defined(LTC_XCBC) + " XCBC\n" +#endif +#if defined(LTC_F9_MODE) + " F9\n" +#endif +#if defined(LTC_POLY1305) + " POLY1305\n" +#endif +#if defined(LTC_BLAKE2SMAC) + " BLAKE2S MAC\n" +#endif +#if defined(LTC_BLAKE2BMAC) + " BLAKE2B MAC\n" +#endif + + "\nENC + AUTH modes:\n" +#if defined(LTC_EAX_MODE) + " EAX\n" +#endif +#if defined(LTC_OCB_MODE) + " OCB\n" +#endif +#if defined(LTC_OCB3_MODE) + " OCB3\n" +#endif +#if defined(LTC_CCM_MODE) + " CCM\n" +#endif +#if defined(LTC_GCM_MODE) + " GCM" +#if defined(LTC_GCM_TABLES) + " (tables) " +#endif +#if defined(LTC_GCM_TABLES_SSE2) + " (SSE2) " +#endif + "\n" +#endif +#if defined(LTC_CHACHA20POLY1305_MODE) + " CHACHA20POLY1305\n" +#endif + + "\nPRNG:\n" +#if defined(LTC_YARROW) + " Yarrow ("NAME_VALUE(LTC_YARROW_AES)")\n" +#endif +#if defined(LTC_SPRNG) + " SPRNG\n" +#endif +#if defined(LTC_RC4) + " RC4\n" +#endif +#if defined(LTC_CHACHA20_PRNG) + " ChaCha20\n" +#endif +#if defined(LTC_FORTUNA) + " Fortuna (" NAME_VALUE(LTC_FORTUNA_POOLS) ", " +#if defined(LTC_FORTUNA_RESEED_RATELIMIT_TIMED) + "LTC_FORTUNA_RESEED_RATELIMIT_TIMED, " +#else + "LTC_FORTUNA_RESEED_RATELIMIT_STATIC, " NAME_VALUE(LTC_FORTUNA_WD) +#endif + ")\n" +#endif +#if defined(LTC_SOBER128) + " SOBER128\n" +#endif + + "\nPK Crypto:\n" +#if defined(LTC_MRSA) + " RSA" +#if defined(LTC_RSA_BLINDING) && defined(LTC_RSA_CRT_HARDENING) + " (with blinding and CRT hardening)" +#elif defined(LTC_RSA_BLINDING) + " (with blinding)" +#elif defined(LTC_RSA_CRT_HARDENING) + " (with CRT hardening)" +#endif + "\n" +#endif +#if defined(LTC_MDH) + " DH\n" +#endif +#if defined(LTC_MECC) + " ECC" +#if defined(LTC_ECC_TIMING_RESISTANT) + " (with blinding)" +#endif + "\n" +#endif +#if defined(LTC_MDSA) + " DSA\n" +#endif +#if defined(LTC_CURVE25519) +#if defined(LTC_CURVE25519) + " Ed25519\n" +#endif +#if defined(LTC_CURVE25519) + " X25519\n" +#endif +#endif +#if defined(LTC_PK_MAX_RETRIES) + " "NAME_VALUE(LTC_PK_MAX_RETRIES)"\n" +#endif + + "\nMPI (Math):\n" +#if defined(LTC_MPI) + " LTC_MPI\n" +#endif +#if defined(LTM_DESC) + " LTM_DESC\n" +#endif +#if defined(TFM_DESC) + " TFM_DESC\n" +#endif +#if defined(GMP_DESC) + " GMP_DESC\n" +#endif +#if defined(LTC_MILLER_RABIN_REPS) + " "NAME_VALUE(LTC_MILLER_RABIN_REPS)"\n" +#endif + + "\nCompiler:\n" +#if defined(_WIN64) + " WIN64 platform detected.\n" +#elif 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(__clang_version__) + " Clang compiler " __clang_version__ ".\n" +#elif defined(INTEL_CC) + " Intel C Compiler " __VERSION__ ".\n" +#elif defined(__GNUC__) /* clang and icc also define __GNUC__ */ + " GCC compiler " __VERSION__ ".\n" +#endif + +#if defined(__x86_64__) + " x86-64 detected.\n" +#endif +#if defined(LTC_PPC32) + " PPC32 detected.\n" +#endif + + "\nVarious others: " +#if defined(ARGTYPE) + " " NAME_VALUE(ARGTYPE) " " +#endif +#if defined(LTC_ADLER32) + " ADLER32 " +#endif +#if defined(LTC_BASE64) + " BASE64 " +#endif +#if defined(LTC_BASE64_URL) + " BASE64-URL-SAFE " +#endif +#if defined(LTC_BASE32) + " BASE32 " +#endif +#if defined(LTC_BASE16) + " BASE16 " +#endif +#if defined(LTC_BCRYPT) + " BCRYPT " + " " NAME_VALUE(LTC_BCRYPT_DEFAULT_ROUNDS) " " +#endif +#if defined(LTC_CRC32) + " CRC32 " +#endif +#if defined(LTC_DER) + " DER " + " " NAME_VALUE(LTC_DER_MAX_RECURSION) " " +#endif +#if defined(LTC_PKCS_1) + " PKCS#1 " +#endif +#if defined(LTC_PKCS_5) + " PKCS#5 " +#endif +#if defined(LTC_PKCS_8) + " PKCS#8 " +#endif +#if defined(LTC_PKCS_12) + " PKCS#12 " +#endif +#if defined(LTC_PADDING) + " PADDING " +#endif +#if defined(LTC_HKDF) + " HKDF " +#endif +#if defined(LTC_PBES) + " PBES1 " + " PBES2 " +#endif +#if defined(LTC_SSH) + " SSH " +#endif +#if defined(LTC_DEVRANDOM) + " LTC_DEVRANDOM " +#endif +#if defined(LTC_TRY_URANDOM_FIRST) + " LTC_TRY_URANDOM_FIRST " +#endif +#if defined(LTC_RNG_GET_BYTES) + " LTC_RNG_GET_BYTES " +#endif +#if defined(LTC_RNG_MAKE_PRNG) + " LTC_RNG_MAKE_PRNG " +#endif +#if defined(LTC_PRNG_ENABLE_LTC_RNG) + " LTC_PRNG_ENABLE_LTC_RNG " +#endif +#if defined(LTC_HASH_HELPERS) + " LTC_HASH_HELPERS " +#endif +#if defined(LTC_VALGRIND) + " LTC_VALGRIND " +#endif +#if defined(LTC_TEST) + " LTC_TEST " +#endif +#if defined(LTC_TEST_DBG) + " " NAME_VALUE(LTC_TEST_DBG) " " +#endif +#if defined(LTC_TEST_EXT) + " LTC_TEST_EXT " +#endif +#if defined(LTC_SMALL_CODE) + " LTC_SMALL_CODE " +#endif +#if defined(LTC_NO_FILE) + " LTC_NO_FILE " +#endif +#if defined(LTC_FILE_READ_BUFSIZE) + " " NAME_VALUE(LTC_FILE_READ_BUFSIZE) " " +#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_ROx_BUILTIN) + " LTC_ROx_BUILTIN " +#elif defined(LTC_ROx_ASM) + " LTC_ROx_ASM " +#if defined(LTC_NO_ROLC) + " LTC_NO_ROLC " +#endif +#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(LTC_EASY) + " LTC_EASY " +#endif +#if defined(LTC_MECC_ACCEL) + " LTC_MECC_ACCEL " +#endif +#if defined(LTC_MECC_FP) + " LTC_MECC_FP " +#endif +#if defined(LTC_ECC_SHAMIR) + " LTC_ECC_SHAMIR " +#endif +#if defined(LTC_CLOCK_GETTIME) + " LTC_CLOCK_GETTIME " +#endif + "\n" + ; + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c new file mode 100644 index 0000000..85b562a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c @@ -0,0 +1,17 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @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); + abort(); +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c new file mode 100644 index 0000000..777870f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c @@ -0,0 +1,13 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_cipher_descriptor.c + Stores the cipher descriptor table, Tom St Denis +*/ + +const struct ltc_cipher_descriptor *cipher_descriptor[TAB_SIZE]; + +LTC_MUTEX_GLOBAL(ltc_cipher_mutex) + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c new file mode 100644 index 0000000..ada1fbf --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] == NULL) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_INVALID_CIPHER; + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_OK; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c new file mode 100644 index 0000000..eac6dae --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c @@ -0,0 +1,290 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_constants.c + + Make various constants available to dynamic languages + like Python - Larry Bugbee, February 2013 + + LB - Dec 2013 - revised to include compiler define options + LB - Mar 2014 - added endianness and word size +*/ + +typedef struct { + const char *name; + const int value; +} crypt_constant; + +#define C_STRINGIFY(s) { #s, s } + +static const crypt_constant s_crypt_constants[] = { + + C_STRINGIFY(CRYPT_OK), + C_STRINGIFY(CRYPT_ERROR), + C_STRINGIFY(CRYPT_NOP), + C_STRINGIFY(CRYPT_INVALID_KEYSIZE), + C_STRINGIFY(CRYPT_INVALID_ROUNDS), + C_STRINGIFY(CRYPT_FAIL_TESTVECTOR), + C_STRINGIFY(CRYPT_BUFFER_OVERFLOW), + C_STRINGIFY(CRYPT_INVALID_PACKET), + C_STRINGIFY(CRYPT_INVALID_PRNGSIZE), + C_STRINGIFY(CRYPT_ERROR_READPRNG), + C_STRINGIFY(CRYPT_INVALID_CIPHER), + C_STRINGIFY(CRYPT_INVALID_HASH), + C_STRINGIFY(CRYPT_INVALID_PRNG), + C_STRINGIFY(CRYPT_MEM), + C_STRINGIFY(CRYPT_PK_TYPE_MISMATCH), + C_STRINGIFY(CRYPT_PK_NOT_PRIVATE), + C_STRINGIFY(CRYPT_INVALID_ARG), + C_STRINGIFY(CRYPT_FILE_NOTFOUND), + C_STRINGIFY(CRYPT_PK_INVALID_TYPE), + C_STRINGIFY(CRYPT_OVERFLOW), + C_STRINGIFY(CRYPT_PK_ASN1_ERROR), + C_STRINGIFY(CRYPT_INPUT_TOO_LONG), + C_STRINGIFY(CRYPT_PK_INVALID_SIZE), + C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE), + C_STRINGIFY(CRYPT_PK_INVALID_PADDING), + C_STRINGIFY(CRYPT_HASH_OVERFLOW), + + C_STRINGIFY(PK_PUBLIC), + C_STRINGIFY(PK_PRIVATE), + + C_STRINGIFY(LTC_ENCRYPT), + C_STRINGIFY(LTC_DECRYPT), + +#ifdef LTC_PKCS_1 + {"LTC_PKCS_1", 1}, + /* Block types */ + C_STRINGIFY(LTC_PKCS_1_EMSA), + C_STRINGIFY(LTC_PKCS_1_EME), + + /* Padding types */ + C_STRINGIFY(LTC_PKCS_1_V1_5), + C_STRINGIFY(LTC_PKCS_1_OAEP), + C_STRINGIFY(LTC_PKCS_1_PSS), + C_STRINGIFY(LTC_PKCS_1_V1_5_NA1), +#else + {"LTC_PKCS_1", 0}, +#endif + +#ifdef LTC_PADDING + {"LTC_PADDING", 1}, + + C_STRINGIFY(LTC_PAD_PKCS7), +#ifdef LTC_RNG_GET_BYTES + C_STRINGIFY(LTC_PAD_ISO_10126), +#endif + C_STRINGIFY(LTC_PAD_ANSI_X923), + C_STRINGIFY(LTC_PAD_ONE_AND_ZERO), + C_STRINGIFY(LTC_PAD_ZERO), + C_STRINGIFY(LTC_PAD_ZERO_ALWAYS), +#else + {"LTC_PADDING", 0}, +#endif + +#ifdef LTC_MRSA + {"LTC_MRSA", 1}, +#else + {"LTC_MRSA", 0}, +#endif + +#ifdef LTC_MECC + {"LTC_MECC", 1}, + C_STRINGIFY(ECC_BUF_SIZE), + C_STRINGIFY(ECC_MAXSIZE), +#else + {"LTC_MECC", 0}, +#endif + +#ifdef LTC_MDSA + {"LTC_MDSA", 1}, + C_STRINGIFY(LTC_MDSA_DELTA), + C_STRINGIFY(LTC_MDSA_MAX_GROUP), + C_STRINGIFY(LTC_MDSA_MAX_MODULUS), +#else + {"LTC_MDSA", 0}, +#endif + +#ifdef LTC_MILLER_RABIN_REPS + C_STRINGIFY(LTC_MILLER_RABIN_REPS), +#endif + +#ifdef LTC_DER +/* DER handling */ + {"LTC_DER", 1}, + C_STRINGIFY(LTC_ASN1_EOL), + C_STRINGIFY(LTC_ASN1_BOOLEAN), + C_STRINGIFY(LTC_ASN1_INTEGER), + C_STRINGIFY(LTC_ASN1_SHORT_INTEGER), + C_STRINGIFY(LTC_ASN1_BIT_STRING), + C_STRINGIFY(LTC_ASN1_OCTET_STRING), + C_STRINGIFY(LTC_ASN1_NULL), + C_STRINGIFY(LTC_ASN1_OBJECT_IDENTIFIER), + C_STRINGIFY(LTC_ASN1_IA5_STRING), + C_STRINGIFY(LTC_ASN1_PRINTABLE_STRING), + C_STRINGIFY(LTC_ASN1_UTF8_STRING), + C_STRINGIFY(LTC_ASN1_UTCTIME), + C_STRINGIFY(LTC_ASN1_CHOICE), + C_STRINGIFY(LTC_ASN1_SEQUENCE), + C_STRINGIFY(LTC_ASN1_SET), + C_STRINGIFY(LTC_ASN1_SETOF), + C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING), + C_STRINGIFY(LTC_ASN1_TELETEX_STRING), + C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME), + C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE), + C_STRINGIFY(LTC_DER_MAX_RECURSION), +#else + {"LTC_DER", 0}, +#endif + +#ifdef LTC_CTR_MODE + {"LTC_CTR_MODE", 1}, + C_STRINGIFY(CTR_COUNTER_LITTLE_ENDIAN), + C_STRINGIFY(CTR_COUNTER_BIG_ENDIAN), + C_STRINGIFY(LTC_CTR_RFC3686), +#else + {"LTC_CTR_MODE", 0}, +#endif +#ifdef LTC_GCM_MODE + C_STRINGIFY(LTC_GCM_MODE_IV), + C_STRINGIFY(LTC_GCM_MODE_AAD), + C_STRINGIFY(LTC_GCM_MODE_TEXT), +#endif + + C_STRINGIFY(LTC_MP_LT), + C_STRINGIFY(LTC_MP_EQ), + C_STRINGIFY(LTC_MP_GT), + + C_STRINGIFY(LTC_MP_NO), + C_STRINGIFY(LTC_MP_YES), + + C_STRINGIFY(MAXBLOCKSIZE), + C_STRINGIFY(TAB_SIZE), + C_STRINGIFY(ARGTYPE), + +#ifdef LTM_DESC + {"LTM_DESC", 1}, +#else + {"LTM_DESC", 0}, +#endif +#ifdef TFM_DESC + {"TFM_DESC", 1}, +#else + {"TFM_DESC", 0}, +#endif +#ifdef GMP_DESC + {"GMP_DESC", 1}, +#else + {"GMP_DESC", 0}, +#endif + +#ifdef LTC_FAST + {"LTC_FAST", 1}, +#else + {"LTC_FAST", 0}, +#endif + +#ifdef LTC_NO_FILE + {"LTC_NO_FILE", 1}, +#else + {"LTC_NO_FILE", 0}, +#endif + +#ifdef ENDIAN_LITTLE + {"ENDIAN_LITTLE", 1}, +#else + {"ENDIAN_LITTLE", 0}, +#endif + +#ifdef ENDIAN_BIG + {"ENDIAN_BIG", 1}, +#else + {"ENDIAN_BIG", 0}, +#endif + +#ifdef ENDIAN_32BITWORD + {"ENDIAN_32BITWORD", 1}, +#else + {"ENDIAN_32BITWORD", 0}, +#endif + +#ifdef ENDIAN_64BITWORD + {"ENDIAN_64BITWORD", 1}, +#else + {"ENDIAN_64BITWORD", 0}, +#endif + +#ifdef ENDIAN_NEUTRAL + {"ENDIAN_NEUTRAL", 1}, +#else + {"ENDIAN_NEUTRAL", 0}, +#endif +}; + + +/* crypt_get_constant() + * valueout will be the value of the named constant + * return -1 if named item not found + */ +int crypt_get_constant(const char* namein, int *valueout) { + int i; + int count = sizeof(s_crypt_constants) / sizeof(s_crypt_constants[0]); + for (i=0; i *names_list_size) { + return -1; + } + /* build the names list */ + ptr = names_list; + for (i=0; i total_len) return -1; + total_len -= number_len; + ptr += number_len; + } + /* to remove the trailing new-line */ + ptr -= 1; + *ptr = 0; + } + return 0; +} + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c new file mode 100644 index 0000000..d1ad352 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] != NULL && !XSTRCMP(cipher_descriptor[x]->name, name)) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c new file mode 100644 index 0000000..9a9925f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + + if(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] == 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; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c new file mode 100644 index 0000000..8907055 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 && cipher_descriptor[x] != NULL; x++) { + if (cipher_descriptor[x]->ID == ID) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c new file mode 100644 index 0000000..31866fb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] != NULL && XSTRCMP(hash_descriptor[x]->name, name) == 0) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c new file mode 100644 index 0000000..5f0e55c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] == 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; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c new file mode 100644 index 0000000..e960af0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] && hash_descriptor[x]->ID == ID) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c new file mode 100644 index 0000000..b764938 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] != 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; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c new file mode 100644 index 0000000..b221f9e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] != NULL) && XSTRCMP(prng_descriptor[x]->name, name) == 0) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return -1; +} + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c new file mode 100644 index 0000000..a23216d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c @@ -0,0 +1,46 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, ...) +{ + 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 (register_cipher(p) == -1) { + va_end(args); + return CRYPT_INVALID_CIPHER; + } + } + + while ((p = va_arg(args, void*)) != NULL) { + if (register_hash(p) == -1) { + va_end(args); + return CRYPT_INVALID_HASH; + } + } + + while ((p = va_arg(args, void*)) != NULL) { + if (register_prng(p) == -1) { + va_end(args); + return CRYPT_INVALID_PRNG; + } + } + + va_end(args); + return CRYPT_OK; +} + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c new file mode 100644 index 0000000..1a826c0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c @@ -0,0 +1,13 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_hash_descriptor.c + Stores the hash descriptor table, Tom St Denis +*/ + +const struct ltc_hash_descriptor *hash_descriptor[TAB_SIZE]; + +LTC_MUTEX_GLOBAL(ltc_hash_mutex) + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c new file mode 100644 index 0000000..d98f715 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] == NULL) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_INVALID_HASH; + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_OK; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c new file mode 100644 index 0000000..f7af2b8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c @@ -0,0 +1,81 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_inits.c + + Provide math library functions for dynamic languages + like Python - Larry Bugbee, February 2013 +*/ + + +#ifdef LTM_DESC +void init_LTM(void) +{ + ltc_mp = ltm_desc; +} +#endif + +#ifdef TFM_DESC +void init_TFM(void) +{ + ltc_mp = tfm_desc; +} +#endif + +#ifdef GMP_DESC +void init_GMP(void) +{ + ltc_mp = gmp_desc; +} +#endif + +int crypt_mp_init(const char* mpi) +{ + if (mpi == NULL) return CRYPT_ERROR; + switch (mpi[0]) { +#ifdef LTM_DESC + case 'l': + case 'L': + ltc_mp = ltm_desc; + return CRYPT_OK; +#endif +#ifdef TFM_DESC + case 't': + case 'T': + ltc_mp = tfm_desc; + return CRYPT_OK; +#endif +#ifdef GMP_DESC + case 'g': + case 'G': + ltc_mp = gmp_desc; + return CRYPT_OK; +#endif +#ifdef EXT_MATH_LIB + case 'e': + case 'E': + { + extern ltc_math_descriptor EXT_MATH_LIB; + ltc_mp = EXT_MATH_LIB; + } + +#if defined(LTC_TEST_DBG) +#define NAME_VALUE(s) #s"="NAME(s) +#define NAME(s) #s + printf("EXT_MATH_LIB = %s\n", NAME_VALUE(EXT_MATH_LIB)); +#undef NAME_VALUE +#undef NAME +#endif + + return CRYPT_OK; +#endif + default: +#if defined(LTC_TEST_DBG) + printf("Unknown/Invalid MPI provider: %s\n", mpi); +#endif + return CRYPT_ERROR; + } +} + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c new file mode 100644 index 0000000..760ba63 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c @@ -0,0 +1,6 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/* Initialize ltc_mp to nulls, to force allocation on all platforms, including macOS. */ +ltc_math_descriptor ltc_mp = { 0 }; diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c new file mode 100644 index 0000000..56ccb6c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c @@ -0,0 +1,12 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_prng_descriptor.c + Stores the PRNG descriptors, Tom St Denis +*/ +const struct ltc_prng_descriptor *prng_descriptor[TAB_SIZE]; + +LTC_MUTEX_GLOBAL(ltc_prng_mutex) + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c new file mode 100644 index 0000000..dea9cf6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] == NULL) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_INVALID_PRNG; + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_OK; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c new file mode 100644 index 0000000..49a456f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c @@ -0,0 +1,7 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PRNG_ENABLE_LTC_RNG +unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c new file mode 100644 index 0000000..bb2b873 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c @@ -0,0 +1,99 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file crypt_register_all_ciphers.c + + Steffen Jaeckel +*/ + +#define REGISTER_CIPHER(h) do {\ + LTC_ARGCHK(register_cipher(h) != -1); \ +} while(0) + +int register_all_ciphers(void) +{ +#ifdef LTC_RIJNDAEL +#ifdef ENCRYPT_ONLY + /* alternative would be + * register_cipher(&rijndael_enc_desc); + */ + REGISTER_CIPHER(&aes_enc_desc); +#else + /* alternative would be + * register_cipher(&rijndael_desc); + */ + REGISTER_CIPHER(&aes_desc); +#endif +#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_ANUBIS + REGISTER_CIPHER(&anubis_desc); +#endif +#ifdef LTC_KHAZAD + REGISTER_CIPHER(&khazad_desc); +#endif +#ifdef LTC_KSEED + REGISTER_CIPHER(&kseed_desc); +#endif +#ifdef LTC_KASUMI + REGISTER_CIPHER(&kasumi_desc); +#endif +#ifdef LTC_MULTI2 + REGISTER_CIPHER(&multi2_desc); +#endif +#ifdef LTC_CAMELLIA + REGISTER_CIPHER(&camellia_desc); +#endif +#ifdef LTC_IDEA + REGISTER_CIPHER(&idea_desc); +#endif +#ifdef LTC_SERPENT + REGISTER_CIPHER(&serpent_desc); +#endif +#ifdef LTC_TEA + REGISTER_CIPHER(&tea_desc); +#endif + return CRYPT_OK; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c new file mode 100644 index 0000000..68a64ae --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c @@ -0,0 +1,95 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file crypt_register_all_hashes.c + + Steffen Jaeckel +*/ + +#define REGISTER_HASH(h) do {\ + LTC_ARGCHK(register_hash(h) != -1); \ +} while(0) + +int register_all_hashes(void) +{ +#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_SHA512_224 + REGISTER_HASH(&sha512_224_desc); +#endif +#ifdef LTC_SHA512_256 + REGISTER_HASH(&sha512_256_desc); +#endif +#ifdef LTC_SHA3 + REGISTER_HASH(&sha3_224_desc); + REGISTER_HASH(&sha3_256_desc); + REGISTER_HASH(&sha3_384_desc); + REGISTER_HASH(&sha3_512_desc); +#endif +#ifdef LTC_KECCAK + REGISTER_HASH(&keccak_224_desc); + REGISTER_HASH(&keccak_256_desc); + REGISTER_HASH(&keccak_384_desc); + REGISTER_HASH(&keccak_512_desc); +#endif +#ifdef LTC_RIPEMD128 + REGISTER_HASH(&rmd128_desc); +#endif +#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_BLAKE2S + REGISTER_HASH(&blake2s_128_desc); + REGISTER_HASH(&blake2s_160_desc); + REGISTER_HASH(&blake2s_224_desc); + REGISTER_HASH(&blake2s_256_desc); +#endif +#ifdef LTC_BLAKE2S + REGISTER_HASH(&blake2b_160_desc); + REGISTER_HASH(&blake2b_256_desc); + REGISTER_HASH(&blake2b_384_desc); + REGISTER_HASH(&blake2b_512_desc); +#endif +#ifdef LTC_CHC_HASH + REGISTER_HASH(&chc_desc); + LTC_ARGCHK(chc_register(find_cipher_any("aes", 8, 16)) == CRYPT_OK); +#endif + return CRYPT_OK; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c new file mode 100644 index 0000000..4a2e2ef --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file crypt_register_all_prngs.c + + Steffen Jaeckel +*/ + +#define REGISTER_PRNG(h) do {\ + LTC_ARGCHK(register_prng(h) != -1); \ +} while(0) + +int register_all_prngs(void) +{ +#ifdef LTC_YARROW + REGISTER_PRNG(&yarrow_desc); +#endif +#ifdef LTC_FORTUNA + REGISTER_PRNG(&fortuna_desc); +#endif +#ifdef LTC_RC4 + REGISTER_PRNG(&rc4_desc); +#endif +#ifdef LTC_CHACHA20_PRNG + REGISTER_PRNG(&chacha20_prng_desc); +#endif +#ifdef LTC_SOBER128 + REGISTER_PRNG(&sober128_desc); +#endif +#ifdef LTC_SPRNG + REGISTER_PRNG(&sprng_desc); +#endif + + return CRYPT_OK; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c new file mode 100644 index 0000000..ee0439d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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] != 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] == NULL) { + cipher_descriptor[x] = cipher; + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c new file mode 100644 index 0000000..742985c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (hash_descriptor[x] == hash) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x] == NULL) { + hash_descriptor[x] = hash; + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c new file mode 100644 index 0000000..bcb0d26 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (prng_descriptor[x] == prng) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (prng_descriptor[x] == NULL) { + prng_descriptor[x] = prng; + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return -1; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c new file mode 100644 index 0000000..7545aa8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c @@ -0,0 +1,351 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_sizes.c + + Make various struct sizes available to dynamic languages + like Python - Larry Bugbee, February 2013 + + LB - Dec 2013 - revised to include compiler define options +*/ + + +typedef struct { + const char *name; + const unsigned int size; +} crypt_size; + +#define SZ_STRINGIFY_S(s) { #s, sizeof(struct s) } +#define SZ_STRINGIFY_T(s) { #s, sizeof(s) } + +static const crypt_size s_crypt_sizes[] = { + /* hash state sizes */ + SZ_STRINGIFY_S(ltc_hash_descriptor), + SZ_STRINGIFY_T(hash_state), +#ifdef LTC_CHC_HASH + SZ_STRINGIFY_S(chc_state), +#endif +#ifdef LTC_WHIRLPOOL + SZ_STRINGIFY_S(whirlpool_state), +#endif +#ifdef LTC_SHA3 + SZ_STRINGIFY_S(sha3_state), +#endif +#ifdef LTC_SHA512 + SZ_STRINGIFY_S(sha512_state), +#endif +#ifdef LTC_SHA256 + SZ_STRINGIFY_S(sha256_state), +#endif +#ifdef LTC_SHA1 + SZ_STRINGIFY_S(sha1_state), +#endif +#ifdef LTC_MD5 + SZ_STRINGIFY_S(md5_state), +#endif +#ifdef LTC_MD4 + SZ_STRINGIFY_S(md4_state), +#endif +#ifdef LTC_MD2 + SZ_STRINGIFY_S(md2_state), +#endif +#ifdef LTC_TIGER + SZ_STRINGIFY_S(tiger_state), +#endif +#ifdef LTC_RIPEMD128 + SZ_STRINGIFY_S(rmd128_state), +#endif +#ifdef LTC_RIPEMD160 + SZ_STRINGIFY_S(rmd160_state), +#endif +#ifdef LTC_RIPEMD256 + SZ_STRINGIFY_S(rmd256_state), +#endif +#ifdef LTC_RIPEMD320 + SZ_STRINGIFY_S(rmd320_state), +#endif +#ifdef LTC_BLAKE2S + SZ_STRINGIFY_S(blake2s_state), +#endif +#ifdef LTC_BLAKE2B + SZ_STRINGIFY_S(blake2b_state), +#endif + + /* block cipher key sizes */ + SZ_STRINGIFY_S(ltc_cipher_descriptor), + SZ_STRINGIFY_T(symmetric_key), +#ifdef LTC_ANUBIS + SZ_STRINGIFY_S(anubis_key), +#endif +#ifdef LTC_CAMELLIA + SZ_STRINGIFY_S(camellia_key), +#endif +#ifdef LTC_BLOWFISH + SZ_STRINGIFY_S(blowfish_key), +#endif +#ifdef LTC_CAST5 + SZ_STRINGIFY_S(cast5_key), +#endif +#ifdef LTC_DES + SZ_STRINGIFY_S(des_key), + SZ_STRINGIFY_S(des3_key), +#endif +#ifdef LTC_IDEA + SZ_STRINGIFY_S(idea_key), +#endif +#ifdef LTC_KASUMI + SZ_STRINGIFY_S(kasumi_key), +#endif +#ifdef LTC_KHAZAD + SZ_STRINGIFY_S(khazad_key), +#endif +#ifdef LTC_KSEED + SZ_STRINGIFY_S(kseed_key), +#endif +#ifdef LTC_MULTI2 + SZ_STRINGIFY_S(multi2_key), +#endif +#ifdef LTC_NOEKEON + SZ_STRINGIFY_S(noekeon_key), +#endif +#ifdef LTC_RC2 + SZ_STRINGIFY_S(rc2_key), +#endif +#ifdef LTC_RC5 + SZ_STRINGIFY_S(rc5_key), +#endif +#ifdef LTC_RC6 + SZ_STRINGIFY_S(rc6_key), +#endif +#ifdef LTC_SERPENT + SZ_STRINGIFY_S(serpent_key), +#endif +#ifdef LTC_SKIPJACK + SZ_STRINGIFY_S(skipjack_key), +#endif +#ifdef LTC_XTEA + SZ_STRINGIFY_S(xtea_key), +#endif +#ifdef LTC_RIJNDAEL + SZ_STRINGIFY_S(rijndael_key), +#endif +#ifdef LTC_SAFER + SZ_STRINGIFY_S(safer_key), +#endif +#ifdef LTC_SAFERP + SZ_STRINGIFY_S(saferp_key), +#endif +#ifdef LTC_TWOFISH + SZ_STRINGIFY_S(twofish_key), +#endif + + /* mode sizes */ +#ifdef LTC_ECB_MODE + SZ_STRINGIFY_T(symmetric_ECB), +#endif +#ifdef LTC_CFB_MODE + SZ_STRINGIFY_T(symmetric_CFB), +#endif +#ifdef LTC_OFB_MODE + SZ_STRINGIFY_T(symmetric_OFB), +#endif +#ifdef LTC_CBC_MODE + SZ_STRINGIFY_T(symmetric_CBC), +#endif +#ifdef LTC_CTR_MODE + SZ_STRINGIFY_T(symmetric_CTR), +#endif +#ifdef LTC_LRW_MODE + SZ_STRINGIFY_T(symmetric_LRW), +#endif +#ifdef LTC_F8_MODE + SZ_STRINGIFY_T(symmetric_F8), +#endif +#ifdef LTC_XTS_MODE + SZ_STRINGIFY_T(symmetric_xts), +#endif + + /* stream cipher sizes */ +#ifdef LTC_CHACHA + SZ_STRINGIFY_T(chacha_state), +#endif +#ifdef LTC_SALSA20 + SZ_STRINGIFY_T(salsa20_state), +#endif +#ifdef LTC_SOSEMANUK + SZ_STRINGIFY_T(sosemanuk_state), +#endif +#ifdef LTC_RABBIT + SZ_STRINGIFY_T(rabbit_state), +#endif +#ifdef LTC_RC4_STREAM + SZ_STRINGIFY_T(rc4_state), +#endif +#ifdef LTC_SOBER128_STREAM + SZ_STRINGIFY_T(sober128_state), +#endif + + /* MAC sizes -- no states for ccm, lrw */ +#ifdef LTC_HMAC + SZ_STRINGIFY_T(hmac_state), +#endif +#ifdef LTC_OMAC + SZ_STRINGIFY_T(omac_state), +#endif +#ifdef LTC_PMAC + SZ_STRINGIFY_T(pmac_state), +#endif +#ifdef LTC_POLY1305 + SZ_STRINGIFY_T(poly1305_state), +#endif +#ifdef LTC_EAX_MODE + SZ_STRINGIFY_T(eax_state), +#endif +#ifdef LTC_OCB_MODE + SZ_STRINGIFY_T(ocb_state), +#endif +#ifdef LTC_OCB3_MODE + SZ_STRINGIFY_T(ocb3_state), +#endif +#ifdef LTC_CCM_MODE + SZ_STRINGIFY_T(ccm_state), +#endif +#ifdef LTC_GCM_MODE + SZ_STRINGIFY_T(gcm_state), +#endif +#ifdef LTC_PELICAN + SZ_STRINGIFY_T(pelican_state), +#endif +#ifdef LTC_XCBC + SZ_STRINGIFY_T(xcbc_state), +#endif +#ifdef LTC_F9_MODE + SZ_STRINGIFY_T(f9_state), +#endif +#ifdef LTC_CHACHA20POLY1305_MODE + SZ_STRINGIFY_T(chacha20poly1305_state), +#endif + + /* asymmetric keys */ +#ifdef LTC_MRSA + SZ_STRINGIFY_T(rsa_key), +#endif +#ifdef LTC_MDSA + SZ_STRINGIFY_T(dsa_key), +#endif +#ifdef LTC_MDH + SZ_STRINGIFY_T(dh_key), +#endif +#ifdef LTC_MECC + SZ_STRINGIFY_T(ltc_ecc_curve), + SZ_STRINGIFY_T(ecc_point), + SZ_STRINGIFY_T(ecc_key), +#endif + + /* DER handling */ +#ifdef LTC_DER + SZ_STRINGIFY_T(ltc_asn1_list), /* a list entry */ + SZ_STRINGIFY_T(ltc_utctime), + SZ_STRINGIFY_T(ltc_generalizedtime), +#endif + + /* prng state sizes */ + SZ_STRINGIFY_S(ltc_prng_descriptor), + SZ_STRINGIFY_T(prng_state), +#ifdef LTC_FORTUNA + SZ_STRINGIFY_S(fortuna_prng), +#endif +#ifdef LTC_CHACHA20_PRNG + SZ_STRINGIFY_S(chacha20_prng), +#endif +#ifdef LTC_RC4 + SZ_STRINGIFY_S(rc4_prng), +#endif +#ifdef LTC_SOBER128 + SZ_STRINGIFY_S(sober128_prng), +#endif +#ifdef LTC_YARROW + SZ_STRINGIFY_S(yarrow_prng), +#endif + /* sprng has no state as it uses other potentially available sources */ + /* like /dev/random. See Developers Guide for more info. */ + +#ifdef LTC_ADLER32 + SZ_STRINGIFY_T(adler32_state), +#endif +#ifdef LTC_CRC32 + SZ_STRINGIFY_T(crc32_state), +#endif + + SZ_STRINGIFY_T(ltc_mp_digit), + SZ_STRINGIFY_T(ltc_math_descriptor) + +}; + +/* crypt_get_size() + * sizeout will be the size (bytes) of the named struct or union + * return -1 if named item not found + */ +int crypt_get_size(const char* namein, unsigned int *sizeout) { + int i; + int count = sizeof(s_crypt_sizes) / sizeof(s_crypt_sizes[0]); + for (i=0; i *names_list_size) { + return -1; + } + /* build the names list */ + ptr = names_list; + for (i=0; i total_len) return -1; + total_len -= number_len; + ptr += number_len; + } + /* to remove the trailing new-line */ + ptr -= 1; + *ptr = 0; + } + return 0; +} + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c new file mode 100644 index 0000000..f63a355 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (cipher_descriptor[x] == cipher) { + cipher_descriptor[x] = NULL; + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_ERROR; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c new file mode 100644 index 0000000..c82d296 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (hash_descriptor[x] == hash) { + hash_descriptor[x] = NULL; + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_ERROR; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c new file mode 100644 index 0000000..ece0630 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (prng_descriptor[x] == prng) { + prng_descriptor[x] = NULL; + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_ERROR; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/misc/crypt/sub.mk new file mode 100644 index 0000000..9880a9b --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/misc/error_to_string.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/error_to_string.c new file mode 100644 index 0000000..5afac84 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/error_to_string.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file error_to_string.c + Convert error codes to ASCII strings, Tom St Denis +*/ + +static const char * const err_2_str[] = +{ + "CRYPT_OK", + "CRYPT_ERROR", + "Non-fatal 'no-operation' requested.", + + "Invalid key size.", + "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.", + + "An overflow of a value was detected/prevented.", + + "An ASN.1 decoding error occurred.", + + "The input was longer than expected.", + + "Invalid sized parameter.", + + "Invalid size for prime.", + + "Invalid padding.", + + "Hash applied to too many bits.", +}; + +/** + 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."; + } + return err_2_str[err]; +} + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf.c new file mode 100644 index 0000000..eb79b9c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf.c @@ -0,0 +1,135 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include +#include +#include + +#include "tomcrypt_private.h" + +#ifdef LTC_HKDF + +/* This is mostly just a wrapper around hmac_memory */ +int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + /* libtomcrypt chokes on a zero length HMAC key, so we need to check for + that. HMAC specifies that keys shorter than the hash's blocksize are + 0 padded to the block size. HKDF specifies that a NULL salt is to be + substituted with a salt comprised of hashLen 0 bytes. HMAC's padding + means that in either case the HMAC is actually using a blocksize long + zero filled key. Unless blocksize < hashLen (which wouldn't make any + sense), we can use a single 0 byte as the HMAC key and still generate + valid results for HKDF. */ + if (salt == NULL || saltlen == 0) { + return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen); + } + return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen); +} + +int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen) +{ + unsigned long hashsize; + int err; + unsigned char N; + unsigned long Noutlen, outoff; + + unsigned char *T, *dat; + unsigned long Tlen, datlen; + + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hashsize = hash_descriptor[hash_idx]->hashsize; + + /* RFC5869 parameter restrictions */ + if (inlen < hashsize || outlen > hashsize * 255) { + return CRYPT_INVALID_ARG; + } + if (info == NULL && infolen != 0) { + return CRYPT_INVALID_ARG; + } + LTC_ARGCHK(out != NULL); + + Tlen = hashsize + infolen + 1; + T = XMALLOC(Tlen); /* Replace with static buffer? */ + if (T == NULL) { + return CRYPT_MEM; + } + if (info != NULL) { + XMEMCPY(T + hashsize, info, infolen); + } + + /* HMAC data T(1) doesn't include a previous hash value */ + dat = T + hashsize; + datlen = Tlen - hashsize; + + N = 0; + outoff = 0; /* offset in out to write to */ + while (1) { /* an exit condition breaks mid-loop */ + Noutlen = MIN(hashsize, outlen - outoff); + T[Tlen - 1] = ++N; + if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen, + out + outoff, &Noutlen)) != CRYPT_OK) { + zeromem(T, Tlen); + XFREE(T); + return err; + } + outoff += Noutlen; + + if (outoff >= outlen) { /* loop exit condition */ + break; + } + + /* All subsequent HMAC data T(N) DOES include the previous hash value */ + XMEMCPY(T, out + hashsize * (N-1), hashsize); + if (N == 1) { + dat = T; + datlen = Tlen; + } + } + zeromem(T, Tlen); + XFREE(T); + return CRYPT_OK; +} + +/* all in one step */ +int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen) +{ + unsigned long hashsize; + int err; + unsigned char *extracted; + + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hashsize = hash_descriptor[hash_idx]->hashsize; + + extracted = XMALLOC(hashsize); /* replace with static buffer? */ + if (extracted == NULL) { + return CRYPT_MEM; + } + if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) { + zeromem(extracted, hashsize); + XFREE(extracted); + return err; + } + err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen); + zeromem(extracted, hashsize); + XFREE(extracted); + return err; +} +#endif /* LTC_HKDF */ + + +/* vim: set ts=2 sw=2 et ai si: */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf_test.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf_test.c new file mode 100644 index 0000000..99a970c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/hkdf/hkdf_test.c @@ -0,0 +1,284 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hkdf_test.c + LTC_HKDF support, self-test, Steffen Jaeckel +*/ + +#ifdef LTC_HKDF + +/* + TEST CASES SOURCE: + +Internet Engineering Task Force (IETF) H. Krawczyk +Request for Comments: 5869 IBM Research +Category: Informational P. Eronen +ISSN: 2070-1721 Nokia + May 2010 +Appendix A. Test Vectors +*/ + +/** + LTC_HKDF self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int hkdf_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + unsigned char OKM[82]; + int i; + + static const struct hkdf_test_case { + int num; + const char* Hash; + unsigned char IKM[80]; + unsigned long IKM_l; + unsigned char salt[80]; + unsigned long salt_l; + unsigned char info[80]; + unsigned long info_l; + unsigned char PRK[32]; + unsigned long PRK_l; + unsigned char OKM[82]; + unsigned long OKM_l; + } cases[] = { +#ifdef LTC_SHA256 + /* + Basic test case with SHA-256 + + Hash = SHA-256 + IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets) + salt = 0x000102030405060708090a0b0c (13 octets) + info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets) + L = 42 + + PRK = 0x077709362c2e32df0ddc3f0dc47bba63 + 90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets) + OKM = 0x3cb25f25faacd57a90434f64d0362f2a + 2d2d0a90cf1a5a4c5db02d56ecc4c5bf + 34007208d5b887185865 (42 octets) + */ + {1, "sha256", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, + {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9}, 10, + {0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, + 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, + 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, + 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, 32, + {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, + 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, + 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, + 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, + 0x58, 0x65}, 42}, +#ifdef LTC_TEST_EXT + /* Test with SHA-256 and longer inputs/outputs */ + {2, "sha256", + {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}, 80, + {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}, 80, + {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}, 80, + {0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, + 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, + 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, + 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44}, 32, + {0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, + 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, + 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, + 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, + 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, + 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, + 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, + 0x1d, 0x87}, 82}, + /* Test with SHA-256 and zero length salt/info */ + {3, "sha256", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0}, 0, + {0}, 0, + {0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, + 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, + 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, + 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}, 32, + {0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, + 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, + 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, + 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, + 0x96, 0xc8}, 42}, +#endif /* LTC_TEST_EXT */ +#endif /* LTC_SHA256 */ +#ifdef LTC_SHA1 + /* Basic test case with SHA-1 */ + {4, "sha1", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b}, 11, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, + {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9}, 10, + {0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, + 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, + 0xaa, 0x2b, 0xa2, 0x43}, 20, + {0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, + 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, + 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, + 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, + 0xf8, 0x96}, 42}, +#ifdef LTC_TEST_EXT + /* Test with SHA-1 and longer inputs/outputs */ + {5, "sha1", + {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}, 80, + {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}, 80, + {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}, 80, + {0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, + 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, + 0x22, 0x4c, 0xfa, 0xf6}, 20, + {0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, + 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, + 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, + 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, + 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, + 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, + 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, + 0xd3, 0xb4}, 82}, + /* Test with SHA-1 and zero-length salt/info */ + {6, "sha1", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0}, 0, + {0}, 0, + {0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, + 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, + 0xa0, 0xd3, 0x2d, 0x01}, 20, + {0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, + 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, + 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, + 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, + 0x49, 0x18}, 42}, + /* Test with SHA-1, salt not provided (defaults to HashLen zero octets), + zero-length info */ + {7, "sha1", + {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 22, + {0}, 0, /* pass a null pointer */ + {0}, 0, + {0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, + 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, + 0x73, 0x13, 0x85, 0xdd}, 20, + {0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, + 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, + 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, + 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, + 0xfc, 0x48}, 42}, +#endif /* LTC_TEST_EXT */ +#endif /* LTC_SHA1 */ + }; + + int err; + int tested=0,failed=0; + for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { + int hash = find_hash(cases[i].Hash); + if (hash == -1) continue; + ++tested; + if((err = hkdf(hash, cases[i].salt, cases[i].salt_l, + cases[i].info, cases[i].info_l, + cases[i].IKM, cases[i].IKM_l, + OKM, cases[i].OKM_l)) != CRYPT_OK) { +#if defined(LTC_TEST_DBG) && (LTC_TEST_DBG > 1) + printf("LTC_HKDF-%s test #%d, %s\n", cases[i].Hash, i, error_to_string(err)); +#endif + return err; + } + + if(compare_testvector(OKM, cases[i].OKM_l, cases[i].OKM, (size_t)cases[i].OKM_l, "HKDF", cases[i].num)) { + failed++; + } + } + + if (failed != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + if (tested == 0) { + return CRYPT_NOP; + } + return CRYPT_OK; + #endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/mem_neq.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/mem_neq.c new file mode 100644 index 0000000..8078a0a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/mem_neq.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mem_neq.c + Compare two blocks of memory for inequality in constant time. + Steffen Jaeckel +*/ + +/** + Compare two blocks of memory for inequality in constant time. + + The usage is similar to that of standard memcmp, but you can only test + if the memory is equal or not - you can not determine by how much the + first different byte differs. + + This function shall be used to compare results of cryptographic + operations where inequality means most likely usage of a wrong key. + The execution time has therefore to be constant as otherwise + timing attacks could be possible. + + @param a The first memory region + @param b The second memory region + @param len The length of the area to compare (octets) + + @return 0 when a and b are equal for len bytes, 1 they are not equal. +*/ +int mem_neq(const void *a, const void *b, size_t len) +{ + unsigned char ret = 0; + const unsigned char* pa; + const unsigned char* pb; + + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + + pa = a; + pb = b; + + while (len-- > 0) { + ret |= *pa ^ *pb; + ++pa; + ++pb; + } + + ret |= ret >> 4; + ret |= ret >> 2; + ret |= ret >> 1; + ret &= 1; + + return ret; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_depad.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_depad.c new file mode 100644 index 0000000..e3f7151 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_depad.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PADDING + +/** + Remove padding from your data + + This depads your data. + + @param data The data to depad + @param length [in/out] The size of the data before/after (removing padding) + @param mode One of the LTC_PAD_xx flags + @return CRYPT_OK on success +*/ +int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode) +{ + unsigned long padded_length, unpadded_length, n; + unsigned char pad; + enum padding_type type; + + LTC_ARGCHK(data != NULL); + LTC_ARGCHK(length != NULL); + + padded_length = *length; + + type = mode & LTC_PAD_MASK; + + if (type < LTC_PAD_ONE_AND_ZERO) { + pad = data[padded_length - 1]; + + if (pad > padded_length || pad == 0) return CRYPT_INVALID_ARG; + + unpadded_length = padded_length - pad; + } else { + /* init pad to calm old compilers */ + pad = 0x0; + unpadded_length = padded_length; + } + + switch (type) { + case LTC_PAD_ANSI_X923: + pad = 0x0; + /* FALLTHROUGH */ + case LTC_PAD_PKCS7: + for (n = unpadded_length; n < padded_length - 1; ++n) { + if (data[n] != pad) return CRYPT_INVALID_PACKET; + } + break; +#ifdef LTC_RNG_GET_BYTES + case LTC_PAD_ISO_10126: + /* nop */ + break; +#endif + case LTC_PAD_SSH: + pad = 0x1; + for (n = unpadded_length; n < padded_length; ++n) { + if (data[n] != pad++) return CRYPT_INVALID_PACKET; + } + break; + case LTC_PAD_ONE_AND_ZERO: + while (unpadded_length > 0 && data[unpadded_length - 1] != 0x80) { + if (data[unpadded_length - 1] != 0x0) return CRYPT_INVALID_PACKET; + unpadded_length--; + } + if (unpadded_length == 0) return CRYPT_INVALID_PACKET; + unpadded_length--; + if (data[unpadded_length] != 0x80) return CRYPT_INVALID_PACKET; + break; + case LTC_PAD_ZERO: + case LTC_PAD_ZERO_ALWAYS: + while (unpadded_length > 0 && data[unpadded_length - 1] == 0x0) { + unpadded_length--; + } + if (type == LTC_PAD_ZERO_ALWAYS) { + if (unpadded_length == padded_length) return CRYPT_INVALID_PACKET; + if (data[unpadded_length] != 0x0) return CRYPT_INVALID_PACKET; + } + break; + default: + return CRYPT_INVALID_ARG; + } + + *length = unpadded_length; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_pad.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_pad.c new file mode 100644 index 0000000..7d8bbba --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/padding/padding_pad.c @@ -0,0 +1,151 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PADDING + +/** + Determine the to-be-padded length. + + @param length [in/out] The size of the data before/after padding + @param mode Mask of (LTC_PAD_xxx | block_length) + @return CRYPT_OK on success +*/ +static int s_padding_padded_length(unsigned long *length, unsigned long mode) +{ + enum padding_type padding; + unsigned char pad, block_length, r, t; + + LTC_ARGCHK(length != NULL); + + block_length = mode & 0xff; + padding = mode & LTC_PAD_MASK; + r = *length % block_length; + + switch (padding) { + case LTC_PAD_ZERO: + if (r == 0) { + t = 0; + break; + } + /* FALLTHROUGH */ + case LTC_PAD_PKCS7: + case LTC_PAD_ONE_AND_ZERO: + case LTC_PAD_ZERO_ALWAYS: + case LTC_PAD_SSH: + t = 1; + break; +#ifdef LTC_RNG_GET_BYTES + case LTC_PAD_ISO_10126: + do { + if (rng_get_bytes(&t, sizeof(t), NULL) != sizeof(t)) { + return CRYPT_ERROR_READPRNG; + } + t %= (256 / block_length); + } while (t == 0); + break; +#endif + case LTC_PAD_ANSI_X923: + if (block_length != 16) { + return CRYPT_INVALID_ARG; + } + t = 1; + break; + default: + return CRYPT_INVALID_ARG; + } + + pad = (t * block_length) - r; + + if ((pad == 0) && (padding != LTC_PAD_ZERO)) { + pad = block_length; + } + + *length += pad; + + return CRYPT_OK; +} + +/** + Add padding to data. + + This pads your data. + + @param data The data to depad + @param length The size of the data before padding + @param padded_length [in/out] The size of the data available/after padding + @param mode One of the LTC_PAD_xx flags + @return CRYPT_OK on success +*/ +int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode) +{ + unsigned long l, n; + enum padding_type type; + int err; + unsigned char diff, pad; + + LTC_ARGCHK(data != NULL); + LTC_ARGCHK(padded_length != NULL); + + l = length; + if ((err = s_padding_padded_length(&l, mode)) != CRYPT_OK) { + return err; + } + + type = mode & LTC_PAD_MASK; + + if (*padded_length < l) { +#ifdef LTC_RNG_GET_BYTES + if (type != LTC_PAD_ISO_10126) { + *padded_length = l; + } else { + *padded_length = length + 256; + } +#else + *padded_length = l; +#endif + return CRYPT_BUFFER_OVERFLOW; + } + + if (l - length > 255) return CRYPT_INVALID_ARG; + diff = (unsigned char)(l - length); + + switch (type) { + case LTC_PAD_PKCS7: + XMEMSET(&data[length], diff, diff); + break; +#ifdef LTC_RNG_GET_BYTES + case LTC_PAD_ISO_10126: + if (rng_get_bytes(&data[length], diff-1u, NULL) != diff-1u) { + return CRYPT_ERROR_READPRNG; + } + data[l-1] = diff; + break; +#endif + case LTC_PAD_ANSI_X923: + XMEMSET(&data[length], 0, diff-1); + data[l-1] = diff; + break; + case LTC_PAD_SSH: + pad = 0x1; + for (n = length; n < l; ++n) { + data[n] = pad++; + } + break; + case LTC_PAD_ONE_AND_ZERO: + XMEMSET(&data[length + 1], 0, diff); + data[length] = 0x80; + break; + case LTC_PAD_ZERO: + case LTC_PAD_ZERO_ALWAYS: + XMEMSET(&data[length], 0, diff); + break; + default: + return CRYPT_INVALID_ARG; + } + *padded_length = l; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes.c new file mode 100644 index 0000000..f332623 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PBES + +/** + Decrypt Data encrypted via either PBES1 or PBES2 + + @param arg The according PBES parameters + @param dec_data [out] The decrypted data + @param dec_size [in/out] The length of the encrypted resp. decrypted data + @return CRYPT_OK on success +*/ +int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size) +{ + int err, hid, cid; + unsigned char k[32], *iv; + unsigned long klen, keylen, dlen; + long diff; + symmetric_CBC cbc; + + LTC_ARGCHK(arg != NULL); + LTC_ARGCHK(arg->type.kdf != NULL); + LTC_ARGCHK(dec_data != NULL); + LTC_ARGCHK(dec_size != NULL); + + hid = find_hash(arg->type.h); + if (hid == -1) return CRYPT_INVALID_HASH; + cid = find_cipher(arg->type.c); + if (cid == -1) return CRYPT_INVALID_CIPHER; + + klen = arg->type.keylen; + + /* RC2 special case */ + if (arg->key_bits != 0) { + /* We can't handle odd lengths of Key Bits */ + if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE; + /* Internally we use bytes, not bits */ + klen = arg->key_bits / 8; + } + keylen = klen; + + if (arg->iv != NULL) { + iv = arg->iv->data; + } else { + iv = k + klen; + klen += arg->type.blocklen; + } + + if (klen > sizeof(k)) return CRYPT_INVALID_ARG; + + if ((err = arg->type.kdf(arg->pwd, arg->pwdlen, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR; + if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR; + if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR; + if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR; + dlen = arg->enc_data->size; + if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR; + diff = (long)arg->enc_data->size - (long)dlen; + if ((diff <= 0) || (diff > cipher_descriptor[cid]->block_length)) { + err = CRYPT_PK_INVALID_PADDING; + goto LBL_ERROR; + } + *dec_size = dlen; + return CRYPT_OK; + +LBL_ERROR: + zeromem(k, sizeof(k)); + zeromem(dec_data, *dec_size); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes1.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes1.c new file mode 100644 index 0000000..f33a009 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes1.c @@ -0,0 +1,117 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PBES + +static int s_pkcs_5_alg1_wrap(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) +{ + LTC_UNUSED_PARAM(salt_len); + return pkcs_5_alg1(password, password_len, salt, iteration_count, hash_idx, out, outlen); +} + +static int s_pkcs_12_wrap(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; + /* convert password to unicode/utf16-be */ + unsigned long pwlen = password_len * 2; + unsigned char* pw; + if (*outlen < 32) return CRYPT_INVALID_ARG; + pw = XMALLOC(pwlen + 2); + if (pw == NULL) return CRYPT_MEM; + if ((err = pkcs12_utf8_to_utf16(password, password_len, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR; + pw[pwlen++] = 0; + pw[pwlen++] = 0; + /* derive KEY */ + if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR; + /* derive IV */ + if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR; + + *outlen = 32; +LBL_ERROR: + zeromem(pw, pwlen); + XFREE(pw); + return err; +} + +static const pbes_properties s_pbes1_types[] = { + { s_pkcs_5_alg1_wrap, "md2", "des", 8, 8 }, + { s_pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 }, + { s_pkcs_5_alg1_wrap, "md5", "des", 8, 8 }, + { s_pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 }, + { s_pkcs_5_alg1_wrap, "sha1", "des", 8, 8 }, + { s_pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 }, + { s_pkcs_12_wrap, "sha1", "3des", 24, 8 }, +}; + +typedef struct { + const pbes_properties *data; + const char *oid; +} oid_to_pbes; + +static const oid_to_pbes s_pbes1_list[] = { + { &s_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */ + { &s_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */ + { &s_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */ + { &s_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */ + { &s_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */ + { &s_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */ + { &s_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */ + { 0 }, +}; + +static int s_pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res) +{ + unsigned int i; + for (i = 0; s_pbes1_list[i].data != NULL; ++i) { + if (pk_oid_cmp_with_asn1(s_pbes1_list[i].oid, oid) == CRYPT_OK) { + if (res != NULL) *res = *s_pbes1_list[i].data; + return CRYPT_OK; + } + } + return CRYPT_INVALID_ARG; +} + +/** + Extract PBES1 parameters + + @param s The start of the sequence with potential PBES1 parameters + @param res Pointer to where the extracted parameters should be stored + @return CRYPT_OK on success +*/ +int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res) +{ + int err; + + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(res != NULL); + + if ((err = s_pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err; + + if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) || + !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) { + return CRYPT_INVALID_PACKET; + } + /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC: + * 0:d=0 hl=4 l= 329 cons: SEQUENCE + * 4:d=1 hl=2 l= 27 cons: SEQUENCE + * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s) + * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam) + * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt) + * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations) + * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) + */ + res->salt = s->next->child; + res->iterations = mp_get_int(s->next->child->next->data); + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes2.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes2.c new file mode 100644 index 0000000..3378cd6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/pbes2.c @@ -0,0 +1,198 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PBES + +static const char * const s_oid_pbes2 = "1.2.840.113549.1.5.13"; +static const char * const s_oid_pbkdf2 = "1.2.840.113549.1.5.12"; + +typedef struct { + const char *oid; + const char *id; +} oid_id_st; + +static const oid_id_st s_hmac_oid_names[] = { + { "1.2.840.113549.2.7", "sha1" }, + { "1.2.840.113549.2.8", "sha224" }, + { "1.2.840.113549.2.9", "sha256" }, + { "1.2.840.113549.2.10", "sha384" }, + { "1.2.840.113549.2.11", "sha512" }, + { "1.2.840.113549.2.12", "sha512-224" }, + { "1.2.840.113549.2.13", "sha512-256" }, +}; + +static const pbes_properties s_pbes2_default_types[] = { + { pkcs_5_alg2, "sha1", "des", 8, 0 }, + { pkcs_5_alg2, "sha1", "rc2", 4, 0 }, + { pkcs_5_alg2, "sha1", "3des", 24, 0 }, + { pkcs_5_alg2, "sha1", "aes", 16, 0 }, + { pkcs_5_alg2, "sha1", "aes", 24, 0 }, + { pkcs_5_alg2, "sha1", "aes", 32, 0 }, +}; + +typedef struct { + const pbes_properties *data; + const char* oid; +} oid_to_pbes; + +static const oid_to_pbes s_pbes2_list[] = { + { &s_pbes2_default_types[0], "1.3.14.3.2.7" }, /* http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */ + { &s_pbes2_default_types[1], "1.2.840.113549.3.2" }, /* http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */ + { &s_pbes2_default_types[2], "1.2.840.113549.3.7" }, /* http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */ + { &s_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2 aes128-CBC */ + { &s_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */ + { &s_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */ +}; + +static int s_pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res) +{ + unsigned int i; + for (i = 0; i < sizeof(s_pbes2_list)/sizeof(s_pbes2_list[0]); ++i) { + if (pk_oid_cmp_with_asn1(s_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) { + *res = *s_pbes2_list[i].data; + break; + } + } + if (res->c == NULL) return CRYPT_INVALID_CIPHER; + if (hmac_oid != NULL) { + for (i = 0; i < sizeof(s_hmac_oid_names)/sizeof(s_hmac_oid_names[0]); ++i) { + if (pk_oid_cmp_with_asn1(s_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) { + res->h = s_hmac_oid_names[i].id; + return CRYPT_OK; + } + } + return CRYPT_INVALID_HASH; + } + return CRYPT_OK; +} + + +/** + Extract PBES2 parameters + + @param s The start of the sequence with potential PBES2 parameters + @param res Pointer to where the extracted parameters should be stored + @return CRYPT_OK on success +*/ +int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res) +{ + unsigned long klen; + ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac; + int err; + + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(res != NULL); + + if ((err = pk_oid_cmp_with_asn1(s_oid_pbes2, s)) != CRYPT_OK) return err; + + if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) || + !LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) { + return CRYPT_INVALID_PACKET; + } + /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc: + * 0:d=0 hl=4 l= 380 cons: SEQUENCE + * 4:d=1 hl=2 l= 78 cons: SEQUENCE + * 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13) (== *s) + * 17:d=2 hl=2 l= 65 cons: SEQUENCE + * 19:d=3 hl=2 l= 41 cons: SEQUENCE + * 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2 (== *lkdf) + * 32:d=4 hl=2 l= 28 cons: SEQUENCE + * 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt) + * 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== res->iterations, *liter) + * 48:d=5 hl=2 l= 12 cons: SEQUENCE (== *loptseq - this sequence is optional, may be missing) + * 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256 (== *lhmac) + * 60:d=6 hl=2 l= 0 prim: NULL + * 62:d=3 hl=2 l= 20 cons: SEQUENCE + * 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc (== *lenc) + * 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A + * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) + */ + lkdf = s->next->child->child; + lenc = s->next->child->next->child; + + if ((err = pk_oid_cmp_with_asn1(s_oid_pbkdf2, lkdf)) != CRYPT_OK) return err; + + if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) || + !LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) { + return CRYPT_INVALID_PACKET; + } + + liter = lkdf->next->child->next; + loptseq = liter->next; + res->salt = lkdf->next->child; + res->iterations = mp_get_int(liter->data); + + /* There's an optional INTEGER keyLength after the iterations, skip that if it's there. + * c.f. RFC 2898 A.2 PBKDF2 */ + if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) { + loptseq = loptseq->next; + } + + /* this sequence is optional */ + lhmac = NULL; + if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) && + LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) { + lhmac = loptseq->child; + } + if ((err = s_pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err; + + if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) { + /* 'NON-RC2'-CBC */ + res->iv = lenc->next; + } else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) { + /* RC2-CBC is a bit special ... + * + * RC2-CBC-Parameter ::= SEQUENCE { + * rc2ParameterVersion INTEGER OPTIONAL, + * iv OCTET STRING (SIZE(8)) } + */ + if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) && + LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) { + klen = mp_get_int(lenc->next->child->data); + res->iv = lenc->next->child->next; + /* + * Effective Key Bits Encoding + * 40 160 + * 64 120 + * 128 58 + * b >= 256 b + */ + switch (klen) { + case 160: + res->key_bits = 40; + break; + case 120: + res->key_bits = 64; + break; + case 58: + res->key_bits = 128; + break; + default: + /* We don't handle undefined Key Bits */ + if (klen < 256) return CRYPT_INVALID_KEYSIZE; + + res->key_bits = klen; + break; + } + } else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) { + res->iv = lenc->next->child; + /* + * If the rc2ParameterVersion field is omitted, the "effective key bits" + * defaults to 32. + */ + res->key_bits = 32; + } else { + return CRYPT_INVALID_PACKET; + } + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/sub.mk new file mode 100644 index 0000000..46557aa --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pbes/sub.mk @@ -0,0 +1,3 @@ +srcs-y += pbes.c +srcs-y += pbes1.c +srcs-y += pbes2.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c new file mode 100644 index 0000000..e278792 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_PKCS_12 + +int pkcs12_kdf( int hash_id, + const unsigned char *pw, unsigned long pwlen, + const unsigned char *salt, unsigned long saltlen, + unsigned int iterations, unsigned char purpose, + unsigned char *out, unsigned long outlen) +{ + unsigned long u = hash_descriptor[hash_id]->hashsize; + unsigned long v = hash_descriptor[hash_id]->blocksize; + unsigned long c = (outlen + u - 1) / u; + unsigned long Slen = ((saltlen + v - 1) / v) * v; + unsigned long Plen = ((pwlen + v - 1) / v) * v; + unsigned long k = (Plen + Slen) / v; + unsigned long Alen, keylen = 0; + unsigned int tmp, i, j, n; + unsigned char ch; + unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE]; + unsigned char *I, *key; + int err = CRYPT_ERROR; + + LTC_ARGCHK(pw != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + + key = XMALLOC(u * c); + I = XMALLOC(Plen + Slen); + if (key == NULL || I == NULL) goto DONE; + zeromem(key, u * c); + + for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */ + for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen]; + for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */ + + for (i = 0; i < c; i++) { + Alen = sizeof(A); + err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, LTC_NULL); /* A = HASH(D || I) */ + if (err != CRYPT_OK) goto DONE; + for (j = 1; j < iterations; j++) { + err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */ + if (err != CRYPT_OK) goto DONE; + } + /* fill buffer B with A */ + for (j = 0; j < v; j++) B[j] = A[j % Alen]; + /* B += 1 */ + for (j = v; j > 0; j--) { + if (++B[j - 1] != 0) break; + } + /* I_n += B */ + for (n = 0; n < k; n++) { + ch = 0; + for (j = v; j > 0; j--) { + tmp = I[n * v + j - 1] + B[j - 1] + ch; + ch = (unsigned char)((tmp >> 8) & 0xFF); + I[n * v + j - 1] = (unsigned char)(tmp & 0xFF); + } + } + /* store derived key block */ + XMEMCPY(&key[keylen], A, Alen); + keylen += Alen; + } + + XMEMCPY(out, key, outlen); + err = CRYPT_OK; +DONE: + if (I) { + zeromem(I, Plen + Slen); + XFREE(I); + } + if (key) { + zeromem(key, u * c); + XFREE(key); + } + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c new file mode 100644 index 0000000..b84fe93 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c @@ -0,0 +1,60 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_PKCS_12 + +int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) { + unsigned long len = 0; + const unsigned char* in_end = in + inlen; + const ulong32 offset[6] = { + 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL + }; + int err = CRYPT_ERROR; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + while (in < in_end) { + ulong32 ch = 0; + unsigned short extra = 0; /* 0 */ + if (*in >= 192) extra++; /* 1 */ + if (*in >= 224) extra++; /* 2 */ + if (*in >= 240) extra++; /* 3 */ + if (*in >= 248) extra++; /* 4 */ + if (*in >= 252) extra++; /* 5 */ + if (in + extra >= in_end) goto ERROR; + switch (extra) { + case 5: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 4: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 3: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 2: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 1: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 0: ch += *in++; + default: break; + } + ch -= offset[extra]; + if (ch > 0xFFFF) goto ERROR; + if (*outlen >= len + 2) { + out[len] = (unsigned short)((ch >> 8) & 0xFF); + out[len + 1] = (unsigned char)(ch & 0xFF); + } + len += 2; + } + + err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK; + *outlen = len; +ERROR: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/sub.mk new file mode 100644 index 0000000..92f782e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs12/sub.mk @@ -0,0 +1,2 @@ +srcs-y += pkcs12_kdf.c +srcs-y += pkcs12_utf8_to_utf16.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c new file mode 100644 index 0000000..a33c2a2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c @@ -0,0 +1,185 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_5_1.c + PKCS #5, Algorithm #1, Tom St Denis +*/ +#ifdef LTC_PKCS_5 +/** + Execute PKCS #5 v1 in strict or OpenSSL EVP_BytesToKey()-compat mode. + + PKCS#5 v1 specifies that the output key length can be no larger than + the hash output length. OpenSSL unilaterally extended that by repeating + the hash process on a block-by-block basis for as long as needed to make + bigger keys. If you want to be compatible with KDF for e.g. "openssl enc", + you'll want that. + + If you want strict PKCS behavior, turn openssl_compat off. Or (more + likely), use one of the convenience functions below. + + @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 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 + @param openssl_compat [in] Whether or not to grow the key to the buffer size ala OpenSSL + @return CRYPT_OK if successful +*/ +static int s_pkcs_5_alg1_common(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 openssl_compat) +{ + int err; + unsigned long x; + hash_state *md; + unsigned char *buf; + /* Storage vars in case we need to support > hashsize (OpenSSL compat) */ + unsigned long block = 0, iter; + /* How many bytes to put in the outbut buffer (convenience calc) */ + unsigned long outidx = 0, nb = 0; + + LTC_ARGCHK(password != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if (iteration_count <= 0) { + return CRYPT_INVALID_ARG; + } + + /* 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; + } + + while(block * hash_descriptor[hash_idx]->hashsize < *outlen) { + + /* hash initial (maybe previous hash) + password + salt */ + if ((err = hash_descriptor[hash_idx]->init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + /* in OpenSSL mode, we first hash the previous result for blocks 2-n */ + if (openssl_compat && block) { + if ((err = hash_descriptor[hash_idx]->process(md, buf, hash_descriptor[hash_idx]->hashsize)) != 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; + } + + iter = iteration_count; + while (--iter) { + /* code goes here. */ + x = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx]->hashsize, buf, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* limit the size of the copy to however many bytes we have left in + the output buffer (and how many bytes we have to copy) */ + outidx = block*hash_descriptor[hash_idx]->hashsize; + nb = hash_descriptor[hash_idx]->hashsize; + if(outidx+nb > *outlen) { + nb = *outlen - outidx; + } + if(nb > 0) { + XMEMCPY(out+outidx, buf, nb); + } + + block++; + if (!openssl_compat) { + break; + } + } + /* In strict mode, we always return the hashsize, in compat we filled it + as much as was requested, so we leave it alone. */ + if(!openssl_compat) { + *outlen = hash_descriptor[hash_idx]->hashsize; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, MAXBLOCKSIZE); + zeromem(md, sizeof(hash_state)); +#endif + + XFREE(buf); + XFREE(md); + + return err; +} + +/** + Execute PKCS #5 v1 - Strict mode (no OpenSSL-compatible extension) + @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 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) +{ + return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count, + hash_idx, out, outlen, 0); +} + +/** + Execute PKCS #5 v1 - OpenSSL-extension-compatible mode + + Use this one if you need to derive keys as "openssl enc" does by default. + OpenSSL (for better or worse), uses MD5 as the hash and iteration_count=1. + @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 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_openssl(const unsigned char *password, + unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count, + hash_idx, out, outlen, 1); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c new file mode 100644 index 0000000..61ebd00 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c @@ -0,0 +1,121 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_5_2.c + PKCS #5, Algorithm #2, Tom St Denis +*/ +#ifdef LTC_PKCS_5 + +/** + Execute 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 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); + + if (iteration_count <= 0) { + return CRYPT_INVALID_ARG; + } + + /* 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c new file mode 100644 index 0000000..73bc4a1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c @@ -0,0 +1,221 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hkdf_test.c + PKCS #5 support, self-test, Steffen Jaeckel +*/ + +#ifdef LTC_PKCS_5 + +/* + TEST CASES SOURCE: + +Internet Engineering Task Force (IETF) S. Josefsson +Request for Comments: 6070 SJD AB +Category: Informational January 2011 +ISSN: 2070-1721 +*/ + +/** + PKCS #5 self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int pkcs_5_test (void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + + typedef struct { + const char* P; + unsigned long P_len; + const char* S; + unsigned long S_len; + int c; + unsigned long dkLen; + unsigned char DK[40]; + } case_item; + + static const case_item cases_5_2[] = { + { + "password", + 8, + "salt", + 4, + 1, + 20, + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 } + }, + { + "password", + 8, + "salt", + 4, + 2, + 20, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 } + }, +#ifdef LTC_TEST_EXT + { + "password", + 8, + "salt", + 4, + 4096, + 20, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 } + }, + { + "password", + 8, + "salt", + 4, + 16777216, + 20, + { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, + 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, + 0x26, 0x34, 0xe9, 0x84 } + }, + { + "passwordPASSWORDpassword", + 25, + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 36, + 4096, + 25, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 } + }, + { + "pass\0word", + 9, + "sa\0lt", + 5, + 4096, + 16, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 } + }, +#endif /* LTC_TEST_EXT */ + }; + + static const case_item cases_5_1[] = { + { + "password", + 8, + "saltsalt", /* must be 8 octects */ + 8, /* ignored by alg1 */ + 1, + 20, + { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, + 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 } + }, + }; + + static const case_item cases_5_1o[] = { + { + "password", + 8, + "saltsalt", /* must be 8 octects */ + 8, /* ignored by alg1_openssl */ + 1, + 20, + { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, + 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 } + + }, + { + "password", + 8, + "saltsalt", /* must be 8 octects */ + 8, /* ignored by alg1_openssl */ + 1, + 30, + { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, + 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44, + 0xf0, 0xbf, 0xf4, 0xc1, 0x2c, 0xf3, 0x59, 0x6f, 0xc0, 0x0b } + + } + }; + + unsigned char DK[40]; + unsigned long dkLen; + int i, err; + int tested=0, failed=0; + int hash = find_hash("sha1"); + if (hash == -1) + { +#ifdef LTC_TEST_DBG + printf("PKCS#5 test failed: 'sha1' hash not found\n"); +#endif + return CRYPT_ERROR; + } + + /* testing alg 2 */ + for(i=0; i < (int)(sizeof(cases_5_2) / sizeof(cases_5_2[0])); i++) { + ++tested; + dkLen = cases_5_2[i].dkLen; + if((err = pkcs_5_alg2((unsigned char*)cases_5_2[i].P, cases_5_2[i].P_len, + (unsigned char*)cases_5_2[i].S, cases_5_2[i].S_len, + cases_5_2[i].c, hash, + DK, &dkLen)) != CRYPT_OK) { +#ifdef LTC_TEST_DBG + printf("\npkcs_5_alg2() #%d: Failed/1 (%s)\n", i, error_to_string(err)); +#endif + ++failed; + } + else if (compare_testvector(DK, dkLen, cases_5_2[i].DK, cases_5_2[i].dkLen, "PKCS#5_2", i)) { + ++failed; + } + } + + /* testing alg 1 */ + for(i=0; i < (int)(sizeof(cases_5_1) / sizeof(case_item)); i++, tested++) { + dkLen = cases_5_1[i].dkLen; + if((err = pkcs_5_alg1((unsigned char*)cases_5_1[i].P, cases_5_1[i].P_len, + (unsigned char*)cases_5_1[i].S, + cases_5_1[i].c, hash, + DK, &dkLen)) != CRYPT_OK) { +#ifdef LTC_TEST_DBG + printf("\npkcs_5_alg1() #%d: Failed/1 (%s)\n", i, error_to_string(err)); +#endif + ++failed; + } + else if (compare_testvector(DK, dkLen, cases_5_1[i].DK, cases_5_1[i].dkLen, "PKCS#5_1", i)) { + ++failed; + } + } + + /* testing alg 1_openssl */ + for(i = 0; i < (int)(sizeof(cases_5_1o) / sizeof(cases_5_1o[0])); i++, tested++) { + dkLen = cases_5_1o[i].dkLen; + if ((err = pkcs_5_alg1_openssl((unsigned char*)cases_5_1o[i].P, cases_5_1o[i].P_len, + (unsigned char*)cases_5_1o[i].S, + cases_5_1o[i].c, hash, + DK, &dkLen)) != CRYPT_OK) { +#ifdef LTC_TEST_DBG + printf("\npkcs_5_alg1_openssl() #%d: Failed/1 (%s)\n", i, error_to_string(err)); +#endif + ++failed; + } + else if (compare_testvector(DK, dkLen, cases_5_1o[i].DK, cases_5_1o[i].dkLen, "PKCS#5_1o", i)) { + ++failed; + } + } + + return (failed != 0) ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK; + #endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk new file mode 100644 index 0000000..7f8ccfe --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c new file mode 100644 index 0000000..ff6fe3c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c @@ -0,0 +1,167 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file ssh_decode_sequence_multi.c + SSH data type representation as per RFC4251, Russ Williams +*/ + +#ifdef LTC_SSH + +/** + Decode a SSH sequence using a VA list + @param in The input buffer + @param inlen [in/out] The length of the input buffer and on output the amount of decoded data + @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long*) + @return CRYPT_OK on success +*/ +int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) +{ + int err; + va_list args; + ssh_data_type type; + void *vdata; + unsigned char *cdata; + char *sdata; + ulong32 *u32data; + ulong64 *u64data; + unsigned long *bufsize; + ulong32 size; + unsigned long remaining; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + + remaining = *inlen; + /* Decode values from buffer */ + va_start(args, inlen); + while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { + /* Size of length field */ + if (type == LTC_SSHDATA_STRING || + type == LTC_SSHDATA_NAMELIST || + type == LTC_SSHDATA_MPINT) + { + /* Check we'll not read too far */ + if (remaining < 4) { + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + } + + /* Calculate (or read) length of data */ + size = 0xFFFFFFFFU; + switch (type) { + case LTC_SSHDATA_BYTE: + case LTC_SSHDATA_BOOLEAN: + size = 1; + break; + case LTC_SSHDATA_UINT32: + size = 4; + break; + case LTC_SSHDATA_UINT64: + size = 8; + break; + case LTC_SSHDATA_STRING: + case LTC_SSHDATA_NAMELIST: + case LTC_SSHDATA_MPINT: + LOAD32H(size, in); + in += 4; + remaining -= 4; + break; + + case LTC_SSHDATA_EOL: + default: + /* Should never get here */ + err = CRYPT_INVALID_ARG; + goto error; + } + + /* Check we'll not read too far */ + if (remaining < size) { + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } else { + remaining -= size; + } + + vdata = va_arg(args, void*); + if (vdata == NULL) { + err = CRYPT_INVALID_ARG; + goto error; + } + + /* Read data */ + switch (type) { + case LTC_SSHDATA_BYTE: + cdata = vdata; + *cdata = *in++; + break; + case LTC_SSHDATA_BOOLEAN: + cdata = vdata; + /* + The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be + interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1. + */ + *cdata = (*in++)?1:0; + break; + case LTC_SSHDATA_UINT32: + u32data = vdata; + LOAD32H(*u32data, in); + in += 4; + break; + case LTC_SSHDATA_UINT64: + u64data = vdata; + LOAD64H(*u64data, in); + in += 8; + break; + case LTC_SSHDATA_STRING: + case LTC_SSHDATA_NAMELIST: + sdata = vdata; + bufsize = va_arg(args, unsigned long*); + if (bufsize == NULL) { + err = CRYPT_INVALID_ARG; + goto error; + } + if (size + 1 >= *bufsize) { + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + if (size > 0) { + XMEMCPY(sdata, (const char *)in, size); + } + sdata[size] = '\0'; + *bufsize = size; + in += size; + break; + case LTC_SSHDATA_MPINT: + if (size == 0) { + if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; } + } else if ((in[0] & 0x80) != 0) { + /* Negative number - not supported */ + err = CRYPT_INVALID_PACKET; + goto error; + } else { + if ((err = mp_read_unsigned_bin(vdata, (unsigned char *)in, size)) != CRYPT_OK) { goto error; } + } + in += size; + break; + + case LTC_SSHDATA_EOL: + default: + /* Should never get here */ + err = CRYPT_INVALID_ARG; + goto error; + } + } + err = CRYPT_OK; + + *inlen -= remaining; + +error: + va_end(args); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c new file mode 100644 index 0000000..c65402c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c @@ -0,0 +1,160 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file ssh_encode_sequence_multi.c + SSH data type representation as per RFC4251, Russ Williams +*/ + +#ifdef LTC_SSH + +/** + Encode a SSH sequence 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, ) except for string&name-list (int, void*, unsigned long) + @return CRYPT_OK on success +*/ +int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) +{ + int err; + va_list args; + ulong32 size; + ssh_data_type type; + void *vdata; + const char *sdata; + int idata; + ulong32 u32data; + ulong64 u64data; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* Check values and calculate output size */ + size = 0; + va_start(args, outlen); + while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { + switch (type) { + case LTC_SSHDATA_BYTE: + case LTC_SSHDATA_BOOLEAN: /* Both stored as 1 byte */ + LTC_UNUSED_PARAM( va_arg(args, int) ); + size++; + break; + case LTC_SSHDATA_UINT32: + LTC_UNUSED_PARAM( va_arg(args, ulong32) ); + size += 4; + break; + case LTC_SSHDATA_UINT64: + LTC_UNUSED_PARAM( va_arg(args, ulong64) ); + size += 8; + break; + case LTC_SSHDATA_STRING: + case LTC_SSHDATA_NAMELIST: + LTC_UNUSED_PARAM( va_arg(args, char*) ); + size += va_arg(args, unsigned long); + size += 4; + break; + case LTC_SSHDATA_MPINT: + vdata = va_arg(args, void*); + /* Calculate size */ + size += 4; + if (mp_iszero(vdata) != LTC_MP_YES) { + size += mp_unsigned_bin_size(vdata); + if ((mp_count_bits(vdata) & 7) == 0) size++; /* Zero padding if high bit set */ + } + break; + + case LTC_SSHDATA_EOL: /* Should never get here */ + default: + err = CRYPT_INVALID_ARG; + goto error; + } + } + va_end(args); + + /* Check we have sufficient space */ + if (*outlen < size) { + *outlen = size; + err = CRYPT_BUFFER_OVERFLOW; + goto errornoargs; + } + *outlen = size; + + /* Encode values into buffer */ + va_start(args, outlen); + while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { + switch (type) { + case LTC_SSHDATA_BYTE: + idata = va_arg(args, int); + + *out++ = (unsigned char)(idata & 255); + break; + case LTC_SSHDATA_BOOLEAN: + idata = va_arg(args, int); + + /* + The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be + interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1. + */ + *out++ = (idata)?1:0; + break; + case LTC_SSHDATA_UINT32: + u32data = va_arg(args, ulong32); + STORE32H(u32data, out); + out += 4; + break; + case LTC_SSHDATA_UINT64: + u64data = va_arg(args, ulong64); + STORE64H(u64data, out); + out += 8; + break; + case LTC_SSHDATA_STRING: + case LTC_SSHDATA_NAMELIST: + sdata = va_arg(args, char*); + size = va_arg(args, unsigned long); + STORE32H(size, out); + out += 4; + XMEMCPY(out, sdata, size); + out += size; + break; + case LTC_SSHDATA_MPINT: + vdata = va_arg(args, void*); + if (mp_iszero(vdata) == LTC_MP_YES) { + STORE32H(0, out); + out += 4; + } else { + size = mp_unsigned_bin_size(vdata); + if ((mp_count_bits(vdata) & 7) == 0) { + /* Zero padding if high bit set */ + STORE32H(size+1, out); + out += 4; + *out++ = 0; + } else { + STORE32H(size, out); + out += 4; + } + if ((err = mp_to_unsigned_bin(vdata, out)) != CRYPT_OK) { + err = CRYPT_ERROR; + goto error; + } + out += size; + } + break; + + case LTC_SSHDATA_EOL: /* Should never get here */ + default: + err = CRYPT_INVALID_ARG; + goto error; + } + } + err = CRYPT_OK; + +error: + va_end(args); +errornoargs: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/sub.mk new file mode 100644 index 0000000..b10fb7c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/ssh/sub.mk @@ -0,0 +1,2 @@ +srcs-y += ssh_decode_sequence_multi.c +srcs-y += ssh_encode_sequence_multi.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/misc/sub.mk new file mode 100644 index 0000000..fc55c8e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/sub.mk @@ -0,0 +1,9 @@ +srcs-y += burn_stack.c +srcs-y += error_to_string.c +srcs-y += mem_neq.c +srcs-y += zeromem.c +subdirs-y += base64 +subdirs-y += crypt +subdirs-y += pkcs5 +subdirs-y += pkcs12 +subdirs-y += ssh diff --git a/optee/optee_os/core/lib/libtomcrypt/src/misc/zeromem.c b/optee/optee_os/core/lib/libtomcrypt/src/misc/zeromem.c new file mode 100644 index 0000000..8bb64ec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/misc/zeromem.c @@ -0,0 +1,20 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @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(volatile void *out, size_t outlen) +{ + LTC_ARGCHKVD(out != NULL); + memzero_explicit((void *)out, outlen); +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c new file mode 100644 index 0000000..4a7517a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c @@ -0,0 +1,84 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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) || cbc->blocklen > (int)sizeof(tmp)) { + 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); + } + 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_PTR_CAST((unsigned char *)cbc->IV + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)tmp + x)); + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); + *(LTC_FAST_TYPE_PTR_CAST((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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c new file mode 100644 index 0000000..2b842f0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c new file mode 100644 index 0000000..86e1481 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c @@ -0,0 +1,85 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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); + } + while (len) { + /* xor IV against plaintext */ +#if defined(LTC_FAST) + for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((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_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c new file mode 100644 index 0000000..7af2cf1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cbc_getiv.c + CBC implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CBC_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param cbc The CBC state + @return CRYPT_OK if successful +*/ +int cbc_getiv(unsigned char *IV, unsigned long *len, const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c new file mode 100644 index 0000000..a9e91c3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cbc_setiv.c + CBC implementation, set IV, Tom St Denis +*/ + + +#ifdef LTC_CBC_MODE + +/** + Set an initialization vector + @param IV The initialization 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c new file mode 100644 index 0000000..c0cec09 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c @@ -0,0 +1,50 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 initialization 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/cbc/sub.mk new file mode 100644 index 0000000..1ce3e77 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c new file mode 100644 index 0000000..ff735e3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c @@ -0,0 +1,55 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c new file mode 100644 index 0000000..28fe514 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c new file mode 100644 index 0000000..b03b036 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c new file mode 100644 index 0000000..9dc2e86 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cfb_getiv.c + CFB implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param cfb The CFB state + @return CRYPT_OK if successful +*/ +int cfb_getiv(unsigned char *IV, unsigned long *len, const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c new file mode 100644 index 0000000..04306f5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cfb_setiv.c + CFB implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + Set an initialization vector + @param IV The initialization 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c new file mode 100644 index 0000000..fd924e0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 initialization 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/cfb/sub.mk new file mode 100644 index 0000000..7a92b01 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c new file mode 100644 index 0000000..a55a08f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c new file mode 100644 index 0000000..3dbea53 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c new file mode 100644 index 0000000..5ef6915 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c @@ -0,0 +1,140 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_encrypt.c + CTR implementation, encrypt data, Tom St Denis +*/ + + +#ifdef LTC_CTR_MODE + +static void s_ctr_increment_counter(symmetric_CTR *ctr) +{ + int x; + + if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { + for (x = 0; x < ctr->ctrlen; x++) { + ctr->ctr[x] = (ctr->ctr[x] + 1) & 0xff; + if (ctr->ctr[x]) + return; + } + } else { + for (x = ctr->blocklen - 1; x >= ctr->ctrlen; x--) { + ctr->ctr[x] = (ctr->ctr[x] + 1) & 0xff; + if (ctr->ctr[x]) { + return; + } + } + } +} + +/** + CTR encrypt software implementation + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param ctr CTR state + @return CRYPT_OK if successful +*/ +static int s_ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) +{ + int err; + + while (len) { + /* is the pad empty? */ + if (ctr->padlen == ctr->blocklen) { + /* encrypt counter into pad */ + 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_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^ + *(LTC_FAST_TYPE_PTR_CAST((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; + + /* done with one full block? if so, set counter for next block. */ + if (ctr->padlen == ctr->blocklen) { + s_ctr_increment_counter(ctr); + } + } + return CRYPT_OK; +} + +/** + 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) +{ + unsigned long incr; + int 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 + + if (cipher_descriptor[ctr->cipher]->accel_ctr_encrypt != NULL ) { + /* handle acceleration only if not in the middle of a block, accelerator is present and length is >= a block size */ + if ((ctr->padlen == 0 || ctr->padlen == ctr->blocklen) && 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; + } + pt += (len / ctr->blocklen) * ctr->blocklen; + ct += (len / ctr->blocklen) * ctr->blocklen; + len %= ctr->blocklen; + /* counter was changed by accelerator so mark pad empty (will need updating in s_ctr_encrypt()) */ + ctr->padlen = ctr->blocklen; + } + + /* try to re-synchronize on a block boundary for maximum use of acceleration */ + incr = ctr->blocklen - ctr->padlen; + if (len >= incr + (unsigned long)ctr->blocklen) { + if ((err = s_ctr_encrypt(pt, ct, incr, ctr)) != CRYPT_OK) { + return err; + } + pt += incr; + ct += incr; + len -= incr; + return ctr_encrypt(pt, ct, len, ctr); + } + } + + return s_ctr_encrypt(pt, ct, len, ctr); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c new file mode 100644 index 0000000..05277fa --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_getiv.c + CTR implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param ctr The CTR state + @return CRYPT_OK if successful +*/ +int ctr_getiv(unsigned char *IV, unsigned long *len, const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c new file mode 100644 index 0000000..7bdccf2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_setiv.c + CTR implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** + Set an initialization vector + @param IV The initialization 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c new file mode 100644 index 0000000..df8117a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c @@ -0,0 +1,89 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 initialization 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c new file mode 100644 index 0000000..df7e649 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (compare_testvector(buf, tests[x].msglen, tests[x].ct, tests[x].msglen, "CTR", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/sub.mk new file mode 100644 index 0000000..1541501 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ctr/sub.mk @@ -0,0 +1,6 @@ +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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c new file mode 100644 index 0000000..1c73f59 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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); + } + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c new file mode 100644 index 0000000..56126ab --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c new file mode 100644 index 0000000..0ac8de6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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); + } + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c new file mode 100644 index 0000000..6d34409 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/ecb/sub.mk new file mode 100644 index 0000000..c47c061 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c new file mode 100644 index 0000000..f9e3a54 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_done.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_done.c new file mode 100644 index 0000000..0f501f8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c new file mode 100644 index 0000000..8a32ad6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c @@ -0,0 +1,91 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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_PTR_CAST(&ct[x])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])); + *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&f8->MIV[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c new file mode 100644 index 0000000..1a4e53f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_getiv.c + F8 implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param f8 The F8 state + @return CRYPT_OK if successful +*/ +int f8_getiv(unsigned char *IV, unsigned long *len, const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c new file mode 100644 index 0000000..45d2239 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f8_setiv.c + F8 implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + Set an initialization vector + @param IV The initialization 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_start.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_start.c new file mode 100644 index 0000000..f23c141 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_start.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 initialization 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c new file mode 100644 index 0000000..7b25175 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "f8", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/sub.mk new file mode 100644 index 0000000..32e1381 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/f8/sub.mk @@ -0,0 +1,6 @@ +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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c new file mode 100644 index 0000000..4e880a4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c new file mode 100644 index 0000000..d216528 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c new file mode 100644 index 0000000..e175911 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c new file mode 100644 index 0000000..9da1aab --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c new file mode 100644 index 0000000..4ee0b41 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c @@ -0,0 +1,109 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 LTC_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 LTC_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_PTR_CAST(lrw->pad + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][lrw->IV[x]][y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&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_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(pt + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(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_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(ct + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c new file mode 100644 index 0000000..a1a355a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 LTC_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 LTC_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_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c new file mode 100644 index 0000000..ec2cdc0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c @@ -0,0 +1,92 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 LTC_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 LTC_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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c new file mode 100644 index 0000000..3d9015b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c @@ -0,0 +1,124 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 (compare_testvector(tests[x].expected_tweak, 16, lrw.pad, 16, "LRW Tweak", x)) { + 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 (compare_testvector(buf[0], 16, tests[x].C, 16, "LRW Encrypt", x)) { + 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 (compare_testvector(buf[1], 16, tests[x].P, 16, "LRW Decrypt", x)) { + lrw_done(&lrw); + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = lrw_done(&lrw)) != CRYPT_OK) { + return err; + } + } + return CRYPT_OK; +#endif +} + +#endif + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/sub.mk new file mode 100644 index 0000000..b464c41 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/lrw/sub.mk @@ -0,0 +1,7 @@ +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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c new file mode 100644 index 0000000..cebcd7b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c new file mode 100644 index 0000000..1a728e6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c new file mode 100644 index 0000000..d07b570 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c new file mode 100644 index 0000000..0a799f0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_getiv.c + OFB implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param ofb The OFB state + @return CRYPT_OK if successful +*/ +int ofb_getiv(unsigned char *IV, unsigned long *len, const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c new file mode 100644 index 0000000..8fcb392 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_setiv.c + OFB implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + Set an initialization vector + @param IV The initialization 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c new file mode 100644 index 0000000..f0a0f04 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 initialization 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/ofb/sub.mk new file mode 100644 index 0000000..f1fceeb --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/modes/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/sub.mk new file mode 100644 index 0000000..45b14a8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/sub.mk @@ -0,0 +1,4 @@ +subdirs-$(_CFG_CORE_LTC_CBC) += cbc +subdirs-$(_CFG_CORE_LTC_CTR) += ctr +subdirs-$(_CFG_CORE_LTC_ECB) += ecb +subdirs-$(_CFG_CORE_LTC_XTS) += xts diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/sub.mk new file mode 100644 index 0000000..d8d9f18 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/sub.mk @@ -0,0 +1,5 @@ +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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c new file mode 100644 index 0000000..c3adf9c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c @@ -0,0 +1,146 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects + */ + +#ifdef LTC_XTS_MODE + +static int s_tweak_uncrypt(const unsigned char *C, unsigned char *P, unsigned char *T, const 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_PTR_CAST(&P[x])) = *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&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_PTR_CAST(&P[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&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, unsigned char *tweak, + const 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; + } + + if (mo == 0) { + lim = m; + } else { + lim = m - 1; + } + + if (cipher_descriptor[xts->cipher]->accel_xts_decrypt && lim > 0) { + + /* use accelerated decryption for whole blocks */ + if ((err = cipher_descriptor[xts->cipher]->accel_xts_decrypt(ct, pt, lim, tweak, &xts->key1, &xts->key2)) != + CRYPT_OK) { + return err; + } + ct += lim * 16; + pt += lim * 16; + + /* tweak is encrypted on output */ + XMEMCPY(T, tweak, sizeof(T)); + } else { + /* encrypt the tweak */ + if ((err = cipher_descriptor[xts->cipher]->ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < lim; i++) { + if ((err = s_tweak_uncrypt(ct, pt, T, xts)) != CRYPT_OK) { + return err; + } + 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 = s_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 = s_tweak_uncrypt(CC, pt, T, xts)) != CRYPT_OK) { + return err; + } + } + + /* Decrypt the tweak back */ + if ((err = cipher_descriptor[xts->cipher]->ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { + return err; + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_done.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_done.c new file mode 100644 index 0000000..66491fa --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_done.c @@ -0,0 +1,21 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c new file mode 100644 index 0000000..08acb45 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c @@ -0,0 +1,147 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects + */ + +#ifdef LTC_XTS_MODE + +static int s_tweak_crypt(const unsigned char *P, unsigned char *C, unsigned char *T, const 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_PTR_CAST(&C[x])) = *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&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_PTR_CAST(&C[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&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, unsigned char *tweak, + const 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; + } + + if (mo == 0) { + lim = m; + } else { + lim = m - 1; + } + + if (cipher_descriptor[xts->cipher]->accel_xts_encrypt && lim > 0) { + + /* use accelerated encryption for whole blocks */ + if ((err = cipher_descriptor[xts->cipher]->accel_xts_encrypt(pt, ct, lim, tweak, &xts->key1, &xts->key2)) != + CRYPT_OK) { + return err; + } + ct += lim * 16; + pt += lim * 16; + + /* tweak is encrypted on output */ + XMEMCPY(T, tweak, sizeof(T)); + } else { + + /* encrypt the tweak */ + if ((err = cipher_descriptor[xts->cipher]->ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < lim; i++) { + if ((err = s_tweak_crypt(pt, ct, T, xts)) != CRYPT_OK) { + return err; + } + ct += 16; + pt += 16; + } + } + + /* if ptlen not divide 16 then */ + if (mo > 0) { + /* CC = tweak encrypt block m-1 */ + if ((err = s_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 = s_tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) { + return err; + } + } + + /* Decrypt the tweak back */ + if ((err = cipher_descriptor[xts->cipher]->ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { + return err; + } + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_init.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_init.c new file mode 100644 index 0000000..224df32 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_init.c @@ -0,0 +1,51 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c new file mode 100644 index 0000000..20947a5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_test.c b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_test.c new file mode 100644 index 0000000..208853a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/modes/xts/xts_test.c @@ -0,0 +1,296 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_XTS_MODE + +#ifndef LTC_NO_TEST +static int s_xts_test_accel_xts_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long blocks, + unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) +{ + int ret; + symmetric_xts xts; + int (*orig)(const unsigned char *, unsigned char *, + unsigned long , unsigned char *, + const symmetric_key *, const symmetric_key *); + + /* AES can be under rijndael or aes... try to find it */ + if ((xts.cipher = find_cipher("aes")) == -1) { + if ((xts.cipher = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + orig = cipher_descriptor[xts.cipher]->accel_xts_encrypt; + cipher_descriptor[xts.cipher]->accel_xts_encrypt = NULL; + + XMEMCPY(&xts.key1, skey1, sizeof(symmetric_key)); + XMEMCPY(&xts.key2, skey2, sizeof(symmetric_key)); + + ret = xts_encrypt(pt, blocks << 4, ct, tweak, &xts); + cipher_descriptor[xts.cipher]->accel_xts_encrypt = orig; + + return ret; +} + +static int s_xts_test_accel_xts_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long blocks, + unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) +{ + int ret; + symmetric_xts xts; + int (*orig)(const unsigned char *, unsigned char *, + unsigned long , unsigned char *, + const symmetric_key *, const symmetric_key *); + + /* AES can be under rijndael or aes... try to find it */ + if ((xts.cipher = find_cipher("aes")) == -1) { + if ((xts.cipher = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + orig = cipher_descriptor[xts.cipher]->accel_xts_decrypt; + cipher_descriptor[xts.cipher]->accel_xts_decrypt = NULL; + + XMEMCPY(&xts.key1, skey1, sizeof(symmetric_key)); + XMEMCPY(&xts.key2, skey2, sizeof(symmetric_key)); + + ret = xts_decrypt(ct, blocks << 4, pt, tweak, &xts); + cipher_descriptor[xts.cipher]->accel_xts_decrypt = orig; + + return ret; +} +#endif + +/** + 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], Torg[16], T[16]; + ulong64 seq; + symmetric_xts xts; + int i, j, k, 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 (k = 0; k < 4; ++k) { + cipher_descriptor[idx]->accel_xts_encrypt = NULL; + cipher_descriptor[idx]->accel_xts_decrypt = NULL; + if (k & 0x1) { + cipher_descriptor[idx]->accel_xts_encrypt = s_xts_test_accel_xts_encrypt; + } + if (k & 0x2) { + cipher_descriptor[idx]->accel_xts_decrypt = s_xts_test_accel_xts_decrypt; + } + for (j = 0; j < 2; j++) { + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + /* skip the cases where + * the length is smaller than 2*blocklen + * or the length is not a multiple of 32 + */ + if ((j == 1) && ((tests[i].PTLEN < 32) || (tests[i].PTLEN % 32))) { + continue; + } + if ((k > 0) && (j == 1)) { + continue; + } + len = tests[i].PTLEN / 2; + + 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, Torg); + XMEMSET(Torg + 8, 0, 8); + + XMEMCPY(T, Torg, sizeof(T)); + if (j == 0) { + err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } else { + err = xts_encrypt(tests[i].PTX, len, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + err = xts_encrypt(&tests[i].PTX[len], len, &OUT[len], T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } + + if (compare_testvector(OUT, tests[i].PTLEN, tests[i].CTX, tests[i].PTLEN, "XTS encrypt", i)) { + xts_done(&xts); + return CRYPT_FAIL_TESTVECTOR; + } + + XMEMCPY(T, Torg, sizeof(T)); + if (j == 0) { + err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } else { + err = xts_decrypt(tests[i].CTX, len, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + err = xts_decrypt(&tests[i].CTX[len], len, &OUT[len], T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } + + if (compare_testvector(OUT, tests[i].PTLEN, tests[i].PTX, tests[i].PTLEN, "XTS decrypt", i)) { + xts_done(&xts); + return CRYPT_FAIL_TESTVECTOR; + } + xts_done(&xts); + } + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c new file mode 100644 index 0000000..83c915d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c @@ -0,0 +1,77 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + int err; + + 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 */ + y = inlen - 1; + if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) { + return err; + } + x += y; + /* is the data len too long or too short? */ + if ((dlen == 0) || (dlen > (inlen - x))) { + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c new file mode 100644 index 0000000..1bc74f6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c @@ -0,0 +1,84 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +#define SETBIT(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n)))) +#define CLRBIT(v, n) (v=((unsigned char)(v) & ~(1U << (unsigned char)(n)))) + +/** + 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 (8 per char) + @param outlen [in/out] The number of bits stored + @return CRYPT_OK if successful +*/ +int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long dlen, blen, x, y; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + 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 */ + y = inlen - 1; + if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) { + return err; + } + x += y; + /* is the data len too long or too short? */ + if ((dlen == 0) || (dlen > (inlen - x))) { + 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++) { + if (in[x] & (1 << (7 - (y & 7)))) { + SETBIT(out[y/8], 7-(y%8)); + } else { + CLRBIT(out[y/8], 7-(y%8)); + } + if ((y & 7) == 7) { + ++x; + } + } + + /* we done */ + *outlen = blen; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c new file mode 100644 index 0000000..0c2cd16 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + 7) >> 3) + 1; + + out[x++] = 0x03; + len = *outlen - x; + if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store number of zero padding bits */ + out[x++] = (unsigned char)((8 - inlen) & 7); + + /* 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c new file mode 100644 index 0000000..9cc23ae --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c @@ -0,0 +1,75 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +#define getbit(n, k) (((n) & ( 1 << (k) )) >> (k)) + +/** + Store a BIT STRING + @param in The array of bits to store (8 per char) + @param inlen The number of bits to store + @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_raw_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 + 7) >> 3) + 1; + + out[x++] = 0x03; + len = *outlen - x; + if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store number of zero padding bits */ + out[x++] = (unsigned char)((8 - inlen) & 7); + + /* store the bits in big endian format */ + for (y = buf = 0; y < inlen; y++) { + buf |= (getbit(in[y/8],7-y%8)?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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c new file mode 100644 index 0000000..4554a80 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, x; + int err; + + LTC_ARGCHK(outlen != NULL); + + /* get the number of the bytes */ + nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1; + + if ((err = der_length_asn1_length(nbytes, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + nbytes; + + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk new file mode 100644 index 0000000..4cf829e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk @@ -0,0 +1,5 @@ +srcs-y += der_decode_bit_string.c +srcs-y += der_encode_bit_string.c +srcs-y += der_length_bit_string.c +srcs-y += der_decode_raw_bit_string.c +srcs-y += der_encode_raw_bit_string.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c new file mode 100644 index 0000000..35ac7ec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c new file mode 100644 index 0000000..a77aefb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c new file mode 100644 index 0000000..f1b9e57 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk new file mode 100644 index 0000000..3761249 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c new file mode 100644 index 0000000..7ff7809 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c @@ -0,0 +1,222 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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_BOOLEAN: + if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) { + if (der_length_boolean(&z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + 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_RAW_BIT_STRING: + if (der_decode_raw_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_TELETEX_STRING: + if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_teletex_string(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_GENERALIZEDTIME: + z = *inlen; + if (der_decode_generalizedtime(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; + + case LTC_ASN1_CUSTOM_TYPE: + if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) { + if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + default: + return CRYPT_INVALID_ARG; + } + } + + return CRYPT_INVALID_PACKET; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk new file mode 100644 index 0000000..d3b95ec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk @@ -0,0 +1 @@ +srcs-y += der_decode_choice.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c new file mode 100644 index 0000000..59a98cc --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c @@ -0,0 +1,427 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @file der_decode_custom_type.c + ASN.1 DER, decode a Custom type, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Decode a Custom type + @param in The DER encoded input + @param inlen The size of the input + @param root The item that defines the custom type to decode + @return CRYPT_OK on success +*/ +int der_decode_custom_type(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root) +{ + LTC_ARGCHK(root != NULL); + return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED); +} + +/** + Extended-decode a Custom type + + This function is used to decode custom types and sequences/sets + For custom types root is used + For sequences/sets list and outlen are used + + @param in The DER encoded input + @param inlen The size of the input + @param root The item that defines the custom type to decode + @param list The list of items to decode + @param outlen The number of items in the list + @param flags c.f. enum ltc_der_seq + @return CRYPT_OK on success +*/ +int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root, + ltc_asn1_list *list, unsigned long outlen, + unsigned int flags) +{ + int err, seq_err, i, ordered; + ltc_asn1_type type; + ltc_asn1_list ident; + unsigned long size, x, y, z, blksize; + unsigned char* in_new = NULL; + void *data; + + LTC_ARGCHK(in != NULL); + + /* get blk size */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + x = 0; + + if (root == NULL) { + LTC_ARGCHK(list != NULL); + + /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */ + if (in[x] != 0x30 && in[x] != 0x31) { + return CRYPT_INVALID_PACKET; + } + ++x; + } else { + if (root->type != LTC_ASN1_CUSTOM_TYPE) { + return CRYPT_INVALID_PACKET; + } + + /* Alloc a copy of the data for primitive handling. */ + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + in_new = XMALLOC(inlen); + if (in_new == NULL) { + return CRYPT_MEM; + } + XMEMCPY(in_new, in, inlen); + in = in_new; + } + + y = inlen; + if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((ident.type != root->type) || + (ident.klass != root->klass) || + (ident.pc != root->pc) || + (ident.tag != root->tag)) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + x += y; + + list = root->data; + outlen = root->size; + } + + if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) { + if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) || + (der_asn1_type_to_identifier_map[root->used] == -1)) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + root->type = (ltc_asn1_type)root->used; + list = root; + outlen = 1; + + x -= 1; + in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type]; + blksize = inlen - x; + } else { + + y = inlen - x; + if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) { + goto LBL_ERR; + } + x += y; + } + + /* would this blksize overflow? */ + if (blksize > (inlen - x)) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* mark all as unused */ + for (i = 0; i < (int)outlen; i++) { + list[i].used = 0; + } + ordered = flags & LTC_DER_SEQ_ORDERED; + + /* ok read data */ + seq_err = CRYPT_OK; + blksize += x; + inlen -= x; + for (i = 0; i < (int)outlen; i++) { + z = 0; + type = list[i].type; + size = list[i].size; + data = list[i].data; + if (!ordered && list[i].used == 1) { continue; } + + if (type == LTC_ASN1_EOL) { + break; + } + + if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) { + err = CRYPT_PK_ASN1_ERROR; + goto LBL_ERR; + } + + switch (type) { + case LTC_ASN1_CUSTOM_TYPE: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + break; + default: + /* Verify that all basic types are indeed UNIVERSAL&PRIMITIVE */ + if (((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT) && (inlen > 0)) { + if (in[x] & 0xE0u) { + err = CRYPT_PK_ASN1_ERROR; + goto LBL_ERR; + } + } + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + z = inlen; + if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_boolean(&z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_INTEGER: + z = inlen; + if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_integer(data, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SHORT_INTEGER: + z = inlen; + if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) { + goto LBL_ERR; + } + + break; + + case LTC_ASN1_BIT_STRING: + z = inlen; + if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_RAW_BIT_STRING: + z = inlen; + if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_OCTET_STRING: + z = inlen; + if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_NULL: + if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) { + if (!ordered || list[i].optional) { continue; } + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + z = 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + z = inlen; + if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_TELETEX_STRING: + z = inlen; + if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_IA5_STRING: + z = inlen; + if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_PRINTABLE_STRING: + z = inlen; + if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTF8_STRING: + z = inlen; + if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTCTIME: + z = inlen; + if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + break; + + case LTC_ASN1_GENERALIZEDTIME: + z = inlen; + if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + break; + + case LTC_ASN1_SET: + z = inlen; + if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + /* detect if we have the right type */ + if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + z = inlen; + err = der_decode_sequence_ex(in + x, z, data, size, flags); + if (err == CRYPT_INPUT_TOO_LONG) { + seq_err = CRYPT_INPUT_TOO_LONG; + err = CRYPT_OK; + } + if (err != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CUSTOM_TYPE: + z = inlen; + err = der_decode_custom_type(in + x, z, &list[i]); + if (err == CRYPT_INPUT_TOO_LONG) { + seq_err = CRYPT_INPUT_TOO_LONG; + err = CRYPT_OK; + } + if (err != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CHOICE: + z = inlen; + if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + break; + + case LTC_ASN1_EOL: + 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 < (int)outlen; i++) { + if (list[i].used == 0 && list[i].optional == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } + + if (blksize == x && seq_err == CRYPT_OK && inlen == 0) { + /* everything decoded and no errors in nested sequences */ + err = CRYPT_OK; + } else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) { + /* a sequence reported too-long input, but now we've decoded everything */ + err = CRYPT_OK; + } else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) { + err = CRYPT_INVALID_PACKET; + } else { + err = CRYPT_INPUT_TOO_LONG; + } + +LBL_ERR: + if (in_new != NULL) { + XFREE(in_new); + } + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c new file mode 100644 index 0000000..f5cc93e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c @@ -0,0 +1,229 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @file der_encode_custom_type.c + ASN.1 DER, encode a Custom Type, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Encode a Custom Type + + This function is a bit special compared to the others, as it requires the + root-ltc_asn1_list where the type is defined. + + @param root The root of the list of items to encode + @param out [out] The destination + @param outlen [in/out] The size of the output + @return CRYPT_OK on success +*/ +int der_encode_custom_type(const ltc_asn1_list *root, + unsigned char *out, unsigned long *outlen) +{ + int err; + ltc_asn1_type type; + const ltc_asn1_list *list; + unsigned long size, x, y, z, i, inlen, id_len; + void *data; + + LTC_ARGCHK(root != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + y = 0; z = 0; + if ((err = der_length_custom_type(root, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG; + + /* too big ? */ + if (*outlen < y) { + *outlen = y; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* get length of the identifier, so we know the offset where to start writing */ + if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) return CRYPT_INVALID_ARG; + x = id_len; + + + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + list = root; + inlen = 1; + /* In case it's a PRIMITIVE type we encode directly to the output + * but leave space for a potentially longer identifier as it will + * simply be replaced afterwards. + */ + x -= 1; + } else { + list = root->data; + inlen = root->size; + /* store length, identifier will be added later */ + y = *outlen - x; + if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + x += y; + } + + /* store data */ + *outlen -= x; + for (i = 0; i < inlen; i++) { + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + type = (ltc_asn1_type)list[i].used; + } else { + type = list[i].type; + } + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + z = *outlen; + if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_INTEGER: + z = *outlen; + if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SHORT_INTEGER: + z = *outlen; + if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_BIT_STRING: + z = *outlen; + if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_RAW_BIT_STRING: + z = *outlen; + if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_OCTET_STRING: + z = *outlen; + if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_NULL: + out[x] = 0x05; + out[x+1] = 0x00; + z = 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + z = *outlen; + if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_IA5_STRING: + z = *outlen; + if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_PRINTABLE_STRING: + z = *outlen; + if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTF8_STRING: + z = *outlen; + if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTCTIME: + z = *outlen; + if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_GENERALIZEDTIME: + z = *outlen; + if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SET: + z = *outlen; + if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SETOF: + z = *outlen; + if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SEQUENCE: + z = *outlen; + if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CUSTOM_TYPE: + z = *outlen; + if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + + + x += z; + *outlen -= z; + } + + if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) { + goto LBL_ERR; + } + *outlen = x; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c new file mode 100644 index 0000000..958badf --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c @@ -0,0 +1,204 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_custom_type.c + ASN.1 DER, length of a custom type, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Get the length of a DER custom type + + This function is a bit special compared to the others, as it requires the + root-ltc_asn1_list where the type is defined. + + @param root The root of the struct to encode + @param outlen [out] The length required in octets to store it + @param payloadlen [out] The length of the payload in octets + @return CRYPT_OK on success +*/ +int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen) +{ + int err; + const ltc_asn1_list *list; + ltc_asn1_type type; + unsigned long size, x, y, i, inlen, id_len; + void *data; + + LTC_ARGCHK(root != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) { + return err; + } + y = id_len; + + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + list = root; + inlen = 1; + } else { + list = root->data; + inlen = root->size; + } + for (i = 0; i < inlen; i++) { + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + type = (ltc_asn1_type)list[i].used; + } else { + type = list[i].type; + } + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + /* some items may be optional during import */ + if (!list[i].used && list[i].optional) continue; + + switch (type) { + case LTC_ASN1_BOOLEAN: + if ((err = der_length_boolean(&x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_INTEGER: + if ((err = der_length_integer(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SHORT_INTEGER: + if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_RAW_BIT_STRING: + if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_OCTET_STRING: + if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_NULL: + y += 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_IA5_STRING: + if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_TELETEX_STRING: + if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_PRINTABLE_STRING: + if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_UTCTIME: + if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_GENERALIZEDTIME: + if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_UTF8_STRING: + if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_CUSTOM_TYPE: + if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + /* In case it's a PRIMITIVE element we're going + * to only replace the identifier of the one element + * by the custom identifier. + */ + y -= 1; + if (payloadlen != NULL) { + *payloadlen = y - id_len; + } + } else { + /* calc length of length */ + if ((err = der_length_asn1_length(y - id_len, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + if (payloadlen != NULL) { + *payloadlen = y - id_len; + } + y += x; + } + + /* store size */ + *outlen = y; + +LBL_ERR: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/sub.mk new file mode 100644 index 0000000..5ba17b7 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_decode_custom_type.c +srcs-y += der_encode_custom_type.c +srcs-y += der_length_custom_type.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c new file mode 100644 index 0000000..8f54f09 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c @@ -0,0 +1,157 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_asn1_maps.c + ASN.1 DER, a collection of maps to convert between different representations, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + A Map from ltc_asn1_type to the regularly used ASN.1 identifier +*/ +const int der_asn1_type_to_identifier_map[] = +{ + /* 0 */ + -1, /* LTC_ASN1_EOL, */ + 1, /* LTC_ASN1_BOOLEAN, */ + 2, /* LTC_ASN1_INTEGER, */ + 2, /* LTC_ASN1_SHORT_INTEGER, */ + 3, /* LTC_ASN1_BIT_STRING, */ + /* 5 */ + 4, /* LTC_ASN1_OCTET_STRING, */ + 5, /* LTC_ASN1_NULL, */ + 6, /* LTC_ASN1_OBJECT_IDENTIFIER, */ + 22, /* LTC_ASN1_IA5_STRING, */ + 19, /* LTC_ASN1_PRINTABLE_STRING, */ + /* 10 */ + 12, /* LTC_ASN1_UTF8_STRING, */ + 23, /* LTC_ASN1_UTCTIME, */ + -1, /* LTC_ASN1_CHOICE, */ + 48, /* LTC_ASN1_SEQUENCE, */ + 49, /* LTC_ASN1_SET, */ + /* 15 */ + 49, /* LTC_ASN1_SETOF, */ + 3, /* LTC_ASN1_RAW_BIT_STRING, */ + 20, /* LTC_ASN1_TELETEX_STRING, */ + 24, /* LTC_ASN1_GENERALIZEDTIME, */ + -1, /* LTC_ASN1_CUSTOM_TYPE, */ +}; +const unsigned long der_asn1_type_to_identifier_map_sz = sizeof(der_asn1_type_to_identifier_map)/sizeof(der_asn1_type_to_identifier_map[0]); + +/** + A Map from the ASN.1 Class to its string +*/ +const char* der_asn1_class_to_string_map[] = +{ + "UNIVERSAL", + "APPLICATION", + "CONTEXT-SPECIFIC", + "PRIVATE", +}; +const unsigned long der_asn1_class_to_string_map_sz = sizeof(der_asn1_class_to_string_map)/sizeof(der_asn1_class_to_string_map[0]); + +/** + A Map from the ASN.1 P/C-bit to its string +*/ +const char* der_asn1_pc_to_string_map[] = +{ + "PRIMITIVE", + "CONSTRUCTED", +}; +const unsigned long der_asn1_pc_to_string_map_sz = sizeof(der_asn1_pc_to_string_map)/sizeof(der_asn1_pc_to_string_map[0]); + +/** + A Map from the ASN.1 tag to its string +*/ +const char* der_asn1_tag_to_string_map[] = +{ + "Reserved for use by the encoding rules", + "Boolean type", + "Integer type", + "Bitstring type", + "Octetstring type", + "Null type", + "Object identifier type", + "Object descriptor type", + "External type and Instance-of type", + "Real type", + "Enumerated type", + "Embedded-pdv type", + "UTF8String type", + "Relative object identifier type", + "The time type", + "Reserved for future editions of this Recommendation | International Standard", + "Sequence and Sequence-of types", + "Set and Set-of types", + "NumericString type", + "PrintableString type", + "TeletexString (T61String) type", + "VideotexString type", + "IA5String type", + "UTCTime type", + "GeneralizedTime type", + "GraphicString type", + "VisibleString (ISO646String) type", + "GeneralString type", + "UniversalString type", + "UnrestrictedCharacterString type", + "BMPString type", + "Date type", + "TimeOfDay type", + "DateTime type", + "Duration type", + "OID internationalized resource identifier type", + "Relative OID internationalized resource identifier type", +}; +const unsigned long der_asn1_tag_to_string_map_sz = sizeof(der_asn1_tag_to_string_map)/sizeof(der_asn1_tag_to_string_map[0]); + +/** + A Map from ASN.1 Tags to ltc_asn1_type +*/ +const ltc_asn1_type der_asn1_tag_to_type_map[] = +{ + /* 0 */ + LTC_ASN1_EOL, /* Reserved for use by the encoding rules */ + LTC_ASN1_BOOLEAN, /* Boolean type */ + LTC_ASN1_INTEGER, /* Integer type */ + LTC_ASN1_BIT_STRING, /* Bitstring type */ + LTC_ASN1_OCTET_STRING, /* Octetstring type */ + /* 5 */ + LTC_ASN1_NULL, /* Null type */ + LTC_ASN1_OBJECT_IDENTIFIER, /* Object identifier type */ + LTC_ASN1_CUSTOM_TYPE, /* Object descriptor type */ + LTC_ASN1_CUSTOM_TYPE, /* External type and Instance-of type */ + LTC_ASN1_CUSTOM_TYPE, /* Real type */ + /* 10 */ + LTC_ASN1_CUSTOM_TYPE, /* Enumerated type */ + LTC_ASN1_CUSTOM_TYPE, /* Embedded-pdv type */ + LTC_ASN1_UTF8_STRING, /* UTF8String type */ + LTC_ASN1_CUSTOM_TYPE, /* Relative object identifier type */ + LTC_ASN1_CUSTOM_TYPE, /* The time type */ + /* 15 */ + LTC_ASN1_EOL, /* Reserved for future editions of this Recommendation | International Standard */ + LTC_ASN1_SEQUENCE, /* Sequence and Sequence-of types */ + LTC_ASN1_SET, /* Set and Set-of types */ + LTC_ASN1_CUSTOM_TYPE, /* NumericString types */ + LTC_ASN1_PRINTABLE_STRING, /* PrintableString types */ + /* 20 */ + LTC_ASN1_TELETEX_STRING, /* TeletexString (T61String) types */ + LTC_ASN1_CUSTOM_TYPE, /* VideotexString types */ + LTC_ASN1_IA5_STRING, /* IA5String types */ + LTC_ASN1_UTCTIME, /* UTCTime types */ + LTC_ASN1_GENERALIZEDTIME, /* GeneralizedTime types */ + /* 25 */ + LTC_ASN1_CUSTOM_TYPE, /* GraphicString types */ + LTC_ASN1_CUSTOM_TYPE, /* VisibleString (ISO646String) types */ + LTC_ASN1_CUSTOM_TYPE, /* GeneralString types */ + LTC_ASN1_CUSTOM_TYPE, /* UniversalString types */ + LTC_ASN1_CUSTOM_TYPE, /* UnrestrictedCharacterString types */ + /* 30 */ + LTC_ASN1_CUSTOM_TYPE, /* BMPString types */ +}; +const unsigned long der_asn1_tag_to_type_map_sz = sizeof(der_asn1_tag_to_type_map)/sizeof(der_asn1_tag_to_type_map[0]); + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c new file mode 100644 index 0000000..ad4dc7b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c @@ -0,0 +1,123 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_asn1_identifier.c + ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */ +static const unsigned char tag_constructed_map[] = +{ + /* 0 */ + 255, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 5 */ + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 10 */ + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 15 */ + 255, + LTC_ASN1_PC_CONSTRUCTED, + LTC_ASN1_PC_CONSTRUCTED, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 20 */ + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 25 */ + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, +}; + static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]); + +/** + Decode the ASN.1 Identifier + @param id Where to store the decoded Identifier + @param in Where to read the Identifier from + @param inlen [in/out] The size of in available/read + @return CRYPT_OK if successful +*/ +int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id) +{ + ulong64 tmp; + unsigned long tag_len; + int err; + + LTC_ARGCHK(id != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + + if (*inlen == 0) { + return CRYPT_BUFFER_OVERFLOW; + } + + tag_len = 1; + id->klass = (in[0] >> 6) & 0x3; + id->pc = (in[0] >> 5) & 0x1; + id->tag = in[0] & 0x1f; + + err = CRYPT_OK; + if (id->tag == 0x1f) { + id->tag = 0; + do { + if (*inlen < tag_len) { + /* break the loop and trigger the BOF error-code */ + tmp = 0xff; + break; + } + id->tag <<= 7; + id->tag |= in[tag_len] & 0x7f; + tmp = in[tag_len] & 0x80; + tag_len++; + } while ((tmp != 0) && (tag_len < 10)); + + if (tmp != 0) { + err = CRYPT_BUFFER_OVERFLOW; + } else if (id->tag < 0x1f) { + err = CRYPT_PK_ASN1_ERROR; + } + } + + if (err != CRYPT_OK) { + id->pc = 0; + id->klass = 0; + id->tag = 0; + } else { + *inlen = tag_len; + if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && + (id->tag < der_asn1_tag_to_type_map_sz) && + (id->tag < tag_constructed_map_sz) && + (id->pc == tag_constructed_map[id->tag])) { + id->type = der_asn1_tag_to_type_map[id->tag]; + } else { + if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) { + id->type = LTC_ASN1_EOL; + } else { + id->type = LTC_ASN1_CUSTOM_TYPE; + } + } + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c new file mode 100644 index 0000000..0e5a393 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_asn1_length.c + ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Decode the ASN.1 Length field + @param in Where to read the length field from + @param inlen [in/out] The size of in available/read + @param outlen [out] The decoded ASN.1 length + @return CRYPT_OK if successful +*/ +int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen) +{ + unsigned long real_len, decoded_len, offset, i; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + + if (*inlen < 1) { + return CRYPT_BUFFER_OVERFLOW; + } + + real_len = in[0]; + + if (real_len < 128) { + decoded_len = real_len; + offset = 1; + } else { + real_len &= 0x7F; + if (real_len == 0) { + return CRYPT_PK_ASN1_ERROR; + } + if (real_len > sizeof(decoded_len)) { + return CRYPT_OVERFLOW; + } + if (real_len > (*inlen - 1)) { + return CRYPT_BUFFER_OVERFLOW; + } + decoded_len = 0; + offset = 1 + real_len; + for (i = 0; i < real_len; i++) { + decoded_len = (decoded_len << 8) | in[1 + i]; + } + } + + if (outlen != NULL) *outlen = decoded_len; + if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW; + *inlen = offset; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c new file mode 100644 index 0000000..51d57ec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_asn1_identifier.c + ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Encode the ASN.1 Identifier + @param id The ASN.1 Identifer to encode + @param out Where to write the identifier to + @param outlen [in/out] The size of out available/written + @return CRYPT_OK if successful +*/ +int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen) +{ + ulong64 tmp; + unsigned long tag_len; + + LTC_ARGCHK(id != NULL); + LTC_ARGCHK(outlen != NULL); + + if (id->type != LTC_ASN1_CUSTOM_TYPE) { + if ((unsigned)id->type >= der_asn1_type_to_identifier_map_sz) { + return CRYPT_INVALID_ARG; + } + if (der_asn1_type_to_identifier_map[id->type] == -1) { + return CRYPT_INVALID_ARG; + } + if (out != NULL) { + *out = der_asn1_type_to_identifier_map[id->type]; + } + *outlen = 1; + return CRYPT_OK; + } + if (id->klass < LTC_ASN1_CL_UNIVERSAL || id->klass > LTC_ASN1_CL_PRIVATE) { + return CRYPT_INVALID_ARG; + } + if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) { + return CRYPT_INVALID_ARG; + } + if (id->tag > (ULONG_MAX >> (8 + 7))) { + return CRYPT_INVALID_ARG; + } + + if (out != NULL) { + if (*outlen < 1) { + return CRYPT_BUFFER_OVERFLOW; + } + + out[0] = id->klass << 6 | id->pc << 5; + } + + if (id->tag < 0x1f) { + if (out != NULL) { + out[0] |= id->tag & 0x1f; + } + *outlen = 1; + } else { + tag_len = 0; + tmp = id->tag; + do { + tag_len++; + tmp >>= 7; + } while (tmp); + + if (out != NULL) { + if (*outlen < tag_len + 1) { + return CRYPT_BUFFER_OVERFLOW; + } + out[0] |= 0x1f; + for (tmp = 1; tmp <= tag_len; ++tmp) { + out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80; + } + out[tag_len] &= ~0x80; + } + *outlen = tag_len + 1; + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c new file mode 100644 index 0000000..7892eea --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c @@ -0,0 +1,117 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_asn1_length.c + ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Encode the ASN.1 length field + @param len The length to encode + @param out Where to write the length field to + @param outlen [in/out] The size of out available/written + @return CRYPT_OK if successful +*/ +int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y; + + LTC_ARGCHK(outlen != NULL); + + x = len; + y = 0; + + while(x != 0) { + y++; + x >>= 8; + } + if (y == 0) { + return CRYPT_PK_ASN1_ERROR; + } + + if (out == NULL) { + if (len < 128) { + x = y; + } else { + x = y + 1; + } + } else { + if (*outlen < y) { + return CRYPT_BUFFER_OVERFLOW; + } + x = 0; + if (len < 128) { + out[x++] = (unsigned char)len; + } else if (len <= 0xffUL) { + out[x++] = 0x81; + out[x++] = (unsigned char)len; + } else if (len <= 0xffffUL) { + out[x++] = 0x82; + out[x++] = (unsigned char)((len>>8UL)&255); + out[x++] = (unsigned char)(len&255); + } else if (len <= 0xffffffUL) { + out[x++] = 0x83; + out[x++] = (unsigned char)((len>>16UL)&255); + out[x++] = (unsigned char)((len>>8UL)&255); + out[x++] = (unsigned char)(len&255); + #if ULONG_MAX != ULLONG_MAX + } else { + out[x++] = 0x84; + out[x++] = (unsigned char)((len>>24UL)&255); + out[x++] = (unsigned char)((len>>16UL)&255); + out[x++] = (unsigned char)((len>>8UL)&255); + out[x++] = (unsigned char)(len&255); + } + #else + } else if (len <= 0xffffffffUL) { + out[x++] = 0x84; + out[x++] = (unsigned char)((len>>24UL)&255); + out[x++] = (unsigned char)((len>>16UL)&255); + out[x++] = (unsigned char)((len>>8UL)&255); + out[x++] = (unsigned char)(len&255); + } else if (len <= 0xffffffffffULL) { + out[x++] = 0x85; + out[x++] = (unsigned char)((len>>32ULL)&255); + out[x++] = (unsigned char)((len>>24ULL)&255); + out[x++] = (unsigned char)((len>>16ULL)&255); + out[x++] = (unsigned char)((len>>8ULL)&255); + out[x++] = (unsigned char)(len&255); + } else if (len <= 0xffffffffffffULL) { + out[x++] = 0x86; + out[x++] = (unsigned char)((len>>40ULL)&255); + out[x++] = (unsigned char)((len>>32ULL)&255); + out[x++] = (unsigned char)((len>>24ULL)&255); + out[x++] = (unsigned char)((len>>16ULL)&255); + out[x++] = (unsigned char)((len>>8ULL)&255); + out[x++] = (unsigned char)(len&255); + } else if (len <= 0xffffffffffffffULL) { + out[x++] = 0x87; + out[x++] = (unsigned char)((len>>48ULL)&255); + out[x++] = (unsigned char)((len>>40ULL)&255); + out[x++] = (unsigned char)((len>>32ULL)&255); + out[x++] = (unsigned char)((len>>24ULL)&255); + out[x++] = (unsigned char)((len>>16ULL)&255); + out[x++] = (unsigned char)((len>>8ULL)&255); + out[x++] = (unsigned char)(len&255); + } else { + out[x++] = 0x88; + out[x++] = (unsigned char)((len>>56ULL)&255); + out[x++] = (unsigned char)((len>>48ULL)&255); + out[x++] = (unsigned char)((len>>40ULL)&255); + out[x++] = (unsigned char)((len>>32ULL)&255); + out[x++] = (unsigned char)((len>>24ULL)&255); + out[x++] = (unsigned char)((len>>16ULL)&255); + out[x++] = (unsigned char)((len>>8ULL)&255); + out[x++] = (unsigned char)(len&255); + } + #endif + } + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c new file mode 100644 index 0000000..63e6bdd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_asn1_identifier.c + ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Determine the length required when encoding the ASN.1 Identifier + @param id The ASN.1 identifier to encode + @param idlen [out] The required length to encode list + @return CRYPT_OK if successful +*/ + +int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen) +{ + return der_encode_asn1_identifier(id, NULL, idlen); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c new file mode 100644 index 0000000..1c81adb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c @@ -0,0 +1,22 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_asn1_length.c + ASN.1 DER, determine the length of the ASN.1 length field, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Determine the length required to encode len in the ASN.1 length field + @param len The length to encode + @param outlen [out] The length that's required to store len + @return CRYPT_OK if successful +*/ +int der_length_asn1_length(unsigned long len, unsigned long *outlen) +{ + return der_encode_asn1_length(len, NULL, outlen); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/sub.mk new file mode 100644 index 0000000..63de0ef --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/general/sub.mk @@ -0,0 +1,7 @@ +srcs-y += der_asn1_maps.c +srcs-y += der_decode_asn1_length.c +srcs-y += der_decode_asn1_identifier.c +srcs-y += der_encode_asn1_identifier.c +srcs-y += der_encode_asn1_length.c +srcs-y += der_length_asn1_identifier.c +srcs-y += der_length_asn1_length.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c new file mode 100644 index 0000000..7d2f296 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c @@ -0,0 +1,135 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_generalizedtime.c + ASN.1 DER, decode a GeneralizedTime, Steffen Jaeckel + Based on der_decode_utctime.c +*/ + +#ifdef LTC_DER + +static int s_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; + } +} + +#define DECODE_V(y, max) do {\ + y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \ + if (y >= max) return CRYPT_INVALID_PACKET; \ + x += 2; \ +} while(0) + +#define DECODE_V4(y, max) do {\ + y = s_char_to_int(buf[x])*1000 + s_char_to_int(buf[x+1])*100 + s_char_to_int(buf[x+2])*10 + s_char_to_int(buf[x+3]); \ + if (y >= max) return CRYPT_INVALID_PACKET; \ + x += 4; \ +} while(0) + +/** + Decodes a Generalized 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 Generalized time structure + @return CRYPT_OK if successful +*/ +int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, + ltc_generalizedtime *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; + } + if (!((y >= '0' && y <= '9') + || y == 'Z' || y == '.' + || y == '+' || y == '-')) { + return CRYPT_INVALID_PACKET; + } + buf[x] = y; + } + *inlen = 2 + x; + + if (x < 15) { + return CRYPT_INVALID_PACKET; + } + + /* possible encodings are +YYYYMMDDhhmmssZ +YYYYMMDDhhmmss+hh'mm' +YYYYMMDDhhmmss-hh'mm' +YYYYMMDDhhmmss.fsZ +YYYYMMDDhhmmss.fs+hh'mm' +YYYYMMDDhhmmss.fs-hh'mm' + + So let's do a trivial decode upto [including] ss + */ + + x = 0; + DECODE_V4(out->YYYY, 10000); + DECODE_V(out->MM, 13); + DECODE_V(out->DD, 32); + DECODE_V(out->hh, 24); + DECODE_V(out->mm, 60); + DECODE_V(out->ss, 60); + + /* clear fractional seconds info */ + out->fs = 0; + + /* now is it Z or . */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } + if (buf[x] == '.') { + x++; + while (buf[x] >= '0' && buf[x] <= '9') { + unsigned fs = out->fs; + if (x >= sizeof(buf)) return CRYPT_INVALID_PACKET; + out->fs *= 10; + out->fs += s_char_to_int(buf[x]); + if (fs > out->fs) return CRYPT_OVERFLOW; + x++; + } + } + + /* now is it Z, +, - */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } + 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; + } + return CRYPT_INVALID_PACKET; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c new file mode 100644 index 0000000..2378eeb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c @@ -0,0 +1,98 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_utctime.c + ASN.1 DER, encode a GeneralizedTime, Steffen Jaeckel + Based on der_encode_utctime.c +*/ + +#ifdef LTC_DER + +static const char * const baseten = "0123456789"; + +#define STORE_V(y) do {\ + out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[y % 10]); \ +} while(0) + +#define STORE_V4(y) do {\ + out[x++] = der_ia5_char_encode(baseten[(y/1000) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[(y/100) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[y % 10]); \ +} while(0) + +/** + Encodes a Generalized time structure in DER format + @param gtime The GeneralizedTime structure to encode + @param out The destination of the DER encoding of the GeneralizedTime structure + @param outlen [in/out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_encode_generalizedtime(const ltc_generalizedtime *gtime, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, tmplen; + int err; + + LTC_ARGCHK(gtime != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = der_length_generalizedtime(gtime, &tmplen)) != CRYPT_OK) { + return err; + } + if (tmplen > *outlen) { + *outlen = tmplen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header */ + out[0] = 0x18; + + /* store values */ + x = 2; + STORE_V4(gtime->YYYY); + STORE_V(gtime->MM); + STORE_V(gtime->DD); + STORE_V(gtime->hh); + STORE_V(gtime->mm); + STORE_V(gtime->ss); + + if (gtime->fs) { + unsigned long divisor; + unsigned fs = gtime->fs; + unsigned len = 0; + out[x++] = der_ia5_char_encode('.'); + divisor = 1; + do { + fs /= 10; + divisor *= 10; + len++; + } while(fs != 0); + while (len-- > 1) { + divisor /= 10; + out[x++] = der_ia5_char_encode(baseten[(gtime->fs/divisor) % 10]); + } + out[x++] = der_ia5_char_encode(baseten[gtime->fs % 10]); + } + + if (gtime->off_mm || gtime->off_hh) { + out[x++] = der_ia5_char_encode(gtime->off_dir ? '-' : '+'); + STORE_V(gtime->off_hh); + STORE_V(gtime->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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c new file mode 100644 index 0000000..dc237d3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_utctime.c + ASN.1 DER, get length of GeneralizedTime, Steffen Jaeckel + Based on der_length_utctime.c +*/ + +#ifdef LTC_DER + +/** + Gets length of DER encoding of GeneralizedTime + @param gtime The GeneralizedTime structure to get the size of + @param outlen [out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(gtime != NULL); + + if (gtime->fs == 0) { + /* we encode as YYYYMMDDhhmmssZ */ + *outlen = 2 + 14 + 1; + } else { + unsigned long len = 2 + 14 + 1; + unsigned fs = gtime->fs; + do { + fs /= 10; + len++; + } while(fs != 0); + if (gtime->off_hh == 0 && gtime->off_mm == 0) { + /* we encode as YYYYMMDDhhmmss.fsZ */ + len += 1; + } + else { + /* we encode as YYYYMMDDhhmmss.fs{+|-}hh'mm' */ + len += 5; + } + *outlen = len; + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/sub.mk new file mode 100644 index 0000000..312e613 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/sub.mk @@ -0,0 +1,3 @@ +srcs-y += der_encode_generalizedtime.c +srcs-y += der_decode_generalizedtime.c +srcs-y += der_length_generalizedtime.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c new file mode 100644 index 0000000..8fd80cf --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, err; + + 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; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len > (inlen - x)) { + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c new file mode 100644 index 0000000..8b8bd36 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + len = *outlen - x; + if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = der_ia5_char_encode(in[y]); + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c new file mode 100644 index 0000000..e397b1c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c @@ -0,0 +1,172 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + int err; + + 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 ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + noctets; + + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk new file mode 100644 index 0000000..dc32a5d --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c new file mode 100644 index 0000000..2c9bf7b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + 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; + } + + /* get the length of the data */ + inlen -= x; + if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) { + return err; + } + x += inlen; + + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c new file mode 100644 index 0000000..7261149 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c @@ -0,0 +1,105 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, len; + 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; + len = *outlen - 1; + if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) { + return err; + } + out += len; + + /* now store msbyte of zero if num is non-zero */ + if (leading_zero) { + *out++ = 0x00; + } + + /* if it's not zero store it as big endian */ + if (mp_cmp_d(num, 0) == LTC_MP_GT) { + /* now store the mpint */ + if ((err = mp_to_unsigned_bin(num, out)) != 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c new file mode 100644 index 0000000..90e2de3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c @@ -0,0 +1,55 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, err; + + 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 */ + len = leading_zero + mp_unsigned_bin_size(num); + } else { + /* it's negative */ + /* find power of 2 that is a multiple of eight and greater than count bits */ + z = mp_count_bits(num); + z = z + (8 - (z & 7)); + if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z; + len = z >> 3; + } + + if ((err = der_length_asn1_length(len, &z)) != CRYPT_OK) { + return err; + } + *outlen = 1 + z + len; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk new file mode 100644 index 0000000..d319f91 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c new file mode 100644 index 0000000..7251247 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c @@ -0,0 +1,94 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + int err; + + 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) { + *outlen = 2; + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode the packet header */ + x = 0; + if ((in[x++] & 0x1F) != 0x06) { + return CRYPT_INVALID_PACKET; + } + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + if ((len == 0) || (len > (inlen - x))) { + 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) { + y++; + } else { + if (y == 0) { + if (t <= 79) { + words[0] = t / 40; + words[1] = t % 40; + } else { + words[0] = 2; + words[1] = t - 80; + } + y = 2; + } else { + words[y++] = t; + } + } + t = 0; + } + } + + if (y > *outlen) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + err = CRYPT_OK; + } + + *outlen = y; + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c new file mode 100644 index 0000000..9a9c62d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c @@ -0,0 +1,92 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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(const 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; + y = *outlen - x; + if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) { + return err; + } + x += y; + + /* store first byte */ + wordbuf = words[0] * 40 + words[1]; + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c new file mode 100644 index 0000000..d9ded02 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c @@ -0,0 +1,77 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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(const 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 and word2 0..39 */ + if (words[0] > 2 || (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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk new file mode 100644 index 0000000..b56efb0 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c new file mode 100644 index 0000000..df84721 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c @@ -0,0 +1,69 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + int err; + + 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; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len > (inlen - x)) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + out[y] = in[x++]; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c new file mode 100644 index 0000000..73f1ee7 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + len = *outlen - x; + if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = in[y]; + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c new file mode 100644 index 0000000..67b071e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c @@ -0,0 +1,33 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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) +{ + unsigned long x; + int err; + + LTC_ARGCHK(outlen != NULL); + + if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + noctets; + + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk new file mode 100644 index 0000000..04607ee --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c new file mode 100644 index 0000000..3f9b533 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, err; + + 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; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len > (inlen - x)) { + 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c new file mode 100644 index 0000000..7b3aefd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + len = *outlen - x; + if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = der_printable_char_encode(in[y]); + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c new file mode 100644 index 0000000..c52e36d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c @@ -0,0 +1,144 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + int err; + + 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 ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + noctets; + + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk new file mode 100644 index 0000000..b509209 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c new file mode 100644 index 0000000..6d7f846 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @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 flags c.f. enum ltc_der_seq + @return CRYPT_OK on success +*/ +int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen, unsigned int flags) +{ + return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c new file mode 100644 index 0000000..2a0841d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c @@ -0,0 +1,541 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 int s_new_element(ltc_asn1_list **l) +{ + /* alloc new link */ + if (*l == NULL) { + *l = XCALLOC(1, sizeof(ltc_asn1_list)); + if (*l == NULL) { + return CRYPT_MEM; + } + } else { + (*l)->next = XCALLOC(1, sizeof(ltc_asn1_list)); + if ((*l)->next == NULL) { + return CRYPT_MEM; + } + (*l)->next->prev = *l; + *l = (*l)->next; + } + return CRYPT_OK; +} + +/** + 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 + @param depth The depth/level of decoding recursion we've already reached + @return CRYPT_OK on success. +*/ +static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth) +{ + ltc_asn1_list *l; + unsigned long err, identifier, len, totlen, data_offset, id_len, len_len; + void *realloc_tmp; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(out != NULL); + + l = NULL; + totlen = 0; + + if (*inlen == 0) { + /* alloc new link */ + if ((err = s_new_element(&l)) != CRYPT_OK) { + goto error; + } + } + + /* scan the input and and get lengths and what not */ + while (*inlen) { + /* alloc new link */ + if ((err = s_new_element(&l)) != CRYPT_OK) { + goto error; + } + + id_len = *inlen; + if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) { + goto error; + } + /* read the type byte */ + identifier = *in; + + if (l->type != LTC_ASN1_EOL) { + /* fetch length */ + len_len = *inlen - id_len; +#if defined(LTC_TEST_DBG) + data_offset = 666; + len = 0; +#endif + if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) { +#if defined(LTC_TEST_DBG) + fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err)); +#endif + goto error; + } else if (len > (*inlen - id_len - len_len)) { + err = CRYPT_INVALID_PACKET; +#if defined(LTC_TEST_DBG) + fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err)); +#endif + goto error; + } + data_offset = id_len + len_len; +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + if (l->type == LTC_ASN1_CUSTOM_TYPE && l->klass == LTC_ASN1_CL_CONTEXT_SPECIFIC) { + fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag); + } else { + fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]); + } +#endif + len += data_offset; + + if (l->type == LTC_ASN1_CUSTOM_TYPE) { + /* Custom type, use the 'used' field to store the original identifier */ + l->used = identifier; + if (l->pc == LTC_ASN1_PC_CONSTRUCTED) { + /* treat constructed elements like SEQUENCEs */ + identifier = 0x20; + } else { + /* primitive elements are treated as opaque data */ + identifier = 0x80; + } + } + } else { + /* Init this so gcc won't complain, + * as this case will only be hit when we + * can't decode the identifier so the + * switch-case should go to default anyway... + */ + data_offset = 0; + len = 0; + } + + /* now switch on type */ + switch (identifier) { + case 0x01: /* BOOLEAN */ + if (l->type != LTC_ASN1_BOOLEAN) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = 1; + l->data = XCALLOC(1, sizeof(int)); + + 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 */ + if (l->type != LTC_ASN1_INTEGER) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + 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 */ + if (l->type != LTC_ASN1_BIT_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + 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 */ + if (l->type != LTC_ASN1_OCTET_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + 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 */ + if (l->type != LTC_ASN1_NULL) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* valid NULL is 0x05 0x00 */ + if (in[0] != 0x05 || in[1] != 0x00) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* simple to store ;-) */ + l->data = NULL; + l->size = 0; + len = 2; + + break; + + case 0x06: /* OID */ + if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + 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 */ + if (l->type != LTC_ASN1_UTF8_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + l->size = len; + + if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) { + 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 */ + if (l->type != LTC_ASN1_PRINTABLE_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + 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 0x14: /* TELETEXT */ + if (l->type != LTC_ASN1_TELETEX_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x16: /* IA5 */ + if (l->type != LTC_ASN1_IA5_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + 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 */ + if (l->type != LTC_ASN1_UTCTIME) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + 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 0x18: + if (l->type != LTC_ASN1_GENERALIZEDTIME) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len; + + if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) { + goto error; + } + + break; + + case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */ + case 0x30: /* SEQUENCE */ + case 0x31: /* SET */ + + /* init field */ + if (identifier == 0x20) { + if (l->type != LTC_ASN1_CUSTOM_TYPE) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + } + else if (identifier == 0x30) { + if (l->type != LTC_ASN1_SEQUENCE) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + } + else { + if (l->type != LTC_ASN1_SET) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + } + + /* check that we don't go over the recursion limit */ + if (depth > LTC_DER_MAX_RECURSION) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + if ((l->data = XMALLOC(len)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + XMEMCPY(l->data, in, len); + l->size = len; + + + /* jump to the start of the data */ + in += data_offset; + *inlen -= data_offset; + len -= data_offset; + + /* save the decoded ASN.1 len */ + len_len = len; + + /* Sequence elements go as child */ + if ((err = s_der_decode_sequence_flexi(in, &len, &(l->child), depth+1)) != CRYPT_OK) { + goto error; + } + if (len_len != len) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* len update */ + totlen += data_offset; + + /* the flexi decoder can also do nothing, so make sure a child has been allocated */ + if (l->child) { + /* link them up y0 */ + l->child->parent = l; + } + + break; + + case 0x80: /* Context-specific */ + if (l->type != LTC_ASN1_CUSTOM_TYPE) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + if ((l->data = XCALLOC(1, len - data_offset)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + XMEMCPY(l->data, in + data_offset, len - data_offset); + l->size = len - data_offset; + + break; + + default: + /* invalid byte ... this is a soft error */ + /* remove link */ + if (l->prev) { + l = l->prev; + XFREE(l->next); + l->next = NULL; + } + goto outside; + } + + /* advance pointers */ + totlen += len; + in += len; + *inlen -= len; + } + +outside: + + /* in case we processed anything */ + if (totlen) { + /* 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; +} + +/** + 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) +{ + return s_der_decode_sequence_flexi(in, inlen, out, 0); +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c new file mode 100644 index 0000000..429b540 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c @@ -0,0 +1,183 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + @param a1 Initialized argument list #1 + @param a2 Initialized argument list #2 (copy of #1) + @param flags c.f. enum ltc_der_seq + @return CRYPT_OK on success +*/ +static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags) +{ + int err; + ltc_asn1_type type; + unsigned long size, x; + void *data; + ltc_asn1_list *list; + + LTC_ARGCHK(in != NULL); + + /* get size of output that will be required */ + x = 0; + for (;;) { + type = (ltc_asn1_type)va_arg(a1, int); + + if (type == LTC_ASN1_EOL) { + break; + } + + size = va_arg(a1, unsigned long); + data = va_arg(a1, void*); + LTC_UNUSED_PARAM(size); + LTC_UNUSED_PARAM(data); + + 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: + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_TELETEX_STRING: + case LTC_ASN1_GENERALIZEDTIME: + ++x; + break; + + case LTC_ASN1_EOL: + case LTC_ASN1_CUSTOM_TYPE: + default: + return CRYPT_INVALID_ARG; + } + } + + /* 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 */ + x = 0; + for (;;) { + type = (ltc_asn1_type)va_arg(a2, int); + size = va_arg(a2, unsigned long); + data = va_arg(a2, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + 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: + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_TELETEX_STRING: + case LTC_ASN1_GENERALIZEDTIME: + LTC_SET_ASN1(list, x++, type, data, size); + break; + /* coverity[dead_error_line] */ + case LTC_ASN1_EOL: + case LTC_ASN1_CUSTOM_TYPE: + default: + break; + } + } + + err = der_decode_sequence_ex(in, inlen, list, x, flags); + XFREE(list); + return err; +} + +/** + Decode a SEQUENCE type using a VA list + @param in Input buffer + @param inlen Length of input in octets + @remark <...> is of the form (int, unsigned long, void*) + @return CRYPT_OK on success +*/ +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) +{ + va_list a1, a2; + int err; + + LTC_ARGCHK(in != NULL); + + va_start(a1, inlen); + va_start(a2, inlen); + + err = s_der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED); + + va_end(a2); + va_end(a1); + + return err; +} + +/** + Decode a SEQUENCE type using a VA list + @param in Input buffer + @param inlen Length of input in octets + @param flags c.f. enum ltc_der_seq + @remark <...> is of the form (int, unsigned long, void*) + @return CRYPT_OK on success +*/ +int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) +{ + va_list a1, a2; + int err; + + LTC_ARGCHK(in != NULL); + + va_start(a1, flags); + va_start(a2, flags); + + err = s_der_decode_sequence_va(in, inlen, a1, a2, flags); + + va_end(a2); + va_end(a1); + + return err; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c new file mode 100644 index 0000000..d7f3c88 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c @@ -0,0 +1,203 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @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(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int type_of) +{ + int err; + ltc_asn1_type 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; z = 0; + if ((err = der_length_sequence_ex(list, inlen, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG; + + /* 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; + + y = *outlen - x; + if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + x += y; + + /* store data */ + *outlen -= x; + for (i = 0; i < inlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + z = *outlen; + if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_INTEGER: + z = *outlen; + if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SHORT_INTEGER: + z = *outlen; + if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_BIT_STRING: + z = *outlen; + if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_RAW_BIT_STRING: + z = *outlen; + if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_OCTET_STRING: + z = *outlen; + if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_NULL: + out[x] = 0x05; + out[x+1] = 0x00; + z = 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + z = *outlen; + if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_IA5_STRING: + z = *outlen; + if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_PRINTABLE_STRING: + z = *outlen; + if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTF8_STRING: + z = *outlen; + if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTCTIME: + z = *outlen; + if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_GENERALIZEDTIME: + z = *outlen; + if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SET: + z = *outlen; + if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SETOF: + z = *outlen; + if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SEQUENCE: + z = *outlen; + if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CUSTOM_TYPE: + z = *outlen; + if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + + x += z; + *outlen -= z; + } + *outlen = x; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c new file mode 100644 index 0000000..a0877fc --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c @@ -0,0 +1,141 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + ltc_asn1_type 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 = (ltc_asn1_type)va_arg(args, int); + + if (type == LTC_ASN1_EOL) { + break; + } + + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + LTC_UNUSED_PARAM(size); + LTC_UNUSED_PARAM(data); + + 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_RAW_BIT_STRING: + case LTC_ASN1_GENERALIZEDTIME: + ++x; + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_CUSTOM_TYPE: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: + 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 = (ltc_asn1_type)va_arg(args, int); + + if (type == LTC_ASN1_EOL) { + break; + } + + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + 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_RAW_BIT_STRING: + case LTC_ASN1_GENERALIZEDTIME: + LTC_SET_ASN1(list, x++, type, data, size); + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_CUSTOM_TYPE: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: + 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c new file mode 100644 index 0000000..fe7dd0e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c @@ -0,0 +1,180 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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(const ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen) +{ + return der_length_sequence_ex(list, inlen, outlen, NULL); +} + +int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen, unsigned long *payloadlen) +{ + int err; + ltc_asn1_type 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; + } + + /* some items may be optional during import */ + if (!list[i].used && list[i].optional) continue; + + switch (type) { + case LTC_ASN1_BOOLEAN: + if ((err = der_length_boolean(&x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_INTEGER: + if ((err = der_length_integer(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SHORT_INTEGER: + if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_RAW_BIT_STRING: + if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_OCTET_STRING: + if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_NULL: + y += 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_IA5_STRING: + if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_TELETEX_STRING: + if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_PRINTABLE_STRING: + if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_UTCTIME: + if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_GENERALIZEDTIME: + if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_UTF8_STRING: + if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_CUSTOM_TYPE: + if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + default: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + + if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (payloadlen != NULL) { + *payloadlen = y; + } + + /* store size */ + *outlen = y + x + 1; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c new file mode 100644 index 0000000..b7cbd07 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + + if (!in) return; + + /* 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_SETOF: 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; + XFREE(in); + in = l; + } +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c new file mode 100644 index 0000000..22634a3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_sequence_shrink.c + Free memory allocated for CONSTRUCTED, SET or SEQUENCE elements by der_decode_sequence_flexi(), Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Free memory allocated for CONSTRUCTED, + SET or SEQUENCE elements by der_decode_sequence_flexi() + @param in The list to shrink +*/ +void der_sequence_shrink(ltc_asn1_list *in) +{ + if (!in) return; + + /* now walk the list and free stuff */ + while (in != NULL) { + /* is there a child? */ + if (in->child) { + der_sequence_shrink(in->child); + } + + switch (in->type) { + case LTC_ASN1_CUSTOM_TYPE: + case LTC_ASN1_SET: + case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break; + default: break; + } + + /* move to next and free current */ + in = in->next; + } +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk new file mode 100644 index 0000000..d44420b --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c new file mode 100644 index 0000000..1e90a1f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c @@ -0,0 +1,74 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 s_ltc_to_asn1(ltc_asn1_type v) +{ + return der_asn1_type_to_identifier_map[v]; +} + + +static int s_qsort_helper(const void *a, const void *b) +{ + ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b; + int r; + + r = s_ltc_to_asn1(A->type) - s_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; + } + 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(const 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), &s_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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c new file mode 100644 index 0000000..184b6ec --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c @@ -0,0 +1,151 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 s_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(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, z; + ptrdiff_t 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 = ptr - 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), &s_qsort_helper); + + /* copy static header */ + XMEMCPY(out, buf, hdrlen); + + /* copy+sort using edges+indecies to output from buffer */ + for (y = (unsigned long)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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk new file mode 100644 index 0000000..52525d6 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c new file mode 100644 index 0000000..e00702d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c @@ -0,0 +1,60 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + } + + if (len > sizeof(unsigned long)) { + return CRYPT_OVERFLOW; + } + + /* read number */ + y = 0; + while (len--) { + y = (y<<8) | (unsigned long)in[x++]; + } + *num = y; + + return CRYPT_OK; + +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c new file mode 100644 index 0000000..3af47c5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c @@ -0,0 +1,85 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c new file mode 100644 index 0000000..aeee948 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + int err; + + 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; + } else if ((num&(1UL<<((z<<3) - 1))) != 0) { + /* in case msb is set */ + ++z; + } + + if ((err = der_length_asn1_length(z, &y)) != CRYPT_OK) { + return err; + } + *outlen = 1 + y + z; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk new file mode 100644 index 0000000..fae1f08 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk new file mode 100644 index 0000000..2951f19 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk @@ -0,0 +1,17 @@ +subdirs-y += bit +subdirs-y += boolean +subdirs-y += choice +subdirs-y += custom_type +subdirs-y += general +subdirs-y += generalizedtime +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 +subdirs-y += teletex_string diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c new file mode 100644 index 0000000..6779cd5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_teletex_string.c + ASN.1 DER, encode a teletex STRING +*/ + +#ifdef LTC_DER + +/** + Store a teletex STRING + @param in The DER encoded teletex STRING + @param inlen The size of the DER teletex 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_teletex_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int t, err; + + 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 0x14 */ + if ((in[0] & 0x1F) != 0x14) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len > (inlen - x)) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_teletex_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c new file mode 100644 index 0000000..05dc4b0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c @@ -0,0 +1,188 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_teletex_string.c + ASN.1 DER, get length of teletex STRING +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} teletex_table[] = { +{ '\0', 0 }, +{ '\a', 7 }, +{ '\b', 8 }, +{ '\t', 9 }, +{ '\n', 10 }, +{ '\v', 11 }, +{ '\f', 12 }, +{ '\r', 13 }, +{ ' ', 32 }, +{ '!', 33 }, +{ '"', 34 }, +{ '%', 37 }, +{ '&', 38 }, +{ '\'', 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 }, +{ ';', 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 }, +{ ']', 93 }, +{ '_', 95 }, +{ '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 }, +{ '|', 124 }, +{ ' ', 160 }, +{ 0xa1, 161 }, +{ 0xa2, 162 }, +{ 0xa3, 163 }, +{ '$', 164 }, +{ 0xa5, 165 }, +{ '#', 166 }, +{ 0xa7, 167 }, +{ 0xa4, 168 }, +{ 0xab, 171 }, +{ 0xb0, 176 }, +{ 0xb1, 177 }, +{ 0xb2, 178 }, +{ 0xb3, 179 }, +{ 0xd7, 180 }, +{ 0xb5, 181 }, +{ 0xb6, 182 }, +{ 0xb7, 183 }, +{ 0xf7, 184 }, +{ 0xbb, 187 }, +{ 0xbc, 188 }, +{ 0xbd, 189 }, +{ 0xbe, 190 }, +{ 0xbf, 191 }, +}; + +int der_teletex_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { + if (teletex_table[x].code == c) { + return teletex_table[x].value; + } + } + return -1; +} + +int der_teletex_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { + if (teletex_table[x].value == v) { + return teletex_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of teletex 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_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + int err; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_teletex_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + noctets; + + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/sub.mk new file mode 100644 index 0000000..8f47f07 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/sub.mk @@ -0,0 +1,2 @@ +srcs-y += der_decode_teletex_string.c +srcs-y += der_length_teletex_string.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c new file mode 100644 index 0000000..6149bfe --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c @@ -0,0 +1,116 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_utctime.c + ASN.1 DER, decode a UTCTIME, Tom St Denis +*/ + +#ifdef LTC_DER + +static int s_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; + } +} + +#define DECODE_V(y, max) \ + y = s_char_to_int(buf[x])*10 + s_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] = { 0 }; /* initialize as all zeroes */ + 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; + } + 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; + } + 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; + } + return CRYPT_INVALID_PACKET; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c new file mode 100644 index 0000000..b1c6fbe --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c @@ -0,0 +1,71 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_utctime.c + ASN.1 DER, encode a UTCTIME, Tom St Denis +*/ + +#ifdef LTC_DER + +static const char * const 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(const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c new file mode 100644 index 0000000..b93c25f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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(const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk new file mode 100644 index 0000000..afb3e1b --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c new file mode 100644 index 0000000..93a5e5e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c @@ -0,0 +1,117 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_utf8_string.c + ASN.1 DER, encode a UTF8 STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Decode a UTF8 STRING and recover an array of unicode characters. + @param in The DER encoded UTF8 STRING + @param inlen The size of the DER UTF8 STRING + @param out [out] The array of unicode characters (wchar_t*) + @param outlen [in/out] The number of unicode characters in the array + @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; + int err; + + 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; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + if (len > (inlen - x)) { + return CRYPT_INVALID_PACKET; + } + + /* proceed to recover unicode characters from utf8 data. + for reference see Section 3 of RFC 3629: + + https://tools.ietf.org/html/rfc3629#section-3 + */ + for (y = 0; x < inlen; ) { + /* read first byte */ + tmp = in[x++]; + + /* a unicode character is recovered from a sequence of 1 to 4 utf8 bytes. + the form of those bytes must match a row in the following table: + + 0xxxxxxx + 110xxxxx 10xxxxxx + 1110xxxx 10xxxxxx 10xxxxxx + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + the number of leading ones in the first byte (0,2,3,4) determines the + number of remaining bytes to read (0,1,2,3) + */ + + /* determine z, the number of leading ones. + this is done by left-shifting tmp, which clears the ms-bits */ + for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF); + + /* z should be in {0,2,3,4} */ + if (z == 1 || z > 4) { + return CRYPT_INVALID_PACKET; + } + + /* right-shift tmp to restore least-sig bits */ + tmp >>= z; + + /* now update z so it equals the number of additional bytes to read */ + if (z > 0) { --z; } + + if (x + z > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read remaining bytes */ + while (z-- != 0) { + if ((in[x] & 0xC0) != 0x80) { + return CRYPT_INVALID_PACKET; + } + tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F); + } + + if (y < *outlen) { + out[y] = tmp; + } + y++; + } + if (y > *outlen) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + err = CRYPT_OK; + } + *outlen = y; + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c new file mode 100644 index 0000000..a8154cd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + for (x = len = 0; x < inlen; x++) { + if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; + len += der_utf8_charsize(in[x]); + } + if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) { + return err; + } + x += len + 1; + + /* too big? */ + if (x > *outlen) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + + /* encode the header+len */ + x = 0; + out[x++] = 0x0C; + + y = *outlen - x; + if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) { + return err; + } + x += y; + + /* store UTF8 */ + for (y = 0; y < inlen; y++) { + 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; +#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF + 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; +#endif + default: break; + } + } + + /* return length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c new file mode 100644 index 0000000..424002b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c @@ -0,0 +1,81 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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; + } + if (c <= 0x7FF) { + return 2; + } +#if LTC_WCHAR_MAX == 0xFFFF + return 3; +#else + if (c <= 0xFFFF) { + return 3; + } + return 4; +#endif +} + +/** + Test whether the given code point is valid character + @param c The UTF-8 character to test + @return 1 - valid, 0 - invalid +*/ +int der_utf8_valid_char(const wchar_t c) +{ + LTC_UNUSED_PARAM(c); +#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF + if (c > 0x10FFFF) return 0; +#endif +#if LTC_WCHAR_MAX != 0xFFFF && LTC_WCHAR_MAX != 0xFFFFFFFF + if (c < 0) return 0; +#endif + return 1; +} + +/** + 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; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(outlen != NULL); + + len = 0; + for (x = 0; x < noctets; x++) { + if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; + len += der_utf8_charsize(in[x]); + } + + if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + len; + + return CRYPT_OK; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk new file mode 100644 index 0000000..3538929 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c new file mode 100644 index 0000000..b3e1ee2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_DER + +typedef struct { + enum ltc_oid_id id; + const char* oid; +} oid_table_entry; + +static const oid_table_entry pka_oids[] = { + { LTC_OID_RSA, "1.2.840.113549.1.1.1" }, + { LTC_OID_DSA, "1.2.840.10040.4.1" }, + { LTC_OID_EC, "1.2.840.10045.2.1" }, + { LTC_OID_EC_PRIMEF, "1.2.840.10045.1.1" }, + { LTC_OID_X25519, "1.3.101.110" }, + { LTC_OID_ED25519, "1.3.101.112" }, +}; + +/* + Returns the OID requested. + @return CRYPT_OK if valid +*/ +int pk_get_oid(enum ltc_oid_id id, const char **st) +{ + unsigned int i; + LTC_ARGCHK(st != NULL); + for (i = 0; i < sizeof(pka_oids)/sizeof(pka_oids[0]); ++i) { + if (pka_oids[i].id == id) { + *st = pka_oids[i].oid; + return CRYPT_OK; + } + } + return CRYPT_INVALID_ARG; +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c new file mode 100644 index 0000000..f842bc5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_DER + +/* + Compare an OID string to an array of `unsigned long`. + @return CRYPT_OK if equal +*/ +int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size) +{ + unsigned long i; + char tmp[256] = { 0 }; + int err; + + if (o1 == NULL || o2 == NULL) return CRYPT_ERROR; + + i = sizeof(tmp); + if ((err = pk_oid_num_to_str(o2, o2size, tmp, &i)) != CRYPT_OK) { + return err; + } + + if (XSTRCMP(o1, tmp) != 0) { + return CRYPT_PK_INVALID_TYPE; + } + + return CRYPT_OK; +} + +/* + Compare an OID string to an OID element decoded from ASN.1. + @return CRYPT_OK if equal +*/ +int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2) +{ + if (o1 == NULL || o2 == NULL) return CRYPT_ERROR; + + if (o2->type != LTC_ASN1_OBJECT_IDENTIFIER) return CRYPT_INVALID_ARG; + + return pk_oid_cmp_with_ulong(o1, o2->data, o2->size); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c new file mode 100644 index 0000000..bc21a6f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen) +{ + unsigned long i, j, limit, oid_j; + size_t OID_len; + + LTC_ARGCHK(oidlen != NULL); + + limit = *oidlen; + *oidlen = 0; /* make sure that we return zero oidlen on error */ + for (i = 0; i < limit; i++) oid[i] = 0; + + if (OID == NULL) return CRYPT_OK; + + OID_len = XSTRLEN(OID); + if (OID_len == 0) return CRYPT_OK; + + for (i = 0, j = 0; i < OID_len; i++) { + if (OID[i] == '.') { + if (++j >= limit) continue; + } + else if ((OID[i] >= '0') && (OID[i] <= '9')) { + if ((j >= limit) || (oid == NULL)) continue; + oid_j = oid[j]; + oid[j] = oid[j] * 10 + (OID[i] - '0'); + if (oid[j] < oid_j) return CRYPT_OVERFLOW; + } + else { + return CRYPT_ERROR; + } + } + if (j == 0) return CRYPT_ERROR; + if (j >= limit) { + *oidlen = j; + return CRYPT_BUFFER_OVERFLOW; + } + *oidlen = j + 1; + return CRYPT_OK; +} + +int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen) +{ + int i; + unsigned long j, k; + char tmp[256] = { 0 }; + + LTC_ARGCHK(oid != NULL); + LTC_ARGCHK(oidlen < INT_MAX); + LTC_ARGCHK(outlen != NULL); + + for (i = oidlen - 1, k = 0; i >= 0; i--) { + j = oid[i]; + if (j == 0) { + tmp[k] = '0'; + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + } + else { + while (j > 0) { + tmp[k] = '0' + (j % 10); + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + j /= 10; + } + } + if (i > 0) { + tmp[k] = '.'; + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + } + } + if (*outlen < k + 1) { + *outlen = k + 1; + return CRYPT_BUFFER_OVERFLOW; + } + LTC_ARGCHK(OID != NULL); + for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1]; + OID[k] = '\0'; + *outlen = k; /* the length without terminating NUL byte */ + return CRYPT_OK; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/sub.mk new file mode 100644 index 0000000..867ffad --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/oid/sub.mk @@ -0,0 +1,2 @@ +srcs-y += pk_oid_cmp.c +srcs-y += pk_oid_str.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c new file mode 100644 index 0000000..e715f11 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c @@ -0,0 +1,97 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PKCS_8 + +/** + PKCS#8 decrypt if necessary & flexi-decode + + @param in Pointer to the ASN.1 encoded input data + @param inlen Length of the input data + @param pwd Pointer to the password that was used when encrypting + @param pwdlen Length of the password + @param decoded_list Pointer to a pointer for the flexi-decoded list + @return CRYPT_OK on success +*/ +int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + ltc_asn1_list **decoded_list) +{ + unsigned long len = inlen; + unsigned long dec_size; + unsigned char *dec_data = NULL; + ltc_asn1_list *l = NULL; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(decoded_list != NULL); + + *decoded_list = NULL; + if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) { + /* the following "if" detects whether it is encrypted or not */ + /* PKCS8 Setup + * 0:d=0 hl=4 l= 380 cons: SEQUENCE + * 4:d=1 hl=2 l= 78 cons: SEQUENCE + * 6:d=2 hl=2 l= 9 prim: OBJECT :OID indicating PBES1 or PBES2 (== *lalgoid) + * 17:d=2 hl=2 l= 65 cons: SEQUENCE + * Stuff in between is dependent on whether it's PBES1 or PBES2 + * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) + */ + if (l->type == LTC_ASN1_SEQUENCE && + LTC_ASN1_IS_TYPE(l->child, LTC_ASN1_SEQUENCE) && + LTC_ASN1_IS_TYPE(l->child->child, LTC_ASN1_OBJECT_IDENTIFIER) && + LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) && + LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) { + ltc_asn1_list *lalgoid = l->child->child; + pbes_arg pbes; + + XMEMSET(&pbes, 0, sizeof(pbes)); + + if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) { + /* Successfully extracted PBES1 parameters */ + } else if (pbes2_extract(lalgoid, &pbes) == CRYPT_OK) { + /* Successfully extracted PBES2 parameters */ + } else { + /* unsupported encryption */ + err = CRYPT_INVALID_PACKET; + goto LBL_DONE; + } + + pbes.enc_data = l->child->next; + pbes.pwd = pwd; + pbes.pwdlen = pwdlen; + + dec_size = pbes.enc_data->size; + if ((dec_data = XMALLOC(dec_size)) == NULL) { + err = CRYPT_MEM; + goto LBL_DONE; + } + + if ((err = pbes_decrypt(&pbes, dec_data, &dec_size)) != CRYPT_OK) goto LBL_DONE; + + der_free_sequence_flexi(l); + l = NULL; + err = der_decode_sequence_flexi(dec_data, &dec_size, &l); + if (err != CRYPT_OK) goto LBL_DONE; + *decoded_list = l; + } + else { + /* not encrypted */ + err = CRYPT_OK; + *decoded_list = l; + } + /* Set l to NULL so it won't be free'd */ + l = NULL; + } + +LBL_DONE: + if (l) der_free_sequence_flexi(l); + if (dec_data) { + zeromem(dec_data, dec_size); + XFREE(dec_data); + } + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/sub.mk new file mode 100644 index 0000000..86d77d4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/sub.mk @@ -0,0 +1,2 @@ +subdirs-y += der +subdirs-y += oid diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c new file mode 100644 index 0000000..feff868 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c @@ -0,0 +1,109 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x509_decode_public_key_from_certificate.c + ASN.1 DER/X.509, decode a certificate +*/ + +#ifdef LTC_DER + +/* Check if it looks like a SubjectPublicKeyInfo */ +#define LOOKS_LIKE_SPKI(l) ((l) != NULL) \ +&& ((l)->type == LTC_ASN1_SEQUENCE) \ +&& ((l)->child != NULL) \ +&& ((l)->child->type == LTC_ASN1_OBJECT_IDENTIFIER) \ +&& ((l)->next != NULL) \ +&& ((l)->next->type == LTC_ASN1_BIT_STRING) + +/** + Try to decode the public key from a X.509 certificate + @param in The input buffer + @param inlen The length of the input buffer + @param algorithm One out of the enum #public_key_algorithms + @param param_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len [in/out] The number of parameters to include + @param callback The callback + @param ctx The context passed to the callback + @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found +*/ +int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, + enum ltc_oid_id algorithm, ltc_asn1_type param_type, + ltc_asn1_list* parameters, unsigned long *parameters_len, + public_key_decode_cb callback, void *ctx) +{ + int err; + unsigned char *tmpbuf; + unsigned long tmpbuf_len, tmp_inlen; + ltc_asn1_list *decoded_list = NULL, *l; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != 0); + LTC_ARGCHK(callback != NULL); + + tmpbuf_len = inlen; + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_OUT; + } + + tmp_inlen = inlen; + if ((err = der_decode_sequence_flexi(in, &tmp_inlen, &decoded_list)) == CRYPT_OK) { + l = decoded_list; + + err = CRYPT_NOP; + + /* Move 2 levels up in the tree + SEQUENCE + SEQUENCE + ... + */ + if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { + l = l->child; + if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { + l = l->child; + + /* Move forward in the tree until we find this combination + ... + SEQUENCE + SEQUENCE + OBJECT IDENTIFIER + NULL + BIT STRING + */ + do { + /* The additional check for l->data is there to make sure + * we won't try to decode a list that has been 'shrunk' + */ + if ((l->type == LTC_ASN1_SEQUENCE) + && (l->data != NULL) + && LOOKS_LIKE_SPKI(l->child)) { + if (algorithm == LTC_OID_EC) { + err = callback(l->data, l->size, ctx); + } else { + err = x509_decode_subject_public_key_info(l->data, l->size, + algorithm, tmpbuf, &tmpbuf_len, + param_type, parameters, parameters_len); + if (err == CRYPT_OK) { + err = callback(tmpbuf, tmpbuf_len, ctx); + goto LBL_OUT; + } + } + } + l = l->next; + } while(l); + } + } + } + +LBL_OUT: + if (decoded_list) der_free_sequence_flexi(decoded_list); + if (tmpbuf != NULL) XFREE(tmpbuf); + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c new file mode 100644 index 0000000..a94362d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c @@ -0,0 +1,119 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x509_decode_subject_public_key_info.c + ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav +*/ + +#ifdef LTC_DER + +/* AlgorithmIdentifier := SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm + * } + * + * SubjectPublicKeyInfo := SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + */ +/** + Decode a SubjectPublicKeyInfo + @param in The input buffer + @param inlen The length of the input buffer + @param algorithm One out of the enum #public_key_algorithms + @param public_key The buffer for the public key + @param public_key_len [in/out] The length of the public key buffer and the written length + @param parameters_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len [in/out] The number of parameters to include + @return CRYPT_OK on success +*/ +int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, + unsigned int algorithm, void* public_key, unsigned long* public_key_len, + ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len) +{ + int err; + unsigned long len, alg_id_num, tmplen; + const char* oid; + unsigned char *tmpbuf; + unsigned long tmpoid[16]; + unsigned long *_parameters_len; + ltc_asn1_list alg_id[2]; + ltc_asn1_list subject_pubkey[2]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != 0); + LTC_ARGCHK(public_key_len != NULL); + + if (parameters_type != LTC_ASN1_EOL) { + if ((parameters == NULL) || (parameters_len == NULL)) { + tmplen = 0; + _parameters_len = &tmplen; + } else { + _parameters_len = parameters_len; + } + } + + err = pk_get_oid(algorithm, &oid); + if (err != CRYPT_OK) { + return err; + } + + /* see if the OpenSSL DER format RSA public key will work */ + tmpbuf = XCALLOC(1, inlen); + 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(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0])); + if (parameters_type == LTC_ASN1_EOL) { + alg_id_num = 1; + } else { + LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, *_parameters_len); + alg_id_num = 2; + } + + /* 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(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, alg_id_num); + LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, inlen*8U); + + err=der_decode_sequence(in, inlen, subject_pubkey, 2UL); + if (err != CRYPT_OK) { + goto LBL_ERR; + } + if (parameters_type != LTC_ASN1_EOL) { + *_parameters_len = alg_id[1].size; + } + + if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) { + /* OID mismatch */ + goto LBL_ERR; + } + + len = subject_pubkey[1].size/8; + if (*public_key_len >= len) { + XMEMCPY(public_key, subject_pubkey[1].data, len); + *public_key_len = len; + } else { + *public_key_len = len; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + err = CRYPT_OK; + +LBL_ERR: + + XFREE(tmpbuf); + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c new file mode 100644 index 0000000..fd0a5d0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x509_encode_subject_public_key_info.c + ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav +*/ + +#ifdef LTC_DER + +/* AlgorithmIdentifier := SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm + * } + * + * SubjectPublicKeyInfo := SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + */ +/** + Encode a SubjectPublicKeyInfo + @param out The output buffer + @param outlen [in/out] Length of buffer and resulting length of output + @param algorithm One out of the enum #public_key_algorithms + @param public_key The buffer for the public key + @param public_key_len The length of the public key buffer + @param parameters_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len The number of parameters to include + @return CRYPT_OK on success +*/ +int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, + unsigned int algorithm, const void* public_key, unsigned long public_key_len, + ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len) +{ + int err; + ltc_asn1_list alg_id[2]; + const char *OID; + unsigned long oid[16], oidlen; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = pk_get_oid(algorithm, &OID)) != CRYPT_OK) { + return err; + } + + oidlen = sizeof(oid)/sizeof(oid[0]); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + return err; + } + + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len); + + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id, + LTC_ASN1_RAW_BIT_STRING, public_key_len*8U, public_key, + LTC_ASN1_EOL, 0UL, NULL); + +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh.c new file mode 100644 index 0000000..277ce30 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh.c @@ -0,0 +1,227 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ +const ltc_dh_set_type ltc_dh_sets[] = { +#ifdef LTC_DH768 +{ /* 768-bit MODP Group 1 - https://tools.ietf.org/html/rfc7296#appendix-B.1 */ + 96, + "DH-768", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH1024 +{ /* 1024-bit MODP Group 2 - https://tools.ietf.org/html/rfc7296#appendix-B.2 */ + 128, + "DH-1024", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" + "FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH1536 +{ /* 1536-bit MODP Group 5 - https://tools.ietf.org/html/rfc3526#section-2 */ + 192, + "DH-1536", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH2048 +{ /* 2048-bit MODP Group 14 - https://tools.ietf.org/html/rfc3526#section-3 */ + 256, + "DH-2048", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH3072 +{ /* 3072-bit MODP Group 15 - https://tools.ietf.org/html/rfc3526#section-4 */ + 384, + "DH-3072", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH4096 +{ /* 4096-bit MODP Group 16 - https://tools.ietf.org/html/rfc3526#section-5 */ + 512, + "DH-4096", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + "FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH6144 +{ /* 6144-bit MODP Group 17 - https://tools.ietf.org/html/rfc3526#section-6 */ + 768, + "DH-6144", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH8192 +{ /* 8192-bit MODP Group 18 - https://tools.ietf.org/html/rfc3526#section-7 */ + 1024, + "DH-8192", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" +}, +#endif +{ + 0, + NULL, + NULL, + NULL +} +}; + +/** + Returns the DH group size (octets) for given key + @param key The DH key to get the size of + @return The group size in octets (0 on error) + */ +int dh_get_groupsize(const dh_key *key) +{ + if (key == NULL) return 0; + return mp_unsigned_bin_size(key->prime); +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_check_pubkey.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_check_pubkey.c new file mode 100644 index 0000000..7dd128e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_check_pubkey.c @@ -0,0 +1,55 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Check DH public key (INTERNAL ONLY, not part of public API) + @param key The key you wish to test + @return CRYPT_OK if successful +*/ +int dh_check_pubkey(const dh_key *key) +{ + void *p_minus1; + ltc_mp_digit digit; + int i, digit_count, bits_set = 0, err; + + LTC_ARGCHK(key != NULL); + + if ((err = mp_init(&p_minus1)) != CRYPT_OK) { + return err; + } + + /* avoid: y <= 1 OR y >= p-1 */ + if ((err = mp_sub_d(key->prime, 1, p_minus1)) != CRYPT_OK) { + goto error; + } + if (mp_cmp(key->y, p_minus1) != LTC_MP_LT || mp_cmp_d(key->y, 1) != LTC_MP_GT) { + err = CRYPT_INVALID_ARG; + goto error; + } + + /* public key must have more than one bit set */ + digit_count = mp_get_digit_count(key->y); + for (i = 0; i < digit_count && bits_set < 2; i++) { + digit = mp_get_digit(key->y, i); + while (digit > 0) { + if (digit & 1) bits_set++; + digit >>= 1; + } + } + if (bits_set > 1) { + err = CRYPT_OK; + } + else { + err = CRYPT_INVALID_ARG; + } + +error: + mp_clear(p_minus1); + return err; +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export.c new file mode 100644 index 0000000..19112c4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Export a DH key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the DH key + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key) +{ + unsigned char flags[1]; + int err; + unsigned long version = 0; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (type == PK_PRIVATE) { + /* export x - private key */ + flags[0] = 1; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } + else { + /* export y - public key */ + flags[0] = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL); + } + + return err; +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export_key.c new file mode 100644 index 0000000..374635c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_export_key.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Binary export a DH key to a buffer + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the DH key + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key) +{ + unsigned long len; + void *k; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + k = (type == PK_PRIVATE) ? key->x : key->y; + len = mp_unsigned_bin_size(k); + + if (*outlen < len) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = len; + + return mp_to_unsigned_bin(k, out); +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_free.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_free.c new file mode 100644 index 0000000..ff56b00 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_free.c @@ -0,0 +1,18 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Free the allocated ram for a DH key + @param key The key which you wish to free +*/ +void dh_free(dh_key *key) +{ + LTC_ARGCHKVD(key != NULL); + mp_cleanup_multi(&key->prime, &key->base, &key->y, &key->x, LTC_NULL); +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c new file mode 100644 index 0000000..c28246f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +static int s_dh_groupsize_to_keysize(int groupsize) +{ + /* The strength estimates from https://tools.ietf.org/html/rfc3526#section-8 + * We use "Estimate 2" to get an appropriate private key (exponent) size. + */ + if (groupsize <= 0) { + return 0; + } + if (groupsize <= 192) { + return 30; /* 1536-bit => key size 240-bit */ + } + if (groupsize <= 256) { + return 40; /* 2048-bit => key size 320-bit */ + } + if (groupsize <= 384) { + return 52; /* 3072-bit => key size 416-bit */ + } + if (groupsize <= 512) { + return 60; /* 4096-bit => key size 480-bit */ + } + if (groupsize <= 768) { + return 67; /* 6144-bit => key size 536-bit */ + } + if (groupsize <= 1024) { + return 77; /* 8192-bit => key size 616-bit */ + } + return 0; +} + +int dh_generate_key(prng_state *prng, int wprng, dh_key *key) +{ + unsigned char *buf; + unsigned long keysize; + int err, max_iterations = LTC_PK_MAX_RETRIES; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* good prng? */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + keysize = s_dh_groupsize_to_keysize(mp_unsigned_bin_size(key->prime)); + if (keysize == 0) { + err = CRYPT_INVALID_KEYSIZE; + goto freemp; + } + + /* allocate buffer */ + buf = XMALLOC(keysize); + if (buf == NULL) { + err = CRYPT_MEM; + goto freemp; + } + + key->type = PK_PRIVATE; + do { + /* make up random buf */ + if (prng_descriptor[wprng]->read(buf, keysize, prng) != keysize) { + err = CRYPT_ERROR_READPRNG; + goto freebuf; + } + /* load the x value - private key */ + if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { + goto freebuf; + } + /* compute the y value - public key */ + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { + goto freebuf; + } + err = dh_check_pubkey(key); + } while (err != CRYPT_OK && max_iterations-- > 0); + +freebuf: + zeromem(buf, keysize); + XFREE(buf); +freemp: + if (err != CRYPT_OK) dh_free(key); + return err; +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_import.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_import.c new file mode 100644 index 0000000..a067a32 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_import.c @@ -0,0 +1,89 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Import a DH key from a binary packet + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) +{ + unsigned char flags[1]; + int err; + unsigned long version; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + /* init */ + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* find out what type of key it is */ + err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, &flags, + LTC_ASN1_EOL, 0UL, NULL); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + goto error; + } + + if (version == 0) { + if (flags[0] == 1) { + key->type = PK_PRIVATE; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + /* compute public key: y = (base ^ x) mod prime */ + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { + goto error; + } + } + else if (flags[0] == 0) { + key->type = PK_PUBLIC; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + } + else { + err = CRYPT_INVALID_PACKET; + goto error; + } + } + else { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* check public key */ + if ((err = dh_check_pubkey(key)) != CRYPT_OK) { + goto error; + } + + return CRYPT_OK; + +error: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_make_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_make_key.c new file mode 100644 index 0000000..e122985 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_make_key.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * 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 "tomcrypt_private.h" +#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) +{ + int err = 0; + 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 */ + void *arg_mod = 0; + uint8_t *buf = 0; /* intermediate buffer to have a raw random */ + + /* + * Check the arguments + */ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->base != NULL); + LTC_ARGCHK(key->prime != 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->prime); + 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->prime; + + /* 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; + } + + /* 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; + } + + /* + * 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; + + /* generate the public key key->y */ + err = mp_exptmod(key->base, key->x, key->prime, 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; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set.c new file mode 100644 index 0000000..e25db08 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set.c @@ -0,0 +1,114 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Import DH key parts p and g from raw numbers + + @param p DH's p (prime) + @param plen DH's p's length + @param g DH's g (group) + @param glen DH's g's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int dh_set_pg(const unsigned char *p, unsigned long plen, + const unsigned char *g, unsigned long glen, + dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(g != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { + return err; + } + + if ((err = mp_read_unsigned_bin(key->base, (unsigned char*)g, glen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->prime, (unsigned char*)p, plen)) != CRYPT_OK) { goto LBL_ERR; } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +/** + Import DH key parts p and g from built-in DH groups + + @param groupsize The size of the DH group to use + @param key [out] Where the newly created DH key will be stored + @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. +*/ +int dh_set_pg_groupsize(int groupsize, dh_key *key) +{ + int err, i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(groupsize > 0); + + for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++); + if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE; + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +/** + Import DH public or private key part from raw numbers + + NB: The p & g parts must be set beforehand + + @param in The key-part to import, either public or private. + @param inlen The key-part's length + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (type == PK_PRIVATE) { + key->type = PK_PRIVATE; + if ((err = mp_read_unsigned_bin(key->x, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto LBL_ERR; } + } + else { + key->type = PK_PUBLIC; + if ((err = mp_read_unsigned_bin(key->y, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + } + + /* check public key */ + if ((err = dh_check_pubkey(key)) != CRYPT_OK) { + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c new file mode 100644 index 0000000..1f2fb3b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Import DH key parts p and g from dhparam + + dhparam data: openssl dhparam -outform DER -out dhparam.der 2048 + + @param dhparam The DH param DER encoded data + @param dhparamlen The length of dhparam data + @param key [out] Where the newly created DH key will be stored + @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. +*/ +int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(dhparam != NULL); + LTC_ARGCHK(dhparamlen > 0); + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { + return err; + } + if ((err = der_decode_sequence_multi(dhparam, dhparamlen, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_shared_secret.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_shared_secret.c new file mode 100644 index 0000000..0c4dfc9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/dh_shared_secret.c @@ -0,0 +1,70 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + 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 + @param out [out] The destination of the shared data + @param outlen [in/out] The max size and resulting size of the shared data. + @return CRYPT_OK if successful +*/ +int dh_shared_secret(const dh_key *private_key, const dh_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + void *tmp; + unsigned long x; + int err; + + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* types valid? */ + if (private_key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* same DH group? */ + if (mp_cmp(private_key->prime, public_key->prime) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } + if (mp_cmp(private_key->base, public_key->base) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } + + /* init big numbers */ + if ((err = mp_init(&tmp)) != CRYPT_OK) { + return err; + } + + /* check public key */ + if ((err = dh_check_pubkey(public_key)) != CRYPT_OK) { + goto error; + } + + /* compute tmp = y^x mod p */ + if ((err = mp_exptmod(public_key->y, private_key->x, private_key->prime, tmp)) != CRYPT_OK) { + goto error; + } + + /* enough space for output? */ + x = (unsigned long)mp_unsigned_bin_size(tmp); + if (*outlen < x) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { + goto error; + } + *outlen = x; + err = CRYPT_OK; + +error: + mp_clear(tmp); + return err; +} + +#endif /* LTC_MDH */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/sub.mk new file mode 100644 index 0000000..86f2d76 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dh/sub.mk @@ -0,0 +1,13 @@ +srcs-y += dh.c +cflags-dh.c-y += -Wno-unused-variable +srcs-y += dh_check_pubkey.c +srcs-y += dh_export.c +srcs-y += dh_export_key.c +srcs-y += dh_free.c +srcs-y += dh_generate_key.c +srcs-y += dh_import.c +srcs-y += dh_make_key.c +srcs-y += dh_set.c +srcs-y += dh_set_pg_dhparam.c +srcs-y += dh_shared_secret.c + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c new file mode 100644 index 0000000..c897023 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c @@ -0,0 +1,129 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, + const dsa_key *key) +{ + unsigned char *skey, *expt; + void *g_pub; + unsigned long x, y; + unsigned long hashOID[32] = { 0 }; + 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])); + err = der_decode_sequence(in, inlen, decode, 1); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + 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 = mp_unsigned_bin_size(key->p) + 1; + y = MIN(y, 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c new file mode 100644 index 0000000..eb49d1b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c @@ -0,0 +1,118 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, + const 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, LTC_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, LTC_NULL); + return CRYPT_MEM; + } + + /* make a random g_priv, g_pub = g^x pair + private key x should be in range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) + */ + if ((err = rand_bn_upto(g_priv, key->q, prng, wprng)) != 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, LTC_NULL); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c new file mode 100644 index 0000000..3550cbe --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c @@ -0,0 +1,100 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, const dsa_key *key) +{ + unsigned long zero=0; + unsigned char flags[1]; + int err, std; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = type & PK_STD; + type &= ~PK_STD; + + if (type == PK_PRIVATE && key->type != PK_PRIVATE) { + return CRYPT_PK_TYPE_MISMATCH; + } + + if (type == PK_PRIVATE) { + if (std) { + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } + flags[0] = 1; + 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); + } + + if (type == PK_PUBLIC) { + if (std) { + unsigned long tmplen = (unsigned long)(mp_count_bits(key->y) / 8) + 8; + unsigned char* tmp = XMALLOC(tmplen); + ltc_asn1_list int_list[3]; + + if (tmp == NULL) { + return CRYPT_MEM; + } + + err = der_encode_integer(key->y, tmp, &tmplen); + if (err != CRYPT_OK) { + goto error; + } + + LTC_SET_ASN1(int_list, 0, LTC_ASN1_INTEGER, key->p, 1UL); + LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL); + LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL); + + err = x509_encode_subject_public_key_info(out, outlen, LTC_OID_DSA, tmp, + tmplen, LTC_ASN1_SEQUENCE, int_list, + sizeof(int_list) / sizeof(int_list[0])); + +error: + XFREE(tmp); + return err; + } + flags[0] = 0; + 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); + } + + return CRYPT_INVALID_ARG; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c new file mode 100644 index 0000000..dbe8625 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, LTC_NULL); + key->type = key->qord = 0; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c new file mode 100644 index 0000000..bc83c0e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_make_key.c + DSA implementation, generate a DSA key +*/ + +#ifdef LTC_MDSA + +/** + Create a DSA key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key [in/out] Where to store the created key + @return CRYPT_OK if successful. +*/ +int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* 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 + */ + /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ + if ((err = rand_bn_upto(key->x, key->q, prng, wprng)) != CRYPT_OK) { return err; } + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; } + key->type = PK_PRIVATE; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c new file mode 100644 index 0000000..954362e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c @@ -0,0 +1,234 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_generate_pqg.c + DSA implementation - generate DSA parameters p, q & g +*/ + +#ifdef LTC_MDSA + +/** + Create DSA parameters (INTERNAL ONLY, not part of public API) + @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 p [out] bignum where generated 'p' is stored (must be initialized by caller) + @param q [out] bignum where generated 'q' is stored (must be initialized by caller) + @param g [out] bignum where generated 'g' is stored (must be initialized by caller) + @return CRYPT_OK if successful, upon error this function will free all allocated memory +*/ +static int s_dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) +{ + unsigned long L, N, n, outbytes, seedbytes, counter, j, i; + int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; + unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; + void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; + const char *accepted_hashes[] = { "sha3-512", "sha512", "sha3-384", "sha384", "sha3-256", "sha256" }; + + /* check size */ + if (group_size > LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size || modulus_size > LTC_MDSA_MAX_MODULUS) { + return CRYPT_INVALID_ARG; + } + + /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function + * + * L = The desired length of the prime p (in bits e.g. L = 1024) + * N = The desired length of the prime q (in bits e.g. N = 160) + * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N + * outlen = The bit length of Hash function + * + * 1. Check that the (L, N) + * 2. If (seedlen = 2^(L-1)) { + * Test whether or not p is prime as specified in Appendix C.3. + * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter + * } + * offset = offset + n + 1 Comment: Increment offset + * } + */ + + seedbytes = group_size; + L = (unsigned long)modulus_size * 8; + N = (unsigned long)group_size * 8; + + /* XXX-TODO no Lucas test */ +#ifdef LTC_MPI_HAS_LUCAS_TEST + /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ + mr_tests_p = (L <= 2048) ? 3 : 2; + if (N <= 160) { mr_tests_q = 19; } + else if (N <= 224) { mr_tests_q = 24; } + else { mr_tests_q = 27; } +#else + /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ + if (L <= 1024) { mr_tests_p = 40; } + else if (L <= 2048) { mr_tests_p = 56; } + else { mr_tests_p = 64; } + + if (N <= 160) { mr_tests_q = 40; } + else if (N <= 224) { mr_tests_q = 56; } + else { mr_tests_q = 64; } +#endif + + hash = -1; + for (i = 0; i < sizeof(accepted_hashes)/sizeof(accepted_hashes[0]); ++i) { + hash = find_hash(accepted_hashes[i]); + if (hash != -1) break; + } + if (hash == -1) { + return CRYPT_INVALID_ARG; /* no appropriate hash function found */ + } + if (N > hash_descriptor[hash]->hashsize * 8) { + return CRYPT_INVALID_ARG; /* group_size too big */ + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } + outbytes = hash_descriptor[hash]->hashsize; + + n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; + + if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } + if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } + + err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, LTC_NULL); + if (err != CRYPT_OK) { goto cleanup1; } + + if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } + /* t2L1 = 2^(L-1) */ + if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } + /* t2N1 = 2^(N-1) */ + if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } + /* t2seedlen = 2^seedlen */ + + for(found_p=0; !found_p;) { + /* q */ + for(found_q=0; !found_q;) { + if (prng_descriptor[wprng]->read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } + i = outbytes; + if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } + if (!mp_isodd(q)) mp_add_d(q, 1, q); + if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } + if (res == LTC_MP_YES) found_q = 1; + } + + /* p */ + if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } + for(counter=0; counter < 4*L && !found_p; counter++) { + for(j=0; j<=n; j++) { + if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } + /* seedinc = (seedinc+1) % 2^seed_bitlen */ + if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } + zeromem(sbuf, seedbytes); + if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } + i = outbytes; + err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); + if (err != CRYPT_OK) { goto cleanup; } + } + if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } + if (mp_cmp(p, t2L1) != LTC_MP_LT) { + /* p >= 2^(L-1) */ + if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } + if (res == LTC_MP_YES) { + found_p = 1; + } + } + } + } + + /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g + * 1. e = (p - 1)/q + * 2. h = any integer satisfying: 1 < h < (p - 1) + * h could be obtained from a random number generator or from a counter that changes after each use + * 3. g = h^e mod p + * 4. if (g == 1), then go to step 2. + * + */ + + if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } + /* e = (p - 1)/q */ + i = mp_count_bits(p); + do { + do { + if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } + } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT); + if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } + /* h is randon and 1 < h < (p-1) */ + if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } + } while (mp_cmp_d(g, 1) == LTC_MP_EQ); + + err = CRYPT_OK; +cleanup: + mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, LTC_NULL); +cleanup1: + XFREE(sbuf); +cleanup2: + XFREE(wbuf); +cleanup3: + return err; +} + +/** + Generate DSA parameters p, q & g + @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. +*/ +int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init mp_ints */ + if ((err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL)) != CRYPT_OK) { + return err; + } + /* generate params */ + err = s_dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g); + if (err != CRYPT_OK) { + goto cleanup; + } + + key->qord = group_size; + + return CRYPT_OK; + +cleanup: + dsa_free(key); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c new file mode 100644 index 0000000..995e0d2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c @@ -0,0 +1,143 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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) +{ + int err, stat; + unsigned long zero = 0, len; + unsigned char* tmpbuf = NULL; + unsigned char flags[1]; + + 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, LTC_NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + /* try to match the old libtomcrypt format */ + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_EOL, 0UL, NULL); + + if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) { + /* private key */ + 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 LBL_ERR; + } + key->type = PK_PRIVATE; + goto LBL_OK; + } + /* public key */ + else if (flags[0] == 0) { + 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 LBL_ERR; + } + key->type = PK_PUBLIC; + goto LBL_OK; + } + else { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } + /* get key type */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { + + key->type = PK_PRIVATE; + } else { /* public */ + ltc_asn1_list params[3]; + unsigned long tmpbuf_len = inlen; + + LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); + LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); + LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL); + + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } + + len = 3; + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_DSA, + tmpbuf, &tmpbuf_len, + LTC_ASN1_SEQUENCE, params, &len); + if (err != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; + } + + if ((err=der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; + } + + XFREE(tmpbuf); + key->type = PK_PUBLIC; + } + +LBL_OK: + key->qord = mp_unsigned_bin_size(key->q); + + /* quick p, q, g validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + /* validate x, y */ + if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; +LBL_ERR: + dsa_free(key); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c new file mode 100644 index 0000000..5a205b2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_make_key.c + DSA implementation, generate a DSA key +*/ + +#ifdef LTC_MDSA + +/** + Old-style creation of 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. +*/ +int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) +{ + int err; + + if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; } + if ((err = dsa_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c new file mode 100644 index 0000000..82b6033 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c @@ -0,0 +1,102 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +#ifdef LTC_MDSA + +/** + Import DSA's p, q & g from raw numbers + @param p DSA's p in binary representation + @param plen The length of p + @param q DSA's q in binary representation + @param qlen The length of q + @param g DSA's g in binary representation + @param glen The length of g + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_pqg(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + const unsigned char *g, unsigned long glen, + dsa_key *key) +{ + int err, stat; + + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(q != NULL); + LTC_ARGCHK(g != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); + if (err != CRYPT_OK) return err; + + if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)g , glen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->q, (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } + + key->qord = mp_unsigned_bin_size(key->q); + + /* do only a quick validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +/** + Import DSA public or private key-part from raw numbers + + NB: The p, q & g parts must be set beforehand + + @param in The key-part to import, either public or private. + @param inlen The key-part's length + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key) +{ + int err, stat = 0; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->x != NULL); + LTC_ARGCHK(key->y != NULL); + LTC_ARGCHK(key->p != NULL); + LTC_ARGCHK(key->g != NULL); + LTC_ARGCHK(key->q != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (type == PK_PRIVATE) { + key->type = PK_PRIVATE; + if ((err = mp_read_unsigned_bin(key->x, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto LBL_ERR; } + } + else { + key->type = PK_PUBLIC; + if ((err = mp_read_unsigned_bin(key->y, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + } + + if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c new file mode 100644 index 0000000..97c71f1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c @@ -0,0 +1,57 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +#ifdef LTC_MDSA + +/** + Import DSA's p, q & g from dsaparam + + dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048 + + @param dsaparam The DSA param DER encoded data + @param dsaparamlen The length of dhparam data + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, + dsa_key *key) +{ + int err, stat; + + LTC_ARGCHK(dsaparam != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); + if (err != CRYPT_OK) return err; + + if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + + key->qord = mp_unsigned_bin_size(key->q); + + /* quick p, q, g validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c new file mode 100644 index 0000000..df11c17 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c @@ -0,0 +1,60 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, + const 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c new file mode 100644 index 0000000..56baa80 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c @@ -0,0 +1,142 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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, const dsa_key *key) +{ + void *k, *kinv, *tmp; + unsigned char *buf; + int err, qbits; + + 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, LTC_NULL)) != CRYPT_OK) { goto ERRBUF; } + + qbits = mp_count_bits(key->q); +retry: + + do { + /* gen random k */ + if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK) { goto error; } + + /* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */ + if (mp_cmp_d(k, 0) != LTC_MP_GT || mp_cmp(k, key->q) != LTC_MP_LT) { 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; } + + /* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/ + inlen = MIN(inlen, (unsigned long)(key->qord)); + + /* 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, LTC_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, const 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, LTC_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, LTC_NULL); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c new file mode 100644 index 0000000..500feda --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c @@ -0,0 +1,127 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 DSA 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, const 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, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* neither r or s can be null or >q*/ + if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* FIPS 186-4 4.7: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash' */ + hashlen = MIN(hashlen, (unsigned long)(key->qord)); + + /* 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, LTC_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 DSA 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, const dsa_key *key) +{ + int err; + void *r, *s; + ltc_asn1_list sig_seq[2]; + unsigned long reallen = 0; + + LTC_ARGCHK(stat != NULL); + *stat = 0; /* must be set before the first return */ + + if ((err = mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) { + return err; + } + + LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL); + LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL); + + err = der_decode_sequence_strict(sig, siglen, sig_seq, 2); + if (err != CRYPT_OK) { + goto LBL_ERR; + } + + err = der_length_sequence(sig_seq, 2, &reallen); + if (err != CRYPT_OK || reallen != siglen) { + goto LBL_ERR; + } + + /* do the op */ + err = dsa_verify_hash_raw(r, s, hash, hashlen, stat, key); + +LBL_ERR: + mp_clear_multi(r, s, LTC_NULL); + return err; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c new file mode 100644 index 0000000..50d566a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c @@ -0,0 +1,189 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_verify_key.c + DSA implementation, verify a key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Validate a DSA key + + Yeah, this function should've been called dsa_validate_key() + in the first place and for compat-reasons we keep it + as it was (for now). + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_verify_key(const dsa_key *key, int *stat) +{ + int err; + + err = dsa_int_validate_primes(key, stat); + if (err != CRYPT_OK || *stat == 0) return err; + + err = dsa_int_validate_pqg(key, stat); + if (err != CRYPT_OK || *stat == 0) return err; + + return dsa_int_validate_xy(key, stat); +} + +/** + Non-complex part (no primality testing) of the validation + of DSA params (p, q, g) + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_pqg(const dsa_key *key, int *stat) +{ + void *tmp1, *tmp2; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + *stat = 0; + + /* check q-order */ + 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 ) { + return CRYPT_OK; + } + + /* FIPS 186-4 chapter 4.1: 1 < g < p */ + if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) { + return CRYPT_OK; + } + + if ((err = mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; } + + /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */ + if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; } + if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; } + if (mp_iszero(tmp2) != LTC_MP_YES) { + err = CRYPT_OK; + goto error; + } + + /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in + * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1 + */ + if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; } + if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + + err = CRYPT_OK; + *stat = 1; +error: + mp_clear_multi(tmp2, tmp1, LTC_NULL); + return err; +} + +/** + Primality testing of DSA params p and q + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_primes(const dsa_key *key, int *stat) +{ + int err, res; + + *stat = 0; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* key->q prime? */ + if ((err = mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { + return err; + } + if (res == LTC_MP_NO) { + return CRYPT_OK; + } + + /* key->p prime? */ + if ((err = mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { + return err; + } + if (res == LTC_MP_NO) { + return CRYPT_OK; + } + + *stat = 1; + return CRYPT_OK; +} + +/** + Validation of a DSA key (x and y values) + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_xy(const dsa_key *key, int *stat) +{ + void *tmp; + int err; + + *stat = 0; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* 1 < y < p-1 */ + if ((err = mp_init(&tmp)) != CRYPT_OK) { + return err; + } + if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) { + goto error; + } + if (mp_cmp_d(key->y, 1) != LTC_MP_GT || mp_cmp(key->y, tmp) != LTC_MP_LT) { + err = CRYPT_OK; + goto error; + } + + if (key->type == PK_PRIVATE) { + /* FIPS 186-4 chapter 4.1: 0 < x < q */ + if (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT) { + err = CRYPT_OK; + goto error; + } + /* FIPS 186-4 chapter 4.1: y = g^x mod p */ + if ((err = mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) { + goto error; + } + if (mp_cmp(tmp, key->y) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + } + else { + /* with just a public key we cannot test y = g^x mod p therefore we + * only test that y^q mod p = 1, which makes sure y is 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; + } + } + + err = CRYPT_OK; + *stat = 1; +error: + mp_clear(tmp); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/sub.mk new file mode 100644 index 0000000..d0b29e5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/dsa/sub.mk @@ -0,0 +1,12 @@ +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_generate_key.c +srcs-y += dsa_generate_pqg.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/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c new file mode 100644 index 0000000..e1efb30 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ec25519_crypto_ctx.c + curve25519 crypto context helper +*/ + +#ifdef LTC_CURVE25519 + +int ec25519_crypto_ctx(unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen) +{ + unsigned char *buf = out; + + const char *prefix = "SigEd25519 no Ed25519 collisions"; + const unsigned long prefix_len = XSTRLEN(prefix); + const unsigned char ctxlen8 = (unsigned char)ctxlen; + + if (ctxlen > 255u) return CRYPT_INPUT_TOO_LONG; + if (*outlen < prefix_len + 2u + ctxlen) return CRYPT_BUFFER_OVERFLOW; + + XMEMCPY(buf, prefix, prefix_len); + buf += prefix_len; + XMEMCPY(buf, &flag, 1); + buf++; + XMEMCPY(buf, &ctxlen8, 1); + buf++; + + if (ctxlen > 0u) { + LTC_ARGCHK(ctx != NULL); + XMEMCPY(buf, ctx, ctxlen); + buf += ctxlen; + } + + *outlen = buf-out; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c new file mode 100644 index 0000000..42f4c4b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ec25519_export.c + Generic export of a Curve/Ed25519 key to a binary packet, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Generic export of a Curve/Ed25519 key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the Ed25519 key + @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int ec25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key) +{ + int err, std; + const char* OID; + unsigned long oid[16], oidlen; + ltc_asn1_list alg_id[1]; + unsigned char private_key[34]; + unsigned long version, private_key_len = sizeof(private_key); + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = which & PK_STD; + which &= ~PK_STD; + + if (which == PK_PRIVATE) { + if(key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + + if (std == PK_STD) { + if ((err = pk_get_oid(key->algo, &OID)) != CRYPT_OK) { + return err; + } + oidlen = sizeof(oid)/sizeof(oid[0]); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + return err; + } + + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + + /* encode private key as PKCS#8 */ + if ((err = der_encode_octet_string(key->priv, 32uL, private_key, &private_key_len)) != CRYPT_OK) { + return err; + } + + version = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1uL, &version, + LTC_ASN1_SEQUENCE, 1uL, alg_id, + LTC_ASN1_OCTET_STRING, private_key_len, private_key, + LTC_ASN1_EOL, 0uL, NULL); + } else { + if (*outlen < sizeof(key->priv)) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + XMEMCPY(out, key->priv, sizeof(key->priv)); + err = CRYPT_OK; + } + *outlen = sizeof(key->priv); + } + } else { + if (std == PK_STD) { + /* encode public key as SubjectPublicKeyInfo */ + err = x509_encode_subject_public_key_info(out, outlen, key->algo, key->pub, 32uL, LTC_ASN1_EOL, NULL, 0); + } else { + if (*outlen < sizeof(key->pub)) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + XMEMCPY(out, key->pub, sizeof(key->pub)); + err = CRYPT_OK; + } + *outlen = sizeof(key->pub); + } + } + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c new file mode 100644 index 0000000..13807ab --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ec25519_import_pkcs8.c + Generic import of a Curve/Ed25519 private key in PKCS#8 format, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Generic import of a Curve/Ed25519 private key in PKCS#8 format + @param in The DER-encoded PKCS#8-formatted private key + @param inlen The length of the input data + @param passwd The password to decrypt the private key + @param passwdlen Password's length (octets) + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + enum ltc_oid_id id, sk_to_pk fp, + curve25519_key *key) +{ + int err; + ltc_asn1_list *l = NULL; + const char *oid; + ltc_asn1_list alg_id[1]; + unsigned char private_key[34]; + unsigned long version, key_len; + unsigned long tmpoid[16]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(fp != NULL); + + if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) { + + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid) / sizeof(tmpoid[0])); + + key_len = sizeof(private_key); + if ((err = der_decode_sequence_multi(l->data, l->size, + LTC_ASN1_SHORT_INTEGER, 1uL, &version, + LTC_ASN1_SEQUENCE, 1uL, alg_id, + LTC_ASN1_OCTET_STRING, key_len, private_key, + LTC_ASN1_EOL, 0uL, NULL)) + != CRYPT_OK) { + /* If there are attributes added after the private_key it is tagged with version 1 and + * we get an 'input too long' error but the rest is already decoded and can be + * handled the same as for version 0 + */ + if ((err == CRYPT_INPUT_TOO_LONG) && (version == 1)) { + version = 0; + } else { + goto out; + } + } + + if ((err = pk_get_oid(id, &oid)) != CRYPT_OK) { + goto out; + } + if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) { + goto out; + } + + if (version == 0) { + key_len = sizeof(key->priv); + if ((err = der_decode_octet_string(private_key, sizeof(private_key), key->priv, &key_len)) == CRYPT_OK) { + fp(key->pub, key->priv); + key->type = PK_PRIVATE; + key->algo = id; + } + } else { + err = CRYPT_PK_INVALID_TYPE; + } + } +out: + if (l) der_free_sequence_flexi(l); +#ifdef LTC_CLEAN_STACK + zeromem(private_key, sizeof(private_key)); +#endif + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/sub.mk new file mode 100644 index 0000000..5040c39 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/sub.mk @@ -0,0 +1,3 @@ +srcs-y += ec25519_crypto_ctx.c +srcs-y += ec25519_export.c +srcs-y += tweetnacl.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c new file mode 100644 index 0000000..ad0a7c6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c @@ -0,0 +1,491 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/* automatically generated file, do not edit */ + +#define FOR(i,n) for (i = 0;i < n;++i) +#define sv static void + +typedef unsigned char u8; +typedef ulong32 u32; +typedef ulong64 u64; +typedef long64 i64; +typedef i64 gf[16]; + +static const u8 + nine[32] = {9}; +static const gf + gf0, + gf1 = {1}, + gf121665 = {0xDB41,1}, + D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, + D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, + X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, + Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}, + I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; + +static int vn(const u8 *x,const u8 *y,int n) +{ + int i; + u32 d = 0; + FOR(i,n) d |= x[i]^y[i]; + return (1 & ((d - 1) >> 8)) - 1; +} + +static int tweetnacl_crypto_verify_32(const u8 *x,const u8 *y) +{ + return vn(x,y,32); +} + +sv set25519(gf r, const gf a) +{ + int i; + FOR(i,16) r[i]=a[i]; +} + +sv car25519(gf o) +{ + int i; + i64 c; + FOR(i,16) { + o[i]+=(1LL<<16); + c=o[i]>>16; + o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); + o[i]-=c<<16; + } +} + +sv sel25519(gf p,gf q,int b) +{ + i64 t,i,c=~(b-1); + FOR(i,16) { + t= c&(p[i]^q[i]); + p[i]^=t; + q[i]^=t; + } +} + +sv pack25519(u8 *o,const gf n) +{ + int i,j,b; + gf m,t; + FOR(i,16) t[i]=n[i]; + car25519(t); + car25519(t); + car25519(t); + FOR(j,2) { + m[0]=t[0]-0xffed; + for(i=1;i<15;i++) { + m[i]=t[i]-0xffff-((m[i-1]>>16)&1); + m[i-1]&=0xffff; + } + m[15]=t[15]-0x7fff-((m[14]>>16)&1); + b=(m[15]>>16)&1; + m[14]&=0xffff; + sel25519(t,m,1-b); + } + FOR(i,16) { + o[2*i]=t[i]&0xff; + o[2*i+1]=t[i]>>8; + } +} + +static int neq25519(const gf a, const gf b) +{ + u8 c[32],d[32]; + pack25519(c,a); + pack25519(d,b); + return tweetnacl_crypto_verify_32(c,d); +} + +static u8 par25519(const gf a) +{ + u8 d[32]; + pack25519(d,a); + return d[0]&1; +} + +sv unpack25519(gf o, const u8 *n) +{ + int i; + FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8); + o[15]&=0x7fff; +} + +sv A(gf o,const gf a,const gf b) +{ + int i; + FOR(i,16) o[i]=a[i]+b[i]; +} + +sv Z(gf o,const gf a,const gf b) +{ + int i; + FOR(i,16) o[i]=a[i]-b[i]; +} + +sv M(gf o,const gf a,const gf b) +{ + i64 i,j,t[31]; + FOR(i,31) t[i]=0; + FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j]; + FOR(i,15) t[i]+=38*t[i+16]; + FOR(i,16) o[i]=t[i]; + car25519(o); + car25519(o); +} + +sv S(gf o,const gf a) +{ + M(o,a,a); +} + +sv inv25519(gf o,const gf i) +{ + gf c; + int a; + FOR(a,16) c[a]=i[a]; + for(a=253;a>=0;a--) { + S(c,c); + if(a!=2&&a!=4) M(c,c,i); + } + FOR(a,16) o[a]=c[a]; +} + +sv pow2523(gf o,const gf i) +{ + gf c; + int a; + FOR(a,16) c[a]=i[a]; + for(a=250;a>=0;a--) { + S(c,c); + if(a!=1) M(c,c,i); + } + FOR(a,16) o[a]=c[a]; +} + +int tweetnacl_crypto_scalarmult(u8 *q,const u8 *n,const u8 *p) +{ + u8 z[32]; + i64 x[80],r,i; + gf a,b,c,d,e,f; + FOR(i,31) z[i]=n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + FOR(i,16) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for(i=254;i>=0;--i) { + r=(z[i>>3]>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,gf121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + FOR(i,16) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + inv25519(x+32,x+32); + M(x+16,x+16,x+32); + pack25519(q,x+16); + return 0; +} + +int tweetnacl_crypto_scalarmult_base(u8 *q,const u8 *n) +{ + return tweetnacl_crypto_scalarmult(q,n,nine); +} + +static LTC_INLINE int tweetnacl_crypto_hash_ctx(u8 *out,const u8 *m,u64 n,const u8 *ctx,u32 cs) +{ + unsigned long len = 64; + int hash_idx = find_hash("sha512"); + + if (n > ULONG_MAX) return CRYPT_OVERFLOW; + + if(cs == 0) + return hash_memory(hash_idx, m, n, out, &len); + + return hash_memory_multi(hash_idx, out, &len, ctx, cs, m, n, LTC_NULL); +} + +static LTC_INLINE int tweetnacl_crypto_hash(u8 *out,const u8 *m,u64 n) +{ + return tweetnacl_crypto_hash_ctx(out, m, n, NULL, 0); +} + +sv add(gf p[4],gf q[4]) +{ + gf a,b,c,d,t,e,f,g,h; + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +sv cswap(gf p[4],gf q[4],u8 b) +{ + int i; + FOR(i,4) + sel25519(p[i],q[i],b); +} + +sv pack(u8 *r,gf p[4]) +{ + gf tx, ty, zi; + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +sv scalarmult(gf p[4],gf q[4],const u8 *s) +{ + int i; + set25519(p[0],gf0); + set25519(p[1],gf1); + set25519(p[2],gf1); + set25519(p[3],gf0); + for (i = 255;i >= 0;--i) { + u8 b = (s[i/8]>>(i&7))&1; + cswap(p,q,b); + add(q,p); + add(p,p); + cswap(p,q,b); + } +} + +sv scalarbase(gf p[4],const u8 *s) +{ + gf q[4]; + set25519(q[0],X); + set25519(q[1],Y); + set25519(q[2],gf1); + M(q[3],X,Y); + scalarmult(p,q,s); +} + +int tweetnacl_crypto_sk_to_pk(u8 *pk, const u8 *sk) +{ + u8 d[64]; + gf p[4]; + tweetnacl_crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p,d); + pack(pk,p); + + return 0; +} + +int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, u8 *pk, u8 *sk) +{ + int err; + + /* randombytes(sk,32); */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (prng_descriptor[wprng]->read(sk,32, prng) != 32) { + return CRYPT_ERROR_READPRNG; + } + + if ((err = tweetnacl_crypto_sk_to_pk(pk, sk)) != CRYPT_OK) { + return err; + } + + /* FOR(i,32) sk[32 + i] = pk[i]; + * we don't copy the pk in the sk */ + return CRYPT_OK; +} + +static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; + +sv modL(u8 *r,i64 x[64]) +{ + i64 carry,i,j; + for (i = 63;i >= 32;--i) { + carry = 0; + for (j = i - 32;j < i - 12;++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = (x[j] + 128) >> 8; + x[j] -= carry << 8; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + FOR(j,32) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + FOR(j,32) x[j] -= carry * L[j]; + FOR(i,32) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +sv reduce(u8 *r) +{ + i64 x[64],i; + FOR(i,64) x[i] = (u64) r[i]; + FOR(i,64) r[i] = 0; + modL(r,x); +} + +int tweetnacl_crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 mlen,const u8 *sk,const u8 *pk, const u8 *ctx, u64 cs) +{ + u8 d[64],h[64],r[64]; + i64 i,j,x[64]; + gf p[4]; + + tweetnacl_crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + *smlen = mlen+64; + FOR(i,(i64)mlen) sm[64 + i] = m[i]; + FOR(i,32) sm[32 + i] = d[32 + i]; + + tweetnacl_crypto_hash_ctx(r, sm+32, mlen+32,ctx,cs); + reduce(r); + scalarbase(p,r); + pack(sm,p); + + FOR(i,32) sm[i+32] = pk[i]; + tweetnacl_crypto_hash_ctx(h,sm,mlen + 64,ctx,cs); + reduce(h); + + FOR(i,64) x[i] = 0; + FOR(i,32) x[i] = (u64) r[i]; + FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; + modL(sm + 32,x); + + return 0; +} + +static int unpackneg(gf r[4],const u8 p[32]) +{ + gf t, chk, num, den, den2, den4, den6; + set25519(r[2],gf1); + unpack25519(r[1],p); + S(num,r[1]); + M(den,num,D); + Z(num,num,r[2]); + A(den,r[2],den); + + S(den2,den); + S(den4,den2); + M(den6,den4,den2); + M(t,den6,num); + M(t,t,den); + + pow2523(t,t); + M(t,t,num); + M(t,t,den); + M(t,t,den); + M(r[0],t,den); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) M(r[0],r[0],I); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]); + + M(r[3],r[0],r[1]); + return 0; +} + +int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen,const u8 *ctx,u64 cs,const u8 *pk) +{ + u64 i; + u8 s[32],t[32],h[64]; + gf p[4],q[4]; + + *stat = 0; + if (*mlen < smlen) return CRYPT_BUFFER_OVERFLOW; + *mlen = -1; + if (smlen < 64) return CRYPT_INVALID_ARG; + + if (unpackneg(q,pk)) return CRYPT_ERROR; + + XMEMMOVE(m,sm,smlen); + XMEMMOVE(s,m + 32,32); + XMEMMOVE(m + 32,pk,32); + tweetnacl_crypto_hash_ctx(h,m,smlen,ctx,cs); + reduce(h); + scalarmult(p,q,h); + + scalarbase(q,s); + add(p,q); + pack(t,p); + + smlen -= 64; + if (tweetnacl_crypto_verify_32(sm, t)) { + FOR(i,smlen) m[i] = 0; + zeromem(m, smlen); + return CRYPT_OK; + } + + *stat = 1; + XMEMMOVE(m,m + 64,smlen); + *mlen = smlen; + return CRYPT_OK; +} + +int tweetnacl_crypto_ph(u8 *out,const u8 *msg,u64 msglen) +{ + return tweetnacl_crypto_hash(out, msg, msglen); +} diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc.c new file mode 100644 index 0000000..5132e0c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc.c @@ -0,0 +1,447 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/* This array holds the curve parameters. + * Curves (prime field only) are taken from: + * - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*) + * - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*) + * - ANS X9.62 (named: PRIMEP*) + * - http://www.ecc-brainpool.org/download/Domain-parameters.pdf (named: BRAINPOOLP*) + */ +const ltc_ecc_curve ltc_ecc_curves[] = { +#ifdef LTC_ECC_SECP112R1 +{ + /* prime */ "DB7C2ABF62E35E668076BEAD208B", + /* A */ "DB7C2ABF62E35E668076BEAD2088", + /* B */ "659EF8BA043916EEDE8911702B22", + /* order */ "DB7C2ABF62E35E7628DFAC6561C5", + /* Gx */ "09487239995A5EE76B55F9C2F098", + /* Gy */ "A89CE5AF8724C0A23E0E0FF77500", + /* cofactor */ 1, + /* OID */ "1.3.132.0.6" +}, +#endif +#ifdef LTC_ECC_SECP112R2 +{ + /* prime */ "DB7C2ABF62E35E668076BEAD208B", + /* A */ "6127C24C05F38A0AAAF65C0EF02C", + /* B */ "51DEF1815DB5ED74FCC34C85D709", + /* order */ "36DF0AAFD8B8D7597CA10520D04B", + /* Gx */ "4BA30AB5E892B4E1649DD0928643", + /* Gy */ "ADCD46F5882E3747DEF36E956E97", + /* cofactor */ 4, + /* OID */ "1.3.132.0.7" +}, +#endif +#ifdef LTC_ECC_SECP128R1 +{ + /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", + /* B */ "E87579C11079F43DD824993C2CEE5ED3", + /* order */ "FFFFFFFE0000000075A30D1B9038A115", + /* Gx */ "161FF7528B899B2D0C28607CA52C5B86", + /* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83", + /* cofactor */ 1, + /* OID */ "1.3.132.0.28" +}, +#endif +#ifdef LTC_ECC_SECP128R2 +{ + /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + /* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1", + /* B */ "5EEEFCA380D02919DC2C6558BB6D8A5D", + /* order */ "3FFFFFFF7FFFFFFFBE0024720613B5A3", + /* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140", + /* Gy */ "27B6916A894D3AEE7106FE805FC34B44", + /* cofactor */ 4, + /* OID */ "1.3.132.0.29" +}, +#endif +#ifdef LTC_ECC_SECP160R1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", + /* B */ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", + /* order */ "0100000000000000000001F4C8F927AED3CA752257", + /* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82", + /* Gy */ "23A628553168947D59DCC912042351377AC5FB32", + /* cofactor */ 1, + /* OID */ "1.3.132.0.8" +}, +#endif +#ifdef LTC_ECC_SECP160R2 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", + /* B */ "B4E134D3FB59EB8BAB57274904664D5AF50388BA", + /* order */ "0100000000000000000000351EE786A818F3A1A16B", + /* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D", + /* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", + /* cofactor */ 1, + /* OID */ "1.3.132.0.30" +}, +#endif +#ifdef LTC_ECC_SECP160K1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + /* A */ "0000000000000000000000000000000000000000", + /* B */ "0000000000000000000000000000000000000007", + /* order */ "0100000000000000000001B8FA16DFAB9ACA16B6B3", + /* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", + /* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE", + /* cofactor */ 1, + /* OID */ "1.3.132.0.9" +}, +#endif +#ifdef LTC_ECC_SECP192R1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + /* B */ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", + /* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", + /* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.1" +}, +#endif +#ifdef LTC_ECC_PRIME192V2 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + /* B */ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", + /* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", + /* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.2" +}, +#endif +#ifdef LTC_ECC_PRIME192V3 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + /* B */ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", + /* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", + /* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.3" +}, +#endif +#ifdef LTC_ECC_SECP192K1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", + /* A */ "000000000000000000000000000000000000000000000000", + /* B */ "000000000000000000000000000000000000000000000003", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", + /* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", + /* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", + /* cofactor */ 1, + /* OID */ "1.3.132.0.31" +}, +#endif +#ifdef LTC_ECC_SECP224R1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", + /* B */ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + /* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", + /* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + /* cofactor */ 1, + /* OID */ "1.3.132.0.33" +}, +#endif +#ifdef LTC_ECC_SECP224K1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", + /* A */ "00000000000000000000000000000000000000000000000000000000", + /* B */ "00000000000000000000000000000000000000000000000000000005", + /* order */ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", + /* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", + /* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", + /* cofactor */ 1, + /* OID */ "1.3.132.0.32" +}, +#endif +#ifdef LTC_ECC_SECP256R1 +{ + /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.7" +}, +#endif +#ifdef LTC_ECC_SECP256K1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + /* A */ "0000000000000000000000000000000000000000000000000000000000000000", + /* B */ "0000000000000000000000000000000000000000000000000000000000000007", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + /* cofactor */ 1, + /* OID */ "1.3.132.0.10" +}, +#endif +#ifdef LTC_ECC_SECP384R1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + /* cofactor */ 1, + /* OID */ "1.3.132.0.34" +}, +#endif +#ifdef LTC_ECC_SECP521R1 +{ + /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + /* cofactor */ 1, + /* OID */ "1.3.132.0.35" +}, +#endif +#ifdef LTC_ECC_PRIME239V1 +{ + /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + /* B */ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", + /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", + /* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", + /* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.4" +}, +#endif +#ifdef LTC_ECC_PRIME239V2 +{ + /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + /* B */ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", + /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", + /* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", + /* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.5" +}, +#endif +#ifdef LTC_ECC_PRIME239V3 +{ + /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + /* B */ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", + /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", + /* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", + /* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.6" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP160R1 +{ + /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", + /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", + /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58", + /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", + /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", + /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.1" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP192R1 +{ + /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", + /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", + /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", + /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", + /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", + /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.3" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP224R1 +{ + /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", + /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", + /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", + /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.5" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP256R1 +{ + /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + /* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + /* B */ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + /* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", + /* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.7" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP320R1 +{ + /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", + /* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", + /* B */ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", + /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", + /* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", + /* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.9" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP384R1 +{ + /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + /* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + /* B */ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + /* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", + /* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.11" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP512R1 +{ + /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + /* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + /* B */ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + /* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", + /* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.13" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP160T1 +{ + /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", + /* A */ "E95E4A5F737059DC60DFC7AD95B3D8139515620C", + /* B */ "7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", + /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", + /* Gx */ "B199B13B9B34EFC1397E64BAEB05ACC265FF2378", + /* Gy */ "ADD6718B7C7C1961F0991B842443772152C9E0AD", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.2" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP192T1 +{ + /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", + /* A */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", + /* B */ "13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", + /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", + /* Gx */ "3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129", + /* Gy */ "097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.4" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP224T1 +{ + /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + /* A */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", + /* B */ "4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", + /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + /* Gx */ "6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580", + /* Gy */ "0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.6" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP256T1 +{ + /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + /* A */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", + /* B */ "662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", + /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + /* Gx */ "A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", + /* Gy */ "2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.8" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP320T1 +{ + /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", + /* A */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", + /* B */ "A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", + /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", + /* Gx */ "925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52", + /* Gy */ "63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.10" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP384T1 +{ + /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + /* A */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", + /* B */ "7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", + /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + /* Gx */ "18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", + /* Gy */ "25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.12" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP512T1 +{ + /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + /* A */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", + /* B */ "7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", + /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + /* Gx */ "640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", + /* Gy */ "5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.14" +}, +#endif +#ifdef LTC_ECC_SM2 +{ + /* prime */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", + /* B */ "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", + /* order */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", + /* Gx */ "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", + /* Gy */ "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", + /* cofactor */ 1, + /* OID */ "1.2.156.10197.1.301" +}, +#endif +{ + NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL +} +}; + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c new file mode 100644 index 0000000..472e1b5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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(const ecc_key *key, unsigned char *out, unsigned long *outlen) +{ + return ecc_get_key(out, outlen, PK_PUBLIC, key); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c new file mode 100644 index 0000000..58eb27d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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, const ltc_ecc_curve *cu) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + /* must be odd */ + if ((inlen & 1) == 0) { + return CRYPT_INVALID_ARG; + } + + /* initialize key->dp */ + if (cu == NULL) { + /* this case works only for uncompressed public keys */ + if ((err = ecc_set_curve_by_size((inlen-1)>>1, key)) != CRYPT_OK) { return err; } + } + else { + /* this one works for both compressed / uncompressed pubkeys */ + if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; } + } + + /* load public key */ + if ((err = ecc_set_key((unsigned char *)in, inlen, PK_PUBLIC, key)) != CRYPT_OK) { return err; } + + /* we're done */ + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c new file mode 100644 index 0000000..ad2d9b1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c @@ -0,0 +1,133 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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, + const ecc_key *key) +{ + unsigned char *ecc_shared, *skey, *pub_expt; + unsigned long x, y; + unsigned long hashOID[32] = { 0 }; + 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])); + err = der_decode_sequence(in, inlen, decode, 1); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + 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_copy_curve(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } + + /* make shared key */ + x = ECC_BUF_SIZE; + 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 + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c new file mode 100644 index 0000000..be24253 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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, + const 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); + + 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_copy_curve(key, &pubkey)) != CRYPT_OK) { return err; } + if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; } + + pub_expt = XMALLOC(ECC_BUF_SIZE); + ecc_shared = XMALLOC(ECC_BUF_SIZE); + 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 (ltc_mp.sqrtmod_prime != NULL) { + /* PK_COMPRESSED requires sqrtmod_prime */ + err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey); + } + else { + err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey); + } + if (err != 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c new file mode 100644 index 0000000..edbe4c3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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, const 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; + } + + /* 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export_openssl.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export_openssl.c new file mode 100644 index 0000000..2e89996 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_export_openssl.c @@ -0,0 +1,167 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#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_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) +{ + int err; + void *prime, *order, *a, *b, *gx, *gy; + unsigned char bin_a[256], bin_b[256], bin_k[256], bin_g[512], bin_xy[512]; + unsigned long len_a, len_b, len_k, len_g, len_xy; + unsigned long cofactor, one = 1; + const char *OID; + unsigned long oid[16], oidlen; + ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], pub_xy, ecparams; + int flag_oid = type & PK_CURVEOID ? 1 : 0; + int flag_com = type & PK_COMPRESSED ? 1 : 0; + int flag_pri = type & PK_PRIVATE ? 1 : 0; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH; + + if (flag_oid) { + /* http://tools.ietf.org/html/rfc5912 + ECParameters ::= CHOICE { + namedCurve CURVE.&id({NamedCurve}) # OBJECT + } + */ + if (key->dp.oidlen == 0) { err = CRYPT_INVALID_ARG; goto error; } + LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen); + } + else { + prime = key->dp.prime; + order = key->dp.order; + a = key->dp.A; + b = key->dp.B; + gx = key->dp.base.x; + gy = key->dp.base.y; + cofactor = key->dp.cofactor; + + /* curve param a */ + len_a = mp_unsigned_bin_size(a); + if (len_a > sizeof(bin_a)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } + if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK) { goto error; } + if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */ + + /* curve param b */ + len_b = mp_unsigned_bin_size(b); + if (len_b > sizeof(bin_b)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } + if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) { goto error; } + if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */ + + /* base point - (un)compressed based on flag_com */ + len_g = sizeof(bin_g); + err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com); + if (err != CRYPT_OK) { goto error; } + + /* we support only prime-field EC */ + if ((err = pk_get_oid(LTC_OID_EC_PRIMEF, &OID)) != CRYPT_OK) { goto error; } + + /* http://tools.ietf.org/html/rfc3279 + ECParameters ::= SEQUENCE { # SEQUENCE + version INTEGER { ecpVer1(1) } (ecpVer1) # INTEGER :01 + FieldID ::= SEQUENCE { # SEQUENCE + fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field + parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER + } + Curve ::= SEQUENCE { # SEQUENCE + a FieldElement ::= OCTET STRING # OCTET STRING + b FieldElement ::= OCTET STRING # OCTET STRING + seed BIT STRING OPTIONAL + } + base ECPoint ::= OCTET STRING # OCTET STRING + order INTEGER, # INTEGER + cofactor INTEGER OPTIONAL # INTEGER + } + */ + + oidlen = sizeof(oid)/sizeof(oid[0]); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + goto error; + } + + /* FieldID SEQUENCE */ + LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); + + /* Curve SEQUENCE */ + LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, len_a); + LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, len_b); + + /* ECParameters SEQUENCE */ + LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL); + LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); + LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 2UL); + LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, len_g); + LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); + LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); + + /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */ + LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); + } + + /* public key - (un)compressed based on flag_com */ + len_xy = sizeof(bin_xy); + err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com); + if (err != CRYPT_OK) { + goto error; + } + + if (flag_pri) { + + /* http://tools.ietf.org/html/rfc5915 + ECPrivateKey ::= SEQUENCE { # SEQUENCE + version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1) # INTEGER :01 + privateKey OCTET STRING, # OCTET STRING + [0] ECParameters # see above + [1] publicKey # BIT STRING + } + */ + + /* private key */ + len_k = mp_unsigned_bin_size(key->k); + if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } + if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) { goto error; } + + LTC_SET_ASN1(&pub_xy, 0, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy); + LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1); + LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k); + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, &ecparams); /* context specific 0 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, &pub_xy); /* context specific 1 */ + + err = der_encode_sequence(seq_priv, 4, out, outlen); + } + else { + /* http://tools.ietf.org/html/rfc5480 + SubjectPublicKeyInfo ::= SEQUENCE { # SEQUENCE + AlgorithmIdentifier ::= SEQUENCE { # SEQUENCE + algorithm OBJECT IDENTIFIER # OBJECT :id-ecPublicKey + ECParameters # see above + } + subjectPublicKey BIT STRING # BIT STRING + } + */ + err = x509_encode_subject_public_key_info( out, outlen, LTC_OID_EC, bin_xy, len_xy, + ecparams.type, ecparams.data, ecparams.size ); + } + +error: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c new file mode 100644 index 0000000..3a01f9f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c @@ -0,0 +1,247 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +static const struct { + const char *OID; + const char *names[6]; +} s_curve_names[] = { +#ifdef LTC_ECC_SECP112R1 + { + "1.3.132.0.6", { "SECP112R1", "ECC-112", NULL } + }, +#endif +#ifdef LTC_ECC_SECP112R2 + { + "1.3.132.0.7", { "SECP112R2", NULL } + }, +#endif +#ifdef LTC_ECC_SECP128R1 + { + "1.3.132.0.28", { "SECP128R1", "ECC-128", NULL } + }, +#endif +#ifdef LTC_ECC_SECP128R2 + { + "1.3.132.0.29", { "SECP128R2", NULL } + }, +#endif +#ifdef LTC_ECC_SECP160R1 + { + "1.3.132.0.8", { "SECP160R1", "ECC-160", NULL } + }, +#endif +#ifdef LTC_ECC_SECP160R2 + { + "1.3.132.0.30", { "SECP160R2", NULL } + }, +#endif +#ifdef LTC_ECC_SECP160K1 + { + "1.3.132.0.9", { "SECP160K1", NULL } + }, +#endif +#ifdef LTC_ECC_SECP192R1 + { + "1.2.840.10045.3.1.1", { "SECP192R1", "NISTP192", "PRIME192V1", "ECC-192", "P-192", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME192V2 + { + "1.2.840.10045.3.1.2", { "PRIME192V2", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME192V3 + { + "1.2.840.10045.3.1.3", { "PRIME192V3", NULL } + }, +#endif +#ifdef LTC_ECC_SECP192K1 + { + "1.3.132.0.31", { "SECP192K1", NULL } + }, +#endif +#ifdef LTC_ECC_SECP224R1 + { + "1.3.132.0.33", { "SECP224R1", "NISTP224", "ECC-224", "P-224", NULL } + }, +#endif +#ifdef LTC_ECC_SECP224K1 + { + "1.3.132.0.32", { "SECP224K1", NULL } + }, +#endif +#ifdef LTC_ECC_SECP256R1 + { + "1.2.840.10045.3.1.7", { "SECP256R1", "NISTP256", "PRIME256V1", "ECC-256", "P-256", NULL } + }, +#endif +#ifdef LTC_ECC_SECP256K1 + { + "1.3.132.0.10", { "SECP256K1", NULL } + }, +#endif +#ifdef LTC_ECC_SECP384R1 + { + "1.3.132.0.34", { "SECP384R1", "NISTP384", "ECC-384", "P-384", NULL } + }, +#endif +#ifdef LTC_ECC_SECP521R1 + { + "1.3.132.0.35", { "SECP521R1", "NISTP521", "ECC-521", "P-521", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME239V1 + { + "1.2.840.10045.3.1.4", { "PRIME239V1", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME239V2 + { + "1.2.840.10045.3.1.5", { "PRIME239V2", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME239V3 + { + "1.2.840.10045.3.1.6", { "PRIME239V3", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP160R1 + { + "1.3.36.3.3.2.8.1.1.1", { "BRAINPOOLP160R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP192R1 + { + "1.3.36.3.3.2.8.1.1.3", { "BRAINPOOLP192R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP224R1 + { + "1.3.36.3.3.2.8.1.1.5", { "BRAINPOOLP224R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP256R1 + { + "1.3.36.3.3.2.8.1.1.7", { "BRAINPOOLP256R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP320R1 + { + "1.3.36.3.3.2.8.1.1.9", { "BRAINPOOLP320R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP384R1 + { + "1.3.36.3.3.2.8.1.1.11", { "BRAINPOOLP384R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP512R1 + { + "1.3.36.3.3.2.8.1.1.13", { "BRAINPOOLP512R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP160T1 + { + "1.3.36.3.3.2.8.1.1.2", { "BRAINPOOLP160T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP192T1 + { + "1.3.36.3.3.2.8.1.1.4", { "BRAINPOOLP192T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP224T1 + { + "1.3.36.3.3.2.8.1.1.6", { "BRAINPOOLP224T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP256T1 + { + "1.3.36.3.3.2.8.1.1.8", { "BRAINPOOLP256T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP320T1 + { + "1.3.36.3.3.2.8.1.1.10", { "BRAINPOOLP320T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP384T1 + { + "1.3.36.3.3.2.8.1.1.12", { "BRAINPOOLP384T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP512T1 + { + "1.3.36.3.3.2.8.1.1.14", { "BRAINPOOLP512T1", NULL } + }, +#endif +#ifdef LTC_ECC_SM2 + { + "1.2.156.10197.1.301", { "SM2", NULL } + }, +#endif + { + NULL, { NULL } + } +}; + +/* case-insensitive match + ignore '-', '_', ' ' */ +static int s_name_match(const char *left, const char *right) +{ + char lc_r, lc_l; + + while ((*left != '\0') && (*right != '\0')) { + while ((*left == ' ') || (*left == '-') || (*left == '_')) left++; + while ((*right == ' ') || (*right == '-') || (*right == '_')) right++; + if (*left == '\0' || *right == '\0') break; + lc_r = *right; + lc_l = *left; + if ((lc_r >= 'A') && (lc_r <= 'Z')) lc_r += 32; + if ((lc_l >= 'A') && (lc_l <= 'Z')) lc_l += 32; + if (lc_l != lc_r) return 0; + left++; + right++; + } + + if ((*left == '\0') && (*right == '\0')) return 1; + return 0; +} + +int ecc_find_curve(const char *name_or_oid, const ltc_ecc_curve **cu) +{ + int i, j; + const char *OID = NULL; + + LTC_ARGCHK(cu != NULL); + LTC_ARGCHK(name_or_oid != NULL); + + *cu = NULL; + + for (i = 0; s_curve_names[i].OID != NULL && !OID; i++) { + if (XSTRCMP(s_curve_names[i].OID, name_or_oid) == 0) { + OID = s_curve_names[i].OID; + } + for (j = 0; s_curve_names[i].names[j] != NULL && !OID; j++) { + if (s_name_match(s_curve_names[i].names[j], name_or_oid)) { + OID = s_curve_names[i].OID; + } + } + } + + if (OID != NULL) { + for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { + if (XSTRCMP(ltc_ecc_curves[i].OID, OID) == 0) { + *cu = <c_ecc_curves[i]; + return CRYPT_OK; + } + } + } + + return CRYPT_INVALID_ARG; /* not found */ +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c new file mode 100644 index 0000000..6133109 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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_cleanup_multi(&key->dp.prime, &key->dp.order, + &key->dp.A, &key->dp.B, + &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, + &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, + &key->k, NULL); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c new file mode 100644 index 0000000..d30fd06 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c @@ -0,0 +1,50 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** Export raw public or private key (public keys = ANS X9.63 compressed or uncompressed; private keys = raw bytes) + @param out [out] destination of export + @param outlen [in/out] Length of destination and final output size + @param type PK_PRIVATE, PK_PUBLIC or PK_PUBLIC|PK_COMPRESSED + @param key Key to export + Return CRYPT_OK on success +*/ + +int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) +{ + unsigned long size, ksize; + int err, compressed; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + size = key->dp.size; + compressed = type & PK_COMPRESSED ? 1 : 0; + type &= ~PK_COMPRESSED; + + if (type == PK_PUBLIC) { + if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, compressed)) != CRYPT_OK) { + return err; + } + } + else if (type == PK_PRIVATE) { + if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; + *outlen = size; + if (size > *outlen) return CRYPT_BUFFER_OVERFLOW; + if ((ksize = mp_unsigned_bin_size(key->k)) > size) return CRYPT_BUFFER_OVERFLOW; + /* pad and store k */ + if ((err = mp_to_unsigned_bin(key->k, out + (size - ksize))) != CRYPT_OK) return err; + zeromem(out, size - ksize); + } + else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c new file mode 100644 index 0000000..756f641 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c @@ -0,0 +1,22 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** Extract OID as a string from ECC key + @param out [out] destination buffer + @param outlen [in/out] Length of destination buffer and final output size (without terminating NUL byte) + @param key The ECC key + Return CRYPT_OK on success +*/ + +int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key) +{ + LTC_ARGCHK(key != NULL); + + return pk_oid_num_to_str(key->dp.oid, key->dp.oidlen, out, outlen); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c new file mode 100644 index 0000000..e563339 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c @@ -0,0 +1,26 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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(const ecc_key *key) +{ + if (key == NULL) { + return INT_MAX; + } + return key->dp.size; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c new file mode 100644 index 0000000..64bed21 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c @@ -0,0 +1,100 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_import.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + 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 cu 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_curve *cu) +{ + unsigned long key_size; + unsigned char flags[1]; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* find out what type of key it is */ + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_EOL, 0UL, NULL); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + return err; + } + + /* allocate & initialize the key */ + if (cu == NULL) { + if ((err = ecc_set_curve_by_size(key_size, key)) != CRYPT_OK) { goto done; } + } else { + if ((err = ecc_set_curve(cu, key)) != 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 if (flags[0] == 0) { + /* 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; + } + } + else { + err = CRYPT_INVALID_PACKET; + goto done; + } + + /* set z */ + if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; } + + /* point on the curve + other checks */ + if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; } + + /* we're good */ + return CRYPT_OK; + +done: + ecc_free(key); + return err; +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c new file mode 100644 index 0000000..325b0b0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +static int s_ecc_import_private_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + ltc_asn1_list seq_priv[4], custom[2]; + unsigned char bin_xy[2*ECC_MAXSIZE+2], bin_k[ECC_MAXSIZE]; + unsigned long len, pkver = 0, curveoid[16]; + char OID[256]; + const ltc_ecc_curve *curve; + int err; + + /* ### try to load private key - no curve parameters just curve OID */ + + /* ECPrivateKey SEQUENCE */ + LTC_SET_ASN1(custom, 0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL); + LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy)); + LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); + LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ + + /* try to load private key */ + err = der_decode_sequence(in, inlen, seq_priv, 4); + if (err == CRYPT_OK) { + /* load curve parameters for given curve OID */ + len = sizeof(OID); + if ((err = pk_oid_num_to_str(curveoid, custom[0].size, OID, &len)) != CRYPT_OK) { goto error; } + if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; } + if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; } + /* load private+public key */ + err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key); + } +error: + return err; +} + +static int s_ecc_import_private_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + void *prime, *order, *a, *b, *gx, *gy; + ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2]; + unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE]; + unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; + unsigned long len_a, len_b, len_k, len_g; + unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16]; + int err; + + if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* ### try to load private key - curve parameters included */ + + /* ECPrivateKey SEQUENCE */ + LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); + LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy)); + LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); + LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ + /* ECParameters SEQUENCE */ + LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); + LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); + LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); + LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); + LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); + LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); + seq_ecparams[5].optional = 1; + /* FieldID SEQUENCE */ + LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); + LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); + /* Curve SEQUENCE */ + LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); + LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); + LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8UL*sizeof(bin_seed)); + seq_curve[2].optional = 1; + /* try to load private key */ + err = der_decode_sequence(in, inlen, seq_priv, 4); + if (err == CRYPT_OK) { + len_k = seq_priv[1].size; + len_a = seq_curve[0].size; + len_b = seq_curve[1].size; + len_g = seq_ecparams[3].size; + /* create bignums */ + if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } + /* load curve parameters */ + if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } + /* load private+public key */ + err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key); + } +error: + mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL); + return err; +} + +int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + int err; + + if ((err = ecc_import_subject_public_key_info(in, inlen, key)) == CRYPT_OK) { + goto success; + } + + if ((err = s_ecc_import_private_with_oid(in, inlen, key)) == CRYPT_OK) { + goto success; + } + + err = s_ecc_import_private_with_curve(in, inlen, key); + +success: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c new file mode 100644 index 0000000..a6fd7bf --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c @@ -0,0 +1,186 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +typedef struct { + ltc_asn1_type t; + ltc_asn1_list **pp; +} der_flexi_check; + +#define LTC_SET_DER_FLEXI_CHECK(list, index, Type, P) \ + do { \ + int LTC_SDFC_temp##__LINE__ = (index); \ + list[LTC_SDFC_temp##__LINE__].t = Type; \ + list[LTC_SDFC_temp##__LINE__].pp = P; \ + } while (0) + +static int s_der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check) +{ + const ltc_asn1_list *cur; + if (flexi->type != LTC_ASN1_SEQUENCE) { + return CRYPT_INVALID_PACKET; + } + cur = flexi->child; + while(check->t != LTC_ASN1_EOL) { + if (!LTC_ASN1_IS_TYPE(cur, check->t)) { + return CRYPT_INVALID_PACKET; + } + if (check->pp != NULL) *check->pp = (ltc_asn1_list*)cur; + cur = cur->next; + check++; + } + return CRYPT_OK; +} + +/* NOTE: s_der_decode_pkcs8_flexi & related stuff can be shared with rsa_import_pkcs8() */ + +int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + ecc_key *key) +{ + void *a, *b, *gx, *gy; + unsigned long len, cofactor, n; + const char *pka_ec_oid; + int err; + char OID[256]; + const ltc_ecc_curve *curve; + ltc_asn1_list *p = NULL, *l = NULL; + der_flexi_check flexi_should[7]; + ltc_asn1_list *seq, *priv_key; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* get EC alg oid */ + err = pk_get_oid(LTC_OID_EC, &pka_ec_oid); + if (err != CRYPT_OK) return err; + + /* init key */ + err = mp_init_multi(&a, &b, &gx, &gy, LTC_NULL); + if (err != CRYPT_OK) return err; + + + if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) { + + /* Setup for basic structure */ + n=0; + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, NULL); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seq); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &priv_key); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); + + if (((err = s_der_flexi_sequence_cmp(l, flexi_should)) == CRYPT_OK) && + (pk_oid_cmp_with_asn1(pka_ec_oid, seq->child) == CRYPT_OK)) { + ltc_asn1_list *version, *field, *point, *point_g, *order, *p_cofactor; + + /* Setup for CASE 2 */ + n=0; + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &version); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &field); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &point); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &point_g); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &order); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &p_cofactor); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); + + if (LTC_ASN1_IS_TYPE(seq->child->next, LTC_ASN1_OBJECT_IDENTIFIER)) { + /* CASE 1: curve by OID (AKA short variant): + * 0:d=0 hl=2 l= 100 cons: SEQUENCE + * 2:d=1 hl=2 l= 1 prim: INTEGER :00 + * 5:d=1 hl=2 l= 16 cons: SEQUENCE (== *seq) + * 7:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey + * 16:d=2 hl=2 l= 5 prim: OBJECT :(== *curve_oid (e.g. secp256k1 (== 1.3.132.0.10))) + * 23:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key) + */ + ltc_asn1_list *curve_oid = seq->child->next; + len = sizeof(OID); + if ((err = pk_oid_num_to_str(curve_oid->data, curve_oid->size, OID, &len)) != CRYPT_OK) { goto LBL_DONE; } + if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto LBL_DONE; } + if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto LBL_DONE; } + } + else if ((err = s_der_flexi_sequence_cmp(seq->child->next, flexi_should)) == CRYPT_OK) { + /* CASE 2: explicit curve parameters (AKA long variant): + * 0:d=0 hl=3 l= 227 cons: SEQUENCE + * 3:d=1 hl=2 l= 1 prim: INTEGER :00 + * 6:d=1 hl=3 l= 142 cons: SEQUENCE (== *seq) + * 9:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey + * 18:d=2 hl=3 l= 130 cons: SEQUENCE + * 21:d=3 hl=2 l= 1 prim: INTEGER :01 + * 24:d=3 hl=2 l= 44 cons: SEQUENCE (== *field) + * 26:d=4 hl=2 l= 7 prim: OBJECT :prime-field + * 35:d=4 hl=2 l= 33 prim: INTEGER :(== *prime / curve.prime) + * 70:d=3 hl=2 l= 6 cons: SEQUENCE (== *point) + * 72:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.A) + * 75:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.B) + * 78:d=3 hl=2 l= 33 prim: OCTET STRING :bytes (== *g_point / curve.G-point) + * 113:d=3 hl=2 l= 33 prim: INTEGER :(== *order / curve.order) + * 148:d=3 hl=2 l= 1 prim: INTEGER :(== curve.cofactor) + * 151:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key) + */ + + if (mp_get_int(version->data) != 1) { + goto LBL_DONE; + } + cofactor = mp_get_int(p_cofactor->data); + + if (LTC_ASN1_IS_TYPE(field->child, LTC_ASN1_OBJECT_IDENTIFIER) && + LTC_ASN1_IS_TYPE(field->child->next, LTC_ASN1_INTEGER) && + LTC_ASN1_IS_TYPE(point->child, LTC_ASN1_OCTET_STRING) && + LTC_ASN1_IS_TYPE(point->child->next, LTC_ASN1_OCTET_STRING)) { + + ltc_asn1_list *prime = field->child->next; + if ((err = mp_read_unsigned_bin(a, point->child->data, point->child->size)) != CRYPT_OK) { + goto LBL_DONE; + } + if ((err = mp_read_unsigned_bin(b, point->child->next->data, point->child->next->size)) != CRYPT_OK) { + goto LBL_DONE; + } + if ((err = ltc_ecc_import_point(point_g->data, point_g->size, prime->data, a, b, gx, gy)) != CRYPT_OK) { + goto LBL_DONE; + } + if ((err = ecc_set_curve_from_mpis(a, b, prime->data, order->data, gx, gy, cofactor, key)) != CRYPT_OK) { + goto LBL_DONE; + } + } + } + else { + err = CRYPT_INVALID_PACKET; + goto LBL_DONE; + } + + /* load private key value 'k' */ + len = priv_key->size; + if ((err = der_decode_sequence_flexi(priv_key->data, &len, &p)) == CRYPT_OK) { + if (p->type == LTC_ASN1_SEQUENCE && + LTC_ASN1_IS_TYPE(p->child, LTC_ASN1_INTEGER) && + LTC_ASN1_IS_TYPE(p->child->next, LTC_ASN1_OCTET_STRING)) { + ltc_asn1_list *lk = p->child->next; + if (mp_cmp_d(p->child->data, 1) != LTC_MP_EQ) { + err = CRYPT_INVALID_PACKET; + goto LBL_ECCFREE; + } + if ((err = ecc_set_key(lk->data, lk->size, PK_PRIVATE, key)) != CRYPT_OK) { + goto LBL_ECCFREE; + } + goto LBL_DONE; /* success */ + } + } + } + } + err = CRYPT_INVALID_PACKET; + goto LBL_DONE; + +LBL_ECCFREE: + ecc_free(key); +LBL_DONE: + mp_clear_multi(a, b, gx, gy, LTC_NULL); + if (l) der_free_sequence_flexi(l); + if (p) der_free_sequence_flexi(p); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c new file mode 100644 index 0000000..e4ba5e3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c @@ -0,0 +1,116 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + unsigned char bin_xy[2*ECC_MAXSIZE+2]; + unsigned long curveoid[16]; + unsigned long len_xy, len_oid, len; + char OID[256]; + const ltc_ecc_curve *curve; + int err; + + len_xy = sizeof(bin_xy); + len_oid = 16; + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, + LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid); + if (err == CRYPT_OK) { + /* load curve parameters for given curve OID */ + len = sizeof(OID); + if ((err = pk_oid_num_to_str(curveoid, len_oid, OID, &len)) != CRYPT_OK) { goto error; } + if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; } + if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; } + /* load public key */ + err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); + } +error: + return err; +} + +static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + void *prime, *order, *a, *b, *gx, *gy; + ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6]; + unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE]; + unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; + unsigned long len_a, len_b, len_g, len_xy, len; + unsigned long cofactor = 0, ecver = 0, tmpoid[16]; + int err; + + if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* ECParameters SEQUENCE */ + LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); + LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); + LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); + LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); + LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); + LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); + seq_ecparams[5].optional = 1; + /* FieldID SEQUENCE */ + LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); + LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); + /* Curve SEQUENCE */ + LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); + LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); + LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8u*sizeof(bin_seed)); + seq_curve[2].optional = 1; + /* try to load public key */ + len_xy = sizeof(bin_xy); + len = 6; + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len); + + if (err == CRYPT_OK) { + len_a = seq_curve[0].size; + len_b = seq_curve[1].size; + len_g = seq_ecparams[3].size; + /* create bignums */ + if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } + /* load curve parameters */ + if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } + /* load public key */ + err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); + } +error: + mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL); + return err; +} + +int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + int err; + + if ((err = s_ecc_import_x509_with_oid(in, inlen, key)) == CRYPT_OK) { + goto success; + } + + err = s_ecc_import_x509_with_curve(in, inlen, key); + +success: + return err; +} + +/** + Import an ECC key from a X.509 certificate + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + return x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_EC, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)ecc_import_subject_public_key_info, key); +} + +#endif /* LTC_MECC */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c new file mode 100644 index 0000000..1b04741 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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 err; + + if ((err = ecc_set_curve_by_size(keysize, key)) != CRYPT_OK) { return err; } + if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } + return CRYPT_OK; +} + +int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu) +{ + int err; + if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; } + if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } + return CRYPT_OK; +} + +int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key) +{ + int err; + + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->dp.size > 0); + + /* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates): + * the generated private key k should be the range [1, order-1] + * a/ N = bitlen(order) + * b/ generate N random bits and convert them into big integer k + * c/ if k not in [1, order-1] go to b/ + * e/ Q = k*G + */ + if ((err = rand_bn_upto(key->k, key->dp.order, prng, wprng)) != CRYPT_OK) { + goto error; + } + + /* make the public key */ + if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) { + goto error; + } + key->type = PK_PRIVATE; + + /* success */ + err = CRYPT_OK; + goto cleanup; + +error: + ecc_free(key); +cleanup: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c new file mode 100644 index 0000000..b6ae644 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c @@ -0,0 +1,260 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +#ifdef LTC_ECC_SHAMIR + +/** + @file ecc_recover_key.c + ECC Crypto, Russ Williams +*/ + +/** + Recover ECC public key from signature and hash + @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 recid The recovery ID ("v"), can be -1 if signature contains it + @param sigformat The format of the signature (ecc_signature_type) + @param key The recovered public ECC key + @return CRYPT_OK if successful (even if the signature is not valid) +*/ +int ecc_recover_key(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int recid, ecc_signature_type sigformat, ecc_key *key) +{ + ecc_point *mG = NULL, *mQ = NULL, *mR = NULL; + void *p, *m, *a, *b; + void *r, *s, *v, *w, *t1, *t2, *u1, *u2, *v1, *v2, *e, *x, *y, *a_plus3; + void *mu = NULL, *ma = NULL; + void *mp = NULL; + int err; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(key != NULL); + + /* BEWARE: requires sqrtmod_prime */ + if (ltc_mp.sqrtmod_prime == NULL) { + return CRYPT_ERROR; + } + + /* allocate ints */ + if ((err = mp_init_multi(&r, &s, &v, &w, &t1, &t2, &u1, &u2, &v1, &v2, &e, &x, &y, &a_plus3, LTC_NULL)) != CRYPT_OK) { + return err; + } + + p = key->dp.order; + m = key->dp.prime; + a = key->dp.A; + b = key->dp.B; + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { + goto error; + } + + /* allocate points */ + mG = ltc_ecc_new_point(); + mQ = ltc_ecc_new_point(); + mR = ltc_ecc_new_point(); + if (mR == NULL || mQ == NULL || mG == NULL) { + err = CRYPT_MEM; + goto error; + } + + if (sigformat == LTC_ECCSIG_ANSIX962) { + /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ + if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } + } + else if (sigformat == LTC_ECCSIG_RFC7518) { + /* RFC7518 format - raw (r,s) */ + i = mp_unsigned_bin_size(key->dp.order); + if (siglen != (2*i)) { + err = CRYPT_INVALID_PACKET; + goto error; + } + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; } + } + else if (sigformat == LTC_ECCSIG_ETH27) { + /* Ethereum (v,r,s) format */ + if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { + /* Only valid for secp256k1 - OID 1.3.132.0.10 */ + err = CRYPT_ERROR; goto error; + } + if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ + err = CRYPT_INVALID_PACKET; + goto error; + } + i = (unsigned long)sig[64]; + if ((i>=27) && (i<31)) i -= 27; /* Ethereum adds 27 to recovery ID */ + if (recid >= 0 && ((unsigned long)recid != i)) { + /* Recovery ID specified, but doesn't match signature */ + err = CRYPT_INVALID_PACKET; + goto error; + } + recid = i; + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; } + } +#ifdef LTC_SSH + else if (sigformat == LTC_ECCSIG_RFC5656) { + char name[64], name2[64]; + unsigned long namelen = sizeof(name); + unsigned long name2len = sizeof(name2); + + /* Decode as SSH data sequence, per RFC4251 */ + if ((err = ssh_decode_sequence_multi(sig, &siglen, + LTC_SSHDATA_STRING, name, &namelen, + LTC_SSHDATA_MPINT, r, + LTC_SSHDATA_MPINT, s, + LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } + + + /* Check curve matches identifier string */ + if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } + if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { + err = CRYPT_INVALID_ARG; + goto error; + } + } +#endif + else { + /* Unknown signature format */ + err = CRYPT_ERROR; + goto error; + } + + if (recid < 0 || (unsigned long)recid >= 2*(key->dp.cofactor+1)) { + /* Recovery ID is out of range, reject it */ + err = CRYPT_INVALID_ARG; + goto error; + } + + /* check for zero */ + if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || + mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* read hash - truncate if needed */ + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > hashlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } + } + + /* decompress point from r=(x mod p) - BEWARE: requires sqrtmod_prime */ + /* x = r + p*(recid/2) */ + if ((err = mp_set(x, recid/2)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(p, x, m, x)) != CRYPT_OK) { goto error; } + if ((err = mp_add(x, r, x)) != CRYPT_OK) { goto error; } + /* compute x^3 */ + if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(t1, x, m, t1)) != CRYPT_OK) { goto error; } + /* compute x^3 + a*x */ + if ((err = mp_mulmod(a, x, m, t2)) != CRYPT_OK) { goto error; } + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto error; } + /* compute x^3 + a*x + b */ + if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto error; } + /* compute sqrt(x^3 + a*x + b) */ + if ((err = mp_sqrtmod_prime(t1, m, t2)) != CRYPT_OK) { goto error; } + + /* fill in mR */ + if ((err = mp_copy(x, mR->x)) != CRYPT_OK) { goto error; } + if ((mp_isodd(t2) && (recid%2)) || (!mp_isodd(t2) && !(recid%2))) { + if ((err = mp_mod(t2, m, mR->y)) != CRYPT_OK) { goto error; } + } + else { + if ((err = mp_submod(m, t2, m, mR->y)) != CRYPT_OK) { goto error; } + } + if ((err = mp_set(mR->z, 1)) != CRYPT_OK) { goto error; } + + /* w = r^-1 mod n */ + if ((err = mp_invmod(r, p, w)) != CRYPT_OK) { goto error; } + /* v1 = sw */ + if ((err = mp_mulmod(s, w, p, v1)) != CRYPT_OK) { goto error; } + /* v2 = -ew */ + if ((err = mp_mulmod(e, w, p, v2)) != CRYPT_OK) { goto error; } + if ((err = mp_submod(p, v2, p, v2)) != 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 */ + if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } + + /* find the montgomery mp */ + if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { + if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } + } + + /* recover mQ from mR */ + /* compute v1*mR + v2*mG = mQ using Shamir's trick */ + if ((err = ltc_mp.ecc_mul2add(mR, v1, mG, v2, mQ, ma, m)) != CRYPT_OK) { goto error; } + + /* compute u1*mG + u2*mQ = mG using Shamir's trick */ + if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, 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) { + /* found public key which verifies signature */ + if ((err = ltc_ecc_copy_point(mQ, &key->pubkey)) != CRYPT_OK) { goto error; } + /* point on the curve + other checks */ + if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto error; } + + key->type = PK_PUBLIC; + + err = CRYPT_OK; + } + else { + /* not found - recid is wrong or we're unable to calculate public key for some other reason */ + err = CRYPT_INVALID_ARG; + } + +error: + if (ma != NULL) mp_clear(ma); + if (mu != NULL) mp_clear(mu); + if (mp != NULL) mp_montgomery_free(mp); + if (mR != NULL) ltc_ecc_del_point(mR); + if (mQ != NULL) ltc_ecc_del_point(mQ); + if (mG != NULL) ltc_ecc_del_point(mG); + mp_clear_multi(a_plus3, y, x, e, v2, v1, u2, u1, t2, t1, w, v, s, r, LTC_NULL); + return err; +} + +#endif +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c new file mode 100644 index 0000000..427a593 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(cu != NULL); + + if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, + &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, + &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, + NULL)) != CRYPT_OK) { + return err; + } + + /* A, B, order, prime, Gx, Gy */ + if ((err = mp_read_radix(key->dp.prime, cu->prime, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.order, cu->order, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.A, cu->A, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.B, cu->B, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.base.x, cu->Gx, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.base.y, cu->Gy, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; } + /* cofactor & size */ + key->dp.cofactor = cu->cofactor; + key->dp.size = mp_unsigned_bin_size(key->dp.prime); + /* OID string >> unsigned long oid[16] + oidlen */ + key->dp.oidlen = 16; + if ((err = pk_oid_str_to_num(cu->OID, key->dp.oid, &key->dp.oidlen)) != CRYPT_OK) { goto error; } + /* success */ + return CRYPT_OK; + +error: + ecc_free(key); + return err; +} + +int ecc_set_curve_by_size(int size, ecc_key *key) +{ + const ltc_ecc_curve *cu = NULL; + int err = CRYPT_ERROR; + + /* for compatibility with libtomcrypt-1.17 the sizes below must match the specific curves */ + if (size <= 14) { + err = ecc_find_curve("SECP112R1", &cu); + } + else if (size <= 16) { + err = ecc_find_curve("SECP128R1", &cu); + } + else if (size <= 20) { + err = ecc_find_curve("SECP160R1", &cu); + } + else if (size <= 24) { + err = ecc_find_curve("SECP192R1", &cu); + } + else if (size <= 28) { + err = ecc_find_curve("SECP224R1", &cu); + } + else if (size <= 32) { + err = ecc_find_curve("SECP256R1", &cu); + } + else if (size <= 48) { + err = ecc_find_curve("SECP384R1", &cu); + } + else if (size <= 66) { + err = ecc_find_curve("SECP521R1", &cu); + } + + if (err == CRYPT_OK && cu != NULL) return ecc_set_curve(cu, key); + + return CRYPT_INVALID_ARG; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c new file mode 100644 index 0000000..4f43914 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c @@ -0,0 +1,119 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +static int s_ecc_cmp_hex_bn(const char *left_hex, void *right_bn, void *tmp_bn) +{ + if (mp_read_radix(tmp_bn, left_hex, 16) != CRYPT_OK) return 0; + if (mp_cmp(tmp_bn, right_bn) != LTC_MP_EQ) return 0; + return 1; +} + +static void s_ecc_oid_lookup(ecc_key *key) +{ + void *bn; + const ltc_ecc_curve *curve; + + key->dp.oidlen = 0; + if (mp_init(&bn) != CRYPT_OK) return; + for (curve = ltc_ecc_curves; curve->prime != NULL; curve++) { + if (s_ecc_cmp_hex_bn(curve->prime, key->dp.prime, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->order, key->dp.order, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->A, key->dp.A, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->B, key->dp.B, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->Gx, key->dp.base.x, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->Gy, key->dp.base.y, bn) != 1) continue; + if (key->dp.cofactor != curve->cofactor) continue; + break; /* found */ + } + mp_clear(bn); + if (curve->prime && curve->OID) { + key->dp.oidlen = 16; /* size of key->dp.oid */ + pk_oid_str_to_num(curve->OID, key->dp.oid, &key->dp.oidlen); + } +} + +int ecc_copy_curve(const ecc_key *srckey, ecc_key *key) +{ + unsigned long i; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(srckey != NULL); + + if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, + &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, + &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, + NULL)) != CRYPT_OK) { + return err; + } + + /* A, B, order, prime, Gx, Gy */ + if ((err = mp_copy(srckey->dp.prime, key->dp.prime )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(srckey->dp.order, key->dp.order )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(srckey->dp.A, key->dp.A )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(srckey->dp.B, key->dp.B )) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_copy_point(&srckey->dp.base, &key->dp.base)) != CRYPT_OK) { goto error; } + /* cofactor & size */ + key->dp.cofactor = srckey->dp.cofactor; + key->dp.size = srckey->dp.size; + /* OID */ + if (srckey->dp.oidlen > 0) { + key->dp.oidlen = srckey->dp.oidlen; + for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = srckey->dp.oid[i]; + } + else { + s_ecc_oid_lookup(key); /* try to find OID in ltc_ecc_curves */ + } + /* success */ + return CRYPT_OK; + +error: + ecc_free(key); + return err; +} + +int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(prime != NULL); + LTC_ARGCHK(order != NULL); + LTC_ARGCHK(gx != NULL); + LTC_ARGCHK(gy != NULL); + + if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, + &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, + &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, + NULL)) != CRYPT_OK) { + return err; + } + + /* A, B, order, prime, Gx, Gy */ + if ((err = mp_copy(prime, key->dp.prime )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(order, key->dp.order )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(a, key->dp.A )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(b, key->dp.B )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(gx, key->dp.base.x)) != CRYPT_OK) { goto error; } + if ((err = mp_copy(gy, key->dp.base.y)) != CRYPT_OK) { goto error; } + if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; } + /* cofactor & size */ + key->dp.cofactor = cofactor; + key->dp.size = mp_unsigned_bin_size(prime); + /* try to find OID in ltc_ecc_curves */ + s_ecc_oid_lookup(key); + /* success */ + return CRYPT_OK; + +error: + ecc_free(key); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c new file mode 100644 index 0000000..3cf5488 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key) +{ + int err; + void *prime, *a, *b; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + prime = key->dp.prime; + a = key->dp.A; + b = key->dp.B; + + if (type == PK_PRIVATE) { + /* load private key */ + if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, inlen)) != CRYPT_OK) { + goto error; + } + if (mp_iszero(key->k) || (mp_cmp(key->k, key->dp.order) != LTC_MP_LT)) { + err = CRYPT_INVALID_PACKET; + goto error; + } + /* compute public key */ + if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto error; } + } + else if (type == PK_PUBLIC) { + /* load public key */ + if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; } + if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; } + } + else { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* point on the curve + other checks */ + if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { + goto error; + } + + key->type = type; + return CRYPT_OK; + +error: + ecc_free(key); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c new file mode 100644 index 0000000..21ac913 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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(const ecc_key *private_key, const ecc_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x; + ecc_point *result; + void *prime, *a; + 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; + } + + /* make new point */ + result = ltc_ecc_new_point(); + if (result == NULL) { + return CRYPT_MEM; + } + + prime = private_key->dp.prime; + a = private_key->dp.A; + + if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; } + + x = (unsigned long)mp_unsigned_bin_size(prime); + if (*outlen < x) { + *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: + ltc_ecc_del_point(result); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c new file mode 100644 index 0000000..229ced1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c @@ -0,0 +1,181 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** + @file ecc_sign_hash.c + ECC Crypto, Tom St Denis +*/ + +/** + 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 sigformat The format of the signature to generate (ecc_signature_type) + @param recid [out] The recovery ID for this signature (optional) + @param key A private ECC key + @return CRYPT_OK if successful +*/ +int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, ecc_signature_type sigformat, + int *recid, const ecc_key *key) +{ + ecc_key pubkey; + void *r, *s, *e, *p, *b; + int v = 0; + int err, max_iterations = LTC_PK_MAX_RETRIES; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; + + 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; + } + + /* init the bignums */ + if ((err = mp_init_multi(&r, &s, &e, &b, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* get the hash and load it as a bignum into 'e' */ + p = key->dp.order; + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > inlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, inlen)) != CRYPT_OK) { goto errnokey; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, pbytes)) != CRYPT_OK) { goto errnokey; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto errnokey; } + } + + /* make up a key and export the public copy */ + do { + if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; } + if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; } + + /* find r = x1 mod n */ + if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; } + + if (recid || sigformat==LTC_ECCSIG_ETH27) { + /* find recovery ID (if needed) */ + v = 0; + if (mp_copy(pubkey.pubkey.x, s) != CRYPT_OK) { goto error; } + while (mp_cmp_d(s, 0) == LTC_MP_GT && mp_cmp(s, p) != LTC_MP_LT) { + /* Compute x1 div n... this will almost never be reached for curves with order 1 */ + v += 2; + if ((err = mp_sub(s, p, s)) != CRYPT_OK) { goto error; } + } + if (mp_isodd(pubkey.pubkey.y)) v += 1; + } + + if (mp_iszero(r) == LTC_MP_YES) { + ecc_free(&pubkey); + } else { + if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */ + /* find s = (e + xr)/k */ + if ((err = mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */ + if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */ + if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */ + if ((err = mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK) { goto error; } /* s = xr/kb */ + if ((err = mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK) { goto error; } /* e = e/kb */ + if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e/kb + xr/kb */ + if ((err = mp_mulmod(s, b, p, s)) != CRYPT_OK) { goto error; } /* s = b(e/kb + xr/kb) = (e + xr)/k */ + ecc_free(&pubkey); + if (mp_iszero(s) == LTC_MP_NO) { + break; + } + } + } while (--max_iterations > 0); + + if (max_iterations == 0) { + goto errnokey; + } + + if (recid) *recid = v; + + if (sigformat == LTC_ECCSIG_ANSIX962) { + /* store as ASN.1 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); + } + else if (sigformat == LTC_ECCSIG_RFC7518) { + /* RFC7518 format - raw (r,s) */ + if (*outlen < 2*pbytes) { err = CRYPT_MEM; goto errnokey; } + zeromem(out, 2*pbytes); + i = mp_unsigned_bin_size(r); + if ((err = mp_to_unsigned_bin(r, out + (pbytes - i))) != CRYPT_OK) { goto errnokey; } + i = mp_unsigned_bin_size(s); + if ((err = mp_to_unsigned_bin(s, out + (2*pbytes - i))) != CRYPT_OK) { goto errnokey; } + *outlen = 2*pbytes; + err = CRYPT_OK; + } + else if (sigformat == LTC_ECCSIG_ETH27) { + /* Ethereum (v,r,s) format */ + if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { + /* Only valid for secp256k1 - OID 1.3.132.0.10 */ + err = CRYPT_ERROR; goto errnokey; + } + if (*outlen < 65) { err = CRYPT_MEM; goto errnokey; } + zeromem(out, 65); + i = mp_unsigned_bin_size(r); + if ((err = mp_to_unsigned_bin(r, out + 32 - i)) != CRYPT_OK) { goto errnokey; } + i = mp_unsigned_bin_size(s); + if ((err = mp_to_unsigned_bin(s, out + 64 - i)) != CRYPT_OK) { goto errnokey; } + out[64] = (unsigned char)(v + 27); /* Recovery ID is 27/28 for Ethereum */ + *outlen = 65; + err = CRYPT_OK; + } +#ifdef LTC_SSH + else if (sigformat == LTC_ECCSIG_RFC5656) { + /* Get identifier string */ + char name[64]; + unsigned long namelen = sizeof(name); + if ((err = ecc_ssh_ecdsa_encode_name(name, &namelen, key)) != CRYPT_OK) { goto errnokey; } + + /* Store as SSH data sequence, per RFC4251 */ + err = ssh_encode_sequence_multi(out, outlen, + LTC_SSHDATA_STRING, name, namelen, + LTC_SSHDATA_MPINT, r, + LTC_SSHDATA_MPINT, s, + LTC_SSHDATA_EOL, NULL); + } +#endif + else { + /* Unknown signature format */ + err = CRYPT_ERROR; + goto error; + } + + goto errnokey; +error: + ecc_free(&pubkey); +errnokey: + mp_clear_multi(r, s, e, b, LTC_NULL); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c new file mode 100644 index 0000000..07379b6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_sizes.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +void ecc_sizes(int *low, int *high) +{ + int i, size; + void *prime; + + LTC_ARGCHKVD(low != NULL); + LTC_ARGCHKVD(high != NULL); + + *low = INT_MAX; + *high = 0; + + if (mp_init(&prime) == CRYPT_OK) { + for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { + if (mp_read_radix(prime, ltc_ecc_curves[i].prime, 16) == CRYPT_OK) { + size = mp_unsigned_bin_size(prime); + if (size < *low) *low = size; + if (size > *high) *high = size; + } + } + mp_clear(prime); + } +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c new file mode 100644 index 0000000..4b8d554 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ecc_ssh_ecdsa_encode_name.c + Curve/OID to SSH+ECDSA name string mapping per RFC5656 + Russ Williams +*/ + +#ifdef LTC_SSH + +/** + Curve/OID to SSH+ECDSA name string mapping + @param buffer [out] The destination for the name + @param buflen [in/out] The max size and resulting size (including terminator) of the name + @param key A public or private ECC key + @return CRYPT_OK if successful +*/ +int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key) +{ + char oidstr[64] = {0}; + unsigned long oidlen = sizeof(oidstr); + int err, size = 0; + + LTC_ARGCHK(buffer != NULL); + LTC_ARGCHK(buflen != NULL); + LTC_ARGCHK(key != NULL); + + /* Get the OID of the curve */ + if ((err = ecc_get_oid_str(oidstr, &oidlen, key)) != CRYPT_OK) goto error; + + /* Check for three named curves: nistp256, nistp384, nistp521 */ + if (XSTRCMP("1.2.840.10045.3.1.7", oidstr) == 0) { + /* nistp256 - secp256r1 - OID 1.2.840.10045.3.1.7 */ + size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp256"); + } + else if (XSTRCMP("1.3.132.0.34", oidstr) == 0) { + /* nistp384 - secp384r1 - OID 1.3.132.0.34 */ + size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp384"); + } + else if (XSTRCMP("1.3.132.0.35", oidstr) == 0) { + /* nistp521 - secp521r1 - OID 1.3.132.0.35 */ + size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp521"); + } else { + /* Otherwise we use the OID... */ + size = snprintf(buffer, *buflen, "ecdsa-sha2-%s", oidstr); + } + + /* snprintf returns a negative value on error + * or the size that would have been written, but limits to buflen-1 chars plus terminator */ + if (size < 0) { + err = CRYPT_ERROR; + } else if ((unsigned)size >= *buflen) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + err = CRYPT_OK; + } + *buflen = size + 1; /* the string length + NUL byte */ + +error: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c new file mode 100644 index 0000000..4480ff4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c @@ -0,0 +1,206 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** + @file ecc_verify_hash.c + ECC Crypto, Tom St Denis +*/ + +/** + Verify an ECC signature in RFC7518 format + @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 sigformat The format of the signature (ecc_signature_type) + @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_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + ecc_signature_type sigformat, int *stat, const ecc_key *key) +{ + ecc_point *mG = NULL, *mQ = NULL; + void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3; + void *mu = NULL, *ma = NULL; + void *mp = NULL; + int err; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid signature */ + *stat = 0; + + /* allocate ints */ + if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, LTC_NULL)) != CRYPT_OK) { + return err; + } + + p = key->dp.order; + m = key->dp.prime; + a = key->dp.A; + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { + goto error; + } + + /* allocate points */ + mG = ltc_ecc_new_point(); + mQ = ltc_ecc_new_point(); + if (mQ == NULL || mG == NULL) { + err = CRYPT_MEM; + goto error; + } + + if (sigformat == LTC_ECCSIG_ANSIX962) { + /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ + if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } + } + else if (sigformat == LTC_ECCSIG_RFC7518) { + /* RFC7518 format - raw (r,s) */ + i = mp_unsigned_bin_size(key->dp.order); + if (siglen != (2 * i)) { + err = CRYPT_INVALID_PACKET; + goto error; + } + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; } + } + else if (sigformat == LTC_ECCSIG_ETH27) { + /* Ethereum (v,r,s) format */ + if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { + /* Only valid for secp256k1 - OID 1.3.132.0.10 */ + err = CRYPT_ERROR; goto error; + } + if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ + err = CRYPT_INVALID_PACKET; + goto error; + } + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; } + } +#ifdef LTC_SSH + else if (sigformat == LTC_ECCSIG_RFC5656) { + char name[64], name2[64]; + unsigned long namelen = sizeof(name); + unsigned long name2len = sizeof(name2); + + /* Decode as SSH data sequence, per RFC4251 */ + if ((err = ssh_decode_sequence_multi(sig, &siglen, + LTC_SSHDATA_STRING, name, &namelen, + LTC_SSHDATA_MPINT, r, + LTC_SSHDATA_MPINT, s, + LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } + + + /* Check curve matches identifier string */ + if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } + if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { + err = CRYPT_INVALID_ARG; + goto error; + } + } +#endif + else { + /* Unknown signature format */ + err = CRYPT_ERROR; + goto error; + } + + /* check for zero */ + if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || + mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* read hash - truncate if needed */ + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > hashlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != 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 = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; } + + /* find the montgomery mp */ + if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { + if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } + } + + /* compute u1*mG + u2*mQ = mG */ + if (ltc_mp.ecc_mul2add == NULL) { + if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; } + if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; } + + /* add them */ + if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, 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, ma, 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: + if (mG != NULL) ltc_ecc_del_point(mG); + if (mQ != NULL) ltc_ecc_del_point(mQ); + if (mu != NULL) mp_clear(mu); + if (ma != NULL) mp_clear(ma); + mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, LTC_NULL); + if (mp != NULL) mp_montgomery_free(mp); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c new file mode 100644 index 0000000..022c6bc --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed) +{ + int err; + unsigned char buf[ECC_BUF_SIZE]; + unsigned long xsize, ysize; + + if (size > sizeof(buf)) return CRYPT_BUFFER_OVERFLOW; + if ((xsize = mp_unsigned_bin_size(x)) > size) return CRYPT_BUFFER_OVERFLOW; + if ((ysize = mp_unsigned_bin_size(y)) > size) return CRYPT_BUFFER_OVERFLOW; + + if(compressed) { + if (*outlen < (1 + size)) { + *outlen = 1 + size; + return CRYPT_BUFFER_OVERFLOW; + } + /* store first byte */ + out[0] = mp_isodd(y) ? 0x03 : 0x02; + /* pad and store x */ + zeromem(buf, sizeof(buf)); + if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; + XMEMCPY(out+1, buf, size); + /* adjust outlen */ + *outlen = 1 + size; + } + else { + if (*outlen < (1 + 2*size)) { + *outlen = 1 + 2*size; + return CRYPT_BUFFER_OVERFLOW; + } + /* store byte 0x04 */ + out[0] = 0x04; + /* pad and store x */ + zeromem(buf, sizeof(buf)); + if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; + XMEMCPY(out+1, buf, size); + /* pad and store y */ + zeromem(buf, sizeof(buf)); + if ((err = mp_to_unsigned_bin(y, buf + (size - ysize))) != CRYPT_OK) return err; + XMEMCPY(out+1+size, buf, size); + /* adjust outlen */ + *outlen = 1 + 2*size; + } + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c new file mode 100644 index 0000000..6250fca --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y) +{ + int err; + unsigned long size; + void *t1, *t2; + + /* init key + temporary numbers */ + if (mp_init_multi(&t1, &t2, LTC_NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + size = mp_unsigned_bin_size(prime); + + if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == size) { + /* read uncompressed point */ + /* load x */ + if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; } + /* load y */ + if ((err = mp_read_unsigned_bin(y, (unsigned char *)in+1+size, size)) != CRYPT_OK) { goto cleanup; } + } + else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == size && ltc_mp.sqrtmod_prime != NULL) { + /* read compressed point - BEWARE: requires sqrtmod_prime */ + /* load x */ + if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; } + /* compute x^3 */ + if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mulmod(t1, x, prime, t1)) != CRYPT_OK) { goto cleanup; } + /* compute x^3 + a*x */ + if ((err = mp_mulmod(a, x, prime, t2)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; } + /* compute x^3 + a*x + b */ + if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; } + /* compute sqrt(x^3 + a*x + b) */ + if ((err = mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; } + /* adjust y */ + if ((mp_isodd(t2) && in[0] == 0x03) || (!mp_isodd(t2) && in[0] == 0x02)) { + if ((err = mp_mod(t2, prime, y)) != CRYPT_OK) { goto cleanup; } + } + else { + if ((err = mp_submod(prime, t2, prime, y)) != CRYPT_OK) { goto cleanup; } + } + } + else { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + + err = CRYPT_OK; +cleanup: + mp_clear_multi(t1, t2, LTC_NULL); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c new file mode 100644 index 0000000..56a9537 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** Returns whether [x,y] is a point on curve defined by dp + @param dp curve parameters + @param x x point coordinate + @param y y point coordinate + @return CRYPT_OK if valid +*/ + +int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y) +{ + void *prime, *a, *b, *t1, *t2; + int err; + + prime = dp->prime; + b = dp->B; + a = dp->A; + + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) return err; + + /* compute y^2 */ + if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup; + + /* compute x^3 */ + if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup; + if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup; + if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup; + + /* compute y^2 - x^3 */ + if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup; + + /* compute y^2 - x^3 - a*x */ + if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup; + if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup; + if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup; + + /* adjust range (0, prime) */ + while (mp_cmp_d(t1, 0) == LTC_MP_LT) { + if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup; + } + while (mp_cmp(t1, prime) != LTC_MP_LT) { + if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup; + } + + /* compare to b */ + if (mp_cmp(t1, b) != LTC_MP_EQ) { + err = CRYPT_INVALID_PACKET; + } else { + err = CRYPT_OK; + } + +cleanup: + mp_clear_multi(t1, t2, LTC_NULL); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c new file mode 100644 index 0000000..2afc4d4 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/* http://crypto.stackexchange.com/questions/41468/point-at-infinity-for-jacobian-coordinates + * a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0) + */ + +int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval) +{ + int err; + void *x3, *y2; + + /* trivial case */ + if (!mp_iszero(P->z)) { + *retval = 0; + return CRYPT_OK; + } + + /* point (0,0,0) is not at infinity */ + if (mp_iszero(P->x) && mp_iszero(P->y)) { + *retval = 0; + return CRYPT_OK; + } + + /* initialize */ + if ((err = mp_init_multi(&x3, &y2, LTC_NULL)) != CRYPT_OK) goto done; + + /* compute y^2 */ + if ((err = mp_mulmod(P->y, P->y, modulus, y2)) != CRYPT_OK) goto cleanup; + + /* compute x^3 */ + if ((err = mp_mulmod(P->x, P->x, modulus, x3)) != CRYPT_OK) goto cleanup; + if ((err = mp_mulmod(P->x, x3, modulus, x3)) != CRYPT_OK) goto cleanup; + + /* test y^2 == x^3 */ + err = CRYPT_OK; + if ((mp_cmp(x3, y2) == LTC_MP_EQ) && !mp_iszero(y2)) { + *retval = 1; + } else { + *retval = 0; + } + +cleanup: + mp_clear_multi(x3, y2, LTC_NULL); +done: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c new file mode 100644 index 0000000..163fb41 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c @@ -0,0 +1,63 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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 (mp_iszero(P->z)) { + return ltc_ecc_set_point_xyz(0, 0, 1, P); + } + + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* 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, LTC_NULL); + return err; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c new file mode 100644 index 0000000..a0188e3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c @@ -0,0 +1,192 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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 ma ECC curve parameter a in montgomery form + @param modulus Modulus for curve + @return CRYPT_OK on success +*/ +int ltc_ecc_mul2add(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus) +{ + ecc_point *precomp[16]; + unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; + unsigned x, y; + unsigned char *tA, *tB; + int err, first; + void *mp, *mu; + + /* 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], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], ma, 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], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], ma, 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)], ma, 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 = 0;; ) { + /* grab a nibble */ + if (++nibble == 4) { + if (x == len) break; + bitbufA = tA[x]; + bitbufB = tB[x]; + nibble = 0; + ++x; + } + + /* 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, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptdbl(C, C, ma, 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 = ltc_ecc_copy_point(precomp[nA + (nB<<2)], C)) != CRYPT_OK) { goto ERR_MU; } + } else { + /* if not first, add from table */ + if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, ma, 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 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c new file mode 100644 index 0000000..cabe266 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c @@ -0,0 +1,204 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_mulmod.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC +#ifndef LTC_ECC_TIMING_RESISTANT + +/* 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, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map) +{ + ecc_point *tG, *M[8]; + int i, j, err, inf; + void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL; + ltc_mp_digit buf; + int first, bitbuf, bitcpy, bitcnt, mode, digidx; + + LTC_ARGCHK(k != NULL); + LTC_ARGCHK(G != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + + if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* return the point at infinity */ + return ltc_ecc_set_point_xyz(1, 1, 0, R); + } + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; } + if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; } + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } + if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { + if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; } + } + + /* alloc ram for window temps */ + 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]); + } + err = CRYPT_MEM; + goto error; + } + } + + /* 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 = ltc_ecc_copy_point(G, tG)) != 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], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, 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], ma, 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, ma, 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 = ltc_ecc_copy_point(M[bitbuf-8], R)) != 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, ma, 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, ma, 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, ma, modulus, mp)) != CRYPT_OK) { goto done; } + } + + bitbuf <<= 1; + if ((bitbuf & (1 << WINSIZE)) != 0) { + if (first == 1){ + /* first add, so copy */ + if ((err = ltc_ecc_copy_point(tG, R)) != CRYPT_OK) { goto done; } + first = 0; + } else { + /* then add */ + if ((err = ltc_mp.ecc_ptadd(R, tG, R, ma, 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); + for (i = 0; i < 8; i++) { + ltc_ecc_del_point(M[i]); + } +error: + if (ma != NULL) mp_clear(ma); + if (a_plus3 != NULL) mp_clear(a_plus3); + if (mu != NULL) mp_clear(mu); + if (mp != NULL) mp_montgomery_free(mp); + return err; +} + +#endif + +#undef WINSIZE + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c new file mode 100644 index 0000000..96f50f9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c @@ -0,0 +1,151 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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 a ECC curve parameter a + @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, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map) +{ + ecc_point *tG, *M[3]; + int i, j, err, inf; + void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL; + ltc_mp_digit buf; + int bitcnt, mode, digidx; + + LTC_ARGCHK(k != NULL); + LTC_ARGCHK(G != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + + if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* return the point at infinity */ + return ltc_ecc_set_point_xyz(1, 1, 0, R); + } + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; } + if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; } + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } + if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { + if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; } + } + + /* alloc ram for window temps */ + 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 = ltc_ecc_copy_point(tG, M[0])) != CRYPT_OK) { goto done; } + /* M[1] == 2G */ + if ((err = ltc_mp.ecc_ptdbl(tG, M[1], ma, modulus, mp)) != CRYPT_OK) { goto done; } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = mp_get_digit_count(k) - 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 = (int)((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], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, 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], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } + continue; + } + + if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], ma, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* copy result out */ + if ((err = ltc_ecc_copy_point(M[0], R)) != 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); + for (i = 0; i < 3; i++) { + ltc_ecc_del_point(M[i]); + } +error: + if (ma != NULL) mp_clear(ma); + if (a_plus3 != NULL) mp_clear(a_plus3); + if (mu != NULL) mp_clear(mu); + if (mp != NULL) mp_montgomery_free(mp); + return err; +} + +#endif +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c new file mode 100644 index 0000000..b6872d3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.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_size(LTC_MAX_ECC * 2, + &p->x, &p->y, &p->z, LTC_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, LTC_NULL); /* note: p->z may be NULL but that's ok with this function anyways */ + XFREE(p); + } +} + +int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p) +{ + int err; + if ((err = ltc_mp.set_int(p->x, x)) != CRYPT_OK) return err; + if ((err = ltc_mp.set_int(p->y, y)) != CRYPT_OK) return err; + if ((err = ltc_mp.set_int(p->z, z)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst) +{ + int err; + if ((err = ltc_mp.copy(src->x, dst->x)) != CRYPT_OK) return err; + if ((err = ltc_mp.copy(src->y, dst->y)) != CRYPT_OK) return err; + if ((err = ltc_mp.copy(src->z, dst->z)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c new file mode 100644 index 0000000..448c2bb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c @@ -0,0 +1,198 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_projective_add_point.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_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 ma ECC curve parameter a in montgomery form + @param modulus The modulus of the field the ECC curve is in + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success +*/ +int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp) +{ + void *t1, *t2, *x, *y, *z; + int err, inf; + + 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, LTC_NULL)) != CRYPT_OK) { + return err; + } + + if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* P is point at infinity >> Result = Q */ + err = ltc_ecc_copy_point(Q, R); + goto done; + } + + if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* Q is point at infinity >> Result = P */ + err = ltc_ecc_copy_point(P, R); + goto done; + } + + if ((mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (mp_cmp(P->z, Q->z) == LTC_MP_EQ)) { + if (mp_cmp(P->y, Q->y) == LTC_MP_EQ) { + /* here P = Q >> Result = 2 * P (use doubling) */ + mp_clear_multi(t1, t2, x, y, z, LTC_NULL); + return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp); + } + if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(P->y, t1) == LTC_MP_EQ) { + /* here Q = -P >>> Result = the point at infinity */ + err = ltc_ecc_set_point_xyz(1, 1, 0, R); + goto done; + } + } + + 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, LTC_NULL); + return err; +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c new file mode 100644 index 0000000..c99a267 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c @@ -0,0 +1,182 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/* ### Point doubling in Jacobian coordinate system ### + * + * let us have a curve: y^2 = x^3 + a*x + b + * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6 + * + * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where: + * Xr = M^2 - 2*S + * Yr = M * (S - Xr) - 8*T + * Zr = 2 * Yp * Zp + * + * M = 3 * Xp^2 + a*Zp^4 + * T = Yp^4 + * S = 4 * Xp * Yp^2 + * + * SPECIAL CASE: when a == -3 we can compute M as + * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2) + */ + +/** + @file ltc_ecc_projective_dbl_point.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) + +/** + Double an ECC point + @param P The point to double + @param R [out] The destination of the double + @param ma ECC curve parameter a in montgomery form + @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(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp) +{ + void *t1, *t2; + int err, inf; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(mp != NULL); + + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { + return err; + } + + if (P != R) { + if ((err = ltc_ecc_copy_point(P, R)) != CRYPT_OK) { goto done; } + } + + if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* if P is point at infinity >> Result = point at infinity */ + err = ltc_ecc_set_point_xyz(1, 1, 0, R); + 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; } + } + + if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ + /* T2 = X - T1 */ + if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(t2, 0) == LTC_MP_LT) { + 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; } + } + } + else { + /* T2 = T1 * T1 */ + if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = T2 * a */ + if ((err = mp_mul(t2, ma, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = X * X */ + if ((err = mp_sqr(R->x, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = T2 + T1 */ + 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; } + } + /* T1 = T2 + T1 */ + 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; } + } + /* T1 = T2 + T1 */ + 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(t2, t1, LTC_NULL); + return err; +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c new file mode 100644 index 0000000..26c8383 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/* origin of this code - OLPC */ + +#ifdef LTC_MECC + +/** + Verify a key according to ANSI spec + @param key The key to validate + @return CRYPT_OK if successful +*/ + +int ltc_ecc_verify_key(const ecc_key *key) +{ + int err, inf; + ecc_point *point; + void *prime = key->dp.prime; + void *order = key->dp.order; + void *a = key->dp.A; + + /* Test 1: Are the x and y points of the public key in the field? */ + if (ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) { + if ((ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) || + (ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) || + (ltc_mp.compare_d(key->pubkey.x, 0) == LTC_MP_LT) || + (ltc_mp.compare_d(key->pubkey.y, 0) == LTC_MP_LT) || + (mp_iszero(key->pubkey.x) && mp_iszero(key->pubkey.y)) + ) + { + err = CRYPT_INVALID_PACKET; + goto done2; + } + } + + /* Test 2: is the public key on the curve? */ + if ((err = ltc_ecc_is_point(&key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; } + + /* Test 3: does nG = O? (n = order, O = point at infinity, G = public key) */ + point = ltc_ecc_new_point(); + if ((err = ltc_ecc_mulmod(order, &(key->pubkey), point, a, prime, 1)) != CRYPT_OK) { goto done1; } + + err = ltc_ecc_is_point_at_infinity(point, prime, &inf); + if (err != CRYPT_OK || inf) { + err = CRYPT_ERROR; + } + else { + err = CRYPT_OK; + } + +done1: + ltc_ecc_del_point(point); +done2: + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/sub.mk new file mode 100644 index 0000000..8567283 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ecc/sub.mk @@ -0,0 +1,20 @@ +srcs-y += ecc.c +srcs-y += ecc_find_curve.c +srcs-y += ecc_free.c +srcs-y += ecc_get_oid_str.c +srcs-y += ecc_make_key.c +srcs-y += ecc_set_curve.c +srcs-y += ecc_set_curve_internal.c +srcs-y += ecc_shared_secret.c +srcs-y += ecc_sign_hash.c +srcs-y += ecc_ssh_ecdsa_encode_name.c +srcs-y += ecc_verify_hash.c +srcs-y += ltc_ecc_is_point.c +srcs-y += ltc_ecc_is_point_at_infinity.c +srcs-y += ltc_ecc_map.c +srcs-y += ltc_ecc_mulmod.c +srcs-y += ltc_ecc_mulmod_timing.c +srcs-y += ltc_ecc_mul2add.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/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c new file mode 100644 index 0000000..2b710e5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_export.c + Export an Ed25519 key to a binary packet, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Export an Ed25519 key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the Ed25519 key + @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int ed25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key) +{ + LTC_ARGCHK(key != NULL); + + if (key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; + + return ec25519_export(out, outlen, which, key); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.c new file mode 100644 index 0000000..f197d59 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import.c + Import a Ed25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Import an Ed25519 public key + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + int err; + unsigned long key_len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + key_len = sizeof(key->pub); + if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { + key->type = PK_PUBLIC; + key->algo = LTC_OID_ED25519; + } + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c new file mode 100644 index 0000000..71f12de --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import_pkcs8.c + Import an Ed25519 key in PKCS#8 format, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Import an Ed25519 private key in PKCS#8 format + @param in The DER-encoded PKCS#8-formatted private key + @param inlen The length of the input data + @param passwd The password to decrypt the private key + @param passwdlen Password's length (octets) + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + curve25519_key *key) +{ + return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_ED25519, tweetnacl_crypto_sk_to_pk, key); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c new file mode 100644 index 0000000..19955d1 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import_raw.c + Set the parameters of an Ed25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Set the parameters of an Ed25519 key + + @param in The key + @param inlen The length of the key + @param which Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] Destination of the key + @return CRYPT_OK if successful +*/ +int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen == 32uL); + LTC_ARGCHK(key != NULL); + + if (which == PK_PRIVATE) { + XMEMCPY(key->priv, in, sizeof(key->priv)); + tweetnacl_crypto_sk_to_pk(key->pub, key->priv); + } else if (which == PK_PUBLIC) { + XMEMCPY(key->pub, in, sizeof(key->pub)); + } else { + return CRYPT_INVALID_ARG; + } + key->algo = LTC_OID_ED25519; + key->type = which; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c new file mode 100644 index 0000000..44978ac --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c @@ -0,0 +1,45 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import_x509.c + Import an Ed25519 key from a X.509 certificate, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_ed25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE; + XMEMCPY(key->pub, in, sizeof(key->pub)); + return CRYPT_OK; +} + +/** + Import an Ed25519 public key from a X.509 certificate + @param in The DER encoded X.509 certificate + @param inlen The length of the certificate + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_ED25519, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)s_ed25519_decode, key)) != CRYPT_OK) { + return err; + } + key->type = PK_PUBLIC; + key->algo = LTC_OID_ED25519; + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c new file mode 100644 index 0000000..b5fe919 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_make_key.c + Create an Ed25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Create an Ed25519 key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful +*/ +int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + + if ((err = tweetnacl_crypto_sign_keypair(prng, wprng, key->pub, key->priv)) != CRYPT_OK) { + return err; + } + + key->type = PK_PRIVATE; + key->algo = LTC_OID_ED25519; + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_sign.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_sign.c new file mode 100644 index 0000000..d5bf364 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_sign.c @@ -0,0 +1,126 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_shared_secret.c + Create an Ed25519 signature, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) +{ + unsigned char *s; + unsigned long long smlen; + int err; + + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(siglen != NULL); + LTC_ARGCHK(private_key != NULL); + + if (private_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; + if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + + if (*siglen < 64uL) { + *siglen = 64uL; + return CRYPT_BUFFER_OVERFLOW; + } + + smlen = msglen + 64; + s = XMALLOC(smlen); + if (s == NULL) return CRYPT_MEM; + + err = tweetnacl_crypto_sign(s, &smlen, + msg, msglen, + private_key->priv, private_key->pub, + ctx, ctxlen); + + XMEMCPY(sig, s, 64uL); + *siglen = 64uL; + +#ifdef LTC_CLEAN_STACK + zeromem(s, smlen); +#endif + XFREE(s); + + return err; +} + +/** + Create an Ed25519ctx signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param ctx [in] The context is a constant null terminated string + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) +{ + int err; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + LTC_ARGCHK(ctx != NULL); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen)) != CRYPT_OK) + return err; + + return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key); +} + +/** + Create an Ed25519ph signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param ctx [in] The context is a constant null terminated string + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) +{ + int err; + unsigned char msg_hash[64]; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) + return err; + + if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) + return err; + + return s_ed25519_sign(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, private_key); +} + +/** + Create an Ed25519 signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const curve25519_key *private_key) +{ + return s_ed25519_sign(msg, msglen, sig, siglen, NULL, 0, private_key); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_verify.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_verify.c new file mode 100644 index 0000000..e7dcc30 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/ed25519_verify.c @@ -0,0 +1,134 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_verify.c + Verify an Ed25519 signature, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_ed25519_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) +{ + unsigned char* m; + unsigned long long mlen; + int err; + + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(public_key != NULL); + + *stat = 0; + + if (siglen != 64uL) return CRYPT_INVALID_ARG; + if (public_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; + + mlen = msglen + siglen; + if ((mlen < msglen) || (mlen < siglen)) return CRYPT_OVERFLOW; + + m = XMALLOC(mlen); + if (m == NULL) return CRYPT_MEM; + + XMEMCPY(m, sig, siglen); + XMEMCPY(m + siglen, msg, msglen); + + err = tweetnacl_crypto_sign_open(stat, + m, &mlen, + m, mlen, + ctx, ctxlen, + public_key->pub); + +#ifdef LTC_CLEAN_STACK + zeromem(m, msglen + siglen); +#endif + XFREE(m); + + return err; +} + +/** + Verify an Ed25519ctx signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param ctx [in] The context + @param ctxlen [in] The size of the context + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) +{ + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + LTC_ARGCHK(ctx != NULL); + + if (ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen) != CRYPT_OK) + return CRYPT_INVALID_ARG; + + return s_ed25519_verify(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); +} + +/** + Verify an Ed25519ph signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param ctx [in] The context + @param ctxlen [in] The size of the context + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) +{ + int err; + unsigned char msg_hash[64]; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) + return err; + + if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) + return err; + + return s_ed25519_verify(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); +} + +/** + Verify an Ed25519 signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + int *stat, + const curve25519_key *public_key) +{ + return s_ed25519_verify(msg, msglen, sig, siglen, NULL, 0, stat, public_key); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/sub.mk new file mode 100644 index 0000000..cb2206d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/ed25519/sub.mk @@ -0,0 +1,7 @@ +srcs-y += ed25519_export.c +srcs-y += ed25519_import.c +srcs-y += ed25519_import_pkcs8.c +srcs-y += ed25519_import_x509.c +srcs-y += ed25519_make_key.c +srcs-y += ed25519_sign.c +srcs-y += ed25519_verify.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c new file mode 100644 index 0000000..a62dd86 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 + */ + +/** + 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 */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c new file mode 100644 index 0000000..d65f003 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_mgf1.c + The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + Perform PKCS #1 MGF1 (internal) + @param hash_idx The index of the hash desired + @param seed The seed for MGF1 + @param seedlen The length of the seed + @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 */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c new file mode 100644 index 0000000..5bb3918 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c @@ -0,0 +1,175 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_oaep_decode.c + OAEP Padding for PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + 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 +*/ +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, ret; + + 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 + + */ + + ret = CRYPT_OK; + + /* must have leading 0x00 byte */ + if (msg[0] != 0x00) { + ret = CRYPT_INVALID_PACKET; + } + + /* 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 (XMEM_NEQ(seed, DB, hLen) != 0) { + ret = CRYPT_INVALID_PACKET; + } + + /* now zeroes before a 0x01 */ + for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { + /* step... */ + } + + /* error if wasn't 0x01 */ + if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { + ret = CRYPT_INVALID_PACKET; + } + + /* rest is the message (and skip 0x01) */ + if ((modulus_len - hLen - 1 - ++x) > *outlen) { + ret = CRYPT_INVALID_PACKET; + } + + if (ret == CRYPT_OK) { + /* copy message */ + *outlen = modulus_len - hLen - 1 - x; + XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x); + + /* valid packet */ + *res = 1; + } + err = ret; + +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 */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c new file mode 100644 index 0000000..93ee1db --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c @@ -0,0 +1,161 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_oaep_encode.c + OAEP Padding for PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + 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 */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c new file mode 100644 index 0000000..438030e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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 */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c new file mode 100644 index 0000000..9718196 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c @@ -0,0 +1,167 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include +#include "tomcrypt_private.h" + +/** + @file pkcs_1_pss_decode.c + PKCS #1 PSS Signature Padding, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + 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_bitlen--; + 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; + } + + /* 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)))) != 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)); + + /* 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 (FTMN_CALLEE_DONE_MEMCMP(XMEM_NEQ, 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 */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c new file mode 100644 index 0000000..00e3bce --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c @@ -0,0 +1,164 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_pss_encode.c + PKCS #1 PSS Signature Padding, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + 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_bitlen--; + 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); + + /* 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 */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c new file mode 100644 index 0000000..e988060 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c @@ -0,0 +1,102 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** @file pkcs_1_v1_5_decode.c + * + * PKCS #1 v1.5 Padding. (Andreas Lange) + */ + +#ifdef LTC_PKCS_1 + +/** @brief 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 + */ +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; + } + + result = CRYPT_OK; + + /* separate encoded message */ + + if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) { + result = CRYPT_INVALID_PACKET; + } + + if (block_type == 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) { + /* There was no octet with hexadecimal value 0x00 to separate ps from m. + */ + result = CRYPT_INVALID_PACKET; + } + } 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; + } + + ps_len = i - 2; + } + + if (ps_len < 8) + { + /* The length of ps is less than 8 octets. + */ + result = CRYPT_INVALID_PACKET; + } + + if (*outlen < (msglen - (2 + ps_len + 1))) { + result = CRYPT_INVALID_PACKET; + } + + if (result == CRYPT_OK) { + *outlen = (msglen - (2 + ps_len + 1)); + XMEMCPY(out, &msg[2 + ps_len + 1], *outlen); + + /* valid packet */ + *is_valid = 1; + } + + return result; +} /* pkcs_1_v1_5_decode */ + +#endif /* #ifdef LTC_PKCS_1 */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c new file mode 100644 index 0000000..5172425 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c @@ -0,0 +1,99 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/*! \file pkcs_1_v1_5_encode.c + * + * PKCS #1 v1.5 Padding (Andreas Lange) + */ + +#ifdef LTC_PKCS_1 + +/*! \brief 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_PKCS_1_EME) + * \param prng_idx The index of the PRNG desired (only for 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_PKCS_1_EMSA) && + (block_type != LTC_PKCS_1_EME)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (block_type == 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_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 */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk new file mode 100644 index 0000000..43f96b9 --- /dev/null +++ b/optee/optee_os/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/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c new file mode 100644 index 0000000..34a11f9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c @@ -0,0 +1,93 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_decrypt_key.c + RSA PKCS #1 Decryption, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + 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_PKCS_1_OAEP or 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, const 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_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_OAEP)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == 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_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 PKCS #1 v1.5 depad the packet */ + err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat); + } + + XFREE(tmp); + return err; +} + +#endif /* LTC_MRSA */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c new file mode 100644 index 0000000..6694260 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c @@ -0,0 +1,92 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_encrypt_key.c + RSA PKCS #1 encryption, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + (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_PKCS_1_OAEP or 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, + const 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_PKCS_1_V1_5) && + (padding != 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_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_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 { + /* PKCS #1 v1.5 pad the key */ + x = *outlen; + if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME, + modulus_bitlen, prng, prng_idx, + out, &x)) != CRYPT_OK) { + return err; + } + } + + /* rsa exptmod the OAEP or PKCS #1 v1.5 pad */ + return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key); +} + +#endif /* LTC_MRSA */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c new file mode 100644 index 0000000..225224d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c @@ -0,0 +1,91 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_export.c + Export RSA PKCS keys, Tom St Denis +*/ + +#ifdef LTC_MRSA + +/** + This will export either an RSAPublicKey or RSAPrivateKey [defined in 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, const rsa_key *key) +{ + unsigned long zero=0; + int err, std; + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = type & PK_STD; + type &= ~PK_STD; + + if (type == PK_PRIVATE && key->type != PK_PRIVATE) { + return CRYPT_PK_TYPE_MISMATCH; + } + + 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); + } + + if (type == PK_PUBLIC) { + /* public key */ + unsigned long tmplen, *ptmplen; + unsigned char* tmp = NULL; + + if (std) { + tmplen = (unsigned long)(mp_count_bits(key->N) / 8) * 2 + 8; + tmp = XMALLOC(tmplen); + ptmplen = &tmplen; + if (tmp == NULL) { + return CRYPT_MEM; + } + } + else { + tmp = out; + ptmplen = outlen; + } + + err = der_encode_sequence_multi(tmp, ptmplen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL); + + if ((err != CRYPT_OK) || !std) { + goto finish; + } + + err = x509_encode_subject_public_key_info(out, outlen, + LTC_OID_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0); + +finish: + if (tmp != out) XFREE(tmp); + return err; + } + + return CRYPT_INVALID_ARG; +} + +#endif /* LTC_MRSA */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c new file mode 100644 index 0000000..73daee5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c @@ -0,0 +1,172 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_exptmod.c + RSA PKCS exptmod, Tom St Denis + Added RSA blinding --nmav +*/ + +#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, + const rsa_key *key) +{ + void *tmp, *tmpa, *tmpb; + #ifdef LTC_RSA_BLINDING + void *rnd, *rndi /* inverse of rnd */; + #endif + unsigned long x; + int err, has_crt_parameters; + + 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, +#ifdef LTC_RSA_BLINDING + &rnd, &rndi, +#endif /* LTC_RSA_BLINDING */ + 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? */ + if (which == PK_PRIVATE) { + #ifdef LTC_RSA_BLINDING + /* do blinding */ + err = mp_rand(rnd, mp_get_digit_count(key->N)); + if (err != CRYPT_OK) { + goto error; + } + + /* rndi = 1/rnd mod N */ + err = mp_invmod(rnd, key->N, rndi); + if (err != CRYPT_OK) { + goto error; + } + + /* rnd = rnd^e */ + err = mp_exptmod( rnd, key->e, key->N, rnd); + if (err != CRYPT_OK) { + goto error; + } + + /* tmp = tmp*rnd mod N */ + err = mp_mulmod( tmp, rnd, key->N, tmp); + if (err != CRYPT_OK) { + goto error; + } + #endif /* LTC_RSA_BLINDING */ + + has_crt_parameters = (key->p != NULL) && (mp_get_digit_count(key->p) != 0) && + (key->q != NULL) && (mp_get_digit_count(key->q) != 0) && + (key->dP != NULL) && (mp_get_digit_count(key->dP) != 0) && + (key->dQ != NULL) && (mp_get_digit_count(key->dQ) != 0) && + (key->qP != NULL) && (mp_get_digit_count(key->qP) != 0); + + if (!has_crt_parameters) { + /* + * In case CRT optimization parameters are not provided, + * the private key is directly used to exptmod it + */ + if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; } + } else { + /* 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; } + } + + #ifdef LTC_RSA_BLINDING + /* unblind */ + err = mp_mulmod( tmp, rndi, key->N, tmp); + if (err != CRYPT_OK) { + goto error; + } + #endif + + #ifdef LTC_RSA_CRT_HARDENING + if (has_crt_parameters) { + if ((err = mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(tmpb, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; } + if (mp_cmp(tmpa, tmpb) != LTC_MP_EQ) { err = CRYPT_ERROR; goto error; } + } + #endif + } 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( +#ifdef LTC_RSA_BLINDING + rndi, rnd, +#endif /* LTC_RSA_BLINDING */ + tmpb, tmpa, tmp, NULL); + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_get_size.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_get_size.c new file mode 100644 index 0000000..72d3f7a --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_get_size.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_get_size.c + Retrieve the size of an RSA key, Steffen Jaeckel. +*/ + +#ifdef LTC_MRSA + +/** + Retrieve the size in bytes of an RSA key. + @param key The RSA key + @return The size in bytes of the RSA key or INT_MAX on error. +*/ +int rsa_get_size(const rsa_key *key) +{ + int ret = INT_MAX; + LTC_ARGCHK(key != NULL); + + if (key) + { + ret = mp_unsigned_bin_size(key->N); + } /* if */ + + return ret; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c new file mode 100644 index 0000000..1240a77 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c @@ -0,0 +1,143 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_import.c + Import a PKCS RSA key, Tom St Denis +*/ + +#ifdef LTC_MRSA + + +/** + Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] + + The `key` passed into this function has to be already initialized and will + NOT be free'd on error! + + @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 +*/ +int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + unsigned long version = -1; + + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_EOL, 0UL, NULL); + + if (err == CRYPT_OVERFLOW) { + /* the version would fit into an LTC_ASN1_SHORT_INTEGER + * so we try to decode as a public key + */ + 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) { + key->type = PK_PUBLIC; + } + goto LBL_OUT; + } else if (err != CRYPT_INPUT_TOO_LONG) { + /* couldn't decode the version, so error out */ + goto LBL_OUT; + } + + if (version == 0) { + /* it's a private key */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + 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) { + goto LBL_OUT; + } + key->type = PK_PRIVATE; + } else if (version == 1) { + /* we don't support multi-prime RSA */ + err = CRYPT_PK_INVALID_TYPE; + goto LBL_OUT; + } + err = CRYPT_OK; +LBL_OUT: + return err; +} + +/** + Import multiple formats of RSA public and private keys. + + RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] + SubjectPublicKeyInfo formatted public keys + + @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; + unsigned char *tmpbuf=NULL; + unsigned long tmpbuf_len, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if ((err = rsa_init(key)) != CRYPT_OK) { + return err; + } + + /* see if the OpenSSL DER format RSA public key will work */ + tmpbuf_len = inlen; + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } + + len = 0; + err = x509_decode_subject_public_key_info(in, inlen, + LTC_OID_RSA, tmpbuf, &tmpbuf_len, + LTC_ASN1_NULL, NULL, &len); + + if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */ + + /* now it should be SEQUENCE { INTEGER, INTEGER } */ + if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len, + 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; + err = CRYPT_OK; + goto LBL_FREE; + } + + /* not SSL public key, try to match against PKCS #1 standards */ + if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) { + goto LBL_FREE; + } + +LBL_ERR: + rsa_free(key); + +LBL_FREE: + if (tmpbuf != NULL) { + XFREE(tmpbuf); + } + return err; +} + +#endif /* LTC_MRSA */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c new file mode 100644 index 0000000..9e02585 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c @@ -0,0 +1,116 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_import_pkcs8.c + Import a PKCS RSA key +*/ + +#ifdef LTC_MRSA + +/* Public-Key Cryptography Standards (PKCS) #8: + * Private-Key Information Syntax Specification Version 1.2 + * https://tools.ietf.org/html/rfc5208 + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * where: + * - Version ::= INTEGER + * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * - PrivateKey ::= OCTET STRING + * - Attributes ::= SET OF Attribute + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData } + * where: + * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * - EncryptedData ::= OCTET STRING + */ + +/** + Import an RSAPrivateKey in PKCS#8 format + @param in The packet to import from + @param inlen It's length (octets) + @param passwd The password for decrypting privkey + @param passwdlen Password'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_pkcs8(const unsigned char *in, unsigned long inlen, + const void *passwd, unsigned long passwdlen, + rsa_key *key) +{ + int err; + unsigned char *buf1 = NULL, *buf2 = NULL; + unsigned long buf1len, buf2len; + unsigned long oid[16], version; + const char *rsaoid; + ltc_asn1_list alg_seq[2], top_seq[3]; + ltc_asn1_list *l = NULL; + unsigned char *decrypted = NULL; + unsigned long decryptedlen; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* get RSA alg oid */ + err = pk_get_oid(LTC_OID_RSA, &rsaoid); + if (err != CRYPT_OK) { goto LBL_NOFREE; } + + /* alloc buffers */ + buf1len = inlen; /* approx. */ + buf1 = XMALLOC(buf1len); + if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; } + buf2len = inlen; /* approx. */ + buf2 = XMALLOC(buf2len); + if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; } + + /* init key */ + if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE2; } + + /* try to decode encrypted priv key */ + if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) { + goto LBL_ERR; + } + decrypted = l->data; + decryptedlen = l->size; + + /* try to decode unencrypted priv key */ + LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL); + LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL); + LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SHORT_INTEGER, &version, 1UL); + LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL); + LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len); + err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL); + if (err != CRYPT_OK) { goto LBL_ERR; } + + /* check alg oid */ + if ((err = pk_oid_cmp_with_asn1(rsaoid, &alg_seq[0])) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = rsa_import_pkcs1(buf1, top_seq[2].size, key)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PRIVATE; + err = CRYPT_OK; + goto LBL_FREE2; + +LBL_ERR: + rsa_free(key); +LBL_FREE2: + if (l) der_free_sequence_flexi(l); + XFREE(buf2); +LBL_FREE1: + XFREE(buf1); +LBL_NOFREE: + return err; +} + +#endif /* LTC_MRSA */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c new file mode 100644 index 0000000..e921aae --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_import.c + Import an RSA key from a X.509 certificate, Steffen Jaeckel +*/ + +#ifdef LTC_MRSA + +static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + /* now it should be SEQUENCE { INTEGER, INTEGER } */ + return der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL); +} + +/** + Import an RSA key from a X.509 certificate + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if ((err = rsa_init(key)) != CRYPT_OK) { + return err; + } + + if ((err = x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_RSA, LTC_ASN1_NULL, + NULL, NULL, + (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { + rsa_free(key); + } else { + key->type = PK_PUBLIC; + } + + return err; +} + +#endif /* LTC_MRSA */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c new file mode 100644 index 0000000..2d0712f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c @@ -0,0 +1,103 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_key.c + Free an RSA key, Tom St Denis + Basic operations on an RSA key, Steffen Jaeckel +*/ + +#ifdef LTC_MRSA +#include + +static void s_mpi_shrink_multi(void **a, ...) +{ + void **cur; + unsigned n; + int err; + va_list args; + void *tmp[10] = { 0 }; + void **arg[10] = { 0 }; + + /* We re-allocate in the order that we received the varargs */ + n = 0; + err = CRYPT_ERROR; + cur = a; + va_start(args, a); + while (cur != NULL) { + if (n >= sizeof(tmp)/sizeof(tmp[0])) { + goto out; + } + if (*cur != NULL) { + arg[n] = cur; + if ((err = mp_init_copy(&tmp[n], *arg[n])) != CRYPT_OK) { + goto out; + } + n++; + } + cur = va_arg(args, void**); + } + va_end(args); + + /* but we clear the old values in the reverse order */ + while (n != 0 && arg[--n] != NULL) { + mp_clear(*arg[n]); + *arg[n] = tmp[n]; + } +out: + va_end(args); + /* clean-up after an error + * or after this was called with too many args + */ + if ((err != CRYPT_OK) || + (n >= sizeof(tmp)/sizeof(tmp[0]))) { + for (n = 0; n < sizeof(tmp)/sizeof(tmp[0]); ++n) { + if (tmp[n] != NULL) { + mp_clear(tmp[n]); + } + } + } +} + +/** + This shrinks the allocated memory of a RSA key + + It will use up some more memory temporarily, + but then it will free-up the entire sequence that + was once allocated when the key was created/populated. + + This only works with libtommath >= 1.2.0 in earlier versions + it has the inverse effect due to the way it worked internally. + Also works for GNU MP, tomsfastmath naturally shows no effect. + + @param key The RSA key to shrink +*/ +void rsa_shrink_key(rsa_key *key) +{ + LTC_ARGCHKVD(key != NULL); + s_mpi_shrink_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL); +} + +/** + Init an RSA key + @param key The RSA key to free + @return CRYPT_OK if successful +*/ +int rsa_init(rsa_key *key) +{ + LTC_ARGCHK(key != NULL); + return mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL); +} + +/** + Free an RSA key from memory + @param key The RSA key to free +*/ +void rsa_free(rsa_key *key) +{ + LTC_ARGCHKVD(key != NULL); + mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c new file mode 100644 index 0000000..6bfc041 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c @@ -0,0 +1,165 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_make_key.c + RSA key generation, Tom St Denis +*/ + +#ifdef LTC_MRSA + +static int s_rsa_make_key(prng_state *prng, int wprng, int size, void *e, rsa_key *key) +{ + void *p, *q, *tmp1, *tmp2; + int err; + + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(size > 0); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* make primes p and q (optimization provided by Wayne Scott) */ + + /* make prime "p" */ + do { + if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = p-1 */ + if ((err = mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* 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 cleanup; } + if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = q-1 */ + if ((err = mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* 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 cleanup; } /* tmp2 = p-1 */ + /* tmp1 = q-1 (previous do/while loop) */ + if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */ + + /* make key */ + if ((err = rsa_init(key)) != CRYPT_OK) { + goto errkey; + } + + if ((err = mp_copy( e, key->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 = p-1 */ + if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = q-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: + rsa_free(key); +cleanup: + mp_clear_multi(tmp2, tmp1, q, p, LTC_NULL); + return err; +} + +/** + Create an RSA key based on a long public exponent type + @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 *tmp_e; + int err; + + if ((e < 3) || ((e & 1) == 0)) { + return CRYPT_INVALID_ARG; + } + + if ((err = mp_init(&tmp_e)) != CRYPT_OK) { + return err; + } + + if ((err = mp_set_int(tmp_e, e)) == CRYPT_OK) + err = s_rsa_make_key(prng, wprng, size, tmp_e, key); + + mp_clear(tmp_e); + + return err; +} + +/** + Create an RSA key based on a hexadecimal public exponent type + @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 elen The length of e (octets) + @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_ubin_e(prng_state *prng, int wprng, int size, + const unsigned char *e, unsigned long elen, rsa_key *key) +{ + int err; + void *tmp_e; + + if ((err = mp_init(&tmp_e)) != CRYPT_OK) { + return err; + } + + if ((err = mp_read_unsigned_bin(tmp_e, (unsigned char *)e, elen)) == CRYPT_OK) + err = rsa_make_key_bn_e(prng, wprng, size, tmp_e, key); + + mp_clear(tmp_e); + + return err; +} + +/** + Create an RSA key based on a bignumber public exponent type + @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_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key) +{ + int err; + int e_bits; + + e_bits = mp_count_bits(e); + if ((e_bits > 1 && e_bits < 256) && (mp_get_digit(e, 0) & 1)) { + err = s_rsa_make_key(prng, wprng, size, e, key); + } else { + err = CRYPT_INVALID_ARG; + } + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_set.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_set.c new file mode 100644 index 0000000..d4dc6ed --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_set.c @@ -0,0 +1,123 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +#ifdef LTC_MRSA + +/** + Import RSA key from raw numbers + + @param N RSA's N + @param Nlen RSA's N's length + @param e RSA's e + @param elen RSA's e's length + @param d RSA's d (only private key, NULL for public key) + @param dlen RSA's d's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_key(const unsigned char *N, unsigned long Nlen, + const unsigned char *e, unsigned long elen, + const unsigned char *d, unsigned long dlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(N != NULL); + LTC_ARGCHK(e != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if ((err = rsa_init(key)) != CRYPT_OK) return err; + + if ((err = mp_read_unsigned_bin(key->N , (unsigned char *)N , Nlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->e , (unsigned char *)e , elen)) != CRYPT_OK) { goto LBL_ERR; } + if (d && dlen) { + if ((err = mp_read_unsigned_bin(key->d , (unsigned char *)d , dlen)) != CRYPT_OK) { goto LBL_ERR; } + key->type = PK_PRIVATE; + } + else { + key->type = PK_PUBLIC; + } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +/** + Import factors of an RSA key from raw numbers + + Only for private keys. + + @param p RSA's p + @param plen RSA's p's length + @param q RSA's q + @param qlen RSA's q's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_factors(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(q != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; + + if ((err = mp_read_unsigned_bin(key->p , (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->q , (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +/** + Import CRT parameters of an RSA key from raw numbers + + Only for private keys. + + @param dP RSA's dP + @param dPlen RSA's dP's length + @param dQ RSA's dQ + @param dQlen RSA's dQ's length + @param qP RSA's qP + @param qPlen RSA's qP's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, + const unsigned char *dQ, unsigned long dQlen, + const unsigned char *qP, unsigned long qPlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(dP != NULL); + LTC_ARGCHK(dQ != NULL); + LTC_ARGCHK(qP != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; + + if ((err = mp_read_unsigned_bin(key->dP, (unsigned char *)dP, dPlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->dQ, (unsigned char *)dQ, dQlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->qP, (unsigned char *)qP, qPlen)) != CRYPT_OK) { goto LBL_ERR; } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +#endif /* LTC_MRSA */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c new file mode 100644 index 0000000..d7bc5af --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c @@ -0,0 +1,136 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_sign_hash.c + RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + 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_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) + @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, + const 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_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_PSS) && + (padding != LTC_PKCS_1_V1_5_NA1)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == LTC_PKCS_1_PSS) { + /* valid prng ? */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + } + + if (padding != LTC_PKCS_1_V1_5_NA1) { + /* 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_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 { + /* PKCS #1 v1.5 pad the hash */ + unsigned char *tmpin; + + if (padding == LTC_PKCS_1_V1_5) { + 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; + } + } else { + /* set the pointer and data-length to the input values */ + tmpin = (unsigned char *)in; + y = inlen; + } + + x = *outlen; + err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); + + if (padding == LTC_PKCS_1_V1_5) { + XFREE(tmpin); + } + + if (err != CRYPT_OK) { + return err; + } + } + + /* RSA encode it */ + return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); +} + +#endif /* LTC_MRSA */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c new file mode 100644 index 0000000..802aac3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_sign_saltlen_get.c + Retrieve the maximum size of the salt, Steffen Jaeckel. +*/ + +#ifdef LTC_MRSA + +/** + Retrieve the maximum possible size of the salt when creating a PKCS#1 PSS signature. + @param padding Type of padding (LTC_PKCS_1_PSS only) + @param hash_idx The index of the desired hash + @param key The RSA key + @return The maximum salt length in bytes or INT_MAX on error. +*/ +int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key) +{ + int ret = INT_MAX; + LTC_ARGCHK(key != NULL); + + if ((hash_is_valid(hash_idx) == CRYPT_OK) && + (padding == LTC_PKCS_1_PSS)) + { + ret = rsa_get_size(key); + if (ret < INT_MAX) + { + ret -= (hash_descriptor[hash_idx]->hashsize + 2); + } /* if */ + } /* if */ + + return ret; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c new file mode 100644 index 0000000..6ce763d --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c @@ -0,0 +1,198 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include +#include "tomcrypt_private.h" + +/** + @file rsa_verify_hash.c + RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + 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_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) + @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, const rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x; + int err; + unsigned int inc1 = 0; + unsigned char *tmpbuf; + struct ftmn ftmn = { }; + + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid */ + *stat = 0; + FTMN_SET_CHECK_RES(&ftmn, FTMN_INCR0, 1); + + /* valid padding? */ + + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_PSS) && + (padding != LTC_PKCS_1_V1_5_NA1)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding != LTC_PKCS_1_V1_5_NA1) { + /* 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_PKCS_1_PSS) { + /* PSS decode and verify it */ + + FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("pkcs_1_pss_decode")); + if(modulus_bitlen%8 == 1){ + err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat); + } + else{ + err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); + } + if (*stat) { + FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR1, 0); + inc1 = 1; + } + FTMN_POP_LINKED_CALL(&ftmn); + + } else { + /* PKCS #1 v1.5 decode it */ + unsigned char *out; + unsigned long outlen; + int decoded; + + /* 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_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) { + XFREE(out); + goto bail_2; + } + + if (padding == LTC_PKCS_1_V1_5) { + unsigned long loid[16], reallen; + 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; + } + + /* 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_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { + /* fallback to Legacy:missing NULL */ + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1); + if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { + XFREE(out); + goto bail_2; + } + } + + if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) { + XFREE(out); + goto bail_2; + } + + /* test OID */ + if ((reallen == outlen) && + (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) && + (ftmn_set_check_res_memcmp(&ftmn, FTMN_INCR1, XMEMCMP, + siginfo[1].data, hash, hashlen) == 0)) { + *stat = 1; + } + inc1 = 1; + } else { + /* only check if the hash is equal */ + if ((hashlen == outlen) && + (ftmn_set_check_res_memcmp(&ftmn, FTMN_INCR1, XMEMCMP, + out, hash, hashlen) == 0)) { + *stat = 1; + } + inc1 = 1; + } + +#ifdef LTC_CLEAN_STACK + zeromem(out, outlen); +#endif + XFREE(out); + } + +bail_2: +#ifdef LTC_CLEAN_STACK + zeromem(tmpbuf, siglen); +#endif + XFREE(tmpbuf); + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1, inc1), !*stat); + return err; +} + +#endif /* LTC_MRSA */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/rsa/sub.mk new file mode 100644 index 0000000..f0b8975 --- /dev/null +++ b/optee/optee_os/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_import.c +srcs-y += rsa_key.c +srcs-y += rsa_make_key.c +srcs-y += rsa_sign_hash.c +srcs-y += rsa_verify_hash.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/sub.mk new file mode 100644 index 0000000..dca26a5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/sub.mk @@ -0,0 +1,11 @@ +subdirs-$(_CFG_CORE_LTC_ASN1) += asn1 +subdirs-$(_CFG_CORE_LTC_DSA) += dsa +# PKCS1 paddings are used with RSA only +subdirs-$(_CFG_CORE_LTC_RSA) += pkcs1 +subdirs-$(_CFG_CORE_LTC_RSA) += rsa +subdirs-$(_CFG_CORE_LTC_DH) += dh +subdirs-$(_CFG_CORE_LTC_ECC) += ecc +subdirs-$(_CFG_CORE_LTC_X25519) += ec25519 +subdirs-$(_CFG_CORE_LTC_X25519) += x25519 +subdirs-$(_CFG_CORE_LTC_ED25519) += ec25519 +subdirs-$(_CFG_CORE_LTC_ED25519) += ed25519 diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/sub.mk new file mode 100644 index 0000000..853371e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/sub.mk @@ -0,0 +1,4 @@ +srcs-y += x25519_export.c +srcs-y += x25519_import.c +srcs-y += x25519_make_key.c +srcs-y += x25519_shared_secret.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_export.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_export.c new file mode 100644 index 0000000..0687c13 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_export.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_export.c + Export a X25519 key to a binary packet, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Export a X25519 key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the X25519 key + @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int x25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key) +{ + LTC_ARGCHK(key != NULL); + + if (key->algo != LTC_OID_X25519) return CRYPT_PK_INVALID_TYPE; + + return ec25519_export(out, outlen, which, key); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c new file mode 100644 index 0000000..247885f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_import.c + Import a X25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Import a X25519 key + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + int err; + unsigned long key_len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + key_len = sizeof(key->pub); + if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { + key->type = PK_PUBLIC; + key->algo = LTC_OID_X25519; + } + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c new file mode 100644 index 0000000..8b577c3 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_import_pkcs8.c + Import a X25519 key in PKCS#8 format, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Import a X25519 private key in PKCS#8 format + @param in The DER-encoded PKCS#8-formatted private key + @param inlen The length of the input data + @param passwd The password to decrypt the private key + @param passwdlen Password's length (octets) + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + curve25519_key *key) +{ + return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_X25519, tweetnacl_crypto_scalarmult_base, key); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c new file mode 100644 index 0000000..e86e8c6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_import_raw.c + Set the parameters of a X25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Set the parameters of a X25519 key + + @param in The key + @param inlen The length of the key + @param which Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] Destination of the key + @return CRYPT_OK if successful +*/ +int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen == 32uL); + LTC_ARGCHK(key != NULL); + + if (which == PK_PRIVATE) { + XMEMCPY(key->priv, in, sizeof(key->priv)); + tweetnacl_crypto_scalarmult_base(key->pub, key->priv); + } else if (which == PK_PUBLIC) { + XMEMCPY(key->pub, in, sizeof(key->pub)); + } else { + return CRYPT_INVALID_ARG; + } + key->algo = LTC_OID_X25519; + key->type = which; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.c new file mode 100644 index 0000000..043b6ad --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.c @@ -0,0 +1,45 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_import_x509.c + Import a X25519 key from a X.509 certificate, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_x25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE; + XMEMCPY(key->pub, in, sizeof(key->pub)); + return CRYPT_OK; +} + +/** + Import a X25519 public key from a X.509 certificate + @param in The DER encoded X.509 certificate + @param inlen The length of the certificate + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_X25519, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)s_x25519_decode, key)) != CRYPT_OK) { + return err; + } + key->type = PK_PUBLIC; + key->algo = LTC_OID_X25519; + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_make_key.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_make_key.c new file mode 100644 index 0000000..9080cbd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_make_key.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_make_key.c + Create a X25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Create a X25519 key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful +*/ +int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (prng_descriptor[wprng]->read(key->priv, sizeof(key->priv), prng) != sizeof(key->priv)) { + return CRYPT_ERROR_READPRNG; + } + + tweetnacl_crypto_scalarmult_base(key->pub, key->priv); + + key->type = PK_PRIVATE; + key->algo = LTC_OID_X25519; + + return err; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_shared_secret.c b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_shared_secret.c new file mode 100644 index 0000000..eaea1c0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/pk/x25519/x25519_shared_secret.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_shared_secret.c + Create a X25519 shared secret, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Create a X25519 shared secret. + @param private_key The private X25519 key in the pair + @param public_key The public X25519 key in the pair + @param out [out] The destination of the shared data + @param outlen [in/out] The max size and resulting size of the shared data. + @return CRYPT_OK if successful +*/ +int x25519_shared_secret(const curve25519_key *private_key, + const curve25519_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if(private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + + if(*outlen < 32uL) { + *outlen = 32uL; + return CRYPT_BUFFER_OVERFLOW; + } + + tweetnacl_crypto_scalarmult(out, private_key->priv, public_key->pub); + *outlen = 32uL; + + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/chacha20.c b/optee/optee_os/core/lib/libtomcrypt/src/prngs/chacha20.c new file mode 100644 index 0000000..d9bd7b0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/chacha20.c @@ -0,0 +1,218 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + + /* the idea of re-keying loosely follows the approach used in: + * http://bxr.su/OpenBSD/lib/libc/crypt/arc4random.c + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20_PRNG + +const struct ltc_prng_descriptor chacha20_prng_desc = +{ + "chacha20", + 40, + &chacha20_prng_start, + &chacha20_prng_add_entropy, + &chacha20_prng_ready, + &chacha20_prng_read, + &chacha20_prng_done, + &chacha20_prng_export, + &chacha20_prng_import, + &chacha20_prng_test +}; + +/** + Start the PRNG + @param prng The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int chacha20_prng_start(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent)); + prng->u.chacha.idx = 0; + LTC_MUTEX_INIT(&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 chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char buf[40]; + unsigned long i; + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { + /* chacha20_prng_ready() was already called, do "rekey" operation */ + if ((err = chacha_keystream(&prng->u.chacha.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; + for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; + /* key 32 bytes, 20 rounds */ + if ((err = chacha_setup(&prng->u.chacha.s, buf, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; + /* iv 8 bytes */ + if ((err = chacha_ivctr64(&prng->u.chacha.s, buf + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; + /* clear KEY + IV */ + zeromem(buf, sizeof(buf)); + } + else { + /* chacha20_prng_ready() was not called yet, add entropy to ent buffer */ + while (inlen--) prng->u.chacha.ent[prng->u.chacha.idx++ % sizeof(prng->u.chacha.ent)] ^= *in++; + } + err = CRYPT_OK; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int chacha20_prng_ready(prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } + /* key 32 bytes, 20 rounds */ + if ((err = chacha_setup(&prng->u.chacha.s, prng->u.chacha.ent, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; + /* iv 8 bytes */ + if ((err = chacha_ivctr64(&prng->u.chacha.s, prng->u.chacha.ent + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; + XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent)); + prng->u.chacha.idx = 0; + prng->ready = 1; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + 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 chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + if (outlen == 0 || prng == NULL || out == NULL) return 0; + LTC_MUTEX_LOCK(&prng->lock); + if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } + if (chacha_keystream(&prng->u.chacha.s, out, outlen) != CRYPT_OK) outlen = 0; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int chacha20_prng_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + err = chacha_done(&prng->u.chacha.s); + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&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 +*/ +LTC_PRNG_EXPORT(chacha20_prng) + +/** + 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 chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + if (inlen < (unsigned long)chacha20_prng_desc.export_size) return CRYPT_INVALID_ARG; + + if ((err = chacha20_prng_start(prng)) != CRYPT_OK) return err; + if ((err = chacha20_prng_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int chacha20_prng_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + prng_state st; + unsigned char en[] = { 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 }; + unsigned char dmp[300]; + unsigned long dmplen = sizeof(dmp); + unsigned char out[500]; + unsigned char t1[] = { 0x59, 0xB2, 0x26, 0x95, 0x2B, 0x01, 0x8F, 0x05, 0xBE, 0xD8 }; + unsigned char t2[] = { 0x47, 0xC9, 0x0D, 0x03, 0xE4, 0x75, 0x34, 0x27, 0xBD, 0xDE }; + unsigned char t3[] = { 0xBC, 0xFA, 0xEF, 0x59, 0x37, 0x7F, 0x1A, 0x91, 0x1A, 0xA6 }; + int err; + + if ((err = chacha20_prng_start(&st)) != CRYPT_OK) return err; + /* add entropy to uninitialized prng */ + if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; + if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; + if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + /* add entropy to already initialized prng */ + if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if ((err = chacha20_prng_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; + if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; + if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; + if ((err = chacha20_prng_import(dmp, dmplen, &st)) != CRYPT_OK) return err; + if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; + if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t3, sizeof(t3), "CHACHA-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; + if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/fortuna.c b/optee/optee_os/core/lib/libtomcrypt/src/prngs/fortuna.c new file mode 100644 index 0000000..6f50098 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/fortuna.c @@ -0,0 +1,520 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED +#if defined(_WIN32) + #include +#elif defined(LTC_CLOCK_GETTIME) + #include /* struct timespec + clock_gettime */ +#else + #include /* struct timeval + gettimeofday */ +#endif +#endif + +/** + @file fortuna.c + Fortuna PRNG, Tom St Denis +*/ + +/* Implementation of Fortuna by Tom St Denis + +We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources" +in the AddEntropy function are fixed to 0. Second since no reliable timer is provided +we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to the read function */ + +#ifdef LTC_FORTUNA + +/* requries LTC_SHA256 and AES */ +#if !(defined(LTC_RIJNDAEL) && defined(LTC_SHA256)) + #error LTC_FORTUNA requires LTC_SHA256 and LTC_RIJNDAEL (AES) +#endif + +#ifndef LTC_FORTUNA_POOLS + #warning LTC_FORTUNA_POOLS was not previously defined (old headers?) + #define LTC_FORTUNA_POOLS 32 +#endif + +#if LTC_FORTUNA_POOLS < 4 || LTC_FORTUNA_POOLS > 32 + #error LTC_FORTUNA_POOLS must be in [4..32] +#endif + +const struct ltc_prng_descriptor fortuna_desc = { + "fortuna", + 64, + &fortuna_start, + &fortuna_add_entropy, + &fortuna_ready, + &fortuna_read, + &fortuna_done, + &fortuna_export, + &fortuna_import, + &fortuna_test +}; + +/* update the IV */ +static void s_fortuna_update_iv(prng_state *prng) +{ + int x; + unsigned char *IV; + /* update IV */ + IV = prng->u.fortuna.IV; + for (x = 0; x < 16; x++) { + IV[x] = (IV[x] + 1) & 255; + if (IV[x] != 0) break; + } +} + +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED +/* get the current time in 100ms steps */ +static ulong64 s_fortuna_current_time(void) +{ + ulong64 cur_time; +#if defined(_WIN32) + FILETIME CurrentTime; + ULARGE_INTEGER ul; + GetSystemTimeAsFileTime(&CurrentTime); + ul.LowPart = CurrentTime.dwLowDateTime; + ul.HighPart = CurrentTime.dwHighDateTime; + cur_time = ul.QuadPart; /* now we have 100ns intervals since 1 January 1601 */ + cur_time -= CONST64(116444736000000000); /* subtract 100ns intervals between 1601-1970 */ + cur_time /= 10; /* 100ns intervals > microseconds */ +#elif defined(LTC_CLOCK_GETTIME) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + cur_time = (ulong64)(ts.tv_sec) * 1000000 + (ulong64)(ts.tv_nsec) / 1000; /* get microseconds */ +#else + struct timeval tv; + gettimeofday(&tv, NULL); + cur_time = (ulong64)(tv.tv_sec) * 1000000 + (ulong64)(tv.tv_usec); /* get microseconds */ +#endif + return cur_time / 100; +} +#endif + +/* reseed the PRNG */ +static int s_fortuna_reseed(prng_state *prng) +{ + unsigned char tmp[MAXBLOCKSIZE]; + hash_state md; + ulong64 reset_cnt; + int err, x; + +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED + ulong64 now = s_fortuna_current_time(); + if (now == prng->u.fortuna.wd) { + return CRYPT_OK; + } +#else + if (++prng->u.fortuna.wd < LTC_FORTUNA_WD) { + return CRYPT_OK; + } +#endif + + /* new K == LTC_SHA256(K || s) where s == LTC_SHA256(P0) || LTC_SHA256(P1) ... */ + sha256_init(&md); + if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + + reset_cnt = prng->u.fortuna.reset_cnt + 1; + + for (x = 0; x < LTC_FORTUNA_POOLS; x++) { + if (x == 0 || ((reset_cnt >> (x-1)) & 1) == 0) { + /* terminate this hash */ + if ((err = sha256_done(&prng->u.fortuna.pool[x], tmp)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + /* add it to the string */ + if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + /* reset this pool */ + if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + } else { + break; + } + } + + /* finish key */ + if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { + return err; + } + if ((err = rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { + return err; + } + s_fortuna_update_iv(prng); + + /* reset/update internals */ + prng->u.fortuna.pool0_len = 0; +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED + prng->u.fortuna.wd = now; +#else + prng->u.fortuna.wd = 0; +#endif + prng->u.fortuna.reset_cnt = reset_cnt; + + +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); + zeromem(tmp, sizeof(tmp)); +#endif + + return CRYPT_OK; +} + +/** + "Update Seed File"-compliant update of K + + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + unsigned char tmp[MAXBLOCKSIZE]; + hash_state md; + + LTC_MUTEX_LOCK(&prng->lock); + /* new K = LTC_SHA256(K || in) */ + sha256_init(&md); + if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) { + sha256_done(&md, tmp); + goto LBL_UNLOCK; + } + if ((err = sha256_process(&md, in, inlen)) != CRYPT_OK) { + sha256_done(&md, tmp); + goto LBL_UNLOCK; + } + /* finish key */ + if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + s_fortuna_update_iv(prng); + +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); +#endif + + return err; +} + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int fortuna_start(prng_state *prng) +{ + int err, x, y; + unsigned char tmp[MAXBLOCKSIZE]; + + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + + /* initialize the pools */ + for (x = 0; x < LTC_FORTUNA_POOLS; x++) { + if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) { + for (y = 0; y < x; y++) { + sha256_done(&prng->u.fortuna.pool[y], tmp); + } + return err; + } + } + prng->u.fortuna.pool_idx = prng->u.fortuna.pool0_len = 0; + prng->u.fortuna.reset_cnt = prng->u.fortuna.wd = 0; + + /* reset bufs */ + zeromem(prng->u.fortuna.K, 32); + if ((err = rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { + for (x = 0; x < LTC_FORTUNA_POOLS; x++) { + sha256_done(&prng->u.fortuna.pool[x], tmp); + } + return err; + } + zeromem(prng->u.fortuna.IV, 16); + + LTC_MUTEX_INIT(&prng->lock) + + return CRYPT_OK; +} + +static int s_fortuna_add(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char tmp[2]; + int err; + + /* ensure inlen <= 32 */ + if (inlen > 32) { + inlen = 32; + } + + /* add s || length(in) || in to pool[pool_idx] */ + tmp[0] = (unsigned char)source; + tmp[1] = (unsigned char)inlen; + + if ((err = sha256_process(&prng->u.fortuna.pool[pool], tmp, 2)) != CRYPT_OK) { + return err; + } + if ((err = sha256_process(&prng->u.fortuna.pool[pool], in, inlen)) != CRYPT_OK) { + return err; + } + if (pool == 0) { + prng->u.fortuna.pool0_len += inlen; + } + return CRYPT_OK; /* success */ +} + +/** + Add random event to the PRNG state as proposed by the original paper. + @param source The source this random event comes from (0 .. 255) + @param pool The pool where to add the data to (0 .. LTC_FORTUNA_POOLS) + @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 fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + LTC_ARGCHK(source <= 255); + LTC_ARGCHK(pool < LTC_FORTUNA_POOLS); + + LTC_MUTEX_LOCK(&prng->lock); + + err = s_fortuna_add(source, pool, in, inlen, prng); + + LTC_MUTEX_UNLOCK(&prng->lock); + + return err; +} + +/** + 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 fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + + err = s_fortuna_add(0, prng->u.fortuna.pool_idx, in, inlen, prng); + + if (err == CRYPT_OK) { + ++(prng->u.fortuna.pool_idx); + prng->u.fortuna.pool_idx %= LTC_FORTUNA_POOLS; + } + + LTC_MUTEX_UNLOCK(&prng->lock); + + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int fortuna_ready(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + /* make sure the reseed doesn't fail because + * of the chosen rate limit */ +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED + prng->u.fortuna.wd = s_fortuna_current_time() - 1; +#else + prng->u.fortuna.wd = LTC_FORTUNA_WD; +#endif + err = s_fortuna_reseed(prng); + prng->ready = (err == CRYPT_OK) ? 1 : 0; + + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + 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 fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + unsigned char tmp[16]; + unsigned long tlen = 0; + + if (outlen == 0 || prng == NULL || out == NULL) return 0; + + LTC_MUTEX_LOCK(&prng->lock); + + if (!prng->ready) { + goto LBL_UNLOCK; + } + + /* do we have to reseed? */ + if (prng->u.fortuna.pool0_len >= 64) { + if (s_fortuna_reseed(prng) != CRYPT_OK) { + goto LBL_UNLOCK; + } + } + + /* ensure that one reseed happened before allowing to read */ + if (prng->u.fortuna.reset_cnt == 0) { + goto LBL_UNLOCK; + } + + /* now generate the blocks required */ + tlen = outlen; + + /* handle whole blocks without the extra XMEMCPY */ + while (outlen >= 16) { + /* encrypt the IV and store it */ + rijndael_ecb_encrypt(prng->u.fortuna.IV, out, &prng->u.fortuna.skey); + out += 16; + outlen -= 16; + s_fortuna_update_iv(prng); + } + + /* left over bytes? */ + if (outlen > 0) { + rijndael_ecb_encrypt(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey); + XMEMCPY(out, tmp, outlen); + s_fortuna_update_iv(prng); + } + + /* generate new key */ + rijndael_ecb_encrypt(prng->u.fortuna.IV, prng->u.fortuna.K , &prng->u.fortuna.skey); + s_fortuna_update_iv(prng); + + rijndael_ecb_encrypt(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey); + s_fortuna_update_iv(prng); + + if (rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) { + tlen = 0; + } + +LBL_UNLOCK: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + LTC_MUTEX_UNLOCK(&prng->lock); + return tlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int fortuna_done(prng_state *prng) +{ + int err, x; + unsigned char tmp[32]; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + + /* terminate all the hashes */ + for (x = 0; x < LTC_FORTUNA_POOLS; x++) { + if ((err = sha256_done(&(prng->u.fortuna.pool[x]), tmp)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + } + /* call cipher done when we invent one ;-) */ + err = CRYPT_OK; /* success */ + +LBL_UNLOCK: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&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 +*/ +LTC_PRNG_EXPORT(fortuna) + +/** + 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 fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + if (inlen < (unsigned long)fortuna_desc.export_size) { + return CRYPT_INVALID_ARG; + } + + if ((err = fortuna_start(prng)) != CRYPT_OK) { + return err; + } + + if ((err = fortuna_update_seed(in, inlen, prng)) != CRYPT_OK) { + return err; + } + + return err; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int fortuna_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + int err; + + if ((err = sha256_test()) != CRYPT_OK) { + return err; + } + return rijndael_test(); +#endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/rc4.c b/optee/optee_os/core/lib/libtomcrypt/src/prngs/rc4.c new file mode 100644 index 0000000..edcd73f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/rc4.c @@ -0,0 +1,221 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file prngs/rc4.c + RC4 PRNG, Tom St Denis +*/ + +#ifdef LTC_RC4 + +const struct ltc_prng_descriptor rc4_desc = +{ + "rc4", + 32, + &rc4_start, + &rc4_add_entropy, + &rc4_ready, + &rc4_read, + &rc4_done, + &rc4_export, + &rc4_import, + &rc4_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int rc4_start(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + /* set entropy (key) size to zero */ + prng->u.rc4.s.x = 0; + /* clear entropy (key) buffer */ + XMEMSET(&prng->u.rc4.s.buf, 0, sizeof(prng->u.rc4.s.buf)); + LTC_MUTEX_INIT(&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 rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char buf[256]; + unsigned long i; + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { + /* rc4_ready() was already called, do "rekey" operation */ + if ((err = rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; + for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; + /* initialize RC4 */ + if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; + /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ + for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf)); + zeromem(buf, sizeof(buf)); + } + else { + /* rc4_ready() was not called yet, add entropy to the buffer */ + while (inlen--) prng->u.rc4.s.buf[prng->u.rc4.s.x++ % sizeof(prng->u.rc4.s.buf)] ^= *in++; + } + err = CRYPT_OK; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int rc4_ready(prng_state *prng) +{ + unsigned char buf[256] = { 0 }; + unsigned long len; + int err, i; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } + XMEMCPY(buf, prng->u.rc4.s.buf, sizeof(buf)); + /* initialize RC4 */ + len = MIN(prng->u.rc4.s.x, 256); /* TODO: we can perhaps always use all 256 bytes */ + if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, len)) != CRYPT_OK) goto LBL_UNLOCK; + /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ + for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf)); + prng->ready = 1; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + 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 rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + if (outlen == 0 || prng == NULL || out == NULL) return 0; + LTC_MUTEX_LOCK(&prng->lock); + if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } + if (rc4_stream_keystream(&prng->u.rc4.s, out, outlen) != CRYPT_OK) outlen = 0; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int rc4_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + err = rc4_stream_done(&prng->u.rc4.s); + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&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 +*/ +LTC_PRNG_EXPORT(rc4) + +/** + 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 rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + if (inlen < (unsigned long)rc4_desc.export_size) return CRYPT_INVALID_ARG; + + if ((err = rc4_start(prng)) != CRYPT_OK) return err; + if ((err = rc4_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int rc4_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + prng_state st; + unsigned char en[] = { 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 }; + unsigned char dmp[500]; + unsigned long dmplen = sizeof(dmp); + unsigned char out[1000]; + unsigned char t1[] = { 0xE0, 0x4D, 0x9A, 0xF6, 0xA8, 0x9D, 0x77, 0x53, 0xAE, 0x09 }; + unsigned char t2[] = { 0xEF, 0x80, 0xA2, 0xE6, 0x50, 0x91, 0xF3, 0x17, 0x4A, 0x8A }; + unsigned char t3[] = { 0x4B, 0xD6, 0x5C, 0x67, 0x99, 0x03, 0x56, 0x12, 0x80, 0x48 }; + int err; + + if ((err = rc4_start(&st)) != CRYPT_OK) return err; + /* add entropy to uninitialized prng */ + if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if ((err = rc4_ready(&st)) != CRYPT_OK) return err; + if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t1, sizeof(t1), "RC4-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; + if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + /* add entropy to already initialized prng */ + if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if ((err = rc4_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; + if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t2, sizeof(t2), "RC4-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; + if ((err = rc4_done(&st)) != CRYPT_OK) return err; + if ((err = rc4_import(dmp, dmplen, &st)) != CRYPT_OK) return err; + if ((err = rc4_ready(&st)) != CRYPT_OK) return err; + if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t3, sizeof(t3), "RC4-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; + if ((err = rc4_done(&st)) != CRYPT_OK) return err; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c b/optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c new file mode 100644 index 0000000..b07238e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c @@ -0,0 +1,152 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_RNG_GET_BYTES +/** + @file rng_get_bytes.c + portable way to get secure random bits to feed a PRNG (Tom St Denis) +*/ + +#if defined(LTC_DEVRANDOM) && !defined(_WIN32) +/* on *NIX read /dev/random */ +static unsigned long s_rng_nix(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(callback); + LTC_UNUSED_PARAM(buf); + LTC_UNUSED_PARAM(len); + return 0; +#else + FILE *f; + unsigned long x; + LTC_UNUSED_PARAM(callback); +#ifdef LTC_TRY_URANDOM_FIRST + f = fopen("/dev/urandom", "rb"); + if (f == NULL) { + f = fopen("/dev/random", "rb"); + } +#else + f = fopen("/dev/random", "rb"); +#endif /* LTC_TRY_URANDOM_FIRST */ + + 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 */ + +#if !defined(_WIN32_WCE) + +#define ANSI_RNG + +static unsigned long s_rng_ansic(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + clock_t t1; + int l, acc, bits, a, b; + + 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; + } + return l; +} + +#endif + +/* Try the Microsoft CSP */ +#if defined(_WIN32) || defined(_WIN32_WCE) +#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0400 +#endif +#ifdef _WIN32_WCE + #define UNDER_CE + #define ARM +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#include + +static unsigned long s_rng_win32(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + HCRYPTPROV hProv = 0; + LTC_UNUSED_PARAM(callback); + 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); + +#ifdef LTC_PRNG_ENABLE_LTC_RNG + if (ltc_rng) { + x = ltc_rng(out, outlen, callback); + if (x != 0) { + return x; + } + } +#endif + +#if defined(_WIN32) || defined(_WIN32_WCE) + x = s_rng_win32(out, outlen, callback); if (x != 0) { return x; } +#elif defined(LTC_DEVRANDOM) + x = s_rng_nix(out, outlen, callback); if (x != 0) { return x; } +#endif +#ifdef ANSI_RNG + x = s_rng_ansic(out, outlen, callback); if (x != 0) { return x; } +#endif + return 0; +} +#endif /* #ifdef LTC_RNG_GET_BYTES */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c b/optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c new file mode 100644 index 0000000..e70c1cd --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/rng_make_prng.c @@ -0,0 +1,81 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_RNG_MAKE_PRNG +/** + @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 + + In case you pass bits as '-1' the PRNG will be setup + as if the export/import functionality has been used, + but the imported data comes directly from the RNG. + + @param bits Number of bits of entropy desired (-1 or 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; + unsigned long bytes; + int err; + + LTC_ARGCHK(prng != NULL); + + /* check parameter */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (bits == -1) { + bytes = prng_descriptor[wprng]->export_size; + } else if (bits < 64 || bits > 1024) { + return CRYPT_INVALID_PRNGSIZE; + } else { + bytes = (unsigned long)((bits+7)/8) * 2; + } + + if ((err = prng_descriptor[wprng]->start(prng)) != CRYPT_OK) { + return err; + } + + buf = XMALLOC(bytes); + if (buf == NULL) { + return CRYPT_MEM; + } + + if (rng_get_bytes(buf, bytes, callback) != bytes) { + err = CRYPT_ERROR_READPRNG; + goto LBL_ERR; + } + + if (bits == -1) { + if ((err = prng_descriptor[wprng]->pimport(buf, bytes, prng)) != CRYPT_OK) { + goto LBL_ERR; + } + } else { + if ((err = prng_descriptor[wprng]->add_entropy(buf, bytes, prng)) != CRYPT_OK) { + goto LBL_ERR; + } + } + if ((err = prng_descriptor[wprng]->ready(prng)) != CRYPT_OK) { + goto LBL_ERR; + } + +LBL_ERR: + #ifdef LTC_CLEAN_STACK + zeromem(buf, bytes); + #endif + XFREE(buf); + return err; +} +#endif /* #ifdef LTC_RNG_MAKE_PRNG */ + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/sober128.c b/optee/optee_os/core/lib/libtomcrypt/src/prngs/sober128.c new file mode 100644 index 0000000..6454578 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/sober128.c @@ -0,0 +1,220 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file prngs/sober128.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +const struct ltc_prng_descriptor sober128_desc = +{ + "sober128", + 40, + &sober128_start, + &sober128_add_entropy, + &sober128_ready, + &sober128_read, + &sober128_done, + &sober128_export, + &sober128_import, + &sober128_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int sober128_start(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent)); + prng->u.sober128.idx = 0; + LTC_MUTEX_INIT(&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 sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char buf[40]; + unsigned long i; + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { + /* sober128_ready() was already called, do "rekey" operation */ + if ((err = sober128_stream_keystream(&prng->u.sober128.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; + for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; + /* key 32 bytes, 20 rounds */ + if ((err = sober128_stream_setup(&prng->u.sober128.s, buf, 32)) != CRYPT_OK) goto LBL_UNLOCK; + /* iv 8 bytes */ + if ((err = sober128_stream_setiv(&prng->u.sober128.s, buf + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; + /* clear KEY + IV */ + zeromem(buf, sizeof(buf)); + } + else { + /* sober128_ready() was not called yet, add entropy to ent buffer */ + while (inlen--) prng->u.sober128.ent[prng->u.sober128.idx++ % sizeof(prng->u.sober128.ent)] ^= *in++; + } + err = CRYPT_OK; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int sober128_ready(prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } + /* key 32 bytes, 20 rounds */ + if ((err = sober128_stream_setup(&prng->u.sober128.s, prng->u.sober128.ent, 32)) != CRYPT_OK) goto LBL_UNLOCK; + /* iv 8 bytes */ + if ((err = sober128_stream_setiv(&prng->u.sober128.s, prng->u.sober128.ent + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; + XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent)); + prng->u.sober128.idx = 0; + prng->ready = 1; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + 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 sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + if (outlen == 0 || prng == NULL || out == NULL) return 0; + LTC_MUTEX_LOCK(&prng->lock); + if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } + if (sober128_stream_keystream(&prng->u.sober128.s, out, outlen) != CRYPT_OK) outlen = 0; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int sober128_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + err = sober128_stream_done(&prng->u.sober128.s); + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&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 +*/ +LTC_PRNG_EXPORT(sober128) + +/** + 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 sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + if (inlen < (unsigned long)sober128_desc.export_size) return CRYPT_INVALID_ARG; + + if ((err = sober128_start(prng)) != CRYPT_OK) return err; + if ((err = sober128_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int sober128_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + prng_state st; + unsigned char en[] = { 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 }; + unsigned char dmp[300]; + unsigned long dmplen = sizeof(dmp); + unsigned char out[500]; + unsigned char t1[] = { 0x31, 0x82, 0xA7, 0xA5, 0x8B, 0xD7, 0xCB, 0x39, 0x86, 0x1A }; + unsigned char t2[] = { 0x6B, 0x43, 0x9E, 0xBC, 0xE7, 0x62, 0x9B, 0xE6, 0x9B, 0x83 }; + unsigned char t3[] = { 0x4A, 0x0E, 0x6C, 0xC1, 0xCF, 0xB4, 0x73, 0x49, 0x99, 0x05 }; + int err; + + if ((err = sober128_start(&st)) != CRYPT_OK) return err; + /* add entropy to uninitialized prng */ + if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if ((err = sober128_ready(&st)) != CRYPT_OK) return err; + if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t1, sizeof(t1), "SOBER128-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; + if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + /* add entropy to already initialized prng */ + if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if ((err = sober128_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; + if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t2, sizeof(t2), "SOBER128-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; + if ((err = sober128_done(&st)) != CRYPT_OK) return err; + if ((err = sober128_import(dmp, dmplen, &st)) != CRYPT_OK) return err; + if ((err = sober128_ready(&st)) != CRYPT_OK) return err; + if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t3, sizeof(t3), "SOBER128-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; + if ((err = sober128_done(&st)) != CRYPT_OK) return err; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/sprng.c b/optee/optee_os/core/lib/libtomcrypt/src/prngs/sprng.c new file mode 100644 index 0000000..e404718 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/sprng.c @@ -0,0 +1,152 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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) +{ + LTC_UNUSED_PARAM(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) +{ + LTC_UNUSED_PARAM(in); + LTC_UNUSED_PARAM(inlen); + LTC_UNUSED_PARAM(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) +{ + LTC_UNUSED_PARAM(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); + LTC_UNUSED_PARAM(prng); + 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) +{ + LTC_UNUSED_PARAM(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 +*/ +/* NOLINTNEXTLINE(readability-non-const-parameter) - silence clang-tidy warning */ +int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_ARGCHK(outlen != NULL); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(prng); + + *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) +{ + LTC_UNUSED_PARAM(in); + LTC_UNUSED_PARAM(inlen); + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int sprng_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + prng_state st; + unsigned char en[] = { 0x01, 0x02, 0x03, 0x04 }; + unsigned char out[1000]; + int err; + + if ((err = sprng_start(&st)) != CRYPT_OK) return err; + if ((err = sprng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if ((err = sprng_ready(&st)) != CRYPT_OK) return err; + if (sprng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if ((err = sprng_done(&st)) != CRYPT_OK) return err; + + return CRYPT_OK; +#endif +} + +#endif + + + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/prngs/sub.mk new file mode 100644 index 0000000..d8a8e51 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/sub.mk @@ -0,0 +1,7 @@ +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 += rc4.c +srcs-$(_CFG_CORE_LTC_FORTUNA_PRNG) += fortuna.c diff --git a/optee/optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c b/optee/optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c new file mode 100644 index 0000000..6131043 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/prngs/yarrow.c @@ -0,0 +1,323 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.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); + prng->ready = 0; + + /* these are the default hash/cipher combo used */ +#ifdef LTC_RIJNDAEL +#if LTC_YARROW_AES==0 + prng->u.yarrow.cipher = register_cipher(&rijndael_enc_desc); +#elif LTC_YARROW_AES==1 + prng->u.yarrow.cipher = register_cipher(&aes_enc_desc); +#elif LTC_YARROW_AES==2 + prng->u.yarrow.cipher = register_cipher(&rijndael_desc); +#elif LTC_YARROW_AES==3 + prng->u.yarrow.cipher = register_cipher(&aes_desc); +#endif +#elif defined(LTC_BLOWFISH) + prng->u.yarrow.cipher = register_cipher(&blowfish_desc); +#elif defined(LTC_TWOFISH) + prng->u.yarrow.cipher = register_cipher(&twofish_desc); +#elif defined(LTC_RC6) + prng->u.yarrow.cipher = register_cipher(&rc6_desc); +#elif defined(LTC_RC5) + prng->u.yarrow.cipher = register_cipher(&rc5_desc); +#elif defined(LTC_SAFERP) + prng->u.yarrow.cipher = register_cipher(&saferp_desc); +#elif defined(LTC_RC2) + prng->u.yarrow.cipher = register_cipher(&rc2_desc); +#elif defined(LTC_NOEKEON) + prng->u.yarrow.cipher = register_cipher(&noekeon_desc); +#elif defined(LTC_ANUBIS) + prng->u.yarrow.cipher = register_cipher(&anubis_desc); +#elif defined(LTC_KSEED) + prng->u.yarrow.cipher = register_cipher(&kseed_desc); +#elif defined(LTC_KHAZAD) + prng->u.yarrow.cipher = register_cipher(&khazad_desc); +#elif defined(LTC_CAST5) + prng->u.yarrow.cipher = register_cipher(&cast5_desc); +#elif defined(LTC_XTEA) + prng->u.yarrow.cipher = register_cipher(&xtea_desc); +#elif defined(LTC_SAFER) + prng->u.yarrow.cipher = register_cipher(&safer_sk128_desc); +#elif defined(LTC_DES) + prng->u.yarrow.cipher = register_cipher(&des3_desc); +#else + #error LTC_YARROW needs at least one CIPHER +#endif + if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_SHA256 + prng->u.yarrow.hash = register_hash(&sha256_desc); +#elif defined(LTC_SHA512) + prng->u.yarrow.hash = register_hash(&sha512_desc); +#elif defined(LTC_TIGER) + prng->u.yarrow.hash = register_hash(&tiger_desc); +#elif defined(LTC_SHA1) + prng->u.yarrow.hash = register_hash(&sha1_desc); +#elif defined(LTC_RIPEMD320) + prng->u.yarrow.hash = register_hash(&rmd320_desc); +#elif defined(LTC_RIPEMD256) + prng->u.yarrow.hash = register_hash(&rmd256_desc); +#elif defined(LTC_RIPEMD160) + prng->u.yarrow.hash = register_hash(&rmd160_desc); +#elif defined(LTC_RIPEMD128) + prng->u.yarrow.hash = register_hash(&rmd128_desc); +#elif defined(LTC_MD5) + prng->u.yarrow.hash = register_hash(&md5_desc); +#elif defined(LTC_MD4) + prng->u.yarrow.hash = register_hash(&md4_desc); +#elif defined(LTC_MD2) + prng->u.yarrow.hash = register_hash(&md2_desc); +#elif defined(LTC_WHIRLPOOL) + prng->u.yarrow.hash = register_hash(&whirlpool_desc); +#else + #error LTC_YARROW needs at least one HASH +#endif + if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { + return err; + } + + /* zero the memory used */ + zeromem(prng->u.yarrow.pool, sizeof(prng->u.yarrow.pool)); + LTC_MUTEX_INIT(&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(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + + if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* start the hash */ + if ((err = hash_descriptor[prng->u.yarrow.hash]->init(&md)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* hash the current pool */ + if ((err = hash_descriptor[prng->u.yarrow.hash]->process(&md, prng->u.yarrow.pool, + hash_descriptor[prng->u.yarrow.hash]->hashsize)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* add the new entropy */ + if ((err = hash_descriptor[prng->u.yarrow.hash]->process(&md, in, inlen)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* store result */ + err = hash_descriptor[prng->u.yarrow.hash]->done(&md, prng->u.yarrow.pool); + +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + 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->lock); + + if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* setup CTR mode using the "pool" as the key */ + ks = (int)hash_descriptor[prng->u.yarrow.hash]->hashsize; + if ((err = cipher_descriptor[prng->u.yarrow.cipher]->keysize(&ks)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + if ((err = ctr_start(prng->u.yarrow.cipher, /* what cipher to use */ + prng->u.yarrow.pool, /* IV */ + prng->u.yarrow.pool, ks, /* KEY and key size */ + 0, /* number of rounds */ + CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ + &prng->u.yarrow.ctr)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + prng->ready = 1; + +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + 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) +{ + if (outlen == 0 || prng == NULL || out == NULL) return 0; + + LTC_MUTEX_LOCK(&prng->lock); + + if (!prng->ready) { + outlen = 0; + goto LBL_UNLOCK; + } + + /* put out in predictable state first */ + zeromem(out, outlen); + + /* now randomize it */ + if (ctr_encrypt(out, out, outlen, &prng->u.yarrow.ctr) != CRYPT_OK) { + outlen = 0; + } + +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&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->lock); + prng->ready = 0; + + /* call cipher done when we invent one ;-) */ + + /* we invented one */ + err = ctr_done(&prng->u.yarrow.ctr); + + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&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 +*/ +LTC_PRNG_EXPORT(yarrow) + +/** + 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); + if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG; + + if ((err = yarrow_start(prng)) != CRYPT_OK) return err; + if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +/** + 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 (cipher_descriptor[prng.u.yarrow.cipher]->test && + ((err = cipher_descriptor[prng.u.yarrow.cipher]->test()) != CRYPT_OK)) { + return err; + } + if (hash_descriptor[prng.u.yarrow.hash]->test && + ((err = hash_descriptor[prng.u.yarrow.hash]->test()) != CRYPT_OK)) { + return err; + } + + return CRYPT_OK; +#endif +} + +#endif + diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c new file mode 100644 index 0000000..2798800 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c @@ -0,0 +1,91 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +#define QUARTERROUND(a,b,c,d) \ + x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 16); \ + x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 12); \ + x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 8); \ + x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 7); + +static void s_chacha_block(unsigned char *output, const ulong32 *input, int rounds) +{ + ulong32 x[16]; + int i; + XMEMCPY(x, input, sizeof(x)); + for (i = rounds; i > 0; i -= 2) { + QUARTERROUND(0, 4, 8,12) + QUARTERROUND(1, 5, 9,13) + QUARTERROUND(2, 6,10,14) + QUARTERROUND(3, 7,11,15) + QUARTERROUND(0, 5,10,15) + QUARTERROUND(1, 6,11,12) + QUARTERROUND(2, 7, 8,13) + QUARTERROUND(3, 4, 9,14) + } + for (i = 0; i < 16; ++i) { + x[i] += input[i]; + STORE32L(x[i], output + 4 * i); + } +} + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha + @param st The ChaCha state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char buf[64]; + unsigned long i, j; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(st->ivlen != 0); + + if (st->ksleft > 0) { + j = MIN(st->ksleft, inlen); + for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; + inlen -= j; + if (inlen == 0) return CRYPT_OK; + out += j; + in += j; + } + for (;;) { + s_chacha_block(buf, st->input, st->rounds); + if (st->ivlen == 8) { + /* IV-64bit, increment 64bit counter */ + if (0 == ++st->input[12] && 0 == ++st->input[13]) return CRYPT_OVERFLOW; + } + else { + /* IV-96bit, increment 32bit counter */ + if (0 == ++st->input[12]) return CRYPT_OVERFLOW; + } + if (inlen <= 64) { + for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; + st->ksleft = 64 - inlen; + for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; + return CRYPT_OK; + } + for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; + inlen -= 64; + out += 64; + in += 64; + } +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_done.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_done.c new file mode 100644 index 0000000..1dc641e --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_done.c @@ -0,0 +1,20 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Terminate and clear ChaCha state + @param st The ChaCha state + @return CRYPT_OK on success +*/ +int chacha_done(chacha_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(chacha_state)); + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.c new file mode 100644 index 0000000..08416f5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Set IV + counter data to the ChaCha state + @param st The ChaCha20 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12) + @param counter 32bit (unsigned) initial counter value + @return CRYPT_OK on success + */ +int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + /* 96bit IV + 32bit counter */ + LTC_ARGCHK(ivlen == 12); + + st->input[12] = counter; + LOAD32L(st->input[13], iv + 0); + LOAD32L(st->input[14], iv + 4); + LOAD32L(st->input[15], iv + 8); + st->ksleft = 0; + st->ivlen = ivlen; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c new file mode 100644 index 0000000..49c5459 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Set IV + counter data to the ChaCha state + @param st The ChaCha20 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 8) + @param counter 64bit (unsigned) initial counter value + @return CRYPT_OK on success + */ +int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + /* 64bit IV + 64bit counter */ + LTC_ARGCHK(ivlen == 8); + + st->input[12] = (ulong32)(counter & 0xFFFFFFFF); + st->input[13] = (ulong32)(counter >> 32); + LOAD32L(st->input[14], iv + 0); + LOAD32L(st->input[15], iv + 4); + st->ksleft = 0; + st->ivlen = ivlen; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.c new file mode 100644 index 0000000..b7fe688 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Generate a stream of random bytes via ChaCha + @param st The ChaCha20 state + @param out [out] The output buffer + @param outlen The output length + @return CRYPT_OK on success + */ +int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return chacha_crypt(st, out, outlen, out); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c new file mode 100644 index 0000000..e73a038 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param rounds The number of rounds + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *iv, unsigned long ivlen, ulong64 counter, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout) +{ + chacha_state st; + int err; + + LTC_ARGCHK(ivlen <= 8 || counter < 4294967296); /* 2**32 */ + + if ((err = chacha_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY; + if (ivlen > 8) { + if ((err = chacha_ivctr32(&st, iv, ivlen, (ulong32)counter)) != CRYPT_OK) goto WIPE_KEY; + } else { + if ((err = chacha_ivctr64(&st, iv, ivlen, counter)) != CRYPT_OK) goto WIPE_KEY; + } + err = chacha_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + chacha_done(&st); + return err; +} + +#endif /* LTC_CHACHA */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_setup.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_setup.c new file mode 100644 index 0000000..6089607 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_setup.c @@ -0,0 +1,57 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +static const char * const sigma = "expand 32-byte k"; +static const char * const tau = "expand 16-byte k"; + +/** + Initialize an ChaCha context (only the key) + @param st [out] The destination of the ChaCha state + @param key The secret key + @param keylen The length of the secret key (octets) + @param rounds Number of rounds (e.g. 20 for ChaCha20) + @return CRYPT_OK if successful +*/ +int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds) +{ + const char *constants; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen == 32 || keylen == 16); + + if (rounds == 0) rounds = 20; + + LOAD32L(st->input[4], key + 0); + LOAD32L(st->input[5], key + 4); + LOAD32L(st->input[6], key + 8); + LOAD32L(st->input[7], key + 12); + if (keylen == 32) { /* 256bit */ + key += 16; + constants = sigma; + } else { /* 128bit */ + constants = tau; + } + LOAD32L(st->input[8], key + 0); + LOAD32L(st->input[9], key + 4); + LOAD32L(st->input[10], key + 8); + LOAD32L(st->input[11], key + 12); + LOAD32L(st->input[0], constants + 0); + LOAD32L(st->input[1], constants + 4); + LOAD32L(st->input[2], constants + 8); + LOAD32L(st->input[3], constants + 12); + st->rounds = rounds; /* e.g. 20 for chacha20 */ + st->ivlen = 0; /* will be set later by chacha_ivctr(32|64) */ + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c new file mode 100644 index 0000000..cdd5f4f --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c @@ -0,0 +1,74 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +int chacha_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned long len; + unsigned char out[1000]; + /* https://tools.ietf.org/html/rfc7539#section-2.4.2 */ + unsigned char k[] = { 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 }; + unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 }; + unsigned char ct[] = { 0x6E, 0x2E, 0x35, 0x9A, 0x25, 0x68, 0xF9, 0x80, 0x41, 0xBA, 0x07, 0x28, 0xDD, 0x0D, 0x69, 0x81, + 0xE9, 0x7E, 0x7A, 0xEC, 0x1D, 0x43, 0x60, 0xC2, 0x0A, 0x27, 0xAF, 0xCC, 0xFD, 0x9F, 0xAE, 0x0B, + 0xF9, 0x1B, 0x65, 0xC5, 0x52, 0x47, 0x33, 0xAB, 0x8F, 0x59, 0x3D, 0xAB, 0xCD, 0x62, 0xB3, 0x57, + 0x16, 0x39, 0xD6, 0x24, 0xE6, 0x51, 0x52, 0xAB, 0x8F, 0x53, 0x0C, 0x35, 0x9F, 0x08, 0x61, 0xD8, + 0x07, 0xCA, 0x0D, 0xBF, 0x50, 0x0D, 0x6A, 0x61, 0x56, 0xA3, 0x8E, 0x08, 0x8A, 0x22, 0xB6, 0x5E, + 0x52, 0xBC, 0x51, 0x4D, 0x16, 0xCC, 0xF8, 0x06, 0x81, 0x8C, 0xE9, 0x1A, 0xB7, 0x79, 0x37, 0x36, + 0x5A, 0xF9, 0x0B, 0xBF, 0x74, 0xA3, 0x5B, 0xE6, 0xB4, 0x0B, 0x8E, 0xED, 0xF2, 0x78, 0x5E, 0x42, + 0x87, 0x4D }; + char pt[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + chacha_state st; + int err; + + len = XSTRLEN(pt); + + /* crypt piece by piece - using chacha_ivctr32() */ + if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; + if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt, 35, out )) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt + 35, 35, out + 35)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt + 70, 5, out + 70)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt + 75, 5, out + 75)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt + 80, len - 80, out + 80)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in one go - using chacha_ivctr32() */ + if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; + if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in one go - using chacha_ivctr64() */ + if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; + if ((err = chacha_ivctr64(&st, n + 4, sizeof(n) - 4, 1)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in a single call using 32-bit counter with a value of 1 */ + if ((err = chacha_memory(k, sizeof(k), 20, + n, sizeof(n), 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in a single call using 64-bit counter with a value of 1 */ + if ((err = chacha_memory(k, sizeof(k), 20, + n + 4, sizeof(n) - 4, 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit.c new file mode 100644 index 0000000..075f4c0 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit.c @@ -0,0 +1,447 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + *--------------------------------------------------------------------------- + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 + ******************************************************************************/ + + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +/* local/private prototypes (NB: rabbit_ctx and rabbit_state are different) */ +static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x); +static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance); +static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out); + +/* -------------------------------------------------------------------------- */ + +/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ +/* the upper 32 bits XOR the lower 32 bits */ +static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x) +{ + ulong32 a, b, h, l; + + /* Construct high and low argument for squaring */ + a = x & 0xFFFF; + b = x >> 16; + + /* Calculate high and low result of squaring */ + h = ((((ulong32)(a*a)>>17) + (ulong32)(a*b))>>15) + b*b; + l = x * x; + + /* Return high XOR low */ + return (ulong32)(h^l); +} + +/* -------------------------------------------------------------------------- */ + +/* Calculate the next internal state */ +static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance) +{ + ulong32 g[8], c_old[8], i; + + /* Save old counter values */ + for (i=0; i<8; i++) { + c_old[i] = p_instance->c[i]; + } + + /* Calculate new counter values */ + p_instance->c[0] = (ulong32)(p_instance->c[0] + 0x4D34D34D + p_instance->carry); + p_instance->c[1] = (ulong32)(p_instance->c[1] + 0xD34D34D3 + (p_instance->c[0] < c_old[0])); + p_instance->c[2] = (ulong32)(p_instance->c[2] + 0x34D34D34 + (p_instance->c[1] < c_old[1])); + p_instance->c[3] = (ulong32)(p_instance->c[3] + 0x4D34D34D + (p_instance->c[2] < c_old[2])); + p_instance->c[4] = (ulong32)(p_instance->c[4] + 0xD34D34D3 + (p_instance->c[3] < c_old[3])); + p_instance->c[5] = (ulong32)(p_instance->c[5] + 0x34D34D34 + (p_instance->c[4] < c_old[4])); + p_instance->c[6] = (ulong32)(p_instance->c[6] + 0x4D34D34D + (p_instance->c[5] < c_old[5])); + p_instance->c[7] = (ulong32)(p_instance->c[7] + 0xD34D34D3 + (p_instance->c[6] < c_old[6])); + p_instance->carry = (p_instance->c[7] < c_old[7]); + + /* Calculate the g-values */ + for (i=0;i<8;i++) { + g[i] = ss_rabbit_g_func((ulong32)(p_instance->x[i] + p_instance->c[i])); + } + + /* Calculate new state values */ + p_instance->x[0] = (ulong32)(g[0] + ROLc(g[7],16) + ROLc(g[6], 16)); + p_instance->x[1] = (ulong32)(g[1] + ROLc(g[0], 8) + g[7]); + p_instance->x[2] = (ulong32)(g[2] + ROLc(g[1],16) + ROLc(g[0], 16)); + p_instance->x[3] = (ulong32)(g[3] + ROLc(g[2], 8) + g[1]); + p_instance->x[4] = (ulong32)(g[4] + ROLc(g[3],16) + ROLc(g[2], 16)); + p_instance->x[5] = (ulong32)(g[5] + ROLc(g[4], 8) + g[3]); + p_instance->x[6] = (ulong32)(g[6] + ROLc(g[5],16) + ROLc(g[4], 16)); + p_instance->x[7] = (ulong32)(g[7] + ROLc(g[6], 8) + g[5]); +} + +/* ------------------------------------------------------------------------- */ + +static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out) +{ + ulong32 *ptr; + + /* Iterate the work context once */ + ss_rabbit_next_state(&(st->work_ctx)); + + /* Generate 16 bytes of pseudo-random data */ + ptr = (ulong32*)&(st->work_ctx.x); + STORE32L((ptr[0] ^ (ptr[5]>>16) ^ (ulong32)(ptr[3]<<16)), out+ 0); + STORE32L((ptr[2] ^ (ptr[7]>>16) ^ (ulong32)(ptr[5]<<16)), out+ 4); + STORE32L((ptr[4] ^ (ptr[1]>>16) ^ (ulong32)(ptr[7]<<16)), out+ 8); + STORE32L((ptr[6] ^ (ptr[3]>>16) ^ (ulong32)(ptr[1]<<16)), out+12); +} + +/* -------------------------------------------------------------------------- */ + +/* Key setup */ +int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen) +{ + ulong32 k0, k1, k2, k3, i; + unsigned char tmpkey[16] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen <= 16); + + /* init state */ + XMEMSET(st, 0, sizeof(rabbit_state)); + + /* pad key in tmpkey */ + XMEMCPY(tmpkey, key, keylen); + + /* Generate four subkeys */ + LOAD32L(k0, tmpkey+ 0); + LOAD32L(k1, tmpkey+ 4); + LOAD32L(k2, tmpkey+ 8); + LOAD32L(k3, tmpkey+12); + +#ifdef LTC_CLEAN_STACK + /* done with tmpkey, wipe it */ + zeromem(tmpkey, sizeof(tmpkey)); +#endif + + /* Generate initial state variables */ + st->master_ctx.x[0] = k0; + st->master_ctx.x[2] = k1; + st->master_ctx.x[4] = k2; + st->master_ctx.x[6] = k3; + st->master_ctx.x[1] = (ulong32)(k3<<16) | (k2>>16); + st->master_ctx.x[3] = (ulong32)(k0<<16) | (k3>>16); + st->master_ctx.x[5] = (ulong32)(k1<<16) | (k0>>16); + st->master_ctx.x[7] = (ulong32)(k2<<16) | (k1>>16); + + /* Generate initial counter values */ + st->master_ctx.c[0] = ROLc(k2, 16); + st->master_ctx.c[2] = ROLc(k3, 16); + st->master_ctx.c[4] = ROLc(k0, 16); + st->master_ctx.c[6] = ROLc(k1, 16); + st->master_ctx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); + st->master_ctx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); + st->master_ctx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); + st->master_ctx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); + + /* Clear carry bit */ + st->master_ctx.carry = 0; + + /* Iterate the master context four times */ + for (i=0; i<4; i++) { + ss_rabbit_next_state(&(st->master_ctx)); + } + + /* Modify the counters */ + for (i=0; i<8; i++) { + st->master_ctx.c[i] ^= st->master_ctx.x[(i+4)&0x7]; + } + + /* Copy master instance to work instance */ + for (i=0; i<8; i++) { + st->work_ctx.x[i] = st->master_ctx.x[i]; + st->work_ctx.c[i] = st->master_ctx.c[i]; + } + st->work_ctx.carry = st->master_ctx.carry; + /* ...and prepare block for crypt() */ + XMEMSET(&(st->block), 0, sizeof(st->block)); + st->unused = 0; + + return CRYPT_OK; +} + +/* -------------------------------------------------------------------------- */ + +/* IV setup */ +int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen) +{ + ulong32 i0, i1, i2, i3, i; + unsigned char tmpiv[8] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL || ivlen == 0); + LTC_ARGCHK(ivlen <= 8); + + /* pad iv in tmpiv */ + if (iv && ivlen > 0) XMEMCPY(tmpiv, iv, ivlen); + + /* Generate four subvectors */ + LOAD32L(i0, tmpiv+0); + LOAD32L(i2, tmpiv+4); + i1 = (i0>>16) | (i2&0xFFFF0000); + i3 = (i2<<16) | (i0&0x0000FFFF); + + /* Modify counter values */ + st->work_ctx.c[0] = st->master_ctx.c[0] ^ i0; + st->work_ctx.c[1] = st->master_ctx.c[1] ^ i1; + st->work_ctx.c[2] = st->master_ctx.c[2] ^ i2; + st->work_ctx.c[3] = st->master_ctx.c[3] ^ i3; + st->work_ctx.c[4] = st->master_ctx.c[4] ^ i0; + st->work_ctx.c[5] = st->master_ctx.c[5] ^ i1; + st->work_ctx.c[6] = st->master_ctx.c[6] ^ i2; + st->work_ctx.c[7] = st->master_ctx.c[7] ^ i3; + + /* Copy state variables */ + for (i=0; i<8; i++) { + st->work_ctx.x[i] = st->master_ctx.x[i]; + } + st->work_ctx.carry = st->master_ctx.carry; + + /* Iterate the work context four times */ + for (i=0; i<4; i++) { + ss_rabbit_next_state(&(st->work_ctx)); + } + + /* reset keystream buffer and unused count */ + XMEMSET(&(st->block), 0, sizeof(st->block)); + st->unused = 0; + + return CRYPT_OK; +} + +/* ------------------------------------------------------------------------- */ + +/* Crypt a chunk of any size (encrypt/decrypt) */ +int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char buf[16]; + unsigned long i, j; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if (st->unused > 0) { + j = MIN(st->unused, inlen); + for (i = 0; i < j; ++i, st->unused--) out[i] = in[i] ^ st->block[16 - st->unused]; + inlen -= j; + if (inlen == 0) return CRYPT_OK; + out += j; + in += j; + } + for (;;) { + /* gen a block for buf */ + ss_rabbit_gen_1_block(st, buf); + if (inlen <= 16) { + /* XOR and send to out */ + for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; + st->unused = 16 - inlen; + /* copy remainder to block */ + for (i = inlen; i < 16; ++i) st->block[i] = buf[i]; + return CRYPT_OK; + } + /* XOR entire buf and send to out */ + for (i = 0; i < 16; ++i) out[i] = in[i] ^ buf[i]; + inlen -= 16; + out += 16; + in += 16; + } +} + +/* ------------------------------------------------------------------------- */ + +int rabbit_keystream(rabbit_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(out != NULL); + + XMEMSET(out, 0, outlen); + return rabbit_crypt(st, out, outlen, out); +} + +/* -------------------------------------------------------------------------- */ + +int rabbit_done(rabbit_state *st) +{ + LTC_ARGCHK(st != NULL); + + zeromem(st, sizeof(rabbit_state)); + return CRYPT_OK; +} + +/* -------------------------------------------------------------------------- */ + +int rabbit_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + rabbit_state st; + int err; + unsigned char out[1000] = { 0 }; + { + /* all 3 tests use key and iv fm set 6, vector 3, the last vector in: + http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/rabbit/verified.test-vectors?rev=210&view=log + */ + + /* --- Test 1 (generate whole blocks) --------------------------------- */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[64] = { 0 }; + unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, + 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, + 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, + 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, + 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D, 0x7C, + 0x0C, 0x10, 0x9B, 0x79, 0xD5, 0x74, 0x94, 0x39, + 0xB7, 0xEF, 0xA4, 0xC4, 0xC9, 0xC8, 0xD2, 0x9D, + 0xC5, 0xB3, 0x88, 0x83, 0x14, 0xA6, 0x81, 0x6F }; + unsigned long ptlen = sizeof(pt); + + /* crypt 64 nulls */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, ptlen, out)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + /* --- Test 2 (generate unusual number of bytes each time) ------------ */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[39] = { 0 }; + unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, + 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, + 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, + 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, + 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D }; + unsigned long ptlen = sizeof(pt); + + /* crypt piece by piece (hit at least one 16-byte boundary) */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 11, out + 5)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 16, 14, out + 16)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 30, 2, out + 30)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 32, 7, out + 32)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + /* --- Test 3 (use non-null data) ------------------------------------- */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[] = "Kilroy was here, there, and everywhere!"; + unsigned char ct[] = { 0x2a, 0x55, 0xdc, 0xc8, 0xf9, 0xd6, 0xd6, 0xbd, + 0xae, 0x59, 0x65, 0xf2, 0x75, 0x58, 0x1a, 0x54, + 0xea, 0xec, 0x34, 0x9d, 0x8f, 0xb4, 0x6b, 0x60, + 0x79, 0x1b, 0xea, 0x16, 0xcb, 0xef, 0x46, 0x87, + 0x60, 0xa6, 0x55, 0x14, 0xff, 0xca, 0xac }; + unsigned long ptlen = XSTRLEN(pt); + unsigned char out2[1000] = { 0 }; + unsigned char nulls[1000] = { 0 }; + + /* crypt piece by piece */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 29, out + 5)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 34, 5, out + 34)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* --- Test 4 (crypt in a single call) ------------------------------------ */ + + if ((err = rabbit_memory(k, sizeof(k), iv, sizeof(iv), + (unsigned char*)pt, sizeof(pt), out)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + /* use 'out' (ciphertext) in the next decryption test */ + + /* --- Test 5 (decrypt ciphertext) ------------------------------------ */ + + /* decrypt ct (out) and compare with pt (start with only setiv() to reset) */ + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, out, ptlen, out2)) != CRYPT_OK) return err; + if (compare_testvector(out2, ptlen, pt, ptlen, "RABBIT-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* --- Test 6 (wipe state, incl key) ---------------------------------- */ + + if ((err = rabbit_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(&st, sizeof(st), nulls, sizeof(st), "RABBIT-TV6", 1)) return CRYPT_FAIL_TESTVECTOR; + + } + + return CRYPT_OK; + } +#endif +} + +/* -------------------------------------------------------------------------- */ + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit_memory.c new file mode 100644 index 0000000..fee0234 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/rabbit/rabbit_memory.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Rabbit + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int rabbit_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout) +{ + rabbit_state st; + int err; + + if ((err = rabbit_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; + if ((err = rabbit_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; + err = rabbit_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + rabbit_done(&st); + return err; +} + +#endif /* LTC_RABBIT */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c new file mode 100644 index 0000000..2587764 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c @@ -0,0 +1,101 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + +/** + Initialize an RC4 context (only the key) + @param st [out] The destination of the RC4 state + @param key The secret key + @param keylen The length of the secret key (8 - 256 bytes) + @return CRYPT_OK if successful +*/ +int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen) +{ + unsigned char tmp, *s; + int x, y; + unsigned long j; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen >= 5); /* 40-2048 bits */ + + s = st->buf; + for (x = 0; x < 256; x++) { + s[x] = x; + } + + for (j = x = y = 0; x < 256; x++) { + y = (y + s[x] + key[j++]) & 255; + if (j == keylen) { + j = 0; + } + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + } + st->x = 0; + st->y = 0; + + return CRYPT_OK; +} + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 + @param st The RC4 state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char x, y, *s, tmp; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + x = st->x; + y = st->y; + s = st->buf; + while (inlen--) { + x = (x + 1) & 255; + y = (y + s[x]) & 255; + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + tmp = (s[x] + s[y]) & 255; + *out++ = *in++ ^ s[tmp]; + } + st->x = x; + st->y = y; + return CRYPT_OK; +} + +/** + Generate a stream of random bytes via RC4 + @param st The RC420 state + @param out [out] The output buffer + @param outlen The output length + @return CRYPT_OK on success + */ +int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return rc4_stream_crypt(st, out, outlen, out); +} + +/** + Terminate and clear RC4 state + @param st The RC4 state + @return CRYPT_OK on success +*/ +int rc4_stream_done(rc4_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(rc4_state)); + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c new file mode 100644 index 0000000..efe4888 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 + @param key The key + @param keylen The key length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int rc4_stream_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout) +{ + rc4_state st; + int err; + + if ((err = rc4_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; + err = rc4_stream_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + rc4_stream_done(&st); + return err; +} + +#endif /* LTC_RC4_STREAM */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c new file mode 100644 index 0000000..d78022b --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c @@ -0,0 +1,33 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + +int rc4_stream_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + rc4_state st; + int err; + const unsigned char key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + const unsigned char pt[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + const unsigned char ct[] = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }; + unsigned char buf[10]; + + if ((err = rc4_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err; + if ((err = rc4_stream_crypt(&st, pt, sizeof(pt), buf)) != CRYPT_OK) return err; + if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV1", 0)) return CRYPT_FAIL_TESTVECTOR; + if ((err = rc4_stream_done(&st)) != CRYPT_OK) return err; + + /* crypt in a single call */ + if ((err = rc4_stream_memory(key, sizeof(key), pt, sizeof(pt), buf)) != CRYPT_OK) return err; + if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV2", 0)) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c new file mode 100644 index 0000000..3058372 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +#define QUARTERROUND(a,b,c,d) \ + x[b] ^= (ROL((x[a] + x[d]), 7)); \ + x[c] ^= (ROL((x[b] + x[a]), 9)); \ + x[d] ^= (ROL((x[c] + x[b]), 13)); \ + x[a] ^= (ROL((x[d] + x[c]), 18)); + +static void s_salsa20_block(unsigned char *output, const ulong32 *input, int rounds) +{ + ulong32 x[16]; + int i; + XMEMCPY(x, input, sizeof(x)); + for (i = rounds; i > 0; i -= 2) { + QUARTERROUND( 0, 4, 8,12) + QUARTERROUND( 5, 9,13, 1) + QUARTERROUND(10,14, 2, 6) + QUARTERROUND(15, 3, 7,11) + QUARTERROUND( 0, 1, 2, 3) + QUARTERROUND( 5, 6, 7, 4) + QUARTERROUND(10,11, 8, 9) + QUARTERROUND(15,12,13,14) + } + for (i = 0; i < 16; ++i) { + x[i] += input[i]; + STORE32L(x[i], output + 4 * i); + } +} + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20 + @param st The Salsa20 state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char buf[64]; + unsigned long i, j; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(st->ivlen == 8 || st->ivlen == 24); + + if (st->ksleft > 0) { + j = MIN(st->ksleft, inlen); + for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; + inlen -= j; + if (inlen == 0) return CRYPT_OK; + out += j; + in += j; + } + for (;;) { + s_salsa20_block(buf, st->input, st->rounds); + /* Salsa20: 64-bit IV, increment 64-bit counter */ + if (0 == ++st->input[8] && 0 == ++st->input[9]) return CRYPT_OVERFLOW; + if (inlen <= 64) { + for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; + st->ksleft = 64 - inlen; + for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; + return CRYPT_OK; + } + for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; + inlen -= 64; + out += 64; + in += 64; + } +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c new file mode 100644 index 0000000..9b8cbb6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c @@ -0,0 +1,20 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +/** + Terminate and clear Salsa20 state + @param st The Salsa20 state + @return CRYPT_OK on success +*/ +int salsa20_done(salsa20_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(salsa20_state)); + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c new file mode 100644 index 0000000..8b25dfb --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +/** + Set IV + counter data to the Salsa20 state + @param st The Salsa20 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 8) + @param counter 64bit (unsigned) initial counter value + @return CRYPT_OK on success + */ +int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + /* Salsa20: 64-bit IV (nonce) + 64-bit counter */ + LTC_ARGCHK(ivlen == 8); + + LOAD32L(st->input[6], iv + 0); + LOAD32L(st->input[7], iv + 4); + st->input[8] = (ulong32)(counter & 0xFFFFFFFF); + st->input[9] = (ulong32)(counter >> 32); + st->ksleft = 0; + st->ivlen = ivlen; + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c new file mode 100644 index 0000000..c51d0d6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +/** + Generate a stream of random bytes via Salsa20 + @param st The Salsa20 state + @param out [out] The output buffer + @param outlen The output length + @return CRYPT_OK on success + */ +int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return salsa20_crypt(st, out, outlen, out); +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_memory.c new file mode 100644 index 0000000..9408eb2 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_memory.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20 + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param rounds The number of rounds + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *iv, unsigned long ivlen, ulong64 counter, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout) +{ + salsa20_state st; + int err; + + if ((err = salsa20_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY; + if ((err = salsa20_ivctr64(&st, iv, ivlen, counter)) != CRYPT_OK) goto WIPE_KEY; + err = salsa20_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + salsa20_done(&st); + return err; +} + +#endif /* LTC_SALSA20 */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c new file mode 100644 index 0000000..012dc95 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +static const char * const sigma = "expand 32-byte k"; +static const char * const tau = "expand 16-byte k"; + +/** + Initialize an Salsa20 context (only the key) + @param st [out] The destination of the Salsa20 state + @param key The secret key + @param keylen The length of the secret key (octets) + @param rounds Number of rounds (e.g. 20 for Salsa20) + @return CRYPT_OK if successful +*/ +int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds) +{ + const char *constants; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen == 32 || keylen == 16); + + if (rounds == 0) rounds = 20; + LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */ + + LOAD32L(st->input[1], key + 0); + LOAD32L(st->input[2], key + 4); + LOAD32L(st->input[3], key + 8); + LOAD32L(st->input[4], key + 12); + if (keylen == 32) { /* 256bit */ + key += 16; + constants = sigma; + } else { /* 128bit */ + constants = tau; + } + LOAD32L(st->input[11], key + 0); + LOAD32L(st->input[12], key + 4); + LOAD32L(st->input[13], key + 8); + LOAD32L(st->input[14], key + 12); + LOAD32L(st->input[ 0], constants + 0); + LOAD32L(st->input[ 5], constants + 4); + LOAD32L(st->input[10], constants + 8); + LOAD32L(st->input[15], constants + 12); + st->rounds = rounds; /* default is 20 for salsa20 */ + st->ivlen = 0; /* will be set later by salsa20_ivctr(32|64) */ + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.c new file mode 100644 index 0000000..c924dbe --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +int salsa20_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + salsa20_state st; + unsigned char k[] = { 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 }; + unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a }; + unsigned char ct[] = { 0x37, 0x37, 0x2e, 0x60, 0xb8, 0xae, 0x88, 0x1f, 0xf8, 0xdf, 0x00, 0x26, 0x6c, 0x30, 0x34, 0x2d, + 0xa1, 0xd7, 0x79, 0x60, 0x67, 0x72, 0xe0, 0x67, 0x26, 0x22, 0xad, 0x00, 0x9e, 0xd5, 0x59, 0x44, + 0x51, 0xd9, 0xe6, 0xaa, 0xc9, 0x59, 0x9e, 0x60, 0xff, 0x87, 0x90, 0xc1, 0xc9, 0x1e }; + unsigned char ct2[] = { 0xec, 0x06, 0x32, 0xb3, 0x83, 0x5c, 0xae, 0x91, 0x01, 0x82, 0x7a, 0x71, 0xd9, 0x7d, 0x45, 0xd7, + 0xa6, 0x5b, 0xa0, 0x89, 0x9d, 0xd2, 0x6c, 0xaa, 0xbb, 0x2f, 0x5f, 0x30, 0x89, 0x54, 0xff, 0x3e, + 0x83, 0xc3, 0x34, 0x10, 0xb6, 0xe1, 0xab, 0xe7, 0xf5, 0xab, 0xab, 0xed, 0xa4, 0xff }; + char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */ + unsigned long len; + unsigned char out[1000]; + int counter; + int rounds; + int err; + len = XSTRLEN(pt); + + /* crypt piece by piece */ + counter = 0; + rounds = 12; + if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err; + if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "SALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in one go - using salsa20_ivctr64() */ + counter = 0; + rounds = 20; + if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err; + if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in a single call */ + if ((err = salsa20_memory(k, sizeof(k), rounds, n, sizeof(n), counter, + (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + { + /* keystream + * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?rev=161&view=markup + * Set 6, vector 0 + */ + unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, + 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D }; + unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE }; + unsigned char ct3[] = { 0xF5, 0xFA, 0xD5, 0x3F, 0x79, 0xF9, 0xDF, 0x58, 0xC4, 0xAE, 0xA0, 0xD0, 0xED, 0x9A, 0x96, 0x01, + 0xF2, 0x78, 0x11, 0x2C, 0xA7, 0x18, 0x0D, 0x56, 0x5B, 0x42, 0x0A, 0x48, 0x01, 0x96, 0x70, 0xEA, + 0xF2, 0x4C, 0xE4, 0x93, 0xA8, 0x62, 0x63, 0xF6, 0x77, 0xB4, 0x6A, 0xCE, 0x19, 0x24, 0x77, 0x3D, + 0x2B, 0xB2, 0x55, 0x71, 0xE1, 0xAA, 0x85, 0x93, 0x75, 0x8F, 0xC3, 0x82, 0xB1, 0x28, 0x0B, 0x71 }; + int counter3 = 0; + int rounds3 = 20; + if ((err = salsa20_setup(&st, k3, sizeof(k3), rounds3)) != CRYPT_OK) return err; + if ((err = salsa20_ivctr64(&st, n3, sizeof(n3), counter3)) != CRYPT_OK) return err; + if ((err = salsa20_keystream(&st, out, 64)) != CRYPT_OK) return err; + if ((err = salsa20_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(out, 64, ct3, sizeof(ct3), "SALSA20-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c new file mode 100644 index 0000000..1908cd5 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_XSALSA20 + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with XSalsa20 + @param key The key + @param keylen The key length + @param nonce The initial vector + @param noncelen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param rounds The number of rounds + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout) +{ + salsa20_state st; + int err; + + if ((err = xsalsa20_setup(&st, key, keylen, nonce, noncelen, rounds)) != CRYPT_OK) goto WIPE_KEY; + err = salsa20_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + salsa20_done(&st); + return err; +} + +#endif /* LTC_XSALSA20 */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c new file mode 100644 index 0000000..6bfac09 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c @@ -0,0 +1,127 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt.h" + +#ifdef LTC_XSALSA20 + +static const char * const constants = "expand 32-byte k"; + +#define QUARTERROUND(a,b,c,d) \ + x[b] ^= (ROL((x[a] + x[d]), 7)); \ + x[c] ^= (ROL((x[b] + x[a]), 9)); \ + x[d] ^= (ROL((x[c] + x[b]), 13)); \ + x[a] ^= (ROL((x[d] + x[c]), 18)); + +/* use modified salsa20 doubleround (no final addition as in salsa20) */ +static void s_xsalsa20_doubleround(ulong32 *x, int rounds) +{ + int i; + + for (i = rounds; i > 0; i -= 2) { + /* columnround */ + QUARTERROUND( 0, 4, 8,12) + QUARTERROUND( 5, 9,13, 1) + QUARTERROUND(10,14, 2, 6) + QUARTERROUND(15, 3, 7,11) + /* rowround */ + QUARTERROUND( 0, 1, 2, 3) + QUARTERROUND( 5, 6, 7, 4) + QUARTERROUND(10,11, 8, 9) + QUARTERROUND(15,12,13,14) + } +} + +#undef QUARTERROUND + +/** + Initialize an XSalsa20 context + @param st [out] The destination of the XSalsa20 state + @param key The secret key + @param keylen The length of the secret key, must be 32 (octets) + @param nonce The nonce + @param noncelen The length of the nonce, must be 24 (octets) + @param rounds Number of rounds (must be evenly divisible by 2, default is 20) + @return CRYPT_OK if successful +*/ +int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + int rounds) +{ + const int sti[] = {0, 5, 10, 15, 6, 7, 8, 9}; /* indices used to build subkey fm x */ + ulong32 x[64]; /* input to & output fm doubleround */ + unsigned char subkey[32]; + int i; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen == 32); + LTC_ARGCHK(nonce != NULL); + LTC_ARGCHK(noncelen == 24); + if (rounds == 0) rounds = 20; + LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */ + + /* load the state to "hash" the key */ + LOAD32L(x[ 0], constants + 0); + LOAD32L(x[ 5], constants + 4); + LOAD32L(x[10], constants + 8); + LOAD32L(x[15], constants + 12); + LOAD32L(x[ 1], key + 0); + LOAD32L(x[ 2], key + 4); + LOAD32L(x[ 3], key + 8); + LOAD32L(x[ 4], key + 12); + LOAD32L(x[11], key + 16); + LOAD32L(x[12], key + 20); + LOAD32L(x[13], key + 24); + LOAD32L(x[14], key + 28); + LOAD32L(x[ 6], nonce + 0); + LOAD32L(x[ 7], nonce + 4); + LOAD32L(x[ 8], nonce + 8); + LOAD32L(x[ 9], nonce + 12); + + /* use modified salsa20 doubleround (no final addition) */ + s_xsalsa20_doubleround(x, rounds); + + /* extract the subkey */ + for (i = 0; i < 8; ++i) { + STORE32L(x[sti[i]], subkey + 4 * i); + } + + /* load the final initial state */ + LOAD32L(st->input[ 0], constants + 0); + LOAD32L(st->input[ 5], constants + 4); + LOAD32L(st->input[10], constants + 8); + LOAD32L(st->input[15], constants + 12); + LOAD32L(st->input[ 1], subkey + 0); + LOAD32L(st->input[ 2], subkey + 4); + LOAD32L(st->input[ 3], subkey + 8); + LOAD32L(st->input[ 4], subkey + 12); + LOAD32L(st->input[11], subkey + 16); + LOAD32L(st->input[12], subkey + 20); + LOAD32L(st->input[13], subkey + 24); + LOAD32L(st->input[14], subkey + 28); + LOAD32L(st->input[ 6], &(nonce[16]) + 0); + LOAD32L(st->input[ 7], &(nonce[16]) + 4); + st->input[ 8] = 0; + st->input[ 9] = 0; + st->rounds = rounds; + st->ksleft = 0; + st->ivlen = 24; /* set switch to say nonce/IV has been loaded */ + +#ifdef LTC_CLEAN_STACK + zeromem(x, sizeof(x)); + zeromem(subkey, sizeof(subkey)); +#endif + + return CRYPT_OK; +} + + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_test.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_test.c new file mode 100644 index 0000000..31522fe --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_test.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt.h" + +#ifdef LTC_XSALSA20 + +#if defined(LTC_SHA256) && defined(LTC_TEST) +static int s_sha256(unsigned char *hash, const unsigned char *data, const int datalen) { + hash_state md; + sha256_init(&md); + sha256_process(&md, data, datalen); + sha256_done(&md, hash); + return CRYPT_OK; +} +#endif + +int xsalsa20_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + + /*************************************************************************** + * verify a round trip: + */ + { + const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89}; + const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37}; + const void *msg = "Kilroy was here!"; + unsigned char msglen = 17; /* includes trailing NULL */ + int rounds = 20; + unsigned char ciphertext[17]; + unsigned char msg2[17]; + salsa20_state st; + int err; + + if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, msg, msglen, ciphertext)) != CRYPT_OK) return err; + if ((err = salsa20_done(&st)) != CRYPT_OK) return err; + + if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, ciphertext, msglen, msg2)) != CRYPT_OK) return err; + if ((err = salsa20_done(&st)) != CRYPT_OK) return err; + + if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + + + /* round trip with two single function calls */ + if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), msg, msglen, ciphertext)) != CRYPT_OK) return err; + if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), ciphertext, msglen, msg2)) != CRYPT_OK) return err; + if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + } + +#ifdef LTC_SHA256 + /*************************************************************************** + * verify correct generation of a keystream + */ + { + const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89}; + const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37}; + const unsigned char expecthash[] = {0x6a,0x60,0x57,0x65,0x27,0xe0,0x00,0x51,0x6d,0xb0,0xda,0x60,0x46,0x20,0xf6,0xd0,0x95,0x65,0x45,0x39,0xf4,0x86,0x83,0x43,0x64,0xdf,0xd9,0x5a,0x6f,0x3f,0xbe,0xb7}; + int rounds = 20; + unsigned char keystream[91101]; + unsigned long keystreamlen = 91101; + unsigned char hash[32]; + salsa20_state st; + int err; + + if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; + if ((err = salsa20_keystream(&st, keystream, keystreamlen)) != CRYPT_OK) return err; + if ((err = salsa20_done(&st)) != CRYPT_OK) return err; + if ((err = s_sha256(hash, keystream, keystreamlen)) != CRYPT_OK) return err; + if (compare_testvector(hash, sizeof(hash), expecthash, sizeof(expecthash), "XSALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + } +#endif + + return CRYPT_OK; + +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream.c new file mode 100644 index 0000000..4445151 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream.c @@ -0,0 +1,333 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file sober128_stream.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +#define LTC_SOBER128TAB_C +#include "sober128tab.c" + +/* don't change these... */ +#define N 17 +#define INITKONST 0x6996c53a /* value of KONST to use during key loading */ +#define KEYP 15 /* where to insert key words */ +#define FOLDP 4 /* where to insert non-linear feedback */ + +static ulong32 BYTE2WORD(const unsigned char *b) +{ + ulong32 t; + LOAD32L(t, b); + return t; +} + +static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out) +{ + ulong32 t; + LOAD32L(t, in); + t ^= w; + STORE32L(t, out); +} + +/* give correct offset for the current position of the register, + * where logically R[0] is at position "zero". + */ +#define OFF(zero, i) (((zero)+(i)) % N) + +/* step the LFSR */ +/* After stepping, "zero" moves right one place */ +#define STEP(R,z) \ + R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; + +static void cycle(ulong32 *R) +{ + ulong32 t; + int i; + + STEP(R,0); + t = R[0]; + for (i = 1; i < N; ++i) { + R[i-1] = R[i]; + } + R[N-1] = t; +} + +/* Return a non-linear function of some parts of the register. + */ +#define NLFUNC(st,z) \ +{ \ + t = st->R[OFF(z,0)] + st->R[OFF(z,16)]; \ + t ^= Sbox[(t >> 24) & 0xFF]; \ + t = RORc(t, 8); \ + t = ((t + st->R[OFF(z,1)]) ^ st->konst) + st->R[OFF(z,6)]; \ + t ^= Sbox[(t >> 24) & 0xFF]; \ + t = t + st->R[OFF(z,13)]; \ +} + +static ulong32 nltap(const sober128_state *st) +{ + ulong32 t; + NLFUNC(st, 0); + return t; +} + +/* Save the current register state + */ +static void s128_savestate(sober128_state *st) +{ + int i; + for (i = 0; i < N; ++i) { + st->initR[i] = st->R[i]; + } +} + +/* initialise to previously saved register state + */ +static void s128_reloadstate(sober128_state *st) +{ + int i; + + for (i = 0; i < N; ++i) { + st->R[i] = st->initR[i]; + } +} + +/* Initialise "konst" + */ +static void s128_genkonst(sober128_state *st) +{ + ulong32 newkonst; + + do { + cycle(st->R); + newkonst = nltap(st); + } while ((newkonst & 0xFF000000) == 0); + st->konst = newkonst; +} + +/* Load key material into the register + */ +#define ADDKEY(k) \ + st->R[KEYP] += (k); + +#define XORNL(nl) \ + st->R[FOLDP] ^= (nl); + +/* nonlinear diffusion of register for key */ +#define DROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); st->R[OFF((z+1),FOLDP)] ^= t; +static void s128_diffuse(sober128_state *st) +{ + ulong32 t; + /* relies on FOLD == N == 17! */ + DROUND(0); + DROUND(1); + DROUND(2); + DROUND(3); + DROUND(4); + DROUND(5); + DROUND(6); + DROUND(7); + DROUND(8); + DROUND(9); + DROUND(10); + DROUND(11); + DROUND(12); + DROUND(13); + DROUND(14); + DROUND(15); + DROUND(16); +} + +/** + Initialize an Sober128 context (only the key) + @param st [out] The destination of the Sober128 state + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen) +{ + ulong32 i, k; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen > 0); + + /* keylen must be multiple of 4 bytes */ + if ((keylen & 3) != 0) { + return CRYPT_INVALID_KEYSIZE; + } + + /* Register initialised to Fibonacci numbers */ + st->R[0] = 1; + st->R[1] = 1; + for (i = 2; i < N; ++i) { + st->R[i] = st->R[i-1] + st->R[i-2]; + } + st->konst = INITKONST; + + for (i = 0; i < keylen; i += 4) { + k = BYTE2WORD((unsigned char *)&key[i]); + ADDKEY(k); + cycle(st->R); + XORNL(nltap(st)); + } + + /* also fold in the length of the key */ + ADDKEY(keylen); + + /* now diffuse */ + s128_diffuse(st); + s128_genkonst(st); + s128_savestate(st); + st->nbuf = 0; + + return CRYPT_OK; +} + +/** + Set IV to the Sober128 state + @param st The Sober12820 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12) + @return CRYPT_OK on success + */ +int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen) +{ + ulong32 i, k; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(ivlen > 0); + + /* ok we are adding an IV then... */ + s128_reloadstate(st); + + /* ivlen must be multiple of 4 bytes */ + if ((ivlen & 3) != 0) { + return CRYPT_INVALID_KEYSIZE; + } + + for (i = 0; i < ivlen; i += 4) { + k = BYTE2WORD((unsigned char *)&iv[i]); + ADDKEY(k); + cycle(st->R); + XORNL(nltap(st)); + } + + /* also fold in the length of the key */ + ADDKEY(ivlen); + + /* now diffuse */ + s128_diffuse(st); + st->nbuf = 0; + + return CRYPT_OK; +} + +/* XOR pseudo-random bytes into buffer + */ +#define SROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); XORWORD(t, in+(z*4), out+(z*4)); + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128 + @param st The Sober128 state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + ulong32 t; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(st != NULL); + + /* handle any previously buffered bytes */ + while (st->nbuf != 0 && inlen != 0) { + *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); + st->sbuf >>= 8; + st->nbuf -= 8; + --inlen; + } + +#ifndef LTC_SMALL_CODE + /* do lots at a time, if there's enough to do */ + while (inlen >= N*4) { + SROUND(0); + SROUND(1); + SROUND(2); + SROUND(3); + SROUND(4); + SROUND(5); + SROUND(6); + SROUND(7); + SROUND(8); + SROUND(9); + SROUND(10); + SROUND(11); + SROUND(12); + SROUND(13); + SROUND(14); + SROUND(15); + SROUND(16); + out += 4*N; + in += 4*N; + inlen -= 4*N; + } +#endif + + /* do small or odd size buffers the slow way */ + while (4 <= inlen) { + cycle(st->R); + t = nltap(st); + XORWORD(t, in, out); + out += 4; + in += 4; + inlen -= 4; + } + + /* handle any trailing bytes */ + if (inlen != 0) { + cycle(st->R); + st->sbuf = nltap(st); + st->nbuf = 32; + while (st->nbuf != 0 && inlen != 0) { + *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); + st->sbuf >>= 8; + st->nbuf -= 8; + --inlen; + } + } + + return CRYPT_OK; +} + +int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return sober128_stream_crypt(st, out, outlen, out); +} + +/** + Terminate and clear Sober128 state + @param st The Sober128 state + @return CRYPT_OK on success +*/ +int sober128_stream_done(sober128_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(sober128_state)); + return CRYPT_OK; +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream_memory.c new file mode 100644 index 0000000..5150b82 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_stream_memory.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOBER128_STREAM + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with SOBER128 + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int sober128_stream_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout) +{ + sober128_state st; + int err; + + if ((err = sober128_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; + if ((err = sober128_stream_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; + err = sober128_stream_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + sober128_stream_done(&st); + return err; +} + +#endif /* LTC_SOBER128_STREAM */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c new file mode 100644 index 0000000..52ea3a8 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOBER128 + +int sober128_stream_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char key[16] = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79, + 0x20, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x73 }; + unsigned char iv[4] = { 0x00, 0x00, 0x00, 0x00 }; + unsigned char out[20] = { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d, + 0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2, + 0x40, 0x37, 0x8b, 0xbb }; + int err, len = 20; + unsigned char src[20], dst[20]; + sober128_state st; + + XMEMSET(src, 0, len); /* input */ + if ((err = sober128_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err; + if ((err = sober128_stream_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = sober128_stream_crypt(&st, src, len, dst)) != CRYPT_OK) return err; + if ((err = sober128_stream_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(dst, len, out, len, "SOBER-128-TV1", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* crypt in a single call */ + if ((err = sober128_stream_memory(key, sizeof(key), iv, sizeof(iv), + src, len, dst)) != CRYPT_OK) return err; + if (compare_testvector(dst, len, out, len, "SOBER-128-TV2", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128tab.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128tab.c new file mode 100644 index 0000000..e067bb6 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/sober128/sober128tab.c @@ -0,0 +1,166 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file sober128tab.c + SOBER-128 Tables +*/ + +#ifdef LTC_SOBER128TAB_C + +/* $ID$ */ +/* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */ +/* Multiplication table for Turing using 0xD02B4367 */ +static const ulong32 Multab[256] = { + 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, + 0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478, + 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746, + 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, + 0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A, + 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB, + 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, + 0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04, + 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2, + 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, + 0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D, + 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC, + 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, + 0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80, + 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE, + 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, + 0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F, + 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE, + 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, + 0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41, + 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC, + 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, + 0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703, + 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2, + 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, + 0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5, + 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB, + 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, + 0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787, + 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656, + 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, + 0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9, + 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748, + 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, + 0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7, + 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476, + 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, + 0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A, + 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34, + 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, + 0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523, + 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2, + 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, + 0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D, + 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0, + 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, + 0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F, + 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E, + 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, + 0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F, + 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71, + 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, + 0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D, + 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC, + 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, + 0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433, + 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5, + 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, + 0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A, + 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB, + 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, + 0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7, + 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789, + 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658, +}; + +/* $ID$ */ +/* Sbox for SOBER-128 */ +/* + * This is really the combination of two SBoxes; the least significant + * 24 bits comes from: + * 8->32 Sbox generated by Millan et. al. at Queensland University of + * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter, + * "On the Design of 8*32 S-boxes". Unpublished report, by the + * Information Systems Research Centre, + * Queensland University of Technology, 1999. + * + * The most significant 8 bits are the Skipjack "F table", which can be + * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf . + * In this optimised table, though, the intent is to XOR the word from + * the table selected by the high byte with the input word. Thus, the + * high byte is actually the Skipjack F-table entry XORED with its + * table index. + */ +static const ulong32 Sbox[256] = { + 0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4, + 0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae, + 0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c, + 0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35, + 0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e, + 0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b, + 0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f, + 0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1, + 0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd, + 0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3, + 0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f, + 0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36, + 0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf, + 0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816, + 0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d, + 0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af, + 0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6, + 0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418, + 0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0, + 0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd, + 0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088, + 0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759, + 0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895, + 0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66, + 0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc, + 0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1, + 0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911, + 0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e, + 0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515, + 0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133, + 0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226, + 0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084, + 0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb, + 0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184, + 0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420, + 0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02, + 0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655, + 0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c, + 0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418, + 0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473, + 0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a, + 0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0, + 0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21, + 0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36, + 0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5, + 0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6, + 0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0, + 0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795, + 0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0, + 0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78, + 0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da, + 0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a, + 0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118, + 0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed, + 0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd, + 0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b, + 0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921, + 0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e, + 0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5, + 0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8, + 0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376, + 0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a, + 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8, + 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40, +}; + +#endif /* LTC_SOBER128TAB_C */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c new file mode 100644 index 0000000..6733450 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c @@ -0,0 +1,807 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * This LTC implementation was adapted from: + * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html + */ + +/* + * SOSEMANUK reference implementation. + * + * This code is supposed to run on any conforming C implementation (C90 + * or later). + * + * (c) 2005 X-CRYPT project. This software is provided 'as-is', without + * any express or implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to no restriction. + * + * Technical remarks and questions can be addressed to + * + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK + +/* ======================================================================== */ + +/* + * We want (and sometimes need) to perform explicit truncations to 32 bits. + */ +#define T32(x) ((x) & (ulong32)0xFFFFFFFF) + +/* + * Some of our functions will be tagged as "inline" to help the compiler + * optimize things. We use "inline" only if the compiler is advanced + * enough to understand it; C99 compilers, and pre-C99 versions of gcc, + * understand enough "inline" for our purposes. + */ + +/* ======================================================================== */ + +/* + * Serpent S-boxes, implemented in bitslice mode. These circuits have + * been published by Dag Arne Osvik ("Speeding up Serpent", published in + * the 3rd AES Candidate Conference) and work on five 32-bit registers: + * the four inputs, and a fifth scratch register. There are meant to be + * quite fast on Pentium-class processors. These are not the fastest + * published, but they are "fast enough" and they are unencumbered as + * far as intellectual property is concerned (note: these are rewritten + * from the article itself, and hence are not covered by the GPL on + * Dag's code, which was not used here). + * + * The output bits are permuted. Here is the correspondance: + * S0: 1420 + * S1: 2031 + * S2: 2314 + * S3: 1234 + * S4: 1403 + * S5: 1302 + * S6: 0142 + * S7: 4310 + * (for instance, the output of S0 is in "r1, r4, r2, r0"). + */ + +#define S0(r0, r1, r2, r3, r4) do { \ + r3 ^= r0; r4 = r1; \ + r1 &= r3; r4 ^= r2; \ + r1 ^= r0; r0 |= r3; \ + r0 ^= r4; r4 ^= r3; \ + r3 ^= r2; r2 |= r1; \ + r2 ^= r4; r4 = ~r4; \ + r4 |= r1; r1 ^= r3; \ + r1 ^= r4; r3 |= r0; \ + r1 ^= r3; r4 ^= r3; \ + } while (0) + +#define S1(r0, r1, r2, r3, r4) do { \ + r0 = ~r0; r2 = ~r2; \ + r4 = r0; r0 &= r1; \ + r2 ^= r0; r0 |= r3; \ + r3 ^= r2; r1 ^= r0; \ + r0 ^= r4; r4 |= r1; \ + r1 ^= r3; r2 |= r0; \ + r2 &= r4; r0 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; r0 &= r2; \ + r0 ^= r4; \ + } while (0) + +#define S2(r0, r1, r2, r3, r4) do { \ + r4 = r0; r0 &= r2; \ + r0 ^= r3; r2 ^= r1; \ + r2 ^= r0; r3 |= r4; \ + r3 ^= r1; r4 ^= r2; \ + r1 = r3; r3 |= r4; \ + r3 ^= r0; r0 &= r1; \ + r4 ^= r0; r1 ^= r3; \ + r1 ^= r4; r4 = ~r4; \ + } while (0) + +#define S3(r0, r1, r2, r3, r4) do { \ + r4 = r0; r0 |= r3; \ + r3 ^= r1; r1 &= r4; \ + r4 ^= r2; r2 ^= r3; \ + r3 &= r0; r4 |= r1; \ + r3 ^= r4; r0 ^= r1; \ + r4 &= r0; r1 ^= r3; \ + r4 ^= r2; r1 |= r0; \ + r1 ^= r2; r0 ^= r3; \ + r2 = r1; r1 |= r3; \ + r1 ^= r0; \ + } while (0) + +#define S4(r0, r1, r2, r3, r4) do { \ + r1 ^= r3; r3 = ~r3; \ + r2 ^= r3; r3 ^= r0; \ + r4 = r1; r1 &= r3; \ + r1 ^= r2; r4 ^= r3; \ + r0 ^= r4; r2 &= r4; \ + r2 ^= r0; r0 &= r1; \ + r3 ^= r0; r4 |= r1; \ + r4 ^= r0; r0 |= r3; \ + r0 ^= r2; r2 &= r3; \ + r0 = ~r0; r4 ^= r2; \ + } while (0) + +#define S5(r0, r1, r2, r3, r4) do { \ + r0 ^= r1; r1 ^= r3; \ + r3 = ~r3; r4 = r1; \ + r1 &= r0; r2 ^= r3; \ + r1 ^= r2; r2 |= r4; \ + r4 ^= r3; r3 &= r1; \ + r3 ^= r0; r4 ^= r1; \ + r4 ^= r2; r2 ^= r0; \ + r0 &= r3; r2 = ~r2; \ + r0 ^= r4; r4 |= r3; \ + r2 ^= r4; \ + } while (0) + +#define S6(r0, r1, r2, r3, r4) do { \ + r2 = ~r2; r4 = r3; \ + r3 &= r0; r0 ^= r4; \ + r3 ^= r2; r2 |= r4; \ + r1 ^= r3; r2 ^= r0; \ + r0 |= r1; r2 ^= r1; \ + r4 ^= r0; r0 |= r3; \ + r0 ^= r2; r4 ^= r3; \ + r4 ^= r0; r3 = ~r3; \ + r2 &= r4; \ + r2 ^= r3; \ + } while (0) + +#define S7(r0, r1, r2, r3, r4) do { \ + r4 = r1; r1 |= r2; \ + r1 ^= r3; r4 ^= r2; \ + r2 ^= r1; r3 |= r4; \ + r3 &= r0; r4 ^= r2; \ + r3 ^= r1; r1 |= r4; \ + r1 ^= r0; r0 |= r4; \ + r0 ^= r2; r1 ^= r4; \ + r2 ^= r1; r1 &= r0; \ + r1 ^= r4; r2 = ~r2; \ + r2 |= r0; \ + r4 ^= r2; \ + } while (0) + +/* + * The Serpent linear transform. + */ +#define SERPENT_LT(x0, x1, x2, x3) do { \ + x0 = ROLc(x0, 13); \ + x2 = ROLc(x2, 3); \ + x1 = x1 ^ x0 ^ x2; \ + x3 = x3 ^ x2 ^ T32(x0 << 3); \ + x1 = ROLc(x1, 1); \ + x3 = ROLc(x3, 7); \ + x0 = x0 ^ x1 ^ x3; \ + x2 = x2 ^ x3 ^ T32(x1 << 7); \ + x0 = ROLc(x0, 5); \ + x2 = ROLc(x2, 22); \ + } while (0) + +/* ======================================================================== */ + +/* + * Initialize Sosemanuk's state by providing a key. The key is an array of + * 1 to 32 bytes. + * @param st The Sosemanuk state + * @param key Key + * @param keylen Length of key in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen) +{ + /* + * This key schedule is actually a truncated Serpent key schedule. + * The key-derived words (w_i) are computed within the eight + * local variables w0 to w7, which are reused again and again. + */ + +#define SKS(S, o0, o1, o2, o3, d0, d1, d2, d3) do { \ + ulong32 r0, r1, r2, r3, r4; \ + r0 = w ## o0; \ + r1 = w ## o1; \ + r2 = w ## o2; \ + r3 = w ## o3; \ + S(r0, r1, r2, r3, r4); \ + st->kc[i ++] = r ## d0; \ + st->kc[i ++] = r ## d1; \ + st->kc[i ++] = r ## d2; \ + st->kc[i ++] = r ## d3; \ + } while (0) + +#define SKS0 SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0) +#define SKS1 SKS(S1, 0, 1, 2, 3, 2, 0, 3, 1) +#define SKS2 SKS(S2, 4, 5, 6, 7, 2, 3, 1, 4) +#define SKS3 SKS(S3, 0, 1, 2, 3, 1, 2, 3, 4) +#define SKS4 SKS(S4, 4, 5, 6, 7, 1, 4, 0, 3) +#define SKS5 SKS(S5, 0, 1, 2, 3, 1, 3, 0, 2) +#define SKS6 SKS(S6, 4, 5, 6, 7, 0, 1, 4, 2) +#define SKS7 SKS(S7, 0, 1, 2, 3, 4, 3, 1, 0) + +#define WUP(wi, wi5, wi3, wi1, cc) do { \ + ulong32 tt = (wi) ^ (wi5) ^ (wi3) \ + ^ (wi1) ^ (0x9E3779B9 ^ (ulong32)(cc)); \ + (wi) = ROLc(tt, 11); \ + } while (0) + +#define WUP0(cc) do { \ + WUP(w0, w3, w5, w7, cc); \ + WUP(w1, w4, w6, w0, cc + 1); \ + WUP(w2, w5, w7, w1, cc + 2); \ + WUP(w3, w6, w0, w2, cc + 3); \ + } while (0) + +#define WUP1(cc) do { \ + WUP(w4, w7, w1, w3, cc); \ + WUP(w5, w0, w2, w4, cc + 1); \ + WUP(w6, w1, w3, w5, cc + 2); \ + WUP(w7, w2, w4, w6, cc + 3); \ + } while (0) + + unsigned char wbuf[32]; + ulong32 w0, w1, w2, w3, w4, w5, w6, w7; + int i = 0; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen > 0 && keylen <= 32); + + /* + * The key is copied into the wbuf[] buffer and padded to 256 bits + * as described in the Serpent specification. + */ + XMEMCPY(wbuf, key, keylen); + if (keylen < 32) { + wbuf[keylen] = 0x01; + if (keylen < 31) { + XMEMSET(wbuf + keylen + 1, 0, 31 - keylen); + } + } + + LOAD32L(w0, wbuf); + LOAD32L(w1, wbuf + 4); + LOAD32L(w2, wbuf + 8); + LOAD32L(w3, wbuf + 12); + LOAD32L(w4, wbuf + 16); + LOAD32L(w5, wbuf + 20); + LOAD32L(w6, wbuf + 24); + LOAD32L(w7, wbuf + 28); + + WUP0(0); SKS3; + WUP1(4); SKS2; + WUP0(8); SKS1; + WUP1(12); SKS0; + WUP0(16); SKS7; + WUP1(20); SKS6; + WUP0(24); SKS5; + WUP1(28); SKS4; + WUP0(32); SKS3; + WUP1(36); SKS2; + WUP0(40); SKS1; + WUP1(44); SKS0; + WUP0(48); SKS7; + WUP1(52); SKS6; + WUP0(56); SKS5; + WUP1(60); SKS4; + WUP0(64); SKS3; + WUP1(68); SKS2; + WUP0(72); SKS1; + WUP1(76); SKS0; + WUP0(80); SKS7; + WUP1(84); SKS6; + WUP0(88); SKS5; + WUP1(92); SKS4; + WUP0(96); SKS3; + +#undef SKS +#undef SKS0 +#undef SKS1 +#undef SKS2 +#undef SKS3 +#undef SKS4 +#undef SKS5 +#undef SKS6 +#undef SKS7 +#undef WUP +#undef WUP0 +#undef WUP1 + + return CRYPT_OK; +} + + +/* + * Initialization continues by setting the IV. The IV length is up to 16 bytes. + * If "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. If multiple + * encryptions/decryptions are to be performed with the same key and + * sosemanuk_done() has not been called, only sosemanuk_setiv() need be called + * to set the state. + * @param st The Sosemanuk state + * @param iv Initialization vector + * @param ivlen Length of iv in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen) +{ + + /* + * The Serpent key addition step. + */ +#define KA(zc, x0, x1, x2, x3) do { \ + x0 ^= st->kc[(zc)]; \ + x1 ^= st->kc[(zc) + 1]; \ + x2 ^= st->kc[(zc) + 2]; \ + x3 ^= st->kc[(zc) + 3]; \ + } while (0) + + /* + * One Serpent round. + * zc = current subkey counter + * S = S-box macro for this round + * i0 to i4 = input register numbers (the fifth is a scratch register) + * o0 to o3 = output register numbers + */ +#define FSS(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ + KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ + S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ + SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ + } while (0) + + /* + * Last Serpent round. Contrary to the "true" Serpent, we keep + * the linear transformation for that last round. + */ +#define FSF(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ + KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ + S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ + SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ + KA(zc + 4, r ## o0, r ## o1, r ## o2, r ## o3); \ + } while (0) + + ulong32 r0, r1, r2, r3, r4; + unsigned char ivtmp[16] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(ivlen <= 16); + LTC_ARGCHK(iv != NULL || ivlen == 0); + + if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen); + + /* + * Decode IV into four 32-bit words (little-endian). + */ + LOAD32L(r0, ivtmp); + LOAD32L(r1, ivtmp + 4); + LOAD32L(r2, ivtmp + 8); + LOAD32L(r3, ivtmp + 12); + + /* + * Encrypt IV with Serpent24. Some values are extracted from the + * output of the twelfth, eighteenth and twenty-fourth rounds. + */ + FSS(0, S0, 0, 1, 2, 3, 4, 1, 4, 2, 0); + FSS(4, S1, 1, 4, 2, 0, 3, 2, 1, 0, 4); + FSS(8, S2, 2, 1, 0, 4, 3, 0, 4, 1, 3); + FSS(12, S3, 0, 4, 1, 3, 2, 4, 1, 3, 2); + FSS(16, S4, 4, 1, 3, 2, 0, 1, 0, 4, 2); + FSS(20, S5, 1, 0, 4, 2, 3, 0, 2, 1, 4); + FSS(24, S6, 0, 2, 1, 4, 3, 0, 2, 3, 1); + FSS(28, S7, 0, 2, 3, 1, 4, 4, 1, 2, 0); + FSS(32, S0, 4, 1, 2, 0, 3, 1, 3, 2, 4); + FSS(36, S1, 1, 3, 2, 4, 0, 2, 1, 4, 3); + FSS(40, S2, 2, 1, 4, 3, 0, 4, 3, 1, 0); + FSS(44, S3, 4, 3, 1, 0, 2, 3, 1, 0, 2); + st->s09 = r3; + st->s08 = r1; + st->s07 = r0; + st->s06 = r2; + + FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2); + FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3); + FSS(56, S6, 4, 2, 1, 3, 0, 4, 2, 0, 1); + FSS(60, S7, 4, 2, 0, 1, 3, 3, 1, 2, 4); + FSS(64, S0, 3, 1, 2, 4, 0, 1, 0, 2, 3); + FSS(68, S1, 1, 0, 2, 3, 4, 2, 1, 3, 0); + st->r1 = r2; + st->s04 = r1; + st->r2 = r3; + st->s05 = r0; + + FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4); + FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2); + FSS(80, S4, 0, 1, 4, 2, 3, 1, 3, 0, 2); + FSS(84, S5, 1, 3, 0, 2, 4, 3, 2, 1, 0); + FSS(88, S6, 3, 2, 1, 0, 4, 3, 2, 4, 1); + FSF(92, S7, 3, 2, 4, 1, 0, 0, 1, 2, 3); + st->s03 = r0; + st->s02 = r1; + st->s01 = r2; + st->s00 = r3; + + st->ptr = sizeof(st->buf); + +#undef KA +#undef FSS +#undef FSF + + return CRYPT_OK; +} + +/* + * Multiplication by alpha: alpha * x = T32(x << 8) ^ mul_a[x >> 24] + */ +static const ulong32 mul_a[] = { + 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, + 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, + 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, + 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, + 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, + 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, + 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, + 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, + 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, + 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, + 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, + 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, + 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, + 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, + 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, + 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, + 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, + 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, + 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, + 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, + 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, + 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, + 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, + 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, + 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, + 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, + 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, + 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, + 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, + 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, + 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, + 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, + 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, + 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, + 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, + 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, + 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, + 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, + 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, + 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, + 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, + 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, + 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, + 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, + 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, + 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, + 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, + 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, + 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, + 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, + 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, + 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, + 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, + 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, + 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, + 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, + 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, + 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, + 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, + 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, + 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, + 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, + 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, + 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB +}; + +/* + * Multiplication by 1/alpha: 1/alpha * x = (x >> 8) ^ mul_ia[x & 0xFF] + */ +static const ulong32 mul_ia[] = { + 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, + 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, + 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, + 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, + 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, + 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, + 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, + 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, + 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, + 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, + 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, + 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, + 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, + 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, + 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, + 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, + 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, + 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, + 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, + 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, + 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, + 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, + 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, + 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, + 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, + 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, + 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, + 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, + 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, + 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, + 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, + 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, + 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, + 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, + 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, + 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, + 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, + 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, + 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, + 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, + 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, + 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, + 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, + 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, + 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, + 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, + 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, + 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, + 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, + 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, + 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, + 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, + 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, + 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, + 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, + 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, + 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, + 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, + 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, + 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, + 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, + 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, + 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, + 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 +}; + + +/* + * Compute the next block of bits of output stream. This is equivalent + * to one full rotation of the shift register. + */ +static LTC_INLINE void s_sosemanuk_internal(sosemanuk_state *st) +{ + /* + * MUL_A(x) computes alpha * x (in F_{2^32}). + * MUL_G(x) computes 1/alpha * x (in F_{2^32}). + */ +#define MUL_A(x) (T32((x) << 8) ^ mul_a[(x) >> 24]) +#define MUL_G(x) (((x) >> 8) ^ mul_ia[(x) & 0xFF]) + + /* + * This macro computes the special multiplexer, which chooses + * between "x" and "x xor y", depending on the least significant + * bit of the control word. We use the C "?:" selection operator + * (which most compilers know how to optimise) except for Alpha, + * where the manual sign extension seems to perform equally well + * with DEC/Compaq/HP compiler, and much better with gcc. + */ +#ifdef __alpha +#define XMUX(c, x, y) ((((signed int)((c) << 31) >> 31) & (y)) ^ (x)) +#else +#define XMUX(c, x, y) (((c) & 0x1) ? ((x) ^ (y)) : (x)) +#endif + + /* + * FSM() updates the finite state machine. + */ +#define FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) do { \ + ulong32 tt, or1; \ + tt = XMUX(r1, s ## x1, s ## x8); \ + or1 = r1; \ + r1 = T32(r2 + tt); \ + tt = T32(or1 * 0x54655307); \ + r2 = ROLc(tt, 7); \ + } while (0) + + /* + * LRU updates the shift register; the dropped value is stored + * in variable "dd". + */ +#define LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd) do { \ + dd = s ## x0; \ + s ## x0 = MUL_A(s ## x0) ^ MUL_G(s ## x3) ^ s ## x9; \ + } while (0) + + /* + * CC1 stores into variable "ee" the next intermediate word + * (combination of the new states of the LFSR and the FSM). + */ +#define CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee) do { \ + ee = T32(s ## x9 + r1) ^ r2; \ + } while (0) + + /* + * STEP computes one internal round. "dd" receives the "s_t" + * value (dropped from the LFSR) and "ee" gets the value computed + * from the LFSR and FSM. + */ +#define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd, ee) do { \ + FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9); \ + LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd); \ + CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee); \ + } while (0) + + /* + * Apply one Serpent round (with the provided S-box macro), XOR + * the result with the "v" values, and encode the result into + * the destination buffer, at the provided offset. The "x*" + * arguments encode the output permutation of the "S" macro. + */ +#define SRD(S, x0, x1, x2, x3, ooff) do { \ + S(u0, u1, u2, u3, u4); \ + STORE32L(u ## x0 ^ v0, st->buf + ooff); \ + STORE32L(u ## x1 ^ v1, st->buf + ooff + 4); \ + STORE32L(u ## x2 ^ v2, st->buf + ooff + 8); \ + STORE32L(u ## x3 ^ v3, st->buf + ooff + 12); \ + } while (0) + + ulong32 s00 = st->s00; + ulong32 s01 = st->s01; + ulong32 s02 = st->s02; + ulong32 s03 = st->s03; + ulong32 s04 = st->s04; + ulong32 s05 = st->s05; + ulong32 s06 = st->s06; + ulong32 s07 = st->s07; + ulong32 s08 = st->s08; + ulong32 s09 = st->s09; + ulong32 r1 = st->r1; + ulong32 r2 = st->r2; + ulong32 u0, u1, u2, u3, u4; + ulong32 v0, v1, v2, v3; + + STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v0, u0); + STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v1, u1); + STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v2, u2); + STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v3, u3); + SRD(S2, 2, 3, 1, 4, 0); + STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v0, u0); + STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v1, u1); + STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v2, u2); + STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v3, u3); + SRD(S2, 2, 3, 1, 4, 16); + STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v0, u0); + STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v1, u1); + STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v2, u2); + STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v3, u3); + SRD(S2, 2, 3, 1, 4, 32); + STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v0, u0); + STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v1, u1); + STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v2, u2); + STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v3, u3); + SRD(S2, 2, 3, 1, 4, 48); + STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v0, u0); + STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v1, u1); + STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v2, u2); + STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v3, u3); + SRD(S2, 2, 3, 1, 4, 64); + + st->s00 = s00; + st->s01 = s01; + st->s02 = s02; + st->s03 = s03; + st->s04 = s04; + st->s05 = s05; + st->s06 = s06; + st->s07 = s07; + st->s08 = s08; + st->s09 = s09; + st->r1 = r1; + st->r2 = r2; +} + +/* + * Combine buffers in1[] and in2[] by XOR, result in out[]. The length + * is "datalen" (in bytes). Partial overlap of out[] with either in1[] + * or in2[] is not allowed. Total overlap (out == in1 and/or out == in2) + * is allowed. + */ +static LTC_INLINE void s_xorbuf(const unsigned char *in1, const unsigned char *in2, + unsigned char *out, unsigned long datalen) +{ + while (datalen -- > 0) { + *out ++ = *in1 ++ ^ *in2 ++; + } +} + + +/* + * Cipher operation, as a stream cipher: data is read from the "in" + * buffer, combined by XOR with the stream, and the result is written + * in the "out" buffer. "in" and "out" must be either equal, or + * reference distinct buffers (no partial overlap is allowed). + * @param st The Sosemanuk state + * @param in Data in + * @param inlen Length of data in bytes + * @param out Data out + * @return CRYPT_OK on success + */ +int sosemanuk_crypt(sosemanuk_state *st, + const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if (st->ptr < (sizeof(st->buf))) { + unsigned long rlen = (sizeof(st->buf)) - st->ptr; + + if (rlen > inlen) { + rlen = inlen; + } + s_xorbuf(st->buf + st->ptr, in, out, rlen); + in += rlen; + out += rlen; + inlen -= rlen; + st->ptr += rlen; + } + while (inlen > 0) { + s_sosemanuk_internal(st); + if (inlen >= sizeof(st->buf)) { + s_xorbuf(st->buf, in, out, sizeof(st->buf)); + in += sizeof(st->buf); + out += sizeof(st->buf); + inlen -= sizeof(st->buf); + } else { + s_xorbuf(st->buf, in, out, inlen); + st->ptr = inlen; + inlen = 0; + } + } + return CRYPT_OK; +} + + + +/* + * Cipher operation, as a PRNG: the provided output buffer is filled with + * pseudo-random bytes as output from the stream cipher. + * @param st The Sosemanuk state + * @param out Data out + * @param outlen Length of output in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return sosemanuk_crypt(st, out, outlen, out); +} + + +/* + * Terminate and clear Sosemanuk key context + * @param st The Sosemanuk state + * @return CRYPT_OK on success + */ +int sosemanuk_done(sosemanuk_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(sosemanuk_state)); + return CRYPT_OK; +} + + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c new file mode 100644 index 0000000..c0fac25 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sosemanuk + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int sosemanuk_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout) +{ + sosemanuk_state st; + int err; + + if ((err = sosemanuk_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; + if ((err = sosemanuk_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; + err = sosemanuk_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + sosemanuk_done(&st); + return err; +} + +#endif /* LTC_SOSEMANUK */ diff --git a/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c b/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c new file mode 100644 index 0000000..2c0a887 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c @@ -0,0 +1,79 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK +int sosemanuk_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + sosemanuk_state st; + int err; + unsigned char out[1000]; + + { + unsigned char k[] = { 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 }; + unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + unsigned char ct[] = { 0x7e, 0xfe, 0x2e, 0x6f, 0x8f, 0x77, 0x15, 0x72, 0x6a, 0x88, 0x14, 0xa6, 0x56, 0x88, 0x29, 0x9a, + 0x86, 0x32, 0x7f, 0x14, 0xd6, 0xb1, 0x94, 0x90, 0x25, 0xbc, 0x73, 0xfd, 0x02, 0x6c, 0x6a, 0xb8, + 0xda, 0x8e, 0x7f, 0x61, 0x70, 0x81, 0xe3, 0xbb, 0x99, 0xaf, 0x19, 0x9f, 0x20, 0x45 }; + char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */ + unsigned long len; + len = XSTRLEN(pt); + /* crypt piece by piece */ + if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in one go - using sosemanuk_ivctr64() */ + if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in a single call */ + if ((err = sosemanuk_memory(k, sizeof(k), n, sizeof(n), + (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + } + { + /* keystream + * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=210&view=auto + * Set 6, vector 0 + * key = 0053A6F94C9FF24598EB3E91E4378ADD + * 3083D6297CCF2275C81B6EC11467BA0D + * IV = 0D74DB42A91077DE45AC137AE148AF16 + * stream[0..63] = 55EB8D174C2E0351E5A53C90E84740EB + * 0F5A24AAFEC8E0C9F9D2CE48B2ADB0A3 + * 4D2E8C4E016102607368FFA43A0F9155 + * 0706E3548AD9E5EA15A53EB6F0EDE9DC + * + */ + + unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, + 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D }; + unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE, 0x45, 0xAC, 0x13, 0x7A, 0xE1, 0x48, 0xAF, 0x16 }; + unsigned char ct3[] = { 0x55, 0xEB, 0x8D, 0x17, 0x4C, 0x2E, 0x03, 0x51, 0xE5, 0xA5, 0x3C, 0x90, 0xE8, 0x47, 0x40, 0xEB, + 0x0F, 0x5A, 0x24, 0xAA, 0xFE, 0xC8, 0xE0, 0xC9, 0xF9, 0xD2, 0xCE, 0x48, 0xB2, 0xAD, 0xB0, 0xA3, + 0x4D, 0x2E, 0x8C, 0x4E, 0x01, 0x61, 0x02, 0x60, 0x73, 0x68, 0xFF, 0xA4, 0x3A, 0x0F, 0x91, 0x55, + 0x07, 0x06, 0xE3, 0x54, 0x8A, 0xD9, 0xE5, 0xEA, 0x15, 0xA5, 0x3E, 0xB6, 0xF0, 0xED, 0xE9, 0xDC }; + if ((err = sosemanuk_setup(&st, k3, sizeof(k3))) != CRYPT_OK) return err; + if ((err = sosemanuk_setiv(&st, n3, sizeof(n3))) != CRYPT_OK) return err; + if ((err = sosemanuk_keystream(&st, out, 64)) != CRYPT_OK) return err; + if ((err = sosemanuk_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(out, 64, ct3, sizeof(ct3), "SOSEMANUK-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/src/sub.mk b/optee/optee_os/core/lib/libtomcrypt/src/sub.mk new file mode 100644 index 0000000..d622204 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/src/sub.mk @@ -0,0 +1,9 @@ +subdirs-$(_CFG_CORE_LTC_CIPHER) += ciphers +subdirs-$(_CFG_CORE_LTC_AUTHENC) += encauth +subdirs-y += hashes +subdirs-$(_CFG_CORE_LTC_MAC) += mac +subdirs-$(_CFG_CORE_LTC_ACIPHER) += math +subdirs-y += misc +subdirs-y += modes +subdirs-$(_CFG_CORE_LTC_ACIPHER) += pk +subdirs-$(_CFG_CORE_LTC_EC25519) += pk diff --git a/optee/optee_os/core/lib/libtomcrypt/sub.mk b/optee/optee_os/core/lib/libtomcrypt/sub.mk new file mode 100644 index 0000000..29ad4fe --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/sub.mk @@ -0,0 +1,154 @@ +global-incdirs-y += include +global-incdirs-y += src/headers + +cflags-lib-y += -Wno-declaration-after-statement + +cppflags-lib-y += -DARGTYPE=4 # Make LTC_ARGCHK() return on error +cppflags-lib-y += -DLTC_NO_TEST -DLTC_NO_PROTOTYPES +cppflags-lib-y += -DLTC_NO_TABLES -DLTC_HASH_HELPERS +cppflags-lib-y += -DLTC_NO_MISC +cppflags-lib-y += -DLTC_HMAC +cppflags-lib-$(_CFG_CORE_LTC_SIZE_OPTIMIZATION) += -DLTC_SMALL_CODE + +cppflags-lib-y += -DLTC_NO_CIPHERS + +ifeq ($(_CFG_CORE_LTC_AES_DESC),y) + cppflags-lib-y += -DLTC_RIJNDAEL +endif +ifeq ($(_CFG_CORE_LTC_DES),y) + cppflags-lib-y += -DLTC_DES +endif + +cppflags-lib-y += -DLTC_NO_MODES + +ifeq ($(_CFG_CORE_LTC_ECB),y) + cppflags-lib-y += -DLTC_ECB_MODE +endif +ifeq ($(_CFG_CORE_LTC_CBC),y) + cppflags-lib-y += -DLTC_CBC_MODE +endif +ifeq ($(_CFG_CORE_LTC_CTR),y) + cppflags-lib-y += -DLTC_CTR_MODE +endif +ifeq ($(_CFG_CORE_LTC_XTS),y) + cppflags-lib-y += -DLTC_XTS_MODE +endif + +cppflags-lib-y += -DLTC_NO_HASHES + +ifeq ($(_CFG_CORE_LTC_MD5),y) + cppflags-lib-y += -DLTC_MD5 +endif +ifeq ($(_CFG_CORE_LTC_SHA1),y) + cppflags-lib-y += -DLTC_SHA1 +endif +ifeq ($(_CFG_CORE_LTC_SHA224),y) + cppflags-lib-y += -DLTC_SHA224 +endif +ifeq ($(_CFG_CORE_LTC_SHA256_DESC),y) + cppflags-lib-y += -DLTC_SHA256 +endif +ifeq ($(_CFG_CORE_LTC_SHA384_DESC),y) + cppflags-lib-y += -DLTC_SHA384 +endif +ifeq ($(_CFG_CORE_LTC_SHA512_DESC),y) + cppflags-lib-y += -DLTC_SHA512 +endif +ifeq ($(_CFG_CORE_LTC_SHA512_256),y) + cppflags-lib-y += -DLTC_SHA512_256 +endif +cppflags-lib-$(_CFG_CORE_LTC_SHA3_DESC) += -DLTC_SHA3 + + +cppflags-lib-y += -DLTC_NO_MACS + +ifeq ($(_CFG_CORE_LTC_HMAC),y) + cppflags-lib-y += -DLTC_HMAC +endif +ifeq ($(_CFG_CORE_LTC_CMAC),y) + cppflags-lib-y += -DLTC_OMAC +endif +ifeq ($(_CFG_CORE_LTC_CCM),y) + cppflags-lib-y += -DLTC_CCM_MODE +endif +ifeq ($(_CFG_CORE_LTC_GCM),y) + cppflags-lib-y += -DLTC_GCM_MODE +endif + +cppflags-lib-y += -DLTC_NO_PK + +ifeq ($(_CFG_CORE_LTC_RSA),y) + cppflags-lib-y += -DLTC_MRSA +endif +ifeq ($(_CFG_CORE_LTC_DSA),y) + cppflags-lib-y += -DLTC_MDSA +endif +ifeq ($(_CFG_CORE_LTC_DH),y) + cppflags-lib-y += -DLTC_MDH +endif +ifeq ($(_CFG_CORE_LTC_ECC),y) + cppflags-lib-y += -DLTC_MECC + + # use Shamir's trick for point mul (speeds up signature verification) + cppflags-lib-y += -DLTC_ECC_SHAMIR + + cppflags-lib-y += -DLTC_ECC192 + cppflags-lib-y += -DLTC_ECC224 + cppflags-lib-y += -DLTC_ECC256 + cppflags-lib-y += -DLTC_ECC384 + cppflags-lib-y += -DLTC_ECC521 + cppflags-lib-y += -DLTC_CURVE25519 + + # ECC 521 bits is the max supported key size + cppflags-lib-y += -DLTC_MAX_ECC=521 +endif +ifneq (,$(filter y,$(_CFG_CORE_LTC_SM2_DSA) $(_CFG_CORE_LTC_SM2_PKE))) + cppflags-lib-y += -DLTC_ECC_SM2 +endif + +cppflags-lib-$(_CFG_CORE_LTC_X25519) += -DLTC_CURVE25519 +cppflags-lib-$(_CFG_CORE_LTC_ED25519) += -DLTC_CURVE25519 + +cppflags-lib-y += -DLTC_NO_PRNGS -DLTC_FORTUNA + +cflags-lib-$(_CFG_CORE_LTC_SIZE_OPTIMIZATION) += -Os + +subdirs-y += src + +srcs-$(_CFG_CORE_LTC_HASH) += hash.c +srcs-$(_CFG_CORE_LTC_HMAC) += hmac.c +srcs-$(_CFG_CORE_LTC_CMAC) += cmac.c +srcs-$(_CFG_CORE_LTC_ECB) += ecb.c +srcs-$(_CFG_CORE_LTC_CBC) += cbc.c +srcs-$(_CFG_CORE_LTC_CTR) += ctr.c +srcs-$(_CFG_CORE_LTC_XTS) += xts.c +srcs-$(_CFG_CORE_LTC_CCM) += ccm.c +srcs-$(_CFG_CORE_LTC_GCM) += gcm.c +srcs-$(_CFG_CORE_LTC_DSA) += dsa.c +srcs-$(_CFG_CORE_LTC_ECC) += ecc.c +srcs-$(_CFG_CORE_LTC_RSA) += rsa.c +srcs-$(_CFG_CORE_LTC_DH) += dh.c +srcs-$(_CFG_CORE_LTC_AES) += aes.c +srcs-$(_CFG_CORE_LTC_AES_ACCEL) += aes_accel.c +srcs-$(_CFG_CORE_LTC_SHA1_ACCEL) += sha1_accel.c +ifeq ($(_CFG_CORE_LTC_SHA256_DESC),y) +srcs-$(_CFG_CORE_LTC_SHA256_ACCEL) += sha256_accel.c +endif +ifeq ($(_CFG_CORE_LTC_SHA512_DESC),y) +srcs-$(_CFG_CORE_LTC_SHA512_ACCEL) += sha512_accel.c +endif +ifeq ($(_CFG_CORE_LTC_SHA3_DESC),y) +srcs-y += shake.c +srcs-$(_CFG_CORE_LTC_SHA3_ACCEL) += sha3_accel.c +endif +srcs-$(_CFG_CORE_LTC_SM2_DSA) += sm2-dsa.c +srcs-$(_CFG_CORE_LTC_SM2_PKE) += sm2-pke.c +srcs-$(_CFG_CORE_LTC_SM2_KEP) += sm2-kep.c +srcs-$(_CFG_CORE_LTC_X25519) += x25519.c +srcs-$(_CFG_CORE_LTC_ED25519) += ed25519.c +ifeq ($(_CFG_CORE_LTC_ACIPHER),y) +srcs-y += mpi_desc.c +endif + +srcs-y += tomcrypt.c + diff --git a/optee/optee_os/core/lib/libtomcrypt/tomcrypt.c b/optee/optee_os/core/lib/libtomcrypt/tomcrypt.c new file mode 100644 index 0000000..f4779e9 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/tomcrypt.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2023, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include "tomcrypt_mp.h" +#include + +#if defined(_CFG_CORE_LTC_VFP) +#include +#include +#endif + +#if defined(_CFG_CORE_LTC_ACIPHER) || defined(_CFG_CORE_LTC_EC25519) +/* Random generator */ +static int prng_crypto_start(prng_state *prng __unused) +{ + return CRYPT_OK; +} + +static int prng_crypto_add_entropy(const unsigned char *in __unused, + unsigned long inlen __unused, + prng_state *prng __unused) +{ + /* No entropy is required */ + return CRYPT_OK; +} + +static int prng_crypto_ready(prng_state *prng __unused) +{ + return CRYPT_OK; +} + +static unsigned long prng_crypto_read(unsigned char *out, unsigned long outlen, + prng_state *prng __unused) +{ + if (crypto_rng_read(out, outlen)) + return 0; + + return outlen; +} + +static int prng_crypto_done(prng_state *prng __unused) +{ + return CRYPT_OK; +} + +static int prng_crypto_export(unsigned char *out __unused, + unsigned long *outlen __unused, + prng_state *prng __unused) +{ + return CRYPT_OK; +} + +static int prng_crypto_import(const unsigned char *in __unused, + unsigned long inlen __unused, + prng_state *prng __unused) +{ + return CRYPT_OK; +} + +static int prng_crypto_test(void) +{ + return CRYPT_OK; +} + +static const struct ltc_prng_descriptor prng_crypto_desc = { + .name = "prng_crypto", + .export_size = 64, + .start = prng_crypto_start, + .add_entropy = prng_crypto_add_entropy, + .ready = prng_crypto_ready, + .read = prng_crypto_read, + .done = prng_crypto_done, + .pexport = prng_crypto_export, + .pimport = prng_crypto_import, + .test = prng_crypto_test, +}; +#endif /*_CFG_CORE_LTC_ACIPHER*/ + +/* + * tee_ltc_reg_algs(): Registers + * - algorithms + * - hash + * - prng (pseudo random generator) + */ + +static void tee_ltc_reg_algs(void) +{ +#if defined(_CFG_CORE_LTC_AES) || defined(_CFG_CORE_LTC_AES_DESC) + register_cipher(&aes_desc); +#endif +#if defined(_CFG_CORE_LTC_DES) + register_cipher(&des_desc); + register_cipher(&des3_desc); +#endif +#if defined(_CFG_CORE_LTC_MD5) + register_hash(&md5_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA1) + register_hash(&sha1_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA224) + register_hash(&sha224_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA256) || defined(_CFG_CORE_LTC_SHA256_DESC) + register_hash(&sha256_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA384) || defined(_CFG_CORE_LTC_SHA384_DESC) + register_hash(&sha384_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA512) || defined(_CFG_CORE_LTC_SHA512_DESC) + register_hash(&sha512_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA3_224) || defined(_CFG_CORE_LTC_SHA3_224_DESC) + register_hash(&sha3_224_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA3_256) || defined(_CFG_CORE_LTC_SHA3_256_DESC) + register_hash(&sha3_256_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA3_384) || defined(_CFG_CORE_LTC_SHA3_384_DESC) + register_hash(&sha3_384_desc); +#endif +#if defined(_CFG_CORE_LTC_SHA3_512) || defined(_CFG_CORE_LTC_SHA3_512_DESC) + register_hash(&sha3_512_desc); +#endif +#if defined(_CFG_CORE_LTC_ACIPHER) || defined(_CFG_CORE_LTC_EC25519) + register_prng(&prng_crypto_desc); +#endif +} + +static void ltc_init(void) +{ +#if defined(_CFG_CORE_LTC_ACIPHER) + init_mp_tomcrypt(); +#endif + tee_ltc_reg_algs(); +} + +#if defined(CFG_CRYPTOLIB_NAME_tomcrypt) +TEE_Result crypto_init(void) +{ + ltc_init(); + + return TEE_SUCCESS; +} +#else +void tomcrypt_init(void) +{ + ltc_init(); +} +#endif + +#if defined(CFG_WITH_VFP) +void tomcrypt_arm_neon_enable(struct tomcrypt_arm_neon_state *state) +{ + state->state = thread_kernel_enable_vfp(); +} + +void tomcrypt_arm_neon_disable(struct tomcrypt_arm_neon_state *state) +{ + thread_kernel_disable_vfp(state->state); +} +#endif diff --git a/optee/optee_os/core/lib/libtomcrypt/x25519.c b/optee/optee_os/core/lib/libtomcrypt/x25519.c new file mode 100644 index 0000000..bfa16c7 --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/x25519.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Technology Innovation Institute (TII) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "acipher_helpers.h" + +/* X25519 key is an octet string of 32 bytes */ +#define X25519_KEY_SIZE_BYTES UL(32) + +TEE_Result crypto_acipher_alloc_x25519_keypair(struct x25519_keypair *key, + size_t key_size) +{ + size_t key_size_bytes = key_size / 8; + + if (!key) + return TEE_ERROR_BAD_PARAMETERS; + + memset(key, 0, sizeof(*key)); + + if (key_size_bytes != X25519_KEY_SIZE_BYTES) + return TEE_ERROR_BAD_PARAMETERS; + + key->priv = calloc(1, key_size_bytes); + key->pub = calloc(1, key_size_bytes); + + if (!key->priv || !key->pub) { + free(key->priv); + free(key->pub); + return TEE_ERROR_OUT_OF_MEMORY; + } + + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_gen_x25519_key(struct x25519_keypair *key, + size_t key_size) +{ + curve25519_key ltc_tmp_key = { }; + size_t key_size_bytes = key_size / 8; + + if (key_size_bytes != X25519_KEY_SIZE_BYTES) + return TEE_ERROR_BAD_PARAMETERS; + + if (x25519_make_key(NULL, find_prng("prng_crypto"), <c_tmp_key) != + CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + if (key_size_bytes < sizeof(ltc_tmp_key.pub) || + key_size_bytes < sizeof(ltc_tmp_key.priv)) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(key->pub, ltc_tmp_key.pub, sizeof(ltc_tmp_key.pub)); + memcpy(key->priv, ltc_tmp_key.priv, sizeof(ltc_tmp_key.priv)); + memzero_explicit(<c_tmp_key, sizeof(ltc_tmp_key)); + + return TEE_SUCCESS; +} + +TEE_Result crypto_acipher_x25519_shared_secret(struct x25519_keypair + *private_key, + void *public_key, + void *secret, + unsigned long *secret_len) +{ + curve25519_key ltc_private_key = { + .type = PK_PRIVATE, + .algo = LTC_OID_X25519, + }; + curve25519_key ltc_public_key = { + .type = PK_PUBLIC, + .algo = LTC_OID_X25519, + }; + + if (!private_key || !public_key || !secret || !secret_len) + return TEE_ERROR_BAD_PARAMETERS; + + static_assert(sizeof(ltc_public_key.pub) == X25519_KEY_SIZE_BYTES && + sizeof(ltc_public_key.priv) == X25519_KEY_SIZE_BYTES); + + memcpy(ltc_public_key.pub, public_key, X25519_KEY_SIZE_BYTES); + memcpy(ltc_private_key.priv, private_key->priv, X25519_KEY_SIZE_BYTES); + + if (x25519_shared_secret(<c_private_key, <c_public_key, + secret, secret_len) != CRYPT_OK) + return TEE_ERROR_BAD_PARAMETERS; + + /* Clear private key from the stack */ + memzero_explicit(<c_private_key, sizeof(ltc_private_key)); + + /* + * RFC 7748, sec 6.1, check for all zero shared secret output to reject + * input points of low order. + */ + if (*secret_len != X25519_KEY_SIZE_BYTES || + !consttime_memcmp(secret, ltc_private_key.pub, + X25519_KEY_SIZE_BYTES)) + return TEE_ERROR_SECURITY; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/lib/libtomcrypt/xts.c b/optee/optee_os/core/lib/libtomcrypt/xts.c new file mode 100644 index 0000000..cd65d6c --- /dev/null +++ b/optee/optee_os/core/lib/libtomcrypt/xts.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ltc_xts_ctx { + struct crypto_cipher_ctx ctx; + int cipher_idx; + int (*update)(const unsigned char *src, unsigned long len, + unsigned char *dst, unsigned char *tweak, + const symmetric_xts *xts); + symmetric_xts state; + uint8_t tweak[TEE_AES_BLOCK_SIZE]; +}; + +static const struct crypto_cipher_ops ltc_xts_ops; + +static struct ltc_xts_ctx *to_xts_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == <c_xts_ops); + + return container_of(ctx, struct ltc_xts_ctx, ctx); +} + +static TEE_Result ltc_xts_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct ltc_xts_ctx *c = to_xts_ctx(ctx); + + if (key1_len != key2_len) + return TEE_ERROR_BAD_PARAMETERS; + if (iv) { + if (iv_len != sizeof(c->tweak)) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(c->tweak, iv, sizeof(c->tweak)); + } else { + memset(c->tweak, 0, sizeof(c->tweak)); + } + + if ((int)iv_len != cipher_descriptor[c->cipher_idx]->block_length) + return TEE_ERROR_BAD_PARAMETERS; + + if (mode == TEE_MODE_ENCRYPT) + c->update = xts_encrypt; + else + c->update = xts_decrypt; + + + if (xts_start(c->cipher_idx, key1, key2, key1_len, 0, + &c->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static TEE_Result ltc_xts_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, uint8_t *dst) +{ + struct ltc_xts_ctx *c = to_xts_ctx(ctx); + + if (c->update && c->update(data, len, dst, c->tweak, + &c->state) == CRYPT_OK) + return TEE_SUCCESS; + else + return TEE_ERROR_BAD_STATE; +} + +static void ltc_xts_final(struct crypto_cipher_ctx *ctx) +{ + xts_done(&to_xts_ctx(ctx)->state); +} + +static void ltc_xts_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_xts_ctx(ctx)); +} + +static void ltc_xts_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct ltc_xts_ctx *src = to_xts_ctx(src_ctx); + struct ltc_xts_ctx *dst = to_xts_ctx(dst_ctx); + + assert(src->cipher_idx == dst->cipher_idx); + dst->update = src->update; + memcpy(dst->tweak, src->tweak, sizeof(src->tweak)); + dst->state = src->state; +} + +static const struct crypto_cipher_ops ltc_xts_ops = { + .init = ltc_xts_init, + .update = ltc_xts_update, + .final = ltc_xts_final, + .free_ctx = ltc_xts_free_ctx, + .copy_state = ltc_xts_copy_state, +}; + +TEE_Result crypto_aes_xts_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct ltc_xts_ctx *c = NULL; + int cipher_idx = find_cipher("aes"); + + if (cipher_idx < 0) + return TEE_ERROR_NOT_SUPPORTED; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = <c_xts_ops; + c->cipher_idx = cipher_idx; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/lib/scmi-server/conf-optee-fvp.mk b/optee/optee_os/core/lib/scmi-server/conf-optee-fvp.mk new file mode 100644 index 0000000..79b3259 --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/conf-optee-fvp.mk @@ -0,0 +1,22 @@ +$(call force,CFG_SCPFW_MOD_CLOCK,y) +$(call force,CFG_SCPFW_MOD_DVFS,y) +$(call force,CFG_SCPFW_MOD_MSG_SMT,y) +$(call force,CFG_SCPFW_MOD_MOCK_CLOCK,y) +$(call force,CFG_SCPFW_MOD_MOCK_PPU,y) +$(call force,CFG_SCPFW_MOD_MOCK_PSU,y) +$(call force,CFG_SCPFW_MOD_OPTEE_MBX,y) +$(call force,CFG_SCPFW_MOD_POWER_DOMAIN,y) +$(call force,CFG_SCPFW_MOD_PSU,y) +$(call force,CFG_SCPFW_MOD_REG_SENSOR,y) +$(call force,CFG_SCPFW_MOD_SCMI,y) +$(call force,CFG_SCPFW_MOD_SCMI_CLOCK,y) +$(call force,CFG_SCPFW_MOD_SCMI_PERF,y) +$(call force,CFG_SCPFW_MOD_SCMI_POWER_DOMAIN,y) +$(call force,CFG_SCPFW_MOD_SCMI_SENSOR,y) +$(call force,CFG_SCPFW_MOD_SYSTEM_PLL,y) +$(call force,CFG_SCPFW_MOD_SENSOR,y) +$(call force,CFG_SCPFW_MOD_VPLL,y) + +$(call force,CFG_SCPFW_NOTIFICATION,y) +$(call force,CFG_SCPFW_SCMI_SENSOR_EVENTS,y) +$(call force,CFG_SCPFW_FAST_CHANNEL,n) diff --git a/optee/optee_os/core/lib/scmi-server/conf-optee-stm32mp1.mk b/optee/optee_os/core/lib/scmi-server/conf-optee-stm32mp1.mk new file mode 100644 index 0000000..34ae07f --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/conf-optee-stm32mp1.mk @@ -0,0 +1,18 @@ +$(call force,CFG_SCPFW_MOD_RESET_DOMAIN,y) +$(call force,CFG_SCPFW_MOD_CLOCK,y) +$(call force,CFG_SCPFW_MOD_OPTEE_CLOCK,y) +$(call force,CFG_SCPFW_MOD_OPTEE_CONSOLE,y) +$(call force,CFG_SCPFW_MOD_OPTEE_MBX,y) +$(call force,CFG_SCPFW_MOD_OPTEE_RESET,y) +$(call force,CFG_SCPFW_MOD_OPTEE_SMT,y) +$(call force,CFG_SCPFW_MOD_SCMI,y) +$(call force,CFG_SCPFW_MOD_SCMI_CLOCK,y) +$(call force,CFG_SCPFW_MOD_SCMI_RESET_DOMAIN,y) +$(call force,CFG_SCPFW_MOD_SCMI_VOLTAGE_DOMAIN,y) +$(call force,CFG_SCPFW_MOD_VOLTAGE_DOMAIN,y) + +$(call force,CFG_SCPFW_MOD_STM32_PMIC_REGU,$(CFG_STPMIC1)) +$(call force,CFG_SCPFW_MOD_STM32_PWR_REGU,y) + +$(call force,CFG_SCPFW_NOTIFICATION,n) +$(call force,CFG_SCPFW_FAST_CHANNEL,n) diff --git a/optee/optee_os/core/lib/scmi-server/conf.mk b/optee/optee_os/core/lib/scmi-server/conf.mk new file mode 100644 index 0000000..ba49748 --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/conf.mk @@ -0,0 +1,78 @@ +# Configuration switches for SCP-firmware: +# +# CFG_SCMI_SCPFW Boolean switch, embeds SCP-firmware SCMI stack when enabled. +# CFG_SCMI_SCPFW_PRODUCT Name of the SCP-firmware product to build. +# CFG_SCP_FIRMWARE Directory path to SCP-firmware source tree +# CFG_SCPFW_LOG_LEVEL SCP-firmware log level +# CFG_SCPFW_MOD_x Boolean switch, embeds SCP-firmware module x when enabled +# CFG_SCPFW_NOTIFICATION Boolean switch, embeds SCMI notification when enabled. +# CFG_SCPFW_FAST_CHANNELS Boolean switch, embeds SCMI fast channel when enabled. +# +# Boolean y|n switches for module features +# CFG_SCPFW_CLOCK_TREE_MGMT +# CFG_SCPFW_SCMI_PERF_FAST_CHANNELS +# CFG_SCPFW_SCMI_SENSOR_EVENTS +# CFG_SCPFW_SCMI_SENSOR_V2 +# CFG_SCPFW_SENSOR_TIMESTAMP +# CFG_SCPFW_SENSOR_MULTI_AXIS +# CFG_SCPFW_SENSOR_EXT_ATTRIBS +# CFG_SCPFW_SENSOR_SIGNED_VALUE + +include core/lib/scmi-server/conf-$(CFG_SCMI_SCPFW_PRODUCT).mk + +# SCP-fmw log level: 0 trace/verbose, 1 info, 2 warning, 3 error, 4 critical +ifeq ($(CFG_TEE_CORE_LOG_LEVEL),0) +CFG_SCPFW_LOG_LEVEL ?= 3 +else ifeq ($(CFG_TEE_CORE_LOG_LEVEL),1) +CFG_SCPFW_LOG_LEVEL ?= 3 +else ifeq ($(CFG_TEE_CORE_LOG_LEVEL),2) +CFG_SCPFW_LOG_LEVEL ?= 1 +else +CFG_SCPFW_LOG_LEVEL ?= 0 +endif + +CFG_SCPFW_MOD_DVFS ?= n +CFG_SCPFW_MOD_RESET_DOMAIN ?= n +CFG_SCPFW_MOD_CLOCK ?= n +CFG_SCPFW_MOD_MSG_SMT ?= n +CFG_SCPFW_MOD_MOCK_CLOCK ?= n +CFG_SCPFW_MOD_MOCK_PPU ?= n +CFG_SCPFW_MOD_MOCK_PSU ?= n +CFG_SCPFW_MOD_OPTEE_CLOCK ?= n +CFG_SCPFW_MOD_OPTEE_CONSOLE ?= y +CFG_SCPFW_MOD_OPTEE_MBX ?= n +CFG_SCPFW_MOD_OPTEE_RESET ?= n +CFG_SCPFW_MOD_OPTEE_SMT ?= n +CFG_SCPFW_MOD_POWER_DOMAIN ?= n +CFG_SCPFW_MOD_PSU ?= n +CFG_SCPFW_MOD_REG_SENSOR ?= n +CFG_SCPFW_MOD_SENSOR ?= n +CFG_SCPFW_MOD_SCMI ?= y +CFG_SCPFW_MOD_SCMI_APCORE ?= n +CFG_SCPFW_MOD_SCMI_CLOCK ?= n +CFG_SCPFW_MOD_SCMI_PERF ?= n +CFG_SCPFW_MOD_SCMI_POWER_DOMAIN ?= n +CFG_SCPFW_MOD_SCMI_RESET_DOMAIN ?= n +CFG_SCPFW_MOD_SCMI_SENSOR ?= n +CFG_SCPFW_MOD_SCMI_VOLTAGE_DOMAIN ?= n +CFG_SCPFW_MOD_SYSTEM_PLL ?= n +CFG_SCPFW_MOD_VOLTAGE_DOMAIN ?= n + +CFG_SCPFW_NOTIFICATION ?= n +CFG_SCPFW_FAST_CHANNELS ?= n + +CFG_SCPFW_CLOCK_TREE_MGMT ?= n +CFG_SCPFW_SCMI_PERF_FAST_CHANNELS ?= n +CFG_SCPFW_SCMI_SENSOR_EVENTS ?= n +CFG_SCPFW_SCMI_SENSOR_V2 ?= n +CFG_SCPFW_SENSOR_TIMESTAMP ?= n +CFG_SCPFW_SENSOR_MULTI_AXIS ?= n +CFG_SCPFW_SENSOR_EXT_ATTRIBS ?= n +CFG_SCPFW_SENSOR_SIGNED_VALUE ?= n + +ifeq ($(CFG_SCPFW_MOD_OPTEE_SMT),y) +_CFG_SCMI_PTA_SMT_HEADER := y +endif +ifeq ($(CFG_SCPFW_MOD_MSG_SMT),y) +_CFG_SCMI_PTA_MSG_HEADER := y +endif diff --git a/optee/optee_os/core/lib/scmi-server/include/optee_scmi.h b/optee/optee_os/core/lib/scmi-server/include/optee_scmi.h new file mode 100644 index 0000000..a15f1f2 --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/include/optee_scmi.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2022, Linaro Limited + */ +#ifndef OPTEE_SCMI_H +#define OPTEE_SCMI_H + +#include +#include + +/* + * Return virtual address mapped for target SMT IOMEM address range + * + * @pa: Target address range base physical address + * @sz: Target address range byte size + * @shmem_is_secure: True if memory is secure, false otherwise + * Return a virtual address or 0 is memory is not mapped + */ +uintptr_t smt_phys_to_virt(uintptr_t pa, size_t sz, bool shmem_is_secure); + +#endif /* OPTEE_SCMI_H */ diff --git a/optee/optee_os/core/lib/scmi-server/scmi_server.c b/optee/optee_os/core/lib/scmi-server/scmi_server.c new file mode 100644 index 0000000..f0bb256 --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/scmi_server.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * OP-TEE helper function exported to SCP-firmware + */ +uintptr_t smt_phys_to_virt(uintptr_t pa, size_t sz, bool shmem_is_secure) +{ + if (shmem_is_secure) + return (uintptr_t)phys_to_virt(pa, MEM_AREA_IO_SEC, sz); + else + return (uintptr_t)phys_to_virt(pa, MEM_AREA_IO_NSEC, sz); +} + +/* + * SCMI server APIs exported to OP-TEE core + */ +int scmi_server_get_channels_count(void) +{ + return scmi_get_devices_count(); +} + +TEE_Result scmi_server_get_channel(unsigned int channel_id, int *handle) +{ + int fwk_id = 0; + + fwk_id = scmi_get_device(channel_id); + if (fwk_id < 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (handle) + *handle = fwk_id; + + return TEE_SUCCESS; +} + +TEE_Result scmi_server_smt_process_thread(unsigned int channel_id) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int fwk_id = 0; + + res = scmi_server_get_channel(channel_id, &fwk_id); + if (!res) + scmi_process_mbx_smt(fwk_id); + + return res; +} + +TEE_Result scmi_server_msg_process_thread(unsigned int channel_id, + void *in_buf, size_t in_sz, + void *out_buf, size_t *out_sz) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int fwk_id = 0; + + res = scmi_server_get_channel(channel_id, &fwk_id); + if (!res) + scmi_process_mbx_msg(fwk_id, in_buf, in_sz, out_buf, out_sz); + + return res; +} + +static TEE_Result scmi_server_initialize(void) +{ + int rc = 0; + + rc = scmi_arch_init(); + if (rc < 0) { + EMSG("SCMI server init failed: %d", rc); + panic(); + } + + return TEE_SUCCESS; +} + +boot_final(scmi_server_initialize); diff --git a/optee/optee_os/core/lib/scmi-server/sub-optee-fvp.mk b/optee/optee_os/core/lib/scmi-server/sub-optee-fvp.mk new file mode 100644 index 0000000..6600a61 --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/sub-optee-fvp.mk @@ -0,0 +1,17 @@ +incdirs_ext-y += $(scpfw-path)/product/optee-fvp/fw +incdirs_ext-y += $(scpfw-path)/product/optee-fvp/include + +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_clock.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_dvfs.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_mbx_smt.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_mock_clock.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_mock_ppu.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_mock_psu.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_power_domain.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_psu.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_scmi.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_scmi_clock.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_scmi_perf.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_scmi_power_domain.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_sensor.c +srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_vpll.c diff --git a/optee/optee_os/core/lib/scmi-server/sub-optee-stm32mp1.mk b/optee/optee_os/core/lib/scmi-server/sub-optee-stm32mp1.mk new file mode 100644 index 0000000..b0cddd6 --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/sub-optee-stm32mp1.mk @@ -0,0 +1,10 @@ +incdirs_ext-y += $(scpfw-path)/product/optee-stm32mp1/include + +srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_mbx_smt.c +srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_scmi.c +srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_scmi_clocks.c +srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_scmi_reset_domains.c +srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_scmi_voltage_domains.c + +$(eval $(call scpfw-embed-product-module,stm32_pmic_regu)) +$(eval $(call scpfw-embed-product-module,stm32_pwr_regu)) diff --git a/optee/optee_os/core/lib/scmi-server/sub.mk b/optee/optee_os/core/lib/scmi-server/sub.mk new file mode 100644 index 0000000..b9ef74b --- /dev/null +++ b/optee/optee_os/core/lib/scmi-server/sub.mk @@ -0,0 +1,208 @@ +# SCMI server library is built from SCP-firmware source tree. +# The firmware is made of a framework, a product and modules. +# Only modules used by firmware must be built, as stated by +# CFG_SCPFW_MOD_* swtches. SCP-firmware needs a C source and +# a header file to be generated to describe embedded modules. +# This is done through cmake configuration of the package. +# The toolchain build directive must also match the list of +# embedded modules. + +scpfw-path = $(CFG_SCP_FIRMWARE) +scpfw-product = $(CFG_SCMI_SCPFW_PRODUCT) +scpfw-out-path := $(out-dir)/$(libdir) + +# This script was validated against SCP-firmware 2.11.0 development branch, +# from commit f1d894921d76 ("product/optee-fvp: Add new OPTEE FVP product"). +scpfw-integ-version-maj = 2 +scpfw-integ-version-min = 11 +scpfw-integ-version-pat = 0 +scpfw-integ-version = $(scpfw-integ-version-maj).$(scpfw-integ-version-min).$(scpfw-integ-version-pat) + +srcs-y += scmi_server.c +incdirs-y += include + +# SCP-firmware cmake configuration generates header fwk_module_idx.h and +# source files fwk_module_list.c needed for scp-firmware compilation. +scpfw-cmake-flags-y = -DSCP_FIRMWARE_SOURCE_DIR:PATH=$(scpfw-product)/fw \ + -DSCP_LOG_LEVEL="TRACE" \ + -DDISABLE_CPPCHECK=1 \ + -DCFG_NUM_THREADS=$(CFG_NUM_THREADS) \ + -DSCP_OPTEE_DIR:PATH=$(CURDIR) \ + -DCFG_CROSS_COMPILE=$(lastword $(CROSS_COMPILE_core)) + +ifeq ($(cmd-echo-silent),true) +scpfw-cmake-redirect = >/dev/null +endif + +gensrcs-y += fwk_module_list +force-gensrc-fwk_module_list := y +produce-fwk_module_list = build/framework/src/fwk_module_list.c +recipe-fwk_module_list = cmake -S $(scpfw-path) -B $(scpfw-out-path)/build \ + $(scpfw-cmake-flags-y) --log-level=WARNING $(scpfw-cmake-redirect) +depends-fwk_module_list = $(scpfw-path)/product/$(scpfw-product)/fw/Firmware.cmake $(conf-file) +# Include path of generated header file fwk_module_idx.h +incdirs_ext-y += $(scpfw-out-path)/build/framework/include + +cppflags-lib-y += -DBUILD_VERSION_MAJOR=$(scpfw-integ-version-maj) \ + -DBUILD_VERSION_MINOR=$(scpfw-integ-version-min) \ + -DBUILD_VERSION_PATCH=$(scpfw-integ-version-pat) + +scpfw-impl-version := $(shell git -C $(scpfw-path) describe --tags --always --dirty=-dev 2>/dev/null || \ + echo Unknown_$(scpfw-integ-version)) +cppflags-lib-y += -DBUILD_VERSION_DESCRIBE_STRING=\"$(scpfw-impl-version)\" + +cppflags-lib-y += -DFWK_LOG_LEVEL=$(CFG_SCPFW_LOG_LEVEL) +ifneq ($(CFG_SCPFW_LOG_LEVEL),0) +cppflags-lib-y += -DFMW_LOG_MINIMAL_BANNER=1 +endif + +cflags-lib-y += -Wno-cast-align \ + -Wno-nonnull-compare \ + -Wno-unused-parameter \ + -Wno-suggest-attribute=format \ + -Wno-declaration-after-statement + +# The below directives will be removed once SCP-firmware pull requests +# 728 and 732 are merged. +cflags-lib-y += -Wno-undef \ + -Wno-missing-prototypes \ + -Wno-missing-declarations \ + -Wno-unused-but-set-variable \ + -Wno-suggest-attribute=format + +# Notification implementation has strict aliasing issues +cflags-lib-$(CFG_SCPFW_NOTIFICATION) += -Wno-strict-aliasing + +cppflags-lib-y += -DBUILD_HAS_SUB_SYSTEM_MODE=1 \ + -DBUILD_HAS_BASE_PROTOCOL + +cppflags-lib-$(CFG_SCPFW_NOTIFICATION) += -DBUILD_HAS_NOTIFICATION \ + -DBUILD_HAS_SCMI_NOTIFICATIONS + +cppflags-lib-$(CFG_SCPFW_FAST_CHANNELS) += -DBUILD_HAS_FAST_CHANNELS \ + -DBUILD_HAS_SCMI_FAST_CHANNELS + +cppflags-lib-$(CFG_SCPFW_CLOCK_TREE_MGMT) += -DBUILD_HAS_CLOCK_TREE_MGMT + +cppflags-lib-$(CFG_SCPFW_SCMI_PERF_FAST_CHANNELS) += -DBUILD_HAS_SCMI_PERF_FAST_CHANNELS + +cppflags-lib-$(CFG_SCPFW_SCMI_SENSOR_EVENTS) += -DBUILD_HAS_SCMI_SENSOR_EVENTS +cppflags-lib-$(CFG_SCPFW_SCMI_SENSOR_V2) += -DBUILD_HAS_SCMI_SENSOR_V2 \ + -DBUILD_HAS_SENSOR_TIMESTAMP \ + -DBUILD_HAS_SENSOR_MULTI_AXIS \ + -DBUILD_HAS_SENSOR_EXT_ATTRIBS \ + -DBUILD_HAS_SENSOR_SIGNED_VALUE + +cppflags-lib-$(CFG_SCPFW_SENSOR_TIMESTAMP) += -DBUILD_HAS_SENSOR_TIMESTAMP +cppflags-lib-$(CFG_SCPFW_SENSOR_MULTI_AXIS) += -DBUILD_HAS_SENSOR_MULTI_AXI +cppflags-lib-$(CFG_SCPFW_SENSOR_EXT_ATTRIBS) += -DBUILD_HAS_SENSOR_EXT_ATTRIBS +cppflags-lib-$(CFG_SCPFW_SENSOR_SIGNED_VALUE) += -DBUILD_HAS_SENSOR_SIGNED_VALUE +cppflags-lib-$(CFG_SCPFW_INBAND_MSG_SUPPORT) += -DBUILD_HAS_INBAND_MSG_SUPPORT + +incdirs_ext-y += $(scpfw-path)/arch/none/optee/include +srcs-y += $(scpfw-path)/arch/none/optee/src/arch_interrupt.c +srcs-y += $(scpfw-path)/arch/none/optee/src/arch_main.c + +incdirs_ext-y += $(scpfw-path)/framework/include +srcs-y += $(scpfw-path)/framework/src/fwk_arch.c +srcs-y += $(scpfw-path)/framework/src/fwk_dlist.c +srcs-y += $(scpfw-path)/framework/src/fwk_id.c +srcs-y += $(scpfw-path)/framework/src/fwk_interrupt.c +srcs-y += $(scpfw-path)/framework/src/fwk_io.c +srcs-y += $(scpfw-path)/framework/src/fwk_log.c +srcs-y += $(scpfw-path)/framework/src/fwk_mm.c +srcs-y += $(scpfw-path)/framework/src/fwk_module.c +srcs-y += $(scpfw-path)/framework/src/fwk_ring.c +srcs-y += $(scpfw-path)/framework/src/fwk_slist.c +srcs-y += $(scpfw-path)/framework/src/fwk_status.c +srcs-y += $(scpfw-path)/framework/src/fwk_string.c +srcs-y += $(scpfw-path)/framework/src/fwk_delayed_resp.c +srcs-y += $(scpfw-path)/framework/src/fwk_time.c +srcs-y += $(scpfw-path)/framework/src/fwk_core.c +srcs-y += $(scpfw-path)/framework/src/assert.c +srcs-y += $(scpfw-path)/framework/src/stdlib.c +srcs-$(CFG_SCPFW_NOTIFICATION) += $(scpfw-path)/framework/src/fwk_notification.c + +# Helper macros for listing SCP-firmware modules source files (in srcs-y) +# and header include paths (in incdirs_ext-y). Each module provides a C source +# file named mod_.c and possibly an include directory. Build +# directive BUILD_HAS_MOD_ must be set for each embedded module. +# +# Standard modules source tree: /module//src/mod_.c +# Optee modules source tree: /module/optee//src/mod_.c +# Product modules source tree: /product//module//src/mod_.c +# +# scpfw-embed-generic-module is to be used for standard modules. +# scpfw-embed-optee-module is to be used for optee modules. +# scpfw-embed-product-module is to be used for product modules. +# For modules that implement other C source files aside mandatory mod_.c we must +# add to srcs-y the required source file paths. +# +# scpfw-embed-mod takes 4 arguments: +# $1 module name, lowercase +# $2 module directory name +# $3 module parent directory relative path in scpfw tree +# $4 module name, uppercase, relates to CFG_SCPFW_MOD_$4 +define scpfw-embed-mod +ifneq (,$$(wildcard $(scpfw-path)/$3/$2/include/*)) +incdirs_ext-y += $(scpfw-path)/$3/$2/include +endif +srcs-$(CFG_SCPFW_MOD_$4) += $(scpfw-path)/$3/$2/src/mod_$1.c +cflags-lib-$(CFG_SCPFW_MOD_$4) += -DBUILD_HAS_MOD_$4 +endef + +define scpfw-embed-generic-module +$(eval $(call scpfw-embed-mod,$1,$1,module,$(shell echo $1 | tr a-z A-Z))) +endef + +define scpfw-embed-optee-module +$(eval $(call scpfw-embed-mod,optee_$1,$1,module/optee,OPTEE_$(shell echo $1 | tr a-z A-Z))) +endef + +define scpfw-embed-product-module +$(eval $(call scpfw-embed-mod,$1,$1,product/$(scpfw-product)/module,$(shell echo $1 | tr a-z A-Z))) +endef + +$(eval $(call scpfw-embed-generic-module,clock)) +$(eval $(call scpfw-embed-generic-module,dvfs)) +$(eval $(call scpfw-embed-generic-module,mock_clock)) +$(eval $(call scpfw-embed-generic-module,mock_ppu)) +$(eval $(call scpfw-embed-generic-module,mock_psu)) +$(eval $(call scpfw-embed-generic-module,msg_smt)) +$(eval $(call scpfw-embed-generic-module,power_domain)) +$(eval $(call scpfw-embed-generic-module,psu)) +$(eval $(call scpfw-embed-generic-module,reg_sensor)) +$(eval $(call scpfw-embed-generic-module,reset_domain)) +$(eval $(call scpfw-embed-generic-module,sensor)) +$(eval $(call scpfw-embed-generic-module,scmi)) +$(eval $(call scpfw-embed-generic-module,scmi_apcore)) +$(eval $(call scpfw-embed-generic-module,scmi_clock)) +$(eval $(call scpfw-embed-generic-module,scmi_perf)) +$(eval $(call scpfw-embed-generic-module,scmi_power_domain)) +$(eval $(call scpfw-embed-generic-module,scmi_reset_domain)) +$(eval $(call scpfw-embed-generic-module,scmi_sensor)) +$(eval $(call scpfw-embed-generic-module,scmi_voltage_domain)) +$(eval $(call scpfw-embed-generic-module,system_pll)) +$(eval $(call scpfw-embed-generic-module,voltage_domain)) +$(eval $(call scpfw-embed-optee-module,clock)) +$(eval $(call scpfw-embed-optee-module,console)) +$(eval $(call scpfw-embed-optee-module,mbx)) +$(eval $(call scpfw-embed-optee-module,reset)) +$(eval $(call scpfw-embed-optee-module,smt)) + +srcs-$(CFG_SCPFW_MOD_CLOCK) += $(scpfw-path)/module/clock/src/clock_tree_management.c +srcs-$(CFG_SCPFW_MOD_POWER_DOMAIN) += $(scpfw-path)/module/power_domain/src/power_domain_utils.c +srcs-$(CFG_SCPFW_MOD_SCMI) += $(scpfw-path)/module/scmi/src/mod_scmi_base.c +srcs-$(CFG_SCPFW_MOD_SCMI_SENSOR) += $(scpfw-path)/module/scmi_sensor/src/mod_scmi_ext_attrib.c +srcs-$(CFG_SCPFW_MOD_SENSOR) += $(scpfw-path)/module/sensor/src/sensor_extended.c + +# Architecture arch/none/optee requires optee mbx header file +incdirs_ext-y += $(scpfw-path)/module/optee/mbx/include +# Some modules require header files from module that are not embedded +ifneq (,$(filter y, $(CFG_SCPFW_MOD_DVFS) $(CFG_SCPFW_MOD_MOCK_PSU) $(CFG_SCPFW_MOD_SCMI_PERF))) +incdirs_ext-y += $(scpfw-path)/module/timer/include +endif +incdirs_ext-$(CFG_SCPFW_MOD_OPTEE_MBX) += $(scpfw-path)/module/msg_smt/include +incdirs_ext-$(CFG_SCPFW_MOD_SCMI) += $(scpfw-path)/module/power_domain/include + +include core/lib/scmi-server/sub-$(CFG_SCMI_SCPFW_PRODUCT).mk diff --git a/optee/optee_os/core/lib/zlib/adler32.c b/optee/optee_os/core/lib/zlib/adler32.c new file mode 100644 index 0000000..fbaec27 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/adler32.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: Zlib +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + +#define BASE 65521U /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32_z(adler, buf, len) + uLong adler; + const Bytef *buf; + z_size_t len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/optee/optee_os/core/lib/zlib/gzguts.h b/optee/optee_os/core/lib/zlib/gzguts.h new file mode 100644 index 0000000..9c5eb41 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/gzguts.h @@ -0,0 +1,220 @@ +/* SPDX-License-Identifier: Zlib */ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include +#include "zlib.h" +#ifdef STDC +# include +# include +# include +#endif + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif +#include + +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +#endif + +#if defined(_WIN32) +# define WIDECHAR +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif +#endif + +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifndef NO_STRERROR +# include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer (double-sized when writing) */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + int reset; /* true if a reset is pending after a Z_FINISH */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/optee/optee_os/core/lib/zlib/inffast.c b/optee/optee_os/core/lib/zlib/inffast.c new file mode 100644 index 0000000..aa5ea80 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/inffast.c @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: Zlib +/* inffast.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code const *here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - 5); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = lcode + (hold & lmask); + dolen: + op = (unsigned)(here->bits); + hold >>= op; + bits -= op; + op = (unsigned)(here->op); + if (op == 0) { /* literal */ + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here->val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = dcode + (hold & dmask); + dodist: + op = (unsigned)(here->bits); + hold >>= op; + bits -= op; + op = (unsigned)(here->op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here->val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = window; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } while (len > 2); + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode + here->val + (hold & ((1U << op) - 1)); + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode + here->val + (hold & ((1U << op) - 1)); + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/optee/optee_os/core/lib/zlib/inffast.h b/optee/optee_os/core/lib/zlib/inffast.h new file mode 100644 index 0000000..7bace8d --- /dev/null +++ b/optee/optee_os/core/lib/zlib/inffast.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: Zlib */ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/optee/optee_os/core/lib/zlib/inffixed.h b/optee/optee_os/core/lib/zlib/inffixed.h new file mode 100644 index 0000000..d628327 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/optee/optee_os/core/lib/zlib/inflate.c b/optee/optee_os/core/lib/zlib/inflate.c new file mode 100644 index 0000000..c494d06 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/inflate.c @@ -0,0 +1,1593 @@ +// SPDX-License-Identifier: Zlib +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); + +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->flags = -1; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, end, copy) +z_streamp strm; +const Bytef *end; +unsigned copy; +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE_CHECK(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + state->flags = 0; /* indicate zlib header */ + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + /* fallthrough */ + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + /* fallthrough */ + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + /* fallthrough */ + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + /* fallthrough */ + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + /* fallthrough */ + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + /* fallthrough */ + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + /* fallthrough */ + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + /* fallthrough */ + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + /* fallthrough */ + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case COPY_: + state->mode = COPY; + /* fallthrough */ + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + /* fallthrough */ + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + /* fallthrough */ + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + /* fallthrough */ + case LEN_: + state->mode = LEN; + /* fallthrough */ + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + /* fallthrough */ + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + /* fallthrough */ + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + /* fallthrough */ + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + /* fallthrough */ + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE_CHECK(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + /* fallthrough */ + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + /* fallthrough */ + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* fallthrough */ + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE_CHECK(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +const unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + int flags; /* temporary to save header status */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + if (state->flags == -1) + state->wrap = 0; /* if no header yet, treat as raw */ + else + state->wrap &= ~4; /* no point in computing a check value now */ + flags = state->flags; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->flags = flags; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check && state->wrap) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/optee/optee_os/core/lib/zlib/inflate.h b/optee/optee_os/core/lib/zlib/inflate.h new file mode 100644 index 0000000..f912e57 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/inflate.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: Zlib */ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2019 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD = 16180, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ +struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags, 0 if zlib, or + -1 if raw or no header yet */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/optee/optee_os/core/lib/zlib/inftrees.c b/optee/optee_os/core/lib/zlib/inftrees.c new file mode 100644 index 0000000..b1e83e8 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/inftrees.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: Zlib +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2022 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.12 Copyright 1995-2022 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + unsigned match; /* use base and extra for symbol >= match */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + match = 20; + break; + case LENS: + base = lbase; + extra = lext; + match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/optee/optee_os/core/lib/zlib/inftrees.h b/optee/optee_os/core/lib/zlib/inftrees.h new file mode 100644 index 0000000..cb1678d --- /dev/null +++ b/optee/optee_os/core/lib/zlib/inftrees.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: Zlib */ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/optee/optee_os/core/lib/zlib/sub.mk b/optee/optee_os/core/lib/zlib/sub.mk new file mode 100644 index 0000000..d4f225d --- /dev/null +++ b/optee/optee_os/core/lib/zlib/sub.mk @@ -0,0 +1,8 @@ +global-incdirs-y += . +srcs-y += adler32.c +srcs-y += inffast.c +srcs-y += inflate.c +srcs-y += inftrees.c +srcs-y += zutil.c +cflags-remove-y += -Wold-style-definition +cflags-remove-y += -Wswitch-default diff --git a/optee/optee_os/core/lib/zlib/zconf.h b/optee/optee_os/core/lib/zlib/zconf.h new file mode 100644 index 0000000..a7d1374 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/zconf.h @@ -0,0 +1,544 @@ +/* SPDX-License-Identifier: Zlib */ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +#define Z_SOLO +#define ZLIB_CONST +#define NO_GZIP + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +/* Other places expect _LFS64_LARGEFILE to be defined with a valid value */ +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE 0 +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/optee/optee_os/core/lib/zlib/zlib.h b/optee/optee_os/core/lib/zlib/zlib.h new file mode 100644 index 0000000..f0c53df --- /dev/null +++ b/optee/optee_os/core/lib/zlib/zlib.h @@ -0,0 +1,1936 @@ +/* SPDX-License-Identifier: Zlib */ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.12, March 11th, 2022 + + Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.12" +#define ZLIB_VERNUM 0x12c0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 12 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields zalloc, zfree and opaque must be initialized before by the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will *not* automatically decode concatenated gzip members. + inflate() will return Z_STREAM_END at the end of the gzip member. The state + would need to be reset to continue decoding a subsequent gzip member. This + *must* be done if there is more data after a gzip member, in order for the + decompression to be compliant with the gzip standard (RFC 1952). + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Open the gzip (.gz) file at path for reading and decompressing, or + compressing and writing. The mode parameter is as in fopen ("rb" or "wb") + but can also include a compression level ("wb9") or a strategy: 'f' for + filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", + 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression + as in "wb9F". (See the description of deflateInit2 for more information + about the strategy parameter.) 'T' will request transparent writing or + appending with no compression and not using the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + Associate a gzFile with the file descriptor fd. File descriptors are + obtained from calls like open, dup, creat, pipe or fileno (if the file has + been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions for file to + size. The default buffer size is 8192 bytes. This function must be called + after gzopen() or gzdopen(), and before any other calls that read or write + the file. The buffer memory allocation is always deferred to the first read + or write. Three times that size in buffer space is allocated. A larger + buffer size of, for example, 64K or 128K bytes will noticeably increase the + speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level and strategy for file. See the + description of deflateInit2 for the meaning of these parameters. Previously + provided data is flushed before applying the parameter changes. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Read and decompress up to len uncompressed bytes from file into buf. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read and decompress up to nitems items of size size from file into buf, + otherwise operating as gzread() does. This duplicates the interface of + stdio's fread(), with size_t request and return types. If the library + defines size_t, then z_size_t is identical to size_t. If not, then z_size_t + is an unsigned integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); +/* + Compress and write the len uncompressed bytes at buf to file. gzwrite + returns the number of uncompressed bytes written or 0 in case of error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + Compress and write nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Convert, format, compress, and write the arguments (...) to file under + control of the string format, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf(), + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Compress and write the given null-terminated string s to file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Read and decompress bytes from file into buf, until len-1 characters are + read, or until a newline character is read and transferred to buf, or an + end-of-file condition is encountered. If any characters are read or if len + is one, the string is terminated with a null character. If no characters + are read due to an end-of-file or len is less than one, then the buffer is + left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Compress and write c, converted to an unsigned char, into file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Read and decompress one byte from file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push c back onto the stream for file to be read as the first character on + the next read. At least one character of push-back is always allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flush all pending output to file. The parameter flush is as in the + deflate() function. The return value is the zlib error number (see function + gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Set the starting position to offset relative to whence for the next gzread + or gzwrite on file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewind file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Return the starting position for the next gzread or gzwrite on file. + This position represents a number of bytes in the uncompressed data stream, + and is zero when starting, even if appending or reading a gzip stream from + the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Return the current compressed (actual) read or write offset of file. This + offset includes the count of bytes that precede the gzip stream, for example + when appending or when using gzdopen() for reading. When reading, the + offset does not include as yet unused buffered input. This information can + be used for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Return true (1) if the end-of-file indicator for file has been set while + reading, false (0) otherwise. Note that the end-of-file indicator is set + only if the read tried to go past the end of the input, but came up short. + Therefore, just like feof(), gzeof() may return false even if there is no + more data to read, in the event that the last read request was for the exact + number of bytes remaining in the input file. This will happen if the input + file size is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Return true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flush all pending output for file, if necessary, close file and + deallocate the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Return the error message for the last error which occurred on file. + errnum is set to zlib error number. If an error occurred in the file system + and not in the compression library, errnum is set to Z_ERRNO and the + application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clear the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. An Adler-32 value is in the range of a 32-bit + unsigned integer. If buf is Z_NULL, this function returns the required + initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. + If buf is Z_NULL, this function returns the required initial value for the + crc. Pre- and post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); + + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). +*/ + +ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); +/* + Give the same result as crc32_combine(), using op in place of len2. op is + is generated from len2 by crc32_combine_gen(). This will be faster than + crc32_combine() if the generated op is used more than once. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# define z_crc32_combine_gen z_crc32_combine_gen64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# define crc32_combine_gen crc32_combine_gen64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/optee/optee_os/core/lib/zlib/zutil.c b/optee/optee_os/core/lib/zlib/zutil.c new file mode 100644 index 0000000..8466f6d --- /dev/null +++ b/optee/optee_os/core/lib/zlib/zutil.c @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: Zlib +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2017 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif + +z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef ZLIB_DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef ZLIB_DEBUG +#include +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 + /* The older Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf; + ulg bsize = (ulg)items*size; + + (void)opaque; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + + (void)opaque; + + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + (void)opaque; + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + (void)opaque; + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + (void)opaque; + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + (void)opaque; + free(ptr); +} + +#endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/optee/optee_os/core/lib/zlib/zutil.h b/optee/optee_os/core/lib/zlib/zutil.h new file mode 100644 index 0000000..fcf8ef5 --- /dev/null +++ b/optee/optee_os/core/lib/zlib/zutil.h @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: Zlib */ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) +# include +# if (ULONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long +# elif (ULLONG_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned long long +# elif (UINT_MAX == 0xffffffffffffffff) +# define Z_U8 unsigned +# endif +#endif + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 1 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 2 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 7 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef __acorn +# define OS_CODE 13 +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 3 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef ZLIB_DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/optee/optee_os/core/mm/core_mmu.c b/optee/optee_os/core/mm/core_mmu.c new file mode 100644 index 0000000..9206cb8 --- /dev/null +++ b/optee/optee_os/core/mm/core_mmu.c @@ -0,0 +1,2535 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, 2022 Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_WITH_STMM_SP +#include +#endif + +#ifndef DEBUG_XLAT_TABLE +#define DEBUG_XLAT_TABLE 0 +#endif + +#define SHM_VASPACE_SIZE (1024 * 1024 * 32) + +#ifdef CFG_CORE_PHYS_RELOCATABLE +unsigned long core_mmu_tee_load_pa __nex_bss; +#else +const unsigned long core_mmu_tee_load_pa = TEE_LOAD_ADDR; +#endif + +/* + * These variables are initialized before .bss is cleared. To avoid + * resetting them when .bss is cleared we're storing them in .data instead, + * even if they initially are zero. + */ + +#ifdef CFG_CORE_RESERVED_SHM +/* Default NSec shared memory allocated from NSec world */ +unsigned long default_nsec_shm_size __nex_bss; +unsigned long default_nsec_shm_paddr __nex_bss; +#endif + +static struct tee_mmap_region static_memory_map[CFG_MMAP_REGIONS +#if defined(CFG_CORE_ASLR) || defined(CFG_CORE_PHYS_RELOCATABLE) + + 1 +#endif + + 1] __nex_bss; + +/* Define the platform's memory layout. */ +struct memaccess_area { + paddr_t paddr; + size_t size; +}; + +#define MEMACCESS_AREA(a, s) { .paddr = a, .size = s } + +static struct memaccess_area secure_only[] __nex_data = { +#ifdef CFG_CORE_PHYS_RELOCATABLE + MEMACCESS_AREA(0, 0), +#else +#ifdef TRUSTED_SRAM_BASE + MEMACCESS_AREA(TRUSTED_SRAM_BASE, TRUSTED_SRAM_SIZE), +#endif + MEMACCESS_AREA(TRUSTED_DRAM_BASE, TRUSTED_DRAM_SIZE), +#endif +}; + +static struct memaccess_area nsec_shared[] __nex_data = { +#ifdef CFG_CORE_RESERVED_SHM + MEMACCESS_AREA(TEE_SHMEM_START, TEE_SHMEM_SIZE), +#endif +}; + +#if defined(CFG_SECURE_DATA_PATH) +static const char *tz_sdp_match = "linaro,secure-heap"; +static struct memaccess_area sec_sdp; +#ifdef CFG_TEE_SDP_MEM_BASE +register_sdp_mem(CFG_TEE_SDP_MEM_BASE, CFG_TEE_SDP_MEM_SIZE); +#endif +#ifdef TEE_SDP_TEST_MEM_BASE +register_sdp_mem(TEE_SDP_TEST_MEM_BASE, TEE_SDP_TEST_MEM_SIZE); +#endif +#endif + +#ifdef CFG_CORE_RESERVED_SHM +register_phys_mem(MEM_AREA_NSEC_SHM, TEE_SHMEM_START, TEE_SHMEM_SIZE); +#endif +static unsigned int mmu_spinlock; + +static uint32_t mmu_lock(void) +{ + return cpu_spin_lock_xsave(&mmu_spinlock); +} + +static void mmu_unlock(uint32_t exceptions) +{ + cpu_spin_unlock_xrestore(&mmu_spinlock, exceptions); +} + +void core_mmu_get_secure_memory(paddr_t *base, paddr_size_t *size) +{ + /* + * The first range is always used to cover OP-TEE core memory, but + * depending on configuration it may cover more than that. + */ + *base = secure_only[0].paddr; + *size = secure_only[0].size; +} + +#ifdef CFG_CORE_PHYS_RELOCATABLE +void core_mmu_set_secure_memory(paddr_t base, size_t size) +{ + static_assert(ARRAY_SIZE(secure_only) == 1); + assert(!secure_only[0].size); + assert(base && size); + + IMSG("Physical secure memory base %#"PRIxPA" size %#zx", base, size); + secure_only[0].paddr = base; + secure_only[0].size = size; +} +#endif + +void core_mmu_get_ta_range(paddr_t *base, size_t *size) +{ + paddr_t b = 0; + size_t s = 0; + + static_assert(!(TEE_RAM_VA_SIZE % SMALL_PAGE_SIZE)); +#ifdef TA_RAM_START + b = TA_RAM_START; + s = TA_RAM_SIZE; +#else + static_assert(ARRAY_SIZE(secure_only) <= 2); + if (ARRAY_SIZE(secure_only) == 1) { + vaddr_t load_offs = 0; + + assert(core_mmu_tee_load_pa >= secure_only[0].paddr); + load_offs = core_mmu_tee_load_pa - secure_only[0].paddr; + + assert(secure_only[0].size > + load_offs + TEE_RAM_VA_SIZE + TEE_SDP_TEST_MEM_SIZE); + b = secure_only[0].paddr + load_offs + TEE_RAM_VA_SIZE; + s = secure_only[0].size - load_offs - TEE_RAM_VA_SIZE - + TEE_SDP_TEST_MEM_SIZE; + } else { + assert(secure_only[1].size > TEE_SDP_TEST_MEM_SIZE); + b = secure_only[1].paddr; + s = secure_only[1].size - TEE_SDP_TEST_MEM_SIZE; + } +#endif + if (base) + *base = b; + if (size) + *size = s; +} + +static struct tee_mmap_region *get_memory_map(void) +{ + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + struct tee_mmap_region *map = virt_get_memory_map(); + + if (map) + return map; + } + + return static_memory_map; +} + +static bool _pbuf_intersects(struct memaccess_area *a, size_t alen, + paddr_t pa, size_t size) +{ + size_t n; + + for (n = 0; n < alen; n++) + if (core_is_buffer_intersect(pa, size, a[n].paddr, a[n].size)) + return true; + return false; +} + +#define pbuf_intersects(a, pa, size) \ + _pbuf_intersects((a), ARRAY_SIZE(a), (pa), (size)) + +static bool _pbuf_is_inside(struct memaccess_area *a, size_t alen, + paddr_t pa, size_t size) +{ + size_t n; + + for (n = 0; n < alen; n++) + if (core_is_buffer_inside(pa, size, a[n].paddr, a[n].size)) + return true; + return false; +} + +#define pbuf_is_inside(a, pa, size) \ + _pbuf_is_inside((a), ARRAY_SIZE(a), (pa), (size)) + +static bool pa_is_in_map(struct tee_mmap_region *map, paddr_t pa, size_t len) +{ + paddr_t end_pa = 0; + + if (!map) + return false; + + if (SUB_OVERFLOW(len, 1, &end_pa) || ADD_OVERFLOW(pa, end_pa, &end_pa)) + return false; + + return (pa >= map->pa && end_pa <= map->pa + map->size - 1); +} + +static bool va_is_in_map(struct tee_mmap_region *map, vaddr_t va) +{ + if (!map) + return false; + return (va >= map->va && va <= (map->va + map->size - 1)); +} + +/* check if target buffer fits in a core default map area */ +static bool pbuf_inside_map_area(unsigned long p, size_t l, + struct tee_mmap_region *map) +{ + return core_is_buffer_inside(p, l, map->pa, map->size); +} + +static struct tee_mmap_region *find_map_by_type(enum teecore_memtypes type) +{ + struct tee_mmap_region *map; + + for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++) + if (map->type == type) + return map; + return NULL; +} + +static struct tee_mmap_region * +find_map_by_type_and_pa(enum teecore_memtypes type, paddr_t pa, size_t len) +{ + struct tee_mmap_region *map; + + for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++) { + if (map->type != type) + continue; + if (pa_is_in_map(map, pa, len)) + return map; + } + return NULL; +} + +static struct tee_mmap_region *find_map_by_va(void *va) +{ + struct tee_mmap_region *map = get_memory_map(); + unsigned long a = (unsigned long)va; + + while (!core_mmap_is_end_of_table(map)) { + if (a >= map->va && a <= (map->va - 1 + map->size)) + return map; + map++; + } + return NULL; +} + +static struct tee_mmap_region *find_map_by_pa(unsigned long pa) +{ + struct tee_mmap_region *map = get_memory_map(); + + while (!core_mmap_is_end_of_table(map)) { + if (pa >= map->pa && pa <= (map->pa + map->size - 1)) + return map; + map++; + } + return NULL; +} + +#if defined(CFG_SECURE_DATA_PATH) +static bool dtb_get_sdp_region(void) +{ + void *fdt = NULL; + int node = 0; + int tmp_node = 0; + paddr_t tmp_addr = 0; + size_t tmp_size = 0; + + if (!IS_ENABLED(CFG_EMBED_DTB)) + return false; + + fdt = get_embedded_dt(); + if (!fdt) + panic("No DTB found"); + + node = fdt_node_offset_by_compatible(fdt, -1, tz_sdp_match); + if (node < 0) { + DMSG("No %s compatible node found", tz_sdp_match); + return false; + } + tmp_node = node; + while (tmp_node >= 0) { + tmp_node = fdt_node_offset_by_compatible(fdt, tmp_node, + tz_sdp_match); + if (tmp_node >= 0) + DMSG("Ignore SDP pool node %s, supports only 1 node", + fdt_get_name(fdt, tmp_node, NULL)); + } + + tmp_addr = fdt_reg_base_address(fdt, node); + if (tmp_addr == DT_INFO_INVALID_REG) { + EMSG("%s: Unable to get base addr from DT", tz_sdp_match); + return false; + } + + tmp_size = fdt_reg_size(fdt, node); + if (tmp_size == DT_INFO_INVALID_REG_SIZE) { + EMSG("%s: Unable to get size of base addr from DT", + tz_sdp_match); + return false; + } + + sec_sdp.paddr = tmp_addr; + sec_sdp.size = tmp_size; + + return true; +} +#endif + +#if defined(CFG_CORE_DYN_SHM) || defined(CFG_SECURE_DATA_PATH) +static bool pbuf_is_special_mem(paddr_t pbuf, size_t len, + const struct core_mmu_phys_mem *start, + const struct core_mmu_phys_mem *end) +{ + const struct core_mmu_phys_mem *mem; + + for (mem = start; mem < end; mem++) { + if (core_is_buffer_inside(pbuf, len, mem->addr, mem->size)) + return true; + } + + return false; +} +#endif + +#ifdef CFG_CORE_DYN_SHM +static void carve_out_phys_mem(struct core_mmu_phys_mem **mem, size_t *nelems, + paddr_t pa, size_t size) +{ + struct core_mmu_phys_mem *m = *mem; + size_t n = 0; + + while (true) { + if (n >= *nelems) { + DMSG("No need to carve out %#" PRIxPA " size %#zx", + pa, size); + return; + } + if (core_is_buffer_inside(pa, size, m[n].addr, m[n].size)) + break; + if (!core_is_buffer_outside(pa, size, m[n].addr, m[n].size)) + panic(); + n++; + } + + if (pa == m[n].addr && size == m[n].size) { + /* Remove this entry */ + (*nelems)--; + memmove(m + n, m + n + 1, sizeof(*m) * (*nelems - n)); + m = nex_realloc(m, sizeof(*m) * *nelems); + if (!m) + panic(); + *mem = m; + } else if (pa == m[n].addr) { + m[n].addr += size; + m[n].size -= size; + } else if ((pa + size) == (m[n].addr + m[n].size)) { + m[n].size -= size; + } else { + /* Need to split the memory entry */ + m = nex_realloc(m, sizeof(*m) * (*nelems + 1)); + if (!m) + panic(); + *mem = m; + memmove(m + n + 1, m + n, sizeof(*m) * (*nelems - n)); + (*nelems)++; + m[n].size = pa - m[n].addr; + m[n + 1].size -= size + m[n].size; + m[n + 1].addr = pa + size; + } +} + +static void check_phys_mem_is_outside(struct core_mmu_phys_mem *start, + size_t nelems, + struct tee_mmap_region *map) +{ + size_t n; + + for (n = 0; n < nelems; n++) { + if (!core_is_buffer_outside(start[n].addr, start[n].size, + map->pa, map->size)) { + EMSG("Non-sec mem (%#" PRIxPA ":%#" PRIxPASZ + ") overlaps map (type %d %#" PRIxPA ":%#zx)", + start[n].addr, start[n].size, + map->type, map->pa, map->size); + panic(); + } + } +} + +static const struct core_mmu_phys_mem *discovered_nsec_ddr_start __nex_bss; +static size_t discovered_nsec_ddr_nelems __nex_bss; + +static int cmp_pmem_by_addr(const void *a, const void *b) +{ + const struct core_mmu_phys_mem *pmem_a = a; + const struct core_mmu_phys_mem *pmem_b = b; + + return CMP_TRILEAN(pmem_a->addr, pmem_b->addr); +} + +void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start, + size_t nelems) +{ + struct core_mmu_phys_mem *m = start; + size_t num_elems = nelems; + struct tee_mmap_region *map = static_memory_map; + const struct core_mmu_phys_mem __maybe_unused *pmem; + size_t n = 0; + + assert(!discovered_nsec_ddr_start); + assert(m && num_elems); + + qsort(m, num_elems, sizeof(*m), cmp_pmem_by_addr); + + /* + * Non-secure shared memory and also secure data + * path memory are supposed to reside inside + * non-secure memory. Since NSEC_SHM and SDP_MEM + * are used for a specific purpose make holes for + * those memory in the normal non-secure memory. + * + * This has to be done since for instance QEMU + * isn't aware of which memory range in the + * non-secure memory is used for NSEC_SHM. + */ + +#ifdef CFG_SECURE_DATA_PATH + if (dtb_get_sdp_region()) + carve_out_phys_mem(&m, &num_elems, sec_sdp.paddr, sec_sdp.size); + + for (pmem = phys_sdp_mem_begin; pmem < phys_sdp_mem_end; pmem++) + carve_out_phys_mem(&m, &num_elems, pmem->addr, pmem->size); +#endif + + for (n = 0; n < ARRAY_SIZE(secure_only); n++) + carve_out_phys_mem(&m, &num_elems, secure_only[n].paddr, + secure_only[n].size); + + for (map = static_memory_map; !core_mmap_is_end_of_table(map); map++) { + switch (map->type) { + case MEM_AREA_NSEC_SHM: + carve_out_phys_mem(&m, &num_elems, map->pa, map->size); + break; + case MEM_AREA_EXT_DT: + case MEM_AREA_RES_VASPACE: + case MEM_AREA_SHM_VASPACE: + case MEM_AREA_TS_VASPACE: + case MEM_AREA_PAGER_VASPACE: + break; + default: + check_phys_mem_is_outside(m, num_elems, map); + } + } + + discovered_nsec_ddr_start = m; + discovered_nsec_ddr_nelems = num_elems; + + if (!core_mmu_check_end_pa(m[num_elems - 1].addr, + m[num_elems - 1].size)) + panic(); +} + +static bool get_discovered_nsec_ddr(const struct core_mmu_phys_mem **start, + const struct core_mmu_phys_mem **end) +{ + if (!discovered_nsec_ddr_start) + return false; + + *start = discovered_nsec_ddr_start; + *end = discovered_nsec_ddr_start + discovered_nsec_ddr_nelems; + + return true; +} + +static bool pbuf_is_nsec_ddr(paddr_t pbuf, size_t len) +{ + const struct core_mmu_phys_mem *start; + const struct core_mmu_phys_mem *end; + + if (!get_discovered_nsec_ddr(&start, &end)) + return false; + + return pbuf_is_special_mem(pbuf, len, start, end); +} + +bool core_mmu_nsec_ddr_is_defined(void) +{ + const struct core_mmu_phys_mem *start; + const struct core_mmu_phys_mem *end; + + if (!get_discovered_nsec_ddr(&start, &end)) + return false; + + return start != end; +} +#else +static bool pbuf_is_nsec_ddr(paddr_t pbuf __unused, size_t len __unused) +{ + return false; +} +#endif /*CFG_CORE_DYN_SHM*/ + +#define MSG_MEM_INSTERSECT(pa1, sz1, pa2, sz2) \ + EMSG("[%" PRIxPA " %" PRIx64 "] intersects [%" PRIxPA " %" PRIx64 "]", \ + pa1, (uint64_t)pa1 + (sz1), pa2, (uint64_t)pa2 + (sz2)) + +#ifdef CFG_SECURE_DATA_PATH +static bool pbuf_is_sdp_mem(paddr_t pbuf, size_t len) +{ + bool is_sdp_mem = false; + + if (sec_sdp.size) + is_sdp_mem = core_is_buffer_inside(pbuf, len, sec_sdp.paddr, + sec_sdp.size); + + if (!is_sdp_mem) + is_sdp_mem = pbuf_is_special_mem(pbuf, len, phys_sdp_mem_begin, + phys_sdp_mem_end); + + return is_sdp_mem; +} + +static struct mobj *core_sdp_mem_alloc_mobj(paddr_t pa, size_t size) +{ + struct mobj *mobj = mobj_phys_alloc(pa, size, TEE_MATTR_MEM_TYPE_CACHED, + CORE_MEM_SDP_MEM); + + if (!mobj) + panic("can't create SDP physical memory object"); + + return mobj; +} + +struct mobj **core_sdp_mem_create_mobjs(void) +{ + const struct core_mmu_phys_mem *mem = NULL; + struct mobj **mobj_base = NULL; + struct mobj **mobj = NULL; + int cnt = phys_sdp_mem_end - phys_sdp_mem_begin; + + if (sec_sdp.size) + cnt++; + + /* SDP mobjs table must end with a NULL entry */ + mobj_base = calloc(cnt + 1, sizeof(struct mobj *)); + if (!mobj_base) + panic("Out of memory"); + + mobj = mobj_base; + + for (mem = phys_sdp_mem_begin; mem < phys_sdp_mem_end; mem++, mobj++) + *mobj = core_sdp_mem_alloc_mobj(mem->addr, mem->size); + + if (sec_sdp.size) + *mobj = core_sdp_mem_alloc_mobj(sec_sdp.paddr, sec_sdp.size); + + return mobj_base; +} + +#else /* CFG_SECURE_DATA_PATH */ +static bool pbuf_is_sdp_mem(paddr_t pbuf __unused, size_t len __unused) +{ + return false; +} + +#endif /* CFG_SECURE_DATA_PATH */ + +/* Check special memories comply with registered memories */ +static void verify_special_mem_areas(struct tee_mmap_region *mem_map, + size_t len, + const struct core_mmu_phys_mem *start, + const struct core_mmu_phys_mem *end, + const char *area_name __maybe_unused) +{ + const struct core_mmu_phys_mem *mem; + const struct core_mmu_phys_mem *mem2; + struct tee_mmap_region *mmap; + size_t n; + + if (start == end) { + DMSG("No %s memory area defined", area_name); + return; + } + + for (mem = start; mem < end; mem++) + DMSG("%s memory [%" PRIxPA " %" PRIx64 "]", + area_name, mem->addr, (uint64_t)mem->addr + mem->size); + + /* Check memories do not intersect each other */ + for (mem = start; mem + 1 < end; mem++) { + for (mem2 = mem + 1; mem2 < end; mem2++) { + if (core_is_buffer_intersect(mem2->addr, mem2->size, + mem->addr, mem->size)) { + MSG_MEM_INSTERSECT(mem2->addr, mem2->size, + mem->addr, mem->size); + panic("Special memory intersection"); + } + } + } + + /* + * Check memories do not intersect any mapped memory. + * This is called before reserved VA space is loaded in mem_map. + */ + for (mem = start; mem < end; mem++) { + for (mmap = mem_map, n = 0; n < len; mmap++, n++) { + if (core_is_buffer_intersect(mem->addr, mem->size, + mmap->pa, mmap->size)) { + MSG_MEM_INSTERSECT(mem->addr, mem->size, + mmap->pa, mmap->size); + panic("Special memory intersection"); + } + } + } +} + +static void add_phys_mem(struct tee_mmap_region *memory_map, size_t num_elems, + const char *mem_name __maybe_unused, + enum teecore_memtypes mem_type, + paddr_t mem_addr, paddr_size_t mem_size, size_t *last) +{ + size_t n = 0; + paddr_t pa; + paddr_size_t size; + + if (!mem_size) /* Discard null size entries */ + return; + /* + * If some ranges of memory of the same type do overlap + * each others they are coalesced into one entry. To help this + * added entries are sorted by increasing physical. + * + * Note that it's valid to have the same physical memory as several + * different memory types, for instance the same device memory + * mapped as both secure and non-secure. This will probably not + * happen often in practice. + */ + DMSG("%s type %s 0x%08" PRIxPA " size 0x%08" PRIxPASZ, + mem_name, teecore_memtype_name(mem_type), mem_addr, mem_size); + while (true) { + if (n >= (num_elems - 1)) { + EMSG("Out of entries (%zu) in memory_map", num_elems); + panic(); + } + if (n == *last) + break; + pa = memory_map[n].pa; + size = memory_map[n].size; + if (mem_type == memory_map[n].type && + ((pa <= (mem_addr + (mem_size - 1))) && + (mem_addr <= (pa + (size - 1))))) { + DMSG("Physical mem map overlaps 0x%" PRIxPA, mem_addr); + memory_map[n].pa = MIN(pa, mem_addr); + memory_map[n].size = MAX(size, mem_size) + + (pa - memory_map[n].pa); + return; + } + if (mem_type < memory_map[n].type || + (mem_type == memory_map[n].type && mem_addr < pa)) + break; /* found the spot where to insert this memory */ + n++; + } + + memmove(memory_map + n + 1, memory_map + n, + sizeof(struct tee_mmap_region) * (*last - n)); + (*last)++; + memset(memory_map + n, 0, sizeof(memory_map[0])); + memory_map[n].type = mem_type; + memory_map[n].pa = mem_addr; + memory_map[n].size = mem_size; +} + +static void add_va_space(struct tee_mmap_region *memory_map, size_t num_elems, + enum teecore_memtypes type, size_t size, size_t *last) +{ + size_t n = 0; + + DMSG("type %s size 0x%08zx", teecore_memtype_name(type), size); + while (true) { + if (n >= (num_elems - 1)) { + EMSG("Out of entries (%zu) in memory_map", num_elems); + panic(); + } + if (n == *last) + break; + if (type < memory_map[n].type) + break; + n++; + } + + memmove(memory_map + n + 1, memory_map + n, + sizeof(struct tee_mmap_region) * (*last - n)); + (*last)++; + memset(memory_map + n, 0, sizeof(memory_map[0])); + memory_map[n].type = type; + memory_map[n].size = size; +} + +uint32_t core_mmu_type_to_attr(enum teecore_memtypes t) +{ + const uint32_t attr = TEE_MATTR_VALID_BLOCK; + const uint32_t tagged = TEE_MATTR_MEM_TYPE_TAGGED << + TEE_MATTR_MEM_TYPE_SHIFT; + const uint32_t cached = TEE_MATTR_MEM_TYPE_CACHED << + TEE_MATTR_MEM_TYPE_SHIFT; + const uint32_t noncache = TEE_MATTR_MEM_TYPE_DEV << + TEE_MATTR_MEM_TYPE_SHIFT; + + switch (t) { + case MEM_AREA_TEE_RAM: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRWX | tagged; + case MEM_AREA_TEE_RAM_RX: + case MEM_AREA_INIT_RAM_RX: + case MEM_AREA_IDENTITY_MAP_RX: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRX | tagged; + case MEM_AREA_TEE_RAM_RO: + case MEM_AREA_INIT_RAM_RO: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | tagged; + case MEM_AREA_TEE_RAM_RW: + case MEM_AREA_NEX_RAM_RO: /* This has to be r/w during init runtime */ + case MEM_AREA_NEX_RAM_RW: + case MEM_AREA_TEE_ASAN: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | tagged; + case MEM_AREA_TEE_COHERENT: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRWX | noncache; + case MEM_AREA_TA_RAM: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | tagged; + case MEM_AREA_NSEC_SHM: + return attr | TEE_MATTR_PRW | cached; + case MEM_AREA_EXT_DT: + /* + * If CFG_MAP_EXT_DT_SECURE is enabled map the external device + * tree as secure non-cached memory, otherwise, fall back to + * non-secure mapping. + */ + if (IS_ENABLED(CFG_MAP_EXT_DT_SECURE)) + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | + noncache; + fallthrough; + case MEM_AREA_IO_NSEC: + return attr | TEE_MATTR_PRW | noncache; + case MEM_AREA_IO_SEC: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | noncache; + case MEM_AREA_RAM_NSEC: + return attr | TEE_MATTR_PRW | cached; + case MEM_AREA_RAM_SEC: + case MEM_AREA_SEC_RAM_OVERALL: + return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached; + case MEM_AREA_RES_VASPACE: + case MEM_AREA_SHM_VASPACE: + return 0; + case MEM_AREA_PAGER_VASPACE: + return TEE_MATTR_SECURE; + default: + panic("invalid type"); + } +} + +static bool __maybe_unused map_is_tee_ram(const struct tee_mmap_region *mm) +{ + switch (mm->type) { + case MEM_AREA_TEE_RAM: + case MEM_AREA_TEE_RAM_RX: + case MEM_AREA_TEE_RAM_RO: + case MEM_AREA_TEE_RAM_RW: + case MEM_AREA_INIT_RAM_RX: + case MEM_AREA_INIT_RAM_RO: + case MEM_AREA_NEX_RAM_RW: + case MEM_AREA_NEX_RAM_RO: + case MEM_AREA_TEE_ASAN: + return true; + default: + return false; + } +} + +static bool __maybe_unused map_is_secure(const struct tee_mmap_region *mm) +{ + return !!(core_mmu_type_to_attr(mm->type) & TEE_MATTR_SECURE); +} + +static bool __maybe_unused map_is_pgdir(const struct tee_mmap_region *mm) +{ + return mm->region_size == CORE_MMU_PGDIR_SIZE; +} + +static int cmp_mmap_by_lower_va(const void *a, const void *b) +{ + const struct tee_mmap_region *mm_a = a; + const struct tee_mmap_region *mm_b = b; + + return CMP_TRILEAN(mm_a->va, mm_b->va); +} + +static void dump_mmap_table(struct tee_mmap_region *memory_map) +{ + struct tee_mmap_region *map; + + for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { + vaddr_t __maybe_unused vstart; + + vstart = map->va + ((vaddr_t)map->pa & (map->region_size - 1)); + DMSG("type %-12s va 0x%08" PRIxVA "..0x%08" PRIxVA + " pa 0x%08" PRIxPA "..0x%08" PRIxPA " size 0x%08zx (%s)", + teecore_memtype_name(map->type), vstart, + vstart + map->size - 1, map->pa, + (paddr_t)(map->pa + map->size - 1), map->size, + map->region_size == SMALL_PAGE_SIZE ? "smallpg" : "pgdir"); + } +} + +#if DEBUG_XLAT_TABLE + +static void dump_xlat_table(vaddr_t va, unsigned int level) +{ + struct core_mmu_table_info tbl_info; + unsigned int idx = 0; + paddr_t pa; + uint32_t attr; + + core_mmu_find_table(NULL, va, level, &tbl_info); + va = tbl_info.va_base; + for (idx = 0; idx < tbl_info.num_entries; idx++) { + core_mmu_get_entry(&tbl_info, idx, &pa, &attr); + if (attr || level > CORE_MMU_BASE_TABLE_LEVEL) { + const char *security_bit = ""; + + if (core_mmu_entry_have_security_bit(attr)) { + if (attr & TEE_MATTR_SECURE) + security_bit = "S"; + else + security_bit = "NS"; + } + + if (attr & TEE_MATTR_TABLE) { + DMSG_RAW("%*s [LVL%d] VA:0x%010" PRIxVA + " TBL:0x%010" PRIxPA " %s", + level * 2, "", level, va, pa, + security_bit); + dump_xlat_table(va, level + 1); + } else if (attr) { + DMSG_RAW("%*s [LVL%d] VA:0x%010" PRIxVA + " PA:0x%010" PRIxPA " %s-%s-%s-%s", + level * 2, "", level, va, pa, + mattr_is_cached(attr) ? "MEM" : + "DEV", + attr & TEE_MATTR_PW ? "RW" : "RO", + attr & TEE_MATTR_PX ? "X " : "XN", + security_bit); + } else { + DMSG_RAW("%*s [LVL%d] VA:0x%010" PRIxVA + " INVALID\n", + level * 2, "", level, va); + } + } + va += BIT64(tbl_info.shift); + } +} + +#else + +static void dump_xlat_table(vaddr_t va __unused, int level __unused) +{ +} + +#endif + +/* + * Reserves virtual memory space for pager usage. + * + * From the start of the first memory used by the link script + + * TEE_RAM_VA_SIZE should be covered, either with a direct mapping or empty + * mapping for pager usage. This adds translation tables as needed for the + * pager to operate. + */ +static void add_pager_vaspace(struct tee_mmap_region *mmap, size_t num_elems, + size_t *last) +{ + paddr_t begin = 0; + paddr_t end = 0; + size_t size = 0; + size_t pos = 0; + size_t n = 0; + + if (*last >= (num_elems - 1)) { + EMSG("Out of entries (%zu) in memory map", num_elems); + panic(); + } + + for (n = 0; !core_mmap_is_end_of_table(mmap + n); n++) { + if (map_is_tee_ram(mmap + n)) { + if (!begin) + begin = mmap[n].pa; + pos = n + 1; + } + } + + end = mmap[pos - 1].pa + mmap[pos - 1].size; + assert(end - begin < TEE_RAM_VA_SIZE); + size = TEE_RAM_VA_SIZE - (end - begin); + + assert(pos <= *last); + memmove(mmap + pos + 1, mmap + pos, + sizeof(struct tee_mmap_region) * (*last - pos)); + (*last)++; + memset(mmap + pos, 0, sizeof(mmap[0])); + mmap[pos].type = MEM_AREA_PAGER_VASPACE; + mmap[pos].va = 0; + mmap[pos].size = size; + mmap[pos].region_size = SMALL_PAGE_SIZE; + mmap[pos].attr = core_mmu_type_to_attr(MEM_AREA_PAGER_VASPACE); +} + +static void check_sec_nsec_mem_config(void) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(secure_only); n++) { + if (pbuf_intersects(nsec_shared, secure_only[n].paddr, + secure_only[n].size)) + panic("Invalid memory access config: sec/nsec"); + } +} + +static size_t collect_mem_ranges(struct tee_mmap_region *memory_map, + size_t num_elems) +{ + const struct core_mmu_phys_mem *mem = NULL; + vaddr_t ram_start = secure_only[0].paddr; + size_t last = 0; + + +#define ADD_PHYS_MEM(_type, _addr, _size) \ + add_phys_mem(memory_map, num_elems, #_addr, (_type), \ + (_addr), (_size), &last) + + if (IS_ENABLED(CFG_CORE_RWDATA_NOEXEC)) { + ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RO, ram_start, + VCORE_UNPG_RX_PA - ram_start); + ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RX, VCORE_UNPG_RX_PA, + VCORE_UNPG_RX_SZ); + ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RO, VCORE_UNPG_RO_PA, + VCORE_UNPG_RO_SZ); + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + ADD_PHYS_MEM(MEM_AREA_NEX_RAM_RO, VCORE_UNPG_RW_PA, + VCORE_UNPG_RW_SZ); + ADD_PHYS_MEM(MEM_AREA_NEX_RAM_RW, VCORE_NEX_RW_PA, + VCORE_NEX_RW_SZ); + } else { + ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RW, VCORE_UNPG_RW_PA, + VCORE_UNPG_RW_SZ); + } + + if (IS_ENABLED(CFG_WITH_PAGER)) { + ADD_PHYS_MEM(MEM_AREA_INIT_RAM_RX, VCORE_INIT_RX_PA, + VCORE_INIT_RX_SZ); + ADD_PHYS_MEM(MEM_AREA_INIT_RAM_RO, VCORE_INIT_RO_PA, + VCORE_INIT_RO_SZ); + } + } else { + ADD_PHYS_MEM(MEM_AREA_TEE_RAM, TEE_RAM_START, TEE_RAM_PH_SIZE); + } + + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { + ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, TRUSTED_DRAM_BASE, + TRUSTED_DRAM_SIZE); + } else { + /* + * Every guest will have own TA RAM if virtualization + * support is enabled. + */ + paddr_t ta_base = 0; + size_t ta_size = 0; + + core_mmu_get_ta_range(&ta_base, &ta_size); + ADD_PHYS_MEM(MEM_AREA_TA_RAM, ta_base, ta_size); + } + + if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS) && + IS_ENABLED(CFG_WITH_PAGER)) { + /* + * Asan ram is part of MEM_AREA_TEE_RAM_RW when pager is + * disabled. + */ + ADD_PHYS_MEM(MEM_AREA_TEE_ASAN, ASAN_MAP_PA, ASAN_MAP_SZ); + } + +#undef ADD_PHYS_MEM + + for (mem = phys_mem_map_begin; mem < phys_mem_map_end; mem++) { + /* Only unmapped virtual range may have a null phys addr */ + assert(mem->addr || !core_mmu_type_to_attr(mem->type)); + + add_phys_mem(memory_map, num_elems, mem->name, mem->type, + mem->addr, mem->size, &last); + } + + if (IS_ENABLED(CFG_SECURE_DATA_PATH)) + verify_special_mem_areas(memory_map, num_elems, + phys_sdp_mem_begin, + phys_sdp_mem_end, "SDP"); + + add_va_space(memory_map, num_elems, MEM_AREA_RES_VASPACE, + CFG_RESERVED_VASPACE_SIZE, &last); + + add_va_space(memory_map, num_elems, MEM_AREA_SHM_VASPACE, + SHM_VASPACE_SIZE, &last); + + memory_map[last].type = MEM_AREA_END; + + return last; +} + +static void assign_mem_granularity(struct tee_mmap_region *memory_map) +{ + struct tee_mmap_region *map = NULL; + + /* + * Assign region sizes, note that MEM_AREA_TEE_RAM always uses + * SMALL_PAGE_SIZE. + */ + for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { + paddr_t mask = map->pa | map->size; + + if (!(mask & CORE_MMU_PGDIR_MASK)) + map->region_size = CORE_MMU_PGDIR_SIZE; + else if (!(mask & SMALL_PAGE_MASK)) + map->region_size = SMALL_PAGE_SIZE; + else + panic("Impossible memory alignment"); + + if (map_is_tee_ram(map)) + map->region_size = SMALL_PAGE_SIZE; + } +} + +static bool place_tee_ram_at_top(paddr_t paddr) +{ + return paddr > BIT64(core_mmu_get_va_width()) / 2; +} + +/* + * MMU arch driver shall override this function if it helps + * optimizing the memory footprint of the address translation tables. + */ +bool __weak core_mmu_prefer_tee_ram_at_top(paddr_t paddr) +{ + return place_tee_ram_at_top(paddr); +} + +static bool assign_mem_va_dir(vaddr_t tee_ram_va, + struct tee_mmap_region *memory_map, + bool tee_ram_at_top) +{ + struct tee_mmap_region *map = NULL; + vaddr_t va = 0; + bool va_is_secure = true; + + /* + * tee_ram_va might equals 0 when CFG_CORE_ASLR=y. + * 0 is by design an invalid va, so return false directly. + */ + if (!tee_ram_va) + return false; + + /* Clear eventual previous assignments */ + for (map = memory_map; !core_mmap_is_end_of_table(map); map++) + map->va = 0; + + /* + * TEE RAM regions are always aligned with region_size. + * + * Note that MEM_AREA_PAGER_VASPACE also counts as TEE RAM here + * since it handles virtual memory which covers the part of the ELF + * that cannot fit directly into memory. + */ + va = tee_ram_va; + for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { + if (map_is_tee_ram(map) || + map->type == MEM_AREA_PAGER_VASPACE) { + assert(!(va & (map->region_size - 1))); + assert(!(map->size & (map->region_size - 1))); + map->va = va; + if (ADD_OVERFLOW(va, map->size, &va)) + return false; + if (va >= BIT64(core_mmu_get_va_width())) + return false; + } + } + + if (tee_ram_at_top) { + /* + * Map non-tee ram regions at addresses lower than the tee + * ram region. + */ + va = tee_ram_va; + for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { + map->attr = core_mmu_type_to_attr(map->type); + if (map->va) + continue; + + if (!IS_ENABLED(CFG_WITH_LPAE) && + va_is_secure != map_is_secure(map)) { + va_is_secure = !va_is_secure; + va = ROUNDDOWN(va, CORE_MMU_PGDIR_SIZE); + } + + if (SUB_OVERFLOW(va, map->size, &va)) + return false; + va = ROUNDDOWN(va, map->region_size); + /* + * Make sure that va is aligned with pa for + * efficient pgdir mapping. Basically pa & + * pgdir_mask should be == va & pgdir_mask + */ + if (map->size > 2 * CORE_MMU_PGDIR_SIZE) { + if (SUB_OVERFLOW(va, CORE_MMU_PGDIR_SIZE, &va)) + return false; + va += (map->pa - va) & CORE_MMU_PGDIR_MASK; + } + map->va = va; + } + } else { + /* + * Map non-tee ram regions at addresses higher than the tee + * ram region. + */ + for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { + map->attr = core_mmu_type_to_attr(map->type); + if (map->va) + continue; + + if (!IS_ENABLED(CFG_WITH_LPAE) && + va_is_secure != map_is_secure(map)) { + va_is_secure = !va_is_secure; + if (ROUNDUP_OVERFLOW(va, CORE_MMU_PGDIR_SIZE, + &va)) + return false; + } + + if (ROUNDUP_OVERFLOW(va, map->region_size, &va)) + return false; + /* + * Make sure that va is aligned with pa for + * efficient pgdir mapping. Basically pa & + * pgdir_mask should be == va & pgdir_mask + */ + if (map->size > 2 * CORE_MMU_PGDIR_SIZE) { + vaddr_t offs = (map->pa - va) & + CORE_MMU_PGDIR_MASK; + + if (ADD_OVERFLOW(va, offs, &va)) + return false; + } + + map->va = va; + if (ADD_OVERFLOW(va, map->size, &va)) + return false; + if (va >= BIT64(core_mmu_get_va_width())) + return false; + } + } + + return true; +} + +static bool assign_mem_va(vaddr_t tee_ram_va, + struct tee_mmap_region *memory_map) +{ + bool tee_ram_at_top = place_tee_ram_at_top(tee_ram_va); + + /* + * Check that we're not overlapping with the user VA range. + */ + if (IS_ENABLED(CFG_WITH_LPAE)) { + /* + * User VA range is supposed to be defined after these + * mappings have been established. + */ + assert(!core_mmu_user_va_range_is_defined()); + } else { + vaddr_t user_va_base = 0; + size_t user_va_size = 0; + + assert(core_mmu_user_va_range_is_defined()); + core_mmu_get_user_va_range(&user_va_base, &user_va_size); + if (tee_ram_va < (user_va_base + user_va_size)) + return false; + } + + if (IS_ENABLED(CFG_WITH_PAGER)) { + bool prefered_dir = core_mmu_prefer_tee_ram_at_top(tee_ram_va); + + /* Try whole mapping covered by a single base xlat entry */ + if (prefered_dir != tee_ram_at_top && + assign_mem_va_dir(tee_ram_va, memory_map, prefered_dir)) + return true; + } + + return assign_mem_va_dir(tee_ram_va, memory_map, tee_ram_at_top); +} + +static int cmp_init_mem_map(const void *a, const void *b) +{ + const struct tee_mmap_region *mm_a = a; + const struct tee_mmap_region *mm_b = b; + int rc = 0; + + rc = CMP_TRILEAN(mm_a->region_size, mm_b->region_size); + if (!rc) + rc = CMP_TRILEAN(mm_a->pa, mm_b->pa); + /* + * 32bit MMU descriptors cannot mix secure and non-secure mapping in + * the same level2 table. Hence sort secure mapping from non-secure + * mapping. + */ + if (!rc && !IS_ENABLED(CFG_WITH_LPAE)) + rc = CMP_TRILEAN(map_is_secure(mm_a), map_is_secure(mm_b)); + + return rc; +} + +static bool mem_map_add_id_map(struct tee_mmap_region *memory_map, + size_t num_elems, size_t *last, + vaddr_t id_map_start, vaddr_t id_map_end) +{ + struct tee_mmap_region *map = NULL; + vaddr_t start = ROUNDDOWN(id_map_start, SMALL_PAGE_SIZE); + vaddr_t end = ROUNDUP(id_map_end, SMALL_PAGE_SIZE); + size_t len = end - start; + + if (*last >= num_elems - 1) { + EMSG("Out of entries (%zu) in memory map", num_elems); + panic(); + } + + for (map = memory_map; !core_mmap_is_end_of_table(map); map++) + if (core_is_buffer_intersect(map->va, map->size, start, len)) + return false; + + *map = (struct tee_mmap_region){ + .type = MEM_AREA_IDENTITY_MAP_RX, + /* + * Could use CORE_MMU_PGDIR_SIZE to potentially save a + * translation table, at the increased risk of clashes with + * the rest of the memory map. + */ + .region_size = SMALL_PAGE_SIZE, + .pa = start, + .va = start, + .size = len, + .attr = core_mmu_type_to_attr(MEM_AREA_IDENTITY_MAP_RX), + }; + + (*last)++; + + return true; +} + +static unsigned long init_mem_map(struct tee_mmap_region *memory_map, + size_t num_elems, unsigned long seed) +{ + /* + * @id_map_start and @id_map_end describes a physical memory range + * that must be mapped Read-Only eXecutable at identical virtual + * addresses. + */ + vaddr_t id_map_start = (vaddr_t)__identity_map_init_start; + vaddr_t id_map_end = (vaddr_t)__identity_map_init_end; + vaddr_t start_addr = secure_only[0].paddr; + unsigned long offs = 0; + size_t last = 0; + + last = collect_mem_ranges(memory_map, num_elems); + assign_mem_granularity(memory_map); + + /* + * To ease mapping and lower use of xlat tables, sort mapping + * description moving small-page regions after the pgdir regions. + */ + qsort(memory_map, last, sizeof(struct tee_mmap_region), + cmp_init_mem_map); + + if (IS_ENABLED(CFG_WITH_PAGER)) + add_pager_vaspace(memory_map, num_elems, &last); + + if (IS_ENABLED(CFG_CORE_ASLR) && seed) { + vaddr_t base_addr = start_addr + seed; + const unsigned int va_width = core_mmu_get_va_width(); + const vaddr_t va_mask = GENMASK_64(va_width - 1, + SMALL_PAGE_SHIFT); + vaddr_t ba = base_addr; + size_t n = 0; + + for (n = 0; n < 3; n++) { + if (n) + ba = base_addr ^ BIT64(va_width - n); + ba &= va_mask; + if (assign_mem_va(ba, memory_map) && + mem_map_add_id_map(memory_map, num_elems, &last, + id_map_start, id_map_end)) { + offs = ba - start_addr; + DMSG("Mapping core at %#"PRIxVA" offs %#lx", + ba, offs); + goto out; + } else { + DMSG("Failed to map core at %#"PRIxVA, ba); + } + } + EMSG("Failed to map core with seed %#lx", seed); + } + + if (!assign_mem_va(start_addr, memory_map)) + panic(); + +out: + qsort(memory_map, last, sizeof(struct tee_mmap_region), + cmp_mmap_by_lower_va); + + dump_mmap_table(memory_map); + + return offs; +} + +static void check_mem_map(struct tee_mmap_region *map) +{ + struct tee_mmap_region *m = NULL; + + for (m = map; !core_mmap_is_end_of_table(m); m++) { + switch (m->type) { + case MEM_AREA_TEE_RAM: + case MEM_AREA_TEE_RAM_RX: + case MEM_AREA_TEE_RAM_RO: + case MEM_AREA_TEE_RAM_RW: + case MEM_AREA_INIT_RAM_RX: + case MEM_AREA_INIT_RAM_RO: + case MEM_AREA_NEX_RAM_RW: + case MEM_AREA_NEX_RAM_RO: + case MEM_AREA_IDENTITY_MAP_RX: + if (!pbuf_is_inside(secure_only, m->pa, m->size)) + panic("TEE_RAM can't fit in secure_only"); + break; + case MEM_AREA_TA_RAM: + if (!pbuf_is_inside(secure_only, m->pa, m->size)) + panic("TA_RAM can't fit in secure_only"); + break; + case MEM_AREA_NSEC_SHM: + if (!pbuf_is_inside(nsec_shared, m->pa, m->size)) + panic("NS_SHM can't fit in nsec_shared"); + break; + case MEM_AREA_SEC_RAM_OVERALL: + case MEM_AREA_TEE_COHERENT: + case MEM_AREA_TEE_ASAN: + case MEM_AREA_IO_SEC: + case MEM_AREA_IO_NSEC: + case MEM_AREA_EXT_DT: + case MEM_AREA_RAM_SEC: + case MEM_AREA_RAM_NSEC: + case MEM_AREA_RES_VASPACE: + case MEM_AREA_SHM_VASPACE: + case MEM_AREA_PAGER_VASPACE: + break; + default: + EMSG("Uhandled memtype %d", m->type); + panic(); + } + } +} + +static struct tee_mmap_region *get_tmp_mmap(void) +{ + struct tee_mmap_region *tmp_mmap = (void *)__heap1_start; + +#ifdef CFG_WITH_PAGER + if (__heap1_end - __heap1_start < (ptrdiff_t)sizeof(static_memory_map)) + tmp_mmap = (void *)__heap2_start; +#endif + + memset(tmp_mmap, 0, sizeof(static_memory_map)); + + return tmp_mmap; +} + +/* + * core_init_mmu_map() - init tee core default memory mapping + * + * This routine sets the static default TEE core mapping. If @seed is > 0 + * and configured with CFG_CORE_ASLR it will map tee core at a location + * based on the seed and return the offset from the link address. + * + * If an error happened: core_init_mmu_map is expected to panic. + * + * Note: this function is weak just to make it possible to exclude it from + * the unpaged area. + */ +void __weak core_init_mmu_map(unsigned long seed, struct core_mmu_config *cfg) +{ +#ifndef CFG_NS_VIRTUALIZATION + vaddr_t start = ROUNDDOWN((vaddr_t)__nozi_start, SMALL_PAGE_SIZE); +#else + vaddr_t start = ROUNDDOWN((vaddr_t)__vcore_nex_rw_start, + SMALL_PAGE_SIZE); +#endif + vaddr_t len = ROUNDUP((vaddr_t)__nozi_end, SMALL_PAGE_SIZE) - start; + struct tee_mmap_region *tmp_mmap = get_tmp_mmap(); + unsigned long offs = 0; + + if (IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE) && + (core_mmu_tee_load_pa & SMALL_PAGE_MASK)) + panic("OP-TEE load address is not page aligned"); + + check_sec_nsec_mem_config(); + + /* + * Add a entry covering the translation tables which will be + * involved in some virt_to_phys() and phys_to_virt() conversions. + */ + static_memory_map[0] = (struct tee_mmap_region){ + .type = MEM_AREA_TEE_RAM, + .region_size = SMALL_PAGE_SIZE, + .pa = start, + .va = start, + .size = len, + .attr = core_mmu_type_to_attr(MEM_AREA_IDENTITY_MAP_RX), + }; + + COMPILE_TIME_ASSERT(CFG_MMAP_REGIONS >= 13); + offs = init_mem_map(tmp_mmap, ARRAY_SIZE(static_memory_map), seed); + + check_mem_map(tmp_mmap); + core_init_mmu(tmp_mmap); + dump_xlat_table(0x0, CORE_MMU_BASE_TABLE_LEVEL); + core_init_mmu_regs(cfg); + cfg->map_offset = offs; + memcpy(static_memory_map, tmp_mmap, sizeof(static_memory_map)); +} + +bool core_mmu_mattr_is_ok(uint32_t mattr) +{ + /* + * Keep in sync with core_mmu_lpae.c:mattr_to_desc and + * core_mmu_v7.c:mattr_to_texcb + */ + + switch ((mattr >> TEE_MATTR_MEM_TYPE_SHIFT) & TEE_MATTR_MEM_TYPE_MASK) { + case TEE_MATTR_MEM_TYPE_DEV: + case TEE_MATTR_MEM_TYPE_STRONGLY_O: + case TEE_MATTR_MEM_TYPE_CACHED: + case TEE_MATTR_MEM_TYPE_TAGGED: + return true; + default: + return false; + } +} + +/* + * test attributes of target physical buffer + * + * Flags: pbuf_is(SECURE, NOT_SECURE, RAM, IOMEM, KEYVAULT). + * + */ +bool core_pbuf_is(uint32_t attr, paddr_t pbuf, size_t len) +{ + paddr_t ta_base = 0; + size_t ta_size = 0; + struct tee_mmap_region *map; + + /* Empty buffers complies with anything */ + if (len == 0) + return true; + + switch (attr) { + case CORE_MEM_SEC: + return pbuf_is_inside(secure_only, pbuf, len); + case CORE_MEM_NON_SEC: + return pbuf_is_inside(nsec_shared, pbuf, len) || + pbuf_is_nsec_ddr(pbuf, len); + case CORE_MEM_TEE_RAM: + return core_is_buffer_inside(pbuf, len, TEE_RAM_START, + TEE_RAM_PH_SIZE); + case CORE_MEM_TA_RAM: + core_mmu_get_ta_range(&ta_base, &ta_size); + return core_is_buffer_inside(pbuf, len, ta_base, ta_size); +#ifdef CFG_CORE_RESERVED_SHM + case CORE_MEM_NSEC_SHM: + return core_is_buffer_inside(pbuf, len, TEE_SHMEM_START, + TEE_SHMEM_SIZE); +#endif + case CORE_MEM_SDP_MEM: + return pbuf_is_sdp_mem(pbuf, len); + case CORE_MEM_CACHED: + map = find_map_by_pa(pbuf); + if (!map || !pbuf_inside_map_area(pbuf, len, map)) + return false; + return mattr_is_cached(map->attr); +#ifdef CFG_WITH_STMM_SP + case CORE_MEM_DEVICE: + /* CORE_MEM_DEVICE is used by StMM only */ + return stmm_is_device_mem_inside(pbuf, len); +#endif + 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) +{ + paddr_t p; + + /* Empty buffers complies with anything */ + if (len == 0) + return true; + + p = virt_to_phys((void *)vbuf); + if (!p) + return false; + + return core_pbuf_is(attr, p, len); +} + +/* core_va2pa - teecore exported service */ +static int __maybe_unused core_va2pa_helper(void *va, paddr_t *pa) +{ + struct tee_mmap_region *map; + + map = find_map_by_va(va); + if (!va_is_in_map(map, (vaddr_t)va)) + return -1; + + /* + * We can calculate PA for static map. Virtual address ranges + * reserved to core dynamic mapping return a 'match' (return 0;) + * together with an invalid null physical address. + */ + if (map->pa) + *pa = map->pa + (vaddr_t)va - map->va; + else + *pa = 0; + + return 0; +} + +static void *map_pa2va(struct tee_mmap_region *map, paddr_t pa, size_t len) +{ + if (!pa_is_in_map(map, pa, len)) + return NULL; + + return (void *)(vaddr_t)(map->va + pa - map->pa); +} + +/* + * teecore gets some memory area definitions + */ +void core_mmu_get_mem_by_type(unsigned int type, vaddr_t *s, vaddr_t *e) +{ + struct tee_mmap_region *map = find_map_by_type(type); + + if (map) { + *s = map->va; + *e = map->va + map->size; + } else { + *s = 0; + *e = 0; + } +} + +enum teecore_memtypes core_mmu_get_type_by_pa(paddr_t pa) +{ + struct tee_mmap_region *map = find_map_by_pa(pa); + + if (!map) + return MEM_AREA_MAXTYPE; + return map->type; +} + +void core_mmu_set_entry(struct core_mmu_table_info *tbl_info, unsigned int idx, + paddr_t pa, uint32_t attr) +{ + assert(idx < tbl_info->num_entries); + core_mmu_set_entry_primitive(tbl_info->table, tbl_info->level, + idx, pa, attr); +} + +void core_mmu_get_entry(struct core_mmu_table_info *tbl_info, unsigned int idx, + paddr_t *pa, uint32_t *attr) +{ + assert(idx < tbl_info->num_entries); + core_mmu_get_entry_primitive(tbl_info->table, tbl_info->level, + idx, pa, attr); +} + +static void clear_region(struct core_mmu_table_info *tbl_info, + struct tee_mmap_region *region) +{ + unsigned int end = 0; + unsigned int idx = 0; + + /* va, len and pa should be block aligned */ + assert(!core_mmu_get_block_offset(tbl_info, region->va)); + assert(!core_mmu_get_block_offset(tbl_info, region->size)); + assert(!core_mmu_get_block_offset(tbl_info, region->pa)); + + idx = core_mmu_va2idx(tbl_info, region->va); + end = core_mmu_va2idx(tbl_info, region->va + region->size); + + while (idx < end) { + core_mmu_set_entry(tbl_info, idx, 0, 0); + idx++; + } +} + +static void set_region(struct core_mmu_table_info *tbl_info, + struct tee_mmap_region *region) +{ + unsigned int end; + unsigned int idx; + paddr_t pa; + + /* va, len and pa should be block aligned */ + assert(!core_mmu_get_block_offset(tbl_info, region->va)); + assert(!core_mmu_get_block_offset(tbl_info, region->size)); + assert(!core_mmu_get_block_offset(tbl_info, region->pa)); + + idx = core_mmu_va2idx(tbl_info, region->va); + end = core_mmu_va2idx(tbl_info, region->va + region->size); + pa = region->pa; + + while (idx < end) { + core_mmu_set_entry(tbl_info, idx, pa, region->attr); + idx++; + pa += BIT64(tbl_info->shift); + } +} + +static void set_pg_region(struct core_mmu_table_info *dir_info, + struct vm_region *region, struct pgt **pgt, + struct core_mmu_table_info *pg_info) +{ + struct tee_mmap_region r = { + .va = region->va, + .size = region->size, + .attr = region->attr, + }; + vaddr_t end = r.va + r.size; + uint32_t pgt_attr = (r.attr & TEE_MATTR_SECURE) | TEE_MATTR_TABLE; + + while (r.va < end) { + if (!pg_info->table || + r.va >= (pg_info->va_base + CORE_MMU_PGDIR_SIZE)) { + /* + * We're assigning a new translation table. + */ + unsigned int idx; + + /* Virtual addresses must grow */ + assert(r.va > pg_info->va_base); + + idx = core_mmu_va2idx(dir_info, r.va); + pg_info->va_base = core_mmu_idx2va(dir_info, idx); + + /* + * Advance pgt to va_base, note that we may need to + * skip multiple page tables if there are large + * holes in the vm map. + */ + while ((*pgt)->vabase < pg_info->va_base) { + *pgt = SLIST_NEXT(*pgt, link); + /* We should have allocated enough */ + assert(*pgt); + } + assert((*pgt)->vabase == pg_info->va_base); + pg_info->table = (*pgt)->tbl; + + core_mmu_set_entry(dir_info, idx, + virt_to_phys(pg_info->table), + pgt_attr); + } + + r.size = MIN(CORE_MMU_PGDIR_SIZE - (r.va - pg_info->va_base), + end - r.va); + + if (!(*pgt)->populated && !mobj_is_paged(region->mobj)) { + size_t granule = BIT(pg_info->shift); + size_t offset = r.va - region->va + region->offset; + + r.size = MIN(r.size, + mobj_get_phys_granule(region->mobj)); + r.size = ROUNDUP(r.size, SMALL_PAGE_SIZE); + + if (mobj_get_pa(region->mobj, offset, granule, + &r.pa) != TEE_SUCCESS) + panic("Failed to get PA of unpaged mobj"); + set_region(pg_info, &r); + } + r.va += r.size; + } +} + +static bool can_map_at_level(paddr_t paddr, vaddr_t vaddr, + size_t size_left, paddr_t block_size, + struct tee_mmap_region *mm __maybe_unused) +{ + /* VA and PA are aligned to block size at current level */ + if ((vaddr | paddr) & (block_size - 1)) + return false; + + /* Remainder fits into block at current level */ + if (size_left < block_size) + return false; + +#ifdef CFG_WITH_PAGER + /* + * If pager is enabled, we need to map tee ram + * regions with small pages only + */ + if (map_is_tee_ram(mm) && block_size != SMALL_PAGE_SIZE) + return false; +#endif + + return true; +} + +void core_mmu_map_region(struct mmu_partition *prtn, struct tee_mmap_region *mm) +{ + struct core_mmu_table_info tbl_info; + unsigned int idx; + vaddr_t vaddr = mm->va; + paddr_t paddr = mm->pa; + ssize_t size_left = mm->size; + unsigned int level; + bool table_found; + uint32_t old_attr; + + assert(!((vaddr | paddr) & SMALL_PAGE_MASK)); + + while (size_left > 0) { + level = CORE_MMU_BASE_TABLE_LEVEL; + + while (true) { + paddr_t block_size = 0; + + assert(level <= CORE_MMU_PGDIR_LEVEL); + + table_found = core_mmu_find_table(prtn, vaddr, level, + &tbl_info); + if (!table_found) + panic("can't find table for mapping"); + + block_size = BIT64(tbl_info.shift); + + idx = core_mmu_va2idx(&tbl_info, vaddr); + if (!can_map_at_level(paddr, vaddr, size_left, + block_size, mm)) { + bool secure = mm->attr & TEE_MATTR_SECURE; + + /* + * This part of the region can't be mapped at + * this level. Need to go deeper. + */ + if (!core_mmu_entry_to_finer_grained(&tbl_info, + idx, + secure)) + panic("Can't divide MMU entry"); + level++; + continue; + } + + /* We can map part of the region at current level */ + core_mmu_get_entry(&tbl_info, idx, NULL, &old_attr); + if (old_attr) + panic("Page is already mapped"); + + core_mmu_set_entry(&tbl_info, idx, paddr, mm->attr); + paddr += block_size; + vaddr += block_size; + size_left -= block_size; + + break; + } + } +} + +TEE_Result core_mmu_map_pages(vaddr_t vstart, paddr_t *pages, size_t num_pages, + enum teecore_memtypes memtype) +{ + TEE_Result ret; + struct core_mmu_table_info tbl_info; + struct tee_mmap_region *mm; + unsigned int idx; + uint32_t old_attr; + uint32_t exceptions; + vaddr_t vaddr = vstart; + size_t i; + bool secure; + + assert(!(core_mmu_type_to_attr(memtype) & TEE_MATTR_PX)); + + secure = core_mmu_type_to_attr(memtype) & TEE_MATTR_SECURE; + + if (vaddr & SMALL_PAGE_MASK) + return TEE_ERROR_BAD_PARAMETERS; + + exceptions = mmu_lock(); + + mm = find_map_by_va((void *)vaddr); + if (!mm || !va_is_in_map(mm, vaddr + num_pages * SMALL_PAGE_SIZE - 1)) + panic("VA does not belong to any known mm region"); + + if (!core_mmu_is_dynamic_vaspace(mm)) + panic("Trying to map into static region"); + + for (i = 0; i < num_pages; i++) { + if (pages[i] & SMALL_PAGE_MASK) { + ret = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + while (true) { + if (!core_mmu_find_table(NULL, vaddr, UINT_MAX, + &tbl_info)) + panic("Can't find pagetable for vaddr "); + + idx = core_mmu_va2idx(&tbl_info, vaddr); + if (tbl_info.shift == SMALL_PAGE_SHIFT) + break; + + /* This is supertable. Need to divide it. */ + if (!core_mmu_entry_to_finer_grained(&tbl_info, idx, + secure)) + panic("Failed to spread pgdir on small tables"); + } + + core_mmu_get_entry(&tbl_info, idx, NULL, &old_attr); + if (old_attr) + panic("Page is already mapped"); + + core_mmu_set_entry(&tbl_info, idx, pages[i], + core_mmu_type_to_attr(memtype)); + vaddr += SMALL_PAGE_SIZE; + } + + /* + * Make sure all the changes to translation tables are visible + * before returning. TLB doesn't need to be invalidated as we are + * guaranteed that there's no valid mapping in this range. + */ + core_mmu_table_write_barrier(); + mmu_unlock(exceptions); + + return TEE_SUCCESS; +err: + mmu_unlock(exceptions); + + if (i) + core_mmu_unmap_pages(vstart, i); + + return ret; +} + +TEE_Result core_mmu_map_contiguous_pages(vaddr_t vstart, paddr_t pstart, + size_t num_pages, + enum teecore_memtypes memtype) +{ + struct core_mmu_table_info tbl_info = { }; + struct tee_mmap_region *mm = NULL; + unsigned int idx = 0; + uint32_t old_attr = 0; + uint32_t exceptions = 0; + vaddr_t vaddr = vstart; + paddr_t paddr = pstart; + size_t i = 0; + bool secure = false; + + assert(!(core_mmu_type_to_attr(memtype) & TEE_MATTR_PX)); + + secure = core_mmu_type_to_attr(memtype) & TEE_MATTR_SECURE; + + if ((vaddr | paddr) & SMALL_PAGE_MASK) + return TEE_ERROR_BAD_PARAMETERS; + + exceptions = mmu_lock(); + + mm = find_map_by_va((void *)vaddr); + if (!mm || !va_is_in_map(mm, vaddr + num_pages * SMALL_PAGE_SIZE - 1)) + panic("VA does not belong to any known mm region"); + + if (!core_mmu_is_dynamic_vaspace(mm)) + panic("Trying to map into static region"); + + for (i = 0; i < num_pages; i++) { + while (true) { + if (!core_mmu_find_table(NULL, vaddr, UINT_MAX, + &tbl_info)) + panic("Can't find pagetable for vaddr "); + + idx = core_mmu_va2idx(&tbl_info, vaddr); + if (tbl_info.shift == SMALL_PAGE_SHIFT) + break; + + /* This is supertable. Need to divide it. */ + if (!core_mmu_entry_to_finer_grained(&tbl_info, idx, + secure)) + panic("Failed to spread pgdir on small tables"); + } + + core_mmu_get_entry(&tbl_info, idx, NULL, &old_attr); + if (old_attr) + panic("Page is already mapped"); + + core_mmu_set_entry(&tbl_info, idx, paddr, + core_mmu_type_to_attr(memtype)); + paddr += SMALL_PAGE_SIZE; + vaddr += SMALL_PAGE_SIZE; + } + + /* + * Make sure all the changes to translation tables are visible + * before returning. TLB doesn't need to be invalidated as we are + * guaranteed that there's no valid mapping in this range. + */ + core_mmu_table_write_barrier(); + mmu_unlock(exceptions); + + return TEE_SUCCESS; +} + +void core_mmu_unmap_pages(vaddr_t vstart, size_t num_pages) +{ + struct core_mmu_table_info tbl_info; + struct tee_mmap_region *mm; + size_t i; + unsigned int idx; + uint32_t exceptions; + + exceptions = mmu_lock(); + + mm = find_map_by_va((void *)vstart); + if (!mm || !va_is_in_map(mm, vstart + num_pages * SMALL_PAGE_SIZE - 1)) + panic("VA does not belong to any known mm region"); + + if (!core_mmu_is_dynamic_vaspace(mm)) + panic("Trying to unmap static region"); + + for (i = 0; i < num_pages; i++, vstart += SMALL_PAGE_SIZE) { + if (!core_mmu_find_table(NULL, vstart, UINT_MAX, &tbl_info)) + panic("Can't find pagetable"); + + if (tbl_info.shift != SMALL_PAGE_SHIFT) + panic("Invalid pagetable level"); + + idx = core_mmu_va2idx(&tbl_info, vstart); + core_mmu_set_entry(&tbl_info, idx, 0, 0); + } + tlbi_all(); + + mmu_unlock(exceptions); +} + +void core_mmu_populate_user_map(struct core_mmu_table_info *dir_info, + struct user_mode_ctx *uctx) +{ + struct core_mmu_table_info pg_info = { }; + struct pgt_cache *pgt_cache = &uctx->pgt_cache; + struct pgt *pgt = NULL; + struct pgt *p = NULL; + struct vm_region *r = NULL; + + if (TAILQ_EMPTY(&uctx->vm_info.regions)) + return; /* Nothing to map */ + + /* + * Allocate all page tables in advance. + */ + pgt_get_all(uctx); + pgt = SLIST_FIRST(pgt_cache); + + core_mmu_set_info_table(&pg_info, dir_info->level + 1, 0, NULL); + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) + set_pg_region(dir_info, r, &pgt, &pg_info); + /* Record that the translation tables now are populated. */ + SLIST_FOREACH(p, pgt_cache, link) { + p->populated = true; + if (p == pgt) + break; + } + assert(p == pgt); +} + +TEE_Result core_mmu_remove_mapping(enum teecore_memtypes type, void *addr, + size_t len) +{ + struct core_mmu_table_info tbl_info = { }; + struct tee_mmap_region *res_map = NULL; + struct tee_mmap_region *map = NULL; + paddr_t pa = virt_to_phys(addr); + size_t granule = 0; + ptrdiff_t i = 0; + paddr_t p = 0; + size_t l = 0; + + map = find_map_by_type_and_pa(type, pa, len); + if (!map) + return TEE_ERROR_GENERIC; + + res_map = find_map_by_type(MEM_AREA_RES_VASPACE); + if (!res_map) + return TEE_ERROR_GENERIC; + if (!core_mmu_find_table(NULL, res_map->va, UINT_MAX, &tbl_info)) + return TEE_ERROR_GENERIC; + granule = BIT(tbl_info.shift); + + if (map < static_memory_map || + map >= static_memory_map + ARRAY_SIZE(static_memory_map)) + return TEE_ERROR_GENERIC; + i = map - static_memory_map; + + /* Check that we have a full match */ + p = ROUNDDOWN(pa, granule); + l = ROUNDUP(len + pa - p, granule); + if (map->pa != p || map->size != l) + return TEE_ERROR_GENERIC; + + clear_region(&tbl_info, map); + tlbi_all(); + + /* If possible remove the va range from res_map */ + if (res_map->va - map->size == map->va) { + res_map->va -= map->size; + res_map->size += map->size; + } + + /* Remove the entry. */ + memmove(map, map + 1, + (ARRAY_SIZE(static_memory_map) - i - 1) * sizeof(*map)); + + /* Clear the last new entry in case it was used */ + memset(static_memory_map + ARRAY_SIZE(static_memory_map) - 1, + 0, sizeof(*map)); + + return TEE_SUCCESS; +} + +struct tee_mmap_region * +core_mmu_find_mapping_exclusive(enum teecore_memtypes type, size_t len) +{ + struct tee_mmap_region *map = NULL; + struct tee_mmap_region *map_found = NULL; + + if (!len) + return NULL; + + for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++) { + if (map->type != type) + continue; + + if (map_found) + return NULL; + + map_found = map; + } + + if (!map_found || map_found->size < len) + return NULL; + + return map_found; +} + +void *core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, size_t len) +{ + struct core_mmu_table_info tbl_info; + struct tee_mmap_region *map; + size_t n; + size_t granule; + paddr_t p; + size_t l; + + if (!len) + return NULL; + + if (!core_mmu_check_end_pa(addr, len)) + return NULL; + + /* Check if the memory is already mapped */ + map = find_map_by_type_and_pa(type, addr, len); + if (map && pbuf_inside_map_area(addr, len, map)) + return (void *)(vaddr_t)(map->va + addr - map->pa); + + /* Find the reserved va space used for late mappings */ + map = find_map_by_type(MEM_AREA_RES_VASPACE); + if (!map) + return NULL; + + if (!core_mmu_find_table(NULL, map->va, UINT_MAX, &tbl_info)) + return NULL; + + granule = BIT64(tbl_info.shift); + p = ROUNDDOWN(addr, granule); + l = ROUNDUP(len + addr - p, granule); + + /* Ban overflowing virtual addresses */ + if (map->size < l) + return NULL; + + /* + * Something is wrong, we can't fit the va range into the selected + * table. The reserved va range is possibly missaligned with + * granule. + */ + if (core_mmu_va2idx(&tbl_info, map->va + len) >= tbl_info.num_entries) + return NULL; + + /* Find end of the memory map */ + n = 0; + while (!core_mmap_is_end_of_table(static_memory_map + n)) + n++; + + if (n < (ARRAY_SIZE(static_memory_map) - 1)) { + /* There's room for another entry */ + static_memory_map[n].va = map->va; + static_memory_map[n].size = l; + static_memory_map[n + 1].type = MEM_AREA_END; + map->va += l; + map->size -= l; + map = static_memory_map + n; + } else { + /* + * There isn't room for another entry, steal the reserved + * entry as it's not useful for anything else any longer. + */ + map->size = l; + } + map->type = type; + map->region_size = granule; + map->attr = core_mmu_type_to_attr(type); + map->pa = p; + + set_region(&tbl_info, map); + + /* Make sure the new entry is visible before continuing. */ + core_mmu_table_write_barrier(); + + return (void *)(vaddr_t)(map->va + addr - map->pa); +} + +#ifdef CFG_WITH_PAGER +static vaddr_t get_linear_map_end_va(void) +{ + /* this is synced with the generic linker file kern.ld.S */ + return (vaddr_t)__heap2_end; +} + +static paddr_t get_linear_map_end_pa(void) +{ + return get_linear_map_end_va() - boot_mmu_config.map_offset; +} +#endif + +#if defined(CFG_TEE_CORE_DEBUG) +static void check_pa_matches_va(void *va, paddr_t pa) +{ + TEE_Result res = TEE_ERROR_GENERIC; + vaddr_t v = (vaddr_t)va; + paddr_t p = 0; + struct core_mmu_table_info ti __maybe_unused = { }; + + if (core_mmu_user_va_range_is_defined()) { + vaddr_t user_va_base = 0; + size_t user_va_size = 0; + + core_mmu_get_user_va_range(&user_va_base, &user_va_size); + if (v >= user_va_base && + v <= (user_va_base - 1 + user_va_size)) { + if (!core_mmu_user_mapping_is_active()) { + if (pa) + panic("issue in linear address space"); + return; + } + + res = vm_va2pa(to_user_mode_ctx(thread_get_tsd()->ctx), + va, &p); + if (res == TEE_ERROR_NOT_SUPPORTED) + return; + if (res == TEE_SUCCESS && pa != p) + panic("bad pa"); + if (res != TEE_SUCCESS && pa) + panic("false pa"); + return; + } + } +#ifdef CFG_WITH_PAGER + if (is_unpaged(va)) { + if (v - boot_mmu_config.map_offset != pa) + panic("issue in linear address space"); + return; + } + + if (tee_pager_get_table_info(v, &ti)) { + uint32_t a; + + /* + * Lookups in the page table managed by the pager is + * dangerous for addresses in the paged area as those pages + * changes all the time. But some ranges are safe, + * rw-locked areas when the page is populated for instance. + */ + core_mmu_get_entry(&ti, core_mmu_va2idx(&ti, v), &p, &a); + if (a & TEE_MATTR_VALID_BLOCK) { + paddr_t mask = BIT64(ti.shift) - 1; + + p |= v & mask; + if (pa != p) + panic(); + } else { + if (pa) + panic(); + } + return; + } +#endif + + if (!core_va2pa_helper(va, &p)) { + /* Verfiy only the static mapping (case non null phys addr) */ + if (p && pa != p) { + DMSG("va %p maps 0x%" PRIxPA ", expect 0x%" PRIxPA, + va, p, pa); + panic(); + } + } else { + if (pa) { + DMSG("va %p unmapped, expect 0x%" PRIxPA, va, pa); + panic(); + } + } +} +#else +static void check_pa_matches_va(void *va __unused, paddr_t pa __unused) +{ +} +#endif + +paddr_t virt_to_phys(void *va) +{ + paddr_t pa = 0; + + if (!arch_va2pa_helper(va, &pa)) + pa = 0; + check_pa_matches_va(va, pa); + return pa; +} + +#if defined(CFG_TEE_CORE_DEBUG) +static void check_va_matches_pa(paddr_t pa, void *va) +{ + paddr_t p = 0; + + if (!va) + return; + + p = virt_to_phys(va); + if (p != pa) { + DMSG("va %p maps 0x%" PRIxPA " expect 0x%" PRIxPA, va, p, pa); + panic(); + } +} +#else +static void check_va_matches_pa(paddr_t pa __unused, void *va __unused) +{ +} +#endif + +static void *phys_to_virt_ts_vaspace(paddr_t pa, size_t len) +{ + if (!core_mmu_user_mapping_is_active()) + return NULL; + + return vm_pa2va(to_user_mode_ctx(thread_get_tsd()->ctx), pa, len); +} + +#ifdef CFG_WITH_PAGER +static void *phys_to_virt_tee_ram(paddr_t pa, size_t len) +{ + paddr_t end_pa = 0; + + if (SUB_OVERFLOW(len, 1, &end_pa) || ADD_OVERFLOW(pa, end_pa, &end_pa)) + return NULL; + + if (pa >= TEE_LOAD_ADDR && pa < get_linear_map_end_pa()) { + if (end_pa > get_linear_map_end_pa()) + return NULL; + return (void *)(vaddr_t)(pa + boot_mmu_config.map_offset); + } + + return tee_pager_phys_to_virt(pa, len); +} +#else +static void *phys_to_virt_tee_ram(paddr_t pa, size_t len) +{ + struct tee_mmap_region *mmap = NULL; + + mmap = find_map_by_type_and_pa(MEM_AREA_TEE_RAM, pa, len); + if (!mmap) + mmap = find_map_by_type_and_pa(MEM_AREA_NEX_RAM_RW, pa, len); + if (!mmap) + mmap = find_map_by_type_and_pa(MEM_AREA_NEX_RAM_RO, pa, len); + if (!mmap) + mmap = find_map_by_type_and_pa(MEM_AREA_TEE_RAM_RW, pa, len); + if (!mmap) + mmap = find_map_by_type_and_pa(MEM_AREA_TEE_RAM_RO, pa, len); + if (!mmap) + mmap = find_map_by_type_and_pa(MEM_AREA_TEE_RAM_RX, pa, len); + /* + * Note that MEM_AREA_INIT_RAM_RO and MEM_AREA_INIT_RAM_RX are only + * used with pager and not needed here. + */ + return map_pa2va(mmap, pa, len); +} +#endif + +void *phys_to_virt(paddr_t pa, enum teecore_memtypes m, size_t len) +{ + void *va = NULL; + + switch (m) { + case MEM_AREA_TS_VASPACE: + va = phys_to_virt_ts_vaspace(pa, len); + break; + case MEM_AREA_TEE_RAM: + case MEM_AREA_TEE_RAM_RX: + case MEM_AREA_TEE_RAM_RO: + case MEM_AREA_TEE_RAM_RW: + case MEM_AREA_NEX_RAM_RO: + case MEM_AREA_NEX_RAM_RW: + va = phys_to_virt_tee_ram(pa, len); + break; + case MEM_AREA_SHM_VASPACE: + /* Find VA from PA in dynamic SHM is not yet supported */ + va = NULL; + break; + default: + va = map_pa2va(find_map_by_type_and_pa(m, pa, len), pa, len); + } + if (m != MEM_AREA_SEC_RAM_OVERALL) + check_va_matches_pa(pa, va); + return va; +} + +void *phys_to_virt_io(paddr_t pa, size_t len) +{ + struct tee_mmap_region *map = NULL; + void *va = NULL; + + map = find_map_by_type_and_pa(MEM_AREA_IO_SEC, pa, len); + if (!map) + map = find_map_by_type_and_pa(MEM_AREA_IO_NSEC, pa, len); + if (!map) + return NULL; + va = map_pa2va(map, pa, len); + check_va_matches_pa(pa, va); + return va; +} + +vaddr_t core_mmu_get_va(paddr_t pa, enum teecore_memtypes type, size_t len) +{ + if (cpu_mmu_enabled()) + return (vaddr_t)phys_to_virt(pa, type, len); + + return (vaddr_t)pa; +} + +#ifdef CFG_WITH_PAGER +bool is_unpaged(void *va) +{ + vaddr_t v = (vaddr_t)va; + + return v >= VCORE_START_VA && v < get_linear_map_end_va(); +} +#else +bool is_unpaged(void *va __unused) +{ + return true; +} +#endif + +void core_mmu_init_virtualization(void) +{ + paddr_t b1 = 0; + paddr_size_t s1 = 0; + + static_assert(ARRAY_SIZE(secure_only) <= 2); + if (ARRAY_SIZE(secure_only) == 2) { + b1 = secure_only[1].paddr; + s1 = secure_only[1].size; + } + virt_init_memory(static_memory_map, secure_only[0].paddr, + secure_only[0].size, b1, s1); +} + +vaddr_t io_pa_or_va(struct io_pa_va *p, size_t len) +{ + assert(p->pa); + if (cpu_mmu_enabled()) { + if (!p->va) + p->va = (vaddr_t)phys_to_virt_io(p->pa, len); + assert(p->va); + return p->va; + } + return p->pa; +} + +vaddr_t io_pa_or_va_secure(struct io_pa_va *p, size_t len) +{ + assert(p->pa); + if (cpu_mmu_enabled()) { + if (!p->va) + p->va = (vaddr_t)phys_to_virt(p->pa, MEM_AREA_IO_SEC, + len); + assert(p->va); + return p->va; + } + return p->pa; +} + +vaddr_t io_pa_or_va_nsec(struct io_pa_va *p, size_t len) +{ + assert(p->pa); + if (cpu_mmu_enabled()) { + if (!p->va) + p->va = (vaddr_t)phys_to_virt(p->pa, MEM_AREA_IO_NSEC, + len); + assert(p->va); + return p->va; + } + return p->pa; +} + +#ifdef CFG_CORE_RESERVED_SHM +static TEE_Result teecore_init_pub_ram(void) +{ + vaddr_t s = 0; + vaddr_t e = 0; + + /* get virtual addr/size of NSec shared mem allocated from teecore */ + core_mmu_get_mem_by_type(MEM_AREA_NSEC_SHM, &s, &e); + + if (s >= e || s & SMALL_PAGE_MASK || e & SMALL_PAGE_MASK) + panic("invalid PUB RAM"); + + /* extra check: we could rely on core_mmu_get_mem_by_type() */ + if (!tee_vbuf_is_non_sec(s, e - s)) + panic("PUB RAM is not non-secure"); + +#ifdef CFG_PL310 + /* Allocate statically the l2cc mutex */ + tee_l2cc_store_mutex_boot_pa(virt_to_phys((void *)s)); + s += sizeof(uint32_t); /* size of a pl310 mutex */ + s = ROUNDUP(s, SMALL_PAGE_SIZE); /* keep required alignment */ +#endif + + default_nsec_shm_paddr = virt_to_phys((void *)s); + default_nsec_shm_size = e - s; + + return TEE_SUCCESS; +} +early_init(teecore_init_pub_ram); +#endif /*CFG_CORE_RESERVED_SHM*/ + +void core_mmu_init_ta_ram(void) +{ + vaddr_t s = 0; + vaddr_t e = 0; + paddr_t ps = 0; + size_t size = 0; + + /* + * Get virtual addr/size of RAM where TA are loaded/executedNSec + * shared mem allocated from teecore. + */ + if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) + virt_get_ta_ram(&s, &e); + else + core_mmu_get_mem_by_type(MEM_AREA_TA_RAM, &s, &e); + + ps = virt_to_phys((void *)s); + size = e - s; + + if (!ps || (ps & CORE_MMU_USER_CODE_MASK) || + !size || (size & CORE_MMU_USER_CODE_MASK)) + panic("invalid TA RAM"); + + /* extra check: we could rely on core_mmu_get_mem_by_type() */ + if (!tee_pbuf_is_sec(ps, size)) + panic("TA RAM is not secure"); + + if (!tee_mm_is_empty(&tee_mm_sec_ddr)) + panic("TA RAM pool is not empty"); + + /* remove previous config and init TA ddr memory pool */ + tee_mm_final(&tee_mm_sec_ddr); + tee_mm_init(&tee_mm_sec_ddr, ps, size, CORE_MMU_USER_CODE_SHIFT, + TEE_MM_POOL_NO_FLAGS); +} diff --git a/optee/optee_os/core/mm/file.c b/optee/optee_os/core/mm/file.c new file mode 100644 index 0000000..1f6a987 --- /dev/null +++ b/optee/optee_os/core/mm/file.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct file_slice_elem { + struct file_slice slice; + SLIST_ENTRY(file_slice_elem) link; +}; + +/* + * struct file - file resources + * @tag: Tag or hash uniquely identifying a file + * @taglen: Byte length of @tag + * @refc: Reference counter + * @link: Linked list element + * @num_slices: Number of elements in the @slices array below + * @slices: Array of file slices holding the fobjs of this file + * + * A file is constructed of slices which may be shared in different + * mappings/contexts. There may be holes in the file for ranges of the file + * that can't be shared. + */ +struct file { + uint8_t tag[FILE_TAG_SIZE]; + unsigned int taglen; + struct refcount refc; + TAILQ_ENTRY(file) link; + struct mutex mu; + SLIST_HEAD(, file_slice_elem) slice_head; +}; + +static struct mutex file_mu = MUTEX_INITIALIZER; +static TAILQ_HEAD(, file) file_head = TAILQ_HEAD_INITIALIZER(file_head); + +static int file_tag_cmp(const struct file *f, const uint8_t *tag, + unsigned int taglen) +{ + if (f->taglen != taglen) + return -1; + return memcmp(tag, f->tag, taglen); +} + +static struct file *file_find_tag_unlocked(const uint8_t *tag, + unsigned int taglen) +{ + struct file *f = NULL; + + TAILQ_FOREACH(f, &file_head, link) + if (!file_tag_cmp(f, tag, taglen)) + return f; + + return NULL; +} + +static void file_free(struct file *f) +{ + mutex_destroy(&f->mu); + + while (!SLIST_EMPTY(&f->slice_head)) { + struct file_slice_elem *fse = SLIST_FIRST(&f->slice_head); + + SLIST_REMOVE_HEAD(&f->slice_head, link); + fobj_put(fse->slice.fobj); + free(fse); + } + + free(f); +} + +TEE_Result file_add_slice(struct file *f, struct fobj *fobj, + unsigned int page_offset) +{ + struct file_slice_elem *fse = NULL; + unsigned int s = 0; + + /* Check for conflicts */ + if (file_find_slice(f, page_offset)) + return TEE_ERROR_BAD_PARAMETERS; + + fse = calloc(1, sizeof(*fse)); + if (!fse) + return TEE_ERROR_OUT_OF_MEMORY; + + fse->slice.fobj = fobj_get(fobj); + if (!fse->slice.fobj || + ADD_OVERFLOW(page_offset, fse->slice.fobj->num_pages, &s)) { + fobj_put(fse->slice.fobj); + free(fse); + return TEE_ERROR_BAD_PARAMETERS; + } + + fse->slice.page_offset = page_offset; + SLIST_INSERT_HEAD(&f->slice_head, fse, link); + + return TEE_SUCCESS; +} + +struct file *file_get(struct file *f) +{ + if (f && !refcount_inc(&f->refc)) + panic(); + + return f; +} + +struct file *file_get_by_tag(const uint8_t *tag, unsigned int taglen) +{ + struct file *f = NULL; + + if (taglen > sizeof(f->tag)) + return NULL; + + mutex_lock(&file_mu); + + /* + * If file is found and reference counter can be increased, we're done. + * If file can't be found, it doesn't exist so it has to be added. + * If it's found but reference counter is 0, the situation is + * a bit complicated: + * - file_put() is about to free the file as soon as it can obtain the + * mutex. + * - Unless there's a mismatch between file_get() and file_put() only + * one thread calling file_put() is about to free the file. + * + * There's a window of opportunity where file_put() is called + * (without a mutex being held, which is quite OK) while we're + * holding the mutex here and are searching for the file and it's + * found, but just after file_put() has decreased the reference + * counter. + * + * To keep it simple we're adding a new file at the head (so new + * searches finds this file instead of the old being freed) instead + * of complicating file_put() by trying to rescue the file and + * possibly hiding a case of mismatching file_put() and file_get(). + */ + f = file_find_tag_unlocked(tag, taglen); + if (f && refcount_inc(&f->refc)) + goto out; + + f = calloc(1, sizeof(*f)); + if (!f) + goto out; + memcpy(f->tag, tag, taglen); + f->taglen = taglen; + refcount_set(&f->refc, 1); + mutex_init(&f->mu); + SLIST_INIT(&f->slice_head); + TAILQ_INSERT_HEAD(&file_head, f, link); + +out: + mutex_unlock(&file_mu); + + return f; +} + +void file_put(struct file *f) +{ + if (f && refcount_dec(&f->refc)) { + mutex_lock(&file_mu); + TAILQ_REMOVE(&file_head, f, link); + mutex_unlock(&file_mu); + + file_free(f); + } + +} + +struct file_slice *file_find_slice(struct file *f, unsigned int page_offset) +{ + struct file_slice_elem *fse = NULL; + + assert(f->mu.state); + + SLIST_FOREACH(fse, &f->slice_head, link) { + struct file_slice *fs = &fse->slice; + + if (page_offset >= fs->page_offset && + page_offset < fs->page_offset + fs->fobj->num_pages) + return fs; + } + + return NULL; +} + +void file_lock(struct file *f) +{ + mutex_lock(&f->mu); +} + +bool file_trylock(struct file *f) +{ + return mutex_trylock(&f->mu); +} + +void file_unlock(struct file *f) +{ + mutex_unlock(&f->mu); +} diff --git a/optee/optee_os/core/mm/fobj.c b/optee/optee_os/core/mm/fobj.c new file mode 100644 index 0000000..e1397cc --- /dev/null +++ b/optee/optee_os/core/mm/fobj.c @@ -0,0 +1,818 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CFG_WITH_PAGER + +#define RWP_AE_KEY_BITS 256 + +struct rwp_aes_gcm_iv { + uint32_t iv[3]; +}; + +#define RWP_AES_GCM_TAG_LEN 16 + +struct rwp_state { + uint64_t iv; + uint8_t tag[RWP_AES_GCM_TAG_LEN]; +}; + +/* + * Note that this struct is padded to a size which is a power of 2, this + * guarantees that this state will not span two pages. This avoids a corner + * case in the pager when making the state available. + */ +struct rwp_state_padded { + struct rwp_state state; + uint64_t pad; +}; + +struct fobj_rwp_unpaged_iv { + uint8_t *store; + struct rwp_state *state; + struct fobj fobj; +}; + +struct fobj_rwp_paged_iv { + size_t idx; + struct fobj fobj; +}; + +const struct fobj_ops ops_rwp_paged_iv; +const struct fobj_ops ops_rwp_unpaged_iv; + +static struct internal_aes_gcm_key rwp_ae_key; + +static struct rwp_state_padded *rwp_state_base; +static uint8_t *rwp_store_base; + +static void fobj_init(struct fobj *fobj, const struct fobj_ops *ops, + unsigned int num_pages) +{ + fobj->ops = ops; + fobj->num_pages = num_pages; + refcount_set(&fobj->refc, 1); + TAILQ_INIT(&fobj->regions); +} + +static void fobj_uninit(struct fobj *fobj) +{ + assert(!refcount_val(&fobj->refc)); + assert(TAILQ_EMPTY(&fobj->regions)); + tee_pager_invalidate_fobj(fobj); +} + +static TEE_Result rwp_load_page(void *va, struct rwp_state *state, + const uint8_t *src) +{ + struct rwp_aes_gcm_iv iv = { + .iv = { (vaddr_t)state, state->iv >> 32, state->iv } + }; + + if (!state->iv) { + /* + * IV still zero which means that this is previously unused + * page. + */ + memset(va, 0, SMALL_PAGE_SIZE); + return TEE_SUCCESS; + } + + return internal_aes_gcm_dec(&rwp_ae_key, &iv, sizeof(iv), + NULL, 0, src, SMALL_PAGE_SIZE, va, + state->tag, sizeof(state->tag)); +} + +static TEE_Result rwp_save_page(const void *va, struct rwp_state *state, + uint8_t *dst) +{ + size_t tag_len = sizeof(state->tag); + struct rwp_aes_gcm_iv iv = { }; + + assert(state->iv + 1 > state->iv); + + state->iv++; + + /* + * IV is constructed as recommended in section "8.2.1 Deterministic + * Construction" of "Recommendation for Block Cipher Modes of + * Operation: Galois/Counter Mode (GCM) and GMAC", + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + */ + iv.iv[0] = (vaddr_t)state; + iv.iv[1] = state->iv >> 32; + iv.iv[2] = state->iv; + + return internal_aes_gcm_enc(&rwp_ae_key, &iv, sizeof(iv), + NULL, 0, va, SMALL_PAGE_SIZE, dst, + state->tag, &tag_len); +} + +static struct rwp_state_padded *idx_to_state_padded(size_t idx) +{ + assert(rwp_state_base); + return rwp_state_base + idx; +} + +static uint8_t *idx_to_store(size_t idx) +{ + assert(rwp_store_base); + return rwp_store_base + idx * SMALL_PAGE_SIZE; +} + +static struct fobj *rwp_paged_iv_alloc(unsigned int num_pages) +{ + struct fobj_rwp_paged_iv *rwp = NULL; + tee_mm_entry_t *mm = NULL; + size_t size = 0; + + COMPILE_TIME_ASSERT(IS_POWER_OF_TWO(sizeof(struct rwp_state_padded))); + + rwp = calloc(1, sizeof(*rwp)); + if (!rwp) + return NULL; + + if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size)) + goto err; + mm = tee_mm_alloc(&tee_mm_sec_ddr, size); + if (!mm) + goto err; + rwp->idx = (tee_mm_get_smem(mm) - tee_mm_sec_ddr.lo) / SMALL_PAGE_SIZE; + + memset(idx_to_state_padded(rwp->idx), 0, + num_pages * sizeof(struct rwp_state_padded)); + + fobj_init(&rwp->fobj, &ops_rwp_paged_iv, num_pages); + + return &rwp->fobj; +err: + tee_mm_free(mm); + free(rwp); + + return NULL; +} + +static struct fobj_rwp_paged_iv *to_rwp_paged_iv(struct fobj *fobj) +{ + assert(fobj->ops == &ops_rwp_paged_iv); + + return container_of(fobj, struct fobj_rwp_paged_iv, fobj); +} + +static TEE_Result rwp_paged_iv_load_page(struct fobj *fobj, + unsigned int page_idx, void *va) +{ + struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj); + uint8_t *src = idx_to_store(rwp->idx) + page_idx * SMALL_PAGE_SIZE; + struct rwp_state_padded *st = idx_to_state_padded(rwp->idx + page_idx); + + assert(refcount_val(&fobj->refc)); + assert(page_idx < fobj->num_pages); + + return rwp_load_page(va, &st->state, src); +} +DECLARE_KEEP_PAGER(rwp_paged_iv_load_page); + +static TEE_Result rwp_paged_iv_save_page(struct fobj *fobj, + unsigned int page_idx, const void *va) +{ + struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj); + uint8_t *dst = idx_to_store(rwp->idx) + page_idx * SMALL_PAGE_SIZE; + struct rwp_state_padded *st = idx_to_state_padded(rwp->idx + page_idx); + + assert(page_idx < fobj->num_pages); + + if (!refcount_val(&fobj->refc)) { + /* + * This fobj is being teared down, it just hasn't had the time + * to call tee_pager_invalidate_fobj() yet. + */ + assert(TAILQ_EMPTY(&fobj->regions)); + return TEE_SUCCESS; + } + + return rwp_save_page(va, &st->state, dst); +} +DECLARE_KEEP_PAGER(rwp_paged_iv_save_page); + +static void rwp_paged_iv_free(struct fobj *fobj) +{ + struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj); + paddr_t pa = rwp->idx * SMALL_PAGE_SIZE + tee_mm_sec_ddr.lo; + tee_mm_entry_t *mm = tee_mm_find(&tee_mm_sec_ddr, pa); + + assert(mm); + + fobj_uninit(fobj); + tee_mm_free(mm); + free(rwp); +} + +static vaddr_t rwp_paged_iv_get_iv_vaddr(struct fobj *fobj, + unsigned int page_idx) +{ + struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj); + struct rwp_state_padded *st = idx_to_state_padded(rwp->idx + page_idx); + + assert(page_idx < fobj->num_pages); + return (vaddr_t)&st->state & ~SMALL_PAGE_MASK; +} +DECLARE_KEEP_PAGER(rwp_paged_iv_get_iv_vaddr); + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct fobj_ops ops_rwp_paged_iv +__weak __relrodata_unpaged("ops_rwp_paged_iv") = { + .free = rwp_paged_iv_free, + .load_page = rwp_paged_iv_load_page, + .save_page = rwp_paged_iv_save_page, + .get_iv_vaddr = rwp_paged_iv_get_iv_vaddr, +}; + +static struct fobj *rwp_unpaged_iv_alloc(unsigned int num_pages) +{ + struct fobj_rwp_unpaged_iv *rwp = NULL; + tee_mm_entry_t *mm = NULL; + size_t size = 0; + + rwp = calloc(1, sizeof(*rwp)); + if (!rwp) + return NULL; + + rwp->state = calloc(num_pages, sizeof(*rwp->state)); + if (!rwp->state) + goto err_free_rwp; + + if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size)) + goto err_free_state; + mm = tee_mm_alloc(&tee_mm_sec_ddr, size); + if (!mm) + goto err_free_state; + rwp->store = phys_to_virt(tee_mm_get_smem(mm), MEM_AREA_TA_RAM, size); + assert(rwp->store); + + fobj_init(&rwp->fobj, &ops_rwp_unpaged_iv, num_pages); + + return &rwp->fobj; + +err_free_state: + free(rwp->state); +err_free_rwp: + free(rwp); + return NULL; +} + +static struct fobj_rwp_unpaged_iv *to_rwp_unpaged_iv(struct fobj *fobj) +{ + assert(fobj->ops == &ops_rwp_unpaged_iv); + + return container_of(fobj, struct fobj_rwp_unpaged_iv, fobj); +} + +static TEE_Result rwp_unpaged_iv_load_page(struct fobj *fobj, + unsigned int page_idx, void *va) +{ + struct fobj_rwp_unpaged_iv *rwp = to_rwp_unpaged_iv(fobj); + uint8_t *src = rwp->store + page_idx * SMALL_PAGE_SIZE; + + assert(refcount_val(&fobj->refc)); + assert(page_idx < fobj->num_pages); + + return rwp_load_page(va, rwp->state + page_idx, src); +} +DECLARE_KEEP_PAGER(rwp_unpaged_iv_load_page); + +static TEE_Result rwp_unpaged_iv_save_page(struct fobj *fobj, + unsigned int page_idx, + const void *va) +{ + struct fobj_rwp_unpaged_iv *rwp = to_rwp_unpaged_iv(fobj); + uint8_t *dst = rwp->store + page_idx * SMALL_PAGE_SIZE; + + assert(page_idx < fobj->num_pages); + + if (!refcount_val(&fobj->refc)) { + /* + * This fobj is being teared down, it just hasn't had the time + * to call tee_pager_invalidate_fobj() yet. + */ + assert(TAILQ_EMPTY(&fobj->regions)); + return TEE_SUCCESS; + } + + return rwp_save_page(va, rwp->state + page_idx, dst); +} +DECLARE_KEEP_PAGER(rwp_unpaged_iv_save_page); + +static void rwp_unpaged_iv_free(struct fobj *fobj) +{ + struct fobj_rwp_unpaged_iv *rwp = NULL; + tee_mm_entry_t *mm = NULL; + + if (IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV)) + panic(); + + rwp = to_rwp_unpaged_iv(fobj); + mm = tee_mm_find(&tee_mm_sec_ddr, virt_to_phys(rwp->store)); + + assert(mm); + + fobj_uninit(fobj); + tee_mm_free(mm); + free(rwp->state); + free(rwp); +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct fobj_ops ops_rwp_unpaged_iv +__weak __relrodata_unpaged("ops_rwp_unpaged_iv") = { + .free = rwp_unpaged_iv_free, + .load_page = rwp_unpaged_iv_load_page, + .save_page = rwp_unpaged_iv_save_page, +}; + +static TEE_Result rwp_init(void) +{ + uint8_t key[RWP_AE_KEY_BITS / 8] = { 0 }; + struct fobj *fobj = NULL; + size_t num_pool_pages = 0; + size_t num_fobj_pages = 0; + + if (crypto_rng_read(key, sizeof(key)) != TEE_SUCCESS) + panic("failed to generate random"); + if (crypto_aes_expand_enc_key(key, sizeof(key), rwp_ae_key.data, + sizeof(rwp_ae_key.data), + &rwp_ae_key.rounds)) + panic("failed to expand key"); + + if (!IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV)) + return TEE_SUCCESS; + + assert(tee_mm_sec_ddr.size && !(tee_mm_sec_ddr.size & SMALL_PAGE_SIZE)); + + num_pool_pages = tee_mm_sec_ddr.size / SMALL_PAGE_SIZE; + num_fobj_pages = ROUNDUP(num_pool_pages * sizeof(*rwp_state_base), + SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; + + /* + * Each page in the pool needs a struct rwp_state. + * + * This isn't entirely true, the pages not used by + * fobj_rw_paged_alloc() don't need any. A future optimization + * may try to avoid allocating for such pages. + */ + fobj = rwp_unpaged_iv_alloc(num_fobj_pages); + if (!fobj) + panic(); + + rwp_state_base = (void *)tee_pager_init_iv_region(fobj); + assert(rwp_state_base); + + rwp_store_base = phys_to_virt(tee_mm_sec_ddr.lo, MEM_AREA_TA_RAM, + tee_mm_sec_ddr.size); + assert(rwp_store_base); + + return TEE_SUCCESS; +} +driver_init_late(rwp_init); + +struct fobj *fobj_rw_paged_alloc(unsigned int num_pages) +{ + assert(num_pages); + + if (IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV)) + return rwp_paged_iv_alloc(num_pages); + else + return rwp_unpaged_iv_alloc(num_pages); +} + +struct fobj_rop { + uint8_t *hashes; + uint8_t *store; + struct fobj fobj; +}; + +const struct fobj_ops ops_ro_paged; + +static void rop_init(struct fobj_rop *rop, const struct fobj_ops *ops, + unsigned int num_pages, void *hashes, void *store) +{ + rop->hashes = hashes; + rop->store = store; + fobj_init(&rop->fobj, ops, num_pages); +} + +struct fobj *fobj_ro_paged_alloc(unsigned int num_pages, void *hashes, + void *store) +{ + struct fobj_rop *rop = NULL; + + assert(num_pages && hashes && store); + + rop = calloc(1, sizeof(*rop)); + if (!rop) + return NULL; + + rop_init(rop, &ops_ro_paged, num_pages, hashes, store); + + return &rop->fobj; +} + +static struct fobj_rop *to_rop(struct fobj *fobj) +{ + assert(fobj->ops == &ops_ro_paged); + + return container_of(fobj, struct fobj_rop, fobj); +} + +static void rop_uninit(struct fobj_rop *rop) +{ + fobj_uninit(&rop->fobj); + tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, virt_to_phys(rop->store))); + free(rop->hashes); +} + +static void rop_free(struct fobj *fobj) +{ + struct fobj_rop *rop = to_rop(fobj); + + rop_uninit(rop); + free(rop); +} + +static TEE_Result rop_load_page_helper(struct fobj_rop *rop, + unsigned int page_idx, void *va) +{ + const uint8_t *hash = rop->hashes + page_idx * TEE_SHA256_HASH_SIZE; + const uint8_t *src = rop->store + page_idx * SMALL_PAGE_SIZE; + + assert(refcount_val(&rop->fobj.refc)); + assert(page_idx < rop->fobj.num_pages); + memcpy(va, src, SMALL_PAGE_SIZE); + + return hash_sha256_check(hash, va, SMALL_PAGE_SIZE); +} + +static TEE_Result rop_load_page(struct fobj *fobj, unsigned int page_idx, + void *va) +{ + return rop_load_page_helper(to_rop(fobj), page_idx, va); +} +DECLARE_KEEP_PAGER(rop_load_page); + +static TEE_Result rop_save_page(struct fobj *fobj __unused, + unsigned int page_idx __unused, + const void *va __unused) +{ + return TEE_ERROR_GENERIC; +} +DECLARE_KEEP_PAGER(rop_save_page); + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct fobj_ops ops_ro_paged +__weak __relrodata_unpaged("ops_ro_paged") = { + .free = rop_free, + .load_page = rop_load_page, + .save_page = rop_save_page, +}; + +#ifdef CFG_CORE_ASLR +/* + * When using relocated pages the relocation information must be applied + * before the pages can be used. With read-only paging the content is only + * integrity protected so relocation cannot be applied on pages in the less + * secure "store" or the load_address selected by ASLR could be given away. + * This means that each time a page has been loaded and verified it has to + * have its relocation information applied before it can be used. + * + * Only the relative relocations are supported, this allows a rather compact + * represenation of the needed relocation information in this struct. + * r_offset is replaced with the offset into the page that need to be updated, + * this number can never be larger than SMALL_PAGE_SIZE so a uint16_t can be + * used to represent it. + * + * All relocations are converted and stored in @relocs. @page_reloc_idx is + * an array of length @rop.fobj.num_pages with an entry for each page. If + * @page_reloc_idx[page_idx] isn't UINT16_MAX it's an index into @relocs. + */ +struct fobj_ro_reloc_paged { + uint16_t *page_reloc_idx; + uint16_t *relocs; + unsigned int num_relocs; + struct fobj_rop rop; +}; + +const struct fobj_ops ops_ro_reloc_paged; + +static unsigned int get_num_rels(unsigned int num_pages, + unsigned int reloc_offs, + const uint32_t *reloc, unsigned int num_relocs) +{ + const unsigned int align_mask __maybe_unused = sizeof(long) - 1; + unsigned int nrels = 0; + unsigned int n = 0; + vaddr_t offs = 0; + + /* + * Count the number of relocations which are needed for these + * pages. Also check that the data is well formed, only expected + * relocations and sorted in order of address which it applies to. + */ + for (; n < num_relocs; n++) { + assert(IS_ALIGNED_WITH_TYPE(reloc[n], unsigned long)); + assert(offs < reloc[n]); /* check that it's sorted */ + offs = reloc[n]; + if (offs >= reloc_offs && + offs <= reloc_offs + num_pages * SMALL_PAGE_SIZE) + nrels++; + } + + return nrels; +} + +static void init_rels(struct fobj_ro_reloc_paged *rrp, unsigned int reloc_offs, + const uint32_t *reloc, unsigned int num_relocs) +{ + unsigned int npg = rrp->rop.fobj.num_pages; + unsigned int pg_idx = 0; + unsigned int reln = 0; + unsigned int n = 0; + uint32_t r = 0; + + for (n = 0; n < npg; n++) + rrp->page_reloc_idx[n] = UINT16_MAX; + + for (n = 0; n < num_relocs ; n++) { + if (reloc[n] < reloc_offs) + continue; + + /* r is the offset from beginning of this fobj */ + r = reloc[n] - reloc_offs; + + pg_idx = r / SMALL_PAGE_SIZE; + if (pg_idx >= npg) + break; + + if (rrp->page_reloc_idx[pg_idx] == UINT16_MAX) + rrp->page_reloc_idx[pg_idx] = reln; + rrp->relocs[reln] = r - pg_idx * SMALL_PAGE_SIZE; + reln++; + } + + assert(reln == rrp->num_relocs); +} + +struct fobj *fobj_ro_reloc_paged_alloc(unsigned int num_pages, void *hashes, + unsigned int reloc_offs, + const void *reloc, + unsigned int reloc_len, void *store) +{ + struct fobj_ro_reloc_paged *rrp = NULL; + const unsigned int num_relocs = reloc_len / sizeof(uint32_t); + unsigned int nrels = 0; + + assert(IS_ALIGNED_WITH_TYPE(reloc, uint32_t)); + assert(IS_ALIGNED_WITH_TYPE(reloc_len, uint32_t)); + assert(num_pages && hashes && store); + if (!reloc_len) { + assert(!reloc); + return fobj_ro_paged_alloc(num_pages, hashes, store); + } + assert(reloc); + + nrels = get_num_rels(num_pages, reloc_offs, reloc, num_relocs); + if (!nrels) + return fobj_ro_paged_alloc(num_pages, hashes, store); + + rrp = calloc(1, sizeof(*rrp) + num_pages * sizeof(uint16_t) + + nrels * sizeof(uint16_t)); + if (!rrp) + return NULL; + rop_init(&rrp->rop, &ops_ro_reloc_paged, num_pages, hashes, store); + rrp->page_reloc_idx = (uint16_t *)(rrp + 1); + rrp->relocs = rrp->page_reloc_idx + num_pages; + rrp->num_relocs = nrels; + init_rels(rrp, reloc_offs, reloc, num_relocs); + + return &rrp->rop.fobj; +} + +static struct fobj_ro_reloc_paged *to_rrp(struct fobj *fobj) +{ + assert(fobj->ops == &ops_ro_reloc_paged); + + return container_of(fobj, struct fobj_ro_reloc_paged, rop.fobj); +} + +static void rrp_free(struct fobj *fobj) +{ + struct fobj_ro_reloc_paged *rrp = to_rrp(fobj); + + rop_uninit(&rrp->rop); + free(rrp); +} + +static TEE_Result rrp_load_page(struct fobj *fobj, unsigned int page_idx, + void *va) +{ + struct fobj_ro_reloc_paged *rrp = to_rrp(fobj); + unsigned int end_rel = rrp->num_relocs; + TEE_Result res = TEE_SUCCESS; + unsigned long *where = NULL; + unsigned int n = 0; + + res = rop_load_page_helper(&rrp->rop, page_idx, va); + if (res) + return res; + + /* Find the reloc index of the next page to tell when we're done */ + for (n = page_idx + 1; n < fobj->num_pages; n++) { + if (rrp->page_reloc_idx[n] != UINT16_MAX) { + end_rel = rrp->page_reloc_idx[n]; + break; + } + } + + for (n = rrp->page_reloc_idx[page_idx]; n < end_rel; n++) { + where = (void *)((vaddr_t)va + rrp->relocs[n]); + *where += boot_mmu_config.map_offset; + } + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(rrp_load_page); + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct fobj_ops ops_ro_reloc_paged +__weak __relrodata_unpaged("ops_ro_reloc_paged") = { + .free = rrp_free, + .load_page = rrp_load_page, + .save_page = rop_save_page, /* Direct reuse */ +}; +#endif /*CFG_CORE_ASLR*/ + +const struct fobj_ops ops_locked_paged; + +struct fobj *fobj_locked_paged_alloc(unsigned int num_pages) +{ + struct fobj *f = NULL; + + assert(num_pages); + + f = calloc(1, sizeof(*f)); + if (!f) + return NULL; + + fobj_init(f, &ops_locked_paged, num_pages); + + return f; +} + +static void lop_free(struct fobj *fobj) +{ + assert(fobj->ops == &ops_locked_paged); + fobj_uninit(fobj); + free(fobj); +} + +static TEE_Result lop_load_page(struct fobj *fobj __maybe_unused, + unsigned int page_idx __maybe_unused, + void *va) +{ + assert(fobj->ops == &ops_locked_paged); + assert(refcount_val(&fobj->refc)); + assert(page_idx < fobj->num_pages); + + memset(va, 0, SMALL_PAGE_SIZE); + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(lop_load_page); + +static TEE_Result lop_save_page(struct fobj *fobj __unused, + unsigned int page_idx __unused, + const void *va __unused) +{ + return TEE_ERROR_GENERIC; +} +DECLARE_KEEP_PAGER(lop_save_page); + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct fobj_ops ops_locked_paged +__weak __relrodata_unpaged("ops_locked_paged") = { + .free = lop_free, + .load_page = lop_load_page, + .save_page = lop_save_page, +}; +#endif /*CFG_WITH_PAGER*/ + +#ifndef CFG_PAGED_USER_TA + +struct fobj_sec_mem { + tee_mm_entry_t *mm; + struct fobj fobj; +}; + +const struct fobj_ops ops_sec_mem; + +struct fobj *fobj_sec_mem_alloc(unsigned int num_pages) +{ + struct fobj_sec_mem *f = calloc(1, sizeof(*f)); + size_t size = 0; + void *va = NULL; + + if (!f) + return NULL; + + if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size)) + goto err; + + f->mm = tee_mm_alloc(&tee_mm_sec_ddr, size); + if (!f->mm) + goto err; + + va = phys_to_virt(tee_mm_get_smem(f->mm), MEM_AREA_TA_RAM, size); + if (!va) + goto err; + + memtag_clear_mem(va, size); + f->fobj.ops = &ops_sec_mem; + f->fobj.num_pages = num_pages; + refcount_set(&f->fobj.refc, 1); + + return &f->fobj; +err: + tee_mm_free(f->mm); + free(f); + + return NULL; +} + +static struct fobj_sec_mem *to_sec_mem(struct fobj *fobj) +{ + assert(fobj->ops == &ops_sec_mem); + + return container_of(fobj, struct fobj_sec_mem, fobj); +} + +static void sec_mem_free(struct fobj *fobj) +{ + struct fobj_sec_mem *f = to_sec_mem(fobj); + + assert(!refcount_val(&fobj->refc)); + tee_mm_free(f->mm); + free(f); +} + +static paddr_t sec_mem_get_pa(struct fobj *fobj, unsigned int page_idx) +{ + struct fobj_sec_mem *f = to_sec_mem(fobj); + + assert(refcount_val(&fobj->refc)); + assert(page_idx < fobj->num_pages); + + return tee_mm_get_smem(f->mm) + page_idx * SMALL_PAGE_SIZE; +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct fobj_ops ops_sec_mem __weak __relrodata_unpaged("ops_sec_mem") = { + .free = sec_mem_free, + .get_pa = sec_mem_get_pa, +}; + +#endif /*PAGED_USER_TA*/ diff --git a/optee/optee_os/core/mm/mobj.c b/optee/optee_os/core/mm/mobj.c new file mode 100644 index 0000000..dc54bb1 --- /dev/null +++ b/optee/optee_os/core/mm/mobj.c @@ -0,0 +1,762 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mobj *mobj_sec_ddr; +struct mobj *mobj_tee_ram_rx; +struct mobj *mobj_tee_ram_rw; + +/* + * mobj_phys implementation + */ + +struct mobj_phys { + struct mobj mobj; + enum buf_is_attr battr; + /* Defined by TEE_MATTR_MEM_TYPE_* in tee_mmu_types.h */ + uint32_t mem_type; + vaddr_t va; + paddr_t pa; +}; + +static struct mobj_phys *to_mobj_phys(struct mobj *mobj); + +static void *mobj_phys_get_va(struct mobj *mobj, size_t offset, size_t len) +{ + struct mobj_phys *moph = to_mobj_phys(mobj); + + if (!moph->va || !mobj_check_offset_and_len(mobj, offset, len)) + return NULL; + + return (void *)(moph->va + offset); +} + +static TEE_Result mobj_phys_get_pa(struct mobj *mobj, size_t offs, + size_t granule, paddr_t *pa) +{ + struct mobj_phys *moph = to_mobj_phys(mobj); + paddr_t p; + + if (!pa) + return TEE_ERROR_GENERIC; + + p = moph->pa + offs; + + if (granule) { + if (granule != SMALL_PAGE_SIZE && + granule != CORE_MMU_PGDIR_SIZE) + return TEE_ERROR_GENERIC; + p &= ~(granule - 1); + } + + *pa = p; + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(mobj_phys_get_pa); + +static TEE_Result mobj_phys_get_mem_type(struct mobj *mobj, uint32_t *mem_type) +{ + struct mobj_phys *moph = to_mobj_phys(mobj); + + if (!mem_type) + return TEE_ERROR_GENERIC; + + *mem_type = moph->mem_type; + return TEE_SUCCESS; +} + +static bool mobj_phys_matches(struct mobj *mobj, enum buf_is_attr attr) +{ + struct mobj_phys *moph = to_mobj_phys(mobj); + enum buf_is_attr a; + + a = moph->battr; + + switch (attr) { + case CORE_MEM_SEC: + return a == CORE_MEM_SEC || a == CORE_MEM_TEE_RAM || + a == CORE_MEM_TA_RAM || a == CORE_MEM_SDP_MEM; + case CORE_MEM_NON_SEC: + return a == CORE_MEM_NSEC_SHM; + case CORE_MEM_TEE_RAM: + case CORE_MEM_TA_RAM: + case CORE_MEM_NSEC_SHM: + case CORE_MEM_SDP_MEM: + return attr == a; + default: + return false; + } +} + +static void mobj_phys_free(struct mobj *mobj) +{ + struct mobj_phys *moph = to_mobj_phys(mobj); + + free(moph); +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct mobj_ops mobj_phys_ops +__weak __relrodata_unpaged("mobj_phys_ops") = { + .get_va = mobj_phys_get_va, + .get_pa = mobj_phys_get_pa, + .get_phys_offs = NULL, /* only offset 0 */ + .get_mem_type = mobj_phys_get_mem_type, + .matches = mobj_phys_matches, + .free = mobj_phys_free, +}; + +static struct mobj_phys *to_mobj_phys(struct mobj *mobj) +{ + assert(mobj->ops == &mobj_phys_ops); + return container_of(mobj, struct mobj_phys, mobj); +} + +static struct mobj *mobj_phys_init(paddr_t pa, size_t size, uint32_t mem_type, + enum buf_is_attr battr, + enum teecore_memtypes area_type) +{ + void *va = NULL; + struct mobj_phys *moph = NULL; + struct tee_mmap_region *map = NULL; + + if ((pa & CORE_MMU_USER_PARAM_MASK) || + (size & CORE_MMU_USER_PARAM_MASK)) { + DMSG("Expect %#x alignment", CORE_MMU_USER_PARAM_SIZE); + return NULL; + } + + if (pa) { + va = phys_to_virt(pa, area_type, size); + } else { + map = core_mmu_find_mapping_exclusive(area_type, size); + if (!map) + return NULL; + + pa = map->pa; + va = (void *)map->va; + } + + /* Only SDP memory may not have a virtual address */ + if (!va && battr != CORE_MEM_SDP_MEM) + return NULL; + + moph = calloc(1, sizeof(*moph)); + if (!moph) + return NULL; + + moph->battr = battr; + moph->mem_type = mem_type; + moph->mobj.size = size; + moph->mobj.ops = &mobj_phys_ops; + refcount_set(&moph->mobj.refc, 1); + moph->pa = pa; + moph->va = (vaddr_t)va; + + return &moph->mobj; +} + +struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t mem_type, + enum buf_is_attr battr) +{ + enum teecore_memtypes area_type; + + switch (battr) { + case CORE_MEM_TEE_RAM: + area_type = MEM_AREA_TEE_RAM_RW_DATA; + break; + case CORE_MEM_TA_RAM: + area_type = MEM_AREA_TA_RAM; + break; + case CORE_MEM_NSEC_SHM: + area_type = MEM_AREA_NSEC_SHM; + break; + case CORE_MEM_SDP_MEM: + area_type = MEM_AREA_SDP_MEM; + break; + case CORE_MEM_DEVICE: + area_type = MEM_AREA_IO_SEC; + break; + default: + DMSG("can't allocate with specified attribute"); + return NULL; + } + + return mobj_phys_init(pa, size, mem_type, battr, area_type); +} + +/* + * mobj_virt implementation + */ + +static void mobj_virt_assert_type(struct mobj *mobj); + +static void *mobj_virt_get_va(struct mobj *mobj, size_t offset, + size_t len __maybe_unused) +{ + mobj_virt_assert_type(mobj); + assert(mobj_check_offset_and_len(mobj, offset, len)); + + return (void *)(vaddr_t)offset; +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct mobj_ops mobj_virt_ops +__weak __relrodata_unpaged("mobj_virt_ops") = { + .get_va = mobj_virt_get_va, +}; + +static void mobj_virt_assert_type(struct mobj *mobj __maybe_unused) +{ + assert(mobj->ops == &mobj_virt_ops); +} + +struct mobj mobj_virt = { .ops = &mobj_virt_ops, .size = SIZE_MAX }; + +/* + * mobj_mm implementation + */ + +struct mobj_mm { + tee_mm_entry_t *mm; + struct mobj *parent_mobj; + struct mobj mobj; +}; + +static struct mobj_mm *to_mobj_mm(struct mobj *mobj); + +static size_t mobj_mm_offs(struct mobj *mobj, size_t offs) +{ + tee_mm_entry_t *mm = to_mobj_mm(mobj)->mm; + + return (mm->offset << mm->pool->shift) + offs; +} + +static void *mobj_mm_get_va(struct mobj *mobj, size_t offs, size_t len) +{ + return mobj_get_va(to_mobj_mm(mobj)->parent_mobj, + mobj_mm_offs(mobj, offs), len); +} + + +static TEE_Result mobj_mm_get_pa(struct mobj *mobj, size_t offs, + size_t granule, paddr_t *pa) +{ + return mobj_get_pa(to_mobj_mm(mobj)->parent_mobj, + mobj_mm_offs(mobj, offs), granule, pa); +} +DECLARE_KEEP_PAGER(mobj_mm_get_pa); + +static size_t mobj_mm_get_phys_offs(struct mobj *mobj, size_t granule) +{ + return mobj_get_phys_offs(to_mobj_mm(mobj)->parent_mobj, granule); +} + +static TEE_Result mobj_mm_get_mem_type(struct mobj *mobj, uint32_t *mem_type) +{ + return mobj_get_mem_type(to_mobj_mm(mobj)->parent_mobj, mem_type); +} + +static bool mobj_mm_matches(struct mobj *mobj, enum buf_is_attr attr) +{ + return mobj_matches(to_mobj_mm(mobj)->parent_mobj, attr); +} + +static void mobj_mm_free(struct mobj *mobj) +{ + struct mobj_mm *m = to_mobj_mm(mobj); + + tee_mm_free(m->mm); + free(m); +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct mobj_ops mobj_mm_ops __weak __relrodata_unpaged("mobj_mm_ops") = { + .get_va = mobj_mm_get_va, + .get_pa = mobj_mm_get_pa, + .get_phys_offs = mobj_mm_get_phys_offs, + .get_mem_type = mobj_mm_get_mem_type, + .matches = mobj_mm_matches, + .free = mobj_mm_free, +}; + +static struct mobj_mm *to_mobj_mm(struct mobj *mobj) +{ + assert(mobj->ops == &mobj_mm_ops); + return container_of(mobj, struct mobj_mm, mobj); +} + +struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size, + tee_mm_pool_t *pool) +{ + struct mobj_mm *m = calloc(1, sizeof(*m)); + + if (!m) + return NULL; + + m->mm = tee_mm_alloc(pool, size); + if (!m->mm) { + free(m); + return NULL; + } + + m->parent_mobj = mobj_parent; + m->mobj.size = size; + m->mobj.ops = &mobj_mm_ops; + refcount_set(&m->mobj.refc, 1); + + return &m->mobj; +} + + +/* + * mobj_shm implementation. mobj_shm represents buffer in predefined shm region + * - it is physically contiguous. + * - it is identified in static physical layout as MEM_AREA_NSEC_SHM. + * - it creates mobjs that match specific CORE_MEM_NSEC_SHM and non secure + * generic CORE_MEM_NON_SEC. + */ + +struct mobj_shm { + struct mobj mobj; + paddr_t pa; + uint64_t cookie; +}; + +static struct mobj_shm *to_mobj_shm(struct mobj *mobj); + +static void *mobj_shm_get_va(struct mobj *mobj, size_t offset, size_t len) +{ + struct mobj_shm *m = to_mobj_shm(mobj); + + if (!mobj_check_offset_and_len(mobj, offset, len)) + return NULL; + + return phys_to_virt(m->pa + offset, MEM_AREA_NSEC_SHM, + mobj->size - offset); +} + +static TEE_Result mobj_shm_get_pa(struct mobj *mobj, size_t offs, + size_t granule, paddr_t *pa) +{ + struct mobj_shm *m = to_mobj_shm(mobj); + paddr_t p; + + if (!pa || offs >= mobj->size) + return TEE_ERROR_GENERIC; + + p = m->pa + offs; + + if (granule) { + if (granule != SMALL_PAGE_SIZE && + granule != CORE_MMU_PGDIR_SIZE) + return TEE_ERROR_GENERIC; + p &= ~(granule - 1); + } + + *pa = p; + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(mobj_shm_get_pa); + +static size_t mobj_shm_get_phys_offs(struct mobj *mobj, size_t granule) +{ + assert(IS_POWER_OF_TWO(granule)); + return to_mobj_shm(mobj)->pa & (granule - 1); +} + +static bool mobj_shm_matches(struct mobj *mobj __unused, enum buf_is_attr attr) +{ + return attr == CORE_MEM_NSEC_SHM || attr == CORE_MEM_NON_SEC; +} + +static TEE_Result mobj_shm_get_mem_type(struct mobj *mobj __unused, + uint32_t *mem_type) +{ + if (!mem_type) + return TEE_ERROR_GENERIC; + + *mem_type = TEE_MATTR_MEM_TYPE_CACHED; + + return TEE_SUCCESS; +} + +static void mobj_shm_free(struct mobj *mobj) +{ + struct mobj_shm *m = to_mobj_shm(mobj); + + free(m); +} + +static uint64_t mobj_shm_get_cookie(struct mobj *mobj) +{ + return to_mobj_shm(mobj)->cookie; +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct mobj_ops mobj_shm_ops +__weak __relrodata_unpaged("mobj_shm_ops") = { + .get_va = mobj_shm_get_va, + .get_pa = mobj_shm_get_pa, + .get_phys_offs = mobj_shm_get_phys_offs, + .get_mem_type = mobj_shm_get_mem_type, + .matches = mobj_shm_matches, + .free = mobj_shm_free, + .get_cookie = mobj_shm_get_cookie, +}; + +static struct mobj_shm *to_mobj_shm(struct mobj *mobj) +{ + assert(mobj->ops == &mobj_shm_ops); + return container_of(mobj, struct mobj_shm, mobj); +} + +struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie) +{ + struct mobj_shm *m; + + if (!core_pbuf_is(CORE_MEM_NSEC_SHM, pa, size)) + return NULL; + + m = calloc(1, sizeof(*m)); + if (!m) + return NULL; + + m->mobj.size = size; + m->mobj.ops = &mobj_shm_ops; + m->mobj.phys_granule = SMALL_PAGE_SIZE; + refcount_set(&m->mobj.refc, 1); + m->pa = pa; + m->cookie = cookie; + + return &m->mobj; +} + +#ifdef CFG_PAGED_USER_TA +/* + * mobj_seccpy_shm implementation + */ + +struct mobj_seccpy_shm { + struct user_ta_ctx *utc; + vaddr_t va; + struct mobj mobj; + struct fobj *fobj; +}; + +static bool __maybe_unused mobj_is_seccpy_shm(struct mobj *mobj); + +static struct mobj_seccpy_shm *to_mobj_seccpy_shm(struct mobj *mobj) +{ + assert(mobj_is_seccpy_shm(mobj)); + return container_of(mobj, struct mobj_seccpy_shm, mobj); +} + +static void *mobj_seccpy_shm_get_va(struct mobj *mobj, size_t offs, size_t len) +{ + struct mobj_seccpy_shm *m = to_mobj_seccpy_shm(mobj); + + if (&m->utc->ta_ctx.ts_ctx != thread_get_tsd()->ctx) + return NULL; + + if (!mobj_check_offset_and_len(mobj, offs, len)) + return NULL; + return (void *)(m->va + offs); +} + +static bool mobj_seccpy_shm_matches(struct mobj *mobj __maybe_unused, + enum buf_is_attr attr) +{ + assert(mobj_is_seccpy_shm(mobj)); + + return attr == CORE_MEM_SEC || attr == CORE_MEM_TEE_RAM; +} + +static void mobj_seccpy_shm_free(struct mobj *mobj) +{ + struct mobj_seccpy_shm *m = to_mobj_seccpy_shm(mobj); + + tee_pager_rem_um_region(&m->utc->uctx, m->va, mobj->size); + vm_rem_rwmem(&m->utc->uctx, mobj, m->va); + fobj_put(m->fobj); + free(m); +} + +static struct fobj *mobj_seccpy_shm_get_fobj(struct mobj *mobj) +{ + return fobj_get(to_mobj_seccpy_shm(mobj)->fobj); +} + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct mobj_ops mobj_seccpy_shm_ops +__weak __relrodata_unpaged("mobj_seccpy_shm_ops") = { + .get_va = mobj_seccpy_shm_get_va, + .matches = mobj_seccpy_shm_matches, + .free = mobj_seccpy_shm_free, + .get_fobj = mobj_seccpy_shm_get_fobj, +}; + +static bool mobj_is_seccpy_shm(struct mobj *mobj) +{ + return mobj && mobj->ops == &mobj_seccpy_shm_ops; +} + +struct mobj *mobj_seccpy_shm_alloc(size_t size) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + struct mobj_seccpy_shm *m; + struct user_ta_ctx *utc; + vaddr_t va = 0; + + if (!is_user_ta_ctx(tsd->ctx)) + return NULL; + utc = to_user_ta_ctx(tsd->ctx); + + m = calloc(1, sizeof(*m)); + if (!m) + return NULL; + + m->mobj.size = size; + m->mobj.ops = &mobj_seccpy_shm_ops; + refcount_set(&m->mobj.refc, 1); + + if (vm_add_rwmem(&utc->uctx, &m->mobj, &va) != TEE_SUCCESS) + goto bad; + + m->fobj = fobj_rw_paged_alloc(ROUNDUP(size, SMALL_PAGE_SIZE) / + SMALL_PAGE_SIZE); + if (tee_pager_add_um_region(&utc->uctx, va, m->fobj, + TEE_MATTR_PRW | TEE_MATTR_URW)) + goto bad; + + m->va = va; + m->utc = to_user_ta_ctx(tsd->ctx); + return &m->mobj; +bad: + if (va) + vm_rem_rwmem(&utc->uctx, &m->mobj, va); + fobj_put(m->fobj); + free(m); + return NULL; +} + + +#endif /*CFG_PAGED_USER_TA*/ + +struct mobj_with_fobj { + struct fobj *fobj; + struct file *file; + struct mobj mobj; + uint8_t mem_type; +}; + +const struct mobj_ops mobj_with_fobj_ops; + +struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file, + uint32_t mem_type) +{ + struct mobj_with_fobj *m = NULL; + + assert(!(mem_type & ~TEE_MATTR_MEM_TYPE_MASK)); + + if (!fobj) + return NULL; + if (mem_type > UINT8_MAX) + return NULL; + + m = calloc(1, sizeof(*m)); + if (!m) + return NULL; + + m->mobj.ops = &mobj_with_fobj_ops; + refcount_set(&m->mobj.refc, 1); + m->mobj.size = fobj->num_pages * SMALL_PAGE_SIZE; + m->mobj.phys_granule = SMALL_PAGE_SIZE; + m->fobj = fobj_get(fobj); + m->file = file_get(file); + m->mem_type = mem_type; + + return &m->mobj; +} + +static struct mobj_with_fobj *to_mobj_with_fobj(struct mobj *mobj) +{ + assert(mobj && mobj->ops == &mobj_with_fobj_ops); + + return container_of(mobj, struct mobj_with_fobj, mobj); +} + +static bool mobj_with_fobj_matches(struct mobj *mobj __maybe_unused, + enum buf_is_attr attr) +{ + assert(to_mobj_with_fobj(mobj)); + + /* + * All fobjs are supposed to be mapped secure so classify it as + * CORE_MEM_SEC. Stay out of CORE_MEM_TEE_RAM etc, if that information + * needed it can probably be carried in another way than to put the + * burden directly on fobj. + */ + return attr == CORE_MEM_SEC; +} + +static void mobj_with_fobj_free(struct mobj *mobj) +{ + struct mobj_with_fobj *m = to_mobj_with_fobj(mobj); + + fobj_put(m->fobj); + file_put(m->file); + free(m); +} + +static struct fobj *mobj_with_fobj_get_fobj(struct mobj *mobj) +{ + return fobj_get(to_mobj_with_fobj(mobj)->fobj); +} + +static TEE_Result mobj_with_fobj_get_mem_type(struct mobj *mobj, + uint32_t *mem_type) +{ + struct mobj_with_fobj *m = to_mobj_with_fobj(mobj); + + if (!mem_type) + return TEE_ERROR_GENERIC; + + *mem_type = m->mem_type; + + return TEE_SUCCESS; +} + +static TEE_Result mobj_with_fobj_get_pa(struct mobj *mobj, size_t offs, + size_t granule, paddr_t *pa) +{ + struct mobj_with_fobj *f = to_mobj_with_fobj(mobj); + paddr_t p = 0; + + if (!f->fobj->ops->get_pa) { + assert(mobj_is_paged(mobj)); + return TEE_ERROR_NOT_SUPPORTED; + } + + p = f->fobj->ops->get_pa(f->fobj, offs / SMALL_PAGE_SIZE) + + offs % SMALL_PAGE_SIZE; + + if (granule) { + if (granule != SMALL_PAGE_SIZE && + granule != CORE_MMU_PGDIR_SIZE) + return TEE_ERROR_GENERIC; + p &= ~(granule - 1); + } + + *pa = p; + + return TEE_SUCCESS; +} +DECLARE_KEEP_PAGER(mobj_with_fobj_get_pa); + +/* + * Note: this variable is weak just to ease breaking its dependency chain + * when added to the unpaged area. + */ +const struct mobj_ops mobj_with_fobj_ops +__weak __relrodata_unpaged("mobj_with_fobj_ops") = { + .matches = mobj_with_fobj_matches, + .free = mobj_with_fobj_free, + .get_fobj = mobj_with_fobj_get_fobj, + .get_mem_type = mobj_with_fobj_get_mem_type, + .get_pa = mobj_with_fobj_get_pa, +}; + +#ifdef CFG_PAGED_USER_TA +bool mobj_is_paged(struct mobj *mobj) +{ + if (mobj->ops == &mobj_seccpy_shm_ops) + return true; + + if (mobj->ops == &mobj_with_fobj_ops && + !to_mobj_with_fobj(mobj)->fobj->ops->get_pa) + return true; + + return false; +} +#endif /*CFG_PAGED_USER_TA*/ + +static TEE_Result mobj_init(void) +{ + mobj_sec_ddr = mobj_phys_alloc(tee_mm_sec_ddr.lo, + tee_mm_sec_ddr.size, + TEE_MATTR_MEM_TYPE_CACHED, + CORE_MEM_TA_RAM); + if (!mobj_sec_ddr) + panic("Failed to register secure ta ram"); + + if (IS_ENABLED(CFG_CORE_RWDATA_NOEXEC)) { + mobj_tee_ram_rx = mobj_phys_init(0, + VCORE_UNPG_RX_SZ, + TEE_MATTR_MEM_TYPE_CACHED, + CORE_MEM_TEE_RAM, + MEM_AREA_TEE_RAM_RX); + if (!mobj_tee_ram_rx) + panic("Failed to register tee ram rx"); + + mobj_tee_ram_rw = mobj_phys_init(0, + VCORE_UNPG_RW_SZ, + TEE_MATTR_MEM_TYPE_CACHED, + CORE_MEM_TEE_RAM, + MEM_AREA_TEE_RAM_RW_DATA); + if (!mobj_tee_ram_rw) + panic("Failed to register tee ram rw"); + } else { + mobj_tee_ram_rw = mobj_phys_init(TEE_RAM_START, + VCORE_UNPG_RW_PA + + VCORE_UNPG_RW_SZ - + TEE_RAM_START, + TEE_MATTR_MEM_TYPE_CACHED, + CORE_MEM_TEE_RAM, + MEM_AREA_TEE_RAM_RW_DATA); + if (!mobj_tee_ram_rw) + panic("Failed to register tee ram"); + + mobj_tee_ram_rx = mobj_tee_ram_rw; + } + + return TEE_SUCCESS; +} + +driver_init_late(mobj_init); diff --git a/optee/optee_os/core/mm/sub.mk b/optee/optee_os/core/mm/sub.mk new file mode 100644 index 0000000..4f9647f --- /dev/null +++ b/optee/optee_os/core/mm/sub.mk @@ -0,0 +1,8 @@ +srcs-y += mobj.c +srcs-y += fobj.c +cflags-fobj.c-$(CFG_CORE_PAGE_TAG_AND_IV) := -Wno-missing-noreturn +srcs-y += file.c +srcs-y += vm.c +srcs-y += core_mmu.c +srcs-y += tee_mm.c + diff --git a/optee/optee_os/core/mm/tee_mm.c b/optee/optee_os/core/mm/tee_mm.c new file mode 100644 index 0000000..c61306d --- /dev/null +++ b/optee/optee_os/core/mm/tee_mm.c @@ -0,0 +1,394 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include + +static void *pmalloc(tee_mm_pool_t *pool, size_t size) +{ + if (pool->flags & TEE_MM_POOL_NEX_MALLOC) + return nex_malloc(size); + else + return malloc(size); +} + +static void *pcalloc(tee_mm_pool_t *pool, size_t num_el, size_t size) +{ + if (pool->flags & TEE_MM_POOL_NEX_MALLOC) + return nex_calloc(num_el, size); + else + return calloc(num_el, size); +} + +static void pfree(tee_mm_pool_t *pool, void *ptr) +{ + if (pool->flags & TEE_MM_POOL_NEX_MALLOC) + nex_free(ptr); + else + free(ptr); +} + +bool tee_mm_init(tee_mm_pool_t *pool, paddr_t lo, paddr_size_t size, + uint8_t shift, uint32_t flags) +{ + paddr_size_t rounded = 0; + paddr_t initial_lo = lo; + + if (pool == NULL) + return false; + + lo = ROUNDUP(lo, 1 << shift); + rounded = lo - initial_lo; + size = ROUNDDOWN(size - rounded, 1 << shift); + + assert(((uint64_t)size >> shift) < (uint64_t)UINT32_MAX); + + pool->lo = lo; + pool->size = size; + pool->shift = shift; + pool->flags = flags; + pool->entry = pcalloc(pool, 1, sizeof(tee_mm_entry_t)); + + if (pool->entry == NULL) + return false; + + if (pool->flags & TEE_MM_POOL_HI_ALLOC) + pool->entry->offset = ((size - 1) >> shift) + 1; + + pool->entry->pool = pool; + pool->lock = SPINLOCK_UNLOCK; + + 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); + pfree(pool, pool->entry); + pool->entry = NULL; +} + +static void tee_mm_add(tee_mm_entry_t *p, tee_mm_entry_t *nn) +{ + /* add to list */ + nn->next = p->next; + p->next = nn; +} + +#ifdef CFG_WITH_STATS +static size_t tee_mm_stats_allocated(tee_mm_pool_t *pool) +{ + tee_mm_entry_t *entry; + uint32_t sz = 0; + + if (!pool) + return 0; + + entry = pool->entry; + while (entry) { + sz += entry->size; + entry = entry->next; + } + + return sz << pool->shift; +} + +void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct malloc_stats *stats, + bool reset) +{ + uint32_t exceptions; + + if (!pool) + return; + + memset(stats, 0, sizeof(*stats)); + + exceptions = cpu_spin_lock_xsave(&pool->lock); + + stats->size = pool->size; + stats->max_allocated = pool->max_allocated; + stats->allocated = tee_mm_stats_allocated(pool); + + if (reset) + pool->max_allocated = 0; + cpu_spin_unlock_xrestore(&pool->lock, exceptions); +} + +static void update_max_allocated(tee_mm_pool_t *pool) +{ + size_t sz = tee_mm_stats_allocated(pool); + + if (sz > pool->max_allocated) + pool->max_allocated = sz; +} +#else /* CFG_WITH_STATS */ +static inline void update_max_allocated(tee_mm_pool_t *pool __unused) +{ +} +#endif /* CFG_WITH_STATS */ + +tee_mm_entry_t *tee_mm_alloc(tee_mm_pool_t *pool, size_t size) +{ + size_t psize; + tee_mm_entry_t *entry; + tee_mm_entry_t *nn; + size_t remaining; + uint32_t exceptions; + + /* Check that pool is initialized */ + if (!pool || !pool->entry) + return NULL; + + nn = pmalloc(pool, sizeof(tee_mm_entry_t)); + if (!nn) + return NULL; + + exceptions = cpu_spin_lock_xsave(&pool->lock); + + entry = pool->entry; + if (!size) + psize = 0; + else + psize = ((size - 1) >> pool->shift) + 1; + + /* 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 (entry->next == NULL) { + if (pool->flags & TEE_MM_POOL_HI_ALLOC) { + /* + * entry->offset is a "block count" offset from + * pool->lo. The byte offset is + * (entry->offset << pool->shift). + * In the HI_ALLOC allocation scheme the memory is + * allocated from the end of the segment, thus to + * validate there is sufficient memory validate that + * (entry->offset << pool->shift) > size. + */ + if ((entry->offset << pool->shift) < size) { + /* out of memory */ + goto err; + } + } else { + if (!pool->size) + panic("invalid pool"); + + remaining = pool->size; + remaining -= ((entry->offset + entry->size) << + pool->shift); + + if (remaining < size) { + /* out of memory */ + goto err; + } + } + } + + tee_mm_add(entry, nn); + + 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; + + update_max_allocated(pool); + + cpu_spin_unlock_xrestore(&pool->lock, exceptions); + return nn; +err: + cpu_spin_unlock_xrestore(&pool->lock, exceptions); + pfree(pool, nn); + return NULL; +} + +static inline bool fit_in_gap(tee_mm_pool_t *pool, tee_mm_entry_t *e, + paddr_t offslo, paddr_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->size) + /* memory not available */ + return false; + } else { + if (offslo < (e->offset + e->size) || + (e->next != NULL && (offshi > e->next->offset)) || + (offshi << pool->shift) > pool->size) + /* memory not available */ + return false; + } + + return true; +} + +tee_mm_entry_t *tee_mm_alloc2(tee_mm_pool_t *pool, paddr_t base, size_t size) +{ + tee_mm_entry_t *entry; + paddr_t offslo; + paddr_t offshi; + tee_mm_entry_t *mm; + uint32_t exceptions; + + /* Check that pool is initialized */ + if (!pool || !pool->entry) + return NULL; + + /* Wrapping and sanity check */ + if ((base + size) < base || base < pool->lo) + return NULL; + + mm = pmalloc(pool, sizeof(tee_mm_entry_t)); + if (!mm) + return NULL; + + exceptions = cpu_spin_lock_xsave(&pool->lock); + + 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)) + goto err; + + tee_mm_add(entry, mm); + + mm->offset = offslo; + mm->size = offshi - offslo; + mm->pool = pool; + + update_max_allocated(pool); + cpu_spin_unlock_xrestore(&pool->lock, exceptions); + return mm; +err: + cpu_spin_unlock_xrestore(&pool->lock, exceptions); + pfree(pool, mm); + return NULL; +} + +void tee_mm_free(tee_mm_entry_t *p) +{ + tee_mm_entry_t *entry; + uint32_t exceptions; + + if (!p || !p->pool) + return; + + exceptions = cpu_spin_lock_xsave(&p->pool->lock); + entry = p->pool->entry; + + /* remove entry from list */ + while (entry->next != NULL && entry->next != p) + entry = entry->next; + + if (!entry->next) + panic("invalid mm_entry"); + + entry->next = entry->next->next; + cpu_spin_unlock_xrestore(&p->pool->lock, exceptions); + + pfree(p->pool, p); +} + +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(const tee_mm_pool_t *pool, paddr_t addr) +{ + return pool && addr >= pool->lo && + addr <= (pool->lo + (pool->size - 1)); +} + +bool tee_mm_is_empty(tee_mm_pool_t *pool) +{ + bool ret; + uint32_t exceptions; + + if (pool == NULL || pool->entry == NULL) + return true; + + exceptions = cpu_spin_lock_xsave(&pool->lock); + ret = pool->entry == NULL || pool->entry->next == NULL; + cpu_spin_unlock_xrestore(&pool->lock, exceptions); + + return ret; +} + +/* Physical Secure DDR pool */ +tee_mm_pool_t tee_mm_sec_ddr; + +/* Virtual eSRAM pool */ +tee_mm_pool_t tee_mm_vcore; + +/* Shared memory pool */ +tee_mm_pool_t tee_mm_shm; + +tee_mm_entry_t *tee_mm_find(const tee_mm_pool_t *pool, paddr_t addr) +{ + tee_mm_entry_t *entry = pool->entry; + uint16_t offset = (addr - pool->lo) >> pool->shift; + uint32_t exceptions; + + if (!tee_mm_addr_is_within_range(pool, addr)) + return NULL; + + exceptions = cpu_spin_lock_xsave(&((tee_mm_pool_t *)pool)->lock); + + while (entry->next != NULL) { + entry = entry->next; + + if ((offset >= entry->offset) && + (offset < (entry->offset + entry->size))) { + cpu_spin_unlock_xrestore(&((tee_mm_pool_t *)pool)->lock, + exceptions); + return entry; + } + } + + cpu_spin_unlock_xrestore(&((tee_mm_pool_t *)pool)->lock, exceptions); + 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/optee/optee_os/core/mm/vm.c b/optee/optee_os/core/mm/vm.c new file mode 100644 index 0000000..1724d90 --- /dev/null +++ b/optee/optee_os/core/mm/vm.c @@ -0,0 +1,1402 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2021, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2021, Arm Limited + */ + +#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 + +#ifdef CFG_PL310 +#include +#endif + +#define TEE_MMU_UDATA_ATTR (TEE_MATTR_VALID_BLOCK | \ + TEE_MATTR_PRW | TEE_MATTR_URW | \ + TEE_MATTR_SECURE) +#define TEE_MMU_UCODE_ATTR (TEE_MATTR_VALID_BLOCK | \ + TEE_MATTR_PRW | TEE_MATTR_URWX | \ + TEE_MATTR_SECURE) + +#define TEE_MMU_UCACHE_DEFAULT_ATTR (TEE_MATTR_MEM_TYPE_CACHED << \ + TEE_MATTR_MEM_TYPE_SHIFT) + +static vaddr_t select_va_in_range(const struct vm_region *prev_reg, + const struct vm_region *next_reg, + const struct vm_region *reg, + size_t pad_begin, size_t pad_end, + size_t granul) +{ + const uint32_t f = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT | + VM_FLAG_SHAREABLE; + vaddr_t begin_va = 0; + vaddr_t end_va = 0; + size_t pad = 0; + + /* + * Insert an unmapped entry to separate regions with differing + * VM_FLAG_EPHEMERAL, VM_FLAG_PERMANENT or VM_FLAG_SHAREABLE + * bits as they never are to be contiguous with another region. + */ + if (prev_reg->flags && (prev_reg->flags & f) != (reg->flags & f)) + pad = SMALL_PAGE_SIZE; + else + pad = 0; + +#ifndef CFG_WITH_LPAE + if ((prev_reg->attr & TEE_MATTR_SECURE) != + (reg->attr & TEE_MATTR_SECURE)) + granul = CORE_MMU_PGDIR_SIZE; +#endif + + if (ADD_OVERFLOW(prev_reg->va, prev_reg->size, &begin_va) || + ADD_OVERFLOW(begin_va, pad_begin, &begin_va) || + ADD_OVERFLOW(begin_va, pad, &begin_va) || + ROUNDUP_OVERFLOW(begin_va, granul, &begin_va)) + return 0; + + if (reg->va) { + if (reg->va < begin_va) + return 0; + begin_va = reg->va; + } + + if (next_reg->flags && (next_reg->flags & f) != (reg->flags & f)) + pad = SMALL_PAGE_SIZE; + else + pad = 0; + +#ifndef CFG_WITH_LPAE + if ((next_reg->attr & TEE_MATTR_SECURE) != + (reg->attr & TEE_MATTR_SECURE)) + granul = CORE_MMU_PGDIR_SIZE; +#endif + if (ADD_OVERFLOW(begin_va, reg->size, &end_va) || + ADD_OVERFLOW(end_va, pad_end, &end_va) || + ADD_OVERFLOW(end_va, pad, &end_va) || + ROUNDUP_OVERFLOW(end_va, granul, &end_va)) + return 0; + + if (end_va <= next_reg->va) { + assert(!reg->va || reg->va == begin_va); + return begin_va; + } + + return 0; +} + +static TEE_Result alloc_pgt(struct user_mode_ctx *uctx) +{ + struct thread_specific_data *tsd __maybe_unused; + + if (!pgt_check_avail(uctx)) { + EMSG("Page tables are not available"); + return TEE_ERROR_OUT_OF_MEMORY; + } + +#ifdef CFG_PAGED_USER_TA + tsd = thread_get_tsd(); + if (uctx->ts_ctx == tsd->ctx) { + /* + * The supplied utc is the current active utc, allocate the + * page tables too as the pager needs to use them soon. + */ + pgt_get_all(uctx); + } +#endif + + return TEE_SUCCESS; +} + +static void rem_um_region(struct user_mode_ctx *uctx, struct vm_region *r) +{ + vaddr_t begin = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); + vaddr_t last = ROUNDUP(r->va + r->size, CORE_MMU_PGDIR_SIZE); + struct vm_region *r2 = NULL; + + if (mobj_is_paged(r->mobj)) { + tee_pager_rem_um_region(uctx, r->va, r->size); + } else { + pgt_clear_range(uctx, r->va, r->va + r->size); + tlbi_mva_range_asid(r->va, r->size, SMALL_PAGE_SIZE, + uctx->vm_info.asid); + } + + /* + * Figure out how much virtual memory on a CORE_MMU_PGDIR_SIZE + * grunalarity can be freed. Only completely unused + * CORE_MMU_PGDIR_SIZE ranges can be supplied to pgt_flush_range(). + * + * Note that there's is no margin for error here, both flushing too + * many or too few translation tables can be fatal. + */ + r2 = TAILQ_NEXT(r, link); + if (r2) + last = MIN(last, ROUNDDOWN(r2->va, CORE_MMU_PGDIR_SIZE)); + + r2 = TAILQ_PREV(r, vm_region_head, link); + if (r2) + begin = MAX(begin, + ROUNDUP(r2->va + r2->size, CORE_MMU_PGDIR_SIZE)); + + if (begin < last) + pgt_flush_range(uctx, begin, last); +} + +static void set_pa_range(struct core_mmu_table_info *ti, vaddr_t va, + paddr_t pa, size_t size, uint32_t attr) +{ + unsigned int end = core_mmu_va2idx(ti, va + size); + unsigned int idx = core_mmu_va2idx(ti, va); + + while (idx < end) { + core_mmu_set_entry(ti, idx, pa, attr); + idx++; + pa += BIT64(ti->shift); + } +} + +static void set_reg_in_table(struct core_mmu_table_info *ti, + struct vm_region *r) +{ + vaddr_t va = MAX(r->va, ti->va_base); + vaddr_t end = MIN(r->va + r->size, ti->va_base + CORE_MMU_PGDIR_SIZE); + size_t sz = MIN(end - va, mobj_get_phys_granule(r->mobj)); + size_t granule = BIT(ti->shift); + size_t offset = 0; + paddr_t pa = 0; + + while (va < end) { + offset = va - r->va + r->offset; + if (mobj_get_pa(r->mobj, offset, granule, &pa)) + panic("Failed to get PA"); + set_pa_range(ti, va, pa, sz, r->attr); + va += sz; + } +} + +static void set_um_region(struct user_mode_ctx *uctx, struct vm_region *r) +{ + struct pgt *p = SLIST_FIRST(&uctx->pgt_cache); + struct core_mmu_table_info ti = { }; + + assert(!mobj_is_paged(r->mobj)); + + core_mmu_set_info_table(&ti, CORE_MMU_PGDIR_LEVEL, 0, NULL); + + if (p) { + /* All the pgts are already allocated, update in place */ + do { + ti.va_base = p->vabase; + ti.table = p->tbl; + set_reg_in_table(&ti, r); + p = SLIST_NEXT(p, link); + } while (p); + } else { + /* + * We may have a few pgts in the cache list, update the + * ones found. + */ + for (ti.va_base = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); + ti.va_base < r->va + r->size; + ti.va_base += CORE_MMU_PGDIR_SIZE) { + p = pgt_pop_from_cache_list(ti.va_base, uctx->ts_ctx); + if (!p) + continue; + ti.table = p->tbl; + set_reg_in_table(&ti, r); + pgt_push_to_cache_list(p); + } + } +} + +static TEE_Result umap_add_region(struct vm_info *vmi, struct vm_region *reg, + size_t pad_begin, size_t pad_end, + size_t align) +{ + struct vm_region dummy_first_reg = { }; + struct vm_region dummy_last_reg = { }; + struct vm_region *r = NULL; + struct vm_region *prev_r = NULL; + vaddr_t va_range_base = 0; + size_t va_range_size = 0; + size_t granul; + vaddr_t va = 0; + size_t offs_plus_size = 0; + + core_mmu_get_user_va_range(&va_range_base, &va_range_size); + dummy_first_reg.va = va_range_base; + dummy_last_reg.va = va_range_base + va_range_size; + + /* Check alignment, it has to be at least SMALL_PAGE based */ + if ((reg->va | reg->size | pad_begin | pad_end) & SMALL_PAGE_MASK) + return TEE_ERROR_ACCESS_CONFLICT; + + /* Check that the mobj is defined for the entire range */ + if (ADD_OVERFLOW(reg->offset, reg->size, &offs_plus_size)) + return TEE_ERROR_BAD_PARAMETERS; + if (offs_plus_size > ROUNDUP(reg->mobj->size, SMALL_PAGE_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + + granul = MAX(align, SMALL_PAGE_SIZE); + if (!IS_POWER_OF_TWO(granul)) + return TEE_ERROR_BAD_PARAMETERS; + + prev_r = &dummy_first_reg; + TAILQ_FOREACH(r, &vmi->regions, link) { + va = select_va_in_range(prev_r, r, reg, pad_begin, pad_end, + granul); + if (va) { + reg->va = va; + TAILQ_INSERT_BEFORE(r, reg, link); + return TEE_SUCCESS; + } + prev_r = r; + } + + r = TAILQ_LAST(&vmi->regions, vm_region_head); + if (!r) + r = &dummy_first_reg; + va = select_va_in_range(r, &dummy_last_reg, reg, pad_begin, pad_end, + granul); + if (va) { + reg->va = va; + TAILQ_INSERT_TAIL(&vmi->regions, reg, link); + return TEE_SUCCESS; + } + + return TEE_ERROR_ACCESS_CONFLICT; +} + +TEE_Result vm_map_pad(struct user_mode_ctx *uctx, vaddr_t *va, size_t len, + uint32_t prot, uint32_t flags, struct mobj *mobj, + size_t offs, size_t pad_begin, size_t pad_end, + size_t align) +{ + TEE_Result res = TEE_SUCCESS; + struct vm_region *reg = NULL; + uint32_t attr = 0; + + /* Check If the memory parameters are correct.*/ + if (!(prot & TEE_MATTR_DEVICE) && (prot & ~TEE_MATTR_PROT_MASK)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Check If the device memory parameters are correct.*/ + if (prot & TEE_MATTR_DEVICE) { + /* Only StMM SPs can map device memory.*/ + if (!is_stmm_ctx(uctx->ts_ctx)) + return TEE_ERROR_BAD_PARAMETERS; + + if ((prot & ~TEE_MATTR_DEVICE_PROT_MASK)) + return TEE_ERROR_BAD_PARAMETERS; + } + + reg = calloc(1, sizeof(*reg)); + if (!reg) + return TEE_ERROR_OUT_OF_MEMORY; + + if (!mobj_is_paged(mobj)) { + uint32_t mem_type = 0; + + res = mobj_get_mem_type(mobj, &mem_type); + if (res) + goto err_free_reg; + attr |= mem_type << TEE_MATTR_MEM_TYPE_SHIFT; + } + attr |= TEE_MATTR_VALID_BLOCK; + if (mobj_is_secure(mobj)) + attr |= TEE_MATTR_SECURE; + + reg->mobj = mobj_get(mobj); + reg->offset = offs; + reg->va = *va; + reg->size = ROUNDUP(len, SMALL_PAGE_SIZE); + reg->attr = attr | prot; + reg->flags = flags; + + res = umap_add_region(&uctx->vm_info, reg, pad_begin, pad_end, align); + if (res) + goto err_put_mobj; + + res = alloc_pgt(uctx); + if (res) + goto err_rem_reg; + + if (mobj_is_paged(mobj)) { + struct fobj *fobj = mobj_get_fobj(mobj); + + if (!fobj) { + res = TEE_ERROR_GENERIC; + goto err_rem_reg; + } + + res = tee_pager_add_um_region(uctx, reg->va, fobj, prot); + fobj_put(fobj); + if (res) + goto err_rem_reg; + } else { + set_um_region(uctx, reg); + } + + /* + * If the context currently is active set it again to update + * the mapping. + */ + if (thread_get_tsd()->ctx == uctx->ts_ctx) + vm_set_ctx(uctx->ts_ctx); + + *va = reg->va; + + return TEE_SUCCESS; + +err_rem_reg: + TAILQ_REMOVE(&uctx->vm_info.regions, reg, link); +err_put_mobj: + mobj_put(reg->mobj); +err_free_reg: + free(reg); + return res; +} + +static struct vm_region *find_vm_region(struct vm_info *vm_info, vaddr_t va) +{ + struct vm_region *r = NULL; + + TAILQ_FOREACH(r, &vm_info->regions, link) + if (va >= r->va && va < r->va + r->size) + return r; + + return NULL; +} + +static bool va_range_is_contiguous(struct vm_region *r0, vaddr_t va, + size_t len, + bool (*cmp_regs)(const struct vm_region *r0, + const struct vm_region *r, + const struct vm_region *rn)) +{ + struct vm_region *r = r0; + vaddr_t end_va = 0; + + if (ADD_OVERFLOW(va, len, &end_va)) + return false; + + while (true) { + struct vm_region *r_next = TAILQ_NEXT(r, link); + vaddr_t r_end_va = r->va + r->size; + + if (r_end_va >= end_va) + return true; + if (!r_next) + return false; + if (r_end_va != r_next->va) + return false; + if (cmp_regs && !cmp_regs(r0, r, r_next)) + return false; + r = r_next; + } +} + +static TEE_Result split_vm_region(struct user_mode_ctx *uctx, + struct vm_region *r, vaddr_t va) +{ + struct vm_region *r2 = NULL; + size_t diff = va - r->va; + + assert(diff && diff < r->size); + + r2 = calloc(1, sizeof(*r2)); + if (!r2) + return TEE_ERROR_OUT_OF_MEMORY; + + if (mobj_is_paged(r->mobj)) { + TEE_Result res = tee_pager_split_um_region(uctx, va); + + if (res) { + free(r2); + return res; + } + } + + r2->mobj = mobj_get(r->mobj); + r2->offset = r->offset + diff; + r2->va = va; + r2->size = r->size - diff; + r2->attr = r->attr; + r2->flags = r->flags; + + r->size = diff; + + TAILQ_INSERT_AFTER(&uctx->vm_info.regions, r, r2, link); + + return TEE_SUCCESS; +} + +static TEE_Result split_vm_range(struct user_mode_ctx *uctx, vaddr_t va, + size_t len, + bool (*cmp_regs)(const struct vm_region *r0, + const struct vm_region *r, + const struct vm_region *rn), + struct vm_region **r0_ret) +{ + TEE_Result res = TEE_SUCCESS; + struct vm_region *r = NULL; + vaddr_t end_va = 0; + + if ((va | len) & SMALL_PAGE_MASK) + return TEE_ERROR_BAD_PARAMETERS; + + if (ADD_OVERFLOW(va, len, &end_va)) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * Find first vm_region in range and check that the entire range is + * contiguous. + */ + r = find_vm_region(&uctx->vm_info, va); + if (!r || !va_range_is_contiguous(r, va, len, cmp_regs)) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * If needed split regions so that va and len covers only complete + * regions. + */ + if (va != r->va) { + res = split_vm_region(uctx, r, va); + if (res) + return res; + r = TAILQ_NEXT(r, link); + } + + *r0_ret = r; + r = find_vm_region(&uctx->vm_info, va + len - 1); + if (!r) + return TEE_ERROR_BAD_PARAMETERS; + if (end_va != r->va + r->size) { + res = split_vm_region(uctx, r, end_va); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +static void merge_vm_range(struct user_mode_ctx *uctx, vaddr_t va, size_t len) +{ + struct vm_region *r_next = NULL; + struct vm_region *r = NULL; + vaddr_t end_va = 0; + + if (ADD_OVERFLOW(va, len, &end_va)) + return; + + tee_pager_merge_um_region(uctx, va, len); + + for (r = TAILQ_FIRST(&uctx->vm_info.regions);; r = r_next) { + r_next = TAILQ_NEXT(r, link); + if (!r_next) + return; + + /* Try merging with the region just before va */ + if (r->va + r->size < va) + continue; + + /* + * If r->va is well past our range we're done. + * Note that if it's just the page after our range we'll + * try to merge. + */ + if (r->va > end_va) + return; + + if (r->va + r->size != r_next->va) + continue; + if (r->mobj != r_next->mobj || + r->flags != r_next->flags || + r->attr != r_next->attr) + continue; + if (r->offset + r->size != r_next->offset) + continue; + + TAILQ_REMOVE(&uctx->vm_info.regions, r_next, link); + r->size += r_next->size; + mobj_put(r_next->mobj); + free(r_next); + r_next = r; + } +} + +static bool cmp_region_for_remap(const struct vm_region *r0, + const struct vm_region *r, + const struct vm_region *rn) +{ + /* + * All the essentionals has to match for remap to make sense. The + * essentials are, mobj/fobj, attr, flags and the offset should be + * contiguous. + * + * Note that vm_remap() depends on mobj/fobj to be the same. + */ + return r0->flags == r->flags && r0->attr == r->attr && + r0->mobj == r->mobj && rn->offset == r->offset + r->size; +} + +TEE_Result vm_remap(struct user_mode_ctx *uctx, vaddr_t *new_va, vaddr_t old_va, + size_t len, size_t pad_begin, size_t pad_end) +{ + struct vm_region_head regs = TAILQ_HEAD_INITIALIZER(regs); + TEE_Result res = TEE_SUCCESS; + struct vm_region *r0 = NULL; + struct vm_region *r = NULL; + struct vm_region *r_next = NULL; + struct vm_region *r_last = NULL; + struct vm_region *r_first = NULL; + struct fobj *fobj = NULL; + vaddr_t next_va = 0; + + assert(thread_get_tsd()->ctx == uctx->ts_ctx); + + if (!len || ((len | old_va) & SMALL_PAGE_MASK)) + return TEE_ERROR_BAD_PARAMETERS; + + res = split_vm_range(uctx, old_va, len, cmp_region_for_remap, &r0); + if (res) + return res; + + if (mobj_is_paged(r0->mobj)) { + fobj = mobj_get_fobj(r0->mobj); + if (!fobj) + panic(); + } + + for (r = r0; r; r = r_next) { + if (r->va + r->size > old_va + len) + break; + r_next = TAILQ_NEXT(r, link); + rem_um_region(uctx, r); + TAILQ_REMOVE(&uctx->vm_info.regions, r, link); + TAILQ_INSERT_TAIL(®s, r, link); + } + + /* + * Synchronize change to translation tables. Even though the pager + * case unmaps immediately we may still free a translation table. + */ + vm_set_ctx(uctx->ts_ctx); + + r_first = TAILQ_FIRST(®s); + while (!TAILQ_EMPTY(®s)) { + r = TAILQ_FIRST(®s); + TAILQ_REMOVE(®s, r, link); + if (r_last) { + r->va = r_last->va + r_last->size; + res = umap_add_region(&uctx->vm_info, r, 0, 0, 0); + } else { + r->va = *new_va; + res = umap_add_region(&uctx->vm_info, r, pad_begin, + pad_end + len - r->size, 0); + } + if (!res) { + r_last = r; + res = alloc_pgt(uctx); + } + if (!res) { + if (!fobj) + set_um_region(uctx, r); + else + res = tee_pager_add_um_region(uctx, r->va, fobj, + r->attr); + } + + if (res) { + /* + * Something went wrong move all the recently added + * regions back to regs for later reinsertion at + * the original spot. + */ + struct vm_region *r_tmp = NULL; + struct vm_region *r_stop = NULL; + + if (r != r_last) { + /* + * umap_add_region() failed, move r back to + * regs before all the rest are moved back. + */ + TAILQ_INSERT_HEAD(®s, r, link); + } + if (r_last) + r_stop = TAILQ_NEXT(r_last, link); + for (r = r_first; r != r_stop; r = r_next) { + r_next = TAILQ_NEXT(r, link); + TAILQ_REMOVE(&uctx->vm_info.regions, r, link); + if (r_tmp) + TAILQ_INSERT_AFTER(®s, r_tmp, r, + link); + else + TAILQ_INSERT_HEAD(®s, r, link); + r_tmp = r; + } + + goto err_restore_map; + } + } + + fobj_put(fobj); + + vm_set_ctx(uctx->ts_ctx); + *new_va = r_first->va; + + return TEE_SUCCESS; + +err_restore_map: + next_va = old_va; + while (!TAILQ_EMPTY(®s)) { + r = TAILQ_FIRST(®s); + TAILQ_REMOVE(®s, r, link); + r->va = next_va; + next_va += r->size; + if (umap_add_region(&uctx->vm_info, r, 0, 0, 0)) + panic("Cannot restore mapping"); + if (alloc_pgt(uctx)) + panic("Cannot restore mapping"); + if (fobj) { + if (tee_pager_add_um_region(uctx, r->va, fobj, r->attr)) + panic("Cannot restore mapping"); + } else { + set_um_region(uctx, r); + } + } + fobj_put(fobj); + vm_set_ctx(uctx->ts_ctx); + + return res; +} + +static bool cmp_region_for_get_flags(const struct vm_region *r0, + const struct vm_region *r, + const struct vm_region *rn __unused) +{ + return r0->flags == r->flags; +} + +TEE_Result vm_get_flags(struct user_mode_ctx *uctx, vaddr_t va, size_t len, + uint32_t *flags) +{ + struct vm_region *r = NULL; + + if (!len || ((len | va) & SMALL_PAGE_MASK)) + return TEE_ERROR_BAD_PARAMETERS; + + r = find_vm_region(&uctx->vm_info, va); + if (!r) + return TEE_ERROR_BAD_PARAMETERS; + + if (!va_range_is_contiguous(r, va, len, cmp_region_for_get_flags)) + return TEE_ERROR_BAD_PARAMETERS; + + *flags = r->flags; + + return TEE_SUCCESS; +} + +static bool cmp_region_for_get_prot(const struct vm_region *r0, + const struct vm_region *r, + const struct vm_region *rn __unused) +{ + return (r0->attr & TEE_MATTR_PROT_MASK) == + (r->attr & TEE_MATTR_PROT_MASK); +} + +TEE_Result vm_get_prot(struct user_mode_ctx *uctx, vaddr_t va, size_t len, + uint16_t *prot) +{ + struct vm_region *r = NULL; + + if (!len || ((len | va) & SMALL_PAGE_MASK)) + return TEE_ERROR_BAD_PARAMETERS; + + r = find_vm_region(&uctx->vm_info, va); + if (!r) + return TEE_ERROR_BAD_PARAMETERS; + + if (!va_range_is_contiguous(r, va, len, cmp_region_for_get_prot)) + return TEE_ERROR_BAD_PARAMETERS; + + *prot = r->attr & TEE_MATTR_PROT_MASK; + + return TEE_SUCCESS; +} + +TEE_Result vm_set_prot(struct user_mode_ctx *uctx, vaddr_t va, size_t len, + uint32_t prot) +{ + TEE_Result res = TEE_SUCCESS; + struct vm_region *r0 = NULL; + struct vm_region *r = NULL; + bool was_writeable = false; + bool need_sync = false; + + assert(thread_get_tsd()->ctx == uctx->ts_ctx); + + if (prot & ~TEE_MATTR_PROT_MASK || !len) + return TEE_ERROR_BAD_PARAMETERS; + + res = split_vm_range(uctx, va, len, NULL, &r0); + if (res) + return res; + + for (r = r0; r; r = TAILQ_NEXT(r, link)) { + if (r->va + r->size > va + len) + break; + if (r->attr & (TEE_MATTR_UW | TEE_MATTR_PW)) + was_writeable = true; + + r->attr &= ~TEE_MATTR_PROT_MASK; + r->attr |= prot; + + if (!mobj_is_paged(r->mobj)) { + need_sync = true; + set_um_region(uctx, r); + /* + * Normally when set_um_region() is called we + * change from no mapping to some mapping, but in + * this case we change the permissions on an + * already present mapping so some TLB invalidation + * is needed. We also depend on the dsb() performed + * as part of the TLB invalidation. + */ + tlbi_mva_range_asid(r->va, r->size, SMALL_PAGE_SIZE, + uctx->vm_info.asid); + } + } + + for (r = r0; r; r = TAILQ_NEXT(r, link)) { + if (r->va + r->size > va + len) + break; + if (mobj_is_paged(r->mobj)) { + if (!tee_pager_set_um_region_attr(uctx, r->va, r->size, + prot)) + panic(); + } else if (was_writeable) { + cache_op_inner(DCACHE_AREA_CLEAN, (void *)r->va, + r->size); + } + + } + if (need_sync && was_writeable) + cache_op_inner(ICACHE_INVALIDATE, NULL, 0); + + merge_vm_range(uctx, va, len); + + return TEE_SUCCESS; +} + +static void umap_remove_region(struct vm_info *vmi, struct vm_region *reg) +{ + TAILQ_REMOVE(&vmi->regions, reg, link); + mobj_put(reg->mobj); + free(reg); +} + +TEE_Result vm_unmap(struct user_mode_ctx *uctx, vaddr_t va, size_t len) +{ + TEE_Result res = TEE_SUCCESS; + struct vm_region *r = NULL; + struct vm_region *r_next = NULL; + size_t end_va = 0; + size_t unmap_end_va = 0; + size_t l = 0; + + assert(thread_get_tsd()->ctx == uctx->ts_ctx); + + if (ROUNDUP_OVERFLOW(len, SMALL_PAGE_SIZE, &l)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!l || (va & SMALL_PAGE_MASK)) + return TEE_ERROR_BAD_PARAMETERS; + + if (ADD_OVERFLOW(va, l, &end_va)) + return TEE_ERROR_BAD_PARAMETERS; + + res = split_vm_range(uctx, va, l, NULL, &r); + if (res) + return res; + + while (true) { + r_next = TAILQ_NEXT(r, link); + unmap_end_va = r->va + r->size; + rem_um_region(uctx, r); + umap_remove_region(&uctx->vm_info, r); + if (!r_next || unmap_end_va == end_va) + break; + r = r_next; + } + + return TEE_SUCCESS; +} + +static TEE_Result map_kinit(struct user_mode_ctx *uctx) +{ + TEE_Result res = TEE_SUCCESS; + struct mobj *mobj = NULL; + size_t offs = 0; + vaddr_t va = 0; + size_t sz = 0; + uint32_t prot = 0; + + thread_get_user_kcode(&mobj, &offs, &va, &sz); + if (sz) { + prot = TEE_MATTR_PRX; + if (IS_ENABLED(CFG_CORE_BTI)) + prot |= TEE_MATTR_GUARDED; + res = vm_map(uctx, &va, sz, prot, VM_FLAG_PERMANENT, + mobj, offs); + if (res) + return res; + } + + thread_get_user_kdata(&mobj, &offs, &va, &sz); + if (sz) + return vm_map(uctx, &va, sz, TEE_MATTR_PRW, VM_FLAG_PERMANENT, + mobj, offs); + + return TEE_SUCCESS; +} + +TEE_Result vm_info_init(struct user_mode_ctx *uctx, struct ts_ctx *ts_ctx) +{ + TEE_Result res; + uint32_t asid = asid_alloc(); + + if (!asid) { + DMSG("Failed to allocate ASID"); + return TEE_ERROR_GENERIC; + } + + memset(uctx, 0, sizeof(*uctx)); + TAILQ_INIT(&uctx->vm_info.regions); + SLIST_INIT(&uctx->pgt_cache); + uctx->vm_info.asid = asid; + uctx->ts_ctx = ts_ctx; + + res = map_kinit(uctx); + if (res) + vm_info_final(uctx); + return res; +} + +void vm_clean_param(struct user_mode_ctx *uctx) +{ + struct vm_region *next_r; + struct vm_region *r; + + TAILQ_FOREACH_SAFE(r, &uctx->vm_info.regions, link, next_r) { + if (r->flags & VM_FLAG_EPHEMERAL) { + rem_um_region(uctx, r); + umap_remove_region(&uctx->vm_info, r); + } + } +} + +static void check_param_map_empty(struct user_mode_ctx *uctx __maybe_unused) +{ + struct vm_region *r = NULL; + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) + assert(!(r->flags & VM_FLAG_EPHEMERAL)); +} + +static TEE_Result param_mem_to_user_va(struct user_mode_ctx *uctx, + struct param_mem *mem, void **user_va) +{ + struct vm_region *region = NULL; + + TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { + vaddr_t va = 0; + size_t phys_offs = 0; + + if (!(region->flags & VM_FLAG_EPHEMERAL)) + continue; + if (mem->mobj != region->mobj) + continue; + + phys_offs = mobj_get_phys_offs(mem->mobj, + CORE_MMU_USER_PARAM_SIZE); + phys_offs += mem->offs; + if (phys_offs < region->offset) + continue; + if (phys_offs >= (region->offset + region->size)) + continue; + va = region->va + phys_offs - region->offset; + *user_va = (void *)va; + return TEE_SUCCESS; + } + return TEE_ERROR_GENERIC; +} + +static int cmp_param_mem(const void *a0, const void *a1) +{ + const struct param_mem *m1 = a1; + const struct param_mem *m0 = a0; + int ret; + + /* Make sure that invalid param_mem are placed last in the array */ + if (!m0->mobj && !m1->mobj) + return 0; + if (!m0->mobj) + return 1; + if (!m1->mobj) + return -1; + + ret = CMP_TRILEAN(mobj_is_secure(m0->mobj), mobj_is_secure(m1->mobj)); + if (ret) + return ret; + + ret = CMP_TRILEAN((vaddr_t)m0->mobj, (vaddr_t)m1->mobj); + if (ret) + return ret; + + ret = CMP_TRILEAN(m0->offs, m1->offs); + if (ret) + return ret; + + return CMP_TRILEAN(m0->size, m1->size); +} + +TEE_Result vm_map_param(struct user_mode_ctx *uctx, struct tee_ta_param *param, + void *param_va[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + size_t n; + size_t m; + struct param_mem mem[TEE_NUM_PARAMS]; + + memset(mem, 0, sizeof(mem)); + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); + size_t phys_offs; + + if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && + param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && + param_type != TEE_PARAM_TYPE_MEMREF_INOUT) + continue; + phys_offs = mobj_get_phys_offs(param->u[n].mem.mobj, + CORE_MMU_USER_PARAM_SIZE); + mem[n].mobj = param->u[n].mem.mobj; + mem[n].offs = ROUNDDOWN(phys_offs + param->u[n].mem.offs, + CORE_MMU_USER_PARAM_SIZE); + mem[n].size = ROUNDUP(phys_offs + param->u[n].mem.offs - + mem[n].offs + param->u[n].mem.size, + CORE_MMU_USER_PARAM_SIZE); + /* + * For size 0 (raw pointer parameter), add minimum size + * value to allow address to be mapped + */ + if (!mem[n].size) + mem[n].size = CORE_MMU_USER_PARAM_SIZE; + } + + /* + * Sort arguments so NULL mobj is last, secure mobjs first, then by + * mobj pointer value since those entries can't be merged either, + * finally by offset. + * + * This should result in a list where all mergeable entries are + * next to each other and unused/invalid entries are at the end. + */ + qsort(mem, TEE_NUM_PARAMS, sizeof(struct param_mem), cmp_param_mem); + + for (n = 1, m = 0; n < TEE_NUM_PARAMS && mem[n].mobj; n++) { + if (mem[n].mobj == mem[m].mobj && + (mem[n].offs == (mem[m].offs + mem[m].size) || + core_is_buffer_intersect(mem[m].offs, mem[m].size, + mem[n].offs, mem[n].size))) { + mem[m].size = mem[n].offs + mem[n].size - mem[m].offs; + continue; + } + m++; + if (n != m) + mem[m] = mem[n]; + } + /* + * We'd like 'm' to be the number of valid entries. Here 'm' is the + * index of the last valid entry if the first entry is valid, else + * 0. + */ + if (mem[0].mobj) + m++; + + check_param_map_empty(uctx); + + for (n = 0; n < m; n++) { + vaddr_t va = 0; + + res = vm_map(uctx, &va, mem[n].size, + TEE_MATTR_PRW | TEE_MATTR_URW, + VM_FLAG_EPHEMERAL | VM_FLAG_SHAREABLE, + mem[n].mobj, mem[n].offs); + if (res) + goto out; + } + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); + + if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && + param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && + param_type != TEE_PARAM_TYPE_MEMREF_INOUT) + continue; + if (!param->u[n].mem.mobj) + continue; + + res = param_mem_to_user_va(uctx, ¶m->u[n].mem, + param_va + n); + if (res != TEE_SUCCESS) + goto out; + } + + res = alloc_pgt(uctx); +out: + if (res) + vm_clean_param(uctx); + + return res; +} + +TEE_Result vm_add_rwmem(struct user_mode_ctx *uctx, struct mobj *mobj, + vaddr_t *va) +{ + TEE_Result res = TEE_SUCCESS; + struct vm_region *reg = NULL; + + if (!mobj_is_secure(mobj) || !mobj_is_paged(mobj)) + return TEE_ERROR_BAD_PARAMETERS; + + reg = calloc(1, sizeof(*reg)); + if (!reg) + return TEE_ERROR_OUT_OF_MEMORY; + + reg->mobj = mobj; + reg->offset = 0; + reg->va = 0; + reg->size = ROUNDUP(mobj->size, SMALL_PAGE_SIZE); + reg->attr = TEE_MATTR_SECURE; + + res = umap_add_region(&uctx->vm_info, reg, 0, 0, 0); + if (res) { + free(reg); + return res; + } + + res = alloc_pgt(uctx); + if (res) + umap_remove_region(&uctx->vm_info, reg); + else + *va = reg->va; + + return res; +} + +void vm_rem_rwmem(struct user_mode_ctx *uctx, struct mobj *mobj, vaddr_t va) +{ + struct vm_region *r = NULL; + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { + if (r->mobj == mobj && r->va == va) { + rem_um_region(uctx, r); + umap_remove_region(&uctx->vm_info, r); + return; + } + } +} + +void vm_info_final(struct user_mode_ctx *uctx) +{ + if (!uctx->vm_info.asid) + return; + + pgt_flush(uctx); + tee_pager_rem_um_regions(uctx); + + /* clear MMU entries to avoid clash when asid is reused */ + tlbi_asid(uctx->vm_info.asid); + + asid_free(uctx->vm_info.asid); + while (!TAILQ_EMPTY(&uctx->vm_info.regions)) + umap_remove_region(&uctx->vm_info, + TAILQ_FIRST(&uctx->vm_info.regions)); + memset(&uctx->vm_info, 0, sizeof(uctx->vm_info)); +} + +/* return true only if buffer fits inside TA private memory */ +bool vm_buf_is_inside_um_private(const struct user_mode_ctx *uctx, + const void *va, size_t size) +{ + struct vm_region *r = NULL; + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { + if (r->flags & VM_FLAGS_NONPRIV) + continue; + if (core_is_buffer_inside((vaddr_t)va, size, r->va, r->size)) + return true; + } + + return false; +} + +/* return true only if buffer intersects TA private memory */ +bool vm_buf_intersects_um_private(const struct user_mode_ctx *uctx, + const void *va, size_t size) +{ + struct vm_region *r = NULL; + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { + if (r->attr & VM_FLAGS_NONPRIV) + continue; + if (core_is_buffer_intersect((vaddr_t)va, size, r->va, r->size)) + return true; + } + + return false; +} + +TEE_Result vm_buf_to_mboj_offs(const struct user_mode_ctx *uctx, + const void *va, size_t size, + struct mobj **mobj, size_t *offs) +{ + struct vm_region *r = NULL; + + TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { + if (!r->mobj) + continue; + if (core_is_buffer_inside((vaddr_t)va, size, r->va, r->size)) { + size_t poffs; + + poffs = mobj_get_phys_offs(r->mobj, + CORE_MMU_USER_PARAM_SIZE); + *mobj = r->mobj; + *offs = (vaddr_t)va - r->va + r->offset - poffs; + return TEE_SUCCESS; + } + } + + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result tee_mmu_user_va2pa_attr(const struct user_mode_ctx *uctx, + void *ua, paddr_t *pa, uint32_t *attr) +{ + struct vm_region *region = NULL; + + TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { + if (!core_is_buffer_inside((vaddr_t)ua, 1, region->va, + region->size)) + continue; + + if (pa) { + TEE_Result res; + paddr_t p; + size_t offset; + size_t granule; + + /* + * mobj and input user address may each include + * a specific offset-in-granule position. + * Drop both to get target physical page base + * address then apply only user address + * offset-in-granule. + * Mapping lowest granule is the small page. + */ + granule = MAX(region->mobj->phys_granule, + (size_t)SMALL_PAGE_SIZE); + assert(!granule || IS_POWER_OF_TWO(granule)); + + offset = region->offset + + ROUNDDOWN((vaddr_t)ua - region->va, granule); + + res = mobj_get_pa(region->mobj, offset, granule, &p); + if (res != TEE_SUCCESS) + return res; + + *pa = p | ((vaddr_t)ua & (granule - 1)); + } + if (attr) + *attr = region->attr; + + return TEE_SUCCESS; + } + + return TEE_ERROR_ACCESS_DENIED; +} + +TEE_Result vm_va2pa(const struct user_mode_ctx *uctx, void *ua, paddr_t *pa) +{ + return tee_mmu_user_va2pa_attr(uctx, ua, pa, NULL); +} + +void *vm_pa2va(const struct user_mode_ctx *uctx, paddr_t pa, size_t pa_size) +{ + paddr_t p = 0; + struct vm_region *region = NULL; + + TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { + size_t granule = 0; + size_t size = 0; + size_t ofs = 0; + + /* pa2va is expected only for memory tracked through mobj */ + if (!region->mobj) + continue; + + /* Physically granulated memory object must be scanned */ + granule = region->mobj->phys_granule; + assert(!granule || IS_POWER_OF_TWO(granule)); + + for (ofs = region->offset; ofs < region->size; ofs += size) { + + if (granule) { + /* From current offset to buffer/granule end */ + size = granule - (ofs & (granule - 1)); + + if (size > (region->size - ofs)) + size = region->size - ofs; + } else { + size = region->size; + } + + if (mobj_get_pa(region->mobj, ofs, granule, &p)) + continue; + + if (core_is_buffer_inside(pa, pa_size, p, size)) { + /* Remove region offset (mobj phys offset) */ + ofs -= region->offset; + /* Get offset-in-granule */ + p = pa - p; + + return (void *)(region->va + ofs + (vaddr_t)p); + } + } + } + + return NULL; +} + +TEE_Result vm_check_access_rights(const struct user_mode_ctx *uctx, + uint32_t flags, uaddr_t uaddr, size_t len) +{ + uaddr_t a = 0; + uaddr_t end_addr = 0; + size_t addr_incr = MIN(CORE_MMU_USER_CODE_SIZE, + CORE_MMU_USER_PARAM_SIZE); + + if (ADD_OVERFLOW(uaddr, len, &end_addr)) + return TEE_ERROR_ACCESS_DENIED; + + if ((flags & TEE_MEMORY_ACCESS_NONSECURE) && + (flags & TEE_MEMORY_ACCESS_SECURE)) + return TEE_ERROR_ACCESS_DENIED; + + /* + * Rely on TA private memory test to check if address range is private + * to TA or not. + */ + if (!(flags & TEE_MEMORY_ACCESS_ANY_OWNER) && + !vm_buf_is_inside_um_private(uctx, (void *)uaddr, len)) + return TEE_ERROR_ACCESS_DENIED; + + for (a = ROUNDDOWN(uaddr, addr_incr); a < end_addr; a += addr_incr) { + uint32_t attr; + TEE_Result res; + + res = tee_mmu_user_va2pa_attr(uctx, (void *)a, NULL, &attr); + if (res != TEE_SUCCESS) + return res; + + if ((flags & TEE_MEMORY_ACCESS_NONSECURE) && + (attr & TEE_MATTR_SECURE)) + return TEE_ERROR_ACCESS_DENIED; + + if ((flags & TEE_MEMORY_ACCESS_SECURE) && + !(attr & TEE_MATTR_SECURE)) + return TEE_ERROR_ACCESS_DENIED; + + if ((flags & TEE_MEMORY_ACCESS_WRITE) && !(attr & TEE_MATTR_UW)) + return TEE_ERROR_ACCESS_DENIED; + if ((flags & TEE_MEMORY_ACCESS_READ) && !(attr & TEE_MATTR_UR)) + return TEE_ERROR_ACCESS_DENIED; + } + + return TEE_SUCCESS; +} + +void vm_set_ctx(struct ts_ctx *ctx) +{ + struct thread_specific_data *tsd = thread_get_tsd(); + struct user_mode_ctx *uctx = NULL; + + core_mmu_set_user_map(NULL); + + if (is_user_mode_ctx(tsd->ctx)) { + /* + * We're coming from a user mode context so we must make + * the pgts available for reuse. + */ + uctx = to_user_mode_ctx(tsd->ctx); + pgt_put_all(uctx); + } + + if (is_user_mode_ctx(ctx)) { + struct core_mmu_user_map map = { }; + + uctx = to_user_mode_ctx(ctx); + core_mmu_create_user_map(uctx, &map); + core_mmu_set_user_map(&map); + tee_pager_assign_um_tables(uctx); + } + tsd->ctx = ctx; +} + +struct mobj *vm_get_mobj(struct user_mode_ctx *uctx, vaddr_t va, size_t *len, + uint16_t *prot, size_t *offs) +{ + struct vm_region *r = NULL; + size_t r_offs = 0; + + if (!len || ((*len | va) & SMALL_PAGE_MASK)) + return NULL; + + r = find_vm_region(&uctx->vm_info, va); + if (!r) + return NULL; + + r_offs = va - r->va; + + *len = MIN(r->size - r_offs, *len); + *offs = r->offset + r_offs; + *prot = r->attr & TEE_MATTR_PROT_MASK; + return mobj_get(r->mobj); +} diff --git a/optee/optee_os/core/pta/apdu.c b/optee/optee_os/core/pta/apdu.c new file mode 100644 index 0000000..940bdb5 --- /dev/null +++ b/optee/optee_os/core/pta/apdu.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) Foundries Ltd. 2021 - All Rights Reserved + * Author: Jorge Ramirez + */ +#include +#include +#include + +#define PTA_NAME "pta.apdu" + +static TEE_Result get_apdu_type(uint32_t val, enum crypto_apdu_type *type) +{ + switch (val) { + case PTA_APDU_TXRX_CASE_NO_HINT: + *type = CRYPTO_APDU_CASE_NO_HINT; + break; + case PTA_APDU_TXRX_CASE_1: + *type = CRYPTO_APDU_CASE_1; + break; + case PTA_APDU_TXRX_CASE_2: + *type = CRYPTO_APDU_CASE_2; + break; + case PTA_APDU_TXRX_CASE_2E: + *type = CRYPTO_APDU_CASE_2E; + break; + case PTA_APDU_TXRX_CASE_3: + *type = CRYPTO_APDU_CASE_3; + break; + case PTA_APDU_TXRX_CASE_3E: + *type = CRYPTO_APDU_CASE_3E; + break; + case PTA_APDU_TXRX_CASE_4: + *type = CRYPTO_APDU_CASE_4; + break; + case PTA_APDU_TXRX_CASE_4E: + *type = CRYPTO_APDU_CASE_4E; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *session_context __unused, + uint32_t command_id, uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT); + enum crypto_apdu_type type = CRYPTO_APDU_CASE_NO_HINT; + TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; + size_t len = 0; + + FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + switch (command_id) { + case PTA_CMD_TXRX_APDU_RAW_FRAME: + ret = get_apdu_type(params[0].value.a, &type); + if (ret) + return ret; + + len = params[3].memref.size; + ret = crypto_se_do_apdu(type, + params[1].memref.buffer, + params[1].memref.size, + params[2].memref.buffer, + params[2].memref.size, + params[3].memref.buffer, + &len); + if (!ret) + params[3].memref.size = len; + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +pseudo_ta_register(.uuid = PTA_APDU_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/attestation.c b/optee/optee_os/core/pta/attestation.c new file mode 100644 index 0000000..03efba8 --- /dev/null +++ b/optee/optee_os/core/pta/attestation.c @@ -0,0 +1,770 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2021, Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PTA_NAME "attestation.pta" + +#define MAX_KEY_SIZE 4096 + +static TEE_UUID pta_uuid = PTA_ATTESTATION_UUID; + +static struct rsa_keypair *key; + +static const uint8_t key_file_name[] = "key"; + +static TEE_Result allocate_key(void) +{ + assert(!key); + + key = calloc(1, sizeof(*key)); + if (!key) + return TEE_ERROR_OUT_OF_MEMORY; + + COMPILE_TIME_ASSERT(CFG_ATTESTATION_PTA_KEY_SIZE <= MAX_KEY_SIZE); + return crypto_acipher_alloc_rsa_keypair(key, MAX_KEY_SIZE); +} + +static void free_key(void) +{ + crypto_acipher_free_rsa_keypair(key); + free(key); + key = NULL; +} + +static TEE_Result generate_key(void) +{ + uint32_t e = TEE_U32_TO_BIG_ENDIAN(65537); + TEE_Result res = TEE_ERROR_GENERIC; + + res = allocate_key(); + if (res) + return res; + + crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key->e); + + /* + * For security reasons, the RSA modulus size has to be at least the + * size of the data to be signed. + */ + DMSG("Generating %u bit RSA key pair", CFG_ATTESTATION_PTA_KEY_SIZE); + COMPILE_TIME_ASSERT(CFG_ATTESTATION_PTA_KEY_SIZE >= + TEE_SHA256_HASH_SIZE); + res = crypto_acipher_gen_rsa_key(key, CFG_ATTESTATION_PTA_KEY_SIZE); + if (res) + free_key(); + + return res; +} + +/* + * Return values: + * > 0 : Number of bytes written to buf + * 0 : @sz too large (> UINT16_MAX) or @buf_sz too small + */ +static size_t serialize_bignum(uint8_t *buf, size_t buf_sz, struct bignum *bn) +{ + uint8_t *p = buf; + size_t sz = crypto_bignum_num_bytes(bn); + uint16_t val = TEE_U16_TO_BIG_ENDIAN(sz); + size_t total_sz = sizeof(val) + sz; + + if (sz > UINT16_MAX || total_sz > buf_sz) + return 0; + + memcpy(p, &val, sizeof(val)); + p += sizeof(val); + + crypto_bignum_bn2bin(bn, p); + + return total_sz; +} + +static size_t bufsize(size_t e_sz, size_t d_sz, size_t n_sz) +{ + /* + * Serialized key pair is 3 bignums (e, p and n) plus their sizes + * encoded as uint16_t. + */ + return e_sz + d_sz + n_sz + 3 * sizeof(uint16_t); +} + +static TEE_Result serialize_key(uint8_t *buf, size_t size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *p = buf; + size_t needed_sz = 0; + size_t e_sz = 0; + size_t d_sz = 0; + size_t n_sz = 0; + size_t sz = 0; + + assert(key); + + e_sz = crypto_bignum_num_bytes(key->e); + d_sz = crypto_bignum_num_bytes(key->d); + n_sz = crypto_bignum_num_bytes(key->n); + if (e_sz > UINT16_MAX || d_sz > UINT16_MAX || n_sz > UINT16_MAX) + goto err; + + needed_sz = bufsize(e_sz, d_sz, n_sz); + if (size < needed_sz) + goto err; + + sz = serialize_bignum(p, needed_sz, key->e); + if (!sz) + goto err; + p += sz; + needed_sz -= sz; + sz = serialize_bignum(p, needed_sz, key->d); + if (!sz) + goto err; + p += sz; + needed_sz -= sz; + sz = serialize_bignum(p, needed_sz, key->n); + if (!sz) + goto err; + needed_sz -= sz; + assert(!needed_sz); + + return TEE_SUCCESS; +err: + return res; +} + +static size_t deserialize_bignum(uint8_t *buf, size_t max_sz, struct bignum *bn) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *p = buf; + uint16_t val = 0; + size_t sz = 0; + + if (max_sz < sizeof(val)) + return 0; + + memcpy(&val, p, sizeof(val)); + sz = TEE_U16_FROM_BIG_ENDIAN(val); + p += sizeof(val); + max_sz -= sizeof(val); + if (max_sz < sz) + return 0; + + res = crypto_bignum_bin2bn(p, sz, bn); + if (res) + return 0; + + return sizeof(val) + sz; +} + +static TEE_Result deserialize_key(uint8_t *buf, size_t buf_sz) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *p = buf; + size_t sz = 0; + + res = allocate_key(); + if (res) + return res; + + sz = deserialize_bignum(p, buf_sz, key->e); + if (!sz) + goto err; + p += sz; + buf_sz -= sz; + sz = deserialize_bignum(p, buf_sz, key->d); + if (!sz) + goto err; + p += sz; + buf_sz -= sz; + sz = deserialize_bignum(p, buf_sz, key->n); + if (!sz) + goto err; + + return TEE_SUCCESS; +err: + free_key(); + return TEE_ERROR_GENERIC; +} + +static TEE_Result sec_storage_obj_read(TEE_UUID *uuid, uint32_t storage_id, + const uint8_t *obj_id, + size_t obj_id_len, + uint8_t *data, size_t *len, + size_t offset, uint32_t flags) +{ + const struct tee_file_operations *fops = NULL; + TEE_Result res = TEE_ERROR_BAD_STATE; + struct tee_file_handle *fh = NULL; + struct tee_pobj *po = NULL; + size_t file_size = 0; + size_t read_len = 0; + + fops = tee_svc_storage_file_ops(storage_id); + if (!fops) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, fops, + &po); + if (res) + return res; + + res = po->fops->open(po, &file_size, &fh); + if (res) + goto out; + + read_len = *len; + res = po->fops->read(fh, offset, data, &read_len); + if (res == TEE_ERROR_CORRUPT_OBJECT) { + EMSG("Object corrupt"); + po->fops->remove(po); + } else if (!res) { + *len = read_len; + } + + po->fops->close(&fh); +out: + tee_pobj_release(po); + + return res; +} + +static TEE_Result sec_storage_obj_write(TEE_UUID *uuid, uint32_t storage_id, + const uint8_t *obj_id, + size_t obj_id_len, + const uint8_t *data, size_t len, + size_t offset, uint32_t flags) + +{ + const struct tee_file_operations *fops = NULL; + struct tee_file_handle *fh = NULL; + TEE_Result res = TEE_SUCCESS; + struct tee_pobj *po = NULL; + + fops = tee_svc_storage_file_ops(storage_id); + if (!fops) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, + fops, &po); + if (res) + return res; + + res = po->fops->open(po, NULL, &fh); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = po->fops->create(po, false, NULL, 0, NULL, 0, NULL, 0, + &fh); + if (!res) { + res = po->fops->write(fh, offset, data, len); + po->fops->close(&fh); + } + + tee_pobj_release(po); + + return res; +} + +static TEE_Result load_key(uint8_t *buf, size_t size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + DMSG("Loading RSA key pair from secure storage"); + res = sec_storage_obj_read(&pta_uuid, TEE_STORAGE_PRIVATE, + key_file_name, sizeof(key_file_name) - 1, + buf, &size, 0, TEE_DATA_FLAG_ACCESS_READ); + if (res) + return res; + DMSG("Read %zu bytes", size); + res = deserialize_key(buf, size); + if (!res) + DMSG("Loaded %zu bit key pair", crypto_bignum_num_bits(key->n)); + + return res; +} + +static TEE_Result write_key(uint8_t *buf, size_t size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + DMSG("Saving key pair"); + res = serialize_key(buf, size); + if (res) + return res; + + res = sec_storage_obj_write(&pta_uuid, TEE_STORAGE_PRIVATE, + key_file_name, sizeof(key_file_name) - 1, + buf, size, 0, TEE_DATA_FLAG_ACCESS_WRITE); + if (!res) + DMSG("Wrote %zu bytes", size); + return res; +} + +static TEE_Result init_key(void) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t *buf = NULL; + size_t size = 0; + + if (!key) { + /* + * e is 65537 so its bignum size is 3 bytes. d and n can be up + * to MAX_KEY_SIZE bits. + */ + size = bufsize(3, MAX_KEY_SIZE / 8, MAX_KEY_SIZE / 8); + buf = calloc(1, size); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + res = load_key(buf, size); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + res = generate_key(); + if (res) + goto out; + res = write_key(buf, size); + } + } +out: + free(buf); + return res; +} + +static TEE_Result cmd_get_pubkey(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *e = params[0].memref.buffer; + size_t *e_out_sz = ¶ms[0].memref.size; + uint8_t *n = params[1].memref.buffer; + size_t *n_out_sz = ¶ms[1].memref.size; + size_t sz = 0; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + res = init_key(); + if (res) + return res; + + sz = crypto_bignum_num_bytes(key->e); + if (*e_out_sz >= sz) + crypto_bignum_bn2bin(key->e, e); + else + res = TEE_ERROR_SHORT_BUFFER; + *e_out_sz = sz; + + sz = crypto_bignum_num_bytes(key->n); + if (*n_out_sz >= sz) + crypto_bignum_bn2bin(key->n, n); + else + res = TEE_ERROR_SHORT_BUFFER; + *n_out_sz = sz; + + params[2].value.a = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256; + + return res; +} + +static TEE_Result hash_binary(const TEE_UUID *uuid, uint8_t *hash) +{ + TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; + unsigned int tag_len = FILE_TAG_SIZE; + const struct ts_store_ops *ops = NULL; + struct ts_store_handle *h = NULL; + + SCATTERED_ARRAY_FOREACH(ops, ta_stores, struct ts_store_ops) { + res = ops->open(uuid, &h); + if (!res) + break; /* TA found */ + } + if (res) + return res; + + /* + * Output hash size is assumed to be the same size as the file tag + * size which is the size of the digest in the TA shdr. If one or the + * other changes, additional hashing will be needed. + */ + COMPILE_TIME_ASSERT(FILE_TAG_SIZE == TEE_SHA256_HASH_SIZE); + assert(ops); + res = ops->get_tag(h, hash, &tag_len); + if (res) + goto out; + + DMSG("TA %pUl hash:", uuid); + DHEXDUMP(hash, TEE_SHA256_HASH_SIZE); +out: + ops->close(h); + return res; +} + +/* Hash @nonce and @hash into @digest */ +static TEE_Result digest_nonce_and_hash(uint8_t *digest, uint8_t *nonce, + size_t nonce_sz, uint8_t *hash) +{ + TEE_Result res = TEE_SUCCESS; + void *ctx = NULL; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); + if (res) + return res; + res = crypto_hash_init(ctx); + if (res) + goto out; + res = crypto_hash_update(ctx, nonce, nonce_sz); + if (res) + goto out; + res = crypto_hash_update(ctx, hash, TEE_SHA256_HASH_SIZE); + if (res) + goto out; + res = crypto_hash_final(ctx, digest, TEE_SHA256_HASH_SIZE); +out: + crypto_hash_free_ctx(ctx); + return res; +} + +static TEE_Result sign_digest(uint8_t *sig, size_t sig_len, + const uint8_t *digest) +{ + return crypto_acipher_rsassa_sign(TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, + key, + TEE_SHA256_HASH_SIZE, /* salt len */ + digest, TEE_SHA256_HASH_SIZE, + sig, &sig_len); +} + +/* + * Sign the first 32 bytes contained in @buf and append signature + * out = [ hash | sig(sha256(nonce | hash)) ] + * ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ + * 32B modulus size + */ +static TEE_Result sign_buffer(uint8_t *buf, size_t buf_sz, uint8_t *nonce, + size_t nonce_sz) +{ + uint8_t digest[TEE_SHA256_HASH_SIZE] = { }; + TEE_Result res = TEE_SUCCESS; + + res = digest_nonce_and_hash(digest, nonce, nonce_sz, buf); + if (res) + return res; + return sign_digest(buf + TEE_SHA256_HASH_SIZE, + buf_sz - TEE_SHA256_HASH_SIZE, digest); +} + +/* + * Is region valid for hashing? + * Exclude writable regions as well as those that are not specific to the TA + * (ldelf, kernel or temporary mappings). + */ +static bool is_region_valid(struct vm_region *r) +{ + uint32_t skip_flags = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT | + VM_FLAG_LDELF; + + return !(r->flags & skip_flags || r->attr & TEE_MATTR_UW); +} + +/* + * With this comparison function, we're hashing the smaller regions first. + * Regions of equal size are ordered based on their content (memcmp()). + * Identical regions can be in any order since they will yield the same hash + * anyways. + */ +static int cmp_regions(const void *a, const void *b) +{ + const struct vm_region *r1 = *(const struct vm_region **)a; + const struct vm_region *r2 = *(const struct vm_region **)b; + + if (r1->size < r2->size) + return -1; + + if (r1->size > r2->size) + return 1; + + return memcmp((void *)r1->va, (void *)r2->va, r1->size); +} + +static TEE_Result hash_regions(struct vm_info *vm_info, uint8_t *hash) +{ + TEE_Result res = TEE_SUCCESS; + struct vm_region *r = NULL; + struct vm_region **regions = NULL; + size_t nregions = 0; + void *ctx = NULL; + size_t i = 0; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); + if (res) + return res; + + res = crypto_hash_init(ctx); + if (res) + goto out; + + /* + * Make an array of region pointers so we can use qsort() to order it. + */ + + TAILQ_FOREACH(r, &vm_info->regions, link) + if (is_region_valid(r)) + nregions++; + + regions = malloc(nregions * sizeof(*regions)); + if (!regions) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + TAILQ_FOREACH(r, &vm_info->regions, link) + if (is_region_valid(r)) + regions[i++] = r; + + /* + * Sort regions so that they are in a consistent order even when TA ASLR + * is enabled. + */ + qsort(regions, nregions, sizeof(*regions), cmp_regions); + + /* Hash regions in order */ + for (i = 0; i < nregions; i++) { + r = regions[i]; + DMSG("va %p size %zu", (void *)r->va, r->size); + res = crypto_hash_update(ctx, (uint8_t *)r->va, r->size); + if (res) + goto out; + } + + res = crypto_hash_final(ctx, hash, TEE_SHA256_HASH_SIZE); +out: + free(regions); + crypto_hash_free_ctx(ctx); + return res; +} + +static TEE_Result cmd_get_ta_shdr_digest(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_UUID *uuid = params[0].memref.buffer; + size_t uuid_sz = params[0].memref.size; + uint8_t *nonce = params[1].memref.buffer; + size_t nonce_sz = params[1].memref.size; + uint8_t *out = params[2].memref.buffer; + size_t out_sz = params[2].memref.size; + size_t min_out_sz = 0; + TEE_Result res = TEE_SUCCESS; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (uuid_sz != sizeof(*uuid)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!nonce || !nonce_sz) + return TEE_ERROR_BAD_PARAMETERS; + + if (!out && out_sz) + return TEE_ERROR_BAD_PARAMETERS; + + res = init_key(); + if (res) + return res; + + min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n); + params[2].memref.size = min_out_sz; + if (out_sz < min_out_sz) + return TEE_ERROR_SHORT_BUFFER; + out_sz = min_out_sz; + + res = hash_binary(uuid, out); + if (res) + return res; + return sign_buffer(out, out_sz, nonce, nonce_sz); +} + +static TEE_Result cmd_hash_ta_memory(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint8_t *nonce = params[0].memref.buffer; + size_t nonce_sz = params[0].memref.size; + uint8_t *out = params[1].memref.buffer; + size_t out_sz = params[1].memref.size; + struct user_mode_ctx *uctx = NULL; + TEE_Result res = TEE_SUCCESS; + struct ts_session *s = NULL; + size_t min_out_sz = 0; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!nonce || !nonce_sz) + return TEE_ERROR_BAD_PARAMETERS; + + if (!out && out_sz) + return TEE_ERROR_BAD_PARAMETERS; + + /* Check that we're called from a user TA */ + s = ts_get_calling_session(); + if (!s) + return TEE_ERROR_ACCESS_DENIED; + uctx = to_user_mode_ctx(s->ctx); + if (!uctx) + return TEE_ERROR_ACCESS_DENIED; + + res = init_key(); + if (res) + return res; + + min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n); + params[1].memref.size = min_out_sz; + if (out_sz < min_out_sz) + return TEE_ERROR_SHORT_BUFFER; + out_sz = min_out_sz; + + s = ts_pop_current_session(); + res = hash_regions(&uctx->vm_info, out); + ts_push_current_session(s); + if (res) + return res; + + return sign_buffer(out, out_sz, nonce, nonce_sz); +} + +static TEE_Result cmd_hash_tee_memory(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint8_t *nonce = params[0].memref.buffer; + size_t nonce_sz = params[0].memref.size; + uint8_t *out = params[1].memref.buffer; + size_t out_sz = params[1].memref.size; + TEE_Result res = TEE_SUCCESS; + size_t min_out_sz = 0; + void *ctx = NULL; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!nonce || !nonce_sz) + return TEE_ERROR_BAD_PARAMETERS; + + if (!out && out_sz) + return TEE_ERROR_BAD_PARAMETERS; + + res = init_key(); + if (res) + return res; + + min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n); + params[1].memref.size = min_out_sz; + if (out_sz < min_out_sz) + return TEE_ERROR_SHORT_BUFFER; + out_sz = min_out_sz; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); + if (res) + return res; + res = crypto_hash_init(ctx); + if (res) + goto out; + res = crypto_hash_update(ctx, __text_start, + __text_data_start - __text_start); + if (res) + goto out; + res = crypto_hash_update(ctx, __text_data_end, + __text_end - __text_data_end); + if (IS_ENABLED(CFG_WITH_PAGER)) { + res = crypto_hash_update(ctx, __text_init_start, + __text_init_end - __text_init_start); + if (res) + goto out; + res = crypto_hash_update(ctx, __text_pageable_start, + __text_pageable_end - + __text_pageable_start); + if (res) + goto out; + } + if (res) + goto out; + res = crypto_hash_update(ctx, __rodata_start, + __rodata_end - __rodata_start); + if (res) + goto out; + if (IS_ENABLED(CFG_WITH_PAGER)) { + res = crypto_hash_update(ctx, __rodata_init_start, + __rodata_init_end - + __rodata_init_start); + if (res) + goto out; + res = crypto_hash_update(ctx, __rodata_pageable_start, + __rodata_pageable_end - + __rodata_pageable_start); + if (res) + goto out; + } + res = crypto_hash_final(ctx, out, TEE_SHA256_HASH_SIZE); + if (res) + goto out; + + DHEXDUMP(out, TEE_SHA256_HASH_SIZE); + + res = sign_buffer(out, out_sz, nonce, nonce_sz); +out: + crypto_hash_free_ctx(ctx); + return res; +} + +static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case PTA_ATTESTATION_GET_PUBKEY: + return cmd_get_pubkey(param_types, params); + case PTA_ATTESTATION_GET_TA_SHDR_DIGEST: + return cmd_get_ta_shdr_digest(param_types, params); + case PTA_ATTESTATION_HASH_TA_MEMORY: + return cmd_hash_ta_memory(param_types, params); + case PTA_ATTESTATION_HASH_TEE_MEMORY: + return cmd_hash_tee_memory(param_types, params); + default: + break; + } + return TEE_ERROR_BAD_PARAMETERS; +} + +pseudo_ta_register(.uuid = PTA_ATTESTATION_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/bcm/bnxt.c b/optee/optee_os/core/pta/bcm/bnxt.c new file mode 100644 index 0000000..e753305 --- /dev/null +++ b/optee/optee_os/core/pta/bcm/bnxt.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BNXT_SERVICE_UUID \ + {0x6272636D, 0x2019, 0x0716, \ + {0x42, 0x43, 0x4D, 0x5F, 0x53, 0x43, 0x48, 0x49} } + +/* + * enum pta_bnxt_cmd - commands supported by this PTA + * PTA_BNXT_FASTBOOT: boot bnxt device by copying f/w into sram + * + * PTA_BNXT_HEALTH_STATUS: check health of bnxt device + * [out] value[0].a - health status + * + * PTA_BNXT_HANDSHAKE_STATUS: check bnxt device is booted + * [inout] value[0].a - max timeout value + * value[0].a - boot status + * + * PTA_BNXT_CRASH_DUMP_COPY: copy the core dump into shm + * [inout] memref[0].buf: destination addr + * [in] value[1].a: offset + * [in] value[1].b: size + */ +enum pta_bnxt_cmd { + PTA_BNXT_FASTBOOT = 0, + PTA_BNXT_HEALTH_STATUS, + PTA_BNXT_HANDSHAKE_STATUS, + PTA_BNXT_CRASH_DUMP_COPY, +}; + +#define BNXT_TA_NAME "pta_bnxt.ta" + +static TEE_Result get_bnxt_status(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + if (type != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + p[0].value.a = bnxt_health_status(); + + return TEE_SUCCESS; +} + +static TEE_Result get_bnxt_handshake_status(uint32_t type, + TEE_Param p[TEE_NUM_PARAMS]) +{ + if (type != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + p[0].value.a = bnxt_wait_handshake(p[0].value.a); + + return TEE_SUCCESS; +} + +static TEE_Result copy_bnxt_crash_dump(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t *d = NULL; + uint32_t offset = 0; + uint32_t req_len = 0; + TEE_Result res = TEE_SUCCESS; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + DMSG("bad parameters types: 0x%" PRIx32, types); + return TEE_ERROR_BAD_PARAMETERS; + } + + d = (uint32_t *)params[0].memref.buffer; + offset = params[1].value.a; + req_len = params[1].value.b; + + if (!d || params[0].memref.size < req_len) + return TEE_ERROR_BAD_PARAMETERS; + + res = bnxt_copy_crash_dump((uint8_t *)d, offset, req_len); + + return res; +} + +static TEE_Result invoke_command(void *session_context __unused, + uint32_t cmd_id, + uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + TEE_Result res = TEE_SUCCESS; + + DMSG("command entry point[%d] for \"%s\"", cmd_id, BNXT_TA_NAME); + + switch (cmd_id) { + case PTA_BNXT_FASTBOOT: + DMSG("bnxt fastboot"); + if (bnxt_load_fw(1) != BNXT_SUCCESS) + return TEE_ERROR_TARGET_DEAD; + break; + case PTA_BNXT_HEALTH_STATUS: + DMSG("bnxt health status"); + return get_bnxt_status(param_types, params); + case PTA_BNXT_HANDSHAKE_STATUS: + DMSG("bnxt handshake status"); + return get_bnxt_handshake_status(param_types, params); + case PTA_BNXT_CRASH_DUMP_COPY: + DMSG("bnxt copy crash dump data"); + return copy_bnxt_crash_dump(param_types, params); + default: + DMSG("cmd: %d Not supported %s", cmd_id, BNXT_TA_NAME); + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + + return res; +} + +pseudo_ta_register(.uuid = BNXT_SERVICE_UUID, + .name = BNXT_TA_NAME, + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_DEVICE_ENUM, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/bcm/elog.c b/optee/optee_os/core/pta/bcm/elog.c new file mode 100644 index 0000000..869e9ea --- /dev/null +++ b/optee/optee_os/core/pta/bcm/elog.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define ELOG_SERVICE_UUID \ + { 0x6272636D, 0x2019, 0x0701, \ + { 0x42, 0x43, 0x4D, 0x5F, 0x45, 0x4C, 0x4F, 0x47 } } + +#define ELOG_TA_NAME "pta_bcm_elog.ta" + +#define BCM_NITRO_FW_LOAD_ADDR 0x8ae00000 +#define BCM_NITRO_CRASH_DUMP_BASE_ADDR 0x8b000000 + +/* Default ELOG buffer size 1MB */ +#define DEFAULT_ELOG_BUFFER_SIZE 0x100000U + +/* + * Get Error log memory dump + * + * [out] memref[0]: Destination + * [in] value[1].a: Offset + */ +#define PTA_BCM_ELOG_CMD_GET_ELOG_MEM 1 + +/* + * Get nitro crash_dump memory + * + * [out] memref[0]: Destination + * [in] value[1].a: Offset + */ +#define PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP 2 + +/* + * Load nitro firmware memory + * + * [in] memref[0]: Nitro f/w image data + * [in] value[1].a: Offset for loading f/w image + * [in] value[2].a: Firmware image size + */ +#define PTA_BCM_ELOG_CMD_LOAD_NITRO_FW 3 + +#define BCM_ELOG_GLOBAL_METADATA_SIG 0x45524c47 + +#define MAX_NITRO_CRASH_DUMP_MEM_SIZE 0x2000000 +#define MAX_NITRO_FW_LOAD_MEM_SIZE 0x200000 + +/* Load Nitro fw image to SEC DDR memory */ +static TEE_Result pta_elog_load_nitro_fw(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + paddr_t src_paddr = BCM_NITRO_FW_LOAD_ADDR + BNXT_IMG_SECMEM_OFFSET; + vaddr_t src_vaddr = 0; + uint32_t offset = 0; + size_t end_offs = 0; + size_t sz = 0; + char *buf = NULL; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Check if firmware file size exceeds reserved memory size */ + if (params[2].value.a > MAX_NITRO_FW_LOAD_MEM_SIZE) { + EMSG("Invalid access"); + return TEE_ERROR_EXCESS_DATA; + } + + offset = params[1].value.a; + buf = params[0].memref.buffer; + sz = params[0].memref.size; + + /* + * Check that we under no circumstances will attempt to write + * beyond BCM_NITRO_FW_LOAD_ADDR + MAX_NITRO_FW_LOAD_MEM_SIZE. + */ + if (ADD_OVERFLOW(sz, offset, &end_offs) || + end_offs > MAX_NITRO_FW_LOAD_MEM_SIZE - BNXT_IMG_SECMEM_OFFSET) { + EMSG("Invalid access"); + return TEE_ERROR_ACCESS_DENIED; + } + + src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset, + MEM_AREA_RAM_SEC, sz); + if (!src_vaddr) { + EMSG("Not enough memory mapped"); + return TEE_ERROR_BAD_PARAMETERS; + } + + memcpy((char *)src_vaddr, buf, sz); + + cache_op_inner(DCACHE_AREA_CLEAN, (void *)src_vaddr, sz); + + return res; +} + +static uint32_t get_dump_data(vaddr_t src, TEE_Param params[TEE_NUM_PARAMS]) +{ + char *buf = NULL; + uint32_t sz = 0; + + buf = params[0].memref.buffer; + sz = params[0].memref.size; + + /* + * If request size exceeds default buf size + * override request size to default DEFAULT_ELOG_BUFFER_SIZE + */ + if (sz > DEFAULT_ELOG_BUFFER_SIZE) + sz = DEFAULT_ELOG_BUFFER_SIZE; + + DMSG("buf %p sz 0x%x", buf, sz); + + memcpy(buf, (char *)src, sz); + + params[0].memref.size = sz; + + return sz; +} + +/* Copy nitro crash dump data */ +static TEE_Result pta_elog_nitro_crash_dump(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + paddr_t src_paddr = BCM_NITRO_CRASH_DUMP_BASE_ADDR; + vaddr_t src_vaddr = 0; + uint32_t offset = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint32_t sz = 0; + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + offset = params[1].value.a; + + /* + * Check if offset is within memory range reserved for nitro crash dump + * minus default size of buffer + */ + if (offset > MAX_NITRO_CRASH_DUMP_MEM_SIZE - DEFAULT_ELOG_BUFFER_SIZE) { + EMSG("Invalid access"); + return TEE_ERROR_ACCESS_DENIED; + } + + sz = MIN(params[0].memref.size, DEFAULT_ELOG_BUFFER_SIZE); + src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset, + MEM_AREA_RAM_SEC, sz); + if (!src_vaddr) { + EMSG("Not enough memory mapped"); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* TODO : check if NITRO_CRASH_DUMP is available */ + + cache_op_inner(DCACHE_AREA_INVALIDATE, (void *)src_vaddr, + DEFAULT_ELOG_BUFFER_SIZE); + + get_dump_data(src_vaddr, params); + + return res; +} + +/* Copy soc error log data */ +static TEE_Result pta_elog_dump(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + paddr_t src_paddr = CFG_BCM_ELOG_BASE; + vaddr_t src_vaddr = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint32_t sz = 0; + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + sz = MIN(params[0].memref.size, DEFAULT_ELOG_BUFFER_SIZE); + src_vaddr = (vaddr_t)phys_to_virt(src_paddr, MEM_AREA_RAM_NSEC, sz); + if (!src_vaddr) { + EMSG("Not enough memory mapped"); + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Validate if Error logs are present */ + if ((*(uint32_t *)src_vaddr) != BCM_ELOG_GLOBAL_METADATA_SIG) { + EMSG("Elog Not setup"); + return TEE_ERROR_NOT_SUPPORTED; + } + + get_dump_data(src_vaddr, params); + + return res; +} + +static TEE_Result invoke_command(void *session_context __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + + DMSG("command entry point[%d] for \"%s\"", cmd_id, ELOG_TA_NAME); + + switch (cmd_id) { + case PTA_BCM_ELOG_CMD_GET_ELOG_MEM: + res = pta_elog_dump(param_types, params); + break; + case PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP: + res = pta_elog_nitro_crash_dump(param_types, params); + break; + case PTA_BCM_ELOG_CMD_LOAD_NITRO_FW: + res = pta_elog_load_nitro_fw(param_types, params); + break; + default: + EMSG("cmd: %d Not supported %s", cmd_id, ELOG_TA_NAME); + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + + return res; +} + +pseudo_ta_register(.uuid = ELOG_SERVICE_UUID, + .name = ELOG_TA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/bcm/gpio.c b/optee/optee_os/core/pta/bcm/gpio.c new file mode 100644 index 0000000..43ed935 --- /dev/null +++ b/optee/optee_os/core/pta/bcm/gpio.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2019 Broadcom. + */ + +#include +#include +#include +#include + +#define GPIO_SERVICE_UUID \ + { 0x6272636D, 0x2018, 0x1101, \ + { 0x42, 0x43, 0x4D, 0x5F, 0x47, 0x50, 0x49, 0x4F } } + +/* + * Configure GPIO Pin + * + * [in] value[0].a: gpio pin number + * [in] value[0].b: direction to configure + */ +#define PTA_BCM_GPIO_CMD_CFG 0 + +/* + * Set GPIO pin + * + * [in] value[0].a: gpio pin number + * [in] value[0].b: value drive on pin + */ +#define PTA_BCM_GPIO_CMD_SET 1 + +/* + * Get GPIO pin + * + * [in] value[0].a: gpio pin number + * [out] value[1].a: value read from gpio pin + */ +#define PTA_BCM_GPIO_CMD_GET 2 + +#define GPIO_TA_NAME "pta_bcm_gpio.ta" + +static TEE_Result pta_gpio_config(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t gpio_num = 0; + struct bcm_gpio_chip *bcm_gc = NULL; + struct gpio_chip *gc = NULL; + bool dir = false; + TEE_Result res = TEE_SUCCESS; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + gpio_num = params[0].value.a; + dir = params[0].value.b; + + bcm_gc = bcm_gpio_pin_to_chip(gpio_num); + if (!bcm_gc) { + EMSG("GPIO %u not supported", gpio_num); + return TEE_ERROR_NOT_SUPPORTED; + } + + gc = &bcm_gc->chip; + + /* Make gpio secure. */ + iproc_gpio_set_secure(gpio_num); + + if (dir) { + /* Set GPIO to output with default value to 0 */ + gc->ops->set_direction(NULL, gpio_num, GPIO_DIR_OUT); + gc->ops->set_value(NULL, gpio_num, 0); + } else { + gc->ops->set_direction(NULL, gpio_num, GPIO_DIR_IN); + } + + return res; +} + +static TEE_Result pta_gpio_set(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t gpio_num = 0; + uint32_t val = 0; + TEE_Result res = TEE_SUCCESS; + struct bcm_gpio_chip *bcm_gc = NULL; + struct gpio_chip *gc = NULL; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + gpio_num = params[0].value.a; + val = !!params[0].value.b; + + bcm_gc = bcm_gpio_pin_to_chip(gpio_num); + if (!bcm_gc) { + EMSG("GPIO %u not supported", gpio_num); + return TEE_ERROR_NOT_SUPPORTED; + } + + gc = &bcm_gc->chip; + + /* + * For setting a value to GPIO Pin, + * need to make sure the PIN is configured in + * output direction. + */ + if (gc->ops->get_direction(NULL, gpio_num) != GPIO_DIR_OUT) { + EMSG("gpio pin %u is configured as INPUT", gpio_num); + return TEE_ERROR_ACCESS_DENIED; + } + + gc->ops->set_value(NULL, gpio_num, val); + + DMSG("GPIO(%d) value = 0x%08x", gpio_num, + gc->ops->get_value(NULL, gpio_num)); + + return res; +} + +static TEE_Result pta_gpio_get(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t gpio_num = 0; + struct bcm_gpio_chip *bcm_gc = NULL; + struct gpio_chip *gc = NULL; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + gpio_num = params[0].value.a; + + bcm_gc = bcm_gpio_pin_to_chip(gpio_num); + if (!bcm_gc) { + EMSG("GPIO %u not supported", gpio_num); + return TEE_ERROR_NOT_SUPPORTED; + } + + gc = &bcm_gc->chip; + + params[1].value.a = gc->ops->get_value(NULL, gpio_num); + + DMSG("gpio(%d) value = 0x%08x", gpio_num, params[1].value.a); + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *session_context __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + + DMSG("command entry point[%d] for \"%s\"", cmd_id, GPIO_TA_NAME); + + switch (cmd_id) { + case PTA_BCM_GPIO_CMD_CFG: + res = pta_gpio_config(param_types, params); + break; + case PTA_BCM_GPIO_CMD_SET: + res = pta_gpio_set(param_types, params); + break; + case PTA_BCM_GPIO_CMD_GET: + res = pta_gpio_get(param_types, params); + break; + default: + EMSG("cmd: %d Not supported %s\n", cmd_id, GPIO_TA_NAME); + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + + return res; +} + +pseudo_ta_register(.uuid = GPIO_SERVICE_UUID, + .name = GPIO_TA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/bcm/hwrng.c b/optee/optee_os/core/pta/bcm/hwrng.c new file mode 100644 index 0000000..daaae5a --- /dev/null +++ b/optee/optee_os/core/pta/bcm/hwrng.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Broadcom + */ + +#include +#include +#include +#include + +#define HWRNG_SERVICE_UUID \ + { 0x6272636D, 0x2019, 0x0201, \ + { 0x42, 0x43, 0x4D, 0x5F, 0x52, 0x4E, 0x47, 0x30 } } + +/* + * Get a HW generated random number + * + * [out] value[0].a: Generated 32-bit random number + */ +#define PTA_BCM_HWRNG_CMD_GET 0 + +#define HWRNG_TA_NAME "pta_hwrng.ta" + +static TEE_Result pta_hwrng_get(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t num_words = 0; + uint32_t rnd_num = 0; + uint32_t res = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + num_words = bcm_hwrng_read_rng(&rnd_num, 1); + + if (num_words < 1) { + res = TEE_ERROR_NO_DATA; + } else { + DMSG("Random Value is: 0x%08x", rnd_num); + params[0].value.a = rnd_num; + res = TEE_SUCCESS; + } + + return res; +} + +static TEE_Result invoke_command(void *session_context __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + + DMSG("command entry point[%d] for \"%s\"", cmd_id, HWRNG_TA_NAME); + + switch (cmd_id) { + case PTA_BCM_HWRNG_CMD_GET: + res = pta_hwrng_get(param_types, params); + break; + default: + EMSG("cmd: %d Not supported %s", cmd_id, HWRNG_TA_NAME); + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + + return res; +} + +pseudo_ta_register(.uuid = HWRNG_SERVICE_UUID, + .name = HWRNG_TA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/bcm/sotp.c b/optee/optee_os/core/pta/bcm/sotp.c new file mode 100644 index 0000000..9b97265 --- /dev/null +++ b/optee/optee_os/core/pta/bcm/sotp.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Broadcom + */ + +#include +#include +#include +#include +#include + +#define SOTP_SERVICE_UUID \ + {0x6272636D, 0x2018, 0x1101, \ + {0x42, 0x43, 0x4D, 0x5F, 0x53, 0x4F, 0x54, 0x50} } + +enum pta_bcm_sotp_cmd { + PTA_BCM_SOTP_CMD_READ = 0, + PTA_BCM_SOTP_CMD_WRITE, +}; + +#define SOTP_TA_NAME "pta_bcm_sotp.ta" + +static bool sotp_access_disabled; + +/** + * close_session() - Print a debug message when closing a session and set the + * driver to disallow any more pta sessions to connect. + * @pSessionContext Unused. + */ +static void close_session(void *pSessionContext __unused) +{ + DMSG("close entry point for \"%s\"", SOTP_TA_NAME); + if (IS_ENABLED(CFG_BCM_SOTP_SINGLE_SESSION)) + sotp_access_disabled = true; +} + +static TEE_Result pta_sotp_read(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint64_t sotp_row_value = 0; + uint32_t val = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + val = params[0].value.a; + + bcm_iproc_sotp_mem_read(val, true, &sotp_row_value); + reg_pair_from_64(sotp_row_value, ¶ms[1].value.a, + ¶ms[1].value.b); + + return TEE_SUCCESS; +} + +static TEE_Result pta_sotp_write(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + /* Nothing as of now */ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static TEE_Result invoke_command(void *session_context __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + + DMSG("command entry point[%d] for \"%s\"", cmd_id, SOTP_TA_NAME); + + if (IS_ENABLED(CFG_BCM_SOTP_SINGLE_SESSION) && sotp_access_disabled) { + DMSG("bcm sotp pta access disabled"); + return TEE_ERROR_ACCESS_DENIED; + } + + switch (cmd_id) { + case PTA_BCM_SOTP_CMD_READ: + res = pta_sotp_read(param_types, params); + break; + case PTA_BCM_SOTP_CMD_WRITE: + res = pta_sotp_write(param_types, params); + break; + default: + EMSG("cmd %d Not supported %s", cmd_id, SOTP_TA_NAME); + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + + return res; +} + +pseudo_ta_register(.uuid = SOTP_SERVICE_UUID, + .name = SOTP_TA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .close_session_entry_point = close_session, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/bcm/sub.mk b/optee/optee_os/core/pta/bcm/sub.mk new file mode 100644 index 0000000..63a29cb --- /dev/null +++ b/optee/optee_os/core/pta/bcm/sub.mk @@ -0,0 +1,6 @@ +srcs-$(CFG_BNXT_FW) += bnxt.c +srcs-$(CFG_SP805_WDT) += wdt.c +srcs-$(CFG_BCM_HWRNG) += hwrng.c +srcs-$(CFG_BCM_SOTP) += sotp.c +srcs-$(CFG_BCM_GPIO) += gpio.c +srcs-$(CFG_BCM_ELOG_DUMP) += elog.c diff --git a/optee/optee_os/core/pta/bcm/wdt.c b/optee/optee_os/core/pta/bcm/wdt.c new file mode 100644 index 0000000..dceaa13 --- /dev/null +++ b/optee/optee_os/core/pta/bcm/wdt.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Broadcom + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SEC_WD_SERVICE_UUID \ + { 0x6272636D, 0x2019, 0x0801, \ + { 0x42, 0x43, 0x4D, 0x5F, 0x57, 0x44, 0x54, 0x30 } } + +#define PTA_BCM_SEC_WD_CMD_CONFIG 0 +#define PTA_BCM_SEC_WD_CMD_START 1 +#define PTA_BCM_SEC_WD_CMD_PING 2 +#define PTA_BCM_SEC_WD_CMD_STOP 3 +#define PTA_BCM_SEC_WD_CMD_SET_TIMEOUT 4 + +#define SEC_WD_TA_NAME "pta_bcm_sec_wd.ta" + +static struct sp805_wdt_data wd_pd; + +static void wd_isr_handler(struct wdt_chip *chip __unused) +{ + /* Do nothing */ + DMSG("Watchdog ISR handler !!!"); +} + +static TEE_Result pta_wd_config(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t timeout = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + timeout = params[0].value.a; + + sp805_wdt_init(&wd_pd, SEC_WDT_BASE, SEC_WDT_CLK_HZ, timeout); + + sp805_register_itr_handler(&wd_pd, GIC_SPI_TO_ITNUM(SEC_WDT_INTR), + ITRF_TRIGGER_LEVEL, wd_isr_handler); + wd_pd.chip.ops->start(&wd_pd.chip); + + return TEE_SUCCESS; +} + +static TEE_Result pta_wd_start(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + wd_pd.chip.ops->start(&wd_pd.chip); + + return TEE_SUCCESS; +} + +static TEE_Result pta_wd_ping(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + wd_pd.chip.ops->ping(&wd_pd.chip); + + return TEE_SUCCESS; +} + +static TEE_Result pta_wd_stop(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + wd_pd.chip.ops->stop(&wd_pd.chip); + + return TEE_SUCCESS; +} + +static TEE_Result pta_wd_set_timeout(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t timeout = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_param_types != param_types) { + EMSG("Invalid Param types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + timeout = params[0].value.a; + + wd_pd.chip.ops->set_timeout(&wd_pd.chip, timeout); + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *session_context __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + + DMSG("command entry point[%d] for \"%s\"", cmd_id, SEC_WD_TA_NAME); + + switch (cmd_id) { + case PTA_BCM_SEC_WD_CMD_CONFIG: + res = pta_wd_config(param_types, params); + break; + case PTA_BCM_SEC_WD_CMD_START: + res = pta_wd_start(param_types, params); + break; + case PTA_BCM_SEC_WD_CMD_PING: + res = pta_wd_ping(param_types, params); + break; + case PTA_BCM_SEC_WD_CMD_STOP: + res = pta_wd_stop(param_types, params); + break; + case PTA_BCM_SEC_WD_CMD_SET_TIMEOUT: + res = pta_wd_set_timeout(param_types, params); + break; + default: + EMSG("cmd: %d Not supported %s", cmd_id, SEC_WD_TA_NAME); + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + + return res; +} + +pseudo_ta_register(.uuid = SEC_WD_SERVICE_UUID, + .name = SEC_WD_TA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/benchmark.c b/optee/optee_os/core/pta/benchmark.c new file mode 100644 index 0000000..bfaa426 --- /dev/null +++ b/optee/optee_os/core/pta/benchmark.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TA_NAME "benchmark.ta" +#define TA_PRINT_PREFIX "Benchmark: " + +static struct tee_ts_global *bench_ts_global; +static size_t bench_ts_size; + +static struct mutex bench_reg_mu = MUTEX_INITIALIZER; +static struct mobj *bench_mobj; + +static TEE_Result rpc_reg_global_buf(uint64_t type, paddr_t phta, size_t size) +{ + struct thread_param tpm = THREAD_PARAM_VALUE(IN, type, phta, size); + + return thread_rpc_cmd(OPTEE_RPC_CMD_BENCH_REG, 1, &tpm); +} + +static TEE_Result alloc_benchmark_buffer(uint32_t type, + TEE_Param p[TEE_NUM_PARAMS]) +{ + TEE_Result res; + + if ((TEE_PARAM_TYPE_GET(type, 0) != TEE_PARAM_TYPE_VALUE_INOUT) || + (TEE_PARAM_TYPE_GET(type, 1) != TEE_PARAM_TYPE_VALUE_INPUT) || + (TEE_PARAM_TYPE_GET(type, 2) != TEE_PARAM_TYPE_NONE) || + (TEE_PARAM_TYPE_GET(type, 3) != TEE_PARAM_TYPE_NONE)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + mutex_lock(&bench_reg_mu); + + /* Check if we have already registered buffer */ + if (bench_ts_global) { + EMSG(TA_PRINT_PREFIX + "timestamp buffer was already registered"); + mutex_unlock(&bench_reg_mu); + return TEE_ERROR_BAD_STATE; + } + + bench_ts_size = sizeof(struct tee_ts_global) + + p[1].value.a * sizeof(struct tee_ts_cpu_buf); + if (!bench_ts_size) { + EMSG(TA_PRINT_PREFIX + "invalid timestamp buffer size"); + mutex_unlock(&bench_reg_mu); + return TEE_ERROR_BAD_STATE; + } + + bench_mobj = thread_rpc_alloc_global_payload(bench_ts_size); + if (!bench_mobj) { + EMSG(TA_PRINT_PREFIX + "can't create mobj for timestamp buffer"); + mutex_unlock(&bench_reg_mu); + return TEE_ERROR_OUT_OF_MEMORY; + } + + bench_ts_global = (struct tee_ts_global *)mobj_get_va(bench_mobj, 0, + bench_ts_size); + if (!bench_ts_global) { + thread_rpc_free_global_payload(bench_mobj); + bench_mobj = NULL; + + mutex_unlock(&bench_reg_mu); + return TEE_ERROR_BAD_STATE; + } + + memset((void *)bench_ts_global, 0, bench_ts_size); + bench_ts_global->cores = p[1].value.a; + + DMSG(TA_PRINT_PREFIX + "allocated timestamp buffer, addr = %p", + (void *)bench_ts_global); + + mutex_unlock(&bench_reg_mu); + + /* Send back to the optee linux kernel module */ + res = rpc_reg_global_buf(OPTEE_MSG_RPC_CMD_BENCH_REG_NEW, + virt_to_phys((void *)bench_ts_global), + bench_ts_size); + + p[0].value.a = virt_to_phys((void *)bench_ts_global); + p[0].value.b = bench_ts_size; + + return res; +} + +static TEE_Result get_benchmark_memref(uint32_t type, + TEE_Param p[TEE_NUM_PARAMS]) +{ + if ((TEE_PARAM_TYPE_GET(type, 0) != TEE_PARAM_TYPE_VALUE_OUTPUT) || + (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)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + mutex_lock(&bench_reg_mu); + + DMSG(TA_PRINT_PREFIX "Sending back timestamp buffer paddr = %p", + (void *)virt_to_phys((void *)bench_ts_global)); + + if (bench_ts_global) { + p[0].value.a = virt_to_phys((void *)bench_ts_global); + p[0].value.b = bench_ts_size; + } else { + p[0].value.a = 0; + p[0].value.b = 0; + } + + mutex_unlock(&bench_reg_mu); + + return TEE_SUCCESS; +} + +static TEE_Result unregister_benchmark(uint32_t type, + TEE_Param p[TEE_NUM_PARAMS] __unused) +{ + TEE_Result res; + + 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_NONE)) { + return TEE_ERROR_BAD_PARAMETERS; + } + mutex_lock(&bench_reg_mu); + + DMSG(TA_PRINT_PREFIX "Unregister benchmark ts buffer paddr = %p", + (void *)virt_to_phys((void *)bench_ts_global)); + bench_ts_global = NULL; + + mutex_unlock(&bench_reg_mu); + + res = rpc_reg_global_buf(OPTEE_MSG_RPC_CMD_BENCH_REG_DEL, 0, 0); + + thread_rpc_free_global_payload(bench_mobj); + bench_mobj = NULL; + + return res; +} + +static TEE_Result invoke_command(void *session_ctx __unused, + uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case BENCHMARK_CMD_ALLOCATE_BUF: + return alloc_benchmark_buffer(param_types, params); + case BENCHMARK_CMD_GET_MEMREF: + return get_benchmark_memref(param_types, params); + case BENCHMARK_CMD_UNREGISTER: + return unregister_benchmark(param_types, params); + default: + break; + } + + return TEE_ERROR_BAD_PARAMETERS; +} + +pseudo_ta_register(.uuid = BENCHMARK_UUID, .name = TA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); + +void bm_timestamp(void) +{ + struct tee_ts_cpu_buf *cpu_buf; + struct tee_time_st ts_data; + uint64_t ts_i; + void *ret_addr; + uint32_t cur_cpu; + uint32_t exceptions; + + if (!bench_ts_global) + return; + + exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); + cur_cpu = get_core_pos(); + + if (cur_cpu >= bench_ts_global->cores) { + thread_unmask_exceptions(exceptions); + return; + } + + ret_addr = __builtin_return_address(0); + + cpu_buf = &bench_ts_global->cpu_buf[cur_cpu]; + ts_i = cpu_buf->head++; + ts_data.cnt = read_pmccntr() * TEE_BENCH_DIVIDER; + ts_data.addr = (uintptr_t)ret_addr; + ts_data.src = TEE_BENCH_CORE; + cpu_buf->stamps[ts_i & TEE_BENCH_MAX_MASK] = ts_data; + + thread_unmask_exceptions(exceptions); +} diff --git a/optee/optee_os/core/pta/device.c b/optee/optee_os/core/pta/device.c new file mode 100644 index 0000000..1a026a6 --- /dev/null +++ b/optee/optee_os/core/pta/device.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + */ + +/* + * This pseudo TA is used by normal world OS TEE driver to fetch pseudo TA's + * UUIDs which can act as TEE bus devices. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PTA_NAME "device.pta" + +static void add_ta(uint32_t flags, const TEE_UUID *uuid, uint8_t *buf, + uint32_t blen, uint32_t *pos, uint32_t rflags) +{ + if ((flags & TA_FLAG_DEVICE_ENUM) && + (flags & TA_FLAG_DEVICE_ENUM_SUPP)) { + EMSG(PTA_NAME ": skipping TA %pUl, inconsistent flags", uuid); + return; + } + + if (flags & rflags) { + if (*pos + sizeof(*uuid) <= blen) + tee_uuid_to_octets(buf + *pos, uuid); + + *pos += sizeof(*uuid); + } +} + +static TEE_Result get_devices(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS], + uint32_t rflags) +{ + const struct pseudo_ta_head *ta = NULL; + const struct embedded_ts *eta = NULL; + void *buf = NULL; + uint32_t blen = 0; + uint32_t pos = 0; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!params[0].memref.buffer && (params[0].memref.size > 0)) + return TEE_ERROR_BAD_PARAMETERS; + + buf = params[0].memref.buffer; + blen = params[0].memref.size; + + SCATTERED_ARRAY_FOREACH(ta, pseudo_tas, struct pseudo_ta_head) + add_ta(ta->flags, &ta->uuid, buf, blen, &pos, rflags); + + if (stmm_get_uuid()) + add_ta(TA_FLAG_DEVICE_ENUM_SUPP, stmm_get_uuid(), buf, blen, + &pos, rflags); + + if (IS_ENABLED(CFG_EARLY_TA)) + for_each_early_ta(eta) + add_ta(eta->flags, &eta->uuid, buf, blen, &pos, + rflags); + + params[0].memref.size = pos; + if (pos > blen) + return TEE_ERROR_SHORT_BUFFER; + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *pSessionContext __unused, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]) +{ + switch (nCommandID) { + case PTA_CMD_GET_DEVICES: + return get_devices(nParamTypes, pParams, + TA_FLAG_DEVICE_ENUM); + case PTA_CMD_GET_DEVICES_SUPP: + return get_devices(nParamTypes, pParams, + TA_FLAG_DEVICE_ENUM_SUPP); + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_DEVICE_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/gprof.c b/optee/optee_os/core/pta/gprof.c new file mode 100644 index 0000000..d999687 --- /dev/null +++ b/optee/optee_os/core/pta/gprof.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result gprof_send_rpc(TEE_UUID *uuid, void *buf, size_t len, + uint32_t *id) +{ + struct thread_param params[3] = { }; + struct mobj *mobj; + TEE_Result res = TEE_ERROR_GENERIC; + char *va; + + mobj = thread_rpc_alloc_payload(sizeof(*uuid) + len); + if (!mobj) + return TEE_ERROR_OUT_OF_MEMORY; + + va = mobj_get_va(mobj, 0, sizeof(*uuid) + len); + if (!va) + goto exit; + + memcpy(va, uuid, sizeof(*uuid)); + memcpy(va + sizeof(*uuid), buf, len); + + params[0] = THREAD_PARAM_VALUE(INOUT, *id, 0, 0); + params[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, sizeof(*uuid)); + params[2] = THREAD_PARAM_MEMREF(IN, mobj, sizeof(*uuid), len); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_GPROF, 3, params); + if (res != TEE_SUCCESS) + goto exit; + + *id = (uint32_t)params[0].u.value.a; +exit: + thread_rpc_free_payload(mobj); + return res; +} + +static TEE_Result gprof_send(struct ts_session *s, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + return gprof_send_rpc(&s->ctx->uuid, params[1].memref.buffer, + params[1].memref.size, ¶ms[0].value.a); +} + +static TEE_Result gprof_start_pc_sampling(struct ts_session *s, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct sample_buf *sbuf = NULL; + uint32_t offset = 0; + uint32_t scale = 0; + uint32_t len = 0; + uaddr_t buf = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (s->sbuf) { + DMSG("PC sampling already started"); + return TEE_ERROR_BAD_STATE; + } + + buf = (uaddr_t)params[0].memref.buffer; + len = params[0].memref.size; + offset = params[1].value.a; + scale = params[1].value.b; + + sbuf = calloc(1, sizeof(*sbuf)); + if (!sbuf) + return TEE_ERROR_OUT_OF_MEMORY; + + sbuf->samples = (uint16_t *)buf; + sbuf->nsamples = len / sizeof(*sbuf->samples); + sbuf->offset = offset; + sbuf->scale = scale; + sbuf->freq = read_cntfrq(); + sbuf->enabled = true; + s->sbuf = sbuf; + + return TEE_SUCCESS; +} + +static TEE_Result gprof_stop_pc_sampling(struct ts_session *s, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct sample_buf *sbuf = NULL; + uint32_t rate = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + sbuf = s->sbuf; + if (!sbuf) + return TEE_ERROR_BAD_STATE; + assert(sbuf->samples); + + /* Stop sampling */ + if (sbuf->enabled) + sbuf->enabled = false; + + rate = ((uint64_t)sbuf->count * sbuf->freq) / sbuf->usr; + params[0].value.a = rate; + + DMSG("TA sampling stats: sample count=%" PRIu32 " user time=%" PRIu64 + " cntfrq=%" PRIu32 " rate=%" PRIu32, sbuf->count, sbuf->usr, + sbuf->freq, rate); + + free(sbuf); + s->sbuf = NULL; + + return TEE_SUCCESS; +} + +/* + * Trusted Application Entry Points + */ + +static TEE_Result open_session(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **sess_ctx __unused) +{ + struct ts_session *s = ts_get_calling_session(); + + /* Check that we're called from a user TA */ + if (!s) + return TEE_ERROR_ACCESS_DENIED; + if (!is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct ts_session *s = ts_get_calling_session(); + + switch (cmd_id) { + case PTA_GPROF_SEND: + return gprof_send(s, param_types, params); + case PTA_GPROF_START_PC_SAMPLING: + return gprof_start_pc_sampling(s, param_types, params); + case PTA_GPROF_STOP_PC_SAMPLING: + return gprof_stop_pc_sampling(s, param_types, params); + default: + break; + } + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_GPROF_UUID, .name = "gprof", + .flags = PTA_DEFAULT_FLAGS, + .open_session_entry_point = open_session, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/hwrng.c b/optee/optee_os/core/pta/hwrng.c new file mode 100644 index 0000000..ed089a1 --- /dev/null +++ b/optee/optee_os/core/pta/hwrng.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, Linaro Limited + * Copyright (c) 2021, EPAM Systems. All rights reserved. + * + * Based on plat-synquacer/rng_pta.c + * + */ + +#include +#include +#include +#include +#include +#include + +#define PTA_NAME "rng.pta" + +/* This PTA only works with hardware random number generators */ +static_assert(!IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)); + +static TEE_Result rng_get_entropy(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint8_t *e = NULL; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + DMSG("bad parameters types: 0x%" PRIx32, types); + return TEE_ERROR_BAD_PARAMETERS; + } + + e = (uint8_t *)params[0].memref.buffer; + if (!e) + return TEE_ERROR_BAD_PARAMETERS; + + return crypto_rng_read(e, params[0].memref.size); +} + +static TEE_Result rng_get_info(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + DMSG("bad parameters types: 0x%" PRIx32, types); + return TEE_ERROR_BAD_PARAMETERS; + } + + params[0].value.a = CFG_HWRNG_RATE; + params[0].value.b = CFG_HWRNG_QUALITY; + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *session __unused, + uint32_t cmd, uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + FMSG(PTA_NAME" command %#"PRIx32" ptypes %#"PRIx32, cmd, ptypes); + + switch (cmd) { + case PTA_CMD_GET_ENTROPY: + return rng_get_entropy(ptypes, params); + case PTA_CMD_GET_RNG_INFO: + return rng_get_info(ptypes, params); + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_RNG_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | + TA_FLAG_DEVICE_ENUM, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/imx/digprog.c b/optee/optee_os/core/pta/imx/digprog.c new file mode 100644 index 0000000..ae569cc --- /dev/null +++ b/optee/optee_os/core/pta/imx/digprog.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + */ +#include +#include +#include + +#define DIGPROG_PTA_NAME "digprog.pta" + +static TEE_Result invokeCommandEntryPoint(void *sess_ctx __unused, + uint32_t cmd_id __unused, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + params[0].value.a = imx_get_digprog(); + params[0].value.b = 0; + + return TEE_SUCCESS; +} + +pseudo_ta_register(.uuid = PTA_DIGPROG_UUID, .name = DIGPROG_PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invokeCommandEntryPoint); diff --git a/optee/optee_os/core/pta/imx/manufacturing_protection.c b/optee/optee_os/core/pta/imx/manufacturing_protection.c new file mode 100644 index 0000000..8b1210a --- /dev/null +++ b/optee/optee_os/core/pta/imx/manufacturing_protection.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2018-2019, 2023 NXP + */ +#include +#include +#include +#include +#include +#include +#include + +#define PTA_NAME "manufacturing_protection.pta" + +static TEE_Result mp_get_public_key(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint8_t *data = NULL; + size_t size = 0; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + data = params[0].memref.buffer; + size = params[0].memref.size; + + res = caam_mp_export_publickey(data, &size); + if (res != TEE_SUCCESS) + EMSG("MP public key export failed with code 0x%" PRIx32, res); + + params[0].memref.size = size; + return res; +} + +static TEE_Result mp_signature(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *msg = NULL; + uint8_t *sig = NULL; + uint8_t *mpmr = NULL; + size_t msg_size = 0; + size_t sig_size = 0; + size_t mpmr_size = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + DMSG("MPSign function"); + + msg = params[0].memref.buffer; + msg_size = params[0].memref.size; + sig = params[1].memref.buffer; + sig_size = params[1].memref.size; + mpmr = params[2].memref.buffer; + mpmr_size = params[2].memref.size; + + memset(sig, 0, sig_size); + memset(mpmr, 0, mpmr_size); + + res = caam_mp_sign(msg, &msg_size, sig, &sig_size); + + params[1].memref.size = sig_size; + + if (res != TEE_SUCCESS) { + EMSG("Manufacturing Protection signature failed 0x%" PRIx32, + res); + return res; + } + + res = caam_mp_export_mpmr(mpmr, &mpmr_size); + + params[2].memref.size = mpmr_size; + + if (res != TEE_SUCCESS) + EMSG("Manufacturing Protection export MPRM failed 0x%" PRIx32, + res); + + return res; +} + +static TEE_Result +pta_mp_open_session(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **sess_ctx __unused) +{ + struct ts_session *s = NULL; + + s = ts_get_calling_session(); + if (!s || !is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +static TEE_Result pta_mp_invoke_cmd(void *sess_ctx __unused, + uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case PTA_IMX_MP_CMD_SIGNATURE_MPMR: + return mp_signature(param_types, params); + case PTA_IMX_MP_CMD_GET_PUBLIC_KEY: + return mp_get_public_key(param_types, params); + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} + +pseudo_ta_register(.uuid = PTA_MANUFACT_PROTEC_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .open_session_entry_point = pta_mp_open_session, + .invoke_command_entry_point = pta_mp_invoke_cmd); diff --git a/optee/optee_os/core/pta/imx/ocotp.c b/optee/optee_os/core/pta/imx/ocotp.c new file mode 100644 index 0000000..97dc4df --- /dev/null +++ b/optee/optee_os/core/pta/imx/ocotp.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2021 NXP + */ +#include +#include +#include +#include + +#define OCOTP_PTA_NAME "ocotp.pta" + +static TEE_Result chip_uid(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint8_t val[IMX_UID_SIZE] = { }; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + /* On i.MX platforms, the chip UID is 64 bits long */ + if (params[0].memref.size != sizeof(uint64_t)) + return TEE_ERROR_BAD_PARAMETERS; + + if (tee_otp_get_die_id(val, IMX_UID_SIZE)) + return TEE_ERROR_GENERIC; + + memcpy(params[0].memref.buffer, val, IMX_UID_SIZE); + + return TEE_SUCCESS; +} + +static TEE_Result read_fuse(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + uint32_t val = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.a = 0; + params[1].value.b = 0; + + ret = imx_ocotp_read(params[0].value.a, params[0].value.b, &val); + if (!ret) + params[1].value.a = val; + + return ret; +} + +static TEE_Result invokeCommandEntryPoint(void *sess_ctx __unused, + uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case PTA_OCOTP_CMD_CHIP_UID: + return chip_uid(param_types, params); + case PTA_OCOTP_CMD_READ_FUSE: + return read_fuse(param_types, params); + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} + +pseudo_ta_register(.uuid = PTA_OCOTP_UUID, .name = OCOTP_PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invokeCommandEntryPoint); diff --git a/optee/optee_os/core/pta/imx/sub.mk b/optee/optee_os/core/pta/imx/sub.mk new file mode 100644 index 0000000..faeea9f --- /dev/null +++ b/optee/optee_os/core/pta/imx/sub.mk @@ -0,0 +1,3 @@ +srcs-$(CFG_IMX_DIGPROG) += digprog.c +srcs-$(CFG_IMX_OCOTP) += ocotp.c +srcs-$(CFG_NXP_CAAM_MP_DRV) += manufacturing_protection.c diff --git a/optee/optee_os/core/pta/k3/otp.c b/optee/optee_os/core/pta/k3/otp.c new file mode 100644 index 0000000..bfe87a3 --- /dev/null +++ b/optee/optee_os/core/pta/k3/otp.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Texas Instruments System Control Interface Driver + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * Manorit Chawdhry + */ + +#include +#include +#include +#include + +static TEE_Result write_otp_row(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result ret = TEE_SUCCESS; + const uint32_t exp_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + /* + * Safely get the invocation parameters + */ + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + ret = ti_sci_write_otp_row(params[0].value.a, params[1].value.a, + params[1].value.b); + if (ret) + return ret; + + DMSG("Written the value: 0x%08"PRIx32, params[1].value.a); + + return TEE_SUCCESS; +} + +static TEE_Result read_otp_mmr(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result ret = TEE_SUCCESS; + const uint32_t exp_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + + /* + * Safely get the invocation parameters + */ + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + ret = ti_sci_read_otp_mmr(params[0].value.a, ¶ms[1].value.a); + if (ret) + return ret; + + DMSG("Got the value: 0x%08"PRIx32, params[1].value.a); + + return TEE_SUCCESS; +} + +static TEE_Result lock_otp_row(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result ret = TEE_SUCCESS; + int hw_write_lock = 0; + int hw_read_lock = 0; + int soft_lock = 0; + const uint32_t exp_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + + /* + * Safely get the invocation parameters + */ + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].value.b & K3_OTP_KEYWRITING_SOFT_LOCK) + soft_lock = 0x5A; + if (params[0].value.b & K3_OTP_KEYWRITING_HW_READ_LOCK) + hw_read_lock = 0x5A; + if (params[0].value.b & K3_OTP_KEYWRITING_HW_WRITE_LOCK) + hw_write_lock = 0x5A; + + DMSG("hw_write_lock: 0x%#x", hw_write_lock); + DMSG("hw_read_lock: 0x%#x", hw_read_lock); + DMSG("soft_lock: 0x%#x", soft_lock); + + ret = ti_sci_lock_otp_row(params[0].value.a, hw_write_lock, + hw_read_lock, soft_lock); + + if (ret) + return ret; + + DMSG("Locked the row: 0x%08"PRIx32, params[1].value.a); + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *session __unused, + uint32_t command, uint32_t param_types, + TEE_Param params[4]) +{ + switch (command) { + case TA_OTP_KEYWRITING_CMD_READ_MMR: + return read_otp_mmr(param_types, params); + case TA_OTP_KEYWRITING_CMD_WRITE_ROW: + return write_otp_row(param_types, params); + case TA_OTP_KEYWRITING_CMD_LOCK_ROW: + return lock_otp_row(param_types, params); + default: + EMSG("Command ID 0x%"PRIx32" is not supported", command); + return TEE_ERROR_NOT_SUPPORTED; + } +} + +pseudo_ta_register(.uuid = PTA_K3_OTP_KEYWRITING_UUID, + .name = PTA_K3_OTP_KEYWRITING_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/k3/sub.mk b/optee/optee_os/core/pta/k3/sub.mk new file mode 100644 index 0000000..3c6d8e2 --- /dev/null +++ b/optee/optee_os/core/pta/k3/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_K3_OTP_KEYWRITING) += otp.c diff --git a/optee/optee_os/core/pta/rtc.c b/optee/optee_os/core/pta/rtc.c new file mode 100644 index 0000000..8cc6797 --- /dev/null +++ b/optee/optee_os/core/pta/rtc.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, Linaro Limited + * Copyright (c) 2021, EPAM Systems. All rights reserved. + * Copyright (c) 2022, Microchip + * + */ + +#include +#include +#include +#include +#include +#include + +#define PTA_NAME "rtc.pta" + +static void rtc_pta_copy_time_from_optee(struct pta_rtc_time *pta_time, + struct optee_rtc_time *optee_time) +{ + pta_time->tm_sec = optee_time->tm_sec; + pta_time->tm_min = optee_time->tm_min; + pta_time->tm_hour = optee_time->tm_hour; + pta_time->tm_mday = optee_time->tm_mday; + pta_time->tm_mon = optee_time->tm_mon; + pta_time->tm_year = optee_time->tm_year; + pta_time->tm_wday = optee_time->tm_wday; +} + +static TEE_Result rtc_pta_get_time(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct optee_rtc_time time = { }; + struct pta_rtc_time *pta_time = NULL; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + pta_time = params[0].memref.buffer; + if (!pta_time || params[0].memref.size != sizeof(*pta_time)) + return TEE_ERROR_BAD_PARAMETERS; + + res = rtc_get_time(&time); + if (res) + return res; + + rtc_pta_copy_time_from_optee(pta_time, &time); + + return TEE_SUCCESS; +} + +static TEE_Result rtc_pta_set_time(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct optee_rtc_time time = { }; + struct pta_rtc_time *pta_time = NULL; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + pta_time = params[0].memref.buffer; + if (!pta_time || params[0].memref.size != sizeof(*pta_time)) + return TEE_ERROR_BAD_PARAMETERS; + + time.tm_sec = pta_time->tm_sec; + time.tm_min = pta_time->tm_min; + time.tm_hour = pta_time->tm_hour; + time.tm_mday = pta_time->tm_mday; + time.tm_mon = pta_time->tm_mon; + time.tm_year = pta_time->tm_year; + time.tm_wday = pta_time->tm_wday; + + return rtc_set_time(&time); +} + +static TEE_Result rtc_pta_set_offset(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + return rtc_set_offset((int32_t)params[0].value.a); +} + +static TEE_Result rtc_pta_get_offset(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + long offset = 0; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + res = rtc_get_offset(&offset); + if (res) + return res; + + if (offset > INT32_MAX || offset < INT32_MIN) + return TEE_ERROR_OVERFLOW; + + params[0].value.a = (uint32_t)offset; + + return res; +} + +static TEE_Result rtc_pta_get_info(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct pta_rtc_info *info = NULL; + struct optee_rtc_time range_min = { }; + struct optee_rtc_time range_max = { }; + uint64_t features = 0; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + info = params[0].memref.buffer; + if (!info || params[0].memref.size != sizeof(*info)) + return TEE_ERROR_BAD_PARAMETERS; + + memset(info, 0, sizeof(*info)); + + res = rtc_get_info(&features, &range_min, &range_max); + if (res) + return res; + + info->version = PTA_RTC_INFO_VERSION; + + if (features & RTC_CORRECTION_FEATURE) + info->features |= PTA_RTC_FEATURE_CORRECTION; + + rtc_pta_copy_time_from_optee(&info->range_min, &range_min); + rtc_pta_copy_time_from_optee(&info->range_max, &range_max); + + return TEE_SUCCESS; +} + +static TEE_Result open_session(uint32_t ptypes __unused, + TEE_Param par[TEE_NUM_PARAMS] __unused, + void **session __unused) +{ + struct ts_session *ts = ts_get_current_session(); + struct tee_ta_session *ta_session = to_ta_session(ts); + + /* Only REE kernel is allowed to access RTC */ + if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *session __unused, + uint32_t cmd, uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd) { + case PTA_CMD_RTC_GET_INFO: + return rtc_pta_get_info(ptypes, params); + case PTA_CMD_RTC_GET_TIME: + return rtc_pta_get_time(ptypes, params); + case PTA_CMD_RTC_SET_TIME: + return rtc_pta_set_time(ptypes, params); + case PTA_CMD_RTC_GET_OFFSET: + return rtc_pta_get_offset(ptypes, params); + case PTA_CMD_RTC_SET_OFFSET: + return rtc_pta_set_offset(ptypes, params); + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_RTC_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | + TA_FLAG_DEVICE_ENUM, + .open_session_entry_point = open_session, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/scmi.c b/optee/optee_os/core/pta/scmi.c new file mode 100644 index 0000000..7686435 --- /dev/null +++ b/optee/optee_os/core/pta/scmi.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2021, Linaro Limited + * Copyright (c) 2019-2021, STMicroelectronics + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static uint32_t supported_caps(void) +{ + uint32_t caps = 0; + + if (IS_ENABLED2(_CFG_SCMI_PTA_SMT_HEADER)) + caps |= PTA_SCMI_CAPS_SMT_HEADER; + + if (IS_ENABLED2(_CFG_SCMI_PTA_MSG_HEADER)) + caps |= PTA_SCMI_CAPS_MSG_HEADER; + + return caps; +} + +static TEE_Result cmd_capabilities(uint32_t ptypes, + TEE_Param param[TEE_NUM_PARAMS]) +{ + const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (ptypes != exp_ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + param[0].value.a = supported_caps(); + param[0].value.b = 0; + + return TEE_SUCCESS; +} + +static TEE_Result cmd_process_smt_channel(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + unsigned int channel_id = params[0].value.a; + + if (ptypes != exp_ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { + struct scmi_msg_channel *channel = NULL; + + channel = plat_scmi_get_channel(channel_id); + if (!channel) + return TEE_ERROR_BAD_PARAMETERS; + + scmi_smt_threaded_entry(channel_id); + + return TEE_SUCCESS; + } + + if (IS_ENABLED(CFG_SCMI_SCPFW)) + return scmi_server_smt_process_thread(channel_id); + + return TEE_ERROR_NOT_SUPPORTED; +} + +static TEE_Result cmd_process_smt_message(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + unsigned int channel_id = params[0].value.a; + TEE_Param *param1 = params + 1; + + if (ptypes != exp_ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { + struct scmi_msg_channel *channel = NULL; + + if (param1->memref.size < SMT_BUF_SLOT_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + channel = plat_scmi_get_channel(channel_id); + if (!channel) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * Caller provides the buffer, we bind channel to that buffer. + * Once message is processed, unbind the buffer since it is + * valid only for the current invocation. + */ + scmi_smt_set_shared_buffer(channel, param1->memref.buffer); + scmi_smt_threaded_entry(channel_id); + scmi_smt_set_shared_buffer(channel, NULL); + + return TEE_SUCCESS; + } + + return TEE_ERROR_NOT_SUPPORTED; +} + +static TEE_Result cmd_process_msg_channel(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + unsigned int channel_id = params[0].value.a; + void *in_buf = params[1].memref.buffer; + size_t in_size = params[1].memref.size; + void *out_buf = params[2].memref.buffer; + size_t out_size = params[2].memref.size; + + if (ptypes != exp_pt || !in_buf || !out_buf) + return TEE_ERROR_BAD_PARAMETERS; + + if (IS_ENABLED(CFG_SCMI_MSG_DRIVERS)) { + struct scmi_msg_channel *channel = NULL; + + if (!IS_ENABLED(CFG_SCMI_MSG_SHM_MSG)) + return TEE_ERROR_NOT_SUPPORTED; + + channel = plat_scmi_get_channel(channel_id); + if (!channel) + return TEE_ERROR_BAD_PARAMETERS; + + res = scmi_msg_threaded_entry(channel_id, in_buf, in_size, + out_buf, &out_size); + if (!res) + params[2].memref.size = out_size; + + return res; + } + + if (IS_ENABLED(CFG_SCMI_SCPFW)) { + if (!in_buf || !out_buf) + return TEE_ERROR_BAD_PARAMETERS; + + res = scmi_server_msg_process_thread(channel_id, in_buf, + in_size, out_buf, + &out_size); + if (!res) { + params[2].memref.size = (uint32_t)out_size; + IMSG("scmi optee shm: out %zu", out_size); + } + + return res; + } + + return TEE_ERROR_NOT_SUPPORTED; +} + +static TEE_Result cmd_get_channel_handle(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + unsigned int channel_id = params[0].value.a; + unsigned int caps = params[0].value.b; + + if (ptypes != exp_ptypes || caps & ~PTA_SCMI_CAPS_MASK) + return TEE_ERROR_BAD_PARAMETERS; + + if (!(caps & supported_caps())) + return TEE_ERROR_NOT_SUPPORTED; + + if (IS_ENABLED(CFG_SCMI_MSG_DRIVERS)) { + struct scmi_msg_channel *channel = NULL; + + channel = plat_scmi_get_channel(channel_id); + if (!channel) + return TEE_ERROR_BAD_PARAMETERS; + + channel->threaded = true; + params[0].value.a = scmi_smt_channel_handle(channel_id); + + return TEE_SUCCESS; + } + + if (IS_ENABLED(CFG_SCMI_SCPFW)) { + /* Only check the channel ID is known from SCP-firwmare */ + return scmi_server_get_channel(channel_id, NULL); + } + + return TEE_ERROR_NOT_SUPPORTED; +} + +static TEE_Result pta_scmi_open_session(uint32_t ptypes __unused, + TEE_Param par[TEE_NUM_PARAMS] __unused, + void **session __unused) +{ + struct ts_session *ts = ts_get_current_session(); + struct tee_ta_session *ta_session = to_ta_session(ts); + + /* Only REE kernel is allowed to access SCMI resources */ + if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL) { + DMSG("Expecting TEE_LOGIN_REE_KERNEL"); + return TEE_ERROR_ACCESS_DENIED; + } + + if (IS_ENABLED(CFG_SCMI_MSG_DRIVERS) || IS_ENABLED(CFG_SCMI_SCPFW)) + return TEE_SUCCESS; + + return TEE_ERROR_NOT_SUPPORTED; +} + +static TEE_Result pta_scmi_invoke_command(void *session __unused, uint32_t cmd, + uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + FMSG("SCMI command %#"PRIx32" ptypes %#"PRIx32, cmd, ptypes); + + switch (cmd) { + case PTA_SCMI_CMD_CAPABILITIES: + return cmd_capabilities(ptypes, params); + case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL: + return cmd_process_smt_channel(ptypes, params); + case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE: + return cmd_process_smt_message(ptypes, params); + case PTA_SCMI_CMD_PROCESS_MSG_CHANNEL: + return cmd_process_msg_channel(ptypes, params); + case PTA_SCMI_CMD_GET_CHANNEL_HANDLE: + return cmd_get_channel_handle(ptypes, params); + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} + +pseudo_ta_register(.uuid = PTA_SCMI_UUID, .name = PTA_SCMI_NAME, + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | + TA_FLAG_DEVICE_ENUM, + .open_session_entry_point = pta_scmi_open_session, + .invoke_command_entry_point = pta_scmi_invoke_command); diff --git a/optee/optee_os/core/pta/scp03.c b/optee/optee_os/core/pta/scp03.c new file mode 100644 index 0000000..b5b24ac --- /dev/null +++ b/optee/optee_os/core/pta/scp03.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved + * Author: Jorge Ramirez + */ + +#include +#include +#include + +#define PTA_NAME "pta.scp03" + +static TEE_Result invoke_command(void *session_context __unused, + uint32_t command_id, uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + bool rotate_keys = false; + + FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + switch (command_id) { + case PTA_CMD_ENABLE_SCP03: + if (params[0].value.a == PTA_SCP03_SESSION_ROTATE_KEYS) + rotate_keys = true; + + return crypto_se_enable_scp03(rotate_keys); + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_SCP03_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/secstor_ta_mgmt.c b/optee/optee_os/core/pta/secstor_ta_mgmt.c new file mode 100644 index 0000000..162de43 --- /dev/null +++ b/optee/optee_os/core/pta/secstor_ta_mgmt.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result check_install_conflict(const struct shdr_bootstrap_ta *bs_ta) +{ + TEE_Result res; + struct tee_tadb_ta_read *ta; + TEE_UUID uuid; + const struct tee_tadb_property *prop; + + tee_uuid_from_octets(&uuid, bs_ta->uuid); + res = tee_tadb_ta_open(&uuid, &ta); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return TEE_SUCCESS; + if (res) + return res; + + prop = tee_tadb_ta_get_property(ta); + if (prop->version > bs_ta->ta_version) + res = TEE_ERROR_ACCESS_CONFLICT; + + tee_tadb_ta_close(ta); + return res; +} + +static TEE_Result install_ta(struct shdr *shdr, const uint8_t *nw, + size_t nw_size) +{ + TEE_Result res; + struct tee_tadb_ta_write *ta; + void *hash_ctx = NULL; + size_t offs; + const size_t buf_size = 2 * 4096; + void *buf; + struct tee_tadb_property property; + struct shdr_bootstrap_ta bs_ta; + + if (shdr->img_type != SHDR_BOOTSTRAP_TA) + return TEE_ERROR_SECURITY; + + if (nw_size < (sizeof(struct shdr_bootstrap_ta) + SHDR_GET_SIZE(shdr))) + return TEE_ERROR_SECURITY; + + if (shdr->hash_size > buf_size) + return TEE_ERROR_SECURITY; + + buf = malloc(buf_size); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * Initialize a hash context and run the algorithm over the signed + * header (less the final file hash and its signature of course) + */ + res = crypto_hash_alloc_ctx(&hash_ctx, + TEE_DIGEST_HASH_TO_ALGO(shdr->algo)); + if (res) + goto err; + res = crypto_hash_init(hash_ctx); + if (res) + goto err_free_hash_ctx; + res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr)); + if (res) + goto err_free_hash_ctx; + + offs = SHDR_GET_SIZE(shdr); + memcpy(&bs_ta, nw + offs, sizeof(bs_ta)); + + /* Check that we're not downgrading a TA */ + res = check_install_conflict(&bs_ta); + if (res) + goto err_free_hash_ctx; + + res = crypto_hash_update(hash_ctx, (uint8_t *)&bs_ta, sizeof(bs_ta)); + if (res) + goto err_free_hash_ctx; + offs += sizeof(bs_ta); + + memset(&property, 0, sizeof(property)); + COMPILE_TIME_ASSERT(sizeof(property.uuid) == sizeof(bs_ta.uuid)); + tee_uuid_from_octets(&property.uuid, bs_ta.uuid); + property.version = bs_ta.ta_version; + property.custom_size = 0; + property.bin_size = nw_size - offs; + DMSG("Installing %pUl", (void *)&property.uuid); + + res = tee_tadb_ta_create(&property, &ta); + if (res) + goto err_free_hash_ctx; + + while (offs < nw_size) { + size_t l = MIN(buf_size, nw_size - offs); + + memcpy(buf, nw + offs, l); + res = crypto_hash_update(hash_ctx, buf, l); + if (res) + goto err_ta_finalize; + res = tee_tadb_ta_write(ta, buf, l); + if (res) + goto err_ta_finalize; + offs += l; + } + + res = crypto_hash_final(hash_ctx, buf, shdr->hash_size); + if (res) + goto err_ta_finalize; + if (consttime_memcmp(buf, SHDR_GET_HASH(shdr), shdr->hash_size)) { + res = TEE_ERROR_SECURITY; + goto err_ta_finalize; + } + + crypto_hash_free_ctx(hash_ctx); + free(buf); + return tee_tadb_ta_close_and_commit(ta); + +err_ta_finalize: + tee_tadb_ta_close_and_delete(ta); +err_free_hash_ctx: + crypto_hash_free_ctx(hash_ctx); +err: + free(buf); + return res; +} + +static TEE_Result bootstrap(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res; + struct shdr *shdr; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + shdr = shdr_alloc_and_copy(0, params->memref.buffer, + params->memref.size); + if (!shdr) + return TEE_ERROR_SECURITY; + + res = shdr_verify_signature(shdr); + if (res) + goto out; + + res = install_ta(shdr, params->memref.buffer, params->memref.size); +out: + shdr_free(shdr); + return res; +} + +static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case PTA_SECSTOR_TA_MGMT_BOOTSTRAP: + return bootstrap(param_types, params); + default: + break; + } + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_SECSTOR_TA_MGMT_UUID, .name = "secstor_ta_mgmt", + /* + * TA_FLAG_SINGLE_INSTANCE and TA_FLAG_MULTI_SESSION are + * current part of PTA_DEFAULT_FLAGS, but as this TA + * depends on those two flags we add them explicitly + * too. + */ + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SINGLE_INSTANCE | + TA_FLAG_MULTI_SESSION, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/stats.c b/optee/optee_os/core/pta/stats.c new file mode 100644 index 0000000..74a75bf --- /dev/null +++ b/optee/optee_os/core/pta/stats.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TA_NAME "stats.ta" + +#define STATS_UUID \ + { 0xd96a5b40, 0xe2c7, 0xb1af, \ + { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } + +#define STATS_CMD_PAGER_STATS 0 +#define STATS_CMD_ALLOC_STATS 1 +#define STATS_CMD_MEMLEAK_STATS 2 +/* + * UTEE_ENTRY_FUNC_DUMP_MEMSTATS + * [out] memref[0] Array of context information of loaded TAs + * + * Each cell of the TA information array contains: + * TEE_UUID TA UUID + * uint32_t Non zero if TA panicked, 0 otherwise + * uint32_t Number of sessions opened by the TA + * uint32_t Byte size currently allocated in TA heap + * uint32_t Max bytes allocated since last stats reset + * uint32_t TA heap pool byte size + * uint32_t Number of failed allocation requests + * uint32_t Biggest byte size which allocation failed + * uint32_t Biggest byte size which allocation succeeded + */ +#define STATS_CMD_TA_STATS 3 + +#define STATS_NB_POOLS 4 + +static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + struct malloc_stats *stats; + uint32_t size_to_retrieve; + uint32_t pool_id; + uint32_t i; + + /* + * p[0].value.a = pool id (from 0 to n) + * - 0 means all the pools to be retrieved + * - 1..n means pool id + * p[0].value.b = 0 if no reset of the stats + * p[1].memref.buffer = output buffer to struct malloc_stats + */ + if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE) != type) { + return TEE_ERROR_BAD_PARAMETERS; + } + + pool_id = p[0].value.a; + if (pool_id > STATS_NB_POOLS) + return TEE_ERROR_BAD_PARAMETERS; + + size_to_retrieve = sizeof(struct malloc_stats); + if (!pool_id) + size_to_retrieve *= STATS_NB_POOLS; + + if (p[1].memref.size < size_to_retrieve) { + p[1].memref.size = size_to_retrieve; + return TEE_ERROR_SHORT_BUFFER; + } + p[1].memref.size = size_to_retrieve; + stats = p[1].memref.buffer; + + for (i = 1; i <= STATS_NB_POOLS; i++) { + if ((pool_id) && (i != pool_id)) + continue; + + switch (i) { + case 1: + malloc_get_stats(stats); + strlcpy(stats->desc, "Heap", sizeof(stats->desc)); + if (p[0].value.b) + malloc_reset_stats(); + break; + + case 2: + EMSG("public DDR not managed by secure side anymore"); + break; + + case 3: + tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats, + !!p[0].value.b); + strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc)); + break; + +#ifdef CFG_NS_VIRTUALIZATION + case 4: + nex_malloc_get_stats(stats); + strlcpy(stats->desc, "KHeap", sizeof(stats->desc)); + if (p[0].value.b) + nex_malloc_reset_stats(); + break; +#endif + default: + EMSG("Wrong pool id"); + break; + } + + stats++; + } + + return TEE_SUCCESS; +} + +static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + struct tee_pager_stats stats; + + if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE) != type) { + EMSG("expect 3 output values as argument"); + return TEE_ERROR_BAD_PARAMETERS; + } + + tee_pager_get_stats(&stats); + p[0].value.a = stats.npages; + p[0].value.b = stats.npages_all; + p[1].value.a = stats.ro_hits; + p[1].value.b = stats.rw_hits; + p[2].value.a = stats.hidden_hits; + p[2].value.b = stats.zi_released; + + return TEE_SUCCESS; +} + +static TEE_Result get_memleak_stats(uint32_t type, + TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) +{ + + if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) + return TEE_ERROR_BAD_PARAMETERS; + + mdbg_check(1); + + return TEE_SUCCESS; +} + +static TEE_Result get_user_ta_stats(uint32_t type, + TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) +{ + uint32_t res = TEE_SUCCESS; + + if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE) != type) + return TEE_ERROR_BAD_PARAMETERS; + +#if defined(CFG_TA_STATS) + res = tee_ta_instance_stats(p[0].memref.buffer, + &p[0].memref.size); + if (res != TEE_SUCCESS) + DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res); +#else + res = TEE_ERROR_NOT_SUPPORTED; +#endif + return res; +} + +/* + * Trusted Application Entry Points + */ + +static TEE_Result invoke_command(void *psess __unused, + uint32_t cmd, uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd) { + case STATS_CMD_PAGER_STATS: + return get_pager_stats(ptypes, params); + case STATS_CMD_ALLOC_STATS: + return get_alloc_stats(ptypes, params); + case STATS_CMD_MEMLEAK_STATS: + return get_memleak_stats(ptypes, params); + case STATS_CMD_TA_STATS: + return get_user_ta_stats(ptypes, params); + default: + break; + } + return TEE_ERROR_BAD_PARAMETERS; +} + +pseudo_ta_register(.uuid = STATS_UUID, .name = TA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/stm32mp/bsec_pta.c b/optee/optee_os/core/pta/stm32mp/bsec_pta.c new file mode 100644 index 0000000..107a935 --- /dev/null +++ b/optee/optee_os/core/pta/stm32mp/bsec_pta.c @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static_assert(IS_ENABLED(CFG_STM32_BSEC)); + +#define PTA_NAME "bsec.pta" + +static TEE_Result bsec_check_access(uint32_t otp_id) +{ + if (!stm32_bsec_nsec_can_access_otp(otp_id)) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +static TEE_Result bsec_read_mem(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint32_t *buf = (uint32_t *)params[1].memref.buffer; + uint32_t otp_start = 0; + size_t otp_length = 0; + uint32_t otp_id = 0; + TEE_Result res = TEE_ERROR_GENERIC; + size_t size = params[1].memref.size; + bool locked = false; + unsigned int otp_base_offset = params[0].value.a; + unsigned int bsec_command = params[0].value.b; + + if (pt != exp_pt || !buf || !size || + !IS_ALIGNED_WITH_TYPE(params[1].memref.buffer, uint32_t)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Check 32bits alignment */ + if (otp_base_offset % BSEC_BYTES_PER_WORD || + size % BSEC_BYTES_PER_WORD) + return TEE_ERROR_BAD_PARAMETERS; + + otp_start = otp_base_offset / BSEC_BYTES_PER_WORD; + otp_length = size / BSEC_BYTES_PER_WORD; + + for (otp_id = otp_start; otp_id < otp_start + otp_length; + otp_id++, buf++) { + res = bsec_check_access(otp_id); + switch (bsec_command) { + case PTA_BSEC_SHADOW_ACCESS: + if (res) { + /* Force 0 when access is not allowed */ + *buf = 0x0; + continue; + } + /* Read shadow register */ + res = stm32_bsec_read_otp(buf, otp_id); + FMSG("Read shadow %"PRIu32" val: %#"PRIx32, otp_id, + *buf); + break; + case PTA_BSEC_FUSE_ACCESS: + /* Check access */ + if (res) + goto out; + /* Read fuse value */ + res = stm32_bsec_shadow_read_otp(buf, otp_id); + FMSG("Read fuse %"PRIu32" val: %#"PRIx32, otp_id, *buf); + break; + case PTA_BSEC_LOCKS_ACCESS: + if (res) { + /* Force error when access is not allowed */ + *buf = PTA_BSEC_LOCK_ERROR; + continue; + } + *buf = 0; + /* Read lock value */ + res = stm32_bsec_read_permanent_lock(otp_id, &locked); + if (res) + goto out; + + if (locked) + *buf |= PTA_BSEC_LOCK_PERM; + + res = stm32_bsec_read_sr_lock(otp_id, &locked); + if (res) + goto out; + + if (locked) + *buf |= PTA_BSEC_LOCK_SHADOW_R; + + res = stm32_bsec_read_sw_lock(otp_id, &locked); + if (res) + goto out; + + if (locked) + *buf |= PTA_BSEC_LOCK_SHADOW_W; + + res = stm32_bsec_read_sp_lock(otp_id, &locked); + if (res) + goto out; + + if (locked) + *buf |= PTA_BSEC_LOCK_SHADOW_P; + + FMSG("Read lock %"PRIu32" val: %#"PRIx32, otp_id, *buf); + break; + default: + FMSG("%"PRIu32" invalid operation: %"PRIu32, otp_id, + bsec_command); + res = TEE_ERROR_BAD_PARAMETERS; + } + + if (res) + goto out; + } + + FMSG("Buffer orig %p, size %zu", buf, size); + + res = TEE_SUCCESS; +out: + return res; +} + +static TEE_Result bsec_write_mem(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + uint32_t *buf = (uint32_t *)params[1].memref.buffer; + size_t size = params[1].memref.size; + uint32_t otp_start = 0; + size_t otp_length = 0; + uint32_t otp_id = 0; + TEE_Result res = TEE_ERROR_GENERIC; + unsigned int otp_base_offset = params[0].value.a; + unsigned int bsec_command = params[0].value.b; + + if (pt != exp_pt || !buf || !size || + !IS_ALIGNED_WITH_TYPE(params[1].memref.buffer, uint32_t)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Check 32bits alignment */ + if (otp_base_offset % BSEC_BYTES_PER_WORD || + size % BSEC_BYTES_PER_WORD) + return TEE_ERROR_BAD_PARAMETERS; + + otp_start = otp_base_offset / BSEC_BYTES_PER_WORD; + otp_length = size / BSEC_BYTES_PER_WORD; + + /* Initial check to ensure that all BSEC words are available */ + for (otp_id = otp_start; otp_id < otp_start + otp_length; otp_id++) { + res = bsec_check_access(otp_id); + if (res) + return res; + } + + for (otp_id = otp_start; otp_id < otp_start + otp_length; + otp_id++, buf++) { + switch (bsec_command) { + case PTA_BSEC_SHADOW_ACCESS: + /* Write shadow register */ + FMSG("Write shadow %"PRIx32" : %"PRIx32, + otp_id, *buf); + res = stm32_bsec_write_otp(*buf, otp_id); + break; + + case PTA_BSEC_FUSE_ACCESS: + /* Write fuse value */ + FMSG("Write fuse %"PRIx32" : %08"PRIx32, + otp_id, *buf); + res = stm32_bsec_program_otp(*buf, otp_id); + break; + + case PTA_BSEC_LOCKS_ACCESS: + if (*buf & PTA_BSEC_LOCK_PERM) { + FMSG("Perm lock access OTP: %u", otp_id); + res = stm32_bsec_permanent_lock_otp(otp_id); + if (res) + break; + } + + if (*buf & PTA_BSEC_LOCK_SHADOW_R) { + FMSG("Shadow read lock"); + res = stm32_bsec_set_sr_lock(otp_id); + if (res) + break; + } + + if (*buf & PTA_BSEC_LOCK_SHADOW_W) { + FMSG("Shadow write lock detected"); + res = stm32_bsec_set_sw_lock(otp_id); + if (res) + break; + } + + if (*buf & PTA_BSEC_LOCK_SHADOW_P) { + FMSG("Shadow programming lock detected"); + res = stm32_bsec_set_sp_lock(otp_id); + } + + break; + + default: + FMSG("OTP %"PRIx32" invalid operation: %"PRIx32, + otp_id, bsec_command); + res = TEE_ERROR_BAD_PARAMETERS; + } + + if (res) + return res; + } + + return TEE_SUCCESS; +} + +static TEE_Result bsec_pta_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result res = TEE_ERROR_GENERIC; + enum stm32_bsec_sec_state state = BSEC_STATE_INVALID; + enum stm32_bsec_pta_sec_state pta_state = PTA_BSEC_STATE_INVALID; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + res = stm32_bsec_get_state(&state); + if (res) + return res; + + switch (state) { + case BSEC_STATE_SEC_CLOSED: + pta_state = PTA_BSEC_STATE_SEC_CLOSE; + break; + case BSEC_STATE_SEC_OPEN: + pta_state = PTA_BSEC_STATE_SEC_OPEN; + break; + default: + pta_state = PTA_BSEC_STATE_INVALID; + break; + } + + params[0].value.a = pta_state; + + return TEE_SUCCESS; +} + +static TEE_Result bsec_pta_invoke_command(void *pSessionContext __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + FMSG(PTA_NAME" command %#"PRIx32" ptypes %#"PRIx32, + cmd_id, param_types); + + switch (cmd_id) { + case PTA_BSEC_CMD_READ_OTP: + return bsec_read_mem(param_types, params); + case PTA_BSEC_CMD_WRITE_OTP: + return bsec_write_mem(param_types, params); + case PTA_BSEC_CMD_GET_STATE: + return bsec_pta_state(param_types, params); + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +static TEE_Result pta_bsec_open_session(uint32_t ptypes __unused, + TEE_Param par[TEE_NUM_PARAMS] __unused, + void **session __unused) +{ + uint32_t login = to_ta_session(ts_get_current_session())->clnt_id.login; + + if (login == TEE_LOGIN_REE_KERNEL) + return TEE_SUCCESS; + + return TEE_ERROR_ACCESS_DENIED; +} + +pseudo_ta_register(.uuid = PTA_BSEC_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | + TA_FLAG_DEVICE_ENUM, + .open_session_entry_point = pta_bsec_open_session, + .invoke_command_entry_point = bsec_pta_invoke_command); diff --git a/optee/optee_os/core/pta/stm32mp/sub.mk b/optee/optee_os/core/pta/stm32mp/sub.mk new file mode 100644 index 0000000..ed16c5f --- /dev/null +++ b/optee/optee_os/core/pta/stm32mp/sub.mk @@ -0,0 +1 @@ +srcs-$(CFG_STM32_BSEC_PTA) += bsec_pta.c diff --git a/optee/optee_os/core/pta/sub.mk b/optee/optee_os/core/pta/sub.mk new file mode 100644 index 0000000..2a72c48 --- /dev/null +++ b/optee/optee_os/core/pta/sub.mk @@ -0,0 +1,22 @@ +subdirs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += tests + +srcs-$(CFG_ATTESTATION_PTA) += attestation.c +srcs-$(CFG_TEE_BENCHMARK) += benchmark.c +srcs-$(CFG_DEVICE_ENUM_PTA) += device.c +srcs-$(CFG_TA_GPROF_SUPPORT) += gprof.c +ifeq ($(CFG_WITH_USER_TA),y) +srcs-$(CFG_SECSTOR_TA_MGMT_PTA) += secstor_ta_mgmt.c +endif +srcs-$(CFG_WITH_STATS) += stats.c +srcs-$(CFG_SYSTEM_PTA) += system.c +srcs-$(CFG_SCP03_PTA) += scp03.c +srcs-$(CFG_APDU_PTA) += apdu.c +srcs-$(CFG_SCMI_PTA) += scmi.c +srcs-$(CFG_HWRNG_PTA) += hwrng.c +srcs-$(CFG_RTC_PTA) += rtc.c + +subdirs-y += bcm +subdirs-y += tegra +subdirs-y += stm32mp +subdirs-y += imx +subdirs-y += k3 diff --git a/optee/optee_os/core/pta/system.c b/optee/optee_os/core/pta/system.c new file mode 100644 index 0000000..6df6504 --- /dev/null +++ b/optee/optee_os/core/pta/system.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2022 Linaro Limited + * Copyright (c) 2020, Arm Limited. + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int system_pnum; + +static TEE_Result system_rng_reseed(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t entropy_sz = 0; + uint8_t *entropy_input = NULL; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + entropy_input = params[0].memref.buffer; + entropy_sz = params[0].memref.size; + + if (!entropy_sz || !entropy_input) + return TEE_ERROR_BAD_PARAMETERS; + + crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum, + entropy_input, entropy_sz); + return TEE_SUCCESS; +} + +static TEE_Result system_derive_ta_unique_key(struct user_mode_ctx *uctx, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t data_len = sizeof(TEE_UUID); + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *data = NULL; + uint32_t access_flags = 0; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].memref.size > TA_DERIVED_EXTRA_DATA_MAX_SIZE || + params[1].memref.size < TA_DERIVED_KEY_MIN_SIZE || + params[1].memref.size > TA_DERIVED_KEY_MAX_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * The derived key shall not end up in non-secure memory by + * mistake. + * + * Note that we're allowing shared memory as long as it's + * secure. This is needed because a TA always uses shared memory + * when communicating with another TA. + */ + access_flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER | + TEE_MEMORY_ACCESS_SECURE; + res = vm_check_access_rights(uctx, access_flags, + (uaddr_t)params[1].memref.buffer, + params[1].memref.size); + if (res != TEE_SUCCESS) + return TEE_ERROR_SECURITY; + + /* Take extra data into account. */ + if (ADD_OVERFLOW(data_len, params[0].memref.size, &data_len)) + return TEE_ERROR_SECURITY; + + data = calloc(data_len, 1); + if (!data) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(data, &uctx->ts_ctx->uuid, sizeof(TEE_UUID)); + + /* Append the user provided data */ + memcpy(data + sizeof(TEE_UUID), params[0].memref.buffer, + params[0].memref.size); + + res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len, + params[1].memref.buffer, + params[1].memref.size); + free_wipe(data); + + return res; +} + +static TEE_Result system_map_zi(struct user_mode_ctx *uctx, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE); + uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW; + TEE_Result res = TEE_ERROR_GENERIC; + struct mobj *mobj = NULL; + uint32_t pad_begin = 0; + uint32_t vm_flags = 0; + struct fobj *f = NULL; + uint32_t pad_end = 0; + size_t num_bytes = 0; + vaddr_t va = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + if (params[0].value.b & ~PTA_SYSTEM_MAP_FLAG_SHAREABLE) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].value.b & PTA_SYSTEM_MAP_FLAG_SHAREABLE) + vm_flags |= VM_FLAG_SHAREABLE; + + num_bytes = params[0].value.a; + va = reg_pair_to_64(params[1].value.a, params[1].value.b); + pad_begin = params[2].value.a; + pad_end = params[2].value.b; + + f = fobj_ta_mem_alloc(ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE)); + if (!f) + return TEE_ERROR_OUT_OF_MEMORY; + mobj = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); + fobj_put(f); + if (!mobj) + return TEE_ERROR_OUT_OF_MEMORY; + res = vm_map_pad(uctx, &va, num_bytes, prot, vm_flags, + mobj, 0, pad_begin, pad_end, 0); + mobj_put(mobj); + if (!res) + reg_pair_from_64(va, ¶ms[1].value.a, ¶ms[1].value.b); + + return res; +} + +static TEE_Result system_unmap(struct user_mode_ctx *uctx, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result res = TEE_SUCCESS; + uint32_t vm_flags = 0; + vaddr_t end_va = 0; + vaddr_t va = 0; + size_t sz = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].value.b) + return TEE_ERROR_BAD_PARAMETERS; + + va = reg_pair_to_64(params[1].value.a, params[1].value.b); + sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE); + + /* + * The vm_get_flags() and vm_unmap() are supposed to detect or + * handle overflow directly or indirectly. However, this function + * an API function so an extra guard here is in order. If nothing + * else to make it easier to review the code. + */ + if (ADD_OVERFLOW(va, sz, &end_va)) + return TEE_ERROR_BAD_PARAMETERS; + + res = vm_get_flags(uctx, va, sz, &vm_flags); + if (res) + return res; + if (vm_flags & VM_FLAG_PERMANENT) + return TEE_ERROR_ACCESS_DENIED; + + return vm_unmap(uctx, va, sz); +} + +static TEE_Result system_dlopen(struct user_mode_ctx *uctx, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result res = TEE_ERROR_GENERIC; + struct ts_session *s = NULL; + TEE_UUID *uuid = NULL; + uint32_t flags = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + uuid = params[0].memref.buffer; + if (!uuid || params[0].memref.size != sizeof(*uuid)) + return TEE_ERROR_BAD_PARAMETERS; + + flags = params[1].value.a; + + s = ts_pop_current_session(); + res = ldelf_dlopen(uctx, uuid, flags); + ts_push_current_session(s); + + return res; +} + +static TEE_Result system_dlsym(struct user_mode_ctx *uctx, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Result res = TEE_ERROR_GENERIC; + struct ts_session *s = NULL; + const char *sym = NULL; + TEE_UUID *uuid = NULL; + size_t maxlen = 0; + vaddr_t va = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + uuid = params[0].memref.buffer; + if (!uuid || params[0].memref.size != sizeof(*uuid)) + return TEE_ERROR_BAD_PARAMETERS; + + sym = params[1].memref.buffer; + if (!sym) + return TEE_ERROR_BAD_PARAMETERS; + maxlen = params[1].memref.size; + + s = ts_pop_current_session(); + res = ldelf_dlsym(uctx, uuid, sym, maxlen, &va); + ts_push_current_session(s); + + if (!res) + reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b); + + return res; +} + +static TEE_Result system_get_tpm_event_log(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + size_t size = 0; + TEE_Result res = TEE_SUCCESS; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + size = params[0].memref.size; + res = tpm_get_event_log(params[0].memref.buffer, &size); + params[0].memref.size = size; + + return res; +} + +static TEE_Result system_supp_plugin_invoke(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + TEE_Result res = TEE_ERROR_GENERIC; + size_t outlen = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_invoke_supp_plugin_rpc(params[0].memref.buffer, /* uuid */ + params[1].value.a, /* cmd */ + params[1].value.b, /* sub_cmd */ + params[2].memref.buffer, /* data */ + params[2].memref.size, /* in len */ + &outlen); + params[3].value.a = (uint32_t)outlen; + + return res; +} + +static TEE_Result open_session(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **sess_ctx __unused) +{ + struct ts_session *s = NULL; + + /* Check that we're called from a user TA */ + s = ts_get_calling_session(); + if (!s) + return TEE_ERROR_ACCESS_DENIED; + if (!is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct ts_session *s = ts_get_calling_session(); + struct user_mode_ctx *uctx = to_user_mode_ctx(s->ctx); + + switch (cmd_id) { + case PTA_SYSTEM_ADD_RNG_ENTROPY: + return system_rng_reseed(param_types, params); + case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY: + return system_derive_ta_unique_key(uctx, param_types, params); + case PTA_SYSTEM_MAP_ZI: + return system_map_zi(uctx, param_types, params); + case PTA_SYSTEM_UNMAP: + return system_unmap(uctx, param_types, params); + case PTA_SYSTEM_DLOPEN: + return system_dlopen(uctx, param_types, params); + case PTA_SYSTEM_DLSYM: + return system_dlsym(uctx, param_types, params); + case PTA_SYSTEM_GET_TPM_EVENT_LOG: + return system_get_tpm_event_log(param_types, params); + case PTA_SYSTEM_SUPP_PLUGIN_INVOKE: + return system_supp_plugin_invoke(param_types, params); + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta", + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, + .open_session_entry_point = open_session, + .invoke_command_entry_point = invoke_command); diff --git a/optee/optee_os/core/pta/tegra/jetson_decrypt_cpubl_payload.h b/optee/optee_os/core/pta/tegra/jetson_decrypt_cpubl_payload.h new file mode 100644 index 0000000..d6fe4dd --- /dev/null +++ b/optee/optee_os/core/pta/tegra/jetson_decrypt_cpubl_payload.h @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ +#ifndef JETSON_DECRYPT_CPUBL_PAYLOAD_H +#define JETSON_DECRYPT_CPUBL_PAYLOAD_H + +#include + +#define JETSON_CPUBL_PAYLOAD_DECRYPTION_PRE_INIT 0 +#define JETSON_CPUBL_PAYLOAD_DECRYPTION_INIT 1 +#define JETSON_CPUBL_PAYLOAD_DECRYPTION_UPDATE 2 +#define JETSON_CPUBL_PAYLOAD_DECRYPTION_FINAL 3 + +/* common macro */ +#define BCH_HEADER_MAGIC "NVDA" +#define BCH_HEADER_MAGIC_OFFSET 0U +#define BCH_HEADER_MAGIC_SIZE 4U + +#if defined(PLATFORM_FLAVOR_t234) +/* T234 BCH Header macro */ +#define T234_BCH_HEADER_SIZE 8192U +#define T234_BCH_HEADER_AAD_OFFSET 5120U +#define T234_BCH_HEADER_AAD_SIZE 80U +#define T234_BCH_HEADER_BINARY_LEN_OFFSET 5124U +#define T234_BCH_HEADER_BINARY_LEN_SIZE 4U +#define T234_BCH_HEADER_VER_OFFSET 5136U +#define T234_BCH_HEADER_VER_SIZE 4U +#define T234_BCH_HEADER_DERIVE_STR_OFFSET 5168U +#define T234_BCH_HEADER_DERIVE_STR_SIZE 16U +#define T234_BCH_HEADER_IV_OFFSET 5188U +#define T234_BCH_HEADER_IV_SIZE 12U +#define T234_BCH_HEADER_TAG_OFFSET 5200U +#define T234_BCH_HEADER_TAG_SIZE 16U +#endif + +#if defined(PLATFORM_FLAVOR_t194) +/* T194 BCH Header macro */ +#define T194_BCH_HEADER_SIZE 4096U +#define T194_BCH_HEADER_BINARY_LEN_OFFSET 2996U +#define T194_BCH_HEADER_BINARY_LEN_SIZE 4U +#define T194_BCH_HEADER_IV_SIZE 16U +#define T194_BCH_HEADER_DIGEST_OFFSET 3040U +#define T194_BCH_HEADER_DIGEST_LEN 32U +#endif + +struct dec_ctx { + void *ctx; + uint32_t dec_phase; + uint32_t payload_size; + uint32_t key_len; + uint8_t key[TEGRA_SE_KEY_256_SIZE]; +#if defined(PLATFORM_FLAVOR_t194) + void *hash_ctx; + uint8_t iv_in_hdr[T194_BCH_HEADER_IV_SIZE]; + uint8_t hash_in_hdr[T194_BCH_HEADER_DIGEST_LEN]; +#endif +#if defined(PLATFORM_FLAVOR_t234) + uint8_t iv_in_hdr[T234_BCH_HEADER_IV_SIZE]; + uint8_t aad_in_hdr[T234_BCH_HEADER_AAD_SIZE]; + uint8_t tag_in_hdr[T234_BCH_HEADER_TAG_SIZE]; +#endif +}; + +TEE_Result jetson_decrypt_cpubl_payload_process_params(struct dec_ctx *dec_ctx, + uint8_t *key, uint32_t key_len, + void *img, size_t *img_size); + +TEE_Result jetson_decrypt_cpubl_payload_init(struct dec_ctx *dec_ctx); + +TEE_Result jetson_decrypt_cpubl_payload_update(struct dec_ctx *dec_ctx, + const uint8_t *src_data, uint32_t src_len, + uint8_t *dst_data, size_t *dst_len); + +TEE_Result jetson_decrypt_cpubl_payload_final(struct dec_ctx *dec_ctx, + const uint8_t *src_data, uint32_t src_len, + uint8_t *dst_data, size_t *dst_len); +#endif /* JETSON_DECRYPT_CPUBL_PAYLOAD_H */ diff --git a/optee/optee_os/core/pta/tegra/jetson_t194_decrypt_cpubl_payload.c b/optee/optee_os/core/pta/tegra/jetson_t194_decrypt_cpubl_payload.c new file mode 100644 index 0000000..4b62599 --- /dev/null +++ b/optee/optee_os/core/pta/tegra/jetson_t194_decrypt_cpubl_payload.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include "utee_defines.h" +#include "crypto/crypto.h" +#include "drivers/tegra/tegra_se_keyslot.h" +#include "jetson_decrypt_cpubl_payload.h" + +static TEE_Result get_one_and_zeros_padding(uint8_t *input, + uint32_t input_len, + size_t *data_len) +{ + uint32_t i; + unsigned char done = 0, prev_done, bad; + + if (NULL == input || NULL == data_len) + return TEE_ERROR_BAD_PARAMETERS; + + if ((input_len % TEGRA_SE_AES_BLOCK_SIZE) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + bad = 0x80; + *data_len = 0; + for (i = input_len; i > 0; i--) { + prev_done = done; + done |= (input[i - 1] != 0); + *data_len |= (i - 1) * (done != prev_done); + bad ^= input[i - 1] * (done != prev_done); + } + + if (bad != 0) + *data_len = input_len; + + return TEE_SUCCESS; +} + +TEE_Result jetson_decrypt_cpubl_payload_process_params(struct dec_ctx *dec_ctx, + uint8_t *key, + uint32_t key_len, + void *img, + size_t *img_size) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t *bch; + + if (!dec_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (!key || (key_len == 0)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!img || !img_size) + return TEE_ERROR_BAD_PARAMETERS; + + if (*img_size < T194_BCH_HEADER_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + bch = img; + + if (memcmp(bch + BCH_HEADER_MAGIC_OFFSET, BCH_HEADER_MAGIC, + BCH_HEADER_MAGIC_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(&(dec_ctx->payload_size), + bch + T194_BCH_HEADER_BINARY_LEN_OFFSET, + T194_BCH_HEADER_BINARY_LEN_SIZE); + memset(dec_ctx->iv_in_hdr, 0, T194_BCH_HEADER_IV_SIZE); + memcpy(dec_ctx->hash_in_hdr, bch + T194_BCH_HEADER_DIGEST_OFFSET, + T194_BCH_HEADER_DIGEST_LEN); + dec_ctx->key_len = key_len; + memcpy(dec_ctx->key, key, key_len); + + return res; +} + +TEE_Result jetson_decrypt_cpubl_payload_init(struct dec_ctx *dec_ctx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!dec_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_hash_alloc_ctx(&(dec_ctx->hash_ctx), TEE_ALG_SHA256); + if (res != TEE_SUCCESS) { + EMSG("crypto_hash_alloc_ctx failed with res(%x)", res); + goto out; + } + + res = crypto_hash_init(dec_ctx->hash_ctx); + if (res != TEE_SUCCESS) { + EMSG("crypto_hash_init failed with res(%x)", res); + goto out; + } + + res = crypto_cipher_alloc_ctx(&(dec_ctx->ctx), TEE_ALG_AES_CBC_NOPAD); + if (res != TEE_SUCCESS) { + EMSG("crypto_cipher_alloc_ctx failed with res(%x)", res); + goto out; + } + + res = crypto_cipher_init(dec_ctx->ctx, TEE_MODE_DECRYPT, + dec_ctx->key, dec_ctx->key_len, + NULL, 0, + dec_ctx->iv_in_hdr, T194_BCH_HEADER_IV_SIZE); + if (res != TEE_SUCCESS) + EMSG("crypto_cipher_init failed with res(%x)", res); + +out: + if (res != TEE_SUCCESS) { + if (dec_ctx->ctx) + crypto_cipher_free_ctx(dec_ctx->ctx); + + if (dec_ctx->hash_ctx) + crypto_hash_free_ctx(dec_ctx->hash_ctx); + } + + return res; +} + +TEE_Result jetson_decrypt_cpubl_payload_update(struct dec_ctx *dec_ctx, + const uint8_t *src_data, + uint32_t src_len, + uint8_t *dst_data, + size_t *dst_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!dec_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (!src_data || src_len <= 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (!dst_data || !dst_len) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_hash_update(dec_ctx->hash_ctx, src_data, src_len); + if (res != TEE_SUCCESS) { + goto out; + EMSG("crypto_hash_update failed with res(%x)", res); + } + + res = crypto_cipher_update(dec_ctx->ctx, TEE_MODE_DECRYPT, + false, src_data, + src_len, dst_data); + if (res != TEE_SUCCESS) + EMSG("crypto_cipher_update failed with res(%x)", res); + +out: + if (res != TEE_SUCCESS) { + if (dec_ctx->ctx) + crypto_cipher_free_ctx(dec_ctx->ctx); + + if (dec_ctx->hash_ctx) + crypto_hash_free_ctx(dec_ctx->hash_ctx); + } + + return res; +} + +TEE_Result jetson_decrypt_cpubl_payload_final(struct dec_ctx *dec_ctx, + const uint8_t *src_data, + uint32_t src_len, + uint8_t *dst_data, + size_t *dst_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + size_t final_len; + uint8_t digest[TEE_SHA256_HASH_SIZE] = {0}; + + if (!dec_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (!src_data || src_len <= 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (!dst_data || !dst_len) + return TEE_ERROR_BAD_PARAMETERS; + + final_len = *dst_len; + + res = crypto_hash_update(dec_ctx->hash_ctx, src_data, src_len); + if (res != TEE_SUCCESS) { + EMSG("crypto_hash_update failed with res(%x)", res); + goto out; + } + + res = crypto_cipher_update(dec_ctx->ctx, TEE_MODE_DECRYPT, + false, src_data, + src_len, dst_data); + if (res != TEE_SUCCESS) { + EMSG("crypto_cipher_update failed with res(%x)", res); + goto out; + } + + res = crypto_hash_final(dec_ctx->hash_ctx, digest, + dec_ctx->payload_size); + if (res != TEE_SUCCESS) { + EMSG("crypto_hash_final failed with res(%x)", res); + goto out; + } + + crypto_cipher_final(dec_ctx->ctx); + + if (memcmp(dec_ctx->hash_in_hdr, digest, T194_BCH_HEADER_DIGEST_LEN)) { + res = TEE_ERROR_SECURITY; + goto out; + } + + res = get_one_and_zeros_padding(dst_data, final_len, dst_len); + if (res != TEE_SUCCESS) + EMSG("unpadding failed with res(%x)", res); + +out: + if (dec_ctx->ctx) + crypto_cipher_free_ctx(dec_ctx->ctx); + + if (dec_ctx->hash_ctx) + crypto_hash_free_ctx(dec_ctx->hash_ctx); + + return res; +} diff --git a/optee/optee_os/core/pta/tegra/jetson_t234_decrypt_cpubl_payload.c b/optee/optee_os/core/pta/tegra/jetson_t234_decrypt_cpubl_payload.c new file mode 100644 index 0000000..1af2983 --- /dev/null +++ b/optee/optee_os/core/pta/tegra/jetson_t234_decrypt_cpubl_payload.c @@ -0,0 +1,312 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include "utee_defines.h" +#include "crypto/crypto.h" +#include "drivers/tegra/tegra_se_keyslot.h" +#include "jetson_decrypt_cpubl_payload.h" + +/* + * A software-based NIST-SP 800-108 KDF. + * derives keys from a key in a key buffer. + * + * key [in] input key for derivation. + * key_len [in] length in bytes of the input key. + * context [in] a pointer to a NIST-SP 800-108 context string. + * context_len [in] length in bytes of the contexct. + * label [in] a pointer to a NIST-SP 800-108 label string. + * label_len [in] length in bytes of the label. + * dk_len [in] length of the derived key in bytes; + * may be 16 (128 bits) or any multiple of 16. + * out_dk [out] a pointer to the derived key. The function stores + * its result in this location. + */ +static TEE_Result nist_sp_800_108_hmac_kdf(uint8_t *key, + uint32_t key_len, + uint8_t *context, + uint32_t context_len, + uint8_t *label, + uint32_t label_len, + uint32_t dk_len, + uint8_t *out_dk) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t zero_byte[] = { 0U }; + uint8_t zero_context[] = { 0U }; + uint8_t *p, tmp_buf[TEE_SHA256_HASH_SIZE] = { 0U }; + uint32_t tmp_len; + uint32_t counter[] = { TEE_U32_TO_BIG_ENDIAN( 1 ) }; + uint32_t L[] = { TEE_U32_TO_BIG_ENDIAN(dk_len * 8) }; + uint8_t *message = NULL; + uint8_t *mptr; + uint32_t msg_len; + void *hmac_ctx = NULL; + + if ((key_len != TEGRA_SE_KEY_128_SIZE) && + (key_len != TEGRA_SE_KEY_256_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + + if ((dk_len % TEE_AES_BLOCK_SIZE) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (!key || !label || !out_dk) + return TEE_ERROR_BAD_PARAMETERS; + + if (!context_len){ + context = zero_context; + context_len = sizeof(zero_context); + } + + /* + * Regarding to NIST-SP 800-108 + * message = counter || label || 0 || context || L + * + * A || B = The concatenation of binary strings A and B. + */ + msg_len = sizeof(counter) + context_len + label_len + sizeof(L) + + sizeof(zero_byte); + message = calloc(1, msg_len); + if (message == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Concatenate the messages */ + mptr = message; + memcpy(mptr, counter, sizeof(counter)); + mptr += sizeof(counter); + memcpy(mptr, label, label_len); + mptr += label_len; + memcpy(mptr, zero_byte, sizeof(zero_byte)); + mptr += sizeof(zero_byte); + memcpy(mptr, context, context_len); + mptr += context_len; + memcpy(mptr, L, sizeof(L)); + + /* HMAC-SHA256 */ + res = crypto_mac_alloc_ctx(&hmac_ctx, TEE_ALG_HMAC_SHA256); + if (res) + goto kdf_error; + + tmp_len = dk_len; + p = out_dk; + + while (tmp_len > 0) { + crypto_mac_init(hmac_ctx, key, key_len); + crypto_mac_update(hmac_ctx, message, msg_len); + + if (tmp_len >= TEE_SHA256_HASH_SIZE) { + crypto_mac_final(hmac_ctx, p, TEE_SHA256_HASH_SIZE); + tmp_len -= TEE_SHA256_HASH_SIZE; + p += TEE_SHA256_HASH_SIZE; + } else { + crypto_mac_final(hmac_ctx, tmp_buf, + TEE_SHA256_HASH_SIZE); + memcpy(p, tmp_buf, tmp_len); + break; + } + + /* Update the counter for next use */ + message[0] += 1; + } + + crypto_mac_free_ctx(hmac_ctx); + +kdf_error: + free(message); + return res; +} + +static TEE_Result get_one_and_zeros_padding(uint8_t *input, + uint32_t input_len, + size_t *data_len) +{ + uint32_t i; + unsigned char done = 0, prev_done, bad; + + if (NULL == input || NULL == data_len) + return TEE_ERROR_BAD_PARAMETERS; + + if ((input_len % TEGRA_SE_AES_BLOCK_SIZE) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + bad = 0x80; + *data_len = 0; + for (i = input_len; i > 0; i--) { + prev_done = done; + done |= (input[i - 1] != 0); + *data_len |= (i - 1) * (done != prev_done); + bad ^= input[i - 1] * (done != prev_done); + } + + if (bad != 0) + *data_len = input_len; + + return TEE_SUCCESS; +} + +TEE_Result jetson_decrypt_cpubl_payload_process_params(struct dec_ctx *dec_ctx, + uint8_t *key, + uint32_t key_len, + void *img, + size_t *img_size) +{ + TEE_Result res; + uint8_t *bch; + + if (!dec_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (!key || (key_len == 0)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!img || !img_size) + return TEE_ERROR_BAD_PARAMETERS; + + if (*img_size < T234_BCH_HEADER_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + bch = img; + + if (memcmp(bch + BCH_HEADER_MAGIC_OFFSET, BCH_HEADER_MAGIC, + BCH_HEADER_MAGIC_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + + memcpy(&(dec_ctx->payload_size), + bch + T234_BCH_HEADER_BINARY_LEN_OFFSET, + T234_BCH_HEADER_BINARY_LEN_SIZE); + memcpy(dec_ctx->aad_in_hdr, bch + T234_BCH_HEADER_AAD_OFFSET, + T234_BCH_HEADER_AAD_SIZE); + memcpy(dec_ctx->iv_in_hdr, bch + T234_BCH_HEADER_IV_OFFSET, + T234_BCH_HEADER_IV_SIZE); + memcpy(dec_ctx->tag_in_hdr, bch + T234_BCH_HEADER_TAG_OFFSET, + T234_BCH_HEADER_TAG_SIZE); + dec_ctx->key_len = TEGRA_SE_KEY_256_SIZE; + + res = nist_sp_800_108_hmac_kdf(key, + key_len, + bch + T234_BCH_HEADER_VER_OFFSET, + T234_BCH_HEADER_VER_SIZE, + bch + T234_BCH_HEADER_DERIVE_STR_OFFSET, + T234_BCH_HEADER_DERIVE_STR_SIZE, + dec_ctx->key_len, + dec_ctx->key); + if (res != TEE_SUCCESS) + EMSG("Derive DK failed with res(%x)", res); + + return res; +} + +TEE_Result jetson_decrypt_cpubl_payload_init(struct dec_ctx *dec_ctx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!dec_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_authenc_alloc_ctx(&(dec_ctx->ctx), TEE_ALG_AES_GCM); + if (res != TEE_SUCCESS) { + EMSG("crypto_authenc_alloc_ctx failed with res(%x)", res); + goto out; + } + + res = crypto_authenc_init(dec_ctx->ctx, + TEE_MODE_DECRYPT, + dec_ctx->key, + dec_ctx->key_len, + dec_ctx->iv_in_hdr, + T234_BCH_HEADER_IV_SIZE, + T234_BCH_HEADER_TAG_SIZE, + T234_BCH_HEADER_AAD_SIZE, + dec_ctx->payload_size); + if (res != TEE_SUCCESS) { + EMSG("crypto_authenc_init failed with res(%x)", res); + goto out; + } + + res = crypto_authenc_update_aad(dec_ctx->ctx, + TEE_MODE_DECRYPT, + dec_ctx->aad_in_hdr, + T234_BCH_HEADER_AAD_SIZE); + if (res != TEE_SUCCESS) + EMSG("crypto_authenc_update_aad failed with res(%x)", res); + +out: + if ((res != TEE_SUCCESS) && (dec_ctx->ctx != NULL)) + crypto_authenc_free_ctx(dec_ctx->ctx); + + return res; +} + +TEE_Result jetson_decrypt_cpubl_payload_update(struct dec_ctx *dec_ctx, + const uint8_t *src_data, + uint32_t src_len, + uint8_t *dst_data, + size_t *dst_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (!dec_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (!src_data || src_len <= 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (!dst_data || !dst_len) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_authenc_update_payload(dec_ctx->ctx, TEE_MODE_DECRYPT, + src_data, src_len, + dst_data, dst_len); + if (res != TEE_SUCCESS) + EMSG("crypto_authenc_update_payload failed with res(%x)", res); + + if ((res != TEE_SUCCESS) && (dec_ctx->ctx != NULL)) + crypto_authenc_free_ctx(dec_ctx->ctx); + + return res; +} + + +TEE_Result jetson_decrypt_cpubl_payload_final(struct dec_ctx *dec_ctx, + const uint8_t *src_data, + uint32_t src_len, + uint8_t *dst_data, + size_t *dst_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + size_t final_len; + + if (!dec_ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (!src_data || src_len <= 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (!dst_data || !dst_len) + return TEE_ERROR_BAD_PARAMETERS; + + final_len = *dst_len; + + res = crypto_authenc_dec_final(dec_ctx->ctx, + src_data, src_len, + dst_data, &final_len, + dec_ctx->tag_in_hdr, + T234_BCH_HEADER_TAG_SIZE); + if (res != TEE_SUCCESS) { + EMSG("crypto_authenc_dec_final failed with res(%x)", res); + goto out; + } + + res = get_one_and_zeros_padding(dst_data, final_len, dst_len); + if (res != TEE_SUCCESS) + EMSG("unpadding failed with res(%x)", res); + +out: + if (dec_ctx->ctx) + crypto_authenc_free_ctx(dec_ctx->ctx); + + return res; +} diff --git a/optee/optee_os/core/pta/tegra/jetson_user_key_pta.c b/optee/optee_os/core/pta/tegra/jetson_user_key_pta.c new file mode 100644 index 0000000..7e9908d --- /dev/null +++ b/optee/optee_os/core/pta/tegra/jetson_user_key_pta.c @@ -0,0 +1,907 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021-2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "jetson_decrypt_cpubl_payload.h" + +#define MAX_EKB_RK 2 +#define JETSON_USER_KEY_PTA_NAME "jetson_user_key_pta.ta" + +static vaddr_t ekb_base_addr; + +/* + * Random fixed vector for EKB. + * + * Note: This vector MUST match the 'fv' vector used for EKB binary + * generation process. + * ba d6 6e b4 48 49 83 68 4b 99 2f e5 4a 64 8b b8 + */ +static uint8_t fv_for_ekb[] = { + 0xba, 0xd6, 0x6e, 0xb4, 0x48, 0x49, 0x83, 0x68, + 0x4b, 0x99, 0x2f, 0xe5, 0x4a, 0x64, 0x8b, 0xb8, +}; + +/* + * Random fixed vector used to derive SSK_DK (Derived Key). + * + * e4 20 f5 8d 1d ea b5 24 c2 70 d8 d2 3e ca 45 e8 + */ +static uint8_t fv_for_ssk_dk[] = { + 0xe4, 0x20, 0xf5, 0x8d, 0x1d, 0xea, 0xb5, 0x24, + 0xc2, 0x70, 0xd8, 0xd2, 0x3e, 0xca, 0x45, 0xe8, +}; + +/* + * Root keys derived from SE keyslots. + */ +static uint8_t ekb_rks[MAX_EKB_RK][TEGRA_SE_KEY_128_SIZE]; +static uint8_t ekb_rks_num = 0; +static uint8_t *ekb_rk_verified = NULL; +static uint8_t ssk_rk[TEGRA_SE_KEY_128_SIZE] = { 0 }; +#if defined(PLATFORM_FLAVOR_t194) +static uint8_t demo_256_rk[TEGRA_SE_KEY_256_SIZE] = { 0 }; +#endif + +/* + * Derived keys from NIST-SP 800-108. + */ +static uint8_t ekb_ek[TEGRA_SE_KEY_128_SIZE] = { 0 }; +static uint8_t ekb_ak[TEGRA_SE_KEY_128_SIZE] = { 0 }; + +struct ekb_content_header { + uint32_t enc_data_len; + uint8_t magic[4]; + uint8_t reserved[8]; +}; + +struct ekb_content { + uint8_t ekb_cmac[TEGRA_SE_AES_BLOCK_SIZE]; + struct ekb_content_header content_header; + uint8_t random_iv[TEGRA_SE_AES_IV_SIZE]; + uint8_t ekb_ciphertext[0]; +}; + +typedef struct user_key { + TAILQ_ENTRY(user_key) link; + uint32_t type; + uint32_t len; + uint8_t *data; +} user_key_t; + +static TAILQ_HEAD(user_keys, user_key) user_keys = + TAILQ_HEAD_INITIALIZER(user_keys); + +/* + * HW unique key for tee_otp_get_hw_unique_key + */ +static struct tee_hw_unique_key *hw_unique_key = NULL; + +/* + * Jetson service flag: + * LUKS_SRV_FLAG: Turn on/off for CA to query passphrase + * PTA_SRV_FLAG: Indicate the TA is available or not + */ +static uint32_t jetson_service_flag = LUKS_SRV_FLAG | + PTA_SRV_FLAG; + +/* + * A software-based NIST-SP 800-108 KDF. + * derives keys from a key in a key buffer. + * + * *key [in] input key for derivation. + * key_len [in] length in bytes of the input key. + * *context [in] a pointer to a NIST-SP 800-108 context string. + * context_len [in] length of the context string. + * *label [in] a pointer to a NIST-SP 800-108 label string. + * label_len [in] length of the label string. + * dk_len [in] length of the derived key in bytes; + * may be 16 (128 bits) or any multiple of 16. + * *out_dk [out] a pointer to the derived key. The function stores + * its result in this location. + */ +static TEE_Result nist_sp_800_108_cmac_kdf(uint8_t *key, + uint32_t key_len, + char const *context, + uint32_t context_len, + char const *label, + uint32_t label_len, + uint32_t dk_len, + uint8_t *out_dk) +{ + uint8_t counter[] = { 1 }, zero_byte[] = { 0 }; + uint32_t L[] = { TEE_U32_TO_BIG_ENDIAN(dk_len * 8) }; + uint8_t *message = NULL, *mptr; + uint32_t msg_len, i, n; + void *cmac_ctx = NULL; + TEE_Result rc = TEE_SUCCESS; + + if ((key_len != TEGRA_SE_KEY_128_SIZE) && + (key_len != TEGRA_SE_KEY_256_SIZE)) + return TEE_ERROR_BAD_PARAMETERS; + + if ((dk_len % TEE_AES_BLOCK_SIZE) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (!key || !context || !label || !out_dk) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * Regarding to NIST-SP 800-108 + * message = counter || label || 0 || context || L + * + * A || B = The concatenation of binary strings A and B. + */ + msg_len = context_len + label_len + 2 + sizeof(L); + message = calloc(1, msg_len); + if (message == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + /* Concatenate the messages */ + mptr = message; + memcpy(mptr, counter, sizeof(counter)); + mptr += sizeof(counter); + memcpy(mptr, label, label_len); + mptr += label_len; + memcpy(mptr, zero_byte, sizeof(zero_byte)); + mptr += sizeof(zero_byte); + memcpy(mptr, context, context_len); + mptr += context_len; + memcpy(mptr, L, sizeof(L)); + + /* AES-CMAC */ + rc = crypto_mac_alloc_ctx(&cmac_ctx, TEE_ALG_AES_CMAC); + if (rc) + goto kdf_error; + + /* n: iterations of the PRF count */ + n = dk_len / TEE_AES_BLOCK_SIZE; + + for (i = 0; i < n; i++) { + /* Update the counter */ + message[0] = i + 1; + + crypto_mac_init(cmac_ctx, key, key_len); + crypto_mac_update(cmac_ctx, message, msg_len); + crypto_mac_final(cmac_ctx, (out_dk + (i * TEE_AES_BLOCK_SIZE)), + TEE_AES_BLOCK_SIZE); + } + + crypto_mac_free_ctx(cmac_ctx); + +kdf_error: + free(message); + return rc; +} + +static TEE_Result ekb_extraction_process(vaddr_t ekb_addr) +{ + TEE_Result rc = TEE_SUCCESS; + struct ekb_content *ekb = (struct ekb_content *)ekb_addr; + struct ekb_content_header *content_header = &ekb->content_header; + uint8_t *magic = content_header->magic; + void *decrypted_ekb_content; + void *crypt_ctx = NULL; + uint8_t ekb_cmac_verify[TEGRA_SE_AES_BLOCK_SIZE]; + struct user_key *ekb_key = NULL; + uint8_t *p = NULL; + int i = 0; + + if (magic[0] != 'E' || magic[1] != 'E' || magic[2] != 'K' || magic[3] != 'B') { + EMSG("Bad parameter: eks image not correct\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + + for (i = 0; i < ekb_rks_num; i++) { + memset(ekb_ek, 0, sizeof(ekb_ek)); + memset(ekb_ak, 0, sizeof(ekb_ak)); + memset(ekb_cmac_verify, 0, sizeof(ekb_cmac_verify)); + crypt_ctx = NULL; + ekb_key = NULL; + + /* Derive EKB_EK */ + rc = nist_sp_800_108_cmac_kdf(ekb_rks[i], TEGRA_SE_KEY_128_SIZE, + "ekb", strlen("ekb"), + "encryption", strlen("encryption"), + TEGRA_SE_KEY_128_SIZE, ekb_ek); + if (rc) { + DMSG("Derive EKB_EK from #%d EKB_RK failed: 0x%x.", i, rc); + continue; + } + + /* Derive EKB_AK */ + rc = nist_sp_800_108_cmac_kdf(ekb_rks[i], TEGRA_SE_KEY_128_SIZE, + "ekb", strlen("ekb"), + "authentication", strlen("authentication"), + TEGRA_SE_KEY_128_SIZE, ekb_ak); + if (rc) { + DMSG("Derive EKB_AK from #%d EKB_RK failed: 0x%x.", i, rc); + continue; + } + + /* Calculate the EKB CMAC */ + rc = crypto_mac_alloc_ctx(&crypt_ctx, TEE_ALG_AES_CMAC); + if (rc) + continue; + + crypto_mac_init(crypt_ctx, ekb_ak, sizeof(ekb_ak)); + crypto_mac_update(crypt_ctx, (uint8_t *)content_header, + sizeof(struct ekb_content_header) + sizeof(ekb->random_iv) + + content_header->enc_data_len); + crypto_mac_final(crypt_ctx, ekb_cmac_verify, TEGRA_SE_AES_BLOCK_SIZE); + crypto_mac_free_ctx(crypt_ctx); + + /* Verify the CMAC */ + if (memcmp(ekb->ekb_cmac, ekb_cmac_verify, TEGRA_SE_AES_BLOCK_SIZE)) { + DMSG("EKB signature mismatch when using #%d EKB_RK.", i); + continue; + } + + /* Decrypt the EKB ciphertext */ + rc = crypto_cipher_alloc_ctx(&crypt_ctx, TEE_ALG_AES_CBC_NOPAD); + if (rc) + continue; + + decrypted_ekb_content = malloc(content_header->enc_data_len); + if (!decrypted_ekb_content) { + crypto_cipher_free_ctx(crypt_ctx); + continue; + } + + crypto_cipher_init(crypt_ctx, TEE_MODE_DECRYPT, + ekb_ek, TEGRA_SE_KEY_128_SIZE, + NULL, 0, + ekb->random_iv, TEGRA_SE_AES_BLOCK_SIZE); + crypto_cipher_update(crypt_ctx, TEE_MODE_DECRYPT, false, + ekb->ekb_ciphertext, + content_header->enc_data_len, + (uint8_t*)decrypted_ekb_content); + crypto_cipher_final(crypt_ctx); + crypto_cipher_free_ctx(crypt_ctx); + + p = decrypted_ekb_content; + /* Parse the EKB keys */ + while (true) { + ekb_key = malloc(sizeof(struct user_key)); + if (!ekb_key) { + rc = TEE_ERROR_OUT_OF_MEMORY; + break; + } + + memcpy(&ekb_key->type, p, sizeof(ekb_key->type)); + p = p + sizeof(ekb_key->type); + memcpy(&ekb_key->len, p, sizeof(ekb_key->len)); + if ((ekb_key->type == 0) && (ekb_key->len == 0)) { + free(ekb_key); + break; + } + p = p + sizeof(ekb_key->len); + ekb_key->data = malloc(ekb_key->len); + if (!(ekb_key->data)) { + free(ekb_key); + rc = TEE_ERROR_OUT_OF_MEMORY; + break; + } + memcpy(ekb_key->data, p, ekb_key->len); + p += ekb_key->len; + TAILQ_INSERT_TAIL(&user_keys, ekb_key, link); + } + + free(decrypted_ekb_content); + if (rc == TEE_SUCCESS) { + DMSG("Verified #%d EKB_RK works. Skip other EKB_RK keys.", i); + ekb_rk_verified = ekb_rks[i]; + break; + } + } + + if (i == ekb_rks_num) { + EMSG("Tried all EKB_RKs but still can't extract the EKB image."); + return TEE_ERROR_SECURITY; + } + + return TEE_SUCCESS; +} + +static TEE_Result hwkey_derivation_process(void) +{ + TEE_Result rc = TEE_SUCCESS; + size_t i = 0; +#if defined(PLATFORM_FLAVOR_t194) + se_aes_keyslot_t fuse_key_for_ekb[] = { SE_AES_KEYSLOT_KEK2_128B }; + se_aes_keyslot_t fuse_key_for_ssk = SE_AES_KEYSLOT_SSK; +#endif +#if defined(PLATFORM_FLAVOR_t234) + se_aes_keyslot_t fuse_key_for_ekb[] = { SE_AES_KEYSLOT_OEM_K1, SE_AES_KEYSLOT_OEM_K2 }; + se_aes_keyslot_t fuse_key_for_ssk = SE_AES_KEYSLOT_OEM_K2; +#endif + static_assert(ARRAY_SIZE(fuse_key_for_ekb) <= MAX_EKB_RK); + + memset(ekb_rks, 0, sizeof(ekb_rks)); + for (i = 0; i < ARRAY_SIZE(fuse_key_for_ekb); i++) { + /* + * Derive root keys by performing AES-ECB encryption with the fixed + * vector (fv) and keys in SE keyslots. + */ + rc = tegra_se_aes_ecb_kdf(ekb_rks[ekb_rks_num], sizeof(ekb_rks[ekb_rks_num]), + fv_for_ekb, sizeof(fv_for_ekb), + fuse_key_for_ekb[i]); + if (rc == TEE_SUCCESS) { + DMSG("Derived EKB_RK from #%lu fuse key succeeded", i); + ekb_rks_num++; + } else { + IMSG("Derive EKB_RK from #%lu fuse key failed, ignored.", i); + rc = TEE_SUCCESS; + } + } + + if (ekb_rks_num == 0) { + EMSG("%s: Failed to derive EKB root key from all fuse keys(%x)", __func__, rc); + goto key_derivation_fail; + } + + rc = tegra_se_aes_ecb_kdf(ssk_rk, sizeof(ssk_rk), + fv_for_ssk_dk, sizeof(fv_for_ssk_dk), + fuse_key_for_ssk); + if (rc != TEE_SUCCESS) { + EMSG("%s: Failed to derive SSK root key (%x)", __func__, rc); + /* + * Failing to derive SSK is not a critical issue, to not halt OP-TEE boots, + * reset the rc to SUCCESS so that OP-TEE can keep booting. + */ + rc = TEE_SUCCESS; + } + +#if defined(PLATFORM_FLAVOR_t194) + /* + * Derive 256-bit root key from KEK256 SE keyslot. + * + * To support this, you need to modify the BR BCT file + * e.g. "tegra194-br-bct-sdmmc.cfg" (or "tegra194-br-bct-qspi.cfg"). + * Add "BctKEKKeySelect = 1" into the BR BCT file. + * The BootRom will check the BCT to load KEK0 and KEK1 as a single + * 256-bit fuse into KEK256 SE keyslot. + */ + rc = tegra_se_nist_sp_800_108_cmac_kdf(SE_AES_KEYSLOT_KEK256, + TEGRA_SE_KEY_256_SIZE, + "Derived 256-bit root key", + strlen("Derived 256-bit root key"), + "256-bit key", + strlen("256-bit key"), + TEGRA_SE_KEY_256_SIZE, + demo_256_rk); + if (rc != TEE_SUCCESS) + EMSG("%s: Failed to derive 256-bit root key (%x).", __func__, + rc); +#endif + +key_derivation_fail: + return rc; +} + +/* Override the weak tee_otp_get_hw_unique_key */ +TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) +{ + bool gen_unique_key_fail = false; + + if (hw_unique_key == NULL) { + fuse_ecid_t *ecid; + char ecid_str[36]; + TEE_Result rc; + + hw_unique_key = calloc(1, sizeof(struct tee_hw_unique_key)); + ecid = tegra_fuse_get_ecid(); + + if ((hw_unique_key != NULL) && (ecid != NULL)) { + snprintf(ecid_str, sizeof(ecid_str), "%08x%08x%08x%08x", + ecid->ecid[3], ecid->ecid[2], ecid->ecid[1], + ecid->ecid[0]); + rc = nist_sp_800_108_cmac_kdf(ekb_rk_verified, + TEGRA_SE_KEY_128_SIZE, + ecid_str, + strlen(ecid_str), + "tee-hw-unique-key", + strlen("tee-hw-unique-key"), + HW_UNIQUE_KEY_LENGTH, + hw_unique_key->data); + if (rc) + gen_unique_key_fail = true; + } else { + gen_unique_key_fail = true; + } + } + + if (gen_unique_key_fail) { + memset(&hwkey->data[0], 0, sizeof(hwkey->data)); + if (hw_unique_key != NULL) { + free(hw_unique_key); + hw_unique_key = NULL; + } + } else { + memcpy(hwkey->data, hw_unique_key->data, HW_UNIQUE_KEY_LENGTH); + } + + return TEE_SUCCESS; +} + +static TEE_Result jetson_pta_get_key_by_type(struct user_key **ekb_key, + uint32_t key_type) +{ + struct user_key *tmp_key; + TAILQ_FOREACH(tmp_key, &user_keys, link) + if (tmp_key->type == key_type) { + *ekb_key = tmp_key; + return TEE_SUCCESS; + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +static TEE_Result jetson_pta_get_ekb_key(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result rc = TEE_SUCCESS; + uint32_t key_type = params[0].value.a; + struct user_key *ekb_key; + + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + rc = jetson_pta_get_key_by_type(&ekb_key, key_type); + if (rc) + return rc; + + if (ekb_key->len <= params[1].memref.size) { + memcpy(params[1].memref.buffer, ekb_key->data, ekb_key->len); + params[1].memref.size = ekb_key->len; + } else { + return TEE_ERROR_SHORT_BUFFER; + } + + return rc; +} + +static TEE_Result jetson_pta_get_random(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result rc = TEE_SUCCESS; + + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + rc = tegra_se_rng_get_random(params[0].memref.buffer, + params[0].memref.size); + if (rc != TEE_SUCCESS) { + memset(params[0].memref.buffer, 0, params[0].memref.size); + params[0].memref.size = 0; + } + + return rc; +} + +static TEE_Result jetson_pta_gen_unique_key_by_ekb(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Result rc = TEE_SUCCESS; + fuse_ecid_t *ecid; + char ecid_str[36]; + uint8_t *key; + struct user_key *ekb_key; + uint32_t key_type = params[0].value.a; + + if ((exp_pt != ptypes) || + (params[1].memref.size == 0)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + rc = jetson_pta_get_key_by_type(&ekb_key, key_type); + if (rc) + return rc; + + key = ekb_key->data; + + ecid = tegra_fuse_get_ecid(); + snprintf(ecid_str, sizeof(ecid_str), "%08x%08x%08x%08x", + ecid->ecid[3], ecid->ecid[2], ecid->ecid[1], + ecid->ecid[0]); + + rc = nist_sp_800_108_cmac_kdf(key, TEGRA_SE_KEY_128_SIZE, + ecid_str, + strlen(ecid_str), + params[1].memref.buffer, + params[1].memref.size, + params[2].memref.size, + params[2].memref.buffer); + + return rc; +} + +static TEE_Result jetson_pta_gen_key(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT); + TEE_Result rc = TEE_SUCCESS; + + if ((exp_pt != ptypes) || + (params[1].memref.size == 0) || + (params[2].memref.size == 0)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + rc = nist_sp_800_108_cmac_kdf(params[0].memref.buffer, + params[0].memref.size, + params[1].memref.buffer, + params[1].memref.size, + params[2].memref.buffer, + params[2].memref.size, + params[3].memref.size, + params[3].memref.buffer); + + return rc; +} + +static TEE_Result jetson_pta_get_flag(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result rc = TEE_SUCCESS; + + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + switch (params[0].value.a) { + case LUKS_SRV_FLAG: + break; + default: + return TEE_ERROR_ACCESS_DENIED; + } + + params[1].value.a = jetson_service_flag & params[0].value.a; + + return rc; +} + +static TEE_Result jetson_pta_set_flag(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result rc = TEE_SUCCESS; + + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + switch (params[0].value.a) { + case LUKS_SRV_FLAG: + break; + default: + return TEE_ERROR_ACCESS_DENIED; + } + if (params[0].value.b) + jetson_service_flag |= params[0].value.a; + else + jetson_service_flag &= ~params[0].value.a; + + return rc; +} + +static bool is_zero(const uint8_t *buf, size_t size) +{ + uint8_t v = 0; + size_t i = 0; + + for (i = 0; i < size; i++) + v |= buf[i]; + + return !v; +} + +static TEE_Result jetson_pta_is_key_exists(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t key_type; + struct user_key *ekb_key; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + if (exp_pt != ptypes) + return TEE_ERROR_BAD_PARAMETERS; + + key_type = params[0].value.a; + + /* default key does not exist */ + params[1].value.a = 0; + + if (jetson_pta_get_key_by_type(&ekb_key, key_type)) + goto out; + + if ((ekb_key->len != TEGRA_SE_KEY_128_SIZE) + && (ekb_key->len != TEGRA_SE_KEY_256_SIZE)) + goto out; + + if (is_zero(ekb_key->data, ekb_key->len)) + goto out; + + /* key is exists */ + params[1].value.a = 1; + +out: + return TEE_SUCCESS; +} + +static TEE_Result jetson_pta_decrypt_cpubl_payload(uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t key_type = EKB_USER_KEY_KERNEL_ENCRYPTION; + struct user_key *ekb_key; + static struct dec_ctx ctx = {0}; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + if ((exp_pt != ptypes) || + (params[0].memref.buffer == NULL) || + (params[0].memref.size == 0)) + return TEE_ERROR_BAD_PARAMETERS; + + switch (params[1].value.a) { + case JETSON_CPUBL_PAYLOAD_DECRYPTION_INIT: + if (ctx.dec_phase != JETSON_CPUBL_PAYLOAD_DECRYPTION_PRE_INIT) { + rc = TEE_ERROR_BAD_STATE; + goto error; + } + + rc = jetson_pta_get_key_by_type(&ekb_key, key_type); + if (rc) + goto error; + + if (is_zero(ekb_key->data, ekb_key->len)) { + rc = TEE_ERROR_BAD_PARAMETERS; + goto error; + } + + rc = jetson_decrypt_cpubl_payload_process_params(&ctx, + ekb_key->data, ekb_key->len, + (void *)params[0].memref.buffer, ¶ms[0].memref.size); + if (rc) + goto error; + + rc = jetson_decrypt_cpubl_payload_init(&ctx); + if (rc) + goto error; + + ctx.dec_phase = JETSON_CPUBL_PAYLOAD_DECRYPTION_INIT; + + break; + + case JETSON_CPUBL_PAYLOAD_DECRYPTION_UPDATE: + if (ctx.dec_phase != JETSON_CPUBL_PAYLOAD_DECRYPTION_INIT + && ctx.dec_phase != JETSON_CPUBL_PAYLOAD_DECRYPTION_UPDATE) { + rc = TEE_ERROR_BAD_STATE; + goto error; + } + + rc = jetson_decrypt_cpubl_payload_update(&ctx, + (void *)params[0].memref.buffer, params[0].memref.size, + (void *)params[0].memref.buffer, ¶ms[0].memref.size); + if (rc) + goto error; + + ctx.dec_phase = JETSON_CPUBL_PAYLOAD_DECRYPTION_UPDATE; + + break; + + case JETSON_CPUBL_PAYLOAD_DECRYPTION_FINAL: + if (ctx.dec_phase != JETSON_CPUBL_PAYLOAD_DECRYPTION_INIT + && ctx.dec_phase != JETSON_CPUBL_PAYLOAD_DECRYPTION_UPDATE) { + rc = TEE_ERROR_BAD_STATE; + goto error; + } + + rc = jetson_decrypt_cpubl_payload_final(&ctx, + (void *)params[0].memref.buffer, params[0].memref.size, + (void *)params[0].memref.buffer, ¶ms[0].memref.size); + + memset(&ctx, 0, sizeof(struct dec_ctx)); + + break; + + default: + rc = TEE_ERROR_BAD_PARAMETERS; + } + + return rc; + +error: + memset(&ctx, 0, sizeof(struct dec_ctx)); + return rc; +} + +static TEE_Result invoke_command(void *psess __unused, + uint32_t cmd, uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + if (!(jetson_service_flag & PTA_SRV_FLAG)) + return TEE_ERROR_ACCESS_DENIED; + + switch(cmd) { + case JETSON_USER_KEY_CMD_GET_EKB_KEY: + return jetson_pta_get_ekb_key(ptypes, params); + case JETSON_USER_KEY_CMD_GET_RANDOM: + return jetson_pta_get_random(ptypes, params); + case JETSON_USER_KEY_CMD_GEN_UNIQUE_KEY_BY_EKB: + return jetson_pta_gen_unique_key_by_ekb(ptypes, params); + case JETSON_USER_KEY_CMD_GEN_KEY: + return jetson_pta_gen_key(ptypes, params); + case JETSON_USER_KEY_CMD_GET_FLAG: + return jetson_pta_get_flag(ptypes, params); + case JETSON_USER_KEY_CMD_SET_FLAG: + return jetson_pta_set_flag(ptypes, params); + case JETSON_USER_KEY_CMD_IS_KEY_EXISTS: + return jetson_pta_is_key_exists(ptypes, params); + case JETSON_USER_KEY_CMD_DECRYPT_CPUBL_PAYLOAD: + return jetson_pta_decrypt_cpubl_payload(ptypes, params); + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} + +static TEE_Result open_session(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **sess_ctx __unused) +{ + struct ts_session *s = NULL; + + /* Check that we're called from a user TA */ + s = ts_get_calling_session(); + if (!s || !is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +pseudo_ta_register(.uuid = JETSON_USER_KEY_UUID, + .name = JETSON_USER_KEY_PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .open_session_entry_point = open_session, + .invoke_command_entry_point = invoke_command); + +static const char *const jetson_ekb_dt_match_table[] = { + "jetson-ekb-blob", +}; + +static TEE_Result jetson_ekb_dt_init(void) +{ + void *fdt = NULL; + int node = -1; + uint32_t i = 0; + paddr_t pbase; + ssize_t sz; + + fdt = get_dt(); + if (!fdt) { + EMSG("%s: DTB is not present.", __func__); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + for (i = 0; i < ARRAY_SIZE(jetson_ekb_dt_match_table); i++) { + node = fdt_node_offset_by_compatible(fdt, 0, + jetson_ekb_dt_match_table[i]); + if (node >= 0) + break; + } + + if (node < 0) { + EMSG("%s: DT not found (%x).", __func__, node); + return TEE_ERROR_ITEM_NOT_FOUND; + } + + pbase = fdt_reg_base_address(fdt, node); + if (pbase == DT_INFO_INVALID_REG) + return TEE_ERROR_GENERIC; + + sz = fdt_reg_size(fdt, node); + if (sz < 0) + return TEE_ERROR_GENERIC; + + if (!core_mmu_add_mapping(MEM_AREA_RAM_SEC, pbase, sz)) { + EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA, + (size_t)sz, pbase); + return TEE_ERROR_GENERIC; + } + + ekb_base_addr = (vaddr_t)phys_to_virt(pbase, MEM_AREA_RAM_SEC, sz); + if (!ekb_base_addr) { + EMSG("Failed to get VA for PA 0x%"PRIxPA, pbase); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +static TEE_Result jetson_user_key_pta_init(void) +{ + TEE_Result rc = TEE_SUCCESS; + struct user_key *ekb_key = NULL; + + if (!IS_ENABLED(CFG_DT)) { + rc = TEE_ERROR_NOT_SUPPORTED; + goto pta_init_fail; + } + + rc = jetson_ekb_dt_init(); + if (rc) + goto pta_init_fail; + + /* Derive keys from SE keyslots. */ + rc = hwkey_derivation_process(); + if(rc) + goto pta_init_fail; + + /* EKB extraction */ + rc = ekb_extraction_process(ekb_base_addr); + if (rc) + goto pta_init_fail; + +pta_init_fail: + if (rc) { + jetson_service_flag &= !PTA_SRV_FLAG; + + TAILQ_FOREACH(ekb_key, &user_keys, link) { + if (ekb_key && ekb_key->data) + free(ekb_key->data); + free(ekb_key); + } + + EMSG("%s: Failed (%x).", __func__, rc); +#if defined(CFG_JETSON_MANDATORY_EKB) + panic(); +#endif + } + + return rc; +} + +service_init_late(jetson_user_key_pta_init); diff --git a/optee/optee_os/core/pta/tegra/sub.mk b/optee/optee_os/core/pta/tegra/sub.mk new file mode 100644 index 0000000..c8d6db4 --- /dev/null +++ b/optee/optee_os/core/pta/tegra/sub.mk @@ -0,0 +1,10 @@ +srcs-$(CFG_JETSON_USER_KEY_PTA) += jetson_user_key_pta.c +srcs-$(PLATFORM_FLAVOR_t234) += jetson_t234_decrypt_cpubl_payload.c +srcs-$(PLATFORM_FLAVOR_t194) += jetson_t194_decrypt_cpubl_payload.c + + +# Add source files and include header files from $(NV_OPTEE_DIR) +ifneq ("$(wildcard $(NV_OPTEE_DIR))","") +subdirs_ext-y += $(NV_OPTEE_DIR)/core/pta/tegra +global-incdirs_ext-y += $(NV_OPTEE_DIR)/lib/libutee/include +endif diff --git a/optee/optee_os/core/pta/tests/aes_perf.c b/optee/optee_os/core/pta/tests/aes_perf.c new file mode 100644 index 0000000..84a48e8 --- /dev/null +++ b/optee/optee_os/core/pta/tests/aes_perf.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" + +/* + * These keys and iv are copied from optee_test/ta/aes_perf/ta_aes_perf.c, + * not because their actual values are important, rather that there's no + * reason to use different values. + */ + +static const uint8_t aes_key[] = { + 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 +}; + +static const uint8_t aes_key2[] = { + 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 +}; + +static uint8_t aes_iv[] = { + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF +}; + +static void free_ctx(void **ctx, uint32_t algo) +{ + if (algo == TEE_ALG_AES_GCM) + crypto_authenc_free_ctx(*ctx); + else + crypto_cipher_free_ctx(*ctx); + + *ctx = NULL; +} + +static TEE_Result init_ctx(void **ctx, uint32_t algo, TEE_OperationMode mode, + size_t key_size_bits, size_t payload_len) +{ + TEE_Result res = TEE_SUCCESS; + const uint8_t *key2 = NULL; + const uint8_t *iv = NULL; + size_t key2_len = 0; + size_t key_len = 0; + size_t iv_len = 0; + + if (key_size_bits % 8) + return TEE_ERROR_BAD_PARAMETERS; + key_len = key_size_bits / 8; + if (key_len > sizeof(aes_key)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Alloc ctx */ + switch (algo) { + case TEE_ALG_AES_XTS: + key2_len = key_len; + key2 = aes_key2; + fallthrough; + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CTR: + res = crypto_cipher_alloc_ctx(ctx, algo); + break; + case TEE_ALG_AES_GCM: + res = crypto_authenc_alloc_ctx(ctx, algo); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + if (res) + return res; + + /* Init ctx */ + switch (algo) { + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_XTS: + iv = aes_iv; + iv_len = sizeof(aes_iv); + fallthrough; + case TEE_ALG_AES_ECB_NOPAD: + res = crypto_cipher_init(*ctx, mode, aes_key, key_len, key2, + key2_len, iv, iv_len); + break; + case TEE_ALG_AES_GCM: + res = crypto_authenc_init(*ctx, mode, aes_key, key_len, aes_iv, + sizeof(aes_iv), TEE_AES_BLOCK_SIZE, + 0, payload_len); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (res) + free_ctx(ctx, algo); + + return res; +} + +static TEE_Result update_ae(void *ctx, TEE_OperationMode mode, + const void *src, size_t len, void *dst) +{ + size_t dlen = len; + + return crypto_authenc_update_payload(ctx, mode, src, len, dst, &dlen); +} + +static TEE_Result update_cipher(void *ctx, TEE_OperationMode mode, + const void *src, size_t len, void *dst) +{ + return crypto_cipher_update(ctx, mode, false, src, len, dst); +} + +static TEE_Result do_update(void *ctx, uint32_t algo, TEE_OperationMode mode, + unsigned int rep_count, unsigned int unit_size, + const uint8_t *in, size_t sz, uint8_t *out) +{ + TEE_Result (*update_func)(void *ctx, TEE_OperationMode mode, + const void *src, size_t len, + void *dst) = NULL; + TEE_Result res = TEE_SUCCESS; + unsigned int n = 0; + unsigned int m = 0; + + if (algo == TEE_ALG_AES_GCM) + update_func = update_ae; + else + update_func = update_cipher; + + for (n = 0; n < rep_count; n++) { + for (m = 0; m < sz / unit_size; m++) { + res = update_func(ctx, mode, in + m * unit_size, + unit_size, out + m * unit_size); + if (res) + return res; + } + if (sz % unit_size) + res = update_func(ctx, mode, in + m * unit_size, + sz % unit_size, out + m * unit_size); + } + + return res; +} + +TEE_Result core_aes_perf_tests(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_INOUT); + TEE_Result res = TEE_SUCCESS; + TEE_OperationMode mode = 0; + unsigned int rep_count = 0; + unsigned int unit_size = 0; + size_t key_size_bits = 0; + uint32_t algo = 0; + void *ctx = NULL; + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + switch (params[0].value.b) { + case PTA_INVOKE_TESTS_AES_ECB: + algo = TEE_ALG_AES_ECB_NOPAD; + break; + case PTA_INVOKE_TESTS_AES_CBC: + algo = TEE_ALG_AES_CBC_NOPAD; + break; + case PTA_INVOKE_TESTS_AES_CTR: + algo = TEE_ALG_AES_CTR; + break; + case PTA_INVOKE_TESTS_AES_XTS: + algo = TEE_ALG_AES_XTS; + break; + case PTA_INVOKE_TESTS_AES_GCM: + algo = TEE_ALG_AES_GCM; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].value.a >> 16) + mode = TEE_MODE_DECRYPT; + else + mode = TEE_MODE_ENCRYPT; + + key_size_bits = params[0].value.a & 0xffff; + + rep_count = params[1].value.a; + unit_size = params[1].value.b; + + if (params[2].memref.size > params[3].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + res = init_ctx(&ctx, algo, mode, key_size_bits, params[2].memref.size); + if (res) + return res; + + res = do_update(ctx, algo, mode, rep_count, unit_size, + params[2].memref.buffer, params[2].memref.size, + params[3].memref.buffer); + + free_ctx(&ctx, algo); + return res; +} diff --git a/optee/optee_os/core/pta/tests/fs_htree.c b/optee/optee_os/core/pta/tests/fs_htree.c new file mode 100644 index 0000000..53c1e0f --- /dev/null +++ b/optee/optee_os/core/pta/tests/fs_htree.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" + +/* + * The smallest blocks size that can hold two struct + * tee_fs_htree_node_image or two struct tee_fs_htree_image. + */ +#define TEST_BLOCK_SIZE 144 + +struct test_aux { + uint8_t *data; + size_t data_len; + size_t data_alloced; + uint8_t *block; +}; + +static TEE_Result test_get_offs_size(enum tee_fs_htree_type type, size_t idx, + uint8_t vers, size_t *offs, size_t *size) +{ + const size_t node_size = sizeof(struct tee_fs_htree_node_image); + const size_t block_nodes = TEST_BLOCK_SIZE / (node_size * 2); + size_t pbn = 0; + size_t bidx = 0; + + COMPILE_TIME_ASSERT(TEST_BLOCK_SIZE > + sizeof(struct tee_fs_htree_node_image) * 2); + COMPILE_TIME_ASSERT(TEST_BLOCK_SIZE > + sizeof(struct tee_fs_htree_image) * 2); + + assert(vers == 0 || vers == 1); + + /* + * File layout + * + * phys block 0: + * tee_fs_htree_image vers 0 @ offs = 0 + * tee_fs_htree_image vers 1 @ offs = sizeof(tee_fs_htree_image) + * + * phys block 1: + * tee_fs_htree_node_image 0 vers 0 @ offs = 0 + * tee_fs_htree_node_image 0 vers 1 @ offs = node_size + * + * phys block 2: + * data block 0 vers 0 + * + * phys block 3: + * tee_fs_htree_node_image 1 vers 0 @ offs = 0 + * tee_fs_htree_node_image 1 vers 1 @ offs = node_size + * + * phys block 4: + * data block 0 vers 1 + * + * ... + */ + + switch (type) { + case TEE_FS_HTREE_TYPE_HEAD: + *offs = sizeof(struct tee_fs_htree_image) * vers; + *size = sizeof(struct tee_fs_htree_image); + return TEE_SUCCESS; + case TEE_FS_HTREE_TYPE_NODE: + pbn = 1 + ((idx / block_nodes) * block_nodes * 2); + *offs = pbn * TEST_BLOCK_SIZE + + 2 * node_size * (idx % block_nodes) + + node_size * vers; + *size = node_size; + return TEE_SUCCESS; + case TEE_FS_HTREE_TYPE_BLOCK: + bidx = 2 * idx + vers; + pbn = 2 + bidx + bidx / (block_nodes * 2 - 1); + *offs = pbn * TEST_BLOCK_SIZE; + *size = TEST_BLOCK_SIZE; + return TEE_SUCCESS; + default: + return TEE_ERROR_GENERIC; + } +} + +static TEE_Result test_read_init(void *aux, struct tee_fs_rpc_operation *op, + enum tee_fs_htree_type type, size_t idx, + uint8_t vers, void **data) +{ + TEE_Result res = TEE_SUCCESS; + struct test_aux *a = aux; + size_t offs = 0; + size_t sz = 0; + + res = test_get_offs_size(type, idx, vers, &offs, &sz); + if (res == TEE_SUCCESS) { + memset(op, 0, sizeof(*op)); + op->params[0].u.value.a = (vaddr_t)aux; + op->params[0].u.value.b = offs; + op->params[0].u.value.c = sz; + *data = a->block; + } + + return res; +} + +static void *uint_to_ptr(uintptr_t p) +{ + return (void *)p; +} + +static TEE_Result test_read_final(struct tee_fs_rpc_operation *op, + size_t *bytes) +{ + struct test_aux *a = uint_to_ptr(op->params[0].u.value.a); + size_t offs = op->params[0].u.value.b; + size_t sz = op->params[0].u.value.c; + + if (offs + sz <= a->data_len) + *bytes = sz; + else if (offs <= a->data_len) + *bytes = a->data_len - offs; + else + *bytes = 0; + + memcpy(a->block, a->data + offs, *bytes); + return TEE_SUCCESS; +} + +static TEE_Result test_write_init(void *aux, struct tee_fs_rpc_operation *op, + enum tee_fs_htree_type type, size_t idx, + uint8_t vers, void **data) +{ + return test_read_init(aux, op, type, idx, vers, data); +} + +static TEE_Result test_write_final(struct tee_fs_rpc_operation *op) +{ + struct test_aux *a = uint_to_ptr(op->params[0].u.value.a); + size_t offs = op->params[0].u.value.b; + size_t sz = op->params[0].u.value.c; + size_t end = offs + sz; + + if (end > a->data_alloced) { + EMSG("out of bounds"); + return TEE_ERROR_GENERIC; + } + + memcpy(a->data + offs, a->block, sz); + if (end > a->data_len) + a->data_len = end; + return TEE_SUCCESS; + +} + +static const struct tee_fs_htree_storage test_htree_ops = { + .block_size = TEST_BLOCK_SIZE, + .rpc_read_init = test_read_init, + .rpc_read_final = test_read_final, + .rpc_write_init = test_write_init, + .rpc_write_final = test_write_final, +}; + +#define CHECK_RES(res, cleanup) \ + do { \ + TEE_Result _res = (res); \ + \ + if (_res != TEE_SUCCESS) { \ + EMSG("error: res = %#" PRIx32, _res); \ + { cleanup; } \ + } \ + } while (0) + +static uint32_t val_from_bn_n_salt(size_t bn, size_t n, uint8_t salt) +{ + assert(bn < UINT16_MAX); + assert(n < UINT8_MAX); + return SHIFT_U32(n, 16) | SHIFT_U32(bn, 8) | salt; +} + +static TEE_Result write_block(struct tee_fs_htree **ht, size_t bn, uint8_t salt) +{ + uint32_t b[TEST_BLOCK_SIZE / sizeof(uint32_t)] = { 0 }; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(b); n++) + b[n] = val_from_bn_n_salt(bn, n, salt); + + return tee_fs_htree_write_block(ht, bn, b); +} + +static TEE_Result read_block(struct tee_fs_htree **ht, size_t bn, uint8_t salt) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t b[TEST_BLOCK_SIZE / sizeof(uint32_t)] = { 0 }; + size_t n = 0; + + res = tee_fs_htree_read_block(ht, bn, b); + if (res != TEE_SUCCESS) + return res; + + for (n = 0; n < ARRAY_SIZE(b); n++) { + if (b[n] != val_from_bn_n_salt(bn, n, salt)) { + DMSG("Unpected b[%zu] %#" PRIx32 + "(expected %#" PRIx32 ")", + n, b[n], val_from_bn_n_salt(bn, n, salt)); + return TEE_ERROR_TIME_NOT_SET; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result do_range(TEE_Result (*fn)(struct tee_fs_htree **ht, + size_t bn, uint8_t salt), + struct tee_fs_htree **ht, size_t begin, + size_t num_blocks, size_t salt) +{ + TEE_Result res = TEE_SUCCESS; + size_t n = 0; + + for (n = 0; n < num_blocks; n++) { + res = fn(ht, n + begin, salt); + CHECK_RES(res, goto out); + } + +out: + return res; +} + +static TEE_Result do_range_backwards(TEE_Result (*fn)(struct tee_fs_htree **ht, + size_t bn, uint8_t salt), + struct tee_fs_htree **ht, size_t begin, + size_t num_blocks, size_t salt) +{ + TEE_Result res = TEE_SUCCESS; + size_t n = 0; + + for (n = 0; n < num_blocks; n++) { + res = fn(ht, num_blocks - 1 - n + begin, salt); + CHECK_RES(res, goto out); + } + +out: + return res; +} + +static TEE_Result htree_test_rewrite(struct test_aux *aux, size_t num_blocks, + size_t w_unsync_begin, size_t w_unsync_num) +{ + struct ts_session *sess = ts_get_current_session(); + const TEE_UUID *uuid = &sess->ctx->uuid; + TEE_Result res = TEE_SUCCESS; + struct tee_fs_htree *ht = NULL; + size_t salt = 23; + uint8_t hash[TEE_FS_HTREE_HASH_SIZE] = { 0 }; + + assert((w_unsync_begin + w_unsync_num) <= num_blocks); + + aux->data_len = 0; + memset(aux->data, 0xce, aux->data_alloced); + + res = tee_fs_htree_open(true, hash, uuid, &test_htree_ops, aux, &ht); + CHECK_RES(res, goto out); + + /* + * Intialize all blocks and verify that they read back as + * expected. + */ + res = do_range(write_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + res = do_range(read_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + /* + * Write all blocks again, but starting from the end using a new + * salt, then verify that that read back as expected. + */ + salt++; + res = do_range_backwards(write_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + res = do_range(read_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + /* + * Use a new salt to write all blocks once more and verify that + * they read back as expected. + */ + salt++; + res = do_range(write_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + res = do_range(read_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + /* + * Sync the changes of the nodes to memory, verify that all + * blocks are read back as expected. + */ + res = tee_fs_htree_sync_to_storage(&ht, hash); + CHECK_RES(res, goto out); + + res = do_range(read_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + /* + * Close and reopen the hash-tree + */ + tee_fs_htree_close(&ht); + res = tee_fs_htree_open(false, hash, uuid, &test_htree_ops, aux, &ht); + CHECK_RES(res, goto out); + + /* + * Verify that all blocks are read as expected. + */ + res = do_range(read_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + /* + * Rewrite a few blocks and verify that all blocks are read as + * expected. + */ + res = do_range_backwards(write_block, &ht, w_unsync_begin, w_unsync_num, + salt + 1); + CHECK_RES(res, goto out); + + res = do_range(read_block, &ht, 0, w_unsync_begin, salt); + CHECK_RES(res, goto out); + res = do_range(read_block, &ht, w_unsync_begin, w_unsync_num, salt + 1); + CHECK_RES(res, goto out); + res = do_range(read_block, &ht, w_unsync_begin + w_unsync_num, + num_blocks - (w_unsync_begin + w_unsync_num), salt); + CHECK_RES(res, goto out); + + /* + * Rewrite the blocks from above again with another salt and + * verify that they are read back as expected. + */ + res = do_range(write_block, &ht, w_unsync_begin, w_unsync_num, + salt + 2); + CHECK_RES(res, goto out); + + res = do_range(read_block, &ht, 0, w_unsync_begin, salt); + CHECK_RES(res, goto out); + res = do_range(read_block, &ht, w_unsync_begin, w_unsync_num, salt + 2); + CHECK_RES(res, goto out); + res = do_range(read_block, &ht, w_unsync_begin + w_unsync_num, + num_blocks - (w_unsync_begin + w_unsync_num), salt); + CHECK_RES(res, goto out); + + /* + * Skip tee_fs_htree_sync_to_storage() and call + * tee_fs_htree_close() directly to undo the changes since last + * call to tee_fs_htree_sync_to_storage(). Reopen the hash-tree + * and verify that recent changes indeed was discarded. + */ + tee_fs_htree_close(&ht); + res = tee_fs_htree_open(false, hash, uuid, &test_htree_ops, aux, &ht); + CHECK_RES(res, goto out); + + res = do_range(read_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + + /* + * Close, reopen and verify that all blocks are read as expected + * again but this time based on the counter value in struct + * tee_fs_htree_image. + */ + tee_fs_htree_close(&ht); + res = tee_fs_htree_open(false, NULL, uuid, &test_htree_ops, aux, &ht); + CHECK_RES(res, goto out); + + res = do_range(read_block, &ht, 0, num_blocks, salt); + CHECK_RES(res, goto out); + +out: + tee_fs_htree_close(&ht); + /* + * read_block() returns TEE_ERROR_TIME_NOT_SET in case unexpected + * data is read. + */ + if (res == TEE_ERROR_TIME_NOT_SET) + res = TEE_ERROR_SECURITY; + return res; +} + +static void aux_free(struct test_aux *aux) +{ + if (aux) { + free(aux->data); + free(aux->block); + free(aux); + } +} + +static struct test_aux *aux_alloc(size_t num_blocks) +{ + struct test_aux *aux = NULL; + size_t o = 0; + size_t sz = 0; + + if (test_get_offs_size(TEE_FS_HTREE_TYPE_BLOCK, num_blocks, 1, &o, &sz)) + return NULL; + + aux = calloc(1, sizeof(*aux)); + if (!aux) + return NULL; + + aux->data_alloced = o + sz; + aux->data = malloc(aux->data_alloced); + if (!aux->data) + goto err; + + aux->block = malloc(TEST_BLOCK_SIZE); + if (!aux->block) + goto err; + + return aux; +err: + aux_free(aux); + return NULL; + +} + +static TEE_Result test_write_read(size_t num_blocks) +{ + struct test_aux *aux = aux_alloc(num_blocks); + TEE_Result res = TEE_SUCCESS; + size_t n = 0; + size_t m = 0; + size_t o = 0; + + if (!aux) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * n is the number of block we're going to initialize/use. + * m is the offset from where we'll rewrite blocks and expect + * the changes to be visible until tee_fs_htree_close() is called + * without a call to tee_fs_htree_sync_to_storage() before. + * o is the number of blocks we're rewriting starting at m. + */ + for (n = 0; n < num_blocks; n += 3) { + for (m = 0; m < n; m += 3) { + for (o = 0; o < (n - m); o++) { + res = htree_test_rewrite(aux, n, m, o); + CHECK_RES(res, goto out); + o += 2; + } + } + } + +out: + aux_free(aux); + return res; +} + +static TEE_Result test_corrupt_type(const TEE_UUID *uuid, uint8_t *hash, + size_t num_blocks, struct test_aux *aux, + enum tee_fs_htree_type type, size_t idx) +{ + TEE_Result res = TEE_SUCCESS; + struct test_aux aux2 = *aux; + struct tee_fs_htree *ht = NULL; + size_t offs = 0; + size_t size = 0; + size_t size0 = 0; + size_t n = 0; + + res = test_get_offs_size(type, idx, 0, &offs, &size0); + CHECK_RES(res, return res); + + aux2.data = malloc(aux->data_alloced); + if (!aux2.data) + return TEE_ERROR_OUT_OF_MEMORY; + + n = 0; + while (true) { + memcpy(aux2.data, aux->data, aux->data_len); + + res = test_get_offs_size(type, idx, 0, &offs, &size); + CHECK_RES(res, goto out); + aux2.data[offs + n]++; + res = test_get_offs_size(type, idx, 1, &offs, &size); + CHECK_RES(res, goto out); + aux2.data[offs + n]++; + + /* + * Errors in head or node is detected by + * tee_fs_htree_open() errors in block is detected when + * actually read by do_range(read_block) + */ + res = tee_fs_htree_open(false, hash, uuid, &test_htree_ops, + &aux2, &ht); + if (!res) { + res = do_range(read_block, &ht, 0, num_blocks, 1); + /* + * do_range(read_block,) is supposed to detect the + * error. If TEE_ERROR_TIME_NOT_SET is returned + * read_block() was acutally able to get some data, + * but the data was incorrect. + * + * If res == TEE_SUCCESS or + * res == TEE_ERROR_TIME_NOT_SET + * there's some problem with the htree + * implementation. + */ + if (res == TEE_ERROR_TIME_NOT_SET) { + EMSG("error: data silently corrupted"); + res = TEE_ERROR_SECURITY; + goto out; + } + if (!res) + break; + tee_fs_htree_close(&ht); + } + + /* We've tested the last byte, let's get out of here */ + if (n == size0 - 1) + break; + + /* Increase n exponentionally after 1 to skip some testing */ + if (n) + n += n; + else + n = 1; + + /* Make sure we test the last byte too */ + if (n >= size0) + n = size0 - 1; + } + + if (res) { + res = TEE_SUCCESS; + } else { + EMSG("error: data corruption undetected"); + res = TEE_ERROR_SECURITY; + } +out: + free(aux2.data); + tee_fs_htree_close(&ht); + return res; +} + + + +static TEE_Result test_corrupt(size_t num_blocks) +{ + struct ts_session *sess = ts_get_current_session(); + const TEE_UUID *uuid = &sess->ctx->uuid; + TEE_Result res = TEE_SUCCESS; + struct tee_fs_htree *ht = NULL; + uint8_t hash[TEE_FS_HTREE_HASH_SIZE] = { 0 }; + struct test_aux *aux = NULL; + size_t n = 0; + + aux = aux_alloc(num_blocks); + if (!aux) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + aux->data_len = 0; + memset(aux->data, 0xce, aux->data_alloced); + + /* Write the object and close it */ + res = tee_fs_htree_open(true, hash, uuid, &test_htree_ops, aux, &ht); + CHECK_RES(res, goto out); + res = do_range(write_block, &ht, 0, num_blocks, 1); + CHECK_RES(res, goto out); + res = tee_fs_htree_sync_to_storage(&ht, hash); + CHECK_RES(res, goto out); + tee_fs_htree_close(&ht); + + /* Verify that the object can be read correctly */ + res = tee_fs_htree_open(false, hash, uuid, &test_htree_ops, aux, &ht); + CHECK_RES(res, goto out); + res = do_range(read_block, &ht, 0, num_blocks, 1); + CHECK_RES(res, goto out); + tee_fs_htree_close(&ht); + + res = test_corrupt_type(uuid, hash, num_blocks, aux, + TEE_FS_HTREE_TYPE_HEAD, 0); + CHECK_RES(res, goto out); + for (n = 0; n < num_blocks; n++) { + res = test_corrupt_type(uuid, hash, num_blocks, aux, + TEE_FS_HTREE_TYPE_NODE, n); + CHECK_RES(res, goto out); + } + for (n = 0; n < num_blocks; n++) { + res = test_corrupt_type(uuid, hash, num_blocks, aux, + TEE_FS_HTREE_TYPE_BLOCK, n); + CHECK_RES(res, goto out); + } + +out: + tee_fs_htree_close(&ht); + aux_free(aux); + return res; +} + +TEE_Result core_fs_htree_tests(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS] __unused) +{ + TEE_Result res = TEE_SUCCESS; + + if (nParamTypes) + return TEE_ERROR_BAD_PARAMETERS; + + res = test_write_read(10); + if (res) + return res; + + return test_corrupt(5); +} diff --git a/optee/optee_os/core/pta/tests/invoke.c b/optee/optee_os/core/pta/tests/invoke.c new file mode 100644 index 0000000..bbc761f --- /dev/null +++ b/optee/optee_os/core/pta/tests/invoke.c @@ -0,0 +1,449 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" + +#define TA_NAME "invoke_tests.pta" + +static TEE_Result test_trace(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + IMSG("pseudo TA \"%s\" says \"Hello world !\"", TA_NAME); + + return TEE_SUCCESS; +} + +static int test_v2p2v(void *va, size_t size) +{ + struct ts_session *session = NULL; + paddr_t p = 0; + void *v = NULL; + + if (!va) + return 0; + + session = ts_get_current_session(); + p = virt_to_phys(va); + + /* 0 is not a valid physical address */ + if (!p) + return 1; + + if (to_ta_session(session)->clnt_id.login == TEE_LOGIN_TRUSTED_APP) { + v = phys_to_virt(p, MEM_AREA_TS_VASPACE, size); + } else { + v = phys_to_virt(p, MEM_AREA_NSEC_SHM, size); + if (!v) + v = phys_to_virt(p, MEM_AREA_SDP_MEM, size); + if (!v) + v = phys_to_virt(p, MEM_AREA_SHM_VASPACE, size); + } + + /* + * Return an error only the vaddr found mismatches input address. + * Finding a virtual address from a physical address cannot be painful + * in some case (i.e pager). Moreover this operation is more debug + * related. Thus do not report error if phys_to_virt failed + */ + if (v && va != v) { + EMSG("Failed to p2v/v2p on caller TA memref arguments"); + EMSG("va %p -> pa 0x%" PRIxPA " -> va %p", va, p, v); + return 1; + } + + return 0; +} + +/* + * Check PTA can be invoked with a memory reference on a NULL buffer + */ +static TEE_Result test_entry_memref_null(uint32_t type, + TEE_Param p[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != type) + return TEE_ERROR_BAD_PARAMETERS; + + if (p[0].memref.buffer || p[0].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + 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[TEE_NUM_PARAMS]) +{ + 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: %p/%zu - %p/%zu - %p/%zu - %p/%zu", + 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; + if (test_v2p2v(in, p[0].memref.size)) + return TEE_ERROR_SECURITY; + 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; + if (test_v2p2v(in, p[1].memref.size)) + return TEE_ERROR_SECURITY; + 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; + if (test_v2p2v(in, p[2].memref.size)) + return TEE_ERROR_SECURITY; + 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; + if (test_v2p2v(in, p[3].memref.size)) + return TEE_ERROR_SECURITY; + 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; +} + +/* + * Test access to Secure Data Path memory from pseudo TAs + */ + +static TEE_Result test_inject_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + char *src = p[0].memref.buffer; + char *dst = p[1].memref.buffer; + size_t sz = p[0].memref.size; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != type) { + DMSG("bad parameter types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (p[1].memref.size < sz) { + p[1].memref.size = sz; + return TEE_ERROR_SHORT_BUFFER; + } + + if (!core_vbuf_is(CORE_MEM_NON_SEC, src, sz) || + !core_vbuf_is(CORE_MEM_SDP_MEM, dst, sz)) { + DMSG("bad memref secure attribute"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!sz) + return TEE_SUCCESS; + + /* Check that core can p2v and v2p over memory reference arguments */ + if (test_v2p2v(src, sz) || test_v2p2v(dst, sz)) + return TEE_ERROR_SECURITY; + + if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + memcpy(dst, src, sz); + + if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result test_transform_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + char *buf = p[0].memref.buffer; + size_t sz = p[0].memref.size; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != type) { + DMSG("bad parameter types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!core_vbuf_is(CORE_MEM_SDP_MEM, buf, sz)) { + DMSG("bad memref secure attribute"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!sz) + return TEE_SUCCESS; + + /* Check that core can p2v and v2p over memory reference arguments */ + if (test_v2p2v(buf, sz)) + return TEE_ERROR_SECURITY; + + if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + for (; sz; sz--, buf++) + *buf = ~(*buf) + 1; + + if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +static TEE_Result test_dump_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) +{ + char *src = p[0].memref.buffer; + char *dst = p[1].memref.buffer; + size_t sz = p[0].memref.size; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != type) { + DMSG("bad parameter types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (p[1].memref.size < sz) { + p[1].memref.size = sz; + return TEE_ERROR_SHORT_BUFFER; + } + + if (!core_vbuf_is(CORE_MEM_SDP_MEM, src, sz) || + !core_vbuf_is(CORE_MEM_NON_SEC, dst, sz)) { + DMSG("bad memref secure attribute"); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!sz) + return TEE_SUCCESS; + + /* Check that core can p2v and v2p over memory reference arguments */ + if (test_v2p2v(src, sz) || test_v2p2v(dst, sz)) + return TEE_ERROR_SECURITY; + + if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + memcpy(dst, src, sz); + + if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +/* + * Trusted Application Entry Points + */ + +static TEE_Result create_ta(void) +{ + DMSG("create entry point for pseudo TA \"%s\"", TA_NAME); + return TEE_SUCCESS; +} + +static void destroy_ta(void) +{ + DMSG("destroy entry point for pseudo ta \"%s\"", TA_NAME); +} + +static TEE_Result open_session(uint32_t nParamTypes __unused, + TEE_Param pParams[TEE_NUM_PARAMS] __unused, + void **ppSessionContext __unused) +{ + DMSG("open entry point for pseudo ta \"%s\"", TA_NAME); + return TEE_SUCCESS; +} + +static void close_session(void *pSessionContext __unused) +{ + DMSG("close entry point for pseudo ta \"%s\"", TA_NAME); +} + +static TEE_Result invoke_command(void *pSessionContext __unused, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]) +{ + FMSG("command entry point for pseudo ta \"%s\"", TA_NAME); + + switch (nCommandID) { + case PTA_INVOKE_TESTS_CMD_TRACE: + return test_trace(nParamTypes, pParams); + case PTA_INVOKE_TESTS_CMD_PARAMS: + return test_entry_params(nParamTypes, pParams); + case PTA_INVOKE_TESTS_CMD_MEMREF_NULL: + return test_entry_memref_null(nParamTypes, pParams); + case PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC: + return test_inject_sdp(nParamTypes, pParams); + case PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC: + return test_transform_sdp(nParamTypes, pParams); + case PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC: + return test_dump_sdp(nParamTypes, pParams); + case PTA_INVOKE_TESTS_CMD_SELF_TESTS: + return core_self_tests(nParamTypes, pParams); +#if defined(CFG_REE_FS) && defined(CFG_WITH_USER_TA) + case PTA_INVOKE_TESTS_CMD_FS_HTREE: + return core_fs_htree_tests(nParamTypes, pParams); +#endif + case PTA_INVOKE_TESTS_CMD_MUTEX: + return core_mutex_tests(nParamTypes, pParams); + case PTA_INVOKE_TESTS_CMD_LOCKDEP: + return core_lockdep_tests(nParamTypes, pParams); + case PTA_INVOKE_TEST_CMD_AES_PERF: + return core_aes_perf_tests(nParamTypes, pParams); + case PTA_INVOKE_TESTS_CMD_DT_DRIVER_TESTS: + return core_dt_driver_tests(nParamTypes, pParams); + default: + break; + } + return TEE_ERROR_BAD_PARAMETERS; +} + +pseudo_ta_register(.uuid = PTA_INVOKE_TESTS_UUID, .name = TA_NAME, + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH | + TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM, + .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/optee/optee_os/core/pta/tests/lockdep.c b/optee/optee_os/core/pta/tests/lockdep.c new file mode 100644 index 0000000..3cdca06 --- /dev/null +++ b/optee/optee_os/core/pta/tests/lockdep.c @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +/* + * Test lockdep with hypothetical thread and lock objects + */ + +#include +#include + +#include "misc.h" + +static int self_test_lockdep1(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct lockdep_node_head graph; + struct lockdep_lock_head thread1; + int count = 1; + + DMSG(""); + + TAILQ_INIT(&thread1); + TAILQ_INIT(&graph); + + /* Not locked, expect failure */ + res = __lockdep_lock_release(&thread1, 1); + if (!res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread1, 1); + if (res) + return count; + count++; + + res = __lockdep_lock_release(&thread1, 1); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread1, 1); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread1, 3); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread1, 2); + if (res) + return count; + count++; + + res = __lockdep_lock_release(&thread1, 3); + if (res) + return count; + count++; + + /* Already locked */ + res = __lockdep_lock_acquire(&graph, &thread1, 2); + if (!res) + return count; + + lockdep_graph_delete(&graph); + lockdep_queue_delete(&thread1); + + return 0; +} + +static int self_test_lockdep2(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct lockdep_node_head graph; + struct lockdep_lock_head thread1; + struct lockdep_lock_head thread2; + struct lockdep_lock_head thread3; + int count = 1; + + DMSG(""); + + TAILQ_INIT(&thread1); + TAILQ_INIT(&thread2); + TAILQ_INIT(&thread3); + TAILQ_INIT(&graph); + + res = __lockdep_lock_acquire(&graph, &thread1, 1); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread2, 2); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread1, 2); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread3, 3); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread2, 3); + if (res) + return count; + count++; + + /* Deadlock 1-2-3 */ + res = __lockdep_lock_acquire(&graph, &thread3, 1); + if (!res) + return count; + + lockdep_graph_delete(&graph); + lockdep_queue_delete(&thread1); + lockdep_queue_delete(&thread2); + lockdep_queue_delete(&thread3); + + return 0; +} + +static int self_test_lockdep3(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct lockdep_node_head graph; + struct lockdep_lock_head thread1; + struct lockdep_lock_head thread2; + int count = 1; + + DMSG(""); + + TAILQ_INIT(&thread1); + TAILQ_INIT(&thread2); + TAILQ_INIT(&graph); + + res = __lockdep_lock_tryacquire(&graph, &thread1, 1); + if (res) + return count; + count++; + + res = __lockdep_lock_release(&thread1, 1); + if (res) + return count; + count++; + + res = __lockdep_lock_tryacquire(&graph, &thread1, 1); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread2, 2); + if (res) + return count; + count++; + + res = __lockdep_lock_acquire(&graph, &thread1, 2); + if (res) + return count; + count++; + + /* Deadlock 1-2 */ + res = __lockdep_lock_acquire(&graph, &thread2, 1); + if (!res) + return count; + + lockdep_graph_delete(&graph); + lockdep_queue_delete(&thread1); + lockdep_queue_delete(&thread2); + + return 0; +} + +TEE_Result core_lockdep_tests(uint32_t nParamTypes __unused, + TEE_Param pParams[TEE_NUM_PARAMS] __unused) + +{ + int count = 0; + + count = self_test_lockdep1(); + if (count) + goto out; + count = self_test_lockdep2(); + if (count) + goto out; + count = self_test_lockdep3(); + if (count) + goto out; +out: + if (count) { + DMSG("count=%d", count); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/pta/tests/misc.c b/optee/optee_os/core/pta/tests/misc.c new file mode 100644 index 0000000..63dbea4 --- /dev/null +++ b/optee/optee_os/core/pta/tests/misc.c @@ -0,0 +1,580 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" + +/* + * Enable expect LOG macro to enable/disable self tests traces. + * + * #define LOG DMSG_RAW + * #define LOG(...) + */ +#define LOG(...) + +static int self_test_add_overflow(void) +{ + uint32_t r_u32; + int32_t r_s32; + uintmax_t r_um; + intmax_t r_sm; + + if (ADD_OVERFLOW(8U, 0U, &r_s32)) + return -1; + if (r_s32 != 8) + return -1; + if (ADD_OVERFLOW(32U, 30U, &r_u32)) + return -1; + if (r_u32 != 62) + return -1; + if (!ADD_OVERFLOW(UINT32_MAX, UINT32_MAX, &r_u32)) + return -1; + if (!ADD_OVERFLOW(UINT32_MAX / 2 + 1, UINT32_MAX / 2 + 1, &r_u32)) + return -1; + if (ADD_OVERFLOW(UINT32_MAX / 2, UINT32_MAX / 2 + 1, &r_u32)) + return -1; + if (r_u32 != UINT32_MAX) + return -1; + + if (ADD_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32)) + return -1; + if (r_s32 != -1) + return -1; + if (ADD_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32)) + return -1; + if (r_s32 != -1) + return -1; + if (ADD_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32)) + return -1; + if (r_s32 != -1) + return -1; + + if (ADD_OVERFLOW(INT32_MIN + 1, -1, &r_s32)) + return -1; + if (r_s32 != INT32_MIN) + return -1; + if (!ADD_OVERFLOW(INT32_MIN, -1, &r_s32)) + return -1; + if (!ADD_OVERFLOW(INT32_MIN + 1, -2, &r_s32)) + return -1; + if (!ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_s32)) + return -1; + if (ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_u32)) + return -1; + if (!ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_sm)) + return -1; + if (ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_um)) + return -1; + if (!ADD_OVERFLOW(INT32_MAX / 2 + 1, INT32_MAX / 2 + 1, &r_s32)) + return -1; + if (ADD_OVERFLOW(INT32_MAX / 2, INT32_MAX / 2 + 1, &r_s32)) + return -1; + if (r_s32 != INT32_MAX) + return -1; + + return 0; +} + +static int self_test_sub_overflow(void) +{ + uint32_t r_u32; + int32_t r_s32; + intmax_t r_sm; + + if (SUB_OVERFLOW(8U, 1U, &r_s32)) + return -1; + if (r_s32 != 7) + return -1; + if (SUB_OVERFLOW(32U, 30U, &r_u32)) + return -1; + if (r_u32 != 2) + return -1; + if (!SUB_OVERFLOW(30U, 31U, &r_u32)) + return -1; + + if (SUB_OVERFLOW(30, 31, &r_s32)) + return -1; + if (r_s32 != -1) + return -1; + if (SUB_OVERFLOW(-1, INT32_MAX, &r_s32)) + return -1; + if (r_s32 != INT32_MIN) + return -1; + if (!SUB_OVERFLOW(-2, INT32_MAX, &r_s32)) + return -1; + + if (SUB_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32)) + return -1; + if (r_s32 != 61) + return -1; + if (SUB_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32)) + return -1; + if (r_s32 != 61) + return -1; + if (SUB_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32)) + return -1; + if (r_s32 != -61) + return -1; + if (SUB_OVERFLOW((int32_t)-31, (int32_t)-30, &r_s32)) + return -1; + if (r_s32 != -1) + return -1; + + if (SUB_OVERFLOW((int32_t)31, -(INTMAX_MIN + 1), &r_sm)) + return -1; + if (r_sm != (INTMAX_MIN + 32)) + return -1; + + return 0; +} + +static int self_test_mul_unsigned_overflow(void) +{ + const size_t um_half_shift = sizeof(uintmax_t) * 8 / 2; + const uintmax_t um_half_mask = UINTMAX_MAX >> um_half_shift; + uint32_t r_u32; + uintmax_t r_um; + + if (MUL_OVERFLOW(32, 30, &r_u32)) + return -1; + if (r_u32 != 960) + return -1; + if (MUL_OVERFLOW(-32, -30, &r_u32)) + return -1; + if (r_u32 != 960) + return -1; + + if (MUL_OVERFLOW(UINTMAX_MAX, 1, &r_um)) + return -1; + if (r_um != UINTMAX_MAX) + return -1; + if (MUL_OVERFLOW(UINTMAX_MAX / 4, 4, &r_um)) + return -1; + if (r_um != (UINTMAX_MAX - 3)) + return -1; + if (!MUL_OVERFLOW(UINTMAX_MAX / 4 + 1, 4, &r_um)) + return -1; + if (!MUL_OVERFLOW(UINTMAX_MAX, UINTMAX_MAX, &r_um)) + return -1; + if (!MUL_OVERFLOW(um_half_mask << um_half_shift, + um_half_mask << um_half_shift, &r_um)) + return -1; + + return 0; +} + +static int self_test_mul_signed_overflow(void) +{ + intmax_t r; + + if (MUL_OVERFLOW(32, -30, &r)) + return -1; + if (r != -960) + return -1; + if (MUL_OVERFLOW(-32, 30, &r)) + return -1; + if (r != -960) + return -1; + if (MUL_OVERFLOW(32, 30, &r)) + return -1; + if (r != 960) + return -1; + + if (MUL_OVERFLOW(INTMAX_MAX, 1, &r)) + return -1; + if (r != INTMAX_MAX) + return -1; + if (MUL_OVERFLOW(INTMAX_MAX / 4, 4, &r)) + return -1; + if (r != (INTMAX_MAX - 3)) + return -1; + if (!MUL_OVERFLOW(INTMAX_MAX / 4 + 1, 4, &r)) + return -1; + if (!MUL_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r)) + return -1; + if (MUL_OVERFLOW(INTMAX_MIN + 1, 1, &r)) + return -1; + if (r != INTMAX_MIN + 1) + return -1; + if (MUL_OVERFLOW(1, INTMAX_MIN + 1, &r)) + return -1; + if (r != INTMAX_MIN + 1) + return -1; + if (MUL_OVERFLOW(0, INTMAX_MIN, &r)) + return -1; + if (r != 0) + return -1; + if (MUL_OVERFLOW(1, INTMAX_MIN, &r)) + return -1; + if (r != INTMAX_MIN) + return -1; + + return 0; +} + +/* test division support. resulting trace shall be manually checked */ +static int self_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)(vaddr_t)&a & 0xFFFFF); + b = (signed)((unsigned)(vaddr_t)&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)(vaddr_t)&a; + b = (signed)((unsigned)(vaddr_t)&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)(vaddr_t)&a & 0xFFFFF); + b = -(signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1; + c = a / b; + d = a % b; + + LOG("- test with unsigned integers, big numerator (> 0x80000000):"); + a = (signed)(vaddr_t)&a; + b = (signed)((unsigned)(vaddr_t)&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)(vaddr_t)&a; + b = (signed)((unsigned)(vaddr_t)&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 self_test_malloc(void) +{ + char *p1 = NULL, *p2 = NULL; + int *p3 = NULL, *p4 = NULL; + bool r; + int ret = 0; + + LOG("malloc tests:"); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)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", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + r = (p1 && p2 && malloc_buffer_is_within_alloced(p1, 1024) && + !malloc_buffer_is_within_alloced(p1 + 25, 1000) && + !malloc_buffer_is_within_alloced(p1 - 25, 500) && + malloc_buffer_overlaps_heap(p1 - 25, 500)); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + + /* test realloc */ + p3 = realloc(p1, 3 * 1024); + if (p3) + p1 = NULL; + LOG("- p3 = 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", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + r = (p2 && p3); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- free p1, p2, p3"); + free(p1); + free(p2); + free(p3); + p1 = NULL; + p2 = NULL; + p3 = NULL; + + /* test calloc */ + p3 = calloc(4, 1024); + p4 = calloc(0x100, 1024 * 1024); + LOG("- p3 = calloc(4, 1024)"); + LOG("- p4 = calloc(0x100, 1024*1024) too big: should fail!"); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)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(0x1000, 1024); + LOG("- p3 = memalign(%d, 1024)", 0x1000); + p1 = malloc(1024); + LOG("- p1 = malloc(1024)"); + p4 = memalign(0x100, 512); + LOG("- p4 = memalign(%d, 512)", 0x100); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + r = (p1 && p3 && p4 && + !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100)); + 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", + (void *)p1, (void *)p2, (void *)p3, (void *)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; +} + +#ifdef CFG_NS_VIRTUALIZATION +/* test nex_malloc support. resulting trace shall be manually checked */ +static int self_test_nex_malloc(void) +{ + char *p1 = NULL, *p2 = NULL; + int *p3 = NULL, *p4 = NULL; + bool r; + int ret = 0; + + LOG("nex_malloc tests:"); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + /* test malloc */ + p1 = nex_malloc(1024); + LOG("- p1 = nex_malloc(1024)"); + p2 = nex_malloc(1024); + LOG("- p2 = nex_malloc(1024)"); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + r = (p1 && p2 && nex_malloc_buffer_is_within_alloced(p1, 1024) && + !nex_malloc_buffer_is_within_alloced(p1 + 25, 1000) && + !nex_malloc_buffer_is_within_alloced(p1 - 25, 500) && + nex_malloc_buffer_overlaps_heap(p1 - 25, 500)); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + + /* test realloc */ + p3 = nex_realloc(p1, 3 * 1024); + if (p3) + p1 = NULL; + LOG("- p3 = nex_realloc(p1, 3*1024)"); + LOG("- nex_free p2"); + nex_free(p2); + p2 = nex_malloc(1024); + LOG("- p2 = nex_malloc(1024)"); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + r = (p2 && p3); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- nex_free p1, p2, p3"); + nex_free(p1); + nex_free(p2); + nex_free(p3); + p1 = NULL; + p2 = NULL; + p3 = NULL; + + /* test calloc */ + p3 = nex_calloc(4, 1024); + p4 = nex_calloc(0x100, 1024 * 1024); + LOG("- p3 = nex_calloc(4, 1024)"); + LOG("- p4 = nex_calloc(0x100, 1024*1024) too big: should fail!"); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + r = (p3 && !p4); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- nex_free p3, p4"); + nex_free(p3); + nex_free(p4); + p3 = NULL; + p4 = NULL; + + /* test memalign */ + p3 = nex_memalign(0x1000, 1024); + LOG("- p3 = nex_memalign(%d, 1024)", 0x1000); + p1 = nex_malloc(1024); + LOG("- p1 = nex_malloc(1024)"); + p4 = nex_memalign(0x100, 512); + LOG("- p4 = nex_memalign(%d, 512)", 0x100); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + r = (p1 && p3 && p4 && + !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100)); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- nex_free p1, p3, p4"); + nex_free(p1); + nex_free(p3); + nex_free(p4); + p1 = NULL; + p3 = NULL; + p4 = NULL; + + /* test memalign with invalid alignments */ + p3 = nex_memalign(100, 1024); + LOG("- p3 = nex_memalign(%d, 1024)", 100); + p4 = nex_memalign(0, 1024); + LOG("- p4 = nex_memalign(%d, 1024)", 0); + LOG(" p1=%p p2=%p p3=%p p4=%p", + (void *)p1, (void *)p2, (void *)p3, (void *)p4); + r = (!p3 && !p4); + if (!r) + ret = -1; + LOG(" => test %s", r ? "ok" : "FAILED"); + LOG(""); + LOG("- nex_free p3, p4"); + nex_free(p3); + nex_free(p4); + p3 = NULL; + p4 = NULL; + + /* test free(NULL) */ + LOG("- nex_free NULL"); + nex_free(NULL); + LOG(""); + LOG("nex_malloc test done"); + + return ret; +} +#else /* CFG_NS_VIRTUALIZATION */ +static int self_test_nex_malloc(void) +{ + return 0; +} +#endif + +/* exported entry points for some basic test */ +TEE_Result core_self_tests(uint32_t nParamTypes __unused, + TEE_Param pParams[TEE_NUM_PARAMS] __unused) +{ + if (self_test_mul_signed_overflow() || self_test_add_overflow() || + self_test_sub_overflow() || self_test_mul_unsigned_overflow() || + self_test_division() || self_test_malloc() || + self_test_nex_malloc()) { + EMSG("some self_test_xxx failed! you should enable local LOG"); + return TEE_ERROR_GENERIC; + } + return TEE_SUCCESS; +} + +/* Exported entrypoint for dt_driver tests */ +TEE_Result core_dt_driver_tests(uint32_t nParamTypes __unused, + TEE_Param pParams[TEE_NUM_PARAMS] __unused) +{ + if (IS_ENABLED(CFG_DT_DRIVER_EMBEDDED_TEST)) { + if (dt_driver_test_status()) + return TEE_ERROR_GENERIC; + } else { + IMSG("dt_driver tests are not embedded"); + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/pta/tests/misc.h b/optee/optee_os/core/pta/tests/misc.h new file mode 100644 index 0000000..58aced4 --- /dev/null +++ b/optee/optee_os/core/pta/tests/misc.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef CORE_PTA_TESTS_MISC_H +#define CORE_PTA_TESTS_MISC_H + +#include +#include +#include + +/* basic run-time tests */ +TEE_Result core_self_tests(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]); + +TEE_Result core_fs_htree_tests(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]); + +TEE_Result core_mutex_tests(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]); + +#ifdef CFG_LOCKDEP +TEE_Result core_lockdep_tests(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]); +#else +static inline TEE_Result core_lockdep_tests( + uint32_t nParamTypes __unused, + TEE_Param pParams[TEE_NUM_PARAMS] __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +TEE_Result core_aes_perf_tests(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]); + +TEE_Result core_dt_driver_tests(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]); + +#endif /*CORE_PTA_TESTS_MISC_H*/ diff --git a/optee/optee_os/core/pta/tests/mutex.c b/optee/optee_os/core/pta/tests/mutex.c new file mode 100644 index 0000000..f1020a1 --- /dev/null +++ b/optee/optee_os/core/pta/tests/mutex.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include + +#include "misc.h" + +static uint32_t before_lock_readers; +static uint32_t before_lock_writers; +static uint32_t during_lock_readers; +static uint32_t during_lock_writers; + +static uint64_t val0; +static uint64_t val1; + +struct mutex test_mutex = MUTEX_INITIALIZER; + +static TEE_Result mutex_test_writer(TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t n; + + params[1].value.a = atomic_inc32(&before_lock_writers); + + mutex_lock(&test_mutex); + + atomic_dec32(&before_lock_writers); + + params[1].value.b = atomic_inc32(&during_lock_writers); + + for (n = 0; n < params[0].value.b; n++) { + val0++; + val1++; + val1++; + } + + atomic_dec32(&during_lock_writers); + mutex_unlock(&test_mutex); + + return TEE_SUCCESS; +} + +static TEE_Result mutex_test_reader(TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + size_t n; + + params[1].value.a = atomic_inc32(&before_lock_readers); + + mutex_read_lock(&test_mutex); + + atomic_dec32(&before_lock_readers); + + params[1].value.b = atomic_inc32(&during_lock_readers); + + for (n = 0; n < params[0].value.b; n++) { + if (val0 * 2 != val1) + res = TEE_ERROR_BAD_STATE; + } + + atomic_dec32(&during_lock_readers); + mutex_read_unlock(&test_mutex); + + return res; +} + +TEE_Result core_mutex_tests(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) { + DMSG("bad parameter types"); + return TEE_ERROR_BAD_PARAMETERS; + } + + switch (params[0].value.a) { + case PTA_MUTEX_TEST_WRITER: + return mutex_test_writer(params); + case PTA_MUTEX_TEST_READER: + return mutex_test_reader(params); + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_os/core/pta/tests/sub.mk b/optee/optee_os/core/pta/tests/sub.mk new file mode 100644 index 0000000..389341c --- /dev/null +++ b/optee/optee_os/core/pta/tests/sub.mk @@ -0,0 +1,7 @@ +srcs-$(call cfg-all-enabled,CFG_REE_FS CFG_WITH_USER_TA) += fs_htree.c +srcs-y += invoke.c +srcs-$(CFG_LOCKDEP) += lockdep.c +srcs-y += misc.c +cflags-misc.c-y += -fno-builtin +srcs-y += mutex.c +srcs-y += aes_perf.c diff --git a/optee/optee_os/core/sub.mk b/optee/optee_os/core/sub.mk new file mode 100644 index 0000000..958524f --- /dev/null +++ b/optee/optee_os/core/sub.mk @@ -0,0 +1,90 @@ +subdirs-y += crypto +subdirs-y += drivers +subdirs-y += kernel +subdirs-y += mm +subdirs-y += pta +subdirs-y += tee +subdirs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += tests + +ifeq ($(CFG_WITH_USER_TA),y) +gensrcs-y += ta_pub_key +produce-ta_pub_key = ta_pub_key.c +depends-ta_pub_key = $(TA_PUBLIC_KEY) scripts/pem_to_pub_c.py +recipe-ta_pub_key = $(PYTHON3) scripts/pem_to_pub_c.py --prefix ta_pub_key \ + --key $(TA_PUBLIC_KEY) --out $(sub-dir-out)/ta_pub_key.c + +gensrcs-y += ldelf +produce-ldelf = ldelf_hex.c +depends-ldelf = scripts/gen_ldelf_hex.py $(out-dir)/ldelf/ldelf.elf +recipe-ldelf = $(PYTHON3) scripts/gen_ldelf_hex.py --input $(out-dir)/ldelf/ldelf.elf \ + --output $(sub-dir-out)/ldelf_hex.c +endif + +ifeq ($(CFG_WITH_USER_TA)-$(CFG_EARLY_TA),y-y) +ifeq ($(CFG_EARLY_TA_COMPRESS),y) +early-ta-compress = --compress +endif +define process_early_ta +early-ta-$1-uuid := $(firstword $(subst ., ,$(notdir $1))) +gensrcs-y += early-ta-$1 +produce-early-ta-$1 = early_ta_$$(early-ta-$1-uuid).c +depends-early-ta-$1 = $1 scripts/ts_bin_to_c.py +recipe-early-ta-$1 = $(PYTHON3) scripts/ts_bin_to_c.py $(early-ta-compress) \ + --ta $1 --out $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c +endef +$(foreach f, $(EARLY_TA_PATHS), $(eval $(call process_early_ta,$(f)))) +$(foreach f, $(CFG_IN_TREE_EARLY_TAS), $(eval $(call \ + process_early_ta,$(out-dir)/ta/$(f).stripped.elf))) +endif + +define process_secure_partition +sp-$1-uuid := $(firstword $(subst ., ,$(notdir $1))) +gensrcs-y += sp-$1 +produce-sp-$1 = sp_$$(sp-$1-uuid).c +depends-sp-$1 = $1 scripts/ts_bin_to_c.py +dtb-$1-path = $(dir $1) +dtb-$1 = $$(dtb-$1-path)../manifest/$$(sp-$1-uuid).dtb +recipe-sp-$1 = $(PYTHON3) scripts/ts_bin_to_c.py --compress --sp $1 \ + --out $(sub-dir-out)/sp_$$(sp-$1-uuid).c \ + --manifest $$(dtb-$1) +endef +$(foreach f, $(SP_PATHS), $(eval $(call process_secure_partition,$(f)))) + +ifeq ($(CFG_EMBED_DTB),y) +core-embed-fdt-dts = $(arch-dir)/dts/$(CFG_EMBED_DTB_SOURCE_FILE) +core-embed-fdt-dtb = $(out-dir)/$(arch-dir)/dts/$(CFG_EMBED_DTB_SOURCE_FILE:.dts=.dtb) +core-embed-fdt-c = $(out-dir)/$(arch-dir)/dts/$(CFG_EMBED_DTB_SOURCE_FILE:.dts=.c) +gensrcs-y += embedded_secure_dtb +produce-embedded_secure_dtb = arch/$(ARCH)/dts/$(CFG_EMBED_DTB_SOURCE_FILE:.dts=.c) +depends-embedded_secure_dtb = $(core-embed-fdt-dtb) scripts/bin_to_c.py +recipe-embedded_secure_dtb = $(PYTHON3) scripts/bin_to_c.py \ + --bin $(core-embed-fdt-dtb) \ + --vname embedded_secure_dtb \ + --out $(core-embed-fdt-c) +$(eval $(call gen-dtb-file,$(core-embed-fdt-dts),$(core-embed-fdt-dtb))) +endif + +ifeq ($(CFG_SHOW_CONF_ON_BOOT),y) +conf-mk-xz-base64 := $(sub-dir-out)/conf.mk.xz.base64 +cleanfiles += $(conf-mk-xz-base64) + +$(conf-mk-xz-base64): $(conf-mk-file) + @$(cmd-echo-silent) ' GEN $@' + $(q)tail +3 $< | xz | base64 -w 100 >$@ + +gensrcs-y += conf_str +produce-conf_str = conf.mk.xz.base64.c +depends-conf_str = $(conf-mk-xz-base64) +recipe-conf_str = $(PYTHON3) scripts/bin_to_c.py --text --bin $(conf-mk-xz-base64) \ + --out $(sub-dir-out)/conf.mk.xz.base64.c \ + --vname conf_str +endif + +ifneq ($(CFG_STMM_PATH),) +gensrcs-y += stmm +produce-stmm = stmm_hex.c +depends-stmm = scripts/gen_stmm_hex.py $(CFG_STMM_PATH) +recipe-stmm = scripts/gen_stmm_hex.py --input $(CFG_STMM_PATH) \ + --output $(sub-dir-out)/stmm_hex.c +cleanfiles += $(sub-dir-out)/stmm_hex.c +endif diff --git a/optee/optee_os/core/tee/entry_std.c b/optee/optee_os/core/tee/entry_std.c new file mode 100644 index 0000000..d933d54 --- /dev/null +++ b/optee/optee_os/core/tee/entry_std.c @@ -0,0 +1,609 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHM_CACHE_ATTRS \ + (uint32_t)(core_mmu_is_shm_cached() ? \ + TEE_MATTR_MEM_TYPE_CACHED : TEE_MATTR_MEM_TYPE_DEV) + +/* Sessions opened from normal world */ +static struct tee_ta_session_head tee_open_sessions = +TAILQ_HEAD_INITIALIZER(tee_open_sessions); + +#ifdef CFG_CORE_RESERVED_SHM +static struct mobj *shm_mobj; +#endif +#ifdef CFG_SECURE_DATA_PATH +static struct mobj **sdp_mem_mobjs; +#endif + +static unsigned int session_pnum; + +static bool __maybe_unused param_mem_from_mobj(struct param_mem *mem, + struct mobj *mobj, + const paddr_t pa, + const size_t sz) +{ + paddr_t b; + + if (mobj_get_pa(mobj, 0, 0, &b) != TEE_SUCCESS) + panic("mobj_get_pa failed"); + + if (!core_is_buffer_inside(pa, MAX(sz, 1UL), b, mobj->size)) + return false; + + mem->mobj = mobj_get(mobj); + mem->offs = pa - b; + mem->size = sz; + return true; +} + +#ifdef CFG_CORE_FFA +static TEE_Result set_fmem_param(const struct optee_msg_param_fmem *fmem, + struct param_mem *mem) +{ + size_t req_size = 0; + uint64_t global_id = READ_ONCE(fmem->global_id); + size_t sz = READ_ONCE(fmem->size); + + if (global_id == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID && !sz) { + mem->mobj = NULL; + mem->offs = 0; + mem->size = 0; + return TEE_SUCCESS; + } + mem->mobj = mobj_ffa_get_by_cookie(global_id, + READ_ONCE(fmem->internal_offs)); + if (!mem->mobj) + return TEE_ERROR_BAD_PARAMETERS; + + mem->offs = reg_pair_to_64(READ_ONCE(fmem->offs_high), + READ_ONCE(fmem->offs_low)); + mem->size = sz; + + /* + * Check that the supplied offset and size is covered by the + * previously verified MOBJ. + */ + if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) || + mem->mobj->size < req_size) + return TEE_ERROR_SECURITY; + + return TEE_SUCCESS; +} +#else /*!CFG_CORE_FFA*/ +/* fill 'struct param_mem' structure if buffer matches a valid memory object */ +static TEE_Result set_tmem_param(const struct optee_msg_param_tmem *tmem, + uint32_t attr, struct param_mem *mem) +{ + struct mobj __maybe_unused **mobj; + paddr_t pa = READ_ONCE(tmem->buf_ptr); + size_t sz = READ_ONCE(tmem->size); + + /* + * Handle NULL memory reference + */ + if (!pa) { + mem->mobj = NULL; + mem->offs = 0; + mem->size = 0; + return TEE_SUCCESS; + } + + /* Handle non-contiguous reference from a shared memory area */ + if (attr & OPTEE_MSG_ATTR_NONCONTIG) { + uint64_t shm_ref = READ_ONCE(tmem->shm_ref); + + mem->mobj = msg_param_mobj_from_noncontig(pa, sz, shm_ref, + false); + if (!mem->mobj) + return TEE_ERROR_BAD_PARAMETERS; + mem->offs = 0; + mem->size = sz; + return TEE_SUCCESS; + } + +#ifdef CFG_CORE_RESERVED_SHM + /* Handle memory reference in the contiguous shared memory */ + if (param_mem_from_mobj(mem, shm_mobj, pa, sz)) + return TEE_SUCCESS; +#endif + +#ifdef CFG_SECURE_DATA_PATH + /* Handle memory reference to Secure Data Path memory areas */ + for (mobj = sdp_mem_mobjs; *mobj; mobj++) + if (param_mem_from_mobj(mem, *mobj, pa, sz)) + return TEE_SUCCESS; +#endif + + return TEE_ERROR_BAD_PARAMETERS; +} + +#ifdef CFG_CORE_DYN_SHM +static TEE_Result set_rmem_param(const struct optee_msg_param_rmem *rmem, + struct param_mem *mem) +{ + size_t req_size = 0; + uint64_t shm_ref = READ_ONCE(rmem->shm_ref); + size_t sz = READ_ONCE(rmem->size); + + mem->mobj = mobj_reg_shm_get_by_cookie(shm_ref); + if (!mem->mobj) + return TEE_ERROR_BAD_PARAMETERS; + + mem->offs = READ_ONCE(rmem->offs); + mem->size = sz; + + /* + * Check that the supplied offset and size is covered by the + * previously verified MOBJ. + */ + if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) || + mem->mobj->size < req_size) + return TEE_ERROR_SECURITY; + + return TEE_SUCCESS; +} +#endif /*CFG_CORE_DYN_SHM*/ +#endif /*!CFG_CORE_FFA*/ + +static TEE_Result copy_in_params(const struct optee_msg_param *params, + uint32_t num_params, + struct tee_ta_param *ta_param, + uint64_t *saved_attr) +{ + TEE_Result res; + size_t n; + uint8_t pt[TEE_NUM_PARAMS] = { 0 }; + + if (num_params > TEE_NUM_PARAMS) + return TEE_ERROR_BAD_PARAMETERS; + + memset(ta_param, 0, sizeof(*ta_param)); + + for (n = 0; n < num_params; n++) { + uint32_t attr; + + saved_attr[n] = READ_ONCE(params[n].attr); + + if (saved_attr[n] & OPTEE_MSG_ATTR_META) + return TEE_ERROR_BAD_PARAMETERS; + + attr = saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK; + switch (attr) { + case OPTEE_MSG_ATTR_TYPE_NONE: + pt[n] = TEE_PARAM_TYPE_NONE; + break; + case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: + case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: + pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr - + OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + ta_param->u[n].val.a = READ_ONCE(params[n].u.value.a); + ta_param->u[n].val.b = READ_ONCE(params[n].u.value.b); + break; +#ifdef CFG_CORE_FFA + case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT: + res = set_fmem_param(¶ms[n].u.fmem, + &ta_param->u[n].mem); + if (res) + return res; + pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - + OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; + break; +#else /*!CFG_CORE_FFA*/ + case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: + res = set_tmem_param(¶ms[n].u.tmem, saved_attr[n], + &ta_param->u[n].mem); + if (res) + return res; + pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - + OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; + break; +#ifdef CFG_CORE_DYN_SHM + case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: + res = set_rmem_param(¶ms[n].u.rmem, + &ta_param->u[n].mem); + if (res) + return res; + pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - + OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; + break; +#endif /*CFG_CORE_DYN_SHM*/ +#endif /*!CFG_CORE_FFA*/ + default: + return TEE_ERROR_BAD_PARAMETERS; + } + } + + ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]); + + return TEE_SUCCESS; +} + +static void cleanup_shm_refs(const uint64_t *saved_attr, + struct tee_ta_param *param, uint32_t num_params) +{ + size_t n; + + for (n = 0; n < MIN((unsigned int)TEE_NUM_PARAMS, num_params); n++) { + switch (saved_attr[n]) { + case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: +#ifdef CFG_CORE_DYN_SHM + case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: + case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: +#endif + mobj_put(param->u[n].mem.mobj); + break; + default: + break; + } + } +} + +static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params, + struct optee_msg_param *params, uint64_t *saved_attr) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + switch (saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK) { + case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: + params[n].u.tmem.size = ta_param->u[n].mem.size; + break; + case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: + case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: + params[n].u.rmem.size = ta_param->u[n].mem.size; + break; + default: + break; + } + break; + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].u.value.a = ta_param->u[n].val.a; + params[n].u.value.b = ta_param->u[n].val.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 TEE_Result get_open_session_meta(size_t num_params, + struct optee_msg_param *params, + size_t *num_meta, TEE_UUID *uuid, + TEE_Identity *clnt_id) +{ + const uint32_t req_attr = OPTEE_MSG_ATTR_META | + OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; + + if (num_params < 2) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].attr != req_attr || params[1].attr != req_attr) + return TEE_ERROR_BAD_PARAMETERS; + + tee_uuid_from_octets(uuid, (void *)¶ms[0].u.value); + clnt_id->login = params[1].u.value.c; + switch (clnt_id->login) { + case TEE_LOGIN_PUBLIC: + case TEE_LOGIN_REE_KERNEL: + memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid)); + break; + case TEE_LOGIN_USER: + case TEE_LOGIN_GROUP: + case TEE_LOGIN_APPLICATION: + case TEE_LOGIN_APPLICATION_USER: + case TEE_LOGIN_APPLICATION_GROUP: + tee_uuid_from_octets(&clnt_id->uuid, + (void *)¶ms[1].u.value); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + *num_meta = 2; + return TEE_SUCCESS; +} + +static void entry_open_session(struct optee_msg_arg *arg, uint32_t num_params) +{ + TEE_Result res; + TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; + struct tee_ta_session *s = NULL; + TEE_Identity clnt_id; + TEE_UUID uuid; + struct tee_ta_param param; + size_t num_meta; + uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; + + res = get_open_session_meta(num_params, arg->params, &num_meta, &uuid, + &clnt_id); + if (res != TEE_SUCCESS) + goto out; + + res = copy_in_params(arg->params + num_meta, num_params - num_meta, + ¶m, saved_attr); + if (res != TEE_SUCCESS) + goto cleanup_shm_refs; + + res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid, + &clnt_id, TEE_TIMEOUT_INFINITE, ¶m); + if (res != TEE_SUCCESS) + s = NULL; + copy_out_param(¶m, num_params - num_meta, arg->params + num_meta, + saved_attr); + + /* + * The occurrence of open/close session command is usually + * un-predictable, using this property to increase randomness + * of prng + */ + plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, + &session_pnum); + +cleanup_shm_refs: + cleanup_shm_refs(saved_attr, ¶m, num_params - num_meta); + +out: + if (s) + arg->session = s->id; + else + arg->session = 0; + arg->ret = res; + arg->ret_origin = err_orig; +} + +static void entry_close_session(struct optee_msg_arg *arg, uint32_t num_params) +{ + TEE_Result res; + struct tee_ta_session *s; + + if (num_params) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, + &session_pnum); + + s = tee_ta_find_session(arg->session, &tee_open_sessions); + res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY); +out: + arg->ret = res; + arg->ret_origin = TEE_ORIGIN_TEE; +} + +static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params) +{ + TEE_Result res; + TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; + struct tee_ta_session *s; + struct tee_ta_param param = { 0 }; + uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; + + bm_timestamp(); + + res = copy_in_params(arg->params, num_params, ¶m, saved_attr); + if (res != TEE_SUCCESS) + goto out; + + s = tee_ta_get_session(arg->session, true, &tee_open_sessions); + if (!s) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY, + TEE_TIMEOUT_INFINITE, arg->func, ¶m); + + bm_timestamp(); + + tee_ta_put_session(s); + + copy_out_param(¶m, num_params, arg->params, saved_attr); + +out: + cleanup_shm_refs(saved_attr, ¶m, num_params); + + arg->ret = res; + arg->ret_origin = err_orig; +} + +static void entry_cancel(struct optee_msg_arg *arg, uint32_t num_params) +{ + TEE_Result res; + TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; + struct tee_ta_session *s; + + if (num_params) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + s = tee_ta_get_session(arg->session, false, &tee_open_sessions); + if (!s) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY); + tee_ta_put_session(s); + +out: + arg->ret = res; + arg->ret_origin = err_orig; +} + +#ifndef CFG_CORE_FFA +#ifdef CFG_CORE_DYN_SHM +static void register_shm(struct optee_msg_arg *arg, uint32_t num_params) +{ + struct optee_msg_param_tmem *tmem = NULL; + struct mobj *mobj = NULL; + + arg->ret = TEE_ERROR_BAD_PARAMETERS; + + if (num_params != 1 || + (arg->params[0].attr != + (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG))) + return; + + tmem = &arg->params[0].u.tmem; + mobj = msg_param_mobj_from_noncontig(tmem->buf_ptr, tmem->size, + tmem->shm_ref, false); + + if (!mobj) + return; + + mobj_reg_shm_unguard(mobj); + arg->ret = TEE_SUCCESS; +} + +static void unregister_shm(struct optee_msg_arg *arg, uint32_t num_params) +{ + if (num_params == 1) { + uint64_t cookie = arg->params[0].u.rmem.shm_ref; + TEE_Result res = mobj_reg_shm_release_by_cookie(cookie); + + if (res) + EMSG("Can't find mapping with given cookie"); + arg->ret = res; + } else { + arg->ret = TEE_ERROR_BAD_PARAMETERS; + arg->ret_origin = TEE_ORIGIN_TEE; + } +} +#endif /*CFG_CORE_DYN_SHM*/ +#endif + +void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions) +{ + *open_sessions = &tee_open_sessions; +} + +/* Note: this function is weak to let platforms add special handling */ +TEE_Result __weak tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) +{ + return __tee_entry_std(arg, num_params); +} + +/* + * If tee_entry_std() is overridden, it's still supposed to call this + * function. + */ +TEE_Result __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) +{ + TEE_Result res = TEE_SUCCESS; + + /* Enable foreign interrupts for STD calls */ + thread_set_foreign_intr(true); + switch (arg->cmd) { + case OPTEE_MSG_CMD_OPEN_SESSION: + entry_open_session(arg, num_params); + break; + case OPTEE_MSG_CMD_CLOSE_SESSION: + entry_close_session(arg, num_params); + break; + case OPTEE_MSG_CMD_INVOKE_COMMAND: + entry_invoke_command(arg, num_params); + break; + case OPTEE_MSG_CMD_CANCEL: + entry_cancel(arg, num_params); + break; +#ifndef CFG_CORE_FFA +#ifdef CFG_CORE_DYN_SHM + case OPTEE_MSG_CMD_REGISTER_SHM: + register_shm(arg, num_params); + break; + case OPTEE_MSG_CMD_UNREGISTER_SHM: + unregister_shm(arg, num_params); + break; +#endif +#endif + + case OPTEE_MSG_CMD_DO_BOTTOM_HALF: + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) + notif_deliver_event(NOTIF_EVENT_DO_BOTTOM_HALF); + else + goto err; + break; + case OPTEE_MSG_CMD_STOP_ASYNC_NOTIF: + if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) + notif_deliver_event(NOTIF_EVENT_STOPPED); + else + goto err; + break; + + default: +err: + EMSG("Unknown cmd 0x%x", arg->cmd); + res = TEE_ERROR_NOT_IMPLEMENTED; + } + + return res; +} + +static TEE_Result default_mobj_init(void) +{ +#ifdef CFG_CORE_RESERVED_SHM + shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr, + default_nsec_shm_size, SHM_CACHE_ATTRS, + CORE_MEM_NSEC_SHM); + if (!shm_mobj) + panic("Failed to register shared memory"); +#endif + +#ifdef CFG_SECURE_DATA_PATH + sdp_mem_mobjs = core_sdp_mem_create_mobjs(); + if (!sdp_mem_mobjs) + panic("Failed to register SDP memory"); +#endif + + return TEE_SUCCESS; +} + +driver_init_late(default_mobj_init); diff --git a/optee/optee_os/core/tee/fs_dirfile.c b/optee/optee_os/core/tee/fs_dirfile.c new file mode 100644 index 0000000..e99770a --- /dev/null +++ b/optee/optee_os/core/tee/fs_dirfile.c @@ -0,0 +1,394 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +struct tee_fs_dirfile_dirh { + const struct tee_fs_dirfile_operations *fops; + struct tee_file_handle *fh; + int nbits; + bitstr_t *files; + size_t ndents; +}; + +struct dirfile_entry { + TEE_UUID uuid; + uint8_t oid[TEE_OBJECT_ID_MAX_LEN]; + uint32_t oidlen; + uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; + uint32_t file_number; +}; + +#define OID_EMPTY_NAME 1 + +/* + * An object can have an ID of size zero. This object is represented by + * oidlen == 0 and oid[0] == OID_EMPTY_NAME. When both are zero, the entry is + * not a valid object. + */ +static bool is_free(struct dirfile_entry *dent) +{ + assert(dent->oidlen || !dent->oid[0] || dent->oid[0] == OID_EMPTY_NAME); + + return !dent->oidlen && !dent->oid[0]; +} + +/* + * File layout + * + * dirfile_entry.0 + * ... + * dirfile_entry.n + * + * where n the index is disconnected from file_number in struct dirfile_entry + */ + +static TEE_Result maybe_grow_files(struct tee_fs_dirfile_dirh *dirh, int idx) +{ + void *p; + + if (idx < dirh->nbits) + return TEE_SUCCESS; + + p = realloc(dirh->files, bitstr_size(idx + 1)); + if (!p) + return TEE_ERROR_OUT_OF_MEMORY; + dirh->files = p; + + bit_nclear(dirh->files, dirh->nbits, idx); + dirh->nbits = idx + 1; + + return TEE_SUCCESS; +} + +static TEE_Result set_file(struct tee_fs_dirfile_dirh *dirh, int idx) +{ + TEE_Result res = maybe_grow_files(dirh, idx); + + if (!res) + bit_set(dirh->files, idx); + + return res; +} + +static void clear_file(struct tee_fs_dirfile_dirh *dirh, int idx) +{ + if (idx < dirh->nbits) + bit_clear(dirh->files, idx); +} + +static bool test_file(struct tee_fs_dirfile_dirh *dirh, int idx) +{ + if (idx < dirh->nbits) + return bit_test(dirh->files, idx); + + return false; +} + +static TEE_Result read_dent(struct tee_fs_dirfile_dirh *dirh, int idx, + struct dirfile_entry *dent) +{ + TEE_Result res; + size_t l; + + l = sizeof(*dent); + res = dirh->fops->read(dirh->fh, sizeof(struct dirfile_entry) * idx, + dent, &l); + if (!res && l != sizeof(*dent)) + res = TEE_ERROR_ITEM_NOT_FOUND; + + return res; +} + +static TEE_Result write_dent(struct tee_fs_dirfile_dirh *dirh, size_t n, + struct dirfile_entry *dent) +{ + TEE_Result res; + + res = dirh->fops->write(dirh->fh, sizeof(*dent) * n, + dent, sizeof(*dent)); + if (!res && n >= dirh->ndents) + dirh->ndents = n + 1; + + return res; +} + +TEE_Result tee_fs_dirfile_open(bool create, uint8_t *hash, + const struct tee_fs_dirfile_operations *fops, + struct tee_fs_dirfile_dirh **dirh_ret) +{ + TEE_Result res; + struct tee_fs_dirfile_dirh *dirh = calloc(1, sizeof(*dirh)); + size_t n; + + if (!dirh) + return TEE_ERROR_OUT_OF_MEMORY; + + dirh->fops = fops; + res = fops->open(create, hash, NULL, NULL, &dirh->fh); + if (res) + goto out; + + for (n = 0;; n++) { + struct dirfile_entry dent; + + res = read_dent(dirh, n, &dent); + if (res) { + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = TEE_SUCCESS; + goto out; + } + + if (is_free(&dent)) + continue; + + if (test_file(dirh, dent.file_number)) { + DMSG("clearing duplicate file number %" PRIu32, + dent.file_number); + memset(&dent, 0, sizeof(dent)); + res = write_dent(dirh, n, &dent); + if (res) + goto out; + continue; + } + + res = set_file(dirh, dent.file_number); + if (res != TEE_SUCCESS) + goto out; + } +out: + if (!res) { + dirh->ndents = n; + *dirh_ret = dirh; + } else { + tee_fs_dirfile_close(dirh); + } + return res; +} + +void tee_fs_dirfile_close(struct tee_fs_dirfile_dirh *dirh) +{ + if (dirh) { + dirh->fops->close(dirh->fh); + free(dirh->files); + free(dirh); + } +} + +TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh, + uint8_t *hash) +{ + return dirh->fops->commit_writes(dirh->fh, hash); +} + +TEE_Result tee_fs_dirfile_get_tmp(struct tee_fs_dirfile_dirh *dirh, + struct tee_fs_dirfile_fileh *dfh) +{ + TEE_Result res; + int i = 0; + + if (dirh->nbits) { + bit_ffc(dirh->files, dirh->nbits, &i); + if (i == -1) + i = dirh->nbits; + } + + res = set_file(dirh, i); + if (!res) + dfh->file_number = i; + + return res; +} + +TEE_Result tee_fs_dirfile_find(struct tee_fs_dirfile_dirh *dirh, + const TEE_UUID *uuid, const void *oid, + size_t oidlen, struct tee_fs_dirfile_fileh *dfh) +{ + TEE_Result res = TEE_SUCCESS; + struct dirfile_entry dent = { }; + int n = 0; + + for (n = 0;; n++) { + res = read_dent(dirh, n, &dent); + if (res) + return res; + + if (is_free(&dent)) + continue; + if (dent.oidlen != oidlen) + continue; + + assert(test_file(dirh, dent.file_number)); + + if (!memcmp(&dent.uuid, uuid, sizeof(dent.uuid)) && + !memcmp(&dent.oid, oid, oidlen)) + break; + } + + if (dfh) { + dfh->idx = n; + dfh->file_number = dent.file_number; + memcpy(dfh->hash, dent.hash, sizeof(dent.hash)); + } + + return TEE_SUCCESS; +} + +static TEE_Result find_empty_idx(struct tee_fs_dirfile_dirh *dh, int *idx) +{ + struct dirfile_entry dent = { }; + TEE_Result res = TEE_SUCCESS; + int n = 0; + + for (n = 0;; n++) { + res = read_dent(dh, n, &dent); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + break; + if (res) + return res; + if (is_free(&dent)) + break; + } + + *idx = n; + return TEE_SUCCESS; +} + +TEE_Result tee_fs_dirfile_fileh_to_fname(const struct tee_fs_dirfile_fileh *dfh, + char *fname, size_t *fnlen) +{ + int r; + size_t l = *fnlen; + + if (dfh) + r = snprintf(fname, l, "%" PRIx32, dfh->file_number); + else + r = snprintf(fname, l, "dirf.db"); + + if (r < 0) + return TEE_ERROR_GENERIC; + + *fnlen = r + 1; + if ((size_t)r >= l) + return TEE_ERROR_SHORT_BUFFER; + + return TEE_SUCCESS; +} + +TEE_Result tee_fs_dirfile_rename(struct tee_fs_dirfile_dirh *dirh, + const TEE_UUID *uuid, + struct tee_fs_dirfile_fileh *dfh, + const void *oid, size_t oidlen) +{ + TEE_Result res; + struct dirfile_entry dent; + + if (oidlen > sizeof(dent.oid)) + return TEE_ERROR_BAD_PARAMETERS; + memset(&dent, 0, sizeof(dent)); + dent.uuid = *uuid; + if (oidlen) + memcpy(dent.oid, oid, oidlen); + else + dent.oid[0] = OID_EMPTY_NAME; + + dent.oidlen = oidlen; + memcpy(dent.hash, dfh->hash, sizeof(dent.hash)); + dent.file_number = dfh->file_number; + + if (dfh->idx < 0) { + struct tee_fs_dirfile_fileh dfh2; + + res = tee_fs_dirfile_find(dirh, uuid, oid, oidlen, &dfh2); + if (res) { + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = find_empty_idx(dirh, &dfh2.idx); + if (res) + return res; + } + dfh->idx = dfh2.idx; + } + + return write_dent(dirh, dfh->idx, &dent); +} + +TEE_Result tee_fs_dirfile_remove(struct tee_fs_dirfile_dirh *dirh, + const struct tee_fs_dirfile_fileh *dfh) +{ + TEE_Result res; + struct dirfile_entry dent; + uint32_t file_number; + + res = read_dent(dirh, dfh->idx, &dent); + if (res) + return res; + + if (is_free(&dent)) + return TEE_SUCCESS; + + file_number = dent.file_number; + assert(dfh->file_number == file_number); + assert(test_file(dirh, file_number)); + + memset(&dent, 0, sizeof(dent)); + res = write_dent(dirh, dfh->idx, &dent); + if (!res) + clear_file(dirh, file_number); + + return res; +} + +TEE_Result tee_fs_dirfile_update_hash(struct tee_fs_dirfile_dirh *dirh, + const struct tee_fs_dirfile_fileh *dfh) +{ + TEE_Result res; + struct dirfile_entry dent; + + res = read_dent(dirh, dfh->idx, &dent); + if (res) + return res; + assert(dent.file_number == dfh->file_number); + assert(test_file(dirh, dent.file_number)); + + memcpy(&dent.hash, dfh->hash, sizeof(dent.hash)); + + return write_dent(dirh, dfh->idx, &dent); +} + +TEE_Result tee_fs_dirfile_get_next(struct tee_fs_dirfile_dirh *dirh, + const TEE_UUID *uuid, int *idx, void *oid, + size_t *oidlen) +{ + TEE_Result res; + int i = *idx + 1; + struct dirfile_entry dent; + + if (i < 0) + i = 0; + + for (;; i++) { + res = read_dent(dirh, i, &dent); + if (res) + return res; + if (!memcmp(&dent.uuid, uuid, sizeof(dent.uuid)) && + !is_free(&dent)) + break; + } + + if (*oidlen < dent.oidlen) + return TEE_ERROR_SHORT_BUFFER; + + memcpy(oid, dent.oid, dent.oidlen); + *oidlen = dent.oidlen; + *idx = i; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/tee/fs_htree.c b/optee/optee_os/core/tee/fs_htree.c new file mode 100644 index 0000000..62609c9 --- /dev/null +++ b/optee/optee_os/core/tee/fs_htree.c @@ -0,0 +1,929 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEE_FS_HTREE_CHIP_ID_SIZE 32 +#define TEE_FS_HTREE_HASH_ALG TEE_ALG_SHA256 +#define TEE_FS_HTREE_TSK_SIZE TEE_FS_HTREE_HASH_SIZE +#define TEE_FS_HTREE_ENC_ALG TEE_ALG_AES_ECB_NOPAD +#define TEE_FS_HTREE_ENC_SIZE TEE_AES_BLOCK_SIZE +#define TEE_FS_HTREE_SSK_SIZE TEE_FS_HTREE_HASH_SIZE + +#define TEE_FS_HTREE_AUTH_ENC_ALG TEE_ALG_AES_GCM +#define TEE_FS_HTREE_HMAC_ALG TEE_ALG_HMAC_SHA256 + +#define BLOCK_NUM_TO_NODE_ID(num) ((num) + 1) + +#define NODE_ID_TO_BLOCK_NUM(id) ((id) - 1) + +/* + * The hash tree is implemented as a binary tree with the purpose to ensure + * integrity of the data in the nodes. The data in the nodes their turn + * provides both integrity and confidentiality of the data blocks. + * + * The hash tree is saved in a file as: + * +----------------------------+ + * | htree_image.0 | + * | htree_image.1 | + * +----------------------------+ + * | htree_node_image.1.0 | + * | htree_node_image.1.1 | + * +----------------------------+ + * | htree_node_image.2.0 | + * | htree_node_image.2.1 | + * +----------------------------+ + * | htree_node_image.3.0 | + * | htree_node_image.3.1 | + * +----------------------------+ + * | htree_node_image.4.0 | + * | htree_node_image.4.1 | + * +----------------------------+ + * ... + * + * htree_image is the header of the file, there's two instances of it. One + * which is committed and the other is used when updating the file. Which + * is committed is indicated by the "counter" field, the one with the + * largest value is selected. + * + * htree_node_image is a node in the hash tree, each node has two instances + * which is committed is decided by the parent node .flag bit + * HTREE_NODE_COMMITTED_CHILD. Which version is the committed version of + * node 1 is determined by the by the lowest bit of the counter field in + * the header. + * + * Note that nodes start counting at 1 while blocks at 0, this means that + * block 0 is represented by node 1. + * + * Where different elements are stored in the file is managed by the file + * system. + */ + +#define HTREE_NODE_COMMITTED_BLOCK BIT32(0) +/* n is 0 or 1 */ +#define HTREE_NODE_COMMITTED_CHILD(n) BIT32(1 + (n)) + +struct htree_node { + size_t id; + bool dirty; + bool block_updated; + struct tee_fs_htree_node_image node; + struct htree_node *parent; + struct htree_node *child[2]; +}; + +struct tee_fs_htree { + struct htree_node root; + struct tee_fs_htree_image head; + uint8_t fek[TEE_FS_HTREE_FEK_SIZE]; + struct tee_fs_htree_imeta imeta; + bool dirty; + const TEE_UUID *uuid; + const struct tee_fs_htree_storage *stor; + void *stor_aux; +}; + +struct traverse_arg; +typedef TEE_Result (*traverse_cb_t)(struct traverse_arg *targ, + struct htree_node *node); +struct traverse_arg { + struct tee_fs_htree *ht; + traverse_cb_t cb; + void *arg; +}; + +static TEE_Result rpc_read(struct tee_fs_htree *ht, enum tee_fs_htree_type type, + size_t idx, size_t vers, void *data, size_t dlen) +{ + TEE_Result res; + struct tee_fs_rpc_operation op; + size_t bytes; + void *p; + + res = ht->stor->rpc_read_init(ht->stor_aux, &op, type, idx, vers, &p); + if (res != TEE_SUCCESS) + return res; + + res = ht->stor->rpc_read_final(&op, &bytes); + if (res != TEE_SUCCESS) + return res; + + if (bytes != dlen) + return TEE_ERROR_CORRUPT_OBJECT; + + memcpy(data, p, dlen); + return TEE_SUCCESS; +} + +static TEE_Result rpc_read_head(struct tee_fs_htree *ht, size_t vers, + struct tee_fs_htree_image *head) +{ + return rpc_read(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers, + head, sizeof(*head)); +} + +static TEE_Result rpc_read_node(struct tee_fs_htree *ht, size_t node_id, + size_t vers, + struct tee_fs_htree_node_image *node) +{ + return rpc_read(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers, + node, sizeof(*node)); +} + +static TEE_Result rpc_write(struct tee_fs_htree *ht, + enum tee_fs_htree_type type, size_t idx, + size_t vers, const void *data, size_t dlen) +{ + TEE_Result res; + struct tee_fs_rpc_operation op; + void *p; + + res = ht->stor->rpc_write_init(ht->stor_aux, &op, type, idx, vers, &p); + if (res != TEE_SUCCESS) + return res; + + memcpy(p, data, dlen); + return ht->stor->rpc_write_final(&op); +} + +static TEE_Result rpc_write_head(struct tee_fs_htree *ht, size_t vers, + const struct tee_fs_htree_image *head) +{ + return rpc_write(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers, + head, sizeof(*head)); +} + +static TEE_Result rpc_write_node(struct tee_fs_htree *ht, size_t node_id, + size_t vers, + const struct tee_fs_htree_node_image *node) +{ + return rpc_write(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers, + node, sizeof(*node)); +} + +static TEE_Result traverse_post_order(struct traverse_arg *targ, + struct htree_node *node) +{ + TEE_Result res; + + /* + * This function is recursing but not very deep, only with Log(N) + * maximum depth. + */ + + if (!node) + return TEE_SUCCESS; + + res = traverse_post_order(targ, node->child[0]); + if (res != TEE_SUCCESS) + return res; + + res = traverse_post_order(targ, node->child[1]); + if (res != TEE_SUCCESS) + return res; + + return targ->cb(targ, node); +} + +static TEE_Result htree_traverse_post_order(struct tee_fs_htree *ht, + traverse_cb_t cb, void *arg) +{ + struct traverse_arg targ = { ht, cb, arg }; + + return traverse_post_order(&targ, &ht->root); +} + +static size_t node_id_to_level(size_t node_id) +{ + assert(node_id && node_id < UINT_MAX); + /* Calculate level of the node, root node (1) has level 1 */ + return sizeof(unsigned int) * 8 - __builtin_clz(node_id); +} + +static struct htree_node *find_closest_node(struct tee_fs_htree *ht, + size_t node_id) +{ + struct htree_node *node = &ht->root; + size_t level = node_id_to_level(node_id); + size_t n; + + /* n = 1 because root node is level 1 */ + for (n = 1; n < level; n++) { + struct htree_node *child; + size_t bit_idx; + + /* + * The difference between levels of the current node and + * the node we're looking for tells which bit decides + * direction in the tree. + * + * As the first bit has index 0 we'll subtract 1 + */ + bit_idx = level - n - 1; + child = node->child[((node_id >> bit_idx) & 1)]; + if (!child) + return node; + node = child; + } + + return node; +} + +static struct htree_node *find_node(struct tee_fs_htree *ht, size_t node_id) +{ + struct htree_node *node = find_closest_node(ht, node_id); + + if (node && node->id == node_id) + return node; + return NULL; +} + +static TEE_Result get_node(struct tee_fs_htree *ht, bool create, + size_t node_id, struct htree_node **node_ret) +{ + struct htree_node *node; + struct htree_node *nc; + size_t n; + + node = find_closest_node(ht, node_id); + if (!node) + return TEE_ERROR_GENERIC; + if (node->id == node_id) + goto ret_node; + + /* + * Trying to read beyond end of file should be caught earlier than + * here. + */ + if (!create) + return TEE_ERROR_GENERIC; + + /* + * Add missing nodes, some nodes may already be there. When we've + * processed the range all nodes up to node_id will be in the tree. + */ + for (n = node->id + 1; n <= node_id; n++) { + node = find_closest_node(ht, n); + if (node->id == n) + continue; + /* Node id n should be a child of node */ + assert((n >> 1) == node->id); + assert(!node->child[n & 1]); + + nc = calloc(1, sizeof(*nc)); + if (!nc) + return TEE_ERROR_OUT_OF_MEMORY; + nc->id = n; + nc->parent = node; + node->child[n & 1] = nc; + node = nc; + } + + if (node->id > ht->imeta.max_node_id) + ht->imeta.max_node_id = node->id; + +ret_node: + *node_ret = node; + return TEE_SUCCESS; +} + +static int get_idx_from_counter(uint32_t counter0, uint32_t counter1) +{ + if (!(counter0 & 1)) { + if (!(counter1 & 1)) + return 0; + if (counter0 > counter1) + return 0; + else + return 1; + } + + if (counter1 & 1) + return 1; + else + return -1; +} + +static TEE_Result init_head_from_data(struct tee_fs_htree *ht, + const uint8_t *hash) +{ + TEE_Result res; + int idx; + + if (hash) { + for (idx = 0;; idx++) { + res = rpc_read_node(ht, 1, idx, &ht->root.node); + if (res != TEE_SUCCESS) + return res; + + if (!memcmp(ht->root.node.hash, hash, + sizeof(ht->root.node.hash))) { + res = rpc_read_head(ht, idx, &ht->head); + if (res != TEE_SUCCESS) + return res; + break; + } + + if (idx) + return TEE_ERROR_CORRUPT_OBJECT; + } + } else { + struct tee_fs_htree_image head[2]; + + for (idx = 0; idx < 2; idx++) { + res = rpc_read_head(ht, idx, head + idx); + if (res != TEE_SUCCESS) + return res; + } + + idx = get_idx_from_counter(head[0].counter, head[1].counter); + if (idx < 0) + return TEE_ERROR_SECURITY; + + res = rpc_read_node(ht, 1, idx, &ht->root.node); + if (res != TEE_SUCCESS) + return res; + + ht->head = head[idx]; + } + + ht->root.id = 1; + + return TEE_SUCCESS; +} + +static TEE_Result init_tree_from_data(struct tee_fs_htree *ht) +{ + TEE_Result res; + struct tee_fs_htree_node_image node_image; + struct htree_node *node; + struct htree_node *nc; + size_t committed_version; + size_t node_id = 2; + + while (node_id <= ht->imeta.max_node_id) { + node = find_node(ht, node_id >> 1); + if (!node) + return TEE_ERROR_GENERIC; + committed_version = !!(node->node.flags & + HTREE_NODE_COMMITTED_CHILD(node_id & 1)); + + res = rpc_read_node(ht, node_id, committed_version, + &node_image); + if (res != TEE_SUCCESS) + return res; + + res = get_node(ht, true, node_id, &nc); + if (res != TEE_SUCCESS) + return res; + nc->node = node_image; + node_id++; + } + + return TEE_SUCCESS; +} + +static TEE_Result calc_node_hash(struct htree_node *node, + struct tee_fs_htree_meta *meta, void *ctx, + uint8_t *digest) +{ + TEE_Result res; + uint8_t *ndata = (uint8_t *)&node->node + sizeof(node->node.hash); + size_t nsize = sizeof(node->node) - sizeof(node->node.hash); + + res = crypto_hash_init(ctx); + if (res != TEE_SUCCESS) + return res; + + res = crypto_hash_update(ctx, ndata, nsize); + if (res != TEE_SUCCESS) + return res; + + if (meta) { + res = crypto_hash_update(ctx, (void *)meta, sizeof(*meta)); + if (res != TEE_SUCCESS) + return res; + } + + if (node->child[0]) { + res = crypto_hash_update(ctx, node->child[0]->node.hash, + sizeof(node->child[0]->node.hash)); + if (res != TEE_SUCCESS) + return res; + } + + if (node->child[1]) { + res = crypto_hash_update(ctx, node->child[1]->node.hash, + sizeof(node->child[1]->node.hash)); + if (res != TEE_SUCCESS) + return res; + } + + return crypto_hash_final(ctx, digest, TEE_FS_HTREE_HASH_SIZE); +} + +static TEE_Result authenc_init(void **ctx_ret, TEE_OperationMode mode, + struct tee_fs_htree *ht, + struct tee_fs_htree_node_image *ni, + size_t payload_len) +{ + TEE_Result res = TEE_SUCCESS; + const uint32_t alg = TEE_FS_HTREE_AUTH_ENC_ALG; + void *ctx; + size_t aad_len = TEE_FS_HTREE_FEK_SIZE + TEE_FS_HTREE_IV_SIZE; + uint8_t *iv; + + if (ni) { + iv = ni->iv; + } else { + iv = ht->head.iv; + aad_len += TEE_FS_HTREE_HASH_SIZE + sizeof(ht->head.counter); + } + + if (mode == TEE_MODE_ENCRYPT) { + res = crypto_rng_read(iv, TEE_FS_HTREE_IV_SIZE); + if (res != TEE_SUCCESS) + return res; + } + + res = crypto_authenc_alloc_ctx(&ctx, alg); + if (res != TEE_SUCCESS) + return res; + + res = crypto_authenc_init(ctx, mode, ht->fek, TEE_FS_HTREE_FEK_SIZE, iv, + TEE_FS_HTREE_IV_SIZE, TEE_FS_HTREE_TAG_SIZE, + aad_len, payload_len); + if (res != TEE_SUCCESS) + goto err_free; + + if (!ni) { + res = crypto_authenc_update_aad(ctx, mode, ht->root.node.hash, + TEE_FS_HTREE_FEK_SIZE); + if (res != TEE_SUCCESS) + goto err; + + res = crypto_authenc_update_aad(ctx, mode, + (void *)&ht->head.counter, + sizeof(ht->head.counter)); + if (res != TEE_SUCCESS) + goto err; + } + + res = crypto_authenc_update_aad(ctx, mode, ht->head.enc_fek, + TEE_FS_HTREE_FEK_SIZE); + if (res != TEE_SUCCESS) + goto err; + + res = crypto_authenc_update_aad(ctx, mode, iv, TEE_FS_HTREE_IV_SIZE); + if (res != TEE_SUCCESS) + goto err; + + *ctx_ret = ctx; + + return TEE_SUCCESS; +err: + crypto_authenc_final(ctx); +err_free: + crypto_authenc_free_ctx(ctx); + return res; +} + +static TEE_Result authenc_decrypt_final(void *ctx, const uint8_t *tag, + const void *crypt, size_t len, + void *plain) +{ + TEE_Result res; + size_t out_size = len; + + res = crypto_authenc_dec_final(ctx, crypt, len, plain, &out_size, tag, + TEE_FS_HTREE_TAG_SIZE); + crypto_authenc_final(ctx); + crypto_authenc_free_ctx(ctx); + + if (res == TEE_SUCCESS && out_size != len) + return TEE_ERROR_GENERIC; + if (res == TEE_ERROR_MAC_INVALID) + return TEE_ERROR_CORRUPT_OBJECT; + + return res; +} + +static TEE_Result authenc_encrypt_final(void *ctx, uint8_t *tag, + const void *plain, size_t len, + void *crypt) +{ + TEE_Result res; + size_t out_size = len; + size_t out_tag_size = TEE_FS_HTREE_TAG_SIZE; + + res = crypto_authenc_enc_final(ctx, plain, len, crypt, &out_size, tag, + &out_tag_size); + crypto_authenc_final(ctx); + crypto_authenc_free_ctx(ctx); + + if (res == TEE_SUCCESS && + (out_size != len || out_tag_size != TEE_FS_HTREE_TAG_SIZE)) + return TEE_ERROR_GENERIC; + + return res; +} + +static TEE_Result verify_root(struct tee_fs_htree *ht) +{ + TEE_Result res; + void *ctx; + + res = tee_fs_fek_crypt(ht->uuid, TEE_MODE_DECRYPT, ht->head.enc_fek, + sizeof(ht->fek), ht->fek); + if (res != TEE_SUCCESS) + return res; + + res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, NULL, sizeof(ht->imeta)); + if (res != TEE_SUCCESS) + return res; + + return authenc_decrypt_final(ctx, ht->head.tag, ht->head.imeta, + sizeof(ht->imeta), &ht->imeta); +} + +static TEE_Result verify_node(struct traverse_arg *targ, + struct htree_node *node) +{ + void *ctx = targ->arg; + TEE_Result res; + uint8_t digest[TEE_FS_HTREE_HASH_SIZE]; + + if (node->parent) + res = calc_node_hash(node, NULL, ctx, digest); + else + res = calc_node_hash(node, &targ->ht->imeta.meta, ctx, digest); + if (res == TEE_SUCCESS && + consttime_memcmp(digest, node->node.hash, sizeof(digest))) + return TEE_ERROR_CORRUPT_OBJECT; + + return res; +} + +static TEE_Result verify_tree(struct tee_fs_htree *ht) +{ + TEE_Result res; + void *ctx; + + res = crypto_hash_alloc_ctx(&ctx, TEE_FS_HTREE_HASH_ALG); + if (res != TEE_SUCCESS) + return res; + + res = htree_traverse_post_order(ht, verify_node, ctx); + crypto_hash_free_ctx(ctx); + + return res; +} + +static TEE_Result init_root_node(struct tee_fs_htree *ht) +{ + TEE_Result res; + void *ctx; + + res = crypto_hash_alloc_ctx(&ctx, TEE_FS_HTREE_HASH_ALG); + if (res != TEE_SUCCESS) + return res; + + ht->root.id = 1; + ht->root.dirty = true; + + res = calc_node_hash(&ht->root, &ht->imeta.meta, ctx, + ht->root.node.hash); + crypto_hash_free_ctx(ctx); + + return res; +} + +TEE_Result tee_fs_htree_open(bool create, uint8_t *hash, const TEE_UUID *uuid, + const struct tee_fs_htree_storage *stor, + void *stor_aux, struct tee_fs_htree **ht_ret) +{ + TEE_Result res; + struct tee_fs_htree *ht = calloc(1, sizeof(*ht)); + + if (!ht) + return TEE_ERROR_OUT_OF_MEMORY; + + ht->uuid = uuid; + ht->stor = stor; + ht->stor_aux = stor_aux; + + if (create) { + const struct tee_fs_htree_image dummy_head = { .counter = 0 }; + + res = crypto_rng_read(ht->fek, sizeof(ht->fek)); + if (res != TEE_SUCCESS) + goto out; + + res = tee_fs_fek_crypt(ht->uuid, TEE_MODE_ENCRYPT, ht->fek, + sizeof(ht->fek), ht->head.enc_fek); + if (res != TEE_SUCCESS) + goto out; + + res = init_root_node(ht); + if (res != TEE_SUCCESS) + goto out; + + ht->dirty = true; + res = tee_fs_htree_sync_to_storage(&ht, hash); + if (res != TEE_SUCCESS) + goto out; + res = rpc_write_head(ht, 0, &dummy_head); + } else { + res = init_head_from_data(ht, hash); + if (res != TEE_SUCCESS) + goto out; + + res = verify_root(ht); + if (res != TEE_SUCCESS) + goto out; + + res = init_tree_from_data(ht); + if (res != TEE_SUCCESS) + goto out; + + res = verify_tree(ht); + } +out: + if (res == TEE_SUCCESS) + *ht_ret = ht; + else + tee_fs_htree_close(&ht); + return res; +} + +struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht) +{ + return &ht->imeta.meta; +} + +void tee_fs_htree_meta_set_dirty(struct tee_fs_htree *ht) +{ + ht->dirty = true; + ht->root.dirty = true; +} + +static TEE_Result free_node(struct traverse_arg *targ __unused, + struct htree_node *node) +{ + if (node->parent) + free(node); + return TEE_SUCCESS; +} + +void tee_fs_htree_close(struct tee_fs_htree **ht) +{ + if (!*ht) + return; + htree_traverse_post_order(*ht, free_node, NULL); + free(*ht); + *ht = NULL; +} + +static TEE_Result htree_sync_node_to_storage(struct traverse_arg *targ, + struct htree_node *node) +{ + TEE_Result res; + uint8_t vers; + struct tee_fs_htree_meta *meta = NULL; + + /* + * The node can be dirty while the block isn't updated due to + * updated children, but if block is updated the node has to be + * dirty. + */ + assert(node->dirty >= node->block_updated); + + if (!node->dirty) + return TEE_SUCCESS; + + if (node->parent) { + uint32_t f = HTREE_NODE_COMMITTED_CHILD(node->id & 1); + + node->parent->dirty = true; + node->parent->node.flags ^= f; + vers = !!(node->parent->node.flags & f); + } else { + /* + * Counter isn't updated yet, it's increased just before + * writing the header. + */ + vers = !(targ->ht->head.counter & 1); + meta = &targ->ht->imeta.meta; + } + + res = calc_node_hash(node, meta, targ->arg, node->node.hash); + if (res != TEE_SUCCESS) + return res; + + node->dirty = false; + node->block_updated = false; + + return rpc_write_node(targ->ht, node->id, vers, &node->node); +} + +static TEE_Result update_root(struct tee_fs_htree *ht) +{ + TEE_Result res; + void *ctx; + + ht->head.counter++; + + res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, NULL, sizeof(ht->imeta)); + if (res != TEE_SUCCESS) + return res; + + return authenc_encrypt_final(ctx, ht->head.tag, &ht->imeta, + sizeof(ht->imeta), &ht->head.imeta); +} + +TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht_arg, + uint8_t *hash) +{ + TEE_Result res; + struct tee_fs_htree *ht = *ht_arg; + void *ctx; + + if (!ht) + return TEE_ERROR_CORRUPT_OBJECT; + + if (!ht->dirty) + return TEE_SUCCESS; + + res = crypto_hash_alloc_ctx(&ctx, TEE_FS_HTREE_HASH_ALG); + if (res != TEE_SUCCESS) + return res; + + res = htree_traverse_post_order(ht, htree_sync_node_to_storage, ctx); + if (res != TEE_SUCCESS) + goto out; + + /* All the nodes are written to storage now. Time to update root. */ + res = update_root(ht); + if (res != TEE_SUCCESS) + goto out; + + res = rpc_write_head(ht, ht->head.counter & 1, &ht->head); + if (res != TEE_SUCCESS) + goto out; + + ht->dirty = false; + if (hash) + memcpy(hash, ht->root.node.hash, sizeof(ht->root.node.hash)); +out: + crypto_hash_free_ctx(ctx); + if (res != TEE_SUCCESS) + tee_fs_htree_close(ht_arg); + return res; +} + +static TEE_Result get_block_node(struct tee_fs_htree *ht, bool create, + size_t block_num, struct htree_node **node) +{ + TEE_Result res; + struct htree_node *nd; + + res = get_node(ht, create, BLOCK_NUM_TO_NODE_ID(block_num), &nd); + if (res == TEE_SUCCESS) + *node = nd; + + return res; +} + +TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht_arg, + size_t block_num, const void *block) +{ + struct tee_fs_htree *ht = *ht_arg; + TEE_Result res; + struct tee_fs_rpc_operation op; + struct htree_node *node = NULL; + uint8_t block_vers; + void *ctx; + void *enc_block; + + if (!ht) + return TEE_ERROR_CORRUPT_OBJECT; + + res = get_block_node(ht, true, block_num, &node); + if (res != TEE_SUCCESS) + goto out; + + if (!node->block_updated) + node->node.flags ^= HTREE_NODE_COMMITTED_BLOCK; + + block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK); + res = ht->stor->rpc_write_init(ht->stor_aux, &op, + TEE_FS_HTREE_TYPE_BLOCK, block_num, + block_vers, &enc_block); + if (res != TEE_SUCCESS) + goto out; + + res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, &node->node, + ht->stor->block_size); + if (res != TEE_SUCCESS) + goto out; + res = authenc_encrypt_final(ctx, node->node.tag, block, + ht->stor->block_size, enc_block); + if (res != TEE_SUCCESS) + goto out; + + res = ht->stor->rpc_write_final(&op); + if (res != TEE_SUCCESS) + goto out; + + node->block_updated = true; + node->dirty = true; + ht->dirty = true; +out: + if (res != TEE_SUCCESS) + tee_fs_htree_close(ht_arg); + return res; +} + +TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht_arg, + size_t block_num, void *block) +{ + struct tee_fs_htree *ht = *ht_arg; + TEE_Result res; + struct tee_fs_rpc_operation op; + struct htree_node *node; + uint8_t block_vers; + size_t len; + void *ctx; + void *enc_block; + + if (!ht) + return TEE_ERROR_CORRUPT_OBJECT; + + res = get_block_node(ht, false, block_num, &node); + if (res != TEE_SUCCESS) + goto out; + + block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK); + res = ht->stor->rpc_read_init(ht->stor_aux, &op, + TEE_FS_HTREE_TYPE_BLOCK, block_num, + block_vers, &enc_block); + if (res != TEE_SUCCESS) + goto out; + + res = ht->stor->rpc_read_final(&op, &len); + if (res != TEE_SUCCESS) + goto out; + if (len != ht->stor->block_size) { + res = TEE_ERROR_CORRUPT_OBJECT; + goto out; + } + + res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, &node->node, + ht->stor->block_size); + if (res != TEE_SUCCESS) + goto out; + + res = authenc_decrypt_final(ctx, node->node.tag, enc_block, + ht->stor->block_size, block); +out: + if (res != TEE_SUCCESS) + tee_fs_htree_close(ht_arg); + return res; +} + +TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht_arg, size_t block_num) +{ + struct tee_fs_htree *ht = *ht_arg; + size_t node_id = BLOCK_NUM_TO_NODE_ID(block_num); + struct htree_node *node; + + if (!ht) + return TEE_ERROR_CORRUPT_OBJECT; + + while (node_id < ht->imeta.max_node_id) { + node = find_closest_node(ht, ht->imeta.max_node_id); + assert(node && node->id == ht->imeta.max_node_id); + assert(!node->child[0] && !node->child[1]); + assert(node->parent); + assert(node->parent->child[node->id & 1] == node); + node->parent->child[node->id & 1] = NULL; + free(node); + ht->imeta.max_node_id--; + ht->dirty = true; + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/core/tee/socket.c b/optee/optee_os/core/tee/socket.c new file mode 100644 index 0000000..4002c61 --- /dev/null +++ b/optee/optee_os/core/tee/socket.c @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +static uint32_t get_instance_id(struct ts_session *sess) +{ + return sess->ctx->ops->get_instance_id(sess->ctx); +} + +static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct thread_param tpm[4] = { }; + struct mobj *mobj = NULL; + TEE_Result res = TEE_SUCCESS; + void *va = NULL; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + + if (exp_pt != param_types) { + DMSG("got param_types 0x%x, expected 0x%x", + param_types, exp_pt); + return TEE_ERROR_BAD_PARAMETERS; + } + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, + THREAD_SHM_TYPE_APPLICATION, + params[1].memref.size, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(va, params[1].memref.buffer, params[1].memref.size); + + tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN, instance_id, 0); + tpm[1] = THREAD_PARAM_VALUE(IN, + params[0].value.b, /* server port number */ + params[2].value.a, /* protocol */ + params[0].value.a /* ip version */); + tpm[2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size); + tpm[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm); + if (res == TEE_SUCCESS) + params[3].value.a = tpm[3].u.value.a; + + return res; +} + +static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct thread_param tpm = { }; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) { + DMSG("got param_types 0x%x, expected 0x%x", + param_types, exp_pt); + return TEE_ERROR_BAD_PARAMETERS; + } + + tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE, instance_id, + params[0].value.a); + + return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); +} + +static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct thread_param tpm[3] = { }; + struct mobj *mobj = NULL; + TEE_Result res = TEE_SUCCESS; + void *va = NULL; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) { + DMSG("got param_types 0x%x, expected 0x%x", + param_types, exp_pt); + return TEE_ERROR_BAD_PARAMETERS; + } + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, + THREAD_SHM_TYPE_APPLICATION, + params[1].memref.size, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(va, params[1].memref.buffer, params[1].memref.size); + + tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id, + params[0].value.a /* handle */); + tpm[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size); + tpm[2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */ + 0, 0); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); + params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */ + + return res; +} + +static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct thread_param tpm[3] = { }; + struct mobj *mobj = NULL; + TEE_Result res = TEE_SUCCESS; + void *va = NULL; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) { + DMSG("got param_types 0x%x, expected 0x%x", + param_types, exp_pt); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[1].memref.size) { + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, + THREAD_SHM_TYPE_APPLICATION, + params[1].memref.size, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + } + + tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id, + params[0].value.a /* handle */); + tpm[1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size); + tpm[2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */, 0, 0); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); + + if (params[1].memref.size) + memcpy(params[1].memref.buffer, va, + MIN(params[1].memref.size, tpm[1].u.memref.size)); + params[1].memref.size = tpm[1].u.memref.size; + + return res; +} + +static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct thread_param tpm[3] = { }; + struct mobj *mobj = NULL; + TEE_Result res = TEE_SUCCESS; + void *va = NULL; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) { + DMSG("got param_types 0x%x, expected 0x%x", + param_types, exp_pt); + return TEE_ERROR_BAD_PARAMETERS; + } + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, + THREAD_SHM_TYPE_APPLICATION, + params[1].memref.size, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(va, params[1].memref.buffer, params[1].memref.size); + + tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL, instance_id, + params[0].value.a /* handle */); + tpm[1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, params[1].memref.size); + tpm[2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* ioctl command */, + 0, 0); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); + if (tpm[1].u.memref.size <= params[1].memref.size) + memcpy(params[1].memref.buffer, va, tpm[1].u.memref.size); + + params[1].memref.size = tpm[1].u.memref.size; + + return res; +} + +typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]); + +static const ta_func ta_funcs[] = { + [PTA_SOCKET_OPEN] = socket_open, + [PTA_SOCKET_CLOSE] = socket_close, + [PTA_SOCKET_SEND] = socket_send, + [PTA_SOCKET_RECV] = socket_recv, + [PTA_SOCKET_IOCTL] = socket_ioctl, +}; + +/* + * Trusted Application Entry Points + */ + +static TEE_Result pta_socket_open_session(uint32_t param_types __unused, + TEE_Param pParams[TEE_NUM_PARAMS] __unused, + void **sess_ctx) +{ + struct ts_session *s = ts_get_calling_session(); + + /* Check that we're called from a TA */ + if (!s || !is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + *sess_ctx = (void *)(vaddr_t)get_instance_id(s); + + return TEE_SUCCESS; +} + +static void pta_socket_close_session(void *sess_ctx) +{ + TEE_Result res; + struct thread_param tpm = { + .attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = { + .a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx, + }, + }; + + res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); + if (res != TEE_SUCCESS) + DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res); +} + +static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id, + uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) +{ + if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id]) + return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params); + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket", + .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, + .open_session_entry_point = pta_socket_open_session, + .close_session_entry_point = pta_socket_close_session, + .invoke_command_entry_point = pta_socket_invoke_command); diff --git a/optee/optee_os/core/tee/sub.mk b/optee/optee_os/core/tee/sub.mk new file mode 100644 index 0000000..92f0111 --- /dev/null +++ b/optee/optee_os/core/tee/sub.mk @@ -0,0 +1,51 @@ +CFG_CRYPTO ?= y + +ifeq (y,$(CFG_CRYPTO)) + +# HMAC-based Extract-and-Expand Key Derivation Function +# http://tools.ietf.org/html/rfc5869 +# This is an OP-TEE extension, not part of the GlobalPlatform Internal API v1.0 +CFG_CRYPTO_HKDF ?= y + +# NIST SP800-56A Concatenation Key Derivation Function +# This is an OP-TEE extension +CFG_CRYPTO_CONCAT_KDF ?= y + +# PKCS #5 v2.0 / RFC 2898 key derivation function 2 +# This is an OP-TEE extension +CFG_CRYPTO_PBKDF2 ?= y + +endif + +srcs-y += entry_std.c +srcs-y += tee_cryp_utl.c +srcs-$(CFG_CRYPTO_HKDF) += tee_cryp_hkdf.c +srcs-$(CFG_CRYPTO_CONCAT_KDF) += tee_cryp_concat_kdf.c +srcs-$(CFG_CRYPTO_PBKDF2) += tee_cryp_pbkdf2.c + +ifeq ($(CFG_WITH_USER_TA),y) +srcs-y += tee_obj.c +srcs-y += tee_svc.c +srcs-y += tee_svc_cryp.c +srcs-y += tee_svc_storage.c +cppflags-tee_svc.c-y += -DTEE_IMPL_VERSION=$(TEE_IMPL_VERSION) +srcs-y += tee_time_generic.c +srcs-$(CFG_SECSTOR_TA) += tadb.c +srcs-$(CFG_GP_SOCKETS) += socket.c +srcs-y += tee_ta_enc_manager.c +endif #CFG_WITH_USER_TA,y + +srcs-$(_CFG_WITH_SECURE_STORAGE) += tee_fs_key_manager.c +srcs-$(CFG_RPMB_FS) += tee_rpmb_fs.c +srcs-$(CFG_NVME_RPMB_FS) += tee_nvme_rpmb_fs.c +srcs-$(CFG_REE_FS) += tee_ree_fs.c +srcs-$(CFG_REE_FS) += fs_dirfile.c +srcs-$(CFG_REE_FS) += fs_htree.c +srcs-$(CFG_REE_FS) += tee_fs_rpc.c + +ifeq ($(call cfg-one-enabled,CFG_WITH_USER_TA _CFG_WITH_SECURE_STORAGE),y) +srcs-y += tee_pobj.c +endif + +srcs-y += uuid.c +srcs-y += tee_supp_plugin_rpc.c diff --git a/optee/optee_os/core/tee/tadb.c b/optee/optee_os/core/tee/tadb.c new file mode 100644 index 0000000..92d62ca --- /dev/null +++ b/optee/optee_os/core/tee/tadb.c @@ -0,0 +1,783 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TADB_MAX_BUFFER_SIZE (64U * 1024) + +#define TADB_AUTH_ENC_ALG TEE_ALG_AES_GCM +#define TADB_IV_SIZE TEE_AES_BLOCK_SIZE +#define TADB_TAG_SIZE TEE_AES_BLOCK_SIZE +#define TADB_KEY_SIZE TEE_AES_MAX_KEY_SIZE + +struct tee_tadb_dir { + const struct tee_file_operations *ops; + struct tee_file_handle *fh; + int nbits; + bitstr_t *files; +}; + +/* + * struct tadb_entry - TA database entry + * @prop: properties of TA + * @file_number: encrypted TA is stored in .ta + * @iv: Initialization vector of the authentication crypto + * @tag: Tag used to validate the authentication encrypted TA + * @key: Key used to decrypt the TA + */ +struct tadb_entry { + struct tee_tadb_property prop; + uint32_t file_number; + uint8_t iv[TADB_IV_SIZE]; + uint8_t tag[TADB_TAG_SIZE]; + uint8_t key[TADB_KEY_SIZE]; +}; + +struct tadb_header { + uint32_t opaque_len; + uint8_t opaque[]; +}; + +struct tee_tadb_ta_write { + struct tee_tadb_dir *db; + int fd; + struct tadb_entry entry; + size_t pos; + void *ctx; +}; + +struct tee_tadb_ta_read { + struct tee_tadb_dir *db; + int fd; + struct tadb_entry entry; + size_t pos; + void *ctx; + struct mobj *ta_mobj; + uint8_t *ta_buf; +}; + +static const char tadb_obj_id[] = "ta.db"; +static struct tee_tadb_dir *tadb_db; +static unsigned int tadb_db_refc; +static struct mutex tadb_mutex = MUTEX_INITIALIZER; + +static void file_num_to_str(char *buf, size_t blen, uint32_t file_number) +{ + int rc __maybe_unused = 0; + + rc = snprintf(buf, blen, "%" PRIu32 ".ta", file_number); + assert(rc >= 0); +} + +static bool is_null_uuid(const TEE_UUID *uuid) +{ + const TEE_UUID null_uuid = { 0 }; + + return !memcmp(uuid, &null_uuid, sizeof(*uuid)); +} + +static TEE_Result ta_operation_open(unsigned int cmd, uint32_t file_number, + int *fd) +{ + struct thread_param params[3] = { }; + struct mobj *mobj = NULL; + TEE_Result res = TEE_SUCCESS; + void *va = NULL; + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, + THREAD_SHM_TYPE_APPLICATION, + TEE_FS_NAME_MAX, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + file_num_to_str(va, TEE_FS_NAME_MAX, file_number); + + params[0] = THREAD_PARAM_VALUE(IN, cmd, 0, 0); + params[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX); + params[2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_FS, ARRAY_SIZE(params), params); + if (!res) + *fd = params[2].u.value.a; + + return res; +} + +static TEE_Result ta_operation_remove(uint32_t file_number) +{ + struct thread_param params[2] = { }; + struct mobj *mobj = NULL; + void *va = NULL; + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, + THREAD_SHM_TYPE_APPLICATION, + TEE_FS_NAME_MAX, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + file_num_to_str(va, TEE_FS_NAME_MAX, file_number); + + params[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_REMOVE, 0, 0); + params[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX); + + return thread_rpc_cmd(OPTEE_RPC_CMD_FS, ARRAY_SIZE(params), params); +} + +static TEE_Result maybe_grow_files(struct tee_tadb_dir *db, int idx) +{ + void *p; + + if (idx < db->nbits) + return TEE_SUCCESS; + + p = realloc(db->files, bitstr_size(idx + 1)); + if (!p) + return TEE_ERROR_OUT_OF_MEMORY; + db->files = p; + + bit_nclear(db->files, db->nbits, idx); + db->nbits = idx + 1; + + return TEE_SUCCESS; +} + +static TEE_Result set_file(struct tee_tadb_dir *db, int idx) +{ + TEE_Result res = maybe_grow_files(db, idx); + + if (!res) + bit_set(db->files, idx); + + return res; +} + +static void clear_file(struct tee_tadb_dir *db, int idx) +{ + /* + * This is safe because db->nbits > 0 implies that + * db->files is non-NULL (see maybe_grow_files()). + */ + if (idx < db->nbits) + bit_clear(db->files, idx); +} + +static bool test_file(struct tee_tadb_dir *db, int idx) +{ + /* + * This is safe because db->nbits > 0 implies that + * db->files is non-NULL (see maybe_grow_files()). + */ + if (idx < db->nbits) + return bit_test(db->files, idx); + + return false; +} + +static TEE_Result read_ent(struct tee_tadb_dir *db, size_t idx, + struct tadb_entry *entry) +{ + size_t l = sizeof(*entry); + TEE_Result res = db->ops->read(db->fh, idx * l, entry, &l); + + if (!res && l != sizeof(*entry)) + return TEE_ERROR_ITEM_NOT_FOUND; + + return res; +} + +static TEE_Result write_ent(struct tee_tadb_dir *db, size_t idx, + const struct tadb_entry *entry) +{ + const size_t l = sizeof(*entry); + + return db->ops->write(db->fh, idx * l, entry, l); +} + +static TEE_Result tadb_open(struct tee_tadb_dir **db_ret) +{ + TEE_Result res; + struct tee_tadb_dir *db = calloc(1, sizeof(*db)); + struct tee_pobj po = { + .obj_id = (void *)tadb_obj_id, + .obj_id_len = sizeof(tadb_obj_id) + }; + + if (!db) + return TEE_ERROR_OUT_OF_MEMORY; + + db->ops = tee_svc_storage_file_ops(TEE_STORAGE_PRIVATE); + + res = db->ops->open(&po, NULL, &db->fh); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = db->ops->create(&po, false, NULL, 0, NULL, 0, NULL, 0, + &db->fh); + + if (res) + free(db); + else + *db_ret = db; + + return res; +} + +static TEE_Result tee_tadb_open(struct tee_tadb_dir **db) +{ + TEE_Result res = TEE_SUCCESS; + + mutex_lock(&tadb_mutex); + if (!tadb_db_refc) { + assert(!tadb_db); + res = tadb_open(&tadb_db); + if (res) + goto err; + } + tadb_db_refc++; + *db = tadb_db; +err: + mutex_unlock(&tadb_mutex); + return res; +} + +static void tadb_put(struct tee_tadb_dir *db) +{ + assert(db == tadb_db); + mutex_lock(&tadb_mutex); + assert(tadb_db_refc); + tadb_db_refc--; + if (!tadb_db_refc) { + db->ops->close(&db->fh); + free(db->files); + free(db); + tadb_db = NULL; + } + mutex_unlock(&tadb_mutex); +} + +static void tee_tadb_close(struct tee_tadb_dir *db) +{ + tadb_put(db); +} + +static TEE_Result tadb_authenc_init(TEE_OperationMode mode, + const struct tadb_entry *entry, + void **ctx_ret) +{ + TEE_Result res; + void *ctx; + const size_t enc_size = entry->prop.custom_size + entry->prop.bin_size; + + res = crypto_authenc_alloc_ctx(&ctx, TADB_AUTH_ENC_ALG); + if (res) + return res; + + res = crypto_authenc_init(ctx, mode, entry->key, sizeof(entry->key), + entry->iv, sizeof(entry->iv), + sizeof(entry->tag), 0, enc_size); + if (res) + crypto_authenc_free_ctx(ctx); + else + *ctx_ret = ctx; + + return res; +} + +static TEE_Result tadb_update_payload(void *ctx, TEE_OperationMode mode, + const void *src, size_t len, void *dst) +{ + TEE_Result res; + size_t sz = len; + + res = crypto_authenc_update_payload(ctx, mode, (const uint8_t *)src, + len, dst, &sz); + assert(res || sz == len); + return res; +} + +static TEE_Result populate_files(struct tee_tadb_dir *db) +{ + TEE_Result res; + size_t idx; + + /* + * If db->files isn't NULL the bitfield is already populated and + * there's nothing left to do here for now. + */ + if (db->nbits) + return TEE_SUCCESS; + + /* + * Iterate over the TA database and set the bits in the bit field + * for used file numbers. Note that set_file() will allocate and + * grow the bitfield as needed. + * + * At the same time clean out duplicate file numbers, the first + * entry with the file number has precedence. Duplicate entries is + * not supposed to be able to happen, but if it still does better + * to clean it out here instead of letting the error spread with + * unexpected side effects. + */ + for (idx = 0;; idx++) { + struct tadb_entry entry; + + res = read_ent(db, idx, &entry); + if (res) { + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return TEE_SUCCESS; + goto err; + } + + if (is_null_uuid(&entry.prop.uuid)) + continue; + + if (test_file(db, entry.file_number)) { + IMSG("Clearing duplicate file number %" PRIu32, + entry.file_number); + memset(&entry, 0, sizeof(entry)); + res = write_ent(db, idx, &entry); + if (res) + goto err; + continue; + } + + res = set_file(db, entry.file_number); + if (res) + goto err; + } + +err: + free(db->files); + db->files = NULL; + db->nbits = 0; + + return res; +} + +TEE_Result tee_tadb_ta_create(const struct tee_tadb_property *property, + struct tee_tadb_ta_write **ta_ret) +{ + TEE_Result res; + struct tee_tadb_ta_write *ta; + int i = 0; + + if (is_null_uuid(&property->uuid)) + return TEE_ERROR_GENERIC; + + ta = calloc(1, sizeof(*ta)); + if (!ta) + return TEE_ERROR_OUT_OF_MEMORY; + + res = tee_tadb_open(&ta->db); + if (res) + goto err_free; + + mutex_lock(&tadb_mutex); + + /* + * Since we're going to search for next free file number below we + * need to populate the bitfield holding used file numbers. + */ + res = populate_files(ta->db); + if (res) + goto err_mutex; + + if (ta->db->files) { + bit_ffc(ta->db->files, ta->db->nbits, &i); + if (i == -1) + i = ta->db->nbits; + } + + res = set_file(ta->db, i); + if (res) + goto err_mutex; + + mutex_unlock(&tadb_mutex); + + ta->entry.file_number = i; + ta->entry.prop = *property; + + res = crypto_rng_read(ta->entry.iv, sizeof(ta->entry.iv)); + if (res) + goto err_put; + + res = crypto_rng_read(ta->entry.key, sizeof(ta->entry.key)); + if (res) + goto err_put; + + res = ta_operation_open(OPTEE_RPC_FS_CREATE, ta->entry.file_number, + &ta->fd); + if (res) + goto err_put; + + res = tadb_authenc_init(TEE_MODE_ENCRYPT, &ta->entry, &ta->ctx); + if (res) + goto err_put; + + *ta_ret = ta; + + return TEE_SUCCESS; + +err_mutex: + mutex_unlock(&tadb_mutex); +err_put: + tadb_put(ta->db); +err_free: + free(ta); + + return res; +} + +TEE_Result tee_tadb_ta_write(struct tee_tadb_ta_write *ta, const void *buf, + size_t len) +{ + TEE_Result res; + const uint8_t *rb = buf; + size_t rl = len; + struct tee_fs_rpc_operation op; + + while (rl) { + size_t wl = MIN(rl, TADB_MAX_BUFFER_SIZE); + void *wb; + + res = tee_fs_rpc_write_init(&op, OPTEE_RPC_CMD_FS, ta->fd, + ta->pos, wl, &wb); + if (res) + return res; + + res = tadb_update_payload(ta->ctx, TEE_MODE_ENCRYPT, + rb, wl, wb); + if (res) + return res; + + res = tee_fs_rpc_write_final(&op); + if (res) + return res; + + rl -= wl; + rb += wl; + ta->pos += wl; + } + + return TEE_SUCCESS; +} + +void tee_tadb_ta_close_and_delete(struct tee_tadb_ta_write *ta) +{ + crypto_authenc_final(ta->ctx); + crypto_authenc_free_ctx(ta->ctx); + tee_fs_rpc_close(OPTEE_RPC_CMD_FS, ta->fd); + ta_operation_remove(ta->entry.file_number); + + mutex_lock(&tadb_mutex); + clear_file(ta->db, ta->entry.file_number); + mutex_unlock(&tadb_mutex); + + tadb_put(ta->db); + free(ta); +} + +static TEE_Result find_ent(struct tee_tadb_dir *db, const TEE_UUID *uuid, + size_t *idx_ret, struct tadb_entry *entry_ret) +{ + TEE_Result res; + size_t idx; + + /* + * Search for the provided uuid, if it's found return the index it + * has together with TEE_SUCCESS. + * + * If the uuid can't be found return the number indexes together + * with TEE_ERROR_ITEM_NOT_FOUND. + */ + for (idx = 0;; idx++) { + struct tadb_entry entry; + + res = read_ent(db, idx, &entry); + if (res) { + if (res == TEE_ERROR_ITEM_NOT_FOUND) + break; + return res; + } + + if (!memcmp(&entry.prop.uuid, uuid, sizeof(*uuid))) { + if (entry_ret) + *entry_ret = entry; + break; + } + } + + *idx_ret = idx; + return res; +} + +static TEE_Result find_free_ent_idx(struct tee_tadb_dir *db, size_t *idx) +{ + const TEE_UUID null_uuid = { 0 }; + TEE_Result res = find_ent(db, &null_uuid, idx, NULL); + + /* + * Note that *idx is set to the number of entries on + * TEE_ERROR_ITEM_NOT_FOUND. + */ + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return TEE_SUCCESS; + return res; +} + +TEE_Result tee_tadb_ta_close_and_commit(struct tee_tadb_ta_write *ta) +{ + TEE_Result res; + size_t dsz = 0; + size_t sz = sizeof(ta->entry.tag); + size_t idx; + struct tadb_entry old_ent; + bool have_old_ent = false; + + res = crypto_authenc_enc_final(ta->ctx, NULL, 0, NULL, &dsz, + ta->entry.tag, &sz); + if (res) + goto err; + + tee_fs_rpc_close(OPTEE_RPC_CMD_FS, ta->fd); + + mutex_lock(&tadb_mutex); + /* + * First try to find an existing TA to replace. If there's one + * we'll use the entry, but we should also remove the old encrypted + * file. + * + * If there isn't an existing TA to replace, grab a new entry. + */ + res = find_ent(ta->db, &ta->entry.prop.uuid, &idx, &old_ent); + if (!res) { + have_old_ent = true; + } else { + res = find_free_ent_idx(ta->db, &idx); + if (res) + goto err_mutex; + } + res = write_ent(ta->db, idx, &ta->entry); + if (res) + goto err_mutex; + if (have_old_ent) + clear_file(ta->db, old_ent.file_number); + mutex_unlock(&tadb_mutex); + + crypto_authenc_final(ta->ctx); + crypto_authenc_free_ctx(ta->ctx); + tadb_put(ta->db); + free(ta); + if (have_old_ent) + ta_operation_remove(old_ent.file_number); + return TEE_SUCCESS; + +err_mutex: + mutex_unlock(&tadb_mutex); +err: + tee_tadb_ta_close_and_delete(ta); + return res; +} + +TEE_Result tee_tadb_ta_delete(const TEE_UUID *uuid) +{ + const struct tadb_entry null_entry = { { { 0 } } }; + struct tee_tadb_dir *db; + struct tadb_entry entry; + size_t idx; + TEE_Result res; + + if (is_null_uuid(uuid)) + return TEE_ERROR_GENERIC; + + res = tee_tadb_open(&db); + if (res) + return res; + + mutex_lock(&tadb_mutex); + res = find_ent(db, uuid, &idx, &entry); + if (res) { + mutex_unlock(&tadb_mutex); + tee_tadb_close(db); + return res; + } + + clear_file(db, entry.file_number); + res = write_ent(db, idx, &null_entry); + mutex_unlock(&tadb_mutex); + + tee_tadb_close(db); + if (res) + return res; + + ta_operation_remove(entry.file_number); + return TEE_SUCCESS; +} + +TEE_Result tee_tadb_ta_open(const TEE_UUID *uuid, + struct tee_tadb_ta_read **ta_ret) +{ + TEE_Result res = TEE_SUCCESS; + size_t idx = 0; + struct tee_tadb_ta_read *ta = NULL; + + if (is_null_uuid(uuid)) + return TEE_ERROR_GENERIC; + + ta = calloc(1, sizeof(*ta)); + if (!ta) + return TEE_ERROR_OUT_OF_MEMORY; + + res = tee_tadb_open(&ta->db); + if (res) + goto err_free; /* Mustn't call tadb_put() */ + + mutex_read_lock(&tadb_mutex); + res = find_ent(ta->db, uuid, &idx, &ta->entry); + mutex_read_unlock(&tadb_mutex); + if (res) + goto err; + + res = ta_operation_open(OPTEE_RPC_FS_OPEN, ta->entry.file_number, + &ta->fd); + if (res) + goto err; + + res = tadb_authenc_init(TEE_MODE_DECRYPT, &ta->entry, &ta->ctx); + if (res) + goto err; + + *ta_ret = ta; + + return TEE_SUCCESS; +err: + tadb_put(ta->db); +err_free: + free(ta); + return res; +} + +const struct tee_tadb_property * +tee_tadb_ta_get_property(struct tee_tadb_ta_read *ta) +{ + return &ta->entry.prop; +} + +TEE_Result tee_tadb_get_tag(struct tee_tadb_ta_read *ta, uint8_t *tag, + unsigned int *tag_len) +{ + if (!tag || *tag_len < sizeof(ta->entry.tag)) { + *tag_len = sizeof(ta->entry.tag); + return TEE_ERROR_SHORT_BUFFER; + } + *tag_len = sizeof(ta->entry.tag); + + memcpy(tag, ta->entry.tag, sizeof(ta->entry.tag)); + + return TEE_SUCCESS; +} + +static TEE_Result ta_load(struct tee_tadb_ta_read *ta) +{ + struct thread_param params[2] = { }; + TEE_Result res; + const size_t sz = ta->entry.prop.custom_size + ta->entry.prop.bin_size; + + if (ta->ta_mobj) + return TEE_SUCCESS; + + ta->ta_mobj = thread_rpc_alloc_payload(sz); + if (!ta->ta_mobj) + return TEE_ERROR_OUT_OF_MEMORY; + + ta->ta_buf = mobj_get_va(ta->ta_mobj, 0, sz); + assert(ta->ta_buf); + + params[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_READ, ta->fd, 0); + params[1] = THREAD_PARAM_MEMREF(OUT, ta->ta_mobj, 0, sz); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_FS, ARRAY_SIZE(params), params); + if (res) { + thread_rpc_free_payload(ta->ta_mobj); + ta->ta_mobj = NULL; + } + return res; +} + +TEE_Result tee_tadb_ta_read(struct tee_tadb_ta_read *ta, void *buf, size_t *len) +{ + TEE_Result res; + const size_t sz = ta->entry.prop.custom_size + ta->entry.prop.bin_size; + size_t l = MIN(*len, sz - ta->pos); + + res = ta_load(ta); + if (res) + return res; + + if (buf) { + res = tadb_update_payload(ta->ctx, TEE_MODE_DECRYPT, + ta->ta_buf + ta->pos, l, buf); + if (res) + return res; + } else { + size_t num_bytes = 0; + size_t b_size = MIN(256U, l); + uint8_t *b = malloc(b_size); + + if (!b) + return TEE_ERROR_OUT_OF_MEMORY; + + while (num_bytes < l) { + size_t n = MIN(b_size, l - num_bytes); + + res = tadb_update_payload(ta->ctx, TEE_MODE_DECRYPT, + ta->ta_buf + ta->pos + + num_bytes, n, b); + if (res) + break; + num_bytes += n; + } + + free(b); + if (res) + return res; + } + + ta->pos += l; + if (ta->pos == sz) { + size_t dl = 0; + + res = crypto_authenc_dec_final(ta->ctx, NULL, 0, NULL, &dl, + ta->entry.tag, TADB_TAG_SIZE); + if (res) + return res; + } + *len = l; + return TEE_SUCCESS; +} + +void tee_tadb_ta_close(struct tee_tadb_ta_read *ta) +{ + crypto_authenc_final(ta->ctx); + crypto_authenc_free_ctx(ta->ctx); + if (ta->ta_mobj) + thread_rpc_free_payload(ta->ta_mobj); + tee_fs_rpc_close(OPTEE_RPC_CMD_FS, ta->fd); + tadb_put(ta->db); + free(ta); +} diff --git a/optee/optee_os/core/tee/tee_cryp_concat_kdf.c b/optee/optee_os/core/tee/tee_cryp_concat_kdf.c new file mode 100644 index 0000000..8e74ec3 --- /dev/null +++ b/optee/optee_os/core/tee/tee_cryp_concat_kdf.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret, + size_t shared_secret_len, + const uint8_t *other_info, + size_t other_info_len, uint8_t *derived_key, + size_t derived_key_len) +{ + TEE_Result res; + size_t hash_len, i, n, sz; + void *ctx = NULL; + uint8_t tmp[TEE_MAX_HASH_SIZE]; + uint32_t be_count; + uint8_t *out = derived_key; + uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); + + res = crypto_hash_alloc_ctx(&ctx, hash_algo); + if (res != TEE_SUCCESS) + return res; + + res = tee_alg_get_digest_size(hash_algo, &hash_len); + if (res != TEE_SUCCESS) + goto out; + + n = derived_key_len / hash_len; + sz = hash_len; + for (i = 1; i <= n + 1; i++) { + be_count = TEE_U32_TO_BIG_ENDIAN(i); + + res = crypto_hash_init(ctx); + if (res != TEE_SUCCESS) + goto out; + res = crypto_hash_update(ctx, (uint8_t *)&be_count, + sizeof(be_count)); + if (res != TEE_SUCCESS) + goto out; + res = crypto_hash_update(ctx, shared_secret, shared_secret_len); + if (res != TEE_SUCCESS) + goto out; + if (other_info && other_info_len) { + res = crypto_hash_update(ctx, other_info, + other_info_len); + if (res != TEE_SUCCESS) + goto out; + } + res = crypto_hash_final(ctx, tmp, sizeof(tmp)); + if (res != TEE_SUCCESS) + goto out; + + if (i == n + 1) + sz = derived_key_len % hash_len; + memcpy(out, tmp, sz); + out += sz; + } + res = TEE_SUCCESS; +out: + crypto_hash_free_ctx(ctx); + return res; +} diff --git a/optee/optee_os/core/tee/tee_cryp_hkdf.c b/optee/optee_os/core/tee/tee_cryp_hkdf.c new file mode 100644 index 0000000..c62f22b --- /dev/null +++ b/optee/optee_os/core/tee/tee_cryp_hkdf.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + + +static const uint8_t zero_salt[TEE_MAX_HASH_SIZE]; + +static TEE_Result hkdf_extract(uint32_t hash_id, const uint8_t *ikm, + size_t ikm_len, const uint8_t *salt, + size_t salt_len, uint8_t *prk, size_t *prk_len) +{ + TEE_Result res; + void *ctx = NULL; + uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); + uint32_t hmac_algo = (TEE_OPERATION_MAC << 28) | hash_id; + + if (!salt || !salt_len) { + /* + * RFC 5869 section 2.2: + * If not provided, [the salt] is set to a string of HashLen + * zeros + */ + salt = zero_salt; + res = tee_alg_get_digest_size(hash_algo, &salt_len); + if (res != TEE_SUCCESS) + goto out; + } + + res = crypto_mac_alloc_ctx(&ctx, hmac_algo); + if (res) + goto out; + + /* + * RFC 5869 section 2.1: "Note that in the extract step, 'IKM' is used + * as the HMAC input, not as the HMAC key." + * Therefore, salt is the HMAC key in the formula from section 2.2: + * "PRK = HMAC-Hash(salt, IKM)" + */ + res = crypto_mac_init(ctx, salt, salt_len); + if (res != TEE_SUCCESS) + goto out; + + res = crypto_mac_update(ctx, ikm, ikm_len); + if (res != TEE_SUCCESS) + goto out; + + res = crypto_mac_final(ctx, prk, *prk_len); + if (res != TEE_SUCCESS) + goto out; + + res = tee_alg_get_digest_size(hash_algo, prk_len); +out: + crypto_mac_free_ctx(ctx); + return res; +} + +static TEE_Result hkdf_expand(uint32_t hash_id, const uint8_t *prk, + size_t prk_len, const uint8_t *info, + size_t info_len, uint8_t *okm, size_t okm_len) +{ + uint8_t tn[TEE_MAX_HASH_SIZE]; + size_t tn_len, hash_len, i, n, where; + TEE_Result res = TEE_SUCCESS; + void *ctx = NULL; + uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); + uint32_t hmac_algo = TEE_ALG_HMAC_ALGO(hash_id); + + res = tee_alg_get_digest_size(hash_algo, &hash_len); + if (res != TEE_SUCCESS) + goto out; + + if (!okm || prk_len < hash_len) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + if (!info) + info_len = 0; + + res = crypto_mac_alloc_ctx(&ctx, hmac_algo); + if (res) + goto out; + + /* N = ceil(L/HashLen) */ + n = okm_len / hash_len; + if ((okm_len % hash_len) != 0) + n++; + + if (n > 255) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + + /* + * RFC 5869 section 2.3 + * T = T(1) | T(2) | T(3) | ... | T(N) + * OKM = first L octets of T + * T(0) = empty string (zero length) + * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) + * ... + */ + tn_len = 0; + where = 0; + for (i = 1; i <= n; i++) { + uint8_t c = i; + + res = crypto_mac_init(ctx, prk, prk_len); + if (res != TEE_SUCCESS) + goto out; + res = crypto_mac_update(ctx, tn, tn_len); + if (res != TEE_SUCCESS) + goto out; + res = crypto_mac_update(ctx, info, info_len); + if (res != TEE_SUCCESS) + goto out; + res = crypto_mac_update(ctx, &c, 1); + if (res != TEE_SUCCESS) + goto out; + res = crypto_mac_final(ctx, tn, sizeof(tn)); + if (res != TEE_SUCCESS) + goto out; + + memcpy(okm + where, tn, (i < n) ? hash_len : (okm_len - where)); + where += hash_len; + tn_len = hash_len; + } + +out: + crypto_mac_free_ctx(ctx); + return res; +} + +TEE_Result tee_cryp_hkdf(uint32_t hash_id, const uint8_t *ikm, size_t ikm_len, + const uint8_t *salt, size_t salt_len, + const uint8_t *info, size_t info_len, uint8_t *okm, + size_t okm_len) +{ + TEE_Result res; + uint8_t prk[TEE_MAX_HASH_SIZE]; + size_t prk_len = sizeof(prk); + + res = hkdf_extract(hash_id, ikm, ikm_len, salt, salt_len, prk, + &prk_len); + if (res != TEE_SUCCESS) + return res; + res = hkdf_expand(hash_id, prk, prk_len, info, info_len, okm, + okm_len); + + return res; +} diff --git a/optee/optee_os/core/tee/tee_cryp_pbkdf2.c b/optee/optee_os/core/tee/tee_cryp_pbkdf2.c new file mode 100644 index 0000000..1a7dd57 --- /dev/null +++ b/optee/optee_os/core/tee/tee_cryp_pbkdf2.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +struct hmac_parms { + uint32_t algo; + size_t hash_len; + void *ctx; +}; + +struct pbkdf2_parms { + const uint8_t *password; + size_t password_len; + const uint8_t *salt; + size_t salt_len; + uint32_t iteration_count; +}; + +static TEE_Result pbkdf2_f(uint8_t *out, size_t len, uint32_t idx, + struct hmac_parms *h, struct pbkdf2_parms *p) +{ + TEE_Result res; + uint8_t u[TEE_MAX_HASH_SIZE]; + uint32_t be_index; + size_t i, j; + + memset(out, 0, len); + for (i = 1; i <= p->iteration_count; i++) { + res = crypto_mac_init(h->ctx, p->password, p->password_len); + if (res != TEE_SUCCESS) + return res; + + if (i == 1) { + if (p->salt && p->salt_len) { + res = crypto_mac_update(h->ctx, p->salt, + p->salt_len); + if (res != TEE_SUCCESS) + return res; + } + + be_index = TEE_U32_TO_BIG_ENDIAN(idx); + + res = crypto_mac_update(h->ctx, (uint8_t *)&be_index, + sizeof(be_index)); + if (res != TEE_SUCCESS) + return res; + } else { + res = crypto_mac_update(h->ctx, u, h->hash_len); + if (res != TEE_SUCCESS) + return res; + } + + res = crypto_mac_final(h->ctx, u, sizeof(u)); + if (res != TEE_SUCCESS) + return res; + + for (j = 0; j < len; j++) + out[j] ^= u[j]; + } + return TEE_SUCCESS; +} + +TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password, + size_t password_len, const uint8_t *salt, + size_t salt_len, uint32_t iteration_count, + uint8_t *derived_key, size_t derived_key_len) +{ + TEE_Result res; + size_t i, l, r; + uint8_t *out = derived_key; + struct pbkdf2_parms pbkdf2_parms; + struct hmac_parms hmac_parms = {0, }; + + hmac_parms.algo = TEE_ALG_HMAC_ALGO(hash_id); + + res = tee_alg_get_digest_size(hmac_parms.algo, &hmac_parms.hash_len); + if (res != TEE_SUCCESS) + return res; + + res = crypto_mac_alloc_ctx(&hmac_parms.ctx, hmac_parms.algo); + if (res != TEE_SUCCESS) + return res; + + pbkdf2_parms.password = password; + pbkdf2_parms.password_len = password_len; + pbkdf2_parms.salt = salt; + pbkdf2_parms.salt_len = salt_len; + pbkdf2_parms.iteration_count = iteration_count; + + l = derived_key_len / hmac_parms.hash_len; + r = derived_key_len % hmac_parms.hash_len; + + for (i = 1; i <= l; i++) { + res = pbkdf2_f(out, hmac_parms.hash_len, i, &hmac_parms, + &pbkdf2_parms); + if (res != TEE_SUCCESS) + goto out; + out += hmac_parms.hash_len; + } + if (r) + res = pbkdf2_f(out, r, i, &hmac_parms, &pbkdf2_parms); + +out: + crypto_mac_free_ctx(hmac_parms.ctx); + return res; +} diff --git a/optee/optee_os/core/tee/tee_cryp_utl.c b/optee/optee_os/core/tee/tee_cryp_utl.c new file mode 100644 index 0000000..3220c16 --- /dev/null +++ b/optee/optee_os/core/tee/tee_cryp_utl.c @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2021, Linaro Limited + * Copyright (c) 2021, SumUp Services GmbH + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result tee_alg_get_digest_size(uint32_t algo, size_t *size) +{ + size_t digest_size = TEE_ALG_GET_DIGEST_SIZE(algo); + + if (!digest_size) + return TEE_ERROR_NOT_SUPPORTED; + + *size = digest_size; + + 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; + void *ctx = NULL; + + res = crypto_hash_alloc_ctx(&ctx, algo); + if (res) + return res; + + res = crypto_hash_init(ctx); + if (res) + goto out; + + if (datalen != 0) { + res = crypto_hash_update(ctx, data, datalen); + if (res) + goto out; + } + + res = crypto_hash_final(ctx, digest, digestlen); +out: + crypto_hash_free_ctx(ctx); + + return res; +} + +TEE_Result tee_cipher_get_block_size(uint32_t algo, size_t *size) +{ + 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: + case TEE_ALG_SM4_ECB_NOPAD: + case TEE_ALG_SM4_CBC_NOPAD: + case TEE_ALG_SM4_XTS: + case TEE_ALG_SM4_CTR: + *size = 16; + 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: + 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: + case TEE_ALG_DES3_CMAC: + *size = 8; + break; + + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +TEE_Result tee_do_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; + size_t block_size; + + if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * 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 && algo != TEE_ALG_AES_CTR) + 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: + case TEE_ALG_SM4_ECB_NOPAD: + case TEE_ALG_SM4_CBC_NOPAD: + return TEE_ERROR_BAD_PARAMETERS; + + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_XTS: + case TEE_ALG_AES_CTS: + case TEE_ALG_SM4_XTS: + /* + * 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; + } + } + + return crypto_cipher_update(ctx, mode, last_block, data, len, dst); +} + +/* + * Override this in your platform code to feed the PRNG platform-specific + * jitter entropy. This implementation does not efficiently deliver entropy + * and is here for backwards-compatibility. + */ +__weak void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, + unsigned int *pnum) +{ + TEE_Time current; + +#ifdef CFG_SECURE_TIME_SOURCE_REE + if (CRYPTO_RNG_SRC_IS_QUICK(sid)) + return; /* Can't read REE time here */ +#endif + + if (tee_time_get_sys_time(¤t) == TEE_SUCCESS) + crypto_rng_add_event(sid, pnum, ¤t, sizeof(current)); +} + +__weak void plat_rng_init(void) +{ + TEE_Result res = TEE_SUCCESS; + TEE_Time t; + +#ifndef CFG_SECURE_TIME_SOURCE_REE + /* + * This isn't much of a seed. Ideally we should either get a seed from + * a hardware RNG or from a previously saved seed. + * + * Seeding with hardware RNG is currently up to the platform to + * override this function. + * + * Seeding with a saved seed will require cooperation from normal + * world, this is still TODO. + */ + res = tee_time_get_sys_time(&t); +#else + EMSG("Warning: seeding RNG with zeroes"); + memset(&t, 0, sizeof(t)); +#endif + if (!res) + res = crypto_rng_init(&t, sizeof(t)); + if (res) { + EMSG("Failed to initialize RNG: %#" PRIx32, res); + panic(); + } +} + +static TEE_Result tee_cryp_init(void) +{ + TEE_Result res = crypto_init(); + + if (res) { + EMSG("Failed to initialize crypto API: %#" PRIx32, res); + panic(); + } + plat_rng_init(); + + dt_driver_crypt_init_complete(); + + return TEE_SUCCESS; +} +service_init(tee_cryp_init); diff --git a/optee/optee_os/core/tee/tee_fs_key_manager.c b/optee/optee_os/core/tee/tee_fs_key_manager.c new file mode 100644 index 0000000..00bafca --- /dev/null +++ b/optee/optee_os/core/tee/tee_fs_key_manager.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + + +/* + * Acronyms: + * + * FEK - File Encryption Key + * SSK - Secure Storage Key + * TSK - Trusted app Storage Key + * IV - Initial vector + * HUK - Hardware Unique Key + * RNG - Random Number Generator + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct tee_fs_ssk { + bool is_init; + uint8_t key[TEE_FS_KM_SSK_SIZE]; +}; + +static struct tee_fs_ssk tee_fs_ssk; + +static TEE_Result do_hmac(void *out_key, size_t out_key_size, + const void *in_key, size_t in_key_size, + const void *message, size_t message_size) +{ + TEE_Result res; + void *ctx = NULL; + + if (!out_key || !in_key || !message) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_mac_alloc_ctx(&ctx, TEE_FS_KM_HMAC_ALG); + if (res != TEE_SUCCESS) + return res; + + res = crypto_mac_init(ctx, in_key, in_key_size); + if (res != TEE_SUCCESS) + goto exit; + + res = crypto_mac_update(ctx, message, message_size); + if (res != TEE_SUCCESS) + goto exit; + + res = crypto_mac_final(ctx, out_key, out_key_size); + if (res != TEE_SUCCESS) + goto exit; + + res = TEE_SUCCESS; + +exit: + crypto_mac_free_ctx(ctx); + return res; +} + +TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode, + const uint8_t *in_key, size_t size, + uint8_t *out_key) +{ + TEE_Result res; + void *ctx = NULL; + uint8_t tsk[TEE_FS_KM_TSK_SIZE]; + uint8_t dst_key[size]; + + if (!in_key || !out_key) + return TEE_ERROR_BAD_PARAMETERS; + + if (size != TEE_FS_KM_FEK_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + if (tee_fs_ssk.is_init == 0) + return TEE_ERROR_GENERIC; + + if (uuid) { + res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, + TEE_FS_KM_SSK_SIZE, uuid, sizeof(*uuid)); + if (res != TEE_SUCCESS) + return res; + } else { + /* + * Pick something of a different size than TEE_UUID to + * guarantee that there's never a conflict. + */ + uint8_t dummy[1] = { 0 }; + + res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, + TEE_FS_KM_SSK_SIZE, dummy, sizeof(dummy)); + if (res != TEE_SUCCESS) + return res; + } + + res = crypto_cipher_alloc_ctx(&ctx, TEE_FS_KM_ENC_FEK_ALG); + if (res != TEE_SUCCESS) + return res; + + res = crypto_cipher_init(ctx, mode, tsk, sizeof(tsk), NULL, 0, NULL, 0); + if (res != TEE_SUCCESS) + goto exit; + + res = crypto_cipher_update(ctx, mode, true, in_key, size, dst_key); + if (res != TEE_SUCCESS) + goto exit; + + crypto_cipher_final(ctx); + + memcpy(out_key, dst_key, sizeof(dst_key)); + +exit: + crypto_cipher_free_ctx(ctx); + memzero_explicit(tsk, sizeof(tsk)); + memzero_explicit(dst_key, sizeof(dst_key)); + + return res; +} + +static TEE_Result generate_fek(uint8_t *key, uint8_t len) +{ + return crypto_rng_read(key, len); +} + +static TEE_Result tee_fs_init_key_manager(void) +{ + TEE_Result res = TEE_SUCCESS; + + COMPILE_TIME_ASSERT(TEE_FS_KM_SSK_SIZE <= HUK_SUBKEY_MAX_LEN); + + res = huk_subkey_derive(HUK_SUBKEY_SSK, NULL, 0, + tee_fs_ssk.key, sizeof(tee_fs_ssk.key)); + if (res == TEE_SUCCESS) + tee_fs_ssk.is_init = 1; + else + memzero_explicit(&tee_fs_ssk, sizeof(tee_fs_ssk)); + + return res; +} + +TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *buf, size_t buf_size) +{ + TEE_Result res; + + if (buf_size != TEE_FS_KM_FEK_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + res = generate_fek(buf, TEE_FS_KM_FEK_SIZE); + if (res != TEE_SUCCESS) + return res; + + return tee_fs_fek_crypt(uuid, TEE_MODE_ENCRYPT, buf, + TEE_FS_KM_FEK_SIZE, buf); +} + +static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in, + size_t in_size) +{ + return tee_hash_createdigest(TEE_ALG_SHA256, in, in_size, + out, out_size); +} + +static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE], + const uint8_t in[TEE_AES_BLOCK_SIZE], + const uint8_t *key, size_t key_size) +{ + TEE_Result res; + void *ctx = NULL; + + res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_ECB_NOPAD); + if (res != TEE_SUCCESS) + return res; + + res = crypto_cipher_init(ctx, TEE_MODE_ENCRYPT, key, + key_size, NULL, 0, NULL, 0); + if (res != TEE_SUCCESS) + goto out; + + res = crypto_cipher_update(ctx, TEE_MODE_ENCRYPT, true, in, + TEE_AES_BLOCK_SIZE, out); + if (res != TEE_SUCCESS) + goto out; + + crypto_cipher_final(ctx); + res = TEE_SUCCESS; + +out: + crypto_cipher_free_ctx(ctx); + return res; +} + +static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE], + const uint8_t fek[TEE_FS_KM_FEK_SIZE], + uint16_t blk_idx) +{ + TEE_Result res; + uint8_t sha[TEE_SHA256_HASH_SIZE]; + uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, }; + + res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE); + if (res != TEE_SUCCESS) + return res; + + pad_blkid[0] = (blk_idx & 0xFF); + pad_blkid[1] = (blk_idx & 0xFF00) >> 8; + + res = aes_ecb(iv, pad_blkid, sha, 16); + + memzero_explicit(sha, sizeof(sha)); + return res; +} + +/* + * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV. + */ +TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out, + const uint8_t *in, size_t size, + uint16_t blk_idx, const uint8_t *encrypted_fek, + TEE_OperationMode mode) +{ + TEE_Result res; + uint8_t fek[TEE_FS_KM_FEK_SIZE]; + uint8_t iv[TEE_AES_BLOCK_SIZE]; + void *ctx; + + DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De", + blk_idx); + + /* Decrypt FEK */ + res = tee_fs_fek_crypt(uuid, TEE_MODE_DECRYPT, encrypted_fek, + TEE_FS_KM_FEK_SIZE, fek); + if (res != TEE_SUCCESS) + goto wipe; + + /* Compute initialization vector for this block */ + res = essiv(iv, fek, blk_idx); + if (res != TEE_SUCCESS) + goto wipe; + + /* Run AES CBC */ + res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_CBC_NOPAD); + if (res != TEE_SUCCESS) + goto wipe; + + res = crypto_cipher_init(ctx, mode, fek, sizeof(fek), NULL, + 0, iv, TEE_AES_BLOCK_SIZE); + if (res != TEE_SUCCESS) + goto exit; + res = crypto_cipher_update(ctx, mode, true, in, size, out); + if (res != TEE_SUCCESS) + goto exit; + + crypto_cipher_final(ctx); + +exit: + crypto_cipher_free_ctx(ctx); +wipe: + memzero_explicit(fek, sizeof(fek)); + memzero_explicit(iv, sizeof(iv)); + return res; +} + +service_init_late(tee_fs_init_key_manager); diff --git a/optee/optee_os/core/tee/tee_fs_rpc.c b/optee/optee_os/core/tee/tee_fs_rpc.c new file mode 100644 index 0000000..e0d54e1 --- /dev/null +++ b/optee/optee_os/core/tee/tee_fs_rpc.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct tee_fs_dir { + int nw_dir; + struct tee_fs_dirent d; +}; + +/* "/dirf.db" or "/" */ +static TEE_Result create_filename(void *buf, size_t blen, + const struct tee_fs_dirfile_fileh *dfh) +{ + char *file = buf; + size_t pos = 0; + size_t l; + + if (pos >= blen) + return TEE_ERROR_SHORT_BUFFER; + + file[pos] = '/'; + pos++; + if (pos >= blen) + return TEE_ERROR_SHORT_BUFFER; + + l = blen - pos; + return tee_fs_dirfile_fileh_to_fname(dfh, file + pos, &l); +} + +static TEE_Result operation_commit(struct tee_fs_rpc_operation *op) +{ + return thread_rpc_cmd(op->id, op->num_params, op->params); +} + +static TEE_Result operation_open_dfh(uint32_t id, unsigned int cmd, + const struct tee_fs_dirfile_fileh *dfh, + int *fd) +{ + struct tee_fs_rpc_operation op = { }; + struct mobj *mobj = NULL; + TEE_Result res = TEE_SUCCESS; + void *va = NULL; + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, + THREAD_SHM_TYPE_APPLICATION, + TEE_FS_NAME_MAX, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + res = create_filename(va, TEE_FS_NAME_MAX, dfh); + if (res != TEE_SUCCESS) + return res; + + op = (struct tee_fs_rpc_operation){ + .id = id, .num_params = 3, .params = { + [0] = THREAD_PARAM_VALUE(IN, cmd, 0, 0), + [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX), + [2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0), + } }; + + res = operation_commit(&op); + if (res == TEE_SUCCESS) + *fd = op.params[2].u.value.a; + + return res; +} + + + +TEE_Result tee_fs_rpc_open_dfh(uint32_t id, + const struct tee_fs_dirfile_fileh *dfh, int *fd) +{ + return operation_open_dfh(id, OPTEE_RPC_FS_OPEN, dfh, fd); +} + +TEE_Result tee_fs_rpc_create_dfh(uint32_t id, + const struct tee_fs_dirfile_fileh *dfh, + int *fd) +{ + return operation_open_dfh(id, OPTEE_RPC_FS_CREATE, dfh, fd); +} + +TEE_Result tee_fs_rpc_close(uint32_t id, int fd) +{ + struct tee_fs_rpc_operation op = { + .id = id, .num_params = 1, .params = { + [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_CLOSE, fd, 0), + }, + }; + + return operation_commit(&op); +} + +TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op, + uint32_t id, int fd, tee_fs_off_t offset, + size_t data_len, void **out_data) +{ + struct mobj *mobj; + uint8_t *va; + + if (offset < 0) + return TEE_ERROR_BAD_PARAMETERS; + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, + THREAD_SHM_TYPE_APPLICATION, + data_len, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + *op = (struct tee_fs_rpc_operation){ + .id = id, .num_params = 2, .params = { + [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_READ, fd, + offset), + [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, data_len), + }, + }; + + *out_data = va; + + return TEE_SUCCESS; +} + +TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op, + size_t *data_len) +{ + TEE_Result res = operation_commit(op); + + if (res == TEE_SUCCESS) + *data_len = op->params[1].u.memref.size; + return res; +} + +TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op, + uint32_t id, int fd, tee_fs_off_t offset, + size_t data_len, void **data) +{ + struct mobj *mobj; + uint8_t *va; + + if (offset < 0) + return TEE_ERROR_BAD_PARAMETERS; + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, + THREAD_SHM_TYPE_APPLICATION, + data_len, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + *op = (struct tee_fs_rpc_operation){ + .id = id, .num_params = 2, .params = { + [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_WRITE, fd, + offset), + [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, data_len), + }, + }; + + *data = va; + + return TEE_SUCCESS; +} + +TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op) +{ + return operation_commit(op); +} + +TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len) +{ + struct tee_fs_rpc_operation op = { + .id = id, .num_params = 1, .params = { + [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_TRUNCATE, fd, + len), + } + }; + + return operation_commit(&op); +} + +TEE_Result tee_fs_rpc_remove_dfh(uint32_t id, + const struct tee_fs_dirfile_fileh *dfh) +{ + struct tee_fs_rpc_operation op = { }; + TEE_Result res = TEE_SUCCESS; + struct mobj *mobj = NULL; + void *va = NULL; + + va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, + THREAD_SHM_TYPE_APPLICATION, + TEE_FS_NAME_MAX, &mobj); + if (!va) + return TEE_ERROR_OUT_OF_MEMORY; + + + res = create_filename(va, TEE_FS_NAME_MAX, dfh); + if (res != TEE_SUCCESS) + return res; + + op = (struct tee_fs_rpc_operation){ + .id = id, .num_params = 2, .params = { + [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_REMOVE, 0, 0), + [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX), + } + }; + + return operation_commit(&op); +} diff --git a/optee/optee_os/core/tee/tee_nvme_rpmb_fs.c b/optee/optee_os/core/tee/tee_nvme_rpmb_fs.c new file mode 100644 index 0000000..7300745 --- /dev/null +++ b/optee/optee_os/core/tee/tee_nvme_rpmb_fs.c @@ -0,0 +1,3023 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#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 +#include + +#define NVME_RPMB_STORAGE_START_ADDRESS 0 +#define NVME_RPMB_FS_FAT_START_ADDRESS 512 + +#define NVME_RPMB_FS_MAGIC 0x52504D42 +#define NVME_FS_VERSION 2 + +#define FILE_IS_ACTIVE (1u << 0) +#define FILE_IS_LAST_ENTRY (1u << 1) + +#define TEE_NVME_RPMB_FS_FILENAME_LENGTH 224 + +#define TMP_BLOCK_SIZE 4096U +#define NVME_RPMB_MAX_RETRIES 10 +#define NVME_RPMB_DEFAULT_TARGET 0x0 + +/** + * Utilized when caching is enabled, i.e., when CFG_NVME_RPMB_FS_CACHE_ENTRIES > 0. + * Cache size + the number of entries that are repeatedly read in and buffered + * once the cache is full. + */ +#define NVME_RPMB_BUF_MAX_ENTRIES (CFG_NVME_RPMB_FS_CACHE_ENTRIES + \ + CFG_NVME_RPMB_FS_RD_ENTRIES) + +/** + * FS parameters: Information often used by internal functions. + * fat_start_address will be set by nvme_rpmb_fs_setup(). + * nvme_rpmb_fs_parameters can be read by any other function. + */ +struct nvme_rpmb_fs_parameters { + uint32_t fat_start_address; + uint32_t max_rpmb_address; +}; + +/** + * File entry for a single file in a NVME_RPMB_FS partition. + */ +struct nvme_rpmb_fat_entry { + uint32_t start_address; + uint32_t data_size; + uint32_t flags; + uint32_t write_counter; + uint8_t fek[TEE_FS_KM_FEK_SIZE]; + char filename[TEE_NVME_RPMB_FS_FILENAME_LENGTH]; +}; + +/** + * Structure that describes buffered/cached FAT FS entries in nvme_rpmb storage. + * This structure is used in functions traversing the FAT FS. + */ +struct nvme_rpmb_fat_entry_dir { + /* + * Buffer storing the FAT FS entries read in from NVME RPMB storage. It + * includes the optional cache entries (CFG_NVME_RPMB_FS_CACHE_ENTRIES) + * and entries temporary read for current FAT FS traversal + * (CFG_NVME_RPMB_FS_RD_ENTRIES) when not found from cached entries. + */ + struct nvme_rpmb_fat_entry *rpmb_fat_entry_buf; + /* Current index of FAT FS entry to read from buffer. */ + uint32_t idx_curr; + /* Total number of FAT FS entries in buffer. */ + uint32_t num_buffered; + /* Total number of FAT FS entries read during traversal. */ + uint32_t num_total_read; + /* Indicates that last FAT FS entry was read. */ + bool last_reached; +}; + +/** + * FAT entry context with reference to a FAT entry and its + * location in RPMB. + */ +struct nvme_rpmb_file_handle { + struct nvme_rpmb_fat_entry fat_entry; + const TEE_UUID *uuid; + char filename[TEE_NVME_RPMB_FS_FILENAME_LENGTH]; + /* Address for current entry in RPMB */ + uint32_t rpmb_fat_address; +}; + +/** + * NVME_RPMB_FS partition data + */ +struct nvme_rpmb_fs_partition { + uint32_t nvme_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]; +}; + +/** + * A node in a list of directory entries. + */ +struct tee_nvme_rpmb_fs_dirent { + struct tee_fs_dirent entry; + SIMPLEQ_ENTRY(tee_nvme_rpmb_fs_dirent) link; +}; + +/** + * The RPMB directory representation. It contains a queue of + * RPMB directory entries: 'next'. + * The current pointer points to the last directory entry + * returned by readdir(). + */ +struct tee_fs_dir { + struct tee_nvme_rpmb_fs_dirent *current; + /* */ + SIMPLEQ_HEAD(next_head, tee_nvme_rpmb_fs_dirent) next; +}; + +static struct nvme_rpmb_fs_parameters *fs_par; +static struct nvme_rpmb_fat_entry_dir *fat_entry_dir; + +/* + * Lower interface to RPMB device + */ + +#define NVME_RPMB_FRAME_SIZE 256 +#define NVME_RPMB_BLOCK_SIZE 512 +#define NVME_RPMB_BLOCK_SIZE_SHIFT 9 +#define NVME_RPMB_STUFF_DATA_SIZE 191 +#define NVME_RPMB_KEY_MAC_SIZE 32 +#define NVME_RPMB_NONCE_SIZE 16 +#define NVME_RPMB_SN_SIZE 20 +#define NVME_RPMB_FRAME_BLOCK_SIZE(block_count) \ + (NVME_RPMB_FRAME_SIZE + (block_count * NVME_RPMB_BLOCK_SIZE)) + +#define NVME_RPMB_TARGET_OFFSET (NVME_RPMB_STUFF_DATA_SIZE + NVME_RPMB_KEY_MAC_SIZE) +#define NVME_RPMB_MAC_PROTECT_DATA_SIZE (NVME_RPMB_FRAME_SIZE - NVME_RPMB_TARGET_OFFSET) + +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM 0x0001 +#define NVME_RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ 0x0002 +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE 0x0003 +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_READ 0x0004 +#define NVME_RPMB_MSG_TYPE_REQ_RESULT_READ 0x0005 +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_DCB_WRITE 0x0006 +#define NVME_RPMB_MSG_TYPE_REQ_AUTH_DCB_READ 0x0007 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM 0x0100 +#define NVME_RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ 0x0200 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE 0x0300 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_DATA_READ 0x0400 +#define NVME_RPMB_MSG_TYPE_RESP_RESULT_READ 0x0500 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_DCB_WRITE 0x0600 +#define NVME_RPMB_MSG_TYPE_RESP_AUTH_DCB_READ 0x0700 + +#define NVME_RPMB_RESULT_OK 0x00 +#define NVME_RPMB_RESULT_GENERAL_FAILURE 0x01 +#define NVME_RPMB_RESULT_AUTH_FAILURE 0x02 +#define NVME_RPMB_RESULT_COUNTER_FAILURE 0x03 +#define NVME_RPMB_RESULT_ADDRESS_FAILURE 0x04 +#define NVME_RPMB_RESULT_WRITE_FAILURE 0x05 +#define NVME_RPMB_RESULT_READ_FAILURE 0x06 +#define NVME_RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED 0x07 +#define NVME_RPMB_RESULT_INVALID_DEV_CONFIG_BLOCK 0x08 +#define NVME_RPMB_RESULT_MASK 0x3F +#define NVME_RPMB_RESULT_WR_CNT_EXPIRED 0x80 + +/* RPMB internal commands */ +#define NVME_RPMB_CMD_DATA_REQ 0x00 +#define NVME_RPMB_CMD_GET_RPMBS_INFO 0x01 + +#define RPMB_SIZE_SINGLE (128 * 1024) + +#define NVME_RPMB_CMD_GET_DEV_INFO_RET_OK 0x00 +#define NVME_RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01 + +struct nvme_rpmb_data_frame { + uint8_t stuff_bytes[NVME_RPMB_STUFF_DATA_SIZE]; + uint8_t key_mac[NVME_RPMB_KEY_MAC_SIZE]; + uint8_t target; + uint8_t nonce[NVME_RPMB_NONCE_SIZE]; + uint32_t write_counter; + uint32_t address; + uint32_t block_count; + uint16_t op_result; + uint16_t msg_type; + uint8_t data[0]; +}; + +struct nvme_rpmb_req { + uint16_t cmd; + uint16_t dev_id; +}; + +#define TEE_NVME_RPMB_REQ_DATA(req) \ + ((void *)((struct nvme_rpmb_req *)(req) + 1)) + +struct nvme_rpmb_raw_data { + uint8_t *data; + uint16_t msg_type; + uint16_t *op_result; + uint32_t *block_count; + uint32_t *blk_idx; + uint32_t *write_counter; + uint8_t *nonce; + uint8_t *target; + uint8_t *key_mac; + /* data length to read or write */ + uint32_t len; + /* Byte address offset in the first block involved */ + uint16_t byte_offset; +}; + +/* RPMB support info */ +union nvme_rpmbs_info { + struct { + /* number of RPMB targets the controller supports */ + unsigned int num_targets:3; + /* authentication function, 0 means HMAC-SHA256 */ + unsigned int auth_method:3; + unsigned int reserved:10; + /* total number of 128K units in each rpmb supported */ + unsigned int total_size:8; + /* maximum number of 512 byte per RPMB access */ + unsigned int access_size:8; + }; + unsigned int rpmbs; +}; + +struct nvme_dev_info { + union nvme_rpmbs_info rpmbs_info; + char sn[NVME_RPMB_SN_SIZE + 1]; +}; + +/* + * Struct for NVMe rpmb context data. + * + * @targets Number of RPMB targets the controller supports. + * @auth_method The authentication method to access RPMB. + * @key RPMB key. + * @wr_cnt Current write counter. + * @max_blk_idx The highest block index supported by current device. + * @access_size Max number of 512B units of data per RPMB access. + * @dev_id Device ID of the NVMe 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. + * @rpmbs_info_synced Flag indicating if dev info has been retrieved from RPMB. + */ +struct tee_nvme_rpmb_ctx { + uint8_t targets; + uint8_t auth_method; + uint8_t key[NVME_RPMB_KEY_MAC_SIZE]; + uint32_t wr_cnt; + uint32_t max_blk_idx; + uint32_t access_size; + uint16_t dev_id; + char sn[NVME_RPMB_SN_SIZE + 1]; + bool wr_cnt_synced; + bool key_derived; + bool key_verified; + bool rpmbs_info_synced; +}; + +static struct tee_nvme_rpmb_ctx *rpmb_ctx; + +/* If set to true, don't try to access RPMB until rebooted */ +static bool rpmb_dead; + +/* + * Mutex to serialize the operations exported by this file. + * It protects rpmb_ctx and prevents overlapping operations on NVMe devices with + * different IDs. + */ +static struct mutex nvme_rpmb_mutex = MUTEX_INITIALIZER; + +#ifdef CFG_NVME_RPMB_TESTKEY + +static const uint8_t nvme_rpmb_test_key[NVME_RPMB_KEY_MAC_SIZE] = { + 0x99, 0x8a, 0xe2, 0x29, 0x0f, 0x0c, 0x6a, 0x2c, + 0xe3, 0x1c, 0xdb, 0xf7, 0x76, 0xd8, 0x1e, 0x77, + 0x9a, 0xe3, 0x2f, 0x46, 0xef, 0x4d, 0xcf, 0xa2, + 0xfc, 0xa6, 0xaa, 0x3b, 0x45, 0xfc, 0xbc, 0x8b +}; + +static TEE_Result tee_nvme_rpmb_key_gen(uint16_t dev_id __unused, + uint8_t *key, uint32_t len) +{ + TEE_Result res = TEE_SUCCESS; + + if (!key || NVME_RPMB_KEY_MAC_SIZE != len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + DMSG("NVME-RPMB: Using test key"); + memcpy(key, nvme_rpmb_test_key, NVME_RPMB_KEY_MAC_SIZE); + +out: + return res; +} + +#else /* !CFG_NVME_RPMB_TESTKEY */ + +#ifdef CFG_RPMB_KEY_HAS_PROVISIONED +static TEE_Result tee_nvme_rpmb_key_gen(uint16_t dev_id __unused, + uint8_t *key, uint32_t len) +{ + if (!key || NVME_RPMB_KEY_MAC_SIZE != len) + return TEE_ERROR_BAD_PARAMETERS; + + IMSG("NVME-RPMB: Using pre-generated key"); + return tee_otp_get_rpmb_key(key, len); +} +#else +static TEE_Result tee_nvme_rpmb_key_gen(uint16_t dev_id __unused, + uint8_t *key, uint32_t len) +{ + + if (!key || NVME_RPMB_KEY_MAC_SIZE != len) + return TEE_ERROR_BAD_PARAMETERS; + + IMSG("NVME-RPMB: Using generated key"); + + return huk_subkey_derive(HUK_SUBKEY_RPMB, NULL, 0, + key, len); +} +#endif /* CFG_RPMB_KEY_HAS_PROVISIONED */ + +#endif /* !CFG_NVME_RPMB_TESTKEY */ + +static TEE_Result tee_nvme_rpmb_mac_calc(uint8_t *mac, uint32_t macsize, + uint8_t *key, uint32_t keysize, + struct nvme_rpmb_data_frame *datafrm) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *ctx = NULL; + + if (!mac || !key || !datafrm) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); + if (res) + return res; + + res = crypto_mac_init(ctx, key, keysize); + if (res != TEE_SUCCESS) + goto func_exit; + + res = crypto_mac_update(ctx, &datafrm->target, + NVME_RPMB_MAC_PROTECT_DATA_SIZE + + datafrm->block_count * NVME_RPMB_BLOCK_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + res = crypto_mac_final(ctx, mac, macsize); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + crypto_mac_free_ctx(ctx); + return res; +} + +struct tee_nvme_rpmb_mem { + struct mobj *phreq_mobj; + struct mobj *phresp_mobj; + size_t req_size; + size_t resp_size; +}; + +static void tee_nvme_rpmb_free(struct tee_nvme_rpmb_mem *mem) +{ + if (!mem) + return; + + if (mem->phreq_mobj) { + thread_rpc_free_payload(mem->phreq_mobj); + mem->phreq_mobj = NULL; + } + if (mem->phresp_mobj) { + thread_rpc_free_payload(mem->phresp_mobj); + mem->phresp_mobj = NULL; + } +} + + +static TEE_Result tee_nvme_rpmb_alloc(size_t req_size, size_t resp_size, + struct tee_nvme_rpmb_mem *mem, void **req, void **resp) +{ + TEE_Result res = TEE_SUCCESS; + size_t req_s = ROUNDUP(req_size, sizeof(uint32_t)); + size_t resp_s = ROUNDUP(resp_size, sizeof(uint32_t)); + + if (!mem) + return TEE_ERROR_BAD_PARAMETERS; + + memset(mem, 0, sizeof(*mem)); + + mem->phreq_mobj = thread_rpc_alloc_payload(req_s); + mem->phresp_mobj = thread_rpc_alloc_payload(resp_s); + + if (!mem->phreq_mobj || !mem->phresp_mobj) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + *req = mobj_get_va(mem->phreq_mobj, 0, req_s); + *resp = mobj_get_va(mem->phresp_mobj, 0, resp_s); + if (!*req || !*resp) { + res = TEE_ERROR_GENERIC; + goto out; + } + + mem->req_size = req_size; + mem->resp_size = resp_size; + +out: + if (res != TEE_SUCCESS) + tee_nvme_rpmb_free(mem); + return res; +} + +static TEE_Result tee_nvme_rpmb_invoke(struct tee_nvme_rpmb_mem *mem) +{ + struct thread_param params[2] = { + [0] = THREAD_PARAM_MEMREF(IN, mem->phreq_mobj, 0, + mem->req_size), + [1] = THREAD_PARAM_MEMREF(OUT, mem->phresp_mobj, 0, + mem->resp_size), + }; + + return thread_rpc_cmd(OPTEE_RPC_CMD_NVME_RPMB, 2, params); +} + +static bool is_zero(const uint8_t *buf, size_t size) +{ + size_t i; + + for (i = 0; i < size; i++) + if (buf[i]) + return false; + return true; +} + +static TEE_Result decrypt(uint8_t *out, const uint8_t *in, + size_t size, size_t offset, + uint32_t blk_idx __maybe_unused, const uint8_t *fek, + const TEE_UUID *uuid) +{ + uint8_t *tmp; + TEE_Result res = TEE_SUCCESS; + + if (size + offset < size) + panic("invalid size or offset"); + + if (!fek) { + /* Block is not encrypted (not a file data block) */ + memcpy(out, in + offset, size); + } else if (is_zero(fek, TEE_FS_KM_FEK_SIZE)) { + /* The file was created with encryption disabled */ + return TEE_ERROR_SECURITY; + } else { + /* Block is encrypted */ + if (size < NVME_RPMB_BLOCK_SIZE) { + tmp = malloc(NVME_RPMB_BLOCK_SIZE); + if (!tmp) + return TEE_ERROR_OUT_OF_MEMORY; + + res = tee_fs_crypt_block(uuid, tmp, in, + NVME_RPMB_BLOCK_SIZE, blk_idx, + fek, TEE_MODE_DECRYPT); + if (res == TEE_SUCCESS) + memcpy(out, tmp + offset, size); + free(tmp); + } else { + res = tee_fs_crypt_block(uuid, out, in, + NVME_RPMB_BLOCK_SIZE, blk_idx, + fek, TEE_MODE_DECRYPT); + } + } + + return res; +} + +static TEE_Result tee_nvme_rpmb_req_pack(struct nvme_rpmb_req *req, + struct nvme_rpmb_raw_data *rawdata, + uint16_t dev_id, + const uint8_t *fek, const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t i; + struct nvme_rpmb_data_frame *datafrm = TEE_NVME_RPMB_REQ_DATA(req); + + if (!req || !rawdata) + return TEE_ERROR_BAD_PARAMETERS; + + /* Make sure write block count is not bigger than max access size */ + if ((rawdata->msg_type == NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE) && + (*rawdata->block_count > rpmb_ctx->access_size)) { + EMSG("wr_blk_cnt(%d) is bigger than access_size(%d)", + *rawdata->block_count, rpmb_ctx->access_size); + return TEE_ERROR_GENERIC; + } + + req->cmd = NVME_RPMB_CMD_DATA_REQ; + req->dev_id = dev_id; + + datafrm->msg_type = rawdata->msg_type; + + if (rawdata->target) + datafrm->target = *rawdata->target; + else + datafrm->target = NVME_RPMB_DEFAULT_TARGET; + + if (rawdata->block_count) + datafrm->block_count = *rawdata->block_count; + + if (rawdata->blk_idx) { + /* Check the block index is within range. */ + if ((*rawdata->blk_idx + *rawdata->block_count - 1) > rpmb_ctx->max_blk_idx) { + res = TEE_ERROR_GENERIC; + goto func_exit; + } + datafrm->address = *rawdata->blk_idx; + } + + if (rawdata->write_counter) + datafrm->write_counter = *rawdata->write_counter; + + if (rawdata->nonce) + memcpy(datafrm->nonce, rawdata->nonce, NVME_RPMB_NONCE_SIZE); + + if (rawdata->data) { + if (fek) { + for (i = 0; i < *rawdata->block_count; i++) { + res = tee_fs_crypt_block(uuid, + datafrm->data + (i * NVME_RPMB_BLOCK_SIZE), + rawdata->data + (i * NVME_RPMB_BLOCK_SIZE), + NVME_RPMB_BLOCK_SIZE, + *rawdata->blk_idx + i, fek, TEE_MODE_ENCRYPT); + if (res != TEE_SUCCESS) + goto func_exit; + } + } else { + memcpy(datafrm->data, rawdata->data, + *rawdata->block_count * NVME_RPMB_BLOCK_SIZE); + } + } + + if (rawdata->key_mac) { + if (rawdata->msg_type == NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE) { + res = tee_nvme_rpmb_mac_calc(rawdata->key_mac, + NVME_RPMB_KEY_MAC_SIZE, rpmb_ctx->key, + NVME_RPMB_KEY_MAC_SIZE, datafrm); + if (res != TEE_SUCCESS) + goto func_exit; + } + memcpy(datafrm->key_mac, rawdata->key_mac, NVME_RPMB_KEY_MAC_SIZE); + } + + if (IS_ENABLED(CFG_NVME_RPMB_FS_DEBUG_DATA)) { + DMSG("Dumping data frame"); + DHEXDUMP((uint8_t *)datafrm + NVME_RPMB_STUFF_DATA_SIZE, + NVME_RPMB_FRAME_SIZE - NVME_RPMB_STUFF_DATA_SIZE); + } + + res = TEE_SUCCESS; + +func_exit: + return res; +} + +static TEE_Result tee_nvme_rpmb_data_cpy_mac_calc(struct nvme_rpmb_data_frame *datafrm, + struct nvme_rpmb_raw_data *rawdata, + const uint8_t *fek, const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t i; + uint16_t offset; + uint32_t size; + uint8_t *data; + struct nvme_rpmb_data_frame *localfrm; + + if (!datafrm || !rawdata) + return TEE_ERROR_BAD_PARAMETERS; + + data = rawdata->data; + + /* + * To avoid TOCTOU attack, we copy the RPMB frame from non-secure memory to + * local secure memory. + */ + localfrm = malloc(NVME_RPMB_FRAME_BLOCK_SIZE(datafrm->block_count)); + if (!localfrm) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(localfrm, datafrm, NVME_RPMB_FRAME_BLOCK_SIZE(datafrm->block_count)); + + res = tee_nvme_rpmb_mac_calc(rawdata->key_mac, + NVME_RPMB_KEY_MAC_SIZE, rpmb_ctx->key, + NVME_RPMB_KEY_MAC_SIZE, localfrm); + if (res) + goto func_exit; + + for (i = 0; i < localfrm->block_count; i++) { + if (localfrm->block_count == 1) { /* Only one block */ + offset = rawdata->byte_offset; + size = rawdata->len; + } else if (i == 0) { /* more than one block */ + /* First block */ + offset = rawdata->byte_offset; + size = NVME_RPMB_BLOCK_SIZE - offset; + } else if (i == localfrm->block_count - 1) { + /* Last block */ + offset = 0; + size = (rawdata->len + rawdata->byte_offset) % NVME_RPMB_BLOCK_SIZE; + if (size == 0) + size = NVME_RPMB_BLOCK_SIZE; + } else { + /* Middle blocks */ + offset = 0; + size = NVME_RPMB_BLOCK_SIZE; + } + + res = decrypt(data, localfrm->data + (i * NVME_RPMB_BLOCK_SIZE), + size, offset, localfrm->address + i, fek, uuid); + if (res) + goto func_exit; + data += size; + } + +func_exit: + free(localfrm); + return res; +} + +static TEE_Result tee_nvme_rpmb_resp_unpack_verify(struct nvme_rpmb_data_frame *datafrm, + struct nvme_rpmb_raw_data *rawdata, + const uint8_t *fek, + const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint16_t msg_type; + uint32_t wr_cnt; + uint32_t blk_idx; + uint8_t op_result; + + if (!datafrm || !rawdata) + return TEE_ERROR_BAD_PARAMETERS; + + if (IS_ENABLED(CFG_NVME_RPMB_FS_DEBUG_DATA)) { + DMSG("Dumping data frame"); + DHEXDUMP((uint8_t *)&datafrm + NVME_RPMB_STUFF_DATA_SIZE, + NVME_RPMB_FRAME_SIZE - NVME_RPMB_STUFF_DATA_SIZE); + } + + /* Handle operation result and translate to TEEC error code. */ + op_result = (datafrm->op_result & 0xff) & NVME_RPMB_RESULT_MASK; + if (op_result == NVME_RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED) + return TEE_ERROR_ITEM_NOT_FOUND; + if (op_result != NVME_RPMB_RESULT_OK) + return TEE_ERROR_GENERIC; + + /* Check the response target. */ + if (datafrm->target != *rawdata->target) { + EMSG("Unexpected target (0x%02x != 0x%02x)", datafrm->target, *rawdata->target); + return TEE_ERROR_GENERIC; + } + + /* Check the response msg_type. */ + msg_type = datafrm->msg_type; + if (msg_type != rawdata->msg_type) { + EMSG("Unexpected msg_type (0x%04x != 0x%04x)", msg_type, rawdata->msg_type); + return TEE_ERROR_GENERIC; + } + + if (rawdata->blk_idx) { + blk_idx = datafrm->address; + if (blk_idx != *rawdata->blk_idx) { + EMSG("Unexpected block index"); + return TEE_ERROR_GENERIC; + } + } + + if (rawdata->write_counter) { + wr_cnt = *rawdata->write_counter; + *rawdata->write_counter = datafrm->write_counter; + if (msg_type == NVME_RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE) { + /* Verify the write counter is incremented by 1 */ + if (*rawdata->write_counter != wr_cnt + 1) { + EMSG("Counter mismatched (0x%04x/0x%04x)", + *rawdata->write_counter, wr_cnt + 1); + return TEE_ERROR_SECURITY; + } + rpmb_ctx->wr_cnt++; + } + } + + if (rawdata->nonce) { + if (buf_compare_ct(rawdata->nonce, datafrm->nonce, + NVME_RPMB_NONCE_SIZE) != 0) { + EMSG("Nonce mismatched"); + return TEE_ERROR_SECURITY; + } + } + + if (rawdata->key_mac) { + if (msg_type == NVME_RPMB_MSG_TYPE_RESP_AUTH_DATA_READ) { + if (!rawdata->data) + return TEE_ERROR_GENERIC; + + res = tee_nvme_rpmb_data_cpy_mac_calc(datafrm, rawdata, fek, uuid); + + if (res != TEE_SUCCESS) { + EMSG("Calc MAC or decrypt data failed wit res = 0x%08x", res); + return res; + } + } else { + res = tee_nvme_rpmb_mac_calc(rawdata->key_mac, + NVME_RPMB_KEY_MAC_SIZE, + rpmb_ctx->key, + NVME_RPMB_KEY_MAC_SIZE, + datafrm); + + if (res != TEE_SUCCESS) { + EMSG("Calculate MAC failed with res = 0x%08x", res); + return res; + } + } + + if (consttime_memcmp(rawdata->key_mac,datafrm->key_mac, + NVME_RPMB_KEY_MAC_SIZE) != 0) { + EMSG("MAC mismatched:"); + if (IS_ENABLED(CFG_NVME_RPMB_FS_DEBUG_DATA)) + DHEXDUMP(rawdata->key_mac, NVME_RPMB_KEY_MAC_SIZE); + + return TEE_ERROR_SECURITY; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result tee_nvme_rpmb_get_rpmb_dev_info(uint16_t dev_id, + struct nvme_dev_info *dev_info) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_nvme_rpmb_mem mem; + struct nvme_rpmb_req *req = NULL; + uint8_t *resp = NULL; + uint32_t req_size; + uint32_t resp_size; + + if (!dev_info) + return TEE_ERROR_BAD_PARAMETERS; + + req_size = sizeof(struct nvme_rpmb_req); + resp_size = sizeof(struct nvme_dev_info); + res = tee_nvme_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + req->cmd = NVME_RPMB_CMD_GET_RPMBS_INFO; + req->dev_id = dev_id; + + res = tee_nvme_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + memcpy((uint8_t *)dev_info, resp, sizeof(struct nvme_dev_info)); + + if (IS_ENABLED(CFG_NVME_RPMB_FS_DEBUG_DATA)) { + DMSG("Dumping dev_info:"); + DHEXDUMP((uint8_t *)dev_info, sizeof(struct nvme_dev_info)); + } + + res = TEE_SUCCESS; + +func_exit: + tee_nvme_rpmb_free(&mem); + return res; +} + +static TEE_Result tee_nvme_rpmb_init_read_wr_cnt(uint16_t dev_id, uint8_t target, + uint32_t *wr_cnt, uint16_t *op_result) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_nvme_rpmb_mem mem; + uint16_t msg_type; + uint8_t nonce[NVME_RPMB_NONCE_SIZE]; + uint8_t hmac[NVME_RPMB_KEY_MAC_SIZE]; + struct nvme_rpmb_req *req = NULL; + struct nvme_rpmb_data_frame *resp = NULL; + struct nvme_rpmb_raw_data rawdata; + uint32_t req_size; + uint32_t resp_size; + + if (!wr_cnt) + return TEE_ERROR_BAD_PARAMETERS; + + req_size = sizeof(struct nvme_rpmb_req) + NVME_RPMB_FRAME_SIZE; + resp_size = NVME_RPMB_FRAME_SIZE; + res = tee_nvme_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + res = crypto_rng_read(nonce, NVME_RPMB_NONCE_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = NVME_RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ; + + memset(&rawdata, 0x00, sizeof(struct nvme_rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.target = ⌖ + rawdata.nonce = nonce; + + res = tee_nvme_rpmb_req_pack(req, &rawdata, dev_id, NULL, NULL); + if (res != TEE_SUCCESS) + goto func_exit; + + res = tee_nvme_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = NVME_RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ; + + memset(&rawdata, 0x00, sizeof(struct nvme_rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.target = ⌖ + rawdata.op_result = op_result; + rawdata.write_counter = wr_cnt; + rawdata.nonce = nonce; + rawdata.key_mac = hmac; + + res = tee_nvme_rpmb_resp_unpack_verify(resp, &rawdata, NULL, NULL); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + tee_nvme_rpmb_free(&mem); + return res; +} + +static TEE_Result tee_nvme_rpmb_verify_key_sync_counter(uint16_t dev_id, uint8_t target) +{ + uint16_t op_result = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + res = tee_nvme_rpmb_init_read_wr_cnt(dev_id, target, &rpmb_ctx->wr_cnt, + &op_result); + + if (res == TEE_SUCCESS) { + rpmb_ctx->key_verified = true; + rpmb_ctx->wr_cnt_synced = true; +#ifdef CFG_RPMB_KEY_HAS_PROVISIONED + } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { + res = TEE_ERROR_BAD_STATE; + EMSG("No key is provisioned"); +#endif + } else + EMSG("Verify key returning 0x%x", res); + return res; +} + +#ifdef CFG_RPMB_WRITE_KEY +static TEE_Result tee_nvme_rpmb_write_key(uint16_t dev_id, uint8_t target) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_nvme_rpmb_mem mem = { 0 }; + uint16_t msg_type; + struct nvme_rpmb_req *req = NULL; + struct nvme_rpmb_data_frame *resp = NULL; + struct nvme_rpmb_raw_data rawdata; + uint32_t req_size; + uint32_t resp_size; + + req_size = sizeof(struct nvme_rpmb_req) + NVME_RPMB_FRAME_SIZE; + resp_size = NVME_RPMB_FRAME_SIZE; + res = tee_nvme_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = NVME_RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM; + + memset(&rawdata, 0x00, sizeof(struct nvme_rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.target = ⌖ + rawdata.key_mac = rpmb_ctx->key; + + res = tee_nvme_rpmb_req_pack(req, &rawdata, dev_id, NULL, NULL); + if (res != TEE_SUCCESS) + goto func_exit; + + res = tee_nvme_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = NVME_RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM; + + memset(&rawdata, 0x00, sizeof(struct nvme_rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.target = ⌖ + + res = tee_nvme_rpmb_resp_unpack_verify(resp, &rawdata, NULL, NULL); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + tee_nvme_rpmb_free(&mem); + return res; +} + +static TEE_Result tee_nvme_rpmb_write_and_verify_key(uint16_t dev_id, uint8_t target) +{ + TEE_Result res; + + if (!plat_rpmb_key_is_ready()) { + EMSG("RPMB INIT: platform indicates RPMB key is not ready"); + return TEE_ERROR_BAD_STATE; + } + + DMSG("RPMB INIT: Writing Key value:"); + DHEXDUMP(rpmb_ctx->key, NVME_RPMB_KEY_MAC_SIZE); + + res = tee_nvme_rpmb_write_key(dev_id, target); + if (res == TEE_SUCCESS) { + DMSG("RPMB INIT: Verifying Key"); + res = tee_nvme_rpmb_verify_key_sync_counter(dev_id, target); + } + return res; +} +#else +static TEE_Result tee_nvme_rpmb_write_and_verify_key(uint16_t dev_id __unused, + uint8_t target __unused) +{ + DMSG("RPMB INIT: CFG_RPMB_WRITE_KEY is not set"); + return TEE_ERROR_BAD_STATE; +} +#endif + +/* This function must never return TEE_SUCCESS if rpmb_ctx == NULL */ +static TEE_Result tee_nvme_rpmb_init(uint16_t dev_id) +{ + TEE_Result res = TEE_SUCCESS; + struct nvme_dev_info dev_info; + uint32_t nblocks = 0; + uint32_t total_size; + uint32_t access_size; + uint32_t auth_method; + uint32_t targets; + union nvme_rpmbs_info rpmbs_info; + + if (rpmb_dead) + return TEE_ERROR_COMMUNICATION; + + if (!rpmb_ctx) { + rpmb_ctx = calloc(1, sizeof(struct tee_nvme_rpmb_ctx)); + if (!rpmb_ctx) + return TEE_ERROR_OUT_OF_MEMORY; + } else if (rpmb_ctx->dev_id != dev_id) { + memset(rpmb_ctx, 0x00, sizeof(struct tee_nvme_rpmb_ctx)); + } + + rpmb_ctx->dev_id = dev_id; + + if (!rpmb_ctx->rpmbs_info_synced) { + DMSG("NVME-RPMB: Syncing rpmb supports information"); + + memset(&dev_info, 0, sizeof(struct nvme_dev_info)); + res = tee_nvme_rpmb_get_rpmb_dev_info(dev_id, &dev_info); + if (res != TEE_SUCCESS) + goto func_exit; + + rpmbs_info = dev_info.rpmbs_info; + total_size = (rpmbs_info.rpmbs & 0xff0000) >> 16; + access_size = (rpmbs_info.rpmbs & 0xff000000) >> 24; + auth_method = (rpmbs_info.rpmbs & 0x38) >> 3; + targets = rpmbs_info.rpmbs & 0x7; + + DMSG("NVME-RPMB: RPMB size is %d*128 KB", total_size + 1); + DMSG("NVME-RPMB: Reliable Write Sector Count is %d", access_size + 1); + DMSG("NVME-RPMB: RPMB auth method is %d, 0 means hmac-sha256", auth_method); + DMSG("NVME-RPMB: RPMB total targets %d", targets); + DMSG("NVME-RPMB: Device SN: %s", dev_info.sn); + + if (total_size == 0) { + res = TEE_ERROR_GENERIC; + goto func_exit; + } + + if (MUL_OVERFLOW(total_size + 1, + RPMB_SIZE_SINGLE / NVME_RPMB_BLOCK_SIZE, &nblocks) || + SUB_OVERFLOW(nblocks, 1, &rpmb_ctx->max_blk_idx)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto func_exit; + } + + rpmb_ctx->access_size = access_size + 1; + rpmb_ctx->targets = targets; + rpmb_ctx->auth_method = auth_method; + memcpy(rpmb_ctx->sn, dev_info.sn, NVME_RPMB_SN_SIZE); + + rpmb_ctx->rpmbs_info_synced = true; + } + + if (!rpmb_ctx->key_derived) { + DMSG("RPMB INIT: Deriving key"); + + res = tee_nvme_rpmb_key_gen(dev_id, rpmb_ctx->key, + NVME_RPMB_KEY_MAC_SIZE); + if (res != TEE_SUCCESS) { + EMSG("RPMB INIT: Deriving key failed with error 0x%x", + res); + 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) { + DMSG("RPMB INIT: Verifying Key"); + + res = tee_nvme_rpmb_verify_key_sync_counter(dev_id, + NVME_RPMB_DEFAULT_TARGET); + if (res == TEE_ERROR_ITEM_NOT_FOUND && + !rpmb_ctx->key_verified) { + /* + * Need to write the key here and verify it. + */ + DMSG("RPMB INIT: Auth key not yet written"); + res = tee_nvme_rpmb_write_and_verify_key(dev_id, + NVME_RPMB_DEFAULT_TARGET); + } else if (res != TEE_SUCCESS) { + EMSG("Verify key failed!"); + EMSG("Make sure key here matches device key"); + } + } + +func_exit: + return res; +} + +/* + * Read RPMB data in bytes. + * + * @dev_id Device ID of the NVMe device. + * @addr Byte address of data. + * @data Pointer to the data. + * @len Size of data in bytes. + * @fek Encrypted File Encryption Key or NULL. + */ +static TEE_Result tee_nvme_rpmb_read(uint16_t dev_id, uint8_t target, + uint32_t addr, uint8_t *data, uint32_t len, + const uint8_t *fek, const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_nvme_rpmb_mem mem = { 0 }; + uint16_t msg_type; + uint8_t nonce[NVME_RPMB_NONCE_SIZE]; + uint8_t hmac[NVME_RPMB_KEY_MAC_SIZE]; + struct nvme_rpmb_req *req = NULL; + struct nvme_rpmb_data_frame *resp = NULL; + struct nvme_rpmb_raw_data rawdata; + uint32_t req_size; + uint32_t resp_size; + uint32_t blk_idx; + uint32_t blk_cnt; + uint16_t byte_offset; + uint32_t chunk_blk_idx; + uint32_t chunk_blk_cnt; + uint32_t num_reads; + uint32_t i; + + if (!data || !len) + return TEE_ERROR_BAD_PARAMETERS; + + blk_idx = addr / NVME_RPMB_BLOCK_SIZE; + byte_offset = addr % NVME_RPMB_BLOCK_SIZE; + + if (len + byte_offset + NVME_RPMB_BLOCK_SIZE < NVME_RPMB_BLOCK_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + blk_cnt = ROUNDUP(len + byte_offset, NVME_RPMB_BLOCK_SIZE) / NVME_RPMB_BLOCK_SIZE; + num_reads = blk_cnt / rpmb_ctx->access_size; + if (blk_cnt % rpmb_ctx->access_size) + num_reads += 1; + chunk_blk_idx = blk_idx; + + res = tee_nvme_rpmb_init(dev_id); + if (res != TEE_SUCCESS) + return res; + + for (i = 0; i < num_reads; i++ ) { + if (num_reads == 1) { /* only one chunk */ + chunk_blk_cnt = blk_cnt; + } else if (i == num_reads - 1) { /* more than one chunk */ + /* last chunk */ + chunk_blk_cnt = blk_cnt % (rpmb_ctx->access_size); + if (chunk_blk_cnt == 0) + chunk_blk_cnt = rpmb_ctx->access_size; + } else { + /* other chunk */ + chunk_blk_cnt = rpmb_ctx->access_size; + } + req_size = sizeof(struct nvme_rpmb_req) + NVME_RPMB_FRAME_SIZE; + resp_size = NVME_RPMB_FRAME_BLOCK_SIZE(chunk_blk_cnt); + res = tee_nvme_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_READ; + res = crypto_rng_read(nonce, NVME_RPMB_NONCE_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + memset(&rawdata, 0x00, sizeof(struct nvme_rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.target = ⌖ + rawdata.nonce = nonce; + rawdata.blk_idx = &chunk_blk_idx; + rawdata.block_count = &chunk_blk_cnt; + res = tee_nvme_rpmb_req_pack(req, &rawdata, dev_id, NULL, NULL); + if (res != TEE_SUCCESS) + goto func_exit; + + DMSG("Read %u block%s at index %u", blk_cnt, ((blk_cnt > 1) ? "s" : ""), + blk_idx); + + res = tee_nvme_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + msg_type = NVME_RPMB_MSG_TYPE_RESP_AUTH_DATA_READ; + + memset(&rawdata, 0x00, sizeof(struct nvme_rpmb_raw_data)); + rawdata.msg_type = msg_type; + rawdata.block_count = &chunk_blk_cnt; + rawdata.target = ⌖ + rawdata.blk_idx = &chunk_blk_idx; + rawdata.nonce = nonce; + rawdata.key_mac = hmac; + rawdata.data = data; + + if (num_reads == 1) { /* only one chunk */ + rawdata.byte_offset = byte_offset; + rawdata.len = len; + } else if (i == 0) { /* more than one chunk */ + /* first chunk */ + rawdata.byte_offset = byte_offset; + rawdata.len = chunk_blk_cnt * NVME_RPMB_BLOCK_SIZE - byte_offset; + } else if (i == num_reads - 1) { + /* last chunk */ + rawdata.byte_offset = 0; + if ((len + byte_offset) % NVME_RPMB_BLOCK_SIZE == 0) + rawdata.len = chunk_blk_cnt * NVME_RPMB_BLOCK_SIZE; + else + rawdata.len = (chunk_blk_cnt - 1) * NVME_RPMB_BLOCK_SIZE + + (len + byte_offset) % NVME_RPMB_BLOCK_SIZE; + } else { + /* middle chunk */ + rawdata.byte_offset = 0; + rawdata.len = chunk_blk_cnt * NVME_RPMB_BLOCK_SIZE; + } + + res = tee_nvme_rpmb_resp_unpack_verify(resp, &rawdata, fek, uuid); + if (res != TEE_SUCCESS) + goto func_exit; + + data += rawdata.len; + chunk_blk_idx += chunk_blk_cnt; + tee_nvme_rpmb_free(&mem); + } + + res = TEE_SUCCESS; + +func_exit: + tee_nvme_rpmb_free(&mem); + return res; +} + +static TEE_Result write_req(uint16_t dev_id, uint8_t target, uint32_t blk_idx, + const void *data_blks, uint32_t blk_cnt, + const uint8_t *fek, const TEE_UUID *uuid, + struct tee_nvme_rpmb_mem *mem, void *req, void *resp) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t hmac[NVME_RPMB_KEY_MAC_SIZE] = { }; + uint32_t wr_cnt = rpmb_ctx->wr_cnt; + struct nvme_rpmb_raw_data rawdata = { }; + size_t retry_count = 0; + + assert(mem->req_size >= sizeof(struct nvme_rpmb_req) + + NVME_RPMB_FRAME_BLOCK_SIZE(blk_cnt)); + assert(mem->resp_size == NVME_RPMB_FRAME_SIZE); + + while (true) { + memset(req, 0, mem->req_size); + memset(resp, 0, mem->resp_size); + + memset(&rawdata, 0, sizeof(struct nvme_rpmb_raw_data)); + rawdata.msg_type = NVME_RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE; + rawdata.target = ⌖ + rawdata.block_count = &blk_cnt; + rawdata.blk_idx = &blk_idx; + rawdata.write_counter = &wr_cnt; + rawdata.key_mac = hmac; + rawdata.data = (uint8_t *)data_blks; + + res = tee_nvme_rpmb_req_pack(req, &rawdata, dev_id, fek, + uuid); + if (res) { + /* + * If we haven't tried to send a request yet we can + * allow a failure here since there's no chance of + * an intercepted request with a valid write + * counter. + */ + if (!retry_count) + return res; + + retry_count++; + if (retry_count >= NVME_RPMB_MAX_RETRIES) + goto out_of_retries; + + EMSG("Request pack failed, retrying %zu", retry_count); + continue; + } + + res = tee_nvme_rpmb_invoke(mem); + if (res != TEE_SUCCESS) { + retry_count++; + if (retry_count >= NVME_RPMB_MAX_RETRIES) + goto out_of_retries; + /* + * 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; + EMSG("Write invoke failed, retrying %zu", retry_count); + continue; + } + + memset(&rawdata, 0, sizeof(struct nvme_rpmb_raw_data)); + rawdata.msg_type = NVME_RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE; + rawdata.target = ⌖ + rawdata.block_count = &blk_cnt; + rawdata.blk_idx = &blk_idx; + rawdata.write_counter = &wr_cnt; + rawdata.key_mac = hmac; + + res = tee_nvme_rpmb_resp_unpack_verify(resp, &rawdata, NULL, NULL); + if (res != TEE_SUCCESS) { + retry_count++; + if (retry_count >= NVME_RPMB_MAX_RETRIES) + goto out_of_retries; + /* + * 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; + EMSG("Write resp unpack verify failed, retrying %zu", retry_count); + continue; + } + + return TEE_SUCCESS; + } + +out_of_retries: + rpmb_dead = true; + /* + * We're using this error code to cause an eventuall calling TA to + * panic since we don't know if the data to be written has been + * committed to storage or not. + */ + return TEE_ERROR_COMMUNICATION; +} + +static TEE_Result tee_nvme_rpmb_write_blk(uint16_t dev_id, uint8_t target, uint32_t blk_idx, + const uint8_t *data_blks, uint32_t blk_cnt, + const uint8_t *fek, const TEE_UUID *uuid) +{ + TEE_Result res; + struct tee_nvme_rpmb_mem mem; + struct nvme_rpmb_req *req = NULL; + struct nvme_rpmb_data_frame *resp = NULL; + uint32_t req_size; + uint32_t resp_size; + uint32_t nbr_writes; + uint32_t chunk_blk_cnt; + uint32_t chunk_blk_idx; + uint32_t i; + + DMSG("Write %u block%s at index %u", blk_cnt, ((blk_cnt > 1) ? "s" : ""), + blk_idx); + + if (!data_blks || !blk_cnt) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_nvme_rpmb_init(dev_id); + if (res != TEE_SUCCESS) + return res; + + /* Split data when block count is bigger than max access size. */ + if (blk_cnt < rpmb_ctx->access_size) + req_size = sizeof(struct nvme_rpmb_req) + + NVME_RPMB_FRAME_BLOCK_SIZE(blk_cnt); + else + req_size = sizeof(struct nvme_rpmb_req) + + NVME_RPMB_FRAME_BLOCK_SIZE(rpmb_ctx->access_size); + + resp_size = NVME_RPMB_FRAME_SIZE; + + res = tee_nvme_rpmb_alloc(req_size, resp_size, &mem, + (void *)&req, (void *)&resp); + if (res != TEE_SUCCESS) + return res; + + nbr_writes = blk_cnt / rpmb_ctx->access_size; + if (blk_cnt % rpmb_ctx->access_size > 0) + nbr_writes += 1; + + chunk_blk_cnt = rpmb_ctx->access_size; + chunk_blk_idx = blk_idx; + for (i = 0; i < nbr_writes; i++) { + size_t offs = i * rpmb_ctx->access_size * NVME_RPMB_BLOCK_SIZE; + /* To handle last chunk */ + if (i == nbr_writes - 1) + chunk_blk_cnt = blk_cnt - + rpmb_ctx->access_size * (nbr_writes - 1); + + res = write_req(dev_id, target, chunk_blk_idx, data_blks + offs, + chunk_blk_cnt, fek, uuid, &mem, req, resp); + if (res) + goto out; + + chunk_blk_idx += chunk_blk_cnt; + } + +out: + tee_nvme_rpmb_free(&mem); + return res; +} + +static bool tee_nvme_rpmb_write_is_atomic(uint16_t dev_id __unused, uint32_t addr, + uint32_t len) +{ + uint16_t byte_offset = addr % NVME_RPMB_BLOCK_SIZE; + uint32_t blk_cnt = ROUNDUP(len + byte_offset, + NVME_RPMB_BLOCK_SIZE) / NVME_RPMB_BLOCK_SIZE; + + return (blk_cnt <= rpmb_ctx->access_size); +} + +/* + * Write RPMB data in bytes. + * + * @dev_id Device ID of the NVMe device. + * @addr Byte address of data. + * @data Pointer to the data. + * @len Size of data in bytes. + * @fek Encrypted File Encryption Key or NULL. + */ +static TEE_Result tee_nvme_rpmb_write(uint16_t dev_id, uint8_t target, + uint32_t addr, const uint8_t *data, uint32_t len, + const uint8_t *fek, const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t *data_tmp = NULL; + uint32_t blk_idx; + uint32_t blk_cnt; + uint16_t byte_offset; + + blk_idx = addr / NVME_RPMB_BLOCK_SIZE; + byte_offset = addr % NVME_RPMB_BLOCK_SIZE; + + blk_cnt = + ROUNDUP(len + byte_offset, NVME_RPMB_BLOCK_SIZE) / NVME_RPMB_BLOCK_SIZE; + + if (byte_offset == 0 && (len % NVME_RPMB_BLOCK_SIZE) == 0) { + res = tee_nvme_rpmb_write_blk(dev_id, target, + blk_idx, data, + blk_cnt, fek, uuid); + if (res != TEE_SUCCESS) + goto func_exit; + } else { + data_tmp = calloc(blk_cnt, NVME_RPMB_BLOCK_SIZE); + if (!data_tmp) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto func_exit; + } + + /* Read the complete blocks */ + res = tee_nvme_rpmb_read(dev_id, target, + blk_idx * NVME_RPMB_BLOCK_SIZE, data_tmp, + blk_cnt * NVME_RPMB_BLOCK_SIZE, fek, uuid); + if (res != TEE_SUCCESS) + goto func_exit; + + /* Partial update of the data blocks */ + memcpy(data_tmp + byte_offset, data, len); + + res = tee_nvme_rpmb_write_blk(dev_id, target, + blk_idx, data_tmp, + blk_cnt, fek, uuid); + if (res != TEE_SUCCESS) + goto func_exit; + } + + res = TEE_SUCCESS; + +func_exit: + free(data_tmp); + return res; +} + +/* + * Read the RPMB write counter. + * + * @dev_id Device ID of the NVMe device. + * @counter Pointer to the counter. + */ +static TEE_Result tee_nvme_rpmb_get_write_counter(uint16_t dev_id, + uint32_t *counter) +{ + TEE_Result res = TEE_SUCCESS; + + if (!counter) + return TEE_ERROR_BAD_PARAMETERS; + + if (rpmb_dead) + return TEE_ERROR_COMMUNICATION; + + if (!rpmb_ctx || !rpmb_ctx->wr_cnt_synced) { + res = tee_nvme_rpmb_init(dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + } + + *counter = rpmb_ctx->wr_cnt; + +func_exit: + return res; +} + +/* + * Read the RPMB max block. + * + * @dev_id Device ID of the NVMe device. + * @counter Pointer to receive the max block. + */ +static TEE_Result tee_nvme_rpmb_get_max_block(uint16_t dev_id, uint32_t *max_block) +{ + TEE_Result res = TEE_SUCCESS; + + if (!max_block) + return TEE_ERROR_BAD_PARAMETERS; + + if (rpmb_dead) + return TEE_ERROR_COMMUNICATION; + + if (!rpmb_ctx || !rpmb_ctx->rpmbs_info_synced) { + res = tee_nvme_rpmb_init(dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + } + + *max_block = rpmb_ctx->max_blk_idx; + +func_exit: + return res; +} + +/* + * End of lower interface to RPMB device + */ + +static TEE_Result get_fat_start_address(uint32_t *addr); +static TEE_Result nvme_rpmb_fs_setup(void); + +/** + * fat_entry_dir_free: Free the FAT entry dir. + */ +static void fat_entry_dir_free(void) +{ + if (fat_entry_dir) { + free(fat_entry_dir->rpmb_fat_entry_buf); + free(fat_entry_dir); + fat_entry_dir = NULL; + } +} + +/** + * fat_entry_dir_init: Initialize the FAT FS entry buffer/cache + * This function must be called before reading FAT FS entries using the + * function fat_entry_dir_get_next. This initializes the buffer/cache with the + * first FAT FS entries. + */ +static TEE_Result fat_entry_dir_init(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct nvme_rpmb_fat_entry *fe = NULL; + uint32_t fat_address = 0; + uint32_t num_elems_read = 0; + + if (fat_entry_dir) + return TEE_SUCCESS; + + res = nvme_rpmb_fs_setup(); + if (res) + return res; + + res = get_fat_start_address(&fat_address); + if (res) + return res; + + fat_entry_dir = calloc(1, sizeof(struct nvme_rpmb_fat_entry_dir)); + if (!fat_entry_dir) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * If caching is enabled, read in up to the maximum cache size, but + * never more than the single read in size. Otherwise, read in as many + * entries fit into the temporary buffer. + */ + if (CFG_NVME_RPMB_FS_CACHE_ENTRIES) + num_elems_read = MIN(CFG_NVME_RPMB_FS_CACHE_ENTRIES, + CFG_NVME_RPMB_FS_RD_ENTRIES); + else + num_elems_read = CFG_NVME_RPMB_FS_RD_ENTRIES; + + /* + * Allocate memory for the FAT FS entries to read in. + */ + fe = calloc(num_elems_read, sizeof(struct nvme_rpmb_fat_entry)); + if (!fe) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + fat_address, (uint8_t *)fe, + num_elems_read * sizeof(*fe), NULL, NULL); + if (res) + goto out; + + fat_entry_dir->rpmb_fat_entry_buf = fe; + + /* + * We use this variable when getting next entries from the buffer/cache + * to see whether we have to read in more entries from storage. + */ + fat_entry_dir->num_buffered = num_elems_read; + + return TEE_SUCCESS; +out: + fat_entry_dir_free(); + free(fe); + return res; +} + +/** + * fat_entry_dir_deinit: If caching is enabled, free the temporary buffer for + * FAT FS entries in case the cache was too small. Keep the elements in the + * cache. Reset the counter variables to start the next traversal from fresh + * from the first cached entry. If caching is disabled, just free the + * temporary buffer by calling fat_entry_dir_free and return. + */ +static void fat_entry_dir_deinit(void) +{ + struct nvme_rpmb_fat_entry *fe = NULL; + + if (!fat_entry_dir) + return; + + if (!CFG_NVME_RPMB_FS_CACHE_ENTRIES) { + fat_entry_dir_free(); + return; + } + + fe = fat_entry_dir->rpmb_fat_entry_buf; + fat_entry_dir->idx_curr = 0; + fat_entry_dir->num_total_read = 0; + fat_entry_dir->last_reached = false; + + if (fat_entry_dir->num_buffered > CFG_NVME_RPMB_FS_CACHE_ENTRIES) { + fat_entry_dir->num_buffered = CFG_NVME_RPMB_FS_CACHE_ENTRIES; + + fe = realloc(fe, fat_entry_dir->num_buffered * sizeof(*fe)); + + /* + * In case realloc fails, we are on the safe side if we destroy + * the whole structure. Upon the next init, the cache has to be + * re-established, but this case should not happen in practice. + */ + if (!fe) + fat_entry_dir_free(); + else + fat_entry_dir->rpmb_fat_entry_buf = fe; + } +} + +/** + * fat_entry_dir_update: Updates a persisted FAT FS entry in the cache. + * This function updates the FAT entry fat_entry that was written to address + * fat_address onto RPMB storage in the cache. + */ +static TEE_Result __maybe_unused fat_entry_dir_update + (struct nvme_rpmb_fat_entry *fat_entry, + uint32_t fat_address) +{ + uint32_t fat_entry_buf_idx = 0; + /* Use a temp var to avoid compiler warning if caching disabled. */ + uint32_t max_cache_entries = CFG_NVME_RPMB_FS_CACHE_ENTRIES; + + assert(!((fat_address - NVME_RPMB_FS_FAT_START_ADDRESS) % + sizeof(struct nvme_rpmb_fat_entry))); + + /* Nothing to update if the cache is not initialized. */ + if (!fat_entry_dir) + return TEE_SUCCESS; + + fat_entry_buf_idx = (fat_address - NVME_RPMB_FS_FAT_START_ADDRESS) / + sizeof(struct nvme_rpmb_fat_entry); + + /* Only need to write if index points to an entry in cache. */ + if (fat_entry_buf_idx < fat_entry_dir->num_buffered && + fat_entry_buf_idx < max_cache_entries) { + memcpy(fat_entry_dir->rpmb_fat_entry_buf + fat_entry_buf_idx, + fat_entry, sizeof(struct nvme_rpmb_fat_entry)); + } + + return TEE_SUCCESS; +} + +/** + * fat_entry_dir_get_next: Get next FAT FS entry. + * Read either from cache/buffer, or by reading from RPMB storage if the + * elements in the buffer/cache are fully read. When reading in from RPMB + * storage, the buffer is overwritten in case caching is disabled. + * In case caching is enabled, the cache is either further filled, or a + * temporary buffer populated if the cache is already full. + * The FAT FS entry is written to fat_entry. The respective address in RPMB + * storage is written to fat_address, if not NULL. When the last FAT FS entry + * was previously read, the function indicates this case by writing a NULL + * pointer to fat_entry. + * Returns a value different TEE_SUCCESS if the next FAT FS entry could not be + * retrieved. + */ +static TEE_Result fat_entry_dir_get_next(struct nvme_rpmb_fat_entry **fat_entry, + uint32_t *fat_address) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct nvme_rpmb_fat_entry *fe = NULL; + uint32_t num_elems_read = 0; + uint32_t fat_address_local = 0; + + assert(fat_entry_dir && fat_entry); + + /* Don't read further if we previously read the last FAT FS entry. */ + if (fat_entry_dir->last_reached) { + *fat_entry = NULL; + return TEE_SUCCESS; + } + + fe = fat_entry_dir->rpmb_fat_entry_buf; + + /* Determine address of FAT FS entry in RPMB storage. */ + fat_address_local = NVME_RPMB_FS_FAT_START_ADDRESS + + (fat_entry_dir->num_total_read * + sizeof(struct nvme_rpmb_fat_entry)); + + /* + * We've read all so-far buffered elements, so we need to + * read in more entries from RPMB storage. + */ + if (fat_entry_dir->idx_curr >= fat_entry_dir->num_buffered) { + /* + * This is the case where we do not cache entries, so just read + * in next set of FAT FS entries into the buffer. + * Goto the end of the when statement if that is done. + */ + if (!CFG_NVME_RPMB_FS_CACHE_ENTRIES) { + num_elems_read = CFG_NVME_RPMB_FS_RD_ENTRIES; + fat_entry_dir->idx_curr = 0; + + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, + NVME_RPMB_DEFAULT_TARGET, + fat_address_local, (uint8_t *)fe, + num_elems_read * sizeof(*fe), NULL, + NULL); + if (res) + return res; + goto post_read_in; + } + + /* + * We cache FAT FS entries, and the buffer is not completely + * filled. Further keep on extending the buffer up to its max + * size by reading in from RPMB. + */ + if (fat_entry_dir->num_total_read < NVME_RPMB_BUF_MAX_ENTRIES) { + /* + * Read at most as many elements as fit in the buffer + * and no more than the defined number of entries to + * read in at once. + */ + num_elems_read = MIN(NVME_RPMB_BUF_MAX_ENTRIES - + fat_entry_dir->num_total_read, + (uint32_t)CFG_NVME_RPMB_FS_RD_ENTRIES); + + /* + * Expand the buffer to fit in the additional entries. + */ + fe = realloc(fe, + (fat_entry_dir->num_buffered + + num_elems_read) * sizeof(*fe)); + if (!fe) + return TEE_ERROR_OUT_OF_MEMORY; + + fat_entry_dir->rpmb_fat_entry_buf = fe; + + /* Read in to the next free slot in the buffer/cache. */ + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, + NVME_RPMB_DEFAULT_TARGET, + fat_address_local, + (uint8_t *)(fe + + fat_entry_dir->num_total_read), + num_elems_read * sizeof(*fe), + NULL, NULL); + if (res) + return res; + + fat_entry_dir->num_buffered += num_elems_read; + } else { + /* + * This happens when we have read as many elements as + * can possibly fit into the buffer. + * As the first part of the buffer serves as our cache, + * we only overwrite the last part that serves as our + * temporary buffer used to iteratively read in entries + * when the cache is full. Read in the temporary buffer + * maximum size. + */ + num_elems_read = CFG_NVME_RPMB_FS_RD_ENTRIES; + /* Reset index to beginning of the temporary buffer. */ + fat_entry_dir->idx_curr = CFG_NVME_RPMB_FS_CACHE_ENTRIES; + + /* Read in elements after the end of the cache. */ + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, + NVME_RPMB_DEFAULT_TARGET, + fat_address_local, + (uint8_t *)(fe + + fat_entry_dir->idx_curr), + num_elems_read * sizeof(*fe), + NULL, NULL); + if (res) + return res; + } + } + +post_read_in: + if (fat_address) + *fat_address = fat_address_local; + + *fat_entry = fe + fat_entry_dir->idx_curr; + + fat_entry_dir->idx_curr++; + fat_entry_dir->num_total_read++; + + /* + * Indicate last entry was read. + * Ensures we return a zero value for fat_entry on next invocation. + */ + if ((*fat_entry)->flags & FILE_IS_LAST_ENTRY) + fat_entry_dir->last_reached = true; + + return TEE_SUCCESS; +} + +#if (TRACE_LEVEL >= TRACE_FLOW) +static void dump_fat(void) +{ + TEE_Result res = TEE_ERROR_SECURITY; + struct nvme_rpmb_fat_entry *fe = NULL; + + if (!fs_par) + return; + + if (fat_entry_dir_init()) + return; + + while (true) { + res = fat_entry_dir_get_next(&fe, NULL); + if (res || !fe) + break; + + FMSG("flags %#"PRIx32", size %"PRIu32", address %#"PRIx32 + ", filename '%s'", + fe->flags, fe->data_size, fe->start_address, fe->filename); + } + + fat_entry_dir_deinit(); +} +#else +static void dump_fat(void) +{ +} +#endif + +#if (TRACE_LEVEL >= TRACE_DEBUG) +static void dump_fh(struct nvme_rpmb_file_handle *fh) +{ + DMSG("fh->filename=%s", fh->filename); + DMSG("fh->rpmb_fat_address=%u", fh->rpmb_fat_address); + DMSG("fh->fat_entry.start_address=%u", fh->fat_entry.start_address); + DMSG("fh->fat_entry.data_size=%u", fh->fat_entry.data_size); +} +#else +static void dump_fh(struct nvme_rpmb_file_handle *fh __unused) +{ +} +#endif + +/* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ +static TEE_Result create_filename(void *buf, size_t blen, struct tee_pobj *po, + bool transient) +{ + uint8_t *file = buf; + uint32_t pos = 0; + uint32_t hslen = 1 /* Leading slash */ + + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len) + + 1; /* Intermediate slash */ + + /* +1 for the '.' (temporary persistent object) */ + if (transient) + hslen++; + + if (blen < hslen) + return TEE_ERROR_SHORT_BUFFER; + + file[pos++] = '/'; + pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos], + sizeof(TEE_UUID), hslen); + file[pos++] = '/'; + + if (transient) + file[pos++] = '.'; + + tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos); + + return TEE_SUCCESS; +} + +/* "/TA_uuid" */ +static TEE_Result create_dirname(void *buf, size_t blen, const TEE_UUID *uuid) +{ + uint8_t *dir = buf; + uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; + + if (blen < hslen) + return TEE_ERROR_SHORT_BUFFER; + + dir[0] = '/'; + tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen); + + return TEE_SUCCESS; +} + +static struct nvme_rpmb_file_handle *alloc_file_handle(struct tee_pobj *po, + bool temporary) +{ + struct nvme_rpmb_file_handle *fh = NULL; + + fh = calloc(1, sizeof(struct nvme_rpmb_file_handle)); + if (!fh) + return NULL; + + if (po) + create_filename(fh->filename, sizeof(fh->filename), po, + temporary); + + return fh; +} + +/** + * write_fat_entry: Store info in a fat_entry to RPMB. + */ +static TEE_Result write_fat_entry(struct nvme_rpmb_file_handle *fh, + bool update_write_counter) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* Protect partition data. */ + if (fh->rpmb_fat_address < sizeof(struct nvme_rpmb_fs_partition)) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto out; + } + + if (fh->rpmb_fat_address % sizeof(struct nvme_rpmb_fat_entry) != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (update_write_counter) { + res = tee_nvme_rpmb_get_write_counter(CFG_NVME_RPMB_FS_DEV_ID, + &fh->fat_entry.write_counter); + if (res) + goto out; + } + + res = tee_nvme_rpmb_write(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + fh->rpmb_fat_address, (uint8_t *)&fh->fat_entry, + sizeof(struct nvme_rpmb_fat_entry), NULL, NULL); + + dump_fat(); + + /* If caching enabled, update a successfully written entry in cache. */ + if (CFG_NVME_RPMB_FS_CACHE_ENTRIES && !res) + res = fat_entry_dir_update(&fh->fat_entry, fh->rpmb_fat_address); + +out: + return res; +} + +/** + * nvme_rpmb_fs_setup: Setup NVME-RPMB FS. + * Set initial partition and FS values and write to RPMB. + * Store frequently used data in RAM. + */ +static TEE_Result nvme_rpmb_fs_setup(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct nvme_rpmb_fs_partition *partition_data = NULL; + struct nvme_rpmb_file_handle *fh = NULL; + uint32_t max_nvme_rpmb_block = 0; + + if (fs_par) { + res = TEE_SUCCESS; + goto out; + } + + res = tee_nvme_rpmb_get_max_block(CFG_NVME_RPMB_FS_DEV_ID, &max_nvme_rpmb_block); + if (res != TEE_SUCCESS) + goto out; + + /* + * We're going to read a full block in order to have a full block + * for the dummy write below. + */ + COMPILE_TIME_ASSERT(sizeof(struct nvme_rpmb_fs_partition) <= + NVME_RPMB_BLOCK_SIZE); + partition_data = calloc(1, NVME_RPMB_BLOCK_SIZE); + if (!partition_data) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + NVME_RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, + NVME_RPMB_BLOCK_SIZE, NULL, NULL); + if (res != TEE_SUCCESS) + goto out; + /* + * Perform a write in order to increase the write counter. This + * prevents late usage (replay attack) of a previously blocked + * request with a valid write counter value. + */ + res = tee_nvme_rpmb_write(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + NVME_RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, + NVME_RPMB_BLOCK_SIZE, NULL, NULL); + if (res != TEE_SUCCESS) + goto out; + /* + * We're reading again in case a stale request was committed + * instead of the one issued above. If this succeeds we're in sync + * with the RPMB block since there are no other possible stale + * blocks with valid write counters available. + */ + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + NVME_RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, + sizeof(struct nvme_rpmb_fs_partition), NULL, NULL); + if (res != TEE_SUCCESS) + goto out; + +#ifndef CFG_NVME_RPMB_RESET_FAT + if (partition_data->nvme_rpmb_fs_magic == NVME_RPMB_FS_MAGIC) { + if (partition_data->fs_version == NVME_FS_VERSION) { + res = TEE_SUCCESS; + goto store_fs_par; + } else { + EMSG("Wrong software is in use."); + res = TEE_ERROR_ACCESS_DENIED; + goto out; + } + } +#else + EMSG("**** Clearing Storage ****"); +#endif + + /* Setup new partition data. */ + partition_data->nvme_rpmb_fs_magic = NVME_RPMB_FS_MAGIC; + partition_data->fs_version = NVME_FS_VERSION; + partition_data->fat_start_address = NVME_RPMB_FS_FAT_START_ADDRESS; + + /* Initial FAT entry with FILE_IS_LAST_ENTRY flag set. */ + fh = alloc_file_handle(NULL, false); + if (!fh) { + 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_nvme_rpmb_get_write_counter(CFG_NVME_RPMB_FS_DEV_ID, + &partition_data->write_counter); + if (res != TEE_SUCCESS) + goto out; + + res = tee_nvme_rpmb_write(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + NVME_RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, + sizeof(struct nvme_rpmb_fs_partition), NULL, NULL); + if (res != TEE_SUCCESS) + goto out; + +#ifndef CFG_NVME_RPMB_RESET_FAT +store_fs_par: +#endif + + /* Store FAT start address. */ + fs_par = calloc(1, sizeof(struct nvme_rpmb_fs_parameters)); + if (!fs_par) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + fs_par->fat_start_address = partition_data->fat_start_address; + fs_par->max_rpmb_address = max_nvme_rpmb_block << NVME_RPMB_BLOCK_SIZE_SHIFT; + + dump_fat(); + +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) +{ + if (!fs_par) + return TEE_ERROR_NO_DATA; + + *addr = fs_par->fat_start_address; + + return TEE_SUCCESS; +} + +/** + * 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 nvme_rpmb_file_handle *fh, tee_mm_pool_t *p) +{ + TEE_Result res = TEE_ERROR_GENERIC; + tee_mm_entry_t *mm = NULL; + struct nvme_rpmb_fat_entry *fe = NULL; + uint32_t fat_address; + bool entry_found = false; + bool expand_fat = false; + struct nvme_rpmb_file_handle last_fh; + + DMSG("fat_address %d", fh->rpmb_fat_address); + + res = fat_entry_dir_init(); + if (res) + goto out; + + /* + * The pool is used to represent the current RPMB layout. To find + * a slot for the file tee_mm_alloc is called on the pool. Thus + * if it is not NULL the entire FAT must be traversed to fill in + * the pool. + */ + while (true) { + res = fat_entry_dir_get_next(&fe, &fat_address); + if (res || !fe) + break; + + /* + * Look for an entry, matching filenames. (read, rm, + * rename and stat.). Only store first filename match. + */ + if ((!strcmp(fh->filename, fe->filename)) && + (fe->flags & FILE_IS_ACTIVE) && !entry_found) { + entry_found = true; + fh->rpmb_fat_address = fat_address; + memcpy(&fh->fat_entry, fe, sizeof(*fe)); + if (!p) + break; + } + + /* Add existing files to memory pool. (write) */ + if (p) { + if ((fe->flags & FILE_IS_ACTIVE) && fe->data_size > 0) { + + mm = tee_mm_alloc2(p, fe->start_address, + fe->data_size); + if (!mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + /* Unused FAT entries can be reused (write) */ + if (((fe->flags & FILE_IS_ACTIVE) == 0) && + fh->rpmb_fat_address == 0) { + fh->rpmb_fat_address = fat_address; + memcpy(&fh->fat_entry, fe, + sizeof(struct nvme_rpmb_fat_entry)); + } + + if (((fe->flags & FILE_IS_LAST_ENTRY) != 0) && + fh->rpmb_fat_address == fat_address) { + + /* + * If the last entry was reached and was chosen + * by the previous check, then the FAT needs to + * be expanded. + * fh->rpmb_fat_address is the address chosen + * to store the files FAT entry and fat_address + * is the current FAT entry address being + * compared. + */ + expand_fat = true; + } + } + } + + if (res) + goto out; + /* + * Represent the FAT table in the pool. + */ + if (p) { + /* + * Since fat_address is the start of the last entry it needs to + * be moved up by an entry. + */ + fat_address += sizeof(struct nvme_rpmb_fat_entry); + + /* Make room for yet a FAT entry and add to memory pool. */ + if (expand_fat) + fat_address += sizeof(struct nvme_rpmb_fat_entry); + + mm = tee_mm_alloc2(p, NVME_RPMB_STORAGE_START_ADDRESS, fat_address); + if (!mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (expand_fat) { + /* + * Point fat_address to the beginning of the new + * entry. + */ + fat_address -= sizeof(struct nvme_rpmb_fat_entry); + memset(&last_fh, 0, sizeof(last_fh)); + last_fh.fat_entry.flags = FILE_IS_LAST_ENTRY; + last_fh.rpmb_fat_address = fat_address; + res = write_fat_entry(&last_fh, true); + if (res != TEE_SUCCESS) + goto out; + } + } + + if (!fh->rpmb_fat_address) + res = TEE_ERROR_ITEM_NOT_FOUND; + +out: + fat_entry_dir_deinit(); + return res; +} + +static TEE_Result generate_fek(struct nvme_rpmb_fat_entry *fe, const TEE_UUID *uuid) +{ + TEE_Result res; + +again: + res = tee_fs_generate_fek(uuid, fe->fek, sizeof(fe->fek)); + if (res != TEE_SUCCESS) + return res; + + if (is_zero(fe->fek, sizeof(fe->fek))) + goto again; + + return res; +} + +static TEE_Result nvme_rpmb_fs_open_internal(struct nvme_rpmb_file_handle *fh, + const TEE_UUID *uuid, bool create) +{ + tee_mm_pool_t p; + bool pool_result; + TEE_Result res = TEE_ERROR_GENERIC; + + /* We need to do setup in order to make sure fs_par is filled in */ + res = nvme_rpmb_fs_setup(); + if (res != TEE_SUCCESS) + goto out; + + fh->uuid = uuid; + if (create) { + /* Upper memory allocation must be used for NVME_RPMB_FS. */ + pool_result = tee_mm_init(&p, NVME_RPMB_STORAGE_START_ADDRESS, + fs_par->max_rpmb_address, + NVME_RPMB_BLOCK_SIZE_SHIFT, + TEE_MM_POOL_HI_ALLOC); + if (!pool_result) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh, &p); + tee_mm_final(&p); + if (res != TEE_SUCCESS) + goto out; + } else { + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + } + + /* + * If this is opened with create and the entry found was not active + * then this is a new file and the FAT entry must be written + */ + if (create) { + if ((fh->fat_entry.flags & FILE_IS_ACTIVE) == 0) { + memset(&fh->fat_entry, 0, + sizeof(struct nvme_rpmb_fat_entry)); + memcpy(fh->fat_entry.filename, fh->filename, + strlen(fh->filename)); + /* Start address and size are 0 */ + fh->fat_entry.flags = FILE_IS_ACTIVE; + + res = generate_fek(&fh->fat_entry, uuid); + if (res != TEE_SUCCESS) + goto out; + DMSG("GENERATE FEK key: %p", + (void *)fh->fat_entry.fek); + DHEXDUMP(fh->fat_entry.fek, sizeof(fh->fat_entry.fek)); + + res = write_fat_entry(fh, true); + if (res != TEE_SUCCESS) + goto out; + } + } + + res = TEE_SUCCESS; + +out: + return res; +} + +static void nvme_rpmb_fs_close(struct tee_file_handle **tfh) +{ + struct nvme_rpmb_file_handle *fh = (struct nvme_rpmb_file_handle *)*tfh; + + free(fh); + *tfh = NULL; +} + +static TEE_Result nvme_rpmb_fs_read(struct tee_file_handle *tfh, size_t pos, + void *buf, size_t *len) +{ + TEE_Result res; + struct nvme_rpmb_file_handle *fh = (struct nvme_rpmb_file_handle *)tfh; + size_t size = *len; + + if (!size) + return TEE_SUCCESS; + + mutex_lock(&nvme_rpmb_mutex); + + dump_fh(fh); + + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + + if (pos >= fh->fat_entry.data_size) { + *len = 0; + goto out; + } + + size = MIN(size, fh->fat_entry.data_size - pos); + if (size) { + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + fh->fat_entry.start_address + pos, buf, size, + fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + goto out; + } + *len = size; + +out: + mutex_unlock(&nvme_rpmb_mutex); + return res; +} + +static TEE_Result update_write_helper(struct nvme_rpmb_file_handle *fh, + size_t pos, const void *buf, + size_t size, uintptr_t new_fat, + size_t new_size) +{ + uintptr_t old_fat = fh->fat_entry.start_address; + size_t old_size = fh->fat_entry.data_size; + const uint8_t *rem_buf = buf; + size_t rem_size = size; + uint8_t *blk_buf = NULL; + size_t blk_offset = 0; + size_t blk_size = 0; + TEE_Result res = TEE_SUCCESS; + + blk_buf = mempool_alloc(mempool_default, TMP_BLOCK_SIZE); + if (!blk_buf) + return TEE_ERROR_OUT_OF_MEMORY; + + while (blk_offset < new_size) { + uint8_t *copy_dst = blk_buf; + size_t copy_size = 0; + size_t rd_size = 0; + + blk_size = MIN(TMP_BLOCK_SIZE, new_size - blk_offset); + memset(blk_buf, 0, blk_size); + + /* Possibly read old RPMB data in temporary buffer */ + if (blk_offset < pos && blk_offset < old_size) { + rd_size = MIN(blk_size, old_size - blk_offset); + + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, + NVME_RPMB_DEFAULT_TARGET, + old_fat + blk_offset, blk_buf, rd_size, + fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + break; + } + + /* Possibly update data in temporary buffer */ + if ((blk_offset + TMP_BLOCK_SIZE > pos) && + (blk_offset < pos + size)) { + size_t offset = 0; + + copy_dst = blk_buf; + copy_size = TMP_BLOCK_SIZE; + + if (blk_offset < pos) { + offset = pos - blk_offset; + + copy_dst += offset; + copy_size -= offset; + } + copy_size = MIN(copy_size, rem_size); + + memcpy(copy_dst, rem_buf, copy_size); + rem_buf += copy_size; + rem_size -= copy_size; + } + + /* Write temporary buffer to new RPMB destination */ + res = tee_nvme_rpmb_write(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + new_fat + blk_offset, blk_buf, blk_size, + fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + break; + + blk_offset += blk_size; + } + + mempool_free(mempool_default, blk_buf); + + return res; +} + +static TEE_Result nvme_rpmb_fs_write_primitive(struct nvme_rpmb_file_handle *fh, + size_t pos, const void *buf, size_t size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + tee_mm_pool_t p = { }; + bool pool_result = false; + size_t end = 0; + uint32_t start_addr = 0; + + if (!size) + return TEE_SUCCESS; + + if (!fs_par) { + res = TEE_ERROR_GENERIC; + goto out; + } + + dump_fh(fh); + + /* Upper memory allocation must be used for NVME_RPMB_FS. */ + pool_result = tee_mm_init(&p, NVME_RPMB_STORAGE_START_ADDRESS, + fs_par->max_rpmb_address, NVME_RPMB_BLOCK_SIZE_SHIFT, + TEE_MM_POOL_HI_ALLOC); + if (!pool_result) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh, &p); + if (res != TEE_SUCCESS) + goto out; + + if (fh->fat_entry.flags & FILE_IS_LAST_ENTRY) + panic("invalid last entry flag"); + + if (ADD_OVERFLOW(pos, size, &end)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + if (ADD_OVERFLOW(fh->fat_entry.start_address, pos, &start_addr)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (end <= fh->fat_entry.data_size && + tee_nvme_rpmb_write_is_atomic(CFG_NVME_RPMB_FS_DEV_ID, start_addr, size)) { + + DMSG("Updating data in-place"); + res = tee_nvme_rpmb_write(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + start_addr, buf, size, + fh->fat_entry.fek, fh->uuid); + } else { + /* + * File must be extended, or update cannot be atomic: allocate, + * read, update, write. + */ + size_t new_size = MAX(end, fh->fat_entry.data_size); + tee_mm_entry_t *mm = tee_mm_alloc(&p, new_size); + uintptr_t new_fat_entry = 0; + + DMSG("Need to re-allocate"); + if (!mm) { + EMSG("NVME-RPMB: No space left"); + res = TEE_ERROR_STORAGE_NO_SPACE; + goto out; + } + + new_fat_entry = tee_mm_get_smem(mm); + + res = update_write_helper(fh, pos, buf, size, + new_fat_entry, new_size); + if (res == TEE_SUCCESS) { + fh->fat_entry.data_size = new_size; + fh->fat_entry.start_address = new_fat_entry; + + res = write_fat_entry(fh, true); + } + } + +out: + if (pool_result) + tee_mm_final(&p); + + return res; +} + +static TEE_Result nvme_rpmb_fs_write(struct tee_file_handle *tfh, size_t pos, + const void *buf, size_t size) +{ + TEE_Result res; + + mutex_lock(&nvme_rpmb_mutex); + res = nvme_rpmb_fs_write_primitive((struct nvme_rpmb_file_handle *)tfh, pos, + buf, size); + mutex_unlock(&nvme_rpmb_mutex); + + return res; +} + +static TEE_Result nvme_rpmb_fs_remove_internal(struct nvme_rpmb_file_handle *fh) +{ + TEE_Result res; + + res = read_fat(fh, NULL); + if (res) + return res; + + /* Clear this file entry. */ + memset(&fh->fat_entry, 0, sizeof(struct nvme_rpmb_fat_entry)); + return write_fat_entry(fh, false); +} + +static TEE_Result nvme_rpmb_fs_remove(struct tee_pobj *po) +{ + TEE_Result res; + struct nvme_rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); + + if (!fh) + return TEE_ERROR_OUT_OF_MEMORY; + + mutex_lock(&nvme_rpmb_mutex); + + res = nvme_rpmb_fs_remove_internal(fh); + + mutex_unlock(&nvme_rpmb_mutex); + + free(fh); + return res; +} + +static TEE_Result nvme_rpmb_fs_rename_internal(struct tee_pobj *old, + struct tee_pobj *new, + bool overwrite) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct nvme_rpmb_file_handle *fh_old = NULL; + struct nvme_rpmb_file_handle *fh_new = NULL; + + if (!old) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (new) + fh_old = alloc_file_handle(old, old->temporary); + else + fh_old = alloc_file_handle(old, true); + if (!fh_old) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (new) + fh_new = alloc_file_handle(new, new->temporary); + else + fh_new = alloc_file_handle(old, false); + if (!fh_new) { + 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) { + if (!overwrite) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto out; + } + + /* Clear this file entry. */ + memset(&fh_new->fat_entry, 0, sizeof(struct nvme_rpmb_fat_entry)); + res = write_fat_entry(fh_new, false); + if (res != TEE_SUCCESS) + goto out; + } + + memset(fh_old->fat_entry.filename, 0, TEE_NVME_RPMB_FS_FILENAME_LENGTH); + memcpy(fh_old->fat_entry.filename, fh_new->filename, + strlen(fh_new->filename)); + + res = write_fat_entry(fh_old, false); + +out: + free(fh_old); + free(fh_new); + + return res; +} + +static TEE_Result nvme_rpmb_fs_rename(struct tee_pobj *old, struct tee_pobj *new, + bool overwrite) +{ + TEE_Result res; + + mutex_lock(&nvme_rpmb_mutex); + res = nvme_rpmb_fs_rename_internal(old, new, overwrite); + mutex_unlock(&nvme_rpmb_mutex); + + return res; +} + +static TEE_Result nvme_rpmb_fs_truncate(struct tee_file_handle *tfh, size_t length) +{ + struct nvme_rpmb_file_handle *fh = (struct nvme_rpmb_file_handle *)tfh; + tee_mm_pool_t p; + bool pool_result = false; + tee_mm_entry_t *mm; + uint32_t newsize; + uint8_t *newbuf = NULL; + uintptr_t newaddr; + TEE_Result res = TEE_ERROR_GENERIC; + + mutex_lock(&nvme_rpmb_mutex); + + if (length > INT32_MAX) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + newsize = length; + + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + + if (newsize > fh->fat_entry.data_size) { + /* Extend file */ + + pool_result = tee_mm_init(&p, NVME_RPMB_STORAGE_START_ADDRESS, + fs_par->max_rpmb_address, NVME_RPMB_BLOCK_SIZE_SHIFT, + TEE_MM_POOL_HI_ALLOC); + if (!pool_result) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + res = read_fat(fh, &p); + if (res != TEE_SUCCESS) + goto out; + + mm = tee_mm_alloc(&p, newsize); + newbuf = calloc(1, newsize); + if (!mm || !newbuf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (fh->fat_entry.data_size) { + res = tee_nvme_rpmb_read(CFG_NVME_RPMB_FS_DEV_ID, + NVME_RPMB_DEFAULT_TARGET, + fh->fat_entry.start_address, newbuf, + fh->fat_entry.data_size, fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + goto out; + } + + newaddr = tee_mm_get_smem(mm); + res = tee_nvme_rpmb_write(CFG_NVME_RPMB_FS_DEV_ID, NVME_RPMB_DEFAULT_TARGET, + newaddr, newbuf, newsize, + fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + goto out; + + } else { + /* Don't change file location */ + newaddr = fh->fat_entry.start_address; + } + + /* fh->pos is unchanged */ + fh->fat_entry.data_size = newsize; + fh->fat_entry.start_address = newaddr; + res = write_fat_entry(fh, true); + +out: + mutex_unlock(&nvme_rpmb_mutex); + if (pool_result) + tee_mm_final(&p); + if (newbuf) + free(newbuf); + + return res; +} + +static void nvme_rpmb_fs_dir_free(struct tee_fs_dir *dir) +{ + struct tee_nvme_rpmb_fs_dirent *e; + + if (!dir) + return; + + free(dir->current); + + while ((e = SIMPLEQ_FIRST(&dir->next))) { + SIMPLEQ_REMOVE_HEAD(&dir->next, link); + free(e); + } +} + +static TEE_Result nvme_rpmb_fs_dir_populate(const char *path, + struct tee_fs_dir *dir) +{ + struct tee_nvme_rpmb_fs_dirent *current = NULL; + struct nvme_rpmb_fat_entry *fe = NULL; + uint32_t fat_address; + uint32_t filelen; + char *filename; + bool matched; + struct tee_nvme_rpmb_fs_dirent *next = NULL; + uint32_t pathlen; + TEE_Result res = TEE_ERROR_GENERIC; + char temp; + + mutex_lock(&nvme_rpmb_mutex); + + res = fat_entry_dir_init(); + if (res) + goto out; + + pathlen = strlen(path); + + while (true) { + res = fat_entry_dir_get_next(&fe, &fat_address); + if (res || !fe) + break; + + filename = fe->filename; + if (fe->flags & FILE_IS_ACTIVE) { + matched = false; + filelen = strlen(filename); + if (filelen > pathlen) { + temp = filename[pathlen]; + filename[pathlen] = '\0'; + if (strcmp(filename, path) == 0) + matched = true; + + filename[pathlen] = temp; + } + + if (matched) { + next = malloc(sizeof(*next)); + if (!next) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + next->entry.oidlen = tee_hs2b((uint8_t *) + &filename[pathlen], + next->entry.oid, + filelen - pathlen, + sizeof(next->entry.oid)); + if (next->entry.oidlen) { + SIMPLEQ_INSERT_TAIL(&dir->next, + next, link); + current = next; + } else { + free(next); + next = NULL; + } + } + } + } + + if (res) + goto out; + + if (current) + res = TEE_SUCCESS; + else + res = TEE_ERROR_ITEM_NOT_FOUND; /* No directories were found. */ + +out: + mutex_unlock(&nvme_rpmb_mutex); + fat_entry_dir_deinit(); + if (res) + nvme_rpmb_fs_dir_free(dir); + + return res; +} + +static TEE_Result nvme_rpmb_fs_opendir(const TEE_UUID *uuid, struct tee_fs_dir **dir) +{ + uint32_t len; + char path_local[TEE_NVME_RPMB_FS_FILENAME_LENGTH]; + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_fs_dir *rpmb_dir = NULL; + + if (!uuid || !dir) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + memset(path_local, 0, sizeof(path_local)); + if (create_dirname(path_local, sizeof(path_local) - 1, uuid)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + len = strlen(path_local); + + /* Add a slash to correctly match the full directory name. */ + if (path_local[len - 1] != '/') + path_local[len] = '/'; + + rpmb_dir = calloc(1, sizeof(*rpmb_dir)); + if (!rpmb_dir) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + SIMPLEQ_INIT(&rpmb_dir->next); + + res = nvme_rpmb_fs_dir_populate(path_local, rpmb_dir); + if (res != TEE_SUCCESS) { + free(rpmb_dir); + rpmb_dir = NULL; + goto out; + } + + *dir = rpmb_dir; + +out: + return res; +} + +static TEE_Result nvme_rpmb_fs_readdir(struct tee_fs_dir *dir, + struct tee_fs_dirent **ent) +{ + if (!dir) + return TEE_ERROR_GENERIC; + + free(dir->current); + + dir->current = SIMPLEQ_FIRST(&dir->next); + if (!dir->current) + return TEE_ERROR_ITEM_NOT_FOUND; + + SIMPLEQ_REMOVE_HEAD(&dir->next, link); + + *ent = &dir->current->entry; + return TEE_SUCCESS; +} + +static void nvme_rpmb_fs_closedir(struct tee_fs_dir *dir) +{ + if (dir) { + nvme_rpmb_fs_dir_free(dir); + free(dir); + } +} + +static TEE_Result nvme_rpmb_fs_open(struct tee_pobj *po, size_t *size, + struct tee_file_handle **ret_fh) +{ + TEE_Result res; + struct nvme_rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); + + if (!fh) + return TEE_ERROR_OUT_OF_MEMORY; + + mutex_lock(&nvme_rpmb_mutex); + + res = nvme_rpmb_fs_open_internal(fh, &po->uuid, false); + if (!res && size) + *size = fh->fat_entry.data_size; + + mutex_unlock(&nvme_rpmb_mutex); + + if (res) + free(fh); + else + *ret_fh = (struct tee_file_handle *)fh; + + return res; +} + +static TEE_Result nvme_rpmb_fs_create(struct tee_pobj *po, bool overwrite, + const void *head, size_t head_size, + const void *attr, size_t attr_size, + const void *data, size_t data_size, + struct tee_file_handle **ret_fh) +{ + TEE_Result res; + size_t pos = 0; + struct nvme_rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); + + if (!fh) + return TEE_ERROR_OUT_OF_MEMORY; + + mutex_lock(&nvme_rpmb_mutex); + res = nvme_rpmb_fs_open_internal(fh, &po->uuid, true); + if (res) + goto out; + + if (head && head_size) { + res = nvme_rpmb_fs_write_primitive(fh, pos, head, head_size); + if (res) + goto out; + pos += head_size; + } + + if (attr && attr_size) { + res = nvme_rpmb_fs_write_primitive(fh, pos, attr, attr_size); + if (res) + goto out; + pos += attr_size; + } + + if (data && data_size) { + res = nvme_rpmb_fs_write_primitive(fh, pos, data, data_size); + if (res) + goto out; + } + + if (po->temporary) { + /* + * If it's a temporary filename (which it normally is) + * rename into the final filename now that the file is + * fully initialized. + */ + po->temporary = false; + res = nvme_rpmb_fs_rename_internal(po, NULL, overwrite); + if (res) { + po->temporary = true; + goto out; + } + /* Update file handle after rename. */ + create_filename(fh->filename, sizeof(fh->filename), po, false); + } + +out: + if (res) { + nvme_rpmb_fs_remove_internal(fh); + free(fh); + } else { + *ret_fh = (struct tee_file_handle *)fh; + } + mutex_unlock(&nvme_rpmb_mutex); + + return res; +} + +const struct tee_file_operations nvme_rpmb_fs_ops = { + .open = nvme_rpmb_fs_open, + .create = nvme_rpmb_fs_create, + .close = nvme_rpmb_fs_close, + .read = nvme_rpmb_fs_read, + .write = nvme_rpmb_fs_write, + .truncate = nvme_rpmb_fs_truncate, + .rename = nvme_rpmb_fs_rename, + .remove = nvme_rpmb_fs_remove, + .opendir = nvme_rpmb_fs_opendir, + .closedir = nvme_rpmb_fs_closedir, + .readdir = nvme_rpmb_fs_readdir, +}; + +TEE_Result tee_nvme_rpmb_fs_raw_open(const char *fname, bool create, + struct tee_file_handle **ret_fh) +{ + TEE_Result res; + struct nvme_rpmb_file_handle *fh = calloc(1, sizeof(*fh)); + /* We use 0 here to indicate that the owner is OPTEE OS */ + static const TEE_UUID uuid = { 0 }; + + if (!fname || !ret_fh) + return TEE_ERROR_BAD_PARAMETERS; + + if (!fh) + return TEE_ERROR_OUT_OF_MEMORY; + + snprintf(fh->filename, sizeof(fh->filename), "/%s", fname); + + mutex_lock(&nvme_rpmb_mutex); + + res = nvme_rpmb_fs_open_internal(fh, &uuid, create); + + mutex_unlock(&nvme_rpmb_mutex); + + if (res) { + if (create) + nvme_rpmb_fs_remove_internal(fh); + free(fh); + } else { + *ret_fh = (struct tee_file_handle *)fh; + } + + return res; +} + +bool __weak plat_nvme_rpmb_key_is_ready(void) +{ + return true; +} diff --git a/optee/optee_os/core/tee/tee_obj.c b/optee/optee_os/core/tee/tee_obj.c new file mode 100644 index 0000000..2d091e4 --- /dev/null +++ b/optee/optee_os/core/tee/tee_obj.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void tee_obj_add(struct user_ta_ctx *utc, struct tee_obj *o) +{ + TAILQ_INSERT_TAIL(&utc->objects, o, link); +} + +TEE_Result tee_obj_get(struct user_ta_ctx *utc, vaddr_t obj_id, + struct tee_obj **obj) +{ + struct tee_obj *o; + + TAILQ_FOREACH(o, &utc->objects, link) { + if (obj_id == (vaddr_t)o) { + *obj = o; + return TEE_SUCCESS; + } + } + return TEE_ERROR_BAD_STATE; +} + +void tee_obj_close(struct user_ta_ctx *utc, struct tee_obj *o) +{ + TAILQ_REMOVE(&utc->objects, o, link); + + if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + o->pobj->fops->close(&o->fh); + tee_pobj_release(o->pobj); + } + + tee_obj_free(o); +} + +void tee_obj_close_all(struct user_ta_ctx *utc) +{ + struct tee_obj_head *objects = &utc->objects; + + while (!TAILQ_EMPTY(objects)) + tee_obj_close(utc, TAILQ_FIRST(objects)); +} + +TEE_Result tee_obj_verify(struct tee_ta_session *sess, struct tee_obj *o) +{ + TEE_Result res; + const struct tee_file_operations *fops = o->pobj->fops; + struct tee_file_handle *fh = NULL; + + if (!fops) + return TEE_ERROR_STORAGE_NOT_AVAILABLE; + + res = fops->open(o->pobj, NULL, &fh); + if (res == TEE_ERROR_CORRUPT_OBJECT) { + EMSG("Object corrupt"); + fops->remove(o->pobj); + tee_obj_close(to_user_ta_ctx(sess->ts_sess.ctx), o); + } + + fops->close(&fh); + return res; +} + +struct tee_obj *tee_obj_alloc(void) +{ + return calloc(1, sizeof(struct tee_obj)); +} + +void tee_obj_free(struct tee_obj *o) +{ + if (o) { + tee_obj_attr_free(o); + free(o->attr); + free(o); + } +} diff --git a/optee/optee_os/core/tee/tee_pobj.c b/optee/optee_os/core/tee/tee_pobj.c new file mode 100644 index 0000000..d8a2d26 --- /dev/null +++ b/optee/optee_os/core/tee/tee_pobj.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include + +static TAILQ_HEAD(tee_pobjs, tee_pobj) tee_pobjs = + TAILQ_HEAD_INITIALIZER(tee_pobjs); +static struct mutex pobjs_mutex = MUTEX_INITIALIZER; + +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; + + /* + * Excerpt of TEE Internal Core API Specification v1.1: + * If more than one handle is opened on the same object, and if any + * of these object handles was opened with the flag + * TEE_DATA_FLAG_ACCESS_READ, then all the object handles MUST have been + * opened with the flag TEE_DATA_FLAG_SHARE_READ + */ + if (((oflags & TEE_DATA_FLAG_ACCESS_READ) || + (nflags & TEE_DATA_FLAG_ACCESS_READ)) && + !((nflags & TEE_DATA_FLAG_SHARE_READ) && + (oflags & TEE_DATA_FLAG_SHARE_READ))) + return TEE_ERROR_ACCESS_CONFLICT; + + /* + * Excerpt of TEE Internal Core API Specification v1.1: + * An object can be opened with only share flags, which locks the access + * to an object against a given mode. + * An object can be opened with no flag set, which completely locks all + * subsequent attempts to access the object + */ + if ((nflags & TEE_DATA_FLAG_SHARE_READ) != + (oflags & TEE_DATA_FLAG_SHARE_READ)) + return TEE_ERROR_ACCESS_CONFLICT; + + /* Same on WRITE access */ + if (((oflags & TEE_DATA_FLAG_ACCESS_WRITE) || + (nflags & TEE_DATA_FLAG_ACCESS_WRITE)) && + !((nflags & TEE_DATA_FLAG_SHARE_WRITE) && + (oflags & TEE_DATA_FLAG_SHARE_WRITE))) + return TEE_ERROR_ACCESS_CONFLICT; + if ((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, enum tee_pobj_usage usage, + const struct tee_file_operations *fops, + struct tee_pobj **obj) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_pobj *o = NULL; + + *obj = NULL; + + mutex_lock(&pobjs_mutex); + /* 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) && + (fops == o->fops)) { + *obj = o; + } + } + + if (*obj) { + if (usage == TEE_POBJ_USAGE_ENUM) { + (*obj)->refcnt++; + goto out; + } + if ((*obj)->creating || (usage == TEE_POBJ_USAGE_CREATE && + !(flags & TEE_DATA_FLAG_OVERWRITE))) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto out; + } + res = tee_pobj_check_access((*obj)->flags, flags); + if (res == TEE_SUCCESS) + (*obj)->refcnt++; + goto out; + } + + /* new file */ + o = calloc(1, sizeof(struct tee_pobj)); + if (!o) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + o->refcnt = 1; + memcpy(&o->uuid, uuid, sizeof(TEE_UUID)); + o->flags = flags; + o->fops = fops; + + if (usage == TEE_POBJ_USAGE_CREATE) { + o->temporary = true; + o->creating = true; + } + + o->obj_id = malloc(obj_id_len); + if (o->obj_id == NULL) { + free(o); + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + 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; + + res = TEE_SUCCESS; +out: + if (res != TEE_SUCCESS) + *obj = NULL; + mutex_unlock(&pobjs_mutex); + return res; +} + +void tee_pobj_create_final(struct tee_pobj *po) +{ + mutex_lock(&pobjs_mutex); + po->temporary = false; + po->creating = false; + mutex_unlock(&pobjs_mutex); +} + +TEE_Result tee_pobj_release(struct tee_pobj *obj) +{ + if (obj == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + mutex_lock(&pobjs_mutex); + obj->refcnt--; + if (obj->refcnt == 0) { + TAILQ_REMOVE(&tee_pobjs, obj, link); + free(obj->obj_id); + free(obj); + } + mutex_unlock(&pobjs_mutex); + + 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; + + mutex_lock(&pobjs_mutex); + if (obj->refcnt != 1) { + res = TEE_ERROR_BAD_STATE; + goto exit; + } + + 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: + mutex_unlock(&pobjs_mutex); + free(new_obj_id); + return res; +} diff --git a/optee/optee_os/core/tee/tee_ree_fs.c b/optee/optee_os/core/tee/tee_ree_fs.c new file mode 100644 index 0000000..566a64c --- /dev/null +++ b/optee/optee_os/core/tee/tee_ree_fs.c @@ -0,0 +1,1018 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BLOCK_SHIFT 12 + +#define BLOCK_SIZE (1 << BLOCK_SHIFT) + +struct tee_fs_fd { + struct tee_fs_htree *ht; + int fd; + struct tee_fs_dirfile_fileh dfh; + const TEE_UUID *uuid; +}; + +struct tee_fs_dir { + struct tee_fs_dirfile_dirh *dirh; + int idx; + struct tee_fs_dirent d; + const TEE_UUID *uuid; +}; + +static int pos_to_block_num(int position) +{ + return position >> BLOCK_SHIFT; +} + +static struct mutex ree_fs_mutex = MUTEX_INITIALIZER; + +static void *get_tmp_block(void) +{ + return mempool_alloc(mempool_default, BLOCK_SIZE); +} + +static void put_tmp_block(void *tmp_block) +{ + mempool_free(mempool_default, tmp_block); +} + +static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, size_t pos, + const void *buf, size_t len) +{ + TEE_Result res; + size_t start_block_num = pos_to_block_num(pos); + size_t end_block_num = pos_to_block_num(pos + len - 1); + size_t remain_bytes = len; + uint8_t *data_ptr = (uint8_t *)buf; + uint8_t *block; + struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht); + + /* + * It doesn't make sense to call this function if nothing is to be + * written. This also guards against end_block_num getting an + * unexpected value when pos == 0 and len == 0. + */ + if (!len) + return TEE_ERROR_BAD_PARAMETERS; + + block = get_tmp_block(); + if (!block) + return TEE_ERROR_OUT_OF_MEMORY; + + while (start_block_num <= end_block_num) { + size_t offset = pos % BLOCK_SIZE; + size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE); + + if (size_to_write + offset > BLOCK_SIZE) + size_to_write = BLOCK_SIZE - offset; + + if (start_block_num * BLOCK_SIZE < + ROUNDUP(meta->length, BLOCK_SIZE)) { + res = tee_fs_htree_read_block(&fdp->ht, + start_block_num, block); + if (res != TEE_SUCCESS) + goto exit; + } else { + memset(block, 0, BLOCK_SIZE); + } + + if (data_ptr) + memcpy(block + offset, data_ptr, size_to_write); + else + memset(block + offset, 0, size_to_write); + + res = tee_fs_htree_write_block(&fdp->ht, start_block_num, + block); + if (res != TEE_SUCCESS) + goto exit; + + if (data_ptr) + data_ptr += size_to_write; + remain_bytes -= size_to_write; + start_block_num++; + pos += size_to_write; + } + + if (pos > meta->length) { + meta->length = pos; + tee_fs_htree_meta_set_dirty(fdp->ht); + } + +exit: + if (block) + put_tmp_block(block); + return res; +} + +static TEE_Result get_offs_size(enum tee_fs_htree_type type, size_t idx, + uint8_t vers, size_t *offs, size_t *size) +{ + const size_t node_size = sizeof(struct tee_fs_htree_node_image); + const size_t block_nodes = BLOCK_SIZE / (node_size * 2); + size_t pbn; + size_t bidx; + + assert(vers == 0 || vers == 1); + + /* + * File layout + * [demo with input: + * BLOCK_SIZE = 4096, + * node_size = 66, + * block_nodes = 4096/(66*2) = 31 ] + * + * phys block 0: + * tee_fs_htree_image vers 0 @ offs = 0 + * tee_fs_htree_image vers 1 @ offs = sizeof(tee_fs_htree_image) + * + * phys block 1: + * tee_fs_htree_node_image 0 vers 0 @ offs = 0 + * tee_fs_htree_node_image 0 vers 1 @ offs = node_size + * tee_fs_htree_node_image 1 vers 0 @ offs = node_size * 2 + * tee_fs_htree_node_image 1 vers 1 @ offs = node_size * 3 + * ... + * tee_fs_htree_node_image 30 vers 0 @ offs = node_size * 60 + * tee_fs_htree_node_image 30 vers 1 @ offs = node_size * 61 + * + * phys block 2: + * data block 0 vers 0 + * + * phys block 3: + * data block 0 vers 1 + * + * ... + * phys block 62: + * data block 30 vers 0 + * + * phys block 63: + * data block 30 vers 1 + * + * phys block 64: + * tee_fs_htree_node_image 31 vers 0 @ offs = 0 + * tee_fs_htree_node_image 31 vers 1 @ offs = node_size + * tee_fs_htree_node_image 32 vers 0 @ offs = node_size * 2 + * tee_fs_htree_node_image 32 vers 1 @ offs = node_size * 3 + * ... + * tee_fs_htree_node_image 61 vers 0 @ offs = node_size * 60 + * tee_fs_htree_node_image 61 vers 1 @ offs = node_size * 61 + * + * phys block 65: + * data block 31 vers 0 + * + * phys block 66: + * data block 31 vers 1 + * ... + */ + + switch (type) { + case TEE_FS_HTREE_TYPE_HEAD: + *offs = sizeof(struct tee_fs_htree_image) * vers; + *size = sizeof(struct tee_fs_htree_image); + return TEE_SUCCESS; + case TEE_FS_HTREE_TYPE_NODE: + pbn = 1 + ((idx / block_nodes) * block_nodes * 2); + *offs = pbn * BLOCK_SIZE + + 2 * node_size * (idx % block_nodes) + + node_size * vers; + *size = node_size; + return TEE_SUCCESS; + case TEE_FS_HTREE_TYPE_BLOCK: + bidx = 2 * idx + vers; + pbn = 2 + bidx + bidx / (block_nodes * 2 - 1); + *offs = pbn * BLOCK_SIZE; + *size = BLOCK_SIZE; + return TEE_SUCCESS; + default: + return TEE_ERROR_GENERIC; + } +} + +static TEE_Result ree_fs_rpc_read_init(void *aux, + struct tee_fs_rpc_operation *op, + enum tee_fs_htree_type type, size_t idx, + uint8_t vers, void **data) +{ + struct tee_fs_fd *fdp = aux; + TEE_Result res; + size_t offs; + size_t size; + + res = get_offs_size(type, idx, vers, &offs, &size); + if (res != TEE_SUCCESS) + return res; + + return tee_fs_rpc_read_init(op, OPTEE_RPC_CMD_FS, fdp->fd, + offs, size, data); +} + +static TEE_Result ree_fs_rpc_write_init(void *aux, + struct tee_fs_rpc_operation *op, + enum tee_fs_htree_type type, size_t idx, + uint8_t vers, void **data) +{ + struct tee_fs_fd *fdp = aux; + TEE_Result res; + size_t offs; + size_t size; + + res = get_offs_size(type, idx, vers, &offs, &size); + if (res != TEE_SUCCESS) + return res; + + return tee_fs_rpc_write_init(op, OPTEE_RPC_CMD_FS, fdp->fd, + offs, size, data); +} + +static const struct tee_fs_htree_storage ree_fs_storage_ops = { + .block_size = BLOCK_SIZE, + .rpc_read_init = ree_fs_rpc_read_init, + .rpc_read_final = tee_fs_rpc_read_final, + .rpc_write_init = ree_fs_rpc_write_init, + .rpc_write_final = tee_fs_rpc_write_final, +}; + +static TEE_Result ree_fs_ftruncate_internal(struct tee_fs_fd *fdp, + tee_fs_off_t new_file_len) +{ + TEE_Result res; + struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht); + + if ((size_t)new_file_len > meta->length) { + size_t ext_len = new_file_len - meta->length; + + res = out_of_place_write(fdp, meta->length, NULL, ext_len); + if (res != TEE_SUCCESS) + return res; + } else { + size_t offs; + size_t sz; + + res = get_offs_size(TEE_FS_HTREE_TYPE_BLOCK, + ROUNDUP(new_file_len, BLOCK_SIZE) / + BLOCK_SIZE, 1, &offs, &sz); + if (res != TEE_SUCCESS) + return res; + + res = tee_fs_htree_truncate(&fdp->ht, + new_file_len / BLOCK_SIZE); + if (res != TEE_SUCCESS) + return res; + + res = tee_fs_rpc_truncate(OPTEE_RPC_CMD_FS, fdp->fd, + offs + sz); + if (res != TEE_SUCCESS) + return res; + + meta->length = new_file_len; + tee_fs_htree_meta_set_dirty(fdp->ht); + } + + return TEE_SUCCESS; +} + +static TEE_Result ree_fs_read_primitive(struct tee_file_handle *fh, size_t pos, + void *buf, size_t *len) +{ + TEE_Result res; + int start_block_num; + int end_block_num; + size_t remain_bytes; + uint8_t *data_ptr = buf; + uint8_t *block = NULL; + struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; + struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht); + + remain_bytes = *len; + if ((pos + remain_bytes) < remain_bytes || pos > meta->length) + remain_bytes = 0; + else if (pos + remain_bytes > meta->length) + remain_bytes = meta->length - pos; + + *len = remain_bytes; + + if (!remain_bytes) { + res = TEE_SUCCESS; + goto exit; + } + + start_block_num = pos_to_block_num(pos); + end_block_num = pos_to_block_num(pos + remain_bytes - 1); + + block = get_tmp_block(); + if (!block) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + while (start_block_num <= end_block_num) { + size_t offset = pos % BLOCK_SIZE; + size_t size_to_read = MIN(remain_bytes, (size_t)BLOCK_SIZE); + + if (size_to_read + offset > BLOCK_SIZE) + size_to_read = BLOCK_SIZE - offset; + + res = tee_fs_htree_read_block(&fdp->ht, start_block_num, block); + if (res != TEE_SUCCESS) + goto exit; + + memcpy(data_ptr, block + offset, size_to_read); + + data_ptr += size_to_read; + remain_bytes -= size_to_read; + pos += size_to_read; + + start_block_num++; + } + res = TEE_SUCCESS; +exit: + if (block) + put_tmp_block(block); + return res; +} + +static TEE_Result ree_fs_read(struct tee_file_handle *fh, size_t pos, + void *buf, size_t *len) +{ + TEE_Result res; + + mutex_lock(&ree_fs_mutex); + res = ree_fs_read_primitive(fh, pos, buf, len); + mutex_unlock(&ree_fs_mutex); + + return res; +} + +static TEE_Result ree_fs_write_primitive(struct tee_file_handle *fh, size_t pos, + const void *buf, size_t len) +{ + TEE_Result res; + struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; + size_t file_size; + + if (!len) + return TEE_SUCCESS; + + file_size = tee_fs_htree_get_meta(fdp->ht)->length; + + if ((pos + len) < len) + return TEE_ERROR_BAD_PARAMETERS; + + if (file_size < pos) { + res = ree_fs_ftruncate_internal(fdp, pos); + if (res != TEE_SUCCESS) + return res; + } + + return out_of_place_write(fdp, pos, buf, len); +} + +static TEE_Result ree_fs_open_primitive(bool create, uint8_t *hash, + const TEE_UUID *uuid, + struct tee_fs_dirfile_fileh *dfh, + struct tee_file_handle **fh) +{ + TEE_Result res; + struct tee_fs_fd *fdp; + + fdp = calloc(1, sizeof(struct tee_fs_fd)); + if (!fdp) + return TEE_ERROR_OUT_OF_MEMORY; + fdp->fd = -1; + fdp->uuid = uuid; + + if (create) + res = tee_fs_rpc_create_dfh(OPTEE_RPC_CMD_FS, + dfh, &fdp->fd); + else + res = tee_fs_rpc_open_dfh(OPTEE_RPC_CMD_FS, dfh, &fdp->fd); + + if (res != TEE_SUCCESS) + goto out; + + res = tee_fs_htree_open(create, hash, uuid, &ree_fs_storage_ops, + fdp, &fdp->ht); +out: + if (res == TEE_SUCCESS) { + if (dfh) + fdp->dfh = *dfh; + else + fdp->dfh.idx = -1; + *fh = (struct tee_file_handle *)fdp; + } else { + if (res == TEE_ERROR_SECURITY) + DMSG("Secure storage corruption detected"); + if (fdp->fd != -1) + tee_fs_rpc_close(OPTEE_RPC_CMD_FS, fdp->fd); + if (create) + tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, dfh); + free(fdp); + } + + return res; +} + +static void ree_fs_close_primitive(struct tee_file_handle *fh) +{ + struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; + + if (fdp) { + tee_fs_htree_close(&fdp->ht); + tee_fs_rpc_close(OPTEE_RPC_CMD_FS, fdp->fd); + free(fdp); + } +} + +static TEE_Result ree_dirf_commit_writes(struct tee_file_handle *fh, + uint8_t *hash) +{ + TEE_Result res; + struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; + + res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash); + + if (!res && hash) + memcpy(hash, fdp->dfh.hash, sizeof(fdp->dfh.hash)); + + return res; +} + +static const struct tee_fs_dirfile_operations ree_dirf_ops = { + .open = ree_fs_open_primitive, + .close = ree_fs_close_primitive, + .read = ree_fs_read_primitive, + .write = ree_fs_write_primitive, + .commit_writes = ree_dirf_commit_writes, +}; + +static struct tee_fs_dirfile_dirh *ree_fs_dirh; +static size_t ree_fs_dirh_refcount; + +#ifdef CFG_REE_FS_INTEGRITY_RPMB +static struct tee_file_handle *ree_fs_rpmb_fh; +const struct tee_file_operations *rpmb_ops; + +static TEE_Result open_dirh(struct tee_fs_dirfile_dirh **dirh) +{ + TEE_Result res; + uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; + uint8_t *hashp = NULL; + const char fname[] = "dirfile.db.hash"; + TEE_Result (*rpmb_fs_raw_open)(const char *, bool, + struct tee_file_handle **); + +#ifdef CFG_RPMB_FS + rpmb_fs_raw_open = tee_rpmb_fs_raw_open; + rpmb_ops = &rpmb_fs_ops; +#elif defined CFG_NVME_RPMB_FS + rpmb_fs_raw_open = tee_nvme_rpmb_fs_raw_open; + rpmb_ops = &nvme_rpmb_fs_ops; +#else + assert(0); +#endif + + res = (*rpmb_fs_raw_open)(fname, false, &ree_fs_rpmb_fh); + if (!res) { + size_t l = sizeof(hash); + + res = rpmb_ops->read(ree_fs_rpmb_fh, 0, hash, &l); + if (res) + return res; + if (l == sizeof(hash)) + hashp = hash; + } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { + res = (*rpmb_fs_raw_open)(fname, true, &ree_fs_rpmb_fh); + } + if (res) + return res; + + res = tee_fs_dirfile_open(false, hashp, &ree_dirf_ops, dirh); + + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + if (hashp) { + if (IS_ENABLED(CFG_REE_FS_ALLOW_RESET)) { + DMSG("dirf.db not found, clear hash in RPMB"); + res = rpmb_ops->truncate(ree_fs_rpmb_fh, 0); + if (res) { + DMSG("Can't clear hash: %#"PRIx32, res); + res = TEE_ERROR_SECURITY; + goto out; + } + } else { + DMSG("dirf.db file not found"); + res = TEE_ERROR_SECURITY; + goto out; + } + } + + res = tee_fs_dirfile_open(true, NULL, &ree_dirf_ops, dirh); + } + +out: + if (res) + rpmb_ops->close(&ree_fs_rpmb_fh); + + return res; +} + +static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh) +{ + TEE_Result res; + uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; + + res = tee_fs_dirfile_commit_writes(dirh, hash); + if (res) + return res; + return rpmb_ops->write(ree_fs_rpmb_fh, 0, hash, sizeof(hash)); +} + +static void close_dirh(struct tee_fs_dirfile_dirh **dirh) +{ + tee_fs_dirfile_close(*dirh); + *dirh = NULL; + rpmb_ops->close(&ree_fs_rpmb_fh); +} + +#else /*!CFG_REE_FS_INTEGRITY_RPMB*/ +static TEE_Result open_dirh(struct tee_fs_dirfile_dirh **dirh) +{ + TEE_Result res; + + res = tee_fs_dirfile_open(false, NULL, &ree_dirf_ops, dirh); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return tee_fs_dirfile_open(true, NULL, &ree_dirf_ops, dirh); + + return res; +} + +static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh) +{ + return tee_fs_dirfile_commit_writes(dirh, NULL); +} + +static void close_dirh(struct tee_fs_dirfile_dirh **dirh) +{ + tee_fs_dirfile_close(*dirh); + *dirh = NULL; +} +#endif /*!CFG_REE_FS_INTEGRITY_RPMB*/ + +static TEE_Result get_dirh(struct tee_fs_dirfile_dirh **dirh) +{ + if (!ree_fs_dirh) { + TEE_Result res = open_dirh(&ree_fs_dirh); + + if (res) { + *dirh = NULL; + return res; + } + } + ree_fs_dirh_refcount++; + assert(ree_fs_dirh); + assert(ree_fs_dirh_refcount); + *dirh = ree_fs_dirh; + return TEE_SUCCESS; +} + +static void put_dirh_primitive(bool close) +{ + assert(ree_fs_dirh_refcount); + + /* + * During the execution of one of the ree_fs_ops ree_fs_dirh is + * guareteed to be a valid pointer. But when the fop has returned + * another thread may get an error or something causing that fop + * to do a put with close=1. + * + * For all fops but ree_fs_close() there's a call to get_dirh() to + * get a new dirh which will open it again if it was closed before. + * But in the ree_fs_close() case there's no call to get_dirh() + * only to this function, put_dirh_primitive(), and in this case + * ree_fs_dirh may actually be NULL. + */ + ree_fs_dirh_refcount--; + if (ree_fs_dirh && (!ree_fs_dirh_refcount || close)) + close_dirh(&ree_fs_dirh); +} + +static void put_dirh(struct tee_fs_dirfile_dirh *dirh, bool close) +{ + if (dirh) { + assert(dirh == ree_fs_dirh); + put_dirh_primitive(close); + } +} + +static TEE_Result ree_fs_open(struct tee_pobj *po, size_t *size, + struct tee_file_handle **fh) +{ + TEE_Result res; + struct tee_fs_dirfile_dirh *dirh = NULL; + struct tee_fs_dirfile_fileh dfh; + + mutex_lock(&ree_fs_mutex); + + res = get_dirh(&dirh); + if (res != TEE_SUCCESS) + goto out; + + res = tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len, + &dfh); + if (res != TEE_SUCCESS) + goto out; + + res = ree_fs_open_primitive(false, dfh.hash, &po->uuid, &dfh, fh); + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + /* + * If the object isn't found someone has tampered with it, + * treat it as corrupt. + */ + res = TEE_ERROR_CORRUPT_OBJECT; + } else if (!res && size) { + struct tee_fs_fd *fdp = (struct tee_fs_fd *)*fh; + + *size = tee_fs_htree_get_meta(fdp->ht)->length; + } + +out: + if (res) + put_dirh(dirh, true); + mutex_unlock(&ree_fs_mutex); + + return res; +} + +static TEE_Result set_name(struct tee_fs_dirfile_dirh *dirh, + struct tee_fs_fd *fdp, struct tee_pobj *po, + bool overwrite) +{ + TEE_Result res; + bool have_old_dfh = false; + struct tee_fs_dirfile_fileh old_dfh = { .idx = -1 }; + + res = tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len, + &old_dfh); + if (!overwrite && !res) + return TEE_ERROR_ACCESS_CONFLICT; + + if (!res) + have_old_dfh = true; + + /* + * If old_dfh wasn't found, the idx will be -1 and + * tee_fs_dirfile_rename() will allocate a new index. + */ + fdp->dfh.idx = old_dfh.idx; + old_dfh.idx = -1; + res = tee_fs_dirfile_rename(dirh, &po->uuid, &fdp->dfh, + po->obj_id, po->obj_id_len); + if (res) + return res; + + res = commit_dirh_writes(dirh); + if (res) + return res; + + if (have_old_dfh) + tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, &old_dfh); + + return TEE_SUCCESS; +} + +static void ree_fs_close(struct tee_file_handle **fh) +{ + if (*fh) { + mutex_lock(&ree_fs_mutex); + put_dirh_primitive(false); + ree_fs_close_primitive(*fh); + *fh = NULL; + mutex_unlock(&ree_fs_mutex); + + } +} + +static TEE_Result ree_fs_create(struct tee_pobj *po, bool overwrite, + const void *head, size_t head_size, + const void *attr, size_t attr_size, + const void *data, size_t data_size, + struct tee_file_handle **fh) +{ + struct tee_fs_fd *fdp; + struct tee_fs_dirfile_dirh *dirh = NULL; + struct tee_fs_dirfile_fileh dfh; + TEE_Result res; + size_t pos = 0; + + *fh = NULL; + mutex_lock(&ree_fs_mutex); + + res = get_dirh(&dirh); + if (res) + goto out; + + res = tee_fs_dirfile_get_tmp(dirh, &dfh); + if (res) + goto out; + + res = ree_fs_open_primitive(true, dfh.hash, &po->uuid, &dfh, fh); + if (res) + goto out; + + if (head && head_size) { + res = ree_fs_write_primitive(*fh, pos, head, head_size); + if (res) + goto out; + pos += head_size; + } + + if (attr && attr_size) { + res = ree_fs_write_primitive(*fh, pos, attr, attr_size); + if (res) + goto out; + pos += attr_size; + } + + if (data && data_size) { + res = ree_fs_write_primitive(*fh, pos, data, data_size); + if (res) + goto out; + } + + fdp = (struct tee_fs_fd *)*fh; + res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash); + if (res) + goto out; + + res = set_name(dirh, fdp, po, overwrite); +out: + if (res) { + put_dirh(dirh, true); + if (*fh) { + ree_fs_close_primitive(*fh); + *fh = NULL; + tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, &dfh); + } + } + mutex_unlock(&ree_fs_mutex); + + return res; +} + +static TEE_Result ree_fs_write(struct tee_file_handle *fh, size_t pos, + const void *buf, size_t len) +{ + TEE_Result res; + struct tee_fs_dirfile_dirh *dirh = NULL; + struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; + + mutex_lock(&ree_fs_mutex); + + res = get_dirh(&dirh); + if (res) + goto out; + + res = ree_fs_write_primitive(fh, pos, buf, len); + if (res) + goto out; + + res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash); + if (res) + goto out; + + res = tee_fs_dirfile_update_hash(dirh, &fdp->dfh); + if (res) + goto out; + res = commit_dirh_writes(dirh); +out: + put_dirh(dirh, res); + mutex_unlock(&ree_fs_mutex); + + return res; +} + +static TEE_Result ree_fs_rename(struct tee_pobj *old, struct tee_pobj *new, + bool overwrite) +{ + TEE_Result res; + struct tee_fs_dirfile_dirh *dirh = NULL; + struct tee_fs_dirfile_fileh dfh; + struct tee_fs_dirfile_fileh remove_dfh = { .idx = -1 }; + + if (!new) + return TEE_ERROR_BAD_PARAMETERS; + + mutex_lock(&ree_fs_mutex); + res = get_dirh(&dirh); + if (res) + goto out; + + res = tee_fs_dirfile_find(dirh, &new->uuid, new->obj_id, + new->obj_id_len, &remove_dfh); + if (!res && !overwrite) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto out; + } + + res = tee_fs_dirfile_find(dirh, &old->uuid, old->obj_id, + old->obj_id_len, &dfh); + if (res) + goto out; + + res = tee_fs_dirfile_rename(dirh, &new->uuid, &dfh, new->obj_id, + new->obj_id_len); + if (res) + goto out; + + if (remove_dfh.idx != -1) { + res = tee_fs_dirfile_remove(dirh, &remove_dfh); + if (res) + goto out; + } + + res = commit_dirh_writes(dirh); + if (res) + goto out; + + if (remove_dfh.idx != -1) + tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, &remove_dfh); + +out: + put_dirh(dirh, res); + mutex_unlock(&ree_fs_mutex); + + return res; + +} + +static TEE_Result ree_fs_remove(struct tee_pobj *po) +{ + TEE_Result res; + struct tee_fs_dirfile_dirh *dirh = NULL; + struct tee_fs_dirfile_fileh dfh; + + mutex_lock(&ree_fs_mutex); + res = get_dirh(&dirh); + if (res) + goto out; + + res = tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len, + &dfh); + if (res) + goto out; + + res = tee_fs_dirfile_remove(dirh, &dfh); + if (res) + goto out; + + res = commit_dirh_writes(dirh); + if (res) + goto out; + + tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, &dfh); + + assert(tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len, + &dfh)); +out: + put_dirh(dirh, res); + mutex_unlock(&ree_fs_mutex); + + return res; +} + +static TEE_Result ree_fs_truncate(struct tee_file_handle *fh, size_t len) +{ + TEE_Result res; + struct tee_fs_dirfile_dirh *dirh = NULL; + struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; + + mutex_lock(&ree_fs_mutex); + + res = get_dirh(&dirh); + if (res) + goto out; + + res = ree_fs_ftruncate_internal(fdp, len); + if (res) + goto out; + + res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash); + if (res) + goto out; + + res = tee_fs_dirfile_update_hash(dirh, &fdp->dfh); + if (res) + goto out; + res = commit_dirh_writes(dirh); +out: + put_dirh(dirh, res); + mutex_unlock(&ree_fs_mutex); + + return res; +} + +static TEE_Result ree_fs_opendir_rpc(const TEE_UUID *uuid, + struct tee_fs_dir **dir) + +{ + TEE_Result res; + struct tee_fs_dir *d = calloc(1, sizeof(*d)); + + if (!d) + return TEE_ERROR_OUT_OF_MEMORY; + + d->uuid = uuid; + + mutex_lock(&ree_fs_mutex); + + res = get_dirh(&d->dirh); + if (res) + goto out; + + /* See that there's at least one file */ + d->idx = -1; + d->d.oidlen = sizeof(d->d.oid); + res = tee_fs_dirfile_get_next(d->dirh, d->uuid, &d->idx, d->d.oid, + &d->d.oidlen); + d->idx = -1; + +out: + if (!res) { + *dir = d; + } else { + if (d) + put_dirh(d->dirh, false); + free(d); + } + mutex_unlock(&ree_fs_mutex); + + return res; +} + +static void ree_fs_closedir_rpc(struct tee_fs_dir *d) +{ + if (d) { + mutex_lock(&ree_fs_mutex); + + put_dirh(d->dirh, false); + free(d); + + mutex_unlock(&ree_fs_mutex); + } +} + +static TEE_Result ree_fs_readdir_rpc(struct tee_fs_dir *d, + struct tee_fs_dirent **ent) +{ + TEE_Result res; + + mutex_lock(&ree_fs_mutex); + + d->d.oidlen = sizeof(d->d.oid); + res = tee_fs_dirfile_get_next(d->dirh, d->uuid, &d->idx, d->d.oid, + &d->d.oidlen); + if (res == TEE_SUCCESS) + *ent = &d->d; + + mutex_unlock(&ree_fs_mutex); + + return res; +} + +const struct tee_file_operations ree_fs_ops = { + .open = ree_fs_open, + .create = ree_fs_create, + .close = ree_fs_close, + .read = ree_fs_read, + .write = ree_fs_write, + .truncate = ree_fs_truncate, + .rename = ree_fs_rename, + .remove = ree_fs_remove, + .opendir = ree_fs_opendir_rpc, + .closedir = ree_fs_closedir_rpc, + .readdir = ree_fs_readdir_rpc, +}; diff --git a/optee/optee_os/core/tee/tee_rpmb_fs.c b/optee/optee_os/core/tee/tee_rpmb_fs.c new file mode 100644 index 0000000..74fce5b --- /dev/null +++ b/optee/optee_os/core/tee/tee_rpmb_fs.c @@ -0,0 +1,3108 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#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 +#include + +#define RPMB_STORAGE_START_ADDRESS 0 +#define RPMB_FS_FAT_START_ADDRESS 512 +#define RPMB_BLOCK_SIZE_SHIFT 8 +#define RPMB_CID_PRV_OFFSET 9 +#define RPMB_CID_CRC_OFFSET 15 + +#define RPMB_FS_MAGIC 0x52504D42 +#define FS_VERSION 2 + +#define FILE_IS_ACTIVE (1u << 0) +#define FILE_IS_LAST_ENTRY (1u << 1) + +#define TEE_RPMB_FS_FILENAME_LENGTH 224 + +#define TMP_BLOCK_SIZE 4096U + +#define RPMB_MAX_RETRIES 10 + +/** + * Utilized when caching is enabled, i.e., when CFG_RPMB_FS_CACHE_ENTRIES > 0. + * Cache size + the number of entries that are repeatedly read in and buffered + * once the cache is full. + */ +#define RPMB_BUF_MAX_ENTRIES (CFG_RPMB_FS_CACHE_ENTRIES + \ + CFG_RPMB_FS_RD_ENTRIES) + +/** + * 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; + uint32_t max_rpmb_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; + uint8_t fek[TEE_FS_KM_FEK_SIZE]; + char filename[TEE_RPMB_FS_FILENAME_LENGTH]; +}; + +/** + * Structure that describes buffered/cached FAT FS entries in RPMB storage. + * This structure is used in functions traversing the FAT FS. + */ +struct rpmb_fat_entry_dir { + /* + * Buffer storing the FAT FS entries read in from RPMB storage. It + * includes the optional cache entries (CFG_RPMB_FS_CACHE_ENTRIES) + * and entries temporary read for current FAT FS traversal + * (CFG_RPMB_FS_RD_ENTRIES) when not found from cached entries. + */ + struct rpmb_fat_entry *rpmb_fat_entry_buf; + /* Current index of FAT FS entry to read from buffer. */ + uint32_t idx_curr; + /* Total number of FAT FS entries in buffer. */ + uint32_t num_buffered; + /* Total number of FAT FS entries read during traversal. */ + uint32_t num_total_read; + /* Indicates that last FAT FS entry was read. */ + bool last_reached; +}; + +/** + * FAT entry context with reference to a FAT entry and its + * location in RPMB. + */ +struct rpmb_file_handle { + struct rpmb_fat_entry fat_entry; + const TEE_UUID *uuid; + char filename[TEE_RPMB_FS_FILENAME_LENGTH]; + /* Address 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]; +}; + +/** + * A node in a list of directory entries. + */ +struct tee_rpmb_fs_dirent { + struct tee_fs_dirent entry; + SIMPLEQ_ENTRY(tee_rpmb_fs_dirent) link; +}; + +/** + * The RPMB directory representation. It contains a queue of + * RPMB directory entries: 'next'. + * The current pointer points to the last directory entry + * returned by readdir(). + */ +struct tee_fs_dir { + struct tee_rpmb_fs_dirent *current; + /* */ + SIMPLEQ_HEAD(next_head, tee_rpmb_fs_dirent) next; +}; + +static struct rpmb_fs_parameters *fs_par; +static struct rpmb_fat_entry_dir *fat_entry_dir; + +/* + * Lower interface to RPMB device + */ + +#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; + uint16_t block_count; + /* 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. + * @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 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; + +/* If set to true, don't try to access RPMB until rebooted */ +static bool rpmb_dead; + +/* + * Mutex to serialize the operations exported by this file. + * It protects rpmb_ctx and prevents overlapping operations on eMMC devices with + * different IDs. + */ +static struct mutex rpmb_mutex = MUTEX_INITIALIZER; + +#ifdef CFG_RPMB_TESTKEY + +static const uint8_t rpmb_test_key[RPMB_KEY_MAC_SIZE] = { + 0xD3, 0xEB, 0x3E, 0xC3, 0x6E, 0x33, 0x4C, 0x9F, + 0x98, 0x8C, 0xE2, 0xC0, 0xB8, 0x59, 0x54, 0x61, + 0x0D, 0x2B, 0xCF, 0x86, 0x64, 0x84, 0x4D, 0xF2, + 0xAB, 0x56, 0xE6, 0xC6, 0x1B, 0xB7, 0x01, 0xE4 +}; + +static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused, + uint8_t *key, uint32_t len) +{ + TEE_Result res = TEE_SUCCESS; + + if (!key || RPMB_KEY_MAC_SIZE != len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + DMSG("RPMB: Using test key"); + memcpy(key, rpmb_test_key, RPMB_KEY_MAC_SIZE); + +out: + return res; +} + +#else /* !CFG_RPMB_TESTKEY */ + +#ifdef CFG_RPMB_KEY_HAS_PROVISIONED +static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused, + uint8_t *key, uint32_t len) +{ + if (!key || RPMB_KEY_MAC_SIZE != len) + return TEE_ERROR_BAD_PARAMETERS; + + IMSG("RPMB: Using pre-generated key"); + return tee_otp_get_rpmb_key(key, len); +} +#else +static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused, + uint8_t *key, uint32_t len) +{ + uint8_t message[RPMB_EMMC_CID_SIZE]; + + if (!key || RPMB_KEY_MAC_SIZE != len) + return TEE_ERROR_BAD_PARAMETERS; + + IMSG("RPMB: Using generated key"); + + /* + * PRV/CRC would be changed when doing eMMC FFU + * The following fields should be masked off when deriving RPMB key + * + * CID [55: 48]: PRV (Product revision) + * CID [07: 01]: CRC (CRC7 checksum) + * CID [00]: not used + */ + memcpy(message, rpmb_ctx->cid, RPMB_EMMC_CID_SIZE); + memset(message + RPMB_CID_PRV_OFFSET, 0, 1); + memset(message + RPMB_CID_CRC_OFFSET, 0, 1); + return huk_subkey_derive(HUK_SUBKEY_RPMB, message, sizeof(message), + key, len); +} +#endif /* CFG_RPMB_KEY_HAS_PROVISIONED */ + +#endif /* !CFG_RPMB_TESTKEY */ + +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 void get_op_result_bits(uint8_t *bytes, uint8_t *res) +{ + *res = *(bytes + 1) & RPMB_RESULT_MASK; +} + +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; + void *ctx = NULL; + + if (!mac || !key || !datafrms) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); + if (res) + return res; + + res = crypto_mac_init(ctx, key, keysize); + if (res != TEE_SUCCESS) + goto func_exit; + + for (i = 0; i < blkcnt; i++) { + res = crypto_mac_update(ctx, datafrms[i].data, + RPMB_MAC_PROTECT_DATA_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + } + + res = crypto_mac_final(ctx, mac, macsize); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + crypto_mac_free_ctx(ctx); + return res; +} + +struct tee_rpmb_mem { + struct mobj *phreq_mobj; + struct mobj *phresp_mobj; + size_t req_size; + size_t resp_size; +}; + +static void tee_rpmb_free(struct tee_rpmb_mem *mem) +{ + if (!mem) + return; + + if (mem->phreq_mobj) { + thread_rpc_free_payload(mem->phreq_mobj); + mem->phreq_mobj = NULL; + } + if (mem->phresp_mobj) { + thread_rpc_free_payload(mem->phresp_mobj); + mem->phresp_mobj = NULL; + } +} + + +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 = ROUNDUP(req_size, sizeof(uint32_t)); + size_t resp_s = ROUNDUP(resp_size, sizeof(uint32_t)); + + if (!mem) + return TEE_ERROR_BAD_PARAMETERS; + + memset(mem, 0, sizeof(*mem)); + + mem->phreq_mobj = thread_rpc_alloc_payload(req_s); + mem->phresp_mobj = thread_rpc_alloc_payload(resp_s); + + if (!mem->phreq_mobj || !mem->phresp_mobj) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + *req = mobj_get_va(mem->phreq_mobj, 0, req_s); + *resp = mobj_get_va(mem->phresp_mobj, 0, resp_s); + if (!*req || !*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 thread_param params[2] = { + [0] = THREAD_PARAM_MEMREF(IN, mem->phreq_mobj, 0, + mem->req_size), + [1] = THREAD_PARAM_MEMREF(OUT, mem->phresp_mobj, 0, + mem->resp_size), + }; + + return thread_rpc_cmd(OPTEE_RPC_CMD_RPMB, 2, params); +} + +static bool is_zero(const uint8_t *buf, size_t size) +{ + size_t i; + + for (i = 0; i < size; i++) + if (buf[i]) + return false; + return true; +} + +static TEE_Result encrypt_block(uint8_t *out, const uint8_t *in, + uint16_t blk_idx, const uint8_t *fek, + const TEE_UUID *uuid) +{ + return tee_fs_crypt_block(uuid, out, in, RPMB_DATA_SIZE, + blk_idx, fek, TEE_MODE_ENCRYPT); +} + +static TEE_Result decrypt_block(uint8_t *out, const uint8_t *in, + uint16_t blk_idx, const uint8_t *fek, + const TEE_UUID *uuid) +{ + return tee_fs_crypt_block(uuid, out, in, RPMB_DATA_SIZE, + blk_idx, fek, TEE_MODE_DECRYPT); +} + +/* Decrypt/copy at most one block of data */ +static TEE_Result decrypt(uint8_t *out, const struct rpmb_data_frame *frm, + size_t size, size_t offset, + uint16_t blk_idx __maybe_unused, const uint8_t *fek, + const TEE_UUID *uuid) +{ + uint8_t *tmp __maybe_unused; + TEE_Result res = TEE_SUCCESS; + + + if ((size + offset < size) || (size + offset > RPMB_DATA_SIZE)) + panic("invalid size or offset"); + + if (!fek) { + /* Block is not encrypted (not a file data block) */ + memcpy(out, frm->data + offset, size); + } else if (is_zero(fek, TEE_FS_KM_FEK_SIZE)) { + /* The file was created with encryption disabled */ + return TEE_ERROR_SECURITY; + } else { + /* Block is encrypted */ + if (size < RPMB_DATA_SIZE) { + /* + * Since output buffer is not large enough to hold one + * block we must allocate a temporary buffer. + */ + tmp = malloc(RPMB_DATA_SIZE); + if (!tmp) + return TEE_ERROR_OUT_OF_MEMORY; + res = decrypt_block(tmp, frm->data, blk_idx, fek, uuid); + if (res == TEE_SUCCESS) + memcpy(out, tmp + offset, size); + free(tmp); + } else { + res = decrypt_block(out, frm->data, blk_idx, fek, uuid); + } + } + + return res; +} + +static TEE_Result tee_rpmb_req_pack(struct rpmb_req *req, + struct rpmb_raw_data *rawdata, + uint16_t nbr_frms, uint16_t dev_id, + const uint8_t *fek, const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int i; + struct rpmb_data_frame *datafrm; + + if (!req || !rawdata || !nbr_frms) + 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("wr_blkcnt(%d) > rel_wr_blkcnt(%d)", 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) + 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) + u16_to_bytes(*rawdata->block_count, + datafrm[i].block_count); + + if (rawdata->blk_idx) { + /* Check the block index is within range. */ + if ((*rawdata->blk_idx + nbr_frms - 1) > + 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) + u32_to_bytes(*rawdata->write_counter, + datafrm[i].write_counter); + + if (rawdata->nonce) + memcpy(datafrm[i].nonce, rawdata->nonce, + RPMB_NONCE_SIZE); + + if (rawdata->data) { + if (fek) { + res = encrypt_block(datafrm[i].data, + rawdata->data + + (i * RPMB_DATA_SIZE), + *rawdata->blk_idx + i, + fek, uuid); + if (res != TEE_SUCCESS) + goto func_exit; + } else { + memcpy(datafrm[i].data, + rawdata->data + (i * RPMB_DATA_SIZE), + RPMB_DATA_SIZE); + } + } + } + + if (rawdata->key_mac) { + 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); + + if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) { + for (i = 0; i < nbr_frms; i++) { + DMSG("Dumping data frame %d:", i); + DHEXDUMP((uint8_t *)&datafrm[i] + RPMB_STUFF_DATA_SIZE, + 512 - RPMB_STUFF_DATA_SIZE); + } + } + + res = TEE_SUCCESS; +func_exit: + free(datafrm); + return res; +} + +static TEE_Result data_cpy_mac_calc_1b(struct rpmb_raw_data *rawdata, + struct rpmb_data_frame *frm, + const uint8_t *fek, const TEE_UUID *uuid) +{ + TEE_Result res; + uint8_t *data; + uint16_t idx; + + if (rawdata->len + rawdata->byte_offset > RPMB_DATA_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_rpmb_mac_calc(rawdata->key_mac, RPMB_KEY_MAC_SIZE, + rpmb_ctx->key, RPMB_KEY_MAC_SIZE, frm, 1); + if (res != TEE_SUCCESS) + return res; + + data = rawdata->data; + bytes_to_u16(frm->address, &idx); + + res = decrypt(data, frm, rawdata->len, rawdata->byte_offset, idx, fek, + uuid); + 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, + const uint8_t *fek, + const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int i; + void *ctx = NULL; + uint16_t offset; + uint32_t size; + uint8_t *data; + uint16_t start_idx; + struct rpmb_data_frame localfrm; + + if (!datafrm || !rawdata || !nbr_frms || !lastfrm) + return TEE_ERROR_BAD_PARAMETERS; + + if (nbr_frms == 1) + return data_cpy_mac_calc_1b(rawdata, lastfrm, fek, uuid); + + /* nbr_frms > 1 */ + + data = rawdata->data; + + res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); + if (res) + goto func_exit; + + res = crypto_mac_init(ctx, rpmb_ctx->key, RPMB_KEY_MAC_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + /* + * Note: JEDEC JESD84-B51: "In every packet the address is the start + * address of the full access (not address of the individual half a + * sector)" + */ + bytes_to_u16(lastfrm->address, &start_idx); + + for (i = 0; i < (nbr_frms - 1); i++) { + + /* + * By working on a local copy of the RPMB frame, we ensure that + * the data can not be modified after the MAC is computed but + * before the payload is decrypted/copied to the output buffer. + */ + memcpy(&localfrm, &datafrm[i], RPMB_DATA_FRAME_SIZE); + + res = crypto_mac_update(ctx, localfrm.data, + RPMB_MAC_PROTECT_DATA_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + if (i == 0) { + /* First block */ + offset = rawdata->byte_offset; + size = RPMB_DATA_SIZE - offset; + } else { + /* Middle blocks */ + size = RPMB_DATA_SIZE; + offset = 0; + } + + res = decrypt(data, &localfrm, size, offset, start_idx + i, + fek, uuid); + if (res != TEE_SUCCESS) + goto func_exit; + + data += size; + } + + /* Last block */ + size = (rawdata->len + rawdata->byte_offset) % RPMB_DATA_SIZE; + if (size == 0) + size = RPMB_DATA_SIZE; + res = decrypt(data, lastfrm, size, 0, start_idx + nbr_frms - 1, fek, + uuid); + if (res != TEE_SUCCESS) + goto func_exit; + + /* Update MAC against the last block */ + res = crypto_mac_update(ctx, lastfrm->data, RPMB_MAC_PROTECT_DATA_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + res = crypto_mac_final(ctx, rawdata->key_mac, RPMB_KEY_MAC_SIZE); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + crypto_mac_free_ctx(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, + const uint8_t *fek, + const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint16_t msg_type; + uint32_t wr_cnt; + uint16_t blk_idx; + uint8_t op_result; + struct rpmb_data_frame lastfrm; + + if (!datafrm || !rawdata || !nbr_frms) + return TEE_ERROR_BAD_PARAMETERS; + + if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) { + size_t i = 0; + + for (i = 0; i < nbr_frms; i++) { + DMSG("Dumping data frame %zu:", i); + DHEXDUMP((uint8_t *)&datafrm[i] + RPMB_STUFF_DATA_SIZE, + 512 - RPMB_STUFF_DATA_SIZE); + } + } + + /* Make sure the last data packet can't be modified once verified */ + memcpy(&lastfrm, &datafrm[nbr_frms - 1], RPMB_DATA_FRAME_SIZE); + + /* Handle operation result and translate to TEEC error code. */ + get_op_result_bits(lastfrm.op_result, &op_result); + if (op_result == RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED) + return TEE_ERROR_ITEM_NOT_FOUND; + if (op_result != RPMB_RESULT_OK) + return TEE_ERROR_GENERIC; + + /* Check the response msg_type. */ + bytes_to_u16(lastfrm.msg_type, &msg_type); + if (msg_type != rawdata->msg_type) { + DMSG("Unexpected msg_type (0x%04x != 0x%04x)", msg_type, + rawdata->msg_type); + return TEE_ERROR_GENERIC; + } + + if (rawdata->blk_idx) { + bytes_to_u16(lastfrm.address, &blk_idx); + if (blk_idx != *rawdata->blk_idx) { + DMSG("Unexpected block index"); + return TEE_ERROR_GENERIC; + } + } + + if (rawdata->write_counter) { + 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("Counter mismatched (0x%04x/0x%04x)", + *rawdata->write_counter, wr_cnt + 1); + return TEE_ERROR_SECURITY; + } + rpmb_ctx->wr_cnt++; + } + } + + if (rawdata->nonce) { + if (buf_compare_ct(rawdata->nonce, lastfrm.nonce, + RPMB_NONCE_SIZE) != 0) { + DMSG("Nonce mismatched"); + return TEE_ERROR_SECURITY; + } + } + + if (rawdata->key_mac) { + if (msg_type == RPMB_MSG_TYPE_RESP_AUTH_DATA_READ) { + if (!rawdata->data) + return TEE_ERROR_GENERIC; + + res = tee_rpmb_data_cpy_mac_calc(datafrm, rawdata, + nbr_frms, &lastfrm, + fek, uuid); + + 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 = tee_rpmb_mac_calc(rawdata->key_mac, + RPMB_KEY_MAC_SIZE, + rpmb_ctx->key, + RPMB_KEY_MAC_SIZE, + &lastfrm, 1); + + if (res != TEE_SUCCESS) + return res; + } + + if (consttime_memcmp(rawdata->key_mac, + (datafrm + nbr_frms - 1)->key_mac, + RPMB_KEY_MAC_SIZE) != 0) { + DMSG("MAC mismatched:"); + if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) + DHEXDUMP(rawdata->key_mac, RPMB_KEY_MAC_SIZE); + + 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_dev_info *di; + struct rpmb_req *req = NULL; + uint8_t *resp = NULL; + uint32_t req_size; + uint32_t resp_size; + + if (!dev_info) + 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; + + di = (struct rpmb_dev_info *)resp; + di->ret_code = RPMB_CMD_GET_DEV_INFO_RET_ERROR; + + res = tee_rpmb_invoke(&mem); + if (res != TEE_SUCCESS) + goto func_exit; + + if (di->ret_code != RPMB_CMD_GET_DEV_INFO_RET_OK) { + res = TEE_ERROR_GENERIC; + goto func_exit; + } + + memcpy((uint8_t *)dev_info, resp, sizeof(struct rpmb_dev_info)); + + if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) { + DMSG("Dumping dev_info:"); + DHEXDUMP((uint8_t *)dev_info, sizeof(struct rpmb_dev_info)); + } + + 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) + 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 = crypto_rng_read(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, NULL, NULL); + 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, NULL, NULL); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + tee_rpmb_free(&mem); + return res; +} + +static TEE_Result tee_rpmb_verify_key_sync_counter(uint16_t dev_id) +{ + uint16_t op_result = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + 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; +#ifdef CFG_RPMB_KEY_HAS_PROVISIONED + } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { + res = TEE_ERROR_BAD_STATE; + EMSG("No key is provisioned"); +#endif + } else + EMSG("Verify key returning 0x%x", res); + return res; +} + +#ifdef CFG_RPMB_WRITE_KEY +static TEE_Result tee_rpmb_write_key(uint16_t dev_id) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_rpmb_mem mem = { 0 }; + 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; + + 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, NULL, NULL); + 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, NULL, NULL); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + tee_rpmb_free(&mem); + return res; +} + +static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id) +{ + TEE_Result res; + + if (!plat_rpmb_key_is_ready()) { + DMSG("RPMB INIT: platform indicates RPMB key is not ready"); + return TEE_ERROR_BAD_STATE; + } + + DMSG("RPMB INIT: Writing Key value:"); + DHEXDUMP(rpmb_ctx->key, RPMB_KEY_MAC_SIZE); + + res = tee_rpmb_write_key(dev_id); + if (res == TEE_SUCCESS) { + DMSG("RPMB INIT: Verifying Key"); + res = tee_rpmb_verify_key_sync_counter(dev_id); + } + return res; +} +#else +static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id __unused) +{ + DMSG("RPMB INIT: CFG_RPMB_WRITE_KEY is not set"); + return TEE_ERROR_STORAGE_NOT_AVAILABLE; +} +#endif + +/* This function must never return TEE_SUCCESS if rpmb_ctx == NULL */ +static TEE_Result tee_rpmb_init(uint16_t dev_id) +{ + TEE_Result res = TEE_SUCCESS; + struct rpmb_dev_info dev_info = { }; + uint32_t nblocks = 0; + + if (rpmb_dead) + return TEE_ERROR_COMMUNICATION; + + if (!rpmb_ctx) { + rpmb_ctx = calloc(1, sizeof(struct tee_rpmb_ctx)); + if (!rpmb_ctx) + 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) { + DMSG("RPMB: Syncing device information"); + + dev_info.rpmb_size_mult = 0; + dev_info.rel_wr_sec_c = 0; + res = tee_rpmb_get_dev_info(dev_id, &dev_info); + if (res != TEE_SUCCESS) + goto func_exit; + + DMSG("RPMB: RPMB size is %d*128 KB", dev_info.rpmb_size_mult); + DMSG("RPMB: Reliable Write Sector Count is %d", + dev_info.rel_wr_sec_c); + + if (dev_info.rpmb_size_mult == 0) { + res = TEE_ERROR_GENERIC; + goto func_exit; + } + + if (MUL_OVERFLOW(dev_info.rpmb_size_mult, + RPMB_SIZE_SINGLE / RPMB_DATA_SIZE, &nblocks) || + SUB_OVERFLOW(nblocks, 1, &rpmb_ctx->max_blk_idx)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto func_exit; + } + + memcpy(rpmb_ctx->cid, dev_info.cid, RPMB_EMMC_CID_SIZE); + +#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) { + DMSG("RPMB INIT: Deriving key"); + + res = tee_rpmb_key_gen(dev_id, rpmb_ctx->key, + RPMB_KEY_MAC_SIZE); + if (res != TEE_SUCCESS) { + EMSG("RPMB INIT: Deriving key failed with error 0x%x", + res); + 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) { + DMSG("RPMB INIT: Verifying Key"); + + res = tee_rpmb_verify_key_sync_counter(dev_id); + if (res == TEE_ERROR_ITEM_NOT_FOUND && + !rpmb_ctx->key_verified) { + /* + * Need to write the key here and verify it. + */ + DMSG("RPMB INIT: Auth key not yet written"); + res = tee_rpmb_write_and_verify_key(dev_id); + } else if (res != TEE_SUCCESS) { + EMSG("Verify key failed!"); + EMSG("Make sure key here matches device key"); + } + } + +func_exit: + return res; +} + +/* + * 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. + * @fek Encrypted File Encryption Key or NULL. + */ +static TEE_Result tee_rpmb_read(uint16_t dev_id, uint32_t addr, uint8_t *data, + uint32_t len, const uint8_t *fek, + const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_rpmb_mem mem = { 0 }; + 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 || !len) + return TEE_ERROR_BAD_PARAMETERS; + + blk_idx = addr / RPMB_DATA_SIZE; + byte_offset = addr % RPMB_DATA_SIZE; + + if (len + byte_offset + RPMB_DATA_SIZE < RPMB_DATA_SIZE) { + /* Overflow */ + return TEE_ERROR_BAD_PARAMETERS; + } + blkcnt = + ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE; + res = tee_rpmb_init(dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + + 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 = crypto_rng_read(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, NULL, NULL); + if (res != TEE_SUCCESS) + goto func_exit; + + req->block_count = blkcnt; + + DMSG("Read %u block%s at index %u", blkcnt, ((blkcnt > 1) ? "s" : ""), + blk_idx); + + 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, fek, uuid); + if (res != TEE_SUCCESS) + goto func_exit; + + res = TEE_SUCCESS; + +func_exit: + tee_rpmb_free(&mem); + return res; +} + +static TEE_Result write_req(uint16_t dev_id, uint16_t blk_idx, + const void *data_blks, uint16_t blkcnt, + const uint8_t *fek, const TEE_UUID *uuid, + struct tee_rpmb_mem *mem, void *req, void *resp) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t hmac[RPMB_KEY_MAC_SIZE] = { }; + uint32_t wr_cnt = rpmb_ctx->wr_cnt; + struct rpmb_raw_data rawdata = { }; + size_t retry_count = 0; + + assert(mem->req_size <= + sizeof(struct rpmb_req) + blkcnt * RPMB_DATA_FRAME_SIZE); + assert(mem->resp_size <= RPMB_DATA_FRAME_SIZE); + + while (true) { + memset(req, 0, mem->req_size); + memset(resp, 0, mem->resp_size); + + memset(&rawdata, 0, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE; + rawdata.block_count = &blkcnt; + rawdata.blk_idx = &blk_idx; + rawdata.write_counter = &wr_cnt; + rawdata.key_mac = hmac; + rawdata.data = (uint8_t *)data_blks; + + res = tee_rpmb_req_pack(req, &rawdata, blkcnt, dev_id, fek, + uuid); + if (res) { + /* + * If we haven't tried to send a request yet we can + * allow a failure here since there's no chance of + * an intercepted request with a valid write + * counter. + */ + if (!retry_count) + return res; + + retry_count++; + if (retry_count >= RPMB_MAX_RETRIES) + goto out_of_retries; + + DMSG("Request pack failed, retrying %zu", retry_count); + continue; + } + + res = tee_rpmb_invoke(mem); + if (res != TEE_SUCCESS) { + retry_count++; + if (retry_count >= RPMB_MAX_RETRIES) + goto out_of_retries; + /* + * 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; + DMSG("Write invoke failed, retrying %zu", retry_count); + continue; + } + + memset(&rawdata, 0, sizeof(struct rpmb_raw_data)); + rawdata.msg_type = RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE; + rawdata.block_count = &blkcnt; + rawdata.blk_idx = &blk_idx; + rawdata.write_counter = &wr_cnt; + rawdata.key_mac = hmac; + + res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL, + NULL); + if (res != TEE_SUCCESS) { + retry_count++; + if (retry_count >= RPMB_MAX_RETRIES) + goto out_of_retries; + /* + * 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; + DMSG("Write resp unpack verify failed, retrying %zu", + retry_count); + continue; + } + + return TEE_SUCCESS; + } + +out_of_retries: + rpmb_dead = true; + /* + * We're using this error code to cause an eventuall calling TA to + * panic since we don't know if the data to be written has been + * committed to storage or not. + */ + return TEE_ERROR_COMMUNICATION; +} + +static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, uint16_t blk_idx, + const uint8_t *data_blks, uint16_t blkcnt, + const uint8_t *fek, const TEE_UUID *uuid) +{ + TEE_Result res; + struct tee_rpmb_mem mem; + struct rpmb_req *req = NULL; + struct rpmb_data_frame *resp = NULL; + uint32_t req_size; + uint32_t resp_size; + uint32_t nbr_writes; + uint16_t tmp_blkcnt; + uint16_t tmp_blk_idx; + uint16_t i; + + DMSG("Write %u block%s at index %u", blkcnt, ((blkcnt > 1) ? "s" : ""), + blk_idx); + + if (!data_blks || !blkcnt) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_rpmb_init(dev_id); + 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) + return res; + + 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++) { + size_t offs = i * rpmb_ctx->rel_wr_blkcnt * RPMB_DATA_SIZE; + + /* + * 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); + + res = write_req(dev_id, tmp_blk_idx, data_blks + offs, + tmp_blkcnt, fek, uuid, &mem, req, resp); + if (res) + goto out; + + + tmp_blk_idx += tmp_blkcnt; + } + +out: + tee_rpmb_free(&mem); + return res; +} + +static bool tee_rpmb_write_is_atomic(uint16_t dev_id __unused, uint32_t addr, + uint32_t len) +{ + uint8_t byte_offset = addr % RPMB_DATA_SIZE; + uint16_t blkcnt = ROUNDUP(len + byte_offset, + RPMB_DATA_SIZE) / RPMB_DATA_SIZE; + + return (blkcnt <= rpmb_ctx->rel_wr_blkcnt); +} + +/* + * 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. + * @fek Encrypted File Encryption Key or NULL. + */ +static TEE_Result tee_rpmb_write(uint16_t dev_id, uint32_t addr, + const uint8_t *data, uint32_t len, + const uint8_t *fek, const TEE_UUID *uuid) +{ + 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 = + 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, fek, + uuid); + if (res != TEE_SUCCESS) + goto func_exit; + } else { + data_tmp = calloc(blkcnt, RPMB_DATA_SIZE); + if (!data_tmp) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto func_exit; + } + + /* Read the complete blocks */ + res = tee_rpmb_read(dev_id, blk_idx * RPMB_DATA_SIZE, data_tmp, + blkcnt * RPMB_DATA_SIZE, fek, uuid); + 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, + fek, uuid); + if (res != TEE_SUCCESS) + goto func_exit; + } + + res = TEE_SUCCESS; + +func_exit: + free(data_tmp); + return res; +} + +/* + * Read the RPMB write counter. + * + * @dev_id Device ID of the eMMC device. + * @counter Pointer to the counter. + */ +static TEE_Result tee_rpmb_get_write_counter(uint16_t dev_id, + uint32_t *counter) +{ + TEE_Result res = TEE_SUCCESS; + + if (!counter) + return TEE_ERROR_BAD_PARAMETERS; + + if (rpmb_dead) + return TEE_ERROR_COMMUNICATION; + + if (!rpmb_ctx || !rpmb_ctx->wr_cnt_synced) { + res = tee_rpmb_init(dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + } + + *counter = rpmb_ctx->wr_cnt; + +func_exit: + return res; +} + +/* + * Read the RPMB max block. + * + * @dev_id Device ID of the eMMC device. + * @counter Pointer to receive the max block. + */ +static TEE_Result tee_rpmb_get_max_block(uint16_t dev_id, uint32_t *max_block) +{ + TEE_Result res = TEE_SUCCESS; + + if (!max_block) + return TEE_ERROR_BAD_PARAMETERS; + + if (rpmb_dead) + return TEE_ERROR_COMMUNICATION; + + if (!rpmb_ctx || !rpmb_ctx->dev_info_synced) { + res = tee_rpmb_init(dev_id); + if (res != TEE_SUCCESS) + goto func_exit; + } + + *max_block = rpmb_ctx->max_blk_idx; + +func_exit: + return res; +} + +/* + * End of lower interface to RPMB device + */ + +static TEE_Result get_fat_start_address(uint32_t *addr); +static TEE_Result rpmb_fs_setup(void); + +/** + * fat_entry_dir_free: Free the FAT entry dir. + */ +static void fat_entry_dir_free(void) +{ + if (fat_entry_dir) { + free(fat_entry_dir->rpmb_fat_entry_buf); + free(fat_entry_dir); + fat_entry_dir = NULL; + } +} + +/** + * fat_entry_dir_init: Initialize the FAT FS entry buffer/cache + * This function must be called before reading FAT FS entries using the + * function fat_entry_dir_get_next. This initializes the buffer/cache with the + * first FAT FS entries. + */ +static TEE_Result fat_entry_dir_init(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct rpmb_fat_entry *fe = NULL; + uint32_t fat_address = 0; + uint32_t num_elems_read = 0; + + if (fat_entry_dir) + return TEE_SUCCESS; + + res = rpmb_fs_setup(); + if (res) + return res; + + res = get_fat_start_address(&fat_address); + if (res) + return res; + + fat_entry_dir = calloc(1, sizeof(struct rpmb_fat_entry_dir)); + if (!fat_entry_dir) + return TEE_ERROR_OUT_OF_MEMORY; + + /* + * If caching is enabled, read in up to the maximum cache size, but + * never more than the single read in size. Otherwise, read in as many + * entries fit into the temporary buffer. + */ + if (CFG_RPMB_FS_CACHE_ENTRIES) + num_elems_read = MIN(CFG_RPMB_FS_CACHE_ENTRIES, + CFG_RPMB_FS_RD_ENTRIES); + else + num_elems_read = CFG_RPMB_FS_RD_ENTRIES; + + /* + * Allocate memory for the FAT FS entries to read in. + */ + fe = calloc(num_elems_read, sizeof(struct rpmb_fat_entry)); + if (!fe) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address, (uint8_t *)fe, + num_elems_read * sizeof(*fe), NULL, NULL); + if (res) + goto out; + + fat_entry_dir->rpmb_fat_entry_buf = fe; + + /* + * We use this variable when getting next entries from the buffer/cache + * to see whether we have to read in more entries from storage. + */ + fat_entry_dir->num_buffered = num_elems_read; + + return TEE_SUCCESS; +out: + fat_entry_dir_free(); + free(fe); + return res; +} + +/** + * fat_entry_dir_deinit: If caching is enabled, free the temporary buffer for + * FAT FS entries in case the cache was too small. Keep the elements in the + * cache. Reset the counter variables to start the next traversal from fresh + * from the first cached entry. If caching is disabled, just free the + * temporary buffer by calling fat_entry_dir_free and return. + */ +static void fat_entry_dir_deinit(void) +{ + struct rpmb_fat_entry *fe = NULL; + + if (!fat_entry_dir) + return; + + if (!CFG_RPMB_FS_CACHE_ENTRIES) { + fat_entry_dir_free(); + return; + } + + fe = fat_entry_dir->rpmb_fat_entry_buf; + fat_entry_dir->idx_curr = 0; + fat_entry_dir->num_total_read = 0; + fat_entry_dir->last_reached = false; + + if (fat_entry_dir->num_buffered > CFG_RPMB_FS_CACHE_ENTRIES) { + fat_entry_dir->num_buffered = CFG_RPMB_FS_CACHE_ENTRIES; + + fe = realloc(fe, fat_entry_dir->num_buffered * sizeof(*fe)); + + /* + * In case realloc fails, we are on the safe side if we destroy + * the whole structure. Upon the next init, the cache has to be + * re-established, but this case should not happen in practice. + */ + if (!fe) + fat_entry_dir_free(); + else + fat_entry_dir->rpmb_fat_entry_buf = fe; + } +} + +/** + * fat_entry_dir_update: Updates a persisted FAT FS entry in the cache. + * This function updates the FAT entry fat_entry that was written to address + * fat_address onto RPMB storage in the cache. + */ +static TEE_Result __maybe_unused fat_entry_dir_update + (struct rpmb_fat_entry *fat_entry, + uint32_t fat_address) +{ + uint32_t fat_entry_buf_idx = 0; + /* Use a temp var to avoid compiler warning if caching disabled. */ + uint32_t max_cache_entries = CFG_RPMB_FS_CACHE_ENTRIES; + + assert(!((fat_address - RPMB_FS_FAT_START_ADDRESS) % + sizeof(struct rpmb_fat_entry))); + + /* Nothing to update if the cache is not initialized. */ + if (!fat_entry_dir) + return TEE_SUCCESS; + + fat_entry_buf_idx = (fat_address - RPMB_FS_FAT_START_ADDRESS) / + sizeof(struct rpmb_fat_entry); + + /* Only need to write if index points to an entry in cache. */ + if (fat_entry_buf_idx < fat_entry_dir->num_buffered && + fat_entry_buf_idx < max_cache_entries) { + memcpy(fat_entry_dir->rpmb_fat_entry_buf + fat_entry_buf_idx, + fat_entry, sizeof(struct rpmb_fat_entry)); + } + + return TEE_SUCCESS; +} + +/** + * fat_entry_dir_get_next: Get next FAT FS entry. + * Read either from cache/buffer, or by reading from RPMB storage if the + * elements in the buffer/cache are fully read. When reading in from RPMB + * storage, the buffer is overwritten in case caching is disabled. + * In case caching is enabled, the cache is either further filled, or a + * temporary buffer populated if the cache is already full. + * The FAT FS entry is written to fat_entry. The respective address in RPMB + * storage is written to fat_address, if not NULL. When the last FAT FS entry + * was previously read, the function indicates this case by writing a NULL + * pointer to fat_entry. + * Returns a value different TEE_SUCCESS if the next FAT FS entry could not be + * retrieved. + */ +static TEE_Result fat_entry_dir_get_next(struct rpmb_fat_entry **fat_entry, + uint32_t *fat_address) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct rpmb_fat_entry *fe = NULL; + uint32_t num_elems_read = 0; + uint32_t fat_address_local = 0; + + assert(fat_entry_dir && fat_entry); + + /* Don't read further if we previously read the last FAT FS entry. */ + if (fat_entry_dir->last_reached) { + *fat_entry = NULL; + return TEE_SUCCESS; + } + + fe = fat_entry_dir->rpmb_fat_entry_buf; + + /* Determine address of FAT FS entry in RPMB storage. */ + fat_address_local = RPMB_FS_FAT_START_ADDRESS + + (fat_entry_dir->num_total_read * + sizeof(struct rpmb_fat_entry)); + + /* + * We've read all so-far buffered elements, so we need to + * read in more entries from RPMB storage. + */ + if (fat_entry_dir->idx_curr >= fat_entry_dir->num_buffered) { + /* + * This is the case where we do not cache entries, so just read + * in next set of FAT FS entries into the buffer. + * Goto the end of the when statement if that is done. + */ + if (!CFG_RPMB_FS_CACHE_ENTRIES) { + num_elems_read = CFG_RPMB_FS_RD_ENTRIES; + fat_entry_dir->idx_curr = 0; + + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fat_address_local, (uint8_t *)fe, + num_elems_read * sizeof(*fe), NULL, + NULL); + if (res) + return res; + goto post_read_in; + } + + /* + * We cache FAT FS entries, and the buffer is not completely + * filled. Further keep on extending the buffer up to its max + * size by reading in from RPMB. + */ + if (fat_entry_dir->num_total_read < RPMB_BUF_MAX_ENTRIES) { + /* + * Read at most as many elements as fit in the buffer + * and no more than the defined number of entries to + * read in at once. + */ + num_elems_read = MIN(RPMB_BUF_MAX_ENTRIES - + fat_entry_dir->num_total_read, + (uint32_t)CFG_RPMB_FS_RD_ENTRIES); + + /* + * Expand the buffer to fit in the additional entries. + */ + fe = realloc(fe, + (fat_entry_dir->num_buffered + + num_elems_read) * sizeof(*fe)); + if (!fe) + return TEE_ERROR_OUT_OF_MEMORY; + + fat_entry_dir->rpmb_fat_entry_buf = fe; + + /* Read in to the next free slot in the buffer/cache. */ + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fat_address_local, + (uint8_t *)(fe + + fat_entry_dir->num_total_read), + num_elems_read * sizeof(*fe), + NULL, NULL); + if (res) + return res; + + fat_entry_dir->num_buffered += num_elems_read; + } else { + /* + * This happens when we have read as many elements as + * can possibly fit into the buffer. + * As the first part of the buffer serves as our cache, + * we only overwrite the last part that serves as our + * temporary buffer used to iteratively read in entries + * when the cache is full. Read in the temporary buffer + * maximum size. + */ + num_elems_read = CFG_RPMB_FS_RD_ENTRIES; + /* Reset index to beginning of the temporary buffer. */ + fat_entry_dir->idx_curr = CFG_RPMB_FS_CACHE_ENTRIES; + + /* Read in elements after the end of the cache. */ + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fat_address_local, + (uint8_t *)(fe + + fat_entry_dir->idx_curr), + num_elems_read * sizeof(*fe), + NULL, NULL); + if (res) + return res; + } + } + +post_read_in: + if (fat_address) + *fat_address = fat_address_local; + + *fat_entry = fe + fat_entry_dir->idx_curr; + + fat_entry_dir->idx_curr++; + fat_entry_dir->num_total_read++; + + /* + * Indicate last entry was read. + * Ensures we return a zero value for fat_entry on next invocation. + */ + if ((*fat_entry)->flags & FILE_IS_LAST_ENTRY) + fat_entry_dir->last_reached = true; + + return TEE_SUCCESS; +} + +#if (TRACE_LEVEL >= TRACE_FLOW) +static void dump_fat(void) +{ + TEE_Result res = TEE_ERROR_SECURITY; + struct rpmb_fat_entry *fe = NULL; + + if (!fs_par) + return; + + if (fat_entry_dir_init()) + return; + + while (true) { + res = fat_entry_dir_get_next(&fe, NULL); + if (res || !fe) + break; + + FMSG("flags %#"PRIx32", size %"PRIu32", address %#"PRIx32 + ", filename '%s'", + fe->flags, fe->data_size, fe->start_address, fe->filename); + } + + fat_entry_dir_deinit(); +} +#else +static void dump_fat(void) +{ +} +#endif + +#if (TRACE_LEVEL >= TRACE_DEBUG) +static void dump_fh(struct rpmb_file_handle *fh) +{ + DMSG("fh->filename=%s", fh->filename); + DMSG("fh->rpmb_fat_address=%u", fh->rpmb_fat_address); + DMSG("fh->fat_entry.start_address=%u", fh->fat_entry.start_address); + DMSG("fh->fat_entry.data_size=%u", fh->fat_entry.data_size); +} +#else +static void dump_fh(struct rpmb_file_handle *fh __unused) +{ +} +#endif + +/* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ +static TEE_Result create_filename(void *buf, size_t blen, struct tee_pobj *po, + bool transient) +{ + uint8_t *file = buf; + uint32_t pos = 0; + uint32_t hslen = 1 /* Leading slash */ + + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len) + + 1; /* Intermediate slash */ + + /* +1 for the '.' (temporary persistent object) */ + if (transient) + hslen++; + + if (blen < hslen) + return TEE_ERROR_SHORT_BUFFER; + + file[pos++] = '/'; + pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos], + sizeof(TEE_UUID), hslen); + file[pos++] = '/'; + + if (transient) + file[pos++] = '.'; + + tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos); + + return TEE_SUCCESS; +} + +/* "/TA_uuid" */ +static TEE_Result create_dirname(void *buf, size_t blen, const TEE_UUID *uuid) +{ + uint8_t *dir = buf; + uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; + + if (blen < hslen) + return TEE_ERROR_SHORT_BUFFER; + + dir[0] = '/'; + tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen); + + return TEE_SUCCESS; +} + +static struct rpmb_file_handle *alloc_file_handle(struct tee_pobj *po, + bool temporary) +{ + struct rpmb_file_handle *fh = NULL; + + fh = calloc(1, sizeof(struct rpmb_file_handle)); + if (!fh) + return NULL; + + if (po) + create_filename(fh->filename, sizeof(fh->filename), po, + temporary); + + return fh; +} + +/** + * write_fat_entry: Store info in a fat_entry to RPMB. + */ +static TEE_Result write_fat_entry(struct rpmb_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(CFG_RPMB_FS_DEV_ID, + &fh->fat_entry.write_counter); + if (res) + goto out; + } + + res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, fh->rpmb_fat_address, + (uint8_t *)&fh->fat_entry, + sizeof(struct rpmb_fat_entry), NULL, NULL); + + dump_fat(); + + /* If caching enabled, update a successfully written entry in cache. */ + if (CFG_RPMB_FS_CACHE_ENTRIES && !res) + res = fat_entry_dir_update(&fh->fat_entry, + fh->rpmb_fat_address); + +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 rpmb_file_handle *fh = NULL; + uint32_t max_rpmb_block = 0; + + if (fs_par) { + res = TEE_SUCCESS; + goto out; + } + + res = tee_rpmb_get_max_block(CFG_RPMB_FS_DEV_ID, &max_rpmb_block); + if (res != TEE_SUCCESS) + goto out; + + /* + * We're going to read a full block in order to have a full block + * for the dummy write below. + */ + COMPILE_TIME_ASSERT(sizeof(struct rpmb_fs_partition) <= + RPMB_DATA_SIZE); + partition_data = calloc(1, RPMB_DATA_SIZE); + if (!partition_data) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, + (uint8_t *)partition_data, RPMB_DATA_SIZE, + NULL, NULL); + if (res != TEE_SUCCESS) + goto out; + /* + * Perform a write in order to increase the write counter. This + * prevents late usage (replay attack) of a previously blocked + * request with a valid write counter value. + */ + res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, + (uint8_t *)partition_data, RPMB_DATA_SIZE, + NULL, NULL); + if (res != TEE_SUCCESS) + goto out; + /* + * We're reading again in case a stale request was committed + * instead of the one issued above. If this succeeds we're in sync + * with the RPMB block since there are no other possible stale + * blocks with valid write counters available. + */ + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, + (uint8_t *)partition_data, + sizeof(struct rpmb_fs_partition), NULL, NULL); + if (res != TEE_SUCCESS) + goto out; + +#ifndef CFG_RPMB_RESET_FAT + if (partition_data->rpmb_fs_magic == RPMB_FS_MAGIC) { + if (partition_data->fs_version == FS_VERSION) { + res = TEE_SUCCESS; + goto store_fs_par; + } else { + EMSG("Wrong software is in use."); + res = TEE_ERROR_ACCESS_DENIED; + goto out; + } + } +#else + EMSG("**** Clearing Storage ****"); +#endif + + /* 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, false); + if (!fh) { + 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(CFG_RPMB_FS_DEV_ID, + &partition_data->write_counter); + if (res != TEE_SUCCESS) + goto out; + res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, + (uint8_t *)partition_data, + sizeof(struct rpmb_fs_partition), NULL, NULL); + +#ifndef CFG_RPMB_RESET_FAT +store_fs_par: +#endif + + /* Store FAT start address. */ + fs_par = calloc(1, sizeof(struct rpmb_fs_parameters)); + if (!fs_par) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + fs_par->fat_start_address = partition_data->fat_start_address; + fs_par->max_rpmb_address = max_rpmb_block << RPMB_BLOCK_SIZE_SHIFT; + + dump_fat(); + +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) +{ + if (!fs_par) + return TEE_ERROR_NO_DATA; + + *addr = fs_par->fat_start_address; + + return TEE_SUCCESS; +} + +/** + * 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 rpmb_file_handle *fh, tee_mm_pool_t *p) +{ + TEE_Result res = TEE_ERROR_GENERIC; + tee_mm_entry_t *mm = NULL; + struct rpmb_fat_entry *fe = NULL; + uint32_t fat_address; + bool entry_found = false; + bool expand_fat = false; + struct rpmb_file_handle last_fh; + + DMSG("fat_address %d", fh->rpmb_fat_address); + + res = fat_entry_dir_init(); + if (res) + goto out; + + /* + * The pool is used to represent the current RPMB layout. To find + * a slot for the file tee_mm_alloc is called on the pool. Thus + * if it is not NULL the entire FAT must be traversed to fill in + * the pool. + */ + while (true) { + res = fat_entry_dir_get_next(&fe, &fat_address); + if (res || !fe) + break; + + /* + * Look for an entry, matching filenames. (read, rm, + * rename and stat.). Only store first filename match. + */ + if ((!strcmp(fh->filename, fe->filename)) && + (fe->flags & FILE_IS_ACTIVE) && !entry_found) { + entry_found = true; + fh->rpmb_fat_address = fat_address; + memcpy(&fh->fat_entry, fe, sizeof(*fe)); + if (!p) + break; + } + + /* Add existing files to memory pool. (write) */ + if (p) { + if ((fe->flags & FILE_IS_ACTIVE) && fe->data_size > 0) { + + mm = tee_mm_alloc2(p, fe->start_address, + fe->data_size); + if (!mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + } + + /* Unused FAT entries can be reused (write) */ + if (((fe->flags & FILE_IS_ACTIVE) == 0) && + fh->rpmb_fat_address == 0) { + fh->rpmb_fat_address = fat_address; + memcpy(&fh->fat_entry, fe, + sizeof(struct rpmb_fat_entry)); + } + + if (((fe->flags & FILE_IS_LAST_ENTRY) != 0) && + fh->rpmb_fat_address == fat_address) { + + /* + * If the last entry was reached and was chosen + * by the previous check, then the FAT needs to + * be expanded. + * fh->rpmb_fat_address is the address chosen + * to store the files FAT entry and fat_address + * is the current FAT entry address being + * compared. + */ + expand_fat = true; + } + } + } + + if (res) + goto out; + /* + * Represent the FAT table in the pool. + */ + if (p) { + /* + * Since fat_address is the start of the last entry it needs to + * be moved up by an entry. + */ + fat_address += sizeof(struct rpmb_fat_entry); + + /* Make room for yet a FAT entry and add to memory pool. */ + if (expand_fat) + fat_address += sizeof(struct rpmb_fat_entry); + + mm = tee_mm_alloc2(p, RPMB_STORAGE_START_ADDRESS, fat_address); + if (!mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (expand_fat) { + /* + * Point fat_address to the beginning of the new + * entry. + */ + fat_address -= sizeof(struct rpmb_fat_entry); + memset(&last_fh, 0, sizeof(last_fh)); + last_fh.fat_entry.flags = FILE_IS_LAST_ENTRY; + last_fh.rpmb_fat_address = fat_address; + res = write_fat_entry(&last_fh, true); + if (res != TEE_SUCCESS) + goto out; + } + } + + if (!fh->rpmb_fat_address) + res = TEE_ERROR_ITEM_NOT_FOUND; + +out: + fat_entry_dir_deinit(); + return res; +} + +static TEE_Result generate_fek(struct rpmb_fat_entry *fe, const TEE_UUID *uuid) +{ + TEE_Result res; + +again: + res = tee_fs_generate_fek(uuid, fe->fek, sizeof(fe->fek)); + if (res != TEE_SUCCESS) + return res; + + if (is_zero(fe->fek, sizeof(fe->fek))) + goto again; + + return res; +} + +static TEE_Result rpmb_fs_open_internal(struct rpmb_file_handle *fh, + const TEE_UUID *uuid, bool create) +{ + tee_mm_pool_t p; + bool pool_result; + paddr_size_t pool_sz = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + /* We need to do setup in order to make sure fs_par is filled in */ + res = rpmb_fs_setup(); + if (res != TEE_SUCCESS) + goto out; + + fh->uuid = uuid; + if (create) { + /* Upper memory allocation must be used for RPMB_FS. */ + pool_sz = fs_par->max_rpmb_address - RPMB_STORAGE_START_ADDRESS; + pool_result = tee_mm_init(&p, + RPMB_STORAGE_START_ADDRESS, + pool_sz, + RPMB_BLOCK_SIZE_SHIFT, + TEE_MM_POOL_HI_ALLOC); + + if (!pool_result) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh, &p); + tee_mm_final(&p); + if (res != TEE_SUCCESS) + goto out; + } else { + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + } + + /* + * If this is opened with create and the entry found was not active + * then this is a new file and the FAT entry must be written + */ + if (create) { + if ((fh->fat_entry.flags & FILE_IS_ACTIVE) == 0) { + memset(&fh->fat_entry, 0, + sizeof(struct rpmb_fat_entry)); + memcpy(fh->fat_entry.filename, fh->filename, + strlen(fh->filename)); + /* Start address and size are 0 */ + fh->fat_entry.flags = FILE_IS_ACTIVE; + + res = generate_fek(&fh->fat_entry, uuid); + if (res != TEE_SUCCESS) + goto out; + DMSG("GENERATE FEK key: %p", + (void *)fh->fat_entry.fek); + DHEXDUMP(fh->fat_entry.fek, sizeof(fh->fat_entry.fek)); + + res = write_fat_entry(fh, true); + if (res != TEE_SUCCESS) + goto out; + } + } + + res = TEE_SUCCESS; + +out: + return res; +} + +static void rpmb_fs_close(struct tee_file_handle **tfh) +{ + struct rpmb_file_handle *fh = (struct rpmb_file_handle *)*tfh; + + free(fh); + *tfh = NULL; +} + +static TEE_Result rpmb_fs_read(struct tee_file_handle *tfh, size_t pos, + void *buf, size_t *len) +{ + TEE_Result res; + struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh; + size_t size = *len; + + if (!size) + return TEE_SUCCESS; + + mutex_lock(&rpmb_mutex); + + dump_fh(fh); + + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + + if (pos >= fh->fat_entry.data_size) { + *len = 0; + goto out; + } + + size = MIN(size, fh->fat_entry.data_size - pos); + if (size) { + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fh->fat_entry.start_address + pos, buf, + size, fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + goto out; + } + *len = size; + +out: + mutex_unlock(&rpmb_mutex); + return res; +} + +static TEE_Result update_write_helper(struct rpmb_file_handle *fh, + size_t pos, const void *buf, + size_t size, uintptr_t new_fat, + size_t new_size) +{ + uintptr_t old_fat = fh->fat_entry.start_address; + size_t old_size = fh->fat_entry.data_size; + const uint8_t *rem_buf = buf; + size_t rem_size = size; + uint8_t *blk_buf = NULL; + size_t blk_offset = 0; + size_t blk_size = 0; + TEE_Result res = TEE_SUCCESS; + + blk_buf = mempool_alloc(mempool_default, TMP_BLOCK_SIZE); + if (!blk_buf) + return TEE_ERROR_OUT_OF_MEMORY; + + while (blk_offset < new_size) { + uint8_t *copy_dst = blk_buf; + size_t copy_size = 0; + size_t rd_size = 0; + + blk_size = MIN(TMP_BLOCK_SIZE, new_size - blk_offset); + memset(blk_buf, 0, blk_size); + + /* Possibly read old RPMB data in temporary buffer */ + if (blk_offset < pos && blk_offset < old_size) { + rd_size = MIN(blk_size, old_size - blk_offset); + + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + old_fat + blk_offset, blk_buf, + rd_size, fh->fat_entry.fek, + fh->uuid); + if (res != TEE_SUCCESS) + break; + } + + /* Possibly update data in temporary buffer */ + if ((blk_offset + TMP_BLOCK_SIZE > pos) && + (blk_offset < pos + size)) { + size_t offset = 0; + + copy_dst = blk_buf; + copy_size = TMP_BLOCK_SIZE; + + if (blk_offset < pos) { + offset = pos - blk_offset; + + copy_dst += offset; + copy_size -= offset; + } + copy_size = MIN(copy_size, rem_size); + + memcpy(copy_dst, rem_buf, copy_size); + rem_buf += copy_size; + rem_size -= copy_size; + } + + /* Write temporary buffer to new RPMB destination */ + res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, new_fat + blk_offset, + blk_buf, blk_size, + fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + break; + + blk_offset += blk_size; + } + + mempool_free(mempool_default, blk_buf); + + return res; +} + +static TEE_Result rpmb_fs_write_primitive(struct rpmb_file_handle *fh, + size_t pos, const void *buf, + size_t size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + tee_mm_pool_t p = { }; + bool pool_result = false; + size_t end = 0; + uint32_t start_addr = 0; + paddr_size_t pool_sz = 0; + + if (!size) + return TEE_SUCCESS; + + if (!fs_par) { + res = TEE_ERROR_GENERIC; + goto out; + } + + dump_fh(fh); + + /* Upper memory allocation must be used for RPMB_FS. */ + pool_sz = fs_par->max_rpmb_address - RPMB_STORAGE_START_ADDRESS; + pool_result = tee_mm_init(&p, + RPMB_STORAGE_START_ADDRESS, + pool_sz, + RPMB_BLOCK_SIZE_SHIFT, + TEE_MM_POOL_HI_ALLOC); + if (!pool_result) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = read_fat(fh, &p); + if (res != TEE_SUCCESS) + goto out; + + if (fh->fat_entry.flags & FILE_IS_LAST_ENTRY) + panic("invalid last entry flag"); + + if (ADD_OVERFLOW(pos, size, &end)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + if (ADD_OVERFLOW(fh->fat_entry.start_address, pos, &start_addr)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (end <= fh->fat_entry.data_size && + tee_rpmb_write_is_atomic(CFG_RPMB_FS_DEV_ID, start_addr, size)) { + + DMSG("Updating data in-place"); + res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, start_addr, buf, + size, fh->fat_entry.fek, fh->uuid); + } else { + /* + * File must be extended, or update cannot be atomic: allocate, + * read, update, write. + */ + size_t new_size = MAX(end, fh->fat_entry.data_size); + tee_mm_entry_t *mm = tee_mm_alloc(&p, new_size); + uintptr_t new_fat_entry = 0; + + DMSG("Need to re-allocate"); + if (!mm) { + DMSG("RPMB: No space left"); + res = TEE_ERROR_STORAGE_NO_SPACE; + goto out; + } + + new_fat_entry = tee_mm_get_smem(mm); + + res = update_write_helper(fh, pos, buf, size, + new_fat_entry, new_size); + if (res == TEE_SUCCESS) { + fh->fat_entry.data_size = new_size; + fh->fat_entry.start_address = new_fat_entry; + + res = write_fat_entry(fh, true); + } + } + +out: + if (pool_result) + tee_mm_final(&p); + + return res; +} + +static TEE_Result rpmb_fs_write(struct tee_file_handle *tfh, size_t pos, + const void *buf, size_t size) +{ + TEE_Result res; + + mutex_lock(&rpmb_mutex); + res = rpmb_fs_write_primitive((struct rpmb_file_handle *)tfh, pos, + buf, size); + mutex_unlock(&rpmb_mutex); + + return res; +} + +static TEE_Result rpmb_fs_remove_internal(struct rpmb_file_handle *fh) +{ + TEE_Result res; + + res = read_fat(fh, NULL); + if (res) + return res; + + /* Clear this file entry. */ + memset(&fh->fat_entry, 0, sizeof(struct rpmb_fat_entry)); + return write_fat_entry(fh, false); +} + +static TEE_Result rpmb_fs_remove(struct tee_pobj *po) +{ + TEE_Result res; + struct rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); + + if (!fh) + return TEE_ERROR_OUT_OF_MEMORY; + + mutex_lock(&rpmb_mutex); + + res = rpmb_fs_remove_internal(fh); + + mutex_unlock(&rpmb_mutex); + + free(fh); + return res; +} + +static TEE_Result rpmb_fs_rename_internal(struct tee_pobj *old, + struct tee_pobj *new, + bool overwrite) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct rpmb_file_handle *fh_old = NULL; + struct rpmb_file_handle *fh_new = NULL; + + if (!old) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (new) + fh_old = alloc_file_handle(old, old->temporary); + else + fh_old = alloc_file_handle(old, true); + if (!fh_old) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (new) + fh_new = alloc_file_handle(new, new->temporary); + else + fh_new = alloc_file_handle(old, false); + if (!fh_new) { + 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) { + if (!overwrite) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto out; + } + + /* Clear this file entry. */ + memset(&fh_new->fat_entry, 0, sizeof(struct rpmb_fat_entry)); + res = write_fat_entry(fh_new, false); + if (res != TEE_SUCCESS) + goto out; + } + + memset(fh_old->fat_entry.filename, 0, TEE_RPMB_FS_FILENAME_LENGTH); + memcpy(fh_old->fat_entry.filename, fh_new->filename, + strlen(fh_new->filename)); + + res = write_fat_entry(fh_old, false); + +out: + free(fh_old); + free(fh_new); + + return res; +} + +static TEE_Result rpmb_fs_rename(struct tee_pobj *old, struct tee_pobj *new, + bool overwrite) +{ + TEE_Result res; + + mutex_lock(&rpmb_mutex); + res = rpmb_fs_rename_internal(old, new, overwrite); + mutex_unlock(&rpmb_mutex); + + return res; +} + +static TEE_Result rpmb_fs_truncate(struct tee_file_handle *tfh, size_t length) +{ + struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh; + tee_mm_pool_t p; + bool pool_result = false; + tee_mm_entry_t *mm; + uint32_t newsize; + uint8_t *newbuf = NULL; + uintptr_t newaddr; + TEE_Result res = TEE_ERROR_GENERIC; + paddr_size_t pool_sz = 0; + + mutex_lock(&rpmb_mutex); + + if (length > INT32_MAX) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + newsize = length; + + res = read_fat(fh, NULL); + if (res != TEE_SUCCESS) + goto out; + + if (newsize > fh->fat_entry.data_size) { + /* Extend file */ + + pool_sz = fs_par->max_rpmb_address - RPMB_STORAGE_START_ADDRESS; + pool_result = tee_mm_init(&p, + RPMB_STORAGE_START_ADDRESS, + pool_sz, + RPMB_BLOCK_SIZE_SHIFT, + TEE_MM_POOL_HI_ALLOC); + if (!pool_result) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + res = read_fat(fh, &p); + if (res != TEE_SUCCESS) + goto out; + + mm = tee_mm_alloc(&p, newsize); + newbuf = calloc(1, newsize); + if (!mm || !newbuf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (fh->fat_entry.data_size) { + res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, + fh->fat_entry.start_address, + newbuf, fh->fat_entry.data_size, + fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + goto out; + } + + newaddr = tee_mm_get_smem(mm); + res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, newaddr, newbuf, + newsize, fh->fat_entry.fek, fh->uuid); + if (res != TEE_SUCCESS) + goto out; + + } else { + /* Don't change file location */ + newaddr = fh->fat_entry.start_address; + } + + /* fh->pos is unchanged */ + fh->fat_entry.data_size = newsize; + fh->fat_entry.start_address = newaddr; + res = write_fat_entry(fh, true); + +out: + mutex_unlock(&rpmb_mutex); + if (pool_result) + tee_mm_final(&p); + if (newbuf) + free(newbuf); + + return res; +} + +static void rpmb_fs_dir_free(struct tee_fs_dir *dir) +{ + struct tee_rpmb_fs_dirent *e; + + if (!dir) + return; + + free(dir->current); + + while ((e = SIMPLEQ_FIRST(&dir->next))) { + SIMPLEQ_REMOVE_HEAD(&dir->next, link); + free(e); + } +} + +static TEE_Result rpmb_fs_dir_populate(const char *path, + struct tee_fs_dir *dir) +{ + struct tee_rpmb_fs_dirent *current = NULL; + struct rpmb_fat_entry *fe = NULL; + uint32_t fat_address; + uint32_t filelen; + char *filename; + bool matched; + struct tee_rpmb_fs_dirent *next = NULL; + uint32_t pathlen; + TEE_Result res = TEE_ERROR_GENERIC; + char temp; + + mutex_lock(&rpmb_mutex); + + res = fat_entry_dir_init(); + if (res) + goto out; + + pathlen = strlen(path); + + while (true) { + res = fat_entry_dir_get_next(&fe, &fat_address); + if (res || !fe) + break; + + filename = fe->filename; + if (fe->flags & FILE_IS_ACTIVE) { + matched = false; + filelen = strlen(filename); + if (filelen > pathlen) { + temp = filename[pathlen]; + filename[pathlen] = '\0'; + if (strcmp(filename, path) == 0) + matched = true; + + filename[pathlen] = temp; + } + + if (matched) { + next = malloc(sizeof(*next)); + if (!next) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + next->entry.oidlen = tee_hs2b((uint8_t *) + &filename[pathlen], + next->entry.oid, + filelen - pathlen, + sizeof(next->entry.oid)); + if (next->entry.oidlen) { + SIMPLEQ_INSERT_TAIL(&dir->next, + next, link); + current = next; + } else { + free(next); + next = NULL; + } + } + } + } + + if (res) + goto out; + + if (current) + res = TEE_SUCCESS; + else + res = TEE_ERROR_ITEM_NOT_FOUND; /* No directories were found. */ + +out: + mutex_unlock(&rpmb_mutex); + fat_entry_dir_deinit(); + if (res) + rpmb_fs_dir_free(dir); + + return res; +} + +static TEE_Result rpmb_fs_opendir(const TEE_UUID *uuid, struct tee_fs_dir **dir) +{ + uint32_t len; + char path_local[TEE_RPMB_FS_FILENAME_LENGTH]; + TEE_Result res = TEE_ERROR_GENERIC; + struct tee_fs_dir *rpmb_dir = NULL; + + if (!uuid || !dir) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + memset(path_local, 0, sizeof(path_local)); + if (create_dirname(path_local, sizeof(path_local) - 1, uuid)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + len = strlen(path_local); + + /* Add a slash to correctly match the full directory name. */ + if (path_local[len - 1] != '/') + path_local[len] = '/'; + + rpmb_dir = calloc(1, sizeof(*rpmb_dir)); + if (!rpmb_dir) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + SIMPLEQ_INIT(&rpmb_dir->next); + + res = rpmb_fs_dir_populate(path_local, rpmb_dir); + if (res != TEE_SUCCESS) { + free(rpmb_dir); + rpmb_dir = NULL; + goto out; + } + + *dir = rpmb_dir; + +out: + return res; +} + +static TEE_Result rpmb_fs_readdir(struct tee_fs_dir *dir, + struct tee_fs_dirent **ent) +{ + if (!dir) + return TEE_ERROR_GENERIC; + + free(dir->current); + + dir->current = SIMPLEQ_FIRST(&dir->next); + if (!dir->current) + return TEE_ERROR_ITEM_NOT_FOUND; + + SIMPLEQ_REMOVE_HEAD(&dir->next, link); + + *ent = &dir->current->entry; + return TEE_SUCCESS; +} + +static void rpmb_fs_closedir(struct tee_fs_dir *dir) +{ + if (dir) { + rpmb_fs_dir_free(dir); + free(dir); + } +} + +static TEE_Result rpmb_fs_open(struct tee_pobj *po, size_t *size, + struct tee_file_handle **ret_fh) +{ + TEE_Result res; + struct rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); + + if (!fh) + return TEE_ERROR_OUT_OF_MEMORY; + + mutex_lock(&rpmb_mutex); + + res = rpmb_fs_open_internal(fh, &po->uuid, false); + if (!res && size) + *size = fh->fat_entry.data_size; + + mutex_unlock(&rpmb_mutex); + + if (res) + free(fh); + else + *ret_fh = (struct tee_file_handle *)fh; + + return res; +} + +static TEE_Result rpmb_fs_create(struct tee_pobj *po, bool overwrite, + const void *head, size_t head_size, + const void *attr, size_t attr_size, + const void *data, size_t data_size, + struct tee_file_handle **ret_fh) +{ + TEE_Result res; + size_t pos = 0; + struct rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); + + if (!fh) + return TEE_ERROR_OUT_OF_MEMORY; + + mutex_lock(&rpmb_mutex); + res = rpmb_fs_open_internal(fh, &po->uuid, true); + if (res) + goto out; + + if (head && head_size) { + res = rpmb_fs_write_primitive(fh, pos, head, head_size); + if (res) + goto out; + pos += head_size; + } + + if (attr && attr_size) { + res = rpmb_fs_write_primitive(fh, pos, attr, attr_size); + if (res) + goto out; + pos += attr_size; + } + + if (data && data_size) { + res = rpmb_fs_write_primitive(fh, pos, data, data_size); + if (res) + goto out; + } + + if (po->temporary) { + /* + * If it's a temporary filename (which it normally is) + * rename into the final filename now that the file is + * fully initialized. + */ + po->temporary = false; + res = rpmb_fs_rename_internal(po, NULL, overwrite); + if (res) { + po->temporary = true; + goto out; + } + /* Update file handle after rename. */ + create_filename(fh->filename, sizeof(fh->filename), po, false); + } + +out: + if (res) { + rpmb_fs_remove_internal(fh); + free(fh); + } else { + *ret_fh = (struct tee_file_handle *)fh; + } + mutex_unlock(&rpmb_mutex); + + return res; +} + +const struct tee_file_operations rpmb_fs_ops = { + .open = rpmb_fs_open, + .create = rpmb_fs_create, + .close = rpmb_fs_close, + .read = rpmb_fs_read, + .write = rpmb_fs_write, + .truncate = rpmb_fs_truncate, + .rename = rpmb_fs_rename, + .remove = rpmb_fs_remove, + .opendir = rpmb_fs_opendir, + .closedir = rpmb_fs_closedir, + .readdir = rpmb_fs_readdir, +}; + +TEE_Result tee_rpmb_fs_raw_open(const char *fname, bool create, + struct tee_file_handle **ret_fh) +{ + TEE_Result res; + struct rpmb_file_handle *fh = calloc(1, sizeof(*fh)); + static const TEE_UUID uuid = { 0 }; + + if (!fh) + return TEE_ERROR_OUT_OF_MEMORY; + + snprintf(fh->filename, sizeof(fh->filename), "/%s", fname); + + mutex_lock(&rpmb_mutex); + + res = rpmb_fs_open_internal(fh, &uuid, create); + + mutex_unlock(&rpmb_mutex); + + if (res) { + if (create) + rpmb_fs_remove_internal(fh); + free(fh); + } else { + *ret_fh = (struct tee_file_handle *)fh; + } + + return res; +} + +bool __weak plat_rpmb_key_is_ready(void) +{ + return true; +} diff --git a/optee/optee_os/core/tee/tee_supp_plugin_rpc.c b/optee/optee_os/core/tee/tee_supp_plugin_rpc.c new file mode 100644 index 0000000..94a2f99 --- /dev/null +++ b/optee/optee_os/core/tee/tee_supp_plugin_rpc.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result tee_invoke_supp_plugin_rpc(const TEE_UUID *uuid, uint32_t cmd, + uint32_t sub_cmd, void *buf, size_t len, + size_t *outlen) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct thread_param params[THREAD_RPC_MAX_NUM_PARAMS]; + uint32_t uuid_words[4] = { }; + void *va = NULL; + struct mobj *mobj = NULL; + + /* + * sizeof 'TEE_UUID' and array 'uuid_words' must be same size, + * because 'tee_uuid_to_octets()' is used to copy variable + * with one type to another. + * + * Array 'uuid_words' is used just for convenient work with + * 'TEE_UUID' as with uint32_t values. + */ + COMPILE_TIME_ASSERT(sizeof(TEE_UUID) == sizeof(uuid_words)); + + if (!uuid || (len && !buf) || (!len && buf)) + return TEE_ERROR_BAD_PARAMETERS; + + if (len) { + mobj = thread_rpc_alloc_payload(len); + if (!mobj) { + EMSG("can't create mobj for plugin data"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + va = mobj_get_va(mobj, 0, len); + if (!va) { + EMSG("can't get va from mobj"); + goto out; + } + + memcpy(va, buf, len); + } + + tee_uuid_to_octets((uint8_t *)uuid_words, uuid); + + params[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SUPP_PLUGIN_INVOKE, + uuid_words[0], uuid_words[1]); + params[1] = THREAD_PARAM_VALUE(IN, uuid_words[2], uuid_words[3], cmd); + params[2] = THREAD_PARAM_VALUE(INOUT, sub_cmd, 0, 0); + params[3] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, len); + + res = thread_rpc_cmd(OPTEE_RPC_CMD_SUPP_PLUGIN, 4, params); + + if (outlen) + *outlen = params[2].u.value.b; + + if (len && outlen && *outlen) + memcpy(buf, va, *outlen <= len ? *outlen : len); + +out: + if (len) + thread_rpc_free_payload(mobj); + + return res; +} diff --git a/optee/optee_os/core/tee/tee_svc.c b/optee/optee_os/core/tee/tee_svc.c new file mode 100644 index 0000000..c49f01c --- /dev/null +++ b/optee/optee_os/core/tee/tee_svc.c @@ -0,0 +1,1115 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020-2022 Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +vaddr_t tee_svc_uref_base; + +void syscall_log(const void *buf, size_t len) +{ + if (IS_ENABLED(CFG_TEE_CORE_TA_TRACE)) { + char *kbuf = NULL; + size_t sz = 0; + + if (!len || ADD_OVERFLOW(len, 1, &sz)) + return; + + kbuf = malloc(sz); + if (!kbuf) + return; + + if (copy_from_user(kbuf, buf, len) == TEE_SUCCESS) { + kbuf[len] = '\0'; + trace_ext_puts(kbuf); + } + + free_wipe(kbuf); + } +} + +TEE_Result syscall_not_supported(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +/* Configuration properties */ +/* API implementation version */ +static const char api_vers[] = TO_STR(CFG_TEE_API_VERSION); + +/* Implementation description (implementation-dependent) */ +static const char descr[] = TO_STR(CFG_TEE_IMPL_DESCR); + +/* + * TA persistent time protection level + * 100: Persistent time based on an REE-controlled real-time clock + * and on the TEE Trusted Storage for the storage of origins (default). + * 1000: Persistent time based on a TEE-controlled real-time clock + * and the TEE Trusted Storage. + * The real-time clock MUST be out of reach of software attacks + * from the REE. + */ +static const uint32_t ta_time_prot_lvl = 100; + +/* Elliptic Curve Cryptographic support */ +#ifdef CFG_CRYPTO_ECC +static const bool crypto_ecc_en = 1; +#else +static const bool crypto_ecc_en; +#endif + +/* + * Trusted storage anti rollback protection level + * 100: Antirollback enforced at REE level + * 1000: Antirollback TEE-controlled hardware + */ +#ifdef CFG_RPMB_FS +static const uint32_t ts_antiroll_prot_lvl = 1000; +#else +static const uint32_t ts_antiroll_prot_lvl = 100; +#endif + +/* Trusted OS implementation version */ +static const char trustedos_impl_version[] = TO_STR(TEE_IMPL_VERSION); + +/* Trusted OS implementation version (binary value) */ +static const uint32_t trustedos_impl_bin_version; /* 0 by default */ + +/* Trusted OS implementation manufacturer name */ +static const char trustedos_manufacturer[] = TO_STR(CFG_TEE_MANUFACTURER); + +/* Trusted firmware version */ +static const char fw_impl_version[] = TO_STR(CFG_TEE_FW_IMPL_VERSION); + +/* Trusted firmware version (binary value) */ +static const uint32_t fw_impl_bin_version; /* 0 by default */ + +/* Trusted firmware manufacturer name */ +static const char fw_manufacturer[] = TO_STR(CFG_TEE_FW_MANUFACTURER); + +static TEE_Result get_prop_tee_dev_id(struct ts_session *sess __unused, + void *buf, size_t *blen) +{ + TEE_Result res; + TEE_UUID uuid; + const size_t nslen = 5; + uint8_t data[5 + FVR_DIE_ID_NUM_REGS * sizeof(uint32_t)] = { + 'O', 'P', 'T', 'E', 'E' }; + + if (*blen < sizeof(uuid)) { + *blen = sizeof(uuid); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(uuid); + + 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 copy_to_user(buf, &uuid, sizeof(TEE_UUID)); +} + +static TEE_Result +get_prop_tee_sys_time_prot_level(struct ts_session *sess __unused, + void *buf, size_t *blen) +{ + uint32_t prot; + + if (*blen < sizeof(prot)) { + *blen = sizeof(prot); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(prot); + prot = tee_time_get_sys_time_protection_level(); + return copy_to_user(buf, &prot, sizeof(prot)); +} + +static TEE_Result get_prop_client_id(struct ts_session *sess, + void *buf, size_t *blen) +{ + if (*blen < sizeof(TEE_Identity)) { + *blen = sizeof(TEE_Identity); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(TEE_Identity); + return copy_to_user(buf, &to_ta_session(sess)->clnt_id, + sizeof(TEE_Identity)); +} + +static TEE_Result get_prop_client_endian(struct ts_session *sess __unused, + void *buf, size_t *blen) +{ + const uint32_t endian = 0; /* assume little-endian */ + + if (*blen < sizeof(endian)) { + *blen = sizeof(endian); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(endian); + return copy_to_user(buf, &endian, sizeof(endian)); +} + +static TEE_Result get_prop_ta_app_id(struct ts_session *sess, + void *buf, size_t *blen) +{ + if (*blen < sizeof(TEE_UUID)) { + *blen = sizeof(TEE_UUID); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(TEE_UUID); + return copy_to_user(buf, &sess->ctx->uuid, sizeof(TEE_UUID)); +} + +#ifdef CFG_TA_BTI +static TEE_Result +get_prop_feat_bti_implemented(struct ts_session *sess __unused, void *buf, + size_t *blen) +{ + bool bti_impl = false; + + if (*blen < sizeof(bti_impl)) { + *blen = sizeof(bti_impl); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(bti_impl); + bti_impl = feat_bti_is_implemented(); + + return copy_to_user(buf, &bti_impl, sizeof(bti_impl)); +} +#endif + +#ifdef CFG_TA_PAUTH +static TEE_Result +get_prop_feat_pauth_implemented(struct ts_session *sess __unused, void *buf, + size_t *blen) +{ + bool pauth_impl = false; + + if (*blen < sizeof(pauth_impl)) { + *blen = sizeof(pauth_impl); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(pauth_impl); + pauth_impl = feat_pauth_is_implemented(); + + return copy_to_user(buf, &pauth_impl, sizeof(pauth_impl)); +} +#endif + +#if MEMTAG_IS_ENABLED +static TEE_Result +get_prop_feat_memtag_implemented(struct ts_session *sess __unused, void *buf, + size_t *blen) +{ + uint32_t v = 0; + + if (*blen < sizeof(v)) { + *blen = sizeof(v); + return TEE_ERROR_SHORT_BUFFER; + } + *blen = sizeof(v); + if (memtag_is_enabled()) + v = feat_mte_implemented(); + + return copy_to_user(buf, &v, sizeof(v)); +} +#endif + +/* Properties of the set TEE_PROPSET_CURRENT_CLIENT */ +const struct tee_props tee_propset_client[] = { + { + .name = "gpd.client.identity", + .prop_type = USER_TA_PROP_TYPE_IDENTITY, + .get_prop_func = get_prop_client_id + }, + { + .name = "gpd.client.endian", + .prop_type = USER_TA_PROP_TYPE_U32, + .get_prop_func = get_prop_client_endian + }, +}; + +/* Properties of the set TEE_PROPSET_CURRENT_TA */ +const struct tee_props tee_propset_ta[] = { + { + .name = "gpd.ta.appID", + .prop_type = USER_TA_PROP_TYPE_UUID, + .get_prop_func = get_prop_ta_app_id + }, + + /* + * Following properties are processed directly in libutee: + * TA_PROP_STR_SINGLE_INSTANCE + * TA_PROP_STR_MULTI_SESSION + * TA_PROP_STR_KEEP_ALIVE + * TA_PROP_STR_DATA_SIZE + * TA_PROP_STR_STACK_SIZE + * TA_PROP_STR_VERSION + * TA_PROP_STR_DESCRIPTION + * USER_TA_PROP_TYPE_STRING, + * TA_DESCRIPTION + */ +}; + +/* Properties of the set TEE_PROPSET_TEE_IMPLEMENTATION */ +const struct tee_props tee_propset_tee[] = { + { + .name = "gpd.tee.apiversion", + .prop_type = USER_TA_PROP_TYPE_STRING, + .data = api_vers, + .len = sizeof(api_vers), + }, + { + .name = "gpd.tee.description", + .prop_type = USER_TA_PROP_TYPE_STRING, + .data = descr, .len = sizeof(descr) + }, + { + .name = "gpd.tee.deviceID", + .prop_type = USER_TA_PROP_TYPE_UUID, + .get_prop_func = get_prop_tee_dev_id + }, + { + .name = "gpd.tee.systemTime.protectionLevel", + .prop_type = USER_TA_PROP_TYPE_U32, + .get_prop_func = get_prop_tee_sys_time_prot_level + }, + { + .name = "gpd.tee.TAPersistentTime.protectionLevel", + .prop_type = USER_TA_PROP_TYPE_U32, + .data = &ta_time_prot_lvl, + .len = sizeof(ta_time_prot_lvl) + }, + { + .name = "gpd.tee.cryptography.ecc", + .prop_type = USER_TA_PROP_TYPE_BOOL, + .data = &crypto_ecc_en, + .len = sizeof(crypto_ecc_en) + }, + { + .name = "gpd.tee.trustedStorage.antiRollback.protectionLevel", + .prop_type = USER_TA_PROP_TYPE_U32, + .data = &ts_antiroll_prot_lvl, + .len = sizeof(ts_antiroll_prot_lvl) + }, + { + .name = "gpd.tee.trustedos.implementation.version", + .prop_type = USER_TA_PROP_TYPE_STRING, + .data = trustedos_impl_version, + .len = sizeof(trustedos_impl_version) + }, + { + .name = "gpd.tee.trustedos.implementation.binaryversion", + .prop_type = USER_TA_PROP_TYPE_U32, + .data = &trustedos_impl_bin_version, + .len = sizeof(trustedos_impl_bin_version) + }, + { + .name = "gpd.tee.trustedos.manufacturer", + .prop_type = USER_TA_PROP_TYPE_STRING, + .data = trustedos_manufacturer, + .len = sizeof(trustedos_manufacturer) + }, + { + .name = "gpd.tee.firmware.implementation.version", + .prop_type = USER_TA_PROP_TYPE_STRING, + .data = fw_impl_version, + .len = sizeof(fw_impl_version) + }, + { + .name = "gpd.tee.firmware.implementation.binaryversion", + .prop_type = USER_TA_PROP_TYPE_U32, + .data = &fw_impl_bin_version, + .len = sizeof(fw_impl_bin_version) + }, + { + .name = "gpd.tee.firmware.manufacturer", + .prop_type = USER_TA_PROP_TYPE_STRING, + .data = fw_manufacturer, + .len = sizeof(fw_manufacturer) + }, +#ifdef CFG_TA_BTI + { + .name = "org.trustedfirmware.optee.cpu.feat_bti_implemented", + .prop_type = USER_TA_PROP_TYPE_BOOL, + .get_prop_func = get_prop_feat_bti_implemented + }, +#endif +#ifdef CFG_TA_PAUTH + { + .name = "org.trustedfirmware.optee.cpu.feat_pauth_implemented", + .prop_type = USER_TA_PROP_TYPE_BOOL, + .get_prop_func = get_prop_feat_pauth_implemented + }, +#endif +#if MEMTAG_IS_ENABLED + { + .name = "org.trustedfirmware.optee.cpu.feat_memtag_implemented", + .prop_type = USER_TA_PROP_TYPE_U32, + .get_prop_func = get_prop_feat_memtag_implemented + } +#endif + + /* + * Following properties are processed directly in libutee: + * gpd.tee.arith.maxBigIntSize + */ +}; + +__weak const struct tee_vendor_props vendor_props_client; +__weak const struct tee_vendor_props vendor_props_ta; +__weak const struct tee_vendor_props vendor_props_tee; + +static void get_prop_set(unsigned long prop_set, + const struct tee_props **props, + size_t *size, + const struct tee_props **vendor_props, + size_t *vendor_size) +{ + if ((TEE_PropSetHandle)prop_set == TEE_PROPSET_CURRENT_CLIENT) { + *props = tee_propset_client; + *size = ARRAY_SIZE(tee_propset_client); + *vendor_props = vendor_props_client.props; + *vendor_size = vendor_props_client.len; + } else if ((TEE_PropSetHandle)prop_set == TEE_PROPSET_CURRENT_TA) { + *props = tee_propset_ta; + *size = ARRAY_SIZE(tee_propset_ta); + *vendor_props = vendor_props_ta.props; + *vendor_size = vendor_props_ta.len; + } else if ((TEE_PropSetHandle)prop_set == + TEE_PROPSET_TEE_IMPLEMENTATION) { + *props = tee_propset_tee; + *size = ARRAY_SIZE(tee_propset_tee); + *vendor_props = vendor_props_tee.props; + *vendor_size = vendor_props_tee.len; + } else { + *props = NULL; + *size = 0; + *vendor_props = NULL; + *vendor_size = 0; + } +} + +static const struct tee_props *get_prop_struct(unsigned long prop_set, + unsigned long index) +{ + const struct tee_props *props; + const struct tee_props *vendor_props; + size_t size; + size_t vendor_size; + + get_prop_set(prop_set, &props, &size, &vendor_props, &vendor_size); + + if (index < size) + return &(props[index]); + index -= size; + + if (index < vendor_size) + return &(vendor_props[index]); + + return NULL; +} + +/* + * prop_set is part of TEE_PROPSET_xxx + * index is the index in the Property Set to retrieve + * if name is not NULL, the name of "index" property is returned + * if buf is not NULL, the property is returned + */ +TEE_Result syscall_get_property(unsigned long prop_set, + unsigned long index, + void *name, uint32_t *name_len, + void *buf, uint32_t *blen, + uint32_t *prop_type) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + TEE_Result res2 = TEE_SUCCESS; + const struct tee_props *prop = NULL; + uint32_t klen = 0; + size_t klen_size = 0; + uint32_t elen = 0; + + prop = get_prop_struct(prop_set, index); + if (!prop) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* Get the property type */ + if (prop_type) { + res = copy_to_user(prop_type, &prop->prop_type, + sizeof(*prop_type)); + if (res != TEE_SUCCESS) + return res; + } + + /* Get the property */ + if (buf && blen) { + res = copy_from_user(&klen, blen, sizeof(klen)); + if (res != TEE_SUCCESS) + return res; + + if (prop->get_prop_func) { + klen_size = klen; + res = prop->get_prop_func(sess, buf, &klen_size); + klen = klen_size; + res2 = copy_to_user(blen, &klen, sizeof(*blen)); + } else { + if (klen < prop->len) + res = TEE_ERROR_SHORT_BUFFER; + else + res = copy_to_user(buf, prop->data, prop->len); + res2 = copy_to_user(blen, &prop->len, sizeof(*blen)); + } + if (res2 != TEE_SUCCESS) + return res2; + if (res != TEE_SUCCESS) + return res; + } + + /* Get the property name */ + if (name && name_len) { + res = copy_from_user(&klen, name_len, sizeof(klen)); + if (res != TEE_SUCCESS) + return res; + + elen = strlen(prop->name) + 1; + + if (klen < elen) + res = TEE_ERROR_SHORT_BUFFER; + else + res = copy_to_user(name, prop->name, elen); + res2 = copy_to_user(name_len, &elen, sizeof(*name_len)); + if (res2 != TEE_SUCCESS) + return res2; + if (res != TEE_SUCCESS) + return res; + } + + return res; +} + +/* + * prop_set is part of TEE_PROPSET_xxx + */ +TEE_Result syscall_get_property_name_to_index(unsigned long prop_set, + void *name, + unsigned long name_len, + uint32_t *index) +{ + TEE_Result res = TEE_SUCCESS; + const struct tee_props *props = NULL; + size_t size = 0; + const struct tee_props *vendor_props = NULL; + size_t vendor_size = 0; + char *kname = NULL; + uint32_t i = 0; + + get_prop_set(prop_set, &props, &size, &vendor_props, &vendor_size); + if (!props) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (!name || !name_len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + kname = malloc(name_len); + if (!kname) + return TEE_ERROR_OUT_OF_MEMORY; + res = copy_from_user(kname, name, name_len); + if (res != TEE_SUCCESS) + goto out; + kname[name_len - 1] = 0; + + res = TEE_ERROR_ITEM_NOT_FOUND; + for (i = 0; i < size; i++) { + if (!strcmp(kname, props[i].name)) { + res = copy_to_user(index, &i, sizeof(*index)); + goto out; + } + } + for (i = size; i < size + vendor_size; i++) { + if (!strcmp(kname, vendor_props[i - size].name)) { + res = copy_to_user(index, &i, sizeof(*index)); + goto out; + } + } + +out: + free_wipe(kname); + return res; +} + +static TEE_Result utee_param_to_param(struct user_ta_ctx *utc, + struct tee_ta_param *p, + struct utee_params *up) +{ + size_t n = 0; + uint32_t types = up->types; + + p->types = types; + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uintptr_t a = up->vals[n * 2]; + size_t b = up->vals[n * 2 + 1]; + uint32_t flags = TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER; + + switch (TEE_PARAM_TYPE_GET(types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + flags |= TEE_MEMORY_ACCESS_WRITE; + fallthrough; + case TEE_PARAM_TYPE_MEMREF_INPUT: + p->u[n].mem.offs = memtag_strip_tag_vaddr((void *)a); + p->u[n].mem.size = b; + + if (!p->u[n].mem.offs) { + /* Allow NULL memrefs if of size 0 */ + if (p->u[n].mem.size) + return TEE_ERROR_BAD_PARAMETERS; + p->u[n].mem.mobj = NULL; + break; + } + + p->u[n].mem.mobj = &mobj_virt; + + if (vm_check_access_rights(&utc->uctx, flags, a, b)) + return TEE_ERROR_ACCESS_DENIED; + break; + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + p->u[n].val.a = a; + p->u[n].val.b = b; + break; + default: + memset(&p->u[n], 0, sizeof(p->u[n])); + break; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result alloc_temp_sec_mem(size_t size, struct mobj **mobj, + uint8_t **va) +{ + struct mobj *m = NULL; + void *v = NULL; + + /* Allocate section in secure DDR */ +#ifdef CFG_PAGED_USER_TA + m = mobj_seccpy_shm_alloc(size); +#else + m = mobj_mm_alloc(mobj_sec_ddr, size, &tee_mm_sec_ddr); +#endif + if (!m) + return TEE_ERROR_GENERIC; + + v = mobj_get_va(*mobj, 0, size); + if (!v) { + mobj_put(m); + return TEE_ERROR_GENERIC; + } + + *mobj = m; + *va = v; + return TEE_SUCCESS; +} + +/* + * 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 ts_session *sess, + struct ts_session *called_sess, + struct utee_params *callee_params, + struct tee_ta_param *param, + void *tmp_buf_va[TEE_NUM_PARAMS], + size_t tmp_buf_size[TEE_NUM_PARAMS], + struct mobj **mobj_tmp) +{ + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + bool ta_private_memref[TEE_NUM_PARAMS] = { false, }; + TEE_Result res = TEE_SUCCESS; + size_t dst_offs = 0; + size_t req_mem = 0; + uint8_t *dst = 0; + void *va = NULL; + size_t n = 0; + size_t s = 0; + + callee_params = memtag_strip_tag(callee_params); + + /* fill 'param' input struct with caller params description buffer */ + if (!callee_params) { + memset(param, 0, sizeof(*param)); + } else { + uint32_t flags = TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER; + + res = vm_check_access_rights(&utc->uctx, flags, + (uaddr_t)callee_params, + sizeof(struct utee_params)); + if (res != TEE_SUCCESS) + return res; + res = utee_param_to_param(utc, param, callee_params); + if (res != TEE_SUCCESS) + return res; + } + + if (called_sess && is_pseudo_ta_ctx(called_sess->ctx)) { + /* pseudo TA borrows the mapping of the calling TA */ + return TEE_SUCCESS; + } + + /* All mobj in param are of type MOJB_TYPE_VIRT */ + + 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: + va = (void *)param->u[n].mem.offs; + s = param->u[n].mem.size; + if (!va) { + if (s) + return TEE_ERROR_BAD_PARAMETERS; + break; + } + /* uTA cannot expose its private memory */ + if (vm_buf_is_inside_um_private(&utc->uctx, va, s)) { + s = ROUNDUP(s, sizeof(uint32_t)); + if (ADD_OVERFLOW(req_mem, s, &req_mem)) + return TEE_ERROR_BAD_PARAMETERS; + ta_private_memref[n] = true; + break; + } + + res = vm_buf_to_mboj_offs(&utc->uctx, va, s, + ¶m->u[n].mem.mobj, + ¶m->u[n].mem.offs); + if (res != TEE_SUCCESS) + return res; + break; + default: + break; + } + } + + if (req_mem == 0) + return TEE_SUCCESS; + + res = alloc_temp_sec_mem(req_mem, mobj_tmp, &dst); + if (res != TEE_SUCCESS) + return res; + dst_offs = 0; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + + if (!ta_private_memref[n]) + continue; + + s = ROUNDUP(param->u[n].mem.size, sizeof(uint32_t)); + + switch (TEE_PARAM_TYPE_GET(param->types, n)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + va = (void *)param->u[n].mem.offs; + if (va) { + res = copy_from_user(dst, va, + param->u[n].mem.size); + if (res != TEE_SUCCESS) + return res; + param->u[n].mem.offs = dst_offs; + param->u[n].mem.mobj = *mobj_tmp; + tmp_buf_va[n] = dst; + tmp_buf_size[n] = param->u[n].mem.size; + dst += s; + dst_offs += s; + } + break; + + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + va = (void *)param->u[n].mem.offs; + if (va) { + param->u[n].mem.offs = dst_offs; + param->u[n].mem.mobj = *mobj_tmp; + tmp_buf_va[n] = dst; + tmp_buf_size[n] = param->u[n].mem.size; + dst += s; + dst_offs += s; + } + break; + + default: + continue; + } + } + + 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_param *param, + void *tmp_buf_va[TEE_NUM_PARAMS], + size_t tmp_buf_size[TEE_NUM_PARAMS], + struct utee_params *usr_param) +{ + size_t n; + uint64_t *vals = usr_param->vals; + size_t sz = 0; + + 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: + /* + * Memory copy is only needed if there's a temporary + * buffer involved, tmp_buf_va[n] is only update if + * a temporary buffer is used. Otherwise only the + * size needs to be updated. + */ + sz = param->u[n].mem.size; + if (tmp_buf_va[n] && sz <= vals[n * 2 + 1]) { + void *src = tmp_buf_va[n]; + void *dst = (void *)(uintptr_t)vals[n * 2]; + TEE_Result res = TEE_SUCCESS; + + /* + * TA is allowed to return a size larger than + * the original size. However, in such cases no + * data should be synchronized as per TEE Client + * API spec. + */ + if (sz <= tmp_buf_size[n]) { + res = copy_to_user(dst, src, sz); + if (res != TEE_SUCCESS) + return res; + } + } + usr_param->vals[n * 2 + 1] = sz; + break; + + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + vals[n * 2] = param->u[n].val.a; + vals[n * 2 + 1] = param->u[n].val.b; + break; + + default: + continue; + } + } + + return TEE_SUCCESS; +} + +/* Called when a TA calls an OpenSession on another TA */ +TEE_Result syscall_open_ta_session(const TEE_UUID *dest, + unsigned long cancel_req_to, + struct utee_params *usr_param, uint32_t *ta_sess, + uint32_t *ret_orig) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + uint32_t ret_o = TEE_ORIGIN_TEE; + struct tee_ta_session *s = NULL; + struct mobj *mobj_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)); + void *tmp_buf_va[TEE_NUM_PARAMS] = { NULL }; + size_t tmp_buf_size[TEE_NUM_PARAMS] = { 0 }; + + 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 = copy_from_user_private(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->uuid, sizeof(TEE_UUID)); + + res = tee_svc_copy_param(sess, NULL, usr_param, param, tmp_buf_va, + tmp_buf_size, &mobj_param); + if (res != TEE_SUCCESS) + goto function_exit; + + res = tee_ta_open_session(&ret_o, &s, &utc->open_sessions, uuid, + clnt_id, cancel_req_to, param); + vm_set_ctx(&utc->ta_ctx.ts_ctx); + if (res != TEE_SUCCESS) + goto function_exit; + + res = tee_svc_update_out_param(param, tmp_buf_va, tmp_buf_size, + usr_param); + +function_exit: + mobj_put_wipe(mobj_param); + if (res == TEE_SUCCESS) + copy_to_user_private(ta_sess, &s->id, sizeof(s->id)); + copy_to_user_private(ret_orig, &ret_o, sizeof(ret_o)); + +out_free_only: + free_wipe(param); + free_wipe(uuid); + free_wipe(clnt_id); + return res; +} + +TEE_Result syscall_close_ta_session(unsigned long ta_sess) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Identity clnt_id = { }; + struct tee_ta_session *s = NULL; + + s = tee_ta_find_session(ta_sess, &utc->open_sessions); + + clnt_id.login = TEE_LOGIN_TRUSTED_APP; + memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); + + return tee_ta_close_session(s, &utc->open_sessions, &clnt_id); +} + +TEE_Result syscall_invoke_ta_command(unsigned long ta_sess, + unsigned long cancel_req_to, unsigned long cmd_id, + struct utee_params *usr_param, uint32_t *ret_orig) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + TEE_Result res2 = TEE_SUCCESS; + uint32_t ret_o = TEE_ORIGIN_TEE; + struct tee_ta_param param = { 0 }; + TEE_Identity clnt_id = { }; + struct tee_ta_session *called_sess = NULL; + struct mobj *mobj_param = NULL; + void *tmp_buf_va[TEE_NUM_PARAMS] = { NULL }; + size_t tmp_buf_size[TEE_NUM_PARAMS] = { }; + + called_sess = tee_ta_get_session((uint32_t)ta_sess, true, + &utc->open_sessions); + if (!called_sess) + return TEE_ERROR_BAD_PARAMETERS; + + clnt_id.login = TEE_LOGIN_TRUSTED_APP; + memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); + + res = tee_svc_copy_param(sess, &called_sess->ts_sess, usr_param, ¶m, + tmp_buf_va, tmp_buf_size, &mobj_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_ERROR_TARGET_DEAD) + goto function_exit; + + res2 = tee_svc_update_out_param(¶m, tmp_buf_va, tmp_buf_size, + usr_param); + if (res2 != TEE_SUCCESS) { + /* + * Spec for TEE_InvokeTACommand() says: + * "If the return origin is different from + * TEE_ORIGIN_TRUSTED_APP, then the function has failed + * before it could reach the destination Trusted + * Application." + * + * But if we can't update params to the caller we have no + * choice we need to return some error to indicate that + * parameters aren't updated as expected. + */ + ret_o = TEE_ORIGIN_TEE; + res = res2; + } + +function_exit: + tee_ta_put_session(called_sess); + mobj_put_wipe(mobj_param); + copy_to_user_private(ret_orig, &ret_o, sizeof(ret_o)); + return res; +} + +TEE_Result syscall_check_access_rights(unsigned long flags, const void *buf, + size_t len) +{ + struct ts_session *s = ts_get_current_session(); + + return vm_check_access_rights(&to_user_ta_ctx(s->ctx)->uctx, flags, + memtag_strip_tag_vaddr(buf), len); +} + +TEE_Result syscall_get_cancellation_flag(uint32_t *cancel) +{ + struct ts_session *s = ts_get_current_session(); + uint32_t c = 0; + + c = tee_ta_session_is_cancelled(to_ta_session(s), NULL); + + return copy_to_user(cancel, &c, sizeof(c)); +} + +TEE_Result syscall_unmask_cancellation(uint32_t *old_mask) +{ + struct ts_session *s = ts_get_current_session(); + struct tee_ta_session *sess = NULL; + uint32_t m = 0; + + sess = to_ta_session(s); + m = sess->cancel_mask; + sess->cancel_mask = false; + return copy_to_user(old_mask, &m, sizeof(m)); +} + +TEE_Result syscall_mask_cancellation(uint32_t *old_mask) +{ + struct ts_session *s = ts_get_current_session(); + struct tee_ta_session *sess = NULL; + uint32_t m = 0; + + sess = to_ta_session(s); + m = sess->cancel_mask; + sess->cancel_mask = true; + return copy_to_user(old_mask, &m, sizeof(m)); +} + +TEE_Result syscall_wait(unsigned long timeout) +{ + struct ts_session *s = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + uint32_t mytime = 0; + TEE_Time base_time = { }; + TEE_Time current_time = { }; + + 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 (tee_ta_session_is_cancelled(to_ta_session(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_time_wait(timeout - mytime); + } + + return res; +} + +TEE_Result syscall_get_time(unsigned long cat, TEE_Time *mytime) +{ + struct ts_session *s = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + TEE_Result res2 = TEE_SUCCESS; + TEE_Time t = { }; + + 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->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 = copy_to_user_private(mytime, &t, sizeof(t)); + if (res2 != TEE_SUCCESS) + res = res2; + } + + return res; +} + +TEE_Result syscall_set_ta_time(const TEE_Time *mytime) +{ + struct ts_session *s = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + TEE_Time t = { }; + + res = copy_from_user_private(&t, mytime, sizeof(t)); + if (res != TEE_SUCCESS) + return res; + + return tee_time_set_ta_time((const void *)&s->ctx->uuid, &t); +} diff --git a/optee/optee_os/core/tee/tee_svc_cryp.c b/optee/optee_os/core/tee/tee_svc_cryp.c new file mode 100644 index 0000000..eda285c --- /dev/null +++ b/optee/optee_os/core/tee/tee_svc_cryp.c @@ -0,0 +1,4489 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, 2022 Linaro Limited + * Copyright (c) 2022, Technology Innovation Institute (TII) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CFG_CRYPTO_HKDF) +#include +#endif +#if defined(CFG_CRYPTO_CONCAT_KDF) +#include +#endif +#if defined(CFG_CRYPTO_PBKDF2) +#include +#endif + +enum cryp_state { + CRYP_STATE_INITIALIZED = 0, + CRYP_STATE_UNINITIALIZED +}; + +typedef void (*tee_cryp_ctx_finalize_func_t) (void *ctx); +struct tee_cryp_state { + TAILQ_ENTRY(tee_cryp_state) link; + uint32_t algo; + uint32_t mode; + vaddr_t key1; + vaddr_t key2; + void *ctx; + tee_cryp_ctx_finalize_func_t ctx_finalize; + enum cryp_state state; +}; + +struct tee_cryp_obj_secret { + uint32_t key_size; + uint32_t alloc_size; + + /* + * Pseudo code visualize layout of structure + * Next follows data, such as: + * uint8_t data[alloc_size] + * key_size must never exceed alloc_size + */ +}; + +#define TEE_TYPE_ATTR_OPTIONAL BIT(0) +#define TEE_TYPE_ATTR_REQUIRED BIT(1) +#define TEE_TYPE_ATTR_OPTIONAL_GROUP BIT(2) +#define TEE_TYPE_ATTR_SIZE_INDICATOR BIT(3) +#define TEE_TYPE_ATTR_GEN_KEY_OPT BIT(4) +#define TEE_TYPE_ATTR_GEN_KEY_REQ BIT(5) +#define TEE_TYPE_ATTR_BIGNUM_MAXBITS BIT(6) + + /* Handle storing of generic secret keys of varying lengths */ +#define ATTR_OPS_INDEX_SECRET 0 + /* Convert to/from big-endian byte array and provider-specific bignum */ +#define ATTR_OPS_INDEX_BIGNUM 1 + /* Convert to/from value attribute depending on direction */ +#define ATTR_OPS_INDEX_VALUE 2 + /* Convert to/from curve25519 attribute depending on direction */ +#define ATTR_OPS_INDEX_25519 3 + + /* Curve25519 key bytes size is always 32 bytes*/ +#define KEY_SIZE_BYTES_25519 UL(32) + /* TEE Internal Core API v1.3.1, Table 6-8 */ +#define TEE_ED25519_CTX_MAX_LENGTH 255 + +struct tee_cryp_obj_type_attrs { + uint32_t attr_id; + uint16_t flags; + uint16_t ops_index; + uint16_t raw_offs; + uint16_t raw_size; +}; + +#define RAW_DATA(_x, _y) \ + .raw_offs = offsetof(_x, _y), .raw_size = 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, + .ops_index = ATTR_OPS_INDEX_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, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_public_key, n) + }, + + { + .attr_id = TEE_ATTR_RSA_PUBLIC_EXPONENT, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct 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, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_keypair, n) + }, + + { + .attr_id = TEE_ATTR_RSA_PUBLIC_EXPONENT, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_OPT, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_keypair, e) + }, + + { + .attr_id = TEE_ATTR_RSA_PRIVATE_EXPONENT, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_keypair, d) + }, + + { + .attr_id = TEE_ATTR_RSA_PRIME1, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_keypair, p) + }, + + { + .attr_id = TEE_ATTR_RSA_PRIME2, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_keypair, q) + }, + + { + .attr_id = TEE_ATTR_RSA_EXPONENT1, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_keypair, dp) + }, + + { + .attr_id = TEE_ATTR_RSA_EXPONENT2, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_keypair, dq) + }, + + { + .attr_id = TEE_ATTR_RSA_COEFFICIENT, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct rsa_keypair, 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 | TEE_TYPE_ATTR_BIGNUM_MAXBITS | + TEE_TYPE_ATTR_SIZE_INDICATOR, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dsa_public_key, p) + }, + + { + .attr_id = TEE_ATTR_DSA_SUBPRIME, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dsa_public_key, q) + }, + + { + .attr_id = TEE_ATTR_DSA_BASE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dsa_public_key, g) + }, + + { + .attr_id = TEE_ATTR_DSA_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct 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 | + TEE_TYPE_ATTR_BIGNUM_MAXBITS | TEE_TYPE_ATTR_SIZE_INDICATOR, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dsa_keypair, p) + }, + + { + .attr_id = TEE_ATTR_DSA_SUBPRIME, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dsa_keypair, q) + }, + + { + .attr_id = TEE_ATTR_DSA_BASE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ | + TEE_TYPE_ATTR_BIGNUM_MAXBITS, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dsa_keypair, g) + }, + + { + .attr_id = TEE_ATTR_DSA_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dsa_keypair, x) + }, + + { + .attr_id = TEE_ATTR_DSA_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dsa_keypair, 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, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dh_keypair, p) + }, + + { + .attr_id = TEE_ATTR_DH_BASE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dh_keypair, g) + }, + + { + .attr_id = TEE_ATTR_DH_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dh_keypair, y) + }, + + { + .attr_id = TEE_ATTR_DH_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dh_keypair, x) + }, + + { + .attr_id = TEE_ATTR_DH_SUBPRIME, + .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP | TEE_TYPE_ATTR_GEN_KEY_OPT, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct dh_keypair, q) + }, + + { + .attr_id = TEE_ATTR_DH_X_BITS, + .flags = TEE_TYPE_ATTR_GEN_KEY_OPT, + .ops_index = ATTR_OPS_INDEX_VALUE, + RAW_DATA(struct dh_keypair, xbits) + }, +}; + +#if defined(CFG_CRYPTO_HKDF) +static const struct tee_cryp_obj_type_attrs + tee_cryp_obj_hkdf_ikm_attrs[] = { + { + .attr_id = TEE_ATTR_HKDF_IKM, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, + .ops_index = ATTR_OPS_INDEX_SECRET, + .raw_offs = 0, + .raw_size = 0 + }, +}; +#endif + +#if defined(CFG_CRYPTO_CONCAT_KDF) +static const struct tee_cryp_obj_type_attrs + tee_cryp_obj_concat_kdf_z_attrs[] = { + { + .attr_id = TEE_ATTR_CONCAT_KDF_Z, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, + .ops_index = ATTR_OPS_INDEX_SECRET, + .raw_offs = 0, + .raw_size = 0 + }, +}; +#endif + +#if defined(CFG_CRYPTO_PBKDF2) +static const struct tee_cryp_obj_type_attrs + tee_cryp_obj_pbkdf2_passwd_attrs[] = { + { + .attr_id = TEE_ATTR_PBKDF2_PASSWORD, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, + .ops_index = ATTR_OPS_INDEX_SECRET, + .raw_offs = 0, + .raw_size = 0 + }, +}; +#endif + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_ecc_pub_key_attrs[] = { + { + .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_public_key, x) + }, + + { + .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_public_key, y) + }, + + { + .attr_id = TEE_ATTR_ECC_CURVE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, + .ops_index = ATTR_OPS_INDEX_VALUE, + RAW_DATA(struct ecc_public_key, curve) + }, +}; + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_ecc_keypair_attrs[] = { + { + .attr_id = TEE_ATTR_ECC_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_keypair, d) + }, + + { + .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_keypair, x) + }, + + { + .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_keypair, y) + }, + + { + .attr_id = TEE_ATTR_ECC_CURVE, + .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR | + TEE_TYPE_ATTR_GEN_KEY_REQ, + .ops_index = ATTR_OPS_INDEX_VALUE, + RAW_DATA(struct ecc_keypair, curve) + }, +}; + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_sm2_pub_key_attrs[] = { + { + .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_public_key, x) + }, + + { + .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_public_key, y) + }, +}; + +static const struct tee_cryp_obj_type_attrs tee_cryp_obj_sm2_keypair_attrs[] = { + { + .attr_id = TEE_ATTR_ECC_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_keypair, d) + }, + + { + .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_keypair, x) + }, + + { + .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_BIGNUM, + RAW_DATA(struct ecc_keypair, y) + }, +}; + +static +const struct tee_cryp_obj_type_attrs tee_cryp_obj_x25519_keypair_attrs[] = { + { + .attr_id = TEE_ATTR_X25519_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_25519, + RAW_DATA(struct x25519_keypair, priv) + }, + + { + .attr_id = TEE_ATTR_X25519_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_25519, + RAW_DATA(struct x25519_keypair, pub) + }, +}; + +static +const struct tee_cryp_obj_type_attrs tee_cryp_obj_ed25519_pub_key_attrs[] = { + { + .attr_id = TEE_ATTR_ED25519_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_25519, + RAW_DATA(struct ed25519_public_key, pub) + }, +}; + +static +const struct tee_cryp_obj_type_attrs tee_cryp_obj_ed25519_keypair_attrs[] = { + { + .attr_id = TEE_ATTR_ED25519_PRIVATE_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_25519, + RAW_DATA(struct ed25519_keypair, priv) + }, + + { + .attr_id = TEE_ATTR_ED25519_PUBLIC_VALUE, + .flags = TEE_TYPE_ATTR_REQUIRED, + .ops_index = ATTR_OPS_INDEX_25519, + RAW_DATA(struct ed25519_keypair, pub) + }, +}; + +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), \ + 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, 64, 64, 64, + /* Valid size 64 with parity */ + 64 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_DES3, 64, 128, 192, + /* Valid sizes 128, 192 with parity */ + 192 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_SM4, 128, 128, 128, + 128 / 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), +#if defined(CFG_HMAC_64_1024_RANGE) + PROP(TEE_TYPE_HMAC_SHA1, 8, 64, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA224, 8, 64, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA256, 8, 64, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA384, 8, 64, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA512, 8, 64, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), +#else + 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), +#endif + PROP(TEE_TYPE_HMAC_SHA3_224, 8, 192, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA3_256, 8, 256, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA3_384, 8, 256, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SHA3_512, 8, 256, 1024, + 1024 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_secret_value_attrs), + PROP(TEE_TYPE_HMAC_SM3, 8, 80, 1024, + 512 / 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), +#if defined(CFG_CRYPTO_HKDF) + PROP(TEE_TYPE_HKDF_IKM, 8, 0, 4096, + 4096 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_hkdf_ikm_attrs), +#endif +#if defined(CFG_CRYPTO_CONCAT_KDF) + PROP(TEE_TYPE_CONCAT_KDF_Z, 8, 0, 4096, + 4096 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_concat_kdf_z_attrs), +#endif +#if defined(CFG_CRYPTO_PBKDF2) + PROP(TEE_TYPE_PBKDF2_PASSWORD, 8, 0, 4096, + 4096 / 8 + sizeof(struct tee_cryp_obj_secret), + tee_cryp_obj_pbkdf2_passwd_attrs), +#endif + PROP(TEE_TYPE_RSA_PUBLIC_KEY, 1, 256, CFG_CORE_BIGNUM_MAX_BITS, + sizeof(struct rsa_public_key), + tee_cryp_obj_rsa_pub_key_attrs), + + PROP(TEE_TYPE_RSA_KEYPAIR, 1, 256, CFG_CORE_BIGNUM_MAX_BITS, + sizeof(struct rsa_keypair), + tee_cryp_obj_rsa_keypair_attrs), + + PROP(TEE_TYPE_DSA_PUBLIC_KEY, 64, 512, 3072, + sizeof(struct dsa_public_key), + tee_cryp_obj_dsa_pub_key_attrs), + + PROP(TEE_TYPE_DSA_KEYPAIR, 64, 512, 3072, + sizeof(struct dsa_keypair), + tee_cryp_obj_dsa_keypair_attrs), + + PROP(TEE_TYPE_DH_KEYPAIR, 1, 256, 2048, + sizeof(struct dh_keypair), + tee_cryp_obj_dh_keypair_attrs), + + PROP(TEE_TYPE_ECDSA_PUBLIC_KEY, 1, 192, 521, + sizeof(struct ecc_public_key), + tee_cryp_obj_ecc_pub_key_attrs), + + PROP(TEE_TYPE_ECDSA_KEYPAIR, 1, 192, 521, + sizeof(struct ecc_keypair), + tee_cryp_obj_ecc_keypair_attrs), + + PROP(TEE_TYPE_ECDH_PUBLIC_KEY, 1, 192, 521, + sizeof(struct ecc_public_key), + tee_cryp_obj_ecc_pub_key_attrs), + + PROP(TEE_TYPE_ECDH_KEYPAIR, 1, 192, 521, + sizeof(struct ecc_keypair), + tee_cryp_obj_ecc_keypair_attrs), + + PROP(TEE_TYPE_SM2_DSA_PUBLIC_KEY, 1, 256, 256, + sizeof(struct ecc_public_key), + tee_cryp_obj_sm2_pub_key_attrs), + + PROP(TEE_TYPE_SM2_DSA_KEYPAIR, 1, 256, 256, + sizeof(struct ecc_keypair), + tee_cryp_obj_sm2_keypair_attrs), + + PROP(TEE_TYPE_SM2_PKE_PUBLIC_KEY, 1, 256, 256, + sizeof(struct ecc_public_key), + tee_cryp_obj_sm2_pub_key_attrs), + + PROP(TEE_TYPE_SM2_PKE_KEYPAIR, 1, 256, 256, + sizeof(struct ecc_keypair), + tee_cryp_obj_sm2_keypair_attrs), + + PROP(TEE_TYPE_SM2_KEP_PUBLIC_KEY, 1, 256, 256, + sizeof(struct ecc_public_key), + tee_cryp_obj_sm2_pub_key_attrs), + + PROP(TEE_TYPE_SM2_KEP_KEYPAIR, 1, 256, 256, + sizeof(struct ecc_keypair), + tee_cryp_obj_sm2_keypair_attrs), + + PROP(TEE_TYPE_X25519_KEYPAIR, 1, 256, 256, + sizeof(struct x25519_keypair), + tee_cryp_obj_x25519_keypair_attrs), + + PROP(TEE_TYPE_ED25519_PUBLIC_KEY, 1, 256, 256, + sizeof(struct ed25519_public_key), + tee_cryp_obj_ed25519_pub_key_attrs), + + PROP(TEE_TYPE_ED25519_KEYPAIR, 1, 256, 256, + sizeof(struct ed25519_keypair), + tee_cryp_obj_ed25519_keypair_attrs), +}; + +struct attr_ops { + TEE_Result (*from_user)(void *attr, const void *buffer, size_t size); + TEE_Result (*to_user)(void *attr, struct ts_session *sess, + void *buffer, uint64_t *size); + TEE_Result (*to_binary)(void *attr, void *data, size_t data_len, + size_t *offs); + bool (*from_binary)(void *attr, const void *data, size_t data_len, + size_t *offs); + TEE_Result (*from_obj)(void *attr, void *src_attr); + void (*free)(void *attr); + void (*clear)(void *attr); +}; + +static TEE_Result op_u32_to_binary_helper(uint32_t v, uint8_t *data, + size_t data_len, size_t *offs) +{ + uint32_t field; + size_t next_offs; + + if (ADD_OVERFLOW(*offs, sizeof(field), &next_offs)) + return TEE_ERROR_OVERFLOW; + + if (data && next_offs <= data_len) { + field = TEE_U32_TO_BIG_ENDIAN(v); + memcpy(data + *offs, &field, sizeof(field)); + } + (*offs) = next_offs; + + return TEE_SUCCESS; +} + +static bool op_u32_from_binary_helper(uint32_t *v, const uint8_t *data, + size_t data_len, size_t *offs) +{ + uint32_t field; + + if (!data || (*offs + sizeof(field)) > data_len) + return false; + + memcpy(&field, data + *offs, sizeof(field)); + *v = TEE_U32_FROM_BIG_ENDIAN(field); + (*offs) += sizeof(field); + return true; +} + +static TEE_Result op_attr_secret_value_from_user(void *attr, const void *buffer, + size_t size) +{ + struct tee_cryp_obj_secret *key = attr; + + /* Data size has to fit in allocated buffer */ + if (size > key->alloc_size) + return TEE_ERROR_SECURITY; + memcpy(key + 1, buffer, size); + key->key_size = size; + return TEE_SUCCESS; +} + +static TEE_Result op_attr_secret_value_to_user(void *attr, + struct ts_session *sess __unused, + void *buffer, uint64_t *size) +{ + TEE_Result res; + struct tee_cryp_obj_secret *key = attr; + uint64_t s; + uint64_t key_size; + + res = copy_from_user(&s, size, sizeof(s)); + if (res != TEE_SUCCESS) + return res; + + key_size = key->key_size; + res = copy_to_user(size, &key_size, sizeof(key_size)); + if (res != TEE_SUCCESS) + return res; + + if (s < key->key_size || !buffer) + return TEE_ERROR_SHORT_BUFFER; + + return copy_to_user(buffer, key + 1, key->key_size); +} + +static TEE_Result op_attr_secret_value_to_binary(void *attr, void *data, + size_t data_len, size_t *offs) +{ + TEE_Result res; + struct tee_cryp_obj_secret *key = attr; + size_t next_offs; + + res = op_u32_to_binary_helper(key->key_size, data, data_len, offs); + if (res != TEE_SUCCESS) + return res; + + if (ADD_OVERFLOW(*offs, key->key_size, &next_offs)) + return TEE_ERROR_OVERFLOW; + + if (data && next_offs <= data_len) + memcpy((uint8_t *)data + *offs, key + 1, key->key_size); + (*offs) = next_offs; + + return TEE_SUCCESS; +} + +static bool op_attr_secret_value_from_binary(void *attr, const void *data, + size_t data_len, size_t *offs) +{ + struct tee_cryp_obj_secret *key = attr; + uint32_t s; + + if (!op_u32_from_binary_helper(&s, data, data_len, offs)) + return false; + + if ((*offs + s) > data_len) + return false; + + /* Data size has to fit in allocated buffer */ + if (s > key->alloc_size) + return false; + key->key_size = s; + memcpy(key + 1, (const uint8_t *)data + *offs, s); + (*offs) += s; + return true; +} + + +static TEE_Result op_attr_secret_value_from_obj(void *attr, void *src_attr) +{ + struct tee_cryp_obj_secret *key = attr; + struct tee_cryp_obj_secret *src_key = src_attr; + + if (src_key->key_size > key->alloc_size) + return TEE_ERROR_BAD_STATE; + memcpy(key + 1, src_key + 1, src_key->key_size); + key->key_size = src_key->key_size; + return TEE_SUCCESS; +} + +static void op_attr_secret_value_clear(void *attr) +{ + struct tee_cryp_obj_secret *key = attr; + + key->key_size = 0; + memzero_explicit(key + 1, key->alloc_size); +} + +static TEE_Result op_attr_bignum_from_user(void *attr, const void *buffer, + size_t size) +{ + struct bignum **bn = attr; + + return crypto_bignum_bin2bn(buffer, size, *bn); +} + +static TEE_Result op_attr_bignum_to_user(void *attr, + struct ts_session *sess, + void *buffer, uint64_t *size) +{ + TEE_Result res = TEE_SUCCESS; + struct bignum **bn = attr; + uint64_t req_size = 0; + uint64_t s = 0; + + res = copy_from_user(&s, size, sizeof(s)); + if (res != TEE_SUCCESS) + return res; + + req_size = crypto_bignum_num_bytes(*bn); + res = copy_to_user(size, &req_size, sizeof(req_size)); + if (res != TEE_SUCCESS) + return res; + if (!req_size) + return TEE_SUCCESS; + if (s < req_size || !buffer) + return TEE_ERROR_SHORT_BUFFER; + + buffer = memtag_strip_tag(buffer); + + /* Check we can access data using supplied user mode pointer */ + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)buffer, req_size); + if (res != TEE_SUCCESS) + return res; + /* + * Write the bignum (wich raw data points to) into an array of + * bytes (stored in buffer) + */ + crypto_bignum_bn2bin(*bn, buffer); + return TEE_SUCCESS; +} + +static TEE_Result op_attr_bignum_to_binary(void *attr, void *data, + size_t data_len, size_t *offs) +{ + TEE_Result res; + struct bignum **bn = attr; + uint32_t n = crypto_bignum_num_bytes(*bn); + size_t next_offs; + + res = op_u32_to_binary_helper(n, data, data_len, offs); + if (res != TEE_SUCCESS) + return res; + + if (ADD_OVERFLOW(*offs, n, &next_offs)) + return TEE_ERROR_OVERFLOW; + + if (data && next_offs <= data_len) + crypto_bignum_bn2bin(*bn, (uint8_t *)data + *offs); + (*offs) = next_offs; + + return TEE_SUCCESS; +} + +static bool op_attr_bignum_from_binary(void *attr, const void *data, + size_t data_len, size_t *offs) +{ + struct bignum **bn = attr; + uint32_t n; + + if (!op_u32_from_binary_helper(&n, data, data_len, offs)) + return false; + + if ((*offs + n) > data_len) + return false; + if (crypto_bignum_bin2bn((const uint8_t *)data + *offs, n, *bn)) + return false; + (*offs) += n; + return true; +} + +static TEE_Result op_attr_bignum_from_obj(void *attr, void *src_attr) +{ + struct bignum **bn = attr; + struct bignum **src_bn = src_attr; + + crypto_bignum_copy(*bn, *src_bn); + return TEE_SUCCESS; +} + +static void op_attr_bignum_clear(void *attr) +{ + struct bignum **bn = attr; + + crypto_bignum_clear(*bn); +} + +static void op_attr_bignum_free(void *attr) +{ + struct bignum **bn = attr; + + crypto_bignum_free(*bn); + *bn = NULL; +} + +static TEE_Result op_attr_value_from_user(void *attr, const void *buffer, + size_t size) +{ + uint32_t *v = attr; + + if (size != sizeof(uint32_t) * 2) + return TEE_ERROR_GENERIC; /* "can't happen */ + + /* Note that only the first value is copied */ + memcpy(v, buffer, sizeof(uint32_t)); + return TEE_SUCCESS; +} + +static TEE_Result op_attr_value_to_user(void *attr, + struct ts_session *sess __unused, + void *buffer, uint64_t *size) +{ + TEE_Result res; + uint32_t *v = attr; + uint64_t s; + uint32_t value[2] = { *v }; + uint64_t req_size = sizeof(value); + + res = copy_from_user(&s, size, sizeof(s)); + if (res != TEE_SUCCESS) + return res; + + if (s < req_size || !buffer) + return TEE_ERROR_SHORT_BUFFER; + + return copy_to_user(buffer, value, req_size); +} + +static TEE_Result op_attr_value_to_binary(void *attr, void *data, + size_t data_len, size_t *offs) +{ + uint32_t *v = attr; + + return op_u32_to_binary_helper(*v, data, data_len, offs); +} + +static bool op_attr_value_from_binary(void *attr, const void *data, + size_t data_len, size_t *offs) +{ + uint32_t *v = attr; + + return op_u32_from_binary_helper(v, data, data_len, offs); +} + +static TEE_Result op_attr_value_from_obj(void *attr, void *src_attr) +{ + uint32_t *v = attr; + uint32_t *src_v = src_attr; + + *v = *src_v; + return TEE_SUCCESS; +} + +static void op_attr_value_clear(void *attr) +{ + uint32_t *v = attr; + + *v = 0; +} + +static TEE_Result op_attr_25519_from_user(void *attr, const void *buffer, + size_t size) +{ + uint8_t **key = attr; + + if (size != KEY_SIZE_BYTES_25519 || !*key) + return TEE_ERROR_SECURITY; + + memcpy(*key, buffer, size); + + return TEE_SUCCESS; +} + +static TEE_Result op_attr_25519_to_user(void *attr, + struct ts_session *sess __unused, + void *buffer, uint64_t *size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t **key = attr; + uint64_t s = 0; + uint64_t key_size = (uint64_t)KEY_SIZE_BYTES_25519; + + res = copy_from_user(&s, size, sizeof(s)); + if (res != TEE_SUCCESS) + return res; + + res = copy_to_user(size, &key_size, sizeof(key_size)); + if (res != TEE_SUCCESS) + return res; + + if (s < key_size || !buffer) + return TEE_ERROR_SHORT_BUFFER; + + return copy_to_user(buffer, *key, key_size); +} + +static TEE_Result op_attr_25519_to_binary(void *attr, void *data, + size_t data_len, size_t *offs) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t **key = attr; + size_t next_offs = 0; + uint64_t key_size = (uint64_t)KEY_SIZE_BYTES_25519; + + res = op_u32_to_binary_helper(key_size, data, data_len, offs); + if (res != TEE_SUCCESS) + return res; + + if (ADD_OVERFLOW(*offs, key_size, &next_offs)) + return TEE_ERROR_OVERFLOW; + + if (data && next_offs <= data_len) + memcpy((uint8_t *)data + *offs, *key, key_size); + *offs = next_offs; + + return TEE_SUCCESS; +} + +static bool op_attr_25519_from_binary(void *attr, const void *data, + size_t data_len, size_t *offs) +{ + uint8_t **key = attr; + uint32_t s = 0; + + if (!op_u32_from_binary_helper(&s, data, data_len, offs)) + return false; + + if (*offs + s > data_len) + return false; + + if (s > (uint32_t)KEY_SIZE_BYTES_25519) + return false; + + memcpy(*key, (const uint8_t *)data + *offs, s); + *offs += s; + return true; +} + +static TEE_Result op_attr_25519_from_obj(void *attr, void *src_attr) +{ + uint8_t **key = attr; + uint8_t **src_key = src_attr; + + if (!*key || !*src_key) + return TEE_ERROR_SECURITY; + + memcpy(*key, *src_key, KEY_SIZE_BYTES_25519); + + return TEE_SUCCESS; +} + +static void op_attr_25519_clear(void *attr) +{ + uint8_t **key = attr; + + assert(*key); + + memzero_explicit(*key, KEY_SIZE_BYTES_25519); +} + +static void op_attr_25519_free(void *attr) +{ + uint8_t **key = attr; + + op_attr_25519_clear(attr); + free(*key); +} + +static const struct attr_ops attr_ops[] = { + [ATTR_OPS_INDEX_SECRET] = { + .from_user = op_attr_secret_value_from_user, + .to_user = op_attr_secret_value_to_user, + .to_binary = op_attr_secret_value_to_binary, + .from_binary = op_attr_secret_value_from_binary, + .from_obj = op_attr_secret_value_from_obj, + .free = op_attr_secret_value_clear, /* not a typo */ + .clear = op_attr_secret_value_clear, + }, + [ATTR_OPS_INDEX_BIGNUM] = { + .from_user = op_attr_bignum_from_user, + .to_user = op_attr_bignum_to_user, + .to_binary = op_attr_bignum_to_binary, + .from_binary = op_attr_bignum_from_binary, + .from_obj = op_attr_bignum_from_obj, + .free = op_attr_bignum_free, + .clear = op_attr_bignum_clear, + }, + [ATTR_OPS_INDEX_VALUE] = { + .from_user = op_attr_value_from_user, + .to_user = op_attr_value_to_user, + .to_binary = op_attr_value_to_binary, + .from_binary = op_attr_value_from_binary, + .from_obj = op_attr_value_from_obj, + .free = op_attr_value_clear, /* not a typo */ + .clear = op_attr_value_clear, + }, + [ATTR_OPS_INDEX_25519] = { + .from_user = op_attr_25519_from_user, + .to_user = op_attr_25519_to_user, + .to_binary = op_attr_25519_to_binary, + .from_binary = op_attr_25519_from_binary, + .from_obj = op_attr_25519_from_obj, + .free = op_attr_25519_free, + .clear = op_attr_25519_clear, + }, +}; + +static TEE_Result get_user_u64_as_size_t(size_t *dst, uint64_t *src) +{ + uint64_t d = 0; + TEE_Result res = copy_from_user(&d, src, sizeof(d)); + + /* + * On 32-bit systems a size_t can't hold a uint64_t so we need to + * check that the value isn't too large. + */ + if (!res && ADD_OVERFLOW(0, d, dst)) + return TEE_ERROR_OVERFLOW; + + return res; +} + +static TEE_Result put_user_u64(uint64_t *dst, size_t value) +{ + uint64_t v = value; + + return copy_to_user(dst, &v, sizeof(v)); +} + +TEE_Result syscall_cryp_obj_get_info(unsigned long obj, + struct utee_object_info *info) +{ + struct ts_session *sess = ts_get_current_session(); + struct utee_object_info o_info = { }; + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), + uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + goto exit; + + o_info.obj_type = o->info.objectType; + o_info.obj_size = o->info.objectSize; + o_info.max_obj_size = o->info.maxObjectSize; + o_info.obj_usage = o->info.objectUsage; + o_info.data_size = o->info.dataSize; + o_info.data_pos = o->info.dataPosition; + o_info.handle_flags = o->info.handleFlags; + res = copy_to_user_private(info, &o_info, sizeof(o_info)); + +exit: + return res; +} + +TEE_Result syscall_cryp_obj_restrict_usage(unsigned long obj, + unsigned long usage) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + goto exit; + + o->info.objectUsage &= usage; + +exit: + return res; +} + +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 < 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; +} + +/* Set an attribute on an object */ +static void set_attribute(struct tee_obj *o, + const struct tee_cryp_obj_type_props *props, + uint32_t attr) +{ + int idx = tee_svc_cryp_obj_find_type_attr_idx(attr, props); + + if (idx < 0) + return; + o->have_attrs |= BIT(idx); +} + +/* Get an attribute on an object */ +static uint32_t get_attribute(const struct tee_obj *o, + const struct tee_cryp_obj_type_props *props, + uint32_t attr) +{ + int idx = tee_svc_cryp_obj_find_type_attr_idx(attr, props); + + if (idx < 0) + return 0; + return o->have_attrs & BIT(idx); +} + +TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id, + void *buffer, uint64_t *size) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + const struct tee_cryp_obj_type_props *type_props = NULL; + int idx = 0; + const struct attr_ops *ops = NULL; + void *attr = NULL; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(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)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Check that getting the attribute is allowed */ + if (!(attr_id & TEE_ATTR_FLAG_PUBLIC) && + !(o->info.objectUsage & TEE_USAGE_EXTRACTABLE)) + return TEE_ERROR_BAD_PARAMETERS; + + type_props = tee_svc_find_type_props(o->info.objectType); + if (!type_props) { + /* 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; + + ops = attr_ops + type_props->type_attrs[idx].ops_index; + attr = (uint8_t *)o->attr + type_props->type_attrs[idx].raw_offs; + return ops->to_user(attr, sess, buffer, size); +} + +void tee_obj_attr_free(struct tee_obj *o) +{ + const struct tee_cryp_obj_type_props *tp; + size_t n; + + if (!o->attr) + return; + tp = tee_svc_find_type_props(o->info.objectType); + if (!tp) + return; + + for (n = 0; n < tp->num_type_attrs; n++) { + const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n; + + attr_ops[ta->ops_index].free((uint8_t *)o->attr + ta->raw_offs); + } +} + +void tee_obj_attr_clear(struct tee_obj *o) +{ + const struct tee_cryp_obj_type_props *tp; + size_t n; + + if (!o->attr) + return; + tp = tee_svc_find_type_props(o->info.objectType); + if (!tp) + return; + + for (n = 0; n < tp->num_type_attrs; n++) { + const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n; + + attr_ops[ta->ops_index].clear((uint8_t *)o->attr + + ta->raw_offs); + } +} + +TEE_Result tee_obj_attr_to_binary(struct tee_obj *o, void *data, + size_t *data_len) +{ + const struct tee_cryp_obj_type_props *tp; + size_t n; + size_t offs = 0; + size_t len = data ? *data_len : 0; + TEE_Result res; + + if (o->info.objectType == TEE_TYPE_DATA) { + *data_len = 0; + return TEE_SUCCESS; /* pure data object */ + } + if (!o->attr) + return TEE_ERROR_BAD_STATE; + tp = tee_svc_find_type_props(o->info.objectType); + if (!tp) + return TEE_ERROR_BAD_STATE; + + for (n = 0; n < tp->num_type_attrs; n++) { + const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n; + void *attr = (uint8_t *)o->attr + ta->raw_offs; + + res = attr_ops[ta->ops_index].to_binary(attr, data, len, &offs); + if (res != TEE_SUCCESS) + return res; + } + + *data_len = offs; + if (data && offs > len) + return TEE_ERROR_SHORT_BUFFER; + return TEE_SUCCESS; +} + +TEE_Result tee_obj_attr_from_binary(struct tee_obj *o, const void *data, + size_t data_len) +{ + const struct tee_cryp_obj_type_props *tp; + size_t n; + size_t offs = 0; + + if (o->info.objectType == TEE_TYPE_DATA) + return TEE_SUCCESS; /* pure data object */ + if (!o->attr) + return TEE_ERROR_BAD_STATE; + tp = tee_svc_find_type_props(o->info.objectType); + if (!tp) + return TEE_ERROR_BAD_STATE; + + for (n = 0; n < tp->num_type_attrs; n++) { + const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n; + void *attr = (uint8_t *)o->attr + ta->raw_offs; + + if (!attr_ops[ta->ops_index].from_binary(attr, data, data_len, + &offs)) + return TEE_ERROR_CORRUPT_OBJECT; + } + return TEE_SUCCESS; +} + +TEE_Result tee_obj_attr_copy_from(struct tee_obj *o, const struct tee_obj *src) +{ + TEE_Result res; + const struct tee_cryp_obj_type_props *tp; + const struct tee_cryp_obj_type_attrs *ta; + size_t n; + uint32_t have_attrs = 0; + void *attr; + void *src_attr; + + if (o->info.objectType == TEE_TYPE_DATA) + return TEE_SUCCESS; /* pure data object */ + if (!o->attr) + return TEE_ERROR_BAD_STATE; + tp = tee_svc_find_type_props(o->info.objectType); + if (!tp) + return TEE_ERROR_BAD_STATE; + + if (o->info.objectType == src->info.objectType) { + have_attrs = src->have_attrs; + for (n = 0; n < tp->num_type_attrs; n++) { + ta = tp->type_attrs + n; + attr = (uint8_t *)o->attr + ta->raw_offs; + src_attr = (uint8_t *)src->attr + ta->raw_offs; + res = attr_ops[ta->ops_index].from_obj(attr, src_attr); + if (res != TEE_SUCCESS) + return res; + } + } else { + const struct tee_cryp_obj_type_props *tp_src; + int idx; + + if (o->info.objectType == TEE_TYPE_RSA_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_RSA_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else if (o->info.objectType == TEE_TYPE_DSA_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_DSA_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else if (o->info.objectType == TEE_TYPE_ECDSA_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_ECDSA_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else if (o->info.objectType == TEE_TYPE_ECDH_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_ECDH_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else if (o->info.objectType == TEE_TYPE_SM2_DSA_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_SM2_DSA_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else if (o->info.objectType == TEE_TYPE_SM2_PKE_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_SM2_PKE_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else if (o->info.objectType == TEE_TYPE_SM2_KEP_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_SM2_KEP_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else if (o->info.objectType == TEE_TYPE_ED25519_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_ED25519_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else if (o->info.objectType == TEE_TYPE_X25519_PUBLIC_KEY) { + if (src->info.objectType != TEE_TYPE_X25519_KEYPAIR) + return TEE_ERROR_BAD_PARAMETERS; + } else { + return TEE_ERROR_BAD_PARAMETERS; + } + + tp_src = tee_svc_find_type_props(src->info.objectType); + if (!tp_src) + return TEE_ERROR_BAD_STATE; + + have_attrs = BIT32(tp->num_type_attrs) - 1; + for (n = 0; n < tp->num_type_attrs; n++) { + ta = tp->type_attrs + n; + + idx = tee_svc_cryp_obj_find_type_attr_idx(ta->attr_id, + tp_src); + if (idx < 0) + return TEE_ERROR_BAD_STATE; + + attr = (uint8_t *)o->attr + ta->raw_offs; + src_attr = (uint8_t *)src->attr + + tp_src->type_attrs[idx].raw_offs; + res = attr_ops[ta->ops_index].from_obj(attr, src_attr); + if (res != TEE_SUCCESS) + return res; + } + } + + o->have_attrs = have_attrs; + return TEE_SUCCESS; +} + +static bool is_gp_legacy_des_key_size(TEE_ObjectType type, size_t sz) +{ + return IS_ENABLED(CFG_COMPAT_GP10_DES) && + ((type == TEE_TYPE_DES && sz == 56) || + (type == TEE_TYPE_DES3 && (sz == 112 || sz == 168))); +} + +static TEE_Result check_key_size(const struct tee_cryp_obj_type_props *props, + size_t key_size) +{ + size_t sz = key_size; + + /* + * In GP Internal API Specification 1.0 the partity bits aren't + * counted when telling the size of the key in bits so add them + * here if missing. + */ + if (is_gp_legacy_des_key_size(props->obj_type, sz)) + sz += sz / 7; + + if (sz % props->quanta != 0) + return TEE_ERROR_NOT_SUPPORTED; + if (sz < props->min_size) + return TEE_ERROR_NOT_SUPPORTED; + if (sz > props->max_size) + return TEE_ERROR_NOT_SUPPORTED; + + return TEE_SUCCESS; +} + +TEE_Result tee_obj_set_type(struct tee_obj *o, uint32_t obj_type, + size_t max_key_size) +{ + TEE_Result res = TEE_SUCCESS; + const struct tee_cryp_obj_type_props *type_props; + + /* Can only set type for newly allocated objs */ + if (o->attr) + return TEE_ERROR_BAD_STATE; + + /* + * Verify that maxObjectSize is supported and find out how + * much should be allocated. + */ + + if (obj_type == TEE_TYPE_DATA) { + if (max_key_size) + return TEE_ERROR_NOT_SUPPORTED; + } else { + /* Find description of object */ + type_props = tee_svc_find_type_props(obj_type); + if (!type_props) + return TEE_ERROR_NOT_SUPPORTED; + + /* Check that max_key_size follows restrictions */ + res = check_key_size(type_props, max_key_size); + if (res) + return res; + + o->attr = calloc(1, type_props->alloc_size); + if (!o->attr) + return TEE_ERROR_OUT_OF_MEMORY; + } + + /* If we have a key structure, pre-allocate the bignums inside */ + switch (obj_type) { + case TEE_TYPE_RSA_PUBLIC_KEY: + res = crypto_acipher_alloc_rsa_public_key(o->attr, + max_key_size); + break; + case TEE_TYPE_RSA_KEYPAIR: + res = crypto_acipher_alloc_rsa_keypair(o->attr, max_key_size); + break; + case TEE_TYPE_DSA_PUBLIC_KEY: + res = crypto_acipher_alloc_dsa_public_key(o->attr, + max_key_size); + break; + case TEE_TYPE_DSA_KEYPAIR: + res = crypto_acipher_alloc_dsa_keypair(o->attr, max_key_size); + break; + case TEE_TYPE_DH_KEYPAIR: + res = crypto_acipher_alloc_dh_keypair(o->attr, max_key_size); + break; + case TEE_TYPE_ECDSA_PUBLIC_KEY: + case TEE_TYPE_ECDH_PUBLIC_KEY: + case TEE_TYPE_SM2_DSA_PUBLIC_KEY: + case TEE_TYPE_SM2_PKE_PUBLIC_KEY: + case TEE_TYPE_SM2_KEP_PUBLIC_KEY: + res = crypto_acipher_alloc_ecc_public_key(o->attr, obj_type, + max_key_size); + break; + case TEE_TYPE_ECDSA_KEYPAIR: + case TEE_TYPE_ECDH_KEYPAIR: + case TEE_TYPE_SM2_DSA_KEYPAIR: + case TEE_TYPE_SM2_PKE_KEYPAIR: + case TEE_TYPE_SM2_KEP_KEYPAIR: + res = crypto_acipher_alloc_ecc_keypair(o->attr, obj_type, + max_key_size); + break; + case TEE_TYPE_X25519_KEYPAIR: + res = crypto_acipher_alloc_x25519_keypair(o->attr, + max_key_size); + break; + case TEE_TYPE_ED25519_KEYPAIR: + res = crypto_acipher_alloc_ed25519_keypair(o->attr, + max_key_size); + break; + case TEE_TYPE_ED25519_PUBLIC_KEY: + res = crypto_acipher_alloc_ed25519_public_key(o->attr, + max_key_size); + break; + default: + if (obj_type != TEE_TYPE_DATA) { + struct tee_cryp_obj_secret *key = o->attr; + + key->alloc_size = type_props->alloc_size - + sizeof(*key); + } + break; + } + + if (res != TEE_SUCCESS) + return res; + + o->info.objectType = obj_type; + o->info.maxObjectSize = max_key_size; + o->info.objectUsage = TEE_USAGE_DEFAULT; + + return TEE_SUCCESS; +} + +TEE_Result syscall_cryp_obj_alloc(unsigned long obj_type, + unsigned long max_key_size, uint32_t *obj) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + + + o = tee_obj_alloc(); + if (!o) + return TEE_ERROR_OUT_OF_MEMORY; + + res = tee_obj_set_type(o, obj_type, max_key_size); + if (res != TEE_SUCCESS) { + tee_obj_free(o); + return res; + } + + tee_obj_add(to_user_ta_ctx(sess->ctx), o); + + res = copy_kaddr_to_uref(obj, o); + if (res != TEE_SUCCESS) + tee_obj_close(to_user_ta_ctx(sess->ctx), o); + return res; +} + +TEE_Result syscall_cryp_obj_close(unsigned long obj) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(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(to_user_ta_ctx(sess->ctx), o); + return TEE_SUCCESS; +} + +TEE_Result syscall_cryp_obj_reset(unsigned long obj) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + return res; + + if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) == 0) { + tee_obj_attr_clear(o); + o->info.objectSize = 0; + o->info.objectUsage = TEE_USAGE_DEFAULT; + } else { + return TEE_ERROR_BAD_PARAMETERS; + } + + /* the object is no more initialized */ + o->info.handleFlags &= ~TEE_HANDLE_FLAG_INITIALIZED; + + return TEE_SUCCESS; +} + +static TEE_Result copy_in_attrs(struct user_ta_ctx *utc, + const struct utee_attribute *usr_attrs, + uint32_t attr_count, TEE_Attribute *attrs) +{ + TEE_Result res = TEE_SUCCESS; + size_t size = 0; + uint32_t n = 0; + + if (MUL_OVERFLOW(sizeof(struct utee_attribute), attr_count, &size)) + return TEE_ERROR_OVERFLOW; + + usr_attrs = memtag_strip_tag_const(usr_attrs); + + res = vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)usr_attrs, size); + if (res != TEE_SUCCESS) + return res; + + for (n = 0; n < attr_count; n++) { + attrs[n].attributeID = usr_attrs[n].attribute_id; + if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) { + attrs[n].content.value.a = usr_attrs[n].a; + attrs[n].content.value.b = usr_attrs[n].b; + } else { + uintptr_t buf = usr_attrs[n].a; + size_t len = usr_attrs[n].b; + uint32_t flags = TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER; + + buf = memtag_strip_tag_vaddr((void *)buf); + + res = vm_check_access_rights(&utc->uctx, flags, buf, + len); + if (res != TEE_SUCCESS) + return res; + attrs[n].content.ref.buffer = (void *)buf; + attrs[n].content.ref.length = len; + } + } + + return TEE_SUCCESS; +} + +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, + const TEE_Attribute *attrs, + uint32_t attr_count) +{ + uint32_t required_flag = 0; + uint32_t opt_flag = 0; + bool all_opt_needed = false; + uint32_t req_attrs = 0; + uint32_t opt_grp_attrs = 0; + uint32_t attrs_found = 0; + size_t n = 0; + uint32_t bit = 0; + uint32_t flags = 0; + int idx = 0; + + 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++) { + bit = 1 << n; + 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++) { + idx = tee_svc_cryp_obj_find_type_attr_idx( + attrs[n].attributeID, + type_props); + + /* attribute not defined in current object type */ + if (idx < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + bit = 1 << idx; + + /* attribute not repeated */ + if ((attrs_found & bit) != 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + /* + * Attribute not defined in current object type for this + * usage. + */ + if (!(bit & (req_attrs | opt_grp_attrs))) + 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 get_ec_key_size(uint32_t curve, size_t *key_size) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + *key_size = 192; + break; + case TEE_ECC_CURVE_NIST_P224: + *key_size = 224; + break; + case TEE_ECC_CURVE_NIST_P256: + *key_size = 256; + break; + case TEE_ECC_CURVE_NIST_P384: + *key_size = 384; + break; + case TEE_ECC_CURVE_NIST_P521: + *key_size = 521; + break; + case TEE_ECC_CURVE_SM2: + case TEE_ECC_CURVE_25519: + *key_size = 256; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +static size_t get_used_bits(const TEE_Attribute *a) +{ + int nbits = a->content.ref.length * 8; + int v = 0; + + bit_ffs(a->content.ref.buffer, nbits, &v); + return nbits - v; +} + +static TEE_Result tee_svc_cryp_obj_populate_type( + struct tee_obj *o, + const struct tee_cryp_obj_type_props *type_props, + const TEE_Attribute *attrs, + uint32_t attr_count) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t have_attrs = 0; + size_t obj_size = 0; + size_t n = 0; + int idx = 0; + const struct attr_ops *ops = NULL; + void *attr = NULL; + + for (n = 0; n < attr_count; n++) { + idx = tee_svc_cryp_obj_find_type_attr_idx( + attrs[n].attributeID, + type_props); + /* attribute not defined in current object type */ + if (idx < 0) + return TEE_ERROR_ITEM_NOT_FOUND; + + have_attrs |= BIT32(idx); + ops = attr_ops + type_props->type_attrs[idx].ops_index; + attr = (uint8_t *)o->attr + + type_props->type_attrs[idx].raw_offs; + if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) + res = ops->from_user(attr, &attrs[n].content.value, + sizeof(attrs[n].content.value)); + else + res = ops->from_user(attr, attrs[n].content.ref.buffer, + attrs[n].content.ref.length); + if (res != TEE_SUCCESS) + return res; + + /* + * The attribute that gives the size of the object is + * flagged with TEE_TYPE_ATTR_SIZE_INDICATOR. + */ + if (type_props->type_attrs[idx].flags & + TEE_TYPE_ATTR_SIZE_INDICATOR) { + /* There should be only one */ + if (obj_size) + return TEE_ERROR_BAD_STATE; + + /* + * For ECDSA/ECDH we need to translate curve into + * object size + */ + if (attrs[n].attributeID == TEE_ATTR_ECC_CURVE) { + res = get_ec_key_size(attrs[n].content.value.a, + &obj_size); + if (res != TEE_SUCCESS) + return res; + } else { + TEE_ObjectType obj_type = o->info.objectType; + size_t sz = o->info.maxObjectSize; + + obj_size = attrs[n].content.ref.length * 8; + /* Drop the parity bits for legacy objects */ + if (is_gp_legacy_des_key_size(obj_type, sz)) + obj_size -= obj_size / 8; + } + if (obj_size > o->info.maxObjectSize) + return TEE_ERROR_BAD_STATE; + res = check_key_size(type_props, obj_size); + if (res != TEE_SUCCESS) + return TEE_ERROR_BAD_PARAMETERS; + } + + /* + * Bignum attributes limited by the number of bits in + * o->info.objectSize are flagged with + * TEE_TYPE_ATTR_BIGNUM_MAXBITS. + */ + if (type_props->type_attrs[idx].flags & + TEE_TYPE_ATTR_BIGNUM_MAXBITS) { + if (get_used_bits(attrs + n) > o->info.maxObjectSize) + return TEE_ERROR_BAD_STATE; + } + } + + o->have_attrs = have_attrs; + o->info.objectSize = obj_size; + /* + * In GP Internal API Specification 1.0 the partity bits aren't + * counted when telling the size of the key in bits so remove the + * parity bits here. + */ + if (is_gp_legacy_des_key_size(o->info.objectType, + o->info.maxObjectSize)) + o->info.objectSize -= o->info.objectSize / 8; + + return TEE_SUCCESS; +} + +TEE_Result syscall_cryp_obj_populate(unsigned long obj, + struct utee_attribute *usr_attrs, + unsigned long attr_count) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + const struct tee_cryp_obj_type_props *type_props = NULL; + TEE_Attribute *attrs = NULL; + size_t alloc_size = 0; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(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) + return TEE_ERROR_NOT_IMPLEMENTED; + + if (MUL_OVERFLOW(sizeof(TEE_Attribute), attr_count, &alloc_size)) + return TEE_ERROR_OVERFLOW; + + attrs = malloc(alloc_size); + if (!attrs) + return TEE_ERROR_OUT_OF_MEMORY; + + res = copy_in_attrs(to_user_ta_ctx(sess->ctx), usr_attrs, attr_count, + attrs); + if (res != TEE_SUCCESS) + goto out; + + res = tee_svc_cryp_check_attr(ATTR_USAGE_POPULATE, type_props, + attrs, attr_count); + if (res != TEE_SUCCESS) + goto out; + + res = tee_svc_cryp_obj_populate_type(o, type_props, attrs, attr_count); + if (res == TEE_SUCCESS) + o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + +out: + free_wipe(attrs); + return res; +} + +TEE_Result syscall_cryp_obj_copy(unsigned long dst, unsigned long src) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *dst_o = NULL; + struct tee_obj *src_o = NULL; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), + uref_to_vaddr(dst), &dst_o); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), + uref_to_vaddr(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; + + res = tee_obj_attr_copy_from(dst_o, src_o); + if (res != TEE_SUCCESS) + return res; + + 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 check_pub_rsa_key(struct bignum *e) +{ + size_t n = crypto_bignum_num_bytes(e); + uint8_t bin_key[256 / 8] = { 0 }; + + /* + * NIST SP800-56B requires public RSA key to be an odd integer in + * the range 65537 <= e < 2^256. + */ + + if (n > sizeof(bin_key) || n < 3) + return TEE_ERROR_BAD_PARAMETERS; + + crypto_bignum_bn2bin(e, bin_key); + + if (!(bin_key[n - 1] & 1)) /* key must be odd */ + return TEE_ERROR_BAD_PARAMETERS; + + if (n == 3) { + uint32_t key = 0; + + for (n = 0; n < 3; n++) { + key <<= 8; + key |= bin_key[n]; + } + + if (key < 65537) + return TEE_ERROR_BAD_PARAMETERS; + } + + /* key is larger than 65537 */ + 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, + const TEE_Attribute *params, uint32_t param_count) +{ + TEE_Result res = TEE_SUCCESS; + struct rsa_keypair *key = o->attr; + uint32_t e = TEE_U32_TO_BIG_ENDIAN(65537); + + /* Copy the present attributes into the obj before starting */ + res = tee_svc_cryp_obj_populate_type(o, type_props, params, + param_count); + if (res != TEE_SUCCESS) + return res; + if (get_attribute(o, type_props, TEE_ATTR_RSA_PUBLIC_EXPONENT)) { + res = check_pub_rsa_key(key->e); + if (res) + return res; + } else { + crypto_bignum_bin2bn((const uint8_t *)&e, sizeof(e), key->e); + } + res = crypto_acipher_gen_rsa_key(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, const TEE_Attribute *params, uint32_t param_count) +{ + TEE_Result res; + + /* Copy the present attributes into the obj before starting */ + res = tee_svc_cryp_obj_populate_type(o, type_props, params, + param_count); + if (res != TEE_SUCCESS) + return res; + + res = crypto_acipher_gen_dsa_key(o->attr, 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_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 dh_keypair *tee_dh_key; + struct bignum *dh_q = NULL; + uint32_t dh_xbits = 0; + + /* Copy the present attributes into the obj before starting */ + res = tee_svc_cryp_obj_populate_type(o, type_props, params, + param_count); + if (res != TEE_SUCCESS) + return res; + + tee_dh_key = (struct dh_keypair *)o->attr; + + 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 = crypto_acipher_gen_dh_key(tee_dh_key, dh_q, dh_xbits, key_size); + 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; +} + +static TEE_Result tee_svc_obj_generate_key_ecc( + 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 ecc_keypair *tee_ecc_key; + + /* Copy the present attributes into the obj before starting */ + res = tee_svc_cryp_obj_populate_type(o, type_props, params, + param_count); + if (res != TEE_SUCCESS) + return res; + + tee_ecc_key = (struct ecc_keypair *)o->attr; + + res = crypto_acipher_gen_ecc_key(tee_ecc_key, key_size); + if (res != TEE_SUCCESS) + return res; + + /* Set bits for the generated public and private key */ + set_attribute(o, type_props, TEE_ATTR_ECC_PRIVATE_VALUE); + set_attribute(o, type_props, TEE_ATTR_ECC_PUBLIC_VALUE_X); + set_attribute(o, type_props, TEE_ATTR_ECC_PUBLIC_VALUE_Y); + set_attribute(o, type_props, TEE_ATTR_ECC_CURVE); + return TEE_SUCCESS; +} + +static TEE_Result +tee_svc_obj_generate_key_x25519(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 = TEE_ERROR_GENERIC; + struct x25519_keypair *tee_x25519_key = NULL; + + /* Copy the present attributes into the obj before starting */ + res = tee_svc_cryp_obj_populate_type(o, type_props, params, + param_count); + if (res != TEE_SUCCESS) + return res; + + tee_x25519_key = (struct x25519_keypair *)o->attr; + + res = crypto_acipher_gen_x25519_key(tee_x25519_key, key_size); + if (res != TEE_SUCCESS) + return res; + + /* Set bits for the generated public and private key */ + set_attribute(o, type_props, TEE_ATTR_X25519_PRIVATE_VALUE); + set_attribute(o, type_props, TEE_ATTR_X25519_PUBLIC_VALUE); + return TEE_SUCCESS; +} + +static TEE_Result +tee_svc_obj_generate_key_ed25519(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 = TEE_ERROR_GENERIC; + struct ed25519_keypair *key = NULL; + + /* Copy the present attributes into the obj before starting */ + res = tee_svc_cryp_obj_populate_type(o, type_props, params, + param_count); + if (res != TEE_SUCCESS) + return res; + + key = o->attr; + + res = crypto_acipher_gen_ed25519_key(key, key_size); + if (res != TEE_SUCCESS) + return res; + + /* Set bits for the generated public and private key */ + set_attribute(o, type_props, TEE_ATTR_ED25519_PRIVATE_VALUE); + set_attribute(o, type_props, TEE_ATTR_ED25519_PUBLIC_VALUE); + return TEE_SUCCESS; +} + +static TEE_Result +tee_svc_obj_ed25519_parse_params(const TEE_Attribute *params, size_t num_params, + bool *ph_flag, const uint8_t **ctx, + size_t *ctx_len) +{ + size_t n = 0; + + *ctx = NULL; + + for (n = 0; n < num_params; n++) { + switch (params[n].attributeID) { + case TEE_ATTR_EDDSA_PREHASH: + if (params[n].content.value.b) + return TEE_ERROR_BAD_PARAMETERS; + if (!params[n].content.value.a) + *ph_flag = false; + else if (params[n].content.value.a == 1) + *ph_flag = true; + else + return TEE_ERROR_BAD_PARAMETERS; + break; + + case TEE_ATTR_EDDSA_CTX: + /* several provided contexts are treated as error */ + if (*ctx) + return TEE_ERROR_BAD_PARAMETERS; + + *ctx_len = params[n].content.ref.length; + if (*ctx_len > TEE_ED25519_CTX_MAX_LENGTH) + return TEE_ERROR_BAD_PARAMETERS; + + if (!*ctx_len) + break; + + *ctx = params[n].content.ref.buffer; + if (!*ctx) + return TEE_ERROR_BAD_PARAMETERS; + break; + + default: + return TEE_ERROR_BAD_PARAMETERS; + } + } + + return TEE_SUCCESS; +} + +static TEE_Result +tee_svc_obj_ed25519_sign(struct ed25519_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len, + const TEE_Attribute *params, size_t num_params) +{ + TEE_Result err = TEE_ERROR_GENERIC; + size_t ctx_len = 0; + const uint8_t *ctx = NULL; + bool ph_flag = false; + + err = tee_svc_obj_ed25519_parse_params(params, num_params, &ph_flag, + &ctx, &ctx_len); + if (err != TEE_SUCCESS) + return err; + + if (ph_flag || ctx) { + return crypto_acipher_ed25519ctx_sign(key, msg, msg_len, sig, + sig_len, ph_flag, + ctx, ctx_len); + } + + return crypto_acipher_ed25519_sign(key, msg, msg_len, sig, sig_len); +} + +static TEE_Result +tee_svc_obj_ed25519_verify(struct ed25519_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len, + const TEE_Attribute *params, size_t num_params) +{ + TEE_Result err = TEE_ERROR_GENERIC; + size_t ctx_len = 0; + const uint8_t *ctx = NULL; + bool ph_flag = false; + + err = tee_svc_obj_ed25519_parse_params(params, num_params, &ph_flag, + &ctx, &ctx_len); + if (err) + return err; + + if (ph_flag || ctx) { + return crypto_acipher_ed25519ctx_verify(key, msg, msg_len, sig, + sig_len, ph_flag, + ctx, ctx_len); + } + + return crypto_acipher_ed25519_verify(key, msg, msg_len, sig, sig_len); +} + +TEE_Result syscall_obj_generate_key(unsigned long obj, unsigned long key_size, + const struct utee_attribute *usr_params, + unsigned long param_count) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + const struct tee_cryp_obj_type_props *type_props = NULL; + struct tee_obj *o = NULL; + struct tee_cryp_obj_secret *key = NULL; + size_t byte_size = 0; + TEE_Attribute *params = NULL; + size_t alloc_size = 0; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(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) + return TEE_ERROR_NOT_SUPPORTED; + + /* Check that key_size follows restrictions */ + res = check_key_size(type_props, key_size); + if (res) + return res; + + if (MUL_OVERFLOW(sizeof(TEE_Attribute), param_count, &alloc_size)) + return TEE_ERROR_OVERFLOW; + + params = malloc(alloc_size); + if (!params) + return TEE_ERROR_OUT_OF_MEMORY; + res = copy_in_attrs(to_user_ta_ctx(sess->ctx), usr_params, param_count, + params); + if (res != TEE_SUCCESS) + goto out; + + res = tee_svc_cryp_check_attr(ATTR_USAGE_GENERATE_KEY, type_props, + params, param_count); + if (res != TEE_SUCCESS) + goto out; + + switch (o->info.objectType) { + case TEE_TYPE_AES: + case TEE_TYPE_DES: + case TEE_TYPE_DES3: + case TEE_TYPE_SM4: + 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_HMAC_SHA3_224: + case TEE_TYPE_HMAC_SHA3_256: + case TEE_TYPE_HMAC_SHA3_384: + case TEE_TYPE_HMAC_SHA3_512: + case TEE_TYPE_HMAC_SM3: + case TEE_TYPE_GENERIC_SECRET: + byte_size = key_size / 8; + + /* + * In GP Internal API Specification 1.0 the partity bits + * aren't counted when telling the size of the key in bits. + */ + if (is_gp_legacy_des_key_size(o->info.objectType, key_size)) + byte_size = (key_size + key_size / 7) / 8; + + key = (struct tee_cryp_obj_secret *)o->attr; + if (byte_size > key->alloc_size) { + res = TEE_ERROR_EXCESS_DATA; + goto out; + } + + res = crypto_rng_read((void *)(key + 1), byte_size); + if (res != TEE_SUCCESS) + goto out; + + 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, + params, param_count); + if (res != TEE_SUCCESS) + goto out; + break; + + case TEE_TYPE_DSA_KEYPAIR: + res = tee_svc_obj_generate_key_dsa(o, type_props, key_size, + params, param_count); + if (res != TEE_SUCCESS) + goto out; + break; + + case TEE_TYPE_DH_KEYPAIR: + res = tee_svc_obj_generate_key_dh(o, type_props, key_size, + params, param_count); + if (res != TEE_SUCCESS) + goto out; + break; + + case TEE_TYPE_ECDSA_KEYPAIR: + case TEE_TYPE_ECDH_KEYPAIR: + case TEE_TYPE_SM2_DSA_KEYPAIR: + case TEE_TYPE_SM2_KEP_KEYPAIR: + case TEE_TYPE_SM2_PKE_KEYPAIR: + res = tee_svc_obj_generate_key_ecc(o, type_props, key_size, + params, param_count); + if (res != TEE_SUCCESS) + goto out; + break; + + case TEE_TYPE_X25519_KEYPAIR: + res = tee_svc_obj_generate_key_x25519(o, type_props, key_size, + params, param_count); + if (res != TEE_SUCCESS) + goto out; + break; + + case TEE_TYPE_ED25519_KEYPAIR: + res = tee_svc_obj_generate_key_ed25519(o, type_props, key_size, + params, param_count); + if (res != TEE_SUCCESS) + goto out; + break; + + default: + res = TEE_ERROR_BAD_FORMAT; + } + +out: + free_wipe(params); + if (res == TEE_SUCCESS) { + o->info.objectSize = key_size; + o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + } + return res; +} + +static TEE_Result tee_svc_cryp_get_state(struct ts_session *sess, + vaddr_t state_id, + struct tee_cryp_state **state) +{ + struct tee_cryp_state *s; + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + + TAILQ_FOREACH(s, &utc->cryp_states, link) { + if (state_id == (vaddr_t)s) { + *state = s; + return TEE_SUCCESS; + } + } + return TEE_ERROR_BAD_PARAMETERS; +} + +static void cryp_state_free(struct user_ta_ctx *utc, struct tee_cryp_state *cs) +{ + struct tee_obj *o; + + if (tee_obj_get(utc, cs->key1, &o) == TEE_SUCCESS) + tee_obj_close(utc, o); + if (tee_obj_get(utc, cs->key2, &o) == TEE_SUCCESS) + tee_obj_close(utc, o); + + TAILQ_REMOVE(&utc->cryp_states, cs, link); + if (cs->ctx_finalize != NULL) + cs->ctx_finalize(cs->ctx); + + switch (TEE_ALG_GET_CLASS(cs->algo)) { + case TEE_OPERATION_CIPHER: + crypto_cipher_free_ctx(cs->ctx); + break; + case TEE_OPERATION_AE: + crypto_authenc_free_ctx(cs->ctx); + break; + case TEE_OPERATION_DIGEST: + crypto_hash_free_ctx(cs->ctx); + break; + case TEE_OPERATION_MAC: + crypto_mac_free_ctx(cs->ctx); + break; + default: + assert(!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; + uint32_t req_key_type2 = 0; + + 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_SHA3_224: + req_key_type = TEE_TYPE_HMAC_SHA3_224; + break; + case TEE_MAIN_ALGO_SHA3_256: + req_key_type = TEE_TYPE_HMAC_SHA3_256; + break; + case TEE_MAIN_ALGO_SHA3_384: + req_key_type = TEE_TYPE_HMAC_SHA3_384; + break; + case TEE_MAIN_ALGO_SHA3_512: + req_key_type = TEE_TYPE_HMAC_SHA3_512; + break; + case TEE_MAIN_ALGO_SM3: + req_key_type = TEE_TYPE_HMAC_SM3; + 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_SM4: + req_key_type = TEE_TYPE_SM4; + break; + case TEE_MAIN_ALGO_RSA: + req_key_type = TEE_TYPE_RSA_KEYPAIR; + if (mode == TEE_MODE_ENCRYPT || mode == TEE_MODE_VERIFY) + req_key_type2 = TEE_TYPE_RSA_PUBLIC_KEY; + break; + case TEE_MAIN_ALGO_DSA: + req_key_type = TEE_TYPE_DSA_KEYPAIR; + if (mode == TEE_MODE_ENCRYPT || mode == TEE_MODE_VERIFY) + req_key_type2 = TEE_TYPE_DSA_PUBLIC_KEY; + break; + case TEE_MAIN_ALGO_DH: + req_key_type = TEE_TYPE_DH_KEYPAIR; + break; + case TEE_MAIN_ALGO_ECDSA: + req_key_type = TEE_TYPE_ECDSA_KEYPAIR; + if (mode == TEE_MODE_VERIFY) + req_key_type2 = TEE_TYPE_ECDSA_PUBLIC_KEY; + break; + case TEE_MAIN_ALGO_ECDH: + req_key_type = TEE_TYPE_ECDH_KEYPAIR; + break; + case TEE_MAIN_ALGO_ED25519: + req_key_type = TEE_TYPE_ED25519_KEYPAIR; + if (mode == TEE_MODE_VERIFY) + req_key_type2 = TEE_TYPE_ED25519_PUBLIC_KEY; + break; + case TEE_MAIN_ALGO_SM2_PKE: + if (mode == TEE_MODE_ENCRYPT) + req_key_type = TEE_TYPE_SM2_PKE_PUBLIC_KEY; + else + req_key_type = TEE_TYPE_SM2_PKE_KEYPAIR; + break; + case TEE_MAIN_ALGO_SM2_DSA_SM3: + if (mode == TEE_MODE_VERIFY) + req_key_type = TEE_TYPE_SM2_DSA_PUBLIC_KEY; + else + req_key_type = TEE_TYPE_SM2_DSA_KEYPAIR; + break; +#if defined(CFG_CRYPTO_SM2_KEP) + case TEE_MAIN_ALGO_SM2_KEP: + req_key_type = TEE_TYPE_SM2_KEP_KEYPAIR; + req_key_type2 = TEE_TYPE_SM2_KEP_PUBLIC_KEY; + break; +#endif +#if defined(CFG_CRYPTO_HKDF) + case TEE_MAIN_ALGO_HKDF: + req_key_type = TEE_TYPE_HKDF_IKM; + break; +#endif +#if defined(CFG_CRYPTO_CONCAT_KDF) + case TEE_MAIN_ALGO_CONCAT_KDF: + req_key_type = TEE_TYPE_CONCAT_KDF_Z; + break; +#endif +#if defined(CFG_CRYPTO_PBKDF2) + case TEE_MAIN_ALGO_PBKDF2: + req_key_type = TEE_TYPE_PBKDF2_PASSWORD; + break; +#endif + case TEE_MAIN_ALGO_X25519: + req_key_type = TEE_TYPE_X25519_KEYPAIR; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (req_key_type != o->info.objectType && + req_key_type2 != o->info.objectType) + return TEE_ERROR_BAD_PARAMETERS; + return TEE_SUCCESS; +} + +static uint32_t translate_compat_algo(uint32_t algo) +{ + switch (algo) { + case __OPTEE_ALG_ECDSA_P192: + return TEE_ALG_ECDSA_SHA1; + case __OPTEE_ALG_ECDSA_P224: + return TEE_ALG_ECDSA_SHA224; + case __OPTEE_ALG_ECDSA_P256: + return TEE_ALG_ECDSA_SHA256; + case __OPTEE_ALG_ECDSA_P384: + return TEE_ALG_ECDSA_SHA384; + case __OPTEE_ALG_ECDSA_P521: + return TEE_ALG_ECDSA_SHA512; + case __OPTEE_ALG_ECDH_P192: + case __OPTEE_ALG_ECDH_P224: + case __OPTEE_ALG_ECDH_P256: + case __OPTEE_ALG_ECDH_P384: + case __OPTEE_ALG_ECDH_P521: + return TEE_ALG_ECDH_DERIVE_SHARED_SECRET; + default: + return algo; + } +} + +TEE_Result syscall_cryp_state_alloc(unsigned long algo, unsigned long mode, + unsigned long key1, unsigned long key2, + uint32_t *state) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + struct tee_cryp_state *cs = NULL; + struct tee_obj *o1 = NULL; + struct tee_obj *o2 = NULL; + + algo = translate_compat_algo(algo); + + if (key1 != 0) { + res = tee_obj_get(utc, uref_to_vaddr(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(utc, uref_to_vaddr(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) + return TEE_ERROR_OUT_OF_MEMORY; + TAILQ_INSERT_TAIL(&utc->cryp_states, cs, link); + cs->algo = algo; + cs->mode = mode; + cs->state = CRYP_STATE_UNINITIALIZED; + + switch (TEE_ALG_GET_CLASS(algo)) { + case TEE_OPERATION_CIPHER: + if ((TEE_ALG_GET_CHAIN_MODE(algo) == TEE_CHAIN_MODE_XTS && + (key1 == 0 || key2 == 0)) || + (TEE_ALG_GET_CHAIN_MODE(algo) != TEE_CHAIN_MODE_XTS && + (key1 == 0 || key2 != 0))) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + res = crypto_cipher_alloc_ctx(&cs->ctx, algo); + if (res != TEE_SUCCESS) + break; + } + break; + case TEE_OPERATION_AE: + if (key1 == 0 || key2 != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + res = crypto_authenc_alloc_ctx(&cs->ctx, algo); + if (res != TEE_SUCCESS) + break; + } + break; + case TEE_OPERATION_MAC: + if (key1 == 0 || key2 != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + res = crypto_mac_alloc_ctx(&cs->ctx, algo); + if (res != TEE_SUCCESS) + break; + } + break; + case TEE_OPERATION_DIGEST: + if (key1 != 0 || key2 != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + res = crypto_hash_alloc_ctx(&cs->ctx, algo); + if (res != TEE_SUCCESS) + break; + } + break; + case TEE_OPERATION_ASYMMETRIC_CIPHER: + case TEE_OPERATION_ASYMMETRIC_SIGNATURE: + if (algo == TEE_ALG_RSASSA_PKCS1_V1_5 && + !IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) { + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + if (key1 == 0 || key2 != 0) + res = TEE_ERROR_BAD_PARAMETERS; + break; + case TEE_OPERATION_KEY_DERIVATION: + if (algo == TEE_ALG_SM2_KEP) { + if (key1 == 0 || key2 == 0) + res = TEE_ERROR_BAD_PARAMETERS; + } else { + 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 = copy_kaddr_to_uref(state, cs); + if (res != TEE_SUCCESS) + goto out; + + /* Register keys */ + if (o1 != NULL) { + o1->busy = true; + cs->key1 = (vaddr_t)o1; + } + if (o2 != NULL) { + o2->busy = true; + cs->key2 = (vaddr_t)o2; + } + +out: + if (res != TEE_SUCCESS) + cryp_state_free(utc, cs); + return res; +} + +TEE_Result syscall_cryp_state_copy(unsigned long dst, unsigned long src) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_cryp_state *cs_dst = NULL; + struct tee_cryp_state *cs_src = NULL; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(dst), &cs_dst); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(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; + + switch (TEE_ALG_GET_CLASS(cs_src->algo)) { + case TEE_OPERATION_CIPHER: + crypto_cipher_copy_state(cs_dst->ctx, cs_src->ctx); + break; + case TEE_OPERATION_AE: + crypto_authenc_copy_state(cs_dst->ctx, cs_src->ctx); + break; + case TEE_OPERATION_DIGEST: + crypto_hash_copy_state(cs_dst->ctx, cs_src->ctx); + break; + case TEE_OPERATION_MAC: + crypto_mac_copy_state(cs_dst->ctx, cs_src->ctx); + break; + default: + return TEE_ERROR_BAD_STATE; + } + + cs_dst->state = cs_src->state; + cs_dst->ctx_finalize = cs_src->ctx_finalize; + + return TEE_SUCCESS; +} + +void tee_svc_cryp_free_states(struct user_ta_ctx *utc) +{ + struct tee_cryp_state_head *states = &utc->cryp_states; + + while (!TAILQ_EMPTY(states)) + cryp_state_free(utc, TAILQ_FIRST(states)); +} + +TEE_Result syscall_cryp_state_free(unsigned long state) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_cryp_state *cs = NULL; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + cryp_state_free(to_user_ta_ctx(sess->ctx), cs); + return TEE_SUCCESS; +} + +TEE_Result syscall_hash_init(unsigned long state, + const void *iv __maybe_unused, + size_t iv_len __maybe_unused) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_cryp_state *cs = NULL; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + switch (TEE_ALG_GET_CLASS(cs->algo)) { + case TEE_OPERATION_DIGEST: + res = crypto_hash_init(cs->ctx); + 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(to_user_ta_ctx(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->attr; + res = crypto_mac_init(cs->ctx, (void *)(key + 1), + key->key_size); + if (res != TEE_SUCCESS) + return res; + break; + } + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + cs->state = CRYP_STATE_INITIALIZED; + + return TEE_SUCCESS; +} + +TEE_Result syscall_hash_update(unsigned long state, const void *chunk, + size_t chunk_size) +{ + struct ts_session *sess = ts_get_current_session(); + struct tee_cryp_state *cs = NULL; + TEE_Result res = TEE_SUCCESS; + + /* No data, but size provided isn't valid parameters. */ + if (!chunk && chunk_size) + return TEE_ERROR_BAD_PARAMETERS; + + /* Zero length hash is valid, but nothing we need to do. */ + if (!chunk_size) + return TEE_SUCCESS; + + chunk = memtag_strip_tag_const(chunk); + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->state != CRYP_STATE_INITIALIZED) + return TEE_ERROR_BAD_STATE; + + switch (TEE_ALG_GET_CLASS(cs->algo)) { + case TEE_OPERATION_DIGEST: + res = crypto_hash_update(cs->ctx, chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + break; + case TEE_OPERATION_MAC: + res = crypto_mac_update(cs->ctx, chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} + +static bool is_xof_algo(uint32_t algo) +{ + return algo == TEE_ALG_SHAKE128 || algo == TEE_ALG_SHAKE256; +} + +TEE_Result syscall_hash_final(unsigned long state, const void *chunk, + size_t chunk_size, void *hash, uint64_t *hash_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct tee_cryp_state *cs = NULL; + TEE_Result res2 = TEE_SUCCESS; + TEE_Result res = TEE_SUCCESS; + size_t hash_size = 0; + size_t hlen = 0; + + /* No data, but size provided isn't valid parameters. */ + if (!chunk && chunk_size) + return TEE_ERROR_BAD_PARAMETERS; + + chunk = memtag_strip_tag_const(chunk); + hash = memtag_strip_tag(hash); + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + + res = get_user_u64_as_size_t(&hlen, hash_len); + if (res != TEE_SUCCESS) + return res; + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)hash, hlen); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->state != CRYP_STATE_INITIALIZED) + return TEE_ERROR_BAD_STATE; + + switch (TEE_ALG_GET_CLASS(cs->algo)) { + case TEE_OPERATION_DIGEST: + if (is_xof_algo(cs->algo)) { + if (chunk_size) { + res = crypto_hash_update(cs->ctx, chunk, + chunk_size); + if (res) + return res; + } + + /* + * hash_size is supposed to be unchanged for XOF + * algorithms so return directly. + */ + return crypto_hash_final(cs->ctx, hash, hlen); + } + + res = tee_alg_get_digest_size(cs->algo, &hash_size); + if (res != TEE_SUCCESS) + return res; + if (hlen < hash_size) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + if (chunk_size) { + res = crypto_hash_update(cs->ctx, chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + } + + res = crypto_hash_final(cs->ctx, hash, hash_size); + if (res != TEE_SUCCESS) + return res; + break; + + case TEE_OPERATION_MAC: + res = tee_alg_get_digest_size(cs->algo, &hash_size); + if (res != TEE_SUCCESS) + return res; + if (hlen < hash_size) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + if (chunk_size) { + res = crypto_mac_update(cs->ctx, chunk, chunk_size); + if (res != TEE_SUCCESS) + return res; + } + + res = crypto_mac_final(cs->ctx, hash, hash_size); + if (res != TEE_SUCCESS) + return res; + break; + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +out: + res2 = put_user_u64(hash_len, hash_size); + if (res2 != TEE_SUCCESS) + return res2; + return res; +} + +TEE_Result syscall_cipher_init(unsigned long state, const void *iv, + size_t iv_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + struct tee_cryp_obj_secret *key1 = NULL; + struct tee_cryp_state *cs = NULL; + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_CIPHER) + return TEE_ERROR_BAD_STATE; + + iv = memtag_strip_tag_const(iv); + + res = vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)iv, iv_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(utc, cs->key1, &o); + if (res != TEE_SUCCESS) + return res; + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + + key1 = o->attr; + + if (tee_obj_get(utc, cs->key2, &o) == TEE_SUCCESS) { + struct tee_cryp_obj_secret *key2 = o->attr; + + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) + return TEE_ERROR_BAD_PARAMETERS; + + res = crypto_cipher_init(cs->ctx, cs->mode, + (uint8_t *)(key1 + 1), key1->key_size, + (uint8_t *)(key2 + 1), key2->key_size, + iv, iv_len); + } else { + res = crypto_cipher_init(cs->ctx, cs->mode, + (uint8_t *)(key1 + 1), key1->key_size, + NULL, 0, iv, iv_len); + } + if (res != TEE_SUCCESS) + return res; + + cs->ctx_finalize = crypto_cipher_final; + cs->state = CRYP_STATE_INITIALIZED; + + return TEE_SUCCESS; +} + +static TEE_Result tee_svc_cipher_update_helper(unsigned long state, + bool last_block, const void *src, size_t src_len, + void *dst, uint64_t *dst_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct tee_cryp_state *cs = NULL; + TEE_Result res = TEE_SUCCESS; + size_t dlen = 0; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->state != CRYP_STATE_INITIALIZED) + return TEE_ERROR_BAD_STATE; + + src = memtag_strip_tag_const(src); + dst = memtag_strip_tag(dst); + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)src, src_len); + if (res != TEE_SUCCESS) + return res; + + if (!dst_len) { + dlen = 0; + } else { + struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx; + uint32_t flags = TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER; + + res = get_user_u64_as_size_t(&dlen, dst_len); + if (res != TEE_SUCCESS) + return res; + + res = vm_check_access_rights(uctx, flags, (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_do_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->ctx_finalize = NULL; + } + +out: + if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) && + dst_len != NULL) { + TEE_Result res2; + + res2 = put_user_u64(dst_len, src_len); + if (res2 != TEE_SUCCESS) + res = res2; + } + + return res; +} + +TEE_Result syscall_cipher_update(unsigned long state, const void *src, + size_t src_len, void *dst, uint64_t *dst_len) +{ + return tee_svc_cipher_update_helper(state, false /* last_block */, + src, src_len, dst, dst_len); +} + +TEE_Result syscall_cipher_final(unsigned long state, const void *src, + size_t src_len, void *dst, uint64_t *dst_len) +{ + return tee_svc_cipher_update_helper(state, true /* last_block */, + src, src_len, dst, dst_len); +} + +#if defined(CFG_CRYPTO_HKDF) +static TEE_Result get_hkdf_params(uint32_t algo, const TEE_Attribute *params, + uint32_t param_count, + void **salt, size_t *salt_len, void **info, + size_t *info_len, size_t *okm_len, + uint32_t *hash_id) +{ + size_t n; + enum { SALT = 0x1, LENGTH = 0x2, INFO = 0x4, HASH = 0x8 }; + uint8_t found = 0; + + *salt = *info = NULL; + *salt_len = *info_len = *okm_len = 0; + + if (algo == TEE_ALG_HKDF) { + *hash_id = TEE_ALG_SHA256; + } else { + *hash_id = TEE_ALG_GET_DIGEST_HASH(algo); + found |= HASH; + } + + for (n = 0; n < param_count; n++) { + switch (params[n].attributeID) { + case __OPTEE_TEE_ATTR_HKDF_SALT: + case TEE_ATTR_HKDF_SALT: + if (!(found & SALT)) { + *salt = params[n].content.ref.buffer; + *salt_len = params[n].content.ref.length; + found |= SALT; + } + break; + case TEE_ATTR_KDF_KEY_SIZE: + case TEE_ATTR_HKDF_OKM_LENGTH: + if (!(found & LENGTH)) { + *okm_len = params[n].content.value.a; + found |= LENGTH; + } + break; + case __OPTEE_ATTR_HKDF_INFO: + case TEE_ATTR_HKDF_INFO: + if (!(found & INFO)) { + *info = params[n].content.ref.buffer; + *info_len = params[n].content.ref.length; + found |= INFO; + } + break; + case TEE_ATTR_HKDF_HASH_ALGORITHM: + if (!(found & HASH)) { + *hash_id = params[n].content.value.a; + found |= HASH; + } + break; + default: + /* Unexpected attribute */ + return TEE_ERROR_BAD_PARAMETERS; + } + + } + + if (!(found & LENGTH)) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} +#endif + +#if defined(CFG_CRYPTO_CONCAT_KDF) +static TEE_Result get_concat_kdf_params(const TEE_Attribute *params, + uint32_t param_count, + void **other_info, + size_t *other_info_len, + size_t *derived_key_len) +{ + size_t n; + enum { LENGTH = 0x1, INFO = 0x2 }; + uint8_t found = 0; + + *other_info = NULL; + *other_info_len = *derived_key_len = 0; + + for (n = 0; n < param_count; n++) { + switch (params[n].attributeID) { + case TEE_ATTR_CONCAT_KDF_OTHER_INFO: + if (!(found & INFO)) { + *other_info = params[n].content.ref.buffer; + *other_info_len = params[n].content.ref.length; + found |= INFO; + } + break; + case TEE_ATTR_CONCAT_KDF_DKM_LENGTH: + if (!(found & LENGTH)) { + *derived_key_len = params[n].content.value.a; + found |= LENGTH; + } + break; + default: + /* Unexpected attribute */ + return TEE_ERROR_BAD_PARAMETERS; + } + } + + if (!(found & LENGTH)) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} +#endif + +#if defined(CFG_CRYPTO_PBKDF2) +static TEE_Result get_pbkdf2_params(const TEE_Attribute *params, + uint32_t param_count, void **salt, + size_t *salt_len, size_t *derived_key_len, + size_t *iteration_count) +{ + size_t n; + enum { SALT = 0x1, LENGTH = 0x2, COUNT = 0x4 }; + uint8_t found = 0; + + *salt = NULL; + *salt_len = *derived_key_len = *iteration_count = 0; + + for (n = 0; n < param_count; n++) { + switch (params[n].attributeID) { + case TEE_ATTR_PBKDF2_SALT: + if (!(found & SALT)) { + *salt = params[n].content.ref.buffer; + *salt_len = params[n].content.ref.length; + found |= SALT; + } + break; + case TEE_ATTR_PBKDF2_DKM_LENGTH: + if (!(found & LENGTH)) { + *derived_key_len = params[n].content.value.a; + found |= LENGTH; + } + break; + case TEE_ATTR_PBKDF2_ITERATION_COUNT: + if (!(found & COUNT)) { + *iteration_count = params[n].content.value.a; + found |= COUNT; + } + break; + default: + /* Unexpected attribute */ + return TEE_ERROR_BAD_PARAMETERS; + } + } + + if ((found & (LENGTH|COUNT)) != (LENGTH|COUNT)) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} +#endif + +#if defined(CFG_CRYPTO_SM2_KEP) +static TEE_Result get_sm2_kep_params(const TEE_Attribute *params, + uint32_t param_count, + struct ecc_public_key *peer_key, + struct ecc_public_key *peer_eph_key, + struct sm2_kep_parms *kep_parms) +{ + TEE_Result res = TEE_ERROR_GENERIC; + size_t n; + enum { + IS_INITIATOR, + PEER_KEY_X, + PEER_KEY_Y, + PEER_EPH_KEY_X, + PEER_EPH_KEY_Y, + INITIATOR_ID, + RESPONDER_ID, + }; + uint8_t mandatory = BIT(IS_INITIATOR) | BIT(PEER_KEY_X) | + BIT(PEER_KEY_Y) | BIT(PEER_EPH_KEY_X) | BIT(PEER_EPH_KEY_Y) | + BIT(INITIATOR_ID) | BIT(RESPONDER_ID); + uint8_t found = 0; + + res = crypto_acipher_alloc_ecc_public_key(peer_key, + TEE_TYPE_SM2_KEP_PUBLIC_KEY, + 256); + if (res) + return res; + + res = crypto_acipher_alloc_ecc_public_key(peer_eph_key, + TEE_TYPE_SM2_KEP_PUBLIC_KEY, + 256); + if (res) + goto out_p; + + peer_key->curve = TEE_ECC_CURVE_SM2; + peer_eph_key->curve = TEE_ECC_CURVE_SM2; + + for (n = 0; n < param_count; n++) { + const TEE_Attribute *p = ¶ms[n]; + + switch (p->attributeID) { + case TEE_ATTR_SM2_KEP_USER: + kep_parms->is_initiator = !p->content.value.a; + found |= BIT(IS_INITIATOR); + break; + case TEE_ATTR_ECC_PUBLIC_VALUE_X: + crypto_bignum_bin2bn(p->content.ref.buffer, + p->content.ref.length, + peer_key->x); + found |= BIT(PEER_KEY_X); + break; + case TEE_ATTR_ECC_PUBLIC_VALUE_Y: + crypto_bignum_bin2bn(p->content.ref.buffer, + p->content.ref.length, + peer_key->y); + found |= BIT(PEER_KEY_Y); + break; + case __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X: + case TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X: + crypto_bignum_bin2bn(p->content.ref.buffer, + p->content.ref.length, + peer_eph_key->x); + found |= BIT(PEER_EPH_KEY_X); + break; + case __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y: + case TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y: + crypto_bignum_bin2bn(p->content.ref.buffer, + p->content.ref.length, + peer_eph_key->y); + found |= BIT(PEER_EPH_KEY_Y); + break; + case TEE_ATTR_SM2_ID_INITIATOR: + kep_parms->initiator_id = p->content.ref.buffer; + kep_parms->initiator_id_len = p->content.ref.length; + found |= BIT(INITIATOR_ID); + break; + case TEE_ATTR_SM2_ID_RESPONDER: + kep_parms->responder_id = p->content.ref.buffer; + kep_parms->responder_id_len = p->content.ref.length; + found |= BIT(RESPONDER_ID); + break; + case TEE_ATTR_SM2_KEP_CONFIRMATION_IN: + kep_parms->conf_in = p->content.ref.buffer; + kep_parms->conf_in_len = p->content.ref.length; + break; + case TEE_ATTR_SM2_KEP_CONFIRMATION_OUT: + kep_parms->conf_out = p->content.ref.buffer; + kep_parms->conf_out_len = p->content.ref.length; + break; + default: + /* Unexpected attribute */ + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + } + + if ((found & mandatory) != mandatory) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + return TEE_SUCCESS; +out: + crypto_acipher_free_ecc_public_key(peer_eph_key); +out_p: + crypto_acipher_free_ecc_public_key(peer_key); + return res; +} +#endif + +TEE_Result syscall_cryp_derive_key(unsigned long state, + const struct utee_attribute *usr_params, + unsigned long param_count, unsigned long derived_key) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_ERROR_NOT_SUPPORTED; + struct tee_obj *ko = NULL; + struct tee_obj *so = NULL; + struct tee_cryp_state *cs = NULL; + struct tee_cryp_obj_secret *sk = NULL; + const struct tee_cryp_obj_type_props *type_props = NULL; + TEE_Attribute *params = NULL; + size_t alloc_size = 0; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (MUL_OVERFLOW(sizeof(TEE_Attribute), param_count, &alloc_size)) + return TEE_ERROR_OVERFLOW; + + params = malloc(alloc_size); + if (!params) + return TEE_ERROR_OUT_OF_MEMORY; + res = copy_in_attrs(utc, usr_params, param_count, params); + if (res != TEE_SUCCESS) + goto out; + + /* Get key set in operation */ + res = tee_obj_get(utc, cs->key1, &ko); + if (res != TEE_SUCCESS) + goto out; + + res = tee_obj_get(utc, uref_to_vaddr(derived_key), &so); + if (res != TEE_SUCCESS) + goto out; + + /* Find information needed about the object to initialize */ + sk = so->attr; + + /* Find description of object */ + type_props = tee_svc_find_type_props(so->info.objectType); + if (!type_props) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + if (cs->algo == TEE_ALG_DH_DERIVE_SHARED_SECRET) { + struct bignum *pub = NULL; + struct bignum *ss = NULL; + size_t bin_size = 0; + + if (param_count != 1 || + params[0].attributeID != TEE_ATTR_DH_PUBLIC_VALUE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + bin_size = params[0].content.ref.length; + + if (MUL_OVERFLOW(bin_size, 8, &alloc_size)) { + res = TEE_ERROR_OVERFLOW; + goto out; + } + + pub = crypto_bignum_allocate(alloc_size); + ss = crypto_bignum_allocate(alloc_size); + if (pub && ss) { + crypto_bignum_bin2bn(params[0].content.ref.buffer, + bin_size, pub); + res = crypto_acipher_dh_shared_secret(ko->attr, + pub, ss); + if (res == TEE_SUCCESS) { + sk->key_size = crypto_bignum_num_bytes(ss); + crypto_bignum_bn2bin(ss, (uint8_t *)(sk + 1)); + so->info.handleFlags |= + TEE_HANDLE_FLAG_INITIALIZED; + set_attribute(so, type_props, + TEE_ATTR_SECRET_VALUE); + } + } else { + res = TEE_ERROR_OUT_OF_MEMORY; + } + crypto_bignum_free(pub); + crypto_bignum_free(ss); + } else if (cs->algo == TEE_ALG_ECDH_DERIVE_SHARED_SECRET) { + uint32_t curve = ((struct ecc_keypair *)ko->attr)->curve; + struct ecc_public_key key_public = { }; + uint8_t *pt_secret = NULL; + unsigned long pt_secret_len = 0; + uint32_t key_type = TEE_TYPE_ECDH_PUBLIC_KEY; + + if (param_count != 2 || + params[0].attributeID != TEE_ATTR_ECC_PUBLIC_VALUE_X || + params[1].attributeID != TEE_ATTR_ECC_PUBLIC_VALUE_Y) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + alloc_size = 192; + break; + case TEE_ECC_CURVE_NIST_P224: + alloc_size = 224; + break; + case TEE_ECC_CURVE_NIST_P256: + alloc_size = 256; + break; + case TEE_ECC_CURVE_NIST_P384: + alloc_size = 384; + break; + case TEE_ECC_CURVE_NIST_P521: + alloc_size = 521; + break; + default: + res = TEE_ERROR_NOT_IMPLEMENTED; + goto out; + } + + /* Create the public key */ + res = crypto_acipher_alloc_ecc_public_key(&key_public, key_type, + alloc_size); + if (res != TEE_SUCCESS) + goto out; + key_public.curve = curve; + crypto_bignum_bin2bn(params[0].content.ref.buffer, + params[0].content.ref.length, + key_public.x); + crypto_bignum_bin2bn(params[1].content.ref.buffer, + params[1].content.ref.length, + key_public.y); + + pt_secret = (uint8_t *)(sk + 1); + pt_secret_len = sk->alloc_size; + res = crypto_acipher_ecc_shared_secret(ko->attr, &key_public, + pt_secret, + &pt_secret_len); + + if (res == TEE_SUCCESS) { + sk->key_size = pt_secret_len; + so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); + } + + /* free the public key */ + crypto_acipher_free_ecc_public_key(&key_public); + } +#if defined(CFG_CRYPTO_HKDF) + else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_HKDF) { + void *salt, *info; + size_t salt_len, info_len, okm_len; + uint32_t hash_id = 0; + struct tee_cryp_obj_secret *ik = ko->attr; + const uint8_t *ikm = (const uint8_t *)(ik + 1); + + res = get_hkdf_params(cs->algo, params, param_count, &salt, + &salt_len, &info, &info_len, &okm_len, + &hash_id); + if (res != TEE_SUCCESS) + goto out; + + /* Requested size must fit into the output object's buffer */ + if (okm_len > ik->alloc_size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = tee_cryp_hkdf(hash_id, ikm, ik->key_size, salt, salt_len, + info, info_len, (uint8_t *)(sk + 1), + okm_len); + if (res == TEE_SUCCESS) { + sk->key_size = okm_len; + so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); + } + } +#endif +#if defined(CFG_CRYPTO_CONCAT_KDF) + else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_CONCAT_KDF) { + void *info; + size_t info_len, derived_key_len; + uint32_t hash_id = TEE_ALG_GET_DIGEST_HASH(cs->algo); + struct tee_cryp_obj_secret *ss = ko->attr; + const uint8_t *shared_secret = (const uint8_t *)(ss + 1); + + res = get_concat_kdf_params(params, param_count, &info, + &info_len, &derived_key_len); + if (res != TEE_SUCCESS) + goto out; + + /* Requested size must fit into the output object's buffer */ + if (derived_key_len > ss->alloc_size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = tee_cryp_concat_kdf(hash_id, shared_secret, ss->key_size, + info, info_len, (uint8_t *)(sk + 1), + derived_key_len); + if (res == TEE_SUCCESS) { + sk->key_size = derived_key_len; + so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); + } + } +#endif +#if defined(CFG_CRYPTO_PBKDF2) + else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_PBKDF2) { + void *salt; + size_t salt_len, iteration_count, derived_key_len; + uint32_t hash_id = TEE_ALG_GET_DIGEST_HASH(cs->algo); + struct tee_cryp_obj_secret *ss = ko->attr; + const uint8_t *password = (const uint8_t *)(ss + 1); + + res = get_pbkdf2_params(params, param_count, &salt, &salt_len, + &derived_key_len, &iteration_count); + if (res != TEE_SUCCESS) + goto out; + + /* Requested size must fit into the output object's buffer */ + if (derived_key_len > ss->alloc_size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = tee_cryp_pbkdf2(hash_id, password, ss->key_size, salt, + salt_len, iteration_count, + (uint8_t *)(sk + 1), derived_key_len); + if (res == TEE_SUCCESS) { + sk->key_size = derived_key_len; + so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); + } + } +#endif +#if defined(CFG_CRYPTO_SM2_KEP) + else if (cs->algo == TEE_ALG_SM2_KEP) { + struct ecc_public_key peer_eph_key = { }; + struct ecc_public_key peer_key = { }; + struct sm2_kep_parms kep_parms = { + .out = (uint8_t *)(sk + 1), + .out_len = so->info.maxObjectSize, + }; + struct tee_obj *ko2 = NULL; + + res = tee_obj_get(utc, cs->key2, &ko2); + if (res != TEE_SUCCESS) + goto out; + + res = get_sm2_kep_params(params, param_count, &peer_key, + &peer_eph_key, &kep_parms); + if (res != TEE_SUCCESS) + goto out; + + /* + * key1 is our private keypair, key2 is our ephemeral public key + */ + res = crypto_acipher_sm2_kep_derive(ko->attr, /* key1 */ + ko2->attr, /* key2 */ + &peer_key, &peer_eph_key, + &kep_parms); + + if (res == TEE_SUCCESS) { + sk->key_size = kep_parms.out_len; + so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); + } + crypto_acipher_free_ecc_public_key(&peer_key); + crypto_acipher_free_ecc_public_key(&peer_eph_key); + } +#endif +#if defined(CFG_CRYPTO_X25519) + else if (cs->algo == TEE_ALG_X25519) { + uint8_t *x25519_pub_key = NULL; + uint8_t *pt_secret = NULL; + unsigned long pt_secret_len = 0; + + if (param_count != 1 || + params[0].attributeID != TEE_ATTR_X25519_PUBLIC_VALUE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* X25519 public key size is 32 bytes */ + if (params[0].content.ref.length != KEY_SIZE_BYTES_25519) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* Set the public key */ + x25519_pub_key = params[0].content.ref.buffer; + + pt_secret = (uint8_t *)(sk + 1); + pt_secret_len = sk->alloc_size; + res = crypto_acipher_x25519_shared_secret(ko->attr, + x25519_pub_key, + pt_secret, + &pt_secret_len); + + if (res == TEE_SUCCESS) { + sk->key_size = pt_secret_len; + so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; + set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); + } + } +#endif + else + res = TEE_ERROR_NOT_SUPPORTED; + +out: + free_wipe(params); + return res; +} + +TEE_Result syscall_cryp_random_number_generate(void *buf, size_t blen) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + + buf = memtag_strip_tag(buf); + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_WRITE, + (uaddr_t)buf, blen); + if (res != TEE_SUCCESS) + return res; + + res = crypto_rng_read(buf, blen); + if (res != TEE_SUCCESS) + return res; + + return res; +} + +TEE_Result syscall_authenc_init(unsigned long state, const void *nonce, + size_t nonce_len, size_t tag_len, + size_t aad_len, size_t payload_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct tee_cryp_obj_secret *key = NULL; + struct tee_cryp_state *cs = NULL; + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + + nonce = memtag_strip_tag_const(nonce); + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)nonce, nonce_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + res = tee_obj_get(to_user_ta_ctx(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 = o->attr; + res = crypto_authenc_init(cs->ctx, 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 = crypto_authenc_final; + cs->state = CRYP_STATE_INITIALIZED; + + return TEE_SUCCESS; +} + +TEE_Result syscall_authenc_update_aad(unsigned long state, + const void *aad_data, size_t aad_data_len) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_cryp_state *cs = NULL; + + aad_data = memtag_strip_tag_const(aad_data); + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)aad_data, aad_data_len); + if (res != TEE_SUCCESS) + return res; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->state != CRYP_STATE_INITIALIZED) + return TEE_ERROR_BAD_STATE; + + if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE) + return TEE_ERROR_BAD_STATE; + + res = crypto_authenc_update_aad(cs->ctx, cs->mode, aad_data, + aad_data_len); + if (res != TEE_SUCCESS) + return res; + + return TEE_SUCCESS; +} + +TEE_Result syscall_authenc_update_payload(unsigned long state, + const void *src_data, + size_t src_len, void *dst_data, + uint64_t *dst_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct tee_cryp_state *cs = NULL; + TEE_Result res = TEE_SUCCESS; + size_t dlen = 0; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->state != CRYP_STATE_INITIALIZED) + return TEE_ERROR_BAD_STATE; + + if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE) + return TEE_ERROR_BAD_STATE; + + src_data = memtag_strip_tag_const(src_data); + dst_data = memtag_strip_tag(dst_data); + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)src_data, src_len); + if (res != TEE_SUCCESS) + return res; + + res = get_user_u64_as_size_t(&dlen, dst_len); + if (res != TEE_SUCCESS) + return res; + + res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)dst_data, dlen); + if (res != TEE_SUCCESS) + return res; + + if (dlen < src_len) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = crypto_authenc_update_payload(cs->ctx, cs->mode, src_data, + src_len, dst_data, &dlen); +out: + if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { + TEE_Result res2 = put_user_u64(dst_len, dlen); + + if (res2 != TEE_SUCCESS) + res = res2; + } + + return res; +} + +TEE_Result syscall_authenc_enc_final(unsigned long state, const void *src_data, + size_t src_len, void *dst_data, + uint64_t *dst_len, void *tag, + uint64_t *tag_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx; + struct tee_cryp_state *cs = NULL; + TEE_Result res = TEE_SUCCESS; + size_t dlen = 0; + size_t tlen = 0; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->state != CRYP_STATE_INITIALIZED) + return TEE_ERROR_BAD_STATE; + + if (cs->mode != TEE_MODE_ENCRYPT) + return TEE_ERROR_BAD_PARAMETERS; + + if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE) + return TEE_ERROR_BAD_STATE; + + src_data = memtag_strip_tag_const(src_data); + dst_data = memtag_strip_tag(dst_data); + tag = memtag_strip_tag(tag); + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)src_data, src_len); + if (res != TEE_SUCCESS) + return res; + + if (!dst_len) { + dlen = 0; + } else { + res = get_user_u64_as_size_t(&dlen, dst_len); + if (res != TEE_SUCCESS) + return res; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)dst_data, dlen); + if (res != TEE_SUCCESS) + return res; + } + + if (dlen < src_len) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = get_user_u64_as_size_t(&tlen, tag_len); + if (res != TEE_SUCCESS) + return res; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)tag, tlen); + if (res != TEE_SUCCESS) + return res; + + res = crypto_authenc_enc_final(cs->ctx, src_data, src_len, dst_data, + &dlen, tag, &tlen); + +out: + if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { + TEE_Result res2 = TEE_SUCCESS; + + if (dst_len != NULL) { + res2 = put_user_u64(dst_len, dlen); + if (res2 != TEE_SUCCESS) + return res2; + } + + res2 = put_user_u64(tag_len, tlen); + if (res2 != TEE_SUCCESS) + return res2; + } + + return res; +} + +TEE_Result syscall_authenc_dec_final(unsigned long state, + const void *src_data, size_t src_len, void *dst_data, + uint64_t *dst_len, const void *tag, size_t tag_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx; + struct tee_cryp_state *cs = NULL; + TEE_Result res = TEE_SUCCESS; + size_t dlen = 0; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->state != CRYP_STATE_INITIALIZED) + return TEE_ERROR_BAD_STATE; + + if (cs->mode != TEE_MODE_DECRYPT) + return TEE_ERROR_BAD_PARAMETERS; + + if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE) + return TEE_ERROR_BAD_STATE; + + src_data = memtag_strip_tag_const(src_data); + dst_data = memtag_strip_tag(dst_data); + tag = memtag_strip_tag_const(tag); + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)src_data, src_len); + if (res != TEE_SUCCESS) + return res; + + if (!dst_len) { + dlen = 0; + } else { + res = get_user_u64_as_size_t(&dlen, dst_len); + if (res != TEE_SUCCESS) + return res; + + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)dst_data, dlen); + if (res != TEE_SUCCESS) + return res; + } + + if (dlen < src_len) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + /* Despite TEE Internal Core API up to v1.3, tag is [inbuf], not [in] */ + res = vm_check_access_rights(uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)tag, tag_len); + if (res != TEE_SUCCESS) + return res; + + res = crypto_authenc_dec_final(cs->ctx, src_data, src_len, dst_data, + &dlen, tag, tag_len); + +out: + if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) && + dst_len != NULL) { + TEE_Result res2 = put_user_u64(dst_len, dlen); + + if (res2 != TEE_SUCCESS) + return res2; + } + + return res; +} + +static int pkcs1_get_salt_len(const TEE_Attribute *params, uint32_t num_params, + size_t default_len) +{ + size_t n; + + assert(default_len < INT_MAX); + + for (n = 0; n < num_params; n++) { + if (params[n].attributeID == TEE_ATTR_RSA_PSS_SALT_LENGTH) { + if (params[n].content.value.a < INT_MAX) + return params[n].content.value.a; + break; + } + } + /* + * If salt length isn't provided use the default value which is + * the length of the digest. + */ + return default_len; +} + +TEE_Result syscall_asymm_operate(unsigned long state, + const struct utee_attribute *usr_params, + size_t num_params, const void *src_data, size_t src_len, + void *dst_data, uint64_t *dst_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + struct tee_cryp_state *cs = NULL; + size_t dlen = 0; + struct tee_obj *o = NULL; + void *label = NULL; + size_t label_len = 0; + size_t n = 0; + int salt_len = 0; + TEE_Attribute *params = NULL; + size_t alloc_size = 0; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + src_data = memtag_strip_tag_const(src_data); + dst_data = memtag_strip_tag(dst_data); + + res = vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)src_data, src_len); + if (res != TEE_SUCCESS) + return res; + + res = get_user_u64_as_size_t(&dlen, dst_len); + if (res != TEE_SUCCESS) + return res; + + res = vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)dst_data, dlen); + if (res != TEE_SUCCESS) + return res; + + if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size)) + return TEE_ERROR_OVERFLOW; + + params = malloc(alloc_size); + if (!params) + return TEE_ERROR_OUT_OF_MEMORY; + res = copy_in_attrs(utc, usr_params, num_params, params); + if (res != TEE_SUCCESS) + goto out; + + res = tee_obj_get(utc, cs->key1, &o); + if (res != TEE_SUCCESS) + goto out; + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_GENERIC; + goto out; + } + + switch (cs->algo) { + case TEE_ALG_RSA_NOPAD: + if (cs->mode == TEE_MODE_ENCRYPT) { + res = crypto_acipher_rsanopad_encrypt(o->attr, src_data, + src_len, dst_data, + &dlen); + } else if (cs->mode == TEE_MODE_DECRYPT) { + res = crypto_acipher_rsanopad_decrypt(o->attr, src_data, + src_len, dst_data, + &dlen); + } else { + /* + * We will panic because "the mode is not compatible + * with the function" + */ + res = TEE_ERROR_GENERIC; + } + break; + + case TEE_ALG_SM2_PKE: + if (cs->mode == TEE_MODE_ENCRYPT) { + res = crypto_acipher_sm2_pke_encrypt(o->attr, src_data, + src_len, dst_data, + &dlen); + } else if (cs->mode == TEE_MODE_DECRYPT) { + res = crypto_acipher_sm2_pke_decrypt(o->attr, src_data, + src_len, dst_data, + &dlen); + } else { + res = TEE_ERROR_GENERIC; + } + break; + + case TEE_ALG_RSAES_PKCS1_V1_5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5: + 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 the optional TEE_ATTR_RSA_OAEP_MGF_HASH is + * provided for algorithm + * TEE_ALG_RSAES_PKCS1_OAEP_MGF1_x it must match + * the internal hash x since we don't support using + * a different hash for MGF1 yet. + */ + if (cs->algo != TEE_ALG_RSAES_PKCS1_V1_5 && + params[n].attributeID == + TEE_ATTR_RSA_OAEP_MGF_HASH) { + uint32_t hash = 0; + + if (params[n].content.ref.length != + sizeof(hash)) { + res = TEE_ERROR_BAD_PARAMETERS; + break; + } + memcpy(&hash, params[n].content.ref.buffer, + sizeof(hash)); + if (hash != + TEE_INTERNAL_HASH_TO_ALGO(cs->algo)) { + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + } + } + + if (cs->mode == TEE_MODE_ENCRYPT) { + res = crypto_acipher_rsaes_encrypt(cs->algo, o->attr, + label, label_len, + src_data, src_len, + dst_data, &dlen); + } else if (cs->mode == TEE_MODE_DECRYPT) { + res = crypto_acipher_rsaes_decrypt( + cs->algo, o->attr, label, label_len, + src_data, src_len, dst_data, &dlen); + } else { + res = TEE_ERROR_BAD_PARAMETERS; + } + break; + +#if defined(CFG_CRYPTO_RSASSA_NA1) + case TEE_ALG_RSASSA_PKCS1_V1_5: +#endif + 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_MD5: + 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; + } + salt_len = pkcs1_get_salt_len(params, num_params, src_len); + res = crypto_acipher_rsassa_sign(cs->algo, o->attr, salt_len, + src_data, src_len, dst_data, + &dlen); + break; + + case TEE_ALG_DSA_SHA1: + case TEE_ALG_DSA_SHA224: + case TEE_ALG_DSA_SHA256: + res = crypto_acipher_dsa_sign(cs->algo, o->attr, src_data, + src_len, dst_data, &dlen); + break; + + case TEE_ALG_ED25519: + res = tee_svc_obj_ed25519_sign(o->attr, src_data, src_len, + dst_data, &dlen, params, + num_params); + break; + + case TEE_ALG_ECDSA_SHA1: + case TEE_ALG_ECDSA_SHA224: + case TEE_ALG_ECDSA_SHA256: + case TEE_ALG_ECDSA_SHA384: + case TEE_ALG_ECDSA_SHA512: + case TEE_ALG_SM2_DSA_SM3: + res = crypto_acipher_ecc_sign(cs->algo, o->attr, src_data, + src_len, dst_data, &dlen); + break; + default: + res = TEE_ERROR_BAD_PARAMETERS; + break; + } + +out: + free_wipe(params); + + if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { + TEE_Result res2 = put_user_u64(dst_len, dlen); + + if (res2 != TEE_SUCCESS) + return res2; + } + + return res; +} + +TEE_Result syscall_asymm_verify(unsigned long state, + const struct utee_attribute *usr_params, + size_t num_params, const void *data, size_t data_len, + const void *sig, size_t sig_len) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + struct tee_cryp_state *cs = NULL; + TEE_Result res = TEE_SUCCESS; + TEE_Attribute *params = NULL; + struct tee_obj *o = NULL; + size_t hash_size = 0; + uint32_t hash_algo = 0; + int salt_len = 0; + size_t alloc_size = 0; + + res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); + if (res != TEE_SUCCESS) + return res; + + if (cs->mode != TEE_MODE_VERIFY) + return TEE_ERROR_BAD_PARAMETERS; + + data = memtag_strip_tag_const(data); + sig = memtag_strip_tag_const(sig); + + res = vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)data, data_len); + if (res != TEE_SUCCESS) + return res; + + res = vm_check_access_rights(&utc->uctx, + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + (uaddr_t)sig, sig_len); + if (res != TEE_SUCCESS) + return res; + + if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size)) + return TEE_ERROR_OVERFLOW; + + params = malloc(alloc_size); + if (!params) + return TEE_ERROR_OUT_OF_MEMORY; + res = copy_in_attrs(utc, usr_params, num_params, params); + if (res != TEE_SUCCESS) + goto out; + + res = tee_obj_get(utc, cs->key1, &o); + if (res != TEE_SUCCESS) + goto out; + if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + switch (TEE_ALG_GET_MAIN_ALG(cs->algo)) { + case TEE_MAIN_ALGO_RSA: + if (cs->algo != TEE_ALG_RSASSA_PKCS1_V1_5) { + hash_algo = TEE_DIGEST_HASH_TO_ALGO(cs->algo); + res = tee_alg_get_digest_size(hash_algo, &hash_size); + if (res != TEE_SUCCESS) + break; + if (data_len != hash_size) { + res = TEE_ERROR_BAD_PARAMETERS; + break; + } + salt_len = pkcs1_get_salt_len(params, num_params, + hash_size); + } + res = crypto_acipher_rsassa_verify(cs->algo, o->attr, salt_len, + data, data_len, sig, + sig_len); + break; + + case TEE_MAIN_ALGO_DSA: + hash_algo = TEE_DIGEST_HASH_TO_ALGO(cs->algo); + res = tee_alg_get_digest_size(hash_algo, &hash_size); + if (res != TEE_SUCCESS) + break; + + if (data_len != hash_size) { + struct dsa_public_key *key = o->attr; + + /* + * Depending on the DSA algorithm (NIST), the + * digital signature output size may be truncated + * to the size of a key pair (Q prime size). Q + * prime size must be less or equal than the hash + * output length of the hash algorithm involved. + * + * We're checking here in order to be able to + * return this particular error code, which will + * cause TEE_AsymmetricVerifyDigest() to panic as + * required by GP. crypto_acipher_dsa_verify() is + * implemented in the glue layer of the crypto + * library and it might be a bit harder to catch + * this particular case there or lead to duplicated + * code in different crypto glue layers. + * + * The GP spec says that we SHOULD panic if + * data_len != hash_size, but that would break a + * few of the DSA tests in xtest where the + * hash_size is larger than possible data_len. So + * the compromise is in case data_len != hash_size + * check that it's not smaller than what makes + * sense. + */ + if (data_len != crypto_bignum_num_bytes(key->q)) { + res = TEE_ERROR_BAD_PARAMETERS; + break; + } + } + res = crypto_acipher_dsa_verify(cs->algo, o->attr, data, + data_len, sig, sig_len); + break; + + case TEE_MAIN_ALGO_ED25519: + res = tee_svc_obj_ed25519_verify(o->attr, data, + data_len, sig, sig_len, + params, num_params); + break; + + case TEE_MAIN_ALGO_ECDSA: + case TEE_MAIN_ALGO_SM2_DSA_SM3: + res = crypto_acipher_ecc_verify(cs->algo, o->attr, data, + data_len, sig, sig_len); + break; + + default: + res = TEE_ERROR_NOT_SUPPORTED; + } + +out: + free_wipe(params); + return res; +} diff --git a/optee/optee_os/core/tee/tee_svc_storage.c b/optee/optee_os/core/tee/tee_svc_storage.c new file mode 100644 index 0000000..1484a7d --- /dev/null +++ b/optee/optee_os/core/tee/tee_svc_storage.c @@ -0,0 +1,937 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, 2022 Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Header of GP formated secure storage files */ +struct tee_svc_storage_head { + uint32_t attr_size; + uint32_t objectSize; + uint32_t maxObjectSize; + uint32_t objectUsage; + uint32_t objectType; + uint32_t have_attrs; +}; + +struct tee_storage_enum { + TAILQ_ENTRY(tee_storage_enum) link; + struct tee_fs_dir *dir; + const struct tee_file_operations *fops; +}; + +static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc, + vaddr_t enum_id, + struct tee_storage_enum **e_out) +{ + struct tee_storage_enum *e; + + TAILQ_FOREACH(e, &utc->storage_enums, link) { + if (enum_id == (vaddr_t)e) { + *e_out = e; + return TEE_SUCCESS; + } + } + return TEE_ERROR_BAD_PARAMETERS; +} + +static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc, + struct tee_storage_enum *e) +{ + if (e == NULL || utc == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + TAILQ_REMOVE(&utc->storage_enums, e, link); + + if (e->fops) + e->fops->closedir(e->dir); + + e->dir = NULL; + e->fops = NULL; + + free(e); + + return TEE_SUCCESS; +} + +static void remove_corrupt_obj(struct user_ta_ctx *utc, struct tee_obj *o) +{ + o->pobj->fops->remove(o->pobj); + if (!(utc->ta_ctx.flags & TA_FLAG_DONT_CLOSE_HANDLE_ON_CORRUPT_OBJECT)) + tee_obj_close(utc, o); +} + +static TEE_Result tee_svc_storage_read_head(struct tee_obj *o) +{ + TEE_Result res = TEE_SUCCESS; + size_t bytes; + struct tee_svc_storage_head head; + const struct tee_file_operations *fops = o->pobj->fops; + void *attr = NULL; + size_t size; + size_t tmp = 0; + + assert(!o->fh); + res = fops->open(o->pobj, &size, &o->fh); + if (res != TEE_SUCCESS) + goto exit; + + /* read head */ + bytes = sizeof(struct tee_svc_storage_head); + res = fops->read(o->fh, 0, &head, &bytes); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_CORRUPT_OBJECT) + EMSG("Head corrupt"); + goto exit; + } + + if (ADD_OVERFLOW(sizeof(head), head.attr_size, &tmp)) { + res = TEE_ERROR_OVERFLOW; + goto exit; + } + if (tmp > size) { + res = TEE_ERROR_CORRUPT_OBJECT; + goto exit; + } + + if (bytes != sizeof(struct tee_svc_storage_head)) { + res = TEE_ERROR_BAD_FORMAT; + goto exit; + } + + res = tee_obj_set_type(o, head.objectType, head.maxObjectSize); + if (res != TEE_SUCCESS) + goto exit; + + o->ds_pos = tmp; + + if (head.attr_size) { + attr = malloc(head.attr_size); + if (!attr) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + /* read meta */ + bytes = head.attr_size; + res = fops->read(o->fh, sizeof(struct tee_svc_storage_head), + attr, &bytes); + if (res == TEE_ERROR_OUT_OF_MEMORY) + goto exit; + if (res != TEE_SUCCESS || bytes != head.attr_size) + res = TEE_ERROR_CORRUPT_OBJECT; + if (res) + goto exit; + } + + res = tee_obj_attr_from_binary(o, attr, head.attr_size); + if (res != TEE_SUCCESS) + goto exit; + + o->info.dataSize = size - sizeof(head) - head.attr_size; + o->info.objectSize = head.objectSize; + o->info.objectUsage = head.objectUsage; + o->info.objectType = head.objectType; + o->have_attrs = head.have_attrs; + +exit: + free(attr); + + return res; +} + +TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, + size_t object_id_len, unsigned long flags, + uint32_t *obj) +{ + const unsigned long valid_flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE; + const struct tee_file_operations *fops = + tee_svc_storage_file_ops(storage_id); + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + struct tee_pobj *po = NULL; + struct tee_obj *o = NULL; + + if (flags & ~valid_flags) + return TEE_ERROR_BAD_PARAMETERS; + + if (!fops) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto exit; + } + + if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + object_id = memtag_strip_tag(object_id); + if (object_id_len) { + res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ, + (uaddr_t)object_id, object_id_len); + if (res != TEE_SUCCESS) + goto err; + } + + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, + object_id_len, flags, TEE_POBJ_USAGE_OPEN, fops, + &po); + if (res != TEE_SUCCESS) + goto err; + + o = tee_obj_alloc(); + if (o == NULL) { + tee_pobj_release(po); + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT | + TEE_HANDLE_FLAG_INITIALIZED | flags; + o->pobj = po; + tee_obj_add(utc, o); + + res = tee_svc_storage_read_head(o); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_CORRUPT_OBJECT) { + EMSG("Object corrupt"); + goto err; + } + goto oclose; + } + + res = copy_kaddr_to_uref(obj, o); + if (res != TEE_SUCCESS) + goto oclose; + + goto exit; + +oclose: + tee_obj_close(utc, o); + o = NULL; + +err: + if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) + res = TEE_ERROR_CORRUPT_OBJECT; + if (res == TEE_ERROR_CORRUPT_OBJECT && o) + remove_corrupt_obj(utc, o); + +exit: + return res; +} + +static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, bool overwrite, + struct tee_obj *attr_o, void *data, + uint32_t len) +{ + TEE_Result res = TEE_SUCCESS; + struct tee_svc_storage_head head = { }; + const struct tee_file_operations *fops = o->pobj->fops; + void *attr = NULL; + size_t attr_size = 0; + + if (attr_o) { + if (o != attr_o) { + res = tee_obj_set_type(o, attr_o->info.objectType, + attr_o->info.maxObjectSize); + if (res) + return res; + res = tee_obj_attr_copy_from(o, attr_o); + if (res) + return res; + o->have_attrs = attr_o->have_attrs; + o->info.objectUsage = attr_o->info.objectUsage; + o->info.objectSize = attr_o->info.objectSize; + } + res = tee_obj_attr_to_binary(o, NULL, &attr_size); + if (res) + return res; + if (attr_size) { + attr = malloc(attr_size); + if (!attr) + return TEE_ERROR_OUT_OF_MEMORY; + res = tee_obj_attr_to_binary(o, attr, &attr_size); + if (res != TEE_SUCCESS) + goto exit; + } + } else { + res = tee_obj_set_type(o, TEE_TYPE_DATA, 0); + if (res != TEE_SUCCESS) + goto exit; + } + + o->ds_pos = sizeof(struct tee_svc_storage_head) + attr_size; + + /* write head */ + head.attr_size = attr_size; + head.objectSize = o->info.objectSize; + head.maxObjectSize = o->info.maxObjectSize; + head.objectUsage = o->info.objectUsage; + head.objectType = o->info.objectType; + head.have_attrs = o->have_attrs; + + res = fops->create(o->pobj, overwrite, &head, sizeof(head), attr, + attr_size, data, len, &o->fh); + + if (res) + o->ds_pos = 0; + else + o->info.dataSize = len; +exit: + free(attr); + return res; +} + +TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, + size_t object_id_len, unsigned long flags, + unsigned long attr, void *data, size_t len, + uint32_t *obj) +{ + const unsigned long valid_flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE | + TEE_DATA_FLAG_OVERWRITE; + const struct tee_file_operations *fops = + tee_svc_storage_file_ops(storage_id); + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + struct tee_obj *attr_o = NULL; + TEE_Result res = TEE_SUCCESS; + struct tee_pobj *po = NULL; + struct tee_obj *o = NULL; + + if (flags & ~valid_flags) + return TEE_ERROR_BAD_PARAMETERS; + + if (!fops) + return TEE_ERROR_ITEM_NOT_FOUND; + + if (object_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + object_id = memtag_strip_tag(object_id); + data = memtag_strip_tag(data); + + if (object_id_len) { + res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ, + (uaddr_t)object_id, object_id_len); + if (res != TEE_SUCCESS) + goto err; + } + + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, + object_id_len, flags, TEE_POBJ_USAGE_CREATE, + fops, &po); + if (res != TEE_SUCCESS) + goto err; + + /* check rights of the provided buffer */ + if (len) { + if (data) { + uint32_t f = TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER; + + res = vm_check_access_rights(&utc->uctx, f, + (uaddr_t)data, len); + + if (res != TEE_SUCCESS) + goto err; + } else { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + } + + if (attr != TEE_HANDLE_NULL) { + res = tee_obj_get(utc, uref_to_vaddr(attr), &attr_o); + if (res != TEE_SUCCESS) + goto err; + /* The supplied handle must be one of an initialized object */ + if (!(attr_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + } + + if (!obj && attr_o && + !(attr_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + /* + * The caller expects the supplied attributes handle to be + * transformed into a persistent object. + */ + uint32_t saved_flags = attr_o->info.handleFlags; + + attr_o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT | + TEE_HANDLE_FLAG_INITIALIZED | flags; + attr_o->pobj = po; + res = tee_svc_storage_init_file(attr_o, + flags & TEE_DATA_FLAG_OVERWRITE, + attr_o, data, len); + if (res) { + attr_o->info.handleFlags = saved_flags; + attr_o->pobj = NULL; + goto err; + } + } else { + o = tee_obj_alloc(); + if (!o) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT | + TEE_HANDLE_FLAG_INITIALIZED | flags; + o->pobj = po; + + res = tee_svc_storage_init_file(o, + flags & TEE_DATA_FLAG_OVERWRITE, + attr_o, data, len); + if (res != TEE_SUCCESS) + goto err; + + po = NULL; /* o owns it from now on */ + tee_obj_add(utc, o); + + if (obj) { + res = copy_kaddr_to_uref(obj, o); + if (res != TEE_SUCCESS) + goto oclose; + } + + tee_pobj_create_final(o->pobj); + + if (!obj) + tee_obj_close(utc, o); + } + + return TEE_SUCCESS; + +oclose: + tee_obj_close(utc, o); + return res; + +err: + if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) + res = TEE_ERROR_CORRUPT_OBJECT; + if (res == TEE_ERROR_CORRUPT_OBJECT && po) + fops->remove(po); + if (o) { + fops->close(&o->fh); + tee_obj_free(o); + } + if (po) + tee_pobj_release(po); + + return res; +} + +TEE_Result syscall_storage_obj_del(unsigned long obj) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + + res = tee_obj_get(utc, uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->info.handleFlags & 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; + + if (IS_ENABLED(CFG_NXP_SE05X)) { + /* Cryptographic layer house-keeping */ + res = crypto_storage_obj_del(o); + if (res) + return res; + } + + res = o->pobj->fops->remove(o->pobj); + tee_obj_close(utc, o); + + return res; +} + +TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, + size_t object_id_len) +{ + const struct tee_file_operations *fops = NULL; + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + struct tee_pobj *po = NULL; + struct tee_obj *o = NULL; + char *new_file = NULL; + char *old_file = NULL; + + if (object_id_len > TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_obj_get(utc, uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + res = TEE_ERROR_BAD_STATE; + goto exit; + } + + if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { + res = TEE_ERROR_BAD_STATE; + goto exit; + } + + if (o->pobj == NULL || o->pobj->obj_id == NULL) { + res = TEE_ERROR_BAD_STATE; + goto exit; + } + + object_id = memtag_strip_tag(object_id); + if (object_id_len) { + res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ, + (uaddr_t)object_id, object_id_len); + if (res != TEE_SUCCESS) + goto exit; + } + + /* reserve dest name */ + fops = o->pobj->fops; + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, + object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, + TEE_POBJ_USAGE_RENAME, fops, &po); + if (res != TEE_SUCCESS) + goto exit; + + /* move */ + res = fops->rename(o->pobj, po, false /* no overwrite */); + if (res) + 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 syscall_storage_alloc_enum(uint32_t *obj_enum) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + struct tee_storage_enum *e = NULL; + + if (obj_enum == NULL) + return TEE_ERROR_BAD_PARAMETERS; + + e = malloc(sizeof(struct tee_storage_enum)); + if (e == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + e->dir = NULL; + e->fops = NULL; + TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); + + return copy_kaddr_to_uref(obj_enum, e); +} + +TEE_Result syscall_storage_free_enum(unsigned long obj_enum) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + struct tee_storage_enum *e = NULL; + TEE_Result res = TEE_SUCCESS; + + res = tee_svc_storage_get_enum(utc, + uref_to_vaddr(obj_enum), &e); + if (res != TEE_SUCCESS) + return res; + + return tee_svc_close_enum(utc, e); +} + +TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) +{ + struct ts_session *sess = ts_get_current_session(); + struct tee_storage_enum *e = NULL; + TEE_Result res = TEE_SUCCESS; + + res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), + uref_to_vaddr(obj_enum), &e); + if (res != TEE_SUCCESS) + return res; + + if (e->fops) { + e->fops->closedir(e->dir); + e->fops = NULL; + e->dir = NULL; + } + assert(!e->dir); + + return TEE_SUCCESS; +} + +TEE_Result syscall_storage_start_enum(unsigned long obj_enum, + unsigned long storage_id) +{ + struct ts_session *sess = ts_get_current_session(); + struct tee_storage_enum *e = NULL; + TEE_Result res = TEE_SUCCESS; + const struct tee_file_operations *fops = + tee_svc_storage_file_ops(storage_id); + + res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), + uref_to_vaddr(obj_enum), &e); + if (res != TEE_SUCCESS) + return res; + + if (e->dir) { + e->fops->closedir(e->dir); + e->dir = NULL; + } + + if (!fops) + return TEE_ERROR_ITEM_NOT_FOUND; + + e->fops = fops; + + return fops->opendir(&sess->ctx->uuid, &e->dir); +} + +TEE_Result syscall_storage_next_enum(unsigned long obj_enum, + struct utee_object_info *info, + void *obj_id, uint64_t *len) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + struct tee_storage_enum *e = NULL; + struct tee_fs_dirent *d = NULL; + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + uint64_t l = 0; + + res = tee_svc_storage_get_enum(utc, uref_to_vaddr(obj_enum), &e); + if (res != TEE_SUCCESS) + goto exit; + + info = memtag_strip_tag(info); + obj_id = memtag_strip_tag(obj_id); + + /* check rights of the provided buffers */ + res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE, + (uaddr_t)info, sizeof(*info)); + if (res != TEE_SUCCESS) + goto exit; + + res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE, + (uaddr_t)obj_id, TEE_OBJECT_ID_MAX_LEN); + if (res != TEE_SUCCESS) + goto exit; + + if (!e->fops) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto exit; + } + + res = e->fops->readdir(e->dir, &d); + if (res != TEE_SUCCESS) + goto exit; + + o = tee_obj_alloc(); + if (o == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + res = tee_pobj_get(&sess->ctx->uuid, d->oid, d->oidlen, 0, + TEE_POBJ_USAGE_ENUM, e->fops, &o->pobj); + if (res) + goto exit; + + o->info.handleFlags = o->pobj->flags | TEE_HANDLE_FLAG_PERSISTENT | + TEE_HANDLE_FLAG_INITIALIZED; + + res = tee_svc_storage_read_head(o); + if (res != TEE_SUCCESS) + goto exit; + + *info = (struct utee_object_info){ + .obj_type = o->info.objectType, + .obj_size = o->info.objectSize, + .max_obj_size = o->info.maxObjectSize, + .obj_usage = o->info.objectUsage, + .data_size = o->info.dataSize, + .data_pos = o->info.dataPosition, + .handle_flags = o->info.handleFlags, + }; + memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); + + l = o->pobj->obj_id_len; + res = copy_to_user_private(len, &l, sizeof(*len)); + +exit: + if (o) { + if (o->pobj) { + o->pobj->fops->close(&o->fh); + tee_pobj_release(o->pobj); + } + tee_obj_free(o); + } + + return res; +} + +TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, + uint64_t *count) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + uint64_t u_count = 0; + size_t pos_tmp = 0; + size_t bytes = 0; + + res = tee_obj_get(utc, uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + goto exit; + + if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + res = TEE_ERROR_BAD_STATE; + goto exit; + } + + if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_READ)) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto exit; + } + + /* Guard o->info.dataPosition += bytes below from overflowing */ + if (ADD_OVERFLOW(o->info.dataPosition, len, &pos_tmp)) { + res = TEE_ERROR_OVERFLOW; + goto exit; + } + + data = memtag_strip_tag(data); + /* check rights of the provided buffer */ + res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE, + (uaddr_t)data, len); + if (res != TEE_SUCCESS) + goto exit; + + bytes = len; + if (ADD_OVERFLOW(o->ds_pos, o->info.dataPosition, &pos_tmp)) { + res = TEE_ERROR_OVERFLOW; + goto exit; + } + res = o->pobj->fops->read(o->fh, pos_tmp, data, &bytes); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_CORRUPT_OBJECT) { + EMSG("Object corrupt"); + remove_corrupt_obj(utc, o); + } + goto exit; + } + + o->info.dataPosition += bytes; + + u_count = bytes; + res = copy_to_user_private(count, &u_count, sizeof(*count)); +exit: + return res; +} + +TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) +{ + struct ts_session *sess = ts_get_current_session(); + struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + size_t pos_tmp = 0; + + res = tee_obj_get(utc, uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + goto exit; + + if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + res = TEE_ERROR_BAD_STATE; + goto exit; + } + + if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE)) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto exit; + } + + /* Guard o->info.dataPosition += bytes below from overflowing */ + if (ADD_OVERFLOW(o->info.dataPosition, len, &pos_tmp)) { + res = TEE_ERROR_OVERFLOW; + goto exit; + } + + data = memtag_strip_tag(data); + /* check rights of the provided buffer */ + res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ, + (uaddr_t)data, len); + if (res != TEE_SUCCESS) + goto exit; + + if (ADD_OVERFLOW(o->ds_pos, o->info.dataPosition, &pos_tmp)) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto exit; + } + res = o->pobj->fops->write(o->fh, pos_tmp, data, len); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_CORRUPT_OBJECT) { + EMSG("Object corrupt"); + remove_corrupt_obj(utc, o); + } + goto exit; + } + + o->info.dataPosition += len; + if (o->info.dataPosition > o->info.dataSize) + o->info.dataSize = o->info.dataPosition; + +exit: + return res; +} + +TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + size_t off = 0; + size_t attr_size = 0; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + goto exit; + + if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { + res = TEE_ERROR_BAD_STATE; + goto exit; + } + + if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE)) { + res = TEE_ERROR_ACCESS_CONFLICT; + goto exit; + } + + res = tee_obj_attr_to_binary(o, NULL, &attr_size); + if (res != TEE_SUCCESS) + goto exit; + + if (ADD_OVERFLOW(sizeof(struct tee_svc_storage_head), attr_size, + &off)) { + res = TEE_ERROR_OVERFLOW; + goto exit; + } + if (ADD_OVERFLOW(len, off, &off)) { + res = TEE_ERROR_OVERFLOW; + goto exit; + } + res = o->pobj->fops->truncate(o->fh, off); + switch (res) { + case TEE_SUCCESS: + o->info.dataSize = len; + break; + case TEE_ERROR_CORRUPT_OBJECT: + EMSG("Object corruption"); + remove_corrupt_obj(to_user_ta_ctx(sess->ctx), o); + break; + default: + res = TEE_ERROR_GENERIC; + break; + } + +exit: + return res; +} + +TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, + unsigned long whence) +{ + struct ts_session *sess = ts_get_current_session(); + TEE_Result res = TEE_SUCCESS; + struct tee_obj *o = NULL; + tee_fs_off_t new_pos = 0; + + res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); + if (res != TEE_SUCCESS) + return res; + + if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) + return TEE_ERROR_BAD_STATE; + + switch (whence) { + case TEE_DATA_SEEK_SET: + new_pos = offset; + break; + case TEE_DATA_SEEK_CUR: + if (ADD_OVERFLOW(o->info.dataPosition, offset, &new_pos)) + return TEE_ERROR_OVERFLOW; + break; + case TEE_DATA_SEEK_END: + if (ADD_OVERFLOW(o->info.dataSize, offset, &new_pos)) + return TEE_ERROR_OVERFLOW; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (new_pos < 0) + new_pos = 0; + + if (new_pos > TEE_DATA_MAX_POSITION) { + EMSG("Position is beyond TEE_DATA_MAX_POSITION"); + return TEE_ERROR_BAD_PARAMETERS; + } + + o->info.dataPosition = new_pos; + + return TEE_SUCCESS; +} + +void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) +{ + struct tee_storage_enum_head *eh = &utc->storage_enums; + + /* disregard return value */ + while (!TAILQ_EMPTY(eh)) + tee_svc_close_enum(utc, TAILQ_FIRST(eh)); +} diff --git a/optee/optee_os/core/tee/tee_ta_enc_manager.c b/optee/optee_os/core/tee/tee_ta_enc_manager.c new file mode 100644 index 0000000..2bab308 --- /dev/null +++ b/optee/optee_os/core/tee/tee_ta_enc_manager.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include + +TEE_Result tee_ta_decrypt_init(void **enc_ctx, struct shdr_encrypted_ta *ehdr, + size_t len) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t key[TEE_TA_ENC_KEY_SIZE] = {0}; + + res = crypto_authenc_alloc_ctx(enc_ctx, ehdr->enc_algo); + if (res != TEE_SUCCESS) + return res; + + res = tee_otp_get_ta_enc_key(ehdr->flags & SHDR_ENC_KEY_TYPE_MASK, + key, sizeof(key)); + if (res != TEE_SUCCESS) + goto out_init; + + res = crypto_authenc_init(*enc_ctx, TEE_MODE_DECRYPT, key, sizeof(key), + SHDR_ENC_GET_IV(ehdr), ehdr->iv_size, + ehdr->tag_size, 0, len); + +out_init: + if (res != TEE_SUCCESS) + crypto_authenc_free_ctx(*enc_ctx); + + memzero_explicit(key, sizeof(key)); + return res; +} + +TEE_Result tee_ta_decrypt_update(void *enc_ctx, uint8_t *dst, uint8_t *src, + size_t len) +{ + TEE_Result res = TEE_SUCCESS; + size_t dlen = len; + + res = crypto_authenc_update_payload(enc_ctx, TEE_MODE_DECRYPT, src, len, + dst, &dlen); + if (res != TEE_SUCCESS) + crypto_authenc_free_ctx(enc_ctx); + + return res; +} + +TEE_Result tee_ta_decrypt_final(void *enc_ctx, struct shdr_encrypted_ta *ehdr, + uint8_t *dst, uint8_t *src, size_t len) +{ + TEE_Result res = TEE_SUCCESS; + size_t dlen = len; + + res = crypto_authenc_dec_final(enc_ctx, src, len, dst, &dlen, + SHDR_ENC_GET_TAG(ehdr), ehdr->tag_size); + + crypto_authenc_free_ctx(enc_ctx); + + return res; +} diff --git a/optee/optee_os/core/tee/tee_time_generic.c b/optee/optee_os/core/tee/tee_time_generic.c new file mode 100644 index 0000000..303b044 --- /dev/null +++ b/optee/optee_os/core/tee/tee_time_generic.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include + +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 = realloc(tee_time_offs, n * sizeof(struct tee_ta_time_offs)); + if (!o) + return TEE_ERROR_OUT_OF_MEMORY; + 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); + } +} + +void tee_time_busy_wait(uint32_t milliseconds_delay) +{ + TEE_Time curr; + TEE_Time delta; + TEE_Time end; + + if (tee_time_get_sys_time(&curr) != TEE_SUCCESS) + panic(); + delta.seconds = milliseconds_delay / 1000; + delta.millis = milliseconds_delay % 1000; + TEE_TIME_ADD(curr, delta, end); + + while (TEE_TIME_LT(curr, end)) + if (tee_time_get_sys_time(&curr) != TEE_SUCCESS) + panic(); +} diff --git a/optee/optee_os/core/tee/uuid.c b/optee/optee_os/core/tee/uuid.c new file mode 100644 index 0000000..065de3e --- /dev/null +++ b/optee/optee_os/core/tee/uuid.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include + +void tee_uuid_to_octets(uint8_t *d, const TEE_UUID *s) +{ + d[0] = s->timeLow >> 24; + d[1] = s->timeLow >> 16; + d[2] = s->timeLow >> 8; + d[3] = s->timeLow; + d[4] = s->timeMid >> 8; + d[5] = s->timeMid; + d[6] = s->timeHiAndVersion >> 8; + d[7] = s->timeHiAndVersion; + memcpy(d + 8, s->clockSeqAndNode, sizeof(s->clockSeqAndNode)); +} + +void tee_uuid_from_octets(TEE_UUID *d, const uint8_t *s) +{ + d->timeLow = SHIFT_U32(s[0], 24) | SHIFT_U32(s[1], 16) | + SHIFT_U32(s[2], 8) | s[3]; + d->timeMid = SHIFT_U32(s[4], 8) | s[5]; + d->timeHiAndVersion = SHIFT_U32(s[6], 8) | s[7]; + memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode)); +} + +void tee_uuid_from_uint32_t(TEE_UUID *d, uint32_t s0, uint32_t s1, uint32_t s2, + uint32_t s3) +{ + d->timeLow = s0; + d->timeMid = s1 >> 16; + d->timeHiAndVersion = s1 & 0xffff; + + d->clockSeqAndNode[0] = (s2 >> 24) & 0xff; + d->clockSeqAndNode[1] = (s2 >> 16) & 0xff; + d->clockSeqAndNode[2] = (s2 >> 8) & 0xff; + d->clockSeqAndNode[3] = s2 & 0xff; + + d->clockSeqAndNode[4] = (s3 >> 24) & 0xff; + d->clockSeqAndNode[5] = (s3 >> 16) & 0xff; + d->clockSeqAndNode[6] = (s3 >> 8) & 0xff; + d->clockSeqAndNode[7] = s3 & 0xff; +} diff --git a/optee/optee_os/core/tests/ftmn_boot_tests.c b/optee/optee_os/core/tests/ftmn_boot_tests.c new file mode 100644 index 0000000..3cd1236 --- /dev/null +++ b/optee/optee_os/core/tests/ftmn_boot_tests.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +/* + * Simple straightforward tests. + */ +static TEE_Result simple_call_func_res; + +static TEE_Result __noinline simple_call_func1(void) +{ + TEE_Result res = simple_call_func_res; + + FTMN_CALLEE_DONE(res); + return res; +} + +static TEE_Result __noinline simple_call_memcmp(const void *s1, const void *s2, + size_t n) +{ + if (!FTMN_CALLEE_DONE_MEMCMP(memcmp, s1, s2, n)) + return TEE_SUCCESS; + return TEE_ERROR_GENERIC; +} + +static void __noinline simple_call(void) +{ + TEE_Result res = TEE_SUCCESS; + struct ftmn ftmn = { }; + static const char s1[] = "s1"; + + simple_call_func_res = TEE_SUCCESS; + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, simple_call_func1); + ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(1), res); + + simple_call_func_res = TEE_ERROR_GENERIC; + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, simple_call_func1); + ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(2, 1), res); + + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, + simple_call_memcmp, s1, s1, sizeof(s1)); + ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(3, 2), res); +} + +/* + * Simulate calling with multiple unmitigated functions in the chain + * between checked callee and the caller. The result has always been set + * regardless of return value. + */ + +static TEE_Result __noinline two_level_call_memcmp2(const void *s1, + const void *s2, size_t n) +{ + if (!FTMN_CALLEE_DONE_MEMCMP(memcmp, s1, s2, n)) + return TEE_SUCCESS; + /* + * If FTMN_CALLEE_DONE_MEMCMP() returned non-zero the strings are + * different. Update with an error code we can understand. + */ + FTMN_CALLEE_UPDATE_NOT_ZERO(TEE_ERROR_GENERIC); + return TEE_ERROR_GENERIC; +} + +static TEE_Result __noinline two_level_call_memcmp1(const void *s1, + const void *s2, size_t n) +{ + return two_level_call_memcmp2(s1, s2, n); +} + +static TEE_Result __noinline two_level_call_memcmp(const void *s1, + const void *s2, size_t n) +{ + unsigned long func_hash = FTMN_FUNC_HASH("two_level_call_memcmp2"); + struct ftmn ftmn = { }; + TEE_Result res = TEE_SUCCESS; + + FTMN_PUSH_LINKED_CALL(&ftmn, func_hash); + res = two_level_call_memcmp1(s1, s2, n); + FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, 0, res); + FTMN_POP_LINKED_CALL(&ftmn); + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR1, 0, res); + + return res; +} + +static void __noinline two_level_call(void) +{ + struct ftmn ftmn = { }; + TEE_Result res = TEE_SUCCESS; + static const char s1[] = "s1"; + static const char s2[] = "s2"; + + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, + two_level_call_memcmp, s1, s1, sizeof(s1)); + ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(1), res); + + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, + two_level_call_memcmp, s1, s2, sizeof(s1)); + ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(2, 1), res); +} + +/* + * Simulate chained calls in several levels. + * + * For instance ree_fs_ta_open() -> shdr_verify_signature() -> + * crypto_acipher_rsassa_verify() -> ... -> + * mbedtls_rsa_rsassa_pss_verify_ext() + */ + +static TEE_Result __noinline chained_call_memcmp2(const void *s1, + const void *s2, size_t n) +{ + if (!FTMN_CALLEE_DONE_MEMCMP(memcmp, s1, s2, n)) + return TEE_SUCCESS; + return TEE_ERROR_GENERIC; +} + +static TEE_Result __noinline chained_call_memcmp1(const void *s1, + const void *s2, size_t n) +{ + TEE_Result res = chained_call_memcmp2(s1, s2, n); + + /* + * If s1 and s2 has the same content but different pointers we're + * testing the case with an error detected after the linked leaf + * function has been called. + */ + if (!res && s1 != s2) + res = TEE_ERROR_BAD_STATE; + + return res; +} + +static TEE_Result __noinline chained_call_memcmp(const void *s1, + const void *s2, size_t n) +{ + struct ftmn ftmn = { }; + TEE_Result res = TEE_SUCCESS; + + FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("chained_call_memcmp2")); + + res = chained_call_memcmp1(s1, s2, n); + + if (!res) + FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, res); + else + FTMN_SET_CHECK_RES(&ftmn, FTMN_INCR0, res); + FTMN_POP_LINKED_CALL(&ftmn); + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res); + + return res; +} + +static void __noinline chained_calls(void) +{ + struct ftmn ftmn = { }; + static const char s[] = "s1s2s1"; + TEE_Result res = TEE_SUCCESS; + + /* Test a normal success case. */ + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, chained_call_memcmp, s, s, 2); + ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(1), res); + + /* Test the case where the leaf function detects an error. */ + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, + chained_call_memcmp, s, s + 2, 2); + assert(res == TEE_ERROR_GENERIC); + ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(2, 1), + TEE_ERROR_GENERIC); + + /* + * Test the case where a function in the call chain detects an error + * after a the leaf function has returned success. + */ + FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, + chained_call_memcmp, s, s + 4, 2); + assert(res == TEE_ERROR_BAD_STATE); + ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(3, 2), + TEE_ERROR_BAD_STATE); +} + +#define CALL_TEST_FUNC(x) do { \ + DMSG("Calling " #x "()"); \ + x(); \ + DMSG("Return from " #x "()"); \ + } while (0) + +static TEE_Result ftmn_boot_tests(void) +{ + CALL_TEST_FUNC(simple_call); + CALL_TEST_FUNC(two_level_call); + CALL_TEST_FUNC(chained_calls); + + DMSG("*************************************************"); + DMSG("************** Tests complete *****************"); + DMSG("*************************************************"); + return TEE_SUCCESS; +} + +driver_init_late(ftmn_boot_tests); diff --git a/optee/optee_os/core/tests/sub.mk b/optee/optee_os/core/tests/sub.mk new file mode 100644 index 0000000..b0833d5 --- /dev/null +++ b/optee/optee_os/core/tests/sub.mk @@ -0,0 +1 @@ +srcs-y += ftmn_boot_tests.c diff --git a/optee/optee_os/keys/default_ta.pem b/optee/optee_os/keys/default_ta.pem new file mode 100644 index 0000000..a8e5dcd --- /dev/null +++ b/optee/optee_os/keys/default_ta.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAploYrcCzzuMMkCt9QJusu1pJiEIKseCSwIaR5p7voOHxL5D2 +Zt3qFVrAKLSd31IMbqXGGUOsaajyX/5gAKXSOswSAfNbugxRHCz0sHe51nI1HA9z +zS8W+bqJhKCbv4tbf+iLi5/IceocbB8AoO7KPr8YjlebSGbri9RAUa6GoYb40Av6 +ti4lLgX/dgFG1z3rH3z83x6Ci16wyqPqFr4tblRQnLhB7xfHf2BUqvlwoPiYLoL5 +jF/7nIiOd7Aycpka4ARevx2q9/AFPLSV3U26OnGh+HKOHZjjE7rKsCe/h1lUJ/jo +7MaFN9I6leSlCZrQH6OGsJLYAh4zddsmvyf8NQIDAQABAoIBAEoooBfVcFMqpM8g +lBXZUIe1GFLGHj5t/v4U/7Xv5KO0FfE+jpoNE+2xJzj+S+LikOhCvq1Enff8eRCS +NfoT8kSD9QMpmhq2ovIMmIiS1yXihAqeWOF/vJ5XqjaV4tjhJ0k+Qfdco98knscU +ixMzYLXYOvo509/TAe60EHhZdWtMKCmHqvFBRDhYFF+HUxWnJa39G1u828ljv8uN +iRCXbEjoaWDwBJWRzDZJehrkQc2gQAkFpyePVqA3wm1tx1ZHEVwCqYOXOP49/LAc +rQfoWUpm4chjEHnZEb+dQxa3N8Qeq2lqgcqrOX8NIfpzWTWQ1JM+ksinQwMJ0BDV ++Lf1nAECgYEA2KBBtsj41ITez8iA0DpXovH1F9oU9aJ9JKopNos8zIZg012bE5Ib +kFII0LiBGKLUP2PepTsPDIOxibLQDojg1aBGHISZVp/y81B4Rk7Wwg206ZQ848dM +AhACIrzOtJLoVEZTPf7C5QrNMhViyf2c8vFBjfTuM7Ze6a0fsvfJ2ikCgYEAxJaO +XKnOgKoG1Fe9JVM01U+260BEybNUbbXQCnvMjTSZCsOEmST9mhXhC56lhCNqmynt +FxNuq/JMwtS3TRhrYCPPCLFly+JNTqUS1mLQ9ytVbaw6fp9mSxFUQE9d9obkGwJC +3uXEx+bc7YSGuwD34wikX0tB1zzGIXRH2JlB6y0CgYEAgFlDVjdxJwmqslXL7JQE +xKizXPR7oqYpm4WucYDB/zRHPjSh41CYQEQ6sOAArUYcl4pmqmN5oSKOGFX37ASx +oiEaKV9vMuIGIp+1A4NGvyc734FTKmo04Kv3d/mCR38bZINeYscFVou11EzTgXZg +fZjwDFnooH8XcUCAHZuu3zECgYEAt6pltSMcgE7Z9JdIas/TI5vHLQEtgzhdH+bm +SHUjRaWnekvy3VWW7deVGtMMlmi0V+US0iVgl5rXposv+gJfh0HNUrTSg2qZiWlm +MQ+/Zb2BoeZv/A8Wdfnpue+svP+Hq8gwC6mlcJI7RFk1uw8LiXxwfWuFRv9LqMPH +wBBnar0CgYAJF3ukzm7rnut19lzS4r1uEIuuPwk/DjEkkil7U9wE5fr+ds5rCtXj +9591DLHrtE/CBOWym2+tIDr7OnmfU+934524mtLWVZdf39/DFM9Fc1VaSualrj/1 +BOLhBb7MEZqN7hHcQP7+49YW72GgX3pm0Ov5ke33FzN3ubIwAS6T7A== +-----END RSA PRIVATE KEY----- diff --git a/optee/optee_os/ldelf/dl.c b/optee/optee_os/ldelf/dl.c new file mode 100644 index 0000000..6e737bf --- /dev/null +++ b/optee/optee_os/ldelf/dl.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ +#include +#include + +#include "dl.h" +#include "ta_elf.h" + +TEE_Result dlopen_entry(struct dl_entry_arg *arg) +{ + TEE_UUID zero = { }; + + if (arg->dlopen.flags != (RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!memcmp(&arg->dlopen.uuid, &zero, sizeof(zero))) + return TEE_SUCCESS; + + return ta_elf_add_library(&arg->dlopen.uuid); +} + +TEE_Result dlsym_entry(struct dl_entry_arg *arg) +{ + struct ta_elf *elf = NULL; + TEE_UUID zero = { }; + + if (memcmp(&arg->dlsym.uuid, &zero, sizeof(zero))) { + elf = ta_elf_find_elf(&arg->dlsym.uuid); + if (!elf) + return TEE_ERROR_ITEM_NOT_FOUND; + } + + return ta_elf_resolve_sym(arg->dlsym.symbol, &arg->dlsym.val, NULL, + elf); +} + diff --git a/optee/optee_os/ldelf/dl.h b/optee/optee_os/ldelf/dl.h new file mode 100644 index 0000000..66828a5 --- /dev/null +++ b/optee/optee_os/ldelf/dl.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef LDELF_DL_H +#define LDELF_DL_H + +#include +#include + +TEE_Result dlopen_entry(struct dl_entry_arg *arg); +TEE_Result dlsym_entry(struct dl_entry_arg *arg); + +#endif /*LDELF_DL_H*/ + diff --git a/optee/optee_os/ldelf/ftrace.c b/optee/optee_os/ldelf/ftrace.c new file mode 100644 index 0000000..934bf43 --- /dev/null +++ b/optee/optee_os/ldelf/ftrace.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "ftrace.h" +#include "ta_elf.h" + +#define MIN_FTRACE_BUF_SIZE 1024 +#define MAX_HEADER_STRLEN 128 + +static struct ftrace_buf *fbuf; + +bool ftrace_init(struct ftrace_buf **fbuf_ptr) +{ + struct __ftrace_info *finfo = NULL; + struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); + TEE_Result res = TEE_SUCCESS; + vaddr_t val = 0; + int count = 0; + size_t fbuf_size = 0; + + res = ta_elf_resolve_sym("__ftrace_info", &val, NULL, NULL); + if (res) + return false; + + finfo = (struct __ftrace_info *)val; + + assert(elf && elf->is_main); + + if (SUB_OVERFLOW(finfo->buf_end.ptr64, finfo->buf_start.ptr64, + &fbuf_size)) + return false; + + if (fbuf_size < MIN_FTRACE_BUF_SIZE) { + DMSG("ftrace buffer too small"); + return false; + } + + fbuf = (struct ftrace_buf *)(vaddr_t)finfo->buf_start.ptr64; + fbuf->head_off = sizeof(struct ftrace_buf); + count = snprintk((char *)fbuf + fbuf->head_off, MAX_HEADER_STRLEN, + "Function graph for TA: %pUl @ %lx\n", + (void *)&elf->uuid, elf->load_addr); + assert(count < MAX_HEADER_STRLEN); + + fbuf->ret_func_ptr = finfo->ret_ptr.ptr64; + fbuf->ret_idx = 0; + fbuf->lr_idx = 0; + fbuf->suspend_time = 0; + fbuf->buf_off = fbuf->head_off + count; + fbuf->curr_size = 0; + fbuf->max_size = fbuf_size - sizeof(struct ftrace_buf) - count; + fbuf->syscall_trace_enabled = false; + fbuf->syscall_trace_suspended = false; + + *fbuf_ptr = fbuf; + + return true; +} + +void ftrace_copy_buf(void *pctx, void (*copy_func)(void *pctx, void *b, + size_t bl)) +{ + if (fbuf) { + struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); + size_t dump_size = fbuf->buf_off - fbuf->head_off + + fbuf->curr_size; + + assert(elf && elf->is_main); + copy_func(pctx, (char *)fbuf + fbuf->head_off, dump_size); + } +} + +void ftrace_map_lr(uint64_t *lr) +{ + if (fbuf) { + if (*lr == fbuf->ret_func_ptr && + fbuf->lr_idx < fbuf->ret_idx) { + fbuf->lr_idx++; + *lr = fbuf->ret_stack[fbuf->ret_idx - fbuf->lr_idx]; + } + } +} diff --git a/optee/optee_os/ldelf/ftrace.h b/optee/optee_os/ldelf/ftrace.h new file mode 100644 index 0000000..83dcf4a --- /dev/null +++ b/optee/optee_os/ldelf/ftrace.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef FTRACE_H +#define FTRACE_H + +#include +#include + +#ifdef CFG_FTRACE_SUPPORT +bool ftrace_init(struct ftrace_buf **fbuf_ptr); +void ftrace_copy_buf(void *pctx, void (*copy_func)(void *pctx, void *b, + size_t bl)); +void ftrace_map_lr(uint64_t *lr); +#else +static inline void ftrace_map_lr(uint64_t *lr __unused) +{ +} +#endif + +#endif /*FTRACE_H*/ + diff --git a/optee/optee_os/ldelf/include/ldelf.h b/optee/optee_os/ldelf/include/ldelf.h new file mode 100644 index 0000000..f638400 --- /dev/null +++ b/optee/optee_os/ldelf/include/ldelf.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2020-2023, Arm Limited + * Copyright 2022-2023 NXP + */ + +#ifndef __LDELF_H +#define __LDELF_H + +#ifndef __ASSEMBLER__ +#include +#include +#include + +/* Size of stack for TEE Core to allocate */ +#define LDELF_STACK_SIZE (4096 * 2) + +/* + * struct ldelf_arg - argument for ldelf + * @uuid: [in] UUID of TA to load + * @is_32bit: [out] 1 if a 32bit TA or 0 if a 64bit TA + * @flags: [out] Flags field of TA header + * @entry_func: [out] TA entry function + * @stack_ptr: [out] TA stack pointer + * @dump_entry: [out] Dump TA mappings and stack trace + * @ftrace_entry: [out] Dump TA mappings and ftrace buffer + * @fbuf: [out] ftrace buffer pointer + * @dl_entry: [out] Dynamic linking interface (for libdl) + */ +struct ldelf_arg { + TEE_UUID uuid; + uint32_t is_32bit; + uint32_t flags; + uint64_t entry_func; + uint64_t load_addr; + uint64_t stack_ptr; + uint64_t dump_entry; + uint64_t ftrace_entry; + uint64_t dl_entry; + struct ftrace_buf *fbuf; +}; + +#define DUMP_MAP_READ BIT(0) +#define DUMP_MAP_WRITE BIT(1) +#define DUMP_MAP_EXEC BIT(2) +#define DUMP_MAP_SECURE BIT(3) +#define DUMP_MAP_EPHEM BIT(4) +#define DUMP_MAP_LDELF BIT(7) + +/* + * struct dump_entry_arg - argument for ldelf_arg::dump_entry() + */ +struct dump_entry_arg { + union { + struct { + uint32_t regs[16]; + } arm32; + struct { + uint64_t fp; + uint64_t sp; + uint64_t pc; + } arm64; + struct { + unsigned long fp; + unsigned long sp; + unsigned long pc; + } rv; + }; + bool is_32bit; + size_t num_maps; + struct dump_map { + vaddr_t va; + paddr_t pa; + size_t sz; + uint32_t flags; + } maps[]; +}; + +/* + * struct dl_entry_arg - argument for ldelf_arg::dl_entry() + */ +struct dl_entry_arg { + uint32_t cmd; + TEE_Result ret; + union { + struct { + TEE_UUID uuid; /* in */ + uint32_t flags; /* in */ + } dlopen; + struct { + TEE_UUID uuid; /* in */ + vaddr_t val; /* out */ + char symbol[]; /* in */ + } dlsym; + }; +}; + +/* + * Values for dl_entry_arg::cmd + */ +#define LDELF_DL_ENTRY_DLOPEN 0 +#define LDELF_DL_ENTRY_DLSYM 1 + +/* + * Values for dl_entry_arg::dlopen::flags + */ +#define RTLD_NOW 2 +#define RTLD_GLOBAL 0x100 +#define RTLD_NODELETE 0x1000 + +#define LDELF_MAP_FLAG_SHAREABLE BIT32(0) +#define LDELF_MAP_FLAG_WRITEABLE BIT32(1) +#define LDELF_MAP_FLAG_EXECUTABLE BIT32(2) +#define LDELF_MAP_FLAG_BTI BIT32(3) + +#endif /*!__ASSEMBLER__*/ + +#define LDELF_RETURN 0 +#define LDELF_LOG 1 +#define LDELF_PANIC 2 +#define LDELF_MAP_ZI 3 +#define LDELF_UNMAP 4 +#define LDELF_OPEN_BIN 5 +#define LDELF_CLOSE_BIN 6 +#define LDELF_MAP_BIN 7 +#define LDELF_CP_FROM_BIN 8 +#define LDELF_SET_PROT 9 +#define LDELF_REMAP 10 +#define LDELF_GEN_RND_NUM 11 + +#define LDELF_SCN_MAX 11 + +/* + * ldelf is loaded into memory by TEE Core. BSS is initialized and a + * stack is allocated and supplied in SP register. A struct ldelf_arg + * is placed in the stack and a pointer to the struct is provided in + * r0/x0 on ARM and in a0/x10 on RISC-V. + * + * ldelf relocates itself to the address where it is loaded before the main + * C routine is called. + * + * In the main C routine the TA is loaded using the PTA System interface. + */ + +#endif /*__LDELF_H*/ diff --git a/optee/optee_os/ldelf/include/ldelf_syscalls.h b/optee/optee_os/ldelf/include/ldelf_syscalls.h new file mode 100644 index 0000000..785f163 --- /dev/null +++ b/optee/optee_os/ldelf/include/ldelf_syscalls.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Arm Limited + */ + +#ifndef LDELF_SYSCALLS_H +#define LDELF_SYSCALLS_H + +#include +#include +#include + +void _ldelf_return(unsigned long ret) __noreturn; +void _ldelf_log(const void *buf, size_t len); +void _ldelf_panic(unsigned long code); +TEE_Result _ldelf_map_zi(vaddr_t *va, size_t num_bytes, size_t pad_begin, + size_t pad_end, unsigned long flags); +TEE_Result _ldelf_unmap(vaddr_t va, size_t num_bytes); +TEE_Result _ldelf_open_bin(const TEE_UUID *uuid, size_t uuid_size, + uint32_t *handle); +TEE_Result _ldelf_close_bin(unsigned long handle); +TEE_Result _ldelf_map_bin(vaddr_t *va, size_t num_bytes, unsigned long handle, + size_t offs, size_t pad_begin, size_t pad_end, + unsigned long flags); +TEE_Result _ldelf_cp_from_bin(void *dst, size_t offs, size_t num_bytes, + unsigned long handle); +TEE_Result _ldelf_set_prot(unsigned long va, size_t num_bytes, + unsigned long flags); +TEE_Result _ldelf_remap(unsigned long old_va, vaddr_t *new_va, size_t num_bytes, + size_t pad_begin, size_t pad_end); +TEE_Result _ldelf_gen_rnd_num(void *buf, size_t num_bytes); + +#endif /* LDELF_SYSCALLS_H */ diff --git a/optee/optee_os/ldelf/ldelf.ld.S b/optee/optee_os/ldelf/ldelf.ld.S new file mode 100644 index 0000000..1e34a19 --- /dev/null +++ b/optee/optee_os/ldelf/ldelf.ld.S @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2016-2019, Linaro Limited + */ + +#ifdef ARM32 +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +#endif +#ifdef ARM64 +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +#endif +#ifdef RV64 +OUTPUT_ARCH(riscv) +#endif + +ENTRY(_ldelf_start) +SECTIONS { + .text : { + __text_start = .; + *(.text._ldelf_start) + *(.text .text.*) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + /* Workaround for an erratum in ARM's VFP11 coprocessor */ + *(.vfp11_veneer) + __text_end = .; + } + .note.gnu.property : { *(.note.gnu.property) } + .plt : { *(.plt) } + + .eh_frame : { *(.eh_frame) } + .rodata : { + *(.gnu.linkonce.r.*) + *(.rodata .rodata.*) + } + /* .ARM.exidx is sorted, so has to go in its own output section. */ + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + .ARM.extab : { *(.ARM.extab*) } + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .hash : { *(.hash) } + + /* + * Relocation sections may be aligned on 4 or 8 bytes. With ALIGN(8) + * we avoid any padding between __reloc_begin and the first relocation. + */ + . = ALIGN(8); + __reloc_begin = .; + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.dyn : { *(.rel.dyn) } + .rela.dyn : { *(.rela.dyn) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + __reloc_end = .; + + /* Page align to allow dropping execute bit for RW data */ + . = ALIGN(4096); + + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.got) } + + .data : { *(.data .data.* .gnu.linkonce.d.*) } + .bss : { *(.bss .bss.* .gnu.linkonce.b.* COMMON) } + + /DISCARD/ : { *(.interp) } +} diff --git a/optee/optee_os/ldelf/ldelf.mk b/optee/optee_os/ldelf/ldelf.mk new file mode 100644 index 0000000..aa7bb57 --- /dev/null +++ b/optee/optee_os/ldelf/ldelf.mk @@ -0,0 +1,58 @@ +include mk/cleanvars.mk + +# Set current submodule (used for module specific flags compile result etc) +sm := ldelf +sm-$(sm) := y + +link-out-dir$(sm) := $(out-dir)/$(sm) + +cppflags$(sm) := $(core-platform-cppflags) +cflags$(sm) := $(core-platform-cflags) -fpie -fvisibility=hidden +aflags$(sm) := $(core-platform-aflags) + +# ldelf is compiled for the same arch or register width as core +ifeq ($(CFG_ARM64_core),y) +CFG_ARM64_$(sm) := y +endif +ifeq ($(CFG_ARM32_core),y) +CFG_ARM32_$(sm) := y +endif +ifeq ($(CFG_RV64_core),y) +CFG_RV64_$(sm) := y +endif +ifeq ($(CFG_RV32_core),y) +CFG_RV32_$(sm) := y +endif +arch-bits-$(sm) := $(arch-bits-core) + +cppflags$(sm) += -include $(conf-file) +cppflags$(sm) += -DTRACE_LEVEL=$(CFG_TEE_CORE_LOG_LEVEL) +cppflags$(sm) += -D__LDELF__ + +# Use same compiler as for core +CROSS_COMPILE_$(sm) := $(CROSS_COMPILE_core) +COMPILER_$(sm) := $(COMPILER_core) +include mk/$(COMPILER_$(sm)).mk + +base-prefix := $(sm)- + +libname = utils +libdir = lib/libutils +include mk/lib.mk + +libname = utee +libdir = lib/libutee +include mk/lib.mk + +libname = unw +libdir = lib/libunw +include mk/lib.mk + +base-prefix := + +subdirs = ldelf +include mk/subdir.mk + +include mk/compile.mk + +include ldelf/link.mk diff --git a/optee/optee_os/ldelf/link.mk b/optee/optee_os/ldelf/link.mk new file mode 100644 index 0000000..bd49551 --- /dev/null +++ b/optee/optee_os/ldelf/link.mk @@ -0,0 +1,59 @@ +link-script$(sm) = ldelf/ldelf.ld.S +link-script-pp$(sm) = $(link-out-dir$(sm))/ldelf.lds +link-script-dep$(sm) = $(link-out-dir$(sm))/.ldelf.ld.d + +.PHONY: ldelf +ldelf: $(link-out-dir$(sm))/ldelf.dmp +ldelf: $(link-out-dir$(sm))/ldelf.elf +all: ldelf + +cleanfiles += $(link-out-dir$(sm))/ldelf.dmp +cleanfiles += $(link-out-dir$(sm))/ldelf.map +cleanfiles += $(link-out-dir$(sm))/ldelf.elf +cleanfiles += $(link-script-pp$(sm)) $(link-script-dep$(sm)) + +link-ldflags = -pie -static --gc-sections +link-ldflags += -T $(link-script-pp$(sm)) +link-ldflags += -Map=$(link-out-dir$(sm))/ldelf.map +link-ldflags += --sort-section=alignment +link-ldflags += -z max-page-size=4096 # OP-TEE always uses 4K alignment +ifeq ($(CFG_CORE_BTI),y) +link-ldflags += $(call ld-option,-z force-bti) --fatal-warnings +endif +ifeq ($(CFG_ARM32_$(sm)), y) +link-ldflags += $(call ld-option,--no-warn-execstack) +endif +link-ldflags += $(link-ldflags$(sm)) + +link-ldadd = $(addprefix -L,$(libdirs)) +link-ldadd += --start-group $(addprefix -l,$(libnames)) --end-group +ldargs-ldelf.elf := $(link-ldflags) $(objs) $(link-ldadd) $(libgcc$(sm)) + +link-script-cppflags-$(sm) := \ + $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \ + $(nostdinc$(sm)) $(CPPFLAGS) \ + $(addprefix -I,$(incdirs$(sm)) $(link-out-dir$(sm))) \ + $(cppflags$(sm))) + +-include $(link-script-dep$(sm)) + +link-script-pp-makefiles$(sm) = $(filter-out %.d %.cmd,$(MAKEFILE_LIST)) + +define gen-link-t +$(link-script-pp$(sm)): $(link-script$(sm)) $(conf-file) \ + $(link-script-pp-makefiles$(sm)) + @$(cmd-echo-silent) ' CPP $$@' + $(q)mkdir -p $$(dir $$@) + $(q)$(CPP$(sm)) -P -MT $$@ -MD -MF $(link-script-dep$(sm)) \ + $(link-script-cppflags-$(sm)) $$< -o $$@ + +$(link-out-dir$(sm))/ldelf.elf: $(objs) $(libdeps) $(link-script-pp$(sm)) + @$(cmd-echo-silent) ' LD $$@' + $(q)$(LD$(sm)) $(ldargs-ldelf.elf) -o $$@ + +$(link-out-dir$(sm))/ldelf.dmp: $(link-out-dir$(sm))/ldelf.elf + @$(cmd-echo-silent) ' OBJDUMP $$@' + $(q)$(OBJDUMP$(sm)) -l -x -d $$< > $$@ +endef + +$(eval $(call gen-link-t)) diff --git a/optee/optee_os/ldelf/main.c b/optee/optee_os/ldelf/main.c new file mode 100644 index 0000000..1aa9d8c --- /dev/null +++ b/optee/optee_os/ldelf/main.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2022-2023, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dl.h" +#include "ftrace.h" +#include "sys.h" +#include "ta_elf.h" + +static size_t mpool_size = 4 * SMALL_PAGE_SIZE; +static vaddr_t mpool_base; + +static void __printf(2, 0) print_to_console(void *pctx __unused, + const char *fmt, va_list ap) +{ + trace_vprintf(NULL, 0, TRACE_ERROR, true, fmt, ap); +} + +static void __noreturn __maybe_unused dump_ta_state(struct dump_entry_arg *arg) +{ + struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); + + assert(elf && elf->is_main); + EMSG_RAW("Status of TA %pUl", (void *)&elf->uuid); + EMSG_RAW(" arch: %s", elf->is_32bit ? "arm" : "aarch64"); + + + ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue, + arg->num_maps, arg->maps, mpool_base); + + if (arg->is_32bit) + ta_elf_stack_trace_a32(arg->arm32.regs); + else + ta_elf_stack_trace_a64(arg->arm64.fp, arg->arm64.sp, + arg->arm64.pc); + + sys_return_cleanup(); +} + +#ifdef CFG_FTRACE_SUPPORT +struct print_buf_ctx { + char *buf; + size_t blen; + size_t ret; +}; + +static void __printf(2, 0) print_to_pbuf(void *pctx, const char *fmt, + va_list ap) +{ + struct print_buf_ctx *pbuf = pctx; + char *buf = NULL; + size_t blen = 0; + int ret = 0; + + if (pbuf->buf && pbuf->blen > pbuf->ret) { + buf = pbuf->buf + pbuf->ret; + blen = pbuf->blen - pbuf->ret; + } + + ret = vsnprintk(buf, blen, fmt, ap); + assert(ret >= 0); + + pbuf->ret += ret; +} + +static void copy_to_pbuf(void *pctx, void *b, size_t bl) +{ + struct print_buf_ctx *pbuf = pctx; + char *buf = NULL; + size_t blen = 0; + + if (pbuf->buf && pbuf->blen > pbuf->ret) { + buf = pbuf->buf + pbuf->ret; + blen = pbuf->blen - pbuf->ret; + memcpy(buf, b, MIN(blen, bl)); + } + + pbuf->ret += bl; + +} + +static void __noreturn ftrace_dump(void *buf, size_t *blen) +{ + struct print_buf_ctx pbuf = { .buf = buf, .blen = *blen }; + + ta_elf_print_mappings(&pbuf, print_to_pbuf, &main_elf_queue, + 0, NULL, mpool_base); + ftrace_copy_buf(&pbuf, copy_to_pbuf); + *blen = pbuf.ret; + sys_return_cleanup(); +} +#endif + +static void __noreturn dl_entry(struct dl_entry_arg *arg) +{ + switch (arg->cmd) { + case LDELF_DL_ENTRY_DLOPEN: + arg->ret = dlopen_entry(arg); + break; + case LDELF_DL_ENTRY_DLSYM: + arg->ret = dlsym_entry(arg); + break; + default: + arg->ret = TEE_ERROR_NOT_SUPPORTED; + } + + sys_return_cleanup(); +} + +/* + * ldelf()- Loads ELF into memory + * @arg: Argument passing to/from TEE Core + * + * Only called from assembly + */ +void __noreturn ldelf(struct ldelf_arg *arg); +void ldelf(struct ldelf_arg *arg) +{ + TEE_Result res = TEE_SUCCESS; + struct ta_elf *elf = NULL; + + DMSG("Loading TS %pUl", (void *)&arg->uuid); + res = sys_map_zi(mpool_size, 0, &mpool_base, 0, 0); + if (res) { + EMSG("sys_map_zi(%zu): result %"PRIx32, mpool_size, res); + panic(); + } + malloc_add_pool((void *)mpool_base, mpool_size); + + /* Load the main binary and get a list of dependencies, if any. */ + ta_elf_load_main(&arg->uuid, &arg->is_32bit, &arg->stack_ptr, + &arg->flags); + + /* + * Load binaries, ta_elf_load() may add external libraries to the + * list, so the loop will end when all the dependencies are + * satisfied. + */ + TAILQ_FOREACH(elf, &main_elf_queue, link) + ta_elf_load_dependency(elf, arg->is_32bit); + + TAILQ_FOREACH(elf, &main_elf_queue, link) { + ta_elf_relocate(elf); + ta_elf_finalize_mappings(elf); + } + + ta_elf_finalize_load_main(&arg->entry_func, &arg->load_addr); + + arg->ftrace_entry = 0; +#ifdef CFG_FTRACE_SUPPORT + if (ftrace_init(&arg->fbuf)) + arg->ftrace_entry = (vaddr_t)(void *)ftrace_dump; +#endif + + TAILQ_FOREACH(elf, &main_elf_queue, link) + DMSG("ELF (%pUl) at %#"PRIxVA, + (void *)&elf->uuid, elf->load_addr); + +#if TRACE_LEVEL >= TRACE_ERROR + arg->dump_entry = (vaddr_t)(void *)dump_ta_state; +#else + arg->dump_entry = 0; +#endif + arg->dl_entry = (vaddr_t)(void *)dl_entry; + + sys_return_cleanup(); +} diff --git a/optee/optee_os/ldelf/pauth.c b/optee/optee_os/ldelf/pauth.c new file mode 100644 index 0000000..ac70b44 --- /dev/null +++ b/optee/optee_os/ldelf/pauth.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include "pauth.h" + +void pauth_strip_pac(uint64_t *lr) +{ + const uint64_t va_mask = GENMASK_64(CFG_LPAE_ADDR_SPACE_BITS - 1, 0); + + *lr = *lr & va_mask; +} diff --git a/optee/optee_os/ldelf/pauth.h b/optee/optee_os/ldelf/pauth.h new file mode 100644 index 0000000..02f9b07 --- /dev/null +++ b/optee/optee_os/ldelf/pauth.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef PAUTH_H +#define PAUTH_H + +#include +#include + +void pauth_strip_pac(uint64_t *lr); + +#endif /*PAUTH_H*/ + diff --git a/optee/optee_os/ldelf/start_a32.S b/optee/optee_os/ldelf/start_a32.S new file mode 100644 index 0000000..70aa31e --- /dev/null +++ b/optee/optee_os/ldelf/start_a32.S @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include +#include + +/* + * _start() - Entry of ldelf + * + * See include/ldelf.h for details on TEE Core interaction. + * + * void start(struct ldelf_arg *arg); + */ +FUNC _ldelf_start , : + /* + * First ldelf needs to be relocated. The binary is compiled to + * contain only a minimal number of R_ARM_RELATIVE relocations in + * read/write memory, leaving read-only and executeble memory + * untouched. + */ + adr r4, reloc_begin_rel + ldr r5, reloc_begin_rel + ldr r6, reloc_end_rel + add r5, r5, r4 + add r6, r6, r4 + cmp r5, r6 + beq 2f + + adr r4, _ldelf_start /* Get the load offset */ + + /* Loop over the relocations (Elf32_Rel) and process all entries */ +1: ldmia r5!, {r7-r8} /* r7 == r_offset, r8 = r_info */ + and r8, r8, #0xff + cmp r8, #R_ARM_RELATIVE + /* We're currently only supporting R_ARM_RELATIVE relocations */ + bne 3f + + /* Update the pointer at r_offset + load_offset */ + add r7, r7, r4 + ldr r8, [r7] + add r8, r8, r4 + str r8, [r7] + + cmp r5, r6 + blo 1b + +2: bl ldelf + mov r0, #0 + bl _ldelf_return +3: mov r0, #0 + bl _ldelf_panic +reloc_begin_rel: + .word __reloc_begin - reloc_begin_rel +reloc_end_rel: + .word __reloc_end - reloc_end_rel +END_FUNC _ldelf_start diff --git a/optee/optee_os/ldelf/start_a64.S b/optee/optee_os/ldelf/start_a64.S new file mode 100644 index 0000000..fae72da --- /dev/null +++ b/optee/optee_os/ldelf/start_a64.S @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include +#include + +/* + * _start() - Entry of ldelf + * + * See include/ldelf.h for details on TEE Core interaction. + * + * void start(struct ldelf_arg *arg); + */ +FUNC _ldelf_start , : + /* + * First ldelf needs to be relocated. The binary is compiled to + * contain only a minimal number of R_AARCH64_RELATIVE relocations + * in read/write memory, leaving read-only and executeble memory + * untouched. + */ + adr x4, reloc_begin_rel + ldr w5, reloc_begin_rel + ldr w6, reloc_end_rel + add x5, x5, x4 + add x6, x6, x4 + cmp x5, x6 + beq 2f + + adr x4, _ldelf_start /* Get the load offset */ + + /* Loop over the relocations (Elf64_Rela) and process all entries */ +1: ldp x7, x8, [x5], #16 /* x7 = r_offset, x8 = r_info */ + ldr x9, [x5], #8 /* x9 = r_addend */ + and x8, x8, #0xffffffff + cmp x8, #R_AARCH64_RELATIVE + /* We're currently only supporting R_AARCH64_RELATIVE relocations */ + bne 3f + + /* + * Update the pointer at r_offset + load_offset with r_addend + + * load_offset. + */ + add x7, x7, x4 + add x9, x9, x4 + str x9, [x7] + + cmp x5, x6 + blo 1b + +2: bl ldelf + mov x0, #0 + bl _ldelf_return +3: mov x0, #0 + bl _ldelf_panic +reloc_begin_rel: + .word __reloc_begin - reloc_begin_rel +reloc_end_rel: + .word __reloc_end - reloc_end_rel +END_FUNC _ldelf_start + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/ldelf/start_rv64.S b/optee/optee_os/ldelf/start_rv64.S new file mode 100644 index 0000000..42d36f5 --- /dev/null +++ b/optee/optee_os/ldelf/start_rv64.S @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 Beijing ESWIN Computing Technology Co., Ltd. + */ + +#include +#include + +/* + * _ldelf_start() - Entry of ldelf + * + * See include/ldelf.h for details on TEE Core interaction. + * + * void _ldelf_start(struct ldelf_arg *arg); + */ +FUNC _ldelf_start , : + /* + * First ldelf needs to be relocated. The binary is compiled to + * contain only a minimal number of R_RISCV_RELATIVE relocations in + * read/write memory, leaving read-only and executable memory + * untouched. + */ + lla a1, reloc_end_rel + lw a3, 0(a1) + lla a1, reloc_begin_rel + lw a2, 0(a1) + add a2, a2, a1 + add a3, a3, a1 + beq a2, a3, 2f + + lla a1, _ldelf_start /* Get the load offset */ + + /* Loop over the relocations (Elf64_Rela) and process all entries */ +1: + ld t1, 0(a2) /* t1 = r_offset */ + ld t2, 8(a2) /* t2 = r_info */ + ld t3, 16(a2) /* t3 = r_addend */ + addi a2, a2, 24 + and t2, t2, 0xff + addi t4, zero, R_RISCV_RELATIVE + bne t2, t4, 3f + + /* Update the pointer at r_offset + load offset */ + add t1, a1, t1 + ld t4, 0(t1) + add t4, t4, t3 + add t4, t4, a1 + sd t4, 0(t1) + ble a2, a3, 1b +2: + jal ldelf + addi a0, a0, 0 + jal _ldelf_return +3: + addi a0, a0, 0 + jal _ldelf_panic +reloc_begin_rel: + .word __reloc_begin - reloc_begin_rel +reloc_end_rel: + .word __reloc_end - reloc_end_rel +END_FUNC _ldelf_start diff --git a/optee/optee_os/ldelf/sub.mk b/optee/optee_os/ldelf/sub.mk new file mode 100644 index 0000000..40c1a0a --- /dev/null +++ b/optee/optee_os/ldelf/sub.mk @@ -0,0 +1,15 @@ +global-incdirs-y += include +srcs-$(CFG_ARM32_$(sm)) += start_a32.S +srcs-$(CFG_ARM64_$(sm)) += start_a64.S +srcs-$(CFG_ARM32_$(sm)) += syscalls_a32.S +srcs-$(CFG_ARM64_$(sm)) += syscalls_a64.S +srcs-$(CFG_ARM64_$(sm)) += tlsdesc_rel_a64.S +srcs-$(CFG_RV64_$(sm)) += start_rv64.S +srcs-$(call cfg-one-enabled,CFG_RV32_$(sm) CFG_RV64_$(sm)) += syscalls_rv.S +srcs-y += dl.c +srcs-y += main.c +srcs-y += sys.c +srcs-y += ta_elf.c +srcs-y += ta_elf_rel.c +srcs-$(CFG_FTRACE_SUPPORT) += ftrace.c +srcs-$(CFG_TA_PAUTH) += pauth.c diff --git a/optee/optee_os/ldelf/sys.c b/optee/optee_os/ldelf/sys.c new file mode 100644 index 0000000..2017d93 --- /dev/null +++ b/optee/optee_os/ldelf/sys.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include +#include + +#include "sys.h" + +int trace_level = TRACE_LEVEL; +const char trace_ext_prefix[] = "LD"; + +void __panic(const char *file __maybe_unused, const int line __maybe_unused, + const char *func __maybe_unused) +{ + if (!file && !func) + EMSG_RAW("Panic"); + else + EMSG_RAW("Panic at %s:%d %s%s%s", + file ? file : "?", file ? line : 0, + func ? "<" : "", func ? func : "", func ? ">" : ""); + + _ldelf_panic(1); + /*NOTREACHED*/ + while (true) + ; +} + +void sys_return_cleanup(void) +{ + _ldelf_return(0); + /*NOTREACHED*/ + while (true) + ; +} + +TEE_Result sys_map_zi(size_t num_bytes, uint32_t flags, vaddr_t *va, + size_t pad_begin, size_t pad_end) +{ + return _ldelf_map_zi(va, num_bytes, pad_begin, pad_end, flags); +} + +TEE_Result sys_unmap(vaddr_t va, size_t num_bytes) +{ + return _ldelf_unmap(va, num_bytes); +} + +TEE_Result sys_open_ta_bin(const TEE_UUID *uuid, uint32_t *handle) +{ + return _ldelf_open_bin(uuid, sizeof(TEE_UUID), handle); +} + +TEE_Result sys_close_ta_bin(uint32_t handle) +{ + return _ldelf_close_bin(handle); +} + +TEE_Result sys_map_ta_bin(vaddr_t *va, size_t num_bytes, uint32_t flags, + uint32_t handle, size_t offs, size_t pad_begin, + size_t pad_end) +{ + return _ldelf_map_bin(va, num_bytes, handle, offs, + pad_begin, pad_end, flags); +} + + +TEE_Result sys_copy_from_ta_bin(void *dst, size_t num_bytes, uint32_t handle, + size_t offs) +{ + return _ldelf_cp_from_bin(dst, offs, num_bytes, handle); +} + +TEE_Result sys_set_prot(vaddr_t va, size_t num_bytes, uint32_t flags) +{ + return _ldelf_set_prot(va, num_bytes, flags); +} + +TEE_Result sys_remap(vaddr_t old_va, vaddr_t *new_va, size_t num_bytes, + size_t pad_begin, size_t pad_end) +{ + return _ldelf_remap(old_va, new_va, num_bytes, pad_begin, pad_end); +} + +TEE_Result sys_gen_random_num(void *buf, size_t blen) +{ + return _ldelf_gen_rnd_num(buf, blen); +} diff --git a/optee/optee_os/ldelf/sys.h b/optee/optee_os/ldelf/sys.h new file mode 100644 index 0000000..7051d55 --- /dev/null +++ b/optee/optee_os/ldelf/sys.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#ifndef SYS_H +#define SYS_H + +#include +#include +#include +#include +#include +#include + +#if defined(CFG_TEE_CORE_DEBUG) +#define panic() __panic(__FILE__, __LINE__, __func__) +#else +#define panic() __panic(NULL, 0, NULL) +#endif + +/* A small page is the smallest unit of memory that can be mapped */ +#define SMALL_PAGE_SHIFT 12 +#define SMALL_PAGE_MASK 0x00000fff +#define SMALL_PAGE_SIZE 0x00001000 + +void __noreturn __panic(const char *file, const int line, const char *func); +void __noreturn sys_return_cleanup(void); + +#define err(res, ...) \ + do { \ + trace_printf_helper(TRACE_ERROR, true, __VA_ARGS__); \ + _ldelf_return(res); \ + } while (0) + +TEE_Result sys_map_zi(size_t num_bytes, uint32_t flags, vaddr_t *va, + size_t pad_begin, size_t pad_end); +TEE_Result sys_unmap(vaddr_t va, size_t num_bytes); +TEE_Result sys_open_ta_bin(const TEE_UUID *uuid, uint32_t *handle); +TEE_Result sys_close_ta_bin(uint32_t handle); +TEE_Result sys_map_ta_bin(vaddr_t *va, size_t num_bytes, uint32_t flags, + uint32_t handle, size_t offs, size_t pad_begin, + size_t pad_end); +TEE_Result sys_copy_from_ta_bin(void *dst, size_t num_bytes, uint32_t handle, + size_t offs); +TEE_Result sys_set_prot(vaddr_t va, size_t num_bytes, uint32_t flags); +TEE_Result sys_remap(vaddr_t old_va, vaddr_t *new_va, size_t num_bytes, + size_t pad_begin, size_t pad_end); +TEE_Result sys_gen_random_num(void *buf, size_t blen); + +#endif /*SYS_H*/ diff --git a/optee/optee_os/ldelf/syscalls_a32.S b/optee/optee_os/ldelf/syscalls_a32.S new file mode 100644 index 0000000..332fa94 --- /dev/null +++ b/optee/optee_os/ldelf/syscalls_a32.S @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include + + .section .text + .balign 4 + .code 32 + + .macro LDELF_SYSCALL name, scn, num_args + FUNC \name , : + + .if \num_args > 8 + .error "Too many arguments for syscall" + .endif + + push {r5-r7, lr} +UNWIND( .save {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} + END_FUNC \name + .endm + + FUNC _ldelf_panic, : + push {r0-r11, lr} +UNWIND( .save {r0-r11, lr}) + mov lr, pc + push {lr} +UNWIND( .save {lr}) + mov r1, sp + bl __ldelf_panic + /* Not reached */ + END_FUNC _ldelf_panic + +#include "syscalls_asm.S" diff --git a/optee/optee_os/ldelf/syscalls_a64.S b/optee/optee_os/ldelf/syscalls_a64.S new file mode 100644 index 0000000..dab790c --- /dev/null +++ b/optee/optee_os/ldelf/syscalls_a64.S @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2020, Arm Limited + */ + +#include + + .section .text + + .macro LDELF_SYSCALL name, scn, num_args + FUNC \name , : + + .if \num_args > 8 + .error "Too many arguments for syscall" + .endif + + mov x8, #(\scn) + svc #0 + ret + END_FUNC \name + .endm + + FUNC _ldelf_panic, : + stp x29, x30, [sp, #-16]! + mov x1, sp + bl __ldelf_panic + /* Not reached */ + END_FUNC _ldelf_panic + +#include "syscalls_asm.S" + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/ldelf/syscalls_asm.S b/optee/optee_os/ldelf/syscalls_asm.S new file mode 100644 index 0000000..959ec6a --- /dev/null +++ b/optee/optee_os/ldelf/syscalls_asm.S @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Arm Limited + */ + +#include + +/* macro function name syscall num num of args */ +LDELF_SYSCALL _ldelf_return, LDELF_RETURN, 1 +LDELF_SYSCALL _ldelf_log, LDELF_LOG, 2 +LDELF_SYSCALL __ldelf_panic, LDELF_PANIC, 1 +LDELF_SYSCALL _ldelf_map_zi, LDELF_MAP_ZI, 6 +LDELF_SYSCALL _ldelf_unmap, LDELF_UNMAP, 3 +LDELF_SYSCALL _ldelf_open_bin, LDELF_OPEN_BIN, 3 +LDELF_SYSCALL _ldelf_close_bin, LDELF_CLOSE_BIN, 1 +LDELF_SYSCALL _ldelf_map_bin, LDELF_MAP_BIN, 8 +LDELF_SYSCALL _ldelf_cp_from_bin, LDELF_CP_FROM_BIN, 4 +LDELF_SYSCALL _ldelf_set_prot, LDELF_SET_PROT, 4 +LDELF_SYSCALL _ldelf_remap, LDELF_REMAP, 7 +LDELF_SYSCALL _ldelf_gen_rnd_num, LDELF_GEN_RND_NUM, 2 diff --git a/optee/optee_os/ldelf/syscalls_rv.S b/optee/optee_os/ldelf/syscalls_rv.S new file mode 100644 index 0000000..ba6eb30 --- /dev/null +++ b/optee/optee_os/ldelf/syscalls_rv.S @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2023 ESWIN Corp. or its affiliates. + * Authors: + * Liu Shiwei + */ + +#include + + .section .text + + .macro LDELF_SYSCALL name, scn, num_args +FUNC \name , : + + .if \num_args > 8 + .error "Too many arguments for syscall" + .endif + + li t0, \scn + li t1, \num_args + ecall + ret +END_FUNC \name + .endm + +FUNC _ldelf_panic, : + j __ldelf_panic + /* Not reached */ +END_FUNC _ldelf_panic + +#include "syscalls_asm.S" diff --git a/optee/optee_os/ldelf/ta_elf.c b/optee/optee_os/ldelf/ta_elf.c new file mode 100644 index 0000000..3c09569 --- /dev/null +++ b/optee/optee_os/ldelf/ta_elf.c @@ -0,0 +1,1989 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2020-2023, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys.h" +#include "ta_elf.h" + +/* + * Layout of a 32-bit struct dl_phdr_info for a 64-bit ldelf to access a 32-bit + * TA + */ +struct dl_phdr_info32 { + uint32_t dlpi_addr; + uint32_t dlpi_name; + uint32_t dlpi_phdr; + uint16_t dlpi_phnum; + uint64_t dlpi_adds; + uint64_t dlpi_subs; + uint32_t dlpi_tls_modid; + uint32_t dlpi_tls_data; +}; + +static vaddr_t ta_stack; +static vaddr_t ta_stack_size; + +struct ta_elf_queue main_elf_queue = TAILQ_HEAD_INITIALIZER(main_elf_queue); + +/* + * Main application is always ID 1, shared libraries with TLS take IDs 2 and + * above + */ +static void assign_tls_mod_id(struct ta_elf *elf) +{ + static size_t last_tls_mod_id = 1; + + if (elf->is_main) + assert(last_tls_mod_id == 1); /* Main always comes first */ + elf->tls_mod_id = last_tls_mod_id++; +} + +static struct ta_elf *queue_elf_helper(const TEE_UUID *uuid) +{ + struct ta_elf *elf = calloc(1, sizeof(*elf)); + + if (!elf) + return NULL; + + TAILQ_INIT(&elf->segs); + + elf->uuid = *uuid; + TAILQ_INSERT_TAIL(&main_elf_queue, elf, link); + return elf; +} + +static struct ta_elf *queue_elf(const TEE_UUID *uuid) +{ + struct ta_elf *elf = ta_elf_find_elf(uuid); + + if (elf) + return NULL; + + elf = queue_elf_helper(uuid); + if (!elf) + err(TEE_ERROR_OUT_OF_MEMORY, "queue_elf_helper"); + + return elf; +} + +struct ta_elf *ta_elf_find_elf(const TEE_UUID *uuid) +{ + struct ta_elf *elf = NULL; + + TAILQ_FOREACH(elf, &main_elf_queue, link) + if (!memcmp(uuid, &elf->uuid, sizeof(*uuid))) + return elf; + + return NULL; +} + +#if defined(ARM32) || defined(ARM64) +static TEE_Result e32_parse_ehdr(struct ta_elf *elf, Elf32_Ehdr *ehdr) +{ + if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_ident[EI_CLASS] != ELFCLASS32 || + ehdr->e_ident[EI_DATA] != ELFDATA2LSB || + ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE || + ehdr->e_type != ET_DYN || ehdr->e_machine != EM_ARM || + (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_VERSION || +#ifndef CFG_WITH_VFP + (ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) || +#endif + ehdr->e_phentsize != sizeof(Elf32_Phdr) || + ehdr->e_shentsize != sizeof(Elf32_Shdr)) + return TEE_ERROR_BAD_FORMAT; + + elf->is_32bit = true; + elf->e_entry = ehdr->e_entry; + elf->e_phoff = ehdr->e_phoff; + elf->e_shoff = ehdr->e_shoff; + elf->e_phnum = ehdr->e_phnum; + elf->e_shnum = ehdr->e_shnum; + elf->e_phentsize = ehdr->e_phentsize; + elf->e_shentsize = ehdr->e_shentsize; + + return TEE_SUCCESS; +} + +#ifdef ARM64 +static TEE_Result e64_parse_ehdr(struct ta_elf *elf, Elf64_Ehdr *ehdr) +{ + if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_ident[EI_CLASS] != ELFCLASS64 || + ehdr->e_ident[EI_DATA] != ELFDATA2LSB || + ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE || + ehdr->e_type != ET_DYN || ehdr->e_machine != EM_AARCH64 || + ehdr->e_flags || ehdr->e_phentsize != sizeof(Elf64_Phdr) || + ehdr->e_shentsize != sizeof(Elf64_Shdr)) + return TEE_ERROR_BAD_FORMAT; + + + elf->is_32bit = false; + elf->e_entry = ehdr->e_entry; + elf->e_phoff = ehdr->e_phoff; + elf->e_shoff = ehdr->e_shoff; + elf->e_phnum = ehdr->e_phnum; + elf->e_shnum = ehdr->e_shnum; + elf->e_phentsize = ehdr->e_phentsize; + elf->e_shentsize = ehdr->e_shentsize; + + return TEE_SUCCESS; +} +#else /*ARM64*/ +static TEE_Result e64_parse_ehdr(struct ta_elf *elf __unused, + Elf64_Ehdr *ehdr __unused) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif /*ARM64*/ +#endif /* ARM32 || ARM64 */ + +#if defined(RV64) +static TEE_Result e32_parse_ehdr(struct ta_elf *elf __unused, + Elf32_Ehdr *ehdr __unused) +{ + return TEE_ERROR_BAD_FORMAT; +} + +static TEE_Result e64_parse_ehdr(struct ta_elf *elf, Elf64_Ehdr *ehdr) +{ + if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_ident[EI_CLASS] != ELFCLASS64 || + ehdr->e_ident[EI_DATA] != ELFDATA2LSB || + ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE || + ehdr->e_type != ET_DYN || ehdr->e_machine != EM_RISCV || + ehdr->e_phentsize != sizeof(Elf64_Phdr) || + ehdr->e_shentsize != sizeof(Elf64_Shdr)) + return TEE_ERROR_BAD_FORMAT; + + elf->is_32bit = false; + elf->e_entry = ehdr->e_entry; + elf->e_phoff = ehdr->e_phoff; + elf->e_shoff = ehdr->e_shoff; + elf->e_phnum = ehdr->e_phnum; + elf->e_shnum = ehdr->e_shnum; + elf->e_phentsize = ehdr->e_phentsize; + elf->e_shentsize = ehdr->e_shentsize; + + return TEE_SUCCESS; +} +#endif /* RV64 */ + +static void check_phdr_in_range(struct ta_elf *elf, unsigned int type, + vaddr_t addr, size_t memsz) +{ + vaddr_t max_addr = 0; + + if (ADD_OVERFLOW(addr, memsz, &max_addr)) + err(TEE_ERROR_BAD_FORMAT, "Program header %#x overflow", type); + + /* + * elf->load_addr and elf->max_addr are both using the + * final virtual addresses, while this program header is + * relative to 0. + */ + if (max_addr > elf->max_addr - elf->load_addr) + err(TEE_ERROR_BAD_FORMAT, "Program header %#x out of bounds", + type); +} + +static void read_dyn(struct ta_elf *elf, vaddr_t addr, + size_t idx, unsigned int *tag, size_t *val) +{ + if (elf->is_32bit) { + Elf32_Dyn *dyn = (Elf32_Dyn *)(addr + elf->load_addr); + + *tag = dyn[idx].d_tag; + *val = dyn[idx].d_un.d_val; + } else { + Elf64_Dyn *dyn = (Elf64_Dyn *)(addr + elf->load_addr); + + *tag = dyn[idx].d_tag; + *val = dyn[idx].d_un.d_val; + } +} + +static void check_range(struct ta_elf *elf, const char *name, const void *ptr, + size_t sz) +{ + size_t max_addr = 0; + + if ((vaddr_t)ptr < elf->load_addr) + err(TEE_ERROR_BAD_FORMAT, "%s %p out of range", name, ptr); + + if (ADD_OVERFLOW((vaddr_t)ptr, sz, &max_addr)) + err(TEE_ERROR_BAD_FORMAT, "%s range overflow", name); + + if (max_addr > elf->max_addr) + err(TEE_ERROR_BAD_FORMAT, + "%s %p..%#zx out of range", name, ptr, max_addr); +} + +static void check_hashtab(struct ta_elf *elf, void *ptr, size_t num_buckets, + size_t num_chains) +{ + /* + * Starting from 2 as the first two words are mandatory and hold + * num_buckets and num_chains. So this function is called twice, + * first to see that there's indeed room for num_buckets and + * num_chains and then to see that all of it fits. + * See http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash + */ + size_t num_words = 2; + size_t sz = 0; + + if (!IS_ALIGNED_WITH_TYPE(ptr, uint32_t)) + err(TEE_ERROR_BAD_FORMAT, "Bad alignment of DT_HASH %p", ptr); + + if (ADD_OVERFLOW(num_words, num_buckets, &num_words) || + ADD_OVERFLOW(num_words, num_chains, &num_words) || + MUL_OVERFLOW(num_words, sizeof(uint32_t), &sz)) + err(TEE_ERROR_BAD_FORMAT, "DT_HASH overflow"); + + check_range(elf, "DT_HASH", ptr, sz); +} + +static void check_gnu_hashtab(struct ta_elf *elf, void *ptr) +{ + struct gnu_hashtab *h = ptr; + size_t num_words = 4; /* nbuckets, symoffset, bloom_size, bloom_shift */ + size_t bloom_words = 0; + size_t sz = 0; + + if (!IS_ALIGNED_WITH_TYPE(ptr, uint32_t)) + err(TEE_ERROR_BAD_FORMAT, "Bad alignment of DT_GNU_HASH %p", + ptr); + + if (elf->gnu_hashtab_size < sizeof(*h)) + err(TEE_ERROR_BAD_FORMAT, "DT_GNU_HASH too small"); + + /* Check validity of h->nbuckets and h->bloom_size */ + + if (elf->is_32bit) + bloom_words = h->bloom_size; + else + bloom_words = h->bloom_size * 2; + if (ADD_OVERFLOW(num_words, h->nbuckets, &num_words) || + ADD_OVERFLOW(num_words, bloom_words, &num_words) || + MUL_OVERFLOW(num_words, sizeof(uint32_t), &sz) || + sz > elf->gnu_hashtab_size) + err(TEE_ERROR_BAD_FORMAT, "DT_GNU_HASH overflow"); +} + +static void save_hashtab(struct ta_elf *elf) +{ + uint32_t *hashtab = NULL; + size_t n = 0; + + if (elf->is_32bit) { + Elf32_Shdr *shdr = elf->shdr; + + for (n = 0; n < elf->e_shnum; n++) { + void *addr = (void *)(vaddr_t)(shdr[n].sh_addr + + elf->load_addr); + + if (shdr[n].sh_type == SHT_HASH) { + elf->hashtab = addr; + } else if (shdr[n].sh_type == SHT_GNU_HASH) { + elf->gnu_hashtab = addr; + elf->gnu_hashtab_size = shdr[n].sh_size; + } + } + } else { + Elf64_Shdr *shdr = elf->shdr; + + for (n = 0; n < elf->e_shnum; n++) { + void *addr = (void *)(vaddr_t)(shdr[n].sh_addr + + elf->load_addr); + + if (shdr[n].sh_type == SHT_HASH) { + elf->hashtab = addr; + } else if (shdr[n].sh_type == SHT_GNU_HASH) { + elf->gnu_hashtab = addr; + elf->gnu_hashtab_size = shdr[n].sh_size; + } + } + } + + if (elf->hashtab) { + check_hashtab(elf, elf->hashtab, 0, 0); + hashtab = elf->hashtab; + check_hashtab(elf, elf->hashtab, hashtab[0], hashtab[1]); + } + if (elf->gnu_hashtab) + check_gnu_hashtab(elf, elf->gnu_hashtab); +} + +static void save_soname_from_segment(struct ta_elf *elf, unsigned int type, + vaddr_t addr, size_t memsz) +{ + size_t dyn_entsize = 0; + size_t num_dyns = 0; + size_t n = 0; + unsigned int tag = 0; + size_t val = 0; + char *str_tab = NULL; + + if (type != PT_DYNAMIC) + return; + + if (elf->is_32bit) + dyn_entsize = sizeof(Elf32_Dyn); + else + dyn_entsize = sizeof(Elf64_Dyn); + + assert(!(memsz % dyn_entsize)); + num_dyns = memsz / dyn_entsize; + + for (n = 0; n < num_dyns; n++) { + read_dyn(elf, addr, n, &tag, &val); + if (tag == DT_STRTAB) { + str_tab = (char *)(val + elf->load_addr); + break; + } + } + for (n = 0; n < num_dyns; n++) { + read_dyn(elf, addr, n, &tag, &val); + if (tag == DT_SONAME) { + elf->soname = str_tab + val; + break; + } + } +} + +static void save_soname(struct ta_elf *elf) +{ + size_t n = 0; + + if (elf->is_32bit) { + Elf32_Phdr *phdr = elf->phdr; + + for (n = 0; n < elf->e_phnum; n++) + save_soname_from_segment(elf, phdr[n].p_type, + phdr[n].p_vaddr, + phdr[n].p_memsz); + } else { + Elf64_Phdr *phdr = elf->phdr; + + for (n = 0; n < elf->e_phnum; n++) + save_soname_from_segment(elf, phdr[n].p_type, + phdr[n].p_vaddr, + phdr[n].p_memsz); + } +} + +static void e32_save_symtab(struct ta_elf *elf, size_t tab_idx) +{ + Elf32_Shdr *shdr = elf->shdr; + size_t str_idx = shdr[tab_idx].sh_link; + + elf->dynsymtab = (void *)(shdr[tab_idx].sh_addr + elf->load_addr); + if (!IS_ALIGNED_WITH_TYPE(elf->dynsymtab, Elf32_Sym)) + err(TEE_ERROR_BAD_FORMAT, "Bad alignment of dynsymtab %p", + elf->dynsymtab); + check_range(elf, "Dynsymtab", elf->dynsymtab, shdr[tab_idx].sh_size); + + if (shdr[tab_idx].sh_size % sizeof(Elf32_Sym)) + err(TEE_ERROR_BAD_FORMAT, + "Size of dynsymtab not an even multiple of Elf32_Sym"); + elf->num_dynsyms = shdr[tab_idx].sh_size / sizeof(Elf32_Sym); + + if (str_idx >= elf->e_shnum) + err(TEE_ERROR_BAD_FORMAT, "Dynstr section index out of range"); + elf->dynstr = (void *)(shdr[str_idx].sh_addr + elf->load_addr); + check_range(elf, "Dynstr", elf->dynstr, shdr[str_idx].sh_size); + + elf->dynstr_size = shdr[str_idx].sh_size; +} + +static void e64_save_symtab(struct ta_elf *elf, size_t tab_idx) +{ + Elf64_Shdr *shdr = elf->shdr; + size_t str_idx = shdr[tab_idx].sh_link; + + elf->dynsymtab = (void *)(vaddr_t)(shdr[tab_idx].sh_addr + + elf->load_addr); + + if (!IS_ALIGNED_WITH_TYPE(elf->dynsymtab, Elf64_Sym)) + err(TEE_ERROR_BAD_FORMAT, "Bad alignment of .dynsym/DYNSYM %p", + elf->dynsymtab); + check_range(elf, ".dynsym/DYNSYM", elf->dynsymtab, + shdr[tab_idx].sh_size); + + if (shdr[tab_idx].sh_size % sizeof(Elf64_Sym)) + err(TEE_ERROR_BAD_FORMAT, + "Size of .dynsym/DYNSYM not an even multiple of Elf64_Sym"); + elf->num_dynsyms = shdr[tab_idx].sh_size / sizeof(Elf64_Sym); + + if (str_idx >= elf->e_shnum) + err(TEE_ERROR_BAD_FORMAT, + ".dynstr/STRTAB section index out of range"); + elf->dynstr = (void *)(vaddr_t)(shdr[str_idx].sh_addr + elf->load_addr); + check_range(elf, ".dynstr/STRTAB", elf->dynstr, shdr[str_idx].sh_size); + + elf->dynstr_size = shdr[str_idx].sh_size; +} + +static void save_symtab(struct ta_elf *elf) +{ + size_t n = 0; + + if (elf->is_32bit) { + Elf32_Shdr *shdr = elf->shdr; + + for (n = 0; n < elf->e_shnum; n++) { + if (shdr[n].sh_type == SHT_DYNSYM) { + e32_save_symtab(elf, n); + break; + } + } + } else { + Elf64_Shdr *shdr = elf->shdr; + + for (n = 0; n < elf->e_shnum; n++) { + if (shdr[n].sh_type == SHT_DYNSYM) { + e64_save_symtab(elf, n); + break; + } + } + + } + + save_hashtab(elf); + save_soname(elf); +} + +static void init_elf(struct ta_elf *elf) +{ + TEE_Result res = TEE_SUCCESS; + vaddr_t va = 0; + uint32_t flags = LDELF_MAP_FLAG_SHAREABLE; + size_t sz = 0; + + res = sys_open_ta_bin(&elf->uuid, &elf->handle); + if (res) + err(res, "sys_open_ta_bin(%pUl)", (void *)&elf->uuid); + + /* + * Map it read-only executable when we're loading a library where + * the ELF header is included in a load segment. + */ + if (!elf->is_main) + flags |= LDELF_MAP_FLAG_EXECUTABLE; + res = sys_map_ta_bin(&va, SMALL_PAGE_SIZE, flags, elf->handle, 0, 0, 0); + if (res) + err(res, "sys_map_ta_bin"); + elf->ehdr_addr = va; + if (!elf->is_main) { + elf->load_addr = va; + elf->max_addr = va + SMALL_PAGE_SIZE; + elf->max_offs = SMALL_PAGE_SIZE; + } + + if (!IS_ELF(*(Elf32_Ehdr *)va)) + err(TEE_ERROR_BAD_FORMAT, "TA is not an ELF"); + + res = e32_parse_ehdr(elf, (void *)va); + if (res == TEE_ERROR_BAD_FORMAT) + res = e64_parse_ehdr(elf, (void *)va); + if (res) + err(res, "Cannot parse ELF"); + + if (MUL_OVERFLOW(elf->e_phnum, elf->e_phentsize, &sz) || + ADD_OVERFLOW(sz, elf->e_phoff, &sz)) + err(TEE_ERROR_BAD_FORMAT, "Program headers size overflow"); + + if (sz > SMALL_PAGE_SIZE) + err(TEE_ERROR_NOT_SUPPORTED, "Cannot read program headers"); + + elf->phdr = (void *)(va + elf->e_phoff); +} + +static size_t roundup(size_t v) +{ + return ROUNDUP(v, SMALL_PAGE_SIZE); +} + +static size_t rounddown(size_t v) +{ + return ROUNDDOWN(v, SMALL_PAGE_SIZE); +} + +static void add_segment(struct ta_elf *elf, size_t offset, size_t vaddr, + size_t filesz, size_t memsz, size_t flags, size_t align) +{ + struct segment *seg = calloc(1, sizeof(*seg)); + + if (!seg) + err(TEE_ERROR_OUT_OF_MEMORY, "calloc"); + + if (memsz < filesz) + err(TEE_ERROR_BAD_FORMAT, "Memsz smaller than filesz"); + + seg->offset = offset; + seg->vaddr = vaddr; + seg->filesz = filesz; + seg->memsz = memsz; + seg->flags = flags; + seg->align = align; + + TAILQ_INSERT_TAIL(&elf->segs, seg, link); +} + +static void parse_load_segments(struct ta_elf *elf) +{ + size_t n = 0; + + if (elf->is_32bit) { + Elf32_Phdr *phdr = elf->phdr; + + for (n = 0; n < elf->e_phnum; n++) + if (phdr[n].p_type == PT_LOAD) { + add_segment(elf, phdr[n].p_offset, + phdr[n].p_vaddr, phdr[n].p_filesz, + phdr[n].p_memsz, phdr[n].p_flags, + phdr[n].p_align); + } else if (phdr[n].p_type == PT_ARM_EXIDX) { + elf->exidx_start = phdr[n].p_vaddr; + elf->exidx_size = phdr[n].p_filesz; + } else if (phdr[n].p_type == PT_TLS) { + assign_tls_mod_id(elf); + } + } else { + Elf64_Phdr *phdr = elf->phdr; + + for (n = 0; n < elf->e_phnum; n++) + if (phdr[n].p_type == PT_LOAD) { + add_segment(elf, phdr[n].p_offset, + phdr[n].p_vaddr, phdr[n].p_filesz, + phdr[n].p_memsz, phdr[n].p_flags, + phdr[n].p_align); + } else if (phdr[n].p_type == PT_TLS) { + elf->tls_start = phdr[n].p_vaddr; + elf->tls_filesz = phdr[n].p_filesz; + elf->tls_memsz = phdr[n].p_memsz; + } else if (IS_ENABLED(CFG_TA_BTI) && + phdr[n].p_type == PT_GNU_PROPERTY) { + elf->prop_start = phdr[n].p_vaddr; + elf->prop_align = phdr[n].p_align; + elf->prop_memsz = phdr[n].p_memsz; + } + } +} + +static void copy_remapped_to(struct ta_elf *elf, const struct segment *seg) +{ + uint8_t *dst = (void *)(seg->vaddr + elf->load_addr); + size_t n = 0; + size_t offs = seg->offset; + size_t num_bytes = seg->filesz; + + if (offs < elf->max_offs) { + n = MIN(elf->max_offs - offs, num_bytes); + memcpy(dst, (void *)(elf->max_addr + offs - elf->max_offs), n); + dst += n; + offs += n; + num_bytes -= n; + } + + if (num_bytes) { + TEE_Result res = sys_copy_from_ta_bin(dst, num_bytes, + elf->handle, offs); + + if (res) + err(res, "sys_copy_from_ta_bin"); + elf->max_offs += offs; + } +} + +static void adjust_segments(struct ta_elf *elf) +{ + struct segment *seg = NULL; + struct segment *prev_seg = NULL; + size_t prev_end_addr = 0; + size_t align = 0; + size_t mask = 0; + + /* Sanity check */ + TAILQ_FOREACH(seg, &elf->segs, link) { + size_t dummy __maybe_unused = 0; + + assert(seg->align >= SMALL_PAGE_SIZE); + assert(!ADD_OVERFLOW(seg->vaddr, seg->memsz, &dummy)); + assert(seg->filesz <= seg->memsz); + assert((seg->offset & SMALL_PAGE_MASK) == + (seg->vaddr & SMALL_PAGE_MASK)); + + prev_seg = TAILQ_PREV(seg, segment_head, link); + if (prev_seg) { + assert(seg->vaddr >= prev_seg->vaddr + prev_seg->memsz); + assert(seg->offset >= + prev_seg->offset + prev_seg->filesz); + } + if (!align) + align = seg->align; + assert(align == seg->align); + } + + mask = align - 1; + + seg = TAILQ_FIRST(&elf->segs); + if (seg) + seg = TAILQ_NEXT(seg, link); + while (seg) { + prev_seg = TAILQ_PREV(seg, segment_head, link); + prev_end_addr = prev_seg->vaddr + prev_seg->memsz; + + /* + * This segment may overlap with the last "page" in the + * previous segment in two different ways: + * 1. Virtual address (and offset) overlaps => + * Permissions needs to be merged. The offset must have + * the SMALL_PAGE_MASK bits set as vaddr and offset must + * add up with prevsion segment. + * + * 2. Only offset overlaps => + * The same page in the ELF is mapped at two different + * virtual addresses. As a limitation this segment must + * be mapped as writeable. + */ + + /* Case 1. */ + if (rounddown(seg->vaddr) < prev_end_addr) { + assert((seg->vaddr & mask) == (seg->offset & mask)); + assert(prev_seg->memsz == prev_seg->filesz); + + /* + * Merge the segments and their permissions. + * Note that the may be a small hole between the + * two sections. + */ + prev_seg->filesz = seg->vaddr + seg->filesz - + prev_seg->vaddr; + prev_seg->memsz = seg->vaddr + seg->memsz - + prev_seg->vaddr; + prev_seg->flags |= seg->flags; + + TAILQ_REMOVE(&elf->segs, seg, link); + free(seg); + seg = TAILQ_NEXT(prev_seg, link); + continue; + } + + /* Case 2. */ + if ((seg->offset & mask) && + rounddown(seg->offset) < + (prev_seg->offset + prev_seg->filesz)) { + + assert(seg->flags & PF_W); + seg->remapped_writeable = true; + } + + /* + * No overlap, but we may need to align address, offset and + * size. + */ + seg->filesz += seg->vaddr - rounddown(seg->vaddr); + seg->memsz += seg->vaddr - rounddown(seg->vaddr); + seg->vaddr = rounddown(seg->vaddr); + seg->offset = rounddown(seg->offset); + seg = TAILQ_NEXT(seg, link); + } + +} + +static void populate_segments_legacy(struct ta_elf *elf) +{ + TEE_Result res = TEE_SUCCESS; + struct segment *seg = NULL; + vaddr_t va = 0; + + assert(elf->is_legacy); + TAILQ_FOREACH(seg, &elf->segs, link) { + struct segment *last_seg = TAILQ_LAST(&elf->segs, segment_head); + size_t pad_end = roundup(last_seg->vaddr + last_seg->memsz - + seg->vaddr - seg->memsz); + size_t num_bytes = roundup(seg->memsz); + + if (!elf->load_addr) + va = 0; + else + va = seg->vaddr + elf->load_addr; + + + if (!(seg->flags & PF_R)) + err(TEE_ERROR_NOT_SUPPORTED, + "Segment must be readable"); + + res = sys_map_zi(num_bytes, 0, &va, 0, pad_end); + if (res) + err(res, "sys_map_zi"); + res = sys_copy_from_ta_bin((void *)va, seg->filesz, + elf->handle, seg->offset); + if (res) + err(res, "sys_copy_from_ta_bin"); + + if (!elf->load_addr) + elf->load_addr = va; + elf->max_addr = va + num_bytes; + elf->max_offs = seg->offset + seg->filesz; + } +} + +static size_t get_pad_begin(void) +{ +#ifdef CFG_TA_ASLR + size_t min = CFG_TA_ASLR_MIN_OFFSET_PAGES; + size_t max = CFG_TA_ASLR_MAX_OFFSET_PAGES; + TEE_Result res = TEE_SUCCESS; + uint32_t rnd32 = 0; + size_t rnd = 0; + + COMPILE_TIME_ASSERT(CFG_TA_ASLR_MIN_OFFSET_PAGES < + CFG_TA_ASLR_MAX_OFFSET_PAGES); + if (max > min) { + res = sys_gen_random_num(&rnd32, sizeof(rnd32)); + if (res) { + DMSG("Random read failed: %#"PRIx32, res); + return min * SMALL_PAGE_SIZE; + } + rnd = rnd32 % (max - min); + } + + return (min + rnd) * SMALL_PAGE_SIZE; +#else /*!CFG_TA_ASLR*/ + return 0; +#endif /*!CFG_TA_ASLR*/ +} + +static void populate_segments(struct ta_elf *elf) +{ + TEE_Result res = TEE_SUCCESS; + struct segment *seg = NULL; + vaddr_t va = 0; + size_t pad_begin = 0; + + assert(!elf->is_legacy); + TAILQ_FOREACH(seg, &elf->segs, link) { + struct segment *last_seg = TAILQ_LAST(&elf->segs, segment_head); + size_t pad_end = roundup(last_seg->vaddr + last_seg->memsz - + seg->vaddr - seg->memsz); + + if (seg->remapped_writeable) { + size_t num_bytes = roundup(seg->vaddr + seg->memsz) - + rounddown(seg->vaddr); + + assert(elf->load_addr); + va = rounddown(elf->load_addr + seg->vaddr); + assert(va >= elf->max_addr); + res = sys_map_zi(num_bytes, 0, &va, 0, pad_end); + if (res) + err(res, "sys_map_zi"); + + copy_remapped_to(elf, seg); + elf->max_addr = va + num_bytes; + } else { + uint32_t flags = 0; + size_t filesz = seg->filesz; + size_t memsz = seg->memsz; + size_t offset = seg->offset; + size_t vaddr = seg->vaddr; + + if (offset < elf->max_offs) { + /* + * We're in a load segment which overlaps + * with (or is covered by) the first page + * of a shared library. + */ + if (vaddr + filesz < SMALL_PAGE_SIZE) { + size_t num_bytes = 0; + + /* + * If this segment is completely + * covered, take next. + */ + if (vaddr + memsz <= SMALL_PAGE_SIZE) + continue; + + /* + * All data of the segment is + * loaded, but we need to zero + * extend it. + */ + va = elf->max_addr; + num_bytes = roundup(vaddr + memsz) - + roundup(vaddr) - + SMALL_PAGE_SIZE; + assert(num_bytes); + res = sys_map_zi(num_bytes, 0, &va, 0, + 0); + if (res) + err(res, "sys_map_zi"); + elf->max_addr = roundup(va + num_bytes); + continue; + } + + /* Partial overlap, remove the first page. */ + vaddr += SMALL_PAGE_SIZE; + filesz -= SMALL_PAGE_SIZE; + memsz -= SMALL_PAGE_SIZE; + offset += SMALL_PAGE_SIZE; + } + + if (!elf->load_addr) { + va = 0; + pad_begin = get_pad_begin(); + /* + * If mapping with pad_begin fails we'll + * retry without pad_begin, effectively + * disabling ASLR for the current ELF file. + */ + } else { + va = vaddr + elf->load_addr; + pad_begin = 0; + } + + if (seg->flags & PF_W) + flags |= LDELF_MAP_FLAG_WRITEABLE; + else + flags |= LDELF_MAP_FLAG_SHAREABLE; + if (seg->flags & PF_X) + flags |= LDELF_MAP_FLAG_EXECUTABLE; + if (!(seg->flags & PF_R)) + err(TEE_ERROR_NOT_SUPPORTED, + "Segment must be readable"); + if (flags & LDELF_MAP_FLAG_WRITEABLE) { + res = sys_map_zi(memsz, 0, &va, pad_begin, + pad_end); + if (pad_begin && res == TEE_ERROR_OUT_OF_MEMORY) + res = sys_map_zi(memsz, 0, &va, 0, + pad_end); + if (res) + err(res, "sys_map_zi"); + res = sys_copy_from_ta_bin((void *)va, filesz, + elf->handle, offset); + if (res) + err(res, "sys_copy_from_ta_bin"); + } else { + if (filesz != memsz) + err(TEE_ERROR_BAD_FORMAT, + "Filesz and memsz mismatch"); + res = sys_map_ta_bin(&va, filesz, flags, + elf->handle, offset, + pad_begin, pad_end); + if (pad_begin && res == TEE_ERROR_OUT_OF_MEMORY) + res = sys_map_ta_bin(&va, filesz, flags, + elf->handle, + offset, 0, + pad_end); + if (res) + err(res, "sys_map_ta_bin"); + } + + if (!elf->load_addr) + elf->load_addr = va; + elf->max_addr = roundup(va + memsz); + elf->max_offs += filesz; + } + } +} + +static void ta_elf_add_bti(struct ta_elf *elf) +{ + TEE_Result res = TEE_SUCCESS; + struct segment *seg = NULL; + uint32_t flags = LDELF_MAP_FLAG_EXECUTABLE | LDELF_MAP_FLAG_BTI; + + TAILQ_FOREACH(seg, &elf->segs, link) { + vaddr_t va = elf->load_addr + seg->vaddr; + + if (seg->flags & PF_X) { + res = sys_set_prot(va, seg->memsz, flags); + if (res) + err(res, "sys_set_prot"); + } + } +} + +static void parse_property_segment(struct ta_elf *elf) +{ + char *desc = NULL; + size_t align = elf->prop_align; + size_t desc_offset = 0; + size_t prop_offset = 0; + vaddr_t va = 0; + Elf_Note *note = NULL; + char *name = NULL; + + if (!IS_ENABLED(CFG_TA_BTI) || !elf->prop_start) + return; + + check_phdr_in_range(elf, PT_GNU_PROPERTY, elf->prop_start, + elf->prop_memsz); + + va = elf->load_addr + elf->prop_start; + note = (void *)va; + name = (char *)(note + 1); + + if (elf->prop_memsz < sizeof(*note) + sizeof(ELF_NOTE_GNU)) + return; + + if (note->n_type != NT_GNU_PROPERTY_TYPE_0 || + note->n_namesz != sizeof(ELF_NOTE_GNU) || + memcmp(name, ELF_NOTE_GNU, sizeof(ELF_NOTE_GNU)) || + !IS_POWER_OF_TWO(align)) + return; + + desc_offset = ROUNDUP(sizeof(*note) + sizeof(ELF_NOTE_GNU), align); + + if (desc_offset > elf->prop_memsz || + ROUNDUP(desc_offset + note->n_descsz, align) > elf->prop_memsz) + return; + + desc = (char *)(va + desc_offset); + + do { + Elf_Prop *prop = (void *)(desc + prop_offset); + size_t data_offset = prop_offset + sizeof(*prop); + + if (note->n_descsz < data_offset) + return; + + data_offset = confine_array_index(data_offset, note->n_descsz); + + if (prop->pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { + uint32_t *pr_data = (void *)(desc + data_offset); + + if (note->n_descsz < (data_offset + sizeof(*pr_data)) && + prop->pr_datasz != sizeof(*pr_data)) + return; + + if (*pr_data & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) { + DMSG("BTI Feature present in note property"); + elf->bti_enabled = true; + } + } + + prop_offset += ROUNDUP(sizeof(*prop) + prop->pr_datasz, align); + } while (prop_offset < note->n_descsz); +} + +static void map_segments(struct ta_elf *elf) +{ + TEE_Result res = TEE_SUCCESS; + + parse_load_segments(elf); + adjust_segments(elf); + if (TAILQ_FIRST(&elf->segs)->offset < SMALL_PAGE_SIZE) { + vaddr_t va = 0; + size_t sz = elf->max_addr - elf->load_addr; + struct segment *seg = TAILQ_LAST(&elf->segs, segment_head); + size_t pad_begin = get_pad_begin(); + + /* + * We're loading a library, if not other parts of the code + * need to be updated too. + */ + assert(!elf->is_main); + + /* + * Now that we know how much virtual memory is needed move + * the already mapped part to a location which can + * accommodate us. + */ + res = sys_remap(elf->load_addr, &va, sz, pad_begin, + roundup(seg->vaddr + seg->memsz)); + if (res == TEE_ERROR_OUT_OF_MEMORY) + res = sys_remap(elf->load_addr, &va, sz, 0, + roundup(seg->vaddr + seg->memsz)); + if (res) + err(res, "sys_remap"); + elf->ehdr_addr = va; + elf->load_addr = va; + elf->max_addr = va + sz; + elf->phdr = (void *)(va + elf->e_phoff); + } +} + +static void add_deps_from_segment(struct ta_elf *elf, unsigned int type, + vaddr_t addr, size_t memsz) +{ + size_t dyn_entsize = 0; + size_t num_dyns = 0; + size_t n = 0; + unsigned int tag = 0; + size_t val = 0; + TEE_UUID uuid = { }; + char *str_tab = NULL; + size_t str_tab_sz = 0; + + if (type != PT_DYNAMIC) + return; + + check_phdr_in_range(elf, type, addr, memsz); + + if (elf->is_32bit) + dyn_entsize = sizeof(Elf32_Dyn); + else + dyn_entsize = sizeof(Elf64_Dyn); + + assert(!(memsz % dyn_entsize)); + num_dyns = memsz / dyn_entsize; + + for (n = 0; n < num_dyns && !(str_tab && str_tab_sz); n++) { + read_dyn(elf, addr, n, &tag, &val); + if (tag == DT_STRTAB) + str_tab = (char *)(val + elf->load_addr); + else if (tag == DT_STRSZ) + str_tab_sz = val; + } + check_range(elf, ".dynstr/STRTAB", str_tab, str_tab_sz); + + for (n = 0; n < num_dyns; n++) { + read_dyn(elf, addr, n, &tag, &val); + if (tag != DT_NEEDED) + continue; + if (val >= str_tab_sz) + err(TEE_ERROR_BAD_FORMAT, + "Offset into .dynstr/STRTAB out of range"); + tee_uuid_from_str(&uuid, str_tab + val); + queue_elf(&uuid); + } +} + +static void add_dependencies(struct ta_elf *elf) +{ + size_t n = 0; + + if (elf->is_32bit) { + Elf32_Phdr *phdr = elf->phdr; + + for (n = 0; n < elf->e_phnum; n++) + add_deps_from_segment(elf, phdr[n].p_type, + phdr[n].p_vaddr, phdr[n].p_memsz); + } else { + Elf64_Phdr *phdr = elf->phdr; + + for (n = 0; n < elf->e_phnum; n++) + add_deps_from_segment(elf, phdr[n].p_type, + phdr[n].p_vaddr, phdr[n].p_memsz); + } +} + +static void copy_section_headers(struct ta_elf *elf) +{ + TEE_Result res = TEE_SUCCESS; + size_t sz = 0; + size_t offs = 0; + + if (MUL_OVERFLOW(elf->e_shnum, elf->e_shentsize, &sz)) + err(TEE_ERROR_BAD_FORMAT, "Section headers size overflow"); + + elf->shdr = malloc(sz); + if (!elf->shdr) + err(TEE_ERROR_OUT_OF_MEMORY, "malloc"); + + /* + * We're assuming that section headers comes after the load segments, + * but if it's a very small dynamically linked library the section + * headers can still end up (partially?) in the first mapped page. + */ + if (elf->e_shoff < SMALL_PAGE_SIZE) { + assert(!elf->is_main); + offs = MIN(SMALL_PAGE_SIZE - elf->e_shoff, sz); + memcpy(elf->shdr, (void *)(elf->load_addr + elf->e_shoff), + offs); + } + + if (offs < sz) { + res = sys_copy_from_ta_bin((uint8_t *)elf->shdr + offs, + sz - offs, elf->handle, + elf->e_shoff + offs); + if (res) + err(res, "sys_copy_from_ta_bin"); + } +} + +static void close_handle(struct ta_elf *elf) +{ + TEE_Result res = sys_close_ta_bin(elf->handle); + + if (res) + err(res, "sys_close_ta_bin"); + elf->handle = -1; +} + +static void clean_elf_load_main(struct ta_elf *elf) +{ + TEE_Result res = TEE_SUCCESS; + + /* + * Clean up from last attempt to load + */ + res = sys_unmap(elf->ehdr_addr, SMALL_PAGE_SIZE); + if (res) + err(res, "sys_unmap"); + + while (!TAILQ_EMPTY(&elf->segs)) { + struct segment *seg = TAILQ_FIRST(&elf->segs); + vaddr_t va = 0; + size_t num_bytes = 0; + + va = rounddown(elf->load_addr + seg->vaddr); + if (seg->remapped_writeable) + num_bytes = roundup(seg->vaddr + seg->memsz) - + rounddown(seg->vaddr); + else + num_bytes = seg->memsz; + + res = sys_unmap(va, num_bytes); + if (res) + err(res, "sys_unmap"); + + TAILQ_REMOVE(&elf->segs, seg, link); + free(seg); + } + + free(elf->shdr); + memset(&elf->is_32bit, 0, + (vaddr_t)&elf->uuid - (vaddr_t)&elf->is_32bit); + + TAILQ_INIT(&elf->segs); +} + +#ifdef ARM64 +/* + * Allocates an offset in the TA's Thread Control Block for the TLS segment of + * the @elf module. + */ +#define TCB_HEAD_SIZE (2 * sizeof(long)) +static void set_tls_offset(struct ta_elf *elf) +{ + static size_t next_offs = TCB_HEAD_SIZE; + + if (!elf->tls_start) + return; + + /* Module has a TLS segment */ + elf->tls_tcb_offs = next_offs; + next_offs += elf->tls_memsz; +} +#else +static void set_tls_offset(struct ta_elf *elf __unused) {} +#endif + +static void load_main(struct ta_elf *elf) +{ + init_elf(elf); + map_segments(elf); + populate_segments(elf); + add_dependencies(elf); + copy_section_headers(elf); + save_symtab(elf); + close_handle(elf); + set_tls_offset(elf); + parse_property_segment(elf); + if (elf->bti_enabled) + ta_elf_add_bti(elf); + + elf->head = (struct ta_head *)elf->load_addr; + if (elf->head->depr_entry != UINT64_MAX) { + /* + * Legacy TAs sets their entry point in ta_head. For + * non-legacy TAs the entry point of the ELF is set instead + * and leaving the ta_head entry point set to UINT64_MAX to + * indicate that it's not used. + * + * NB, everything before the commit a73b5878c89d ("Replace + * ta_head.entry with elf entry") is considered legacy TAs + * for ldelf. + * + * Legacy TAs cannot be mapped with shared memory segments + * so restart the mapping if it turned out we're loading a + * legacy TA. + */ + + DMSG("Reloading TA %pUl as legacy TA", (void *)&elf->uuid); + clean_elf_load_main(elf); + elf->is_legacy = true; + init_elf(elf); + map_segments(elf); + populate_segments_legacy(elf); + add_dependencies(elf); + copy_section_headers(elf); + save_symtab(elf); + close_handle(elf); + elf->head = (struct ta_head *)elf->load_addr; + /* + * Check that the TA is still a legacy TA, if it isn't give + * up now since we're likely under attack. + */ + if (elf->head->depr_entry == UINT64_MAX) + err(TEE_ERROR_GENERIC, + "TA %pUl was changed on disk to non-legacy", + (void *)&elf->uuid); + } + +} + +void ta_elf_load_main(const TEE_UUID *uuid, uint32_t *is_32bit, uint64_t *sp, + uint32_t *ta_flags) +{ + struct ta_elf *elf = queue_elf(uuid); + vaddr_t va = 0; + TEE_Result res = TEE_SUCCESS; + + assert(elf); + elf->is_main = true; + + load_main(elf); + + *is_32bit = elf->is_32bit; + res = sys_map_zi(elf->head->stack_size, 0, &va, 0, 0); + if (res) + err(res, "sys_map_zi stack"); + + if (elf->head->flags & ~TA_FLAGS_MASK) + err(TEE_ERROR_BAD_FORMAT, "Invalid TA flags(s) %#"PRIx32, + elf->head->flags & ~TA_FLAGS_MASK); + + *ta_flags = elf->head->flags; + *sp = va + elf->head->stack_size; + ta_stack = va; + ta_stack_size = elf->head->stack_size; +} + +void ta_elf_finalize_load_main(uint64_t *entry, uint64_t *load_addr) +{ + struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); + TEE_Result res = TEE_SUCCESS; + + assert(elf->is_main); + + res = ta_elf_set_init_fini_info_compat(elf->is_32bit); + if (res) + err(res, "ta_elf_set_init_fini_info_compat"); + res = ta_elf_set_elf_phdr_info(elf->is_32bit); + if (res) + err(res, "ta_elf_set_elf_phdr_info"); + + if (elf->is_legacy) + *entry = elf->head->depr_entry; + else + *entry = elf->e_entry + elf->load_addr; + + *load_addr = elf->load_addr; +} + + +void ta_elf_load_dependency(struct ta_elf *elf, bool is_32bit) +{ + if (elf->is_main) + return; + + init_elf(elf); + if (elf->is_32bit != is_32bit) + err(TEE_ERROR_BAD_FORMAT, "ELF %pUl is %sbit (expected %sbit)", + (void *)&elf->uuid, elf->is_32bit ? "32" : "64", + is_32bit ? "32" : "64"); + + map_segments(elf); + populate_segments(elf); + add_dependencies(elf); + copy_section_headers(elf); + save_symtab(elf); + close_handle(elf); + set_tls_offset(elf); + parse_property_segment(elf); + if (elf->bti_enabled) + ta_elf_add_bti(elf); +} + +void ta_elf_finalize_mappings(struct ta_elf *elf) +{ + TEE_Result res = TEE_SUCCESS; + struct segment *seg = NULL; + + if (!elf->is_legacy) + return; + + TAILQ_FOREACH(seg, &elf->segs, link) { + vaddr_t va = elf->load_addr + seg->vaddr; + uint32_t flags = 0; + + if (seg->flags & PF_W) + flags |= LDELF_MAP_FLAG_WRITEABLE; + if (seg->flags & PF_X) + flags |= LDELF_MAP_FLAG_EXECUTABLE; + + res = sys_set_prot(va, seg->memsz, flags); + if (res) + err(res, "sys_set_prot"); + } +} + +static void __printf(3, 4) print_wrapper(void *pctx, print_func_t print_func, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + print_func(pctx, fmt, ap); + va_end(ap); +} + +static void print_seg(void *pctx, print_func_t print_func, + size_t idx __maybe_unused, int elf_idx __maybe_unused, + vaddr_t va __maybe_unused, paddr_t pa __maybe_unused, + size_t sz __maybe_unused, uint32_t flags) +{ + int rc __maybe_unused = 0; + int width __maybe_unused = 8; + char desc[14] __maybe_unused = ""; + char flags_str[] __maybe_unused = "----"; + + if (elf_idx > -1) { + rc = snprintf(desc, sizeof(desc), " [%d]", elf_idx); + assert(rc >= 0); + } else { + if (flags & DUMP_MAP_EPHEM) { + rc = snprintf(desc, sizeof(desc), " (param)"); + assert(rc >= 0); + } + if (flags & DUMP_MAP_LDELF) { + rc = snprintf(desc, sizeof(desc), " (ldelf)"); + assert(rc >= 0); + } + if (va == ta_stack) { + rc = snprintf(desc, sizeof(desc), " (stack)"); + assert(rc >= 0); + } + } + + if (flags & DUMP_MAP_READ) + flags_str[0] = 'r'; + if (flags & DUMP_MAP_WRITE) + flags_str[1] = 'w'; + if (flags & DUMP_MAP_EXEC) + flags_str[2] = 'x'; + if (flags & DUMP_MAP_SECURE) + flags_str[3] = 's'; + + print_wrapper(pctx, print_func, + "region %2zu: va 0x%0*"PRIxVA" pa 0x%0*"PRIxPA" size 0x%06zx flags %s%s\n", + idx, width, va, width, pa, sz, flags_str, desc); +} + +static bool get_next_in_order(struct ta_elf_queue *elf_queue, + struct ta_elf **elf, struct segment **seg, + size_t *elf_idx) +{ + struct ta_elf *e = NULL; + struct segment *s = NULL; + size_t idx = 0; + vaddr_t va = 0; + struct ta_elf *e2 = NULL; + size_t i2 = 0; + + assert(elf && seg && elf_idx); + e = *elf; + s = *seg; + assert((e == NULL && s == NULL) || (e != NULL && s != NULL)); + + if (s) { + s = TAILQ_NEXT(s, link); + if (s) { + *seg = s; + return true; + } + } + + if (e) + va = e->load_addr; + + /* Find the ELF with next load address */ + e = NULL; + TAILQ_FOREACH(e2, elf_queue, link) { + if (e2->load_addr > va) { + if (!e || e2->load_addr < e->load_addr) { + e = e2; + idx = i2; + } + } + i2++; + } + if (!e) + return false; + + *elf = e; + *seg = TAILQ_FIRST(&e->segs); + *elf_idx = idx; + return true; +} + +void ta_elf_print_mappings(void *pctx, print_func_t print_func, + struct ta_elf_queue *elf_queue, size_t num_maps, + struct dump_map *maps, vaddr_t mpool_base) +{ + struct segment *seg = NULL; + struct ta_elf *elf = NULL; + size_t elf_idx = 0; + size_t idx = 0; + size_t map_idx = 0; + + /* + * Loop over all segments and maps, printing virtual address in + * order. Segment has priority if the virtual address is present + * in both map and segment. + */ + get_next_in_order(elf_queue, &elf, &seg, &elf_idx); + while (true) { + vaddr_t va = -1; + size_t sz = 0; + uint32_t flags = DUMP_MAP_SECURE; + size_t offs = 0; + + if (seg) { + va = rounddown(seg->vaddr + elf->load_addr); + sz = roundup(seg->vaddr + seg->memsz) - + rounddown(seg->vaddr); + } + + while (map_idx < num_maps && maps[map_idx].va <= va) { + uint32_t f = 0; + + /* If there's a match, it should be the same map */ + if (maps[map_idx].va == va) { + /* + * In shared libraries the first page is + * mapped separately with the rest of that + * segment following back to back in a + * separate entry. + */ + if (map_idx + 1 < num_maps && + maps[map_idx].sz == SMALL_PAGE_SIZE) { + vaddr_t next_va = maps[map_idx].va + + maps[map_idx].sz; + size_t comb_sz = maps[map_idx].sz + + maps[map_idx + 1].sz; + + if (next_va == maps[map_idx + 1].va && + comb_sz == sz && + maps[map_idx].flags == + maps[map_idx + 1].flags) { + /* Skip this and next entry */ + map_idx += 2; + continue; + } + } + assert(maps[map_idx].sz == sz); + } else if (maps[map_idx].va < va) { + if (maps[map_idx].va == mpool_base) + f |= DUMP_MAP_LDELF; + print_seg(pctx, print_func, idx, -1, + maps[map_idx].va, maps[map_idx].pa, + maps[map_idx].sz, + maps[map_idx].flags | f); + idx++; + } + map_idx++; + } + + if (!seg) + break; + + offs = rounddown(seg->offset); + if (seg->flags & PF_R) + flags |= DUMP_MAP_READ; + if (seg->flags & PF_W) + flags |= DUMP_MAP_WRITE; + if (seg->flags & PF_X) + flags |= DUMP_MAP_EXEC; + + print_seg(pctx, print_func, idx, elf_idx, va, offs, sz, flags); + idx++; + + if (!get_next_in_order(elf_queue, &elf, &seg, &elf_idx)) + seg = NULL; + } + + elf_idx = 0; + TAILQ_FOREACH(elf, elf_queue, link) { + print_wrapper(pctx, print_func, + " [%zu] %pUl @ 0x%0*"PRIxVA"\n", + elf_idx, (void *)&elf->uuid, 8, elf->load_addr); + elf_idx++; + } +} + +#ifdef CFG_UNWIND +/* Called by libunw */ +bool find_exidx(vaddr_t addr, vaddr_t *idx_start, vaddr_t *idx_end) +{ + struct segment *seg = NULL; + struct ta_elf *elf = NULL; + vaddr_t a = 0; + + TAILQ_FOREACH(elf, &main_elf_queue, link) { + if (addr < elf->load_addr) + continue; + a = addr - elf->load_addr; + TAILQ_FOREACH(seg, &elf->segs, link) { + if (a < seg->vaddr) + continue; + if (a - seg->vaddr < seg->filesz) { + *idx_start = elf->exidx_start + elf->load_addr; + *idx_end = elf->exidx_start + elf->load_addr + + elf->exidx_size; + return true; + } + } + } + + return false; +} + +void ta_elf_stack_trace_a32(uint32_t regs[16]) +{ + struct unwind_state_arm32 state = { }; + + memcpy(state.registers, regs, sizeof(state.registers)); + print_stack_arm32(&state, ta_stack, ta_stack_size); +} + +void ta_elf_stack_trace_a64(uint64_t fp, uint64_t sp, uint64_t pc) +{ + struct unwind_state_arm64 state = { .fp = fp, .sp = sp, .pc = pc }; + + print_stack_arm64(&state, ta_stack, ta_stack_size); +} +#endif + +TEE_Result ta_elf_add_library(const TEE_UUID *uuid) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct ta_elf *ta = TAILQ_FIRST(&main_elf_queue); + struct ta_elf *lib = ta_elf_find_elf(uuid); + struct ta_elf *elf = NULL; + + if (lib) + return TEE_SUCCESS; /* Already mapped */ + + lib = queue_elf_helper(uuid); + if (!lib) + return TEE_ERROR_OUT_OF_MEMORY; + + for (elf = lib; elf; elf = TAILQ_NEXT(elf, link)) + ta_elf_load_dependency(elf, ta->is_32bit); + + for (elf = lib; elf; elf = TAILQ_NEXT(elf, link)) { + ta_elf_relocate(elf); + ta_elf_finalize_mappings(elf); + } + + for (elf = lib; elf; elf = TAILQ_NEXT(elf, link)) + DMSG("ELF (%pUl) at %#"PRIxVA, + (void *)&elf->uuid, elf->load_addr); + + res = ta_elf_set_init_fini_info_compat(ta->is_32bit); + if (res) + return res; + + return ta_elf_set_elf_phdr_info(ta->is_32bit); +} + +/* Get address/size of .init_array and .fini_array from the dynamic segment */ +static void get_init_fini_array(struct ta_elf *elf, unsigned int type, + vaddr_t addr, size_t memsz, vaddr_t *init, + size_t *init_cnt, vaddr_t *fini, + size_t *fini_cnt) +{ + size_t addrsz = 0; + size_t dyn_entsize = 0; + size_t num_dyns = 0; + size_t n = 0; + unsigned int tag = 0; + size_t val = 0; + + assert(type == PT_DYNAMIC); + + check_phdr_in_range(elf, type, addr, memsz); + + if (elf->is_32bit) { + dyn_entsize = sizeof(Elf32_Dyn); + addrsz = 4; + } else { + dyn_entsize = sizeof(Elf64_Dyn); + addrsz = 8; + } + + assert(!(memsz % dyn_entsize)); + num_dyns = memsz / dyn_entsize; + + for (n = 0; n < num_dyns; n++) { + read_dyn(elf, addr, n, &tag, &val); + if (tag == DT_INIT_ARRAY) + *init = val + elf->load_addr; + else if (tag == DT_FINI_ARRAY) + *fini = val + elf->load_addr; + else if (tag == DT_INIT_ARRAYSZ) + *init_cnt = val / addrsz; + else if (tag == DT_FINI_ARRAYSZ) + *fini_cnt = val / addrsz; + } +} + +/* Get address/size of .init_array and .fini_array in @elf (if present) */ +static void elf_get_init_fini_array(struct ta_elf *elf, vaddr_t *init, + size_t *init_cnt, vaddr_t *fini, + size_t *fini_cnt) +{ + size_t n = 0; + + if (elf->is_32bit) { + Elf32_Phdr *phdr = elf->phdr; + + for (n = 0; n < elf->e_phnum; n++) { + if (phdr[n].p_type == PT_DYNAMIC) { + get_init_fini_array(elf, phdr[n].p_type, + phdr[n].p_vaddr, + phdr[n].p_memsz, + init, init_cnt, fini, + fini_cnt); + return; + } + } + } else { + Elf64_Phdr *phdr = elf->phdr; + + for (n = 0; n < elf->e_phnum; n++) { + if (phdr[n].p_type == PT_DYNAMIC) { + get_init_fini_array(elf, phdr[n].p_type, + phdr[n].p_vaddr, + phdr[n].p_memsz, + init, init_cnt, fini, + fini_cnt); + return; + } + } + } +} + +/* + * Deprecated by __elf_phdr_info below. Kept for compatibility. + * + * Pointers to ELF initialization and finalization functions are extracted by + * ldelf and stored on the TA heap, then exported to the TA via the global + * symbol __init_fini_info. libutee in OP-TEE 3.9.0 uses this mechanism. + */ + +struct __init_fini { + uint32_t flags; + uint16_t init_size; + uint16_t fini_size; + + void (**init)(void); /* @init_size entries */ + void (**fini)(void); /* @fini_size entries */ +}; + +#define __IFS_VALID BIT(0) +#define __IFS_INIT_HAS_RUN BIT(1) +#define __IFS_FINI_HAS_RUN BIT(2) + +struct __init_fini_info { + uint32_t reserved; + uint16_t size; + uint16_t pad; + struct __init_fini *ifs; /* @size entries */ +}; + +/* 32-bit variants for a 64-bit ldelf to access a 32-bit TA */ + +struct __init_fini32 { + uint32_t flags; + uint16_t init_size; + uint16_t fini_size; + uint32_t init; + uint32_t fini; +}; + +struct __init_fini_info32 { + uint32_t reserved; + uint16_t size; + uint16_t pad; + uint32_t ifs; +}; + +static TEE_Result realloc_ifs(vaddr_t va, size_t cnt, bool is_32bit) +{ + struct __init_fini_info32 *info32 = (struct __init_fini_info32 *)va; + struct __init_fini_info *info = (struct __init_fini_info *)va; + struct __init_fini32 *ifs32 = NULL; + struct __init_fini *ifs = NULL; + size_t prev_cnt = 0; + void *ptr = NULL; + + if (is_32bit) { + ptr = (void *)(vaddr_t)info32->ifs; + ptr = realloc(ptr, cnt * sizeof(struct __init_fini32)); + if (!ptr) + return TEE_ERROR_OUT_OF_MEMORY; + ifs32 = ptr; + prev_cnt = info32->size; + if (cnt > prev_cnt) + memset(ifs32 + prev_cnt, 0, + (cnt - prev_cnt) * sizeof(*ifs32)); + info32->ifs = (uint32_t)(vaddr_t)ifs32; + info32->size = cnt; + } else { + ptr = realloc(info->ifs, cnt * sizeof(struct __init_fini)); + if (!ptr) + return TEE_ERROR_OUT_OF_MEMORY; + ifs = ptr; + prev_cnt = info->size; + if (cnt > prev_cnt) + memset(ifs + prev_cnt, 0, + (cnt - prev_cnt) * sizeof(*ifs)); + info->ifs = ifs; + info->size = cnt; + } + + return TEE_SUCCESS; +} + +static void fill_ifs(vaddr_t va, size_t idx, struct ta_elf *elf, bool is_32bit) +{ + struct __init_fini_info32 *info32 = (struct __init_fini_info32 *)va; + struct __init_fini_info *info = (struct __init_fini_info *)va; + struct __init_fini32 *ifs32 = NULL; + struct __init_fini *ifs = NULL; + size_t init_cnt = 0; + size_t fini_cnt = 0; + vaddr_t init = 0; + vaddr_t fini = 0; + + if (is_32bit) { + assert(idx < info32->size); + ifs32 = &((struct __init_fini32 *)(vaddr_t)info32->ifs)[idx]; + + if (ifs32->flags & __IFS_VALID) + return; + + elf_get_init_fini_array(elf, &init, &init_cnt, &fini, + &fini_cnt); + + ifs32->init = (uint32_t)init; + ifs32->init_size = init_cnt; + + ifs32->fini = (uint32_t)fini; + ifs32->fini_size = fini_cnt; + + ifs32->flags |= __IFS_VALID; + } else { + assert(idx < info->size); + ifs = &info->ifs[idx]; + + if (ifs->flags & __IFS_VALID) + return; + + elf_get_init_fini_array(elf, &init, &init_cnt, &fini, + &fini_cnt); + + ifs->init = (void (**)(void))init; + ifs->init_size = init_cnt; + + ifs->fini = (void (**)(void))fini; + ifs->fini_size = fini_cnt; + + ifs->flags |= __IFS_VALID; + } +} + +/* + * Set or update __init_fini_info in the TA with information from the ELF + * queue + */ +TEE_Result ta_elf_set_init_fini_info_compat(bool is_32bit) +{ + struct __init_fini_info *info = NULL; + TEE_Result res = TEE_SUCCESS; + struct ta_elf *elf = NULL; + vaddr_t info_va = 0; + size_t cnt = 0; + + res = ta_elf_resolve_sym("__init_fini_info", &info_va, NULL, NULL); + if (res) { + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + /* + * Not an error, only TAs linked against libutee from + * OP-TEE 3.9.0 have this symbol. + */ + return TEE_SUCCESS; + } + return res; + } + assert(info_va); + + info = (struct __init_fini_info *)info_va; + if (info->reserved) + return TEE_ERROR_NOT_SUPPORTED; + + TAILQ_FOREACH(elf, &main_elf_queue, link) + cnt++; + + /* Queue has at least one file (main) */ + assert(cnt); + + res = realloc_ifs(info_va, cnt, is_32bit); + if (res) + goto err; + + cnt = 0; + TAILQ_FOREACH(elf, &main_elf_queue, link) { + fill_ifs(info_va, cnt, elf, is_32bit); + cnt++; + } + + return TEE_SUCCESS; +err: + free(info); + return res; +} + +static TEE_Result realloc_elf_phdr_info(vaddr_t va, size_t cnt, bool is_32bit) +{ + struct __elf_phdr_info32 *info32 = (struct __elf_phdr_info32 *)va; + struct __elf_phdr_info *info = (struct __elf_phdr_info *)va; + struct dl_phdr_info32 *dlpi32 = NULL; + struct dl_phdr_info *dlpi = NULL; + size_t prev_cnt = 0; + void *ptr = NULL; + + if (is_32bit) { + ptr = (void *)(vaddr_t)info32->dlpi; + ptr = realloc(ptr, cnt * sizeof(*dlpi32)); + if (!ptr) + return TEE_ERROR_OUT_OF_MEMORY; + dlpi32 = ptr; + prev_cnt = info32->count; + if (cnt > prev_cnt) + memset(dlpi32 + prev_cnt, 0, + (cnt - prev_cnt) * sizeof(*dlpi32)); + info32->dlpi = (uint32_t)(vaddr_t)dlpi32; + info32->count = cnt; + } else { + ptr = realloc(info->dlpi, cnt * sizeof(*dlpi)); + if (!ptr) + return TEE_ERROR_OUT_OF_MEMORY; + dlpi = ptr; + prev_cnt = info->count; + if (cnt > prev_cnt) + memset(dlpi + prev_cnt, 0, + (cnt - prev_cnt) * sizeof(*dlpi)); + info->dlpi = dlpi; + info->count = cnt; + } + + return TEE_SUCCESS; +} + +static void fill_elf_phdr_info(vaddr_t va, size_t idx, struct ta_elf *elf, + bool is_32bit) +{ + struct __elf_phdr_info32 *info32 = (struct __elf_phdr_info32 *)va; + struct __elf_phdr_info *info = (struct __elf_phdr_info *)va; + struct dl_phdr_info32 *dlpi32 = NULL; + struct dl_phdr_info *dlpi = NULL; + + if (is_32bit) { + assert(idx < info32->count); + dlpi32 = (struct dl_phdr_info32 *)(vaddr_t)info32->dlpi + idx; + + dlpi32->dlpi_addr = elf->load_addr; + if (elf->soname) + dlpi32->dlpi_name = (vaddr_t)elf->soname; + else + dlpi32->dlpi_name = (vaddr_t)&info32->zero; + dlpi32->dlpi_phdr = (vaddr_t)elf->phdr; + dlpi32->dlpi_phnum = elf->e_phnum; + dlpi32->dlpi_adds = 1; /* No unloading on dlclose() currently */ + dlpi32->dlpi_subs = 0; /* No unloading on dlclose() currently */ + dlpi32->dlpi_tls_modid = elf->tls_mod_id; + dlpi32->dlpi_tls_data = elf->tls_start; + } else { + assert(idx < info->count); + dlpi = info->dlpi + idx; + + dlpi->dlpi_addr = elf->load_addr; + if (elf->soname) + dlpi->dlpi_name = elf->soname; + else + dlpi->dlpi_name = &info32->zero; + dlpi->dlpi_phdr = elf->phdr; + dlpi->dlpi_phnum = elf->e_phnum; + dlpi->dlpi_adds = 1; /* No unloading on dlclose() currently */ + dlpi->dlpi_subs = 0; /* No unloading on dlclose() currently */ + dlpi->dlpi_tls_modid = elf->tls_mod_id; + dlpi->dlpi_tls_data = (void *)elf->tls_start; + } +} + +/* Set or update __elf_hdr_info in the TA with information from the ELF queue */ +TEE_Result ta_elf_set_elf_phdr_info(bool is_32bit) +{ + struct __elf_phdr_info *info = NULL; + TEE_Result res = TEE_SUCCESS; + struct ta_elf *elf = NULL; + vaddr_t info_va = 0; + size_t cnt = 0; + + res = ta_elf_resolve_sym("__elf_phdr_info", &info_va, NULL, NULL); + if (res) { + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + /* Older TA */ + return TEE_SUCCESS; + } + return res; + } + assert(info_va); + + info = (struct __elf_phdr_info *)info_va; + if (info->reserved) + return TEE_ERROR_NOT_SUPPORTED; + + TAILQ_FOREACH(elf, &main_elf_queue, link) + cnt++; + + res = realloc_elf_phdr_info(info_va, cnt, is_32bit); + if (res) + return res; + + cnt = 0; + TAILQ_FOREACH(elf, &main_elf_queue, link) { + fill_elf_phdr_info(info_va, cnt, elf, is_32bit); + cnt++; + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/ldelf/ta_elf.h b/optee/optee_os/ldelf/ta_elf.h new file mode 100644 index 0000000..079026b --- /dev/null +++ b/optee/optee_os/ldelf/ta_elf.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2022-2023, Arm Limited + */ + +#ifndef TA_ELF_H +#define TA_ELF_H + +#include +#include +#include +#include +#include + +struct segment { + size_t offset; + size_t vaddr; + size_t filesz; + size_t memsz; + size_t flags; + size_t align; + bool remapped_writeable; + TAILQ_ENTRY(segment) link; +}; + +TAILQ_HEAD(segment_head, segment); + +struct ta_elf { + bool is_main; + bool is_32bit; /* Initialized from Elf32_Ehdr/Elf64_Ehdr */ + bool is_legacy; + bool bti_enabled; + + vaddr_t load_addr; + vaddr_t max_addr; + vaddr_t max_offs; + + vaddr_t ehdr_addr; + + /* Initialized from Elf32_Ehdr/Elf64_Ehdr */ + vaddr_t e_entry; + vaddr_t e_phoff; + vaddr_t e_shoff; + unsigned int e_phnum; + unsigned int e_shnum; + unsigned int e_phentsize; + unsigned int e_shentsize; + + void *phdr; + void *shdr; + /* + * dynsymtab and dynstr are used for external symbols, they may hold + * other symbols too. + */ + void *dynsymtab; + size_t num_dynsyms; + const char *dynstr; + size_t dynstr_size; + + /* DT_HASH hash table for faster resolution of external symbols */ + void *hashtab; + /* DT_GNU_HASH table as an alternative to DT_HASH */ + void *gnu_hashtab; + size_t gnu_hashtab_size; + + /* DT_SONAME */ + char *soname; + + struct segment_head segs; + + vaddr_t exidx_start; + size_t exidx_size; + + /* Thread Local Storage */ + + size_t tls_mod_id; + /* PT_TLS segment */ + vaddr_t tls_start; + size_t tls_filesz; /* Covers the .tdata section */ + size_t tls_memsz; /* Covers the .tdata and .tbss sections */ +#ifdef ARM64 + /* Offset of the copy of the TLS block in the TLS area of the TCB */ + size_t tls_tcb_offs; +#endif + + /* PT_GNU_PROPERTY segment */ + vaddr_t prop_start; + size_t prop_align; + size_t prop_memsz; + + uint32_t handle; + + struct ta_head *head; + + TEE_UUID uuid; + TAILQ_ENTRY(ta_elf) link; +}; + +TAILQ_HEAD(ta_elf_queue, ta_elf); + +/* Format of the DT_GNU_HASH entry in the ELF dynamic section */ +struct gnu_hashtab { + uint32_t nbuckets; + uint32_t symoffset; + uint32_t bloom_size; + uint32_t bloom_shift; + /* + * Followed by: + * + * uint{32,64}_t bloom[bloom_size]; + * uint32_t buckets[nbuckets]; + * uint32_t chain[]; + */ +}; + +typedef void (*print_func_t)(void *pctx, const char *fmt, va_list ap) + __printf(2, 0); + +extern struct ta_elf_queue main_elf_queue; +struct ta_elf *ta_elf_find_elf(const TEE_UUID *uuid); + +void ta_elf_load_main(const TEE_UUID *uuid, uint32_t *is_32bit, uint64_t *sp, + uint32_t *ta_flags); +void ta_elf_finalize_load_main(uint64_t *entry, uint64_t *load_addr); +void ta_elf_load_dependency(struct ta_elf *elf, bool is_32bit); +void ta_elf_relocate(struct ta_elf *elf); +void ta_elf_finalize_mappings(struct ta_elf *elf); + +void ta_elf_print_mappings(void *pctx, print_func_t print_func, + struct ta_elf_queue *elf_queue, size_t num_maps, + struct dump_map *maps, vaddr_t mpool_base); + +#ifdef CFG_UNWIND +void ta_elf_stack_trace_a32(uint32_t regs[16]); +void ta_elf_stack_trace_a64(uint64_t fp, uint64_t sp, uint64_t pc); +#else +static inline void ta_elf_stack_trace_a32(uint32_t regs[16] __unused) { } +static inline void ta_elf_stack_trace_a64(uint64_t fp __unused, + uint64_t sp __unused, + uint64_t pc __unused) { } +#endif /*CFG_UNWIND*/ + +TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val, + struct ta_elf **found_elf, struct ta_elf *elf); +TEE_Result ta_elf_add_library(const TEE_UUID *uuid); +TEE_Result ta_elf_set_init_fini_info_compat(bool is_32bit); +TEE_Result ta_elf_set_elf_phdr_info(bool is_32bit); + +#endif /*TA_ELF_H*/ diff --git a/optee/optee_os/ldelf/ta_elf_rel.c b/optee/optee_os/ldelf/ta_elf_rel.c new file mode 100644 index 0000000..5d5b1eb --- /dev/null +++ b/optee/optee_os/ldelf/ta_elf_rel.c @@ -0,0 +1,752 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys.h" +#include "ta_elf.h" + +static uint32_t elf_hash(const char *name) +{ + const unsigned char *p = (const unsigned char *)name; + uint32_t h = 0; + uint32_t g = 0; + + while (*p) { + h = (h << 4) + *p++; + g = h & 0xf0000000; + if (g) + h ^= g >> 24; + h &= ~g; + } + return h; +} + +static uint32_t gnu_hash(const char *name) +{ + const unsigned char *p = (const unsigned char *)name; + uint32_t h = 5381; + + while (*p) + h = (h << 5) + h + *p++; + + return h; +} + +static bool sym_compare(struct ta_elf *elf, unsigned int st_bind, + unsigned int st_type, size_t st_shndx, + size_t st_name, size_t st_value, const char *name, + vaddr_t *val, bool weak_ok) +{ + bool bind_ok = false; + + if (!st_name) + return false; + if (st_name > elf->dynstr_size) + err(TEE_ERROR_BAD_FORMAT, "Symbol name out of range"); + if (strcmp(name, elf->dynstr + st_name)) + return false; + if (st_bind == STB_GLOBAL || (weak_ok && st_bind == STB_WEAK)) + bind_ok = true; + if (!bind_ok) + return false; + if (st_bind == STB_WEAK && st_shndx == SHN_UNDEF) { + if (val) + *val = 0; + return true; + } + if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX) + return false; + + switch (st_type) { + case STT_NOTYPE: + case STT_OBJECT: + case STT_FUNC: + if (st_value > (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, + "Symbol location out of range"); + if (val) + *val = st_value + elf->load_addr; + break; + case STT_TLS: + if (val) + *val = st_value; + break; + default: + err(TEE_ERROR_NOT_SUPPORTED, "Symbol type not supported"); + } + + return true; +} + +static bool check_found_sym(struct ta_elf *elf, const char *name, vaddr_t *val, + bool weak_ok, size_t n) +{ + Elf32_Sym *sym32 = NULL; + Elf64_Sym *sym64 = NULL; + unsigned int st_bind = 0; + unsigned int st_type = 0; + size_t st_shndx = 0; + size_t st_name = 0; + size_t st_value = 0; + + if (n >= elf->num_dynsyms) + err(TEE_ERROR_BAD_FORMAT, "Index out of range"); + + /* + * We're loading values from sym[] which later + * will be used to load something. + * => Spectre V1 pattern, need to cap the index + * against speculation. + */ + n = confine_array_index(n, elf->num_dynsyms); + + if (elf->is_32bit) { + sym32 = elf->dynsymtab; + st_bind = ELF32_ST_BIND(sym32[n].st_info); + st_type = ELF32_ST_TYPE(sym32[n].st_info); + st_shndx = sym32[n].st_shndx; + st_name = sym32[n].st_name; + st_value = sym32[n].st_value; + } else { + sym64 = elf->dynsymtab; + st_bind = ELF64_ST_BIND(sym64[n].st_info); + st_type = ELF64_ST_TYPE(sym64[n].st_info); + st_shndx = sym64[n].st_shndx; + st_name = sym64[n].st_name; + st_value = sym64[n].st_value; + } + + return sym_compare(elf, st_bind, st_type, st_shndx, st_name, st_value, + name, val, weak_ok); +} + +static TEE_Result resolve_sym_helper(const char *name, vaddr_t *val, + struct ta_elf *elf, bool weak_ok) +{ + uint32_t n = 0; + uint32_t hash = 0; + + if (elf->gnu_hashtab) { + struct gnu_hashtab *h = elf->gnu_hashtab; + uint32_t *end = (void *)((uint8_t *)elf->gnu_hashtab + + elf->gnu_hashtab_size); + uint32_t *bucket = NULL; + uint32_t *chain = NULL; + uint32_t hashval = 0; + + hash = gnu_hash(name); + + if (elf->is_32bit) { + uint32_t *bloom = (void *)(h + 1); + uint32_t word = bloom[(hash / 32) % h->bloom_size]; + uint32_t mask = BIT32(hash % 32) | + BIT32((hash >> h->bloom_shift) % 32); + + if ((word & mask) != mask) + return TEE_ERROR_ITEM_NOT_FOUND; + bucket = bloom + h->bloom_size; + } else { + uint64_t *bloom = (void *)(h + 1); + uint64_t word = bloom[(hash / 64) % h->bloom_size]; + uint64_t mask = BIT64(hash % 64) | + BIT64((hash >> h->bloom_shift) % 64); + + if ((word & mask) != mask) + return TEE_ERROR_ITEM_NOT_FOUND; + bucket = (uint32_t *)(bloom + h->bloom_size); + } + chain = bucket + h->nbuckets; + + n = bucket[hash % h->nbuckets]; + if (n < h->symoffset) + return TEE_ERROR_ITEM_NOT_FOUND; + + hash |= 1; + do { + size_t idx = n - h->symoffset; + + if (chain + idx > end) + return TEE_ERROR_ITEM_NOT_FOUND; + + hashval = chain[idx]; + + if ((hashval | 1) == hash && + check_found_sym(elf, name, val, weak_ok, n)) + return TEE_SUCCESS; + + n++; + } while (!(hashval & 1)); + } else if (elf->hashtab) { + /* + * Using uint32_t here for convenience because both Elf64_Word + * and Elf32_Word are 32-bit types + */ + uint32_t *hashtab = elf->hashtab; + uint32_t nbuckets = hashtab[0]; + uint32_t nchains = hashtab[1]; + uint32_t *bucket = &hashtab[2]; + uint32_t *chain = &bucket[nbuckets]; + + hash = elf_hash(name); + + for (n = bucket[hash % nbuckets]; n; n = chain[n]) { + if (n >= nchains) + err(TEE_ERROR_BAD_FORMAT, "Index out of range"); + if (check_found_sym(elf, name, val, weak_ok, n)) + return TEE_SUCCESS; + } + } + + return TEE_ERROR_ITEM_NOT_FOUND; +} + +/* + * Look for named symbol in @elf, or all modules if @elf == NULL. Global symbols + * are searched first, then weak ones. Last option, when at least one weak but + * undefined symbol exists, resolve to zero. Otherwise return + * TEE_ERROR_ITEM_NOT_FOUND. + * @val (if != 0) receives the symbol value + * @found_elf (if != 0) receives the module where the symbol is found + */ +TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val, + struct ta_elf **found_elf, + struct ta_elf *elf) +{ + if (elf) { + /* Search global symbols */ + if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */)) + goto success; + /* Search weak symbols */ + if (!resolve_sym_helper(name, val, elf, true /* weak_ok */)) + goto success; + } + + TAILQ_FOREACH(elf, &main_elf_queue, link) { + if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */)) + goto success; + if (!resolve_sym_helper(name, val, elf, true /* weak_ok */)) + goto success; + } + + return TEE_ERROR_ITEM_NOT_FOUND; + +success: + if (found_elf) + *found_elf = elf; + return TEE_SUCCESS; +} + +static void e32_get_sym_name(const Elf32_Sym *sym_tab, size_t num_syms, + const char *str_tab, size_t str_tab_size, + Elf32_Rel *rel, const char **name, + bool *weak_undef) +{ + size_t sym_idx = 0; + size_t name_idx = 0; + + sym_idx = ELF32_R_SYM(rel->r_info); + if (sym_idx >= num_syms) + err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); + sym_idx = confine_array_index(sym_idx, num_syms); + + name_idx = sym_tab[sym_idx].st_name; + if (name_idx >= str_tab_size) + err(TEE_ERROR_BAD_FORMAT, "Name index out of range"); + *name = str_tab + name_idx; + + if (!weak_undef) + return; + if (sym_tab[sym_idx].st_shndx == SHN_UNDEF && + ELF32_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK) + *weak_undef = true; + else + *weak_undef = false; +} + +static void resolve_sym(const char *name, vaddr_t *val, struct ta_elf **mod, + bool err_if_not_found) +{ + TEE_Result res = ta_elf_resolve_sym(name, val, mod, NULL); + + if (res) { + if (err_if_not_found) + err(res, "Symbol %s not found", name); + else + *val = 0; + } +} + +static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms, + const char *str_tab, size_t str_tab_size, + Elf32_Rel *rel, Elf32_Addr *where) +{ + const char *name = NULL; + vaddr_t val = 0; + bool weak_undef = false; + + e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name, + &weak_undef); + resolve_sym(name, &val, NULL, !weak_undef); + *where = val; +} + +static void e32_tls_get_module(const Elf32_Sym *sym_tab, size_t num_syms, + const char *str_tab, size_t str_tab_size, + Elf32_Rel *rel, struct ta_elf **mod) +{ + const char *name = NULL; + size_t sym_idx = 0; + + sym_idx = ELF32_R_SYM(rel->r_info); + if (sym_idx >= num_syms) + err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); + sym_idx = confine_array_index(sym_idx, num_syms); + if (!sym_idx || sym_tab[sym_idx].st_shndx != SHN_UNDEF) { + /* No symbol, or symbol is defined in current module */ + return; + } + + e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name, + NULL); + resolve_sym(name, NULL, mod, false); +} + +static void e32_tls_resolve(const Elf32_Sym *sym_tab, size_t num_syms, + const char *str_tab, size_t str_tab_size, + Elf32_Rel *rel, vaddr_t *val) +{ + const char *name = NULL; + + e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name, + NULL); + resolve_sym(name, val, NULL, false); +} + +static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx) +{ + Elf32_Shdr *shdr = elf->shdr; + Elf32_Rel *rel = NULL; + Elf32_Rel *rel_end = NULL; + size_t sym_tab_idx = 0; + Elf32_Sym *sym_tab = NULL; + size_t num_syms = 0; + size_t sh_end = 0; + const char *str_tab = NULL; + size_t str_tab_size = 0; + + assert(shdr[rel_sidx].sh_type == SHT_REL); + + assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel)); + + sym_tab_idx = shdr[rel_sidx].sh_link; + if (sym_tab_idx) { + size_t str_tab_idx = 0; + + if (sym_tab_idx >= elf->e_shnum) + err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range"); + sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum); + + assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym)); + + /* Check the address is inside ELF memory */ + if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, + shdr[sym_tab_idx].sh_size, &sh_end)) + err(TEE_ERROR_BAD_FORMAT, "Overflow"); + if (sh_end >= (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range"); + + sym_tab = (Elf32_Sym *)(elf->load_addr + + shdr[sym_tab_idx].sh_addr); + + num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym); + + str_tab_idx = shdr[sym_tab_idx].sh_link; + if (str_tab_idx) { + if (str_tab_idx >= elf->e_shnum) + err(TEE_ERROR_BAD_FORMAT, + "STRTAB index out of range"); + str_tab_idx = confine_array_index(str_tab_idx, + elf->e_shnum); + + /* Check the address is inside ELF memory */ + if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, + shdr[str_tab_idx].sh_size, &sh_end)) + err(TEE_ERROR_BAD_FORMAT, "Overflow"); + if (sh_end >= (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, + "STRTAB out of range"); + + str_tab = (const char *)(elf->load_addr + + shdr[str_tab_idx].sh_addr); + str_tab_size = shdr[str_tab_idx].sh_size; + } + } + + /* Check the address is inside TA memory */ + if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, + shdr[rel_sidx].sh_size, &sh_end)) + err(TEE_ERROR_BAD_FORMAT, "Overflow"); + if (sh_end >= (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range"); + rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr); + + rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel); + for (; rel < rel_end; rel++) { + struct ta_elf *mod = NULL; + Elf32_Addr *where = NULL; + size_t sym_idx = 0; + vaddr_t val = 0; + + /* Check the address is inside TA memory */ + if (rel->r_offset >= (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, + "Relocation offset out of range"); + where = (Elf32_Addr *)(elf->load_addr + rel->r_offset); + + switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_NONE: + /* + * One would expect linker prevents such useless entry + * in the relocation table. We still handle this type + * here in case such entries exist. + */ + break; + case R_ARM_ABS32: + sym_idx = ELF32_R_SYM(rel->r_info); + if (sym_idx >= num_syms) + err(TEE_ERROR_BAD_FORMAT, + "Symbol index out of range"); + if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { + /* Symbol is external */ + e32_process_dyn_rel(sym_tab, num_syms, str_tab, + str_tab_size, rel, where); + } else { + *where += elf->load_addr + + sym_tab[sym_idx].st_value; + } + break; + case R_ARM_REL32: + sym_idx = ELF32_R_SYM(rel->r_info); + if (sym_idx >= num_syms) + err(TEE_ERROR_BAD_FORMAT, + "Symbol index out of range"); + *where += sym_tab[sym_idx].st_value - rel->r_offset; + break; + case R_ARM_RELATIVE: + *where += elf->load_addr; + break; + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + if (!sym_tab) + err(TEE_ERROR_BAD_FORMAT, + "Missing symbol table"); + e32_process_dyn_rel(sym_tab, num_syms, str_tab, + str_tab_size, rel, where); + break; + case R_ARM_TLS_DTPMOD32: + if (!sym_tab) + err(TEE_ERROR_BAD_FORMAT, + "Missing symbol table"); + mod = elf; + e32_tls_get_module(sym_tab, num_syms, str_tab, + str_tab_size, rel, &mod); + *where = mod->tls_mod_id; + break; + case R_ARM_TLS_DTPOFF32: + if (!sym_tab) + err(TEE_ERROR_BAD_FORMAT, + "Missing symbol table"); + e32_tls_resolve(sym_tab, num_syms, str_tab, + str_tab_size, rel, &val); + *where = val; + break; + default: + err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d", + ELF32_R_TYPE(rel->r_info)); + } + } +} + +#if defined(ARM64) || defined(RV64) +static void e64_get_sym_name(const Elf64_Sym *sym_tab, size_t num_syms, + const char *str_tab, size_t str_tab_size, + Elf64_Rela *rela, const char **name, + bool *weak_undef) +{ + size_t sym_idx = 0; + size_t name_idx = 0; + + sym_idx = ELF64_R_SYM(rela->r_info); + if (sym_idx >= num_syms) + err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); + sym_idx = confine_array_index(sym_idx, num_syms); + + name_idx = sym_tab[sym_idx].st_name; + if (name_idx >= str_tab_size) + err(TEE_ERROR_BAD_FORMAT, "Name index out of range"); + *name = str_tab + name_idx; + + if (sym_tab[sym_idx].st_shndx == SHN_UNDEF && + ELF64_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK) + *weak_undef = true; + else + *weak_undef = false; +} + +static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms, + const char *str_tab, size_t str_tab_size, + Elf64_Rela *rela, Elf64_Addr *where) +{ + const char *name = NULL; + uintptr_t val = 0; + bool weak_undef = false; + + e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela, &name, + &weak_undef); + resolve_sym(name, &val, NULL, !weak_undef); + *where = val; +} + +#ifdef ARM64 +static void e64_process_tls_tprel_rela(const Elf64_Sym *sym_tab, + size_t num_syms, const char *str_tab, + size_t str_tab_size, Elf64_Rela *rela, + Elf64_Addr *where, struct ta_elf *elf) +{ + struct ta_elf *mod = NULL; + bool weak_undef = false; + const char *name = NULL; + size_t sym_idx = 0; + vaddr_t symval = 0; + + sym_idx = ELF64_R_SYM(rela->r_info); + if (sym_idx) { + e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela, + &name, &weak_undef); + resolve_sym(name, &symval, &mod, !weak_undef); + } else { + mod = elf; + } + *where = symval + mod->tls_tcb_offs + rela->r_addend; +} + +struct tlsdesc { + long (*resolver)(struct tlsdesc *td); + long value; +}; + +/* Helper function written in assembly due to the calling convention */ +long tlsdesc_resolve(struct tlsdesc *td); + +static void e64_process_tlsdesc_rela(const Elf64_Sym *sym_tab, size_t num_syms, + const char *str_tab, size_t str_tab_size, + Elf64_Rela *rela, Elf64_Addr *where, + struct ta_elf *elf) +{ + /* + * @where points to a pair of 64-bit words in the GOT or PLT which is + * mapped to a struct tlsdesc: + * + * - resolver() must return the offset of the thread-local variable + * relative to TPIDR_EL0. + * - value is implementation-dependent. The TLS_TPREL handling code is + * re-used to get the desired offset so that tlsdesc_resolve() just + * needs to return this value. + * + * Both the TA and ldelf are AArch64 so it is OK to point to a function + * in ldelf. + */ + *where = (Elf64_Addr)tlsdesc_resolve; + e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, str_tab_size, + rela, where + 1, elf); +} +#endif /*ARM64*/ + +static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx) +{ + Elf64_Shdr *shdr = elf->shdr; + Elf64_Rela *rela = NULL; + Elf64_Rela *rela_end = NULL; + size_t sym_tab_idx = 0; + Elf64_Sym *sym_tab = NULL; + size_t num_syms = 0; + size_t sh_end = 0; + const char *str_tab = NULL; + size_t str_tab_size = 0; + + assert(shdr[rel_sidx].sh_type == SHT_RELA); + + assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela)); + + sym_tab_idx = shdr[rel_sidx].sh_link; + if (sym_tab_idx) { + size_t str_tab_idx = 0; + + if (sym_tab_idx >= elf->e_shnum) + err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range"); + sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum); + + assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym)); + + /* Check the address is inside TA memory */ + if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, + shdr[sym_tab_idx].sh_size, &sh_end)) + err(TEE_ERROR_BAD_FORMAT, "Overflow"); + if (sh_end >= (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range"); + + sym_tab = (Elf64_Sym *)(elf->load_addr + + shdr[sym_tab_idx].sh_addr); + + num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym); + + str_tab_idx = shdr[sym_tab_idx].sh_link; + if (str_tab_idx) { + if (str_tab_idx >= elf->e_shnum) + err(TEE_ERROR_BAD_FORMAT, + "STRTAB index out of range"); + str_tab_idx = confine_array_index(str_tab_idx, + elf->e_shnum); + + /* Check the address is inside ELF memory */ + if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, + shdr[str_tab_idx].sh_size, &sh_end)) + err(TEE_ERROR_BAD_FORMAT, "Overflow"); + if (sh_end >= (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, + "STRTAB out of range"); + + str_tab = (const char *)(elf->load_addr + + shdr[str_tab_idx].sh_addr); + str_tab_size = shdr[str_tab_idx].sh_size; + } + } + + /* Check the address is inside TA memory */ + if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, + shdr[rel_sidx].sh_size, &sh_end)) + err(TEE_ERROR_BAD_FORMAT, "Overflow"); + if (sh_end >= (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range"); + rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr); + + rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela); + for (; rela < rela_end; rela++) { + Elf64_Addr *where = NULL; + size_t sym_idx = 0; + + /* Check the address is inside TA memory */ + if (rela->r_offset >= (elf->max_addr - elf->load_addr)) + err(TEE_ERROR_BAD_FORMAT, + "Relocation offset out of range"); + + where = (Elf64_Addr *)(elf->load_addr + rela->r_offset); + + switch (ELF64_R_TYPE(rela->r_info)) { +#ifdef ARM64 + case R_AARCH64_NONE: + /* + * One would expect linker prevents such useless entry + * in the relocation table. We still handle this type + * here in case such entries exist. + */ + break; + case R_AARCH64_ABS64: + sym_idx = ELF64_R_SYM(rela->r_info); + if (sym_idx >= num_syms) + err(TEE_ERROR_BAD_FORMAT, + "Symbol index out of range"); + sym_idx = confine_array_index(sym_idx, num_syms); + if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { + /* Symbol is external */ + e64_process_dyn_rela(sym_tab, num_syms, str_tab, + str_tab_size, rela, where); + } else { + *where = rela->r_addend + elf->load_addr + + sym_tab[sym_idx].st_value; + } + break; + case R_AARCH64_RELATIVE: + *where = rela->r_addend + elf->load_addr; + break; + case R_AARCH64_GLOB_DAT: + case R_AARCH64_JUMP_SLOT: + e64_process_dyn_rela(sym_tab, num_syms, str_tab, + str_tab_size, rela, where); + break; + case R_AARCH64_TLS_TPREL: + e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, + str_tab_size, rela, where, + elf); + break; + case R_AARCH64_TLSDESC: + e64_process_tlsdesc_rela(sym_tab, num_syms, str_tab, + str_tab_size, rela, where, + elf); + break; +#endif /*ARM64*/ +#ifdef RV64 + case R_RISCV_NONE: + /* + * One would expect linker prevents such useless entry + * in the relocation table. We still handle this type + * here in case such entries exist. + */ + break; + case R_RISCV_RELATIVE: + *where = rela->r_addend + elf->load_addr; + break; + case R_RISCV_64: + e64_process_dyn_rela(sym_tab, num_syms, str_tab, + str_tab_size, rela, where); + *where += rela->r_addend; + break; + case R_RISCV_JUMP_SLOT: + e64_process_dyn_rela(sym_tab, num_syms, str_tab, + str_tab_size, rela, where); + break; +#endif /*RV64*/ + default: + err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd", + ELF64_R_TYPE(rela->r_info)); + } + } +} +#else /*ARM64 || RV64*/ +static void __noreturn e64_relocate(struct ta_elf *elf __unused, + unsigned int rel_sidx __unused) +{ + err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported"); +} +#endif /*ARM64 || RV64*/ + +void ta_elf_relocate(struct ta_elf *elf) +{ + size_t n = 0; + + if (elf->is_32bit) { + Elf32_Shdr *shdr = elf->shdr; + + for (n = 0; n < elf->e_shnum; n++) + if (shdr[n].sh_type == SHT_REL) + e32_relocate(elf, n); + } else { + Elf64_Shdr *shdr = elf->shdr; + + for (n = 0; n < elf->e_shnum; n++) + if (shdr[n].sh_type == SHT_RELA) + e64_relocate(elf, n); + + } +} diff --git a/optee/optee_os/ldelf/tlsdesc_rel_a64.S b/optee/optee_os/ldelf/tlsdesc_rel_a64.S new file mode 100644 index 0000000..b187505 --- /dev/null +++ b/optee/optee_os/ldelf/tlsdesc_rel_a64.S @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Huawei Technologies Co. Ltd. + */ + +#include + +/* + * long tlsdesc_resolve(struct tlsdesc *); + * + * Must preserve all registers except x0, x1 and the processor flags. + * See https://www.fsfla.org/~lxoliva/writeups/TLS/RFC-TLSDESC-ARM.txt section + * "Resolvers' Calling Convention". The document applies to 32-bit Arm but other + * sources mention similar constraints for other architectures. + */ +FUNC tlsdesc_resolve , : + ldr x0, [x0, #8] + ret +END_FUNC tlsdesc_resolve + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/lib/libdl/dlfcn.c b/optee/optee_os/lib/libdl/dlfcn.c new file mode 100644 index 0000000..338c176 --- /dev/null +++ b/optee/optee_os/lib/libdl/dlfcn.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019 Linaro limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_TASessionHandle sess = TEE_HANDLE_NULL; +static size_t hcount; + +static TEE_Result invoke_system_pta(uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const TEE_UUID core_uuid = PTA_SYSTEM_UUID; + TEE_Result res = TEE_ERROR_GENERIC; + + if (sess == TEE_HANDLE_NULL) { + res = TEE_OpenTASession(&core_uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &sess, NULL); + if (res) + return res; + } + return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + cmd_id, param_types, params, NULL); +} + +struct dl_handle { + TEE_UUID uuid; +}; + +void *dlopen(const char *filename, int flags) +{ + TEE_Param params[TEE_NUM_PARAMS] = { }; + struct dl_handle *h = NULL; + uint32_t param_types = 0; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_UUID uuid = { }; + + h = malloc(sizeof(*h)); + if (!h) + return NULL; + + if (filename) { + res = tee_uuid_from_str(&uuid, filename); + if (res) + goto err; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + params[0].memref.buffer = (void *)&uuid; + params[0].memref.size = sizeof(uuid); + params[1].value.a = flags; + + res = invoke_system_pta(PTA_SYSTEM_DLOPEN, param_types, params); + if (res) + goto err; + + __utee_tcb_init(); + __utee_call_elf_init_fn(); + } + + hcount++; + h->uuid = uuid; + return (void *)h; +err: + free(h); + return NULL; +} + +int dlclose(void *handle) +{ + free(handle); + hcount--; + if (!hcount && sess != TEE_HANDLE_NULL) { + TEE_CloseTASession(sess); + sess = TEE_HANDLE_NULL; + } + return 0; +} + +void *dlsym(void *handle, const char *symbol) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Param params[TEE_NUM_PARAMS] = { }; + struct dl_handle *h = handle; + uint32_t param_types = 0; + void *ptr = NULL; + + if (!handle || !symbol) + return NULL; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + + params[0].memref.buffer = &h->uuid; + params[0].memref.size = sizeof(h->uuid); + params[1].memref.buffer = (void *)symbol; + params[1].memref.size = strlen(symbol) + 1; + + res = invoke_system_pta(PTA_SYSTEM_DLSYM, param_types, params); + if (!res) + ptr = (void *)(vaddr_t)reg_pair_to_64(params[2].value.a, + params[2].value.b); + + return ptr; +} + diff --git a/optee/optee_os/lib/libdl/include/dlfcn.h b/optee/optee_os/lib/libdl/include/dlfcn.h new file mode 100644 index 0000000..2110375 --- /dev/null +++ b/optee/optee_os/lib/libdl/include/dlfcn.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019 Linaro limited + */ + +#ifndef _DLFCN_H_ +#define _DLFCN_H_ + +/* Relocations are performed when the object is loaded. */ +#define RTLD_NOW 2 +/* All symbols are available for relocation processing of other modules. */ +#define RTLD_GLOBAL 0x100 +/* Do not unload the shared object during dlclose(). */ +#define RTLD_NODELETE 0x1000 +/* Other flags are not supported */ + +/* Note: @flags must be (RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE) */ +void *dlopen(const char *filename, int flags); +int dlclose(void *handle); +void *dlsym(void *handle, const char *symbol); + +#endif /* _DLFCN_H_ */ diff --git a/optee/optee_os/lib/libdl/sub.mk b/optee/optee_os/lib/libdl/sub.mk new file mode 100644 index 0000000..ec94656 --- /dev/null +++ b/optee/optee_os/lib/libdl/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += dlfcn.c diff --git a/optee/optee_os/lib/libmbedtls/core/aes.c b/optee/optee_os/lib/libmbedtls/core/aes.c new file mode 100644 index 0000000..1dfa28c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/aes.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result crypto_aes_expand_enc_key(const void *key, size_t key_len, + void *enc_key, size_t enc_keylen, + unsigned int *rounds) +{ +#if defined(MBEDTLS_AES_ALT) + return crypto_accel_aes_expand_keys(key, key_len, enc_key, NULL, + enc_keylen, rounds); +#else + mbedtls_aes_context ctx; + + memset(&ctx, 0, sizeof(ctx)); + mbedtls_aes_init(&ctx); + if (mbedtls_aes_setkey_enc(&ctx, key, key_len * 8) != 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (enc_keylen > sizeof(ctx.buf)) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(enc_key, ctx.buf, enc_keylen); + *rounds = ctx.nr; + mbedtls_aes_free(&ctx); + return TEE_SUCCESS; +#endif +} + +void crypto_aes_enc_block(const void *enc_key, size_t enc_keylen __maybe_unused, + unsigned int rounds, const void *src, void *dst) +{ +#if defined(MBEDTLS_AES_ALT) + crypto_accel_aes_ecb_enc(dst, src, enc_key, rounds, 1); +#else + mbedtls_aes_context ctx; + + memset(&ctx, 0, sizeof(ctx)); + mbedtls_aes_init(&ctx); + if (enc_keylen > sizeof(ctx.buf)) + panic(); + memcpy(ctx.buf, enc_key, enc_keylen); + ctx.rk = ctx.buf; + ctx.nr = rounds; + mbedtls_aes_encrypt(&ctx, src, dst); + mbedtls_aes_free(&ctx); +#endif +} + +#if defined(MBEDTLS_AES_ALT) +void mbedtls_aes_init(mbedtls_aes_context *ctx) +{ + assert(ctx); + memset(ctx, 0, sizeof(*ctx)); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if (ctx) + mbedtls_platform_zeroize(ctx, sizeof(*ctx)); +} + +int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits) +{ + assert(ctx && key); + + if (keybits != 128 && keybits != 192 && keybits != 256) + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + + if (crypto_accel_aes_expand_keys(key, keybits / 8, ctx->key, NULL, + sizeof(ctx->key), &ctx->round_count)) + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + + return 0; +} + +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits) +{ + uint32_t enc_key[sizeof(ctx->key)] = { 0 }; + + assert(ctx && key); + + if (keybits != 128 && keybits != 192 && keybits != 256) + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + + if (crypto_accel_aes_expand_keys(key, keybits / 8, enc_key, ctx->key, + sizeof(ctx->key), &ctx->round_count)) + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + + return 0; +} +#endif /*MBEDTLS_AES_ALT*/ diff --git a/optee/optee_os/lib/libmbedtls/core/aes_cbc.c b/optee/optee_os/lib/libmbedtls/core/aes_cbc.c new file mode 100644 index 0000000..34a6f00 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/aes_cbc.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + * Copyright (C) 2021, Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" + +struct mbed_aes_cbc_ctx { + struct crypto_cipher_ctx ctx; + int mbed_mode; + mbedtls_aes_context aes_ctx; + unsigned char iv[TEE_AES_BLOCK_SIZE]; +}; + +static const struct crypto_cipher_ops mbed_aes_cbc_ops; + +static struct mbed_aes_cbc_ctx *to_aes_cbc_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_aes_cbc_ops); + + return container_of(ctx, struct mbed_aes_cbc_ctx, ctx); +} + +static TEE_Result mbed_aes_cbc_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv, size_t iv_len) +{ + struct mbed_aes_cbc_ctx *c = to_aes_cbc_ctx(ctx); + int mbed_res = 0; + + if (iv_len != sizeof(c->iv)) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(c->iv, iv, sizeof(c->iv)); + + mbedtls_aes_init(&c->aes_ctx); + + if (mode == TEE_MODE_ENCRYPT) { + c->mbed_mode = MBEDTLS_AES_ENCRYPT; + mbed_res = mbedtls_aes_setkey_enc(&c->aes_ctx, key1, + key1_len * 8); + } else { + c->mbed_mode = MBEDTLS_AES_DECRYPT; + mbed_res = mbedtls_aes_setkey_dec(&c->aes_ctx, key1, + key1_len * 8); + } + + if (mbed_res) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_aes_cbc_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, + uint8_t *dst) +{ + struct mbed_aes_cbc_ctx *c = to_aes_cbc_ctx(ctx); + + if (mbedtls_aes_crypt_cbc(&c->aes_ctx, c->mbed_mode, len, c->iv, + data, dst)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static void mbed_aes_cbc_final(struct crypto_cipher_ctx *ctx) +{ + mbedtls_aes_free(&to_aes_cbc_ctx(ctx)->aes_ctx); +} + +static void mbed_aes_cbc_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_aes_cbc_ctx(ctx)); +} + +static void mbed_aes_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct mbed_aes_cbc_ctx *src = to_aes_cbc_ctx(src_ctx); + struct mbed_aes_cbc_ctx *dst = to_aes_cbc_ctx(dst_ctx); + + memcpy(dst->iv, src->iv, sizeof(dst->iv)); + dst->mbed_mode = src->mbed_mode; + mbed_copy_mbedtls_aes_context(&dst->aes_ctx, &src->aes_ctx); +} + +static const struct crypto_cipher_ops mbed_aes_cbc_ops = { + .init = mbed_aes_cbc_init, + .update = mbed_aes_cbc_update, + .final = mbed_aes_cbc_final, + .free_ctx = mbed_aes_cbc_free_ctx, + .copy_state = mbed_aes_cbc_copy_state, +}; + +TEE_Result crypto_aes_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct mbed_aes_cbc_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &mbed_aes_cbc_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} + +#if defined(MBEDTLS_AES_ALT) +int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, int mode, size_t length, + unsigned char iv[16], const unsigned char *input, + unsigned char *output) +{ + if (length % 16) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + if (mode == MBEDTLS_AES_ENCRYPT) + crypto_accel_aes_cbc_enc(output, input, ctx->key, + ctx->round_count, length / 16, iv); + else + crypto_accel_aes_cbc_dec(output, input, ctx->key, + ctx->round_count, length / 16, iv); + + return 0; +} +#endif /*MBEDTLS_AES_ALT*/ diff --git a/optee/optee_os/lib/libmbedtls/core/aes_ctr.c b/optee/optee_os/lib/libmbedtls/core/aes_ctr.c new file mode 100644 index 0000000..093d912 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/aes_ctr.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + * Copyright (C) 2021, Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" + +struct mbed_aes_ctr_ctx { + struct crypto_cipher_ctx ctx; + mbedtls_aes_context aes_ctx; + size_t nc_off; + unsigned char counter[TEE_AES_BLOCK_SIZE]; + unsigned char block[TEE_AES_BLOCK_SIZE]; +}; + +static const struct crypto_cipher_ops mbed_aes_ctr_ops; + +static struct mbed_aes_ctr_ctx *to_aes_ctr_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_aes_ctr_ops); + + return container_of(ctx, struct mbed_aes_ctr_ctx, ctx); +} + +static TEE_Result mbed_aes_ctr_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode __unused, + const uint8_t *key1, size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv, size_t iv_len) +{ + struct mbed_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); + + if (iv_len != sizeof(c->counter)) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(c->counter, iv, sizeof(c->counter)); + + mbedtls_aes_init(&c->aes_ctx); + c->nc_off = 0; + + if (mbedtls_aes_setkey_enc(&c->aes_ctx, key1, key1_len * 8)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_aes_ctr_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, + uint8_t *dst) +{ + struct mbed_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); + + if (mbedtls_aes_crypt_ctr(&c->aes_ctx, len, &c->nc_off, c->counter, + c->block, data, dst)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static void mbed_aes_ctr_final(struct crypto_cipher_ctx *ctx) +{ + struct mbed_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); + + mbedtls_aes_free(&c->aes_ctx); + memset(c->block, 0, sizeof(c->block)); +} + +static void mbed_aes_ctr_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_aes_ctr_ctx(ctx)); +} + +static void mbed_aes_ctr_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct mbed_aes_ctr_ctx *src = to_aes_ctr_ctx(src_ctx); + struct mbed_aes_ctr_ctx *dst = to_aes_ctr_ctx(dst_ctx); + + memcpy(dst->counter, src->counter, sizeof(dst->counter)); + memcpy(dst->block, src->block, sizeof(dst->block)); + dst->nc_off = src->nc_off; + mbed_copy_mbedtls_aes_context(&dst->aes_ctx, &src->aes_ctx); +} + +static const struct crypto_cipher_ops mbed_aes_ctr_ops = { + .init = mbed_aes_ctr_init, + .update = mbed_aes_ctr_update, + .final = mbed_aes_ctr_final, + .free_ctx = mbed_aes_ctr_free_ctx, + .copy_state = mbed_aes_ctr_copy_state, +}; + +TEE_Result crypto_aes_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct mbed_aes_ctr_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &mbed_aes_ctr_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} + +#if defined(MBEDTLS_AES_ALT) +static void next_ctr(unsigned char stream_block[16], mbedtls_aes_context *ctx, + unsigned char nonce_counter[16]) +{ + const unsigned char zeroes[16] = { 0 }; + + crypto_accel_aes_ctr_be_enc(stream_block, zeroes, ctx->key, + ctx->round_count, 1, nonce_counter); +} + +int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, size_t length, + size_t *nc_off, unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, unsigned char *output) +{ + size_t offs = 0; + + if (*nc_off >= 16) + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + + /* + * If the stream_block is in use, continue until done or + * stream_block is consumed. + */ + while (*nc_off) { + output[offs] = stream_block[*nc_off] ^ input[offs]; + offs++; + *nc_off = (*nc_off + 1) % 16; + if (offs == length) + return 0; + } + + if ((length - offs) >= 16) { + size_t block_count = (length - offs) / 16; + + crypto_accel_aes_ctr_be_enc(output + offs, input + offs, + ctx->key, ctx->round_count, + block_count, nonce_counter); + offs += block_count * 16; + } + + while (offs < length) { + if (!*nc_off) + next_ctr(stream_block, ctx, nonce_counter); + output[offs] = stream_block[*nc_off] ^ input[offs]; + offs++; + *nc_off = (*nc_off + 1) % 16; + } + + return 0; +} +#endif /*MBEDTLS_AES_ALT*/ diff --git a/optee/optee_os/lib/libmbedtls/core/aes_ecb.c b/optee/optee_os/lib/libmbedtls/core/aes_ecb.c new file mode 100644 index 0000000..934befa --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/aes_ecb.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + * Copyright (C) 2021, Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" + +struct mbed_aes_ecb_ctx { + struct crypto_cipher_ctx ctx; + int mbed_mode; + mbedtls_aes_context aes_ctx; +}; + +static const struct crypto_cipher_ops mbed_aes_ecb_ops; + +static struct mbed_aes_ecb_ctx *to_aes_ecb_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_aes_ecb_ops); + + return container_of(ctx, struct mbed_aes_ecb_ctx, ctx); +} + +static TEE_Result mbed_aes_ecb_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct mbed_aes_ecb_ctx *c = to_aes_ecb_ctx(ctx); + int mbed_res = 0; + + mbedtls_aes_init(&c->aes_ctx); + + if (mode == TEE_MODE_ENCRYPT) { + c->mbed_mode = MBEDTLS_AES_ENCRYPT; + mbed_res = mbedtls_aes_setkey_enc(&c->aes_ctx, key1, + key1_len * 8); + } else { + c->mbed_mode = MBEDTLS_AES_DECRYPT; + mbed_res = mbedtls_aes_setkey_dec(&c->aes_ctx, key1, + key1_len * 8); + } + + if (mbed_res) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_aes_ecb_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, + uint8_t *dst) +{ + struct mbed_aes_ecb_ctx *c = to_aes_ecb_ctx(ctx); + size_t block_size = TEE_AES_BLOCK_SIZE; + size_t offs = 0; + + if (len % block_size) + return TEE_ERROR_BAD_PARAMETERS; + + for (offs = 0; offs < len; offs += block_size) { + if (mbedtls_aes_crypt_ecb(&c->aes_ctx, c->mbed_mode, + data + offs, dst + offs)) + return TEE_ERROR_BAD_STATE; + } + + return TEE_SUCCESS; +} + +static void mbed_aes_ecb_final(struct crypto_cipher_ctx *ctx) +{ + mbedtls_aes_free(&to_aes_ecb_ctx(ctx)->aes_ctx); +} + +static void mbed_aes_ecb_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_aes_ecb_ctx(ctx)); +} + +static void mbed_aes_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct mbed_aes_ecb_ctx *src = to_aes_ecb_ctx(src_ctx); + struct mbed_aes_ecb_ctx *dst = to_aes_ecb_ctx(dst_ctx); + + dst->mbed_mode = src->mbed_mode; + mbed_copy_mbedtls_aes_context(&dst->aes_ctx, &src->aes_ctx); +} + +static const struct crypto_cipher_ops mbed_aes_ecb_ops = { + .init = mbed_aes_ecb_init, + .update = mbed_aes_ecb_update, + .final = mbed_aes_ecb_final, + .free_ctx = mbed_aes_ecb_free_ctx, + .copy_state = mbed_aes_ecb_copy_state, +}; + +TEE_Result crypto_aes_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct mbed_aes_ecb_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &mbed_aes_ecb_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} + +#if defined(MBEDTLS_AES_ALT) +int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, + const unsigned char input[16], + unsigned char output[16]) + +{ + if (mode == MBEDTLS_AES_ENCRYPT) + crypto_accel_aes_ecb_enc(output, input, ctx->key, + ctx->round_count, 1); + else + crypto_accel_aes_ecb_dec(output, input, ctx->key, + ctx->round_count, 1); + + return 0; +} +#endif /*MBEDTLS_AES_ALT*/ diff --git a/optee/optee_os/lib/libmbedtls/core/bignum.c b/optee/optee_os/lib/libmbedtls/core/bignum.c new file mode 100644 index 0000000..61f6c5c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/bignum.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0)) + +size_t crypto_bignum_num_bytes(struct bignum *a) +{ + assert(a != NULL); + return mbedtls_mpi_size((const mbedtls_mpi *)a); +} + +size_t crypto_bignum_num_bits(struct bignum *a) +{ + assert(a != NULL); + return mbedtls_mpi_bitlen((const mbedtls_mpi *)a); +} + +int32_t crypto_bignum_compare(struct bignum *a, struct bignum *b) +{ + int ret = 0; + + assert(a != NULL); + assert(b != NULL); + ret = mbedtls_mpi_cmp_mpi((const mbedtls_mpi *)a, + (const mbedtls_mpi *)b); + return CMP_TRILEAN(ret, 0); +} + +void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to) +{ + size_t len = 0; + + assert(from != NULL); + assert(to != NULL); + len = crypto_bignum_num_bytes((struct bignum *)from); + if (mbedtls_mpi_write_binary((mbedtls_mpi *)from, to, len)) + panic(); +} + +TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize, + struct bignum *to) +{ + assert(from != NULL); + assert(to != NULL); + if (mbedtls_mpi_read_binary((mbedtls_mpi *)to, from, fromsize)) + return TEE_ERROR_BAD_PARAMETERS; + return TEE_SUCCESS; +} + +void crypto_bignum_copy(struct bignum *to, const struct bignum *from) +{ + assert(from != NULL); + assert(to != NULL); + if (mbedtls_mpi_copy((mbedtls_mpi *)to, (const mbedtls_mpi *)from)) + panic(); +} + +struct bignum *crypto_bignum_allocate(size_t size_bits) +{ + mbedtls_mpi *bn = NULL; + + if (size_bits > CFG_CORE_BIGNUM_MAX_BITS) + size_bits = CFG_CORE_BIGNUM_MAX_BITS; + + bn = calloc(1, sizeof(mbedtls_mpi)); + if (!bn) + return NULL; + mbedtls_mpi_init(bn); + if (mbedtls_mpi_grow(bn, BITS_TO_LIMBS(size_bits)) != 0) { + free(bn); + return NULL; + } + + return (struct bignum *)bn; +} + +void crypto_bignum_free(struct bignum *s) +{ + mbedtls_mpi_free((mbedtls_mpi *)s); + free(s); +} + +void crypto_bignum_clear(struct bignum *s) +{ + mbedtls_mpi *bn = (mbedtls_mpi *)s; + + memset(bn->p, 0, mbedtls_mpi_size((const mbedtls_mpi *)bn)); +} diff --git a/optee/optee_os/lib/libmbedtls/core/cmac.c b/optee/optee_os/lib/libmbedtls/core/cmac.c new file mode 100644 index 0000000..53878ba --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/cmac.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + * Copyright (C) 2021, SumUp Services GmbH + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mbed_cmac_ctx { + struct crypto_mac_ctx mac_ctx; + mbedtls_cipher_context_t cipher_ctx; + mbedtls_cipher_id_t cipher_id; +}; + +static const struct crypto_mac_ops mbed_cmac_ops; + +static struct mbed_cmac_ctx *to_cmac_ctx(struct crypto_mac_ctx *ctx) +{ + assert(ctx); + assert(ctx->ops == &mbed_cmac_ops); + + return container_of(ctx, struct mbed_cmac_ctx, mac_ctx); +} + +static TEE_Result mbed_cmac_init(struct crypto_mac_ctx *ctx, + const uint8_t *key, size_t len) +{ + struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); + const mbedtls_cipher_info_t *cipher_info = NULL; + + cipher_info = mbedtls_cipher_info_from_values(c->cipher_id, + len * 8, + MBEDTLS_MODE_ECB); + if (!cipher_info) + return TEE_ERROR_NOT_SUPPORTED; + + if (mbedtls_cipher_setup_info(&c->cipher_ctx, cipher_info)) + return TEE_ERROR_BAD_STATE; + + if (mbedtls_cipher_cmac_reset(&c->cipher_ctx)) + return TEE_ERROR_BAD_STATE; + + if (mbedtls_cipher_cmac_starts(&c->cipher_ctx, key, len * 8)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_cmac_update(struct crypto_mac_ctx *ctx, + const uint8_t *data, size_t len) +{ + struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); + + if (mbedtls_cipher_cmac_update(&c->cipher_ctx, data, len)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_cmac_final(struct crypto_mac_ctx *ctx, + uint8_t *digest, size_t len) +{ + struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); + size_t block_size = TEE_AES_BLOCK_SIZE; + uint8_t block_digest[TEE_AES_BLOCK_SIZE] = { }; + uint8_t *tmp_digest = NULL; + + COMPILE_TIME_ASSERT(TEE_AES_BLOCK_SIZE >= TEE_DES_BLOCK_SIZE); + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (c->cipher_id == MBEDTLS_CIPHER_ID_3DES) + block_size = TEE_DES_BLOCK_SIZE; + + if (len < block_size) + tmp_digest = block_digest; /* use a tempory buffer */ + else + tmp_digest = digest; + + if (mbedtls_cipher_cmac_finish(&c->cipher_ctx, tmp_digest)) + return TEE_ERROR_BAD_STATE; + + if (len < block_size) + memcpy(digest, tmp_digest, len); + + return TEE_SUCCESS; +} + +static void mbed_cmac_free_ctx(struct crypto_mac_ctx *ctx) +{ + struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); + + mbedtls_cipher_free(&c->cipher_ctx); + free(c); +} + +static void mbed_cmac_copy_state(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx) +{ + struct mbed_cmac_ctx *src = to_cmac_ctx(src_ctx); + struct mbed_cmac_ctx *dst = to_cmac_ctx(dst_ctx); + + if (mbedtls_cipher_clone(&dst->cipher_ctx, &src->cipher_ctx)) + panic(); +} + +static const struct crypto_mac_ops mbed_cmac_ops = { + .init = mbed_cmac_init, + .update = mbed_cmac_update, + .final = mbed_cmac_final, + .free_ctx = mbed_cmac_free_ctx, + .copy_state = mbed_cmac_copy_state, +}; + +static TEE_Result crypto_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, + const mbedtls_cipher_id_t cipher_id, + int key_bitlen) +{ + int mbed_res = 0; + struct mbed_cmac_ctx *c = NULL; + const mbedtls_cipher_info_t *cipher_info = NULL; + + /* + * Use a default key length for getting 'cipher_info' to do the + * setup. The 'cipher_info' will need to be re-assigned with final + * key length obtained in mbed_cmac_init() above. + * + * This is safe since 'mbedtls_cipher_base_t' (used for cipher + * context) uses the same fixed allocation all key lengths. + */ + cipher_info = mbedtls_cipher_info_from_values(cipher_id, key_bitlen, + MBEDTLS_MODE_ECB); + if (!cipher_info) + return TEE_ERROR_NOT_SUPPORTED; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->cipher_id = cipher_id; + c->mac_ctx.ops = &mbed_cmac_ops; + + mbedtls_cipher_init(&c->cipher_ctx); + mbed_res = mbedtls_cipher_setup(&c->cipher_ctx, cipher_info); + if (mbed_res) { + free(c); + if (mbed_res == MBEDTLS_ERR_CIPHER_ALLOC_FAILED) + return TEE_ERROR_OUT_OF_MEMORY; + return TEE_ERROR_NOT_SUPPORTED; + } + mbed_res = mbedtls_cipher_cmac_setup(&c->cipher_ctx); + if (mbed_res) { + free(c); + return TEE_ERROR_NOT_SUPPORTED; + } + + *ctx_ret = &c->mac_ctx; + + return TEE_SUCCESS; +} + +TEE_Result crypto_des3_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) +{ + return crypto_cmac_alloc_ctx(ctx_ret, MBEDTLS_CIPHER_ID_3DES, 192); +} + +TEE_Result crypto_aes_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) +{ + return crypto_cmac_alloc_ctx(ctx_ret, MBEDTLS_CIPHER_ID_AES, 128); +} diff --git a/optee/optee_os/lib/libmbedtls/core/des3_cbc.c b/optee/optee_os/lib/libmbedtls/core/des3_cbc.c new file mode 100644 index 0000000..17dba17 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/des3_cbc.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mbed_des3_cbc_ctx { + struct crypto_cipher_ctx ctx; + int mbed_mode; + mbedtls_des3_context des3_ctx; + unsigned char iv[TEE_DES_BLOCK_SIZE]; +}; + +static const struct crypto_cipher_ops mbed_des3_cbc_ops; + +static struct mbed_des3_cbc_ctx *to_des3_cbc_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_des3_cbc_ops); + + return container_of(ctx, struct mbed_des3_cbc_ctx, ctx); +} + +static TEE_Result mbed_des3_cbc_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, + const uint8_t *key1, size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct mbed_des3_cbc_ctx *c = to_des3_cbc_ctx(ctx); + int mbed_res = 0; + + if (key1_len != MBEDTLS_DES_KEY_SIZE * 2 && + key1_len != MBEDTLS_DES_KEY_SIZE * 3) + return TEE_ERROR_BAD_PARAMETERS; + if (iv_len != sizeof(c->iv)) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(c->iv, iv, sizeof(c->iv)); + + mbedtls_des3_init(&c->des3_ctx); + + if (mode == TEE_MODE_ENCRYPT) { + c->mbed_mode = MBEDTLS_DES_ENCRYPT; + if (key1_len == MBEDTLS_DES_KEY_SIZE * 3) + mbed_res = mbedtls_des3_set3key_enc(&c->des3_ctx, key1); + else + mbed_res = mbedtls_des3_set2key_enc(&c->des3_ctx, key1); + } else { + c->mbed_mode = MBEDTLS_DES_DECRYPT; + if (key1_len == MBEDTLS_DES_KEY_SIZE * 3) + mbed_res = mbedtls_des3_set3key_dec(&c->des3_ctx, key1); + else + mbed_res = mbedtls_des3_set2key_dec(&c->des3_ctx, key1); + } + + if (mbed_res) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_des3_cbc_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, + uint8_t *dst) +{ + struct mbed_des3_cbc_ctx *c = to_des3_cbc_ctx(ctx); + + if (mbedtls_des3_crypt_cbc(&c->des3_ctx, c->mbed_mode, len, c->iv, + data, dst)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static void mbed_des3_cbc_final(struct crypto_cipher_ctx *ctx) +{ + mbedtls_des3_free(&to_des3_cbc_ctx(ctx)->des3_ctx); +} + +static void mbed_des3_cbc_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_des3_cbc_ctx(ctx)); +} + +static void mbed_des3_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct mbed_des3_cbc_ctx *src = to_des3_cbc_ctx(src_ctx); + struct mbed_des3_cbc_ctx *dst = to_des3_cbc_ctx(dst_ctx); + + memcpy(dst->iv, src->iv, sizeof(dst->iv)); + dst->mbed_mode = src->mbed_mode; + dst->des3_ctx = src->des3_ctx; +} + +static const struct crypto_cipher_ops mbed_des3_cbc_ops = { + .init = mbed_des3_cbc_init, + .update = mbed_des3_cbc_update, + .final = mbed_des3_cbc_final, + .free_ctx = mbed_des3_cbc_free_ctx, + .copy_state = mbed_des3_cbc_copy_state, +}; + +TEE_Result crypto_des3_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct mbed_des3_cbc_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &mbed_des3_cbc_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/lib/libmbedtls/core/des3_ecb.c b/optee/optee_os/lib/libmbedtls/core/des3_ecb.c new file mode 100644 index 0000000..56e3b8d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/des3_ecb.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mbed_des3_ecb_ctx { + struct crypto_cipher_ctx ctx; + mbedtls_des3_context des3_ctx; +}; + +static const struct crypto_cipher_ops mbed_des3_ecb_ops; + +static struct mbed_des3_ecb_ctx *to_des3_ecb_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_des3_ecb_ops); + + return container_of(ctx, struct mbed_des3_ecb_ctx, ctx); +} + +static TEE_Result mbed_des3_ecb_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, + const uint8_t *key1, size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct mbed_des3_ecb_ctx *c = to_des3_ecb_ctx(ctx); + int mbed_res = 0; + + if (key1_len != MBEDTLS_DES_KEY_SIZE * 2 && + key1_len != MBEDTLS_DES_KEY_SIZE * 3) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_des3_init(&c->des3_ctx); + + if (key1_len == MBEDTLS_DES_KEY_SIZE * 3) { + if (mode == TEE_MODE_ENCRYPT) + mbed_res = mbedtls_des3_set3key_enc(&c->des3_ctx, key1); + else + mbed_res = mbedtls_des3_set3key_dec(&c->des3_ctx, key1); + } else { + if (mode == TEE_MODE_ENCRYPT) + mbed_res = mbedtls_des3_set2key_enc(&c->des3_ctx, key1); + else + mbed_res = mbedtls_des3_set2key_dec(&c->des3_ctx, key1); + } + + if (mbed_res) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_des3_ecb_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, + uint8_t *dst) +{ + struct mbed_des3_ecb_ctx *c = to_des3_ecb_ctx(ctx); + size_t block_size = TEE_DES_BLOCK_SIZE; + size_t offs = 0; + + if (len % block_size) + return TEE_ERROR_BAD_PARAMETERS; + + for (offs = 0; offs < len; offs += block_size) { + if (mbedtls_des3_crypt_ecb(&c->des3_ctx, data + offs, + dst + offs)) + return TEE_ERROR_BAD_STATE; + } + + return TEE_SUCCESS; +} + +static void mbed_des3_ecb_final(struct crypto_cipher_ctx *ctx) +{ + mbedtls_des3_free(&to_des3_ecb_ctx(ctx)->des3_ctx); +} + +static void mbed_des3_ecb_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_des3_ecb_ctx(ctx)); +} + +static void mbed_des3_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct mbed_des3_ecb_ctx *src = to_des3_ecb_ctx(src_ctx); + struct mbed_des3_ecb_ctx *dst = to_des3_ecb_ctx(dst_ctx); + + dst->des3_ctx = src->des3_ctx; +} + +static const struct crypto_cipher_ops mbed_des3_ecb_ops = { + .init = mbed_des3_ecb_init, + .update = mbed_des3_ecb_update, + .final = mbed_des3_ecb_final, + .free_ctx = mbed_des3_ecb_free_ctx, + .copy_state = mbed_des3_ecb_copy_state, +}; + +TEE_Result crypto_des3_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct mbed_des3_ecb_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &mbed_des3_ecb_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/lib/libmbedtls/core/des_cbc.c b/optee/optee_os/lib/libmbedtls/core/des_cbc.c new file mode 100644 index 0000000..a79b794 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/des_cbc.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mbed_des_cbc_ctx { + struct crypto_cipher_ctx ctx; + int mbed_mode; + mbedtls_des_context des_ctx; + unsigned char iv[TEE_DES_BLOCK_SIZE]; +}; + +static const struct crypto_cipher_ops mbed_des_cbc_ops; + +static struct mbed_des_cbc_ctx *to_des_cbc_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_des_cbc_ops); + + return container_of(ctx, struct mbed_des_cbc_ctx, ctx); +} + +static TEE_Result mbed_des_cbc_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct mbed_des_cbc_ctx *c = to_des_cbc_ctx(ctx); + int mbed_res = 0; + + if (key1_len != MBEDTLS_DES_KEY_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + if (iv_len != sizeof(c->iv)) + return TEE_ERROR_BAD_PARAMETERS; + memcpy(c->iv, iv, sizeof(c->iv)); + + mbedtls_des_init(&c->des_ctx); + + if (mode == TEE_MODE_ENCRYPT) { + c->mbed_mode = MBEDTLS_DES_ENCRYPT; + mbed_res = mbedtls_des_setkey_enc(&c->des_ctx, key1); + } else { + c->mbed_mode = MBEDTLS_DES_DECRYPT; + mbed_res = mbedtls_des_setkey_dec(&c->des_ctx, key1); + } + + if (mbed_res) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_des_cbc_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, + uint8_t *dst) +{ + struct mbed_des_cbc_ctx *c = to_des_cbc_ctx(ctx); + + if (mbedtls_des_crypt_cbc(&c->des_ctx, c->mbed_mode, len, c->iv, + data, dst)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static void mbed_des_cbc_final(struct crypto_cipher_ctx *ctx) +{ + mbedtls_des_free(&to_des_cbc_ctx(ctx)->des_ctx); +} + +static void mbed_des_cbc_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_des_cbc_ctx(ctx)); +} + +static void mbed_des_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct mbed_des_cbc_ctx *src = to_des_cbc_ctx(src_ctx); + struct mbed_des_cbc_ctx *dst = to_des_cbc_ctx(dst_ctx); + + memcpy(dst->iv, src->iv, sizeof(dst->iv)); + dst->mbed_mode = src->mbed_mode; + dst->des_ctx = src->des_ctx; +} + +static const struct crypto_cipher_ops mbed_des_cbc_ops = { + .init = mbed_des_cbc_init, + .update = mbed_des_cbc_update, + .final = mbed_des_cbc_final, + .free_ctx = mbed_des_cbc_free_ctx, + .copy_state = mbed_des_cbc_copy_state, +}; + +TEE_Result crypto_des_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct mbed_des_cbc_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &mbed_des_cbc_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/lib/libmbedtls/core/des_ecb.c b/optee/optee_os/lib/libmbedtls/core/des_ecb.c new file mode 100644 index 0000000..38823a6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/des_ecb.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mbed_des_ecb_ctx { + struct crypto_cipher_ctx ctx; + mbedtls_des_context des_ctx; +}; + +static const struct crypto_cipher_ops mbed_des_ecb_ops; + +static struct mbed_des_ecb_ctx *to_des_ecb_ctx(struct crypto_cipher_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_des_ecb_ops); + + return container_of(ctx, struct mbed_des_ecb_ctx, ctx); +} + +static TEE_Result mbed_des_ecb_init(struct crypto_cipher_ctx *ctx, + TEE_OperationMode mode, const uint8_t *key1, + size_t key1_len, + const uint8_t *key2 __unused, + size_t key2_len __unused, + const uint8_t *iv __unused, + size_t iv_len __unused) +{ + struct mbed_des_ecb_ctx *c = to_des_ecb_ctx(ctx); + int mbed_res = 0; + + if (key1_len != MBEDTLS_DES_KEY_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_des_init(&c->des_ctx); + + if (mode == TEE_MODE_ENCRYPT) + mbed_res = mbedtls_des_setkey_enc(&c->des_ctx, key1); + else + mbed_res = mbedtls_des_setkey_dec(&c->des_ctx, key1); + + if (mbed_res) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_des_ecb_update(struct crypto_cipher_ctx *ctx, + bool last_block __unused, + const uint8_t *data, size_t len, + uint8_t *dst) +{ + struct mbed_des_ecb_ctx *c = to_des_ecb_ctx(ctx); + size_t block_size = TEE_DES_BLOCK_SIZE; + size_t offs = 0; + + if (len % block_size) + return TEE_ERROR_BAD_PARAMETERS; + + for (offs = 0; offs < len; offs += block_size) { + if (mbedtls_des_crypt_ecb(&c->des_ctx, data + offs, dst + offs)) + return TEE_ERROR_BAD_STATE; + } + + return TEE_SUCCESS; +} + +static void mbed_des_ecb_final(struct crypto_cipher_ctx *ctx) +{ + mbedtls_des_free(&to_des_ecb_ctx(ctx)->des_ctx); +} + +static void mbed_des_ecb_free_ctx(struct crypto_cipher_ctx *ctx) +{ + free(to_des_ecb_ctx(ctx)); +} + +static void mbed_des_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, + struct crypto_cipher_ctx *src_ctx) +{ + struct mbed_des_ecb_ctx *src = to_des_ecb_ctx(src_ctx); + struct mbed_des_ecb_ctx *dst = to_des_ecb_ctx(dst_ctx); + + dst->des_ctx = src->des_ctx; +} + +static const struct crypto_cipher_ops mbed_des_ecb_ops = { + .init = mbed_des_ecb_init, + .update = mbed_des_ecb_update, + .final = mbed_des_ecb_final, + .free_ctx = mbed_des_ecb_free_ctx, + .copy_state = mbed_des_ecb_copy_state, +}; + +TEE_Result crypto_des_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) +{ + struct mbed_des_ecb_ctx *c = NULL; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->ctx.ops = &mbed_des_ecb_ops; + *ctx_ret = &c->ctx; + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/lib/libmbedtls/core/dh.c b/optee/optee_os/lib/libmbedtls/core/dh.c new file mode 100644 index 0000000..b3415aa --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/dh.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" + +TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s, + size_t key_size_bits) +{ + memset(s, 0, sizeof(*s)); + s->g = crypto_bignum_allocate(key_size_bits); + if (!s->g) + goto err; + s->p = crypto_bignum_allocate(key_size_bits); + if (!s->p) + goto err; + s->y = crypto_bignum_allocate(key_size_bits); + if (!s->y) + goto err; + s->x = crypto_bignum_allocate(key_size_bits); + if (!s->x) + goto err; + s->q = crypto_bignum_allocate(key_size_bits); + if (!s->q) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->g); + crypto_bignum_free(s->p); + crypto_bignum_free(s->y); + crypto_bignum_free(s->x); + return TEE_ERROR_OUT_OF_MEMORY; +} + +TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, + struct bignum *q __unused, + size_t xbits, size_t key_size) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + mbedtls_dhm_context dhm; + unsigned char *buf = NULL; + size_t xbytes = 0; + + memset(&dhm, 0, sizeof(dhm)); + mbedtls_dhm_init(&dhm); + + dhm.G = *(mbedtls_mpi *)key->g; + dhm.P = *(mbedtls_mpi *)key->p; + + dhm.len = crypto_bignum_num_bytes(key->p); + if (key_size != 8 * dhm.len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (xbits == 0) + xbytes = dhm.len; + else + xbytes = xbits / 8; + + buf = malloc(dhm.len); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + lmd_res = mbedtls_dhm_make_public(&dhm, (int)xbytes, buf, + dhm.len, mbd_rand, NULL); + if (lmd_res != 0) { + FMSG("mbedtls_dhm_make_public err, return is 0x%x", -lmd_res); + res = TEE_ERROR_BAD_PARAMETERS; + } else { + crypto_bignum_bin2bn(buf, xbytes, key->y); + crypto_bignum_copy(key->x, (void *)&dhm.X); + res = TEE_SUCCESS; + } +out: + free(buf); + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&dhm.G); + mbedtls_mpi_init(&dhm.P); + mbedtls_dhm_free(&dhm); + return res; +} + +TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, + struct bignum *public_key, + struct bignum *secret) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + mbedtls_dhm_context dhm; + unsigned char *buf = NULL; + size_t olen = 0; + + memset(&dhm, 0, sizeof(dhm)); + mbedtls_dhm_init(&dhm); + + dhm.G = *(mbedtls_mpi *)private_key->g; + dhm.P = *(mbedtls_mpi *)private_key->p; + dhm.GX = *(mbedtls_mpi *)private_key->y; + dhm.X = *(mbedtls_mpi *)private_key->x; + dhm.GY = *(mbedtls_mpi *)public_key; + + dhm.len = crypto_bignum_num_bytes(private_key->p); + + buf = malloc(dhm.len); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + lmd_res = mbedtls_dhm_calc_secret(&dhm, buf, dhm.len, + &olen, mbd_rand, NULL); + if (lmd_res != 0) { + FMSG("mbedtls_dhm_calc_secret failed, ret is 0x%x", -lmd_res); + res = TEE_ERROR_BAD_PARAMETERS; + } else { + crypto_bignum_bin2bn(buf, olen, secret); + res = TEE_SUCCESS; + } +out: + free(buf); + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&dhm.G); + mbedtls_mpi_init(&dhm.P); + mbedtls_mpi_init(&dhm.GX); + mbedtls_mpi_init(&dhm.X); + mbedtls_mpi_init(&dhm.GY); + mbedtls_dhm_free(&dhm); + return res; +} diff --git a/optee/optee_os/lib/libmbedtls/core/ecc.c b/optee/optee_os/lib/libmbedtls/core/ecc.c new file mode 100644 index 0000000..8ec9f16 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/ecc.c @@ -0,0 +1,564 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" +#include "sm2-dsa.h" +#include "sm2-pke.h" + +/* Translate mbedtls result to TEE result */ +static TEE_Result get_tee_result(int lmd_res) +{ + switch (lmd_res) { + case 0: + return TEE_SUCCESS; + case MBEDTLS_ERR_ECP_VERIFY_FAILED: + return TEE_ERROR_SIGNATURE_INVALID; + case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: + return TEE_ERROR_SHORT_BUFFER; + default: + return TEE_ERROR_BAD_STATE; + } +} + +static void ecc_free_public_key(struct ecc_public_key *s) +{ + if (!s) + return; + + crypto_bignum_free(s->x); + crypto_bignum_free(s->y); +} + +static TEE_Result ecc_get_keysize(uint32_t curve, uint32_t algo, + size_t *key_size_bytes, size_t *key_size_bits) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + *key_size_bits = 192; + *key_size_bytes = 24; + break; + case TEE_ECC_CURVE_NIST_P224: + *key_size_bits = 224; + *key_size_bytes = 28; + break; + case TEE_ECC_CURVE_NIST_P256: + *key_size_bits = 256; + *key_size_bytes = 32; + break; + case TEE_ECC_CURVE_NIST_P384: + *key_size_bits = 384; + *key_size_bytes = 48; + break; + case TEE_ECC_CURVE_NIST_P521: + *key_size_bits = 521; + *key_size_bytes = 66; + break; + case TEE_ECC_CURVE_SM2: + *key_size_bits = 256; + *key_size_bytes = 32; + if (algo != 0 && algo != TEE_ALG_SM2_DSA_SM3 && + algo != TEE_ALG_SM2_KEP && algo != TEE_ALG_SM2_PKE) + return TEE_ERROR_BAD_PARAMETERS; + break; + default: + *key_size_bits = 0; + *key_size_bytes = 0; + return TEE_ERROR_NOT_SUPPORTED; + } + + return TEE_SUCCESS; +} + +/* + * Clear some memory that was used to prepare the context + */ +static void ecc_clear_precomputed(mbedtls_ecp_group *grp) +{ + size_t i = 0; + + if (grp->T) { + for (i = 0; i < grp->T_size; i++) + mbedtls_ecp_point_free(&grp->T[i]); + free(grp->T); + } + grp->T = NULL; + grp->T_size = 0; +} + +static mbedtls_ecp_group_id curve_to_group_id(uint32_t curve) +{ + switch (curve) { + case TEE_ECC_CURVE_NIST_P192: + return MBEDTLS_ECP_DP_SECP192R1; + case TEE_ECC_CURVE_NIST_P224: + return MBEDTLS_ECP_DP_SECP224R1; + case TEE_ECC_CURVE_NIST_P256: + return MBEDTLS_ECP_DP_SECP256R1; + case TEE_ECC_CURVE_NIST_P384: + return MBEDTLS_ECP_DP_SECP384R1; + case TEE_ECC_CURVE_NIST_P521: + return MBEDTLS_ECP_DP_SECP521R1; + case TEE_ECC_CURVE_SM2: + return MBEDTLS_ECP_DP_SM2; + default: + return MBEDTLS_ECP_DP_NONE; + } +} + +static TEE_Result ecc_generate_keypair(struct ecc_keypair *key, size_t key_size) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + mbedtls_ecdsa_context ecdsa; + mbedtls_ecp_group_id gid; + size_t key_size_bytes = 0; + size_t key_size_bits = 0; + + memset(&ecdsa, 0, sizeof(ecdsa)); + memset(&gid, 0, sizeof(gid)); + + res = ecc_get_keysize(key->curve, 0, &key_size_bytes, &key_size_bits); + if (res != TEE_SUCCESS) + return res; + + if (key_size != key_size_bits) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_ecdsa_init(&ecdsa); + + /* Generate the ECC key */ + gid = curve_to_group_id(key->curve); + lmd_res = mbedtls_ecdsa_genkey(&ecdsa, gid, mbd_rand, NULL); + if (lmd_res != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + FMSG("mbedtls_ecdsa_genkey failed."); + goto exit; + } + ecc_clear_precomputed(&ecdsa.grp); + + /* check the size of the keys */ + if ((mbedtls_mpi_bitlen(&ecdsa.Q.X) > key_size_bits) || + (mbedtls_mpi_bitlen(&ecdsa.Q.Y) > key_size_bits) || + (mbedtls_mpi_bitlen(&ecdsa.d) > key_size_bits)) { + res = TEE_ERROR_BAD_PARAMETERS; + FMSG("Check the size of the keys failed."); + goto exit; + } + + /* check LMD is returning z==1 */ + if (mbedtls_mpi_bitlen(&ecdsa.Q.Z) != 1) { + res = TEE_ERROR_BAD_PARAMETERS; + FMSG("Check LMD failed."); + goto exit; + } + + /* Copy the key */ + crypto_bignum_copy(key->d, (void *)&ecdsa.d); + crypto_bignum_copy(key->x, (void *)&ecdsa.Q.X); + crypto_bignum_copy(key->y, (void *)&ecdsa.Q.Y); + + res = TEE_SUCCESS; +exit: + mbedtls_ecdsa_free(&ecdsa); /* Free the temporary key */ + return res; +} + +static TEE_Result ecc_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, uint8_t *sig, + size_t *sig_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + const mbedtls_pk_info_t *pk_info = NULL; + mbedtls_ecdsa_context ecdsa; + mbedtls_ecp_group_id gid; + size_t key_size_bytes = 0; + size_t key_size_bits = 0; + mbedtls_mpi r; + mbedtls_mpi s; + + memset(&ecdsa, 0, sizeof(ecdsa)); + memset(&gid, 0, sizeof(gid)); + memset(&r, 0, sizeof(r)); + memset(&s, 0, sizeof(s)); + + if (algo == 0) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecdsa_init(&ecdsa); + + gid = curve_to_group_id(key->curve); + lmd_res = mbedtls_ecp_group_load(&ecdsa.grp, gid); + if (lmd_res != 0) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + ecdsa.d = *(mbedtls_mpi *)key->d; + + res = ecc_get_keysize(key->curve, algo, &key_size_bytes, + &key_size_bits); + if (res != TEE_SUCCESS) + goto out; + + if (*sig_len < 2 * key_size_bytes) { + *sig_len = 2 * key_size_bytes; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); + if (pk_info == NULL) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + lmd_res = mbedtls_ecdsa_sign(&ecdsa.grp, &r, &s, &ecdsa.d, msg, + msg_len, mbd_rand, NULL); + if (lmd_res == 0) { + *sig_len = 2 * key_size_bytes; + memset(sig, 0, *sig_len); + mbedtls_mpi_write_binary(&r, sig + *sig_len / 2 - + mbedtls_mpi_size(&r), + mbedtls_mpi_size(&r)); + + mbedtls_mpi_write_binary(&s, sig + *sig_len - + mbedtls_mpi_size(&s), + mbedtls_mpi_size(&s)); + res = TEE_SUCCESS; + } else { + FMSG("mbedtls_ecdsa_sign failed, returned 0x%x\n", -lmd_res); + res = TEE_ERROR_GENERIC; + } +out: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&ecdsa.d); + mbedtls_ecdsa_free(&ecdsa); + return res; +} + +static TEE_Result ecc_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + mbedtls_ecdsa_context ecdsa; + mbedtls_ecp_group_id gid; + size_t key_size_bytes, key_size_bits = 0; + uint8_t one[1] = { 1 }; + mbedtls_mpi r; + mbedtls_mpi s; + + memset(&ecdsa, 0, sizeof(ecdsa)); + memset(&gid, 0, sizeof(gid)); + memset(&r, 0, sizeof(r)); + memset(&s, 0, sizeof(s)); + + if (algo == 0) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + + mbedtls_ecdsa_init(&ecdsa); + + gid = curve_to_group_id(key->curve); + lmd_res = mbedtls_ecp_group_load(&ecdsa.grp, gid); + if (lmd_res != 0) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + ecdsa.Q.X = *(mbedtls_mpi *)key->x; + ecdsa.Q.Y = *(mbedtls_mpi *)key->y; + mbedtls_mpi_read_binary(&ecdsa.Q.Z, one, sizeof(one)); + + res = ecc_get_keysize(key->curve, algo, + &key_size_bytes, &key_size_bits); + if (res != TEE_SUCCESS) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* check keysize vs sig_len */ + if ((key_size_bytes * 2) != sig_len) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + mbedtls_mpi_read_binary(&r, sig, sig_len / 2); + mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2); + + lmd_res = mbedtls_ecdsa_verify(&ecdsa.grp, msg, msg_len, &ecdsa.Q, + &r, &s); + if (lmd_res != 0) { + FMSG("mbedtls_ecdsa_verify failed, returned 0x%x", -lmd_res); + res = get_tee_result(lmd_res); + } +out: + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&ecdsa.Q.X); + mbedtls_mpi_init(&ecdsa.Q.Y); + mbedtls_ecdsa_free(&ecdsa); + return res; +} + +static TEE_Result ecc_shared_secret(struct ecc_keypair *private_key, + struct ecc_public_key *public_key, + void *secret, unsigned long *secret_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + uint8_t one[1] = { 1 }; + mbedtls_ecdh_context ecdh; + mbedtls_ecp_group_id gid; + size_t out_len = 0; + + memset(&ecdh, 0, sizeof(ecdh)); + memset(&gid, 0, sizeof(gid)); + mbedtls_ecdh_init(&ecdh); + gid = curve_to_group_id(private_key->curve); + lmd_res = mbedtls_ecp_group_load(&ecdh.grp, gid); + if (lmd_res != 0) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + ecdh.d = *(mbedtls_mpi *)private_key->d; + ecdh.Qp.X = *(mbedtls_mpi *)public_key->x; + ecdh.Qp.Y = *(mbedtls_mpi *)public_key->y; + mbedtls_mpi_read_binary(&ecdh.Qp.Z, one, sizeof(one)); + + lmd_res = mbedtls_ecdh_calc_secret(&ecdh, &out_len, secret, + *secret_len, mbd_rand, NULL); + if (lmd_res != 0) { + res = get_tee_result(lmd_res); + goto out; + } + *secret_len = out_len; +out: + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&ecdh.d); + mbedtls_mpi_init(&ecdh.Qp.X); + mbedtls_mpi_init(&ecdh.Qp.Y); + mbedtls_ecdh_free(&ecdh); + return res; +} + +static const struct crypto_ecc_keypair_ops ecc_keypair_ops = { + .generate = ecc_generate_keypair, + .sign = ecc_sign, + .shared_secret = ecc_shared_secret, +}; + +static const struct crypto_ecc_keypair_ops sm2_pke_keypair_ops = { + .generate = ecc_generate_keypair, + .decrypt = sm2_mbedtls_pke_decrypt, +}; + +static const struct crypto_ecc_keypair_ops sm2_kep_keypair_ops = { + .generate = ecc_generate_keypair, +}; + +static const struct crypto_ecc_keypair_ops sm2_dsa_keypair_ops = { + .generate = ecc_generate_keypair, + .sign = sm2_mbedtls_dsa_sign, +}; + +const struct crypto_ecc_keypair_ops * +crypto_asym_get_ecc_keypair_ops(uint32_t key_type) +{ + switch (key_type) { + case TEE_TYPE_ECDSA_KEYPAIR: + case TEE_TYPE_ECDH_KEYPAIR: + return &ecc_keypair_ops; + case TEE_TYPE_SM2_DSA_KEYPAIR: + if (!IS_ENABLED(CFG_CRYPTO_SM2_DSA)) + return NULL; + return &sm2_dsa_keypair_ops; + case TEE_TYPE_SM2_PKE_KEYPAIR: + if (!IS_ENABLED(CFG_CRYPTO_SM2_PKE)) + return NULL; + return &sm2_pke_keypair_ops; + case TEE_TYPE_SM2_KEP_KEYPAIR: + if (!IS_ENABLED(CFG_CRYPTO_SM2_KEP)) + return NULL; + return &sm2_kep_keypair_ops; + default: + return NULL; + } +} + +TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *s, + uint32_t key_type, + size_t key_size_bits) +{ + memset(s, 0, sizeof(*s)); + + switch (key_type) { + case TEE_TYPE_ECDSA_KEYPAIR: + case TEE_TYPE_ECDH_KEYPAIR: + s->ops = &ecc_keypair_ops; + break; + case TEE_TYPE_SM2_DSA_KEYPAIR: + if (!IS_ENABLED(CFG_CRYPTO_SM2_DSA)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_dsa_keypair_ops; + break; + case TEE_TYPE_SM2_PKE_KEYPAIR: + if (!IS_ENABLED(CFG_CRYPTO_SM2_PKE)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_pke_keypair_ops; + break; + case TEE_TYPE_SM2_KEP_KEYPAIR: + if (!IS_ENABLED(CFG_CRYPTO_SM2_KEP)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_kep_keypair_ops; + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + + s->d = crypto_bignum_allocate(key_size_bits); + if (!s->d) + goto err; + s->x = crypto_bignum_allocate(key_size_bits); + if (!s->x) + goto err; + s->y = crypto_bignum_allocate(key_size_bits); + if (!s->y) + goto err; + + return TEE_SUCCESS; + +err: + crypto_bignum_free(s->d); + crypto_bignum_free(s->x); + + return TEE_ERROR_OUT_OF_MEMORY; +} + +static const struct crypto_ecc_public_ops ecc_public_key_ops = { + .free = ecc_free_public_key, + .verify = ecc_verify, +}; + +static const struct crypto_ecc_public_ops sm2_pke_public_key_ops = { + .free = ecc_free_public_key, + .encrypt = sm2_mbedtls_pke_encrypt, +}; + +static const struct crypto_ecc_public_ops sm2_kep_public_key_ops = { + .free = ecc_free_public_key, +}; + +static const struct crypto_ecc_public_ops sm2_dsa_public_key_ops = { + .free = ecc_free_public_key, + .verify = sm2_mbedtls_dsa_verify, +}; + +const struct crypto_ecc_public_ops* +crypto_asym_get_ecc_public_ops(uint32_t key_type) +{ + switch (key_type) { + case TEE_TYPE_ECDSA_PUBLIC_KEY: + case TEE_TYPE_ECDH_PUBLIC_KEY: + return &ecc_public_key_ops; + case TEE_TYPE_SM2_DSA_PUBLIC_KEY: + if (!IS_ENABLED(CFG_CRYPTO_SM2_DSA)) + return NULL; + + return &sm2_dsa_public_key_ops; + case TEE_TYPE_SM2_PKE_PUBLIC_KEY: + if (!IS_ENABLED(CFG_CRYPTO_SM2_PKE)) + return NULL; + + return &sm2_pke_public_key_ops; + case TEE_TYPE_SM2_KEP_PUBLIC_KEY: + if (!IS_ENABLED(CFG_CRYPTO_SM2_KEP)) + return NULL; + return &sm2_kep_public_key_ops; + default: + return NULL; + } +} + +TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *s, + uint32_t key_type, + size_t key_size_bits) +{ + memset(s, 0, sizeof(*s)); + + switch (key_type) { + case TEE_TYPE_ECDSA_PUBLIC_KEY: + case TEE_TYPE_ECDH_PUBLIC_KEY: + s->ops = &ecc_public_key_ops; + break; + case TEE_TYPE_SM2_DSA_PUBLIC_KEY: + if (!IS_ENABLED(CFG_CRYPTO_SM2_DSA)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_dsa_public_key_ops; + break; + case TEE_TYPE_SM2_PKE_PUBLIC_KEY: + if (!IS_ENABLED(CFG_CRYPTO_SM2_PKE)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_pke_public_key_ops; + break; + case TEE_TYPE_SM2_KEP_PUBLIC_KEY: + if (!IS_ENABLED(CFG_CRYPTO_SM2_KEP)) + return TEE_ERROR_NOT_IMPLEMENTED; + + s->curve = TEE_ECC_CURVE_SM2; + s->ops = &sm2_kep_public_key_ops; + break; + default: + return TEE_ERROR_NOT_IMPLEMENTED; + } + + s->x = crypto_bignum_allocate(key_size_bits); + if (!s->x) + goto err; + s->y = crypto_bignum_allocate(key_size_bits); + if (!s->y) + goto err; + + return TEE_SUCCESS; + +err: + crypto_bignum_free(s->x); + + return TEE_ERROR_OUT_OF_MEMORY; +} diff --git a/optee/optee_os/lib/libmbedtls/core/hash.c b/optee/optee_os/lib/libmbedtls/core/hash.c new file mode 100644 index 0000000..d2977c5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/hash.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mbed_hash_ctx { + struct crypto_hash_ctx hash_ctx; + mbedtls_md_context_t md_ctx; +}; + +static const struct crypto_hash_ops mbed_hash_ops; + +static struct mbed_hash_ctx *to_hash_ctx(struct crypto_hash_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_hash_ops); + + return container_of(ctx, struct mbed_hash_ctx, hash_ctx); +} + +static TEE_Result mbed_hash_init(struct crypto_hash_ctx *ctx) +{ + if (mbedtls_md_starts(&to_hash_ctx(ctx)->md_ctx)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_hash_update(struct crypto_hash_ctx *ctx, + const uint8_t *data, size_t len) +{ + if (mbedtls_md_update(&to_hash_ctx(ctx)->md_ctx, data, len)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_hash_final(struct crypto_hash_ctx *ctx, uint8_t *digest, + size_t len) +{ + struct mbed_hash_ctx *hc = to_hash_ctx(ctx); + size_t hash_size = mbedtls_md_get_size(hc->md_ctx.md_info); + uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 }; + uint8_t *tmp_digest = NULL; + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (hash_size > len) { + if (hash_size > sizeof(block_digest)) + return TEE_ERROR_BAD_STATE; + tmp_digest = block_digest; /* use a tempory buffer */ + } else { + tmp_digest = digest; + } + + if (mbedtls_md_finish(&hc->md_ctx, tmp_digest)) + return TEE_ERROR_BAD_STATE; + + if (hash_size > len) + memcpy(digest, tmp_digest, len); + + return TEE_SUCCESS; +} + +static void mbed_hash_free_ctx(struct crypto_hash_ctx *ctx) +{ + struct mbed_hash_ctx *hc = to_hash_ctx(ctx); + + mbedtls_md_free(&hc->md_ctx); + free(hc); +} + +static void mbed_hash_copy_state(struct crypto_hash_ctx *dst_ctx, + struct crypto_hash_ctx *src_ctx) +{ + struct mbed_hash_ctx *src = to_hash_ctx(src_ctx); + struct mbed_hash_ctx *dst = to_hash_ctx(dst_ctx); + + if (mbedtls_md_clone(&dst->md_ctx, &src->md_ctx)) + panic(); +} + +static const struct crypto_hash_ops mbed_hash_ops = { + .init = mbed_hash_init, + .update = mbed_hash_update, + .final = mbed_hash_final, + .free_ctx = mbed_hash_free_ctx, + .copy_state = mbed_hash_copy_state, +}; + +static TEE_Result mbed_hash_alloc_ctx(struct crypto_hash_ctx **ctx_ret, + mbedtls_md_type_t md_type) +{ + int mbed_res = 0; + struct mbed_hash_ctx *hc = NULL; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); + + if (!md_info) + return TEE_ERROR_NOT_SUPPORTED; + + hc = calloc(1, sizeof(*hc)); + if (!hc) + return TEE_ERROR_OUT_OF_MEMORY; + + hc->hash_ctx.ops = &mbed_hash_ops; + mbed_res = mbedtls_md_setup(&hc->md_ctx, md_info, 0); + if (mbed_res) { + free(hc); + if (mbed_res == MBEDTLS_ERR_MD_ALLOC_FAILED) + return TEE_ERROR_OUT_OF_MEMORY; + return TEE_ERROR_NOT_SUPPORTED; + } + + *ctx_ret = &hc->hash_ctx; + + return TEE_SUCCESS; +} + +#if defined(CFG_CRYPTO_MD5) +TEE_Result crypto_md5_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_MD5); +} +#endif + +#if defined(CFG_CRYPTO_SHA1) +TEE_Result crypto_sha1_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA1); +} +#endif + +#if defined(CFG_CRYPTO_SHA224) +TEE_Result crypto_sha224_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA224); +} +#endif + +#if defined(CFG_CRYPTO_SHA256) +TEE_Result crypto_sha256_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA256); +} +#endif + +#if defined(CFG_CRYPTO_SHA384) +TEE_Result crypto_sha384_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA384); +} +#endif + +#if defined(CFG_CRYPTO_SHA512) +TEE_Result crypto_sha512_alloc_ctx(struct crypto_hash_ctx **ctx) +{ + return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA512); +} +#endif + +#if defined(CFG_CRYPTO_SHA256) +TEE_Result hash_sha256_check(const uint8_t *hash, const uint8_t *data, + size_t data_size) +{ + mbedtls_sha256_context hs; + uint8_t digest[TEE_SHA256_HASH_SIZE] = { 0 }; + + memset(&hs, 0, sizeof(hs)); + mbedtls_sha256_init(&hs); + mbedtls_sha256_starts(&hs, 0); + mbedtls_sha256_update(&hs, data, data_size); + mbedtls_sha256_finish(&hs, digest); + mbedtls_sha256_free(&hs); + + if (consttime_memcmp(digest, hash, sizeof(digest))) + return TEE_ERROR_SECURITY; + return TEE_SUCCESS; +} +#endif + +#if defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, + const unsigned char data[64]) +{ + MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, + MBEDTLS_ERR_SHA1_BAD_INPUT_DATA); + MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL, + MBEDTLS_ERR_SHA1_BAD_INPUT_DATA); + + crypto_accel_sha1_compress(ctx->state, data, 1); + + return 0; +} +#endif /*MBEDTLS_SHA1_PROCESS_ALT*/ + +#if defined(MBEDTLS_SHA256_PROCESS_ALT) +int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, + const unsigned char data[64]) +{ + MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, + MBEDTLS_ERR_SHA256_BAD_INPUT_DATA); + MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL, + MBEDTLS_ERR_SHA256_BAD_INPUT_DATA); + + crypto_accel_sha256_compress(ctx->state, data, 1); + + return 0; +} +#endif /*MBEDTLS_SHA256_PROCESS_ALT*/ + +#if defined(MBEDTLS_SHA512_PROCESS_ALT) +int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, + const unsigned char data[64]) +{ + MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, + MBEDTLS_ERR_SHA512_BAD_INPUT_DATA); + MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL, + MBEDTLS_ERR_SHA512_BAD_INPUT_DATA); + + crypto_accel_sha512_compress(ctx->state, data, 1); + + return 0; +} +#endif /*MBEDTLS_SHA512_PROCESS_ALT*/ diff --git a/optee/optee_os/lib/libmbedtls/core/hmac.c b/optee/optee_os/lib/libmbedtls/core/hmac.c new file mode 100644 index 0000000..391693a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/hmac.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct mbed_hmac_ctx { + struct crypto_mac_ctx mac_ctx; + mbedtls_md_context_t md_ctx; +}; + +static const struct crypto_mac_ops mbed_hmac_ops; + +static struct mbed_hmac_ctx *to_hmac_ctx(struct crypto_mac_ctx *ctx) +{ + assert(ctx && ctx->ops == &mbed_hmac_ops); + + return container_of(ctx, struct mbed_hmac_ctx, mac_ctx); +} + +static TEE_Result mbed_hmac_init(struct crypto_mac_ctx *ctx, + const uint8_t *key, size_t len) +{ + if (mbedtls_md_hmac_starts(&to_hmac_ctx(ctx)->md_ctx, key, len)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_hmac_update(struct crypto_mac_ctx *ctx, + const uint8_t *data, size_t len) +{ + if (mbedtls_md_hmac_update(&to_hmac_ctx(ctx)->md_ctx, data, len)) + return TEE_ERROR_BAD_STATE; + + return TEE_SUCCESS; +} + +static TEE_Result mbed_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, + size_t len) +{ + struct mbed_hmac_ctx *c = to_hmac_ctx(ctx); + size_t hmac_size = mbedtls_md_get_size(c->md_ctx.md_info); + uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 }; + uint8_t *tmp_digest = NULL; + + if (len == 0) + return TEE_ERROR_BAD_PARAMETERS; + + if (hmac_size > len) { + if (hmac_size > sizeof(block_digest)) + return TEE_ERROR_BAD_STATE; + tmp_digest = block_digest; /* use a tempory buffer */ + } else { + tmp_digest = digest; + } + + if (mbedtls_md_hmac_finish(&c->md_ctx, tmp_digest)) + return TEE_ERROR_BAD_STATE; + + if (hmac_size > len) + memcpy(digest, tmp_digest, len); + + return TEE_SUCCESS; +} + +static void mbed_hmac_free_ctx(struct crypto_mac_ctx *ctx) +{ + struct mbed_hmac_ctx *c = to_hmac_ctx(ctx); + + mbedtls_md_free(&c->md_ctx); + free(c); +} + +static void mbed_hmac_copy_state(struct crypto_mac_ctx *dst_ctx, + struct crypto_mac_ctx *src_ctx) +{ + struct mbed_hmac_ctx *src = to_hmac_ctx(src_ctx); + struct mbed_hmac_ctx *dst = to_hmac_ctx(dst_ctx); + + if (mbedtls_md_clone(&dst->md_ctx, &src->md_ctx)) + panic(); +} + +static const struct crypto_mac_ops mbed_hmac_ops = { + .init = mbed_hmac_init, + .update = mbed_hmac_update, + .final = mbed_hmac_final, + .free_ctx = mbed_hmac_free_ctx, + .copy_state = mbed_hmac_copy_state, +}; + +static TEE_Result mbed_hmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, + mbedtls_md_type_t md_type) +{ + int mbed_res = 0; + struct mbed_hmac_ctx *c = NULL; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); + + if (!md_info) + return TEE_ERROR_NOT_SUPPORTED; + + c = calloc(1, sizeof(*c)); + if (!c) + return TEE_ERROR_OUT_OF_MEMORY; + + c->mac_ctx.ops = &mbed_hmac_ops; + mbed_res = mbedtls_md_setup(&c->md_ctx, md_info, 1); + if (mbed_res) { + free(c); + if (mbed_res == MBEDTLS_ERR_MD_ALLOC_FAILED) + return TEE_ERROR_OUT_OF_MEMORY; + return TEE_ERROR_NOT_SUPPORTED; + } + + *ctx_ret = &c->mac_ctx; + + return TEE_SUCCESS; +} + +#if defined(CFG_CRYPTO_MD5) +TEE_Result crypto_hmac_md5_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_MD5); +} +#endif + +#if defined(CFG_CRYPTO_SHA1) +TEE_Result crypto_hmac_sha1_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA1); +} +#endif + +#if defined(CFG_CRYPTO_SHA224) +TEE_Result crypto_hmac_sha224_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA224); +} +#endif + +#if defined(CFG_CRYPTO_SHA256) +TEE_Result crypto_hmac_sha256_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA256); +} +#endif + +#if defined(CFG_CRYPTO_SHA384) +TEE_Result crypto_hmac_sha384_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA384); +} +#endif + +#if defined(CFG_CRYPTO_SHA512) +TEE_Result crypto_hmac_sha512_alloc_ctx(struct crypto_mac_ctx **ctx) +{ + return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA512); +} +#endif diff --git a/optee/optee_os/lib/libmbedtls/core/mbed_helpers.c b/optee/optee_os/lib/libmbedtls/core/mbed_helpers.c new file mode 100644 index 0000000..49d322e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/mbed_helpers.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" + +/* Generate random number 1 <= n < max */ +TEE_Result mbed_gen_random_upto(mbedtls_mpi *n, mbedtls_mpi *max) +{ + size_t sz = mbedtls_mpi_size(max); + bool found = false; + int mres = 0; + + do { + mres = mbedtls_mpi_fill_random(n, sz, mbd_rand, NULL); + if (mres) + return TEE_ERROR_BAD_STATE; + if (mbedtls_mpi_bitlen(n) != 0 && + mbedtls_mpi_cmp_mpi(n, max) == -1) + found = true; + } while (!found); + + return TEE_SUCCESS; +} + diff --git a/optee/optee_os/lib/libmbedtls/core/mbed_helpers.h b/optee/optee_os/lib/libmbedtls/core/mbed_helpers.h new file mode 100644 index 0000000..ffea285 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/mbed_helpers.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#ifndef MBED_HELPERS_H +#define MBED_HELPERS_H + +#include +#include +#include +#include +#include + +static inline int mbd_rand(void *rng_state __unused, unsigned char *output, + size_t len) +{ + if (crypto_rng_read(output, len)) + return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; + return 0; +} + +static inline void mbed_copy_mbedtls_aes_context(mbedtls_aes_context *dst, + mbedtls_aes_context *src) +{ + *dst = *src; +#if !defined(MBEDTLS_AES_ALT) +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + /* + * This build configuration should not occur, but just in case error out + * here. It needs special handling of the rk pointer, see + * mbedtls_aes_setkey_enc(). + */ +#error Do not know how to copy mbedtls_aes_context::rk +#endif + dst->rk = dst->buf; +#endif +} + +TEE_Result mbed_gen_random_upto(mbedtls_mpi *n, mbedtls_mpi *max); +#endif /*MBED_HELPERS_H*/ diff --git a/optee/optee_os/lib/libmbedtls/core/rsa.c b/optee/optee_os/lib/libmbedtls/core/rsa.c new file mode 100644 index 0000000..99b0290 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/rsa.c @@ -0,0 +1,781 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" + +static TEE_Result get_tee_result(int lmd_res) +{ + switch (lmd_res) { + case 0: + return TEE_SUCCESS; + case MBEDTLS_ERR_RSA_PRIVATE_FAILED + + MBEDTLS_ERR_MPI_BAD_INPUT_DATA: + case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: + case MBEDTLS_ERR_RSA_INVALID_PADDING: + case MBEDTLS_ERR_PK_TYPE_MISMATCH: + return TEE_ERROR_BAD_PARAMETERS; + case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: + return TEE_ERROR_SHORT_BUFFER; + default: + return TEE_ERROR_BAD_STATE; + } +} + +static uint32_t tee_algo_to_mbedtls_hash_algo(uint32_t algo) +{ + switch (algo) { +#if defined(CFG_CRYPTO_SHA1) + 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: + return MBEDTLS_MD_SHA1; +#endif +#if defined(CFG_CRYPTO_MD5) + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: + case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5: + case TEE_ALG_MD5: + case TEE_ALG_HMAC_MD5: + return MBEDTLS_MD_MD5; +#endif +#if defined(CFG_CRYPTO_SHA224) + 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_DSA_SHA224: + case TEE_ALG_HMAC_SHA224: + return MBEDTLS_MD_SHA224; +#endif +#if defined(CFG_CRYPTO_SHA256) + 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_DSA_SHA256: + case TEE_ALG_HMAC_SHA256: + return MBEDTLS_MD_SHA256; +#endif +#if defined(CFG_CRYPTO_SHA384) + 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: + return MBEDTLS_MD_SHA384; +#endif +#if defined(CFG_CRYPTO_SHA512) + 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: + return MBEDTLS_MD_SHA512; +#endif + default: + return MBEDTLS_MD_NONE; + } +} + +static void rsa_init_from_key_pair(mbedtls_rsa_context *rsa, + struct rsa_keypair *key) +{ + mbedtls_rsa_init(rsa, 0, 0); + + rsa->E = *(mbedtls_mpi *)key->e; + rsa->N = *(mbedtls_mpi *)key->n; + rsa->D = *(mbedtls_mpi *)key->d; + if (key->p && crypto_bignum_num_bytes(key->p)) { + rsa->P = *(mbedtls_mpi *)key->p; + rsa->Q = *(mbedtls_mpi *)key->q; + rsa->QP = *(mbedtls_mpi *)key->qp; + rsa->DP = *(mbedtls_mpi *)key->dp; + rsa->DQ = *(mbedtls_mpi *)key->dq; + } + rsa->len = mbedtls_mpi_size(&rsa->N); +} + +static void mbd_rsa_free(mbedtls_rsa_context *rsa) +{ + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&rsa->E); + mbedtls_mpi_init(&rsa->N); + mbedtls_mpi_init(&rsa->D); + if (mbedtls_mpi_size(&rsa->P)) { + mbedtls_mpi_init(&rsa->P); + mbedtls_mpi_init(&rsa->Q); + mbedtls_mpi_init(&rsa->QP); + mbedtls_mpi_init(&rsa->DP); + mbedtls_mpi_init(&rsa->DQ); + } + mbedtls_rsa_free(rsa); +} + +TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, + size_t key_size_bits) +__weak __alias("sw_crypto_acipher_alloc_rsa_keypair"); + +TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, + size_t key_size_bits) +{ + memset(s, 0, sizeof(*s)); + s->e = crypto_bignum_allocate(key_size_bits); + if (!s->e) + goto err; + s->d = crypto_bignum_allocate(key_size_bits); + if (!s->d) + goto err; + s->n = crypto_bignum_allocate(key_size_bits); + if (!s->n) + goto err; + s->p = crypto_bignum_allocate(key_size_bits); + if (!s->p) + goto err; + s->q = crypto_bignum_allocate(key_size_bits); + if (!s->q) + goto err; + s->qp = crypto_bignum_allocate(key_size_bits); + if (!s->qp) + goto err; + s->dp = crypto_bignum_allocate(key_size_bits); + if (!s->dp) + goto err; + s->dq = crypto_bignum_allocate(key_size_bits); + if (!s->dq) + goto err; + + return TEE_SUCCESS; +err: + crypto_acipher_free_rsa_keypair(s); + return TEE_ERROR_OUT_OF_MEMORY; +} + +TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, + size_t key_size_bits) +__weak __alias("sw_crypto_acipher_alloc_rsa_public_key"); + +TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, + size_t key_size_bits) +{ + memset(s, 0, sizeof(*s)); + s->e = crypto_bignum_allocate(key_size_bits); + if (!s->e) + return TEE_ERROR_OUT_OF_MEMORY; + s->n = crypto_bignum_allocate(key_size_bits); + if (!s->n) + goto err; + return TEE_SUCCESS; +err: + crypto_bignum_free(s->e); + return TEE_ERROR_OUT_OF_MEMORY; +} + +void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) +__weak __alias("sw_crypto_acipher_free_rsa_public_key"); + +void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) +{ + if (!s) + return; + crypto_bignum_free(s->n); + crypto_bignum_free(s->e); +} + +void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) +__weak __alias("sw_crypto_acipher_free_rsa_keypair"); + +void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) +{ + if (!s) + return; + crypto_bignum_free(s->e); + crypto_bignum_free(s->d); + crypto_bignum_free(s->n); + crypto_bignum_free(s->p); + crypto_bignum_free(s->q); + crypto_bignum_free(s->qp); + crypto_bignum_free(s->dp); + crypto_bignum_free(s->dq); +} + +TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, + size_t key_size) +__weak __alias("sw_crypto_acipher_gen_rsa_key"); + +TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key, + size_t key_size) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_rsa_context rsa; + mbedtls_ctr_drbg_context rngctx; + int lmd_res = 0; + uint32_t e = 0; + + mbedtls_ctr_drbg_init(&rngctx); + if (mbedtls_ctr_drbg_seed(&rngctx, mbd_rand, NULL, NULL, 0)) + return TEE_ERROR_BAD_STATE; + + memset(&rsa, 0, sizeof(rsa)); + mbedtls_rsa_init(&rsa, 0, 0); + + /* get the public exponent */ + mbedtls_mpi_write_binary((mbedtls_mpi *)key->e, + (unsigned char *)&e, sizeof(uint32_t)); + + e = TEE_U32_FROM_BIG_ENDIAN(e); + lmd_res = mbedtls_rsa_gen_key(&rsa, mbedtls_ctr_drbg_random, &rngctx, + key_size, (int)e); + mbedtls_ctr_drbg_free(&rngctx); + if (lmd_res != 0) { + res = get_tee_result(lmd_res); + } else if ((size_t)mbedtls_mpi_bitlen(&rsa.N) != key_size) { + res = TEE_ERROR_BAD_PARAMETERS; + } else { + /* Copy the key */ + crypto_bignum_copy(key->e, (void *)&rsa.E); + crypto_bignum_copy(key->d, (void *)&rsa.D); + crypto_bignum_copy(key->n, (void *)&rsa.N); + crypto_bignum_copy(key->p, (void *)&rsa.P); + + crypto_bignum_copy(key->q, (void *)&rsa.Q); + crypto_bignum_copy(key->qp, (void *)&rsa.QP); + crypto_bignum_copy(key->dp, (void *)&rsa.DP); + crypto_bignum_copy(key->dq, (void *)&rsa.DQ); + + res = TEE_SUCCESS; + } + + mbedtls_rsa_free(&rsa); + + return res; +} + +TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +__weak __alias("sw_crypto_acipher_rsanopad_encrypt"); + +TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_rsa_context rsa; + int lmd_res = 0; + uint8_t *buf = NULL; + unsigned long blen = 0; + unsigned long offset = 0; + + memset(&rsa, 0, sizeof(rsa)); + mbedtls_rsa_init(&rsa, 0, 0); + + rsa.E = *(mbedtls_mpi *)key->e; + rsa.N = *(mbedtls_mpi *)key->n; + + rsa.len = crypto_bignum_num_bytes((void *)&rsa.N); + + blen = CFG_CORE_BIGNUM_MAX_BITS / 8; + buf = malloc(blen); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memset(buf, 0, blen); + memcpy(buf + rsa.len - src_len, src, src_len); + + lmd_res = mbedtls_rsa_public(&rsa, buf, buf); + if (lmd_res != 0) { + FMSG("mbedtls_rsa_public() returned 0x%x", -lmd_res); + res = get_tee_result(lmd_res); + goto out; + } + + /* Remove the zero-padding (leave one zero if buff is all zeroes) */ + offset = 0; + while ((offset < rsa.len - 1) && (buf[offset] == 0)) + offset++; + + if (*dst_len < rsa.len - offset) { + *dst_len = rsa.len - offset; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + *dst_len = rsa.len - offset; + memcpy(dst, buf + offset, *dst_len); +out: + free(buf); + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&rsa.E); + mbedtls_mpi_init(&rsa.N); + mbedtls_rsa_free(&rsa); + + return res; +} + +TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +__weak __alias("sw_crypto_acipher_rsanopad_decrypt"); + +TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, + const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_rsa_context rsa; + int lmd_res = 0; + uint8_t *buf = NULL; + unsigned long blen = 0; + unsigned long offset = 0; + + memset(&rsa, 0, sizeof(rsa)); + rsa_init_from_key_pair(&rsa, key); + + blen = CFG_CORE_BIGNUM_MAX_BITS / 8; + buf = malloc(blen); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + memset(buf, 0, blen); + memcpy(buf + rsa.len - src_len, src, src_len); + + lmd_res = mbedtls_rsa_private(&rsa, NULL, NULL, buf, buf); + if (lmd_res != 0) { + FMSG("mbedtls_rsa_private() returned 0x%x", -lmd_res); + res = get_tee_result(lmd_res); + goto out; + } + + /* Remove the zero-padding (leave one zero if buff is all zeroes) */ + offset = 0; + while ((offset < rsa.len - 1) && (buf[offset] == 0)) + offset++; + + if (*dst_len < rsa.len - offset) { + *dst_len = rsa.len - offset; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + *dst_len = rsa.len - offset; + memcpy(dst, (char *)buf + offset, *dst_len); +out: + if (buf) + free(buf); + mbd_rsa_free(&rsa); + return res; +} + +TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, + struct rsa_keypair *key, + const uint8_t *label __unused, + size_t label_len __unused, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +__weak __alias("sw_crypto_acipher_rsaes_decrypt"); + +TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo, + struct rsa_keypair *key, + const uint8_t *label __unused, + size_t label_len __unused, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + int lmd_padding = 0; + size_t blen = 0; + size_t mod_size = 0; + void *buf = NULL; + mbedtls_rsa_context rsa; + const mbedtls_pk_info_t *pk_info = NULL; + uint32_t md_algo = MBEDTLS_MD_NONE; + + memset(&rsa, 0, sizeof(rsa)); + rsa_init_from_key_pair(&rsa, key); + + /* + * 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. + */ + if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { + mod_size = crypto_bignum_num_bytes(key->n); + blen = mod_size - 11; + lmd_padding = MBEDTLS_RSA_PKCS_V15; + } else { + /* Decoded message is always shorter than encrypted message */ + blen = src_len; + lmd_padding = MBEDTLS_RSA_PKCS_V21; + } + + buf = malloc(blen); + if (!buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if (!pk_info) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + /* + * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will + * not be used in rsa, so skip it here. + */ + if (algo != TEE_ALG_RSAES_PKCS1_V1_5) { + md_algo = tee_algo_to_mbedtls_hash_algo(algo); + if (md_algo == MBEDTLS_MD_NONE) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + } + + mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo); + + if (lmd_padding == MBEDTLS_RSA_PKCS_V15) + lmd_res = pk_info->decrypt_func(&rsa, src, src_len, buf, &blen, + blen, NULL, NULL); + else + lmd_res = pk_info->decrypt_func(&rsa, src, src_len, buf, &blen, + blen, mbd_rand, NULL); + if (lmd_res != 0) { + FMSG("decrypt_func() returned 0x%x", -lmd_res); + res = get_tee_result(lmd_res); + 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); + mbd_rsa_free(&rsa); + return res; +} + +TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, + struct rsa_public_key *key, + const uint8_t *label __unused, + size_t label_len __unused, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +__weak __alias("sw_crypto_acipher_rsaes_encrypt"); + +TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo, + struct rsa_public_key *key, + const uint8_t *label __unused, + size_t label_len __unused, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + int lmd_padding = 0; + size_t mod_size = 0; + mbedtls_rsa_context rsa; + const mbedtls_pk_info_t *pk_info = NULL; + uint32_t md_algo = MBEDTLS_MD_NONE; + + memset(&rsa, 0, sizeof(rsa)); + mbedtls_rsa_init(&rsa, 0, 0); + + rsa.E = *(mbedtls_mpi *)key->e; + rsa.N = *(mbedtls_mpi *)key->n; + + mod_size = crypto_bignum_num_bytes(key->n); + if (*dst_len < mod_size) { + *dst_len = mod_size; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + *dst_len = mod_size; + rsa.len = mod_size; + + if (algo == TEE_ALG_RSAES_PKCS1_V1_5) + lmd_padding = MBEDTLS_RSA_PKCS_V15; + else + lmd_padding = MBEDTLS_RSA_PKCS_V21; + + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if (!pk_info) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + /* + * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will + * not be used in rsa, so skip it here. + */ + if (algo != TEE_ALG_RSAES_PKCS1_V1_5) { + md_algo = tee_algo_to_mbedtls_hash_algo(algo); + if (md_algo == MBEDTLS_MD_NONE) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + } + + mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo); + + lmd_res = pk_info->encrypt_func(&rsa, src, src_len, dst, dst_len, + *dst_len, mbd_rand, NULL); + if (lmd_res != 0) { + FMSG("encrypt_func() returned 0x%x", -lmd_res); + res = get_tee_result(lmd_res); + goto out; + } + res = TEE_SUCCESS; +out: + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&rsa.E); + mbedtls_mpi_init(&rsa.N); + mbedtls_rsa_free(&rsa); + return res; +} + +TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, + int salt_len __unused, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +__weak __alias("sw_crypto_acipher_rsassa_sign"); + +TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, + int salt_len __unused, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + int lmd_padding = 0; + size_t mod_size = 0; + size_t hash_size = 0; + mbedtls_rsa_context rsa; + const mbedtls_pk_info_t *pk_info = NULL; + uint32_t md_algo = 0; + + memset(&rsa, 0, sizeof(rsa)); + rsa_init_from_key_pair(&rsa, key); + + 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: + lmd_padding = MBEDTLS_RSA_PKCS_V15; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: + 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: + lmd_padding = MBEDTLS_RSA_PKCS_V21; + break; + default: + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), + &hash_size); + if (res != TEE_SUCCESS) + goto err; + + if (msg_len != hash_size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + mod_size = crypto_bignum_num_bytes(key->n); + if (*sig_len < mod_size) { + *sig_len = mod_size; + res = TEE_ERROR_SHORT_BUFFER; + goto err; + } + rsa.len = mod_size; + + md_algo = tee_algo_to_mbedtls_hash_algo(algo); + if (md_algo == MBEDTLS_MD_NONE) { + res = TEE_ERROR_NOT_SUPPORTED; + goto err; + } + + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if (!pk_info) { + res = TEE_ERROR_NOT_SUPPORTED; + goto err; + } + + mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo); + + if (lmd_padding == MBEDTLS_RSA_PKCS_V15) + lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig, + sig_len, NULL, NULL); + else + lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig, + sig_len, mbd_rand, NULL); + if (lmd_res != 0) { + FMSG("sign_func failed, returned 0x%x", -lmd_res); + res = get_tee_result(lmd_res); + goto err; + } + res = TEE_SUCCESS; +err: + mbd_rsa_free(&rsa); + return res; +} + +TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, + struct rsa_public_key *key, + int salt_len __unused, + const uint8_t *msg, + size_t msg_len, const uint8_t *sig, + size_t sig_len) +__weak __alias("sw_crypto_acipher_rsassa_verify"); + +TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo, + struct rsa_public_key *key, + int salt_len __unused, + const uint8_t *msg, + size_t msg_len, const uint8_t *sig, + size_t sig_len) +{ + TEE_Result res = TEE_SUCCESS; + int lmd_res = 0; + int lmd_padding = 0; + size_t hash_size = 0; + size_t bigint_size = 0; + mbedtls_rsa_context rsa; + const mbedtls_pk_info_t *pk_info = NULL; + uint32_t md_algo = 0; + struct ftmn ftmn = { }; + unsigned long arg_hash = 0; + + /* + * The caller expects to call crypto_acipher_rsassa_verify(), + * update the hash as needed. + */ + FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify")); + + memset(&rsa, 0, sizeof(rsa)); + mbedtls_rsa_init(&rsa, 0, 0); + + rsa.E = *(mbedtls_mpi *)key->e; + rsa.N = *(mbedtls_mpi *)key->n; + + res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), + &hash_size); + if (res != TEE_SUCCESS) + goto err; + + if (msg_len != hash_size) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + bigint_size = crypto_bignum_num_bytes(key->n); + if (sig_len < bigint_size) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto err; + } + + rsa.len = bigint_size; + + 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: + arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pkcs1_v15_verify"); + lmd_padding = MBEDTLS_RSA_PKCS_V15; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: + 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: + arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pss_verify_ext"); + lmd_padding = MBEDTLS_RSA_PKCS_V21; + break; + default: + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + + md_algo = tee_algo_to_mbedtls_hash_algo(algo); + if (md_algo == MBEDTLS_MD_NONE) { + res = TEE_ERROR_NOT_SUPPORTED; + goto err; + } + + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if (!pk_info) { + res = TEE_ERROR_NOT_SUPPORTED; + goto err; + } + + mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo); + + FTMN_PUSH_LINKED_CALL(&ftmn, arg_hash); + lmd_res = pk_info->verify_func(&rsa, md_algo, msg, msg_len, + sig, sig_len); + if (!lmd_res) + FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, lmd_res); + FTMN_POP_LINKED_CALL(&ftmn); + if (lmd_res != 0) { + FMSG("verify_func failed, returned 0x%x", -lmd_res); + res = TEE_ERROR_SIGNATURE_INVALID; + goto err; + } + res = TEE_SUCCESS; + goto out; + +err: + FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR0, res); +out: + FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res); + /* Reset mpi to skip freeing here, those mpis will be freed with key */ + mbedtls_mpi_init(&rsa.E); + mbedtls_mpi_init(&rsa.N); + mbedtls_rsa_free(&rsa); + return res; +} diff --git a/optee/optee_os/lib/libmbedtls/core/sm2-dsa.c b/optee/optee_os/lib/libmbedtls/core/sm2-dsa.c new file mode 100644 index 0000000..6e6e1d3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/sm2-dsa.c @@ -0,0 +1,268 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2021 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" +#include "sm2-dsa.h" + +/* SM2 uses 256 bit unsigned integers in big endian format */ +#define SM2_INT_SIZE_BYTES 32 + +/* + * GM/T 0003.1‒2012 Part1 2 Section 6.1 + */ +TEE_Result sm2_mbedtls_dsa_sign(uint32_t algo __unused, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_ecp_group grp = { }; + mbedtls_ecp_point x1y1p = { }; + int mres = 0; + mbedtls_mpi k = { }; + mbedtls_mpi e = { }; + mbedtls_mpi r = { }; + mbedtls_mpi s = { }; + mbedtls_mpi tmp = { }; + + if (*sig_len < 2 * SM2_INT_SIZE_BYTES) { + *sig_len = 64; + return TEE_ERROR_SHORT_BUFFER; + } + + mbedtls_mpi_init(&k); + mbedtls_mpi_init(&e); + mbedtls_mpi_init(&r); + mbedtls_mpi_init(&s); + mbedtls_mpi_init(&tmp); + + mbedtls_ecp_point_init(&x1y1p); + + mbedtls_ecp_group_init(&grp); + mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + + /* + * Steps A1 and A2 are the generation of the hash value e from user + * information (ZA) and the message to be signed (M). There are not done + * here since @msg is expected to be the hash value e already. + */ + + /* Step A3: generate random number 1 <= k < n */ + do { + res = mbed_gen_random_upto(&k, &grp.N); + if (res) + goto out; + + res = TEE_ERROR_BAD_STATE; + + /* Step A4: compute (x1, y1) = [k]G */ + + mres = mbedtls_ecp_mul(&grp, &x1y1p, &k, &grp.G, mbd_rand, + NULL); + if (mres) + goto out; + + /* Step A5: compute r = (e + x1) mod n */ + + mbedtls_mpi_read_binary(&e, (unsigned char *)msg, msg_len); + mres = mbedtls_mpi_add_mpi(&r, &e, &x1y1p.X); + if (mres) + goto out; + mres = mbedtls_mpi_mod_mpi(&r, &r, &grp.N); + if (mres) + goto out; + + /* Step A5 (continued): return to A3 if r = 0 or r + k = n */ + + mres = mbedtls_mpi_add_mpi(&tmp, &r, &k); + if (mres) + goto out; + } while (!mbedtls_mpi_cmp_int(&r, 0) || + !mbedtls_mpi_cmp_mpi(&tmp, &grp.N)); + + /* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */ + + mres = mbedtls_mpi_add_int(&s, (mbedtls_mpi *)key->d, 1); + if (mres) + goto out; + mres = mbedtls_mpi_inv_mod(&s, &s, &grp.N); + if (mres) + goto out; + mres = mbedtls_mpi_mul_mpi(&tmp, &r, (mbedtls_mpi *)key->d); + if (mres) + goto out; + mres = mbedtls_mpi_mod_mpi(&tmp, &tmp, &grp.N); + if (mres) + goto out; + mres = mbedtls_mpi_sub_mpi(&tmp, &k, &tmp); + if (mres) + goto out; + mres = mbedtls_mpi_mul_mpi(&s, &s, &tmp); + if (mres) + goto out; + mres = mbedtls_mpi_mod_mpi(&s, &s, &grp.N); + if (mres) + goto out; + + /* Step A7: convert (r, s) to binary for output */ + + *sig_len = 2 * SM2_INT_SIZE_BYTES; + memset(sig, 0, *sig_len); + mres = mbedtls_mpi_write_binary(&r, sig, SM2_INT_SIZE_BYTES); + if (mres) + goto out; + mres = mbedtls_mpi_write_binary(&s, sig + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (mres) + goto out; + + res = TEE_SUCCESS; +out: + mbedtls_ecp_point_free(&x1y1p); + mbedtls_mpi_free(&k); + mbedtls_mpi_free(&e); + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + mbedtls_mpi_free(&tmp); + mbedtls_ecp_group_free(&grp); + return res; +} + +/* + * GM/T 0003.1‒2012 Part1 2 Section 7.1 + */ +TEE_Result sm2_mbedtls_dsa_verify(uint32_t algo __unused, + struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len) +{ + TEE_Result res = TEE_ERROR_BAD_STATE; + mbedtls_ecp_group grp = { }; + mbedtls_mpi rprime = { }; + mbedtls_mpi sprime = { }; + mbedtls_mpi t = { }; + mbedtls_mpi eprime = { }; + mbedtls_mpi R = { }; + mbedtls_ecp_point x1y1p = { }; + mbedtls_ecp_point PA = { }; + int mres = 0; + + if (sig_len != 64) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_mpi_init(&rprime); + mbedtls_mpi_init(&sprime); + mbedtls_mpi_init(&t); + mbedtls_mpi_init(&eprime); + mbedtls_mpi_init(&R); + + mbedtls_ecp_point_init(&x1y1p); + mbedtls_ecp_point_init(&PA); + + mbedtls_ecp_group_init(&grp); + mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + + mres = mbedtls_mpi_read_binary(&rprime, sig, 32); + if (mres) + goto out; + mres = mbedtls_mpi_read_binary(&sprime, sig + 32, 32); + if (mres) + goto out; + + /* Step B1: verify r' in [1, n - 1] */ + + if (mbedtls_mpi_cmp_int(&rprime, 1) < 0 || + mbedtls_mpi_cmp_mpi(&rprime, &grp.N) >= 0) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto out; + } + + /* Step B2: verify s' in [1, n - 1] */ + + if (mbedtls_mpi_cmp_int(&sprime, 1) < 0 || + mbedtls_mpi_cmp_mpi(&sprime, &grp.N) >= 0) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto out; + } + + /* + * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here + * because @msg is supposed to contain the hash value e' already. + */ + + /* Step B5: t = (r' + s') mod n and check t != 0 */ + + mres = mbedtls_mpi_add_mpi(&t, &rprime, &sprime); + if (mres) + goto out; + mres = mbedtls_mpi_mod_mpi(&t, &t, &grp.N); + if (mres) + goto out; + if (!mbedtls_mpi_cmp_int(&t, 0)) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto out; + } + + /* Step B6: (x1', y1') = [s']G + [t]PA */ + + mres = mbedtls_mpi_copy(&PA.X, (mbedtls_mpi *)key->x); + if (mres) + goto out; + mres = mbedtls_mpi_copy(&PA.Y, (mbedtls_mpi *)key->y); + if (mres) + goto out; + mres = mbedtls_mpi_lset(&PA.Z, 1); + if (mres) + goto out; + + mres = mbedtls_ecp_muladd(&grp, &x1y1p, &sprime, &grp.G, &t, &PA); + if (mres) + goto out; + + /* Step B7: compute R = (e' + x1') mod n and verify R == r' */ + + mres = mbedtls_mpi_read_binary(&eprime, msg, msg_len); + if (mres) + goto out; + mres = mbedtls_mpi_add_mpi(&R, &eprime, &x1y1p.X); + if (mres) + goto out; + mres = mbedtls_mpi_mod_mpi(&R, &R, &grp.N); + if (mres) + goto out; + if (mbedtls_mpi_cmp_mpi(&R, &rprime)) { + res = TEE_ERROR_SIGNATURE_INVALID; + goto out; + } + + res = TEE_SUCCESS; +out: + mbedtls_ecp_point_free(&x1y1p); + mbedtls_ecp_point_free(&PA); + mbedtls_mpi_free(&rprime); + mbedtls_mpi_free(&sprime); + mbedtls_mpi_free(&t); + mbedtls_mpi_free(&eprime); + mbedtls_mpi_free(&R); + mbedtls_ecp_group_free(&grp); + return res; +} diff --git a/optee/optee_os/lib/libmbedtls/core/sm2-dsa.h b/optee/optee_os/lib/libmbedtls/core/sm2-dsa.h new file mode 100644 index 0000000..a7b22ea --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/sm2-dsa.h @@ -0,0 +1,20 @@ + +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021 Huawei Technologies Co., Ltd + */ + +#ifndef _SM2_DSA_H_ + +#include +#include +#include + +TEE_Result sm2_mbedtls_dsa_sign(uint32_t algo, struct ecc_keypair *key, + const uint8_t *msg, size_t msg_len, + uint8_t *sig, size_t *sig_len); + +TEE_Result sm2_mbedtls_dsa_verify(uint32_t algo, struct ecc_public_key *key, + const uint8_t *msg, size_t msg_len, + const uint8_t *sig, size_t sig_len); +#endif /* _SM2_DSA_H_ */ diff --git a/optee/optee_os/lib/libmbedtls/core/sm2-kep.c b/optee/optee_os/lib/libmbedtls/core/sm2-kep.c new file mode 100644 index 0000000..46f994e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/sm2-kep.c @@ -0,0 +1,499 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020-21 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" + +/* SM2 uses 256 bit unsigned integers in big endian format */ +#define SM2_INT_SIZE_BYTES 32 + +/* The public x and y values extracted from a public or private ECC key */ +struct key_xy { + mbedtls_mpi *x; + mbedtls_mpi *y; +}; + +/* + * Compute a hash of a user's identity and public key + * For user A: ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) + */ +static TEE_Result sm2_kep_compute_Z(const mbedtls_ecp_group *grp, uint8_t *Z, + size_t Zlen, const uint8_t *id, + size_t idlen, struct key_xy *key) +{ + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t ENTLEN[2] = { }; + uint8_t buf[SM2_INT_SIZE_BYTES] = { }; + void *ctx = NULL; + int mres = 0; + + if (Zlen < TEE_SM3_HASH_SIZE) + return TEE_ERROR_SHORT_BUFFER; + + /* + * ENTLEN is the length in bits if the user's distinguished identifier + * encoded over 16 bits in big endian format. + */ + ENTLEN[0] = (idlen * 8) >> 8; + ENTLEN[1] = idlen * 8; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + goto out; + + res = crypto_hash_init(ctx); + if (res) + goto out; + + res = crypto_hash_update(ctx, ENTLEN, sizeof(ENTLEN)); + if (res) + goto out; + + res = crypto_hash_update(ctx, id, idlen); + if (res) + goto out; + + mres = mbedtls_mpi_write_binary(&grp->A, buf, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mres = mbedtls_mpi_write_binary(&grp->B, buf, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mres = mbedtls_mpi_write_binary(&grp->G.X, buf, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mres = mbedtls_mpi_write_binary(&grp->G.Y, buf, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mres = mbedtls_mpi_write_binary(key->x, buf, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + mres = mbedtls_mpi_write_binary(key->y, buf, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + res = crypto_hash_final(ctx, Z, TEE_SM3_HASH_SIZE); +out: + crypto_hash_free_ctx(ctx); + return res; +} + +/* + * Compute a verification value, to be checked against the value sent by the + * peer. + * On the initiator's side: + * S1 = SM3(0x02 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2)) + * On the responder's side: + * S2 = SM3(0x03 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2)) + */ +static TEE_Result sm2_kep_compute_S(uint8_t *S, size_t S_len, uint8_t flag, + mbedtls_ecp_point *UV, const uint8_t *ZAZB, + size_t ZAZB_len, + struct key_xy *initiator_eph_key, + struct key_xy *responder_eph_key) +{ + uint8_t hash[TEE_SM3_HASH_SIZE] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint8_t buf[SM2_INT_SIZE_BYTES]; + void *ctx = NULL; + int mres = 0; + + if (S_len < TEE_SM3_HASH_SIZE) + return TEE_ERROR_SHORT_BUFFER; + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + goto out; + + /* Compute the inner hash */ + + res = crypto_hash_init(ctx); + if (res) + goto out; + + /* xU or xV */ + mres = mbedtls_mpi_write_binary(&UV->X, buf, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* ZA || ZB */ + res = crypto_hash_update(ctx, ZAZB, ZAZB_len); + if (res) + goto out; + + /* x1 */ + mres = mbedtls_mpi_write_binary(initiator_eph_key->x, buf, + SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* y1 */ + mres = mbedtls_mpi_write_binary(initiator_eph_key->y, buf, + SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* x2 */ + mres = mbedtls_mpi_write_binary(responder_eph_key->x, buf, + SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* y2 */ + mres = mbedtls_mpi_write_binary(responder_eph_key->y, buf, + SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + res = crypto_hash_final(ctx, hash, sizeof(hash)); + if (res) + goto out; + + /* Now compute S */ + + res = crypto_hash_init(ctx); + if (res) + goto out; + + /* 0x02 or 0x03 */ + res = crypto_hash_update(ctx, &flag, sizeof(flag)); + if (res) + goto out; + + /* yU or yV */ + mres = mbedtls_mpi_write_binary(&UV->Y, buf, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + res = crypto_hash_update(ctx, buf, sizeof(buf)); + if (res) + goto out; + + /* Inner SM3(...) */ + res = crypto_hash_update(ctx, hash, sizeof(hash)); + if (res) + goto out; + + res = crypto_hash_final(ctx, S, TEE_SM3_HASH_SIZE); + +out: + crypto_hash_free_ctx(ctx); + return res; + +} + +static void extract_xy_from_keypair(struct key_xy *xy, + const struct ecc_keypair *pair) +{ + xy->x = (mbedtls_mpi *)pair->x; + xy->y = (mbedtls_mpi *)pair->y; + /* Other fields are not used */ +} + +static void extract_xy_from_public_key(struct key_xy *xy, + const struct ecc_public_key *from) +{ + xy->x = (mbedtls_mpi *)from->x; + xy->y = (mbedtls_mpi *)from->y; +} + +/* + * GM/T 0003.1‒2012 Part 3 Section 6.1 + * Key exchange protocol + */ +TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key, + struct ecc_keypair *my_eph_key, + struct ecc_public_key *peer_key, + struct ecc_public_key *peer_eph_key, + struct sm2_kep_parms *p) +{ + /* + * Variable names and documented steps reflect the initator side (user A + * in the spec), but the other side is quite similar hence only one + * function. + */ + uint8_t xUyUZAZB[2 * SM2_INT_SIZE_BYTES + 2 * TEE_SM3_HASH_SIZE] = { }; + struct key_xy initiator_eph_key = { }; + struct key_xy responder_eph_key = { }; + struct key_xy initiator_key = { }; + struct key_xy responder_key = { }; + TEE_Result res = TEE_ERROR_BAD_STATE; + uint8_t tmp[SM2_INT_SIZE_BYTES] = { }; + mbedtls_ecp_group grp = { }; + mbedtls_ecp_point PB = { }; + mbedtls_ecp_point RB = { }; + mbedtls_ecp_point U = { }; + mbedtls_mpi x1bar = { }; + mbedtls_mpi x2bar = { }; + mbedtls_mpi tA = { }; + mbedtls_mpi h = { }; + mbedtls_mpi htA = { }; + mbedtls_mpi one = { }; + int mres = 0; + + if (p->is_initiator) { + extract_xy_from_keypair(&initiator_eph_key, my_eph_key); + extract_xy_from_public_key(&responder_eph_key, peer_eph_key); + extract_xy_from_keypair(&initiator_key, my_key); + extract_xy_from_public_key(&responder_key, peer_key); + } else { + extract_xy_from_public_key(&initiator_eph_key, peer_eph_key); + extract_xy_from_keypair(&responder_eph_key, my_eph_key); + extract_xy_from_public_key(&initiator_key, peer_key); + extract_xy_from_keypair(&responder_key, my_key); + } + + mbedtls_mpi_init(&x1bar); + mbedtls_mpi_init(&x2bar); + mbedtls_mpi_init(&tA); + mbedtls_mpi_init(&h); + mbedtls_mpi_init(&htA); + mbedtls_mpi_init(&one); + + mbedtls_ecp_point_init(&PB); + mbedtls_ecp_point_init(&RB); + mbedtls_ecp_point_init(&U); + + mbedtls_ecp_group_init(&grp); + mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); + if (mres) + goto out; + + /* + * Steps A1-A3 are supposedly done already (generate ephemeral key, send + * it to peer). + * Step A4: (x1, y1) = RA; x1bar = 2^w + (x1 & (2^w - 1)) + */ + + mres = mbedtls_mpi_write_binary((mbedtls_mpi *)my_eph_key->x, tmp, + SM2_INT_SIZE_BYTES); + if (mres) + goto out; + tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80; + mres = mbedtls_mpi_read_binary(&x1bar, tmp + SM2_INT_SIZE_BYTES / 2, + SM2_INT_SIZE_BYTES / 2); + if (mres) + goto out; + + /* Step A5: tA = (dA + x1bar * rA) mod n */ + + mres = mbedtls_mpi_mul_mpi(&tA, &x1bar, (mbedtls_mpi *)my_eph_key->d); + if (mres) + goto out; + mres = mbedtls_mpi_mod_mpi(&tA, &tA, &grp.N); + if (mres) + goto out; + mres = mbedtls_mpi_add_mpi(&tA, &tA, (mbedtls_mpi *)my_key->d); + if (mres) + goto out; + mres = mbedtls_mpi_mod_mpi(&tA, &tA, &grp.N); + if (mres) + goto out; + + /* Step A6: verify whether RB verifies the curve equation */ + + mbedtls_mpi_copy(&RB.X, (mbedtls_mpi *)peer_eph_key->x); + mbedtls_mpi_copy(&RB.Y, (mbedtls_mpi *)peer_eph_key->y); + mbedtls_mpi_lset(&RB.Z, 1); + mres = mbedtls_ecp_check_pubkey(&grp, &RB); + if (mres) + goto out; + + /* Step A6 (continued): (x2, y2) = RB; x2bar = 2^w + (x2 & (2^w - 1)) */ + + mres = mbedtls_mpi_write_binary((mbedtls_mpi *)peer_eph_key->x, tmp, + SM2_INT_SIZE_BYTES); + if (mres) + goto out; + tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80; + mres = mbedtls_mpi_read_binary(&x2bar, tmp + SM2_INT_SIZE_BYTES / 2, + SM2_INT_SIZE_BYTES / 2); + if (mres) + goto out; + + /* Step A7: compute U = [h.tA](PB + [x2bar]RB) and check for infinity */ + + mres = mbedtls_mpi_copy(&PB.X, (mbedtls_mpi *)peer_key->x); + if (mres) + goto out; + mres = mbedtls_mpi_copy(&PB.Y, (mbedtls_mpi *)peer_key->y); + if (mres) + goto out; + mres = mbedtls_mpi_lset(&PB.Z, 1); + if (mres) + goto out; + mres = mbedtls_mpi_lset(&one, 1); + if (mres) + goto out; + + mres = mbedtls_ecp_muladd(&grp, &U, &one, &PB, &x2bar, &RB); + if (mres) + goto out; + + /* Note: the cofactor for SM2 is 1 so [h.tA] == tA */ + mres = mbedtls_ecp_mul(&grp, &U, &tA, &U, mbd_rand, NULL); + if (mres) + goto out; + + /* + * "Point is zero" is same as "point is at infinity". Returns 1 if + * point is zero, < 0 on error and 0 if point is non-zero. + */ + mres = mbedtls_ecp_is_zero(&U); + if (mres) + goto out; + + /* Step A8: compute KA = KDF(xU || yU || ZA || ZB, klen) */ + + /* xU */ + mres = mbedtls_mpi_write_binary(&U.X, xUyUZAZB, SM2_INT_SIZE_BYTES); + if (mres) + goto out; + + /* yU */ + mres = mbedtls_mpi_write_binary(&U.Y, xUyUZAZB + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (mres) + goto out; + + /* ZA */ + res = sm2_kep_compute_Z(&grp, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, + TEE_SM3_HASH_SIZE, p->initiator_id, + p->initiator_id_len, &initiator_key); + if (res) + goto out; + + /* ZB */ + res = sm2_kep_compute_Z(&grp, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES + + TEE_SM3_HASH_SIZE, + TEE_SM3_HASH_SIZE, p->responder_id, + p->responder_id_len, &responder_key); + if (res) + goto out; + + res = sm2_kdf(xUyUZAZB, sizeof(xUyUZAZB), p->out, p->out_len); + if (res) + goto out; + + /* Step A9: compute S1 and check S1 == SB */ + + if (p->conf_in) { + uint8_t S1[TEE_SM3_HASH_SIZE] = { }; + uint8_t flag = p->is_initiator ? 0x02 : 0x03; + + if (p->conf_in_len < TEE_SM3_HASH_SIZE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + res = sm2_kep_compute_S(S1, sizeof(S1), flag, &U, + xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, + 2 * SM2_INT_SIZE_BYTES, + &initiator_eph_key, &responder_eph_key); + if (res) + goto out; + + if (consttime_memcmp(S1, p->conf_in, sizeof(S1))) { + /* Verification failed */ + res = TEE_ERROR_BAD_STATE; + goto out; + } + } + + /* Step A10: compute SA */ + + if (p->conf_out) { + uint8_t flag = p->is_initiator ? 0x03 : 0x02; + + if (p->conf_out_len < TEE_SM3_HASH_SIZE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = sm2_kep_compute_S(p->conf_out, TEE_SM3_HASH_SIZE, flag, + &U, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, + 2 * SM2_INT_SIZE_BYTES, + &initiator_eph_key, &responder_eph_key); + } +out: + mbedtls_mpi_free(&x1bar); + mbedtls_mpi_free(&x2bar); + mbedtls_mpi_free(&tA); + mbedtls_mpi_free(&h); + mbedtls_mpi_free(&htA); + mbedtls_mpi_free(&one); + mbedtls_ecp_point_free(&PB); + mbedtls_ecp_point_free(&RB); + mbedtls_ecp_point_free(&U); + mbedtls_ecp_group_free(&grp); + return res; +} diff --git a/optee/optee_os/lib/libmbedtls/core/sm2-pke.c b/optee/optee_os/lib/libmbedtls/core/sm2-pke.c new file mode 100644 index 0000000..e1c3d23 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/sm2-pke.c @@ -0,0 +1,452 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019-2021 Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mbed_helpers.h" +#include "sm2-pke.h" + +/* SM2 uses 256 bit unsigned integers in big endian format */ +#define SM2_INT_SIZE_BYTES 32 + +static TEE_Result +sm2_uncompressed_bytes_to_point(const mbedtls_ecp_group *grp, + mbedtls_ecp_point *p, const uint8_t *x1y1, + size_t max_size, size_t *consumed) +{ + uint8_t *ptr = (uint8_t *)x1y1; + int mres = 0; + + if (max_size < (size_t)(2 * SM2_INT_SIZE_BYTES)) + return TEE_ERROR_BAD_PARAMETERS; + + mres = mbedtls_mpi_read_binary(&p->X, ptr, SM2_INT_SIZE_BYTES); + if (mres) + return TEE_ERROR_BAD_PARAMETERS; + + ptr += SM2_INT_SIZE_BYTES; + + mres = mbedtls_mpi_read_binary(&p->Y, ptr, SM2_INT_SIZE_BYTES); + if (mres) + return TEE_ERROR_BAD_PARAMETERS; + + mres = mbedtls_mpi_lset(&p->Z, 1); + if (mres) + return TEE_ERROR_BAD_PARAMETERS; + + mres = mbedtls_ecp_check_pubkey(grp, p); + if (mres) + return TEE_ERROR_BAD_PARAMETERS; + + *consumed = 2 * SM2_INT_SIZE_BYTES + 1; /* PC */ + + return TEE_SUCCESS; +} + +/* + * GM/T 0003.1‒2012 Part 1 Section 4.2.9 + * Conversion of a byte string @buf to a point @p. Makes sure @p is on the curve + * defined by domain parameters @dp. + * Note: only the uncompressed form is supported. Uncompressed and hybrid forms + * are TBD. + */ +static TEE_Result sm2_bytes_to_point(const mbedtls_ecp_group *grp, + mbedtls_ecp_point *p, const uint8_t *buf, + size_t max_size, size_t *consumed) +{ + uint8_t PC = 0; + + if (!max_size) + return TEE_ERROR_BAD_PARAMETERS; + + PC = buf[0]; + + switch (PC) { + case 0x02: + case 0x03: + /* Compressed form */ + return TEE_ERROR_NOT_SUPPORTED; + case 0x04: + /* Uncompressed form */ + return sm2_uncompressed_bytes_to_point(grp, p, buf + 1, + max_size - 1, consumed); + case 0x06: + case 0x07: + /* Hybrid form */ + return TEE_ERROR_NOT_SUPPORTED; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_ERROR_GENERIC; +} + +static bool is_zero(const uint8_t *buf, size_t size) +{ + uint8_t v = 0; + size_t i = 0; + + for (i = 0; i < size; i++) + v |= buf[i]; + + return !v; +} + +/* + * GM/T 0003.1‒2012 Part 4 Section 7.1 + * Decryption algorithm + */ +TEE_Result sm2_mbedtls_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t x2y2[64] = { }; + mbedtls_ecp_point C1 = { }; + size_t C1_len = 0; + mbedtls_ecp_point x2y2p = { }; + mbedtls_ecp_group grp = { }; + void *ctx = NULL; + int mres = 0; + uint8_t *t = NULL; + size_t C2_len = 0; + size_t i = 0; + size_t out_len = 0; + uint8_t *eom = NULL; + uint8_t u[TEE_SM3_HASH_SIZE] = { }; + + /* + * Input buffer src is (C1 || C2 || C3) + * - C1 represents a point (should be on the curve) + * - C2 is the encrypted message + * - C3 is a SM3 hash + */ + + mbedtls_ecp_point_init(&C1); + mbedtls_ecp_point_init(&x2y2p); + + mbedtls_ecp_group_init(&grp); + mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + + /* Step B1: read and validate point C1 from encrypted message */ + + res = sm2_bytes_to_point(&grp, &C1, src, src_len, &C1_len); + if (res) + goto out; + + /* + * Step B2: S = [h]C1, the cofactor h is 1 for SM2 so S == C1. + * The fact that S is on the curve has already been checked in + * sm2_bytes_to_point(). + */ + + /* Step B3: (x2, y2) = [dB]C1 */ + + mres = mbedtls_ecp_mul(&grp, &x2y2p, (mbedtls_mpi *)key->d, &C1, + mbd_rand, NULL); + if (mres) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + if (mbedtls_mpi_size(&x2y2p.X) > SM2_INT_SIZE_BYTES || + mbedtls_mpi_size(&x2y2p.Y) > SM2_INT_SIZE_BYTES) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + mres = mbedtls_mpi_write_binary(&x2y2p.X, x2y2, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + mres = mbedtls_mpi_write_binary(&x2y2p.Y, x2y2 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step B4: t = KDF(x2 || y2, klen) */ + + /* C = C1 || C2 || C3 */ + if (src_len <= C1_len + TEE_SM3_HASH_SIZE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + C2_len = src_len - C1_len - TEE_SM3_HASH_SIZE; + + t = calloc(1, C2_len); + if (!t) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = sm2_kdf(x2y2, sizeof(x2y2), t, C2_len); + if (res) + goto out; + + if (is_zero(t, C2_len)) { + res = TEE_ERROR_CIPHERTEXT_INVALID; + goto out; + } + + /* Step B5: get C2 from C and compute Mprime = C2 (+) t */ + + out_len = MIN(*dst_len, C2_len); + for (i = 0; i < out_len; i++) + dst[i] = src[C1_len + i] ^ t[i]; + *dst_len = out_len; + if (out_len < C2_len) { + eom = calloc(1, C2_len - out_len); + if (!eom) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + for (i = out_len; i < C2_len; i++) + eom[i - out_len] = src[C1_len + i] ^ t[i]; + } + + /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */ + + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + goto out; + res = crypto_hash_init(ctx); + if (res) + goto out; + res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); + if (res) + goto out; + res = crypto_hash_update(ctx, dst, out_len); + if (res) + goto out; + if (out_len < C2_len) { + res = crypto_hash_update(ctx, eom, C2_len - out_len); + if (res) + goto out; + } + res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (res) + goto out; + res = crypto_hash_final(ctx, u, sizeof(u)); + if (res) + goto out; + + if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) { + res = TEE_ERROR_CIPHERTEXT_INVALID; + goto out; + } +out: + free(eom); + free(t); + crypto_hash_free_ctx(ctx); + mbedtls_ecp_point_free(&C1); + mbedtls_ecp_point_free(&x2y2p); + mbedtls_ecp_group_free(&grp); + return res; +} + +/* + * GM/T 0003.1‒2012 Part 1 Section 4.2.8 + * Conversion of point @p to a byte string @buf (uncompressed form). + */ +static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size, + const mbedtls_ecp_point *p) +{ + size_t xsize = mbedtls_mpi_size(&p->X); + size_t ysize = mbedtls_mpi_size(&p->Y); + size_t sz = 2 * SM2_INT_SIZE_BYTES + 1; + int mres = 0; + + if (xsize > SM2_INT_SIZE_BYTES || ysize > SM2_INT_SIZE_BYTES || + *size < sz) + return TEE_ERROR_BAD_STATE; + + memset(buf, 0, sz); + buf[0] = 0x04; /* Uncompressed form indicator */ + mres = mbedtls_mpi_write_binary(&p->X, buf + 1, SM2_INT_SIZE_BYTES); + if (mres) + return TEE_ERROR_BAD_STATE; + mres = mbedtls_mpi_write_binary(&p->Y, buf + 1 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (mres) + return TEE_ERROR_BAD_STATE; + + *size = sz; + + return TEE_SUCCESS; +} + +/* + * GM/T 0003.1‒2012 Part 4 Section 6.1 + * Encryption algorithm + */ +TEE_Result sm2_mbedtls_pke_encrypt(struct ecc_public_key *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_ecp_group grp = { }; + mbedtls_ecp_point x2y2p = { }; + mbedtls_ecp_point PB = { }; + mbedtls_ecp_point C1 = { }; + uint8_t x2y2[64] = { }; + uint8_t *t = NULL; + int mres = 0; + mbedtls_mpi k = { }; + size_t C1_len = 0; + void *ctx = NULL; + size_t i = 0; + + mbedtls_mpi_init(&k); + + mbedtls_ecp_point_init(&x2y2p); + mbedtls_ecp_point_init(&PB); + mbedtls_ecp_point_init(&C1); + + mbedtls_ecp_group_init(&grp); + mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); + if (mres) { + res = TEE_ERROR_GENERIC; + goto out; + } + + /* Step A1: generate random number 1 <= k < n */ + + res = mbed_gen_random_upto(&k, &grp.N); + if (res) + goto out; + + /* Step A2: compute C1 = [k]G */ + + mres = mbedtls_ecp_mul(&grp, &C1, &k, &grp.G, mbd_rand, NULL); + if (mres) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* + * Step A3: compute S = [h]PB and check for infinity. + * The cofactor h is 1 for SM2 so S == PB, nothing to do. + */ + + /* Step A4: compute (x2, y2) = [k]PB */ + + mbedtls_mpi_copy(&PB.X, (mbedtls_mpi *)key->x); + mbedtls_mpi_copy(&PB.Y, (mbedtls_mpi *)key->y); + mbedtls_mpi_lset(&PB.Z, 1); + + mres = mbedtls_ecp_mul(&grp, &x2y2p, &k, &PB, mbd_rand, NULL); + if (mres) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + if (mbedtls_mpi_size(&x2y2p.X) > SM2_INT_SIZE_BYTES || + mbedtls_mpi_size(&x2y2p.Y) > SM2_INT_SIZE_BYTES) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + mres = mbedtls_mpi_write_binary(&x2y2p.X, x2y2, SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + mres = mbedtls_mpi_write_binary(&x2y2p.Y, x2y2 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (mres) { + res = TEE_ERROR_BAD_STATE; + goto out; + } + + /* Step A5: compute t = KDF(x2 || y2, klen) */ + + t = calloc(1, src_len); + if (!t) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = sm2_kdf(x2y2, sizeof(x2y2), t, src_len); + if (res) + goto out; + + if (is_zero(t, src_len)) { + res = TEE_ERROR_CIPHERTEXT_INVALID; + goto out; + } + + /* + * Steps A6, A7, A8: + * Compute C2 = M (+) t + * Compute C3 = Hash(x2 || M || y2) + * Output C = C1 || C2 || C3 + */ + + /* C1 */ + C1_len = *dst_len; + res = sm2_point_to_bytes(dst, &C1_len, &C1); + if (res) + goto out; + + if (*dst_len < C1_len + src_len + TEE_SM3_HASH_SIZE) { + *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + /* C2 */ + for (i = 0; i < src_len; i++) + dst[i + C1_len] = src[i] ^ t[i]; + + /* C3 */ + res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); + if (res) + goto out; + res = crypto_hash_init(ctx); + if (res) + goto out; + res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); + if (res) + goto out; + res = crypto_hash_update(ctx, src, src_len); + if (res) + goto out; + res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, + SM2_INT_SIZE_BYTES); + if (res) + goto out; + res = crypto_hash_final(ctx, dst + C1_len + src_len, TEE_SM3_HASH_SIZE); + if (res) + goto out; + + *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; +out: + crypto_hash_free_ctx(ctx); + free(t); + mbedtls_ecp_point_free(&x2y2p); + mbedtls_ecp_point_free(&PB); + mbedtls_ecp_point_free(&C1); + mbedtls_ecp_group_free(&grp); + mbedtls_mpi_free(&k); + return res; +} diff --git a/optee/optee_os/lib/libmbedtls/core/sm2-pke.h b/optee/optee_os/lib/libmbedtls/core/sm2-pke.h new file mode 100644 index 0000000..7e8d013 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/sm2-pke.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021 Huawei Technologies Co., Ltd + */ + +#ifndef _SM2_PKE_H_ + +#include +#include +#include + +TEE_Result sm2_mbedtls_pke_encrypt(struct ecc_public_key *key, + const uint8_t *src, size_t src_len, + uint8_t *dst, size_t *dst_len); + +TEE_Result sm2_mbedtls_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, + size_t src_len, uint8_t *dst, + size_t *dst_len); +#endif /* _SM2_PKE_H_ */ diff --git a/optee/optee_os/lib/libmbedtls/core/sub.mk b/optee/optee_os/lib/libmbedtls/core/sub.mk new file mode 100644 index 0000000..9ab4ceb --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/sub.mk @@ -0,0 +1,32 @@ +srcs-y += mbed_helpers.c +srcs-y += tomcrypt.c +srcs-$(call cfg-one-enabled, CFG_CRYPTO_MD5 CFG_CRYPTO_SHA1 CFG_CRYPTO_SHA224 \ + CFG_CRYPTO_SHA256 CFG_CRYPTO_SHA384 \ + CFG_CRYPTO_SHA512) += hash.c + +ifeq ($(CFG_CRYPTO_AES),y) +srcs-y += aes.c +srcs-$(CFG_CRYPTO_ECB) += aes_ecb.c +srcs-$(CFG_CRYPTO_CBC) += aes_cbc.c +srcs-$(CFG_CRYPTO_CTR) += aes_ctr.c +endif +ifeq ($(CFG_CRYPTO_DES),y) +srcs-$(CFG_CRYPTO_ECB) += des_ecb.c +srcs-$(CFG_CRYPTO_ECB) += des3_ecb.c +srcs-$(CFG_CRYPTO_CBC) += des_cbc.c +srcs-$(CFG_CRYPTO_CBC) += des3_cbc.c +endif + +srcs-$(CFG_CRYPTO_HMAC) += hmac.c +srcs-$(CFG_CRYPTO_CMAC) += cmac.c + +ifneq ($(CFG_CRYPTO_DSA),y) +srcs-$(call cfg-one-enabled, CFG_CRYPTO_RSA CFG_CRYPTO_DH \ + CFG_CRYPTO_ECC) += bignum.c +endif +srcs-$(CFG_CRYPTO_RSA) += rsa.c +srcs-$(CFG_CRYPTO_DH) += dh.c +srcs-$(CFG_CRYPTO_ECC) += ecc.c +srcs-$(CFG_CRYPTO_SM2_DSA) += sm2-dsa.c +srcs-$(CFG_CRYPTO_SM2_KEP) += sm2-kep.c +srcs-$(CFG_CRYPTO_SM2_PKE) += sm2-pke.c diff --git a/optee/optee_os/lib/libmbedtls/core/tomcrypt.c b/optee/optee_os/lib/libmbedtls/core/tomcrypt.c new file mode 100644 index 0000000..049d9f3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/core/tomcrypt.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2018, ARM Limited + * Copyright (C) 2019, Linaro Limited + */ + +#include +#include + +TEE_Result crypto_init(void) +{ + tomcrypt_init(); + + return TEE_SUCCESS; +} diff --git a/optee/optee_os/lib/libmbedtls/include/aes_alt.h b/optee/optee_os/lib/libmbedtls/include/aes_alt.h new file mode 100644 index 0000000..88a7103 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/include/aes_alt.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2020, Linaro Limited */ + +#ifndef __MBEDTLS_AES_ALT_H +#define __MBEDTLS_AES_ALT_H + +typedef struct mbedtls_aes_context { + uint32_t key[60]; + unsigned int round_count; +} mbedtls_aes_context; + +#endif /*__MBEDTLS_AES_ALT_H*/ diff --git a/optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h b/optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h new file mode 100644 index 0000000..d633370 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/include/mbedtls_config_kernel.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited */ +#ifndef __MBEDTLS_CONFIG_KERNEL_H +#define __MBEDTLS_CONFIG_KERNEL_H + +#ifdef ARM32 +#define MBEDTLS_HAVE_INT32 +#endif +#ifdef ARM64 +#define MBEDTLS_HAVE_INT64 +#endif +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_GENPRIME + +/* Test if Mbedtls is the primary crypto lib */ +#ifdef CFG_CRYPTOLIB_NAME_mbedtls + +#if defined(CFG_CRYPTO_MD5) +#define MBEDTLS_MD5_C +#define MBEDTLS_MD_C +#endif + +#if defined(CFG_CRYPTO_SHA1) +#define MBEDTLS_SHA1_C +#define MBEDTLS_MD_C +#if defined(CFG_CORE_CRYPTO_SHA1_ACCEL) +#define MBEDTLS_SHA1_PROCESS_ALT +#endif +#endif + +#if defined(CFG_CRYPTO_SHA224) || defined(CFG_CRYPTO_SHA256) +#define MBEDTLS_SHA256_C +#define MBEDTLS_MD_C +#if defined(CFG_CORE_CRYPTO_SHA256_ACCEL) +#define MBEDTLS_SHA256_PROCESS_ALT +#endif +#endif + +#if defined(CFG_CRYPTO_SHA384) || defined(CFG_CRYPTO_SHA512) +#define MBEDTLS_SHA512_C +#define MBEDTLS_MD_C +#if defined(CFG_CORE_CRYPTO_SHA512_ACCEL) +#define MBEDTLS_SHA512_PROCESS_ALT +#endif +#endif + +#if defined(CFG_CRYPTO_HMAC) +#define MBEDTLS_MD_C +#endif + +#if defined(CFG_CRYPTO_AES) +#define MBEDTLS_AES_C +#define MBEDTLS_AES_ROM_TABLES +#if defined(CFG_CORE_CRYPTO_AES_ACCEL) +#define MBEDTLS_AES_ALT +#endif +#endif + +#if defined(CFG_CRYPTO_DES) +#define MBEDTLS_DES_C +#endif + +#if defined(CFG_CRYPTO_CBC) +#define MBEDTLS_CIPHER_MODE_CBC +#endif + +#if defined(CFG_CRYPTO_CTR) +#define MBEDTLS_CIPHER_MODE_CTR +#endif + +#if defined(CFG_CRYPTO_CMAC) +#define MBEDTLS_CMAC_C +#define MBEDTLS_CIPHER_C +#endif + +#if defined(CFG_CRYPTO_RSA) || defined(CFG_CRYPTO_DH) || defined(CFG_CRYPTO_ECC) +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_PKCS1_V21 +#define MBEDTLS_PK_C +#define MBEDTLS_GENPRIME +#define MBEDTLS_CTR_DRBG_C +#endif + +#if defined(CFG_CRYPTO_RSA) +#define MBEDTLS_RSA_C +#define MBEDTLS_RSA_NO_CRT +#endif + +#if defined(CFG_CRYPTO_RSA) || defined(CFG_CRYPTO_ECC) +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif + +#if defined(CFG_CRYPTO_DH) +#define MBEDTLS_DHM_C +#endif + +#if defined(CFG_CRYPTO_ECC) +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDH_LEGACY_CONTEXT +#if defined(CFG_CRYPTO_DSA) || defined(CFG_CRYPTO_SM2_PKE) || \ + defined(CFG_CRYPTO_SM2_KEP) +#define MBEDTLS_ECP_DP_SM2_ENABLED +#endif +#endif + +#endif /*CFG_CRYPTOLIB_NAME_mbedtls*/ + +#include + +#endif /* __MBEDTLS_CONFIG_KERNEL_H */ diff --git a/optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h b/optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h new file mode 100644 index 0000000..83b454e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/include/mbedtls_config_uta.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited */ +#ifndef __MBEDTLS_CONFIG_UTA_H +#define __MBEDTLS_CONFIG_UTA_H + +/* + * When wrapping using TEE_BigInt to represent a mbedtls_mpi we can only + * use 32-bit arithmetics. + */ +#define MBEDTLS_HAVE_INT32 + +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PKCS1_V15 + +#define MBEDTLS_CIPHER_C +#define MBEDTLS_DES_C +#define MBEDTLS_AES_C +#define MBEDTLS_NIST_KW_C +#define MBEDTLS_POLY1305_C +#define MBEDTLS_CHACHA20_C +#define MBEDTLS_CHACHAPOLY_C + +#define MBEDTLS_SHA1_C +#define MBEDTLS_SHA256_C +#define MBEDTLS_MD_C +#define MBEDTLS_MD5_C + +#define MBEDTLS_CTR_DRBG_C +#define MBEDTLS_ENTROPY_C +#define MBEDTLS_NO_PLATFORM_ENTROPY + +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_GENPRIME +#define MBEDTLS_RSA_C +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED + +#define MBEDTLS_PK_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_OID_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#define MBEDTLS_X509_CRT_PARSE_C +#define MBEDTLS_X509_CRT_WRITE_C +#define MBEDTLS_X509_CSR_PARSE_C +#define MBEDTLS_X509_CSR_WRITE_C +#define MBEDTLS_X509_CREATE_C +#define MBEDTLS_X509_CHECK_KEY_USAGE +#define MBEDTLS_X509_USE_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_CERTS_C +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_PEM_WRITE_C + +#include + +#endif /* __MBEDTLS_CONFIG_UTA_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md b/optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md new file mode 100644 index 0000000..47bde07 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/BUGS.md @@ -0,0 +1,20 @@ +## Known issues + +Known issues in Mbed TLS are [tracked on GitHub](https://github.com/Mbed-TLS/mbedtls/issues). + +## Reporting a bug + +If you think you've found a bug in Mbed TLS, please follow these steps: + +1. Make sure you're using the latest version of a + [maintained branch](BRANCHES.md): `master`, `development`, + or a long-time support branch. +2. Check [GitHub](https://github.com/Mbed-TLS/mbedtls/issues) to see if + your issue has already been reported. If not, … +3. If the issue is a security risk (for example: buffer overflow, + data leak), please report it confidentially as described in + [`SECURITY.md`](SECURITY.md). If not, … +4. Please [create an issue on on GitHub](https://github.com/Mbed-TLS/mbedtls/issues). + +Please do not use GitHub for support questions. If you want to know +how to do something with Mbed TLS, please see [`SUPPORT.md`](SUPPORT.md) for available documentation and support channels. diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md b/optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md new file mode 100644 index 0000000..cea12f1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/CONTRIBUTING.md @@ -0,0 +1,81 @@ +Contributing +============ +We gratefully accept bug reports and contributions from the community. There are some requirements we need to fulfill in order to be able to integrate contributions: + + - As with any open source project, contributions will be reviewed by the project team and community and may need some modifications to be accepted. + - The contribution should not break API or ABI, unless there is a real justification for that. If there is an API change, the contribution, if accepted, will be merged only when there will be a major release. + +Coding Standards +---------------- +- We would ask that contributions conform to [our coding standards](https://tls.mbed.org/kb/development/mbedtls-coding-standards), and that contributions are fully tested before submission, as mentioned in the [Tests](#tests) and [Continuous Integration](#continuous-integration-tests) sections. +- The code should be written in a clean and readable style. +- The code should be written in a portable generic way, that will benefit the whole community, and not only your own needs. +- The code should be secure, and will be reviewed from a security point of view as well. + +Making a Contribution +--------------------- +1. [Check for open issues](https://github.com/Mbed-TLS/mbedtls/issues) or [start a discussion](https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org) around a feature idea or a bug. +1. Fork the [Mbed TLS repository on GitHub](https://github.com/Mbed-TLS/mbedtls) to start making your changes. As a general rule, you should use the ["development" branch](https://github.com/Mbed-TLS/mbedtls/tree/development) as a basis. +1. Write a test which shows that the bug was fixed or that the feature works as expected. +1. Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary. We will include your name in the ChangeLog :) +1. For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it. +1. All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible. +1. Ensure that each commit has at least one `Signed-off-by:` line from the committer. If anyone else contributes to the commit, they should also add their own `Signed-off-by:` line. By adding this line, contributor(s) certify that the contribution is made under the terms of the [Developer Certificate of Origin](dco.txt). The contribution licensing is described in the [License section of the README](README.md#License). + +Backwards Compatibility +----------------------- + +The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches, as described in [BRANCHES.md](BRANCHES.md). + +To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change. + +Where changes to an existing interface are necessary, functions in the public interface which need to be changed, are marked as 'deprecated'. This is done with the preprocessor symbols `MBEDTLS_DEPRECATED_WARNING` and `MBEDTLS_DEPRECATED_REMOVED`. Then, a new function with a new name but similar if not identical behaviour to the original function containing the necessary changes should be created alongside the existing deprecated function. + +When a build is made with the deprecation preprocessor symbols defined, a compiler warning will be generated to warn a user that the function will be removed at some point in the future, notifying users that they should change from the older deprecated function to the newer function at their own convenience. + +Therefore, no changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. As described above, if a function needs to be changed, a new function needs to be created alongside it, with a new name, and whatever change is necessary, such as a new parameter or the addition of a return value. + +Periodically, the library will remove deprecated functions from the library which will be a breaking change in the API, but such changes will be made only in a planned, structured way that gives sufficient notice to users of the library. + +Long Term Support Branches +-------------------------- +Mbed TLS maintains several LTS (Long Term Support) branches, which are maintained continuously for a given period. The LTS branches are provided to allow users of the library to have a maintained, stable version of the library which contains only security fixes and fixes for other defects, without encountering additional features or API extensions which may introduce issues or change the code size or RAM usage, which can be significant considerations on some platforms. To allow users to take advantage of the LTS branches, these branches maintain backwards compatibility for both the public API and ABI. + +When backporting to these branches please observe the following rules: + +1. Any change to the library which changes the API or ABI cannot be backported. +1. All bug fixes that correct a defect that is also present in an LTS branch must be backported to that LTS branch. If a bug fix introduces a change to the API such as a new function, the fix should be reworked to avoid the API change. API changes without very strong justification are unlikely to be accepted. +1. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be additional test cases or quality improvements such as changes to build or test scripts. + +It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/Mbed-TLS/mbedtls/tree/development) by contributors. + +The list of maintained branches can be found in the [Current Branches section +of BRANCHES.md](BRANCHES.md#current-branches). + +Tests +----- +As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist. + +Mbed TLS includes a comprehensive set of test suites in the `tests/` directory that are dynamically generated to produce the actual test source files (e.g. `test_suite_mpi.c`). These files are generated from a `function file` (e.g. `suites/test_suite_mpi.function`) and a `data file` (e.g. `suites/test_suite_mpi.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function. + +[A Knowledge Base article describing how to add additional tests is available on the Mbed TLS website](https://tls.mbed.org/kb/development/test_suites). + +A test script `tests/scripts/basic-build-test.sh` is available to show test coverage of the library. New code contributions should provide a similar level of code coverage to that which already exists for the library. + +Sample applications, if needed, should be modified as well. + +Continuous Integration Tests +---------------------------- +Once a PR has been made, the Continuous Integration (CI) tests are triggered and run. You should follow the result of the CI tests, and fix failures. + +It is advised to enable the [githooks scripts](https://github.com/Mbed-TLS/mbedtls/tree/development/tests/git-scripts) prior to pushing your changes, for catching some of the issues as early as possible. + +Documentation +------------- +Mbed TLS is well documented, but if you think documentation is needed, speak out! + +1. All interfaces should be documented through Doxygen. New APIs should introduce Doxygen documentation. +1. Complex parts in the code should include comments. +1. If needed, a Readme file is advised. +1. If a [Knowledge Base (KB)](https://tls.mbed.org/kb) article should be added, write this as a comment in the PR description. +1. A [ChangeLog](https://github.com/Mbed-TLS/mbedtls/blob/development/ChangeLog.d/00README.md) entry should be added for this contribution. diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog b/optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog new file mode 100644 index 0000000..54217fe --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/ChangeLog @@ -0,0 +1,4607 @@ +Mbed TLS ChangeLog (Sorted per branch, date) + += Mbed TLS 2.28.1 branch released 2022-07-11 + +Default behavior changes + * mbedtls_cipher_set_iv will now fail with ChaCha20 and ChaCha20+Poly1305 + for IV lengths other than 12. The library was silently overwriting this + length with 12, but did not inform the caller about it. Fixes #4301. + +Features + * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, you may list the PSA crypto + feature requirements in the file named by the new macro + MBEDTLS_PSA_CRYPTO_CONFIG_FILE instead of the default psa/crypto_config.h. + Furthermore you may name an additional file to include after the main + file with the macro MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE. + +Security + * Zeroize dynamically-allocated buffers used by the PSA Crypto key storage + module before freeing them. These buffers contain secret key material, and + could thus potentially leak the key through freed heap. + * Fix a potential heap buffer overread in TLS 1.2 server-side when + MBEDTLS_USE_PSA_CRYPTO is enabled, an opaque key (created with + mbedtls_pk_setup_opaque()) is provisioned, and a static ECDH ciphersuite + is selected. This may result in an application crash or potentially an + information leak. + * Fix a buffer overread in DTLS ClientHello parsing in servers with + MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE enabled. An unauthenticated client + or a man-in-the-middle could cause a DTLS server to read up to 255 bytes + after the end of the SSL input buffer. The buffer overread only happens + when MBEDTLS_SSL_IN_CONTENT_LEN is less than a threshold that depends on + the exact configuration: 258 bytes if using mbedtls_ssl_cookie_check(), + and possibly up to 571 bytes with a custom cookie check function. + Reported by the Cybeats PSI Team. + +Bugfix + * Fix a memory leak if mbedtls_ssl_config_defaults() is called twice. + * Fix several bugs (warnings, compiler and linker errors, test failures) + in reduced configurations when MBEDTLS_USE_PSA_CRYPTO is enabled. + * Fix a bug in (D)TLS curve negotiation: when MBEDTLS_USE_PSA_CRYPTO was + enabled and an ECDHE-ECDSA or ECDHE-RSA key exchange was used, the + client would fail to check that the curve selected by the server for + ECDHE was indeed one that was offered. As a result, the client would + accept any curve that it supported, even if that curve was not allowed + according to its configuration. Fixes #5291. + * Fix unit tests that used 0 as the file UID. This failed on some + implementations of PSA ITS. Fixes #3838. + * Fix API violation in mbedtls_md_process() test by adding a call to + mbedtls_md_starts(). Fixes #2227. + * Fix compile errors when MBEDTLS_HAVE_TIME is not defined. Add tests + to catch bad uses of time.h. + * Fix the library search path when building a shared library with CMake + on Windows. + * Fix bug in the alert sending function mbedtls_ssl_send_alert_message() + potentially leading to corrupted alert messages being sent in case + the function needs to be re-called after initially returning + MBEDTLS_SSL_WANT_WRITE. Fixes #1916. + * In configurations with MBEDTLS_SSL_DTLS_CONNECTION_ID enabled but none of + MBEDTLS_SSL_HW_RECORD_ACCEL, MBEDTLS_SSL_EXPORT_KEYS or MBEDTLS_DEBUG_C, + DTLS handshakes using CID would crash due to a null pointer dereference. + Fix this. Fixes #3998. + * Fix incorrect documentation of mbedtls_x509_crt_profile. The previous + documentation stated that the `allowed_pks` field applies to signatures + only, but in fact it does apply to the public key type of the end entity + certificate, too. Fixes #1992. + * Fix PSA cipher multipart operations using ARC4. Previously, an IV was + required but discarded. Now, an IV is rejected, as it should be. + * Fix undefined behavior in mbedtls_asn1_find_named_data(), where val is + not NULL and val_len is zero. + * psa_raw_key_agreement() now returns PSA_ERROR_BUFFER_TOO_SMALL when + applicable. Fixes #5735. + * Fix a bug in the x25519 example program where the removal of + MBEDTLS_ECDH_LEGACY_CONTEXT caused the program not to run. Fixes #4901 and + #3191. + * Encode X.509 dates before 1/1/2000 as UTCTime rather than + GeneralizedTime. Fixes #5465. + * Fix order value of curve x448. + * Fix string representation of DNs when outputting values containing commas + and other special characters, conforming to RFC 1779. Fixes #769. + * Silence a warning from GCC 12 in the selftest program. Fixes #5974. + * Fix mbedtls_asn1_write_mpi() writing an incorrect encoding of 0. + * Fix resource leaks in mbedtls_pk_parse_public_key() in low + memory conditions. + * Fix server connection identifier setting for outgoing encrypted records + on DTLS 1.2 session resumption. After DTLS 1.2 session resumption with + connection identifier, the Mbed TLS client now properly sends the server + connection identifier in encrypted record headers. Fix #5872. + * Fix a null pointer dereference when performing some operations on zero + represented with 0 limbs (specifically mbedtls_mpi_mod_int() dividing + by 2, and mbedtls_mpi_write_string() in base 2). + * Fix record sizes larger than 16384 being sometimes accepted despite being + non-compliant. This could not lead to a buffer overflow. In particular, + application data size was already checked correctly. + +Changes + * Assume source files are in UTF-8 when using MSVC with CMake. + += mbed TLS 2.28.0 branch released 2021-12-17 + +API changes + * Some fields of mbedtls_ssl_session and mbedtls_ssl_config are in a + different order. This only affects applications that define such + structures directly or serialize them. + +Requirement changes + * Sign-magnitude and one's complement representations for signed integers are + not supported. Two's complement is the only supported representation. + +Removals + * Remove config option MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES, + which allowed SHA-1 in the default TLS configuration for certificate + signing. It was intended to facilitate the transition in environments + with SHA-1 certificates. SHA-1 is considered a weak message digest and + its use constitutes a security risk. + * Remove the partial support for running unit tests via Greentea on Mbed OS, + which had been unmaintained since 2018. + +Features + * The identifier of the CID TLS extension can be configured by defining + MBEDTLS_TLS_EXT_CID at compile time. + * Warn if errors from certain functions are ignored. This is currently + supported on GCC-like compilers and on MSVC and can be configured through + the macro MBEDTLS_CHECK_RETURN. The warnings are always enabled + (where supported) for critical functions where ignoring the return + value is almost always a bug. Enable the new configuration option + MBEDTLS_CHECK_RETURN_WARNING to get warnings for other functions. This + is currently implemented in the AES, DES and md modules, and will be + extended to other modules in the future. + * Add missing PSA macros declared by PSA Crypto API 1.0.0: + PSA_ALG_IS_SIGN_HASH, PSA_ALG_NONE, PSA_HASH_BLOCK_LENGTH, PSA_KEY_ID_NULL. + * Add new API mbedtls_ct_memcmp for constant time buffer comparison. + * Add PSA API definition for ARIA. + +Security + * Zeroize several intermediate variables used to calculate the expected + value when verifying a MAC or AEAD tag. This hardens the library in + case the value leaks through a memory disclosure vulnerability. For + example, a memory disclosure vulnerability could have allowed a + man-in-the-middle to inject fake ciphertext into a DTLS connection. + * In psa_cipher_generate_iv() and psa_cipher_encrypt(), do not read back + from the output buffer. This fixes a potential policy bypass or decryption + oracle vulnerability if the output buffer is in memory that is shared with + an untrusted application. + * Fix a double-free that happened after mbedtls_ssl_set_session() or + mbedtls_ssl_get_session() failed with MBEDTLS_ERR_SSL_ALLOC_FAILED + (out of memory). After that, calling mbedtls_ssl_session_free() + and mbedtls_ssl_free() would cause an internal session buffer to + be free()'d twice. + +Bugfix + * Stop using reserved identifiers as local variables. Fixes #4630. + * The GNU makefiles invoke python3 in preference to python except on Windows. + The check was accidentally not performed when cross-compiling for Windows + on Linux. Fix this. Fixes #4774. + * Prevent divide by zero if either of PSA_CIPHER_ENCRYPT_OUTPUT_SIZE() or + PSA_CIPHER_UPDATE_OUTPUT_SIZE() were called using an asymmetric key type. + * Fix a parameter set but unused in psa_crypto_cipher.c. Fixes #4935. + * Don't use the obsolete header path sys/fcntl.h in unit tests. + These header files cause compilation errors in musl. + Fixes #4969. + * Fix missing constraints on x86_64 and aarch64 assembly code + for bignum multiplication that broke some bignum operations with + (at least) Clang 12. + Fixes #4116, #4786, #4917, #4962. + * Fix mbedtls_cipher_crypt: AES-ECB when MBEDTLS_USE_PSA_CRYPTO is enabled. + * Failures of alternative implementations of AES or DES single-block + functions enabled with MBEDTLS_AES_ENCRYPT_ALT, MBEDTLS_AES_DECRYPT_ALT, + MBEDTLS_DES_CRYPT_ECB_ALT or MBEDTLS_DES3_CRYPT_ECB_ALT were ignored. + This does not concern the implementation provided with Mbed TLS, + where this function cannot fail, or full-module replacements with + MBEDTLS_AES_ALT or MBEDTLS_DES_ALT. Reported by Armelle Duboc in #1092. + * Some failures of HMAC operations were ignored. These failures could only + happen with an alternative implementation of the underlying hash module. + * Fix the error returned by psa_generate_key() for a public key. Fixes #4551. + * Fix the build of sample programs when neither MBEDTLS_ERROR_C nor + MBEDTLS_ERROR_STRERROR_DUMMY is enabled. + * Fix PSA_ALG_RSA_PSS verification accepting an arbitrary salt length. + This algorithm now accepts only the same salt length for verification + that it produces when signing, as documented. Use the new algorithm + PSA_ALG_RSA_PSS_ANY_SALT to accept any salt length. Fixes #4946. + * The existing predicate macro name PSA_ALG_IS_HASH_AND_SIGN is now reserved + for algorithm values that fully encode the hashing step, as per the PSA + Crypto API specification. This excludes PSA_ALG_RSA_PKCS1V15_SIGN_RAW and + PSA_ALG_ECDSA_ANY. The new predicate macro PSA_ALG_IS_SIGN_HASH covers + all algorithms that can be used with psa_{sign,verify}_hash(), including + these two. + * Fix issue in Makefile on Linux with SHARED=1, that caused shared libraries + not to list other shared libraries they need. + * Fix a bug in mbedtls_gcm_starts() when the bit length of the iv + exceeds 2^32. Fixes #4884. + * Fix an uninitialized variable warning in test_suite_ssl.function with GCC + version 11. + * Fix the build when no SHA2 module is included. Fixes #4930. + * Fix the build when only the bignum module is included. Fixes #4929. + * Fix a potential invalid pointer dereference and infinite loop bugs in + pkcs12 functions when the password is empty. Fix the documentation to + better describe the inputs to these functions and their possible values. + Fixes #5136. + * The key usage flags PSA_KEY_USAGE_SIGN_MESSAGE now allows the MAC + operations psa_mac_compute() and psa_mac_sign_setup(). + * The key usage flags PSA_KEY_USAGE_VERIFY_MESSAGE now allows the MAC + operations psa_mac_verify() and psa_mac_verify_setup(). + +Changes + * Set config option MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE to be + disabled by default. + * Improve the performance of base64 constant-flow code. The result is still + slower than the original non-constant-flow implementation, but much faster + than the previous constant-flow implementation. Fixes #4814. + * Indicate in the error returned if the nonce length used with + ChaCha20-Poly1305 is invalid, and not just unsupported. + * The mbedcrypto library includes a new source code module constant_time.c, + containing various functions meant to resist timing side channel attacks. + This module does not have a separate configuration option, and functions + from this module will be included in the build as required. Currently + most of the interface of this module is private and may change at any + time. + += mbed TLS 2.27.0 branch released 2021-07-07 + +API changes + * Update AEAD output size macros to bring them in line with the PSA Crypto + API version 1.0 spec. This version of the spec parameterizes them on the + key type used, as well as the key bit-size in the case of + PSA_AEAD_TAG_LENGTH. + The old versions of these macros were renamed and deprecated as follows: + - PSA_AEAD_TAG_LENGTH -> PSA_AEAD_TAG_LENGTH_1_ARG + - PSA_AEAD_ENCRYPT_OUTPUT_SIZE -> PSA_AEAD_ENCRYPT_OUTPUT_SIZE_2_ARG + - PSA_AEAD_DECRYPT_OUTPUT_SIZE -> PSA_AEAD_DECRYPT_OUTPUT_SIZE_2_ARG + - PSA_AEAD_UPDATE_OUTPUT_SIZE -> PSA_AEAD_UPDATE_OUTPUT_SIZE_2_ARG + - PSA_AEAD_FINISH_OUTPUT_SIZE -> PSA_AEAD_FINISH_OUTPUT_SIZE_1_ARG + - PSA_AEAD_VERIFY_OUTPUT_SIZE -> PSA_AEAD_VERIFY_OUTPUT_SIZE_1_ARG + * Implement one-shot cipher functions, psa_cipher_encrypt and + psa_cipher_decrypt, according to the PSA Crypto API 1.0.0 + specification. + +Requirement changes + * The library now uses the %zu format specifier with the printf() family of + functions, so requires a toolchain that supports it. This change does not + affect the maintained LTS branches, so when contributing changes please + bear this in mind and do not add them to backported code. + +Features + * Add mbedtls_rsa_rsassa_pss_sign_ext() function allowing to generate a + signature with a specific salt length. This function allows to validate + test cases provided in the NIST's CAVP test suite. Contributed by Cédric + Meuter in PR #3183. + * Added support for built-in driver keys through the PSA opaque crypto + driver interface. Refer to the documentation of + MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS for more information. + * Implement psa_sign_message() and psa_verify_message(). + * The new function mbedtls_mpi_random() generates a random value in a + given range uniformly. + * Implement psa_mac_compute() and psa_mac_verify() as defined in the + PSA Cryptograpy API 1.0.0 specification. + * MBEDTLS_ECP_MAX_BITS is now determined automatically from the configured + curves and no longer needs to be configured explicitly to save RAM. + +Security + * Fix a bias in the generation of finite-field Diffie-Hellman-Merkle (DHM) + private keys and of blinding values for DHM and elliptic curves (ECP) + computations. Reported by FlorianF89 in #4245. + * Fix a potential side channel vulnerability in ECDSA ephemeral key generation. + An adversary who is capable of very precise timing measurements could + learn partial information about the leading bits of the nonce used for the + signature, allowing the recovery of the private key after observing a + large number of signature operations. This completes a partial fix in + Mbed TLS 2.20.0. + * It was possible to configure MBEDTLS_ECP_MAX_BITS to a value that is + too small, leading to buffer overflows in ECC operations. Fail the build + in such a case. + * An adversary with access to precise enough information about memory + accesses (typically, an untrusted operating system attacking a secure + enclave) could recover an RSA private key after observing the victim + performing a single private-key operation. Found and reported by + Zili KOU, Wenjian HE, Sharad Sinha, and Wei ZHANG. + * An adversary with access to precise enough timing information (typically, a + co-located process) could recover a Curve25519 or Curve448 static ECDH key + after inputting a chosen public key and observing the victim performing the + corresponding private-key operation. Found and reported by Leila Batina, + Lukas Chmielewski, Björn Haase, Niels Samwel and Peter Schwabe. + +Bugfix + * Add printf function attributes to mbedtls_debug_print_msg to ensure we + get printf format specifier warnings. + * Fix premature fopen() call in mbedtls_entropy_write_seed_file which may + lead to seed file corruption in the case where the path to the seed file is + equal to MBEDTLS_PLATFORM_STD_NV_SEED_FILE. Contributed by Victor + Krasnoshchok in #3616. + * PSA functions other than psa_open_key now return PSA_ERROR_INVALID_HANDLE + rather than PSA_ERROR_DOES_NOT_EXIST for an invalid handle, bringing them + in line with version 1.0.0 of the specification. Fix #4162. + * PSA functions creating a key now return PSA_ERROR_INVALID_ARGUMENT rather + than PSA_ERROR_INVALID_HANDLE when the identifier specified for the key + to create is not valid, bringing them in line with version 1.0.0 of the + specification. Fix #4271. + * Fix some cases in the bignum module where the library constructed an + unintended representation of the value 0 which was not processed + correctly by some bignum operations. This could happen when + mbedtls_mpi_read_string() was called on "-0", or when + mbedtls_mpi_mul_mpi() and mbedtls_mpi_mul_int() was called with one of + the arguments being negative and the other being 0. Fixes #4643. + * Fix a bug in ECDSA that would cause it to fail when the hash is all-bits + zero. Fixes #1792 + * Fix a compilation error when MBEDTLS_ECP_RANDOMIZE_MXZ_ALT is + defined. Fixes #4217. + * Fix an incorrect error code when parsing a PKCS#8 private key. + * In a TLS client, enforce the Diffie-Hellman minimum parameter size + set with mbedtls_ssl_conf_dhm_min_bitlen() precisely. Before, the + minimum size was rounded down to the nearest multiple of 8. + * In library/net_sockets.c, _POSIX_C_SOURCE and _XOPEN_SOURCE are + defined to specific values. If the code is used in a context + where these are already defined, this can result in a compilation + error. Instead, assume that if they are defined, the values will + be adequate to build Mbed TLS. + * The cipher suite TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384 was not available + when SHA-1 was disabled and was offered when SHA-1 was enabled but SHA-384 + was disabled. Fix the dependency. Fixes #4472. + * Do not offer SHA384 cipher suites when SHA-384 is disabled. Fixes #4499. + * With MBEDTLS_PSA_CRYPTO_C disabled, some functions were getting built + nonetheless, resulting in undefined reference errors when building a + shared library. Reported by Guillermo Garcia M. in #4411. + * Fix test suite code on platforms where int32_t is not int, such as + Arm Cortex-M. Fixes #4530. + * Fix some issues affecting MBEDTLS_ARIA_ALT implementations: a misplaced + directive in a header and a missing initialization in the self-test. + * Fix a missing initialization in the Camellia self-test, affecting + MBEDTLS_CAMELLIA_ALT implementations. + * Restore the ability to configure PSA via Mbed TLS options to support RSA + key pair operations but exclude RSA key generation. When MBEDTLS_GENPRIME + is not defined PSA will no longer attempt to use mbedtls_rsa_gen_key(). + Fixes #4512. + * Fix a regression introduced in 2.24.0 which broke (D)TLS CBC ciphersuites + (when the encrypt-then-MAC extension is not in use) with some ALT + implementations of the underlying hash (SHA-1, SHA-256, SHA-384), causing + the affected side to wrongly reject valid messages. Fixes #4118. + * Remove outdated check-config.h check that prevented implementing the + timing module on Mbed OS. Fixes #4633. + * Fix PSA_ALG_TLS12_PRF and PSA_ALG_TLS12_PSK_TO_MS being too permissive + about missing inputs. + * Fix mbedtls_net_poll() and mbedtls_net_recv_timeout() often failing with + MBEDTLS_ERR_NET_POLL_FAILED on Windows. Fixes #4465. + * Fix a resource leak in a test suite with an alternative AES + implementation. Fixes #4176. + * Fix a crash in mbedtls_mpi_debug_mpi on a bignum having 0 limbs. This + could notably be triggered by setting the TLS debug level to 3 or above + and using a Montgomery curve for the key exchange. Reported by lhuang04 + in #4578. Fixes #4608. + * psa_verify_hash() was relying on implementation-specific behavior of + mbedtls_rsa_rsassa_pss_verify() and was causing failures in some _ALT + implementations. This reliance is now removed. Fixes #3990. + * Disallow inputs of length different from the corresponding hash when + signing or verifying with PSA_ALG_RSA_PSS (The PSA Crypto API mandates + that PSA_ALG_RSA_PSS uses the same hash throughout the algorithm.) + * Fix a null pointer dereference when mbedtls_mpi_exp_mod() was called with + A=0 represented with 0 limbs. Up to and including Mbed TLS 2.26, this bug + could not be triggered by code that constructed A with one of the + mbedtls_mpi_read_xxx functions (including in particular TLS code) since + those always built an mpi object with at least one limb. + Credit to OSS-Fuzz. Fixes #4641. + * Fix mbedtls_mpi_gcd(G,A,B) when the value of B is zero. This had no + effect on Mbed TLS's internal use of mbedtls_mpi_gcd(), but may affect + applications that call mbedtls_mpi_gcd() directly. Fixes #4642. + * The PSA API no longer allows the creation or destruction of keys with a + read-only lifetime. The persistence level PSA_KEY_PERSISTENCE_READ_ONLY + can now only be used as intended, for keys that cannot be modified through + normal use of the API. + * When MBEDTLS_PSA_CRYPTO_SPM is enabled, crypto_spe.h was not included + in all the right places. Include it from crypto_platform.h, which is + the natural place. Fixes #4649. + * mbedtls_pk_sign() and mbedtls_pk_verify() and their extended and + restartable variants now always honor the specified hash length if + nonzero. Before, for RSA, hash_len was ignored in favor of the length of + the specified hash algorithm. + * Fix which alert is sent in some cases to conform to the + applicable RFC: on an invalid Finished message value, an + invalid max_fragment_length extension, or an + unsupported extension used by the server. + * Correct (change from 12 to 13 bytes) the value of the macro describing the + maximum nonce length returned by psa_aead_generate_nonce(). + +Changes + * Add extra printf compiler warning flags to builds. + * Fix memsan build false positive in x509_crt.c with Clang 11 + * Fix the setting of the read timeout in the DTLS sample programs. + * Remove the AES sample application programs/aes/aescrypt2 which shows + bad cryptographic practice. Fix #1906. + * Alternative implementations of CMAC may now opt to not support 3DES as a + CMAC block cipher, and still pass the CMAC self test. + * Remove configs/config-psa-crypto.h, which was identical to the default + configuration except for having some extra cryptographic mechanisms + enabled and for unintended differences. This configuration was primarily + intended to demonstrate the PSA API, and lost most of its usefulness when + MBEDTLS_PSA_CRYPTO_C became enabled by default. + * When building the test suites with GNU make, invoke python3 or python, not + python2, which is no longer supported upstream. + * When using session cache based session resumption on the server, + double-check that custom session cache implementations return + sessions which are consistent with the negotiated ciphersuite + and compression method. + * Fix build failure on MinGW toolchain when __USE_MING_ANSI_STDIO is on. + When that flag is on, standard GNU C printf format specifiers + should be used. + * Reduce the default value of MBEDTLS_ECP_WINDOW_SIZE. This reduces RAM usage + during ECC operations at a negligible performance cost. + * mbedtls_mpi_read_binary(), mbedtls_mpi_read_binary_le() and + mbedtls_mpi_read_string() now construct an mbedtls_mpi object with 0 limbs + when their input has length 0. Note that this is an implementation detail + and can change at any time, so this change should be transparent, but it + may result in mbedtls_mpi_write_binary() or mbedtls_mpi_write_string() + now writing an empty string where it previously wrote one or more + zero digits when operating from values constructed with an mpi_read + function and some mpi operations. + * Implicitly add PSA_KEY_USAGE_SIGN_MESSAGE key usage policy flag when + PSA_KEY_USAGE_SIGN_HASH flag is set and PSA_KEY_USAGE_VERIFY_MESSAGE flag + when PSA_KEY_USAGE_VERIFY_HASH flag is set. This usage flag extension + is also applied when loading a key from storage. + += mbed TLS 2.26.0 branch released 2021-03-08 + +API changes + * Renamed the PSA Crypto API output buffer size macros to bring them in line + with version 1.0.0 of the specification. + * The API glue function mbedtls_ecc_group_of_psa() now takes the curve size + in bits rather than bytes, with an additional flag to indicate if the + size may have been rounded up to a whole number of bytes. + * Renamed the PSA Crypto API AEAD tag length macros to bring them in line + with version 1.0.0 of the specification. + +Default behavior changes + * In mbedtls_rsa_context objects, the ver field was formerly documented + as always 0. It is now reserved for internal purposes and may take + different values. + +New deprecations + * PSA_KEY_EXPORT_MAX_SIZE, PSA_HASH_SIZE, PSA_MAC_FINAL_SIZE, + PSA_BLOCK_CIPHER_BLOCK_SIZE, PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE and + PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN have been renamed, and the old names + deprecated. + * PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH and PSA_ALG_AEAD_WITH_TAG_LENGTH + have been renamed, and the old names deprecated. + +Features + * The PSA crypto subsystem can now use HMAC_DRBG instead of CTR_DRBG. + CTR_DRBG is used by default if it is available, but you can override + this choice by setting MBEDTLS_PSA_HMAC_DRBG_MD_TYPE at compile time. + Fix #3354. + * Automatic fallback to a software implementation of ECP when + MBEDTLS_ECP_xxx_ALT accelerator hooks are in use can now be turned off + through setting the new configuration flag MBEDTLS_ECP_NO_FALLBACK. + * The PSA crypto subsystem can now be configured to use less static RAM by + tweaking the setting for the maximum amount of keys simultaneously in RAM. + MBEDTLS_PSA_KEY_SLOT_COUNT sets the maximum number of volatile keys that + can exist simultaneously. It has a sensible default if not overridden. + * Partial implementation of the PSA crypto driver interface: Mbed TLS can + now use an external random generator instead of the library's own + entropy collection and DRBG code. Enable MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + and see the documentation of mbedtls_psa_external_get_random() for details. + * Applications using both mbedtls_xxx and psa_xxx functions (for example, + applications using TLS and MBEDTLS_USE_PSA_CRYPTO) can now use the PSA + random generator with mbedtls_xxx functions. See the documentation of + mbedtls_psa_get_random() for details. + * In the PSA API, the policy for a MAC or AEAD algorithm can specify a + minimum MAC or tag length thanks to the new wildcards + PSA_ALG_AT_LEAST_THIS_LENGTH_MAC and + PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG. + +Security + * Fix a security reduction in CTR_DRBG when the initial seeding obtained a + nonce from entropy. Applications were affected if they called + mbedtls_ctr_drbg_set_nonce_len(), if they called + mbedtls_ctr_drbg_set_entropy_len() with a size that was 3/2 times the key + length, or when the entropy module uses SHA-256 and CTR_DRBG uses AES-256. + In such cases, a random nonce was necessary to achieve the advertised + security strength, but the code incorrectly used a constant instead of + entropy from the nonce. + Found by John Stroebel in #3819 and fixed in #3973. + * Fix a buffer overflow in mbedtls_mpi_sub_abs() when calculating + |A| - |B| where |B| is larger than |A| and has more limbs (so the + function should return MBEDTLS_ERR_MPI_NEGATIVE_VALUE). Only + applications calling mbedtls_mpi_sub_abs() directly are affected: + all calls inside the library were safe since this function is + only called with |A| >= |B|. Reported by Guido Vranken in #4042. + * Fix an errorneous estimation for an internal buffer in + mbedtls_pk_write_key_pem(). If MBEDTLS_MPI_MAX_SIZE is set to an odd + value the function might fail to write a private RSA keys of the largest + supported size. + Found by Daniel Otte, reported in #4093 and fixed in #4094. + * Fix a stack buffer overflow with mbedtls_net_poll() and + mbedtls_net_recv_timeout() when given a file descriptor that is + beyond FD_SETSIZE. Reported by FigBug in #4169. + * Guard against strong local side channel attack against base64 tables by + making access aceess to them use constant flow code. + +Bugfix + * Fix use-after-scope error in programs/ssl/ssl_client2.c and ssl_server2.c + * Fix memory leak that occured when calling psa_close_key() on a + wrapped key with MBEDTLS_PSA_CRYPTO_SE_C defined. + * Fix an incorrect error code if an RSA private operation glitched. + * Fix a memory leak in an error case in psa_generate_derived_key_internal(). + * Fix a resource leak in CTR_DRBG and HMAC_DRBG when MBEDTLS_THREADING_C + is enabled, on platforms where initializing a mutex allocates resources. + This was a regression introduced in the previous release. Reported in + #4017, #4045 and #4071. + * Ensure that calling mbedtls_rsa_free() or mbedtls_entropy_free() + twice is safe. This happens for RSA when some Mbed TLS library functions + fail. Such a double-free was not safe when MBEDTLS_THREADING_C was + enabled on platforms where freeing a mutex twice is not safe. + * Fix a resource leak in a bad-arguments case of mbedtls_rsa_gen_key() + when MBEDTLS_THREADING_C is enabled on platforms where initializing + a mutex allocates resources. + * Fixes a bug where, if the library was configured to include support for + both the old SE interface and the new PSA driver interface, external keys were + not loaded from storage. This was fixed by #3996. + * This change makes 'mbedtls_x509write_crt_set_basic_constraints' + consistent with RFC 5280 4.2.1.9 which says: "Conforming CAs MUST + include this extension in all CA certificates that contain public keys + used to validate digital signatures on certificates and MUST mark the + extension as critical in such certificates." Previous to this change, + the extension was always marked as non-critical. This was fixed by + #3698. + +Changes + * A new library C file psa_crypto_client.c has been created to contain + the PSA code needed by a PSA crypto client when the PSA crypto + implementation is not included into the library. + * On recent enough versions of FreeBSD and DragonFlyBSD, the entropy module + now uses the getrandom syscall instead of reading from /dev/urandom. + += mbed TLS 2.25.0 branch released 2020-12-11 + +API changes + * The numerical values of the PSA Crypto API macros have been updated to + conform to version 1.0.0 of the specification. + * PSA_ALG_STREAM_CIPHER replaces PSA_ALG_CHACHA20 and PSA_ALG_ARC4. + The underlying stream cipher is determined by the key type + (PSA_KEY_TYPE_CHACHA20 or PSA_KEY_TYPE_ARC4). + * The functions mbedtls_cipher_auth_encrypt() and + mbedtls_cipher_auth_decrypt() no longer accept NIST_KW contexts, + as they have no way to check if the output buffer is large enough. + Please use mbedtls_cipher_auth_encrypt_ext() and + mbedtls_cipher_auth_decrypt_ext() instead. Credit to OSS-Fuzz and + Cryptofuzz. Fixes #3665. + +Requirement changes + * Update the minimum required CMake version to 2.8.12. This silences a + warning on CMake 3.19.0. #3801 + +New deprecations + * PSA_ALG_CHACHA20 and PSA_ALG_ARC4 have been deprecated. + Use PSA_ALG_STREAM_CIPHER instead. + * The functions mbedtls_cipher_auth_encrypt() and + mbedtls_cipher_auth_decrypt() are deprecated in favour of the new + functions mbedtls_cipher_auth_encrypt_ext() and + mbedtls_cipher_auth_decrypt_ext(). Please note that with AEAD ciphers, + these new functions always append the tag to the ciphertext, and include + the tag in the ciphertext length. + +Features + * Partial implementation of the new PSA Crypto accelerator APIs. (Symmetric + ciphers, asymmetric signing/verification and key generation, validate_key + entry point, and export_public_key interface.) + * Add support for ECB to the PSA cipher API. + * In PSA, allow using a key declared with a base key agreement algorithm + in combined key agreement and derivation operations, as long as the key + agreement algorithm in use matches the algorithm the key was declared with. + This is currently non-standard behaviour, but expected to make it into a + future revision of the PSA Crypto standard. + * Add MBEDTLS_TARGET_PREFIX CMake variable, which is prefixed to the mbedtls, + mbedcrypto, mbedx509 and apidoc CMake target names. This can be used by + external CMake projects that include this one to avoid CMake target name + clashes. The default value of this variable is "", so default target names + are unchanged. + * Add support for DTLS-SRTP as defined in RFC 5764. Contributed by Johan + Pascal, improved by Ron Eldor. + * In the PSA API, it is no longer necessary to open persistent keys: + operations now accept the key identifier. The type psa_key_handle_t is now + identical to psa_key_id_t instead of being platform-defined. This bridges + the last major gap to compliance with the PSA Cryptography specification + version 1.0.0. Opening persistent keys is still supported for backward + compatibility, but will be deprecated and later removed in future + releases. + * PSA_AEAD_NONCE_LENGTH, PSA_AEAD_NONCE_MAX_SIZE, PSA_CIPHER_IV_LENGTH and + PSA_CIPHER_IV_MAX_SIZE macros have been added as defined in version + 1.0.0 of the PSA Crypto API specification. + +Security + * The functions mbedtls_cipher_auth_encrypt() and + mbedtls_cipher_auth_decrypt() would write past the minimum documented + size of the output buffer when used with NIST_KW. As a result, code using + those functions as documented with NIST_KW could have a buffer overwrite + of up to 15 bytes, with consequences ranging up to arbitrary code + execution depending on the location of the output buffer. + * Limit the size of calculations performed by mbedtls_mpi_exp_mod to + MBEDTLS_MPI_MAX_SIZE to prevent a potential denial of service when + generating Diffie-Hellman key pairs. Credit to OSS-Fuzz. + * A failure of the random generator was ignored in mbedtls_mpi_fill_random(), + which is how most uses of randomization in asymmetric cryptography + (including key generation, intermediate value randomization and blinding) + are implemented. This could cause failures or the silent use of non-random + values. A random generator can fail if it needs reseeding and cannot not + obtain entropy, or due to an internal failure (which, for Mbed TLS's own + CTR_DRBG or HMAC_DRBG, can only happen due to a misconfiguration). + * Fix a compliance issue whereby we were not checking the tag on the + algorithm parameters (only the size) when comparing the signature in the + description part of the cert to the real signature. This meant that a + NULL algorithm parameters entry would look identical to an array of REAL + (size zero) to the library and thus the certificate would be considered + valid. However, if the parameters do not match in *any* way then the + certificate should be considered invalid, and indeed OpenSSL marks these + certs as invalid when mbedtls did not. + Many thanks to guidovranken who found this issue via differential fuzzing + and reported it in #3629. + * Zeroising of local buffers and variables which are used for calculations + in mbedtls_pkcs5_pbkdf2_hmac(), mbedtls_internal_sha*_process(), + mbedtls_internal_md*_process() and mbedtls_internal_ripemd160_process() + functions to erase sensitive data from memory. Reported by + Johan Malmgren and Johan Uppman Bruce from Sectra. + +Bugfix + * Fix an invalid (but non-zero) return code from mbedtls_pk_parse_subpubkey() + when the input has trailing garbage. Fixes #2512. + * Fix build failure in configurations where MBEDTLS_USE_PSA_CRYPTO is + enabled but ECDSA is disabled. Contributed by jdurkop. Fixes #3294. + * Include the psa_constant_names generated source code in the source tree + instead of generating it at build time. Fixes #3524. + * Fix rsa_prepare_blinding() to retry when the blinding value is not + invertible (mod N), instead of returning MBEDTLS_ERR_RSA_RNG_FAILED. This + addresses a regression but is rare in practice (approx. 1 in 2/sqrt(N)). + Found by Synopsys Coverity, fix contributed by Peter Kolbus (Garmin). + Fixes #3647. + * Use socklen_t on Android and other POSIX-compliant system + * Fix the build when the macro _GNU_SOURCE is defined to a non-empty value. + Fix #3432. + * Consistently return PSA_ERROR_INVALID_ARGUMENT on invalid cipher input + sizes (instead of PSA_ERROR_BAD_STATE in some cases) to make the + psa_cipher_* functions compliant with the PSA Crypto API specification. + * mbedtls_ecp_curve_list() now lists Curve25519 and Curve448 under the names + "x25519" and "x448". These curves support ECDH but not ECDSA. If you need + only the curves that support ECDSA, filter the list with + mbedtls_ecdsa_can_do(). + * Fix psa_generate_key() returning an error when asked to generate + an ECC key pair on Curve25519 or secp244k1. + * Fix psa_key_derivation_output_key() to allow the output of a combined key + agreement and subsequent key derivation operation to be used as a key + inside of the PSA Crypto core. + * Fix handling of EOF against 0xff bytes and on platforms with unsigned + chars. Fixes a build failure on platforms where char is unsigned. Fixes + #3794. + * Fix an off-by-one error in the additional data length check for + CCM, which allowed encryption with a non-standard length field. + Fixes #3719. + * Correct the default IV size for mbedtls_cipher_info_t structures using + MBEDTLS_MODE_ECB to 0, since ECB mode ciphers don't use IVs. + * Make arc4random_buf available on NetBSD and OpenBSD when _POSIX_C_SOURCE is + defined. Fix contributed in #3571. + * Fix conditions for including string.h in error.c. Fixes #3866. + * psa_set_key_id() now also sets the lifetime to persistent for keys located + in a secure element. + * Attempting to create a volatile key with a non-zero key identifier now + fails. Previously the key identifier was just ignored when creating a + volatile key. + * Attempting to create or register a key with a key identifier in the vendor + range now fails. + * Fix build failures on GCC 11. Fixes #3782. + * Add missing arguments of debug message in mbedtls_ssl_decrypt_buf. + * Fix a memory leak in mbedtls_mpi_sub_abs() when the result was negative + (an error condition) and the second operand was aliased to the result. + * Fix a case in elliptic curve arithmetic where an out-of-memory condition + could go undetected, resulting in an incorrect result. + * In CTR_DRBG and HMAC_DRBG, don't reset the reseed interval in seed(). + Fixes #2927. + * In PEM writing functions, fill the trailing part of the buffer with null + bytes. This guarantees that the corresponding parsing function can read + the buffer back, which was the case for mbedtls_x509write_{crt,csr}_pem + until this property was inadvertently broken in Mbed TLS 2.19.0. + Fixes #3682. + * Fix a build failure that occurred with the MBEDTLS_AES_SETKEY_DEC_ALT + option on. In this configuration key management methods that are required + for MBEDTLS_CIPHER_MODE_XTS were excluded from the build and made it fail. + Fixes #3818. Reported by John Stroebel. + +Changes + * Reduce stack usage significantly during sliding window exponentiation. + Reported in #3591 and fix contributed in #3592 by Daniel Otte. + * The PSA persistent storage format is updated to always store the key bits + attribute. No automatic upgrade path is provided. Previously stored keys + must be erased, or manually upgraded based on the key storage format + specification (docs/architecture/mbed-crypto-storage-specification.md). + Fixes #3740. + * Remove the zeroization of a pointer variable in AES rounds. It was valid + but spurious and misleading since it looked like a mistaken attempt to + zeroize the pointed-to buffer. Reported by Antonio de la Piedra, CEA + Leti, France. + += mbed TLS 2.24.0 branch released 2020-09-01 + +API changes + * In the PSA API, rename the types of elliptic curve and Diffie-Hellman + group families to psa_ecc_family_t and psa_dh_family_t, in line with the + PSA Crypto API specification version 1.0.0. + Rename associated macros as well: + PSA_ECC_CURVE_xxx renamed to PSA_ECC_FAMILY_xxx + PSA_DH_GROUP_xxx renamed to PSA_DH_FAMILY_xxx + PSA_KEY_TYPE_GET_CURVE renamed to to PSA_KEY_TYPE_ECC_GET_FAMILY + PSA_KEY_TYPE_GET_GROUP renamed to PSA_KEY_TYPE_DH_GET_FAMILY + +Default behavior changes + * Stop storing persistent information about externally stored keys created + through PSA Crypto with a volatile lifetime. Reported in #3288 and + contributed by Steven Cooreman in #3382. + +Features + * The new function mbedtls_ecp_write_key() exports private ECC keys back to + a byte buffer. It is the inverse of the existing mbedtls_ecp_read_key(). + * Support building on e2k (Elbrus) architecture: correctly enable + -Wformat-signedness, and fix the code that causes signed-one-bit-field + and sign-compare warnings. Contributed by makise-homura (Igor Molchanov) + . + +Security + * Fix a vulnerability in the verification of X.509 certificates when + matching the expected common name (the cn argument of + mbedtls_x509_crt_verify()) with the actual certificate name: when the + subjecAltName extension is present, the expected name was compared to any + name in that extension regardless of its type. This means that an + attacker could for example impersonate a 4-bytes or 16-byte domain by + getting a certificate for the corresponding IPv4 or IPv6 (this would + require the attacker to control that IP address, though). Similar attacks + using other subjectAltName name types might be possible. Found and + reported by kFYatek in #3498. + * When checking X.509 CRLs, a certificate was only considered as revoked if + its revocationDate was in the past according to the local clock if + available. In particular, on builds without MBEDTLS_HAVE_TIME_DATE, + certificates were never considered as revoked. On builds with + MBEDTLS_HAVE_TIME_DATE, an attacker able to control the local clock (for + example, an untrusted OS attacking a secure enclave) could prevent + revocation of certificates via CRLs. Fixed by no longer checking the + revocationDate field, in accordance with RFC 5280. Reported by + yuemonangong in #3340. Reported independently and fixed by + Raoul Strackx and Jethro Beekman in #3433. + * In (D)TLS record decryption, when using a CBC ciphersuites without the + Encrypt-then-Mac extension, use constant code flow memory access patterns + to extract and check the MAC. This is an improvement to the existing + countermeasure against Lucky 13 attacks. The previous countermeasure was + effective against network-based attackers, but less so against local + attackers. The new countermeasure defends against local attackers, even + if they have access to fine-grained measurements. In particular, this + fixes a local Lucky 13 cache attack found and reported by Tuba Yavuz, + Farhaan Fowze, Ken (Yihan) Bai, Grant Hernandez, and Kevin Butler + (University of Florida) and Dave Tian (Purdue University). + * Fix side channel in RSA private key operations and static (finite-field) + Diffie-Hellman. An adversary with precise enough timing and memory access + information (typically an untrusted operating system attacking a secure + enclave) could bypass an existing counter-measure (base blinding) and + potentially fully recover the private key. + * Fix a 1-byte buffer overread in mbedtls_x509_crl_parse_der(). + Credit to OSS-Fuzz for detecting the problem and to Philippe Antoine + for pinpointing the problematic code. + * Zeroising of plaintext buffers in mbedtls_ssl_read() to erase unused + application data from memory. Reported in #689 by + Johan Uppman Bruce of Sectra. + +Bugfix + * Library files installed after a CMake build no longer have execute + permission. + * Use local labels in mbedtls_padlock_has_support() to fix an invalid symbol + redefinition if the function is inlined. + Reported in #3451 and fix contributed in #3452 by okhowang. + * Fix the endianness of Curve25519 keys imported/exported through the PSA + APIs. psa_import_key and psa_export_key will now correctly expect/output + Montgomery keys in little-endian as defined by RFC7748. Contributed by + Steven Cooreman in #3425. + * Fix build errors when the only enabled elliptic curves are Montgomery + curves. Raised by signpainter in #941 and by Taiki-San in #1412. This + also fixes missing declarations reported by Steven Cooreman in #1147. + * Fix self-test failure when the only enabled short Weierstrass elliptic + curve is secp192k1. Fixes #2017. + * PSA key import will now correctly import a Curve25519/Curve448 public key + instead of erroring out. Contributed by Steven Cooreman in #3492. + * Use arc4random_buf on NetBSD instead of rand implementation with cyclical + lower bits. Fix contributed in #3540. + * Fix a memory leak in mbedtls_md_setup() when using HMAC under low memory + conditions. Reported and fix suggested by Guido Vranken in #3486. + * Fix bug in redirection of unit test outputs on platforms where stdout is + defined as a macro. First reported in #2311 and fix contributed in #3528. + +Changes + * Only pass -Wformat-signedness to versions of GCC that support it. Reported + in #3478 and fix contributed in #3479 by okhowang. + * Reduce the stack consumption of mbedtls_x509write_csr_der() which + previously could lead to stack overflow on constrained devices. + Contributed by Doru Gucea and Simon Leet in #3464. + * Undefine the ASSERT macro before defining it locally, in case it is defined + in a platform header. Contributed by Abdelatif Guettouche in #3557. + * Update copyright notices to use Linux Foundation guidance. As a result, + the copyright of contributors other than Arm is now acknowledged, and the + years of publishing are no longer tracked in the source files. This also + eliminates the need for the lines declaring the files to be part of + MbedTLS. Fixes #3457. + * Add the command line parameter key_pwd to the ssl_client2 and ssl_server2 + example applications which allows to provide a password for the key file + specified through the existing key_file argument. This allows the use of + these applications with password-protected key files. Analogously but for + ssl_server2 only, add the command line parameter key_pwd2 which allows to + set a password for the key file provided through the existing key_file2 + argument. + += mbed TLS 2.23.0 branch released 2020-07-01 + +Default behavior changes + * In the experimental PSA secure element interface, change the encoding of + key lifetimes to encode a persistence level and the location. Although C + prototypes do not effectively change, code calling + psa_register_se_driver() must be modified to pass the driver's location + instead of the keys' lifetime. If the library is upgraded on an existing + device, keys created with the old lifetime value will not be readable or + removable through Mbed TLS after the upgrade. + +Features + * New functions in the error module return constant strings for + high- and low-level error codes, complementing mbedtls_strerror() + which constructs a string for any error code, including compound + ones, but requires a writable buffer. Contributed by Gaurav Aggarwal + in #3176. + * The new utility programs/ssl/ssl_context_info prints a human-readable + dump of an SSL context saved with mbedtls_ssl_context_save(). + * Add support for midipix, a POSIX layer for Microsoft Windows. + * Add new mbedtls_x509_crt_parse_der_with_ext_cb() routine which allows + parsing unsupported certificate extensions via user provided callback. + Contributed by Nicola Di Lieto in #3243 as + a solution to #3241. + * Pass the "certificate policies" extension to the callback supplied to + mbedtls_x509_crt_parse_der_with_ext_cb() if it contains unsupported + policies (#3419). + * Added support to entropy_poll for the kern.arandom syscall supported on + some BSD systems. Contributed by Nia Alarie in #3423. + * Add support for Windows 2000 in net_sockets. Contributed by opatomic. #3239 + +Security + * Fix a side channel vulnerability in modular exponentiation that could + reveal an RSA private key used in a secure enclave. Noticed by Sangho Lee, + Ming-Wei Shih, Prasun Gera, Taesoo Kim and Hyesoon Kim (Georgia Institute + of Technology); and Marcus Peinado (Microsoft Research). Reported by Raoul + Strackx (Fortanix) in #3394. + * Fix side channel in mbedtls_ecp_check_pub_priv() and + mbedtls_pk_parse_key() / mbedtls_pk_parse_keyfile() (when loading a + private key that didn't include the uncompressed public key), as well as + mbedtls_ecp_mul() / mbedtls_ecp_mul_restartable() when called with a NULL + f_rng argument. An attacker with access to precise enough timing and + memory access information (typically an untrusted operating system + attacking a secure enclave) could fully recover the ECC private key. + Found and reported by Alejandro Cabrera Aldaya and Billy Brumley. + * Fix issue in Lucky 13 counter-measure that could make it ineffective when + hardware accelerators were used (using one of the MBEDTLS_SHAxxx_ALT + macros). This would cause the original Lucky 13 attack to be possible in + those configurations, allowing an active network attacker to recover + plaintext after repeated timing measurements under some conditions. + Reported and fix suggested by Luc Perneel in #3246. + +Bugfix + * Fix the Visual Studio Release x64 build configuration for mbedtls itself. + Completes a previous fix in Mbed TLS 2.19 that only fixed the build for + the example programs. Reported in #1430 and fix contributed by irwir. + * Fix undefined behavior in X.509 certificate parsing if the + pathLenConstraint basic constraint value is equal to INT_MAX. + The actual effect with almost every compiler is the intended + behavior, so this is unlikely to be exploitable anywhere. #3192 + * Fix issue with a detected HW accelerated record error not being exposed + due to shadowed variable. Contributed by Sander Visser in #3310. + * Avoid NULL pointer dereferencing if mbedtls_ssl_free() is called with a + NULL pointer argument. Contributed by Sander Visser in #3312. + * Fix potential linker errors on dual world platforms by inlining + mbedtls_gcc_group_to_psa(). This allows the pk.c module to link separately + from psa_crypto.c. Fixes #3300. + * Remove dead code in X.509 certificate parsing. Contributed by irwir in + #2855. + * Include asn1.h in error.c. Fixes #3328 reported by David Hu. + * Fix potential memory leaks in ecp_randomize_jac() and ecp_randomize_mxz() + when PRNG function fails. Contributed by Jonas Lejeune in #3318. + * Remove unused macros from MSVC projects. Reported in #3297 and fix + submitted in #3333 by irwir. + * Add additional bounds checks in ssl_write_client_hello() preventing + output buffer overflow if the configuration declared a buffer that was + too small. + * Set _POSIX_C_SOURCE to at least 200112L in C99 code. Reported in #3420 and + fix submitted in #3421 by Nia Alarie. + * Fix building library/net_sockets.c and the ssl_mail_client program on + NetBSD. Contributed by Nia Alarie in #3422. + * Fix false positive uninitialised variable reported by cpp-check. + Contributed by Sander Visser in #3311. + * Update iv and len context pointers manually when reallocating buffers + using the MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH feature. This caused issues + when receiving a connection with CID, when these fields were shifted + in ssl_parse_record_header(). + +Changes + * Fix warnings about signedness issues in format strings. The build is now + clean of -Wformat-signedness warnings. Contributed by Kenneth Soerensen + in #3153. + * Fix minor performance issue in operations on Curve25519 caused by using a + suboptimal modular reduction in one place. Found and fix contributed by + Aurelien Jarno in #3209. + * Combine identical cases in switch statements in md.c. Contributed + by irwir in #3208. + * Simplify a bounds check in ssl_write_certificate_request(). Contributed + by irwir in #3150. + * Unify the example programs termination to call mbedtls_exit() instead of + using a return command. This has been done to enable customization of the + behavior in bare metal environments. + * Fix mbedtls_x509_dn_gets to escape non-ASCII characters as "?". + Contributed by Koh M. Nakagawa in #3326. + * Use FindPython3 when cmake version >= 3.15.0 + * Abort the ClientHello writing function as soon as some extension doesn't + fit into the record buffer. Previously, such extensions were silently + dropped. As a consequence, the TLS handshake now fails when the output + buffer is not large enough to hold the ClientHello. + * The unit tests now rely on header files in tests/include/test and source + files in tests/src. When building with make or cmake, the files in + tests/src are compiled and the resulting object linked into each test + executable. + * The ECP module, enabled by `MBEDTLS_ECP_C`, now depends on + `MBEDTLS_CTR_DRBG_C` or `MBEDTLS_HMAC_DRBG_C` for some side-channel + coutermeasures. If side channels are not a concern, this dependency can + be avoided by enabling the new option `MBEDTLS_ECP_NO_INTERNAL_RNG`. + * Align MSVC error flag with GCC and Clang. Contributed by Carlos Gomes + Martinho. #3147 + * Remove superfluous assignment in mbedtls_ssl_parse_certificate(). Reported + in #3182 and fix submitted by irwir. #3217 + * Fix typo in XTS tests. Reported and fix submitted by Kxuan. #3319 + += mbed TLS 2.22.0 branch released 2020-04-14 + +New deprecations + * Deprecate MBEDTLS_SSL_HW_RECORD_ACCEL that enables function hooks in the + SSL module for hardware acceleration of individual records. + * Deprecate mbedtls_ssl_get_max_frag_len() in favour of + mbedtls_ssl_get_output_max_frag_len() and + mbedtls_ssl_get_input_max_frag_len() to be more precise about which max + fragment length is desired. + +Security + * Fix issue in DTLS handling of new associations with the same parameters + (RFC 6347 section 4.2.8): an attacker able to send forged UDP packets to + the server could cause it to drop established associations with + legitimate clients, resulting in a Denial of Service. This could only + happen when MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE was enabled in config.h + (which it is by default). + * Fix side channel in ECC code that allowed an adversary with access to + precise enough timing and memory access information (typically an + untrusted operating system attacking a secure enclave) to fully recover + an ECDSA private key. Found and reported by Alejandro Cabrera Aldaya, + Billy Brumley and Cesar Pereida Garcia. CVE-2020-10932 + * Fix a potentially remotely exploitable buffer overread in a + DTLS client when parsing the Hello Verify Request message. + +Features + * The new build option MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH automatically + resizes the I/O buffers before and after handshakes, reducing the memory + consumption during application data transfer. + +Bugfix + * Fix compilation failure when both MBEDTLS_SSL_PROTO_DTLS and + MBEDTLS_SSL_HW_RECORD_ACCEL are enabled. + * Remove a spurious check in ssl_parse_client_psk_identity that triggered + a warning with some compilers. Fix contributed by irwir in #2856. + * Fix a function name in a debug message. Contributed by Ercan Ozturk in + #3013. + +Changes + * Mbed Crypto is no longer a Git submodule. The crypto part of the library + is back directly in the present repository. + * Split mbedtls_ssl_get_max_frag_len() into + mbedtls_ssl_get_output_max_frag_len() and + mbedtls_ssl_get_input_max_frag_len() to ensure that a sufficient input + buffer is allocated by the server (if MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + is defined), regardless of what MFL was configured for it. + += mbed TLS 2.21.0 branch released 2020-02-20 + +New deprecations + * Deprecate MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO that enables parsing + SSLv2 ClientHello messages. + * Deprecate MBEDTLS_SSL_PROTO_SSL3 that enables support for SSLv3. + * Deprecate for MBEDTLS_PKCS11_C, the wrapper around the pkcs11-helper + library which allows TLS authentication to use keys stored in a + PKCS#11 token such as a smartcard. + +Security + * Fix potential memory overread when performing an ECDSA signature + operation. The overread only happens with cryptographically low + probability (of the order of 2^-n where n is the bitsize of the curve) + unless the RNG is broken, and could result in information disclosure or + denial of service (application crash or extra resource consumption). + Found by Auke Zeilstra and Peter Schwabe, using static analysis. + * To avoid a side channel vulnerability when parsing an RSA private key, + read all the CRT parameters from the DER structure rather than + reconstructing them. Found by Alejandro Cabrera Aldaya and Billy Bob + Brumley. Reported and fix contributed by Jack Lloyd. + ARMmbed/mbed-crypto#352 + +Features + * The new build option MBEDTLS_SHA512_NO_SHA384 allows building SHA-512 + support without SHA-384. + +API changes + * Change the encoding of key types and curves in the PSA API. The new + values are aligned with the upcoming release of the PSA Crypto API + specification version 1.0.0. The main change which may break some + existing code is that elliptic curve key types no longer encode the + exact curve: a psa_ecc_curve_t or psa_key_type_t value only encodes + a curve family and the key size determines the exact curve (for example, + PSA_ECC_CURVE_SECP_R1 with 256 bits is P256R1). ARMmbed/mbed-crypto#330 + +Bugfix + * Fix an unchecked call to mbedtls_md() in the x509write module. + * Fix build failure with MBEDTLS_ZLIB_SUPPORT enabled. Reported by + Jack Lloyd in #2859. Fix submitted by jiblime in #2963. + * Fix some false-positive uninitialized variable warnings in X.509. Fix + contributed by apple-ihack-geek in #2663. + * Fix a possible error code mangling in psa_mac_verify_finish() when + a cryptographic accelerator fails. ARMmbed/mbed-crypto#345 + * Fix a bug in mbedtls_pk_parse_key() that would cause it to accept some + RSA keys that would later be rejected by functions expecting private + keys. Found by Catena cyber using oss-fuzz (issue 20467). + * Fix a bug in mbedtls_pk_parse_key() that would cause it to + accept some RSA keys with invalid values by silently fixing those values. + += mbed TLS 2.20.0 branch released 2020-01-15 + +Default behavior changes + * The initial seeding of a CTR_DRBG instance makes a second call to the + entropy function to obtain entropy for a nonce if the entropy size is less + than 3/2 times the key size. In case you want to disable the extra call to + grab entropy, you can call mbedtls_ctr_drbg_set_nonce_len() to force the + nonce length to 0. + +Security + * Enforce that mbedtls_entropy_func() gathers a total of + MBEDTLS_ENTROPY_BLOCK_SIZE bytes or more from strong sources. In the + default configuration, on a platform with a single entropy source, the + entropy module formerly only grabbed 32 bytes, which is good enough for + security if the source is genuinely strong, but less than the expected 64 + bytes (size of the entropy accumulator). + * Zeroize local variables in mbedtls_internal_aes_encrypt() and + mbedtls_internal_aes_decrypt() before exiting the function. The value of + these variables can be used to recover the last round key. To follow best + practice and to limit the impact of buffer overread vulnerabilities (like + Heartbleed) we need to zeroize them before exiting the function. + Issue reported by Tuba Yavuz, Farhaan Fowze, Ken (Yihang) Bai, + Grant Hernandez, and Kevin Butler (University of Florida) and + Dave Tian (Purdue University). + * Fix side channel vulnerability in ECDSA. Our bignum implementation is not + constant time/constant trace, so side channel attacks can retrieve the + blinded value, factor it (as it is smaller than RSA keys and not guaranteed + to have only large prime factors), and then, by brute force, recover the + key. Reported by Alejandro Cabrera Aldaya and Billy Brumley. + * Fix side channel vulnerability in ECDSA key generation. Obtaining precise + timings on the comparison in the key generation enabled the attacker to + learn leading bits of the ephemeral key used during ECDSA signatures and to + recover the private key. Reported by Jeremy Dubeuf. + * Catch failure of AES functions in mbedtls_ctr_drbg_random(). Uncaught + failures could happen with alternative implementations of AES. Bug + reported and fix proposed by Johan Uppman Bruce and Christoffer Lauri, + Sectra. + +Features + * Key derivation inputs in the PSA API can now either come from a key object + or from a buffer regardless of the step type. + * The CTR_DRBG module can grab a nonce from the entropy source during the + initial seeding. The default nonce length is chosen based on the key size + to achieve the security strength defined by NIST SP 800-90A. You can + change it with mbedtls_ctr_drbg_set_nonce_len(). + * Add ENUMERATED tag support to the ASN.1 module. Contributed by + msopiha-linaro in ARMmbed/mbed-crypto#307. + +API changes + * In the PSA API, forbid zero-length keys. To pass a zero-length input to a + key derivation function, use a buffer instead (this is now always + possible). + * Rename psa_asymmetric_sign() to psa_sign_hash() and + psa_asymmetric_verify() to psa_verify_hash(). + +Bugfix + * Fix an incorrect size in a debugging message. Reported and fix + submitted by irwir. Fixes #2717. + * Fix an unused variable warning when compiling without DTLS. + Reported and fix submitted by irwir. Fixes #2800. + * Remove a useless assignment. Reported and fix submitted by irwir. + Fixes #2801. + * Fix a buffer overflow in the PSA HMAC code when using a long key with an + unsupported algorithm. Fixes ARMmbed/mbed-crypto#254. + * Fix mbedtls_asn1_get_int to support any number of leading zeros. Credit + to OSS-Fuzz for finding a bug in an intermediate version of the fix. + * Fix mbedtls_asn1_get_bitstring_null to correctly parse bitstrings of at + most 2 bytes. + * mbedtls_ctr_drbg_set_entropy_len() and + mbedtls_hmac_drbg_set_entropy_len() now work if you call them before + mbedtls_ctr_drbg_seed() or mbedtls_hmac_drbg_seed(). + +Changes + * Remove the technical possibility to define custom mbedtls_md_info + structures, which was exposed only in an internal header. + * psa_close_key(0) and psa_destroy_key(0) now succeed (doing nothing, as + before). + * Variables containing error codes are now initialized to an error code + rather than success, so that coding mistakes or memory corruption tends to + cause functions to return this error code rather than a success. There are + no known instances where this changes the behavior of the library: this is + merely a robustness improvement. ARMmbed/mbed-crypto#323 + * Remove a useless call to mbedtls_ecp_group_free(). Contributed by + Alexander Krizhanovsky in ARMmbed/mbed-crypto#210. + * Speed up PBKDF2 by caching the digest calculation. Contributed by Jack + Lloyd and Fortanix Inc in ARMmbed/mbed-crypto#277. + * Small performance improvement of mbedtls_mpi_div_mpi(). Contributed by + Alexander Krizhanovsky in ARMmbed/mbed-crypto#308. + += mbed TLS 2.19.1 branch released 2019-09-16 + +Features + * Declare include headers as PUBLIC to propagate to CMake project consumers + Contributed by Zachary J. Fields in PR #2949. + * Add nss_keylog to ssl_client2 and ssl_server2, enabling easier analysis of + TLS sessions with tools like Wireshark. + +API Changes + * Make client_random and server_random const in + mbedtls_ssl_export_keys_ext_t, so that the key exporter is discouraged + from modifying the client/server hello. + +Bugfix + * Fix some false-positive uninitialized variable warnings in crypto. Fix + contributed by apple-ihack-geek in #2663. + += mbed TLS 2.19.0 branch released 2019-09-06 + +Security + * Fix a missing error detection in ECJPAKE. This could have caused a + predictable shared secret if a hardware accelerator failed and the other + side of the key exchange had a similar bug. + * When writing a private EC key, use a constant size for the private + value, as specified in RFC 5915. Previously, the value was written + as an ASN.1 INTEGER, which caused the size of the key to leak + about 1 bit of information on average and could cause the value to be + 1 byte too large for the output buffer. + * The deterministic ECDSA calculation reused the scheme's HMAC-DRBG to + implement blinding. Because of this for the same key and message the same + blinding value was generated. This reduced the effectiveness of the + countermeasure and leaked information about the private key through side + channels. Reported by Jack Lloyd. + +Features + * Add new API functions mbedtls_ssl_session_save() and + mbedtls_ssl_session_load() to allow serializing a session, for example to + store it in non-volatile storage, and later using it for TLS session + resumption. + * Add a new API function mbedtls_ssl_check_record() to allow checking that + an incoming record is valid, authentic and has not been seen before. This + feature can be used alongside Connection ID and SSL context serialisation. + The feature is enabled at compile-time by MBEDTLS_SSL_RECORD_CHECKING + option. + * New implementation of X25519 (ECDH using Curve25519) from Project Everest + (https://project-everest.github.io/). It can be enabled at compile time + with MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED. This implementation is formally + verified and significantly faster, but is only supported on x86 platforms + (32-bit and 64-bit) using GCC, Clang or Visual Studio. Contributed by + Christoph Wintersteiger from Microsoft Research. + * Add mbedtls_net_close(), enabling the building of forking servers where + the parent process closes the client socket and continue accepting, and + the child process closes the listening socket and handles the client + socket. Contributed by Robert Larsen in #2803. + +API Changes + * Add DER-encoded test CRTs to library/certs.c, allowing + the example programs ssl_server2 and ssl_client2 to be run + if MBEDTLS_FS_IO and MBEDTLS_PEM_PARSE_C are unset. Fixes #2254. + * The HAVEGE state type now uses uint32_t elements instead of int. + * The functions mbedtls_ecp_curve_list() and mbedtls_ecp_grp_id_list() now + list all curves for which at least one of ECDH or ECDSA is supported, not + just curves for which both are supported. Call mbedtls_ecdsa_can_do() or + mbedtls_ecdh_can_do() on each result to check whether each algorithm is + supported. + * The new function mbedtls_ecdsa_sign_det_ext() is similar to + mbedtls_ecdsa_sign_det() but allows passing an external RNG for the + purpose of blinding. + +New deprecations + * Deprecate mbedtls_ecdsa_sign_det() in favor of a functions that can take an + RNG function as an input. + * Calling mbedtls_ecdsa_write_signature() with NULL as the f_rng argument + is now deprecated. + +Bugfix + * Fix missing bounds checks in X.509 parsing functions that could + lead to successful parsing of ill-formed X.509 CRTs. Fixes #2437. + * Fix multiple X.509 functions previously returning ASN.1 low-level error + codes to always wrap these codes into X.509 high level error codes before + returning. Fixes #2431. + * Fix to allow building test suites with any warning that detects unused + functions. Fixes #1628. + * Fix typo in net_would_block(). Fixes #528 reported by github-monoculture. + * Remove redundant include file in timing.c. Fixes #2640 reported by irwir. + * Fix build failure when building with mingw on Windows by including + stdarg.h where needed. Fixes #2656. + * Fix Visual Studio Release x64 build configuration by inheriting + PlatformToolset from the project configuration. Fixes #1430 reported by + irwir. + * Enable Suite B with subset of ECP curves. Make sure the code compiles even + if some curves are not defined. Fixes #1591 reported by dbedev. + * Fix misuse of signed arithmetic in the HAVEGE module. #2598 + * Avoid use of statically sized stack buffers for certificate writing. + This previously limited the maximum size of DER encoded certificates + in mbedtls_x509write_crt_der() to 2Kb. Reported by soccerGB in #2631. + * Fix partial zeroing in x509_get_other_name. Found and fixed by ekse, #2716. + * Update test certificates that were about to expire. Reported by + Bernhard M. Wiedemann in #2357. + * Fix the build on ARMv5TE in ARM mode to not use assembly instructions + that are only available in Thumb mode. Fix contributed by Aurelien Jarno + in #2169. + * Fix propagation of restart contexts in restartable EC operations. + This could previously lead to segmentation faults in builds using an + address-sanitizer and enabling but not using MBEDTLS_ECP_RESTARTABLE. + * Fix memory leak in in mpi_miller_rabin(). Contributed by + Jens Wiklander in #2363 + * Improve code clarity in x509_crt module, removing false-positive + uninitialized variable warnings on some recent toolchains (GCC8, etc). + Discovered and fixed by Andy Gross (Linaro), #2392. + * Fix bug in endianness conversion in bignum module. This lead to + functionally incorrect code on bigendian systems which don't have + __BYTE_ORDER__ defined. Reported by Brendan Shanks. Fixes #2622. + +Changes + * Replace multiple uses of MD2 by SHA-256 in X.509 test suite. Fixes #821. + * Make it easier to define MBEDTLS_PARAM_FAILED as assert (which config.h + suggests). #2671 + * Make `make clean` clean all programs always. Fixes #1862. + * Add a Dockerfile and helper scripts (all-in-docker.sh, basic-in-docker.sh, + docker-env.sh) to simplify running test suites on a Linux host. Contributed + by Peter Kolbus (Garmin). + * Add `reproducible` option to `ssl_client2` and `ssl_server2` to enable + test runs without variability. Contributed by Philippe Antoine (Catena + cyber) in #2681. + * Extended .gitignore to ignore Visual Studio artifacts. Fixed by ConfusedSushi. + * Adds fuzz targets, especially for continuous fuzzing with OSS-Fuzz. + Contributed by Philippe Antoine (Catena cyber). + * Remove the crypto part of the library from Mbed TLS. The crypto + code and tests are now only available via Mbed Crypto, which + Mbed TLS references as a Git submodule. + += mbed TLS 2.18.1 branch released 2019-07-12 + +Bugfix + * Fix build failure when building with mingw on Windows by including + stdarg.h where needed. Fixes #2656. + +Changes + * Enable building of Mbed TLS as a CMake subproject. Suggested and fixed by + Ashley Duncan in #2609. + += mbed TLS 2.18.0 branch released 2019-06-11 + +Features + * Add the Any Policy certificate policy oid, as defined in + rfc 5280 section 4.2.1.4. + * It is now possible to use NIST key wrap mode via the mbedtls_cipher API. + Contributed by Jack Lloyd and Fortanix Inc. + * Add the Wi-SUN Field Area Network (FAN) device extended key usage. + * Add the oid certificate policy x509 extension. + * It is now possible to perform RSA PKCS v1.5 signatures with RIPEMD-160 digest. + Contributed by Jack Lloyd and Fortanix Inc. + * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes, + and the used tls-prf. + * Add public API for tls-prf function, according to requested enum. + * Add support for parsing otherName entries in the Subject Alternative Name + X.509 certificate extension, specifically type hardware module name, + as defined in RFC 4108 section 5. + * Add support for parsing certificate policies extension, as defined in + RFC 5280 section 4.2.1.4. Currently, only the "Any Policy" policy is + supported. + * List all SAN types in the subject_alt_names field of the certificate. + Resolves #459. + * Add support for draft-05 of the Connection ID extension, as specified + in https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05. + The Connection ID extension allows to keep DTLS connections beyond the + lifetime of the underlying transport by adding a connection identifier + to the DTLS record header. This identifier can be used to associated an + incoming record with the correct connection data even after the peer has + changed its IP or port. The feature is enabled at compile-time by setting + MBEDTLS_SSL_DTLS_CONNECTION_ID (disabled by default), and at run-time + through the new APIs mbedtls_ssl_conf_cid() and mbedtls_ssl_set_cid(). + + +API Changes + * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes, + and the used tls-prf. + * Add public API for tls-prf function, according to requested enum. + +Bugfix + * Fix private key DER output in the key_app_writer example. File contents + were shifted by one byte, creating an invalid ASN.1 tag. Fixed by + Christian Walther in #2239. + * Fix potential memory leak in X.509 self test. Found and fixed by + Junhwan Park, #2106. + * Reduce stack usage of hkdf tests. Fixes #2195. + * Fix 1-byte buffer overflow in mbedtls_mpi_write_string() when + used with negative inputs. Found by Guido Vranken in #2404. Credit to + OSS-Fuzz. + * Fix bugs in the AEAD test suite which would be exposed by ciphers which + either used both encrypt and decrypt key schedules, or which perform padding. + GCM and CCM were not affected. Fixed by Jack Lloyd. + * Fix incorrect default port number in ssl_mail_client example's usage. + Found and fixed by irwir. #2337 + * Add psa_util.h to test/cpp_dummy_build to fix build_default_make_gcc_and_cxx. + Fixed by Peter Kolbus (Garmin). #2579 + * Add missing parentheses around parameters in the definition of the + public macro MBEDTLS_X509_ID_FLAG. This could lead to invalid evaluation + in case operators binding less strongly than subtraction were used + for the parameter. + * Add a check for MBEDTLS_X509_CRL_PARSE_C in ssl_server2, guarding the crl + sni entry parameter. Reported by inestlerode in #560. + * Set the next sequence of the subject_alt_name to NULL when deleting + sequence on failure. Found and fix suggested by Philippe Antoine. + Credit to OSS-Fuzz. + +Changes + * Server's RSA certificate in certs.c was SHA-1 signed. In the default + mbedTLS configuration only SHA-2 signed certificates are accepted. + This certificate is used in the demo server programs, which lead the + client programs to fail at the peer's certificate verification + due to an unacceptable hash signature. The certificate has been + updated to one that is SHA-256 signed. Fix contributed by + Illya Gerasymchuk. + * Return from various debugging routines immediately if the + provided SSL context is unset. + * Remove dead code from bignum.c in the default configuration. + Found by Coverity, reported and fixed by Peter Kolbus (Garmin). Fixes #2309. + * Add test for minimal value of MBEDTLS_MPI_WINDOW_SIZE to all.sh. + Contributed by Peter Kolbus (Garmin). + * Change wording in the `mbedtls_ssl_conf_max_frag_len()`'s documentation to + improve clarity. Fixes #2258. + += mbed TLS 2.17.0 branch released 2019-03-19 + +Features + * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()` + which allows copy-less parsing of DER encoded X.509 CRTs, + at the cost of additional lifetime constraints on the input + buffer, but at the benefit of reduced RAM consumption. + * Add a new function mbedtls_asn1_write_named_bitstring() to write ASN.1 + named bitstring in DER as required by RFC 5280 Appendix B. + * Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites + from the default list (enabled by default). See + https://sweet32.info/SWEET32_CCS16.pdf. + +API Changes + * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`. + See the Features section for more information. + * Allow to opt in to the removal the API mbedtls_ssl_get_peer_cert() + for the benefit of saving RAM, by disabling the new compile-time + option MBEDTLS_SSL_KEEP_PEER_CERTIFICATE (enabled by default for + API stability). Disabling this option makes mbedtls_ssl_get_peer_cert() + always return NULL, and removes the peer_cert field from the + mbedtls_ssl_session structure which otherwise stores the peer's + certificate. + +Security + * Make mbedtls_ecdh_get_params return an error if the second key + belongs to a different group from the first. Before, if an application + passed keys that belonged to different group, the first key's data was + interpreted according to the second group, which could lead to either + an error or a meaningless output from mbedtls_ecdh_get_params. In the + latter case, this could expose at most 5 bits of the private key. + +Bugfix + * Fix a compilation issue with mbedtls_ecp_restart_ctx not being defined + when MBEDTLS_ECP_ALT is defined. Reported by jwhui. Fixes #2242. + * Run the AD too long test only if MBEDTLS_CCM_ALT is not defined. + Raised as a comment in #1996. + * Reduce the stack consumption of mbedtls_mpi_fill_random() which could + previously lead to a stack overflow on constrained targets. + * Add `MBEDTLS_SELF_TEST` for the mbedtls_self_test functions + in the header files, which missed the precompilation check. #971 + * Fix returning the value 1 when mbedtls_ecdsa_genkey failed. + * Remove a duplicate #include in a sample program. Fixed by Masashi Honma #2326. + * Remove the mbedtls namespacing from the header file, to fix a "file not found" + build error. Fixed by Haijun Gu #2319. + * Fix signed-to-unsigned integer conversion warning + in X.509 module. Fixes #2212. + * Reduce stack usage of `mpi_write_hlp()` by eliminating recursion. + Fixes #2190. + * Fix false failure in all.sh when backup files exist in include/mbedtls + (e.g. config.h.bak). Fixed by Peter Kolbus (Garmin) #2407. + * Ensure that unused bits are zero when writing ASN.1 bitstrings when using + mbedtls_asn1_write_bitstring(). + * Fix issue when writing the named bitstrings in KeyUsage and NsCertType + extensions in CSRs and CRTs that caused these bitstrings to not be encoded + correctly as trailing zeroes were not accounted for as unused bits in the + leading content octet. Fixes #1610. + +Changes + * Reduce RAM consumption during session renegotiation by not storing + the peer CRT chain and session ticket twice. + * Include configuration file in all header files that use configuration, + instead of relying on other header files that they include. + Inserted as an enhancement for #1371 + * Add support for alternative CSR headers, as used by Microsoft and defined + in RFC 7468. Found by Michael Ernst. Fixes #767. + * Correct many misspellings. Fixed by MisterDA #2371. + * Provide an abstraction of vsnprintf to allow alternative implementations + for platforms that don't provide it. Based on contributions by Joris Aerts + and Nathaniel Wesley Filardo. + * Fix clobber list in MIPS assembly for large integer multiplication. + Previously, this could lead to functionally incorrect assembly being + produced by some optimizing compilers, showing up as failures in + e.g. RSA or ECC signature operations. Reported in #1722, fix suggested + by Aurelien Jarno and submitted by Jeffrey Martin. + * Reduce the complexity of the timing tests. They were assuming more than the + underlying OS actually guarantees. + * Fix configuration queries in ssl-opt.h. #2030 + * Ensure that ssl-opt.h can be run in OS X. #2029 + * Re-enable certain interoperability tests in ssl-opt.sh which had previously + been disabled for lack of a sufficiently recent version of GnuTLS on the CI. + * Ciphersuites based on 3DES now have the lowest priority by default when + they are enabled. + += mbed TLS 2.16.0 branch released 2018-12-21 + +Features + * Add a new config.h option of MBEDTLS_CHECK_PARAMS that enables validation + of parameters in the API. This allows detection of obvious misuses of the + API, such as passing NULL pointers. The API of existing functions hasn't + changed, but requirements on parameters have been made more explicit in + the documentation. See the corresponding API documentation for each + function to see for which parameter values it is defined. This feature is + disabled by default. See its API documentation in config.h for additional + steps you have to take when enabling it. + +API Changes + * The following functions in the random generator modules have been + deprecated and replaced as shown below. The new functions change + the return type from void to int to allow returning error codes when + using MBEDTLS__ALT for the underlying AES or message digest + primitive. Fixes #1798. + mbedtls_ctr_drbg_update() -> mbedtls_ctr_drbg_update_ret() + mbedtls_hmac_drbg_update() -> mbedtls_hmac_drbg_update_ret() + * Extend ECDH interface to enable alternative implementations. + * Deprecate error codes of the form MBEDTLS_ERR_xxx_INVALID_KEY_LENGTH for + ARIA, CAMELLIA and Blowfish. These error codes will be replaced by + the more generic per-module error codes MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * Additional parameter validation checks have been added for the following + modules - AES, ARIA, Blowfish, CAMELLIA, CCM, GCM, DHM, ECP, ECDSA, ECDH, + ECJPAKE, SHA, Chacha20 and Poly1305, cipher, pk, RSA, and MPI. + Where modules have had parameter validation added, existing parameter + checks may have changed. Some modules, such as Chacha20 had existing + parameter validation whereas other modules had little. This has now been + changed so that the same level of validation is present in all modules, and + that it is now optional with the MBEDTLS_CHECK_PARAMS flag which by default + is off. That means that checks which were previously present by default + will no longer be. + +New deprecations + * Deprecate mbedtls_ctr_drbg_update and mbedtls_hmac_drbg_update + in favor of functions that can return an error code. + +Bugfix + * Fix for Clang, which was reporting a warning for the bignum.c inline + assembly for AMD64 targets creating string literals greater than those + permitted by the ISO C99 standard. Found by Aaron Jones. Fixes #482. + * Fix runtime error in `mbedtls_platform_entropy_poll()` when run + through qemu user emulation. Reported and fix suggested by randombit + in #1212. Fixes #1212. + * Fix an unsafe bounds check when restoring an SSL session from a ticket. + This could lead to a buffer overflow, but only in case ticket authentication + was broken. Reported and fix suggested by Guido Vranken in #659. + * Add explicit integer to enumeration type casts to example program + programs/pkey/gen_key which previously led to compilation failure + on some toolchains. Reported by phoenixmcallister. Fixes #2170. + * Fix double initialization of ECC hardware that made some accelerators + hang. + * Clarify documentation of mbedtls_ssl_set_own_cert() regarding the absence + of check for certificate/key matching. Reported by Attila Molnar, #507. + + = mbed TLS 2.15.1 branch released 2018-11-30 + + Changes + * Update the Mbed Crypto submodule to version 0.1.0b2. + + = mbed TLS 2.15.0 branch released 2018-11-23 + + Features + * Add an experimental build option, USE_CRYPTO_SUBMODULE, to enable use of + Mbed Crypto as the source of the cryptography implementation. + * Add an experimental configuration option, MBEDTLS_PSA_CRYPTO_C, to enable + the PSA Crypto API from Mbed Crypto when additionally used with the + USE_CRYPTO_SUBMODULE build option. + + Changes + * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx() + from the cipher abstraction layer. Fixes #2198. + += mbed TLS 2.14.1 branch released 2018-11-30 + +Security + * Fix timing variations and memory access variations in RSA PKCS#1 v1.5 + decryption that could lead to a Bleichenbacher-style padding oracle + attack. In TLS, this affects servers that accept ciphersuites based on + RSA decryption (i.e. ciphersuites whose name contains RSA but not + (EC)DH(E)). Discovered by Eyal Ronen (Weizmann Institute), Robert Gillham + (University of Adelaide), Daniel Genkin (University of Michigan), + Adi Shamir (Weizmann Institute), David Wong (NCC Group), and Yuval Yarom + (University of Adelaide, Data61). The attack is described in more detail + in the paper available here: http://cat.eyalro.net/cat.pdf CVE-2018-19608 + * In mbedtls_mpi_write_binary(), don't leak the exact size of the number + via branching and memory access patterns. An attacker who could submit + a plaintext for RSA PKCS#1 v1.5 decryption but only observe the timing + of the decryption and not its result could nonetheless decrypt RSA + plaintexts and forge RSA signatures. Other asymmetric algorithms may + have been similarly vulnerable. Reported by Eyal Ronen, Robert Gillham, + Daniel Genkin, Adi Shamir, David Wong and Yuval Yarom. + * Wipe sensitive buffers on the stack in the CTR_DRBG and HMAC_DRBG + modules. + +API Changes + * The new functions mbedtls_ctr_drbg_update_ret() and + mbedtls_hmac_drbg_update_ret() are similar to mbedtls_ctr_drbg_update() + and mbedtls_hmac_drbg_update() respectively, but the new functions + report errors whereas the old functions return void. We recommend that + applications use the new functions. + += mbed TLS 2.14.0 branch released 2018-11-19 + +Security + * Fix overly strict DN comparison when looking for CRLs belonging to a + particular CA. This previously led to ignoring CRLs when the CRL's issuer + name and the CA's subject name differed in their string encoding (e.g., + one using PrintableString and the other UTF8String) or in the choice of + upper and lower case. Reported by Henrik Andersson of Bosch GmbH in issue + #1784. + * Fix a flawed bounds check in server PSK hint parsing. In case the + incoming message buffer was placed within the first 64KiB of address + space and a PSK-(EC)DHE ciphersuite was used, this allowed an attacker + to trigger a memory access up to 64KiB beyond the incoming message buffer, + potentially leading to an application crash or information disclosure. + * Fix mbedtls_mpi_is_prime() to use more rounds of probabilistic testing. The + previous settings for the number of rounds made it practical for an + adversary to construct non-primes that would be erroneously accepted as + primes with high probability. This does not have an impact on the + security of TLS, but can matter in other contexts with numbers chosen + potentially by an adversary that should be prime and can be validated. + For example, the number of rounds was enough to securely generate RSA key + pairs or Diffie-Hellman parameters, but was insufficient to validate + Diffie-Hellman parameters properly. + See "Prime and Prejudice" by by Martin R. Albrecht and Jake Massimo and + Kenneth G. Paterson and Juraj Somorovsky. + +Features + * Add support for temporarily suspending expensive ECC computations after + some configurable amount of operations. This is intended to be used in + constrained, single-threaded systems where ECC is time consuming and can + block other operations until they complete. This is disabled by default, + but can be enabled by MBEDTLS_ECP_RESTARTABLE at compile time and + configured by mbedtls_ecp_set_max_ops() at runtime. It applies to the new + xxx_restartable functions in ECP, ECDSA, PK and X.509 (CRL not supported + yet), and to existing functions in ECDH and SSL (currently only + implemented client-side, for ECDHE-ECDSA ciphersuites in TLS 1.2, + including client authentication). + * Add support for Arm CPU DSP extensions to accelerate asymmetric key + operations. On CPUs where the extensions are available, they can accelerate + MPI multiplications used in ECC and RSA cryptography. Contributed by + Aurelien Jarno. + * Extend RSASSA-PSS signature to allow a smaller salt size. Previously, PSS + signature always used a salt with the same length as the hash, and returned + an error if this was not possible. Now the salt size may be up to two bytes + shorter. This allows the library to support all hash and signature sizes + that comply with FIPS 186-4, including SHA-512 with a 1024-bit key. + * Add support for 128-bit keys in CTR_DRBG. Note that using keys shorter + than 256 bits limits the security of generated material to 128 bits. + +API Changes + * Add a common error code of `MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED` for + a feature that is not supported by underlying alternative + implementations implementing cryptographic primitives. This is useful for + hardware accelerators that don't implement all options or features. + +New deprecations + * All module specific errors following the form + MBEDTLS_ERR_XXX_FEATURE_UNAVAILABLE that indicate a feature is not + supported are deprecated and are now replaced by the new equivalent + platform error. + * All module specific generic hardware acceleration errors following the + form MBEDTLS_ERR_XXX_HW_ACCEL_FAILED that are deprecated and are replaced + by the equivalent plaform error. + * Deprecate the function mbedtls_mpi_is_prime() in favor of + mbedtls_mpi_is_prime_ext() which allows specifying the number of + Miller-Rabin rounds. + +Bugfix + * Fix wrong order of freeing in programs/ssl/ssl_server2 example + application leading to a memory leak in case both + MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE are set. + Fixes #2069. + * Fix a bug in the update function for SSL ticket keys which previously + invalidated keys of a lifetime of less than a 1s. Fixes #1968. + * Fix failure in hmac_drbg in the benchmark sample application, when + MBEDTLS_THREADING_C is defined. Found by TrinityTonic, #1095 + * Fix a bug in the record decryption routine ssl_decrypt_buf() + which lead to accepting properly authenticated but improperly + padded records in case of CBC ciphersuites using Encrypt-then-MAC. + * Fix memory leak and freeing without initialization in the example + program programs/x509/cert_write. Fixes #1422. + * Ignore IV in mbedtls_cipher_set_iv() when the cipher mode is + MBEDTLS_MODE_ECB. Found by ezdevelop. Fixes #1091. + * Zeroize memory used for buffering or reassembling handshake messages + after use. + * Use `mbedtls_platform_zeroize()` instead of `memset()` for zeroization + of sensitive data in the example programs aescrypt2 and crypt_and_hash. + * Change the default string format used for various X.509 DN attributes to + UTF8String. Previously, the use of the PrintableString format led to + wildcards and non-ASCII characters being unusable in some DN attributes. + Reported by raprepo in #1860 and by kevinpt in #468. Fix contributed by + Thomas-Dee. + * Fix compilation failure for configurations which use compile time + replacements of standard calloc/free functions through the macros + MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO. + Reported by ole-de and ddhome2006. Fixes #882, #1642 and #1706. + +Changes + * Removed support for Yotta as a build tool. + * Add tests for session resumption in DTLS. + * Close a test gap in (D)TLS between the client side and the server side: + test the handling of large packets and small packets on the client side + in the same way as on the server side. + * Change the dtls_client and dtls_server samples to work by default over + IPv6 and optionally by a build option over IPv4. + * Change the use of Windows threading to use Microsoft Visual C++ runtime + calls, rather than Win32 API calls directly. This is necessary to avoid + conflict with C runtime usage. Found and fixed by irwir. + * Remember the string format of X.509 DN attributes when replicating + X.509 DNs. Previously, DN attributes were always written in their default + string format (mostly PrintableString), which could lead to CRTs being + created which used PrintableStrings in the issuer field even though the + signing CA used UTF8Strings in its subject field; while X.509 compliant, + such CRTs were rejected in some applications, e.g. some versions of + Firefox, curl and GnuTLS. Reported in #1033 by Moschn. Fix contributed by + Thomas-Dee. + * Improve documentation of mbedtls_ssl_get_verify_result(). + Fixes #517 reported by github-monoculture. + * Add MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR flag to mbedtls_mpi_gen_prime() and + use it to reduce error probability in RSA key generation to levels mandated + by FIPS-186-4. + += mbed TLS 2.13.1 branch released 2018-09-06 + +API Changes + * Extend the platform module with an abstraction mbedtls_platform_gmtime_r() + whose implementation should behave as a thread-safe version of gmtime(). + This allows users to configure such an implementation at compile time when + the target system cannot be deduced automatically, by setting the option + MBEDTLS_PLATFORM_GMTIME_R_ALT. At this stage Mbed TLS is only able to + automatically select implementations for Windows and POSIX C libraries. + +Bugfix + * Fix build failures on platforms where only gmtime() is available but + neither gmtime_r() nor gmtime_s() are present. Fixes #1907. + += mbed TLS 2.13.0 branch released 2018-08-31 + +Security + * Fix an issue in the X.509 module which could lead to a buffer overread + during certificate extensions parsing. In case of receiving malformed + input (extensions length field equal to 0), an illegal read of one byte + beyond the input buffer is made. Found and analyzed by Nathan Crandall. + +Features + * Add support for fragmentation of outgoing DTLS handshake messages. This + is controlled by the maximum fragment length as set locally or negotiated + with the peer, as well as by a new per-connection MTU option, set using + mbedtls_ssl_set_mtu(). + * Add support for auto-adjustment of MTU to a safe value during the + handshake when flights do not get through (RFC 6347, section 4.1.1.1, + last paragraph). + * Add support for packing multiple records within a single datagram, + enabled by default. + * Add support for buffering out-of-order handshake messages in DTLS. + The maximum amount of RAM used for this can be controlled by the + compile-time constant MBEDTLS_SSL_DTLS_MAX_BUFFERING defined + in mbedtls/config.h. + +API Changes + * Add function mbedtls_ssl_set_datagram_packing() to configure + the use of datagram packing (enabled by default). + +Bugfix + * Fix a potential memory leak in mbedtls_ssl_setup() function. An allocation + failure in the function could lead to other buffers being leaked. + * Fixes an issue with MBEDTLS_CHACHAPOLY_C which would not compile if + MBEDTLS_ARC4_C and MBEDTLS_CIPHER_NULL_CIPHER weren't also defined. #1890 + * Fix a memory leak in ecp_mul_comb() if ecp_precompute_comb() fails. + Fix contributed by Espressif Systems. + * Add ecc extensions only if an ecc based ciphersuite is used. + This improves compliance to RFC 4492, and as a result, solves + interoperability issues with BouncyCastle. Raised by milenamil in #1157. + * Replace printf with mbedtls_printf in the ARIA module. Found by + TrinityTonic in #1908. + * Fix potential use-after-free in mbedtls_ssl_get_max_frag_len() + and mbedtls_ssl_get_record_expansion() after a session reset. Fixes #1941. + * Fix a bug that caused SSL/TLS clients to incorrectly abort the handshake + with TLS versions 1.1 and earlier when the server requested authentication + without providing a list of CAs. This was due to an overly strict bounds + check in parsing the CertificateRequest message, + introduced in Mbed TLS 2.12.0. Fixes #1954. + * Fix a miscalculation of the maximum record expansion in + mbedtls_ssl_get_record_expansion() in case of ChachaPoly ciphersuites, + or CBC ciphersuites in (D)TLS versions 1.1 or higher. Fixes #1913, #1914. + * Fix undefined shifts with negative values in certificates parsing + (found by Catena cyber using oss-fuzz) + * Fix memory leak and free without initialization in pk_encrypt + and pk_decrypt example programs. Reported by Brace Stout. Fixes #1128. + * Remove redundant else statement. Raised by irwir. Fixes #1776. + +Changes + * Copy headers preserving timestamps when doing a "make install". + Contributed by xueruini. + * Allow the forward declaration of public structs. Contributed by Dawid + Drozd. Fixes #1215 raised by randombit. + * Improve compatibility with some alternative CCM implementations by using + CCM test vectors from RAM. + * Add support for buffering of out-of-order handshake messages. + * Add warnings to the documentation of the HKDF module to reduce the risk + of misusing the mbedtls_hkdf_extract() and mbedtls_hkdf_expand() + functions. Fixes #1775. Reported by Brian J. Murray. + += mbed TLS 2.12.0 branch released 2018-07-25 + +Security + * Fix a vulnerability in TLS ciphersuites based on CBC and using SHA-384, + in (D)TLS 1.0 to 1.2, that allowed an active network attacker to + partially recover the plaintext of messages under some conditions by + exploiting timing measurements. With DTLS, the attacker could perform + this recovery by sending many messages in the same connection. With TLS + or if mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only + worked if the same secret (for example a HTTP Cookie) has been repeatedly + sent over connections manipulated by the attacker. Connections using GCM + or CCM instead of CBC, using hash sizes other than SHA-384, or using + Encrypt-then-Mac (RFC 7366) were not affected. The vulnerability was + caused by a miscalculation (for SHA-384) in a countermeasure to the + original Lucky 13 attack. Found by Kenny Paterson, Eyal Ronen and Adi + Shamir. + * Fix a vulnerability in TLS ciphersuites based on CBC, in (D)TLS 1.0 to + 1.2, that allowed a local attacker, able to execute code on the local + machine as well as manipulate network packets, to partially recover the + plaintext of messages under some conditions by using a cache attack + targeting an internal MD/SHA buffer. With TLS or if + mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only worked if + the same secret (for example a HTTP Cookie) has been repeatedly sent over + connections manipulated by the attacker. Connections using GCM or CCM + instead of CBC or using Encrypt-then-Mac (RFC 7366) were not affected. + Found by Kenny Paterson, Eyal Ronen and Adi Shamir. + * Add a counter-measure against a vulnerability in TLS ciphersuites based + on CBC, in (D)TLS 1.0 to 1.2, that allowed a local attacker, able to + execute code on the local machine as well as manipulate network packets, + to partially recover the plaintext of messages under some conditions (see + previous entry) by using a cache attack targeting the SSL input record + buffer. Connections using GCM or CCM instead of CBC or using + Encrypt-then-Mac (RFC 7366) were not affected. Found by Kenny Paterson, + Eyal Ronen and Adi Shamir. + +Features + * Add new crypto primitives from RFC 7539: stream cipher Chacha20, one-time + authenticator Poly1305 and AEAD construct Chacha20-Poly1305. Contributed + by Daniel King. + * Add support for CHACHA20-POLY1305 ciphersuites from RFC 7905. + * Add platform support for the Haiku OS. (https://www.haiku-os.org). + Contributed by Augustin Cavalier. + * Make the receive and transmit buffers independent sizes, for situations + where the outgoing buffer can be fixed at a smaller size than the incoming + buffer, which can save some RAM. If buffer lengths are kept equal, there + is no functional difference. Contributed by Angus Gratton, and also + independently contributed again by Paul Sokolovsky. + * Add support for key wrapping modes based on AES as defined by + NIST SP 800-38F algorithms KW and KWP and by RFC 3394 and RFC 5649. + +Bugfix + * Fix the key_app_writer example which was writing a leading zero byte which + was creating an invalid ASN.1 tag. Found by Aryeh R. Fixes #1257. + * Fix compilation error on C++, because of a variable named new. + Found and fixed by Hirotaka Niisato in #1783. + * Fix "no symbols" warning issued by ranlib when building on Mac OS X. Fix + contributed by tabascoeye. + * Clarify documentation for mbedtls_ssl_write() to include 0 as a valid + return value. Found by @davidwu2000. #839 + * Fix a memory leak in mbedtls_x509_csr_parse(), found by catenacyber, + Philippe Antoine. Fixes #1623. + * Remove unused headers included in x509.c. Found by Chris Hanson and fixed + by Brendan Shanks. Part of a fix for #992. + * Fix compilation error when MBEDTLS_ARC4_C is disabled and + MBEDTLS_CIPHER_NULL_CIPHER is enabled. Found by TrinityTonic in #1719. + * Added length checks to some TLS parsing functions. Found and fixed by + Philippe Antoine from Catena cyber. #1663. + * Fix the inline assembly for the MPI multiply helper function for i386 and + i386 with SSE2. Found by László Langó. Fixes #1550 + * Fix namespacing in header files. Remove the `mbedtls` namespacing in + the `#include` in the header files. Resolves #857 + * Fix compiler warning of 'use before initialisation' in + mbedtls_pk_parse_key(). Found by Martin Boye Petersen and fixed by Dawid + Drozd. #1098 + * Fix decryption for zero length messages (which contain all padding) when a + CBC based ciphersuite is used together with Encrypt-then-MAC. Previously, + such a message was wrongly reported as an invalid record and therefore lead + to the connection being terminated. Seen most often with OpenSSL using + TLS 1.0. Reported by @kFYatek and by Conor Murphy on the forum. Fix + contributed by Espressif Systems. Fixes #1632 + * Fix ssl_client2 example to send application data with 0-length content + when the request_size argument is set to 0 as stated in the documentation. + Fixes #1833. + * Correct the documentation for `mbedtls_ssl_get_session()`. This API has + deep copy of the session, and the peer certificate is not lost. Fixes #926. + * Fix build using -std=c99. Fixed by Nick Wilson. + +Changes + * Fail when receiving a TLS alert message with an invalid length, or invalid + zero-length messages when using TLS 1.2. Contributed by Espressif Systems. + * Change the default behaviour of mbedtls_hkdf_extract() to return an error + when calling with a NULL salt and non-zero salt_len. Contributed by + Brian J Murray + * Change the shebang line in Perl scripts to look up perl in the PATH. + Contributed by fbrosson. + * Allow overriding the time on Windows via the platform-time abstraction. + Fixed by Nick Wilson. + * Use gmtime_r/gmtime_s for thread-safety. Fixed by Nick Wilson. + += mbed TLS 2.11.0 branch released 2018-06-18 + +Features + * Add additional block mode, OFB (Output Feedback), to the AES module and + cipher abstraction module. + * Implement the HMAC-based extract-and-expand key derivation function + (HKDF) per RFC 5869. Contributed by Thomas Fossati. + * Add support for the CCM* block cipher mode as defined in IEEE Std. 802.15.4. + * Add support for the XTS block cipher mode with AES (AES-XTS). + Contributed by Aorimn in pull request #414. + * In TLS servers, support offloading private key operations to an external + cryptoprocessor. Private key operations can be asynchronous to allow + non-blocking operation of the TLS server stack. + +Bugfix + * Fix the cert_write example to handle certificates signed with elliptic + curves as well as RSA. Fixes #777 found by dbedev. + * Fix for redefinition of _WIN32_WINNT to avoid overriding a definition + used by user applications. Found and fixed by Fabio Alessandrelli. + * Fix compilation warnings with IAR toolchain, on 32 bit platform. + Reported by rahmanih in #683 + * Fix braces in mbedtls_memory_buffer_alloc_status(). Found by sbranden, #552. + +Changes + * Changed CMake defaults for IAR to treat all compiler warnings as errors. + * Changed the Clang parameters used in the CMake build files to work for + versions later than 3.6. Versions of Clang earlier than this may no longer + work. Fixes #1072 + += mbed TLS 2.10.0 branch released 2018-06-06 + +Features + * Add support for ARIA cipher (RFC 5794) and associated TLS ciphersuites + (RFC 6209). Disabled by default, see MBEDTLS_ARIA_C in config.h + +API Changes + * Extend the platform module with a util component that contains + functionality shared by multiple Mbed TLS modules. At this stage + platform_util.h (and its associated platform_util.c) only contain + mbedtls_platform_zeroize(), which is a critical function from a security + point of view. mbedtls_platform_zeroize() needs to be regularly tested + against compilers to ensure that calls to it are not removed from the + output binary as part of redundant code elimination optimizations. + Therefore, mbedtls_platform_zeroize() is moved to the platform module to + facilitate testing and maintenance. + +Bugfix + * Fix an issue with MicroBlaze support in bn_mul.h which was causing the + build to fail. Found by zv-io. Fixes #1651. + +Changes + * Support TLS testing in out-of-source builds using cmake. Fixes #1193. + * Fix redundant declaration of mbedtls_ssl_list_ciphersuites. Raised by + TrinityTonic. #1359. + += mbed TLS 2.9.0 branch released 2018-04-30 + +Security + * Fix an issue in the X.509 module which could lead to a buffer overread + during certificate validation. Additionally, the issue could also lead to + unnecessary callback checks being made or to some validation checks to be + omitted. The overread could be triggered remotely, while the other issues + would require a non DER-compliant certificate to be correctly signed by a + trusted CA, or a trusted CA with a non DER-compliant certificate. Found by + luocm. Fixes #825. + * Fix the buffer length assertion in the ssl_parse_certificate_request() + function which led to an arbitrary overread of the message buffer. The + overreads could be caused by receiving a malformed message at the point + where an optional signature algorithms list is expected when the signature + algorithms section is too short. In builds with debug output, the overread + data is output with the debug data. + * Fix a client-side bug in the validation of the server's ciphersuite choice + which could potentially lead to the client accepting a ciphersuite it didn't + offer or a ciphersuite that cannot be used with the TLS or DTLS version + chosen by the server. This could lead to corruption of internal data + structures for some configurations. + +Features + * Add an option, MBEDTLS_AES_FEWER_TABLES, to dynamically compute smaller AES + tables during runtime, thereby reducing the RAM/ROM footprint by ~6KiB. + Suggested and contributed by jkivilin in pull request #394. + * Add initial support for Curve448 (RFC 7748). Only mbedtls_ecp_mul() and + ECDH primitive functions (mbedtls_ecdh_gen_public(), + mbedtls_ecdh_compute_shared()) are supported for now. Contributed by + Nicholas Wilson in pull request #348. + +API Changes + * Extend the public API with the function of mbedtls_net_poll() to allow user + applications to wait for a network context to become ready before reading + or writing. + * Add function mbedtls_ssl_check_pending() to the public API to allow + a check for whether more more data is pending to be processed in the + internal message buffers. + This function is necessary to determine when it is safe to idle on the + underlying transport in case event-driven IO is used. + +Bugfix + * Fix a spurious uninitialized variable warning in cmac.c. Fix independently + contributed by Brian J Murray and David Brown. + * Add missing dependencies in test suites that led to build failures + in configurations that omit certain hashes or public-key algorithms. + Fixes #1040. + * Fix C89 incompatibility in benchmark.c. Contributed by Brendan Shanks. + #1353 + * Add missing dependencies for MBEDTLS_HAVE_TIME_DATE and + MBEDTLS_VERSION_FEATURES in some test suites. Contributed by + Deomid Ryabkov. Fixes #1299, #1475. + * Fix the Makefile build process for building shared libraries on Mac OS X. + Fixed by mnacamura. + * Fix parsing of PKCS#8 encoded Elliptic Curve keys. Previously Mbed TLS was + unable to parse keys which had only the optional parameters field of the + ECPrivateKey structure. Found by Jethro Beekman, fixed in #1379. + * Return the plaintext data more quickly on unpadded CBC decryption, as + stated in the mbedtls_cipher_update() documentation. Contributed by + Andy Leiserson. + * Fix overriding and ignoring return values when parsing and writing to + a file in pk_sign program. Found by kevlut in #1142. + * Restrict usage of error code MBEDTLS_ERR_SSL_WANT_READ to situations + where data needs to be fetched from the underlying transport in order + to make progress. Previously, this error code was also occasionally + returned when unexpected messages were being discarded, ignoring that + further messages could potentially already be pending to be processed + in the internal buffers; these cases led to deadlocks when event-driven + I/O was used. Found and reported by Hubert Mis in #772. + * Fix buffer length assertions in the ssl_parse_certificate_request() + function which leads to a potential one byte overread of the message + buffer. + * Fix invalid buffer sizes passed to zlib during record compression and + decompression. + * Fix the soversion of libmbedcrypto to match the soversion of the + maintained 2.7 branch. The soversion was increased in Mbed TLS + version 2.7.1 to reflect breaking changes in that release, but the + increment was missed in 2.8.0 and later releases outside of the 2.7 branch. + +Changes + * Remove some redundant code in bignum.c. Contributed by Alexey Skalozub. + * Support cmake builds where Mbed TLS is a subproject. Fix contributed + independently by Matthieu Volat and Arne Schwabe. + * Improve testing in configurations that omit certain hashes or + public-key algorithms. Includes contributions by Gert van Dijk. + * Improve negative testing of X.509 parsing. + * Do not define global mutexes around readdir() and gmtime() in + configurations where the feature is disabled. Found and fixed by Gergely + Budai. + * Harden the function mbedtls_ssl_config_free() against misuse, so that it + doesn't leak memory if the user doesn't use mbedtls_ssl_conf_psk() and + instead incorrectly manipulates the configuration structure directly. + Found and fix submitted by junyeonLEE in #1220. + * Provide an empty implementation of mbedtls_pkcs5_pbes2() when + MBEDTLS_ASN1_PARSE_C is not enabled. This allows the use of PBKDF2 + without PBES2. Fixed by Marcos Del Sol Vives. + * Add the order of the base point as N in the mbedtls_ecp_group structure + for Curve25519 (other curves had it already). Contributed by Nicholas + Wilson #481 + * Improve the documentation of mbedtls_net_accept(). Contributed by Ivan + Krylov. + * Improve the documentation of mbedtls_ssl_write(). Suggested by + Paul Sokolovsky in #1356. + * Add an option in the Makefile to support ar utilities where the operation + letter must not be prefixed by '-', such as LLVM. Found and fixed by + Alex Hixon. + * Allow configuring the shared library extension by setting the DLEXT + environment variable when using the project makefiles. + * Optimize unnecessary zeroing in mbedtls_mpi_copy. Based on a contribution + by Alexey Skalozub in #405. + * In the SSL module, when f_send, f_recv or f_recv_timeout report + transmitting more than the required length, return an error. Raised by + Sam O'Connor in #1245. + * Improve robustness of mbedtls_ssl_derive_keys against the use of + HMAC functions with non-HMAC ciphersuites. Independently contributed + by Jiayuan Chen in #1377. Fixes #1437. + * Improve security of RSA key generation by including criteria from + FIPS 186-4. Contributed by Jethro Beekman. #1380 + * Declare functions in header files even when an alternative implementation + of the corresponding module is activated by defining the corresponding + MBEDTLS_XXX_ALT macro. This means that alternative implementations do + not need to copy the declarations, and ensures that they will have the + same API. + * Add platform setup and teardown calls in test suites. + += mbed TLS 2.8.0 branch released 2018-03-16 + +Default behavior changes + * The truncated HMAC extension now conforms to RFC 6066. This means + that when both sides of a TLS connection negotiate the truncated + HMAC extension, Mbed TLS can now interoperate with other + compliant implementations, but this breaks interoperability with + prior versions of Mbed TLS. To restore the old behavior, enable + the (deprecated) option MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT in + config.h. Found by Andreas Walz (ivESK, Offenburg University of + Applied Sciences). + +Security + * Fix implementation of the truncated HMAC extension. The previous + implementation allowed an offline 2^80 brute force attack on the + HMAC key of a single, uninterrupted connection (with no + resumption of the session). + * Verify results of RSA private key operations to defend + against Bellcore glitch attack. + * Fix a buffer overread in ssl_parse_server_key_exchange() that could cause + a crash on invalid input. + * Fix a buffer overread in ssl_parse_server_psk_hint() that could cause a + crash on invalid input. + * Fix CRL parsing to reject CRLs containing unsupported critical + extensions. Found by Falko Strenzke and Evangelos Karatsiolis. + +Features + * Extend PKCS#8 interface by introducing support for the entire SHA + algorithms family when encrypting private keys using PKCS#5 v2.0. + This allows reading encrypted PEM files produced by software that + uses PBKDF2-SHA2, such as OpenSSL 1.1. Submitted by Antonio Quartulli, + OpenVPN Inc. Fixes #1339 + * Add support for public keys encoded in PKCS#1 format. #1122 + +New deprecations + * Deprecate support for record compression (configuration option + MBEDTLS_ZLIB_SUPPORT). + +Bugfix + * Fix the name of a DHE parameter that was accidentally changed in 2.7.0. + Fixes #1358. + * Fix test_suite_pk to work on 64-bit ILP32 systems. #849 + * Fix mbedtls_x509_crt_profile_suiteb, which used to reject all certificates + with flag MBEDTLS_X509_BADCERT_BAD_PK even when the key type was correct. + In the context of SSL, this resulted in handshake failure. Reported by + daniel in the Mbed TLS forum. #1351 + * Fix Windows x64 builds with the included mbedTLS.sln file. #1347 + * Fix setting version TLSv1 as minimal version, even if TLS 1 + is not enabled. Set MBEDTLS_SSL_MIN_MAJOR_VERSION + and MBEDTLS_SSL_MIN_MINOR_VERSION instead of + MBEDTLS_SSL_MAJOR_VERSION_3 and MBEDTLS_SSL_MINOR_VERSION_1. #664 + * Fix compilation error on Mingw32 when _TRUNCATE is defined. Use _TRUNCATE + only if __MINGW32__ not defined. Fix suggested by Thomas Glanzmann and + Nick Wilson on issue #355 + * In test_suite_pk, pass valid parameters when testing for hash length + overflow. #1179 + * Fix memory allocation corner cases in memory_buffer_alloc.c module. Found + by Guido Vranken. #639 + * Log correct number of ciphersuites used in Client Hello message. #918 + * Fix X509 CRT parsing that would potentially accept an invalid tag when + parsing the subject alternative names. + * Fix a possible arithmetic overflow in ssl_parse_server_key_exchange() + that could cause a key exchange to fail on valid data. + * Fix a possible arithmetic overflow in ssl_parse_server_psk_hint() that + could cause a key exchange to fail on valid data. + * Don't define mbedtls_aes_decrypt and mbedtls_aes_encrypt under + MBEDTLS_DEPRECATED_REMOVED. #1388 + * Fix a 1-byte heap buffer overflow (read-only) during private key parsing. + Found through fuzz testing. + +Changes + * Fix tag lengths and value ranges in the documentation of CCM encryption. + Contributed by Mathieu Briand. + * Fix typo in a comment ctr_drbg.c. Contributed by Paul Sokolovsky. + * Remove support for the library reference configuration for picocoin. + * MD functions deprecated in 2.7.0 are no longer inline, to provide + a migration path for those depending on the library's ABI. + * Clarify the documentation of mbedtls_ssl_setup. + * Use (void) when defining functions with no parameters. Contributed by + Joris Aerts. #678 + += mbed TLS 2.7.0 branch released 2018-02-03 + +Security + * Fix a heap corruption issue in the implementation of the truncated HMAC + extension. When the truncated HMAC extension is enabled and CBC is used, + sending a malicious application packet could be used to selectively corrupt + 6 bytes on the peer's heap, which could potentially lead to crash or remote + code execution. The issue could be triggered remotely from either side in + both TLS and DTLS. CVE-2018-0488 + * Fix a buffer overflow in RSA-PSS verification when the hash was too large + for the key size, which could potentially lead to crash or remote code + execution. Found by Seth Terashima, Qualcomm Product Security Initiative, + Qualcomm Technologies Inc. CVE-2018-0487 + * Fix buffer overflow in RSA-PSS verification when the unmasked data is all + zeros. + * Fix an unsafe bounds check in ssl_parse_client_psk_identity() when adding + 64 KiB to the address of the SSL buffer and causing a wrap around. + * Fix a potential heap buffer overflow in mbedtls_ssl_write(). When the (by + default enabled) maximum fragment length extension is disabled in the + config and the application data buffer passed to mbedtls_ssl_write + is larger than the internal message buffer (16384 bytes by default), the + latter overflows. The exploitability of this issue depends on whether the + application layer can be forced into sending such large packets. The issue + was independently reported by Tim Nordell via e-mail and by Florin Petriuc + and sjorsdewit on GitHub. Fix proposed by Florin Petriuc in #1022. + Fixes #707. + * Add a provision to prevent compiler optimizations breaking the time + constancy of mbedtls_ssl_safer_memcmp(). + * Ensure that buffers are cleared after use if they contain sensitive data. + Changes were introduced in multiple places in the library. + * Set PEM buffer to zero before freeing it, to avoid decoded private keys + being leaked to memory after release. + * Fix dhm_check_range() failing to detect trivial subgroups and potentially + leaking 1 bit of the private key. Reported by prashantkspatil. + * Make mbedtls_mpi_read_binary() constant-time with respect to the input + data. Previously, trailing zero bytes were detected and omitted for the + sake of saving memory, but potentially leading to slight timing + differences. Reported by Marco Macchetti, Kudelski Group. + * Wipe stack buffer temporarily holding EC private exponent + after keypair generation. + * Fix a potential heap buffer over-read in ALPN extension parsing + (server-side). Could result in application crash, but only if an ALPN + name larger than 16 bytes had been configured on the server. + * Change default choice of DHE parameters from untrustworthy RFC 5114 + to RFC 3526 containing parameters generated in a nothing-up-my-sleeve + manner. + +Features + * Allow comments in test data files. + * The selftest program can execute a subset of the tests based on command + line arguments. + * New unit tests for timing. Improve the self-test to be more robust + when run on a heavily-loaded machine. + * Add alternative implementation support for CCM and CMAC (MBEDTLS_CCM_ALT, + MBEDTLS_CMAC_ALT). Submitted by Steven Cooreman, Silicon Labs. + * Add support for alternative implementations of GCM, selected by the + configuration flag MBEDTLS_GCM_ALT. + * Add support for alternative implementations for ECDSA, controlled by new + configuration flags MBEDTLS_ECDSA_SIGN_ALT, MBEDTLS_ECDSA_VERIFY_ALT and + MBEDTLS_ECDSDA_GENKEY_AT in config.h. + The following functions from the ECDSA module can be replaced + with alternative implementation: + mbedtls_ecdsa_sign(), mbedtls_ecdsa_verify() and mbedtls_ecdsa_genkey(). + * Add support for alternative implementation of ECDH, controlled by the + new configuration flags MBEDTLS_ECDH_COMPUTE_SHARED_ALT and + MBEDTLS_ECDH_GEN_PUBLIC_ALT in config.h. + The following functions from the ECDH module can be replaced + with an alternative implementation: + mbedtls_ecdh_gen_public() and mbedtls_ecdh_compute_shared(). + * Add support for alternative implementation of ECJPAKE, controlled by + the new configuration flag MBEDTLS_ECJPAKE_ALT. + * Add mechanism to provide alternative implementation of the DHM module. + +API Changes + * Extend RSA interface by multiple functions allowing structure- + independent setup and export of RSA contexts. Most notably, + mbedtls_rsa_import() and mbedtls_rsa_complete() are introduced for setting + up RSA contexts from partial key material and having them completed to the + needs of the implementation automatically. This allows to setup private RSA + contexts from keys consisting of N,D,E only, even if P,Q are needed for the + purpose or CRT and/or blinding. + * The configuration option MBEDTLS_RSA_ALT can be used to define alternative + implementations of the RSA interface declared in rsa.h. + * The following functions in the message digest modules (MD2, MD4, MD5, + SHA1, SHA256, SHA512) have been deprecated and replaced as shown below. + The new functions change the return type from void to int to allow + returning error codes when using MBEDTLS__ALT. + mbedtls__starts() -> mbedtls__starts_ret() + mbedtls__update() -> mbedtls__update_ret() + mbedtls__finish() -> mbedtls__finish_ret() + mbedtls__process() -> mbedtls_internal__process() + +New deprecations + * Deprecate usage of RSA primitives with non-matching key-type + (e.g. signing with a public key). + * Direct manipulation of structure fields of RSA contexts is deprecated. + Users are advised to use the extended RSA API instead. + * Deprecate usage of message digest functions that return void + (mbedtls__starts, mbedtls__update, + mbedtls__finish and mbedtls__process where is + any of MD2, MD4, MD5, SHA1, SHA256, SHA512) in favor of functions + that can return an error code. + * Deprecate untrustworthy DHE parameters from RFC 5114. Superseded by + parameters from RFC 3526 or the newly added parameters from RFC 7919. + * Deprecate hex string DHE constants MBEDTLS_DHM_RFC3526_MODP_2048_P etc. + Supserseded by binary encoded constants MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN + etc. + * Deprecate mbedtls_ssl_conf_dh_param() for setting default DHE parameters + from hex strings. Superseded by mbedtls_ssl_conf_dh_param_bin() + accepting DHM parameters in binary form, matching the new constants. + +Bugfix + * Fix ssl_parse_record_header() to silently discard invalid DTLS records + as recommended in RFC 6347 Section 4.1.2.7. + * Fix memory leak in mbedtls_ssl_set_hostname() when called multiple times. + Found by projectgus and Jethro Beekman, #836. + * Fix usage help in ssl_server2 example. Found and fixed by Bei Lin. + * Parse signature algorithm extension when renegotiating. Previously, + renegotiated handshakes would only accept signatures using SHA-1 + regardless of the peer's preferences, or fail if SHA-1 was disabled. + * Fix leap year calculation in x509_date_is_valid() to ensure that invalid + dates on leap years with 100 and 400 intervals are handled correctly. Found + by Nicholas Wilson. #694 + * Fix some invalid RSA-PSS signatures with keys of size 8N+1 that were + accepted. Generating these signatures required the private key. + * Fix out-of-memory problem when parsing 4096-bit PKCS8-encrypted RSA keys. + Found independently by Florian in the mbed TLS forum and by Mishamax. + #878, #1019. + * Fix variable used before assignment compilation warnings with IAR + toolchain. Found by gkerrien38. + * Fix unchecked return codes from AES, DES and 3DES functions in + pem_aes_decrypt(), pem_des_decrypt() and pem_des3_decrypt() respectively. + If a call to one of the functions of the cryptographic primitive modules + failed, the error may not be noticed by the function + mbedtls_pem_read_buffer() causing it to return invalid values. Found by + Guido Vranken. #756 + * Include configuration file in md.h, to fix compilation warnings. + Reported by aaronmdjones in #1001 + * Correct extraction of signature-type from PK instance in X.509 CRT and CSR + writing routines that prevented these functions to work with alternative + RSA implementations. Raised by J.B. in the Mbed TLS forum. Fixes #1011. + * Don't print X.509 version tag for v1 CRT's, and omit extensions for + non-v3 CRT's. + * Fix bugs in RSA test suite under MBEDTLS_NO_PLATFORM_ENTROPY. #1023 #1024 + * Fix net_would_block() to avoid modification by errno through fcntl() call. + Found by nkolban. Fixes #845. + * Fix handling of handshake messages in mbedtls_ssl_read() in case + MBEDTLS_SSL_RENEGOTIATION is disabled. Found by erja-gp. + * Add a check for invalid private parameters in mbedtls_ecdsa_sign(). + Reported by Yolan Romailler. + * Fix word size check in in pk.c to not depend on MBEDTLS_HAVE_INT64. + * Fix incorrect unit in benchmark output. #850 + * Add size-checks for record and handshake message content, securing + fragile yet non-exploitable code-paths. + * Fix crash when calling mbedtls_ssl_cache_free() twice. Found by + MilenkoMitrovic, #1104 + * Fix mbedtls_timing_alarm(0) on Unix and MinGW. + * Fix use of uninitialized memory in mbedtls_timing_get_timer() when reset=1. + * Fix possible memory leaks in mbedtls_gcm_self_test(). + * Added missing return code checks in mbedtls_aes_self_test(). + * Fix issues in RSA key generation program programs/x509/rsa_genkey and the + RSA test suite where the failure of CTR DRBG initialization lead to + freeing an RSA context and several MPI's without proper initialization + beforehand. + * Fix error message in programs/pkey/gen_key.c. Found and fixed by Chris Xue. + * Fix programs/pkey/dh_server.c so that it actually works with dh_client.c. + Found and fixed by Martijn de Milliano. + * Fix an issue in the cipher decryption with the mode + MBEDTLS_PADDING_ONE_AND_ZEROS that sometimes accepted invalid padding. + Note, this padding mode is not used by the TLS protocol. Found and fixed by + Micha Kraus. + * Fix the entropy.c module to not call mbedtls_sha256_starts() or + mbedtls_sha512_starts() in the mbedtls_entropy_init() function. + * Fix the entropy.c module to ensure that mbedtls_sha256_init() or + mbedtls_sha512_init() is called before operating on the relevant context + structure. Do not assume that zeroizing a context is a correct way to + reset it. Found independently by ccli8 on Github. + * In mbedtls_entropy_free(), properly free the message digest context. + * Fix status handshake status message in programs/ssl/dtls_client.c. Found + and fixed by muddog. + +Changes + * Extend cert_write example program by options to set the certificate version + and the message digest. Further, allow enabling/disabling of authority + identifier, subject identifier and basic constraints extensions. + * Only check for necessary RSA structure fields in `mbedtls_rsa_private`. In + particular, don't require P,Q if neither CRT nor blinding are + used. Reported and fix proposed independently by satur9nine and sliai + on GitHub. + * Only run AES-192 self-test if AES-192 is available. Fixes #963. + * Tighten the RSA PKCS#1 v1.5 signature verification code and remove the + undeclared dependency of the RSA module on the ASN.1 module. + * Update all internal usage of deprecated message digest functions to the + new ones with return codes. In particular, this modifies the + mbedtls_md_info_t structure. Propagate errors from these functions + everywhere except some locations in the ssl_tls.c module. + * Improve CTR_DRBG error handling by propagating underlying AES errors. + * Add MBEDTLS_ERR_XXX_HW_ACCEL_FAILED error codes for all cryptography + modules where the software implementation can be replaced by a hardware + implementation. + * Add explicit warnings for the use of MD2, MD4, MD5, SHA-1, DES and ARC4 + throughout the library. + += mbed TLS 2.6.0 branch released 2017-08-10 + +Security + * Fix authentication bypass in SSL/TLS: when authmode is set to optional, + mbedtls_ssl_get_verify_result() would incorrectly return 0 when the peer's + X.509 certificate chain had more than MBEDTLS_X509_MAX_INTERMEDIATE_CA + (default: 8) intermediates, even when it was not trusted. This could be + triggered remotely from either side. (With authmode set to 'required' + (the default), the handshake was correctly aborted). + * Reliably wipe sensitive data after use in the AES example applications + programs/aes/aescrypt2 and programs/aes/crypt_and_hash. + Found by Laurent Simon. + +Features + * Add the functions mbedtls_platform_setup() and mbedtls_platform_teardown() + and the context struct mbedtls_platform_context to perform + platform-specific setup and teardown operations. The macro + MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT allows the functions to be overridden + by the user in a platform_alt.h file. These new functions are required in + some embedded environments to provide a means of initialising underlying + cryptographic acceleration hardware. + +API Changes + * Reverted API/ABI breaking changes introduced in mbed TLS 2.5.1, to make the + API consistent with mbed TLS 2.5.0. Specifically removed the inline + qualifier from the functions mbedtls_aes_decrypt, mbedtls_aes_encrypt, + mbedtls_ssl_ciphersuite_uses_ec and mbedtls_ssl_ciphersuite_uses_psk. Found + by James Cowgill. #978 + * Certificate verification functions now set flags to -1 in case the full + chain was not verified due to an internal error (including in the verify + callback) or chain length limitations. + * With authmode set to optional, the TLS handshake is now aborted if the + verification of the peer's certificate failed due to an overlong chain or + a fatal error in the verify callback. + +Bugfix + * Add a check if iv_len is zero in GCM, and return an error if it is zero. + Reported by roberto. #716 + * Replace preprocessor condition from #if defined(MBEDTLS_THREADING_PTHREAD) + to #if defined(MBEDTLS_THREADING_C) as the library cannot assume they will + always be implemented by pthread support. #696 + * Fix a resource leak on Windows platforms in mbedtls_x509_crt_parse_path(), + in the case of an error. Found by redplait. #590 + * Add MBEDTLS_MPI_CHK to check for error value of mbedtls_mpi_fill_random. + Reported and fix suggested by guidovranken. #740 + * Fix conditional preprocessor directives in bignum.h to enable 64-bit + compilation when using ARM Compiler 6. + * Fix a potential integer overflow in the version verification for DER + encoded X.509 CRLs. The overflow could enable maliciously constructed CRLs + to bypass the version verification check. Found by Peng Li/Yueh-Hsun Lin, + KNOX Security, Samsung Research America + * Fix potential integer overflow in the version verification for DER + encoded X.509 CSRs. The overflow could enable maliciously constructed CSRs + to bypass the version verification check. Found by Peng Li/Yueh-Hsun Lin, + KNOX Security, Samsung Research America + * Fix a potential integer overflow in the version verification for DER + encoded X.509 certificates. The overflow could enable maliciously + constructed certificates to bypass the certificate verification check. + * Fix a call to the libc function time() to call the platform abstraction + function mbedtls_time() instead. Found by wairua. #666 + * Avoid shadowing of time and index functions through mbed TLS function + arguments. Found by inestlerode. #557. + +Changes + * Added config.h option MBEDTLS_NO_UDBL_DIVISION, to prevent the use of + 64-bit division. This is useful on embedded platforms where 64-bit division + created a dependency on external libraries. #708 + * Removed mutexes from ECP hardware accelerator code. Now all hardware + accelerator code in the library leaves concurrency handling to the + platform. Reported by Steven Cooreman. #863 + * Define the macro MBEDTLS_AES_ROM_TABLES in the configuration file + config-no-entropy.h to reduce the RAM footprint. + * Added a test script that can be hooked into git that verifies commits + before they are pushed. + * Improve documentation of PKCS1 decryption functions. + += mbed TLS 2.5.1 released 2017-06-21 + +Security + * Fixed unlimited overread of heap-based buffer in mbedtls_ssl_read(). + The issue could only happen client-side with renegotiation enabled. + Could result in DoS (application crash) or information leak + (if the application layer sent data read from mbedtls_ssl_read() + back to the server or to a third party). Can be triggered remotely. + * Removed SHA-1 and RIPEMD-160 from the default hash algorithms for + certificate verification. SHA-1 can be turned back on with a compile-time + option if needed. + * Fixed offset in FALLBACK_SCSV parsing that caused TLS server to fail to + detect it sometimes. Reported by Hugo Leisink. #810 + * Tighten parsing of RSA PKCS#1 v1.5 signatures, to avoid a + potential Bleichenbacher/BERserk-style attack. + +Bugfix + * Remove size zero arrays from ECJPAKE test suite. Size zero arrays are not + valid C and they prevented the test from compiling in Visual Studio 2015 + and with GCC using the -Wpedantic compilation option. + * Fix insufficient support for signature-hash-algorithm extension, + resulting in compatibility problems with Chrome. Found by hfloyrd. #823 + * Fix behaviour that hid the original cause of fatal alerts in some cases + when sending the alert failed. The fix makes sure not to hide the error + that triggered the alert. + * Fix SSLv3 renegotiation behaviour and stop processing data received from + peer after sending a fatal alert to refuse a renegotiation attempt. + Previous behaviour was to keep processing data even after the alert has + been sent. + * Accept empty trusted CA chain in authentication mode + MBEDTLS_SSL_VERIFY_OPTIONAL. Found by Jethro Beekman. #864 + * Fix implementation of mbedtls_ssl_parse_certificate() to not annihilate + fatal errors in authentication mode MBEDTLS_SSL_VERIFY_OPTIONAL and to + reflect bad EC curves within verification result. + * Fix bug that caused the modular inversion function to accept the invalid + modulus 1 and therefore to hang. Found by blaufish. #641. + * Fix incorrect sign computation in modular exponentiation when the base is + a negative MPI. Previously the result was always negative. Found by Guido + Vranken. + * Fix a numerical underflow leading to stack overflow in mpi_read_file() + that was triggered uppon reading an empty line. Found by Guido Vranken. + +Changes + * Send fatal alerts in more cases. The previous behaviour was to skip + sending the fatal alert and just drop the connection. + * Clarify ECDSA documentation and improve the sample code to avoid + misunderstanding and potentially dangerous use of the API. Pointed out + by Jean-Philippe Aumasson. + += mbed TLS 2.5.0 branch released 2017-05-17 + +Security + * Wipe stack buffers in RSA private key operations + (rsa_rsaes_pkcs1_v15_decrypt(), rsa_rsaes_oaep_decrypt). Found by Laurent + Simon. + * Add exponent blinding to RSA private operations as a countermeasure + against side-channel attacks like the cache attack described in + https://arxiv.org/abs/1702.08719v2. + Found and fix proposed by Michael Schwarz, Samuel Weiser, Daniel Gruss, + Clémentine Maurice and Stefan Mangard. + +Features + * Add hardware acceleration support for the Elliptic Curve Point module. + This involved exposing parts of the internal interface to enable + replacing the core functions and adding and alternative, module level + replacement support for enabling the extension of the interface. + * Add a new configuration option to 'mbedtls_ssl_config' to enable + suppressing the CA list in Certificate Request messages. The default + behaviour has not changed, namely every configured CAs name is included. + +API Changes + * The following functions in the AES module have been deprecated and replaced + by the functions shown below. The new functions change the return type from + void to int to allow returning error codes when using MBEDTLS_AES_ALT, + MBEDTLS_AES_DECRYPT_ALT or MBEDTLS_AES_ENCRYPT_ALT. + mbedtls_aes_decrypt() -> mbedtls_internal_aes_decrypt() + mbedtls_aes_encrypt() -> mbedtls_internal_aes_encrypt() + +Bugfix + * Remove macros from compat-1.3.h that correspond to deleted items from most + recent versions of the library. Found by Kyle Keen. + * Fixed issue in the Threading module that prevented mutexes from + initialising. Found by sznaider. #667 #843 + * Add checks in the PK module for the RSA functions on 64-bit systems. + The PK and RSA modules use different types for passing hash length and + without these checks the type cast could lead to data loss. Found by Guido + Vranken. + += mbed TLS 2.4.2 branch released 2017-03-08 + +Security + * Add checks to prevent signature forgeries for very large messages while + using RSA through the PK module in 64-bit systems. The issue was caused by + some data loss when casting a size_t to an unsigned int value in the + functions rsa_verify_wrap(), rsa_sign_wrap(), rsa_alt_sign_wrap() and + mbedtls_pk_sign(). Found by Jean-Philippe Aumasson. + * Fixed potential livelock during the parsing of a CRL in PEM format in + mbedtls_x509_crl_parse(). A string containing a CRL followed by trailing + characters after the footer could result in the execution of an infinite + loop. The issue can be triggered remotely. Found by Greg Zaverucha, + Microsoft. + * Removed MD5 from the allowed hash algorithms for CertificateRequest and + CertificateVerify messages, to prevent SLOTH attacks against TLS 1.2. + Introduced by interoperability fix for #513. + * Fixed a bug that caused freeing a buffer that was allocated on the stack, + when verifying the validity of a key on secp224k1. This could be + triggered remotely for example with a maliciously constructed certificate + and potentially could lead to remote code execution on some platforms. + Reported independently by rongsaws and Aleksandar Nikolic, Cisco Talos + team. #569 CVE-2017-2784 + +Bugfix + * Fix output certificate verification flags set by x509_crt_verify_top() when + traversing a chain of trusted CA. The issue would cause both flags, + MBEDTLS_X509_BADCERT_NOT_TRUSTED and MBEDTLS_X509_BADCERT_EXPIRED, to be + set when the verification conditions are not met regardless of the cause. + Found by Harm Verhagen and inestlerode. #665 #561 + * Fix the redefinition of macro ssl_set_bio to an undefined symbol + mbedtls_ssl_set_bio_timeout in compat-1.3.h, by removing it. + Found by omlib-lin. #673 + * Fix unused variable/function compilation warnings in pem.c, x509_crt.c and + x509_csr.c that are reported when building mbed TLS with a config.h that + does not define MBEDTLS_PEM_PARSE_C. Found by omnium21. #562 + * Fix incorrect renegotiation condition in ssl_check_ctr_renegotiate() that + would compare 64 bits of the record counter instead of 48 bits as indicated + in RFC 6347 Section 4.3.1. This could cause the execution of the + renegotiation routines at unexpected times when the protocol is DTLS. Found + by wariua. #687 + * Fixed multiple buffer overreads in mbedtls_pem_read_buffer() when parsing + the input string in PEM format to extract the different components. Found + by Eyal Itkin. + * Fixed potential arithmetic overflow in mbedtls_ctr_drbg_reseed() that could + cause buffer bound checks to be bypassed. Found by Eyal Itkin. + * Fixed potential arithmetic overflows in mbedtls_cipher_update() that could + cause buffer bound checks to be bypassed. Found by Eyal Itkin. + * Fixed potential arithmetic overflow in mbedtls_md2_update() that could + cause buffer bound checks to be bypassed. Found by Eyal Itkin. + * Fixed potential arithmetic overflow in mbedtls_base64_decode() that could + cause buffer bound checks to be bypassed. Found by Eyal Itkin. + * Fixed heap overreads in mbedtls_x509_get_time(). Found by Peng + Li/Yueh-Hsun Lin, KNOX Security, Samsung Research America. + * Fix potential memory leak in mbedtls_x509_crl_parse(). The leak was caused + by missing calls to mbedtls_pem_free() in cases when a + MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT error was encountered. Found and + fix proposed by Guido Vranken. #722 + * Fixed the templates used to generate project and solution files for Visual + Studio 2015 as well as the files themselves, to remove a build warning + generated in Visual Studio 2015. Reported by Steve Valliere. #742 + * Fix a resource leak in ssl_cookie, when using MBEDTLS_THREADING_C. + Raised and fix suggested by Alan Gillingham in the mbed TLS forum. #771 + * Fix 1 byte buffer overflow in mbedtls_mpi_write_string() when the MPI + number to write in hexadecimal is negative and requires an odd number of + digits. Found and fixed by Guido Vranken. + * Fix unlisted DES configuration dependency in some pkparse test cases. Found + by inestlerode. #555 + += mbed TLS 2.4.1 branch released 2016-12-13 + +Changes + * Update to CMAC test data, taken from - NIST Special Publication 800-38B - + Recommendation for Block Cipher Modes of Operation: The CMAC Mode for + Authentication – October 2016 + += mbed TLS 2.4.0 branch released 2016-10-17 + +Security + * Removed the MBEDTLS_SSL_AEAD_RANDOM_IV option, because it was not compliant + with RFC-5116 and could lead to session key recovery in very long TLS + sessions. "Nonce-Disrespecting Adversaries Practical Forgery Attacks on GCM in + TLS" - H. Bock, A. Zauner, S. Devlin, J. Somorovsky, P. Jovanovic. + https://eprint.iacr.org/2016/475.pdf + * Fixed potential stack corruption in mbedtls_x509write_crt_der() and + mbedtls_x509write_csr_der() when the signature is copied to the buffer + without checking whether there is enough space in the destination. The + issue cannot be triggered remotely. Found by Jethro Beekman. + +Features + * Added support for CMAC for AES and 3DES and AES-CMAC-PRF-128, as defined by + NIST SP 800-38B, RFC-4493 and RFC-4615. + * Added hardware entropy selftest to verify that the hardware entropy source + is functioning correctly. + * Added a script to print build environment info for diagnostic use in test + scripts, which is also now called by all.sh. + * Added the macro MBEDTLS_X509_MAX_FILE_PATH_LEN that enables the user to + configure the maximum length of a file path that can be buffered when + calling mbedtls_x509_crt_parse_path(). + * Added a configuration file config-no-entropy.h that configures the subset of + library features that do not require an entropy source. + * Added the macro MBEDTLS_ENTROPY_MIN_HARDWARE in config.h. This allows users + to configure the minimum number of bytes for entropy sources using the + mbedtls_hardware_poll() function. + +Bugfix + * Fix for platform time abstraction to avoid dependency issues where a build + may need time but not the standard C library abstraction, and added + configuration consistency checks to check_config.h + * Fix dependency issue in Makefile to allow parallel builds. + * Fix incorrect handling of block lengths in crypt_and_hash.c sample program, + when GCM is used. Found by udf2457. #441 + * Fix for key exchanges based on ECDH-RSA or ECDH-ECDSA which weren't + enabled unless others were also present. Found by David Fernandez. #428 + * Fix for out-of-tree builds using CMake. Found by jwurzer, and fix based on + a contribution from Tobias Tangemann. #541 + * Fixed cert_app.c sample program for debug output and for use when no root + certificates are provided. + * Fix conditional statement that would cause a 1 byte overread in + mbedtls_asn1_get_int(). Found and fixed by Guido Vranken. #599 + * Fixed pthread implementation to avoid unintended double initialisations + and double frees. Found by Niklas Amnebratt. + * Fixed the sample applications gen_key.c, cert_req.c and cert_write.c for + builds where the configuration MBEDTLS_PEM_WRITE_C is not defined. Found + by inestlerode. #559. + * Fix mbedtls_x509_get_sig() to update the ASN1 type in the mbedtls_x509_buf + data structure until after error checks are successful. Found by + subramanyam-c. #622 + * Fix documentation and implementation missmatch for function arguments of + mbedtls_gcm_finish(). Found by cmiatpaar. #602 + * Guarantee that P>Q at RSA key generation. Found by inestlerode. #558 + * Fix potential byte overread when verifying malformed SERVER_HELLO in + ssl_parse_hello_verify_request() for DTLS. Found by Guido Vranken. + * Fix check for validity of date when parsing in mbedtls_x509_get_time(). + Found by subramanyam-c. #626 + * Fix compatibility issue with Internet Explorer client authentication, + where the limited hash choices prevented the client from sending its + certificate. Found by teumas. #513 + * Fix compilation without MBEDTLS_SELF_TEST enabled. + +Changes + * Extended test coverage of special cases, and added new timing test suite. + * Removed self-tests from the basic-built-test.sh script, and added all + missing self-tests to the test suites, to ensure self-tests are only + executed once. + * Added support for 3 and 4 byte lengths to mbedtls_asn1_write_len(). + * Added support for a Yotta specific configuration file - + through the symbol YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE. + * Added optimization for code space for X.509/OID based on configured + features. Contributed by Aviv Palivoda. + * Renamed source file library/net.c to library/net_sockets.c to avoid + naming collision in projects which also have files with the common name + net.c. For consistency, the corresponding header file, net.h, is marked as + deprecated, and its contents moved to net_sockets.h. + * Changed the strategy for X.509 certificate parsing and validation, to no + longer disregard certificates with unrecognised fields. + += mbed TLS 2.3.0 branch released 2016-06-28 + +Security + * Fix missing padding length check in mbedtls_rsa_rsaes_pkcs1_v15_decrypt + required by PKCS1 v2.2 + * Fix potential integer overflow to buffer overflow in + mbedtls_rsa_rsaes_pkcs1_v15_encrypt and mbedtls_rsa_rsaes_oaep_encrypt + (not triggerable remotely in (D)TLS). + * Fix a potential integer underflow to buffer overread in + mbedtls_rsa_rsaes_oaep_decrypt. It is not triggerable remotely in + SSL/TLS. + +Features + * Support for platform abstraction of the standard C library time() + function. + +Bugfix + * Fix bug in mbedtls_mpi_add_mpi() that caused wrong results when the three + arguments where the same (in-place doubling). Found and fixed by Janos + Follath. #309 + * Fix potential build failures related to the 'apidoc' target, introduced + in the previous patch release. Found by Robert Scheck. #390 #391 + * Fix issue in Makefile that prevented building using armar. #386 + * Fix memory leak that occurred only when ECJPAKE was enabled and ECDHE and + ECDSA was disabled in config.h . The leak didn't occur by default. + * Fix an issue that caused valid certificates to be rejected whenever an + expired or not yet valid certificate was parsed before a valid certificate + in the trusted certificate list. + * Fix bug in mbedtls_x509_crt_parse that caused trailing extra data in the + buffer after DER certificates to be included in the raw representation. + * Fix issue that caused a hang when generating RSA keys of odd bitlength + * Fix bug in mbedtls_rsa_rsaes_pkcs1_v15_encrypt that made null pointer + dereference possible. + * Fix issue that caused a crash if invalid curves were passed to + mbedtls_ssl_conf_curves. #373 + * Fix issue in ssl_fork_server which was preventing it from functioning. #429 + * Fix memory leaks in test framework + * Fix test in ssl-opt.sh that does not run properly with valgrind + * Fix unchecked calls to mmbedtls_md_setup(). Fix by Brian Murray. #502 + +Changes + * On ARM platforms, when compiling with -O0 with GCC, Clang or armcc5, + don't use the optimized assembly for bignum multiplication. This removes + the need to pass -fomit-frame-pointer to avoid a build error with -O0. + * Disabled SSLv3 in the default configuration. + * Optimized mbedtls_mpi_zeroize() for MPI integer size. (Fix by Alexey + Skalozub). + * Fix non-compliance server extension handling. Extensions for SSLv3 are now + ignored, as required by RFC6101. + += mbed TLS 2.2.1 released 2016-01-05 + +Security + * Fix potential double free when mbedtls_asn1_store_named_data() fails to + allocate memory. Only used for certificate generation, not triggerable + remotely in SSL/TLS. Found by RafaÅ‚ Przywara. #367 + * Disable MD5 handshake signatures in TLS 1.2 by default to prevent the + SLOTH attack on TLS 1.2 server authentication (other attacks from the + SLOTH paper do not apply to any version of mbed TLS or PolarSSL). + https://www.mitls.org/pages/attacks/SLOTH + +Bugfix + * Fix over-restrictive length limit in GCM. Found by Andreas-N. #362 + * Fix bug in certificate validation that caused valid chains to be rejected + when the first intermediate certificate has pathLenConstraint=0. Found by + Nicholas Wilson. Introduced in mbed TLS 2.2.0. #280 + * Removed potential leak in mbedtls_rsa_rsassa_pkcs1_v15_sign(), found by + JayaraghavendranK. #372 + * Fix suboptimal handling of unexpected records that caused interop issues + with some peers over unreliable links. Avoid dropping an entire DTLS + datagram if a single record in a datagram is unexpected, instead only + drop the record and look at subsequent records (if any are present) in + the same datagram. Found by jeannotlapin. #345 + += mbed TLS 2.2.0 released 2015-11-04 + +Security + * Fix potential double free if mbedtls_ssl_conf_psk() is called more than + once and some allocation fails. Cannot be forced remotely. Found by Guido + Vranken, Intelworks. + * Fix potential heap corruption on Windows when + mbedtls_x509_crt_parse_path() is passed a path longer than 2GB. Cannot be + triggered remotely. Found by Guido Vranken, Intelworks. + * Fix potential buffer overflow in some asn1_write_xxx() functions. + Cannot be triggered remotely unless you create X.509 certificates based + on untrusted input or write keys of untrusted origin. Found by Guido + Vranken, Intelworks. + * The X509 max_pathlen constraint was not enforced on intermediate + certificates. Found by Nicholas Wilson, fix and tests provided by + Janos Follath. #280 and #319 + +Features + * Experimental support for EC J-PAKE as defined in Thread 1.0.0. + Disabled by default as the specification might still change. + * Added a key extraction callback to accees the master secret and key + block. (Potential uses include EAP-TLS and Thread.) + +Bugfix + * Self-signed certificates were not excluded from pathlen counting, + resulting in some valid X.509 being incorrectly rejected. Found and fix + provided by Janos Follath. #319 + * Fix build error with configurations where ECDHE-PSK is the only key + exchange. Found and fix provided by Chris Hammond. #270 + * Fix build error with configurations where RSA, RSA-PSK, ECDH-RSA or + ECHD-ECDSA if the only key exchange. Multiple reports. #310 + * Fixed a bug causing some handshakes to fail due to some non-fatal alerts + not being properly ignored. Found by mancha and Kasom Koht-arsa, #308 + * mbedtls_x509_crt_verify(_with_profile)() now also checks the key type and + size/curve against the profile. Before that, there was no way to set a + minimum key size for end-entity certificates with RSA keys. Found by + Matthew Page of Scannex Electronics Ltd. + * Fix failures in MPI on Sparc(64) due to use of bad assembly code. + Found by Kurt Danielson. #292 + * Fix typo in name of the extKeyUsage OID. Found by inestlerode, #314 + * Fix bug in ASN.1 encoding of booleans that caused generated CA + certificates to be rejected by some applications, including OS X + Keychain. Found and fixed by Jonathan Leroy, Inikup. + +Changes + * Improved performance of mbedtls_ecp_muladd() when one of the scalars is 1 + or -1. + += mbed TLS 2.1.2 released 2015-10-06 + +Security + * Added fix for CVE-2015-5291 to prevent heap corruption due to buffer + overflow of the hostname or session ticket. Found by Guido Vranken, + Intelworks. + * Fix potential double-free if mbedtls_ssl_set_hs_psk() is called more than + once in the same handhake and mbedtls_ssl_conf_psk() was used. + Found and patch provided by Guido Vranken, Intelworks. Cannot be forced + remotely. + * Fix stack buffer overflow in pkcs12 decryption (used by + mbedtls_pk_parse_key(file)() when the password is > 129 bytes. + Found by Guido Vranken, Intelworks. Not triggerable remotely. + * Fix potential buffer overflow in mbedtls_mpi_read_string(). + Found by Guido Vranken, Intelworks. Not exploitable remotely in the context + of TLS, but might be in other uses. On 32 bit machines, requires reading a + string of close to or larger than 1GB to exploit; on 64 bit machines, would + require reading a string of close to or larger than 2^62 bytes. + * Fix potential random memory allocation in mbedtls_pem_read_buffer() + on crafted PEM input data. Found and fix provided by Guido Vranken, + Intelworks. Not triggerable remotely in TLS. Triggerable remotely if you + accept PEM data from an untrusted source. + * Fix possible heap buffer overflow in base64_encoded() when the input + buffer is 512MB or larger on 32-bit platforms. Found by Guido Vranken, + Intelworks. Not trigerrable remotely in TLS. + * Fix potential double-free if mbedtls_conf_psk() is called repeatedly on + the same mbedtls_ssl_config object and memory allocation fails. Found by + Guido Vranken, Intelworks. Cannot be forced remotely. + * Fix potential heap buffer overflow in servers that perform client + authentication against a crafted CA cert. Cannot be triggered remotely + unless you allow third parties to pick trust CAs for client auth. + Found by Guido Vranken, Intelworks. + +Bugfix + * Fix compile error in net.c with musl libc. Found and patch provided by + zhasha (#278). + * Fix macroization of 'inline' keyword when building as C++. (#279) + +Changes + * Added checking of hostname length in mbedtls_ssl_set_hostname() to ensure + domain names are compliant with RFC 1035. + * Fixed paths for check_config.h in example config files. (Found by bachp) + (#291) + += mbed TLS 2.1.1 released 2015-09-17 + +Security + * Add countermeasure against Lenstra's RSA-CRT attack for PKCS#1 v1.5 + signatures. (Found by Florian Weimer, Red Hat.) + https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/ + * Fix possible client-side NULL pointer dereference (read) when the client + tries to continue the handshake after it failed (a misuse of the API). + (Found and patch provided by Fabian Foerg, Gotham Digital Science using + afl-fuzz.) + +Bugfix + * Fix warning when using a 64bit platform. (found by embedthis) (#275) + * Fix off-by-one error in parsing Supported Point Format extension that + caused some handshakes to fail. + +Changes + * Made X509 profile pointer const in mbedtls_ssl_conf_cert_profile() to allow + use of mbedtls_x509_crt_profile_next. (found by NWilson) + * When a client initiates a reconnect from the same port as a live + connection, if cookie verification is available + (MBEDTLS_SSL_DTLS_HELLO_VERIFY defined in config.h, and usable cookie + callbacks set with mbedtls_ssl_conf_dtls_cookies()), this will be + detected and mbedtls_ssl_read() will return + MBEDTLS_ERR_SSL_CLIENT_RECONNECT - it is then possible to start a new + handshake with the same context. (See RFC 6347 section 4.2.8.) + += mbed TLS 2.1.0 released 2015-09-04 + +Features + * Added support for yotta as a build system. + * Primary open source license changed to Apache 2.0 license. + +Bugfix + * Fix segfault in the benchmark program when benchmarking DHM. + * Fix build error with CMake and pre-4.5 versions of GCC (found by Hugo + Leisink). + * Fix bug when parsing a ServerHello without extensions (found by David + Sears). + * Fix bug in CMake lists that caused libmbedcrypto.a not to be installed + (found by Benoit Lecocq). + * Fix bug in Makefile that caused libmbedcrypto and libmbedx509 not to be + installed (found by Rawi666). + * Fix compile error with armcc 5 with --gnu option. + * Fix bug in Makefile that caused programs not to be installed correctly + (found by robotanarchy) (#232). + * Fix bug in Makefile that prevented from installing without building the + tests (found by robotanarchy) (#232). + * Fix missing -static-libgcc when building shared libraries for Windows + with make. + * Fix link error when building shared libraries for Windows with make. + * Fix error when loading libmbedtls.so. + * Fix bug in mbedtls_ssl_conf_default() that caused the default preset to + be always used (found by dcb314) (#235) + * Fix bug in mbedtls_rsa_public() and mbedtls_rsa_private() that could + result trying to unlock an unlocked mutex on invalid input (found by + Fredrik Axelsson) (#257) + * Fix -Wshadow warnings (found by hnrkp) (#240) + * Fix memory corruption on client with overlong PSK identity, around + SSL_MAX_CONTENT_LEN or higher - not triggerrable remotely (found by + Aleksandrs Saveljevs) (#238) + * Fix unused function warning when using MBEDTLS_MDx_ALT or + MBEDTLS_SHAxxx_ALT (found by Henrik) (#239) + * Fix memory corruption in pkey programs (found by yankuncheng) (#210) + +Changes + * The PEM parser now accepts a trailing space at end of lines (#226). + * It is now possible to #include a user-provided configuration file at the + end of the default config.h by defining MBEDTLS_USER_CONFIG_FILE on the + compiler's command line. + * When verifying a certificate chain, if an intermediate certificate is + trusted, no later cert is checked. (suggested by hannes-landeholm) + (#220). + * Prepend a "thread identifier" to debug messages (issue pointed out by + Hugo Leisink) (#210). + * Add mbedtls_ssl_get_max_frag_len() to query the current maximum fragment + length. + += mbed TLS 2.0.0 released 2015-07-13 + +Features + * Support for DTLS 1.0 and 1.2 (RFC 6347). + * Ability to override core functions from MDx, SHAx, AES and DES modules + with custom implementation (eg hardware accelerated), complementing the + ability to override the whole module. + * New server-side implementation of session tickets that rotate keys to + preserve forward secrecy, and allows sharing across multiple contexts. + * Added a concept of X.509 cerificate verification profile that controls + which algorithms and key sizes (curves for ECDSA) are acceptable. + * Expanded configurability of security parameters in the SSL module with + mbedtls_ssl_conf_dhm_min_bitlen() and mbedtls_ssl_conf_sig_hashes(). + * Introduced a concept of presets for SSL security-relevant configuration + parameters. + +API Changes + * The library has been split into libmbedcrypto, libmbedx509, libmbedtls. + You now need to link to all of them if you use TLS for example. + * All public identifiers moved to the mbedtls_* or MBEDTLS_* namespace. + Some names have been further changed to make them more consistent. + Migration helpers scripts/rename.pl and include/mbedtls/compat-1.3.h are + provided. Full list of renamings in scripts/data_files/rename-1.3-2.0.txt + * Renamings of fields inside structures, not covered by the previous list: + mbedtls_cipher_info_t.key_length -> key_bitlen + mbedtls_cipher_context_t.key_length -> key_bitlen + mbedtls_ecp_curve_info.size -> bit_size + * Headers are now found in the 'mbedtls' directory (previously 'polarssl'). + * The following _init() functions that could return errors have + been split into an _init() that returns void and another function that + should generally be the first function called on this context after init: + mbedtls_ssl_init() -> mbedtls_ssl_setup() + mbedtls_ccm_init() -> mbedtls_ccm_setkey() + mbedtls_gcm_init() -> mbedtls_gcm_setkey() + mbedtls_hmac_drbg_init() -> mbedtls_hmac_drbg_seed(_buf)() + mbedtls_ctr_drbg_init() -> mbedtls_ctr_drbg_seed() + Note that for mbedtls_ssl_setup(), you need to be done setting up the + ssl_config structure before calling it. + * Most ssl_set_xxx() functions (all except ssl_set_bio(), ssl_set_hostname(), + ssl_set_session() and ssl_set_client_transport_id(), plus + ssl_legacy_renegotiation()) have been renamed to mbedtls_ssl_conf_xxx() + (see rename.pl and compat-1.3.h above) and their first argument's type + changed from ssl_context to ssl_config. + * ssl_set_bio() changed signature (contexts merged, order switched, one + additional callback for read-with-timeout). + * The following functions have been introduced and must be used in callback + implementations (SNI, PSK) instead of their *conf counterparts: + mbedtls_ssl_set_hs_own_cert() + mbedtls_ssl_set_hs_ca_chain() + mbedtls_ssl_set_hs_psk() + * mbedtls_ssl_conf_ca_chain() lost its last argument (peer_cn), now set + using mbedtls_ssl_set_hostname(). + * mbedtls_ssl_conf_session_cache() changed prototype (only one context + pointer, parameters reordered). + * On server, mbedtls_ssl_conf_session_tickets_cb() must now be used in + place of mbedtls_ssl_conf_session_tickets() to enable session tickets. + * The SSL debug callback gained two new arguments (file name, line number). + * Debug modes were removed. + * mbedtls_ssl_conf_truncated_hmac() now returns void. + * mbedtls_memory_buffer_alloc_init() now returns void. + * X.509 verification flags are now an uint32_t. Affect the signature of: + mbedtls_ssl_get_verify_result() + mbedtls_x509_ctr_verify_info() + mbedtls_x509_crt_verify() (flags, f_vrfy -> needs to be updated) + mbedtls_ssl_conf_verify() (f_vrfy -> needs to be updated) + * The following functions changed prototype to avoid an in-out length + parameter: + mbedtls_base64_encode() + mbedtls_base64_decode() + mbedtls_mpi_write_string() + mbedtls_dhm_calc_secret() + * In the NET module, all "int" and "int *" arguments for file descriptors + changed type to "mbedtls_net_context *". + * net_accept() gained new arguments for the size of the client_ip buffer. + * In the threading layer, mbedtls_mutex_init() and mbedtls_mutex_free() now + return void. + * ecdsa_write_signature() gained an additional md_alg argument and + ecdsa_write_signature_det() was deprecated. + * pk_sign() no longer accepts md_alg == POLARSSL_MD_NONE with ECDSA. + * Last argument of x509_crt_check_key_usage() and + mbedtls_x509write_crt_set_key_usage() changed from int to unsigned. + * test_ca_list (from certs.h) is renamed to test_cas_pem and is only + available if POLARSSL_PEM_PARSE_C is defined (it never worked without). + * Test certificates in certs.c are no longer guaranteed to be nul-terminated + strings; use the new *_len variables instead of strlen(). + * Functions mbedtls_x509_xxx_parse(), mbedtls_pk_parse_key(), + mbedtls_pk_parse_public_key() and mbedtls_dhm_parse_dhm() now expect the + length parameter to include the terminating null byte for PEM input. + * Signature of mpi_mul_mpi() changed to make the last argument unsigned + * calloc() is now used instead of malloc() everywhere. API of platform + layer and the memory_buffer_alloc module changed accordingly. + (Thanks to Mansour Moufid for helping with the replacement.) + * Change SSL_DISABLE_RENEGOTIATION config.h flag to SSL_RENEGOTIATION + (support for renegotiation now needs explicit enabling in config.h). + * Split MBEDTLS_HAVE_TIME into MBEDTLS_HAVE_TIME and MBEDTLS_HAVE_TIME_DATE + in config.h + * net_connect() and net_bind() have a new 'proto' argument to choose + between TCP and UDP, using the macros NET_PROTO_TCP or NET_PROTO_UDP. + Their 'port' argument type is changed to a string. + * Some constness fixes + +Removals + * Removed mbedtls_ecp_group_read_string(). Only named groups are supported. + * Removed mbedtls_ecp_sub() and mbedtls_ecp_add(), use + mbedtls_ecp_muladd(). + * Removed individual mdX_hmac, shaX_hmac, mdX_file and shaX_file functions + (use generic functions from md.h) + * Removed mbedtls_timing_msleep(). Use mbedtls_net_usleep() or a custom + waiting function. + * Removed test DHM parameters from the test certs module. + * Removed the PBKDF2 module (use PKCS5). + * Removed POLARSSL_ERROR_STRERROR_BC (use mbedtls_strerror()). + * Removed compat-1.2.h (helper for migrating from 1.2 to 1.3). + * Removed openssl.h (very partial OpenSSL compatibility layer). + * Configuration options POLARSSL_HAVE_LONGLONG was removed (now always on). + * Configuration options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 have + been removed (compiler is required to support 32-bit operations). + * Configuration option POLARSSL_HAVE_IPV6 was removed (always enabled). + * Removed test program o_p_test, the script compat.sh does more. + * Removed test program ssl_test, superseded by ssl-opt.sh. + * Removed helper script active-config.pl + +New deprecations + * md_init_ctx() is deprecated in favour of md_setup(), that adds a third + argument (allowing memory savings if HMAC is not used) + +Semi-API changes (technically public, morally private) + * Renamed a few headers to include _internal in the name. Those headers are + not supposed to be included by users. + * Changed md_info_t into an opaque structure (use md_get_xxx() accessors). + * Changed pk_info_t into an opaque structure. + * Changed cipher_base_t into an opaque structure. + * Removed sig_oid2 and rename sig_oid1 to sig_oid in x509_crt and x509_crl. + * x509_crt.key_usage changed from unsigned char to unsigned int. + * Removed r and s from ecdsa_context + * Removed mode from des_context and des3_context + +Default behavior changes + * The default minimum TLS version is now TLS 1.0. + * RC4 is now blacklisted by default in the SSL/TLS layer, and excluded from the + default ciphersuite list returned by ssl_list_ciphersuites() + * Support for receiving SSLv2 ClientHello is now disabled by default at + compile time. + * The default authmode for SSL/TLS clients is now REQUIRED. + * Support for RSA_ALT contexts in the PK layer is now optional. Since is is + enabled in the default configuration, this is only noticeable if using a + custom config.h + * Default DHM parameters server-side upgraded from 1024 to 2048 bits. + * A minimum RSA key size of 2048 bits is now enforced during ceritificate + chain verification. + * Negotiation of truncated HMAC is now disabled by default on server too. + * The following functions are now case-sensitive: + mbedtls_cipher_info_from_string() + mbedtls_ecp_curve_info_from_name() + mbedtls_md_info_from_string() + mbedtls_ssl_ciphersuite_from_string() + mbedtls_version_check_feature() + +Requirement changes + * The minimum MSVC version required is now 2010 (better C99 support). + * The NET layer now unconditionnaly relies on getaddrinfo() and select(). + * Compiler is required to support C99 types such as long long and uint32_t. + +API changes from the 1.4 preview branch + * ssl_set_bio_timeout() was removed, split into mbedtls_ssl_set_bio() with + new prototype, and mbedtls_ssl_set_read_timeout(). + * The following functions now return void: + mbedtls_ssl_conf_transport() + mbedtls_ssl_conf_max_version() + mbedtls_ssl_conf_min_version() + * DTLS no longer hard-depends on TIMING_C, but uses a callback interface + instead, see mbedtls_ssl_set_timer_cb(), with the Timing module providing + an example implementation, see mbedtls_timing_delay_context and + mbedtls_timing_set/get_delay(). + * With UDP sockets, it is no longer necessary to call net_bind() again + after a successful net_accept(). + +Changes + * mbedtls_ctr_drbg_random() and mbedtls_hmac_drbg_random() are now + thread-safe if MBEDTLS_THREADING_C is enabled. + * Reduced ROM fooprint of SHA-256 and added an option to reduce it even + more (at the expense of performance) MBEDTLS_SHA256_SMALLER. + += mbed TLS 1.3 branch + +Security + * With authmode set to SSL_VERIFY_OPTIONAL, verification of keyUsage and + extendedKeyUsage on the leaf certificate was lost (results not accessible + via ssl_get_verify_results()). + * Add countermeasure against "Lucky 13 strikes back" cache-based attack, + https://dl.acm.org/citation.cfm?id=2714625 + +Features + * Improve ECC performance by using more efficient doubling formulas + (contributed by Peter Dettman). + * Add x509_crt_verify_info() to display certificate verification results. + * Add support for reading DH parameters with privateValueLength included + (contributed by Daniel Kahn Gillmor). + * Add support for bit strings in X.509 names (request by Fredrik Axelsson). + * Add support for id-at-uniqueIdentifier in X.509 names. + * Add support for overriding snprintf() (except on Windows) and exit() in + the platform layer. + * Add an option to use macros instead of function pointers in the platform + layer (helps get rid of unwanted references). + * Improved Makefiles for Windows targets by fixing library targets and making + cross-compilation easier (thanks to Alon Bar-Lev). + * The benchmark program also prints heap usage for public-key primitives + if POLARSSL_MEMORY_BUFFER_ALLOC_C and POLARSSL_MEMORY_DEBUG are defined. + * New script ecc-heap.sh helps measuring the impact of ECC parameters on + speed and RAM (heap only for now) usage. + * New script memory.sh helps measuring the ROM and RAM requirements of two + reduced configurations (PSK-CCM and NSA suite B). + * Add config flag POLARSSL_DEPRECATED_WARNING (off by default) to produce + warnings on use of deprecated functions (with GCC and Clang only). + * Add config flag POLARSSL_DEPRECATED_REMOVED (off by default) to produce + errors on use of deprecated functions. + +Bugfix + * Fix compile errors with PLATFORM_NO_STD_FUNCTIONS. + * Fix compile error with PLATFORM_EXIT_ALT (thanks to RafaÅ‚ Przywara). + * Fix bug in entropy.c when THREADING_C is also enabled that caused + entropy_free() to crash (thanks to RafaÅ‚ Przywara). + * Fix memory leak when gcm_setkey() and ccm_setkey() are used more than + once on the same context. + * Fix bug in ssl_mail_client when password is longer that username (found + by Bruno Pape). + * Fix undefined behaviour (memcmp( NULL, NULL, 0 );) in X.509 modules + (detected by Clang's 3.6 UBSan). + * mpi_size() and mpi_msb() would segfault when called on an mpi that is + initialized but not set (found by pravic). + * Fix detection of support for getrandom() on Linux (reported by syzzer) by + doing it at runtime (using uname) rather that compile time. + * Fix handling of symlinks by "make install" (found by Gaël PORTAY). + * Fix potential NULL pointer dereference (not trigerrable remotely) when + ssl_write() is called before the handshake is finished (introduced in + 1.3.10) (first reported by Martin Blumenstingl). + * Fix bug in pk_parse_key() that caused some valid private EC keys to be + rejected. + * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). + * Fix thread safety bug in RSA operations (found by Fredrik Axelsson). + * Fix hardclock() (only used in the benchmarking program) with some + versions of mingw64 (found by kxjhlele). + * Fix warnings from mingw64 in timing.c (found by kxjklele). + * Fix potential unintended sign extension in asn1_get_len() on 64-bit + platforms. + * Fix potential memory leak in ssl_set_psk() (found by Mansour Moufid). + * Fix compile error when POLARSSL_SSL_DISABLE_RENEGOTATION and + POLARSSL_SSL_SSESSION_TICKETS where both enabled in config.h (introduced + in 1.3.10). + * Add missing extern "C" guard in aesni.h (reported by amir zamani). + * Add missing dependency on SHA-256 in some x509 programs (reported by + Gergely Budai). + * Fix bug related to ssl_set_curves(): the client didn't check that the + curve picked by the server was actually allowed. + +Changes + * Remove bias in mpi_gen_prime (contributed by Pascal Junod). + * Remove potential sources of timing variations (some contributed by Pascal + Junod). + * Options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 are deprecated. + * Enabling POLARSSL_NET_C without POLARSSL_HAVE_IPV6 is deprecated. + * compat-1.2.h and openssl.h are deprecated. + * Adjusting/overriding CFLAGS and LDFLAGS with the make build system is now + more flexible (warning: OFLAGS is not used any more) (see the README) + (contributed by Alon Bar-Lev). + * ssl_set_own_cert() no longer calls pk_check_pair() since the + performance impact was bad for some users (this was introduced in 1.3.10). + * Move from SHA-1 to SHA-256 in example programs using signatures + (suggested by Thorsten Mühlfelder). + * Remove some unneeded inclusions of header files from the standard library + "minimize" others (eg use stddef.h if only size_t is needed). + * Change #include lines in test files to use double quotes instead of angle + brackets for uniformity with the rest of the code. + * Remove dependency on sscanf() in X.509 parsing modules. + += mbed TLS 1.3.10 released 2015-02-09 +Security + * NULL pointer dereference in the buffer-based allocator when the buffer is + full and polarssl_free() is called (found by Mark Hasemeyer) + (only possible if POLARSSL_MEMORY_BUFFER_ALLOC_C is enabled, which it is + not by default). + * Fix remotely-triggerable uninitialised pointer dereference caused by + crafted X.509 certificate (TLS server is not affected if it doesn't ask for a + client certificate) (found using Codenomicon Defensics). + * Fix remotely-triggerable memory leak caused by crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate) + (found using Codenomicon Defensics). + * Fix potential stack overflow while parsing crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate) + (found using Codenomicon Defensics). + * Fix timing difference that could theoretically lead to a + Bleichenbacher-style attack in the RSA and RSA-PSK key exchanges + (reported by Sebastian Schinzel). + +Features + * Add support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv). + * Add support for Extended Master Secret (draft-ietf-tls-session-hash). + * Add support for Encrypt-then-MAC (RFC 7366). + * Add function pk_check_pair() to test if public and private keys match. + * Add x509_crl_parse_der(). + * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the + length of an X.509 verification chain. + * Support for renegotiation can now be disabled at compile-time + * Support for 1/n-1 record splitting, a countermeasure against BEAST. + * Certificate selection based on signature hash, preferring SHA-1 over SHA-2 + for pre-1.2 clients when multiple certificates are available. + * Add support for getrandom() syscall on recent Linux kernels with Glibc or + a compatible enough libc (eg uClibc). + * Add ssl_set_arc4_support() to make it easier to disable RC4 at runtime + while using the default ciphersuite list. + * Added new error codes and debug messages about selection of + ciphersuite/certificate. + +Bugfix + * Stack buffer overflow if ctr_drbg_update() is called with too large + add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). + * Possible buffer overflow of length at most POLARSSL_MEMORY_ALIGN_MULTIPLE + if memory_buffer_alloc_init() was called with buf not aligned and len not + a multiple of POLARSSL_MEMORY_ALIGN_MULTIPLE (not triggerable remotely). + * User set CFLAGS were ignored by Cmake with gcc (introduced in 1.3.9, found + by Julian Ospald). + * Fix potential undefined behaviour in Camellia. + * Fix potential failure in ECDSA signatures when POLARSSL_ECP_MAX_BITS is a + multiple of 8 (found by Gergely Budai). + * Fix unchecked return code in x509_crt_parse_path() on Windows (found by + Peter Vaskovic). + * Fix assembly selection for MIPS64 (thanks to James Cowgill). + * ssl_get_verify_result() now works even if the handshake was aborted due + to a failed verification (found by Fredrik Axelsson). + * Skip writing and parsing signature_algorithm extension if none of the + key exchanges enabled needs certificates. This fixes a possible interop + issue with some servers when a zero-length extension was sent. (Reported + by Peter Dettman.) + * On a 0-length input, base64_encode() did not correctly set output length + (found by Hendrik van den Boogaard). + +Changes + * Use deterministic nonces for AEAD ciphers in TLS by default (possible to + switch back to random with POLARSSL_SSL_AEAD_RANDOM_IV in config.h). + * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. + * ssl_set_own_cert() now returns an error on key-certificate mismatch. + * Forbid repeated extensions in X.509 certificates. + * debug_print_buf() now prints a text view in addition to hexadecimal. + * A specific error is now returned when there are ciphersuites in common + but none of them is usable due to external factors such as no certificate + with a suitable (extended)KeyUsage or curve or no PSK set. + * It is now possible to disable negotiation of truncated HMAC server-side + at runtime with ssl_set_truncated_hmac(). + * Example programs for SSL client and server now disable SSLv3 by default. + * Example programs for SSL client and server now disable RC4 by default. + * Use platform.h in all test suites and programs. + += PolarSSL 1.3.9 released 2014-10-20 +Security + * Lowest common hash was selected from signature_algorithms extension in + TLS 1.2 (found by Darren Bane) (introduced in 1.3.8). + * Remotely-triggerable memory leak when parsing some X.509 certificates + (server is not affected if it doesn't ask for a client certificate) + (found using Codenomicon Defensics). + * Remotely-triggerable memory leak when parsing crafted ClientHello + (not affected if ECC support was compiled out) (found using Codenomicon + Defensics). + +Bugfix + * Support escaping of commas in x509_string_to_names() + * Fix compile error in ssl_pthread_server (found by Julian Ospald). + * Fix net_accept() regarding non-blocking sockets (found by Luca Pesce). + * Don't print uninitialised buffer in ssl_mail_client (found by Marc Abel). + * Fix warnings from Clang's scan-build (contributed by Alfred Klomp). + * Fix compile error in timing.c when POLARSSL_NET_C and POLARSSL_SELFTEST + are defined but not POLARSSL_HAVE_TIME (found by Stephane Di Vito). + * Remove non-existent file from VS projects (found by Peter Vaskovic). + * ssl_read() could return non-application data records on server while + renegotation was pending, and on client when a HelloRequest was received. + * Server-initiated renegotiation would fail with non-blocking I/O if the + write callback returned WANT_WRITE when requesting renegotiation. + * ssl_close_notify() could send more than one message in some circumstances + with non-blocking I/O. + * Fix compiler warnings on iOS (found by Sander Niemeijer). + * x509_crt_parse() did not increase total_failed on PEM error + * Fix compile error with armcc in mpi_is_prime() + * Fix potential bad read in parsing ServerHello (found by Adrien + Vialletelle). + +Changes + * Ciphersuites using SHA-256 or SHA-384 now require TLS 1.x (there is no + standard defining how to use SHA-2 with SSL 3.0). + * Ciphersuites using RSA-PSK key exchange new require TLS 1.x (the spec is + ambiguous on how to encode some packets with SSL 3.0). + * Made buffer size in pk_write_(pub)key_pem() more dynamic, eg smaller if + RSA is disabled, larger if POLARSSL_MPI_MAX_SIZE is larger. + * ssl_read() now returns POLARSSL_ERR_NET_WANT_READ rather than + POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts. + * POLARSSL_MPI_MAX_SIZE now defaults to 1024 in order to allow 8192 bits + RSA keys. + * Accept spaces at end of line or end of buffer in base64_decode(). + * X.509 certificates with more than one AttributeTypeAndValue per + RelativeDistinguishedName are not accepted any more. + += PolarSSL 1.3.8 released 2014-07-11 +Security + * Fix length checking for AEAD ciphersuites (found by Codenomicon). + It was possible to crash the server (and client) using crafted messages + when a GCM suite was chosen. + +Features + * Add CCM module and cipher mode to Cipher Layer + * Support for CCM and CCM_8 ciphersuites + * Support for parsing and verifying RSASSA-PSS signatures in the X.509 + modules (certificates, CRLs and CSRs). + * Blowfish in the cipher layer now supports variable length keys. + * Add example config.h for PSK with CCM, optimized for low RAM usage. + * Optimize for RAM usage in example config.h for NSA Suite B profile. + * Add POLARSSL_REMOVE_ARC4_CIPHERSUITES to allow removing RC4 ciphersuites + from the default list (inactive by default). + * Add server-side enforcement of sent renegotiation requests + (ssl_set_renegotiation_enforced()) + * Add SSL_CIPHERSUITES config.h flag to allow specifying a list of + ciphersuites to use and save some memory if the list is small. + +Changes + * Add LINK_WITH_PTHREAD option in CMake for explicit linking that is + required on some platforms (e.g. OpenBSD) + * Migrate zeroizing of data to polarssl_zeroize() instead of memset() + against unwanted compiler optimizations + * md_list() now returns hashes strongest first + * Selection of hash for signing ServerKeyExchange in TLS 1.2 now picks + strongest offered by client. + * All public contexts have _init() and _free() functions now for simpler + usage pattern + +Bugfix + * Fix in debug_print_msg() + * Enforce alignment in the buffer allocator even if buffer is not aligned + * Remove less-than-zero checks on unsigned numbers + * Stricter check on SSL ClientHello internal sizes compared to actual packet + size (found by TrustInSoft) + * Fix WSAStartup() return value check (found by Peter Vaskovic) + * Other minor issues (found by Peter Vaskovic) + * Fix symlink command for cross compiling with CMake (found by Andre + Heinecke) + * Fix DER output of gen_key app (found by Gergely Budai) + * Very small records were incorrectly rejected when truncated HMAC was in + use with some ciphersuites and versions (RC4 in all versions, CBC with + versions < TLS 1.1). + * Very large records using more than 224 bytes of padding were incorrectly + rejected with CBC-based ciphersuites and TLS >= 1.1 + * Very large records using less padding could cause a buffer overread of up + to 32 bytes with CBC-based ciphersuites and TLS >= 1.1 + * Restore ability to use a v1 cert as a CA if trusted locally. (This had + been removed in 1.3.6.) + * Restore ability to locally trust a self-signed cert that is not a proper + CA for use as an end entity certificate. (This had been removed in + 1.3.6.) + * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan). + * Use \n\t rather than semicolons for bn_mul asm, since some assemblers + interpret semicolons as comment delimiters (found by Barry K. Nathan). + * Fix off-by-one error in parsing Supported Point Format extension that + caused some handshakes to fail. + * Fix possible miscomputation of the premaster secret with DHE-PSK key + exchange that caused some handshakes to fail with other implementations. + (Failure rate <= 1/255 with common DHM moduli.) + * Disable broken Sparc64 bn_mul assembly (found by Florian Obser). + * Fix base64_decode() to return and check length correctly (in case of + tight buffers) + * Fix mpi_write_string() to write "00" as hex output for empty MPI (found + by Hui Dong) + += PolarSSL 1.3.7 released on 2014-05-02 +Features + * debug_set_log_mode() added to determine raw or full logging + * debug_set_threshold() added to ignore messages over threshold level + * version_check_feature() added to check for compile-time options at + run-time + +Changes + * POLARSSL_CONFIG_OPTIONS has been removed. All values are individually + checked and filled in the relevant module headers + * Debug module only outputs full lines instead of parts + * Better support for the different Attribute Types from IETF PKIX (RFC 5280) + * AES-NI now compiles with "old" assemblers too + * Ciphersuites based on RC4 now have the lowest priority by default + +Bugfix + * Only iterate over actual certificates in ssl_write_certificate_request() + (found by Matthew Page) + * Typos in platform.c and pkcs11.c (found by Daniel Phillips and Steffan + Karger) + * cert_write app should use subject of issuer certificate as issuer of cert + * Fix false reject in padding check in ssl_decrypt_buf() for CBC + ciphersuites, for full SSL frames of data. + * Improve interoperability by not writing extension length in ClientHello / + ServerHello when no extensions are present (found by Matthew Page) + * rsa_check_pubkey() now allows an E up to N + * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings + * mpi_fill_random() was creating numbers larger than requested on + big-endian platform when size was not an integer number of limbs + * Fix dependencies issues in X.509 test suite. + * Some parts of ssl_tls.c were compiled even when the module was disabled. + * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer) + * Fix detection of Clang on some Apple platforms with CMake + (found by Barry K. Nathan) + += PolarSSL 1.3.6 released on 2014-04-11 + +Features + * Support for the ALPN SSL extension + * Add option 'use_dev_random' to gen_key application + * Enable verification of the keyUsage extension for CA and leaf + certificates (POLARSSL_X509_CHECK_KEY_USAGE) + * Enable verification of the extendedKeyUsage extension + (POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) + +Changes + * x509_crt_info() now prints information about parsed extensions as well + * pk_verify() now returns a specific error code when the signature is valid + but shorter than the supplied length. + * Use UTC time to check certificate validity. + * Reject certificates with times not in UTC, per RFC 5280. + +Security + * Avoid potential timing leak in ecdsa_sign() by blinding modular division. + (Found by Watson Ladd.) + * The notAfter date of some certificates was no longer checked since 1.3.5. + This affects certificates in the user-supplied chain except the top + certificate. If the user-supplied chain contains only one certificates, + it is not affected (ie, its notAfter date is properly checked). + * Prevent potential NULL pointer dereference in ssl_read_record() (found by + TrustInSoft) + +Bugfix + * The length of various ClientKeyExchange messages was not properly checked. + * Some example server programs were not sending the close_notify alert. + * Potential memory leak in mpi_exp_mod() when error occurs during + calculation of RR. + * Fixed malloc/free default #define in platform.c (found by Gergely Budai). + * Fixed type which made POLARSSL_ENTROPY_FORCE_SHA256 uneffective (found by + Gergely Budai). + * Fix #include path in ecdsa.h which wasn't accepted by some compilers. + (found by Gergely Budai) + * Fix compile errors when POLARSSL_ERROR_STRERROR_BC is undefined (found by + Shuo Chen). + * oid_get_numeric_string() used to truncate the output without returning an + error if the output buffer was just 1 byte too small. + * dhm_parse_dhm() (hence dhm_parse_dhmfile()) did not set dhm->len. + * Calling pk_debug() on an RSA-alt key would segfault. + * pk_get_size() and pk_get_len() were off by a factor 8 for RSA-alt keys. + * Potential buffer overwrite in pem_write_buffer() because of low length + indication (found by Thijs Alkemade) + * EC curves constants, which should be only in ROM since 1.3.3, were also + stored in RAM due to missing 'const's (found by Gergely Budai). + += PolarSSL 1.3.5 released on 2014-03-26 +Features + * HMAC-DRBG as a separate module + * Option to set the Curve preference order (disabled by default) + * Single Platform compatilibity layer (for memory / printf / fprintf) + * Ability to provide alternate timing implementation + * Ability to force the entropy module to use SHA-256 as its basis + (POLARSSL_ENTROPY_FORCE_SHA256) + * Testing script ssl-opt.sh added for testing 'live' ssl option + interoperability against OpenSSL and PolarSSL + * Support for reading EC keys that use SpecifiedECDomain in some cases. + * Entropy module now supports seed writing and reading + +Changes + * Deprecated the Memory layer + * entropy_add_source(), entropy_update_manual() and entropy_gather() + now thread-safe if POLARSSL_THREADING_C defined + * Improvements to the CMake build system, contributed by Julian Ospald. + * Work around a bug of the version of Clang shipped by Apple with Mavericks + that prevented bignum.c from compiling. (Reported by Rafael Baptista.) + * Revamped the compat.sh interoperatibility script to include support for + testing against GnuTLS + * Deprecated ssl_set_own_cert_rsa() and ssl_set_own_cert_rsa_alt() + * Improvements to tests/Makefile, contributed by Oden Eriksson. + +Security + * Forbid change of server certificate during renegotiation to prevent + "triple handshake" attack when authentication mode is 'optional' (the + attack was already impossible when authentication is required). + * Check notBefore timestamp of certificates and CRLs from the future. + * Forbid sequence number wrapping + * Fixed possible buffer overflow with overlong PSK + * Possible remotely-triggered out-of-bounds memory access fixed (found by + TrustInSoft) + +Bugfix + * ecp_gen_keypair() does more tries to prevent failure because of + statistics + * Fixed bug in RSA PKCS#1 v1.5 "reversed" operations + * Fixed testing with out-of-source builds using cmake + * Fixed version-major intolerance in server + * Fixed CMake symlinking on out-of-source builds + * Fixed dependency issues in test suite + * Programs rsa_sign_pss and rsa_verify_pss were not using PSS since 1.3.0 + * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by + Alex Wilson.) + * ssl_cache was creating entries when max_entries=0 if TIMING_C was enabled. + * m_sleep() was sleeping twice too long on most Unix platforms. + * Fixed bug with session tickets and non-blocking I/O in the unlikely case + send() would return an EAGAIN error when sending the ticket. + * ssl_cache was leaking memory when reusing a timed out entry containing a + client certificate. + * ssl_srv was leaking memory when client presented a timed out ticket + containing a client certificate + * ssl_init() was leaving a dirty pointer in ssl_context if malloc of + out_ctr failed + * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc + of one of them failed + * Fix typo in rsa_copy() that impacted PKCS#1 v2 contexts + * x509_get_current_time() uses localtime_r() to prevent thread issues + += PolarSSL 1.3.4 released on 2014-01-27 +Features + * Support for the Koblitz curves: secp192k1, secp224k1, secp256k1 + * Support for RIPEMD-160 + * Support for AES CFB8 mode + * Support for deterministic ECDSA (RFC 6979) + +Bugfix + * Potential memory leak in bignum_selftest() + * Replaced expired test certificate + * ssl_mail_client now terminates lines with CRLF, instead of LF + * net module handles timeouts on blocking sockets better (found by Tilman + Sauerbeck) + * Assembly format fixes in bn_mul.h + +Security + * Missing MPI_CHK calls added around unguarded mpi calls (found by + TrustInSoft) + += PolarSSL 1.3.3 released on 2013-12-31 +Features + * EC key generation support in gen_key app + * Support for adhering to client ciphersuite order preference + (POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + * Support for Curve25519 + * Support for ECDH-RSA and ECDH-ECDSA key exchanges and ciphersuites + * Support for IPv6 in the NET module + * AES-NI support for AES, AES-GCM and AES key scheduling + * SSL Pthread-based server example added (ssl_pthread_server) + +Changes + * gen_prime() speedup + * Speedup of ECP multiplication operation + * Relaxed some SHA2 ciphersuite's version requirements + * Dropped use of readdir_r() instead of readdir() with threading support + * More constant-time checks in the RSA module + * Split off curves from ecp.c into ecp_curves.c + * Curves are now stored fully in ROM + * Memory usage optimizations in ECP module + * Removed POLARSSL_THREADING_DUMMY + +Bugfix + * Fixed bug in mpi_set_bit() on platforms where t_uint is wider than int + * Fixed X.509 hostname comparison (with non-regular characters) + * SSL now gracefully handles missing RNG + * Missing defines / cases for RSA_PSK key exchange + * crypt_and_hash app checks MAC before final decryption + * Potential memory leak in ssl_ticket_keys_init() + * Memory leak in benchmark application + * Fixed x509_crt_parse_path() bug on Windows platforms + * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by + TrustInSoft) + * Fixed potential overflow in certificate size verification in + ssl_write_certificate() (found by TrustInSoft) + +Security + * Possible remotely-triggered out-of-bounds memory access fixed (found by + TrustInSoft) + += PolarSSL 1.3.2 released on 2013-11-04 +Features + * PK tests added to test framework + * Added optional optimization for NIST MODP curves (POLARSSL_ECP_NIST_OPTIM) + * Support for Camellia-GCM mode and ciphersuites + +Changes + * Padding checks in cipher layer are now constant-time + * Value comparisons in SSL layer are now constant-time + * Support for serialNumber, postalAddress and postalCode in X509 names + * SSL Renegotiation was refactored + +Bugfix + * More stringent checks in cipher layer + * Server does not send out extensions not advertised by client + * Prevent possible alignment warnings on casting from char * to 'aligned *' + * Misc fixes and additions to dependency checks + * Const correctness + * cert_write with selfsign should use issuer_name as subject_name + * Fix ECDSA corner case: missing reduction mod N (found by DualTachyon) + * Defines to handle UEFI environment under MSVC + * Server-side initiated renegotiations send HelloRequest + += PolarSSL 1.3.1 released on 2013-10-15 +Features + * Support for Brainpool curves and TLS ciphersuites (RFC 7027) + * Support for ECDHE-PSK key-exchange and ciphersuites + * Support for RSA-PSK key-exchange and ciphersuites + +Changes + * RSA blinding locks for a smaller amount of time + * TLS compression only allocates working buffer once + * Introduced POLARSSL_HAVE_READDIR_R for systems without it + * config.h is more script-friendly + +Bugfix + * Missing MSVC defines added + * Compile errors with POLARSSL_RSA_NO_CRT + * Header files with 'polarssl/' + * Const correctness + * Possible naming collision in dhm_context + * Better support for MSVC + * threading_set_alt() name + * Added missing x509write_crt_set_version() + += PolarSSL 1.3.0 released on 2013-10-01 +Features + * Elliptic Curve Cryptography module added + * Elliptic Curve Diffie Hellman module added + * Ephemeral Elliptic Curve Diffie Hellman support for SSL/TLS + (ECDHE-based ciphersuites) + * Ephemeral Elliptic Curve Digital Signature Algorithm support for SSL/TLS + (ECDSA-based ciphersuites) + * Ability to specify allowed ciphersuites based on the protocol version. + * PSK and DHE-PSK based ciphersuites added + * Memory allocation abstraction layer added + * Buffer-based memory allocator added (no malloc() / free() / HEAP usage) + * Threading abstraction layer added (dummy / pthread / alternate) + * Public Key abstraction layer added + * Parsing Elliptic Curve keys + * Parsing Elliptic Curve certificates + * Support for max_fragment_length extension (RFC 6066) + * Support for truncated_hmac extension (RFC 6066) + * Support for zeros-and-length (ANSI X.923) padding, one-and-zeros + (ISO/IEC 7816-4) padding and zero padding in the cipher layer + * Support for session tickets (RFC 5077) + * Certificate Request (CSR) generation with extensions (key_usage, + ns_cert_type) + * X509 Certificate writing with extensions (basic_constraints, + issuer_key_identifier, etc) + * Optional blinding for RSA, DHM and EC + * Support for multiple active certificate / key pairs in SSL servers for + the same host (Not to be confused with SNI!) + +Changes + * Ability to enable / disable SSL v3 / TLS 1.0 / TLS 1.1 / TLS 1.2 + individually + * Introduced separate SSL Ciphersuites module that is based on + Cipher and MD information + * Internals for SSL module adapted to have separate IV pointer that is + dynamically set (Better support for hardware acceleration) + * Moved all OID functionality to a separate module. RSA function + prototypes for the RSA sign and verify functions changed as a result + * Split up the GCM module into a starts/update/finish cycle + * Client and server now filter sent and accepted ciphersuites on minimum + and maximum protocol version + * Ability to disable server_name extension (RFC 6066) + * Renamed error_strerror() to the less conflicting polarssl_strerror() + (Ability to keep old as well with POLARSSL_ERROR_STRERROR_BC) + * SHA2 renamed to SHA256, SHA4 renamed to SHA512 and functions accordingly + * All RSA operations require a random generator for blinding purposes + * X509 core refactored + * x509_crt_verify() now case insensitive for cn (RFC 6125 6.4) + * Also compiles / runs without time-based functions (!POLARSSL_HAVE_TIME) + * Support faulty X509 v1 certificates with extensions + (POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) + +Bugfix + * Fixed parse error in ssl_parse_certificate_request() + * zlib compression/decompression skipped on empty blocks + * Support for AIX header locations in net.c module + * Fixed file descriptor leaks + +Security + * RSA blinding on CRT operations to counter timing attacks + (found by Cyril Arnaud and Pierre-Alain Fouque) + + += Version 1.2.14 released 2015-05-?? + +Security + * Fix potential invalid memory read in the server, that allows a client to + crash it remotely (found by Caj Larsson). + * Fix potential invalid memory read in certificate parsing, that allows a + client to crash the server remotely if client authentication is enabled + (found using Codenomicon Defensics). + * Add countermeasure against "Lucky 13 strikes back" cache-based attack, + https://dl.acm.org/citation.cfm?id=2714625 + +Bugfix + * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). + * Fix hardclock() (only used in the benchmarking program) with some + versions of mingw64 (found by kxjhlele). + * Fix warnings from mingw64 in timing.c (found by kxjklele). + * Fix potential unintended sign extension in asn1_get_len() on 64-bit + platforms (found with Coverity Scan). + += Version 1.2.13 released 2015-02-16 +Note: Although PolarSSL has been renamed to mbed TLS, no changes reflecting + this will be made in the 1.2 branch at this point. + +Security + * Fix remotely-triggerable uninitialised pointer dereference caused by + crafted X.509 certificate (TLS server is not affected if it doesn't ask + for a client certificate) (found using Codenomicon Defensics). + * Fix remotely-triggerable memory leak caused by crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate) + (found using Codenomicon Defensics). + * Fix potential stack overflow while parsing crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate) + found using Codenomicon Defensics). + * Fix buffer overread of size 1 when parsing crafted X.509 certificates + (TLS server is not affected if it doesn't ask for a client certificate). + +Bugfix + * Fix potential undefined behaviour in Camellia. + * Fix memory leaks in PKCS#5 and PKCS#12. + * Stack buffer overflow if ctr_drbg_update() is called with too large + add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). + * Fix bug in MPI/bignum on s390/s390x (reported by Dan Horák) (introduced + in 1.2.12). + * Fix unchecked return code in x509_crt_parse_path() on Windows (found by + Peter Vaskovic). + * Fix assembly selection for MIPS64 (thanks to James Cowgill). + * ssl_get_verify_result() now works even if the handshake was aborted due + to a failed verification (found by Fredrik Axelsson). + * Skip writing and parsing signature_algorithm extension if none of the + key exchanges enabled needs certificates. This fixes a possible interop + issue with some servers when a zero-length extension was sent. (Reported + by Peter Dettman.) + * On a 0-length input, base64_encode() did not correctly set output length + (found by Hendrik van den Boogaard). + +Changes + * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. + * Forbid repeated extensions in X.509 certificates. + * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the + length of an X.509 verification chain (default = 8). += Version 1.2.12 released 2014-10-24 + +Security + * Remotely-triggerable memory leak when parsing some X.509 certificates + (server is not affected if it doesn't ask for a client certificate). + (Found using Codenomicon Defensics.) + +Bugfix + * Fix potential bad read in parsing ServerHello (found by Adrien + Vialletelle). + * ssl_close_notify() could send more than one message in some circumstances + with non-blocking I/O. + * x509_crt_parse() did not increase total_failed on PEM error + * Fix compiler warnings on iOS (found by Sander Niemeijer). + * Don't print uninitialised buffer in ssl_mail_client (found by Marc Abel). + * Fix net_accept() regarding non-blocking sockets (found by Luca Pesce). + * ssl_read() could return non-application data records on server while + renegotation was pending, and on client when a HelloRequest was received. + * Fix warnings from Clang's scan-build (contributed by Alfred Klomp). + +Changes + * X.509 certificates with more than one AttributeTypeAndValue per + RelativeDistinguishedName are not accepted any more. + * ssl_read() now returns POLARSSL_ERR_NET_WANT_READ rather than + POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts. + * Accept spaces at end of line or end of buffer in base64_decode(). + += Version 1.2.11 released 2014-07-11 +Features + * Entropy module now supports seed writing and reading + +Changes + * Introduced POLARSSL_HAVE_READDIR_R for systems without it + * Improvements to the CMake build system, contributed by Julian Ospald. + * Work around a bug of the version of Clang shipped by Apple with Mavericks + that prevented bignum.c from compiling. (Reported by Rafael Baptista.) + * Improvements to tests/Makefile, contributed by Oden Eriksson. + * Use UTC time to check certificate validity. + * Reject certificates with times not in UTC, per RFC 5280. + * Migrate zeroizing of data to polarssl_zeroize() instead of memset() + against unwanted compiler optimizations + +Security + * Forbid change of server certificate during renegotiation to prevent + "triple handshake" attack when authentication mode is optional (the + attack was already impossible when authentication is required). + * Check notBefore timestamp of certificates and CRLs from the future. + * Forbid sequence number wrapping + * Prevent potential NULL pointer dereference in ssl_read_record() (found by + TrustInSoft) + * Fix length checking for AEAD ciphersuites (found by Codenomicon). + It was possible to crash the server (and client) using crafted messages + when a GCM suite was chosen. + +Bugfix + * Fixed X.509 hostname comparison (with non-regular characters) + * SSL now gracefully handles missing RNG + * crypt_and_hash app checks MAC before final decryption + * Fixed x509_crt_parse_path() bug on Windows platforms + * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by + TrustInSoft) + * Fixed potential overflow in certificate size verification in + ssl_write_certificate() (found by TrustInSoft) + * Fix ASM format in bn_mul.h + * Potential memory leak in bignum_selftest() + * Replaced expired test certificate + * ssl_mail_client now terminates lines with CRLF, instead of LF + * Fix bug in RSA PKCS#1 v1.5 "reversed" operations + * Fixed testing with out-of-source builds using cmake + * Fixed version-major intolerance in server + * Fixed CMake symlinking on out-of-source builds + * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by + Alex Wilson.) + * ssl_init() was leaving a dirty pointer in ssl_context if malloc of + out_ctr failed + * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc + of one of them failed + * x509_get_current_time() uses localtime_r() to prevent thread issues + * Some example server programs were not sending the close_notify alert. + * Potential memory leak in mpi_exp_mod() when error occurs during + calculation of RR. + * Improve interoperability by not writing extension length in ClientHello + when no extensions are present (found by Matthew Page) + * rsa_check_pubkey() now allows an E up to N + * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings + * mpi_fill_random() was creating numbers larger than requested on + big-endian platform when size was not an integer number of limbs + * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer) + * Stricter check on SSL ClientHello internal sizes compared to actual packet + size (found by TrustInSoft) + * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan). + * Use \n\t rather than semicolons for bn_mul asm, since some assemblers + interpret semicolons as comment delimiters (found by Barry K. Nathan). + * Disable broken Sparc64 bn_mul assembly (found by Florian Obser). + * Fix base64_decode() to return and check length correctly (in case of + tight buffers) + += Version 1.2.10 released 2013-10-07 +Changes + * Changed RSA blinding to a slower but thread-safe version + +Bugfix + * Fixed memory leak in RSA as a result of introduction of blinding + * Fixed ssl_pkcs11_decrypt() prototype + * Fixed MSVC project files + += Version 1.2.9 released 2013-10-01 +Changes + * x509_verify() now case insensitive for cn (RFC 6125 6.4) + +Bugfix + * Fixed potential memory leak when failing to resume a session + * Fixed potential file descriptor leaks (found by Remi Gacogne) + * Minor fixes + +Security + * Fixed potential heap buffer overflow on large hostname setting + * Fixed potential negative value misinterpretation in load_file() + * RSA blinding on CRT operations to counter timing attacks + (found by Cyril Arnaud and Pierre-Alain Fouque) + += Version 1.2.8 released 2013-06-19 +Features + * Parsing of PKCS#8 encrypted private key files + * PKCS#12 PBE and derivation functions + * Centralized module option values in config.h to allow user-defined + settings without editing header files by using POLARSSL_CONFIG_OPTIONS + +Changes + * HAVEGE random generator disabled by default + * Internally split up x509parse_key() into a (PEM) handler function + and specific DER parser functions for the PKCS#1 and unencrypted + PKCS#8 private key formats + * Added mechanism to provide alternative implementations for all + symmetric cipher and hash algorithms (e.g. POLARSSL_AES_ALT in + config.h) + * PKCS#5 module added. Moved PBKDF2 functionality inside and deprecated + old PBKDF2 module + +Bugfix + * Secure renegotiation extension should only be sent in case client + supports secure renegotiation + * Fixed offset for cert_type list in ssl_parse_certificate_request() + * Fixed const correctness issues that have no impact on the ABI + * x509parse_crt() now better handles PEM error situations + * ssl_parse_certificate() now calls x509parse_crt_der() directly + instead of the x509parse_crt() wrapper that can also parse PEM + certificates + * x509parse_crtpath() is now reentrant and uses more portable stat() + * Fixed bignum.c and bn_mul.h to support Thumb2 and LLVM compiler + * Fixed values for 2-key Triple DES in cipher layer + * ssl_write_certificate_request() can handle empty ca_chain + +Security + * A possible DoS during the SSL Handshake, due to faulty parsing of + PEM-encoded certificates has been fixed (found by Jack Lloyd) + += Version 1.2.7 released 2013-04-13 +Features + * Ability to specify allowed ciphersuites based on the protocol version. + +Changes + * Default Blowfish keysize is now 128-bits + * Test suites made smaller to accommodate Raspberry Pi + +Bugfix + * Fix for MPI assembly for ARM + * GCM adapted to support sizes > 2^29 + += Version 1.2.6 released 2013-03-11 +Bugfix + * Fixed memory leak in ssl_free() and ssl_reset() for active session + * Corrected GCM counter incrementation to use only 32-bits instead of + 128-bits (found by Yawning Angel) + * Fixes for 64-bit compilation with MS Visual Studio + * Fixed net_bind() for specified IP addresses on little endian systems + * Fixed assembly code for ARM (Thumb and regular) for some compilers + +Changes + * Internally split up rsa_pkcs1_encrypt(), rsa_pkcs1_decrypt(), + rsa_pkcs1_sign() and rsa_pkcs1_verify() to separate PKCS#1 v1.5 and + PKCS#1 v2.1 functions + * Added support for custom labels when using rsa_rsaes_oaep_encrypt() + or rsa_rsaes_oaep_decrypt() + * Re-added handling for SSLv2 Client Hello when the define + POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is set + * The SSL session cache module (ssl_cache) now also retains peer_cert + information (not the entire chain) + +Security + * Removed further timing differences during SSL message decryption in + ssl_decrypt_buf() + * Removed timing differences due to bad padding from + rsa_rsaes_pkcs1_v15_decrypt() and rsa_pkcs1_decrypt() for PKCS#1 v1.5 + operations + += Version 1.2.5 released 2013-02-02 +Changes + * Allow enabling of dummy error_strerror() to support some use-cases + * Debug messages about padding errors during SSL message decryption are + disabled by default and can be enabled with POLARSSL_SSL_DEBUG_ALL + * Sending of security-relevant alert messages that do not break + interoperability can be switched on/off with the flag + POLARSSL_SSL_ALL_ALERT_MESSAGES + +Security + * Removed timing differences during SSL message decryption in + ssl_decrypt_buf() due to badly formatted padding + += Version 1.2.4 released 2013-01-25 +Changes + * More advanced SSL ciphersuite representation and moved to more dynamic + SSL core + * Added ssl_handshake_step() to allow single stepping the handshake process + +Bugfix + * Memory leak when using RSA_PKCS_V21 operations fixed + * Handle future version properly in ssl_write_certificate_request() + * Correctly handle CertificateRequest message in client for <= TLS 1.1 + without DN list + += Version 1.2.3 released 2012-11-26 +Bugfix + * Server not always sending correct CertificateRequest message + += Version 1.2.2 released 2012-11-24 +Changes + * Added p_hw_data to ssl_context for context specific hardware acceleration + data + * During verify trust-CA is only checked for expiration and CRL presence + +Bugfixes + * Fixed client authentication compatibility + * Fixed dependency on POLARSSL_SHA4_C in SSL modules + += Version 1.2.1 released 2012-11-20 +Changes + * Depth that the certificate verify callback receives is now numbered + bottom-up (Peer cert depth is 0) + +Bugfixes + * Fixes for MSVC6 + * Moved mpi_inv_mod() outside POLARSSL_GENPRIME + * Allow R and A to point to same mpi in mpi_div_mpi (found by Manuel + Pégourié-Gonnard) + * Fixed possible segfault in mpi_shift_r() (found by Manuel + Pégourié-Gonnard) + * Added max length check for rsa_pkcs1_sign with PKCS#1 v2.1 + += Version 1.2.0 released 2012-10-31 +Features + * Added support for NULL cipher (POLARSSL_CIPHER_NULL_CIPHER) and weak + ciphersuites (POLARSSL_ENABLE_WEAK_CIPHERSUITES). They are disabled by + default! + * Added support for wildcard certificates + * Added support for multi-domain certificates through the X509 Subject + Alternative Name extension + * Added preliminary ASN.1 buffer writing support + * Added preliminary X509 Certificate Request writing support + * Added key_app_writer example application + * Added cert_req example application + * Added base Galois Counter Mode (GCM) for AES + * Added TLS 1.2 support (RFC 5246) + * Added GCM suites to TLS 1.2 (RFC 5288) + * Added commandline error code convertor (util/strerror) + * Added support for Hardware Acceleration hooking in SSL/TLS + * Added OpenSSL / PolarSSL compatibility script (tests/compat.sh) and + example application (programs/ssl/o_p_test) (requires OpenSSL) + * Added X509 CA Path support + * Added Thumb assembly optimizations + * Added DEFLATE compression support as per RFC3749 (requires zlib) + * Added blowfish algorithm (Generic and cipher layer) + * Added PKCS#5 PBKDF2 key derivation function + * Added Secure Renegotiation (RFC 5746) + * Added predefined DHM groups from RFC 5114 + * Added simple SSL session cache implementation + * Added ServerName extension parsing (SNI) at server side + * Added option to add minimum accepted SSL/TLS protocol version + +Changes + * Removed redundant POLARSSL_DEBUG_MSG define + * AES code only check for Padlock once + * Fixed const-correctness mpi_get_bit() + * Documentation for mpi_lsb() and mpi_msb() + * Moved out_msg to out_hdr + 32 to support hardware acceleration + * Changed certificate verify behaviour to comply with RFC 6125 section 6.3 + to not match CN if subjectAltName extension is present (Closes ticket #56) + * Cipher layer cipher_mode_t POLARSSL_MODE_CFB128 is renamed to + POLARSSL_MODE_CFB, to also handle different block size CFB modes. + * Removed handling for SSLv2 Client Hello (as per RFC 5246 recommendation) + * Revamped session resumption handling + * Generalized external private key implementation handling (like PKCS#11) + in SSL/TLS + * Revamped x509_verify() and the SSL f_vrfy callback implementations + * Moved from unsigned long to fixed width uint32_t types throughout code + * Renamed ciphersuites naming scheme to IANA reserved names + +Bugfix + * Fixed handling error in mpi_cmp_mpi() on longer B values (found by + Hui Dong) + * Fixed potential heap corruption in x509_name allocation + * Fixed single RSA test that failed on Big Endian systems (Closes ticket #54) + * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket + #52) + * Handle encryption with private key and decryption with public key as per + RFC 2313 + * Handle empty certificate subject names + * Prevent reading over buffer boundaries on X509 certificate parsing + * mpi_add_abs() now correctly handles adding short numbers to long numbers + with carry rollover (found by Ruslan Yushchenko) + * Handle existence of OpenSSL Trust Extensions at end of X.509 DER blob + * Fixed MPI assembly for SPARC64 platform + +Security + * Fixed potential memory zeroization on miscrafted RSA key (found by Eloi + Vanderbeken) + += Version 1.1.8 released on 2013-10-01 +Bugfix + * Fixed potential memory leak when failing to resume a session + * Fixed potential file descriptor leaks + +Security + * Potential buffer-overflow for ssl_read_record() (independently found by + both TrustInSoft and Paul Brodeur of Leviathan Security Group) + * Potential negative value misinterpretation in load_file() + * Potential heap buffer overflow on large hostname setting + += Version 1.1.7 released on 2013-06-19 +Changes + * HAVEGE random generator disabled by default + +Bugfix + * x509parse_crt() now better handles PEM error situations + * ssl_parse_certificate() now calls x509parse_crt_der() directly + instead of the x509parse_crt() wrapper that can also parse PEM + certificates + * Fixed values for 2-key Triple DES in cipher layer + * ssl_write_certificate_request() can handle empty ca_chain + +Security + * A possible DoS during the SSL Handshake, due to faulty parsing of + PEM-encoded certificates has been fixed (found by Jack Lloyd) + += Version 1.1.6 released on 2013-03-11 +Bugfix + * Fixed net_bind() for specified IP addresses on little endian systems + +Changes + * Allow enabling of dummy error_strerror() to support some use-cases + * Debug messages about padding errors during SSL message decryption are + disabled by default and can be enabled with POLARSSL_SSL_DEBUG_ALL + +Security + * Removed timing differences during SSL message decryption in + ssl_decrypt_buf() + * Removed timing differences due to bad padding from + rsa_rsaes_pkcs1_v15_decrypt() and rsa_pkcs1_decrypt() for PKCS#1 v1.5 + operations + += Version 1.1.5 released on 2013-01-16 +Bugfix + * Fixed MPI assembly for SPARC64 platform + * Handle existence of OpenSSL Trust Extensions at end of X.509 DER blob + * mpi_add_abs() now correctly handles adding short numbers to long numbers + with carry rollover + * Moved mpi_inv_mod() outside POLARSSL_GENPRIME + * Prevent reading over buffer boundaries on X509 certificate parsing + * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket + #52) + * Fixed possible segfault in mpi_shift_r() (found by Manuel + Pégourié-Gonnard) + * Allow R and A to point to same mpi in mpi_div_mpi (found by Manuel + Pégourié-Gonnard) + * Added max length check for rsa_pkcs1_sign with PKCS#1 v2.1 + * Memory leak when using RSA_PKCS_V21 operations fixed + * Handle encryption with private key and decryption with public key as per + RFC 2313 + * Fixes for MSVC6 + +Security + * Fixed potential memory zeroization on miscrafted RSA key (found by Eloi + Vanderbeken) + += Version 1.1.4 released on 2012-05-31 +Bugfix + * Correctly handle empty SSL/TLS packets (Found by James Yonan) + * Fixed potential heap corruption in x509_name allocation + * Fixed single RSA test that failed on Big Endian systems (Closes ticket #54) + += Version 1.1.3 released on 2012-04-29 +Bugfix + * Fixed random MPI generation to not generate more size than requested. + += Version 1.1.2 released on 2012-04-26 +Bugfix + * Fixed handling error in mpi_cmp_mpi() on longer B values (found by + Hui Dong) + +Security + * Fixed potential memory corruption on miscrafted client messages (found by + Frama-C team at CEA LIST) + * Fixed generation of DHM parameters to correct length (found by Ruslan + Yushchenko) + += Version 1.1.1 released on 2012-01-23 +Bugfix + * Check for failed malloc() in ssl_set_hostname() and x509_get_entries() + (Closes ticket #47, found by Hugo Leisink) + * Fixed issues with Intel compiler on 64-bit systems (Closes ticket #50) + * Fixed multiple compiler warnings for VS6 and armcc + * Fixed bug in CTR_CRBG selftest + += Version 1.1.0 released on 2011-12-22 +Features + * Added ssl_session_reset() to allow better multi-connection pools of + SSL contexts without needing to set all non-connection-specific + data and pointers again. Adapted ssl_server to use this functionality. + * Added ssl_set_max_version() to allow clients to offer a lower maximum + supported version to a server to help buggy server implementations. + (Closes ticket #36) + * Added cipher_get_cipher_mode() and cipher_get_cipher_operation() + introspection functions (Closes ticket #40) + * Added CTR_DRBG based on AES-256-CTR (NIST SP 800-90) random generator + * Added a generic entropy accumulator that provides support for adding + custom entropy sources and added some generic and platform dependent + entropy sources + +Changes + * Documentation for AES and Camellia in modes CTR and CFB128 clarified. + * Fixed rsa_encrypt and rsa_decrypt examples to use public key for + encryption and private key for decryption. (Closes ticket #34) + * Inceased maximum size of ASN1 length reads to 32-bits. + * Added an EXPLICIT tag number parameter to x509_get_ext() + * Added a separate CRL entry extension parsing function + * Separated the ASN.1 parsing code from the X.509 specific parsing code. + So now there is a module that is controlled with POLARSSL_ASN1_PARSE_C. + * Changed the defined key-length of DES ciphers in cipher.h to include the + parity bits, to prevent mistakes in copying data. (Closes ticket #33) + * Loads of minimal changes to better support WINCE as a build target + (Credits go to Marco Lizza) + * Added POLARSSL_MPI_WINDOW_SIZE definition to allow easier time to memory + trade-off + * Introduced POLARSSL_MPI_MAX_SIZE and POLARSSL_MPI_MAX_BITS for MPI size + management (Closes ticket #44) + * Changed the used random function pointer to more flexible format. Renamed + havege_rand() to havege_random() to prevent mistakes. Lots of changes as + a consequence in library code and programs + * Moved all examples programs to use the new entropy and CTR_DRBG + * Added permissive certificate parsing to x509parse_crt() and + x509parse_crtfile(). With permissive parsing the parsing does not stop on + encountering a parse-error. Beware that the meaning of return values has + changed! + * All error codes are now negative. Even on mermory failures and IO errors. + +Bugfix + * Fixed faulty HMAC-MD2 implementation. Found by dibac. (Closes + ticket #37) + * Fixed a bug where the CRL parser expected an EXPLICIT ASN.1 tag + before version numbers + * Allowed X509 key usage parsing to accept 4 byte values instead of the + standard 1 byte version sometimes used by Microsoft. (Closes ticket #38) + * Fixed incorrect behaviour in case of RSASSA-PSS with a salt length + smaller than the hash length. (Closes ticket #41) + * If certificate serial is longer than 32 octets, serial number is now + appended with '....' after first 28 octets + * Improved build support for s390x and sparc64 in bignum.h + * Fixed MS Visual C++ name clash with int64 in sha4.h + * Corrected removal of leading "00:" in printing serial numbers in + certificates and CRLs + += Version 1.0.0 released on 2011-07-27 +Features + * Expanded cipher layer with support for CFB128 and CTR mode + * Added rsa_encrypt and rsa_decrypt simple example programs. + +Changes + * The generic cipher and message digest layer now have normal error + codes instead of integers + +Bugfix + * Undid faulty bug fix in ssl_write() when flushing old data (Ticket + #18) + += Version 0.99-pre5 released on 2011-05-26 +Features + * Added additional Cipher Block Modes to symmetric ciphers + (AES CTR, Camellia CTR, XTEA CBC) including the option to + enable and disable individual modes when needed + * Functions requiring File System functions can now be disabled + by undefining POLARSSL_FS_IO + * A error_strerror function() has been added to translate between + error codes and their description. + * Added mpi_get_bit() and mpi_set_bit() individual bit setter/getter + functions. + * Added ssl_mail_client and ssl_fork_server as example programs. + +Changes + * Major argument / variable rewrite. Introduced use of size_t + instead of int for buffer lengths and loop variables for + better unsigned / signed use. Renamed internal bigint types + t_int and t_dbl to t_uint and t_udbl in the process + * mpi_init() and mpi_free() now only accept a single MPI + argument and do not accept variable argument lists anymore. + * The error codes have been remapped and combining error codes + is now done with a PLUS instead of an OR as error codes + used are negative. + * Changed behaviour of net_read(), ssl_fetch_input() and ssl_recv(). + net_recv() now returns 0 on EOF instead of + POLARSSL_ERR_NET_CONN_RESET. ssl_fetch_input() returns + POLARSSL_ERR_SSL_CONN_EOF on an EOF from its f_recv() function. + ssl_read() returns 0 if a POLARSSL_ERR_SSL_CONN_EOF is received + after the handshake. + * Network functions now return POLARSSL_ERR_NET_WANT_READ or + POLARSSL_ERR_NET_WANT_WRITE instead of the ambiguous + POLARSSL_ERR_NET_TRY_AGAIN + += Version 0.99-pre4 released on 2011-04-01 +Features + * Added support for PKCS#1 v2.1 encoding and thus support + for the RSAES-OAEP and RSASSA-PSS operations. + * Reading of Public Key files incorporated into default x509 + functionality as well. + * Added mpi_fill_random() for centralized filling of big numbers + with random data (Fixed ticket #10) + +Changes + * Debug print of MPI now removes leading zero octets and + displays actual bit size of the value. + * x509parse_key() (and as a consequence x509parse_keyfile()) + does not zeroize memory in advance anymore. Use rsa_init() + before parsing a key or keyfile! + +Bugfix + * Debug output of MPI's now the same independent of underlying + platform (32-bit / 64-bit) (Fixes ticket #19, found by Mads + Kiilerich and Mihai Militaru) + * Fixed bug in ssl_write() when flushing old data (Fixed ticket + #18, found by Nikolay Epifanov) + * Fixed proper handling of RSASSA-PSS verification with variable + length salt lengths + += Version 0.99-pre3 released on 2011-02-28 +This release replaces version 0.99-pre2 which had possible copyright issues. +Features + * Parsing PEM private keys encrypted with DES and AES + are now supported as well (Fixes ticket #5) + * Added crl_app program to allow easy reading and + printing of X509 CRLs from file + +Changes + * Parsing of PEM files moved to separate module (Fixes + ticket #13). Also possible to remove PEM support for + systems only using DER encoding + +Bugfixes + * Corrected parsing of UTCTime dates before 1990 and + after 1950 + * Support more exotic OID's when parsing certificates + (found by Mads Kiilerich) + * Support more exotic name representations when parsing + certificates (found by Mads Kiilerich) + * Replaced the expired test certificates + * Do not bail out if no client certificate specified. Try + to negotiate anonymous connection (Fixes ticket #12, + found by Boris Krasnovskiy) + +Security fixes + * Fixed a possible Man-in-the-Middle attack on the + Diffie Hellman key exchange (thanks to Larry Highsmith, + Subreption LLC) + += Version 0.99-pre1 released on 2011-01-30 +Features +Note: Most of these features have been donated by Fox-IT + * Added Doxygen source code documentation parts + * Added reading of DHM context from memory and file + * Improved X509 certificate parsing to include extended + certificate fields, including Key Usage + * Improved certificate verification and verification + against the available CRLs + * Detection for DES weak keys and parity bits added + * Improvements to support integration in other + applications: + + Added generic message digest and cipher wrapper + + Improved information about current capabilities, + status, objects and configuration + + Added verification callback on certificate chain + verification to allow external blacklisting + + Additional example programs to show usage + * Added support for PKCS#11 through the use of the + libpkcs11-helper library + +Changes + * x509parse_time_expired() checks time in addition to + the existing date check + * The ciphers member of ssl_context and the cipher member + of ssl_session have been renamed to ciphersuites and + ciphersuite respectively. This clarifies the difference + with the generic cipher layer and is better naming + altogether + += Version 0.14.0 released on 2010-08-16 +Features + * Added support for SSL_EDH_RSA_AES_128_SHA and + SSL_EDH_RSA_CAMELLIA_128_SHA ciphersuites + * Added compile-time and run-time version information + * Expanded ssl_client2 arguments for more flexibility + * Added support for TLS v1.1 + +Changes + * Made Makefile cleaner + * Removed dependency on rand() in rsa_pkcs1_encrypt(). + Now using random fuction provided to function and + changed the prototype of rsa_pkcs1_encrypt(), + rsa_init() and rsa_gen_key(). + * Some SSL defines were renamed in order to avoid + future confusion + +Bug fixes + * Fixed CMake out of source build for tests (found by + kkert) + * rsa_check_private() now supports PKCS1v2 keys as well + * Fixed deadlock in rsa_pkcs1_encrypt() on failing random + generator + += Version 0.13.1 released on 2010-03-24 +Bug fixes + * Fixed Makefile in library that was mistakenly merged + * Added missing const string fixes + += Version 0.13.0 released on 2010-03-21 +Features + * Added option parsing for host and port selection to + ssl_client2 + * Added support for GeneralizedTime in X509 parsing + * Added cert_app program to allow easy reading and + printing of X509 certificates from file or SSL + connection. + +Changes + * Added const correctness for main code base + * X509 signature algorithm determination is now + in a function to allow easy future expansion + * Changed symmetric cipher functions to + identical interface (returning int result values) + * Changed ARC4 to use separate input/output buffer + * Added reset function for HMAC context as speed-up + for specific use-cases + +Bug fixes + * Fixed bug resulting in failure to send the last + certificate in the chain in ssl_write_certificate() and + ssl_write_certificate_request() (found by fatbob) + * Added small fixes for compiler warnings on a Mac + (found by Frank de Brabander) + * Fixed algorithmic bug in mpi_is_prime() (found by + Smbat Tonoyan) + += Version 0.12.1 released on 2009-10-04 +Changes + * Coverage test definitions now support 'depends_on' + tagging system. + * Tests requiring specific hashing algorithms now honor + the defines. + +Bug fixes + * Changed typo in #ifdef in x509parse.c (found + by Eduardo) + += Version 0.12.0 released on 2009-07-28 +Features + * Added CMake makefiles as alternative to regular Makefiles. + * Added preliminary Code Coverage tests for AES, ARC4, + Base64, MPI, SHA-family, MD-family, HMAC-SHA-family, + Camellia, DES, 3-DES, RSA PKCS#1, XTEA, Diffie-Hellman + and X509parse. + +Changes + * Error codes are not (necessarily) negative. Keep + this is mind when checking for errors. + * RSA_RAW renamed to SIG_RSA_RAW for consistency. + * Fixed typo in name of POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE. + * Changed interface for AES and Camellia setkey functions + to indicate invalid key lengths. + +Bug fixes + * Fixed include location of endian.h on FreeBSD (found by + Gabriel) + * Fixed include location of endian.h and name clash on + Apples (found by Martin van Hensbergen) + * Fixed HMAC-MD2 by modifying md2_starts(), so that the + required HMAC ipad and opad variables are not cleared. + (found by code coverage tests) + * Prevented use of long long in bignum if + POLARSSL_HAVE_LONGLONG not defined (found by Giles + Bathgate). + * Fixed incorrect handling of negative strings in + mpi_read_string() (found by code coverage tests). + * Fixed segfault on handling empty rsa_context in + rsa_check_pubkey() and rsa_check_privkey() (found by + code coverage tests). + * Fixed incorrect handling of one single negative input + value in mpi_add_abs() (found by code coverage tests). + * Fixed incorrect handling of negative first input + value in mpi_sub_abs() (found by code coverage tests). + * Fixed incorrect handling of negative first input + value in mpi_mod_mpi() and mpi_mod_int(). Resulting + change also affects mpi_write_string() (found by code + coverage tests). + * Corrected is_prime() results for 0, 1 and 2 (found by + code coverage tests). + * Fixed Camellia and XTEA for 64-bit Windows systems. + += Version 0.11.1 released on 2009-05-17 + * Fixed missing functionality for SHA-224, SHA-256, SHA384, + SHA-512 in rsa_pkcs1_sign() + += Version 0.11.0 released on 2009-05-03 + * Fixed a bug in mpi_gcd() so that it also works when both + input numbers are even and added testcases to check + (found by Pierre Habouzit). + * Added support for SHA-224, SHA-256, SHA-384 and SHA-512 + one way hash functions with the PKCS#1 v1.5 signing and + verification. + * Fixed minor bug regarding mpi_gcd located within the + POLARSSL_GENPRIME block. + * Fixed minor memory leak in x509parse_crt() and added better + handling of 'full' certificate chains (found by Mathias + Olsson). + * Centralized file opening and reading for x509 files into + load_file() + * Made definition of net_htons() endian-clean for big endian + systems (Found by Gernot). + * Undefining POLARSSL_HAVE_ASM now also handles prevents asm in + padlock and timing code. + * Fixed an off-by-one buffer allocation in ssl_set_hostname() + responsible for crashes and unwanted behaviour. + * Added support for Certificate Revocation List (CRL) parsing. + * Added support for CRL revocation to x509parse_verify() and + SSL/TLS code. + * Fixed compatibility of XTEA and Camellia on a 64-bit system + (found by Felix von Leitner). + += Version 0.10.0 released on 2009-01-12 + * Migrated XySSL to PolarSSL + * Added XTEA symmetric cipher + * Added Camellia symmetric cipher + * Added support for ciphersuites: SSL_RSA_CAMELLIA_128_SHA, + SSL_RSA_CAMELLIA_256_SHA and SSL_EDH_RSA_CAMELLIA_256_SHA + * Fixed dangerous bug that can cause a heap overflow in + rsa_pkcs1_decrypt (found by Christophe Devine) + +================================================================ +XySSL ChangeLog + += Version 0.9 released on 2008-03-16 + + * Added support for ciphersuite: SSL_RSA_AES_128_SHA + * Enabled support for large files by default in aescrypt2.c + * Preliminary openssl wrapper contributed by David Barrett + * Fixed a bug in ssl_write() that caused the same payload to + be sent twice in non-blocking mode when send returns EAGAIN + * Fixed ssl_parse_client_hello(): session id and challenge must + not be swapped in the SSLv2 ClientHello (found by Greg Robson) + * Added user-defined callback debug function (Krystian Kolodziej) + * Before freeing a certificate, properly zero out all cert. data + * Fixed the "mode" parameter so that encryption/decryption are + not swapped on PadLock; also fixed compilation on older versions + of gcc (bug reported by David Barrett) + * Correctly handle the case in padlock_xcryptcbc() when input or + output data is non-aligned by falling back to the software + implementation, as VIA Nehemiah cannot handle non-aligned buffers + * Fixed a memory leak in x509parse_crt() which was reported by Greg + Robson-Garth; some x509write.c fixes by Pascal Vizeli, thanks to + Matthew Page who reported several bugs + * Fixed x509_get_ext() to accept some rare certificates which have + an INTEGER instead of a BOOLEAN for BasicConstraints::cA. + * Added support on the client side for the TLS "hostname" extension + (patch contributed by David Patino) + * Make x509parse_verify() return BADCERT_CN_MISMATCH when an empty + string is passed as the CN (bug reported by spoofy) + * Added an option to enable/disable the BN assembly code + * Updated rsa_check_privkey() to verify that (D*E) = 1 % (P-1)*(Q-1) + * Disabled obsolete hash functions by default (MD2, MD4); updated + selftest and benchmark to not test ciphers that have been disabled + * Updated x509parse_cert_info() to correctly display byte 0 of the + serial number, setup correct server port in the ssl client example + * Fixed a critical denial-of-service with X.509 cert. verification: + peer may cause xyssl to loop indefinitely by sending a certificate + for which the RSA signature check fails (bug reported by Benoit) + * Added test vectors for: AES-CBC, AES-CFB, DES-CBC and 3DES-CBC, + HMAC-MD5, HMAC-SHA1, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 + * Fixed HMAC-SHA-384 and HMAC-SHA-512 (thanks to Josh Sinykin) + * Modified ssl_parse_client_key_exchange() to protect against + Daniel Bleichenbacher attack on PKCS#1 v1.5 padding, as well + as the Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * Updated rsa_gen_key() so that ctx->N is always nbits in size + * Fixed assembly PPC compilation errors on Mac OS X, thanks to + David Barrett and Dusan Semen + += Version 0.8 released on 2007-10-20 + + * Modified the HMAC functions to handle keys larger + than 64 bytes, thanks to Stephane Desneux and gary ng + * Fixed ssl_read_record() to properly update the handshake + message digests, which fixes IE6/IE7 client authentication + * Cleaned up the XYSSL* #defines, suggested by Azriel Fasten + * Fixed net_recv(), thanks to Lorenz Schori and Egon Kocjan + * Added user-defined callbacks for handling I/O and sessions + * Added lots of debugging output in the SSL/TLS functions + * Added preliminary X.509 cert. writing by Pascal Vizeli + * Added preliminary support for the VIA PadLock routines + * Added AES-CFB mode of operation, contributed by chmike + * Added an SSL/TLS stress testing program (ssl_test.c) + * Updated the RSA PKCS#1 code to allow choosing between + RSA_PUBLIC and RSA_PRIVATE, as suggested by David Barrett + * Updated ssl_read() to skip 0-length records from OpenSSL + * Fixed the make install target to comply with *BSD make + * Fixed a bug in mpi_read_binary() on 64-bit platforms + * mpi_is_prime() speedups, thanks to Kevin McLaughlin + * Fixed a long standing memory leak in mpi_is_prime() + * Replaced realloc with malloc in mpi_grow(), and set + the sign of zero as positive in mpi_init() (reported + by Jonathan M. McCune) + += Version 0.7 released on 2007-07-07 + + * Added support for the MicroBlaze soft-core processor + * Fixed a bug in ssl_tls.c which sometimes prevented SSL + connections from being established with non-blocking I/O + * Fixed a couple bugs in the VS6 and UNIX Makefiles + * Fixed the "PIC register ebx clobbered in asm" bug + * Added HMAC starts/update/finish support functions + * Added the SHA-224, SHA-384 and SHA-512 hash functions + * Fixed the net_set_*block routines, thanks to Andreas + * Added a few demonstration programs: md5sum, sha1sum, + dh_client, dh_server, rsa_genkey, rsa_sign, rsa_verify + * Added new bignum import and export helper functions + * Rewrote README.txt in program/ssl/ca to better explain + how to create a test PKI + += Version 0.6 released on 2007-04-01 + + * Ciphers used in SSL/TLS can now be disabled at compile + time, to reduce the memory footprint on embedded systems + * Added multiply assembly code for the TriCore and modified + havege_struct for this processor, thanks to David Patiño + * Added multiply assembly code for 64-bit PowerPCs, + thanks to Peking University and the OSU Open Source Lab + * Added experimental support of Quantum Cryptography + * Added support for autoconf, contributed by Arnaud Cornet + * Fixed "long long" compilation issues on IA-64 and PPC64 + * Fixed a bug introduced in xyssl-0.5/timing.c: hardclock + was not being correctly defined on ARM and MIPS + += Version 0.5 released on 2007-03-01 + + * Added multiply assembly code for SPARC and Alpha + * Added (beta) support for non-blocking I/O operations + * Implemented session resuming and client authentication + * Fixed some portability issues on WinCE, MINIX 3, Plan9 + (thanks to Benjamin Newman), HP-UX, FreeBSD and Solaris + * Improved the performance of the EDH key exchange + * Fixed a bug that caused valid packets with a payload + size of 16384 bytes to be rejected + += Version 0.4 released on 2007-02-01 + + * Added support for Ephemeral Diffie-Hellman key exchange + * Added multiply asm code for SSE2, ARM, PPC, MIPS and M68K + * Various improvement to the modular exponentiation code + * Rewrote the headers to generate the API docs with doxygen + * Fixed a bug in ssl_encrypt_buf (incorrect padding was + generated) and in ssl_parse_client_hello (max. client + version was not properly set), thanks to Didier Rebeix + * Fixed another bug in ssl_parse_client_hello: clients with + cipherlists larger than 96 bytes were incorrectly rejected + * Fixed a couple memory leak in x509_read.c + += Version 0.3 released on 2007-01-01 + + * Added server-side SSLv3 and TLSv1.0 support + * Multiple fixes to enhance the compatibility with g++, + thanks to Xosé Antón Otero Ferreira + * Fixed a bug in the CBC code, thanks to dowst; also, + the bignum code is no longer dependent on long long + * Updated rsa_pkcs1_sign to handle arbitrary large inputs + * Updated timing.c for improved compatibility with i386 + and 486 processors, thanks to Arnaud Cornet + += Version 0.2 released on 2006-12-01 + + * Updated timing.c to support ARM and MIPS arch + * Updated the MPI code to support 8086 on MSVC 1.5 + * Added the copyright notice at the top of havege.h + * Fixed a bug in sha2_hmac, thanks to newsoft/Wenfang Zhang + * Fixed a bug reported by Adrian Rüegsegger in x509_read_key + * Fixed a bug reported by Torsten Lauter in ssl_read_record + * Fixed a bug in rsa_check_privkey that would wrongly cause + valid RSA keys to be dismissed (thanks to oldwolf) + * Fixed a bug in mpi_is_prime that caused some primes to fail + the Miller-Rabin primality test + + I'd also like to thank Younès Hafri for the CRUX linux port, + Khalil Petit who added XySSL into pkgsrc and Arnaud Cornet + who maintains the Debian package :-) + += Version 0.1 released on 2006-11-01 diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/LICENSE b/optee/optee_os/lib/libmbedtls/mbedtls/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/README.md b/optee/optee_os/lib/libmbedtls/mbedtls/README.md new file mode 100644 index 0000000..df85ff2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/README.md @@ -0,0 +1,264 @@ +README for Mbed TLS +=================== + +Mbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems. + +Mbed TLS includes a reference implementation of the [PSA Cryptography API](#psa-cryptography-api). This is currently a preview for evaluation purposes only. + +Configuration +------------- + +Mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Python 3 script `scripts/config.py` (use `--help` for usage instructions). + +Compiler options can be set using conventional environment variables such as `CC` and `CFLAGS` when using the Make and CMake build system (see below). + +We provide some non-standard configurations focused on specific use cases in the `configs/` directory. You can read more about those in `configs/README.txt` + +Documentation +------------- + +Documentation for the Mbed TLS interfaces in the default library configuration is available as part of the [Mbed TLS documentation](https://tls.mbed.org/api/). + +To generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration: + +1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed. We use version 1.8.11 but slightly older or more recent versions should work. +1. Run `make apidoc`. +1. Browse `apidoc/index.html` or `apidoc/modules.html`. + +For other sources of documentation, see the [SUPPORT](SUPPORT.md) document. + +Compiling +--------- + +There are currently three active build systems used within Mbed TLS releases: + +- GNU Make +- CMake +- Microsoft Visual Studio (Microsoft Visual Studio 2013 or later) + +The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically. + +The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`. + +### Tool versions + +You need the following tools to build the library with the provided makefiles: + +* GNU Make or a build tool that CMake supports. +* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, IAR8 and Visual Studio 2013. More recent versions should work. Slightly older versions may work. +* Python 3 to generate the test code. +* Perl to run the tests. + +### Make + +We require GNU Make. To build the library and the sample programs, GNU Make and a C compiler are sufficient. Some of the more advanced build targets require some Unix/Linux tools. + +We intentionally only use a minimum of functionality in the makefiles in order to keep them as simple and independent of different toolchains as possible, to allow users to more easily move between different platforms. Users who need more features are recommended to use CMake. + +In order to build from the source code using GNU Make, just enter at the command line: + + make + +In order to run the tests, enter: + + make check + +The tests need Python to be built and Perl to be run. If you don't have one of them installed, you can skip building the tests with: + + make no_test + +You'll still be able to run a much smaller set of tests with: + + programs/test/selftest + +In order to build for a Windows platform, you should use `WINDOWS_BUILD=1` if the target is Windows but the build environment is Unix-like (for instance when cross-compiling, or compiling from an MSYS shell), and `WINDOWS=1` if the build environment is a Windows shell (for instance using mingw32-make) (in that case some targets will not be available). + +Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved. + +Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -Wextra`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overridden from the command line. + +Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://tls.mbed.org/kb) for articles on your platform or issue. + +In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://tls.mbed.org/kb). + +### CMake + +In order to build the source using CMake in a separate directory (recommended), just enter at the command line: + + mkdir /path/to/build_dir && cd /path/to/build_dir + cmake /path/to/mbedtls_source + cmake --build . + +In order to run the tests, enter: + + ctest + +The test suites need Python to be built and Perl to be executed. If you don't have one of these installed, you'll want to disable the test suites with: + + cmake -DENABLE_TESTING=Off /path/to/mbedtls_source + +If you disabled the test suites, but kept the programs enabled, you can still run a much smaller set of tests with: + + programs/test/selftest + +To configure CMake for building shared libraries, use: + + cmake -DUSE_SHARED_MBEDTLS_LIBRARY=On /path/to/mbedtls_source + +There are many different build modes available within the CMake buildsystem. Most of them are available for gcc and clang, though some are compiler-specific: + +- `Release`. This generates the default code without any unnecessary information in the binary files. +- `Debug`. This generates debug information and disables optimization of the code. +- `Coverage`. This generates code coverage information in addition to debug information. +- `ASan`. This instruments the code with AddressSanitizer to check for memory errors. (This includes LeakSanitizer, with recent version of gcc and clang.) (With recent version of clang, this mode also instruments the code with UndefinedSanitizer to check for undefined behaviour.) +- `ASanDbg`. Same as ASan but slower, with debug information and better stack traces. +- `MemSan`. This instruments the code with MemorySanitizer to check for uninitialised memory reads. Experimental, needs recent clang on Linux/x86\_64. +- `MemSanDbg`. Same as MemSan but slower, with debug information, better stack traces and origin tracking. +- `Check`. This activates the compiler warnings that depend on optimization and treats all warnings as errors. + +Switching build modes in CMake is simple. For debug mode, enter at the command line: + + cmake -D CMAKE_BUILD_TYPE=Debug /path/to/mbedtls_source + +To list other available CMake options, use: + + cmake -LH + +Note that, with CMake, you can't adjust the compiler or its flags after the +initial invocation of cmake. This means that `CC=your_cc make` and `make +CC=your_cc` will *not* work (similarly with `CFLAGS` and other variables). +These variables need to be adjusted when invoking cmake for the first time, +for example: + + CC=your_cc cmake /path/to/mbedtls_source + +If you already invoked cmake and want to change those settings, you need to +remove the build directory and create it again. + +Note that it is possible to build in-place; this will however overwrite the +provided Makefiles (see `scripts/tmp_ignore_makefiles.sh` if you want to +prevent `git status` from showing them as modified). In order to do so, from +the Mbed TLS source directory, use: + + cmake . + make + +If you want to change `CC` or `CFLAGS` afterwards, you will need to remove the +CMake cache. This can be done with the following command using GNU find: + + find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} + + +You can now make the desired change: + + CC=your_cc cmake . + make + +Regarding variables, also note that if you set CFLAGS when invoking cmake, +your value of CFLAGS doesn't override the content provided by cmake (depending +on the build mode as seen above), it's merely prepended to it. + +#### Mbed TLS as a subproject + +Mbed TLS supports being built as a CMake subproject. One can +use `add_subdirectory()` from a parent CMake project to include Mbed TLS as a +subproject. + +### Microsoft Visual Studio + +The build files for Microsoft Visual Studio are generated for Visual Studio 2010. + +The solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need Python and perl environments as well. However, the selftest program in `programs/test/` is still available. + +Example programs +---------------- + +We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md). +Please note that the goal of these sample programs is to demonstrate specific features of the library, and the code may need to be adapted to build a real-world application. + +Tests +----- + +Mbed TLS includes an elaborate test suite in `tests/` that initially requires Python to generate the tests files (e.g. `test\_suite\_mpi.c`). These files are generated from a `function file` (e.g. `suites/test\_suite\_mpi.function`) and a `data file` (e.g. `suites/test\_suite\_mpi.data`). The `function file` contains the test functions. The `data file` contains the test cases, specified as parameters that will be passed to the test function. + +For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, additional test scripts are available: + +- `tests/ssl-opt.sh` runs integration tests for various TLS options (renegotiation, resumption, etc.) and tests interoperability of these options with other implementations. +- `tests/compat.sh` tests interoperability of every ciphersuite with other implementations. +- `tests/scripts/test-ref-configs.pl` test builds in various reduced configurations. +- `tests/scripts/key-exchanges.pl` test builds in configurations with a single key exchange enabled +- `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `config.h`, etc). + +Porting Mbed TLS +---------------- + +Mbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following Knowledge Base articles useful: + +- [Porting Mbed TLS to a new environment or OS](https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS) +- [What external dependencies does Mbed TLS rely on?](https://tls.mbed.org/kb/development/what-external-dependencies-does-mbedtls-rely-on) +- [How do I configure Mbed TLS](https://tls.mbed.org/kb/compiling-and-building/how-do-i-configure-mbedtls) + +Mbed TLS is mostly written in portable C99; however, it has a few platform requirements that go beyond the standard, but are met by most modern architectures: + +- Bytes must be 8 bits. +- All-bits-zero must be a valid representation of a null pointer. +- Signed integers must be represented using two's complement. +- `int` and `size_t` must be at least 32 bits wide. +- The types `uint8_t`, `uint16_t`, `uint32_t` and their signed equivalents must be available. + +PSA cryptography API +-------------------- + +### PSA API design + +Arm's [Platform Security Architecture (PSA)](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level. + +The [PSA cryptography API](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform. + +The design goals of the PSA cryptography API include: + +* The API distinguishes caller memory from internal memory, which allows the library to be implemented in an isolated space for additional security. Library calls can be implemented as direct function calls if isolation is not desired, and as remote procedure calls if isolation is desired. +* The structure of internal data is hidden to the application, which allows substituting alternative implementations at build time or run time, for example, in order to take advantage of hardware accelerators. +* All access to the keys happens through key identifiers, which allows support for external cryptoprocessors that is transparent to applications. +* The interface to algorithms is generic, favoring algorithm agility. +* The interface is designed to be easy to use and hard to accidentally misuse. + +Arm welcomes feedback on the design of the API. If you think something could be improved, please open an issue on our Github repository. Alternatively, if you prefer to provide your feedback privately, please email us at [`mbed-crypto@arm.com`](mailto:mbed-crypto@arm.com). All feedback received by email is treated confidentially. + +### PSA API documentation + +A browsable copy of the PSA Cryptography API documents is available on the [PSA cryptography interfaces documentation portal](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) in [PDF](https://armmbed.github.io/mbed-crypto/PSA_Cryptography_API_Specification.pdf) and [HTML](https://armmbed.github.io/mbed-crypto/html/index.html) formats. + +### PSA implementation in Mbed TLS + +Mbed TLS includes a reference implementation of the PSA Cryptography API. +This implementation is not yet as mature as the rest of the library. Some parts of the code have not been reviewed as thoroughly, and some parts of the PSA implementation are not yet well optimized for code size. + +The X.509 and TLS code can use PSA cryptography for a limited subset of operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `config.h`. + +There are currently a few deviations where the library does not yet implement the latest version of the specification. Please refer to the [compliance issues on Github](https://github.com/Mbed-TLS/mbed-crypto/labels/compliance) for an up-to-date list. + +### Upcoming features + +Future releases of this library will include: + +* A driver programming interface, which makes it possible to use hardware accelerators instead of the default software implementation for chosen algorithms. +* Support for external keys to be stored and manipulated exclusively in a separate cryptoprocessor. +* A configuration mechanism to compile only the algorithms you need for your application. +* A wider set of cryptographic algorithms. + +License +------- + +Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license. Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. This enables LTS (Long Term Support) branches of the software to be provided under either the Apache-2.0 OR GPL-2.0-or-later licenses. + +Contributing +------------ + +We gratefully accept bug reports and contributions from the community. Please see the [contributing guidelines](CONTRIBUTING.md) for details on how to do this. + +Contact +------- + +* To report a security vulnerability in Mbed TLS, please email . For more information, see [`SECURITY.md`](SECURITY.md). +* To report a bug or request a feature in Mbed TLS, please [file an issue on GitHub](https://github.com/Mbed-TLS/mbedtls/issues/new/choose). +* Please see [`SUPPORT.md`](SUPPORT.md) for other channels for discussion and support about Mbed TLS. diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md b/optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md new file mode 100644 index 0000000..26b77ab --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/SECURITY.md @@ -0,0 +1,20 @@ +## Reporting Vulneratibilities + +If you think you have found an Mbed TLS security vulnerability, then please +send an email to the security team at +. + +## Security Incident Handling Process + +Our security process is detailed in our +[security +center](https://developer.trustedfirmware.org/w/mbed-tls/security-center/). + +Its primary goal is to ensure fixes are ready to be deployed when the issue +goes public. + +## Maintained branches + +Only the maintained branches, as listed in [`BRANCHES.md`](BRANCHES.md), +get security fixes. +Users are urged to always use the latest version of a maintained branch. diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md b/optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md new file mode 100644 index 0000000..dab7ac5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/SUPPORT.md @@ -0,0 +1,15 @@ +## Documentation + +Here are some useful sources of information about using Mbed TLS: + +- API documentation, see the [Documentation section of the + README](README.md#License); +- the `docs` directory in the source tree; +- the [Mbed TLS knowledge Base](https://tls.mbed.org/kb); +- the [Mbed TLS mailing-list + archives](https://lists.trustedfirmware.org/archives/list/mbed-tls@lists.trustedfirmware.org/). + +## Asking Questions + +If you can't find your answer in the above sources, please use the [Mbed TLS +mailing list](https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org). diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/dco.txt b/optee/optee_os/lib/libmbedtls/mbedtls/dco.txt new file mode 100644 index 0000000..8201f99 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/dco.txt @@ -0,0 +1,37 @@ +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h new file mode 100644 index 0000000..401ac39 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aes.h @@ -0,0 +1,689 @@ +/** + * \file aes.h + * + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/platform_util.h" + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +/** Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 +/** Invalid data input length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 + +/* Error codes in range 0x0021-0x0025 */ +/** Invalid input data. */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 + +/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ +/** Feature not available. For example, an unsupported AES key size. */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 + +/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** AES hardware accelerator failed. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct mbedtls_aes_context +{ + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context +{ + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. + + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (\c 16 Bytes). + * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in Bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length Bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length Bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 Bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both strategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * It must point to a valid \c size_t. + * \param nonce_counter The 128-bit nonce and counter. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_encrypt() + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_decrypt() + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_aes_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h new file mode 100644 index 0000000..c1d22f5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aesni.h @@ -0,0 +1,136 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_AESNI_H +#define MBEDTLS_AESNI_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_HAVE_X86_64 +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal function to detect the AES-NI feature in CPUs. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param what The feature to detect + * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesni_has_support( unsigned int what ); + +/** + * \brief Internal AES-NI AES-ECB block encryption and decryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, + int nr ); + +/** + * \brief Internal key expansion for encryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h new file mode 100644 index 0000000..f4b0f9f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/arc4.h @@ -0,0 +1,145 @@ +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef MBEDTLS_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** ARC4 hardware accelerator failed. */ +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +/** + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * + */ +typedef struct mbedtls_arc4_context +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +mbedtls_arc4_context; + +#else /* MBEDTLS_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* MBEDTLS_ARC4_ALT */ + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h new file mode 100644 index 0000000..d294c47 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/aria.h @@ -0,0 +1,373 @@ +/** + * \file aria.h + * + * \brief ARIA block cipher + * + * The ARIA algorithm is a symmetric block cipher that can encrypt and + * decrypt information. It is defined by the Korean Agency for + * Technology and Standards (KATS) in KS X 1213:2004 (in + * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) + * and also described by the IETF in RFC 5794. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_ARIA_H +#define MBEDTLS_ARIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ +#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ + +#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ +#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maximum number of rounds in ARIA. */ +#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +/** Bad input data. */ +#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C + +/** Invalid data input length. */ +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E + +/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used. + */ +/** Feature not available. For example, an unsupported ARIA key size. */ +#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A + +/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** ARIA hardware accelerator failed. */ +#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_ARIA_ALT) +// Regular implementation +// + +/** + * \brief The ARIA context-type definition. + */ +typedef struct mbedtls_aria_context +{ + unsigned char nr; /*!< The number of rounds (12, 14 or 16) */ + /*! The ARIA round keys. */ + uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; +} +mbedtls_aria_context; + +#else /* MBEDTLS_ARIA_ALT */ +#include "aria_alt.h" +#endif /* MBEDTLS_ARIA_ALT */ + +/** + * \brief This function initializes the specified ARIA context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The ARIA context to initialize. This must not be \c NULL. + */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ); + +/** + * \brief This function releases and clears the specified ARIA context. + * + * \param ctx The ARIA context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized ARIA context. + */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The encryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of \p key in Bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an ARIA single-block encryption or + * decryption operation. + * + * It performs encryption or decryption (depending on whether + * the key was set for encryption on decryption) on the input + * data buffer defined in the \p input parameter. + * + * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or + * mbedtls_aria_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an ARIA-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aria_init(), and either + * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the ARIA block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an ARIA-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data \p input in Bytes. + * \param iv_off The offset in IV (updated after use). + * This must not be larger than 15. + * \param iv The initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an ARIA-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aria_setkey_enc() + * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both strategies, sizes are measured in blocks and + * that an ARIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param length The length of the input data \p input in Bytes. + * \param nc_off The offset in Bytes in the current \p stream_block, + * for resuming within the current cipher stream. The + * offset pointer should be \c 0 at the start of a + * stream. This must not be larger than \c 15 Bytes. + * \param nonce_counter The 128-bit nonce and counter. This must point to + * a read/write buffer of length \c 16 bytes. + * \param stream_block The saved stream block for resuming. This must + * point to a read/write buffer of length \c 16 bytes. + * This is overwritten by the function. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aria_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aria.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h new file mode 100644 index 0000000..5117fc7 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h @@ -0,0 +1,616 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +/** Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 +/** ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 +/** Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 +/** Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 +/** Data is invalid. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 +/** Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A +/** Buffer too small when writing ASN.1 data structure. */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C + +/** \} name ASN1 Error codes */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_ENUMERATED 0x0A +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* Slightly smaller way to check if tag is a string tag + * compared to canonical implementation. */ +#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \ + ( ( tag ) < 32u && ( \ + ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \ + ( 1u << MBEDTLS_ASN1_T61_STRING ) | \ + ( 1u << MBEDTLS_ASN1_IA5_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \ + ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \ + ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) ) + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/** \} name DER constants */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \ + memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p On entry, \c *p points to the first byte of the length, + * i.e. immediately after the tag. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the element. + * Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * \param tag The expected tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start + * with the requested tag. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value (\c 0 or \c 1). + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BOOLEAN. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an enumerated ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 ENUMERATED. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param bs On success, ::mbedtls_asn1_bitstring information about + * the parsed value. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid BIT STRING. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs ); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * of the content of the BIT STRING. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On success, \c *len is the length of the content in bytes. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with + * a valid BIT STRING with a nonzero number of unused bits. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF ". + * Updates the pointer to immediately behind the full sequence tag. + * + * This function allocates memory for the sequence elements. You can free + * the allocated memory with mbedtls_asn1_sequence_free(). + * + * \note On error, this function may return a partial list in \p cur. + * You must set `cur->next = NULL` before calling this function! + * Otherwise it is impossible to distinguish a previously non-null + * pointer from a pointer to an object allocated by this function. + * + * \note If the sequence is empty, this function does not modify + * \c *cur. If the sequence is valid and non-empty, this + * function sets `cur->buf.tag` to \p tag. This allows + * callers to distinguish between an empty sequence and + * a one-element sequence. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param cur A ::mbedtls_asn1_sequence which this function fills. + * When this function returns, \c *cur is the head of a linked + * list. Each node in this list is allocated with + * mbedtls_calloc() apart from \p cur itself, and should + * therefore be freed with mbedtls_free(). + * The list describes the content of the sequence. + * The head of the list (i.e. \c *cur itself) describes the + * first element, `*cur->next` describes the second element, etc. + * For each element, `buf.tag == tag`, `buf.len` is the length + * of the content of the content of the element, and `buf.p` + * points to the first byte of the content (i.e. immediately + * past the length of the element). + * Note that list elements may be allocated even on error. + * \param tag Each element of the sequence must have this tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid SEQUENCE OF \p tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with + * an ASN.1 SEQUENCE in which an element has a tag that + * is different from \p tag. + * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag ); +/** + * \brief Free a heap-allocated linked list presentation of + * an ASN.1 sequence, including the first element. + * + * There are two common ways to manage the memory used for the representation + * of a parsed ASN.1 sequence: + * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). + * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head`. + * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, + * for example on the stack. Make sure that `head->next == NULL`. + * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head->cur`, + * then free `head` itself in the appropriate manner. + * + * \param seq The address of the first sequence component. This may + * be \c NULL, in which case this functions returns + * immediately. + */ +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ); + +/** + * \brief Traverse an ASN.1 SEQUENCE container and + * call a callback for each entry. + * + * This function checks that the input is a SEQUENCE of elements that + * each have a "must" tag, and calls a callback function on the elements + * that have a "may" tag. + * + * For example, to validate that the input is a SEQUENCE of `tag1` and call + * `cb` on each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of ANY and call `cb` on + * each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} + * and call `cb` on each element that is an OCTET STRING, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); + * ``` + * + * The callback is called on the elements with a "may" tag from left to + * right. If the input is not a valid SEQUENCE of elements with a "must" tag, + * the callback is called on the elements up to the leftmost point where + * the input is invalid. + * + * \warning This function is still experimental and may change + * at any time. + * + * \param p The address of the pointer to the beginning of + * the ASN.1 SEQUENCE header. This is updated to + * point to the end of the ASN.1 SEQUENCE container + * on a successful invocation. + * \param end The end of the ASN.1 SEQUENCE container. + * \param tag_must_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_must_value. + * \param tag_must_val The required value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_must_mask. + * Mismatching tags lead to an error. + * For example, a value of \c 0 for both \p tag_must_mask + * and \p tag_must_val means that every tag is allowed, + * while a value of \c 0xFF for \p tag_must_mask means + * that \p tag_must_val is the only allowed tag. + * \param tag_may_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_may_value. + * \param tag_may_val The desired value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_may_mask. + * Mismatching tags will be silently ignored. + * For example, a value of \c 0 for \p tag_may_mask and + * \p tag_may_val means that any tag will be considered, + * while a value of \c 0xFF for \p tag_may_mask means + * that all tags with value different from \p tag_may_val + * will be ignored. + * \param cb The callback to trigger for each component + * in the ASN.1 SEQUENCE that matches \p tag_may_val. + * The callback function is called with the following + * parameters: + * - \p ctx. + * - The tag of the current element. + * - A pointer to the start of the current element's + * content inside the input. + * - The length of the content of the current element. + * If the callback returns a non-zero value, + * the function stops immediately, + * forwarding the callback's return value. + * \param ctx The context to be passed to the callback \p cb. + * + * \return \c 0 if successful the entire ASN.1 SEQUENCE + * was traversed without parsing or callback errors. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input + * contains extra data after a valid SEQUENCE + * of elements with an accepted tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts + * with an ASN.1 SEQUENCE in which an element has a tag + * that is not accepted. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + * \return A non-zero error code forwarded from the callback + * \p cb in case the latter returns a non-zero value. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char* start, size_t len ), + void *ctx ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param X On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + * \return An MPI error code if the parsed value is too large. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * \param params The buffer to receive the parameters. + * This is zeroized if there are no parameters. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free. + * This function calls mbedtls_free() on + * `entry->oid.p` and `entry->val.p`. + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list. + * + * \param head Pointer to the head of the list of named data entries to free. + * This function calls mbedtls_asn1_free_named_data() and + * mbedtls_free() on each list element and + * sets \c *head to \c NULL. + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +/** \} name Functions to parse ASN.1 data structures */ +/** \} addtogroup asn1_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h new file mode 100644 index 0000000..44afae0 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h @@ -0,0 +1,370 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" + +#define MBEDTLS_ASN1_CHK_ADD(g, f) \ + do \ + { \ + if( ( ret = (f) ) < 0 ) \ + return( ret ); \ + else \ + (g) += ret; \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param len The length value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, + size_t len ); +/** + * \brief Write an ASN.1 tag in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The tag to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The data buffer to write. + * \param size The length of the data buffer. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param X The MPI to write. + * It must be non-negative. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, + const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID to write. + * \param oid_len The length of the OID. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID of the algorithm to write. + * \param oid_len The length of the algorithm's OID. + * \param par_len The length of the parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, + unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param boolean The boolean value to write, either \c 0 or \c 1. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, + int boolean ); + +/** + * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * It must be non-negative. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a string in ASN.1 format using a specific + * string encoding tag. + + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The string encoding tag to write, e.g. + * #MBEDTLS_ASN1_UTF8_STRING. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, + int tag, const char *text, + size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the PrintableString + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, + unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a UTF8 string in ASN.1 format using the UTF8String + * string encoding tag (#MBEDTLS_ASN1_UTF8_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the IA5String + * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief This function writes a named bitstring tag + * (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format. + * + * As stated in RFC 5280 Appendix B, trailing zeroes are + * omitted when encoding named bitstrings in DER. + * + * \note This function works backwards within the data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer which is used for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_named_bitstring( unsigned char **p, + unsigned char *start, + const unsigned char *buf, + size_t bits ); + +/** + * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) + * and value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The buffer holding the data to write. + * \param size The length of the data buffer \p buf. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list The pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry). + * \param oid The OID to look for. + * \param oid_len The size of the OID. + * \param val The associated data to store. If this is \c NULL, + * no data is copied to the new or existing buffer. + * \param val_len The minimum length of the data buffer needed. + * If this is 0, do not allocate a buffer for the associated + * data. + * If the OID was already present, enlarge, shrink or free + * the existing buffer to fit \p val_len. + * + * \return A pointer to the new / existing entry on success. + * \return \c NULL if if there was a memory allocation error. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h new file mode 100644 index 0000000..cf4149e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/base64.h @@ -0,0 +1,98 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A +/** Invalid character in input. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h new file mode 100644 index 0000000..3f109c6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h @@ -0,0 +1,1097 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +/** An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 +/** There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 +/** The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 +/** The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A +/** The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C +/** The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E +/** Memory allocation failed. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 + +#define MBEDTLS_MPI_CHK(f) \ + do \ + { \ + if( ( ret = (f) ) != 0 ) \ + goto cleanup; \ + } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) || \ + defined(__aarch64__) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct mbedtls_mpi +{ + short s; /*!< Sign: -1 if the mpi is negative, 1 otherwise */ + short use_mempool; + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +extern void *mbedtls_mpi_mempool; + +/** + * \brief Initialize an MPI context. + * + * This makes the MPI ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X The MPI context to initialize. This must not be \c NULL. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); +void mbedtls_mpi_init_mempool( mbedtls_mpi *X ); + +/** + * \brief This function frees the components of an MPI context. + * + * \param X The MPI context to be cleared. This may be \c NULL, + * in which case this function is a no-op. If it is + * not \c NULL, it must point to an initialized MPI. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge an MPI to the specified number of limbs. + * + * \note This function does nothing if the MPI is + * already large enough. + * + * \param X The MPI to grow. It must be initialized. + * \param nblimbs The target number of limbs. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief This function resizes an MPI downwards, keeping at least the + * specified number of limbs. + * + * If \c X is smaller than \c nblimbs, it is resized up + * instead. + * + * \param X The MPI to shrink. This must point to an initialized MPI. + * \param nblimbs The minimum number of limbs to keep. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Make a copy of an MPI. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param Y The source MPI. This must point to an initialized MPI. + * + * \note The limb-buffer in the destination MPI is enlarged + * if necessary to hold the value in the source MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of two MPIs. + * + * \param X The first MPI. It must be initialized. + * \param Y The second MPI. It must be initialized. + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Perform a safe conditional copy of MPI which doesn't + * reveal whether the condition was true or not. + * + * \param X The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param Y The MPI to be assigned from. This must point to an + * initialized MPI. + * \param assign The condition deciding whether to perform the + * assignment or not. Possible values: + * * \c 1: Perform the assignment `X = Y`. + * * \c 0: Keep the original value of \p X. + * + * \note This function is equivalent to + * `if( assign ) mbedtls_mpi_copy( X, Y );` + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Perform a safe conditional swap which doesn't + * reveal whether the condition was true or not. + * + * \param X The first MPI. This must be initialized. + * \param Y The second MPI. This must be initialized. + * \param assign The condition deciding whether to perform + * the swap or not. Possible values: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + * + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Store integer value in MPI. + * + * \param X The MPI to set. This must be initialized. + * \param z The value to use. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from an MPI. + * + * \param X The MPI to query. This must be initialized. + * \param pos Zero-based index of the bit to query. + * + * \return \c 0 or \c 1 on success, depending on whether bit \c pos + * of \c X is unset or set. + * \return A negative error code on failure. + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Modify a specific bit in an MPI. + * + * \note This function will grow the target MPI if necessary to set a + * bit to \c 1 in a not yet existing limb. It will not grow if + * the bit should be set to \c 0. + * + * \param X The MPI to modify. This must be initialized. + * \param pos Zero-based index of the bit to modify. + * \param val The desired value of bit \c pos: \c 0 or \c 1. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of bits of value \c 0 before the + * least significant bit of value \c 1. + * + * \note This is the same as the zero-based index of + * the least significant bit of value \c 1. + * + * \param X The MPI to query. + * + * \return The number of bits of value \c 0 before the least significant + * bit of value \c 1 in \p X. + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant bit of value \c 1. + * + * * \note This is same as the one-based index of the most + * significant bit of value \c 1. + * + * \param X The MPI to query. This must point to an initialized MPI. + * + * \return The number of bits up to and including the most + * significant bit of value \c 1. + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size of an MPI value in bytes. + * + * \param X The MPI to use. This must point to an initialized MPI. + * + * \note The value returned by this function may be less than + * the number of bytes used to store \p X internally. + * This happens if and only if there are trailing bytes + * of value zero. + * + * \return The least number of bytes capable of storing + * the absolute value of \p X. + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import an MPI from an ASCII string. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the input string. + * \param s Null-terminated string buffer. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export an MPI to an ASCII string. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base of the output string. + * \param buf The buffer to write the string to. This must be writable + * buffer of length \p buflen Bytes. + * \param buflen The available size in Bytes of \p buf. + * \param olen The address at which to store the length of the string + * written, including the final \c NULL byte. This must + * not be \c NULL. + * + * \note You can call this function with `buflen == 0` to obtain the + * minimum required buffer size in `*olen`. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf + * is too small to hold the value of \p X in the desired base. + * In this case, `*olen` is nonetheless updated to contain the + * size of \p buf required for a successful call. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read an MPI from a line in an opened file. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the string representation used + * in the source line. + * \param fin The input file handle to use. This must not be \c NULL. + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns \c 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix \c 16. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer + * is too small. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Export an MPI into an opened file. + * + * \param p A string prefix to emit prior to the MPI data. + * For example, this might be a label, or "0x" when + * printing in base \c 16. This may be \c NULL if no prefix + * is needed. + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base to be used in the emitted string. + * \param fout The output file handle. This may be \c NULL, in which case + * the output is written to \c stdout. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, + int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import an MPI from unsigned big endian binary data. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Import X from unsigned binary data, little endian + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, + size_t buflen ); + +/** + * \brief Export X into unsigned binary data, little endian. + * Always fills the whole buffer, which will end with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ); + +/** + * \brief Perform a left-shift on an MPI: X <<= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Perform a right-shift on an MPI: X >>= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare the absolute values of two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if `|X|` is greater than `|Y|`. + * \return \c -1 if `|X|` is lesser than `|Y|`. + * \return \c 0 if `|X|` is equal to `|Y|`. + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if \p X is greater than \p Y. + * \return \c -1 if \p X is lesser than \p Y. + * \return \c 0 if \p X is equal to \p Y. + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an initialized MPI + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an initialized MPI + * with the same allocated length as X. + * \param ret The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + * + * \return 0 on success. + * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of + * the two input MPIs is not the same. + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ); + +/** + * \brief Compare an MPI with an integer. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param z The integer value to compare \p X to. + * + * \return \c 1 if \p X is greater than \p z. + * \return \c -1 if \p X is lesser than \p z. + * \return \c 0 if \p X is equal to \p z. + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Perform an unsigned addition of MPIs: X = |A| + |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of MPIs: X = A + B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed subtraction of MPIs: X = A - B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of an MPI and an integer: X = A + b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param b The second summand. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a signed subtraction of an MPI and an integer: + * X = A - b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param b The subtrahend. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a multiplication of two MPIs: X = A * B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param B The second factor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a multiplication of an MPI with an unsigned integer: + * X = A * b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param b The second factor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_uint b ); + +/** + * \brief Perform a division with remainder of two MPIs: + * A = Q * B + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param B The divisor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a division with remainder of an MPI by an integer: + * A = Q * b + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param b The divisor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a modular reduction. R = A mod B + * + * \param R The destination MPI for the residue value. + * This must point to an initialized MPI. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPI. + * \param B The base of the modular reduction. + * This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a modular reduction with respect to an integer. + * r = A mod b + * + * \param r The address at which to store the residue. + * This must not be \c NULL. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPi. + * \param b The integer base of the modular reduction. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a sliding-window exponentiation: X = A^E mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The base of the exponentiation. + * This must point to an initialized MPI. + * \param E The exponent MPI. This must point to an initialized MPI. + * \param N The base for the modular reduction. This must point to an + * initialized MPI. + * \param prec_RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. If it hasn't been used after + * the call to mbedtls_mpi_init(), this function will compute + * the helper value and store it in \p prec_RR for reuse on + * subsequent calls to this function. Otherwise, the function + * will assume that \p prec_RR holds the helper value set by a + * previous call to mbedtls_mpi_exp_mod(), and reuse it. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * \return Another negative error code on different kinds of failures. + * + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *prec_RR ); + +/** + * \brief Fill an MPI with a number of random bytes. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param size The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on failure. + * + * \note The bytes obtained from the RNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** Generate a random number uniformly in a range. + * + * This function generates a random number between \p min inclusive and + * \p N exclusive. + * + * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) + * when the RNG is a suitably parametrized instance of HMAC_DRBG + * and \p min is \c 1. + * + * \note There are `N - min` possible outputs. The lower bound + * \p min can be reached, but the upper bound \p N cannot. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param min The minimum value to return. + * It must be nonnegative. + * \param N The upper bound of the range, exclusive. + * In other words, this is one plus the maximum value to return. + * \p N must be strictly larger than \p min. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p min or \p N is invalid + * or if they are incompatible. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was + * unable to find a suitable value within a limited number + * of attempts. This has a negligible probability if \p N + * is significantly larger than \p min, which is the case + * for all usual cryptographic applications. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_random( mbedtls_mpi *X, + mbedtls_mpi_sint min, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute the greatest common divisor: G = gcd(A, B) + * + * \param G The destination MPI. This must point to an initialized MPI. + * \param A The first operand. This must point to an initialized MPI. + * \param B The second operand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Compute the modular inverse: X = A^-1 mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The MPI to calculate the modular inverse of. This must point + * to an initialized MPI. + * \param N The base of the modular inversion. This must point to an + * initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than + * or equal to one. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse + * with respect to \p N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *N ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Perform a Miller-Rabin primality test with error + * probability of 2-80. + * + * \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows + * specifying the number of Miller-Rabin rounds. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use a + * context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Miller-Rabin primality test. + * + * \warning If \p X is potentially generated by an adversary, for example + * when validating cryptographic parameters that you didn't + * generate yourself and that are supposed to be prime, then + * \p rounds should be at least the half of the security + * strength of the cryptographic algorithm. On the other hand, + * if \p X is chosen uniformly or non-adversarially (as is the + * case when mbedtls_mpi_gen_prime calls this function), then + * \p rounds can be much lower. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param rounds The number of bases to perform the Miller-Rabin primality + * test for. The probability of returning 0 on a composite is + * at most 2-2*\p rounds. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +/** + * \brief Flags for mbedtls_mpi_gen_prime() + * + * Each of these flags is a constraint on the result X returned by + * mbedtls_mpi_gen_prime(). + */ +typedef enum { + MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ + MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ +} mbedtls_mpi_gen_prime_flag_t; + +/** + * \brief Generate a prime number. + * + * \param X The destination MPI to store the generated prime in. + * This must point to an initialized MPi. + * \param nbits The required size of the destination MPI in bits. + * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. + * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, in which case \p X holds a + * probably prime number. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between + * \c 3 and #MBEDTLS_MPI_MAX_BITS. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Montgomery initialization + * + * \param mm The -1/m mod N result + * \param N The modulus + */ +void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ); + +/** + * \brief Montgomery multiplication: A = A * B * R^-1 mod N + * \A Parameter and result + * \B Parameter + * \N Modulus + * \mm Parameter from mbedtls_mpi_montg_init() + * \T Temporary variable, should be as twice as big as N + 2 + */ +void mbedtls_mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, + const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ); + +/** + * \brief Montgomery reduction: A = A * R^-1 mod N + * \A Parameter and result + * \N Modulus + * \mm Parameter from mbedtls_mpi_montg_init() + * \T Temporary variable, should be as twice as big as N + 2 + */ +void mbedtls_mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h new file mode 100644 index 0000000..d5f8099 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/blowfish.h @@ -0,0 +1,288 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_BLOWFISH_ENCRYPT 1 +#define MBEDTLS_BLOWFISH_DECRYPT 0 +#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 +#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 +#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +/** Bad input data. */ +#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 + +/** Invalid data input length. */ +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 + +/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used. + */ +/** Blowfish hardware accelerator failed. */ +#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + +/** + * \brief Blowfish context structure + */ +typedef struct mbedtls_blowfish_context +{ + uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +mbedtls_blowfish_context; + +#else /* MBEDTLS_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + +/** + * \brief Initialize a Blowfish context. + * + * \param ctx The Blowfish context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); + +/** + * \brief Clear a Blowfish context. + * + * \param ctx The Blowfish context to be cleared. + * This may be \c NULL, in which case this function + * returns immediately. If it is not \c NULL, it must + * point to an initialized Blowfish context. + */ +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); + +/** + * \brief Perform a Blowfish key schedule operation. + * + * \param ctx The Blowfish context to perform the key schedule on. + * \param key The encryption key. This must be a readable buffer of + * length \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be between + * \c 32 and \c 448 and a multiple of \c 8. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a Blowfish-ECB block encryption/decryption operation. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param input The input block. This must be a readable buffer + * of size \c 8 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 8 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a Blowfish-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be + * multiple of \c 8. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 8 Bytes. It is updated by this function. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a Blowfish CFB buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in the initialization vector. + * The value pointed to must be smaller than \c 8 Bytes. + * It is updated by this function to support the aforementioned + * streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of size \c 8 Bytes. It is updated after use. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a Blowfish-CTR buffer encryption/decryption operation. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**64 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 4 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 4 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**32 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. + * + * Note that for both strategies, sizes are measured in blocks and + * that a Blowfish block is 8 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data in Bytes. + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer + * should be \c 0 at the start of a stream and must be + * smaller than \c 8. It is updated by this function. + * \param nonce_counter The 64-bit nonce and counter. This must point to a + * read/write buffer of length \c 8 Bytes. + * \param stream_block The saved stream-block for resuming. This must point to + * a read/write buffer of length \c 8 Bytes. + * \param input The input data. This must be a readable buffer of + * length \p length Bytes. + * \param output The output data. This must be a writable buffer of + * length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#endif /* blowfish.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h new file mode 100644 index 0000000..31137cd --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/bn_mul.h @@ -0,0 +1,978 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) + +#define MBEDTLS_BYTES_TO_T_UINT_2( a, b ) \ + MBEDTLS_BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ), \ + MBEDTLS_BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) | \ + ( (mbedtls_mpi_uint) (e) << 32 ) | \ + ( (mbedtls_mpi_uint) (f) << 40 ) | \ + ( (mbedtls_mpi_uint) (g) << 48 ) | \ + ( (mbedtls_mpi_uint) (h) << 56 ) + +#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ) \ + MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define MBEDTLS_BYTES_TO_T_UINT_2( a, b ) \ + MBEDTLS_BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in mbedtls_mpi_uint */ + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8\n" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \ + : "b" (b), "m" (*(const uint64_t (*)[16]) s) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__aarch64__) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr x4, [%2], #8 \n\t" \ + "ldr x5, [%1] \n\t" \ + "mul x6, x4, %4 \n\t" \ + "umulh x7, x4, %4 \n\t" \ + "adds x5, x5, x6 \n\t" \ + "adc x7, x7, xzr \n\t" \ + "adds x5, x5, %0 \n\t" \ + "adc %0, x7, xzr \n\t" \ + "str x5, [%1], #8 \n\t" + +#define MULADDC_STOP \ + : "+r" (c), "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d) \ + : "r" (b), "m" (*(const uint64_t (*)[16]) s) \ + : "x4", "x5", "x6", "x7", "cc" \ + ); + +#endif /* Aarch64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about + * our use of r7 below, unless -fomit-frame-pointer is passed. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#elif (__ARM_ARCH >= 6) && \ + defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr r0, [%0], #4 \n\t" \ + "ldr r1, [%1] \n\t" \ + "umaal r1, %2, %3, r0 \n\t" \ + "str r1, [%1], #4 \n\t" + +#define MULADDC_STOP \ + : "=r" (s), "=r" (d), "=r" (c) \ + : "r" (b), "0" (s), "1" (d), "2" (c) \ + : "r0", "r1", "memory" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h new file mode 100644 index 0000000..d39d932 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h @@ -0,0 +1,327 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +/** Bad input data. */ +#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 + +/** Invalid data input length. */ +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 + +/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used. + */ +/** Camellia hardware accelerator failed. */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +/** + * \brief CAMELLIA context structure + */ +typedef struct mbedtls_camellia_context +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + +/** + * \brief Initialize a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, + * in which case this function returns immediately. If it is not + * \c NULL, it must be initialized. + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief Perform a CAMELLIA key schedule operation for encryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The encryption key to use. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA key schedule operation for decryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param input The input block. This must be a readable buffer + * of size \c 16 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 16 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length in Bytes of the input data \p input. + * This must be a multiple of \c 16 Bytes. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated to allow streaming + * use as explained above. + * \param input The buffer holding the input data. This must point to a + * readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must point to a + * writable buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption + * operation. + * + * \note Due to the nature of CFB mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length of the input data \p input. Any value is allowed. + * \param iv_off The current offset in the IV. This must be smaller + * than \c 16 Bytes. It is updated after this call to allow + * the aforementioned streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated after this call to + * allow the aforementioned streaming usage. + * \param input The buffer holding the input data. This must be a readable + * buffer of size \p length Bytes. + * \param output The buffer to hold the output data. This must be a writable + * buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. + * + * *note Due to the nature of CTR mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first \c 12 Bytes for the + * per-message nonce, and the last \c 4 Bytes for internal use. + * In that case, before calling this function on a new message you + * need to set the first \c 12 Bytes of \p nonce_counter to your + * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 + * (which will cause \p stream_block to be ignored). That way, you + * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks + * each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be + * unique. The recommended way to ensure uniqueness is to use a + * message counter. An alternative is to generate random nonces, + * but this limits the number of messages that can be securely + * encrypted: for example, with 96-bit random nonces, you should + * not encrypt more than 2**32 messages with the same key. + * + * Note that for both strategies, sizes are measured in blocks and + * that a CAMELLIA block is \c 16 Bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data \p input in Bytes. + * Any value is allowed. + * \param nc_off The offset in the current \p stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be \c 0 at the start of a stream. It is updated + * at the end of this call. + * \param nonce_counter The 128-bit nonce and counter. This must be a read/write + * buffer of length \c 16 Bytes. + * \param stream_block The saved stream-block for resuming. This must be a + * read/write buffer of length \c 16 Bytes. + * \param input The input data stream. This must be a readable buffer of + * size \p length Bytes. + * \param output The output data stream. This must be a writable buffer + * of size \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h new file mode 100644 index 0000000..ece5a90 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h @@ -0,0 +1,311 @@ +/** + * \file ccm.h + * + * \brief This file provides an API for the CCM authenticated encryption + * mode for block ciphers. + * + * CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CCM_H +#define MBEDTLS_CCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +/** Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D +/** Authenticated decryption failed. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F + +/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** CCM hardware accelerator failed. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct mbedtls_ccm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} +mbedtls_ccm_context; + +#else /* MBEDTLS_CCM_ALT */ +#include "ccm_alt.h" +#endif /* MBEDTLS_CCM_ALT */ + +/** + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). + * + * \param ctx The CCM context to initialize. This must not be \c NULL. + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The CCM context to initialize. This must be an initialized + * context. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must not be \c NULL. + * \param keybits The key size in bits. This must be acceptable by the cipher. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function releases and clears the specified CCM context + * and underlying cipher sub-context. + * + * \param ctx The CCM context to clear. If this is \c NULL, the function + * has no effect. Otherwise, this must be initialized. + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief This function encrypts a buffer using CCM. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. If \p add_len is greater than + * zero, \p add must be a readable buffer of at least that + * length. + * \param add_len The length of additional data in Bytes. + * This must be less than `2^16 - 2^8`. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function encrypts a buffer using CCM*. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \note When using this function in a variable tag length context, + * the tag length has to be encoded into the \p iv passed to + * this function. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer + * of at least that \p add_len Bytes.. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. This indicates that the message is authentic. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM* authenticated decryption of a + * buffer. + * + * \note When using this function in a variable tag length context, + * the tag length has to be decoded from \p iv and passed to + * this function as \p tag_len. (\p tag needs to be adjusted + * accordingly.) + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least that \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field in Bytes. + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is nos + * longer authenticated. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The CCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/certs.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/certs.h new file mode 100644 index 0000000..c93c741 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/certs.h @@ -0,0 +1,250 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_CERTS_H +#define MBEDTLS_CERTS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* List of all PEM-encoded CA certificates, terminated by NULL; + * PEM encoded if MBEDTLS_PEM_PARSE_C is enabled, DER encoded + * otherwise. */ +extern const char * mbedtls_test_cas[]; +extern const size_t mbedtls_test_cas_len[]; + +/* List of all DER-encoded CA certificates, terminated by NULL */ +extern const unsigned char * mbedtls_test_cas_der[]; +extern const size_t mbedtls_test_cas_der_len[]; + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all CA certificates in PEM format if available */ +extern const char mbedtls_test_cas_pem[]; +extern const size_t mbedtls_test_cas_pem_len; +#endif /* MBEDTLS_PEM_PARSE_C */ + +/* + * CA test certificates + */ + +extern const char mbedtls_test_ca_crt_ec_pem[]; +extern const char mbedtls_test_ca_key_ec_pem[]; +extern const char mbedtls_test_ca_pwd_ec_pem[]; +extern const char mbedtls_test_ca_key_rsa_pem[]; +extern const char mbedtls_test_ca_pwd_rsa_pem[]; +extern const char mbedtls_test_ca_crt_rsa_sha1_pem[]; +extern const char mbedtls_test_ca_crt_rsa_sha256_pem[]; + +extern const unsigned char mbedtls_test_ca_crt_ec_der[]; +extern const unsigned char mbedtls_test_ca_key_ec_der[]; +extern const unsigned char mbedtls_test_ca_key_rsa_der[]; +extern const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[]; +extern const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[]; + +extern const size_t mbedtls_test_ca_crt_ec_pem_len; +extern const size_t mbedtls_test_ca_key_ec_pem_len; +extern const size_t mbedtls_test_ca_pwd_ec_pem_len; +extern const size_t mbedtls_test_ca_key_rsa_pem_len; +extern const size_t mbedtls_test_ca_pwd_rsa_pem_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len; + +extern const size_t mbedtls_test_ca_crt_ec_der_len; +extern const size_t mbedtls_test_ca_key_ec_der_len; +extern const size_t mbedtls_test_ca_pwd_ec_der_len; +extern const size_t mbedtls_test_ca_key_rsa_der_len; +extern const size_t mbedtls_test_ca_pwd_rsa_der_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_der_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_ca_crt_ec[]; +extern const char mbedtls_test_ca_key_ec[]; +extern const char mbedtls_test_ca_pwd_ec[]; +extern const char mbedtls_test_ca_key_rsa[]; +extern const char mbedtls_test_ca_pwd_rsa[]; +extern const char mbedtls_test_ca_crt_rsa_sha1[]; +extern const char mbedtls_test_ca_crt_rsa_sha256[]; + +extern const size_t mbedtls_test_ca_crt_ec_len; +extern const size_t mbedtls_test_ca_key_ec_len; +extern const size_t mbedtls_test_ca_pwd_ec_len; +extern const size_t mbedtls_test_ca_key_rsa_len; +extern const size_t mbedtls_test_ca_pwd_rsa_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha1_len; +extern const size_t mbedtls_test_ca_crt_rsa_sha256_len; + +/* Config-dependent dispatch between SHA-1 and SHA-256 + * (SHA-256 if enabled, otherwise SHA-1) */ + +extern const char mbedtls_test_ca_crt_rsa[]; +extern const size_t mbedtls_test_ca_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_ca_crt; +extern const char * mbedtls_test_ca_key; +extern const char * mbedtls_test_ca_pwd; +extern const size_t mbedtls_test_ca_crt_len; +extern const size_t mbedtls_test_ca_key_len; +extern const size_t mbedtls_test_ca_pwd_len; + +/* + * Server test certificates + */ + +extern const char mbedtls_test_srv_crt_ec_pem[]; +extern const char mbedtls_test_srv_key_ec_pem[]; +extern const char mbedtls_test_srv_pwd_ec_pem[]; +extern const char mbedtls_test_srv_key_rsa_pem[]; +extern const char mbedtls_test_srv_pwd_rsa_pem[]; +extern const char mbedtls_test_srv_crt_rsa_sha1_pem[]; +extern const char mbedtls_test_srv_crt_rsa_sha256_pem[]; + +extern const unsigned char mbedtls_test_srv_crt_ec_der[]; +extern const unsigned char mbedtls_test_srv_key_ec_der[]; +extern const unsigned char mbedtls_test_srv_key_rsa_der[]; +extern const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[]; +extern const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[]; + +extern const size_t mbedtls_test_srv_crt_ec_pem_len; +extern const size_t mbedtls_test_srv_key_ec_pem_len; +extern const size_t mbedtls_test_srv_pwd_ec_pem_len; +extern const size_t mbedtls_test_srv_key_rsa_pem_len; +extern const size_t mbedtls_test_srv_pwd_rsa_pem_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len; + +extern const size_t mbedtls_test_srv_crt_ec_der_len; +extern const size_t mbedtls_test_srv_key_ec_der_len; +extern const size_t mbedtls_test_srv_pwd_ec_der_len; +extern const size_t mbedtls_test_srv_key_rsa_der_len; +extern const size_t mbedtls_test_srv_pwd_rsa_der_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_der_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_srv_crt_ec[]; +extern const char mbedtls_test_srv_key_ec[]; +extern const char mbedtls_test_srv_pwd_ec[]; +extern const char mbedtls_test_srv_key_rsa[]; +extern const char mbedtls_test_srv_pwd_rsa[]; +extern const char mbedtls_test_srv_crt_rsa_sha1[]; +extern const char mbedtls_test_srv_crt_rsa_sha256[]; + +extern const size_t mbedtls_test_srv_crt_ec_len; +extern const size_t mbedtls_test_srv_key_ec_len; +extern const size_t mbedtls_test_srv_pwd_ec_len; +extern const size_t mbedtls_test_srv_key_rsa_len; +extern const size_t mbedtls_test_srv_pwd_rsa_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha1_len; +extern const size_t mbedtls_test_srv_crt_rsa_sha256_len; + +/* Config-dependent dispatch between SHA-1 and SHA-256 + * (SHA-256 if enabled, otherwise SHA-1) */ + +extern const char mbedtls_test_srv_crt_rsa[]; +extern const size_t mbedtls_test_srv_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_srv_crt; +extern const char * mbedtls_test_srv_key; +extern const char * mbedtls_test_srv_pwd; +extern const size_t mbedtls_test_srv_crt_len; +extern const size_t mbedtls_test_srv_key_len; +extern const size_t mbedtls_test_srv_pwd_len; + +/* + * Client test certificates + */ + +extern const char mbedtls_test_cli_crt_ec_pem[]; +extern const char mbedtls_test_cli_key_ec_pem[]; +extern const char mbedtls_test_cli_pwd_ec_pem[]; +extern const char mbedtls_test_cli_key_rsa_pem[]; +extern const char mbedtls_test_cli_pwd_rsa_pem[]; +extern const char mbedtls_test_cli_crt_rsa_pem[]; + +extern const unsigned char mbedtls_test_cli_crt_ec_der[]; +extern const unsigned char mbedtls_test_cli_key_ec_der[]; +extern const unsigned char mbedtls_test_cli_key_rsa_der[]; +extern const unsigned char mbedtls_test_cli_crt_rsa_der[]; + +extern const size_t mbedtls_test_cli_crt_ec_pem_len; +extern const size_t mbedtls_test_cli_key_ec_pem_len; +extern const size_t mbedtls_test_cli_pwd_ec_pem_len; +extern const size_t mbedtls_test_cli_key_rsa_pem_len; +extern const size_t mbedtls_test_cli_pwd_rsa_pem_len; +extern const size_t mbedtls_test_cli_crt_rsa_pem_len; + +extern const size_t mbedtls_test_cli_crt_ec_der_len; +extern const size_t mbedtls_test_cli_key_ec_der_len; +extern const size_t mbedtls_test_cli_key_rsa_der_len; +extern const size_t mbedtls_test_cli_crt_rsa_der_len; + +/* Config-dependent dispatch between PEM and DER encoding + * (PEM if enabled, otherwise DER) */ + +extern const char mbedtls_test_cli_crt_ec[]; +extern const char mbedtls_test_cli_key_ec[]; +extern const char mbedtls_test_cli_pwd_ec[]; +extern const char mbedtls_test_cli_key_rsa[]; +extern const char mbedtls_test_cli_pwd_rsa[]; +extern const char mbedtls_test_cli_crt_rsa[]; + +extern const size_t mbedtls_test_cli_crt_ec_len; +extern const size_t mbedtls_test_cli_key_ec_len; +extern const size_t mbedtls_test_cli_pwd_ec_len; +extern const size_t mbedtls_test_cli_key_rsa_len; +extern const size_t mbedtls_test_cli_pwd_rsa_len; +extern const size_t mbedtls_test_cli_crt_rsa_len; + +/* Config-dependent dispatch between EC and RSA + * (RSA if enabled, otherwise EC) */ + +extern const char * mbedtls_test_cli_crt; +extern const char * mbedtls_test_cli_key; +extern const char * mbedtls_test_cli_pwd; +extern const size_t mbedtls_test_cli_crt_len; +extern const size_t mbedtls_test_cli_key_len; +extern const size_t mbedtls_test_cli_pwd_len; + +#ifdef __cplusplus +} +#endif + +#endif /* certs.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h new file mode 100644 index 0000000..03b4871 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h @@ -0,0 +1,228 @@ +/** + * \file chacha20.h + * + * \brief This file contains ChaCha20 definitions and functions. + * + * ChaCha20 is a stream cipher that can encrypt and decrypt + * information. ChaCha was created by Daniel Bernstein as a variant of + * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf + * ChaCha20 is the variant with 20 rounds, that was also standardized + * in RFC 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CHACHA20_H +#define MBEDTLS_CHACHA20_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/** Invalid input parameter(s). */ +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 + +/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +/** Feature not available. For example, s part of the API is not implemented. */ +#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 + +/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used. + */ +/** Chacha20 hardware accelerator failed. */ +#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct mbedtls_chacha20_context +{ + uint32_t state[16]; /*! The state (before round operations). */ + uint8_t keystream8[64]; /*! Leftover keystream bytes. */ + size_t keystream_bytes_used; /*! Number of keystream bytes already used. */ +} +mbedtls_chacha20_context; + +#else /* MBEDTLS_CHACHA20_ALT */ +#include "chacha20_alt.h" +#endif /* MBEDTLS_CHACHA20_ALT */ + +/** + * \brief This function initializes the specified ChaCha20 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by calls to + * \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts(), then one or more calls to + * to \c mbedtls_chacha20_update(), and finally to + * \c mbedtls_chacha20_free(). + * + * \param ctx The ChaCha20 context to initialize. + * This must not be \c NULL. + */ +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. This may be \c NULL, + * in which case this function is a no-op. If it is not + * \c NULL, it must point to an initialized context. + * + */ +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function sets the encryption/decryption key. + * + * \note After using this function, you must also call + * \c mbedtls_chacha20_starts() to set a nonce before you + * start encrypting/decrypting data with + * \c mbedtls_chacha_update(). + * + * \param ctx The ChaCha20 context to which the key should be bound. + * It must be initialized. + * \param key The encryption/decryption key. This must be \c 32 Bytes + * in length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. + */ +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function sets the nonce and initial counter value. + * + * \note A ChaCha20 context can be re-used with the same key by + * calling this function to change the nonce. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality guarantees for the + * messages encrypted with the same nonce and key. + * + * \param ctx The ChaCha20 context to which the nonce should be bound. + * It must be initialized and bound to a key. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is + * NULL. + */ +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ); + +/** + * \brief This function encrypts or decrypts data. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \note \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts() must be called at least once + * to setup the context before this function can be called. + * + * \note This function can be called multiple times in a row in + * order to encrypt of decrypt data piecewise with the same + * key and nonce. + * + * \param ctx The ChaCha20 context to use for encryption or decryption. + * It must be initialized and bound to a key and nonce. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function encrypts or decrypts data with ChaCha20 and + * the given key and nonce. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \warning You must never use the same (key, nonce) pair more than + * once. This would void any confidentiality guarantees for + * the messages encrypted with the same nonce and key. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \param key The encryption/decryption key. + * This must be \c 32 Bytes in length. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t size, + const unsigned char* input, + unsigned char* output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chacha20_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHA20_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h new file mode 100644 index 0000000..ed568bc --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h @@ -0,0 +1,359 @@ +/** + * \file chachapoly.h + * + * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and + * functions. + * + * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption + * with Associated Data (AEAD) that can be used to encrypt and + * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel + * Bernstein and was standardized in RFC 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CHACHAPOLY_H +#define MBEDTLS_CHACHAPOLY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* for shared error codes */ +#include "mbedtls/poly1305.h" + +/** The requested operation is not permitted in the current state. */ +#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 +/** Authenticated decryption failed: data was not authentic. */ +#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ + MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ +} +mbedtls_chachapoly_mode_t; + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#include "mbedtls/chacha20.h" + +typedef struct mbedtls_chachapoly_context +{ + mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ + mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ + uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */ + int state; /**< The current state of the context. */ + mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */ +} +mbedtls_chachapoly_context; + +#else /* !MBEDTLS_CHACHAPOLY_ALT */ +#include "chachapoly_alt.h" +#endif /* !MBEDTLS_CHACHAPOLY_ALT */ + +/** + * \brief This function initializes the specified ChaCha20-Poly1305 context. + * + * It must be the first API called before using + * the context. It must be followed by a call to + * \c mbedtls_chachapoly_setkey() before any operation can be + * done, and to \c mbedtls_chachapoly_free() once all + * operations with that context have been finished. + * + * In order to encrypt or decrypt full messages at once, for + * each message you should make a single call to + * \c mbedtls_chachapoly_crypt_and_tag() or + * \c mbedtls_chachapoly_auth_decrypt(). + * + * In order to encrypt messages piecewise, for each + * message you should make a call to + * \c mbedtls_chachapoly_starts(), then 0 or more calls to + * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to + * \c mbedtls_chachapoly_update(), then one call to + * \c mbedtls_chachapoly_finish(). + * + * \warning Decryption with the piecewise API is discouraged! Always + * use \c mbedtls_chachapoly_auth_decrypt() when possible! + * + * If however this is not possible because the data is too + * large to fit in memory, you need to: + * + * - call \c mbedtls_chachapoly_starts() and (if needed) + * \c mbedtls_chachapoly_update_aad() as above, + * - call \c mbedtls_chachapoly_update() multiple times and + * ensure its output (the plaintext) is NOT used in any other + * way than placing it in temporary storage at this point, + * - call \c mbedtls_chachapoly_finish() to compute the + * authentication tag and compared it in constant time to the + * tag received with the ciphertext. + * + * If the tags are not equal, you must immediately discard + * all previous outputs of \c mbedtls_chachapoly_update(), + * otherwise you can now safely use the plaintext. + * + * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. + */ +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20-Poly1305 context. + * + * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which + * case this function is a no-op. + */ +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function sets the ChaCha20-Poly1305 + * symmetric encryption key. + * + * \param ctx The ChaCha20-Poly1305 context to which the key should be + * bound. This must be initialized. + * \param key The \c 256 Bit (\c 32 Bytes) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function starts a ChaCha20-Poly1305 encryption or + * decryption operation. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \note If the context is being used for AAD only (no data to + * encrypt or decrypt) then \p mode can be set to any value. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param nonce The nonce/IV to use for the message. + * This must be a readable buffer of length \c 12 Bytes. + * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or + * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ); + +/** + * \brief This function feeds additional data to be authenticated + * into an ongoing ChaCha20-Poly1305 operation. + * + * The Additional Authenticated Data (AAD), also called + * Associated Data (AD) is only authenticated but not + * encrypted nor included in the encrypted output. It is + * usually transmitted separately from the ciphertext or + * computed locally by each party. + * + * \note This function is called before data is encrypted/decrypted. + * I.e. call this function to process the AAD before calling + * \c mbedtls_chachapoly_update(). + * + * You may call this function multiple times to process + * an arbitrary amount of AAD. It is permitted to call + * this function 0 times, if no AAD is used. + * + * This function cannot be called any more if data has + * been processed by \c mbedtls_chachapoly_update(), + * or if the context has been finished. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param aad_len The length in Bytes of the AAD. The length has no + * restrictions. + * \param aad Buffer containing the AAD. + * This pointer can be \c NULL if `aad_len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p aad are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operations has not been started or has been + * finished, or if the AAD has been finished. + */ +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief Thus function feeds data to be encrypted or decrypted + * into an on-going ChaCha20-Poly1305 + * operation. + * + * The direction (encryption or decryption) depends on the + * mode that was given when calling + * \c mbedtls_chachapoly_starts(). + * + * You may call this function multiple times to process + * an arbitrary amount of data. It is permitted to call + * this function 0 times, if no data is to be encrypted + * or decrypted. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param len The length (in bytes) of the data to encrypt or decrypt. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `len == 0`. + * \param output The buffer to where the encrypted or decrypted data is + * written. This must be able to hold \p len bytes. + * This pointer can be \c NULL if `len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finished the ChaCha20-Poly1305 operation and + * generates the MAC (authentication tag). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated encryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * This must be initialized. + * \param length The length (in bytes) of the data to encrypt or decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated + * data (AAD). This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the encrypted or decrypted data + * is written. This pointer can be \c NULL if `ilen == 0`. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC + * is written. This must not be \c NULL. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated decryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in Bytes) of the data to decrypt. + * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param tag The buffer holding the authentication tag. + * This must be a readable buffer of length \c 16 Bytes. + * \param input The buffer containing the data to decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the decrypted data is written. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED + * if the data was not authentic. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20-Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chachapoly_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHAPOLY_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h new file mode 100644 index 0000000..be5c548 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h @@ -0,0 +1,936 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.py. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif + +#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C) +#error "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !( defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) ) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( defined(MBEDTLS_USE_PSA_CRYPTO) || \ + defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ + defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ + defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ + defined(MBEDTLS_ECP_INTERNAL_ALT) || \ + defined(MBEDTLS_ECP_ALT) ) +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ! defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +#error "MBEDTLS_ECP_RESTARTABLE defined, but not MBEDTLS_ECDH_LEGACY_CONTEXT" +#endif + +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) && \ + defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +#error "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but MBEDTLS_ECDH_LEGACY_CONTEXT not disabled" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && !( \ + defined(MBEDTLS_ECP_ALT) || \ + defined(MBEDTLS_CTR_DRBG_C) || \ + defined(MBEDTLS_HMAC_DRBG_C) || \ + defined(MBEDTLS_ECP_NO_INTERNAL_RNG)) +#error "MBEDTLS_ECP_C requires a DRBG module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS5_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_PKCS5_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define MBEDTLS_HAS_MEMSAN +#endif +#endif +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) +#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" +#endif +#undef MBEDTLS_HAS_MEMSAN + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_CCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) +#error "MBEDTLS_CCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CCM_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_CCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_CHACHA20_C) +#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_POLY1305_C) +#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ + ( !defined(MBEDTLS_SHA256_C) && \ + !defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA1_C) ) +#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_PKCS11_C */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) && \ + !( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \ + defined(MBEDTLS_ENTROPY_C) ) || \ + defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) ) +#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \ + defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) ) +#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + ! defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + defined(MBEDTLS_ENTROPY_NV_SEED) ) +#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG" +#endif + +#if defined(MBEDTLS_PSA_ITS_FILE_C) && \ + !defined(MBEDTLS_FS_IO) +#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO." +#endif + +#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) && \ + !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_ECDSA_C) +#error "MBEDTLS_PK_C in configuration with MBEDTLS_USE_PSA_CRYPTO and \ + MBEDTLS_ECDSA_C requires MBEDTLS_PK_WRITE_C to be defined." +#endif + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V15) && \ + !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_C, MBEDTLS_RSA_C and MBEDTLS_PKCS1_V15 defined, \ + but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SHA512_NO_SHA384) && !defined(MBEDTLS_SHA512_C) +#error "MBEDTLS_SHA512_NO_SHA384 defined without MBEDTLS_SHA512_C" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) && ( !defined(MBEDTLS_HKDF_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL defined, but not all prerequisites" +#endif + +#if (defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ + !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) +#error "One or more versions of the TLS protocol are enabled " \ + "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \ + MBEDTLS_SSL_CID_IN_LEN_MAX > 255 +#error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \ + MBEDTLS_SSL_CID_OUT_LEN_MAX > 255 +#error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ + !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) +#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CERTS_C) && !defined(MBEDTLS_X509_USE_C) +#error "MBEDTLS_CERTS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" +#endif +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" +#elif defined(MBEDTLS_DEPRECATED_WARNING) +#warning "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && ( !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ) +#error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites" +#endif + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in empty translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h new file mode 100644 index 0000000..03e1639 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h @@ -0,0 +1,1127 @@ +/** + * \file cipher.h + * + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/** The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 +/** Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 +/** Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 +/** Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 +/** Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 +/** The context is invalid. For example, because it was freed. */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 + +/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** Cipher hardware accelerator failed. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported cipher types. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ + MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ +} mbedtls_cipher_id_t; + +/** + * \brief Supported {cipher type, cipher mode} pairs. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ + MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ + MBEDTLS_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */ + MBEDTLS_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ + MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */ +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ + MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */ + MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */ +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined + * in ssl_internal.h. */ +#define MBEDTLS_MAX_IV_LENGTH 16 + +/** Maximum block size of any cipher, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in ssl_internal.h. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** Maximum key length, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * For now, only check whether XTS is enabled which uses 64 Byte keys, + * and use 32 Bytes as an upper bound for the maximum key length otherwise. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in ssl_internal.h, which however deliberately ignores the case of XTS + * since the latter isn't used in SSL/TLS. */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +#define MBEDTLS_MAX_KEY_LENGTH 64 +#else +#define MBEDTLS_MAX_KEY_LENGTH 32 +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + */ +typedef struct mbedtls_cipher_info_t +{ + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t type; + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t mode; + + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int key_bitlen; + + /** Name of the cipher. */ + const char * name; + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int iv_size; + + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ + int flags; + + /** The block size, in Bytes. */ + unsigned int block_size; + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct mbedtls_cipher_context_t +{ + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use. */ + int key_bitlen; + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t iv_size; + + /** The cipher-specific context. */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *cmac_ctx; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /** Indicates whether the cipher operations should be performed + * by Mbed TLS' own crypto library or an external implementation + * of the PSA Crypto API. + * This is unset if the cipher context was established through + * mbedtls_cipher_setup(), and set if it was established through + * mbedtls_cipher_setup_psa(). + */ + unsigned char psa_enabled; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +} mbedtls_cipher_context_t; + +/** + * \brief This function retrieves the list of ciphers supported + * by the generic cipher module. + * + * For any cipher identifier in the returned list, you can + * obtain the corresponding generic cipher information structure + * via mbedtls_cipher_info_from_type(), which can then be used + * to prepare a cipher context via mbedtls_cipher_setup(). + * + * + * \return A statically-allocated array of cipher identifiers + * of type cipher_type_t. The last entry is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. This must not be + * \c NULL. + * + * \return The cipher information structure associated with the + * given \p cipher_name. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief This function initializes a \p cipher_context as NONE. + * + * \param ctx The context to be initialized. This must not be \c NULL. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + * + * \param ctx The context to be freed. If this is \c NULL, the + * function has no effect, otherwise this must point to an + * initialized context. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + +/** + * \brief Clone the state of an cipher context + * + * \note The two contexts must have been setup to the same type + * (cloning from AES to DES make no sense). + * + * \param dst The destination context + * \param src The context to be cloned + * + * \return \c 0 on success, + * \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure. + */ +int mbedtls_cipher_clone( mbedtls_cipher_context_t *dst, + const mbedtls_cipher_context_t *src ); + +/** + * \brief This function initializes a cipher context for + * use with the given cipher primitive. + * + * \param ctx The context to initialize. This must be initialized. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief This function initializes a cipher context for + * PSA-based use with the given cipher primitive. + * + * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA. + * + * \param ctx The context to initialize. May not be \c NULL. + * \param cipher_info The cipher to use. + * \param taglen For AEAD ciphers, the length in bytes of the + * authentication tag to use. Subsequent uses of + * mbedtls_cipher_auth_encrypt() or + * mbedtls_cipher_auth_decrypt() must provide + * the same tag length. + * For non-AEAD ciphers, the value must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + */ +int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief setup the cipher info structure. + * + * \param ctx cipher's context. Must have been initialised. + * \param cipher_info cipher to use. + * + * \return 0 on success, + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure + */ +int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The block size of the underlying cipher. + * \return \c 0 if \p ctx has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. + */ +static inline int mbedtls_cipher_get_iv_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_CIPHER_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_KEY_LENGTH_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_OPERATION_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param key The key to use. This must be a readable buffer of at + * least \p key_bitlen Bits. + * \param key_bitlen The key length to use, in Bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param mode The padding mode. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This + * must be a readable buffer of at least \p iv_len Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ); + +/** + * \brief This function resets the cipher state. + * + * \param ctx The generic cipher context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called exactly once, after + * mbedtls_cipher_reset(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param ad The additional data to use. This must be a readable + * buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad in Bytes. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \note If the underlying cipher is used in GCM mode, all calls + * to this function, except for the last one before + * mbedtls_cipher_finish(), must have \p ilen as a + * multiple of the block size of the cipher. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, + size_t ilen, unsigned char *output, + size_t *olen ); + +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least \p block_size Bytes. + * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized, + * bound to a key, and have just completed a cipher + * operation through mbedtls_cipher_finish() the tag for + * which should be written. + * \param tag The buffer to write the tag to. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param tag The buffer holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. This must be initialized. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_WARNING */ +/** + * \brief The generic authenticated encryption (AEAD) function. + * + * \deprecated Superseded by mbedtls_cipher_auth_encrypt_ext(). + * + * \note This function only supports AEAD algorithms, not key + * wrapping algorithms such as NIST_KW; for this, see + * mbedtls_cipher_auth_encrypt_ext(). + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key associated with an AEAD algorithm. + * \param iv The nonce to use. This must be a readable buffer of + * at least \p iv_len Bytes and must not be \c NULL. + * \param iv_len The length of the nonce. This must satisfy the + * constraints imposed by the AEAD cipher used. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes, and may + * be \c NULL is \p ad_len is \c 0. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes, and may be + * \c NULL if \p ilen is \c 0. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be a + * writable buffer of at least \p ilen Bytes, and must + * not be \c NULL. + * \param olen This will be filled with the actual number of Bytes + * written to the \p output buffer. This must point to a + * writable object of type \c size_t. + * \param tag The buffer for the authentication tag. This must be a + * writable buffer of at least \p tag_len Bytes. See note + * below regarding restrictions with PSA-based contexts. + * \param tag_len The desired length of the authentication tag. This + * must match the constraints imposed by the AEAD cipher + * used, and in particular must not be \c 0. + * + * \note If the context is based on PSA (that is, it was set up + * with mbedtls_cipher_setup_psa()), then it is required + * that \c tag == output + ilen. That is, the tag must be + * appended to the ciphertext as recommended by RFC 5116. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) + MBEDTLS_DEPRECATED; + +/** + * \brief The generic authenticated decryption (AEAD) function. + * + * \deprecated Superseded by mbedtls_cipher_auth_decrypt_ext(). + * + * \note This function only supports AEAD algorithms, not key + * wrapping algorithms such as NIST_KW; for this, see + * mbedtls_cipher_auth_decrypt_ext(). + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key associated with an AEAD algorithm. + * \param iv The nonce to use. This must be a readable buffer of + * at least \p iv_len Bytes and must not be \c NULL. + * \param iv_len The length of the nonce. This must satisfy the + * constraints imposed by the AEAD cipher used. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes, and may + * be \c NULL is \p ad_len is \c 0. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes, and may be + * \c NULL if \p ilen is \c 0. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be a + * writable buffer of at least \p ilen Bytes, and must + * not be \c NULL. + * \param olen This will be filled with the actual number of Bytes + * written to the \p output buffer. This must point to a + * writable object of type \c size_t. + * \param tag The buffer for the authentication tag. This must be a + * readable buffer of at least \p tag_len Bytes. See note + * below regarding restrictions with PSA-based contexts. + * \param tag_len The length of the authentication tag. This must match + * the constraints imposed by the AEAD cipher used, and in + * particular must not be \c 0. + * + * \note If the context is based on PSA (that is, it was set up + * with mbedtls_cipher_setup_psa()), then it is required + * that \c tag == input + len. That is, the tag must be + * appended to the ciphertext as recommended by RFC 5116. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) + MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) +/** + * \brief The authenticated encryption (AEAD/NIST_KW) function. + * + * \note For AEAD modes, the tag will be appended to the + * ciphertext, as recommended by RFC 5116. + * (NIST_KW doesn't have a separate tag.) + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key, with an AEAD algorithm or NIST_KW. + * \param iv The nonce to use. This must be a readable buffer of + * at least \p iv_len Bytes and may be \c NULL if \p + * iv_len is \c 0. + * \param iv_len The length of the nonce. For AEAD ciphers, this must + * satisfy the constraints imposed by the cipher used. + * For NIST_KW, this must be \c 0. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes, and may + * be \c NULL is \p ad_len is \c 0. + * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes, and may be + * \c NULL if \p ilen is \c 0. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be a + * writable buffer of at least \p output_len Bytes, and + * must not be \c NULL. + * \param output_len The length of the \p output buffer in Bytes. For AEAD + * ciphers, this must be at least \p ilen + \p tag_len. + * For NIST_KW, this must be at least \p ilen + 8 + * (rounded up to a multiple of 8 if KWP is used); + * \p ilen + 15 is always a safe value. + * \param olen This will be filled with the actual number of Bytes + * written to the \p output buffer. This must point to a + * writable object of type \c size_t. + * \param tag_len The desired length of the authentication tag. For AEAD + * ciphers, this must match the constraints imposed by + * the cipher used, and in particular must not be \c 0. + * For NIST_KW, this must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ); + +/** + * \brief The authenticated encryption (AEAD/NIST_KW) function. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \note For AEAD modes, the tag must be appended to the + * ciphertext, as recommended by RFC 5116. + * (NIST_KW doesn't have a separate tag.) + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key, with an AEAD algorithm or NIST_KW. + * \param iv The nonce to use. This must be a readable buffer of + * at least \p iv_len Bytes and may be \c NULL if \p + * iv_len is \c 0. + * \param iv_len The length of the nonce. For AEAD ciphers, this must + * satisfy the constraints imposed by the cipher used. + * For NIST_KW, this must be \c 0. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes, and may + * be \c NULL is \p ad_len is \c 0. + * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes, and may be + * \c NULL if \p ilen is \c 0. + * \param ilen The length of the input data. For AEAD ciphers this + * must be at least \p tag_len. For NIST_KW this must be + * at least \c 8. + * \param output The buffer for the output data. This must be a + * writable buffer of at least \p output_len Bytes, and + * may be \c NULL if \p output_len is \c 0. + * \param output_len The length of the \p output buffer in Bytes. For AEAD + * ciphers, this must be at least \p ilen - \p tag_len. + * For NIST_KW, this must be at least \p ilen - 8. + * \param olen This will be filled with the actual number of Bytes + * written to the \p output buffer. This must point to a + * writable object of type \c size_t. + * \param tag_len The actual length of the authentication tag. For AEAD + * ciphers, this must match the constraints imposed by + * the cipher used, and in particular must not be \c 0. + * For NIST_KW, this must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h new file mode 100644 index 0000000..d437b80 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cipher_internal.h @@ -0,0 +1,153 @@ +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Clone context **/ + void (*ctx_clone_func)( void *dst, const void *src ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +typedef enum +{ + MBEDTLS_CIPHER_PSA_KEY_UNSET = 0, + MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */ + /* use raw key material internally imported */ + /* as a volatile key, and which hence need */ + /* to destroy that key when the context is */ + /* freed. */ + MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */ + /* which use a key provided by the */ + /* user, and which hence will not be */ + /* destroyed when the context is freed. */ +} mbedtls_cipher_psa_key_ownership; + +typedef struct +{ + psa_algorithm_t alg; + psa_key_id_t slot; + mbedtls_cipher_psa_key_ownership slot_state; +} mbedtls_cipher_context_psa; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h new file mode 100644 index 0000000..85fe6a0 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h @@ -0,0 +1,260 @@ +/** + * \file cmac.h + * + * \brief This file contains CMAC definitions and functions. + * + * The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CMAC_H +#define MBEDTLS_CMAC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** CMAC hardware accelerator failed. */ +#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A + +#define MBEDTLS_AES_BLOCK_SIZE 16 +#define MBEDTLS_DES3_BLOCK_SIZE 8 + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ +#endif + +#if !defined(MBEDTLS_CMAC_ALT) + +/** + * The CMAC context structure. + */ +struct mbedtls_cmac_context_t +{ + /** The internal state of the CMAC algorithm. */ + unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Unprocessed data - either data that was not block aligned and is still + * pending processing, or the final block. */ + unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** The length of data pending processing. */ + size_t unprocessed_len; +}; + +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + +/** + * \brief Initialises and allocate CMAC context memory + * Must be called with an initialized cipher context. + * + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_cmac_setup(mbedtls_cipher_context_t *ctx); + +/** + * \brief This function starts a new CMAC computation + * by setting the CMAC key, and preparing to authenticate + * the input data. + * It must be called with an initialized cipher context. + * + * Once this function has completed, data can be supplied + * to the CMAC computation by calling + * mbedtls_cipher_cmac_update(). + * + * To start a CMAC computation using the same key as a previous + * CMAC computation, use mbedtls_cipher_cmac_finish(). + * + * \note When the CMAC implementation is supplied by an alternate + * implementation (through #MBEDTLS_CMAC_ALT), some ciphers + * may not be supported by that implementation, and thus + * return an error. Alternate implementations must support + * AES-128 and AES-256, and may support AES-192 and 3DES. + * + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. + * \param key The CMAC key. + * \param keybits The length of the CMAC key in bits. + * Must be supported by the cipher. + * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ); + +/** + * \brief This function feeds an input buffer into an ongoing CMAC + * computation. + * + * The CMAC computation must have previously been started + * by calling mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset(). + * + * Call this function as many times as needed to input the + * data to be authenticated. + * Once all of the required data has been input, + * call mbedtls_cipher_cmac_finish() to obtain the result + * of the CMAC operation. + * + * \param ctx The cipher context used for the CMAC operation. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes an ongoing CMAC operation, and + * writes the result to the output buffer. + * + * It should be followed either by + * mbedtls_cipher_cmac_reset(), which starts another CMAC + * operation with the same key, or mbedtls_cipher_free(), + * which clears the cipher context. + * + * \param ctx The cipher context used for the CMAC operation. + * \param output The output buffer for the CMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); + +/** + * \brief This function starts a new CMAC operation with the same + * key as the previous one. + * + * It should be called after finishing the previous CMAC + * operation with mbedtls_cipher_cmac_finish(). + * After calling this function, + * call mbedtls_cipher_cmac_update() to supply the new + * CMAC operation with data. + * + * \param ctx The cipher context used for the CMAC operation. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function calculates the full generic CMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The CMAC result is calculated as + * output = generic CMAC(cmac key, input buffer). + * + * \note When the CMAC implementation is supplied by an alternate + * implementation (through #MBEDTLS_CMAC_ALT), some ciphers + * may not be supported by that implementation, and thus + * return an error. Alternate implementations must support + * AES-128 and AES-256, and may support AES-192 and 3DES. + * + * \param cipher_info The cipher information. + * \param key The CMAC key. + * \param keylen The length of the CMAC key in bits. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the generic CMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_AES_C) +/** + * \brief This function implements the AES-CMAC-PRF-128 pseudorandom + * function, as defined in + * RFC-4615: The Advanced Encryption Standard-Cipher-based + * Message Authentication Code-Pseudo-Random Function-128 + * (AES-CMAC-PRF-128) Algorithm for the Internet Key + * Exchange Protocol (IKE). + * + * \param key The key to use. + * \param key_len The key length in Bytes. + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * \param output The buffer holding the generated 16 Bytes of + * pseudorandom output. + * + * \return \c 0 on success. + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, + const unsigned char *input, size_t in_len, + unsigned char output[16] ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +/** + * \brief The CMAC checkup routine. + * + * \note In case the CMAC routines are provided by an alternative + * implementation (i.e. #MBEDTLS_CMAC_ALT is defined), the + * checkup routine will succeed even if the implementation does + * not support the less widely used AES-192 or 3DES primitives. + * The self-test requires at least AES-128 and AES-256 to be + * supported by the underlying implementation. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_cmac_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h new file mode 100644 index 0000000..4017751 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/compat-1.3.h @@ -0,0 +1,2529 @@ +/** + * \file compat-1.3.h + * + * \brief Compatibility definitions for using mbed TLS with client code written + * for the PolarSSL naming conventions. + * + * \deprecated Use the new names directly instead + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Including compat-1.3.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT13_H +#define MBEDTLS_COMPAT13_H + +/* + * config.h options + */ +#if defined MBEDTLS_AESNI_C +#define POLARSSL_AESNI_C MBEDTLS_AESNI_C +#endif +#if defined MBEDTLS_AES_ALT +#define POLARSSL_AES_ALT MBEDTLS_AES_ALT +#endif +#if defined MBEDTLS_AES_C +#define POLARSSL_AES_C MBEDTLS_AES_C +#endif +#if defined MBEDTLS_AES_ROM_TABLES +#define POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES +#endif +#if defined MBEDTLS_ARC4_ALT +#define POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT +#endif +#if defined MBEDTLS_ARC4_C +#define POLARSSL_ARC4_C MBEDTLS_ARC4_C +#endif +#if defined MBEDTLS_ASN1_PARSE_C +#define POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C +#endif +#if defined MBEDTLS_ASN1_WRITE_C +#define POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C +#endif +#if defined MBEDTLS_BASE64_C +#define POLARSSL_BASE64_C MBEDTLS_BASE64_C +#endif +#if defined MBEDTLS_BIGNUM_C +#define POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C +#endif +#if defined MBEDTLS_BLOWFISH_ALT +#define POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT +#endif +#if defined MBEDTLS_BLOWFISH_C +#define POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C +#endif +#if defined MBEDTLS_CAMELLIA_ALT +#define POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT +#endif +#if defined MBEDTLS_CAMELLIA_C +#define POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C +#endif +#if defined MBEDTLS_CAMELLIA_SMALL_MEMORY +#define POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY +#endif +#if defined MBEDTLS_CCM_C +#define POLARSSL_CCM_C MBEDTLS_CCM_C +#endif +#if defined MBEDTLS_CERTS_C +#define POLARSSL_CERTS_C MBEDTLS_CERTS_C +#endif +#if defined MBEDTLS_CIPHER_C +#define POLARSSL_CIPHER_C MBEDTLS_CIPHER_C +#endif +#if defined MBEDTLS_CIPHER_MODE_CBC +#define POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC +#endif +#if defined MBEDTLS_CIPHER_MODE_CFB +#define POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB +#endif +#if defined MBEDTLS_CIPHER_MODE_CTR +#define POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR +#endif +#if defined MBEDTLS_CIPHER_NULL_CIPHER +#define POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER +#endif +#if defined MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#endif +#if defined MBEDTLS_CTR_DRBG_C +#define POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C +#endif +#if defined MBEDTLS_DEBUG_C +#define POLARSSL_DEBUG_C MBEDTLS_DEBUG_C +#endif +#if defined MBEDTLS_DEPRECATED_REMOVED +#define POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED +#endif +#if defined MBEDTLS_DEPRECATED_WARNING +#define POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING +#endif +#if defined MBEDTLS_DES_ALT +#define POLARSSL_DES_ALT MBEDTLS_DES_ALT +#endif +#if defined MBEDTLS_DES_C +#define POLARSSL_DES_C MBEDTLS_DES_C +#endif +#if defined MBEDTLS_DHM_C +#define POLARSSL_DHM_C MBEDTLS_DHM_C +#endif +#if defined MBEDTLS_ECDH_C +#define POLARSSL_ECDH_C MBEDTLS_ECDH_C +#endif +#if defined MBEDTLS_ECDSA_C +#define POLARSSL_ECDSA_C MBEDTLS_ECDSA_C +#endif +#if defined MBEDTLS_ECDSA_DETERMINISTIC +#define POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC +#endif +#if defined MBEDTLS_ECP_C +#define POLARSSL_ECP_C MBEDTLS_ECP_C +#endif +#if defined MBEDTLS_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP512R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED +#endif +#if defined MBEDTLS_ECP_FIXED_POINT_OPTIM +#define POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM +#endif +#if defined MBEDTLS_ECP_MAX_BITS +#define POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS +#endif +#if defined MBEDTLS_ECP_NIST_OPTIM +#define POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM +#endif +#if defined MBEDTLS_ECP_WINDOW_SIZE +#define POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE +#endif +#if defined MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#endif +#if defined MBEDTLS_ENTROPY_C +#define POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C +#endif +#if defined MBEDTLS_ENTROPY_FORCE_SHA256 +#define POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 +#endif +#if defined MBEDTLS_ERROR_C +#define POLARSSL_ERROR_C MBEDTLS_ERROR_C +#endif +#if defined MBEDTLS_ERROR_STRERROR_DUMMY +#define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY +#endif +#if defined MBEDTLS_FS_IO +#define POLARSSL_FS_IO MBEDTLS_FS_IO +#endif +#if defined MBEDTLS_GCM_C +#define POLARSSL_GCM_C MBEDTLS_GCM_C +#endif +#if defined MBEDTLS_GENPRIME +#define POLARSSL_GENPRIME MBEDTLS_GENPRIME +#endif +#if defined MBEDTLS_HAVEGE_C +#define POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C +#endif +#if defined MBEDTLS_HAVE_ASM +#define POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM +#endif +#if defined MBEDTLS_HAVE_SSE2 +#define POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 +#endif +#if defined MBEDTLS_HAVE_TIME +#define POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME +#endif +#if defined MBEDTLS_HMAC_DRBG_C +#define POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_INPUT +#define POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_REQUEST +#define POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#endif +#if defined MBEDTLS_MD2_ALT +#define POLARSSL_MD2_ALT MBEDTLS_MD2_ALT +#endif +#if defined MBEDTLS_MD2_C +#define POLARSSL_MD2_C MBEDTLS_MD2_C +#endif +#if defined MBEDTLS_MD2_PROCESS_ALT +#define POLARSSL_MD2_PROCESS_ALT MBEDTLS_MD2_PROCESS_ALT +#endif +#if defined MBEDTLS_MD4_ALT +#define POLARSSL_MD4_ALT MBEDTLS_MD4_ALT +#endif +#if defined MBEDTLS_MD4_C +#define POLARSSL_MD4_C MBEDTLS_MD4_C +#endif +#if defined MBEDTLS_MD4_PROCESS_ALT +#define POLARSSL_MD4_PROCESS_ALT MBEDTLS_MD4_PROCESS_ALT +#endif +#if defined MBEDTLS_MD5_ALT +#define POLARSSL_MD5_ALT MBEDTLS_MD5_ALT +#endif +#if defined MBEDTLS_MD5_C +#define POLARSSL_MD5_C MBEDTLS_MD5_C +#endif +#if defined MBEDTLS_MD5_PROCESS_ALT +#define POLARSSL_MD5_PROCESS_ALT MBEDTLS_MD5_PROCESS_ALT +#endif +#if defined MBEDTLS_MD_C +#define POLARSSL_MD_C MBEDTLS_MD_C +#endif +#if defined MBEDTLS_MEMORY_ALIGN_MULTIPLE +#define POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE +#endif +#if defined MBEDTLS_MEMORY_BACKTRACE +#define POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE +#endif +#if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C +#endif +#if defined MBEDTLS_MEMORY_DEBUG +#define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG +#endif +#if defined MBEDTLS_MPI_MAX_SIZE +#define POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif +#if defined MBEDTLS_MPI_WINDOW_SIZE +#define POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE +#endif +#if defined MBEDTLS_NET_C +#define POLARSSL_NET_C MBEDTLS_NET_C +#endif +#if defined MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#endif +#if defined MBEDTLS_NO_PLATFORM_ENTROPY +#define POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY +#endif +#if defined MBEDTLS_OID_C +#define POLARSSL_OID_C MBEDTLS_OID_C +#endif +#if defined MBEDTLS_PADLOCK_C +#define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C +#endif +#if defined MBEDTLS_PEM_PARSE_C +#define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C +#endif +#if defined MBEDTLS_PEM_WRITE_C +#define POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C +#endif +#if defined MBEDTLS_PKCS11_C +#define POLARSSL_PKCS11_C MBEDTLS_PKCS11_C +#endif +#if defined MBEDTLS_PKCS12_C +#define POLARSSL_PKCS12_C MBEDTLS_PKCS12_C +#endif +#if defined MBEDTLS_PKCS1_V15 +#define POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 +#endif +#if defined MBEDTLS_PKCS1_V21 +#define POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 +#endif +#if defined MBEDTLS_PKCS5_C +#define POLARSSL_PKCS5_C MBEDTLS_PKCS5_C +#endif +#if defined MBEDTLS_PK_C +#define POLARSSL_PK_C MBEDTLS_PK_C +#endif +#if defined MBEDTLS_PK_PARSE_C +#define POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C +#endif +#if defined MBEDTLS_PK_PARSE_EC_EXTENDED +#define POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED +#endif +#if defined MBEDTLS_PK_RSA_ALT_SUPPORT +#define POLARSSL_PK_RSA_ALT_SUPPORT MBEDTLS_PK_RSA_ALT_SUPPORT +#endif +#if defined MBEDTLS_PK_WRITE_C +#define POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C +#endif +#if defined MBEDTLS_PLATFORM_C +#define POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C +#endif +#if defined MBEDTLS_PLATFORM_EXIT_ALT +#define POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT +#endif +#if defined MBEDTLS_PLATFORM_EXIT_MACRO +#define POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_ALT +#define POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_MACRO +#define POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FREE_MACRO +#define POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO +#endif +#if defined MBEDTLS_PLATFORM_MEMORY +#define POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY +#endif +#if defined MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_ALT +#define POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_MACRO +#define POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_ALT +#define POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_MACRO +#define POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_STD_EXIT +#define POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT +#endif +#if defined MBEDTLS_PLATFORM_STD_FPRINTF +#define POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_FREE +#define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE +#endif +#if defined MBEDTLS_PLATFORM_STD_MEM_HDR +#define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#if defined MBEDTLS_PLATFORM_STD_PRINTF +#define POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_SNPRINTF +#define POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF +#endif +#if defined MBEDTLS_PSK_MAX_LEN +#define POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN +#endif +#if defined MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#endif +#if defined MBEDTLS_RIPEMD160_ALT +#define POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT +#endif +#if defined MBEDTLS_RIPEMD160_C +#define POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C +#endif +#if defined MBEDTLS_RIPEMD160_PROCESS_ALT +#define POLARSSL_RIPEMD160_PROCESS_ALT MBEDTLS_RIPEMD160_PROCESS_ALT +#endif +#if defined MBEDTLS_RSA_C +#define POLARSSL_RSA_C MBEDTLS_RSA_C +#endif +#if defined MBEDTLS_RSA_NO_CRT +#define POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT +#endif +#if defined MBEDTLS_SELF_TEST +#define POLARSSL_SELF_TEST MBEDTLS_SELF_TEST +#endif +#if defined MBEDTLS_SHA1_ALT +#define POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT +#endif +#if defined MBEDTLS_SHA1_C +#define POLARSSL_SHA1_C MBEDTLS_SHA1_C +#endif +#if defined MBEDTLS_SHA1_PROCESS_ALT +#define POLARSSL_SHA1_PROCESS_ALT MBEDTLS_SHA1_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA256_ALT +#define POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT +#endif +#if defined MBEDTLS_SHA256_C +#define POLARSSL_SHA256_C MBEDTLS_SHA256_C +#endif +#if defined MBEDTLS_SHA256_PROCESS_ALT +#define POLARSSL_SHA256_PROCESS_ALT MBEDTLS_SHA256_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA512_ALT +#define POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT +#endif +#if defined MBEDTLS_SHA512_C +#define POLARSSL_SHA512_C MBEDTLS_SHA512_C +#endif +#if defined MBEDTLS_SHA512_PROCESS_ALT +#define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT +#endif +#if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES +#endif +#if defined MBEDTLS_SSL_ALPN +#define POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN +#endif +#if defined MBEDTLS_SSL_CACHE_C +#define POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C +#endif +#if defined MBEDTLS_SSL_CBC_RECORD_SPLITTING +#define POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING +#endif +#if defined MBEDTLS_SSL_CLI_C +#define POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C +#endif +#if defined MBEDTLS_SSL_COOKIE_C +#define POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C +#endif +#if defined MBEDTLS_SSL_COOKIE_TIMEOUT +#define POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT +#endif +#if defined MBEDTLS_SSL_DEBUG_ALL +#define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL +#endif +#if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY +#endif +#if defined MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#define POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#endif +#if defined MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY +#endif +#if defined MBEDTLS_SSL_ENCRYPT_THEN_MAC +#define POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC +#endif +#if defined MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#define POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#endif +#if defined MBEDTLS_SSL_FALLBACK_SCSV +#define POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#endif +#if defined MBEDTLS_SSL_HW_RECORD_ACCEL +#define POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL +#endif +#if defined MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#endif +#if defined MBEDTLS_SSL_PROTO_DTLS +#define POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS +#endif +#if defined MBEDTLS_SSL_PROTO_SSL3 +#define POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1 +#define POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_1 +#define POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_2 +#define POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 +#endif +#if defined MBEDTLS_SSL_RENEGOTIATION +#define POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#endif +#if defined MBEDTLS_SSL_SERVER_NAME_INDICATION +#define POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif +#if defined MBEDTLS_SSL_SESSION_TICKETS +#define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS +#endif +#if defined MBEDTLS_SSL_SRV_C +#define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C +#endif +#if defined MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#endif +#if defined MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#endif +#if defined MBEDTLS_SSL_TLS_C +#define POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C +#endif +#if defined MBEDTLS_SSL_TRUNCATED_HMAC +#define POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC +#endif +#if defined MBEDTLS_THREADING_ALT +#define POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT +#endif +#if defined MBEDTLS_THREADING_C +#define POLARSSL_THREADING_C MBEDTLS_THREADING_C +#endif +#if defined MBEDTLS_THREADING_PTHREAD +#define POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD +#endif +#if defined MBEDTLS_TIMING_ALT +#define POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT +#endif +#if defined MBEDTLS_TIMING_C +#define POLARSSL_TIMING_C MBEDTLS_TIMING_C +#endif +#if defined MBEDTLS_VERSION_C +#define POLARSSL_VERSION_C MBEDTLS_VERSION_C +#endif +#if defined MBEDTLS_VERSION_FEATURES +#define POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES +#endif +#if defined MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#endif +#if defined MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#endif +#if defined MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CHECK_KEY_USAGE +#define POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CREATE_C +#define POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C +#endif +#if defined MBEDTLS_X509_CRL_PARSE_C +#define POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_PARSE_C +#define POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_WRITE_C +#define POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C +#endif +#if defined MBEDTLS_X509_CSR_PARSE_C +#define POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C +#endif +#if defined MBEDTLS_X509_CSR_WRITE_C +#define POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C +#endif +#if defined MBEDTLS_X509_MAX_INTERMEDIATE_CA +#define POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA +#endif +#if defined MBEDTLS_X509_RSASSA_PSS_SUPPORT +#define POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT +#endif +#if defined MBEDTLS_X509_USE_C +#define POLARSSL_X509_USE_C MBEDTLS_X509_USE_C +#endif +#if defined MBEDTLS_XTEA_ALT +#define POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT +#endif +#if defined MBEDTLS_XTEA_C +#define POLARSSL_XTEA_C MBEDTLS_XTEA_C +#endif +#if defined MBEDTLS_ZLIB_SUPPORT +#define POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT +#endif + +/* + * Misc names (macros, types, functions, enum constants...) + */ +#define AES_DECRYPT MBEDTLS_AES_DECRYPT +#define AES_ENCRYPT MBEDTLS_AES_ENCRYPT +#define ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING +#define ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING +#define ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN +#define ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD +#define ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED +#define ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC +#define ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME +#define ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING +#define ASN1_INTEGER MBEDTLS_ASN1_INTEGER +#define ASN1_NULL MBEDTLS_ASN1_NULL +#define ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING +#define ASN1_OID MBEDTLS_ASN1_OID +#define ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE +#define ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING +#define ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE +#define ASN1_SET MBEDTLS_ASN1_SET +#define ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING +#define ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING +#define ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME +#define ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING +#define BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH +#define BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED +#define BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE +#define BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING +#define BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED +#define BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER +#define BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED +#define BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY +#define BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED +#define BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE +#define BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED +#define BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE +#define BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT +#define BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT +#define BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS +#define BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS +#define BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS +#define CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT +#define CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT +#define COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE +#define CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE +#define CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN +#define CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS +#define CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE +#define CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT +#define CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +#define CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +#define CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF +#define CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON +#define CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL +#define CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN +#define DEPRECATED MBEDTLS_DEPRECATED +#define DES_DECRYPT MBEDTLS_DES_DECRYPT +#define DES_ENCRYPT MBEDTLS_DES_ENCRYPT +#define DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE +#define ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE +#define ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER +#define ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE +#define ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES +#define ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK +#define ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE +#define ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM +#define ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL +#define EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS +#define EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES +#define EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS +#define EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE +#define EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL +#define EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY +#define EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME +#define EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE +#define EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS +#define EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE +#define EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS +#define EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS +#define EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME +#define EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define GCM_DECRYPT MBEDTLS_GCM_DECRYPT +#define GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT +#define KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN +#define KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT +#define KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE +#define KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT +#define KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN +#define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT +#define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION +#define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 +#define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC +#define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS +#define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE +#define MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE +#define MPI_CHK MBEDTLS_MPI_CHK +#define NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP +#define NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP +#define NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL +#define NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA +#define NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING +#define NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA +#define NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED +#define NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA +#define NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT +#define NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER +#define OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 +#define OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE +#define OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD +#define OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG +#define OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 +#define OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE +#define OID_AT MBEDTLS_OID_AT +#define OID_AT_CN MBEDTLS_OID_AT_CN +#define OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY +#define OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER +#define OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER +#define OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME +#define OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS +#define OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY +#define OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION +#define OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT +#define OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS +#define OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE +#define OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM +#define OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER +#define OID_AT_STATE MBEDTLS_OID_AT_STATE +#define OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME +#define OID_AT_TITLE MBEDTLS_OID_AT_TITLE +#define OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER +#define OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER +#define OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS +#define OID_CERTICOM MBEDTLS_OID_CERTICOM +#define OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES +#define OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH +#define OID_CMP MBEDTLS_OID_CMP +#define OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING +#define OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US +#define OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS +#define OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER +#define OID_DES_CBC MBEDTLS_OID_DES_CBC +#define OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC +#define OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 +#define OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 +#define OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 +#define OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 +#define OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 +#define OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 +#define OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 +#define OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 +#define OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT +#define OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 +#define OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 +#define OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 +#define OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 +#define OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 +#define OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH +#define OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED +#define OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 +#define OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 +#define OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 +#define OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 +#define OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 +#define OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 +#define OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 +#define OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 +#define OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 +#define OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 +#define OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 +#define OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 +#define OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION +#define OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE +#define OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL +#define OID_GOV MBEDTLS_OID_GOV +#define OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 +#define OID_ID_CE MBEDTLS_OID_ID_CE +#define OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY +#define OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS +#define OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG +#define OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY +#define OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG +#define OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES +#define OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME +#define OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE +#define OID_KP MBEDTLS_OID_KP +#define OID_MGF1 MBEDTLS_OID_MGF1 +#define OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS +#define OID_NETSCAPE MBEDTLS_OID_NETSCAPE +#define OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL +#define OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL +#define OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL +#define OID_NS_CERT MBEDTLS_OID_NS_CERT +#define OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE +#define OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE +#define OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT +#define OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE +#define OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL +#define OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL +#define OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME +#define OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING +#define OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG +#define OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG +#define OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 +#define OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION +#define OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 +#define OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM +#define OID_ORG_DOD MBEDTLS_OID_ORG_DOD +#define OID_ORG_GOV MBEDTLS_OID_ORG_GOV +#define OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE +#define OID_ORG_OIW MBEDTLS_OID_ORG_OIW +#define OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY +#define OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST +#define OID_PKCS MBEDTLS_OID_PKCS +#define OID_PKCS1 MBEDTLS_OID_PKCS1 +#define OID_PKCS12 MBEDTLS_OID_PKCS12 +#define OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE +#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC +#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC +#define OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC +#define OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC +#define OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 +#define OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 +#define OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 +#define OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 +#define OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 +#define OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA +#define OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 +#define OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 +#define OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 +#define OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 +#define OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 +#define OID_PKCS5 MBEDTLS_OID_PKCS5 +#define OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 +#define OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC +#define OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC +#define OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC +#define OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC +#define OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC +#define OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC +#define OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 +#define OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 +#define OID_PKCS9 MBEDTLS_OID_PKCS9 +#define OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ +#define OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL +#define OID_PKIX MBEDTLS_OID_PKIX +#define OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS +#define OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS +#define OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD +#define OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS +#define OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY +#define OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS +#define OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH +#define OID_SIZE MBEDTLS_OID_SIZE +#define OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME +#define OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS +#define OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER +#define OID_TELETRUST MBEDTLS_OID_TELETRUST +#define OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING +#define PADLOCK_ACE MBEDTLS_PADLOCK_ACE +#define PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 +#define PADLOCK_PHE MBEDTLS_PADLOCK_PHE +#define PADLOCK_PMM MBEDTLS_PADLOCK_PMM +#define PADLOCK_RNG MBEDTLS_PADLOCK_RNG +#define PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV +#define PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY +#define PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY +#define PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT +#define PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT +#define PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT +#define PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT +#define POLARSSL_AESNI_AES MBEDTLS_AESNI_AES +#define POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL +#define POLARSSL_AESNI_H MBEDTLS_AESNI_H +#define POLARSSL_AES_H MBEDTLS_AES_H +#define POLARSSL_ARC4_H MBEDTLS_ARC4_H +#define POLARSSL_ASN1_H MBEDTLS_ASN1_H +#define POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H +#define POLARSSL_BASE64_H MBEDTLS_BASE64_H +#define POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H +#define POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H +#define POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H +#define POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H +#define POLARSSL_CCM_H MBEDTLS_CCM_H +#define POLARSSL_CERTS_H MBEDTLS_CERTS_H +#define POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H +#define POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS +#define POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG +#define POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK +#define POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC +#define POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM +#define POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 +#define POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR +#define POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB +#define POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM +#define POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC +#define POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM +#define POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 +#define POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR +#define POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB +#define POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM +#define POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC +#define POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM +#define POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 +#define POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR +#define POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB +#define POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM +#define POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 +#define POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC +#define POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 +#define POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR +#define POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC +#define POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM +#define POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR +#define POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM +#define POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC +#define POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM +#define POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR +#define POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB +#define POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM +#define POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC +#define POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM +#define POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR +#define POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB +#define POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM +#define POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC +#define POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB +#define POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC +#define POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB +#define POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC +#define POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB +#define POLARSSL_CIPHER_H MBEDTLS_CIPHER_H +#define POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES +#define POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES +#define POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 +#define POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH +#define POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA +#define POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES +#define POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE +#define POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL +#define POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD +#define POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM +#define POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING +#define POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE +#define POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL +#define POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN +#define POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN +#define POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H +#define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H +#define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H +#define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H +#define POLARSSL_DECRYPT MBEDTLS_DECRYPT +#define POLARSSL_DES_H MBEDTLS_DES_H +#define POLARSSL_DHM_H MBEDTLS_DHM_H +#define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G +#define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P +#define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G +#define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P +#define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G +#define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P +#define POLARSSL_ECDH_H MBEDTLS_ECDH_H +#define POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS +#define POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS +#define POLARSSL_ECDSA_H MBEDTLS_ECDSA_H +#define POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 +#define POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 +#define POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 +#define POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 +#define POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX +#define POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE +#define POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 +#define POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 +#define POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 +#define POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 +#define POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 +#define POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 +#define POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 +#define POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 +#define POLARSSL_ECP_H MBEDTLS_ECP_H +#define POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES +#define POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN +#define POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED +#define POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED +#define POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE +#define POLARSSL_ENCRYPT MBEDTLS_ENCRYPT +#define POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H +#define POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H +#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#define POLARSSL_ERROR_H MBEDTLS_ERROR_H +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH +#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL +#define POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA +#define POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH +#define POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED +#define POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER +#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED +#define POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT +#define POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED +#define POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED +#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA +#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED +#define POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING +#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA +#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED +#define POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR +#define POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT +#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED +#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED +#define POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED +#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED +#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL +#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY +#define POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED +#define POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED +#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH +#define POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED +#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR +#define POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES +#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED +#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED +#define POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT +#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED +#define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA +#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO +#define POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER +#define POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE +#define POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED +#define POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED +#define POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED +#define POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET +#define POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED +#define POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED +#define POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED +#define POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED +#define POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#define POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST +#define POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL +#define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED +#define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA +#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA +#define POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV +#define POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED +#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT +#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH +#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED +#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG +#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH +#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA +#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR +#define POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG +#define POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY +#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +#define POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION +#define POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED +#define POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED +#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH +#define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH +#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE +#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA +#define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE +#define POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED +#define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED +#define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED +#define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY +#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP +#define POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED +#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET +#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA +#define POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL +#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE +#define POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED +#define POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF +#define POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING +#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE +#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED +#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED +#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH +#define POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR +#define POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC +#define POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD +#define POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED +#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN +#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE +#define POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG +#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE +#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY +#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED +#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH +#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED +#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED +#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE +#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER +#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY +#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO +#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA +#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR +#define POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA +#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR +#define POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG +#define POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE +#define POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS +#define POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT +#define POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME +#define POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL +#define POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE +#define POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION +#define POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED +#define POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH +#define POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID +#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG +#define POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION +#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH +#define POLARSSL_GCM_H MBEDTLS_GCM_H +#define POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H +#define POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 +#define POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 +#define POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL +#define POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 +#define POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 +#define POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF +#define POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON +#define POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK +#define POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA +#define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE +#define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK +#define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA +#define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED +#define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES +#define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE +#define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 +#define POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE +#define POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH +#define POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH +#define POLARSSL_MD2_H MBEDTLS_MD2_H +#define POLARSSL_MD4_H MBEDTLS_MD4_H +#define POLARSSL_MD5_H MBEDTLS_MD5_H +#define POLARSSL_MD_H MBEDTLS_MD_H +#define POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE +#define POLARSSL_MD_MD2 MBEDTLS_MD_MD2 +#define POLARSSL_MD_MD4 MBEDTLS_MD_MD4 +#define POLARSSL_MD_MD5 MBEDTLS_MD_MD5 +#define POLARSSL_MD_NONE MBEDTLS_MD_NONE +#define POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 +#define POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 +#define POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 +#define POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 +#define POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 +#define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 +#define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H +#define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC +#define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM +#define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB +#define POLARSSL_MODE_CTR MBEDTLS_MODE_CTR +#define POLARSSL_MODE_ECB MBEDTLS_MODE_ECB +#define POLARSSL_MODE_GCM MBEDTLS_MODE_GCM +#define POLARSSL_MODE_NONE MBEDTLS_MODE_NONE +#define POLARSSL_MODE_OFB MBEDTLS_MODE_OFB +#define POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM +#define POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS +#define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 +#define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS +#define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE +#define POLARSSL_NET_H MBEDTLS_NET_SOCKETS_H +#define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG +#define POLARSSL_OID_H MBEDTLS_OID_H +#define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE +#define POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE +#define POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS +#define POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 +#define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS +#define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN +#define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H +#define POLARSSL_PEM_H MBEDTLS_PEM_H +#define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H +#define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H +#define POLARSSL_PKCS5_H MBEDTLS_PKCS5_H +#define POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP +#define POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS +#define POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI +#define POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE +#define POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA +#define POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY +#define POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH +#define POLARSSL_PK_H MBEDTLS_PK_H +#define POLARSSL_PK_NONE MBEDTLS_PK_NONE +#define POLARSSL_PK_RSA MBEDTLS_PK_RSA +#define POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS +#define POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT +#define POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H +#define POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H +#define POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE +#define POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H +#define POLARSSL_RSA_H MBEDTLS_RSA_H +#define POLARSSL_SHA1_H MBEDTLS_SHA1_H +#define POLARSSL_SHA256_H MBEDTLS_SHA256_H +#define POLARSSL_SHA512_H MBEDTLS_SHA512_H +#define POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H +#define POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H +#define POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H +#define POLARSSL_SSL_H MBEDTLS_SSL_H +#define POLARSSL_THREADING_H MBEDTLS_THREADING_H +#define POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL +#define POLARSSL_TIMING_H MBEDTLS_TIMING_H +#define POLARSSL_VERSION_H MBEDTLS_VERSION_H +#define POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR +#define POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR +#define POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER +#define POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH +#define POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING +#define POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL +#define POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H +#define POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H +#define POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H +#define POLARSSL_X509_H MBEDTLS_X509_H +#define POLARSSL_XTEA_H MBEDTLS_XTEA_H +#define RSA_CRYPT MBEDTLS_RSA_CRYPT +#define RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 +#define RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 +#define RSA_PRIVATE MBEDTLS_RSA_PRIVATE +#define RSA_PUBLIC MBEDTLS_RSA_PUBLIC +#define RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY +#define RSA_SIGN MBEDTLS_RSA_SIGN +#define SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL +#define SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING +#define SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED +#define SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT +#define SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC +#define SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED +#define SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED +#define SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN +#define SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY +#define SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE +#define SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED +#define SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR +#define SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER +#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY +#define SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR +#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL +#define SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT +#define SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION +#define SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION +#define SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE +#define SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY +#define SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME +#define SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT +#define SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT +#define SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED +#define SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED +#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED +#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED +#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED +#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \ + ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) +#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES +#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT +#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED +#define SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED +#define SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST +#define SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY +#define SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN +#define SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN +#define SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND +#define SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND +#define SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES +#define SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE +#define SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC +#define SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED +#define SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO +#define SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE +#define SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD +#define SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE +#define SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL +#define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +#define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +#define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +#define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +#define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +#define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET +#define SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME +#define SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX +#define SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN +#define SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO +#define SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED +#define SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED +#define SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED +#define SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED +#define SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#define SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS +#define SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER +#define SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP +#define SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 +#define SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE +#define SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 +#define SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 +#define SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 +#define SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 +#define SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 +#define SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST +#define SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE +#define SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST +#define SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY +#define SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO +#define SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE +#define SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED +#define SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST +#define SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST +#define SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET +#define SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO +#define SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE +#define SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE +#define SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE +#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT +#define SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK +#define SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK +#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER +#define SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION +#define SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE +#define SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION +#define SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION +#define SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD +#define SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 +#define SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 +#define SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 +#define SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 +#define SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 +#define SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID +#define SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION +#define SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION +#define SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 +#define SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 +#define SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 +#define SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 +#define SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION +#define SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION +#define SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT +#define SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA +#define SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC +#define SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE +#define SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD +#define SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#define SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE +#define SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED +#define SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED +#define SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING +#define SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT +#define SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED +#define SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING +#define SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING +#define SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING +#define SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION +#define SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE +#define SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC +#define SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED +#define SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO +#define SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE +#define SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT +#define SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE +#define SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET +#define SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED +#define SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON +#define SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA +#define SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA +#define SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM +#define SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM +#define SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN +#define SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED +#define SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED +#define SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN +#define SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE +#define SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL +#define SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM +#define TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 +#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM +#define TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 +#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA +#define TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 +#define TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 +#define TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA +#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA +#define TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 +#define TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 +#define TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA +#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA +#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA +#define TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA +#define TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN +#define TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC +#define TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET +#define TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH +#define TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO +#define TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME +#define TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME +#define TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET +#define TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES +#define TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS +#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT +#define TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM +#define TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 +#define TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA +#define TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM +#define TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 +#define TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA +#define TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 +#define TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 +#define TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA +#define TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 +#define TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 +#define TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM +#define TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 +#define TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA +#define TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM +#define TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 +#define TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA +#define TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 +#define TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA +#define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 +#define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 +#define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA +#define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 +#define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 +#define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 +#define X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER +#define X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM +#define X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE +#define X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN +#define X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN +#define XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT +#define XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT +#define _asn1_bitstring mbedtls_asn1_bitstring +#define _asn1_buf mbedtls_asn1_buf +#define _asn1_named_data mbedtls_asn1_named_data +#define _asn1_sequence mbedtls_asn1_sequence +#define _ssl_cache_context mbedtls_ssl_cache_context +#define _ssl_cache_entry mbedtls_ssl_cache_entry +#define _ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define _ssl_context mbedtls_ssl_context +#define _ssl_flight_item mbedtls_ssl_flight_item +#define _ssl_handshake_params mbedtls_ssl_handshake_params +#define _ssl_key_cert mbedtls_ssl_key_cert +#define _ssl_premaster_secret mbedtls_ssl_premaster_secret +#define _ssl_session mbedtls_ssl_session +#define _ssl_transform mbedtls_ssl_transform +#define _x509_crl mbedtls_x509_crl +#define _x509_crl_entry mbedtls_x509_crl_entry +#define _x509_crt mbedtls_x509_crt +#define _x509_csr mbedtls_x509_csr +#define _x509_time mbedtls_x509_time +#define _x509write_cert mbedtls_x509write_cert +#define _x509write_csr mbedtls_x509write_csr +#define aes_context mbedtls_aes_context +#define aes_crypt_cbc mbedtls_aes_crypt_cbc +#define aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 +#define aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 +#define aes_crypt_ctr mbedtls_aes_crypt_ctr +#define aes_crypt_ecb mbedtls_aes_crypt_ecb +#define aes_free mbedtls_aes_free +#define aes_init mbedtls_aes_init +#define aes_self_test mbedtls_aes_self_test +#define aes_setkey_dec mbedtls_aes_setkey_dec +#define aes_setkey_enc mbedtls_aes_setkey_enc +#define aesni_crypt_ecb mbedtls_aesni_crypt_ecb +#define aesni_gcm_mult mbedtls_aesni_gcm_mult +#define aesni_inverse_key mbedtls_aesni_inverse_key +#define aesni_setkey_enc mbedtls_aesni_setkey_enc +#define aesni_supports mbedtls_aesni_has_support +#define alarmed mbedtls_timing_alarmed +#define arc4_context mbedtls_arc4_context +#define arc4_crypt mbedtls_arc4_crypt +#define arc4_free mbedtls_arc4_free +#define arc4_init mbedtls_arc4_init +#define arc4_self_test mbedtls_arc4_self_test +#define arc4_setup mbedtls_arc4_setup +#define asn1_bitstring mbedtls_asn1_bitstring +#define asn1_buf mbedtls_asn1_buf +#define asn1_find_named_data mbedtls_asn1_find_named_data +#define asn1_free_named_data mbedtls_asn1_free_named_data +#define asn1_free_named_data_list mbedtls_asn1_free_named_data_list +#define asn1_get_alg mbedtls_asn1_get_alg +#define asn1_get_alg_null mbedtls_asn1_get_alg_null +#define asn1_get_bitstring mbedtls_asn1_get_bitstring +#define asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null +#define asn1_get_bool mbedtls_asn1_get_bool +#define asn1_get_int mbedtls_asn1_get_int +#define asn1_get_len mbedtls_asn1_get_len +#define asn1_get_mpi mbedtls_asn1_get_mpi +#define asn1_get_sequence_of mbedtls_asn1_get_sequence_of +#define asn1_get_tag mbedtls_asn1_get_tag +#define asn1_named_data mbedtls_asn1_named_data +#define asn1_sequence mbedtls_asn1_sequence +#define asn1_store_named_data mbedtls_asn1_store_named_data +#define asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier +#define asn1_write_bitstring mbedtls_asn1_write_bitstring +#define asn1_write_bool mbedtls_asn1_write_bool +#define asn1_write_ia5_string mbedtls_asn1_write_ia5_string +#define asn1_write_int mbedtls_asn1_write_int +#define asn1_write_len mbedtls_asn1_write_len +#define asn1_write_mpi mbedtls_asn1_write_mpi +#define asn1_write_null mbedtls_asn1_write_null +#define asn1_write_octet_string mbedtls_asn1_write_octet_string +#define asn1_write_oid mbedtls_asn1_write_oid +#define asn1_write_printable_string mbedtls_asn1_write_printable_string +#define asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer +#define asn1_write_tag mbedtls_asn1_write_tag +#define base64_decode mbedtls_base64_decode +#define base64_encode mbedtls_base64_encode +#define base64_self_test mbedtls_base64_self_test +#define blowfish_context mbedtls_blowfish_context +#define blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc +#define blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 +#define blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr +#define blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb +#define blowfish_free mbedtls_blowfish_free +#define blowfish_init mbedtls_blowfish_init +#define blowfish_setkey mbedtls_blowfish_setkey +#define camellia_context mbedtls_camellia_context +#define camellia_crypt_cbc mbedtls_camellia_crypt_cbc +#define camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 +#define camellia_crypt_ctr mbedtls_camellia_crypt_ctr +#define camellia_crypt_ecb mbedtls_camellia_crypt_ecb +#define camellia_free mbedtls_camellia_free +#define camellia_init mbedtls_camellia_init +#define camellia_self_test mbedtls_camellia_self_test +#define camellia_setkey_dec mbedtls_camellia_setkey_dec +#define camellia_setkey_enc mbedtls_camellia_setkey_enc +#define ccm_auth_decrypt mbedtls_ccm_auth_decrypt +#define ccm_context mbedtls_ccm_context +#define ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag +#define ccm_free mbedtls_ccm_free +#define ccm_init mbedtls_ccm_init +#define ccm_self_test mbedtls_ccm_self_test +#define cipher_auth_decrypt mbedtls_cipher_auth_decrypt +#define cipher_auth_encrypt mbedtls_cipher_auth_encrypt +#define cipher_base_t mbedtls_cipher_base_t +#define cipher_check_tag mbedtls_cipher_check_tag +#define cipher_context_t mbedtls_cipher_context_t +#define cipher_crypt mbedtls_cipher_crypt +#define cipher_definition_t mbedtls_cipher_definition_t +#define cipher_definitions mbedtls_cipher_definitions +#define cipher_finish mbedtls_cipher_finish +#define cipher_free mbedtls_cipher_free +#define cipher_get_block_size mbedtls_cipher_get_block_size +#define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode +#define cipher_get_iv_size mbedtls_cipher_get_iv_size +#define cipher_get_key_size mbedtls_cipher_get_key_bitlen +#define cipher_get_name mbedtls_cipher_get_name +#define cipher_get_operation mbedtls_cipher_get_operation +#define cipher_get_type mbedtls_cipher_get_type +#define cipher_id_t mbedtls_cipher_id_t +#define cipher_info_from_string mbedtls_cipher_info_from_string +#define cipher_info_from_type mbedtls_cipher_info_from_type +#define cipher_info_from_values mbedtls_cipher_info_from_values +#define cipher_info_t mbedtls_cipher_info_t +#define cipher_init mbedtls_cipher_init +#define cipher_init_ctx mbedtls_cipher_setup +#define cipher_list mbedtls_cipher_list +#define cipher_mode_t mbedtls_cipher_mode_t +#define cipher_padding_t mbedtls_cipher_padding_t +#define cipher_reset mbedtls_cipher_reset +#define cipher_set_iv mbedtls_cipher_set_iv +#define cipher_set_padding_mode mbedtls_cipher_set_padding_mode +#define cipher_setkey mbedtls_cipher_setkey +#define cipher_type_t mbedtls_cipher_type_t +#define cipher_update mbedtls_cipher_update +#define cipher_update_ad mbedtls_cipher_update_ad +#define cipher_write_tag mbedtls_cipher_write_tag +#define ctr_drbg_context mbedtls_ctr_drbg_context +#define ctr_drbg_free mbedtls_ctr_drbg_free +#define ctr_drbg_init mbedtls_ctr_drbg_init +#define ctr_drbg_random mbedtls_ctr_drbg_random +#define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add +#define ctr_drbg_reseed mbedtls_ctr_drbg_reseed +#define ctr_drbg_self_test mbedtls_ctr_drbg_self_test +#define ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len +#define ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance +#define ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval +#define ctr_drbg_update mbedtls_ctr_drbg_update +#define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file +#define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file +#define debug_print_buf mbedtls_debug_print_buf +#define debug_print_crt mbedtls_debug_print_crt +#define debug_print_ecp mbedtls_debug_print_ecp +#define debug_print_mpi mbedtls_debug_print_mpi +#define debug_print_msg mbedtls_debug_print_msg +#define debug_print_ret mbedtls_debug_print_ret +#define debug_set_threshold mbedtls_debug_set_threshold +#define des3_context mbedtls_des3_context +#define des3_crypt_cbc mbedtls_des3_crypt_cbc +#define des3_crypt_ecb mbedtls_des3_crypt_ecb +#define des3_free mbedtls_des3_free +#define des3_init mbedtls_des3_init +#define des3_set2key_dec mbedtls_des3_set2key_dec +#define des3_set2key_enc mbedtls_des3_set2key_enc +#define des3_set3key_dec mbedtls_des3_set3key_dec +#define des3_set3key_enc mbedtls_des3_set3key_enc +#define des_context mbedtls_des_context +#define des_crypt_cbc mbedtls_des_crypt_cbc +#define des_crypt_ecb mbedtls_des_crypt_ecb +#define des_free mbedtls_des_free +#define des_init mbedtls_des_init +#define des_key_check_key_parity mbedtls_des_key_check_key_parity +#define des_key_check_weak mbedtls_des_key_check_weak +#define des_key_set_parity mbedtls_des_key_set_parity +#define des_self_test mbedtls_des_self_test +#define des_setkey_dec mbedtls_des_setkey_dec +#define des_setkey_enc mbedtls_des_setkey_enc +#define dhm_calc_secret mbedtls_dhm_calc_secret +#define dhm_context mbedtls_dhm_context +#define dhm_free mbedtls_dhm_free +#define dhm_init mbedtls_dhm_init +#define dhm_make_params mbedtls_dhm_make_params +#define dhm_make_public mbedtls_dhm_make_public +#define dhm_parse_dhm mbedtls_dhm_parse_dhm +#define dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile +#define dhm_read_params mbedtls_dhm_read_params +#define dhm_read_public mbedtls_dhm_read_public +#define dhm_self_test mbedtls_dhm_self_test +#define ecdh_calc_secret mbedtls_ecdh_calc_secret +#define ecdh_compute_shared mbedtls_ecdh_compute_shared +#define ecdh_context mbedtls_ecdh_context +#define ecdh_free mbedtls_ecdh_free +#define ecdh_gen_public mbedtls_ecdh_gen_public +#define ecdh_get_params mbedtls_ecdh_get_params +#define ecdh_init mbedtls_ecdh_init +#define ecdh_make_params mbedtls_ecdh_make_params +#define ecdh_make_public mbedtls_ecdh_make_public +#define ecdh_read_params mbedtls_ecdh_read_params +#define ecdh_read_public mbedtls_ecdh_read_public +#define ecdh_side mbedtls_ecdh_side +#define ecdsa_context mbedtls_ecdsa_context +#define ecdsa_free mbedtls_ecdsa_free +#define ecdsa_from_keypair mbedtls_ecdsa_from_keypair +#define ecdsa_genkey mbedtls_ecdsa_genkey +#define ecdsa_info mbedtls_ecdsa_info +#define ecdsa_init mbedtls_ecdsa_init +#define ecdsa_read_signature mbedtls_ecdsa_read_signature +#define ecdsa_sign mbedtls_ecdsa_sign +#define ecdsa_sign_det mbedtls_ecdsa_sign_det +#define ecdsa_verify mbedtls_ecdsa_verify +#define ecdsa_write_signature mbedtls_ecdsa_write_signature +#define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det +#define eckey_info mbedtls_eckey_info +#define eckeydh_info mbedtls_eckeydh_info +#define ecp_check_privkey mbedtls_ecp_check_privkey +#define ecp_check_pub_priv mbedtls_ecp_check_pub_priv +#define ecp_check_pubkey mbedtls_ecp_check_pubkey +#define ecp_copy mbedtls_ecp_copy +#define ecp_curve_info mbedtls_ecp_curve_info +#define ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id +#define ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name +#define ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id +#define ecp_curve_list mbedtls_ecp_curve_list +#define ecp_gen_key mbedtls_ecp_gen_key +#define ecp_gen_keypair mbedtls_ecp_gen_keypair +#define ecp_group mbedtls_ecp_group +#define ecp_group_copy mbedtls_ecp_group_copy +#define ecp_group_free mbedtls_ecp_group_free +#define ecp_group_id mbedtls_ecp_group_id +#define ecp_group_init mbedtls_ecp_group_init +#define ecp_grp_id_list mbedtls_ecp_grp_id_list +#define ecp_is_zero mbedtls_ecp_is_zero +#define ecp_keypair mbedtls_ecp_keypair +#define ecp_keypair_free mbedtls_ecp_keypair_free +#define ecp_keypair_init mbedtls_ecp_keypair_init +#define ecp_mul mbedtls_ecp_mul +#define ecp_point mbedtls_ecp_point +#define ecp_point_free mbedtls_ecp_point_free +#define ecp_point_init mbedtls_ecp_point_init +#define ecp_point_read_binary mbedtls_ecp_point_read_binary +#define ecp_point_read_string mbedtls_ecp_point_read_string +#define ecp_point_write_binary mbedtls_ecp_point_write_binary +#define ecp_self_test mbedtls_ecp_self_test +#define ecp_set_zero mbedtls_ecp_set_zero +#define ecp_tls_read_group mbedtls_ecp_tls_read_group +#define ecp_tls_read_point mbedtls_ecp_tls_read_point +#define ecp_tls_write_group mbedtls_ecp_tls_write_group +#define ecp_tls_write_point mbedtls_ecp_tls_write_point +#define ecp_use_known_dp mbedtls_ecp_group_load +#define entropy_add_source mbedtls_entropy_add_source +#define entropy_context mbedtls_entropy_context +#define entropy_free mbedtls_entropy_free +#define entropy_func mbedtls_entropy_func +#define entropy_gather mbedtls_entropy_gather +#define entropy_init mbedtls_entropy_init +#define entropy_self_test mbedtls_entropy_self_test +#define entropy_update_manual mbedtls_entropy_update_manual +#define entropy_update_seed_file mbedtls_entropy_update_seed_file +#define entropy_write_seed_file mbedtls_entropy_write_seed_file +#define error_strerror mbedtls_strerror +#define f_source_ptr mbedtls_entropy_f_source_ptr +#define gcm_auth_decrypt mbedtls_gcm_auth_decrypt +#define gcm_context mbedtls_gcm_context +#define gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag +#define gcm_finish mbedtls_gcm_finish +#define gcm_free mbedtls_gcm_free +#define gcm_init mbedtls_gcm_init +#define gcm_self_test mbedtls_gcm_self_test +#define gcm_starts mbedtls_gcm_starts +#define gcm_update mbedtls_gcm_update +#define get_timer mbedtls_timing_get_timer +#define hardclock mbedtls_timing_hardclock +#define hardclock_poll mbedtls_hardclock_poll +#define havege_free mbedtls_havege_free +#define havege_init mbedtls_havege_init +#define havege_poll mbedtls_havege_poll +#define havege_random mbedtls_havege_random +#define havege_state mbedtls_havege_state +#define hmac_drbg_context mbedtls_hmac_drbg_context +#define hmac_drbg_free mbedtls_hmac_drbg_free +#define hmac_drbg_init mbedtls_hmac_drbg_init +#define hmac_drbg_random mbedtls_hmac_drbg_random +#define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add +#define hmac_drbg_reseed mbedtls_hmac_drbg_reseed +#define hmac_drbg_self_test mbedtls_hmac_drbg_self_test +#define hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len +#define hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance +#define hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval +#define hmac_drbg_update mbedtls_hmac_drbg_update +#define hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file +#define hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file +#define hr_time mbedtls_timing_hr_time +#define key_exchange_type_t mbedtls_key_exchange_type_t +#define md mbedtls_md +#define md2 mbedtls_md2 +#define md2_context mbedtls_md2_context +#define md2_finish mbedtls_md2_finish +#define md2_free mbedtls_md2_free +#define md2_info mbedtls_md2_info +#define md2_init mbedtls_md2_init +#define md2_process mbedtls_md2_process +#define md2_self_test mbedtls_md2_self_test +#define md2_starts mbedtls_md2_starts +#define md2_update mbedtls_md2_update +#define md4 mbedtls_md4 +#define md4_context mbedtls_md4_context +#define md4_finish mbedtls_md4_finish +#define md4_free mbedtls_md4_free +#define md4_info mbedtls_md4_info +#define md4_init mbedtls_md4_init +#define md4_process mbedtls_md4_process +#define md4_self_test mbedtls_md4_self_test +#define md4_starts mbedtls_md4_starts +#define md4_update mbedtls_md4_update +#define md5 mbedtls_md5 +#define md5_context mbedtls_md5_context +#define md5_finish mbedtls_md5_finish +#define md5_free mbedtls_md5_free +#define md5_info mbedtls_md5_info +#define md5_init mbedtls_md5_init +#define md5_process mbedtls_md5_process +#define md5_self_test mbedtls_md5_self_test +#define md5_starts mbedtls_md5_starts +#define md5_update mbedtls_md5_update +#define md_context_t mbedtls_md_context_t +#define md_file mbedtls_md_file +#define md_finish mbedtls_md_finish +#define md_free mbedtls_md_free +#define md_get_name mbedtls_md_get_name +#define md_get_size mbedtls_md_get_size +#define md_get_type mbedtls_md_get_type +#define md_hmac mbedtls_md_hmac +#define md_hmac_finish mbedtls_md_hmac_finish +#define md_hmac_reset mbedtls_md_hmac_reset +#define md_hmac_starts mbedtls_md_hmac_starts +#define md_hmac_update mbedtls_md_hmac_update +#define md_info_from_string mbedtls_md_info_from_string +#define md_info_from_type mbedtls_md_info_from_type +#define md_info_t mbedtls_md_info_t +#define md_init mbedtls_md_init +#define md_init_ctx mbedtls_md_init_ctx +#define md_list mbedtls_md_list +#define md_process mbedtls_md_process +#define md_starts mbedtls_md_starts +#define md_type_t mbedtls_md_type_t +#define md_update mbedtls_md_update +#define memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get +#define memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free +#define memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init +#define memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get +#define memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset +#define memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test +#define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status +#define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify +#define memory_buffer_set_verify mbedtls_memory_buffer_set_verify +#define mpi mbedtls_mpi +#define mpi_add_abs mbedtls_mpi_add_abs +#define mpi_add_int mbedtls_mpi_add_int +#define mpi_add_mpi mbedtls_mpi_add_mpi +#define mpi_cmp_abs mbedtls_mpi_cmp_abs +#define mpi_cmp_int mbedtls_mpi_cmp_int +#define mpi_cmp_mpi mbedtls_mpi_cmp_mpi +#define mpi_copy mbedtls_mpi_copy +#define mpi_div_int mbedtls_mpi_div_int +#define mpi_div_mpi mbedtls_mpi_div_mpi +#define mpi_exp_mod mbedtls_mpi_exp_mod +#define mpi_fill_random mbedtls_mpi_fill_random +#define mpi_free mbedtls_mpi_free +#define mpi_gcd mbedtls_mpi_gcd +#define mpi_gen_prime mbedtls_mpi_gen_prime +#define mpi_get_bit mbedtls_mpi_get_bit +#define mpi_grow mbedtls_mpi_grow +#define mpi_init mbedtls_mpi_init +#define mpi_inv_mod mbedtls_mpi_inv_mod +#define mpi_is_prime mbedtls_mpi_is_prime +#define mpi_lsb mbedtls_mpi_lsb +#define mpi_lset mbedtls_mpi_lset +#define mpi_mod_int mbedtls_mpi_mod_int +#define mpi_mod_mpi mbedtls_mpi_mod_mpi +#define mpi_msb mbedtls_mpi_bitlen +#define mpi_mul_int mbedtls_mpi_mul_int +#define mpi_mul_mpi mbedtls_mpi_mul_mpi +#define mpi_read_binary mbedtls_mpi_read_binary +#define mpi_read_file mbedtls_mpi_read_file +#define mpi_read_string mbedtls_mpi_read_string +#define mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign +#define mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap +#define mpi_self_test mbedtls_mpi_self_test +#define mpi_set_bit mbedtls_mpi_set_bit +#define mpi_shift_l mbedtls_mpi_shift_l +#define mpi_shift_r mbedtls_mpi_shift_r +#define mpi_shrink mbedtls_mpi_shrink +#define mpi_size mbedtls_mpi_size +#define mpi_sub_abs mbedtls_mpi_sub_abs +#define mpi_sub_int mbedtls_mpi_sub_int +#define mpi_sub_mpi mbedtls_mpi_sub_mpi +#define mpi_swap mbedtls_mpi_swap +#define mpi_write_binary mbedtls_mpi_write_binary +#define mpi_write_file mbedtls_mpi_write_file +#define mpi_write_string mbedtls_mpi_write_string +#define net_accept mbedtls_net_accept +#define net_bind mbedtls_net_bind +#define net_close mbedtls_net_free +#define net_connect mbedtls_net_connect +#define net_recv mbedtls_net_recv +#define net_recv_timeout mbedtls_net_recv_timeout +#define net_send mbedtls_net_send +#define net_set_block mbedtls_net_set_block +#define net_set_nonblock mbedtls_net_set_nonblock +#define net_usleep mbedtls_net_usleep +#define oid_descriptor_t mbedtls_oid_descriptor_t +#define oid_get_attr_short_name mbedtls_oid_get_attr_short_name +#define oid_get_cipher_alg mbedtls_oid_get_cipher_alg +#define oid_get_ec_grp mbedtls_oid_get_ec_grp +#define oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage +#define oid_get_md_alg mbedtls_oid_get_md_alg +#define oid_get_numeric_string mbedtls_oid_get_numeric_string +#define oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp +#define oid_get_oid_by_md mbedtls_oid_get_oid_by_md +#define oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg +#define oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg +#define oid_get_pk_alg mbedtls_oid_get_pk_alg +#define oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg +#define oid_get_sig_alg mbedtls_oid_get_sig_alg +#define oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc +#define oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type +#define operation_t mbedtls_operation_t +#define padlock_supports mbedtls_padlock_has_support +#define padlock_xcryptcbc mbedtls_padlock_xcryptcbc +#define padlock_xcryptecb mbedtls_padlock_xcryptecb +#define pem_context mbedtls_pem_context +#define pem_free mbedtls_pem_free +#define pem_init mbedtls_pem_init +#define pem_read_buffer mbedtls_pem_read_buffer +#define pem_write_buffer mbedtls_pem_write_buffer +#define pk_can_do mbedtls_pk_can_do +#define pk_check_pair mbedtls_pk_check_pair +#define pk_context mbedtls_pk_context +#define pk_debug mbedtls_pk_debug +#define pk_debug_item mbedtls_pk_debug_item +#define pk_debug_type mbedtls_pk_debug_type +#define pk_decrypt mbedtls_pk_decrypt +#define pk_ec mbedtls_pk_ec +#define pk_encrypt mbedtls_pk_encrypt +#define pk_free mbedtls_pk_free +#define pk_get_len mbedtls_pk_get_len +#define pk_get_name mbedtls_pk_get_name +#define pk_get_size mbedtls_pk_get_bitlen +#define pk_get_type mbedtls_pk_get_type +#define pk_info_from_type mbedtls_pk_info_from_type +#define pk_info_t mbedtls_pk_info_t +#define pk_init mbedtls_pk_init +#define pk_init_ctx mbedtls_pk_setup +#define pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt +#define pk_load_file mbedtls_pk_load_file +#define pk_parse_key mbedtls_pk_parse_key +#define pk_parse_keyfile mbedtls_pk_parse_keyfile +#define pk_parse_public_key mbedtls_pk_parse_public_key +#define pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile +#define pk_parse_subpubkey mbedtls_pk_parse_subpubkey +#define pk_rsa mbedtls_pk_rsa +#define pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func +#define pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func +#define pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func +#define pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options +#define pk_sign mbedtls_pk_sign +#define pk_type_t mbedtls_pk_type_t +#define pk_verify mbedtls_pk_verify +#define pk_verify_ext mbedtls_pk_verify_ext +#define pk_write_key_der mbedtls_pk_write_key_der +#define pk_write_key_pem mbedtls_pk_write_key_pem +#define pk_write_pubkey mbedtls_pk_write_pubkey +#define pk_write_pubkey_der mbedtls_pk_write_pubkey_der +#define pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem +#define pkcs11_context mbedtls_pkcs11_context +#define pkcs11_decrypt mbedtls_pkcs11_decrypt +#define pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free +#define pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind +#define pkcs11_sign mbedtls_pkcs11_sign +#define pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind +#define pkcs12_derivation mbedtls_pkcs12_derivation +#define pkcs12_pbe mbedtls_pkcs12_pbe +#define pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 +#define pkcs5_pbes2 mbedtls_pkcs5_pbes2 +#define pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac +#define pkcs5_self_test mbedtls_pkcs5_self_test +#define platform_entropy_poll mbedtls_platform_entropy_poll +#define platform_set_exit mbedtls_platform_set_exit +#define platform_set_fprintf mbedtls_platform_set_fprintf +#define platform_set_printf mbedtls_platform_set_printf +#define platform_set_snprintf mbedtls_platform_set_snprintf +#define polarssl_exit mbedtls_exit +#define polarssl_fprintf mbedtls_fprintf +#define polarssl_free mbedtls_free +#define polarssl_mutex_free mbedtls_mutex_free +#define polarssl_mutex_init mbedtls_mutex_init +#define polarssl_mutex_lock mbedtls_mutex_lock +#define polarssl_mutex_unlock mbedtls_mutex_unlock +#define polarssl_printf mbedtls_printf +#define polarssl_snprintf mbedtls_snprintf +#define polarssl_strerror mbedtls_strerror +#define ripemd160 mbedtls_ripemd160 +#define ripemd160_context mbedtls_ripemd160_context +#define ripemd160_finish mbedtls_ripemd160_finish +#define ripemd160_free mbedtls_ripemd160_free +#define ripemd160_info mbedtls_ripemd160_info +#define ripemd160_init mbedtls_ripemd160_init +#define ripemd160_process mbedtls_ripemd160_process +#define ripemd160_self_test mbedtls_ripemd160_self_test +#define ripemd160_starts mbedtls_ripemd160_starts +#define ripemd160_update mbedtls_ripemd160_update +#define rsa_alt_context mbedtls_rsa_alt_context +#define rsa_alt_info mbedtls_rsa_alt_info +#define rsa_check_privkey mbedtls_rsa_check_privkey +#define rsa_check_pub_priv mbedtls_rsa_check_pub_priv +#define rsa_check_pubkey mbedtls_rsa_check_pubkey +#define rsa_context mbedtls_rsa_context +#define rsa_copy mbedtls_rsa_copy +#define rsa_free mbedtls_rsa_free +#define rsa_gen_key mbedtls_rsa_gen_key +#define rsa_info mbedtls_rsa_info +#define rsa_init mbedtls_rsa_init +#define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt +#define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt +#define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign +#define rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify +#define rsa_private mbedtls_rsa_private +#define rsa_public mbedtls_rsa_public +#define rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt +#define rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt +#define rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt +#define rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt +#define rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign +#define rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify +#define rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign +#define rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify +#define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext +#define rsa_self_test mbedtls_rsa_self_test +#define rsa_set_padding mbedtls_rsa_set_padding +#define safer_memcmp mbedtls_ssl_safer_memcmp +#define set_alarm mbedtls_set_alarm +#define sha1 mbedtls_sha1 +#define sha1_context mbedtls_sha1_context +#define sha1_finish mbedtls_sha1_finish +#define sha1_free mbedtls_sha1_free +#define sha1_info mbedtls_sha1_info +#define sha1_init mbedtls_sha1_init +#define sha1_process mbedtls_sha1_process +#define sha1_self_test mbedtls_sha1_self_test +#define sha1_starts mbedtls_sha1_starts +#define sha1_update mbedtls_sha1_update +#define sha224_info mbedtls_sha224_info +#define sha256 mbedtls_sha256 +#define sha256_context mbedtls_sha256_context +#define sha256_finish mbedtls_sha256_finish +#define sha256_free mbedtls_sha256_free +#define sha256_info mbedtls_sha256_info +#define sha256_init mbedtls_sha256_init +#define sha256_process mbedtls_sha256_process +#define sha256_self_test mbedtls_sha256_self_test +#define sha256_starts mbedtls_sha256_starts +#define sha256_update mbedtls_sha256_update +#define sha384_info mbedtls_sha384_info +#define sha512 mbedtls_sha512 +#define sha512_context mbedtls_sha512_context +#define sha512_finish mbedtls_sha512_finish +#define sha512_free mbedtls_sha512_free +#define sha512_info mbedtls_sha512_info +#define sha512_init mbedtls_sha512_init +#define sha512_process mbedtls_sha512_process +#define sha512_self_test mbedtls_sha512_self_test +#define sha512_starts mbedtls_sha512_starts +#define sha512_update mbedtls_sha512_update +#define source_state mbedtls_entropy_source_state +#define ssl_cache_context mbedtls_ssl_cache_context +#define ssl_cache_entry mbedtls_ssl_cache_entry +#define ssl_cache_free mbedtls_ssl_cache_free +#define ssl_cache_get mbedtls_ssl_cache_get +#define ssl_cache_init mbedtls_ssl_cache_init +#define ssl_cache_set mbedtls_ssl_cache_set +#define ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries +#define ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout +#define ssl_check_cert_usage mbedtls_ssl_check_cert_usage +#define ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id +#define ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string +#define ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec +#define ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk +#define ssl_close_notify mbedtls_ssl_close_notify +#define ssl_context mbedtls_ssl_context +#define ssl_cookie_check mbedtls_ssl_cookie_check +#define ssl_cookie_check_t mbedtls_ssl_cookie_check_t +#define ssl_cookie_ctx mbedtls_ssl_cookie_ctx +#define ssl_cookie_free mbedtls_ssl_cookie_free +#define ssl_cookie_init mbedtls_ssl_cookie_init +#define ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout +#define ssl_cookie_setup mbedtls_ssl_cookie_setup +#define ssl_cookie_write mbedtls_ssl_cookie_write +#define ssl_cookie_write_t mbedtls_ssl_cookie_write_t +#define ssl_derive_keys mbedtls_ssl_derive_keys +#define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check +#define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update +#define ssl_fetch_input mbedtls_ssl_fetch_input +#define ssl_flight_item mbedtls_ssl_flight_item +#define ssl_flush_output mbedtls_ssl_flush_output +#define ssl_free mbedtls_ssl_free +#define ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol +#define ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail +#define ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite +#define ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id +#define ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name +#define ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg +#define ssl_get_peer_cert mbedtls_ssl_get_peer_cert +#define ssl_get_record_expansion mbedtls_ssl_get_record_expansion +#define ssl_get_session mbedtls_ssl_get_session +#define ssl_get_verify_result mbedtls_ssl_get_verify_result +#define ssl_get_version mbedtls_ssl_get_version +#define ssl_handshake mbedtls_ssl_handshake +#define ssl_handshake_client_step mbedtls_ssl_handshake_client_step +#define ssl_handshake_free mbedtls_ssl_handshake_free +#define ssl_handshake_params mbedtls_ssl_handshake_params +#define ssl_handshake_server_step mbedtls_ssl_handshake_server_step +#define ssl_handshake_step mbedtls_ssl_handshake_step +#define ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup +#define ssl_hdr_len mbedtls_ssl_hdr_len +#define ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len +#define ssl_hw_record_activate mbedtls_ssl_hw_record_activate +#define ssl_hw_record_finish mbedtls_ssl_hw_record_finish +#define ssl_hw_record_init mbedtls_ssl_hw_record_init +#define ssl_hw_record_read mbedtls_ssl_hw_record_read +#define ssl_hw_record_reset mbedtls_ssl_hw_record_reset +#define ssl_hw_record_write mbedtls_ssl_hw_record_write +#define ssl_init mbedtls_ssl_init +#define ssl_key_cert mbedtls_ssl_key_cert +#define ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation +#define ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites +#define ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash +#define ssl_optimize_checksum mbedtls_ssl_optimize_checksum +#define ssl_own_cert mbedtls_ssl_own_cert +#define ssl_own_key mbedtls_ssl_own_key +#define ssl_parse_certificate mbedtls_ssl_parse_certificate +#define ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec +#define ssl_parse_finished mbedtls_ssl_parse_finished +#define ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig +#define ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt +#define ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len +#define ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign +#define ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster +#define ssl_read mbedtls_ssl_read +#define ssl_read_record mbedtls_ssl_read_record +#define ssl_read_version mbedtls_ssl_read_version +#define ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed +#define ssl_renegotiate mbedtls_ssl_renegotiate +#define ssl_resend mbedtls_ssl_resend +#define ssl_reset_checksum mbedtls_ssl_reset_checksum +#define ssl_send_alert_message mbedtls_ssl_send_alert_message +#define ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure +#define ssl_send_flight_completed mbedtls_ssl_send_flight_completed +#define ssl_session mbedtls_ssl_session +#define ssl_session_free mbedtls_ssl_session_free +#define ssl_session_init mbedtls_ssl_session_init +#define ssl_session_reset mbedtls_ssl_session_reset +#define ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols +#define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support +#define ssl_set_authmode mbedtls_ssl_conf_authmode +#define ssl_set_bio mbedtls_ssl_set_bio +#define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain +#define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting +#define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites +#define ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version +#define ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id +#define ssl_set_curves mbedtls_ssl_conf_curves +#define ssl_set_dbg mbedtls_ssl_conf_dbg +#define ssl_set_dh_param mbedtls_ssl_conf_dh_param +#define ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx +#define ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay +#define ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit +#define ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies +#define ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac +#define ssl_set_endpoint mbedtls_ssl_conf_endpoint +#define ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret +#define ssl_set_fallback mbedtls_ssl_conf_fallback +#define ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout +#define ssl_set_hostname mbedtls_ssl_set_hostname +#define ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len +#define ssl_set_max_version mbedtls_ssl_conf_max_version +#define ssl_set_min_version mbedtls_ssl_conf_min_version +#define ssl_set_own_cert mbedtls_ssl_conf_own_cert +#define ssl_set_psk mbedtls_ssl_conf_psk +#define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb +#define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation +#define ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced +#define ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period +#define ssl_set_rng mbedtls_ssl_conf_rng +#define ssl_set_session mbedtls_ssl_set_session +#define ssl_set_session_cache mbedtls_ssl_conf_session_cache +#define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets +#define ssl_set_sni mbedtls_ssl_conf_sni +#define ssl_set_transport mbedtls_ssl_conf_transport +#define ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac +#define ssl_set_verify mbedtls_ssl_conf_verify +#define ssl_sig_from_pk mbedtls_ssl_sig_from_pk +#define ssl_states mbedtls_ssl_states +#define ssl_transform mbedtls_ssl_transform +#define ssl_transform_free mbedtls_ssl_transform_free +#define ssl_write mbedtls_ssl_write +#define ssl_write_certificate mbedtls_ssl_write_certificate +#define ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec +#define ssl_write_finished mbedtls_ssl_write_finished +#define ssl_write_record mbedtls_ssl_write_record +#define ssl_write_version mbedtls_ssl_write_version +#define supported_ciphers mbedtls_cipher_supported +#define t_sint mbedtls_mpi_sint +#define t_udbl mbedtls_t_udbl +#define t_uint mbedtls_mpi_uint +#define test_ca_crt mbedtls_test_ca_crt +#define test_ca_crt_ec mbedtls_test_ca_crt_ec +#define test_ca_crt_rsa mbedtls_test_ca_crt_rsa +#define test_ca_key mbedtls_test_ca_key +#define test_ca_key_ec mbedtls_test_ca_key_ec +#define test_ca_key_rsa mbedtls_test_ca_key_rsa +#define test_ca_list mbedtls_test_cas_pem +#define test_ca_pwd mbedtls_test_ca_pwd +#define test_ca_pwd_ec mbedtls_test_ca_pwd_ec +#define test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa +#define test_cli_crt mbedtls_test_cli_crt +#define test_cli_crt_ec mbedtls_test_cli_crt_ec +#define test_cli_crt_rsa mbedtls_test_cli_crt_rsa +#define test_cli_key mbedtls_test_cli_key +#define test_cli_key_ec mbedtls_test_cli_key_ec +#define test_cli_key_rsa mbedtls_test_cli_key_rsa +#define test_srv_crt mbedtls_test_srv_crt +#define test_srv_crt_ec mbedtls_test_srv_crt_ec +#define test_srv_crt_rsa mbedtls_test_srv_crt_rsa +#define test_srv_key mbedtls_test_srv_key +#define test_srv_key_ec mbedtls_test_srv_key_ec +#define test_srv_key_rsa mbedtls_test_srv_key_rsa +#define threading_mutex_t mbedtls_threading_mutex_t +#define threading_set_alt mbedtls_threading_set_alt +#define timing_self_test mbedtls_timing_self_test +#define version_check_feature mbedtls_version_check_feature +#define version_get_number mbedtls_version_get_number +#define version_get_string mbedtls_version_get_string +#define version_get_string_full mbedtls_version_get_string_full +#define x509_bitstring mbedtls_x509_bitstring +#define x509_buf mbedtls_x509_buf +#define x509_crl mbedtls_x509_crl +#define x509_crl_entry mbedtls_x509_crl_entry +#define x509_crl_free mbedtls_x509_crl_free +#define x509_crl_info mbedtls_x509_crl_info +#define x509_crl_init mbedtls_x509_crl_init +#define x509_crl_parse mbedtls_x509_crl_parse +#define x509_crl_parse_der mbedtls_x509_crl_parse_der +#define x509_crl_parse_file mbedtls_x509_crl_parse_file +#define x509_crt mbedtls_x509_crt +#define x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage +#define x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage +#define x509_crt_free mbedtls_x509_crt_free +#define x509_crt_info mbedtls_x509_crt_info +#define x509_crt_init mbedtls_x509_crt_init +#define x509_crt_parse mbedtls_x509_crt_parse +#define x509_crt_parse_der mbedtls_x509_crt_parse_der +#define x509_crt_parse_file mbedtls_x509_crt_parse_file +#define x509_crt_parse_path mbedtls_x509_crt_parse_path +#define x509_crt_revoked mbedtls_x509_crt_is_revoked +#define x509_crt_verify mbedtls_x509_crt_verify +#define x509_csr mbedtls_x509_csr +#define x509_csr_free mbedtls_x509_csr_free +#define x509_csr_info mbedtls_x509_csr_info +#define x509_csr_init mbedtls_x509_csr_init +#define x509_csr_parse mbedtls_x509_csr_parse +#define x509_csr_parse_der mbedtls_x509_csr_parse_der +#define x509_csr_parse_file mbedtls_x509_csr_parse_file +#define x509_dn_gets mbedtls_x509_dn_gets +#define x509_get_alg mbedtls_x509_get_alg +#define x509_get_alg_null mbedtls_x509_get_alg_null +#define x509_get_ext mbedtls_x509_get_ext +#define x509_get_name mbedtls_x509_get_name +#define x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params +#define x509_get_serial mbedtls_x509_get_serial +#define x509_get_sig mbedtls_x509_get_sig +#define x509_get_sig_alg mbedtls_x509_get_sig_alg +#define x509_get_time mbedtls_x509_get_time +#define x509_key_size_helper mbedtls_x509_key_size_helper +#define x509_name mbedtls_x509_name +#define x509_self_test mbedtls_x509_self_test +#define x509_sequence mbedtls_x509_sequence +#define x509_serial_gets mbedtls_x509_serial_gets +#define x509_set_extension mbedtls_x509_set_extension +#define x509_sig_alg_gets mbedtls_x509_sig_alg_gets +#define x509_string_to_names mbedtls_x509_string_to_names +#define x509_time mbedtls_x509_time +#define x509_time_expired mbedtls_x509_time_is_past +#define x509_time_future mbedtls_x509_time_is_future +#define x509_write_extensions mbedtls_x509_write_extensions +#define x509_write_names mbedtls_x509_write_names +#define x509_write_sig mbedtls_x509_write_sig +#define x509write_cert mbedtls_x509write_cert +#define x509write_crt_der mbedtls_x509write_crt_der +#define x509write_crt_free mbedtls_x509write_crt_free +#define x509write_crt_init mbedtls_x509write_crt_init +#define x509write_crt_pem mbedtls_x509write_crt_pem +#define x509write_crt_set_authority_key_identifier mbedtls_x509write_crt_set_authority_key_identifier +#define x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints +#define x509write_crt_set_extension mbedtls_x509write_crt_set_extension +#define x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key +#define x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name +#define x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage +#define x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg +#define x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type +#define x509write_crt_set_serial mbedtls_x509write_crt_set_serial +#define x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key +#define x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier +#define x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name +#define x509write_crt_set_validity mbedtls_x509write_crt_set_validity +#define x509write_crt_set_version mbedtls_x509write_crt_set_version +#define x509write_csr mbedtls_x509write_csr +#define x509write_csr_der mbedtls_x509write_csr_der +#define x509write_csr_free mbedtls_x509write_csr_free +#define x509write_csr_init mbedtls_x509write_csr_init +#define x509write_csr_pem mbedtls_x509write_csr_pem +#define x509write_csr_set_extension mbedtls_x509write_csr_set_extension +#define x509write_csr_set_key mbedtls_x509write_csr_set_key +#define x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage +#define x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg +#define x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type +#define x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name +#define xtea_context mbedtls_xtea_context +#define xtea_crypt_cbc mbedtls_xtea_crypt_cbc +#define xtea_crypt_ecb mbedtls_xtea_crypt_ecb +#define xtea_free mbedtls_xtea_free +#define xtea_init mbedtls_xtea_init +#define xtea_self_test mbedtls_xtea_self_test +#define xtea_setup mbedtls_xtea_setup + +#endif /* compat-1.3.h */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config.h new file mode 100644 index 0000000..5a4661c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/config.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited */ +#ifdef __KERNEL__ +#include +#else +#include +#endif diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h new file mode 100644 index 0000000..c5de57a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h @@ -0,0 +1,45 @@ +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CONSTANT_TIME_H +#define MBEDTLS_CONSTANT_TIME_H + +#include + + +/** Constant-time buffer comparison without branches. + * + * This is equivalent to the standard memcmp function, but is likely to be + * compiled to code using bitwise operation rather than a branch. + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param a Pointer to the first buffer. + * \param b Pointer to the second buffer. + * \param n The number of bytes to compare in the buffer. + * + * \return Zero if the content of the two buffer is the same, + * otherwise non-zero. + */ +int mbedtls_ct_memcmp( const void *a, + const void *b, + size_t n ); + +#endif /* MBEDTLS_CONSTANT_TIME_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h new file mode 100644 index 0000000..e68237a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h @@ -0,0 +1,611 @@ +/** + * \file ctr_drbg.h + * + * \brief This file contains definitions and functions for the + * CTR_DRBG pseudorandom generator. + * + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 + * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) + * as the underlying block cipher, with a derivation function. + * + * The security strength as defined in NIST SP 800-90A is + * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) + * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is + * kept at its default value (and not overridden in config.h) and that the + * DRBG instance is set up with default parameters. + * See the documentation of mbedtls_ctr_drbg_seed() for more + * information. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/** The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 +/** The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 +/** The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 +/** Read or write error in file. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +#define MBEDTLS_CTR_DRBG_KEYSIZE 16 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 16 bytes (128 bits) + * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled. + */ +#else +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 32 bytes (256 bits) + * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled. + */ +#endif + +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them using the compiler command + * line. + * \{ + */ + +/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN + * + * \brief The amount of entropy used per seed by default, in bytes. + */ +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +/** This is 48 bytes because the entropy module uses SHA-512 + * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled). + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 + +#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ + +/** This is 32 bytes because the entropy module uses SHA-256 + * (the SHA512 module is disabled or + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled). + */ +#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +/** \warning To achieve a 256-bit security strength, you must pass a nonce + * to mbedtls_ctr_drbg_seed(). + */ +#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer in bytes. */ +#endif + +/** \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** The default length of the nonce read from the entropy source. + * + * This is \c 0 because a single read from the entropy source is sufficient + * to include a nonce. + * See the documentation of mbedtls_ctr_drbg_seed() for more information. + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0 +#else +/** The default length of the nonce read from the entropy source. + * + * This is half of the default entropy length because a single read from + * the entropy source does not provide enough material to form a nonce. + * See the documentation of mbedtls_ctr_drbg_seed() for more information. + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2 +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct mbedtls_ctr_drbg_context +{ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. + * This is the number of requests that have + * been made since the last (re)seeding, + * minus one. + * Before the initial seeding, this field + * contains the amount of entropy in bytes + * to use as a nonce for the initial seeding, + * or -1 if no nonce length has been explicitly + * set (see mbedtls_ctr_drbg_set_nonce_len()). + */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation, in bytes. */ + int reseed_interval; /*!< The reseed interval. + * This is the maximum number of requests + * that can be made between reseedings. */ + + mbedtls_aes_context aes_ctx; /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *p_entropy; /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if f_entropy != NULL. + * This means that the mutex is initialized during the initial seeding + * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \note The reseed interval is + * #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default. + * You can override it by calling + * mbedtls_ctr_drbg_set_reseed_interval(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. + * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). + * + * The entropy nonce length is: + * - \c 0 if the entropy length is at least 3/2 times the entropy length, + * which guarantees that the security strength is the maximum permitted + * by the key size and entropy length according to NIST SP 800-90A §10.2.1; + * - Half the entropy length otherwise. + * You can override it by calling mbedtls_ctr_drbg_set_nonce_len(). + * With the default entropy length, the entropy nonce length is + * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN. + * + * You can provide a nonce and personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * See SP 800-90A §8.6.7 for more details about nonces. + * + * The _seed_material_ value passed to the derivation function in + * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2 + * is the concatenation of the following strings: + * - A string obtained by calling \p f_entropy function for the entropy + * length. + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0 +/** + * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string + * obtained by calling \p f_entropy function for the specified length. + */ +#else +/** + * - A string obtained by calling \p f_entropy function for the entropy nonce + * length. If the entropy nonce length is \c 0, this function does not + * make a second call to \p f_entropy. + */ +#endif +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * - The \p custom string. + * + * \note To achieve the nominal security strength permitted + * by CTR_DRBG, the entropy length must be: + * - at least 16 bytes for a 128-bit strength + * (maximum achievable strength when using AES-128); + * - at least 32 bytes for a 256-bit strength + * (maximum achievable strength when using AES-256). + * + * In addition, if you do not pass a nonce in \p custom, + * the sum of the entropy length + * and the entropy nonce length must be: + * - at least 24 bytes for a 128-bit strength + * (maximum achievable strength when using AES-128); + * - at least 48 bytes for a 256-bit strength + * (maximum achievable strength when using AES-256). + * + * \param ctx The CTR_DRBG context to seed. + * It must have been initialized with + * mbedtls_ctr_drbg_init(). + * After a successful call to mbedtls_ctr_drbg_seed(), + * you may not call mbedtls_ctr_drbg_seed() again on + * the same context unless you call + * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() + * again first. + * After a failed call to mbedtls_ctr_drbg_seed(), + * you must call mbedtls_ctr_drbg_free(). + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a buffer size + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add() + * or mbedtls_ctr_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \note The security strength of CTR_DRBG is bounded by the + * entropy length. Thus: + * - When using AES-256 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled, + * which is the default), + * \p len must be at least 32 (in bytes) + * to achieve a 256-bit strength. + * - When using AES-128 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled) + * \p len must be at least 16 (in bytes) + * to achieve a 128-bit strength. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * and at most the maximum length accepted by the + * entropy function that is set in the context. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the amount of entropy grabbed + * as a nonce for the initial seeding. + * + * Call this function before calling mbedtls_ctr_drbg_seed() to read + * a nonce from the entropy source during the initial seeding. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab for the nonce, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * and at most the maximum length accepted by the + * entropy function that is set in the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is + * more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + * if the initial seeding has already taken place. + */ +int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() + * or mbedtls_ctr_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be \c NULL. + * \param len The length of the additional data. + * This must be less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. This must not be + * \c NULL unless \p add_len is \c 0. + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * \param additional Additional data to update. Can be \c NULL, in which + * case the additional data is empty regardless of + * the value of \p add_len. + * \param add_len The length of the additional data + * if \p additional is not \c NULL. + * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT + * and less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function uses CTR_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \deprecated Superseded by mbedtls_ctr_drbg_update_ret() + * in 2.16.0. + * + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + */ +MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update( + mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h new file mode 100644 index 0000000..4fc4662 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/debug.h @@ -0,0 +1,311 @@ +/** + * \file debug.h + * + * \brief Functions for controlling and providing debug output from the library. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_DEBUG_H +#define MBEDTLS_DEBUG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ + mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ + MBEDTLS_DEBUG_STRIP_PARENS args ) + +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ + mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) + +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ + mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) + +#if defined(MBEDTLS_BIGNUM_C) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ + mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ + mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ + mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) +#endif + +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \ + mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr ) +#endif + +#else /* MBEDTLS_DEBUG_C */ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 ) + +#endif /* MBEDTLS_DEBUG_C */ + +/** + * \def MBEDTLS_PRINTF_ATTRIBUTE + * + * Mark a function as having printf attributes, and thus enable checking + * via -wFormat and other flags. This does nothing on builds with compilers + * that do not support the format attribute + * + * Module: library/debug.c + * Caller: + * + * This module provides debugging functions. + */ +#if defined(__has_attribute) +#if __has_attribute(format) +#if defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 +#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__ (gnu_printf, string_index, first_to_check))) +#else /* defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 */ +#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((format(printf, string_index, first_to_check))) +#endif +#else /* __has_attribute(format) */ +#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) +#endif /* __has_attribute(format) */ +#else /* defined(__has_attribute) */ +#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) +#endif + +/** + * \def MBEDTLS_PRINTF_SIZET + * + * MBEDTLS_PRINTF_xxx: Due to issues with older window compilers + * and MinGW we need to define the printf specifier for size_t + * and long long per platform. + * + * Module: library/debug.c + * Caller: + * + * This module provides debugging functions. + */ +#if (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) + #include + #define MBEDTLS_PRINTF_SIZET PRIuPTR + #define MBEDTLS_PRINTF_LONGLONG "I64d" +#else /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ + #define MBEDTLS_PRINTF_SIZET "zu" + #define MBEDTLS_PRINTF_LONGLONG "lld" +#endif /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the threshold error level to handle globally all debug output. + * Debug messages that have a level over the threshold value are + * discarded. + * (Default value: 0 = No debug ) + * + * \param threshold threshold level of messages to filter on. Messages at a + * higher level will be discarded. + * - Debug levels + * - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ +void mbedtls_debug_set_threshold( int threshold ); + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) MBEDTLS_PRINTF_ATTRIBUTE(5, 6); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ); +#endif + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ); +#endif + +#if defined(MBEDTLS_ECDH_C) +typedef enum +{ + MBEDTLS_DEBUG_ECDH_Q, + MBEDTLS_DEBUG_ECDH_QP, + MBEDTLS_DEBUG_ECDH_Z, +} mbedtls_debug_ecdh_attr; + +/** + * \brief Print a field of the ECDH structure in the SSL context to the debug + * output. This function is always used through the + * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file + * and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param ecdh the ECDH context + * \param attr the identifier of the attribute being output + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h new file mode 100644 index 0000000..325aab5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/des.h @@ -0,0 +1,370 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/platform_util.h" + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +/** The data input has an invalid length. */ +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 + +/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** DES hardware accelerator failed. */ +#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 + +#define MBEDTLS_DES_KEY_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des_context +{ + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct mbedtls_des3_context +{ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_des_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h new file mode 100644 index 0000000..c4b15a2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h @@ -0,0 +1,1103 @@ +/** + * \file dhm.h + * + * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange + * definitions and functions. + * + * Diffie-Hellman-Merkle (DHM) key exchange is defined in + * RFC-2631: Diffie-Hellman Key Agreement Method and + * Public-Key Cryptography Standards (PKCS) #3: Diffie + * Hellman Key Agreement Standard. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_DHM_H +#define MBEDTLS_DHM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/bignum.h" + +/* + * DHM Error codes + */ +/** Bad input parameters. */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 +/** Reading of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 +/** Making of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 +/** Reading of the public values failed. */ +#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 +/** Making of the public value failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 +/** Calculation of the DHM secret failed. */ +#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 +/** The ASN.1 data is not formatted correctly. */ +#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 +/** Allocation of memory failed. */ +#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 +/** Read or write of file failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 + +/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** DHM hardware accelerator failed. */ +#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 + +/** Setting the modulus and generator failed. */ +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/** + * \brief The DHM context structure. + */ +typedef struct mbedtls_dhm_context +{ + size_t len; /*!< The size of \p P in Bytes. */ + mbedtls_mpi P; /*!< The prime modulus. */ + mbedtls_mpi G; /*!< The generator. */ + mbedtls_mpi X; /*!< Our secret value. */ + mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi Vi; /*!< The blinding value. */ + mbedtls_mpi Vf; /*!< The unblinding value. */ + mbedtls_mpi pX; /*!< The previous \c X. */ +} +mbedtls_dhm_context; + +#else /* MBEDTLS_DHM_ALT */ +#include "dhm_alt.h" +#endif /* MBEDTLS_DHM_ALT */ + +/** + * \brief This function initializes the DHM context. + * + * \param ctx The DHM context to initialize. + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief This function parses the DHM parameters in a + * TLS ServerKeyExchange handshake message + * (DHM modulus, generator, and public key). + * + * \note In a TLS handshake, this is the how the client + * sets up its DHM context from the server's public + * DHM key material. + * + * \param ctx The DHM context to use. This must be initialized. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief This function generates a DHM key pair and exports its + * public part together with the DHM parameters in the format + * used in a TLS ServerKeyExchange handshake message. + * + * \note This function assumes that the DHM parameters \c ctx->P + * and \c ctx->G have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). + * + * \note In a TLS handshake, this is the how the server generates + * and exports its DHM key material. + * + * \param ctx The DHM context to use. This must be initialized + * and have the DHM parameters set. It may or may not + * already have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param olen The address at which to store the number of Bytes + * written on success. This must not be \c NULL. + * \param output The destination buffer. This must be a writable buffer of + * sufficient size to hold the reduced binary presentation of + * the modulus, the generator and the public key, each wrapped + * with a 2-byte length field. It is the responsibility of the + * caller to ensure that enough space is available. Refer to + * mbedtls_mpi_size() to computing the byte-size of an MPI. + * \param f_rng The RNG function. Must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function sets the prime modulus and generator. + * + * \note This function can be used to set \c ctx->P, \c ctx->G + * in preparation for mbedtls_dhm_make_params(). + * + * \param ctx The DHM context to configure. This must be initialized. + * \param P The MPI holding the DHM prime modulus. This must be + * an initialized MPI. + * \param G The MPI holding the DHM generator. This must be an + * initialized MPI. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the raw public value of the peer. + * + * \note In a TLS handshake, this is the how the server imports + * the Client's public DHM key. + * + * \param ctx The DHM context to use. This must be initialized and have + * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). + * It may or may not already have generated its own private key. + * \param input The input buffer containing the \c G^Y value of the peer. + * This must be a readable buffer of size \p ilen Bytes. + * \param ilen The size of the input buffer \p input in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function creates a DHM key pair and exports + * the raw public key in big-endian format. + * + * \note The destination buffer is always fully written + * so as to contain a big-endian representation of G^X mod P. + * If it is larger than \c ctx->len, it is padded accordingly + * with zero-bytes at the beginning. + * + * \param ctx The DHM context to use. This must be initialized and + * have the DHM parameters set. It may or may not already + * have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param output The destination buffer. This must be a writable buffer of + * size \p olen Bytes. + * \param olen The length of the destination buffer. This must be at least + * equal to `ctx->len` (the size of \c P). + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. + * + * \note If \p f_rng is not \c NULL, it is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our private key \c X is re-used, and not used + * otherwise. We recommend always passing a non-NULL + * \p f_rng argument. + * + * \param ctx The DHM context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param output The buffer to write the generated shared key to. This + * must be a writable buffer of size \p output_size Bytes. + * \param output_size The size of the destination buffer. This must be at + * least the size of \c ctx->len (the size of \c P). + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function frees and clears the components + * of a DHM context. + * + * \param ctx The DHM context to free and clear. This may be \c NULL, + * in which case this function is a no-op. If it is not \c NULL, + * it must point to an initialized DHM context. + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** + * \brief This function parses DHM parameters in PEM or DER format. + * + * \param dhm The DHM context to import the DHM parameters into. + * This must be initialized. + * \param dhmin The input buffer. This must be a readable buffer of + * length \p dhminlen Bytes. + * \param dhminlen The size of the input buffer \p dhmin, including the + * terminating \c NULL Byte for PEM data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error + * code on failure. + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function loads and parses DHM parameters from a file. + * + * \param dhm The DHM context to load the parameters to. + * This must be initialized. + * \param path The filename to read the DHM parameters from. + * This must not be \c NULL. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX + * error code on failure. + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The DMH checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_dhm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ +#ifdef __cplusplus +} +#endif + +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/** + * \warning The origin of the primes in RFC 5114 is not documented and + * their use therefore constitutes a security risk! + * + * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are + * likely to be removed in a future version of the library without + * replacement. + */ + +/** + * The hexadecimal presentation of the prime underlying the + * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined + * in RFC-5114: Additional Diffie-Hellman Groups for Use with + * IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: + * Additional Diffie-Hellman Groups for Use with IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ + "81BC087F2A7065B384B890D3191F2BFA" ) + +/** + * The hexadecimal presentation of the prime underlying the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + * + * \deprecated The hex-encoded primes from RFC 3625 are deprecated and + * superseded by the corresponding macros providing them as + * binary constants. Their hex-encoded constants are likely + * to be removed in a future version of the library. + * + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 3072-bit MODP + * Group, as defined in RFC-3072: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 3072-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + +#endif /* dhm.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h new file mode 100644 index 0000000..05855cd --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h @@ -0,0 +1,446 @@ +/** + * \file ecdh.h + * + * \brief This file contains ECDH definitions and functions. + * + * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous + * key agreement protocol allowing two parties to establish a shared + * secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_ECDH_H +#define MBEDTLS_ECDH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" + +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) +#undef MBEDTLS_ECDH_LEGACY_CONTEXT +#include "everest/everest.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the source of the imported EC key. + */ +typedef enum +{ + MBEDTLS_ECDH_OURS, /**< Our key. */ + MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ +} mbedtls_ecdh_side; + +#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +/** + * Defines the ECDH implementation used. + * + * Later versions of the library may add new variants, therefore users should + * not make any assumptions about them. + */ +typedef enum +{ + MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ + MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + MBEDTLS_ECDH_VARIANT_EVEREST /*!< Everest implementation */ +#endif +} mbedtls_ecdh_variant; + +/** + * The context used by the default ECDH implementation. + * + * Later versions might change the structure of this context, therefore users + * should not make any assumptions about the structure of + * mbedtls_ecdh_context_mbed. + */ +typedef struct mbedtls_ecdh_context_mbed +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif +} mbedtls_ecdh_context_mbed; +#endif + +/** + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + * \brief The ECDH context structure. + */ +typedef struct mbedtls_ecdh_context +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ + int point_format; /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point Vi; /*!< The blinding value. */ + mbedtls_ecp_point Vf; /*!< The unblinding value. */ + mbedtls_mpi _d; /*!< The previous \p d. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + int restart_enabled; /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t point_format; /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */ + mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */ + union + { + mbedtls_ecdh_context_mbed mbed_ecdh; +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + mbedtls_ecdh_context_everest everest_ecdh; +#endif + } ctx; /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ +} +mbedtls_ecdh_context; + +/** + * \brief Check whether a given group can be used for ECDH. + * + * \param gid The ECP group ID to check. + * + * \return \c 1 if the group can be used, \c 0 otherwise + */ +int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ); + +/** + * \brief This function generates an ECDH keypair on an elliptic + * curve. + * + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). + * + * \see ecp.h + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param d The destination MPI (private key). + * This must be initialized. + * \param Q The destination point (public key). + * This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the shared secret. + * + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param z The destination MPI (shared secret). + * This must be initialized. + * \param Q The public key from another party. + * This must be initialized. + * \param d Our secret exponent (private key). + * This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results during the ECP computations is + * not needed (discouraged). See the documentation of + * mbedtls_ecp_mul() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a + * context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function initializes an ECDH context. + * + * \param ctx The ECDH context to initialize. This must not be \c NULL. + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function sets up the ECDH context with the information + * given. + * + * This function should be called after mbedtls_ecdh_init() but + * before mbedtls_ecdh_make_params(). There is no need to call + * this function before mbedtls_ecdh_read_params(). + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param grp_id The group id of the group to set up the context for. + * + * \return \c 0 on success. + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. This may be \c NULL, in which + * case this function does nothing. If it is not \c NULL, + * it must point to an initialized ECDH context. + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function generates an EC key pair and exports its + * in the format used in a TLS ServerKeyExchange handshake + * message. + * + * This is the second function used by a TLS server for ECDHE + * ciphersuites. (It is called after mbedtls_ecdh_setup().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param olen The address at which to store the number of Bytes written. + * \param buf The destination buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses the ECDHE parameters in a + * TLS ServerKeyExchange handshake message. + * + * \note In a TLS handshake, this is the how the client + * sets up its ECDHE context from the server's public + * ECDHE key material. + * + * \see ecp.h + * + * \param ctx The ECDHE context to use. This must be initialized. + * \param buf On input, \c *buf must be the start of the input buffer. + * On output, \c *buf is updated to point to the end of the + * data that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ); + +/** + * \brief This function sets up an ECDH context from an EC key. + * + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \see ecp.h + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param key The EC key to use. This must be initialized. + * \param side Defines the source of the key. Possible values are: + * - #MBEDTLS_ECDH_OURS: The key is ours. + * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief This function generates a public key and exports it + * as a TLS ClientKeyExchange payload. + * + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, the latter usually by + * mbedtls_ecdh_read_params(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The destination buffer. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The size of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes the ECDHE payload of a + * TLS ClientKeyExchange message. + * + * This is the third function used by a TLS server for ECDH(E) + * ciphersuites. (It is called after mbedtls_ecdh_setup() and + * mbedtls_ecdh_make_params().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param buf The pointer to the ClientKeyExchange payload. This must + * be a readable buffer of length \p blen Bytes. + * \param blen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief This function derives and exports the shared secret. + * + * This is the last function used by both TLS client + * and servers. + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \see ecp.h + + * \param ctx The ECDH context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param olen The address at which to store the total number of + * Bytes written on success. This must not be \c NULL. + * \param buf The buffer to write the generated shared key to. This + * must be a writable buffer of size \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief This function enables restartable EC computations for this + * context. (Default: disabled.) + * + * \see \c mbedtls_ecp_set_max_ops() + * + * \note It is not possible to safely disable restartable + * computations once enabled, except by free-ing the context, + * which cancels possible in-progress operations. + * + * \param ctx The ECDH context to use. This must be initialized. + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h new file mode 100644 index 0000000..264a638 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h @@ -0,0 +1,626 @@ +/** + * \file ecdsa.h + * + * \brief This file contains ECDSA definitions and functions. + * + * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in + * Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_ECDSA_H +#define MBEDTLS_ECDSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +/** + * \brief Maximum ECDSA signature size for a given curve bit size + * + * \param bits Curve size in bits + * \return Maximum signature size in bytes + * + * \note This macro returns a compile-time constant if its argument + * is one. It may evaluate its argument multiple times. + */ +/* + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * For each of r and s, the value (V) may include an extra initial "0" bit. + */ +#define MBEDTLS_ECDSA_MAX_SIG_LEN( bits ) \ + ( /*T,L of SEQUENCE*/ ( ( bits ) >= 61 * 8 ? 3 : 2 ) + \ + /*T,L of r,s*/ 2 * ( ( ( bits ) >= 127 * 8 ? 3 : 2 ) + \ + /*V of r,s*/ ( ( bits ) + 8 ) / 8 ) ) + +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN( MBEDTLS_ECP_MAX_BITS ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ECDSA context structure. + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for ecdsa_verify() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; + +/** + * \brief Internal restart context for ecdsa_sign() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Internal restart context for ecdsa_sign_det() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; +#endif + +/** + * \brief General context for resuming ECDSA operations + */ +typedef struct +{ + mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ +#endif +} mbedtls_ecdsa_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_ecdsa_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function checks whether a given group can be used + * for ECDSA. + * + * \param gid The ECP group ID to check. + * + * \return \c 1 if the group can be used, \c 0 otherwise + */ +int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid ); + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det() is usually preferred. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized. + * \param buf The content to be signed. This is usually the hash of + * the original data to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \warning Since the output of the internal RNG is always the same for + * the same key and message, this limits the efficiency of + * blinding and leaks information through side channels. For + * secure behavior use mbedtls_ecdsa_sign_det_ext() instead. + * + * (Optimally the blinding is a random value that is different + * on every execution. In this case the blinding is still + * random from the attackers perspective, but is the same on + * each execution. This means that this blinding does not + * prevent attackers from recovering secrets by combining + * several measurement traces, but may prevent some attacks + * that exploit relationships between secret data.) + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param buf The hashed content that was signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param Q The public key to use for verification. This must be + * initialized and setup. + * \param r The first integer of the signature. + * This must be initialized. + * \param s The second integer of the signature. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature + * is invalid. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, + const mbedtls_mpi *s); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is used only for blinding and may be set to \c NULL, but + * doing so is DEPRECATED. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, in a restartable way. + * + * \see \c mbedtls_ecdsa_write_signature() + * + * \note This function is like \c mbedtls_ecdsa_write_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes an ECDSA signature and writes + * it to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) + * and Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in + * Mbed TLS version 2.0 and later. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param md_alg The message digest that was used to hash the message. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function reads and verifies an ECDSA signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function reads and verifies an ECDSA signature, + * in a restartable way. + * + * \see \c mbedtls_ecdsa_read_signature() + * + * \note This function is like \c mbedtls_ecdsa_read_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \see ecp.h + * + * \param ctx The ECDSA context to store the keypair in. + * This must be initialized. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function sets up an ECDSA context from an EC key pair. + * + * \see ecp.h + * + * \param ctx The ECDSA context to setup. This must be initialized. + * \param key The EC key to use. This must be initialized and hold + * a private-public key pair or a public key. In the former + * case, the ECDSA context may be used for signature creation + * and verification after this call. In the latter case, it + * may be used for signature verification. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, + const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h new file mode 100644 index 0000000..3564ff8 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h @@ -0,0 +1,275 @@ +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ECJPAKE_H +#define MBEDTLS_ECJPAKE_H + +/* + * J-PAKE is a password-authenticated key exchange that allows deriving a + * strong shared secret from a (potentially low entropy) pre-shared + * passphrase, with forward secrecy and mutual authentication. + * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling + * + * This file implements the Elliptic Curve variant of J-PAKE, + * as defined in Chapter 7.4 of the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + * + * As the J-PAKE algorithm is inherently symmetric, so is our API. + * Each party needs to send its first round message, in any order, to the + * other party, then each sends its second round message, in any order. + * The payloads are serialized in a way suitable for use in TLS, but could + * also be use outside TLS. + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Roles in the EC J-PAKE exchange + */ +typedef enum { + MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ + MBEDTLS_ECJPAKE_SERVER, /**< Server */ +} mbedtls_ecjpake_role; + +#if !defined(MBEDTLS_ECJPAKE_ALT) +/** + * EC J-PAKE context structure. + * + * J-PAKE is a symmetric protocol, except for the identifiers used in + * Zero-Knowledge Proofs, and the serialization of the second message + * (KeyExchange) as defined by the Thread spec. + * + * In order to benefit from this symmetry, we choose a different naming + * convention from the Thread v1.0 spec. Correspondence is indicated in the + * description as a pair C: client name, S: server name + */ +typedef struct mbedtls_ecjpake_context +{ + const mbedtls_md_info_t *md_info; /**< Hash to use */ + mbedtls_ecp_group grp; /**< Elliptic curve */ + mbedtls_ecjpake_role role; /**< Are we client or server? */ + int point_format; /**< Format for point export */ + + mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ +} mbedtls_ecjpake_context; + +#else /* MBEDTLS_ECJPAKE_ALT */ +#include "ecjpake_alt.h" +#endif /* MBEDTLS_ECJPAKE_ALT */ + +/** + * \brief Initialize an ECJPAKE context. + * + * \param ctx The ECJPAKE context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); + +/** + * \brief Set up an ECJPAKE context for use. + * + * \note Currently the only values for hash/curve allowed by the + * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. + * + * \param ctx The ECJPAKE context to set up. This must be initialized. + * \param role The role of the caller. This must be either + * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. + * \param hash The identifier of the hash function to use, + * for example #MBEDTLS_MD_SHA256. + * \param curve The identifier of the elliptic curve to use, + * for example #MBEDTLS_ECP_DP_SECP256R1. + * \param secret The pre-shared secret (passphrase). This must be + * a readable buffer of length \p len Bytes. It need + * only be valid for the duration of this call. + * \param len The length of the pre-shared secret \p secret. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ); + +/** + * \brief Check if an ECJPAKE context is ready for use. + * + * \param ctx The ECJPAKE context to check. This must be + * initialized. + * + * \return \c 0 if the context is ready for use. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); + +/** + * \brief Generate and write the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be + * initialized and set up. + * \param buf The buffer to write the contents to. This must be a + * writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number + * of Bytes written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up. + * \param buf The buffer holding the first round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Generate and write the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up, and already have performed round one. + * \param buf The buffer to write the round two contents to. + * This must be a writable buffer of length \p len Bytes. + * \param len The size of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up and already have performed round one. + * \param buf The buffer holding the second round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Derive the shared secret + * (TLS: Pre-Master Secret). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up and have performed both round one and two. + * \param buf The buffer to write the derived secret to. This must + * be a writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This clears an ECJPAKE context and frees any + * embedded data structure. + * + * \param ctx The ECJPAKE context to free. This may be \c NULL, + * in which case this function does nothing. If it is not + * \c NULL, it must point to an initialized ECJPAKE context. + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* ecjpake.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h new file mode 100644 index 0000000..c8702f9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h @@ -0,0 +1,1315 @@ +/** + * \file ecp.h + * + * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). + * + * The use of ECP in cryptography and TLS is defined in + * Standards for Efficient Cryptography Group (SECG): SEC1 + * Elliptic Curve Cryptography and + * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites + * for Transport Layer Security (TLS). + * + * RFC-2409: The Internet Key Exchange (IKE) defines ECP + * group types. + * + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_ECP_H +#define MBEDTLS_ECP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + +/* + * ECP error codes + */ +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 +/** The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 +/** The requested feature is not available, for example, the requested curve is not supported. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 +/** The signature is not valid. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 +/** Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 +/** Generation of random value, such as ephemeral key, failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 +/** Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 +/** The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 + +/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** The ECP hardware accelerator failed. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 + +/** Operation in progress, call again with the same parameters to continue. */ +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 + +/* Flags indicating whether to include code that is specific to certain + * types of curves. These flags are for internal library use only. */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SM2_ENABLED) +#define MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED +#endif +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_ECP_MONTGOMERY_ENABLED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain-parameter identifiers: curve, subgroup, and generator. + * + * \note Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only standardized domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +/* Note: when adding a new curve: + * - Add it at the end of this enum, otherwise you'll break the ABI by + * changing the numerical value for existing curves. + * - Increment MBEDTLS_ECP_DP_MAX below if needed. + * - Update the calculation of MBEDTLS_ECP_MAX_BITS_MIN below. + * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to + * config.h. + * - List the curve as a dependency of MBEDTLS_ECP_C and + * MBEDTLS_ECDSA_C if supported in check_config.h. + * - Add the curve to the appropriate curve type macro + * MBEDTLS_ECP_yyy_ENABLED above. + * - Add the necessary definitions to ecp_curves.c. + * - Add the curve to the ecp_supported_curves array in ecp.c. + * - Add the curve to applicable profiles in x509_crt.c if applicable. + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ + MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ + MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ + MBEDTLS_ECP_DP_SM2, /*!< Domain parameters for SM2. */ +} mbedtls_ecp_group_id; + +/** + * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. + * + * \note Montgomery curves are currently excluded. + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/* + * Curve types + */ +typedef enum +{ + MBEDTLS_ECP_TYPE_NONE = 0, + MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + MBEDTLS_ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} mbedtls_ecp_curve_type; + +/** + * Curve information, for use by other modules. + */ +typedef struct mbedtls_ecp_curve_info +{ + mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ + uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ + uint16_t bit_size; /*!< The curve size in bits. */ + const char *name; /*!< A human-friendly name. */ +} mbedtls_ecp_curve_info; + +/** + * \brief The ECP point structure, in Jacobian coordinates. + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or + * Z == 1. Other values of \p Z are + * used only by internal functions. + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, \p X and \p Y are its standard (affine) + * coordinates. + */ +typedef struct mbedtls_ecp_point +{ + mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ + mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */ +} +mbedtls_ecp_point; + +/* Determine the minimum safe value of MBEDTLS_ECP_MAX_BITS. */ +#if !defined(MBEDTLS_ECP_C) +#define MBEDTLS_ECP_MAX_BITS_MIN 0 +/* Note: the curves must be listed in DECREASING size! */ +#elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 521 +#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 512 +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 448 +#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 384 +#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 384 +#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 256 +#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 256 +#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 256 +#elif defined(MBEDTLS_ECP_DP_SM2_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 256 +#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 255 +#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 225 // n is slightly above 2^224 +#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 224 +#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 192 +#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS_MIN 192 +#else +#error "MBEDTLS_ECP_C enabled, but no curve?" +#endif + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +/** + * \brief The ECP group structure. + * + * We consider two types of curve equations: + *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P + * (SEC1 + RFC-4492)
  • + *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, + * Curve448)
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed. + * + * For Short Weierstrass, this subgroup is the whole curve, and its + * cardinality is denoted by \p N. Our code requires that \p N is an + * odd prime as mbedtls_ecp_mul() requires an odd number, and + * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. + * + * For Montgomery curves, we do not store \p A, but (A + 2) / 4, + * which is the quantity used in the formulas. Additionally, \p nbits is + * not the size of \p N but the required size for private keys. + * + * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. + * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the + * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer + * which is congruent mod \p P to the given MPI, and is close enough to \p pbits + * in size, so that it may be efficiently brought in the 0..P-1 range by a few + * additions or subtractions. Therefore, it is only an approximative modular + * reduction. It must return 0 on success and non-zero on failure. + * + * \note Alternative implementations must keep the group IDs distinct. If + * two group structures have the same ID, then they must be + * identical. + * + */ +typedef struct mbedtls_ecp_group +{ + mbedtls_ecp_group_id id; /*!< An internal group identifier. */ + mbedtls_mpi P; /*!< The prime modulus of the base field. */ + mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For + Montgomery curves: (A + 2) / 4. */ + mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. + For Montgomery curves: unused. */ + mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ + mbedtls_mpi N; /*!< The order of \p G. */ + size_t pbits; /*!< The number of bits in \p P.*/ + size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. + For Montgomery curves: the number of bits in the + private keys. */ + unsigned int h; /*!< \internal 1 if the constants are static. */ + int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *t_data; /*!< Unused. */ + mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */ + size_t T_size; /*!< The number of pre-computed points. */ +} +mbedtls_ecp_group; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h, or define them using the compiler command line. + * \{ + */ + +#if defined(MBEDTLS_ECP_MAX_BITS) + +#if MBEDTLS_ECP_MAX_BITS < MBEDTLS_ECP_MAX_BITS_MIN +#error "MBEDTLS_ECP_MAX_BITS is smaller than the largest supported curve" +#endif + +#elif defined(MBEDTLS_ECP_C) +/** + * The maximum size of the groups, that is, of \c N and \c P. + */ +#define MBEDTLS_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS_MIN + +#else +/* MBEDTLS_ECP_MAX_BITS is not relevant without MBEDTLS_ECP_C, but set it + * to a nonzero value so that code that unconditionally allocates an array + * of a size based on it keeps working if built without ECC support. */ +#define MBEDTLS_ECP_MAX_BITS 1 +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: a point where higher memory usage yields diminishing performance + * returns. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 4 /**< The maximum window size used. */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/** \} name SECTION: Module settings */ + +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for multiplication + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; + +/** + * \brief Internal restart context for ecp_muladd() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; + +/** + * \brief General context for resuming ECC operations + */ +typedef struct +{ + unsigned ops_done; /*!< current ops count */ + unsigned depth; /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ +} mbedtls_ecp_restart_ctx; + +/* + * Operation counts for restartable functions + */ +#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ +#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ +#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ +#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ + +/** + * \brief Internal; for restartable functions in other modules. + * Check and update basic ops budget. + * + * \param grp Group structure + * \param rs_ctx Restart context + * \param ops Number of basic ops to do + * + * \return \c 0 if doing \p ops basic ops is still allowed, + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ); + +/* Utility macro for checking and updating ops budget */ +#define MBEDTLS_ECP_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \ + (unsigned) (ops) ) ); + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */ + +/* We want to declare restartable versions of existing functions anyway */ +typedef void mbedtls_ecp_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief The ECP key-pair structure. + * + * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. + * + * \note Members are deliberately in the same order as in the + * ::mbedtls_ecdsa_context structure. + */ +typedef struct mbedtls_ecp_keypair +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Set the maximum number of basic operations done in a row. + * + * If more operations are needed to complete a computation, + * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * function performing the computation. It is then the + * caller's responsibility to either call again with the same + * parameters until it returns 0 or an error code; or to free + * the restart context if the operation is to be aborted. + * + * It is strictly required that all input parameters and the + * restart context be the same on successive calls for the + * same operation, but output parameters need not be the + * same; they must not be used until the function finally + * returns 0. + * + * This only applies to functions whose documentation + * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the + * SSL module). For functions that accept a "restart context" + * argument, passing NULL disables restart and makes the + * function equivalent to the function with the same name + * with \c _restartable removed. For functions in the ECDH + * module, restart is disabled unless the function accepts + * an "ECDH context" argument and + * mbedtls_ecdh_enable_restart() was previously called on + * that context. For function in the SSL module, restart is + * only enabled for specific sides and key exchanges + * (currently only for clients and ECDHE-ECDSA). + * + * \param max_ops Maximum number of basic operations done in a row. + * Default: 0 (unlimited). + * Lower (non-zero) values mean ECC functions will block for + * a lesser maximum amount of time. + * + * \note A "basic operation" is defined as a rough equivalent of a + * multiplication in GF(p) for the NIST P-256 curve. + * As an indication, with default settings, a scalar + * multiplication (full run of \c mbedtls_ecp_mul()) is: + * - about 3300 basic operations for P-256 + * - about 9400 basic operations for P-384 + * + * \note Very low values are not always respected: sometimes + * functions need to block for a minimum number of + * operations, and will do so even if max_ops is set to a + * lower value. That minimum depends on the curve size, and + * can be made lower by decreasing the value of + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the + * lowest effective value for various curves and values of + * that parameter (w for short): + * w=6 w=5 w=4 w=3 w=2 + * P-256 208 208 160 136 124 + * P-384 682 416 320 272 248 + * P-521 1364 832 640 544 496 + * + * \note This setting is currently ignored by Curve25519. + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ); + +/** + * \brief Check if restart is enabled (max_ops != 0) + * + * \return \c 0 if \c max_ops == 0 (restart disabled) + * \return \c 1 otherwise (restart enabled) + */ +int mbedtls_ecp_restart_is_enabled( void ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get the type of a curve + */ +mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp ); + +/** + * \brief This function retrieves the information defined in + * mbedtls_ecp_curve_info() for all supported curves. + * + * \note This function returns information about all curves + * supported by the library. Some curves may not be + * supported for all algorithms. Call mbedtls_ecdh_can_do() + * or mbedtls_ecdsa_can_do() to check if a curve is + * supported for ECDH or ECDSA. + * + * \return A statically allocated array. The last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief This function retrieves the list of internal group + * identifiers of all supported curves in the order of + * preference. + * + * \note This function returns information about all curves + * supported by the library. Some curves may not be + * supported for all algorithms. Call mbedtls_ecdh_can_do() + * or mbedtls_ecdsa_can_do() to check if a curve is + * supported for ECDH or ECDSA. + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief This function retrieves curve information from an internal + * group identifier. + * + * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function retrieves curve information from a TLS + * NamedCurve value. + * + * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief This function retrieves curve information from a + * human-readable name. + * + * \param name The human-readable name. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief This function initializes a point as zero. + * + * \param pt The point to initialize. + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief This function initializes an ECP group context + * without loading any domain parameters. + * + * \note After this function is called, domain parameters + * for various ECP groups can be loaded through the + * mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group() + * functions. + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief This function initializes a key pair as an invalid one. + * + * \param key The key pair to initialize. + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief This function frees the components of a point. + * + * \param pt The point to free. + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief This function frees the components of an ECP group. + * + * \param grp The group to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP group. + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief This function frees the components of a key pair. + * + * \param key The key pair to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP key pair. + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. This must + * not be \c NULL. + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized restart context. + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function copies the contents of point \p Q into + * point \p P. + * + * \param P The destination point. This must be initialized. + * \param Q The source point. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code for other kinds of failure. + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief This function copies the contents of group \p src into + * group \p dst. + * + * \param dst The destination group. This must be initialized. + * \param src The source group. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, + const mbedtls_ecp_group *src ); + +/** + * \brief This function sets a point to the point at infinity. + * + * \param pt The point to set. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function checks if a point is the point at infinity. + * + * \param pt The point to test. This must be initialized. + * + * \return \c 1 if the point is zero. + * \return \c 0 if the point is non-zero. + * \return A negative error code on failure. + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function compares two points. + * + * \note This assumes that the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P The first point to compare. This must be initialized. + * \param Q The second point to compare. This must be initialized. + * + * \return \c 0 if the points are equal. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief This function imports a non-zero point from two ASCII + * strings. + * + * \param P The destination point. This must be initialized. + * \param radix The numeric base of the input. + * \param x The first affine coordinate, as a null-terminated string. + * \param y The second affine coordinate, as a null-terminated string. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief This function exports a point into unsigned binary data. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The point to export. This must be initialized. + * \param format The point format. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * (For groups without these formats, this parameter is + * ignored. But it still has to be either of the above + * values.) + * \param olen The address at which to store the length of + * the output in Bytes. This must not be \c NULL. + * \param buf The output buffer. This must be a writable buffer + * of length \p buflen Bytes. + * \param buflen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer + * is too small to hold the point. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * or the export for the given group is not implemented. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function imports a point from unsigned binary data. + * + * \note This function does not check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() + * for that. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The destination context to import the point to. + * This must be initialized. + * \param buf The input buffer. This must be a readable buffer + * of length \p ilen Bytes. + * \param ilen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the import for the + * given group is not implemented. + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief This function imports a point from a TLS ECPoint record. + * + * \note On function return, \p *buf is updated to point immediately + * after the ECPoint record. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The destination point. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization + * failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief This function exports a point as a TLS ECPoint record + * defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to be exported. This must be initialized. + * \param format The point format to use. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length in Bytes + * of the data written. + * \param buf The target buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the target buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer + * is too small to hold the exported point. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function sets up an ECP group context + * from a standardized set of domain parameters. + * + * \note The index should be a value of the NamedCurve enum, + * as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS), + * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. + * + * \param grp The group context to setup. This must be initialized. + * \param id The identifier of the domain parameter set to load. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief This function sets up an ECP group context from a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The group context to setup. This must be initialized. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ); + +/** + * \brief This function extracts an elliptic curve group ID from a + * TLS ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The address at which to store the group id. + * This must not be \c NULL. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, + size_t len ); +/** + * \brief This function exports an elliptic curve as a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to be exported. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The buffer to write to. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output + * buffer is too small to hold the exported group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, + size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function performs a scalar multiplication of a point + * by an integer: \p R = \p m * \p P. + * + * It is not thread-safe to use same group in multiple threads. + * + * \note To prevent timing attacks, this function + * executes the exact same sequence of base-field + * operations for any valid \p m. It avoids any if-branch or + * array index depending on the value of \p m. + * + * \note If \p f_rng is not NULL, it is used to randomize + * intermediate results to prevent potential timing attacks + * targeting these results. We recommend always providing + * a non-NULL \p f_rng. The overhead is negligible. + * Note: unless #MBEDTLS_ECP_NO_INTERNAL_RNG is defined, when + * \p f_rng is NULL, an internal RNG (seeded from the value + * of \p m) will be used instead. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P in a restartable way. + * + * \see mbedtls_ecp_mul() + * + * \note This function does the same as \c mbedtls_ecp_mul(), but + * it can return early and restart according to the limit set + * with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q + * + * It is not thread-safe to use same group in multiple threads. + * + * \note In contrast to mbedtls_ecp_mul(), this function does not + * guarantee a constant execution flow and timing. + * + * \note This function is only defined for short Weierstrass curves. + * It may not be included in builds without any short + * Weierstrass curve. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not + * designate a short Weierstrass curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q in a + * restartable way. + * + * \see \c mbedtls_ecp_muladd() + * + * \note This function works the same as \c mbedtls_ecp_muladd(), + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \note This function is only defined for short Weierstrass curves. + * It may not be included in builds without any short + * Weierstrass curve. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not + * designate a short Weierstrass curve. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +/** + * \brief This function checks that a point is a valid public key + * on this curve. + * + * It only checks that the point is non-zero, has + * valid coordinates and lies on the curve. It does not verify + * that it is indeed a multiple of \p G. This additional + * check is computationally more expensive, is not required + * by standards, and should not be necessary if the group + * used has a small cofactor. In particular, it is useless for + * the NIST groups which all have a cofactor of 1. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure, to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the point should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to check. This must be initialized. + * + * \return \c 0 if the point is a valid public key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not + * a valid public key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ); + +/** + * \brief This function checks that an \p mbedtls_mpi is a + * valid private key for this curve. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the private key should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The integer to check. This must be initialized. + * + * \return \c 0 if the point is a valid private key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid + * private key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ); + +/** + * \brief This function generates a private key. + * + * \param grp The ECP group to generate a private key for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates a keypair with a configurable base + * point. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param G The base point to use. This must be initialized + * and belong to \p grp. It replaces the default base + * point \c grp->G used by mbedtls_ecp_gen_keypair(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP keypair. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, + mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function reads an elliptic curve private key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. + * \param buf The buffer containing the binary representation of the + * key. (Big endian integer for Weierstrass curves, byte + * string for Montgomery curves.) + * \param buflen The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY error if the key is + * invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for + * the group is not implemented. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + const unsigned char *buf, size_t buflen ); + +/** + * \brief This function exports an elliptic curve private key. + * + * \param key The private key. + * \param buf The output buffer for containing the binary representation + * of the key. (Big endian integer for Weierstrass curves, byte + * string for Montgomery curves.) + * \param buflen The total length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key + representation is larger than the available space in \p buf. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for + * the group is not implemented. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_ecp_write_key( mbedtls_ecp_keypair *key, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function checks that the keypair objects + * \p pub and \p prv have the same group and the + * same public point, and that the private key in + * \p prv is consistent with the public key. + * + * \param pub The keypair structure holding the public key. This + * must be initialized. If it contains a private key, that + * part is ignored. + * \param prv The keypair structure holding the full keypair. + * This must be initialized. + * + * \return \c 0 on success, meaning that the keys are valid and match. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, + const mbedtls_ecp_keypair *prv ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The ECP checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h new file mode 100644 index 0000000..6a47a8f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ecp_internal.h @@ -0,0 +1,297 @@ +/** + * \file ecp_internal.h + * + * \brief Function declarations for alternative implementation of elliptic curve + * point arithmetic. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * References: + * + * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. + * + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + * + * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. + * + * + * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic + * Curve Cryptography. + * + * [6] Digital Signature Standard (DSS), FIPS 186-4. + * + * + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * Security (TLS), RFC 4492. + * + * + * [8] + * + * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. + * Springer Science & Business Media, 1 Aug 2000 + */ + +#ifndef MBEDTLS_ECP_INTERNAL_H +#define MBEDTLS_ECP_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Special cases: (1) P or Q is zero, (2) R is zero, + * (3) P == Q. + * None of these cases can happen as intermediate step in + * ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base + * point, the factor being less than its order, so none of + * them is zero; + * - Q is an odd multiple of the base point, P an even + * multiple, due to the choice of precomputed points in the + * modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as + * meaning 1. + * + * Cost in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ); +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ); +#endif + +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) +int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); +#endif + +/** + * \brief Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * + * \param grp pointer to the group representing the curve + * + * \param P the point on the curve to be randomised given with + * projective coordinates. This is an input/output parameter. + * + * \param f_rng a function pointer to the random number generator + * + * \param p_rng a pointer to the random number generator state + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) +int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +/** + * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. + * + * \param grp pointer to the group representing the curve + * + * \param P pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) +int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P ); +#endif + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#endif /* ecp_internal.h */ + diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h new file mode 100644 index 0000000..40259eb --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h @@ -0,0 +1,294 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#include "mbedtls/sha512.h" +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#include "mbedtls/sha256.h" +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +/** Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C +/** No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E +/** No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 +/** No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D +/** Read/write error in file. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/** \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct mbedtls_entropy_source_state +{ + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received in bytes */ + size_t threshold; /**< Minimum bytes required before release */ + int strong; /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct mbedtls_entropy_context +{ + int accumulator_started; /* 0 after init. + * 1 after the first update. + * -1 after free. */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR) + mbedtls_sha256_context accumulator; +#endif + int source_count; /* Number of entries used in source. */ + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTLS_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h new file mode 100644 index 0000000..e1d7491 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/entropy_poll.h @@ -0,0 +1,108 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_TIMING_C) +/** + * \brief mbedtls_timing_hardclock-based entropy poll callback + */ +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h new file mode 100644 index 0000000..50f2538 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/error.h @@ -0,0 +1,217 @@ +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0001-0x007F) + * + * Module Nr Codes assigned + * ERROR 2 0x006E 0x0001 + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * THREADING 3 0x001A-0x001E + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 0x0073-0x0073 + * SHA256 1 0x0037-0x0037 0x0074-0x0074 + * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 + * PLATFORM 2 0x0070-0x0072 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 10 (Started from top) + * MD 5 5 + * HKDF 5 1 (Started from top) + * SSL 5 2 (Started from 0x5F00) + * CIPHER 6 8 (Started from 0x6080) + * SSL 6 24 (Started from top, plus 0x6000) + * SSL 7 32 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Generic error */ +#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 +/** This is a bug in the library */ +#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E + +/** + * \brief Combines a high-level and low-level error code together. + * + * Wrapper macro for mbedtls_error_add(). See that function for + * more details. + */ +#define MBEDTLS_ERROR_ADD( high, low ) \ + mbedtls_error_add( high, low, __FILE__, __LINE__ ) + +#if defined(MBEDTLS_TEST_HOOKS) +/** + * \brief Testing hook called before adding/combining two error codes together. + * Only used when invasive testing is enabled via MBEDTLS_TEST_HOOKS. + */ +extern void (*mbedtls_test_hook_error_add)( int, int, const char *, int ); +#endif + +/** + * \brief Combines a high-level and low-level error code together. + * + * This function can be called directly however it is usually + * called via the #MBEDTLS_ERROR_ADD macro. + * + * While a value of zero is not a negative error code, it is still an + * error code (that denotes success) and can be combined with both a + * negative error code or another value of zero. + * + * \note When invasive testing is enabled via #MBEDTLS_TEST_HOOKS, also try to + * call \link mbedtls_test_hook_error_add \endlink. + * + * \param high high-level error code. See error.h for more details. + * \param low low-level error code. See error.h for more details. + * \param file file where this error code addition occurred. + * \param line line where this error code addition occurred. + */ +static inline int mbedtls_error_add( int high, int low, + const char *file, int line ) +{ +#if defined(MBEDTLS_TEST_HOOKS) + if( *mbedtls_test_hook_error_add != NULL ) + ( *mbedtls_test_hook_error_add )( high, low, file, line ); +#endif + (void)file; + (void)line; + + return( high + low ); +} + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +/** + * \brief Translate the high-level part of an Mbed TLS error code into a string + * representation. + * + * This function returns a const pointer to an un-modifiable string. The caller + * must not try to modify the string. It is intended to be used mostly for + * logging purposes. + * + * \param error_code error code + * + * \return The string representation of the error code, or \c NULL if the error + * code is unknown. + */ +const char * mbedtls_high_level_strerr( int error_code ); + +/** + * \brief Translate the low-level part of an Mbed TLS error code into a string + * representation. + * + * This function returns a const pointer to an un-modifiable string. The caller + * must not try to modify the string. It is intended to be used mostly for + * logging purposes. + * + * \param error_code error code + * + * \return The string representation of the error code, or \c NULL if the error + * code is unknown. + */ +const char * mbedtls_low_level_strerr( int error_code ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h new file mode 100644 index 0000000..9723a17 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h @@ -0,0 +1,327 @@ +/** + * \file gcm.h + * + * \brief This file contains GCM definitions and functions. + * + * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_GCM_H +#define MBEDTLS_GCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#include + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +/** Authenticated decryption failed. */ +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 + +/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** GCM hardware accelerator failed. */ +#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 + +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_GCM_ALT) + +/** + * \brief The GCM context structure. + */ +typedef struct mbedtls_gcm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint64_t len; /*!< The total length of the encrypted data. */ + uint64_t add_len; /*!< The total length of the additional data. */ + unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ + unsigned char y[16]; /*!< The Y working value. */ + unsigned char buf[16]; /*!< The buf working value. */ + int mode; /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +#else /* !MBEDTLS_GCM_ALT */ +#include "gcm_alt.h" +#endif /* !MBEDTLS_GCM_ALT */ + +/** + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). + * + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. This must not be \c NULL. + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief This function associates a GCM context with a + * cipher algorithm and a key. + * + * \param ctx The GCM context. This must be initialized. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must be a readable buffer of at + * least \p keybits bits. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the + * input buffer. For decryption, the output buffer cannot be + * the same as input buffer. If the buffers overlap, the output + * buffer must trail at least 8 Bytes behind the input buffer. + * + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. + * + * \param ctx The GCM context to use for encryption or decryption. This + * must be initialized. + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is greater + * than zero, this must be a writable buffer of at least that + * size in Bytes. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the encryption + * or decryption failed. + */ +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the ciphertext to decrypt, which is also + * the length of the decrypted plaintext. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag to verify. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size. + * \param output The buffer for holding the decrypted plaintext. If \p length + * is greater than zero, this must be a writable buffer of at + * least that size. + * + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the decryption + * failed. + */ +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data, or \c NULL + * if \p add_len is \c 0. + * \param add_len The length of the additional data. If \c 0, + * \p add may be \c NULL. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * ` The function expects input to be a multiple of 16 + * Bytes. Only the last call before calling + * mbedtls_gcm_finish() can be less than 16 Bytes. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the input data. This must be a multiple of + * 16 except in the last call before mbedtls_gcm_finish(). + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is + * greater than zero, this must be a writable buffer of at + * least that size in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. This must be initialized. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to generate. This must be at least + * four. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief This function clears a GCM context and the underlying + * cipher sub-context. + * + * \param ctx The GCM context to clear. If this is \c NULL, the call has + * no effect. Otherwise, this must be initialized. + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The GCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_gcm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* gcm.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/havege.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/havege.h new file mode 100644 index 0000000..7d27039 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/havege.h @@ -0,0 +1,80 @@ +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_HAVEGE_H +#define MBEDTLS_HAVEGE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct mbedtls_havege_state +{ + uint32_t PT1, PT2, offset[2]; + uint32_t pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; + uint32_t WALK[8192]; +} +mbedtls_havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void mbedtls_havege_free( mbedtls_havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h new file mode 100644 index 0000000..111d960 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h @@ -0,0 +1,140 @@ +/** + * \file hkdf.h + * + * \brief This file contains the HKDF interface. + * + * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is + * specified by RFC 5869. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_HKDF_H +#define MBEDTLS_HKDF_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +/** + * \name HKDF Error codes + * \{ + */ +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 +/** \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function + * (HKDF). + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros of + * md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +/** + * \brief Take the input keying material \p ikm and extract from it a + * fixed-length pseudorandom key \p prk. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the + * hash function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros + * of md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param[out] prk A pseudorandom key of at least md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +/** + * \brief Expand the supplied \p prk into several additional pseudorandom + * keys, which is the output of the HKDF. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is + * usually the output from the HKDF extract step. + * \param prk_len The length in bytes of \p prk. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* hkdf.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h new file mode 100644 index 0000000..6d372b9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h @@ -0,0 +1,474 @@ +/** + * \file hmac_drbg.h + * + * \brief The HMAC_DRBG pseudorandom generator. + * + * This module implements the HMAC_DRBG pseudorandom generator described + * in NIST SP 800-90A: Recommendation for Random Number Generation Using + * Deterministic Random Bit Generators. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * Error codes + */ +/** Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 +/** Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 +/** Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 +/** The entropy source failed. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/** \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct mbedtls_hmac_drbg_context +{ + /* Working state: the key K is not stored explicitly, + * but is implied by the HMAC context */ + mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if + * md_ctx->md_info != NULL. This means that the mutex is initialized + * during the initial seeding in mbedtls_hmac_drbg_seed() or + * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization. + * + * This function makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). + * + * \note The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL + * by default. Override this value by calling + * mbedtls_hmac_drbg_set_reseed_interval(). + * + * \param ctx HMAC_DRBG context to be initialized. + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding. + * + * Set the initial seed and set up the entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note By default, the security strength as defined by NIST is: + * - 128 bits if \p md_info is SHA-1; + * - 192 bits if \p md_info is SHA-224; + * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. + * Note that SHA-256 is just as efficient as SHA-224. + * The security strength can be reduced if a smaller + * entropy length is set with + * mbedtls_hmac_drbg_set_entropy_len(). + * + * \note The default entropy length is the security strength + * (converted from bits to bytes). You can override + * it by calling mbedtls_hmac_drbg_set_entropy_len(). + * + * \note During the initial seeding, this function calls + * the entropy source to obtain a nonce + * whose length is half the entropy length. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx HMAC_DRBG context to be seeded. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a length that is + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2 + * where \p entropy_len is the entropy length + * described above. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if the call to \p f_entropy failed. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initialisation of simplified HMAC_DRBG (never reseeds). + * + * This function is meant for use in algorithms that need a pseudorandom + * input such as deterministic ECDSA. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx HMAC_DRBG context to be initialised. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param data Concatenation of the initial entropy string and + * the additional data. + * \param data_len Length of \p data in bytes. + * + * \return \c 0 if successful. or + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_hmac_drbg_random_with_add() + * or mbedtls_hmac_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The HMAC_DRBG context. + * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF. + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * See the documentation of mbedtls_hmac_drbg_seed() for the default value. + * + * \param ctx The HMAC_DRBG context. + * \param len The amount of entropy to grab, in bytes. + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() + * or mbedtls_hmac_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. + * + * \param ctx The HMAC_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function reseeds the HMAC_DRBG context, that is + * extracts data from the entropy source. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The HMAC_DRBG context. + * \param additional Additional data to add to the state. + * If this is \c NULL, there is no additional data + * and \p len should be \c 0. + * \param len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len + * where \p entropy_len is the entropy length + * (see mbedtls_hmac_drbg_set_entropy_len()). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy function failed. + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates an HMAC_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \param additional Additional data to update with. + * If this is \c NULL, there is no additional data + * and \p add_len should be \c 0. + * \param add_len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if + * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function uses HMAC_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param out_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). + * + * \param ctx The HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \deprecated Superseded by mbedtls_hmac_drbg_update_ret() + * in 2.16.0. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + */ +MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( + mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The HMAC_DRBG Checkup routine. + * + * \return \c 0 if successful. + * \return \c 1 if the test failed. + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h new file mode 100644 index 0000000..84fafd2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md.h @@ -0,0 +1,493 @@ + /** + * \file md.h + * + * \brief This file contains the generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/platform_util.h" + +/** The selected feature is not available. */ +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 +/** Opening or reading of file failed. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 + +/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** MD hardware accelerator failed. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported message digests. + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD2, /**< The MD2 message digest. */ + MBEDTLS_MD_MD4, /**< The MD4 message digest. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 128 +#else +#define MBEDTLS_MD_MAX_BLOCK_SIZE 64 +#endif + +/** + * Opaque struct defined in md_internal.h. + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * The generic message-digest context. + */ +typedef struct mbedtls_md_context_t +{ + /** Information about the associated message digest. */ + const mbedtls_md_info_t *md_info; + + /** The digest-specific context. */ + void *md_ctx; + + /** The HMAC part of the context. */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \note The list starts with the strongest available hashes. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md2.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md2.h new file mode 100644 index 0000000..7f3d5cf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md2.h @@ -0,0 +1,305 @@ +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef MBEDTLS_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** MD2 hardware accelerator failed */ +#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + +/** + * \brief MD2 context structure + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md2_context +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + size_t left; /*!< amount of data in buffer */ +} +mbedtls_md2_context; + +#else /* MBEDTLS_MD2_ALT */ +#include "md2_alt.h" +#endif /* MBEDTLS_MD2_ALT */ + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_init( mbedtls_md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_free( mbedtls_md2_context *ctx ); + +/** + * \brief Clone (the state of) an MD2 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \param ctx MD2 context + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD2 context setup + * + * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 + * + * \param ctx MD2 context + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD2( input buffer ) + * + * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md2.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md4.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md4.h new file mode 100644 index 0000000..0238c67 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md4.h @@ -0,0 +1,310 @@ +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef MBEDTLS_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** MD4 hardware accelerator failed */ +#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + +/** + * \brief MD4 context structure + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md4_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md4_context; + +#else /* MBEDTLS_MD4_ALT */ +#include "md4_alt.h" +#endif /* MBEDTLS_MD4_ALT */ + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_init( mbedtls_md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_free( mbedtls_md4_context *ctx ); + +/** + * \brief Clone (the state of) an MD4 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD4 context setup + * + * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD4( input buffer ) + * + * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md4.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h new file mode 100644 index 0000000..73e4dd2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md5.h @@ -0,0 +1,310 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** MD5 hardware accelerator failed */ +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md5_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h new file mode 100644 index 0000000..f33cdf6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/md_internal.h @@ -0,0 +1,90 @@ +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Name of the message digest */ + const char * name; + + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Output length of the digest function in bytes */ + unsigned char size; + + /** Block length of the digest function in bytes */ + unsigned char block_size; +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) +extern const mbedtls_md_info_t mbedtls_sha384_info; +#endif +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h new file mode 100644 index 0000000..3954b36 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h @@ -0,0 +1,149 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/** \} name SECTION: Module settings */ + +#define MBEDTLS_MEMORY_VERIFY_NONE 0 +#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) +#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) +#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call calloc() and free(). + * It sets the global mbedtls_calloc() and mbedtls_free() pointers + * to its own functions. + * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if + * MBEDTLS_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + */ +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void mbedtls_memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MBEDTLS_MEMORY_VERIFY_NONE) + * + * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, + * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS + */ +void mbedtls_memory_buffer_set_verify( int verify ); + +#if defined(MBEDTLS_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if MBEDTLS_MEMORY_BACKTRACE is defined. + */ +void mbedtls_memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param max_blocks Peak number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void mbedtls_memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Current number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param cur_blocks Current number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. + * Prints out full header information if MBEDTLS_MEMORY_DEBUG + * is defined. (Includes stack trace information for each block if + * MBEDTLS_MEMORY_BACKTRACE is defined as well). + * + * \return 0 if verified, 1 otherwise + */ +int mbedtls_memory_buffer_alloc_verify( void ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net.h new file mode 100644 index 0000000..6692188 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net.h @@ -0,0 +1,35 @@ +/** + * \file net.h + * + * \brief Deprecated header file that includes net_sockets.h + * + * \deprecated Superseded by mbedtls/net_sockets.h + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#include "mbedtls/net_sockets.h" +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h new file mode 100644 index 0000000..ceb7d5f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h @@ -0,0 +1,301 @@ +/** + * \file net_sockets.h + * + * \brief Network sockets abstraction layer to integrate Mbed TLS into a + * BSD-style sockets API. + * + * The network sockets module provides an example integration of the + * Mbed TLS library into a BSD sockets implementation. The module is + * intended to be an example of how Mbed TLS can be integrated into a + * networking stack, as well as to be Mbed TLS's network integration + * for its supported platforms. + * + * The module is intended only to be used with the Mbed TLS library and + * is not intended to be used by third party application software + * directly. + * + * The supported platforms are as follows: + * * Microsoft Windows and Windows CE + * * POSIX/Unix platforms including Linux, OS X + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#include +#include + +/** Failed to open a socket. */ +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 +/** The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 +/** Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 +/** Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 +/** Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A +/** Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C +/** Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E +/** Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 +/** Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 +/** Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 +/** The context is invalid, eg because it was free()ed. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 +/** Polling the net context failed. */ +#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 +/** Input invalid. */ +#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */ +#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct mbedtls_net_context +{ + int fd; /**< The underlying file descriptor */ +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init( mbedtls_net_context *ctx ); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \note Sets the socket in connected mode even with UDP. + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \note Regardless of the protocol, opens the sockets and binds it. + * In addition, make the socket listening if protocol is TCP. + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address, can be NULL + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written, + * can be NULL if client_ip is null + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to + * non-blocking and accept() would block. + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ); + +/** + * \brief Check and wait for the context to be ready for read/write + * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * + * \param ctx Socket to check + * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and + * MBEDTLS_NET_POLL_WRITE specifying the events + * to wait for: + * - If MBEDTLS_NET_POLL_READ is set, the function + * will return as soon as the net context is available + * for reading. + * - If MBEDTLS_NET_POLL_WRITE is set, the function + * will return as soon as the net context is available + * for writing. + * \param timeout Maximal amount of time to wait before returning, + * in milliseconds. If \c timeout is zero, the + * function returns immediately. If \c timeout is + * -1u, the function blocks potentially indefinitely. + * + * \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE + * on success or timeout, or a negative return code otherwise. + */ +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return The number of bytes received if successful. + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out. + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * Another negative error code (MBEDTLS_ERR_NET_xxx) + * for other failures. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ); + +/** + * \brief Closes down the connection and free associated data + * + * \param ctx The context to close + */ +void mbedtls_net_close( mbedtls_net_context *ctx ); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free( mbedtls_net_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h new file mode 100644 index 0000000..7f3e64a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h @@ -0,0 +1,182 @@ +/** + * \file nist_kw.h + * + * \brief This file provides an API for key wrapping (KW) and key wrapping with + * padding (KWP) as defined in NIST SP 800-38F. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * + * Key wrapping specifies a deterministic authenticated-encryption mode + * of operation, according to NIST SP 800-38F: Recommendation for + * Block Cipher Modes of Operation: Methods for Key Wrapping. Its + * purpose is to protect cryptographic keys. + * + * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. + * https://tools.ietf.org/html/rfc3394 + * https://tools.ietf.org/html/rfc5649 + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_NIST_KW_H +#define MBEDTLS_NIST_KW_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_KW_MODE_KW = 0, + MBEDTLS_KW_MODE_KWP = 1 +} mbedtls_nist_kw_mode_t; + +#if !defined(MBEDTLS_NIST_KW_ALT) +// Regular implementation +// + +/** + * \brief The key wrapping context-type definition. The key wrapping context is passed + * to the APIs called. + * + * \note The definition of this type may change in future library versions. + * Don't make any assumptions on this context! + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} mbedtls_nist_kw_context; + +#else /* MBEDTLS_NIST_key wrapping_ALT */ +#include "nist_kw_alt.h" +#endif /* MBEDTLS_NIST_KW_ALT */ + +/** + * \brief This function initializes the specified key wrapping context + * to make references valid and prepare the context + * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). + * + * \param ctx The key wrapping context to initialize. + * + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function initializes the key wrapping context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The key wrapping context. + * \param cipher The 128-bit block cipher to use. Only AES is supported. + * \param key The Key Encryption Key (KEK). + * \param keybits The KEK size in bits. This must be acceptable by the cipher. + * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. + * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers + * which are not supported. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ); + +/** + * \brief This function releases and clears the specified key wrapping context + * and underlying cipher sub-context. + * + * \param ctx The key wrapping context to clear. + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function encrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for encryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
  • + *
  • For KWP mode: any length between 1 and 2^32-1 inclusive.
+ * \param[out] output The buffer holding the output data. + *
  • For KW mode: Must be at least 8 bytes larger than \p in_len.
  • + *
  • For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of + * 8 bytes for KWP (15 bytes at most).
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size ); + +/** + * \brief This function decrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for decryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * The input must be a multiple of semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
  • + *
  • For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
+ * \param[out] output The buffer holding the output data. + * The output buffer's minimal length is 8 bytes shorter than \p in_len. + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, + * depending on how much padding was added to the data. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size); + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The key wrapping checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_nist_kw_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_NIST_KW_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h new file mode 100644 index 0000000..0186217 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/oid.h @@ -0,0 +1,649 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +/** OID is not found. */ +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E +/** output buffer is too small */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B + +/* This is for the benefit of X.509, but defined here in order to avoid + * having a "backwards" include of x.509.h here */ +/* + * X.509 extension types (internal, arbitrary values for bitsets) + */ +#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) +#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) +#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) +#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01" +#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Certificate policies + */ +#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/** + * Wi-SUN Alliance Field Area Network + * { iso(1) identified-organization(3) dod(6) internet(1) + * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } + */ +#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" + +#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ +#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ + +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct mbedtls_oid_descriptor_t +{ + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate certificate policies OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_certificate_policies( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h new file mode 100644 index 0000000..624d02d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/padlock.h @@ -0,0 +1,125 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PADLOCK_H +#define MBEDTLS_PADLOCK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +/** Input data should be aligned. */ +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define MBEDTLS_HAVE_ASAN +#endif +#endif + +/* Some versions of ASan result in errors about not enough registers */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ + !defined(MBEDTLS_HAVE_ASAN) + +#ifndef MBEDTLS_HAVE_X86 +#define MBEDTLS_HAVE_X86 +#endif + +#include + +#define MBEDTLS_PADLOCK_RNG 0x000C +#define MBEDTLS_PADLOCK_ACE 0x00C0 +#define MBEDTLS_PADLOCK_PHE 0x0C00 +#define MBEDTLS_PADLOCK_PMM 0x3000 + +#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal PadLock detection routine + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param feature The feature to detect + * + * \return non-zero if CPU has support for the feature, 0 otherwise + */ +int mbedtls_padlock_has_support( int feature ); + +/** + * \brief Internal PadLock AES-ECB block en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal PadLock AES-CBC buffer en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h new file mode 100644 index 0000000..daa71c8 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pem.h @@ -0,0 +1,153 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +/** No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 +/** PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 +/** RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 +/** Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 +/** Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 +/** Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 +/** \} name PEM Error codes */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct mbedtls_pem_context +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header The header string to write. + * \param footer The footer string to write. + * \param der_data The DER data to encode. + * \param der_len The length of the DER data \p der_data in Bytes. + * \param buf The buffer to write to. + * \param buf_len The length of the output buffer \p buf in Bytes. + * \param olen The address at which to store the total length written + * or required (if \p buf_len is not enough). + * + * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len + * to request the length of the resulting PEM buffer in + * `*olen`. + * + * \note This function may be called with overlapping \p der_data + * and \p buf buffers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large + * enough to hold the PEM buffer. In this case, `*olen` holds + * the required minimum size of \p buf. + * \return Another PEM or BASE64 error code on other kinds of failure. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h new file mode 100644 index 0000000..c9a13f4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk.h @@ -0,0 +1,918 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/** Memory allocation failed. */ +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 +/** Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 +/** Read/write of file failed. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 +/** Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 +/** Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 +/** Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 +/** Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 +/** The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 +/** The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 +/** Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 +/** Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 +/** The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 + +/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** PK hardware accelerator failed. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, + MBEDTLS_PK_OPAQUE, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct mbedtls_pk_rsassa_pss_options +{ + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Maximum size of a signature made by mbedtls_pk_sign(). + */ +/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature + * size among the supported signature types. Do it by starting at 0, + * then incrementally increasing to be large enough for each supported + * signature mechanism. + * + * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled + * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C + * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). + */ +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 + +#if ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ) && \ + MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For RSA, the signature can be as large as the bignum module allows. + * For RSA_ALT, the signature size is not necessarily tied to what the + * bignum module can do, but in the absence of any specific setting, + * we use that (rsa_alt_sign_wrap in pk_wrap will check). */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For ECDSA, the ecdsa module exports a constant for the maximum + * signature size. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made + * through the PSA API in the PSA representation. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE +#endif + +#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* The Mbed TLS representation is different for ECDSA signatures: + * PSA uses the raw concatenation of r and s, + * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). + * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the + * types, lengths (represented by up to 2 bytes), and potential leading + * zeros of the INTEGERs and the SEQUENCE. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 ) +#endif +#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct mbedtls_pk_debug_item +{ + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * pk_ctx; /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * rs_ctx; /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + * + * \note For contexts that have been set up with + * mbedtls_pk_setup_opaque(), this does not free the underlying + * PSA key and you still need to call psa_destroy_key() + * independently if you want to destroy that key. + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Initialize a PK context to wrap a PSA key. + * + * \note This function replaces mbedtls_pk_setup() for contexts + * that wrap a (possibly opaque) PSA key instead of + * storing and manipulating the key material directly. + * + * \param ctx The context to initialize. It must be empty (type NONE). + * \param key The PSA key to wrap, which must hold an ECC key pair + * (see notes below). + * + * \note The wrapped key must remain valid as long as the + * wrapping PK context is in use, that is at least between + * the point this function is called and the point + * mbedtls_pk_free() is called on this context. The wrapped + * key might then be independently used or destroyed. + * + * \note This function is currently only available for ECC key + * pairs (that is, ECC keys containing private key material). + * Support for other key types may be added later. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input + * (context already used, invalid key identifier). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an + * ECC key pair. + * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, + const psa_key_id_t key ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign()) + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(). + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return \c 0 on success (keys were checked and match each other). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not + * be checked - in that case they may or may not match. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. + * \return Another non-zero value if the keys do not match. + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx The PK context to use. It must have been initialized. + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning This function can only be used when the type of the context, as + * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA. + * Ensuring that is the caller's responsibility. + * Alternatively, you can check whether this function returns NULL. + * + * \return The internal RSA context held by the PK context, or NULL. + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + switch( mbedtls_pk_get_type( &pk ) ) + { + case MBEDTLS_PK_RSA: + return( (mbedtls_rsa_context *) (pk).pk_ctx ); + default: + return( NULL ); + } +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning This function can only be used when the type of the context, as + * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY, + * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA. + * Ensuring that is the caller's responsibility. + * Alternatively, you can check whether this function returns NULL. + * + * \return The internal EC context held by the PK context, or NULL. + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + switch( mbedtls_pk_get_type( &pk ) ) + { + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); + default: + return( NULL ); + } +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the private key from + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk The PK context to fill. It must have been initialized + * but not set up. + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key PK context which must contain a valid public or private key. + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Turn an EC key into an opaque one. + * + * \warning This is a temporary utility function for tests. It might + * change or be removed at any time without notice. + * + * \note Only ECDSA keys are supported so far. Signing with the + * specified hash is the only allowed use of that key. + * + * \param pk Input: the EC key to import to a PSA key. + * Output: a PK context wrapping that PSA key. + * \param key Output: a PSA key identifier. + * It's the caller's responsibility to call + * psa_destroy_key() on that key identifier after calling + * mbedtls_pk_free() on the PK context. + * \param hash_alg The hash algorithm to allow for use with that key. + * + * \return \c 0 if successful. + * \return An Mbed TLS error code otherwise. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_id_t *key, + psa_algorithm_t hash_alg ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h new file mode 100644 index 0000000..47f7767 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pk_internal.h @@ -0,0 +1,140 @@ +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/pk.h" + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +extern const mbedtls_pk_info_t mbedtls_pk_opaque_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h new file mode 100644 index 0000000..3530ee1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs11.h @@ -0,0 +1,246 @@ +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PKCS11_H +#define MBEDTLS_PKCS11_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS11_C) + +#include "mbedtls/x509_crt.h" + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) + +/** + * Context for PKCS #11 private keys. + */ +typedef struct mbedtls_pkcs11_context +{ + pkcs11h_certificate_t pkcs11h_cert; + int len; +} mbedtls_pkcs11_context; + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * Initialize a mbedtls_pkcs11_context. + * (Just making memory references valid.) + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + */ +MBEDTLS_DEPRECATED void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); + +/** + * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * + * \param cert X.509 certificate to fill + * \param pkcs11h_cert PKCS #11 helper certificate + * + * \return 0 on success. + */ +MBEDTLS_DEPRECATED int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, + pkcs11h_certificate_t pkcs11h_cert ); + +/** + * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the + * mbedtls_pkcs11_context will take over control of the certificate, freeing it when + * done. + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * + * \param priv_key Private key structure to fill. + * \param pkcs11_cert PKCS #11 helper certificate + * + * \return 0 on success + */ +MBEDTLS_DEPRECATED int mbedtls_pkcs11_priv_key_bind( + mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ); + +/** + * Free the contents of the given private key context. Note that the structure + * itself is not freed. + * + * \deprecated This function is deprecated and will be removed in a + * future version of the library. + * + * \param priv_key Private key structure to cleanup + */ +MBEDTLS_DEPRECATED void mbedtls_pkcs11_priv_key_free( + mbedtls_pkcs11_context *priv_key ); + +/** + * \brief Do an RSA private key decrypt, then remove the message + * padding + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param input buffer holding the encrypted data + * \param output buffer that will hold the plaintext + * \param olen will contain the plaintext length + * \param output_max_len maximum length of the output buffer + * + * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The output buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise + * an error is thrown. + */ +MBEDTLS_DEPRECATED int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief Do a private RSA to sign a message digest + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx PKCS #11 context + * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature + * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) + * \param hashlen message digest length (for MBEDTLS_MD_NONE only) + * \param hash buffer holding the message digest + * \param sig buffer that will hold the ciphertext + * + * \return 0 if the signing operation was successful, + * or an MBEDTLS_ERR_RSA_XXX error code + * + * \note The "sig" buffer must be as large as the size + * of ctx->N (eg. 128 bytes if RSA-1024 is used). + */ +MBEDTLS_DEPRECATED int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * SSL/TLS wrappers for PKCS#11 functions + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + */ +MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, + int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ) +{ + return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, + output_max_len ); +} + +/** + * \brief This function signs a message digest using RSA. + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx The PKCS #11 context. + * \param f_rng The RNG function. This parameter is unused. + * \param p_rng The RNG context. This parameter is unused. + * \param mode The operation to run. This must be set to + * MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's + * signature. + * \param md_alg The message digest algorithm. One of the MBEDTLS_MD_XXX + * must be passed to this function and MBEDTLS_MD_NONE can be + * used for signing raw data. + * \param hashlen The message digest length (for MBEDTLS_MD_NONE only). + * \param hash The buffer holding the message digest. + * \param sig The buffer that will hold the ciphertext. + * + * \return \c 0 if the signing operation was successful. + * \return A non-zero error code on failure. + * + * \note The \p sig buffer must be as large as the size of + * ctx->N. For example, 128 bytes if RSA-1024 is + * used. + */ +MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_sign( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ) +{ + ((void) f_rng); + ((void) p_rng); + return mbedtls_pkcs11_sign( (mbedtls_pkcs11_context *) ctx, mode, md_alg, + hashlen, hash, sig ); +} + +/** + * This function gets the length of the private key. + * + * \deprecated This function is deprecated and will be removed in a future + * version of the library. + * + * \param ctx The PKCS #11 context. + * + * \return The length of the private key. + */ +MBEDTLS_DEPRECATED static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) +{ + return ( (mbedtls_pkcs11_context *) ctx )->len; +} + +#undef MBEDTLS_DEPRECATED + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PKCS11_C */ + +#endif /* MBEDTLS_PKCS11_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h new file mode 100644 index 0000000..d9e85b1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h @@ -0,0 +1,140 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PKCS12_H +#define MBEDTLS_PKCS12_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" +#include "mbedtls/cipher.h" +#include "mbedtls/asn1.h" + +#include + +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 +/** Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 +/** PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure + * \param mode either #MBEDTLS_PKCS12_PBE_ENCRYPT or + * #MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd Latin1-encoded password used. This may only be \c NULL when + * \p pwdlen is 0. No null terminator should be used. + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an initialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length of buffer to fill + * \param pwd The password to use. For compliance with PKCS#12 §B.1, this + * should be a BMPString, i.e. a Unicode string where each + * character is encoded as 2 bytes in big-endian order, with + * no byte order mark and with a null terminator (i.e. the + * last two bytes should be 0x00 0x00). + * \param pwdlen length of the password (may be 0). + * \param salt Salt buffer to use This may only be \c NULL when + * \p saltlen is 0. + * \param saltlen length of the salt (may be zero) + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be + * #MBEDTLS_PKCS12_DERIVE_KEY, #MBEDTLS_PKCS12_DERIVE_IV or + * #MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h new file mode 100644 index 0000000..696930f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h @@ -0,0 +1,111 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PKCS5_H +#define MBEDTLS_PKCS5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" +#include "mbedtls/md.h" + +#include +#include + +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 +/** Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 +/** Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h new file mode 100644 index 0000000..06dd192 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform.h @@ -0,0 +1,421 @@ +/** + * \file platform.h + * + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. + * + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +/** Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 +/** The requested feature is not supported by the platform */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* The older Microsoft Windows common runtime provides non-conforming + * implementations of some standard library functions, including snprintf + * and vsnprintf. This affects MSVC and MinGW builds. + */ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF +#endif + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#if defined(MBEDTLS_HAVE_TIME) +#include +#endif +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/** \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free. + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); + +/** + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom + * \c snprintf function pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for vsnprintf + * + * The vsnprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ); +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#include +extern int (*mbedtls_vsnprintf)( char * s, size_t n, const char * format, va_list arg ); + +/** + * \brief Set your own snprintf function pointer + * + * \param vsnprintf_func The \c vsnprintf function implementation + * + * \return \c 0 + */ +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, va_list arg ) ); +#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO +#else +#define mbedtls_vsnprintf vsnprintf +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct mbedtls_platform_context +{ + char dummy; /**< A placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else +#include "platform_alt.h" +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform-specific initialization + * operations. + * + * \note This function should be called before any other library functions. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h new file mode 100644 index 0000000..9405571 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h @@ -0,0 +1,72 @@ +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h new file mode 100644 index 0000000..cd112ab --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h @@ -0,0 +1,283 @@ +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_time.h" +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) + +#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) +/* Allow the user to define MBEDTLS_PARAM_FAILED to something like assert + * (which is what our config.h suggests). */ +#include +#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ + +#if defined(MBEDTLS_PARAM_FAILED) +/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h. + * + * This flag can be used to check whether it is safe to assume that + * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed(). + */ +#define MBEDTLS_PARAM_FAILED_ALT + +#elif defined(MBEDTLS_CHECK_PARAMS_ASSERT) +#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) +#define MBEDTLS_PARAM_FAILED_ALT + +#else /* MBEDTLS_PARAM_FAILED */ +#define MBEDTLS_PARAM_FAILED( cond ) \ + mbedtls_param_failed( #cond, __FILE__, __LINE__ ) + +/** + * \brief User supplied callback function for parameter validation failure. + * See #MBEDTLS_CHECK_PARAMS for context. + * + * This function will be called unless an alternative treatment + * is defined through the #MBEDTLS_PARAM_FAILED macro. + * + * This function can return, and the operation will be aborted, or + * alternatively, through use of setjmp()/longjmp() can resume + * execution in the application code. + * + * \param failure_condition The assertion that didn't hold. + * \param file The file where the assertion failed. + * \param line The line in the file where the assertion failed. + */ +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ); +#endif /* MBEDTLS_PARAM_FAILED */ + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return( ret ); \ + } \ + } while( 0 ) + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE( cond ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return; \ + } \ + } while( 0 ) + +#else /* MBEDTLS_CHECK_PARAMS */ + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +#endif /* MBEDTLS_CHECK_PARAMS */ + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here + * to avoid conflict with other headers which define and use + * it, too. We might want to move all these definitions here at + * some point for uniformity. */ +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_string_constant_t) ( VAL ) ) +MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) ) +#undef MBEDTLS_DEPRECATED +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* Implementation of the check-return facility. + * See the user documentation in config.h. + * + * Do not use this macro directly to annotate function: instead, + * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL + * depending on how important it is to check the return value. + */ +#if !defined(MBEDTLS_CHECK_RETURN) +#if defined(__GNUC__) +#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) +#elif defined(_MSC_VER) && _MSC_VER >= 1700 +#include +#define MBEDTLS_CHECK_RETURN _Check_return_ +#else +#define MBEDTLS_CHECK_RETURN +#endif +#endif + +/** Critical-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that its return value should be checked in all applications. + * Omitting the check is very likely to indicate a bug in the application + * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN + * is implemented for the compiler in use. + * + * \note The use of this macro is a work in progress. + * This macro may be added to more functions in the future. + * Such an extension is not considered an API break, provided that + * there are near-unavoidable circumstances under which the function + * can fail. For example, signature/MAC/AEAD verification functions, + * and functions that require a random generator, are considered + * return-check-critical. + */ +#define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN + +/** Ordinary-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that its return value should be generally be checked in portable + * applications. Omitting the check will result in a compile-time warning if + * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and + * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration. + * + * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value + * of a function that is annotated with #MBEDTLS_CHECK_RETURN. + * + * \note The use of this macro is a work in progress. + * This macro will be added to more functions in the future. + * Eventually this should appear before most functions returning + * an error code (as \c int in the \c mbedtls_xxx API or + * as ::psa_status_t in the \c psa_xxx API). + */ +#if defined(MBEDTLS_CHECK_RETURN_WARNING) +#define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN +#else +#define MBEDTLS_CHECK_RETURN_TYPICAL +#endif + +/** Benign-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that it is rarely useful to check its return value. + * + * This macro has an empty expansion. It exists for documentation purposes: + * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function + * has been analyzed for return-check usefulness, whereas the lack of + * an annotation indicates that the function has not been analyzed and its + * return-check usefulness is unknown. + */ +#define MBEDTLS_CHECK_RETURN_OPTIONAL + +/** \def MBEDTLS_IGNORE_RETURN + * + * Call this macro with one argument, a function call, to suppress a warning + * from #MBEDTLS_CHECK_RETURN due to that function call. + */ +#if !defined(MBEDTLS_IGNORE_RETURN) +/* GCC doesn't silence the warning with just (void)(result). + * (void)!(result) is known to work up at least up to GCC 10, as well + * as with Clang and MSVC. + * + * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html + * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34 + */ +#define MBEDTLS_IGNORE_RETURN(result) ( (void) !( result ) ) +#endif + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h new file mode 100644 index 0000000..a69ede9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h @@ -0,0 +1,194 @@ +/** + * \file poly1305.h + * + * \brief This file contains Poly1305 definitions and functions. + * + * Poly1305 is a one-time message authenticator that can be used to + * authenticate messages. Poly1305-AES was created by Daniel + * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic + * Poly1305 algorithm (not tied to AES) was also standardized in RFC + * 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_POLY1305_H +#define MBEDTLS_POLY1305_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/** Invalid input parameter(s). */ +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 + +/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +/** Feature not available. For example, s part of the API is not implemented. */ +#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 + +/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used. + */ +/** Poly1305 hardware accelerator failed. */ +#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct mbedtls_poly1305_context +{ + uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t acc[5]; /** The accumulator number. */ + uint8_t queue[16]; /** The current partial block of data. */ + size_t queue_len; /** The number of bytes stored in 'queue'. */ +} +mbedtls_poly1305_context; + +#else /* MBEDTLS_POLY1305_ALT */ +#include "poly1305_alt.h" +#endif /* MBEDTLS_POLY1305_ALT */ + +/** + * \brief This function initializes the specified Poly1305 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by a call to + * \c mbedtls_poly1305_starts(), then one or more calls to + * \c mbedtls_poly1305_update(), then one call to + * \c mbedtls_poly1305_finish(), then finally + * \c mbedtls_poly1305_free(). + * + * \param ctx The Poly1305 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function releases and clears the specified + * Poly1305 context. + * + * \param ctx The Poly1305 context to clear. This may be \c NULL, in which + * case this function is a no-op. If it is not \c NULL, it must + * point to an initialized Poly1305 context. + */ +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function sets the one-time authentication key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param ctx The Poly1305 context to which the key should be bound. + * This must be initialized. + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This functions feeds an input buffer into an ongoing + * Poly1305 computation. + * + * It is called between \c mbedtls_cipher_poly1305_starts() and + * \c mbedtls_cipher_poly1305_finish(). + * It can be called repeatedly to process a stream of data. + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function generates the Poly1305 Message + * Authentication Code (MAC). + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param mac The buffer to where the MAC is written. This must + * be a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function calculates the Poly1305 MAC of the input + * buffer with the provided key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * \param mac The buffer to where the MAC is written. This must be + * a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_poly1305_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_POLY1305_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h new file mode 100644 index 0000000..af7a809 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h @@ -0,0 +1,512 @@ +/** + * \file psa_util.h + * + * \brief Utility functions for the use of the PSA Crypto library. + * + * \warning This function is not part of the public API and may + * change at any time. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_PSA_UTIL_H +#define MBEDTLS_PSA_UTIL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +#include "psa/crypto.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" +#include "mbedtls/pk.h" +#include "mbedtls/oid.h" + +#include + +/* Translations for symmetric crypto. */ + +static inline psa_key_type_t mbedtls_psa_translate_cipher_type( + mbedtls_cipher_type_t cipher ) +{ + switch( cipher ) + { + case MBEDTLS_CIPHER_AES_128_CCM: + case MBEDTLS_CIPHER_AES_192_CCM: + case MBEDTLS_CIPHER_AES_256_CCM: + case MBEDTLS_CIPHER_AES_128_GCM: + case MBEDTLS_CIPHER_AES_192_GCM: + case MBEDTLS_CIPHER_AES_256_GCM: + case MBEDTLS_CIPHER_AES_128_CBC: + case MBEDTLS_CIPHER_AES_192_CBC: + case MBEDTLS_CIPHER_AES_256_CBC: + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + return( PSA_KEY_TYPE_AES ); + + /* ARIA not yet supported in PSA. */ + /* case MBEDTLS_CIPHER_ARIA_128_CCM: + case MBEDTLS_CIPHER_ARIA_192_CCM: + case MBEDTLS_CIPHER_ARIA_256_CCM: + case MBEDTLS_CIPHER_ARIA_128_GCM: + case MBEDTLS_CIPHER_ARIA_192_GCM: + case MBEDTLS_CIPHER_ARIA_256_GCM: + case MBEDTLS_CIPHER_ARIA_128_CBC: + case MBEDTLS_CIPHER_ARIA_192_CBC: + case MBEDTLS_CIPHER_ARIA_256_CBC: + return( PSA_KEY_TYPE_ARIA ); */ + + default: + return( 0 ); + } +} + +static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode( + mbedtls_cipher_mode_t mode, size_t taglen ) +{ + switch( mode ) + { + case MBEDTLS_MODE_ECB: + return( PSA_ALG_ECB_NO_PADDING ); + case MBEDTLS_MODE_GCM: + return( PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, taglen ) ); + case MBEDTLS_MODE_CCM: + return( PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, taglen ) ); + case MBEDTLS_MODE_CBC: + if( taglen == 0 ) + return( PSA_ALG_CBC_NO_PADDING ); + else + return( 0 ); + default: + return( 0 ); + } +} + +static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation( + mbedtls_operation_t op ) +{ + switch( op ) + { + case MBEDTLS_ENCRYPT: + return( PSA_KEY_USAGE_ENCRYPT ); + case MBEDTLS_DECRYPT: + return( PSA_KEY_USAGE_DECRYPT ); + default: + return( 0 ); + } +} + +/* Translations for hashing. */ + +static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg ) +{ + switch( md_alg ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( PSA_ALG_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( PSA_ALG_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( PSA_ALG_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( PSA_ALG_SHA_1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( PSA_ALG_SHA_224 ); + case MBEDTLS_MD_SHA256: + return( PSA_ALG_SHA_256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( PSA_ALG_SHA_384 ); + case MBEDTLS_MD_SHA512: + return( PSA_ALG_SHA_512 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( PSA_ALG_RIPEMD160 ); +#endif + case MBEDTLS_MD_NONE: + return( 0 ); + default: + return( 0 ); + } +} + +/* Translations for ECC. */ + +static inline int mbedtls_psa_get_ecc_oid_from_id( + psa_ecc_family_t curve, size_t bits, + char const **oid, size_t *oid_len ) +{ + switch( curve ) + { + case PSA_ECC_FAMILY_SECP_R1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case 384: + *oid = MBEDTLS_OID_EC_GRP_SECP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case 521: + *oid = MBEDTLS_OID_EC_GRP_SECP521R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + } + break; + case PSA_ECC_FAMILY_SECP_K1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + } + break; + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_BP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case 384: + *oid = MBEDTLS_OID_EC_GRP_BP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case 512: + *oid = MBEDTLS_OID_EC_GRP_BP512R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + } + break; + } + (void) oid; + (void) oid_len; + return( -1 ); +} + +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1 + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 521 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 521 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 512 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 512 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + + +/* Translations for PK layer */ + +static inline int mbedtls_psa_err_translate_pk( psa_status_t status ) +{ + switch( status ) + { + case PSA_SUCCESS: + return( 0 ); + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + case PSA_ERROR_INSUFFICIENT_ENTROPY: + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + case PSA_ERROR_BAD_STATE: + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + /* All other failures */ + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + case PSA_ERROR_CORRUPTION_DETECTED: + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + default: /* We return the same as for the 'other failures', + * but list them separately nonetheless to indicate + * which failure conditions we have considered. */ + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + } +} + +/* Translations for ECC */ + +/* This function transforms an ECC group identifier from + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * into a PSA ECC group identifier. */ +#if defined(MBEDTLS_ECP_C) +static inline psa_key_type_t mbedtls_psa_parse_tls_ecc_group( + uint16_t tls_ecc_grp_reg_id, size_t *bits ) +{ + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( tls_ecc_grp_reg_id ); + if( curve_info == NULL ) + return( 0 ); + return( PSA_KEY_TYPE_ECC_KEY_PAIR( + mbedtls_ecc_group_to_psa( curve_info->grp_id, bits ) ) ); +} +#endif /* MBEDTLS_ECP_C */ + +/* This function takes a buffer holding an EC public key + * exported through psa_export_public_key(), and converts + * it into an ECPoint structure to be put into a ClientKeyExchange + * message in an ECDHE exchange. + * + * Both the present and the foreseeable future format of EC public keys + * used by PSA have the ECPoint structure contained in the exported key + * as a subbuffer, and the function merely selects this subbuffer instead + * of making a copy. + */ +static inline int mbedtls_psa_tls_psa_ec_to_ecpoint( unsigned char *src, + size_t srclen, + unsigned char **dst, + size_t *dstlen ) +{ + *dst = src; + *dstlen = srclen; + return( 0 ); +} + +/* This function takes a buffer holding an ECPoint structure + * (as contained in a TLS ServerKeyExchange message for ECDHE + * exchanges) and converts it into a format that the PSA key + * agreement API understands. + */ +static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src, + size_t srclen, + unsigned char *dst, + size_t dstlen, + size_t *olen ) +{ + if( srclen > dstlen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( dst, src, srclen ); + *olen = srclen; + return( 0 ); +} + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* Expose whatever RNG the PSA subsystem uses to applications using the + * mbedtls_xxx API. The declarations and definitions here need to be + * consistent with the implementation in library/psa_crypto_random_impl.h. + * See that file for implementation documentation. */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + +/* The type of a `f_rng` random generator function that many library functions + * take. + * + * This type name is not part of the Mbed TLS stable API. It may be renamed + * or moved without warning. + */ +typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_size ); + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + +/** The random generator function for the PSA subsystem. + * + * This function is suitable as the `f_rng` random generator function + * parameter of many `mbedtls_xxx` functions. Use #MBEDTLS_PSA_RANDOM_STATE + * to obtain the \p p_rng parameter. + * + * The implementation of this function depends on the configuration of the + * library. + * + * \note Depending on the configuration, this may be a function or + * a pointer to a function. + * + * \note This function may only be used if the PSA crypto subsystem is active. + * This means that you must call psa_crypto_init() before any call to + * this function, and you must not call this function after calling + * mbedtls_psa_crypto_free(). + * + * \param p_rng The random generator context. This must be + * #MBEDTLS_PSA_RANDOM_STATE. No other state is + * supported. + * \param output The buffer to fill. It must have room for + * \c output_size bytes. + * \param output_size The number of bytes to write to \p output. + * This function may fail if \p output_size is too + * large. It is guaranteed to accept any output size + * requested by Mbed TLS library functions. The + * maximum request size depends on the library + * configuration. + * + * \return \c 0 on success. + * \return An `MBEDTLS_ERR_ENTROPY_xxx`, + * `MBEDTLS_ERR_PLATFORM_xxx, + * `MBEDTLS_ERR_CTR_DRBG_xxx` or + * `MBEDTLS_ERR_HMAC_DRBG_xxx` on error. + */ +int mbedtls_psa_get_random( void *p_rng, + unsigned char *output, + size_t output_size ); + +/** The random generator state for the PSA subsystem. + * + * This macro expands to an expression which is suitable as the `p_rng` + * random generator state parameter of many `mbedtls_xxx` functions. + * It must be used in combination with the random generator function + * mbedtls_psa_get_random(). + * + * The implementation of this macro depends on the configuration of the + * library. Do not make any assumption on its nature. + */ +#define MBEDTLS_PSA_RANDOM_STATE NULL + +#else /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; +static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random; +#elif defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; +static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random; +#endif +extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state; + +#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state + +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#endif /* MBEDTLS_PSA_UTIL_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h new file mode 100644 index 0000000..63270d1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h @@ -0,0 +1,236 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used. + */ +/** RIPEMD160 hardware accelerator failed */ +#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct mbedtls_ripemd160_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_ripemd160_context; + +#else /* MBEDTLS_RIPEMD160_ALT */ +#include "ripemd160_alt.h" +#endif /* MBEDTLS_RIPEMD160_ALT */ + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clone (the state of) an RIPEMD-160 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief RIPEMD-160 context setup + * + * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( + mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( + mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( + mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( + mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ripemd160_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_ripemd160.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h new file mode 100644 index 0000000..062df73 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h @@ -0,0 +1,1351 @@ +/** + * \file rsa.h + * + * \brief This file provides an API for the RSA public-key cryptosystem. + * + * The RSA public-key cryptosystem is defined in Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption + * and Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" +#include "mbedtls/md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * RSA Error codes + */ +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 +/** Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 +/** Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 +/** Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 +/** The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 +/** The private key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 +/** The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 +/** The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 +/** The random generator failed to generate non-zeros. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 + +/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used. + */ +/** The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 + +/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** RSA hardware accelerator failed. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implementations in the PK layers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +/** + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. + */ +typedef struct mbedtls_rsa_context +{ + int ver; /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ + size_t len; /*!< The size of \p N in Bytes. */ + + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ + + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ + + mbedtls_mpi DP; /*!< D % (P - 1). */ + mbedtls_mpi DQ; /*!< D % (Q - 1). */ + mbedtls_mpi QP; /*!< 1 / (Q % P). */ + + mbedtls_mpi RN; /*!< cached R^2 mod N. */ + + mbedtls_mpi RP; /*!< cached R^2 mod P. */ + mbedtls_mpi RQ; /*!< cached R^2 mod Q. */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized iff ver != 0. */ + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +#else /* MBEDTLS_RSA_ALT */ +#include "rsa_alt.h" +#endif /* MBEDTLS_RSA_ALT */ + +/** + * \brief This function initializes an RSA context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overridden by calling specific + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overridden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overridden. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of ::mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. It is unused + * otherwise. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param D The private exponent. This may be \c NULL. + * \param E The public exponent. This may be \c NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. + * \param D The private exponent. This may be \c NULL. + * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. + * \param E The public exponent. This may be \c NULL. + * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus. + * This may be \c NULL if this field need not be exported. + * \param P The MPI to hold the first prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param Q The MPI to hold the second prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param D The MPI to hold the private exponent. + * This may be \c NULL if this field need not be exported. + * \param E The MPI to hold the public exponent. + * This may be \c NULL if this field need not be exported. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, + * or \c NULL if this field need not be exported. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, + * or \c NULL if this field need not be exported. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, + * or \c NULL if this field need not be exported. + * \param E_len The size of the buffer for the public exponent. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold \c D modulo `P-1`, + * or \c NULL if it need not be exported. + * \param DQ The MPI to hold \c D modulo `Q-1`, + * or \c NULL if it need not be exported. + * \param QP The MPI to hold modular inverse of \c Q modulo \c P, + * or \c NULL if it need not be exported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The initialized RSA context to be configured. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \param ctx The initialized RSA context used to hold the key. + * \param f_rng The RNG function to be used for key generation. + * This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't need a context. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent to use. For example, \c 65537. + * This must be odd and greater than \c 1. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The initialized RSA context holding the public key. + * \param prv The initialized RSA context holding the private key. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The initialized RSA context to use. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentiation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function, used for blinding. It is discouraged + * and deprecated to pass \c NULL here, in which case + * blinding will be omitted. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or if \p f_rng doesn't need a context. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is mandatory for PKCS#1 v2.1 padding + * encoding, and for PKCS#1 v1.5 padding encoding when used + * with \p mode set to #MBEDTLS_RSA_PUBLIC. For PKCS#1 v1.5 + * padding encoding and \p mode set to #MBEDTLS_RSA_PRIVATE, + * it is used for blinding and should be provided in this + * case; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng is \c NULL or if \p f_rng doesn't + * need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is needed for padding generation + * if \p mode is #MBEDTLS_RSA_PUBLIC. If \p mode is + * #MBEDTLS_RSA_PRIVATE (discouraged), it is used for + * blinding and should be provided; see mbedtls_rsa_private(). + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng is \c NULL or if \p f_rng + * doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and must be provided. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param ilen The length of the plaintext buffer \p input in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. If the padding mode is PKCS#1 v2.1, + * this must be provided. If the padding mode is PKCS#1 v1.5 and + * \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding + * and should be provided; see mbedtls_rsa_private() for more + * more. It is ignored otherwise. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \c hash_id set in \p ctx (when calling + * mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding() + * afterwards) selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * + * \note This function enforces that the provided salt length complies + * with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 v2.2) §9.1.1 + * step 3. The constraint is that the hash length plus the salt + * length plus 2 bytes must be at most the key length. If this + * constraint is not met, this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param saltlen The length of the salt that should be used. + * If passed #MBEDTLS_RSA_SALT_LEN_ANY, the function will use + * the largest possible salt length up to the hash length, + * which is the largest permitted by some standards including + * FIPS 186-4 §5.5. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \c hash_id set in \p ctx (when calling + * mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding() + * afterwards) selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * + * \note This function always uses the maximum possible salt size, + * up to the length of the payload hash. This choice of salt + * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 + * v2.2) §9.1.1 step 3. Furthermore this function enforces a + * minimum salt size which is the hash size minus 2 bytes. If + * this minimum size is too large given the key size (the salt + * size, plus the hash size, plus 2 bytes must be no more than + * the key size in bytes), this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * \note The \c hash_id set in \p ctx (when calling + * mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding() + * afterwards) selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. If the \c hash_id set in \p ctx is + * #MBEDTLS_MD_NONE, the \p md_alg parameter is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \c hash_id set in \p ctx (when calling + * mbedtls_rsa_init() or by calling mbedtls_rsa_set_padding() + * afterwards) is ignored. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param mgf1_hash_id The message digest algorithm used for the + * verification operation and the mask generation + * function (MGF1). For more details on the encoding + * operation and the mask generation function, consult + * RFC-3447: Public-Key Cryptography Standards + * (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. This must be initialized. + * \param src The source context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); + +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA context to free. May be \c NULL, in which case + * this function is a no-op. If it is not \c NULL, it must + * point to an initialized RSA context. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h new file mode 100644 index 0000000..d55492b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/rsa_internal.h @@ -0,0 +1,224 @@ +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa_internal.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h new file mode 100644 index 0000000..4c3251b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h @@ -0,0 +1,352 @@ +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** SHA-1 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 +/** SHA-1 input data was malformed. */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_sha1_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +/** + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized. + * \param data The data block being processed. + * This must be a readable buffer of length \c 64 bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of size \c 20 Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h new file mode 100644 index 0000000..5b54be2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h @@ -0,0 +1,300 @@ +/** + * \file sha256.h + * + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** SHA-256 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 +/** SHA-256 input data was malformed. */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct mbedtls_sha256_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +} +mbedtls_sha256_context; + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The context to use. This must be initialized. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to use. This must be + * initialized and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must + * be a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be either + * \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h new file mode 100644 index 0000000..cca47c2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h @@ -0,0 +1,316 @@ +/** + * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. + * + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** SHA-512 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 +/** SHA-512 input data was malformed. */ +#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). + */ +typedef struct mbedtls_sha512_context +{ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ +#if !defined(MBEDTLS_SHA512_NO_SHA384) + int is384; /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ +#endif +} +mbedtls_sha512_context; + +#else /* MBEDTLS_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* MBEDTLS_SHA512_ALT */ + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must point to an initialized + * SHA-512 context. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be + * either \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * This function is for internal use only. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This + * must be a readable buffer of length \c 128 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512 or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will fail to work. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of length \c 128 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. This must be + * a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. This must be a + * readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will fail to work. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h new file mode 100644 index 0000000..5064ec5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h @@ -0,0 +1,4427 @@ +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SSL_H +#define MBEDTLS_SSL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" + +#include "mbedtls/ssl_ciphersuites.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_crl.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due + * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap + * in functionality that access to ecdh_ctx structure is needed for + * MBEDTLS_ECDSA_C which does not seem correct. + */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdh.h" +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and will be removed in the next major revision of the library" +#endif + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "Record compression support via MBEDTLS_ZLIB_SUPPORT is deprecated and cannot be used if MBEDTLS_DEPRECATED_REMOVED is set" +#endif + +#include "zlib.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * SSL Error codes + */ +/** The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 +/** Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 +/** An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 +/** The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 +/** An unknown cipher was received. */ +#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 +/** The server has no ciphersuites in common with the client. */ +#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 +/** No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 +/** No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 +/** Our own certificate(s) is/are too large to send in an SSL message. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 +/** The own certificate is not set, but needed by the server. */ +#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 +/** The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 +/** No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 +/** An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 +/** A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 +/** Verification of our peer failed. */ +#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 +/** The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 +/** Processing of the ClientHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 +/** Processing of the ServerHello handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 +/** Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 +/** Processing of the CertificateRequest handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 +/** Processing of the ServerKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 +/** Processing of the ServerHelloDone handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 +/** Processing of the ClientKeyExchange handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 +/** Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 +/** Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 +/** Processing of the CertificateVerify handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 +/** Processing of the ChangeCipherSpec handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 +/** Processing of the Finished handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 +/** Memory allocation failed */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 +/** Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 +/** Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 +/** Processing of the compression / decompression failed */ +#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 +/** Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 +/** Processing of the NewSessionTicket handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 +/** Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 +/** Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 +/** Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 +/** Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 +/** A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 +/** Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 +/** DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 +/** A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 +/** None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ +#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 +/** No data of requested type currently available on underlying transport. */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 +/** Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 +/** The operation timed out. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 +/** The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 +/** Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 +/** The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 +/** Couldn't set the hash for verifying CertificateVerify */ +#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 +/** Internal-only message signaling that further message-processing should be done */ +#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 +/** The asynchronous operation is not completed yet. */ +#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 +/** Internal-only message signaling that a message arrived early. */ +#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 +/** An encrypted DTLS-frame with an unexpected CID was received. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_CID -0x6000 +/** An operation failed due to an unexpected version or configuration. */ +#define MBEDTLS_ERR_SSL_VERSION_MISMATCH -0x5F00 +/** A cryptographic operation is in progress. Try again later. */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 +/** Invalid value in SSL config */ +#define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 + +/* + * Various constants + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ +#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ +#define MBEDTLS_SSL_MINOR_VERSION_4 4 /*!< TLS v1.3 (experimental) */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ +#define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ + +#define MBEDTLS_SSL_MAX_ALPN_LIST_LEN 65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 +#define MBEDTLS_SSL_IS_FALLBACK 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_CID_DISABLED 0 +#define MBEDTLS_SSL_CID_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 +#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 + +#define MBEDTLS_SSL_ARC4_ENABLED 0 +#define MBEDTLS_SSL_ARC4_DISABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + +#define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED 0 +#define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED 1 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) +#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +#endif + +/* + * Maximum fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) +#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ +#endif + +#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) +#define MBEDTLS_SSL_IN_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#endif + +/* + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + */ +#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) +#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 +#endif + +/* + * Maximum length of CIDs for incoming and outgoing messages. + */ +#if !defined(MBEDTLS_SSL_CID_IN_LEN_MAX) +#define MBEDTLS_SSL_CID_IN_LEN_MAX 32 +#endif + +#if !defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) +#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 +#endif + +#if !defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) +#define MBEDTLS_SSL_CID_PADDING_GRANULARITY 16 +#endif + +#if !defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) +#define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1 +#endif + +/** \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 +#else +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 +#endif + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ +#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 +#define MBEDTLS_SSL_MSG_CID 25 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 + +#define MBEDTLS_TLS_EXT_USE_SRTP 14 + +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +/* The value of the CID extension is still TBD as of + * draft-ietf-tls-dtls-connection-id-05 + * (https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05). + * + * A future minor revision of Mbed TLS may change the default value of + * this option to match evolving standards and usage. + */ +#if !defined(MBEDTLS_TLS_EXT_CID) +#define MBEDTLS_TLS_EXT_CID 254 /* TBD */ +#endif + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret +{ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum +{ + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +} +mbedtls_ssl_states; + +/* + * The tls_prf function types. + */ +typedef enum +{ + MBEDTLS_SSL_TLS_PRF_NONE, + MBEDTLS_SSL_TLS_PRF_SSL3, + MBEDTLS_SSL_TLS_PRF_TLS1, + MBEDTLS_SSL_TLS_PRF_SHA384, + MBEDTLS_SSL_TLS_PRF_SHA256 +} +mbedtls_tls_prf_types; +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send fewer bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \returns If data has been received, the positive number of bytes received. + * \returns \c 0 if the connection has been closed. + * \returns If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * \returns Another negative error code on other kinds of failures. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in ssl_internal.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) +typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Callback type: start external signature operation. + * + * This callback is called during an SSL handshake to start + * a signature decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p hash if the value + * is needed for later processing, because the \p hash buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \note For RSA signatures, this function must produce output + * that is consistent with PKCS#1 v1.5 in the same way as + * mbedtls_rsa_pkcs1_sign(). Before the private key operation, + * apply the padding steps described in RFC 8017, section 9.2 + * "EMSA-PKCS1-v1_5" as follows. + * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the DigestInfo to be + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 3, with `T = hash` and `tLen = hash_len`. + * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the hash to be encoded and + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 2, with `digestAlgorithm` obtained by calling + * mbedtls_oid_get_oid_by_md() on \p md_alg. + * + * \note For ECDSA signatures, the output format is the DER encoding + * `Ecdsa-Sig-Value` defined in + * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param md_alg Hash algorithm. + * \param hash Buffer containing the hash. This buffer is + * no longer valid when the function returns. + * \param hash_len Size of the \c hash buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ); + +/** + * \brief Callback type: start external decryption operation. + * + * This callback is called during an SSL handshake to start + * an RSA decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p input if the value + * is needed for later processing, because the \p input buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \warning RSA decryption as used in TLS is subject to a potential + * timing side channel attack first discovered by Bleichenbacher + * in 1998. This attack can be remotely exploitable + * in practice. To avoid this attack, you must ensure that + * if the callback performs an RSA decryption, the time it + * takes to execute and return the result does not depend + * on whether the RSA decryption succeeded or reported + * invalid padding. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param input Buffer containing the input ciphertext. This buffer + * is no longer valid when the function returns. + * \param input_len Size of the \p input buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Callback type: resume external operation. + * + * This callback is called during an SSL handshake to resume + * an external operation started by the + * ::mbedtls_ssl_async_sign_t or + * ::mbedtls_ssl_async_decrypt_t callback. + * + * This function typically checks the status of a pending + * request or causes the request queue to make progress, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * It may call mbedtls_ssl_set_async_operation_data() to modify + * this context. + * + * Note that when this function returns a status other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any + * resources associated with the operation. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param output Buffer containing the output (signature or decrypted + * data) on success. + * \param output_len On success, number of bytes written to \p output. + * \param output_size Size of the \p output buffer in bytes. + * + * \return 0 if output of the operation is available in the + * \p output buffer. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * is still in progress. Subsequent requests for progress + * on the SSL connection will call the resume callback + * again. + * \return Any other error means that the operation is aborted. + * The SSL handshake is aborted. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ); + +/** + * \brief Callback type: cancel external operation. + * + * This callback is called if an SSL connection is closed + * while an asynchronous operation is in progress. Note that + * this callback is not called if the + * ::mbedtls_ssl_async_resume_t callback has run and has + * returned a value other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case + * the asynchronous operation has already completed. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * + * \param ssl The SSL connection instance. It should not be + * modified. + */ +typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48 +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32 +#elif defined(MBEDTLS_SHA512_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48 +#elif defined(MBEDTLS_SHA1_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20 +#else +/* This is already checked in check_config.h, but be sure. */ +#error "Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT." +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && + !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + +#define MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH 255 +#define MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH 4 +/* + * For code readability use a typedef for DTLS-SRTP profiles + * + * Use_srtp extension protection profiles values as defined in + * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + * + * Reminder: if this list is expanded mbedtls_ssl_check_srtp_profile_value + * must be updated too. + */ +#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80 ( (uint16_t) 0x0001) +#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32 ( (uint16_t) 0x0002) +#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80 ( (uint16_t) 0x0005) +#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32 ( (uint16_t) 0x0006) +/* This one is not iana defined, but for code readability. */ +#define MBEDTLS_TLS_SRTP_UNSET ( (uint16_t) 0x0000) + +typedef uint16_t mbedtls_ssl_srtp_profile; + +typedef struct mbedtls_dtls_srtp_info_t +{ + /*! The SRTP profile that was negotiated. */ + mbedtls_ssl_srtp_profile chosen_dtls_srtp_profile; + /*! The length of mki_value. */ + uint16_t mki_len; + /*! The mki_value used, with max size of 256 bytes. */ + unsigned char mki_value[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH]; +} +mbedtls_dtls_srtp_info; + +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * This structure is used for storing current session data. + * + * Note: when changing this definition, we need to check and update: + * - in tests/suites/test_suite_ssl.function: + * ssl_populate_session() and ssl_serialize_session_save_load() + * - in library/ssl_tls.c: + * mbedtls_ssl_session_init() and mbedtls_ssl_session_free() + * mbedtls_ssl_session_save() and ssl_session_load() + * ssl_session_copy() + */ +struct mbedtls_ssl_session +{ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t start; /*!< starting time */ +#endif + int ciphersuite; /*!< chosen ciphersuite */ + int compression; /*!< chosen compression */ + size_t id_len; /*!< session id length */ + unsigned char id[32]; /*!< session identifier */ + unsigned char master[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /*! The digest of the peer's end-CRT. This must be kept to detect CRT + * changes during renegotiation, mitigating the triple handshake attack. */ + unsigned char *peer_cert_digest; + size_t peer_cert_digest_len; + mbedtls_md_type_t peer_cert_digest_type; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t verify_result; /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *ticket; /*!< RFC 5077 session ticket */ + size_t ticket_len; /*!< session ticket length */ + uint32_t ticket_lifetime; /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac; /*!< flag for truncated hmac activation */ +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif +}; + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config +{ + /* Group items by size and reorder them to maximize usage of immediate offset access. */ + + /* + * Numerical settings (char) + */ + + unsigned char max_major_ver; /*!< max. major version used */ + unsigned char max_minor_ver; /*!< max. minor version used */ + unsigned char min_major_ver; /*!< min. major version used */ + unsigned char min_minor_ver; /*!< min. minor version used */ + + /* + * Flags (could be bit-fields to save RAM, but separate bytes make + * the code smaller on architectures with an instruction for direct + * byte access). + */ + + uint8_t endpoint /*bool*/; /*!< 0: client, 1: server */ + uint8_t transport /*bool*/; /*!< stream (TLS) or datagram (DTLS) */ + uint8_t authmode /*2 bits*/; /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + uint8_t allow_legacy_renegotiation /*2 bits*/; /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_ARC4_C) + uint8_t arc4_disabled /*bool*/; /*!< blacklist RC4 ciphersuites? */ +#endif +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + uint8_t mfl_code /*3 bits*/; /*!< desired fragment length */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + uint8_t encrypt_then_mac /*bool*/; /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + uint8_t extended_ms /*bool*/; /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint8_t anti_replay /*bool*/; /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + uint8_t cbc_record_splitting /*bool*/; /*!< do cbc record splitting */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + uint8_t disable_renegotiation /*bool*/; /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + uint8_t trunc_hmac /*bool*/; /*!< negotiate truncated hmac? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint8_t session_tickets /*bool*/; /*!< use session tickets? */ +#endif +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) + uint8_t fallback /*bool*/; /*!< is this a fallback? */ +#endif +#if defined(MBEDTLS_SSL_SRV_C) + uint8_t cert_req_ca_list /*bool*/; /*!< enable sending CA list in + Certificate Request messages? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t ignore_unexpected_cid /*bool*/; /*!< Determines whether DTLS + * record with unexpected CID + * should lead to failure. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_DTLS_SRTP) + uint8_t dtls_srtp_mki_support /*bool*/; /*!< support having mki_value + in the use_srtp extension? */ +#endif + + /* + * Numerical settings (int or larger) + */ + + uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t hs_timeout_min; /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t hs_timeout_max; /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_max_records; /*!< grace period for renegotiation */ + unsigned char renego_period[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned int badmac_limit; /*!< limit of records with a bad MAC */ +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ +#endif + + /* + * Pointers + */ + + const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ + + /** Callback for printing debug output */ + void (*f_dbg)(void *, int, const char *, int, const char *); + void *p_dbg; /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + int (*f_get_cache)(void *, mbedtls_ssl_session *); + /** Callback to store a session into the cache */ + int (*f_set_cache)(void *, const mbedtls_ssl_session *); + void *p_cache; /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_sni; /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + /** Callback to retrieve PSK key from identity */ + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *p_psk; /*!< context for PSK callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a cookie for ClientHello verification */ + int (*f_cookie_write)( void *, unsigned char **, unsigned char *, + const unsigned char *, size_t ); + /** Callback to verify validity of a ClientHello cookie */ + int (*f_cookie_check)( void *, const unsigned char *, size_t, + const unsigned char *, size_t ); + void *p_cookie; /*!< context for the cookie callbacks */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a session ticket */ + int (*f_ticket_write)( void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, uint32_t * ); + /** Callback to parse a session ticket into a session structure */ + int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *p_ticket; /*!< context for the ticket callbacks */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + /** Callback to export key block and master secret */ + int (*f_export_keys)( void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t ); + /** Callback to export key block, master secret, + * tls_prf and random bytes. Should replace f_export_keys */ + int (*f_export_keys_ext)( void *, const unsigned char *, + const unsigned char *, size_t, size_t, size_t, + const unsigned char[32], const unsigned char[32], + mbedtls_tls_prf_types ); + void *p_export_keys; /*!< context for key export callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + size_t cid_len; /*!< The length of CIDs for incoming DTLS records. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ + mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ + mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_ca_cb_t f_ca_cb; + void *p_ca_cb; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */ + void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + const int *sig_hashes; /*!< allowed signature hashes */ +#endif + +#if defined(MBEDTLS_ECP_C) + const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ + mbedtls_mpi dhm_G; /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_id_t psk_opaque; /*!< PSA key slot holding opaque PSK. This field + * should only be set via + * mbedtls_ssl_conf_psk_opaque(). + * If either no PSK or a raw PSK have been + * configured, this has value \c 0. + */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + unsigned char *psk; /*!< The raw pre-shared key. This field should + * only be set via mbedtls_ssl_conf_psk(). + * If either no PSK or an opaque PSK + * have been configured, this has value NULL. */ + size_t psk_len; /*!< The length of the raw pre-shared key. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL. */ + + unsigned char *psk_identity; /*!< The PSK identity for PSK negotiation. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * This is set if and only if either + * \c psk or \c psk_opaque are set. */ + size_t psk_identity_len;/*!< The length of PSK identity. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL or \c psk_opaque + * is not \c 0. */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + const char **alpn_list; /*!< ordered list of protocols */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + /*! ordered list of supported srtp profile */ + const mbedtls_ssl_srtp_profile *dtls_srtp_profile_list; + /*! number of supported profiles */ + size_t dtls_srtp_profile_list_len; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ +}; + +struct mbedtls_ssl_context +{ + const mbedtls_ssl_config *conf; /*!< configuration information */ + + /* + * Miscellaneous + */ + int state; /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renego_status; /*!< Initial, in progress, pending? */ + int renego_records_seen; /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ + int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + unsigned badmac_seen; /*!< records with a bad MAC received */ +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; /*!< context for X.509 verify callback */ +#endif + + mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ + mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *f_recv_timeout; + /*!< Callback for network receive with timeout */ + + void *p_bio; /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *session_in; /*!< current session data (in) */ + mbedtls_ssl_session *session_out; /*!< current session data (out) */ + mbedtls_ssl_session *session; /*!< negotiated session data */ + mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *handshake; /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ + mbedtls_ssl_transform *transform; /*!< negotiated transform params */ + mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ + + /* + * Timers + */ + void *p_timer; /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ + mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *in_buf; /*!< input buffer */ + unsigned char *in_ctr; /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *in_hdr; /*!< start of record header */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char *in_cid; /*!< The start of the CID; + * (the end is marked by in_len). */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + unsigned char *in_len; /*!< two-bytes message length field */ + unsigned char *in_iv; /*!< ivlen-byte IV */ + unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ + unsigned char *in_offt; /*!< read offset in application data */ + + int in_msgtype; /*!< record header: message type */ + size_t in_msglen; /*!< record header: message length */ + size_t in_left; /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len; /*!< length of input buffer */ +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t in_epoch; /*!< DTLS epoch for incoming records */ + size_t next_record_offset; /*!< offset of the next record in datagram + (equal to in_left if none) */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint64_t in_window_top; /*!< last validated record seq_num */ + uint64_t in_window; /*!< bitmask for replay detection */ +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + + size_t in_hslen; /*!< current handshake message length, + including the handshake header */ + int nb_zero; /*!< # of 0-length encrypted messages */ + + int keep_current_message; /*!< drop or reuse current message + on next call to record layer? */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t disable_datagram_packing; /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Record layer (outgoing data) + */ + unsigned char *out_buf; /*!< output buffer */ + unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ + unsigned char *out_hdr; /*!< start of record header */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char *out_cid; /*!< The start of the CID; + * (the end is marked by in_len). */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + unsigned char *out_len; /*!< two-bytes message length field */ + unsigned char *out_iv; /*!< ivlen-byte IV */ + unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ + + int out_msgtype; /*!< record header: message type */ + size_t out_msglen; /*!< record header: message length */ + size_t out_left; /*!< amount of data not yet written */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len; /*!< length of output buffer */ +#endif + + unsigned char cur_out_ctr[8]; /*!< Outgoing record sequence number. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t mtu; /*!< path mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_ZLIB_SUPPORT) + unsigned char *compress_buf; /*!< zlib data buffer */ +#endif /* MBEDTLS_ZLIB_SUPPORT */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + signed char split_done; /*!< current record already split? */ +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + + /* + * PKI layer + */ + int client_auth; /*!< flag for client auth. */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *hostname; /*!< expected peer CN for verification + (and SNI if available) */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_chosen; /*!< negotiated protocol */ +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + /* + * use_srtp extension + */ + mbedtls_dtls_srtp_info dtls_srtp_info; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + /* + * Information for DTLS hello verify + */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + unsigned char *cli_id; /*!< transport-level ID of the client */ + size_t cli_id_len; /*!< length of cli_id */ +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + + /* + * Secure renegotiation + */ + /* needed to know when to send extension on server */ + int secure_renegotiation; /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t verify_data_len; /*!< length of verify data stored */ + char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* CID configuration to use in subsequent handshakes. */ + + /*! The next incoming CID, chosen by the user and applying to + * all subsequent handshakes. This may be different from the + * CID currently used in case the user has re-configured the CID + * after an initial handshake. */ + unsigned char own_cid[ MBEDTLS_SSL_CID_IN_LEN_MAX ]; + uint8_t own_cid_len; /*!< The length of \c own_cid. */ + uint8_t negotiate_cid; /*!< This indicates whether the CID extension should + * be negotiated in the next handshake or not. + * Possible values are #MBEDTLS_SSL_CID_ENABLED + * and #MBEDTLS_SSL_CID_DISABLED. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +}; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#define MBEDTLS_SSL_CHANNEL_OUTBOUND MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( 0 ) +#define MBEDTLS_SSL_CHANNEL_INBOUND MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( 1 ) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_WARNING */ + +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_init)( + mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_activate)( + mbedtls_ssl_context *ssl, + int direction ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_reset)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_write)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_read)( + mbedtls_ssl_context *ssl ); +MBEDTLS_DEPRECATED extern int (*mbedtls_ssl_hw_record_finish)( + mbedtls_ssl_context *ssl ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); + +/** + * \brief Initialize an SSL context + * Just makes the context ready for mbedtls_ssl_setup() or + * mbedtls_ssl_free() + * + * \param ssl SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); + +/** + * \brief Set up an SSL context for use + * + * \note No copy of the configuration context is made, it can be + * shared by many mbedtls_ssl_context structures. + * + * \warning The conf structure will be accessed during the session. + * It must not be modified or freed as long as the session + * is active. + * + * \warning This function must be called exactly once per context. + * Calling mbedtls_ssl_setup again is not supported, even + * if no session is active. + * + * \param ssl SSL context + * \param conf SSL configuration to use + * + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if + * memory allocation failed + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or + * MBEDTLS_ERR_SSL_COMPRESSION_FAILED + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param conf SSL configuration + * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); + +/** + * \brief Set the transport type (TLS or DTLS). + * Default: TLS + * + * \note For DTLS, you must either provide a recv callback that + * doesn't block, or one that handles timeouts, see + * \c mbedtls_ssl_set_bio(). You also need to provide timer + * callbacks with \c mbedtls_ssl_set_timer_cb(). + * + * \param conf SSL configuration + * \param transport transport type: + * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. + */ +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); + +/** + * \brief Set the certificate verification mode + * Default: NONE on server, REQUIRED on client + * + * \param conf SSL configuration + * \param authmode can be: + * + * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked + * (default on server) + * (insecure on client) + * + * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * mbedtls_ssl_get_verify_result() can be called after the + * handshake is complete. + * + * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * (default on client) + * + * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. + * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the provided verify callback is called for each + * certificate in the peer's CRT chain, including the trusted + * root. For more information, please see the documentation of + * \c mbedtls_x509_crt_verify(). + * + * \note For per context callbacks and contexts, please use + * mbedtls_ssl_set_verify() instead. + * + * \param conf The SSL configuration to use. + * \param f_vrfy The verification callback to use during CRT verification. + * \param p_vrfy The opaque context to be passed to the callback. + */ +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param conf SSL configuration + * \param f_rng RNG function + * \param p_rng RNG parameter + */ +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * The callback has the following argument: + * void * opaque context for the callback + * int debug level + * const char * file name + * int line number + * const char * message + * + * \param conf SSL configuration + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO callbacks for write, read and + * read-with-timeout. + * + * \param ssl SSL context + * \param p_bio parameter (context) shared by BIO callbacks + * \param f_send write callback + * \param f_recv read callback + * \param f_recv_timeout blocking read callback with timeout. + * + * \note One of f_recv or f_recv_timeout can be NULL, in which case + * the other is used. If both are non-NULL, f_recv_timeout is + * used and f_recv is ignored (as if it were NULL). + * + * \note The two most common use cases are: + * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL + * - blocking I/O, f_recv == NULL, f_recv_timeout != NULL + * + * \note For DTLS, you need to provide either a non-NULL + * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_send_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the conventions those callbacks must follow. + * + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \c mbedtls_net_recv_timeout() that are suitable to be used + * here. + */ +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + + +/** + * \brief Configure the use of the Connection ID (CID) + * extension in the next handshake. + * + * Reference: draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * The DTLS CID extension allows the reliable association of + * DTLS records to DTLS connections across changes in the + * underlying transport (changed IP and Port metadata) by + * adding explicit connection identifiers (CIDs) to the + * headers of encrypted DTLS records. The desired CIDs are + * configured by the application layer and are exchanged in + * new `ClientHello` / `ServerHello` extensions during the + * handshake, where each side indicates the CID it wants the + * peer to use when writing encrypted messages. The CIDs are + * put to use once records get encrypted: the stack discards + * any incoming records that don't include the configured CID + * in their header, and adds the peer's requested CID to the + * headers of outgoing messages. + * + * This API enables or disables the use of the CID extension + * in the next handshake and sets the value of the CID to + * be used for incoming messages. + * + * \param ssl The SSL context to configure. This must be initialized. + * \param enable This value determines whether the CID extension should + * be used or not. Possible values are: + * - MBEDTLS_SSL_CID_ENABLED to enable the use of the CID. + * - MBEDTLS_SSL_CID_DISABLED (default) to disable the use + * of the CID. + * \param own_cid The address of the readable buffer holding the CID we want + * the peer to use when sending encrypted messages to us. + * This may be \c NULL if \p own_cid_len is \c 0. + * This parameter is unused if \p enabled is set to + * MBEDTLS_SSL_CID_DISABLED. + * \param own_cid_len The length of \p own_cid. + * This parameter is unused if \p enabled is set to + * MBEDTLS_SSL_CID_DISABLED. + * + * \note The value of \p own_cid_len must match the value of the + * \c len parameter passed to mbedtls_ssl_conf_cid() + * when configuring the ::mbedtls_ssl_config that \p ssl + * is bound to. + * + * \note This CID configuration applies to subsequent handshakes + * performed on the SSL context \p ssl, but does not trigger + * one. You still have to call `mbedtls_ssl_handshake()` + * (for the initial handshake) or `mbedtls_ssl_renegotiate()` + * (for a renegotiation handshake) explicitly after a + * successful call to this function to run the handshake. + * + * \note This call cannot guarantee that the use of the CID + * will be successfully negotiated in the next handshake, + * because the peer might not support it. Specifically: + * - On the Client, enabling the use of the CID through + * this call implies that the `ClientHello` in the next + * handshake will include the CID extension, thereby + * offering the use of the CID to the server. Only if + * the `ServerHello` contains the CID extension, too, + * the CID extension will actually be put to use. + * - On the Server, enabling the use of the CID through + * this call implies that that the server will look for + * the CID extension in a `ClientHello` from the client, + * and, if present, reply with a CID extension in its + * `ServerHello`. + * + * \note To check whether the use of the CID was negotiated + * after the subsequent handshake has completed, please + * use the API mbedtls_ssl_get_peer_cid(). + * + * \warning If the use of the CID extension is enabled in this call + * and the subsequent handshake negotiates its use, Mbed TLS + * will silently drop every packet whose CID does not match + * the CID configured in \p own_cid. It is the responsibility + * of the user to adapt the underlying transport to take care + * of CID-based demultiplexing before handing datagrams to + * Mbed TLS. + * + * \return \c 0 on success. In this case, the CID configuration + * applies to the next handshake. + * \return A negative error code on failure. + */ +int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl, + int enable, + unsigned char const *own_cid, + size_t own_cid_len ); + +/** + * \brief Get information about the use of the CID extension + * in the current connection. + * + * \param ssl The SSL context to query. + * \param enabled The address at which to store whether the CID extension + * is currently in use or not. If the CID is in use, + * `*enabled` is set to MBEDTLS_SSL_CID_ENABLED; + * otherwise, it is set to MBEDTLS_SSL_CID_DISABLED. + * \param peer_cid The address of the buffer in which to store the CID + * chosen by the peer (if the CID extension is used). + * This may be \c NULL in case the value of peer CID + * isn't needed. If it is not \c NULL, \p peer_cid_len + * must not be \c NULL. + * \param peer_cid_len The address at which to store the size of the CID + * chosen by the peer (if the CID extension is used). + * This is also the number of Bytes in \p peer_cid that + * have been written. + * This may be \c NULL in case the length of the peer CID + * isn't needed. If it is \c NULL, \p peer_cid must be + * \c NULL, too. + * + * \note This applies to the state of the CID negotiated in + * the last complete handshake. If a handshake is in + * progress, this function will attempt to complete + * the handshake first. + * + * \note If CID extensions have been exchanged but both client + * and server chose to use an empty CID, this function + * sets `*enabled` to #MBEDTLS_SSL_CID_DISABLED + * (the rationale for this is that the resulting + * communication is the same as if the CID extensions + * hadn't been used). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl, + int *enabled, + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ], + size_t *peer_cid_len ); + +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +/** + * \brief Set the Maximum Transport Unit (MTU). + * Special value: 0 means unset (no limit). + * This represents the maximum size of a datagram payload + * handled by the transport layer (usually UDP) as determined + * by the network link and stack. In practice, this controls + * the maximum size datagram the DTLS layer will pass to the + * \c f_send() callback set using \c mbedtls_ssl_set_bio(). + * + * \note The limit on datagram size is converted to a limit on + * record payload by subtracting the current overhead of + * encapsulation and encryption/authentication if any. + * + * \note This can be called at any point during the connection, for + * example when a Path Maximum Transfer Unit (PMTU) + * estimate becomes available from other sources, + * such as lower (or higher) protocol layers. + * + * \note This setting only controls the size of the packets we send, + * and does not restrict the size of the datagrams we're + * willing to receive. Client-side, you can request the + * server to use smaller records with \c + * mbedtls_ssl_conf_max_frag_len(). + * + * \note If both a MTU and a maximum fragment length have been + * configured (or negotiated with the peer), the resulting + * lower limit on record payload (see first note) is used. + * + * \note This can only be used to decrease the maximum size + * of datagrams (hence records, see first note) sent. It + * cannot be used to increase the maximum size of records over + * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN. + * + * \note Values lower than the current record layer expansion will + * result in an error when trying to send data. + * + * \note Using record compression together with a non-zero MTU value + * will result in an error when trying to send data. + * + * \param ssl SSL context + * \param mtu Value of the path MTU in bytes + */ +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set a connection-specific verification callback (optional). + * + * If set, the provided verify callback is called for each + * certificate in the peer's CRT chain, including the trusted + * root. For more information, please see the documentation of + * \c mbedtls_x509_crt_verify(). + * + * \note This call is analogous to mbedtls_ssl_conf_verify() but + * binds the verification callback and context to an SSL context + * as opposed to an SSL configuration. + * If mbedtls_ssl_conf_verify() and mbedtls_ssl_set_verify() + * are both used, mbedtls_ssl_set_verify() takes precedence. + * + * \param ssl The SSL context to use. + * \param f_vrfy The verification callback to use during CRT verification. + * \param p_vrfy The opaque context to be passed to the callback. + */ +void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the timeout period for mbedtls_ssl_read() + * (Default: no timeout.) + * + * \param conf SSL configuration context + * \param timeout Timeout value in milliseconds. + * Use 0 for no timeout (default). + * + * \note With blocking I/O, this will only work if a non-NULL + * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). + * With non-blocking I/O, this will only work if timer + * callbacks were set with \c mbedtls_ssl_set_timer_cb(). + * + * \note With non-blocking I/O, you may also skip this function + * altogether and handle timeouts at the application layer. + */ +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); + +#if defined(MBEDTLS_SSL_RECORD_CHECKING) +/** + * \brief Check whether a buffer contains a valid and authentic record + * that has not been seen before. (DTLS only). + * + * This function does not change the user-visible state + * of the SSL context. Its sole purpose is to provide + * an indication of the legitimacy of an incoming record. + * + * This can be useful e.g. in distributed server environments + * using the DTLS Connection ID feature, in which connections + * might need to be passed between service instances on a change + * of peer address, but where such disruptive operations should + * only happen after the validity of incoming records has been + * confirmed. + * + * \param ssl The SSL context to use. + * \param buf The address of the buffer holding the record to be checked. + * This must be a read/write buffer of length \p buflen Bytes. + * \param buflen The length of \p buf in Bytes. + * + * \note This routine only checks whether the provided buffer begins + * with a valid and authentic record that has not been seen + * before, but does not check potential data following the + * initial record. In particular, it is possible to pass DTLS + * datagrams containing multiple records, in which case only + * the first record is checked. + * + * \note This function modifies the input buffer \p buf. If you need + * to preserve the original record, you have to maintain a copy. + * + * \return \c 0 if the record is valid and authentic and has not been + * seen before. + * \return MBEDTLS_ERR_SSL_INVALID_MAC if the check completed + * successfully but the record was found to be not authentic. + * \return MBEDTLS_ERR_SSL_INVALID_RECORD if the check completed + * successfully but the record was found to be invalid for + * a reason different from authenticity checking. + * \return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD if the check completed + * successfully but the record was found to be unexpected + * in the state of the SSL context, including replayed records. + * \return Another negative error code on different kinds of failure. + * In this case, the SSL context becomes unusable and needs + * to be freed or reset before reuse. + */ +int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t buflen ); +#endif /* MBEDTLS_SSL_RECORD_CHECKING */ + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) + * + * \param ssl SSL context + * \param p_timer parameter (context) shared by timer callbacks + * \param f_set_timer set timer callback + * \param f_get_timer get timer callback. Must return: + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must follow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \note See also the "DTLS tutorial" article in our knowledge base. + * https://tls.mbed.org/kb/how-to/dtls-tutorial + */ +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ); + +/** + * \brief Callback type: generate and write session ticket + * + * \note This describes what a callback implementation should do. + * This callback should generate an encrypted and + * authenticated ticket for the session and write it to the + * output buffer. Here, ticket means the opaque ticket part + * of the NewSessionTicket structure of RFC 5077. + * + * \param p_ticket Context for the callback + * \param session SSL session to be written in the ticket + * \param start Start of the output buffer + * \param end End of the output buffer + * \param tlen On exit, holds the length written + * \param lifetime On exit, holds the lifetime of the ticket in seconds + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *lifetime ); + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Callback type: Export key block and master secret + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback + * \param ms Pointer to master secret (fixed length: 48 bytes) + * \param kb Pointer to key block, see RFC 5246 section 6.3 + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length + * \param keylen Key length + * \param ivlen IV length + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_export_keys_t( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen ); + +/** + * \brief Callback type: Export key block, master secret, + * handshake randbytes and the tls_prf function + * used to derive keys. + * + * \note This is required for certain uses of TLS, e.g. EAP-TLS + * (RFC 5216) and Thread. The key pointers are ephemeral and + * therefore must not be stored. The master secret and keys + * should not be used directly except as an input to a key + * derivation function. + * + * \param p_expkey Context for the callback. + * \param ms Pointer to master secret (fixed length: 48 bytes). + * \param kb Pointer to key block, see RFC 5246 section 6.3. + * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). + * \param maclen MAC length. + * \param keylen Key length. + * \param ivlen IV length. + * \param client_random The client random bytes. + * \param server_random The server random bytes. + * \param tls_prf_type The tls_prf enum type. + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_export_keys_ext_t( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +/** + * \brief Callback type: parse and load session ticket + * + * \note This describes what a callback implementation should do. + * This callback should parse a session ticket as generated + * by the corresponding mbedtls_ssl_ticket_write_t function, + * and, if the ticket is authentic and valid, load the + * session. + * + * \note The implementation is allowed to modify the first len + * bytes of the input buffer, eg to use it as a temporary + * area for the decrypted ticket contents. + * + * \param p_ticket Context for the callback + * \param session SSL session to be loaded + * \param buf Start of the buffer containing the ticket + * \param len Length of the ticket. + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or + * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or + * any other non-zero code for other failures. + */ +typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Configure SSL session ticket callbacks (server only). + * (Default: none.) + * + * \note On server, session tickets are enabled by providing + * non-NULL callbacks. + * + * \note On client, use \c mbedtls_ssl_conf_session_tickets(). + * + * \param conf SSL configuration context + * \param f_ticket_write Callback for writing a ticket + * \param f_ticket_parse Callback for parsing a ticket + * \param p_ticket Context shared by the two callbacks + */ +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +/** + * \brief Configure key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_t. + * + * \param conf SSL configuration context + * \param f_export_keys Callback for exporting keys + * \param p_export_keys Context for the callback + */ +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ); + +/** + * \brief Configure extended key export callback. + * (Default: none.) + * + * \note See \c mbedtls_ssl_export_keys_ext_t. + * \warning Exported key material must not be used for any purpose + * before the (D)TLS handshake is completed + * + * \param conf SSL configuration context + * \param f_export_keys_ext Callback for exporting keys + * \param p_export_keys Context for the callback + */ +void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_ext_t *f_export_keys_ext, + void *p_export_keys ); +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +/** + * \brief Configure asynchronous private key operation callbacks. + * + * \param conf SSL configuration context + * \param f_async_sign Callback to start a signature operation. See + * the description of ::mbedtls_ssl_async_sign_t + * for more information. This may be \c NULL if the + * external processor does not support any signature + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_decrypt Callback to start a decryption operation. See + * the description of ::mbedtls_ssl_async_decrypt_t + * for more information. This may be \c NULL if the + * external processor does not support any decryption + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_resume Callback to resume an asynchronous operation. See + * the description of ::mbedtls_ssl_async_resume_t + * for more information. This may not be \c NULL unless + * \p f_async_sign and \p f_async_decrypt are both + * \c NULL. + * \param f_async_cancel Callback to cancel an asynchronous operation. See + * the description of ::mbedtls_ssl_async_cancel_t + * for more information. This may be \c NULL if + * no cleanup is needed. + * \param config_data A pointer to configuration data which can be + * retrieved with + * mbedtls_ssl_conf_get_async_config_data(). The + * library stores this value without dereferencing it. + */ +void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *config_data ); + +/** + * \brief Retrieve the configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + * + * \param conf SSL configuration context + * \return The configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + */ +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * + * \return The asynchronous operation user context that was last + * set during the current handshake. If + * mbedtls_ssl_set_async_operation_data() has not yet been + * called during the current handshake, this function returns + * \c NULL. + */ +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * \param ctx The new value of the asynchronous operation user context. + * Call mbedtls_ssl_get_async_operation_data() later during the + * same handshake to retrieve this value. + */ +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/** + * \brief Callback type: generate a cookie + * + * \param ctx Context for the callback + * \param p Buffer to write to, + * must be updated to point right after the cookie + * \param end Pointer to one past the end of the output buffer + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 on success, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_write_t( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen ); + +/** + * \brief Callback type: verify a cookie + * + * \param ctx Context for the callback + * \param cookie Cookie to verify + * \param clen Length of cookie + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 if cookie is valid, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_check_t( void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Register callbacks for DTLS cookies + * (Server only. DTLS only.) + * + * Default: dummy callbacks that fail, in order to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * + * \note See comments on \c mbedtls_ssl_handshake() about handling + * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected + * on the first handshake attempt when this is enabled. + * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * + * \param conf SSL configuration + * \param f_cookie_write Cookie write callback + * \param f_cookie_check Cookie check callback + * \param p_cookie Context for both callbacks + */ +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ); + +/** + * \brief Set client's transport-level identification info. + * (Server only. DTLS only.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. + */ +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ); + +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enabled. + * + * \param conf SSL configuration + * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. + * + * \warning Disabling this is a security risk unless the application + * protocol handles duplicated packets in a safe way. You + * should not disable this without careful consideration. + * However, if your application already detects duplicated + * packets and needs information about them to adjust its + * transmission strategy, then you'll want to disable this. + */ +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param conf SSL configuration + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker to inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/** + * \brief Allow or disallow packing of multiple handshake records + * within a single datagram. + * + * \param ssl The SSL context to configure. + * \param allow_packing This determines whether datagram packing may + * be used or not. A value of \c 0 means that every + * record will be sent in a separate datagram; a + * value of \c 1 means that, if space permits, + * multiple handshake messages (including CCS) belonging to + * a single flight may be packed within a single datagram. + * + * \note This is enabled by default and should only be disabled + * for test purposes, or if datagram packing causes + * interoperability issues with peers that don't support it. + * + * \note Allowing datagram packing reduces the network load since + * there's less overhead if multiple messages share the same + * datagram. Also, it increases the handshake efficiency + * since messages belonging to a single datagram will not + * be reordered in transit, and so future message buffering + * or flight retransmission (if no buffering is used) as + * means to deal with reordering are needed less frequently. + * + * \note Application records are not affected by this option and + * are currently always sent in separate datagrams. + * + */ +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ); + +/** + * \brief Set retransmit timeout values for the DTLS handshake. + * (DTLS only, no effect on TLS.) + * + * \param conf SSL configuration + * \param min Initial timeout value in milliseconds. + * Default: 1000 (1 second). + * \param max Maximum timeout value in milliseconds. + * Default: 60000 (60 seconds). + * + * \note Default values are from RFC 6347 section 4.2.4.1. + * + * \note The 'min' value should typically be slightly above the + * expected round-trip time to your peer, plus whatever time + * it takes for the peer to process the message. For example, + * if your RTT is about 600ms and you peer needs up to 1s to + * do the cryptographic operations in the handshake, then you + * should set 'min' slightly above 1600. Lower values of 'min' + * might cause spurious resends which waste network resources, + * while larger value of 'min' will increase overall latency + * on unreliable network links. + * + * \note The more unreliable your network connection is, the larger + * your max / min ratio needs to be in order to achieve + * reliable handshakes. + * + * \note Messages are retransmitted up to log2(ceil(max/min)) times. + * For example, if min = 1s and max = 5s, the retransmit plan + * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> + * resend ... 5s -> give up and return a timeout error. + */ +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, mbedtls_ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const mbedtls_ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the mbedtls_ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param conf SSL configuration + * \param p_cache parameter (context) for both callbacks + * \param f_get_cache session get callback + * \param f_set_cache session set callback + */ +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Request resumption of session (client-side only) + * Session data is copied from presented session structure. + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid + * + * \sa mbedtls_ssl_get_session() + */ +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Load serialized session data into a session structure. + * On client, this can be used for loading saved sessions + * before resuming them with mbedtls_ssl_set_session(). + * On server, this can be used for alternative implementations + * of session cache or session tickets. + * + * \warning If a peer certificate chain is associated with the session, + * the serialized state will only contain the peer's + * end-entity certificate and the result of the chain + * verification (unless verification was disabled), but not + * the rest of the chain. + * + * \see mbedtls_ssl_session_save() + * \see mbedtls_ssl_set_session() + * + * \param session The session structure to be populated. It must have been + * initialised with mbedtls_ssl_session_init() but not + * populated yet. + * \param buf The buffer holding the serialized session data. It must be a + * readable buffer of at least \p len bytes. + * \param len The size of the serialized data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data + * was generated in a different version or configuration of + * Mbed TLS. + * \return Another negative value for other kinds of errors (for + * example, unsupported features in the embedded certificate). + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ); + +/** + * \brief Save session structure as serialized data in a buffer. + * On client, this can be used for saving session data, + * potentially in non-volatile storage, for resuming later. + * On server, this can be used for alternative implementations + * of session cache or session tickets. + * + * \see mbedtls_ssl_session_load() + * \see mbedtls_ssl_get_session_pointer() + * + * \param session The session structure to be saved. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p len bytes, or may be \c + * NULL if \p len is \c 0. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ); + +/** + * \brief Get a pointer to the current session structure, for example + * to serialize it. + * + * \warning Ownership of the session remains with the SSL context, and + * the returned pointer is only guaranteed to be valid until + * the next API call operating on the same \p ssl context. + * + * \see mbedtls_ssl_session_save() + * + * \param ssl The SSL context. + * + * \return A pointer to the current session if successful. + * \return \c NULL if no session is active. + */ +const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl ); + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * (Overrides all version-specific lists) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * Note: The server uses its own preferences + * over the preference of the client unless + * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + */ +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0 +#define MBEDTLS_SSL_UNEXPECTED_CID_FAIL 1 +/** + * \brief Specify the length of Connection IDs for incoming + * encrypted DTLS records, as well as the behaviour + * on unexpected CIDs. + * + * By default, the CID length is set to \c 0, + * and unexpected CIDs are silently ignored. + * + * \param conf The SSL configuration to modify. + * \param len The length in Bytes of the CID fields in encrypted + * DTLS records using the CID mechanism. This must + * not be larger than #MBEDTLS_SSL_CID_OUT_LEN_MAX. + * \param ignore_other_cids This determines the stack's behaviour when + * receiving a record with an unexpected CID. + * Possible values are: + * - #MBEDTLS_SSL_UNEXPECTED_CID_IGNORE + * In this case, the record is silently ignored. + * - #MBEDTLS_SSL_UNEXPECTED_CID_FAIL + * In this case, the stack fails with the specific + * error code #MBEDTLS_ERR_SSL_UNEXPECTED_CID. + * + * \note The CID specification allows implementations to either + * use a common length for all incoming connection IDs or + * allow variable-length incoming IDs. Mbed TLS currently + * requires a common length for all connections sharing the + * same SSL configuration; this allows simpler parsing of + * record headers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p own_cid_len + * is too large. + */ +int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf, size_t len, + int ignore_other_cids ); +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +/** + * \brief Set the list of allowed ciphersuites and the + * preference order for a specific version of the protocol. + * (Only useful on the server side) + * + * The ciphersuites array is not copied, and must remain + * valid for the lifetime of the ssl_config. + * + * \param conf SSL configuration + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 + * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + */ +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the X.509 security profile used for verification + * + * \note The restrictions are enforced for all certificates in the + * chain. However, signatures in the handshake are not covered + * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). + * + * \param conf SSL configuration + * \param profile Profile to use + */ +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ); + +/** + * \brief Set the data required to verify peer certificate + * + * \note See \c mbedtls_x509_crt_verify() for notes regarding the + * parameters ca_chain (maps to trust_ca for that function) + * and ca_crl. + * + * \param conf SSL configuration + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/** + * \brief Set the trusted certificate callback. + * + * This API allows to register the set of trusted certificates + * through a callback, instead of a linked list as configured + * by mbedtls_ssl_conf_ca_chain(). + * + * This is useful for example in contexts where a large number + * of CAs are used, and the inefficiency of maintaining them + * in a linked list cannot be tolerated. It is also useful when + * the set of trusted CAs needs to be modified frequently. + * + * See the documentation of `mbedtls_x509_crt_ca_cb_t` for + * more information. + * + * \param conf The SSL configuration to register the callback with. + * \param f_ca_cb The trusted certificate callback to use when verifying + * certificate chains. + * \param p_ca_cb The context to be passed to \p f_ca_cb (for example, + * a reference to a trusted CA database). + * + * \note This API is incompatible with mbedtls_ssl_conf_ca_chain(): + * Any call to this function overwrites the values set through + * earlier calls to mbedtls_ssl_conf_ca_chain() or + * mbedtls_ssl_conf_ca_cb(). + * + * \note This API is incompatible with CA indication in + * CertificateRequest messages: A server-side SSL context which + * is bound to an SSL configuration that uses a CA callback + * configured via mbedtls_ssl_conf_ca_cb(), and which requires + * client authentication, will send an empty CA list in the + * corresponding CertificateRequest message. + * + * \note This API is incompatible with mbedtls_ssl_set_hs_ca_chain(): + * If an SSL context is bound to an SSL configuration which uses + * CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then + * calls to mbedtls_ssl_set_hs_ca_chain() have no effect. + * + * \note The use of this API disables the use of restartable ECC + * during X.509 CRT signature verification (but doesn't affect + * other uses). + * + * \warning This API is incompatible with the use of CRLs. Any call to + * mbedtls_ssl_conf_ca_cb() unsets CRLs configured through + * earlier calls to mbedtls_ssl_conf_ca_chain(). + * + * \warning In multi-threaded environments, the callback \p f_ca_cb + * must be thread-safe, and it is the user's responsibility + * to guarantee this (for example through a mutex + * contained in the callback context pointed to by \p p_ca_cb). + */ +void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb ); +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note On server, this function can be called multiple times to + * provision more than one cert/key pair (eg one ECDSA, one + * RSA with SHA-256, one RSA with SHA-1). An adequate + * certificate will be selected according to the client's + * advertised capabilities. In case multiple certificates are + * adequate, preference is given to the one set by the first + * call to this function, then second, etc. + * + * \note On client, only the first call has any effect. That is, + * only one client certificate can be provisioned. The + * server's preferences in its CertificateRequest message will + * be ignored and our only cert will be sent regardless of + * whether it matches those preferences - the server can then + * decide what it wants to do with it. + * + * \note The provided \p pk_key needs to match the public key in the + * first certificate in \p own_cert, or all handshakes using + * that certificate will fail. It is your responsibility + * to ensure that; this function will not perform any check. + * You may use mbedtls_pk_check_pair() in order to perform + * this check yourself, but be aware that this function can + * be computationally expensive on some key types. + * + * \param conf SSL configuration + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +/** + * \brief Configure a pre-shared key (PSK) and identity + * to be used in PSK-based ciphersuites. + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note A PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback + * takes precedence over a PSK configured by this function. + * + * \warning Currently, clients can only register a single pre-shared key. + * Calling this function or mbedtls_ssl_conf_psk_opaque() more + * than once will overwrite values configured in previous calls. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature, + * but feedback is welcomed. + * + * \param conf The SSL configuration to register the PSK with. + * \param psk The pointer to the pre-shared key to use. + * \param psk_len The length of the pre-shared key in bytes. + * \param psk_identity The pointer to the pre-shared key identity. + * \param psk_identity_len The length of the pre-shared key identity + * in bytes. + * + * \note The PSK and its identity are copied internally and + * hence need not be preserved by the caller for the lifetime + * of the SSL configuration. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Configure an opaque pre-shared key (PSK) and identity + * to be used in PSK-based ciphersuites. + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note An opaque PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in + * the PSK callback takes precedence over an opaque PSK + * configured by this function. + * + * \warning Currently, clients can only register a single pre-shared key. + * Calling this function or mbedtls_ssl_conf_psk() more than + * once will overwrite values configured in previous calls. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature, + * but feedback is welcomed. + * + * \param conf The SSL configuration to register the PSK with. + * \param psk The identifier of the key slot holding the PSK. + * Until \p conf is destroyed or this function is successfully + * called again, the key slot \p psk must be populated with a + * key of type PSA_ALG_CATEGORY_KEY_DERIVATION whose policy + * allows its use for the key derivation algorithm applied + * in the handshake. + * \param psk_identity The pointer to the pre-shared key identity. + * \param psk_identity_len The length of the pre-shared key identity + * in bytes. + * + * \note The PSK identity hint is copied internally and hence need + * not be preserved by the caller for the lifetime of the + * SSL configuration. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, + psa_key_id_t psk, + const unsigned char *psk_identity, + size_t psk_identity_len ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief Set the pre-shared Key (PSK) for the current handshake. + * + * \note This should only be called inside the PSK callback, + * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \note A PSK set by this function takes precedence over a PSK + * configured by \c mbedtls_ssl_conf_psk(). + * + * \param ssl The SSL context to configure a PSK for. + * \param psk The pointer to the pre-shared key. + * \param psk_len The length of the pre-shared key in bytes. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Set an opaque pre-shared Key (PSK) for the current handshake. + * + * \note This should only be called inside the PSK callback, + * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \note An opaque PSK set by this function takes precedence over an + * opaque PSK configured by \c mbedtls_ssl_conf_psk_opaque(). + * + * \param ssl The SSL context to configure a PSK for. + * \param psk The identifier of the key slot holding the PSK. + * For the duration of the current handshake, the key slot + * must be populated with a key of type + * PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its + * use for the key derivation algorithm + * applied in the handshake. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, + psa_key_id_t psk ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief Set the PSK callback (server-side only). + * + * If set, the PSK callback is called for each + * handshake where a PSK-based ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: + * - \c void*: The opaque pointer \p p_psk. + * - \c mbedtls_ssl_context*: The SSL context to which + * the operation applies. + * - \c const unsigned char*: The PSK identity + * selected by the client. + * - \c size_t: The length of the PSK identity + * selected by the client. + * + * If a valid PSK identity is found, the callback should use + * \c mbedtls_ssl_set_hs_psk() or + * \c mbedtls_ssl_set_hs_psk_opaque() + * on the SSL context to set the correct PSK and return \c 0. + * Any other return value will result in a denied PSK identity. + * + * \note A dynamic PSK (i.e. set by the PSK callback) takes + * precedence over a static PSK (i.e. set by + * \c mbedtls_ssl_conf_psk() or + * \c mbedtls_ssl_conf_psk_opaque()). + * This means that if you set a PSK callback using this + * function, you don't need to set a PSK using + * \c mbedtls_ssl_conf_psk() or + * \c mbedtls_ssl_conf_psk_opaque()). + * + * \param conf The SSL configuration to register the callback with. + * \param f_psk The callback for selecting and setting the PSK based + * in the PSK identity chosen by the client. + * \param p_psk A pointer to an opaque structure to be passed to + * the callback, for example a PSK store. + */ +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read as hexadecimal strings (server-side only) + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus + * \param dhm_G Diffie-Hellman-Merkle generator + * + * \deprecated Superseded by \c mbedtls_ssl_conf_dh_param_bin. + * + * \return 0 if successful + */ +MBEDTLS_DEPRECATED int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, + const char *dhm_P, + const char *dhm_G ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Set the Diffie-Hellman public P and G values + * from big-endian binary presentations. + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form + * \param P_len Length of DHM modulus + * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form + * \param G_len Length of DHM generator + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ); + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read from existing context (server-side only) + * + * \param conf SSL configuration + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); +#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the minimum length for Diffie-Hellman parameters. + * (Client-side only.) + * (Default: 1024 bits.) + * + * \param conf SSL configuration + * \param bitlen Minimum bit length of the DHM prime + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ); +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Set the allowed curves in order of preference. + * (Default: all defined curves in order of decreasing size, + * except that Montgomery curves come last. This order + * is likely to change in a future version.) + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves accepted for use in + * ECDHE and in the peer's end-entity certificate. + * + * \note This has no influence on which curves are allowed inside the + * certificate chains, see \c mbedtls_ssl_conf_cert_profile() + * for that. For the end-entity certificate however, the key + * will be accepted only if it is allowed both by this list + * and by the cert profile. + * + * \note This list should be ordered by decreasing preference + * (preferred curve first). + * + * \param conf SSL configuration + * \param curves Ordered list of allowed curves, + * terminated by MBEDTLS_ECP_DP_NONE. + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/** + * \brief Set the allowed hashes for signatures during the handshake. + * (Default: all SHA-2 hashes, largest first. Also SHA-1 if + * the compile-time option + * `MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE` is enabled.) + * + * \note This only affects which hashes are offered and can be used + * for signatures during the handshake. Hashes for message + * authentication and the TLS PRF are controlled by the + * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes + * used for certificate signature are controlled by the + * verification profile, see \c mbedtls_ssl_conf_cert_profile(). + * + * \note This list should be ordered by decreasing preference + * (preferred hash first). + * + * \param conf SSL configuration + * \param hashes Ordered list of allowed signature hashes, + * terminated by \c MBEDTLS_MD_NONE. + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ); +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, + * too, if that extension is enabled. (client-side only) + * + * \param ssl SSL context + * \param hostname the server hostname, may be NULL to clear hostname + + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. + * + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * too long input hostname. + * + * Hostname set to the one provided on success (cleared + * when NULL). On allocation failure hostname is cleared. + * On too long input failure, old hostname is unchanged. + */ +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set own certificate and key for the current handshake + * + * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); + +/** + * \brief Set the data required to verify peer certificate for the + * current handshake + * + * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or + * MBEDTLS_SSL_VERIFY_REQUIRED + */ +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, mbedtls_ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback must set the + * certificate(s) and key(s) to use with \c + * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), + * and may optionally adjust the CA and associated CRL with \c + * mbedtls_ssl_set_hs_ca_chain() as well as the client + * authentication mode with \c mbedtls_ssl_set_hs_authmode(), + * then must return 0. If no matching name is found, the + * callback must either set a default cert, or + * return non-zero to abort the handshake at this point. + * + * \param conf SSL configuration + * \param f_sni verification function + * \param p_sni verification parameter + */ +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/** + * \brief Set the EC J-PAKE password for current handshake. + * + * \note An internal copy is made, and destroyed as soon as the + * handshake is completed, or when the SSL context is reset or + * freed. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret) + * \param pw_len length of pw in bytes + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ); +#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param conf SSL configuration + * \param protos Pointer to a NULL-terminated list of supported protocols, + * in decreasing preference order. The pointer to the list is + * recorded by the library for later reference as required, so + * the lifetime of the table must be at least as long as the + * lifetime of the SSL configuration structure. + * + * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. + */ +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protocol name, or NULL if no protocol was negotiated. + */ +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +#if defined(MBEDTLS_DEBUG_C) +static inline const char *mbedtls_ssl_get_srtp_profile_as_string( mbedtls_ssl_srtp_profile profile ) +{ + switch( profile ) + { + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: + return( "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80" ); + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: + return( "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32" ); + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: + return( "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80" ); + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: + return( "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32" ); + default: break; + } + return( "" ); +} +#endif /* MBEDTLS_DEBUG_C */ +/** + * \brief Manage support for mki(master key id) value + * in use_srtp extension. + * MKI is an optional part of SRTP used for key management + * and re-keying. See RFC3711 section 3.1 for details. + * The default value is + * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED. + * + * \param conf The SSL configuration to manage mki support. + * \param support_mki_value Enable or disable mki usage. Values are + * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED + * or #MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED. + */ +void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf, + int support_mki_value ); + +/** + * \brief Set the supported DTLS-SRTP protection profiles. + * + * \param conf SSL configuration + * \param profiles Pointer to a List of MBEDTLS_TLS_SRTP_UNSET terminated + * supported protection profiles + * in decreasing preference order. + * The pointer to the list is recorded by the library + * for later reference as required, so the lifetime + * of the table must be at least as long as the lifetime + * of the SSL configuration structure. + * The list must not hold more than + * MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH elements + * (excluding the terminating MBEDTLS_TLS_SRTP_UNSET). + * + * \return 0 on success + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA when the list of + * protection profiles is incorrect. + */ +int mbedtls_ssl_conf_dtls_srtp_protection_profiles + ( mbedtls_ssl_config *conf, + const mbedtls_ssl_srtp_profile *profiles ); + +/** + * \brief Set the mki_value for the current DTLS-SRTP session. + * + * \param ssl SSL context to use. + * \param mki_value The MKI value to set. + * \param mki_len The length of the MKI value. + * + * \note This function is relevant on client side only. + * The server discovers the mki value during handshake. + * A mki value set on server side using this function + * is ignored. + * + * \return 0 on success + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE + */ +int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl, + unsigned char *mki_value, + uint16_t mki_len ); +/** + * \brief Get the negotiated DTLS-SRTP information: + * Protection profile and MKI value. + * + * \warning This function must be called after the handshake is + * completed. The value returned by this function must + * not be trusted or acted upon before the handshake completes. + * + * \param ssl The SSL context to query. + * \param dtls_srtp_info The negotiated DTLS-SRTP information: + * - Protection profile in use. + * A direct mapping of the iana defined value for protection + * profile on an uint16_t. + http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + * #MBEDTLS_TLS_SRTP_UNSET if the use of SRTP was not negotiated + * or peer's Hello packet was not parsed yet. + * - mki size and value( if size is > 0 ). + */ +void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl, + mbedtls_dtls_srtp_info *dtls_srtp_info ); +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * + * \note This ignores ciphersuites from higher versions. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: TLS 1.0) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and + * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, + * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, + * MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the fallback flag (client-side only). + * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). + * + * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback + * connection, that is a connection with max_version set to a + * lower value than the value you're willing to use. Such + * fallback connections are not recommended but are sometimes + * necessary to interoperate with buggy (version-intolerant) + * servers. + * + * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for + * non-fallback connections! This would appear to work for a + * while, then cause failures when the server is upgraded to + * support a newer TLS version. + * + * \param conf SSL configuration + * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK + */ +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); +#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: MBEDTLS_SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED + */ +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED + */ +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_ARC4_C) +/** + * \brief Disable or enable support for RC4 + * (Default: MBEDTLS_SSL_ARC4_DISABLED) + * + * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 + * for security reasons. Use at your own risk. + * + * \note This function is deprecated and will be removed in + * a future version of the library. + * RC4 is disabled by default at compile time and needs to be + * actively enabled for use with legacy systems. + * + * \param conf SSL configuration + * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED + */ +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate. + * (Typical: the smaller of #MBEDTLS_SSL_IN_CONTENT_LEN and + * #MBEDTLS_SSL_OUT_CONTENT_LEN, usually `2^14` bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake) + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE) + * + * \note On the client side, the maximum fragment length extension + * *will not* be used, unless the maximum fragment length has + * been set via this function to a value different than + * #MBEDTLS_SSL_MAX_FRAG_LEN_NONE. + * + * \note With TLS, this currently only affects ApplicationData (sent + * with \c mbedtls_ssl_read()), not handshake messages. + * With DTLS, this affects both ApplicationData and handshake. + * + * \note This sets the maximum length for a record's payload, + * excluding record overhead that will be added to it, see + * \c mbedtls_ssl_get_record_expansion(). + * + * \note For DTLS, it is also possible to set a limit for the total + * size of datagrams passed to the transport layer, including + * record overhead, see \c mbedtls_ssl_set_mtu(). + * + * \param conf SSL configuration + * \param mfl_code Code for maximum fragment length (allowed values: + * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, + * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) + * + * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + */ +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +/** + * \brief Activate negotiation of truncated HMAC + * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + * + * \param conf SSL configuration + * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or + * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) + */ +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +/** + * \brief Enable / Disable 1/n-1 record splitting + * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) + * + * \note Only affects SSLv3 and TLS 1.0, not higher versions. + * Does not affect non-CBC ciphersuites in any version. + * + * \param conf SSL configuration + * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or + * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED + */ +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Enable / Disable session tickets (client only). + * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) + * + * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). + * + * \param conf SSL configuration + * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or + * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) + */ +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) + * + * \warning It is recommended to always disable renegotiation unless you + * know you need it and you know what you're doing. In the + * past, there have been several issues associated with + * renegotiation or a poor understanding of its properties. + * + * \note Server-side, enabling renegotiation also makes the server + * susceptible to a resource DoS by a malicious client. + * + * \param conf SSL configuration + * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or + * MBEDTLS_SSL_RENEGOTIATION_DISABLED) + */ +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) + * + * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param conf SSL configuration + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) + */ +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enforce renegotiation requests. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \note With DTLS and server-initiated renegotiation, the + * HelloRequest is retransmitted every time mbedtls_ssl_read() times + * out or receives Application Data, until: + * - max_records records have beens seen, if it is >= 0, or + * - the number of retransmits that would happen during an + * actual handshake has been reached. + * Please remember the request might be lost a few times + * if you consider setting max_records to a really low value. + * + * \warning On client, the grace period can only happen during + * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during mbedtls_ssl_read(). + * + * \param conf SSL configuration + * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^48 - 1) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or incoming) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * + * \param conf SSL configuration + * \param period The threshold value: a big-endian 64-bit number. + */ +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Check if there is data already read from the + * underlying transport but not yet processed. + * + * \param ssl SSL context + * + * \return 0 if nothing's pending, 1 otherwise. + * + * \note This is different in purpose and behaviour from + * \c mbedtls_ssl_get_bytes_avail in that it considers + * any kind of unprocessed data, not only unread + * application data. If \c mbedtls_ssl_get_bytes + * returns a non-zero value, this function will + * also signal pending data, but the converse does + * not hold. For example, in DTLS there might be + * further records waiting to be processed from + * the current underlying transport's datagram. + * + * \note If this function returns 1 (data pending), this + * does not imply that a subsequent call to + * \c mbedtls_ssl_read will provide any data; + * e.g., the unprocessed data might turn out + * to be an alert or a handshake message. + * + * \note This function is useful in the following situation: + * If the SSL/TLS module successfully returns from an + * operation - e.g. a handshake or an application record + * read - and you're awaiting incoming data next, you + * must not immediately idle on the underlying transport + * to have data ready, but you need to check the value + * of this function first. The reason is that the desired + * data might already be read but not yet processed. + * If, in contrast, a previous call to the SSL/TLS module + * returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary + * to call this function, as the latter error code entails + * that all internal data has been processed. + * + */ +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the number of application data bytes + * remaining to be read from the current record. + * + * \param ssl SSL context + * + * \return How many bytes are available in the application + * data record read buffer. + * + * \note When working over a datagram transport, this is + * useful to detect the current datagram's boundary + * in case \c mbedtls_ssl_read has written the maximal + * amount of data fitting into the input buffer. + * + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl The SSL context to use. + * + * \return \c 0 if the certificate verification was successful. + * \return \c -1u if the result is not available. This may happen + * e.g. if the handshake aborts early, or a verification + * callback returned a fatal error. + * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX + * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current SSL version (SSLv3/TLSv1/etc) + * + * \param ssl SSL context + * + * \return a string containing the SSL version + */ +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) + * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes, or + * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is + * enabled, which makes expansion much less predictable + */ +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the output buffer. For the client, this is the configured + * value. For the server, it is the minimum of two - the + * configured value and the negotiated one. + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the input buffer. This is the negotiated maximum fragment + * length, or, if there is none, MBEDTLS_SSL_MAX_CONTENT_LEN. + * If it is not defined either, the value is 2^14. This function + * works as its predecessor, \c mbedtls_ssl_get_max_frag_len(). + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function is a deprecated approach to getting the max + * fragment length. Its an alias for + * \c mbedtls_ssl_get_output_max_frag_len(), as the behaviour + * is the same. See \c mbedtls_ssl_get_output_max_frag_len() for + * more detail. + * + * \sa mbedtls_ssl_get_input_max_frag_len() + * \sa mbedtls_ssl_get_output_max_frag_len() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +MBEDTLS_DEPRECATED size_t mbedtls_ssl_get_max_frag_len( + const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +/** + * \brief Return the current maximum outgoing record payload in bytes. + * This takes into account the config.h setting \c + * MBEDTLS_SSL_OUT_CONTENT_LEN, the configured and negotiated + * max fragment length extension if used, and for DTLS the + * path MTU as configured and current record expansion. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \note This function is not available (always returns an error) + * when record compression is enabled. + * + * \sa mbedtls_ssl_set_mtu() + * \sa mbedtls_ssl_get_output_max_frag_len() + * \sa mbedtls_ssl_get_input_max_frag_len() + * \sa mbedtls_ssl_get_record_expansion() + * + * \param ssl SSL context + * + * \return Current maximum payload for an outgoing record, + * or a negative error code. + */ +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection. + * + * \param ssl The SSL context to use. This must be initialized and setup. + * + * \return The current peer certificate, if available. + * The returned certificate is owned by the SSL context and + * is valid only until the next call to the SSL API. + * \return \c NULL if no peer certificate is available. This might + * be because the chosen ciphersuite doesn't use CRTs + * (PSK-based ciphersuites, for example), or because + * #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled, + * allowing the stack to free the peer's CRT to save memory. + * + * \note For one-time inspection of the peer's certificate during + * the handshake, consider registering an X.509 CRT verification + * callback through mbedtls_ssl_conf_verify() instead of calling + * this function. Using mbedtls_ssl_conf_verify() also comes at + * the benefit of allowing you to influence the verification + * process, for example by masking expected and tolerated + * verification failures. + * + * \warning You must not use the pointer returned by this function + * after any further call to the SSL API, including + * mbedtls_ssl_read() and mbedtls_ssl_write(); this is + * because the pointer might change during renegotiation, + * which happens transparently to the user. + * If you want to use the certificate across API calls, + * you must make a copy. + */ +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Save session in order to resume it later (client-side only) + * Session data is copied to presented session structure. + * + * + * \param ssl SSL context + * \param session session context + * + * \return 0 if successful, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or + * arguments are otherwise invalid. + * + * \note Only the server certificate is copied, and not the full chain, + * so you should not attempt to validate the certificate again + * by calling \c mbedtls_x509_crt_verify() on it. + * Instead, you should use the results from the verification + * in the original handshake by calling \c mbedtls_ssl_get_verify_result() + * after loading the session again into a new SSL context + * using \c mbedtls_ssl_set_session(). + * + * \note Once the session object is not needed anymore, you should + * free it by calling \c mbedtls_ssl_session_free(). + * + * \sa mbedtls_ssl_set_session() + */ +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use + * and the client did not demonstrate reachability yet - in + * this case you must stop using the context (see below). + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. + * + * \note Remarks regarding event-driven DTLS: + * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. This is not true for a successful handshake, + * in which case the datagram of the underlying transport that is + * currently being processed might or might not contain further + * DTLS records. + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * \note The state of the context (ssl->state) will be at + * the next state after this function returns \c 0. Do not + * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * + * \param ssl SSL context + * + * \return See mbedtls_ssl_handshake(). + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to mbedtls_ssl_read() if honored by + * client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any mbedtls_ssl_handshake() return + * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't + * happen during a renegotiation. + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. + * + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return The (positive) number of bytes read if successful. + * \return \c 0 if the read end of the underlying transport was closed + * without sending a CloseNotify beforehand, which might happen + * because of various reasons (internal error of an underlying + * stack, non-conformant peer not sending a CloseNotify and + * such) - in this case you must stop using the context + * (see below). + * \return #MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY if the underlying + * transport is still functional, but the peer has + * acknowledged to not send anything anymore. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server + * side of a DTLS connection and the client is initiating a + * new connection using the same source port. See below. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a positive value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * (which can only happen server-side), it means that a client + * is initiating a new connection using the same source port. + * You can either treat that as a connection close and wait + * for the client to resend a ClientHello, or directly + * continue with \c mbedtls_ssl_handshake() with the same + * context (as it has been reset internally). Either way, you + * must make sure this is seen by the application as a new + * connection: application state, if any, should be reset, and + * most importantly the identity of the client must be checked + * again. WARNING: not validating the identity of the client + * again, or not transmitting the new identity to the + * application layer, would allow authentication bypass! + * + * \note Remarks regarding event-driven DTLS: + * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. + * - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was + * initially available on the underlying transport, as this data may have + * been only e.g. duplicated messages or a renegotiation request. + * Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even + * when reacting to an incoming-data event from the underlying transport. + * - On success, the datagram of the underlying transport that is currently + * being processed may contain further DTLS records. You should call + * \c mbedtls_ssl_check_pending to check for remaining records. + * + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Try to write exactly 'len' application data bytes + * + * \warning This function will do partial writes in some cases. If the + * return value is non-negative but less than length, the + * function must be called again with updated arguments: + * buf + ret, len - ret (if ret is the return value) until + * it returns a value equal to the last 'len' argument. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a non-negative value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * it must be called later with the *same* arguments, + * until it returns a value greater that or equal to 0. When + * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be + * some partial data in the output buffer, however this is not + * yet sent. + * + * \note If the requested length is greater than the maximum + * fragment length (either the built-in limit or the one set + * or negotiated with the peer), then: + * - with TLS, less bytes than requested are written. + * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. + * \c mbedtls_ssl_get_output_max_frag_len() may be used to + * query the active maximum fragment length. + * + * \note Attempting to write 0 bytes will result in an empty TLS + * application record being sent. + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. + */ +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +/** + * \brief Save an active connection as serialized data in a buffer. + * This allows the freeing or re-using of the SSL context + * while still picking up the connection later in a way that + * it entirely transparent to the peer. + * + * \see mbedtls_ssl_context_load() + * + * \note This feature is currently only available under certain + * conditions, see the documentation of the return value + * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. + * + * \note When this function succeeds, it calls + * mbedtls_ssl_session_reset() on \p ssl which as a result is + * no longer associated with the connection that has been + * serialized. This avoids creating copies of the connection + * state. You're then free to either re-use the context + * structure for a different connection, or call + * mbedtls_ssl_free() on it. See the documentation of + * mbedtls_ssl_session_reset() for more details. + * + * \param ssl The SSL context to save. On success, it is no longer + * associated with the connection that has been serialized. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p buf_len bytes, or may be \c + * NULL if \p buf_len is \c 0. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. However, + * the value of \p olen is only guaranteed to be correct when + * the function returns #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL or + * \c 0. If the return value is different, then the value of + * \p olen is undefined. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed + * while resetting the context. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in + * progress, or there is pending data for reading or sending, + * or the connection does not use DTLS 1.2 with an AEAD + * ciphersuite, or renegotiation is enabled. + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ); + +/** + * \brief Load serialized connection data to an SSL context. + * + * \see mbedtls_ssl_context_save() + * + * \warning The same serialized data must never be loaded into more + * that one context. In order to ensure that, after + * successfully loading serialized data to an SSL context, you + * should immediately destroy or invalidate all copies of the + * serialized data that was loaded. Loading the same data in + * more than one context would cause severe security failures + * including but not limited to loss of confidentiality. + * + * \note Before calling this function, the SSL context must be + * prepared in one of the two following ways. The first way is + * to take a context freshly initialised with + * mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with + * the same ::mbedtls_ssl_config structure that was used in + * the original connection. The second way is to + * call mbedtls_ssl_session_reset() on a context that was + * previously prepared as above but used in the meantime. + * Either way, you must not use the context to perform a + * handshake between calling mbedtls_ssl_setup() or + * mbedtls_ssl_session_reset() and calling this function. You + * may however call other setter functions in that time frame + * as indicated in the note below. + * + * \note Before or after calling this function successfully, you + * also need to configure some connection-specific callbacks + * and settings before you can use the connection again + * (unless they were already set before calling + * mbedtls_ssl_session_reset() and the values are suitable for + * the present connection). Specifically, you want to call + * at least mbedtls_ssl_set_bio() and + * mbedtls_ssl_set_timer_cb(). All other SSL setter functions + * are not necessary to call, either because they're only used + * in handshakes, or because the setting is already saved. You + * might choose to call them anyway, for example in order to + * share code between the cases of establishing a new + * connection and the case of loading an already-established + * connection. + * + * \note If you have new information about the path MTU, you want to + * call mbedtls_ssl_set_mtu() after calling this function, as + * otherwise this function would overwrite your + * newly-configured value with the value that was active when + * the context was saved. + * + * \note When this function returns an error code, it calls + * mbedtls_ssl_free() on \p ssl. In this case, you need to + * prepare the context with the usual sequence starting with a + * call to mbedtls_ssl_init() if you want to use it again. + * + * \param ssl The SSL context structure to be populated. It must have + * been prepared as described in the note above. + * \param buf The buffer holding the serialized connection data. It must + * be a readable buffer of at least \p len bytes. + * \param len The size of the serialized data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data + * comes from a different Mbed TLS version or build. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ); +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + +/** + * \brief Initialize an SSL configuration context + * Just makes the context ready for + * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). + * + * \note You need to call mbedtls_ssl_config_defaults() unless you + * manually set all of the relevant fields yourself. + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); + +/** + * \brief Load reasonable default SSL configuration values. + * (You need to call mbedtls_ssl_config_init() first.) + * + * \param conf SSL configuration context + * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS + * \param preset a MBEDTLS_SSL_PRESET_XXX value + * + * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. + * + * \return 0 if successful, or + * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ); + +/** + * \brief Free an SSL configuration context + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \note A session object can be freed even if the SSL context + * that was used to retrieve the session is still in use. + * + * \param session SSL session + */ +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); + +/** + * \brief TLS-PRF function for key derivation. + * + * \param prf The tls_prf type function type to be used. + * \param secret Secret for the key derivation function. + * \param slen Length of the secret. + * \param label String label for the key derivation function, + * terminated with null character. + * \param random Random bytes. + * \param rlen Length of the random bytes buffer. + * \param dstbuf The buffer holding the derived key. + * \param dlen Length of the output buffer. + * + * \return 0 on success. An SSL specific error on failure. + */ +int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h new file mode 100644 index 0000000..02eab96 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h @@ -0,0 +1,149 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SSL_CACHE_H +#define MBEDTLS_SSL_CACHE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) +#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/** \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; +typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct mbedtls_ssl_cache_entry +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t timestamp; /*!< entry timestamp */ +#endif + mbedtls_ssl_session session; /*!< entry session */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ +#endif + mbedtls_ssl_cache_entry *next; /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct mbedtls_ssl_cache_context +{ + mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ + int timeout; /*!< cache entry timeout */ + int max_entries; /*!< maximum entries */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to retrieve entry for + */ +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data SSL cache context + * \param session session to store entry for + */ +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); +#endif /* MBEDTLS_HAVE_TIME */ + +/** + * \brief Set the maximum number of cache entries + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h new file mode 100644 index 0000000..93c32a5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h @@ -0,0 +1,556 @@ +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/pk.h" +#include "mbedtls/cipher.h" +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 +#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 +#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A + +#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A +#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E +#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 +#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* RFC 7905 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED +#endif + +/* Key exchanges allowing client certificate requests */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED +#endif + +/* Key exchanges involving server signature in ServerKeyExchange */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED +#endif + +/* Key exchanges using ECDH */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED +#endif + +/* Key exchanges that don't involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED +#endif + +/* Key exchanges that involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED +#endif + +/* Key exchanges using a PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED +#endif + +/* Key exchanges using DHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED +#endif + +/* Key exchanges using ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED +#endif + +typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; + +#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ +#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct mbedtls_ssl_ciphersuite_t +{ + int id; + const char * name; + + mbedtls_cipher_type_t cipher; + mbedtls_md_type_t mac; + mbedtls_key_exchange_type_t key_exchange; + + int min_major_ver; + int min_minor_ver; + int max_major_ver; + int max_minor_ver; + + unsigned char flags; +}; + +const int *mbedtls_ssl_list_ciphersuites( void ); + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); +#endif + +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +static inline int mbedtls_ssl_ciphersuite_uses_srv_cert( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h new file mode 100644 index 0000000..2aa3731 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h @@ -0,0 +1,113 @@ +/** + * \file ssl_cookie.h + * + * \brief DTLS cookie callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SSL_COOKIE_H +#define MBEDTLS_SSL_COOKIE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ +#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT +#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ +#endif + +/** \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Context for the default cookie functions. + */ +typedef struct mbedtls_ssl_cookie_ctx +{ + mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ +#if !defined(MBEDTLS_HAVE_TIME) + unsigned long serial; /*!< serial number for expiration */ +#endif + unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_ssl_cookie_ctx; + +/** + * \brief Initialize cookie context + */ +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Setup cookie context (generate keys) + */ +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set expiration delay for cookies + * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) + * + * \param ctx Cookie context + * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies + * issued in the meantime. + * 0 to disable expiration (NOT recommended) + */ +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); + +/** + * \brief Free cookie context + */ +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; + +/** + * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cookie.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h new file mode 100644 index 0000000..46ade67 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_internal.h @@ -0,0 +1,1352 @@ +/** + * \file ssl_internal.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SSL_INTERNAL_H +#define MBEDTLS_SSL_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#include "mbedtls/ecjpake.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Determine minimum supported version */ +#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +/* Determine maximum supported version */ +#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 +#else +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +/* Shorthand for restartable ECC */ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED +#endif + +#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) + * and allow for a maximum of 1024 of compression expansion if + * enabled. + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) +#define MBEDTLS_SSL_COMPRESSION_ADD 1024 +#else +#define MBEDTLS_SSL_COMPRESSION_ADD 0 +#endif + +/* This macro determines whether CBC is supported. */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || \ + defined(MBEDTLS_CAMELLIA_C) || \ + defined(MBEDTLS_ARIA_C) || \ + defined(MBEDTLS_DES_C) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC +#endif + +/* This macro determines whether the CBC construct used in TLS 1.0-1.2 (as + * opposed to the very different CBC construct used in SSLv3) is supported. */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) +#define MBEDTLS_SSL_SOME_MODES_USE_MAC +#endif + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define MBEDTLS_SSL_MAC_ADD 16 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_SSL_PADDING_ADD 256 +#else +#define MBEDTLS_SSL_PADDING_ADD 0 +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_MAX_CID_EXPANSION MBEDTLS_SSL_CID_PADDING_GRANULARITY +#else +#define MBEDTLS_SSL_MAX_CID_EXPANSION 0 +#endif + +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_SSL_COMPRESSION_ADD + \ + MBEDTLS_MAX_IV_LENGTH + \ + MBEDTLS_SSL_MAC_ADD + \ + MBEDTLS_SSL_PADDING_ADD + \ + MBEDTLS_SSL_MAX_CID_EXPANSION \ + ) + +#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_IN_CONTENT_LEN ) ) + +#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_OUT_CONTENT_LEN ) ) + +/* The maximum number of buffered handshake messages. */ +#define MBEDTLS_SSL_MAX_BUFFERED_HS 4 + +/* Maximum length we can advertise as our max content length for + RFC 6066 max_fragment_length extension negotiation purposes + (the lesser of both sizes, if they are unequal.) + */ +#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ + (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ + ? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \ + : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \ + ) + +/* Maximum size in bytes of list in sig-hash algorithm ext., RFC 5246 */ +#define MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN 65534 + +/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ +#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_MAX_CONTENT_LEN > 16384 +#error "Bad configuration - record content too large." +#endif + +#if MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - incoming record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN +#error "Bad configuration - outgoing record content should not be larger than MBEDTLS_SSL_MAX_CONTENT_LEN." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." +#endif + +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_MAX_CONTENT_LEN + 2048 +#error "Bad configuration - outgoing protected record payload too large." +#endif + +/* Calculate buffer sizes */ + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) ) +#else +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) \ + + ( MBEDTLS_SSL_CID_IN_LEN_MAX ) ) +#endif + +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) ) +#else +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) \ + + ( MBEDTLS_SSL_CID_OUT_LEN_MAX ) ) +#endif + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +static inline size_t mbedtls_ssl_get_output_buflen( const mbedtls_ssl_context *ctx ) +{ +#if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID) + return mbedtls_ssl_get_output_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_OUT_LEN_MAX; +#else + return mbedtls_ssl_get_output_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} + +static inline size_t mbedtls_ssl_get_input_buflen( const mbedtls_ssl_context *ctx ) +{ +#if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID) + return mbedtls_ssl_get_input_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_IN_LEN_MAX; +#else + return mbedtls_ssl_get_input_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} +#endif + +#ifdef MBEDTLS_ZLIB_SUPPORT +/* Compression buffer holds both IN and OUT buffers, so should be size of the larger */ +#define MBEDTLS_SSL_COMPRESS_BUFFER_LEN ( \ + ( MBEDTLS_SSL_IN_BUFFER_LEN > MBEDTLS_SSL_OUT_BUFFER_LEN ) \ + ? MBEDTLS_SSL_IN_BUFFER_LEN \ + : MBEDTLS_SSL_OUT_BUFFER_LEN \ + ) +#endif + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +/** + * \brief This function checks if the remaining size in a buffer is + * greater or equal than a needed space. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + * \return Zero if the needed space is available in the buffer, non-zero + * otherwise. + */ +static inline int mbedtls_ssl_chk_buf_ptr( const uint8_t *cur, + const uint8_t *end, size_t need ) +{ + return( ( cur > end ) || ( need > (size_t)( end - cur ) ) ); +} + +/** + * \brief This macro checks if the remaining size in a buffer is + * greater or equal than a needed space. If it is not the case, + * it returns an SSL_BUFFER_TOO_SMALL error. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_PTR( cur, end, need ) \ + do { \ + if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 ) \ + { \ + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); \ + } \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Abstraction for a grid of allowed signature-hash-algorithm pairs. + */ +struct mbedtls_ssl_sig_hash_set_t +{ + /* At the moment, we only need to remember a single suitable + * hash algorithm per signature algorithm. As long as that's + * the case - and we don't need a general lookup function - + * we can implement the sig-hash-set as a map from signatures + * to hash algorithms. */ + mbedtls_md_type_t rsa; + mbedtls_md_type_t ecdsa; +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +typedef int mbedtls_ssl_tls_prf_cb( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); + +/* cipher.h exports the maximum IV, key and block length from + * all ciphers enabled in the config, regardless of whether those + * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled + * in the default configuration and uses 64 Byte keys, but it is + * not used for record protection in SSL/TLS. + * + * In order to prevent unnecessary inflation of key structures, + * we introduce SSL-specific variants of the max-{key,block,IV} + * macros here which are meant to only take those ciphers into + * account which can be negotiated in SSL/TLS. + * + * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH + * in cipher.h are rough overapproximations of the real maxima, here + * we content ourselves with replicating those overapproximations + * for the maximum block and IV length, and excluding XTS from the + * computation of the maximum key length. */ +#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16 +#define MBEDTLS_SSL_MAX_IV_LENGTH 16 +#define MBEDTLS_SSL_MAX_KEY_LENGTH 32 + +/** + * \brief The data structure holding the cryptographic material (key and IV) + * used for record protection in TLS 1.3. + */ +struct mbedtls_ssl_key_set +{ + /*! The key for client->server records. */ + unsigned char client_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ]; + /*! The key for server->client records. */ + unsigned char server_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ]; + /*! The IV for client->server records. */ + unsigned char client_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ]; + /*! The IV for server->client records. */ + unsigned char server_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ]; + + size_t key_len; /*!< The length of client_write_key and + * server_write_key, in Bytes. */ + size_t iv_len; /*!< The length of client_write_iv and + * server_write_iv, in Bytes. */ +}; +typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params +{ + /* + * Handshake specific crypto variables + */ + + uint8_t max_major_ver; /*!< max. major version client*/ + uint8_t max_minor_ver; /*!< max. minor version client*/ + uint8_t resume; /*!< session resume indicator*/ + uint8_t cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + uint8_t sni_authmode; /*!< authmode from SNI callback */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint8_t new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + uint8_t extended_ms; /*!< use Extended Master Secret? */ +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + uint8_t async_in_progress; /*!< an asynchronous operation is in progress */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned char retransmit_state; /*!< Retransmission state */ +#endif + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + uint8_t ecrs_enabled; /*!< Handshake supports EC restart? */ + enum { /* this complements ssl->state with info on intra-state operations */ + ssl_ecrs_none = 0, /*!< nothing going on (yet) */ + ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ + ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ + ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ + } ecrs_state; /*!< current (or last) operation */ + mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */ + size_t ecrs_n; /*!< place for saving a length */ +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ +#endif + + size_t pmslen; /*!< premaster length */ + + mbedtls_ssl_ciphersuite_t const *ciphersuite_info; + + void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); + void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + mbedtls_ssl_tls_prf_cb *tls_prf; + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif + +/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due + * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap + * in functionality that access to ecdh_ctx structure is needed for + * MBEDTLS_ECDSA_C which does not seem correct. + */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_type_t ecdh_psa_type; + uint16_t ecdh_bits; + psa_key_id_t ecdh_psa_privkey; + unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t ecdh_psa_peerkey_len; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_id_t psk_opaque; /*!< Opaque PSK from the callback */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */ +#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + struct + { + size_t total_bytes_buffered; /*!< Cumulative size of heap allocated + * buffers used for message buffering. */ + + uint8_t seen_ccs; /*!< Indicates if a CCS message has + * been seen in the current flight. */ + + struct mbedtls_ssl_hs_buffer + { + unsigned is_valid : 1; + unsigned is_fragmented : 1; + unsigned is_complete : 1; + unsigned char *data; + size_t data_len; + } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; + + struct + { + unsigned char *data; + size_t len; + unsigned epoch; + } future_record; + + } buffering; + + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie + Srv: unused */ + unsigned char verify_cookie_len; /*!< Cli: cookie length + Srv: flag for sending a cookie */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned char *cur_msg_p; /*!< Position in current message */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter + for resending messages */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* The state of CID configuration in this handshake. */ + + uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension + * has been negotiated. Possible values are + * #MBEDTLS_SSL_CID_ENABLED and + * #MBEDTLS_SSL_CID_DISABLED. */ + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */ + uint8_t peer_cid_len; /*!< The length of + * \c peer_cid. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Checksum contexts + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_context fin_md5; + mbedtls_sha1_context fin_sha1; +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha256_psa; +#else + mbedtls_sha256_context fin_sha256; +#endif +#endif +#if defined(MBEDTLS_SHA512_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha384_psa; +#else + mbedtls_sha512_context fin_sha512; +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + unsigned char randbytes[64]; /*!< random bytes */ + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /** Asynchronous operation context. This field is meant for use by the + * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, + * mbedtls_ssl_config::f_async_decrypt_start, + * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). + * The library does not use it internally. */ + void *user_async_ctx; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +}; + +typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; + +/* + * Representation of decryption/encryption transformations on records + * + * There are the following general types of record transformations: + * - Stream transformations (TLS versions <= 1.2 only) + * Transformation adding a MAC and applying a stream-cipher + * to the authenticated message. + * - CBC block cipher transformations ([D]TLS versions <= 1.2 only) + * In addition to the distinction of the order of encryption and + * authentication, there's a fundamental difference between the + * handling in SSL3 & TLS 1.0 and TLS 1.1 and TLS 1.2: For SSL3 + * and TLS 1.0, the final IV after processing a record is used + * as the IV for the next record. No explicit IV is contained + * in an encrypted record. The IV for the first record is extracted + * at key extraction time. In contrast, for TLS 1.1 and 1.2, no + * IV is generated at key extraction time, but every encrypted + * record is explicitly prefixed by the IV with which it was encrypted. + * - AEAD transformations ([D]TLS versions >= 1.2 only) + * These come in two fundamentally different versions, the first one + * used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second + * one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3. + * In the first transformation, the IV to be used for a record is obtained + * as the concatenation of an explicit, static 4-byte IV and the 8-byte + * record sequence number, and explicitly prepending this sequence number + * to the encrypted record. In contrast, in the second transformation + * the IV is obtained by XOR'ing a static IV obtained at key extraction + * time with the 8-byte record sequence number, without prepending the + * latter to the encrypted record. + * + * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext + * which allows to add flexible length padding and to hide a record's true + * content type. + * + * In addition to type and version, the following parameters are relevant: + * - The symmetric cipher algorithm to be used. + * - The (static) encryption/decryption keys for the cipher. + * - For stream/CBC, the type of message digest to be used. + * - For stream/CBC, (static) encryption/decryption keys for the digest. + * - For AEAD transformations, the size (potentially 0) of an explicit, + * random initialization vector placed in encrypted records. + * - For some transformations (currently AEAD and CBC in SSL3 and TLS 1.0) + * an implicit IV. It may be static (e.g. AEAD) or dynamic (e.g. CBC) + * and (if present) is combined with the explicit IV in a transformation- + * dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3). + * - For stream/CBC, a flag determining the order of encryption and MAC. + * - The details of the transformation depend on the SSL/TLS version. + * - The length of the authentication tag. + * + * Note: Except for CBC in SSL3 and TLS 1.0, these parameters are + * constant across multiple encryption/decryption operations. + * For CBC, the implicit IV needs to be updated after each + * operation. + * + * The struct below refines this abstract view as follows: + * - The cipher underlying the transformation is managed in + * cipher contexts cipher_ctx_{enc/dec}, which must have the + * same cipher type. The mode of these cipher contexts determines + * the type of the transformation in the sense above: e.g., if + * the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM + * then the transformation has type CBC resp. AEAD. + * - The cipher keys are never stored explicitly but + * are maintained within cipher_ctx_{enc/dec}. + * - For stream/CBC transformations, the message digest contexts + * used for the MAC's are stored in md_ctx_{enc/dec}. These contexts + * are unused for AEAD transformations. + * - For stream/CBC transformations and versions > SSL3, the + * MAC keys are not stored explicitly but maintained within + * md_ctx_{enc/dec}. + * - For stream/CBC transformations and version SSL3, the MAC + * keys are stored explicitly in mac_enc, mac_dec and have + * a fixed size of 20 bytes. These fields are unused for + * AEAD transformations or transformations >= TLS 1.0. + * - For transformations using an implicit IV maintained within + * the transformation context, its contents are stored within + * iv_{enc/dec}. + * - The value of ivlen indicates the length of the IV. + * This is redundant in case of stream/CBC transformations + * which always use 0 resp. the cipher's block length as the + * IV length, but is needed for AEAD ciphers and may be + * different from the underlying cipher's block length + * in this case. + * - The field fixed_ivlen is nonzero for AEAD transformations only + * and indicates the length of the static part of the IV which is + * constant throughout the communication, and which is stored in + * the first fixed_ivlen bytes of the iv_{enc/dec} arrays. + * Note: For CBC in SSL3 and TLS 1.0, the fields iv_{enc/dec} + * still store IV's for continued use across multiple transformations, + * so it is not true that fixed_ivlen == 0 means that iv_{enc/dec} are + * not being used! + * - minor_ver denotes the SSL/TLS version + * - For stream/CBC transformations, maclen denotes the length of the + * authentication tag, while taglen is unused and 0. + * - For AEAD transformations, taglen denotes the length of the + * authentication tag, while maclen is unused and 0. + * - For CBC transformations, encrypt_then_mac determines the + * order of encryption and authentication. This field is unused + * in other transformations. + * + */ +struct mbedtls_ssl_transform +{ + /* + * Session specific crypto layer + */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC(CBC) len */ + size_t taglen; /*!< TAG(AEAD) len */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* Needed only for SSL v3.0 secret */ + unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ + unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif + +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ + int minor_ver; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t in_cid_len; + uint8_t out_cid_len; + unsigned char in_cid [ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; + unsigned char out_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Session specific compression layer + */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + z_stream ctx_deflate; /*!< compression context */ + z_stream ctx_inflate; /*!< decompression context */ +#endif + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + /* We need the Hello random bytes in order to re-derive keys from the + * Master Secret and other session info, see ssl_populate_transform() */ + unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */ +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ +}; + +/* + * Return 1 if the transform uses an AEAD cipher, 0 otherwise. + * Equivalently, return 0 if a separate MAC is used, 1 otherwise. + */ +static inline int mbedtls_ssl_transform_uses_aead( + const mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + return( transform->maclen == 0 && transform->taglen != 0 ); +#else + (void) transform; + return( 1 ); +#endif +} + +/* + * Internal representation of record frames + * + * Instances come in two flavors: + * (1) Encrypted + * These always have data_offset = 0 + * (2) Unencrypted + * These have data_offset set to the amount of + * pre-expansion during record protection. Concretely, + * this is the length of the fixed part of the explicit IV + * used for encryption, or 0 if no explicit IV is used + * (e.g. for CBC in TLS 1.0, or stream ciphers). + * + * The reason for the data_offset in the unencrypted case + * is to allow for in-place conversion of an unencrypted to + * an encrypted record. If the offset wasn't included, the + * encrypted content would need to be shifted afterwards to + * make space for the fixed IV. + * + */ +#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX +#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX +#else +#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX +#endif + +typedef struct +{ + uint8_t ctr[8]; /* In TLS: The implicit record sequence number. + * In DTLS: The 2-byte epoch followed by + * the 6-byte sequence number. + * This is stored as a raw big endian byte array + * as opposed to a uint64_t because we rarely + * need to perform arithmetic on this, but do + * need it as a Byte array for the purpose of + * MAC computations. */ + uint8_t type; /* The record content type. */ + uint8_t ver[2]; /* SSL/TLS version as present on the wire. + * Convert to internal presentation of versions + * using mbedtls_ssl_read_version() and + * mbedtls_ssl_write_version(). + * Keep wire-format for MAC computations. */ + + unsigned char *buf; /* Memory buffer enclosing the record content */ + size_t buf_len; /* Buffer length */ + size_t data_offset; /* Offset of record content */ + size_t data_len; /* Length of record content */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t cid_len; /* Length of the CID (0 if not present) */ + unsigned char cid[ MBEDTLS_SSL_CID_LEN_MAX ]; /* The CID */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +} mbedtls_record; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct mbedtls_ssl_key_cert +{ + mbedtls_x509_crt *cert; /*!< cert */ + mbedtls_pk_context *key; /*!< private key */ + mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +struct mbedtls_ssl_flight_item +{ + unsigned char *p; /*!< message, including handshake headers */ + size_t len; /*!< length of p */ + unsigned char type; /*!< type of the message: handshake or CCS */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ); +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ); +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ); + +/* Setup an empty signature-hash set */ +static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) +{ + mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); + +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl The SSL context to use. + * \param update_hs_digest This indicates if the handshake digest + * should be automatically updated in case + * a handshake message is found. + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); + +/** + * Get the first defined PSK by order of precedence: + * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback + * 2. static PSK configured by \c mbedtls_ssl_conf_psk() + * Return a code and update the pair (PSK, PSK length) passed to this function + */ +static inline int mbedtls_ssl_get_psk( const mbedtls_ssl_context *ssl, + const unsigned char **psk, size_t *psk_len ) +{ + if( ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0 ) + { + *psk = ssl->handshake->psk; + *psk_len = ssl->handshake->psk_len; + } + + else if( ssl->conf->psk != NULL && ssl->conf->psk_len > 0 ) + { + *psk = ssl->conf->psk; + *psk_len = ssl->conf->psk_len; + } + + else + { + *psk = NULL; + *psk_len = 0; + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * Get the first defined opaque PSK by order of precedence: + * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in the PSK + * callback + * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque() + * Return an opaque PSK + */ +static inline psa_key_id_t mbedtls_ssl_get_opaque_psk( + const mbedtls_ssl_context *ssl ) +{ + if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) ) + return( ssl->handshake->psk_opaque ); + + if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) ) + return( ssl->conf->psk_opaque ); + + return( MBEDTLS_SVC_KEY_ID_INIT ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_PK_C) +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); +unsigned char mbedtls_ssl_hash_from_md_alg( int md ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); + +#if defined(MBEDTLS_ECP_C) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ); +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value + ( const uint16_t srtp_profile_value ) +{ + switch( srtp_profile_value ) + { + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: + return srtp_profile_value; + default: break; + } + return( MBEDTLS_TLS_SRTP_UNSET ); +} +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->key ); +} + +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ); +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ); + +static inline size_t mbedtls_ssl_in_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + return( 13 ); + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + return( 5 ); + } +} + +static inline size_t mbedtls_ssl_out_hdr_len( const mbedtls_ssl_context *ssl ) +{ + return( (size_t) ( ssl->out_iv - ssl->out_hdr ) ); +} + +static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 12 ); +#else + ((void) ssl); +#endif + return( 4 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ); +#endif + +/* Visible for testing purposes only */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ); +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); +#endif + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ); +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#ifdef __cplusplus +} +#endif + +void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec ); + +/* Length of the "epoch" field in the record header */ +static inline size_t mbedtls_ssl_ep_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 2 ); +#else + ((void) ssl); +#endif + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ); +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); +void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ); + +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); +#endif + +void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); +void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_TEST_HOOKS) +int mbedtls_ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_context *ssl, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ); +#endif + +#endif /* ssl_internal.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h new file mode 100644 index 0000000..8221051 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h @@ -0,0 +1,140 @@ +/** + * \file ssl_ticket.h + * + * \brief TLS server ticket callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SSL_TICKET_H +#define MBEDTLS_SSL_TICKET_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* + * This implementation of the session ticket callbacks includes key + * management, rotating the keys periodically in order to preserve forward + * secrecy, when MBEDTLS_HAVE_TIME is defined. + */ + +#include "mbedtls/ssl.h" +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Information for session ticket protection + */ +typedef struct mbedtls_ssl_ticket_key +{ + unsigned char name[4]; /*!< random key identifier */ + uint32_t generation_time; /*!< key generation timestamp (seconds) */ + mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ +} +mbedtls_ssl_ticket_key; + +/** + * \brief Context for session ticket handling functions + */ +typedef struct mbedtls_ssl_ticket_context +{ + mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ + unsigned char active; /*!< index of the currently active key */ + + uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ + + /** Callback for getting (pseudo-)random numbers */ + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; /*!< context for the RNG function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ssl_ticket_context; + +/** + * \brief Initialize a ticket context. + * (Just make it ready for mbedtls_ssl_ticket_setup() + * or mbedtls_ssl_ticket_free().) + * + * \param ctx Context to be initialized + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); + +/** + * \brief Prepare context to be actually used + * + * \param ctx Context to be set up + * \param f_rng RNG callback function + * \param p_rng RNG callback context + * \param cipher AEAD cipher to use for ticket protection. + * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note It is highly recommended to select a cipher that is at + * least as strong as the strongest ciphersuite + * supported. Usually that means a 256-bit key. + * + * \note The lifetime of the keys is twice the lifetime of tickets. + * It is recommended to pick a reasonable lifetime so as not + * to negate the benefits of forward secrecy. + * + * \return 0 if successful, + * or a specific MBEDTLS_ERR_XXX error code + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ); + +/** + * \brief Implementation of the ticket write callback + * + * \note See \c mbedtls_ssl_ticket_write_t for description + */ +mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; + +/** + * \brief Implementation of the ticket parse callback + * + * \note See \c mbedtls_ssl_ticket_parse_t for description + */ +mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; + +/** + * \brief Free a context's content and zeroize it. + * + * \param ctx Context to be cleaned up + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ticket.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h new file mode 100644 index 0000000..d147c73 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/threading.h @@ -0,0 +1,126 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +/** The selected feature is not available. */ +#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A + +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C +/** Locking / unlocking / free failed with error code. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct mbedtls_threading_mutex_t +{ + pthread_mutex_t mutex; + /* is_valid is 0 after a failed init or a free, and nonzero after a + * successful init. This field is not considered part of the public + * API of Mbed TLS and may change without notice. */ + char is_valid; +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +#if defined(MBEDTLS_FS_IO) +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +/* This mutex may or may not be used in the default definition of + * mbedtls_platform_gmtime_r(), but in order to determine that, + * we need to check POSIX features, hence modify _POSIX_C_SOURCE. + * With the current approach, this declaration is orphaned, lacking + * an accompanying definition, in case mbedtls_platform_gmtime_r() + * doesn't need it, but that's not a problem. */ +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h new file mode 100644 index 0000000..b7290cf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/timing.h @@ -0,0 +1,151 @@ +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct mbedtls_timing_delay_context +{ + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + * + * \note This value starts at an unspecified origin and + * may wrap around. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * (must be >=0) + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm( int seconds ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data. + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0), + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h new file mode 100644 index 0000000..44adcbf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/version.h @@ -0,0 +1,110 @@ +/** + * \file version.h + * + * \brief Run-time version information + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * This set of compile-time defines and run-time variables can be used to + * determine the version number of the mbed TLS library used. + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 28 +#define MBEDTLS_VERSION_PATCH 1 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x021C0100 +#define MBEDTLS_VERSION_STRING "2.28.1" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.1" + +#if defined(MBEDTLS_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int mbedtls_version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void mbedtls_version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void mbedtls_version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * \note only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") + * + * \return 0 if the feature is present, + * -1 if the feature is not present and + * -2 if support for feature checking as a whole was not + * compiled in. + */ +int mbedtls_version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_VERSION_C */ + +#endif /* version.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h new file mode 100644 index 0000000..31b78df --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509.h @@ -0,0 +1,380 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +/** Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 +/** Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 +/** The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 +/** The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 +/** The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 +/** The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 +/** The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 +/** The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 +/** The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 +/** The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 +/** CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 +/** Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 +/** Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 +/** Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 +/** Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 +/** Input invalid. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 +/** Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 +/** Read/write of file failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 +/** Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 +/** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 +/** \} name X509 Error codes */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/** \} name X509 Verify codes */ +/** \} addtogroup x509_module */ + +/* + * X.509 v3 Subject Alternative Name types. + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER + */ +#define MBEDTLS_X509_SAN_OTHER_NAME 0 +#define MBEDTLS_X509_SAN_RFC822_NAME 1 +#define MBEDTLS_X509_SAN_DNS_NAME 2 +#define MBEDTLS_X509_SAN_X400_ADDRESS_NAME 3 +#define MBEDTLS_X509_SAN_DIRECTORY_NAME 4 +#define MBEDTLS_X509_SAN_EDI_PARTY_NAME 5 +#define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER 6 +#define MBEDTLS_X509_SAN_IP_ADDRESS 7 +#define MBEDTLS_X509_SAN_REGISTERED_ID 8 + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + * + * Those are defined in oid.h as oid.c needs them in a data structure. Since + * these were previously defined here, let's have aliases for compatibility. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define MBEDTLS_X509_EXT_KEY_USAGE MBEDTLS_OID_X509_EXT_KEY_USAGE +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY +#define MBEDTLS_X509_EXT_FRESHEST_CRL MBEDTLS_OID_X509_EXT_FRESHEST_CRL +#define MBEDTLS_X509_EXT_NS_CERT_TYPE MBEDTLS_OID_X509_EXT_NS_CERT_TYPE + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param to mbedtls_x509_time to check + * + * \return 1 if the given time is in the past or an error occurred, + * 0 otherwise. + */ +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param from mbedtls_x509_time to check + * + * \return 1 if the given time is in the future or an error occurred, + * 0 otherwise. + */ +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +/** \} addtogroup x509_module */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_x509_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ); +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ); +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ); +#endif +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ); +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t ); +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ); +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ); +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ); +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#define MBEDTLS_X509_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h new file mode 100644 index 0000000..9222009 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h @@ -0,0 +1,172 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_X509_CRL_H +#define MBEDTLS_X509_CRL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct mbedtls_x509_crl_entry +{ + mbedtls_x509_buf raw; + + mbedtls_x509_buf serial; + + mbedtls_x509_time revocation_date; + + mbedtls_x509_buf entry_ext; + + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct mbedtls_x509_crl +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + mbedtls_x509_buf sig_oid2; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Multiple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Multiple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); + +/** \} name Structures and functions for parsing CRLs */ +/** \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h new file mode 100644 index 0000000..0f2885a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h @@ -0,0 +1,1097 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_X509_CRT_H +#define MBEDTLS_X509_CRT_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/x509.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/bignum.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct mbedtls_x509_crt +{ + int own_buffer; /**< Indicates if \c raw is owned + * by the structure or not. */ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_x509_buf pk_raw; + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */ + + mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ +} +mbedtls_x509_crt; + +/** + * From RFC 5280 section 4.2.1.6: + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + */ +typedef struct mbedtls_x509_san_other_name +{ + /** + * The type_id is an OID as defined in RFC 5280. + * To check the value of the type id, you should use + * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. + */ + mbedtls_x509_buf type_id; /**< The type id. */ + union + { + /** + * From RFC 4108 section 5: + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + */ + struct + { + mbedtls_x509_buf oid; /**< The object identifier. */ + mbedtls_x509_buf val; /**< The named value. */ + } + hardware_module_name; + } + value; +} +mbedtls_x509_san_other_name; + +/** + * A structure for holding the parsed Subject Alternative Name, according to type + */ +typedef struct mbedtls_x509_subject_alternative_name +{ + int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */ + union { + mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */ + mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */ + } + san; /**< A union of the supported SAN types */ +} +mbedtls_x509_subject_alternative_name; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( (id) - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +typedef struct mbedtls_x509_crt_profile +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for public keys; + * this applies to all certificates + * in the provided chain. */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +/** + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} mbedtls_x509_crt_verify_chain_item; + +/** + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/** + * Verification chain as built by \c mbedtls_crt_verify_chain() + */ +typedef struct +{ + mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + unsigned len; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* This stores the list of potential trusted signers obtained from + * the CA callback used for the CRT verification, if configured. + * We must track it somewhere because the callback passes its + * ownership to the caller. */ + mbedtls_x509_crt *trust_ca_cb_result; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} mbedtls_x509_crt_verify_chain; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Context for resuming X.509 verify operations + */ +typedef struct +{ + /* for check_signature() */ + mbedtls_pk_restart_ctx pk; + + /* for find_parent_in() */ + mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ + mbedtls_x509_crt *fallback_parent; + int fallback_signature_is_good; + + /* for find_parent() */ + int parent_is_trusted; /* -1 if find_parent is not in progress */ + + /* for verify_chain() */ + enum { + x509_crt_rs_none, + x509_crt_rs_find_parent, + } in_progress; /* none if no operation is in progress */ + int self_cnt; + mbedtls_x509_crt_verify_chain ver_chain; + +} mbedtls_x509_crt_restart_ctx; + +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_x509_crt_restart_ctx; + +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + * + * This profile permits: + * - SHA2 hashes. + * - All supported elliptic curves. + * - RSA with 2048 bits and above. + * + * New minor versions of Mbed TLS may extend this profile, for example if + * new curves are added to the library. New minor versions of Mbed TLS will + * not reduce this profile unless serious security concerns require it. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for allowing RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The buffer holding the DER encoded certificate. + * \param buflen The size in Bytes of \p buf. + * + * \note This function makes an internal copy of the CRT buffer + * \p buf. In particular, \p buf may be destroyed or reused + * after this call returns. To avoid duplicating the CRT + * buffer (at the cost of stricter lifetime constraints), + * use mbedtls_x509_crt_parse_der_nocopy() instead. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ); + +/** + * \brief The type of certificate extension callbacks. + * + * Callbacks of this type are passed to and used by the + * mbedtls_x509_crt_parse_der_with_ext_cb() routine when + * it encounters either an unsupported extension or a + * "certificate policies" extension containing any + * unsupported certificate policies. + * Future versions of the library may invoke the callback + * in other cases, if and when the need arises. + * + * \param p_ctx An opaque context passed to the callback. + * \param crt The certificate being parsed. + * \param oid The OID of the extension. + * \param critical Whether the extension is critical. + * \param p Pointer to the start of the extension value + * (the content of the OCTET STRING). + * \param end End of extension value. + * + * \note The callback must fail and return a negative error code + * if it can not parse or does not support the extension. + * When the callback fails to parse a critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. + * When the callback fails to parse a non critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips + * the extension and continues parsing. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +typedef int (*mbedtls_x509_crt_ext_cb_t)( void *p_ctx, + mbedtls_x509_crt const *crt, + mbedtls_x509_buf const *oid, + int critical, + const unsigned char *p, + const unsigned char *end ); + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The buffer holding the DER encoded certificate. + * \param buflen The size in Bytes of \p buf. + * \param make_copy When not zero this function makes an internal copy of the + * CRT buffer \p buf. In particular, \p buf may be destroyed + * or reused after this call returns. + * When zero this function avoids duplicating the CRT buffer + * by taking temporary ownership thereof until the CRT + * is destroyed (like mbedtls_x509_crt_parse_der_nocopy()) + * \param cb A callback invoked for every unsupported certificate + * extension. + * \param p_ctx An opaque context passed to the callback. + * + * \note This call is functionally equivalent to + * mbedtls_x509_crt_parse_der(), and/or + * mbedtls_x509_crt_parse_der_nocopy() + * but it calls the callback with every unsupported + * certificate extension and additionally the + * "certificate policies" extension if it contains any + * unsupported certificate policies. + * The callback must return a negative error code if it + * does not know how to handle such an extension. + * When the callback fails to parse a critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. + * When the callback fails to parse a non critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips + * the extension and continues parsing. + * Future versions of the library may invoke the callback + * in other cases, if and when the need arises. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der_with_ext_cb( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ); + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. This is a + * variant of mbedtls_x509_crt_parse_der() which takes + * temporary ownership of the CRT buffer until the CRT + * is destroyed. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The address of the readable buffer holding the DER encoded + * certificate to use. On success, this buffer must be + * retained and not be changed for the liftetime of the + * CRT chain \p chain, that is, until \p chain is destroyed + * through a call to mbedtls_x509_crt_free(). + * \param buflen The size in Bytes of \p buf. + * + * \note This call is functionally equivalent to + * mbedtls_x509_crt_parse_der(), but it avoids creating a + * copy of the input buffer at the cost of stronger lifetime + * constraints. This is useful in constrained environments + * where duplication of the CRT cannot be tolerated. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one DER-encoded or one or more concatenated PEM-encoded + * certificates and add them to the chained list. + * + * For CRTs in PEM encoding, the function parses permissively: + * if at least one certificate can be parsed, the function + * returns the number of certificates for which parsing failed + * (hence \c 0 if all certificates were parsed successfully). + * If no certificate could be parsed, the function returns + * the first (negative) error encountered during parsing. + * + * PEM encoded certificates may be interleaved by other data + * such as human readable descriptions of their content, as + * long as the certificates are enclosed in the PEM specific + * '-----{BEGIN/END} CERTIFICATE-----' delimiters. + * + * \param chain The chain to which to add the parsed certificates. + * \param buf The buffer holding the certificate data in PEM or DER format. + * For certificates in PEM encoding, this may be a concatenation + * of multiple certificates; for DER encoding, the buffer must + * comprise exactly one certificate. + * \param buflen The size of \p buf, including the terminating \c NULL byte + * in case of PEM encoded data. + * + * \return \c 0 if all certificates were parsed successfully. + * \return The (positive) number of certificates that couldn't + * be parsed if parsing was partly successful (see above). + * \return A negative X509 or PEM error code otherwise. + * + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); + +#endif /* MBEDTLS_FS_IO */ +/** + * \brief This function parses an item in the SubjectAlternativeNames + * extension. + * + * \param san_buf The buffer holding the raw data item of the subject + * alternative name. + * \param san The target structure to populate with the parsed presentation + * of the subject alternative name encoded in \p san_raw. + * + * \note Only "dnsName" and "otherName" of type hardware_module_name + * as defined in RFC 4180 is supported. + * + * \note This function should be called on a single raw data of + * subject alternative name. For example, after successful + * certificate parsing, one must iterate on every item in the + * \p crt->subject_alt_names sequence, and pass it to + * this function. + * + * \warning The target structure contains pointers to the raw data of the + * parsed certificate, and its lifetime is restricted by the + * lifetime of the certificate. + * + * \return \c 0 on success + * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported + * SAN type. + * \return Another negative value for any other failure. + */ +int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf, + mbedtls_x509_subject_alternative_name *san ); +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); + +/** + * \brief Verify a chain of certificates. + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \note The \c trust_ca list can contain two types of certificates: + * (1) those of trusted root CAs, so that certificates + * chaining up to those CAs will be trusted, and (2) + * self-signed end-entity certificates to be trusted (for + * specific peers you know) - in that case, the self-signed + * certificate doesn't need to have the CA bit set. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param cn The expected Common Name. This will be checked to be + * present in the certificate's subjectAltNames extension or, + * if this extension is absent, as a CN component in its + * Subject name. Currently only DNS names are supported. This + * may be \c NULL if the CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return \c 0 if the chain is valid with respect to the + * passed CN, CAs, CRLs and security profile. + * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the + * certificate chain verification failed. In this case, + * \c *flags will have one or more + * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX + * flags set. + * \return Another negative error code in case of a fatal error + * encountered during the verification process. + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Verify a chain of certificates with respect to + * a configurable security profile. + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param profile The security profile to use for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return \c 0 if the chain is valid with respect to the + * passed CN, CAs, CRLs and security profile. + * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the + * certificate chain verification failed. In this case, + * \c *flags will have one or more + * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX + * flags set. + * \return Another negative error code in case of a fatal error + * encountered during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Restartable version of \c mbedtls_crt_verify_with_profile() + * + * \note Performs the same job as \c mbedtls_crt_verify_with_profile() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param profile The security profile to use for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * \param rs_ctx The restart context to use. This may be set to \c NULL + * to disable restartable ECC. + * + * \return See \c mbedtls_crt_verify_with_profile(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ); + +/** + * \brief The type of trusted certificate callbacks. + * + * Callbacks of this type are passed to and used by the CRT + * verification routine mbedtls_x509_crt_verify_with_ca_cb() + * when looking for trusted signers of a given certificate. + * + * On success, the callback returns a list of trusted + * certificates to be considered as potential signers + * for the input certificate. + * + * \param p_ctx An opaque context passed to the callback. + * \param child The certificate for which to search a potential signer. + * This will point to a readable certificate. + * \param candidate_cas The address at which to store the address of the first + * entry in the generated linked list of candidate signers. + * This will not be \c NULL. + * + * \note The callback must only return a non-zero value on a + * fatal error. If, in contrast, the search for a potential + * signer completes without a single candidate, the + * callback must return \c 0 and set \c *candidate_cas + * to \c NULL. + * + * \return \c 0 on success. In this case, \c *candidate_cas points + * to a heap-allocated linked list of instances of + * ::mbedtls_x509_crt, and ownership of this list is passed + * to the caller. + * \return A negative error code on failure. + */ +typedef int (*mbedtls_x509_crt_ca_cb_t)( void *p_ctx, + mbedtls_x509_crt const *child, + mbedtls_x509_crt **candidate_cas ); + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/** + * \brief Version of \c mbedtls_x509_crt_verify_with_profile() which + * uses a callback to acquire the list of trusted CA + * certificates. + * + * \param crt The certificate chain to be verified. + * \param f_ca_cb The callback to be used to query for potential signers + * of a given child certificate. See the documentation of + * ::mbedtls_x509_crt_ca_cb_t for more information. + * \param p_ca_cb The opaque context to be passed to \p f_ca_cb. + * \param profile The security profile for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return See \c mbedtls_crt_verify_with_profile(). + */ +int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c mbedtls_x509_crt_verify(). + */ +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extendedKeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or + * MBEDTLS_OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). + * + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ); +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** \} name Structures and functions for parsing and writing X.509 certificates */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the version for a Certificate + * Default: MBEDTLS_X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or + * MBEDTLS_X509_CRT_VERSION_3) + */ +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * unlimited) + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(MBEDTLS_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); +#endif /* MBEDTLS_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +/** \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crt.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h new file mode 100644 index 0000000..2a1c046 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h @@ -0,0 +1,306 @@ +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_X509_CSR_H +#define MBEDTLS_X509_CSR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + */ +typedef struct mbedtls_x509_csr +{ + mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ + mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf sig_oid; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ +} +mbedtls_x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct mbedtls_x509write_csr +{ + mbedtls_pk_context *key; + mbedtls_asn1_named_data *subject; + mbedtls_md_type_t md_alg; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_csr; + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \note CSR attributes (if any) are currently silently ignored. + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \note See notes for \c mbedtls_x509_csr_parse_der() + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \note See notes for \c mbedtls_x509_csr_parse() + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ); + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/** \} name Structures and functions for X.509 Certificate Signing Requests (CSR) */ + +#if defined(MBEDTLS_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymmetric key to include + */ +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note The decipherOnly flag from the Key Usage + * extension is represented by bit 8 (i.e. + * 0x8000), which cannot typically be represented + * in an unsigned char. Therefore, the flag + * decipherOnly (i.e. + * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this + * function. + */ +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +/** \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_csr.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h new file mode 100644 index 0000000..4bdc711 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/include/mbedtls/xtea.h @@ -0,0 +1,139 @@ +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_XTEA_H +#define MBEDTLS_XTEA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_XTEA_ENCRYPT 1 +#define MBEDTLS_XTEA_DECRYPT 0 + +/** The data input has an invalid length. */ +#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 + +/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */ +/** XTEA hardware accelerator failed. */ +#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + +/** + * \brief XTEA context structure + */ +typedef struct mbedtls_xtea_context +{ + uint32_t k[4]; /*!< key */ +} +mbedtls_xtea_context; + +#else /* MBEDTLS_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* MBEDTLS_XTEA_ALT */ + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_xtea_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c new file mode 100644 index 0000000..03d8b7e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aes.c @@ -0,0 +1,2189 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_AES_C) + +#include + +#include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) +#define AES_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( (x) << 8 ) & 0xFFFFFFFF ) | ( (x) >> 24 ) +#define XTIME(x) ( ( (x) << 1 ) ^ ( ( (x) & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( (x) && (y) ) ? pow[(log[(x)]+log[(y)]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = MBEDTLS_BYTE_0( x ^ XTIME( x ) ); + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = MBEDTLS_BYTE_0( XTIME( x ) ); + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) ); + x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) ); + x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) ); + x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) ); + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = MBEDTLS_BYTE_0( XTIME( x ) ); + z = MBEDTLS_BYTE_0( y ^ x ); + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + } +} + +#undef ROTL8 + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +#if defined(MBEDTLS_AES_FEWER_TABLES) + +#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) +#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) +#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8( RT0[idx] ) +#define AES_RT2(idx) ROTL16( RT0[idx] ) +#define AES_RT3(idx) ROTL24( RT0[idx] ) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8( FT0[idx] ) +#define AES_FT2(idx) ROTL16( FT0[idx] ) +#define AES_FT3(idx) ROTL24( FT0[idx] ) + +#else /* MBEDTLS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* MBEDTLS_AES_FEWER_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + mbedtls_aes_init( &ctx->crypt ); + mbedtls_aes_init( &ctx->tweak ); +} + +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_aes_free( &ctx->crypt ); + mbedtls_aes_free( &ctx->tweak ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + RK[i] = MBEDTLS_GET_UINT32_LE( key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[3] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[3] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[3] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[3] ) ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[5] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[5] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[5] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[5] ) ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[7] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[7] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[7] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[7] ) ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[11] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[11] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[11] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[11] ) ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = AES_RT0( FSb[ MBEDTLS_BYTE_0( *SK ) ] ) ^ + AES_RT1( FSb[ MBEDTLS_BYTE_1( *SK ) ] ) ^ + AES_RT2( FSb[ MBEDTLS_BYTE_2( *SK ) ] ) ^ + AES_RT3( FSb[ MBEDTLS_BYTE_3( *SK ) ] ); + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free( &cty ); + + return( ret ); +} +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); +} + +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y0 ) ) ^ \ + AES_FT1( MBEDTLS_BYTE_1( Y1 ) ) ^ \ + AES_FT2( MBEDTLS_BYTE_2( Y2 ) ) ^ \ + AES_FT3( MBEDTLS_BYTE_3( Y3 ) ); \ + \ + (X1) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y1 ) ) ^ \ + AES_FT1( MBEDTLS_BYTE_1( Y2 ) ) ^ \ + AES_FT2( MBEDTLS_BYTE_2( Y3 ) ) ^ \ + AES_FT3( MBEDTLS_BYTE_3( Y0 ) ); \ + \ + (X2) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y2 ) ) ^ \ + AES_FT1( MBEDTLS_BYTE_1( Y3 ) ) ^ \ + AES_FT2( MBEDTLS_BYTE_2( Y0 ) ) ^ \ + AES_FT3( MBEDTLS_BYTE_3( Y1 ) ); \ + \ + (X3) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y3 ) ) ^ \ + AES_FT1( MBEDTLS_BYTE_1( Y0 ) ) ^ \ + AES_FT2( MBEDTLS_BYTE_2( Y1 ) ) ^ \ + AES_FT3( MBEDTLS_BYTE_3( Y2 ) ); \ + } while( 0 ) + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y0 ) ) ^ \ + AES_RT1( MBEDTLS_BYTE_1( Y3 ) ) ^ \ + AES_RT2( MBEDTLS_BYTE_2( Y2 ) ) ^ \ + AES_RT3( MBEDTLS_BYTE_3( Y1 ) ); \ + \ + (X1) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y1 ) ) ^ \ + AES_RT1( MBEDTLS_BYTE_1( Y0 ) ) ^ \ + AES_RT2( MBEDTLS_BYTE_2( Y3 ) ) ^ \ + AES_RT3( MBEDTLS_BYTE_3( Y2 ) ); \ + \ + (X2) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y2 ) ) ^ \ + AES_RT1( MBEDTLS_BYTE_1( Y1 ) ) ^ \ + AES_RT2( MBEDTLS_BYTE_2( Y0 ) ) ^ \ + AES_RT3( MBEDTLS_BYTE_3( Y3 ) ); \ + \ + (X3) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y3 ) ) ^ \ + AES_RT1( MBEDTLS_BYTE_1( Y2 ) ) ^ \ + AES_RT2( MBEDTLS_BYTE_2( Y1 ) ) ^ \ + AES_RT3( MBEDTLS_BYTE_3( Y0 ) ); \ + } while( 0 ) + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + t.X[0] = MBEDTLS_GET_UINT32_LE( input, 0 ); t.X[0] ^= *RK++; + t.X[1] = MBEDTLS_GET_UINT32_LE( input, 4 ); t.X[1] ^= *RK++; + t.X[2] = MBEDTLS_GET_UINT32_LE( input, 8 ); t.X[2] ^= *RK++; + t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_FROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[0] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[1] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[2] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[3] ) ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[1] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[2] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[3] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[0] ) ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[2] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[3] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[0] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[1] ) ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[3] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[0] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[1] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[2] ) ] << 24 ); + + MBEDTLS_PUT_UINT32_LE( t.X[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( t.X[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( t.X[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + MBEDTLS_IGNORE_RETURN( mbedtls_internal_aes_encrypt( ctx, input, output ) ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + t.X[0] = MBEDTLS_GET_UINT32_LE( input, 0 ); t.X[0] ^= *RK++; + t.X[1] = MBEDTLS_GET_UINT32_LE( input, 4 ); t.X[1] ^= *RK++; + t.X[2] = MBEDTLS_GET_UINT32_LE( input, 8 ); t.X[2] ^= *RK++; + t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_RROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[0] ) ] ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[3] ) ] << 8 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[2] ) ] << 16 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[1] ) ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[1] ) ] ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[0] ) ] << 8 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[3] ) ] << 16 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[2] ) ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[2] ) ] ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[1] ) ] << 8 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[0] ) ] << 16 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[3] ) ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[3] ) ] ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[2] ) ] << 8 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[1] ) ] << 16 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[0] ) ] << 24 ); + + MBEDTLS_PUT_UINT32_LE( t.X[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( t.X[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( t.X[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_DECRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + MBEDTLS_IGNORE_RETURN( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_ENCRYPT ) + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); + else + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char temp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + ret = mbedtls_aes_crypt_ecb( ctx, mode, input, output ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + ret = mbedtls_aes_crypt_ecb( ctx, mode, output, output ); + if( ret != 0 ) + goto exit; + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianness and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + a = MBEDTLS_GET_UINT64_LE( x, 0 ); + b = MBEDTLS_GET_UINT64_LE( x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + MBEDTLS_PUT_UINT64_LE( ra, r, 0 ); + MBEDTLS_PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( data_unit != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + /* Data units must be at least 16 bytes long. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + mbedtls_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of ciphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + ret = 0; + +exit: + return( ret ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char c; + unsigned char ov[17]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + while( length-- ) + { + memcpy( ov, iv, 16 ); + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + + if( mode == MBEDTLS_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == MBEDTLS_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( nc_off != NULL ); + AES_VALIDATE_RET( nonce_counter != NULL ); + AES_VALIDATE_RET( stream_block != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *nc_off; + + if ( n > 0x0F ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); + if( ret != 0 ) + goto exit; + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 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 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_ofb_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = +{ + 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 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 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, 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 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 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 } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][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 }, + { 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 }, + { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, +}; + +static const unsigned char aes_test_xts_pt32[][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 }, + { 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 }, + { 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 }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = +{ + { 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 }, + { 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 }, + { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) + size_t offset; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) + int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + mbedtls_aes_context ctx; + + memset( key, 0, 32 ); + mbedtls_aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-ECB-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_ecb_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_ecb_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf ); + if( ret != 0 ) + goto exit; + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CBC-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_cbc_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + if( mode == MBEDTLS_AES_ENCRYPT ) + { + unsigned char tmp[16]; + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CFB128-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_tests = aes_test_cfb128_pt; + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_tests = aes_test_cfb128_ct[u]; + } + + ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-OFB-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_ofb_iv, 16 ); + memcpy( key, aes_test_ofb_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ofb_ct[u], 64 ); + aes_tests = aes_test_ofb_pt; + } + else + { + memcpy( buf, aes_test_ofb_pt, 64 ); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CTR-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) + goto exit; + + len = aes_test_ctr_len[u]; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ctr_ct[u], len ); + aes_tests = aes_test_ctr_pt[u]; + } + else + { + memcpy( buf, aes_test_ctr_pt[u], len ); + aes_tests = aes_test_ctr_ct[u]; + } + + ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, + stream_block, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init( &ctx_xts ); + + for( i = 0; i < num_tests << 1; i++ ) + { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-XTS-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( key, 0, sizeof( key ) ); + memcpy( key, aes_test_xts_key[u], 32 ); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof( *aes_test_xts_ct32 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_ct32[u], len ); + aes_tests = aes_test_xts_pt32[u]; + } + else + { + ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_pt32[u], len ); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, + buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + mbedtls_aes_xts_free( &ctx_xts ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + + ret = 0; + +exit: + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "failed\n" ); + + mbedtls_aes_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c new file mode 100644 index 0000000..996292f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aesni.c @@ -0,0 +1,464 @@ +/* + * AES-NI support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set + * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ + */ + +#include "common.h" + +#if defined(MBEDTLS_AESNI_C) + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." +#endif +#endif + +#include "mbedtls/aesni.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +/* + * AES-NI support detection routine + */ +int mbedtls_aesni_has_support( unsigned int what ) +{ + static int done = 0; + static unsigned int c = 0; + + if( ! done ) + { + asm( "movl $1, %%eax \n\t" + "cpuid \n\t" + : "=c" (c) + : + : "eax", "ebx", "edx" ); + done = 1; + } + + return( ( c & what ) != 0 ); +} + +/* + * Binutils needs to be at least 2.19 to support AES-NI instructions. + * Unfortunately, a lot of users have a lower version now (2014-04). + * Emit bytecode directly in order to support "old" version of gas. + * + * Opcodes from the Intel architecture reference manual, vol. 3. + * We always use registers, so we don't need prefixes for memory operands. + * Operand macros are in gas order (src, dst) as opposed to Intel order + * (dst, src) in order to blend better into the surrounding assembly code. + */ +#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," +#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," +#define AESENC ".byte 0x66,0x0F,0x38,0xDC," +#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," +#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," +#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," +#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," + +#define xmm0_xmm0 "0xC0" +#define xmm0_xmm1 "0xC8" +#define xmm0_xmm2 "0xD0" +#define xmm0_xmm3 "0xD8" +#define xmm0_xmm4 "0xE0" +#define xmm1_xmm0 "0xC1" +#define xmm1_xmm2 "0xD1" + +/* + * AES-NI AES-ECB block en(de)cryption + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + asm( "movdqu (%3), %%xmm0 \n\t" // load input + "movdqu (%1), %%xmm1 \n\t" // load round key 0 + "pxor %%xmm1, %%xmm0 \n\t" // round 0 + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // normal rounds = nr - 1 + "test %2, %2 \n\t" // mode? + "jz 2f \n\t" // 0 = decrypt + + "1: \n\t" // encryption loop + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // loop + "jnz 1b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENCLAST xmm1_xmm0 "\n\t" // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" + "subl $1, %0 \n\t" + "jnz 2b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESDECLAST xmm1_xmm0 "\n\t" // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output + : + : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) + : "memory", "cc", "xmm0", "xmm1" ); + + + return( 0 ); +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ) +{ + unsigned char aa[16], bb[16], cc[16]; + size_t i; + + /* The inputs are in big-endian order, so byte-reverse them */ + for( i = 0; i < 16; i++ ) + { + aa[i] = a[15 - i]; + bb[i] = b[15 - i]; + } + + asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 + "movdqu (%1), %%xmm1 \n\t" // b1:b0 + + /* + * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 + * using [CLMUL-WP] algorithm 1 (p. 13). + */ + "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 + "movdqa %%xmm1, %%xmm3 \n\t" // same + "movdqa %%xmm1, %%xmm4 \n\t" // same + PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 + PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 + PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 + PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 + "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 + "movdqa %%xmm4, %%xmm3 \n\t" // same + "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 + "pslldq $8, %%xmm3 \n\t" // e0+f0:0 + "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 + "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 + + /* + * Now shift the result one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 20) + */ + "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 + "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 + "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 + "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 + "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 + "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 + "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 + "pslldq $8, %%xmm3 \n\t" // r0>>63:0 + "pslldq $8, %%xmm4 \n\t" // r2>>63:0 + "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 + "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 + "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 + "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 + + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 20). + * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). + */ + /* Step 2 (1) */ + "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 + "movdqa %%xmm1, %%xmm4 \n\t" // same + "movdqa %%xmm1, %%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a + "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b + "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c + + /* Step 2 (2) */ + "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b + "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c + "pslldq $8, %%xmm3 \n\t" // a+b+c:0 + "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 + + /* Steps 3 and 4 */ + "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' + "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' + "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' + "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' + "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' + // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing + // bits carried from d. Now get those\t bits back in. + "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // d<<63:stuff + "psllq $62, %%xmm4 \n\t" // d<<62:stuff + "psllq $57, %%xmm5 \n\t" // d<<57:stuff + "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff + "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff + "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d + "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 + "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 + "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 + + "movdqu %%xmm0, (%2) \n\t" // done + : + : "r" (aa), "r" (bb), "r" (cc) + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); + + /* Now byte-reverse the outputs */ + for( i = 0; i < 16; i++ ) + c[i] = cc[15 - i]; + + return; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ) +{ + unsigned char *ik = invkey; + const unsigned char *fk = fwdkey + 16 * nr; + + memcpy( ik, fk, 16 ); + + for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) + asm( "movdqu (%0), %%xmm0 \n\t" + AESIMC xmm0_xmm0 "\n\t" + "movdqu %%xmm0, (%1) \n\t" + : + : "r" (fk), "r" (ik) + : "memory", "xmm0" ); + + memcpy( ik, fk, 16 ); +} + +/* + * Key expansion, 128-bit case + */ +static void aesni_setkey_enc_128( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key + "movdqu %%xmm0, (%0) \n\t" // as round key 0 + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next round key. + * + * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 + "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm1 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! + "add $16, %0 \n\t" // point to next round key + "movdqu %%xmm0, (%0) \n\t" // write it + "ret \n\t" + + /* Main "loop" */ + "2: \n\t" + AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_setkey_enc_192( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movq 16(%1), %%xmm1 \n\t" + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next 6 quarter-keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 + * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 + "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 + "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 + "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "ret \n\t" + + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" + + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_setkey_enc_256( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movdqu 16(%1), %%xmm1 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next two round keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and + * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * + * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 + * and those have been written to the output buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + + /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + AESKEYGENA xmm0_xmm2 ",0x00 \n\t" + "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm2, %%xmm1 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "ret \n\t" + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of mbedtls_aes_context.buf + */ + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ) +{ + switch( bits ) + { + case 128: aesni_setkey_enc_128( rk, key ); break; + case 192: aesni_setkey_enc_192( rk, key ); break; + case 256: aesni_setkey_enc_256( rk, key ); break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/arc4.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/arc4.c new file mode 100644 index 0000000..b34dc5e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/arc4.c @@ -0,0 +1,195 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#include "common.h" + +#if defined(MBEDTLS_ARC4_C) + +#include "mbedtls/arc4.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARC4_ALT) + +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); +} + +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); +} + +/* + * ARC4 key schedule + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ) +{ + int i, j, a; + unsigned int k; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ) +{ + int x, y, a, b; + size_t i; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < length; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + output[i] = (unsigned char) + ( input[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; + + return( 0 ); +} + +#endif /* !MBEDTLS_ARC4_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: + * + * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 + */ +static const unsigned char arc4_test_key[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_pt[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_ct[3][8] = +{ + { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, + { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, + { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } +}; + +/* + * Checkup routine + */ +int mbedtls_arc4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char ibuf[8]; + unsigned char obuf[8]; + mbedtls_arc4_context ctx; + + mbedtls_arc4_init( &ctx ); + + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ARC4 test #%d: ", i + 1 ); + + memcpy( ibuf, arc4_test_pt[i], 8 ); + + mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); + mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); + + if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_arc4_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARC4_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c new file mode 100644 index 0000000..bc05c4a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/aria.c @@ -0,0 +1,1058 @@ +/* + * ARIA implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This implementation is based on the following standards: + * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf + * [2] https://tools.ietf.org/html/rfc5794 + */ + +#include "common.h" + +#if defined(MBEDTLS_ARIA_C) + +#include "mbedtls/aria.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARIA_ALT) + +#include "mbedtls/platform_util.h" + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define ARIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) +#define ARIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes + * + * This is submatrix P1 in [1] Appendix B.1 + * + * Common compilers fail to translate this to minimal number of instructions, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev16 available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P1 aria_p1 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 r, x" ); + return( r ); +} +#define ARIA_P1 aria_p1 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +/* I couldn't find an Intel equivalent of rev16, so two instructions */ +#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) ) +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P1) +#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) +#endif + +/* + * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits + * + * This is submatrix P2 in [1] Appendix B.1 + * + * Common compilers will translate this to a single instruction. + */ +#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) + +/* + * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness + * + * This is submatrix P3 in [1] Appendix B.1 + * + * Some compilers fail to translate this to a single instruction, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P3 aria_p3 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev r, x" ); + return( r ); +} +#define ARIA_P3 aria_p3 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +static inline uint32_t aria_p3( uint32_t x ) +{ + __asm( "bswap %0" : "=r" (x) : "0" (x) ); + return( x ); +} +#define ARIA_P3 aria_p3 +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P3) +#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) ) +#endif + +/* + * ARIA Affine Transform + * (a, b, c, d) = state in/out + * + * If we denote the first byte of input by 0, ..., the last byte by f, + * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. + * + * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple + * rearrangements on adjacent pairs, output is: + * + * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe + * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd + * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd + * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc + * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe + * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc + * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef + * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef + * + * Note: another presentation of the A transform can be found as the first + * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. + * The implementation below uses only P1 and P2 as they are sufficient. + */ +static inline void aria_a( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d ) +{ + uint32_t ta, tb, tc; + ta = *b; // 4567 + *b = *a; // 0123 + *a = ARIA_P2( ta ); // 6745 + tb = ARIA_P2( *d ); // efcd + *d = ARIA_P1( *c ); // 98ba + *c = ARIA_P1( tb ); // fedc + ta ^= *d; // 4567+98ba + tc = ARIA_P2( *b ); // 2301 + ta = ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc + tb ^= ARIA_P2( *d ); // ba98+efcd + tc ^= ARIA_P1( *a ); // 2301+7654 + *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT + tb = ARIA_P2( tb ) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc + *a ^= ARIA_P1( tb ); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT + ta = ARIA_P2( ta ); // 0123+7654+ab89+dcfe + *d ^= ARIA_P1( ta ) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT + tc = ARIA_P2( tc ); // 0123+5476 + *c ^= ARIA_P1( tc ) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT +} + +/* + * ARIA Substitution Layer SL1 / SL2 + * (a, b, c, d) = state in/out + * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) + * + * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 + * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 + */ +static inline void aria_sl( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d, + const uint8_t sa[256], const uint8_t sb[256], + const uint8_t sc[256], const uint8_t sd[256] ) +{ + *a = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *a ) ] ) ^ + (((uint32_t) sb[ MBEDTLS_BYTE_1( *a ) ]) << 8) ^ + (((uint32_t) sc[ MBEDTLS_BYTE_2( *a ) ]) << 16) ^ + (((uint32_t) sd[ MBEDTLS_BYTE_3( *a ) ]) << 24); + *b = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *b ) ] ) ^ + (((uint32_t) sb[ MBEDTLS_BYTE_1( *b ) ]) << 8) ^ + (((uint32_t) sc[ MBEDTLS_BYTE_2( *b ) ]) << 16) ^ + (((uint32_t) sd[ MBEDTLS_BYTE_3( *b ) ]) << 24); + *c = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *c ) ] ) ^ + (((uint32_t) sb[ MBEDTLS_BYTE_1( *c ) ]) << 8) ^ + (((uint32_t) sc[ MBEDTLS_BYTE_2( *c ) ]) << 16) ^ + (((uint32_t) sd[ MBEDTLS_BYTE_3( *c ) ]) << 24); + *d = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *d ) ] ) ^ + (((uint32_t) sb[ MBEDTLS_BYTE_1( *d ) ]) << 8) ^ + (((uint32_t) sc[ MBEDTLS_BYTE_2( *d ) ]) << 16) ^ + (((uint32_t) sd[ MBEDTLS_BYTE_3( *d ) ]) << 24); +} + +/* + * S-Boxes + */ +static const uint8_t aria_sb1[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, + 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, + 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, + 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, + 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, + 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, + 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, + 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, + 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, + 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, + 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, + 0xB0, 0x54, 0xBB, 0x16 +}; + +static const uint8_t aria_sb2[256] = +{ + 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, + 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, + 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, + 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, + 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, + 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, + 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, + 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, + 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, + 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, + 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, + 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, + 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, + 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, + 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, + 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, + 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, + 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, + 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, + 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, + 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, + 0xAF, 0xBA, 0xB5, 0x81 +}; + +static const uint8_t aria_is1[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, + 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, + 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, + 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, + 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, + 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, + 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, + 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, + 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, + 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0C, 0x7D +}; + +static const uint8_t aria_is2[256] = +{ + 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, + 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, + 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, + 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, + 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, + 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, + 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, + 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, + 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, + 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, + 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, + 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, + 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, + 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, + 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, + 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, + 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, + 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, + 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, + 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, + 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, + 0x03, 0xA2, 0xAC, 0x60 +}; + +/* + * Helper for key schedule: r = FO( p, k ) ^ x + */ +static void aria_fo_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Helper for key schedule: r = FE( p, k ) ^ x + */ +static void aria_fe_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. + * + * We chose to store bytes into 32-bit words in little-endian format (see + * MBEDTLS_GET_UINT32_LE / MBEDTLS_PUT_UINT32_LE ) so we need to reverse + * bytes here. + */ +static void aria_rot128( uint32_t r[4], const uint32_t a[4], + const uint32_t b[4], uint8_t n ) +{ + uint8_t i, j; + uint32_t t, u; + + const uint8_t n1 = n % 32; // bit offset + const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset + + j = ( n / 32 ) % 4; // initial word offset + t = ARIA_P3( b[j] ); // big endian + for( i = 0; i < 4; i++ ) + { + j = ( j + 1 ) % 4; // get next word, big endian + u = ARIA_P3( b[j] ); + t <<= n1; // rotate + t |= u >> n2; + t = ARIA_P3( t ); // back to little endian + r[i] = a[i] ^ t; // store + t = u; // move to next word + } +} + +/* + * Set encryption key + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + /* round constant masks */ + const uint32_t rc[3][4] = + { + { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, + { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, + { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } + }; + + int i; + uint32_t w[4][4], *w2; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + if( keybits != 128 && keybits != 192 && keybits != 256 ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + /* Copy key to W0 (and potential remainder to W1) */ + w[0][0] = MBEDTLS_GET_UINT32_LE( key, 0 ); + w[0][1] = MBEDTLS_GET_UINT32_LE( key, 4 ); + w[0][2] = MBEDTLS_GET_UINT32_LE( key, 8 ); + w[0][3] = MBEDTLS_GET_UINT32_LE( key, 12 ); + + memset( w[1], 0, 16 ); + if( keybits >= 192 ) + { + w[1][0] = MBEDTLS_GET_UINT32_LE( key, 16 ); // 192 bit key + w[1][1] = MBEDTLS_GET_UINT32_LE( key, 20 ); + } + if( keybits == 256 ) + { + w[1][2] = MBEDTLS_GET_UINT32_LE( key, 24 ); // 256 bit key + w[1][3] = MBEDTLS_GET_UINT32_LE( key, 28 ); + } + + i = ( keybits - 128 ) >> 6; // index: 0, 1, 2 + ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 + + aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR + i = i < 2 ? i + 1 : 0; + aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0 + i = i < 2 ? i + 1 : 0; + aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1 + + for( i = 0; i < 4; i++ ) // create round keys + { + w2 = w[(i + 1) & 3]; + aria_rot128( ctx->rk[i ], w[i], w2, 128 - 19 ); + aria_rot128( ctx->rk[i + 4], w[i], w2, 128 - 31 ); + aria_rot128( ctx->rk[i + 8], w[i], w2, 61 ); + aria_rot128( ctx->rk[i + 12], w[i], w2, 31 ); + } + aria_rot128( ctx->rk[16], w[0], w[1], 19 ); + + /* w holds enough info to reconstruct the round keys */ + mbedtls_platform_zeroize( w, sizeof( w ) ); + + return( 0 ); +} + +/* + * Set decryption key + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + int i, j, k, ret; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aria_setkey_enc( ctx, key, keybits ); + if( ret != 0 ) + return( ret ); + + /* flip the order of round keys */ + for( i = 0, j = ctx->nr; i < j; i++, j-- ) + { + for( k = 0; k < 4; k++ ) + { + uint32_t t = ctx->rk[i][k]; + ctx->rk[i][k] = ctx->rk[j][k]; + ctx->rk[j][k] = t; + } + } + + /* apply affine transform to middle keys */ + for( i = 1; i < ctx->nr; i++ ) + { + aria_a( &ctx->rk[i][0], &ctx->rk[i][1], + &ctx->rk[i][2], &ctx->rk[i][3] ); + } + + return( 0 ); +} + +/* + * Encrypt a block + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ) +{ + int i; + + uint32_t a, b, c, d; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( input != NULL ); + ARIA_VALIDATE_RET( output != NULL ); + + a = MBEDTLS_GET_UINT32_LE( input, 0 ); + b = MBEDTLS_GET_UINT32_LE( input, 4 ); + c = MBEDTLS_GET_UINT32_LE( input, 8 ); + d = MBEDTLS_GET_UINT32_LE( input, 12 ); + + i = 0; + while( 1 ) + { + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + if( i >= ctx->nr ) + break; + aria_a( &a, &b, &c, &d ); + } + + /* final key mixing */ + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + + MBEDTLS_PUT_UINT32_LE( a, output, 0 ); + MBEDTLS_PUT_UINT32_LE( b, output, 4 ); + MBEDTLS_PUT_UINT32_LE( c, output, 8 ); + MBEDTLS_PUT_UINT32_LE( d, output, 12 ); + + return( 0 ); +} + +/* Initialize context */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ) +{ + ARIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_aria_context ) ); +} + +/* Clear context */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * ARIA-CBC buffer encryption/decryption + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + + if( length % MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE ); + mbedtls_aria_crypt_ecb( ctx, input, output ); + + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aria_crypt_ecb( ctx, output, output ); + memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * ARIA-CFB128 buffer encryption/decryption + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + ARIA_VALIDATE_RET( iv_off != NULL ); + + n = *iv_off; + + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + c = *input++; + *output++ = c ^ iv[n]; + iv[n] = c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * ARIA-CTR buffer encryption/decryption + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( nonce_counter != NULL ); + ARIA_VALIDATE_RET( stream_block != NULL ); + ARIA_VALIDATE_RET( nc_off != NULL ); + + n = *nc_off; + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aria_crypt_ecb( ctx, nonce_counter, + stream_block ); + + for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_ARIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Basic ARIA ECB test vectors from RFC 5794 + */ +static const uint8_t aria_test1_ecb_key[32] = // test key +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit +}; + +static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes +}; + +static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext +{ + { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit + 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, + { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit + 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, + { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit + 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } +}; + +/* + * Mode tests from "Test Vectors for ARIA" Version 1.0 + * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf + */ +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) +static const uint8_t aria_test2_key[32] = +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit +}; + +static const uint8_t aria_test2_pt[48] = +{ + 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all + 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, + 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, + 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, + 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, + 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, +}; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) +static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = +{ + 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB + 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV +}; +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext +{ + { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key + 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, + 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, + 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, + 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, + 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, + { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key + 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, + 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, + 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, + 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, + 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, + { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key + 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, + 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, + 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, + 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, + 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext +{ + { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key + 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, + 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, + 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, + 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, + 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, + { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key + 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, + 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, + 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, + 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, + 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, + { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key + 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, + 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, + 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, + 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, + 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext +{ + { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key + 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, + 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, + 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, + 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, + 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, + { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key + 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, + 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, + 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, + 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, + 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, + { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key + 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, + 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, + 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, + 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, + 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#define ARIA_SELF_TEST_IF_FAIL \ + { \ + if( verbose ) \ + mbedtls_printf( "failed\n" ); \ + goto exit; \ + } else { \ + if( verbose ) \ + mbedtls_printf( "passed\n" ); \ + } + +/* + * Checkup routine + */ +int mbedtls_aria_self_test( int verbose ) +{ + int i; + uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; + mbedtls_aria_context ctx; + int ret = 1; + +#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) + size_t j; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ + defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) + uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; +#endif + + mbedtls_aria_init( &ctx ); + + /* + * Test set 1 + */ + for( i = 0; i < 3; i++ ) + { + /* test ECB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk ); + if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* test ECB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk ); + if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + + /* + * Test set 2 + */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + for( i = 0; i < 3; i++ ) + { + /* Test CBC encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CBC decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, + aria_test2_cbc_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + for( i = 0; i < 3; i++ ) + { + /* Test CFB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CFB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, + iv, aria_test2_cfb_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + for( i = 0; i < 3; i++ ) + { + /* Test CTR encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CTR decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_ctr_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + mbedtls_aria_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARIA_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c new file mode 100644 index 0000000..22747d3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/asn1parse.c @@ -0,0 +1,481 @@ +/* + * Generic ASN.1 parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#include "mbedtls/asn1.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 16 ) | + ( (size_t)(*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | + ( (size_t)(*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +static int asn1_get_tagged_int( unsigned char **p, + const unsigned char *end, + int tag, int *val ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 ) + return( ret ); + + /* + * len==0 is malformed (0 must be represented as 020100 for INTEGER, + * or 0A0100 for ENUMERATED tags + */ + if( len == 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + /* This is a cryptography library. Reject negative integers. */ + if( ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Skip leading zeros. */ + while( len > 0 && **p == 0 ) + { + ++( *p ); + --len; + } + + /* Reject integers that don't fit in an int. This code assumes that + * the int type has no padding bit. */ + if( len > sizeof( int ) ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + if( len == sizeof( int ) && ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) ); +} + +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ) +{ + return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Traverse an ASN.1 "SEQUENCE OF " + * and call a callback for each entry found. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char *start, size_t len ), + void *ctx ) +{ + int ret; + size_t len; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( ret ); + } + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + unsigned char const tag = *(*p)++; + + if( ( tag & tag_must_mask ) != tag_must_val ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 ) + return( ret ); + + if( ( tag & tag_may_mask ) == tag_may_val ) + { + if( cb != NULL ) + { + ret = cb( ctx, tag, *p, len ); + if( ret != 0 ) + return( ret ); + } + } + + *p += len; + } + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( *len == 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + --( *len ); + + if( **p != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + ++( *p ); + + return( 0 ); +} + +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ) +{ + while( seq != NULL ) + { + mbedtls_asn1_sequence *next = seq->next; + mbedtls_platform_zeroize( seq, sizeof( *seq ) ); + mbedtls_free( seq ); + seq = next; + } +} + +typedef struct +{ + int tag; + mbedtls_asn1_sequence *cur; +} asn1_get_sequence_of_cb_ctx_t; + +static int asn1_get_sequence_of_cb( void *ctx, + int tag, + unsigned char *start, + size_t len ) +{ + asn1_get_sequence_of_cb_ctx_t *cb_ctx = + (asn1_get_sequence_of_cb_ctx_t *) ctx; + mbedtls_asn1_sequence *cur = + cb_ctx->cur; + + if( cur->buf.p != NULL ) + { + cur->next = + mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + cur->buf.p = start; + cur->buf.len = len; + cur->buf.tag = tag; + + cb_ctx->cur = cur; + return( 0 ); +} + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur }; + memset( cur, 0, sizeof( mbedtls_asn1_sequence ) ); + return( mbedtls_asn1_traverse_sequence_of( + p, end, 0xFF, tag, 0, 0, + asn1_get_sequence_of_cb, &cb_ctx ) ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c new file mode 100644 index 0000000..afa26a6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/asn1write.c @@ -0,0 +1,485 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_ASN1_WRITE_C) + +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( len <= 0xFFFF ) + { + if( *p - start < 3 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = MBEDTLS_BYTE_0( len ); + *--(*p) = MBEDTLS_BYTE_1( len ); + *--(*p) = 0x82; + return( 3 ); + } + + if( len <= 0xFFFFFF ) + { + if( *p - start < 4 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = MBEDTLS_BYTE_0( len ); + *--(*p) = MBEDTLS_BYTE_1( len ); + *--(*p) = MBEDTLS_BYTE_2( len ); + *--(*p) = 0x83; + return( 4 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + if( len <= 0xFFFFFFFF ) +#endif + { + if( *p - start < 5 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = MBEDTLS_BYTE_0( len ); + *--(*p) = MBEDTLS_BYTE_1( len ); + *--(*p) = MBEDTLS_BYTE_2( len ); + *--(*p) = MBEDTLS_BYTE_3( len ); + *--(*p) = 0x84; + return( 5 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif +} + +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + // Write the MPI + // + len = mbedtls_mpi_size( X ); + + /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not + * as 0 digits. We need to end up with 020100, not with 0200. */ + if( len == 0 ) + len = 1; + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); + + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( X->s ==1 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + // Write NULL + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( par_len == 0 ) + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); + else + len += par_len; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 255 : 0; + len++; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + do + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + len += 1; + *--(*p) = val & 0xff; + val >>= 8; + } + while( val > 0 ); + + if( **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) +{ + return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) ); +} + +int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val ) +{ + return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) ); +} + +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, + const char *text, size_t text_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_named_bitstring( unsigned char **p, + unsigned char *start, + const unsigned char *buf, + size_t bits ) +{ + size_t unused_bits, byte_len; + const unsigned char *cur_byte; + unsigned char cur_byte_shifted; + unsigned char bit; + + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; + + /* + * Named bitstrings require that trailing 0s are excluded in the encoding + * of the bitstring. Trailing 0s are considered part of the 'unused' bits + * when encoding this value in the first content octet + */ + if( bits != 0 ) + { + cur_byte = buf + byte_len - 1; + cur_byte_shifted = *cur_byte >> unused_bits; + + for( ; ; ) + { + bit = cur_byte_shifted & 0x1; + cur_byte_shifted >>= 1; + + if( bit != 0 ) + break; + + bits--; + if( bits == 0 ) + break; + + if( bits % 8 == 0 ) + cur_byte_shifted = *--cur_byte; + } + } + + return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) ); +} + +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + size_t unused_bits, byte_len; + + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; + + if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = byte_len + 1; + + /* Write the bitstring. Ensure the unused bits are zeroed */ + if( byte_len > 0 ) + { + byte_len--; + *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); + ( *p ) -= byte_len; + memcpy( *p, buf, byte_len ); + } + + /* Write unused bits */ + *--( *p ) = (unsigned char)unused_bits; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + + +/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), + * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ +static mbedtls_asn1_named_data *asn1_find_named_data( + mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( + mbedtls_asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, + sizeof(mbedtls_asn1_named_data) ); + if( cur == NULL ) + return( NULL ); + + cur->oid.len = oid_len; + cur->oid.p = mbedtls_calloc( 1, oid_len ); + if( cur->oid.p == NULL ) + { + mbedtls_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->val.len = val_len; + if( val_len != 0 ) + { + cur->val.p = mbedtls_calloc( 1, val_len ); + if( cur->val.p == NULL ) + { + mbedtls_free( cur->oid.p ); + mbedtls_free( cur ); + return( NULL ); + } + } + + cur->next = *head; + *head = cur; + } + else if( val_len == 0 ) + { + mbedtls_free( cur->val.p ); + cur->val.p = NULL; + } + else if( cur->val.len != val_len ) + { + /* + * Enlarge existing value buffer if needed + * Preserve old data until the allocation succeeded, to leave list in + * a consistent state in case allocation fails. + */ + void *p = mbedtls_calloc( 1, val_len ); + if( p == NULL ) + return( NULL ); + + mbedtls_free( cur->val.p ); + cur->val.p = p; + cur->val.len = val_len; + } + + if( val != NULL && val_len != 0 ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* MBEDTLS_ASN1_WRITE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/base64.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/base64.c new file mode 100644 index 0000000..83daa0b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/base64.c @@ -0,0 +1,277 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_BASE64_C) + +#include "mbedtls/base64.h" +#include "constant_time_internal.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) + & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) + & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( C3 & 0x3F ); + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) + & 0x3F ); + + if( ( i + 1 ) < slen ) + *p++ = mbedtls_ct_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F ); + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i; /* index in source */ + size_t n; /* number of digits or trailing = in source */ + uint32_t x; /* value accumulator */ + unsigned accumulated_digits = 0; + unsigned equals = 0; + int spaces_present = 0; + unsigned char *p; + + /* First pass: check for validity and get output length */ + for( i = n = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + spaces_present = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + spaces_present = 1; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( spaces_present ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' ) + { + if( ++equals > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + } + else + { + if( equals != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + if( mbedtls_ct_base64_dec_value( src[i] ) < 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + } + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); + n -= equals; + + if( dst == NULL || dlen < n ) + { + *olen = n; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + equals = 0; + for( x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' || *src == ' ' ) + continue; + + x = x << 6; + if( *src == '=' ) + ++equals; + else + x |= mbedtls_ct_base64_dec_value( *src ); + + if( ++accumulated_digits == 4 ) + { + accumulated_digits = 0; + *p++ = MBEDTLS_BYTE_2( x ); + if( equals <= 1 ) *p++ = MBEDTLS_BYTE_1( x ); + if( equals <= 0 ) *p++ = MBEDTLS_BYTE_0( x ); + } + } + + *olen = p - dst; + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int mbedtls_base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + mbedtls_printf( " Base64 encoding test: " ); + + src = base64_test_dec; + + if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n Base64 decoding test: " ); + + src = base64_test_enc; + + if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BASE64_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c new file mode 100644 index 0000000..598a78c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/bignum.c @@ -0,0 +1,3174 @@ +/* + * Multi-precision integer library + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "constant_time_internal.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +void *mbedtls_mpi_mempool; + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) +{ + mbedtls_platform_zeroize( v, ciL * n ); +} + +/* + * Initialize one MPI + */ +static void mpi_init( mbedtls_mpi *X, short use_mempool ) +{ + MPI_VALIDATE( X != NULL ); + + X->s = 1; + X->use_mempool = use_mempool; + X->n = 0; + X->p = NULL; +} + +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + mpi_init( X, 0 /*use_mempool*/ ); +} + +void mbedtls_mpi_init_mempool( mbedtls_mpi *X ) +{ + mpi_init( X, !!mbedtls_mpi_mempool /*use_mempool*/ ); +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + if( X->use_mempool ) + mempool_free( mbedtls_mpi_mempool, X->p ); + else + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( X->use_mempool ) + { + p = mempool_alloc( mbedtls_mpi_mempool, nblimbs * ciL ); + if( p == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + memset( p, 0, nblimbs * ciL ); + } + else + { + p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ); + if( p == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + if( X->use_mempool ) + mempool_free( mbedtls_mpi_mempool, X->p); + else + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + /* Actually resize up if there are currently fewer than nblimbs limbs. */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( X->use_mempool ) + { + p = mempool_alloc( mbedtls_mpi_mempool, i * ciL ); + if( p == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + memset( p, 0, i * ciL ); + } + else + { + p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ); + if( p == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + if( X->use_mempool ) + mempool_free( mbedtls_mpi_mempool, X->p ); + else + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* Resize X to have exactly n limbs and set it to 0. */ +static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs ) +{ + if( limbs == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + else if( X->n == limbs ) + { + memset( X->p, 0, limbs * ciL ); + X->s = 1; + return( 0 ); + } + else + { + mbedtls_mpi_free( X ); + return( mbedtls_mpi_grow( X, limbs ) ); + } +} + +/* + * Copy the contents of Y into X. + * + * This function is not constant-time. Leading zeros in Y may be removed. + * + * Ensure that X does not shrink. This is not guaranteed by the public API, + * but some code in the bignum module relies on this property, for example + * in mbedtls_mpi_exp_mod(). + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + if( Y->n == 0 ) + { + if( X->n != 0 ) + { + X->s = 1; + memset( X->p, 0, X->n * ciL ); + } + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } + + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + MPI_VALIDATE( X != NULL ); + MPI_VALIDATE( Y != NULL ); + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( X != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + MPI_VALIDATE_RET( X != NULL ); + + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + MPI_VALIDATE_RET( X != NULL ); + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j, slen, n; + int sign = 1; + mbedtls_mpi_uint d; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( s != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init_mempool( &T ); + + if( s[0] == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + if( s[0] == '-' ) + { + ++s; + sign = -1; + } + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + } + + if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 ) + X->s = -1; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first. + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, + char **p, const size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint r; + size_t length = 0; + char *p_end = *p + buflen; + + do + { + if( length >= buflen ) + { + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + /* + * Write the residue in the current position, as an ASCII character. + */ + if( r < 0xA ) + *(--p_end) = (char)( '0' + r ); + else + *(--p_end) = (char)( 'A' + ( r - 0xA ) ); + + length++; + } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); + + memmove( *p, p_end, length ); + *p += length; + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( olen != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ + if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present + * `n`. If radix > 4, this might be a strict + * overapproximation of the number of + * radix-adic digits needed to present `n`. */ + if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to + * present `n`. */ + + n += 1; /* Terminating null byte */ + n += 1; /* Compensate for the divisions above, which round down `n` + * in case it's not even. */ + n += 1; /* Potential '-'-sign. */ + n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, + * which always uses an even number of hex-digits. */ + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init_mempool( &T ); + + if( X->s == -1 ) + { + *p++ = '-'; + buflen--; + } + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( fin != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + + +/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. */ + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) +{ + uint8_t i; + unsigned char *x_ptr; + mbedtls_mpi_uint tmp = 0; + + for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ ) + { + tmp <<= CHAR_BIT; + tmp |= (mbedtls_mpi_uint) *x_ptr; + } + + return( tmp ); +} + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) +{ +#if defined(__BYTE_ORDER__) + +/* Nothing to do on bigendian systems. */ +#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + return( x ); +#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ + +#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + +/* For GCC and Clang, have builtins for byte swapping. */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4,3) +#define have_bswap +#endif +#endif + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap32) && \ + __has_builtin(__builtin_bswap64) +#define have_bswap +#endif +#endif + +#if defined(have_bswap) + /* The compiler is hopefully able to statically evaluate this! */ + switch( sizeof(mbedtls_mpi_uint) ) + { + case 4: + return( __builtin_bswap32(x) ); + case 8: + return( __builtin_bswap64(x) ); + } +#endif +#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ +#endif /* __BYTE_ORDER__ */ + + /* Fall back to C-based reordering if we don't know the byte order + * or we couldn't use a compiler-specific builtin. */ + return( mpi_uint_bigendian_to_host_c( x ) ); +} + +static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) +{ + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if( limbs == 0 ) + return; + + /* + * Traverse limbs and + * - adapt byte-order in each limb + * - swap the limbs themselves. + * For that, simultaneously traverse the limbs from left to right + * and from right to left, as long as the left index is not bigger + * than the right index (it's not a problem if limbs is odd and the + * indices coincide in the last iteration). + */ + for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); + cur_limb_left <= cur_limb_right; + cur_limb_left++, cur_limb_right-- ) + { + mbedtls_mpi_uint tmp; + /* Note that if cur_limb_left == cur_limb_right, + * this code effectively swaps the bytes only once. */ + tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); + *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); + *cur_limb_right = tmp; + } +} + +/* + * Import X from unsigned binary data, little endian + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + + for( i = 0; i < buflen; i++ ) + X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3); + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + size_t const overhead = ( limbs * ciL ) - buflen; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + + /* Avoid calling `memcpy` with NULL source or destination argument, + * even if buflen is 0. */ + if( buflen != 0 ) + { + Xp = (unsigned char*) X->p; + memcpy( Xp + overhead, buf, buflen ); + + mpi_bigendian_to_host( X->p, limbs ); + } + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Export X into unsigned binary data, little endian + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes = X->n * ciL; + size_t bytes_to_copy; + size_t i; + + if( stored_bytes < buflen ) + { + bytes_to_copy = stored_bytes; + } + else + { + bytes_to_copy = buflen; + + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + buf[i] = GET_BYTE( X, i ); + + if( stored_bytes < buflen ) + { + /* Write trailing 0 bytes */ + memset( buf + stored_bytes, 0, buflen - stored_bytes ); + } + + return( 0 ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + size_t i; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + stored_bytes = X->n * ciL; + + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/** + * Helper for mbedtls_mpi subtraction. + * + * Calculate l - r where l and r have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise). + * + * d may be aliased to l or r. + * + * \param n Number of limbs of \p d, \p l and \p r. + * \param[out] d The result of the subtraction. + * \param[in] l The left operand. + * \param[in] r The right operand. + * + * \return 1 if `l < r`. + * 0 if `l >= r`. + */ +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, + mbedtls_mpi_uint *d, + const mbedtls_mpi_uint *l, + const mbedtls_mpi_uint *r ) +{ + size_t i; + mbedtls_mpi_uint c = 0, t, z; + + for( i = 0; i < n; i++ ) + { + z = ( l[i] < c ); t = l[i] - c; + c = ( t < r[i] ) + z; d[i] = t - r[i]; + } + + return( c ); +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + mbedtls_mpi_uint carry; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + if( n > A->n ) + { + /* B >= (2^ciL)^n > A */ + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) ); + + /* Set the high limbs of X to match A. Don't touch the lower limbs + * because X might be aliased to B, and we must not overwrite the + * significant digits of B. */ + if( A->n > n ) + memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL ); + if( X->n > A->n ) + memset( X->p + A->n, 0, ( X->n - A->n ) * ciL ); + + carry = mpi_sub_hlp( n, X->p, A->p, B->p ); + if( carry != 0 ) + { + /* Propagate the carry to the first nonzero limb of X. */ + for( ; n < X->n && X->p[n] == 0; n++ ) + --X->p[n]; + /* If we ran out of space for the carry, it means that the result + * is negative. */ + if( n == X->n ) + { + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + --X->p[n]; + } + + /* X should always be positive as a result of unsigned subtractions. */ + X->s = 1; + +cleanup: + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &B ) ); +} + +/** Helper for mbedtls_mpi multiplication. + * + * Add \p b * \p s to \p d. + * + * \param i The number of limbs of \p s. + * \param[in] s A bignum to multiply, of size \p i. + * It may overlap with \p d, but only if + * \p d <= \p s. + * Its leading limb must not be \c 0. + * \param[in,out] d The bignum to add to. + * It must be sufficiently large to store the + * result of the multiplication. This means + * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b + * is not known a priori. + * \param b A scalar to multiply. + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, + const mbedtls_mpi_uint *s, + mbedtls_mpi_uint *d, + mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + while( c != 0 ) + { + *d += c; c = ( *d < c ); d++; + } +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi TA, TB; + int result_is_zero = 0; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + if( i == 0 ) + result_is_zero = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + if( j == 0 ) + result_is_zero = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); + + /* If the result is 0, we don't shortcut the operation, which reduces + * but does not eliminate side channels leaking the zero-ness. We do + * need to take care to set the sign bit properly since the library does + * not fully support an MPI object with a value of 0 and s == -1. */ + if( result_is_zero ) + X->s = 1; + else + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + /* mpi_mul_hlp can't deal with a leading 0. */ + size_t n = A->n; + while( n > 0 && A->p[n - 1] == 0 ) + --n; + + /* The general method below doesn't work if n==0 or b==0. By chance + * calculating the result is trivial in those cases. */ + if( b == 0 || n == 0 ) + { + return( mbedtls_mpi_lset( X, 0 ) ); + } + + /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* In general, A * b requires 1 limb more than b. If + * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same + * number of limbs as A and the call to grow() is not required since + * copy() will take care of the growth if needed. However, experimentally, + * making the call to grow() unconditional causes slightly fewer + * calls to calloc() in ECP code, presumably because it reuses the + * same mpi for a while and this way the mpi is more likely to directly + * grow to its final size. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + mpi_mul_hlp( n, A->p, X->p, b - 1 ); + +cleanup: + return( ret ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + mbedtls_mpi_uint TP2[3]; + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init_mempool( &X ); mbedtls_mpi_init_mempool( &Y ); + mbedtls_mpi_init_mempool( &Z ); mbedtls_mpi_init_mempool( &T1 ); + /* + * Avoid dynamic memory allocations for constant-size T2. + * + * T2 is used for comparison only and the 3 limbs are assigned explicitly, + * so nobody increase the size of the MPI and we're safe to use an on-stack + * buffer. + */ + T2.s = 1; + T2.n = sizeof( TP2 ) / sizeof( *TP2 ); + T2.p = TP2; + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); + mbedtls_platform_zeroize( TP2, sizeof( TP2 ) ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, + const mbedtls_mpi *A, + mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( R != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + MPI_VALIDATE_RET( r != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 || A->n == 0 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mpi_montg_init( mm, N ); +} + +/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by `mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. + */ +static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + /* At this point, d is either the desired result or the desired result + * plus N. We now potentially subtract N, avoiding leaking whether the + * subtraction is performed through side channels. */ + + /* Copy the n least significant limbs of d to A, so that + * A = d if d < N (recall that N has n limbs). */ + memcpy( A->p, d, n * ciL ); + /* If d >= N then we want to set A to d - N. To prevent timing attacks, + * do the calculation without using conditional tests. */ + /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ + d[n] += 1; + d[n] -= mpi_sub_hlp( n, d, d, N->p ); + /* If d0 < N then d < (2^biL)^n + * so d[n] == 0 and we want to keep A as it is. + * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n + * so d[n] == 1 and we want to set A to the result of the subtraction + * which is d - (2^biL)^n, i.e. the n least significant limbs of d. + * This exactly corresponds to a conditional assignment. */ + mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] ); +} + +void mbedtls_mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + mpi_montmul( A, B, N, mm, T); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters. + */ +static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +void mbedtls_mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mpi_montred( A, N, mm, T ); +} + +/** + * Select an MPI from a table without leaking the index. + * + * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it + * reads the entire table in order to avoid leaking the value of idx to an + * attacker able to observe memory access patterns. + * + * \param[out] R Where to write the selected MPI. + * \param[in] T The table to read from. + * \param[in] T_size The number of elements in the table. + * \param[in] idx The index of the element to select; + * this must satisfy 0 <= idx < T_size. + * + * \return \c 0 on success, or a negative error code. + */ +static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for( size_t i = 0; i < T_size; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i], + (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) ); + } + +cleanup: + return( ret ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *prec_RR ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, WW, Apos; + mbedtls_mpi *W = NULL; + const size_t array_size_W = 2 << MBEDTLS_MPI_WINDOW_SIZE; + int neg; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS || + mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS ) + return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init_mempool( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init_mempool( &Apos ); + mbedtls_mpi_init_mempool( &WW ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + +#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; +#endif + + j = N->n + 1; + /* All W[i] and X must have at least N->n limbs for the mpi_montmul() + * and mpi_montred() calls later. Here we ensure that W[1] and X are + * large enough, and later we'll grow other W[i] to the same length. + * They must not be shrunk midway through this function! + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( prec_RR == NULL || prec_RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( prec_RR != NULL ) + memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) ); + + W = mempool_alloc( mbedtls_mpi_mempool, + sizeof( mbedtls_mpi ) * array_size_W ); + if( W == NULL ) { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + for( i = 0; i < array_size_W; i++ ) + mbedtls_mpi_init_mempool( W + i ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + /* This should be a no-op because W[1] is already that large before + * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow + * in mpi_montmul() below, so let's make sure. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + /* Note that this is safe because W[1] always has at least N->n limbs + * (it grew above and was preserved by mbedtls_mpi_copy()). */ + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) ); + mpi_montmul( X, &WW, N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + if( W ) + for( i = 0; i < array_size_W; i++ ) + mbedtls_mpi_free( W + i ); + mempool_free( mbedtls_mpi_mempool , W ); + + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + mbedtls_mpi_free( &WW ); + + if( prec_RR == NULL || prec_RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t lz, lzt; + mbedtls_mpi TA, TB; + + MPI_VALIDATE_RET( G != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + /* The loop below gives the correct result when A==0 but not when B==0. + * So have a special case for B==0. Leverage the fact that we just + * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test + * slightly more efficient than cmp_int(). */ + if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 ) + { + ret = mbedtls_mpi_copy( G, A ); + goto cleanup; + } + + if( lzt < lz ) + lz = lzt; + + TA.s = TB.s = 1; + + /* We mostly follow the procedure described in HAC 14.54, but with some + * minor differences: + * - Sequences of multiplications or divisions by 2 are grouped into a + * single shift operation. + * - The procedure in HAC assumes that 0 < TB <= TA. + * - The condition TB <= TA is not actually necessary for correctness. + * TA and TB have symmetric roles except for the loop termination + * condition, and the shifts at the beginning of the loop body + * remove any significance from the ordering of TA vs TB before + * the shifts. + * - If TA = 0, the loop goes through 0 iterations and the result is + * correctly TB. + * - The case TB = 0 was short-circuited above. + * + * For the correctness proof below, decompose the original values of + * A and B as + * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1 + * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1 + * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'), + * and gcd(A',B') is odd or 0. + * + * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB). + * The code maintains the following invariant: + * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I) + */ + + /* Proof that the loop terminates: + * At each iteration, either the right-shift by 1 is made on a nonzero + * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases + * by at least 1, or the right-shift by 1 is made on zero and then + * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted + * since in that case TB is calculated from TB-TA with the condition TB>TA). + */ + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + /* Divisions by 2 preserve the invariant (I). */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd, + * TA-TB is even so the division by 2 has an integer result. + * Invariant (I) is preserved since any odd divisor of both TA and TB + * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2 + * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also + * divides TA. + */ + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + /* Note that one of TA or TB is still odd. */ + } + + /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k. + * At the loop exit, TA = 0, so gcd(TA,TB) = TB. + * - If there was at least one loop iteration, then one of TA or TB is odd, + * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case, + * lz = min(a,b) so gcd(A,B) = 2^lz * TB. + * - If there was no loop iteration, then A was 0, and gcd(A,B) = B. + * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* Fill X with n_bytes random bytes. + * X must already have room for those bytes. + * The ordering of the bytes returned from the RNG is suitable for + * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()). + * The size and sign of X are unchanged. + * n_bytes must not be 0. + */ +static int mpi_fill_random_internal( + mbedtls_mpi *X, size_t n_bytes, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t limbs = CHARS_TO_LIMBS( n_bytes ); + const size_t overhead = ( limbs * ciL ) - n_bytes; + + if( X->n < limbs ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( X->p, 0, overhead ); + memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL ); + MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) ); + mpi_bigendian_to_host( X->p, limbs ); + +cleanup: + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( size ); + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + if( size == 0 ) + return( 0 ); + + ret = mpi_fill_random_internal( X, size, f_rng, p_rng ); + +cleanup: + return( ret ); +} + +int mbedtls_mpi_random( mbedtls_mpi *X, + mbedtls_mpi_sint min, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + int count; + unsigned lt_lower = 1, lt_upper = 0; + size_t n_bits = mbedtls_mpi_bitlen( N ); + size_t n_bytes = ( n_bits + 7 ) / 8; + mbedtls_mpi lower_bound; + + if( min < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + if( mbedtls_mpi_cmp_int( N, min ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * When min == 0, each try has at worst a probability 1/2 of failing + * (the msb has a probability 1/2 of being 0, and then the result will + * be < N), so after 30 tries failure probability is a most 2**(-30). + * + * When N is just below a power of 2, as is the case when generating + * a random scalar on most elliptic curves, 1 try is enough with + * overwhelming probability. When N is just above a power of 2, + * as when generating a random scalar on secp224k1, each try has + * a probability of failing that is almost 1/2. + * + * The probabilities are almost the same if min is nonzero but negligible + * compared to N. This is always the case when N is crypto-sized, but + * it's convenient to support small N for testing purposes. When N + * is small, use a higher repeat count, otherwise the probability of + * failure is macroscopic. + */ + count = ( n_bytes > 4 ? 30 : 250 ); + + mbedtls_mpi_init( &lower_bound ); + + /* Ensure that target MPI has exactly the same number of limbs + * as the upper bound, even if the upper bound has leading zeros. + * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) ); + + /* + * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA) + * when f_rng is a suitably parametrized instance of HMAC_DRBG: + * - use the same byte ordering; + * - keep the leftmost n_bits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any bias, which is especially important for ECDSA. + */ + do + { + MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) ); + + if( --count == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, <_lower ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, <_upper ) ); + } + while( lt_lower != 0 || lt_upper == 0 ); + +cleanup: + mbedtls_mpi_free( &lower_bound ); + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init_mempool( &TA ); mbedtls_mpi_init_mempool( &TU ); + mbedtls_mpi_init_mempool( &U1 ); mbedtls_mpi_init_mempool( &U2 ); + mbedtls_mpi_init_mempool( &G ); mbedtls_mpi_init_mempool( &TB ); + mbedtls_mpi_init_mempool( &TV ); mbedtls_mpi_init_mempool( &V1 ); + mbedtls_mpi_init_mempool( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, s; + mbedtls_mpi W, R, T, A, RR; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + mbedtls_mpi_init_mempool( &W ); mbedtls_mpi_init_mempool( &R ); + mbedtls_mpi_init_mempool( &T ); mbedtls_mpi_init_mempool( &A ); + mbedtls_mpi_init_mempool( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + for( i = 0; i < rounds; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; + } + + if (count++ > 300) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi XX; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Pseudo-primality test, error probability 2^-80 + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* + * In the past our key generation aimed for an error rate of at most + * 2^-80. Since this function is deprecated, aim for the same certainty + * here as well. + */ + return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) ); +} +#endif + +/* + * Prime number generation + * + * To generate an RSA key in a way recommended by FIPS 186-4, both primes must + * be either 1024 bits or 1536 bits long, and flags must contain + * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + size_t k, n; + int rounds; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init_mempool( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) + { + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); + } + else + { + /* + * 2^-100 error probability, number of rounds computed based on HAC, + * fact 4.48 + */ + rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : + ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : + ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : + ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); + } + + while( 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; + + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) + { + ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) + == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init_mempool( &A ); mbedtls_mpi_init_mempool( &E ); + mbedtls_mpi_init_mempool( &N ); mbedtls_mpi_init_mempool( &X ); + mbedtls_mpi_init_mempool( &Y ); mbedtls_mpi_init_mempool( &U ); + mbedtls_mpi_init_mempool( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/blowfish.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/blowfish.c new file mode 100644 index 0000000..621e9f7 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/blowfish.c @@ -0,0 +1,667 @@ +/* + * Blowfish implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The Blowfish block cipher was designed by Bruce Schneier in 1993. + * http://www.schneier.com/blowfish.html + * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_BLOWFISH_C) + +#include "mbedtls/blowfish.h" +#include "mbedtls/platform_util.h" + +#include + +#if !defined(MBEDTLS_BLOWFISH_ALT) + +/* Parameter validation macros */ +#define BLOWFISH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ) +#define BLOWFISH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +/* declarations of data at the end of this file */ +static const uint32_t S[4][256]; + +static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) +{ + unsigned short a, b, c, d; + uint32_t y; + + d = MBEDTLS_BYTE_0( x ); + x >>= 8; + c = MBEDTLS_BYTE_0( x ); + x >>= 8; + b = MBEDTLS_BYTE_0( x ); + x >>= 8; + a = MBEDTLS_BYTE_0( x ); + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return( y ); +} + +static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; + Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; + + *xl = Xl; + *xr = Xr; +} + +static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) +{ + BLOWFISH_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); +} + +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); +} + +/* + * Blowfish key schedule + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i, j, k; + uint32_t data, datal, datar; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( key != NULL ); + + if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || + keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || + keybits % 8 != 0 ) + { + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + } + + keybits >>= 3; + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j++ ) + ctx->S[i][j] = S[i][j]; + } + + j = 0; + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) + { + data = 0x00000000; + for( k = 0; k < 4; ++k ) + { + data = ( data << 8 ) | key[j++]; + if( j >= keybits ) + j = 0; + } + ctx->P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } + return( 0 ); +} + +/* + * Blowfish-ECB block encryption/decryption + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) +{ + uint32_t X0, X1; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( input != NULL ); + BLOWFISH_VALIDATE_RET( output != NULL ); + + X0 = MBEDTLS_GET_UINT32_BE( input, 0 ); + X1 = MBEDTLS_GET_UINT32_BE( input, 4 ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + blowfish_dec( ctx, &X0, &X1 ); + } + else /* MBEDTLS_BLOWFISH_ENCRYPT */ + { + blowfish_enc( ctx, &X0, &X1 ); + } + + MBEDTLS_PUT_UINT32_BE( X0, output, 0 ); + MBEDTLS_PUT_UINT32_BE( X1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Blowfish-CBC buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) + return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); + mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Blowfish CFB buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT || + mode == MBEDTLS_BLOWFISH_DECRYPT ); + BLOWFISH_VALIDATE_RET( iv != NULL ); + BLOWFISH_VALIDATE_RET( iv_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Blowfish CTR buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + BLOWFISH_VALIDATE_RET( ctx != NULL ); + BLOWFISH_VALIDATE_RET( nonce_counter != NULL ); + BLOWFISH_VALIDATE_RET( stream_block != NULL ); + BLOWFISH_VALIDATE_RET( nc_off != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || input != NULL ); + BLOWFISH_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 8 ) + return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, + stream_block ); + + for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static const uint32_t S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + +#endif /* !MBEDTLS_BLOWFISH_ALT */ +#endif /* MBEDTLS_BLOWFISH_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c new file mode 100644 index 0000000..29d730a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/camellia.c @@ -0,0 +1,1087 @@ +/* + * Camellia implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The Camellia block cipher was designed by NTT and Mitsubishi Electric + * Corporation. + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_CAMELLIA_C) + +#include "mbedtls/camellia.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) + +/* Parameter validation macros */ +#define CAMELLIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ) +#define CAMELLIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +static const unsigned char SIGMA_CHARS[6][8] = +{ + { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, + { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, + { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, + { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, + { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, + { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } +}; + +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + +static const unsigned char FSb[256] = +{ + 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, + 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, + 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, + 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, + 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, + 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, + 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, + 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, + 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, + 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, + 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) +#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) +#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] + +#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char FSb[256] = +{ + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 +}; + +static const unsigned char FSb2[256] = +{ + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 +}; + +static const unsigned char FSb3[256] = +{ + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 +}; + +static const unsigned char FSb4[256] = +{ + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) FSb2[(n)] +#define SBOX3(n) FSb3[(n)] +#define SBOX4(n) FSb4[(n)] + +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char shifts[2][4][4] = +{ + { + { 1, 1, 1, 1 }, /* KL */ + { 0, 0, 0, 0 }, /* KR */ + { 1, 1, 1, 1 }, /* KA */ + { 0, 0, 0, 0 } /* KB */ + }, + { + { 1, 0, 1, 1 }, /* KL */ + { 1, 1, 0, 1 }, /* KR */ + { 1, 1, 1, 0 }, /* KA */ + { 1, 1, 0, 1 } /* KB */ + } +}; + +static const signed char indexes[2][4][20] = +{ + { + { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, + 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ + { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, + 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ + }, + { + { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, + -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ + { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ + { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ + { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, + 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ + } +}; + +static const signed char transposes[2][20] = +{ + { + 21, 22, 23, 20, + -1, -1, -1, -1, + 18, 19, 16, 17, + 11, 8, 9, 10, + 15, 12, 13, 14 + }, + { + 25, 26, 27, 24, + 29, 30, 31, 28, + 18, 19, 16, 17, + -1, -1, -1, -1, + -1, -1, -1, -1 + } +}; + +/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ +#define ROTL(DEST, SRC, SHIFT) \ +{ \ + (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ + (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ + (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ + (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ +} + +#define FL(XL, XR, KL, KR) \ +{ \ + (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ + (XL) = ((XR) | (KR)) ^ (XL); \ +} + +#define FLInv(YL, YR, KL, KR) \ +{ \ + (YL) = ((YR) | (KR)) ^ (YL); \ + (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ +} + +#define SHIFT_AND_PLACE(INDEX, OFFSET) \ +{ \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ + \ + for( i = 1; i <= 4; i++ ) \ + if( shifts[(INDEX)][(OFFSET)][i -1] ) \ + ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ + \ + for( i = 0; i < 20; i++ ) \ + if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ + RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ + } \ +} + +static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], + uint32_t z[2]) +{ + uint32_t I0, I1; + I0 = x[0] ^ k[0]; + I1 = x[1] ^ k[1]; + + I0 = ((uint32_t) SBOX1( MBEDTLS_BYTE_3( I0 )) << 24) | + ((uint32_t) SBOX2( MBEDTLS_BYTE_2( I0 )) << 16) | + ((uint32_t) SBOX3( MBEDTLS_BYTE_1( I0 )) << 8) | + ((uint32_t) SBOX4( MBEDTLS_BYTE_0( I0 )) ); + I1 = ((uint32_t) SBOX2( MBEDTLS_BYTE_3( I1 )) << 24) | + ((uint32_t) SBOX3( MBEDTLS_BYTE_2( I1 )) << 16) | + ((uint32_t) SBOX4( MBEDTLS_BYTE_1( I1 )) << 8) | + ((uint32_t) SBOX1( MBEDTLS_BYTE_0( I1 )) ); + + I0 ^= (I1 << 8) | (I1 >> 24); + I1 ^= (I0 << 16) | (I0 >> 16); + I0 ^= (I1 >> 8) | (I1 << 24); + I1 ^= (I0 >> 8) | (I0 << 24); + + z[0] ^= I1; + z[1] ^= I0; +} + +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) +{ + CAMELLIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); +} + +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + int idx; + size_t i; + uint32_t *RK; + unsigned char t[64]; + uint32_t SIGMA[6][2]; + uint32_t KC[16]; + uint32_t TK[20]; + + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + + RK = ctx->rk; + + memset( t, 0, 64 ); + memset( RK, 0, sizeof(ctx->rk) ); + + switch( keybits ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + } + + for( i = 0; i < keybits / 8; ++i ) + t[i] = key[i]; + + if( keybits == 192 ) { + for( i = 0; i < 8; i++ ) + t[24 + i] = ~t[16 + i]; + } + + /* + * Prepare SIGMA values + */ + for( i = 0; i < 6; i++ ) { + SIGMA[i][0] = MBEDTLS_GET_UINT32_BE( SIGMA_CHARS[i], 0 ); + SIGMA[i][1] = MBEDTLS_GET_UINT32_BE( SIGMA_CHARS[i], 4 ); + } + + /* + * Key storage in KC + * Order: KL, KR, KA, KB + */ + memset( KC, 0, sizeof(KC) ); + + /* Store KL, KR */ + for( i = 0; i < 8; i++ ) + KC[i] = MBEDTLS_GET_UINT32_BE( t, i * 4 ); + + /* Generate KA */ + for( i = 0; i < 4; ++i ) + KC[8 + i] = KC[i] ^ KC[4 + i]; + + camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); + + for( i = 0; i < 4; ++i ) + KC[8 + i] ^= KC[i]; + + camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); + + if( keybits > 128 ) { + /* Generate KB */ + for( i = 0; i < 4; ++i ) + KC[12 + i] = KC[4 + i] ^ KC[8 + i]; + + camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); + camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); + } + + /* + * Generating subkeys + */ + + /* Manipulating KL */ + SHIFT_AND_PLACE( idx, 0 ); + + /* Manipulating KR */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 3 ); + } + + /* Do transpositions */ + for( i = 0; i < 20; i++ ) { + if( transposes[idx][i] != -1 ) { + RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; + } + } + + return( 0 ); +} + +/* + * Camellia key schedule (decryption) + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + int idx, ret; + size_t i; + mbedtls_camellia_context cty; + uint32_t *RK; + uint32_t *SK; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + + mbedtls_camellia_init( &cty ); + + /* Also checks keybits */ + if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + idx = ( ctx->nr == 4 ); + + RK = ctx->rk; + SK = cty.rk + 24 * 2 + 8 * idx * 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) + { + *RK++ = *SK++; + *RK++ = *SK++; + } + + SK -= 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int NR; + uint32_t *RK, X[4]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( input != NULL ); + CAMELLIA_VALIDATE_RET( output != NULL ); + + ( (void) mode ); + + NR = ctx->nr; + RK = ctx->rk; + + X[0] = MBEDTLS_GET_UINT32_BE( input, 0 ); + X[1] = MBEDTLS_GET_UINT32_BE( input, 4 ); + X[2] = MBEDTLS_GET_UINT32_BE( input, 8 ); + X[3] = MBEDTLS_GET_UINT32_BE( input, 12 ); + + X[0] ^= *RK++; + X[1] ^= *RK++; + X[2] ^= *RK++; + X[3] ^= *RK++; + + while( NR ) { + --NR; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + + if( NR ) { + FL(X[0], X[1], RK[0], RK[1]); + RK += 2; + FLInv(X[2], X[3], RK[0], RK[1]); + RK += 2; + } + } + + X[2] ^= *RK++; + X[3] ^= *RK++; + X[0] ^= *RK++; + X[1] ^= *RK++; + + MBEDTLS_PUT_UINT32_BE( X[2], output, 0 ); + MBEDTLS_PUT_UINT32_BE( X[3], output, 4 ); + MBEDTLS_PUT_UINT32_BE( X[0], output, 8 ); + MBEDTLS_PUT_UINT32_BE( X[1], output, 12 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + if( length % 16 ) + return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( iv_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( nonce_counter != NULL ); + CAMELLIA_VALIDATE_RET( stream_block != NULL ); + CAMELLIA_VALIDATE_RET( nc_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, + stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_CAMELLIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Camellia test vectors from: + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt + * (For each bitlength: Key 0, Nr 39) + */ +#define CAMELLIA_TESTS_ECB 2 + +static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = +{ + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 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 } + }, +}; + +static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = +{ + { + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, + { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, + 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } + }, + { + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, + { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, + 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } + }, + { + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, + { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, + 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } + } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define CAMELLIA_TESTS_CBC 3 + +static const unsigned char camellia_test_cbc_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + , + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } + , + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char camellia_test_cbc_iv[16] = + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } +; + +static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = +{ + { 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 } + +}; + +static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = +{ + { + { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, + 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, + { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, + 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, + { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, + 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } + }, + { + { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, + 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, + { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, + 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, + { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, + 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } + }, + { + { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, + 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, + { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, + 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, + { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, + 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc5528.html + */ + +static const unsigned char camellia_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char camellia_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char camellia_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 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, 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 } +}; + +static const unsigned char camellia_test_ctr_ct[3][48] = +{ + { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, + 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, + { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, + 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, + 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, + 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, + { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, + 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, + 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, + 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, + 0xDF, 0x50, 0x86, 0x96 } +}; + +static const int camellia_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_camellia_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char src[16]; + unsigned char dst[16]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + int ret = 1; + + mbedtls_camellia_context ctx; + + mbedtls_camellia_init( &ctx ); + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); + + for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { + memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); + memcpy( dst, camellia_test_ecb_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_plain[i], 16 ); + memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + mbedtls_camellia_setkey_enc( &ctx, key, 128 ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + mbedtls_camellia_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CAMELLIA_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c new file mode 100644 index 0000000..a21a37f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ccm.c @@ -0,0 +1,546 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + +#include "common.h" + +#if defined(MBEDTLS_CCM_C) + +#include "mbedtls/ccm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_CCM_ALT) + +#define CCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT ) +#define CCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +/* + * Initialize context + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) +{ + CCM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); +} + +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( key != NULL ); + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) +{ + if( ctx == NULL ) + return; + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); +} + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * Update the CBC-MAC state in y using a block in b + * (Always using b as the source helps the compiler optimise a bit better.) + */ +#define UPDATE_CBC_MAC \ + for( i = 0; i < 16; i++ ) \ + y[i] ^= b[i]; \ + \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ + return( ret ); + +/* + * Encrypt or decrypt a partial block with CTR + * Warning: using b for temporary storage! src and dst must not be b! + * This avoids allocating one more 16 bytes buffer while allowing src == dst. + */ +#define CTR_CRYPT( dst, src, len ) \ + do \ + { \ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, \ + 16, b, &olen ) ) != 0 ) \ + { \ + return( ret ); \ + } \ + \ + for( i = 0; i < (len); i++ ) \ + (dst)[i] = (src)[i] ^ b[i]; \ + } while( 0 ) + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + unsigned char q; + size_t len_left, olen; + unsigned char b[16]; + unsigned char y[16]; + unsigned char ctr[16]; + const unsigned char *src; + unsigned char *dst; + + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + * + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). + */ + if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + /* Also implies q is within bounds */ + if( iv_len < 7 || iv_len > 13 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( add_len >= 0xFF00 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + q = 16 - 1 - (unsigned char) iv_len; + + /* + * First block B_0: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + b[0] = 0; + b[0] |= ( add_len > 0 ) << 6; + b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; + b[0] |= q - 1; + + memcpy( b + 1, iv, iv_len ); + + for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) + b[15-i] = MBEDTLS_BYTE_0( len_left ); + + if( len_left > 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + + /* Start CBC-MAC with first block */ + memset( y, 0, 16 ); + UPDATE_CBC_MAC; + + /* + * If there is additional data, update CBC-MAC with + * add_len, add, 0 (padding to a block boundary) + */ + if( add_len > 0 ) + { + size_t use_len; + len_left = add_len; + src = add; + + memset( b, 0, 16 ); + MBEDTLS_PUT_UINT16_BE( add_len, b, 0 ); + + use_len = len_left < 16 - 2 ? len_left : 16 - 2; + memcpy( b + 2, src, use_len ); + len_left -= use_len; + src += use_len; + + UPDATE_CBC_MAC; + + while( len_left > 0 ) + { + use_len = len_left > 16 ? 16 : len_left; + + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + + len_left -= use_len; + src += use_len; + } + } + + /* + * Prepare counter block for encryption: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 counter (initially 1) + * + * With flags as (bits): + * 7 .. 3 0 + * 2 .. 0 q - 1 + */ + ctr[0] = q - 1; + memcpy( ctr + 1, iv, iv_len ); + memset( ctr + 1 + iv_len, 0, q ); + ctr[15] = 1; + + /* + * Authenticate and {en,de}crypt the message. + * + * The only difference between encryption and decryption is + * the respective order of authentication and {en,de}cryption. + */ + len_left = length; + src = input; + dst = output; + + while( len_left > 0 ) + { + size_t use_len = len_left > 16 ? 16 : len_left; + + if( mode == CCM_ENCRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, src, use_len ); + UPDATE_CBC_MAC; + } + + CTR_CRYPT( dst, src, use_len ); + + if( mode == CCM_DECRYPT ) + { + memset( b, 0, 16 ); + memcpy( b, dst, use_len ); + UPDATE_CBC_MAC; + } + + dst += use_len; + src += use_len; + len_left -= use_len; + + /* + * Increment counter. + * No need to check for overflow thanks to the length check above. + */ + for( i = 0; i < q; i++ ) + if( ++ctr[15-i] != 0 ) + break; + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for( i = 0; i < q; i++ ) + ctr[15-i] = 0; + + CTR_CRYPT( y, y, 16 ); + memcpy( tag, y, tag_len ); + + return( 0 ); +} + +/* + * Authenticated encryption + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CCM_AUTH_FAILED ); + } + + return( 0 ); +} + +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + CCM_VALIDATE_RET( ctx != NULL ); + CCM_VALIDATE_RET( iv != NULL ); + CCM_VALIDATE_RET( add_len == 0 || add != NULL ); + CCM_VALIDATE_RET( length == 0 || input != NULL ); + CCM_VALIDATE_RET( length == 0 || output != NULL ); + CCM_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + if( tag_len == 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len ) ); +} +#endif /* !MBEDTLS_CCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * Examples 1 to 3 from SP800-38C Appendix C + */ + +#define NB_TESTS 3 +#define CCM_SELFTEST_PT_MAX_LEN 24 +#define CCM_SELFTEST_CT_MAX_LEN 32 +/* + * The data is the same for all tests, only the used length changes + */ +static const unsigned char key_test_data[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; + +static const unsigned char iv_test_data[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b +}; + +static const unsigned char ad_test_data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +}; + +static const size_t iv_len_test_data [NB_TESTS] = { 7, 8, 12 }; +static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 }; +static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 }; +static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 }; + +static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { + { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, + { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, + 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, + 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, + { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, + 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, + 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, + 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } +}; + +int mbedtls_ccm_self_test( int verbose ) +{ + mbedtls_ccm_context ctx; + /* + * Some hardware accelerators require the input and output buffers + * would be in RAM, because the flash is not accessible. + * Use buffers on the stack to hold the test vectors data. + */ + unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; + unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; + size_t i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_ccm_init( &ctx ); + + if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key_test_data, + 8 * sizeof key_test_data ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM: setup failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN ); + memcpy( plaintext, msg_test_data, msg_len_test_data[i] ); + + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len_test_data[i], + iv_test_data, iv_len_test_data[i], + ad_test_data, add_len_test_data[i], + plaintext, ciphertext, + ciphertext + msg_len_test_data[i], + tag_len_test_data[i] ); + + if( ret != 0 || + memcmp( ciphertext, res_test_data[i], + msg_len_test_data[i] + tag_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + + ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len_test_data[i], + iv_test_data, iv_len_test_data[i], + ad_test_data, add_len_test_data[i], + ciphertext, plaintext, + ciphertext + msg_len_test_data[i], + tag_len_test_data[i] ); + + if( ret != 0 || + memcmp( plaintext, msg_test_data, msg_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + mbedtls_ccm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_CCM_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/certs.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/certs.c new file mode 100644 index 0000000..a5695e3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/certs.c @@ -0,0 +1,1746 @@ +/* + * X.509 test certificates + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#include "mbedtls/certs.h" + +#if defined(MBEDTLS_CERTS_C) + +/* + * Test CA Certificates + * + * We define test CA certificates for each choice of the following parameters: + * - PEM or DER encoding + * - SHA-1 or SHA-256 hash + * - RSA or EC key + * + * Things to add: + * - multiple EC curve types + * + */ + +/* This is taken from tests/data_files/test-ca2.crt */ +/* BEGIN FILE string macro TEST_CA_CRT_EC_PEM tests/data_files/test-ca2.crt */ +#define TEST_CA_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIICBDCCAYigAwIBAgIJAMFD4n5iQ8zoMAwGCCqGSM49BAMCBQAwPjELMAkGA1UE\r\n" \ + "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ + "IEVDIENBMB4XDTE5MDIxMDE0NDQwMFoXDTI5MDIxMDE0NDQwMFowPjELMAkGA1UE\r\n" \ + "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n" \ + "IEVDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEw9orNEE3WC+HVv78ibopQ0tO\r\n" \ + "4G7DDldTMzlY1FK0kZU5CyPfXxckYkj8GpUpziwth8KIUoCv1mqrId240xxuWLjK\r\n" \ + "6LJpjvNBrSnDtF91p0dv1RkpVWmaUzsgtGYWYDMeo1AwTjAMBgNVHRMEBTADAQH/\r\n" \ + "MB0GA1UdDgQWBBSdbSAkSQE/K8t4tRm8fiTJ2/s2fDAfBgNVHSMEGDAWgBSdbSAk\r\n" \ + "SQE/K8t4tRm8fiTJ2/s2fDAMBggqhkjOPQQDAgUAA2gAMGUCMFHKrjAPpHB0BN1a\r\n" \ + "LH8TwcJ3vh0AxeKZj30mRdOKBmg/jLS3rU3g8VQBHpn8sOTTBwIxANxPO5AerimZ\r\n" \ + "hCjMe0d4CTHf1gFZMF70+IqEP+o5VHsIp2Cqvflb0VGWFC5l9a4cQg==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/test-ca2.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_CRT_EC_DER tests/data_files/test-ca2.crt.der */ +#define TEST_CA_CRT_EC_DER { \ + 0x30, 0x82, 0x02, 0x04, 0x30, 0x82, 0x01, 0x88, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, \ + 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, \ + 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ + 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ + 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ + 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ + 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, \ + 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, \ + 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, \ + 0x30, 0x5a, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \ + 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \ + 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \ + 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \ + 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, \ + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, \ + 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37, \ + 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e, \ + 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4, \ + 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc, \ + 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf, \ + 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca, \ + 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75, \ + 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20, \ + 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x0c, \ + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, \ + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, \ + 0x6d, 0x20, 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, \ + 0x7e, 0x24, 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x1f, 0x06, 0x03, 0x55, \ + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, \ + 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, \ + 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, \ + 0x30, 0x51, 0xca, 0xae, 0x30, 0x0f, 0xa4, 0x70, 0x74, 0x04, 0xdd, 0x5a, \ + 0x2c, 0x7f, 0x13, 0xc1, 0xc2, 0x77, 0xbe, 0x1d, 0x00, 0xc5, 0xe2, 0x99, \ + 0x8f, 0x7d, 0x26, 0x45, 0xd3, 0x8a, 0x06, 0x68, 0x3f, 0x8c, 0xb4, 0xb7, \ + 0xad, 0x4d, 0xe0, 0xf1, 0x54, 0x01, 0x1e, 0x99, 0xfc, 0xb0, 0xe4, 0xd3, \ + 0x07, 0x02, 0x31, 0x00, 0xdc, 0x4f, 0x3b, 0x90, 0x1e, 0xae, 0x29, 0x99, \ + 0x84, 0x28, 0xcc, 0x7b, 0x47, 0x78, 0x09, 0x31, 0xdf, 0xd6, 0x01, 0x59, \ + 0x30, 0x5e, 0xf4, 0xf8, 0x8a, 0x84, 0x3f, 0xea, 0x39, 0x54, 0x7b, 0x08, \ + 0xa7, 0x60, 0xaa, 0xbd, 0xf9, 0x5b, 0xd1, 0x51, 0x96, 0x14, 0x2e, 0x65, \ + 0xf5, 0xae, 0x1c, 0x42 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca2.key.enc */ +/* BEGIN FILE string macro TEST_CA_KEY_EC_PEM tests/data_files/test-ca2.key.enc */ +#define TEST_CA_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "Proc-Type: 4,ENCRYPTED\r\n" \ + "DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" \ + "\r\n" \ + "IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" \ + "ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" \ + "UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" \ + "a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +#define TEST_CA_PWD_EC_PEM "PolarSSLTest" + +/* This is generated from tests/data_files/test-ca2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_KEY_EC_DER tests/data_files/test-ca2.key.der */ +#define TEST_CA_KEY_EC_DER { \ + 0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x83, 0xd9, 0x15, 0x0e, \ + 0xa0, 0x71, 0xf0, 0x57, 0x10, 0x33, 0xa3, 0x38, 0xb8, 0x86, 0xc1, 0xa6, \ + 0x11, 0x5d, 0x6d, 0xb4, 0x03, 0xe1, 0x29, 0x76, 0x45, 0xd7, 0x87, 0x6f, \ + 0x23, 0xab, 0x44, 0x20, 0xea, 0x64, 0x7b, 0x85, 0xb1, 0x76, 0xe7, 0x85, \ + 0x95, 0xaa, 0x74, 0xd6, 0xd1, 0xa4, 0x5e, 0xea, 0xa0, 0x07, 0x06, 0x05, \ + 0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xc3, \ + 0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, \ + 0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, \ + 0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, \ + 0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, \ + 0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, \ + 0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, \ + 0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, \ + 0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha256.crt. */ +/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA256_PEM tests/data_files/test-ca-sha256.crt */ +#define TEST_CA_CRT_RSA_SHA256_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ + "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ + "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ + "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ + "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ + "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ + "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ + "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ + "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBCwUA\r\n" \ + "A4IBAQA4qFSCth2q22uJIdE4KGHJsJjVEfw2/xn+MkTvCMfxVrvmRvqCtjE4tKDl\r\n" \ + "oK4MxFOek07oDZwvtAT9ijn1hHftTNS7RH9zd/fxNpfcHnMZXVC4w4DNA1fSANtW\r\n" \ + "5sY1JB5Je9jScrsLSS+mAjyv0Ow3Hb2Bix8wu7xNNrV5fIf7Ubm+wt6SqEBxu3Kb\r\n" \ + "+EfObAT4huf3czznhH3C17ed6NSbXwoXfby7stWUDeRJv08RaFOykf/Aae7bY5PL\r\n" \ + "yTVrkAnikMntJ9YI+hNNYt3inqq11A5cN0+rVTst8UKCxzQ4GpvroSwPKTFkbMw4\r\n" \ + "/anT1dVxr/BtwJfiESoK3/4CeXR1\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/test-ca-sha256.crt.der + * using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA256_DER tests/data_files/test-ca-sha256.crt.der */ +#define TEST_CA_CRT_RSA_SHA256_DER { \ + 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ + 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ + 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ + 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ + 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ + 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ + 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ + 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ + 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ + 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ + 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ + 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ + 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ + 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ + 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ + 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ + 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ + 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ + 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ + 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ + 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ + 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ + 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ + 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ + 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ + 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ + 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x01, 0x00, 0x38, 0xa8, 0x54, 0x82, 0xb6, 0x1d, 0xaa, \ + 0xdb, 0x6b, 0x89, 0x21, 0xd1, 0x38, 0x28, 0x61, 0xc9, 0xb0, 0x98, 0xd5, \ + 0x11, 0xfc, 0x36, 0xff, 0x19, 0xfe, 0x32, 0x44, 0xef, 0x08, 0xc7, 0xf1, \ + 0x56, 0xbb, 0xe6, 0x46, 0xfa, 0x82, 0xb6, 0x31, 0x38, 0xb4, 0xa0, 0xe5, \ + 0xa0, 0xae, 0x0c, 0xc4, 0x53, 0x9e, 0x93, 0x4e, 0xe8, 0x0d, 0x9c, 0x2f, \ + 0xb4, 0x04, 0xfd, 0x8a, 0x39, 0xf5, 0x84, 0x77, 0xed, 0x4c, 0xd4, 0xbb, \ + 0x44, 0x7f, 0x73, 0x77, 0xf7, 0xf1, 0x36, 0x97, 0xdc, 0x1e, 0x73, 0x19, \ + 0x5d, 0x50, 0xb8, 0xc3, 0x80, 0xcd, 0x03, 0x57, 0xd2, 0x00, 0xdb, 0x56, \ + 0xe6, 0xc6, 0x35, 0x24, 0x1e, 0x49, 0x7b, 0xd8, 0xd2, 0x72, 0xbb, 0x0b, \ + 0x49, 0x2f, 0xa6, 0x02, 0x3c, 0xaf, 0xd0, 0xec, 0x37, 0x1d, 0xbd, 0x81, \ + 0x8b, 0x1f, 0x30, 0xbb, 0xbc, 0x4d, 0x36, 0xb5, 0x79, 0x7c, 0x87, 0xfb, \ + 0x51, 0xb9, 0xbe, 0xc2, 0xde, 0x92, 0xa8, 0x40, 0x71, 0xbb, 0x72, 0x9b, \ + 0xf8, 0x47, 0xce, 0x6c, 0x04, 0xf8, 0x86, 0xe7, 0xf7, 0x73, 0x3c, 0xe7, \ + 0x84, 0x7d, 0xc2, 0xd7, 0xb7, 0x9d, 0xe8, 0xd4, 0x9b, 0x5f, 0x0a, 0x17, \ + 0x7d, 0xbc, 0xbb, 0xb2, 0xd5, 0x94, 0x0d, 0xe4, 0x49, 0xbf, 0x4f, 0x11, \ + 0x68, 0x53, 0xb2, 0x91, 0xff, 0xc0, 0x69, 0xee, 0xdb, 0x63, 0x93, 0xcb, \ + 0xc9, 0x35, 0x6b, 0x90, 0x09, 0xe2, 0x90, 0xc9, 0xed, 0x27, 0xd6, 0x08, \ + 0xfa, 0x13, 0x4d, 0x62, 0xdd, 0xe2, 0x9e, 0xaa, 0xb5, 0xd4, 0x0e, 0x5c, \ + 0x37, 0x4f, 0xab, 0x55, 0x3b, 0x2d, 0xf1, 0x42, 0x82, 0xc7, 0x34, 0x38, \ + 0x1a, 0x9b, 0xeb, 0xa1, 0x2c, 0x0f, 0x29, 0x31, 0x64, 0x6c, 0xcc, 0x38, \ + 0xfd, 0xa9, 0xd3, 0xd5, 0xd5, 0x71, 0xaf, 0xf0, 0x6d, 0xc0, 0x97, 0xe2, \ + 0x11, 0x2a, 0x0a, 0xdf, 0xfe, 0x02, 0x79, 0x74, 0x75 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha1.crt. */ +/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA1_PEM tests/data_files/test-ca-sha1.crt */ +#define TEST_CA_CRT_RSA_SHA1_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ + "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ + "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ + "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ + "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ + "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ + "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ + "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n" \ + "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA\r\n" \ + "A4IBAQABE3OEPfEd/bcJW5ZdU3/VgPNS4tMzh8gnJP/V2FcvFtGylMpQq6YnEBYI\r\n" \ + "yBHAL4DRvlMY5rnXGBp3ODR8MpqHC6AquRTCLzjS57iYff//4QFQqW9n92zctspv\r\n" \ + "czkaPKgjqo1No3Uq0Xaz10rcxyTUPrf5wNVRZ2V0KvllvAAVSzbI4mpdUXztjhST\r\n" \ + "S5A2BeWQAAOr0zq1F7TSRVJpJs7jmB2ai/igkh1IAjcuwV6VwlP+sbw0gjQ0NpGM\r\n" \ + "iHpnlzRAi/tIbtOvMIGOBU2TIfax/5jq1agUx5aPmT5TWAiJPOOP6l5xXnDwxeYS\r\n" \ + "NWqiX9GyusBZjezaCaHabjDLU0qQ\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/test-ca-sha1.crt.der. */ +/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA1_DER tests/data_files/test-ca-sha1.crt.der */ +#define TEST_CA_CRT_RSA_SHA1_DER { \ + 0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \ + 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \ + 0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \ + 0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \ + 0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \ + 0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \ + 0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \ + 0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \ + 0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \ + 0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \ + 0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \ + 0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \ + 0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \ + 0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \ + 0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \ + 0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \ + 0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \ + 0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \ + 0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \ + 0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \ + 0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \ + 0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \ + 0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \ + 0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \ + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \ + 0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \ + 0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \ + 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \ + 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \ + 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \ + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, \ + 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x13, 0x73, 0x84, 0x3d, 0xf1, 0x1d, \ + 0xfd, 0xb7, 0x09, 0x5b, 0x96, 0x5d, 0x53, 0x7f, 0xd5, 0x80, 0xf3, 0x52, \ + 0xe2, 0xd3, 0x33, 0x87, 0xc8, 0x27, 0x24, 0xff, 0xd5, 0xd8, 0x57, 0x2f, \ + 0x16, 0xd1, 0xb2, 0x94, 0xca, 0x50, 0xab, 0xa6, 0x27, 0x10, 0x16, 0x08, \ + 0xc8, 0x11, 0xc0, 0x2f, 0x80, 0xd1, 0xbe, 0x53, 0x18, 0xe6, 0xb9, 0xd7, \ + 0x18, 0x1a, 0x77, 0x38, 0x34, 0x7c, 0x32, 0x9a, 0x87, 0x0b, 0xa0, 0x2a, \ + 0xb9, 0x14, 0xc2, 0x2f, 0x38, 0xd2, 0xe7, 0xb8, 0x98, 0x7d, 0xff, 0xff, \ + 0xe1, 0x01, 0x50, 0xa9, 0x6f, 0x67, 0xf7, 0x6c, 0xdc, 0xb6, 0xca, 0x6f, \ + 0x73, 0x39, 0x1a, 0x3c, 0xa8, 0x23, 0xaa, 0x8d, 0x4d, 0xa3, 0x75, 0x2a, \ + 0xd1, 0x76, 0xb3, 0xd7, 0x4a, 0xdc, 0xc7, 0x24, 0xd4, 0x3e, 0xb7, 0xf9, \ + 0xc0, 0xd5, 0x51, 0x67, 0x65, 0x74, 0x2a, 0xf9, 0x65, 0xbc, 0x00, 0x15, \ + 0x4b, 0x36, 0xc8, 0xe2, 0x6a, 0x5d, 0x51, 0x7c, 0xed, 0x8e, 0x14, 0x93, \ + 0x4b, 0x90, 0x36, 0x05, 0xe5, 0x90, 0x00, 0x03, 0xab, 0xd3, 0x3a, 0xb5, \ + 0x17, 0xb4, 0xd2, 0x45, 0x52, 0x69, 0x26, 0xce, 0xe3, 0x98, 0x1d, 0x9a, \ + 0x8b, 0xf8, 0xa0, 0x92, 0x1d, 0x48, 0x02, 0x37, 0x2e, 0xc1, 0x5e, 0x95, \ + 0xc2, 0x53, 0xfe, 0xb1, 0xbc, 0x34, 0x82, 0x34, 0x34, 0x36, 0x91, 0x8c, \ + 0x88, 0x7a, 0x67, 0x97, 0x34, 0x40, 0x8b, 0xfb, 0x48, 0x6e, 0xd3, 0xaf, \ + 0x30, 0x81, 0x8e, 0x05, 0x4d, 0x93, 0x21, 0xf6, 0xb1, 0xff, 0x98, 0xea, \ + 0xd5, 0xa8, 0x14, 0xc7, 0x96, 0x8f, 0x99, 0x3e, 0x53, 0x58, 0x08, 0x89, \ + 0x3c, 0xe3, 0x8f, 0xea, 0x5e, 0x71, 0x5e, 0x70, 0xf0, 0xc5, 0xe6, 0x12, \ + 0x35, 0x6a, 0xa2, 0x5f, 0xd1, 0xb2, 0xba, 0xc0, 0x59, 0x8d, 0xec, 0xda, \ + 0x09, 0xa1, 0xda, 0x6e, 0x30, 0xcb, 0x53, 0x4a, 0x90 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/test-ca.key */ +/* BEGIN FILE string macro TEST_CA_KEY_RSA_PEM tests/data_files/test-ca.key */ +#define TEST_CA_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "Proc-Type: 4,ENCRYPTED\r\n" \ + "DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" \ + "\r\n" \ + "9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" \ + "7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" \ + "Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" \ + "PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" \ + "GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" \ + "gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" \ + "QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" \ + "PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" \ + "vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" \ + "WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" \ + "JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" \ + "KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" \ + "Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" \ + "9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" \ + "iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" \ + "tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" \ + "P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" \ + "1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" \ + "nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" \ + "X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" \ + "rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" \ + "L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" \ + "I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" \ + "wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" \ + "P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n" +/* END FILE */ + +#define TEST_CA_PWD_RSA_PEM "PolarSSLTest" + +/* This was generated from test-ca.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CA_KEY_RSA_DER tests/data_files/test-ca.key.der */ +#define TEST_CA_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, 0x86, 0xde, \ + 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, 0x99, 0xd4, \ + 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, 0x9b, 0xc5, \ + 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, 0xc0, 0x8d, \ + 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, 0x93, 0xe8, \ + 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, 0xe7, 0x40, \ + 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, 0xf9, 0x3e, \ + 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, 0x29, 0x00, \ + 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, 0xbd, 0x83, \ + 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, 0x60, 0xc3, \ + 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, 0x32, 0xbe, \ + 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, 0xfb, 0xf5, \ + 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, 0xee, 0xe2, \ + 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, 0x47, 0xb1, \ + 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, 0xf1, 0x79, \ + 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, 0x6f, 0x27, \ + 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, 0xa1, 0x30, \ + 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, 0x28, 0xd1, \ + 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, 0x09, 0xea, \ + 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, 0xc9, 0xab, \ + 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, 0x9e, 0x99, \ + 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x00, 0x3f, 0xf7, 0x07, 0xd3, 0x34, 0x6f, 0xdb, 0xc9, 0x37, 0xb7, 0x84, \ + 0xdc, 0x37, 0x45, 0xe1, 0x63, 0xad, 0xb8, 0xb6, 0x75, 0xb1, 0xc7, 0x35, \ + 0xb4, 0x77, 0x2a, 0x5b, 0x77, 0xf9, 0x7e, 0xe0, 0xc1, 0xa3, 0xd1, 0xb7, \ + 0xcb, 0xa9, 0x5a, 0xc1, 0x87, 0xda, 0x5a, 0xfa, 0x17, 0xe4, 0xd5, 0x38, \ + 0x03, 0xde, 0x68, 0x98, 0x81, 0xec, 0xb5, 0xf2, 0x2a, 0x8d, 0xe9, 0x2c, \ + 0xf3, 0xa6, 0xe5, 0x32, 0x17, 0x7f, 0x33, 0x81, 0xe8, 0x38, 0x72, 0xd5, \ + 0x9c, 0xfa, 0x4e, 0xfb, 0x26, 0xf5, 0x15, 0x0b, 0xaf, 0x84, 0x66, 0xab, \ + 0x02, 0xe0, 0x18, 0xd5, 0x91, 0x7c, 0xd6, 0x8f, 0xc9, 0x4b, 0x76, 0x08, \ + 0x2b, 0x1d, 0x81, 0x68, 0x30, 0xe1, 0xfa, 0x70, 0x6c, 0x13, 0x4e, 0x10, \ + 0x03, 0x35, 0x3e, 0xc5, 0xca, 0x58, 0x20, 0x8a, 0x21, 0x18, 0x38, 0xa0, \ + 0x0f, 0xed, 0xc4, 0xbb, 0x45, 0x6f, 0xf5, 0x84, 0x5b, 0xb0, 0xcf, 0x4e, \ + 0x9d, 0x58, 0x13, 0x6b, 0x35, 0x35, 0x69, 0xa1, 0xd2, 0xc4, 0xf2, 0xc1, \ + 0x48, 0x04, 0x20, 0x51, 0xb9, 0x6b, 0xa4, 0x5d, 0xa5, 0x4b, 0x84, 0x88, \ + 0x43, 0x48, 0x99, 0x2c, 0xbb, 0xa4, 0x97, 0xd6, 0xd6, 0x18, 0xf6, 0xec, \ + 0x5c, 0xd1, 0x31, 0x49, 0xc9, 0xf2, 0x8f, 0x0b, 0x4d, 0xef, 0x09, 0x02, \ + 0xfe, 0x7d, 0xfd, 0xbb, 0xaf, 0x2b, 0x83, 0x94, 0x22, 0xc4, 0xa7, 0x3e, \ + 0x66, 0xf5, 0xe0, 0x57, 0xdc, 0xf2, 0xed, 0x2c, 0x3e, 0x81, 0x74, 0x76, \ + 0x1e, 0x96, 0x6f, 0x74, 0x1e, 0x32, 0x0e, 0x14, 0x31, 0xd0, 0x74, 0xf0, \ + 0xf4, 0x07, 0xbd, 0xc3, 0xd1, 0x22, 0xc2, 0xa8, 0x95, 0x92, 0x06, 0x7f, \ + 0x43, 0x02, 0x91, 0xbc, 0xdd, 0x23, 0x01, 0x89, 0x94, 0x20, 0x44, 0x64, \ + 0xf5, 0x1d, 0x67, 0xd2, 0x8f, 0xe8, 0x69, 0xa5, 0x29, 0x25, 0xe6, 0x50, \ + 0x9c, 0xe3, 0xe9, 0xcb, 0x75, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x29, 0x3e, \ + 0xaa, 0x6b, 0xd5, 0x59, 0x1e, 0x9c, 0xe6, 0x47, 0xd5, 0xb6, 0xd7, 0xe3, \ + 0xf1, 0x8e, 0x9e, 0xe9, 0x83, 0x5f, 0x10, 0x9f, 0x63, 0xec, 0x04, 0x44, \ + 0xcc, 0x3f, 0xf8, 0xd9, 0x3a, 0x17, 0xe0, 0x4f, 0xfe, 0xd8, 0x4d, 0xcd, \ + 0x46, 0x54, 0x74, 0xbf, 0x0a, 0xc4, 0x67, 0x9c, 0xa7, 0xd8, 0x89, 0x65, \ + 0x4c, 0xfd, 0x58, 0x2a, 0x47, 0x0f, 0xf4, 0x37, 0xb6, 0x55, 0xb0, 0x1d, \ + 0xed, 0xa7, 0x39, 0xfc, 0x4f, 0xa3, 0xc4, 0x75, 0x3a, 0xa3, 0x98, 0xa7, \ + 0x45, 0xf5, 0x66, 0xcb, 0x7c, 0x65, 0xfb, 0x80, 0x23, 0xe6, 0xff, 0xfd, \ + 0x99, 0x1f, 0x8e, 0x6b, 0xff, 0x5e, 0x93, 0x66, 0xdf, 0x6c, 0x6f, 0xc3, \ + 0xf6, 0x38, 0x2e, 0xff, 0x69, 0xb5, 0xac, 0xae, 0xbb, 0xc6, 0x71, 0x16, \ + 0x6b, 0xd0, 0xf8, 0x22, 0xd9, 0xf8, 0xa2, 0x72, 0x20, 0xd2, 0xe2, 0x3a, \ + 0x70, 0x4b, 0xde, 0xab, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xda, 0x51, 0x9b, \ + 0xb8, 0xb2, 0x2a, 0x14, 0x75, 0x58, 0x40, 0x8d, 0x27, 0x70, 0xfa, 0x31, \ + 0x48, 0xb0, 0x20, 0x21, 0x34, 0xfa, 0x4c, 0x57, 0xa8, 0x11, 0x88, 0xf3, \ + 0xa7, 0xae, 0x21, 0xe9, 0xb6, 0x2b, 0xd1, 0xcd, 0xa7, 0xf8, 0xd8, 0x0c, \ + 0x8a, 0x76, 0x22, 0x35, 0x44, 0xce, 0x3f, 0x25, 0x29, 0x83, 0x7d, 0x79, \ + 0xa7, 0x31, 0xd6, 0xec, 0xb2, 0xbf, 0xda, 0x34, 0xb6, 0xf6, 0xb2, 0x3b, \ + 0xf3, 0x78, 0x5a, 0x04, 0x83, 0x33, 0x3e, 0xa2, 0xe2, 0x81, 0x82, 0x13, \ + 0xd4, 0x35, 0x17, 0x63, 0x9b, 0x9e, 0xc4, 0x8d, 0x91, 0x4c, 0x03, 0x77, \ + 0xc7, 0x71, 0x5b, 0xee, 0x83, 0x6d, 0xd5, 0x78, 0x88, 0xf6, 0x2c, 0x79, \ + 0xc2, 0x4a, 0xb4, 0x79, 0x90, 0x70, 0xbf, 0xdf, 0x34, 0x56, 0x96, 0x71, \ + 0xe3, 0x0e, 0x68, 0x91, 0xbc, 0xea, 0xcb, 0x33, 0xc0, 0xbe, 0x45, 0xd7, \ + 0xfc, 0x30, 0xfd, 0x01, 0x3b, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x9f, 0x2a, \ + 0xb7, 0x38, 0x19, 0xc7, 0x17, 0x95, 0x73, 0x78, 0xae, 0xf5, 0xcb, 0x75, \ + 0x83, 0x7f, 0x19, 0x4b, 0xcb, 0x86, 0xfb, 0x4a, 0x15, 0x9a, 0xb6, 0x17, \ + 0x04, 0x49, 0x07, 0x8d, 0xf6, 0x66, 0x4a, 0x06, 0xf6, 0x05, 0xa7, 0xdf, \ + 0x66, 0x82, 0x3c, 0xff, 0xb6, 0x1d, 0x57, 0x89, 0x33, 0x5f, 0x9c, 0x05, \ + 0x75, 0x7f, 0xf3, 0x5d, 0xdc, 0x34, 0x65, 0x72, 0x85, 0x22, 0xa4, 0x14, \ + 0x1b, 0x41, 0xc3, 0xe4, 0xd0, 0x9e, 0x69, 0xd5, 0xeb, 0x38, 0x74, 0x70, \ + 0x43, 0xdc, 0xd9, 0x50, 0xe4, 0x97, 0x6d, 0x73, 0xd6, 0xfb, 0xc8, 0xa7, \ + 0xfa, 0xb4, 0xc2, 0xc4, 0x9d, 0x5d, 0x0c, 0xd5, 0x9f, 0x79, 0xb3, 0x54, \ + 0xc2, 0xb7, 0x6c, 0x3d, 0x7d, 0xcb, 0x2d, 0xf8, 0xc4, 0xf3, 0x78, 0x5a, \ + 0x33, 0x2a, 0xb8, 0x0c, 0x6d, 0x06, 0xfa, 0xf2, 0x62, 0xd3, 0x42, 0xd0, \ + 0xbd, 0xc8, 0x4a, 0xa5, 0x0d, 0x02, 0x81, 0x81, 0x00, 0xd4, 0xa9, 0x90, \ + 0x15, 0xde, 0xbf, 0x2c, 0xc4, 0x8d, 0x9d, 0xfb, 0xa1, 0xc2, 0xe4, 0x83, \ + 0xe3, 0x79, 0x65, 0x22, 0xd3, 0xb7, 0x49, 0x6c, 0x4d, 0x94, 0x1f, 0x22, \ + 0xb1, 0x60, 0xe7, 0x3a, 0x00, 0xb1, 0x38, 0xa2, 0xab, 0x0f, 0xb4, 0x6c, \ + 0xaa, 0xe7, 0x9e, 0x34, 0xe3, 0x7c, 0x40, 0x78, 0x53, 0xb2, 0xf9, 0x23, \ + 0xea, 0xa0, 0x9a, 0xea, 0x60, 0xc8, 0x8f, 0xa6, 0xaf, 0xdf, 0x29, 0x09, \ + 0x4b, 0x06, 0x1e, 0x31, 0xad, 0x17, 0xda, 0xd8, 0xd1, 0xe9, 0x33, 0xab, \ + 0x5b, 0x18, 0x08, 0x5b, 0x87, 0xf8, 0xa5, 0x1f, 0xfd, 0xbb, 0xdc, 0xd8, \ + 0xed, 0x97, 0x57, 0xe4, 0xc3, 0x73, 0xd6, 0xf0, 0x9e, 0x01, 0xa6, 0x9b, \ + 0x48, 0x8e, 0x7a, 0xb4, 0xbb, 0xe5, 0x88, 0x91, 0xc5, 0x2a, 0xdf, 0x4b, \ + 0xba, 0xd0, 0x8b, 0x3e, 0x03, 0x97, 0x77, 0x2f, 0x47, 0x7e, 0x51, 0x0c, \ + 0xae, 0x65, 0x8d, 0xde, 0x87, 0x02, 0x81, 0x80, 0x20, 0x24, 0x0f, 0xd2, \ + 0xaf, 0xc2, 0x28, 0x3b, 0x97, 0x20, 0xb2, 0x92, 0x49, 0xeb, 0x09, 0x68, \ + 0x40, 0xb2, 0xbe, 0xd1, 0xc3, 0x83, 0x94, 0x34, 0x38, 0xd6, 0xc9, 0xec, \ + 0x34, 0x09, 0xf9, 0x41, 0x6d, 0x5c, 0x42, 0x94, 0xf7, 0x04, 0xfc, 0x32, \ + 0x39, 0x69, 0xbc, 0x1c, 0xfb, 0x3e, 0x61, 0x98, 0xc0, 0x80, 0xd8, 0x36, \ + 0x47, 0xc3, 0x6d, 0xc2, 0x2e, 0xe7, 0x81, 0x2a, 0x17, 0x34, 0x64, 0x30, \ + 0x4e, 0x96, 0xbb, 0x26, 0x16, 0xb9, 0x41, 0x36, 0xfe, 0x8a, 0xd6, 0x53, \ + 0x7c, 0xaa, 0xec, 0x39, 0x42, 0x50, 0xef, 0xe3, 0xb3, 0x01, 0x28, 0x32, \ + 0xca, 0x6d, 0xf5, 0x9a, 0x1e, 0x9f, 0x37, 0xbe, 0xfe, 0x38, 0x20, 0x22, \ + 0x91, 0x8c, 0xcd, 0x95, 0x02, 0xf2, 0x4d, 0x6f, 0x1a, 0xb4, 0x43, 0xf0, \ + 0x19, 0xdf, 0x65, 0xc0, 0x92, 0xe7, 0x9d, 0x2f, 0x09, 0xe7, 0xec, 0x69, \ + 0xa8, 0xc2, 0x8f, 0x0d \ +} +/* END FILE */ + +/* + * Test server Certificates + * + * Test server certificates are defined for each choice + * of the following parameters: + * - PEM or DER encoding + * - SHA-1 or SHA-256 hash + * - RSA or EC key + * + * Things to add: + * - multiple EC curve types + */ + +/* This is taken from tests/data_files/server5.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_EC_PEM tests/data_files/server5.crt */ +#define TEST_SRV_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" \ + "MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" \ + "CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" \ + "2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" \ + "BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" \ + "PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" \ + "clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" \ + "CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" \ + "C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" \ + "fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/server5.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_EC_DER tests/data_files/server5.crt.der */ +#define TEST_SRV_CRT_EC_DER { \ + 0x30, 0x82, 0x02, 0x1f, 0x30, 0x82, 0x01, 0xa5, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x09, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, \ + 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x33, 0x30, 0x39, 0x32, 0x34, 0x31, 0x35, 0x35, 0x32, 0x30, 0x34, \ + 0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x39, 0x32, 0x32, 0x31, 0x35, 0x35, \ + 0x32, 0x30, 0x34, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x59, \ + 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, \ + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, \ + 0x04, 0x37, 0xcc, 0x56, 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, \ + 0x59, 0x2d, 0xff, 0x20, 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, \ + 0xad, 0x14, 0xb5, 0xf7, 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, \ + 0xd8, 0x23, 0x11, 0xff, 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, \ + 0x8a, 0x88, 0xc2, 0x6b, 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, \ + 0x01, 0xc8, 0xb4, 0xed, 0xff, 0xa3, 0x81, 0x9d, 0x30, 0x81, 0x9a, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, \ + 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x50, 0x61, 0xa5, \ + 0x8f, 0xd4, 0x07, 0xd9, 0xd7, 0x82, 0x01, 0x0c, 0xe5, 0x65, 0x7f, 0x8c, \ + 0x63, 0x46, 0xa7, 0x13, 0xbe, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23, \ + 0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01, \ + 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb, \ + 0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09, \ + 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0a, 0x06, \ + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x68, 0x00, \ + 0x30, 0x65, 0x02, 0x31, 0x00, 0x9a, 0x2c, 0x5c, 0xd7, 0xa6, 0xdb, 0xa2, \ + 0xe5, 0x64, 0x0d, 0xf0, 0xb9, 0x4e, 0xdd, 0xd7, 0x61, 0xd6, 0x13, 0x31, \ + 0xc7, 0xab, 0x73, 0x80, 0xbb, 0xd3, 0xd3, 0x73, 0x13, 0x54, 0xad, 0x92, \ + 0x0b, 0x5d, 0xab, 0xd0, 0xbc, 0xf7, 0xae, 0x2f, 0xe6, 0xa1, 0x21, 0x29, \ + 0x35, 0x95, 0xaa, 0x3e, 0x39, 0x02, 0x30, 0x21, 0x36, 0x7f, 0x9d, 0xc6, \ + 0x5d, 0xc6, 0x0b, 0xab, 0x27, 0xf2, 0x25, 0x1d, 0x3b, 0xf1, 0xcf, 0xf1, \ + 0x35, 0x25, 0x14, 0xe7, 0xe5, 0xf1, 0x97, 0xb5, 0x59, 0xe3, 0x5e, 0x15, \ + 0x7c, 0x66, 0xb9, 0x90, 0x7b, 0xc7, 0x01, 0x10, 0x4f, 0x73, 0xc6, 0x00, \ + 0x21, 0x52, 0x2a, 0x0e, 0xf1, 0xc7, 0xd5 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server5.key. */ +/* BEGIN FILE string macro TEST_SRV_KEY_EC_PEM tests/data_files/server5.key */ +#define TEST_SRV_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" \ + "AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" \ + "6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/server5.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_KEY_EC_DER tests/data_files/server5.key.der */ +#define TEST_SRV_KEY_EC_DER { \ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf1, 0x2a, 0x13, 0x20, 0x76, \ + 0x02, 0x70, 0xa8, 0x3c, 0xbf, 0xfd, 0x53, 0xf6, 0x03, 0x1e, 0xf7, 0x6a, \ + 0x5d, 0x86, 0xc8, 0xa2, 0x04, 0xf2, 0xc3, 0x0c, 0xa9, 0xeb, 0xf5, 0x1f, \ + 0x0f, 0x0e, 0xa7, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x37, 0xcc, 0x56, \ + 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, 0x59, 0x2d, 0xff, 0x20, \ + 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, 0xad, 0x14, 0xb5, 0xf7, \ + 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, 0xd8, 0x23, 0x11, 0xff, \ + 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, 0x8a, 0x88, 0xc2, 0x6b, \ + 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, 0x01, 0xc8, 0xb4, 0xed, \ + 0xff \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2-sha256.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA256_PEM tests/data_files/server2-sha256.crt */ +#define TEST_SRV_CRT_RSA_SHA256_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ + "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ + "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ + "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ + "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ + "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ + "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ + "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ + "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQELBQADggEBAC465FJh\r\n" \ + "Pqel7zJngHIHJrqj/wVAxGAFOTF396XKATGAp+HRCqJ81Ry60CNK1jDzk8dv6M6U\r\n" \ + "HoS7RIFiM/9rXQCbJfiPD5xMTejZp5n5UYHAmxsxDaazfA5FuBhkfokKK6jD4Eq9\r\n" \ + "1C94xGKb6X4/VkaPF7cqoBBw/bHxawXc0UEPjqayiBpCYU/rJoVZgLqFVP7Px3sv\r\n" \ + "a1nOrNx8rPPI1hJ+ZOg8maiPTxHZnBVLakSSLQy/sWeWyazO1RnrbxjrbgQtYKz0\r\n" \ + "e3nwGpu1w13vfckFmUSBhHXH7AAS/HpKC4IH7G2GAk3+n8iSSN71sZzpxonQwVbo\r\n" \ + "pMZqLmbBm/7WPLc=\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/server2-sha256.crt.der. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA256_DER tests/data_files/server2-sha256.crt.der */ +#define TEST_SRV_CRT_RSA_SHA256_DER { \ + 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ + 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ + 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ + 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ + 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ + 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ + 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ + 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ + 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ + 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ + 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ + 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ + 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ + 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ + 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ + 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ + 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ + 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ + 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ + 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ + 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ + 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ + 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ + 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ + 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ + 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, \ + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0x3a, 0xe4, 0x52, 0x61, \ + 0x3e, 0xa7, 0xa5, 0xef, 0x32, 0x67, 0x80, 0x72, 0x07, 0x26, 0xba, 0xa3, \ + 0xff, 0x05, 0x40, 0xc4, 0x60, 0x05, 0x39, 0x31, 0x77, 0xf7, 0xa5, 0xca, \ + 0x01, 0x31, 0x80, 0xa7, 0xe1, 0xd1, 0x0a, 0xa2, 0x7c, 0xd5, 0x1c, 0xba, \ + 0xd0, 0x23, 0x4a, 0xd6, 0x30, 0xf3, 0x93, 0xc7, 0x6f, 0xe8, 0xce, 0x94, \ + 0x1e, 0x84, 0xbb, 0x44, 0x81, 0x62, 0x33, 0xff, 0x6b, 0x5d, 0x00, 0x9b, \ + 0x25, 0xf8, 0x8f, 0x0f, 0x9c, 0x4c, 0x4d, 0xe8, 0xd9, 0xa7, 0x99, 0xf9, \ + 0x51, 0x81, 0xc0, 0x9b, 0x1b, 0x31, 0x0d, 0xa6, 0xb3, 0x7c, 0x0e, 0x45, \ + 0xb8, 0x18, 0x64, 0x7e, 0x89, 0x0a, 0x2b, 0xa8, 0xc3, 0xe0, 0x4a, 0xbd, \ + 0xd4, 0x2f, 0x78, 0xc4, 0x62, 0x9b, 0xe9, 0x7e, 0x3f, 0x56, 0x46, 0x8f, \ + 0x17, 0xb7, 0x2a, 0xa0, 0x10, 0x70, 0xfd, 0xb1, 0xf1, 0x6b, 0x05, 0xdc, \ + 0xd1, 0x41, 0x0f, 0x8e, 0xa6, 0xb2, 0x88, 0x1a, 0x42, 0x61, 0x4f, 0xeb, \ + 0x26, 0x85, 0x59, 0x80, 0xba, 0x85, 0x54, 0xfe, 0xcf, 0xc7, 0x7b, 0x2f, \ + 0x6b, 0x59, 0xce, 0xac, 0xdc, 0x7c, 0xac, 0xf3, 0xc8, 0xd6, 0x12, 0x7e, \ + 0x64, 0xe8, 0x3c, 0x99, 0xa8, 0x8f, 0x4f, 0x11, 0xd9, 0x9c, 0x15, 0x4b, \ + 0x6a, 0x44, 0x92, 0x2d, 0x0c, 0xbf, 0xb1, 0x67, 0x96, 0xc9, 0xac, 0xce, \ + 0xd5, 0x19, 0xeb, 0x6f, 0x18, 0xeb, 0x6e, 0x04, 0x2d, 0x60, 0xac, 0xf4, \ + 0x7b, 0x79, 0xf0, 0x1a, 0x9b, 0xb5, 0xc3, 0x5d, 0xef, 0x7d, 0xc9, 0x05, \ + 0x99, 0x44, 0x81, 0x84, 0x75, 0xc7, 0xec, 0x00, 0x12, 0xfc, 0x7a, 0x4a, \ + 0x0b, 0x82, 0x07, 0xec, 0x6d, 0x86, 0x02, 0x4d, 0xfe, 0x9f, 0xc8, 0x92, \ + 0x48, 0xde, 0xf5, 0xb1, 0x9c, 0xe9, 0xc6, 0x89, 0xd0, 0xc1, 0x56, 0xe8, \ + 0xa4, 0xc6, 0x6a, 0x2e, 0x66, 0xc1, 0x9b, 0xfe, 0xd6, 0x3c, 0xb7 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2.crt. */ +/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA1_PEM tests/data_files/server2.crt */ +#define TEST_SRV_CRT_RSA_SHA1_PEM \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" \ +"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" \ +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n" \ +"cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n" \ +"O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n" \ +"KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n" \ +"iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n" \ +"HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n" \ +"Awgk0+4m0T25cNs=\r\n" \ +"-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is taken from tests/data_files/server2.crt.der. */ +/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA1_DER tests/data_files/server2.crt.der */ +#define TEST_SRV_CRT_RSA_SHA1_DER { \ + 0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, 0x31, 0x32, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \ + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \ + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \ + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \ + 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \ + 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \ + 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \ + 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \ + 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \ + 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \ + 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \ + 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \ + 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \ + 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \ + 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \ + 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \ + 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \ + 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \ + 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \ + 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \ + 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \ + 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \ + 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \ + 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \ + 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \ + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \ + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \ + 0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \ + 0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \ + 0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \ + 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \ + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, \ + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x01, 0x73, 0x0b, 0x4a, 0xc5, \ + 0xcb, 0xa0, 0xde, 0xf1, 0x63, 0x1c, 0x76, 0x04, 0x2b, 0x13, 0x0d, 0xc0, \ + 0x84, 0x11, 0xc5, 0x8f, 0x3a, 0xa7, 0xc5, 0x9c, 0x35, 0x7a, 0x77, 0xb8, \ + 0x20, 0x14, 0x82, 0xee, 0x54, 0xf0, 0xf2, 0xb0, 0x52, 0xcb, 0x78, 0xce, \ + 0x59, 0x07, 0x4f, 0x51, 0x69, 0xfe, 0xd3, 0x2f, 0xe9, 0x09, 0xe7, 0x85, \ + 0x92, 0xd8, 0xba, 0xb1, 0xeb, 0xc5, 0x76, 0x5d, 0x61, 0x2d, 0xe9, 0x86, \ + 0xb5, 0xde, 0x2a, 0xf9, 0x3f, 0x53, 0x28, 0x42, 0x86, 0x83, 0x73, 0x43, \ + 0xe0, 0x04, 0x5f, 0x07, 0x90, 0x14, 0x65, 0x9f, 0x6e, 0x10, 0x7a, 0xbc, \ + 0x58, 0x19, 0x22, 0xc2, 0xeb, 0x39, 0x72, 0x51, 0x92, 0xd7, 0xb4, 0x1d, \ + 0x75, 0x2f, 0xd3, 0x3a, 0x2b, 0x01, 0xe7, 0xdb, 0x50, 0xae, 0xe2, 0xf1, \ + 0xd4, 0x4d, 0x5b, 0x3c, 0xbb, 0x41, 0x2b, 0x2a, 0xa4, 0xe2, 0x4a, 0x02, \ + 0xe5, 0x60, 0x14, 0x2c, 0x9c, 0x1f, 0xa6, 0xcc, 0x06, 0x4b, 0x25, 0x89, \ + 0x4e, 0x96, 0x30, 0x22, 0x9c, 0x5c, 0x58, 0x4d, 0xc3, 0xda, 0xd0, 0x6e, \ + 0x50, 0x1e, 0x8c, 0x65, 0xf5, 0xd9, 0x17, 0x35, 0xa6, 0x58, 0x43, 0xb2, \ + 0x29, 0xb7, 0xa8, 0x5e, 0x35, 0xde, 0xf0, 0x60, 0x42, 0x1a, 0x01, 0xcb, \ + 0xcb, 0x0b, 0xd8, 0x0e, 0xc1, 0x90, 0xdf, 0xa1, 0xd2, 0x1a, 0xd1, 0x2c, \ + 0x02, 0xf4, 0x76, 0x41, 0xa4, 0xcb, 0x4b, 0x15, 0x98, 0x71, 0xf9, 0x35, \ + 0x7d, 0xb0, 0xe7, 0xe2, 0x34, 0x96, 0x91, 0xbe, 0x32, 0x67, 0x2d, 0x6b, \ + 0xd3, 0x55, 0x04, 0x8a, 0x01, 0x50, 0xb4, 0xe3, 0x62, 0x78, 0x6c, 0x11, \ + 0x15, 0xa5, 0x2a, 0x11, 0xc1, 0x49, 0x1c, 0x9b, 0xc4, 0x10, 0x65, 0x60, \ + 0x87, 0xd9, 0x1e, 0x69, 0x59, 0x4e, 0x8f, 0x6b, 0xeb, 0xc1, 0xfe, 0x6b, \ + 0xe2, 0x63, 0x78, 0x95, 0x6e, 0xe0, 0x2d, 0xd7, 0xa7, 0x37, 0xa8 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/server2.key. */ +/* BEGIN FILE string macro TEST_SRV_KEY_RSA_PEM tests/data_files/server2.key */ +#define TEST_SRV_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" \ + "lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" \ + "2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" \ + "Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" \ + "GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" \ + "y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" \ + "++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" \ + "Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" \ + "/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" \ + "WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" \ + "GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" \ + "TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" \ + "CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" \ + "nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" \ + "AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" \ + "sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" \ + "mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" \ + "BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" \ + "whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" \ + "vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" \ + "3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" \ + "3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" \ + "ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" \ + "4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" \ + "TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This was generated from tests/data_files/server2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_SRV_KEY_RSA_DER tests/data_files/server2.key.der */ +#define TEST_SRV_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, \ + 0xb8, 0x99, 0xac, 0x0e, 0x78, 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, \ + 0x16, 0xd0, 0x5a, 0xe4, 0xcd, 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, \ + 0x96, 0xa7, 0x52, 0xb4, 0x90, 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, \ + 0xfc, 0xb6, 0x34, 0xac, 0x24, 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, \ + 0xb0, 0x28, 0x7d, 0xa1, 0xda, 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, \ + 0xfe, 0xc1, 0x04, 0x52, 0xb3, 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, \ + 0xd8, 0x90, 0xc1, 0x61, 0xb4, 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, \ + 0xab, 0x74, 0x5e, 0x07, 0x7d, 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, \ + 0xd9, 0x0d, 0x1c, 0x2d, 0x49, 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, \ + 0x0b, 0x8a, 0x4f, 0x69, 0x0c, 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, \ + 0x66, 0x7d, 0xae, 0x54, 0x2b, 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, \ + 0xc3, 0xcd, 0x40, 0x49, 0x08, 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, \ + 0x46, 0xbf, 0xd0, 0xb8, 0xaa, 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, \ + 0x1e, 0x44, 0x18, 0x0f, 0x0f, 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, \ + 0x18, 0xc6, 0x62, 0x2f, 0xc7, 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, \ + 0x27, 0x89, 0x29, 0x01, 0xc5, 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, \ + 0x4a, 0x0e, 0xef, 0xd6, 0xde, 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, \ + 0x7a, 0xc4, 0x02, 0x3c, 0x9a, 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, \ + 0xcb, 0x73, 0x4b, 0x52, 0x96, 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, \ + 0x39, 0x5a, 0xd3, 0x0f, 0xb0, 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, \ + 0x12, 0x01, 0x30, 0x97, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x01, 0x00, 0x97, 0x47, 0x44, 0xbc, 0x10, 0x81, 0xc5, 0x18, 0xe4, 0x59, \ + 0xfb, 0xe0, 0x2d, 0x3a, 0x0e, 0x9e, 0x10, 0xdc, 0x43, 0xfb, 0x15, 0x6c, \ + 0xd1, 0xfd, 0x48, 0x78, 0x6c, 0xf9, 0xed, 0x38, 0xe8, 0xdd, 0x09, 0xd7, \ + 0x5f, 0xb5, 0x41, 0x64, 0xd7, 0x63, 0xfa, 0x9d, 0x44, 0x0a, 0xf8, 0x42, \ + 0x13, 0xf1, 0xbb, 0x5e, 0x79, 0x20, 0x53, 0x98, 0x4b, 0x65, 0x7f, 0x86, \ + 0x67, 0x48, 0xe4, 0xcf, 0xfb, 0x6a, 0x24, 0xe2, 0x34, 0xbd, 0x14, 0x9d, \ + 0x2c, 0x16, 0xe2, 0xa4, 0x79, 0xd6, 0xa2, 0xec, 0x81, 0x43, 0x87, 0xbf, \ + 0x03, 0x5c, 0x88, 0x25, 0xd9, 0x41, 0xb6, 0xa5, 0xf1, 0x27, 0x52, 0x84, \ + 0xfe, 0x2b, 0x6e, 0x1d, 0x16, 0xcd, 0x73, 0x88, 0xf8, 0x90, 0xbf, 0x19, \ + 0xfe, 0xbe, 0xa9, 0xbf, 0x09, 0xd3, 0x23, 0x43, 0xd2, 0xc7, 0x61, 0x2a, \ + 0xb3, 0x4e, 0x3c, 0x61, 0xd4, 0xbd, 0xd8, 0xb4, 0xfa, 0xa8, 0x0b, 0xf8, \ + 0x7e, 0x56, 0xcd, 0x0f, 0x13, 0x27, 0xda, 0xe6, 0x3b, 0xb3, 0x8c, 0x9c, \ + 0x4b, 0x84, 0x3c, 0xc3, 0x52, 0x57, 0x9c, 0x27, 0x9a, 0x02, 0x76, 0x26, \ + 0x59, 0x82, 0x39, 0xc3, 0x13, 0xbe, 0x6e, 0xf4, 0x44, 0x2d, 0x1d, 0x8c, \ + 0x73, 0x3e, 0x43, 0x99, 0x59, 0xcb, 0xf2, 0x34, 0x72, 0x9a, 0x5e, 0xa5, \ + 0xeb, 0x9f, 0x36, 0x6d, 0x2b, 0xf9, 0xa2, 0xe7, 0xd1, 0x78, 0x52, 0x1b, \ + 0xc8, 0xf6, 0x5b, 0x41, 0x69, 0x57, 0x81, 0x89, 0xe9, 0xbb, 0xa1, 0xde, \ + 0x19, 0x37, 0x3b, 0x13, 0x5c, 0xca, 0x61, 0x01, 0x86, 0xff, 0xdf, 0x83, \ + 0x41, 0x49, 0x7f, 0xd6, 0xf4, 0x2e, 0x08, 0xfa, 0x90, 0xc2, 0x7c, 0xb4, \ + 0xb5, 0x0a, 0x17, 0xdb, 0x0e, 0x6d, 0x75, 0x8a, 0x5d, 0x31, 0xd5, 0x66, \ + 0xfb, 0x39, 0x0b, 0xb5, 0xb6, 0xa3, 0xcd, 0xd4, 0xef, 0x88, 0x92, 0x5a, \ + 0x4d, 0x6c, 0xcb, 0xea, 0x5b, 0x79, 0x02, 0x81, 0x81, 0x00, 0xdf, 0x3a, \ + 0xf9, 0x25, 0x5e, 0x24, 0x37, 0x26, 0x40, 0x97, 0x2f, 0xe0, 0x4a, 0xba, \ + 0x52, 0x1b, 0x51, 0xaf, 0x84, 0x06, 0x32, 0x24, 0x0c, 0xcf, 0x44, 0xa8, \ + 0x77, 0xa7, 0xad, 0xb5, 0x8c, 0x58, 0xcc, 0xc8, 0x31, 0xb7, 0x0d, 0xbc, \ + 0x08, 0x8a, 0xe0, 0xa6, 0x8c, 0xc2, 0x73, 0xe5, 0x1a, 0x64, 0x92, 0xe8, \ + 0xed, 0x4c, 0x6f, 0x0b, 0xa6, 0xa7, 0xf3, 0x9a, 0xf5, 0x6f, 0x69, 0xca, \ + 0x3c, 0x22, 0xd0, 0x15, 0xa8, 0x20, 0x27, 0x41, 0xf8, 0x43, 0x42, 0x7f, \ + 0xb1, 0x93, 0xa1, 0x04, 0x85, 0xda, 0xa0, 0x1c, 0xd6, 0xc6, 0xf7, 0x8a, \ + 0x9e, 0xea, 0x5c, 0x78, 0xa7, 0x55, 0xc4, 0x6b, 0x05, 0x8b, 0xc0, 0x83, \ + 0xcb, 0xce, 0x83, 0x05, 0xf8, 0xb2, 0x16, 0x2b, 0xdf, 0x06, 0x3f, 0xb8, \ + 0xec, 0x16, 0xda, 0x43, 0x33, 0xc1, 0x8f, 0xb0, 0xb8, 0xac, 0xae, 0xd4, \ + 0x94, 0xb8, 0xda, 0x6f, 0x6a, 0xc3, 0x02, 0x81, 0x81, 0x00, 0xdd, 0xae, \ + 0x00, 0xcd, 0xa0, 0x72, 0x1a, 0x05, 0x8a, 0xee, 0x2f, 0xd4, 0x71, 0x4b, \ + 0xf0, 0x3e, 0xe5, 0xc1, 0xe1, 0x29, 0x8b, 0xa6, 0x67, 0x30, 0x98, 0xe7, \ + 0x12, 0xef, 0xdd, 0x12, 0x01, 0x90, 0x24, 0x58, 0xf0, 0x76, 0x92, 0xe7, \ + 0x3d, 0xbb, 0x23, 0xe1, 0xce, 0xf9, 0xa1, 0xd4, 0x38, 0x1b, 0x3f, 0x20, \ + 0xb3, 0x0f, 0x65, 0x6a, 0x8f, 0x55, 0x57, 0x36, 0xee, 0xb2, 0x84, 0x44, \ + 0xfc, 0x91, 0x88, 0xe1, 0xa4, 0xdd, 0x3b, 0x4a, 0x40, 0x4d, 0x7c, 0x86, \ + 0xed, 0xe1, 0xb5, 0x42, 0xef, 0xb9, 0x61, 0xcd, 0x58, 0x19, 0x77, 0x02, \ + 0xae, 0x58, 0x80, 0xdb, 0x13, 0x3d, 0xc7, 0x1f, 0x9d, 0xed, 0xff, 0xac, \ + 0x98, 0xfc, 0xcd, 0xf9, 0x62, 0x04, 0x83, 0x91, 0x89, 0x0d, 0x86, 0x43, \ + 0x8c, 0x0c, 0xc7, 0x1b, 0x90, 0x4d, 0xbe, 0x2f, 0xc5, 0x7c, 0xcd, 0x42, \ + 0xf5, 0xd3, 0xad, 0x8e, 0xfd, 0x9d, 0x02, 0x81, 0x80, 0x17, 0x4b, 0x79, \ + 0x2a, 0x6c, 0x1b, 0x8d, 0x61, 0xc1, 0x85, 0xc5, 0x6a, 0x3b, 0x82, 0x1c, \ + 0x05, 0x5b, 0xcd, 0xdc, 0x12, 0x25, 0x73, 0x5b, 0x9e, 0xd9, 0x84, 0x57, \ + 0x10, 0x39, 0x71, 0x63, 0x96, 0xf4, 0xaf, 0xc3, 0x78, 0x5d, 0xc7, 0x8c, \ + 0x80, 0xa9, 0x96, 0xd7, 0xc3, 0x87, 0x02, 0x96, 0x71, 0x7e, 0x5f, 0x2e, \ + 0x3c, 0x36, 0xae, 0x59, 0x92, 0xd7, 0x3a, 0x09, 0x78, 0xb9, 0xea, 0x6f, \ + 0xc2, 0x16, 0x42, 0xdc, 0x4b, 0x96, 0xad, 0x2c, 0xb2, 0x20, 0x23, 0x61, \ + 0x2d, 0x8d, 0xb5, 0x02, 0x1e, 0xe1, 0x6c, 0x81, 0x01, 0x3c, 0x5d, 0xcb, \ + 0xdd, 0x9b, 0x0e, 0xc0, 0x2f, 0x94, 0x12, 0xb2, 0xfe, 0x75, 0x75, 0x8b, \ + 0x74, 0x1e, 0x7a, 0x26, 0x0c, 0xb7, 0x81, 0x96, 0x81, 0x79, 0x6e, 0xdb, \ + 0xbc, 0x3a, 0xc4, 0x9e, 0x87, 0x09, 0x6e, 0xa0, 0xa6, 0xec, 0x8b, 0xa4, \ + 0x85, 0x71, 0xce, 0x04, 0xaf, 0x02, 0x81, 0x81, 0x00, 0xc2, 0xa7, 0x47, \ + 0x07, 0x48, 0x6a, 0xc8, 0xd4, 0xb3, 0x20, 0xe1, 0x98, 0xee, 0xff, 0x5a, \ + 0x6f, 0x30, 0x7a, 0xa5, 0x47, 0x40, 0xdc, 0x16, 0x62, 0x42, 0xf1, 0x2c, \ + 0xdc, 0xb8, 0xc7, 0x55, 0xde, 0x07, 0x3c, 0x9d, 0xb1, 0xd0, 0xdf, 0x02, \ + 0x82, 0xb0, 0x48, 0x58, 0xe1, 0x34, 0xab, 0xcf, 0xb4, 0x85, 0x23, 0x26, \ + 0x78, 0x4f, 0x7a, 0x59, 0x6f, 0xfb, 0x8c, 0x3d, 0xdf, 0x3d, 0x6c, 0x02, \ + 0x47, 0x9c, 0xe5, 0x5e, 0x49, 0xf1, 0x05, 0x0b, 0x1f, 0xbf, 0x48, 0x0f, \ + 0xdc, 0x10, 0xb9, 0x3d, 0x1d, 0x10, 0x77, 0x2a, 0x73, 0xf9, 0xdf, 0xbd, \ + 0xcd, 0xf3, 0x1f, 0xeb, 0x6e, 0x64, 0xca, 0x2b, 0x78, 0x4f, 0xf8, 0x73, \ + 0xc2, 0x10, 0xef, 0x79, 0x95, 0x33, 0x1e, 0x79, 0x35, 0x09, 0xff, 0x88, \ + 0x1b, 0xb4, 0x3e, 0x4c, 0xe1, 0x27, 0x2e, 0x75, 0x80, 0x58, 0x11, 0x03, \ + 0x21, 0x23, 0x96, 0x9a, 0xb5, 0x02, 0x81, 0x80, 0x05, 0x12, 0x64, 0x71, \ + 0x83, 0x00, 0x1c, 0xfe, 0xef, 0x83, 0xea, 0xdd, 0x2c, 0xc8, 0x2c, 0x00, \ + 0x62, 0x1e, 0x8f, 0x3a, 0xdb, 0x1c, 0xab, 0xd6, 0x34, 0x8b, 0xd1, 0xb2, \ + 0x5a, 0x4f, 0x3d, 0x37, 0x38, 0x02, 0xe0, 0xd7, 0x70, 0xc1, 0xb0, 0x47, \ + 0xe0, 0x08, 0x1a, 0x84, 0xec, 0x48, 0xc5, 0x7c, 0x76, 0x83, 0x12, 0x67, \ + 0xab, 0x7c, 0x9f, 0x90, 0x97, 0xc8, 0x8f, 0x07, 0xf4, 0xb3, 0x60, 0xf2, \ + 0x3f, 0x49, 0x18, 0xdb, 0x2e, 0x94, 0x6b, 0x53, 0x9e, 0xa2, 0x63, 0xde, \ + 0x63, 0xd9, 0xab, 0x21, 0x2e, 0x2d, 0x0a, 0xe0, 0xd0, 0xe8, 0xba, 0xc4, \ + 0x4c, 0x1e, 0xa5, 0xf5, 0x51, 0xa8, 0xc4, 0x92, 0xf8, 0x7f, 0x21, 0xe7, \ + 0x65, 0xbf, 0x0b, 0xe6, 0x01, 0xaf, 0x9c, 0x1d, 0x5b, 0x6c, 0x3f, 0x1c, \ + 0x2f, 0xa6, 0x0f, 0x68, 0x38, 0x8e, 0x85, 0xc4, 0x6c, 0x78, 0x2f, 0x6f, \ + 0x06, 0x21, 0x2e, 0x56 \ +} +/* END FILE */ + +/* + * Test client Certificates + * + * Test client certificates are defined for each choice + * of the following parameters: + * - PEM or DER encoding + * - RSA or EC key + * + * Things to add: + * - hash type + * - multiple EC curve types + */ + +/* This is taken from tests/data_files/cli2.crt. */ +/* BEGIN FILE string macro TEST_CLI_CRT_EC_PEM tests/data_files/cli2.crt */ +#define TEST_CLI_CRT_EC_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIB3zCCAWOgAwIBAgIBDTAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw\r\n" \ + "DwYDVQQKDAhQb2xhclNTTDEcMBoGA1UEAwwTUG9sYXJTU0wgVGVzdCBFQyBDQTAe\r\n" \ + "Fw0xOTAyMTAxNDQ0MDBaFw0yOTAyMTAxNDQ0MDBaMEExCzAJBgNVBAYTAk5MMREw\r\n" \ + "DwYDVQQKDAhQb2xhclNTTDEfMB0GA1UEAwwWUG9sYXJTU0wgVGVzdCBDbGllbnQg\r\n" \ + "MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFflrrFz39Osu5O4gf8Sru7mU6zO\r\n" \ + "VVP2NA7MLuNjJQvfmOLzXGA2lsDVGBRw5X+f1UtFGOWwbNVc+JaPh3Cj5MejTTBL\r\n" \ + "MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMB8GA1Ud\r\n" \ + "IwQYMBaAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8MAwGCCqGSM49BAMCBQADaAAwZQIx\r\n" \ + "AMqme4DKMldUlplDET9Q6Eptre7uUWKhsLOF+zPkKDlfzpIkJYEFgcloDHGYw80u\r\n" \ + "IgIwNftyPXsabTqMM7iEHgVpX/GRozKklY9yQI/5eoA6gGW7Y+imuGR/oao5ySOb\r\n" \ + "a9Vk\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/cli2.crt.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_CRT_EC_DER tests/data_files/cli2.crt.der */ +#define TEST_CLI_CRT_EC_DER { \ + 0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \ + 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, \ + 0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, \ + 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, \ + 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, \ + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \ + 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \ + 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, \ + 0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \ + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, \ + 0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, \ + 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac, \ + 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce, \ + 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf, \ + 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70, \ + 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, \ + 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b, \ + 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, \ + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00, \ + 0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6, \ + 0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, \ + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, \ + 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, \ + 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, \ + 0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43, \ + 0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1, \ + 0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24, \ + 0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e, \ + 0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c, \ + 0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4, \ + 0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb, \ + 0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b, \ + 0x6b, 0xd5, 0x64 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli2.key. */ +/* BEGIN FILE string macro TEST_CLI_KEY_EC_PEM tests/data_files/cli2.key */ +#define TEST_CLI_KEY_EC_PEM \ + "-----BEGIN EC PRIVATE KEY-----\r\n" \ + "MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" \ + "AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" \ + "wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" \ + "-----END EC PRIVATE KEY-----\r\n" +/* END FILE */ + +/* This is generated from tests/data_files/cli2.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_KEY_EC_DER tests/data_files/cli2.key.der */ +#define TEST_CLI_KEY_EC_DER { \ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6, 0xf7, 0x86, 0x64, 0xf1, \ + 0x67, 0x7f, 0xe6, 0x64, 0x8d, 0xef, 0xca, 0x4e, 0xe9, 0xdd, 0x4d, 0xf0, \ + 0x05, 0xff, 0x96, 0x22, 0x8a, 0x7a, 0x84, 0x38, 0x64, 0x17, 0x32, 0x61, \ + 0x98, 0xb7, 0x2a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \ + 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, \ + 0xb1, 0x73, 0xdf, 0xd3, 0xac, 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, \ + 0xee, 0xe6, 0x53, 0xac, 0xce, 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, \ + 0xe3, 0x63, 0x25, 0x0b, 0xdf, 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, \ + 0xc0, 0xd5, 0x18, 0x14, 0x70, 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, \ + 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, \ + 0xc7 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli-rsa-sha256.crt. */ +/* BEGIN FILE string macro TEST_CLI_CRT_RSA_PEM tests/data_files/cli-rsa-sha256.crt */ +#define TEST_CLI_CRT_RSA_PEM \ + "-----BEGIN CERTIFICATE-----\r\n" \ + "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ + "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ + "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" \ + "A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" \ + "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" \ + "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" \ + "1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" \ + "MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" \ + "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" \ + "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" \ + "o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n" \ + "BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n" \ + "AQEAXidv1d4pLlBiKWED95rMycBdgDcgyNqJxakFkRfRyA2y1mlyTn7uBXRkNLY5\r\n" \ + "ZFzK82GCjk2Q2OD4RZSCPAJJqLpHHU34t71ciffvy2KK81YvrxczRhMAE64i+qna\r\n" \ + "yP3Td2XuWJR05PVPoSemsNELs9gWttdnYy3ce+EY2Y0n7Rsi7982EeLIAA7H6ca4\r\n" \ + "2Es/NUH//JZJT32OP0doMxeDRA+vplkKqTLLWf7dX26LIriBkBaRCgR5Yv9LBPFc\r\n" \ + "NOtpzu/LbrY7QFXKJMI+JXDudCsOn8KCmiA4d6Emisqfh3V3485l7HEQNcvLTxlD\r\n" \ + "6zDQyi0/ykYUYZkwQTK1N2Nvlw==\r\n" \ + "-----END CERTIFICATE-----\r\n" +/* END FILE */ + +/* This was generated from tests/data_files/cli-rsa-sha256.crt.der + using `xxd -i.` */ +/* BEGIN FILE binary macro TEST_CLI_CRT_RSA_DER tests/data_files/cli-rsa-sha256.crt.der */ +#define TEST_CLI_CRT_RSA_DER { \ + 0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01, \ + 0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \ + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \ + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \ + 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \ + 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \ + 0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \ + 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \ + 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \ + 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \ + 0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \ + 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \ + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \ + 0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \ + 0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c, \ + 0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, \ + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, \ + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, \ + 0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, \ + 0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, \ + 0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, \ + 0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, \ + 0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, \ + 0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, \ + 0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, \ + 0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, \ + 0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, \ + 0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, \ + 0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, \ + 0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, \ + 0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, \ + 0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, \ + 0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, \ + 0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, \ + 0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, \ + 0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, \ + 0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, \ + 0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, \ + 0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, \ + 0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, \ + 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, \ + 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \ + 0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e, \ + 0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f, \ + 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, \ + 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95, \ + 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, \ + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, \ + 0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62, \ + 0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20, \ + 0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2, \ + 0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39, \ + 0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8, \ + 0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8, \ + 0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f, \ + 0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda, \ + 0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f, \ + 0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67, \ + 0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22, \ + 0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8, \ + 0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e, \ + 0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a, \ + 0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81, \ + 0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c, \ + 0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca, \ + 0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82, \ + 0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77, \ + 0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43, \ + 0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30, \ + 0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97 \ +} +/* END FILE */ + +/* This is taken from tests/data_files/cli-rsa.key. */ +/* BEGIN FILE string macro TEST_CLI_KEY_RSA_PEM tests/data_files/cli-rsa.key */ +#define TEST_CLI_KEY_RSA_PEM \ + "-----BEGIN RSA PRIVATE KEY-----\r\n" \ + "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" \ + "B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" \ + "bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" \ + "Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" \ + "7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" \ + "dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" \ + "yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" \ + "4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" \ + "ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" \ + "zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" \ + "l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" \ + "DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" \ + "VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" \ + "Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" \ + "wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" \ + "c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" \ + "33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" \ + "ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" \ + "BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" \ + "KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" \ + "UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" \ + "7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" \ + "gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" \ + "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" \ + "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" \ + "-----END RSA PRIVATE KEY-----\r\n"/* END FILE */ + +/* This was generated from tests/data_files/cli-rsa.key.der using `xxd -i`. */ +/* BEGIN FILE binary macro TEST_CLI_KEY_RSA_DER tests/data_files/cli-rsa.key.der */ +#define TEST_CLI_KEY_RSA_DER { \ + 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \ + 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, 0x45, 0xd9, 0x14, \ + 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, 0x33, 0xad, 0x0d, \ + 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, 0xcc, 0x66, 0x85, \ + 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, 0x9e, 0x0a, 0x6e, \ + 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, 0x93, 0x86, 0x49, \ + 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, 0xd4, 0x2f, 0x77, \ + 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, 0x48, 0x70, 0xf5, \ + 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, 0xe6, 0x43, 0xea, \ + 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, 0x57, 0x4e, 0xa9, \ + 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, 0x32, 0x30, 0xd5, \ + 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, 0x5f, 0xf9, 0x3d, \ + 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, 0xfb, 0xe5, 0x0c, \ + 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, 0x7f, 0xca, 0xad, \ + 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, 0xe0, 0x9b, 0xf8, \ + 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, 0x04, 0x66, 0xc7, \ + 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, 0x06, 0x67, 0xf4, \ + 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, 0x3c, 0x8b, 0x35, \ + 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, 0xfc, 0x36, 0x6b, \ + 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, 0x00, 0xcf, 0xaf, \ + 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, 0xe7, 0x50, 0x71, \ + 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, 0xe4, 0xc4, 0xfd, \ + 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \ + 0x00, 0x67, 0x4d, 0xb5, 0xf6, 0x03, 0x89, 0xaa, 0x7a, 0x6f, 0x3b, 0x2d, \ + 0xca, 0x10, 0xa2, 0x23, 0xc9, 0xbd, 0x4e, 0xda, 0xe1, 0x67, 0x0e, 0x0c, \ + 0x8a, 0xc6, 0x84, 0x68, 0xdf, 0xe5, 0x97, 0x75, 0xd2, 0x8d, 0xa3, 0x86, \ + 0xd9, 0xdb, 0xd5, 0xeb, 0x13, 0x19, 0x08, 0xc5, 0x7e, 0xe5, 0x37, 0x97, \ + 0x0c, 0x73, 0x80, 0x66, 0x76, 0x35, 0xf1, 0x88, 0xb5, 0xf2, 0xfc, 0xf3, \ + 0xe1, 0x4b, 0x76, 0x4e, 0x73, 0x45, 0xce, 0x2c, 0xc2, 0x10, 0x26, 0x0d, \ + 0x68, 0x0d, 0x9f, 0x49, 0x3d, 0xd6, 0x80, 0x89, 0xe7, 0xc5, 0x49, 0x15, \ + 0xdd, 0x85, 0xc0, 0xc8, 0xfe, 0x82, 0x37, 0x12, 0x5a, 0x0a, 0x6b, 0xf6, \ + 0x68, 0x0d, 0x32, 0x16, 0xbd, 0xa4, 0x15, 0x54, 0x9e, 0x68, 0xa1, 0xad, \ + 0xca, 0x6b, 0xe5, 0x8c, 0xda, 0x76, 0x35, 0x59, 0x2f, 0x9b, 0xb4, 0xe1, \ + 0xf1, 0xf0, 0x50, 0x04, 0xee, 0xc8, 0xec, 0x05, 0xe1, 0xcf, 0x8d, 0xe4, \ + 0xd2, 0x64, 0x7b, 0x5e, 0x63, 0xe0, 0x7b, 0x07, 0xbc, 0x02, 0x96, 0x4e, \ + 0x1b, 0x78, 0x6c, 0xb6, 0x43, 0x9a, 0x32, 0xf6, 0xd6, 0x02, 0xf5, 0x80, \ + 0xcc, 0x26, 0x6e, 0xa5, 0xd0, 0xe3, 0x65, 0x88, 0xce, 0x26, 0xa9, 0x40, \ + 0xe1, 0xe1, 0x00, 0xe0, 0x7f, 0x3f, 0xc3, 0xb1, 0x7c, 0xde, 0xbe, 0x42, \ + 0xba, 0x07, 0x81, 0x13, 0xc2, 0xe0, 0x11, 0x11, 0x23, 0x2c, 0xf8, 0xb2, \ + 0x7a, 0x3a, 0xd4, 0xe4, 0x7d, 0x5f, 0xb9, 0xb1, 0x18, 0xfa, 0x1d, 0x1d, \ + 0x97, 0x91, 0xd9, 0x04, 0x9e, 0xbc, 0xc9, 0xb4, 0xd7, 0x7d, 0x0e, 0x54, \ + 0xf6, 0x8f, 0xd0, 0x28, 0x0d, 0xdd, 0x77, 0x4b, 0x68, 0x04, 0x48, 0x61, \ + 0x75, 0x15, 0x03, 0x1b, 0x35, 0xad, 0x8e, 0xfc, 0x24, 0x11, 0x07, 0xea, \ + 0x17, 0x5a, 0xde, 0x19, 0x68, 0xff, 0xb6, 0x87, 0x7f, 0x80, 0x2a, 0x5f, \ + 0x0c, 0x58, 0xba, 0x5f, 0x41, 0x02, 0x81, 0x81, 0x00, 0xe3, 0x03, 0xaf, \ + 0xfe, 0x98, 0xd2, 0x0b, 0x7b, 0x72, 0xe9, 0x3b, 0x8e, 0xbc, 0xa5, 0xf6, \ + 0xac, 0xe5, 0x22, 0x06, 0xb2, 0xd7, 0x5e, 0xfd, 0x89, 0x4b, 0x16, 0x67, \ + 0x32, 0x83, 0x22, 0x58, 0x8e, 0x62, 0xa4, 0xb4, 0x2d, 0xf9, 0x16, 0x13, \ + 0x54, 0xf6, 0x9f, 0x2f, 0xf9, 0xbb, 0x0e, 0x7e, 0x8c, 0x6f, 0x08, 0xda, \ + 0xc8, 0xe9, 0x1c, 0x66, 0x10, 0x70, 0x93, 0x90, 0x8d, 0xcf, 0x90, 0x3a, \ + 0x43, 0x89, 0x49, 0xeb, 0x83, 0x2a, 0xfe, 0x5a, 0x87, 0xce, 0x74, 0x42, \ + 0x41, 0x0d, 0x8c, 0x73, 0x51, 0xbc, 0x7b, 0x20, 0xc5, 0xfd, 0xf6, 0x0b, \ + 0x65, 0xed, 0xa9, 0x2e, 0xfc, 0x0f, 0xf5, 0x50, 0xf9, 0x8d, 0x37, 0x36, \ + 0x9a, 0x20, 0xdf, 0xc3, 0xe3, 0x27, 0xbc, 0x98, 0x72, 0xc1, 0x14, 0x4b, \ + 0x71, 0xe9, 0x83, 0x14, 0xff, 0x24, 0xe2, 0x14, 0x15, 0xb6, 0x6f, 0x0f, \ + 0x32, 0x9d, 0xd9, 0x98, 0xd1, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x0c, 0xfb, \ + 0xc3, 0x33, 0x9b, 0x47, 0x88, 0x27, 0xf2, 0x26, 0xde, 0xeb, 0x5e, 0xee, \ + 0x40, 0xf6, 0x63, 0x5b, 0x35, 0x23, 0xf5, 0xd5, 0x07, 0x61, 0xdf, 0xa2, \ + 0x9f, 0x58, 0x30, 0x04, 0x22, 0x2b, 0xb4, 0xd9, 0xda, 0x46, 0x7f, 0x48, \ + 0xf5, 0x4f, 0xd0, 0xea, 0xd7, 0xa0, 0x45, 0x8a, 0x62, 0x8b, 0x8c, 0xac, \ + 0x73, 0x5e, 0xfa, 0x36, 0x65, 0x3e, 0xba, 0x6c, 0xba, 0x5e, 0x6b, 0x92, \ + 0x29, 0x5e, 0x6a, 0x0f, 0xd6, 0xd2, 0xa5, 0x95, 0x86, 0xda, 0x72, 0xc5, \ + 0x9e, 0xc9, 0x6b, 0x37, 0x5e, 0x4b, 0x9b, 0x77, 0xe1, 0x67, 0x1a, 0x1e, \ + 0x30, 0xd8, 0x41, 0x68, 0x40, 0xd3, 0x9c, 0xb4, 0xf6, 0xeb, 0x2a, 0x22, \ + 0xdf, 0x78, 0x29, 0xd2, 0x64, 0x92, 0x5b, 0x2f, 0x78, 0x64, 0x4a, 0xa2, \ + 0xa6, 0x6b, 0x3e, 0x50, 0xb1, 0x7a, 0xb1, 0x8d, 0x59, 0xb4, 0x55, 0xba, \ + 0xb6, 0x91, 0x85, 0xa3, 0x2f, 0x02, 0x81, 0x80, 0x10, 0x1e, 0x19, 0xe7, \ + 0xbc, 0x97, 0xe5, 0x22, 0xcd, 0xa4, 0xcb, 0x8a, 0xb5, 0xd0, 0x1e, 0xb4, \ + 0x65, 0xcc, 0x45, 0xa7, 0x7a, 0xed, 0x0e, 0x99, 0x29, 0xd0, 0x9c, 0x61, \ + 0x14, 0xb8, 0x62, 0x8b, 0x31, 0x6b, 0xba, 0x33, 0x2d, 0x65, 0x28, 0xd8, \ + 0x36, 0x6e, 0x54, 0xec, 0xa9, 0x20, 0x3d, 0x51, 0xe1, 0x2c, 0x42, 0xc4, \ + 0x52, 0xf0, 0xa6, 0x3a, 0x72, 0x93, 0xb7, 0x86, 0xa9, 0xfe, 0xf6, 0x74, \ + 0x07, 0x12, 0x4d, 0x7b, 0x51, 0x99, 0x1f, 0x7a, 0x56, 0xe9, 0x20, 0x2f, \ + 0x18, 0x34, 0x29, 0x97, 0xdb, 0x06, 0xee, 0xeb, 0xbf, 0xbd, 0x31, 0x4f, \ + 0xfa, 0x50, 0xb1, 0xba, 0x49, 0xb3, 0xc4, 0x1d, 0x03, 0xae, 0xb0, 0xdc, \ + 0xbe, 0x8a, 0xc4, 0x90, 0xa3, 0x28, 0x9b, 0xb6, 0x42, 0x09, 0x1b, 0xd6, \ + 0x29, 0x9b, 0x19, 0xe9, 0x87, 0x87, 0xd9, 0x9f, 0x35, 0x05, 0xab, 0x91, \ + 0x8f, 0x6d, 0x7c, 0x91, 0x02, 0x81, 0x81, 0x00, 0x94, 0x57, 0xf0, 0xe0, \ + 0x28, 0xfd, 0xbd, 0xf3, 0x9c, 0x43, 0x4d, 0x3e, 0xfd, 0x37, 0x4f, 0x23, \ + 0x52, 0x8d, 0xe1, 0x4c, 0xfe, 0x4c, 0x55, 0x80, 0x82, 0xba, 0x3f, 0xfe, \ + 0x51, 0xe1, 0x30, 0xd5, 0x3b, 0xd9, 0x73, 0x1d, 0xcb, 0x25, 0xbc, 0xbb, \ + 0x3f, 0xa5, 0xda, 0x77, 0xa6, 0xb5, 0xfc, 0x1a, 0xaf, 0x79, 0xa1, 0xb2, \ + 0x14, 0xa2, 0x1f, 0x10, 0x52, 0x1a, 0x05, 0x40, 0x48, 0xb6, 0x4f, 0x34, \ + 0xd6, 0xc0, 0xc3, 0xa4, 0x36, 0x98, 0x73, 0x88, 0x0b, 0xd3, 0x45, 0xdc, \ + 0xee, 0x51, 0x6e, 0x04, 0x73, 0x99, 0x93, 0x12, 0x58, 0x96, 0xcb, 0x39, \ + 0x42, 0xb1, 0xa9, 0xb8, 0xe1, 0x25, 0xf5, 0x9c, 0x14, 0xb7, 0x92, 0x2b, \ + 0x14, 0xb0, 0x5d, 0x61, 0xa2, 0xaa, 0x34, 0x7c, 0xcd, 0x54, 0x2d, 0x69, \ + 0x08, 0xf7, 0xdb, 0xfc, 0x9c, 0x87, 0xe8, 0x3a, 0xf6, 0x1d, 0x4c, 0x6a, \ + 0x83, 0x15, 0x30, 0x01, 0x02, 0x81, 0x81, 0x00, 0x9c, 0x53, 0xa1, 0xb6, \ + 0x2f, 0xc0, 0x06, 0xf5, 0xdf, 0x5c, 0xd1, 0x4a, 0x4e, 0xc8, 0xbd, 0x6d, \ + 0x32, 0xf1, 0x5e, 0xe5, 0x3b, 0x70, 0xd0, 0xa8, 0xe5, 0x41, 0x57, 0x6c, \ + 0x87, 0x53, 0x0f, 0xeb, 0x28, 0xa0, 0x62, 0x8f, 0x43, 0x62, 0xec, 0x2e, \ + 0x6c, 0x71, 0x55, 0x5b, 0x6a, 0xf4, 0x74, 0x14, 0xea, 0x7a, 0x03, 0xf6, \ + 0xfc, 0xa4, 0xce, 0xc4, 0xac, 0xda, 0x1d, 0xf0, 0xb5, 0xa9, 0xfd, 0x11, \ + 0x18, 0x3b, 0x14, 0xa0, 0x90, 0x8d, 0x26, 0xb7, 0x75, 0x73, 0x0a, 0x02, \ + 0x2c, 0x6f, 0x0f, 0xd8, 0x41, 0x78, 0xc3, 0x73, 0x81, 0xac, 0xaa, 0xaf, \ + 0xf2, 0xee, 0x32, 0xb5, 0x8d, 0x05, 0xf9, 0x59, 0x5a, 0x9e, 0x3e, 0x65, \ + 0x9b, 0x74, 0xda, 0xa0, 0x74, 0x95, 0x17, 0x5f, 0x8d, 0x58, 0xfc, 0x8e, \ + 0x4e, 0x2c, 0x1e, 0xbc, 0x81, 0x02, 0x18, 0xac, 0x12, 0xc6, 0xf9, 0x64, \ + 0x8b, 0x87, 0xc3, 0x00 \ +} +/* END FILE */ + +/* + * + * Test certificates and keys as C variables + * + */ + +/* + * CA + */ + +const char mbedtls_test_ca_crt_ec_pem[] = TEST_CA_CRT_EC_PEM; +const char mbedtls_test_ca_key_ec_pem[] = TEST_CA_KEY_EC_PEM; +const char mbedtls_test_ca_pwd_ec_pem[] = TEST_CA_PWD_EC_PEM; +const char mbedtls_test_ca_key_rsa_pem[] = TEST_CA_KEY_RSA_PEM; +const char mbedtls_test_ca_pwd_rsa_pem[] = TEST_CA_PWD_RSA_PEM; +const char mbedtls_test_ca_crt_rsa_sha1_pem[] = TEST_CA_CRT_RSA_SHA1_PEM; +const char mbedtls_test_ca_crt_rsa_sha256_pem[] = TEST_CA_CRT_RSA_SHA256_PEM; + +const unsigned char mbedtls_test_ca_crt_ec_der[] = TEST_CA_CRT_EC_DER; +const unsigned char mbedtls_test_ca_key_ec_der[] = TEST_CA_KEY_EC_DER; +const unsigned char mbedtls_test_ca_key_rsa_der[] = TEST_CA_KEY_RSA_DER; +const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[] = + TEST_CA_CRT_RSA_SHA1_DER; +const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[] = + TEST_CA_CRT_RSA_SHA256_DER; + +const size_t mbedtls_test_ca_crt_ec_pem_len = + sizeof( mbedtls_test_ca_crt_ec_pem ); +const size_t mbedtls_test_ca_key_ec_pem_len = + sizeof( mbedtls_test_ca_key_ec_pem ); +const size_t mbedtls_test_ca_pwd_ec_pem_len = + sizeof( mbedtls_test_ca_pwd_ec_pem ) - 1; +const size_t mbedtls_test_ca_key_rsa_pem_len = + sizeof( mbedtls_test_ca_key_rsa_pem ); +const size_t mbedtls_test_ca_pwd_rsa_pem_len = + sizeof( mbedtls_test_ca_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1_pem ); +const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256_pem ); + +const size_t mbedtls_test_ca_crt_ec_der_len = + sizeof( mbedtls_test_ca_crt_ec_der ); +const size_t mbedtls_test_ca_key_ec_der_len = + sizeof( mbedtls_test_ca_key_ec_der ); +const size_t mbedtls_test_ca_pwd_ec_der_len = 0; +const size_t mbedtls_test_ca_key_rsa_der_len = + sizeof( mbedtls_test_ca_key_rsa_der ); +const size_t mbedtls_test_ca_pwd_rsa_der_len = 0; +const size_t mbedtls_test_ca_crt_rsa_sha1_der_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1_der ); +const size_t mbedtls_test_ca_crt_rsa_sha256_der_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256_der ); + +/* + * Server + */ + +const char mbedtls_test_srv_crt_ec_pem[] = TEST_SRV_CRT_EC_PEM; +const char mbedtls_test_srv_key_ec_pem[] = TEST_SRV_KEY_EC_PEM; +const char mbedtls_test_srv_pwd_ec_pem[] = ""; +const char mbedtls_test_srv_key_rsa_pem[] = TEST_SRV_KEY_RSA_PEM; +const char mbedtls_test_srv_pwd_rsa_pem[] = ""; +const char mbedtls_test_srv_crt_rsa_sha1_pem[] = TEST_SRV_CRT_RSA_SHA1_PEM; +const char mbedtls_test_srv_crt_rsa_sha256_pem[] = TEST_SRV_CRT_RSA_SHA256_PEM; + +const unsigned char mbedtls_test_srv_crt_ec_der[] = TEST_SRV_CRT_EC_DER; +const unsigned char mbedtls_test_srv_key_ec_der[] = TEST_SRV_KEY_EC_DER; +const unsigned char mbedtls_test_srv_key_rsa_der[] = TEST_SRV_KEY_RSA_DER; +const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[] = + TEST_SRV_CRT_RSA_SHA1_DER; +const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[] = + TEST_SRV_CRT_RSA_SHA256_DER; + +const size_t mbedtls_test_srv_crt_ec_pem_len = + sizeof( mbedtls_test_srv_crt_ec_pem ); +const size_t mbedtls_test_srv_key_ec_pem_len = + sizeof( mbedtls_test_srv_key_ec_pem ); +const size_t mbedtls_test_srv_pwd_ec_pem_len = + sizeof( mbedtls_test_srv_pwd_ec_pem ) - 1; +const size_t mbedtls_test_srv_key_rsa_pem_len = + sizeof( mbedtls_test_srv_key_rsa_pem ); +const size_t mbedtls_test_srv_pwd_rsa_pem_len = + sizeof( mbedtls_test_srv_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1_pem ); +const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256_pem ); + +const size_t mbedtls_test_srv_crt_ec_der_len = + sizeof( mbedtls_test_srv_crt_ec_der ); +const size_t mbedtls_test_srv_key_ec_der_len = + sizeof( mbedtls_test_srv_key_ec_der ); +const size_t mbedtls_test_srv_pwd_ec_der_len = 0; +const size_t mbedtls_test_srv_key_rsa_der_len = + sizeof( mbedtls_test_srv_key_rsa_der ); +const size_t mbedtls_test_srv_pwd_rsa_der_len = 0; +const size_t mbedtls_test_srv_crt_rsa_sha1_der_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1_der ); +const size_t mbedtls_test_srv_crt_rsa_sha256_der_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256_der ); + +/* + * Client + */ + +const char mbedtls_test_cli_crt_ec_pem[] = TEST_CLI_CRT_EC_PEM; +const char mbedtls_test_cli_key_ec_pem[] = TEST_CLI_KEY_EC_PEM; +const char mbedtls_test_cli_pwd_ec_pem[] = ""; +const char mbedtls_test_cli_key_rsa_pem[] = TEST_CLI_KEY_RSA_PEM; +const char mbedtls_test_cli_pwd_rsa_pem[] = ""; +const char mbedtls_test_cli_crt_rsa_pem[] = TEST_CLI_CRT_RSA_PEM; + +const unsigned char mbedtls_test_cli_crt_ec_der[] = TEST_CLI_CRT_EC_DER; +const unsigned char mbedtls_test_cli_key_ec_der[] = TEST_CLI_KEY_EC_DER; +const unsigned char mbedtls_test_cli_key_rsa_der[] = TEST_CLI_KEY_RSA_DER; +const unsigned char mbedtls_test_cli_crt_rsa_der[] = TEST_CLI_CRT_RSA_DER; + +const size_t mbedtls_test_cli_crt_ec_pem_len = + sizeof( mbedtls_test_cli_crt_ec_pem ); +const size_t mbedtls_test_cli_key_ec_pem_len = + sizeof( mbedtls_test_cli_key_ec_pem ); +const size_t mbedtls_test_cli_pwd_ec_pem_len = + sizeof( mbedtls_test_cli_pwd_ec_pem ) - 1; +const size_t mbedtls_test_cli_key_rsa_pem_len = + sizeof( mbedtls_test_cli_key_rsa_pem ); +const size_t mbedtls_test_cli_pwd_rsa_pem_len = + sizeof( mbedtls_test_cli_pwd_rsa_pem ) - 1; +const size_t mbedtls_test_cli_crt_rsa_pem_len = + sizeof( mbedtls_test_cli_crt_rsa_pem ); + +const size_t mbedtls_test_cli_crt_ec_der_len = + sizeof( mbedtls_test_cli_crt_ec_der ); +const size_t mbedtls_test_cli_key_ec_der_len = + sizeof( mbedtls_test_cli_key_ec_der ); +const size_t mbedtls_test_cli_key_rsa_der_len = + sizeof( mbedtls_test_cli_key_rsa_der ); +const size_t mbedtls_test_cli_crt_rsa_der_len = + sizeof( mbedtls_test_cli_crt_rsa_der ); + +/* + * + * Definitions of test CRTs without specification of all parameters, choosing + * them automatically according to the config. For example, mbedtls_test_ca_crt + * is one of mbedtls_test_ca_crt_{rsa|ec}_{sha1|sha256}_{pem|der}. + * + */ + +/* + * Dispatch between PEM and DER according to config + */ + +#if defined(MBEDTLS_PEM_PARSE_C) + +/* PEM encoded test CA certificates and keys */ + +#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_PEM +#define TEST_CA_PWD_RSA TEST_CA_PWD_RSA_PEM +#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_PEM +#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_PEM +#define TEST_CA_KEY_EC TEST_CA_KEY_EC_PEM +#define TEST_CA_PWD_EC TEST_CA_PWD_EC_PEM +#define TEST_CA_CRT_EC TEST_CA_CRT_EC_PEM + +/* PEM encoded test server certificates and keys */ + +#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_PEM +#define TEST_SRV_PWD_RSA "" +#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_PEM +#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_PEM +#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_PEM +#define TEST_SRV_PWD_EC "" +#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_PEM + +/* PEM encoded test client certificates and keys */ + +#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_PEM +#define TEST_CLI_PWD_RSA "" +#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_PEM +#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_PEM +#define TEST_CLI_PWD_EC "" +#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_PEM + +#else /* MBEDTLS_PEM_PARSE_C */ + +/* DER encoded test CA certificates and keys */ + +#define TEST_CA_KEY_RSA TEST_CA_KEY_RSA_DER +#define TEST_CA_PWD_RSA "" +#define TEST_CA_CRT_RSA_SHA256 TEST_CA_CRT_RSA_SHA256_DER +#define TEST_CA_CRT_RSA_SHA1 TEST_CA_CRT_RSA_SHA1_DER +#define TEST_CA_KEY_EC TEST_CA_KEY_EC_DER +#define TEST_CA_PWD_EC "" +#define TEST_CA_CRT_EC TEST_CA_CRT_EC_DER + +/* DER encoded test server certificates and keys */ + +#define TEST_SRV_KEY_RSA TEST_SRV_KEY_RSA_DER +#define TEST_SRV_PWD_RSA "" +#define TEST_SRV_CRT_RSA_SHA256 TEST_SRV_CRT_RSA_SHA256_DER +#define TEST_SRV_CRT_RSA_SHA1 TEST_SRV_CRT_RSA_SHA1_DER +#define TEST_SRV_KEY_EC TEST_SRV_KEY_EC_DER +#define TEST_SRV_PWD_EC "" +#define TEST_SRV_CRT_EC TEST_SRV_CRT_EC_DER + +/* DER encoded test client certificates and keys */ + +#define TEST_CLI_KEY_RSA TEST_CLI_KEY_RSA_DER +#define TEST_CLI_PWD_RSA "" +#define TEST_CLI_CRT_RSA TEST_CLI_CRT_RSA_DER +#define TEST_CLI_KEY_EC TEST_CLI_KEY_EC_DER +#define TEST_CLI_PWD_EC "" +#define TEST_CLI_CRT_EC TEST_CLI_CRT_EC_DER + +#endif /* MBEDTLS_PEM_PARSE_C */ + +const char mbedtls_test_ca_key_rsa[] = TEST_CA_KEY_RSA; +const char mbedtls_test_ca_pwd_rsa[] = TEST_CA_PWD_RSA; +const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; +const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; +const char mbedtls_test_ca_key_ec[] = TEST_CA_KEY_EC; +const char mbedtls_test_ca_pwd_ec[] = TEST_CA_PWD_EC; +const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; + +const char mbedtls_test_srv_key_rsa[] = TEST_SRV_KEY_RSA; +const char mbedtls_test_srv_pwd_rsa[] = TEST_SRV_PWD_RSA; +const char mbedtls_test_srv_crt_rsa_sha256[] = TEST_SRV_CRT_RSA_SHA256; +const char mbedtls_test_srv_crt_rsa_sha1[] = TEST_SRV_CRT_RSA_SHA1; +const char mbedtls_test_srv_key_ec[] = TEST_SRV_KEY_EC; +const char mbedtls_test_srv_pwd_ec[] = TEST_SRV_PWD_EC; +const char mbedtls_test_srv_crt_ec[] = TEST_SRV_CRT_EC; + +const char mbedtls_test_cli_key_rsa[] = TEST_CLI_KEY_RSA; +const char mbedtls_test_cli_pwd_rsa[] = TEST_CLI_PWD_RSA; +const char mbedtls_test_cli_crt_rsa[] = TEST_CLI_CRT_RSA; +const char mbedtls_test_cli_key_ec[] = TEST_CLI_KEY_EC; +const char mbedtls_test_cli_pwd_ec[] = TEST_CLI_PWD_EC; +const char mbedtls_test_cli_crt_ec[] = TEST_CLI_CRT_EC; + +const size_t mbedtls_test_ca_key_rsa_len = + sizeof( mbedtls_test_ca_key_rsa ); +const size_t mbedtls_test_ca_pwd_rsa_len = + sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +const size_t mbedtls_test_ca_crt_rsa_sha256_len = + sizeof( mbedtls_test_ca_crt_rsa_sha256 ); +const size_t mbedtls_test_ca_crt_rsa_sha1_len = + sizeof( mbedtls_test_ca_crt_rsa_sha1 ); +const size_t mbedtls_test_ca_key_ec_len = + sizeof( mbedtls_test_ca_key_ec ); +const size_t mbedtls_test_ca_pwd_ec_len = + sizeof( mbedtls_test_ca_pwd_ec ) - 1; +const size_t mbedtls_test_ca_crt_ec_len = + sizeof( mbedtls_test_ca_crt_ec ); + +const size_t mbedtls_test_srv_key_rsa_len = + sizeof( mbedtls_test_srv_key_rsa ); +const size_t mbedtls_test_srv_pwd_rsa_len = + sizeof( mbedtls_test_srv_pwd_rsa ) -1; +const size_t mbedtls_test_srv_crt_rsa_sha256_len = + sizeof( mbedtls_test_srv_crt_rsa_sha256 ); +const size_t mbedtls_test_srv_crt_rsa_sha1_len = + sizeof( mbedtls_test_srv_crt_rsa_sha1 ); +const size_t mbedtls_test_srv_key_ec_len = + sizeof( mbedtls_test_srv_key_ec ); +const size_t mbedtls_test_srv_pwd_ec_len = + sizeof( mbedtls_test_srv_pwd_ec ) - 1; +const size_t mbedtls_test_srv_crt_ec_len = + sizeof( mbedtls_test_srv_crt_ec ); + +const size_t mbedtls_test_cli_key_rsa_len = + sizeof( mbedtls_test_cli_key_rsa ); +const size_t mbedtls_test_cli_pwd_rsa_len = + sizeof( mbedtls_test_cli_pwd_rsa ) - 1; +const size_t mbedtls_test_cli_crt_rsa_len = + sizeof( mbedtls_test_cli_crt_rsa ); +const size_t mbedtls_test_cli_key_ec_len = + sizeof( mbedtls_test_cli_key_ec ); +const size_t mbedtls_test_cli_pwd_ec_len = + sizeof( mbedtls_test_cli_pwd_ec ) - 1; +const size_t mbedtls_test_cli_crt_ec_len = + sizeof( mbedtls_test_cli_crt_ec ); + +/* + * Dispatch between SHA-1 and SHA-256 + */ + +#if defined(MBEDTLS_SHA256_C) +#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA256 +#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA256 +#else +#define TEST_CA_CRT_RSA TEST_CA_CRT_RSA_SHA1 +#define TEST_SRV_CRT_RSA TEST_SRV_CRT_RSA_SHA1 +#endif /* MBEDTLS_SHA256_C */ + +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA; +const char mbedtls_test_srv_crt_rsa[] = TEST_SRV_CRT_RSA; + +const size_t mbedtls_test_ca_crt_rsa_len = + sizeof( mbedtls_test_ca_crt_rsa ); +const size_t mbedtls_test_srv_crt_rsa_len = + sizeof( mbedtls_test_srv_crt_rsa ); + +/* + * Dispatch between RSA and EC + */ + +#if defined(MBEDTLS_RSA_C) + +#define TEST_CA_KEY TEST_CA_KEY_RSA +#define TEST_CA_PWD TEST_CA_PWD_RSA +#define TEST_CA_CRT TEST_CA_CRT_RSA + +#define TEST_SRV_KEY TEST_SRV_KEY_RSA +#define TEST_SRV_PWD TEST_SRV_PWD_RSA +#define TEST_SRV_CRT TEST_SRV_CRT_RSA + +#define TEST_CLI_KEY TEST_CLI_KEY_RSA +#define TEST_CLI_PWD TEST_CLI_PWD_RSA +#define TEST_CLI_CRT TEST_CLI_CRT_RSA + +#else /* no RSA, so assume ECDSA */ + +#define TEST_CA_KEY TEST_CA_KEY_EC +#define TEST_CA_PWD TEST_CA_PWD_EC +#define TEST_CA_CRT TEST_CA_CRT_EC + +#define TEST_SRV_KEY TEST_SRV_KEY_EC +#define TEST_SRV_PWD TEST_SRV_PWD_EC +#define TEST_SRV_CRT TEST_SRV_CRT_EC + +#define TEST_CLI_KEY TEST_CLI_KEY_EC +#define TEST_CLI_PWD TEST_CLI_PWD_EC +#define TEST_CLI_CRT TEST_CLI_CRT_EC +#endif /* MBEDTLS_RSA_C */ + +/* API stability forces us to declare + * mbedtls_test_{ca|srv|cli}_{key|pwd|crt} + * as pointers. */ +static const char test_ca_key[] = TEST_CA_KEY; +static const char test_ca_pwd[] = TEST_CA_PWD; +static const char test_ca_crt[] = TEST_CA_CRT; + +static const char test_srv_key[] = TEST_SRV_KEY; +static const char test_srv_pwd[] = TEST_SRV_PWD; +static const char test_srv_crt[] = TEST_SRV_CRT; + +static const char test_cli_key[] = TEST_CLI_KEY; +static const char test_cli_pwd[] = TEST_CLI_PWD; +static const char test_cli_crt[] = TEST_CLI_CRT; + +const char *mbedtls_test_ca_key = test_ca_key; +const char *mbedtls_test_ca_pwd = test_ca_pwd; +const char *mbedtls_test_ca_crt = test_ca_crt; + +const char *mbedtls_test_srv_key = test_srv_key; +const char *mbedtls_test_srv_pwd = test_srv_pwd; +const char *mbedtls_test_srv_crt = test_srv_crt; + +const char *mbedtls_test_cli_key = test_cli_key; +const char *mbedtls_test_cli_pwd = test_cli_pwd; +const char *mbedtls_test_cli_crt = test_cli_crt; + +const size_t mbedtls_test_ca_key_len = + sizeof( test_ca_key ); +const size_t mbedtls_test_ca_pwd_len = + sizeof( test_ca_pwd ) - 1; +const size_t mbedtls_test_ca_crt_len = + sizeof( test_ca_crt ); + +const size_t mbedtls_test_srv_key_len = + sizeof( test_srv_key ); +const size_t mbedtls_test_srv_pwd_len = + sizeof( test_srv_pwd ) - 1; +const size_t mbedtls_test_srv_crt_len = + sizeof( test_srv_crt ); + +const size_t mbedtls_test_cli_key_len = + sizeof( test_cli_key ); +const size_t mbedtls_test_cli_pwd_len = + sizeof( test_cli_pwd ) - 1; +const size_t mbedtls_test_cli_crt_len = + sizeof( test_cli_crt ); + +/* + * + * Lists of certificates + * + */ + +/* List of CAs in PEM or DER, depending on config */ +const char * mbedtls_test_cas[] = { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) + mbedtls_test_ca_crt_rsa_sha1, +#endif +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) + mbedtls_test_ca_crt_rsa_sha256, +#endif +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec, +#endif + NULL +}; +const size_t mbedtls_test_cas_len[] = { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA1_C) + sizeof( mbedtls_test_ca_crt_rsa_sha1 ), +#endif +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) + sizeof( mbedtls_test_ca_crt_rsa_sha256 ), +#endif +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec ), +#endif + 0 +}; + +/* List of all available CA certificates in DER format */ +const unsigned char * mbedtls_test_cas_der[] = { +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + mbedtls_test_ca_crt_rsa_sha256_der, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + mbedtls_test_ca_crt_rsa_sha1_der, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec_der, +#endif /* MBEDTLS_ECDSA_C */ + NULL +}; + +const size_t mbedtls_test_cas_der_len[] = { +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + sizeof( mbedtls_test_ca_crt_rsa_sha256_der ), +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + sizeof( mbedtls_test_ca_crt_rsa_sha1_der ), +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec_der ), +#endif /* MBEDTLS_ECDSA_C */ + 0 +}; + +/* Concatenation of all available CA certificates in PEM format */ +#if defined(MBEDTLS_PEM_PARSE_C) +const char mbedtls_test_cas_pem[] = +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_SHA256_C) + TEST_CA_CRT_RSA_SHA256_PEM +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA1_C) + TEST_CA_CRT_RSA_SHA1_PEM +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + TEST_CA_CRT_EC_PEM +#endif /* MBEDTLS_ECDSA_C */ + ""; +const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#endif /* MBEDTLS_CERTS_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c new file mode 100644 index 0000000..658f046 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/chacha20.c @@ -0,0 +1,558 @@ +/** + * \file chacha20.c + * + * \brief ChaCha20 cipher. + * + * \author Daniel King + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_CHACHA20_C) + +#include "mbedtls/chacha20.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHA20_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define CHACHA20_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) +#define CHACHA20_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define ROTL32( value, amount ) \ + ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) ) + +#define CHACHA20_CTR_INDEX ( 12U ) + +#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) + +/** + * \brief ChaCha20 quarter round operation. + * + * The quarter round is defined as follows (from RFC 7539): + * 1. a += b; d ^= a; d <<<= 16; + * 2. c += d; b ^= c; b <<<= 12; + * 3. a += b; d ^= a; d <<<= 8; + * 4. c += d; b ^= c; b <<<= 7; + * + * \param state ChaCha20 state to modify. + * \param a The index of 'a' in the state. + * \param b The index of 'b' in the state. + * \param c The index of 'c' in the state. + * \param d The index of 'd' in the state. + */ +static inline void chacha20_quarter_round( uint32_t state[16], + size_t a, + size_t b, + size_t c, + size_t d ) +{ + /* a += b; d ^= a; d <<<= 16; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 16 ); + + /* c += d; b ^= c; b <<<= 12 */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 12 ); + + /* a += b; d ^= a; d <<<= 8; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 8 ); + + /* c += d; b ^= c; b <<<= 7; */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 7 ); +} + +/** + * \brief Perform the ChaCha20 inner block operation. + * + * This function performs two rounds: the column round and the + * diagonal round. + * + * \param state The ChaCha20 state to update. + */ +static void chacha20_inner_block( uint32_t state[16] ) +{ + chacha20_quarter_round( state, 0, 4, 8, 12 ); + chacha20_quarter_round( state, 1, 5, 9, 13 ); + chacha20_quarter_round( state, 2, 6, 10, 14 ); + chacha20_quarter_round( state, 3, 7, 11, 15 ); + + chacha20_quarter_round( state, 0, 5, 10, 15 ); + chacha20_quarter_round( state, 1, 6, 11, 12 ); + chacha20_quarter_round( state, 2, 7, 8, 13 ); + chacha20_quarter_round( state, 3, 4, 9, 14 ); +} + +/** + * \brief Generates a keystream block. + * + * \param initial_state The initial ChaCha20 state (key, nonce, counter). + * \param keystream Generated keystream bytes are written to this buffer. + */ +static void chacha20_block( const uint32_t initial_state[16], + unsigned char keystream[64] ) +{ + uint32_t working_state[16]; + size_t i; + + memcpy( working_state, + initial_state, + CHACHA20_BLOCK_SIZE_BYTES ); + + for( i = 0U; i < 10U; i++ ) + chacha20_inner_block( working_state ); + + working_state[ 0] += initial_state[ 0]; + working_state[ 1] += initial_state[ 1]; + working_state[ 2] += initial_state[ 2]; + working_state[ 3] += initial_state[ 3]; + working_state[ 4] += initial_state[ 4]; + working_state[ 5] += initial_state[ 5]; + working_state[ 6] += initial_state[ 6]; + working_state[ 7] += initial_state[ 7]; + working_state[ 8] += initial_state[ 8]; + working_state[ 9] += initial_state[ 9]; + working_state[10] += initial_state[10]; + working_state[11] += initial_state[11]; + working_state[12] += initial_state[12]; + working_state[13] += initial_state[13]; + working_state[14] += initial_state[14]; + working_state[15] += initial_state[15]; + + for( i = 0U; i < 16; i++ ) + { + size_t offset = i * 4U; + + MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset); + } + + mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); +} + +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) +{ + CHACHA20_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; +} + +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); + } +} + +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( key != NULL ); + + /* ChaCha20 constants - the string "expand 32-byte k" */ + ctx->state[0] = 0x61707865; + ctx->state[1] = 0x3320646e; + ctx->state[2] = 0x79622d32; + ctx->state[3] = 0x6b206574; + + /* Set key */ + ctx->state[4] = MBEDTLS_GET_UINT32_LE( key, 0 ); + ctx->state[5] = MBEDTLS_GET_UINT32_LE( key, 4 ); + ctx->state[6] = MBEDTLS_GET_UINT32_LE( key, 8 ); + ctx->state[7] = MBEDTLS_GET_UINT32_LE( key, 12 ); + ctx->state[8] = MBEDTLS_GET_UINT32_LE( key, 16 ); + ctx->state[9] = MBEDTLS_GET_UINT32_LE( key, 20 ); + ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 ); + ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 ); + + return( 0 ); +} + +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + + /* Counter */ + ctx->state[12] = counter; + + /* Nonce */ + ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 ); + ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 ); + ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 ); + + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + + return( 0 ); +} + +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ) +{ + size_t offset = 0U; + size_t i; + + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || output != NULL ); + + /* Use leftover keystream bytes, if available */ + while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) + { + output[offset] = input[offset] + ^ ctx->keystream8[ctx->keystream_bytes_used]; + + ctx->keystream_bytes_used++; + offset++; + size--; + } + + /* Process full blocks */ + while( size >= CHACHA20_BLOCK_SIZE_BYTES ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < 64U; i += 8U ) + { + output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; + output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; + output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; + output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; + output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; + output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; + output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; + output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; + } + + offset += CHACHA20_BLOCK_SIZE_BYTES; + size -= CHACHA20_BLOCK_SIZE_BYTES; + } + + /* Last (partial) block */ + if( size > 0U ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < size; i++) + { + output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; + } + + ctx->keystream_bytes_used = size; + + } + + return( 0 ); +} + +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t data_len, + const unsigned char* input, + unsigned char* output ) +{ + mbedtls_chacha20_context ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + CHACHA20_VALIDATE_RET( key != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL ); + + mbedtls_chacha20_init( &ctx ); + + ret = mbedtls_chacha20_setkey( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); + +cleanup: + mbedtls_chacha20_free( &ctx ); + return( ret ); +} + +#endif /* !MBEDTLS_CHACHA20_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][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 + }, + { + 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, 0x01 + } +}; + +static const unsigned char test_nonces[2][12] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02 + } +}; + +static const uint32_t test_counters[2] = +{ + 0U, + 1U +}; + +static const unsigned char test_input[2][375] = +{ + { + 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, + 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 + }, + { + 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f + } +}; + +static const unsigned char test_output[2][375] = +{ + { + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, + 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, + 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, + 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, + 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, + 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, + 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 + }, + { + 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, + 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, + 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, + 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, + 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, + 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, + 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, + 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, + 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, + 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, + 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, + 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, + 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, + 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, + 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, + 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, + 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, + 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, + 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, + 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, + 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, + 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, + 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, + 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, + 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, + 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, + 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, + 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, + 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, + 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, + 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, + 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, + 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, + 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, + 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, + 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, + 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, + 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, + 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, + 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, + 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, + 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, + 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, + 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, + 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, + 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, + 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 + } +}; + +static const size_t test_lengths[2] = +{ + 64U, + 375U +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chacha20_self_test( int verbose ) +{ + unsigned char output[381]; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20 test %u ", i ); + + ret = mbedtls_chacha20_crypt( test_keys[i], + test_nonces[i], + test_counters[i], + test_lengths[i], + test_input[i], + output ); + + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), + ( "failed (output)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_CHACHA20_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c new file mode 100644 index 0000000..dc75b20 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/chachapoly.c @@ -0,0 +1,524 @@ +/** + * \file chachapoly.c + * + * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "common.h" + +#if defined(MBEDTLS_CHACHAPOLY_C) + +#include "mbedtls/chachapoly.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +/* Parameter validation macros */ +#define CHACHAPOLY_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define CHACHAPOLY_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define CHACHAPOLY_STATE_INIT ( 0 ) +#define CHACHAPOLY_STATE_AAD ( 1 ) +#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ +#define CHACHAPOLY_STATE_FINISHED ( 3 ) + +/** + * \brief Adds nul bytes to pad the AAD for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +/** + * \brief Adds nul bytes to pad the ciphertext for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) +{ + CHACHAPOLY_VALIDATE( ctx != NULL ); + + mbedtls_chacha20_init( &ctx->chacha20_ctx ); + mbedtls_poly1305_init( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_chacha20_free( &ctx->chacha20_ctx ); + mbedtls_poly1305_free( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( key != NULL ); + + ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); + + return( ret ); +} + +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char poly1305_key[64]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + + /* Set counter = 0, will be update to 1 when generating Poly1305 key */ + ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); + if( ret != 0 ) + goto cleanup; + + /* Generate the Poly1305 key by getting the ChaCha20 keystream output with + * counter = 0. This is the same as encrypting a buffer of zeroes. + * Only the first 256-bits (32 bytes) of the key is used for Poly1305. + * The other 256 bits are discarded. + */ + memset( poly1305_key, 0, sizeof( poly1305_key ) ); + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), + poly1305_key, poly1305_key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); + + if( ret == 0 ) + { + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_AAD; + ctx->mode = mode; + } + +cleanup: + mbedtls_platform_zeroize( poly1305_key, 64U ); + return( ret ); +} + +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + + if( ctx->state != CHACHAPOLY_STATE_AAD ) + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + + ctx->aad_len += aad_len; + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); +} + +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL ); + + if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && + ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; + + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->ciphertext_len += len; + + if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) + { + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); + if( ret != 0 ) + return( ret ); + } + else /* DECRYPT */ + { + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + } + + return( 0 ); +} + +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char len_block[16]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( mac != NULL ); + + if( ctx->state == CHACHAPOLY_STATE_INIT ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) + { + ret = chachapoly_pad_ciphertext( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->state = CHACHAPOLY_STATE_FINISHED; + + /* The lengths of the AAD and ciphertext are processed by + * Poly1305 as the final 128-bit block, encoded as little-endian integers. + */ + MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0); + MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); + + return( ret ); +} + +static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, + mbedtls_chachapoly_mode_t mode, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update( ctx, length, input, output ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_finish( ctx, tag ); + +cleanup: + return( ret ); +} + +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, + length, nonce, aad, aad_len, + input, output, tag ) ); +} + +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + size_t i; + int diff; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = chachapoly_crypt_and_tag( ctx, + MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, + aad, aad_len, input, output, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_CHACHAPOLY_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_key[1][32] = +{ + { + 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 + } +}; + +static const unsigned char test_nonce[1][12] = +{ + { + 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ + } +}; + +static const unsigned char test_aad[1][12] = +{ + { + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7 + } +}; + +static const size_t test_aad_len[1] = +{ + 12U +}; + +static const unsigned char test_input[1][114] = +{ + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + } +}; + +static const unsigned char test_output[1][114] = +{ + { + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 + } +}; + +static const size_t test_input_len[1] = +{ + 114U +}; + +static const unsigned char test_mac[1][16] = +{ + { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 + } +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chachapoly_self_test( int verbose ) +{ + mbedtls_chachapoly_context ctx; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output[200]; + unsigned char mac[16]; + + for( i = 0U; i < 1U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); + + mbedtls_chachapoly_init( &ctx ); + + ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); + ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); + + ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, + test_input_len[i], + test_nonce[i], + test_aad[i], + test_aad_len[i], + test_input[i], + output, + mac ); + + ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), + ( "failure (wrong output)\n" ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), + ( "failure (wrong MAC)\n" ) ); + + mbedtls_chachapoly_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CHACHAPOLY_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h new file mode 100644 index 0000000..d7ad16a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/check_crypto_config.h @@ -0,0 +1,91 @@ +/** + * \file check_crypto_config.h + * + * \brief Consistency checks for PSA configuration options + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * It is recommended to include this file from your crypto_config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H +#define MBEDTLS_CHECK_CRYPTO_CONFIG_H + +#if defined(PSA_WANT_ALG_CCM) && \ + !( defined(PSA_WANT_KEY_TYPE_AES) || \ + defined(PSA_WANT_KEY_TYPE_CAMELLIA) ) +#error "PSA_WANT_ALG_CCM defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_CMAC) && \ + !( defined(PSA_WANT_KEY_TYPE_AES) || \ + defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \ + defined(PSA_WANT_KEY_TYPE_DES) ) +#error "PSA_WANT_ALG_CMAC defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \ + !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_ECDSA) && \ + !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_GCM) && \ + !( defined(PSA_WANT_KEY_TYPE_AES) || \ + defined(PSA_WANT_KEY_TYPE_CAMELLIA) ) +#error "PSA_WANT_ALG_GCM defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \ + !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \ + !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_RSA_OAEP) && \ + !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_RSA_PSS) && \ + !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \ + !defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR defined, but not all prerequisites" +#endif + +#endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c new file mode 100644 index 0000000..31147df --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher.c @@ -0,0 +1,1676 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher.h" +#include "mbedtls/cipher_internal.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/constant_time.h" + +#include +#include + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_NIST_KW_C) +#include "mbedtls/nist_kw.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define CIPHER_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) +#define CIPHER_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( + const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( + const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( + const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + CIPHER_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + if( ctx->cipher_ctx != NULL ) + { + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED ) + { + /* xxx_free() doesn't allow to return failures. */ + (void) psa_destroy_key( cipher_psa->slot ); + } + + mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) ); + mbedtls_free( cipher_psa ); + } + + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); + return; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_platform_zeroize( ctx->cmac_ctx, + sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_clone( mbedtls_cipher_context_t *dst, + const mbedtls_cipher_context_t *src ) +{ + if( dst == NULL || dst->cipher_info == NULL || + src == NULL || src->cipher_info == NULL) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + dst->cipher_info = src->cipher_info; + dst->key_bitlen = src->key_bitlen; + dst->operation = src->operation; +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + dst->add_padding = src->add_padding; + dst->get_padding = src->get_padding; +#endif + memcpy( dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH ); + dst->unprocessed_len = src->unprocessed_len; + memcpy( dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH ); + dst->iv_size = src->iv_size; + if( dst->cipher_info->base->ctx_clone_func ) + dst->cipher_info->base->ctx_clone_func( dst->cipher_ctx, src->cipher_ctx ); + +#if defined(MBEDTLS_CMAC_C) + if( dst->cmac_ctx != NULL && src->cmac_ctx != NULL ) + memcpy( dst->cmac_ctx, src->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); +#endif + return( 0 ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen ) +{ + psa_algorithm_t alg; + mbedtls_cipher_context_psa *cipher_psa; + + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* Check that the underlying cipher mode and cipher type are + * supported by the underlying PSA Crypto implementation. */ + alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen ); + if( alg == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) ); + if( cipher_psa == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + cipher_psa->alg = alg; + ctx->cipher_ctx = cipher_psa; + ctx->cipher_info = cipher_info; + ctx->psa_enabled = 1; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +int mbedtls_cipher_setup_info( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) +{ + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->cipher_info = cipher_info; + return( 0 ); +} + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( key != NULL ); + CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || + operation == MBEDTLS_DECRYPT ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8; + + psa_status_t status; + psa_key_type_t key_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + /* PSA Crypto API only accepts byte-aligned keys. */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* Don't allow keys to be set multiple times. */ + if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + key_type = mbedtls_psa_translate_cipher_type( + ctx->cipher_info->type ); + if( key_type == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + psa_set_key_type( &attributes, key_type ); + + /* Mbed TLS' cipher layer doesn't enforce the mode of operation + * (encrypt vs. decrypt): it is possible to setup a key for encryption + * and use it for AEAD decryption. Until tests relying on this + * are changed, allow any usage in PSA. */ + psa_set_key_usage_flags( &attributes, + /* mbedtls_psa_translate_cipher_operation( operation ); */ + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); + psa_set_key_algorithm( &attributes, cipher_psa->alg ); + + status = psa_import_key( &attributes, key, key_bytelen, + &cipher_psa->slot ); + switch( status ) + { + case PSA_SUCCESS: + break; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + default: + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + } + /* Indicate that we own the key slot and need to + * destroy it in mbedtls_cipher_free(). */ + cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For OFB, CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); + } + + if( MBEDTLS_DECRYPT == operation ) + return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ) +{ + size_t actual_iv_size; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + /* Even though the actual_iv_size is overwritten with a correct value + * of 12 from the cipher info, return an error to indicate that + * the input iv_len is wrong. */ + if( iv_len != 12 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 && + iv_len != 12 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#endif +#endif + + if ( actual_iv_size != 0 ) + { + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + } + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* We don't support resetting PSA-based + * cipher contexts, yet. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int result; + mbedtls_chachapoly_mode_t mode; + + mode = ( ctx->operation == MBEDTLS_ENCRYPT ) + ? MBEDTLS_CHACHAPOLY_ENCRYPT + : MBEDTLS_CHACHAPOLY_DECRYPT; + + result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ctx->iv, + mode ); + if ( result != 0 ) + return( result ); + + return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ) ); + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t block_size; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + if ( 0 == block_size ) + { + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); + } + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + *olen = ilen; + return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) + { + *olen = ilen; + return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ) ); + } +#endif + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && + ilen < block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen < block_size - ctx->unprocessed_len ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + /* Encryption: only cache partial blocks + * Decryption w/ padding: always keep at least one whole block + * Decryption w/o padding: only cache partial blocks + */ + copy_len = ilen % block_size; + if( copy_len == 0 && + ctx->operation == MBEDTLS_DECRYPT && + NULL != ctx->add_padding) + { + copy_len = block_size; + } + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) + { + if( ctx->unprocessed_len > 0 ) { + /* We can only process an entire data unit at a time. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ); + if( ret != 0 ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0x80; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i - 1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad ^= input[i - 1] * ( done != prev_done ); + } + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in mbedtls_cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + *olen = 0; + + if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode || + MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_XTS == ctx->cipher_info->mode || + MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || + ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) + { + return( 0 ); + } + + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( MBEDTLS_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( MBEDTLS_DECRYPT == ctx->operation ) + return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ) ); + + /* Set output size for encryption */ + *olen = mbedtls_cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + + if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto knows about CBC padding + * schemes, we currently don't make them + * accessible through the cipher layer. */ + if( mode != MBEDTLS_PADDING_NONE ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + switch( mode ) + { +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + case MBEDTLS_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + case MBEDTLS_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + case MBEDTLS_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + case MBEDTLS_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case MBEDTLS_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_ENCRYPT != ctx->operation ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + tag, tag_len ) ); +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != 16U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( mbedtls_chachapoly_finish( + (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) ); + } +#endif + + return( 0 ); +} + +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + unsigned char check_tag[16]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_DECRYPT != ctx->operation ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* Status to return on a non-authenticated algorithm. It would make sense + * to return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT or perhaps + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, but at the time I write this our + * unit tests assume 0. */ + ret = 0; + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + if( tag_len > sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = mbedtls_gcm_finish( + (mbedtls_gcm_context *) ctx->cipher_ctx, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto exit; + } + } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ret = mbedtls_chachapoly_finish( + (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag ); + if ( ret != 0 ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto exit; + } + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + +exit: + mbedtls_platform_zeroize( check_tag, tag_len ); + return( ret ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t finish_olen; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; + size_t part_len; + + if( ctx->operation == MBEDTLS_DECRYPT ) + { + status = psa_cipher_decrypt_setup( &cipher_op, + cipher_psa->slot, + cipher_psa->alg ); + } + else if( ctx->operation == MBEDTLS_ENCRYPT ) + { + status = psa_cipher_encrypt_setup( &cipher_op, + cipher_psa->slot, + cipher_psa->alg ); + } + else + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* In the following, we can immediately return on an error, + * because the PSA Crypto API guarantees that cipher operations + * are terminated by unsuccessful calls to psa_cipher_update(), + * and by any call to psa_cipher_finish(). */ + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + if( ctx->cipher_info->mode != MBEDTLS_MODE_ECB ) + { + status = psa_cipher_set_iv( &cipher_op, iv, iv_len ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + } + + status = psa_cipher_update( &cipher_op, + input, ilen, + output, ilen, olen ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + status = psa_cipher_finish( &cipher_op, + output + *olen, ilen - *olen, + &part_len ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + *olen += part_len; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_update( ctx, input, ilen, + output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, + &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes: internal function shared by + * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext(). + */ +static int mbedtls_cipher_aead_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + + /* PSA Crypto API always writes the authentication tag + * at the end of the encrypted message. */ + if( output == NULL || tag != output + ilen ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + status = psa_aead_encrypt( cipher_psa->slot, + cipher_psa->alg, + iv, iv_len, + ad, ad_len, + input, ilen, + output, ilen + tag_len, olen ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + *olen -= tag_len; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, + ilen, iv, iv_len, ad, ad_len, + input, output, tag_len, tag ) ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, + ilen, iv, ad, ad_len, input, output, tag ) ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented encryption for AEAD modes: internal function shared by + * mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_encrypt_ext(). + */ +static int mbedtls_cipher_aead_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + + /* PSA Crypto API always writes the authentication tag + * at the end of the encrypted message. */ + if( input == NULL || tag != input + ilen ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + status = psa_aead_decrypt( cipher_psa->slot, + cipher_psa->alg, + iv, iv_len, + ad, ad_len, + input, ilen + tag_len, + output, ilen, olen ); + if( status == PSA_ERROR_INVALID_SIGNATURE ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + else if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + *olen = ilen; + ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + *olen = ilen; + ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, + iv, ad, ad_len, tag, input, output ); + + if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Packet-oriented encryption for AEAD modes: public legacy function. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + return( mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len, + input, ilen, output, olen, + tag, tag_len ) ); +} + +/* + * Packet-oriented decryption for AEAD modes: public legacy function. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + + return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len, + input, ilen, output, olen, + tag, tag_len ) ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) +/* + * Packet-oriented encryption for AEAD/NIST_KW: public function. + */ +int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + +#if defined(MBEDTLS_NIST_KW_C) + if( +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ctx->psa_enabled == 0 && +#endif + ( MBEDTLS_MODE_KW == ctx->cipher_info->mode || + MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) ) + { + mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? + MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; + + /* There is no iv, tag or ad associated with KW and KWP, + * so these length should be 0 as documented. */ + if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + (void) iv; + (void) ad; + + return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen, + output, olen, output_len ) ); + } +#endif /* MBEDTLS_NIST_KW_C */ + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) + /* AEAD case: check length before passing on to shared function */ + if( output_len < ilen + tag_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + int ret = mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len, + input, ilen, output, olen, + output + ilen, tag_len ); + *olen += tag_len; + return( ret ); +#else + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ +} + +/* + * Packet-oriented decryption for AEAD/NIST_KW: public function. + */ +int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output_len == 0 || output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + +#if defined(MBEDTLS_NIST_KW_C) + if( +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ctx->psa_enabled == 0 && +#endif + ( MBEDTLS_MODE_KW == ctx->cipher_info->mode || + MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) ) + { + mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? + MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; + + /* There is no iv, tag or ad associated with KW and KWP, + * so these length should be 0 as documented. */ + if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + (void) iv; + (void) ad; + + return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen, + output, olen, output_len ) ); + } +#endif /* MBEDTLS_NIST_KW_C */ + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) + /* AEAD case: check length before passing on to shared function */ + if( ilen < tag_len || output_len < ilen - tag_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len, + input, ilen - tag_len, output, olen, + input + ilen - tag_len, tag_len ) ); +#else + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c new file mode 100644 index 0000000..f05fa15 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/cipher_wrap.c @@ -0,0 +1,2484 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher_internal.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_NIST_KW_C) +#include "mbedtls/nist_kw.h" +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); + + if( ctx != NULL ) + mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); + + return( ctx ); +} + +static void gcm_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_gcm_context ) ); +} + +static void gcm_ctx_free( void *ctx ) +{ + mbedtls_gcm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); + + if( ctx != NULL ) + mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); + + return( ctx ); +} + +static void ccm_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_ccm_context ) ); +} + +static void ccm_ctx_free( void *ctx ) +{ + mbedtls_ccm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, + iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + int mode; + + switch( operation ) + { + case MBEDTLS_ENCRYPT: + mode = MBEDTLS_AES_ENCRYPT; + break; + case MBEDTLS_DECRYPT: + mode = MBEDTLS_AES_DECRYPT; + break; + default: + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_aes_crypt_xts( xts_ctx, mode, length, + data_unit, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static void * aes_ctx_alloc( void ) +{ + mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_aes_context ) ); +} + +static void aes_ctx_free( void *ctx ) +{ + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aes_info = { + MBEDTLS_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + aes_crypt_ofb_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_clone, + aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_ecb_info = { + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "AES-128-ECB", + 0, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ecb_info = { + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "AES-192-ECB", + 0, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ecb_info = { + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "AES-256-ECB", + 0, + 0, + 16, + &aes_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aes_128_cbc_info = { + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cbc_info = { + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cbc_info = { + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aes_128_cfb128_info = { + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cfb128_info = { + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cfb128_info = { + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static const mbedtls_cipher_info_t aes_128_ofb_info = { + MBEDTLS_CIPHER_AES_128_OFB, + MBEDTLS_MODE_OFB, + 128, + "AES-128-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ofb_info = { + MBEDTLS_CIPHER_AES_192_OFB, + MBEDTLS_MODE_OFB, + 192, + "AES-192-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ofb_info = { + MBEDTLS_CIPHER_AES_256_OFB, + MBEDTLS_MODE_OFB, + 256, + "AES-256-OFB", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aes_128_ctr_info = { + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ctr_info = { + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ctr_info = { + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); +} + +static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); +} + +static void *xts_aes_ctx_alloc( void ) +{ + mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); + + if( xts_ctx != NULL ) + mbedtls_aes_xts_init( xts_ctx ); + + return( xts_ctx ); +} + +static void xts_aes_ctx_free( void *ctx ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + + if( xts_ctx == NULL ) + return; + + mbedtls_aes_xts_free( xts_ctx ); + mbedtls_free( xts_ctx ); +} + +static const mbedtls_cipher_base_t xts_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + aes_crypt_xts_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + xts_aes_setkey_enc_wrap, + xts_aes_setkey_dec_wrap, + xts_aes_ctx_alloc, + xts_aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_xts_info = { + MBEDTLS_CIPHER_AES_128_XTS, + MBEDTLS_MODE_XTS, + 256, + "AES-128-XTS", + 16, + 0, + 16, + &xts_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_xts_info = { + MBEDTLS_CIPHER_AES_256_XTS, + MBEDTLS_MODE_XTS, + 512, + "AES-256-XTS", + 16, + 0, + 16, + &xts_aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_clone, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_gcm_info = { + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "AES-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_gcm_info = { + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "AES-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_gcm_info = { + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "AES-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_clone, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_ccm_info = { + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "AES-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_info = { + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "AES-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_info = { + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "AES-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static void * camellia_ctx_alloc( void ) +{ + mbedtls_camellia_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_camellia_context ) ); +} + +static void camellia_ctx_free( void *ctx ) +{ + mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_clone, + camellia_ctx_free +}; + +static const mbedtls_cipher_info_t camellia_128_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 0, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 0, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 0, + 0, + 16, + &camellia_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t camellia_128_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t camellia_128_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t camellia_128_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_clone, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_clone, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + +static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + (void) operation; + return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static void * aria_ctx_alloc( void ) +{ + mbedtls_aria_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_aria_init( ctx ); + + return( ctx ); +} + +static void aria_ctx_free( void *ctx ) +{ + mbedtls_aria_free( (mbedtls_aria_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + aria_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aria_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aria_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aria_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aria_setkey_enc_wrap, + aria_setkey_dec_wrap, + aria_ctx_alloc, + aria_ctx_free +}; + +static const mbedtls_cipher_info_t aria_128_ecb_info = { + MBEDTLS_CIPHER_ARIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "ARIA-128-ECB", + 0, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ecb_info = { + MBEDTLS_CIPHER_ARIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "ARIA-192-ECB", + 0, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ecb_info = { + MBEDTLS_CIPHER_ARIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "ARIA-256-ECB", + 0, + 0, + 16, + &aria_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aria_128_cbc_info = { + MBEDTLS_CIPHER_ARIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "ARIA-128-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cbc_info = { + MBEDTLS_CIPHER_ARIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "ARIA-192-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cbc_info = { + MBEDTLS_CIPHER_ARIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "ARIA-256-CBC", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aria_128_cfb128_info = { + MBEDTLS_CIPHER_ARIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "ARIA-128-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cfb128_info = { + MBEDTLS_CIPHER_ARIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "ARIA-192-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cfb128_info = { + MBEDTLS_CIPHER_ARIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "ARIA-256-CFB128", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aria_128_ctr_info = { + MBEDTLS_CIPHER_ARIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "ARIA-128-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ctr_info = { + MBEDTLS_CIPHER_ARIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "ARIA-192-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ctr_info = { + MBEDTLS_CIPHER_ARIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "ARIA-256-CTR", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aria_setkey_wrap, + gcm_aria_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_gcm_info = { + MBEDTLS_CIPHER_ARIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "ARIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_gcm_info = { + MBEDTLS_CIPHER_ARIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "ARIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_gcm_info = { + MBEDTLS_CIPHER_ARIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "ARIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aria_setkey_wrap, + ccm_aria_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_ccm_info = { + MBEDTLS_CIPHER_ARIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "ARIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_info = { + MBEDTLS_CIPHER_ARIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "ARIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_info = { + MBEDTLS_CIPHER_ARIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "ARIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); + + if( des == NULL ) + return( NULL ); + + mbedtls_des_init( des ); + + return( des ); +} + +static void des_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_des_context ) ); +} + +static void des_ctx_free( void *ctx ) +{ + mbedtls_des_free( (mbedtls_des_context *) ctx ); + mbedtls_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + mbedtls_des3_context *des3; + des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + mbedtls_des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_des3_context ) ); +} + +static void des3_ctx_free( void *ctx ) +{ + mbedtls_des3_free( (mbedtls_des3_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t des_info = { + MBEDTLS_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_clone, + des_ctx_free +}; + +static const mbedtls_cipher_info_t des_ecb_info = { + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES, + "DES-ECB", + 0, + 0, + 8, + &des_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_cbc_info = { + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede_info = { + MBEDTLS_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_clone, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede_ecb_info = { + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 0, + 0, + 8, + &des_ede_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede_cbc_info = { + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede3_info = { + MBEDTLS_CIPHER_ID_3DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_clone, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede3_ecb_info = { + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 0, + 0, + 8, + &des_ede3_info +}; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede3_cbc_info = { + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); +} + +static void * blowfish_ctx_alloc( void ) +{ + mbedtls_blowfish_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_blowfish_context ) ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t blowfish_info = { + MBEDTLS_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + blowfish_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + blowfish_crypt_cfb64_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + blowfish_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_clone, + blowfish_ctx_free +}; + +static const mbedtls_cipher_info_t blowfish_ecb_info = { + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_MODE_ECB, + 128, + "BLOWFISH-ECB", + 0, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t blowfish_cbc_info = { + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t blowfish_cfb64_info = { + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t blowfish_ctr_info = { + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + /* we get key_bitlen in bits, arc4 expects it in bytes */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + mbedtls_arc4_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_arc4_context ) ); +} + +static void arc4_ctx_free( void *ctx ) +{ + mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t arc4_base_info = { + MBEDTLS_CIPHER_ID_ARC4, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + arc4_crypt_stream_wrap, +#endif + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_clone, + arc4_ctx_free +}; + +static const mbedtls_cipher_info_t arc4_128_info = { + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int chacha20_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_chacha20_update( ctx, length, input, output ); + if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( ret ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_chacha20_context ) ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + chacha20_stream_wrap, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_clone, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_STREAM, + 256, + "CHACHA20", + 12, + 0, + 1, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + +static int chachapoly_setkey_wrap( void *ctx, + const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chachapoly_ctx_alloc( void ) +{ + mbedtls_chachapoly_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chachapoly_init( ctx ); + + return( ctx ); +} + +static void chachapoly_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_chachapoly_context ) ); +} + +static void chachapoly_ctx_free( void *ctx ) +{ + mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chachapoly_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chachapoly_setkey_wrap, + chachapoly_setkey_wrap, + chachapoly_ctx_alloc, + chachapoly_ctx_clone, + chachapoly_ctx_free +}; +static const mbedtls_cipher_info_t chachapoly_info = { + MBEDTLS_CIPHER_CHACHA20_POLY1305, + MBEDTLS_MODE_CHACHAPOLY, + 256, + "CHACHA20-POLY1305", + 12, + 0, + 1, + &chachapoly_base_info +}; +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) ctx); + ((void) key); + ((void) key_bitlen); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_clone( void *dst, const void *src ) +{ + ((void) dst); + ((void) src); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const mbedtls_cipher_base_t null_base_info = { + MBEDTLS_CIPHER_ID_NULL, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_clone, + null_ctx_free +}; + +static const mbedtls_cipher_info_t null_cipher_info = { + MBEDTLS_CIPHER_NULL, + MBEDTLS_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ + +#if defined(MBEDTLS_NIST_KW_C) +static void *kw_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_nist_kw_context ) ); + + if( ctx != NULL ) + mbedtls_nist_kw_init( (mbedtls_nist_kw_context *) ctx ); + + return( ctx ); +} + +static void kw_ctx_clone( void *dst, const void *src ) +{ + memcpy( dst, src, sizeof( mbedtls_nist_kw_context ) ); +} + +static void kw_ctx_free( void *ctx ) +{ + mbedtls_nist_kw_free( ctx ); + mbedtls_free( ctx ); +} + +static int kw_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx, + MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1 ); +} + +static int kw_aes_setkey_unwrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx, + MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0 ); +} + +static const mbedtls_cipher_base_t kw_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + kw_aes_setkey_wrap, + kw_aes_setkey_unwrap, + kw_ctx_alloc, + kw_ctx_clone, + kw_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_nist_kw_info = { + MBEDTLS_CIPHER_AES_128_KW, + MBEDTLS_MODE_KW, + 128, + "AES-128-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_nist_kw_info = { + MBEDTLS_CIPHER_AES_192_KW, + MBEDTLS_MODE_KW, + 192, + "AES-192-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_nist_kw_info = { + MBEDTLS_CIPHER_AES_256_KW, + MBEDTLS_MODE_KW, + 256, + "AES-256-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_128_nist_kwp_info = { + MBEDTLS_CIPHER_AES_128_KWP, + MBEDTLS_MODE_KWP, + 128, + "AES-128-KWP", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_nist_kwp_info = { + MBEDTLS_CIPHER_AES_192_KWP, + MBEDTLS_MODE_KWP, + 192, + "AES-192-KWP", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_nist_kwp_info = { + MBEDTLS_CIPHER_AES_256_KWP, + MBEDTLS_MODE_KWP, + 256, + "AES-256-KWP", + 0, + 0, + 16, + &kw_aes_info +}; +#endif /* MBEDTLS_NIST_KW_C */ + +const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = +{ +#if defined(MBEDTLS_AES_C) + { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, + { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, + { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, + { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, + { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, + { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, + { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, + { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, + { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, + { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, + { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, + { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, +#endif +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, +#endif + +#if defined(MBEDTLS_NIST_KW_C) + { MBEDTLS_CIPHER_AES_128_KW, &aes_128_nist_kw_info }, + { MBEDTLS_CIPHER_AES_192_KW, &aes_192_nist_kw_info }, + { MBEDTLS_CIPHER_AES_256_KW, &aes_256_nist_kw_info }, + { MBEDTLS_CIPHER_AES_128_KWP, &aes_128_nist_kwp_info }, + { MBEDTLS_CIPHER_AES_192_KWP, &aes_192_nist_kwp_info }, + { MBEDTLS_CIPHER_AES_256_KWP, &aes_256_nist_kwp_info }, +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + { MBEDTLS_CIPHER_NULL, &null_cipher_info }, +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + + { MBEDTLS_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS ( sizeof(mbedtls_cipher_definitions) / \ + sizeof(mbedtls_cipher_definitions[0]) ) +int mbedtls_cipher_supported[NUM_CIPHERS]; + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c new file mode 100644 index 0000000..8dd7fab --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/cmac.c @@ -0,0 +1,1096 @@ +/** + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * References: + * + * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The + * CMAC Mode for Authentication + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf + * + * - RFC 4493 - The AES-CMAC Algorithm + * https://tools.ietf.org/html/rfc4493 + * + * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message + * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) + * Algorithm for the Internet Key Exchange Protocol (IKE) + * https://tools.ietf.org/html/rfc4615 + * + * Additional test vectors: ISO/IEC 9797-1 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_CMAC_C) + +#include "mbedtls/cmac.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include + +#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) + +/* + * Multiplication by u in the Galois field of GF(2^n) + * + * As explained in NIST SP 800-38B, this can be computed: + * + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ R_n + * with R_64 = 0x1B and R_128 = 0x87 + * + * Input and output MUST NOT point to the same buffer + * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. + */ +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize ) +{ + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i; + + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) + { + R_n = R_128; + } + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) + { + R_n = R_64; + } + else + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + for( i = (int)blocksize - 1; i >= 0; i-- ) + { + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; + } + + /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 + * using bit operations to avoid branches */ + + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( input[0] >> 7 ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + output[ blocksize - 1 ] ^= R_n & mask; + + return( 0 ); +} + +/* + * Generate subkeys + * + * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm + */ +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + size_t olen, block_size; + + mbedtls_platform_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; + + /* Calculate Ek(0) */ + if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) + goto exit; + + /* + * Generate K1 and K2 + */ + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) + goto exit; + + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( L, sizeof( L ) ); + + return( ret ); +} +#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ + +#if !defined(MBEDTLS_CMAC_ALT) +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) +{ + size_t idx; + + for( idx = 0; idx < block_size; idx++ ) + output[ idx ] = input1[ idx ] ^ input2[ idx ]; +} + +/* + * Create padded last block from (partial) last block. + * + * We can't use the padding option from the cipher layer, as it only works for + * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. + */ +static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], + size_t padded_block_len, + const unsigned char *last_block, + size_t last_block_len ) +{ + size_t j; + + for( j = 0; j < padded_block_len; j++ ) + { + if( j < last_block_len ) + padded_block[j] = last_block[j]; + else if( j == last_block_len ) + padded_block[j] = 0x80; + else + padded_block[j] = 0x00; + } +} + +int mbedtls_cipher_cmac_setup(mbedtls_cipher_context_t *ctx) +{ + mbedtls_cmac_context_t *cmac_ctx; + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + return 0; +} + +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ) +{ + mbedtls_cipher_type_t type; + int retval; + + if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Check if cmac ctx had been allocated by mbedtls_cipher_cmac_setup() */ + if( ctx->cmac_ctx != NULL ) + return 0; + + return mbedtls_cipher_cmac_setup( ctx ); +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + int ret = 0; + size_t n, j, olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; + + /* Is there data still to process from the last call, that's greater in + * size than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen > block_size - cmac_ctx->unprocessed_len ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; + cmac_ctx->unprocessed_len = 0; + } + + /* n is the number of blocks including any final partial block */ + n = ( ilen + block_size - 1 ) / block_size; + + /* Iterate across the input data in block sized chunks, excluding any + * final partial or complete block */ + for( j = 1; j < n; j++ ) + { + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + } + + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state, *last_block; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || + output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = cmac_ctx->state; + + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + cmac_generate_subkeys( ctx, K1, K2 ); + + last_block = cmac_ctx->unprocessed_block; + + /* Calculate last block */ + if( cmac_ctx->unprocessed_len < block_size ) + { + cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); + cmac_xor_block( M_last, M_last, K2, block_size ); + } + else + { + /* Last block is complete block */ + cmac_xor_block( M_last, last_block, K1, block_size ); + } + + + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + memcpy( output, state, block_size ); + +exit: + /* Wipe the generated keys on the stack, and any other transients to avoid + * side channel leakage */ + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + + mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + return( ret ); +} + +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) +{ + mbedtls_cmac_context_t* cmac_ctx; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); + + return( 0 ); +} + +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_cipher_context_t ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_finish( &ctx, output ); + +exit: + mbedtls_cipher_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +/* + * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; + + if( key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) + { + /* Use key as is */ + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); + } + else + { + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); + + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); + +exit: + mbedtls_platform_zeroize( int_key, sizeof( int_key ) ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* !MBEDTLS_CMAC_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * CMAC test data for SP800-38B + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf + * + * AES-CMAC-PRF-128 test data from RFC 4615 + * https://tools.ietf.org/html/rfc4615#page-4 + */ + +#define NB_CMAC_TESTS_PER_KEY 4 +#define NB_PRF_TESTS 3 + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) +/* All CMAC test inputs are truncated from the same 64 byte buffer. */ +static const unsigned char test_message[] = { + /* PT */ + 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 +}; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* Truncation point of message for AES CMAC tests */ +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + /* Mlen */ + 0, + 16, + 20, + 64 +}; + +/* CMAC-AES128 Test Data */ +static const unsigned char aes_128_key[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde + }, + { + /* K2 */ + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b + } +}; +static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }, + { + /* Example #2 */ + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }, + { + /* Example #3 */ + 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, + 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde + }, + { + /* Example #4 */ + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + } +}; + +/* CMAC-AES192 Test Data */ +static const unsigned char aes_192_key[24] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; +static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 + }, + { + /* K2 */ + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c + } +}; +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }, + { + /* Example #2 */ + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }, + { + /* Example #3 */ + 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, + 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 + }, + { + /* Example #4 */ + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + } +}; + +/* CMAC-AES256 Test Data */ +static const unsigned char aes_256_key[32] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; +static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f + }, + { + /* K2 */ + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 + } +}; +static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }, + { + /* Example #2 */ + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }, + { + /* Example #3 */ + 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, + 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 + }, + { + /* Example #4 */ + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + } +}; +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) +/* Truncation point of message for 3DES CMAC tests */ +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 20, + 32 +}; + +/* CMAC-TDES (Generation) - 2 Key Test Data */ +static const unsigned char des3_2key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, + /* Key3 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef +}; +static const unsigned char des3_2key_subkeys[2][8] = { + { + /* K1 */ + 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 + }, + { + /* K2 */ + 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 + } +}; +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 + }, + { + /* Sample #2 */ + 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b + }, + { + /* Sample #3 */ + 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 + }, + { + /* Sample #4 */ + 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb + } +}; + +/* CMAC-TDES (Generation) - 3 Key Test Data */ +static const unsigned char des3_3key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, + /* Key3 */ + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 +}; +static const unsigned char des3_3key_subkeys[2][8] = { + { + /* K1 */ + 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 + }, + { + /* K2 */ + 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b + } +}; +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 + }, + { + /* Sample #2 */ + 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 + }, + { + /* Sample #3 */ + 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 + }, + { + /* Sample #4 */ + 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 + } +}; + +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* AES AES-CMAC-PRF-128 Test Data */ +static const unsigned char PRFK[] = { + /* Key */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xed, 0xcb +}; + +/* Sizes in bytes */ +static const size_t PRFKlen[NB_PRF_TESTS] = { + 18, + 16, + 10 +}; + +/* Message */ +static const unsigned char PRFM[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char PRFT[NB_PRF_TESTS][16] = { + { + 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, + 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a + }, + { + 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, + 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d + }, + { + 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, + 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d + } +}; +#endif /* MBEDTLS_AES_C */ + +static int cmac_test_subkeys( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* subkeys, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + int i, ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC subkey #%d: ", testname, i + 1 ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + /* When CMAC is implemented by an alternative implementation, or + * the underlying primitive itself is implemented alternatively, + * AES-192 may be unavailable. This should not cause the selftest + * function to fail. */ + if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED || + ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) && + cipher_type == MBEDTLS_CIPHER_AES_192_ECB ) { + if( verbose != 0 ) + mbedtls_printf( "skipped\n" ); + goto next_test; + } + + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +next_test: + mbedtls_cipher_free( &ctx ); + } + + ret = 0; + goto exit; + +cleanup: + mbedtls_cipher_free( &ctx ); + +exit: + return( ret ); +} + +static int cmac_test_wth_cipher( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* expected_result, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret = 0; + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%d: ", testname, i + 1 ); + + if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, + message_lengths[i], output ) ) != 0 ) + { + /* When CMAC is implemented by an alternative implementation, or + * the underlying primitive itself is implemented alternatively, + * AES-192 and/or 3DES may be unavailable. This should not cause + * the selftest function to fail. */ + if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED || + ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) && + ( cipher_type == MBEDTLS_CIPHER_AES_192_ECB || + cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB ) ) { + if( verbose != 0 ) + mbedtls_printf( "skipped\n" ); + continue; + } + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + ret = 0; + +exit: + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES CMAC 128 PRF #%d: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); + if( ret != 0 || + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) + { + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +int mbedtls_cmac_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_AES_C) + /* AES-128 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 128", + aes_128_key, + 128, + (const unsigned char*)aes_128_subkeys, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*)aes_128_expected_result, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-192 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 192", + aes_192_key, + 192, + (const unsigned char*)aes_192_subkeys, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*)aes_192_expected_result, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-256 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 256", + aes_256_key, + 256, + (const unsigned char*)aes_256_subkeys, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*)aes_256_expected_result, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) + /* 3DES 2 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 2 key", + des3_2key_key, + 192, + (const unsigned char*)des3_2key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_2key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* 3DES 3 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 3 key", + des3_3key_key, + 192, + (const unsigned char*)des3_3key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_3key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_AES_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CMAC_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/common.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/common.h new file mode 100644 index 0000000..c064724 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/common.h @@ -0,0 +1,305 @@ +/** + * \file common.h + * + * \brief Utility macros for internal use in the library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_LIBRARY_COMMON_H +#define MBEDTLS_LIBRARY_COMMON_H + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#include + +/** Helper to define a function as static except when building invasive tests. + * + * If a function is only used inside its own source file and should be + * declared `static` to allow the compiler to optimize for code size, + * but that function has unit tests, define it with + * ``` + * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... } + * ``` + * and declare it in a header in the `library/` directory with + * ``` + * #if defined(MBEDTLS_TEST_HOOKS) + * int mbedtls_foo(...); + * #endif + * ``` + */ +#if defined(MBEDTLS_TEST_HOOKS) +#define MBEDTLS_STATIC_TESTABLE +#else +#define MBEDTLS_STATIC_TESTABLE static +#endif + +/** Byte Reading Macros + * + * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th + * byte from x, where byte 0 is the least significant byte. + */ +#define MBEDTLS_BYTE_0( x ) ( (uint8_t) ( ( x ) & 0xff ) ) +#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8 ) & 0xff ) ) +#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) ) +#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) ) +#define MBEDTLS_BYTE_4( x ) ( (uint8_t) ( ( ( x ) >> 32 ) & 0xff ) ) +#define MBEDTLS_BYTE_5( x ) ( (uint8_t) ( ( ( x ) >> 40 ) & 0xff ) ) +#define MBEDTLS_BYTE_6( x ) ( (uint8_t) ( ( ( x ) >> 48 ) & 0xff ) ) +#define MBEDTLS_BYTE_7( x ) ( (uint8_t) ( ( ( x ) >> 56 ) & 0xff ) ) + +/** + * Get the unsigned 32 bits integer corresponding to four bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the four bytes from. + * \param offset Offset from \p base of the first and most significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT32_BE +#define MBEDTLS_GET_UINT32_BE( data , offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] << 24 ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 16 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 3] ) \ + ) +#endif + +/** + * Put in memory a 32 bits unsigned integer in big-endian order. + * + * \param n 32 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 32 + * bits unsigned integer in. + * \param offset Offset from \p base where to put the most significant + * byte of the 32 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT32_BE +#define MBEDTLS_PUT_UINT32_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 32 bits integer corresponding to four bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the four bytes from. + * \param offset Offset from \p base of the first and least significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT32_LE +#define MBEDTLS_GET_UINT32_LE( data, offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \ + | ( (uint32_t) ( data )[( offset ) + 3] << 24 ) \ + ) +#endif + +/** + * Put in memory a 32 bits unsigned integer in little-endian order. + * + * \param n 32 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 32 + * bits unsigned integer in. + * \param offset Offset from \p base where to put the least significant + * byte of the 32 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT32_LE +#define MBEDTLS_PUT_UINT32_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \ +} +#endif + +/** + * Get the unsigned 16 bits integer corresponding to two bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the two bytes from. + * \param offset Offset from \p base of the first and least significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT16_LE +#define MBEDTLS_GET_UINT16_LE( data, offset ) \ + ( \ + ( (uint16_t) ( data )[( offset ) ] ) \ + | ( (uint16_t) ( data )[( offset ) + 1] << 8 ) \ + ) +#endif + +/** + * Put in memory a 16 bits unsigned integer in little-endian order. + * + * \param n 16 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 16 + * bits unsigned integer in. + * \param offset Offset from \p base where to put the least significant + * byte of the 16 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT16_LE +#define MBEDTLS_PUT_UINT16_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ +} +#endif + +/** + * Get the unsigned 16 bits integer corresponding to two bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the two bytes from. + * \param offset Offset from \p base of the first and most significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT16_BE +#define MBEDTLS_GET_UINT16_BE( data, offset ) \ + ( \ + ( (uint16_t) ( data )[( offset ) ] << 8 ) \ + | ( (uint16_t) ( data )[( offset ) + 1] ) \ + ) +#endif + +/** + * Put in memory a 16 bits unsigned integer in big-endian order. + * + * \param n 16 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 16 + * bits unsigned integer in. + * \param offset Offset from \p base where to put the most significant + * byte of the 16 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT16_BE +#define MBEDTLS_PUT_UINT16_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 64 bits integer corresponding to eight bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the eight bytes from. + * \param offset Offset from \p base of the first and most significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT64_BE +#define MBEDTLS_GET_UINT64_BE( data, offset ) \ + ( \ + ( (uint64_t) ( data )[( offset ) ] << 56 ) \ + | ( (uint64_t) ( data )[( offset ) + 1] << 48 ) \ + | ( (uint64_t) ( data )[( offset ) + 2] << 40 ) \ + | ( (uint64_t) ( data )[( offset ) + 3] << 32 ) \ + | ( (uint64_t) ( data )[( offset ) + 4] << 24 ) \ + | ( (uint64_t) ( data )[( offset ) + 5] << 16 ) \ + | ( (uint64_t) ( data )[( offset ) + 6] << 8 ) \ + | ( (uint64_t) ( data )[( offset ) + 7] ) \ + ) +#endif + +/** + * Put in memory a 64 bits unsigned integer in big-endian order. + * + * \param n 64 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 64 + * bits unsigned integer in. + * \param offset Offset from \p base where to put the most significant + * byte of the 64 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT64_BE +#define MBEDTLS_PUT_UINT64_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_7( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_6( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_5( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_4( n ); \ + ( data )[( offset ) + 4] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 5] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 6] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 7] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 64 bits integer corresponding to eight bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the eight bytes from. + * \param offset Offset from \p base of the first and least significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT64_LE +#define MBEDTLS_GET_UINT64_LE( data, offset ) \ + ( \ + ( (uint64_t) ( data )[( offset ) + 7] << 56 ) \ + | ( (uint64_t) ( data )[( offset ) + 6] << 48 ) \ + | ( (uint64_t) ( data )[( offset ) + 5] << 40 ) \ + | ( (uint64_t) ( data )[( offset ) + 4] << 32 ) \ + | ( (uint64_t) ( data )[( offset ) + 3] << 24 ) \ + | ( (uint64_t) ( data )[( offset ) + 2] << 16 ) \ + | ( (uint64_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint64_t) ( data )[( offset ) ] ) \ + ) +#endif + +/** + * Put in memory a 64 bits unsigned integer in little-endian order. + * + * \param n 64 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 64 + * bits unsigned integer in. + * \param offset Offset from \p base where to put the least significant + * byte of the 64 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT64_LE +#define MBEDTLS_PUT_UINT64_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 4] = MBEDTLS_BYTE_4( n ); \ + ( data )[( offset ) + 5] = MBEDTLS_BYTE_5( n ); \ + ( data )[( offset ) + 6] = MBEDTLS_BYTE_6( n ); \ + ( data )[( offset ) + 7] = MBEDTLS_BYTE_7( n ); \ +} +#endif + +#endif /* MBEDTLS_LIBRARY_COMMON_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c new file mode 100644 index 0000000..e276d23 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time.c @@ -0,0 +1,832 @@ +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /* + * The following functions are implemented without using comparison operators, as those + * might be translated to branches by some compilers on some platforms. + */ + +#include "common.h" +#include "constant_time_internal.h" +#include "mbedtls/constant_time.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl_internal.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "constant_time_invasive.h" +#endif + +#include + +int mbedtls_ct_memcmp( const void *a, + const void *b, + size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( (int)diff ); +} + +unsigned mbedtls_ct_uint_mask( unsigned value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +size_t mbedtls_ct_size_mask( size_t value ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BIGNUM_C) + +mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Constant-flow mask generation for "less than" comparison: + * - if \p x < \p y, return all-bits 1, that is (size_t) -1 + * - otherwise, return all bits 0, that is 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return All-bits-one if \p x is less than \p y, otherwise zero. + */ +static size_t mbedtls_ct_size_mask_lt( size_t x, + size_t y ) +{ + /* This has the most significant bit set if and only if x < y */ + const size_t sub = x - y; + + /* sub1 = (x < y) ? 1 : 0 */ + const size_t sub1 = sub >> ( sizeof( sub ) * 8 - 1 ); + + /* mask = (x < y) ? 0xff... : 0x00... */ + const size_t mask = mbedtls_ct_size_mask( sub1 ); + + return( mask ); +} + +size_t mbedtls_ct_size_mask_ge( size_t x, + size_t y ) +{ + return( ~mbedtls_ct_size_mask_lt( x, y ) ); +} + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BASE64_C) + +/* Return 0xff if low <= c <= high, 0 otherwise. + * + * Constant flow with respect to c. + */ +MBEDTLS_STATIC_TESTABLE +unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low, + unsigned char high, + unsigned char c ) +{ + /* low_mask is: 0 if low <= c, 0x...ff if low > c */ + unsigned low_mask = ( (unsigned) c - low ) >> 8; + /* high_mask is: 0 if c <= high, 0x...ff if c > high */ + unsigned high_mask = ( (unsigned) high - c ) >> 8; + return( ~( low_mask | high_mask ) & 0xff ); +} + +#endif /* MBEDTLS_BASE64_C */ + +unsigned mbedtls_ct_size_bool_eq( size_t x, + size_t y ) +{ + /* diff = 0 if x == y, non-zero otherwise */ + const size_t diff = x ^ y; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* diff_msb's most significant bit is equal to x != y */ + const size_t diff_msb = ( diff | (size_t) -diff ); + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* diff1 = (x != y) ? 1 : 0 */ + const unsigned diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 ); + + return( 1 ^ diff1 ); +} + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** Constant-flow "greater than" comparison: + * return x > y + * + * This is equivalent to \p x > \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x greater than \p y, otherwise 0. + */ +static unsigned mbedtls_ct_size_gt( size_t x, + size_t y ) +{ + /* Return the sign bit (1 for negative) of (y - x). */ + return( ( y - x ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_BIGNUM_C) + +unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ) +{ + mbedtls_mpi_uint ret; + mbedtls_mpi_uint cond; + + /* + * Check if the most significant bits (MSB) of the operands are different. + */ + cond = ( x ^ y ); + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> ( sizeof( mbedtls_mpi_uint ) * 8 - 1 ); + + return (unsigned) ret; +} + +#endif /* MBEDTLS_BIGNUM_C */ + +unsigned mbedtls_ct_uint_if( unsigned condition, + unsigned if1, + unsigned if0 ) +{ + unsigned mask = mbedtls_ct_uint_mask( condition ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} + +#if defined(MBEDTLS_BIGNUM_C) + +/** Select between two sign values without branches. + * + * This is functionally equivalent to `condition ? if1 : if0` but uses only bit + * operations in order to avoid branches. + * + * \note if1 and if0 must be either 1 or -1, otherwise the result + * is undefined. + * + * \param condition Condition to test. + * \param if1 The first sign; must be either +1 or -1. + * \param if0 The second sign; must be either +1 or -1. + * + * \return \c if1 if \p condition is nonzero, otherwise \c if0. + * */ +static int mbedtls_ct_cond_select_sign( unsigned char condition, + int if1, + int if0 ) +{ + /* In order to avoid questions about what we can reasonably assume about + * the representations of signed integers, move everything to unsigned + * by taking advantage of the fact that if1 and if0 are either +1 or -1. */ + unsigned uif1 = if1 + 1; + unsigned uif0 = if0 + 1; + + /* condition was 0 or 1, mask is 0 or 2 as are uif1 and uif0 */ + const unsigned mask = condition << 1; + + /* select uif1 or uif0 */ + unsigned ur = ( uif0 & ~mask ) | ( uif1 & mask ); + + /* ur is now 0 or 2, convert back to -1 or +1 */ + return( (int) ur - 1 ); +} + +void mbedtls_ct_mpi_uint_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char condition ) +{ + size_t i; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */ + const mbedtls_mpi_uint mask = -condition; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + for( i = 0; i < n; i++ ) + dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask ); +} + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BASE64_C) + +unsigned char mbedtls_ct_base64_enc_char( unsigned char value ) +{ + unsigned char digit = 0; + /* For each range of values, if value is in that range, mask digit with + * the corresponding value. Since value can only be in a single range, + * only at most one masking will change digit. */ + digit |= mbedtls_ct_uchar_mask_of_range( 0, 25, value ) & ( 'A' + value ); + digit |= mbedtls_ct_uchar_mask_of_range( 26, 51, value ) & ( 'a' + value - 26 ); + digit |= mbedtls_ct_uchar_mask_of_range( 52, 61, value ) & ( '0' + value - 52 ); + digit |= mbedtls_ct_uchar_mask_of_range( 62, 62, value ) & '+'; + digit |= mbedtls_ct_uchar_mask_of_range( 63, 63, value ) & '/'; + return( digit ); +} + +signed char mbedtls_ct_base64_dec_value( unsigned char c ) +{ + unsigned char val = 0; + /* For each range of digits, if c is in that range, mask val with + * the corresponding value. Since c can only be in a single range, + * only at most one masking will change val. Set val to one plus + * the desired value so that it stays 0 if c is in none of the ranges. */ + val |= mbedtls_ct_uchar_mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 ); + /* At this point, val is 0 if c is an invalid digit and v+1 if c is + * a digit with the value v. */ + return( val - 1 ); +} + +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** Shift some data towards the left inside a buffer. + * + * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally + * equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mbedtls_ct_mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = mbedtls_ct_size_gt( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = mbedtls_ct_uint_if( no_op, current, next ); + } + buf[total-1] = mbedtls_ct_uint_if( no_op, buf[total-1], 0 ); + } +} + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +void mbedtls_ct_memcpy_if_eq( unsigned char *dest, + const unsigned char *src, + size_t len, + size_t c1, + size_t c2 ) +{ + /* mask = c1 == c2 ? 0xff : 0x00 */ + const size_t equal = mbedtls_ct_size_bool_eq( c1, c2 ); + const unsigned char mask = (unsigned char) mbedtls_ct_size_mask( equal ); + + /* dest[i] = c1 == c2 ? src[i] : dest[i] */ + for( size_t i = 0; i < len; i++ ) + dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask ); +} + +void mbedtls_ct_memcpy_offset( unsigned char *dest, + const unsigned char *src, + size_t offset, + size_t offset_min, + size_t offset_max, + size_t len ) +{ + size_t offsetval; + + for( offsetval = offset_min; offsetval <= offset_max; offsetval++ ) + { + mbedtls_ct_memcpy_if_eq( dest, src + offsetval, len, + offsetval, offset ); + } +} + +int mbedtls_ct_hmac( mbedtls_md_context_t *ctx, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output ) +{ + /* + * This function breaks the HMAC abstraction and uses the md_clone() + * extension to the MD API in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. + * + * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to + * minlen, then cloning the context, and for each byte up to maxlen + * finishing up the hash computation, keeping only the correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info ); + /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5, + * all of which have the same block size except SHA-384. */ + const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; + const unsigned char * const ikey = ctx->hmac_ctx; + const unsigned char * const okey = ikey + block_size; + const size_t hash_size = mbedtls_md_get_size( ctx->md_info ); + + unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_context_t aux; + size_t offset; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &aux ); + +#define MD_CHK( func_call ) \ + do { \ + ret = (func_call); \ + if( ret != 0 ) \ + goto cleanup; \ + } while( 0 ) + + MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) ); + + /* After hmac_start() of hmac_reset(), ikey has already been hashed, + * so we can start directly with the message */ + MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) ); + MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) ); + + /* Fill the hash buffer in advance with something that is + * not a valid hash (barring an attack on the hash and + * deliberately-crafted input), in case the caller doesn't + * check the return status properly. */ + memset( output, '!', hash_size ); + + /* For each possible length, compute the hash up to that point */ + for( offset = min_data_len; offset <= max_data_len; offset++ ) + { + MD_CHK( mbedtls_md_clone( &aux, ctx ) ); + MD_CHK( mbedtls_md_finish( &aux, aux_out ) ); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ct_memcpy_if_eq( output, aux_out, hash_size, + offset, data_len_secret ); + + if( offset < max_data_len ) + MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) ); + } + + /* The context needs to finish() before it starts() again */ + MD_CHK( mbedtls_md_finish( ctx, aux_out ) ); + + /* Now compute HASH(okey + inner_hash) */ + MD_CHK( mbedtls_md_starts( ctx ) ); + MD_CHK( mbedtls_md_update( ctx, okey, block_size ) ); + MD_CHK( mbedtls_md_update( ctx, output, hash_size ) ); + MD_CHK( mbedtls_md_finish( ctx, output ) ); + + /* Done, get ready for next time */ + MD_CHK( mbedtls_md_hmac_reset( ctx ) ); + +#undef MD_CHK + +cleanup: + mbedtls_md_free( &aux ); + return( ret ); +} + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BIGNUM_C) + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103) +/* + * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: + * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 + */ +__declspec(noinline) +#endif +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, + const mbedtls_mpi *Y, + unsigned char assign ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint limb_mask; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */ + limb_mask = mbedtls_ct_mpi_uint_mask( assign );; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = mbedtls_ct_cond_select_sign( assign, Y->s, X->s ); + + mbedtls_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign ); + + for( i = Y->n; i < X->n; i++ ) + X->p[i] &= ~limb_mask; + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which would lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, + mbedtls_mpi *Y, + unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint limb_mask; + mbedtls_mpi_uint tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */ + limb_mask = mbedtls_ct_mpi_uint_mask( swap ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = mbedtls_ct_cond_select_sign( swap, Y->s, X->s ); + Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s ); + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask ); + Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask ); + } + +cleanup: + return( ret ); +} + +/* + * Compare signed values in constant time + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, + const mbedtls_mpi *Y, + unsigned *ret ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned cond, done, X_is_negative, Y_is_negative; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + MPI_VALIDATE_RET( ret != NULL ); + + if( X->n != Y->n ) + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* + * Set sign_N to 1 if N >= 0, 0 if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = ( X->s & 2 ) >> 1; + Y_is_negative = ( Y->s & 2 ) >> 1; + + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + cond = ( X_is_negative ^ Y_is_negative ); + *ret = cond & X_is_negative; + + /* + * This is a constant-time function. We might have the result, but we still + * need to go through the loop. Record if we have the result already. + */ + done = cond; + + for( i = X->n; i > 0; i-- ) + { + /* + * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both + * X and Y are negative. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_mpi_uint_lt( Y->p[i - 1], X->p[i - 1] ); + *ret |= cond & ( 1 - done ) & X_is_negative; + done |= cond; + + /* + * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both + * X and Y are positive. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_mpi_uint_lt( X->p[i - 1], Y->p[i - 1] ); + *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); + done |= cond; + } + + return( 0 ); +} + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +int mbedtls_ct_rsaes_pkcs1_v15_unpadding( int mode, + unsigned char *input, + size_t ilen, + unsigned char *output, + size_t output_max_len, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, plaintext_max_size; + + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + plaintext_max_size = ( output_max_len > ilen - 11 ) ? ilen - 11 + : output_max_len; + + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= input[0]; + + if( mode == MBEDTLS_RSA_PRIVATE ) + { + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= input[1] ^ MBEDTLS_RSA_CRYPT; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= ((input[i] | (unsigned char)-input[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + } + else + { + /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 + * where PS must be at least 8 bytes with the value 0xFF. */ + bad |= input[1] ^ MBEDTLS_RSA_SIGN; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. + * If there's a non-0xff byte in the padding, the padding is bad. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= mbedtls_ct_uint_if( input[i], 0, 1 ); + pad_count += mbedtls_ct_uint_if( pad_done, 0, 1 ); + bad |= mbedtls_ct_uint_if( pad_done, 0, input[i] ^ 0xFF ); + } + } + + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= mbedtls_ct_uint_if( pad_done, 0, 1 ); + + /* There must be at least 8 bytes of padding. */ + bad |= mbedtls_ct_size_gt( 8, pad_count ); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = mbedtls_ct_uint_if( + bad, (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = mbedtls_ct_size_gt( plaintext_size, + plaintext_max_size ); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) mbedtls_ct_uint_if( + bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + mbedtls_ct_uint_if( output_too_large, + - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = mbedtls_ct_uint_mask( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + input[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = mbedtls_ct_uint_if( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mbedtls_ct_mem_move_to_left( input + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros into the output + * buffer. If output_max_len is 0, then output may be an invalid pointer + * and the result of memcpy() would be undefined; prevent undefined + * behavior making sure to depend only on output_max_len (the size of the + * user-provided output buffer), which is independent from plaintext + * length, validity of padding, success of the decryption, and other + * secrets. */ + if( output_max_len != 0 ) + memcpy( output, input + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + + return( ret ); +} + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h new file mode 100644 index 0000000..a550b38 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_internal.h @@ -0,0 +1,336 @@ +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H +#define MBEDTLS_CONSTANT_TIME_INTERNAL_H + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl_internal.h" +#endif + +#include + + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (unsigned) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +unsigned mbedtls_ct_uint_mask( unsigned value ); + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (size_t) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +size_t mbedtls_ct_size_mask( size_t value ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BIGNUM_C) + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (mbedtls_mpi_uint) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value ); + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Constant-flow mask generation for "greater or equal" comparison: + * - if \p x >= \p y, return all-bits 1, that is (size_t) -1 + * - otherwise, return all bits 0, that is 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return All-bits-one if \p x is greater or equal than \p y, + * otherwise zero. + */ +size_t mbedtls_ct_size_mask_ge( size_t x, + size_t y ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +/** Constant-flow boolean "equal" comparison: + * return x == y + * + * This is equivalent to \p x == \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x equals to \p y, otherwise 0. + */ +unsigned mbedtls_ct_size_bool_eq( size_t x, + size_t y ); + +#if defined(MBEDTLS_BIGNUM_C) + +/** Decide if an integer is less than the other, without branches. + * + * This is equivalent to \p x < \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x is less than \p y, otherwise 0. + */ +unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ); + +#endif /* MBEDTLS_BIGNUM_C */ + +/** Choose between two integer values without branches. + * + * This is equivalent to `condition ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition is nonzero. + * \param if0 Value to use if \p condition is zero. + * + * \return \c if1 if \p condition is nonzero, otherwise \c if0. + */ +unsigned mbedtls_ct_uint_if( unsigned condition, + unsigned if1, + unsigned if0 ); + +#if defined(MBEDTLS_BIGNUM_C) + +/** Conditionally assign a value without branches. + * + * This is equivalent to `if ( condition ) dest = src`, but is likely + * to be compiled to code using bitwise operation rather than a branch. + * + * \param n \p dest and \p src must be arrays of limbs of size n. + * \param dest The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param src The MPI to be assigned from. This must point to an + * initialized MPI. + * \param condition Condition to test, must be 0 or 1. + */ +void mbedtls_ct_mpi_uint_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char condition ); + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BASE64_C) + +/** Given a value in the range 0..63, return the corresponding Base64 digit. + * + * The implementation assumes that letters are consecutive (e.g. ASCII + * but not EBCDIC). + * + * \param value A value in the range 0..63. + * + * \return A base64 digit converted from \p value. + */ +unsigned char mbedtls_ct_base64_enc_char( unsigned char value ); + +/** Given a Base64 digit, return its value. + * + * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'), + * return -1. + * + * The implementation assumes that letters are consecutive (e.g. ASCII + * but not EBCDIC). + * + * \param c A base64 digit. + * + * \return The value of the base64 digit \p c. + */ +signed char mbedtls_ct_base64_dec_value( unsigned char c ); + +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Conditional memcpy without branches. + * + * This is equivalent to `if ( c1 == c2 ) memcpy(dest, src, len)`, but is likely + * to be compiled to code using bitwise operation rather than a branch. + * + * \param dest The pointer to conditionally copy to. + * \param src The pointer to copy from. Shouldn't overlap with \p dest. + * \param len The number of bytes to copy. + * \param c1 The first value to analyze in the condition. + * \param c2 The second value to analyze in the condition. + */ +void mbedtls_ct_memcpy_if_eq( unsigned char *dest, + const unsigned char *src, + size_t len, + size_t c1, size_t c2 ); + +/** Copy data from a secret position with constant flow. + * + * This function copies \p len bytes from \p src_base + \p offset_secret to \p + * dst, with a code flow and memory access pattern that does not depend on \p + * offset_secret, but only on \p offset_min, \p offset_max and \p len. + * Functionally equivalent to `memcpy(dst, src + offset_secret, len)`. + * + * \note This function reads from \p dest, but the value that + * is read does not influence the result and this + * function's behavior is well-defined regardless of the + * contents of the buffers. This may result in false + * positives from static or dynamic analyzers, especially + * if \p dest is not initialized. + * + * \param dest The destination buffer. This must point to a writable + * buffer of at least \p len bytes. + * \param src The base of the source buffer. This must point to a + * readable buffer of at least \p offset_max + \p len + * bytes. Shouldn't overlap with \p dest. + * \param offset The offset in the source buffer from which to copy. + * This must be no less than \p offset_min and no greater + * than \p offset_max. + * \param offset_min The minimal value of \p offset. + * \param offset_max The maximal value of \p offset. + * \param len The number of bytes to copy. + */ +void mbedtls_ct_memcpy_offset( unsigned char *dest, + const unsigned char *src, + size_t offset, + size_t offset_min, + size_t offset_max, + size_t len ); + +/** Compute the HMAC of variable-length data with constant flow. + * + * This function computes the HMAC of the concatenation of \p add_data and \p + * data, and does with a code flow and memory access pattern that does not + * depend on \p data_len_secret, but only on \p min_data_len and \p + * max_data_len. In particular, this function always reads exactly \p + * max_data_len bytes from \p data. + * + * \param ctx The HMAC context. It must have keys configured + * with mbedtls_md_hmac_starts() and use one of the + * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. + * It is reset using mbedtls_md_hmac_reset() after + * the computation is complete to prepare for the + * next computation. + * \param add_data The first part of the message whose HMAC is being + * calculated. This must point to a readable buffer + * of \p add_data_len bytes. + * \param add_data_len The length of \p add_data in bytes. + * \param data The buffer containing the second part of the + * message. This must point to a readable buffer + * of \p max_data_len bytes. + * \param data_len_secret The length of the data to process in \p data. + * This must be no less than \p min_data_len and no + * greater than \p max_data_len. + * \param min_data_len The minimal length of the second part of the + * message, read from \p data. + * \param max_data_len The maximal length of the second part of the + * message, read from \p data. + * \param output The HMAC will be written here. This must point to + * a writable buffer of sufficient size to hold the + * HMAC value. + * + * \retval 0 on success. + * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED + * The hardware accelerator failed. + */ +int mbedtls_ct_hmac( mbedtls_md_context_t *ctx, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** This function performs the unpadding part of a PKCS#1 v1.5 decryption + * operation (EME-PKCS1-v1_5 decoding). + * + * \note The return value from this function is a sensitive value + * (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen + * in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING + * is often a situation that an attacker can provoke and leaking which + * one is the result is precisely the information the attacker wants. + * + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param input The input buffer which is the payload inside PKCS#1v1.5 + * encryption padding, called the "encoded message EM" + * by the terminology. + * \param ilen The length of the payload in the \p input buffer. + * \param output The buffer for the payload, called "message M" by the + * PKCS#1 terminology. This must be a writable buffer of + * length \p output_max_len bytes. + * \param olen The address at which to store the length of + * the payload. This must not be \c NULL. + * \param output_max_len The length in bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE + * The output buffer is too small for the unpadded payload. + * \return #MBEDTLS_ERR_RSA_INVALID_PADDING + * The input doesn't contain properly formatted padding. + */ +int mbedtls_ct_rsaes_pkcs1_v15_unpadding( int mode, + unsigned char *input, + size_t ilen, + unsigned char *output, + size_t output_max_len, + size_t *olen ); + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ + +#endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_invasive.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_invasive.h new file mode 100644 index 0000000..4620ca1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/constant_time_invasive.h @@ -0,0 +1,51 @@ +/** + * \file constant_time_invasive.h + * + * \brief Constant-time module: interfaces for invasive testing only. + * + * The interfaces in this file are intended for testing purposes only. + * They SHOULD NOT be made available in library integrations except when + * building the library for testing. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CONSTANT_TIME_INVASIVE_H +#define MBEDTLS_CONSTANT_TIME_INVASIVE_H + +#include "common.h" + +#if defined(MBEDTLS_TEST_HOOKS) + +/** Turn a value into a mask: + * - if \p low <= \p c <= \p high, + * return the all-bits 1 mask, aka (unsigned) -1 + * - otherwise, return the all-bits 0 mask, aka 0 + * + * \param low The value to analyze. + * \param high The value to analyze. + * \param c The value to analyze. + * + * \return All-bits-one if \p low <= \p c <= \p high, otherwise zero. + */ +unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low, + unsigned char high, + unsigned char c ); + +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* MBEDTLS_CONSTANT_TIME_INVASIVE_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c new file mode 100644 index 0000000..a00d66c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ctr_drbg.c @@ -0,0 +1,898 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The NIST SP 800-90 DRBGs are described in the following publication. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + /* Indicate that the entropy nonce length is not set explicitly. + * See mbedtls_ctr_drbg_set_nonce_len(). */ + ctx->reseed_counter = -1; + + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; +} + +/* + * This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + /* The mutex is initialized iff f_entropy is set. */ + if( ctx->f_entropy != NULL ) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + ctx->reseed_counter = -1; +} + +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ) +{ + ctx->entropy_len = len; +} + +int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, + size_t len ) +{ + /* If mbedtls_ctr_drbg_seed() has already been called, it's + * too late. Return the error code that's closest to making sense. */ + if( ctx->f_entropy != NULL ) + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + + if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); +#if SIZE_MAX > INT_MAX + /* This shouldn't be an issue because + * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible + * configuration, but make sure anyway. */ + if( len > INT_MAX ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); +#endif + + /* For backward compatibility with Mbed TLS <= 2.19, store the + * entropy nonce length in a field that already exists, but isn't + * used until after the initial seeding. */ + /* Due to the capping of len above, the value fits in an int. */ + ctx->reseed_counter = (int) len; + return( 0 ); +} + +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + mbedtls_aes_context aes_ctx; + int ret = 0; + + int i, j; + size_t buf_len, use_len; + + if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); + mbedtls_aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; + MBEDTLS_PUT_UINT32_BE( data_len, p, 0); + p += 4 + 3; + *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + + /* + * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? + MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; + + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, + chain, chain ) ) != 0 ) + { + goto exit; + } + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, + iv, iv ) ) != 0 ) + { + goto exit; + } + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } +exit: + mbedtls_aes_free( &aes_ctx ); + /* + * tidy up the stack + */ + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( chain, sizeof( chain ) ); + if( 0 != ret ) + { + /* + * wipe partial seed from memory + */ + mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + } + + return( ret ); +} + +/* CTR_DRBG_Update (SP 800-90A §10.2.1.2) + * ctr_drbg_update_internal(ctx, provided_data) + * implements + * CTR_DRBG_Update(provided_data, Key, V) + * with inputs and outputs + * ctx->aes_ctx = Key + * ctx->counter = V + */ +static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + int ret = 0; + + memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, + ctx->counter, p ) ) != 0 ) + { + goto exit; + } + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, + MBEDTLS_CTR_DRBG_BLOCKSIZE ); + +exit: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_update(ctx, additional, add_len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * ctx->counter = all-bits-0 + * ctx->aes_ctx = context from all-bits-0 key + * additional[:add_len] = entropy_input || nonce || personalization_string + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( add_len == 0 ) + return( 0 ); + + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) + * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) + * -> new_working_state + * with inputs + * ctx contains working_state + * additional[:len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * for (ctx->entropy_len + nonce_len) bytes + * and with output + * ctx contains new_working_state + */ +static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t len, + size_t nonce_len ) +{ + unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + + /* Gather entropy_len bytes of entropy to seed state. */ + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += ctx->entropy_len; + + /* Gather entropy for a nonce if requested. */ + if( nonce_len != 0 ) + { + if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += nonce_len; + } + + /* Add additional data if provided. */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* Reduce to 384 bits. */ + if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) + goto exit; + + /* Update state. */ + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + goto exit; + ctx->reseed_counter = 1; + +exit: + mbedtls_platform_zeroize( seed, sizeof( seed ) ); + return( ret ); +} + +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) ); +} + +/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length + * is sufficient to achieve the maximum security strength given the key + * size and entropy length. If there is enough entropy in the initial + * call to the entropy function to serve as both the entropy input and + * the nonce, don't make a second call to get a nonce. */ +static size_t good_nonce_len( size_t entropy_len ) +{ + if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 ) + return( 0 ); + else + return( ( entropy_len + 1 ) / 2 ); +} + +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * custom[:len] = nonce || personalization_string + * where entropy_input comes from f_entropy for ctx->entropy_len bytes + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + size_t nonce_len; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + /* The mutex is initialized iff f_entropy is set. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; + /* ctx->reseed_counter contains the desired amount of entropy to + * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). + * If it's -1, indicating that the entropy nonce length was not set + * explicitly, use a sufficiently large nonce for security. */ + nonce_len = ( ctx->reseed_counter >= 0 ? + (size_t) ctx->reseed_counter : + good_nonce_len( ctx->entropy_len ) ); + + /* Initialize with an empty key. */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + /* Do the initial seeding. */ + if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len, + nonce_len ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) + * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) + * -> working_state_after_reseed + * if required, then + * CTR_DRBG_Generate(working_state_after_reseed, + * requested_number_of_bits, additional_input) + * -> status, returned_bits, new_working_state + * with inputs + * ctx contains working_state + * requested_number_of_bits = 8 * output_len + * additional[:add_len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with outputs + * status = SUCCESS (this function does the reseed internally) + * returned_bits = output[:output_len] + * ctx contains new_working_state + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = 0; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + { + return( ret ); + } + add_len = 0; + } + + if( add_len > 0 ) + { + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + } + + while( output_len > 0 ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, + ctx->counter, tmp ) ) != 0 ) + { + goto exit; + } + + use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) + ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; + /* + * Copy random block to destination + */ + memcpy( p, tmp, use_len ); + p += use_len; + output_len -= use_len; + } + + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + + ctx->reseed_counter++; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, + size_t output_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, + const char *path ) +{ + int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, + MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != + MBEDTLS_CTR_DRBG_MAX_INPUT ) + { + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + } + else + { + ret = 0; + } + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, + const char *path ) +{ + int ret = 0; + FILE *f = NULL; + size_t n; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + unsigned char c; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) + { + ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; + goto exit; + } + if( n == 0 || ferror( f ) ) + { + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + goto exit; + } + fclose( f ); + f = NULL; + + ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); + return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +/* The CTR_DRBG NIST test vectors used here are available at + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip + * + * The parameters used to derive the test data are: + * + * [AES-128 use df] + * [PredictionResistance = True/False] + * [EntropyInputLen = 128] + * [NonceLen = 64] + * [PersonalizationStringLen = 128] + * [AdditionalInputLen = 0] + * [ReturnedBitsLen = 512] + * + * [AES-256 use df] + * [PredictionResistance = True/False] + * [EntropyInputLen = 256] + * [NonceLen = 128] + * [PersonalizationStringLen = 256] + * [AdditionalInputLen = 0] + * [ReturnedBitsLen = 512] + * + */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +static const unsigned char entropy_source_pr[] = + { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, + 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, + 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, + 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, + 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, + 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, + 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; + +static const unsigned char entropy_source_nopr[] = + { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, + 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, + 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, + 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, + 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; + +static const unsigned char pers_pr[] = + { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, + 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; + +static const unsigned char pers_nopr[] = + { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, + 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; + +static const unsigned char result_pr[] = + { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, + 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, + 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, + 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, + 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, + 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, + 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, + 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; + +static const unsigned char result_nopr[] = + { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, + 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, + 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, + 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, + 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, + 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, + 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, + 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; +#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ + +static const unsigned char entropy_source_pr[] = + { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, + 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, + 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, + 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, + 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, + 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, + 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, + 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, + 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, + 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, + 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, + 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, + 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, + 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; + +static const unsigned char entropy_source_nopr[] = + { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, + 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, + 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, + 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, + 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, + 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, + 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, + 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, + 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, + 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; + +static const unsigned char pers_pr[] = + { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, + 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, + 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, + 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; + +static const unsigned char pers_nopr[] = + { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, + 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, + 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, + 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; + +static const unsigned char result_pr[] = + { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, + 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, + 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, + 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, + 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, + 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, + 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, + 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; + +static const unsigned char result_nopr[] = + { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, + 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, + 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, + 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, + 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, + 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, + 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, + 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ + +static size_t test_offset; +static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, + size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64 + +/* + * Checkup routine + */ +int mbedtls_ctr_drbg_self_test( int verbose ) +{ + mbedtls_ctr_drbg_context ctx; + unsigned char buf[ sizeof( result_pr ) ]; + + mbedtls_ctr_drbg_init( &ctx ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE ); + mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, + pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); + mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) ); + CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); + + mbedtls_ctr_drbg_init( &ctx ); + + test_offset = 0; + mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE); + mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, + pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); + CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) ); + CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CTR_DRBG_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c new file mode 100644 index 0000000..e108600 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/debug.c @@ -0,0 +1,422 @@ +/* + * Debugging routines + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time_t time_t +#define mbedtls_snprintf snprintf +#define mbedtls_vsnprintf vsnprintf +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define DEBUG_BUF_SIZE 512 + +static int debug_threshold = 0; + +void mbedtls_debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +/* + * All calls to f_dbg must be made via this function + */ +static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *str ) +{ + /* + * If in a threaded environment, we need a thread identifier. + * Since there is no portable way to get one, use the address of the ssl + * context instead, as it shouldn't be shared between threads. + */ +#if defined(MBEDTLS_THREADING_C) + char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ + mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); +#else + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); +#endif +} + +MBEDTLS_PRINTF_ATTRIBUTE(5, 6) +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) +{ + va_list argp; + char str[DEBUG_BUF_SIZE]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + va_start( argp, format ); + ret = mbedtls_vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); + va_end( argp ); + + if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) + { + str[ret] = '\n'; + str[ret + 1] = '\0'; + } + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ) +{ + char str[DEBUG_BUF_SIZE]; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + /* + * With non-blocking I/O and examples that just retry immediately, + * the logs would be quickly flooded with WANT_READ, so ignore that. + * Don't ignore WANT_WRITE however, since is is usually rare. + */ + if( ret == MBEDTLS_ERR_SSL_WANT_READ ) + return; + + mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", + text, ret, (unsigned int) -ret ); + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ) +{ + char str[DEBUG_BUF_SIZE]; + char txt[17]; + size_t i, idx = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", + text, (unsigned int) len ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + for( i = 0; i < len; i++ ) + { + if( i >= 4096 ) + break; + + if( i % 16 == 0 ) + { + if( i > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", + (unsigned int) i ); + + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", + (unsigned int) buf[i] ); + txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; + } + + if( len > 0 ) + { + for( /* i = i */; i % 16 != 0; i++ ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + } +} + +#if defined(MBEDTLS_ECP_C) +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ) +{ + char str[DEBUG_BUF_SIZE]; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); + + mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_BIGNUM_C) +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ) +{ + char str[DEBUG_BUF_SIZE]; + size_t bitlen; + size_t idx = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == X || + level > debug_threshold ) + { + return; + } + + bitlen = mbedtls_mpi_bitlen( X ); + + mbedtls_snprintf( str, sizeof( str ), "value of '%s' (%u bits) is:\n", + text, (unsigned) bitlen ); + debug_send_line( ssl, level, file, line, str ); + + if( bitlen == 0 ) + { + str[0] = ' '; str[1] = '0'; str[2] = '0'; + idx = 3; + } + else + { + int n; + for( n = (int) ( ( bitlen - 1 ) / 8 ); n >= 0; n-- ) + { + size_t limb_offset = n / sizeof( mbedtls_mpi_uint ); + size_t offset_in_limb = n % sizeof( mbedtls_mpi_uint ); + unsigned char octet = + ( X->p[limb_offset] >> ( offset_in_limb * 8 ) ) & 0xff; + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", octet ); + idx += 3; + /* Wrap lines after 16 octets that each take 3 columns */ + if( idx >= 3 * 16 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); + idx = 0; + } + } + } + + if( idx != 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); + } +} +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_pk_context *pk ) +{ + size_t i; + mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset( items, 0, sizeof( items ) ); + + if( mbedtls_pk_debug( pk, items ) != 0 ) + { + debug_send_line( ssl, level, file, line, + "invalid PK context\n" ); + return; + } + + for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) + { + if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) + return; + + mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); + name[sizeof( name ) - 1] = '\0'; + + if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) + mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); + else +#if defined(MBEDTLS_ECP_C) + if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) + mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); + else +#endif + debug_send_line( ssl, level, file, line, + "should not happen\n" ); + } +} + +static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text ) +{ + char str[DEBUG_BUF_SIZE]; + const char *start, *cur; + + start = text; + for( cur = text; *cur != '\0'; cur++ ) + { + if( *cur == '\n' ) + { + size_t len = cur - start + 1; + if( len > DEBUG_BUF_SIZE - 1 ) + len = DEBUG_BUF_SIZE - 1; + + memcpy( str, start, len ); + str[len] = '\0'; + + debug_send_line( ssl, level, file, line, str ); + + start = cur + 1; + } + } +} + +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ) +{ + char str[DEBUG_BUF_SIZE]; + int i = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == crt || + level > debug_threshold ) + { + return; + } + + while( crt != NULL ) + { + char buf[1024]; + + mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); + debug_send_line( ssl, level, file, line, str ); + + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + debug_print_line_by_line( ssl, level, file, line, buf ); + + debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); + + crt = crt->next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_ECDH_C) +static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl, + int level, const char *file, + int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + const mbedtls_ecdh_context* ctx = ecdh; +#else + const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh; +#endif + + switch( attr ) + { + case MBEDTLS_DEBUG_ECDH_Q: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q", + &ctx->Q ); + break; + case MBEDTLS_DEBUG_ECDH_QP: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp", + &ctx->Qp ); + break; + case MBEDTLS_DEBUG_ECDH_Z: + mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z", + &ctx->z ); + break; + default: + break; + } +} + +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr ); +#else + switch( ecdh->var ) + { + default: + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, + attr ); + } +#endif +} +#endif /* MBEDTLS_ECDH_C */ + +#endif /* MBEDTLS_DEBUG_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/des.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/des.c new file mode 100644 index 0000000..91d22b5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/des.c @@ -0,0 +1,1062 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_DES_C) + +#include "mbedtls/des.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_DES_ALT) + +/* + * Expanded DES S-boxes + */ +static const uint32_t SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const uint32_t SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const uint32_t SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const uint32_t SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const uint32_t SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const uint32_t SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const uint32_t SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const uint32_t SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const uint32_t LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const uint32_t RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ + do \ + { \ + T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ + T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ + T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ + T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ + (Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF; \ + T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T; \ + (X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF; \ + } while( 0 ) + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ + do \ + { \ + (X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF; \ + T = ((X) ^ (Y)) & 0xAAAAAAAA; (X) ^= T; (Y) ^= T; \ + (Y) = (((Y) << 31) | ((Y) >> 1)) & 0xFFFFFFFF; \ + T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ + T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ + T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ + T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ + } while( 0 ) + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ + do \ + { \ + T = *SK++ ^ (X); \ + (Y) ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ (((X) << 28) | ((X) >> 4)); \ + (Y) ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ + } while( 0 ) + +#define SWAP(a,b) \ + do \ + { \ + uint32_t t = (a); (a) = (b); (b) = t; t = 0; \ + } while( 0 ) + +void mbedtls_des_init( mbedtls_des_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des_free( mbedtls_des_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des3_init( mbedtls_des3_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des3_context ) ); +} + +void mbedtls_des3_free( mbedtls_des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) ); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + key[i] = odd_parity_table[key[i] / 2]; +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DES_SETKEY_ALT) +void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + uint32_t X, Y, T; + + X = MBEDTLS_GET_UINT32_BE( key, 0 ); + Y = MBEDTLS_GET_UINT32_BE( key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} +#endif /* !MBEDTLS_DES_SETKEY_ALT */ + +/* + * DES key schedule (56-bit, encryption) + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + mbedtls_des_setkey( ctx->sk, key ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + mbedtls_des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } + + return( 0 ); +} + +static void des3_set2key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[30 - i]; + dsk[i + 1] = esk[31 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + esk[i + 64] = esk[i ]; + esk[i + 65] = esk[i + 1]; + + dsk[i + 64] = dsk[i ]; + dsk[i + 65] = dsk[i + 1]; + } +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +static void des3_set3key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[24] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + mbedtls_des_setkey( esk + 64, key + 16 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[94 - i]; + dsk[i + 1] = esk[95 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + dsk[i + 64] = esk[30 - i]; + dsk[i + 65] = esk[31 - i]; + } +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + X = MBEDTLS_GET_UINT32_BE( input, 0 ); + Y = MBEDTLS_GET_UINT32_BE( input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + MBEDTLS_PUT_UINT32_BE( Y, output, 0 ); + MBEDTLS_PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + ret = mbedtls_des_crypt_ecb( ctx, output, output ); + if( ret != 0 ) + goto exit; + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + ret = mbedtls_des_crypt_ecb( ctx, input, output ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + X = MBEDTLS_GET_UINT32_BE( input, 0 ); + Y = MBEDTLS_GET_UINT32_BE( input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( X, Y ); + DES_ROUND( Y, X ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + MBEDTLS_PUT_UINT32_BE( Y, output, 0 ); + MBEDTLS_PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + ret = mbedtls_des3_crypt_ecb( ctx, output, output ); + if( ret != 0 ) + goto exit; + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + ret = mbedtls_des3_crypt_ecb( ctx, input, output ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#endif /* !MBEDTLS_DES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * DES and 3DES test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip + */ +static const unsigned char des3_test_keys[24] = +{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 +}; + +static const unsigned char des3_test_buf[8] = +{ + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 +}; + +static const unsigned char des3_test_ecb_dec[3][8] = +{ + { 0x37, 0x2B, 0x98, 0xBF, 0x52, 0x65, 0xB0, 0x59 }, + { 0xC2, 0x10, 0x19, 0x9C, 0x38, 0x5A, 0x65, 0xA1 }, + { 0xA2, 0x70, 0x56, 0x68, 0x69, 0xE5, 0x15, 0x1D } +}; + +static const unsigned char des3_test_ecb_enc[3][8] = +{ + { 0x1C, 0xD5, 0x97, 0xEA, 0x84, 0x26, 0x73, 0xFB }, + { 0xB3, 0x92, 0x4D, 0xF3, 0xC5, 0xB5, 0x42, 0x93 }, + { 0xDA, 0x37, 0x64, 0x41, 0xBA, 0x6F, 0x62, 0x6F } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char des3_test_iv[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, +}; + +static const unsigned char des3_test_cbc_dec[3][8] = +{ + { 0x58, 0xD9, 0x48, 0xEF, 0x85, 0x14, 0x65, 0x9A }, + { 0x5F, 0xC8, 0x78, 0xD4, 0xD7, 0x92, 0xD9, 0x54 }, + { 0x25, 0xF9, 0x75, 0x85, 0xA8, 0x1E, 0x48, 0xBF } +}; + +static const unsigned char des3_test_cbc_enc[3][8] = +{ + { 0x91, 0x1C, 0x6D, 0xCF, 0x48, 0xA7, 0xC3, 0x4D }, + { 0x60, 0x1A, 0x76, 0x8F, 0xA1, 0xF9, 0x66, 0xF1 }, + { 0xA1, 0x50, 0x0F, 0x99, 0xB2, 0xCD, 0x64, 0x76 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int mbedtls_des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + mbedtls_des_context ctx; + mbedtls_des3_context ctx3; + unsigned char buf[8]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + mbedtls_des_init( &ctx ); + mbedtls_des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + if( ret != 0 ) + goto exit; + + for( j = 0; j < 100; j++ ) + { + if( u == 0 ) + ret = mbedtls_des_crypt_ecb( &ctx, buf, buf ); + else + ret = mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); + if( ret != 0 ) + goto exit; + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, des3_test_iv, 8 ); + memcpy( prv, des3_test_iv, 8 ); + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + if( ret != 0 ) + goto exit; + + if( v == MBEDTLS_DES_DECRYPT ) + { + for( j = 0; j < 100; j++ ) + { + if( u == 0 ) + ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + if( ret != 0 ) + goto exit; + } + } + else + { + for( j = 0; j < 100; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + memcpy( tmp, prv, 8 ); + memcpy( prv, buf, 8 ); + memcpy( buf, tmp, 8 ); + } + + memcpy( buf, prv, 8 ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_des_free( &ctx ); + mbedtls_des3_free( &ctx3 ); + + if( ret != 0 ) + ret = 1; + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DES_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c new file mode 100644 index 0000000..88e148b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/dhm.c @@ -0,0 +1,719 @@ +/* + * Diffie-Hellman-Merkle key exchange + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The following sources were referenced in the design of this implementation + * of the Diffie-Hellman-Merkle algorithm: + * + * [1] Handbook of Applied Cryptography - 1997, Chapter 12 + * Menezes, van Oorschot and Vanstone + * + */ + +#include "common.h" + +#if defined(MBEDTLS_DHM_C) + +#include "mbedtls/dhm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +#define DHM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA ) +#define DHM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * helper to validate the mbedtls_mpi size and import it + */ +static int dhm_read_bignum( mbedtls_mpi *X, + unsigned char **p, + const unsigned char *end ) +{ + int ret, n; + + if( end - *p < 2 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + n = ( (*p)[0] << 8 ) | (*p)[1]; + (*p) += 2; + + if( (int)( end - *p ) < n ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret ) ); + + (*p) += n; + + return( 0 ); +} + +/* + * Verify sanity of parameter with regards to P + * + * Parameter should be: 2 <= public_param <= P - 2 + * + * This means that we need to return an error if + * public_param < 2 or public_param > P-2 + * + * For more information on the attack, see: + * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf + * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 + */ +static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) +{ + mbedtls_mpi U; + int ret = 0; + + mbedtls_mpi_init( &U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); + + if( mbedtls_mpi_cmp_int( param, 2 ) < 0 || + mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) + { + ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + +cleanup: + mbedtls_mpi_free( &U ); + return( ret ); +} + +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) +{ + DHM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( p != NULL && *p != NULL ); + DHM_VALIDATE_RET( end != NULL ); + + if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) + return( ret ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + ctx->len = mbedtls_mpi_size( &ctx->P ); + + return( 0 ); +} + +/* + * Pick a random R in the range [2, M-2] for blinding or key generation. + */ +static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) ); + +cleanup: + return( ret ); +} + +static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + if( x_size < 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + } + else + { + /* Generate X as large as possible ( <= P - 2 ) */ + ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng ); + if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); + if( ret != 0 ) + return( ret ); + } + + /* + * Calculate GX = G^X mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + +cleanup: + return( ret ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t n1, n2, n3; + unsigned char *p; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + ret = dhm_make_common( ctx, x_size, f_rng, p_rng ); + if( ret != 0 ) + goto cleanup; + + /* + * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are + * not required". We omit leading zeros for compactness. + */ +#define DHM_MPI_EXPORT( X, n ) \ + do { \ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ + p + 2, \ + ( n ) ) ); \ + *p++ = MBEDTLS_BYTE_1( n ); \ + *p++ = MBEDTLS_BYTE_0( n ); \ + p += ( n ); \ + } while( 0 ) + + n1 = mbedtls_mpi_size( &ctx->P ); + n2 = mbedtls_mpi_size( &ctx->G ); + n3 = mbedtls_mpi_size( &ctx->GX ); + + p = output; + DHM_MPI_EXPORT( &ctx->P , n1 ); + DHM_MPI_EXPORT( &ctx->G , n2 ); + DHM_MPI_EXPORT( &ctx->GX, n3 ); + + *olen = p - output; + + ctx->len = n1; + +cleanup: + if( ret != 0 && ret > -128 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret ); + return( ret ); +} + +/* + * Set prime modulus and generator + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( P != NULL ); + DHM_VALIDATE_RET( G != NULL ); + + if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) ); + } + + ctx->len = mbedtls_mpi_size( &ctx->P ); + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( input != NULL ); + + if( ilen < 1 || ilen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + if( olen < 1 || olen > ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + ret = dhm_make_common( ctx, x_size, f_rng, p_rng ); + if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); + if( ret != 0 ) + goto cleanup; + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + if( ret != 0 && ret > -128 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret ); + return( ret ); +} + + +/* + * Use the blinding method and optimisation suggested in section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int dhm_update_blinding( mbedtls_dhm_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + /* + * Don't use any blinding the first time a particular X is used, + * but remember it to use blinding next time. + */ + if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); + + return( 0 ); + } + + /* + * Ok, we need blinding. Can we re-use existing values? + * If yes, just update them by squaring them. + */ + if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + return( 0 ); + } + + /* + * We need to generate blinding values from scratch + */ + + /* Vi = random( 2, P-2 ) */ + MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) ); + + /* Vf = Vi^-X mod P + * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), + * then elevate to the Xth power. */ + MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Derive and export the shared secret (G^Y)^X mod P + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi GYb; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + + if( output_size < ctx->len ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mbedtls_mpi_init( &GYb ); + + /* Blind peer's value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); + + /* Do modular exponentiation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + if( f_rng != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + } + + /* Output the secret without any leading zero byte. This is mandatory + * for TLS per RFC 5246 §8.1.2. */ + *olen = mbedtls_mpi_size( &ctx->K ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mbedtls_mpi_free( &GYb ); + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->pX ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->K ); + mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); + mbedtls_mpi_free( &ctx->X ); + mbedtls_mpi_free( &ctx->G ); + mbedtls_mpi_free( &ctx->P ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); +} + +#if defined(MBEDTLS_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end; +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_context pem; +#endif /* MBEDTLS_PEM_PARSE_C */ + + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( dhmin != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN DH PARAMETERS-----", + "-----END DH PARAMETERS-----", + dhmin, NULL, 0, &dhminlen ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + dhminlen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* MBEDTLS_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * privateValueLength INTEGER OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret ); + goto exit; + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret ); + goto exit; + } + + if( p != end ) + { + /* This might be the optional privateValueLength. + * If so, we can cleanly discard it */ + mbedtls_mpi rec; + mbedtls_mpi_init( &rec ); + ret = mbedtls_asn1_get_mpi( &p, end, &rec ); + mbedtls_mpi_free( &rec ); + if ( ret != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret ); + goto exit; + } + if ( p != end ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + goto exit; + } + } + + ret = 0; + + dhm->len = mbedtls_mpi_size( &dhm->P ); + +exit: +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + if( ret != 0 ) + mbedtls_dhm_free( dhm ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n + 1 ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse DHM parameters + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( path != NULL ); + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_DHM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PEM_PARSE_C) +static const char mbedtls_test_dhm_params[] = +"-----BEGIN DH PARAMETERS-----\r\n" +"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" +"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" +"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" +"-----END DH PARAMETERS-----\r\n"; +#else /* MBEDTLS_PEM_PARSE_C */ +static const char mbedtls_test_dhm_params[] = { + 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44, + 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d, + 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3, + 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1, + 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18, + 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a, + 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1, + 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6, + 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64, + 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8, + 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f, + 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 }; +#endif /* MBEDTLS_PEM_PARSE_C */ + +static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); + +/* + * Checkup routine + */ +int mbedtls_dhm_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_dhm_context dhm; + + mbedtls_dhm_init( &dhm ); + + if( verbose != 0 ) + mbedtls_printf( " DHM parameter load: " ); + + if( ( ret = mbedtls_dhm_parse_dhm( &dhm, + (const unsigned char *) mbedtls_test_dhm_params, + mbedtls_test_dhm_params_len ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + +exit: + mbedtls_dhm_free( &dhm ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DHM_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c new file mode 100644 index 0000000..60c6e42 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecdh.c @@ -0,0 +1,729 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#include "common.h" + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/ecdh.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +/* Parameter validation macros based on platform_util.h */ +#define ECDH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; +#endif + +static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( + const mbedtls_ecdh_context *ctx ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ctx->grp.id ); +#else + return( ctx->grp_id ); +#endif +} + +int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ) +{ + /* At this time, all groups support ECDH. */ + (void) gid; + return( 1 ); +} + +#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) +/* + * Generate public key (restartable version) + * + * Note: this internal function relies on its caller preserving the value of + * the output parameter 'd' across continuation calls. This would not be + * acceptable for a public function but is OK here as we control call sites. + */ +static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* If multiplication is in progress, we already generated a privkey */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + return( ret ); +} + +/* + * Generate public key + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ + +#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) +/* + * Compute shared secret (SEC1 3.3.1) + */ +static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point P; + + mbedtls_ecp_point_init( &P ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, + f_rng, p_rng, rs_ctx ) ); + + if( mbedtls_ecp_is_zero( &P ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); + +cleanup: + mbedtls_ecp_point_free( &P ); + + return( ret ); +} + +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( z != NULL ); + return( ecdh_compute_shared_restartable( grp, z, Q, d, + f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_init( &ctx->grp ); + mbedtls_mpi_init( &ctx->d ); + mbedtls_ecp_point_init( &ctx->Q ); + mbedtls_ecp_point_init( &ctx->Qp ); + mbedtls_mpi_init( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_init( &ctx->rs ); +#endif +} + +/* + * Initialize context + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + ecdh_init_internal( ctx ); + mbedtls_ecp_point_init( &ctx->Vi ); + mbedtls_ecp_point_init( &ctx->Vf ); + mbedtls_mpi_init( &ctx->_d ); +#else + memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); + + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; +#endif + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + ctx->restart_enabled = 0; +#endif +} + +static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, + mbedtls_ecp_group_id grp_id ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); + if( ret != 0 ) + { + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +/* + * Setup context + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_setup_internal( ctx, grp_id ) ); +#else + switch( grp_id ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST; + ctx->grp_id = grp_id; + return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) ); +#endif + default: + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; + ctx->grp_id = grp_id; + ecdh_init_internal( &ctx->ctx.mbed_ecdh ); + return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); + } +#endif +} + +static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_mpi_free( &ctx->d ); + mbedtls_ecp_point_free( &ctx->Q ); + mbedtls_ecp_point_free( &ctx->Qp ); + mbedtls_mpi_free( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_free( &ctx->rs ); +#endif +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Enable restartable operations for context + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + + ctx->restart_enabled = 1; +} +#endif + +/* + * Free context + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_point_free( &ctx->Vi ); + mbedtls_ecp_point_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->_d ); + ecdh_free_internal( ctx ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + mbedtls_everest_free( &ctx->ctx.everest_ecdh ); + break; +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + ecdh_free_internal( &ctx->ctx.mbed_ecdh ); + break; + default: + break; + } + + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; + ctx->grp_id = MBEDTLS_ECP_DP_NONE; +#endif +} + +static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t grp_len, pt_len; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, + blen ) ) != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, + &pt_len, buf, blen ) ) != 0 ) + return( ret ); + + *olen = grp_len + pt_len; + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, + end - *buf ) ); +} + +/* + * Read the ServerKeyExchange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( *buf != NULL ); + ECDH_VALIDATE_RET( end != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) + != 0 ) + return( ret ); + + if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_params_internal( ctx, buf, end ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh, + buf, end) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, + buf, end ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* If it's not our key, just import the public part as Qp */ + if( side == MBEDTLS_ECDH_THEIRS ) + return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); + + /* Our key: import public (as Q) and private parts */ + if( side != MBEDTLS_ECDH_OURS ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Get parameters from a keypair + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( key != NULL ); + ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || + side == MBEDTLS_ECDH_THEIRS ); + + if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE ) + { + /* This is the first call to get_params(). Set up the context + * for use with the group. */ + if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) + return( ret ); + } + else + { + /* This is not the first call to get_params(). Check that the + * current key's group is the same as the context's, which was set + * from the first key's group. */ + if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_get_params_internal( ctx, key, side ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + { + mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ? + MBEDTLS_EVEREST_ECDH_OURS : + MBEDTLS_EVEREST_ECDH_THEIRS; + return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh, + key, s) ); + } +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, + key, side ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, + buf, blen ); +} + +/* + * Setup and export the client public value + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, + blen ) ) != 0 ) + return( ret ); + + if( (size_t)( p - buf ) != blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Parse and import the client's public value + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_public_internal( ctx, buf, blen ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh, + buf, blen ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, + buf, blen ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, unsigned char *buf, + size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng, + rs_ctx ) ) != 0 ) + { + return( ret ); + } +#else + if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( mbedtls_mpi_size( &ctx->z ) > blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); + + if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen ); + + return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); +} + +/* + * Derive and export the shared secret + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, + restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, + blen, f_rng, p_rng, + restart_enabled ) ); + default: + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } +#endif +} + +#endif /* MBEDTLS_ECDH_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c new file mode 100644 index 0000000..640eb24 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c @@ -0,0 +1,1012 @@ +/* + * Elliptic curve DSA + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#include "common.h" + +#if defined(MBEDTLS_ECDSA_C) + +#include "mbedtls/ecdsa.h" +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +/* Parameter validation macros based on platform_util.h */ +#define ECDSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/* + * Sub-context for ecdsa_verify() + */ +struct mbedtls_ecdsa_restart_ver +{ + mbedtls_mpi u1, u2; /* intermediate values */ + enum { /* what to do next? */ + ecdsa_ver_init = 0, /* getting started */ + ecdsa_ver_muladd, /* muladd step */ + } state; +}; + +/* + * Init verify restart sub-context + */ +static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + mbedtls_mpi_init( &ctx->u1 ); + mbedtls_mpi_init( &ctx->u2 ); + ctx->state = ecdsa_ver_init; +} + +/* + * Free the components of a verify restart sub-context + */ +static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->u1 ); + mbedtls_mpi_free( &ctx->u2 ); + + ecdsa_restart_ver_init( ctx ); +} + +/* + * Sub-context for ecdsa_sign() + */ +struct mbedtls_ecdsa_restart_sig +{ + int sign_tries; + int key_tries; + mbedtls_mpi k; /* per-signature random */ + mbedtls_mpi r; /* r value */ + enum { /* what to do next? */ + ecdsa_sig_init = 0, /* getting started */ + ecdsa_sig_mul, /* doing ecp_mul() */ + ecdsa_sig_modn, /* mod N computations */ + } state; +}; + +/* + * Init verify sign sub-context + */ +static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + ctx->sign_tries = 0; + ctx->key_tries = 0; + mbedtls_mpi_init( &ctx->k ); + mbedtls_mpi_init( &ctx->r ); + ctx->state = ecdsa_sig_init; +} + +/* + * Free the components of a sign restart sub-context + */ +static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->k ); + mbedtls_mpi_free( &ctx->r ); +} + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Sub-context for ecdsa_sign_det() + */ +struct mbedtls_ecdsa_restart_det +{ + mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ + enum { /* what to do next? */ + ecdsa_det_init = 0, /* getting started */ + ecdsa_det_sign, /* make signature */ + } state; +}; + +/* + * Init verify sign_det sub-context + */ +static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + mbedtls_hmac_drbg_init( &ctx->rng_ctx ); + ctx->state = ecdsa_det_init; +} + +/* + * Free the components of a sign_det restart sub-context + */ +static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_hmac_drbg_free( &ctx->rng_ctx ); + + ecdsa_restart_det_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#define ECDSA_RS_ECP ( rs_ctx == NULL ? NULL : &rs_ctx->ecp ) + +/* Utility macro for checking and updating ops budget */ +#define ECDSA_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, ECDSA_RS_ECP, ops ) ); + +/* Call this when entering a function that needs its own sub-context */ +#define ECDSA_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ + rs_ctx->ecp.ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECDSA_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->ecp.depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECDSA_RS_ECP NULL + +#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ + +#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx +#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \ + !defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Derive a suitable integer for group grp from a buffer of length len + * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 + */ +static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, + const unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n_size = ( grp->nbits + 7 ) / 8; + size_t use_size = blen > n_size ? n_size : blen; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); + +cleanup: + return( ret ); +} +#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */ + +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/* + * Compute ECDSA signature of a hashed message (SEC1 4.1.3) + * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) + */ +static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret, key_tries, sign_tries; + int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; + mbedtls_ecp_point R; + mbedtls_mpi k, e, t; + mbedtls_mpi *pk = &k, *pr = r; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* Make sure d is in range 1..n-1 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); + + ECDSA_RS_ENTER( sig ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + { + /* redirect to our context */ + p_sign_tries = &rs_ctx->sig->sign_tries; + p_key_tries = &rs_ctx->sig->key_tries; + pk = &rs_ctx->sig->k; + pr = &rs_ctx->sig->r; + + /* jump to current step */ + if( rs_ctx->sig->state == ecdsa_sig_mul ) + goto mul; + if( rs_ctx->sig->state == ecdsa_sig_modn ) + goto modn; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + *p_sign_tries = 0; + do + { + if( (*p_sign_tries)++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + /* + * Steps 1-3: generate a suitable ephemeral keypair + * and set r = xR mod n + */ + *p_key_tries = 0; + do + { + if( (*p_key_tries)++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_mul; + +mul: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, + f_rng_blind, + p_rng_blind, + ECDSA_RS_ECP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); + } + while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_modn; + +modn: +#endif + /* + * Accounting for everything up to the end of the loop + * (step 6, but checking now avoids saving e and t) + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); + + /* + * Step 5: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Generate a random value to blind inv_mod in next step, + * avoiding a potential timing leak. + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind, + p_rng_blind ) ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); + } + while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + mbedtls_mpi_copy( r, pr ); +#endif + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + + ECDSA_RS_LEAVE( sig ); + + return( ret ); +} + +int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid ) +{ + switch( gid ) + { +#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED + case MBEDTLS_ECP_DP_CURVE25519: return 0; +#endif +#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED + case MBEDTLS_ECP_DP_CURVE448: return 0; +#endif + default: return 1; + } +} + +/* + * Compute ECDSA signature of a hashed message + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + /* Use the same RNG for both blinding and ephemeral key generation */ + return( ecdsa_sign_restartable( grp, r, s, d, buf, blen, + f_rng, p_rng, f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + */ +static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context rng_ctx; + mbedtls_hmac_drbg_context *p_rng = &rng_ctx; + unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const mbedtls_md_info_t *md_info; + mbedtls_mpi h; + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &h ); + mbedtls_hmac_drbg_init( &rng_ctx ); + + ECDSA_RS_ENTER( det ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + { + /* redirect to our context */ + p_rng = &rs_ctx->det->rng_ctx; + + /* jump to current step */ + if( rs_ctx->det->state == ecdsa_det_sign ) + goto sign; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); + MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); + mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + rs_ctx->det->state = ecdsa_det_sign; + +sign: +#endif +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + (void) f_rng_blind; + (void) p_rng_blind; + ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng ); +#else + if( f_rng_blind != NULL ) + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + f_rng_blind, p_rng_blind, rs_ctx ); + else + { + mbedtls_hmac_drbg_context *p_rng_blind_det; + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + /* + * To avoid reusing rng_ctx and risking incorrect behavior we seed a + * second HMAC-DRBG with the same seed. We also apply a label to avoid + * reusing the bits of the ephemeral key for blinding and eliminate the + * risk that they leak this way. + */ + const char* blind_label = "BLINDING CONTEXT"; + mbedtls_hmac_drbg_context rng_ctx_blind; + + mbedtls_hmac_drbg_init( &rng_ctx_blind ); + p_rng_blind_det = &rng_ctx_blind; + mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info, + data, 2 * grp_len ); + ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det, + (const unsigned char*) blind_label, + strlen( blind_label ) ); + if( ret != 0 ) + { + mbedtls_hmac_drbg_free( &rng_ctx_blind ); + goto cleanup; + } +#else + /* + * In the case of restartable computations we would either need to store + * the second RNG in the restart context too or set it up at every + * restart. The first option would penalize the correct application of + * the function and the second would defeat the purpose of the + * restartable feature. + * + * Therefore in this case we reuse the original RNG. This comes with the + * price that the resulting signature might not be a valid deterministic + * ECDSA signature with a very low probability (same magnitude as + * successfully guessing the private key). However even then it is still + * a valid ECDSA signature. + */ + p_rng_blind_det = p_rng; +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* + * Since the output of the RNGs is always the same for the same key and + * message, this limits the efficiency of blinding and leaks information + * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL + * won't be a valid value for f_rng_blind anymore. Therefore it should + * be checked by the caller and this branch and check can be removed. + */ + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + mbedtls_hmac_drbg_random, p_rng_blind_det, + rs_ctx ); + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_hmac_drbg_free( &rng_ctx_blind ); +#endif + } +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +cleanup: + mbedtls_hmac_drbg_free( &rng_ctx ); + mbedtls_mpi_free( &h ); + + ECDSA_RS_LEAVE( det ); + + return( ret ); +} + +/* + * Deterministic signature wrappers + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, + NULL, NULL, NULL ) ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + ECDSA_VALIDATE_RET( f_rng_blind != NULL ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, + f_rng_blind, p_rng_blind, NULL ) ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Verify ECDSA signature of hashed message (SEC1 4.1.4) + * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) + */ +static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi e, s_inv, u1, u2; + mbedtls_ecp_point R; + mbedtls_mpi *pu1 = &u1, *pu2 = &u2; + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); + mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + ECDSA_RS_ENTER( ver ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + { + /* redirect to our context */ + pu1 = &rs_ctx->ver->u1; + pu2 = &rs_ctx->ver->u2; + + /* jump to current step */ + if( rs_ctx->ver->state == ecdsa_ver_muladd ) + goto muladd; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || + mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 3: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + rs_ctx->ver->state = ecdsa_ver_muladd; + +muladd: +#endif + /* + * Step 5: R = u1 G + u2 Q + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, + &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); + + if( mbedtls_ecp_is_zero( &R ) ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); + mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + ECDSA_RS_LEAVE( ver ); + + return( ret ); +} + +/* + * Verify ECDSA signature of hashed message + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( Q != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = {0}; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, f_rng, + p_rng, rs_ctx ) ); +#else + (void) md_alg; + +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + (void) rs_ctx; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng ) ); +#else + /* Use the same RNG for both blinding and ephemeral key generation */ + MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng, f_rng, + p_rng, rs_ctx ) ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \ + defined(MBEDTLS_ECDSA_DETERMINISTIC) +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, + NULL, NULL ) ); +} +#endif + +/* + * Read and check signature + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + return( mbedtls_ecdsa_read_signature_restartable( + ctx, hash, hlen, sig, slen, NULL ) ); +} + +/* + * Restartable read and check signature + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( p + len != end ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_ECP_BAD_INPUT_DATA, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + goto cleanup; + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + (void) rs_ctx; + + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s ) ) != 0 ) + goto cleanup; +#else + if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ + if( p != end ) + ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) +/* + * Generate key pair + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = 0; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + + ret = mbedtls_ecp_group_load( &ctx->grp, gid ); + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, + &ctx->Q, f_rng, p_rng ) ); +} +#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ + +/* + * Set context from an mbedtls_ecp_keypair + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( key != NULL ); + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + mbedtls_ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_keypair_init( ctx ); +} + +/* + * Free context + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_keypair_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_restart_init( &ctx->ecp ); + + ctx->ver = NULL; + ctx->sig = NULL; +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ctx->det = NULL; +#endif +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_restart_free( &ctx->ecp ); + + ecdsa_restart_ver_free( ctx->ver ); + mbedtls_free( ctx->ver ); + ctx->ver = NULL; + + ecdsa_restart_sig_free( ctx->sig ); + mbedtls_free( ctx->sig ); + ctx->sig = NULL; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ecdsa_restart_det_free( ctx->det ); + mbedtls_free( ctx->det ); + ctx->det = NULL; +#endif +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_ECDSA_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c new file mode 100644 index 0000000..0b9bffb --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecjpake.c @@ -0,0 +1,1141 @@ +/* + * Elliptic curve J-PAKE + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * References in the code are to the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + */ + +#include "common.h" + +#if defined(MBEDTLS_ECJPAKE_C) + +#include "mbedtls/ecjpake.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECJPAKE_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECJPAKE_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Convert a mbedtls_ecjpake_role to identifier string + */ +static const char * const ecjpake_id[] = { + "client", + "server" +}; + +#define ID_MINE ( ecjpake_id[ ctx->role ] ) +#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) + +/* + * Initialize context + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) +{ + ECJPAKE_VALIDATE( ctx != NULL ); + + ctx->md_info = NULL; + mbedtls_ecp_group_init( &ctx->grp ); + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + + mbedtls_ecp_point_init( &ctx->Xm1 ); + mbedtls_ecp_point_init( &ctx->Xm2 ); + mbedtls_ecp_point_init( &ctx->Xp1 ); + mbedtls_ecp_point_init( &ctx->Xp2 ); + mbedtls_ecp_point_init( &ctx->Xp ); + + mbedtls_mpi_init( &ctx->xm1 ); + mbedtls_mpi_init( &ctx->xm2 ); + mbedtls_mpi_init( &ctx->s ); +} + +/* + * Free context + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->md_info = NULL; + mbedtls_ecp_group_free( &ctx->grp ); + + mbedtls_ecp_point_free( &ctx->Xm1 ); + mbedtls_ecp_point_free( &ctx->Xm2 ); + mbedtls_ecp_point_free( &ctx->Xp1 ); + mbedtls_ecp_point_free( &ctx->Xp2 ); + mbedtls_ecp_point_free( &ctx->Xp ); + + mbedtls_mpi_free( &ctx->xm1 ); + mbedtls_mpi_free( &ctx->xm2 ); + mbedtls_mpi_free( &ctx->s ); +} + +/* + * Setup context + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT || + role == MBEDTLS_ECJPAKE_SERVER ); + ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 ); + + ctx->role = role; + + if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); + +cleanup: + if( ret != 0 ) + mbedtls_ecjpake_free( ctx ); + + return( ret ); +} + +/* + * Check if context is ready for use + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + + if( ctx->md_info == NULL || + ctx->grp.id == MBEDTLS_ECP_DP_NONE || + ctx->s.p == NULL ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Write a point plus its length to a buffer + */ +static int ecjpake_write_len_point( unsigned char **p, + const unsigned char *end, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *P ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Need at least 4 for length plus 1 for point */ + if( end < *p || end - *p < 5 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + ret = mbedtls_ecp_point_write_binary( grp, P, pf, + &len, *p + 4, end - ( *p + 4 ) ); + if( ret != 0 ) + return( ret ); + + MBEDTLS_PUT_UINT32_BE( len, *p, 0 ); + + *p += 4 + len; + + return( 0 ); +} + +/* + * Size of the temporary buffer for ecjpake_hash: + * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) + */ +#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) + +/* + * Compute hash for ZKP (7.4.2.2.2.1) + */ +static int ecjpake_hash( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *V, + const mbedtls_ecp_point *X, + const char *id, + mbedtls_mpi *h ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[ECJPAKE_HASH_BUF_LEN]; + unsigned char *p = buf; + const unsigned char *end = buf + sizeof( buf ); + const size_t id_len = strlen( id ); + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + /* Write things to temporary buffer */ + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); + + if( end - p < 4 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + MBEDTLS_PUT_UINT32_BE( id_len, p, 0 ); + p += 4; + + if( end < p || (size_t)( end - p ) < id_len ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( p, id, id_len ); + p += id_len; + + /* Compute hash */ + MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) ); + + /* Turn it into an integer mod n */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, + mbedtls_md_get_size( md_info ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); + +cleanup: + return( ret ); +} + +/* + * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) + */ +static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point V, VV; + mbedtls_mpi r, h; + size_t r_len; + + mbedtls_ecp_point_init( &V ); + mbedtls_ecp_point_init( &VV ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &h ); + + /* + * struct { + * ECPoint V; + * opaque r<1..2^8-1>; + * } ECSchnorrZKP; + */ + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); + + if( end < *p || (size_t)( end - *p ) < 1 ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + r_len = *(*p)++; + + if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); + *p += r_len; + + /* + * Verification + */ + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, + &VV, &h, X, &r, G ) ); + + if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_ecp_point_free( &VV ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) + */ +static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_mpi *x, + const mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point V; + mbedtls_mpi v; + mbedtls_mpi h; /* later recycled to hold r */ + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &V ); + mbedtls_mpi_init( &v ); + mbedtls_mpi_init( &h ); + + /* Compute signature */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, + G, &v, &V, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ + + /* Write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, + pf, &len, *p, end - *p ) ); + *p += len; + + len = mbedtls_mpi_size( &h ); /* actually r */ + if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + + *(*p)++ = MBEDTLS_BYTE_0( len ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ + *p += len; + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_mpi_free( &v ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof + * Output: verified public key X + */ +static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * struct { + * ECPoint X; + * ECSchnorrZKP zkp; + * } ECJPAKEKeyKP; + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); + if( mbedtls_ecp_is_zero( X ) ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); + +cleanup: + return( ret ); +} + +/* + * Generate an ECJPAKEKeyKP + * Output: the serialized structure, plus private/public key pair + */ +static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *x, + mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* Generate key (7.4.2.3.1) and write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, + pf, &len, *p, end - *p ) ); + *p += len; + + /* Generate and write proof */ + MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, + p, end, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs + * Outputs: verified peer public keys Xa, Xb + */ +static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *Xa, + mbedtls_ecp_point *Xb, + const char *id, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + + /* + * struct { + * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; + * } ECJPAKEKeyKPPairList; + */ + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); + + if( p != end ) + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + +cleanup: + return( ret ); +} + +/* + * Generate a ECJPAKEKeyKPPairList + * Outputs: the serialized structure, plus two private/public key pairs + */ +static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *xm1, + mbedtls_ecp_point *Xa, + mbedtls_mpi *xm2, + mbedtls_ecp_point *Xb, + const char *id, + unsigned char *buf, + size_t len, + size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + const unsigned char *end = buf + len; + + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, + &p, end, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + return( ret ); +} + +/* + * Read and process the first round message + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + + return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->Xp1, &ctx->Xp2, ID_PEER, + buf, len ) ); +} + +/* + * Generate and write the first round message + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, + ID_MINE, buf, len, olen, f_rng, p_rng ) ); +} + +/* + * Compute the sum of three points R = A + B + C + */ +static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *A, + const mbedtls_ecp_point *B, + const mbedtls_ecp_point *C ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi one; + + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); + +cleanup: + mbedtls_mpi_free( &one ); + + return( ret ); +} + +/* + * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + mbedtls_ecp_group grp; + mbedtls_ecp_point G; /* C: GB, S: GA */ + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &G ); + + /* + * Server: GA = X3 + X4 + X1 (7.4.2.6.1) + * Client: GB = X1 + X2 + X3 (7.4.2.5.1) + * Unified: G = Xm1 + Xm2 + Xp1 + * We need that before parsing in order to check Xp as we read it + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); + + /* + * struct { + * ECParameters curve_params; // only client reading server msg + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); + if( grp.id != ctx->grp.id ) + { + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &ctx->Xp, ID_PEER, &p, end ) ); + + if( p != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &G ); + + return( ret ); +} + +/* + * Compute R = +/- X * S mod N, taking care not to leak S + */ +static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, + const mbedtls_mpi *X, + const mbedtls_mpi *S, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi b; /* Blinding value, then s + N * blinding */ + + mbedtls_mpi_init( &b ); + + /* b = s + rnd-128-bit * N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); + + /* R = sign * X * b mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); + R->s *= sign; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); + +cleanup: + mbedtls_mpi_free( &b ); + + return( ret ); +} + +/* + * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point G; /* C: GA, S: GB */ + mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ + mbedtls_mpi xm; /* C: xc, S: xs */ + unsigned char *p = buf; + const unsigned char *end = buf + len; + size_t ec_len; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + mbedtls_ecp_point_init( &G ); + mbedtls_ecp_point_init( &Xm ); + mbedtls_mpi_init( &xm ); + + /* + * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) + * + * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA + * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB + * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); + + /* + * Now write things out + * + * struct { + * ECParameters curve_params; // only server writing its message + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) + { + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, + p, end - p ) ); + p += ec_len; + } + + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, + ctx->point_format, &ec_len, p, end - p ) ); + p += ec_len; + + MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &xm, &Xm, ID_MINE, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + mbedtls_ecp_point_free( &G ); + mbedtls_ecp_point_free( &Xm ); + mbedtls_mpi_free( &xm ); + + return( ret ); +} + +/* + * Derive PMS (7.4.2.7 / 7.4.2.8) + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point K; + mbedtls_mpi m_xm2_s, one; + unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; + size_t x_bytes; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + *olen = mbedtls_md_get_size( ctx->md_info ); + if( len < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &K ); + mbedtls_mpi_init( &m_xm2_s ); + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + + /* + * Client: K = ( Xs - X4 * x2 * s ) * x2 + * Server: K = ( Xc - X2 * x4 * s ) * x4 + * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 + */ + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, + &one, &ctx->Xp, + &m_xm2_s, &ctx->Xp2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, + f_rng, p_rng ) ); + + /* PMS = SHA-256( K.X ) */ + x_bytes = ( ctx->grp.pbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); + +cleanup: + mbedtls_ecp_point_free( &K ); + mbedtls_mpi_free( &m_xm2_s ); + mbedtls_mpi_free( &one ); + + return( ret ); +} + +#undef ID_MINE +#undef ID_PEER + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + !defined(MBEDTLS_SHA256_C) +int mbedtls_ecjpake_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +static const unsigned char ecjpake_test_password[] = { + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, + 0x65, 0x73, 0x74 +}; + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +static const unsigned char ecjpake_test_x1[] = { + 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, 0x21 +}; + +static const unsigned char ecjpake_test_x2[] = { + 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, 0x81 +}; + +static const unsigned char ecjpake_test_x3[] = { + 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, 0x81 +}; + +static const unsigned char ecjpake_test_x4[] = { + 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, 0xe1 +}; + +static const unsigned char ecjpake_test_cli_one[] = { + 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, + 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, + 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, + 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, + 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, + 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, + 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, + 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, + 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, + 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, + 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, + 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, + 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, + 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, + 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, + 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, + 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, + 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, + 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, + 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, + 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, + 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, + 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, + 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, + 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, + 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, + 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, + 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 +}; + +static const unsigned char ecjpake_test_srv_one[] = { + 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, + 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, + 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, + 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, + 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, + 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, + 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, + 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, + 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, + 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, + 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, + 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, + 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, + 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, + 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, + 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, + 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, + 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, + 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, + 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, + 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, + 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, + 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, + 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, + 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, + 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, + 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, + 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 +}; + +static const unsigned char ecjpake_test_srv_two[] = { + 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, + 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, + 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, + 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, + 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, + 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, + 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, + 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, + 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, + 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, + 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, + 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, + 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, + 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c +}; + +static const unsigned char ecjpake_test_cli_two[] = { + 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, + 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, + 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, + 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, + 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, + 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, + 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, + 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, + 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, + 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, + 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, + 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, + 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, + 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c +}; + +static const unsigned char ecjpake_test_pms[] = { + 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, + 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, + 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 +}; + +/* Load my private keys and generate the corresponding public keys */ +static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, + const unsigned char *xm1, size_t len1, + const unsigned char *xm2, size_t len2 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, + &ctx->grp.G, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, + &ctx->grp.G, NULL, NULL ) ); + +cleanup: + return( ret ); +} + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +/* For tests we don't need a secure RNG; + * use the LGC from Numerical Recipes for simplicity */ +static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) +{ + static uint32_t x = 42; + (void) p; + + while( len > 0 ) + { + size_t use_len = len > 4 ? 4 : len; + x = 1664525 * x + 1013904223; + memcpy( out, &x, use_len ); + out += use_len; + len -= use_len; + } + + return( 0 ); +} + +#define TEST_ASSERT( x ) \ + do { \ + if( x ) \ + ret = 0; \ + else \ + { \ + ret = 1; \ + goto cleanup; \ + } \ + } while( 0 ) + +/* + * Checkup routine + */ +int mbedtls_ecjpake_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecjpake_context cli; + mbedtls_ecjpake_context srv; + unsigned char buf[512], pms[32]; + size_t len, pmslen; + + mbedtls_ecjpake_init( &cli ); + mbedtls_ecjpake_init( &srv ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #0 (setup): " ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == pmslen ); + TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if !defined(MBEDTLS_ECJPAKE_ALT) + /* 'reference handshake' tests can only be run against implementations + * for which we have 100% control over how the random ephemeral keys + * are generated. This is only the case for the internal mbed TLS + * implementation, so these tests are skipped in case the internal + * implementation is swapped out for an alternative one. */ + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); + + /* Simulate generation of round one */ + MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, + ecjpake_test_x1, sizeof( ecjpake_test_x1 ), + ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); + + MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, + ecjpake_test_x3, sizeof( ecjpake_test_x3 ), + ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); + + /* Read round one */ + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, + ecjpake_test_cli_one, + sizeof( ecjpake_test_cli_one ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, + ecjpake_test_srv_one, + sizeof( ecjpake_test_srv_one ) ) == 0 ); + + /* Skip generation of round two, read round two */ + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, + ecjpake_test_srv_two, + sizeof( ecjpake_test_srv_two ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, + ecjpake_test_cli_two, + sizeof( ecjpake_test_cli_two ) ) == 0 ); + + /* Server derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + memset( buf, 0, len ); /* Avoid interferences with next step */ + + /* Client derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +cleanup: + mbedtls_ecjpake_free( &cli ); + mbedtls_ecjpake_free( &srv ); + + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#undef TEST_ASSERT + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ECJPAKE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c new file mode 100644 index 0000000..192ce6f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp.c @@ -0,0 +1,3608 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * RFC 7748 for the Curve448 and Curve25519 curve definitions + * + * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#include "common.h" + +/** + * \brief Function level alternative implementation. + * + * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to + * replace certain functions in this module. The alternative implementations are + * typically hardware accelerators and need to activate the hardware before the + * computation starts and deactivate it after it finishes. The + * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve + * this purpose. + * + * To preserve the correct functionality the following conditions must hold: + * + * - The alternative implementation must be activated by + * mbedtls_internal_ecp_init() before any of the replaceable functions is + * called. + * - mbedtls_internal_ecp_free() must \b only be called when the alternative + * implementation is activated. + * - mbedtls_internal_ecp_init() must \b not be called when the alternative + * implementation is activated. + * - Public functions must not return while the alternative implementation is + * activated. + * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and + * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) + * \endcode ensures that the alternative implementation supports the current + * group. + */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/threading.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/bn_mul.h" + +#include "ecp_invasive.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ecp_internal.h" + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#elif defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#else +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +/* + * Currently ecp_mul() takes a RNG function as an argument, used for + * side-channel protection, but it can be NULL. The initial reasoning was + * that people will pass non-NULL RNG when they care about side-channels, but + * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with + * no opportunity for the user to do anything about it. + * + * The obvious strategies for addressing that include: + * - change those APIs so that they take RNG arguments; + * - require a global RNG to be available to all crypto modules. + * + * Unfortunately those would break compatibility. So what we do instead is + * have our own internal DRBG instance, seeded from the secret scalar. + * + * The following is a light-weight abstraction layer for doing that with + * HMAC_DRBG (first choice) or CTR_DRBG. + */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_hmac_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + /* The list starts with strong hashes */ + const mbedtls_md_type_t md_type = mbedtls_md_list()[0]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type ); + + if( secret_len > MBEDTLS_ECP_MAX_BYTES ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len ); + +cleanup: + mbedtls_platform_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#elif defined(MBEDTLS_CTR_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_ctr_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) ); +} + +/* + * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does, + * we need to pass an entropy function when seeding. So we use a dummy + * function for that, and pass the actual entropy as customisation string. + * (During seeding of CTR_DRBG the entropy input and customisation string are + * concatenated before being used to update the secret state.) + */ +static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len) +{ + (void) ctx; + memset( out, 0, len ); + return( 0 ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + + if( secret_len > MBEDTLS_ECP_MAX_BYTES ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL, + secret_bytes, secret_len ); + +cleanup: + mbedtls_platform_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#else +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif /* DRBG modules */ +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Maximum number of "basic operations" to be done in a row. + * + * Default value 0 means that ECC operations will not yield. + * Note that regardless of the value of ecp_max_ops, always at + * least one step is performed before yielding. + * + * Setting ecp_max_ops=1 can be suitable for testing purposes + * as it will interrupt computation at all possible points. + */ +static unsigned ecp_max_ops = 0; + +/* + * Set ecp_max_ops + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ) +{ + ecp_max_ops = max_ops; +} + +/* + * Check if restart is enabled + */ +int mbedtls_ecp_restart_is_enabled( void ) +{ + return( ecp_max_ops != 0 ); +} + +/* + * Restart sub-context for ecp_mul_comb() + */ +struct mbedtls_ecp_restart_mul +{ + mbedtls_ecp_point R; /* current intermediate result */ + size_t i; /* current index in various loops, 0 outside */ + mbedtls_ecp_point *T; /* table for precomputed points */ + unsigned char T_size; /* number of points in table T */ + enum { /* what were we doing last time we returned? */ + ecp_rsm_init = 0, /* nothing so far, dummy initial state */ + ecp_rsm_pre_dbl, /* precompute 2^n multiples */ + ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ + ecp_rsm_pre_add, /* precompute remaining points by adding */ + ecp_rsm_pre_norm_add, /* normalize all precomputed points */ + ecp_rsm_comb_core, /* ecp_mul_comb_core() */ + ecp_rsm_final_norm, /* do the final normalization */ + } state; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + unsigned char drbg_seeded; +#endif +}; + +/* + * Init restart_mul sub-context + */ +static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->R ); + ctx->i = 0; + ctx->T = NULL; + ctx->T_size = 0; + ctx->state = ecp_rsm_init; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_init( &ctx->drbg_ctx ); + ctx->drbg_seeded = 0; +#endif +} + +/* + * Free the components of a restart_mul sub-context + */ +static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + unsigned char i; + + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->R ); + + if( ctx->T != NULL ) + { + for( i = 0; i < ctx->T_size; i++ ) + mbedtls_ecp_point_free( ctx->T + i ); + mbedtls_free( ctx->T ); + } + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &ctx->drbg_ctx ); +#endif + + ecp_restart_rsm_init( ctx ); +} + +/* + * Restart context for ecp_muladd() + */ +struct mbedtls_ecp_restart_muladd +{ + mbedtls_ecp_point mP; /* mP value */ + mbedtls_ecp_point R; /* R intermediate result */ + enum { /* what should we do next? */ + ecp_rsma_mul1 = 0, /* first multiplication */ + ecp_rsma_mul2, /* second multiplication */ + ecp_rsma_add, /* addition */ + ecp_rsma_norm, /* normalization */ + } state; +}; + +/* + * Init restart_muladd sub-context + */ +static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->mP ); + mbedtls_ecp_point_init( &ctx->R ); + ctx->state = ecp_rsma_mul1; +} + +/* + * Free the components of a restart_muladd sub-context + */ +static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->mP ); + mbedtls_ecp_point_free( &ctx->R ); + + ecp_restart_ma_init( ctx ); +} + +/* + * Initialize a restart context + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +{ + ECP_VALIDATE( ctx != NULL ); + ctx->ops_done = 0; + ctx->depth = 0; + ctx->rsm = NULL; + ctx->ma = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_restart_rsm_free( ctx->rsm ); + mbedtls_free( ctx->rsm ); + + ecp_restart_ma_free( ctx->ma ); + mbedtls_free( ctx->ma ); + + mbedtls_ecp_restart_init( ctx ); +} + +/* + * Check if we can do the next step + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ) +{ + ECP_VALIDATE_RET( grp != NULL ); + + if( rs_ctx != NULL && ecp_max_ops != 0 ) + { + /* scale depending on curve size: the chosen reference is 256-bit, + * and multiplication is quadratic. Round to the closest integer. */ + if( grp->pbits >= 512 ) + ops *= 4; + else if( grp->pbits >= 384 ) + ops *= 2; + + /* Avoid infinite loops: always allow first step. + * Because of that, however, it's not generally true + * that ops_done <= ecp_max_ops, so the check + * ops_done > ecp_max_ops below is mandatory. */ + if( ( rs_ctx->ops_done != 0 ) && + ( rs_ctx->ops_done > ecp_max_ops || + ops > ecp_max_ops - rs_ctx->ops_done ) ) + { + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + } + + /* update running count */ + rs_ctx->ops_done += ops; + } + + return( 0 ); +} + +/* Call this when entering a function that needs its own sub-context */ +#define ECP_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ + rs_ctx->ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECP_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECP_RS_ENTER( sub ) (void) rs_ctx; +#define ECP_RS_LEAVE( sub ) (void) rs_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2, RFC 8446 sec. 4.2.7) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. This provides the default order for the SSL module. + * + * Reminder: update profiles in x509_crt.c when adding a new curves! + */ +static const mbedtls_ecp_curve_info ecp_supported_curves[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + { MBEDTLS_ECP_DP_CURVE25519, 29, 256, "x25519" }, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + { MBEDTLS_ECP_DP_CURVE448, 30, 448, "x448" }, +#endif +#if defined(MBEDTLS_ECP_DP_SM2_ENABLED) + /* https://tools.ietf.org/id/draft-yang-tls-tls13-sm-suites-05.html */ + { MBEDTLS_ECP_DP_SM2, 41, 256, "sm2" }, +#endif + { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) +{ + const mbedtls_ecp_curve_info *curve_info; + + if( name == NULL ) + return( NULL ); + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( strcmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( MBEDTLS_ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( MBEDTLS_ECP_TYPE_MONTGOMERY ); + else + return( MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE( pt != NULL ); + + mbedtls_mpi_init( &pt->X ); + mbedtls_mpi_init( &pt->Y ); + mbedtls_mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) +{ + ECP_VALIDATE( grp != NULL ); + + grp->id = MBEDTLS_ECP_DP_NONE; + mbedtls_mpi_init( &grp->P ); + mbedtls_mpi_init( &grp->A ); + mbedtls_mpi_init( &grp->B ); + mbedtls_ecp_point_init( &grp->G ); + mbedtls_mpi_init( &grp->N ); + grp->pbits = 0; + grp->nbits = 0; + grp->h = 0; + grp->modp = NULL; + grp->t_pre = NULL; + grp->t_post = NULL; + grp->t_data = NULL; + grp->T = NULL; + grp->T_size = 0; +} + +/* + * Initialize (the components of) a key pair + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) +{ + ECP_VALIDATE( key != NULL ); + + mbedtls_ecp_group_init( &key->grp ); + mbedtls_mpi_init( &key->d ); + mbedtls_ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_free( &( pt->X ) ); + mbedtls_mpi_free( &( pt->Y ) ); + mbedtls_mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mbedtls_mpi_free( &grp->P ); + mbedtls_mpi_free( &grp->A ); + mbedtls_mpi_free( &grp->B ); + mbedtls_ecp_point_free( &grp->G ); + mbedtls_mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + + mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_free( &key->grp ); + mbedtls_mpi_free( &key->d ); + mbedtls_ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) +{ + ECP_VALIDATE_RET( dst != NULL ); + ECP_VALIDATE_RET( src != NULL ); + + return( mbedtls_ecp_group_load( dst, src->id ) ); +} + +/* + * Set point to zero + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( pt != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE_RET( pt != NULL ); + + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Compare two points lazily + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( x != NULL ); + ECP_VALIDATE_RET( y != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3 and RFC7748) + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); + + plen = mbedtls_mpi_size( &grp->P ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + (void) format; /* Montgomery curves always use the same point format */ + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + *olen = plen; + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &P->X, buf, plen ) ); + } +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* + * Common case: P == 0 + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == MBEDTLS_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + } + } +#endif + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748) + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + + if( ilen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + plen = mbedtls_mpi_size( &grp->P ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + if( plen != ilen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &pt->X, buf, plen ) ); + mbedtls_mpi_free( &pt->Y ); + + if( grp->id == MBEDTLS_ECP_DP_CURVE25519 ) + /* Set most significant bit to 0 as prescribed in RFC7748 §5 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &pt->X, plen * 8 - 1, 0 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + } +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( mbedtls_ecp_set_zero( pt ) ); + else + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + if( buf[0] != 0x04 ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, + buf + 1 + plen, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + } +#endif + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_group_load( grp, grp_id ) ); +} + +/* + * Read a group id from an ECParameters record (RFC 4492) and convert it to + * mbedtls_ecp_group_id. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + *grp = curve_info->grp_id; + + return( 0 ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + MBEDTLS_PUT_UINT16_BE( curve_info->tls_id, buf, 0 ); + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. + * See the documentation of struct mbedtls_ecp_group. + * + * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( grp->modp == NULL ) + return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || + mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + MBEDTLS_MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); + + while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi + */ +#if defined(MBEDTLS_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) \ + do \ + { \ + MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \ + INC_MUL_COUNT \ + } while( 0 ) + +static inline int mbedtls_mpi_mul_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( X, A, B ) ); + MOD_MUL( *X ); +cleanup: + return( ret ); +} + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) ) + +#if ( defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \ + !( defined(MBEDTLS_ECP_NO_FALLBACK) && \ + defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \ + defined(MBEDTLS_ECP_ADD_MIXED_ALT) ) ) || \ + ( defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) && \ + !( defined(MBEDTLS_ECP_NO_FALLBACK) && \ + defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) ) ) +static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( X, A, B ) ); + MOD_SUB( *X ); +cleanup: + return( ret ); +} +#endif /* All functions referencing mbedtls_mpi_sub_mod() are alt-implemented without fallback */ + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) ) + +static inline int mbedtls_mpi_add_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, A, B ) ); + MOD_ADD( *X ); +cleanup: + return( ret ); +} + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \ + !( defined(MBEDTLS_ECP_NO_FALLBACK) && \ + defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \ + defined(MBEDTLS_ECP_ADD_MIXED_ALT) ) +static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, count ) ); + MOD_ADD( *X ); +cleanup: + return( ret ); +} +#endif /* All functions referencing mbedtls_mpi_shift_l_mod() are alt-implemented without fallback */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with countermeasures against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) +{ + if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac( grp, pt ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi Zi, ZZi; + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi, &Zi, &Zi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X, &pt->X, &ZZi ) ); + + /* + * Y = Y / Z^3 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &Zi ) ); + + /* + * Z = 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */ +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t T_size ) +{ + if( T_size < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) ); +#endif + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi *c, u, Zi, ZZi; + + if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_init( &c[i] ); + + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < T_size; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &c[i], &c[i-1], &T[i]->Z ) ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) ); + + for( i = T_size - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Zi, &u, &c[i-1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &u, &u, &T[i]->Z ) ); + } + + /* + * proceed as in normalize() + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi, &Zi, &Zi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->X, &T[i]->X, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &Zi ) ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_free( &c[i] ); + mbedtls_free( c ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) */ +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *Q, + unsigned char inv ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char nonzero; + mbedtls_mpi mQY; + + mbedtls_mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mbedtls_mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . + * + * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR + * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. + * + * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + */ +static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ +#if defined(MBEDTLS_SELF_TEST) + dbl_count++; +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_jac( grp, R, P ) ); +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi M, S, T, U; + + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &T, &P->X, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &U, &P->X, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &T, &U ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->X, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &S, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &T, &grp->A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &M, &M, &S ) ); + } + } + + /* S = 4.X.Y^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &P->Y, &P->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &S, 1 ) ); + + /* U = 8.Y^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U, &T, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U, 1 ) ); + + /* T = M^2 - 2.S */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &M, &M ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T, &T, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T, &T, &S ) ); + + /* S = M(S - T) - U */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S, &S, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &S, &M ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S, &S, &U ) ); + + /* U = 2.Y.Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U, &P->Y, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); + +cleanup: + mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */ +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ +#if defined(MBEDTLS_SELF_TEST) + add_count++; +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) ); +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_ADD_MIXED_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2, &T1, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1, &T1, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2, &T2, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T1, &T1, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T2, &T2, &P->Y ) ); + + /* Special cases (2) and (3) */ + if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = mbedtls_ecp_set_zero( R ); + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Z, &P->Z, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T1, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4, &T3, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T3, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &T3 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &X, &T2, &T2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X, &X, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X, &X, &T4 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T3, &T3, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T3, &T2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4, &T4, &P->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &Y, &T3, &T4 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */ +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi l, ll; + + mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) ); + + /* Z = l * Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Z, &pt->Z, &l ) ); + + /* X = l^2 * X */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll, &l, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X, &pt->X, &ll ) ); + + /* Y = l^3 * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll, &ll, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &ll ) ); + +cleanup: + mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); + + if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */ +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 +#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries, but saves on the size of + * the precomputed table. + * + * Summary of the comb method and its modifications: + * + * - The goal is to compute m*P for some w*d-bit integer m. + * + * - The basic comb method splits m into the w-bit integers + * x[0] .. x[d-1] where x[i] consists of the bits in m whose + * index has residue i modulo d, and computes m * P as + * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where + * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. + * + * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by + * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., + * thereby successively converting it into a form where all summands + * are nonzero, at the cost of negative summands. This is the basic idea of [3]. + * + * - More generally, even if x[i+1] != 0, we can first transform the sum as + * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., + * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. + * Performing and iterating this procedure for those x[i] that are even + * (keeping track of carry), we can transform the original sum into one of the form + * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] + * with all x'[i] odd. It is therefore only necessary to know S at odd indices, + * which is why we are only computing half of it in the first place in + * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. + * + * - For the sake of compactness, only the seven low-order bits of x[i] + * are used to represent its absolute value (K_i in the paper), and the msb + * of x[i] encodes the sign (s_i in the paper): it is set if and only if + * if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_recode_core( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the adapted comb method + * + * Assumption: T must be able to hold 2^{w - 1} elements. + * + * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, + * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + * + * Note: Even comb values (those where P would be omitted from the + * sum defining T[i] above) are not needed in our adaption + * the comb method. See ecp_comb_recode_core(). + * + * This function currently works in four steps: + * (1) [dbl] Computation of intermediate T[i] for 2-power values of i + * (2) [norm_dbl] Normalization of coordinates of these T[i] + * (3) [add] Computation of all T[i] + * (4) [norm_add] Normalization of all T[i] + * + * Step 1 can be interrupted but not the others; together with the final + * coordinate normalization they are the largest steps done at once, depending + * on the window size. Here are operation counts for P-256: + * + * step (2) (3) (4) + * w = 5 142 165 208 + * w = 4 136 77 160 + * w = 3 130 33 136 + * w = 2 124 11 124 + * + * So if ECC operations are blocking for too long even with a low max_ops + * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order + * to minimize maximum blocking time. + */ +static int ecp_precompute_comb( const mbedtls_ecp_group *grp, + mbedtls_ecp_point T[], const mbedtls_ecp_point *P, + unsigned char w, size_t d, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t j = 0; + const unsigned char T_size = 1U << ( w - 1 ); + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + goto dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) + goto norm_dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_add ) + goto add; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) + goto norm_add; + } +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + rs_ctx->rsm->state = ecp_rsm_pre_dbl; + + /* initial state for the loop */ + rs_ctx->rsm->i = 0; + } + +dbl: +#endif + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + j = rs_ctx->rsm->i; + else +#endif + j = 0; + + for( ; j < d * ( w - 1 ); j++ ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL ); + + i = 1U << ( j / d ); + cur = T + i; + + if( j % d == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; + +norm_dbl: +#endif + /* + * Normalize current elements in T. As T has holes, + * use an auxiliary array of pointers to elements in T. + */ + j = 0; + for( i = 1; i < T_size; i <<= 1 ) + TT[j++] = T + i; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_add; + +add: +#endif + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); + + for( i = 1; i < T_size; i <<= 1 ) + { + j = i; + while( j-- ) + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_add; + +norm_add: +#endif + /* + * Normalize final elements in T. Even though there are no holes now, we + * still need the auxiliary array for homogeneity with the previous + * call. Also, skip T[0] which is already normalised, being a copy of P. + */ + for( j = 0; j + 1 < T_size; j++ ) + TT[j] = T + j + 1; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +cleanup: +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + rs_ctx->rsm->i = j; + } +#endif + + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + * + * See ecp_comb_recode_core() for background + */ +static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char T_size, + unsigned char i ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < T_size; j++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char T_size, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point Txi; + size_t i; + + mbedtls_ecp_point_init( &Txi ); + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + rs_ctx->rsm->state != ecp_rsm_comb_core ) + { + rs_ctx->rsm->i = 0; + rs_ctx->rsm->state = ecp_rsm_comb_core; + } + + /* new 'if' instead of nested for the sake of the 'else' branch */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + { + /* restore current index (R already pointing to rs_ctx->rsm->R) */ + i = rs_ctx->rsm->i; + } + else +#endif + { + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != 0 ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + } + + while( i != 0 ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); + --i; + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + + mbedtls_ecp_point_free( &Txi ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + rs_ctx->rsm->i = i; + /* no need to save R, already pointing to rs_ctx->rsm->R */ + } +#endif + + return( ret ); +} + +/* + * Recode the scalar to get constant-time comb multiplication + * + * As the actual scalar recoding needs an odd scalar as a starting point, + * this wrapper ensures that by replacing m by N - m if necessary, and + * informs the caller that the result of multiplication will be negated. + * + * This works because we only support large prime order for Short Weierstrass + * curves, so N is always odd hence either m or N - m is. + * + * See ecp_comb_recode_core() for background. + */ +static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, + const mbedtls_mpi *m, + unsigned char k[COMB_MAX_D + 1], + size_t d, + unsigned char w, + unsigned char *parity_trick ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi M, mm; + + mbedtls_mpi_init( &M ); + mbedtls_mpi_init( &mm ); + + /* N is always odd (see above), just make extra sure */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* do we need the parity trick? */ + *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 ); + + /* execute parity fix in constant time */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) ); + + /* actual scalar recoding */ + ecp_comb_recode_core( k, d, w, &M ); + +cleanup: + mbedtls_mpi_free( &mm ); + mbedtls_mpi_free( &M ); + + return( ret ); +} + +/* + * Perform comb multiplication (for short Weierstrass curves) + * once the auxiliary table has been pre-computed. + * + * Scalar recoding may use a parity trick that makes us compute -m * P, + * if that is the case we'll need to recover m * P at the end. + */ +static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *T, + unsigned char T_size, + unsigned char w, + size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char parity_trick; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *RR = R; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + RR = &rs_ctx->rsm->R; + + if( rs_ctx->rsm->state == ecp_rsm_final_norm ) + goto final_norm; + } +#endif + + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, + &parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, + f_rng, p_rng, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_final_norm; + +final_norm: + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); +#endif + /* + * Knowledge of the jacobian coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != 0 ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); +#endif + +cleanup: + return( ret ); +} + +/* + * Pick window size based on curve size and whether we optimize for base point + */ +static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, + unsigned char p_eq_g ) +{ + unsigned char w; + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ + if( p_eq_g ) + w++; + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ +#if( MBEDTLS_ECP_WINDOW_SIZE < 6 ) + if( w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; +#endif + if( w >= grp->nbits ) + w = 2; + + return( w ); +} + +/* + * Multiplication using the comb method - for curves in short Weierstrass form + * + * This function is mainly responsible for administrative work: + * - managing the restart context if enabled + * - managing the table of precomputed points (passed between the below two + * functions): allocation, computation, ownership transfer, freeing. + * + * It delegates the actual arithmetic work to: + * ecp_precompute_comb() and ecp_mul_comb_with_precomp() + * + * See comments on ecp_comb_recode_core() regarding the computation strategy. + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char w, p_eq_g, i; + size_t d; + unsigned char T_size = 0, T_ok = 0; + mbedtls_ecp_point *T = NULL; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + + ecp_drbg_init( &drbg_ctx ); +#endif + + ECP_RS_ENTER( rsm ); + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + /* Adjust pointers */ + f_rng = &ecp_drbg_random; +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + p_rng = &rs_ctx->rsm->drbg_ctx; + else +#endif + p_rng = &drbg_ctx; + + /* Initialize internal DRBG if necessary */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL || + rs_ctx->rsm->drbg_seeded == 0 ) +#endif + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) ); + } +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->drbg_seeded = 1; +#endif + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + + /* Is P the base point ? */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); +#else + p_eq_g = 0; +#endif + + /* Pick window size and deduce related sizes */ + w = ecp_pick_window_size( grp, p_eq_g ); + T_size = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* Pre-computed table: do we have it already for the base point? */ + if( p_eq_g && grp->T != NULL ) + { + /* second pointer to the same table, will be deleted on exit */ + T = grp->T; + T_ok = 1; + } + else +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* Pre-computed table: do we have one in progress? complete? */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL ) + { + /* transfer ownership of T from rsm to local function */ + T = rs_ctx->rsm->T; + rs_ctx->rsm->T = NULL; + rs_ctx->rsm->T_size = 0; + + /* This effectively jumps to the call to mul_comb_after_precomp() */ + T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; + } + else +#endif + /* Allocate table if we didn't have any */ + { + T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); + if( T == NULL ) + { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_init( &T[i] ); + + T_ok = 0; + } + + /* Compute table (or finish computing it) if not done already */ + if( !T_ok ) + { + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) ); + + if( p_eq_g ) + { + /* almost transfer ownership of T to the group, but keep a copy of + * the pointer to use for calling the next function more easily */ + grp->T = T; + grp->T_size = T_size; + } + } + + /* Actual comb multiplication using precomputed points */ + MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, + T, T_size, w, d, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + + /* does T belong to the group? */ + if( T == grp->T ) + T = NULL; + + /* does T belong to the restart context? */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) + { + /* transfer ownership of T from local function to rsm */ + rs_ctx->rsm->T_size = T_size; + rs_ctx->rsm->T = T; + T = NULL; + } +#endif + + /* did T belong to us? then let's destroy it! */ + if( T != NULL ) + { + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_free( &T[i] ); + mbedtls_free( T ); + } + + /* don't free R while in progress in case R == P */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + /* prevent caller from using invalid value */ + if( ret != 0 ) + mbedtls_ecp_point_free( R ); + + ECP_RS_LEAVE( rsm ); + + return( ret ); +} + +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +/* + * For Montgomery curves, we do all the internal arithmetic in projective + * coordinates. Import/export of points uses only the x coordinates, which is + * internally represented as X / Z. + * + * For scalar multiplication, we'll use a Montgomery ladder. + */ + +/* + * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 + * Cost: 1M + 1I + */ +static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) +{ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_mxz( grp, P ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) */ +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi l; + mbedtls_mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->Z, &P->Z, &l ) ); + +cleanup: + mbedtls_mpi_free( &l ); + + if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */ +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + const mbedtls_mpi *d ) +{ +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) ); +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); + mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &A, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &AA, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &B, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &BB, &B, &B ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &E, &AA, &BB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &C, &Q->X, &Q->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &D, &Q->X, &Q->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &DA, &D, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &CB, &C, &B ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &S->X, &DA, &CB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->X, &S->X, &S->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S->Z, &DA, &CB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, &S->Z, &S->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, d, &S->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->X, &AA, &BB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &grp->A, &E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &R->Z, &BB, &R->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &E, &R->Z ) ); + +cleanup: + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); + mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */ +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + unsigned char b; + mbedtls_ecp_point RP; + mbedtls_mpi PX; +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + + ecp_drbg_init( &drbg_ctx ); +#endif + mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) ); + f_rng = &ecp_drbg_random; + p_rng = &drbg_ctx; + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + + /* Save PX and read from P before writing to R, in case P == R */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); + mbedtls_mpi_free( &R->Y ); + + /* RP.X might be slightly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != NULL ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mbedtls_mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + /* + * Knowledge of the projective coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != NULL ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); + + return( ret ); +} + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +/* + * Restartable multiplication R = m * P + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) + rs_ctx->ops_done = 0; +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* skip argument check when restarting */ + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + { + /* check_privkey is free */ + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK ); + + /* Common sanity checks */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); + } + + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); +#endif + +cleanup: + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL ) + rs_ctx->depth--; +#endif + + return( ret ); +} + +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) ); +} + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || + mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || + mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &YY, &pt->Y, &pt->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &pt->X, &pt->X ) ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->A ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &RHS, &pt->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->B ) ); + + if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + +cleanup: + + mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * R = m * P with shortcuts for m == 0, m == 1 and m == -1 + * NOT constant-time - ONLY for short Weierstrass! + */ +static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *P, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( mbedtls_mpi_cmp_int( m, 0 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_set_zero( R ) ); + } + else if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + } + else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P, + NULL, NULL, rs_ctx ) ); + } + +cleanup: + return( ret ); +} + +/* + * Restartable linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point mP; + mbedtls_ecp_point *pmP = &mP; + mbedtls_ecp_point *pR = R; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( mbedtls_ecp_get_type( grp ) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + ECP_RS_ENTER( ma ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + { + /* redirect intermediate results to restart context */ + pmP = &rs_ctx->ma->mP; + pR = &rs_ctx->ma->R; + + /* jump to next operation */ + if( rs_ctx->ma->state == ecp_rsma_mul2 ) + goto mul2; + if( rs_ctx->ma->state == ecp_rsma_add ) + goto add; + if( rs_ctx->ma->state == ecp_rsma_norm ) + goto norm; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_mul2; + +mul2: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_add; + +add: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_norm; + +norm: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); +#endif + +cleanup: +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + + mbedtls_ecp_point_free( &mP ); + + ECP_RS_LEAVE( ma ); + + return( ret ); +} + +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) ); +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define ECP_MPI_INIT(s, n, p) {s, 0, (n), (mbedtls_mpi_uint *)(p)} +#define ECP_MPI_INIT_ARRAY(x) \ + ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x) +/* + * Constants for the two points other than 0, 1, -1 (mod p) in + * https://cr.yp.to/ecdh.html#validate + * See ecp_check_pubkey_x25519(). + */ +static const mbedtls_mpi_uint x25519_bad_point_1[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 ), +}; +static const mbedtls_mpi_uint x25519_bad_point_2[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 ), +}; +static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY( + x25519_bad_point_1 ); +static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY( + x25519_bad_point_2 ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +/* + * Check that the input point is not one of the low-order points. + * This is recommended by the "May the Fourth" paper: + * https://eprint.iacr.org/2017/806.pdf + * Those points are never sent by an honest peer. + */ +static int ecp_check_bad_points_mx( const mbedtls_mpi *X, const mbedtls_mpi *P, + const mbedtls_ecp_group_id grp_id ) +{ + int ret; + mbedtls_mpi XmP; + + mbedtls_mpi_init( &XmP ); + + /* Reduce X mod P so that we only need to check values less than P. + * We know X < 2^256 so we can proceed by subtraction. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &XmP, X ) ); + while( mbedtls_mpi_cmp_mpi( &XmP, P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &XmP, &XmP, P ) ); + + /* Check against the known bad values that are less than P. For Curve448 + * these are 0, 1 and -1. For Curve25519 we check the values less than P + * from the following list: https://cr.yp.to/ecdh.html#validate */ + if( mbedtls_mpi_cmp_int( &XmP, 1 ) <= 0 ) /* takes care of 0 and 1 */ + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + if( grp_id == MBEDTLS_ECP_DP_CURVE25519 ) + { + if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_1 ) == 0 ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_2 ) == 0 ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + } +#else + (void) grp_id; +#endif + + /* Final check: check if XmP + 1 is P (final because it changes XmP!) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &XmP, &XmP, 1 ) ); + if( mbedtls_mpi_cmp_mpi( &XmP, P ) == 0 ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + ret = 0; + +cleanup: + mbedtls_mpi_free( &XmP ); + + return( ret ); +} + +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + /* Allow any public value, if it's too big then we'll just reduce it mod p + * (RFC 7748 sec. 5 para. 3). */ + if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + /* Implicit in all standards (as they don't consider negative numbers): + * X must be non-negative. This is normally ensured by the way it's + * encoded for transmission, but let's be extra sure. */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( ecp_check_bad_points_mx( &pt->X, &grp->P, grp->id ) ); +} +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +/* + * Check that a point is valid as a public key + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mbedtls_mpi is valid as a private key + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + /* see RFC 7748 sec. 5 para. 5 */ + if( mbedtls_mpi_get_bit( d, 0 ) != 0 || + mbedtls_mpi_get_bit( d, 1 ) != 0 || + mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + /* see [Curve25519] page 5 */ + if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); + } +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_gen_privkey_mx( size_t high_bit, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + size_t n_random_bytes = high_bit / 8 + 1; + + /* [Curve25519] page 5 */ + /* Generate a (high_bit+1)-bit random number by generating just enough + * random bytes, then shifting out extra bits from the top (necessary + * when (high_bit+1) is not a multiple of 8). */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_random_bytes, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_random_bytes - high_bit - 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, high_bit, 1 ) ); + + /* Make sure the last two bits are unset for Curve448, three bits for + Curve25519 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); + if( high_bit == 254 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +static int mbedtls_ecp_gen_privkey_sw( + const mbedtls_mpi *N, mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = mbedtls_mpi_random( d, 1, N, f_rng, p_rng ); + switch( ret ) + { + case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + default: + return( ret ); + } +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +/* + * Generate a private key + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + return( mbedtls_ecp_gen_privkey_mx( grp->nbits, d, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + return( mbedtls_ecp_gen_privkey_sw( &grp->N, d, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( G != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Generate key pair, wrapper for conventional base point + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +#define ECP_CURVE25519_KEY_SIZE 32 +/* + * Read a private key. + */ +int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + const unsigned char *buf, size_t buflen ) +{ + int ret = 0; + + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + /* + * If it is Curve25519 curve then mask the key as mandated by RFC7748 + */ + if( grp_id == MBEDTLS_ECP_DP_CURVE25519 ) + { + if( buflen != ECP_CURVE25519_KEY_SIZE ) + return MBEDTLS_ERR_ECP_INVALID_KEY; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &key->d, buf, buflen ) ); + + /* Set the three least significant bits to 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 2, 0 ) ); + + /* Set the most significant bit to 0 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( &key->d, + ECP_CURVE25519_KEY_SIZE * 8 - 1, 0 ) + ); + + /* Set the second most significant bit to 1 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( &key->d, + ECP_CURVE25519_KEY_SIZE * 8 - 2, 1 ) + ); + } + else + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } + +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &key->d, buf, buflen ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( &key->grp, &key->d ) ); + } + +#endif +cleanup: + + if( ret != 0 ) + mbedtls_mpi_free( &key->d ); + + return( ret ); +} + +/* + * Write a private key. + */ +int mbedtls_ecp_write_key( mbedtls_ecp_keypair *key, + unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + if( key->grp.id == MBEDTLS_ECP_DP_CURVE25519 ) + { + if( buflen < ECP_CURVE25519_KEY_SIZE ) + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &key->d, buf, buflen ) ); + } + else + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } + +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &key->d, buf, buflen ) ); + } + +#endif +cleanup: + + return( ret ); +} + + +/* + * Check a public-private key pair + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + ECP_VALIDATE_RET( pub != NULL ); + ECP_VALIDATE_RET( prv != NULL ); + + if( pub->grp.id == MBEDTLS_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + mbedtls_ecp_point_init( &Q ); + mbedtls_ecp_group_init( &grp ); + + /* mbedtls_ecp_mul() needs a non-const group... */ + mbedtls_ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); + + if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &Q ); + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* Adjust the exponent to be a valid private point for the specified curve. + * This is sometimes necessary because we use a single set of exponents + * for all curves but the validity of values depends on the curve. */ +static int self_test_adjust_exponent( const mbedtls_ecp_group *grp, + mbedtls_mpi *m ) +{ + int ret = 0; + switch( grp->id ) + { + /* If Curve25519 is available, then that's what we use for the + * Montgomery test, so we don't need the adjustment code. */ +#if ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + /* Move highest bit from 254 to N-1. Setting bit N-1 is + * necessary to enforce the highest-bit-set constraint. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( m, 254, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( m, grp->nbits, 1 ) ); + /* Copy second-highest bit from 253 to N-2. This is not + * necessary but improves the test variety a bit. */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( m, grp->nbits - 1, + mbedtls_mpi_get_bit( m, 253 ) ) ); + break; +#endif +#endif /* ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) */ + default: + /* Non-Montgomery curves and Curve25519 need no adjustment. */ + (void) grp; + (void) m; + goto cleanup; + } +cleanup: + return( ret ); +} + +/* Calculate R = m.P for each m in exponents. Check that the number of + * basic operations doesn't depend on the value of m. */ +static int self_test_point( int verbose, + mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + mbedtls_mpi *m, + const mbedtls_ecp_point *P, + const char *const *exponents, + size_t n_exponents ) +{ + int ret = 0; + size_t i = 0; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( self_test_adjust_exponent( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + + for( i = 1; i < n_exponents; i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( self_test_adjust_exponent( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + ret = 1; + break; + } + } + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + else + mbedtls_printf( "passed\n" ); + } + return( ret ); +} + +/* + * Checkup routine + */ +int mbedtls_ecp_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, P; + mbedtls_mpi m; + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + /* Exponents especially adapted for secp192k1, which has the lowest + * order n of all supported curves (secp192r1 is in a slightly larger + * field but the order of its base point is slightly smaller). */ + const char *sw_exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8C", /* n - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + const char *m_exponents[] = + { + /* Valid private values for Curve25519. In a build with Curve448 + * but not Curve25519, they will be adjusted in + * self_test_adjust_exponent(). */ + "4000000000000000000000000000000000000000000000000000000000000000", + "5C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C30", + "5715ECCE24583F7A7023C24164390586842E816D7280A49EF6DF4EAE6B280BF8", + "41A2B017516F6D254E1F002BCCBADD54BE30F8CEC737A0E912B4963B6BA74460", + "5555555555555555555555555555555555555555555555555555555555555550", + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8", + }; +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &P ); + mbedtls_mpi_init( &m ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + /* Use secp192r1 if available, or any available curve */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); +#else + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + mbedtls_printf( " ECP SW test #1 (constant op_count, base point G): " ); + /* Do a dummy multiplication first to trigger precomputation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + ret = self_test_point( verbose, + &grp, &R, &m, &grp.G, + sw_exponents, + sizeof( sw_exponents ) / sizeof( sw_exponents[0] )); + if( ret != 0 ) + goto cleanup; + + if( verbose != 0 ) + mbedtls_printf( " ECP SW test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + ret = self_test_point( verbose, + &grp, &R, &m, &P, + sw_exponents, + sizeof( sw_exponents ) / sizeof( sw_exponents[0] )); + if( ret != 0 ) + goto cleanup; + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( verbose != 0 ) + mbedtls_printf( " ECP Montgomery test (constant op_count): " ); +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_CURVE25519 ) ); +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_CURVE448 ) ); +#else +#error "MBEDTLS_ECP_MONTGOMERY_ENABLED is defined, but no curve is supported for self-test" +#endif + ret = self_test_point( verbose, + &grp, &R, &m, &grp.G, + m_exponents, + sizeof( m_exponents ) / sizeof( m_exponents[0] )); + if( ret != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +cleanup: + + if( ret < 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret ); + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &P ); + mbedtls_mpi_free( &m ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c new file mode 100644 index 0000000..ea43e1f --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_curves.c @@ -0,0 +1,1526 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/bn_mul.h" + +#include "ecp_invasive.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)} + +#define ECP_MPI_INIT_ARRAY(x) \ + ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x) + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + MBEDTLS_BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* For these curves, we build the group parameters dynamically. */ +#define ECP_LOAD_GROUP +#endif + +#if defined(ECP_LOAD_GROUP) +/* + * Domain parameters for SM2 (GM/T 0003 Part 5) + */ +#if defined(MBEDTLS_ECP_DP_SM2_ENABLED) +static const mbedtls_mpi_uint sm2_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint sm2_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint sm2_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x0E, 0x94, 0x4D, 0x41, 0xBD, 0xBC, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x8F, 0xAB, 0x15, 0xF5, 0x89, 0x97, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x09, 0x65, 0xCF, 0x4B, 0x9E, 0x5A, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x5E, 0x9F, 0x9D, 0x9E, 0xFA, 0xE9, 0x28 ), +}; +static const mbedtls_mpi_uint sm2_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0x74, 0x4C, 0x33, 0x89, 0x45, 0x5A, 0x71 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x0B, 0x66, 0xF2, 0xBF, 0x0B, 0xE3, 0x8F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0xC9, 0x39, 0x6A, 0x46, 0x04, 0x99, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x81, 0x19, 0x1F, 0x2C, 0xAE, 0xC4, 0x32 ), +}; +static const mbedtls_mpi_uint sm2_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xF0, 0x39, 0x21, 0xE5, 0x32, 0xDF, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x47, 0x2A, 0xC6, 0x7C, 0x87, 0xA9, 0xD0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0x21, 0x69, 0x6B, 0xE3, 0xCE, 0xBD, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0x77, 0xF6, 0xF4, 0xA2, 0x36, 0x37, 0xBC ), +}; +static const mbedtls_mpi_uint sm2_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x41, 0xD5, 0x39, 0x09, 0xF4, 0xBB, 0x53 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0x05, 0xC6, 0x21, 0x6B, 0xDF, 0x03, 0x72 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SM2_ENABLED */ +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + */ +static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( mbedtls_mpi_uint ); + X->p = (mbedtls_mpi_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mbedtls_mpi *X ) +{ + static mbedtls_mpi_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + grp->h = 1; + + return( 0 ); +} +#endif /* ECP_LOAD_GROUP */ + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mbedtls_mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +static int ecp_mod_p448( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mbedtls_mpi * ); +#endif + +#if defined(ECP_LOAD_GROUP) +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) +#endif /* ECP_LOAD_GROUP */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* Constants used by ecp_use_curve25519() */ +static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42; +static const unsigned char curve25519_part_of_n[] = { + 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, + 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED, +}; + +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve25519_a24 ) ); + + /* P = 2^255 - 19 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* N = 2^252 + 27742317777372353535851937790883648493 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &grp->N, + curve25519_part_of_n, sizeof( curve25519_part_of_n ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* Constants used by ecp_use_curve448() */ +static const mbedtls_mpi_sint curve448_a24 = 0x98AA; +static const unsigned char curve448_part_of_n[] = { + 0x83, 0x35, 0xDC, 0x16, 0x3B, 0xB1, 0x24, + 0xB6, 0x51, 0x29, 0xC9, 0x6F, 0xDE, 0x93, + 0x3D, 0x8D, 0x72, 0x3A, 0x70, 0xAA, 0xDC, + 0x87, 0x3D, 0x6D, 0x54, 0xA7, 0xBB, 0x0D, +}; + +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448( mbedtls_ecp_group *grp ) +{ + mbedtls_mpi Ns; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_mpi_init( &Ns ); + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve448_a24 ) ); + + /* P = 2^448 - 2^224 - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &Ns, + curve448_part_of_n, sizeof( curve448_part_of_n ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) ); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + mbedtls_mpi_free( &Ns ); + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) +{ + ECP_VALIDATE_RET( grp != NULL ); + mbedtls_ecp_group_free( grp ); + + mbedtls_ecp_group_init( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SM2_ENABLED) + case MBEDTLS_ECP_DP_SM2: + return( LOAD_GROUP_A( sm2 ) ); +#endif /* MBEDTLS_ECP_DP_SM2_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + grp->modp = ecp_mod_p448; + return( ecp_use_curve448( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + + default: + grp->id = MBEDTLS_ECP_DP_NONE; + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) +#define A( i ) N->p + (i) * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint c = 0; + mbedtls_mpi_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) (j) % 2 ? (uint32_t)( N->p[(j)/2] >> 32 ) : \ + (uint32_t)( N->p[(j)/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (mbedtls_mpi_uint) cur; \ + } + +#endif /* sizeof( mbedtls_mpi_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ + +/* + * Helpers for the main 'loop' + */ +#define INIT( b ) \ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = (b); \ + /* N is the size of the product of two b-bit numbers, plus one */ \ + /* limb for fix_negative */ \ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, ( b ) * 2 / biL + 1 ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) mbedtls_ecp_fix_negative( N, c, bits ); + +/* + * If the result is negative, we get it in the form + * c * 2^bits + N, with c negative and N positive shorter than 'bits' + */ +MBEDTLS_STATIC_TESTABLE +void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits ) +{ + size_t i; + + /* Set N := 2^bits - 1 - N. We know that 0 <= N < 2^bits, so + * set the absolute value to 0xfff...fff - N. There is no carry + * since we're subtracting from all-bits-one. */ + for( i = 0; i <= bits / 8 / sizeof( mbedtls_mpi_uint ); i++ ) + { + N->p[i] = ~(mbedtls_mpi_uint)0 - N->p[i]; + } + /* Add 1, taking care of the carry. */ + i = 0; + do + ++N->p[i]; + while( N->p[i++] == 0 && i <= bits / 8 / sizeof( mbedtls_mpi_uint ) ); + /* Invert the sign. + * Now N = N0 - 2^bits where N0 is the initial value of N. */ + N->s = -1; + + /* Add |c| * 2^bits to the absolute value. Since c and N are + * negative, this adds c * 2^bits. */ + mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c; +#if defined(MBEDTLS_HAVE_INT64) + if( bits == 224 ) + msw <<= 32; +#endif + N->p[bits / 8 / sizeof( mbedtls_mpi_uint)] += msw; +} + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mbedtls_mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mbedtls_mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mbedtls_mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/* Size of p448 in terms of mbedtls_mpi_uint */ +#define P448_WIDTH ( 448 / 8 / sizeof( mbedtls_mpi_uint ) ) + +/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ +#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) ) +#define P224_WIDTH_MIN ( 28 / sizeof( mbedtls_mpi_uint ) ) +#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) ) +#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 ) + +/* + * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return + * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference + * implementation of Curve448, which uses its own special 56-bit limbs rather + * than a generic bignum library. We could squeeze some extra speed out on + * 32-bit machines by splitting N up into 32-bit limbs and doing the + * arithmetic using the limbs directly as we do for the NIST primes above, + * but for 64-bit targets it should use half the number of operations if we do + * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. + */ +static int ecp_mod_p448( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M, Q; + mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; + + if( N->n <= P448_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P448_WIDTH ); + if( M.n > P448_WIDTH ) + /* Shouldn't be called with N larger than 2^896! */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof( Mp ) ); + memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) ); + + /* N = A0 */ + for( i = P448_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N += A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + + /* Q = B1, N += B1 */ + Q = M; + Q.p = Qp; + memcpy( Qp, Mp, sizeof( Qp ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) ); + + /* M = (B0 + B1) * 2^224, N += M */ + if( sizeof( mbedtls_mpi_uint ) > 4 ) + Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS ); + for( i = P224_WIDTH_MAX; i < M.n; ++i ) + Mp[i] = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) ); + M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, mbedtls_mpi_uint mask ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M, R; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, + 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00 ) }; + +#if defined(MBEDTLS_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, + 0 ) ); +#endif +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, + 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h new file mode 100644 index 0000000..71c7702 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ecp_invasive.h @@ -0,0 +1,81 @@ +/** + * \file ecp_invasive.h + * + * \brief ECP module: interfaces for invasive testing only. + * + * The interfaces in this file are intended for testing purposes only. + * They SHOULD NOT be made available in library integrations except when + * building the library for testing. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ECP_INVASIVE_H +#define MBEDTLS_ECP_INVASIVE_H + +#include "common.h" +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" + +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C) + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* Preconditions: + * - bits is a multiple of 64 or is 224 + * - c is -1 or -2 + * - 0 <= N < 2^bits + * - N has room for bits plus one limb + * + * Behavior: + * Set N to c * 2^bits + old_value_of_N. + */ +void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits ); +#endif + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +/** Generate a private key on a Montgomery curve (Curve25519 or Curve448). + * + * This function implements key generation for the set of secret keys + * specified in [Curve25519] p. 5 and in [Curve448]. The resulting value + * has the lower bits masked but is not necessarily canonical. + * + * \note - [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * - [RFC7748] https://tools.ietf.org/html/rfc7748 + * + * \p high_bit The position of the high-order bit of the key to generate. + * This is the bit-size of the key minus 1: + * 254 for Curve25519 or 447 for Curve448. + * \param d The randomly generated key. This is a number of size + * exactly \p n_bits + 1 bits, with the least significant bits + * masked as specified in [Curve25519] and in [RFC7748] §5. + * \param f_rng The RNG function. + * \param p_rng The RNG context to be passed to \p f_rng. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure. + */ +int mbedtls_ecp_gen_privkey_mx( size_t n_bits, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */ + +#endif /* MBEDTLS_ECP_INVASIVE_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c new file mode 100644 index 0000000..12fd3b9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy.c @@ -0,0 +1,737 @@ +/* + * Entropy accumulator implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_ENTROPY_C) + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " +#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " +#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + ctx->accumulator_started = 0; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_init( &ctx->accumulator ); +#else + mbedtls_sha256_init( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, + 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + +#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_TIMING_C) + mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDCLOCK, + MBEDTLS_ENTROPY_SOURCE_WEAK ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, + MBEDTLS_ENTROPY_MIN_HAVEGE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); + ctx->initial_entropy_run = 0; +#endif +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) +{ + /* If the context was already free, don't call free() again. + * This is important for mutexes which don't allow double-free. */ + if( ctx->accumulator_started == -1 ) + return; + +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_free( &ctx->havege_data ); +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_free( &ctx->accumulator ); +#else + mbedtls_sha256_free( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + ctx->initial_entropy_run = 0; +#endif + ctx->source_count = 0; + mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); + ctx->accumulator_started = -1; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ) +{ + int idx, ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + idx = ctx->source_count; + if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) + { + ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + ctx->source[idx].f_source = f_source; + ctx->source[idx].p_source = p_source; + ctx->source[idx].threshold = threshold; + ctx->source[idx].strong = strong; + + ctx->source_count++; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + int ret = 0; + + if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#else + if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#endif + p = tmp; + use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + + /* + * Start the accumulator if this has not already happened. Note that + * it is sufficient to start the accumulator here only because all calls to + * gather entropy eventually execute this code. + */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); +#else + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); +#endif + +cleanup: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + return( ret ); +} + +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + int i; + int have_one_strong = 0; + unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + have_one_strong = 1; + + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) + { + goto cleanup; + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + if( ( ret = entropy_update( ctx, (unsigned char) i, + buf, olen ) ) != 0 ) + return( ret ); + ctx->source[i].size += olen; + } + } + + if( have_one_strong == 0 ) + ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, thresholds_reached; + size_t strong_size; + mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + /* Update the NV entropy seed before generating any entropy for outside + * use. + */ + if( ctx->initial_entropy_run == 0 ) + { + ctx->initial_entropy_run = 1; + if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) + return( ret ); + } +#endif + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + thresholds_reached = 1; + strong_size = 0; + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].size < ctx->source[i].threshold ) + thresholds_reached = 0; + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + strong_size += ctx->source[i].size; + } + } + while( ! thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE ); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + /* + * Note that at this stage it is assumed that the accumulator was started + * in a previous call to entropy_update(). If this is not guaranteed, the + * code below will fail. + */ + if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha512_free( &ctx->accumulator ); + mbedtls_sha512_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-512 on entropy + */ + if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha256_free( &ctx->accumulator ); + mbedtls_sha256_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-256 on entropy + */ + if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; + + memcpy( output, buf, len ); + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + /* Read new seed and write it to NV */ + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + return( ret ); + + if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + /* Manually update the remaining stream with a separator value to diverge */ + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + return( ret ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f = NULL; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( f = fopen( path, "wb" ) ) == NULL ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( f != NULL ) + fclose( f ); + + return( ret ); +} + +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) + n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = mbedtls_entropy_update_manual( ctx, buf, n ); + + fclose( f ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_entropy_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) +{ + int ret = 0; + size_t entropy_len = 0; + size_t olen = 0; + size_t attempts = buf_len; + + while( attempts > 0 && entropy_len < buf_len ) + { + if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, + buf_len - entropy_len, &olen ) ) != 0 ) + return( ret ); + + entropy_len += olen; + attempts--; + } + + if( entropy_len < buf_len ) + { + ret = 1; + } + + return( ret ); +} + + +static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, + size_t buf_len ) +{ + unsigned char set= 0xFF; + unsigned char unset = 0x00; + size_t i; + + for( i = 0; i < buf_len; i++ ) + { + set &= buf[i]; + unset |= buf[i]; + } + + return( set == 0xFF || unset == 0x00 ); +} + +/* + * A test to ensure hat the entropy sources are functioning correctly + * and there is no obvious failure. The test performs the following checks: + * - The entropy source is not providing only 0s (all bits unset) or 1s (all + * bits set). + * - The entropy source is not providing values in a pattern. Because the + * hardware could be providing data in an arbitrary length, this check polls + * the hardware entropy source twice and compares the result to ensure they + * are not equal. + * - The error code returned by the entropy source is not an error. + */ +int mbedtls_entropy_source_self_test( int verbose ) +{ + int ret = 0; + unsigned char buf0[2 * sizeof( unsigned long long int )]; + unsigned char buf1[2 * sizeof( unsigned long long int )]; + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY_BIAS test: " ); + + memset( buf0, 0x00, sizeof( buf0 ) ); + memset( buf1, 0x00, sizeof( buf1 ) ); + + if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the returned values are not all 0 or 1 */ + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the entropy source is not returning values in a + * pattern */ + ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} + +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int mbedtls_entropy_self_test( int verbose ) +{ + int ret = 1; +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_context ctx; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY test: " ); + +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_init( &ctx ); + + /* First do a gather to make sure we have default sources */ + if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, + MBEDTLS_ENTROPY_SOURCE_WEAK ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that mbedtls_entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) + goto cleanup; +#endif + +cleanup: + mbedtls_entropy_free( &ctx ); +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c new file mode 100644 index 0000000..2c1e093 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/entropy_poll.c @@ -0,0 +1,291 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(__linux__) && !defined(_GNU_SOURCE) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + +#include "common.h" + +#include + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_TIMING_C) +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__)) +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM +#include + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} +#endif /* SYS_getrandom */ +#endif /* __linux__ || __midipix__ */ + +#if defined(__FreeBSD__) || defined(__DragonFly__) +#include +#if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \ + (defined(__DragonFly__) && __DragonFly_version >= 500700) +#include +#include +#define HAVE_GETRANDOM +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + return getrandom( buf, buflen, flags ); +} +#endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) || + (__DragonFly__ && __DragonFly_version >= 500700) */ +#endif /* __FreeBSD__ || __DragonFly__ */ + +/* + * Some BSD systems provide KERN_ARND. + * This is equivalent to reading from /dev/urandom, only it doesn't require an + * open file descriptor, and provides up to 256 bytes per call (basically the + * same as getentropy(), but with a longer history). + * + * Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7 + */ +#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM) +#include +#include +#if defined(KERN_ARND) +#define HAVE_SYSCTL_ARND + +static int sysctl_arnd_wrapper( unsigned char *buf, size_t buflen ) +{ + int name[2]; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_ARND; + + while( buflen > 0 ) + { + len = buflen > 256 ? 256 : buflen; + if( sysctl(name, 2, buf, &len, NULL, 0) == -1 ) + return( -1 ); + buflen -= len; + buf += len; + } + return( 0 ); +} +#endif /* KERN_ARND */ +#endif /* __FreeBSD__ || __NetBSD__ */ + +#include + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) data); + +#if defined(HAVE_GETRANDOM) + ret = getrandom_wrapper( output, len, 0 ); + if( ret >= 0 ) + { + *olen = ret; + return( 0 ); + } + else if( errno != ENOSYS ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + /* Fall through if the system call isn't known. */ +#else + ((void) ret); +#endif /* HAVE_GETRANDOM */ + +#if defined(HAVE_SYSCTL_ARND) + ((void) file); + ((void) read_len); + if( sysctl_arnd_wrapper( output, len ) == -1 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + *olen = len; + return( 0 ); +#else + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +#endif /* HAVE_SYSCTL_ARND */ +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + + *olen = 0; + if( len < sizeof(unsigned char) ) + return( 0 ); + + output[0] = 0; + *olen = sizeof(unsigned char); + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/error.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/error.c new file mode 100644 index 0000000..afad389 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/error.c @@ -0,0 +1,980 @@ +/* + * Error message information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#include "mbedtls/error.h" + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +#if defined(MBEDTLS_ERROR_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#include +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "mbedtls/base64.h" +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ENTROPY_C) +#include "mbedtls/entropy.h" +#endif + +#if defined(MBEDTLS_ERROR_C) +#include "mbedtls/error.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_HKDF_C) +#include "mbedtls/hkdf.h" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + +#if defined(MBEDTLS_OID_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#endif + +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#endif + + +const char * mbedtls_high_level_strerr( int error_code ) +{ + int high_level_error_code; + + if( error_code < 0 ) + error_code = -error_code; + + /* Extract the high-level part from the error code. */ + high_level_error_code = error_code & 0xFF80; + + switch( high_level_error_code ) + { + /* Begin Auto-Generated Code. */ +#if defined(MBEDTLS_CIPHER_C) + case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE): + return( "CIPHER - The selected feature is not available" ); + case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA): + return( "CIPHER - Bad input parameters" ); + case -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED): + return( "CIPHER - Failed to allocate memory" ); + case -(MBEDTLS_ERR_CIPHER_INVALID_PADDING): + return( "CIPHER - Input data contains invalid padding and is rejected" ); + case -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED): + return( "CIPHER - Decryption of block requires a full block" ); + case -(MBEDTLS_ERR_CIPHER_AUTH_FAILED): + return( "CIPHER - Authentication failed (for AEAD modes)" ); + case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT): + return( "CIPHER - The context is invalid. For example, because it was freed" ); + case -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED): + return( "CIPHER - Cipher hardware accelerator failed" ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_DHM_C) + case -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA): + return( "DHM - Bad input parameters" ); + case -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED): + return( "DHM - Reading of the DHM parameters failed" ); + case -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED): + return( "DHM - Making of the DHM parameters failed" ); + case -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED): + return( "DHM - Reading of the public values failed" ); + case -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED): + return( "DHM - Making of the public value failed" ); + case -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED): + return( "DHM - Calculation of the DHM secret failed" ); + case -(MBEDTLS_ERR_DHM_INVALID_FORMAT): + return( "DHM - The ASN.1 data is not formatted correctly" ); + case -(MBEDTLS_ERR_DHM_ALLOC_FAILED): + return( "DHM - Allocation of memory failed" ); + case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR): + return( "DHM - Read or write of file failed" ); + case -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED): + return( "DHM - DHM hardware accelerator failed" ); + case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED): + return( "DHM - Setting the modulus and generator failed" ); +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECP_C) + case -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA): + return( "ECP - Bad input parameters to function" ); + case -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL): + return( "ECP - The buffer is too small to write to" ); + case -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE): + return( "ECP - The requested feature is not available, for example, the requested curve is not supported" ); + case -(MBEDTLS_ERR_ECP_VERIFY_FAILED): + return( "ECP - The signature is not valid" ); + case -(MBEDTLS_ERR_ECP_ALLOC_FAILED): + return( "ECP - Memory allocation failed" ); + case -(MBEDTLS_ERR_ECP_RANDOM_FAILED): + return( "ECP - Generation of random value, such as ephemeral key, failed" ); + case -(MBEDTLS_ERR_ECP_INVALID_KEY): + return( "ECP - Invalid private or public key" ); + case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH): + return( "ECP - The buffer contains a valid signature followed by more data" ); + case -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED): + return( "ECP - The ECP hardware accelerator failed" ); + case -(MBEDTLS_ERR_ECP_IN_PROGRESS): + return( "ECP - Operation in progress, call again with the same parameters to continue" ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) + case -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE): + return( "MD - The selected feature is not available" ); + case -(MBEDTLS_ERR_MD_BAD_INPUT_DATA): + return( "MD - Bad input parameters to function" ); + case -(MBEDTLS_ERR_MD_ALLOC_FAILED): + return( "MD - Failed to allocate memory" ); + case -(MBEDTLS_ERR_MD_FILE_IO_ERROR): + return( "MD - Opening or reading of file failed" ); + case -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED): + return( "MD - MD hardware accelerator failed" ); +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + case -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT): + return( "PEM - No PEM header or footer found" ); + case -(MBEDTLS_ERR_PEM_INVALID_DATA): + return( "PEM - PEM string is not as expected" ); + case -(MBEDTLS_ERR_PEM_ALLOC_FAILED): + return( "PEM - Failed to allocate memory" ); + case -(MBEDTLS_ERR_PEM_INVALID_ENC_IV): + return( "PEM - RSA IV is not in hex-format" ); + case -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG): + return( "PEM - Unsupported key encryption algorithm" ); + case -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED): + return( "PEM - Private key password can't be empty" ); + case -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH): + return( "PEM - Given private key password does not allow for correct decryption" ); + case -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE): + return( "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + case -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA): + return( "PEM - Bad input parameters to function" ); +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + case -(MBEDTLS_ERR_PK_ALLOC_FAILED): + return( "PK - Memory allocation failed" ); + case -(MBEDTLS_ERR_PK_TYPE_MISMATCH): + return( "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + case -(MBEDTLS_ERR_PK_BAD_INPUT_DATA): + return( "PK - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PK_FILE_IO_ERROR): + return( "PK - Read/write of file failed" ); + case -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION): + return( "PK - Unsupported key version" ); + case -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT): + return( "PK - Invalid key tag or value" ); + case -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG): + return( "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + case -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED): + return( "PK - Private key password can't be empty" ); + case -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH): + return( "PK - Given private key password does not allow for correct decryption" ); + case -(MBEDTLS_ERR_PK_INVALID_PUBKEY): + return( "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + case -(MBEDTLS_ERR_PK_INVALID_ALG): + return( "PK - The algorithm tag or value is invalid" ); + case -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE): + return( "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + case -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE): + return( "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH): + return( "PK - The buffer contains a valid signature followed by more data" ); + case -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED): + return( "PK - PK hardware accelerator failed" ); +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PKCS12_C) + case -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA): + return( "PKCS12 - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE): + return( "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + case -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT): + return( "PKCS12 - PBE ASN.1 data not as expected" ); + case -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH): + return( "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PKCS5_C) + case -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA): + return( "PKCS5 - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT): + return( "PKCS5 - Unexpected ASN.1 data" ); + case -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE): + return( "PKCS5 - Requested encryption or digest alg not available" ); + case -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH): + return( "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_RSA_C) + case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA): + return( "RSA - Bad input parameters to function" ); + case -(MBEDTLS_ERR_RSA_INVALID_PADDING): + return( "RSA - Input data contains invalid padding and is rejected" ); + case -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED): + return( "RSA - Something failed during generation of a key" ); + case -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED): + return( "RSA - Key failed to pass the validity check of the library" ); + case -(MBEDTLS_ERR_RSA_PUBLIC_FAILED): + return( "RSA - The public key operation failed" ); + case -(MBEDTLS_ERR_RSA_PRIVATE_FAILED): + return( "RSA - The private key operation failed" ); + case -(MBEDTLS_ERR_RSA_VERIFY_FAILED): + return( "RSA - The PKCS#1 verification failed" ); + case -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE): + return( "RSA - The output buffer for decryption is not large enough" ); + case -(MBEDTLS_ERR_RSA_RNG_FAILED): + return( "RSA - The random generator failed to generate non-zeros" ); + case -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION): + return( "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); + case -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED): + return( "RSA - RSA hardware accelerator failed" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE): + return( "SSL - The requested feature is not available" ); + case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA): + return( "SSL - Bad input parameters to function" ); + case -(MBEDTLS_ERR_SSL_INVALID_MAC): + return( "SSL - Verification of the message MAC failed" ); + case -(MBEDTLS_ERR_SSL_INVALID_RECORD): + return( "SSL - An invalid SSL record was received" ); + case -(MBEDTLS_ERR_SSL_CONN_EOF): + return( "SSL - The connection indicated an EOF" ); + case -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER): + return( "SSL - An unknown cipher was received" ); + case -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN): + return( "SSL - The server has no ciphersuites in common with the client" ); + case -(MBEDTLS_ERR_SSL_NO_RNG): + return( "SSL - No RNG was provided to the SSL module" ); + case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE): + return( "SSL - No client certification received from the client, but required by the authentication mode" ); + case -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE): + return( "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + case -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED): + return( "SSL - The own certificate is not set, but needed by the server" ); + case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED): + return( "SSL - The own private key or pre-shared key is not set, but needed" ); + case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED): + return( "SSL - No CA Chain is set, but required to operate" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE): + return( "SSL - An unexpected message was received from our peer" ); + case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE): + return( "SSL - A fatal alert message was received from our peer" ); + case -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED): + return( "SSL - Verification of our peer failed" ); + case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY): + return( "SSL - The peer notified us that the connection is going to be closed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO): + return( "SSL - Processing of the ClientHello handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO): + return( "SSL - Processing of the ServerHello handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE): + return( "SSL - Processing of the Certificate handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST): + return( "SSL - Processing of the CertificateRequest handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE): + return( "SSL - Processing of the ServerKeyExchange handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE): + return( "SSL - Processing of the ServerHelloDone handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE): + return( "SSL - Processing of the ClientKeyExchange handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP): + return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS): + return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY): + return( "SSL - Processing of the CertificateVerify handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC): + return( "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED): + return( "SSL - Processing of the Finished handshake message failed" ); + case -(MBEDTLS_ERR_SSL_ALLOC_FAILED): + return( "SSL - Memory allocation failed" ); + case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED): + return( "SSL - Hardware acceleration function returned with error" ); + case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH): + return( "SSL - Hardware acceleration function skipped / left alone data" ); + case -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED): + return( "SSL - Processing of the compression / decompression failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION): + return( "SSL - Handshake protocol not within min/max boundaries" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET): + return( "SSL - Processing of the NewSessionTicket handshake message failed" ); + case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED): + return( "SSL - Session ticket has expired" ); + case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH): + return( "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + case -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY): + return( "SSL - Unknown identity received (eg, PSK identity)" ); + case -(MBEDTLS_ERR_SSL_INTERNAL_ERROR): + return( "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + case -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING): + return( "SSL - A counter would wrap (eg, too many messages exchanged)" ); + case -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO): + return( "SSL - Unexpected message at ServerHello in renegotiation" ); + case -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED): + return( "SSL - DTLS client must retry for hello verification" ); + case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL): + return( "SSL - A buffer is too small to receive or write a message" ); + case -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE): + return( "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + case -(MBEDTLS_ERR_SSL_WANT_READ): + return( "SSL - No data of requested type currently available on underlying transport" ); + case -(MBEDTLS_ERR_SSL_WANT_WRITE): + return( "SSL - Connection requires a write call" ); + case -(MBEDTLS_ERR_SSL_TIMEOUT): + return( "SSL - The operation timed out" ); + case -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT): + return( "SSL - The client initiated a reconnect from the same port" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD): + return( "SSL - Record header looks valid but is not expected" ); + case -(MBEDTLS_ERR_SSL_NON_FATAL): + return( "SSL - The alert message received indicates a non-fatal error" ); + case -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH): + return( "SSL - Couldn't set the hash for verifying CertificateVerify" ); + case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING): + return( "SSL - Internal-only message signaling that further message-processing should be done" ); + case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS): + return( "SSL - The asynchronous operation is not completed yet" ); + case -(MBEDTLS_ERR_SSL_EARLY_MESSAGE): + return( "SSL - Internal-only message signaling that a message arrived early" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_CID): + return( "SSL - An encrypted DTLS-frame with an unexpected CID was received" ); + case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH): + return( "SSL - An operation failed due to an unexpected version or configuration" ); + case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): + return( "SSL - A cryptographic operation is in progress. Try again later" ); + case -(MBEDTLS_ERR_SSL_BAD_CONFIG): + return( "SSL - Invalid value in SSL config" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + case -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE): + return( "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_OID): + return( "X509 - Requested OID is unknown" ); + case -(MBEDTLS_ERR_X509_INVALID_FORMAT): + return( "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + case -(MBEDTLS_ERR_X509_INVALID_VERSION): + return( "X509 - The CRT/CRL/CSR version element is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_SERIAL): + return( "X509 - The serial tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_ALG): + return( "X509 - The algorithm tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_NAME): + return( "X509 - The name tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_DATE): + return( "X509 - The date tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_SIGNATURE): + return( "X509 - The signature tag or value invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS): + return( "X509 - The extension tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_VERSION): + return( "X509 - CRT/CRL/CSR has an unsupported version number" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG): + return( "X509 - Signature algorithm (oid) is unsupported" ); + case -(MBEDTLS_ERR_X509_SIG_MISMATCH): + return( "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + case -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED): + return( "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + case -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT): + return( "X509 - Format not recognized as DER or PEM" ); + case -(MBEDTLS_ERR_X509_BAD_INPUT_DATA): + return( "X509 - Input invalid" ); + case -(MBEDTLS_ERR_X509_ALLOC_FAILED): + return( "X509 - Allocation of memory failed" ); + case -(MBEDTLS_ERR_X509_FILE_IO_ERROR): + return( "X509 - Read/write of file failed" ); + case -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL): + return( "X509 - Destination buffer is too small" ); + case -(MBEDTLS_ERR_X509_FATAL_ERROR): + return( "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" ); +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + /* End Auto-Generated Code. */ + + default: + break; + } + + return( NULL ); +} + +const char * mbedtls_low_level_strerr( int error_code ) +{ + int low_level_error_code; + + if( error_code < 0 ) + error_code = -error_code; + + /* Extract the low-level part from the error code. */ + low_level_error_code = error_code & ~0xFF80; + + switch( low_level_error_code ) + { + /* Begin Auto-Generated Code. */ +#if defined(MBEDTLS_AES_C) + case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH): + return( "AES - Invalid key length" ); + case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH): + return( "AES - Invalid data input length" ); + case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA): + return( "AES - Invalid input data" ); + case -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE): + return( "AES - Feature not available. For example, an unsupported AES key size" ); + case -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED): + return( "AES - AES hardware accelerator failed" ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + case -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED): + return( "ARC4 - ARC4 hardware accelerator failed" ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_ARIA_C) + case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA): + return( "ARIA - Bad input data" ); + case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH): + return( "ARIA - Invalid data input length" ); + case -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE): + return( "ARIA - Feature not available. For example, an unsupported ARIA key size" ); + case -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED): + return( "ARIA - ARIA hardware accelerator failed" ); +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_ASN1_PARSE_C) + case -(MBEDTLS_ERR_ASN1_OUT_OF_DATA): + return( "ASN1 - Out of data when parsing an ASN1 data structure" ); + case -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG): + return( "ASN1 - ASN1 tag was of an unexpected value" ); + case -(MBEDTLS_ERR_ASN1_INVALID_LENGTH): + return( "ASN1 - Error when trying to determine the length or invalid length" ); + case -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH): + return( "ASN1 - Actual length differs from expected length" ); + case -(MBEDTLS_ERR_ASN1_INVALID_DATA): + return( "ASN1 - Data is invalid" ); + case -(MBEDTLS_ERR_ASN1_ALLOC_FAILED): + return( "ASN1 - Memory allocation failed" ); + case -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL): + return( "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_BASE64_C) + case -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL): + return( "BASE64 - Output buffer too small" ); + case -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER): + return( "BASE64 - Invalid character in input" ); +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_BIGNUM_C) + case -(MBEDTLS_ERR_MPI_FILE_IO_ERROR): + return( "BIGNUM - An error occurred while reading from or writing to a file" ); + case -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA): + return( "BIGNUM - Bad input parameters to function" ); + case -(MBEDTLS_ERR_MPI_INVALID_CHARACTER): + return( "BIGNUM - There is an invalid character in the digit string" ); + case -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL): + return( "BIGNUM - The buffer is too small to write to" ); + case -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE): + return( "BIGNUM - The input arguments are negative or result in illegal output" ); + case -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO): + return( "BIGNUM - The input argument for division is zero, which is not allowed" ); + case -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE): + return( "BIGNUM - The input arguments are not acceptable" ); + case -(MBEDTLS_ERR_MPI_ALLOC_FAILED): + return( "BIGNUM - Memory allocation failed" ); +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + case -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA): + return( "BLOWFISH - Bad input data" ); + case -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH): + return( "BLOWFISH - Invalid data input length" ); + case -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED): + return( "BLOWFISH - Blowfish hardware accelerator failed" ); +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA): + return( "CAMELLIA - Bad input data" ); + case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH): + return( "CAMELLIA - Invalid data input length" ); + case -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED): + return( "CAMELLIA - Camellia hardware accelerator failed" ); +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CCM_C) + case -(MBEDTLS_ERR_CCM_BAD_INPUT): + return( "CCM - Bad input parameters to the function" ); + case -(MBEDTLS_ERR_CCM_AUTH_FAILED): + return( "CCM - Authenticated decryption failed" ); + case -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED): + return( "CCM - CCM hardware accelerator failed" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CHACHA20_C) + case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA): + return( "CHACHA20 - Invalid input parameter(s)" ); + case -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE): + return( "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); + case -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED): + return( "CHACHA20 - Chacha20 hardware accelerator failed" ); +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + case -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE): + return( "CHACHAPOLY - The requested operation is not permitted in the current state" ); + case -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED): + return( "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CMAC_C) + case -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED): + return( "CMAC - CMAC hardware accelerator failed" ); +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) + case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED): + return( "CTR_DRBG - The entropy source failed" ); + case -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG): + return( "CTR_DRBG - The requested random buffer length is too big" ); + case -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG): + return( "CTR_DRBG - The input (entropy + additional data) is too large" ); + case -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR): + return( "CTR_DRBG - Read or write error in file" ); +#endif /* MBEDTLS_CTR_DRBG_C */ + +#if defined(MBEDTLS_DES_C) + case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH): + return( "DES - The data input has an invalid length" ); + case -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED): + return( "DES - DES hardware accelerator failed" ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ENTROPY_C) + case -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED): + return( "ENTROPY - Critical entropy source failure" ); + case -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES): + return( "ENTROPY - No more sources can be added" ); + case -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED): + return( "ENTROPY - No sources have been added to poll" ); + case -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE): + return( "ENTROPY - No strong sources have been added to poll" ); + case -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR): + return( "ENTROPY - Read/write error in file" ); +#endif /* MBEDTLS_ENTROPY_C */ + +#if defined(MBEDTLS_ERROR_C) + case -(MBEDTLS_ERR_ERROR_GENERIC_ERROR): + return( "ERROR - Generic error" ); + case -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED): + return( "ERROR - This is a bug in the library" ); +#endif /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_GCM_C) + case -(MBEDTLS_ERR_GCM_AUTH_FAILED): + return( "GCM - Authenticated decryption failed" ); + case -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED): + return( "GCM - GCM hardware accelerator failed" ); + case -(MBEDTLS_ERR_GCM_BAD_INPUT): + return( "GCM - Bad input parameters to function" ); +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HKDF_C) + case -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA): + return( "HKDF - Bad input parameters to function" ); +#endif /* MBEDTLS_HKDF_C */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + case -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG): + return( "HMAC_DRBG - Too many random requested in single call" ); + case -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG): + return( "HMAC_DRBG - Input too large (Entropy + additional)" ); + case -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR): + return( "HMAC_DRBG - Read/write error in file" ); + case -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED): + return( "HMAC_DRBG - The entropy source failed" ); +#endif /* MBEDTLS_HMAC_DRBG_C */ + +#if defined(MBEDTLS_MD2_C) + case -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED): + return( "MD2 - MD2 hardware accelerator failed" ); +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + case -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED): + return( "MD4 - MD4 hardware accelerator failed" ); +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + case -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED): + return( "MD5 - MD5 hardware accelerator failed" ); +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_NET_C) + case -(MBEDTLS_ERR_NET_SOCKET_FAILED): + return( "NET - Failed to open a socket" ); + case -(MBEDTLS_ERR_NET_CONNECT_FAILED): + return( "NET - The connection to the given server / port failed" ); + case -(MBEDTLS_ERR_NET_BIND_FAILED): + return( "NET - Binding of the socket failed" ); + case -(MBEDTLS_ERR_NET_LISTEN_FAILED): + return( "NET - Could not listen on the socket" ); + case -(MBEDTLS_ERR_NET_ACCEPT_FAILED): + return( "NET - Could not accept the incoming connection" ); + case -(MBEDTLS_ERR_NET_RECV_FAILED): + return( "NET - Reading information from the socket failed" ); + case -(MBEDTLS_ERR_NET_SEND_FAILED): + return( "NET - Sending information through the socket failed" ); + case -(MBEDTLS_ERR_NET_CONN_RESET): + return( "NET - Connection was reset by peer" ); + case -(MBEDTLS_ERR_NET_UNKNOWN_HOST): + return( "NET - Failed to get an IP address for the given hostname" ); + case -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL): + return( "NET - Buffer is too small to hold the data" ); + case -(MBEDTLS_ERR_NET_INVALID_CONTEXT): + return( "NET - The context is invalid, eg because it was free()ed" ); + case -(MBEDTLS_ERR_NET_POLL_FAILED): + return( "NET - Polling the net context failed" ); + case -(MBEDTLS_ERR_NET_BAD_INPUT_DATA): + return( "NET - Input invalid" ); +#endif /* MBEDTLS_NET_C */ + +#if defined(MBEDTLS_OID_C) + case -(MBEDTLS_ERR_OID_NOT_FOUND): + return( "OID - OID is not found" ); + case -(MBEDTLS_ERR_OID_BUF_TOO_SMALL): + return( "OID - output buffer is too small" ); +#endif /* MBEDTLS_OID_C */ + +#if defined(MBEDTLS_PADLOCK_C) + case -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED): + return( "PADLOCK - Input data should be aligned" ); +#endif /* MBEDTLS_PADLOCK_C */ + +#if defined(MBEDTLS_PLATFORM_C) + case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED): + return( "PLATFORM - Hardware accelerator failed" ); + case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED): + return( "PLATFORM - The requested feature is not supported by the platform" ); +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_POLY1305_C) + case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA): + return( "POLY1305 - Invalid input parameter(s)" ); + case -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE): + return( "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); + case -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED): + return( "POLY1305 - Poly1305 hardware accelerator failed" ); +#endif /* MBEDTLS_POLY1305_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + case -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED): + return( "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + case -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED): + return( "SHA1 - SHA-1 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA): + return( "SHA1 - SHA-1 input data was malformed" ); +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + case -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED): + return( "SHA256 - SHA-256 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA): + return( "SHA256 - SHA-256 input data was malformed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + case -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED): + return( "SHA512 - SHA-512 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA): + return( "SHA512 - SHA-512 input data was malformed" ); +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_THREADING_C) + case -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE): + return( "THREADING - The selected feature is not available" ); + case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA): + return( "THREADING - Bad input parameters to function" ); + case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR): + return( "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* MBEDTLS_THREADING_C */ + +#if defined(MBEDTLS_XTEA_C) + case -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH): + return( "XTEA - The data input has an invalid length" ); + case -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED): + return( "XTEA - XTEA hardware accelerator failed" ); +#endif /* MBEDTLS_XTEA_C */ + /* End Auto-Generated Code. */ + + default: + break; + } + + return( NULL ); +} + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + const char * high_level_error_description = NULL; + const char * low_level_error_description = NULL; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // Translate high level error code. + high_level_error_description = mbedtls_high_level_strerr( ret ); + + if( high_level_error_description == NULL ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret ); + else + mbedtls_snprintf( buf, buflen, "%s", high_level_error_description ); + +#if defined(MBEDTLS_SSL_TLS_C) + // Early return in case of a fatal error - do not try to translate low + // level code. + if(use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) + return; +#endif /* MBEDTLS_SSL_TLS_C */ + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Translate low level error code. + low_level_error_description = mbedtls_low_level_strerr( ret ); + + if( low_level_error_description == NULL ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret ); + else + mbedtls_snprintf( buf, buflen, "%s", low_level_error_description ); +} + +#else /* MBEDTLS_ERROR_C */ + +/* + * Provide an non-function in case MBEDTLS_ERROR_C is not defined + */ +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#endif /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_TEST_HOOKS) +void (*mbedtls_test_hook_error_add)( int, int, const char *, int ); +#endif + +#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c new file mode 100644 index 0000000..43a5e1b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/gcm.c @@ -0,0 +1,1003 @@ +/* + * NIST SP800-38D compliant GCM implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + * + * See also: + * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + * + * We use the algorithm described as Shoup's method with 4-bit tables in + * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. + */ + +#include "common.h" + +#if defined(MBEDTLS_GCM_C) + +#include "mbedtls/gcm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_GCM_ALT) + +/* Parameter validation macros */ +#define GCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT ) +#define GCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Initialize a context + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) +{ + GCM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); +} + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( mbedtls_gcm_context *ctx ) +{ + int ret, i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char h[16]; + size_t olen = 0; + + memset( h, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); + + /* pack h as two 64-bits ints, big-endian */ + hi = MBEDTLS_GET_UINT32_BE( h, 0 ); + lo = MBEDTLS_GET_UINT32_BE( h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + hi = MBEDTLS_GET_UINT32_BE( h, 8 ); + lo = MBEDTLS_GET_UINT32_BE( h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) + return( 0 ); +#endif + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for( i = 4; i > 0; i >>= 1 ) + { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for( i = 2; i <= 8; i *= 2 ) + { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for( j = 1; j < i; j++ ) + { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return( 0 ); +} + +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( key != NULL ); + GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 ); + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = +{ + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { + unsigned char h[16]; + + MBEDTLS_PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); + MBEDTLS_PUT_UINT32_BE( ctx->HH[8], h, 4 ); + MBEDTLS_PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); + MBEDTLS_PUT_UINT32_BE( ctx->HL[8], h, 12 ); + + mbedtls_aesni_gcm_mult( output, x, h ); + return; + } +#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ + + lo = x[15] & 0xf; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + for( i = 15; i >= 0; i-- ) + { + lo = x[i] & 0xf; + hi = ( x[i] >> 4 ) & 0xf; + + if( i != 15 ) + { + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + } + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + MBEDTLS_PUT_UINT32_BE( zh >> 32, output, 0 ); + MBEDTLS_PUT_UINT32_BE( zh, output, 4 ); + MBEDTLS_PUT_UINT32_BE( zl >> 32, output, 8 ); + MBEDTLS_PUT_UINT32_BE( zl, output, 12 ); +} + +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char work_buf[16]; + size_t i; + const unsigned char *p; + size_t use_len, olen = 0; + uint64_t iv_bits; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + /* IV is not allowed to be zero length */ + if( iv_len == 0 || + ( (uint64_t) iv_len ) >> 61 != 0 || + ( (uint64_t) add_len ) >> 61 != 0 ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + memset( ctx->y, 0x00, sizeof(ctx->y) ); + memset( ctx->buf, 0x00, sizeof(ctx->buf) ); + + ctx->mode = mode; + ctx->len = 0; + ctx->add_len = 0; + + if( iv_len == 12 ) + { + memcpy( ctx->y, iv, iv_len ); + ctx->y[15] = 1; + } + else + { + memset( work_buf, 0x00, 16 ); + iv_bits = (uint64_t)iv_len * 8; + MBEDTLS_PUT_UINT64_BE( iv_bits, work_buf, 8 ); + + p = iv; + while( iv_len > 0 ) + { + use_len = ( iv_len < 16 ) ? iv_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->y[i] ^= p[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + + iv_len -= use_len; + p += use_len; + } + + for( i = 0; i < 16; i++ ) + ctx->y[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + } + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, + ctx->base_ectr, &olen ) ) != 0 ) + { + return( ret ); + } + + ctx->add_len = add_len; + p = add; + while( add_len > 0 ) + { + use_len = ( add_len < 16 ) ? add_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->buf[i] ^= p[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + add_len -= use_len; + p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char ectr[16]; + size_t i; + const unsigned char *p; + unsigned char *out_p = output; + size_t use_len, olen = 0; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + + if( output > input && (size_t) ( output - input ) < length ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if( ctx->len + length < ctx->len || + (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + ctx->len += length; + + p = input; + while( length > 0 ) + { + use_len = ( length < 16 ) ? length : 16; + + for( i = 16; i > 12; i-- ) + if( ++ctx->y[i - 1] != 0 ) + break; + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == MBEDTLS_GCM_DECRYPT ) + ctx->buf[i] ^= p[i]; + out_p[i] = ectr[i] ^ p[i]; + if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) + ctx->buf[i] ^= out_p[i]; + } + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + length -= use_len; + p += use_len; + out_p += use_len; + } + + return( 0 ); +} + +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ) +{ + unsigned char work_buf[16]; + size_t i; + uint64_t orig_len; + uint64_t orig_add_len; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + orig_len = ctx->len * 8; + orig_add_len = ctx->add_len * 8; + + if( tag_len > 16 || tag_len < 4 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + memcpy( tag, ctx->base_ectr, tag_len ); + + if( orig_len || orig_add_len ) + { + memset( work_buf, 0x00, 16 ); + + MBEDTLS_PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); + MBEDTLS_PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); + MBEDTLS_PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); + MBEDTLS_PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); + + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + for( i = 0; i < tag_len; i++ ) + tag[i] ^= ctx->buf[i]; + } + + return( 0 ); +} + +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + size_t i; + int diff; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) +{ + if( ctx == NULL ) + return; + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); +} + +#endif /* !MBEDTLS_GCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * AES-GCM test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip + */ +#define MAX_TESTS 6 + +static const int key_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char key_test_data[MAX_TESTS][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 }, + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, +}; + +static const size_t iv_len_test_data[MAX_TESTS] = + { 12, 12, 12, 12, 8, 60 }; + +static const int iv_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 2 }; + +static const unsigned char iv_test_data[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 }, + { 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 }, +}; + +static const size_t add_len_test_data[MAX_TESTS] = + { 0, 0, 0, 20, 20, 20 }; + +static const int add_index_test_data[MAX_TESTS] = + { 0, 0, 0, 1, 1, 1 }; + +static const unsigned char additional_test_data[MAX_TESTS][64] = +{ + { 0x00 }, + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 }, +}; + +static const size_t pt_len_test_data[MAX_TESTS] = + { 0, 16, 64, 60, 60, 60 }; + +static const int pt_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char pt_test_data[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 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 }, +}; + +static const unsigned char ct_test_data[MAX_TESTS * 3][64] = +{ + { 0x00 }, + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 0x00 }, + { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10 }, + { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7 }, + { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b }, + { 0x00 }, + { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 }, + { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f }, + { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f }, +}; + +static const unsigned char tag_test_data[MAX_TESTS * 3][16] = +{ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, + { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, + { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, + { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, + { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, + { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, + { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, + { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, + { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, + { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, + { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, + { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, + { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, +}; + +int mbedtls_gcm_self_test( int verbose ) +{ + mbedtls_gcm_context ctx; + unsigned char buf[64]; + unsigned char tag_buf[16]; + int i, j, ret; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 ) + { + mbedtls_printf( "skipped\n" ); + break; + } + else if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, + pt_len_test_data[i], + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i], + pt_test_data[pt_index_test_data[i]], + buf, 16, tag_buf ); +#if defined(MBEDTLS_GCM_ALT) + /* Allow alternative implementations to only support 12-byte nonces. */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && + iv_len_test_data[i] != 12 ) + { + mbedtls_printf( "skipped\n" ); + break; + } +#endif /* defined(MBEDTLS_GCM_ALT) */ + if( ret != 0 ) + goto exit; + + if ( memcmp( buf, ct_test_data[j * 6 + i], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, + pt_len_test_data[i], + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i], + ct_test_data[j * 6 + i], buf, 16, tag_buf ); + + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt_test_data[pt_index_test_data[i]], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len_test_data[i] > 32 ) + { + size_t rest_len = pt_len_test_data[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, + pt_test_data[pt_index_test_data[i]], + buf ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, + pt_test_data[pt_index_test_data[i]] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i], + pt_test_data[pt_index_test_data[i]], + buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, ct_test_data[j * 6 + i], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len_test_data[i] > 32 ) + { + size_t rest_len = pt_len_test_data[i] - 32; + ret = mbedtls_gcm_update( &ctx, 32, ct_test_data[j * 6 + i], + buf ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, rest_len, + ct_test_data[j * 6 + i] + 32, + buf + 32 ); + if( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, pt_len_test_data[i], + ct_test_data[j * 6 + i], + buf ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt_test_data[pt_index_test_data[i]], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + ret = 0; + +exit: + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + mbedtls_gcm_free( &ctx ); + } + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_GCM_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/havege.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/havege.c new file mode 100644 index 0000000..2a360a1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/havege.c @@ -0,0 +1,237 @@ +/** + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The HAVEGE RNG was designed by Andre Seznec in 2002. + * + * http://www.irisa.fr/caps/projects/hipsor/publi.php + * + * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr + */ + +#include "common.h" + +#if defined(MBEDTLS_HAVEGE_C) + +#include "mbedtls/havege.h" +#include "mbedtls/timing.h" +#include "mbedtls/platform_util.h" + +#include +#include + +/* ------------------------------------------------------------------------ + * On average, one iteration accesses two 8-word blocks in the havege WALK + * table, and generates 16 words in the RES array. + * + * The data read in the WALK table is updated and permuted after each use. + * The result of the hardware clock counter read is used for this update. + * + * 25 conditional tests are present. The conditional tests are grouped in + * two nested groups of 12 conditional tests and 1 test that controls the + * permutation; on average, there should be 6 tests executed and 3 of them + * should be mispredicted. + * ------------------------------------------------------------------------ + */ + +#define SWAP(X,Y) { uint32_t *T = (X); (X) = (Y); (Y) = T; } + +#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; +#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; + +#define TST1_LEAVE U1++; } +#define TST2_LEAVE U2++; } + +#define ONE_ITERATION \ + \ + PTEST = PT1 >> 20; \ + \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ + \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ + \ + PTX = (PT1 >> 18) & 7; \ + PT1 &= 0x1FFF; \ + PT2 &= 0x1FFF; \ + CLK = (uint32_t) mbedtls_timing_hardclock(); \ + \ + i = 0; \ + A = &WALK[PT1 ]; RES[i++] ^= *A; \ + B = &WALK[PT2 ]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ + \ + IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ + *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ + *B = IN ^ U1; \ + *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ + *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ + \ + if( PTEST & 1 ) SWAP( A, C ); \ + \ + IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ + *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ + *B = IN; CLK = (uint32_t) mbedtls_timing_hardclock(); \ + *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ + *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 4]; \ + B = &WALK[PT2 ^ 1]; \ + \ + PTEST = PT2 >> 1; \ + \ + PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ + PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ + PTY = (PT2 >> 10) & 7; \ + \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ + \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ + \ + C = &WALK[PT1 ^ 5]; \ + D = &WALK[PT2 ^ 5]; \ + \ + RES[i++] ^= *A; \ + RES[i++] ^= *B; \ + RES[i++] ^= *C; \ + RES[i++] ^= *D; \ + \ + IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ + *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ + *B = IN ^ U2; \ + *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ + *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ + \ + A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ + B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ + C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ + D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ + \ + IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ + *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ + *B = IN; \ + *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ + *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ + \ + PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ + WALK[PT1 ^ PTX ^ 7] ) & (~1); \ + PT1 ^= (PT2 ^ 0x10) & 0x10; \ + \ + for( n++, i = 0; i < 16; i++ ) \ + hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( mbedtls_havege_state *hs ) +{ + size_t n = 0; + size_t i; + uint32_t U1, U2, *A, *B, *C, *D; + uint32_t PT1, PT2, *WALK, RES[16]; + uint32_t PTX, PTY, CLK, PTEST, IN; + + WALK = hs->WALK; + PT1 = hs->PT1; + PT2 = hs->PT2; + + PTX = U1 = 0; + PTY = U2 = 0; + + (void)PTX; + + memset( RES, 0, sizeof( RES ) ); + + while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) + { + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + ONE_ITERATION + } + + hs->PT1 = PT1; + hs->PT2 = PT2; + + hs->offset[0] = 0; + hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; +} + +/* + * HAVEGE initialization + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ) +{ + memset( hs, 0, sizeof( mbedtls_havege_state ) ); + + havege_fill( hs ); +} + +void mbedtls_havege_free( mbedtls_havege_state *hs ) +{ + if( hs == NULL ) + return; + + mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) ); +} + +/* + * HAVEGE rand function + */ +int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) +{ + uint32_t val; + size_t use_len; + mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; + unsigned char *p = buf; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof( val ) ) + use_len = sizeof( val ); + + if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) + havege_fill( hs ); + + val = hs->pool[hs->offset[0]++]; + val ^= hs->pool[hs->offset[1]++]; + + memcpy( p, &val, use_len ); + + len -= use_len; + p += use_len; + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVEGE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c new file mode 100644 index 0000000..5013729 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/hkdf.c @@ -0,0 +1,189 @@ +/* + * HKDF implementation -- RFC 5869 + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "common.h" + +#if defined(MBEDTLS_HKDF_C) + +#include +#include "mbedtls/hkdf.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char prk[MBEDTLS_MD_MAX_SIZE]; + + ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); + + if( ret == 0 ) + { + ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), + info, info_len, okm, okm_len ); + } + + mbedtls_platform_zeroize( prk, sizeof( prk ) ); + + return( ret ); +} + +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ) +{ + unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; + + if( salt == NULL ) + { + size_t hash_len; + + if( salt_len != 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + hash_len = mbedtls_md_get_size( md ); + + if( hash_len == 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + salt = null_salt; + salt_len = hash_len; + } + + return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); +} + +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ) +{ + size_t hash_len; + size_t where = 0; + size_t n; + size_t t_len = 0; + size_t i; + int ret = 0; + mbedtls_md_context_t ctx; + unsigned char t[MBEDTLS_MD_MAX_SIZE]; + + if( okm == NULL ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + hash_len = mbedtls_md_get_size( md ); + + if( prk_len < hash_len || hash_len == 0 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + if( info == NULL ) + { + info = (const unsigned char *) ""; + info_len = 0; + } + + n = okm_len / hash_len; + + if( okm_len % hash_len != 0 ) + { + n++; + } + + /* + * Per RFC 5869 Section 2.3, okm_len must not exceed + * 255 times the hash length + */ + if( n > 255 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md, 1 ) ) != 0 ) + { + goto exit; + } + + memset( t, 0, hash_len ); + + /* + * Compute T = T(1) | T(2) | T(3) | ... | T(N) + * Where T(N) is defined in RFC 5869 Section 2.3 + */ + for( i = 1; i <= n; i++ ) + { + size_t num_to_copy; + unsigned char c = i & 0xff; + + ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, t, t_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, info, info_len ); + if( ret != 0 ) + { + goto exit; + } + + /* The constant concatenated to the end of each T(n) is a single octet. + * */ + ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_finish( &ctx, t ); + if( ret != 0 ) + { + goto exit; + } + + num_to_copy = i != n ? hash_len : okm_len - where; + memcpy( okm + where, t, num_to_copy ); + where += hash_len; + t_len = hash_len; + } + +exit: + mbedtls_md_free( &ctx ); + mbedtls_platform_zeroize( t, sizeof( t ) ); + + return( ret ); +} + +#endif /* MBEDTLS_HKDF_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c new file mode 100644 index 0000000..de97068 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/hmac_drbg.c @@ -0,0 +1,629 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The NIST SP 800-90A DRBGs are described in the following publication. + * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + * References below are based on rev. 1 (January 2012). + */ + +#include "common.h" + +#if defined(MBEDTLS_HMAC_DRBG_C) + +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* + * HMAC_DRBG context initialization + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[MBEDTLS_MD_MAX_SIZE]; + int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + sep, 1 ) ) != 0 ) + goto exit; + if( rounds == 2 ) + { + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) + goto exit; + + /* Step 2 or 5 */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_platform_zeroize( K, sizeof( K ) ); + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, + mbedtls_md_get_size( md_info ) ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); + + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Internal function used both for seeding and reseeding the DRBG. + * Comments starting with arabic numbers refer to section 10.1.2.4 + * of SP800-90A, while roman numbers refer to section 9.2. + */ +static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len, + int use_nonce ) +{ + unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + { + size_t total_entropy_len; + + if( use_nonce == 0 ) + total_entropy_len = ctx->entropy_len; + else + total_entropy_len = ctx->entropy_len * 3 / 2; + + /* III. Check input length */ + if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || + total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + } + + memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); + + /* IV. Gather entropy_len bytes of entropy for the seed */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed, ctx->entropy_len ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += ctx->entropy_len; + + /* For initial seeding, allow adding of nonce generated + * from the entropy source. See Sect 8.6.7 in SP800-90A. */ + if( use_nonce ) + { + /* Note: We don't merge the two calls to f_entropy() in order + * to avoid requesting too much entropy from f_entropy() + * at once. Specifically, if the underlying digest is not + * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which + * is larger than the maximum of 32 Bytes that our own + * entropy source implementation can emit in a single + * call in configurations disabling SHA-512. */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed + seedlen, + ctx->entropy_len / 2 ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len / 2; + } + + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 ) + goto exit; + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + +exit: + /* 4. Done */ + mbedtls_platform_zeroize( seed, seedlen ); + return( ret ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 + 9.2 + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + * + * The nonce is not passed as a separate parameter but extracted + * from the entropy source as suggested in 8.6.7. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t md_size; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + /* The mutex is initialized iff the md context is set up. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + md_size = mbedtls_md_get_size( md_info ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, md_size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + { + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + } + + if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, + 1 /* add nonce */ ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for seeding + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +/* + * HMAC_DRBG random function with optional additional data: + * 10.1.2.5 (arabic) + 9.3 (Roman) + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t out_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + + /* 1. (aka VII and IX) Check reseed counter and PR */ + if( ctx->f_entropy != NULL && /* For no-reseeding instances */ + ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; /* VII.4 */ + } + + /* 2. Use additional data if any */ + if( additional != NULL && add_len != 0 ) + { + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + +exit: + /* 8. Done */ + return( ret ); +} + +/* + * HMAC_DRBG random function + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + /* The mutex is initialized iff the md context is set up. */ + if( ctx->md_ctx.md_info != NULL ) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_md_free( &ctx->md_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f = NULL; + size_t n; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + unsigned char c; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; + goto exit; + } + if( n == 0 || ferror( f ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + fclose( f ); + f = NULL; + + ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n ); + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); + return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +/* Dummy checkup routine */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +#define OUTPUT_LEN 80 + +/* From a NIST PR=true test vector */ +static const unsigned char entropy_pr[] = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, + 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, + 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, + 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; +static const unsigned char result_pr[OUTPUT_LEN] = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, + 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, + 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, + 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, + 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, + 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; + +/* From a NIST PR=false test vector */ +static const unsigned char entropy_nopr[] = { + 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, + 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, + 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, + 0xe9, 0x9d, 0xfe, 0xdf }; +static const unsigned char result_nopr[OUTPUT_LEN] = { + 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, + 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, + 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, + 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, + 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, + 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, + 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; + +/* "Entropy" from buffer */ +static size_t test_offset; +static int hmac_drbg_self_test_entropy( void *data, + unsigned char *buf, size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + mbedtls_hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + + mbedtls_hmac_drbg_init( &ctx ); + + /* + * PR = True + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_pr, + NULL, 0 ) ); + mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = False) : " ); + + mbedtls_hmac_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_nopr, + NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/md.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/md.c new file mode 100644 index 0000000..341a9cf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/md.c @@ -0,0 +1,893 @@ +/** + * \file md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_MD2_C) +const mbedtls_md_info_t mbedtls_md2_info = { + "MD2", + MBEDTLS_MD_MD2, + 16, + 16, +}; +#endif + +#if defined(MBEDTLS_MD4_C) +const mbedtls_md_info_t mbedtls_md4_info = { + "MD4", + MBEDTLS_MD_MD4, + 16, + 64, +}; +#endif + +#if defined(MBEDTLS_MD5_C) +const mbedtls_md_info_t mbedtls_md5_info = { + "MD5", + MBEDTLS_MD_MD5, + 16, + 64, +}; +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +const mbedtls_md_info_t mbedtls_ripemd160_info = { + "RIPEMD160", + MBEDTLS_MD_RIPEMD160, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA1_C) +const mbedtls_md_info_t mbedtls_sha1_info = { + "SHA1", + MBEDTLS_MD_SHA1, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA256_C) +const mbedtls_md_info_t mbedtls_sha224_info = { + "SHA224", + MBEDTLS_MD_SHA224, + 28, + 64, +}; + +const mbedtls_md_info_t mbedtls_sha256_info = { + "SHA256", + MBEDTLS_MD_SHA256, + 32, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) +const mbedtls_md_info_t mbedtls_sha384_info = { + "SHA384", + MBEDTLS_MD_SHA384, + 48, + 128, +}; +#endif + +const mbedtls_md_info_t mbedtls_sha512_info = { + "SHA512", + MBEDTLS_MD_SHA512, + 64, + 128, +}; +#endif + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, +#if !defined(MBEDTLS_SHA512_NO_SHA384) + MBEDTLS_MD_SHA384, +#endif +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD4_C) + MBEDTLS_MD_MD4, +#endif + +#if defined(MBEDTLS_MD2_C) + MBEDTLS_MD_MD2, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD2_C) + if( !strcmp( "MD2", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + if( !strcmp( "MD4", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); +#endif + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); +#endif + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + { + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + mbedtls_md2_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + mbedtls_md4_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + mbedtls_sha256_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + mbedtls_sha512_free( ctx->md_ctx ); + break; +#endif + default: + /* Shouldn't happen */ + break; + } + mbedtls_free( ctx->md_ctx ); + } + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + switch( src->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + mbedtls_md2_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + mbedtls_md4_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + mbedtls_sha256_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + mbedtls_sha512_clone( dst->md_ctx, src->md_ctx ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + if( dst->hmac_ctx != NULL && src->hmac_ctx != NULL ) + memcpy( dst->hmac_ctx, src->hmac_ctx, 2 * src->md_info->block_size ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) +{ + return mbedtls_md_setup( ctx, md_info, 1 ); +} +#endif + +#define ALLOC( type ) \ + do { \ + ctx->md_ctx = mbedtls_calloc( 1, sizeof( mbedtls_##type##_context ) ); \ + if( ctx->md_ctx == NULL ) \ + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); \ + mbedtls_##type##_init( ctx->md_ctx ); \ + } \ + while( 0 ) + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info = md_info; + ctx->md_ctx = NULL; + ctx->hmac_ctx = NULL; + + switch( md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + ALLOC( md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + ALLOC( md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + ALLOC( md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + ALLOC( ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + ALLOC( sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + ALLOC( sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + ALLOC( sha512 ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + mbedtls_md_free( ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + return( 0 ); +} +#undef ALLOC + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_starts_ret( ctx->md_ctx, 1 ) ); + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_starts_ret( ctx->md_ctx, 0 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_starts_ret( ctx->md_ctx, 1 ) ); +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_starts_ret( ctx->md_ctx, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_ret( input, ilen, output, 1 ) ); + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + goto cleanup; + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + if( ( ret = mbedtls_md_update( &ctx, buf, n ) ) != 0 ) + goto cleanup; + + if( ferror( f ) != 0 ) + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + else + ret = mbedtls_md_finish( &ctx, output ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_finish( ctx, sum ) ) != 0 ) + goto cleanup; + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_platform_zeroize( sum, sizeof( sum ) ); + + return( ret ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( mbedtls_md_update( ctx, input, ilen ) ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + if( ( ret = mbedtls_md_finish( ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( mbedtls_md_finish( ctx, output ) ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + return( mbedtls_md_update( ctx, ipad, ctx->md_info->block_size ) ); +} + +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_internal_md2_process( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_internal_md4_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_internal_md5_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_internal_ripemd160_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_internal_sha1_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/md2.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/md2.c new file mode 100644 index 0000000..7264e30 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/md2.c @@ -0,0 +1,360 @@ +/* + * RFC 1115/1319 compliant MD2 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The MD2 algorithm was designed by Ron Rivest in 1989. + * + * http://www.ietf.org/rfc/rfc1115.txt + * http://www.ietf.org/rfc/rfc1319.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_MD2_C) + +#include "mbedtls/md2.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD2_ALT) + +static const unsigned char PI_SUBST[256] = +{ + 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, + 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, + 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, + 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, + 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, + 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, + 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, + 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, + 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, + 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, + 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, + 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, + 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, + 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, + 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, + 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, + 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, + 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, + 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, + 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, + 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, + 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, + 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, + 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, + 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, + 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 +}; + +void mbedtls_md2_init( mbedtls_md2_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_free( mbedtls_md2_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) ); +} + +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ) +{ + *dst = *src; +} + +/* + * MD2 context setup + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ) +{ + memset( ctx->cksum, 0, 16 ); + memset( ctx->state, 0, 46 ); + memset( ctx->buffer, 0, 16 ); + ctx->left = 0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_starts( mbedtls_md2_context *ctx ) +{ + mbedtls_md2_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD2_PROCESS_ALT) +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ) +{ + int i, j; + unsigned char t = 0; + + for( i = 0; i < 16; i++ ) + { + ctx->state[i + 16] = ctx->buffer[i]; + ctx->state[i + 32] = + (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); + } + + for( i = 0; i < 18; i++ ) + { + for( j = 0; j < 48; j++ ) + { + ctx->state[j] = (unsigned char) + ( ctx->state[j] ^ PI_SUBST[t] ); + t = ctx->state[j]; + } + + t = (unsigned char)( t + i ); + } + + t = ctx->cksum[15]; + + for( i = 0; i < 16; i++ ) + { + ctx->cksum[i] = (unsigned char) + ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); + t = ctx->cksum[i]; + } + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_process( mbedtls_md2_context *ctx ) +{ + mbedtls_internal_md2_process( ctx ); +} +#endif +#endif /* !MBEDTLS_MD2_PROCESS_ALT */ + +/* + * MD2 process buffer + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + + while( ilen > 0 ) + { + if( ilen > 16 - ctx->left ) + fill = 16 - ctx->left; + else + fill = ilen; + + memcpy( ctx->buffer + ctx->left, input, fill ); + + ctx->left += fill; + input += fill; + ilen -= fill; + + if( ctx->left == 16 ) + { + ctx->left = 0; + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + } + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md2_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD2 final digest + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + unsigned char x; + + x = (unsigned char)( 16 - ctx->left ); + + for( i = ctx->left; i < 16; i++ ) + ctx->buffer[i] = x; + + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( ctx->buffer, ctx->cksum, 16 ); + if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 ) + return( ret ); + + memcpy( output, ctx->state, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md2_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD2_ALT */ + +/* + * output = MD2( input buffer ) + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md2_context ctx; + + mbedtls_md2_init( &ctx ); + + if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md2_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md2_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1319 test vectors + */ +static const unsigned char md2_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } +}; + +static const size_t md2_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md2_test_sum[7][16] = +{ + { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, + 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, + { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, + 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, + { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, + 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, + { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, + 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, + { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, + 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, + { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, + 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, + { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, + 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } +}; + +/* + * Checkup routine + */ +int mbedtls_md2_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md2sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD2 test #%d: ", i + 1 ); + + ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD2_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/md4.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/md4.c new file mode 100644 index 0000000..eaa679a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/md4.c @@ -0,0 +1,461 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The MD4 algorithm was designed by Ron Rivest in 1990. + * + * http://www.ietf.org/rfc/rfc1186.txt + * http://www.ietf.org/rfc/rfc1320.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_MD4_C) + +#include "mbedtls/md4.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD4_ALT) + +void mbedtls_md4_init( mbedtls_md4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_free( mbedtls_md4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) ); +} + +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ) +{ + *dst = *src; +} + +/* + * MD4 context setup + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_starts( mbedtls_md4_context *ctx ) +{ + mbedtls_md4_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD4_PROCESS_ALT) +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t X[16], A, B, C, D; + } local; + + local.X[ 0] = MBEDTLS_GET_UINT32_LE( data, 0 ); + local.X[ 1] = MBEDTLS_GET_UINT32_LE( data, 4 ); + local.X[ 2] = MBEDTLS_GET_UINT32_LE( data, 8 ); + local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 ); + local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 ); + local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 ); + local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 ); + local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 ); + local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 ); + local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 ); + local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 ); + local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 ); + local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 ); + local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 ); + local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 ); + local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + +#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x); \ + (a) = S((a),(s)); \ + } while( 0 ) + + + P( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 1], 7 ); + P( local.C, local.D, local.A, local.B, local.X[ 2], 11 ); + P( local.B, local.C, local.D, local.A, local.X[ 3], 19 ); + P( local.A, local.B, local.C, local.D, local.X[ 4], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 5], 7 ); + P( local.C, local.D, local.A, local.B, local.X[ 6], 11 ); + P( local.B, local.C, local.D, local.A, local.X[ 7], 19 ); + P( local.A, local.B, local.C, local.D, local.X[ 8], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 9], 7 ); + P( local.C, local.D, local.A, local.B, local.X[10], 11 ); + P( local.B, local.C, local.D, local.A, local.X[11], 19 ); + P( local.A, local.B, local.C, local.D, local.X[12], 3 ); + P( local.D, local.A, local.B, local.C, local.X[13], 7 ); + P( local.C, local.D, local.A, local.B, local.X[14], 11 ); + P( local.B, local.C, local.D, local.A, local.X[15], 19 ); + +#undef P +#undef F + +#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x) + 0x5A827999; \ + (a) = S((a),(s)); \ + } while( 0 ) + + P( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 4], 5 ); + P( local.C, local.D, local.A, local.B, local.X[ 8], 9 ); + P( local.B, local.C, local.D, local.A, local.X[12], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 1], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 5], 5 ); + P( local.C, local.D, local.A, local.B, local.X[ 9], 9 ); + P( local.B, local.C, local.D, local.A, local.X[13], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 2], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 6], 5 ); + P( local.C, local.D, local.A, local.B, local.X[10], 9 ); + P( local.B, local.C, local.D, local.A, local.X[14], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 3], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 7], 5 ); + P( local.C, local.D, local.A, local.B, local.X[11], 9 ); + P( local.B, local.C, local.D, local.A, local.X[15], 13 ); + +#undef P +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define P(a,b,c,d,x,s) \ + do \ + { \ + (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \ + (a) = S((a),(s)); \ + } while( 0 ) + + P( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 8], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 4], 11 ); + P( local.B, local.C, local.D, local.A, local.X[12], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 2], 3 ); + P( local.D, local.A, local.B, local.C, local.X[10], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 6], 11 ); + P( local.B, local.C, local.D, local.A, local.X[14], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 1], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 9], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 5], 11 ); + P( local.B, local.C, local.D, local.A, local.X[13], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 3], 3 ); + P( local.D, local.A, local.B, local.C, local.X[11], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 7], 11 ); + P( local.B, local.C, local.D, local.A, local.X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md4_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD4_PROCESS_ALT */ + +/* + * MD4 process buffer + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, fill ); + + if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), + (void *) input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md4_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char md4_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * MD4 final digest + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_LE( low, msglen, 0 ); + MBEDTLS_PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn ); + if( ret != 0 ) + return( ret ); + + if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 ) + return( ret ); + + + MBEDTLS_PUT_UINT32_LE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md4_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD4_ALT */ + +/* + * output = MD4( input buffer ) + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md4_context ctx; + + mbedtls_md4_init( &ctx ); + + if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md4_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md4_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * RFC 1320 test vectors + */ +static const unsigned char md4_test_str[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } +}; + +static const size_t md4_test_strlen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md4_test_sum[7][16] = +{ + { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, + 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, + { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, + 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, + { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, + 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, + { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, + 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, + { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, + 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, + { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, + 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, + { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, + 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } +}; + +/* + * Checkup routine + */ +int mbedtls_md4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md4sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD4 test #%d: ", i + 1 ); + + ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD4_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c new file mode 100644 index 0000000..4b53fcf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/md5.c @@ -0,0 +1,475 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_MD5_C) + +#include "mbedtls/md5.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD5_ALT) + +void mbedtls_md5_init( mbedtls_md5_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_free( mbedtls_md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + mbedtls_md5_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t X[16], A, B, C, D; + } local; + + local.X[ 0] = MBEDTLS_GET_UINT32_LE( data, 0 ); + local.X[ 1] = MBEDTLS_GET_UINT32_LE( data, 4 ); + local.X[ 2] = MBEDTLS_GET_UINT32_LE( data, 8 ); + local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 ); + local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 ); + local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 ); + local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 ); + local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 ); + local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 ); + local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 ); + local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 ); + local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 ); + local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 ); + local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 ); + local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 ); + local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 ); + +#define S(x,n) \ + ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) ) + +#define P(a,b,c,d,k,s,t) \ + do \ + { \ + (a) += F((b),(c),(d)) + local.X[(k)] + (t); \ + (a) = S((a),(s)) + (b); \ + } while( 0 ) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + + P( local.A, local.B, local.C, local.D, 0, 7, 0xD76AA478 ); + P( local.D, local.A, local.B, local.C, 1, 12, 0xE8C7B756 ); + P( local.C, local.D, local.A, local.B, 2, 17, 0x242070DB ); + P( local.B, local.C, local.D, local.A, 3, 22, 0xC1BDCEEE ); + P( local.A, local.B, local.C, local.D, 4, 7, 0xF57C0FAF ); + P( local.D, local.A, local.B, local.C, 5, 12, 0x4787C62A ); + P( local.C, local.D, local.A, local.B, 6, 17, 0xA8304613 ); + P( local.B, local.C, local.D, local.A, 7, 22, 0xFD469501 ); + P( local.A, local.B, local.C, local.D, 8, 7, 0x698098D8 ); + P( local.D, local.A, local.B, local.C, 9, 12, 0x8B44F7AF ); + P( local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1 ); + P( local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE ); + P( local.A, local.B, local.C, local.D, 12, 7, 0x6B901122 ); + P( local.D, local.A, local.B, local.C, 13, 12, 0xFD987193 ); + P( local.C, local.D, local.A, local.B, 14, 17, 0xA679438E ); + P( local.B, local.C, local.D, local.A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y)))) + + P( local.A, local.B, local.C, local.D, 1, 5, 0xF61E2562 ); + P( local.D, local.A, local.B, local.C, 6, 9, 0xC040B340 ); + P( local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51 ); + P( local.B, local.C, local.D, local.A, 0, 20, 0xE9B6C7AA ); + P( local.A, local.B, local.C, local.D, 5, 5, 0xD62F105D ); + P( local.D, local.A, local.B, local.C, 10, 9, 0x02441453 ); + P( local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681 ); + P( local.B, local.C, local.D, local.A, 4, 20, 0xE7D3FBC8 ); + P( local.A, local.B, local.C, local.D, 9, 5, 0x21E1CDE6 ); + P( local.D, local.A, local.B, local.C, 14, 9, 0xC33707D6 ); + P( local.C, local.D, local.A, local.B, 3, 14, 0xF4D50D87 ); + P( local.B, local.C, local.D, local.A, 8, 20, 0x455A14ED ); + P( local.A, local.B, local.C, local.D, 13, 5, 0xA9E3E905 ); + P( local.D, local.A, local.B, local.C, 2, 9, 0xFCEFA3F8 ); + P( local.C, local.D, local.A, local.B, 7, 14, 0x676F02D9 ); + P( local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) + + P( local.A, local.B, local.C, local.D, 5, 4, 0xFFFA3942 ); + P( local.D, local.A, local.B, local.C, 8, 11, 0x8771F681 ); + P( local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122 ); + P( local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C ); + P( local.A, local.B, local.C, local.D, 1, 4, 0xA4BEEA44 ); + P( local.D, local.A, local.B, local.C, 4, 11, 0x4BDECFA9 ); + P( local.C, local.D, local.A, local.B, 7, 16, 0xF6BB4B60 ); + P( local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70 ); + P( local.A, local.B, local.C, local.D, 13, 4, 0x289B7EC6 ); + P( local.D, local.A, local.B, local.C, 0, 11, 0xEAA127FA ); + P( local.C, local.D, local.A, local.B, 3, 16, 0xD4EF3085 ); + P( local.B, local.C, local.D, local.A, 6, 23, 0x04881D05 ); + P( local.A, local.B, local.C, local.D, 9, 4, 0xD9D4D039 ); + P( local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5 ); + P( local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8 ); + P( local.B, local.C, local.D, local.A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((x) | ~(z))) + + P( local.A, local.B, local.C, local.D, 0, 6, 0xF4292244 ); + P( local.D, local.A, local.B, local.C, 7, 10, 0x432AFF97 ); + P( local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7 ); + P( local.B, local.C, local.D, local.A, 5, 21, 0xFC93A039 ); + P( local.A, local.B, local.C, local.D, 12, 6, 0x655B59C3 ); + P( local.D, local.A, local.B, local.C, 3, 10, 0x8F0CCC92 ); + P( local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D ); + P( local.B, local.C, local.D, local.A, 1, 21, 0x85845DD1 ); + P( local.A, local.B, local.C, local.D, 8, 6, 0x6FA87E4F ); + P( local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0 ); + P( local.C, local.D, local.A, local.B, 6, 15, 0xA3014314 ); + P( local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1 ); + P( local.A, local.B, local.C, local.D, 4, 6, 0xF7537E82 ); + P( local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235 ); + P( local.C, local.D, local.A, local.B, 2, 15, 0x2AD7D2BB ); + P( local.B, local.C, local.D, local.A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md5_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD5 final digest + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_LE( low, ctx->buffer, 56 ); + MBEDTLS_PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + MBEDTLS_PUT_UINT32_LE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md5_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + + if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md5_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md5_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } +}; + +static const size_t md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c new file mode 100644 index 0000000..cc62324 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c @@ -0,0 +1,744 @@ +/* + * Buffer-based memory allocator + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" + +/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C + is dependent upon MBEDTLS_PLATFORM_C */ +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_MEMORY_BACKTRACE) +#include +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#define MAGIC1 0xFF00AA55 +#define MAGIC2 0xEE119966 +#define MAX_BT 20 + +typedef struct _memory_header memory_header; +struct _memory_header +{ + size_t magic1; + size_t size; + size_t alloc; + memory_header *prev; + memory_header *next; + memory_header *prev_free; + memory_header *next_free; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + char **trace; + size_t trace_count; +#endif + size_t magic2; +}; + +typedef struct +{ + unsigned char *buf; + size_t len; + memory_header *first; + memory_header *first_free; + int verify; +#if defined(MBEDTLS_MEMORY_DEBUG) + size_t alloc_count; + size_t free_count; + size_t total_used; + size_t maximum_used; + size_t header_count; + size_t maximum_header_count; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +buffer_alloc_ctx; + +static buffer_alloc_ctx heap; + +#if defined(MBEDTLS_MEMORY_DEBUG) +static void debug_header( memory_header *hdr ) +{ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + size_t i; +#endif + + mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " + "ALLOC(%zu), SIZE(%10zu)\n", + (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, + hdr->alloc, hdr->size ); + mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", + (size_t) hdr->prev_free, (size_t) hdr->next_free ); + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + mbedtls_fprintf( stderr, "TRACE: \n" ); + for( i = 0; i < hdr->trace_count; i++ ) + mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); + mbedtls_fprintf( stderr, "\n" ); +#endif +} + +static void debug_chain( void ) +{ + memory_header *cur = heap.first; + + mbedtls_fprintf( stderr, "\nBlock list\n" ); + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next; + } + + mbedtls_fprintf( stderr, "Free list\n" ); + cur = heap.first_free; + + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next_free; + } +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +static int verify_header( memory_header *hdr ) +{ + if( hdr->magic1 != MAGIC1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->magic2 != MAGIC2 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->alloc > 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); +#endif + return( 1 ); + } + + if( hdr->prev != NULL && hdr->prev == hdr->next ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); +#endif + return( 1 ); + } + + if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); +#endif + return( 1 ); + } + + return( 0 ); +} + +static int verify_chain( void ) +{ + memory_header *prv = heap.first, *cur; + + if( prv == NULL || verify_header( prv ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of first header " + "failed\n" ); +#endif + return( 1 ); + } + + if( heap.first->prev != NULL ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "first->prev != NULL\n" ); +#endif + return( 1 ); + } + + cur = heap.first->next; + + while( cur != NULL ) + { + if( verify_header( cur ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of header " + "failed\n" ); +#endif + return( 1 ); + } + + if( cur->prev != prv ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "cur->prev != prv\n" ); +#endif + return( 1 ); + } + + prv = cur; + cur = cur->next; + } + + return( 0 ); +} + +static void *buffer_alloc_calloc( size_t n, size_t size ) +{ + memory_header *new, *cur = heap.first_free; + unsigned char *p; + void *ret; + size_t original_len, len; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + void *trace_buffer[MAX_BT]; + size_t trace_cnt; +#endif + + if( heap.buf == NULL || heap.first == NULL ) + return( NULL ); + + original_len = len = n * size; + + if( n == 0 || size == 0 || len / n != size ) + return( NULL ); + else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return( NULL ); + + if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + // Find block that fits + // + while( cur != NULL ) + { + if( cur->size >= len ) + break; + + cur = cur->next_free; + } + + if( cur == NULL ) + return( NULL ); + + if( cur->alloc != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.alloc_count++; +#endif + + // Found location, split block if > memory_header + 4 room left + // + if( cur->size - len < sizeof(memory_header) + + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + cur->alloc = 1; + + // Remove from free_list + // + if( cur->prev_free != NULL ) + cur->prev_free->next_free = cur->next_free; + else + heap.first_free = cur->next_free; + + if( cur->next_free != NULL ) + cur->next_free->prev_free = cur->prev_free; + + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); + } + + p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; + new = (memory_header *) p; + + new->size = cur->size - len - sizeof(memory_header); + new->alloc = 0; + new->prev = cur; + new->next = cur->next; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + new->trace = NULL; + new->trace_count = 0; +#endif + new->magic1 = MAGIC1; + new->magic2 = MAGIC2; + + if( new->next != NULL ) + new->next->prev = new; + + // Replace cur with new in free_list + // + new->prev_free = cur->prev_free; + new->next_free = cur->next_free; + if( new->prev_free != NULL ) + new->prev_free->next_free = new; + else + heap.first_free = new; + + if( new->next_free != NULL ) + new->next_free->prev_free = new; + + cur->alloc = 1; + cur->size = len; + cur->next = new; + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count++; + if( heap.header_count > heap.maximum_header_count ) + heap.maximum_header_count = heap.header_count; + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); +} + +static void buffer_alloc_free( void *ptr ) +{ + memory_header *hdr, *old = NULL; + unsigned char *p = (unsigned char *) ptr; + + if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) + return; + + if( p < heap.buf || p >= heap.buf + heap.len ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " + "space\n" ); +#endif + mbedtls_exit( 1 ); + } + + p -= sizeof(memory_header); + hdr = (memory_header *) p; + + if( verify_header( hdr ) != 0 ) + mbedtls_exit( 1 ); + + if( hdr->alloc != 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + + hdr->alloc = 0; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.free_count++; + heap.total_used -= hdr->size; +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + free( hdr->trace ); + hdr->trace = NULL; + hdr->trace_count = 0; +#endif + + // Regroup with block before + // + if( hdr->prev != NULL && hdr->prev->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->prev->size += sizeof(memory_header) + hdr->size; + hdr->prev->next = hdr->next; + old = hdr; + hdr = hdr->prev; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Regroup with block after + // + if( hdr->next != NULL && hdr->next->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->size += sizeof(memory_header) + hdr->next->size; + old = hdr->next; + hdr->next = hdr->next->next; + + if( hdr->prev_free != NULL || hdr->next_free != NULL ) + { + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr->next_free; + else + heap.first_free = hdr->next_free; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr->prev_free; + } + + hdr->prev_free = old->prev_free; + hdr->next_free = old->next_free; + + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr; + else + heap.first_free = hdr; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Prepend to free_list if we have not merged + // (Does not have to stay in same order as prev / next list) + // + if( old == NULL ) + { + hdr->next_free = heap.first_free; + if( heap.first_free != NULL ) + heap.first_free->prev_free = hdr; + heap.first_free = hdr; + } + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); +} + +void mbedtls_memory_buffer_set_verify( int verify ) +{ + heap.verify = verify; +} + +int mbedtls_memory_buffer_alloc_verify( void ) +{ + return verify_chain(); +} + +#if defined(MBEDTLS_MEMORY_DEBUG) +void mbedtls_memory_buffer_alloc_status( void ) +{ + mbedtls_fprintf( stderr, + "Current use: %zu blocks / %zu bytes, max: %zu blocks / " + "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", + heap.header_count, heap.total_used, + heap.maximum_header_count, heap.maximum_used, + heap.maximum_header_count * sizeof( memory_header ) + + heap.maximum_used, + heap.alloc_count, heap.free_count ); + + if( heap.first->next == NULL ) + { + mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + } + else + { + mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); + debug_chain(); + } +} + +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) +{ + *max_used = heap.maximum_used; + *max_blocks = heap.maximum_header_count; +} + +void mbedtls_memory_buffer_alloc_max_reset( void ) +{ + heap.maximum_used = 0; + heap.maximum_header_count = 0; +} + +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) +{ + *cur_used = heap.total_used; + *cur_blocks = heap.header_count; +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +#if defined(MBEDTLS_THREADING_C) +static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) +{ + void *buf; + if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) + return( NULL ); + buf = buffer_alloc_calloc( n, size ); + if( mbedtls_mutex_unlock( &heap.mutex ) ) + return( NULL ); + return( buf ); +} + +static void buffer_alloc_free_mutexed( void *ptr ) +{ + /* We have no good option here, but corrupting the heap seems + * worse than losing memory. */ + if( mbedtls_mutex_lock( &heap.mutex ) ) + return; + buffer_alloc_free( ptr ); + (void) mbedtls_mutex_unlock( &heap.mutex ); +} +#endif /* MBEDTLS_THREADING_C */ + +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) +{ + memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &heap.mutex ); + mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, + buffer_alloc_free_mutexed ); +#else + mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); +#endif + + if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return; + else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + /* Adjust len first since buf is used in the computation */ + len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + memset( buf, 0, len ); + + heap.buf = buf; + heap.len = len; + + heap.first = (memory_header *)buf; + heap.first->size = len - sizeof( memory_header ); + heap.first->magic1 = MAGIC1; + heap.first->magic2 = MAGIC2; + heap.first_free = heap.first; +} + +void mbedtls_memory_buffer_alloc_free( void ) +{ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &heap.mutex ); +#endif + mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) ); +} + +#if defined(MBEDTLS_SELF_TEST) +static int check_pointer( void *p ) +{ + if( p == NULL ) + return( -1 ); + + if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) + return( -1 ); + + return( 0 ); +} + +static int check_all_free( void ) +{ + if( +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used != 0 || +#endif + heap.first != heap.first_free || + (void *) heap.first != (void *) heap.buf ) + { + return( -1 ); + } + + return( 0 ); +} + +#define TEST_ASSERT( condition ) \ + if( ! (condition) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + \ + ret = 1; \ + goto cleanup; \ + } + +int mbedtls_memory_buffer_alloc_self_test( int verbose ) +{ + unsigned char buf[1024]; + unsigned char *p, *q, *r, *end; + int ret = 0; + + if( verbose != 0 ) + mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + /* Memorize end to compare with the next test */ + end = heap.buf + heap.len; + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #2 (buf not aligned): " ); + + mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); + + TEST_ASSERT( heap.buf + heap.len == end ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #3 (full): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); + + TEST_ASSERT( check_pointer( p ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( p ); + + p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); + q = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( q ); + + TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); + + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_memory_buffer_alloc_free( ); + + return( ret ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c new file mode 100644 index 0000000..8c765e1 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/net_sockets.c @@ -0,0 +1,715 @@ +/* + * TCP/IP or UDP/IP networking functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must + * be set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L +#endif +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 /* sockaddr_storage */ +#endif + +#include "common.h" + +#if defined(MBEDTLS_NET_C) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" + +#include + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR ) + +#if !defined(_WIN32_WINNT) +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#endif + +#include + +#include +#include +#if (_WIN32_WINNT < 0x0501) +#include +#endif + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) +#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) +#define close(fd) closesocket(fd) + +static int wsa_init_done = 0; + +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_EINTR( ret ) ( ( ret ) == EINTR ) + +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* Some MS functions want int and MSVC warns if we pass size_t, + * but the standard functions use socklen_t, so cast only for MSVC */ +#if defined(_MSC_VER) +#define MSVC_INT_CAST (int) +#else +#define MSVC_INT_CAST +#endif + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include +#endif + +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Return 0 if the file descriptor is valid, an error otherwise. + * If for_select != 0, check whether the file descriptor is within the range + * allowed for fd_set used for the FD_xxx macros and the select() function. + */ +static int check_fd( int fd, int for_select ) +{ + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + (void) for_select; +#else + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( for_select && fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); +#endif + + return( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int n, ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if( proto == MBEDTLS_NET_PROTO_TCP ) + { + if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* Bind was successful */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + int err = errno; + + /* + * Never return 'WOULD BLOCK' on a blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) + { + errno = err; + return( 0 ); + } + + switch( errno = err ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } + return( 0 ); +} +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* + * Accept a connection from a remote client + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int type; + + struct sockaddr_storage client_addr; + +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \ + defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) + socklen_t n = (socklen_t) sizeof( client_addr ); + socklen_t type_len = (socklen_t) sizeof( type ); +#else + int n = (int) sizeof( client_addr ); + int type_len = (int) sizeof( type ); +#endif + + /* Is this a TCP or UDP socket? */ + if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, + (void *) &type, &type_len ) != 0 || + ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) + { + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + if( type == SOCK_STREAM ) + { + /* TCP: actual accept() */ + ret = client_ctx->fd = (int) accept( bind_ctx->fd, + (struct sockaddr *) &client_addr, &n ); + } + else + { + /* UDP: wait for a message, but keep it in the queue */ + char buf[1] = { 0 }; + + ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + (struct sockaddr *) &client_addr, &n ); + +#if defined(_WIN32) + if( ret == SOCKET_ERROR && + WSAGetLastError() == WSAEMSGSIZE ) + { + /* We know buf is too small, thanks, just peeking here */ + ret = 0; + } +#endif + } + + if( ret < 0 ) + { + if( net_would_block( bind_ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ + if( type != SOCK_STREAM ) + { + struct sockaddr_storage local_addr; + int one = 1; + + if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + + client_ctx->fd = bind_ctx->fd; + bind_ctx->fd = -1; /* In case we exit early */ + + n = sizeof( struct sockaddr_storage ); + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.ss_family, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) + { + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } + + if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) + { + return( MBEDTLS_ERR_NET_BIND_FAILED ); + } + } + + if( client_ip != NULL ) + { + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + *ip_len = sizeof( addr4->sin_addr.s_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } + else + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + *ip_len = sizeof( addr6->sin6_addr.s6_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + } + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 0; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); +#endif +} + +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 1; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); +#endif +} + +/* + * Check if data is available on the socket + */ + +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct timeval tv; + + fd_set read_fds; + fd_set write_fds; + + int fd = ctx->fd; + + ret = check_fd( fd, 1 ); + if( ret != 0 ) + return( ret ); + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + /* Ensure that memory sanitizers consider read_fds and write_fds as + * initialized even on platforms such as Glibc/x86_64 where FD_ZERO + * is implemented in assembly. */ + memset( &read_fds, 0, sizeof( read_fds ) ); + memset( &write_fds, 0, sizeof( write_fds ) ); +#endif +#endif + + FD_ZERO( &read_fds ); + if( rw & MBEDTLS_NET_POLL_READ ) + { + rw &= ~MBEDTLS_NET_POLL_READ; + FD_SET( fd, &read_fds ); + } + + FD_ZERO( &write_fds ); + if( rw & MBEDTLS_NET_POLL_WRITE ) + { + rw &= ~MBEDTLS_NET_POLL_WRITE; + FD_SET( fd, &write_fds ); + } + + if( rw != 0 ) + return( MBEDTLS_ERR_NET_BAD_INPUT_DATA ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + do + { + ret = select( fd + 1, &read_fds, &write_fds, NULL, + timeout == (uint32_t) -1 ? NULL : &tv ); + } + while( IS_EINTR( ret ) ); + + if( ret < 0 ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + + ret = 0; + if( FD_ISSET( fd, &read_fds ) ) + ret |= MBEDTLS_NET_POLL_READ; + if( FD_ISSET( fd, &write_fds ) ) + ret |= MBEDTLS_NET_POLL_WRITE; + + return( ret ); +} + +/* + * Portable usleep helper + */ +void mbedtls_net_usleep( unsigned long usec ) +{ +#if defined(_WIN32) + Sleep( ( usec + 999 ) / 1000 ); +#else + struct timeval tv; + tv.tv_sec = usec / 1000000; +#if defined(__unix__) || defined(__unix) || \ + ( defined(__APPLE__) && defined(__MACH__) ) + tv.tv_usec = (suseconds_t) usec % 1000000; +#else + tv.tv_usec = usec % 1000000; +#endif + select( 0, NULL, NULL, NULL, &tv ); +#endif +} + +/* + * Read at most 'len' characters + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int fd = ((mbedtls_net_context *) ctx)->fd; + + ret = check_fd( fd, 0 ); + if( ret != 0 ) + return( ret ); + + ret = (int) read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Read at most 'len' characters, blocking for at most 'timeout' ms + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, + size_t len, uint32_t timeout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + ret = check_fd( fd, 1 ); + if( ret != 0 ) + return( ret ); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_TIMEOUT ); + + if( ret < 0 ) + { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#else + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( mbedtls_net_recv( ctx, buf, len ) ); +} + +/* + * Write at most 'len' characters + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int fd = ((mbedtls_net_context *) ctx)->fd; + + ret = check_fd( fd, 0 ); + if( ret != 0 ) + return( ret ); + + ret = (int) write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); +#endif + + return( MBEDTLS_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Close the connection + */ +void mbedtls_net_close( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + close( ctx->fd ); + + ctx->fd = -1; +} + +/* + * Gracefully close the connection + */ +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + shutdown( ctx->fd, 2 ); + close( ctx->fd ); + + ctx->fd = -1; +} + +#endif /* MBEDTLS_NET_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c new file mode 100644 index 0000000..1aea0b6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/nist_kw.c @@ -0,0 +1,713 @@ +/* + * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes + * only + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Definition of Key Wrapping: + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" + * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" + * + * Note: RFC 3394 defines different methodology for intermediate operations for + * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. + */ + +#include "common.h" + +#if defined(MBEDTLS_NIST_KW_C) + +#include "mbedtls/nist_kw.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/constant_time.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_NIST_KW_ALT) + +#define KW_SEMIBLOCK_LENGTH 8 +#define MIN_SEMIBLOCKS_COUNT 3 + +/*! The 64-bit default integrity check value (ICV) for KW mode. */ +static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; +/*! The 32-bit default integrity check value (ICV) for KWP mode. */ +static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; + +/* + * Initialize context + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); +} + +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, + keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* + * SP 800-38F currently defines AES cipher as the only block cipher allowed: + * "For KW and KWP, the underlying block cipher shall be approved, and the + * block size shall be 128 bits. Currently, the AES block cipher, with key + * lengths of 128, 192, or 256 bits, is the only block cipher that fits + * this profile." + * Currently we don't support other 128 bit block ciphers for key wrapping, + * such as Camellia and Aria. + */ + if( cipher != MBEDTLS_CIPHER_ID_AES ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + is_wrap ? MBEDTLS_ENCRYPT : + MBEDTLS_DECRYPT ) + ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); +} + +/* + * Helper function for Xoring the uint64_t "t" with the encrypted A. + * Defined in NIST SP 800-38F section 6.1 + */ +static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) +{ + size_t i = 0; + for( i = 0; i < sizeof( t ); i++ ) + { + A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; + } +} + +/* + * KW-AE as defined in SP 800-38F section 6.2 + * KWP-AE as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t semiblocks = 0; + size_t s; + size_t olen, padlen = 0; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + + *out_len = 0; + /* + * Generate the String to work on + */ + if( mode == MBEDTLS_KW_MODE_KW ) + { + if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KW + * must be between 2 to 2^54-1 semiblocks inclusive. + */ + if( in_len < 16 || +#if SIZE_MAX > 0x1FFFFFFFFFFFFF8 + in_len > 0x1FFFFFFFFFFFFF8 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); + memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + } + else + { + if( in_len % 8 != 0 ) + { + padlen = ( 8 - ( in_len % 8 ) ); + } + + if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KWP + * must be between 1 and 2^32-1 octets inclusive. + */ + if( in_len < 1 +#if SIZE_MAX > 0xFFFFFFFF + || in_len > 0xFFFFFFFF +#endif + ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); + MBEDTLS_PUT_UINT32_BE( ( in_len & 0xffffffff ), output, + KW_SEMIBLOCK_LENGTH / 2 ); + + memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); + } + semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; + + s = 6 * ( semiblocks - 1 ); + + if( mode == MBEDTLS_KW_MODE_KWP + && in_len <= KW_SEMIBLOCK_LENGTH ) + { + memcpy( inbuff, output, 16 ); + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, output, &olen ); + if( ret != 0 ) + goto cleanup; + } + else + { + unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; + unsigned char *A = output; + + /* + * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 + */ + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + goto cleanup; + } + + /* Calculate intermediate values */ + for( t = 1; t <= s; t++ ) + { + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + calc_a_xor_t( A, t ); + + memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + R2 += KW_SEMIBLOCK_LENGTH; + if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) + R2 = output + KW_SEMIBLOCK_LENGTH; + } + } + + *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; + +cleanup: + + if( ret != 0) + { + memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); + } + mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); + + return( ret ); +} + +/* + * W-1 function as defined in RFC 3394 section 2.2.2 + * This function assumes the following: + * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. + * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. + * 3. Minimal number of semiblocks is 3. + * 4. A is a buffer to hold the first semiblock of the input buffer. + */ +static int unwrap( mbedtls_nist_kw_context *ctx, + const unsigned char *input, size_t semiblocks, + unsigned char A[KW_SEMIBLOCK_LENGTH], + unsigned char *output, size_t* out_len ) +{ + int ret = 0; + const size_t s = 6 * ( semiblocks - 1 ); + size_t olen; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R = NULL; + *out_len = 0; + + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( A, input, KW_SEMIBLOCK_LENGTH ); + memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + + /* Calculate intermediate values */ + for( t = s; t >= 1; t-- ) + { + calc_a_xor_t( A, t ); + + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + + /* Set R as LSB64 of outbuff */ + memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + + if( R == output ) + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + else + R -= KW_SEMIBLOCK_LENGTH; + } + + *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; + +cleanup: + if( ret != 0) + memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + + return( ret ); +} + +/* + * KW-AD as defined in SP 800-38F section 6.2 + * KWP-AD as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t i, olen; + unsigned char A[KW_SEMIBLOCK_LENGTH]; + unsigned char diff, bad_padding = 0; + + *out_len = 0; + if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( mode == MBEDTLS_KW_MODE_KW ) + { + /* + * According to SP 800-38F Table 1, the ciphertext length for KW + * must be between 3 to 2^54 semiblocks inclusive. + */ + if( in_len < 24 || +#if SIZE_MAX > 0x200000000000000 + in_len > 0x200000000000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + + /* Check ICV in "constant-time" */ + diff = mbedtls_ct_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto cleanup; + } + + } + else if( mode == MBEDTLS_KW_MODE_KWP ) + { + size_t padlen = 0; + uint32_t Plen; + /* + * According to SP 800-38F Table 1, the ciphertext length for KWP + * must be between 2 to 2^29 semiblocks inclusive. + */ + if( in_len < KW_SEMIBLOCK_LENGTH * 2 || +#if SIZE_MAX > 0x100000000 + in_len > 0x100000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) + { + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + input, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + *out_len = KW_SEMIBLOCK_LENGTH; + } + else + { + /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + } + + /* Check ICV in "constant-time" */ + diff = mbedtls_ct_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + Plen = MBEDTLS_GET_UINT32_BE( A, KW_SEMIBLOCK_LENGTH / 2 ); + + /* + * Plen is the length of the plaintext, when the input is valid. + * If Plen is larger than the plaintext and padding, padlen will be + * larger than 8, because of the type wrap around. + */ + padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; + if ( padlen > 7 ) + { + padlen &= 7; + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + /* Check padding in "constant-time" */ + for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) + { + if( i >= KW_SEMIBLOCK_LENGTH - padlen ) + diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + else + bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + } + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + if( ret != 0 ) + { + goto cleanup; + } + memset( output + Plen, 0, padlen ); + *out_len = Plen; + } + else + { + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + +cleanup: + if( ret != 0 ) + { + memset( output, 0, *out_len ); + *out_len = 0; + } + + mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); + mbedtls_platform_zeroize( &diff, sizeof( diff ) ); + mbedtls_platform_zeroize( A, sizeof( A ) ); + + return( ret ); +} + +#endif /* !MBEDTLS_NIST_KW_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#define KW_TESTS 3 + +/* + * Test vectors taken from NIST + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW + */ +static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; + +static const unsigned char kw_key[KW_TESTS][32] = { + { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, + 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, + { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, + 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, + 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, + { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, + 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, + 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, + 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } +}; + +static const unsigned char kw_msg[KW_TESTS][40] = { + { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, + 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, + { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, + 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, + 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, + 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, + 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, + { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, + 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, + 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } +}; + +static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; +static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; +static const unsigned char kw_res[KW_TESTS][48] = { + { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, + 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, + 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, + { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, + 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, + 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, + 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, + 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, + 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, + { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, + 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, + 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, + 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } +}; + +static const unsigned char kwp_key[KW_TESTS][32] = { + { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, + 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, + { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, + 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, + 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, + { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, + 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, + 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, + 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } +}; + +static const unsigned char kwp_msg[KW_TESTS][31] = { + { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, + 0x96 }, + { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, + 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, + 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, + 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, + { 0xd1 } +}; +static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; + +static const unsigned char kwp_res[KW_TESTS][48] = { + { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, + 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, + 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, + { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, + 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, + 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, + 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, + 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, + { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, + 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } +}; +static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; + +int mbedtls_nist_kw_self_test( int verbose ) +{ + mbedtls_nist_kw_context ctx; + unsigned char out[48]; + size_t olen; + int i; + int ret = 0; + mbedtls_nist_kw_init( &ctx ); + + for( i = 0; i < KW_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed " ); + + goto end; + } + + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], + kw_msg_len[i], out, &olen, sizeof( out ) ); + if( ret != 0 || kw_out_len[i] != olen || + memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, + out, olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kw_msg_len[i] || + memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } + + for( i = 0; i < KW_TESTS; i++ ) + { + olen = sizeof( out ); + if( verbose != 0 ) + mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], + key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed " ); + + goto end; + } + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], + kwp_msg_len[i], out, &olen, sizeof( out ) ); + + if( ret != 0 || kwp_out_len[i] != olen || + memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kwp_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, + olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kwp_msg_len[i] || + memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } +end: + mbedtls_nist_kw_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_NIST_KW_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c new file mode 100644 index 0000000..19c8ac2 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/oid.c @@ -0,0 +1,767 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ + static const TYPE_T * oid_ ## NAME ## _from_asn1( \ + const mbedtls_asn1_buf *oid ) \ + { \ + const TYPE_T *p = (LIST); \ + const mbedtls_oid_descriptor_t *cur = \ + (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ + } + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ + ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *(ATTR1) = data->ATTR1; \ + *(ATTR2) = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, + "uniqueIdentifier", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + MBEDTLS_OID_X509_EXT_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, + MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, + }, + { + { ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" }, + MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { ADD_LEN( MBEDTLS_OID_WISUN_FAN ), "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) + +static const mbedtls_oid_descriptor_t oid_certificate_policies[] = +{ + { ADD_LEN( MBEDTLS_OID_ANY_POLICY ), "anyPolicy", "Any Policy" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) +FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description) + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + MBEDTLS_PK_ECKEY, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + MBEDTLS_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, + MBEDTLS_CIPHER_DES_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + MBEDTLS_MD_MD2, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + MBEDTLS_MD_MD4, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_RIPEMD160_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_RIPEMD160 ), "id-ripemd160", "RIPEMD-160" }, + MBEDTLS_MD_RIPEMD160, + }, +#endif /* MBEDTLS_RIPEMD160_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%u", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c new file mode 100644 index 0000000..8373374 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/padlock.c @@ -0,0 +1,164 @@ +/* + * VIA PadLock support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * This implementation is based on the VIA PadLock Programming Guide: + * + * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ + * programming_guide.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_PADLOCK_C) + +#include "mbedtls/padlock.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86) + +/* + * PadLock detection routine + */ +int mbedtls_padlock_has_support( int feature ) +{ + static int flags = -1; + int ebx = 0, edx = 0; + + if( flags == -1 ) + { + asm( "movl %%ebx, %0 \n\t" + "movl $0xC0000000, %%eax \n\t" + "cpuid \n\t" + "cmpl $0xC0000001, %%eax \n\t" + "movl $0, %%edx \n\t" + "jb 1f \n\t" + "movl $0xC0000001, %%eax \n\t" + "cpuid \n\t" + "1: \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%ebx \n\t" + : "=m" (ebx), "=m" (edx) + : "m" (ebx) + : "eax", "ecx", "edx" ); + + flags = edx; + } + + return( flags & feature ); +} + +/* + * PadLock AES-ECB block en(de)cryption + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int ebx = 0; + uint32_t *rk; + uint32_t *blk; + uint32_t *ctrl; + unsigned char buf[256]; + + rk = ctx->rk; + blk = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( blk, input, 16 ); + + ctrl = blk + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl $1, %%ecx \n\t" + "movl %2, %%edx \n\t" + "movl %3, %%ebx \n\t" + "movl %4, %%esi \n\t" + "movl %4, %%edi \n\t" + ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) + : "memory", "ecx", "edx", "esi", "edi" ); + + memcpy( output, blk, 16 ); + + return( 0 ); +} + +/* + * PadLock AES-CBC buffer en(de)cryption + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ebx = 0; + size_t count; + uint32_t *rk; + uint32_t *iw; + uint32_t *ctrl; + unsigned char buf[256]; + + if( ( (long) input & 15 ) != 0 || + ( (long) output & 15 ) != 0 ) + return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); + + rk = ctx->rk; + iw = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( iw, iv, 16 ); + + ctrl = iw + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); + + count = ( length + 15 ) >> 4; + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl %2, %%ecx \n\t" + "movl %3, %%edx \n\t" + "movl %4, %%ebx \n\t" + "movl %5, %%esi \n\t" + "movl %6, %%edi \n\t" + "movl %7, %%eax \n\t" + ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (count), "m" (ctrl), + "m" (rk), "m" (input), "m" (output), "m" (iw) + : "memory", "eax", "ecx", "edx", "esi", "edi" ); + + memcpy( iv, iw, 16 ); + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86 */ + +#endif /* MBEDTLS_PADLOCK_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c new file mode 100644 index 0000000..fcfde94 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pem.c @@ -0,0 +1,489 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/md5.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +void mbedtls_pem_init( mbedtls_pem_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pem_context ) ); +} + +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; + + memset( iv, 0, iv_len ); + + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + k = ( ( i & 1 ) != 0 ) ? j : j << 4; + + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } + + return( 0 ); +} + +static int pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + goto exit; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + +exit: + mbedtls_md5_free( &md5_ctx ); + mbedtls_platform_zeroize( md5sum, 16 ); + + return( ret ); +} + +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des_context des_ctx; + unsigned char des_key[8]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_des_init( &des_ctx ); + + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); + +exit: + mbedtls_des_free( &des_ctx ); + mbedtls_platform_zeroize( des_key, 8 ); + + return( ret ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des3_context des3_ctx; + unsigned char des3_key[24]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_des3_init( &des3_ctx ); + + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); + +exit: + mbedtls_des3_free( &des3_ctx ); + mbedtls_platform_zeroize( des3_key, 24 ); + + return( ret ); +} +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_aes_context aes_ctx; + unsigned char aes_key[32]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_aes_init( &aes_ctx ); + + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); + +exit: + mbedtls_aes_free( &aes_ctx ); + mbedtls_platform_zeroize( aes_key, keylen ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ + + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); + + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) ); + + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) ); + } + + if( enc != 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + if( pwd == NULL ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } + + ret = 0; + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } + + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as a heuristic to try to detect password mismatches. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void mbedtls_pem_free( mbedtls_pem_context *ctx ) +{ + if ( ctx->buf != NULL ) + { + mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); + mbedtls_free( ctx->buf ); + } + mbedtls_free( ctx->info ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); +} +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *encode_buf = NULL, *c, *p = buf; + size_t len = 0, use_len, add_len = 0; + + mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; + + if( use_len + add_len > buf_len ) + { + *olen = use_len + add_len; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( use_len != 0 && + ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, + der_len ) ) != 0 ) + { + mbedtls_free( encode_buf ); + return( ret ); + } + + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; + + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); + + *p++ = '\0'; + *olen = p - buf; + + /* Clean any remaining data previously written to the buffer */ + memset( buf + *olen, 0, buf_len - *olen ); + + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c new file mode 100644 index 0000000..05cc213 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pk.c @@ -0,0 +1,642 @@ +/* + * Public Key abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#endif + +#include +#include + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + if ( ctx->pk_info != NULL ) + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL ) + { + return; + } + + ctx->pk_info->rs_free_func( ctx->rs_ctx ); + + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return( &mbedtls_rsa_info ); +#endif +#if defined(MBEDTLS_ECP_C) + case MBEDTLS_PK_ECKEY: + return( &mbedtls_eckey_info ); + case MBEDTLS_PK_ECKEY_DH: + return( &mbedtls_eckeydh_info ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_PK_ECDSA: + return( &mbedtls_ecdsa_info ); +#endif + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( info == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Initialise a PSA-wrapping context + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, + const psa_key_id_t key ) +{ + const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t *pk_ctx; + psa_key_type_t type; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( PSA_SUCCESS != psa_get_key_attributes( key, &attributes ) ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + type = psa_get_key_type( &attributes ); + psa_reset_key_attributes( &attributes ); + + /* Current implementation of can_do() relies on this. */ + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ; + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + pk_ctx = (psa_key_id_t *) ctx->pk_ctx; + *pk_ctx = key; + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) +{ + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->can_do( type ) ); +} + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) +{ + const mbedtls_md_info_t *md_info; + + if( *hash_len != 0 && md_alg == MBEDTLS_MD_NONE ) + return( 0 ); + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + if ( *hash_len != 0 && *hash_len != mbedtls_md_get_size( md_info ) ) + return ( -1 ); + + *hash_len = mbedtls_md_get_size( md_info ); + return( 0 ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Helper to set up a restart context if needed + */ +static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info ) +{ + /* Don't do anything if already set up or invalid */ + if( ctx == NULL || ctx->pk_info != NULL ) + return( 0 ); + + /* Should never happen when we're called */ + if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Verify a signature (restartable) + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->verify_rs_func != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + +/* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, NULL ) ); +} + +/* + * Verify a signature with options + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ! mbedtls_pk_can_do( ctx, type ) ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + if( type == MBEDTLS_PK_RSASSA_PSS ) + { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_rsassa_pss_options *pss_opts; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + NULL, NULL, MBEDTLS_RSA_PUBLIC, + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } + + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature (restartable) + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->sign_rs_func != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng, NULL ) ); +} + +/* + * Decrypt message + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) +{ + PK_VALIDATE_RET( pub != NULL ); + PK_VALIDATE_RET( prv != NULL ); + + if( pub->pk_info == NULL || + prv->pk_info == NULL ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + + if( prv->pk_info->check_pair_func == NULL ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + /* For backward compatibility, accept NULL or a context that + * isn't set up yet, and return a fake value that should be safe. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Load the key to a PSA key slot, + * then turn the PK context into a wrapper for that key slot. + * + * Currently only works for EC private keys. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_id_t *key, + psa_algorithm_t hash_alg ) +{ +#if !defined(MBEDTLS_ECP_C) + ((void) pk); + ((void) key); + ((void) hash_alg); + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + const mbedtls_ecp_keypair *ec; + unsigned char d[MBEDTLS_ECP_MAX_BYTES]; + size_t d_len; + psa_ecc_family_t curve_id; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + size_t bits; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* export the private key material in the format PSA wants */ + if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ec = mbedtls_pk_ec( *pk ); + d_len = ( ec->grp.nbits + 7 ) / 8; + if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 ) + return( ret ); + + curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits ); + key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id ); + + /* prepare the key attributes */ + psa_set_key_type( &attributes, key_type ); + psa_set_key_bits( &attributes, bits ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); + psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) ); + + /* import private key into PSA */ + if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, key ) ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + + /* make PK context wrap the key slot */ + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + + return( mbedtls_pk_setup_opaque( pk, *key ) ); +#endif /* MBEDTLS_ECP_C */ +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c new file mode 100644 index 0000000..107e912 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pk_wrap.c @@ -0,0 +1,1069 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk_internal.h" +#include "mbedtls/error.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/asn1write.h" +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} + +static size_t rsa_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} + +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if( sig_len > rsa_len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); + +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + eckey_restart_ctx *rs_ctx; + + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); +} + +static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} + +static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif +#else /* MBEDTLS_ECDSA_C */ + NULL, + NULL, +#endif /* MBEDTLS_ECDSA_C */ + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of + * those integers and convert it to the fixed-length encoding expected by PSA. + */ +static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end, + unsigned char *to, size_t to_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t unpadded_len, padding_len; + + if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len, + MBEDTLS_ASN1_INTEGER ) ) != 0 ) + { + return( ret ); + } + + while( unpadded_len > 0 && **from == 0x00 ) + { + ( *from )++; + unpadded_len--; + } + + if( unpadded_len > to_len || unpadded_len == 0 ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + padding_len = to_len - unpadded_len; + memset( to, 0x00, padding_len ); + memcpy( to + padding_len, *from, unpadded_len ); + ( *from ) += unpadded_len; + + return( 0 ); +} + +/* + * Convert a signature from an ASN.1 sequence of two integers + * to a raw {r,s} buffer. Note: the provided sig buffer must be at least + * twice as big as int_size. + */ +static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end, + unsigned char *sig, size_t int_size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tmp_size; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + /* Extract r */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 ) + return( ret ); + /* Extract s */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +static int ecdsa_verify_wrap( void *ctx_arg, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + mbedtls_ecdsa_context *ctx = ctx_arg; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */ + unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES]; + unsigned char *p; + mbedtls_pk_info_t pk_info = mbedtls_eckey_info; + psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; + size_t curve_bits; + psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits ); + const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8; + ((void) md_alg); + + if( curve == 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* mbedtls_pk_write_pubkey() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &pk_info; + key.pk_ctx = ctx; + p = buf + sizeof( buf ); + key_len = mbedtls_pk_write_pubkey( &p, buf, &key ); + if( key_len <= 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &attributes, psa_sig_md ); + + status = psa_import_key( &attributes, + buf + sizeof( buf ) - key_len, key_len, + &key_id ); + if( status != PSA_SUCCESS ) + { + ret = mbedtls_psa_err_translate_pk( status ); + goto cleanup; + } + + /* We don't need the exported key anymore and can + * reuse its buffer for signature extraction. */ + if( 2 * signature_part_size > sizeof( buf ) ) + { + ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; + goto cleanup; + } + + p = (unsigned char*) sig; + if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf, + signature_part_size ) ) != 0 ) + { + goto cleanup; + } + + if( psa_verify_hash( key_id, psa_sig_md, + hash, hash_len, + buf, 2 * signature_part_size ) + != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + if( p != sig + sig_len ) + { + ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + goto cleanup; + } + ret = 0; + +cleanup: + psa_destroy_key( key_id ); + return( ret ); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); + +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void ecdsa_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv ) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, &sig_len, NULL, NULL ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, +}; + +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +static void *pk_opaque_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( psa_key_id_t ) ); + + /* no _init() function to call, an calloc() already zeroized */ + + return( ctx ); +} + +static void pk_opaque_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( psa_key_id_t ) ); + mbedtls_free( ctx ); +} + +static size_t pk_opaque_get_bitlen( const void *ctx ) +{ + const psa_key_id_t *key = (const psa_key_id_t *) ctx; + size_t bits; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + if( PSA_SUCCESS != psa_get_key_attributes( *key, &attributes ) ) + return( 0 ); + + bits = psa_get_key_bits( &attributes ); + psa_reset_key_attributes( &attributes ); + return( bits ); +} + +static int pk_opaque_can_do( mbedtls_pk_type_t type ) +{ + /* For now opaque PSA keys can only wrap ECC keypairs, + * as checked by setup_psa(). + * Also, ECKEY_DH does not really make sense with the current API. */ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECDSA ); +} + +#if defined(MBEDTLS_ECDSA_C) + +/* + * Simultaneously convert and move raw MPI from the beginning of a buffer + * to an ASN.1 MPI at the end of the buffer. + * See also mbedtls_asn1_write_mpi(). + * + * p: pointer to the end of the output buffer + * start: start of the output buffer, and also of the mpi to write at the end + * n_len: length of the mpi to read from start + */ +static int asn1_write_mpibuf( unsigned char **p, unsigned char *start, + size_t n_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( (size_t)( *p - start ) < n_len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = n_len; + *p -= len; + memmove( *p, start, len ); + + /* ASN.1 DER encoding requires minimal length, so skip leading 0s. + * Neither r nor s should be 0, but as a failsafe measure, still detect + * that rather than overflowing the buffer in case of a PSA error. */ + while( len > 0 && **p == 0x00 ) + { + ++(*p); + --len; + } + + /* this is only reached if the signature was invalid */ + if( len == 0 ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + + /* if the msb is 1, ASN.1 requires that we prepend a 0. + * Neither r nor s can be 0, so we can assume len > 0 at all times. */ + if( **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_INTEGER ) ); + + return( (int) len ); +} + +/* Transcode signature from PSA format to ASN.1 sequence. + * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of + * MPIs, and in-place. + * + * [in/out] sig: the signature pre- and post-transcoding + * [in/out] sig_len: signature length pre- and post-transcoding + * [int] buf_len: the available size the in/out buffer + */ +static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len, + size_t buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const size_t rs_len = *sig_len / 2; + unsigned char *p = sig + buf_len; + + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memmove( sig, p, len ); + *sig_len = len; + + return( 0 ); +} + +#endif /* MBEDTLS_ECDSA_C */ + +static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ +#if !defined(MBEDTLS_ECDSA_C) + ((void) ctx); + ((void) md_alg); + ((void) hash); + ((void) hash_len); + ((void) sig); + ((void) sig_len); + ((void) f_rng); + ((void) p_rng); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#else /* !MBEDTLS_ECDSA_C */ + const psa_key_id_t *key = (const psa_key_id_t *) ctx; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) ); + size_t buf_len; + psa_status_t status; + + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; + + /* PSA needs an output buffer of known size, but our API doesn't provide + * that information. Assume that the buffer is large enough for a + * maximal-length signature with that key (otherwise the application is + * buggy anyway). */ + status = psa_get_key_attributes( *key, &attributes ); + if( status != PSA_SUCCESS ) + return( mbedtls_psa_err_translate_pk( status ) ); + buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN( psa_get_key_bits( &attributes ) ); + psa_reset_key_attributes( &attributes ); + if( buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* make the signature */ + status = psa_sign_hash( *key, alg, hash, hash_len, + sig, buf_len, sig_len ); + if( status != PSA_SUCCESS ) + return( mbedtls_psa_err_translate_pk( status ) ); + + /* transcode it to ASN.1 sequence */ + return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, buf_len ) ); +#endif /* !MBEDTLS_ECDSA_C */ +} + +const mbedtls_pk_info_t mbedtls_pk_opaque_info = { + MBEDTLS_PK_OPAQUE, + "Opaque", + pk_opaque_get_bitlen, + pk_opaque_can_do, + NULL, /* verify - will be done later */ + pk_opaque_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, /* restartable verify - not relevant */ + NULL, /* restartable sign - not relevant */ +#endif + NULL, /* decrypt - will be done later */ + NULL, /* encrypt - will be done later */ + NULL, /* check_pair - could be done later or left NULL */ + pk_opaque_alloc_wrap, + pk_opaque_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, /* restart alloc - not relevant */ + NULL, /* restart free - not relevant */ +#endif + NULL, /* debug - could be done later, or even left NULL */ +}; + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_PK_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs11.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs11.c new file mode 100644 index 0000000..4deccf3 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs11.c @@ -0,0 +1,238 @@ +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbedtls/pkcs11.h" + +#if defined(MBEDTLS_PKCS11_C) + +#include "mbedtls/md.h" +#include "mbedtls/oid.h" +#include "mbedtls/x509_crt.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); +} + +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + unsigned char *cert_blob = NULL; + size_t cert_blob_size = 0; + + if( cert == NULL ) + { + ret = 2; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, + &cert_blob_size ) != CKR_OK ) + { + ret = 3; + goto cleanup; + } + + cert_blob = mbedtls_calloc( 1, cert_blob_size ); + if( NULL == cert_blob ) + { + ret = 4; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, + &cert_blob_size ) != CKR_OK ) + { + ret = 5; + goto cleanup; + } + + if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) + { + ret = 6; + goto cleanup; + } + + ret = 0; + +cleanup: + if( NULL != cert_blob ) + mbedtls_free( cert_blob ); + + return( ret ); +} + + +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + mbedtls_x509_crt cert; + + mbedtls_x509_crt_init( &cert ); + + if( priv_key == NULL ) + goto cleanup; + + if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) + goto cleanup; + + priv_key->len = mbedtls_pk_get_len( &cert.pk ); + priv_key->pkcs11h_cert = pkcs11_cert; + + ret = 0; + +cleanup: + mbedtls_x509_crt_free( &cert ); + + return( ret ); +} + +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) +{ + if( NULL != priv_key ) + pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); +} + +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + size_t input_len, output_len; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + output_len = input_len = ctx->len; + + if( input_len < 16 || input_len > output_max_len ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Determine size of output buffer */ + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, NULL, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( output_len > output_max_len ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, output, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + *olen = output_len; + return( 0 ); +} + +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t sig_len = 0, asn_len = 0, oid_size = 0; + unsigned char *p = sig; + const char *oid; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->len; + if( hashlen > sig_len || asn_len > sig_len || + hashlen + asn_len > sig_len ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = hashlen; + } + + memcpy( p, hash, hashlen ); + + if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, + asn_len + hashlen, sig, &sig_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#endif /* defined(MBEDTLS_PKCS11_C) */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c new file mode 100644 index 0000000..cacf7db --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs12.c @@ -0,0 +1,404 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 + * + * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn + */ + +#include "common.h" + +#if defined(MBEDTLS_PKCS12_C) + +#include "mbedtls/pkcs12.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + + /* + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret ) ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret ) ); + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +#define PKCS12_MAX_PWDLEN 128 + +static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + unsigned char *key, size_t keylen, + unsigned char *iv, size_t ivlen ) +{ + int ret, iterations = 0; + mbedtls_asn1_buf salt; + size_t i; + unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; + + if( pwdlen > PKCS12_MAX_PWDLEN ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); + memset( &unipwd, 0, sizeof(unipwd) ); + + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, + &iterations ) ) != 0 ) + return( ret ); + + for( i = 0; i < pwdlen; i++ ) + unipwd[i * 2 + 1] = pwd[i]; + + if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +#undef PKCS12_MAX_PWDLEN + +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ +#if !defined(MBEDTLS_ARC4_C) + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) len); + ((void) output); + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char key[16]; + mbedtls_arc4_context ctx; + ((void) mode); + + mbedtls_arc4_init( &ctx ); + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, + pwd, pwdlen, + key, 16, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + mbedtls_arc4_setup( &ctx, key, 16 ); + if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_arc4_free( &ctx ); + + return( ret ); +#endif /* MBEDTLS_ARC4_C */ +} + +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ + int ret, keylen = 0; + unsigned char key[32]; + unsigned char iv[16]; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_cipher_context_t cipher_ctx; + size_t olen = 0; + + if( pwd == NULL && pwdlen != 0 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_bitlen / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + mbedtls_cipher_init( &cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( iv, sizeof( iv ) ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, + const unsigned char *filler, size_t fill_len ) +{ + unsigned char *p = data; + size_t use_len; + + if( filler != NULL && fill_len != 0 ) + { + while( data_len > 0 ) + { + use_len = ( data_len > fill_len ) ? fill_len : data_len; + memcpy( p, filler, use_len ); + p += use_len; + data_len -= use_len; + } + } + else + { + /* If either of the above are not true then clearly there is nothing + * that this function can do. The function should *not* be called + * under either of those circumstances, as you could end up with an + * incorrect output but for safety's sake, leaving the check in as + * otherwise we could end up with memory corruption.*/ + } +} + +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t md_type, int id, int iterations ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int j; + + unsigned char diversifier[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + int use_password = 0; + int use_salt = 0; + + size_t hlen, use_len, v, i; + + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + // This version only allows max of 64 bytes of password or salt + if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + if( pwd == NULL && pwdlen != 0 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + if( salt == NULL && saltlen != 0 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + use_password = ( pwd && pwdlen != 0 ); + use_salt = ( salt && saltlen != 0 ); + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + mbedtls_md_init( &md_ctx ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + return( ret ); + hlen = mbedtls_md_get_size( md_info ); + + if( hlen <= 32 ) + v = 64; + else + v = 128; + + memset( diversifier, (unsigned char) id, v ); + + if( use_salt != 0 ) + { + pkcs12_fill_buffer( salt_block, v, salt, saltlen ); + } + + if( use_password != 0 ) + { + pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); + } + + p = data; + while( datalen > 0 ) + { + // Calculate hash( diversifier || salt_block || pwd_block ) + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( use_salt != 0 ) + { + if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v )) != 0 ) + goto exit; + } + + if( use_password != 0) + { + if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v )) != 0 ) + goto exit; + } + + if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) + goto exit; + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for( i = 1; i < (size_t) iterations; i++ ) + { + if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) + goto exit; + } + + use_len = ( datalen > hlen ) ? hlen : datalen; + memcpy( p, hash_output, use_len ); + datalen -= use_len; + p += use_len; + + if( datalen == 0 ) + break; + + // Concatenating copies of hash_output into hash_block (B) + pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); + + // B += 1 + for( i = v; i > 0; i-- ) + if( ++hash_block[i - 1] != 0 ) + break; + + if( use_salt != 0 ) + { + // salt_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = salt_block[i - 1] + hash_block[i - 1] + c; + c = MBEDTLS_BYTE_1( j ); + salt_block[i - 1] = MBEDTLS_BYTE_0( j ); + } + } + + if( use_password != 0 ) + { + // pwd_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = pwd_block[i - 1] + hash_block[i - 1] + c; + c = MBEDTLS_BYTE_1( j ); + pwd_block[i - 1] = MBEDTLS_BYTE_0( j ); + } + } + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); + + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PKCS12_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c new file mode 100644 index 0000000..2b014d9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkcs5.c @@ -0,0 +1,420 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#include "common.h" + +#if defined(MBEDTLS_PKCS5_C) + +#include "mbedtls/pkcs5.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/oid.h" +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations, + int *keylen, mbedtls_md_type_t *md_type ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + salt->p = p; + p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + int ret, iterations = 0, keylen = 0; + unsigned char *p, *end; + mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + mbedtls_asn1_buf salt; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const mbedtls_md_info_t *md_info; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_md_context_t md_ctx; + mbedtls_cipher_type_t cipher_alg; + mbedtls_cipher_context_t cipher_ctx; + + p = pbe_params->p; + end = p + pbe_params->len; + + /* + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} + * } + */ + if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, + &kdf_alg_params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + // Only PBKDF2 supported at the moment + // + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + } + + if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + /* + * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored + * since it is optional and we don't know if it was set or not + */ + keylen = cipher_info->key_bitlen / 8; + + if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); + } + + mbedtls_md_init( &md_ctx ); + mbedtls_cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, + (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + mbedtls_md_free( &md_ctx ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_ASN1_PARSE_C */ + +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, + const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int j; + unsigned int i; + unsigned char md1[MBEDTLS_MD_MAX_SIZE]; + unsigned char work[MBEDTLS_MD_MAX_SIZE]; + unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4]; + + memset( counter, 0, 4 ); + counter[3] = 1; + +#if UINT_MAX > 0xFFFFFFFF + if( iteration_count > 0xFFFFFFFF ) + return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif + + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 ) + goto cleanup; + + memcpy( md1, work, md_size ); + + for( i = 1; i < iteration_count; i++ ) + { + // U2 ends up in md1 + // + if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 ) + goto cleanup; + + // U1 xor U2 + // + for( j = 0; j < md_size; j++ ) + work[j] ^= md1[j]; + } + + use_len = ( key_length < md_size ) ? key_length : md_size; + memcpy( out_p, work, use_len ); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for( i = 4; i > 0; i-- ) + if( ++counter[i - 1] != 0 ) + break; + } + +cleanup: + /* Zeroise buffers to clear sensitive data from memory. */ + mbedtls_platform_zeroize( work, MBEDTLS_MD_MAX_SIZE ); + mbedtls_platform_zeroize( md1, MBEDTLS_MD_MAX_SIZE ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +int mbedtls_pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); + + return( 0 ); +} +#else + +#define MAX_TESTS 6 + +static const size_t plen_test_data[MAX_TESTS] = + { 8, 8, 8, 24, 9 }; + +static const unsigned char password_test_data[MAX_TESTS][32] = +{ + "password", + "password", + "password", + "passwordPASSWORDpassword", + "pass\0word", +}; + +static const size_t slen_test_data[MAX_TESTS] = + { 4, 4, 4, 36, 5 }; + +static const unsigned char salt_test_data[MAX_TESTS][40] = +{ + "salt", + "salt", + "salt", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + "sa\0lt", +}; + +static const uint32_t it_cnt_test_data[MAX_TESTS] = + { 1, 2, 4096, 4096, 4096 }; + +static const uint32_t key_len_test_data[MAX_TESTS] = + { 20, 20, 20, 25, 16 }; + +static const unsigned char result_key_test_data[MAX_TESTS][32] = +{ + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 }, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 }, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 }, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, +}; + +int mbedtls_pkcs5_self_test( int verbose ) +{ + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + mbedtls_md_init( &sha1_ctx ); + + info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password_test_data[i], + plen_test_data[i], salt_test_data[i], + slen_test_data[i], it_cnt_test_data[i], + key_len_test_data[i], key ); + if( ret != 0 || + memcmp( result_key_test_data[i], key, key_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_md_free( &sha1_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_SHA1_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_PKCS5_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c new file mode 100644 index 0000000..ea5c6b6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkparse.c @@ -0,0 +1,1545 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + PK_VALIDATE_RET( path != NULL ); + PK_VALIDATE_RET( buf != NULL ); + PK_VALIDATE_RET( n != NULL ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ( end - *p < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init( &ref ); + + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( end != NULL ); + PK_VALIDATE_RET( pk != NULL ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); +} + +#if defined(MBEDTLS_RSA_C) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. + * + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). + * + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. + */ +static int asn1_get_nonzero_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + + ret = mbedtls_asn1_get_mpi( p, end, X ); + if( ret != 0 ) + return( ret ); + + if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + return( 0 ); +} + +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init( &T ); + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + if( version != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + /* Import N */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import E */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + NULL, &T ) ) != 0 ) + goto cleanup; + + /* Import D */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + &T, NULL ) ) != 0 ) + goto cleanup; + + /* Import P */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import Q */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, + NULL, NULL ) ) != 0 ) + goto cleanup; + +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) + goto cleanup; + + /* Import DQ */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) + goto cleanup; + + /* Import QP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) + goto cleanup; + +#else + /* Verify existence of the CRT params */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || + ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) + { + goto cleanup; + } + + if( p != end ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ); + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + + mbedtls_rsa_free( rsa ); + } + + return( ret ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + } + + if( p != end ) + { + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( p + len != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( version != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret ) ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( len < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + + p = key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + buf = p; + + /* + * Decrypt EncryptedData with appropriate PBE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, + MBEDTLS_PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + // + if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_info_t *pk_info; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + PK_VALIDATE_RET( pk != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + { + unsigned char *key_copy; + + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen ); + + mbedtls_platform_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); + } + + if( ret == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ); + if( ret == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) == 0 ) + { + return( 0 ); + } + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_ECP_C */ + + /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + PK_VALIDATE_RET( ctx != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL || keylen == 0 ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + { + mbedtls_pem_free( &pem ); + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + } + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + mbedtls_pem_free( &pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c new file mode 100644 index 0000000..566153d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/pkwrite.c @@ -0,0 +1,623 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + mbedtls_rsa_context *rsa ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_mpi T; + + mbedtls_mpi_init( &T ); + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + +end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} + +/* + * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + */ +static int pk_write_ec_private( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t byte_length = ( ec->grp.pbits + 7 ) / 8; + unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; + + ret = mbedtls_ecp_write_key( ec, tmp, byte_length ); + if( ret != 0 ) + goto exit; + ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length ); + +exit: + mbedtls_platform_zeroize( tmp, byte_length ); + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( start != NULL ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); + else +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE ) + { + size_t buffer_size; + psa_key_id_t* key_id = (psa_key_id_t*) key->pk_ctx; + + if ( *p < start ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + buffer_size = (size_t)( *p - start ); + if ( psa_export_public_key( *key_id, start, buffer_size, &len ) + != PSA_SUCCESS ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + else + { + *p -= len; + memmove( *p, start, len ); + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + mbedtls_pk_type_t pk_type; + const char *oid; + + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + pk_type = mbedtls_pk_get_type( key ); +#if defined(MBEDTLS_ECP_C) + if( pk_type == MBEDTLS_PK_ECKEY ) + { + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); + } +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( pk_type == MBEDTLS_PK_OPAQUE ) + { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + psa_key_id_t key_id; + psa_ecc_family_t curve; + size_t bits; + + key_id = *((psa_key_id_t*) key->pk_ctx ); + if( PSA_SUCCESS != psa_get_key_attributes( key_id, &attributes ) ) + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + key_type = psa_get_key_type( &attributes ); + bits = psa_get_key_bits( &attributes ); + psa_reset_key_attributes( &attributes ); + + curve = PSA_KEY_TYPE_ECC_GET_FAMILY( key_type ); + if( curve == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + ret = mbedtls_psa_get_ecc_oid_from_id( curve, bits, &oid, &oid_len ); + if( ret != 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + /* Write EC algorithm parameters; that's akin + * to pk_write_ec_param() above. */ + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf, + oid, oid_len ) ); + + /* The rest of the function works as for legacy EC contexts. */ + pk_type = MBEDTLS_PK_ECKEY; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid, + &oid_len ) ) != 0 ) + { + return( ret ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + size_t len = 0; + + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + mbedtls_mpi T; /* Temporary holding the exported parameters */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init( &T ); + + /* Export QP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DQ */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export Q */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export P */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export D */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, + buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) ); + + /* version */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(MBEDTLS_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" + +/* + * Max sizes of key per types. Shown as tag + len (+ content). + */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSA public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 9 (rsa oid) + * + 1 + 1 (params null) + * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) + * RSAPublicKey ::= SEQUENCE { 1 + 3 + * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 + * } + */ +#define RSA_PUB_DER_MAX_BYTES ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE ) + +/* + * RSA private keys: + * RSAPrivateKey ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * modulus INTEGER, 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) + * } + */ +#define MPI_MAX_SIZE_2 ( MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 ) +#define RSA_PRV_DER_MAX_BYTES ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 ) + +#else /* MBEDTLS_RSA_C */ + +#define RSA_PUB_DER_MAX_BYTES 0 +#define RSA_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 7 (ec oid) + * + 1 + 1 + 9 (namedCurve oid) + * subjectPublicKey BIT STRING 1 + 2 + 1 [1] + * + 1 (point format) [1] + * + 2 * ECP_MAX (coords) [1] + * } + */ +#define ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES ) + +/* + * EC private keys: + * ECPrivateKey ::= SEQUENCE { 1 + 2 + * version INTEGER , 1 + 1 + 1 + * privateKey OCTET STRING, 1 + 1 + ECP_MAX + * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) + * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above + * } + */ +#define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) + +#else /* MBEDTLS_ECP_C */ + +#define ECP_PUB_DER_MAX_BYTES 0 +#define ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_ECP_C */ + +#define PUB_DER_MAX_BYTES ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES ) +#define PRV_DER_MAX_BYTES ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES ) + +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output_buf[PUB_DER_MAX_BYTES]; + size_t olen = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output_buf[PRV_DER_MAX_BYTES]; + const char *begin, *end; + size_t olen = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c new file mode 100644 index 0000000..e742fde --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/platform.c @@ -0,0 +1,386 @@ +/* + * Platform abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PLATFORM_C) + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +/* The compile time configuration of memory allocation via the macros + * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime + * configuration via mbedtls_platform_set_calloc_free(). So, omit everything + * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ +#if defined(MBEDTLS_PLATFORM_MEMORY) && \ + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) + +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY && + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ + +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + va_list argp; + + va_start( argp, fmt ); + ret = mbedtls_vsnprintf( s, n, fmt, argp ); + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + +#if defined(_TRUNCATE) + ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg ); +#else + ret = vsnprintf( s, n, fmt, arg ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_vsnprintf_uninit( char * s, size_t n, + const char * format, va_list arg ) +{ + ((void) s); + ((void) n); + ((void) format); + ((void) arg); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */ + +int (*mbedtls_vsnprintf)( char * s, size_t n, + const char * format, + va_list arg ) = MBEDTLS_PLATFORM_STD_VSNPRINTF; + +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, + va_list arg ) ) +{ + mbedtls_vsnprintf = vsnprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return( -1 ); + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + mbedtls_platform_zeroize( buf, buf_len ); + return( -1 ); + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#endif /* MBEDTLS_PLATFORM_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c new file mode 100644 index 0000000..98fe5de --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/platform_util.c @@ -0,0 +1,133 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#include "common.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" +#include "mbedtls/threading.h" + +#include +#include + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL ); + + if( len > 0 ) + memset_func( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ + +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_r( tt, tm_buf ) ); +#else + struct tm *lt; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + lt = gmtime( tt ); + + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c new file mode 100644 index 0000000..7375a0c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/poly1305.c @@ -0,0 +1,538 @@ +/** + * \file poly1305.c + * + * \brief Poly1305 authentication algorithm. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "common.h" + +#if defined(MBEDTLS_POLY1305_C) + +#include "mbedtls/poly1305.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_POLY1305_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define POLY1305_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define POLY1305_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define POLY1305_BLOCK_SIZE_BYTES ( 16U ) + +/* + * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. + * However we provided an alternative for platforms without such a multiplier. + */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) +static uint64_t mul64( uint32_t a, uint32_t b ) +{ + /* a = al + 2**16 ah, b = bl + 2**16 bh */ + const uint16_t al = (uint16_t) a; + const uint16_t bl = (uint16_t) b; + const uint16_t ah = a >> 16; + const uint16_t bh = b >> 16; + + /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ + const uint32_t lo = (uint32_t) al * bl; + const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh; + const uint32_t hi = (uint32_t) ah * bh; + + return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) ); +} +#else +static inline uint64_t mul64( uint32_t a, uint32_t b ) +{ + return( (uint64_t) a * b ); +} +#endif + + +/** + * \brief Process blocks with Poly1305. + * + * \param ctx The Poly1305 context. + * \param nblocks Number of blocks to process. Note that this + * function only processes full blocks. + * \param input Buffer containing the input block(s). + * \param needs_padding Set to 0 if the padding bit has already been + * applied to the input data before calling this + * function. Otherwise, set this parameter to 1. + */ +static void poly1305_process( mbedtls_poly1305_context *ctx, + size_t nblocks, + const unsigned char *input, + uint32_t needs_padding ) +{ + uint64_t d0, d1, d2, d3; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t r0, r1, r2, r3; + uint32_t rs1, rs2, rs3; + size_t offset = 0U; + size_t i; + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + + rs1 = r1 + ( r1 >> 2U ); + rs2 = r2 + ( r2 >> 2U ); + rs3 = r3 + ( r3 >> 2U ); + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Process full blocks */ + for( i = 0U; i < nblocks; i++ ) + { + /* The input block is treated as a 128-bit little-endian integer */ + d0 = MBEDTLS_GET_UINT32_LE( input, offset + 0 ); + d1 = MBEDTLS_GET_UINT32_LE( input, offset + 4 ); + d2 = MBEDTLS_GET_UINT32_LE( input, offset + 8 ); + d3 = MBEDTLS_GET_UINT32_LE( input, offset + 12 ); + + /* Compute: acc += (padded) block as a 130-bit integer */ + d0 += (uint64_t) acc0; + d1 += (uint64_t) acc1 + ( d0 >> 32U ); + d2 += (uint64_t) acc2 + ( d1 >> 32U ); + d3 += (uint64_t) acc3 + ( d2 >> 32U ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding; + + /* Compute: acc *= r */ + d0 = mul64( acc0, r0 ) + + mul64( acc1, rs3 ) + + mul64( acc2, rs2 ) + + mul64( acc3, rs1 ); + d1 = mul64( acc0, r1 ) + + mul64( acc1, r0 ) + + mul64( acc2, rs3 ) + + mul64( acc3, rs2 ) + + mul64( acc4, rs1 ); + d2 = mul64( acc0, r2 ) + + mul64( acc1, r1 ) + + mul64( acc2, r0 ) + + mul64( acc3, rs3 ) + + mul64( acc4, rs2 ); + d3 = mul64( acc0, r3 ) + + mul64( acc1, r2 ) + + mul64( acc2, r1 ) + + mul64( acc3, r0 ) + + mul64( acc4, rs3 ); + acc4 *= r0; + + /* Compute: acc %= (2^130 - 5) (partial remainder) */ + d1 += ( d0 >> 32 ); + d2 += ( d1 >> 32 ); + d3 += ( d2 >> 32 ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 = (uint32_t) ( d3 >> 32 ) + acc4; + + d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU ); + acc4 &= 3U; + acc0 = (uint32_t) d0; + d0 = (uint64_t) acc1 + ( d0 >> 32U ); + acc1 = (uint32_t) d0; + d0 = (uint64_t) acc2 + ( d0 >> 32U ); + acc2 = (uint32_t) d0; + d0 = (uint64_t) acc3 + ( d0 >> 32U ); + acc3 = (uint32_t) d0; + d0 = (uint64_t) acc4 + ( d0 >> 32U ); + acc4 = (uint32_t) d0; + + offset += POLY1305_BLOCK_SIZE_BYTES; + } + + ctx->acc[0] = acc0; + ctx->acc[1] = acc1; + ctx->acc[2] = acc2; + ctx->acc[3] = acc3; + ctx->acc[4] = acc4; +} + +/** + * \brief Compute the Poly1305 MAC + * + * \param ctx The Poly1305 context. + * \param mac The buffer to where the MAC is written. Must be + * big enough to contain the 16-byte MAC. + */ +static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + uint64_t d; + uint32_t g0, g1, g2, g3, g4; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t mask; + uint32_t mask_inv; + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. + * We do this by calculating acc - (2^130 - 5), then checking if + * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) + */ + + /* Calculate acc + -(2^130 - 5) */ + d = ( (uint64_t) acc0 + 5U ); + g0 = (uint32_t) d; + d = ( (uint64_t) acc1 + ( d >> 32 ) ); + g1 = (uint32_t) d; + d = ( (uint64_t) acc2 + ( d >> 32 ) ); + g2 = (uint32_t) d; + d = ( (uint64_t) acc3 + ( d >> 32 ) ); + g3 = (uint32_t) d; + g4 = acc4 + (uint32_t) ( d >> 32U ); + + /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ + mask = (uint32_t) 0U - ( g4 >> 2U ); + mask_inv = ~mask; + + /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ + acc0 = ( acc0 & mask_inv ) | ( g0 & mask ); + acc1 = ( acc1 & mask_inv ) | ( g1 & mask ); + acc2 = ( acc2 & mask_inv ) | ( g2 & mask ); + acc3 = ( acc3 & mask_inv ) | ( g3 & mask ); + + /* Add 's' */ + d = (uint64_t) acc0 + ctx->s[0]; + acc0 = (uint32_t) d; + d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U ); + acc1 = (uint32_t) d; + d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U ); + acc2 = (uint32_t) d; + acc3 += ctx->s[3] + (uint32_t) ( d >> 32U ); + + /* Compute MAC (128 least significant bits of the accumulator) */ + MBEDTLS_PUT_UINT32_LE( acc0, mac, 0 ); + MBEDTLS_PUT_UINT32_LE( acc1, mac, 4 ); + MBEDTLS_PUT_UINT32_LE( acc2, mac, 8 ); + MBEDTLS_PUT_UINT32_LE( acc3, mac, 12 ); +} + +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) +{ + POLY1305_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( key != NULL ); + + /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = MBEDTLS_GET_UINT32_LE( key, 0 ) & 0x0FFFFFFFU; + ctx->r[1] = MBEDTLS_GET_UINT32_LE( key, 4 ) & 0x0FFFFFFCU; + ctx->r[2] = MBEDTLS_GET_UINT32_LE( key, 8 ) & 0x0FFFFFFCU; + ctx->r[3] = MBEDTLS_GET_UINT32_LE( key, 12 ) & 0x0FFFFFFCU; + + ctx->s[0] = MBEDTLS_GET_UINT32_LE( key, 16 ); + ctx->s[1] = MBEDTLS_GET_UINT32_LE( key, 20 ); + ctx->s[2] = MBEDTLS_GET_UINT32_LE( key, 24 ); + ctx->s[3] = MBEDTLS_GET_UINT32_LE( key, 28 ); + + /* Initial accumulator state */ + ctx->acc[0] = 0U; + ctx->acc[1] = 0U; + ctx->acc[2] = 0U; + ctx->acc[3] = 0U; + ctx->acc[4] = 0U; + + /* Queue initially empty */ + mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) ); + ctx->queue_len = 0U; + + return( 0 ); +} + +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + size_t offset = 0U; + size_t remaining = ilen; + size_t queue_free_len; + size_t nblocks; + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) + { + queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + if( ilen < queue_free_len ) + { + /* Not enough data to complete the block. + * Store this data with the other leftovers. + */ + memcpy( &ctx->queue[ctx->queue_len], + input, + ilen ); + + ctx->queue_len += ilen; + + remaining = 0U; + } + else + { + /* Enough data to produce a complete block */ + memcpy( &ctx->queue[ctx->queue_len], + input, + queue_free_len ); + + ctx->queue_len = 0U; + + poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */ + + offset += queue_free_len; + remaining -= queue_free_len; + } + } + + if( remaining >= POLY1305_BLOCK_SIZE_BYTES ) + { + nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; + + poly1305_process( ctx, nblocks, &input[offset], 1U ); + + offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; + remaining %= POLY1305_BLOCK_SIZE_BYTES; + } + + if( remaining > 0U ) + { + /* Store partial block */ + ctx->queue_len = remaining; + memcpy( ctx->queue, &input[offset], remaining ); + } + + return( 0 ); +} + +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + + /* Process any leftover data */ + if( ctx->queue_len > 0U ) + { + /* Add padding bit */ + ctx->queue[ctx->queue_len] = 1U; + ctx->queue_len++; + + /* Pad with zeroes */ + memset( &ctx->queue[ctx->queue_len], + 0, + POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + poly1305_process( ctx, 1U, /* Process 1 block */ + ctx->queue, 0U ); /* Already padded above */ + } + + poly1305_compute_mac( ctx, mac ); + + return( 0 ); +} + +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ) +{ + mbedtls_poly1305_context ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + POLY1305_VALIDATE_RET( key != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + mbedtls_poly1305_init( &ctx ); + + ret = mbedtls_poly1305_starts( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_update( &ctx, input, ilen ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_finish( &ctx, mac ); + +cleanup: + mbedtls_poly1305_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_POLY1305_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, + 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b + }, + { + 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, + 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 + } +}; + +static const unsigned char test_data[2][127] = +{ + { + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70 + }, + { + 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e + } +}; + +static const size_t test_data_len[2] = +{ + 34U, + 127U +}; + +static const unsigned char test_mac[2][16] = +{ + { + 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 + }, + { + 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 + } +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_poly1305_self_test( int verbose ) +{ + unsigned char mac[16]; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " Poly1305 test %u ", i ); + + ret = mbedtls_poly1305_mac( test_keys[i], + test_data[i], + test_data_len[i], + mac ); + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_POLY1305_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c new file mode 100644 index 0000000..aed7322 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ripemd160.c @@ -0,0 +1,536 @@ +/* + * RIPE MD-160 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#include "common.h" + +#if defined(MBEDTLS_RIPEMD160_C) + +#include "mbedtls/ripemd160.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) + +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ) +{ + *dst = *src; +} + +/* + * RIPEMD-160 context setup + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + mbedtls_ripemd160_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + } local; + + local.X[ 0] = MBEDTLS_GET_UINT32_LE( data, 0 ); + local.X[ 1] = MBEDTLS_GET_UINT32_LE( data, 4 ); + local.X[ 2] = MBEDTLS_GET_UINT32_LE( data, 8 ); + local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 ); + local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 ); + local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 ); + local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 ); + local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 ); + local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 ); + local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 ); + local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 ); + local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 ); + local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 ); + local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 ); + local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 ); + local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 ); + + local.A = local.Ap = ctx->state[0]; + local.B = local.Bp = ctx->state[1]; + local.C = local.Cp = ctx->state[2]; + local.D = local.Dp = ctx->state[3]; + local.E = local.Ep = ctx->state[4]; + +#define F1( x, y, z ) ( (x) ^ (y) ^ (z) ) +#define F2( x, y, z ) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) +#define F3( x, y, z ) ( ( (x) | ~(y) ) ^ (z) ) +#define F4( x, y, z ) ( ( (x) & (z) ) | ( (y) & ~(z) ) ) +#define F5( x, y, z ) ( (x) ^ ( (y) | ~(z) ) ) + +#define S( x, n ) ( ( (x) << (n) ) | ( (x) >> (32 - (n)) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + do \ + { \ + (a) += f( (b), (c), (d) ) + local.X[r] + (k); \ + (a) = S( (a), (s) ) + (e); \ + (c) = S( (c), 10 ); \ + } while( 0 ) + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + do \ + { \ + P( (a), (b), (c), (d), (e), (r), (s), F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, \ + (rp), (sp), Fp, Kp ); \ + } while( 0 ) + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( local.A, local.B, local.C, local.D, local.E, 0, 11, 5, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 1, 14, 14, 9 ); + P2( local.D, local.E, local.A, local.B, local.C, 2, 15, 7, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 3, 12, 0, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 4, 5, 9, 13 ); + P2( local.A, local.B, local.C, local.D, local.E, 5, 8, 2, 15 ); + P2( local.E, local.A, local.B, local.C, local.D, 6, 7, 11, 15 ); + P2( local.D, local.E, local.A, local.B, local.C, 7, 9, 4, 5 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 11, 13, 7 ); + P2( local.B, local.C, local.D, local.E, local.A, 9, 13, 6, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 10, 14, 15, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 11, 15, 8, 11 ); + P2( local.D, local.E, local.A, local.B, local.C, 12, 6, 1, 14 ); + P2( local.C, local.D, local.E, local.A, local.B, 13, 7, 10, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 9, 3, 12 ); + P2( local.A, local.B, local.C, local.D, local.E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( local.E, local.A, local.B, local.C, local.D, 7, 7, 6, 9 ); + P2( local.D, local.E, local.A, local.B, local.C, 4, 6, 11, 13 ); + P2( local.C, local.D, local.E, local.A, local.B, 13, 8, 3, 15 ); + P2( local.B, local.C, local.D, local.E, local.A, 1, 13, 7, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 10, 11, 0, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 6, 9, 13, 8 ); + P2( local.D, local.E, local.A, local.B, local.C, 15, 7, 5, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 3, 15, 10, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 7, 14, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 0, 12, 15, 7 ); + P2( local.E, local.A, local.B, local.C, local.D, 9, 15, 8, 12 ); + P2( local.D, local.E, local.A, local.B, local.C, 5, 9, 12, 7 ); + P2( local.C, local.D, local.E, local.A, local.B, 2, 11, 4, 6 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 7, 9, 15 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 13, 1, 13 ); + P2( local.E, local.A, local.B, local.C, local.D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( local.D, local.E, local.A, local.B, local.C, 3, 11, 15, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 10, 13, 5, 7 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 6, 1, 15 ); + P2( local.A, local.B, local.C, local.D, local.E, 4, 7, 3, 11 ); + P2( local.E, local.A, local.B, local.C, local.D, 9, 14, 7, 8 ); + P2( local.D, local.E, local.A, local.B, local.C, 15, 9, 14, 6 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 13, 6, 6 ); + P2( local.B, local.C, local.D, local.E, local.A, 1, 15, 9, 14 ); + P2( local.A, local.B, local.C, local.D, local.E, 2, 14, 11, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 7, 8, 8, 13 ); + P2( local.D, local.E, local.A, local.B, local.C, 0, 13, 12, 5 ); + P2( local.C, local.D, local.E, local.A, local.B, 6, 6, 2, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 13, 5, 10, 13 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 12, 0, 13 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 7, 4, 7 ); + P2( local.D, local.E, local.A, local.B, local.C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( local.C, local.D, local.E, local.A, local.B, 1, 11, 8, 15 ); + P2( local.B, local.C, local.D, local.E, local.A, 9, 12, 6, 5 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 14, 4, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 10, 15, 1, 11 ); + P2( local.D, local.E, local.A, local.B, local.C, 0, 14, 3, 14 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 15, 11, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 9, 15, 6 ); + P2( local.A, local.B, local.C, local.D, local.E, 4, 8, 0, 14 ); + P2( local.E, local.A, local.B, local.C, local.D, 13, 9, 5, 6 ); + P2( local.D, local.E, local.A, local.B, local.C, 3, 14, 12, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 7, 5, 2, 12 ); + P2( local.B, local.C, local.D, local.E, local.A, 15, 6, 13, 9 ); + P2( local.A, local.B, local.C, local.D, local.E, 14, 8, 9, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 6, 7, 5 ); + P2( local.D, local.E, local.A, local.B, local.C, 6, 5, 10, 15 ); + P2( local.C, local.D, local.E, local.A, local.B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( local.B, local.C, local.D, local.E, local.A, 4, 9, 12, 8 ); + P2( local.A, local.B, local.C, local.D, local.E, 0, 15, 15, 5 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 5, 10, 12 ); + P2( local.D, local.E, local.A, local.B, local.C, 9, 11, 4, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 7, 6, 1, 12 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 8, 5, 5 ); + P2( local.A, local.B, local.C, local.D, local.E, 2, 13, 8, 14 ); + P2( local.E, local.A, local.B, local.C, local.D, 10, 12, 7, 6 ); + P2( local.D, local.E, local.A, local.B, local.C, 14, 5, 6, 8 ); + P2( local.C, local.D, local.E, local.A, local.B, 1, 12, 2, 13 ); + P2( local.B, local.C, local.D, local.E, local.A, 3, 13, 13, 6 ); + P2( local.A, local.B, local.C, local.D, local.E, 8, 14, 14, 5 ); + P2( local.E, local.A, local.B, local.C, local.D, 11, 11, 0, 15 ); + P2( local.D, local.E, local.A, local.B, local.C, 6, 8, 3, 13 ); + P2( local.C, local.D, local.E, local.A, local.B, 15, 5, 9, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + local.C = ctx->state[1] + local.C + local.Dp; + ctx->state[1] = ctx->state[2] + local.D + local.Ep; + ctx->state[2] = ctx->state[3] + local.E + local.Ap; + ctx->state[3] = ctx->state[4] + local.A + local.Bp; + ctx->state[4] = ctx->state[0] + local.B + local.Cp; + ctx->state[0] = local.C; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_ripemd160_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char ripemd160_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_LE( low, msglen, 0 ); + MBEDTLS_PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 ); + if( ret != 0 ) + return( ret ); + + MBEDTLS_PUT_UINT32_LE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + mbedtls_ripemd160_finish_ret( ctx, output ); +} +#endif + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + +/* + * output = RIPEMD-160( input buffer ) + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ripemd160_context ctx; + + mbedtls_ripemd160_init( &ctx ); + + if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_ripemd160_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_ripemd160_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC + */ +#define TESTS 8 +static const unsigned char ripemd160_test_str[TESTS][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }, +}; + +static const size_t ripemd160_test_strlen[TESTS] = +{ + 0, 1, 3, 14, 26, 56, 62, 80 +}; + +static const unsigned char ripemd160_test_md[TESTS][20] = +{ + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, + { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, + { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, +}; + +/* + * Checkup routine + */ +int mbedtls_ripemd160_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + ret = mbedtls_ripemd160_ret( ripemd160_test_str[i], + ripemd160_test_strlen[i], output ); + if( ret != 0 ) + goto fail; + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RIPEMD160_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c new file mode 100644 index 0000000..61d7f8e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa.c @@ -0,0 +1,2601 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/rsa_internal.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "constant_time_internal.h" +#include "mbedtls/constant_time.h" + +#include + +#if defined(MBEDTLS_PKCS1_V21) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if !defined(MBEDTLS_RSA_ALT) + +/* Parameter validation macros */ +#define RSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) +#define RSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( ctx != NULL ); + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + RSA_VALIDATE_RET( ctx != NULL ); + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + int have_N, have_P, have_Q, have_D, have_E; +#if !defined(MBEDTLS_RSA_NO_CRT) + int have_DP, have_DQ, have_QP; +#endif + int n_missing, pq_missing, d_missing, is_pub, is_priv; + + RSA_VALIDATE_RET( ctx != NULL ); + + have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + n_missing = have_P && have_Q && have_D && have_E; + pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + d_missing = have_P && have_Q && !have_D && have_E; + is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#endif + + return( 0 ); +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ) +{ + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + mbedtls_rsa_set_padding( ctx, padding, hash_id ); + +#if defined(MBEDTLS_THREADING_C) + /* Set ctx->ver to nonzero to indicate that the mutex has been + * initialized and will need to be freed. */ + ctx->ver = 1; + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ) +{ + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + +#if defined(MBEDTLS_GENPRIME) + +/* + * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi H, G, L; + int prime_quality = 0; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( f_rng != NULL ); + + /* + * If the modulus is 1024 bit long or shorter, then the security strength of + * the RSA algorithm is less than or equal to 80 bits and therefore an error + * rate of 2^-80 is sufficient. + */ + if( nbits > 1024 ) + prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; + + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); + + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + /* + * find primes P and Q with Q < P so that: + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); + + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) + continue; + + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; + + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); + + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; + + break; + } + while( 1 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); + +cleanup: + + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); + + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); + + if( ( -ret & ~0x7f ) == 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret ); + return( ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_GENPRIME */ + +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Check for the consistency of all fields in an RSA private key context + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) +{ + RSA_VALIDATE_RET( pub != NULL ); + RSA_VALIDATE_RET( prv != NULL ); + + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + mbedtls_mpi T; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret ) ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + + /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* At this point, Vi is invertible mod N if and only if both Vf and R + * are invertible mod N. If one of them isn't, we don't need to know + * which one, we just loop and choose new values for both of them. + * (Each iteration succeeds with overwhelming probability.) */ + ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N ); + if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* Blinding value: Vi = Vf^(-e) mod N + * (Vi already contains Vf^-1 at this point) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on average. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on average. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 1 /* private key checks */, + f_rng != NULL /* blinding y/n */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + if( ret != 0 && ret >= -0x007f ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret ) ); + + return( ret ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) +{ + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + int ret = 0; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_platform_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p += hlen; + + /* Construct DB */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == MBEDTLS_RSA_PUBLIC ) + { + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p++; + } + } + else + { + *p++ = MBEDTLS_RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + /* + * Parameters sanity checks + */ + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + if( ctx->P.n == 0 ) + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, NULL, NULL, input, buf ); + else + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + if( *olen != 0 ) + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + ilen = ctx->len; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding( mode, buf, ilen, + output, output_max_len, olen ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +static int rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char *salt = NULL; + size_t slen, min_slen, hlen, offset = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) + { + /* Calculate the largest possible salt length, up to the hash size. + * Normally this is the hash length, which is the maximum salt length + * according to FIPS 185-4 §5.5 (e) and common practice. If there is not + * enough room, use the maximum salt length that fits. The constraint is + * that the hash length plus the salt length plus 2 bytes must be at most + * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 + * (PKCS#1 v2.2) §9.1.1 step 3. */ + min_slen = hlen - 2; + if( olen < hlen + min_slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + else if( olen >= hlen + hlen + 2 ) + slen = hlen; + else + slen = olen - hlen - 2; + } + else if ( (saltlen < 0) || (saltlen + hlen + 2 > olen) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + else + { + slen = (size_t) saltlen; + } + + memset( sig, 0, olen ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen - slen - 2; + *p++ = 0x01; + + /* Generate salt of length slen in place in the encoded message */ + salt = p; + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + if( ctx->P.n == 0) + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, sig ) + : mbedtls_rsa_private( ctx, NULL, NULL, sig, sig ) ); + else + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, sig ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with + * the option to pass in the salt length. + */ +int mbedtls_rsa_rsassa_pss_sign_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ) +{ + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, md_alg, + hashlen, hash, saltlen, sig ); +} + + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *sig_try = NULL, *verif = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* + * Call respective RSA primitive + */ + + if( mode == MBEDTLS_RSA_PUBLIC ) + { + /* Skip verification on a public key operation */ + return( mbedtls_rsa_public( ctx, sig, sig ) ); + } + + /* Private key operation + * + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + + sig_try = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + if( mbedtls_ct_memcmp( verif, sig, ctx->len ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_platform_zeroize( sig_try, ctx->len ); + mbedtls_platform_zeroize( verif, ctx->len ); + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + if( ret != 0 ) + memset( sig, '!', ctx->len ); + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t siglen; + unsigned char *p; + unsigned char *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( FTMN_CALLEE_DONE_MEMCMP( memcmp, hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + mbedtls_md_type_t mgf1_hash_id; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret = 0; + size_t sig_len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + sig_len = ctx->len; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, encoded ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = FTMN_CALLEE_DONE_MEMCMP(mbedtls_ct_memcmp, encoded, + encoded_expected, sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_platform_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_platform_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( dst != NULL ); + RSA_VALIDATE_RET( src != NULL ); + + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); + mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); + mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); + mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + /* Free the mutex, but only if it hasn't been freed already. */ + if( ctx->ver != 0 ) + { + mbedtls_mutex_free( &ctx->mutex ); + ctx->ver = 0; + } +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) && !defined(__NetBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD && !NetBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif + + mbedtls_mpi K; + + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); + + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); + + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); + + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_internal.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_internal.c new file mode 100644 index 0000000..d6ba97a --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/rsa_internal.c @@ -0,0 +1,486 @@ +/* + * Helper functions for the RSA module + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "common.h" + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa_internal.h" + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + /* + * When generating keys, the strongest security we support aims for an error + * rate of at most 2^-100 and we are aiming for the same certainty here as + * well. + */ + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c new file mode 100644 index 0000000..0a5edaf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha1.c @@ -0,0 +1,553 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA1_C) + +#include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) + +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA1_ALT) + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + SHA1_VALIDATE( dst != NULL ); + SHA1_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE_RET( ctx != NULL ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t temp, W[16], A, B, C, D, E; + } local; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); + + local.W[ 0] = MBEDTLS_GET_UINT32_BE( data, 0 ); + local.W[ 1] = MBEDTLS_GET_UINT32_BE( data, 4 ); + local.W[ 2] = MBEDTLS_GET_UINT32_BE( data, 8 ); + local.W[ 3] = MBEDTLS_GET_UINT32_BE( data, 12 ); + local.W[ 4] = MBEDTLS_GET_UINT32_BE( data, 16 ); + local.W[ 5] = MBEDTLS_GET_UINT32_BE( data, 20 ); + local.W[ 6] = MBEDTLS_GET_UINT32_BE( data, 24 ); + local.W[ 7] = MBEDTLS_GET_UINT32_BE( data, 28 ); + local.W[ 8] = MBEDTLS_GET_UINT32_BE( data, 32 ); + local.W[ 9] = MBEDTLS_GET_UINT32_BE( data, 36 ); + local.W[10] = MBEDTLS_GET_UINT32_BE( data, 40 ); + local.W[11] = MBEDTLS_GET_UINT32_BE( data, 44 ); + local.W[12] = MBEDTLS_GET_UINT32_BE( data, 48 ); + local.W[13] = MBEDTLS_GET_UINT32_BE( data, 52 ); + local.W[14] = MBEDTLS_GET_UINT32_BE( data, 56 ); + local.W[15] = MBEDTLS_GET_UINT32_BE( data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + +#define R(t) \ + ( \ + local.temp = local.W[( (t) - 3 ) & 0x0F] ^ \ + local.W[( (t) - 8 ) & 0x0F] ^ \ + local.W[( (t) - 14 ) & 0x0F] ^ \ + local.W[ (t) & 0x0F], \ + ( local.W[(t) & 0x0F] = S(local.temp,1) ) \ + ) + +#define P(a,b,c,d,e,x) \ + do \ + { \ + (e) += S((a),5) + F((b),(c),(d)) + K + (x); \ + (b) = S((b),30); \ + } while( 0 ) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + local.E = ctx->state[4]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define K 0x5A827999 + + P( local.A, local.B, local.C, local.D, local.E, local.W[0] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[1] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[2] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[3] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[4] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[5] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[6] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[7] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[8] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[9] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[10] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[11] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[12] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[13] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[14] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[15] ); + P( local.E, local.A, local.B, local.C, local.D, R(16) ); + P( local.D, local.E, local.A, local.B, local.C, R(17) ); + P( local.C, local.D, local.E, local.A, local.B, R(18) ); + P( local.B, local.C, local.D, local.E, local.A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0x6ED9EBA1 + + P( local.A, local.B, local.C, local.D, local.E, R(20) ); + P( local.E, local.A, local.B, local.C, local.D, R(21) ); + P( local.D, local.E, local.A, local.B, local.C, R(22) ); + P( local.C, local.D, local.E, local.A, local.B, R(23) ); + P( local.B, local.C, local.D, local.E, local.A, R(24) ); + P( local.A, local.B, local.C, local.D, local.E, R(25) ); + P( local.E, local.A, local.B, local.C, local.D, R(26) ); + P( local.D, local.E, local.A, local.B, local.C, R(27) ); + P( local.C, local.D, local.E, local.A, local.B, R(28) ); + P( local.B, local.C, local.D, local.E, local.A, R(29) ); + P( local.A, local.B, local.C, local.D, local.E, R(30) ); + P( local.E, local.A, local.B, local.C, local.D, R(31) ); + P( local.D, local.E, local.A, local.B, local.C, R(32) ); + P( local.C, local.D, local.E, local.A, local.B, R(33) ); + P( local.B, local.C, local.D, local.E, local.A, R(34) ); + P( local.A, local.B, local.C, local.D, local.E, R(35) ); + P( local.E, local.A, local.B, local.C, local.D, R(36) ); + P( local.D, local.E, local.A, local.B, local.C, R(37) ); + P( local.C, local.D, local.E, local.A, local.B, R(38) ); + P( local.B, local.C, local.D, local.E, local.A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define K 0x8F1BBCDC + + P( local.A, local.B, local.C, local.D, local.E, R(40) ); + P( local.E, local.A, local.B, local.C, local.D, R(41) ); + P( local.D, local.E, local.A, local.B, local.C, R(42) ); + P( local.C, local.D, local.E, local.A, local.B, R(43) ); + P( local.B, local.C, local.D, local.E, local.A, R(44) ); + P( local.A, local.B, local.C, local.D, local.E, R(45) ); + P( local.E, local.A, local.B, local.C, local.D, R(46) ); + P( local.D, local.E, local.A, local.B, local.C, R(47) ); + P( local.C, local.D, local.E, local.A, local.B, R(48) ); + P( local.B, local.C, local.D, local.E, local.A, R(49) ); + P( local.A, local.B, local.C, local.D, local.E, R(50) ); + P( local.E, local.A, local.B, local.C, local.D, R(51) ); + P( local.D, local.E, local.A, local.B, local.C, R(52) ); + P( local.C, local.D, local.E, local.A, local.B, R(53) ); + P( local.B, local.C, local.D, local.E, local.A, R(54) ); + P( local.A, local.B, local.C, local.D, local.E, R(55) ); + P( local.E, local.A, local.B, local.C, local.D, R(56) ); + P( local.D, local.E, local.A, local.B, local.C, R(57) ); + P( local.C, local.D, local.E, local.A, local.B, R(58) ); + P( local.B, local.C, local.D, local.E, local.A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0xCA62C1D6 + + P( local.A, local.B, local.C, local.D, local.E, R(60) ); + P( local.E, local.A, local.B, local.C, local.D, R(61) ); + P( local.D, local.E, local.A, local.B, local.C, R(62) ); + P( local.C, local.D, local.E, local.A, local.B, R(63) ); + P( local.B, local.C, local.D, local.E, local.A, R(64) ); + P( local.A, local.B, local.C, local.D, local.E, R(65) ); + P( local.E, local.A, local.B, local.C, local.D, R(66) ); + P( local.D, local.E, local.A, local.B, local.C, R(67) ); + P( local.C, local.D, local.E, local.A, local.B, R(68) ); + P( local.B, local.C, local.D, local.E, local.A, R(69) ); + P( local.A, local.B, local.C, local.D, local.E, R(70) ); + P( local.E, local.A, local.B, local.C, local.D, R(71) ); + P( local.D, local.E, local.A, local.B, local.C, R(72) ); + P( local.C, local.D, local.E, local.A, local.B, R(73) ); + P( local.B, local.C, local.D, local.E, local.A, R(74) ); + P( local.A, local.B, local.C, local.D, local.E, R(75) ); + P( local.E, local.A, local.B, local.C, local.D, R(76) ); + P( local.D, local.E, local.A, local.B, local.C, R(77) ); + P( local.C, local.D, local.E, local.A, local.B, R(78) ); + P( local.B, local.C, local.D, local.E, local.A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + ctx->state[4] += local.E; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 ); + MBEDTLS_PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + MBEDTLS_PUT_UINT32_BE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha1_context ctx; + + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha1_init( &ctx ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_sha1_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto fail; + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) + goto fail; + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c new file mode 100644 index 0000000..db675ef --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha256.c @@ -0,0 +1,585 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA256_ALT) + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + SHA256_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + SHA256_VALIDATE( dst != NULL ); + SHA256_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) +{ + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) (((x) & 0xFFFFFFFF) >> (n)) +#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n)))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define R(t) \ + ( \ + local.W[t] = S1(local.W[(t) - 2]) + local.W[(t) - 7] + \ + S0(local.W[(t) - 15]) + local.W[(t) - 16] \ + ) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + local.temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += local.temp1; (h) = local.temp1 + local.temp2; \ + } while( 0 ) + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + } local; + + unsigned int i; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); + + for( i = 0; i < 8; i++ ) + local.A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i ); + else + R( i ); + + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); + + local.temp1 = local.A[7]; local.A[7] = local.A[6]; + local.A[6] = local.A[5]; local.A[5] = local.A[4]; + local.A[4] = local.A[3]; local.A[3] = local.A[2]; + local.A[2] = local.A[1]; local.A[1] = local.A[0]; + local.A[0] = local.temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], R(i+0), K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], R(i+1), K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], R(i+2), K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], R(i+3), K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], R(i+4), K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], R(i+5), K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], R(i+6), K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += local.A[i]; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 ); + MBEDTLS_PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + MBEDTLS_PUT_UINT32_BE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[5], output, 20 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + MBEDTLS_PUT_UINT32_BE( ctx->state[7], output, 28 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha256_context ctx; + + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha256_init( &ctx ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha256_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + mbedtls_sha256_ret( input, ilen, output, is224 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 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 }, + { 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 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 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 }, + { 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 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha256_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + + } + else + { + ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 ) + goto fail; + + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c new file mode 100644 index 0000000..02a135c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/sha512.c @@ -0,0 +1,660 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA512_C) + +#include "mbedtls/sha512.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA512_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) +#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA512_ALT) + +#if defined(MBEDTLS_SHA512_SMALLER) +static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i ) +{ + MBEDTLS_PUT_UINT64_BE(n, b, i); +} +#else +#define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE +#endif /* MBEDTLS_SHA512_SMALLER */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + SHA512_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + SHA512_VALIDATE( dst != NULL ); + SHA512_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) +{ + SHA512_VALIDATE_RET( ctx != NULL ); +#if !defined(MBEDTLS_SHA512_NO_SHA384) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { +#if defined(MBEDTLS_SHA512_NO_SHA384) + return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ); +#else + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); +#endif /* MBEDTLS_SHA512_NO_SHA384 */ + } + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + ctx->is384 = is384; +#endif + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + int i; + struct + { + uint64_t temp1, temp2, W[80]; + uint64_t A[8]; + } local; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); + +#define SHR(x,n) ((x) >> (n)) +#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n)))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + local.temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += local.temp1; (h) = local.temp1 + local.temp2; \ + } while( 0 ) + + for( i = 0; i < 8; i++ ) + local.A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA512_SMALLER) + for( i = 0; i < 80; i++ ) + { + if( i < 16 ) + { + local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 ); + } + else + { + local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + + S0(local.W[i - 15]) + local.W[i - 16]; + } + + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); + + local.temp1 = local.A[7]; local.A[7] = local.A[6]; + local.A[6] = local.A[5]; local.A[5] = local.A[4]; + local.A[4] = local.A[3]; local.A[3] = local.A[2]; + local.A[2] = local.A[1]; local.A[1] = local.A[0]; + local.A[0] = local.temp1; + } +#else /* MBEDTLS_SHA512_SMALLER */ + for( i = 0; i < 16; i++ ) + { + local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + + S0(local.W[i - 15]) + local.W[i - 16]; + } + + i = 0; + do + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++; + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++; + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++; + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++; + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++; + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++; + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++; + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++; + } + while( i < 80 ); +#endif /* MBEDTLS_SHA512_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += local.A[i]; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + unsigned int left; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned used; + uint64_t high, low; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + + ctx->buffer[used++] = 0x80; + + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + sha512_put_uint64_be( high, ctx->buffer, 112 ); + sha512_put_uint64_be( low, ctx->buffer, 120 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + sha512_put_uint64_be( ctx->state[0], output, 0 ); + sha512_put_uint64_be( ctx->state[1], output, 8 ); + sha512_put_uint64_be( ctx->state[2], output, 16 ); + sha512_put_uint64_be( ctx->state[3], output, 24 ); + sha512_put_uint64_be( ctx->state[4], output, 32 ); + sha512_put_uint64_be( ctx->state[5], output, 40 ); + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + if( ctx->is384 == 0 ) +#endif + { + sha512_put_uint64_be( ctx->state[6], output, 48 ); + sha512_put_uint64_be( ctx->state[7], output, 56 ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha512_context ctx; + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha512_init( &ctx ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + mbedtls_sha512_ret( input, ilen, output, is384 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[][64] = +{ +#if !defined(MBEDTLS_SHA512_NO_SHA384) + /* + * SHA-384 test vectors + */ + { 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 }, + { 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 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, +#endif /* !MBEDTLS_SHA512_NO_SHA384 */ + + /* + * SHA-512 test vectors + */ + { 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 }, + { 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 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) ) + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha512_init( &ctx ); + + for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ ) + { + j = i % 3; +#if !defined(MBEDTLS_SHA512_NO_SHA384) + k = i < 3; +#else + k = 0; +#endif + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha512_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 ) + goto fail; + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#undef ARRAY_LENGTH + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c new file mode 100644 index 0000000..32188cf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cache.c @@ -0,0 +1,345 @@ +/* + * SSL session cache implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CACHE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cache.h" +#include "mbedtls/ssl_internal.h" + +#include + +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); + + cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &cache->mutex ); +#endif +} + +int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ); +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *entry; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + cur = cache->chain; + entry = NULL; + + while( cur != NULL ) + { + entry = cur; + cur = cur->next; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - entry->timestamp ) > cache->timeout ) + continue; +#endif + + if( session->id_len != entry->session.id_len || + memcmp( session->id, entry->session.id, + entry->session.id_len ) != 0 ) + { + continue; + } + + ret = mbedtls_ssl_session_copy( session, &entry->session ); + if( ret != 0 ) + { + ret = 1; + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* + * Restore peer certificate (without rest of the original chain) + */ + if( entry->peer_cert.p != NULL ) + { + /* `session->peer_cert` is NULL after the call to + * mbedtls_ssl_session_copy(), because cache entries + * have the `peer_cert` field set to NULL. */ + + if( ( session->peer_cert = mbedtls_calloc( 1, + sizeof(mbedtls_x509_crt) ) ) == NULL ) + { + ret = 1; + goto exit; + } + + mbedtls_x509_crt_init( session->peer_cert ); + if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, + entry->peer_cert.len ) != 0 ) + { + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + ret = 1; + goto exit; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + ret = 0; + goto exit; + } + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; + mbedtls_ssl_cache_entry *old = NULL; +#endif + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur, *prv; + int count = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + cur = cache->chain; + prv = NULL; + + while( cur != NULL ) + { + count++; + +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + cur->timestamp = t; + break; /* expired, reuse this slot, update timestamp */ + } +#endif + + if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) + break; /* client reconnected, keep timestamp for session id */ + +#if defined(MBEDTLS_HAVE_TIME) + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } +#endif + + prv = cur; + cur = cur->next; + } + + if( cur == NULL ) + { +#if defined(MBEDTLS_HAVE_TIME) + /* + * Reuse oldest entry if max_entries reached + */ + if( count >= cache->max_entries ) + { + if( old == NULL ) + { + ret = 1; + goto exit; + } + + cur = old; + } +#else /* MBEDTLS_HAVE_TIME */ + /* + * Reuse first entry in chain if max_entries reached, + * but move to last place + */ + if( count >= cache->max_entries ) + { + if( cache->chain == NULL ) + { + ret = 1; + goto exit; + } + + cur = cache->chain; + cache->chain = cur->next; + cur->next = NULL; + prv->next = cur; + } +#endif /* MBEDTLS_HAVE_TIME */ + else + { + /* + * max_entries not reached, create new entry + */ + cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); + if( cur == NULL ) + { + ret = 1; + goto exit; + } + + if( prv == NULL ) + cache->chain = cur; + else + prv->next = cur; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur->timestamp = t; +#endif + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* + * If we're reusing an entry, free its certificate first + */ + if( cur->peer_cert.p != NULL ) + { + mbedtls_free( cur->peer_cert.p ); + memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* Copy the entire session; this temporarily makes a copy of the + * X.509 CRT structure even though we only want to store the raw CRT. + * This inefficiency will go away as soon as we implement on-demand + * parsing of CRTs, in which case there's no need for the `peer_cert` + * field anymore in the first place, and we're done after this call. */ + ret = mbedtls_ssl_session_copy( &cur->session, session ); + if( ret != 0 ) + { + ret = 1; + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* If present, free the X.509 structure and only store the raw CRT data. */ + if( cur->session.peer_cert != NULL ) + { + cur->peer_cert.p = + mbedtls_calloc( 1, cur->session.peer_cert->raw.len ); + if( cur->peer_cert.p == NULL ) + { + ret = 1; + goto exit; + } + + memcpy( cur->peer_cert.p, + cur->session.peer_cert->raw.p, + cur->session.peer_cert->raw.len ); + cur->peer_cert.len = session->peer_cert->raw.len; + + mbedtls_x509_crt_free( cur->session.peer_cert ); + mbedtls_free( cur->session.peer_cert ); + cur->session.peer_cert = NULL; + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +#if defined(MBEDTLS_HAVE_TIME) +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* MBEDTLS_HAVE_TIME */ + +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) +{ + mbedtls_ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + mbedtls_ssl_session_free( &prv->session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_free( prv->peer_cert.p ); +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + mbedtls_free( prv ); + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &cache->mutex ); +#endif + cache->chain = NULL; +} + +#endif /* MBEDTLS_SSL_CACHE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c new file mode 100644 index 0000000..ceec77e --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c @@ -0,0 +1,2373 @@ +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for mbed TLS + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" + +#include + +#undef HAVE_SHA384 +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +#define HAVE_SHA384 +#endif + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except RC4 and 3DES, weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK + * 2. By key length and cipher: + * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(MBEDTLS_SSL_CIPHERSUITES) + MBEDTLS_SSL_CIPHERSUITES, +#else + /* Chacha-Poly ephemeral suites */ + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + + /* All AES-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All ARIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + + /* All AES-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All ARIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + + /* The PSK ephemeral suites */ + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + + /* The ECJPAKE suite */ + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + + /* All AES-256 suites */ + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All ARIA-256 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + + /* All AES-128 suites */ + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All ARIA-128 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + + /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + + /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + + /* 3DES suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, + + /* RC4 suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, + + /* Weak suites */ + MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, + + /* NULL suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, + + MBEDTLS_TLS_RSA_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_WITH_NULL_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_PSK_WITH_NULL_SHA, + +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + 0 +}; + +static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(MBEDTLS_CHACHAPOLY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* MBEDTLS_CHACHAPOLY_C && + MBEDTLS_SHA256_C && + MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* HAVE_SHA384 */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(HAVE_SHA384) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(HAVE_SHA384) && defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* HAVE_SHA384 */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", + MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ARC4_C) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", + MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_NODTLS }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_ARC4_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(HAVE_SHA384) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_DES_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", + MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ + +#if defined(MBEDTLS_ARIA_C) + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(HAVE_SHA384)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#endif /* MBEDTLS_ARIA_C */ + + + { 0, "", + MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(MBEDTLS_SSL_CIPHERSUITES) +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info ) +{ + (void)cs_info; + +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ + +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB || + cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC ) + { + return( 1 ); + } +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ + + return( 0 ); +} + +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + !ciphersuite_is_removed( cs_info ) ) + { + *(q++) = *p; + } + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +} +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( MBEDTLS_PK_ECKEY ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cli.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cli.c new file mode 100644 index 0000000..72351c9 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cli.c @@ -0,0 +1,4609 @@ +/* + * SSLv3/TLSv1 client-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/constant_time.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf ) +{ + if( conf->psk_identity == NULL || + conf->psk_identity_len == 0 ) + { + return( 0 ); + } + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf ) +{ + if( conf->psk_identity == NULL || + conf->psk_identity_len == 0 ) + { + return( 0 ); + } + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t hostname_len; + + *olen = 0; + + if( ssl->hostname == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + hostname_len = strlen( ssl->hostname ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, hostname_len + 9 ); + + /* + * Sect. 3, RFC 6066 (TLS Extensions Definitions) + * + * In order to provide any of the server names, clients MAY include an + * extension of type "server_name" in the (extended) client hello. The + * "extension_data" field of this extension SHALL contain + * "ServerNameList" where: + * + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + * + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SERVERNAME, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( hostname_len + 5, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( hostname_len + 3, p, 0 ); + p += 2; + + *p++ = MBEDTLS_BYTE_0( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ); + + MBEDTLS_PUT_UINT16_BE( hostname_len, p, 0 ); + p += 2; + + memcpy( p, ssl->hostname, hostname_len ); + + *olen = hostname_len + 9; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the + * initial ClientHello, in which case also adding the renegotiation + * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding renegotiation extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 + ssl->verify_data_len ); + + /* + * Secure renegotiation + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = MBEDTLS_BYTE_0( ssl->verify_data_len + 1 ); + *p++ = MBEDTLS_BYTE_0( ssl->verify_data_len ); + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t sig_alg_len = 0; + const int *md; + +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding signature_algorithms extension" ) ); + + if( ssl->conf->sig_hashes == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + if( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "length in bytes of sig-hash-alg extension too big" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty signature algorithms list, this is a configuration error. */ + if( sig_alg_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 ); + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ + sig_alg_len = 0; + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; +#endif + } + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( sig_alg_len + 2, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( sig_alg_len, p, 0 ); + p += 2; + + *olen = 6 + sig_alg_len; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; + const mbedtls_ecp_group_id *grp_id; + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_elliptic_curves extension" ) ); + + if( ssl->conf->curve_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + if( info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "invalid curve in ssl configuration" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + elliptic_curve_len += 2; + + if( elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "malformed supported_elliptic_curves extension in config" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty elliptic curve list, this is a configuration error. */ + if( elliptic_curve_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + elliptic_curve_len ); + + elliptic_curve_len = 0; + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + elliptic_curve_list[elliptic_curve_len++] = MBEDTLS_BYTE_1( info->tls_id ); + elliptic_curve_list[elliptic_curve_len++] = MBEDTLS_BYTE_0( info->tls_id ); + } + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( elliptic_curve_len + 2, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( elliptic_curve_len, p, 0 ); + p += 2; + + *olen = 6 + elliptic_curve_len; + + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + (void) ssl; /* ssl used for debugging only */ + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_point_formats extension" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly extension if we can't use EC J-PAKE anyway */ + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding ecjpake_kkpp extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 ); + p += 2; + + /* + * We may need to send ClientHello multiple times for Hello verification. + * We don't want to compute fresh values every time (both for performance + * and consistency reasons), so cache the extension content. + */ + if( ssl->handshake->ecjpake_cache == NULL || + ssl->handshake->ecjpake_cache_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , + "mbedtls_ecjpake_write_round_one", ret ); + return( ret ); + } + + ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); + if( ssl->handshake->ecjpake_cache == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); + ssl->handshake->ecjpake_cache_len = kkpp_len; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); + + kkpp_len = ssl->handshake->ecjpake_cache_len; + MBEDTLS_SSL_CHK_BUF_PTR( p + 2, end, kkpp_len ); + + memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); + } + + MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 ); + p += 2; + + *olen = kkpp_len + 4; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_cid_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t ext_len; + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + + *olen = 0; + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + return( 0 ); + } + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding CID extension" ) ); + + /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX + * which is at most 255, so the increment cannot overflow. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, (unsigned)( ssl->own_cid_len + 5 ) ); + + /* Add extension ID + size */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_CID, p, 0 ); + p += 2; + ext_len = (size_t) ssl->own_cid_len + 1; + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2; + + *p++ = (uint8_t) ssl->own_cid_len; + memcpy( p, ssl->own_cid, ssl->own_cid_len ); + + *olen = ssl->own_cid_len + 5; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding max_fragment_length extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->conf->mfl_code; + + *olen = 5; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding truncated_hmac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_TRUNCATED_HMAC, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding encrypt_then_mac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding extended_master_secret extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t tlen = ssl->session_negotiate->ticket_len; + + *olen = 0; + + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding session ticket extension" ) ); + + /* The addition is safe here since the ticket length is 16 bit. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( tlen, p, 0 ); + p += 2; + + *olen = 4; + + if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t alpnlen = 0; + const char **cur; + + *olen = 0; + + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + alpnlen += strlen( *cur ) + 1; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, p, 0 ); + p += 2; + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Skip writing extension and list length for now */ + p += 4; + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + /* + * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of + * protocol names is less than 255. + */ + *p = (unsigned char)strlen( *cur ); + memcpy( p + 1, *cur, *p ); + p += 1 + *p; + } + + *olen = p - buf; + + /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 ); + + /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ + MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t protection_profiles_index = 0, ext_len = 0; + uint16_t mki_len = 0, profile_value = 0; + + *olen = 0; + + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + { + return( 0 ); + } + + /* RFC 5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + /* Extension length = 2 bytes for profiles length, + * ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ), + * 1 byte for srtp_mki vector length and the mki_len value + */ + ext_len = 2 + 2 * ( ssl->conf->dtls_srtp_profile_list_len ) + 1 + mki_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding use_srtp extension" ) ); + + /* Check there is room in the buffer for the extension + 4 bytes + * - the extension tag (2 bytes) + * - the extension length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, ext_len + 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_USE_SRTP, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2; + + /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */ + /* micro-optimization: + * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + * which is lower than 127, so the upper byte of the length is always 0 + * For the documentation, the more generic code is left in comments + * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len ) + * >> 8 ) & 0xFF ); + */ + *p++ = 0; + *p++ = MBEDTLS_BYTE_0( 2 * ssl->conf->dtls_srtp_profile_list_len ); + + for( protection_profiles_index=0; + protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len; + protection_profiles_index++ ) + { + profile_value = mbedtls_ssl_check_srtp_profile_value + ( ssl->conf->dtls_srtp_profile_list[protection_profiles_index] ); + if( profile_value != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_write_use_srtp_ext, add profile: %04x", + profile_value ) ); + MBEDTLS_PUT_UINT16_BE( profile_value, p, 0 ); + p += 2; + } + else + { + /* + * Note: we shall never arrive here as protection profiles + * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function + */ + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, " + "illegal DTLS-SRTP protection profile %d", + ssl->conf->dtls_srtp_profile_list[protection_profiles_index] + ) ); + return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ); + } + } + + *p++ = mki_len & 0xFF; + + if( mki_len != 0 ) + { + memcpy( p, ssl->dtls_srtp_info.mki_value, mki_len ); + /* + * Increment p to point to the current position. + */ + p += mki_len; + MBEDTLS_SSL_DEBUG_BUF( 3, "sending mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } + + /* + * total extension length: extension type (2 bytes) + * + extension length (2 bytes) + * + protection profile length (2 bytes) + * + 2 * number of protection profiles + * + srtp_mki vector length(1 byte) + * + mki value + */ + *olen = p - buf; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Generate random bytes for ClientHello + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_generate_random( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = ssl->handshake->randbytes; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + + /* + * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie != NULL ) + { + return( 0 ); + } +#endif + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + MBEDTLS_PUT_UINT32_BE( t, p, 0 ); + p += 4; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %" MBEDTLS_PRINTF_LONGLONG, + (long long) t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param suite_info cipher suite to validate + * \param ssl SSL context + * \param min_minor_ver Minimal minor version to accept a cipher suite + * \param max_minor_ver Maximal minor version to accept a cipher suite + * + * \return 0 if valid, else 1 + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_validate_ciphersuite( + const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl, + int min_minor_ver, int max_minor_ver ) +{ + (void) ssl; + if( suite_info == NULL ) + return( 1 ); + + if( suite_info->min_minor_ver > max_minor_ver || + suite_info->max_minor_ver < min_minor_ver ) + return( 1 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 1 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 1 ); +#endif + + /* Don't suggest PSK-based ciphersuite if no PSK is available. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl_conf_has_static_psk( ssl->conf ) == 0 ) + { + return( 1 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, olen, ext_len = 0; + + unsigned char *buf; + unsigned char *p, *q; + const unsigned char *end; + + unsigned char offer_compress; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + int uses_ec = 0; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + ssl->major_ver = ssl->conf->min_major_ver; + ssl->minor_ver = ssl->conf->min_minor_ver; + } + + if( ssl->conf->max_major_ver == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "configured max major version is invalid, consider using mbedtls_ssl_config_defaults()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + buf = ssl->out_msg; + end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN; + + /* + * Check if there's enough space for the first part of the ClientHello + * consisting of the 38 bytes described below, the session identifier (at + * most 32 bytes) and its length (1 byte). + * + * Use static upper bounds instead of the actual values + * to allow the compiler to optimize this away. + */ + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 ); + + /* + * The 38 first bytes of the ClientHello: + * 0 . 0 handshake type (written later) + * 1 . 3 handshake length (written later) + * 4 . 5 highest version supported + * 6 . 9 current UNIX time + * 10 . 37 random bytes + * + * The current UNIX time (4 bytes) and following 28 random bytes are written + * by ssl_generate_random() into ssl->handshake->randbytes buffer and then + * copied from there into the output buffer. + */ + + p = buf + 4; + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", + buf[4], buf[5] ) ); + + if( ( ret = ssl_generate_random( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); + return( ret ); + } + + memcpy( p, ssl->handshake->randbytes, 32 ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); + p += 32; + + /* + * 38 . 38 session id length + * 39 . 39+n session id + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + n = ssl->session_negotiate->id_len; + + if( n < 16 || n > 32 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0 ) + { + n = 0; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + /* + * RFC 5077 section 3.4: "When presenting a ticket, the client MAY + * generate and include a Session ID in the TLS ClientHello." + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ssl->session_negotiate->ticket != NULL && + ssl->session_negotiate->ticket_len != 0 ) + { + ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->session_negotiate->id, 32 ); + + if( ret != 0 ) + return( ret ); + + ssl->session_negotiate->id_len = n = 32; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + /* + * The first check of the output buffer size above ( + * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );) + * has checked that there is enough space in the output buffer for the + * session identifier length byte and the session identifier (n <= 32). + */ + *p++ = (unsigned char) n; + + for( i = 0; i < n; i++ ) + *p++ = ssl->session_negotiate->id[i]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); + + /* + * With 'n' being the length of the session identifier + * + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + + /* + * DTLS cookie + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); + + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); + *p++ = 0; + } + else + { + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + + *p++ = ssl->handshake->verify_cookie_len; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, + ssl->handshake->verify_cookie_len ); + memcpy( p, ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + p += ssl->handshake->verify_cookie_len; + } + } +#endif + + /* + * Ciphersuite list + */ + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + + /* Skip writing ciphersuite length for now */ + n = 0; + q = p; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p += 2; + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ssl_validate_ciphersuite( ciphersuite_info, ssl, + ssl->conf->min_minor_ver, + ssl->conf->max_minor_ver ) != 0 ) + continue; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %#04x (%s)", + (unsigned int)ciphersuites[i], ciphersuite_info->name ) ); + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); +#endif + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + + n++; + MBEDTLS_PUT_UINT16_BE( ciphersuites[i], p, 0 ); + p += 2; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, got %" MBEDTLS_PRINTF_SIZET " ciphersuites (excluding SCSVs)", n ) ); + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0 ); + p += 2; + n++; + } + + /* Some versions of OpenSSL don't handle it correctly if not at end */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( MBEDTLS_SSL_FALLBACK_SCSV_VALUE, p, 0 ); + p += 2; + n++; + } +#endif + + *q++ = (unsigned char)( n >> 7 ); + *q++ = (unsigned char)( n << 1 ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + offer_compress = 1; +#else + offer_compress = 0; +#endif + + /* + * We don't support compression with DTLS right now: if many records come + * in the same datagram, uncompressing one could overwrite the next one. + * We don't want to add complexity for handling that case unless there is + * an actual need for it. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + offer_compress = 0; +#endif + + if( offer_compress ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", + MBEDTLS_SSL_COMPRESS_DEFLATE, + MBEDTLS_SSL_COMPRESS_NULL ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 3 ); + *p++ = 2; + *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", + MBEDTLS_SSL_COMPRESS_NULL ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + + /* First write extensions, then the total length */ + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ( ret = ssl_write_hostname_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_hostname_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + + /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added + * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_renegotiation_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( uses_ec ) + { + if( ( ret = ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_elliptic_curves_ext", ret ); + return( ret ); + } + ext_len += olen; + + if( ( ret = ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_point_formats_ext", ret ); + return( ret ); + } + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ( ret = ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_ecjpake_kkpp_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( ( ret = ssl_write_cid_ext( ssl, p + 2 + ext_len, end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_cid_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_max_fragment_length_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( ( ret = ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_truncated_hmac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ( ret = ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_encrypt_then_mac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ( ret = ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_extended_ms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( ( ret = ssl_write_alpn_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_alpn_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + if( ( ret = ssl_write_use_srtp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_use_srtp_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_session_ticket_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + + /* olen unused if all extensions are disabled */ + ((void) olen); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET, + ext_len ) ); + + if( ext_len > 0 ) + { + /* No need to check for space here, because the extension + * writing functions already took care of that. */ + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2 + ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + mbedtls_ct_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + mbedtls_ct_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x00 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->conf->mfl_code ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching truncated HMAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t peer_cid_len; + + if( /* CID extension only makes sense in DTLS */ + ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + /* The server must only send the CID extension if we have offered it. */ + ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension unexpected" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + peer_cid_len = *buf++; + len--; + + if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( len != peer_cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; + ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; + memcpy( ssl->handshake->peer_cid, buf, peer_cid_len ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Server CID", buf, peer_cid_len ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + list_size = buf[0]; + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl->handshake->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + /* If we got here, we no longer need our cached extension */ + mbedtls_free( ssl->handshake->ecjpake_cache ); + ssl->handshake->ecjpake_cache = NULL; + ssl->handshake->ecjpake_cache_len = 0; + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, name_len; + const char **p; + + /* If we didn't send it, the server shouldn't send it */ + if( ssl->conf->alpn_list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + name_len = buf[2]; + if( name_len != list_len - 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->conf->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET; + size_t i, mki_len = 0; + uint16_t server_protection_profile_value = 0; + + /* If use_srtp is not configured, just ignore the extension */ + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + return( 0 ); + + /* RFC 5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + * + */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + + /* + * Length is 5 + optional mki_value : one protection profile length (2 bytes) + * + protection profile (2 bytes) + * + mki_len(1 byte) + * and optional srtp_mki + */ + if( ( len < 5 ) || ( len != ( buf[4] + 5u ) ) ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + + /* + * get the server protection profile + */ + + /* + * protection profile length must be 0x0002 as we must have only + * one protection profile in server Hello + */ + if( ( buf[0] != 0 ) || ( buf[1] != 2 ) ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + + server_protection_profile_value = ( buf[2] << 8 ) | buf[3]; + server_protection = mbedtls_ssl_check_srtp_profile_value( + server_protection_profile_value ); + if( server_protection != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + server_protection ) ) ); + } + + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; + + /* + * Check we have the server profile in our list + */ + for( i=0; i < ssl->conf->dtls_srtp_profile_list_len; i++) + { + if( server_protection == ssl->conf->dtls_srtp_profile_list[i] ) + { + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + server_protection ) ) ); + break; + } + } + + /* If no match was found : server problem, it shall never answer with incompatible profile */ + if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* If server does not use mki in its reply, make sure the client won't keep + * one as negotiated */ + if( len == 5 ) + { + ssl->dtls_srtp_info.mki_len = 0; + } + + /* + * RFC5764: + * If the client detects a nonzero-length MKI in the server's response + * that is different than the one the client offered, then the client + * MUST abort the handshake and SHOULD send an invalid_parameter alert. + */ + if( len > 5 && ( buf[4] != mki_len || + ( memcmp( ssl->dtls_srtp_info.mki_value, &buf[5], mki_len ) ) ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } +#if defined (MBEDTLS_DEBUG_C) + if( len > 5 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "received mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } +#endif + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Parse HelloVerifyRequest. Only called after verifying the HS type. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + int major_ver, minor_ver; + unsigned char cookie_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + + /* Check that there is enough room for: + * - 2 bytes of version + * - 1 byte of cookie_len + */ + if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "incoming HelloVerifyRequest message is too short" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); + p += 2; + + /* + * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) + * even is lower than our min version. + */ + if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || + major_ver > ssl->conf->max_major_ver || + minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + cookie_len = *p++; + if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "cookie length does not match incoming message size" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); + + mbedtls_free( ssl->handshake->verify_cookie ); + + ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->verify_cookie, p, cookie_len ); + ssl->handshake->verify_cookie_len = cookie_len; + + /* Start over at ClientHello */ + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_reset_checksum( ssl ); + + mbedtls_ssl_recv_flight_completed( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret, i; + size_t n; + size_t ext_len; + unsigned char *buf, *ext; + unsigned char comp; +#if defined(MBEDTLS_ZLIB_SUPPORT) + int accept_comp; +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const mbedtls_ssl_ciphersuite_t *suite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + buf = ssl->in_msg; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_records_seen++; + + if( ssl->conf->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation requested, but not honored by server" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-handshake message during renegotiation" ) ); + + ssl->keep_current_message = 1; + return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + return( ssl_parse_hello_verify_request( ssl ) ); + } + else + { + /* We made it through the verification process */ + mbedtls_free( ssl->handshake->verify_cookie ); + ssl->handshake->verify_cookie = NULL; + ssl->handshake->verify_cookie_len = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || + buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* + * 0 . 1 server_version + * 2 . 33 random (maybe including 4 bytes of Unix time) + * 34 . 34 session_id length = n + * 35 . 34+n session_id + * 35+n . 36+n cipher_suite + * 37+n . 37+n compression_method + * + * 38+n . 39+n extensions length (optional) + * 40+n . .. extensions + */ + buf += mbedtls_ssl_hs_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf + 0 ); + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver || + ssl->major_ver > ssl->conf->max_major_ver || + ssl->minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server version out of bounds - min: [%d:%d], server: [%d:%d], max: [%d:%d]", + ssl->conf->min_major_ver, + ssl->conf->min_minor_ver, + ssl->major_ver, ssl->minor_ver, + ssl->conf->max_major_ver, + ssl->conf->max_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", + ( (unsigned long) buf[2] << 24 ) | + ( (unsigned long) buf[3] << 16 ) | + ( (unsigned long) buf[4] << 8 ) | + ( (unsigned long) buf[5] ) ) ); + + memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); + + n = buf[34]; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); + + if( n > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) + { + ext_len = ( ( buf[38 + n] << 8 ) + | ( buf[39 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) + { + ext_len = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + /* ciphersuite (used later) */ + i = ( buf[35 + n] << 8 ) | buf[36 + n]; + + /* + * Read and check compression + */ + comp = buf[37 + n]; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + accept_comp = 0; + else +#endif + accept_comp = 1; + + if( comp != MBEDTLS_SSL_COMPRESS_NULL && + ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) +#else /* MBEDTLS_ZLIB_SUPPORT */ + if( comp != MBEDTLS_SSL_COMPRESS_NULL ) +#endif/* MBEDTLS_ZLIB_SUPPORT */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * Initialize update checksum functions + */ + ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); + if( ssl->handshake->ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "ciphersuite info for %04x not found", (unsigned int)i ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->handshake->resume == 0 || n == 0 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->id_len != n || + memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->id_len = n; + memcpy( ssl->session_negotiate->id, buf + 35, n ); + } + else + { + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", (unsigned) i ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", + buf[37 + n] ) ); + + /* + * Perform cipher suite validation in same way as in ssl_write_client_hello. + */ + i = 0; + while( 1 ) + { + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + suite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, + ssl->minor_ver ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ecrs_enabled = 1; + } +#endif + + if( comp != MBEDTLS_SSL_COMPRESS_NULL +#if defined(MBEDTLS_ZLIB_SUPPORT) + && comp != MBEDTLS_SSL_COMPRESS_DEFLATE +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 40 + n; + + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len ) ); + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + switch( ext_id ) + { + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, + ext_size ) ) != 0 ) + return( ret ); + + break; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found max_fragment_length extension" ) ); + + if( ( ret = ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); + + if( ( ret = ssl_parse_truncated_hmac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + case MBEDTLS_TLS_EXT_CID: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) ); + + if( ( ret = ssl_parse_cid_ext( ssl, + ext + 4, + ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); + + if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found extended_master_secret extension" ) ); + + if( ( ret = ssl_parse_extended_ms_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); + + if( ( ret = ssl_parse_session_ticket_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found supported_point_formats extension" ) ); + + if( ( ret = ssl_parse_supported_point_formats_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); + + if( ( ret = ssl_parse_ecjpake_kkpp( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + case MBEDTLS_TLS_EXT_USE_SRTP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) ); + + if( ( ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "unknown extension found: %u (ignoring)", ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + } + + /* + * mbedtls_ssl_derive_keys() has to be called after the parsing of the + * extensions. It sets the transform data for the resumed session which in + * case of DTLS includes the server CID extracted from the CID extension. + */ + if( ssl->handshake->resume ) + { + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( ret ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t dhm_actual_bitlen; + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, + p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); + return( ret ); + } + + dhm_actual_bitlen = mbedtls_mpi_bitlen( &ssl->handshake->dhm_ctx.P ); + if( dhm_actual_bitlen < ssl->conf->dhm_min_bitlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u", + dhm_actual_bitlen, + ssl->conf->dhm_min_bitlen ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif + + curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + uint16_t tls_id; + size_t ecdh_bits = 0; + uint8_t ecpoint_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* + * Parse ECC group + */ + + if( end - *p < 4 ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* First byte is curve_type; only named_curve is handled */ + if( *(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* Next two bytes are the namedcurve value */ + tls_id = *(*p)++; + tls_id <<= 8; + tls_id |= *(*p)++; + + /* Check it's a curve we offered */ + if( mbedtls_ssl_check_curve_tls_id( ssl, tls_id ) != 0 ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* Convert EC group to PSA key type. */ + if( ( handshake->ecdh_psa_type = + mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + if( ecdh_bits > 0xffff ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + handshake->ecdh_bits = (uint16_t) ecdh_bits; + + /* + * Put peer's ECDH public key in the format understood by PSA. + */ + + ecpoint_len = *(*p)++; + if( (size_t)( end - *p ) < ecpoint_len ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + if( mbedtls_psa_tls_ecpoint_to_psa_ec( + *p, ecpoint_len, + handshake->ecdh_psa_peerkey, + sizeof( handshake->ecdh_psa_peerkey ), + &handshake->ecdh_psa_peerkey_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + *p += ecpoint_len; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (ECDHE curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + uint16_t len; + ((void) ssl); + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + if( end - (*p) < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + len = (*p)[0] << 8 | (*p)[1]; + *p += 2; + + if( end - (*p) < len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Note: we currently ignore the PKS identity hint, as we only allow one + * PSK to be provisionned on the client. This could be changed later if + * someone needs that feature. + */ + *p += len; + ret = 0; + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + mbedtls_pk_context * peer_pk; + + if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * Now write it out, encrypted + */ + if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_encrypt( peer_pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + MBEDTLS_PUT_UINT16_BE( *olen, ssl->out_msg, offset ); + *olen += 2; + } +#endif + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end, + mbedtls_md_type_t *md_alg, + mbedtls_pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = MBEDTLS_MD_NONE; + *pk_alg = MBEDTLS_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) + == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "Server used unsupported HashAlgorithm %d", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + /* + * Check if the hash is acceptable + */ + if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used HashAlgorithm %d that was not offered", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", + (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", + (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ecp_keypair *peer_key; + mbedtls_pk_context * peer_pk; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* This is a public key, so it can't be opaque, so can_do() is a good + * enough check to ensure pk_ec() is safe to use below. */ + if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + peer_key = mbedtls_pk_ec( *peer_pk ); + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, + MBEDTLS_ECDH_THEIRS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it, + * so that more RAM is available for upcoming expensive + * operations like ECDHE. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + unsigned char *p = NULL, *end = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) + { + goto start_processing; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server + * doesn't use a psk_identity_hint + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* Current message is probably either + * CertificateRequest or ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server key exchange message must not be skipped" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; + +start_processing: +#endif + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } /* FALLTHROUGH */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params_psa( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t sig_len, hashlen; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char hash[PSA_HASH_MAX_SIZE]; +#else + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; +#endif + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + size_t params_len = p - params; + void *rs_ctx = NULL; + + mbedtls_pk_context * peer_pk; + + /* + * Handle the digitally-signed structure + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + if( pk_alg != + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + + /* Default hash for ECDSA is SHA-1 */ + if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + + if( p > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( p != end - sig_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, params, + params_len ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + params, params_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * Verify signature + */ + if( !mbedtls_pk_can_do( peer_pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_verify_restartable( peer_pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it, + * so that more RAM is available for upcoming expensive + * operations like ECDHE. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + +exit: + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t n = 0; + size_t cert_type_len = 0, dn_len = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->state++; + ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", + ssl->client_auth ? "a" : "no" ) ); + + if( ssl->client_auth == 0 ) + { + /* Current message is probably the ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + /* + * struct { + * ClientCertificateType certificate_types<1..2^8-1>; + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only + * DistinguishedName certificate_authorities<0..2^16-1>; + * } CertificateRequest; + * + * Since we only support a single certificate on clients, let's just + * ignore all the information that's supposed to help us pick a + * certificate. + * + * We could check that our certificate matches the request, and bail out + * if it doesn't, but it's simpler to just send the certificate anyway, + * and give the server the opportunity to decide if it should terminate + * the connection when it doesn't like our certificate. + * + * Same goes for the hash in TLS 1.2's signature_algorithms: at this + * point we only have one hash available (see comments in + * write_certificate_verify), so let's just use what we have. + * + * However, we still minimally parse the message to check it is at least + * superficially sane. + */ + buf = ssl->in_msg; + + /* certificate_types */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; + n = cert_type_len; + + /* + * In the subsequent code there are two paths that read from buf: + * * the length of the signature algorithms field (if minor version of + * SSL is 3), + * * distinguished name length otherwise. + * Both reach at most the index: + * ...hdr_len + 2 + n, + * therefore the buffer length at this point must be greater than that + * regardless of the actual code path. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + + /* supported_signature_algorithms */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + size_t sig_alg_len = + ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); +#if defined(MBEDTLS_DEBUG_C) + unsigned char* sig_alg; + size_t i; +#endif + + /* + * The furthest access in buf is in the loop few lines below: + * sig_alg[i + 1], + * where: + * sig_alg = buf + ...hdr_len + 3 + n, + * max(i) = sig_alg_len - 1. + * Therefore the furthest access is: + * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], + * which reduces to: + * buf[...hdr_len + 3 + n + sig_alg_len], + * which is one less than we need the buf to be. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + + 3 + n + sig_alg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +#if defined(MBEDTLS_DEBUG_C) + sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + for( i = 0; i < sig_alg_len; i += 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "Supported Signature Algorithm found: %d,%d", + sig_alg[i], sig_alg[i + 1] ) ); + } +#endif + + n += 2 + sig_alg_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* certificate_authorities */ + dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); + + n += dn_len; + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); + } + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || + ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + size_t header_len; + size_t content_len; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + /* + * DHM key exchange -- send G^X mod P + */ + content_len = ssl->handshake->dhm_ctx.len; + + MBEDTLS_PUT_UINT16_BE( content_len, ssl->out_msg, 4 ); + header_len = 6; + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[header_len], content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t key_attributes; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + unsigned char own_pubkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t own_pubkey_len; + unsigned char *own_pubkey_ecpoint; + size_t own_pubkey_ecpoint_len; + + header_len = 4; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based ECDH computation." ) ); + + /* + * Generate EC private key for ECDHE exchange. + */ + + /* The master secret is obtained from the shared ECDH secret by + * applying the TLS 1.2 PRF with a specific salt and label. While + * the PSA Crypto API encourages combining key agreement schemes + * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not + * yet support the provisioning of salt + label to the KDF. + * For the time being, we therefore need to split the computation + * of the ECDH secret and the application of the TLS 1.2 PRF. */ + key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &key_attributes, PSA_ALG_ECDH ); + psa_set_key_type( &key_attributes, handshake->ecdh_psa_type ); + psa_set_key_bits( &key_attributes, handshake->ecdh_bits ); + + /* Generate ECDH private key. */ + status = psa_generate_key( &key_attributes, + &handshake->ecdh_psa_privkey ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + /* Export the public part of the ECDH private key from PSA + * and convert it to ECPoint format used in ClientKeyExchange. */ + status = psa_export_public_key( handshake->ecdh_psa_privkey, + own_pubkey, sizeof( own_pubkey ), + &own_pubkey_len ); + if( status != PSA_SUCCESS ) + { + psa_destroy_key( handshake->ecdh_psa_privkey ); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( mbedtls_psa_tls_psa_ec_to_ecpoint( own_pubkey, + own_pubkey_len, + &own_pubkey_ecpoint, + &own_pubkey_ecpoint_len ) != 0 ) + { + psa_destroy_key( handshake->ecdh_psa_privkey ); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + /* Copy ECPoint structure to outgoing message buffer. */ + ssl->out_msg[header_len] = (unsigned char) own_pubkey_ecpoint_len; + memcpy( ssl->out_msg + header_len + 1, + own_pubkey_ecpoint, own_pubkey_ecpoint_len ); + content_len = own_pubkey_ecpoint_len + 1; + + /* The ECDH secret is the premaster secret used for key derivation. */ + + /* Compute ECDH shared secret. */ + status = psa_raw_key_agreement( PSA_ALG_ECDH, + handshake->ecdh_psa_privkey, + handshake->ecdh_psa_peerkey, + handshake->ecdh_psa_peerkey_len, + ssl->handshake->premaster, + sizeof( ssl->handshake->premaster ), + &ssl->handshake->pmslen ); + + destruction_status = psa_destroy_key( handshake->ecdh_psa_privkey ); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + + if( status != PSA_SUCCESS || destruction_status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + header_len = 4; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + { + if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) + goto ecdh_calc_secret; + + mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + } +#endif + + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &content_len, + &ssl->out_msg[header_len], 1000, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + { + ssl->handshake->ecrs_n = content_len; + ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; + } + +ecdh_calc_secret: + if( ssl->handshake->ecrs_enabled ) + content_len = ssl->handshake->ecrs_n; +#endif + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl_conf_has_static_psk( ssl->conf ) == 0 ) + { + /* We don't offer PSK suites if we don't have a PSK, + * and we check that the server's choice is among the + * ciphersuites we offered, so this should never happen. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + header_len = 4; + content_len = ssl->conf->psk_identity_len; + + if( header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity too long or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[header_len++] = MBEDTLS_BYTE_1( content_len ); + ssl->out_msg[header_len++] = MBEDTLS_BYTE_0( content_len ); + + memcpy( ssl->out_msg + header_len, + ssl->conf->psk_identity, + ssl->conf->psk_identity_len ); + header_len += ssl->conf->psk_identity_len; + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + content_len = 0; + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = ssl_write_encrypted_pms( ssl, header_len, + &content_len, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + content_len = ssl->handshake->dhm_ctx.len; + + if( header_len + 2 + content_len > + MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity or DHM size too long or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[header_len++] = MBEDTLS_BYTE_1( content_len ); + ssl->out_msg[header_len++] = MBEDTLS_BYTE_0( content_len ); + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + &ssl->out_msg[header_len], content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * ClientECDiffieHellmanPublic public; + */ + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &content_len, + &ssl->out_msg[header_len], + MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "skip PMS generation for opaque PSK" ) ); + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + header_len = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, header_len, + &content_len, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + header_len = 4; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + ssl->out_msg + header_len, + MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, + &content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen = header_len + content_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + size_t n = 0, offset = 0; + unsigned char hash[48]; + unsigned char *hash_start = hash; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + size_t hashlen; + void *rs_ctx = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) + { + goto sign; + } +#endif + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make a signature of the handshake digests + */ +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; + +sign: +#endif + + ssl->handshake->calc_verify( ssl, hash, &hashlen ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(handshake_messages); + * + * sha_hash + * SHA(handshake_messages); + */ + md_alg = MBEDTLS_MD_NONE; + + /* + * For ECDSA, default hash is SHA-1 only + */ + if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and + * SHA224 in order to satisfy 'weird' needs from the server + * side. + */ + if( ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + md_alg = MBEDTLS_MD_SHA384; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; + } + else + { + md_alg = MBEDTLS_MD_SHA256; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; + } + ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), + md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, &n, + ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_PUT_UINT16_BE( n, ssl->out_msg, offset + 4 ); + + ssl->out_msglen = 6 + n + offset; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + const unsigned char *msg; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 3 ticket_lifetime_hint + * 4 . 5 ticket_len (n) + * 6 . 5+n ticket content + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + + lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); + + ticket_len = ( msg[4] << 8 ) | ( msg[5] ); + + if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len ) ); + + /* We're not waiting for a NewSessionTicket message any more */ + ssl->handshake->new_session_ticket = 0; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + /* + * Zero-length ticket means the server changed his mind and doesn't want + * to send a ticket after all, so just forget it + */ + if( ticket_len == 0 ) + return( 0 ); + + if( ssl->session != NULL && ssl->session->ticket != NULL ) + { + mbedtls_platform_zeroize( ssl->session->ticket, + ssl->session->ticket_len ); + mbedtls_free( ssl->session->ticket ); + ssl->session->ticket = NULL; + ssl->session->ticket_len = 0; + } + + mbedtls_platform_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + mbedtls_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ticket, msg + 6, ticket_len ); + + ssl->session_negotiate->ticket = ticket; + ssl->session_negotiate->ticket_len = ticket_len; + ssl->session_negotiate->ticket_lifetime = lifetime; + + /* + * RFC 5077 section 3.4: + * "If the client receives a session ticket from the server, then it + * discards any Session ID that was sent in the ServerHello." + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->id_len = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Change state now, so that it is right in mbedtls_ssl_read_record(), used + * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && + ssl->handshake->new_session_ticket != 0 ) + { + ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: + ret = ssl_parse_new_session_ticket( ssl ); + break; +#endif + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c new file mode 100644 index 0000000..3781796 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_cookie.c @@ -0,0 +1,258 @@ +/* + * DTLS cookie callbacks implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/constant_time.h" + +#include + +/* + * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is + * available. Try SHA-256 first, 512 wastes resources since we need to stay + * with max 32 bytes of cookie for DTLS 1.0 + */ +#if defined(MBEDTLS_SHA256_C) +#define COOKIE_MD MBEDTLS_MD_SHA224 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA512_C) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA1_C) +#define COOKIE_MD MBEDTLS_MD_SHA1 +#define COOKIE_MD_OUTLEN 20 +#define COOKIE_HMAC_LEN 20 +#else +#error "DTLS hello verify needs SHA-1 or SHA-2" +#endif + +/* + * Cookies are formed of a 4-bytes timestamp (or serial number) and + * an HMAC of timestamp and client ID. + */ +#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) + +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_init( &ctx->hmac_ctx ); +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) +{ + ctx->timeout = delay; +} + +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_free( &ctx->hmac_ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); +} + +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char key[COOKIE_MD_OUTLEN]; + + if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) + return( ret ); + + ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); + if( ret != 0 ) + return( ret ); + + mbedtls_platform_zeroize( key, sizeof( key ) ); + + return( 0 ); +} + +/* + * Generate the HMAC part of a cookie + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, + const unsigned char time[4], + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char hmac_out[COOKIE_MD_OUTLEN]; + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN ); + + if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || + mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); + *p += COOKIE_HMAC_LEN; + + return( 0 ); +} + +/* + * Generate cookie for DTLS ClientHello verification + */ +int mbedtls_ssl_cookie_write( void *p_ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long t; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN ); + +#if defined(MBEDTLS_HAVE_TIME) + t = (unsigned long) mbedtls_time( NULL ); +#else + t = ctx->serial++; +#endif + + MBEDTLS_PUT_UINT32_BE(t, *p, 0); + *p += 4; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) ); +#endif + + ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, + p, end, cli_id, cli_id_len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, + MBEDTLS_ERR_THREADING_MUTEX_ERROR ) ); +#endif + + return( ret ); +} + +/* + * Check a cookie + */ +int mbedtls_ssl_cookie_check( void *p_ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char ref_hmac[COOKIE_HMAC_LEN]; + int ret = 0; + unsigned char *p = ref_hmac; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long cur_time, cookie_time; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cookie_len != COOKIE_LEN ) + return( -1 ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) ); +#endif + + if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, + &p, p + sizeof( ref_hmac ), + cli_id, cli_id_len ) != 0 ) + ret = -1; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + } +#endif + + if( ret != 0 ) + goto exit; + + if( mbedtls_ct_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) + { + ret = -1; + goto exit; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur_time = (unsigned long) mbedtls_time( NULL ); +#else + cur_time = ctx->serial; +#endif + + cookie_time = ( (unsigned long) cookie[0] << 24 ) | + ( (unsigned long) cookie[1] << 16 ) | + ( (unsigned long) cookie[2] << 8 ) | + ( (unsigned long) cookie[3] ); + + if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) + { + ret = -1; + goto exit; + } + +exit: + mbedtls_platform_zeroize( ref_hmac, sizeof( ref_hmac ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c new file mode 100644 index 0000000..e47c538 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_msg.c @@ -0,0 +1,5991 @@ +/* + * Generic SSL/TLS messaging layer functions + * (record layer + retransmission state machine) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/version.h" +#include "constant_time_internal.h" +#include "mbedtls/constant_time.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); + +/* + * Start a timer. + * Passing millisecs = 0 cancels a running timer. + */ +void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) +{ + if( ssl->f_set_timer == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); + ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); +} + +/* + * Return -1 is timer is expired, 0 if it isn't. + */ +int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ) +{ + if( ssl->f_get_timer == NULL ) + return( 0 ); + + if( ssl->f_get_timer( ssl->p_timer ) == 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); + return( -1 ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_RECORD_CHECKING) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t len, + mbedtls_record *rec ); + +int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t buflen ) +{ + int ret = 0; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen ); + + /* We don't support record checking in TLS because + * (a) there doesn't seem to be a usecase for it, and + * (b) In SSLv3 and TLS 1.0, CBC record decryption has state + * and we'd need to backup the transform here. + */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + goto exit; + } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + else + { + mbedtls_record rec; + + ret = ssl_parse_record_header( ssl, buf, buflen, &rec ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret ); + goto exit; + } + + if( ssl->transform_in != NULL ) + { + ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret ); + goto exit; + } + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +exit: + /* On success, we have decrypted the buffer in-place, so make + * sure we don't leak any plaintext data. */ + mbedtls_platform_zeroize( buf, buflen ); + + /* For the purpose of this API, treat messages with unexpected CID + * as well as such from future epochs as unexpected. */ + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID || + ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_RECORD_CHECKING */ + +#define SSL_DONT_FORCE_FLUSH 0 +#define SSL_FORCE_FLUSH 1 + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/* Forward declarations for functions related to message buffering. */ +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ); +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_buffer_message( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, + mbedtls_record const *rec ); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); + +static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) +{ + size_t mtu = mbedtls_ssl_get_current_mtu( ssl ); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + if( mtu != 0 && mtu < out_buf_len ) + return( mtu ); + + return( out_buf_len ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) +{ + size_t const bytes_written = ssl->out_left; + size_t const mtu = ssl_get_maximum_datagram_size( ssl ); + + /* Double-check that the write-index hasn't gone + * past what we can transmit in a single datagram. */ + if( bytes_written > mtu ) + { + /* Should never happen... */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int) ( mtu - bytes_written ) ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t remaining, expansion; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; + + /* By the standard (RFC 6066 Sect. 4), the MFL extension + * only limits the maximum record payload size, so in theory + * we would be allowed to pack multiple records of payload size + * MFL into a single datagram. However, this would mean that there's + * no way to explicitly communicate MTU restrictions to the peer. + * + * The following reduction of max_len makes sure that we never + * write datagrams larger than MFL + Record Expansion Overhead. + */ + if( max_len <= ssl->out_left ) + return( 0 ); + + max_len -= ssl->out_left; +#endif + + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + remaining = (size_t) ret; + + ret = mbedtls_ssl_get_record_expansion( ssl ); + if( ret < 0 ) + return( ret ); + expansion = (size_t) ret; + + if( remaining <= expansion ) + return( 0 ); + + remaining -= expansion; + if( remaining >= max_len ) + remaining = max_len; + + return( (int) remaining ); +} + +/* + * Double the retransmit timeout value, within the allowed range, + * returning -1 if the maximum value has already been reached. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + uint32_t new_timeout; + + if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) + return( -1 ); + + /* Implement the final paragraph of RFC 6347 section 4.1.1.1 + * in the following way: after the initial transmission and a first + * retransmission, back off to a temporary estimated MTU of 508 bytes. + * This value is guaranteed to be deliverable (if not guaranteed to be + * delivered) of any compliant IPv4 (and IPv6) network, and should work + * on most non-IP stacks too. */ + if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) + { + ssl->handshake->mtu = 508; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); + } + + new_timeout = 2 * ssl->handshake->retransmit_timeout; + + /* Avoid arithmetic overflow and range overflow */ + if( new_timeout < ssl->handshake->retransmit_timeout || + new_timeout > ssl->conf->hs_timeout_max ) + { + new_timeout = ssl->conf->hs_timeout_max; + } + + ssl->handshake->retransmit_timeout = new_timeout; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs", + (unsigned long) ssl->handshake->retransmit_timeout ) ); + + return( 0 ); +} + +static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs", + (unsigned long) ssl->handshake->retransmit_timeout ) ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) +int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, + const unsigned char *key_enc, const unsigned char *key_dec, + size_t keylen, + const unsigned char *iv_enc, const unsigned char *iv_dec, + size_t ivlen, + const unsigned char *mac_enc, const unsigned char *mac_dec, + size_t maclen ) = NULL; +int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; +int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; +int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +/* + * Encryption/decryption functions + */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + +static size_t ssl_compute_padding_length( size_t len, + size_t granularity ) +{ + return( ( granularity - ( len + 1 ) % granularity ) % granularity ); +} + +/* This functions transforms a (D)TLS plaintext fragment and a record content + * type into an instance of the (D)TLSInnerPlaintext structure. This is used + * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect + * a record's content type. + * + * struct { + * opaque content[DTLSPlaintext.length]; + * ContentType real_type; + * uint8 zeros[length_of_padding]; + * } (D)TLSInnerPlaintext; + * + * Input: + * - `content`: The beginning of the buffer holding the + * plaintext to be wrapped. + * - `*content_size`: The length of the plaintext in Bytes. + * - `max_len`: The number of Bytes available starting from + * `content`. This must be `>= *content_size`. + * - `rec_type`: The desired record content type. + * + * Output: + * - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure. + * - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure. + * + * Returns: + * - `0` on success. + * - A negative error code if `max_len` didn't offer enough space + * for the expansion. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_build_inner_plaintext( unsigned char *content, + size_t *content_size, + size_t remaining, + uint8_t rec_type, + size_t pad ) +{ + size_t len = *content_size; + + /* Write real content type */ + if( remaining == 0 ) + return( -1 ); + content[ len ] = rec_type; + len++; + remaining--; + + if( remaining < pad ) + return( -1 ); + memset( content + len, 0, pad ); + len += pad; + remaining -= pad; + + *content_size = len; + return( 0 ); +} + +/* This function parses a (D)TLSInnerPlaintext structure. + * See ssl_build_inner_plaintext() for details. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_inner_plaintext( unsigned char const *content, + size_t *content_size, + uint8_t *rec_type ) +{ + size_t remaining = *content_size; + + /* Determine length of padding by skipping zeroes from the back. */ + do + { + if( remaining == 0 ) + return( -1 ); + remaining--; + } while( content[ remaining ] == 0 ); + + *content_size = remaining; + *rec_type = content[ remaining ]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || + MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + +/* `add_data` must have size 13 Bytes if the CID extension is disabled, + * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */ +static void ssl_extract_add_data_from_record( unsigned char* add_data, + size_t *add_data_len, + mbedtls_record *rec, + unsigned minor_ver ) +{ + /* Quoting RFC 5246 (TLS 1.2): + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; + * + * For the CID extension, this is extended as follows + * (quoting draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05): + * + * additional_data = seq_num + DTLSPlaintext.type + + * DTLSPlaintext.version + + * cid + + * cid_length + + * length_of_DTLSInnerPlaintext; + * + * For TLS 1.3, the record sequence number is dropped from the AAD + * and encoded within the nonce of the AEAD operation instead. + */ + + unsigned char *cur = add_data; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + if( minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 ) +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + { + ((void) minor_ver); + memcpy( cur, rec->ctr, sizeof( rec->ctr ) ); + cur += sizeof( rec->ctr ); + } + + *cur = rec->type; + cur++; + + memcpy( cur, rec->ver, sizeof( rec->ver ) ); + cur += sizeof( rec->ver ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( rec->cid_len != 0 ) + { + memcpy( cur, rec->cid, rec->cid_len ); + cur += rec->cid_len; + + *cur = rec->cid_len; + cur++; + + MBEDTLS_PUT_UINT16_BE( rec->data_len, cur, 0 ); + cur += 2; + } + else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + MBEDTLS_PUT_UINT16_BE( rec->data_len, cur, 0 ); + cur += 2; + } + + *add_data_len = cur - add_data; +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + +#define SSL3_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */ + +/* + * SSLv3.0 MAC functions + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_mac( mbedtls_md_context_t *md_ctx, + const unsigned char *secret, + const unsigned char *buf, size_t len, + const unsigned char *ctr, int type, + unsigned char out[SSL3_MAC_MAX_BYTES] ) +{ + unsigned char header[11]; + unsigned char padding[48]; + int padlen; + int md_size = mbedtls_md_get_size( md_ctx->md_info ); + int md_type = mbedtls_md_get_type( md_ctx->md_info ); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Only MD5 and SHA-1 supported */ + if( md_type == MBEDTLS_MD_MD5 ) + padlen = 48; + else + padlen = 40; + + memcpy( header, ctr, 8 ); + header[8] = (unsigned char) type; + MBEDTLS_PUT_UINT16_BE( len, header, 9); + + memset( padding, 0x36, padlen ); + ret = mbedtls_md_starts( md_ctx ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_update( md_ctx, secret, md_size ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_update( md_ctx, padding, padlen ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_update( md_ctx, header, 11 ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_update( md_ctx, buf, len ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_finish( md_ctx, out ); + if( ret != 0 ) + return( ret ); + + memset( padding, 0x5C, padlen ); + ret = mbedtls_md_starts( md_ctx ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_update( md_ctx, secret, md_size ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_update( md_ctx, padding, padlen ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_update( md_ctx, out, md_size ); + if( ret != 0 ) + return( ret ); + ret = mbedtls_md_finish( md_ctx, out ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_transform_aead_dynamic_iv_is_explicit( + mbedtls_ssl_transform const *transform ) +{ + return( transform->ivlen != transform->fixed_ivlen ); +} + +/* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV ) + * + * Concretely, this occurs in two variants: + * + * a) Fixed and dynamic IV lengths add up to total IV length, giving + * IV = fixed_iv || dynamic_iv + * + * This variant is used in TLS 1.2 when used with GCM or CCM. + * + * b) Fixed IV lengths matches total IV length, giving + * IV = fixed_iv XOR ( 0 || dynamic_iv ) + * + * This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly. + * + * See also the documentation of mbedtls_ssl_transform. + * + * This function has the precondition that + * + * dst_iv_len >= max( fixed_iv_len, dynamic_iv_len ) + * + * which has to be ensured by the caller. If this precondition + * violated, the behavior of this function is undefined. + */ +static void ssl_build_record_nonce( unsigned char *dst_iv, + size_t dst_iv_len, + unsigned char const *fixed_iv, + size_t fixed_iv_len, + unsigned char const *dynamic_iv, + size_t dynamic_iv_len ) +{ + size_t i; + + /* Start with Fixed IV || 0 */ + memset( dst_iv, 0, dst_iv_len ); + memcpy( dst_iv, fixed_iv, fixed_iv_len ); + + dst_iv += dst_iv_len - dynamic_iv_len; + for( i = 0; i < dynamic_iv_len; i++ ) + dst_iv[i] ^= dynamic_iv[i]; +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ + +int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; + unsigned char * data; + unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ]; + size_t add_data_len; + size_t post_avail; + + /* The SSL context is only used for debugging purposes! */ +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + /* The PRNG is used for dynamic IV generation that's used + * for CBC transformations in TLS 1.1 and TLS 1.2. */ +#if !( defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) ) + ((void) f_rng); + ((void) p_rng); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( transform == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + if( rec == NULL + || rec->buf == NULL + || rec->buf_len < rec->data_offset + || rec->buf_len - rec->data_offset < rec->data_len +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + || rec->cid_len != 0 +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data = rec->buf + rec->data_offset; + post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); + MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", + data, rec->data_len ); + + mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ); + + if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %" MBEDTLS_PRINTF_SIZET + " too large, maximum %" MBEDTLS_PRINTF_SIZET, + rec->data_len, + (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* The following two code paths implement the (D)TLSInnerPlaintext + * structure present in TLS 1.3 and DTLS 1.2 + CID. + * + * See ssl_build_inner_plaintext() for more information. + * + * Note that this changes `rec->data_len`, and hence + * `post_avail` needs to be recalculated afterwards. + * + * Note also that the two code paths cannot occur simultaneously + * since they apply to different versions of the protocol. There + * is hence no risk of double-addition of the inner plaintext. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + size_t padding = + ssl_compute_padding_length( rec->data_len, + MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY ); + if( ssl_build_inner_plaintext( data, + &rec->data_len, + post_avail, + rec->type, + padding ) != 0 ) + { + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* + * Add CID information + */ + rec->cid_len = transform->out_cid_len; + memcpy( rec->cid, transform->out_cid, transform->out_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len ); + + if( rec->cid_len != 0 ) + { + size_t padding = + ssl_compute_padding_length( rec->data_len, + MBEDTLS_SSL_CID_PADDING_GRANULARITY ); + /* + * Wrap plaintext into DTLSInnerPlaintext structure. + * See ssl_build_inner_plaintext() for more information. + * + * Note that this changes `rec->data_len`, and hence + * `post_avail` needs to be recalculated afterwards. + */ + if( ssl_build_inner_plaintext( data, + &rec->data_len, + post_avail, + rec->type, + padding ) != 0 ) + { + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + rec->type = MBEDTLS_SSL_MSG_CID; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); + + /* + * Add MAC before if needed + */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + if( mode == MBEDTLS_MODE_STREAM || + ( mode == MBEDTLS_MODE_CBC +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED +#endif + ) ) + { + if( post_avail < transform->maclen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + unsigned char mac[SSL3_MAC_MAX_BYTES]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ret = ssl_mac( &transform->md_ctx_enc, transform->mac_enc, + data, rec->data_len, rec->ctr, rec->type, mac ); + if( ret == 0 ) + memcpy( data + rec->data_len, mac, transform->maclen ); + mbedtls_platform_zeroize( mac, transform->maclen ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_mac", ret ); + return( ret ); + } + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + + ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, + add_data, add_data_len ); + if( ret != 0 ) + goto hmac_failed_etm_disabled; + ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, + data, rec->data_len ); + if( ret != 0 ) + goto hmac_failed_etm_disabled; + ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); + if( ret != 0 ) + goto hmac_failed_etm_disabled; + ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc ); + if( ret != 0 ) + goto hmac_failed_etm_disabled; + + memcpy( data + rec->data_len, mac, transform->maclen ); + + hmac_failed_etm_disabled: + mbedtls_platform_zeroize( mac, transform->maclen ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_hmac_xxx", ret ); + return( ret ); + } + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len, + transform->maclen ); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " + "including %d bytes of padding", + rec->data_len, 0 ) ); + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, + transform->iv_enc, transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char iv[12]; + unsigned char *dynamic_iv; + size_t dynamic_iv_len; + int dynamic_iv_is_explicit = + ssl_transform_aead_dynamic_iv_is_explicit( transform ); + + /* Check that there's space for the authentication tag. */ + if( post_avail < transform->taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Build nonce for AEAD encryption. + * + * Note: In the case of CCM and GCM in TLS 1.2, the dynamic + * part of the IV is prepended to the ciphertext and + * can be chosen freely - in particular, it need not + * agree with the record sequence number. + * However, since ChaChaPoly as well as all AEAD modes + * in TLS 1.3 use the record sequence number as the + * dynamic part of the nonce, we uniformly use the + * record sequence number here in all cases. + */ + dynamic_iv = rec->ctr; + dynamic_iv_len = sizeof( rec->ctr ); + + ssl_build_record_nonce( iv, sizeof( iv ), + transform->iv_enc, + transform->fixed_ivlen, + dynamic_iv, + dynamic_iv_len ); + + /* + * Build additional data for AEAD encryption. + * This depends on the TLS version. + */ + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", + iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", + dynamic_iv, + dynamic_iv_is_explicit ? dynamic_iv_len : 0 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, add_data_len ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " + "including 0 bytes of padding", + rec->data_len ) ); + + /* + * Encrypt and authenticate + */ + + if( ( ret = mbedtls_cipher_auth_encrypt_ext( &transform->cipher_ctx_enc, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len, /* src */ + data, rec->buf_len - (data - rec->buf), /* dst */ + &rec->data_len, + transform->taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", + data + rec->data_len - transform->taglen, + transform->taglen ); + /* Account for authentication tag. */ + post_avail -= transform->taglen; + + /* + * Prefix record content with dynamic IV in case it is explicit. + */ + if( dynamic_iv_is_explicit != 0 ) + { + if( rec->data_offset < dynamic_iv_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + memcpy( data - dynamic_iv_len, dynamic_iv, dynamic_iv_len ); + rec->data_offset -= dynamic_iv_len; + rec->data_len += dynamic_iv_len; + } + + auth_done++; + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) + if( mode == MBEDTLS_MODE_CBC ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t padlen, i; + size_t olen; + + /* Currently we're always using minimal padding + * (up to 255 bytes would be allowed). */ + padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen; + if( padlen == transform->ivlen ) + padlen = 0; + + /* Check there's enough space in the buffer for the padding. */ + if( post_avail < padlen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + for( i = 0; i <= padlen; i++ ) + data[rec->data_len + i] = (unsigned char) padlen; + + rec->data_len += padlen + 1; + post_avail -= padlen + 1; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.1 and up as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + if( f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( rec->data_offset < transform->ivlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate IV + */ + ret = f_rng( p_rng, transform->iv_enc, transform->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( data - transform->ivlen, transform->iv_enc, + transform->ivlen ); + + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " + "including %" MBEDTLS_PRINTF_SIZET + " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding", + rec->data_len, transform->ivlen, + padlen + 1 ) ); + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, + transform->iv_enc, + transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1 + */ + memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv, + transform->ivlen ); + } + else +#endif + { + data -= transform->ivlen; + rec->data_offset -= transform->ivlen; + rec->data_len += transform->ivlen; + } + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( auth_done == 0 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + /* + * MAC(MAC_write_key, seq_num + + * TLSCipherText.type + + * TLSCipherText.version + + * length_of( (IV +) ENC(...) ) + + * IV + // except for TLS 1.0 + * ENC(content + padding + padding_length)); + */ + + if( post_avail < transform->maclen) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl_extract_add_data_from_record( add_data, &add_data_len, + rec, transform->minor_ver ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, + add_data_len ); + + ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, + add_data_len ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, + data, rec->data_len ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + + memcpy( data + rec->data_len, mac, transform->maclen ); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + + hmac_failed_etm_enabled: + mbedtls_platform_zeroize( mac, transform->maclen ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "HMAC calculation failed", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec ) +{ + size_t olen; + mbedtls_cipher_mode_t mode; + int ret, auth_done = 0; +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + unsigned char* data; + unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ]; + size_t add_data_len; + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + if( rec == NULL || + rec->buf == NULL || + rec->buf_len < rec->data_offset || + rec->buf_len - rec->data_offset < rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data = rec->buf + rec->data_offset; + mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* + * Match record's CID with incoming CID. + */ + if( rec->cid_len != transform->in_cid_len || + memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_UNEXPECTED_CID ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) + if( mode == MBEDTLS_MODE_STREAM ) + { + padlen = 0; + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, + transform->iv_dec, + transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + unsigned char iv[12]; + unsigned char *dynamic_iv; + size_t dynamic_iv_len; + + /* + * Extract dynamic part of nonce for AEAD decryption. + * + * Note: In the case of CCM and GCM in TLS 1.2, the dynamic + * part of the IV is prepended to the ciphertext and + * can be chosen freely - in particular, it need not + * agree with the record sequence number. + */ + dynamic_iv_len = sizeof( rec->ctr ); + if( ssl_transform_aead_dynamic_iv_is_explicit( transform ) == 1 ) + { + if( rec->data_len < dynamic_iv_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ", + rec->data_len, + dynamic_iv_len ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + dynamic_iv = data; + + data += dynamic_iv_len; + rec->data_offset += dynamic_iv_len; + rec->data_len -= dynamic_iv_len; + } + else + { + dynamic_iv = rec->ctr; + } + + /* Check that there's space for the authentication tag. */ + if( rec->data_len < transform->taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ", + rec->data_len, + transform->taglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + rec->data_len -= transform->taglen; + + /* + * Prepare nonce from dynamic and static parts. + */ + ssl_build_record_nonce( iv, sizeof( iv ), + transform->iv_dec, + transform->fixed_ivlen, + dynamic_iv, + dynamic_iv_len ); + + /* + * Build additional data for AEAD encryption. + * This depends on the TLS version. + */ + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, add_data_len ); + + /* Because of the check above, we know that there are + * explicit_iv_len Bytes preceding data, and taglen + * bytes following data + data_len. This justifies + * the debug message and the invocation of + * mbedtls_cipher_auth_decrypt() below. */ + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len, + transform->taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_decrypt_ext( &transform->cipher_ctx_dec, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len + transform->taglen, /* src */ + data, rec->buf_len - (data - rec->buf), &olen, /* dst */ + transform->taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); + + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + /* Double-check that AEAD decryption doesn't change content length. */ + if( olen != rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) + if( mode == MBEDTLS_MODE_CBC ) + { + size_t minlen = 0; + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* The ciphertext is prefixed with the CBC IV. */ + minlen += transform->ivlen; + } +#endif + + /* Size considerations: + * + * - The CBC cipher text must not be empty and hence + * at least of size transform->ivlen. + * + * Together with the potential IV-prefix, this explains + * the first of the two checks below. + * + * - The record must contain a MAC, either in plain or + * encrypted, depending on whether Encrypt-then-MAC + * is used or not. + * - If it is, the message contains the IV-prefix, + * the CBC ciphertext, and the MAC. + * - If it is not, the padded plaintext, and hence + * the CBC ciphertext, has at least length maclen + 1 + * because there is at least the padding length byte. + * + * As the CBC ciphertext is not empty, both cases give the + * lower bound minlen + maclen + 1 on the record size, which + * we test for in the second check below. + */ + if( rec->data_len < minlen + transform->ivlen || + rec->data_len < minlen + transform->maclen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET + "), maclen (%" MBEDTLS_PRINTF_SIZET ") " + "+ 1 ) ( + expl IV )", rec->data_len, + transform->ivlen, + transform->maclen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + /* + * Authenticate before decrypt if enabled + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + /* Update data_len in tandem with add_data. + * + * The subtraction is safe because of the previous check + * data_len >= minlen + maclen + 1. + * + * Afterwards, we know that data + data_len is followed by at + * least maclen Bytes, which justifies the call to + * mbedtls_ct_memcmp() below. + * + * Further, we still know that data_len > minlen */ + rec->data_len -= transform->maclen; + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + + /* Calculate expected MAC. */ + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, + add_data_len ); + ret = mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data, + add_data_len ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_update( &transform->md_ctx_dec, + data, rec->data_len ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_reset( &transform->md_ctx_dec ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, + transform->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, + transform->maclen ); + + /* Compare expected MAC with MAC at the end of the record. */ + if( mbedtls_ct_memcmp( data + rec->data_len, mac_expect, + transform->maclen ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + ret = MBEDTLS_ERR_SSL_INVALID_MAC; + goto hmac_failed_etm_enabled; + } + auth_done++; + + hmac_failed_etm_enabled: + mbedtls_platform_zeroize( mac_expect, transform->maclen ); + if( ret != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_hmac_xxx", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + + /* We know from above that data_len > minlen >= 0, + * so the following check in particular implies that + * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */ + if( rec->data_len % transform->ivlen != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0", + rec->data_len, transform->ivlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.1 and up + */ + if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ + memcpy( transform->iv_dec, data, transform->ivlen ); + + data += transform->ivlen; + rec->data_offset += transform->ivlen; + rec->data_len -= transform->ivlen; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, + transform->iv_dec, transform->ivlen, + data, rec->data_len, data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + /* Double-check that length hasn't changed during decryption. */ + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + { + /* + * Save IV in SSL3 and TLS1, where CBC decryption of consecutive + * records is equivalent to CBC decryption of the concatenation + * of the records; in other words, IVs are maintained across + * record decryptions. + */ + memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv, + transform->ivlen ); + } +#endif + + /* Safe since data_len >= minlen + maclen + 1, so after having + * subtracted at most minlen and maclen up to this point, + * data_len > 0 (because of data_len % ivlen == 0, it's actually + * >= ivlen ). */ + padlen = data[rec->data_len - 1]; + + if( auth_done == 1 ) + { + const size_t mask = mbedtls_ct_size_mask_ge( + rec->data_len, + padlen + 1 ); + correct &= mask; + padlen &= mask; + } + else + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( rec->data_len < transform->maclen + padlen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + ") < maclen (%" MBEDTLS_PRINTF_SIZET + ") + padlen (%" MBEDTLS_PRINTF_SIZET ")", + rec->data_len, + transform->maclen, + padlen + 1 ) ); + } +#endif + + const size_t mask = mbedtls_ct_size_mask_ge( + rec->data_len, + transform->maclen + padlen + 1 ); + correct &= mask; + padlen &= mask; + } + + padlen++; + + /* Regardless of the validity of the padding, + * we have data_len >= padlen here. */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* This is the SSL 3.0 path, we don't have to worry about Lucky + * 13, because there's a strictly worse padding attack built in + * the protocol (known as part of POODLE), so we don't care if the + * code is not constant-time, in particular branches are OK. */ + if( padlen > transform->ivlen ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %" MBEDTLS_PRINTF_SIZET ", " + "should be no more than %" MBEDTLS_PRINTF_SIZET, + padlen, transform->ivlen ) ); +#endif + correct = 0; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* The padding check involves a series of up to 256 + * consecutive memory reads at the end of the record + * plaintext buffer. In order to hide the length and + * validity of the padding, always perform exactly + * `min(256,plaintext_len)` reads (but take into account + * only the last `padlen` bytes for the padding check). */ + size_t pad_count = 0; + volatile unsigned char* const check = data; + + /* Index of first padding byte; it has been ensured above + * that the subtraction is safe. */ + size_t const padding_idx = rec->data_len - padlen; + size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; + size_t const start_idx = rec->data_len - num_checks; + size_t idx; + + for( idx = start_idx; idx < rec->data_len; idx++ ) + { + /* pad_count += (idx >= padding_idx) && + * (check[idx] == padlen - 1); + */ + const size_t mask = mbedtls_ct_size_mask_ge( idx, padding_idx ); + const size_t equal = mbedtls_ct_size_bool_eq( check[idx], + padlen - 1 ); + pad_count += mask & equal; + } + correct &= mbedtls_ct_size_bool_eq( pad_count, padlen ); + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= mbedtls_ct_size_mask( correct ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* If the padding was found to be invalid, padlen == 0 + * and the subtraction is safe. If the padding was found valid, + * padlen hasn't been changed and the previous assertion + * data_len >= padlen still holds. */ + rec->data_len -= padlen; + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + data, rec->data_len ); +#endif + + /* + * Authenticate if not done yet. + * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). + */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 }; + unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 }; + + /* If the initial value of padlen was such that + * data_len < maclen + padlen + 1, then padlen + * got reset to 1, and the initial check + * data_len >= minlen + maclen + 1 + * guarantees that at this point we still + * have at least data_len >= maclen. + * + * If the initial value of padlen was such that + * data_len >= maclen + padlen + 1, then we have + * subtracted either padlen + 1 (if the padding was correct) + * or 0 (if the padding was incorrect) since then, + * hence data_len >= maclen in any case. + */ + rec->data_len -= transform->maclen; + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ret = ssl_mac( &transform->md_ctx_dec, + transform->mac_dec, + data, rec->data_len, + rec->ctr, rec->type, + mac_expect ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_mac", ret ); + goto hmac_failed_etm_disabled; + } + memcpy( mac_peer, data + rec->data_len, transform->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* + * The next two sizes are the minimum and maximum values of + * data_len over all padlen values. + * + * They're independent of padlen, since we previously did + * data_len -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = rec->data_len + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + ret = mbedtls_ct_hmac( &transform->md_ctx_dec, + add_data, add_data_len, + data, rec->data_len, min_len, max_len, + mac_expect ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ct_hmac", ret ); + goto hmac_failed_etm_disabled; + } + + mbedtls_ct_memcpy_offset( mac_peer, data, + rec->data_len, + min_len, max_len, + transform->maclen ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", mac_peer, transform->maclen ); +#endif + + if( mbedtls_ct_memcmp( mac_peer, mac_expect, + transform->maclen ) != 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + + hmac_failed_etm_disabled: + mbedtls_platform_zeroize( mac_peer, transform->maclen ); + mbedtls_platform_zeroize( mac_expect, transform->maclen ); + if( ret != 0 ) + return( ret ); + } + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + /* Remove inner padding and infer true content type. */ + ret = ssl_parse_inner_plaintext( data, &rec->data_len, + &rec->type ); + + if( ret != 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( rec->cid_len != 0 ) + { + ret = ssl_parse_inner_plaintext( data, &rec->data_len, + &rec->type ); + if( ret != 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +#if defined(MBEDTLS_ZLIB_SUPPORT) +/* + * Compression/decompression functions + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_compress_buf( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *msg_post = ssl->out_msg; + ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; + size_t len_pre = ssl->out_msglen; + unsigned char *msg_pre = ssl->compress_buf; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->out_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + ssl->transform_out->ctx_deflate.next_in = msg_pre; + ssl->transform_out->ctx_deflate.avail_in = len_pre; + ssl->transform_out->ctx_deflate.next_out = msg_post; + ssl->transform_out->ctx_deflate.avail_out = out_buf_len - bytes_written; + + ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->out_msglen = out_buf_len - + ssl->transform_out->ctx_deflate.avail_out - bytes_written; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %" MBEDTLS_PRINTF_SIZET ", ", + ssl->out_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", + ssl->out_msg, ssl->out_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); + + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *msg_post = ssl->in_msg; + ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; + size_t len_pre = ssl->in_msglen; + unsigned char *msg_pre = ssl->compress_buf; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); + + if( len_pre == 0 ) + return( 0 ); + + memcpy( msg_pre, ssl->in_msg, len_pre ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + ssl->transform_in->ctx_inflate.next_in = msg_pre; + ssl->transform_in->ctx_inflate.avail_in = len_pre; + ssl->transform_in->ctx_inflate.next_out = msg_post; + ssl->transform_in->ctx_inflate.avail_out = in_buf_len - header_bytes; + + ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); + if( ret != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); + return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); + } + + ssl->in_msglen = in_buf_len - + ssl->transform_in->ctx_inflate.avail_out - header_bytes; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %" MBEDTLS_PRINTF_SIZET ", ", + ssl->in_msglen ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", + ssl->in_msg, ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +/* + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. + */ +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( nb_want > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + uint32_t timeout; + + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ + + /* + * Move to the next record in the already read datagram if applicable + */ + if( ssl->next_record_offset != 0 ) + { + if( ssl->in_left < ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left -= ssl->next_record_offset; + + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %" + MBEDTLS_PRINTF_SIZET, + ssl->next_record_offset ) ); + memmove( ssl->in_hdr, + ssl->in_hdr + ssl->next_record_offset, + ssl->in_left ); + } + + ssl->next_record_offset = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET + ", nb_want: %" MBEDTLS_PRINTF_SIZET, + ssl->in_left, nb_want ) ); + + /* + * Done if we already have enough data. + */ + if( nb_want <= ssl->in_left) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + return( 0 ); + } + + /* + * A record can't be split across datagrams. If we need to read but + * are not at the beginning of a new record, the caller did something + * wrong. + */ + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Don't even try to read if time's out already. + * This avoids by-passing the timer when repeatedly receiving messages + * that will end up being dropped. + */ + if( mbedtls_ssl_check_timer( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); + ret = MBEDTLS_ERR_SSL_TIMEOUT; + } + else + { + len = in_buf_len - ( ssl->in_hdr - ssl->in_buf ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + timeout = ssl->handshake->retransmit_timeout; + else + timeout = ssl->conf->read_timeout; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %lu ms", (unsigned long) timeout ) ); + + if( ssl->f_recv_timeout != NULL ) + ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, + timeout ); + else + ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + } + + if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); + mbedtls_ssl_set_timer( ssl, 0 ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl_double_retransmit_timeout( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); + return( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request", + ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + } + + if( ret < 0 ) + return( ret ); + + ssl->in_left = ret; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET + ", nb_want: %" MBEDTLS_PRINTF_SIZET, + ssl->in_left, nb_want ) ); + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + + if( mbedtls_ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + if( ssl->f_recv_timeout != NULL ) + { + ret = ssl->f_recv_timeout( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len, + ssl->conf->read_timeout ); + } + else + { + ret = ssl->f_recv( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET + ", nb_want: %" MBEDTLS_PRINTF_SIZET, + ssl->in_left, nb_want ) ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested", + ret, len ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left += ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + if( ssl->f_send == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Avoid incrementing counter if data is flushed */ + if( ssl->out_left == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + return( 0 ); + } + + while( ssl->out_left > 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %" MBEDTLS_PRINTF_SIZET + ", out_left: %" MBEDTLS_PRINTF_SIZET, + mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr - ssl->out_left; + ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent", + ret, ssl->out_left ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_left -= ret; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + } + else +#endif + { + ssl->out_hdr = ssl->out_buf + 8; + } + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Functions to handle the DTLS retransmission state machine + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Append current handshake message to current outgoing flight + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_flight_append( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_flight_item *msg; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", + ssl->out_msg, ssl->out_msglen ); + + /* Allocate space for current message */ + if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed", + sizeof( mbedtls_ssl_flight_item ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed", + ssl->out_msglen ) ); + mbedtls_free( msg ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Copy current handshake message with headers */ + memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); + msg->len = ssl->out_msglen; + msg->type = ssl->out_msgtype; + msg->next = NULL; + + /* Append to the current flight */ + if( ssl->handshake->flight == NULL ) + ssl->handshake->flight = msg; + else + { + mbedtls_ssl_flight_item *cur = ssl->handshake->flight; + while( cur->next != NULL ) + cur = cur->next; + cur->next = msg; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); + return( 0 ); +} + +/* + * Free the current flight of handshake messages + */ +void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ) +{ + mbedtls_ssl_flight_item *cur = flight; + mbedtls_ssl_flight_item *next; + + while( cur != NULL ) + { + next = cur->next; + + mbedtls_free( cur->p ); + mbedtls_free( cur ); + + cur = next; + } +} + +/* + * Swap transform_out and out_ctr with the alternative ones + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[8]; + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); + + /* Swap transforms */ + tmp_transform = ssl->transform_out; + ssl->transform_out = ssl->handshake->alt_transform_out; + ssl->handshake->alt_transform_out = tmp_transform; + + /* Swap epoch + sequence_number */ + memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 ); + memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 ); + memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); + + /* Adjust to the newly activated transform */ + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + int ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + return( 0 ); +} + +/* + * Retransmit the current flight of messages. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + ret = mbedtls_ssl_flight_transmit( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( ret ); +} + +/* + * Transmit or retransmit the current flight of messages. + * + * Need to remember the current message in case flush_output returns + * WANT_WRITE, causing us to exit this function and come back later. + * This function must be called until state is no longer SENDING. + */ +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); + + if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); + + ssl->handshake->cur_msg = ssl->handshake->flight; + ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + size_t max_frag_len; + const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + + int const is_finished = + ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); + + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; + + /* Swap epochs before sending Finished: we can't do it after + * sending ChangeCipherSpec, in case write returns WANT_READ. + * Must be done before copying, may change out_msg pointer */ + if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + } + + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + max_frag_len = (size_t) ret; + + /* CCS is copied as is, while HS messages may need fragmentation */ + if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( max_frag_len == 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur->len; + } + else + { + const unsigned char * const p = ssl->handshake->cur_msg_p; + const size_t hs_len = cur->len - 12; + const size_t frag_off = p - ( cur->p + 12 ); + const size_t rem_len = hs_len - frag_off; + size_t cur_hs_frag_len, max_hs_frag_len; + + if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) + { + if( is_finished ) + { + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + max_hs_frag_len = max_frag_len - 12; + + cur_hs_frag_len = rem_len > max_hs_frag_len ? + max_hs_frag_len : rem_len; + + if( frag_off == 0 && cur_hs_frag_len != hs_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", + (unsigned) cur_hs_frag_len, + (unsigned) max_hs_frag_len ) ); + } + + /* Messages are stored with handshake headers as if not fragmented, + * copy beginning of headers then fill fragmentation fields. + * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ + memcpy( ssl->out_msg, cur->p, 6 ); + + ssl->out_msg[6] = MBEDTLS_BYTE_2( frag_off ); + ssl->out_msg[7] = MBEDTLS_BYTE_1( frag_off ); + ssl->out_msg[8] = MBEDTLS_BYTE_0( frag_off ); + + ssl->out_msg[ 9] = MBEDTLS_BYTE_2( cur_hs_frag_len ); + ssl->out_msg[10] = MBEDTLS_BYTE_1( cur_hs_frag_len ); + ssl->out_msg[11] = MBEDTLS_BYTE_0( cur_hs_frag_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); + + /* Copy the handshake message content and set records fields */ + memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); + ssl->out_msglen = cur_hs_frag_len + 12; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur_hs_frag_len; + } + + /* If done with the current message move to the next one if any */ + if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) + { + if( cur->next != NULL ) + { + ssl->handshake->cur_msg = cur->next; + ssl->handshake->cur_msg_p = cur->next->p + 12; + } + else + { + ssl->handshake->cur_msg = NULL; + ssl->handshake->cur_msg_p = NULL; + } + } + + /* Actually send the message out */ + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + /* Update state and set timer */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + else + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); + + return( 0 ); +} + +/* + * To be called when the last message of an incoming flight is received. + */ +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) +{ + /* We won't need to resend that one any more */ + mbedtls_ssl_flight_free( ssl->handshake->flight ); + ssl->handshake->flight = NULL; + ssl->handshake->cur_msg = NULL; + + /* The next incoming flight will start with this msg_seq */ + ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + + /* We don't want to remember CCS's across flight boundaries. */ + ssl->handshake->buffering.seen_ccs = 0; + + /* Clear future message buffering structure. */ + mbedtls_ssl_buffering_free( ssl ); + + /* Cancel timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; +} + +/* + * To be called when the last message of an outgoing flight is send. + */ +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) +{ + ssl_reset_retransmit_timeout( ssl ); + mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Handshake layer functions + */ + +/* + * Write (DTLS: or queue) current handshake (including CCS) message. + * + * - fill in handshake headers + * - update handshake checksum + * - DTLS: save message for resending + * - then pass to the record layer + * + * DTLS: except for HelloRequest, messages are only queued, and will only be + * actually sent when calling flight_transmit() or resend(). + * + * Inputs: + * - ssl->out_msglen: 4 + actual handshake message len + * (4 is the size of handshake headers for TLS) + * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) + * - ssl->out_msg + 4: the handshake message body + * + * Outputs, ie state before passing to flight_append() or write_record(): + * - ssl->out_msglen: the length of the record contents + * (including handshake headers but excluding record headers) + * - ssl->out_msg: the record contents (handshake headers + content) + */ +int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t hs_len = ssl->out_msglen - 4; + const unsigned char hs_type = ssl->out_msg[0]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); + + /* + * Sanity checks + */ + if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + /* In SSLv3, the client might send a NoCertificate alert. */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) + if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ) +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* Whenever we send anything different from a + * HelloRequest we should be in a handshake - double check. */ + if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } +#endif + + /* Double-check that we did not exceed the bounds + * of the outgoing record buffer. + * This should never fail as the various message + * writing functions must obey the bounds of the + * outgoing record buffer, but better be safe. + * + * Note: We deliberately do not check for the MTU or MFL here. + */ + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " + "size %" MBEDTLS_PRINTF_SIZET + ", maximum %" MBEDTLS_PRINTF_SIZET, + ssl->out_msglen, + (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Fill handshake headers + */ + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + ssl->out_msg[1] = MBEDTLS_BYTE_2( hs_len ); + ssl->out_msg[2] = MBEDTLS_BYTE_1( hs_len ); + ssl->out_msg[3] = MBEDTLS_BYTE_0( hs_len ); + + /* + * DTLS has additional fields in the Handshake layer, + * between the length field and the actual payload: + * uint16 message_seq; + * uint24 fragment_offset; + * uint24 fragment_length; + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Make room for the additional DTLS fields */ + if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " + "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET, + hs_len, + (size_t) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); + ssl->out_msglen += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + MBEDTLS_PUT_UINT16_BE( ssl->handshake->out_msg_seq, ssl->out_msg, 4 ); + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* Handshake hashes are computed without fragmentation, + * so set frag_offset = 0 and frag_len = hs_len for now */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Update running hashes of handshake messages seen */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); + } + + /* Either send now, or just save to be sent (and resent) later */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } + else +#endif + { + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ + +/* + * Write current record. + * + * Uses: + * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) + * - ssl->out_msglen: length of the record content (excl headers) + * - ssl->out_msg: record content + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + uint8_t flush = force_flush; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_out != NULL && + ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); + return( ret ); + } + + len = ssl->out_msglen; + } +#endif /*MBEDTLS_ZLIB_SUPPORT */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_write != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); + + ret = mbedtls_ssl_hw_record_write( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done ) + { + unsigned i; + size_t protected_record_size; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + /* Skip writing the record content type to after the encryption, + * as it may change when using the CID extension. */ + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 ); + MBEDTLS_PUT_UINT16_BE( len, ssl->out_len, 0); + + if( ssl->transform_out != NULL ) + { + mbedtls_record rec; + + rec.buf = ssl->out_iv; + rec.buf_len = out_buf_len - ( ssl->out_iv - ssl->out_buf ); + rec.data_len = ssl->out_msglen; + rec.data_offset = ssl->out_msg - rec.buf; + + memcpy( &rec.ctr[0], ssl->out_ctr, 8 ); + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, rec.ver ); + rec.type = ssl->out_msgtype; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* The CID is set by mbedtls_ssl_encrypt_buf(). */ + rec.cid_len = 0; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + if( rec.data_offset != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Update the record content type and CID. */ + ssl->out_msgtype = rec.type; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID ) + memcpy( ssl->out_cid, rec.cid, rec.cid_len ); +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_msglen = len = rec.data_len; + MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->out_len, 0 ); + } + + protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* In case of DTLS, double-check that we don't exceed + * the remaining space in the datagram. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + + if( protected_record_size > (size_t) ret ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Now write the potentially updated record content type. */ + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %u, " + "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET, + ssl->out_hdr[0], ssl->out_hdr[1], + ssl->out_hdr[2], len ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, protected_record_size ); + + ssl->out_left += protected_record_size; + ssl->out_hdr += protected_record_size; + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == mbedtls_ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + flush == SSL_DONT_FORCE_FLUSH ) + { + size_t remaining; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", + ret ); + return( ret ); + } + + remaining = (size_t) ret; + if( remaining == 0 ) + { + flush = SSL_FORCE_FLUSH; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( flush == SSL_FORCE_FLUSH ) && + ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) + { + return( 1 ); + } + return( 0 ); +} + +static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11] ); +} + +static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8] ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) +{ + uint32_t msg_len, frag_off, frag_len; + + msg_len = ssl_get_hs_total_len( ssl ); + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + if( frag_off > msg_len ) + return( -1 ); + + if( frag_len > msg_len - frag_off ) + return( -1 ); + + if( frag_len + 12 > ssl->in_msglen ) + return( -1 ); + + return( 0 ); +} + +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* msg_len does not include the handshake header */ +static size_t ssl_get_reassembly_buffer_size( size_t msg_len, + unsigned add_bitmap ) +{ + size_t alloc_len; + + alloc_len = 12; /* Handshake header */ + alloc_len += msg_len; /* Content buffer */ + + if( add_bitmap ) + alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ + + return( alloc_len ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); +} + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %" MBEDTLS_PRINTF_SIZET, + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET, + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + if( ssl_check_hs_header( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->handshake != NULL && + ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + recv_msg_seq != ssl->handshake->in_msg_seq ) || + ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) + { + if( recv_msg_seq > ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %u, start_of_flight = %u", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %u, expected = %u", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Message reassembly is handled alongside buffering of future + * messages; the commonality is that both handshake fragments and + * future messages cannot be forwarded immediately to the + * handshake logic layer. */ + if( ssl_hs_is_proper_fragment( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + unsigned offset; + mbedtls_ssl_hs_buffer *hs_buf; + + /* Increment handshake sequence number */ + hs->in_msg_seq++; + + /* + * Clear up handshake buffering and reassembly structure. + */ + + /* Free first entry */ + ssl_buffering_free_slot( ssl, 0 ); + + /* Shift all other entries */ + for( offset = 0, hs_buf = &hs->buffering.hs[0]; + offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; + offset++, hs_buf++ ) + { + *hs_buf = *(hs_buf + 1); + } + + /* Create a fresh last entry */ + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *original_in_ctr; + + // save original in_ctr + original_in_ctr = ssl->in_ctr; + + // use counter from record + ssl->in_ctr = record_in_ctr; + + ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl ); + + // restore the counter + ssl->in_ctr = original_in_ctr; + + return ret; +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* + * Check if a datagram looks like a ClientHello with a valid cookie, + * and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +MBEDTLS_CHECK_RETURN_CRITICAL +MBEDTLS_STATIC_TESTABLE +int mbedtls_ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_context *ssl, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: in_len=%u", + (unsigned) in_len ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "cli_id", cli_id, cli_id_len ); + if( in_len < 61 ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: record too short" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + if( in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: not a good ClientHello" ) ); + MBEDTLS_SSL_DEBUG_MSG( 4, ( " type=%u epoch=%u fragment_offset=%u", + in[0], + (unsigned) in[3] << 8 | in[4], + (unsigned) in[19] << 16 | in[20] << 8 | in[21] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + sid_len = in[59]; + if( 59 + 1 + sid_len + 1 > in_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: sid_len=%u > %u", + (unsigned) sid_len, + (unsigned) in_len - 61 ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + MBEDTLS_SSL_DEBUG_BUF( 4, "sid received from network", + in + 60, sid_len ); + + cookie_len = in[60 + sid_len]; + if( 59 + 1 + sid_len + 1 + cookie_len > in_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: cookie_len=%u > %u", + (unsigned) cookie_len, + (unsigned) ( in_len - sid_len - 61 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "cookie received from network", + in + sid_len + 61, cookie_len ); + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: valid" ) ); + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, obuf + buf_len, + cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = MBEDTLS_BYTE_2( *olen - 25 ); + obuf[15] = obuf[23] = MBEDTLS_BYTE_1( *olen - 25 ); + obuf[16] = obuf[24] = MBEDTLS_BYTE_0( *olen - 25 ); + + MBEDTLS_PUT_UINT16_BE( *olen - 13, obuf, 11 ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then return 0 + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * This function is called (through ssl_check_client_reconnect()) when an + * unexpected record is found in ssl_get_next_record(), which will discard the + * record if we return 0, and bubble up the return value otherwise (this + * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected + * errors, and is the right thing to do in both cases). + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ssl->conf->f_cookie_write == NULL || + ssl->conf->f_cookie_check == NULL ) + { + /* If we can't use cookies to verify reachability of the peer, + * drop the record. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no cookie callbacks, " + "can't check reconnect validity" ) ); + return( 0 ); + } + + ret = mbedtls_ssl_check_dtls_clihlo_cookie( + ssl, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + int send_ret; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_buf, len ); + /* Don't check write errors as we can't do anything here. + * If the error is permanent we'll catch it later, + * if it's not, then hopefully it'll work next time. */ + send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret ); + (void) send_ret; + + return( 0 ); + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) ); + if( ( ret = mbedtls_ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_record_type( uint8_t record_type ) +{ + if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE && + record_type != MBEDTLS_SSL_MSG_ALERT && + record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + return( 0 ); +} + +/* + * ContentType type; + * ProtocolVersion version; + * uint16 epoch; // DTLS only + * uint48 sequence_number; // DTLS only + * uint16 length; + * + * Return 0 if header looks sane (and, for DTLS, the record is expected) + * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. + * + * With DTLS, mbedtls_ssl_read_record() will: + * 1. proceed with the record if this function returns 0 + * 2. drop only the current record if this function returns UNEXPECTED_RECORD + * 3. return CLIENT_RECONNECT if this function return that value + * 4. drop the whole datagram if this function returns anything else. + * Point 2 is needed when the peer is resending, and we have already received + * the first record from a datagram but are still waiting for the others. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t len, + mbedtls_record *rec ) +{ + int major_ver, minor_ver; + + size_t const rec_hdr_type_offset = 0; + size_t const rec_hdr_type_len = 1; + + size_t const rec_hdr_version_offset = rec_hdr_type_offset + + rec_hdr_type_len; + size_t const rec_hdr_version_len = 2; + + size_t const rec_hdr_ctr_len = 8; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t rec_epoch; + size_t const rec_hdr_ctr_offset = rec_hdr_version_offset + + rec_hdr_version_len; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset + + rec_hdr_ctr_len; + size_t rec_hdr_cid_len = 0; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + size_t rec_hdr_len_offset; /* To be determined */ + size_t const rec_hdr_len_len = 2; + + /* + * Check minimum lengths for record header. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len; + } + + if( len < rec_hdr_len_offset + rec_hdr_len_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u", + (unsigned) len, + (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* + * Parse and validate record content type + */ + + rec->type = buf[ rec_hdr_type_offset ]; + + /* Check record content type */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + rec->cid_len = 0; + + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->cid_len != 0 && + rec->type == MBEDTLS_SSL_MSG_CID ) + { + /* Shift pointers to account for record header including CID + * struct { + * ContentType special_type = tls12_cid; + * ProtocolVersion version; + * uint16 epoch; + * uint48 sequence_number; + * opaque cid[cid_length]; // Additional field compared to + * // default DTLS record format + * uint16 length; + * opaque enc_content[DTLSCiphertext.length]; + * } DTLSCiphertext; + */ + + /* So far, we only support static CID lengths + * fixed in the configuration. */ + rec_hdr_cid_len = ssl->conf->cid_len; + rec_hdr_len_offset += rec_hdr_cid_len; + + if( len < rec_hdr_len_offset + rec_hdr_len_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u", + (unsigned) len, + (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* configured CID len is guaranteed at most 255, see + * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */ + rec->cid_len = (uint8_t) rec_hdr_cid_len; + memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + if( ssl_check_record_type( rec->type ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u", + (unsigned) rec->type ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + + /* + * Parse and validate record version + */ + rec->ver[0] = buf[ rec_hdr_version_offset + 0 ]; + rec->ver[1] = buf[ rec_hdr_version_offset + 1 ]; + mbedtls_ssl_read_version( &major_ver, &minor_ver, + ssl->conf->transport, + &rec->ver[0] ); + + if( major_ver != ssl->major_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch: got %u, expected %u", + (unsigned) major_ver, + (unsigned) ssl->major_ver ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch: got %u, expected max %u", + (unsigned) minor_ver, + (unsigned) ssl->conf->max_minor_ver ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + /* + * Parse/Copy record sequence number. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Copy explicit record sequence number from input buffer. */ + memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset, + rec_hdr_ctr_len ); + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + /* Copy implicit record sequence number from SSL context structure. */ + memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len ); + } + + /* + * Parse record length. + */ + + rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len; + rec->data_len = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) | + ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %u, " + "version = [%d:%d], msglen = %" MBEDTLS_PRINTF_SIZET, + rec->type, + major_ver, minor_ver, rec->data_len ) ); + + rec->buf = buf; + rec->buf_len = rec->data_offset + rec->data_len; + + if( rec->data_len == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + + /* + * DTLS-related tests. + * Check epoch before checking length constraint because + * the latter varies with the epoch. E.g., if a ChangeCipherSpec + * message gets duplicated before the corresponding Finished message, + * the second ChangeCipherSpec should be discarded because it belongs + * to an old epoch, but not because its length is shorter than + * the minimum record length for packets using the new record transform. + * Note that these two kinds of failures are handled differently, + * as an unexpected record is silently skipped but an invalid + * record leads to the entire datagram being dropped. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1]; + + /* Check that the datagram is large enough to contain a record + * of the advertised length. */ + if( len < rec->data_offset + rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.", + (unsigned) len, + (unsigned)( rec->data_offset + rec->data_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Records from other, non-matching epochs are silently discarded. + * (The case of same-port Client reconnects must be considered in + * the caller). */ + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " + "expected %u, received %lu", + ssl->in_epoch, (unsigned long) rec_epoch ) ); + + /* Records from the next epoch are considered for buffering + * (concretely: early Finished messages). */ + if( rec_epoch == (unsigned) ssl->in_epoch + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + /* For records from the correct epoch, check whether their + * sequence number has been seen before. */ + else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl, + &rec->ctr[0] ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl ) +{ + unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; + + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( rec_epoch == 0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +/* + * If applicable, decrypt record content + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_prepare_record_content( mbedtls_ssl_context *ssl, + mbedtls_record *rec ) +{ + int ret, done = 0; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", + rec->buf, rec->buf_len ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_read != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); + + ret = mbedtls_ssl_hw_record_read( ssl ); + if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ret == 0 ) + done = 1; + } +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + if( !done && ssl->transform_in != NULL ) + { + unsigned char const old_msg_type = rec->type; + + if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, + rec ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID && + ssl->conf->ignore_unexpected_cid + == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) ); + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + return( ret ); + } + + if( old_msg_type != rec->type ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d", + old_msg_type, rec->type ) ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", + rec->buf + rec->data_offset, rec->data_len ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* We have already checked the record content type + * in ssl_parse_record_header(), failing or silently + * dropping the record in the case of an unknown type. + * + * Since with the use of CIDs, the record content type + * might change during decryption, re-check the record + * content type, but treat a failure as fatal this time. */ + if( ssl_check_record_type( rec->type ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + if( rec->data_len == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + /* Treat the records as if they were not properly authenticated, + * thereby failing the connection if we see more than allowed + * by the configured bad MAC threshold. */ + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ; /* in_ctr read from peer, not maintained internally */ + } + else +#endif + { + unsigned i; + for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- ) + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == mbedtls_ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + mbedtls_ssl_dtls_replay_update( ssl ); + } +#endif + + /* Check actual (decrypted) record content length against + * configured maximum. */ + if( rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + return( 0 ); +} + +/* + * Read a record. + * + * Silently ignore non-fatal alert (and for DTLS, invalid records as well, + * RFC 6347 4.1.2.7) and continue reading until a valid record is found. + * + */ + +/* Helper functions for mbedtls_ssl_read_record(). */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_next_record( mbedtls_ssl_context *ssl ); +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + if( ssl->keep_current_message == 0 ) + { + do { + + ret = ssl_consume_current_message( ssl ); + if( ret != 0 ) + return( ret ); + + if( ssl_record_is_in_progress( ssl ) == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + int have_buffered = 0; + + /* We only check for buffered messages if the + * current datagram is fully consumed. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl_next_record_is_in_datagram( ssl ) == 0 ) + { + if( ssl_load_buffered_message( ssl ) == 0 ) + have_buffered = 1; + } + + if( have_buffered == 0 ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ret = ssl_get_next_record( ssl ); + if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) + continue; + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); + return( ret ); + } + } + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + /* Buffer future message */ + ret = ssl_buffer_message( ssl ); + if( ret != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || + MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + update_hs_digest == 1 ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); + ssl->keep_current_message = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_left > ssl->next_record_offset ) + return( 1 ); + + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * hs_buf; + int ret = 0; + + if( hs == NULL ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); + + if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || + ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + /* Check if we have seen a ChangeCipherSpec before. + * If yes, synthesize a CCS record. */ + if( !hs->buffering.seen_ccs ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); + ret = -1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); + ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->in_msglen = 1; + ssl->in_msg[0] = 1; + + /* As long as they are equal, the exact value doesn't matter. */ + ssl->in_left = 0; + ssl->next_record_offset = 0; + + hs->buffering.seen_ccs = 0; + goto exit; + } + +#if defined(MBEDTLS_DEBUG_C) + /* Debug only */ + { + unsigned offset; + for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + { + hs_buf = &hs->buffering.hs[offset]; + if( hs_buf->is_valid == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", + hs->in_msg_seq + offset, + hs_buf->is_complete ? "fully" : "partially" ) ); + } + } + } +#endif /* MBEDTLS_DEBUG_C */ + + /* Check if we have buffered and/or fully reassembled the + * next handshake message. */ + hs_buf = &hs->buffering.hs[0]; + if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) + { + /* Synthesize a record containing the buffered HS message. */ + size_t msg_len = ( hs_buf->data[1] << 16 ) | + ( hs_buf->data[2] << 8 ) | + hs_buf->data[3]; + + /* Double-check that we haven't accidentally buffered + * a message that doesn't fit into the input buffer. */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", + hs_buf->data, msg_len + 12 ); + + ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->in_hslen = msg_len + 12; + ssl->in_msglen = msg_len + 12; + memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); + + ret = 0; + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", + hs->in_msg_seq ) ); + } + + ret = -1; + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); + return( ret ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, + size_t desired ) +{ + int offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", + (unsigned) desired ) ); + + /* Get rid of future records epoch first, if such exist. */ + ssl_free_buffered_record( ssl ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); + return( 0 ); + } + + /* We don't have enough space to buffer the next expected handshake + * message. Remove buffers used for future messages to gain space, + * starting with the most distant one. */ + for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; + offset >= 0; offset-- ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", + offset ) ); + + ssl_buffering_free_slot( ssl, (uint8_t) offset ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); + return( 0 ); + } + } + + return( -1 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_buffer_message( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); + + switch( ssl->in_msgtype ) + { + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); + + hs->buffering.seen_ccs = 1; + break; + + case MBEDTLS_SSL_MSG_HANDSHAKE: + { + unsigned recv_msg_seq_offset; + unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + mbedtls_ssl_hs_buffer *hs_buf; + size_t msg_len = ssl->in_hslen - 12; + + /* We should never receive an old handshake + * message - double-check nonetheless. */ + if( recv_msg_seq < ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; + if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + { + /* Silently ignore -- message too far in the future */ + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "Ignore future HS message with sequence number %u, " + "buffering window %u - %u", + recv_msg_seq, ssl->handshake->in_msg_seq, + ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); + + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", + recv_msg_seq, recv_msg_seq_offset ) ); + + hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; + + /* Check if the buffering for this seq nr has already commenced. */ + if( !hs_buf->is_valid ) + { + size_t reassembly_buf_sz; + + hs_buf->is_fragmented = + ( ssl_hs_is_proper_fragment( ssl ) == 1 ); + + /* We copy the message back into the input buffer + * after reassembly, so check that it's not too large. + * This is an implementation-specific limitation + * and not one from the standard, hence it is not + * checked in ssl_check_hs_header(). */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + /* Ignore message */ + goto exit; + } + + /* Check if we have enough space to buffer the message. */ + if( hs->buffering.total_bytes_buffered > + MBEDTLS_SSL_DTLS_MAX_BUFFERING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, + hs_buf->is_fragmented ); + + if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + if( recv_msg_seq_offset > 0 ) + { + /* If we can't buffer a future message because + * of space limitations -- ignore. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET + " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET + " (already %" MBEDTLS_PRINTF_SIZET + " bytes buffered) -- ignore\n", + msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, + hs->buffering.total_bytes_buffered ) ); + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET + " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET + " (already %" MBEDTLS_PRINTF_SIZET + " bytes buffered) -- attempt to make space by freeing buffered future messages\n", + msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, + hs->buffering.total_bytes_buffered ) ); + } + + if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET + " (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed" + " the compile-time limit %" MBEDTLS_PRINTF_SIZET + " (already %" MBEDTLS_PRINTF_SIZET + " bytes buffered) -- fail\n", + msg_len, + reassembly_buf_sz, + (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, + hs->buffering.total_bytes_buffered ) ); + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET, + msg_len ) ); + + hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); + if( hs_buf->data == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + hs_buf->data_len = reassembly_buf_sz; + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( hs_buf->data, ssl->in_msg, 6 ); + memset( hs_buf->data + 6, 0, 3 ); + memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); + + hs_buf->is_valid = 1; + + hs->buffering.total_bytes_buffered += reassembly_buf_sz; + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); + /* Ignore */ + goto exit; + } + } + + if( !hs_buf->is_complete ) + { + size_t frag_len, frag_off; + unsigned char * const msg = hs_buf->data + 12; + + /* + * Check and copy current fragment + */ + + /* Validation of header fields already done in + * mbedtls_ssl_prepare_handshake_record(). */ + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %" MBEDTLS_PRINTF_SIZET + ", length = %" MBEDTLS_PRINTF_SIZET, + frag_off, frag_len ) ); + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + + if( hs_buf->is_fragmented ) + { + unsigned char * const bitmask = msg + msg_len; + ssl_bitmask_set( bitmask, frag_off, frag_len ); + hs_buf->is_complete = ( ssl_bitmask_check( bitmask, + msg_len ) == 0 ); + } + else + { + hs_buf->is_complete = 1; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", + hs_buf->is_complete ? "" : "not yet " ) ); + } + + break; + } + + default: + /* We don't buffer other types of messages. */ + break; + } + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) +{ + /* + * Consume last content-layer message and potentially + * update in_msglen which keeps track of the contents' + * consumption state. + * + * (1) Handshake messages: + * Remove last handshake message, move content + * and adapt in_msglen. + * + * (2) Alert messages: + * Consume whole record content, in_msglen = 0. + * + * (3) Change cipher spec: + * Consume whole record content, in_msglen = 0. + * + * (4) Application data: + * Don't do anything - the record layer provides + * the application data as a stream transport + * and consumes through mbedtls_ssl_read only. + * + */ + + /* Case (1): Handshake messages */ + if( ssl->in_hslen != 0 ) + { + /* Hard assertion to be sure that no application data + * is in flight, as corrupting ssl->in_msglen during + * ssl->in_offt != NULL is fatal. */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Get next Handshake message in the current record + */ + + /* Notes: + * (1) in_hslen is not necessarily the size of the + * current handshake content: If DTLS handshake + * fragmentation is used, that's the fragment + * size instead. Using the total handshake message + * size here is faulty and should be changed at + * some point. + * (2) While it doesn't seem to cause problems, one + * has to be very careful not to assume that in_hslen + * is always <= in_msglen in a sensible communication. + * Again, it's wrong for DTLS handshake fragmentation. + * The following check is therefore mandatory, and + * should not be treated as a silently corrected assertion. + * Additionally, ssl->in_hslen might be arbitrarily out of + * bounds after handling a DTLS message with an unexpected + * sequence number, see mbedtls_ssl_prepare_handshake_record. + */ + if( ssl->in_hslen < ssl->in_msglen ) + { + ssl->in_msglen -= ssl->in_hslen; + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + } + else + { + ssl->in_msglen = 0; + } + + ssl->in_hslen = 0; + } + /* Case (4): Application data */ + else if( ssl->in_offt != NULL ) + { + return( 0 ); + } + /* Everything else (CCS & Alerts) */ + else + { + ssl->in_msglen = 0; + } + + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen > 0 ) + return( 1 ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + if( hs == NULL ) + return; + + if( hs->buffering.future_record.data != NULL ) + { + hs->buffering.total_bytes_buffered -= + hs->buffering.future_record.len; + + mbedtls_free( hs->buffering.future_record.data ); + hs->buffering.future_record.data = NULL; + } +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + unsigned char * rec; + size_t rec_len; + unsigned rec_epoch; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 0 ); + + if( hs == NULL ) + return( 0 ); + + rec = hs->buffering.future_record.data; + rec_len = hs->buffering.future_record.len; + rec_epoch = hs->buffering.future_record.epoch; + + if( rec == NULL ) + return( 0 ); + + /* Only consider loading future records if the + * input buffer is empty. */ + if( ssl_next_record_is_in_datagram( ssl ) == 1 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); + + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); + + /* Double-check that the record is not too large */ + if( rec_len > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->in_hdr, rec, rec_len ); + ssl->in_left = rec_len; + ssl->next_record_offset = 0; + + ssl_free_buffered_record( ssl ); + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, + mbedtls_record const *rec ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + /* Don't buffer future records outside handshakes. */ + if( hs == NULL ) + return( 0 ); + + /* Only buffer handshake records (we are only interested + * in Finished messages). */ + if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE ) + return( 0 ); + + /* Don't buffer more than one future epoch record. */ + if( hs->buffering.future_record.data != NULL ) + return( 0 ); + + /* Don't buffer record if there's not enough buffering space remaining. */ + if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET + " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET + " (already %" MBEDTLS_PRINTF_SIZET + " bytes buffered) -- ignore\n", + rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, + hs->buffering.total_bytes_buffered ) ); + return( 0 ); + } + + /* Buffer record */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", + ssl->in_epoch + 1U ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len ); + + /* ssl_parse_record_header() only considers records + * of the next epoch as candidates for buffering. */ + hs->buffering.future_record.epoch = ssl->in_epoch + 1; + hs->buffering.future_record.len = rec->buf_len; + + hs->buffering.future_record.data = + mbedtls_calloc( 1, hs->buffering.future_record.len ); + if( hs->buffering.future_record.data == NULL ) + { + /* If we run out of RAM trying to buffer a + * record from the next epoch, just ignore. */ + return( 0 ); + } + + memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len ); + + hs->buffering.total_bytes_buffered += rec->buf_len; + return( 0 ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_next_record( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_record rec; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* We might have buffered a future record; if so, + * and if the epoch matches now, load it. + * On success, this call will set ssl->in_left to + * the length of the buffered record, so that + * the calls to ssl_fetch_input() below will + * essentially be no-ops. */ + ret = ssl_load_buffered_record( ssl ); + if( ret != 0 ) + return( ret ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Ensure that we have enough space available for the default form + * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS, + * with no space for CIDs counted in). */ + ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec ); + if( ret != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = ssl_buffer_future_record( ssl, &rec ); + if( ret != 0 ) + return( ret ); + + /* Fall through to handling of unexpected records */ + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) + { +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* Reset in pointers to default state for TLS/DTLS records, + * assuming no CID and no offset between record content and + * record plaintext. */ + mbedtls_ssl_update_in_pointers( ssl ); + + /* Setup internal message pointers from record structure. */ + ssl->in_msgtype = rec.type; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_len = ssl->in_cid + rec.cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_msg = ssl->in_len + 2; + ssl->in_msglen = rec.data_len; + + ret = ssl_check_client_reconnect( ssl ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_client_reconnect", ret ); + if( ret != 0 ) + return( ret ); +#endif + + /* Skip unexpected record (but not whole datagram) */ + ssl->next_record_offset = rec.buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " + "(header)" ) ); + } + else + { + /* Skip invalid record and the rest of the datagram */ + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " + "(header)" ) ); + } + + /* Get next record */ + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + else +#endif + { + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Remember offset of next record within datagram. */ + ssl->next_record_offset = rec.buf_len; + if( ssl->next_record_offset < ssl->in_left ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); + } + } + else +#endif + { + /* + * Fetch record contents from underlying transport. + */ + ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->in_left = 0; + } + + /* + * Decrypt record contents. + */ + + if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Silently discard invalid records */ + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + /* Except when waiting for Finished as a bad mac here + * probably means something went wrong in the handshake + * (eg wrong psk used, mitm downgrade attempt, etc.) */ + if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || + ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) + { +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( ssl->conf->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->conf->badmac_limit ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } +#endif + + /* As above, invalid records cause + * dismissal of the whole datagram. */ + + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + + return( ret ); + } + else +#endif + { + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + } + + + /* Reset in pointers to default state for TLS/DTLS records, + * assuming no CID and no offset between record content and + * record plaintext. */ + mbedtls_ssl_update_in_pointers( ssl ); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_len = ssl->in_cid + rec.cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + + /* The record content type may change during decryption, + * so re-read it. */ + ssl->in_msgtype = rec.type; + /* Also update the input buffer, because unfortunately + * the server-side ssl_parse_client_hello() reparses the + * record header when receiving a ClientHello initiating + * a renegotiation. */ + ssl->in_hdr[0] = rec.type; + ssl->in_msg = rec.buf + rec.data_offset; + ssl->in_msglen = rec.data_len; + MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->in_len, 0 ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->transform_in != NULL && + ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); + return( ret ); + } + + /* Check actual (decompress) record content length against + * configured maximum. */ + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + + return( 0 ); +} + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Handle particular types of records + */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) + { + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( ssl->in_msglen != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET, + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", + ssl->in_msg[0] ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } +#endif + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %" MBEDTLS_PRINTF_SIZET, + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%u:%u]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify and no_renegotiation + */ + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) ); + /* Will be handled when trying to parse ServerHello */ + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); + /* Will be handled in mbedtls_ssl_parse_certificate() */ + return( 0 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ + + /* Silently ignore: fetch new message */ + return MBEDTLS_ERR_SSL_NON_FATAL; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_NON_FATAL ); + } + + if( ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ); +} + +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* CCS records are only accepted if they have length 1 and content '1', + * so we don't need to check this here. */ + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset( ssl ); +#endif + + /* Increment epoch */ + if( ++ssl->in_epoch == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->in_ctr, 0, 8 ); + + mbedtls_ssl_update_in_pointers( ssl ); + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +/* Once ssl->out_hdr as the address of the beginning of the + * next outgoing record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->out_hdr, + * and the caller has to make sure there's space for this. + */ + +static size_t ssl_transform_get_explicit_iv_len( + mbedtls_ssl_transform const *transform ) +{ + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) + return( 0 ); + + return( transform->ivlen - transform->fixed_ivlen ); +} + +void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_ctr = ssl->out_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->out_cid = ssl->out_ctr + 8; + ssl->out_len = ssl->out_cid; + if( transform != NULL ) + ssl->out_len += transform->out_cid_len; +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_len = ssl->out_ctr + 8; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_iv = ssl->out_len + 2; + } + else +#endif + { + ssl->out_ctr = ssl->out_hdr - 8; + ssl->out_len = ssl->out_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->out_cid = ssl->out_len; +#endif + ssl->out_iv = ssl->out_hdr + 5; + } + + ssl->out_msg = ssl->out_iv; + /* Adjust out_msg to make space for explicit IV, if used. */ + if( transform != NULL ) + ssl->out_msg += ssl_transform_get_explicit_iv_len( transform ); +} + +/* Once ssl->in_hdr as the address of the beginning of the + * next incoming record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->in_hdr, + * and the caller has to make sure there's space for this. + */ + +void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ) +{ + /* This function sets the pointers to match the case + * of unprotected TLS/DTLS records, with both ssl->in_iv + * and ssl->in_msg pointing to the beginning of the record + * content. + * + * When decrypting a protected record, ssl->in_msg + * will be shifted to point to the beginning of the + * record plaintext. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* This sets the header pointers to match records + * without CID. When we receive a record containing + * a CID, the fields are shifted accordingly in + * ssl_parse_record_header(). */ + ssl->in_ctr = ssl->in_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_cid = ssl->in_ctr + 8; + ssl->in_len = ssl->in_cid; /* Default: no CID */ +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_len = ssl->in_ctr + 8; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + } + else +#endif + { + ssl->in_ctr = ssl->in_hdr - 8; + ssl->in_len = ssl->in_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_cid = ssl->in_len; +#endif + ssl->in_iv = ssl->in_hdr + 5; + } + + /* This will be adjusted at record decryption time. */ + ssl->in_msg = ssl->in_iv; +} + +/* + * Setup an SSL context + */ + +void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) +{ + /* Set the incoming and outgoing record pointers. */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->in_hdr = ssl->in_buf; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ssl->out_hdr = ssl->out_buf + 8; + ssl->in_hdr = ssl->in_buf + 8; + } + + /* Derive other internal pointers. */ + mbedtls_ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); + mbedtls_ssl_update_in_pointers ( ssl ); +} + +/* + * SSL get accessors + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) +{ + /* + * Case A: We're currently holding back + * a message for further processing. + */ + + if( ssl->keep_current_message == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); + return( 1 ); + } + + /* + * Case B: Further records are pending in the current datagram. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->in_left > ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); + return( 1 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Case C: A handshake message is being processed. + */ + + if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); + return( 1 ); + } + + /* + * Case D: An application data message is being processed + */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); + return( 1 ); + } + + /* + * In all other cases, the rest of the message can be dropped. + * As in ssl_get_next_record, this needs to be adapted if + * we implement support for multiple alerts in single records. + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); + return( 0 ); +} + + +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +{ + size_t transform_expansion = 0; + const mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned block_size; + + size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl ); + + if( transform == NULL ) + return( (int) out_hdr_len ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + { + case MBEDTLS_MODE_GCM: + case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_CHACHAPOLY: + case MBEDTLS_MODE_STREAM: + transform_expansion = transform->minlen; + break; + + case MBEDTLS_MODE_CBC: + + block_size = mbedtls_cipher_get_block_size( + &transform->cipher_ctx_enc ); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.1 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( transform->out_cid_len != 0 ) + transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + return( (int)( out_hdr_len + transform_expansion ) ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/* + * Check record counters and renegotiate if they're above the limit. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) +{ + size_t ep_len = mbedtls_ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len, + ssl->conf->renego_period + ep_len, 8 - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + { + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); + return( mbedtls_ssl_renegotiate( ssl ) ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + if( ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } + } +#endif + + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ret = ssl_check_ctr_renegotiate( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + /* Loop as long as no application data record is available */ + while( ssl->in_offt == NULL ) + { + /* Start timer if not already running */ + if( ssl->f_get_timer != NULL && + ssl->f_get_timer( ssl->p_timer ) == -1 ) + { + mbedtls_ssl_set_timer( ssl, ssl->conf->read_timeout ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); + + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + continue; + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + continue; + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) + { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = mbedtls_ssl_start_renegotiation( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", + ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + /* SSLv3 does not have a "no_renegotiation" warning, so + we send a fatal alert and abort the connection. */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + + /* At this point, we don't know whether the renegotiation has been + * completed or not. The cases to consider are the following: + * 1) The renegotiation is complete. In this case, no new record + * has been read yet. + * 2) The renegotiation is incomplete because the client received + * an application data record while awaiting the ServerHello. + * 3) The renegotiation is incomplete because the client received + * a non-handshake, non-application data message while awaiting + * the ServerHello. + * In each of these case, looping will be the proper action: + * - For 1), the next iteration will read a new record and check + * if it's application data. + * - For 2), the loop condition isn't satisfied as application data + * is present, hence continue is the same as break + * - For 3), the loop condition is satisfied and read_record + * will re-deliver the message that was held back by the client + * when expecting the ServerHello. + */ + continue; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->renego_max_records >= 0 ) + { + if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + + /* We're going to return something now, cancel timer, + * except if handshake (renegotiation) is in progress */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + mbedtls_ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* If we requested renego but received AppData, resend HelloRequest. + * Do it now, after setting in_offt, to avoid taking this branch + * again if ssl_write_hello_request() returns WANT_WRITE */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request", + ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + /* Zeroising the plaintext buffer to erase unused application data + from the memory. */ + mbedtls_platform_zeroize( ssl->in_offt, n ); + + if( ssl->in_msglen == 0 ) + { + /* all bytes consumed */ + ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } + else + { + /* more data available */ + ssl->in_offt += n; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer, taking care of max + * fragment length and buffer size. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); + const size_t max_len = (size_t) ret; + + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); + return( ret ); + } + + if( len > max_len ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " + "maximum fragment length: %" MBEDTLS_PRINTF_SIZET + " > %" MBEDTLS_PRINTF_SIZET, + len, max_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + else +#endif + len = max_len; + } + + if( ssl->out_left != 0 ) + { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + } + else + { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ + ssl->out_msglen = len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, len ); + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + return( (int) len ); +} + +/* + * Write application data, doing 1/n-1 splitting if necessary. + * + * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, + * then the caller will call us again with the same arguments, so + * remember whether we already did the split or not. + */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_split( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl->conf->cbc_record_splitting == + MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || + len <= 1 || + ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || + mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) + != MBEDTLS_MODE_CBC ) + { + return( ssl_write_real( ssl, buf, len ) ); + } + + if( ssl->split_done == 0 ) + { + if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 1; + } + + if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) + return( ret ); + ssl->split_done = 0; + + return( ret + 1 ); +} +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ + +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) +{ + if( transform == NULL ) + return; + +#if defined(MBEDTLS_ZLIB_SUPPORT) + deflateEnd( &transform->ctx_deflate ); + inflateEnd( &transform->ctx_inflate ); +#endif + + mbedtls_cipher_free( &transform->cipher_ctx_enc ); + mbedtls_cipher_free( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + mbedtls_md_free( &transform->md_ctx_enc ); + mbedtls_md_free( &transform->md_ctx_dec ); +#endif + + mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ) +{ + unsigned offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return; + + ssl_free_buffered_record( ssl ); + + for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + ssl_buffering_free_slot( ssl, offset ); +} + +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; + + if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + return; + + if( hs_buf->is_valid == 1 ) + { + hs->buffering.total_bytes_buffered -= hs_buf->data_len; + mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); + mbedtls_free( hs_buf->data ); + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Convert version numbers to/from wire format + * and, for DTLS, to/from TLS equivalent. + * + * For TLS this is the identity. + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: + * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + */ +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) + --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + + ver[0] = (unsigned char)( 255 - ( major - 2 ) ); + ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); + } + else +#else + ((void) transport); +#endif + { + ver[0] = (unsigned char) major; + ver[1] = (unsigned char) minor; + } +} + +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + *major = 255 - ver[0] + 2; + *minor = 255 - ver[1] + 1; + + if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) + ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + } + else +#else + ((void) transport); +#endif + { + *major = ver[0]; + *minor = ver[1]; + } +} + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_srv.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_srv.c new file mode 100644 index 0000000..2efb13c --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_srv.c @@ -0,0 +1,4855 @@ +/* + * SSLv3/TLSv1 server-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "constant_time_internal.h" +#include "mbedtls/constant_time.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ) +{ + if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + mbedtls_free( ssl->cli_id ); + + if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->cli_id, info, ilen ); + ssl->cli_id_len = ilen; + + return( 0 ); +} + +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ) +{ + conf->f_cookie_write = f_cookie_write; + conf->f_cookie_check = f_cookie_check; + conf->p_cookie = p_cookie; +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + if( len < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + p = buf + 2; + while( servername_list_size > 2 ) + { + hostname_len = ( ( p[1] << 8 ) | p[2] ); + if( hostname_len + 3 > servername_list_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl->conf->f_sni( ssl->conf->p_sni, + ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf ) +{ + if( conf->f_psk != NULL ) + return( 1 ); + + if( conf->psk_identity_len == 0 || conf->psk_identity == NULL ) + return( 0 ); + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) +{ + if( ssl->conf->f_psk != NULL ) + { + /* If we've used a callback to select the PSK, + * the static configuration is irrelevant. */ + + if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) ) + return( 1 ); + + return( 0 ); + } + + if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len || + buf[0] != ssl->verify_data_len || + mbedtls_ct_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* + * Status of the implementation of signature-algorithms extension: + * + * Currently, we are only considering the signature-algorithm extension + * to pick a ciphersuite which allows us to send the ServerKeyExchange + * message with a signature-hash combination that the user allows. + * + * We do *not* check whether all certificates in our certificate + * chain are signed with an allowed signature-hash pair. + * This needs to be done at a later stage. + * + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t sig_alg_list_size; + + const unsigned char *p; + const unsigned char *end = buf + len; + + mbedtls_md_type_t md_cur; + mbedtls_pk_type_t sig_cur; + + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( sig_alg_list_size + 2 != len || + sig_alg_list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Currently we only guarantee signing the ServerKeyExchange message according + * to the constraints specified in this extension (see above), so it suffices + * to remember only one suitable hash for each possible signature algorithm. + * + * This will change when we also consider certificate signatures, + * in which case we will need to remember the whole signature-hash + * pair list from the extension. + */ + + for( p = buf + 2; p < end; p += 2 ) + { + /* Silently ignore unknown signature or hash algorithms. */ + + if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" + " unknown sig alg encoding %d", p[1] ) ); + continue; + } + + /* Check if we support the hash the user proposes */ + md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); + if( md_cur == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " unknown hash alg encoding %d", p[0] ) ); + continue; + } + + if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) + { + mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " match sig %u and hash %u", + (unsigned) sig_cur, (unsigned) md_cur ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " + "hash alg %u not supported", (unsigned) md_cur ) ); + } + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const mbedtls_ecp_curve_info *curve_info, **curves; + + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Should never happen unless client duplicates the extension */ + if( ssl->handshake->curves != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Don't allow our peer to make us allocate too much memory, + * and leave room for a final 0 */ + our_size = list_size / 2 + 1; + if( our_size > MBEDTLS_ECP_DP_MAX ) + our_size = MBEDTLS_ECP_DP_MAX; + + if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); + + if( curve_info != NULL ) + { + *curves++ = curve_info; + our_size--; + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + list_size = buf[0]; + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl->handshake->ecjpake_ctx.point_format = p[0]; +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( ret ); + } + + /* Only mark the extension as OK when we're sure it is */ + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t peer_cid_len; + + /* CID extension only makes sense in DTLS */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + + if( len < 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + peer_cid_len = *buf++; + len--; + + if( len != peer_cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Ignore CID if the user has disabled its use. */ + if( ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + /* Leave ssl->handshake->cid_in_use in its default + * value of MBEDTLS_SSL_CID_DISABLED. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Client sent CID extension, but CID disabled" ) ); + return( 0 ); + } + + if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; + ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; + memcpy( ssl->handshake->peer_cid, buf, peer_cid_len ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Client CID", buf, peer_cid_len ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ((void) buf); + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_session session; + + mbedtls_ssl_session_init( &session ); + + if( ssl->conf->f_ticket_parse == NULL || + ssl->conf->f_ticket_write == NULL ) + { + return( 0 ); + } + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, len ) ); + + if( len == 0 ) + return( 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, + buf, len ) ) != 0 ) + { + mbedtls_ssl_session_free( &session ); + + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); + else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); + else + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); + + return( 0 ); + } + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform them we're accepting the ticket (RFC 5077 section 3.4) + */ + session.id_len = ssl->session_negotiate->id_len; + memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); + + mbedtls_ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); + + ssl->handshake->resume = 1; + + /* Don't send a new ticket after all, this one is OK */ + ssl->handshake->new_session_ticket = 0; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, cur_len, ours_len; + const unsigned char *theirs, *start, *end; + const char **ours; + + /* If ALPN not configured, just ignore the extension */ + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Validate peer's list (lengths) + */ + start = buf + 2; + end = buf + len; + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + /* Current identifier must fit in list */ + if( cur_len > (size_t)( end - theirs ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + + /* + * Use our order of preference + */ + for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) + { + ours_len = strlen( *ours ); + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + if( cur_len == ours_len && + memcmp( theirs, *ours, cur_len ) == 0 ) + { + ssl->alpn_chosen = *ours; + return( 0 ); + } + } + } + + /* If we get there, no match was found */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET; + size_t i,j; + size_t profile_length; + uint16_t mki_length; + /*! 2 bytes for profile length and 1 byte for mki len */ + const size_t size_of_lengths = 3; + + /* If use_srtp is not configured, just ignore the extension */ + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + { + return( 0 ); + } + + /* RFC5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + */ + + /* + * Min length is 5: at least one protection profile(2 bytes) + * and length(2 bytes) + srtp_mki length(1 byte) + * Check here that we have at least 2 bytes of protection profiles length + * and one of srtp_mki length + */ + if( len < size_of_lengths ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; + + /* first 2 bytes are protection profile length(in bytes) */ + profile_length = ( buf[0] << 8 ) | buf[1]; + buf += 2; + + /* The profile length cannot be bigger than input buffer size - lengths fields */ + if( profile_length > len - size_of_lengths || + profile_length % 2 != 0 ) /* profiles are 2 bytes long, so the length must be even */ + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + /* + * parse the extension list values are defined in + * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + */ + for( j = 0; j < profile_length; j += 2 ) + { + uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1]; + client_protection = mbedtls_ssl_check_srtp_profile_value( protection_profile_value ); + + if( client_protection != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + client_protection ) ) ); + } + else + { + continue; + } + /* check if suggested profile is in our list */ + for( i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) + { + if( client_protection == ssl->conf->dtls_srtp_profile_list[i] ) + { + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + client_protection ) ) ); + break; + } + } + if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET ) + break; + } + buf += profile_length; /* buf points to the mki length */ + mki_length = *buf; + buf++; + + if( mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH || + mki_length + profile_length + size_of_lengths != len ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* Parse the mki only if present and mki is supported locally */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED && + mki_length > 0 ) + { + ssl->dtls_srtp_info.mki_len = mki_length; + + memcpy( ssl->dtls_srtp_info.mki_value, buf, mki_length ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "using mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise + */ +#if defined(MBEDTLS_ECDSA_C) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_key_curve( mbedtls_pk_context *pk, + const mbedtls_ecp_curve_info **curves ) +{ + const mbedtls_ecp_curve_info **crv = curves; + mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 0 ); + crv++; + } + + return( -1 ); +} +#endif /* MBEDTLS_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_pick_cert( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) +{ + mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; + mbedtls_pk_type_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + uint32_t flags; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->conf->key_cert; + + if( pk_alg == MBEDTLS_PK_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); + + if( list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); + return( -1 ); + } + + for( cur = list; cur != NULL; cur = cur->next ) + { + flags = 0; + MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", + cur->cert ); + + if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); + continue; + } + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + * + * It also allows the user to provision different certificates for + * different uses based on keyUsage, eg if they want to avoid signing + * and decrypting with the same RSA key. + */ + if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, + MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " + "(extended) key usage extension" ) ); + continue; + } + +#if defined(MBEDTLS_ECDSA_C) + if( pk_alg == MBEDTLS_PK_ECDSA && + ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); + continue; + } +#endif + + /* + * Try to select a SHA-1 certificate for pre-1.2 clients, but still + * present them a SHA-higher cert rather than failing if it's the only + * one we got that satisfies the other conditions. + */ + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && + cur->cert->sig_md != MBEDTLS_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " + "sha-2 with pre-TLS 1.2 client" ) ); + continue; + } + } + + /* If we get there, we got a winner */ + break; + } + + if( cur == NULL ) + cur = fallback; + + /* Do not update ssl->handshake->key_cert unless there is a match */ + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", + ssl->handshake->key_cert->cert ); + return( 0 ); + } + + return( -1 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, + const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) +{ + const mbedtls_ssl_ciphersuite_t *suite_info; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_pk_type_t sig_type; +#endif + + suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %#04x (%s)", + (unsigned int) suite_id, suite_info->name ) ); + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 0 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " + "not configured or ext missing" ) ); + return( 0 ); + } +#endif + + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no common elliptic curve" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); + if( sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %u", (unsigned) sig_type ) ); + return( 0 ); + } + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no suitable certificate" ) ); + return( 0 ); + } +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + unsigned int i, j; + size_t n; + unsigned int ciph_len, sess_len, chal_len; + unsigned char *buf, *p; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + buf = ssl->in_hdr; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", + buf[2] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", + ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", + buf[3], buf[4] ) ); + + /* + * SSLv2 Client Hello + * + * Record layer: + * 0 . 1 message length + * + * SSL layer: + * 2 . 2 message type + * 3 . 4 protocol version + */ + if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || + buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; + + if( n < 17 || n > 512 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) + ? buf[4] : ssl->conf->max_minor_ver; + + if( ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + ssl->handshake->max_major_ver = buf[3]; + ssl->handshake->max_minor_ver = buf[4]; + + if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->handshake->update_checksum( ssl, buf + 2, n ); + + buf = ssl->in_msg; + n = ssl->in_left - 5; + + /* + * 0 . 1 ciphersuitelist length + * 2 . 3 session id length + * 4 . 5 challenge length + * 6 . .. ciphersuitelist + * .. . .. session id + * .. . .. challenge + */ + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); + + ciph_len = ( buf[0] << 8 ) | buf[1]; + sess_len = ( buf[2] << 8 ) | buf[3]; + chal_len = ( buf[4] << 8 ) | buf[5]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %u, sess_len: %u, chal_len: %u", + ciph_len, sess_len, chal_len ) ); + + /* + * Make sure each parameter length is valid + */ + if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( sess_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( chal_len < 8 || chal_len > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( n != 6 + ciph_len + sess_len + chal_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + 6, ciph_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", + buf + 6 + ciph_len, sess_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", + buf + 6 + ciph_len + sess_len, chal_len ); + + p = buf + 6 + ciph_len; + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); + + p += sess_len; + memset( ssl->handshake->randbytes, 0, 64 ); + memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) + { + if( p[0] == 0 && + MBEDTLS_GET_UINT16_BE(p, 1) != MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) +#endif + { + if( p[0] != 0 || + MBEDTLS_GET_UINT16_BE(p, 1) != ciphersuites[i] ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite_v2; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite_v2: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->handshake->ciphersuite_info = ciphersuite_info; + + /* + * SSLv2 Client Hello relevant renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->in_left = 0; + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ + +/* This function doesn't alert on errors that happen early during + ClientHello parsing because they might indicate that the client is + not talking SSL/TLS at all and would not understand our alert. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + size_t i, j; + size_t ciph_offset, comp_offset, ext_offset; + size_t msg_len, ciph_len, sess_len, comp_len, ext_len; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + size_t cookie_offset, cookie_len; +#endif + unsigned char *buf, *p, *ext; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int major, minor; + + /* If there is no signature-algorithm extension present, + * we need to fall back to the default values for allowed + * signature-hash pairs. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + int sig_hash_alg_ext_present = 0; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +read_record_header: +#endif + /* + * If renegotiating, then the input was read with mbedtls_ssl_read_record(), + * otherwise read it ourselves manually in order to support SSLv2 + * ClientHello, which doesn't use the same record layer format. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_hdr; + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) +#endif + if( ( buf[0] & 0x80 ) != 0 ) + return( ssl_parse_client_hello_v2( ssl ) ); +#endif + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_in_hdr_len( ssl ) ); + + /* + * SSLv3/TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 11 DTLS: epoch + record sequence number + * 3 . 4 message length + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", + buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", + ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", + buf[1], buf[2] ) ); + + mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); + + /* According to RFC 5246 Appendix E.1, the version here is typically + * "{03,00}, the lowest version number supported by the client, [or] the + * value of ClientHello.client_version", so the only meaningful check here + * is the major version shouldn't be less than 3 */ + if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* For DTLS if this is the initial handshake, remember the client sequence + * number to use it in our next message (RFC 6347 4.2.1) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + /* Epoch should be 0 for initial handshakes */ + if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); + ssl->next_record_offset = 0; + ssl->in_left = 0; + goto read_record_header; + } + + /* No MAC to check yet, so we can update right now */ + mbedtls_ssl_dtls_replay_update( ssl ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Set by mbedtls_ssl_read_record() */ + msg_len = ssl->in_hslen; + } + else +#endif + { + if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_in_hdr_len( ssl ) + msg_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + } + + buf = ssl->in_msg; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); + + ssl->handshake->update_checksum( ssl, buf, msg_len ); + + /* + * Handshake layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 DTLS only: message sequence number + * 6 . 8 DTLS only: fragment offset + * 9 . 11 DTLS only: fragment length + */ + if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + + if( buf[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != 0", + (unsigned) buf[1] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + /* We don't support fragmentation of ClientHello (yet?) */ + if( msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != %u + %u", + (unsigned) msg_len, + (unsigned) mbedtls_ssl_hs_hdr_len( ssl ), + (unsigned) ( buf[2] << 8 ) | buf[3] ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* + * Copy the client's handshake message_seq on initial handshakes, + * check sequence number on renego. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* This couldn't be done in ssl_prepare_handshake_record() */ + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + + if( cli_msg_seq != ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " + "%u (expected %u)", cli_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->in_msg_seq++; + } + else +#endif + { + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + ssl->handshake->out_msg_seq = cli_msg_seq; + ssl->handshake->in_msg_seq = cli_msg_seq + 1; + } + + /* + * For now we don't support fragmentation, so make sure + * fragment_offset == 0 and fragment_length == length + */ + MBEDTLS_SSL_DEBUG_MSG( + 4, ( "fragment_offset=%u fragment_length=%u length=%u", + (unsigned) ( ssl->in_msg[6] << 16 | ssl->in_msg[7] << 8 | ssl->in_msg[8] ), + (unsigned) ( ssl->in_msg[9] << 16 | ssl->in_msg[10] << 8 | ssl->in_msg[11] ), + (unsigned) ( ssl->in_msg[1] << 16 | ssl->in_msg[2] << 8 | ssl->in_msg[3] ) ) ); + if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || + memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + buf += mbedtls_ssl_hs_hdr_len( ssl ); + msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * ClientHello layer: + * 0 . 1 protocol version + * 2 . 33 random bytes (starting with 4 bytes of Unix time) + * 34 . 35 session id length (1 byte) + * 35 . 34+x session id + * 35+x . 35+x DTLS only: cookie length (1 byte) + * 36+x . .. DTLS only: cookie + * .. . .. ciphersuite list length (2 bytes) + * .. . .. ciphersuite list + * .. . .. compression alg. list length (1 byte) + * .. . .. compression alg. list + * .. . .. extensions length (2 bytes, optional) + * .. . .. extensions (optional) + */ + + /* + * Minimal length (with everything empty and extensions omitted) is + * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can + * read at least up to session id length without worrying. + */ + if( msg_len < 38 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Check and save the protocol version + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); + + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf ); + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->conf->max_major_ver ) + { + ssl->major_ver = ssl->conf->max_major_ver; + ssl->minor_ver = ssl->conf->max_minor_ver; + } + else if( ssl->minor_ver > ssl->conf->max_minor_ver ) + ssl->minor_ver = ssl->conf->max_minor_ver; + + /* + * Save client random (inc. Unix time) + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); + + memcpy( ssl->handshake->randbytes, buf + 2, 32 ); + + /* + * Check the session ID length and save session ID + */ + sess_len = buf[34]; + + if( sess_len > sizeof( ssl->session_negotiate->id ) || + sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); + + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 35, + ssl->session_negotiate->id_len ); + + /* + * Check the cookie length and content + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + cookie_offset = 35 + sess_len; + cookie_len = buf[cookie_offset]; + + if( cookie_offset + 1 + cookie_len + 2 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + buf + cookie_offset + 1, cookie_len ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->f_cookie_check != NULL +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + buf + cookie_offset + 1, cookie_len, + ssl->cli_id, ssl->cli_id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); + ssl->handshake->verify_cookie_len = 1; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); + ssl->handshake->verify_cookie_len = 0; + } + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + /* We know we didn't send a cookie, so it should be empty */ + if( cookie_len != 0 ) + { + /* This may be an attacker's probe, so don't send an alert */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); + } + + /* + * Check the ciphersuitelist length (will be parsed later) + */ + ciph_offset = cookie_offset + 1 + cookie_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + ciph_offset = 35 + sess_len; + + ciph_len = ( buf[ciph_offset + 0] << 8 ) + | ( buf[ciph_offset + 1] ); + + if( ciph_len < 2 || + ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ + ( ciph_len % 2 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + ciph_offset + 2, ciph_len ); + + /* + * Check the compression algorithms length and pick one + */ + comp_offset = ciph_offset + 2 + ciph_len; + + comp_len = buf[comp_offset]; + + if( comp_len < 1 || + comp_len > 16 || + comp_len + comp_offset + 1 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", + buf + comp_offset + 1, comp_len ); + + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#if defined(MBEDTLS_ZLIB_SUPPORT) + for( i = 0; i < comp_len; ++i ) + { + if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; + break; + } + } +#endif + + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#endif + + /* Do not parse the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + /* + * Check the extension length + */ + ext_offset = comp_offset + 1 + comp_len; + if( msg_len > ext_offset ) + { + if( msg_len < ext_offset + 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ext_len = ( buf[ext_offset + 0] << 8 ) + | ( buf[ext_offset + 1] ); + + if( msg_len != ext_offset + 2 + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + } + else + ext_len = 0; + + ext = buf + ext_offset + 2; + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); + + while( ext_len != 0 ) + { + unsigned int ext_id; + unsigned int ext_size; + if ( ext_len < 4 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); + ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + switch( ext_id ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->conf->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + + sig_hash_alg_ext_present = 1; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); + + ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); + + ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + case MBEDTLS_TLS_EXT_CID: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) ); + + ret = ssl_parse_cid_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); + + ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + case MBEDTLS_TLS_EXT_USE_SRTP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) ); + + ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %u (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + } +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( MBEDTLS_GET_UINT16_BE( p, 0 ) == MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); + + if( ssl->minor_ver < ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); + + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + break; + } + } +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + + /* + * Try to fall back to default hash SHA1 if the client + * hasn't provided any preferred signature-hash combinations. + */ + if( sig_hash_alg_ext_present == 0 ) + { + mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; + + if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) + md_default = MBEDTLS_MD_NONE; + + mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions + * and certificate from the SNI callback triggered by the SNI extension.) + */ + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) + for( i = 0; ciphersuites[i] != 0; i++ ) +#else + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) +#endif + { + if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + +have_ciphersuite: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->handshake->ciphersuite_info = ciphersuite_info; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + /* Debugging-only output for testsuite */ +#if defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); + if( sig_alg != MBEDTLS_PK_NONE ) + { + mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " + "%u - should not happen", (unsigned) sig_alg ) ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_TRUNCATED_HMAC, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static void ssl_write_cid_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + size_t ext_len; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + + *olen = 0; + + /* Skip writing the extension if we don't want to use it or if + * the client hasn't offered it. */ + if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED ) + return; + + /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX + * which is at most 255, so the increment cannot overflow. */ + if( end < p || (size_t)( end - p ) < (unsigned)( ssl->own_cid_len + 5 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding CID extension" ) ); + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_CID, p, 0 ); + p += 2; + ext_len = (size_t) ssl->own_cid_len + 1; + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2; + + *p++ = (uint8_t) ssl->own_cid_len; + memcpy( p, ssl->own_cid, ssl->own_cid_len ); + + *olen = ssl->own_cid_len + 5; +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const mbedtls_ssl_ciphersuite_t *suite = NULL; + const mbedtls_cipher_info_t *cipher = NULL; + + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; + + /* + * RFC 7366: "If a server receives an encrypt-then-MAC request extension + * from a client and then selects a stream or Authenticated Encryption + * with Associated Data (AEAD) ciphersuite, it MUST NOT send an + * encrypt-then-MAC response extension back to the client." + */ + if( ( suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ) ) == NULL || + ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || + cipher->mode != MBEDTLS_MODE_CBC ) + { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; + } + + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0 ); + p += 2; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + *p++ = 0x00; + *p++ = 0x01; + *p++ = 0x00; + } + + *olen = p - buf; +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly computation if not needed */ + if( ssl->handshake->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 ); + p += 2; + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 ); + p += 2; + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN ) +static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); + + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, buf, 0); + + *olen = 7 + strlen( ssl->alpn_chosen ); + + MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 ); + + MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 ); + + buf[6] = MBEDTLS_BYTE_0( *olen - 7 ); + + memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP ) && defined(MBEDTLS_SSL_PROTO_DTLS) +static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + size_t mki_len = 0, ext_len = 0; + uint16_t profile_value = 0; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + + *olen = 0; + + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding use_srtp extension" ) ); + + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + + /* The extension total size is 9 bytes : + * - 2 bytes for the extension tag + * - 2 bytes for the total size + * - 2 bytes for the protection profile length + * - 2 bytes for the protection profile + * - 1 byte for the mki length + * + the actual mki length + * Check we have enough room in the output buffer */ + if( (size_t)( end - buf ) < mki_len + 9 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* extension */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0 ); + /* + * total length 5 and mki value: only one profile(2 bytes) + * and length(2 bytes) and srtp_mki ) + */ + ext_len = 5 + mki_len; + MBEDTLS_PUT_UINT16_BE( ext_len, buf, 2 ); + + /* protection profile length: 2 */ + buf[4] = 0x00; + buf[5] = 0x02; + profile_value = mbedtls_ssl_check_srtp_profile_value( + ssl->dtls_srtp_info.chosen_dtls_srtp_profile ); + if( profile_value != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_PUT_UINT16_BE( profile_value, buf, 6 ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "use_srtp extension invalid profile" ) ); + return; + } + + buf[8] = mki_len & 0xFF; + memcpy( &buf[9], ssl->dtls_srtp_info.mki_value, mki_len ); + + *olen = 9 + mki_len; +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = ssl->out_msg + 4; + unsigned char *cookie_len_byte; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + + /* The RFC is not clear on this point, but sending the actual negotiated + * version looks like the most interoperable thing to do. */ + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + p += 2; + + /* If we get here, f_cookie_check is not null */ + if( ssl->conf->f_cookie_write == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Skip length byte until we know the length */ + cookie_len_byte = p++; + + if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, + ssl->cli_id, ssl->cli_id_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); + return( ret ); + } + + *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); + + ssl->out_msglen = p - ssl->out_msg; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + + ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +static void ssl_handle_id_based_session_resumption( mbedtls_ssl_context *ssl ) +{ + int ret; + mbedtls_ssl_session session_tmp; + mbedtls_ssl_session * const session = ssl->session_negotiate; + + /* Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). */ + if( ssl->handshake->resume == 1 ) + return; + if( session->id_len == 0 ) + return; + if( ssl->conf->f_get_cache == NULL ) + return; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + return; +#endif + + mbedtls_ssl_session_init( &session_tmp ); + + session_tmp.id_len = session->id_len; + memcpy( session_tmp.id, session->id, session->id_len ); + + ret = ssl->conf->f_get_cache( ssl->conf->p_cache, + &session_tmp ); + if( ret != 0 ) + goto exit; + + if( session->ciphersuite != session_tmp.ciphersuite || + session->compression != session_tmp.compression ) + { + /* Mismatch between cached and negotiated session */ + goto exit; + } + + /* Move semantics */ + mbedtls_ssl_session_free( session ); + *session = session_tmp; + memset( &session_tmp, 0, sizeof( session_tmp ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); + ssl->handshake->resume = 1; + +exit: + + mbedtls_ssl_session_free( &session_tmp ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie_len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ssl_write_hello_verify_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + MBEDTLS_PUT_UINT32_BE( t, p, 0 ); + p += 4; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %" MBEDTLS_PRINTF_LONGLONG, + (long long) t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + ssl_handle_id_based_session_resumption( ssl ); + + if( ssl->handshake->resume == 0 ) + { + /* + * New session, create a new session id, + * unless we're about to issue a session ticket + */ + ssl->state++; + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->id_len = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->id_len = n = 32; + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->id_len; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions + */ + *p++ = (unsigned char) ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_PUT_UINT16_BE( ssl->session_negotiate->ciphersuite, p, 0 ); + p += 2; + *p++ = MBEDTLS_BYTE_0( ssl->session_negotiate->compression ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + (unsigned int) ssl->session_negotiate->compression ) ); + + /* Do not write the extensions if the protocol is SSLv3 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) + { +#endif + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl_write_cid_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if ( mbedtls_ssl_ciphersuite_uses_ec( + mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) ) + { + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + ssl_write_use_srtp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, + ext_len ) ); + + if( ext_len > 0 ) + { + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2 + ext_len; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + } +#endif + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; + + ret = mbedtls_ssl_write_handshake_msg( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + uint16_t dn_size, total_dn_size; /* excluding length bytes */ + size_t ct_len, sa_len; /* including length bytes */ + unsigned char *buf, *p; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + const mbedtls_x509_crt *crt; + int authmode; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; + else +#endif + authmode = ssl->conf->authmode; + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) || + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + buf = ssl->out_msg; + p = buf + 4; + + /* + * Supported certificate types + * + * ClientCertificateType certificate_types<1..2^8-1>; + * enum { (255) } ClientCertificateType; + */ + ct_len = 0; + +#if defined(MBEDTLS_RSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Add signature_algorithms for verify (TLS 1.2) + * + * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * enum { (255) } HashAlgorithm; + * enum { (255) } SignatureAlgorithm; + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + const int *cur; + + /* + * Supported signature algorithms + */ + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + { + unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); + + if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) + continue; + +#if defined(MBEDTLS_RSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif + } + + MBEDTLS_PUT_UINT16_BE( sa_len, p, 0 ); + sa_len += 2; + p += sa_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; + + total_dn_size = 0; + + if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) + { + /* NOTE: If trusted certificates are provisioned + * via a CA callback (configured through + * `mbedtls_ssl_conf_ca_cb()`, then the + * CertificateRequest is currently left empty. */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; + + while( crt != NULL && crt->version != 0 ) + { + /* It follows from RFC 5280 A.1 that this length + * can be represented in at most 11 bits. */ + dn_size = (uint16_t) crt->subject_raw.len; + + if( end < p || (size_t)( end - p ) < 2 + (size_t) dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + MBEDTLS_PUT_UINT16_BE( dn_size, p, 0 ); + p += 2; + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; + MBEDTLS_PUT_UINT16_BE( total_dn_size, ssl->out_msg, 4 + ct_len + sa_len ); + + ret = mbedtls_ssl_write_handshake_msg( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_context *own_key = mbedtls_ssl_own_key( ssl ); + + /* Check if the key is a transparent ECDH key. + * This also ensures that it is safe to call mbedtls_pk_ec(). */ + if( mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY && + mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY_DH ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, + mbedtls_pk_ec( *own_key ), + MBEDTLS_ECDH_OURS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; + size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN + - sig_start ); + int ret = ssl->conf->f_async_resume( ssl, + sig_start, signature_len, sig_max_len ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); + return( ret ); +} +#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + +/* Prepare the ServerKeyExchange message, up to and including + * calculating the signature if any, but excluding formatting the + * signature and sending the message. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + unsigned char *dig_signed = NULL; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ + + (void) ciphersuite_info; /* unused in some configurations */ +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + (void) signature_len; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + + ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ + + /* + * + * Part 1: Provide key exchange parameters for chosen ciphersuite. + * + */ + + /* + * - ECJPAKE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + ret = mbedtls_ecjpake_write_round_two( + &ssl->handshake->ecjpake_ctx, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ssl->out_msglen += len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + + /* + * For (EC)DHE key exchanges with PSK, parameters are prefixed by support + * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, + * we use empty support identity hints here. + **/ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + ssl->out_msg[ssl->out_msglen++] = 0x00; + ssl->out_msg[ssl->out_msglen++] = 0x00; + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + + /* + * - DHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx, + &ssl->conf->dhm_P, + &ssl->conf->dhm_G ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret ); + return( ret ); + } + + if( ( ret = mbedtls_dhm_make_params( + &ssl->handshake->dhm_ctx, + (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), + ssl->out_msg + ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */ + + /* + * - ECDHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const mbedtls_ecp_curve_info **curve = NULL; + const mbedtls_ecp_group_id *gid; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* Match our preference list against the offered curves */ + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->grp_id == *gid ) + goto curve_matching_done; + +curve_matching_done: + if( curve == NULL || *curve == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx, + (*curve)->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_make_params( + &ssl->handshake->ecdh_ctx, &len, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ + + /* + * + * Part 2: For key exchanges involving the server signing the + * exchange parameters, compute and add the signature here. + * + */ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + size_t hashlen = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char hash[PSA_HASH_MAX_SIZE]; +#else + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; +#endif + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * 2.1: Choose hash algorithm: + * A: For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. + * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 + * (RFC 4492, Sec. 5.4) + * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) + */ + + mbedtls_md_type_t md_alg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t sig_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* A: For TLS 1.2, obey signature-hash-algorithm extension + * (RFC 5246, Sec. 7.4.1.4.1). */ + if( sig_alg == MBEDTLS_PK_NONE || + ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + /* (... because we choose a cipher suite + * only if there is a matching hash.) */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + /* B: Default hash SHA1 */ + md_alg = MBEDTLS_MD_SHA1; + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + { + /* C: MD5 + SHA1 */ + md_alg = MBEDTLS_MD_NONE; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %u for signing", (unsigned) md_alg ) ); + + /* + * 2.2: Compute the hash to be signed + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( md_alg == MBEDTLS_MD_NONE ) + { + hashlen = 36; + ret = mbedtls_ssl_get_key_exchange_md_ssl_tls( ssl, hash, + dig_signed, + dig_signed_len ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + dig_signed, + dig_signed_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); + + /* + * 2.3: Compute and add the signature + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * For TLS 1.2, we need to specify signature and hash algorithm + * explicitly through a prefix to the signature. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * struct { + * SignatureAndHashAlgorithm algorithm; + * opaque signature<0..2^16-1>; + * } DigitallySigned; + * + */ + + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_hash_from_md_alg( md_alg ); + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_sig_from_pk_alg( sig_alg ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_sign_start != NULL ) + { + ret = ssl->conf->f_async_sign_start( ssl, + mbedtls_ssl_own_cert( ssl ), + md_alg, hash, hashlen ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_sign was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_server_key_exchange( ssl, signature_len ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), + md_alg, hash, hashlen, + ssl->out_msg + ssl->out_msglen + 2, + signature_len, + ssl->conf->f_rng, + ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + + return( 0 ); +} + +/* Prepare the ServerKeyExchange message and send it. For ciphersuites + * that do not include a ServerKeyExchange message, do nothing. Either + * way, if successful, move on to the next step in the SSL state + * machine. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t signature_len = 0; +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) + /* Extract static ECDH parameters and abort if ServerKeyExchange + * is not needed. */ + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ret = ssl_get_ecdh_params_from_cert( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ + + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already prepared the message and there is an ongoing + * signature operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) ); + ret = ssl_resume_server_key_exchange( ssl, &signature_len ); + } + else +#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + { + /* ServerKeyExchange is needed. Prepare the message. */ + ret = ssl_prepare_server_key_exchange( ssl, &signature_len ); + } + + if( ret != 0 ) + { + /* If we're starting to write a new message, set ssl->out_msglen + * to 0. But if we're resuming after an asynchronous message, + * out_msglen is the amount of data written so far and mst be + * preserved. */ + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) ); + else + ssl->out_msglen = 0; + return( ret ); + } + + /* If there is a signature, write its length. + * ssl_prepare_server_key_exchange already wrote the signature + * itself at its proper place in the output buffer. */ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( signature_len != 0 ) + { + ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_1( signature_len ); + ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_0( signature_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", + ssl->out_msg + ssl->out_msglen, + signature_len ); + + /* Skip over the already-written signature */ + ssl->out_msglen += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + + /* Add header and send. */ + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + return( 0 ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + *p += n; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = ssl->conf->f_async_resume( ssl, + peer_pms, peer_pmslen, peer_pmssize ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret ); + return( ret ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl ); + mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk; + size_t len = mbedtls_pk_get_len( public_key ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already started decoding the message and there is an ongoing + * decryption operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) ); + return( ssl_resume_decrypt_pms( ssl, + peer_pms, peer_pmslen, peer_pmssize ) ); + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + /* + * Prepare to decrypt the premaster using own private RSA key + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if ( p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + if( *p++ != MBEDTLS_BYTE_1( len ) || + *p++ != MBEDTLS_BYTE_0( len ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + } +#endif + + if( p + len != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + /* + * Decrypt the premaster secret + */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_decrypt_start != NULL ) + { + ret = ssl->conf->f_async_decrypt_start( ssl, + mbedtls_ssl_own_cert( ssl ), + p, len ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_decrypt_start was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_decrypt_pms( ssl, + peer_pms, + peer_pmslen, + peer_pmssize ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + ret = mbedtls_pk_decrypt( private_key, p, len, + peer_pms, peer_pmslen, peer_pmssize, + ssl->conf->f_rng, ssl->conf->p_rng ); + return( ret ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + /* In case of a failure in decryption, the decryption may write less than + * 2 bytes of output, but we always read the first two bytes. It doesn't + * matter in the end because diff will be nonzero in that case due to + * ret being nonzero, and we only care whether diff is 0. + * But do initialize peer_pms and peer_pmslen for robustness anyway. This + * also makes memory analyzers happy (don't access uninitialized memory, + * even if it's an unsigned char). */ + peer_pms[0] = peer_pms[1] = ~0; + peer_pmslen = 0; + + ret = ssl_decrypt_encrypted_pms( ssl, p, end, + peer_pms, + &peer_pmslen, + sizeof( peer_pms ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + return( ret ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* Avoid data-dependent branches while checking for invalid + * padding, to protect against timing-based Bleichenbacher-type + * attacks. */ + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + mask = mbedtls_ct_uint_mask( diff ); + + /* + * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding + * must not cause the connection to end immediately; instead, send a + * bad_record_mac later in the handshake. + * To protect against timing-based variants of the attack, we must + * not have any branch that depends on whether the decryption was + * successful. In particular, always generate the fake premaster secret, + * regardless of whether it will ultimately influence the output or not. + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); + if( ret != 0 ) + { + /* It's ok to abort on an RNG failure, since this does not reveal + * anything about the RSA decryption. */ + return( ret ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( diff != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); +#endif + + if( sizeof( ssl->handshake->premaster ) < pms_offset || + sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->handshake->pmslen = 48; + + /* Set pms to either the true or the fake PMS, without + * data-dependent branches. */ + for( i = 0; i < ssl->handshake->pmslen; i++ ) + pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + uint16_t n; + + if( ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( end - *p < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( n == 0 || n > end - *p ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->conf->f_psk != NULL ) + { + if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + else + { + /* Identity is not a big secret since clients send it in the clear, + * but treat it carefully anyway, just in case */ + if( n != ssl->conf->psk_identity_len || + mbedtls_ct_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) + { + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); + return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char *p, *end; + + ciphersuite_info = ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) + if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) && + ( ssl->handshake->async_in_progress != 0 ) ) + { + /* We've already read a record and there is an asynchronous + * operation in progress to decrypt it. So skip reading the + * record. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) ); + } + else +#endif + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* For opaque PSKs, we perform the PSK-to-MS derivation automatically + * and skip the intermediate PMS. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) ); + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ssl->handshake->async_in_progress != 0 ) + { + /* There is an asynchronous operation in progress to + * decrypt the encrypted premaster secret, so skip + * directly to resuming this operation. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) ); + /* Update p to skip the PSK identity. ssl_parse_encrypted_pms + * won't actually use it, but maintain p anyway for robustness. */ + p += ssl->conf->psk_identity_len + 2; + } + else +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } +#endif + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } +#endif + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } +#endif + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t pk_alg; +#endif + mbedtls_md_type_t md_alg; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + mbedtls_pk_context * peer_pk; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert_digest == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* Read the message without adding it to the checksum */ + ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ ); + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret ); + return( ret ); + } + + ssl->state++; + + /* Process the message contents */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * struct { + * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only + * opaque signature<0..2^16-1>; + * } DigitallySigned; + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + md_alg = MBEDTLS_MD_NONE; + hashlen = 36; + + /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ + if( mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECDSA ) ) + { + hash_start += 16; + hashlen -= 16; + md_alg = MBEDTLS_MD_SHA1; + } + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || + MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Hash + */ + md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); + + if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + +#if !defined(MBEDTLS_MD_SHA1) + if( MBEDTLS_MD_SHA1 == md_alg ) + hash_start += 16; +#endif + + /* Info from md_alg will be used instead */ + hashlen = 0; + + i++; + + /* + * Signature + */ + if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( !mbedtls_pk_can_do( peer_pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + i++; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; + i += 2; + + if( i + sig_len != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); + } + + /* Calculate hash and verify signature */ + { + size_t dummy_hlen; + ssl->handshake->calc_verify( ssl, hash, &dummy_hlen ); + } + + if( ( ret = mbedtls_pk_verify( peer_pk, + md_alg, hash_start, hashlen, + ssl->in_msg + i, sig_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + + mbedtls_ssl_update_handshake_status( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tlen; + uint32_t lifetime; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 4 . 7 ticket_lifetime_hint (0 = unspecified) + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + + if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, + ssl->session_negotiate, + ssl->out_msg + 10, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, + &tlen, &lifetime ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); + tlen = 0; + } + + MBEDTLS_PUT_UINT32_BE( lifetime, ssl->out_msg, 4 ); + MBEDTLS_PUT_UINT16_BE( tlen, ssl->out_msg, 8 ); + ssl->out_msglen = 10 + tlen; + + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +#endif + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_SRV_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c new file mode 100644 index 0000000..e0126cc --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_ticket.c @@ -0,0 +1,406 @@ +/* + * TLS server tickets callbacks implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TICKET_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_internal.h" +#include "mbedtls/ssl_ticket.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include + +/* + * Initialize context + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +#define MAX_KEY_BYTES 32 /* 256 bits */ + +#define TICKET_KEY_NAME_BYTES 4 +#define TICKET_IV_BYTES 12 +#define TICKET_CRYPT_LEN_BYTES 2 +#define TICKET_AUTH_TAG_BYTES 16 + +#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES + \ + TICKET_AUTH_TAG_BYTES ) +#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES ) + +/* + * Generate/update a key + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, + unsigned char index ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MAX_KEY_BYTES]; + mbedtls_ssl_ticket_key *key = ctx->keys + index; + +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = (uint32_t) mbedtls_time( NULL ); +#endif + + if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) + return( ret ); + + if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) + return( ret ); + + /* With GCM and CCM, same context can encrypt & decrypt */ + ret = mbedtls_cipher_setkey( &key->ctx, buf, + mbedtls_cipher_get_key_bitlen( &key->ctx ), + MBEDTLS_ENCRYPT ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Rotate/generate keys if necessary + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) +{ +#if !defined(MBEDTLS_HAVE_TIME) + ((void) ctx); +#else + if( ctx->ticket_lifetime != 0 ) + { + uint32_t current_time = (uint32_t) mbedtls_time( NULL ); + uint32_t key_time = ctx->keys[ctx->active].generation_time; + + if( current_time >= key_time && + current_time - key_time < ctx->ticket_lifetime ) + { + return( 0 ); + } + + ctx->active = 1 - ctx->active; + + return( ssl_ticket_gen_key( ctx, ctx->active ) ); + } + else +#endif /* MBEDTLS_HAVE_TIME */ + return( 0 ); +} + +/* + * Setup context for actual use + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; + + ctx->ticket_lifetime = lifetime; + + cipher_info = mbedtls_cipher_info_from_type( cipher); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cipher_info->mode != MBEDTLS_MODE_GCM && + cipher_info->mode != MBEDTLS_MODE_CCM ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx, + cipher_info, TICKET_AUTH_TAG_BYTES ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + return( ret ); + /* We don't yet expect to support all ciphers through PSA, + * so allow fallback to ordinary mbedtls_cipher_setup(). */ + if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx, + cipher_info, TICKET_AUTH_TAG_BYTES ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + return( ret ); + if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || + ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Create session ticket, with the following structure: + * + * struct { + * opaque key_name[4]; + * opaque iv[12]; + * opaque encrypted_state<0..2^16-1>; + * opaque tag[16]; + * } ticket; + * + * The key_name, iv, and length of encrypted_state are the additional + * authenticated data. + */ + +int mbedtls_ssl_ticket_write( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *ticket_lifetime ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = start; + unsigned char *iv = start + TICKET_KEY_NAME_BYTES; + unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; + unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; + size_t clear_len, ciph_len; + + *tlen = 0; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, + * in addition to session itself, that will be checked when writing it. */ + MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + key = &ctx->keys[ctx->active]; + + *ticket_lifetime = ctx->ticket_lifetime; + + memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES ); + + if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 ) + goto cleanup; + + /* Dump session state */ + if( ( ret = mbedtls_ssl_session_save( session, + state, end - state, + &clear_len ) ) != 0 || + (unsigned long) clear_len > 65535 ) + { + goto cleanup; + } + MBEDTLS_PUT_UINT16_BE( clear_len, state_len_bytes, 0 ); + + /* Encrypt and authenticate */ + if( ( ret = mbedtls_cipher_auth_encrypt_ext( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, + state, end - state, &ciph_len, + TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + goto cleanup; + } + if( ciph_len != clear_len + TICKET_AUTH_TAG_BYTES ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES; + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Select key based on name + */ +static mbedtls_ssl_ticket_key *ssl_ticket_select_key( + mbedtls_ssl_ticket_context *ctx, + const unsigned char name[4] ) +{ + unsigned char i; + + for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) + if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) + return( &ctx->keys[i] ); + + return( NULL ); +} + +/* + * Load session ticket (see mbedtls_ssl_ticket_write for structure) + */ +int mbedtls_ssl_ticket_parse( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = buf; + unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; + unsigned char *enc_len_p = iv + TICKET_IV_BYTES; + unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; + size_t enc_len, clear_len; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( len < TICKET_MIN_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; + + if( len != TICKET_MIN_LEN + enc_len ) + { + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + goto cleanup; + } + + /* Select key */ + if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) + { + /* We can't know for sure but this is a likely option unless we're + * under attack - this is only informative anyway */ + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + + /* Decrypt and authenticate */ + if( ( ret = mbedtls_cipher_auth_decrypt_ext( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len + TICKET_AUTH_TAG_BYTES, + ticket, enc_len, &clear_len, + TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + ret = MBEDTLS_ERR_SSL_INVALID_MAC; + + goto cleanup; + } + if( clear_len != enc_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + /* Actually load session */ + if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 ) + goto cleanup; + +#if defined(MBEDTLS_HAVE_TIME) + { + /* Check for expiration */ + mbedtls_time_t current_time = mbedtls_time( NULL ); + + if( current_time < session->start || + (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) + { + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + } +#endif + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free context + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) +{ + mbedtls_cipher_free( &ctx->keys[0].ctx ); + mbedtls_cipher_free( &ctx->keys[1].ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); +} + +#endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c new file mode 100644 index 0000000..7badec5 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls.c @@ -0,0 +1,7742 @@ +/* + * SSLv3/TLSv1 shared functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SSL 3.0 specification was drafted by Netscape in 1996, + * and became an IETF standard in 1999. + * + * http://wp.netscape.com/eng/ssl3/ + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/version.h" +#include "mbedtls/constant_time.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +/* Top-level Connection ID API */ + +int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf, + size_t len, + int ignore_other_cid ) +{ + if( len > MBEDTLS_SSL_CID_IN_LEN_MAX ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL && + ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->ignore_unexpected_cid = ignore_other_cid; + conf->cid_len = len; + return( 0 ); +} + +int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl, + int enable, + unsigned char const *own_cid, + size_t own_cid_len ) +{ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->negotiate_cid = enable; + if( enable == MBEDTLS_SSL_CID_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Disable use of CID extension." ) ); + return( 0 ); + } + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Enable use of CID extension." ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Own CID", own_cid, own_cid_len ); + + if( own_cid_len != ssl->conf->cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "CID length %u does not match CID length %u in config", + (unsigned) own_cid_len, + (unsigned) ssl->conf->cid_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memcpy( ssl->own_cid, own_cid, own_cid_len ); + /* Truncation is not an issue here because + * MBEDTLS_SSL_CID_IN_LEN_MAX at most 255. */ + ssl->own_cid_len = (uint8_t) own_cid_len; + + return( 0 ); +} + +int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl, + int *enabled, + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ], + size_t *peer_cid_len ) +{ + *enabled = MBEDTLS_SSL_CID_DISABLED; + + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* We report MBEDTLS_SSL_CID_DISABLED in case the CID extensions + * were used, but client and server requested the empty CID. + * This is indistinguishable from not using the CID extension + * in the first place. */ + if( ssl->transform_in->in_cid_len == 0 && + ssl->transform_in->out_cid_len == 0 ) + { + return( 0 ); + } + + if( peer_cid_len != NULL ) + { + *peer_cid_len = ssl->transform_in->out_cid_len; + if( peer_cid != NULL ) + { + memcpy( peer_cid, ssl->transform_in->out_cid, + ssl->transform_in->out_cid_len ); + } + } + + *enabled = MBEDTLS_SSL_CID_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int ssl_mfl_code_to_length( int mfl ) +{ + switch( mfl ) + { + case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + case MBEDTLS_SSL_MAX_FRAG_LEN_512: + return 512; + case MBEDTLS_SSL_MAX_FRAG_LEN_1024: + return 1024; + case MBEDTLS_SSL_MAX_FRAG_LEN_2048: + return 2048; + case MBEDTLS_SSL_MAX_FRAG_LEN_4096: + return 4096; + default: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + } +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src ) +{ + mbedtls_ssl_session_free( dst ); + memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + dst->ticket = NULL; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( src->peer_cert != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); + if( dst->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( dst->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + mbedtls_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( src->peer_cert_digest != NULL ) + { + dst->peer_cert_digest = + mbedtls_calloc( 1, src->peer_cert_digest_len ); + if( dst->peer_cert_digest == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->peer_cert_digest, src->peer_cert_digest, + src->peer_cert_digest_len ); + dst->peer_cert_digest_type = src->peer_cert_digest_type; + dst->peer_cert_digest_len = src->peer_cert_digest_len; + } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( src->ticket != NULL ) + { + dst->ticket = mbedtls_calloc( 1, src->ticket_len ); + if( dst->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +MBEDTLS_CHECK_RETURN_CRITICAL +static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old ) +{ + unsigned char* resized_buffer = mbedtls_calloc( 1, len_new ); + if( resized_buffer == NULL ) + return -1; + + /* We want to copy len_new bytes when downsizing the buffer, and + * len_old bytes when upsizing, so we choose the smaller of two sizes, + * to fit one buffer into another. Size checks, ensuring that no data is + * lost, are done outside of this function. */ + memcpy( resized_buffer, *buffer, + ( len_new < *len_old ) ? len_new : *len_old ); + mbedtls_platform_zeroize( *buffer, *len_old ); + mbedtls_free( *buffer ); + + *buffer = resized_buffer; + *len_old = len_new; + + return 0; +} + +static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing, + size_t in_buf_new_len, + size_t out_buf_new_len ) +{ + int modified = 0; + size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0; + size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0; + if( ssl->in_buf != NULL ) + { + written_in = ssl->in_msg - ssl->in_buf; + iv_offset_in = ssl->in_iv - ssl->in_buf; + len_offset_in = ssl->in_len - ssl->in_buf; + if( downsizing ? + ssl->in_buf_len > in_buf_new_len && ssl->in_left < in_buf_new_len : + ssl->in_buf_len < in_buf_new_len ) + { + if( resize_buffer( &ssl->in_buf, in_buf_new_len, &ssl->in_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %" MBEDTLS_PRINTF_SIZET, + in_buf_new_len ) ); + modified = 1; + } + } + } + + if( ssl->out_buf != NULL ) + { + written_out = ssl->out_msg - ssl->out_buf; + iv_offset_out = ssl->out_iv - ssl->out_buf; + len_offset_out = ssl->out_len - ssl->out_buf; + if( downsizing ? + ssl->out_buf_len > out_buf_new_len && ssl->out_left < out_buf_new_len : + ssl->out_buf_len < out_buf_new_len ) + { + if( resize_buffer( &ssl->out_buf, out_buf_new_len, &ssl->out_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %" MBEDTLS_PRINTF_SIZET, + out_buf_new_len ) ); + modified = 1; + } + } + } + if( modified ) + { + /* Update pointers here to avoid doing it twice. */ + mbedtls_ssl_reset_in_out_pointers( ssl ); + /* Fields below might not be properly updated with record + * splitting or with CID, so they are manually updated here. */ + ssl->out_msg = ssl->out_buf + written_out; + ssl->out_len = ssl->out_buf + len_offset_out; + ssl->out_iv = ssl->out_buf + iv_offset_out; + + ssl->in_msg = ssl->in_buf + written_in; + ssl->in_len = ssl->in_buf + len_offset_in; + ssl->in_iv = ssl->in_buf + iv_offset_in; + } +} +#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ + +/* + * Key material generation + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl3_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + int ret = 0; + size_t i; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padding[16]; + unsigned char sha1sum[20]; + ((void)label); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + /* + * SSLv3: + * block = + * MD5( secret + SHA1( 'A' + secret + random ) ) + + * MD5( secret + SHA1( 'BB' + secret + random ) ) + + * MD5( secret + SHA1( 'CCC' + secret + random ) ) + + * ... + */ + for( i = 0; i < dlen / 16; i++ ) + { + memset( padding, (unsigned char) ('A' + i), 1 + i ); + + if( ( ret = mbedtls_sha1_starts_ret( &sha1 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, padding, 1 + i ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_update_ret( &sha1, random, rlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha1_finish_ret( &sha1, sha1sum ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_starts_ret( &md5 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, secret, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5, sha1sum, 20 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5, dstbuf + i * 16 ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padding, sizeof( padding ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls1_prf( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb, hs; + size_t i, j, k; + const unsigned char *S1, *S2; + unsigned char *tmp; + size_t tmp_len = 0; + unsigned char h_i[20]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &md_ctx ); + + tmp_len = 20 + strlen( label ) + rlen; + tmp = mbedtls_calloc( 1, tmp_len ); + if( tmp == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + hs = ( slen + 1 ) / 2; + S1 = secret; + S2 = secret + slen - hs; + + nb = strlen( label ); + memcpy( tmp + 20, label, nb ); + memcpy( tmp + 20 + nb, random, rlen ); + nb += rlen; + + /* + * First compute P_md5(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_starts( &md_ctx, S1, hs ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < dlen; i += 16 ) + { + ret = mbedtls_md_hmac_reset ( &md_ctx ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, h_i ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_md_hmac_reset ( &md_ctx ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); + if( ret != 0 ) + goto exit; + + k = ( i + 16 > dlen ) ? dlen % 16 : 16; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + + mbedtls_md_free( &md_ctx ); + + /* + * XOR out with P_sha1(secret,label+random)[0..dlen] + */ + if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_starts( &md_ctx, S2, hs ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, tmp ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < dlen; i += 20 ) + { + ret = mbedtls_md_hmac_reset ( &md_ctx ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, h_i ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_md_hmac_reset ( &md_ctx ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, tmp ); + if( ret != 0 ) + goto exit; + + k = ( i + 20 > dlen ) ? dlen % 20 : 20; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); + } + +exit: + mbedtls_md_free( &md_ctx ); + + mbedtls_platform_zeroize( tmp, tmp_len ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); + + mbedtls_free( tmp ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* derivation, + psa_key_id_t key, + psa_algorithm_t alg, + const unsigned char* seed, size_t seed_length, + const unsigned char* label, size_t label_length, + size_t capacity ) +{ + psa_status_t status; + + status = psa_key_derivation_setup( derivation, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( PSA_ALG_IS_TLS12_PRF( alg ) || PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) ) + { + status = psa_key_derivation_input_bytes( derivation, + PSA_KEY_DERIVATION_INPUT_SEED, + seed, seed_length ); + if( status != PSA_SUCCESS ) + return( status ); + + if( mbedtls_svc_key_id_is_null( key ) ) + { + status = psa_key_derivation_input_bytes( + derivation, PSA_KEY_DERIVATION_INPUT_SECRET, + NULL, 0 ); + } + else + { + status = psa_key_derivation_input_key( + derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key ); + } + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_key_derivation_input_bytes( derivation, + PSA_KEY_DERIVATION_INPUT_LABEL, + label, label_length ); + if( status != PSA_SUCCESS ) + return( status ); + } + else + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + status = psa_key_derivation_set_capacity( derivation, capacity ); + if( status != PSA_SUCCESS ) + return( status ); + + return( PSA_SUCCESS ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + psa_status_t status; + psa_algorithm_t alg; + psa_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + if( md_type == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384); + else + alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256); + + /* Normally a "secret" should be long enough to be impossible to + * find by brute force, and in particular should not be empty. But + * this PRF is also used to derive an IV, in particular in EAP-TLS, + * and for this use case it makes sense to have a 0-length "secret". + * Since the key API doesn't allow importing a key of length 0, + * keep master_key=0, which setup_psa_key_derivation() understands + * to mean a 0-length "secret" input. */ + if( slen != 0 ) + { + psa_key_attributes_t key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &key_attributes, alg ); + psa_set_key_type( &key_attributes, PSA_KEY_TYPE_DERIVE ); + + status = psa_import_key( &key_attributes, secret, slen, &master_key ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = setup_psa_key_derivation( &derivation, + master_key, alg, + random, rlen, + (unsigned char const *) label, + (size_t) strlen( label ), + dlen ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + psa_destroy_key( master_key ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_output_bytes( &derivation, dstbuf, dlen ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + psa_destroy_key( master_key ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + { + psa_destroy_key( master_key ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ! mbedtls_svc_key_id_is_null( master_key ) ) + status = psa_destroy_key( master_key ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + return( 0 ); +} + +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k, md_len; + unsigned char *tmp; + size_t tmp_len = 0; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &md_ctx ); + + if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + md_len = mbedtls_md_get_size( md_info ); + + tmp_len = md_len + strlen( label ) + rlen; + tmp = mbedtls_calloc( 1, tmp_len ); + if( tmp == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + nb = strlen( label ); + memcpy( tmp + md_len, label, nb ); + memcpy( tmp + md_len + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + ret = mbedtls_md_hmac_starts( &md_ctx, secret, slen ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, tmp ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < dlen; i += md_len ) + { + ret = mbedtls_md_hmac_reset ( &md_ctx ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, h_i ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_md_hmac_reset ( &md_ctx ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, tmp ); + if( ret != 0 ) + goto exit; + + k = ( i + md_len > dlen ) ? dlen % md_len : md_len; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + +exit: + mbedtls_md_free( &md_ctx ); + + mbedtls_platform_zeroize( tmp, tmp_len ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); + + mbedtls_free( tmp ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_SHA256_C) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_sha256( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +MBEDTLS_CHECK_RETURN_CRITICAL +static int tls_prf_sha384( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_verify_ssl( const mbedtls_ssl_context *, unsigned char *, size_t * ); +static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_verify_tls( const mbedtls_ssl_context *, unsigned char*, size_t * ); +static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *,unsigned char*, size_t * ); +static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char*, size_t * ); +static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) +{ + if( ssl->conf->f_psk != NULL ) + { + /* If we've used a callback to select the PSK, + * the static configuration is irrelevant. */ + if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) ) + return( 1 ); + + return( 0 ); + } + + if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +static mbedtls_tls_prf_types tls_prf_get_type( mbedtls_ssl_tls_prf_cb *tls_prf ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( tls_prf == ssl3_prf ) + { + return( MBEDTLS_SSL_TLS_PRF_SSL3 ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( tls_prf == tls1_prf ) + { + return( MBEDTLS_SSL_TLS_PRF_TLS1 ); + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + if( tls_prf == tls_prf_sha384 ) + { + return( MBEDTLS_SSL_TLS_PRF_SHA384 ); + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( tls_prf == tls_prf_sha256 ) + { + return( MBEDTLS_SSL_TLS_PRF_SHA256 ); + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + return( MBEDTLS_SSL_TLS_PRF_NONE ); +} +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ + +int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + mbedtls_ssl_tls_prf_cb *tls_prf = NULL; + + switch( prf ) + { +#if defined(MBEDTLS_SSL_PROTO_SSL3) + case MBEDTLS_SSL_TLS_PRF_SSL3: + tls_prf = ssl3_prf; + break; +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + case MBEDTLS_SSL_TLS_PRF_TLS1: + tls_prf = tls1_prf; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_SSL_TLS_PRF_SHA384: + tls_prf = tls_prf_sha384; + break; +#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */ +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_TLS_PRF_SHA256: + tls_prf = tls_prf_sha256; + break; +#endif /* MBEDTLS_SHA256_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + default: + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( tls_prf( secret, slen, label, random, rlen, dstbuf, dlen ) ); +} + +/* Type for the TLS PRF */ +typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + +/* + * Populate a transform structure with session keys and all the other + * necessary information. + * + * Parameters: + * - [in/out]: transform: structure to populate + * [in] must be just initialised with mbedtls_ssl_transform_init() + * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() + * - [in] ciphersuite + * - [in] master + * - [in] encrypt_then_mac + * - [in] trunc_hmac + * - [in] compression + * - [in] tls_prf: pointer to PRF to use for key derivation + * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random + * - [in] minor_ver: SSL/TLS minor version + * - [in] endpoint: client or server + * - [in] ssl: optionally used for: + * - MBEDTLS_SSL_HW_RECORD_ACCEL: whole context (non-const) + * - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys + * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_populate_transform( mbedtls_ssl_transform *transform, + int ciphersuite, + const unsigned char master[48], +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac, +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + int compression, +#endif + ssl_tls_prf_t tls_prf, + const unsigned char randbytes[64], + int minor_ver, + unsigned endpoint, +#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + const +#endif + mbedtls_ssl_context *ssl ) +{ + int ret = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int psa_fallthrough; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t mac_key_len = 0; + size_t iv_copy_len; + unsigned keylen; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; + +#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \ + !defined(MBEDTLS_SSL_EXPORT_KEYS) && \ + !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + /* + * Some data just needs copying into the structure + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + transform->encrypt_then_mac = encrypt_then_mac; +#endif + transform->minor_ver = minor_ver; + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + memcpy( transform->randbytes, randbytes, sizeof( transform->randbytes ) ); +#endif + + /* + * Get various info structures + */ + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite ); + if( ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found", + ciphersuite ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %u not found", + ciphersuite_info->cipher ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( ciphersuite_info->mac ); + if( md_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %u not found", + (unsigned) ciphersuite_info->mac ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Copy own and peer's CID if the use of the CID + * extension has been negotiated. */ + if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Copy CIDs into SSL transform" ) ); + + transform->in_cid_len = ssl->own_cid_len; + memcpy( transform->in_cid, ssl->own_cid, ssl->own_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Incoming CID", transform->in_cid, + transform->in_cid_len ); + + transform->out_cid_len = ssl->handshake->peer_cid_len; + memcpy( transform->out_cid, ssl->handshake->peer_cid, + ssl->handshake->peer_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Outgoing CID", transform->out_cid, + transform->out_cid_len ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Compute key block using the PRF + */ + ret = tls_prf( master, 48, "key expansion", randbytes, 64, keyblk, 256 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + mbedtls_ssl_get_ciphersuite_name( ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", master, 48 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", randbytes, 64 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + keylen = cipher_info->key_bitlen / 8; + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( cipher_info->mode == MBEDTLS_MODE_GCM || + cipher_info->mode == MBEDTLS_MODE_CCM || + cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + { + size_t explicit_ivlen; + + transform->maclen = 0; + mac_key_len = 0; + transform->taglen = + ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + /* All modes haves 96-bit IVs, but the length of the static parts vary + * with mode and version: + * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes + * (to be concatenated with a dynamically chosen IV of 8 Bytes) + * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's + * a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record + * sequence number). + */ + transform->ivlen = 12; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + transform->fixed_ivlen = 12; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ + { + if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY ) + transform->fixed_ivlen = 12; + else + transform->fixed_ivlen = 4; + } + + /* Minimum length of encrypted record */ + explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + transform->minlen = explicit_ivlen + transform->taglen; + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + if( cipher_info->mode == MBEDTLS_MODE_STREAM || + cipher_info->mode == MBEDTLS_MODE_CBC ) + { + /* Initialize HMAC contexts */ + if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || + ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto end; + } + + /* Get MAC length */ + mac_key_len = mbedtls_md_get_size( md_info ); + transform->maclen = mac_key_len; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + /* + * If HMAC is to be truncated, we shall keep the leftmost bytes, + * (rfc 6066 page 13 or rfc 2104 section 4), + * so we only need to adjust the length here. + */ + if( trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + { + transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + /* Fall back to old, non-compliant version of the truncated + * HMAC implementation which also truncates the key + * (Mbed TLS versions from 1.3 to 2.6.0) */ + mac_key_len = transform->maclen; +#endif + } +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( cipher_info->mode == MBEDTLS_MODE_STREAM ) + transform->minlen = transform->maclen; + else + { + /* + * GenericBlockCipher: + * 1. if EtM is in use: one block plus MAC + * otherwise: * first multiple of blocklen greater than maclen + * 2. IV except for SSL3 and TLS 1.0 + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + transform->minlen = transform->maclen + + cipher_info->block_size; + } + else +#endif + { + transform->minlen = transform->maclen + + cipher_info->block_size + - transform->maclen % cipher_info->block_size; + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) + ; /* No need to adjust minlen */ + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || + minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + } + } + else +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %u, minlen: %u, ivlen: %u, maclen: %u", + (unsigned) keylen, + (unsigned) transform->minlen, + (unsigned) transform->ivlen, + (unsigned) transform->maclen ) ); + + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + key1 = keyblk + mac_key_len * 2; + key2 = keyblk + mac_key_len * 2 + keylen; + + mac_enc = keyblk; + mac_dec = keyblk + mac_key_len; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + key1 = keyblk + mac_key_len * 2 + keylen; + key2 = keyblk + mac_key_len * 2; + + mac_enc = keyblk + mac_key_len; + mac_dec = keyblk; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( mac_key_len > sizeof( transform->mac_enc ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + + memcpy( transform->mac_enc, mac_enc, mac_key_len ); + memcpy( transform->mac_dec, mac_dec, mac_key_len ); + } + else +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + { + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if( mac_key_len != 0 ) + { + ret = mbedtls_md_hmac_starts( &transform->md_ctx_enc, + mac_enc, mac_key_len ); + if( ret != 0 ) + goto end; + ret = mbedtls_md_hmac_starts( &transform->md_ctx_dec, + mac_dec, mac_key_len ); + if( ret != 0 ) + goto end; + } + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_init != NULL ) + { + ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); + + if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, keylen, + transform->iv_enc, transform->iv_dec, + iv_copy_len, + mac_enc, mac_dec, + mac_key_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto end; + } + } +#else + ((void) mac_dec); + ((void) mac_enc); +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + if( ssl->conf->f_export_keys != NULL ) + { + ssl->conf->f_export_keys( ssl->conf->p_export_keys, + master, keyblk, + mac_key_len, keylen, + iv_copy_len ); + } + + if( ssl->conf->f_export_keys_ext != NULL ) + { + ssl->conf->f_export_keys_ext( ssl->conf->p_export_keys, + master, keyblk, + mac_key_len, keylen, + iv_copy_len, + randbytes + 32, + randbytes, + tls_prf_get_type( tls_prf ) ); + } +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + + /* Only use PSA-based ciphers for TLS-1.2. + * That's relevant at least for TLS-1.0, where + * we assume that mbedtls_cipher_crypt() updates + * the structure field for the IV, which the PSA-based + * implementation currently doesn't. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc, + cipher_info, transform->taglen ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret ); + goto end; + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) ); + psa_fallthrough = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) ); + psa_fallthrough = 1; + } + } + else + psa_fallthrough = 1; +#else + psa_fallthrough = 1; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( psa_fallthrough == 1 ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + goto end; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Only use PSA-based ciphers for TLS-1.2. + * That's relevant at least for TLS-1.0, where + * we assume that mbedtls_cipher_crypt() updates + * the structure field for the IV, which the PSA-based + * implementation currently doesn't. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec, + cipher_info, transform->taglen ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret ); + goto end; + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) ); + psa_fallthrough = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) ); + psa_fallthrough = 1; + } + } + else + psa_fallthrough = 1; +#else + psa_fallthrough = 1; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + if( psa_fallthrough == 1 ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, + cipher_info->key_bitlen, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, + cipher_info->key_bitlen, + MBEDTLS_DECRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + goto end; + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( cipher_info->mode == MBEDTLS_MODE_CBC ) + { + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + goto end; + } + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + + /* Initialize Zlib contexts */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); + + memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); + memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); + + if( deflateInit( &transform->ctx_deflate, + Z_DEFAULT_COMPRESSION ) != Z_OK || + inflateInit( &transform->ctx_inflate ) != Z_OK ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); + ret = MBEDTLS_ERR_SSL_COMPRESSION_FAILED; + goto end; + } + } +#endif /* MBEDTLS_ZLIB_SUPPORT */ + +end: + mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) ); + return( ret ); +} + +/* + * Set appropriate PRF function and other SSL / TLS 1.0/1.1 / TLS1.2 functions + * + * Inputs: + * - SSL/TLS minor version + * - hash associated with the ciphersuite (only used by TLS 1.2) + * + * Outputs: + * - the tls_prf, calc_verify and calc_finished members of handshake structure + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, + int minor_ver, + mbedtls_md_type_t hash ) +{ +#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) || \ + !( defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) ) + (void) hash; +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + hash == MBEDTLS_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( 0 ); +} + +/* + * Compute master secret if needed + * + * Parameters: + * [in/out] handshake + * [in] resume, premaster, extended_ms, calc_verify, tls_prf + * (PSA-PSK) ciphersuite_info, psk_opaque + * [out] premaster (cleared) + * [out] master + * [in] ssl: optionally used for debugging, EMS and PSA-PSK + * debug: conf->f_dbg, conf->p_dbg + * EMS: passed to calc_verify (debug + (SSL3) session_negotiate) + * PSA-PSA: minor_ver, conf + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, + unsigned char *master, + const mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* cf. RFC 5246, Section 8.1: + * "The master secret is always exactly 48 bytes in length." */ + size_t const master_secret_len = 48; + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned char session_hash[48]; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + + /* The label for the KDF used for key expansion. + * This is either "master secret" or "extended master secret" + * depending on whether the Extended Master Secret extension + * is used. */ + char const *lbl = "master secret"; + + /* The salt for the KDF used for key expansion. + * - If the Extended Master Secret extension is not used, + * this is ClientHello.Random + ServerHello.Random + * (see Sect. 8.1 in RFC 5246). + * - If the Extended Master Secret extension is used, + * this is the transcript of the handshake so far. + * (see Sect. 4 in RFC 7627). */ + unsigned char const *salt = handshake->randbytes; + size_t salt_len = 64; + +#if !defined(MBEDTLS_DEBUG_C) && \ + !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + if( handshake->resume != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + lbl = "extended master secret"; + salt = session_hash; + handshake->calc_verify( ssl, session_hash, &salt_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash for extended master secret", + session_hash, salt_len ); + } +#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_use_opaque_psk( ssl ) == 1 ) + { + /* Perform PSK-to-MS expansion in a single step. */ + psa_status_t status; + psa_algorithm_t alg; + psa_key_id_t psk; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); + + psk = mbedtls_ssl_get_opaque_psk( ssl ); + + if( hash_alg == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + + status = setup_psa_key_derivation( &derivation, psk, alg, + salt, salt_len, + (unsigned char const *) lbl, + (size_t) strlen( lbl ), + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_output_bytes( &derivation, + master, + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + else +#endif + { + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + lbl, salt, salt_len, + master, + master_secret_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", + handshake->premaster, + handshake->pmslen ); + + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); + } + + return( 0 ); +} + +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + /* Set PRF, calc_verify and calc_finished function pointers */ + ret = ssl_set_handshake_prfs( ssl->handshake, + ssl->minor_ver, + ciphersuite_info->mac ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_set_handshake_prfs", ret ); + return( ret ); + } + + /* Compute master secret if needed */ + ret = ssl_compute_master( ssl->handshake, + ssl->session_negotiate->master, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compute_master", ret ); + return( ret ); + } + + /* Swap the client and server random values: + * - MS derivation wanted client+server (RFC 5246 8.1) + * - key derivation wants server+client (RFC 5246 6.3) */ + { + unsigned char tmp[64]; + memcpy( tmp, ssl->handshake->randbytes, 64 ); + memcpy( ssl->handshake->randbytes, tmp + 32, 32 ); + memcpy( ssl->handshake->randbytes + 32, tmp, 32 ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + } + + /* Populate transform structure */ + ret = ssl_populate_transform( ssl->transform_negotiate, + ssl->session_negotiate->ciphersuite, + ssl->session_negotiate->master, +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl->session_negotiate->encrypt_then_mac, +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl->session_negotiate->trunc_hmac, +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + ssl->session_negotiate->compression, +#endif + ssl->handshake->tls_prf, + ssl->handshake->randbytes, + ssl->minor_ver, + ssl->conf->endpoint, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_populate_transform", ret ); + return( ret ); + } + + /* We no longer need Server/ClientHello.random values */ + mbedtls_platform_zeroize( ssl->handshake->randbytes, + sizeof( ssl->handshake->randbytes ) ); + + /* Allocate compression buffer */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_negotiate->compression == MBEDTLS_SSL_COMPRESS_DEFLATE && + ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl, + unsigned char *hash, + size_t *hlen ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char pad_1[48]; + unsigned char pad_2[48]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + memset( pad_1, 0x36, 48 ); + memset( pad_2, 0x5C, 48 ); + + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_1, 48 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, ssl->session_negotiate->master, 48 ); + mbedtls_md5_update_ret( &md5, pad_2, 48 ); + mbedtls_md5_update_ret( &md5, hash, 16 ); + mbedtls_md5_finish_ret( &md5, hash ); + + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_1, 40 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, ssl->session_negotiate->master, 48 ); + mbedtls_sha1_update_ret( &sha1, pad_2, 40 ); + mbedtls_sha1_update_ret( &sha1, hash + 16, 20 ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + *hlen = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl, + unsigned char *hash, + size_t *hlen ) +{ + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + mbedtls_md5_finish_ret( &md5, hash ); + mbedtls_sha1_finish_ret( &sha1, hash + 16 ); + + *hlen = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + return; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, + unsigned char *hash, + size_t *hlen ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_status_t status; + psa_hash_operation_t sha256_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha256" ) ); + status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha256_psa, hash, 32, &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + + *hlen = 32; + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) ); +#else + mbedtls_sha256_context sha256; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + mbedtls_sha256_finish_ret( &sha256, hash ); + + *hlen = 32; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha256_free( &sha256 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return; +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, + unsigned char *hash, + size_t *hlen ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_status_t status; + psa_hash_operation_t sha384_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha384" ) ); + status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha384_psa, hash, 48, &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + + *hlen = 48; + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) ); +#else + mbedtls_sha512_context sha512; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + mbedtls_sha512_finish_ret( &sha512, hash ); + + *hlen = 48; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha512_free( &sha512 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return; +} +#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + const unsigned char *psk = NULL; + size_t psk_len = 0; + + if( mbedtls_ssl_get_psk( ssl, &psk, &psk_len ) + == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ) + { + /* + * This should never happen because the existence of a PSK is always + * checked before calling this function + */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_PUT_UINT16_BE( psk_len, p, 0 ); + p += 2; + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memset( p, 0, psk_len ); + p += psk_len; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Write length only when we know the actual value */ + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, end - ( p + 2 ), &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + MBEDTLS_PUT_UINT16_BE( len, p, 0 ); + p += 2 + len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t zlen; + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_PUT_UINT16_BE( zlen, p, 0 ); + p += 2 + zlen; + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_PUT_UINT16_BE( psk_len, p, 0 ); + p += 2; + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( p, psk, psk_len ); + p += psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ) +{ + /* If renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if( ssl->conf->renego_max_records < 0 ) + { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; + + while( ratio != 0 ) + { + ++doublings; + ratio >>= 1; + } + + if( ++ssl->renego_records_seen > doublings ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); + return( 0 ); + } + } + + return( ssl_write_hello_request( ssl ) ); +} +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_clear_peer_cert( mbedtls_ssl_session *session ) +{ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( session->peer_cert != NULL ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( session->peer_cert_digest != NULL ) + { + /* Zeroization is not necessary. */ + mbedtls_free( session->peer_cert_digest ); + session->peer_cert_digest = NULL; + session->peer_cert_digest_type = MBEDTLS_MD_NONE; + session->peer_cert_digest_len = 0; + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* No certificate support -> dummy functions */ +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +/* Some certificate support -> implement write and parse */ + +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * If using SSLv3 and got no cert, send an Alert message + * (otherwise an empty Certificate message will be sent). + */ + if( mbedtls_ssl_own_cert( ssl ) == NULL && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + ssl->out_msglen = 2; + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; + ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); + goto write_msg; + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %" MBEDTLS_PRINTF_SIZET + " > %" MBEDTLS_PRINTF_SIZET, + i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); + } + + ssl->out_msg[i ] = MBEDTLS_BYTE_2( n ); + ssl->out_msg[i + 1] = MBEDTLS_BYTE_1( n ); + ssl->out_msg[i + 2] = MBEDTLS_BYTE_0( n ); + + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = MBEDTLS_BYTE_2( i - 7 ); + ssl->out_msg[5] = MBEDTLS_BYTE_1( i - 7 ); + ssl->out_msg[6] = MBEDTLS_BYTE_0( i - 7 ); + + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) +write_msg: +#endif + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len ) +{ + mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; + + if( peer_crt == NULL ) + return( -1 ); + + if( peer_crt->raw.len != crt_buf_len ) + return( -1 ); + + return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) ); +} +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char const * const peer_cert_digest = + ssl->session->peer_cert_digest; + mbedtls_md_type_t const peer_cert_digest_type = + ssl->session->peer_cert_digest_type; + mbedtls_md_info_t const * const digest_info = + mbedtls_md_info_from_type( peer_cert_digest_type ); + unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; + size_t digest_len; + + if( peer_cert_digest == NULL || digest_info == NULL ) + return( -1 ); + + digest_len = mbedtls_md_get_size( digest_info ); + if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN ) + return( -1 ); + + ret = mbedtls_md( digest_info, crt_buf, crt_buf_len, tmp_digest ); + if( ret != 0 ) + return( -1 ); + + return( memcmp( tmp_digest, peer_cert_digest, digest_len ) ); +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *chain ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + int crt_cnt=0; +#endif + size_t i, n; + uint8_t alert; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || + ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + + if( ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */ + i += 3; + + /* Iterate through and parse the CRTs in the provided chain. */ + while( i < ssl->in_hslen ) + { + /* Check that there's room for the next CRT's length fields. */ + if ( i + 3 > ssl->in_hslen ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + /* In theory, the CRT can be up to 2**24 Bytes, but we don't support + * anything beyond 2**16 ~ 64K. */ + if( ssl->in_msg[i] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* Read length of the next CRT in the chain. */ + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* Check if we're handling the first CRT in the chain. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if( crt_cnt++ == 0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* During client-side renegotiation, check that the server's + * end-CRTs hasn't changed compared to the initial handshake, + * mitigating the triple handshake attack. On success, reuse + * the original end-CRT instead of parsing it again. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Check that peer CRT hasn't changed during renegotiation" ) ); + if( ssl_check_peer_crt_unchanged( ssl, + &ssl->in_msg[i], + n ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); + } + + /* Now we can safely free the original chain. */ + ssl_clear_peer_cert( ssl->session ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + /* Parse the next certificate in the chain. */ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + ret = mbedtls_x509_crt_parse_der( chain, ssl->in_msg + i, n ); +#else + /* If we don't need to store the CRT chain permanently, parse + * it in-place from the input buffer instead of making a copy. */ + ret = mbedtls_x509_crt_parse_der_nocopy( chain, ssl->in_msg + i, n ); +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + switch( ret ) + { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + crt_parse_der_failed: + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", chain ); + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl ) +{ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + return( -1 ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) + /* + * Check if the client sent an empty certificate + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + if( ssl->in_msglen == 2 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && + ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); + return( 0 ); + } + + return( -1 ); + } +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + return( 0 ); + } + + return( -1 ); +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* Check if a certificate message is expected. + * Return either + * - SSL_CERTIFICATE_EXPECTED, or + * - SSL_CERTIFICATE_SKIP + * indicating whether a Certificate message is expected or not. + */ +#define SSL_CERTIFICATE_EXPECTED 0 +#define SSL_CERTIFICATE_SKIP 1 +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl, + int authmode ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + return( SSL_CERTIFICATE_SKIP ); + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + return( SSL_CERTIFICATE_SKIP ); + + if( authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = + MBEDTLS_X509_BADCERT_SKIP_VERIFY; + return( SSL_CERTIFICATE_SKIP ); + } + } +#else + ((void) authmode); +#endif /* MBEDTLS_SSL_SRV_C */ + + return( SSL_CERTIFICATE_EXPECTED ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, + int authmode, + mbedtls_x509_crt *chain, + void *rs_ctx ) +{ + int ret = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + int have_ca_chain = 0; + + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; + + if( authmode == MBEDTLS_SSL_VERIFY_NONE ) + return( 0 ); + + if( ssl->f_vrfy != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use context-specific verification callback" ) ); + f_vrfy = ssl->f_vrfy; + p_vrfy = ssl->p_vrfy; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use configuration-specific verification callback" ) ); + f_vrfy = ssl->conf->f_vrfy; + p_vrfy = ssl->conf->p_vrfy; + } + + /* + * Main check: verify certificate + */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( ssl->conf->f_ca_cb != NULL ) + { + ((void) rs_ctx); + have_ca_chain = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "use CA callback for X.509 CRT verification" ) ); + ret = mbedtls_x509_crt_verify_with_ca_cb( + chain, + ssl->conf->f_ca_cb, + ssl->conf->p_ca_cb, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + f_vrfy, p_vrfy ); + } + else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + if( ca_chain != NULL ) + have_ca_chain = 1; + + ret = mbedtls_x509_crt_verify_restartable( + chain, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + f_vrfy, p_vrfy, rs_ctx ); + } + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); +#endif + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_ECP_C) + { + const mbedtls_pk_context *pk = &chain->pk; + + /* If certificate uses an EC key, make sure the curve is OK. + * This is a public key, so it can't be opaque, so can_do() is a good + * enough check to ensure pk_ec() is safe to use here. */ + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && + mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) + { + ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + } +#endif /* MBEDTLS_ECP_C */ + + if( mbedtls_ssl_check_cert_usage( chain, + ciphersuite_info, + ! ssl->conf->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; + } + + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * ssl_parse_certificate even if verification was optional. */ + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) + { + ret = 0; + } + + if( have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if( ret != 0 ) + { + uint8_t alert; + + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) + alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) + alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; + else + alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert ); + } + +#if defined(MBEDTLS_DEBUG_C) + if( ssl->session_negotiate->verify_result != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %08x", + (unsigned int) ssl->session_negotiate->verify_result ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); + } +#endif /* MBEDTLS_DEBUG_C */ + + return( ret ); +} + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl, + unsigned char *start, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* Remember digest of the peer's end-CRT. */ + ssl->session_negotiate->peer_cert_digest = + mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ); + if( ssl->session_negotiate->peer_cert_digest == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ret = mbedtls_md( mbedtls_md_info_from_type( + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ), + start, len, + ssl->session_negotiate->peer_cert_digest ); + + ssl->session_negotiate->peer_cert_digest_type = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE; + ssl->session_negotiate->peer_cert_digest_len = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN; + + return( ret ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl, + unsigned char *start, size_t len ) +{ + unsigned char *end = start + len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Make a copy of the peer's raw public key. */ + mbedtls_pk_init( &ssl->handshake->peer_pubkey ); + ret = mbedtls_pk_parse_subpubkey( &start, end, + &ssl->handshake->peer_pubkey ); + if( ret != 0 ) + { + /* We should have parsed the public key before. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( 0 ); +} +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + int crt_expected; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif + void *rs_ctx = NULL; + mbedtls_x509_crt *chain = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + crt_expected = ssl_parse_certificate_coordinate( ssl, authmode ); + if( crt_expected == SSL_CERTIFICATE_SKIP ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + goto exit; + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) + { + chain = ssl->handshake->ecrs_peer_cert; + ssl->handshake->ecrs_peer_cert = NULL; + goto crt_verify; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + goto exit; + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + + if( authmode != MBEDTLS_SSL_VERIFY_OPTIONAL ) + ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; + + goto exit; + } +#endif /* MBEDTLS_SSL_SRV_C */ + + /* Clear existing peer CRT structure in case we tried to + * reuse a session but it failed, and allocate a new one. */ + ssl_clear_peer_cert( ssl->session_negotiate ); + + chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + if( chain == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", + sizeof( mbedtls_x509_crt ) ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + mbedtls_x509_crt_init( chain ); + + ret = ssl_parse_certificate_chain( ssl, chain ); + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled) + ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; + +crt_verify: + if( ssl->handshake->ecrs_enabled) + rs_ctx = &ssl->handshake->ecrs_ctx; +#endif + + ret = ssl_parse_certificate_verify( ssl, authmode, + chain, rs_ctx ); + if( ret != 0 ) + goto exit; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + { + unsigned char *crt_start, *pk_start; + size_t crt_len, pk_len; + + /* We parse the CRT chain without copying, so + * these pointers point into the input buffer, + * and are hence still valid after freeing the + * CRT chain. */ + + crt_start = chain->raw.p; + crt_len = chain->raw.len; + + pk_start = chain->pk_raw.p; + pk_len = chain->pk_raw.len; + + /* Free the CRT structures before computing + * digest and copying the peer's public key. */ + mbedtls_x509_crt_free( chain ); + mbedtls_free( chain ); + chain = NULL; + + ret = ssl_remember_peer_crt_digest( ssl, crt_start, crt_len ); + if( ret != 0 ) + goto exit; + + ret = ssl_remember_peer_pubkey( ssl, pk_start, pk_len ); + if( ret != 0 ) + goto exit; + } +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Pass ownership to session structure. */ + ssl->session_negotiate->peer_cert = chain; + chain = NULL; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + +exit: + + if( ret == 0 ) + ssl->state++; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + ssl->handshake->ecrs_peer_cert = chain; + chain = NULL; + } +#endif + + if( chain != NULL ) + { + mbedtls_x509_crt_free( chain ); + mbedtls_free( chain ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_starts_ret( &ssl->handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &ssl->handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &ssl->handshake->fin_sha256_psa ); + psa_hash_setup( &ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256 ); +#else + mbedtls_sha256_starts_ret( &ssl->handshake->fin_sha256, 0 ); +#endif +#endif +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &ssl->handshake->fin_sha384_psa ); + psa_hash_setup( &ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384 ); +#else + mbedtls_sha512_starts_ret( &ssl->handshake->fin_sha512, 1 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len ); +#else + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +#endif +#endif +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len ); +#else + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + mbedtls_md5_update_ret( &ssl->handshake->fin_md5 , buf, len ); + mbedtls_sha1_update_ret( &ssl->handshake->fin_sha1, buf, len ); +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len ); +#else + mbedtls_sha256_update_ret( &ssl->handshake->fin_sha256, buf, len ); +#endif +} +#endif + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len ); +#else + mbedtls_sha512_update_ret( &ssl->handshake->fin_sha512, buf, len ); +#endif +} +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +static void ssl_calc_finished_ssl( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + + unsigned char padbuf[48]; + unsigned char md5sum[16]; + unsigned char sha1sum[20]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * SSLv3: + * hash = + * MD5( master + pad2 + + * MD5( handshake + sender + master + pad1 ) ) + * + SHA1( master + pad2 + + * SHA1( handshake + sender + master + pad1 ) ) + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT" + : "SRVR"; + + memset( padbuf, 0x36, 48 ); + + mbedtls_md5_update_ret( &md5, (const unsigned char *) sender, 4 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_finish_ret( &md5, md5sum ); + + mbedtls_sha1_update_ret( &sha1, (const unsigned char *) sender, 4 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf, 40 ); + mbedtls_sha1_finish_ret( &sha1, sha1sum ); + + memset( padbuf, 0x5C, 48 ); + + mbedtls_md5_starts_ret( &md5 ); + mbedtls_md5_update_ret( &md5, session->master, 48 ); + mbedtls_md5_update_ret( &md5, padbuf, 48 ); + mbedtls_md5_update_ret( &md5, md5sum, 16 ); + mbedtls_md5_finish_ret( &md5, buf ); + + mbedtls_sha1_starts_ret( &sha1 ); + mbedtls_sha1_update_ret( &sha1, session->master, 48 ); + mbedtls_sha1_update_ret( &sha1, padbuf , 40 ); + mbedtls_sha1_update_ret( &sha1, sha1sum, 20 ); + mbedtls_sha1_finish_ret( &sha1, buf + 16 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + mbedtls_platform_zeroize( md5sum, sizeof( md5sum ) ); + mbedtls_platform_zeroize( sha1sum, sizeof( sha1sum ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +static void ssl_calc_finished_tls( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + mbedtls_md5_context md5; + mbedtls_sha1_context sha1; + unsigned char padbuf[36]; + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); + + mbedtls_md5_init( &md5 ); + mbedtls_sha1_init( &sha1 ); + + mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); + mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); + + /* + * TLSv1: + * hash = PRF( master, finished_label, + * MD5( handshake ) + SHA1( handshake ) )[0..11] + */ + +#if !defined(MBEDTLS_MD5_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) + md5.state, sizeof( md5.state ) ); +#endif + +#if !defined(MBEDTLS_SHA1_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) + sha1.state, sizeof( sha1.state ) ); +#endif + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + + mbedtls_md5_finish_ret( &md5, padbuf ); + mbedtls_sha1_finish_ret( &sha1, padbuf + 16 ); + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 36, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_md5_free( &md5 ); + mbedtls_sha1_free( &sha1 ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_calc_finished_tls_sha256( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + unsigned char padbuf[32]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT; + psa_status_t status; +#else + mbedtls_sha256_context sha256; +#endif + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + sha256_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha256" ) ); + + status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha256_psa, padbuf, sizeof( padbuf ), &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 32 ); +#else + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA256_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha256.state, sizeof( sha256.state ) ); +#endif + + mbedtls_sha256_finish_ret( &sha256, padbuf ); + mbedtls_sha256_free( &sha256 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + +static void ssl_calc_finished_tls_sha384( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + unsigned char padbuf[48]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT; + psa_status_t status; +#else + mbedtls_sha512_context sha512; +#endif + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + sha384_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha384" ) ); + + status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha384_psa, padbuf, sizeof( padbuf ), &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 48 ); +#else + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA512_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) + sha512.state, sizeof( sha512.state ) ); +#endif + /* mbedtls_sha512_finish_ret's output parameter is declared as a + * 64-byte buffer, but sice we're using SHA-384, we know that the + * output fits in 48 bytes. This is correct C, but GCC 11.1 warns + * about it. + */ +#if defined(__GNUC__) && __GNUC__ >= 11 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + mbedtls_sha512_finish_ret( &sha512, padbuf ); +#if defined(__GNUC__) && __GNUC__ >= 11 +#pragma GCC diagnostic pop +#endif + + mbedtls_sha512_free( &sha512 ); +#endif + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA512_C && !MBEDTLS_SHA512_NO_SHA384 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); + + /* + * Free our handshake params + */ + mbedtls_ssl_handshake_free( ssl ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + + /* + * Free the previous transform and switch in the current one + */ + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); +} + +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } +#endif + + /* + * Free the previous session and switch in the current one + */ + if( ssl->session ) + { +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif + + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->conf->f_set_cache != NULL && + ssl->session->id_len != 0 && + resume == 0 ) + { + if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->flight != NULL ) + { + /* Cancel handshake timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + + /* Keep last flight around in case we need to resend it: + * we need the handshake and transform structures for that */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); + } + else +#endif + mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) +{ + int ret, hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_negotiate ); + + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); + + /* + * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites + * may define some other value. Currently (early 2016), no defined + * ciphersuite does this (and this is unlikely to change as activity has + * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. + */ + hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); +#endif + + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned char i; + + /* Remember current epoch settings for resending */ + ssl->handshake->alt_transform_out = ssl->transform_out; + memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 ); + + /* Set sequence_number to zero */ + memset( ssl->cur_out_ctr + 2, 0, 6 ); + + /* Increment epoch */ + for( i = 2; i > 0; i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->cur_out_ctr, 0, 8 ); + + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_activate != NULL ) + { + if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) +#define SSL_MAX_HASH_LEN 36 +#else +#define SSL_MAX_HASH_LEN 12 +#endif + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int hash_len; + unsigned char buf[SSL_MAX_HASH_LEN]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + /* There is currently no ciphersuite using another length with TLS 1.2 */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + hash_len = 36; + else +#endif + hash_len = 12; + + ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + goto exit; + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto exit; + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + ret = MBEDTLS_ERR_SSL_BAD_HS_FINISHED; + goto exit; + } + + if( mbedtls_ct_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), + buf, hash_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + ret = MBEDTLS_ERR_SSL_BAD_HS_FINISHED; + goto exit; + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); +#endif + + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif + } + else + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + +exit: + mbedtls_platform_zeroize( buf, hash_len ); + return( ret ); +} + +static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_init( &handshake->fin_md5 ); + mbedtls_sha1_init( &handshake->fin_sha1 ); + mbedtls_md5_starts_ret( &handshake->fin_md5 ); + mbedtls_sha1_starts_ret( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha256_psa = psa_hash_operation_init(); + psa_hash_setup( &handshake->fin_sha256_psa, PSA_ALG_SHA_256 ); +#else + mbedtls_sha256_init( &handshake->fin_sha256 ); + mbedtls_sha256_starts_ret( &handshake->fin_sha256, 0 ); +#endif +#endif +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha384_psa = psa_hash_operation_init(); + psa_hash_setup( &handshake->fin_sha384_psa, PSA_ALG_SHA_384 ); +#else + mbedtls_sha512_init( &handshake->fin_sha512 ); + mbedtls_sha512_starts_ret( &handshake->fin_sha512, 1 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_init( &handshake->peer_pubkey ); +#endif +} + +void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform ) +{ + memset( transform, 0, sizeof(mbedtls_ssl_transform) ); + + mbedtls_cipher_init( &transform->cipher_ctx_enc ); + mbedtls_cipher_init( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + mbedtls_md_init( &transform->md_ctx_enc ); + mbedtls_md_init( &transform->md_ctx_dec ); +#endif +} + +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) +{ + memset( session, 0, sizeof(mbedtls_ssl_session) ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_handshake_init( mbedtls_ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + mbedtls_ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + mbedtls_ssl_handshake_free( ssl ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); + } +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too small - reallocate */ + + handle_buffer_resizing( ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN, + MBEDTLS_SSL_OUT_BUFFER_LEN ); +#endif + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Initialize structures */ + mbedtls_ssl_session_init( ssl->session_negotiate ); + mbedtls_ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->handshake->alt_transform_out = ssl->transform_out; + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + + mbedtls_ssl_set_timer( ssl, 0 ); + } +#endif + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/* Dummy cookie callbacks for defaults */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cookie_write_dummy( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_cookie_check_dummy( void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +/* + * Initialize an SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) +{ + memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Setup an SSL context + */ + +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + ssl->conf = conf; + + /* + * Prepare base structures + */ + + /* Set to NULL in case of an error condition */ + ssl->out_buf = NULL; + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = in_buf_len; +#endif + ssl->in_buf = mbedtls_calloc( 1, in_buf_len ); + if( ssl->in_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len ) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->out_buf_len = out_buf_len; +#endif + ssl->out_buf = mbedtls_calloc( 1, out_buf_len ); + if( ssl->out_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len ) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + + mbedtls_ssl_reset_in_out_pointers( ssl ); + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + memset( &ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info) ); +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + goto error; + + return( 0 ); + +error: + mbedtls_free( ssl->in_buf ); + mbedtls_free( ssl->out_buf ); + + ssl->conf = NULL; + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = 0; + ssl->out_buf_len = 0; +#endif + ssl->in_buf = NULL; + ssl->out_buf = NULL; + + ssl->in_hdr = NULL; + ssl->in_ctr = NULL; + ssl->in_len = NULL; + ssl->in_iv = NULL; + ssl->in_msg = NULL; + + ssl->out_hdr = NULL; + ssl->out_ctr = NULL; + ssl->out_len = NULL; + ssl->out_iv = NULL; + ssl->out_msg = NULL; + + return( ret ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) + */ +int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; + size_t out_buf_len = ssl->out_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + +#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \ + !defined(MBEDTLS_SSL_SRV_C) + ((void) partial); +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + + /* Cancel any possibly running timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); + memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; + + ssl->in_offt = NULL; + mbedtls_ssl_reset_in_out_pointers( ssl ); + + ssl->in_msgtype = 0; + ssl->in_msglen = 0; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset( ssl ); +#endif + + ssl->in_hslen = 0; + ssl->nb_zero = 0; + + ssl->keep_current_message = 0; + + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) + ssl->split_done = 0; +#endif + + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); + + ssl->transform_in = NULL; + ssl->transform_out = NULL; + + ssl->session_in = NULL; + ssl->session_out = NULL; + + memset( ssl->out_buf, 0, out_buf_len ); + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + if( partial == 0 ) +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + { + ssl->in_left = 0; + memset( ssl->in_buf, 0, in_buf_len ); + } + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_reset != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); + if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + ssl->transform = NULL; + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(MBEDTLS_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + if( partial == 0 ) +#endif + { + mbedtls_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * SSL set accessors + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) +{ + conf->endpoint = endpoint; +} + +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) +{ + conf->transport = transport; +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) +{ + conf->anti_replay = mode; +} +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) +{ + conf->badmac_limit = limit; +} +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ) +{ + ssl->disable_datagram_packing = !allow_packing; +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, + uint32_t min, uint32_t max ) +{ + conf->hs_timeout_min = min; + conf->hs_timeout_max = max; +} +#endif + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) +{ + conf->authmode = authmode; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + conf->f_vrfy = f_vrfy; + conf->p_vrfy = p_vrfy; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + conf->f_rng = f_rng; + conf->p_rng = p_rng; +} + +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ) +{ + conf->f_dbg = f_dbg; + conf->p_dbg = p_dbg; +} + +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ) +{ + ssl->p_bio = p_bio; + ssl->f_send = f_send; + ssl->f_recv = f_recv; + ssl->f_recv_timeout = f_recv_timeout; +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ) +{ + ssl->mtu = mtu; +} +#endif + +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) +{ + conf->read_timeout = timeout; +} + +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ) +{ + ssl->p_timer = p_timer; + ssl->f_set_timer = f_set_timer; + ssl->f_get_timer = f_get_timer; + + /* Make sure we start with no timer running */ + mbedtls_ssl_set_timer( ssl, 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + int (*f_get_cache)(void *, mbedtls_ssl_session *), + int (*f_set_cache)(void *, const mbedtls_ssl_session *) ) +{ + conf->p_cache = p_cache; + conf->f_get_cache = f_get_cache; + conf->f_set_cache = f_set_cache; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ( ret = mbedtls_ssl_session_copy( ssl->session_negotiate, + session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ) +{ + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; +} + +void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, + const int *ciphersuites, + int major, int minor ) +{ + if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) + return; + + if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) + return; + + conf->ciphersuite_list[minor] = ciphersuites; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ) +{ + conf->cert_profile = profile; +} + +/* Append a new keycert entry to a (possibly empty) list */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, + mbedtls_x509_crt *cert, + mbedtls_pk_context *key ) +{ + mbedtls_ssl_key_cert *new_cert; + + new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; + + /* Update head is the list was null, else add to the end */ + if( *head == NULL ) + { + *head = new_cert; + } + else + { + mbedtls_ssl_key_cert *cur = *head; + while( cur->next != NULL ) + cur = cur->next; + cur->next = new_cert; + } + + return( 0 ); +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + conf->ca_chain = ca_chain; + conf->ca_crl = ca_crl; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->f_ca_cb = NULL; + conf->p_ca_cb = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb ) +{ + conf->f_ca_cb = f_ca_cb; + conf->p_ca_cb = p_ca_cb; + + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->ca_chain = NULL; + conf->ca_crl = NULL; +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, + own_cert, pk_key ) ); +} + +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + ssl->handshake->sni_ca_chain = ca_chain; + ssl->handshake->sni_ca_crl = ca_crl; +} + +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ) +{ + ssl->handshake->sni_authmode = authmode; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + ssl->f_vrfy = f_vrfy; + ssl->p_vrfy = p_vrfy; +} +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Set EC J-PAKE password for current handshake + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + mbedtls_ecjpake_role role; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + role = MBEDTLS_ECJPAKE_SERVER; + else + role = MBEDTLS_ECJPAKE_CLIENT; + + return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, + role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + pw, pw_len ) ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + +static void ssl_conf_remove_psk( mbedtls_ssl_config *conf ) +{ + /* Remove reference to existing PSK, if any. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) ) + { + /* The maintenance of the PSK key slot is the + * user's responsibility. */ + conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } + /* This and the following branch should never + * be taken simultaenously as we maintain the + * invariant that raw and opaque PSKs are never + * configured simultaneously. As a safeguard, + * though, `else` is omitted here. */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + + /* Remove reference to PSK identity, if any. */ + if( conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +} + +/* This function assumes that PSK identity in the SSL config is unset. + * It checks that the provided identity is well-formed and attempts + * to make a copy of it in the SSL config. + * On failure, the PSK identity in the config remains unset. */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf, + unsigned char const *psk_identity, + size_t psk_identity_len ) +{ + /* Identity len will be encoded on two bytes */ + if( psk_identity == NULL || + ( psk_identity_len >> 16 ) != 0 || + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ); + if( conf->psk_identity == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + conf->psk_identity_len = psk_identity_len; + memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); + + return( 0 ); +} + +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* Remove opaque/raw PSK + PSK Identity */ + ssl_conf_remove_psk( conf ); + + /* Check and set raw PSK */ + if( psk == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( psk_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + conf->psk_len = psk_len; + memcpy( conf->psk, psk, conf->psk_len ); + + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity( conf, psk_identity, psk_identity_len ); + if( ret != 0 ) + ssl_conf_remove_psk( conf ); + + return( ret ); +} + +static void ssl_remove_psk( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) ) + { + ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ssl->handshake->psk != NULL ) + { + mbedtls_platform_zeroize( ssl->handshake->psk, + ssl->handshake->psk_len ); + mbedtls_free( ssl->handshake->psk ); + ssl->handshake->psk_len = 0; + } +} + +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ) +{ + if( psk == NULL || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_remove_psk( ssl ); + + if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + ssl->handshake->psk_len = psk_len; + memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, + psa_key_id_t psk, + const unsigned char *psk_identity, + size_t psk_identity_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* Clear opaque/raw PSK + PSK Identity, if present. */ + ssl_conf_remove_psk( conf ); + + /* Check and set opaque PSK */ + if( mbedtls_svc_key_id_is_null( psk ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + conf->psk_opaque = psk; + + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity( conf, psk_identity, + psk_identity_len ); + if( ret != 0 ) + ssl_conf_remove_psk( conf ); + + return( ret ); +} + +int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, + psa_key_id_t psk ) +{ + if( ( mbedtls_svc_key_id_is_null( psk ) ) || + ( ssl->handshake == NULL ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_remove_psk( ssl ); + ssl->handshake->psk_opaque = psk; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ) +{ + conf->f_psk = f_psk; + conf->p_psk = p_psk; +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 || + ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + + if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + + if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/* + * Set the minimum length for Diffie-Hellman parameters + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ) +{ + conf->dhm_min_bitlen = bitlen; +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Set allowed/preferred hashes for handshake signatures + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ) +{ + conf->sig_hashes = hashes; +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECP_C) +/* + * Set the allowed elliptic curves + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curve_list ) +{ + conf->curve_list = curve_list; +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; + + /* Check if new hostname is valid before + * making any change to current one */ + if( hostname != NULL ) + { + hostname_len = strlen( hostname ); + + if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ + + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } + + /* Passing NULL as hostname shall clear the old one */ + + if( hostname == NULL ) + { + ssl->hostname = NULL; + } + else + { + ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); + if( ssl->hostname == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->hostname, hostname, hostname_len ); + + ssl->hostname[hostname_len] = '\0'; + } + + return( 0 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + conf->f_sni = f_sni; + conf->p_sni = p_sni; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) +{ + size_t cur_len, tot_len; + const char **p; + + /* + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. + */ + tot_len = 0; + for( p = protos; *p != NULL; p++ ) + { + cur_len = strlen( *p ); + tot_len += cur_len; + + if( ( cur_len == 0 ) || + ( cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN ) || + ( tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->alpn_list = protos; + + return( 0 ); +} + +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf, + int support_mki_value ) +{ + conf->dtls_srtp_mki_support = support_mki_value; +} + +int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl, + unsigned char *mki_value, + uint16_t mki_len ) +{ + if( mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED ) + { + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + memcpy( ssl->dtls_srtp_info.mki_value, mki_value, mki_len ); + ssl->dtls_srtp_info.mki_len = mki_len; + return( 0 ); +} + +int mbedtls_ssl_conf_dtls_srtp_protection_profiles( mbedtls_ssl_config *conf, + const mbedtls_ssl_srtp_profile *profiles ) +{ + const mbedtls_ssl_srtp_profile *p; + size_t list_size = 0; + + /* check the profiles list: all entry must be valid, + * its size cannot be more than the total number of supported profiles, currently 4 */ + for( p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET && + list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH; + p++ ) + { + if( mbedtls_ssl_check_srtp_profile_value( *p ) != MBEDTLS_TLS_SRTP_UNSET ) + { + list_size++; + } + else + { + /* unsupported value, stop parsing and set the size to an error value */ + list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1; + } + } + + if( list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH ) + { + conf->dtls_srtp_profile_list = NULL; + conf->dtls_srtp_profile_list_len = 0; + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->dtls_srtp_profile_list = profiles; + conf->dtls_srtp_profile_list_len = list_size; + + return( 0 ); +} + +void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl, + mbedtls_dtls_srtp_info *dtls_srtp_info ) +{ + dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile; + /* do not copy the mki value if there is no chosen profile */ + if( dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) + { + dtls_srtp_info->mki_len = 0; + } + else + { + dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len; + memcpy( dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->max_major_ver = major; + conf->max_minor_ver = minor; +} + +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->min_major_ver = major; + conf->min_minor_ver = minor; +} + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) +{ + conf->fallback = fallback; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) +{ + conf->encrypt_then_mac = etm; +} +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) +{ + conf->extended_ms = ems; +} +#endif + +#if defined(MBEDTLS_ARC4_C) +void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) +{ + conf->arc4_disabled = arc4; +} +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) +{ + if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || + ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) +{ + conf->trunc_hmac = truncate; +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) +{ + conf->cbc_record_splitting = split; +} +#endif + +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) +{ + conf->allow_legacy_renegotiation = allow_legacy; +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) +{ + conf->disable_renegotiation = renegotiation; +} + +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) +{ + conf->renego_max_records = max_records; +} + +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ) +{ + memcpy( conf->renego_period, period, 8 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) +{ + conf->session_tickets = use_tickets; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ) +{ + conf->f_ticket_write = f_ticket_write; + conf->f_ticket_parse = f_ticket_parse; + conf->p_ticket = p_ticket; +} +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXPORT_KEYS) +void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ) +{ + conf->f_export_keys = f_export_keys; + conf->p_export_keys = p_export_keys; +} + +void mbedtls_ssl_conf_export_keys_ext_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_export_keys_ext_t *f_export_keys_ext, + void *p_export_keys ) +{ + conf->f_export_keys_ext = f_export_keys_ext; + conf->p_export_keys = p_export_keys; +} +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *async_config_data ) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_config_data = async_config_data; +} + +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ) +{ + return( conf->p_async_config_data ); +} + +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake == NULL ) + return( NULL ); + else + return( ssl->handshake->user_async_ctx ); +} + +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ) +{ + if( ssl->handshake != NULL ) + ssl->handshake->user_async_ctx = ctx; +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/* + * SSL get accessors + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) +{ + if( ssl->session != NULL ) + return( ssl->session->verify_result ); + + if( ssl->session_negotiate != NULL ) + return( ssl->session_negotiate->verify_result ); + + return( 0xFFFFFFFF ); +} + +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "DTLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "DTLSv1.2" ); + + default: + return( "unknown (DTLS)" ); + } + } +#endif + + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_0: + return( "SSLv3.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_1: + return( "TLSv1.0" ); + + case MBEDTLS_SSL_MINOR_VERSION_2: + return( "TLSv1.1" ); + + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + return( "unknown" ); + } +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_MAX_CONTENT_LEN; + size_t read_mfl; + + /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE ) + { + return ssl_mfl_code_to_length( ssl->conf->mfl_code ); + } + + /* Check if a smaller max length was negotiated */ + if( ssl->session_out != NULL ) + { + read_mfl = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); + if( read_mfl < max_len ) + { + max_len = read_mfl; + } + } + + // During a handshake, use the value being negotiated + if( ssl->session_negotiate != NULL ) + { + read_mfl = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + if( read_mfl < max_len ) + { + max_len = read_mfl; + } + } + + return( max_len ); +} + +size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len; + + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); + + /* Check if a smaller max length was negotiated */ + if( ssl->session_out != NULL && + ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); + } + + /* During a handshake, use the value being negotiated */ + if( ssl->session_negotiate != NULL && + ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + } + + return( max_len ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + return mbedtls_ssl_get_output_max_frag_len( ssl ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) +{ + /* Return unlimited mtu for client hello messages to avoid fragmentation. */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO || + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) ) + return ( 0 ); + + if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) + return( ssl->mtu ); + + if( ssl->mtu == 0 ) + return( ssl->handshake->mtu ); + + return( ssl->mtu < ssl->handshake->mtu ? + ssl->mtu : ssl->handshake->mtu ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + (void) ssl; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( mbedtls_ssl_get_current_mtu( ssl ) != 0 ) + { + const size_t mtu = mbedtls_ssl_get_current_mtu( ssl ); + const int ret = mbedtls_ssl_get_record_expansion( ssl ); + const size_t overhead = (size_t) ret; + + if( ret < 0 ) + return( ret ); + + if( mtu <= overhead ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( max_len > mtu - overhead ) + max_len = mtu - overhead; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + + return( (int) max_len ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + return( ssl->session->peer_cert ); +#else + return( NULL ); +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, + mbedtls_ssl_session *dst ) +{ + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( mbedtls_ssl_session_copy( dst, ssl->session ) ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return( NULL ); + + return( ssl->session ); +} + +/* + * Define ticket header determining Mbed TLS version + * and structure of the ticket. + */ + +/* + * Define bitflag determining compile-time settings influencing + * structure of serialized SSL sessions. + */ + +#if defined(MBEDTLS_HAVE_TIME) +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0 +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0 +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0 +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 0 +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0 +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3 +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 4 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 5 +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 6 + +#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ + ( (uint16_t) ( \ + ( SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC << SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) ) ) + +static unsigned char ssl_serialized_session_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + MBEDTLS_BYTE_1( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ), + MBEDTLS_BYTE_0( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ), +}; + +/* + * Serialize a session in the following format: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * opaque mbedtls_version[3]; // major, minor, patch + * opaque session_format[2]; // version-specific 16-bit field determining + * // the format of the remaining + * // serialized data. + * + * Note: When updating the format, remember to keep + * these version+format bytes. + * + * // In this version, `session_format` determines + * // the setting of those compile-time + * // configuration options which influence + * // the structure of mbedtls_ssl_session. + * uint64 start_time; + * uint8 ciphersuite[2]; // defined by the standard + * uint8 compression; // 0 or 1 + * uint8 session_id_len; // at most 32 + * opaque session_id[32]; + * opaque master[48]; // fixed length in the standard + * uint32 verify_result; + * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert + * opaque ticket<0..2^24-1>; // length 0 means no ticket + * uint32 ticket_lifetime; + * uint8 mfl_code; // up to 255 according to standard + * uint8 trunc_hmac; // 0 or 1 + * uint8 encrypt_then_mac; // 0 or 1 + * + * The order is the same as in the definition of the structure, except + * verify_result is put before peer_cert so that all mandatory fields come + * together in one block. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_session_save( const mbedtls_ssl_session *session, + unsigned char omit_header, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t used = 0; +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + + if( !omit_header ) + { + /* + * Add version identifier + */ + + used += sizeof( ssl_serialized_session_header ); + + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ); + p += sizeof( ssl_serialized_session_header ); + } + } + + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + used += 8; + + if( used <= buf_len ) + { + start = (uint64_t) session->start; + + MBEDTLS_PUT_UINT64_BE( start, p, 0 ); + p += 8; + } +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * Basic mandatory fields + */ + used += 2 /* ciphersuite */ + + 1 /* compression */ + + 1 /* id_len */ + + sizeof( session->id ) + + sizeof( session->master ) + + 4; /* verify_result */ + + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT16_BE( session->ciphersuite, p, 0 ); + p += 2; + + *p++ = MBEDTLS_BYTE_0( session->compression ); + + *p++ = MBEDTLS_BYTE_0( session->id_len ); + memcpy( p, session->id, 32 ); + p += 32; + + memcpy( p, session->master, 48 ); + p += 48; + + MBEDTLS_PUT_UINT32_BE( session->verify_result, p, 0 ); + p += 4; + } + + /* + * Peer's end-entity certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( session->peer_cert == NULL ) + cert_len = 0; + else + cert_len = session->peer_cert->raw.len; + + used += 3 + cert_len; + + if( used <= buf_len ) + { + *p++ = MBEDTLS_BYTE_2( cert_len ); + *p++ = MBEDTLS_BYTE_1( cert_len ); + *p++ = MBEDTLS_BYTE_0( cert_len ); + + if( session->peer_cert != NULL ) + { + memcpy( p, session->peer_cert->raw.p, cert_len ); + p += cert_len; + } + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( session->peer_cert_digest != NULL ) + { + used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len; + if( used <= buf_len ) + { + *p++ = (unsigned char) session->peer_cert_digest_type; + *p++ = (unsigned char) session->peer_cert_digest_len; + memcpy( p, session->peer_cert_digest, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; + } + } + else + { + used += 2; + if( used <= buf_len ) + { + *p++ = (unsigned char) MBEDTLS_MD_NONE; + *p++ = 0; + } + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * Session ticket if any, plus associated data + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */ + + if( used <= buf_len ) + { + *p++ = MBEDTLS_BYTE_2( session->ticket_len ); + *p++ = MBEDTLS_BYTE_1( session->ticket_len ); + *p++ = MBEDTLS_BYTE_0( session->ticket_len ); + + if( session->ticket != NULL ) + { + memcpy( p, session->ticket, session->ticket_len ); + p += session->ticket_len; + } + + MBEDTLS_PUT_UINT32_BE( session->ticket_lifetime, p, 0 ); + p += 4; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + used += 1; + + if( used <= buf_len ) + *p++ = session->mfl_code; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + used += 1; + + if( used <= buf_len ) + *p++ = (unsigned char)( ( session->trunc_hmac ) & 0xFF ); +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + used += 1; + + if( used <= buf_len ) + *p++ = MBEDTLS_BYTE_0( session->encrypt_then_mac ); +#endif + + /* Done */ + *olen = used; + + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + return( 0 ); +} + +/* + * Public wrapper for ssl_session_save() + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + return( ssl_session_save( session, 0, buf, buf_len, olen ) ); +} + +/* + * Deserialize session, see mbedtls_ssl_session_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error, and has an extra option omit_header. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_session_load( mbedtls_ssl_session *session, + unsigned char omit_header, + const unsigned char *buf, + size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( !omit_header ) + { + /* + * Check version identifier + */ + + if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( memcmp( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_session_header ); + } + + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + if( 8 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + start = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; + + session->start = (time_t) start; +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * Basic mandatory fields + */ + if( 2 + 1 + 1 + 32 + 48 + 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ciphersuite = ( p[0] << 8 ) | p[1]; + p += 2; + + session->compression = *p++; + + session->id_len = *p++; + memcpy( session->id, p, 32 ); + p += 32; + + memcpy( session->master, p, 48 ); + p += 48; + + session->verify_result = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; + + /* Immediately clear invalid pointer values that have been read, in case + * we exit early before we replaced them with valid ones. */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + session->peer_cert = NULL; +#else + session->peer_cert_digest = NULL; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + session->ticket = NULL; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Peer certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* Deserialize CRT from the end of the ticket. */ + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len != 0 ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( cert_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( session->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( session->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Deserialize CRT digest from the end of the ticket. */ + if( 2 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; + session->peer_cert_digest_len = (size_t) *p++; + + if( session->peer_cert_digest_len != 0 ) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type( session->peer_cert_digest_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( session->peer_cert_digest_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert_digest = + mbedtls_calloc( 1, session->peer_cert_digest_len ); + if( session->peer_cert_digest == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->peer_cert_digest, p, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; + } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * Session ticket and associated data + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( session->ticket_len != 0 ) + { + if( session->ticket_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket = mbedtls_calloc( 1, session->ticket_len ); + if( session->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->ticket, p, session->ticket_len ); + p += session->ticket_len; + } + + if( 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_lifetime = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->mfl_code = *p++; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->trunc_hmac = *p++; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->encrypt_then_mac = *p++; +#endif + + /* Done, should have consumed entire buffer */ + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Deserialize session: public wrapper for error cleaning + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_session_load( session, 0, buf, len ); + + if( ret != 0 ) + mbedtls_ssl_session_free( session ); + + return( ret ); +} + +/* + * Perform a single step of the SSL handshake + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ret = mbedtls_ssl_handshake_client_step( ssl ); +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ret = mbedtls_ssl_handshake_server_step( ssl ); +#endif + + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + /* Sanity checks */ + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " + "mbedtls_ssl_set_timer_cb() for DTLS" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + /* Main handshake loop */ + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. + */ +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; + } +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return( ret ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) +{ + mbedtls_ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if( handshake == NULL ) + return; + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 ) + { + ssl->conf->f_async_cancel( ssl ); + handshake->async_in_progress = 0; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) + mbedtls_md5_free( &handshake->fin_md5 ); + mbedtls_sha1_free( &handshake->fin_sha1 ); +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &handshake->fin_sha256_psa ); +#else + mbedtls_sha256_free( &handshake->fin_sha256 ); +#endif +#endif +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &handshake->fin_sha384_psa ); +#else + mbedtls_sha512_free( &handshake->fin_sha512 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_free( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( handshake->ecjpake_cache ); + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + /* explicit void pointer cast for buggy MS compiler */ + mbedtls_free( (void *) handshake->curves ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( handshake->psk != NULL ) + { + mbedtls_platform_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_free( handshake->psk ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); + if( handshake->ecrs_peer_cert != NULL ) + { + mbedtls_x509_crt_free( handshake->ecrs_peer_cert ); + mbedtls_free( handshake->ecrs_peer_cert ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_free( &handshake->peer_pubkey ); +#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_free( handshake->verify_cookie ); + mbedtls_ssl_flight_free( handshake->flight ); + mbedtls_ssl_buffering_free( ssl ); +#endif + +#if defined(MBEDTLS_ECDH_C) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key( handshake->ecdh_psa_privkey ); +#endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */ + + mbedtls_platform_zeroize( handshake, + sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too big - reallocate. Because of the way Mbed TLS + * processes datagrams and the fact that a datagram is allowed to have + * several records in it, it is possible that the I/O buffers are not + * empty at this stage */ + handle_buffer_resizing( ssl, 1, mbedtls_ssl_get_input_buflen( ssl ), + mbedtls_ssl_get_output_buflen( ssl ) ); +#endif +} + +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_clear_peer_cert( session ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( session->ticket ); +#endif + + mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); +} + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 0u +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_ALPN) +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u +#endif /* MBEDTLS_SSL_ALPN */ + +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2 +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3 + +#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \ + ( (uint32_t) ( \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT ) | \ + 0u ) ) + +static unsigned char ssl_serialized_context_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + MBEDTLS_BYTE_1( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ), + MBEDTLS_BYTE_0( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ), + MBEDTLS_BYTE_2( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ), + MBEDTLS_BYTE_1( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ), + MBEDTLS_BYTE_0( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ), +}; + +/* + * Serialize a full SSL context + * + * The format of the serialized data is: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * // header + * opaque mbedtls_version[3]; // major, minor, patch + * opaque context_format[5]; // version-specific field determining + * // the format of the remaining + * // serialized data. + * Note: When updating the format, remember to keep these + * version+format bytes. (We may make their size part of the API.) + * + * // session sub-structure + * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() + * // transform sub-structure + * uint8 random[64]; // ServerHello.random+ClientHello.random + * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value + * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use + * // fields from ssl_context + * uint32 badmac_seen; // DTLS: number of records with failing MAC + * uint64 in_window_top; // DTLS: last validated record seq_num + * uint64 in_window; // DTLS: bitmask for replay protection + * uint8 disable_datagram_packing; // DTLS: only one record per datagram + * uint64 cur_out_ctr; // Record layer: outgoing sequence number + * uint16 mtu; // DTLS: path mtu (max outgoing fragment size) + * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol + * + * Note that many fields of the ssl_context or sub-structures are not + * serialized, as they fall in one of the following categories: + * + * 1. forced value (eg in_left must be 0) + * 2. pointer to dynamically-allocated memory (eg session, transform) + * 3. value can be re-derived from other data (eg session keys from MS) + * 4. value was temporary (eg content of input buffer) + * 5. value will be provided by the user again (eg I/O callbacks and context) + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t used = 0; + size_t session_len; + int ret = 0; + + /* + * Enforce usage restrictions, see "return BAD_INPUT_DATA" in + * this function's documentation. + * + * These are due to assumptions/limitations in the implementation. Some of + * them are likely to stay (no handshake in progress) some might go away + * (only DTLS) but are currently used to simplify the implementation. + */ + /* The initial handshake must be over */ + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Initial handshake isn't over" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->handshake != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Handshake isn't completed" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Double-check that sub-structures are indeed ready */ + if( ssl->transform == NULL || ssl->session == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Serialised structures aren't ready" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* There must be no pending incoming or outgoing data */ + if( mbedtls_ssl_check_pending( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending incoming data" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->out_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending outgoing data" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Protocol must be DLTS, not TLS */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only DTLS is supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Version must be 1.2 */ + if( ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* We must be using an AEAD ciphersuite */ + if( mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only AEAD ciphersuites supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Renegotiation must not be enabled */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Renegotiation must not be enabled" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } +#endif + + /* + * Version and format identifier + */ + used += sizeof( ssl_serialized_context_header ); + + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_context_header, + sizeof( ssl_serialized_context_header ) ); + p += sizeof( ssl_serialized_context_header ); + } + + /* + * Session (length + data) + */ + ret = ssl_session_save( ssl->session, 1, NULL, 0, &session_len ); + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + return( ret ); + + used += 4 + session_len; + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT32_BE( session_len, p, 0 ); + p += 4; + + ret = ssl_session_save( ssl->session, 1, + p, session_len, &session_len ); + if( ret != 0 ) + return( ret ); + + p += session_len; + } + + /* + * Transform + */ + used += sizeof( ssl->transform->randbytes ); + if( used <= buf_len ) + { + memcpy( p, ssl->transform->randbytes, + sizeof( ssl->transform->randbytes ) ); + p += sizeof( ssl->transform->randbytes ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + used += 2 + ssl->transform->in_cid_len + ssl->transform->out_cid_len; + if( used <= buf_len ) + { + *p++ = ssl->transform->in_cid_len; + memcpy( p, ssl->transform->in_cid, ssl->transform->in_cid_len ); + p += ssl->transform->in_cid_len; + + *p++ = ssl->transform->out_cid_len; + memcpy( p, ssl->transform->out_cid, ssl->transform->out_cid_len ); + p += ssl->transform->out_cid_len; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Saved fields from top-level ssl_context structure + */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + used += 4; + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT32_BE( ssl->badmac_seen, p, 0 ); + p += 4; + } +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + used += 16; + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT64_BE( ssl->in_window_top, p, 0 ); + p += 8; + + MBEDTLS_PUT_UINT64_BE( ssl->in_window, p, 0 ); + p += 8; + } +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 1; + if( used <= buf_len ) + { + *p++ = ssl->disable_datagram_packing; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + used += 8; + if( used <= buf_len ) + { + memcpy( p, ssl->cur_out_ctr, 8 ); + p += 8; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 2; + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT16_BE( ssl->mtu, p, 0 ); + p += 2; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + { + const uint8_t alpn_len = ssl->alpn_chosen + ? (uint8_t) strlen( ssl->alpn_chosen ) + : 0; + + used += 1 + alpn_len; + if( used <= buf_len ) + { + *p++ = alpn_len; + + if( ssl->alpn_chosen != NULL ) + { + memcpy( p, ssl->alpn_chosen, alpn_len ); + p += alpn_len; + } + } + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * Done + */ + *olen = used; + + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used ); + + return( mbedtls_ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * Helper to get TLS 1.2 PRF from ciphersuite + * (Duplicates bits of logic from ssl_set_handshake_prfs().) + */ +typedef int (*tls_prf_fn)( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); +static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id ) +{ +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + return( tls_prf_sha384 ); +#else + (void) ciphersuite_id; +#endif + return( tls_prf_sha256 ); +} + +/* + * Deserialize context, see mbedtls_ssl_context_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +static int ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + size_t session_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * The context should have been freshly setup or reset. + * Give the user an error in case of obvious misuse. + * (Checking session is useful because it won't be NULL if we're + * renegotiating, or if the user mistakenly loaded a session first.) + */ + if( ssl->state != MBEDTLS_SSL_HELLO_REQUEST || + ssl->session != NULL ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * We can't check that the config matches the initial one, but we can at + * least check it matches the requirements for serializing. + */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->conf->max_major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->conf->min_major_ver > MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->conf->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 || + ssl->conf->min_minor_ver > MBEDTLS_SSL_MINOR_VERSION_3 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || +#endif + 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "context to load", buf, len ); + + /* + * Check version identifier + */ + if( (size_t)( end - p ) < sizeof( ssl_serialized_context_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( memcmp( p, ssl_serialized_context_header, + sizeof( ssl_serialized_context_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_context_header ); + + /* + * Session + */ + if( (size_t)( end - p ) < 4 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session_len = ( (size_t) p[0] << 24 ) | + ( (size_t) p[1] << 16 ) | + ( (size_t) p[2] << 8 ) | + ( (size_t) p[3] ); + p += 4; + + /* This has been allocated by ssl_handshake_init(), called by + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->session = ssl->session_negotiate; + ssl->session_in = ssl->session; + ssl->session_out = ssl->session; + ssl->session_negotiate = NULL; + + if( (size_t)( end - p ) < session_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ret = ssl_session_load( ssl->session, 1, p, session_len ); + if( ret != 0 ) + { + mbedtls_ssl_session_free( ssl->session ); + return( ret ); + } + + p += session_len; + + /* + * Transform + */ + + /* This has been allocated by ssl_handshake_init(), called by + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->transform = ssl->transform_negotiate; + ssl->transform_in = ssl->transform; + ssl->transform_out = ssl->transform; + ssl->transform_negotiate = NULL; + + /* Read random bytes and populate structure */ + if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ret = ssl_populate_transform( ssl->transform, + ssl->session->ciphersuite, + ssl->session->master, +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl->session->encrypt_then_mac, +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl->session->trunc_hmac, +#endif +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + ssl->session->compression, +#endif + ssl_tls12prf_from_cs( ssl->session->ciphersuite ), + p, /* currently pointing to randbytes */ + MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */ + ssl->conf->endpoint, + ssl ); + if( ret != 0 ) + return( ret ); + + p += sizeof( ssl->transform->randbytes ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Read connection IDs and store them */ + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->transform->in_cid_len = *p++; + + if( (size_t)( end - p ) < ssl->transform->in_cid_len + 1u ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->transform->in_cid, p, ssl->transform->in_cid_len ); + p += ssl->transform->in_cid_len; + + ssl->transform->out_cid_len = *p++; + + if( (size_t)( end - p ) < ssl->transform->out_cid_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->transform->out_cid, p, ssl->transform->out_cid_len ); + p += ssl->transform->out_cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Saved fields from top-level ssl_context structure + */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( (size_t)( end - p ) < 4 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->badmac_seen = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( (size_t)( end - p ) < 16 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->in_window_top = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; + + ssl->in_window = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->disable_datagram_packing = *p++; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( (size_t)( end - p ) < 8 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->cur_out_ctr, p, 8 ); + p += 8; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( (size_t)( end - p ) < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->mtu = ( p[0] << 8 ) | p[1]; + p += 2; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + { + uint8_t alpn_len; + const char **cur; + + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + alpn_len = *p++; + + if( alpn_len != 0 && ssl->conf->alpn_list != NULL ) + { + /* alpn_chosen should point to an item in the configured list */ + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + if( strlen( *cur ) == alpn_len && + memcmp( p, cur, alpn_len ) == 0 ) + { + ssl->alpn_chosen = *cur; + break; + } + } + } + + /* can only happen on conf mismatch */ + if( alpn_len != 0 && ssl->alpn_chosen == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + p += alpn_len; + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * Forced fields from top-level ssl_context structure + * + * Most of them already set to the correct value by mbedtls_ssl_init() and + * mbedtls_ssl_reset(), so we only need to set the remaining ones. + */ + ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; + + /* Adjust pointers for header fields of outgoing records to + * the given transform, accounting for explicit IV and CID. */ + mbedtls_ssl_update_out_pointers( ssl, ssl->transform ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->in_epoch = 1; +#endif + + /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, + * which we don't want - otherwise we'd end up freeing the wrong transform + * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform() + * inappropriately. */ + if( ssl->handshake != NULL ) + { + mbedtls_ssl_handshake_free( ssl ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + } + + /* + * Done - should have consumed entire buffer + */ + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Deserialize context: public wrapper for error cleaning + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *context, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_context_load( context, buf, len ); + + if( ret != 0 ) + mbedtls_ssl_free( context ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + +/* + * Free an SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_buf != NULL ) + { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + mbedtls_platform_zeroize( ssl->out_buf, out_buf_len ); + mbedtls_free( ssl->out_buf ); + ssl->out_buf = NULL; + } + + if( ssl->in_buf != NULL ) + { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + mbedtls_platform_zeroize( ssl->in_buf, in_buf_len ); + mbedtls_free( ssl->in_buf ); + ssl->in_buf = NULL; + } + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->compress_buf != NULL ) + { + mbedtls_platform_zeroize( ssl->compress_buf, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); + mbedtls_free( ssl->compress_buf ); + } +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + + if( ssl->handshake ) + { + mbedtls_ssl_handshake_free( ssl ); + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + mbedtls_ssl_session_free( ssl->session_negotiate ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + } + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + if( mbedtls_ssl_hw_record_finish != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); + mbedtls_ssl_hw_record_finish( ssl ); + } +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + mbedtls_free( ssl->cli_id ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Initialze mbedtls_ssl_config + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) +{ + memset( conf, 0, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +static int ssl_preset_default_hashes[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, +#endif +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif + +static int ssl_preset_suiteb_ciphersuites[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + 0 +}; + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +static int ssl_preset_suiteb_hashes[] = { + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_NONE +}; +#endif + +#if defined(MBEDTLS_ECP_C) +static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_ECP_DP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_ECP_DP_SECP384R1, +#endif + MBEDTLS_ECP_DP_NONE +}; +#endif + +/* + * Load default in mbedtls_ssl_config + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ) +{ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#endif + + /* Use the functions here so that they are covered in tests, + * but otherwise access member directly for efficiency */ + mbedtls_ssl_conf_endpoint( conf, endpoint ); + mbedtls_ssl_conf_transport( conf, transport ); + + /* + * Things that are common to all presets + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; +#endif + } +#endif + +#if defined(MBEDTLS_ARC4_C) + conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + conf->f_cookie_write = ssl_cookie_write_dummy; + conf->f_cookie_check = ssl_cookie_check_dummy; +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; + conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset( conf->renego_period, 0x00, 2 ); + memset( conf->renego_period + 2, 0xFF, 6 ); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + const unsigned char dhm_p[] = + MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; + const unsigned char dhm_g[] = + MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + + if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf, + dhm_p, sizeof( dhm_p ), + dhm_g, sizeof( dhm_g ) ) ) != 0 ) + { + return( ret ); + } + } +#endif + + /* + * Preset-specific defaults + */ + switch( preset ) + { + /* + * NSA Suite B + */ + case MBEDTLS_SSL_PRESET_SUITEB: + conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + ssl_preset_suiteb_ciphersuites; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + conf->sig_hashes = ssl_preset_suiteb_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = ssl_preset_suiteb_curves; +#endif + break; + + /* + * Default + */ + default: + conf->min_major_ver = ( MBEDTLS_SSL_MIN_MAJOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ? + MBEDTLS_SSL_MIN_MAJOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; + conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ? + MBEDTLS_SSL_MIN_MINOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; +#endif + + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = + conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = + mbedtls_ssl_list_ciphersuites(); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + conf->sig_hashes = ssl_preset_default_hashes; +#endif + +#if defined(MBEDTLS_ECP_C) + conf->curve_list = mbedtls_ecp_grp_id_list(); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + conf->dhm_min_bitlen = 1024; +#endif + } + + return( 0 ); +} + +/* + * Free mbedtls_ssl_config + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) +{ +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + + if( conf->psk_identity != NULL ) + { + mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_key_cert_free( conf->key_cert ); +#endif + + mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_PK_C) && \ + ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) +/* + * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX + */ +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) + return( MBEDTLS_SSL_SIG_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) + return( MBEDTLS_SSL_SIG_ECDSA ); +#endif + return( MBEDTLS_SSL_SIG_ANON ); +} + +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) +{ + switch( type ) { + case MBEDTLS_PK_RSA: + return( MBEDTLS_SSL_SIG_RSA ); + case MBEDTLS_PK_ECDSA: + case MBEDTLS_PK_ECKEY: + return( MBEDTLS_SSL_SIG_ECDSA ); + default: + return( MBEDTLS_SSL_SIG_ANON ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + return( MBEDTLS_PK_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_SSL_SIG_ECDSA: + return( MBEDTLS_PK_ECDSA ); +#endif + default: + return( MBEDTLS_PK_NONE ); + } +} +#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + return( set->rsa ); + case MBEDTLS_PK_ECDSA: + return( set->ecdsa ); + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + if( set->rsa == MBEDTLS_MD_NONE ) + set->rsa = md_alg; + break; + + case MBEDTLS_PK_ECDSA: + if( set->ecdsa == MBEDTLS_MD_NONE ) + set->ecdsa = md_alg; + break; + + default: + break; + } +} + +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ) +{ + set->rsa = md_alg; + set->ecdsa = md_alg; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/* + * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX + */ +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + return( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA224: + return( MBEDTLS_MD_SHA224 ); + case MBEDTLS_SSL_HASH_SHA256: + return( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_SSL_HASH_SHA384: + return( MBEDTLS_MD_SHA384 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA512: + return( MBEDTLS_MD_SHA512 ); +#endif + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* + * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX + */ +unsigned char mbedtls_ssl_hash_from_md_alg( int md ) +{ + switch( md ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( MBEDTLS_SSL_HASH_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( MBEDTLS_SSL_HASH_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( MBEDTLS_SSL_HASH_SHA224 ); + case MBEDTLS_MD_SHA256: + return( MBEDTLS_SSL_HASH_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( MBEDTLS_SSL_HASH_SHA384 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( MBEDTLS_SSL_HASH_SHA512 ); +#endif + default: + return( MBEDTLS_SSL_HASH_NONE ); + } +} + +#if defined(MBEDTLS_ECP_C) +/* + * Check if a curve proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_group_id *gid; + + if( ssl->conf->curve_list == NULL ) + return( -1 ); + + for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) + if( *gid == grp_id ) + return( 0 ); + + return( -1 ); +} + +/* + * Same as mbedtls_ssl_check_curve() but takes a TLS ID for the curve. + */ +int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( tls_id ); + if( curve_info == NULL ) + return( -1 ); + return( mbedtls_ssl_check_curve( ssl, curve_info->grp_id ) ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Check if a hash proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ) +{ + const int *cur; + + if( ssl->conf->sig_hashes == NULL ) + return( -1 ); + + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + if( *cur == (int) md ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ) +{ + int ret = 0; +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + int usage = 0; +#endif +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + const char *ext_oid; + size_t ext_len; +#endif + +#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ + !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + ((void) cert); + ((void) cert_endpoint); + ((void) flags); +#endif + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + break; + + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + break; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + usage = MBEDTLS_X509_KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case MBEDTLS_KEY_EXCHANGE_NONE: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + } + + if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; + ret = -1; + } +#else + ((void) ciphersuite); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); + } + else + { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); + } + + if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; + ret = -1; + } +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + + return( ret ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + + switch( md ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + ssl->handshake->calc_verify = ssl_calc_verify_tls; + break; +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; + } + + return 0; +#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ + (void) ssl; + (void) md; + + return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) +int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl, + unsigned char *output, + unsigned char *data, size_t data_len ) +{ + int ret = 0; + mbedtls_md5_context mbedtls_md5; + mbedtls_sha1_context mbedtls_sha1; + + mbedtls_md5_init( &mbedtls_md5 ); + mbedtls_sha1_init( &mbedtls_sha1 ); + + /* + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * md5_hash + * MD5(ClientHello.random + ServerHello.random + * + ServerParams); + * sha_hash + * SHA(ClientHello.random + ServerHello.random + * + ServerParams); + */ + if( ( ret = mbedtls_md5_starts_ret( &mbedtls_md5 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_update_ret( &mbedtls_md5, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_md5_finish_ret( &mbedtls_md5, output ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md5_finish_ret", ret ); + goto exit; + } + + if( ( ret = mbedtls_sha1_starts_ret( &mbedtls_sha1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_starts_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, + ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_update_ret( &mbedtls_sha1, data, + data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_update_ret", ret ); + goto exit; + } + if( ( ret = mbedtls_sha1_finish_ret( &mbedtls_sha1, + output + 16 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha1_finish_ret", ret ); + goto exit; + } + +exit: + mbedtls_md5_free( &mbedtls_md5 ); + mbedtls_sha1_free( &mbedtls_sha1 ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); + +} +#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ + MBEDTLS_SSL_PROTO_TLS1_1 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + psa_status_t status; + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( md_alg ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform PSA-based computation of digest of ServerKeyExchange" ) ); + + if( ( status = psa_hash_setup( &hash_operation, + hash_alg ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_setup", status ); + goto exit; + } + + if( ( status = psa_hash_update( &hash_operation, ssl->handshake->randbytes, + 64 ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status ); + goto exit; + } + + if( ( status = psa_hash_update( &hash_operation, + data, data_len ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status ); + goto exit; + } + + if( ( status = psa_hash_finish( &hash_operation, hash, PSA_HASH_MAX_SIZE, + hashlen ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_finish", status ); + goto exit; + } + +exit: + if( status != PSA_SUCCESS ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + switch( status ) + { + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */ + case PSA_ERROR_BUFFER_TOO_SMALL: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + default: + return( MBEDTLS_ERR_MD_HW_ACCEL_FAILED ); + } + } + return( 0 ); +} + +#else + +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + int ret = 0; + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + *hashlen = mbedtls_md_get_size( md_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform mbedtls-based computation of digest of ServerKeyExchange" ) ); + + mbedtls_md_init( &ctx ); + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto exit; + } + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); + goto exit; + } + +exit: + mbedtls_md_free( &ctx ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ + MBEDTLS_SSL_PROTO_TLS1_2 */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c new file mode 100644 index 0000000..3de6f03 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c @@ -0,0 +1,349 @@ +/* + * TLS 1.3 key schedule + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 ( the "License" ); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + +#include "mbedtls/hkdf.h" +#include "mbedtls/ssl_internal.h" +#include "ssl_tls13_keys.h" + +#include +#include + +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + .name = string, + +struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels = +{ + /* This seems to work in C, despite the string literal being one + * character too long due to the 0-termination. */ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; + +#undef MBEDTLS_SSL_TLS1_3_LABEL + +/* + * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule. + * + * The HkdfLabel is specified in RFC 8446 as follows: + * + * struct HkdfLabel { + * uint16 length; // Length of expanded key material + * opaque label<7..255>; // Always prefixed by "tls13 " + * opaque context<0..255>; // Usually a communication transcript hash + * }; + * + * Parameters: + * - desired_length: Length of expanded key material + * Even though the standard allows expansion to up to + * 2**16 Bytes, TLS 1.3 never uses expansion to more than + * 255 Bytes, so we require `desired_length` to be at most + * 255. This allows us to save a few Bytes of code by + * hardcoding the writing of the high bytes. + * - (label, llen): label + label length, without "tls13 " prefix + * The label length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN + * It is the caller's responsibility to ensure this. + * All (label, label length) pairs used in TLS 1.3 + * can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(). + * - (ctx, clen): context + context length + * The context length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN + * It is the caller's responsibility to ensure this. + * - dst: Target buffer for HkdfLabel structure, + * This MUST be a writable buffer of size + * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes. + * - dlen: Pointer at which to store the actual length of + * the HkdfLabel structure on success. + */ + +static const char tls1_3_label_prefix[6] = "tls13 "; + +#define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( label_len, context_len ) \ + ( 2 /* expansion length */ \ + + 1 /* label length */ \ + + label_len \ + + 1 /* context length */ \ + + context_len ) + +#define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \ + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( \ + sizeof(tls1_3_label_prefix) + \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN, \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN ) + +static void ssl_tls1_3_hkdf_encode_label( + size_t desired_length, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *dst, size_t *dlen ) +{ + size_t total_label_len = + sizeof(tls1_3_label_prefix) + llen; + size_t total_hkdf_lbl_len = + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( total_label_len, clen ); + + unsigned char *p = dst; + + /* Add the size of the expanded key material. + * We're hardcoding the high byte to 0 here assuming that we never use + * TLS 1.3 HKDF key expansion to more than 255 Bytes. */ +#if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255 +#error "The implementation of ssl_tls1_3_hkdf_encode_label() is not fit for the \ + value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN" +#endif + + *p++ = 0; + *p++ = MBEDTLS_BYTE_0( desired_length ); + + /* Add label incl. prefix */ + *p++ = MBEDTLS_BYTE_0( total_label_len ); + memcpy( p, tls1_3_label_prefix, sizeof(tls1_3_label_prefix) ); + p += sizeof(tls1_3_label_prefix); + memcpy( p, label, llen ); + p += llen; + + /* Add context value */ + *p++ = MBEDTLS_BYTE_0( clen ); + if( clen != 0 ) + memcpy( p, ctx, clen ); + + /* Return total length to the caller. */ + *dlen = total_hkdf_lbl_len; +} + +int mbedtls_ssl_tls1_3_hkdf_expand_label( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_md_info_t *md; + unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ]; + size_t hkdf_label_len; + + if( llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN ) + { + /* Should never happen since this is an internal + * function, and we know statically which labels + * are allowed. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN ) + { + /* Should not happen, as above. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN ) + { + /* Should not happen, as above. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_tls1_3_hkdf_encode_label( blen, + label, llen, + ctx, clen, + hkdf_label, + &hkdf_label_len ); + + return( mbedtls_hkdf_expand( md, + secret, slen, + hkdf_label, hkdf_label_len, + buf, blen ) ); +} + +/* + * The traffic keying material is generated from the following inputs: + * + * - One secret value per sender. + * - A purpose value indicating the specific value being generated + * - The desired lengths of key and IV. + * + * The expansion itself is based on HKDF: + * + * [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length ) + * [sender]_write_iv = HKDF-Expand-Label( Secret, "iv" , "", iv_length ) + * + * [sender] denotes the sending side and the Secret value is provided + * by the function caller. Note that we generate server and client side + * keys in a single function call. + */ +int mbedtls_ssl_tls1_3_make_traffic_keys( + mbedtls_md_type_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, + size_t slen, size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys ) +{ + int ret = 0; + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + client_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ), + NULL, 0, + keys->client_write_key, key_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + server_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ), + NULL, 0, + keys->server_write_key, key_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + client_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ), + NULL, 0, + keys->client_write_iv, iv_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + server_secret, slen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ), + NULL, 0, + keys->server_write_iv, iv_len ); + if( ret != 0 ) + return( ret ); + + keys->key_len = key_len; + keys->iv_len = iv_len; + + return( 0 ); +} + +int mbedtls_ssl_tls1_3_derive_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + int ctx_hashed, + unsigned char *dstbuf, size_t buflen ) +{ + int ret; + unsigned char hashed_context[ MBEDTLS_MD_MAX_SIZE ]; + + const mbedtls_md_info_t *md; + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED ) + { + ret = mbedtls_md( md, ctx, clen, hashed_context ); + if( ret != 0 ) + return( ret ); + clen = mbedtls_md_get_size( md ); + } + else + { + if( clen > sizeof(hashed_context) ) + { + /* This should never happen since this function is internal + * and the code sets `ctx_hashed` correctly. + * Let's double-check nonetheless to not run at the risk + * of getting a stack overflow. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( hashed_context, ctx, clen ); + } + + return( mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg, + secret, slen, + label, llen, + hashed_context, clen, + dstbuf, buflen ) ); +} + +int mbedtls_ssl_tls1_3_evolve_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new ) +{ + int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + size_t hlen, ilen; + unsigned char tmp_secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 }; + unsigned char tmp_input [ MBEDTLS_MD_MAX_SIZE ] = { 0 }; + + const mbedtls_md_info_t *md; + md = mbedtls_md_info_from_type( hash_alg ); + if( md == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md ); + + /* For non-initial runs, call Derive-Secret( ., "derived", "") + * on the old secret. */ + if( secret_old != NULL ) + { + ret = mbedtls_ssl_tls1_3_derive_secret( + hash_alg, + secret_old, hlen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ), + NULL, 0, /* context */ + MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + tmp_secret, hlen ); + if( ret != 0 ) + goto cleanup; + } + + if( input != NULL ) + { + memcpy( tmp_input, input, input_len ); + ilen = input_len; + } + else + { + ilen = hlen; + } + + /* HKDF-Extract takes a salt and input key material. + * The salt is the old secret, and the input key material + * is the input secret (PSK / ECDHE). */ + ret = mbedtls_hkdf_extract( md, + tmp_secret, hlen, + tmp_input, ilen, + secret_new ); + if( ret != 0 ) + goto cleanup; + + ret = 0; + + cleanup: + + mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) ); + mbedtls_platform_zeroize( tmp_input, sizeof(tmp_input) ); + return( ret ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h new file mode 100644 index 0000000..7089049 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h @@ -0,0 +1,274 @@ +/* + * TLS 1.3 key schedule + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 ( the "License" ); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if !defined(MBEDTLS_SSL_TLS1_3_KEYS_H) +#define MBEDTLS_SSL_TLS1_3_KEYS_H + +/* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at + * the point of use. See e.g. the definition of mbedtls_ssl_tls1_3_labels_union + * below. */ +#define MBEDTLS_SSL_TLS1_3_LABEL_LIST \ + MBEDTLS_SSL_TLS1_3_LABEL( finished , "finished" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( resumption , "resumption" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( traffic_upd , "traffic upd" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( exporter , "exporter" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( key , "key" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( iv , "iv" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_hs_traffic, "c hs traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_ap_traffic, "c ap traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_e_traffic , "c e traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_hs_traffic, "s hs traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_ap_traffic, "s ap traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_e_traffic , "s e traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( e_exp_master, "e exp master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( res_master , "res master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( exp_master , "exp master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( ext_binder , "ext binder" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( res_binder , "res binder" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( derived , "derived" ) + +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + const unsigned char name [ sizeof(string) - 1 ]; + +union mbedtls_ssl_tls1_3_labels_union +{ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +struct mbedtls_ssl_tls1_3_labels_struct +{ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +#undef MBEDTLS_SSL_TLS1_3_LABEL + +extern const struct mbedtls_ssl_tls1_3_labels_struct mbedtls_ssl_tls1_3_labels; + +#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( LABEL ) \ + mbedtls_ssl_tls1_3_labels.LABEL, \ + sizeof(mbedtls_ssl_tls1_3_labels.LABEL) + +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \ + sizeof( union mbedtls_ssl_tls1_3_labels_union ) + +/* The maximum length of HKDF contexts used in the TLS 1.3 standard. + * Since contexts are always hashes of message transcripts, this can + * be approximated from above by the maximum hash size. */ +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN \ + MBEDTLS_MD_MAX_SIZE + +/* Maximum desired length for expanded key material generated + * by HKDF-Expand-Label. + * + * Warning: If this ever needs to be increased, the implementation + * ssl_tls1_3_hkdf_encode_label() in ssl_tls13_keys.c needs to be + * adjusted since it currently assumes that HKDF key expansion + * is never used with more than 255 Bytes of output. */ +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255 + +/** + * \brief The \c HKDF-Expand-Label function from + * the TLS 1.3 standard RFC 8446. + * + * + * HKDF-Expand-Label( Secret, Label, Context, Length ) = + * HKDF-Expand( Secret, HkdfLabel, Length ) + * + * + * \param hash_alg The identifier for the hash algorithm to use. + * \param secret The \c Secret argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p slen Bytes. + * \param slen The length of \p secret in Bytes. + * \param label The \c Label argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p llen Bytes. + * \param llen The length of \p label in Bytes. + * \param ctx The \c Context argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p clen Bytes. + * \param clen The length of \p context in Bytes. + * \param buf The destination buffer to hold the expanded secret. + * This must be a writable buffer of length \p blen Bytes. + * \param blen The desired size of the expanded secret in Bytes. + * + * \returns \c 0 on success. + * \return A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_hkdf_expand_label( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function is part of the TLS 1.3 key schedule. + * It extracts key and IV for the actual client/server traffic + * from the client/server traffic secrets. + * + * From RFC 8446: + * + * + * [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length) + * [sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)* + * + * + * \param hash_alg The identifier for the hash algorithm to be used + * for the HKDF-based expansion of the secret. + * \param client_secret The client traffic secret. + * This must be a readable buffer of size \p slen Bytes + * \param server_secret The server traffic secret. + * This must be a readable buffer of size \p slen Bytes + * \param slen Length of the secrets \p client_secret and + * \p server_secret in Bytes. + * \param key_len The desired length of the key to be extracted in Bytes. + * \param iv_len The desired length of the IV to be extracted in Bytes. + * \param keys The address of the structure holding the generated + * keys and IVs. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_make_traffic_keys( + mbedtls_md_type_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, + size_t slen, size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys ); + + +#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 +#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 + +/** + * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446. + * + * + * Derive-Secret( Secret, Label, Messages ) = + * HKDF-Expand-Label( Secret, Label, + * Hash( Messages ), + * Hash.Length ) ) + * + * + * \param hash_alg The identifier for the hash function used for the + * applications of HKDF. + * \param secret The \c Secret argument to the \c Derive-Secret function. + * This must be a readable buffer of length \p slen Bytes. + * \param slen The length of \p secret in Bytes. + * \param label The \c Label argument to the \c Derive-Secret function. + * This must be a readable buffer of length \p llen Bytes. + * \param llen The length of \p label in Bytes. + * \param ctx The hash of the \c Messages argument to the + * \c Derive-Secret function, or the \c Messages argument + * itself, depending on \p context_already_hashed. + * \param clen The length of \p hash. + * \param ctx_hashed This indicates whether the \p ctx contains the hash of + * the \c Messages argument in the application of the + * \c Derive-Secret function + * (value MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED), or whether + * it is the content of \c Messages itself, in which case + * the function takes care of the hashing + * (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED). + * \param dstbuf The target buffer to write the output of + * \c Derive-Secret to. This must be a writable buffer of + * size \p buflen Bytes. + * \param buflen The length of \p dstbuf in Bytes. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls1_3_derive_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t slen, + const unsigned char *label, size_t llen, + const unsigned char *ctx, size_t clen, + int ctx_hashed, + unsigned char *dstbuf, size_t buflen ); + +/** + * \brief Compute the next secret in the TLS 1.3 key schedule + * + * The TLS 1.3 key schedule proceeds as follows to compute + * the three main secrets during the handshake: The early + * secret for early data, the handshake secret for all + * other encrypted handshake messages, and the master + * secret for all application traffic. + * + * + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * (EC)DHE -> HKDF-Extract = Handshake Secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * 0 -> HKDF-Extract = Master Secret + * + * + * Each of the three secrets in turn is the basis for further + * key derivations, such as the derivation of traffic keys and IVs; + * see e.g. mbedtls_ssl_tls1_3_make_traffic_keys(). + * + * This function implements one step in this evolution of secrets: + * + * + * old_secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * input -> HKDF-Extract = new_secret + * + * + * \param hash_alg The identifier for the hash function used for the + * applications of HKDF. + * \param secret_old The address of the buffer holding the old secret + * on function entry. If not \c NULL, this must be a + * readable buffer whose size matches the output size + * of the hash function represented by \p hash_alg. + * If \c NULL, an all \c 0 array will be used instead. + * \param input The address of the buffer holding the additional + * input for the key derivation (e.g., the PSK or the + * ephemeral (EC)DH secret). If not \c NULL, this must be + * a readable buffer whose size \p input_len Bytes. + * If \c NULL, an all \c 0 array will be used instead. + * \param input_len The length of \p input in Bytes. + * \param secret_new The address of the buffer holding the new secret + * on function exit. This must be a writable buffer + * whose size matches the output size of the hash + * function represented by \p hash_alg. + * This may be the same as \p secret_old. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ + +int mbedtls_ssl_tls1_3_evolve_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new ); + +#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c new file mode 100644 index 0000000..5e0aaa4 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/threading.c @@ -0,0 +1,187 @@ +/* + * Threading abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#include "common.h" + +#if defined(MBEDTLS_THREADING_C) + +#include "mbedtls/threading.h" + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) + +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ + +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define THREADING_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ + +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return; + + /* A nonzero value of is_valid indicates a successfully initialized + * mutex. This is a workaround for not being able to return an error + * code for this function. The lock/unlock functions return an error + * if is_valid is nonzero. The Mbed TLS unit test code uses this field + * to distinguish more states of the mutex; see + * tests/src/threading_helpers for details. */ + mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; +} + +static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || !mutex->is_valid ) + return; + + (void) pthread_mutex_destroy( &mutex->mutex ); + mutex->is_valid = 0; +} + +static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; + +/* + * With pthreads we can statically initialize mutexes + */ +#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } + +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_THREADING_ALT) +static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); +} +static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return; +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; + +/* + * Set functions pointers and initialize global mutexes + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) +{ + mbedtls_mutex_init = mutex_init; + mbedtls_mutex_free = mutex_free; + mbedtls_mutex_lock = mutex_lock; + mbedtls_mutex_unlock = mutex_unlock; + +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +#if defined(MBEDTLS_FS_IO) +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +#endif +#if defined(THREADING_USE_GMTIME) +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif + +#endif /* MBEDTLS_THREADING_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c new file mode 100644 index 0000000..57bc9bc --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/timing.c @@ -0,0 +1,529 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_TIMING_C) + +#include "mbedtls/timing.h" + +#if !defined(MBEDTLS_TIMING_ALT) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" +#endif + +#ifndef asm +#define asm __asm +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +/* time.h should be included independently of MBEDTLS_HAVE_TIME. If the + * platform matches the ifdefs above, it will be used. */ +#include +#include +struct _hr_time +{ + struct timeval start; +}; +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +/* some versions of mingw-64 have 32-bit longs even on x84_64 */ +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__i386__) || ( \ + ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm volatile( "mftbu %0" : "=r" (tbu0) ); + asm volatile( "mftb %0" : "=r" (tbl ) ); + asm volatile( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) + +#define HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long mbedtls_timing_hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { + gettimeofday( &tv_init, NULL ); + hardclock_init = 1; + } + + gettimeofday( &tv_cur, NULL ); + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} +#endif /* !HAVE_HARDCLOCK */ + +volatile int mbedtls_timing_alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + QueryPerformanceCounter( &t->start ); + return( 0 ); + } + else + { + unsigned long delta; + LARGE_INTEGER now, hfreq; + QueryPerformanceCounter( &now ); + QueryPerformanceFrequency( &hfreq ); + delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul + / hfreq.QuadPart ); + return( delta ); + } +} + +/* It's OK to use a global because alarm() is supposed to be global anyway */ +static DWORD alarmMs; + +static void TimerProc( void *TimerContext ) +{ + (void) TimerContext; + Sleep( alarmMs ); + mbedtls_timing_alarmed = 1; + /* _endthread will be called implicitly on return + * That ensures execution of thread funcition's epilogue */ +} + +void mbedtls_set_alarm( int seconds ) +{ + if( seconds == 0 ) + { + /* No need to create a thread for this simple case. + * Also, this shorcut is more reliable at least on MinGW32 */ + mbedtls_timing_alarmed = 1; + return; + } + + mbedtls_timing_alarmed = 0; + alarmMs = seconds * 1000; + (void) _beginthread( TimerProc, 0, NULL ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + gettimeofday( &t->start, NULL ); + return( 0 ); + } + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.tv_usec - t->start.tv_usec ) / 1000; + return( delta ); + } +} + +static void sighandler( int signum ) +{ + mbedtls_timing_alarmed = 1; + signal( signum, sighandler ); +} + +void mbedtls_set_alarm( int seconds ) +{ + mbedtls_timing_alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); + if( seconds == 0 ) + { + /* alarm(0) cancelled any previous pending alarm, but the + handler won't fire, so raise the flag straight away. */ + mbedtls_timing_alarmed = 1; + } +} + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->fin_ms == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); + + if( elapsed_ms >= ctx->fin_ms ) + return( 2 ); + + if( elapsed_ms >= ctx->int_ms ) + return( 1 ); + + return( 0 ); +} + + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing mbedtls_timing_hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct mbedtls_timing_hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +#define FAIL do \ + { \ + if( verbose != 0 ) \ + { \ + mbedtls_printf( "failed at line %d\n", __LINE__ ); \ + mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ + cycles, ratio, millisecs, secs, hardfail, \ + (unsigned long) a, (unsigned long) b ); \ + mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ + mbedtls_timing_get_timer( &hires, 0 ), \ + mbedtls_timing_get_timer( &ctx.timer, 0 ), \ + mbedtls_timing_get_delay( &ctx ) ); \ + } \ + return( 1 ); \ + } while( 0 ) + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int mbedtls_timing_self_test( int verbose ) +{ + unsigned long cycles = 0, ratio = 0; + unsigned long millisecs = 0, secs = 0; + int hardfail = 0; + struct mbedtls_timing_hr_time hires; + uint32_t a = 0, b = 0; + mbedtls_timing_delay_context ctx; + + if( verbose != 0 ) + mbedtls_printf( " TIMING tests note: will take some time!\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); + + { + secs = 1; + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + mbedtls_set_alarm( (int) secs ); + while( !mbedtls_timing_alarmed ) + ; + + millisecs = mbedtls_timing_get_timer( &hires, 0 ); + + /* For some reason on Windows it looks like alarm has an extra delay + * (maybe related to creating a new thread). Allow some room here. */ + if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) + FAIL; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); + + { + a = 800; + b = 400; + mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */ + + busy_msleep( a - a / 4 ); /* T = a - a/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; + + busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b ); /* T = a + b + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 2 ) + FAIL; + } + + mbedtls_timing_set_delay( &ctx, 0, 0 ); + busy_msleep( 200 ); + if( mbedtls_timing_get_delay( &ctx ) != -1 ) + FAIL; + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (ignored)\n" ); + + goto hard_test_done; + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +hard_test_done: + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ +#endif /* !MBEDTLS_TIMING_ALT */ +#endif /* MBEDTLS_TIMING_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/version.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/version.c new file mode 100644 index 0000000..32a0d7d --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/version.c @@ -0,0 +1,44 @@ +/* + * Version information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" +#include + +unsigned int mbedtls_version_get_number( void ) +{ + return( MBEDTLS_VERSION_NUMBER ); +} + +void mbedtls_version_get_string( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING, + sizeof( MBEDTLS_VERSION_STRING ) ); +} + +void mbedtls_version_get_string_full( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING_FULL, + sizeof( MBEDTLS_VERSION_STRING_FULL ) ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c new file mode 100644 index 0000000..40c9520 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/version_features.c @@ -0,0 +1,872 @@ +/* + * Version feature information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" + +#include + +static const char * const features[] = { +#if defined(MBEDTLS_VERSION_FEATURES) +#if defined(MBEDTLS_HAVE_ASM) + "MBEDTLS_HAVE_ASM", +#endif /* MBEDTLS_HAVE_ASM */ +#if defined(MBEDTLS_NO_UDBL_DIVISION) + "MBEDTLS_NO_UDBL_DIVISION", +#endif /* MBEDTLS_NO_UDBL_DIVISION */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) + "MBEDTLS_NO_64BIT_MULTIPLICATION", +#endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ +#if defined(MBEDTLS_HAVE_SSE2) + "MBEDTLS_HAVE_SSE2", +#endif /* MBEDTLS_HAVE_SSE2 */ +#if defined(MBEDTLS_HAVE_TIME) + "MBEDTLS_HAVE_TIME", +#endif /* MBEDTLS_HAVE_TIME */ +#if defined(MBEDTLS_HAVE_TIME_DATE) + "MBEDTLS_HAVE_TIME_DATE", +#endif /* MBEDTLS_HAVE_TIME_DATE */ +#if defined(MBEDTLS_PLATFORM_MEMORY) + "MBEDTLS_PLATFORM_MEMORY", +#endif /* MBEDTLS_PLATFORM_MEMORY */ +#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) + "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) + "MBEDTLS_PLATFORM_EXIT_ALT", +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) + "MBEDTLS_PLATFORM_TIME_ALT", +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) + "MBEDTLS_PLATFORM_FPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) + "MBEDTLS_PLATFORM_PRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) + "MBEDTLS_PLATFORM_SNPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) + "MBEDTLS_PLATFORM_VSNPRINTF_ALT", +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) + "MBEDTLS_PLATFORM_NV_SEED_ALT", +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ +#if defined(MBEDTLS_DEPRECATED_WARNING) + "MBEDTLS_DEPRECATED_WARNING", +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#if defined(MBEDTLS_DEPRECATED_REMOVED) + "MBEDTLS_DEPRECATED_REMOVED", +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#if defined(MBEDTLS_CHECK_PARAMS) + "MBEDTLS_CHECK_PARAMS", +#endif /* MBEDTLS_CHECK_PARAMS */ +#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) + "MBEDTLS_CHECK_PARAMS_ASSERT", +#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ +#if defined(MBEDTLS_TIMING_ALT) + "MBEDTLS_TIMING_ALT", +#endif /* MBEDTLS_TIMING_ALT */ +#if defined(MBEDTLS_AES_ALT) + "MBEDTLS_AES_ALT", +#endif /* MBEDTLS_AES_ALT */ +#if defined(MBEDTLS_ARC4_ALT) + "MBEDTLS_ARC4_ALT", +#endif /* MBEDTLS_ARC4_ALT */ +#if defined(MBEDTLS_ARIA_ALT) + "MBEDTLS_ARIA_ALT", +#endif /* MBEDTLS_ARIA_ALT */ +#if defined(MBEDTLS_BLOWFISH_ALT) + "MBEDTLS_BLOWFISH_ALT", +#endif /* MBEDTLS_BLOWFISH_ALT */ +#if defined(MBEDTLS_CAMELLIA_ALT) + "MBEDTLS_CAMELLIA_ALT", +#endif /* MBEDTLS_CAMELLIA_ALT */ +#if defined(MBEDTLS_CCM_ALT) + "MBEDTLS_CCM_ALT", +#endif /* MBEDTLS_CCM_ALT */ +#if defined(MBEDTLS_CHACHA20_ALT) + "MBEDTLS_CHACHA20_ALT", +#endif /* MBEDTLS_CHACHA20_ALT */ +#if defined(MBEDTLS_CHACHAPOLY_ALT) + "MBEDTLS_CHACHAPOLY_ALT", +#endif /* MBEDTLS_CHACHAPOLY_ALT */ +#if defined(MBEDTLS_CMAC_ALT) + "MBEDTLS_CMAC_ALT", +#endif /* MBEDTLS_CMAC_ALT */ +#if defined(MBEDTLS_DES_ALT) + "MBEDTLS_DES_ALT", +#endif /* MBEDTLS_DES_ALT */ +#if defined(MBEDTLS_DHM_ALT) + "MBEDTLS_DHM_ALT", +#endif /* MBEDTLS_DHM_ALT */ +#if defined(MBEDTLS_ECJPAKE_ALT) + "MBEDTLS_ECJPAKE_ALT", +#endif /* MBEDTLS_ECJPAKE_ALT */ +#if defined(MBEDTLS_GCM_ALT) + "MBEDTLS_GCM_ALT", +#endif /* MBEDTLS_GCM_ALT */ +#if defined(MBEDTLS_NIST_KW_ALT) + "MBEDTLS_NIST_KW_ALT", +#endif /* MBEDTLS_NIST_KW_ALT */ +#if defined(MBEDTLS_MD2_ALT) + "MBEDTLS_MD2_ALT", +#endif /* MBEDTLS_MD2_ALT */ +#if defined(MBEDTLS_MD4_ALT) + "MBEDTLS_MD4_ALT", +#endif /* MBEDTLS_MD4_ALT */ +#if defined(MBEDTLS_MD5_ALT) + "MBEDTLS_MD5_ALT", +#endif /* MBEDTLS_MD5_ALT */ +#if defined(MBEDTLS_POLY1305_ALT) + "MBEDTLS_POLY1305_ALT", +#endif /* MBEDTLS_POLY1305_ALT */ +#if defined(MBEDTLS_RIPEMD160_ALT) + "MBEDTLS_RIPEMD160_ALT", +#endif /* MBEDTLS_RIPEMD160_ALT */ +#if defined(MBEDTLS_RSA_ALT) + "MBEDTLS_RSA_ALT", +#endif /* MBEDTLS_RSA_ALT */ +#if defined(MBEDTLS_SHA1_ALT) + "MBEDTLS_SHA1_ALT", +#endif /* MBEDTLS_SHA1_ALT */ +#if defined(MBEDTLS_SHA256_ALT) + "MBEDTLS_SHA256_ALT", +#endif /* MBEDTLS_SHA256_ALT */ +#if defined(MBEDTLS_SHA512_ALT) + "MBEDTLS_SHA512_ALT", +#endif /* MBEDTLS_SHA512_ALT */ +#if defined(MBEDTLS_XTEA_ALT) + "MBEDTLS_XTEA_ALT", +#endif /* MBEDTLS_XTEA_ALT */ +#if defined(MBEDTLS_ECP_ALT) + "MBEDTLS_ECP_ALT", +#endif /* MBEDTLS_ECP_ALT */ +#if defined(MBEDTLS_MD2_PROCESS_ALT) + "MBEDTLS_MD2_PROCESS_ALT", +#endif /* MBEDTLS_MD2_PROCESS_ALT */ +#if defined(MBEDTLS_MD4_PROCESS_ALT) + "MBEDTLS_MD4_PROCESS_ALT", +#endif /* MBEDTLS_MD4_PROCESS_ALT */ +#if defined(MBEDTLS_MD5_PROCESS_ALT) + "MBEDTLS_MD5_PROCESS_ALT", +#endif /* MBEDTLS_MD5_PROCESS_ALT */ +#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) + "MBEDTLS_RIPEMD160_PROCESS_ALT", +#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ +#if defined(MBEDTLS_SHA1_PROCESS_ALT) + "MBEDTLS_SHA1_PROCESS_ALT", +#endif /* MBEDTLS_SHA1_PROCESS_ALT */ +#if defined(MBEDTLS_SHA256_PROCESS_ALT) + "MBEDTLS_SHA256_PROCESS_ALT", +#endif /* MBEDTLS_SHA256_PROCESS_ALT */ +#if defined(MBEDTLS_SHA512_PROCESS_ALT) + "MBEDTLS_SHA512_PROCESS_ALT", +#endif /* MBEDTLS_SHA512_PROCESS_ALT */ +#if defined(MBEDTLS_DES_SETKEY_ALT) + "MBEDTLS_DES_SETKEY_ALT", +#endif /* MBEDTLS_DES_SETKEY_ALT */ +#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) + "MBEDTLS_DES_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) + "MBEDTLS_DES3_CRYPT_ECB_ALT", +#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ +#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) + "MBEDTLS_AES_SETKEY_ENC_ALT", +#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ +#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) + "MBEDTLS_AES_SETKEY_DEC_ALT", +#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ +#if defined(MBEDTLS_AES_ENCRYPT_ALT) + "MBEDTLS_AES_ENCRYPT_ALT", +#endif /* MBEDTLS_AES_ENCRYPT_ALT */ +#if defined(MBEDTLS_AES_DECRYPT_ALT) + "MBEDTLS_AES_DECRYPT_ALT", +#endif /* MBEDTLS_AES_DECRYPT_ALT */ +#if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) + "MBEDTLS_ECDH_GEN_PUBLIC_ALT", +#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ +#if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) + "MBEDTLS_ECDH_COMPUTE_SHARED_ALT", +#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + "MBEDTLS_ECDSA_VERIFY_ALT", +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + "MBEDTLS_ECDSA_SIGN_ALT", +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#if defined(MBEDTLS_ECDSA_GENKEY_ALT) + "MBEDTLS_ECDSA_GENKEY_ALT", +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + "MBEDTLS_ECP_INTERNAL_ALT", +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(MBEDTLS_ECP_NO_FALLBACK) + "MBEDTLS_ECP_NO_FALLBACK", +#endif /* MBEDTLS_ECP_NO_FALLBACK */ +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + "MBEDTLS_ECP_ADD_MIXED_ALT", +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + "MBEDTLS_ECP_DOUBLE_JAC_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + "MBEDTLS_ECP_NORMALIZE_JAC_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + "MBEDTLS_TEST_NULL_ENTROPY", +#endif /* MBEDTLS_TEST_NULL_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + "MBEDTLS_ENTROPY_HARDWARE_ALT", +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#if defined(MBEDTLS_AES_ROM_TABLES) + "MBEDTLS_AES_ROM_TABLES", +#endif /* MBEDTLS_AES_ROM_TABLES */ +#if defined(MBEDTLS_AES_FEWER_TABLES) + "MBEDTLS_AES_FEWER_TABLES", +#endif /* MBEDTLS_AES_FEWER_TABLES */ +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + "MBEDTLS_CAMELLIA_SMALL_MEMORY", +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ +#if defined(MBEDTLS_CHECK_RETURN_WARNING) + "MBEDTLS_CHECK_RETURN_WARNING", +#endif /* MBEDTLS_CHECK_RETURN_WARNING */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + "MBEDTLS_CIPHER_MODE_CBC", +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_CFB) + "MBEDTLS_CIPHER_MODE_CFB", +#endif /* MBEDTLS_CIPHER_MODE_CFB */ +#if defined(MBEDTLS_CIPHER_MODE_CTR) + "MBEDTLS_CIPHER_MODE_CTR", +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#if defined(MBEDTLS_CIPHER_MODE_OFB) + "MBEDTLS_CIPHER_MODE_OFB", +#endif /* MBEDTLS_CIPHER_MODE_OFB */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) + "MBEDTLS_CIPHER_MODE_XTS", +#endif /* MBEDTLS_CIPHER_MODE_XTS */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + "MBEDTLS_CIPHER_NULL_CIPHER", +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + "MBEDTLS_CIPHER_PADDING_PKCS7", +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + "MBEDTLS_CIPHER_PADDING_ZEROS", +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) + "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ +#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) + "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", +#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + "MBEDTLS_REMOVE_3DES_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + "MBEDTLS_ECP_DP_SECP192R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + "MBEDTLS_ECP_DP_SECP224R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + "MBEDTLS_ECP_DP_SECP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + "MBEDTLS_ECP_DP_SECP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + "MBEDTLS_ECP_DP_SECP521R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + "MBEDTLS_ECP_DP_SECP192K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + "MBEDTLS_ECP_DP_SECP224K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + "MBEDTLS_ECP_DP_SECP256K1_ENABLED", +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + "MBEDTLS_ECP_DP_BP256R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + "MBEDTLS_ECP_DP_BP384R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + "MBEDTLS_ECP_DP_BP512R1_ENABLED", +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + "MBEDTLS_ECP_DP_CURVE25519_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + "MBEDTLS_ECP_DP_CURVE448_ENABLED", +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ +#if defined(MBEDTLS_ECP_NIST_OPTIM) + "MBEDTLS_ECP_NIST_OPTIM", +#endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + "MBEDTLS_ECP_NO_INTERNAL_RNG", +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + "MBEDTLS_ECP_RESTARTABLE", +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + "MBEDTLS_ECDH_LEGACY_CONTEXT", +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + "MBEDTLS_ECDSA_DETERMINISTIC", +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + "MBEDTLS_PK_PARSE_EC_EXTENDED", +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + "MBEDTLS_ERROR_STRERROR_DUMMY", +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ +#if defined(MBEDTLS_GENPRIME) + "MBEDTLS_GENPRIME", +#endif /* MBEDTLS_GENPRIME */ +#if defined(MBEDTLS_FS_IO) + "MBEDTLS_FS_IO", +#endif /* MBEDTLS_FS_IO */ +#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) + "MBEDTLS_NO_PLATFORM_ENTROPY", +#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ +#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) + "MBEDTLS_ENTROPY_FORCE_SHA256", +#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) + "MBEDTLS_ENTROPY_NV_SEED", +#endif /* MBEDTLS_ENTROPY_NV_SEED */ +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER", +#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ +#if defined(MBEDTLS_MEMORY_DEBUG) + "MBEDTLS_MEMORY_DEBUG", +#endif /* MBEDTLS_MEMORY_DEBUG */ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + "MBEDTLS_MEMORY_BACKTRACE", +#endif /* MBEDTLS_MEMORY_BACKTRACE */ +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) + "MBEDTLS_PK_RSA_ALT_SUPPORT", +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ +#if defined(MBEDTLS_PKCS1_V15) + "MBEDTLS_PKCS1_V15", +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) + "MBEDTLS_PKCS1_V21", +#endif /* MBEDTLS_PKCS1_V21 */ +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + "MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS", +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) + "MBEDTLS_PSA_CRYPTO_CLIENT", +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + "MBEDTLS_PSA_CRYPTO_DRIVERS", +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + "MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG", +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +#if defined(MBEDTLS_PSA_CRYPTO_SPM) + "MBEDTLS_PSA_CRYPTO_SPM", +#endif /* MBEDTLS_PSA_CRYPTO_SPM */ +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) + "MBEDTLS_PSA_INJECT_ENTROPY", +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ +#if defined(MBEDTLS_RSA_NO_CRT) + "MBEDTLS_RSA_NO_CRT", +#endif /* MBEDTLS_RSA_NO_CRT */ +#if defined(MBEDTLS_SELF_TEST) + "MBEDTLS_SELF_TEST", +#endif /* MBEDTLS_SELF_TEST */ +#if defined(MBEDTLS_SHA256_SMALLER) + "MBEDTLS_SHA256_SMALLER", +#endif /* MBEDTLS_SHA256_SMALLER */ +#if defined(MBEDTLS_SHA512_SMALLER) + "MBEDTLS_SHA512_SMALLER", +#endif /* MBEDTLS_SHA512_SMALLER */ +#if defined(MBEDTLS_SHA512_NO_SHA384) + "MBEDTLS_SHA512_NO_SHA384", +#endif /* MBEDTLS_SHA512_NO_SHA384 */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + "MBEDTLS_SSL_ALL_ALERT_MESSAGES", +#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ +#if defined(MBEDTLS_SSL_RECORD_CHECKING) + "MBEDTLS_SSL_RECORD_CHECKING", +#endif /* MBEDTLS_SSL_RECORD_CHECKING */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + "MBEDTLS_SSL_DTLS_CONNECTION_ID", +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + "MBEDTLS_SSL_ASYNC_PRIVATE", +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + "MBEDTLS_SSL_CONTEXT_SERIALIZATION", +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ +#if defined(MBEDTLS_SSL_DEBUG_ALL) + "MBEDTLS_SSL_DEBUG_ALL", +#endif /* MBEDTLS_SSL_DEBUG_ALL */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + "MBEDTLS_SSL_ENCRYPT_THEN_MAC", +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + "MBEDTLS_SSL_FALLBACK_SCSV", +#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + "MBEDTLS_SSL_HW_RECORD_ACCEL", +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + "MBEDTLS_SSL_CBC_RECORD_SPLITTING", +#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + "MBEDTLS_SSL_RENEGOTIATION", +#endif /* MBEDTLS_SSL_RENEGOTIATION */ +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) + "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", +#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ +#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) + "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", +#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + "MBEDTLS_SSL_PROTO_SSL3", +#endif /* MBEDTLS_SSL_PROTO_SSL3 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1) + "MBEDTLS_SSL_PROTO_TLS1", +#endif /* MBEDTLS_SSL_PROTO_TLS1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) + "MBEDTLS_SSL_PROTO_TLS1_1", +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + "MBEDTLS_SSL_PROTO_TLS1_2", +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) + "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL", +#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + "MBEDTLS_SSL_PROTO_DTLS", +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_ALPN) + "MBEDTLS_SSL_ALPN", +#endif /* MBEDTLS_SSL_ALPN */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + "MBEDTLS_SSL_DTLS_ANTI_REPLAY", +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + "MBEDTLS_SSL_DTLS_HELLO_VERIFY", +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ +#if defined(MBEDTLS_SSL_DTLS_SRTP) + "MBEDTLS_SSL_DTLS_SRTP", +#endif /* MBEDTLS_SSL_DTLS_SRTP */ +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + "MBEDTLS_SSL_SESSION_TICKETS", +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#if defined(MBEDTLS_SSL_EXPORT_KEYS) + "MBEDTLS_SSL_EXPORT_KEYS", +#endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + "MBEDTLS_SSL_SERVER_NAME_INDICATION", +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + "MBEDTLS_SSL_TRUNCATED_HMAC", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) + "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH", +#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) + "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) + "MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ +#if defined(MBEDTLS_TEST_HOOKS) + "MBEDTLS_TEST_HOOKS", +#endif /* MBEDTLS_TEST_HOOKS */ +#if defined(MBEDTLS_THREADING_ALT) + "MBEDTLS_THREADING_ALT", +#endif /* MBEDTLS_THREADING_ALT */ +#if defined(MBEDTLS_THREADING_PTHREAD) + "MBEDTLS_THREADING_PTHREAD", +#endif /* MBEDTLS_THREADING_PTHREAD */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + "MBEDTLS_USE_PSA_CRYPTO", +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) + "MBEDTLS_PSA_CRYPTO_CONFIG", +#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ +#if defined(MBEDTLS_VERSION_FEATURES) + "MBEDTLS_VERSION_FEATURES", +#endif /* MBEDTLS_VERSION_FEATURES */ +#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", +#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ +#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", +#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK", +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + "MBEDTLS_X509_CHECK_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) + "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + "MBEDTLS_X509_RSASSA_PSS_SUPPORT", +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + "MBEDTLS_ZLIB_SUPPORT", +#endif /* MBEDTLS_ZLIB_SUPPORT */ +#if defined(MBEDTLS_AESNI_C) + "MBEDTLS_AESNI_C", +#endif /* MBEDTLS_AESNI_C */ +#if defined(MBEDTLS_AES_C) + "MBEDTLS_AES_C", +#endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_ARC4_C) + "MBEDTLS_ARC4_C", +#endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_ASN1_PARSE_C) + "MBEDTLS_ASN1_PARSE_C", +#endif /* MBEDTLS_ASN1_PARSE_C */ +#if defined(MBEDTLS_ASN1_WRITE_C) + "MBEDTLS_ASN1_WRITE_C", +#endif /* MBEDTLS_ASN1_WRITE_C */ +#if defined(MBEDTLS_BASE64_C) + "MBEDTLS_BASE64_C", +#endif /* MBEDTLS_BASE64_C */ +#if defined(MBEDTLS_BIGNUM_C) + "MBEDTLS_BIGNUM_C", +#endif /* MBEDTLS_BIGNUM_C */ +#if defined(MBEDTLS_BLOWFISH_C) + "MBEDTLS_BLOWFISH_C", +#endif /* MBEDTLS_BLOWFISH_C */ +#if defined(MBEDTLS_CAMELLIA_C) + "MBEDTLS_CAMELLIA_C", +#endif /* MBEDTLS_CAMELLIA_C */ +#if defined(MBEDTLS_ARIA_C) + "MBEDTLS_ARIA_C", +#endif /* MBEDTLS_ARIA_C */ +#if defined(MBEDTLS_CCM_C) + "MBEDTLS_CCM_C", +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CERTS_C) + "MBEDTLS_CERTS_C", +#endif /* MBEDTLS_CERTS_C */ +#if defined(MBEDTLS_CHACHA20_C) + "MBEDTLS_CHACHA20_C", +#endif /* MBEDTLS_CHACHA20_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + "MBEDTLS_CHACHAPOLY_C", +#endif /* MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_CIPHER_C) + "MBEDTLS_CIPHER_C", +#endif /* MBEDTLS_CIPHER_C */ +#if defined(MBEDTLS_CMAC_C) + "MBEDTLS_CMAC_C", +#endif /* MBEDTLS_CMAC_C */ +#if defined(MBEDTLS_CTR_DRBG_C) + "MBEDTLS_CTR_DRBG_C", +#endif /* MBEDTLS_CTR_DRBG_C */ +#if defined(MBEDTLS_DEBUG_C) + "MBEDTLS_DEBUG_C", +#endif /* MBEDTLS_DEBUG_C */ +#if defined(MBEDTLS_DES_C) + "MBEDTLS_DES_C", +#endif /* MBEDTLS_DES_C */ +#if defined(MBEDTLS_DHM_C) + "MBEDTLS_DHM_C", +#endif /* MBEDTLS_DHM_C */ +#if defined(MBEDTLS_ECDH_C) + "MBEDTLS_ECDH_C", +#endif /* MBEDTLS_ECDH_C */ +#if defined(MBEDTLS_ECDSA_C) + "MBEDTLS_ECDSA_C", +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_ECJPAKE_C) + "MBEDTLS_ECJPAKE_C", +#endif /* MBEDTLS_ECJPAKE_C */ +#if defined(MBEDTLS_ECP_C) + "MBEDTLS_ECP_C", +#endif /* MBEDTLS_ECP_C */ +#if defined(MBEDTLS_ENTROPY_C) + "MBEDTLS_ENTROPY_C", +#endif /* MBEDTLS_ENTROPY_C */ +#if defined(MBEDTLS_ERROR_C) + "MBEDTLS_ERROR_C", +#endif /* MBEDTLS_ERROR_C */ +#if defined(MBEDTLS_GCM_C) + "MBEDTLS_GCM_C", +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_HAVEGE_C) + "MBEDTLS_HAVEGE_C", +#endif /* MBEDTLS_HAVEGE_C */ +#if defined(MBEDTLS_HKDF_C) + "MBEDTLS_HKDF_C", +#endif /* MBEDTLS_HKDF_C */ +#if defined(MBEDTLS_HMAC_DRBG_C) + "MBEDTLS_HMAC_DRBG_C", +#endif /* MBEDTLS_HMAC_DRBG_C */ +#if defined(MBEDTLS_NIST_KW_C) + "MBEDTLS_NIST_KW_C", +#endif /* MBEDTLS_NIST_KW_C */ +#if defined(MBEDTLS_MD_C) + "MBEDTLS_MD_C", +#endif /* MBEDTLS_MD_C */ +#if defined(MBEDTLS_MD2_C) + "MBEDTLS_MD2_C", +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + "MBEDTLS_MD4_C", +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + "MBEDTLS_MD5_C", +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + "MBEDTLS_MEMORY_BUFFER_ALLOC_C", +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ +#if defined(MBEDTLS_NET_C) + "MBEDTLS_NET_C", +#endif /* MBEDTLS_NET_C */ +#if defined(MBEDTLS_OID_C) + "MBEDTLS_OID_C", +#endif /* MBEDTLS_OID_C */ +#if defined(MBEDTLS_PADLOCK_C) + "MBEDTLS_PADLOCK_C", +#endif /* MBEDTLS_PADLOCK_C */ +#if defined(MBEDTLS_PEM_PARSE_C) + "MBEDTLS_PEM_PARSE_C", +#endif /* MBEDTLS_PEM_PARSE_C */ +#if defined(MBEDTLS_PEM_WRITE_C) + "MBEDTLS_PEM_WRITE_C", +#endif /* MBEDTLS_PEM_WRITE_C */ +#if defined(MBEDTLS_PK_C) + "MBEDTLS_PK_C", +#endif /* MBEDTLS_PK_C */ +#if defined(MBEDTLS_PK_PARSE_C) + "MBEDTLS_PK_PARSE_C", +#endif /* MBEDTLS_PK_PARSE_C */ +#if defined(MBEDTLS_PK_WRITE_C) + "MBEDTLS_PK_WRITE_C", +#endif /* MBEDTLS_PK_WRITE_C */ +#if defined(MBEDTLS_PKCS5_C) + "MBEDTLS_PKCS5_C", +#endif /* MBEDTLS_PKCS5_C */ +#if defined(MBEDTLS_PKCS11_C) + "MBEDTLS_PKCS11_C", +#endif /* MBEDTLS_PKCS11_C */ +#if defined(MBEDTLS_PKCS12_C) + "MBEDTLS_PKCS12_C", +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PLATFORM_C) + "MBEDTLS_PLATFORM_C", +#endif /* MBEDTLS_PLATFORM_C */ +#if defined(MBEDTLS_POLY1305_C) + "MBEDTLS_POLY1305_C", +#endif /* MBEDTLS_POLY1305_C */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + "MBEDTLS_PSA_CRYPTO_C", +#endif /* MBEDTLS_PSA_CRYPTO_C */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + "MBEDTLS_PSA_CRYPTO_SE_C", +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + "MBEDTLS_PSA_CRYPTO_STORAGE_C", +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ +#if defined(MBEDTLS_PSA_ITS_FILE_C) + "MBEDTLS_PSA_ITS_FILE_C", +#endif /* MBEDTLS_PSA_ITS_FILE_C */ +#if defined(MBEDTLS_RIPEMD160_C) + "MBEDTLS_RIPEMD160_C", +#endif /* MBEDTLS_RIPEMD160_C */ +#if defined(MBEDTLS_RSA_C) + "MBEDTLS_RSA_C", +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_SHA1_C) + "MBEDTLS_SHA1_C", +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + "MBEDTLS_SHA256_C", +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + "MBEDTLS_SHA512_C", +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SSL_CACHE_C) + "MBEDTLS_SSL_CACHE_C", +#endif /* MBEDTLS_SSL_CACHE_C */ +#if defined(MBEDTLS_SSL_COOKIE_C) + "MBEDTLS_SSL_COOKIE_C", +#endif /* MBEDTLS_SSL_COOKIE_C */ +#if defined(MBEDTLS_SSL_TICKET_C) + "MBEDTLS_SSL_TICKET_C", +#endif /* MBEDTLS_SSL_TICKET_C */ +#if defined(MBEDTLS_SSL_CLI_C) + "MBEDTLS_SSL_CLI_C", +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + "MBEDTLS_SSL_SRV_C", +#endif /* MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_TLS_C) + "MBEDTLS_SSL_TLS_C", +#endif /* MBEDTLS_SSL_TLS_C */ +#if defined(MBEDTLS_THREADING_C) + "MBEDTLS_THREADING_C", +#endif /* MBEDTLS_THREADING_C */ +#if defined(MBEDTLS_TIMING_C) + "MBEDTLS_TIMING_C", +#endif /* MBEDTLS_TIMING_C */ +#if defined(MBEDTLS_VERSION_C) + "MBEDTLS_VERSION_C", +#endif /* MBEDTLS_VERSION_C */ +#if defined(MBEDTLS_X509_USE_C) + "MBEDTLS_X509_USE_C", +#endif /* MBEDTLS_X509_USE_C */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + "MBEDTLS_X509_CRT_PARSE_C", +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_X509_CRL_PARSE_C) + "MBEDTLS_X509_CRL_PARSE_C", +#endif /* MBEDTLS_X509_CRL_PARSE_C */ +#if defined(MBEDTLS_X509_CSR_PARSE_C) + "MBEDTLS_X509_CSR_PARSE_C", +#endif /* MBEDTLS_X509_CSR_PARSE_C */ +#if defined(MBEDTLS_X509_CREATE_C) + "MBEDTLS_X509_CREATE_C", +#endif /* MBEDTLS_X509_CREATE_C */ +#if defined(MBEDTLS_X509_CRT_WRITE_C) + "MBEDTLS_X509_CRT_WRITE_C", +#endif /* MBEDTLS_X509_CRT_WRITE_C */ +#if defined(MBEDTLS_X509_CSR_WRITE_C) + "MBEDTLS_X509_CSR_WRITE_C", +#endif /* MBEDTLS_X509_CSR_WRITE_C */ +#if defined(MBEDTLS_XTEA_C) + "MBEDTLS_XTEA_C", +#endif /* MBEDTLS_XTEA_C */ +#endif /* MBEDTLS_VERSION_FEATURES */ + NULL +}; + +int mbedtls_version_check_feature( const char *feature ) +{ + const char * const *idx = features; + + if( *idx == NULL ) + return( -2 ); + + if( feature == NULL ) + return( -1 ); + + while( *idx != NULL ) + { + if( !strcmp( *idx, feature ) ) + return( 0 ); + idx++; + } + return( -1 ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c new file mode 100644 index 0000000..3997ebd --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509.c @@ -0,0 +1,1074 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_USE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_util.h" +#include +#endif + +#define CHECK(code) if( ( ret = ( code ) ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) \ + do \ + { \ + if( ( val ) < ( min ) || ( val ) > ( max ) ) \ + { \ + return( ret ); \ + } \ + } while( 0 ) + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL, ret ) ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) parameters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + p = alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE, + MBEDTLS_ERR_OID_NOT_FOUND ) ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) ); + + end = *p + len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) ); + + val->p = *p; + *p += val->len; + + if( *p != end ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ + *res = 0; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + *res *= 10; + *res += ( *(*p)++ - '0' ); + } + + return( 0 ); +} + +static int x509_date_is_valid(const mbedtls_x509_time *t ) +{ + int ret = MBEDTLS_ERR_X509_INVALID_DATE; + int month_len; + + CHECK_RANGE( 0, 9999, t->year ); + CHECK_RANGE( 0, 23, t->hour ); + CHECK_RANGE( 0, 59, t->min ); + CHECK_RANGE( 0, 59, t->sec ); + + switch( t->mon ) + { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + month_len = 31; + break; + case 4: case 6: case 9: case 11: + month_len = 30; + break; + case 2: + if( ( !( t->year % 4 ) && t->year % 100 ) || + !( t->year % 400 ) ) + month_len = 29; + else + month_len = 28; + break; + default: + return( ret ); + } + CHECK_RANGE( 1, month_len, t->day ); + + return( 0 ); +} + +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *tm ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &tm->year ) ); + if ( 2 == yearlen ) + { + if ( tm->year < 50 ) + tm->year += 100; + + tm->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &tm->mon ) ); + CHECK( x509_parse_int( p, 2, &tm->day ) ); + CHECK( x509_parse_int( p, 2, &tm->hour ) ); + CHECK( x509_parse_int( p, 2, &tm->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( tm ) ); + + return ( 0 ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *tm ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len, year_len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + tag = **p; + + if( tag == MBEDTLS_ASN1_UTC_TIME ) + year_len = 2; + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + year_len = 4; + else + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, ret ) ); + + return x509_parse_time( p, len, year_len, tm ); +} + +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + int tag_type; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SIGNATURE, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + tag_type = **p; + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret ) ); + + sig->tag = tag_type; + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *sig_opts != NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret ) ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + mbedtls_pk_rsassa_pss_options *pss_opts; + + pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + ret = mbedtls_x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + mbedtls_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed!) + */ +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Extension structure use EXPLICIT tagging. That is, the actual + * `Extensions` structure is wrapped by a tag-length pair using + * the respective context-specific tag. */ + ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( end != *p + len ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j, n; + unsigned char c, merge = 0; + const mbedtls_x509_name *name; + const char *short_name = NULL; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = mbedtls_snprintf( p, n, "%s=", short_name ); + else + ret = mbedtls_snprintf( p, n, "\?\?=" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + for( i = 0, j = 0; i < name->val.len; i++, j++ ) + { + if( j >= sizeof( s ) - 1 ) + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + + c = name->val.p[i]; + // Special characters requiring escaping, RFC 1779 + if( c && strchr( ",=+<>#;\"\\", c ) ) + { + if( j + 1 >= sizeof( s ) - 1 ) + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + s[j++] = '\\'; + } + if( c < 32 || c >= 127 ) + s[j] = '?'; + else s[j] = c; + } + s[j] = '\0'; + ret = mbedtls_snprintf( p, n, "%s", s ); + MBEDTLS_X509_SAFE_SNPRINTF; + + merge = name->next_merged; + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + if( nr != serial->len ) + { + ret = mbedtls_snprintf( p, n, "...." ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = mbedtls_snprintf( p, n, "???" ); + else + ret = mbedtls_snprintf( p, n, "%s", desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_pk_rsassa_pss_options *pss_opts; + const mbedtls_md_info_t *md_info, *mgf_md_info; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + md_info = mbedtls_md_info_from_type( md_alg ); + mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? mbedtls_md_get_name( md_info ) : "???", + mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", + (unsigned int) pss_opts->expected_salt_len ); + MBEDTLS_X509_SAFE_SNPRINTF; + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) +{ + char *p = buf; + size_t n = buf_size; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_snprintf( p, n, "%s key size", name ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( 0 ); +} + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/* + * Set the time structure to the current time. + * Return 0 on success, non-zero on failure. + */ +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + struct tm *lt, tm_buf; + mbedtls_time_t tt; + int ret = 0; + + tt = mbedtls_time( NULL ); + lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); + + if( lt == NULL ) + ret = -1; + else + { + now->year = lt->tm_year + 1900; + now->mon = lt->tm_mon + 1; + now->day = lt->tm_mday; + now->hour = lt->tm_hour; + now->min = lt->tm_min; + now->sec = lt->tm_sec; + } + + return( ret ); +} + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( &now, to ) ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( from, &now ) ); +} + +#else /* MBEDTLS_HAVE_TIME_DATE */ + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/certs.h" + +/* + * Checkup routine + */ +int mbedtls_x509_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + + if( verbose != 0 ) + mbedtls_printf( " X.509 certificate load: " ); + + mbedtls_x509_crt_init( &cacert ); + mbedtls_x509_crt_init( &clicert ); + + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, + mbedtls_test_ca_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n X.509 signature verify: "); + + ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n"); + +cleanup: + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &clicert ); +#else + ((void) verbose); +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_X509_USE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c new file mode 100644 index 0000000..056bbaa --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_create.c @@ -0,0 +1,374 @@ +/* + * X.509 base functions for creating certificates / CSRs + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CREATE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" + +#include + +/* Structure linking OIDs for X.509 DN AttributeTypes to their + * string representations and default string encodings used by Mbed TLS. */ +typedef struct { + const char *name; /* String representation of AttributeType, e.g. + * "CN" or "emailAddress". */ + size_t name_len; /* Length of 'name', without trailing 0 byte. */ + const char *oid; /* String representation of OID of AttributeType, + * as per RFC 5280, Appendix A.1. */ + int default_tag; /* The default character encoding used for the + * given attribute type, e.g. + * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ +} x509_attr_descriptor_t; + +#define ADD_STRLEN( s ) s, sizeof( s ) - 1 + +/* X.509 DN attributes from RFC 5280, Appendix A.1. */ +static const x509_attr_descriptor_t x509_attrs[] = +{ + { ADD_STRLEN( "CN" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "commonName" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "C" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "countryName" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "O" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationName" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "L" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "locality" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "R" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "OU" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationalUnitName" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "ST" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "stateOrProvinceName" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "emailAddress" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "serialNumber" ), + MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalAddress" ), + MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalCode" ), + MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "dnQualifier" ), + MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "title" ), + MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "surName" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "SN" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "givenName" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "GN" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "initials" ), + MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "pseudonym" ), + MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "generationQualifier" ), + MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "domainComponent" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "DC" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { NULL, 0, NULL, MBEDTLS_ASN1_NULL } +}; + +static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len ) +{ + const x509_attr_descriptor_t *cur; + + for( cur = x509_attrs; cur->name != NULL; cur++ ) + if( cur->name_len == name_len && + strncmp( cur->name, name, name_len ) == 0 ) + break; + + if ( cur->name == NULL ) + return( NULL ); + + return( cur ); +} + +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) +{ + int ret = 0; + const char *s = name, *c = s; + const char *end = s + strlen( s ); + const char *oid = NULL; + const x509_attr_descriptor_t* attr_descr = NULL; + int in_tag = 1; + char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + char *d = data; + + /* Clear existing chain if present */ + mbedtls_asn1_free_named_data_list( head ); + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL ) + { + ret = MBEDTLS_ERR_X509_UNKNOWN_OID; + goto exit; + } + + oid = attr_descr->oid; + s = c + 1; + in_tag = 0; + d = data; + } + + if( !in_tag && *c == '\\' && c != end ) + { + c++; + + /* Check for valid escaped characters */ + if( c == end || *c != ',' ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + else if( !in_tag && ( *c == ',' || c == end ) ) + { + mbedtls_asn1_named_data* cur = + mbedtls_asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ); + + if(cur == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + // set tagType + cur->val.tag = attr_descr->default_tag; + + while( c < end && *(c + 1) == ' ' ) + c++; + + s = c + 1; + in_tag = 1; + } + + if( !in_tag && s != c + 1 ) + { + *(d++) = *c; + + if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + + c++; + } + +exit: + + return( ret ); +} + +/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved + * to store the critical boolean for us + */ +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + cur->val.p[0] = critical; + memcpy( cur->val.p + 1, val, val_len ); + + return( 0 ); +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const char *oid = (const char*)cur_name->oid.p; + size_t oid_len = cur_name->oid.len; + const unsigned char *name = cur_name->val.p; + size_t name_len = cur_name->val.len; + + // Write correct string tag and value + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start, + cur_name->val.tag, + (const char *) name, + name_len ) ); + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, + oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_asn1_named_data *cur = first; + + while( cur != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) ); + cur = cur->next; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, sig, len ); + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, + oid_len, 0 ) ); + + return( (int) len ); +} + +static int x509_write_extension( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +/* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + */ +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( (int) len ); +} + +#endif /* MBEDTLS_X509_CREATE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c new file mode 100644 index 0000000..d2d8042 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crl.c @@ -0,0 +1,770 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + +#include "mbedtls/x509_crl.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0), v2(1) } + */ +static int x509_crl_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) ); + } + + return( 0 ); +} + +/* + * X.509 CRL v2 extensions + * + * We currently don't parse any extension's content, but we do check that the + * list of extensions is well-formed and abort on critical extensions (that + * are unsupported as we don't support any extension so far) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *p == end ) + return( 0 ); + + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) + return( ret ); + + end = ext->p + ext->len; + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + int is_critical = 0; + const unsigned char *end_ext_data; + size_t len; + + /* Get enclosing sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + end_ext_data = *p + len; + + /* Get OID (currently ignored) */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + } + *p += len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, + &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + } + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + /* Ignore data so far and just check its length */ + *p += len; + if( *p != end_ext_data ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* Abort on (unsupported) critical extensions */ + if( is_critical ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * X.509 CRL v2 entry extensions (no extensions parsed yet.) + */ +static int x509_get_crl_entry_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* OPTIONAL */ + if( end <= *p ) + return( 0 ); + + ext->tag = **p; + ext->p = *p; + + /* + * Get CRL-entry extension sequence header + * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + while( *p < end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + *p += len; + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crl_entry *entry ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t entry_len; + mbedtls_x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + cur_entry->raw.tag = **p; + if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + cur_entry->raw.p = *p; + cur_entry->raw.len = len2; + end2 = *p + len2; + + if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end2, + &cur_entry->revocation_date ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_crl_entry_ext( p, end2, + &cur_entry->entry_ext ) ) != 0 ) + return( ret ); + + if( *p < end ) + { + cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur_entry = cur_entry->next; + } + } + + return( 0 ); +} + +/* + * Parse one CRLs in DER format and append it to the chained list + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p = NULL, *end = NULL; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + mbedtls_x509_crl *crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Add new CRL on the end of the chain if needed. + */ + while( crl->version != 0 && crl->next != NULL ) + crl = crl->next; + + if( crl->version != 0 && crl->next == NULL ) + { + crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); + + if( crl->next == NULL ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + mbedtls_x509_crl_init( crl->next ); + crl = crl->next; + } + + /* + * Copy raw DER-encoded CRL + */ + if( buflen == 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + p = mbedtls_calloc( 1, buflen ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crl->raw.p = p; + crl->raw.len = buflen; + + end = p + buflen; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->version < 0 || crl->version > 1 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crl->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) && + ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid.len != sig_oid2.len || + memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t use_len = 0; + mbedtls_pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + do + { + mbedtls_pem_init( &pem ); + + // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated + // string + if( buflen == 0 || buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + is_pem = 1; + + buflen -= use_len; + buf += use_len; + + if( ( ret = mbedtls_x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + } + else if( is_pem ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + + mbedtls_pem_free( &pem ); + } + /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. + * And a valid CRL cannot be less than 1 byte anyway. */ + while( is_pem && buflen > 1 ); + + if( is_pem ) + return( 0 ); + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crl_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + const mbedtls_x509_crl_entry *entry; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = &crl->entry; + + ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%sserial number: ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = entry->next; + } + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) +{ + memset( crl, 0, sizeof(mbedtls_x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) +{ + mbedtls_x509_crl *crl_cur = crl; + mbedtls_x509_crl *crl_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + mbedtls_platform_zeroize( entry_prv, + sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + if( crl_prv != crl ) + mbedtls_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c new file mode 100644 index 0000000..911644b --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_crt.c @@ -0,0 +1,3399 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#include +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif + +/* + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} x509_crt_verify_chain_item; + +/* + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/* Default profile. Do not remove items unless there are serious security + * concerns. */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ + /* Only SHA-2 hashes */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 2048, +}; + +/* + * Next-default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), +#if defined(MBEDTLS_ECP_C) + /* Only NIST P-256 and P-384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), +#else + 0, +#endif + 0, +}; + +/* + * Check md_alg against profile + * Return 0 if md_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg ) +{ + if( md_alg == MBEDTLS_MD_NONE ) + return( -1 ); + + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check pk_alg against profile + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg ) +{ + if( pk_alg == MBEDTLS_PK_NONE ) + return( -1 ); + + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check key against profile + * Return 0 if pk is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, + const mbedtls_pk_context *pk ) +{ + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) + return( 0 ); + + return( -1 ); + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECDSA || + pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + + if( gid == MBEDTLS_ECP_DP_NONE ) + return( -1 ); + + if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) + return( 0 ); + + return( -1 ); + } +#endif + + return( -1 ); +} + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + /* We can't have a match if there is no wildcard to match */ + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( -1 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Reset (init or clear) a verify_chain + */ +static void x509_crt_verify_chain_reset( + mbedtls_x509_crt_verify_chain *ver_chain ) +{ + size_t i; + + for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ ) + { + ver_chain->items[i].crt = NULL; + ver_chain->items[i].flags = (uint32_t) -1; + } + + ver_chain->len = 0; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + ver_chain->trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + end = *p + len; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) ); + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *from, + mbedtls_x509_time *to ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, ret ) ); + + end = *p + len; + + if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *uid, int n ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + uid->p = *p; + *p += uid->len; + + return( 0 ); +} + +static int x509_get_basic_constraints( unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + ret = mbedtls_asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer + * overflow, which is an undefined behavior. */ + if( *max_pathlen == INT_MAX ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH ) ); + + (*max_pathlen)++; + + return( 0 ); +} + +static int x509_get_ns_cert_type( unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( bs.len != 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH ) ); + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return( 0 ); +} + +static int x509_get_key_usage( unsigned char **p, + const unsigned char *end, + unsigned int *key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( bs.len < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH ) ); + + /* Get actual bitstring */ + *key_usage = 0; + for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) + { + *key_usage |= (unsigned int) bs.p[i] << (8*i); + } + + return( 0 ); +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH ) ); + + return( 0 ); +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * NOTE: we list all types, but only use dNSName and otherName + * of type HwModuleName, as defined in RFC 4108, at this point. + */ +static int x509_get_subject_alt_name( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len, tag_len; + mbedtls_asn1_buf *buf; + unsigned char tag; + mbedtls_asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + while( *p < end ) + { + mbedtls_x509_subject_alternative_name dummy_san_buf; + memset( &dummy_san_buf, 0, sizeof( dummy_san_buf ) ); + + tag = **p; + (*p)++; + if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } + + /* + * Check that the SAN is structured correctly. + */ + ret = mbedtls_x509_parse_subject_alt_name( &(cur->buf), &dummy_san_buf ); + /* + * In case the extension is malformed, return an error, + * and clear the allocated sequences. + */ + if( ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + { + mbedtls_x509_sequence *seq_cur = subject_alt_name->next; + mbedtls_x509_sequence *seq_prv; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + subject_alt_name->next = NULL; + return( ret ); + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_ALLOC_FAILED ) ); + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + * + * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * CertPolicyId ::= OBJECT IDENTIFIER + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * -- policyQualifierIds for Internet policy qualifiers + * + * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + * + * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + * + * Qualifier ::= CHOICE { + * cPSuri CPSuri, + * userNotice UserNotice } + * + * CPSuri ::= IA5String + * + * UserNotice ::= SEQUENCE { + * noticeRef NoticeReference OPTIONAL, + * explicitText DisplayText OPTIONAL } + * + * NoticeReference ::= SEQUENCE { + * organization DisplayText, + * noticeNumbers SEQUENCE OF INTEGER } + * + * DisplayText ::= CHOICE { + * ia5String IA5String (SIZE (1..200)), + * visibleString VisibleString (SIZE (1..200)), + * bmpString BMPString (SIZE (1..200)), + * utf8String UTF8String (SIZE (1..200)) } + * + * NOTE: we only parse and use anyPolicy without qualifiers at this point + * as defined in RFC 5280. + */ +static int x509_get_certificate_policies( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *certificate_policies ) +{ + int ret, parse_ret = 0; + size_t len; + mbedtls_asn1_buf *buf; + mbedtls_asn1_sequence *cur = certificate_policies; + + /* Get main sequence tag */ + ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * Cannot be an empty sequence. + */ + if( len == 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + while( *p < end ) + { + mbedtls_x509_buf policy_oid; + const unsigned char *policy_end; + + /* + * Get the policy sequence + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + policy_end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + policy_oid.tag = MBEDTLS_ASN1_OID; + policy_oid.len = len; + policy_oid.p = *p; + + /* + * Only AnyPolicy is currently supported when enforcing policy. + */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_POLICY, &policy_oid ) != 0 ) + { + /* + * Set the parsing return code but continue parsing, in case this + * extension is critical and MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * is configured. + */ + parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_ALLOC_FAILED ) ); + + cur = cur->next; + } + + buf = &( cur->buf ); + buf->tag = policy_oid.tag; + buf->p = policy_oid.p; + buf->len = policy_oid.len; + + *p += len; + + /* + * If there is an optional qualifier, then *p < policy_end + * Check the Qualifier len to verify it doesn't exceed policy_end. + */ + if( *p < policy_end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + /* + * Skip the optional policy qualifiers. + */ + *p += len; + } + + if( *p != policy_end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( parse_ret ); +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + return( ret ); + + end = crt->v3_ext.p + crt->v3_ext.len; + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + end_ext_data = *p + len; + + /* Get extension ID */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + extn_oid.tag = MBEDTLS_ASN1_OID; + extn_oid.p = *p; + *p += extn_oid.len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + start_ext_octet = *p; + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* Give the callback (if any) a chance to handle the extension */ + if( cb != NULL ) + { + ret = cb( p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet ); + if( ret != 0 && is_critical ) + return( ret ); + *p = end_ext_octet; + continue; + } + + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } +#endif + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES: + /* Parse certificate policies type */ + if( ( ret = x509_get_certificate_policies( p, end_ext_octet, + &crt->certificate_policies ) ) != 0 ) + { + /* Give the callback (if any) a chance to handle the extension + * if it contains unsupported policies */ + if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL && + cb( p_ctx, crt, &extn_oid, is_critical, + start_ext_octet, end_ext_octet ) == 0 ) + break; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + return( ret ); + else +#endif + /* + * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we + * cannot interpret or enforce the policy. However, it is up to + * the user to choose how to enforce the policies, + * unless the extension is critical. + */ + if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + return( ret ); + } + break; + + default: + /* + * If this is a non-critical extension, which the oid layer + * supports, but there isn't an x509 parser for it, + * skip the extension. + */ +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + else +#endif + *p = end_ext_octet; + } + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* Use the original buffer until we figure out actual length. */ + p = (unsigned char*) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + end = crt_end = p + len; + crt->raw.len = crt_end - buf; + if( make_copy != 0 ) + { + /* Create and populate a new buffer for the raw field. */ + crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); + if( crt->raw.p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( crt->raw.p, buf, crt->raw.len ); + crt->own_buffer = 1; + + p += crt->raw.len - len; + end = crt_end = p + len; + } + else + { + crt->raw.p = (unsigned char*) buf; + crt->own_buffer = 0; + } + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, + &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->version < 0 || crt->version > 2 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crt->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + crt->pk_raw.p = p; + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + crt->pk_raw.len = p - crt->pk_raw.p; + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) +#endif + { + ret = x509_get_crt_ext( &p, end, crt, cb, p_ctx ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid.len != sig_oid2.len || + memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || + sig_params1.tag != sig_params2.tag || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( crt->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + prev = crt; + mbedtls_x509_crt_init( crt->next ); + crt = crt->next; + } + + ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy, cb, p_ctx ); + if( ret != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + mbedtls_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0, NULL, NULL ) ); +} + +int mbedtls_x509_crt_parse_der_with_ext_cb( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, make_copy, cb, p_ctx ) ); +} + +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1, NULL, NULL ) ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if( buflen != 0 && buf[buflen - 1] == '\0' && + strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if( buf_format == MBEDTLS_X509_FORMAT_DER ) + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if( buf_format == MBEDTLS_X509_FORMAT_PEM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while( buflen > 1 ) + { + size_t use_len; + mbedtls_pem_init( &pem ); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + else + break; + + ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + mbedtls_pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crt_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, + MAX_PATH - 3 ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, (int) len - 1, + NULL, NULL ); + if( w_ret == 0 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + w_ret = mbedtls_x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + +cleanup: + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) + { + closedir( dir ); + return( ret ); + } +#endif /* MBEDTLS_THREADING_C */ + + memset( &sb, 0, sizeof( sb ) ); + + while( ( entry = readdir( dir ) ) != NULL ) + { + snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, + "%s/%s", path, entry->d_name ); + + if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) + { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } + else if( stat( entry_name, &sb ) == -1 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + +cleanup: + closedir( dir ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; +#endif /* MBEDTLS_THREADING_C */ + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + * + * NOTE: we currently only parse and use otherName of type HwModuleName, + * as defined in RFC 4108. + */ +static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name, + mbedtls_x509_san_other_name *other_name ) +{ + int ret = 0; + size_t len; + unsigned char *p = subject_alt_name->p; + const unsigned char *end = p + subject_alt_name->len; + mbedtls_x509_buf cur_oid; + + if( ( subject_alt_name->tag & + ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) ) != + ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ) ) + { + /* + * The given subject alternative name is not of type "othername". + */ + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + cur_oid.tag = MBEDTLS_ASN1_OID; + cur_oid.p = p; + cur_oid.len = len; + + /* + * Only HwModuleName is currently supported. + */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid ) != 0 ) + { + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + + if( p + len >= end ) + { + mbedtls_platform_zeroize( other_name, sizeof( *other_name ) ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + p += len; + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; + other_name->value.hardware_module_name.oid.p = p; + other_name->value.hardware_module_name.oid.len = len; + + if( p + len >= end ) + { + mbedtls_platform_zeroize( other_name, sizeof( *other_name ) ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + p += len; + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; + other_name->value.hardware_module_name.val.p = p; + other_name->value.hardware_module_name.val.len = len; + p += len; + if( p != end ) + { + mbedtls_platform_zeroize( other_name, + sizeof( *other_name ) ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + return( 0 ); +} + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const mbedtls_x509_sequence + *subject_alt_name, + const char *prefix ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + mbedtls_x509_subject_alternative_name san; + int parse_ret; + + while( cur != NULL ) + { + memset( &san, 0, sizeof( san ) ); + parse_ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san ); + if( parse_ret != 0 ) + { + if( parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + { + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + else + { + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + cur = cur->next; + continue; + } + + switch( san.type ) + { + /* + * otherName + */ + case MBEDTLS_X509_SAN_OTHER_NAME: + { + mbedtls_x509_san_other_name *other_name = &san.san.other_name; + + ret = mbedtls_snprintf( p, n, "\n%s otherName :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, + &other_name->value.hardware_module_name.oid ) != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%s hardware module name :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "\n%s hardware type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_oid_get_numeric_string( p, n, &other_name->value.hardware_module_name.oid ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%s hardware serial number : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( other_name->value.hardware_module_name.val.len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + memcpy( p, other_name->value.hardware_module_name.val.p, + other_name->value.hardware_module_name.val.len ); + p += other_name->value.hardware_module_name.val.len; + + n -= other_name->value.hardware_module_name.val.len; + + }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ + } + break; + + /* + * dNSName + */ + case MBEDTLS_X509_SAN_DNS_NAME: + { + ret = mbedtls_snprintf( p, n, "\n%s dNSName : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + if( san.san.unstructured_name.len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + memcpy( p, san.san.unstructured_name.p, san.san.unstructured_name.len ); + p += san.san.unstructured_name.len; + n -= san.san.unstructured_name.len; + } + break; + + /* + * Type not supported, skip item. + */ + default: + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + break; + } + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf, + mbedtls_x509_subject_alternative_name *san ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + switch( san_buf->tag & + ( MBEDTLS_ASN1_TAG_CLASS_MASK | + MBEDTLS_ASN1_TAG_VALUE_MASK ) ) + { + /* + * otherName + */ + case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ): + { + mbedtls_x509_san_other_name other_name; + + ret = x509_get_other_name( san_buf, &other_name ); + if( ret != 0 ) + return( ret ); + + memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) ); + san->type = MBEDTLS_X509_SAN_OTHER_NAME; + memcpy( &san->san.other_name, + &other_name, sizeof( other_name ) ); + + } + break; + + /* + * dNSName + */ + case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ): + { + memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) ); + san->type = MBEDTLS_X509_SAN_DNS_NAME; + + memcpy( &san->san.unstructured_name, + san_buf, sizeof( *san_buf ) ); + + } + break; + + /* + * Type not supported + */ + default: + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & (type) ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & (code) ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned int key_usage ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); + KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_cert_policies( char **buf, size_t *size, + const mbedtls_x509_sequence *certificate_policies ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = certificate_policies; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_certificate_policies( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "%sserial number : ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &crt->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) + { + ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( crt->max_pathlen > 0 ) + { + ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + ret = mbedtls_snprintf( p, n, "\n%ssubject alt name :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names, + prefix ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) + { + ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES ) + { + ret = mbedtls_snprintf( p, n, "\n%scertificate policies : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_policies( &p, &n, + &crt->certificate_policies ) ) != 0 ) + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, + { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, + { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, + { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, + { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, + { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { 0, NULL } +}; + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) + return( 0 ); + + usage_must = usage & ~may_mask; + + if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + usage_may = usage & may_mask; + + if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) + return( 0 ); + } + + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation if no CRL for the given CA is present. + */ +static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( mbedtls_x509_crt_check_key_usage( ca, + MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + + if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + + md_info = mbedtls_md_info_from_type( crl_list->sig_md ); + if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + if( x509_profile_check_key( profile, &ca->pk ) != 0 ) + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + + if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) + flags |= MBEDTLS_X509_BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) + { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return( flags ); +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Check the signature of a certificate by its parent + */ +static int x509_crt_check_signature( const mbedtls_x509_crt *child, + mbedtls_x509_crt *parent, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + size_t hash_len; +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + const mbedtls_md_info_t *md_info; + md_info = mbedtls_md_info_from_type( child->sig_md ); + hash_len = mbedtls_md_get_size( md_info ); + + /* Note: hash errors can happen only after an internal error */ + if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) + return( -1 ); +#else + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( child->sig_md ); + + if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS ) + return( -1 ); + + if( psa_hash_update( &hash_operation, child->tbs.p, child->tbs.len ) + != PSA_SUCCESS ) + { + return( -1 ); + } + + if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len ) + != PSA_SUCCESS ) + { + return( -1 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /* Skip expensive computation on obvious mismatch */ + if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) + return( -1 ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) + { + return( mbedtls_pk_verify_restartable( &parent->pk, + child->sig_md, hash, hash_len, + child->sig.p, child->sig.len, &rs_ctx->pk ) ); + } +#else + (void) rs_ctx; +#endif + + return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, hash_len, + child->sig.p, child->sig.len ) ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + */ +static int x509_crt_check_parent( const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + return( -1 ); + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +/* + * Find a suitable parent for child in candidates, or return NULL. + * + * Here suitable is defined as: + * 1. subject name matches child's issuer + * 2. if necessary, the CA bit is set and key usage allows signing certs + * 3. for trusted roots, the signature is correct + * (for intermediates, the signature is checked and the result reported) + * 4. pathlen constraints are satisfied + * + * If there's a suitable candidate which is also time-valid, return the first + * such. Otherwise, return the first suitable candidate (or NULL if there is + * none). + * + * The rationale for this rule is that someone could have a list of trusted + * roots with two versions on the same root with different validity periods. + * (At least one user reported having such a list and wanted it to just work.) + * The reason we don't just require time-validity is that generally there is + * only one version, and if it's expired we want the flags to state that + * rather than NOT_TRUSTED, as would be the case if we required it here. + * + * The rationale for rule 3 (signature for trusted roots) is that users might + * have two versions of the same CA with different keys in their list, and the + * way we select the correct one is by checking the signature (as we don't + * rely on key identifier extensions). (This is one way users might choose to + * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent + * - [in] candidates: chained list of potential parents + * - [out] r_parent: parent found (or NULL) + * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top + * of the chain, 0 otherwise + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will never be greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent_in( + mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + mbedtls_x509_crt **r_parent, + int *r_signature_is_good, + int top, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *parent, *fallback_parent; + int signature_is_good = 0, fallback_signature_is_good; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* did we have something in progress? */ + if( rs_ctx != NULL && rs_ctx->parent != NULL ) + { + /* restore saved state */ + parent = rs_ctx->parent; + fallback_parent = rs_ctx->fallback_parent; + fallback_signature_is_good = rs_ctx->fallback_signature_is_good; + + /* clear saved state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_signature_is_good = 0; + + /* resume where we left */ + goto check_signature; + } +#endif + + fallback_parent = NULL; + fallback_signature_is_good = 0; + + for( parent = candidates; parent != NULL; parent = parent->next ) + { + /* basic parenting skills (name, CA bit, key usage) */ + if( x509_crt_check_parent( child, parent, top ) != 0 ) + continue; + + /* +1 because stored max_pathlen is 1 higher that the actual value */ + if( parent->max_pathlen > 0 && + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) + { + continue; + } + + /* Signature */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +check_signature: +#endif + ret = x509_crt_check_signature( child, parent, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent = parent; + rs_ctx->fallback_parent = fallback_parent; + rs_ctx->fallback_signature_is_good = fallback_signature_is_good; + + return( ret ); + } +#else + (void) ret; +#endif + + signature_is_good = ret == 0; + if( top && ! signature_is_good ) + continue; + + /* optional time check */ + if( mbedtls_x509_time_is_past( &parent->valid_to ) || + mbedtls_x509_time_is_future( &parent->valid_from ) ) + { + if( fallback_parent == NULL ) + { + fallback_parent = parent; + fallback_signature_is_good = signature_is_good; + } + + continue; + } + + *r_parent = parent; + *r_signature_is_good = signature_is_good; + + break; + } + + if( parent == NULL ) + { + *r_parent = fallback_parent; + *r_signature_is_good = fallback_signature_is_good; + } + + return( 0 ); +} + +/* + * Find a parent in trusted CAs or the provided chain, or return NULL. + * + * Searches in trusted CAs first, and return the first suitable parent found + * (see find_parent_in() for definition of suitable). + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent, followed + * by a chain of possible intermediates + * - [in] trust_ca: list of locally trusted certificates + * - [out] parent: parent found (or NULL) + * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 + * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * - [in] self_cnt: number of self-signed certs in the chain so far + * (will always be no greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent( + mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crt **parent, + int *parent_is_trusted, + int *signature_is_good, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *search_list; + + *parent_is_trusted = 1; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore then clear saved state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 ) + { + *parent_is_trusted = rs_ctx->parent_is_trusted; + rs_ctx->parent_is_trusted = -1; + } +#endif + + while( 1 ) { + search_list = *parent_is_trusted ? trust_ca : child->next; + + ret = x509_crt_find_parent_in( child, search_list, + parent, signature_is_good, + *parent_is_trusted, + path_cnt, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent_is_trusted = *parent_is_trusted; + return( ret ); + } +#else + (void) ret; +#endif + + /* stop here if found or already in second iteration */ + if( *parent != NULL || *parent_is_trusted == 0 ) + break; + + /* prepare second iteration */ + *parent_is_trusted = 0; + } + + /* extra precaution against mistakes in the caller */ + if( *parent == NULL ) + { + *parent_is_trusted = 0; + *signature_is_good = 0; + } + + return( 0 ); +} + +/* + * Check if an end-entity certificate is locally trusted + * + * Currently we require such certificates to be self-signed (actually only + * check for self-issued as self-signatures are not checked) + */ +static int x509_crt_check_ee_locally_trusted( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca ) +{ + mbedtls_x509_crt *cur; + + /* must be self-issued */ + if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) + return( -1 ); + + /* look for an exact match with trusted cert */ + for( cur = trust_ca; cur != NULL; cur = cur->next ) + { + if( crt->raw.len == cur->raw.len && + memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 ) + { + return( 0 ); + } + } + + /* too bad */ + return( -1 ); +} + +/* + * Build and verify a certificate chain + * + * Given a peer-provided list of certificates EE, C1, ..., Cn and + * a list of trusted certs R1, ... Rp, try to build and verify a chain + * EE, Ci1, ... Ciq [, Rj] + * such that every cert in the chain is a child of the next one, + * jumping to a trusted root as early as possible. + * + * Verify that chain and return it with flags for all issues found. + * + * Special cases: + * - EE == Rj -> return a one-element list containing it + * - EE, Ci1, ..., Ciq cannot be continued with a trusted root + * -> return that chain with NOT_TRUSTED set on Ciq + * + * Tests for (aspects of) this function should include at least: + * - trusted EE + * - EE -> trusted root + * - EE -> intermediate CA -> trusted root + * - if relevant: EE untrusted + * - if relevant: EE -> intermediate, untrusted + * with the aspect under test checked at each relevant level (EE, int, root). + * For some aspects longer chains are required, but usually length 2 is + * enough (but length 1 is not in general). + * + * Arguments: + * - [in] crt: the cert list EE, C1, ..., Cn + * - [in] trust_ca: the trusted list R1, ..., Rp + * - [in] ca_crl, profile: as in verify_with_profile() + * - [out] ver_chain: the built and verified chain + * Only valid when return value is 0, may contain garbage otherwise! + * Restart note: need not be the same when calling again to resume. + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - non-zero if the chain could not be fully built and examined + * - 0 is the chain was successfully built and examined, + * even if it was found to be invalid + */ +static int x509_crt_verify_chain( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + mbedtls_x509_crt_verify_chain *ver_chain, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + /* Don't initialize any of those variables here, so that the compiler can + * catch potential issues with jumping ahead when restarting */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t *flags; + mbedtls_x509_crt_verify_chain_item *cur; + mbedtls_x509_crt *child; + mbedtls_x509_crt *parent; + int parent_is_trusted; + int child_is_trusted; + int signature_is_good; + unsigned self_cnt; + mbedtls_x509_crt *cur_trust_ca = NULL; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* resume if we had an operation in progress */ + if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent ) + { + /* restore saved state */ + *ver_chain = rs_ctx->ver_chain; /* struct copy */ + self_cnt = rs_ctx->self_cnt; + + /* restore derived state */ + cur = &ver_chain->items[ver_chain->len - 1]; + child = cur->crt; + flags = &cur->flags; + + goto find_parent; + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + child = crt; + self_cnt = 0; + parent_is_trusted = 0; + child_is_trusted = 0; + + while( 1 ) { + /* Add certificate to the verification chain */ + cur = &ver_chain->items[ver_chain->len]; + cur->crt = child; + cur->flags = 0; + ver_chain->len++; + flags = &cur->flags; + + /* Check time-validity (all certificates) */ + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + /* Stop here for trusted roots (but not for trusted EE certs) */ + if( child_is_trusted ) + return( 0 ); + + /* Check signature algorithm: MD & PK algs */ + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* Special case: EE certs that are locally trusted */ + if( ver_chain->len == 1 && + x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) + { + return( 0 ); + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +find_parent: +#endif + + /* Obtain list of potential trusted signers from CA callback, + * or use statically provided list. */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( f_ca_cb != NULL ) + { + mbedtls_x509_crt_free( ver_chain->trust_ca_cb_result ); + mbedtls_free( ver_chain->trust_ca_cb_result ); + ver_chain->trust_ca_cb_result = NULL; + + ret = f_ca_cb( p_ca_cb, child, &ver_chain->trust_ca_cb_result ); + if( ret != 0 ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + cur_trust_ca = ver_chain->trust_ca_cb_result; + } + else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + ((void) f_ca_cb); + ((void) p_ca_cb); + cur_trust_ca = trust_ca; + } + + /* Look for a parent in trusted CAs or up the chain */ + ret = x509_crt_find_parent( child, cur_trust_ca, &parent, + &parent_is_trusted, &signature_is_good, + ver_chain->len - 1, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->in_progress = x509_crt_rs_find_parent; + rs_ctx->self_cnt = self_cnt; + rs_ctx->ver_chain = *ver_chain; /* struct copy */ + + return( ret ); + } +#else + (void) ret; +#endif + + /* No parent? We're done here */ + if( parent == NULL ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return( 0 ); + } + + /* Count intermediate self-issued (not necessarily self-signed) certs. + * These can occur with some strategies for key rollover, see [SIRO], + * and should be excluded from max_pathlen checks. */ + if( ver_chain->len != 1 && + x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + { + self_cnt++; + } + + /* path_cnt is 0 for the first intermediate CA, + * and if parent is trusted it's not an intermediate CA */ + if( ! parent_is_trusted && + ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately to avoid overflow the chain array */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + /* signature was checked while searching parent */ + if( ! signature_is_good ) + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + /* check size of signing key */ + if( x509_profile_check_key( profile, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); +#else + (void) ca_crl; +#endif + + /* prepare for next iteration */ + child = parent; + parent = NULL; + child_is_trusted = parent_is_trusted; + signature_is_good = 0; + } +} + +/* + * Check for CN match + */ +static int x509_crt_check_cn( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + /* try exact match */ + if( name->len == cn_len && + x509_memcasecmp( cn, name->p, cn_len ) == 0 ) + { + return( 0 ); + } + + /* try wildcard match */ + if( x509_check_wildcard( cn, name ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Check for SAN match, see RFC 5280 Section 4.2.1.6 + */ +static int x509_crt_check_san( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + const unsigned char san_type = (unsigned char) name->tag & + MBEDTLS_ASN1_TAG_VALUE_MASK; + + /* dNSName */ + if( san_type == MBEDTLS_X509_SAN_DNS_NAME ) + return( x509_crt_check_cn( name, cn, cn_len ) ); + + /* (We may handle other types here later.) */ + + /* Unrecognized type */ + return( -1 ); +} + +/* + * Verify the requested CN - only call this if cn is not NULL! + */ +static void x509_crt_verify_name( const mbedtls_x509_crt *crt, + const char *cn, + uint32_t *flags ) +{ + const mbedtls_x509_name *name; + const mbedtls_x509_sequence *cur; + size_t cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next ) + { + if( x509_crt_check_san( &cur->buf, cn, cn_len ) == 0 ) + break; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + for( name = &crt->subject; name != NULL; name = name->next ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 && + x509_crt_check_cn( &name->val, cn, cn_len ) == 0 ) + { + break; + } + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } +} + +/* + * Merge the flags for all certs in the chain, after calling callback + */ +static int x509_crt_merge_flags_with_cb( + uint32_t *flags, + const mbedtls_x509_crt_verify_chain *ver_chain, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned i; + uint32_t cur_flags; + const mbedtls_x509_crt_verify_chain_item *cur; + + for( i = ver_chain->len; i != 0; --i ) + { + cur = &ver_chain->items[i-1]; + cur_flags = cur->flags; + + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 ) + return( ret ); + + *flags |= cur_flags; + } + + return( 0 ); +} + +/* + * Verify the certificate validity, with profile, restartable version + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags + * + * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` + * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the + * verification routine to search for trusted signers, and CRLs will + * be disabled. Otherwise, `trust_ca` will be used as the static list + * of trusted signers, and `ca_crl` will be use as the static list + * of CRLs. + */ +static int x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_type_t pk_type; + mbedtls_x509_crt_verify_chain ver_chain; + uint32_t ee_flags; + + *flags = 0; + ee_flags = 0; + x509_crt_verify_chain_reset( &ver_chain ); + + if( profile == NULL ) + { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; + } + + /* check name if requested */ + if( cn != NULL ) + x509_crt_verify_name( crt, cn, &ee_flags ); + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type( &crt->pk ); + + if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + if( x509_profile_check_key( profile, &crt->pk ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + /* Check the chain */ + ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, + f_ca_cb, p_ca_cb, profile, + &ver_chain, rs_ctx ); + + if( ret != 0 ) + goto exit; + + /* Merge end-entity flags */ + ver_chain.items[0].flags |= ee_flags; + + /* Build final flags, calling callback on the way if any */ + ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); + +exit: + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_free( ver_chain.trust_ca_cb_result ); + mbedtls_free( ver_chain.trust_ca_cb_result ); + ver_chain.trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_x509_crt_restart_free( rs_ctx ); +#endif + + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + + if( ret != 0 ) + { + *flags = (uint32_t) -1; + return( ret ); + } + + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + + +/* + * Verify the certificate validity (default profile, not restartable) + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + &mbedtls_x509_crt_profile_default, + cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +/* + * Verify the certificate validity (user-chosen profile, not restartable) + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/* + * Verify the certificate validity (user-chosen profile, CA callback, + * not restartable). + */ +int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, NULL, NULL, + f_ca_cb, p_ca_cb, + profile, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, rs_ctx ) ); +} + + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) +{ + memset( crt, 0, sizeof(mbedtls_x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_sequence *seq_cur; + mbedtls_x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + mbedtls_pk_free( &cert_cur->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->certificate_policies.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL && cert_cur->own_buffer ) + { + mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + if( cert_prv != crt ) + mbedtls_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) +{ + mbedtls_pk_restart_init( &ctx->pk ); + + ctx->parent = NULL; + ctx->fallback_parent = NULL; + ctx->fallback_signature_is_good = 0; + + ctx->parent_is_trusted = -1; + + ctx->in_progress = x509_crt_rs_none; + ctx->self_cnt = 0; + x509_crt_verify_chain_reset( &ctx->ver_chain ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_pk_restart_free( &ctx->pk ); + mbedtls_x509_crt_restart_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c new file mode 100644 index 0000000..e259410 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c @@ -0,0 +1,414 @@ +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end; + mbedtls_x509_buf sig_params; + + memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + mbedtls_x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = mbedtls_calloc( 1, len = buflen ); + + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( csr->version != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + csr->version++; + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + * + * The list of possible attributes is open-ended, though RFC 2985 + * (PKCS#9) defines a few in section 5.4. We currently don't support any, + * so we just ignore them. This is a safe thing to do as the worst thing + * that could happen is that we issue a certificate that does not match + * the requester's expectations - this cannot cause a violation of our + * signature policies. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t use_len; + mbedtls_pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_PEM_PARSE_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( buf[buflen - 1] == '\0' ) + { + mbedtls_pem_init( &pem ); + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN NEW CERTIFICATE REQUEST-----", + "-----END NEW CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + } + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); + } + + mbedtls_pem_free( &pem ); + if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + } +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load a CSR into the structure + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_csr_parse( csr, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &csr->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CSR + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) +{ + memset( csr, 0, sizeof(mbedtls_x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if( csr == NULL ) + return; + + mbedtls_pk_free( &csr->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + mbedtls_platform_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_free( csr->raw.p ); + } + + mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) ); +} + +#endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c new file mode 100644 index 0000000..0c5e991 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_crt.c @@ -0,0 +1,543 @@ +/* + * X.509 certificate writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * References: + * - certificates: RFC 5280, updated by RFC 6818 + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif /* MBEDTLS_PEM_WRITE_C */ + +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); + + mbedtls_mpi_init( &ctx->serial ); + ctx->version = MBEDTLS_X509_CRT_VERSION_3; +} + +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) +{ + mbedtls_mpi_free( &ctx->serial ); + + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->issuer ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); +} + +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, + int version ) +{ + ctx->version = version; +} + +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, + mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) +{ + ctx->subject_key = key; +} + +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) +{ + ctx->issuer_key = key; +} + +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ) +{ + return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); +} + +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, + const mbedtls_mpi *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, + const char *not_before, + const char *not_after ) +{ + if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || + strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ) ); +} + +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[9]; + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + + if( is_ca && max_pathlen > 127 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, + max_pathlen ) ); + } + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( + mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, + MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), + is_ca, buf + sizeof(buf) - len, len ) ); +} + +#if defined(MBEDTLS_SHA1_C) +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); + + return mbedtls_x509write_crt_set_extension( ctx, + MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof( buf ); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + + ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( + ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof( buf ) - len, len ); +} +#endif /* MBEDTLS_SHA1_C */ + +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ) +{ + unsigned char buf[5] = {0}, ku[2] = {0}; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | + MBEDTLS_X509_KU_NON_REPUDIATION | + MBEDTLS_X509_KU_KEY_ENCIPHERMENT | + MBEDTLS_X509_KU_DATA_ENCIPHERMENT | + MBEDTLS_X509_KU_KEY_AGREEMENT | + MBEDTLS_X509_KU_KEY_CERT_SIGN | + MBEDTLS_X509_KU_CRL_SIGN | + MBEDTLS_X509_KU_ENCIPHER_ONLY | + MBEDTLS_X509_KU_DECIPHER_ONLY; + + /* Check that nothing other than the allowed flags is set */ + if( ( key_usage & ~allowed_bits ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + + c = buf + 5; + MBEDTLS_PUT_UINT16_LE( key_usage, ku, 0 ); + ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 5 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4] = {0}; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *t, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* + * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( t[0] < '2' || ( t[0] == '2' && t[1] == '0' && t[2] < '5' ) ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t + 2, + size - 2 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_UTC_TIME ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t, + size ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed at the end of the target buffer + */ + c = buf + size; + + /* Signature algorithm needed in TBS, and later for actual signature */ + + /* There's no direct way of extracting a signature algorithm + * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ + if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + + /* Only for v3 */ + if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) + { + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_extensions( &c, + buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + } + + /* + * SubjectPublicKeyInfo + */ + MBEDTLS_ASN1_CHK_ADD( pub_len, + mbedtls_pk_write_pubkey_der( ctx->subject_key, + buf, c - buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_after, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_before, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Issuer ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_algorithm_identifier( &c, buf, + sig_oid, strlen( sig_oid ), 0 ) ); + + /* + * Serial ::= INTEGER + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, + &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + + /* Can be omitted for v1 */ + if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) + { + sub_len = 0; + MBEDTLS_ASN1_CHK_ADD( sub_len, + mbedtls_asn1_write_int( &c, buf, ctx->version ) ); + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Make signature + */ + + /* Compute hash of CRT. */ + if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, + len, hash ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, + hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + /* Move CRT to the front of the buffer to have space + * for the signature. */ + memmove( buf, c, len ); + c = buf + len; + + /* Add signature at the end of the buffer, + * making sure that it doesn't underflow + * into the CRT buffer. */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c, + sig_oid, sig_oid_len, sig, sig_len ) ); + + /* + * Memory layout after this step: + * + * buf c=buf+len c2 buf+size + * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm] + */ + + /* Move raw CRT to just before the signature. */ + c = c2 - len; + memmove( c, buf, len ); + + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + if( ( ret = mbedtls_x509write_crt_der( crt, buf, size, + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, + buf + size - ret, ret, + buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CRT_WRITE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c new file mode 100644 index 0000000..afda950 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/x509write_csr.c @@ -0,0 +1,341 @@ +/* + * X.509 Certificate Signing Request writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) +{ + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) +{ + ctx->key = key; +} + +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + const unsigned char *val, size_t val_len ) +{ + return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + 0, val, val_len ); +} + +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4] = {0}; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &key_usage, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4] = {0}; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509write_csr_der_internal( mbedtls_x509write_csr *ctx, + unsigned char *buf, + size_t size, + unsigned char *sig, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + size_t hash_len; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( ctx->md_alg ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* Write the CSR backwards starting from the end of buf */ + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, buf, + ctx->extensions ) ); + + if( len ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ); + + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_oid( + &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, + MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, + buf, c - buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Sign the written CSR data into the sig buffer + * Note: hash errors can happen only after an internal error + */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + if( psa_hash_update( &hash_operation, c, len ) != PSA_SUCCESS ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len ) + != PSA_SUCCESS ) + { + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } +#else /* MBEDTLS_USE_PSA_CRYPTO */ + ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + if( ret != 0 ) + return( ret ); +#endif + if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Move the written CSR data to the start of buf to create space for + * writing the signature into buf. + */ + memmove( buf, c, len ); + + /* + * Write sig and its OID into buf backwards from the end of buf. + * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len + * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, + mbedtls_x509_write_sig( &c2, buf + len, sig_oid, sig_oid_len, + sig, sig_len ) ); + + /* + * Compact the space between the CSR data and signature by moving the + * CSR data to the start of the signature. + */ + c2 -= len; + memmove( c2, buf, len ); + + /* ASN encode the total size and tag the CSR data with it. */ + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c2, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* Zero the unused bytes at the start of buf */ + memset( buf, 0, c2 - buf); + + return( (int) len ); +} + +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, + size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char *sig; + + if( ( sig = mbedtls_calloc( 1, MBEDTLS_PK_SIGNATURE_MAX_SIZE ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + ret = x509write_csr_der_internal( ctx, buf, size, sig, f_rng, p_rng ); + + mbedtls_free( sig ); + + return( ret ); +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen = 0; + + if( ( ret = mbedtls_x509write_csr_der( ctx, buf, size, + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, + buf + size - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CSR_WRITE_C */ diff --git a/optee/optee_os/lib/libmbedtls/mbedtls/library/xtea.c b/optee/optee_os/lib/libmbedtls/mbedtls/library/xtea.c new file mode 100644 index 0000000..77f6cb6 --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/mbedtls/library/xtea.c @@ -0,0 +1,248 @@ +/* + * An 32-bit implementation of the XTEA algorithm + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_XTEA_C) + +#include "mbedtls/xtea.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_XTEA_ALT) + +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_xtea_context ) ); +} + +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); +} + +/* + * XTEA key schedule + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ) +{ + int i; + + memset( ctx, 0, sizeof(mbedtls_xtea_context) ); + + for( i = 0; i < 4; i++ ) + { + ctx->k[i] = MBEDTLS_GET_UINT32_BE( key, i << 2 ); + } +} + +/* + * XTEA encrypt function + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode, + const unsigned char input[8], unsigned char output[8]) +{ + uint32_t *k, v0, v1, i; + + k = ctx->k; + + v0 = MBEDTLS_GET_UINT32_BE( input, 0 ); + v1 = MBEDTLS_GET_UINT32_BE( input, 4 ); + + if( mode == MBEDTLS_XTEA_ENCRYPT ) + { + uint32_t sum = 0, delta = 0x9E3779B9; + + for( i = 0; i < 32; i++ ) + { + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + sum += delta; + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + } + } + else /* MBEDTLS_XTEA_DECRYPT */ + { + uint32_t delta = 0x9E3779B9, sum = delta * 32; + + for( i = 0; i < 32; i++ ) + { + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); + sum -= delta; + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + } + } + + MBEDTLS_PUT_UINT32_BE( v0, output, 0 ); + MBEDTLS_PUT_UINT32_BE( v1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * XTEA-CBC buffer encryption/decryption + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length, + unsigned char iv[8], const unsigned char *input, + unsigned char *output) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_XTEA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_xtea_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_xtea_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* !MBEDTLS_XTEA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * XTEA tests vectors (non-official) + */ + +static const unsigned char xtea_test_key[6][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 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, + { 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 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char xtea_test_pt[6][8] = +{ + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } +}; + +static const unsigned char xtea_test_ct[6][8] = +{ + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } +}; + +/* + * Checkup routine + */ +int mbedtls_xtea_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char buf[8]; + mbedtls_xtea_context ctx; + + mbedtls_xtea_init( &ctx ); + for( i = 0; i < 6; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " XTEA test #%d: ", i + 1 ); + + memcpy( buf, xtea_test_pt[i], 8 ); + + mbedtls_xtea_setup( &ctx, xtea_test_key[i] ); + mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf ); + + if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_xtea_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_XTEA_C */ diff --git a/optee/optee_os/lib/libmbedtls/sub.mk b/optee/optee_os/lib/libmbedtls/sub.mk new file mode 100644 index 0000000..1a752bf --- /dev/null +++ b/optee/optee_os/lib/libmbedtls/sub.mk @@ -0,0 +1,133 @@ +global-incdirs-y += include +global-incdirs-y += mbedtls/include + +# OBJS_CRYPTO from make file +SRCS_CRYPTO := +ifneq ($(sm),core) +SRCS_CRYPTO += aes.c +SRCS_CRYPTO += aesni.c +SRCS_CRYPTO += arc4.c +SRCS_CRYPTO += aria.c +SRCS_CRYPTO += asn1parse.c +SRCS_CRYPTO += asn1write.c +SRCS_CRYPTO += base64.c +SRCS_CRYPTO += bignum.c +SRCS_CRYPTO += blowfish.c +SRCS_CRYPTO += camellia.c +SRCS_CRYPTO += ccm.c +SRCS_CRYPTO += chacha20.c +SRCS_CRYPTO += chachapoly.c +SRCS_CRYPTO += cipher.c +SRCS_CRYPTO += cipher_wrap.c +SRCS_CRYPTO += cmac.c +SRCS_CRYPTO += constant_time.c +SRCS_CRYPTO += ctr_drbg.c +SRCS_CRYPTO += des.c +SRCS_CRYPTO += dhm.c +SRCS_CRYPTO += ecdh.c +SRCS_CRYPTO += ecdsa.c +SRCS_CRYPTO += ecjpake.c +SRCS_CRYPTO += ecp.c +SRCS_CRYPTO += ecp_curves.c +SRCS_CRYPTO += entropy.c +SRCS_CRYPTO += entropy_poll.c +SRCS_CRYPTO += error.c +SRCS_CRYPTO += gcm.c +SRCS_CRYPTO += havege.c +SRCS_CRYPTO += hkdf.c +SRCS_CRYPTO += hmac_drbg.c +SRCS_CRYPTO += md.c +SRCS_CRYPTO += md2.c +SRCS_CRYPTO += md4.c +SRCS_CRYPTO += md5.c +SRCS_CRYPTO += memory_buffer_alloc.c +SRCS_CRYPTO += nist_kw.c +SRCS_CRYPTO += oid.c +SRCS_CRYPTO += padlock.c +SRCS_CRYPTO += pem.c +SRCS_CRYPTO += pk.c +SRCS_CRYPTO += pk_wrap.c +SRCS_CRYPTO += pkcs12.c +SRCS_CRYPTO += pkcs5.c +SRCS_CRYPTO += pkparse.c +SRCS_CRYPTO += pkwrite.c +SRCS_CRYPTO += platform.c +SRCS_CRYPTO += platform_util.c +SRCS_CRYPTO += poly1305.c +SRCS_CRYPTO += ripemd160.c +SRCS_CRYPTO += rsa_internal.c +SRCS_CRYPTO += rsa.c +SRCS_CRYPTO += sha1.c +SRCS_CRYPTO += sha256.c +SRCS_CRYPTO += sha512.c +SRCS_CRYPTO += threading.c +SRCS_CRYPTO += timing.c +SRCS_CRYPTO += version.c +SRCS_CRYPTO += version_features.c +SRCS_CRYPTO += xtea.c +else +SRCS_CRYPTO += aes.c +SRCS_CRYPTO += aesni.c +SRCS_CRYPTO += asn1parse.c +SRCS_CRYPTO += asn1write.c +SRCS_CRYPTO += bignum.c +SRCS_CRYPTO += cipher.c +SRCS_CRYPTO += cipher_wrap.c +SRCS_CRYPTO += cmac.c +SRCS_CRYPTO += constant_time.c +SRCS_CRYPTO += ctr_drbg.c +SRCS_CRYPTO += des.c +SRCS_CRYPTO += dhm.c +SRCS_CRYPTO += ecdh.c +SRCS_CRYPTO += ecdsa.c +SRCS_CRYPTO += ecp.c +SRCS_CRYPTO += ecp_curves.c +SRCS_CRYPTO += md.c +SRCS_CRYPTO += md5.c +SRCS_CRYPTO += oid.c +SRCS_CRYPTO += pk.c +SRCS_CRYPTO += pk_wrap.c +SRCS_CRYPTO += platform.c +SRCS_CRYPTO += platform_util.c +SRCS_CRYPTO += rsa_internal.c +SRCS_CRYPTO += rsa.c +SRCS_CRYPTO += sha1.c +SRCS_CRYPTO += sha256.c +SRCS_CRYPTO += sha512.c +endif + +# OBJS_X509 +SRCS_X509 := +SRCS_X509 += certs.c +SRCS_X509 += pkcs11.c +SRCS_X509 += x509.c +SRCS_X509 += x509_create.c +SRCS_X509 += x509_crl.c +SRCS_X509 += x509_crt.c +SRCS_X509 += x509_csr.c +SRCS_X509 += x509write_crt.c +SRCS_X509 += x509write_csr.c + +# OBJS_TLS +SRCS_TLS := +SRCS_TLS += debug.c +SRCS_TLS += net_sockets.c +SRCS_TLS += ssl_cache.c +SRCS_TLS += ssl_ciphersuites.c +SRCS_TLS += ssl_cli.c +SRCS_TLS += ssl_cookie.c +SRCS_TLS += ssl_srv.c +SRCS_TLS += ssl_ticket.c +SRCS_TLS += ssl_tls.c + +srcs-y += $(addprefix mbedtls/library/, $(SRCS_CRYPTO)) +srcs-$(sm-$(ta-target)) += $(addprefix mbedtls/library/, $(SRCS_X509)) +srcs-$(sm-$(ta-target)) += $(addprefix mbedtls/library/, $(SRCS_TLS)) + +cflags-lib-y += -Wno-redundant-decls +cflags-lib-y += -Wno-switch-default +cflags-lib-y += -Wno-declaration-after-statement + +ifeq ($(CFG_CRYPTOLIB_NAME_mbedtls),y) +subdirs-$(sm-core) += core +endif diff --git a/optee/optee_os/lib/libunw/include/unw/unwind.h b/optee/optee_os/lib/libunw/include/unw/unwind.h new file mode 100644 index 0000000..275cebf --- /dev/null +++ b/optee/optee_os/lib/libunw/include/unw/unwind.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND MIT-CMU) */ +/*- + * Copyright (c) 2015-2019, Linaro Limited + * Copyright (c) 2000, 2001 Ben Harris + * Copyright (c) 1996 Scott K. Stevens + * + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * $FreeBSD$ + */ + +#ifndef UNW_UNWIND_H +#define UNW_UNWIND_H + +#include +#include + +/* The state of the unwind process (32-bit mode) */ +struct unwind_state_arm32 { + uint32_t registers[16]; + uint32_t start_pc; + vaddr_t insn; + unsigned int entries; + unsigned int byte; + uint16_t update_mask; +}; + +#ifdef CFG_UNWIND +/* + * Unwind a 32-bit stack. + * @stack, @stack_size: the bottom of the stack and its size, respectively. + * Returns false when there is nothing more to unwind. + */ +bool unwind_stack_arm32(struct unwind_state_arm32 *state, + vaddr_t stack, size_t stack_size); + +void print_stack_arm32(struct unwind_state_arm32 *state, + vaddr_t stack, size_t stack_size); +#else +static inline bool unwind_stack_arm32(struct unwind_state_arm32 *state __unused, + vaddr_t stack __unused, + size_t stack_size __unused) +{ + return false; +} + +static inline void print_stack_arm32(struct unwind_state_arm32 *state __unused, + vaddr_t stack __unused, + size_t stack_size __unused) +{ +} +#endif + +/* + * External helper function. Must be implemented by the caller of the 32-bit + * stack unwinding functions. + */ +bool find_exidx(vaddr_t addr, vaddr_t *idx_start, vaddr_t *idx_end); + +/* The state of the unwind process (64-bit mode) */ +struct unwind_state_arm64 { + uint64_t fp; + uint64_t sp; + uint64_t pc; +}; + +#if defined(ARM64) && defined(CFG_UNWIND) +/* + * Unwind a 64-bit stack. + * @stack, @stack_size: the bottom of the stack and its size, respectively. + * Returns false when there is nothing more to unwind. + */ +bool unwind_stack_arm64(struct unwind_state_arm64 *state, + vaddr_t stack, size_t stack_size); + +void print_stack_arm64(struct unwind_state_arm64 *state, + vaddr_t stack, size_t stack_size); +#else +static inline bool unwind_stack_arm64(struct unwind_state_arm64 *state __unused, + vaddr_t stack __unused, + size_t stack_size __unused) +{ + return false; +} + +static inline void print_stack_arm64(struct unwind_state_arm64 *state __unused, + vaddr_t stack __unused, + size_t stack_size __unused) +{ +} +#endif + +/* + * External helper function optionally implemented by the caller of the 64-bit + * stack unwinding functions. + */ +void ftrace_map_lr(uint64_t *lr); + +/* Strip out PAuth tags from LR content if applicable */ +void pauth_strip_pac(uint64_t *lr); + +#endif /*UNW_UNWIND_H*/ diff --git a/optee/optee_os/lib/libunw/sub.mk b/optee/optee_os/lib/libunw/sub.mk new file mode 100644 index 0000000..bbb7e91 --- /dev/null +++ b/optee/optee_os/lib/libunw/sub.mk @@ -0,0 +1,5 @@ +global-incdirs-y += include +ifeq ($(CFG_UNWIND),y) +srcs-y += unwind_arm32.c +srcs-$(CFG_ARM64_$(sm)) += unwind_arm64.c +endif diff --git a/optee/optee_os/lib/libunw/unwind_arm32.c b/optee/optee_os/lib/libunw/unwind_arm32.c new file mode 100644 index 0000000..18b3480 --- /dev/null +++ b/optee/optee_os/lib/libunw/unwind_arm32.c @@ -0,0 +1,418 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright 2015-2019 Linaro Limited + * Copyright 2013-2014 Andrew Turner. + * Copyright 2013-2014 Ian Lepore. + * Copyright 2013-2014 Rui Paulo. + * Copyright 2013 Eitan Adler. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 + +/* The register names */ +#define FP 11 +#define SP 13 +#define LR 14 +#define PC 15 + +/* + * Definitions for the instruction interpreter. + * + * The ARM EABI specifies how to perform the frame unwinding in the + * Exception Handling ABI for the ARM Architecture document. To perform + * the unwind we need to know the initial frame pointer, stack pointer, + * link register and program counter. We then find the entry within the + * index table that points to the function the program counter is within. + * This gives us either a list of three instructions to process, a 31-bit + * relative offset to a table of instructions, or a value telling us + * we can't unwind any further. + * + * When we have the instructions to process we need to decode them + * following table 4 in section 9.3. This describes a collection of bit + * patterns to encode that steps to take to update the stack pointer and + * link register to the correct values at the start of the function. + */ + +/* A special case when we are unable to unwind past this function */ +#define EXIDX_CANTUNWIND 1 + +/* + * Entry types. + * These are the only entry types that have been seen in the kernel. + */ +#define ENTRY_MASK 0xff000000 +#define ENTRY_ARM_SU16 0x80000000 +#define ENTRY_ARM_LU16 0x81000000 + +/* Instruction masks. */ +#define INSN_VSP_MASK 0xc0 +#define INSN_VSP_SIZE_MASK 0x3f +#define INSN_STD_MASK 0xf0 +#define INSN_STD_DATA_MASK 0x0f +#define INSN_POP_TYPE_MASK 0x08 +#define INSN_POP_COUNT_MASK 0x07 +#define INSN_VSP_LARGE_INC_MASK 0xff + +/* Instruction definitions */ +#define INSN_VSP_INC 0x00 +#define INSN_VSP_DEC 0x40 +#define INSN_POP_MASKED 0x80 +#define INSN_VSP_REG 0x90 +#define INSN_POP_COUNT 0xa0 +#define INSN_FINISH 0xb0 +#define INSN_POP_REGS 0xb1 +#define INSN_VSP_LARGE_INC 0xb2 + +/* An item in the exception index table */ +struct unwind_idx { + uint32_t offset; + uint32_t insn; +}; + +static bool copy_in(void *dst, const void *src, size_t n) +{ + memcpy(dst, src, n); + return true; +} + +/* Expand a 31-bit signed value to a 32-bit signed value */ +static int32_t expand_prel31(uint32_t prel31) +{ + return prel31 | SHIFT_U32(prel31 & BIT32(30), 1); +} + +/* + * Perform a binary search of the index table to find the function + * with the largest address that does not exceed addr. + */ +static struct unwind_idx *find_index(uint32_t addr) +{ + vaddr_t idx_start = 0; + vaddr_t idx_end = 0; + unsigned int min = 0; + unsigned int mid = 0; + unsigned int max = 0; + struct unwind_idx *start = NULL; + struct unwind_idx *item = NULL; + int32_t prel31_addr = 0; + vaddr_t func_addr = 0; + + if (!find_exidx(addr, &idx_start, &idx_end)) + return NULL; + + start = (struct unwind_idx *)idx_start; + + min = 0; + max = (idx_end - idx_start) / sizeof(struct unwind_idx); + + while (min != max) { + mid = min + (max - min + 1) / 2; + + item = &start[mid]; + + prel31_addr = expand_prel31(item->offset); + func_addr = (vaddr_t)&item->offset + prel31_addr; + + if (func_addr <= addr) + min = mid; + else + max = mid - 1; + } + + return &start[min]; +} + +/* Reads the next byte from the instruction list */ +static bool unwind_exec_read_byte(struct unwind_state_arm32 *state, + uint32_t *ret_insn) +{ + uint32_t insn; + + if (!copy_in(&insn, (void *)state->insn, sizeof(insn))) + return false; + + /* Read the unwind instruction */ + *ret_insn = (insn >> (state->byte * 8)) & 0xff; + + /* Update the location of the next instruction */ + if (state->byte == 0) { + state->byte = 3; + state->insn += sizeof(uint32_t); + state->entries--; + } else { + state->byte--; + } + + return true; +} + +static bool pop_vsp(uint32_t *reg, vaddr_t *vsp, vaddr_t stack, + size_t stack_size) +{ + if (*vsp < stack) + return false; + if (*vsp + sizeof(*reg) > stack + stack_size) + return false; + + if (!copy_in(reg, (void *)*vsp, sizeof(*reg))) + return false; + (*vsp) += sizeof(*reg); + return true; +} + +/* Executes the next instruction on the list */ +static bool unwind_exec_insn(struct unwind_state_arm32 *state, vaddr_t stack, + size_t stack_size) +{ + uint32_t insn; + vaddr_t vsp = state->registers[SP]; + int update_vsp = 0; + + /* Read the next instruction */ + if (!unwind_exec_read_byte(state, &insn)) + return false; + + if ((insn & INSN_VSP_MASK) == INSN_VSP_INC) { + state->registers[SP] += ((insn & INSN_VSP_SIZE_MASK) << 2) + 4; + + } else if ((insn & INSN_VSP_MASK) == INSN_VSP_DEC) { + state->registers[SP] -= ((insn & INSN_VSP_SIZE_MASK) << 2) + 4; + + } else if ((insn & INSN_STD_MASK) == INSN_POP_MASKED) { + uint32_t mask; + unsigned int reg; + + /* Load the mask */ + if (!unwind_exec_read_byte(state, &mask)) + return false; + mask |= (insn & INSN_STD_DATA_MASK) << 8; + + /* We have a refuse to unwind instruction */ + if (mask == 0) + return false; + + /* Update SP */ + update_vsp = 1; + + /* Load the registers */ + for (reg = 4; mask && reg < 16; mask >>= 1, reg++) { + if (mask & 1) { + if (!pop_vsp(&state->registers[reg], &vsp, + stack, stack_size)) + return false; + state->update_mask |= 1 << reg; + + /* If we have updated SP kep its value */ + if (reg == SP) + update_vsp = 0; + } + } + + } else if ((insn & INSN_STD_MASK) == INSN_VSP_REG && + ((insn & INSN_STD_DATA_MASK) != 13) && + ((insn & INSN_STD_DATA_MASK) != 15)) { + /* sp = register */ + state->registers[SP] = + state->registers[insn & INSN_STD_DATA_MASK]; + + } else if ((insn & INSN_STD_MASK) == INSN_POP_COUNT) { + unsigned int count, reg; + + /* Read how many registers to load */ + count = insn & INSN_POP_COUNT_MASK; + + /* Update sp */ + update_vsp = 1; + + /* Pop the registers */ + for (reg = 4; reg <= 4 + count; reg++) { + if (!pop_vsp(&state->registers[reg], &vsp, + stack, stack_size)) + return false; + state->update_mask |= 1 << reg; + } + + /* Check if we are in the pop r14 version */ + if ((insn & INSN_POP_TYPE_MASK) != 0) { + if (!pop_vsp(&state->registers[14], &vsp, + stack, stack_size)) + return false; + } + + } else if (insn == INSN_FINISH) { + /* Stop processing */ + state->entries = 0; + + } else if (insn == INSN_POP_REGS) { + uint32_t mask; + unsigned int reg; + + if (!unwind_exec_read_byte(state, &mask)) + return false; + if (mask == 0 || (mask & 0xf0) != 0) + return false; + + /* Update SP */ + update_vsp = 1; + + /* Load the registers */ + for (reg = 0; mask && reg < 4; mask >>= 1, reg++) { + if (mask & 1) { + if (!pop_vsp(&state->registers[reg], &vsp, + stack, stack_size)) + return false; + state->update_mask |= 1 << reg; + } + } + + } else if ((insn & INSN_VSP_LARGE_INC_MASK) == INSN_VSP_LARGE_INC) { + uint32_t uleb128; + + /* Read the increment value */ + if (!unwind_exec_read_byte(state, &uleb128)) + return false; + + state->registers[SP] += 0x204 + (uleb128 << 2); + + } else { + /* We hit a new instruction that needs to be implemented */ + DMSG("Unhandled instruction %.2x", insn); + return false; + } + + if (update_vsp) + state->registers[SP] = vsp; + + return true; +} + +/* Performs the unwind of a function */ +static bool unwind_tab(struct unwind_state_arm32 *state, vaddr_t stack, + size_t stack_size) +{ + uint32_t entry; + uint32_t insn; + + /* Set PC to a known value */ + state->registers[PC] = 0; + + if (!copy_in(&insn, (void *)state->insn, sizeof(insn))) { + DMSG("Bad insn addr %p", (void *)state->insn); + return true; + } + + /* Read the personality */ + entry = insn & ENTRY_MASK; + + if (entry == ENTRY_ARM_SU16) { + state->byte = 2; + state->entries = 1; + } else if (entry == ENTRY_ARM_LU16) { + state->byte = 1; + state->entries = ((insn >> 16) & 0xFF) + 1; + } else { + DMSG("Unknown entry: %x", entry); + return true; + } + + while (state->entries > 0) { + if (!unwind_exec_insn(state, stack, stack_size)) + return true; + } + + /* + * The program counter was not updated, load it from the link register. + */ + if (state->registers[PC] == 0) { + state->registers[PC] = state->registers[LR]; + + /* + * If the program counter changed, flag it in the update mask. + */ + if (state->start_pc != state->registers[PC]) + state->update_mask |= 1 << PC; + } + + return false; +} + +bool unwind_stack_arm32(struct unwind_state_arm32 *state, + vaddr_t stack, size_t stack_size) +{ + struct unwind_idx *index; + bool finished; + + /* Reset the mask of updated registers */ + state->update_mask = 0; + + /* The pc value is correct and will be overwritten, save it */ + state->start_pc = state->registers[PC]; + + /* + * Find the item to run. Subtract 2 from PC to make sure that we're + * still inside the calling function in case a __no_return function + * (typically panic()) is called unconditionally and may cause LR and + * thus this PC to point into the next and entirely unrelated function. + */ + index = find_index(state->start_pc - 2); + if (!index) + return false; + + finished = false; + if (index->insn != EXIDX_CANTUNWIND) { + if (index->insn & (1U << 31)) { + /* The data is within the instruction */ + state->insn = (vaddr_t)&index->insn; + } else { + /* A prel31 offset to the unwind table */ + state->insn = (vaddr_t)&index->insn + + expand_prel31(index->insn); + } + + /* Run the unwind function */ + finished = unwind_tab(state, stack, stack_size); + } + + /* This is the top of the stack, finish */ + if (index->insn == EXIDX_CANTUNWIND) + finished = true; + + return !finished; +} + +void print_stack_arm32(struct unwind_state_arm32 *state, + vaddr_t stack, size_t stack_size) +{ + trace_printf_helper_raw(TRACE_ERROR, true, "Call stack:"); + do { + trace_printf_helper_raw(TRACE_ERROR, true, " 0x%08" PRIx32, + state->registers[PC]); + } while (unwind_stack_arm32(state, stack, stack_size)); +} diff --git a/optee/optee_os/lib/libunw/unwind_arm64.c b/optee/optee_os/lib/libunw/unwind_arm64.c new file mode 100644 index 0000000..0e01d3e --- /dev/null +++ b/optee/optee_os/lib/libunw/unwind_arm64.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-2-Clause +/*- + * Copyright (c) 2015-2019 Linaro Limited + * Copyright (c) 2015 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under + * the sponsorship of the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 __weak ftrace_map_lr(uint64_t *lr __unused) +{} + +void __weak pauth_strip_pac(uint64_t *lr __unused) +{} + +static bool copy_in_reg(uint64_t *reg, vaddr_t addr) +{ + memcpy(reg, (void *)addr, sizeof(*reg)); + return true; +} + +bool unwind_stack_arm64(struct unwind_state_arm64 *frame, + vaddr_t stack, size_t stack_size) +{ + vaddr_t fp = frame->fp; + + if (fp < stack) + return false; + if (fp + sizeof(uint64_t) * 3 > stack + stack_size) + return false; + + frame->sp = fp + 0x10; + /* FP to previous frame (X29) */ + if (!copy_in_reg(&frame->fp, fp)) + return false; + if (!frame->fp) + return false; + /* LR (X30) */ + if (!copy_in_reg(&frame->pc, fp + 8)) + return false; + + pauth_strip_pac(&frame->pc); + + ftrace_map_lr(&frame->pc); + + frame->pc -= 4; + + return true; +} + +void print_stack_arm64(struct unwind_state_arm64 *state, + vaddr_t stack, size_t stack_size) +{ + int width = 8; + + trace_printf_helper_raw(TRACE_ERROR, true, "Call stack:"); + + ftrace_map_lr(&state->pc); + do { + trace_printf_helper_raw(TRACE_ERROR, true, " 0x%0*"PRIx64, + width, state->pc); + } while (unwind_stack_arm64(state, stack, stack_size)); +} diff --git a/optee/optee_os/lib/libutee/abort.c b/optee/optee_os/lib/libutee/abort.c new file mode 100644 index 0000000..09ccd96 --- /dev/null +++ b/optee/optee_os/lib/libutee/abort.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include +#include +#include +#include +#include + +void abort(void) +{ + printf("Abort!\n"); + _utee_panic(0); + /* Not reached */ + while (1) + ; +} diff --git a/optee/optee_os/lib/libutee/arch/arm/arm32_user_sysreg.txt b/optee/optee_os/lib/libutee/arch/arm/arm32_user_sysreg.txt new file mode 100644 index 0000000..8905219 --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/arm32_user_sysreg.txt @@ -0,0 +1,14 @@ +# Format of file +# +# lines beginning with '@' will be printed as additional comments + +@ Based on register description in +@ ARM Architecture Reference Manual +@ ARMv7-A and ARMv7-R edition +@ Issue C.c +@ + +@ B8.2 Generic Timer registers summary +CNTFRQ c14 0 c0 0 RW Counter Frequency register +CNTPCT - 0 c14 - RO Physical Count register +CNTVCT - 1 c14 - RO Virtual Count register diff --git a/optee/optee_os/lib/libutee/arch/arm/gprof/gmon.h b/optee/optee_os/lib/libutee/arch/arm/gprof/gmon.h new file mode 100644 index 0000000..da5466b --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/gprof/gmon.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) */ +/* + * Copyright (c) 2016, 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. + */ + +/* + * This file is adapted from glibc' gmon/sys/gmon.h. + *- + * Copyright (c) 1982, 1986, 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. + * 4. 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. + */ + +/* + * See gmon_out.h for gmon.out format. + */ + +#ifndef GMON_H +#define GMON_H + +#include +#include + +/* Exported by the TA linker script */ +extern uint8_t __text_start[]; +extern uint8_t __text_end[]; + +void __mcount_internal(unsigned long frompc, unsigned long selfpc); + + +/* + * Histogram counters are unsigned shorts (according to the kernel). + */ +#define HISTCOUNTER unsigned short + +/* + * Fraction of text space to allocate for histogram counters here, 1/2 + */ +#define HISTFRACTION 2 + +/* + * Fraction of text space to allocate for from hash buckets. + * The value of HASHFRACTION is based on the minimum number of bytes + * of separation between two subroutine call points in the object code. + * Given MIN_SUBR_SEPARATION bytes of separation the value of + * HASHFRACTION is calculated as: + * + * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1); + * + * For example, on the VAX, the shortest two call sequence is: + * + * calls $0,(r0) + * calls $0,(r0) + * + * which is separated by only three bytes, thus HASHFRACTION is + * calculated as: + * + * HASHFRACTION = 3 / (2 * 2 - 1) = 1 + * + * Note that the division above rounds down, thus if MIN_SUBR_FRACTION + * is less than three, this algorithm will not work! + * + * In practice, however, call instructions are rarely at a minimal + * distance. Hence, we will define HASHFRACTION to be 2 across all + * architectures. This saves a reasonable amount of space for + * profiling data structures without (in practice) sacrificing + * any granularity. + */ +#define HASHFRACTION 2 + +/* + * Percent of text space to allocate for tostructs. + * This is a heuristic; we will fail with a warning when profiling programs + * with a very large number of very small functions, but that's + * normally OK. + * 2 is probably still a good value for normal programs. + * Profiling a test case with 64000 small functions will work if + * you raise this value to 3 and link statically (which bloats the + * text size, thus raising the number of arcs expected by the heuristic). + */ +#define ARCDENSITY 3 + +/* + * Always allocate at least this many tostructs. This + * hides the inadequacy of the ARCDENSITY heuristic, at least + * for small programs. + */ +#define MINARCS 50 + +/* + * The type used to represent indices into gmonparam.tos[]. + */ +#define ARCINDEX unsigned long + +/* + * Maximum number of arcs we want to allow. + * Used to be max representable value of ARCINDEX minus 2, but now + * that ARCINDEX is a long, that's too large; we don't really want + * to allow a 48 gigabyte table. + * The old value of 1<<16 wasn't high enough in practice for large C++ + * programs; will 1<<20 be adequate for long? FIXME + */ +#define MAXARCS (1 << 20) + +struct tostruct { + unsigned long selfpc; + long count; + ARCINDEX link; +}; + +/* + * A raw arc, with pointers to the calling site and the called site and a + * count. + */ +struct rawarc { + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; +}; + +/* + * The profiling data structures are housed in this structure. + */ +struct gmonparam { + long int state; + unsigned short *kcount; + unsigned long kcountsize; + ARCINDEX *froms; + unsigned long fromssize; + struct tostruct *tos; + unsigned long tossize; + unsigned long tolimit; + unsigned long lowpc; + unsigned long highpc; + unsigned long textsize; + unsigned long hashfraction; + long log_hashfraction; + /* */ + uint32_t prof_rate; /* PC sampling frequency */ +}; + +/* + * Possible states of profiling. + */ +#define GMON_PROF_ON 0 +#define GMON_PROF_BUSY 1 +#define GMON_PROF_ERROR 2 +#define GMON_PROF_OFF 3 +#define GMON_PROF_OFF_EXITING 4 + +#endif /* GMON_H */ diff --git a/optee/optee_os/lib/libutee/arch/arm/gprof/gmon_out.h b/optee/optee_os/lib/libutee/arch/arm/gprof/gmon_out.h new file mode 100644 index 0000000..6faadaa --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/gprof/gmon_out.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, 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. + */ + +/* + * gmon.out file format + * + * This file is adapted from glibc's gmon/sys/gmon_out.h + * Although gmon/sys/gmon_out.h is covered by the LGPL v2.1 license or later + * as stated below, please note the following: + * (https://www.gnu.org/licenses/lgpl-3.0.en.html#section3) + * + * "3. Object Code Incorporating Material from Library Header Files. + * The object code form of an Application may incorporate material from a + * header file that is part of the Library. You may convey such object code + * under terms of your choice, provided that, if the incorporated material + * is not limited to numerical parameters, data structure layouts and + * accessors, or small macros, inline functions and templates (ten or fewer + * lines in length), you do both of the following: [...]" + * + * The code below is indeed limited to data structure layouts. + */ + +/* + * Copyright (C) 1996-2016 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * Contributed by David Mosberger . + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * . + */ + +/* + * This file specifies the format of gmon.out files. It should have + * as few external dependencies as possible as it is going to be included + * in many different programs. That is, minimize the number of #include's. + * + * A gmon.out file consists of a header (defined by gmon_hdr) followed by + * a sequence of records. Each record starts with a one-byte tag + * identifying the type of records, followed by records specific data. + */ + +#ifndef GMON_OUT_H +#define GMON_OUT_H + +#define GMON_MAGIC "gmon" /* magic cookie */ +#define GMON_VERSION 1 /* version number */ + +/* + * Raw header as it appears on file (without padding). This header + * always comes first in gmon.out and is then followed by a series + * records defined below. + * Virtual addresses are stored as uintptr_t, gprof knows which size to expect + * because the executable file is provided. + */ +struct gmon_hdr { + char cookie[4]; + int32_t version; + char spare[3 * 4]; +} __packed; + +/* types of records in this file: */ +enum gmon_record_tag { + GMON_TAG_TIME_HIST = 0, + GMON_TAG_CG_ARC = 1, + GMON_TAG_BB_COUNT = 2 +}; + +struct gmon_hist_hdr { + uintptr_t low_pc; /* base pc address of sample buffer */ + uintptr_t high_pc; /* max pc address of sampled buffer */ + uint32_t hist_size; /* size of sample buffer */ + uint32_t prof_rate; /* profiling clock rate */ + char dimen[15]; /* phys. dim., usually "seconds" */ + char dimen_abbrev; /* usually 's' for "seconds" */ +} __packed; + +struct gmon_cg_arc_record { + uintptr_t from_pc; /* address within caller's body */ + uintptr_t self_pc; /* address within callee's body */ + int32_t count; /* number of arc traversals */ +} __packed; + +#endif /* GMON_OUT_H */ diff --git a/optee/optee_os/lib/libutee/arch/arm/gprof/gprof.c b/optee/optee_os/lib/libutee/arch/arm/gprof/gprof.c new file mode 100644 index 0000000..d35da96 --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/gprof/gprof.c @@ -0,0 +1,434 @@ +// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) +/* + * Copyright (c) 2016, 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. + */ + +/* + * Portions of this file are adapted from glibc: + * gmon/gmon.c + * gmon/mcount.c + * + *- + * Copyright (c) 1983, 1992, 1993, 2011 + * 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. + * 4. 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gmon.h" +#include "gmon_out.h" +#include "gprof_pta.h" + +static void *gprof_buf; +static size_t gprof_buf_len; + +#if defined(ARM32) +#define MCOUNT_SYM __gnu_mcount_nc +#elif defined(ARM64) +#define MCOUNT_SYM _mcount +#endif + +static void dummy(void) {} +void (*MCOUNT_SYM)(void) __weak = dummy; + +static bool ta_instrumented(void) +{ + /* + * Return true if the mcount function is called somewhere (and therefore + * profiling should be initialized). + * Since gprof is not supported with shared libraries, checking if + * mcount is called is the same as checking if it is present in the + * TA binary, because the function would be eliminated at link time if + * not used. + */ + return dummy != MCOUNT_SYM; +} + +#undef MCOUNT_SYM + +static void *gprof_alloc(size_t len) +{ + assert(!gprof_buf); + gprof_buf = tee_map_zi(len, TEE_MEMORY_ACCESS_ANY_OWNER); + gprof_buf_len = len; + return gprof_buf; +} + +static struct gmonparam _gmonparam = { GMON_PROF_OFF }; + +static uint32_t _gprof_file_id; /* File id returned by tee-supplicant */ + +static int _gprof_s_scale; +#define SCALE_1_TO_1 0x10000L + +/* Adjust PC so that gprof can locate it in the TA ELF file */ +static unsigned long __noprof adjust_pc(unsigned long pc) +{ + return pc - (unsigned long)__text_start + sizeof(struct ta_head); +} + +void __utee_gprof_init(void) +{ + unsigned long lowpc; + unsigned long highpc; + struct gmonparam *p = &_gmonparam; + size_t bufsize; + TEE_Result res; + char *cp; + + if (!ta_instrumented()) + return; + + lowpc = adjust_pc((unsigned long)__text_start); + highpc = adjust_pc((unsigned long)__text_end); + + /* + * Round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->textsize = p->highpc - p->lowpc; + p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms)); + p->hashfraction = HASHFRACTION; + p->log_hashfraction = -1; + /* + * The following test must be kept in sync with the corresponding + * test in __mcount_internal + */ + if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) { + /* + * If HASHFRACTION is a power of two, mcount can use shifting + * instead of integer division. Precompute shift amount. + */ + p->log_hashfraction = __builtin_ffs(p->hashfraction * + sizeof(*p->froms)) - 1; + } + p->fromssize = p->textsize / HASHFRACTION; + p->tolimit = p->textsize * ARCDENSITY / 100; + if (p->tolimit < MINARCS) + p->tolimit = MINARCS; + else if (p->tolimit > MAXARCS) + p->tolimit = MAXARCS; + p->tossize = p->tolimit * sizeof(struct tostruct); + + bufsize = p->kcountsize + p->fromssize + p->tossize; + + IMSG("gprof: initializing"); + DMSG("TA text size: %zu, gprof buffer size: %zu", + __text_end - __text_start, bufsize); + + cp = gprof_alloc(bufsize); + if (!cp) { + EMSG("gprof: could not allocate profiling buffer"); + p->tos = NULL; + p->state = GMON_PROF_ERROR; + return; + } + + p->tos = (struct tostruct *)cp; + cp += p->tossize; + p->kcount = (HISTCOUNTER *)cp; + cp += p->kcountsize; + p->froms = (ARCINDEX *)cp; + + p->tos[0].link = 0; + + if (p->kcountsize < p->textsize) + _gprof_s_scale = ((float)p->kcountsize / p->textsize) * + SCALE_1_TO_1; + else + _gprof_s_scale = SCALE_1_TO_1; + + res = __pta_gprof_pc_sampling_start(p->kcount, p->kcountsize, + p->lowpc + + ((unsigned long)__text_start - + sizeof(struct ta_head)), + _gprof_s_scale); + if (res != TEE_SUCCESS) + EMSG("gprof: could not start PC sampling (0x%08x)", res); + + p->state = GMON_PROF_ON; +} + +static void _gprof_write_buf(void *buf, size_t size) +{ + TEE_Result res; + + res = __pta_gprof_send(buf, size, &_gprof_file_id); + if (res != TEE_SUCCESS) + EMSG("gprof: could not send gprof data (0x%08x)", res); +} + +static void _gprof_write_header(void) +{ + struct gmon_hdr ghdr; + size_t size = sizeof(struct gmon_hdr); + + memcpy(&ghdr.cookie[0], GMON_MAGIC, sizeof(ghdr.cookie)); + ghdr.version = GMON_VERSION; + memset(ghdr.spare, '\0', sizeof(ghdr.spare)); + + _gprof_write_buf(&ghdr, size); +} + +static void _gprof_write_hist(void) +{ + struct out_record { + uint8_t tag; + struct gmon_hist_hdr hist_hdr; + } __packed out = { + .tag = GMON_TAG_TIME_HIST, + .hist_hdr = { + .low_pc = _gmonparam.lowpc, + .high_pc = _gmonparam.highpc, + .hist_size = _gmonparam.kcountsize/sizeof(HISTCOUNTER), + .prof_rate = _gmonparam.prof_rate, + .dimen = "seconds", + .dimen_abbrev = 's', + } + }; + + _gprof_write_buf(&out, sizeof(out)); + _gprof_write_buf(_gmonparam.kcount, _gmonparam.kcountsize); +} + +static void _gprof_write_call_graph(void) +{ +#define NARCS_PER_WRITE 16 + struct out_record { + uint8_t tag; + uint8_t data[sizeof(struct gmon_cg_arc_record)]; + } out[NARCS_PER_WRITE]; + struct gmon_cg_arc_record arc; + ARCINDEX from_index, to_index; + unsigned long from_len; + unsigned long frompc; + int nfilled = 0; + + from_len = _gmonparam.fromssize / sizeof(*_gmonparam.froms); + + for (from_index = 0; from_index < from_len; ++from_index) { + + if (_gmonparam.froms[from_index] == 0) + continue; + + frompc = _gmonparam.lowpc; + frompc += (from_index * _gmonparam.hashfraction + * sizeof(*_gmonparam.froms)); + for (to_index = _gmonparam.froms[from_index]; + to_index != 0; + to_index = _gmonparam.tos[to_index].link) { + + arc.from_pc = frompc; + arc.self_pc = _gmonparam.tos[to_index].selfpc; + arc.count = _gmonparam.tos[to_index].count; + + out[nfilled].tag = GMON_TAG_CG_ARC; + memcpy(out[nfilled].data, &arc, sizeof(arc)); + + if (++nfilled == NARCS_PER_WRITE) { + _gprof_write_buf(out, sizeof(out)); + nfilled = 0; + } + } + } + if (nfilled > 0) + _gprof_write_buf(out, nfilled * sizeof(out[0])); +} + +/* Stop profiling and send profile data in gmon.out format to Normal World */ +void __utee_gprof_fini(void) +{ + TEE_Result res; + + if (_gmonparam.state != GMON_PROF_ON) + return; + + /* Stop call graph tracing */ + _gmonparam.state = GMON_PROF_OFF_EXITING; + + /* Stop TA sampling */ + res = __pta_gprof_pc_sampling_stop(&_gmonparam.prof_rate); + + _gprof_write_header(); + if (res == TEE_SUCCESS) + _gprof_write_hist(); + _gprof_write_call_graph(); + + __pta_gprof_fini(); + + if (gprof_buf) { + res = tee_unmap(gprof_buf, gprof_buf_len); + assert(!res); + gprof_buf = NULL; + } +} + +/* + * Called from the assembly stub (_mcount or __gnu_mcount_nc). + * + * __mcount_internal updates data structures that represent traversals of the + * program's call graph edges. frompc and selfpc are the return + * address and function address that represents the given call graph edge. + */ +void __noprof __mcount_internal(unsigned long frompc, unsigned long selfpc) +{ + ARCINDEX *frompcindex; + struct tostruct *top, *prevtop; + struct gmonparam *p; + ARCINDEX toindex; + int i; + + p = &_gmonparam; + + /* + * Check that we are profiling and that we aren't recursively invoked. + */ + if (p->state != GMON_PROF_ON) + return; + p->state = GMON_PROF_BUSY; + + frompc = adjust_pc(frompc); + selfpc = adjust_pc(selfpc); + + /* Check that frompcindex is a reasonable pc value. */ + frompc -= p->lowpc; + if (frompc > p->textsize) + goto done; + + /* Note: keep in sync. with the initialization function above */ + if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) { + /* Avoid integer divide if possible */ + i = frompc >> p->log_hashfraction; + } else { + i = frompc / (p->hashfraction * sizeof(*p->froms)); + } + frompcindex = &p->froms[i]; + toindex = *frompcindex; + if (toindex == 0) { + /* First time traversing this arc */ + toindex = ++p->tos[0].link; + if (toindex >= p->tolimit) { + /* Halt further profiling */ + goto overflow; + } + + *frompcindex = toindex; + top = &p->tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = 0; + goto done; + } + top = &p->tos[toindex]; + if (top->selfpc == selfpc) { + /* Arc at front of chain; usual case */ + top->count++; + goto done; + } + /* + * Have to go looking down chain for it. + * top points to what we are looking at, + * prevtop points to previous top. + * we know it is not at the head of the chain. + */ + for (;;) { + if (top->link == 0) { + /* + * top is end of the chain and none of the chain + * had top->selfpc == selfpc. + * so we allocate a new tostruct + * and link it to the head of the chain. + */ + toindex = ++p->tos[0].link; + if (toindex >= p->tolimit) + goto overflow; + + top = &p->tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + /* + * Otherwise, check the next arc on the chain. + */ + prevtop = top; + top = &p->tos[top->link]; + if (top->selfpc == selfpc) { + /* + * There it is. Increment its count, move it to the + * head of the chain. + */ + top->count++; + toindex = prevtop->link; + prevtop->link = top->link; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + } +done: + p->state = GMON_PROF_ON; + return; +overflow: + p->state = GMON_PROF_ERROR; +} diff --git a/optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.c b/optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.c new file mode 100644 index 0000000..f77d46b --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include "gprof_pta.h" + +static TEE_TASessionHandle sess = TEE_HANDLE_NULL; + +static TEE_Result invoke_gprof_pta(uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + static const TEE_UUID core_uuid = PTA_GPROF_UUID; + TEE_Result res; + + if (!sess) { + res = TEE_OpenTASession(&core_uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &sess, NULL); + if (res != TEE_SUCCESS) + return res; + } + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, + param_types, params, NULL); + return res; +} + +TEE_Result __pta_gprof_send(void *buf, size_t len, uint32_t *id) +{ + TEE_Param params[TEE_NUM_PARAMS]; + uint32_t param_types; + TEE_Result res; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + params[0].value.a = *id; + params[1].memref.buffer = buf; + params[1].memref.size = len; + res = invoke_gprof_pta(PTA_GPROF_SEND, param_types, params); + if (res == TEE_SUCCESS) + *id = params[0].value.a; + return res; +} + +TEE_Result __pta_gprof_pc_sampling_start(void *buf, size_t len, size_t offset, + size_t scale) +{ + TEE_Param params[TEE_NUM_PARAMS]; + uint32_t param_types; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + params[0].memref.buffer = buf; + params[0].memref.size = len; + params[1].value.a = offset; + params[1].value.b = scale; + return invoke_gprof_pta(PTA_GPROF_START_PC_SAMPLING, param_types, + params); +} + +TEE_Result __pta_gprof_pc_sampling_stop(uint32_t *rate) +{ + TEE_Param params[TEE_NUM_PARAMS]; + uint32_t param_types; + TEE_Result res; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + res = invoke_gprof_pta(PTA_GPROF_STOP_PC_SAMPLING, param_types, + params); + if (res != TEE_SUCCESS) + return res; + if (rate) + *rate = params[0].value.a; + return res; +} + +void __pta_gprof_fini(void) +{ + if (sess) + TEE_CloseTASession(sess); +} diff --git a/optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.h b/optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.h new file mode 100644 index 0000000..6b7bcc3 --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/gprof/gprof_pta.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __GPROF_PTA_H +#define __GPROF_PTA_H + +#include +#include +#include +#include + +TEE_Result __pta_gprof_send(void *buf, size_t len, uint32_t *id); +TEE_Result __pta_gprof_pc_sampling_start(void *buf, size_t len, size_t offset, + size_t scale); +TEE_Result __pta_gprof_pc_sampling_stop(uint32_t *rate); +void __pta_gprof_fini(void); +#endif /* __GPROF_PTA_H */ diff --git a/optee/optee_os/lib/libutee/arch/arm/gprof/sub.mk b/optee/optee_os/lib/libutee/arch/arm/gprof/sub.mk new file mode 100644 index 0000000..eacd788 --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/gprof/sub.mk @@ -0,0 +1,5 @@ +cppflags-y += -I$(sub-dir)/../../.. + +srcs-$(CFG_TA_GPROF_SUPPORT) += gprof.c +srcs-$(CFG_TA_GPROF_SUPPORT) += gprof_pta.c +cflags-remove-gprof.c-y += -Wcast-align diff --git a/optee/optee_os/lib/libutee/arch/arm/sub.mk b/optee/optee_os/lib/libutee/arch/arm/sub.mk new file mode 100644 index 0000000..7afd068 --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/sub.mk @@ -0,0 +1,9 @@ +cppflags-y += -I$(sub-dir)/../.. + +srcs-$(CFG_ARM32_$(sm)) += utee_syscalls_a32.S +srcs-$(CFG_ARM64_$(sm)) += utee_syscalls_a64.S + +ifneq ($(sm),ldelf) +subdirs-y += gprof +endif #$(sm-$(sm)-is-ld) + diff --git a/optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a32.S b/optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a32.S new file mode 100644 index 0000000..2dea83a --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a32.S @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include + + .section .note.GNU-stack,"",%progbits + + .section .text + .balign 4 + .code 32 + + .macro UTEE_SYSCALL name, scn, num_args + FUNC \name , : + push {r5-r7,lr} +UNWIND( .save {r5-r7,lr}) +#if defined(CFG_SYSCALL_WRAPPERS_MCOUNT) && !defined(__LDELF__) + .if \scn != TEE_SCN_RETURN + mov ip, sp + push {r0-r4, fp, ip} + add fp, ip, #16 + push {lr} + bl __gnu_mcount_nc + pop {r0-r4, fp, ip} + mov sp, ip + .endif +#endif + mov r7, #(\scn) + .if \num_args > TEE_SVC_MAX_ARGS + .error "Too many arguments for syscall" + .endif + .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} + END_FUNC \name + .endm + + FUNC _utee_panic, : + push {r0-r11, lr} +UNWIND( .save {r0-r11, lr}) + mov lr, pc + push {lr} +UNWIND( .save {lr}) + mov r1, sp + bl __utee_panic + /* Not reached */ + END_FUNC _utee_panic + +#include diff --git a/optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S b/optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S new file mode 100644 index 0000000..2e6e6c0 --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/arm/utee_syscalls_a64.S @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include + + .section .text + + .macro UTEE_SYSCALL name, scn, num_args + FUNC \name , : + + .if \num_args > TEE_SVC_MAX_ARGS || \num_args > 8 + .error "Too many arguments for syscall" + .endif +#if defined(CFG_SYSCALL_WRAPPERS_MCOUNT) && !defined(__LDELF__) + .if \scn != TEE_SCN_RETURN + stp x29, x30, [sp, #-80]! + mov x29, sp + stp x0, x1, [sp, #16] + stp x2, x3, [sp, #32] + stp x4, x5, [sp, #48] + stp x6, x7, [sp, #64] + mov x0, x30 + bl _mcount + ldp x0, x1, [sp, #16] + ldp x2, x3, [sp, #32] + ldp x4, x5, [sp, #48] + ldp x6, x7, [sp, #64] + ldp x29, x30, [sp], #80 + .endif +#endif + mov x8, #(\scn) + svc #0 + ret + END_FUNC \name + .endm + + FUNC _utee_panic, : + stp x29, x30, [sp, #-16]! + mov x1, sp + bl __utee_panic + /* Not reached */ + END_FUNC _utee_panic + +#include + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/lib/libutee/arch/riscv/sub.mk b/optee/optee_os/lib/libutee/arch/riscv/sub.mk new file mode 100644 index 0000000..16f776a --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/riscv/sub.mk @@ -0,0 +1,3 @@ +cppflags-y += -I$(sub-dir)/../.. + +srcs-y += utee_syscalls_rv.S diff --git a/optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S b/optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S new file mode 100644 index 0000000..8f82636 --- /dev/null +++ b/optee/optee_os/lib/libutee/arch/riscv/utee_syscalls_rv.S @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022 Beijing ESWIN Computing Technology Co., Ltd. + */ + +#include +#include + + .section .text + + .macro UTEE_SYSCALL name, scn, num_args + FUNC \name , : + + .if \num_args > TEE_SVC_MAX_ARGS || \num_args > 8 + .error "Too many arguments for syscall" + .endif + li t0, \scn + li t1, \num_args + ecall + ret + END_FUNC \name + .endm + + FUNC _utee_panic, : + j __utee_panic + END_FUNC _utee_panic + +#include diff --git a/optee/optee_os/lib/libutee/assert.c b/optee/optee_os/lib/libutee/assert.c new file mode 100644 index 0000000..022b202 --- /dev/null +++ b/optee/optee_os/lib/libutee/assert.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include + +void _assert_log(const char *expr __maybe_unused, + const char *file __maybe_unused, + const int line __maybe_unused, + const char *func __maybe_unused) +{ + EMSG_RAW("assertion '%s' failed at %s:%d in %s()", + expr, file, line, func); +} + +void __noreturn _assert_break(void) +{ + _utee_panic(TEE_ERROR_GENERIC); + /* Not reached */ + while (1) + ; +} diff --git a/optee/optee_os/lib/libutee/base64.c b/optee/optee_os/lib/libutee/base64.c new file mode 100644 index 0000000..a1eacec --- /dev/null +++ b/optee/optee_os/lib/libutee/base64.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include "base64.h" + +static const char base64_table[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +size_t _base64_enc_len(size_t size) +{ + return 4 * ((size + 2) / 3) + 1; +} + +bool _base64_enc(const void *data, size_t dlen, char *buf, size_t *blen) +{ + size_t n = 0; + size_t boffs = 0; + const unsigned char *d = data; + + n = _base64_enc_len(dlen); + 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 = 0; + + 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) +{ + bool ret = false; + size_t n = 0; + uint8_t idx = 0; + uint8_t *b = buf; + size_t m = 0; + size_t s = 0; + uint8_t byte = 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; + + switch (s) { + case 0: + byte = idx << 2; + s++; + break; + case 1: + if (b && m < *blen) + b[m] = byte | (idx >> 4); + m++; + byte = (idx & 0xf) << 4; + s++; + break; + case 2: + if (b && m < *blen) + b[m] = byte | (idx >> 2); + m++; + byte = (idx & 0x3) << 6; + s++; + break; + case 3: + if (b && m < *blen) + b[m] = byte | 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. + * We expect that each fully extracted byte is stored in output buffer. + */ + ret = (!m && !*blen) || (b && (m <= *blen)); + *blen = m; + + return ret; +} diff --git a/optee/optee_os/lib/libutee/base64.h b/optee/optee_os/lib/libutee/base64.h new file mode 100644 index 0000000..ed4ba36 --- /dev/null +++ b/optee/optee_os/lib/libutee/base64.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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); +size_t _base64_enc_len(size_t size); + +#endif /* BASE64_H */ diff --git a/optee/optee_os/lib/libutee/include/__tee_ipsocket.h b/optee/optee_os/lib/libutee/include/__tee_ipsocket.h new file mode 100644 index 0000000..c25437c --- /dev/null +++ b/optee/optee_os/lib/libutee/include/__tee_ipsocket.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#ifndef ____TEE_IPSOCKET_H +#define ____TEE_IPSOCKET_H + +typedef enum TEE_ipSocket_ipVersion_e { + TEE_IP_VERSION_DC = 0, /* don’t care */ + TEE_IP_VERSION_4 = 1, + TEE_IP_VERSION_6 = 2 +} TEE_ipSocket_ipVersion; + +#endif /*____TEE_IPSOCKET_H*/ diff --git a/optee/optee_os/lib/libutee/include/__tee_isocket_defines.h b/optee/optee_os/lib/libutee/include/__tee_isocket_defines.h new file mode 100644 index 0000000..bfb42c7 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/__tee_isocket_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ +#ifndef ____TEE_ISOCKET_DEFINES_H +#define ____TEE_ISOCKET_DEFINES_H + +#define TEE_ISOCKET_VERSION 0x01000000 + +#define TEE_ISOCKET_ERROR_PROTOCOL 0xF1007001 +#define TEE_ISOCKET_ERROR_REMOTE_CLOSED 0xF1007002 +#define TEE_ISOCKET_ERROR_TIMEOUT 0xF1007003 +#define TEE_ISOCKET_ERROR_OUT_OF_RESOURCES 0xF1007004 +#define TEE_ISOCKET_ERROR_LARGE_BUFFER 0xF1007005 +#define TEE_ISOCKET_WARNING_PROTOCOL 0xF1007006 +#define TEE_ISOCKET_ERROR_HOSTNAME 0xF1007007 + +#endif /*____TEE_ISOCKET_DEFINES_H*/ diff --git a/optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines.h b/optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines.h new file mode 100644 index 0000000..ddaf58d --- /dev/null +++ b/optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#ifndef ____TEE_TCPSOCKET_DEFINES_H +#define ____TEE_TCPSOCKET_DEFINES_H + +/* Protocol identifier */ +#define TEE_ISOCKET_PROTOCOLID_TCP 0x65 + +/* Instance specific errors */ +#define TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND 0xF1010002 + +#endif /*____TEE_TCPSOCKET_DEFINES_H*/ diff --git a/optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines_extensions.h b/optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines_extensions.h new file mode 100644 index 0000000..ca9ece0 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/__tee_tcpsocket_defines_extensions.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#ifndef ____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H +#define ____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H + +/* Instance and implementation specific ioctl functions */ +#define TEE_TCP_SET_RECVBUF 0x65f00000 +#define TEE_TCP_SET_SENDBUF 0x65f00001 + +#endif /*____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H*/ diff --git a/optee/optee_os/lib/libutee/include/__tee_udpsocket_defines.h b/optee/optee_os/lib/libutee/include/__tee_udpsocket_defines.h new file mode 100644 index 0000000..ef0b4f2 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/__tee_udpsocket_defines.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#ifndef ____TEE_UDPSOCKET_DEFINES_H +#define ____TEE_UDPSOCKET_DEFINES_H + +/* Protocol identifier */ +#define TEE_ISOCKET_PROTOCOLID_UDP 0x66 + +/* Instance specific errors */ +#define TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND 0xF1020002 + +/* Instance specific ioctl functions */ +#define TEE_UDP_CHANGEADDR 0x66000001 +#define TEE_UDP_CHANGEPORT 0x66000002 + +#endif /*____TEE_UDPSOCKET_DEFINES_H*/ diff --git a/optee/optee_os/lib/libutee/include/arm64_user_sysreg.h b/optee/optee_os/lib/libutee/include/arm64_user_sysreg.h new file mode 100644 index 0000000..3205b73 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/arm64_user_sysreg.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ +#ifndef ARM64_USER_SYSREG_H +#define ARM64_USER_SYSREG_H + +#include +#include + +/* + * Templates for register read/write functions based on mrs/msr + */ + +#define DEFINE_REG_READ_FUNC_(reg, type, asmreg) \ +static inline __noprof type read_##reg(void) \ +{ \ + uint64_t val64 = 0; \ + \ + asm volatile("mrs %0, " #asmreg : "=r" (val64)); \ + return val64; \ +} + +#define DEFINE_REG_WRITE_FUNC_(reg, type, asmreg) \ +static inline __noprof void write_##reg(type val) \ +{ \ + uint64_t val64 = val; \ + \ + asm volatile("msr " #asmreg ", %0" : : "r" (val64)); \ +} + +/* ARM Generic timer functions */ +DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0) +DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0) +DEFINE_REG_READ_FUNC_(cntvct, uint64_t, cntvct_el0) +DEFINE_REG_READ_FUNC_(tpidr_el0, uint64_t, tpidr_el0) +DEFINE_REG_WRITE_FUNC_(tpidr_el0, uint64_t, tpidr_el0) + +DEFINE_REG_READ_FUNC_(dczid_el0, uint64_t, dczid_el0) + +#endif /*ARM64_USER_SYSREG_H*/ diff --git a/optee/optee_os/lib/libutee/include/arm_user_sysreg.h b/optee/optee_os/lib/libutee/include/arm_user_sysreg.h new file mode 100644 index 0000000..974388b --- /dev/null +++ b/optee/optee_os/lib/libutee/include/arm_user_sysreg.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ +#ifndef ARM_USER_SYSREG_H +#define ARM_USER_SYSREG_H + +#include + +#ifdef ARM32 +#include +#endif + +#ifdef ARM64 +#include +#endif + +#ifndef __ASSEMBLER__ +static inline __noprof void isb(void) +{ + asm volatile ("isb"); +} + +static inline __noprof uint64_t barrier_read_counter_timer(void) +{ + isb(); +#ifdef CFG_CORE_SEL2_SPMC + return read_cntvct(); +#else + return read_cntpct(); +#endif +} +#endif + +#endif /*ARM_USER_SYSREG_H*/ diff --git a/optee/optee_os/lib/libutee/include/elf.h b/optee/optee_os/lib/libutee/include/elf.h new file mode 100644 index 0000000..b616b79 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/elf.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ +#ifndef _ELF_H_ +#define _ELF_H_ + +#if defined(ARM32) || defined(RV32) + +#include + +typedef Elf32_Addr Elf_Addr; +typedef Elf32_Half Elf_Half; +typedef Elf32_Off Elf_Off; +typedef Elf32_Sword Elf_Sword; +typedef Elf32_Word Elf_Word; +typedef Elf32_Lword Elf_Lword; +typedef Elf32_Hashelt Elf_Hashelt; +typedef Elf32_Size Elf_Size; +typedef Elf32_Ssize Elf_Ssize; +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Phdr Elf_Phdr; +typedef Elf32_Dyn Elf_Dyn; +typedef Elf32_Rel Elf_Rel; +typedef Elf32_Rela Elf_Rela; +typedef Elf32_Move Elf_Move; +typedef Elf32_Cap Elf_Cap; +typedef Elf32_Sym Elf_Sym; +typedef Elf32_Verdef Elf_Verdef; +typedef Elf32_Verdaux Elf_Verdaux; +typedef Elf32_Verneed Elf_Verneed; +typedef Elf32_Vernaux Elf_Vernaux; +typedef Elf32_Syminfo Elf_Syminfo; + +#elif defined(ARM64) || defined(RV64) + +#include + +typedef Elf64_Addr Elf_Addr; +typedef Elf64_Half Elf_Half; +typedef Elf64_Off Elf_Off; +typedef Elf64_Sword Elf_Sword; +typedef Elf64_Sxword Elf_Sxword; +typedef Elf64_Word Elf_Word; +typedef Elf64_Lword Elf_Lword; +typedef Elf64_Xword Elf_Xword; +typedef Elf64_Hashelt Elf_Hashelt; +typedef Elf64_Size Elf_Size; +typedef Elf64_Ssize Elf_Ssize; +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Phdr Elf_Phdr; +typedef Elf64_Dyn Elf_Dyn; +typedef Elf64_Rel Elf_Rel; +typedef Elf64_Rela Elf_Rela; +typedef Elf64_Move Elf_Move; +typedef Elf64_Cap Elf_Cap; +typedef Elf64_Sym Elf_Sym; +typedef Elf64_Verdef Elf_Verdef; +typedef Elf64_Verdaux Elf_Verdaux; +typedef Elf64_Verneed Elf_Verneed; +typedef Elf64_Vernaux Elf_Vernaux; +typedef Elf64_Syminfo Elf_Syminfo; + +#else +#error Unknown architecture +#endif + +#endif /* _ELF_H_ */ diff --git a/optee/optee_os/lib/libutee/include/elf32.h b/optee/optee_os/lib/libutee/include/elf32.h new file mode 100644 index 0000000..de74f6f --- /dev/null +++ b/optee/optee_os/lib/libutee/include/elf32.h @@ -0,0 +1,247 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + +#include +#include + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +typedef uint64_t Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/optee/optee_os/lib/libutee/include/elf64.h b/optee/optee_os/lib/libutee/include/elf64.h new file mode 100644 index 0000000..060819b --- /dev/null +++ b/optee/optee_os/lib/libutee/include/elf64.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + +#include +#include + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef int64_t Elf64_Sxword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Lword; +typedef uint64_t Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/optee/optee_os/lib/libutee/include/elf_common.h b/optee/optee_os/lib/libutee/include/elf_common.h new file mode 100644 index 0000000..0ac08fa --- /dev/null +++ b/optee/optee_os/lib/libutee/include/elf_common.h @@ -0,0 +1,1058 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/*- + * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +#include + +/* + * ELF definitions that are independent of architecture or word size. + */ + +#ifndef __ASSEMBLER__ +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + uint32_t n_namesz; /* Length of name. */ + uint32_t n_descsz; /* Length of descriptor. */ + uint32_t n_type; /* Type of this note. */ +} Elf_Note; + +/* + * The header for GNU-style hash sections. + */ + +typedef struct { + uint32_t gh_nbuckets; /* Number of hash buckets. */ + uint32_t gh_symndx; /* First visible symbol in .dynsym. */ + uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ + uint32_t gh_shift2; /* Bloom filter shift count. */ +} Elf_GNU_Hash_Header; + +/* + * Program Property Array + */ +typedef struct { + uint32_t pr_type; + uint32_t pr_datasz; +} Elf_Prop; +#endif /*__ASSEMBLER__*/ + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_PDSP 63 /* Sony DSP Processor. */ +#define EM_FX66 66 /* Siemens FX66 microcontroller. */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 + microcontroller. */ +#define EM_ST7 68 /* STmicroelectronics ST7 8-bit + microcontroller. */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */ +#define EM_SVX 73 /* Silicon Graphics SVx. */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */ +#define EM_VAX 75 /* Digital VAX. */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded + processor. */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded + processor. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University machine-independent + object files. */ +#define EM_PRISM 82 /* SiTera Prism. */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */ +#define EM_FR30 84 /* Fujitsu FR30. */ +#define EM_D10V 85 /* Mitsubishi D10V. */ +#define EM_D30V 86 /* Mitsubishi D30V. */ +#define EM_V850 87 /* NEC v850. */ +#define EM_M32R 88 /* Mitsubishi M32R. */ +#define EM_MN10300 89 /* Matsushita MN10300. */ +#define EM_MN10200 90 /* Matsushita MN10200. */ +#define EM_PJ 91 /* picoJava. */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose + Processor. */ +#define EM_NS32K 97 /* National Semiconductor 32000 series. */ +#define EM_TPC 98 /* Tenor Network TPC processor. */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */ +#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */ +#define EM_MAX 102 /* MAX Processor. */ +#define EM_CR 103 /* National Semiconductor CompactRISC + microprocessor. */ +#define EM_F2MC16 104 /* Fujitsu F2MC16. */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller + msp430. */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */ +#define EM_SEP 108 /* Sharp embedded microprocessor. */ +#define EM_ARCA 109 /* Arca RISC Microprocessor. */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. + and MPRC of Peking University */ +#define EM_AARCH64 183 /* AArch64 (64-bit ARM) */ +#define EM_RISCV 243 /* RISC-V */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* e_flags for EM_ARM */ +#define EF_ARM_ABI_VERSION 0x05000000 /* ABI version 5 */ +#define EF_ARM_ABIMASK 0xFF000000 +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_ABI_FLOAT_HARD 0x00000400 /* ABI version 5 and later */ +#define EF_ARM_ABI_FLOAT_SOFT 0x00000200 /* ABI version 5 and later */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking + pre-emption map. */ +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility + attributes. */ +#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ +#define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ +#define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 +#define PT_GNU_RELRO 0x6474e552 +#define PT_GNU_PROPERTY 0x6474e553 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + termination functions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', odd == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ +#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ +#define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ +#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ + +/* Note section names */ +#define ELF_NOTE_FREEBSD "FreeBSD" +#define ELF_NOTE_NETBSD "NetBSD" +#define ELF_NOTE_SOLARIS "SUNW Solaris" +#define ELF_NOTE_GNU "GNU" + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ +#define NT_THRMISC 7 /* Thread miscellaneous info. */ +#define NT_PROCSTAT_PROC 8 /* Procstat proc data. */ +#define NT_PROCSTAT_FILES 9 /* Procstat files data. */ +#define NT_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */ +#define NT_PROCSTAT_GROUPS 11 /* Procstat groups data. */ +#define NT_PROCSTAT_UMASK 12 /* Procstat umask data. */ +#define NT_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */ +#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */ +#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */ +#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */ + +/* GNU note types. */ +#define NT_GNU_ABI_TAG 1 +#define NT_GNU_HWCAP 2 +#define NT_GNU_BUILD_ID 3 +#define NT_GNU_GOLD_VERSION 4 +#define NT_GNU_PROPERTY_TYPE_0 5 + +#define GNU_PROPERTY_LOPROC 0xc0000000 +#define GNU_PROPERTY_HIPROC 0xdfffffff + +#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 + +#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 0x00000001 +#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 0x00000002 + +#define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_GNU_IFUNC 10 +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ +#define STV_EXPORTED 0x4 +#define STV_SINGLETON 0x5 +#define STV_ELIMINATE 0x6 + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ +#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */ + +#define R_RISCV_NONE 0 /* No relocation. */ +#define R_RISCV_64 2 /* 64-bit relocation. */ +#define R_RISCV_RELATIVE 3 /* Adjust a link address (A) to its + load address (B + A). */ +#define R_RISCV_JUMP_SLOT 5 /* Indicates the symbol associated + with a PLT entry. */ + +#define R_AARCH64_NONE 0 /* No relocation. */ +#define R_AARCH64_ABS64 257 +#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address. */ +#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address. */ +#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object. */ +#define R_AARCH64_TLS_TPREL 1030 /* Offset of the TLS block in the TCB */ +#define R_AARCH64_TLSDESC 1031 /* TLS descriptor to be filled */ + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +/* TLS relocations */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +#define R_MIPS_64 18 /* Direct 64 bit */ +#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ +#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * 64-bit relocations + */ +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL64 78 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +#define R_X86_64_IRELATIVE 37 + + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/optee/optee_os/lib/libutee/include/k3/otp_keywriting_ta.h b/optee/optee_os/lib/libutee/include/k3/otp_keywriting_ta.h new file mode 100644 index 0000000..85b5863 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/k3/otp_keywriting_ta.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Texas Instruments System Control Interface Driver + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * Manorit Chawdhry + */ + +#ifndef __K3_OTP_KEYWRITING_TA_H__ +#define __K3_OTP_KEYWRITING_TA_H__ + +/* UUID of the trusted application */ +#define PTA_K3_OTP_KEYWRITING_UUID \ + { 0xacc50f40, 0x0613, 0x4abd, \ + { 0x8d, 0xfe, 0xa9, 0x64, 0xcb, 0x74, 0xeb, 0x69} } + +#define PTA_K3_OTP_KEYWRITING_NAME "pta_k3_otp.ta" + +/* + * TA_OTP_KEYWRITING_CMD_READ_MMR - Read an extended OTP bit + * param[0] (value/input) 32-bit MMR index + * param[1] (value/output) OTP value written in efuse + * param[2] unused + * param[3] unused + */ +#define TA_OTP_KEYWRITING_CMD_READ_MMR 0 + +/* + * TA_OTP_KEYWRITING_CMD_WRITE_ROW - Write into extended OTP row + * param[0] (value/input) Row index + * param[1].a (value/input) Value to be written + * param[1].b (value/input) Mask for the value + * param[2] unused + * param[3] unused + */ +#define TA_OTP_KEYWRITING_CMD_WRITE_ROW 1 + +/* + * TA_OTP_KEYWRITING_CMD_LOCK_ROW - Lock an extended OTP row + * param[0].a (value/input) Row index + * param[0].b (value/input) + * BIT(0) - soft_lock + * BIT(1) - hw_read_lock + * BIT(2) - hw_write_lock + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define TA_OTP_KEYWRITING_CMD_LOCK_ROW 2 + +#define K3_OTP_KEYWRITING_SOFT_LOCK BIT(0) +#define K3_OTP_KEYWRITING_HW_READ_LOCK BIT(1) +#define K3_OTP_KEYWRITING_HW_WRITE_LOCK BIT(2) + +#endif /* __K3_OTP_KEYWRITING_TA_H__ */ diff --git a/optee/optee_os/lib/libutee/include/link.h b/optee/optee_os/lib/libutee/include/link.h new file mode 100644 index 0000000..88d4eec --- /dev/null +++ b/optee/optee_os/lib/libutee/include/link.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2012 The Android Open Source Project + */ + +#ifndef _LINK_H_ +#define _LINK_H_ + +#include +#include + +struct dl_phdr_info { + Elf_Addr dlpi_addr; /* module relocation base */ + const char *dlpi_name; /* module name */ + const Elf_Phdr *dlpi_phdr; /* pointer to module's phdr */ + Elf_Half dlpi_phnum; /* number of entries in phdr */ + unsigned long long dlpi_adds; /* total # of loads */ + unsigned long long dlpi_subs; /* total # of unloads */ + size_t dlpi_tls_modid; + void *dlpi_tls_data; +}; + +int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *info, size_t size, + void *data), + void *data); + +#endif /* _LINK_H_ */ diff --git a/optee/optee_os/lib/libutee/include/pta_apdu.h b/optee/optee_os/lib/libutee/include/pta_apdu.h new file mode 100644 index 0000000..8fed78f --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_apdu.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (C) 2021, Foundries Limited + * Author: Jorge Ramirez + */ + +#ifndef __PTA_APDU_H +#define __PTA_APDU_H + +#define PTA_APDU_UUID { 0x3f3eb880, 0x3639, 0x11ec, \ + { 0x9b, 0x9d, 0x0f, 0x3f, 0xc9, 0x46, 0x8f, 0x50 } } + +/* + * ADPU based communication with the Secure Element + * + * [in] value[0].a Use APDU TXRX hints: PTA_APDU_TXRX_CASE_* + * [in] memref[1].buffer APDU header. + * [in] memref[1].size APDU header length. + * [in] memref[2].buffer request (APDU raw frame). + * [in] memref[2].size request length. + * [out] memref[3].buffer response (APDU raw frame). + * [out] memref[3].size response length. + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_NOT_IMPLEMENTED - Invoke command not implemented + * TEE_ERROR_GENERIC - Invoke command failure + */ +#define PTA_CMD_TXRX_APDU_RAW_FRAME 0 + +/* + * Type identifier for the APDU message as described by Smart Card Standard + * ISO7816-4 about ADPU message bodies decoding convention: + * + * https://cardwerk.com/smart-card-standard-iso7816-4-section-5-basic-organizations/#chap5_3_2 + */ +#define PTA_APDU_TXRX_CASE_NO_HINT 0 +#define PTA_APDU_TXRX_CASE_1 1 +#define PTA_APDU_TXRX_CASE_2 2 +#define PTA_APDU_TXRX_CASE_2E 3 +#define PTA_APDU_TXRX_CASE_3 4 +#define PTA_APDU_TXRX_CASE_3E 5 +#define PTA_APDU_TXRX_CASE_4 6 +#define PTA_APDU_TXRX_CASE_4E 7 + +#endif /* __PTA_APDU_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_attestation.h b/optee/optee_os/lib/libutee/include/pta_attestation.h new file mode 100644 index 0000000..76a1d3a --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_attestation.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2021, Huawei Technologies Co., Ltd + */ + +/* + * Provide remote attestation services + */ + +#ifndef __PTA_ATTESTATION_H +#define __PTA_ATTESTATION_H + +#define PTA_ATTESTATION_UUID { 0x39800861, 0x182a, 0x4720, \ + { 0x9b, 0x67, 0x2b, 0xcd, 0x62, 0x2b, 0xc0, 0xb5 } } + +/* + * Get the RSA public key that should be used to verify the values returned by + * other commands. + * + * [out] memref[0] Public key exponent in big endian order + * [out] memref[1] Modulus in big endian order + * [out] value[2] Signature algorithm used by other commands. + * Currently always + * TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256. + * + * Return codes: + * TEE_SUCCESS + * TEE_ERROR_GENERIC - Internal error + * TEE_ERROR_SHORT_BUFFER - One or both buffers are too small, required size + * is provided in memref[i].size + */ +#define PTA_ATTESTATION_GET_PUBKEY 0x0 + +/* + * Return the digest found in the header of a Trusted Application binary or a + * Trusted Shared library + * + * [in] memref[0] UUID of the TA or shared library + * [in] memref[1] Nonce (random non-NULL, non-empty buffer of any + * size to prevent replay attacks) + * [out] memref[2] Output buffer. Receives the signed digest. + * - The first 32 bytes are the digest itself (from + * the TA signed header: struct shdr::hash) + * - The following bytes are a signature: + * SIG(SHA256(Nonce | digest)) + * - The algorithm is + * TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 with a salt + * length of 32. + * - The key pair is generated internally and stored + * in secure storage. The public key can be + * retrieved with command PTA_ATTESTATION_GET_PUBKEY + * (typically during device provisioning). + * Given that the sigature length is equal to the + * RSA modulus size in bytes, the output buffer size + * should be at least (digest size + modulus size) + * bytes. For example, for a 32-byte SHA256 digest and + * 2048 bit key (256 bytes) the minimum buffer size is + * 288 bytes. + * + * Return codes: + * TEE_SUCCESS + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required + */ +#define PTA_ATTESTATION_GET_TA_SHDR_DIGEST 0x1 + +/* + * Return a signed hash for a running user space TA, which must be the caller + * of this PTA. It is a runtime measurement of the memory pages that contain + * immutable data (code and read-only data). + * + * [in] memref[0] Nonce + * [out] memref[1] SHA256 hash of the TA memory followed by a + * signature. See PTA_ATTESTATION_GET_TA_HDR_DIGEST + * for a description of the signature. + * + * Return codes: + * TEE_SUCCESS + * TEE_ERROR_ACCESS_DENIED - Caller is not a user space TA + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required + */ +#define PTA_ATTESTATION_HASH_TA_MEMORY 0x2 + +/* + * Return a signed hash of the TEE OS (kernel) memory. It is a runtime + * measurement of the memory pages that contain immutable data (code and + * read-only data). + * + * [in] memref[0] Nonce + * [out] memref[1] SHA256 hash of the TEE memory followed by a + * signature. See PTA_ATTESTATION_GET_TA_HDR_DIGEST + * for a description of the signature. + * + * Return codes: + * TEE_SUCCESS + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required + */ +#define PTA_ATTESTATION_HASH_TEE_MEMORY 0x3 + +#endif /* __PTA_ATTESTATION_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_benchmark.h b/optee/optee_os/lib/libutee/include/pta_benchmark.h new file mode 100644 index 0000000..2b6f157 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_benchmark.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __PTA_BENCHMARK_H +#define __PTA_BENCHMARK_H + +/* + * Interface to the benchmark pseudo-TA, which is used for registering + * timestamp buffers + */ + +#define BENCHMARK_UUID \ + { 0x0b9a63b0, 0xb4c6, 0x4c85, \ + { 0xa2, 0x84, 0xa2, 0x28, 0xef, 0x54, 0x7b, 0x4e } } + +/* + * Benchmark PTA supported commands + */ +#define BENCHMARK_CMD(id) (0xFA190000 | ((id) & 0xFFFF)) +#define BENCHMARK_CMD_ALLOCATE_BUF BENCHMARK_CMD(1) +#define BENCHMARK_CMD_GET_MEMREF BENCHMARK_CMD(2) +#define BENCHMARK_CMD_UNREGISTER BENCHMARK_CMD(3) + +#endif /* __PTA_BENCHMARK_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_device.h b/optee/optee_os/lib/libutee/include/pta_device.h new file mode 100644 index 0000000..2cd2bcd --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_device.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019, Linaro Limited + */ + +/* + * Enumerate the pseudo TAs that have the TA_FLAG_DEVICE_ENUM flag enabled. + */ + +#ifndef __PTA_DEVICE_H +#define __PTA_DEVICE_H + +#define PTA_DEVICE_UUID { 0x7011a688, 0xddde, 0x4053, \ + { 0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8 } } + +/* + * Get device UUIDs + * + * [out] memref[0] Array of device UUIDs + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required + */ +#define PTA_CMD_GET_DEVICES 0x0 /* before tee-supplicant run */ +#define PTA_CMD_GET_DEVICES_SUPP 0x1 /* after tee-supplicant run */ + +#endif /* __PTA_DEVICE_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_gprof.h b/optee/optee_os/lib/libutee/include/pta_gprof.h new file mode 100644 index 0000000..60e9c8f --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_gprof.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __PTA_GPROF_H +#define __PTA_GPROF_H + +/* + * Interface to the gprof pseudo-TA, which is used by libutee to control TA + * profiling and forward data to tee-supplicant. + */ + +#define PTA_GPROF_UUID { 0x2f6e0d48, 0xc574, 0x426d, { \ + 0x82, 0x4e, 0x40, 0x19, 0x8c, 0xde, 0x5c, 0xac } } + +/* + * Send TA profiling data (gmon.out format) to tee-supplicant + * Data may be sent in several chunks: first set id to 0, then re-use the + * allocated value in subsequent calls. + * + * [in/out] value[0].a: id + * [in] memref[1]: profiling data + */ +#define PTA_GPROF_SEND 0 + +/* + * Start PC sampling of a user TA session + * + * [in/out] memref[0]: sampling buffer + * [in] value[1].a: offset: the lowest PC value in the TA + * [in] value[1].b: scale: histogram scaling factor + */ +#define PTA_GPROF_START_PC_SAMPLING 1 + +/* + * Stop PC sampling of a user TA session and retrieve data + * + * [out] value[0].a: sampling frequency + */ +#define PTA_GPROF_STOP_PC_SAMPLING 2 + +#endif /* __PTA_GPROF_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_imx_digprog.h b/optee/optee_os/lib/libutee/include/pta_imx_digprog.h new file mode 100644 index 0000000..bb00400 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_imx_digprog.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + */ +#ifndef __PTA_IMX_DIGPROG_H__ +#define __PTA_IMX_DIGPROG_H__ + +#define PTA_DIGPROG_UUID { 0xbfdbe409, 0x3302, 0x4abf, \ + { 0x99, 0xbc, 0x5f, 0x62, 0x32, 0x26, 0xa7, 0x39 } } + +#endif /* __PTA_IMX_DIGPROG_H__ */ diff --git a/optee/optee_os/lib/libutee/include/pta_imx_manufacturing_protection.h b/optee/optee_os/lib/libutee/include/pta_imx_manufacturing_protection.h new file mode 100644 index 0000000..fe4c274 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_imx_manufacturing_protection.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2018-2019, 2023 NXP + */ +#ifndef PTA_IMX_MANUFACTURING_PROTECTION_H +#define PTA_IMX_MANUFACTURING_PROTECTION_H + +#define PTA_MANUFACT_PROTEC_UUID { 0x83268b7c, 0x85e3, 0x11e8, \ + { 0xad, 0xc0, 0xfa, 0x7a, 0xe0, 0x1b, 0xbe, 0xbc} } + +/* + * Sign the given message with the manufacturing protection private key + * + * [in] memref[0].buffer Message buffer + * [in] memref[0].size Message size + * [out] memref[1].buffer Signature buffer + * [out] memref[1].size Signature size + * [out] memref[2].buffer MPMR buffer + * [out] memref[2].size MPMR size + */ +#define PTA_IMX_MP_CMD_SIGNATURE_MPMR 0 + +/* + * Get the manufacturing protection public key + * + * [out] memref[0].buffer Public key buffer + * [out] memref[0].size Public key size + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define PTA_IMX_MP_CMD_GET_PUBLIC_KEY 1 + +#endif /* PTA_IMX_MANUFACTURING_PROTECTION_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_imx_ocotp.h b/optee/optee_os/lib/libutee/include/pta_imx_ocotp.h new file mode 100644 index 0000000..d54e2e8 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_imx_ocotp.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2021 NXP + */ +#ifndef __PTA_IMX_OCOTP_H__ +#define __PTA_IMX_OCOTP_H__ + +#define PTA_OCOTP_UUID { 0x9abdf255, 0xd8fa, 0x40de, \ + { 0x8f, 0x60, 0x4d, 0x0b, 0x27, 0x92, 0x7b, 0x7d } } + +/** + * Read chip UID + * + * [out] memref[0].buffer Output buffer to store UID + * [out] memref[0].size Size of the UID (64 bits) + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input parameter + * TEE_ERROR_GENERIC - UID not available + */ +#define PTA_OCOTP_CMD_CHIP_UID 0 + +/* + * Read chip OTP fuse + * + * [in] params[0].value.a Fuse bank number + * [in] params[0].value.b Fuse word number + * [out] params[1].value.a Fuse value + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input parameter + * TEE_ERROR_BUSY - OCOTP not available + */ +#define PTA_OCOTP_CMD_READ_FUSE 1 +#endif /* __PTA_IMX_OCOTP_H__ */ diff --git a/optee/optee_os/lib/libutee/include/pta_invoke_tests.h b/optee/optee_os/lib/libutee/include/pta_invoke_tests.h new file mode 100644 index 0000000..79cd989 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_invoke_tests.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __PTA_INVOKE_TESTS_H +#define __PTA_INVOKE_TESTS_H + +#define PTA_INVOKE_TESTS_UUID \ + { 0xd96a5b40, 0xc3e5, 0x21e3, \ + { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } + +/* Trace some hello string. Parameters are not used/checked. */ +#define PTA_INVOKE_TESTS_CMD_TRACE 0 + +/* + * Types of parameter drives the test sequences: + * - test on value parameters + * - test on SHM memory reference parameters + * - test on SDP memory reference parameters + */ +#define PTA_INVOKE_TESTS_CMD_PARAMS 1 + +/* Run some core internal tests. Parameters are not used/checked. */ +#define PTA_INVOKE_TESTS_CMD_SELF_TESTS 2 + +/* + * Secure data path: check that PTA can copy data from non-secure shared memory + * to SDP secure memory + * + * [in] memref[0] source (non-secure shared memory) + * [out] memref[1] destination (SDP secure memory) + */ +#define PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC 3 + +/* + * Secure data path: check that PTA can read data from SDP secure memory and + * write it back. Data are processed so that client check the expected + * read/write sequence succeed. + * + * [in/out] memref[0] SDP secure buffer to read from and write to + */ +#define PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC 4 + +/* + * Secure data path: check that PTA can copy data from SDP secure memory to + * non-secure shared memory + * + * [in] memref[0] source (SDP secure memory) + * [out] memref[1] destination (non-secure shared memory) + */ +#define PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC 5 + +/* + * Tests FS hash-tree corner cases in error handling + */ +#define PTA_INVOKE_TESTS_CMD_FS_HTREE 6 + +/* + * Tests mutex + * + * [in] value[0].a Test function PTA_MUTEX_TEST_* + * [in] value[0].b delay number + * [out] value[1].a before lock concurency + * [out] value[1].b during lock concurency + */ +#define PTA_MUTEX_TEST_WRITER 0 +#define PTA_MUTEX_TEST_READER 1 +#define PTA_INVOKE_TESTS_CMD_MUTEX 7 + +/* + * Tests lock dependency checking algorithm + */ +#define PTA_INVOKE_TESTS_CMD_LOCKDEP 8 + +/* + * These values should match the ones in + * optee_test/ta/aes_perf/include/ta_aes_perf.h + */ +#define PTA_INVOKE_TESTS_AES_ECB 0 +#define PTA_INVOKE_TESTS_AES_CBC 1 +#define PTA_INVOKE_TESTS_AES_CTR 2 +#define PTA_INVOKE_TESTS_AES_XTS 3 +#define PTA_INVOKE_TESTS_AES_GCM 4 + +/* + * AES performance tests + * + * [in] value[0].a Top 16 bits Decrypt, low 16 bits key size in bits + * [in] value[0].b AES mode, one of + * PTA_INVOKE_TESTS_AES_{ECB_NOPAD,CBC_NOPAD,CTR,XTS,GCM} + * [in] value[1].a repetition count + * [in] value[1].b unit size + * [in] memref[2] In buffer + * [in] memref[3] Out buffer + */ +#define PTA_INVOKE_TEST_CMD_AES_PERF 9 + +/* + * NULL memory reference parameter + * + * [in/out] memref[0] NULL memory reference of size zero + */ +#define PTA_INVOKE_TESTS_CMD_MEMREF_NULL 10 + +/* + * Retrieve results of the dt_driver framework internal test + */ +#define PTA_INVOKE_TESTS_CMD_DT_DRIVER_TESTS 11 + +#endif /*__PTA_INVOKE_TESTS_H*/ + diff --git a/optee/optee_os/lib/libutee/include/pta_jetson_user_key.h b/optee/optee_os/lib/libutee/include/pta_jetson_user_key.h new file mode 100644 index 0000000..fe5d09c --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_jetson_user_key.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021-2023, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef __JETSON_USER_KEY_PTA_H__ +#define __JETSON_USER_KEY_PTA_H__ + +/* + * Each trusted app UUID should have a unique UUID that is + * generated from a UUID generator such as + * https://www.uuidgenerator.net/ + * + * UUID : {e9e156e8-e161-4c8a-91a9-0bba5e247ee8} + */ +#define JETSON_USER_KEY_UUID \ + { 0xe9e156e8, 0xe161, 0x4c8a, \ + {0x91, 0xa9, 0x0b, 0xba, 0x5e, 0x24, 0x7e, 0xe8} } + +/* + * JETSON_USER_KEY_CMD_GET_EKB_KEY - Query the EKB key + * param[0] in (value) a: EKB key index + * param[1] out (memref) key buffer, key size + * param[2] unused + * param[3] unused + */ +#define JETSON_USER_KEY_CMD_GET_EKB_KEY 0 + +/* + * EKB user symmetric keys. + */ +typedef enum { + EKB_USER_KEY_KERNEL_ENCRYPTION = 1, + EKB_USER_KEY_DISK_ENCRYPTION, + EKB_USER_KEY_UEFI_PV_PUBLIC_KEY, + EKB_USER_KEY_UEFI_ENCRYPTION, + EKB_USER_KEY_DEVICE_ID_CERT, +} ekb_key_index_t; + +/* + * JETSON_USER_KEY_CMD_GET_RANDOM - Get random bytes from RNG + * param[0] out (memref) RNG data, RNG size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define JETSON_USER_KEY_CMD_GET_RANDOM 1 + +/* + * JETSON_USER_KEY_CMD_GEN_UNIQUE_KEY_BY_EKB - Generate a unique key by EKB key + * param[0] in (value) a: EKB key index + * param[1] in (memref) label string, length + * param[2] out (memref) key, size + * param[3] unused + */ +#define JETSON_USER_KEY_CMD_GEN_UNIQUE_KEY_BY_EKB 2 + +/* + * JETSON_USER_KEY_CMD_GEN_KEY - Generate a key by a input key + * param[0] in (memref) input key, size + * param[1] in (memref) context string, length + * param[2] in (memref) label string, length + * param[3] out (memref) output key, size + */ +#define JETSON_USER_KEY_CMD_GEN_KEY 3 + +#define LUKS_SRV_FLAG (1U << 0) +#define PTA_SRV_FLAG (1U << 31) + +/* + * JETSON_USER_KEY_CMD_GET_FLAG - Get the service flag + * param[0] in (value) a: flag + * param[1] out (value) a: flag status + * param[2] unused + * param[3] unused + */ +#define JETSON_USER_KEY_CMD_GET_FLAG 4 + +/* + * JETSON_USER_KEY_CMD_SET_FLAG - Set the service flag + * param[0] in (value) a: flag, b: flag status + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define JETSON_USER_KEY_CMD_SET_FLAG 5 + +/* + * JETSON_USER_KEY_CMD_IS_KEY_EXISTS - Check if key is exists + * param[0] in (value), A: key type + * param[1] out (value), A: indicates if key is exists + * param[2] unused + * param[3] unused + */ +#define JETSON_USER_KEY_CMD_IS_KEY_EXISTS 6 + +/* + * JETSON_USER_KEY_CMD_DECRYPT_CPUBL_PAYLOAD - Decrypt CPUBL payload(Kernel/Kernel-dtb) + * param[0] inout (memref): encrypt/decrypt image&size + * param[1] input (value): A: decryption phase: init/update/final + * param[2] unused + * param[3] unused + */ +#define JETSON_USER_KEY_CMD_DECRYPT_CPUBL_PAYLOAD 7 + +#endif diff --git a/optee/optee_os/lib/libutee/include/pta_rng.h b/optee/optee_os/lib/libutee/include/pta_rng.h new file mode 100644 index 0000000..5f9264c --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_rng.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2018, Linaro Limited + */ + +#ifndef __PTA_RNG_H +#define __PTA_RNG_H + +#define PTA_RNG_UUID { 0xab7a617c, 0xb8e7, 0x4d8f, \ + { 0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64 } } + +#define TEE_ERROR_HEALTH_TEST_FAIL 0x00000001 + +/* + * PTA_CMD_GET_ENTROPY - Get Entropy from RNG using Thermal Sensor + * + * [in/out] memref[0] - Entropy buffer memory reference + * param[1] unused + * param[2] unused + * param[3] unused + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_NOT_SUPPORTED - Requested entropy size greater than size of pool + * TEE_ERROR_HEALTH_TEST_FAIL - Continuous health testing failed + */ +#define PTA_CMD_GET_ENTROPY 0x0 + +/* + * PTA_CMD_GET_RNG_INFO - Get RNG information + * + * [out] value[0].a - RNG data-rate in bytes per second + * [out] value[0].b - Quality/Entropy per 1024 bit of data + * param[1] unused + * param[2] unused + * param[3] unused + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define PTA_CMD_GET_RNG_INFO 0x1 + +#endif /* __PTA_RNG_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_rtc.h b/optee/optee_os/lib/libutee/include/pta_rtc.h new file mode 100644 index 0000000..ae14c2e --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_rtc.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022, Microchip + */ +#ifndef __PTA_RTC_H +#define __PTA_RTC_H + +#include + +#define PTA_RTC_UUID { 0xf389f8c8, 0x845f, 0x496c, \ + { 0x8b, 0xbe, 0xd6, 0x4b, 0xd2, 0x4c, 0x92, 0xfd } } + +#define PTA_RTC_INFO_VERSION 0x1 + +/* + * RTC provides set/get offset and thus command PTA_CMD_RTC_GET_OFFSET and + * PTA_CMD_RTC_SET_OFFSET might be called + */ +#define PTA_RTC_FEATURE_CORRECTION BIT(0) + +struct pta_rtc_time { + uint32_t tm_sec; + uint32_t tm_min; + uint32_t tm_hour; + uint32_t tm_mday; + uint32_t tm_mon; + uint32_t tm_year; + uint32_t tm_wday; +}; + +/* + * struct pta_rtc_info - RTC service information + * @version - 1st 64bit cell, version of the structure: PTA_RTC_INFO_VERSION + * @features - 64bit flag mask related to PTA_RTC_FEATURE_* + * @range_min - Minima time reference the RTC can be programmed to + * @range_max - Maxima time reference the RTC can reach + */ +struct pta_rtc_info { + uint64_t version; + uint64_t features; + struct pta_rtc_time range_min; + struct pta_rtc_time range_max; +}; + +/* + * PTA_CMD_RTC_GET_INFO - Get RTC information + * + * [out] memref[0] RTC buffer memory reference containing a struct + * pta_rtc_info + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define PTA_CMD_RTC_GET_INFO 0x0 + +/* + * PTA_CMD_RTC_GET_TIME - Get time from RTC + * + * [out] memref[0] RTC buffer memory reference containing a struct + * pta_rtc_time + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define PTA_CMD_RTC_GET_TIME 0x1 + +/* + * PTA_CMD_RTC_SET_TIME - Set time from RTC + * + * [in] memref[0] RTC buffer memory reference containing a struct + * pta_rtc_time to be used as RTC time + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define PTA_CMD_RTC_SET_TIME 0x2 + +/* + * PTA_CMD_RTC_GET_OFFSET - Get RTC offset + * + * [out] value[0].a RTC offset (signed 32bit value) + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define PTA_CMD_RTC_GET_OFFSET 0x3 + +/* + * PTA_CMD_RTC_SET_OFFSET - Set RTC offset + * + * [in] value[0].a RTC offset to be set (signed 32bit value) + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define PTA_CMD_RTC_SET_OFFSET 0x4 + +#endif /* __PTA_RTC_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_scmi_client.h b/optee/optee_os/lib/libutee/include/pta_scmi_client.h new file mode 100644 index 0000000..3e7b931 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_scmi_client.h @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019-2021, Linaro Limited + */ +#ifndef PTA_SCMI_CLIENT_H +#define PTA_SCMI_CLIENT_H + +#define PTA_SCMI_UUID { 0xa8cfe406, 0xd4f5, 0x4a2e, \ + { 0x9f, 0x8d, 0xa2, 0x5d, 0xc7, 0x54, 0xc0, 0x99 } } + +#define PTA_SCMI_NAME "PTA-SCMI" + +/* + * PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities + * + * [out] value[0].a: Capabilities bit mask (PTA_SCMI_CAPS_*) + * [out] value[0].b: Extended capabilities or 0 + */ +#define PTA_SCMI_CMD_CAPABILITIES 0 + +/* + * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL - Process SCMI message in SMT buffer + * + * [in] value[0].a: Channel handle + * + * Shared memory used for SCMI message/response exhange is expected + * already identified and bound to channel handle in both SCMI agent + * and SCMI server (OP-TEE) parts. + * The memory uses SMT header to carry SCMI meta-data (protocol ID and + * protocol message ID). + */ +#define PTA_SCMI_CMD_PROCESS_SMT_CHANNEL 1 + +/* + * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE - Process SCMI message in + * SMT buffer pointed by memref parameters + * + * [in] value[0].a: Channel handle + * [in/out] memref[1]: Message/response buffer (SMT and SCMI payload) + * + * Shared memory used for SCMI message/response is a SMT buffer + * referenced by param[1]. It shall be 128 bytes large to fit response + * payload whatever message playload size. + * The memory uses SMT header to carry SCMI meta-data (protocol ID and + * protocol message ID). + */ +#define PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE 2 + +/* + * PTA_SCMI_CMD_GET_CHANNEL_HANDLE - Get handle for an SCMI channel + * + * Get a handle for the SCMI channel. This handle value is to be passed + * as argument to some commands as PTA_SCMI_CMD_PROCESS_*. + * + * [in] value[0].a: Channel identifier or 0 if no assigned ID + * [in] value[0].b: Requested capabilities mask (PTA_SCMI_CAPS_*) + * [out] value[0].a: Returned channel handle + */ +#define PTA_SCMI_CMD_GET_CHANNEL_HANDLE 3 + +/* + * PTA_SCMI_CMD_PROCESS_MSG_CHANNEL - Process SCMI message in a MSG + * buffer pointed by memref parameters + * + * [in] value[0].a: Channel handle + * [in] memref[1]: Input message shared buffer + * [out] memref[2]: Output message shared buffer + */ +#define PTA_SCMI_CMD_PROCESS_MSG_CHANNEL 4 + +/* + * Capabilities + */ + +/* Channel supports shared memory using the SMT header protocol */ +#define PTA_SCMI_CAPS_SMT_HEADER BIT32(0) + +/* Channel supports shared memory using the MSG header protocol */ +#define PTA_SCMI_CAPS_MSG_HEADER BIT32(1) + +/* Mask of defined capabilities */ +#define PTA_SCMI_CAPS_MASK GENMASK_32(1, 0) + +#endif /* SCMI_PTA_SCMI_CLIENT_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_scp03.h b/optee/optee_os/lib/libutee/include/pta_scp03.h new file mode 100644 index 0000000..393ca56 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_scp03.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (C) 2020, Foundries Limited + */ + +#ifndef __PTA_SCP03_H +#define __PTA_SCP03_H + +#define PTA_SCP03_UUID { 0xbe0e5821, 0xe718, 0x4f77, \ + { 0xab, 0x3e, 0x8e, 0x6c, 0x73, 0xa9, 0xc7, 0x35 } } + +/* + * Enable SCP03 support on the SE + * + * [in] value[0].a Use session keys PTA_SCP03_SESSION_* + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_NOT_IMPLEMENTED - Invoke command not implemented + * TEE_ERROR_GENERIC - Invoke command failure + */ +#define PTA_CMD_ENABLE_SCP03 0 + +/* Enable the session using the current keys in the Secure Element */ +#define PTA_SCP03_SESSION_CURRENT_KEYS 0 + +/* Enable the session after replacing the current keys in the Secure Element */ +#define PTA_SCP03_SESSION_ROTATE_KEYS 1 + +#endif /* __PTA_SCP03_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_secstor_ta_mgmt.h b/optee/optee_os/lib/libutee/include/pta_secstor_ta_mgmt.h new file mode 100644 index 0000000..47c74b0 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_secstor_ta_mgmt.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + */ + +#ifndef __PTA_SECSTOR_TA_MGMT_H +#define __PTA_SECSTOR_TA_MGMT_H + +/* + * Bootstrap (install initial) Trusted Application or Secure Domain into + * secure storage from a signed binary. + * + * [in] memref[0]: signed binary + */ +#define PTA_SECSTOR_TA_MGMT_BOOTSTRAP 0 + +#define PTA_SECSTOR_TA_MGMT_UUID { 0x6e256cba, 0xfc4d, 0x4941, { \ + 0xad, 0x09, 0x2c, 0xa1, 0x86, 0x03, 0x42, \ + 0xdd } } + +#endif /*__PTA_SECSTOR_TA_MGMT_H*/ diff --git a/optee/optee_os/lib/libutee/include/pta_socket.h b/optee/optee_os/lib/libutee/include/pta_socket.h new file mode 100644 index 0000000..ad5f7d7 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_socket.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __PTA_SOCKET +#define __PTA_SOCKET + +#define PTA_SOCKET_UUID { 0x3b996a7d, 0x2c2b, 0x4a49, { \ + 0xa8, 0x96, 0xe1, 0xfb, 0x57, 0x66, 0xd2, 0xf4 } } + +/* + * [in] value[0].a ip version TEE_IP_VERSION_* from tee_ipsocket.h + * [in] value[0].b server port number + * [in] memref[1] server address + * [in] value[2].a protocol, TEE_ISOCKET_PROTOCOLID_* + * [out] value[3].a socket handle + */ +#define PTA_SOCKET_OPEN 1 + +/* + * [in] value[0].a socket handle + */ +#define PTA_SOCKET_CLOSE 2 + +#define PTA_SOCKET_TIMEOUT_NONBLOCKING 0 +#define PTA_SOCKET_TIMEOUT_BLOCKING 0xffffffff + +/* + * [in] value[0].a socket handle + * [in] value[0].b timeout ms or TEE_TIMEOUT_INFINITE + * [in] memref[1] buffer to transmit + * [out] value[2].a number of transmitted bytes + */ +#define PTA_SOCKET_SEND 3 + +/* + * [in] value[0].a socket handle + * [in] value[0].b timeout ms or TEE_TIMEOUT_INFINITE + * [out] memref[1] buffer + */ +#define PTA_SOCKET_RECV 4 + +/* + * [in] value[0].a socket handle + * [in] value[0].b ioctl command + * [in/out] memref[1] buffer + */ +#define PTA_SOCKET_IOCTL 5 + +#endif /*__PTA_SOCKET*/ diff --git a/optee/optee_os/lib/libutee/include/pta_stm32mp_bsec.h b/optee/optee_os/lib/libutee/include/pta_stm32mp_bsec.h new file mode 100644 index 0000000..d16fadf --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_stm32mp_bsec.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + */ + +#ifndef __PTA_STM32MP_BSEC_H +#define __PTA_STM32MP_BSEC_H + +#define PTA_BSEC_UUID { 0x94cf71ad, 0x80e6, 0x40b5, \ + { 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03 } } + +/** + * Read OTP memory + * + * [in] value[0].a OTP start offset in byte + * [in] value[0].b Access type, see PTA_BSEC_TYPE_* + * [out] memref[1].buffer Output buffer to store read values + * [out] memref[1].size Size of OTP to be read + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller + */ +#define PTA_BSEC_CMD_READ_OTP 0x0 + +/** + * Write OTP memory + * + * [in] value[0].a OTP start offset in byte + * [in] value[0].b Access type (0 : shadow, + * 1 : fuse, 2 : lock) + * [in] memref[1].buffer Input buffer to read values + * [in] memref[1].size Size of OTP to be written + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller + */ +#define PTA_BSEC_CMD_WRITE_OTP 0x1 + +/** + * Get BSEC state + * Return the chip security level by reading the BSEC state + * + * [out] value[0].a One of PTA_BSEC_STATE_* + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define PTA_BSEC_CMD_GET_STATE 0x3 + +enum stm32_bsec_pta_sec_state { + PTA_BSEC_STATE_SEC_OPEN = 0, + PTA_BSEC_STATE_SEC_CLOSE = 1, + PTA_BSEC_STATE_INVALID = 3 +}; + +/* + * Access types identifiers for PTA_BSEC_CMD_READ_OTP and + * PTA_BSEC_CMD_WRITE_OTP = value[in].b. + * + * PTA_BSEC_SHADOW_ACCESS Access OTP shadow memory + * PTA_BSEC_FUSE_ACCESS Access OTP fuse memory + * PTA_BSEC_LOCKS_ACCESS Access OTP locks. The locks value read/written + * in memref[1] 32bit words are related to bit flag + * masks PTA_BSEC_LOCK_*. + */ +#define PTA_BSEC_SHADOW_ACCESS 0 +#define PTA_BSEC_FUSE_ACCESS 1 +#define PTA_BSEC_LOCKS_ACCESS 2 + +/* + * PTA_BSEC_LOCK_* - Bit mask of OTP locks in memref[1] + * + * PTA_BSEC_LOCK_PERM Fuse programming permanent lock + * PTA_BSEC_LOCK_SHADOW_R Shadow programming (from fuse) lock + * PTA_BSEC_LOCK_SHADOW_W Shadow memory write lock + * PTA_BSEC_LOCK_SHADOW_P Fuse programming sticky lock + * PTA_BSEC_LOCK_ERROR Flag indicating an error in lock access + */ +#define PTA_BSEC_LOCK_PERM BIT(30) +#define PTA_BSEC_LOCK_SHADOW_R BIT(29) +#define PTA_BSEC_LOCK_SHADOW_W BIT(28) +#define PTA_BSEC_LOCK_SHADOW_P BIT(27) +#define PTA_BSEC_LOCK_ERROR BIT(26) + +#endif /* __PTA_STM32MP_BSEC_H */ diff --git a/optee/optee_os/lib/libutee/include/pta_system.h b/optee/optee_os/lib/libutee/include/pta_system.h new file mode 100644 index 0000000..a23f60b --- /dev/null +++ b/optee/optee_os/lib/libutee/include/pta_system.h @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018-2019, Linaro Limited + * Copyright (c) 2020, Open Mobile Platform LLC + */ +#ifndef __PTA_SYSTEM_H +#define __PTA_SYSTEM_H + +#include + +/* + * Interface to the pseudo TA, which is provides misc. auxiliary services, + * extending existing GlobalPlatform Core API + */ + +#define PTA_SYSTEM_UUID { 0x3a2f8978, 0x5dc0, 0x11e8, { \ + 0x9c, 0x2d, 0xfa, 0x7a, 0xe0, 0x1b, 0xbe, 0xbc } } + +/* + * Having keys with too few bits impose a potential security risk, hence set a + * lower bound of 128 bits. + */ +#define TA_DERIVED_KEY_MIN_SIZE 16 + +/* Same value as max in huk_subkey_derive */ +#define TA_DERIVED_KEY_MAX_SIZE 32 + +#define TA_DERIVED_EXTRA_DATA_MAX_SIZE 1024 + +/* + * Add (re-seed) caller-provided entropy to the RNG pool. Keymaster + * implementations need to securely mix the provided entropy into their pool, + * which also must contain internally-generated entropy from a hardware random + * number generator. + * + * [in] memref[0]: entropy input data + */ +#define PTA_SYSTEM_ADD_RNG_ENTROPY 0 + +/* + * Derives a device and TA unique key. The caller can also provide extra data + * that will be mixed together with existing device unique properties. If no + * extra data is provided, then the derived key will only use device unique + * properties and caller TA UUID. + * + * [in] params[0].memref.buffer Buffer for extra data + * [in] params[0].memref.size Size of extra data (max 1024 bytes) + * [out] params[1].memref.buffer Buffer for the derived key + * [out] params[1].memref.size Size of the derived key (16 to 32 bytes) + */ +#define PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY 1 + +/* Memory can be shared with other TAs */ +#define PTA_SYSTEM_MAP_FLAG_SHAREABLE BIT32(0) +/* Read/write memory */ +#define PTA_SYSTEM_MAP_FLAG_WRITEABLE BIT32(1) +/* Executable memory */ +#define PTA_SYSTEM_MAP_FLAG_EXECUTABLE BIT32(2) + +/* + * Map zero initialized memory + * + * [in] value[0].a: Number of bytes + * [in] value[0].b: Flags, 0 or PTA_SYSTEM_MAP_FLAG_SHAREABLE + * [out] value[1].a: Address upper 32-bits + * [out] value[1].b: Address lower 32-bits + * [in] value[2].a: Extra pad before memory range + * [in] value[2].b: Extra pad after memory range + */ +#define PTA_SYSTEM_MAP_ZI 2 + +/* + * Unmap memory + * + * [in] value[0].a: Number of bytes + * [in] value[0].b: Must be 0 + * [in] value[1].a: Address upper 32-bits + * [in] value[1].b: Address lower 32-bits + */ +#define PTA_SYSTEM_UNMAP 3 + +/* + * Find and opens an TA binary and return a handle + * + * [in] memref[0]: UUID of TA binary + * [out] value[1].a: Handle to TA binary + * [out] value[1].b: 0 + */ +#define PTA_SYSTEM_OPEN_TA_BINARY 4 + +/* + * Close an TA binary handle + * + * When a TA is done mapping new parts of an TA binary it closes the handle + * to free resources, established mappings remains. + * + * [in] value[1].a: Handle to TA binary + * [in] value[1].b: Must be 0 + * + * Returns TEE_SUCCESS if the TA binary was verified successfully. + */ +#define PTA_SYSTEM_CLOSE_TA_BINARY 5 + +/* + * Map segment of TA binary + * + * Different parts of an TA binary file needs different permissions. + * Read-write mapped parts are private to the TA, while read-only (which + * includes execute) mapped parts are shared with other TAs. This is + * transparent to the TA. If the supplied address in value[3] is 0 a + * suitable address is selected, else it will either be mapped at that + * address of an error is returned. + * + * [in] value[0].a: Handle to TA binary + * [in] value[0].b: Flags, PTA_SYSTEM_MAP_FLAG_* + * [in] value[1].a: Offset into TA binary, must be page aligned + * [in] value[1].b: Number of bytes, the last page will be zero + * extended if not page aligned + * [in/out] value[2].a: Address upper 32-bits + * [in/out] value[2].b: Address lower 32-bits + * [in] value[3].a: Extra pad before memory range + * [in] value[3].b: Extra pad after memory range + */ +#define PTA_SYSTEM_MAP_TA_BINARY 6 + +/* + * Copy a memory range from TA binary + * + * [in] value[0].a: Handle to TA binary + * [in] value[0].b: Offset into TA binary + * [out] memref[1]: Destination + */ +#define PTA_SYSTEM_COPY_FROM_TA_BINARY 7 + +/* + * Set memory protection + * + * [in] value[0].a: Number of bytes + * [in] value[0].b: Flags, PTA_SYSTEM_MAP_FLAG_* + * [in] value[1].a: Address upper 32-bits + * [in] value[1].b: Address lower 32-bits + */ +#define PTA_SYSTEM_SET_PROT 8 + +/* + * Remap a segment of a TA mapping + * + * Moves an already mapped segment of a TA to a new address. If the + * supplied new address is 0 a suitable address is selected, else it will + * either be mapped at that address or an error is returned. + * + * [in] value[0].a: Number of bytes, must match length rounded up to + * closest page of original mapping + * [in] value[0].b: Must be 0 + * [in] value[1].a: Old address upper 32-bits + * [in] value[1].b: Old address lower 32-bits + * [in/out] value[2].a: New address upper 32-bits + * [in/out] value[2].b: New address lower 32-bits + * [in] value[3].a: Extra pad before memory range + * [in] value[3].b: Extra pad after memory range + */ +#define PTA_SYSTEM_REMAP 9 + +/* + * Load a shared library + * + * [in] memref[0]: the UUID of the shared library (@filename) + * [in] value[1].a: @flags, must be (RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE) + * + * Used by: (libdl) dlopen(const char *filename, int flags) + */ +#define PTA_SYSTEM_DLOPEN 10 + +/* + * Resolve a symbol in a previously loaded shared library or in the whole TA + * + * [in] memref[0]: the UUID of the shared library, or the nil UUID to + * search the whole TA + * [in] memref[1]: symbol name (@symbol) + * [out] value[2]: address of the symbol or NULL + * + * Used by: (libdl) dlsym(void *handle, const char *symbol) + */ +#define PTA_SYSTEM_DLSYM 11 + +/* + * Retrieves a copy of the TPM Event log held in secure memory. + * + * [out] memref[0]: Pointer to the buffer where to store the event log. + */ +#define PTA_SYSTEM_GET_TPM_EVENT_LOG 12 + +/* + * Invoke a tee-supplicant's plugin + * + * [in] memref[0] uuid of the plugin (TEE_UUID) + * [in] value[1].a command for the plugin + * [in] value[1].b sub_command for the plugin + * [in/out] memref[2] additional data for the plugin + * [out] value[3].a output length of data + */ +#define PTA_SYSTEM_SUPP_PLUGIN_INVOKE 13 + +#endif /* __PTA_SYSTEM_H */ diff --git a/optee/optee_os/lib/libutee/include/rng_pta_client.h b/optee/optee_os/lib/libutee/include/rng_pta_client.h new file mode 100644 index 0000000..6de3c64 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/rng_pta_client.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2018-2022, Linaro Limited + * + * This header file is deprecated and kept for backward compatibility. + */ + +#ifndef __RNG_PTA_CLIENT_H +#define __RNG_PTA_CLIENT_H + +#include + +#endif /* __RNG_PTA_CLIENT_H */ diff --git a/optee/optee_os/lib/libutee/include/tee_api.h b/optee/optee_os/lib/libutee/include/tee_api.h new file mode 100644 index 0000000..22b6b04 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_api.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef TEE_API_H +#define TEE_API_H + +#include + +#endif /* TEE_API_H */ diff --git a/optee/optee_os/lib/libutee/include/tee_api_compat.h b/optee/optee_os/lib/libutee/include/tee_api_compat.h new file mode 100644 index 0000000..166f1a7 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_api_compat.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef __TEE_API_COMPAT_H +#define __TEE_API_COMPAT_H + +/* + * This function will be called from TA_OpenSessionEntryPoint() in + * user_ta_header.c (if compiled with __OPTEE_CORE_API_COMPAT_1_1), the + * compatibility entry function is passed as a function pointer in @fp. + * This is needed since libutee is never compiled with + * __OPTEE_CORE_API_COMPAT_1_1, but we still need a way to call the + * compatibility function __GP11_TA_InvokeCommandEntryPoint(), but only + * when __OPTEE_CORE_API_COMPAT_1_1 is defined. + */ +TEE_Result __ta_open_sess(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], + void **sess_ctx, + TEE_Result (*fp)(uint32_t, + __GP11_TEE_Param [TEE_NUM_PARAMS], + void **)); + +/* + * Same as for __ta_open_sess_func(), except that @fp now is a pointer to + * __GP11_TA_InvokeCommandEntryPoint(). + */ +TEE_Result __ta_invoke_cmd(void *sess_ctx, uint32_t cmd_id, uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS], + TEE_Result (*fp)(void *, uint32_t, uint32_t, + __GP11_TEE_Param [TEE_NUM_PARAMS])); + +#if __OPTEE_CORE_API_COMPAT_1_1 +/* Types */ +#define TEE_Attribute __GP11_TEE_Attribute +#define TEE_ObjectInfo __GP11_TEE_ObjectInfo +#define TEE_Param __GP11_TEE_Param + +/* Functions */ +#define TA_InvokeCommandEntryPoint __GP11_TA_InvokeCommandEntryPoint +#define TA_OpenSessionEntryPoint __GP11_TA_OpenSessionEntryPoint +#define TEE_AEDecryptFinal __GP11_TEE_AEDecryptFinal +#define TEE_AEEncryptFinal __GP11_TEE_AEEncryptFinal +#define TEE_AEInit __GP11_TEE_AEInit +#define TEE_AEUpdateAAD __GP11_TEE_AEUpdateAAD +#define TEE_AEUpdate __GP11_TEE_AEUpdate +#define TEE_AllocateTransientObject __GP11_TEE_AllocateTransientObject +#define TEE_AsymmetricDecrypt __GP11_TEE_AsymmetricDecrypt +#define TEE_AsymmetricEncrypt __GP11_TEE_AsymmetricEncrypt +#define TEE_AsymmetricSignDigest __GP11_TEE_AsymmetricSignDigest +#define TEE_AsymmetricVerifyDigest __GP11_TEE_AsymmetricVerifyDigest +#define TEE_BigIntConvertFromOctetString __GP11_TEE_BigIntConvertFromOctetString +#define TEE_BigIntConvertToOctetString __GP11_TEE_BigIntConvertToOctetString +#define TEE_BigIntFMMContextSizeInU32 __GP11_TEE_BigIntFMMContextSizeInU32 +#define TEE_BigIntFMMSizeInU32 __GP11_TEE_BigIntFMMSizeInU32 +#define TEE_BigIntInitFMMContext __GP11_TEE_BigIntInitFMMContext +#define TEE_BigIntInitFMM __GP11_TEE_BigIntInitFMM +#define TEE_BigIntShiftRight __GP11_TEE_BigIntShiftRight +#define TEE_CheckMemoryAccessRights __GP11_TEE_CheckMemoryAccessRights +#define TEE_CipherDoFinal __GP11_TEE_CipherDoFinal +#define TEE_CipherInit __GP11_TEE_CipherInit +#define TEE_CipherUpdate __GP11_TEE_CipherUpdate +#define TEE_CreatePersistentObject __GP11_TEE_CreatePersistentObject +#define TEE_DeriveKey __GP11_TEE_DeriveKey +#define TEE_DigestDoFinal __GP11_TEE_DigestDoFinal +#define TEE_DigestUpdate __GP11_TEE_DigestUpdate +#define TEE_FreeOperation __GP11_TEE_FreeOperation +#define TEE_GenerateKey __GP11_TEE_GenerateKey +#define TEE_GenerateRandom __GP11_TEE_GenerateRandom +#define TEE_GetNextPersistentObject __GP11_TEE_GetNextPersistentObject +#define TEE_GetObjectBufferAttribute __GP11_TEE_GetObjectBufferAttribute +#define TEE_GetObjectInfo1 __GP11_TEE_GetObjectInfo1 +#define TEE_GetObjectInfo __GP11_TEE_GetObjectInfo +#define TEE_GetOperationInfoMultiple __GP11_TEE_GetOperationInfoMultiple +#define TEE_GetPropertyAsBinaryBlock __GP11_TEE_GetPropertyAsBinaryBlock +#define TEE_GetPropertyAsString __GP11_TEE_GetPropertyAsString +#define TEE_GetPropertyName __GP11_TEE_GetPropertyName +#define TEE_InitRefAttribute __GP11_TEE_InitRefAttribute +#define TEE_InitValueAttribute __GP11_TEE_InitValueAttribute +#define TEE_InvokeTACommand __GP11_TEE_InvokeTACommand +#define TEE_MACCompareFinal __GP11_TEE_MACCompareFinal +#define TEE_MACComputeFinal __GP11_TEE_MACComputeFinal +#define TEE_MACInit __GP11_TEE_MACInit +#define TEE_MACUpdate __GP11_TEE_MACUpdate +#define TEE_Malloc __GP11_TEE_Malloc +#define TEE_MemCompare __GP11_TEE_MemCompare +#define TEE_MemFill __GP11_TEE_MemFill +#define TEE_MemMove __GP11_TEE_MemMove +#define TEE_OpenPersistentObject __GP11_TEE_OpenPersistentObject +#define TEE_OpenTASession __GP11_TEE_OpenTASession +#define TEE_PopulateTransientObject __GP11_TEE_PopulateTransientObject +#define TEE_ReadObjectData __GP11_TEE_ReadObjectData +#define TEE_Realloc __GP11_TEE_Realloc +#define TEE_RenamePersistentObject __GP11_TEE_RenamePersistentObject +#define TEE_SeekObjectData __GP11_TEE_SeekObjectData +#define TEE_SetOperationKey2 __GP11_TEE_SetOperationKey2 +#define TEE_SetOperationKey __GP11_TEE_SetOperationKey +#define TEE_TruncateObjectData __GP11_TEE_TruncateObjectData +#define TEE_WriteObjectData __GP11_TEE_WriteObjectData +#endif + +#endif /*__TEE_API_COMPAT_H*/ diff --git a/optee/optee_os/lib/libutee/include/tee_api_defines.h b/optee/optee_os/lib/libutee/include/tee_api_defines.h new file mode 100644 index 0000000..9e0979c --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_api_defines.h @@ -0,0 +1,697 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022, Linaro Limited + */ + +/* Based on GP TEE Internal Core API Specification Version 1.3.1 */ + +#ifndef TEE_API_DEFINES_H +#define TEE_API_DEFINES_H + +#define TEE_CORE_API_MAJOR_VERSION 1U +#define TEE_CORE_API_MINOR_VERSION 3U +#define TEE_CORE_API_MAINTENANCE_VERSION 1U +#define TEE_CORE_API_VERSION \ + ((TEE_CORE_API_MAJOR_VERSION << 24) | \ + (TEE_CORE_API_MINOR_VERSION << 16) | \ + (TEE_CORE_API_MAINTENANCE_VERSION << 8)) +#define TEE_CORE_API_1_3_1 + +/* + * Below follows the GP defined way of letting a TA define that it wants an + * API compatible with version 1.1 or the latest. An alternative approach + * is to set __OPTEE_CORE_API_COMPAT_1_1, but that's an OP-TEE extension. + * + * The GP specs (>= 1.2) requires that only APIs defined in the indicated + * version SHALL be made available when using this mechanism. However, that + * is far beyond what ordinary standards requires as they permit + * extensions. With this, in OP-TEE, extensions and new API that doesn't + * interfere with the selected version of the standard will be permitted. + */ +#if defined(TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION) && \ + !defined(TEE_CORE_API_REQUIRED_MINOR_VERSION) +#error "Required TEE_CORE_API_REQUIRED_MINOR_VERSION undefined" +#endif +#if defined(TEE_CORE_API_REQUIRED_MINOR_VERSION) && \ + !defined(TEE_CORE_API_REQUIRED_MAJOR_VERSION) +#error "Required TEE_CORE_API_REQUIRED_MAJOR_VERSION undefined" +#endif + +#if defined(TEE_CORE_API_REQUIRED_MAJOR_VERSION) +#if TEE_CORE_API_REQUIRED_MAJOR_VERSION != 1 && \ + TEE_CORE_API_REQUIRED_MAJOR_VERSION != 0 +#error "Required major version not supported" +#endif +#ifdef TEE_CORE_API_REQUIRED_MINOR_VERSION +#if TEE_CORE_API_REQUIRED_MINOR_VERSION == 1 +#define __OPTEE_CORE_API_COMPAT_1_1 1 +#else +#error "Required minor version not supported" +#endif +#if defined(TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION) && \ + TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION != 0 +#error "Required maintenance version not supported" +#endif +#endif +#endif + +/* + * For backwards compatibility with v1.1 as provided by up to OP-TEE + * version 3.19.0, define __OPTEE_CORE_API_COMPAT_1_1 to 1. + * + * Some versions of the GP specs have introduced backwards incompatible + * changes. For example the v1.0: + * + * TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, + * const void *chunk, uint32_t chunkLen, + * void *hash, uint32_t *hashLen); + * + * Was changed in v1.1.1 to this: + * + * TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, + * const void *chunk, size_t chunkLen, + * void *hash, size_t *hashLen); + * + * Note the type change for "hashLen", a source of problem especially on + * platforms where size_t is a 64-bit unsigned integer. + * + * As a way of allowing older TAs to be compiled with a newer version of + * the API we can turn off or hide different incompatible changes. New + * features which are not interfering with older versions of the API are + * not disabled. So by enabling __OPTEE_CORE_API_COMPAT_1_1 will not result + * in pure 1.1 API, it will be a hybrid API that should work with most TAs + * not yet updated to the new API. + * + * Backwards compatibility is provided by duplicating all functions that + * has changed since v1.1. The original function is given a "__GP11_" + * prefix and preprocessor macros are used to let a legacy TA use the old + * function instead. The same principle applies to defined types. + */ +#ifndef __OPTEE_CORE_API_COMPAT_1_1 +#define __OPTEE_CORE_API_COMPAT_1_1 0 +#endif + +#define TEE_HANDLE_NULL 0 + +#define TEE_TIMEOUT_INFINITE 0xFFFFFFFF + +/* API Error Codes */ +#define TEE_SUCCESS 0x00000000 +#define TEE_ERROR_CORRUPT_OBJECT 0xF0100001 +#define TEE_ERROR_CORRUPT_OBJECT_2 0xF0100002 +#define TEE_ERROR_STORAGE_NOT_AVAILABLE 0xF0100003 +#define TEE_ERROR_STORAGE_NOT_AVAILABLE_2 0xF0100004 +#define TEE_ERROR_UNSUPPORTED_VERSION 0xF0100005 +#define TEE_ERROR_CIPHERTEXT_INVALID 0xF0100006 +#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_ERROR_EXTERNAL_CANCEL 0xFFFF0011 +#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 + +/* 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_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_TEE_IMPLEMENTATION (TEE_PropSetHandle)0xFFFFFFFD +#define TEE_PROPSET_CURRENT_CLIENT (TEE_PropSetHandle)0xFFFFFFFE +#define TEE_PROPSET_CURRENT_TA (TEE_PropSetHandle)0xFFFFFFFF + +/* Memory Access Rights Constants */ +#define TEE_MEMORY_ACCESS_READ 0x00000001 +#define TEE_MEMORY_ACCESS_WRITE 0x00000002 +#define TEE_MEMORY_ACCESS_ANY_OWNER 0x00000004 + +/* Memory Management Constant */ +#define TEE_MALLOC_FILL_ZERO 0x00000000 +#define TEE_MALLOC_NO_FILL 0x00000001 +#define TEE_MALLOC_NO_SHARE 0x00000002 + +/* TEE_Whence Constants */ +#define TEE_DATA_SEEK_SET 0x00000000 +#define TEE_DATA_SEEK_CUR 0x00000001 +#define TEE_DATA_SEEK_END 0x00000002 +#define TEE_WHENCE_ILLEGAL_VALUE 0x7FFFFFFF + +/* TEE_OperationMode Values */ +#define TEE_MODE_ENCRYPT 0x00000000 +#define TEE_MODE_DECRYPT 0x00000001 +#define TEE_MODE_SIGN 0x00000002 +#define TEE_MODE_VERIFY 0x00000003 +#define TEE_MODE_MAC 0x00000004 +#define TEE_MODE_DIGEST 0x00000005 +#define TEE_MODE_DERIVE 0x00000006 +#define TEE_MODE_ILLEGAL_VALUE 0x7FFFFFFF + +/* 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_OVERWRITE 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_HANDLE_FLAG_EXTRACTING 0x00100000 +#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 +#define TEE_OPERATION_STATE_INITIAL 0x00000000 +#define TEE_OPERATION_STATE_ACTIVE 0x00000001 +#define TEE_OPERATION_STATE_EXTRACTING 0x00000002 + +/* 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_SM4_ECB_NOPAD 0x10000014 +#define TEE_ALG_SM4_CBC_NOPAD 0x10000114 +#define TEE_ALG_SM4_CTR 0x10000214 +#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_V1_5_SHA3_224 0x70008830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA3_256 0x70009830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA3_384 0x7000A830 +#define TEE_ALG_RSASSA_PKCS1_V1_5_SHA3_512 0x7000B830 +#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_RSASSA_PKCS1_PSS_MGF1_SHA3_224 0x70818930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA3_256 0x70919930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA3_384 0x70A1A930 +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA3_512 0x70B1B930 +#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_RSAES_PKCS1_OAEP_MGF1_SHA3_224 0x60810230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA3_256 0x60910230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA3_384 0x60A10230 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA3_512 0x60B10230 +#define TEE_ALG_RSA_NOPAD 0x60000030 +#define TEE_ALG_DSA_SHA1 0x70002131 +#define TEE_ALG_DSA_SHA224 0x70003131 +#define TEE_ALG_DSA_SHA256 0x70004131 +#define TEE_ALG_DSA_SHA3_224 0x70008131 +#define TEE_ALG_DSA_SHA3_256 0x70009131 +#define TEE_ALG_DSA_SHA3_384 0x7000A131 +#define TEE_ALG_DSA_SHA3_512 0x7000B131 +#define TEE_ALG_SM2_DSA_SM3 0x70006045 +#define TEE_ALG_DH_DERIVE_SHARED_SECRET 0x80000032 +#define TEE_ALG_SM2_KEP 0x60000045 +#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_SHA3_224 0x50000008 +#define TEE_ALG_SHA3_256 0x50000009 +#define TEE_ALG_SHA3_384 0x5000000A +#define TEE_ALG_SHA3_512 0x5000000B +#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 +#define TEE_ALG_HMAC_SM3 0x30000007 +#define TEE_ALG_HMAC_SHA3_224 0x30000008 +#define TEE_ALG_HMAC_SHA3_256 0x30000009 +#define TEE_ALG_HMAC_SHA3_384 0x3000000A +#define TEE_ALG_HMAC_SHA3_512 0x3000000B + +/* + * These are used in the OP-TEE ABI, due to an inconsistency in the v1.1 + * specification the wrong values we assumed and now we're stuck with those. + * + * In GP Internal Core API v1.1 + * "Table 6-12: Structure of Algorithm Identifier" + * indicates ECDSA have the algorithm "0x41" and ECDH "0x42" + * whereas + * "Table 6-11: List of Algorithm Identifiers" defines + * TEE_ALG_ECDSA_P192 as 0x70001042 + * + * We chose to define __OPTEE_TEE_ALG_ECDSA_P192 as 0x70001041 and so on + * to conform to table 6-12. + */ +#define __OPTEE_ALG_ECDSA_P192 0x70001041 +#define __OPTEE_ALG_ECDSA_P224 0x70002041 +#define __OPTEE_ALG_ECDSA_P256 0x70003041 +#define __OPTEE_ALG_ECDSA_P384 0x70004041 +#define __OPTEE_ALG_ECDSA_P521 0x70005041 +#define __OPTEE_ALG_ECDH_P192 0x80001042 +#define __OPTEE_ALG_ECDH_P224 0x80002042 +#define __OPTEE_ALG_ECDH_P256 0x80003042 +#define __OPTEE_ALG_ECDH_P384 0x80004042 +#define __OPTEE_ALG_ECDH_P521 0x80005042 + +/* TEE_ALG_ECDSA_P* and TEE_ALG_ECDH_P* are deprecated */ +#define TEE_ALG_ECDSA_P192 TEE_ALG_ECDSA_SHA1 +#define TEE_ALG_ECDSA_P224 TEE_ALG_ECDSA_SHA224 +#define TEE_ALG_ECDSA_P256 TEE_ALG_ECDSA_SHA256 +#define TEE_ALG_ECDSA_P384 TEE_ALG_ECDSA_SHA384 +#define TEE_ALG_ECDSA_P521 TEE_ALG_ECDSA_SHA512 +#define TEE_ALG_ECDH_P192 TEE_ALG_ECDH_DERIVE_SHARED_SECRET +#define TEE_ALG_ECDH_P224 TEE_ALG_ECDH_DERIVE_SHARED_SECRET +#define TEE_ALG_ECDH_P256 TEE_ALG_ECDH_DERIVE_SHARED_SECRET +#define TEE_ALG_ECDH_P384 TEE_ALG_ECDH_DERIVE_SHARED_SECRET +#define TEE_ALG_ECDH_P521 TEE_ALG_ECDH_DERIVE_SHARED_SECRET + +#define TEE_ALG_ECDH_DERIVE_SHARED_SECRET 0x80000042 +#define TEE_ALG_ECDSA_SHA1 0x70001042 +#define TEE_ALG_ECDSA_SHA224 0x70002042 +#define TEE_ALG_ECDSA_SHA256 0x70003042 +#define TEE_ALG_ECDSA_SHA384 0x70004042 +#define TEE_ALG_ECDSA_SHA512 0x70005042 +#define TEE_ALG_ECDSA_SHA3_224 0x70006042 +#define TEE_ALG_ECDSA_SHA3_256 0x70007042 +#define TEE_ALG_ECDSA_SHA3_384 0x70008042 +#define TEE_ALG_ECDSA_SHA3_512 0x70009042 + +#define TEE_ALG_ED25519 0x70006043 +#define TEE_ALG_ED448 0x70006044 +#define TEE_ALG_SM2_PKE 0x80000046 +#define TEE_ALG_HKDF 0x80000047 +#define TEE_ALG_SM3 0x50000007 +#define TEE_ALG_X25519 0x80000044 +#define TEE_ALG_X448 0x80000045 +#define TEE_ALG_SM4_ECB_PKCS5 0x10000015 +#define TEE_ALG_SM4_CBC_PKCS5 0x10000115 +#define TEE_ALG_ILLEGAL_VALUE 0xEFFFFFFF + +#define TEE_ALG_SHA3_224 0x50000008 +#define TEE_ALG_SHA3_256 0x50000009 +#define TEE_ALG_SHA3_384 0x5000000A +#define TEE_ALG_SHA3_512 0x5000000B +#define TEE_ALG_SHAKE128 0x50000101 +#define TEE_ALG_SHAKE256 0x50000102 + +/* Object Types */ + +#define TEE_TYPE_AES 0xA0000010 +#define TEE_TYPE_DES 0xA0000011 +#define TEE_TYPE_DES3 0xA0000013 +#define TEE_TYPE_SM4 0xA0000014 +#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_HMAC_SM3 0xA0000007 +#define TEE_TYPE_HMAC_SHA3_224 0xA0000008 +#define TEE_TYPE_HMAC_SHA3_256 0xA0000009 +#define TEE_TYPE_HMAC_SHA3_384 0xA000000A +#define TEE_TYPE_HMAC_SHA3_512 0xA000000B +#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_ECDSA_PUBLIC_KEY 0xA0000041 +#define TEE_TYPE_ECDSA_KEYPAIR 0xA1000041 +#define TEE_TYPE_ECDH_PUBLIC_KEY 0xA0000042 +#define TEE_TYPE_ECDH_KEYPAIR 0xA1000042 +#define TEE_TYPE_ED25519_PUBLIC_KEY 0xA0000043 +#define TEE_TYPE_ED25519_KEYPAIR 0xA1000043 +#define TEE_TYPE_ED448_PUBLIC_KEY 0xA0000048 +#define TEE_TYPE_ED448_KEYPAIR 0xA1000048 +#define TEE_TYPE_X448_PUBLIC_KEY 0xA0000049 +#define TEE_TYPE_X448_KEYPAIR 0xA1000049 +#define TEE_TYPE_SM2_DSA_PUBLIC_KEY 0xA0000045 +#define TEE_TYPE_SM2_DSA_KEYPAIR 0xA1000045 +#define TEE_TYPE_SM2_KEP_PUBLIC_KEY 0xA0000046 +#define TEE_TYPE_SM2_KEP_KEYPAIR 0xA1000046 +#define TEE_TYPE_SM2_PKE_PUBLIC_KEY 0xA0000047 +#define TEE_TYPE_SM2_PKE_KEYPAIR 0xA1000047 +#define TEE_TYPE_HKDF 0xA000004A +#define TEE_TYPE_GENERIC_SECRET 0xA0000000 +#define TEE_TYPE_CORRUPTED_OBJECT 0xA00000BE +#define TEE_TYPE_DATA 0xA00000BF +#define TEE_TYPE_X25519_PUBLIC_KEY 0xA0000044 +#define TEE_TYPE_X25519_KEYPAIR 0xA1000044 +#define TEE_TYPE_ILLEGAL_VALUE 0xEFFFFFFF + +/* 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_OAEP_MGF_HASH 0xD0000931 +#define TEE_ATTR_RSA_PSS_SALT_LENGTH 0xF0000A30 +#define TEE_ATTR_ECC_PUBLIC_VALUE_X 0xD0000141 +#define TEE_ATTR_ECC_PUBLIC_VALUE_Y 0xD0000241 +#define TEE_ATTR_ECC_PRIVATE_VALUE 0xC0000341 +#define TEE_ATTR_ECC_CURVE 0xF0000441 +#define TEE_ATTR_SM2_ID_INITIATOR 0xD0000446 +#define TEE_ATTR_SM2_ID_RESPONDER 0xD0000546 +#define TEE_ATTR_SM2_KEP_USER 0xF0000646 +#define TEE_ATTR_SM2_KEP_CONFIRMATION_IN 0xD0000746 +#define TEE_ATTR_SM2_KEP_CONFIRMATION_OUT 0xD0000846 + +/* + * Commit 5b385b3f835d ("core: crypto: add support for SM2 KEP") defined by + * mistake the wrong values for these two. OP-TEE recognizes these two as + * alternative IDs in parallel with the correct official values when + * supplied as parameters when deriving a key using the TEE_ALG_SM2_KEP + * algorithm. + */ +#define __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X 0xD0000946 +#define __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y 0xD0000A46 + +#define TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X 0xD0000146 +#define TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y 0xD0000246 +#define TEE_ATTR_EDDSA_CTX 0xD0000643 +#define TEE_ATTR_ED25519_PUBLIC_VALUE 0xD0000743 +#define TEE_ATTR_ED25519_PRIVATE_VALUE 0xC0000843 +#define TEE_ATTR_X25519_PUBLIC_VALUE 0xD0000944 +#define TEE_ATTR_X25519_PRIVATE_VALUE 0xC0000A44 +#define TEE_ATTR_EDDSA_PREHASH 0xF0000004 +#define TEE_ATTR_X448_PUBLIC_VALUE 0xD0000A45 +#define TEE_ATTR_X448_PRIVATE_VALUE 0xC0000A46 +#define TEE_ATTR_HKDF_SALT 0xD0000946 +#define TEE_ATTR_HKDF_INFO 0xD0000A46 +#define TEE_ATTR_HKDF_HASH_ALGORITHM 0xF0000B46 +#define TEE_ATTR_KDF_KEY_SIZE 0xF0000C46 + +#define TEE_ATTR_FLAG_PUBLIC (1 << 28) +#define TEE_ATTR_FLAG_VALUE (1 << 29) +/* + * Deprecated, but kept for backwards compatibility + * + * Be careful with GPD TEE Internal API specification v1.0 where table 6-12 + * defines BIT [28] with the right meaning whereas sections 5.4.3 and 5.4.4 + * falsely describe a reversed bit flag value meaning. + */ +#define TEE_ATTR_BIT_PROTECTED TEE_ATTR_FLAG_PUBLIC +#define TEE_ATTR_BIT_VALUE TEE_ATTR_FLAG_VALUE + +/* List of Supported ECC Curves */ +#define TEE_CRYPTO_ELEMENT_NONE 0x00000000 +#define TEE_ECC_CURVE_NIST_P192 0x00000001 +#define TEE_ECC_CURVE_NIST_P224 0x00000002 +#define TEE_ECC_CURVE_NIST_P256 0x00000003 +#define TEE_ECC_CURVE_NIST_P384 0x00000004 +#define TEE_ECC_CURVE_NIST_P521 0x00000005 +#define TEE_ECC_CURVE_25519 0x00000300 +#define TEE_ECC_CURVE_SM2 0x00000400 + +/* Panicked Functions Identification */ +/* TA Interface */ +#define TEE_PANIC_ID_TA_CLOSESESSIONENTRYPOINT 0x00000101 +#define TEE_PANIC_ID_TA_CREATEENTRYPOINT 0x00000102 +#define TEE_PANIC_ID_TA_DESTROYENTRYPOINT 0x00000103 +#define TEE_PANIC_ID_TA_INVOKECOMMANDENTRYPOINT 0x00000104 +#define TEE_PANIC_ID_TA_OPENSESSIONENTRYPOINT 0x00000105 +/* Property Access */ +#define TEE_PANIC_ID_TEE_ALLOCATEPROPERTYENUMERATOR 0x00000201 +#define TEE_PANIC_ID_TEE_FREEPROPERTYENUMERATOR 0x00000202 +#define TEE_PANIC_ID_TEE_GETNEXTPROPERTY 0x00000203 +#define TEE_PANIC_ID_TEE_GETPROPERTYASBINARYBLOCK 0x00000204 +#define TEE_PANIC_ID_TEE_GETPROPERTYASBOOL 0x00000205 +#define TEE_PANIC_ID_TEE_GETPROPERTYASIDENTITY 0x00000206 +#define TEE_PANIC_ID_TEE_GETPROPERTYASSTRING 0x00000207 +#define TEE_PANIC_ID_TEE_GETPROPERTYASU32 0x00000208 +#define TEE_PANIC_ID_TEE_GETPROPERTYASUUID 0x00000209 +#define TEE_PANIC_ID_TEE_GETPROPERTYNAME 0x0000020A +#define TEE_PANIC_ID_TEE_RESETPROPERTYENUMERATOR 0x0000020B +#define TEE_PANIC_ID_TEE_STARTPROPERTYENUMERATOR 0x0000020C +/* Panic Function */ +#define TEE_PANIC_ID_TEE_PANIC 0x00000301 +/* Internal Client API */ +#define TEE_PANIC_ID_TEE_CLOSETASESSION 0x00000401 +#define TEE_PANIC_ID_TEE_INVOKETACOMMAND 0x00000402 +#define TEE_PANIC_ID_TEE_OPENTASESSION 0x00000403 +/* Cancellation */ +#define TEE_PANIC_ID_TEE_GETCANCELLATIONFLAG 0x00000501 +#define TEE_PANIC_ID_TEE_MASKCANCELLATION 0x00000502 +#define TEE_PANIC_ID_TEE_UNMASKCANCELLATION 0x00000503 +/* Memory Management */ +#define TEE_PANIC_ID_TEE_CHECKMEMORYACCESSRIGHTS 0x00000601 +#define TEE_PANIC_ID_TEE_FREE 0x00000602 +#define TEE_PANIC_ID_TEE_GETINSTANCEDATA 0x00000603 +#define TEE_PANIC_ID_TEE_MALLOC 0x00000604 +#define TEE_PANIC_ID_TEE_MEMCOMPARE 0x00000605 +#define TEE_PANIC_ID_TEE_MEMFILL 0x00000606 +#define TEE_PANIC_ID_TEE_MEMMOVE 0x00000607 +#define TEE_PANIC_ID_TEE_REALLOC 0x00000608 +#define TEE_PANIC_ID_TEE_SETINSTANCEDATA 0x00000609 +/* Generic Object */ +#define TEE_PANIC_ID_TEE_CLOSEOBJECT 0x00000701 +#define TEE_PANIC_ID_TEE_GETOBJECTBUFFERATTRIBUTE 0x00000702 +/* deprecated */ +#define TEE_PANIC_ID_TEE_GETOBJECTINFO 0x00000703 +#define TEE_PANIC_ID_TEE_GETOBJECTVALUEATTRIBUTE 0x00000704 +/* deprecated */ +#define TEE_PANIC_ID_TEE_RESTRICTOBJECTUSAGE 0x00000705 +#define TEE_PANIC_ID_TEE_GETOBJECTINFO1 0x00000706 +#define TEE_PANIC_ID_TEE_RESTRICTOBJECTUSAGE1 0x00000707 +/* Transient Object */ +#define TEE_PANIC_ID_TEE_ALLOCATETRANSIENTOBJECT 0x00000801 +/* deprecated */ +#define TEE_PANIC_ID_TEE_COPYOBJECTATTRIBUTES 0x00000802 +#define TEE_PANIC_ID_TEE_FREETRANSIENTOBJECT 0x00000803 +#define TEE_PANIC_ID_TEE_GENERATEKEY 0x00000804 +#define TEE_PANIC_ID_TEE_INITREFATTRIBUTE 0x00000805 +#define TEE_PANIC_ID_TEE_INITVALUEATTRIBUTE 0x00000806 +#define TEE_PANIC_ID_TEE_POPULATETRANSIENTOBJECT 0x00000807 +#define TEE_PANIC_ID_TEE_RESETTRANSIENTOBJECT 0x00000808 +#define TEE_PANIC_ID_TEE_COPYOBJECTATTRIBUTES1 0x00000809 +/* Persistent Object */ +/* deprecated */ +#define TEE_PANIC_ID_TEE_CLOSEANDDELETEPERSISTENTOBJECT 0x00000901 +#define TEE_PANIC_ID_TEE_CREATEPERSISTENTOBJECT 0x00000902 +#define TEE_PANIC_ID_TEE_OPENPERSISTENTOBJECT 0x00000903 +#define TEE_PANIC_ID_TEE_RENAMEPERSISTENTOBJECT 0x00000904 +#define TEE_PANIC_ID_TEE_CLOSEANDDELETEPERSISTENTOBJECT1 0x00000905 +/* Persistent Object Enumeration */ +#define TEE_PANIC_ID_TEE_ALLOCATEPERSISTENTOBJECTENUMERATOR 0x00000A01 +#define TEE_PANIC_ID_TEE_FREEPERSISTENTOBJECTENUMERATOR 0x00000A02 +#define TEE_PANIC_ID_TEE_GETNEXTPERSISTENTOBJECT 0x00000A03 +#define TEE_PANIC_ID_TEE_RESETPERSISTENTOBJECTENUMERATOR 0x00000A04 +#define TEE_PANIC_ID_TEE_STARTPERSISTENTOBJECTENUMERATOR 0x00000A05 +/* Data Stream Access */ +#define TEE_PANIC_ID_TEE_READOBJECTDATA 0x00000B01 +#define TEE_PANIC_ID_TEE_SEEKOBJECTDATA 0x00000B02 +#define TEE_PANIC_ID_TEE_TRUNCATEOBJECTDATA 0x00000B03 +#define TEE_PANIC_ID_TEE_WRITEOBJECTDATA 0x00000B04 +/* Generic Operation */ +#define TEE_PANIC_ID_TEE_ALLOCATEOPERATION 0x00000C01 +#define TEE_PANIC_ID_TEE_COPYOPERATION 0x00000C02 +#define TEE_PANIC_ID_TEE_FREEOPERATION 0x00000C03 +#define TEE_PANIC_ID_TEE_GETOPERATIONINFO 0x00000C04 +#define TEE_PANIC_ID_TEE_RESETOPERATION 0x00000C05 +#define TEE_PANIC_ID_TEE_SETOPERATIONKEY 0x00000C06 +#define TEE_PANIC_ID_TEE_SETOPERATIONKEY2 0x00000C07 +#define TEE_PANIC_ID_TEE_GETOPERATIONINFOMULTIPLE 0x00000C08 +/* Message Digest */ +#define TEE_PANIC_ID_TEE_DIGESTDOFINAL 0x00000D01 +#define TEE_PANIC_ID_TEE_DIGESTUPDATE 0x00000D02 +/* Symmetric Cipher */ +#define TEE_PANIC_ID_TEE_CIPHERDOFINAL 0x00000E01 +#define TEE_PANIC_ID_TEE_CIPHERINIT 0x00000E02 +#define TEE_PANIC_ID_TEE_CIPHERUPDATE 0x00000E03 +/* MAC */ +#define TEE_PANIC_ID_TEE_MACCOMPAREFINAL 0x00000F01 +#define TEE_PANIC_ID_TEE_MACCOMPUTEFINAL 0x00000F02 +#define TEE_PANIC_ID_TEE_MACINIT 0x00000F03 +#define TEE_PANIC_ID_TEE_MACUPDATE 0x00000F04 +/* Authenticated Encryption */ +#define TEE_PANIC_ID_TEE_AEDECRYPTFINAL 0x00001001 +#define TEE_PANIC_ID_TEE_AEENCRYPTFINAL 0x00001002 +#define TEE_PANIC_ID_TEE_AEINIT 0x00001003 +#define TEE_PANIC_ID_TEE_AEUPDATE 0x00001004 +#define TEE_PANIC_ID_TEE_AEUPDATEAAD 0x00001005 +/* Asymmetric */ +#define TEE_PANIC_ID_TEE_ASYMMETRICDECRYPT 0x00001101 +#define TEE_PANIC_ID_TEE_ASYMMETRICENCRYPT 0x00001102 +#define TEE_PANIC_ID_TEE_ASYMMETRICSIGNDIGEST 0x00001103 +#define TEE_PANIC_ID_TEE_ASYMMETRICVERIFYDIGEST 0x00001104 +/* Key Derivation */ +#define TEE_PANIC_ID_TEE_DERIVEKEY 0x00001201 +/* Random Data Generation */ +#define TEE_PANIC_ID_TEE_GENERATERANDOM 0x00001301 +/* Time */ +#define TEE_PANIC_ID_TEE_GETREETIME 0x00001401 +#define TEE_PANIC_ID_TEE_GETSYSTEMTIME 0x00001402 +#define TEE_PANIC_ID_TEE_GETTAPERSISTENTTIME 0x00001403 +#define TEE_PANIC_ID_TEE_SETTAPERSISTENTTIME 0x00001404 +#define TEE_PANIC_ID_TEE_WAIT 0x00001405 +/* Memory Allocation and Size of Objects */ +#define TEE_PANIC_ID_TEE_BIGINTFMMCONTEXTSIZEINU32 0x00001501 +#define TEE_PANIC_ID_TEE_BIGINTFMMSIZEINU32 0x00001502 +/* Initialization */ +#define TEE_PANIC_ID_TEE_BIGINTINIT 0x00001601 +#define TEE_PANIC_ID_TEE_BIGINTINITFMM 0x00001602 +#define TEE_PANIC_ID_TEE_BIGINTINITFMMCONTEXT 0x00001603 +/* Converter */ +#define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMOCTETSTRING 0x00001701 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMS32 0x00001702 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTTOOCTETSTRING 0x00001703 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTTOS32 0x00001704 +/* Logical Operation */ +#define TEE_PANIC_ID_TEE_BIGINTCMP 0x00001801 +#define TEE_PANIC_ID_TEE_BIGINTCMPS32 0x00001802 +#define TEE_PANIC_ID_TEE_BIGINTGETBIT 0x00001803 +#define TEE_PANIC_ID_TEE_BIGINTGETBITCOUNT 0x00001804 +#define TEE_PANIC_ID_TEE_BIGINTSHIFTRIGHT 0x00001805 +/* Basic Arithmetic */ +#define TEE_PANIC_ID_TEE_BIGINTADD 0x00001901 +#define TEE_PANIC_ID_TEE_BIGINTDIV 0x00001902 +#define TEE_PANIC_ID_TEE_BIGINTMUL 0x00001903 +#define TEE_PANIC_ID_TEE_BIGINTNEG 0x00001904 +#define TEE_PANIC_ID_TEE_BIGINTSQUARE 0x00001905 +#define TEE_PANIC_ID_TEE_BIGINTSUB 0x00001906 +/* Modular Arithmetic */ +#define TEE_PANIC_ID_TEE_BIGINTADDMOD 0x00001A01 +#define TEE_PANIC_ID_TEE_BIGINTINVMOD 0x00001A02 +#define TEE_PANIC_ID_TEE_BIGINTMOD 0x00001A03 +#define TEE_PANIC_ID_TEE_BIGINTMULMOD 0x00001A04 +#define TEE_PANIC_ID_TEE_BIGINTSQUAREMOD 0x00001A05 +#define TEE_PANIC_ID_TEE_BIGINTSUBMOD 0x00001A06 +/* Other Arithmetic */ +#define TEE_PANIC_ID_TEE_BIGINTCOMPUTEEXTENDEDGCD 0x00001B01 +#define TEE_PANIC_ID_TEE_BIGINTISPROBABLEPRIME 0x00001B02 +#define TEE_PANIC_ID_TEE_BIGINTRELATIVEPRIME 0x00001B03 +/* Fast Modular Multiplication */ +#define TEE_PANIC_ID_TEE_BIGINTCOMPUTEFMM 0x00001C01 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMFMM 0x00001C02 +#define TEE_PANIC_ID_TEE_BIGINTCONVERTTOFMM 0x00001C03 + +/* + * 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/optee/optee_os/lib/libutee/include/tee_api_defines_extensions.h b/optee/optee_os/lib/libutee/include/tee_api_defines_extensions.h new file mode 100644 index 0000000..e19a9d1 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_api_defines_extensions.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2021, Linaro Limited + * Copyright (c) 2021, SumUp Services GmbH + * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. + */ + +#ifndef TEE_API_DEFINES_EXTENSIONS_H +#define TEE_API_DEFINES_EXTENSIONS_H + +/* + * RSA signatures with MD5 hash + * Values prefixed with vendor ID bit31 with by TEE bitfields IDs + */ +#define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5 0xF0111930 +#define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5 0xF0110230 + +/* + * API extended result codes as per TEE_Result IDs defined in GPD TEE + * Internal Core API specification v1.1: + * + * 0x70000000 - 0x7FFFFFFF: Reserved for implementation-specific return + * code providing non-error information + * 0x80000000 - 0x8FFFFFFF: Reserved for implementation-specific errors + * + * TEE_ERROR_DEFER_DRIVER_INIT - Device driver failed to initialize because + * the driver depends on a device not yet initialized. + */ +#define TEE_ERROR_DEFER_DRIVER_INIT 0x80000000 + +/* + * TEE_ERROR_NODE_DISABLED - Device driver failed to initialize because it is + * not allocated for TEE environment. + */ +#define TEE_ERROR_NODE_DISABLED 0x80000001 + +/* + * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) + */ + +#define TEE_ALG_HKDF_MD5_DERIVE_KEY 0x800010C0 +#define TEE_ALG_HKDF_SHA1_DERIVE_KEY 0x800020C0 +#define TEE_ALG_HKDF_SHA224_DERIVE_KEY 0x800030C0 +#define TEE_ALG_HKDF_SHA256_DERIVE_KEY 0x800040C0 +#define TEE_ALG_HKDF_SHA384_DERIVE_KEY 0x800050C0 +#define TEE_ALG_HKDF_SHA512_DERIVE_KEY 0x800060C0 + +#define TEE_TYPE_HKDF_IKM 0xA10000C0 + +#define TEE_ATTR_HKDF_IKM 0xC00001C0 +/* + * There is a name clash with the official attributes TEE_ATTR_HKDF_SALT + * and TEE_ATTR_HKDF_INFO so define these alternative ID. + */ +#define __OPTEE_TEE_ATTR_HKDF_SALT 0xD00002C0 +#define __OPTEE_ATTR_HKDF_INFO 0xD00003C0 +#define TEE_ATTR_HKDF_OKM_LENGTH 0xF00004C0 + +/* + * Concatenation Key Derivation Function (Concat KDF) + * NIST SP 800-56A section 5.8.1 + */ + +#define TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY 0x800020C1 +#define TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY 0x800030C1 +#define TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY 0x800040C1 +#define TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY 0x800050C1 +#define TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY 0x800060C1 + +#define TEE_TYPE_CONCAT_KDF_Z 0xA10000C1 + +#define TEE_ATTR_CONCAT_KDF_Z 0xC00001C1 +#define TEE_ATTR_CONCAT_KDF_OTHER_INFO 0xD00002C1 +#define TEE_ATTR_CONCAT_KDF_DKM_LENGTH 0xF00003C1 + +/* + * PKCS #5 v2.0 Key Derivation Function 2 (PBKDF2) + * RFC 2898 section 5.2 + * https://www.ietf.org/rfc/rfc2898.txt + */ + +#define TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY 0x800020C2 + +#define TEE_TYPE_PBKDF2_PASSWORD 0xA10000C2 + +#define TEE_ATTR_PBKDF2_PASSWORD 0xC00001C2 +#define TEE_ATTR_PBKDF2_SALT 0xD00002C2 +#define TEE_ATTR_PBKDF2_ITERATION_COUNT 0xF00003C2 +#define TEE_ATTR_PBKDF2_DKM_LENGTH 0xF00004C2 + +/* + * PKCS#1 v1.5 RSASSA pre-hashed sign/verify + */ + +#define TEE_ALG_RSASSA_PKCS1_V1_5 0xF0000830 + +/* + * TDEA CMAC (NIST SP800-38B) + */ +#define TEE_ALG_DES3_CMAC 0xF0000613 + +/* + * SM4-XTS + */ +#define TEE_ALG_SM4_XTS 0xF0000414 + +/* + * Implementation-specific object storage constants + */ + +/* Storage is provided by the Rich Execution Environment (REE) */ +#define TEE_STORAGE_PRIVATE_REE 0x80000000 +/* Storage is the Replay Protected Memory Block partition of an eMMC device */ +#define TEE_STORAGE_PRIVATE_RPMB 0x80000100 +/* Was TEE_STORAGE_PRIVATE_SQL, which isn't supported any longer */ +#define TEE_STORAGE_PRIVATE_SQL_RESERVED 0x80000200 +/* Storage is the Replay Protected Memory Block partition of an NVMe device */ +#define TEE_STORAGE_PRIVATE_NVME_RPMB 0x80000400 + +/* + * Extension of "Memory Access Rights Constants" + * #define TEE_MEMORY_ACCESS_READ 0x00000001 + * #define TEE_MEMORY_ACCESS_WRITE 0x00000002 + * #define TEE_MEMORY_ACCESS_ANY_OWNER 0x00000004 + * + * TEE_MEMORY_ACCESS_NONSECURE : if set TEE_CheckMemoryAccessRights() + * successfully returns only if target vmem range is mapped non-secure. + * + * TEE_MEMORY_ACCESS_SECURE : if set TEE_CheckMemoryAccessRights() + * successfully returns only if target vmem range is mapped secure. + + */ +#define TEE_MEMORY_ACCESS_NONSECURE 0x10000000 +#define TEE_MEMORY_ACCESS_SECURE 0x20000000 + +/* + * Implementation-specific login types + */ + +/* Private login method for REE kernel clients */ +#define TEE_LOGIN_REE_KERNEL 0x80000000 + +#endif /* TEE_API_DEFINES_EXTENSIONS_H */ diff --git a/optee/optee_os/lib/libutee/include/tee_api_types.h b/optee/optee_os/lib/libutee/include/tee_api_types.h new file mode 100644 index 0000000..b78acd4 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_api_types.h @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* Based on GP TEE Internal API Specification Version 0.11 */ +#ifndef TEE_API_TYPES_H +#define TEE_API_TYPES_H + +#include +#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; + +typedef union { + struct { + void *buffer; + uint32_t size; + } memref; + struct { + uint32_t a; + uint32_t b; + } value; +} __GP11_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; + size_t dataSize; + size_t dataPosition; + uint32_t handleFlags; +} TEE_ObjectInfo; + +typedef struct { + uint32_t objectType; + __extension__ union { + uint32_t keySize; /* used in 1.1 spec */ + uint32_t objectSize; /* used in 1.1.1 spec */ + }; + __extension__ union { + uint32_t maxKeySize; /* used in 1.1 spec */ + uint32_t maxObjectSize; /* used in 1.1.1 spec */ + }; + uint32_t objectUsage; + uint32_t dataSize; + uint32_t dataPosition; + uint32_t handleFlags; +} __GP11_TEE_ObjectInfo; + +typedef uint32_t TEE_Whence; + +typedef struct { + uint32_t attributeID; + union { + struct { + void *buffer; + size_t length; + } ref; + struct { + uint32_t a, b; + } value; + } content; +} TEE_Attribute; + +typedef struct { + uint32_t attributeID; + union { + struct { + void *buffer; + uint32_t length; + } ref; + struct { + uint32_t a, b; + } value; + } content; +} __GP11_TEE_Attribute; + +/* Cryptographic Operations API */ + +typedef uint32_t 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; + +typedef struct { + uint32_t keySize; + uint32_t requiredKeyUsage; +} TEE_OperationInfoKey; + +typedef struct { + uint32_t algorithm; + uint32_t operationClass; + uint32_t mode; + uint32_t digestLength; + uint32_t maxKeySize; + uint32_t handleState; + uint32_t operationState; + uint32_t numberOfKeys; + TEE_OperationInfoKey keyInformation[]; +} TEE_OperationInfoMultiple; + +/* 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 __aligned(__alignof__(void *)); + +/* Tee Secure Element APIs */ + +typedef struct __TEE_SEServiceHandle *TEE_SEServiceHandle; +typedef struct __TEE_SEReaderHandle *TEE_SEReaderHandle; +typedef struct __TEE_SESessionHandle *TEE_SESessionHandle; +typedef struct __TEE_SEChannelHandle *TEE_SEChannelHandle; + +typedef struct { + bool sePresent; + bool teeOnly; + bool selectResponseEnable; +} TEE_SEReaderProperties; + +typedef struct { + uint8_t *buffer; + size_t bufferLen; +} TEE_SEAID; + +/* 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 + +#define TEE_SE_READER_NAME_MAX 20 + +#endif /* TEE_API_TYPES_H */ diff --git a/optee/optee_os/lib/libutee/include/tee_arith_internal.h b/optee/optee_os/lib/libutee/include/tee_arith_internal.h new file mode 100644 index 0000000..fc5678e --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_arith_internal.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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 + * + *************************************************************/ + +/************************************************************* + * + * 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/optee/optee_os/lib/libutee/include/tee_internal_api.h b/optee/optee_os/lib/libutee/include/tee_internal_api.h new file mode 100644 index 0000000..887b52f --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_internal_api.h @@ -0,0 +1,832 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* Based on GP TEE Internal API Specification Version 0.27 */ +#ifndef TEE_INTERNAL_API_H +#define TEE_INTERNAL_API_H + +#ifdef __TEE_API_COMPAT_H +#error " must not be included before " +#endif + +#include +#include +#include +#include +#include + +/* Property access functions */ + +TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, + const char *name, char *valueBuffer, + size_t *valueBufferLen); +TEE_Result __GP11_TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, + const char *name, char *valueBuffer, + uint32_t *valueBufferLen); + +TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, + const char *name, bool *value); + +TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, + const char *name, uint32_t *value); + +TEE_Result TEE_GetPropertyAsU64(TEE_PropSetHandle propsetOrEnumerator, + const char *name, uint64_t *value); + +TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, + const char *name, void *valueBuffer, + size_t *valueBufferLen); +TEE_Result +__GP11_TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, + const char *name, void *valueBuffer, + uint32_t *valueBufferLen); + +TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, + const char *name, TEE_UUID *value); + +TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, + const 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 __GP11_TEE_GetPropertyName(TEE_PropSetHandle enumerator, + void *nameBuffer, + uint32_t *nameBufferLen); + +TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator); + +/* System API - Misc */ + +void TEE_Panic(TEE_Result panicCode); + +/* System API - Internal Client API */ + +TEE_Result TEE_OpenTASession(const TEE_UUID *destination, + uint32_t cancellationRequestTimeout, + uint32_t paramTypes, + TEE_Param params[TEE_NUM_PARAMS], + TEE_TASessionHandle *session, + uint32_t *returnOrigin); +TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination, + uint32_t cancellationRequestTimeout, + uint32_t paramTypes, + __GP11_TEE_Param params[TEE_NUM_PARAMS], + 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[TEE_NUM_PARAMS], + uint32_t *returnOrigin); +TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session, + uint32_t cancellationRequestTimeout, + uint32_t commandID, uint32_t paramTypes, + __GP11_TEE_Param params[TEE_NUM_PARAMS], + 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); +TEE_Result __GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags, + void *buffer, uint32_t size); + +void TEE_SetInstanceData(const void *instanceData); + +const void *TEE_GetInstanceData(void); + +void *TEE_Malloc(size_t size, uint32_t hint); +void *__GP11_TEE_Malloc(uint32_t size, uint32_t hint); + +void *TEE_Realloc(void *buffer, size_t newSize); +void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize); + +void TEE_Free(void *buffer); + +void *TEE_MemMove(void *dest, const void *src, size_t size); +void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size); + +/* + * Note: TEE_MemCompare() has a constant-time implementation (execution time + * does not depend on buffer content but only on buffer size). It is the main + * difference with memcmp(). + */ +int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size); +int32_t __GP11_TEE_MemCompare(const void *buffer1, const void *buffer2, + uint32_t size); + +void TEE_MemFill(void *buff, uint32_t x, size_t size); +void __GP11_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 __GP11_TEE_GetObjectInfo(TEE_ObjectHandle object, + __GP11_TEE_ObjectInfo *objectInfo); + +TEE_Result TEE_GetObjectInfo1(TEE_ObjectHandle object, + TEE_ObjectInfo *objectInfo); +TEE_Result __GP11_TEE_GetObjectInfo1(TEE_ObjectHandle object, + __GP11_TEE_ObjectInfo *objectInfo); + +void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage); +TEE_Result TEE_RestrictObjectUsage1(TEE_ObjectHandle object, + uint32_t objectUsage); + +TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + uint32_t attributeID, void *buffer, + size_t *size); +TEE_Result __GP11_TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + uint32_t attributeID, + void *buffer, uint32_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); +TEE_Result __GP11_TEE_AllocateTransientObject(TEE_ObjectType objectType, + uint32_t maxKeySize, + TEE_ObjectHandle *object); + +void TEE_FreeTransientObject(TEE_ObjectHandle object); + +void TEE_ResetTransientObject(TEE_ObjectHandle object); + +TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, + const TEE_Attribute *attrs, + uint32_t attrCount); +TEE_Result __GP11_TEE_PopulateTransientObject(TEE_ObjectHandle object, + const __GP11_TEE_Attribute *attrs, + uint32_t attrCount); + +void TEE_InitRefAttribute(TEE_Attribute *attr, uint32_t attributeID, + const void *buffer, size_t length); +void __GP11_TEE_InitRefAttribute(__GP11_TEE_Attribute *attr, + uint32_t attributeID, + const void *buffer, uint32_t length); + +void TEE_InitValueAttribute(TEE_Attribute *attr, uint32_t attributeID, + uint32_t a, uint32_t b); +void __GP11_TEE_InitValueAttribute(__GP11_TEE_Attribute *attr, + uint32_t attributeID, + uint32_t a, uint32_t b); + +void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, + TEE_ObjectHandle srcObject); + +TEE_Result TEE_CopyObjectAttributes1(TEE_ObjectHandle destObject, + TEE_ObjectHandle srcObject); + +TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, + const TEE_Attribute *params, uint32_t paramCount); +TEE_Result __GP11_TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, + const __GP11_TEE_Attribute *params, + uint32_t paramCount); + +/* Data and Key Storage API - Persistent Object Functions */ + +TEE_Result TEE_OpenPersistentObject(uint32_t storageID, const void *objectID, + size_t objectIDLen, uint32_t flags, + TEE_ObjectHandle *object); +TEE_Result __GP11_TEE_OpenPersistentObject(uint32_t storageID, + const void *objectID, + uint32_t objectIDLen, uint32_t flags, + TEE_ObjectHandle *object); + +TEE_Result TEE_CreatePersistentObject(uint32_t storageID, const void *objectID, + size_t objectIDLen, uint32_t flags, + TEE_ObjectHandle attributes, + const void *initialData, + size_t initialDataLen, + TEE_ObjectHandle *object); +TEE_Result __GP11_TEE_CreatePersistentObject(uint32_t storageID, + const void *objectID, + uint32_t objectIDLen, + uint32_t flags, + TEE_ObjectHandle attributes, + const void *initialData, + uint32_t initialDataLen, + TEE_ObjectHandle *object); + +void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object); + +TEE_Result TEE_CloseAndDeletePersistentObject1(TEE_ObjectHandle object); + +TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, + const void *newObjectID, + size_t newObjectIDLen); +TEE_Result __GP11_TEE_RenamePersistentObject(TEE_ObjectHandle object, + const void *newObjectID, + uint32_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); +TEE_Result +__GP11_TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, + __GP11_TEE_ObjectInfo *objectInfo, + void *objectID, uint32_t *objectIDLen); + +/* Data and Key Storage API - Data Stream Access Functions */ + +TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, + size_t size, size_t *count); +TEE_Result __GP11_TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, + uint32_t size, uint32_t *count); + +TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, const void *buffer, + size_t size); +TEE_Result __GP11_TEE_WriteObjectData(TEE_ObjectHandle object, + const void *buffer, uint32_t size); + +TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, size_t size); +TEE_Result __GP11_TEE_TruncateObjectData(TEE_ObjectHandle object, + uint32_t size); + +TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, intmax_t offset, + TEE_Whence whence); +TEE_Result __GP11_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 __GP11_TEE_FreeOperation(TEE_OperationHandle operation); + +void TEE_GetOperationInfo(TEE_OperationHandle operation, + TEE_OperationInfo *operationInfo); + +TEE_Result +TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, + TEE_OperationInfoMultiple *operationInfoMultiple, + size_t *operationSize); +TEE_Result +__GP11_TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, + TEE_OperationInfoMultiple *info, + uint32_t *operationSize); + +void TEE_ResetOperation(TEE_OperationHandle operation); + +TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, + TEE_ObjectHandle key); +TEE_Result __GP11_TEE_SetOperationKey(TEE_OperationHandle operation, + TEE_ObjectHandle key); + +TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, TEE_ObjectHandle key2); +TEE_Result __GP11_TEE_SetOperationKey2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, + TEE_ObjectHandle key2); + +void TEE_CopyOperation(TEE_OperationHandle dstOperation, + TEE_OperationHandle srcOperation); + +TEE_Result TEE_IsAlgorithmSupported(uint32_t algId, uint32_t element); + +/* Cryptographic Operations API - Message Digest Functions */ + +void TEE_DigestUpdate(TEE_OperationHandle operation, + const void *chunk, size_t chunkSize); +void __GP11_TEE_DigestUpdate(TEE_OperationHandle operation, + const void *chunk, uint32_t chunkSize); + +TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, + size_t chunkLen, void *hash, size_t *hashLen); +TEE_Result __GP11_TEE_DigestDoFinal(TEE_OperationHandle operation, + const void *chunk, uint32_t chunkLen, + void *hash, uint32_t *hashLen); + +TEE_Result TEE_DigestExtract(TEE_OperationHandle operation, void *hash, + size_t *hashLen); + +/* Cryptographic Operations API - Symmetric Cipher Functions */ + +void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, + size_t IVLen); +void __GP11_TEE_CipherInit(TEE_OperationHandle operation, const void *IV, + uint32_t IVLen); + +TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, + size_t srcLen, void *destData, size_t *destLen); +TEE_Result __GP11_TEE_CipherUpdate(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen); + +TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, + const void *srcData, size_t srcLen, + void *destData, size_t *destLen); +TEE_Result __GP11_TEE_CipherDoFinal(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen); + +/* Cryptographic Operations API - MAC Functions */ + +void TEE_MACInit(TEE_OperationHandle operation, const void *IV, + size_t IVLen); +void __GP11_TEE_MACInit(TEE_OperationHandle operation, const void *IV, + uint32_t IVLen); + +void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, + size_t chunkSize); +void __GP11_TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, + uint32_t chunkSize); + +TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, + const void *message, size_t messageLen, + void *mac, size_t *macLen); +TEE_Result __GP11_TEE_MACComputeFinal(TEE_OperationHandle operation, + const void *message, uint32_t messageLen, + void *mac, uint32_t *macLen); + +TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, + const void *message, size_t messageLen, + const void *mac, size_t macLen); +TEE_Result __GP11_TEE_MACCompareFinal(TEE_OperationHandle operation, + const void *message, uint32_t messageLen, + const void *mac, uint32_t macLen); + +/* Cryptographic Operations API - Authenticated Encryption Functions */ + +TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, + size_t nonceLen, uint32_t tagLen, size_t AADLen, + size_t payloadLen); +TEE_Result __GP11_TEE_AEInit(TEE_OperationHandle operation, const void *nonce, + uint32_t nonceLen, uint32_t tagLen, + uint32_t AADLen, uint32_t payloadLen); + +void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, + size_t AADdataLen); +void __GP11_TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, + uint32_t AADdataLen); + +TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, + size_t srcLen, void *destData, size_t *destLen); +TEE_Result __GP11_TEE_AEUpdate(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_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 __GP11_TEE_AEEncryptFinal(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen, + void *tag, uint32_t *tagLen); + +TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, + const void *srcData, size_t srcLen, + void *destData, size_t *destLen, void *tag, + size_t tagLen); +TEE_Result __GP11_TEE_AEDecryptFinal(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen, + void *tag, uint32_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 __GP11_TEE_AsymmetricEncrypt(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, + const void *srcData, uint32_t srcLen, + void *destData, uint32_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 __GP11_TEE_AsymmetricDecrypt(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, + const void *srcData, uint32_t srcLen, + void *destData, uint32_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 __GP11_TEE_AsymmetricSignDigest(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, + const void *digest, + uint32_t digestLen, void *signature, + uint32_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); +TEE_Result __GP11_TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, + const void *digest, + uint32_t digestLen, + const void *signature, + uint32_t signatureLen); + +/* Cryptographic Operations API - Key Derivation Functions */ + +void TEE_DeriveKey(TEE_OperationHandle operation, + const TEE_Attribute *params, uint32_t paramCount, + TEE_ObjectHandle derivedKey); +void __GP11_TEE_DeriveKey(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, TEE_ObjectHandle derivedKey); + +/* Cryptographic Operations API - Random Number Generation Functions */ + +void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen); +void __GP11_TEE_GenerateRandom(void *randomBuffer, uint32_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); +uint32_t __GP11_TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits); + +size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits); +uint32_t __GP11_TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits); + +/* TEE Arithmetical API - Initialization functions */ + +void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len); +void __GP11_TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len); + +void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, size_t len, + const TEE_BigInt *modulus); +void __GP11_TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, + uint32_t len, const TEE_BigInt *modulus); + +TEE_Result TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext *context, + size_t len, const TEE_BigInt *modulus); + +void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, size_t len); +void __GP11_TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_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 __GP11_TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, + const uint8_t *buffer, + uint32_t bufferLen, + int32_t sign); + +TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, size_t *bufferLen, + const TEE_BigInt *bigInt); +TEE_Result __GP11_TEE_BigIntConvertToOctetString(uint8_t *buffer, + uint32_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); + +/* 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); +void __GP11_TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, + uint32_t bits); + +bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex); + +uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src); + +TEE_Result TEE_BigIntSetBit(TEE_BigInt *op, uint32_t bitIndex, bool value); + +TEE_Result TEE_BigIntAssign(TEE_BigInt *dest, const TEE_BigInt *src); + +TEE_Result TEE_BigIntAbs(TEE_BigInt *dest, 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); + +/* 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_Result TEE_BigIntExpMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n, + const TEE_BigIntFMMContext *context); + +/* 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); + +#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[TEE_NUM_PARAMS], + void **sessionContext); +TEE_Result TA_EXPORT +__GP11_TA_OpenSessionEntryPoint(uint32_t paramTypes, + __GP11_TEE_Param params[TEE_NUM_PARAMS], + 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[TEE_NUM_PARAMS]); +TEE_Result TA_EXPORT +__GP11_TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID, + uint32_t paramTypes, + __GP11_TEE_Param params[TEE_NUM_PARAMS]); + +/* + * Matching 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. + */ + +#include + +#endif /*TEE_INTERNAL_API_H*/ diff --git a/optee/optee_os/lib/libutee/include/tee_internal_api_extensions.h b/optee/optee_os/lib/libutee/include/tee_internal_api_extensions.h new file mode 100644 index 0000000..78b0e39 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_internal_api_extensions.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#ifndef TEE_INTERNAL_API_EXTENSIONS_H +#define TEE_INTERNAL_API_EXTENSIONS_H + +/* trace support */ +#include +#include +#include +#include + +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 + +/* + * Cache maintenance support (TA requires the CACHE_MAINTENANCE property) + * + * TEE_CacheClean() Write back to memory any dirty data cache lines. The line + * is marked as not dirty. The valid bit is unchanged. + * + * TEE_CacheFlush() Purges any valid data cache lines. Any dirty cache lines + * are first written back to memory, then the cache line is + * invalidated. + * + * TEE_CacheInvalidate() Invalidate any valid data cache lines. Any dirty line + * are not written back to memory. + */ +TEE_Result TEE_CacheClean(char *buf, size_t len); +TEE_Result TEE_CacheFlush(char *buf, size_t len); +TEE_Result TEE_CacheInvalidate(char *buf, size_t len); + +/* + * tee_map_zi() - Map zero initialized memory + * @len: Number of bytes + * @flags: 0 or TEE_MEMORY_ACCESS_ANY_OWNER to allow sharing with other TAs + * + * Returns valid pointer on success or NULL on error. + */ +void *tee_map_zi(size_t len, uint32_t flags); + +/* + * tee_unmap() - Unmap previously mapped memory + * @buf: Buffer + * @len: Number of bytes + * + * Note that supplied @buf and @len has to match exactly what has + * previously been returned by tee_map_zi(). + * + * Return TEE_SUCCESS on success or TEE_ERRROR_* on failure. + */ +TEE_Result tee_unmap(void *buf, size_t len); + +/* + * Convert a UUID string @s into a TEE_UUID @uuid + * Expected format for @s is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + * 'x' being any hexadecimal digit (0-9a-fA-F) + */ +TEE_Result tee_uuid_from_str(TEE_UUID *uuid, const char *s); + +/* + * tee_invoke_supp_plugin() - invoke a tee-supplicant's plugin + * @uuid: uuid of the plugin + * @cmd: command for the plugin + * @sub_cmd: subcommand for the plugin + * @buf: data [for/from] the plugin [in/out] + * @len: length of the input buf + * @outlen: pointer to length of the output data (if they will be used) + * + * Return TEE_SUCCESS on success or TEE_ERRROR_* on failure. + */ +TEE_Result tee_invoke_supp_plugin(const TEE_UUID *uuid, uint32_t cmd, + uint32_t sub_cmd, void *buf, size_t len, + size_t *outlen); + +#endif diff --git a/optee/optee_os/lib/libutee/include/tee_isocket.h b/optee/optee_os/lib/libutee/include/tee_isocket.h new file mode 100644 index 0000000..d87c204 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_isocket.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#ifndef __TEE_ISOCKET_H +#define __TEE_ISOCKET_H + +#include +#include +#include <__tee_isocket_defines.h> + +typedef void *TEE_iSocketHandle; + +typedef const struct TEE_iSocket_s { + uint32_t TEE_iSocketVersion; + uint8_t protocolID; + TEE_Result (*open)(TEE_iSocketHandle *ctx, void *setup, + uint32_t *protocolError); + + TEE_Result (*close)(TEE_iSocketHandle ctx); + + TEE_Result (*send)(TEE_iSocketHandle ctx, const void *buf, + uint32_t *length, uint32_t timeout); + + TEE_Result (*recv)(TEE_iSocketHandle ctx, void *buf, uint32_t *length, + uint32_t timeout); + + uint32_t (*error)(TEE_iSocketHandle ctx); + + TEE_Result (*ioctl)(TEE_iSocketHandle ctx, uint32_t commandCode, + void *buf, uint32_t *length); +} TEE_iSocket; + +#endif /*__TEE_ISOCKET_H*/ diff --git a/optee/optee_os/lib/libutee/include/tee_syscall_numbers.h b/optee/optee_os/lib/libutee/include/tee_syscall_numbers.h new file mode 100644 index 0000000..82d429b --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_syscall_numbers.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#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_GET_PROPERTY 3 +#define TEE_SCN_GET_PROPERTY_NAME_TO_INDEX 4 +#define TEE_SCN_OPEN_TA_SESSION 5 +#define TEE_SCN_CLOSE_TA_SESSION 6 +#define TEE_SCN_INVOKE_TA_COMMAND 7 +#define TEE_SCN_CHECK_ACCESS_RIGHTS 8 +#define TEE_SCN_GET_CANCELLATION_FLAG 9 +#define TEE_SCN_UNMASK_CANCELLATION 10 +#define TEE_SCN_MASK_CANCELLATION 11 +#define TEE_SCN_WAIT 12 +#define TEE_SCN_GET_TIME 13 +#define TEE_SCN_SET_TA_TIME 14 +#define TEE_SCN_CRYP_STATE_ALLOC 15 +#define TEE_SCN_CRYP_STATE_COPY 16 +#define TEE_SCN_CRYP_STATE_FREE 17 +#define TEE_SCN_HASH_INIT 18 +#define TEE_SCN_HASH_UPDATE 19 +#define TEE_SCN_HASH_FINAL 20 +#define TEE_SCN_CIPHER_INIT 21 +#define TEE_SCN_CIPHER_UPDATE 22 +#define TEE_SCN_CIPHER_FINAL 23 +#define TEE_SCN_CRYP_OBJ_GET_INFO 24 +#define TEE_SCN_CRYP_OBJ_RESTRICT_USAGE 25 +#define TEE_SCN_CRYP_OBJ_GET_ATTR 26 +#define TEE_SCN_CRYP_OBJ_ALLOC 27 +#define TEE_SCN_CRYP_OBJ_CLOSE 28 +#define TEE_SCN_CRYP_OBJ_RESET 29 +#define TEE_SCN_CRYP_OBJ_POPULATE 30 +#define TEE_SCN_CRYP_OBJ_COPY 31 +#define TEE_SCN_CRYP_DERIVE_KEY 32 +#define TEE_SCN_CRYP_RANDOM_NUMBER_GENERATE 33 +#define TEE_SCN_AUTHENC_INIT 34 +#define TEE_SCN_AUTHENC_UPDATE_AAD 35 +#define TEE_SCN_AUTHENC_UPDATE_PAYLOAD 36 +#define TEE_SCN_AUTHENC_ENC_FINAL 37 +#define TEE_SCN_AUTHENC_DEC_FINAL 38 +#define TEE_SCN_ASYMM_OPERATE 39 +#define TEE_SCN_ASYMM_VERIFY 40 +#define TEE_SCN_STORAGE_OBJ_OPEN 41 +#define TEE_SCN_STORAGE_OBJ_CREATE 42 +#define TEE_SCN_STORAGE_OBJ_DEL 43 +#define TEE_SCN_STORAGE_OBJ_RENAME 44 +#define TEE_SCN_STORAGE_ENUM_ALLOC 45 +#define TEE_SCN_STORAGE_ENUM_FREE 46 +#define TEE_SCN_STORAGE_ENUM_RESET 47 +#define TEE_SCN_STORAGE_ENUM_START 48 +#define TEE_SCN_STORAGE_ENUM_NEXT 49 +#define TEE_SCN_STORAGE_OBJ_READ 50 +#define TEE_SCN_STORAGE_OBJ_WRITE 51 +#define TEE_SCN_STORAGE_OBJ_TRUNC 52 +#define TEE_SCN_STORAGE_OBJ_SEEK 53 +#define TEE_SCN_CRYP_OBJ_GENERATE_KEY 54 +/* Deprecated Secure Element API syscalls return TEE_ERROR_NOT_SUPPORTED */ +#define TEE_SCN_SE_SERVICE_OPEN__DEPRECATED 55 +#define TEE_SCN_SE_SERVICE_CLOSE__DEPRECATED 56 +#define TEE_SCN_SE_SERVICE_GET_READERS__DEPRECATED 57 +#define TEE_SCN_SE_READER_GET_PROP__DEPRECATED 58 +#define TEE_SCN_SE_READER_GET_NAME__DEPRECATED 59 +#define TEE_SCN_SE_READER_OPEN_SESSION__DEPRECATED 60 +#define TEE_SCN_SE_READER_CLOSE_SESSIONS__DEPRECATED 61 +#define TEE_SCN_SE_SESSION_IS_CLOSED__DEPRECATED 62 +#define TEE_SCN_SE_SESSION_GET_ATR__DEPRECATED 63 +#define TEE_SCN_SE_SESSION_OPEN_CHANNEL__DEPRECATED 64 +#define TEE_SCN_SE_SESSION_CLOSE__DEPRECATED 65 +#define TEE_SCN_SE_CHANNEL_SELECT_NEXT__DEPRECATED 66 +#define TEE_SCN_SE_CHANNEL_GET_SELECT_RESP__DEPRECATED 67 +#define TEE_SCN_SE_CHANNEL_TRANSMIT__DEPRECATED 68 +#define TEE_SCN_SE_CHANNEL_CLOSE__DEPRECATED 69 +/* End of deprecated Secure Element API syscalls */ +#define TEE_SCN_CACHE_OPERATION 70 + +#define TEE_SCN_MAX 70 + +/* Maximum number of allowed arguments for a syscall */ +#define TEE_SVC_MAX_ARGS 8 + +#endif /* TEE_SYSCALL_NUMBERS_H */ diff --git a/optee/optee_os/lib/libutee/include/tee_ta_api.h b/optee/optee_os/lib/libutee/include/tee_ta_api.h new file mode 100644 index 0000000..84d2084 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_ta_api.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* Based on GP TEE Internal API Specification Version 0.22 */ +#ifndef TEE_TA_API_H +#define TEE_TA_API_H + +#include + +#endif diff --git a/optee/optee_os/lib/libutee/include/tee_tcpsocket.h b/optee/optee_os/lib/libutee/include/tee_tcpsocket.h new file mode 100644 index 0000000..c80c243 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_tcpsocket.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#ifndef __TEE_TCPSOCKET_H +#define __TEE_TCPSOCKET_H + +#include +#include <__tee_ipsocket.h> +#include <__tee_tcpsocket_defines.h> + +typedef struct TEE_tcpSocket_Setup_s { + TEE_ipSocket_ipVersion ipVersion; + char *server_addr; + uint16_t server_port; +} TEE_tcpSocket_Setup; + +extern TEE_iSocket *const TEE_tcpSocket; + +#endif /*__TEE_TCPSOCKET_H*/ diff --git a/optee/optee_os/lib/libutee/include/tee_udpsocket.h b/optee/optee_os/lib/libutee/include/tee_udpsocket.h new file mode 100644 index 0000000..83563e7 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/tee_udpsocket.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#ifndef __TEE_UDPSOCKET_H +#define __TEE_UDPSOCKET_H + +#include +#include <__tee_ipsocket.h> +#include <__tee_udpsocket_defines.h> + +typedef struct TEE_udpSocket_Setup_s { + TEE_ipSocket_ipVersion ipVersion; + char *server_addr; + uint16_t server_port; +} TEE_udpSocket_Setup; + +extern TEE_iSocket *const TEE_udpSocket; + +#endif /*__TEE_UDPSOCKET_H*/ diff --git a/optee/optee_os/lib/libutee/include/user_ta_header.h b/optee/optee_os/lib/libutee/include/user_ta_header.h new file mode 100644 index 0000000..30aa641 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/user_ta_header.h @@ -0,0 +1,153 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2018, Linaro Limited. + */ + +#ifndef USER_TA_HEADER_H +#define USER_TA_HEADER_H + +#include +#include + +#define TA_FLAG_USER_MODE 0 /* Deprecated, was BIT32(0) */ +#define TA_FLAG_EXEC_DDR 0 /* Deprecated, was BIT32(1) */ +#define TA_FLAG_SINGLE_INSTANCE BIT32(2) +#define TA_FLAG_MULTI_SESSION BIT32(3) +#define TA_FLAG_INSTANCE_KEEP_ALIVE BIT32(4) /* remains after last close */ +#define TA_FLAG_SECURE_DATA_PATH BIT32(5) /* accesses SDP memory */ +#define TA_FLAG_REMAP_SUPPORT 0 /* Deprecated, was BIT32(6) */ +#define TA_FLAG_CACHE_MAINTENANCE BIT32(7) /* use cache flush syscall */ + /* + * TA instance can execute multiple sessions concurrently + * (pseudo-TAs only). + */ +#define TA_FLAG_CONCURRENT BIT32(8) + /* + * Device enumeration is done in two stages by the normal world, first + * before the tee-supplicant has started and then once more when the + * tee-supplicant is started. The flags below control if the TA should + * be reported in the first or second or case. + */ +#define TA_FLAG_DEVICE_ENUM BIT32(9) /* without tee-supplicant */ +#define TA_FLAG_DEVICE_ENUM_SUPP BIT32(10) /* with tee-supplicant */ + /* See also "gpd.ta.doesNotCloseHandleOnCorruptObject" */ +#define TA_FLAG_DONT_CLOSE_HANDLE_ON_CORRUPT_OBJECT \ + BIT32(11) + +#define TA_FLAGS_MASK GENMASK_32(10, 0) + +struct ta_head { + TEE_UUID uuid; + uint32_t stack_size; + uint32_t flags; + uint64_t depr_entry; +}; + +#if defined(CFG_FTRACE_SUPPORT) +#define FTRACE_RETFUNC_DEPTH 50 +union compat_ptr { + uint64_t ptr64; + struct { + uint32_t lo; + uint32_t hi; + } ptr32; +}; + +struct __ftrace_info { + union compat_ptr buf_start; + union compat_ptr buf_end; + union compat_ptr ret_ptr; +}; + +struct ftrace_buf { + uint64_t ret_func_ptr; /* __ftrace_return pointer */ + uint64_t ret_stack[FTRACE_RETFUNC_DEPTH]; /* Return stack */ + uint32_t ret_idx; /* Return stack index */ + uint32_t lr_idx; /* lr index used for stack unwinding */ + uint64_t begin_time[FTRACE_RETFUNC_DEPTH]; /* Timestamp */ + uint64_t suspend_time; /* Suspend timestamp */ + uint32_t curr_size; /* Size of ftrace buffer */ + uint32_t max_size; /* Max allowed size of ftrace buffer */ + uint32_t head_off; /* Ftrace buffer header offset */ + uint32_t buf_off; /* Ftrace buffer offset */ + bool syscall_trace_enabled; /* Some syscalls are never traced */ + bool syscall_trace_suspended; /* By foreign interrupt or RPC */ +}; + +/* Defined by the linker script */ +extern struct ftrace_buf __ftrace_buf_start; +extern uint8_t __ftrace_buf_end[]; + +unsigned long ftrace_return(void); +void __ftrace_return(void); +#endif + +void __utee_call_elf_init_fn(void); +void __utee_call_elf_fini_fn(void); + +void __utee_tcb_init(void); + +/* + * Information about the ELF objects loaded by the application + */ + +struct __elf_phdr_info { + uint32_t reserved; + uint16_t count; + uint8_t reserved2; + char zero; + struct dl_phdr_info *dlpi; /* @count entries */ +}; + +/* 32-bit variant for a 64-bit ldelf to access a 32-bit TA */ +struct __elf_phdr_info32 { + uint32_t reserved; + uint16_t count; + uint8_t reserved2; + char zero; + uint32_t dlpi; +}; + +extern struct __elf_phdr_info __elf_phdr_info; + +#define TA_PROP_STR_SINGLE_INSTANCE "gpd.ta.singleInstance" +#define TA_PROP_STR_MULTI_SESSION "gpd.ta.multiSession" +#define TA_PROP_STR_KEEP_ALIVE "gpd.ta.instanceKeepAlive" +#define TA_PROP_STR_DATA_SIZE "gpd.ta.dataSize" +#define TA_PROP_STR_STACK_SIZE "gpd.ta.stackSize" +#define TA_PROP_STR_VERSION "gpd.ta.version" +#define TA_PROP_STR_DESCRIPTION "gpd.ta.description" +#define TA_PROP_STR_ENDIAN "gpd.ta.endian" +#define TA_PROP_STR_DOES_NOT_CLOSE_HANDLE_ON_CORRUPT_OBJECT \ + "gpd.ta.doesNotCloseHandleOnCorruptObject" + +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 */ + USER_TA_PROP_TYPE_U64, /* uint64_t */ +}; + +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; + +extern uint8_t __ta_no_share_heap[]; +extern const size_t __ta_no_share_heap_size; +/* Needed by TEE_CheckMemoryAccessRights() */ +extern uint32_t ta_param_types; +extern TEE_Param ta_params[TEE_NUM_PARAMS]; +extern struct malloc_ctx *__ta_no_share_malloc_ctx; + +int tahead_get_trace_level(void); + +#endif /* USER_TA_HEADER_H */ diff --git a/optee/optee_os/lib/libutee/include/utee_defines.h b/optee/optee_os/lib/libutee/include/utee_defines.h new file mode 100644 index 0000000..564bd23 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/utee_defines.h @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2021, SumUp Services GmbH + */ +#ifndef UTEE_DEFINES_H +#define UTEE_DEFINES_H + +#include +#include +#include +#include + +/* + * 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_SM3 0x07 +#define TEE_MAIN_ALGO_SHA3_224 0x08 +#define TEE_MAIN_ALGO_SHA3_256 0x09 +#define TEE_MAIN_ALGO_SHA3_384 0x0A +#define TEE_MAIN_ALGO_SHA3_512 0x0B +#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_SM4 0x14 /* Not in v1.2, extrapolated */ +#define TEE_MAIN_ALGO_RSA 0x30 +#define TEE_MAIN_ALGO_DSA 0x31 +#define TEE_MAIN_ALGO_DH 0x32 +#define TEE_MAIN_ALGO_ECDSA 0x41 +#define TEE_MAIN_ALGO_ECDH 0x42 +#define TEE_MAIN_ALGO_ED25519 0x43 +#define TEE_MAIN_ALGO_SM2_DSA_SM3 0x45 /* Not in v1.2 spec */ +#define TEE_MAIN_ALGO_SM2_KEP 0x46 /* Not in v1.2 spec */ +#define TEE_MAIN_ALGO_SM2_PKE 0x47 /* Not in v1.2 spec */ +#define TEE_MAIN_ALGO_HKDF 0xC0 /* OP-TEE extension */ +#define TEE_MAIN_ALGO_CONCAT_KDF 0xC1 /* OP-TEE extension */ +#define TEE_MAIN_ALGO_PBKDF2 0xC2 /* OP-TEE extension */ +#define TEE_MAIN_ALGO_X25519 0x44 /* Not in v1.2 spec */ +#define TEE_MAIN_ALGO_SHAKE128 0xC3 /* OP-TEE extension */ +#define TEE_MAIN_ALGO_SHAKE256 0xC4 /* OP-TEE extension */ + + +#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 /* ??? */ + + +static inline uint32_t __tee_alg_get_class(uint32_t algo) +{ + if (algo == TEE_ALG_SM2_PKE) + return TEE_OPERATION_ASYMMETRIC_CIPHER; + if (algo == TEE_ALG_SM2_KEP) + return TEE_OPERATION_KEY_DERIVATION; + if (algo == TEE_ALG_RSASSA_PKCS1_V1_5) + return TEE_OPERATION_ASYMMETRIC_SIGNATURE; + if (algo == TEE_ALG_DES3_CMAC) + return TEE_OPERATION_MAC; + if (algo == TEE_ALG_SM4_XTS) + return TEE_OPERATION_CIPHER; + if (algo == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5) + return TEE_OPERATION_ASYMMETRIC_SIGNATURE; + if (algo == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5) + return TEE_OPERATION_ASYMMETRIC_CIPHER; + + return (algo >> 28) & 0xF; /* Bits [31:28] */ +} + +#define TEE_ALG_GET_CLASS(algo) __tee_alg_get_class(algo) + +static inline uint32_t __tee_alg_get_main_alg(uint32_t algo) +{ + switch (algo) { + case TEE_ALG_SM2_PKE: + return TEE_MAIN_ALGO_SM2_PKE; + case TEE_ALG_SM2_KEP: + return TEE_MAIN_ALGO_SM2_KEP; + case TEE_ALG_X25519: + return TEE_MAIN_ALGO_X25519; + case TEE_ALG_ED25519: + return TEE_MAIN_ALGO_ED25519; + case TEE_ALG_ECDSA_SHA1: + case TEE_ALG_ECDSA_SHA224: + case TEE_ALG_ECDSA_SHA256: + case TEE_ALG_ECDSA_SHA384: + case TEE_ALG_ECDSA_SHA512: + return TEE_MAIN_ALGO_ECDSA; + case TEE_ALG_HKDF: + return TEE_MAIN_ALGO_HKDF; + case TEE_ALG_SHAKE128: + return TEE_MAIN_ALGO_SHAKE128; + case TEE_ALG_SHAKE256: + return TEE_MAIN_ALGO_SHAKE256; + default: + break; + } + + return algo & 0xff; +} + +#define TEE_ALG_GET_MAIN_ALG(algo) __tee_alg_get_main_alg(algo) + + /* Bits [11:8] */ +#define TEE_ALG_GET_CHAIN_MODE(algo) (((algo) >> 8) & 0xF) + +/* + * Value not defined in the GP spec, and not used as bits 15-12 of any TEE_ALG* + * value. TEE_ALG_SM2_DSA_SM3 has value 0x6 for bits 15-12 which would yield the + * SHA512 digest if we were to apply the bit masks that were valid up to the TEE + * Internal Core API v1.1. + */ +#define __TEE_MAIN_HASH_SM3 0x7 + +static inline uint32_t __tee_alg_get_digest_hash(uint32_t algo) +{ + if (algo == TEE_ALG_SM2_DSA_SM3) + return __TEE_MAIN_HASH_SM3; + + /* Bits [15:12] */ + return (algo >> 12) & 0xF; +} + +#define TEE_ALG_GET_DIGEST_HASH(algo) __tee_alg_get_digest_hash(algo) + + /* Bits [23:20] */ +#define TEE_ALG_GET_INTERNAL_HASH(algo) (((algo) >> 20) & 0x7) + +static inline uint32_t __tee_alg_get_key_type(uint32_t algo, bool with_priv) +{ + uint32_t key_type = 0xA0000000 | TEE_ALG_GET_MAIN_ALG(algo); + + if (with_priv) + key_type |= 0x01000000; + + return key_type; +} + +#define TEE_ALG_GET_KEY_TYPE(algo, with_private_key) \ + __tee_alg_get_key_type(algo, with_private_key) + +static inline uint32_t __tee_alg_hash_algo(uint32_t main_hash) +{ + if (main_hash == __TEE_MAIN_HASH_SM3) + return TEE_ALG_SM3; + + return (TEE_OPERATION_DIGEST << 28) | main_hash; +} + + /* Return hash algorithm based on main hash */ +#define TEE_ALG_HASH_ALGO(main_hash) __tee_alg_hash_algo(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)) + +/* Return HMAC algorithm based on main hash */ +#define TEE_ALG_HMAC_ALGO(main_hash) \ + (TEE_OPERATION_MAC << 28 | (main_hash)) + +#define TEE_AES_BLOCK_SIZE 16UL +#define TEE_DES_BLOCK_SIZE 8UL +#define TEE_SM4_BLOCK_SIZE 16UL + +#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_SM3_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 + +static inline size_t __tee_alg_get_digest_size(uint32_t algo) +{ + switch (algo) { + case TEE_ALG_MD5: + case TEE_ALG_HMAC_MD5: + return TEE_MD5_HASH_SIZE; + case TEE_ALG_SHA1: + case TEE_ALG_HMAC_SHA1: + case TEE_ALG_DSA_SHA1: + case TEE_ALG_ECDSA_SHA1: + return TEE_SHA1_HASH_SIZE; + case TEE_ALG_SHA224: + case TEE_ALG_SHA3_224: + case TEE_ALG_HMAC_SHA224: + case TEE_ALG_HMAC_SHA3_224: + case TEE_ALG_DSA_SHA224: + case TEE_ALG_ECDSA_SHA224: + return TEE_SHA224_HASH_SIZE; + case TEE_ALG_SHA256: + case TEE_ALG_SHA3_256: + case TEE_ALG_HMAC_SHA256: + case TEE_ALG_HMAC_SHA3_256: + case TEE_ALG_DSA_SHA256: + case TEE_ALG_ECDSA_SHA256: + return TEE_SHA256_HASH_SIZE; + case TEE_ALG_SHA384: + case TEE_ALG_SHA3_384: + case TEE_ALG_HMAC_SHA384: + case TEE_ALG_HMAC_SHA3_384: + case TEE_ALG_ECDSA_SHA384: + return TEE_SHA384_HASH_SIZE; + case TEE_ALG_SHA512: + case TEE_ALG_SHA3_512: + case TEE_ALG_HMAC_SHA512: + case TEE_ALG_HMAC_SHA3_512: + case TEE_ALG_ECDSA_SHA512: + return TEE_SHA512_HASH_SIZE; + case TEE_ALG_SM3: + case TEE_ALG_HMAC_SM3: + return TEE_SM3_HASH_SIZE; + case TEE_ALG_AES_CBC_MAC_NOPAD: + case TEE_ALG_AES_CBC_MAC_PKCS5: + case TEE_ALG_AES_CMAC: + return TEE_AES_BLOCK_SIZE; + 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: + case TEE_ALG_DES3_CMAC: + return TEE_DES_BLOCK_SIZE; + default: + return 0; + } +} + + /* Return algorithm digest size */ +#define TEE_ALG_GET_DIGEST_SIZE(algo) __tee_alg_get_digest_size(algo) + +/* + * Bit indicating that the attribute is a value attribute + * See TEE Internal API specificaion v1.0 table 6-12 "Partial Structure of + * Attribute Identifier" + */ + + +#ifdef __compiler_bswap64 +#define TEE_U64_BSWAP(x) __compiler_bswap64((x)) +#else +#define TEE_U64_BSWAP(x) ((uint64_t)( \ + (((uint64_t)(x) & UINT64_C(0xff00000000000000ULL)) >> 56) | \ + (((uint64_t)(x) & UINT64_C(0x00ff000000000000ULL)) >> 40) | \ + (((uint64_t)(x) & UINT64_C(0x0000ff0000000000ULL)) >> 24) | \ + (((uint64_t)(x) & UINT64_C(0x000000ff00000000ULL)) >> 8) | \ + (((uint64_t)(x) & UINT64_C(0x00000000ff000000ULL)) << 8) | \ + (((uint64_t)(x) & UINT64_C(0x0000000000ff0000ULL)) << 24) | \ + (((uint64_t)(x) & UINT64_C(0x000000000000ff00ULL)) << 40) | \ + (((uint64_t)(x) & UINT64_C(0x00000000000000ffULL)) << 56))) +#endif + +#ifdef __compiler_bswap32 +#define TEE_U32_BSWAP(x) __compiler_bswap32((x)) +#else +#define TEE_U32_BSWAP(x) ((uint32_t)( \ + (((uint32_t)(x) & UINT32_C(0xff000000)) >> 24) | \ + (((uint32_t)(x) & UINT32_C(0x00ff0000)) >> 8) | \ + (((uint32_t)(x) & UINT32_C(0x0000ff00)) << 8) | \ + (((uint32_t)(x) & UINT32_C(0x000000ff)) << 24))) +#endif + +#ifdef __compiler_bswap16 +#define TEE_U16_BSWAP(x) __compiler_bswap16((x)) +#else +#define TEE_U16_BSWAP(x) ((uint16_t)( \ + (((uint16_t)(x) & UINT16_C(0xff00)) >> 8) | \ + (((uint16_t)(x) & UINT16_C(0x00ff)) << 8))) +#endif + +/* If we we're on a big endian platform we'll have to update these */ +#define TEE_U64_FROM_BIG_ENDIAN(x) TEE_U64_BSWAP(x) +#define TEE_U32_FROM_BIG_ENDIAN(x) TEE_U32_BSWAP(x) +#define TEE_U16_FROM_BIG_ENDIAN(x) TEE_U16_BSWAP(x) +#define TEE_U64_TO_BIG_ENDIAN(x) TEE_U64_BSWAP(x) +#define TEE_U32_TO_BIG_ENDIAN(x) TEE_U32_BSWAP(x) +#define TEE_U16_TO_BIG_ENDIAN(x) TEE_U16_BSWAP(x) + +#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) + +#define UTEE_SE_READER_PRESENT (1 << 0) +#define UTEE_SE_READER_TEE_ONLY (1 << 1) +#define UTEE_SE_READER_SELECT_RESPONE_ENABLE (1 << 2) + +#endif /* UTEE_DEFINES_H */ diff --git a/optee/optee_os/lib/libutee/include/utee_syscalls.h b/optee/optee_os/lib/libutee/include/utee_syscalls.h new file mode 100644 index 0000000..e83f803 --- /dev/null +++ b/optee/optee_os/lib/libutee/include/utee_syscalls.h @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef UTEE_SYSCALLS_H +#define UTEE_SYSCALLS_H + +#include +#include +#include + +#include +#include +#include + +/* + * Arguments must use the native register width, unless it's a signed + * argument then it must be a 32-bit value instead to avoid problems with + * sign extension. To keep it simple, only use pointers, int32_t, unsigned + * long and size_t. Pointers may only point structures or types based on + * fixed width integer types. Only exception are buffers with opaque data. + * + * Return values should not use a fixed width larger than 32 bits, unsigned + * long and pointers are OK though. + * + * Members in structs on the other hand should only use fixed width integer + * types; uint32_t, uint64_t etc. To keep it simple, use uint64_t for all + * length fields. + */ + +void _utee_return(unsigned long ret) __noreturn; + +void _utee_log(const void *buf, size_t len); + +/* This is not __noreturn because AArch32 stack unwinding fails otherwise */ +void _utee_panic(unsigned long code); + +/* prop_set is TEE_PROPSET_xxx*/ +TEE_Result _utee_get_property(unsigned long prop_set, unsigned long index, + void *name, uint32_t *name_len, void *buf, + uint32_t *blen, uint32_t *prop_type); + +TEE_Result _utee_get_property_name_to_index(unsigned long prop_set, + const void *name, + unsigned long name_len, + uint32_t *index); + +/* sess has type TEE_TASessionHandle */ +TEE_Result _utee_open_ta_session(const TEE_UUID *dest, + unsigned long cancel_req_to, + struct utee_params *params, uint32_t *sess, + uint32_t *ret_orig); + +/* sess has type TEE_TASessionHandle */ +TEE_Result _utee_close_ta_session(unsigned long sess); + +/* sess has type TEE_TASessionHandle */ +TEE_Result _utee_invoke_ta_command(unsigned long sess, + unsigned long cancel_req_to, + unsigned long cmd_id, + struct utee_params *params, + uint32_t *ret_orig); + +TEE_Result _utee_check_access_rights(uint32_t flags, const void *buf, + size_t len); + +/* cancel has type bool */ +TEE_Result _utee_get_cancellation_flag(uint32_t *cancel); + +/* old_mask has type bool */ +TEE_Result _utee_unmask_cancellation(uint32_t *old_mask); + +/* old_mask has type bool */ +TEE_Result _utee_mask_cancellation(uint32_t *old_mask); + +TEE_Result _utee_wait(unsigned long timeout); + +/* cat has type enum _utee_time_category */ +TEE_Result _utee_get_time(unsigned long cat, TEE_Time *time); + +TEE_Result _utee_set_ta_time(const TEE_Time *time); + +TEE_Result _utee_cryp_state_alloc(unsigned long algo, unsigned long op_mode, + unsigned long key1, unsigned long key2, + uint32_t *state); +TEE_Result _utee_cryp_state_copy(unsigned long dst, unsigned long src); +TEE_Result _utee_cryp_state_free(unsigned long state); + +/* iv and iv_len are ignored for some algorithms */ +TEE_Result _utee_hash_init(unsigned long state, const void *iv, size_t iv_len); +TEE_Result _utee_hash_update(unsigned long state, const void *chunk, + size_t chunk_size); +TEE_Result _utee_hash_final(unsigned long state, const void *chunk, + size_t chunk_size, void *hash, uint64_t *hash_len); + +TEE_Result _utee_cipher_init(unsigned long state, const void *iv, + size_t iv_len); +TEE_Result _utee_cipher_update(unsigned long state, const void *src, + size_t src_len, void *dest, uint64_t *dest_len); +TEE_Result _utee_cipher_final(unsigned long state, const void *src, + size_t src_len, void *dest, uint64_t *dest_len); + +/* Generic Object Functions */ +TEE_Result _utee_cryp_obj_get_info(unsigned long obj, + struct utee_object_info *info); +TEE_Result _utee_cryp_obj_restrict_usage(unsigned long obj, + unsigned long usage); +TEE_Result _utee_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id, + void *buffer, uint64_t *size); + +/* Transient Object Functions */ +/* type has type TEE_ObjectType */ +TEE_Result _utee_cryp_obj_alloc(unsigned long type, unsigned long max_size, + uint32_t *obj); +TEE_Result _utee_cryp_obj_close(unsigned long obj); +TEE_Result _utee_cryp_obj_reset(unsigned long obj); +TEE_Result _utee_cryp_obj_populate(unsigned long obj, + struct utee_attribute *attrs, + unsigned long attr_count); +TEE_Result _utee_cryp_obj_copy(unsigned long dst_obj, unsigned long src_obj); + +TEE_Result _utee_cryp_obj_generate_key(unsigned long obj, + unsigned long key_size, + const struct utee_attribute *params, + unsigned long param_count); + +TEE_Result _utee_cryp_derive_key(unsigned long state, + const struct utee_attribute *params, + unsigned long param_count, + unsigned long derived_key); + +TEE_Result _utee_cryp_random_number_generate(void *buf, size_t blen); + +TEE_Result _utee_authenc_init(unsigned long 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(unsigned long state, const void *aad_data, + size_t aad_data_len); +TEE_Result _utee_authenc_update_payload(unsigned long state, + const void *src_data, size_t src_len, + void *dest_data, uint64_t *dest_len); +TEE_Result _utee_authenc_enc_final(unsigned long state, const void *src_data, + size_t src_len, void *dest_data, + uint64_t *dest_len, void *tag, + uint64_t *tag_len); +TEE_Result _utee_authenc_dec_final(unsigned long state, const void *src_data, + size_t src_len, void *dest_data, + uint64_t *dest_len, const void *tag, + size_t tag_len); + +TEE_Result _utee_asymm_operate(unsigned long state, + const struct utee_attribute *params, + unsigned long num_params, const void *src_data, + size_t src_len, void *dest_data, + uint64_t *dest_len); + +TEE_Result _utee_asymm_verify(unsigned long state, + const struct utee_attribute *params, + unsigned long num_params, const void *data, + size_t data_len, const void *sig, size_t sig_len); + +/* Persistant Object Functions */ +/* obj is of type TEE_ObjectHandle */ +TEE_Result _utee_storage_obj_open(unsigned long storage_id, + const void *object_id, size_t object_id_len, + unsigned long flags, uint32_t *obj); + +/* + * attr is of type TEE_ObjectHandle + * obj is of type TEE_ObjectHandle + */ +TEE_Result _utee_storage_obj_create(unsigned long storage_id, + const void *object_id, + size_t object_id_len, unsigned long flags, + unsigned long attr, const void *data, + size_t len, uint32_t *obj); + +/* obj is of type TEE_ObjectHandle */ +TEE_Result _utee_storage_obj_del(unsigned long obj); + +/* obj is of type TEE_ObjectHandle */ +TEE_Result _utee_storage_obj_rename(unsigned long obj, const void *new_obj_id, + size_t new_obj_id_len); + +/* Persistent Object Enumeration Functions */ +/* obj_enum is of type TEE_ObjectEnumHandle */ +TEE_Result _utee_storage_alloc_enum(uint32_t *obj_enum); + + +/* obj_enum is of type TEE_ObjectEnumHandle */ +TEE_Result _utee_storage_free_enum(unsigned long obj_enum); + +/* obj_enum is of type TEE_ObjectEnumHandle */ +TEE_Result _utee_storage_reset_enum(unsigned long obj_enum); + +/* obj_enum is of type TEE_ObjectEnumHandle */ +TEE_Result _utee_storage_start_enum(unsigned long obj_enum, + unsigned long storage_id); + +/* obj_enum is of type TEE_ObjectEnumHandle */ +TEE_Result _utee_storage_next_enum(unsigned long obj_enum, + struct utee_object_info *info, + void *obj_id, uint64_t *len); + +/* Data Stream Access Functions */ +/* obj is of type TEE_ObjectHandle */ +TEE_Result _utee_storage_obj_read(unsigned long obj, void *data, size_t len, + uint64_t *count); + +/* obj is of type TEE_ObjectHandle */ +TEE_Result _utee_storage_obj_write(unsigned long obj, const void *data, + size_t len); + +/* obj is of type TEE_ObjectHandle */ +TEE_Result _utee_storage_obj_trunc(unsigned long obj, size_t len); + +/* obj is of type TEE_ObjectHandle */ +/* whence is of type TEE_Whence */ +TEE_Result _utee_storage_obj_seek(unsigned long obj, int32_t offset, + unsigned long whence); + +/* op is of type enum _utee_cache_operation */ +TEE_Result _utee_cache_operation(void *va, size_t l, unsigned long op); + +TEE_Result _utee_gprof_send(void *buf, size_t size, uint32_t *id); + +#endif /* UTEE_SYSCALLS_H */ diff --git a/optee/optee_os/lib/libutee/include/utee_syscalls_asm.S b/optee/optee_os/lib/libutee/include/utee_syscalls_asm.S new file mode 100644 index 0000000..44bc60d --- /dev/null +++ b/optee/optee_os/lib/libutee/include/utee_syscalls_asm.S @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + + + UTEE_SYSCALL _utee_return, TEE_SCN_RETURN, 1 + + UTEE_SYSCALL _utee_log, TEE_SCN_LOG, 2 + + UTEE_SYSCALL __utee_panic, TEE_SCN_PANIC, 2 + + UTEE_SYSCALL _utee_get_property, TEE_SCN_GET_PROPERTY, 7 + + UTEE_SYSCALL _utee_get_property_name_to_index, \ + TEE_SCN_GET_PROPERTY_NAME_TO_INDEX, 4 + + UTEE_SYSCALL _utee_open_ta_session, TEE_SCN_OPEN_TA_SESSION, 5 + + UTEE_SYSCALL _utee_close_ta_session, TEE_SCN_CLOSE_TA_SESSION, 1 + + UTEE_SYSCALL _utee_invoke_ta_command, TEE_SCN_INVOKE_TA_COMMAND, 5 + + UTEE_SYSCALL _utee_get_cancellation_flag, \ + TEE_SCN_GET_CANCELLATION_FLAG, 1 + + UTEE_SYSCALL _utee_check_access_rights, TEE_SCN_CHECK_ACCESS_RIGHTS, 3 + + UTEE_SYSCALL _utee_unmask_cancellation, TEE_SCN_UNMASK_CANCELLATION, 1 + + UTEE_SYSCALL _utee_mask_cancellation, TEE_SCN_MASK_CANCELLATION, 1 + + 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 + + UTEE_SYSCALL _utee_cache_operation, TEE_SCN_CACHE_OPERATION, 3 diff --git a/optee/optee_os/lib/libutee/include/utee_types.h b/optee/optee_os/lib/libutee/include/utee_types.h new file mode 100644 index 0000000..547c21a --- /dev/null +++ b/optee/optee_os/lib/libutee/include/utee_types.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef UTEE_TYPES_H +#define UTEE_TYPES_H + +#include +#include + +enum utee_time_category { + UTEE_TIME_CAT_SYSTEM = 0, + UTEE_TIME_CAT_TA_PERSISTENT, + UTEE_TIME_CAT_REE +}; + +enum utee_entry_func { + UTEE_ENTRY_FUNC_OPEN_SESSION = 0, + UTEE_ENTRY_FUNC_CLOSE_SESSION, + UTEE_ENTRY_FUNC_INVOKE_COMMAND, + /* + * UTEE_ENTRY_FUNC_DUMP_MEMSTATS + * [out] value[0].a Byte size currently allocated + * [out] value[0].b Max bytes allocated since stats reset + * [out] value[1].a Pool byte size + * [out] value[1].b Number of failed allocation requests + * [out] value[2].a Biggest byte size which allocation failed + * [out] value[2].b Biggest byte size which allocation succeeded + */ + UTEE_ENTRY_FUNC_DUMP_MEMSTATS, +}; + +/* + * Cache operation types. + * Used when extensions TEE_CacheClean() / TEE_CacheFlush() / + * TEE_CacheInvalidate() are used + */ +enum utee_cache_operation { + TEE_CACHECLEAN = 0, + TEE_CACHEFLUSH, + TEE_CACHEINVALIDATE, +}; + +struct utee_params { + uint64_t types; + /* vals[n * 2] corresponds to either value.a or memref.buffer + * vals[n * 2 + ] corresponds to either value.b or memref.size + * when converting to/from struct tee_ta_param + */ + uint64_t vals[TEE_NUM_PARAMS * 2]; +}; + +struct utee_attribute { + uint64_t a; /* also serves as a pointer for references */ + uint64_t b; /* also serves as a length for references */ + uint32_t attribute_id; +}; + +struct utee_object_info { + uint32_t obj_type; + uint32_t obj_size; + uint32_t max_obj_size; + uint32_t obj_usage; + uint32_t data_size; + uint32_t data_pos; + uint32_t handle_flags; +}; + +#endif /* UTEE_TYPES_H */ diff --git a/optee/optee_os/lib/libutee/sub.mk b/optee/optee_os/lib/libutee/sub.mk new file mode 100644 index 0000000..145d021 --- /dev/null +++ b/optee/optee_os/lib/libutee/sub.mk @@ -0,0 +1,29 @@ +global-incdirs-y += include + +# Include header files from $(NV_OPTEE_DIR) +ifneq ("$(wildcard $(NV_OPTEE_DIR))","") +global-incdirs_ext-y += $(NV_OPTEE_DIR)/lib/libutee/include +endif + +srcs-y += abort.c +srcs-y += assert.c +srcs-y += tee_uuid_from_str.c +srcs-y += trace_ext.c + +ifneq ($(sm),ldelf) +srcs-y += base64.c +srcs-y += tee_api.c +srcs-y += tee_api_arith_mpi.c +srcs-y += tee_api_objects.c +srcs-y += tee_api_operations.c +srcs-y += tee_api_panic.c +srcs-y += tee_api_property.c +srcs-y += tee_socket_pta.c +srcs-y += tee_system_pta.c +srcs-y += tee_tcpudp_socket.c +srcs-y += tcb.c +srcs-y += user_ta_entry.c +srcs-y += user_ta_entry_compat.c +endif #ifneq ($(sm),ldelf) + +subdirs-y += arch/$(ARCH) diff --git a/optee/optee_os/lib/libutee/tcb.c b/optee/optee_os/lib/libutee/tcb.c new file mode 100644 index 0000000..20d44e7 --- /dev/null +++ b/optee/optee_os/lib/libutee/tcb.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ +/* + * Support for Thread-Local Storage (TLS) ABIs for ARMv7/Aarch32 and Aarch64. + * + * TAs are currently single-threaded, so the only benefit of implementing these + * ABIs is to support toolchains that need them even when the target program is + * single-threaded. Such as, the g++ compiler from the GCC toolchain targeting a + * "Posix thread" Linux runtime, which OP-TEE has been using for quite some time + * (arm-linux-gnueabihf-* and aarch64-linux-gnu-*). This allows building C++ TAs + * without having to build a specific toolchain with --disable-threads. + * + * This implementation is based on [1]. + * + * - "TLS data structures variant 1" (section 3): the AArch64 compiler uses the + * TPIDR_EL0 to access TLS data directly. This assumes a specific layout for + * the TCB, and (for shared objects) the use of R_AARCH64_TLS_TPREL + * relocations. + * - The "General Dynamic access model" (section 4.1): the ARMv7/Aarch32 + * compiler inserts calls to the __tls_get_addr() function which has to be + * implemented by the runtime library. The function takes a module ID and an + * offset parameter, which are provided thanks to R_ARM_TLS_DTPMOD32 and + * R_ARM_TLS_DTPOFF32 relocations. + * + * In addition, dl_iterate_phdr() is implemented here, because it is used by the + * g++ Aarch64 exception handling and it does use the TCB to provide TLS + * information to the caller. + * + * [1] "ELF Handling For Thread-Local Storage" + * https://www.akkadia.org/drepper/tls.pdf + */ + +#include +#include +#include +#include +#include +#include +#include "user_ta_header.h" + +/* DTV - Dynamic Thread Vector + * + * Maintains an array of pointers to TLS data for each module in the TCB. Each + * module that has a TLS segment has an entry (and consequently, some space in + * the tcb_head::tls buffer). The index is the "module ID". + * dtv[0].size is the number of elements in the vector + * dtv[1].tls points to TLS for the main executable (may be NULL) + * tls[2 .. (size-1)] are for shared libraries + */ +union dtv { + unsigned long size; + uint8_t *tls; +}; + +#define DTV_SIZE(size) (sizeof(union dtv) + (size)) + +/* Thread Control Block */ +struct tcb_head { + /* Two words are reserved as per the "TLS variant 1" ABI */ + union dtv *dtv; + unsigned long reserved; + /* + * The rest of the structure contains the TLS blocks for each ELF module + * having a PT_TLS segment. Each block is a copy of the .tdata section + * plus some zero-initialized space for .tbss. + */ + uint8_t tls[]; +}; + +/* + * Since TAs are single threaded, only one TCB is needed. This would need to + * change if multi-threading is introduced. + */ +static struct tcb_head *_tcb; +static size_t _tls_size; + +#define TCB_SIZE(tls_size) (sizeof(*_tcb) + (tls_size)) + +/* + * Initialize or update the TCB. + * Called on application initialization and when additional shared objects are + * loaded via dlopen(). + */ +void __utee_tcb_init(void) +{ + struct dl_phdr_info *dlpi = NULL; + const Elf_Phdr *phdr = NULL; + size_t total_size = 0; + size_t size = 0; + size_t i = 0; + size_t j = 0; + + /* Compute the size needed for all the TLS blocks */ + for (i = 0; i < __elf_phdr_info.count; i++) { + dlpi = __elf_phdr_info.dlpi + i; + for (j = 0; j < dlpi->dlpi_phnum; j++) { + phdr = dlpi->dlpi_phdr + j; + if (phdr->p_type == PT_TLS) { + total_size += phdr->p_memsz; + break; + } + } + } + + /* ELF modules currently cannot be unmapped */ + assert(total_size >= _tls_size); + + if (total_size == _tls_size) + return; + + /* (Re-)allocate the TCB */ + _tcb = realloc(_tcb, TCB_SIZE(total_size)); + if (!_tcb) { + EMSG("TCB allocation failed (%zu bytes)", TCB_SIZE(total_size)); + abort(); + } + + /* (Re-)allocate the DTV. + 1 since dtv[0] holds the size */ + size = DTV_SIZE((__elf_phdr_info.count + 1) * sizeof(union dtv)); + _tcb->dtv = realloc(_tcb->dtv, size); + if (!_tcb->dtv) { + EMSG("DTV allocation failed (%zu bytes)", size); + abort(); + } + + /* Copy TLS data to the TCB */ + size = 0; + for (i = 0; i < __elf_phdr_info.count; i++) { + dlpi = __elf_phdr_info.dlpi + i; + for (j = 0; j < dlpi->dlpi_phnum; j++) { + phdr = dlpi->dlpi_phdr + j; + if (phdr->p_type != PT_TLS) + continue; + if (size + phdr->p_memsz <= _tls_size) { + /* Already copied */ + break; + } + _tcb->dtv[i + 1].tls = _tcb->tls + size; + /* Copy .tdata */ + memcpy(_tcb->tls + size, + (void *)(dlpi->dlpi_addr + phdr->p_vaddr), + phdr->p_filesz); + /* Initialize .tbss */ + memset(_tcb->tls + size + phdr->p_filesz, 0, + phdr->p_memsz - phdr->p_filesz); + size += phdr->p_memsz; + } + } + _tcb->dtv[0].size = i; + + _tls_size = total_size; +#ifdef ARM64 + /* + * Aarch64 ABI requirement: the thread pointer shall point to the + * thread's TCB. ARMv7 and Aarch32 access the TCB via _tls_get_addr(). + */ + write_tpidr_el0((vaddr_t)_tcb); +#endif +} + +struct tls_index { + unsigned long module; + unsigned long offset; +}; + +void *__tls_get_addr(struct tls_index *ti); + +void *__tls_get_addr(struct tls_index *ti) +{ + return _tcb->dtv[ti->module].tls + ti->offset; +} + +int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), + void *data) +{ + struct dl_phdr_info *dlpi = NULL; + size_t id = 0; + size_t i = 0; + int st = 0; + + /* + * dlpi_tls_data is thread-specific so if we were to support + * multi-threading, we would need one copy of struct dl_phdr_info per + * thread. Could be a pre-allocated area, or could be allocated on the + * heap. Doing the latter here so that it would at least work if/when we + * add thread support. Further optimization can always come later. + */ + dlpi = calloc(1, sizeof(*dlpi)); + if (!dlpi) { + EMSG("dl_phdr_info allocation failed"); + abort(); + } + + for (i = 0; i < __elf_phdr_info.count; i++) { + memcpy(dlpi, __elf_phdr_info.dlpi + i, sizeof(*dlpi)); + dlpi->dlpi_tls_data = NULL; + id = dlpi->dlpi_tls_modid; + if (id) + dlpi->dlpi_tls_data = _tcb->dtv[id].tls; + st = callback(dlpi, sizeof(*dlpi), data); + } + + free(dlpi); + return st; +} diff --git a/optee/optee_os/lib/libutee/tee_api.c b/optee/optee_os/lib/libutee/tee_api.c new file mode 100644 index 0000000..fdc2474 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api.c @@ -0,0 +1,809 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "tee_api_private.h" + +/* + * return a known non-NULL invalid pointer when the + * requested size is zero + */ +#define TEE_NULL_SIZED_VA ((void *)1) +#define TEE_NULL_SIZED_NO_SHARE_VA ((void *)2) + +/* + * Workaround build error in Teaclave TrustZone SDK + * + * These are supposed to be provided by ta/arch/arm/user_ta_header.c, but + * Teaclave TrustZone SDK seems to roll their own in Rust. + */ +uint8_t __ta_no_share_heap[0] __weak; +const size_t __ta_no_share_heap_size __weak; +struct malloc_ctx *__ta_no_share_malloc_ctx __weak; + +static const void *tee_api_instance_data; + +/* System API - Internal Client API */ + +static void copy_param(struct utee_params *up, uint32_t param_types, + const TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t n = 0; + uint64_t a = 0; + uint64_t b = 0; + + up->types = param_types; + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(up->types, n)) { + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + a = params[n].value.a; + b = params[n].value.b; + break; + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + case TEE_PARAM_TYPE_MEMREF_INPUT: + a = (vaddr_t)params[n].memref.buffer; + b = params[n].memref.size; + break; + default: + a = 0; + b = 0; + } + up->vals[n * 2] = a; + up->vals[n * 2 + 1] = b; + } +} + +static void copy_gp11_param(struct utee_params *up, uint32_t param_types, + const __GP11_TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t n = 0; + uint64_t a = 0; + uint64_t b = 0; + + up->types = param_types; + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(up->types, n)) { + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + a = params[n].value.a; + b = params[n].value.b; + break; + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + case TEE_PARAM_TYPE_MEMREF_INPUT: + a = (vaddr_t)params[n].memref.buffer; + b = params[n].memref.size; + break; + default: + a = 0; + b = 0; + } + up->vals[n * 2] = a; + up->vals[n * 2 + 1] = b; + } +} + +static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf, + size_t *tmp_len, void *tmp_va[TEE_NUM_PARAMS]) +{ + size_t n = 0; + uint8_t *tb = NULL; + size_t tbl = 0; + size_t tmp_align = sizeof(vaddr_t) * 2; + bool is_tmp_mem[TEE_NUM_PARAMS] = { false }; + void *b = NULL; + size_t s = 0; + const uint32_t flags = TEE_MEMORY_ACCESS_READ; + + /* + * If a memory parameter points to TA private memory we need to + * allocate a temporary buffer to avoid exposing the memory + * directly to the called TA. + */ + + *tmp_buf = NULL; + *tmp_len = 0; + for (n = 0; n < TEE_NUM_PARAMS; n++) { + tmp_va[n] = NULL; + switch (TEE_PARAM_TYPE_GET(up->types, n)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + b = (void *)(vaddr_t)up->vals[n * 2]; + s = up->vals[n * 2 + 1]; + /* + * We're only allocating temporary memory if the + * buffer is completely within TA memory. If it's + * NULL, empty, partially outside or completely + * outside TA memory there's nothing more we need + * to do here. If there's security/permissions + * problem we'll get an error in the + * invoke_command/open_session below. + */ + if (b && s && + !TEE_CheckMemoryAccessRights(flags, b, s)) { + is_tmp_mem[n] = true; + tbl += ROUNDUP(s, tmp_align); + } + break; + default: + break; + } + } + + if (tbl) { + tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER); + if (!tb) + return TEE_ERROR_OUT_OF_MEMORY; + *tmp_buf = tb; + *tmp_len = tbl; + } + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(up->types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + case TEE_PARAM_TYPE_MEMREF_INPUT: + if (!is_tmp_mem[n]) + break; + s = up->vals[n * 2 + 1]; + b = (void *)(vaddr_t)up->vals[n * 2]; + tmp_va[n] = tb; + tb += ROUNDUP(s, tmp_align); + up->vals[n * 2] = (vaddr_t)tmp_va[n]; + if (TEE_PARAM_TYPE_GET(up->types, n) != + TEE_PARAM_TYPE_MEMREF_OUTPUT) + memcpy(tmp_va[n], b, s); + break; + default: + break; + } + } + + return TEE_SUCCESS; + +} + +static void update_out_param(TEE_Param params[TEE_NUM_PARAMS], + void *tmp_va[TEE_NUM_PARAMS], + const struct utee_params *up) +{ + size_t n; + uint32_t types = up->types; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uintptr_t a = up->vals[n * 2]; + uintptr_t b = up->vals[n * 2 + 1]; + + switch (TEE_PARAM_TYPE_GET(types, n)) { + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].value.a = a; + params[n].value.b = b; + break; + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + if (tmp_va[n]) + memcpy(params[n].memref.buffer, tmp_va[n], + MIN(b, params[n].memref.size)); + params[n].memref.size = b; + break; + default: + break; + } + } +} + +static void update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS], + void *tmp_va[TEE_NUM_PARAMS], + const struct utee_params *up) +{ + size_t n = 0; + uint32_t types = up->types; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uintptr_t a = up->vals[n * 2]; + uintptr_t b = up->vals[n * 2 + 1]; + + switch (TEE_PARAM_TYPE_GET(types, n)) { + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].value.a = a; + params[n].value.b = b; + break; + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + if (tmp_va[n]) + memcpy(params[n].memref.buffer, tmp_va[n], + MIN(b, params[n].memref.size)); + params[n].memref.size = b; + break; + default: + break; + } + } +} + +static bool bufs_intersect(void *buf1, size_t sz1, void *buf2, size_t sz2) +{ + vaddr_t b1 = (vaddr_t)buf1; + vaddr_t b2 = (vaddr_t)buf2; + vaddr_t e1 = b1 + sz1 - 1; + vaddr_t e2 = b2 + sz2 - 1; + + if (!sz1 || !sz2) + return false; + + if (e1 < b2 || e2 < b1) + return false; + + return true; +} + +static TEE_Result check_mem_access_rights_params(uint32_t flags, void *buf, + size_t len) +{ + size_t n = 0; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER; + + switch (TEE_PARAM_TYPE_GET(ta_param_types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + f |= TEE_MEMORY_ACCESS_WRITE; + fallthrough; + case TEE_PARAM_TYPE_MEMREF_INPUT: + f |= TEE_MEMORY_ACCESS_READ; + if (bufs_intersect(buf, len, + ta_params[n].memref.buffer, + ta_params[n].memref.size)) { + if ((flags & f) != flags) + return TEE_ERROR_ACCESS_DENIED; + } + break; + default: + break; + } + } + + return TEE_SUCCESS; +} + +static bool buf_overlaps_no_share_heap(void *buf, size_t size) +{ + struct malloc_ctx *ctx = __ta_no_share_malloc_ctx; + + return ctx && raw_malloc_buffer_overlaps_heap(ctx, buf, size); +} + +static void check_invoke_param(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t n = 0; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER; + void *buf = params[n].memref.buffer; + size_t size = params[n].memref.size; + + switch (TEE_PARAM_TYPE_GET(pt, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + f |= TEE_MEMORY_ACCESS_WRITE; + fallthrough; + case TEE_PARAM_TYPE_MEMREF_INPUT: + f |= TEE_MEMORY_ACCESS_READ; + if (check_mem_access_rights_params(f, buf, size)) + TEE_Panic(0); + if (buf_overlaps_no_share_heap(buf, size)) + TEE_Panic(0); + break; + default: + break; + } + } +} + +TEE_Result TEE_OpenTASession(const TEE_UUID *destination, + uint32_t cancellationRequestTimeout, + uint32_t paramTypes, + TEE_Param params[TEE_NUM_PARAMS], + TEE_TASessionHandle *session, + uint32_t *returnOrigin) +{ + TEE_Result res = TEE_SUCCESS; + struct utee_params up = { }; + uint32_t s = 0; + void *tmp_buf = NULL; + size_t tmp_len = 0; + void *tmp_va[TEE_NUM_PARAMS] = { NULL }; + + if (paramTypes) { + __utee_check_inout_annotation(params, + sizeof(TEE_Param) * + TEE_NUM_PARAMS); + check_invoke_param(paramTypes, params); + } + __utee_check_out_annotation(session, sizeof(*session)); + + copy_param(&up, paramTypes, params); + res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); + if (res) + goto out; + res = _utee_open_ta_session(destination, cancellationRequestTimeout, + &up, &s, returnOrigin); + update_out_param(params, tmp_va, &up); + if (tmp_buf) { + TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); + + if (res2) + TEE_Panic(res2); + } + +out: + /* + * 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) + s = TEE_HANDLE_NULL; + + *session = (TEE_TASessionHandle)(uintptr_t)s; + return res; +} + +TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination, + uint32_t cancellationRequestTimeout, + uint32_t paramTypes, + __GP11_TEE_Param params[TEE_NUM_PARAMS], + TEE_TASessionHandle *session, + uint32_t *returnOrigin) +{ + TEE_Result res = TEE_SUCCESS; + struct utee_params up = { }; + uint32_t s = 0; + void *tmp_buf = NULL; + size_t tmp_len = 0; + void *tmp_va[TEE_NUM_PARAMS] = { NULL }; + + if (paramTypes) + __utee_check_inout_annotation(params, + sizeof(__GP11_TEE_Param) * + TEE_NUM_PARAMS); + __utee_check_out_annotation(session, sizeof(*session)); + + copy_gp11_param(&up, paramTypes, params); + res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); + if (res) + goto out; + res = _utee_open_ta_session(destination, cancellationRequestTimeout, + &up, &s, returnOrigin); + update_out_gp11_param(params, tmp_va, &up); + if (tmp_buf) { + TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); + + if (res2) + TEE_Panic(res2); + } + +out: + /* + * Specification says that *session must hold TEE_HANDLE_NULL if + * TEE_SUCCESS isn't returned. Set it here explicitly in case + * the syscall fails before out parameters has been updated. + */ + if (res != TEE_SUCCESS) + s = TEE_HANDLE_NULL; + + *session = (TEE_TASessionHandle)(uintptr_t)s; + return res; +} + +void TEE_CloseTASession(TEE_TASessionHandle session) +{ + if (session != TEE_HANDLE_NULL) { + TEE_Result res = _utee_close_ta_session((uintptr_t)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[TEE_NUM_PARAMS], + uint32_t *returnOrigin) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t ret_origin = TEE_ORIGIN_TEE; + struct utee_params up = { }; + void *tmp_buf = NULL; + size_t tmp_len = 0; + void *tmp_va[TEE_NUM_PARAMS] = { NULL }; + + if (paramTypes) { + __utee_check_inout_annotation(params, + sizeof(TEE_Param) * + TEE_NUM_PARAMS); + check_invoke_param(paramTypes, params); + } + if (returnOrigin) + __utee_check_out_annotation(returnOrigin, + sizeof(*returnOrigin)); + + copy_param(&up, paramTypes, params); + res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); + if (res) + goto out; + res = _utee_invoke_ta_command((uintptr_t)session, + cancellationRequestTimeout, + commandID, &up, &ret_origin); + update_out_param(params, tmp_va, &up); + if (tmp_buf) { + TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); + + if (res2) + TEE_Panic(res2); + } + +out: + if (returnOrigin != NULL) + *returnOrigin = ret_origin; + + if (ret_origin == TEE_ORIGIN_TRUSTED_APP) + return res; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_OUT_OF_MEMORY && + res != TEE_ERROR_TARGET_DEAD) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session, + uint32_t cancellationRequestTimeout, + uint32_t commandID, uint32_t paramTypes, + __GP11_TEE_Param params[TEE_NUM_PARAMS], + uint32_t *returnOrigin) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t ret_origin = TEE_ORIGIN_TEE; + struct utee_params up = { }; + void *tmp_buf = NULL; + size_t tmp_len = 0; + void *tmp_va[TEE_NUM_PARAMS] = { NULL }; + + if (paramTypes) + __utee_check_inout_annotation(params, + sizeof(__GP11_TEE_Param) * + TEE_NUM_PARAMS); + if (returnOrigin) + __utee_check_out_annotation(returnOrigin, + sizeof(*returnOrigin)); + + copy_gp11_param(&up, paramTypes, params); + res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); + if (res) + goto out; + res = _utee_invoke_ta_command((uintptr_t)session, + cancellationRequestTimeout, + commandID, &up, &ret_origin); + update_out_gp11_param(params, tmp_va, &up); + if (tmp_buf) { + TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); + + if (res2) + TEE_Panic(res2); + } + +out: + if (returnOrigin) + *returnOrigin = ret_origin; + + if (ret_origin == TEE_ORIGIN_TRUSTED_APP) + return res; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_OUT_OF_MEMORY && + res != TEE_ERROR_TARGET_DEAD) + TEE_Panic(res); + + return res; +} + +/* System API - Cancellations */ + +bool TEE_GetCancellationFlag(void) +{ + uint32_t c; + TEE_Result res = _utee_get_cancellation_flag(&c); + + if (res != TEE_SUCCESS) + c = 0; + return !!c; +} + +bool TEE_UnmaskCancellation(void) +{ + uint32_t old_mask; + TEE_Result res = _utee_unmask_cancellation(&old_mask); + + if (res != TEE_SUCCESS) + TEE_Panic(res); + return !!old_mask; +} + +bool TEE_MaskCancellation(void) +{ + uint32_t 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) +{ + uint32_t flags = accessFlags; + + if (!size) + return TEE_SUCCESS; + + /* + * Check access rights against memory mapping. If this check is + * OK the size can't cause an overflow when added with buffer. + */ + if (_utee_check_access_rights(accessFlags, buffer, size)) + return TEE_ERROR_ACCESS_DENIED; + + /* + * Check access rights against input parameters. + * + * Clear eventual extension flags like TEE_MEMORY_ACCESS_NONSECURE + * and TEE_MEMORY_ACCESS_SECURE. + */ + flags &= TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_ANY_OWNER; + if (check_mem_access_rights_params(flags, buffer, size)) + return TEE_ERROR_ACCESS_DENIED; + + if (malloc_buffer_overlaps_heap(buffer, size) && + !malloc_buffer_is_within_alloced(buffer, size)) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +TEE_Result __GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags, + void *buffer, uint32_t size) +{ + return TEE_CheckMemoryAccessRights(accessFlags, buffer, size); +} + +void TEE_SetInstanceData(const void *instanceData) +{ + tee_api_instance_data = instanceData; +} + +const void *TEE_GetInstanceData(void) +{ + return tee_api_instance_data; +} + +void *TEE_MemMove(void *dest, const void *src, size_t size) +{ + return memmove(dest, src, size); +} + +void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size) +{ + return TEE_MemMove(dest, src, size); +} + +int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size) +{ + return consttime_memcmp(buffer1, buffer2, size); +} + +int32_t __GP11_TEE_MemCompare(const void *buffer1, const void *buffer2, + uint32_t size) +{ + return TEE_MemCompare(buffer1, buffer2, size); +} + +void TEE_MemFill(void *buff, uint32_t x, size_t size) +{ + memset(buff, x, size); +} + +void __GP11_TEE_MemFill(void *buff, uint32_t x, uint32_t size) +{ + TEE_MemFill(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(res); +} + +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) +{ + TEE_Result res; + + res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time); + + if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) { + time->seconds = 0; + time->millis = 0; + } + + if (res != TEE_SUCCESS && + res != TEE_ERROR_TIME_NOT_SET && + res != TEE_ERROR_TIME_NEEDS_RESET && + res != TEE_ERROR_OVERFLOW && + res != TEE_ERROR_OUT_OF_MEMORY) + TEE_Panic(res); + + return res; +} + +TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time) +{ + TEE_Result res; + + res = _utee_set_ta_time(time); + + if (res != TEE_SUCCESS && + res != TEE_ERROR_OUT_OF_MEMORY && + res != TEE_ERROR_STORAGE_NO_SPACE) + TEE_Panic(res); + + return res; +} + +void TEE_GetREETime(TEE_Time *time) +{ + TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time); + + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +void *TEE_Malloc(size_t len, uint32_t hint) +{ + switch (hint) { + case TEE_MALLOC_FILL_ZERO: + if (!len) + return TEE_NULL_SIZED_VA; + return calloc(1, len); + + case TEE_MALLOC_NO_FILL: + TEE_Panic(0); + break; + + case TEE_MALLOC_NO_SHARE: + if (!len) + return TEE_NULL_SIZED_NO_SHARE_VA; + if (!__ta_no_share_malloc_ctx) + return NULL; + return raw_calloc(0, 0, 1, len, __ta_no_share_malloc_ctx); + + case TEE_MALLOC_NO_FILL | TEE_MALLOC_NO_SHARE: + if (!len) + return TEE_NULL_SIZED_NO_SHARE_VA; + if (!__ta_no_share_malloc_ctx) + return NULL; + return raw_malloc(0, 0, len, __ta_no_share_malloc_ctx); + + case TEE_USER_MEM_HINT_NO_FILL_ZERO: + if (!len) + return TEE_NULL_SIZED_VA; + return malloc(len); + + default: + break; + } + + EMSG("Invalid hint %#" PRIx32, hint); + + return NULL; +} + +void *__GP11_TEE_Malloc(uint32_t size, uint32_t hint) +{ + return TEE_Malloc(size, hint); +} + +static bool addr_is_in_no_share_heap(void *p) +{ + return buf_overlaps_no_share_heap(p, 1); +} + +void *TEE_Realloc(void *buffer, size_t newSize) +{ + if (!newSize) { + TEE_Free(buffer); + + if (addr_is_in_no_share_heap(buffer)) + return TEE_NULL_SIZED_NO_SHARE_VA; + else + return TEE_NULL_SIZED_VA; + } + + if (buffer == TEE_NULL_SIZED_VA) + return calloc(1, newSize); + if (buffer == TEE_NULL_SIZED_NO_SHARE_VA) { + if (!__ta_no_share_malloc_ctx) + return NULL; + return raw_calloc(0, 0, 1, newSize, __ta_no_share_malloc_ctx); + } + + if (addr_is_in_no_share_heap(buffer)) + return raw_realloc(buffer, 0, 0, newSize, + __ta_no_share_malloc_ctx); + else + return realloc(buffer, newSize); +} + +void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize) +{ + return TEE_Realloc(buffer, newSize); +} + +void TEE_Free(void *buffer) +{ + if (buffer != TEE_NULL_SIZED_VA && + buffer != TEE_NULL_SIZED_NO_SHARE_VA) { + if (addr_is_in_no_share_heap(buffer)) + raw_free(buffer, __ta_no_share_malloc_ctx, false); + else + free(buffer); + } +} + +/* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */ +TEE_Result TEE_CacheClean(char *buf, size_t len) +{ + return _utee_cache_operation(buf, len, TEE_CACHECLEAN); +} +TEE_Result TEE_CacheFlush(char *buf, size_t len) +{ + return _utee_cache_operation(buf, len, TEE_CACHEFLUSH); +} + +TEE_Result TEE_CacheInvalidate(char *buf, size_t len) +{ + return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE); +} diff --git a/optee/optee_os/lib/libutee/tee_api_arith_mpi.c b/optee/optee_os/lib/libutee/tee_api_arith_mpi.c new file mode 100644 index 0000000..baa2976 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api_arith_mpi.c @@ -0,0 +1,1016 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MPI_MEMPOOL_SIZE (14 * 1024) + +static void __noreturn api_panic(const char *func, int line, const char *msg) +{ + printf("Panic function %s, line %d: %s\n", func, line, msg); + TEE_Panic(0xB16127 /*BIGINT*/); + while (1) + ; /* Panic will crash the thread */ +} + +#define API_PANIC(x) api_panic(__func__, __LINE__, x) + +static void __noreturn mpi_panic(const char *func, int line, int rc) +{ + printf("Panic function %s, line %d, code %d\n", func, line, rc); + TEE_Panic(0xB16127 /*BIGINT*/); + while (1) + ; /* Panic will crash the thread */ +} + +#define MPI_CHECK(x) do { \ + int _rc = (x); \ + \ + if (_rc) \ + mpi_panic(__func__, __LINE__, _rc); \ + } while (0) + +void _TEE_MathAPI_Init(void) +{ + static uint8_t data[MPI_MEMPOOL_SIZE] __aligned(MEMPOOL_ALIGN); + + mbedtls_mpi_mempool = mempool_alloc_pool(data, sizeof(data), NULL); + if (!mbedtls_mpi_mempool) + API_PANIC("Failed to initialize memory pool"); +} + +struct bigint_hdr { + int32_t sign; + uint16_t alloc_size; + uint16_t nblimbs; +}; + +#define BIGINT_HDR_SIZE_IN_U32 2 + +static TEE_Result copy_mpi_to_bigint(mbedtls_mpi *mpi, TEE_BigInt *bigInt) +{ + struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; + size_t n = mpi->n; + + /* Trim of eventual insignificant zeroes */ + while (n && !mpi->p[n - 1]) + n--; + + if (hdr->alloc_size < n) + return TEE_ERROR_OVERFLOW; + + hdr->nblimbs = n; + hdr->sign = mpi->s; + memcpy(hdr + 1, mpi->p, mpi->n * sizeof(mbedtls_mpi_uint)); + + return TEE_SUCCESS; +} + +/* + * Initializes a MPI. + * + * A temporary MPI is allocated and if a bigInt is supplied the MPI is + * initialized with the value of the bigInt. + */ +static void get_mpi(mbedtls_mpi *mpi, const TEE_BigInt *bigInt) +{ + /* + * The way the GP spec is defining the bignums it's + * difficult/tricky to do it using 64-bit arithmetics given that + * we'd need 64-bit alignment of the data as well. + */ + COMPILE_TIME_ASSERT(sizeof(mbedtls_mpi_uint) == sizeof(uint32_t)); + + /* + * The struct bigint_hdr is the overhead added to the bigint and + * is required to take exactly 2 uint32_t. + */ + COMPILE_TIME_ASSERT(sizeof(struct bigint_hdr) == + sizeof(uint32_t) * BIGINT_HDR_SIZE_IN_U32); + + mbedtls_mpi_init_mempool(mpi); + + if (bigInt) { + const struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; + const mbedtls_mpi_uint *p = (const mbedtls_mpi_uint *)(hdr + 1); + size_t n = hdr->nblimbs; + + /* Trim of eventual insignificant zeroes */ + while (n && !p[n - 1]) + n--; + + MPI_CHECK(mbedtls_mpi_grow(mpi, n)); + mpi->s = hdr->sign; + memcpy(mpi->p, p, n * sizeof(mbedtls_mpi_uint)); + } +} + +void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len) +{ + struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; + + static_assert(MBEDTLS_MPI_MAX_LIMBS + BIGINT_HDR_SIZE_IN_U32 >= + CFG_TA_BIGNUM_MAX_BITS / 32); + + memset(bigInt, 0, len * sizeof(uint32_t)); + hdr->sign = 1; + + /* "gpd.tee.arith.maxBigIntSize" is assigned CFG_TA_BIGNUM_MAX_BITS */ + if (len > CFG_TA_BIGNUM_MAX_BITS / 4) + API_PANIC("Too large bigint"); + hdr->alloc_size = len - BIGINT_HDR_SIZE_IN_U32; +} + +void __GP11_TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len) +{ + TEE_BigIntInit(bigInt, len); +} + +TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, + const uint8_t *buffer, + size_t bufferLen, int32_t sign) +{ + TEE_Result res; + mbedtls_mpi mpi_dest; + + get_mpi(&mpi_dest, NULL); + + if (mbedtls_mpi_read_binary(&mpi_dest, buffer, bufferLen)) + res = TEE_ERROR_OVERFLOW; + else + res = TEE_SUCCESS; + + if (sign < 0) + mpi_dest.s = -1; + + if (!res) + res = copy_mpi_to_bigint(&mpi_dest, dest); + + mbedtls_mpi_free(&mpi_dest); + + return res; +} + +TEE_Result __GP11_TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, + const uint8_t *buffer, + uint32_t bufferLen, + int32_t sign) +{ + return TEE_BigIntConvertFromOctetString(dest, buffer, bufferLen, sign); +} + +TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, size_t *bufferLen, + const TEE_BigInt *bigInt) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_mpi mpi; + size_t sz; + + get_mpi(&mpi, bigInt); + + sz = mbedtls_mpi_size(&mpi); + if (sz <= *bufferLen) + MPI_CHECK(mbedtls_mpi_write_binary(&mpi, buffer, sz)); + else + res = TEE_ERROR_SHORT_BUFFER; + + *bufferLen = sz; + + mbedtls_mpi_free(&mpi); + + return res; +} + +TEE_Result __GP11_TEE_BigIntConvertToOctetString(uint8_t *buffer, + uint32_t *bufferLen, + const TEE_BigInt *bigInt) +{ + TEE_Result res = TEE_SUCCESS; + size_t l = *bufferLen; + + res = TEE_BigIntConvertToOctetString(buffer, &l, bigInt); + *bufferLen = l; + return res; +} + +void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal) +{ + mbedtls_mpi mpi; + + get_mpi(&mpi, dest); + + MPI_CHECK(mbedtls_mpi_lset(&mpi, shortVal)); + + MPI_CHECK(copy_mpi_to_bigint(&mpi, dest)); + mbedtls_mpi_free(&mpi); +} + +TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_mpi mpi; + uint32_t v; + + get_mpi(&mpi, src); + + if (mbedtls_mpi_write_binary(&mpi, (void *)&v, sizeof(v))) { + res = TEE_ERROR_OVERFLOW; + goto out; + } + + if (mpi.s > 0) { + if (ADD_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest)) + res = TEE_ERROR_OVERFLOW; + } else { + if (SUB_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest)) + res = TEE_ERROR_OVERFLOW; + } + +out: + mbedtls_mpi_free(&mpi); + + return res; +} + +int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2) +{ + mbedtls_mpi mpi1; + mbedtls_mpi mpi2; + int32_t rc; + + get_mpi(&mpi1, op1); + get_mpi(&mpi2, op2); + + rc = mbedtls_mpi_cmp_mpi(&mpi1, &mpi2); + + mbedtls_mpi_free(&mpi1); + mbedtls_mpi_free(&mpi2); + + return rc; +} + +int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal) +{ + mbedtls_mpi mpi; + int32_t rc; + + get_mpi(&mpi, op); + + rc = mbedtls_mpi_cmp_int(&mpi, shortVal); + + mbedtls_mpi_free(&mpi); + + return rc; +} + +void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits) +{ + mbedtls_mpi mpi_dest; + mbedtls_mpi mpi_op; + + get_mpi(&mpi_dest, dest); + + if (dest == op) { + MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits)); + goto out; + } + + get_mpi(&mpi_op, op); + + if (mbedtls_mpi_size(&mpi_dest) >= mbedtls_mpi_size(&mpi_op)) { + MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_op)); + MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits)); + } else { + mbedtls_mpi mpi_t; + + get_mpi(&mpi_t, NULL); + + /* + * We're using a temporary buffer to avoid the corner case + * where destination is unexpectedly overflowed by up to + * @bits number of bits. + */ + MPI_CHECK(mbedtls_mpi_copy(&mpi_t, &mpi_op)); + MPI_CHECK(mbedtls_mpi_shift_r(&mpi_t, bits)); + MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_t)); + + mbedtls_mpi_free(&mpi_t); + } + + mbedtls_mpi_free(&mpi_op); + +out: + MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); + mbedtls_mpi_free(&mpi_dest); +} + +void __GP11_TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, + uint32_t bits) +{ + TEE_BigIntShiftRight(dest, op, bits); +} + +bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex) +{ + bool rc; + mbedtls_mpi mpi; + + get_mpi(&mpi, src); + + rc = mbedtls_mpi_get_bit(&mpi, bitIndex); + + mbedtls_mpi_free(&mpi); + + return rc; +} + +uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src) +{ + uint32_t rc; + mbedtls_mpi mpi; + + get_mpi(&mpi, src); + + rc = mbedtls_mpi_bitlen(&mpi); + + mbedtls_mpi_free(&mpi); + + return rc; +} + +TEE_Result TEE_BigIntSetBit(TEE_BigInt *op, uint32_t bitIndex, bool value) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_mpi mpi = { }; + int rc = 0; + + get_mpi(&mpi, op); + + rc = mbedtls_mpi_set_bit(&mpi, bitIndex, value); + if (rc) + res = TEE_ERROR_OVERFLOW; + else + res = copy_mpi_to_bigint(&mpi, op); + + mbedtls_mpi_free(&mpi); + + return res; +} + +TEE_Result TEE_BigIntAssign(TEE_BigInt *dest, const TEE_BigInt *src) +{ + const struct bigint_hdr *src_hdr = (struct bigint_hdr *)src; + struct bigint_hdr *dst_hdr = (struct bigint_hdr *)dest; + + if (dst_hdr == src_hdr) + return TEE_SUCCESS; + + if (dst_hdr->alloc_size < src_hdr->nblimbs) + return TEE_ERROR_OVERFLOW; + + dst_hdr->nblimbs = src_hdr->nblimbs; + dst_hdr->sign = src_hdr->sign; + memcpy(dst_hdr + 1, src_hdr + 1, src_hdr->nblimbs * sizeof(uint32_t)); + + return TEE_SUCCESS; +} + +TEE_Result TEE_BigIntAbs(TEE_BigInt *dest, const TEE_BigInt *src) +{ + TEE_Result res = TEE_BigIntAssign(dest, src); + + if (!res) + ((struct bigint_hdr *)dest)->sign = 1; + + return res; +} + +static void bigint_binary(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, + int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B)) +{ + mbedtls_mpi mpi_dest; + mbedtls_mpi mpi_op1; + mbedtls_mpi mpi_op2; + mbedtls_mpi *pop1 = &mpi_op1; + mbedtls_mpi *pop2 = &mpi_op2; + + get_mpi(&mpi_dest, dest); + + if (op1 == dest) + pop1 = &mpi_dest; + else + get_mpi(&mpi_op1, op1); + + if (op2 == dest) + pop2 = &mpi_dest; + else if (op2 == op1) + pop2 = pop1; + else + get_mpi(&mpi_op2, op2); + + MPI_CHECK(func(&mpi_dest, pop1, pop2)); + + MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); + mbedtls_mpi_free(&mpi_dest); + if (pop1 == &mpi_op1) + mbedtls_mpi_free(&mpi_op1); + if (pop2 == &mpi_op2) + mbedtls_mpi_free(&mpi_op2); +} + +static void bigint_binary_mod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n, + int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B)) +{ + mbedtls_mpi mpi_dest; + mbedtls_mpi mpi_op1; + mbedtls_mpi mpi_op2; + mbedtls_mpi mpi_n; + mbedtls_mpi *pop1 = &mpi_op1; + mbedtls_mpi *pop2 = &mpi_op2; + mbedtls_mpi mpi_t; + + if (TEE_BigIntCmpS32(n, 2) < 0) + API_PANIC("Modulus is too short"); + + get_mpi(&mpi_dest, dest); + get_mpi(&mpi_n, n); + + if (op1 == dest) + pop1 = &mpi_dest; + else + get_mpi(&mpi_op1, op1); + + if (op2 == dest) + pop2 = &mpi_dest; + else if (op2 == op1) + pop2 = pop1; + else + get_mpi(&mpi_op2, op2); + + get_mpi(&mpi_t, NULL); + + MPI_CHECK(func(&mpi_t, pop1, pop2)); + MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dest, &mpi_t, &mpi_n)); + + MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); + mbedtls_mpi_free(&mpi_dest); + if (pop1 == &mpi_op1) + mbedtls_mpi_free(&mpi_op1); + if (pop2 == &mpi_op2) + mbedtls_mpi_free(&mpi_op2); + mbedtls_mpi_free(&mpi_t); + mbedtls_mpi_free(&mpi_n); +} + +void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2) +{ + bigint_binary(dest, op1, op2, mbedtls_mpi_add_mpi); +} + +void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2) +{ + bigint_binary(dest, op1, op2, mbedtls_mpi_sub_mpi); +} + +void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src) +{ + mbedtls_mpi mpi_dest; + + get_mpi(&mpi_dest, dest); + + if (dest != src) { + mbedtls_mpi mpi_src; + + get_mpi(&mpi_src, src); + + MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_src)); + + mbedtls_mpi_free(&mpi_src); + } + + mpi_dest.s *= -1; + + MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); + mbedtls_mpi_free(&mpi_dest); +} + +void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2) +{ + size_t bs1 = TEE_BigIntGetBitCount(op1); + size_t bs2 = TEE_BigIntGetBitCount(op2); + size_t s = TEE_BigIntSizeInU32(bs1) + TEE_BigIntSizeInU32(bs2); + TEE_BigInt zero[TEE_BigIntSizeInU32(1)] = { 0 }; + TEE_BigInt *tmp = NULL; + + tmp = mempool_alloc(mbedtls_mpi_mempool, sizeof(uint32_t) * s); + if (!tmp) + TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); + + TEE_BigIntInit(tmp, s); + TEE_BigIntInit(zero, TEE_BigIntSizeInU32(1)); + + bigint_binary(tmp, op1, op2, mbedtls_mpi_mul_mpi); + + TEE_BigIntAdd(dest, tmp, zero); + + mempool_free(mbedtls_mpi_mempool, tmp); +} + +void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op) +{ + TEE_BigIntMul(dest, op, op); +} + +void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, + const TEE_BigInt *op1, const TEE_BigInt *op2) +{ + mbedtls_mpi mpi_dest_q; + mbedtls_mpi mpi_dest_r; + mbedtls_mpi mpi_op1; + mbedtls_mpi mpi_op2; + mbedtls_mpi *pop1 = &mpi_op1; + mbedtls_mpi *pop2 = &mpi_op2; + + get_mpi(&mpi_dest_q, dest_q); + get_mpi(&mpi_dest_r, dest_r); + + if (op1 == dest_q) + pop1 = &mpi_dest_q; + else if (op1 == dest_r) + pop1 = &mpi_dest_r; + else + get_mpi(&mpi_op1, op1); + + if (op2 == dest_q) + pop2 = &mpi_dest_q; + else if (op2 == dest_r) + pop2 = &mpi_dest_r; + else if (op2 == op1) + pop2 = pop1; + else + get_mpi(&mpi_op2, op2); + + MPI_CHECK(mbedtls_mpi_div_mpi(&mpi_dest_q, &mpi_dest_r, pop1, pop2)); + + if (dest_q) + MPI_CHECK(copy_mpi_to_bigint(&mpi_dest_q, dest_q)); + if (dest_r) + MPI_CHECK(copy_mpi_to_bigint(&mpi_dest_r, dest_r)); + mbedtls_mpi_free(&mpi_dest_q); + mbedtls_mpi_free(&mpi_dest_r); + if (pop1 == &mpi_op1) + mbedtls_mpi_free(&mpi_op1); + if (pop2 == &mpi_op2) + mbedtls_mpi_free(&mpi_op2); +} + +void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n) +{ + if (TEE_BigIntCmpS32(n, 2) < 0) + API_PANIC("Modulus is too short"); + + bigint_binary(dest, op, n, mbedtls_mpi_mod_mpi); +} + +void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n) +{ + bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_add_mpi); +} + +void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n) +{ + bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_sub_mpi); +} + +void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n) +{ + bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_mul_mpi); +} + +void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n) +{ + TEE_BigIntMulMod(dest, op, op, n); +} + +void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, + const TEE_BigInt *n) +{ + mbedtls_mpi mpi_dest; + mbedtls_mpi mpi_op; + mbedtls_mpi mpi_n; + mbedtls_mpi *pop = &mpi_op; + + if (TEE_BigIntCmpS32(n, 2) < 0 || TEE_BigIntCmpS32(op, 0) == 0) + API_PANIC("too small modulus or trying to invert zero"); + + get_mpi(&mpi_dest, dest); + get_mpi(&mpi_n, n); + + if (op == dest) + pop = &mpi_dest; + else + get_mpi(&mpi_op, op); + + MPI_CHECK(mbedtls_mpi_inv_mod(&mpi_dest, pop, &mpi_n)); + + MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); + mbedtls_mpi_free(&mpi_dest); + mbedtls_mpi_free(&mpi_n); + if (pop == &mpi_op) + mbedtls_mpi_free(&mpi_op); +} + +bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2) +{ + bool rc; + mbedtls_mpi mpi_op1; + mbedtls_mpi mpi_op2; + mbedtls_mpi *pop2 = &mpi_op2; + mbedtls_mpi gcd; + + get_mpi(&mpi_op1, op1); + + if (op2 == op1) + pop2 = &mpi_op1; + else + get_mpi(&mpi_op2, op2); + + get_mpi(&gcd, NULL); + + MPI_CHECK(mbedtls_mpi_gcd(&gcd, &mpi_op1, &mpi_op2)); + + rc = !mbedtls_mpi_cmp_int(&gcd, 1); + + mbedtls_mpi_free(&gcd); + mbedtls_mpi_free(&mpi_op1); + if (pop2 == &mpi_op2) + mbedtls_mpi_free(&mpi_op2); + + return rc; +} + +static bool mpi_is_odd(mbedtls_mpi *x) +{ + return mbedtls_mpi_get_bit(x, 0); +} + +static bool mpi_is_even(mbedtls_mpi *x) +{ + return !mpi_is_odd(x); +} + +TEE_Result TEE_BigIntExpMod(TEE_BigInt *dest, const TEE_BigInt *op1, + const TEE_BigInt *op2, const TEE_BigInt *n, + const TEE_BigIntFMMContext *context __unused) +{ + TEE_Result res = TEE_SUCCESS; + mbedtls_mpi mpi_dest = { }; + mbedtls_mpi mpi_op1 = { }; + mbedtls_mpi mpi_op2 = { }; + mbedtls_mpi mpi_n = { }; + mbedtls_mpi *pop1 = &mpi_op1; + mbedtls_mpi *pop2 = &mpi_op2; + + get_mpi(&mpi_dest, dest); + get_mpi(&mpi_n, n); + if (op1 == dest) + pop1 = &mpi_dest; + else + get_mpi(&mpi_op1, op1); + + if (op2 == dest) + pop2 = &mpi_dest; + else if (op2 == op1) + pop2 = pop1; + else + get_mpi(&mpi_op2, op2); + + if (mbedtls_mpi_cmp_int(&mpi_n, 2) <= 0) + API_PANIC("too small modulus"); + if (!mpi_is_odd(&mpi_n)) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + + MPI_CHECK(mbedtls_mpi_exp_mod(&mpi_dest, pop1, pop2, &mpi_n, NULL)); + MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); +out: + mbedtls_mpi_free(&mpi_dest); + mbedtls_mpi_free(&mpi_n); + if (pop1 == &mpi_op1) + mbedtls_mpi_free(&mpi_op1); + if (pop2 == &mpi_op2) + mbedtls_mpi_free(&mpi_op2); + + return res; +} + +/* + * Based on libmpa implementation __mpa_egcd(), modified to work with MPI + * instead. + */ +static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b, + mbedtls_mpi *x_in, mbedtls_mpi *y_in) +{ + mbedtls_mpi_uint k; + mbedtls_mpi A; + mbedtls_mpi B; + mbedtls_mpi C; + mbedtls_mpi D; + mbedtls_mpi x; + mbedtls_mpi y; + mbedtls_mpi u; + + get_mpi(&A, NULL); + get_mpi(&B, NULL); + get_mpi(&C, NULL); + get_mpi(&D, NULL); + get_mpi(&x, NULL); + get_mpi(&y, NULL); + get_mpi(&u, NULL); + + /* have y < x from assumption */ + if (!mbedtls_mpi_cmp_int(y_in, 0)) { + MPI_CHECK(mbedtls_mpi_lset(a, 1)); + MPI_CHECK(mbedtls_mpi_lset(b, 0)); + MPI_CHECK(mbedtls_mpi_copy(gcd, x_in)); + goto out; + } + + MPI_CHECK(mbedtls_mpi_copy(&x, x_in)); + MPI_CHECK(mbedtls_mpi_copy(&y, y_in)); + + k = 0; + while (mpi_is_even(&x) && mpi_is_even(&y)) { + k++; + MPI_CHECK(mbedtls_mpi_shift_r(&x, 1)); + MPI_CHECK(mbedtls_mpi_shift_r(&y, 1)); + } + + MPI_CHECK(mbedtls_mpi_copy(&u, &x)); + MPI_CHECK(mbedtls_mpi_copy(gcd, &y)); + MPI_CHECK(mbedtls_mpi_lset(&A, 1)); + MPI_CHECK(mbedtls_mpi_lset(&B, 0)); + MPI_CHECK(mbedtls_mpi_lset(&C, 0)); + MPI_CHECK(mbedtls_mpi_lset(&D, 1)); + + while (mbedtls_mpi_cmp_int(&u, 0)) { + while (mpi_is_even(&u)) { + MPI_CHECK(mbedtls_mpi_shift_r(&u, 1)); + if (mpi_is_odd(&A) || mpi_is_odd(&B)) { + MPI_CHECK(mbedtls_mpi_add_mpi(&A, &A, &y)); + MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &x)); + } + MPI_CHECK(mbedtls_mpi_shift_r(&A, 1)); + MPI_CHECK(mbedtls_mpi_shift_r(&B, 1)); + } + + while (mpi_is_even(gcd)) { + MPI_CHECK(mbedtls_mpi_shift_r(gcd, 1)); + if (mpi_is_odd(&C) || mpi_is_odd(&D)) { + MPI_CHECK(mbedtls_mpi_add_mpi(&C, &C, &y)); + MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &x)); + } + MPI_CHECK(mbedtls_mpi_shift_r(&C, 1)); + MPI_CHECK(mbedtls_mpi_shift_r(&D, 1)); + + } + + if (mbedtls_mpi_cmp_mpi(&u, gcd) >= 0) { + MPI_CHECK(mbedtls_mpi_sub_mpi(&u, &u, gcd)); + MPI_CHECK(mbedtls_mpi_sub_mpi(&A, &A, &C)); + MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &D)); + } else { + MPI_CHECK(mbedtls_mpi_sub_mpi(gcd, gcd, &u)); + MPI_CHECK(mbedtls_mpi_sub_mpi(&C, &C, &A)); + MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &B)); + } + } + + MPI_CHECK(mbedtls_mpi_copy(a, &C)); + MPI_CHECK(mbedtls_mpi_copy(b, &D)); + MPI_CHECK(mbedtls_mpi_shift_l(gcd, k)); + +out: + mbedtls_mpi_free(&A); + mbedtls_mpi_free(&B); + mbedtls_mpi_free(&C); + mbedtls_mpi_free(&D); + mbedtls_mpi_free(&x); + mbedtls_mpi_free(&y); + mbedtls_mpi_free(&u); +} + +void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, + TEE_BigInt *v, const TEE_BigInt *op1, + const TEE_BigInt *op2) +{ + mbedtls_mpi mpi_gcd_res; + mbedtls_mpi mpi_op1; + mbedtls_mpi mpi_op2; + mbedtls_mpi *pop2 = &mpi_op2; + + get_mpi(&mpi_gcd_res, gcd); + get_mpi(&mpi_op1, op1); + + if (op2 == op1) + pop2 = &mpi_op1; + else + get_mpi(&mpi_op2, op2); + + if (!u && !v) { + MPI_CHECK(mbedtls_mpi_gcd(&mpi_gcd_res, &mpi_op1, pop2)); + } else { + mbedtls_mpi mpi_u; + mbedtls_mpi mpi_v; + int8_t s1 = mpi_op1.s; + int8_t s2 = pop2->s; + int cmp; + + mpi_op1.s = 1; + pop2->s = 1; + + get_mpi(&mpi_u, u); + get_mpi(&mpi_v, v); + + cmp = mbedtls_mpi_cmp_abs(&mpi_op1, pop2); + if (cmp == 0) { + MPI_CHECK(mbedtls_mpi_copy(&mpi_gcd_res, &mpi_op1)); + MPI_CHECK(mbedtls_mpi_lset(&mpi_u, 1)); + MPI_CHECK(mbedtls_mpi_lset(&mpi_v, 0)); + } else if (cmp > 0) { + mpi_egcd(&mpi_gcd_res, &mpi_u, &mpi_v, &mpi_op1, pop2); + } else { + mpi_egcd(&mpi_gcd_res, &mpi_v, &mpi_u, pop2, &mpi_op1); + } + + mpi_u.s *= s1; + mpi_v.s *= s2; + + MPI_CHECK(copy_mpi_to_bigint(&mpi_u, u)); + MPI_CHECK(copy_mpi_to_bigint(&mpi_v, v)); + mbedtls_mpi_free(&mpi_u); + mbedtls_mpi_free(&mpi_v); + } + + MPI_CHECK(copy_mpi_to_bigint(&mpi_gcd_res, gcd)); + mbedtls_mpi_free(&mpi_gcd_res); + mbedtls_mpi_free(&mpi_op1); + if (pop2 == &mpi_op2) + mbedtls_mpi_free(&mpi_op2); +} + +static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen) +{ + if (_utee_cryp_random_number_generate(buf, blen)) + return MBEDTLS_ERR_MPI_FILE_IO_ERROR; + return 0; +} + +int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, + uint32_t confidenceLevel __unused) +{ + int rc; + mbedtls_mpi mpi_op; + + get_mpi(&mpi_op, op); + + rc = mbedtls_mpi_is_prime(&mpi_op, rng_read, NULL); + + mbedtls_mpi_free(&mpi_op); + + if (rc) + return 0; + + return 1; +} + +/* + * Not so fast FMM implementation based on the normal big int functions. + * + * Note that these functions (along with all the other functions in this + * file) only are used directly by the TA doing bigint arithmetics on its + * own. Performance of RSA operations in TEE Internal API are not affected + * by this. + */ +void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, size_t len) +{ + TEE_BigIntInit(bigIntFMM, len); +} + +void __GP11_TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_t len) +{ + TEE_BigIntInitFMM(bigIntFMM, len); +} + +void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context __unused, + size_t len __unused, + const TEE_BigInt *modulus __unused) +{ +} + +void __GP11_TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, + uint32_t len, const TEE_BigInt *modulus) +{ + TEE_BigIntInitFMMContext(context, len, modulus); +} + +TEE_Result TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext *context __unused, + size_t len __unused, + const TEE_BigInt *modulus __unused) +{ + return TEE_SUCCESS; +} + +size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits) +{ + return TEE_BigIntSizeInU32(modulusSizeInBits); +} + +uint32_t __GP11_TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits) +{ + return TEE_BigIntFMMSizeInU32(modulusSizeInBits); +} + +size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits __unused) +{ + /* Return something larger than 0 to keep malloc() and friends happy */ + return 1; +} + +uint32_t __GP11_TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits) +{ + return TEE_BigIntFMMContextSizeInU32(modulusSizeInBits); +} + +void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src, + const TEE_BigInt *n, + const TEE_BigIntFMMContext *context __unused) +{ + TEE_BigIntMod(dest, src, n); +} + +void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src, + const TEE_BigInt *n __unused, + const TEE_BigIntFMMContext *context __unused) +{ + mbedtls_mpi mpi_dst; + mbedtls_mpi mpi_src; + + get_mpi(&mpi_dst, dest); + get_mpi(&mpi_src, src); + + MPI_CHECK(mbedtls_mpi_copy(&mpi_dst, &mpi_src)); + + MPI_CHECK(copy_mpi_to_bigint(&mpi_dst, dest)); + mbedtls_mpi_free(&mpi_dst); + mbedtls_mpi_free(&mpi_src); +} + +void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1, + const TEE_BigIntFMM *op2, const TEE_BigInt *n, + const TEE_BigIntFMMContext *context __unused) +{ + mbedtls_mpi mpi_dst; + mbedtls_mpi mpi_op1; + mbedtls_mpi mpi_op2; + mbedtls_mpi mpi_n; + mbedtls_mpi mpi_t; + + get_mpi(&mpi_dst, dest); + get_mpi(&mpi_op1, op1); + get_mpi(&mpi_op2, op2); + get_mpi(&mpi_n, n); + get_mpi(&mpi_t, NULL); + + MPI_CHECK(mbedtls_mpi_mul_mpi(&mpi_t, &mpi_op1, &mpi_op2)); + MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dst, &mpi_t, &mpi_n)); + + mbedtls_mpi_free(&mpi_t); + mbedtls_mpi_free(&mpi_n); + mbedtls_mpi_free(&mpi_op2); + mbedtls_mpi_free(&mpi_op1); + MPI_CHECK(copy_mpi_to_bigint(&mpi_dst, dest)); + mbedtls_mpi_free(&mpi_dst); +} diff --git a/optee/optee_os/lib/libutee/tee_api_objects.c b/optee/optee_os/lib/libutee/tee_api_objects.c new file mode 100644 index 0000000..2514bde --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api_objects.c @@ -0,0 +1,1054 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include +#include + +#include +#include +#include "tee_api_private.h" + +#define TEE_USAGE_DEFAULT 0xffffffff + +void __utee_from_attr(struct utee_attribute *ua, const TEE_Attribute *attrs, + uint32_t attr_count) +{ + size_t n; + + for (n = 0; n < attr_count; n++) { + ua[n].attribute_id = attrs[n].attributeID; + if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) { + ua[n].a = attrs[n].content.value.a; + ua[n].b = attrs[n].content.value.b; + } else { + ua[n].a = (uintptr_t)attrs[n].content.ref.buffer; + ua[n].b = attrs[n].content.ref.length; + } + } +} + +void __utee_from_gp11_attr(struct utee_attribute *ua, + const __GP11_TEE_Attribute *attrs, + uint32_t attr_count) +{ + size_t n = 0; + + for (n = 0; n < attr_count; n++) { + ua[n].attribute_id = attrs[n].attributeID; + if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) { + ua[n].a = attrs[n].content.value.a; + ua[n].b = attrs[n].content.value.b; + } else { + ua[n].a = (uintptr_t)attrs[n].content.ref.buffer; + ua[n].b = attrs[n].content.ref.length; + } + } +} + +/* Data and Key Storage API - Generic Object Functions */ +/* + * Use of this function is deprecated + * new code SHOULD use the TEE_GetObjectInfo1 function instead + * These functions will be removed at some future major revision of + * this specification + */ +void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + + if (res != TEE_SUCCESS) + TEE_Panic(res); + + if (info.obj_type == TEE_TYPE_CORRUPTED_OBJECT) { + objectInfo->objectSize = 0; + objectInfo->maxObjectSize = 0; + objectInfo->objectUsage = 0; + objectInfo->dataSize = 0; + objectInfo->dataPosition = 0; + objectInfo->handleFlags = 0; + } else { + objectInfo->objectType = info.obj_type; + objectInfo->objectSize = info.obj_size; + objectInfo->maxObjectSize = info.max_obj_size; + objectInfo->objectUsage = info.obj_usage; + objectInfo->dataSize = info.data_size; + objectInfo->dataPosition = info.data_pos; + objectInfo->handleFlags = info.handle_flags; + } +} + +void __GP11_TEE_GetObjectInfo(TEE_ObjectHandle object, + __GP11_TEE_ObjectInfo *objectInfo) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + + if (res != TEE_SUCCESS) + TEE_Panic(res); + + if (info.obj_type == TEE_TYPE_CORRUPTED_OBJECT) { + objectInfo->keySize = 0; + objectInfo->maxKeySize = 0; + objectInfo->objectUsage = 0; + objectInfo->dataSize = 0; + objectInfo->dataPosition = 0; + objectInfo->handleFlags = 0; + } else { + objectInfo->objectType = info.obj_type; + objectInfo->keySize = info.obj_size; + objectInfo->maxKeySize = info.max_obj_size; + objectInfo->objectUsage = info.obj_usage; + objectInfo->dataSize = info.data_size; + objectInfo->dataPosition = info.data_pos; + objectInfo->handleFlags = info.handle_flags; + } +} + +TEE_Result TEE_GetObjectInfo1(TEE_ObjectHandle object, + TEE_ObjectInfo *objectInfo) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + + if (res != TEE_SUCCESS && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + objectInfo->objectType = info.obj_type; + objectInfo->objectSize = info.obj_size; + objectInfo->maxObjectSize = info.max_obj_size; + objectInfo->objectUsage = info.obj_usage; + objectInfo->dataSize = info.data_size; + objectInfo->dataPosition = info.data_pos; + objectInfo->handleFlags = info.handle_flags; + + return res; +} + +TEE_Result __GP11_TEE_GetObjectInfo1(TEE_ObjectHandle object, + __GP11_TEE_ObjectInfo *objectInfo) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + + if (res != TEE_SUCCESS && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + objectInfo->objectType = info.obj_type; + objectInfo->keySize = info.obj_size; + objectInfo->maxKeySize = info.max_obj_size; + objectInfo->objectUsage = info.obj_usage; + objectInfo->dataSize = info.data_size; + objectInfo->dataPosition = info.data_pos; + objectInfo->handleFlags = info.handle_flags; + + return res; +} + +/* + * Use of this function is deprecated + * new code SHOULD use the TEE_RestrictObjectUsage1 function instead + * These functions will be removed at some future major revision of + * this specification + */ +void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + if (info.obj_type == TEE_TYPE_CORRUPTED_OBJECT) + return; + + res = TEE_RestrictObjectUsage1(object, objectUsage); + + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +TEE_Result TEE_RestrictObjectUsage1(TEE_ObjectHandle object, uint32_t objectUsage) +{ + TEE_Result res; + + res = _utee_cryp_obj_restrict_usage((unsigned long)object, + objectUsage); + + if (res != TEE_SUCCESS && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + uint32_t attributeID, void *buffer, + size_t *size) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + uint64_t sz = 0; + + __utee_check_inout_annotation(size, sizeof(*size)); + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + if (res != TEE_SUCCESS) + goto exit; + + /* This function only supports reference attributes */ + if ((attributeID & TEE_ATTR_FLAG_VALUE)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + sz = *size; + res = _utee_cryp_obj_get_attr((unsigned long)object, attributeID, + buffer, &sz); + *size = sz; + +exit: + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_SHORT_BUFFER && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + uint32_t attributeID, + void *buffer, uint32_t *size) +{ + TEE_Result res = TEE_SUCCESS; + size_t l = 0; + + __utee_check_inout_annotation(size, sizeof(*size)); + l = *size; + res = TEE_GetObjectBufferAttribute(object, attributeID, buffer, &l); + *size = l; + return res; +} + +TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, + uint32_t attributeID, uint32_t *a, + uint32_t *b) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + uint32_t buf[2]; + uint64_t size = sizeof(buf); + + if (a) + __utee_check_out_annotation(a, sizeof(*a)); + if (b) + __utee_check_out_annotation(b, sizeof(*b)); + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + if (res != TEE_SUCCESS) + goto exit; + + /* This function only supports value attributes */ + if (!(attributeID & TEE_ATTR_FLAG_VALUE)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto exit; + } + + res = _utee_cryp_obj_get_attr((unsigned long)object, attributeID, buf, + &size); + +exit: + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + if (size != sizeof(buf)) + TEE_Panic(0); + + if (res == TEE_SUCCESS) { + if (a) + *a = buf[0]; + if (b) + *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((unsigned long)object); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +/* Data and Key Storage API - Transient Object Functions */ + +TEE_Result TEE_AllocateTransientObject(TEE_ObjectType objectType, + uint32_t maxObjectSize, + TEE_ObjectHandle *object) +{ + if (objectType == TEE_TYPE_DATA) + return TEE_ERROR_NOT_SUPPORTED; + + return __GP11_TEE_AllocateTransientObject(objectType, maxObjectSize, + object); +} + +TEE_Result __GP11_TEE_AllocateTransientObject(TEE_ObjectType objectType, + uint32_t maxKeySize, + TEE_ObjectHandle *object) +{ + TEE_Result res; + uint32_t obj; + + __utee_check_out_annotation(object, sizeof(*object)); + + res = _utee_cryp_obj_alloc(objectType, maxKeySize, &obj); + + if (res != TEE_SUCCESS && + res != TEE_ERROR_OUT_OF_MEMORY && + res != TEE_ERROR_NOT_SUPPORTED) + TEE_Panic(res); + + if (res == TEE_SUCCESS) + *object = (TEE_ObjectHandle)(uintptr_t)obj; + + return res; +} + +void TEE_FreeTransientObject(TEE_ObjectHandle object) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + if (object == TEE_HANDLE_NULL) + return; + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(res); + + if ((info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + TEE_Panic(0); + + res = _utee_cryp_obj_close((unsigned long)object); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +void TEE_ResetTransientObject(TEE_ObjectHandle object) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + if (object == TEE_HANDLE_NULL) + return; + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(res); + + if ((info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + TEE_Panic(0); + + res = _utee_cryp_obj_reset((unsigned long)object); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, + const TEE_Attribute *attrs, + uint32_t attrCount) +{ + struct utee_attribute ua[attrCount]; + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + __utee_check_attr_in_annotation(attrs, attrCount); + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(res); + + /* Must be a transient object */ + if ((info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + TEE_Panic(0); + + /* Must not be initialized already */ + if ((info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + TEE_Panic(0); + + __utee_from_attr(ua, attrs, attrCount); + res = _utee_cryp_obj_populate((unsigned long)object, ua, attrCount); + if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) + TEE_Panic(res); + return res; +} + +TEE_Result __GP11_TEE_PopulateTransientObject(TEE_ObjectHandle object, + const __GP11_TEE_Attribute *attrs, + uint32_t attrCount) +{ + struct utee_attribute ua[attrCount]; + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + __utee_check_gp11_attr_in_annotation(attrs, attrCount); + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + if (res != TEE_SUCCESS) + TEE_Panic(res); + + /* Must be a transient object */ + if ((info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT) != 0) + TEE_Panic(0); + + /* Must not be initialized already */ + if ((info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + TEE_Panic(0); + + __utee_from_gp11_attr(ua, attrs, attrCount); + res = _utee_cryp_obj_populate((unsigned long)object, ua, attrCount); + if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) + TEE_Panic(res); + return res; +} + +void TEE_InitRefAttribute(TEE_Attribute *attr, uint32_t attributeID, + const void *buffer, size_t length) +{ + __utee_check_out_annotation(attr, sizeof(*attr)); + + if ((attributeID & TEE_ATTR_FLAG_VALUE) != 0) + TEE_Panic(0); + attr->attributeID = attributeID; + attr->content.ref.buffer = (void *)buffer; + attr->content.ref.length = length; +} + +void __GP11_TEE_InitRefAttribute(__GP11_TEE_Attribute *attr, + uint32_t attributeID, + const void *buffer, uint32_t length) +{ + __utee_check_out_annotation(attr, sizeof(*attr)); + + if ((attributeID & TEE_ATTR_FLAG_VALUE) != 0) + TEE_Panic(0); + attr->attributeID = attributeID; + attr->content.ref.buffer = (void *)buffer; + attr->content.ref.length = length; +} + +void TEE_InitValueAttribute(TEE_Attribute *attr, uint32_t attributeID, + uint32_t a, uint32_t b) +{ + __utee_check_out_annotation(attr, sizeof(*attr)); + + if ((attributeID & TEE_ATTR_FLAG_VALUE) == 0) + TEE_Panic(0); + attr->attributeID = attributeID; + attr->content.value.a = a; + attr->content.value.b = b; +} + +void __GP11_TEE_InitValueAttribute(__GP11_TEE_Attribute *attr, + uint32_t attributeID, + uint32_t a, uint32_t b) +{ + __utee_check_out_annotation(attr, sizeof(*attr)); + + if ((attributeID & TEE_ATTR_FLAG_VALUE) == 0) + TEE_Panic(0); + attr->attributeID = attributeID; + attr->content.value.a = a; + attr->content.value.b = b; +} + +/* + * Use of this function is deprecated + * new code SHOULD use the TEE_CopyObjectAttributes1 function instead + * These functions will be removed at some future major revision of + * this specification + */ +void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, + TEE_ObjectHandle srcObject) +{ + struct utee_object_info src_info = { }; + TEE_Result res = TEE_SUCCESS; + + res = _utee_cryp_obj_get_info((unsigned long)srcObject, &src_info); + if (src_info.obj_type == TEE_TYPE_CORRUPTED_OBJECT) + return; + + res = TEE_CopyObjectAttributes1(destObject, srcObject); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +TEE_Result TEE_CopyObjectAttributes1(TEE_ObjectHandle destObject, + TEE_ObjectHandle srcObject) +{ + struct utee_object_info dst_info = { }; + struct utee_object_info src_info = { }; + TEE_Result res = TEE_SUCCESS; + + res = _utee_cryp_obj_get_info((unsigned long)destObject, &dst_info); + if (res != TEE_SUCCESS) + goto exit; + + res = _utee_cryp_obj_get_info((unsigned long)srcObject, &src_info); + if (res != TEE_SUCCESS) + goto exit; + + if (!(src_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED)) + TEE_Panic(0); + + if ((dst_info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT)) + TEE_Panic(0); + + if ((dst_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED)) + TEE_Panic(0); + + res = _utee_cryp_obj_copy((unsigned long)destObject, + (unsigned long)srcObject); + +exit: + if (res != TEE_SUCCESS && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, + const TEE_Attribute *params, uint32_t paramCount) +{ + TEE_Result res; + struct utee_attribute ua[paramCount]; + + __utee_check_attr_in_annotation(params, paramCount); + + __utee_from_attr(ua, params, paramCount); + res = _utee_cryp_obj_generate_key((unsigned long)object, keySize, + ua, paramCount); + + if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, + const __GP11_TEE_Attribute *params, + uint32_t paramCount) +{ + TEE_Result res = TEE_SUCCESS; + struct utee_attribute ua[paramCount]; + + __utee_check_gp11_attr_in_annotation(params, paramCount); + + __utee_from_gp11_attr(ua, params, paramCount); + res = _utee_cryp_obj_generate_key((unsigned long)object, keySize, + ua, paramCount); + + if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) + TEE_Panic(res); + + return res; +} + +/* Data and Key Storage API - Persistent Object Functions */ + +TEE_Result TEE_OpenPersistentObject(uint32_t storageID, const void *objectID, + size_t objectIDLen, uint32_t flags, + TEE_ObjectHandle *object) +{ + TEE_Result res; + uint32_t obj; + + __utee_check_out_annotation(object, sizeof(*object)); + + res = _utee_storage_obj_open(storageID, objectID, objectIDLen, flags, + &obj); + if (res == TEE_SUCCESS) + *object = (TEE_ObjectHandle)(uintptr_t)obj; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_ACCESS_CONFLICT && + res != TEE_ERROR_OUT_OF_MEMORY && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + if (res != TEE_SUCCESS) + *object = TEE_HANDLE_NULL; + + return res; +} + +TEE_Result __GP11_TEE_OpenPersistentObject(uint32_t storageID, + const void *objectID, + uint32_t objectIDLen, uint32_t flags, + TEE_ObjectHandle *object) +{ + return TEE_OpenPersistentObject(storageID, objectID, objectIDLen, + flags, object); +} + +TEE_Result TEE_CreatePersistentObject(uint32_t storageID, const void *objectID, + size_t objectIDLen, uint32_t flags, + TEE_ObjectHandle attributes, + const void *initialData, + size_t initialDataLen, + TEE_ObjectHandle *object) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t *obj_ptr = NULL; + uint32_t obj = 0; + + if (object) { + __utee_check_out_annotation(object, sizeof(*object)); + obj_ptr = &obj; + } + + res = _utee_storage_obj_create(storageID, objectID, objectIDLen, flags, + (unsigned long)attributes, initialData, + initialDataLen, obj_ptr); + + if (res == TEE_SUCCESS && object) + *object = (TEE_ObjectHandle)(uintptr_t)obj; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_ACCESS_CONFLICT && + res != TEE_ERROR_OUT_OF_MEMORY && + res != TEE_ERROR_STORAGE_NO_SPACE && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + if (res != TEE_SUCCESS && object) + *object = TEE_HANDLE_NULL; + + return res; +} + +TEE_Result __GP11_TEE_CreatePersistentObject(uint32_t storageID, + const void *objectID, + uint32_t objectIDLen, + uint32_t flags, + TEE_ObjectHandle attributes, + const void *initialData, + uint32_t initialDataLen, + TEE_ObjectHandle *object) +{ + __utee_check_out_annotation(object, sizeof(*object)); + + return TEE_CreatePersistentObject(storageID, objectID, objectIDLen, + flags, attributes, initialData, + initialDataLen, object); +} + +/* + * Use of this function is deprecated + * new code SHOULD use the TEE_CloseAndDeletePersistentObject1 function instead + * These functions will be removed at some future major revision of + * this specification + */ +void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) + return; + + res = TEE_CloseAndDeletePersistentObject1(object); + + if (res != TEE_SUCCESS) + TEE_Panic(0); +} + +TEE_Result TEE_CloseAndDeletePersistentObject1(TEE_ObjectHandle object) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) + return TEE_SUCCESS; + + res = _utee_storage_obj_del((unsigned long)object); + + if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + + +TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, + const void *newObjectID, + size_t newObjectIDLen) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto out; + } + + res = _utee_storage_obj_rename((unsigned long)object, newObjectID, + newObjectIDLen); + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_ACCESS_CONFLICT && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_RenamePersistentObject(TEE_ObjectHandle object, + const void *newObjectID, + uint32_t newObjectIDLen) +{ + return TEE_RenamePersistentObject(object, newObjectID, newObjectIDLen); +} + +TEE_Result TEE_AllocatePersistentObjectEnumerator(TEE_ObjectEnumHandle * + objectEnumerator) +{ + TEE_Result res; + uint32_t oe; + + __utee_check_out_annotation(objectEnumerator, + sizeof(*objectEnumerator)); + + res = _utee_storage_alloc_enum(&oe); + + if (res != TEE_SUCCESS) + oe = TEE_HANDLE_NULL; + + *objectEnumerator = (TEE_ObjectEnumHandle)(uintptr_t)oe; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ACCESS_CONFLICT) + TEE_Panic(res); + + return res; +} + +void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator) +{ + TEE_Result res; + + if (objectEnumerator == TEE_HANDLE_NULL) + return; + + res = _utee_storage_free_enum((unsigned long)objectEnumerator); + + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator) +{ + TEE_Result res; + + if (objectEnumerator == TEE_HANDLE_NULL) + return; + + res = _utee_storage_reset_enum((unsigned long)objectEnumerator); + + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +TEE_Result TEE_StartPersistentObjectEnumerator(TEE_ObjectEnumHandle + objectEnumerator, + uint32_t storageID) +{ + TEE_Result res; + + res = _utee_storage_start_enum((unsigned long)objectEnumerator, + storageID); + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, + TEE_ObjectInfo *objectInfo, + void *objectID, size_t *objectIDLen) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + uint64_t len = 0; + + if (objectInfo) + __utee_check_out_annotation(objectInfo, sizeof(*objectInfo)); + __utee_check_out_annotation(objectIDLen, sizeof(*objectIDLen)); + + if (!objectID) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + len = *objectIDLen; + res = _utee_storage_next_enum((unsigned long)objectEnumerator, + &info, objectID, &len); + if (objectInfo) { + objectInfo->objectType = info.obj_type; + objectInfo->objectSize = info.obj_size; + objectInfo->maxObjectSize = info.max_obj_size; + objectInfo->objectUsage = info.obj_usage; + objectInfo->dataSize = info.data_size; + objectInfo->dataPosition = info.data_pos; + objectInfo->handleFlags = info.handle_flags; + } + *objectIDLen = len; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result +__GP11_TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, + __GP11_TEE_ObjectInfo *objectInfo, + void *objectID, uint32_t *objectIDLen) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + uint64_t len = 0; + + if (objectInfo) + __utee_check_out_annotation(objectInfo, sizeof(*objectInfo)); + __utee_check_out_annotation(objectIDLen, sizeof(*objectIDLen)); + + if (!objectID) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + len = *objectIDLen; + res = _utee_storage_next_enum((unsigned long)objectEnumerator, + &info, objectID, &len); + if (objectInfo) { + objectInfo->objectType = info.obj_type; + objectInfo->keySize = info.obj_size; + objectInfo->maxKeySize = info.max_obj_size; + objectInfo->objectUsage = info.obj_usage; + objectInfo->dataSize = info.data_size; + objectInfo->dataPosition = info.data_pos; + objectInfo->handleFlags = info.handle_flags; + } + *objectIDLen = len; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +/* Data and Key Storage API - Data Stream Access Functions */ + +TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, + size_t size, size_t *count) +{ + TEE_Result res; + uint64_t cnt64; + + if (object == TEE_HANDLE_NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + __utee_check_out_annotation(count, sizeof(*count)); + + cnt64 = *count; + res = _utee_storage_obj_read((unsigned long)object, buffer, size, + &cnt64); + *count = cnt64; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, + uint32_t size, uint32_t *count) +{ + TEE_Result res = TEE_SUCCESS; + size_t cnt = 0; + + __utee_check_out_annotation(count, sizeof(*count)); + cnt = *count; + res = TEE_ReadObjectData(object, buffer, size, &cnt); + *count = cnt; + return res; +} + +TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, const void *buffer, + size_t size) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (size > TEE_DATA_MAX_POSITION) { + res = TEE_ERROR_OVERFLOW; + goto out; + } + + res = _utee_storage_obj_write((unsigned long)object, buffer, size); + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_STORAGE_NO_SPACE && + res != TEE_ERROR_OVERFLOW && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_WriteObjectData(TEE_ObjectHandle object, + const void *buffer, uint32_t size) +{ + return TEE_WriteObjectData(object, buffer, size); +} + +TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, size_t size) +{ + TEE_Result res; + + if (object == TEE_HANDLE_NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = _utee_storage_obj_trunc((unsigned long)object, size); + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_STORAGE_NO_SPACE && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_TruncateObjectData(TEE_ObjectHandle object, + uint32_t size) +{ + return TEE_TruncateObjectData(object, size); +} + +TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, intmax_t offset, + TEE_Whence whence) +{ + struct utee_object_info info = { }; + TEE_Result res = TEE_SUCCESS; + + if (object == TEE_HANDLE_NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = _utee_cryp_obj_get_info((unsigned long)object, &info); + if (res != TEE_SUCCESS) + goto out; + + switch (whence) { + case TEE_DATA_SEEK_SET: + if (offset > 0 && (uint32_t)offset > TEE_DATA_MAX_POSITION) { + res = TEE_ERROR_OVERFLOW; + goto out; + } + break; + case TEE_DATA_SEEK_CUR: + if (offset > 0 && + ((uint32_t)offset + info.data_pos > TEE_DATA_MAX_POSITION || + (uint32_t)offset + info.data_pos < info.data_pos)) { + res = TEE_ERROR_OVERFLOW; + goto out; + } + break; + case TEE_DATA_SEEK_END: + if (offset > 0 && + ((uint32_t)offset + info.data_size > + TEE_DATA_MAX_POSITION || + (uint32_t)offset + info.data_size < info.data_size)) { + res = TEE_ERROR_OVERFLOW; + goto out; + } + break; + default: + res = TEE_ERROR_ITEM_NOT_FOUND; + goto out; + } + + res = _utee_storage_obj_seek((unsigned long)object, offset, whence); + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_OVERFLOW && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_SeekObjectData(TEE_ObjectHandle object, int32_t offset, + TEE_Whence whence) +{ + return TEE_SeekObjectData(object, offset, whence); +} diff --git a/optee/optee_os/lib/libutee/tee_api_operations.c b/optee/optee_os/lib/libutee/tee_api_operations.c new file mode 100644 index 0000000..f44350d --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api_operations.c @@ -0,0 +1,2712 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2021, SumUp Services GmbH + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tee_api_private.h" + +struct __TEE_OperationHandle { + TEE_OperationInfo info; + TEE_ObjectHandle key1; + TEE_ObjectHandle key2; + uint32_t operationState;/* Operation state : INITIAL or ACTIVE */ + + /* + * buffer to collect complete blocks or to keep a complete digest + * for TEE_DigestExtract(). + */ + uint8_t *buffer; + 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 */ +}; + +/* 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) + TEE_Panic(0); + + if (algorithm == TEE_ALG_AES_XTS || algorithm == TEE_ALG_SM2_KEP || + algorithm == TEE_ALG_SM4_XTS) + handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; + + /* Check algorithm max key size */ + switch (algorithm) { + case TEE_ALG_DSA_SHA1: + if (maxKeySize < 512) + return TEE_ERROR_NOT_SUPPORTED; + if (maxKeySize > 1024) + return TEE_ERROR_NOT_SUPPORTED; + if (maxKeySize % 64 != 0) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_DSA_SHA224: + if (maxKeySize != 2048) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_DSA_SHA256: + if (maxKeySize != 2048 && maxKeySize != 3072) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_ECDSA_SHA1: + case __OPTEE_ALG_ECDSA_P192: + case __OPTEE_ALG_ECDH_P192: + if (maxKeySize != 192) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_ECDSA_SHA224: + case __OPTEE_ALG_ECDSA_P224: + case __OPTEE_ALG_ECDH_P224: + if (maxKeySize != 224) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_ECDSA_SHA256: + case __OPTEE_ALG_ECDSA_P256: + case __OPTEE_ALG_ECDH_P256: + case TEE_ALG_SM2_PKE: + case TEE_ALG_SM2_DSA_SM3: + if (maxKeySize != 256) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_SM2_KEP: + /* Two 256-bit keys */ + if (maxKeySize != 512) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_ECDSA_SHA384: + case __OPTEE_ALG_ECDSA_P384: + case __OPTEE_ALG_ECDH_P384: + if (maxKeySize != 384) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_ECDSA_SHA512: + case __OPTEE_ALG_ECDSA_P521: + case __OPTEE_ALG_ECDH_P521: + if (maxKeySize != 521) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_ECDH_DERIVE_SHARED_SECRET: + if (maxKeySize > 521) + return TEE_ERROR_NOT_SUPPORTED; + break; + + case TEE_ALG_ED25519: + case TEE_ALG_X25519: + if (maxKeySize != 256) + return TEE_ERROR_NOT_SUPPORTED; + break; + default: + break; + } + + /* Check algorithm mode (and maxKeySize for digests) */ + switch (algorithm) { + case TEE_ALG_AES_CTS: + case TEE_ALG_AES_XTS: + case TEE_ALG_SM4_XTS: + buffer_two_blocks = true; + fallthrough; + case TEE_ALG_AES_ECB_NOPAD: + case TEE_ALG_AES_CBC_NOPAD: + case TEE_ALG_AES_CCM: + case TEE_ALG_DES_ECB_NOPAD: + case TEE_ALG_DES_CBC_NOPAD: + case TEE_ALG_DES3_ECB_NOPAD: + case TEE_ALG_DES3_CBC_NOPAD: + case TEE_ALG_SM4_ECB_NOPAD: + case TEE_ALG_SM4_CBC_NOPAD: + case TEE_ALG_SM4_CTR: + if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES) + block_size = TEE_AES_BLOCK_SIZE; + else if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_SM4) + block_size = TEE_SM4_BLOCK_SIZE; + else + block_size = TEE_DES_BLOCK_SIZE; + fallthrough; + case TEE_ALG_AES_CTR: + case TEE_ALG_AES_GCM: + 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; + +#if defined(CFG_CRYPTO_RSASSA_NA1) + case TEE_ALG_RSASSA_PKCS1_V1_5: +#endif + 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_MD5: + 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: + case TEE_ALG_DSA_SHA224: + case TEE_ALG_DSA_SHA256: + case TEE_ALG_ECDSA_SHA1: + case TEE_ALG_ECDSA_SHA224: + case TEE_ALG_ECDSA_SHA256: + case TEE_ALG_ECDSA_SHA384: + case TEE_ALG_ECDSA_SHA512: + case __OPTEE_ALG_ECDSA_P192: + case __OPTEE_ALG_ECDSA_P224: + case __OPTEE_ALG_ECDSA_P256: + case __OPTEE_ALG_ECDSA_P384: + case __OPTEE_ALG_ECDSA_P521: + case TEE_ALG_SM2_DSA_SM3: + case TEE_ALG_ED25519: + 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_MD5: + 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: + case TEE_ALG_SM2_PKE: + 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: + case TEE_ALG_ECDH_DERIVE_SHARED_SECRET: + case __OPTEE_ALG_ECDH_P192: + case __OPTEE_ALG_ECDH_P224: + case __OPTEE_ALG_ECDH_P256: + case __OPTEE_ALG_ECDH_P384: + case __OPTEE_ALG_ECDH_P521: + case TEE_ALG_HKDF_MD5_DERIVE_KEY: + case TEE_ALG_HKDF_SHA1_DERIVE_KEY: + case TEE_ALG_HKDF_SHA224_DERIVE_KEY: + case TEE_ALG_HKDF_SHA256_DERIVE_KEY: + case TEE_ALG_HKDF_SHA384_DERIVE_KEY: + case TEE_ALG_HKDF_SHA512_DERIVE_KEY: + case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY: + case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY: + case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY: + case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY: + case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY: + case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY: + case TEE_ALG_SM2_KEP: + case TEE_ALG_X25519: + 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: + case TEE_ALG_SHA3_224: + case TEE_ALG_SHA3_256: + case TEE_ALG_SHA3_384: + case TEE_ALG_SHA3_512: + case TEE_ALG_SHAKE128: + case TEE_ALG_SHAKE256: + case TEE_ALG_SM3: + if (mode != TEE_MODE_DIGEST) + return TEE_ERROR_NOT_SUPPORTED; + if (maxKeySize) + return TEE_ERROR_NOT_SUPPORTED; + /* v1.1: flags always set for digest operations */ + 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_DES3_CMAC: + 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: + case TEE_ALG_HMAC_SHA3_224: + case TEE_ALG_HMAC_SHA3_256: + case TEE_ALG_HMAC_SHA3_384: + case TEE_ALG_HMAC_SHA3_512: + case TEE_ALG_HMAC_SM3: + 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), TEE_MALLOC_FILL_ZERO); + if (!op) + return TEE_ERROR_OUT_OF_MEMORY; + + op->info.algorithm = algorithm; + op->info.operationClass = TEE_ALG_GET_CLASS(algorithm); +#ifdef CFG_CRYPTO_RSASSA_NA1 + if (algorithm == TEE_ALG_RSASSA_PKCS1_V1_5) + op->info.operationClass = TEE_OPERATION_ASYMMETRIC_SIGNATURE; +#endif + op->info.mode = mode; + op->info.digestLength = TEE_ALG_GET_DIGEST_SIZE(algorithm); + op->info.maxKeySize = maxKeySize; + op->info.requiredKeyUsage = req_key_usage; + op->info.handleState = handle_state; + + /* + * Needed to buffer the digest if TEE_DigestExtract() doesn't + * retrieve the entire digest in one go. + */ + if (op->info.operationClass == TEE_OPERATION_DIGEST) + block_size = op->info.digestLength; + + 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) { + res = TEE_AllocateTransientObject(key_type, mks, + &op->key2); + if (res != TEE_SUCCESS) + goto out; + } + } + + res = _utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1, + (unsigned long)op->key2, &op->state); + if (res != TEE_SUCCESS) + goto out; + + /* + * Initialize digest operations + * Other multi-stage operations initialized w/ TEE_xxxInit functions + * Non-applicable on asymmetric operations + */ + if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) { + res = _utee_hash_init(op->state, NULL, 0); + if (res != TEE_SUCCESS) + goto out; + /* v1.1: flags always set for digest operations */ + op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; + } + + op->operationState = TEE_OPERATION_STATE_INITIAL; + + *operation = op; + +out: + if (res != TEE_SUCCESS) { + if (res != TEE_ERROR_OUT_OF_MEMORY && + res != TEE_ERROR_NOT_SUPPORTED) + TEE_Panic(res); + if (op) { + if (op->state) { + TEE_FreeOperation(op); + } else { + TEE_Free(op->buffer); + TEE_FreeTransientObject(op->key1); + TEE_FreeTransientObject(op->key2); + TEE_Free(op); + } + } + } + + return res; +} + +void TEE_FreeOperation(TEE_OperationHandle operation) +{ + TEE_Result res; + + if (operation == TEE_HANDLE_NULL) + return; + + /* + * Note that keys should not be freed here, since they are + * claimed by the operation they will be freed by + * utee_cryp_state_free(). + */ + res = _utee_cryp_state_free(operation->state); + if (res != TEE_SUCCESS) + TEE_Panic(res); + + TEE_Free(operation->buffer); + TEE_Free(operation); +} + +void __GP11_TEE_FreeOperation(TEE_OperationHandle operation) +{ + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + TEE_FreeOperation(operation); +} + +void TEE_GetOperationInfo(TEE_OperationHandle operation, + TEE_OperationInfo *operationInfo) +{ + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + + __utee_check_out_annotation(operationInfo, sizeof(*operationInfo)); + + *operationInfo = operation->info; + if (operationInfo->handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) { + operationInfo->keySize = 0; + operationInfo->requiredKeyUsage = 0; + } +} + +TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle op, + TEE_OperationInfoMultiple *op_info, + size_t *size) +{ + TEE_Result res = TEE_SUCCESS; + TEE_ObjectInfo kinfo = { }; + size_t max_key_count = 0; + bool two_keys = false; + + if (op == TEE_HANDLE_NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + __utee_check_outbuf_annotation(op_info, size); + + if (*size < sizeof(*op_info)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + max_key_count = (*size - sizeof(*op_info)) / + sizeof(TEE_OperationInfoKey); + + TEE_MemFill(op_info, 0, *size); + + /* Two keys flag (TEE_ALG_AES_XTS only) */ + two_keys = op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; + + if (op->info.mode == TEE_MODE_DIGEST) { + op_info->numberOfKeys = 0; + } else if (!two_keys) { + if (max_key_count < 1) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = TEE_GetObjectInfo1(op->key1, &kinfo); + /* Key1 is not a valid handle, "can't happen". */ + if (res) + goto out; + + op_info->keyInformation[0].keySize = kinfo.objectSize; + op_info->keyInformation[0].requiredKeyUsage = + op->info.requiredKeyUsage; + op_info->numberOfKeys = 1; + } else { + if (max_key_count < 2) { + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + res = TEE_GetObjectInfo1(op->key1, &kinfo); + /* Key1 is not a valid handle, "can't happen". */ + if (res) + goto out; + + op_info->keyInformation[0].keySize = kinfo.objectSize; + op_info->keyInformation[0].requiredKeyUsage = + op->info.requiredKeyUsage; + + res = TEE_GetObjectInfo1(op->key2, &kinfo); + /* Key2 is not a valid handle, "can't happen". */ + if (res) + goto out; + + op_info->keyInformation[1].keySize = kinfo.objectSize; + op_info->keyInformation[1].requiredKeyUsage = + op->info.requiredKeyUsage; + + op_info->numberOfKeys = 2; + } + + op_info->algorithm = op->info.algorithm; + op_info->operationClass = op->info.operationClass; + op_info->mode = op->info.mode; + op_info->digestLength = op->info.digestLength; + op_info->maxKeySize = op->info.maxKeySize; + op_info->handleState = op->info.handleState; + op_info->operationState = op->operationState; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +TEE_Result +__GP11_TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, + TEE_OperationInfoMultiple *info, + uint32_t *operationSize) +{ + TEE_Result res = TEE_SUCCESS; + size_t s = 0; + + __utee_check_gp11_outbuf_annotation(info, operationSize); + s = *operationSize; + res = TEE_GetOperationInfoMultiple(operation, info, &s); + *operationSize = s; + return res; +} + +static void reset_operation_state(TEE_OperationHandle op) +{ + op->operationState = TEE_OPERATION_STATE_INITIAL; + + if (op->info.operationClass == TEE_OPERATION_DIGEST) { + TEE_Result res = _utee_hash_init(op->state, NULL, 0); + + if (res != TEE_SUCCESS) + TEE_Panic(res); + op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; + } else { + op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + } +} + +void TEE_ResetOperation(TEE_OperationHandle operation) +{ + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) + TEE_Panic(0); + + reset_operation_state(operation); +} + +TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, + TEE_ObjectHandle key) +{ + TEE_Result res; + uint32_t key_size = 0; + TEE_ObjectInfo key_info; + + if (operation == TEE_HANDLE_NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (key == TEE_HANDLE_NULL) { + /* Operation key cleared */ + TEE_ResetTransientObject(operation->key1); + operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; + if (operation->operationState != TEE_OPERATION_STATE_INITIAL) + reset_operation_state(operation); + return TEE_SUCCESS; + } + + /* No key for digest operation */ + if (operation->info.operationClass == TEE_OPERATION_DIGEST) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */ + if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != + 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = TEE_GetObjectInfo1(key, &key_info); + /* Key is not a valid handle */ + if (res != TEE_SUCCESS) + goto out; + + /* Supplied key has to meet required usage */ + if ((key_info.objectUsage & operation->info.requiredKeyUsage) != + operation->info.requiredKeyUsage) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (operation->info.maxKeySize < key_info.objectSize) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + key_size = key_info.objectSize; + + TEE_ResetTransientObject(operation->key1); + operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; + + res = TEE_CopyObjectAttributes1(operation->key1, key); + if (res != TEE_SUCCESS) + goto out; + + operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; + + operation->info.keySize = key_size; + + if (operation->operationState != TEE_OPERATION_STATE_INITIAL) + reset_operation_state(operation); + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_SetOperationKey(TEE_OperationHandle operation, + TEE_ObjectHandle key) +{ + if (operation == TEE_HANDLE_NULL || + operation->operationState != TEE_OPERATION_STATE_INITIAL) + TEE_Panic(0); + + return TEE_SetOperationKey(operation, key); +} + +static TEE_Result set_operation_key2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, + TEE_ObjectHandle key2) +{ + TEE_Result res; + uint32_t key_size = 0; + TEE_ObjectInfo key_info1; + TEE_ObjectInfo key_info2; + + if (operation == TEE_HANDLE_NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * Key1/Key2 and/or are not initialized and + * Either both keys are NULL or both are not NULL + */ + if (!key1 && !key2) { + /* Clear the keys */ + TEE_ResetTransientObject(operation->key1); + TEE_ResetTransientObject(operation->key2); + operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; + if (operation->operationState != TEE_OPERATION_STATE_INITIAL) + reset_operation_state(operation); + return TEE_SUCCESS; + } else if (!key1 || !key2) { + /* Both keys are obviously not valid. */ + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* No key for digest operation */ + if (operation->info.operationClass == TEE_OPERATION_DIGEST) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* Two keys flag expected (TEE_ALG_AES_XTS and TEE_ALG_SM2_KEP only) */ + if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == + 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = TEE_GetObjectInfo1(key1, &key_info1); + /* Key1 is not a valid handle */ + if (res != TEE_SUCCESS) + goto out; + + /* Supplied key has to meet required usage */ + if ((key_info1.objectUsage & operation->info. + requiredKeyUsage) != operation->info.requiredKeyUsage) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = TEE_GetObjectInfo1(key2, &key_info2); + /* Key2 is not a valid handle */ + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_CORRUPT_OBJECT) + res = TEE_ERROR_CORRUPT_OBJECT_2; + goto out; + } + + /* Supplied key has to meet required usage */ + if ((key_info2.objectUsage & operation->info. + requiredKeyUsage) != operation->info.requiredKeyUsage) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * All the multi key algorithm currently supported requires the keys to + * be of equal size. + */ + if (key_info1.objectSize != key_info2.objectSize) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + + } + + if (operation->info.maxKeySize < key_info1.objectSize) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * 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; + + res = TEE_CopyObjectAttributes1(operation->key1, key1); + if (res != TEE_SUCCESS) + goto out; + res = TEE_CopyObjectAttributes1(operation->key2, key2); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_CORRUPT_OBJECT) + res = TEE_ERROR_CORRUPT_OBJECT_2; + goto out; + } + + operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; + + operation->info.keySize = key_size; + + if (operation->operationState != TEE_OPERATION_STATE_INITIAL) + reset_operation_state(operation); +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_CORRUPT_OBJECT && + res != TEE_ERROR_CORRUPT_OBJECT_2 && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE && + res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2) + TEE_Panic(res); + + return res; +} + +TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, TEE_ObjectHandle key2) +{ + if (operation != TEE_HANDLE_NULL && key1 && key1 == key2) + return TEE_ERROR_SECURITY; + + return set_operation_key2(operation, key1, key2); +} + +TEE_Result __GP11_TEE_SetOperationKey2(TEE_OperationHandle operation, + TEE_ObjectHandle key1, + TEE_ObjectHandle key2) +{ + if (operation == TEE_HANDLE_NULL || + operation->operationState != TEE_OPERATION_STATE_INITIAL) + TEE_Panic(0); + + return set_operation_key2(operation, key1, key2); +} + +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 (dst_op->info.mode != src_op->info.mode) + 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; + dst_op->info.digestLength = src_op->info.digestLength; + dst_op->operationState = src_op->operationState; + + 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) { + size_t sz = src_op->block_size; + + if (src_op->buffer == NULL) + TEE_Panic(0); + + if (src_op->buffer_two_blocks) + sz *= 2; + memcpy(dst_op->buffer, src_op->buffer, sz); + 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 */ + +static void init_hash_operation(TEE_OperationHandle operation, const void *IV, + uint32_t IVLen) +{ + TEE_Result res; + + /* + * Note : IV and IVLen are never used in current implementation + * This is why coherent values of IV and IVLen are not checked + */ + 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_DigestUpdate(TEE_OperationHandle operation, + const void *chunk, size_t chunkSize) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (operation == TEE_HANDLE_NULL || + operation->info.operationClass != TEE_OPERATION_DIGEST) + TEE_Panic(0); + + operation->operationState = TEE_OPERATION_STATE_ACTIVE; + + res = _utee_hash_update(operation->state, chunk, chunkSize); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +void __GP11_TEE_DigestUpdate(TEE_OperationHandle operation, + const void *chunk, uint32_t chunkSize) +{ + return TEE_DigestUpdate(operation, chunk, chunkSize); +} + +TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, + size_t chunkLen, void *hash, size_t *hashLen) +{ + TEE_Result res = TEE_SUCCESS; + uint64_t hl = 0; + size_t len = 0; + + if ((operation == TEE_HANDLE_NULL) || + (!chunk && chunkLen) || + (operation->info.operationClass != TEE_OPERATION_DIGEST)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + if (operation->operationState == TEE_OPERATION_STATE_EXTRACTING && + chunkLen) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + __utee_check_inout_annotation(hashLen, sizeof(*hashLen)); + + if (operation->operationState == TEE_OPERATION_STATE_EXTRACTING && + operation->buffer) { + /* + * This is not an Extendable-Output Function and we have + * already started extracting + */ + len = MIN(operation->block_size - operation->buffer_offs, + *hashLen); + memcpy(hash, operation->buffer + operation->buffer_offs, len); + *hashLen = len; + } else { + hl = *hashLen; + res = _utee_hash_final(operation->state, chunk, chunkLen, hash, + &hl); + *hashLen = hl; + if (res) + goto out; + } + + /* Reset operation state */ + init_hash_operation(operation, NULL, 0); + + operation->operationState = TEE_OPERATION_STATE_INITIAL; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_DigestDoFinal(TEE_OperationHandle operation, + const void *chunk, uint32_t chunkLen, + void *hash, uint32_t *hashLen) +{ + TEE_Result res = TEE_SUCCESS; + size_t l = 0; + + __utee_check_inout_annotation(hashLen, sizeof(*hashLen)); + l = *hashLen; + res = TEE_DigestDoFinal(operation, chunk, chunkLen, hash, &l); + *hashLen = l; + return res; +} + +TEE_Result TEE_DigestExtract(TEE_OperationHandle operation, void *hash, + size_t *hashLen) +{ + TEE_Result res = TEE_SUCCESS; + uint64_t hl = 0; + size_t len = 0; + + if (operation == TEE_HANDLE_NULL || + operation->info.operationClass != TEE_OPERATION_DIGEST) + TEE_Panic(0); + __utee_check_inout_annotation(hashLen, sizeof(*hashLen)); + + if (!operation->buffer) { + /* This is an Extendable-Output Function */ + operation->info.handleState |= TEE_HANDLE_FLAG_EXTRACTING; + operation->operationState = TEE_OPERATION_STATE_EXTRACTING; + hl = *hashLen; + res = _utee_hash_final(operation->state, NULL, 0, hash, &hl); + if (res) + TEE_Panic(0); + *hashLen = hl; + + return TEE_SUCCESS; + } + + if (operation->operationState != TEE_OPERATION_STATE_EXTRACTING) { + hl = operation->block_size; + res = _utee_hash_final(operation->state, NULL, 0, + operation->buffer, &hl); + if (res) + TEE_Panic(0); + if (hl != operation->block_size) + TEE_Panic(0); + assert(!operation->buffer_offs); + operation->info.handleState |= TEE_HANDLE_FLAG_EXTRACTING; + operation->operationState = TEE_OPERATION_STATE_EXTRACTING; + } + + len = MIN(operation->block_size - operation->buffer_offs, *hashLen); + memcpy(hash, operation->buffer + operation->buffer_offs, len); + *hashLen = len; + operation->buffer_offs += len; + + return TEE_SUCCESS; +} + +/* 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); + + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || + !(operation->key1)) + TEE_Panic(0); + + if (operation->operationState != TEE_OPERATION_STATE_INITIAL) + TEE_ResetOperation(operation); + + if (IV && IVLen) { + if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD || + operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD || + operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || + operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD) + TEE_Panic(0); + } + + operation->operationState = TEE_OPERATION_STATE_ACTIVE; + + 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; +} + +void __GP11_TEE_CipherInit(TEE_OperationHandle operation, const void *IV, + uint32_t IVLen) +{ + return TEE_CipherInit(operation, IV, IVLen); +} + +static TEE_Result tee_buffer_update( + TEE_OperationHandle op, + TEE_Result(*update_func)(unsigned long state, const void *src, + size_t slen, void *dst, uint64_t *dlen), + const void *src_data, size_t src_len, + void *dest_data, uint64_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; + uint64_t tmp_dlen; + size_t l; + size_t buffer_size; + size_t buffer_left; + + if (!src) { + if (slen) + TEE_Panic(0); + goto out; + } + + if (op->buffer_two_blocks) { + buffer_size = op->block_size * 2; + buffer_left = 1; + } else { + buffer_size = op->block_size; + buffer_left = 0; + } + + 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 + buffer_left))) { + l = 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_left)) { + /* Buffer is empty, feed as much as possible from src */ + if (op->info.algorithm == TEE_ALG_AES_CTS) + l = ROUNDUP(slen - buffer_size, op->block_size); + else + l = 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; + } + + /* 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 operation, const void *srcData, + size_t srcLen, void *destData, size_t *destLen) +{ + TEE_Result res; + size_t req_dlen; + uint64_t dl; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + + if (operation->info.operationClass != TEE_OPERATION_CIPHER) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (!srcData && !srcLen) { + *destLen = 0; + res = TEE_SUCCESS; + goto out; + } + + /* Calculate required dlen */ + if (operation->block_size > 1) { + req_dlen = ((operation->buffer_offs + srcLen) / + operation->block_size) * operation->block_size; + } else { + req_dlen = srcLen; + } + if (operation->buffer_two_blocks) { + if (req_dlen > operation->block_size * 2) + req_dlen -= operation->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; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + dl = *destLen; + if (operation->block_size > 1) { + res = tee_buffer_update(operation, _utee_cipher_update, srcData, + srcLen, destData, &dl); + } else { + if (srcLen > 0) { + res = _utee_cipher_update(operation->state, srcData, + srcLen, destData, &dl); + } else { + res = TEE_SUCCESS; + dl = 0; + } + } + *destLen = dl; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_CipherUpdate(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen) +{ + TEE_Result res = TEE_SUCCESS; + size_t dl = 0; + + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + dl = *destLen; + res = TEE_CipherUpdate(operation, srcData, srcLen, destData, &dl); + *destLen = dl; + return res; +} + +TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, + const void *srcData, size_t srcLen, + void *destData, size_t *destLen) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t *dst = destData; + size_t acc_dlen = 0; + uint64_t tmp_dlen = 0; + size_t req_dlen = 0; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + if (destLen) + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + + if (operation->info.operationClass != TEE_OPERATION_CIPHER) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * Check that the final block doesn't require padding for those + * algorithms that requires client to supply padding. + */ + if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD || + operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD || + operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD || + operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD || + operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || + operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD || + operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD || + operation->info.algorithm == TEE_ALG_SM4_CBC_NOPAD) { + if (((operation->buffer_offs + srcLen) % operation->block_size) + != 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + } + + /* + * 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 (operation->block_size > 1) { + req_dlen = operation->buffer_offs + srcLen; + } else { + req_dlen = srcLen; + } + if (destLen) + tmp_dlen = *destLen; + if (tmp_dlen < req_dlen) { + if (destLen) + *destLen = req_dlen; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + if (operation->block_size > 1) { + if (srcLen) { + res = tee_buffer_update(operation, _utee_cipher_update, + srcData, srcLen, dst, + &tmp_dlen); + if (res != TEE_SUCCESS) + goto out; + + dst += tmp_dlen; + acc_dlen += tmp_dlen; + + tmp_dlen = *destLen - acc_dlen; + } + res = _utee_cipher_final(operation->state, operation->buffer, + operation->buffer_offs, dst, + &tmp_dlen); + } else { + res = _utee_cipher_final(operation->state, srcData, srcLen, dst, + &tmp_dlen); + } + if (res != TEE_SUCCESS) + goto out; + + acc_dlen += tmp_dlen; + if (destLen) + *destLen = acc_dlen; + + operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + + operation->operationState = TEE_OPERATION_STATE_INITIAL; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_CipherDoFinal(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen) +{ + TEE_Result res = TEE_SUCCESS; + size_t dl = 0; + + if (destLen) { + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + dl = *destLen; + } + res = TEE_CipherDoFinal(operation, srcData, srcLen, destData, &dl); + if (destLen) + *destLen = dl; + return res; +} + +/* Cryptographic Operations API - MAC Functions */ + +void TEE_MACInit(TEE_OperationHandle operation, const void *IV, size_t IVLen) +{ + if (operation == TEE_HANDLE_NULL) + TEE_Panic(0); + + if (operation->info.operationClass != TEE_OPERATION_MAC) + TEE_Panic(0); + + if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || + !(operation->key1)) + TEE_Panic(0); + + if (operation->operationState != TEE_OPERATION_STATE_INITIAL) + TEE_ResetOperation(operation); + + operation->operationState = TEE_OPERATION_STATE_ACTIVE; + + init_hash_operation(operation, IV, IVLen); +} + +void __GP11_TEE_MACInit(TEE_OperationHandle operation, const void *IV, + uint32_t IVLen) +{ + return TEE_MACInit(operation, IV, IVLen); +} + +void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, + size_t chunkSize) +{ + TEE_Result res; + + if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0)) + TEE_Panic(0); + + if (operation->info.operationClass != TEE_OPERATION_MAC) + TEE_Panic(0); + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) + TEE_Panic(0); + + res = _utee_hash_update(operation->state, chunk, chunkSize); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +void __GP11_TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, + uint32_t chunkSize) +{ + return TEE_MACUpdate(operation, chunk, chunkSize); +} + +TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, + const void *message, size_t messageLen, + void *mac, size_t *macLen) +{ + TEE_Result res; + uint64_t ml; + + if (operation == TEE_HANDLE_NULL || (!message && messageLen)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + __utee_check_inout_annotation(macLen, sizeof(*macLen)); + + if (operation->info.operationClass != TEE_OPERATION_MAC) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + ml = *macLen; + res = _utee_hash_final(operation->state, message, messageLen, mac, &ml); + *macLen = ml; + if (res != TEE_SUCCESS) + goto out; + + operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + + operation->operationState = TEE_OPERATION_STATE_INITIAL; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_MACComputeFinal(TEE_OperationHandle operation, + const void *message, uint32_t messageLen, + void *mac, uint32_t *macLen) +{ + TEE_Result res = TEE_SUCCESS; + size_t ml = 0; + + __utee_check_inout_annotation(macLen, sizeof(*macLen)); + ml = *macLen; + res = TEE_MACComputeFinal(operation, message, messageLen, mac, &ml); + *macLen = ml; + 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] = { 0 }; + size_t computed_mac_size = TEE_MAX_HASH_SIZE; + + if (operation->info.operationClass != TEE_OPERATION_MAC) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac, + &computed_mac_size); + if (res != TEE_SUCCESS) + goto out; + + if (computed_mac_size != macLen) { + res = TEE_ERROR_MAC_INVALID; + goto out; + } + + if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) { + res = TEE_ERROR_MAC_INVALID; + goto out; + } + + operation->operationState = TEE_OPERATION_STATE_INITIAL; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_MAC_INVALID) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_MACCompareFinal(TEE_OperationHandle operation, + const void *message, uint32_t messageLen, + const void *mac, uint32_t macLen) +{ + return TEE_MACCompareFinal(operation, message, messageLen, mac, macLen); +} + +/* Cryptographic Operations API - Authenticated Encryption Functions */ + +TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, + size_t nonceLen, uint32_t tagLen, size_t AADLen, + size_t payloadLen) +{ + TEE_Result res; + + if (operation == TEE_HANDLE_NULL || nonce == NULL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (operation->info.operationClass != TEE_OPERATION_AE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * 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 (operation->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)) { + res = TEE_ERROR_NOT_SUPPORTED; + goto out; + } + } + + res = _utee_authenc_init(operation->state, nonce, nonceLen, tagLen / 8, + AADLen, payloadLen); + if (res != TEE_SUCCESS) + goto out; + + operation->info.digestLength = tagLen / 8; + operation->buffer_offs = 0; + operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_NOT_SUPPORTED) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_AEInit(TEE_OperationHandle operation, const void *nonce, + uint32_t nonceLen, uint32_t tagLen, + uint32_t AADLen, uint32_t payloadLen) +{ + return TEE_AEInit(operation, nonce, nonceLen, tagLen, AADLen, + payloadLen); +} + +void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, + size_t AADdataLen) +{ + TEE_Result res = TEE_SUCCESS; + + if (operation == TEE_HANDLE_NULL || (!AADdata && AADdataLen)) + TEE_Panic(0); + + if (operation->info.operationClass != TEE_OPERATION_AE) + TEE_Panic(0); + + if (operation->operationState != TEE_OPERATION_STATE_INITIAL) + TEE_Panic(0); + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +void __GP11_TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, + uint32_t AADdataLen) +{ + TEE_Result res = TEE_SUCCESS; + + if (operation == TEE_HANDLE_NULL || + (AADdata == NULL && AADdataLen != 0)) + TEE_Panic(0); + + if (operation->info.operationClass != TEE_OPERATION_AE) + TEE_Panic(0); + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) + TEE_Panic(0); + + res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen); + + operation->operationState = TEE_OPERATION_STATE_ACTIVE; + + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +static TEE_Result ae_update_helper(TEE_OperationHandle operation, + const void *src, size_t slen, void *dst, + size_t *dlen) +{ + TEE_Result res = TEE_SUCCESS; + size_t req_dlen = 0; + uint64_t dl = 0; + + if (!src && !slen) { + *dlen = 0; + return TEE_SUCCESS; + } + + /* + * 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 (operation->block_size > 1) { + req_dlen = ROUNDDOWN(operation->buffer_offs + slen, + operation->block_size); + } else { + req_dlen = slen; + } + + dl = *dlen; + if (dl < req_dlen) { + *dlen = req_dlen; + return TEE_ERROR_SHORT_BUFFER; + } + + if (operation->block_size > 1) { + res = tee_buffer_update(operation, _utee_authenc_update_payload, + src, slen, dst, &dl); + } else { + if (slen > 0) { + res = _utee_authenc_update_payload(operation->state, + src, slen, dst, &dl); + } else { + dl = 0; + res = TEE_SUCCESS; + } + } + + if (!res) + *dlen = dl; + + return res; +} + +TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, + size_t srcLen, void *destData, size_t *destLen) +{ + TEE_Result res = TEE_SUCCESS; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + __utee_check_outbuf_annotation(destData, destLen); + + if (operation->info.operationClass != TEE_OPERATION_AE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + res = ae_update_helper(operation, srcData, srcLen, destData, destLen); + if (res != TEE_ERROR_SHORT_BUFFER && srcLen) + operation->operationState = TEE_OPERATION_STATE_ACTIVE; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_AEUpdate(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen) +{ + TEE_Result res = TEE_SUCCESS; + size_t dl = 0; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + __utee_check_gp11_outbuf_annotation(destData, destLen); + + if (operation->info.operationClass != TEE_OPERATION_AE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + dl = *destLen; + res = ae_update_helper(operation, srcData, srcLen, destData, &dl); + *destLen = dl; + + if (res != TEE_SUCCESS) + goto out; + + operation->operationState = TEE_OPERATION_STATE_ACTIVE; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +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 res = TEE_SUCCESS; + uint8_t *dst = destData; + size_t acc_dlen = 0; + uint64_t tmp_dlen = 0; + size_t req_dlen = 0; + uint64_t tl = 0; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + __utee_check_inout_annotation(tagLen, sizeof(*tagLen)); + + if (operation->info.operationClass != TEE_OPERATION_AE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * 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. + * + * Need to check this before update_payload since sync would be lost if + * we return short buffer after that. + */ + res = TEE_ERROR_GENERIC; + + req_dlen = operation->buffer_offs + srcLen; + if (*destLen < req_dlen) { + *destLen = req_dlen; + res = TEE_ERROR_SHORT_BUFFER; + } + + if (*tagLen < operation->info.digestLength) { + *tagLen = operation->info.digestLength; + res = TEE_ERROR_SHORT_BUFFER; + } + + if (res == TEE_ERROR_SHORT_BUFFER) + goto out; + + tl = *tagLen; + tmp_dlen = *destLen - acc_dlen; + if (operation->block_size > 1) { + res = tee_buffer_update(operation, _utee_authenc_update_payload, + srcData, srcLen, dst, &tmp_dlen); + if (res != TEE_SUCCESS) + goto out; + + dst += tmp_dlen; + acc_dlen += tmp_dlen; + + tmp_dlen = *destLen - acc_dlen; + res = _utee_authenc_enc_final(operation->state, + operation->buffer, + operation->buffer_offs, dst, + &tmp_dlen, tag, &tl); + } else { + res = _utee_authenc_enc_final(operation->state, srcData, + srcLen, dst, &tmp_dlen, + tag, &tl); + } + *tagLen = tl; + if (res != TEE_SUCCESS) + goto out; + + acc_dlen += tmp_dlen; + *destLen = acc_dlen; + + operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + + operation->operationState = TEE_OPERATION_STATE_INITIAL; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_AEEncryptFinal(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen, + void *tag, uint32_t *tagLen) +{ + TEE_Result res = TEE_SUCCESS; + size_t dl = 0; + size_t tl = 0; + + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + __utee_check_inout_annotation(tagLen, sizeof(*tagLen)); + dl = *destLen; + tl = *tagLen; + res = TEE_AEEncryptFinal(operation, srcData, srcLen, destData, &dl, + tag, &tl); + *destLen = dl; + *tagLen = tl; + return res; +} + +TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, + const void *srcData, size_t srcLen, + void *destData, size_t *destLen, void *tag, + size_t tagLen) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t *dst = destData; + size_t acc_dlen = 0; + uint64_t tmp_dlen = 0; + size_t req_dlen = 0; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + + if (operation->info.operationClass != TEE_OPERATION_AE) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + /* + * 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 = operation->buffer_offs + srcLen; + if (*destLen < req_dlen) { + *destLen = req_dlen; + res = TEE_ERROR_SHORT_BUFFER; + goto out; + } + + tmp_dlen = *destLen - acc_dlen; + if (operation->block_size > 1) { + res = tee_buffer_update(operation, _utee_authenc_update_payload, + srcData, srcLen, dst, &tmp_dlen); + if (res != TEE_SUCCESS) + goto out; + + dst += tmp_dlen; + acc_dlen += tmp_dlen; + + tmp_dlen = *destLen - acc_dlen; + res = _utee_authenc_dec_final(operation->state, + operation->buffer, + operation->buffer_offs, dst, + &tmp_dlen, tag, tagLen); + } else { + res = _utee_authenc_dec_final(operation->state, srcData, + srcLen, dst, &tmp_dlen, + tag, tagLen); + } + if (res != TEE_SUCCESS) + goto out; + + /* Supplied tagLen should match what we initiated with */ + if (tagLen != operation->info.digestLength) + res = TEE_ERROR_MAC_INVALID; + + acc_dlen += tmp_dlen; + *destLen = acc_dlen; + + operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; + + operation->operationState = TEE_OPERATION_STATE_INITIAL; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER && + res != TEE_ERROR_MAC_INVALID) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_AEDecryptFinal(TEE_OperationHandle operation, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen, + void *tag, uint32_t tagLen) +{ + TEE_Result res = TEE_SUCCESS; + size_t dl = 0; + + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + dl = *destLen; + res = TEE_AEDecryptFinal(operation, srcData, srcLen, destData, &dl, + tag, tagLen); + *destLen = dl; + return res; +} + +/* 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 res = TEE_SUCCESS; + struct utee_attribute ua[paramCount]; + uint64_t dl = 0; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) + TEE_Panic(0); + + __utee_check_attr_in_annotation(params, paramCount); + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + + if (!operation->key1) + TEE_Panic(0); + if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_ENCRYPT) + TEE_Panic(0); + + __utee_from_attr(ua, params, paramCount); + dl = *destLen; + res = _utee_asymm_operate(operation->state, ua, paramCount, srcData, + srcLen, destData, &dl); + *destLen = dl; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER && + res != TEE_ERROR_BAD_PARAMETERS && + res != TEE_ERROR_CIPHERTEXT_INVALID && + res != TEE_ERROR_NOT_SUPPORTED) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_AsymmetricEncrypt(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen) +{ + TEE_Result res = TEE_SUCCESS; + struct utee_attribute ua[paramCount]; + uint64_t dl = 0; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) + TEE_Panic(0); + + __utee_check_gp11_attr_in_annotation(params, paramCount); + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + + if (!operation->key1) + TEE_Panic(0); + if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_ENCRYPT) + TEE_Panic(0); + + __utee_from_gp11_attr(ua, params, paramCount); + dl = *destLen; + res = _utee_asymm_operate(operation->state, ua, paramCount, srcData, + srcLen, destData, &dl); + *destLen = dl; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER && + res != TEE_ERROR_BAD_PARAMETERS) + TEE_Panic(res); + + return res; +} + +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 res = TEE_SUCCESS; + struct utee_attribute ua[paramCount]; + uint64_t dl = 0; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) + TEE_Panic(0); + + __utee_check_attr_in_annotation(params, paramCount); + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + + if (!operation->key1) + TEE_Panic(0); + if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_DECRYPT) + TEE_Panic(0); + + __utee_from_attr(ua, params, paramCount); + dl = *destLen; + res = _utee_asymm_operate(operation->state, ua, paramCount, srcData, + srcLen, destData, &dl); + *destLen = dl; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER && + res != TEE_ERROR_BAD_PARAMETERS && + res != TEE_ERROR_CIPHERTEXT_INVALID && + res != TEE_ERROR_NOT_SUPPORTED) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_AsymmetricDecrypt(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, + const void *srcData, uint32_t srcLen, + void *destData, uint32_t *destLen) +{ + TEE_Result res = TEE_SUCCESS; + struct utee_attribute ua[paramCount]; + uint64_t dl = 0; + + if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) + TEE_Panic(0); + + __utee_check_gp11_attr_in_annotation(params, paramCount); + __utee_check_inout_annotation(destLen, sizeof(*destLen)); + + if (!operation->key1) + TEE_Panic(0); + if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_DECRYPT) + TEE_Panic(0); + + __utee_from_gp11_attr(ua, params, paramCount); + dl = *destLen; + res = _utee_asymm_operate(operation->state, ua, paramCount, srcData, + srcLen, destData, &dl); + *destLen = dl; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_SHORT_BUFFER && + res != TEE_ERROR_BAD_PARAMETERS) + TEE_Panic(res); + + return res; +} + +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 res = TEE_SUCCESS; + struct utee_attribute ua[paramCount]; + uint64_t sl = 0; + + if (operation == TEE_HANDLE_NULL || (!digest && digestLen)) + TEE_Panic(0); + + __utee_check_attr_in_annotation(params, paramCount); + __utee_check_inout_annotation(signatureLen, sizeof(*signatureLen)); + + if (!operation->key1) + TEE_Panic(0); + if (operation->info.operationClass != + TEE_OPERATION_ASYMMETRIC_SIGNATURE) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_SIGN) + TEE_Panic(0); + + __utee_from_attr(ua, params, paramCount); + sl = *signatureLen; + res = _utee_asymm_operate(operation->state, ua, paramCount, digest, + digestLen, signature, &sl); + *signatureLen = sl; + + if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_AsymmetricSignDigest(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, + const void *digest, + uint32_t digestLen, void *signature, + uint32_t *signatureLen) +{ + TEE_Result res = TEE_SUCCESS; + struct utee_attribute ua[paramCount]; + uint64_t sl = 0; + + if (operation == TEE_HANDLE_NULL || (!digest && digestLen)) + TEE_Panic(0); + + __utee_check_gp11_attr_in_annotation(params, paramCount); + __utee_check_inout_annotation(signatureLen, sizeof(*signatureLen)); + + if (!operation->key1) + TEE_Panic(0); + if (operation->info.operationClass != + TEE_OPERATION_ASYMMETRIC_SIGNATURE) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_SIGN) + TEE_Panic(0); + + __utee_from_gp11_attr(ua, params, paramCount); + sl = *signatureLen; + res = _utee_asymm_operate(operation->state, ua, paramCount, digest, + digestLen, signature, &sl); + *signatureLen = sl; + + if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(res); + + return res; +} + +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) +{ + TEE_Result res; + struct utee_attribute ua[paramCount]; + + if (operation == TEE_HANDLE_NULL || + (digest == NULL && digestLen != 0) || + (signature == NULL && signatureLen != 0)) + TEE_Panic(0); + + __utee_check_attr_in_annotation(params, paramCount); + + if (!operation->key1) + TEE_Panic(0); + if (operation->info.operationClass != + TEE_OPERATION_ASYMMETRIC_SIGNATURE) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_VERIFY) + TEE_Panic(0); + + __utee_from_attr(ua, params, paramCount); + res = _utee_asymm_verify(operation->state, ua, paramCount, digest, + digestLen, signature, signatureLen); + + if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID) + TEE_Panic(res); + + return res; +} + +TEE_Result __GP11_TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, + const void *digest, + uint32_t digestLen, + const void *signature, + uint32_t signatureLen) +{ + TEE_Result res = TEE_SUCCESS; + struct utee_attribute ua[paramCount]; + + if (operation == TEE_HANDLE_NULL || (!digest && digestLen) || + (!signature && signatureLen)) + TEE_Panic(0); + + __utee_check_gp11_attr_in_annotation(params, paramCount); + + if (!operation->key1) + TEE_Panic(0); + if (operation->info.operationClass != + TEE_OPERATION_ASYMMETRIC_SIGNATURE) + TEE_Panic(0); + if (operation->info.mode != TEE_MODE_VERIFY) + TEE_Panic(0); + + __utee_from_gp11_attr(ua, params, paramCount); + res = _utee_asymm_verify(operation->state, ua, 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) +{ + struct utee_attribute ua[paramCount]; + struct utee_object_info key_info = { }; + TEE_Result res = TEE_SUCCESS; + + if (operation == TEE_HANDLE_NULL || derivedKey == 0) + TEE_Panic(0); + + __utee_check_attr_in_annotation(params, paramCount); + + if (TEE_ALG_GET_CLASS(operation->info.algorithm) != + TEE_OPERATION_KEY_DERIVATION) + TEE_Panic(0); + + if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) + TEE_Panic(0); + if (!operation->key1) + 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((unsigned long)derivedKey, &key_info); + if (res != TEE_SUCCESS) + TEE_Panic(res); + + if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET) + TEE_Panic(0); + if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + TEE_Panic(0); + + __utee_from_attr(ua, params, paramCount); + res = _utee_cryp_derive_key(operation->state, ua, paramCount, + (unsigned long)derivedKey); + if (res != TEE_SUCCESS) + TEE_Panic(res); +} + +void __GP11_TEE_DeriveKey(TEE_OperationHandle operation, + const __GP11_TEE_Attribute *params, + uint32_t paramCount, TEE_ObjectHandle derivedKey) +{ + struct utee_attribute ua[paramCount]; + struct utee_object_info key_info = { }; + TEE_Result res = TEE_SUCCESS; + + if (operation == TEE_HANDLE_NULL || derivedKey == 0) + TEE_Panic(0); + + __utee_check_gp11_attr_in_annotation(params, paramCount); + + if (TEE_ALG_GET_CLASS(operation->info.algorithm) != + TEE_OPERATION_KEY_DERIVATION) + TEE_Panic(0); + + if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) + TEE_Panic(0); + if (!operation->key1) + 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((unsigned long)derivedKey, &key_info); + if (res != TEE_SUCCESS) + TEE_Panic(res); + + if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET) + TEE_Panic(0); + if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0) + TEE_Panic(0); + + __utee_from_gp11_attr(ua, params, paramCount); + res = _utee_cryp_derive_key(operation->state, ua, paramCount, + (unsigned long)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); +} + +void __GP11_TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen) +{ + TEE_GenerateRandom(randomBuffer, randomBufferLen); +} + +int rand(void) +{ + int rc; + + TEE_GenerateRandom(&rc, sizeof(rc)); + + /* + * RAND_MAX is the larges int, INT_MAX which is all bits but the + * highest bit set. + */ + return rc & RAND_MAX; +} + +TEE_Result TEE_IsAlgorithmSupported(uint32_t alg, uint32_t element) +{ + if (IS_ENABLED(CFG_CRYPTO_AES)) { + if (IS_ENABLED(CFG_CRYPTO_ECB)) { + if (alg == TEE_ALG_AES_ECB_NOPAD) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CBC)) { + if (alg == TEE_ALG_AES_CBC_NOPAD) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CTR)) { + if (alg == TEE_ALG_AES_CTR) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CTS)) { + if (alg == TEE_ALG_AES_CTS) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_XTS)) { + if (alg == TEE_ALG_AES_XTS) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) { + if (alg == TEE_ALG_AES_CBC_MAC_NOPAD || + alg == TEE_ALG_AES_CBC_MAC_PKCS5) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CMAC)) { + if (alg == TEE_ALG_AES_CMAC) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CCM)) { + if (alg == TEE_ALG_AES_CCM) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_GCM)) { + if (alg == TEE_ALG_AES_GCM) + goto check_element_none; + } + } + if (IS_ENABLED(CFG_CRYPTO_DES)) { + if (IS_ENABLED(CFG_CRYPTO_ECB)) { + if (alg == TEE_ALG_DES_ECB_NOPAD || + alg == TEE_ALG_DES3_ECB_NOPAD) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CBC)) { + if (alg == TEE_ALG_DES_CBC_NOPAD || + alg == TEE_ALG_DES3_CBC_NOPAD) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) { + if (alg == TEE_ALG_DES_CBC_MAC_NOPAD || + alg == TEE_ALG_DES_CBC_MAC_PKCS5 || + alg == TEE_ALG_DES3_CBC_MAC_NOPAD || + alg == TEE_ALG_DES3_CBC_MAC_PKCS5) + goto check_element_none; + } + } + if (IS_ENABLED(CFG_CRYPTO_MD5)) { + if (alg == TEE_ALG_MD5) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA1)) { + if (alg == TEE_ALG_SHA1) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA224)) { + if (alg == TEE_ALG_SHA224) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA256)) { + if (alg == TEE_ALG_SHA256) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA384)) { + if (alg == TEE_ALG_SHA384) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA512)) { + if (alg == TEE_ALG_SHA512) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA3_224)) { + if (alg == TEE_ALG_SHA3_224) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA3_256)) { + if (alg == TEE_ALG_SHA3_256) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA3_384)) { + if (alg == TEE_ALG_SHA3_384) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA3_512)) { + if (alg == TEE_ALG_SHA3_512) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) { + if (alg == TEE_ALG_MD5SHA1) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_HMAC)) { + if (IS_ENABLED(CFG_CRYPTO_MD5)) { + if (alg == TEE_ALG_HMAC_MD5) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA1)) { + if (alg == TEE_ALG_HMAC_SHA1) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA224)) { + if (alg == TEE_ALG_HMAC_SHA224) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA256)) { + if (alg == TEE_ALG_HMAC_SHA256) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA384)) { + if (alg == TEE_ALG_HMAC_SHA384) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA512)) { + if (alg == TEE_ALG_HMAC_SHA512) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA3_224)) { + if (alg == TEE_ALG_HMAC_SHA3_224) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA3_256)) { + if (alg == TEE_ALG_HMAC_SHA3_256) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA3_384)) { + if (alg == TEE_ALG_HMAC_SHA3_384) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA3_512)) { + if (alg == TEE_ALG_HMAC_SHA3_512) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SM3)) { + if (alg == TEE_ALG_HMAC_SM3) + goto check_element_none; + } + } + if (IS_ENABLED(CFG_CRYPTO_SM3)) { + if (alg == TEE_ALG_SM3) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SM4)) { + if (IS_ENABLED(CFG_CRYPTO_ECB)) { + if (alg == TEE_ALG_SM4_ECB_NOPAD) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CBC)) { + if (alg == TEE_ALG_SM4_CBC_NOPAD) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_CTR)) { + if (alg == TEE_ALG_SM4_CTR) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_XTS)) { + if (alg == TEE_ALG_SM4_XTS) + goto check_element_none; + } + } + if (IS_ENABLED(CFG_CRYPTO_RSA)) { + if (IS_ENABLED(CFG_CRYPTO_MD5)) { + if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5 || + alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5 || + alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA1)) { + if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 || + alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 || + alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) { + if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA224)) { + if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 || + alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 || + alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA256)) { + if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 || + alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 || + alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA384)) { + if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 || + alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 || + alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA512)) { + if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 || + alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 || + alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) { + if (alg == TEE_ALG_RSASSA_PKCS1_V1_5) + goto check_element_none; + } + if (alg == TEE_ALG_RSA_NOPAD) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_DSA)) { + if (IS_ENABLED(CFG_CRYPTO_SHA1)) { + if (alg == TEE_ALG_DSA_SHA1) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA224)) { + if (alg == TEE_ALG_DSA_SHA224) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_SHA256)) { + if (alg == TEE_ALG_DSA_SHA256) + goto check_element_none; + } + } + if (IS_ENABLED(CFG_CRYPTO_DH)) { + if (alg == TEE_ALG_DH_DERIVE_SHARED_SECRET) + goto check_element_none; + } + if (IS_ENABLED(CFG_CRYPTO_ECC)) { + if ((alg == __OPTEE_ALG_ECDH_P192 || + alg == __OPTEE_ALG_ECDSA_P192 || + alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || + alg == TEE_ALG_ECDSA_SHA1) && + element == TEE_ECC_CURVE_NIST_P192) + return TEE_SUCCESS; + if ((alg == __OPTEE_ALG_ECDH_P224 || + alg == __OPTEE_ALG_ECDSA_P224 || + alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || + alg == TEE_ALG_ECDSA_SHA224) && + element == TEE_ECC_CURVE_NIST_P224) + return TEE_SUCCESS; + if ((alg == __OPTEE_ALG_ECDH_P256 || + alg == __OPTEE_ALG_ECDSA_P256 || + alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || + alg == TEE_ALG_ECDSA_SHA256) && + element == TEE_ECC_CURVE_NIST_P256) + return TEE_SUCCESS; + if ((alg == __OPTEE_ALG_ECDH_P384 || + alg == __OPTEE_ALG_ECDSA_P384 || + alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || + alg == TEE_ALG_ECDSA_SHA384) && + element == TEE_ECC_CURVE_NIST_P384) + return TEE_SUCCESS; + if ((alg == __OPTEE_ALG_ECDH_P521 || + alg == __OPTEE_ALG_ECDSA_P521 || + alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || + alg == TEE_ALG_ECDSA_SHA512) && + element == TEE_ECC_CURVE_NIST_P521) + return TEE_SUCCESS; + } + if (IS_ENABLED(CFG_CRYPTO_SM2_DSA)) { + if (alg == TEE_ALG_SM2_DSA_SM3 && element == TEE_ECC_CURVE_SM2) + return TEE_SUCCESS; + } + if (IS_ENABLED(CFG_CRYPTO_SM2_KEP)) { + if (alg == TEE_ALG_SM2_KEP && element == TEE_ECC_CURVE_SM2) + return TEE_SUCCESS; + } + if (IS_ENABLED(CFG_CRYPTO_SM2_PKE)) { + if (alg == TEE_ALG_SM2_PKE && element == TEE_ECC_CURVE_SM2) + return TEE_SUCCESS; + } + if (IS_ENABLED(CFG_CRYPTO_X25519)) { + if (alg == TEE_ALG_X25519 && element == TEE_ECC_CURVE_25519) + return TEE_SUCCESS; + } + if (IS_ENABLED(CFG_CRYPTO_ED25519)) { + if (alg == TEE_ALG_ED25519 && element == TEE_ECC_CURVE_25519) + return TEE_SUCCESS; + } + + return TEE_ERROR_NOT_SUPPORTED; +check_element_none: + if (element == TEE_CRYPTO_ELEMENT_NONE) + return TEE_SUCCESS; + return TEE_ERROR_NOT_SUPPORTED; +} diff --git a/optee/optee_os/lib/libutee/tee_api_panic.c b/optee/optee_os/lib/libutee/tee_api_panic.c new file mode 100644 index 0000000..35105bc --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api_panic.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "tee_api_private.h" + +#define ACCESS_RW (TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE) +#define ACCESS_W_ANY (TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER) +#define ACCESS_R TEE_MEMORY_ACCESS_READ +#define ACCESS_W TEE_MEMORY_ACCESS_WRITE + +/* System API - Misc */ + +void TEE_Panic(TEE_Result panicCode) +{ + _utee_panic(panicCode); +#ifdef __COVERITY__ + __coverity_panic__(); +#endif +} + +static void check_res(const char *msg __maybe_unused, TEE_Result res) +{ + if (res) { + DMSG("%s: error %#"PRIx32, msg, res); + TEE_Panic(0); + } +} + +static TEE_Result check_access(uint32_t flags, void *buf, size_t len) +{ + if (!len) + return TEE_SUCCESS; + + if (!buf) + return TEE_ERROR_SECURITY; + + if (IS_ENABLED(CFG_TA_STRICT_ANNOTATION_CHECKS)) + return TEE_CheckMemoryAccessRights(flags, buf, len); + + return TEE_SUCCESS; +} + +void __utee_check_outbuf_annotation(void *buf, size_t *len) +{ + check_res("[outbuf] len", + check_access(ACCESS_RW, len, sizeof(*len))); + check_res("[outbuf] buf", + check_access(ACCESS_W_ANY, buf, *len)); +} + +void __utee_check_gp11_outbuf_annotation(void *buf, uint32_t *len) +{ + check_res("[outbuf] len", + check_access(ACCESS_RW, len, sizeof(*len))); + check_res("[outbuf] buf", + check_access(ACCESS_W_ANY, buf, *len)); +} + +void __utee_check_instring_annotation(const char *buf) +{ + check_res("[instring]", + check_access(ACCESS_R, (char *)buf, strlen(buf) + 1)); +} + +void __utee_check_outstring_annotation(char *buf, size_t *len) +{ + check_res("[outstring] len", + check_access(ACCESS_RW, len, sizeof(*len))); + check_res("[outstring] buf", + check_access(ACCESS_W_ANY, buf, *len)); +} + +void __utee_check_gp11_outstring_annotation(char *buf, uint32_t *len) +{ + check_res("[outstring] len", + check_access(ACCESS_RW, len, sizeof(*len))); + check_res("[outstring] buf", + check_access(ACCESS_W_ANY, buf, *len)); +} + +void __utee_check_out_annotation(void *buf, const size_t len) +{ + check_res("[out]", + check_access(ACCESS_W, buf, len)); +} + +void __utee_check_attr_in_annotation(const TEE_Attribute *attr, size_t count) +{ + check_res("[in] attr", + check_access(ACCESS_R, (void *)attr, sizeof(*attr) * count)); +} + +void __utee_check_gp11_attr_in_annotation(const __GP11_TEE_Attribute *attr, + size_t count) + +{ + check_res("[in] attr", + check_access(ACCESS_R, (void *)attr, sizeof(*attr) * count)); +} + +void __utee_check_inout_annotation(void *buf, const size_t len) +{ + check_res("[inout]", + check_access(ACCESS_RW, buf, len)); +} diff --git a/optee/optee_os/lib/libutee/tee_api_private.h b/optee/optee_os/lib/libutee/tee_api_private.h new file mode 100644 index 0000000..2370372 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api_private.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2020, Linaro Limited + */ +#ifndef TEE_API_PRIVATE +#define TEE_API_PRIVATE + +#include +#include + + +void __utee_from_attr(struct utee_attribute *ua, const TEE_Attribute *attrs, + uint32_t attr_count); +void __utee_from_gp11_attr(struct utee_attribute *ua, + const __GP11_TEE_Attribute *attrs, + uint32_t attr_count); + +TEE_Result __utee_entry(unsigned long func, unsigned long session_id, + struct utee_params *up, unsigned long cmd_id); + + +#if defined(CFG_TA_GPROF_SUPPORT) +void __utee_gprof_init(void); +void __utee_gprof_fini(void); +#else +static inline void __utee_gprof_init(void) {} +static inline void __utee_gprof_fini(void) {} +#endif + +/* + * The functions help checking that the pointers comply with the parameters + * annotation as described in the spec. Any descrepency results in a panic + * of the TA. + */ +void __utee_check_out_annotation(void *buf, const size_t len); +void __utee_check_inout_annotation(void *buf, const size_t len); +void __utee_check_attr_in_annotation(const TEE_Attribute *attr, size_t count); +void __utee_check_gp11_attr_in_annotation(const __GP11_TEE_Attribute *attr, + size_t count); +void __utee_check_outbuf_annotation(void *buf, size_t *len); +void __utee_check_gp11_outbuf_annotation(void *buf, uint32_t *len); +void __utee_check_instring_annotation(const char *buf); +void __utee_check_outstring_annotation(char *buf, size_t *len); +void __utee_check_gp11_outstring_annotation(char *buf, uint32_t *len); + +#endif /*TEE_API_PRIVATE*/ diff --git a/optee/optee_os/lib/libutee/tee_api_property.c b/optee/optee_os/lib/libutee/tee_api_property.c new file mode 100644 index 0000000..3d6709a --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_api_property.c @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2017-2020, Linaro Limited + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "base64.h" +#include "string_ext.h" +#include "tee_api_private.h" + +#define PROP_STR_MAX 80 + +#define PROP_ENUMERATOR_NOT_STARTED 0xffffffff + +struct prop_enumerator { + uint32_t idx; /* current index */ + TEE_PropSetHandle prop_set; /* part of TEE_PROPSET_xxx */ +}; + +const struct user_ta_property tee_props[] = { + { + "gpd.tee.arith.maxBigIntSize", + USER_TA_PROP_TYPE_U32, + &(const uint32_t){CFG_TA_BIGNUM_MAX_BITS} + }, + { + "gpd.tee.sockets.version", + USER_TA_PROP_TYPE_U32, + &(const uint32_t){TEE_ISOCKET_VERSION} + }, + { + "gpd.tee.sockets.tcp.version", + USER_TA_PROP_TYPE_U32, + &(const uint32_t){TEE_ISOCKET_VERSION} + }, + { + "gpd.tee.internalCore.version", + USER_TA_PROP_TYPE_U32, + &(const uint32_t){TEE_CORE_API_VERSION} + }, +}; + +static TEE_Result propset_get(TEE_PropSetHandle h, + const struct user_ta_property **eps, + size_t *eps_len) +{ + if (h == TEE_PROPSET_CURRENT_TA) { + *eps = ta_props; + *eps_len = ta_num_props; + } else if (h == TEE_PROPSET_CURRENT_CLIENT) { + *eps = NULL; + *eps_len = 0; + } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { + *eps = tee_props; + *eps_len = ARRAY_SIZE(tee_props); + } else { + return TEE_ERROR_ITEM_NOT_FOUND; + } + + return TEE_SUCCESS; +} + +static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, + enum user_ta_prop_type *type, + void *buf, uint32_t *len) +{ + size_t l; + + *type = ep->type; + switch (*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_U64: + l = sizeof(uint64_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: + /* take the leading 0 into account */ + l = strlen(ep->value) + 1; + break; + case USER_TA_PROP_TYPE_BINARY_BLOCK: + /* + * in case of TA property, a binary block is provided as a + * string, which is base64 encoded. We must first decode it, + * without taking into account the zero termination of the + * string + */ + l = *len; + if (!_base64_dec(ep->value, strlen(ep->value), buf, &l) && + l <= *len) + return TEE_ERROR_GENERIC; + if (*len < l) { + *len = l; + return TEE_ERROR_SHORT_BUFFER; + } + + *len = l; + return TEE_SUCCESS; + default: + return TEE_ERROR_GENERIC; + } + + if (*len < l) { + *len = l; + return TEE_ERROR_SHORT_BUFFER; + } + + *len = l; + memcpy(buf, ep->value, l); + return TEE_SUCCESS; +} + +static bool is_propset_pseudo_handle(TEE_PropSetHandle h) +{ + return h == TEE_PROPSET_CURRENT_TA || + h == TEE_PROPSET_CURRENT_CLIENT || + h == TEE_PROPSET_TEE_IMPLEMENTATION; +} + +static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name, + enum user_ta_prop_type *type, + void *buf, uint32_t *len) +{ + TEE_Result res; + const struct user_ta_property *eps; + size_t eps_len; + uint32_t prop_type; + uint32_t index; + + if (is_propset_pseudo_handle(h)) { + size_t n; + + res = propset_get(h, &eps, &eps_len); + if (res != TEE_SUCCESS) + return res; + + for (n = 0; n < eps_len; n++) { + if (!strcmp(name, eps[n].name)) + return propget_get_ext_prop(eps + n, type, + buf, len); + } + + /* get the index from the name */ + res = _utee_get_property_name_to_index((unsigned long)h, name, + strlen(name) + 1, + &index); + if (res != TEE_SUCCESS) + return res; + res = _utee_get_property((unsigned long)h, index, NULL, NULL, + buf, len, &prop_type); + } 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, &eps, &eps_len); + if (res != TEE_SUCCESS) + return res; + + if (idx < eps_len) + return propget_get_ext_prop(eps + idx, type, buf, len); + idx -= eps_len; + + res = _utee_get_property((unsigned long)pe->prop_set, idx, + NULL, NULL, buf, len, &prop_type); + if (res == TEE_ERROR_ITEM_NOT_FOUND) + res = TEE_ERROR_BAD_PARAMETERS; + } + + *type = prop_type; + return res; +} + +TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, + const char *name, char *value, + size_t *value_len) +{ + TEE_Result res; + size_t l; + enum user_ta_prop_type type; + void *tmp_buf = 0; + uint32_t tmp_len; + uint32_t uint32_val; + bool bool_val; + TEE_Identity *p_identity_val; + + if (is_propset_pseudo_handle(propsetOrEnumerator)) + __utee_check_instring_annotation(name); + __utee_check_outstring_annotation(value, value_len); + + tmp_len = *value_len; + if (tmp_len < sizeof(TEE_Identity)) + tmp_len = sizeof(TEE_Identity); + tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!tmp_buf) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = propget_get_property(propsetOrEnumerator, name, &type, + tmp_buf, &tmp_len); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_SHORT_BUFFER) { + if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) { + /* + * in this case, we must enlarge the buffer + * with the size of the of the base64 encoded + * see base64_enc() function + */ + tmp_len = _base64_enc_len(tmp_len); + } + *value_len = tmp_len; + } + goto out; + } + + switch (type) { + case USER_TA_PROP_TYPE_BOOL: + bool_val = *((bool *)tmp_buf); + l = strlcpy(value, (bool_val ? "true" : "false"), *value_len); + break; + + case USER_TA_PROP_TYPE_U32: + uint32_val = *((uint32_t *)tmp_buf); + l = snprintf(value, *value_len, "%u", uint32_val); + break; + + case USER_TA_PROP_TYPE_UUID: + l = snprintk(value, *value_len, "%pUl", tmp_buf); + break; + + case USER_TA_PROP_TYPE_IDENTITY: + p_identity_val = ((TEE_Identity *)tmp_buf); + l = snprintk(value, *value_len, "%u:%pUl", + p_identity_val->login, + (void *)(&(p_identity_val->uuid))); + break; + + case USER_TA_PROP_TYPE_STRING: + l = strlcpy(value, tmp_buf, *value_len); + break; + + case USER_TA_PROP_TYPE_BINARY_BLOCK: + l = *value_len; /* l includes the zero-termination */ + if (!_base64_enc(tmp_buf, tmp_len, value, &l) && + l <= *value_len) { + res = TEE_ERROR_GENERIC; + goto out; + } + l--; /* remove the zero-termination that is added later */ + break; + + default: + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + l++; /* include zero termination */ + + if (l > *value_len) + res = TEE_ERROR_SHORT_BUFFER; + *value_len = l; + +out: + if (tmp_buf) + TEE_Free(tmp_buf); + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(0); + + return res; +} + +TEE_Result __GP11_TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, + const char *name, char *valueBuffer, + uint32_t *valueBufferLen) +{ + TEE_Result res = TEE_SUCCESS; + size_t l = 0; + + __utee_check_gp11_outstring_annotation(valueBuffer, valueBufferLen); + l = *valueBufferLen; + res = TEE_GetPropertyAsString(propsetOrEnumerator, name, valueBuffer, + &l); + *valueBufferLen = l; + return res; +} + +TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, + const char *name, bool *value) +{ + TEE_Result res; + enum user_ta_prop_type type; + uint32_t bool_len = sizeof(bool); + + if (is_propset_pseudo_handle(propsetOrEnumerator)) + __utee_check_instring_annotation(name); + __utee_check_out_annotation(value, sizeof(*value)); + + type = USER_TA_PROP_TYPE_BOOL; + res = propget_get_property(propsetOrEnumerator, name, &type, + value, &bool_len); + if (type != USER_TA_PROP_TYPE_BOOL) + res = TEE_ERROR_BAD_FORMAT; + if (res != TEE_SUCCESS) + goto out; + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_BAD_FORMAT) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, + const char *name, uint32_t *value) +{ + TEE_Result res; + enum user_ta_prop_type type; + uint32_t uint32_len = sizeof(uint32_t); + + if (is_propset_pseudo_handle(propsetOrEnumerator)) + __utee_check_instring_annotation(name); + __utee_check_out_annotation(value, sizeof(*value)); + + type = USER_TA_PROP_TYPE_U32; + res = propget_get_property(propsetOrEnumerator, name, &type, + value, &uint32_len); + if (type != USER_TA_PROP_TYPE_U32) + res = TEE_ERROR_BAD_FORMAT; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_BAD_FORMAT) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_GetPropertyAsU64(TEE_PropSetHandle propsetOrEnumerator, + const char *name, uint64_t *value) +{ + TEE_Result res; + enum user_ta_prop_type type; + uint32_t uint64_len = sizeof(*value); + + if (is_propset_pseudo_handle(propsetOrEnumerator)) + __utee_check_instring_annotation(name); + __utee_check_out_annotation(value, sizeof(*value)); + + type = USER_TA_PROP_TYPE_U64; + res = propget_get_property(propsetOrEnumerator, name, &type, + value, &uint64_len); + if (type != USER_TA_PROP_TYPE_U64) + res = TEE_ERROR_BAD_FORMAT; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_BAD_FORMAT) + TEE_Panic(0); + + return res; +} + +TEE_Result +__GP11_TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, + const char *name, void *value, + uint32_t *value_len) +{ + TEE_Result res = TEE_SUCCESS; + enum user_ta_prop_type type = USER_TA_PROP_TYPE_BOOL; + + if (is_propset_pseudo_handle(propsetOrEnumerator)) + __utee_check_instring_annotation(name); + __utee_check_gp11_outbuf_annotation(value, value_len); + + type = USER_TA_PROP_TYPE_BINARY_BLOCK; + res = propget_get_property(propsetOrEnumerator, name, &type, + value, value_len); + if (type != USER_TA_PROP_TYPE_BINARY_BLOCK) + res = TEE_ERROR_BAD_FORMAT; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_BAD_FORMAT && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, + const char *name, void *value, + size_t *value_len) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t l = 0; + + __utee_check_outbuf_annotation(value, value_len); + l = *value_len; + res = __GP11_TEE_GetPropertyAsBinaryBlock(propsetOrEnumerator, name, + value, &l); + *value_len = l; + return res; +} + +TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, + const char *name, TEE_UUID *value) +{ + TEE_Result res; + enum user_ta_prop_type type; + uint32_t uuid_len = sizeof(TEE_UUID); + + if (is_propset_pseudo_handle(propsetOrEnumerator)) + __utee_check_instring_annotation(name); + __utee_check_out_annotation(value, sizeof(*value)); + + type = USER_TA_PROP_TYPE_UUID; + res = propget_get_property(propsetOrEnumerator, name, &type, + value, &uuid_len); + if (type != USER_TA_PROP_TYPE_UUID) + res = TEE_ERROR_BAD_FORMAT; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_BAD_FORMAT) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, + const char *name, TEE_Identity *value) +{ + TEE_Result res; + enum user_ta_prop_type type; + uint32_t identity_len = sizeof(TEE_Identity); + + if (is_propset_pseudo_handle(propsetOrEnumerator)) + __utee_check_instring_annotation(name); + __utee_check_out_annotation(value, sizeof(*value)); + + type = USER_TA_PROP_TYPE_IDENTITY; + res = propget_get_property(propsetOrEnumerator, name, &type, + value, &identity_len); + if (type != USER_TA_PROP_TYPE_IDENTITY) + res = TEE_ERROR_BAD_FORMAT; + + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_BAD_FORMAT) + TEE_Panic(0); + + return res; +} + +TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) +{ + TEE_Result res; + struct prop_enumerator *pe; + + __utee_check_out_annotation(enumerator, sizeof(*enumerator)); + + pe = TEE_Malloc(sizeof(struct prop_enumerator), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (pe == NULL) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto err; + } + + *enumerator = (TEE_PropSetHandle) pe; + TEE_ResetPropertyEnumerator(*enumerator); + + goto out; + +err: + if (res == TEE_ERROR_OUT_OF_MEMORY) + return res; + TEE_Panic(0); +out: + 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) + return; + + pe->idx = 0; + pe->prop_set = propSet; +} + +TEE_Result __GP11_TEE_GetPropertyName(TEE_PropSetHandle enumerator, + void *name, uint32_t *name_len) +{ + TEE_Result res; + struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; + const struct user_ta_property *eps; + size_t eps_len; + const char *str; + size_t bufferlen; + + if (!pe) { + res = TEE_ERROR_BAD_PARAMETERS; + goto err; + } + __utee_check_gp11_outstring_annotation(name, name_len); + + bufferlen = *name_len; + res = propset_get(pe->prop_set, &eps, &eps_len); + if (res != TEE_SUCCESS) + goto err; + + if (pe->idx < eps_len) { + str = eps[pe->idx].name; + bufferlen = strlcpy(name, str, *name_len) + 1; + if (bufferlen > *name_len) + res = TEE_ERROR_SHORT_BUFFER; + *name_len = bufferlen; + } else { + res = _utee_get_property((unsigned long)pe->prop_set, + pe->idx - eps_len, name, name_len, + NULL, NULL, NULL); + if (res != TEE_SUCCESS) + goto err; + } + +err: + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND && + res != TEE_ERROR_SHORT_BUFFER) + TEE_Panic(0); + return res; +} + +TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, + void *nameBuffer, size_t *nameBufferLen) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t l = 0; + + __utee_check_outstring_annotation(nameBuffer, nameBufferLen); + l = *nameBufferLen; + res = __GP11_TEE_GetPropertyName(enumerator, nameBuffer, &l); + *nameBufferLen = l; + return res; +} + +TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) +{ + TEE_Result res; + struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; + uint32_t next_idx; + const struct user_ta_property *eps; + size_t eps_len; + + if (!pe) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + + if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { + res = TEE_ERROR_ITEM_NOT_FOUND; + goto out; + } + + res = propset_get(pe->prop_set, &eps, &eps_len); + if (res != TEE_SUCCESS) + goto out; + + next_idx = pe->idx + 1; + pe->idx = next_idx; + if (next_idx < eps_len) + res = TEE_SUCCESS; + else + res = _utee_get_property((unsigned long)pe->prop_set, + next_idx - eps_len, NULL, NULL, NULL, + NULL, NULL); + +out: + if (res != TEE_SUCCESS && + res != TEE_ERROR_ITEM_NOT_FOUND) + TEE_Panic(0); + return res; +} diff --git a/optee/optee_os/lib/libutee/tee_socket_private.h b/optee/optee_os/lib/libutee/tee_socket_private.h new file mode 100644 index 0000000..28f48d9 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_socket_private.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#ifndef __TEE_SOCKET_PRIVATE_H +#define __TEE_SOCKET_PRIVATE_H + +#include +#include <__tee_ipsocket.h> + +static inline uint8_t __tee_socket_ioctl_cmd_to_proto(uint32_t cmd_code) +{ + return cmd_code >> 24; +} + +TEE_Result __tee_socket_pta_open(TEE_ipSocket_ipVersion ip_vers, + const char *addr, uint16_t port, + uint32_t protocol, uint32_t *handle); + +TEE_Result __tee_socket_pta_close(uint32_t handle); + +TEE_Result __tee_socket_pta_send(uint32_t handle, const void *buf, + uint32_t *len, uint32_t timeout); + +TEE_Result __tee_socket_pta_recv(uint32_t handle, void *buf, uint32_t *len, + uint32_t timeout); + +TEE_Result __tee_socket_pta_ioctl(uint32_t handle, uint32_t command, void *buf, + uint32_t *len); + +#endif /*__TEE_SOCKET_PRIVATE_H*/ diff --git a/optee/optee_os/lib/libutee/tee_socket_pta.c b/optee/optee_os/lib/libutee/tee_socket_pta.c new file mode 100644 index 0000000..2104c15 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_socket_pta.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#include +#include +#include +#include <__tee_tcpsocket_defines.h> +#include <__tee_udpsocket_defines.h> + +#include "tee_socket_private.h" + +static TEE_Result invoke_socket_pta(uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + static TEE_TASessionHandle sess = TEE_HANDLE_NULL; + static const TEE_UUID socket_uuid = PTA_SOCKET_UUID; + + if (sess == TEE_HANDLE_NULL) { + TEE_Result res = TEE_OpenTASession(&socket_uuid, + TEE_TIMEOUT_INFINITE, + 0, NULL, &sess, NULL); + + if (res != TEE_SUCCESS) + return res; + } + + return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, + param_types, params, NULL); +} + +TEE_Result __tee_socket_pta_open(TEE_ipSocket_ipVersion ip_vers, + const char *addr, uint16_t port, + uint32_t protocol, uint32_t *handle) +{ + TEE_Result res; + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + memset(params, 0, sizeof(params)); + + switch (ip_vers) { + case TEE_IP_VERSION_DC: + case TEE_IP_VERSION_4: + case TEE_IP_VERSION_6: + params[0].value.a = ip_vers; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + params[0].value.b = port; + + if (!addr) + return TEE_ERROR_BAD_PARAMETERS; + params[1].memref.buffer = (void *)addr; + params[1].memref.size = strlen(addr) + 1; + + switch (protocol) { + case TEE_ISOCKET_PROTOCOLID_TCP: + case TEE_ISOCKET_PROTOCOLID_UDP: + params[2].value.a = protocol; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + res = invoke_socket_pta(PTA_SOCKET_OPEN, param_types, params); + if (res == TEE_SUCCESS) + *handle = params[3].value.a; + return res; +} + +TEE_Result __tee_socket_pta_close(uint32_t handle) +{ + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + + params[0].value.a = handle; + return invoke_socket_pta(PTA_SOCKET_CLOSE, param_types, params); +} + +TEE_Result __tee_socket_pta_send(uint32_t handle, const void *buf, + uint32_t *len, uint32_t timeout) +{ + TEE_Result res; + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + + params[0].value.a = handle; + params[0].value.b = timeout; + + params[1].memref.buffer = (void *)buf; + params[1].memref.size = *len; + + res = invoke_socket_pta(PTA_SOCKET_SEND, param_types, params); + *len = params[2].value.a; + return res; +} + +TEE_Result __tee_socket_pta_recv(uint32_t handle, void *buf, uint32_t *len, + uint32_t timeout) + +{ + TEE_Result res; + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + + params[0].value.a = handle; + params[0].value.b = timeout; + + params[1].memref.buffer = buf; + params[1].memref.size = *len; + + res = invoke_socket_pta(PTA_SOCKET_RECV, param_types, params); + *len = params[1].memref.size; + return res; +} + +TEE_Result __tee_socket_pta_ioctl(uint32_t handle, uint32_t command, void *buf, + uint32_t *len) +{ + TEE_Result res; + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + memset(params, 0, sizeof(params)); + + params[0].value.a = handle; + params[0].value.b = command; + + params[1].memref.buffer = buf; + params[1].memref.size = *len; + + res = invoke_socket_pta(PTA_SOCKET_IOCTL, param_types, params); + *len = params[1].memref.size; + return res; +} diff --git a/optee/optee_os/lib/libutee/tee_system_pta.c b/optee/optee_os/lib/libutee/tee_system_pta.c new file mode 100644 index 0000000..6c35045 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_system_pta.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2020, Open Mobile Platform LLC + */ + +#include +#include +#include +#include +#include +#include + +static TEE_Result invoke_system_pta(uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + static TEE_TASessionHandle sess = TEE_HANDLE_NULL; + static const TEE_UUID uuid = PTA_SYSTEM_UUID; + + if (sess == TEE_HANDLE_NULL) { + TEE_Result res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &sess, NULL); + + if (res) + return res; + } + + return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, + param_types, params, NULL); +} + +void *tee_map_zi(size_t len, uint32_t flags) +{ + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_SUCCESS; + + params[0].value.a = len; + if (params[0].value.a != len) + return NULL; + switch (flags) { + case 0: + break; + case TEE_MEMORY_ACCESS_ANY_OWNER: + params[0].value.b = PTA_SYSTEM_MAP_FLAG_SHAREABLE; + break; + default: + return NULL; + } + + res = invoke_system_pta(PTA_SYSTEM_MAP_ZI, param_types, params); + if (res) + return NULL; + + return (void *)(vaddr_t)reg_pair_to_64(params[1].value.a, + params[1].value.b); +} + +TEE_Result tee_unmap(void *buf, size_t len) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = { }; + + params[0].value.a = len; + reg_pair_from_64((vaddr_t)buf, ¶ms[1].value.a, ¶ms[1].value.b); + + res = invoke_system_pta(PTA_SYSTEM_UNMAP, param_types, params); + if (res) + EMSG("Invoke PTA_SYSTEM_UNMAP: buf %p, len %#zx", buf, len); + + return res; +} + +TEE_Result tee_invoke_supp_plugin(const TEE_UUID *uuid, uint32_t cmd, + uint32_t sub_cmd, void *buf, size_t len, + size_t *outlen) +{ + TEE_Result res = TEE_SUCCESS; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + + if (!uuid || (len && !buf) || (!len && buf)) + return TEE_ERROR_BAD_PARAMETERS; + + params[0].memref.buffer = (void *)uuid; + params[0].memref.size = sizeof(TEE_UUID); + params[1].value.a = cmd; + params[1].value.b = sub_cmd; + params[2].memref.buffer = buf; + params[2].memref.size = len; + + res = invoke_system_pta(PTA_SYSTEM_SUPP_PLUGIN_INVOKE, param_types, + params); + if (res) + EMSG("Invoke tee-supplicant's plugin failed: %#"PRIx32, res); + + if (outlen) + *outlen = params[3].value.a; + + return res; +} diff --git a/optee/optee_os/lib/libutee/tee_tcpudp_socket.c b/optee/optee_os/lib/libutee/tee_tcpudp_socket.c new file mode 100644 index 0000000..5117151 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_tcpudp_socket.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016-2017, Linaro Limited + */ + +#include +#include +#include +#include +#include <__tee_tcpsocket_defines_extensions.h> +#include + +#include "tee_socket_private.h" + +struct socket_ctx { + uint32_t handle; + uint32_t proto_error; +}; + +static TEE_Result tcp_open(TEE_iSocketHandle *ctx, void *setup, + uint32_t *proto_error) +{ + TEE_Result res; + struct socket_ctx *sock_ctx; + TEE_tcpSocket_Setup *tcp_setup = setup; + + if (!ctx || !setup || !proto_error) + TEE_Panic(0); + + *proto_error = TEE_SUCCESS; + + sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); + if (!sock_ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + res = __tee_socket_pta_open(tcp_setup->ipVersion, + tcp_setup->server_addr, + tcp_setup->server_port, + TEE_ISOCKET_PROTOCOLID_TCP, + &sock_ctx->handle); + if (res != TEE_SUCCESS) { + TEE_Free(sock_ctx); + sock_ctx = NULL; + } + *ctx = (TEE_iSocketHandle)sock_ctx; + + switch (res) { + case TEE_ISOCKET_ERROR_HOSTNAME: + *proto_error = res; + return TEE_ISOCKET_ERROR_PROTOCOL; + case TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND: + *proto_error = res; + return TEE_ISOCKET_WARNING_PROTOCOL; + default: + return res; + } +} + +static TEE_Result udp_open(TEE_iSocketHandle *ctx, void *setup, + uint32_t *proto_error) +{ + TEE_Result res; + struct socket_ctx *sock_ctx; + TEE_udpSocket_Setup *udp_setup = setup; + + if (!ctx || !setup || !proto_error) + TEE_Panic(0); + + *proto_error = TEE_SUCCESS; + + sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); + if (!sock_ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + res = __tee_socket_pta_open(udp_setup->ipVersion, + udp_setup->server_addr, + udp_setup->server_port, + TEE_ISOCKET_PROTOCOLID_UDP, + &sock_ctx->handle); + if (res != TEE_SUCCESS) { + TEE_Free(sock_ctx); + sock_ctx = NULL; + } + *ctx = (TEE_iSocketHandle)sock_ctx; + + switch (res) { + case TEE_ISOCKET_ERROR_HOSTNAME: + *proto_error = res; + return TEE_ISOCKET_ERROR_PROTOCOL; + case TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND: + *proto_error = res; + return TEE_ISOCKET_WARNING_PROTOCOL; + default: + return res; + } +} + +static TEE_Result sock_close(TEE_iSocketHandle ctx) +{ + TEE_Result res; + struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; + + if (ctx == TEE_HANDLE_NULL) + return TEE_SUCCESS; + + res = __tee_socket_pta_close(sock_ctx->handle); + TEE_Free(sock_ctx); + + return res; +} + +static TEE_Result sock_send(TEE_iSocketHandle ctx, const void *buf, + uint32_t *length, uint32_t timeout) +{ + TEE_Result res; + struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; + + if (ctx == TEE_HANDLE_NULL || !buf || !length) + TEE_Panic(0); + + res = __tee_socket_pta_send(sock_ctx->handle, buf, length, timeout); + sock_ctx->proto_error = res; + + return res; +} + +static TEE_Result sock_recv(TEE_iSocketHandle ctx, void *buf, uint32_t *length, + uint32_t timeout) +{ + TEE_Result res; + struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; + + if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) + TEE_Panic(0); + + res = __tee_socket_pta_recv(sock_ctx->handle, buf, length, timeout); + sock_ctx->proto_error = res; + + return res; +} + +static uint32_t sock_error(TEE_iSocketHandle ctx) +{ + struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; + + if (ctx == TEE_HANDLE_NULL) + TEE_Panic(0); + + return sock_ctx->proto_error; +} + +static TEE_Result tcp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, + void *buf, uint32_t *length) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; + + if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) + TEE_Panic(0); + + if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) + return TEE_SUCCESS; + + switch (commandCode) { + case TEE_TCP_SET_RECVBUF: + case TEE_TCP_SET_SENDBUF: + res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, + buf, length); + break; + default: + TEE_Panic(0); + } + + sock_ctx->proto_error = res; + + return res; +} + +static TEE_Result udp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, + void *buf, uint32_t *length) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; + + if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) + TEE_Panic(0); + + if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) + return TEE_SUCCESS; + + switch (commandCode) { + case TEE_UDP_CHANGEADDR: + case TEE_UDP_CHANGEPORT: + res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, + buf, length); + break; + default: + TEE_Panic(0); + } + + sock_ctx->proto_error = res; + + return res; +} + + + +static TEE_iSocket tcp_socket_instance = { + .TEE_iSocketVersion = TEE_ISOCKET_VERSION, + .protocolID = TEE_ISOCKET_PROTOCOLID_TCP, + .open = tcp_open, + .close = sock_close, + .send = sock_send, + .recv = sock_recv, + .error = sock_error, + .ioctl = tcp_ioctl, +}; + +static TEE_iSocket udp_socket_instance = { + .TEE_iSocketVersion = TEE_ISOCKET_VERSION, + .protocolID = TEE_ISOCKET_PROTOCOLID_UDP, + .open = udp_open, + .close = sock_close, + .send = sock_send, + .recv = sock_recv, + .error = sock_error, + .ioctl = udp_ioctl, +}; + +TEE_iSocket *const TEE_tcpSocket = &tcp_socket_instance; +TEE_iSocket *const TEE_udpSocket = &udp_socket_instance; diff --git a/optee/optee_os/lib/libutee/tee_uuid_from_str.c b/optee/optee_os/lib/libutee/tee_uuid_from_str.c new file mode 100644 index 0000000..04dc564 --- /dev/null +++ b/optee/optee_os/lib/libutee/tee_uuid_from_str.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include + +static int hex(char c) +{ + char lc = tolower(c); + + if (isdigit(lc)) + return lc - '0'; + if (isxdigit(lc)) + return lc - 'a' + 10; + return -1; +} + +static uint32_t parse_hex(const char *s, size_t nchars, uint32_t *res) +{ + uint32_t v = 0; + size_t n = 0; + int c = 0; + + for (n = 0; n < nchars; n++) { + c = hex(s[n]); + if (c == -1) { + *res = TEE_ERROR_BAD_FORMAT; + goto out; + } + v = (v << 4) + c; + } + *res = TEE_SUCCESS; +out: + return v; +} + +TEE_Result tee_uuid_from_str(TEE_UUID *uuid, const char *s) +{ + TEE_Result res = TEE_SUCCESS; + TEE_UUID u = { }; + const char *p = s; + size_t i = 0; + + if (!p || strnlen(p, 37) != 36) + return TEE_ERROR_BAD_FORMAT; + if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-') + return TEE_ERROR_BAD_FORMAT; + + u.timeLow = parse_hex(p, 8, &res); + if (res) + goto out; + p += 9; + u.timeMid = parse_hex(p, 4, &res); + if (res) + goto out; + p += 5; + u.timeHiAndVersion = parse_hex(p, 4, &res); + if (res) + goto out; + p += 5; + for (i = 0; i < 8; i++) { + u.clockSeqAndNode[i] = parse_hex(p, 2, &res); + if (res) + goto out; + if (i == 1) + p += 3; + else + p += 2; + } + *uuid = u; +out: + return res; +} diff --git a/optee/optee_os/lib/libutee/trace_ext.c b/optee/optee_os/lib/libutee/trace_ext.c new file mode 100644 index 0000000..70c2c30 --- /dev/null +++ b/optee/optee_os/lib/libutee/trace_ext.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Arm Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __LDELF__ +#include +#endif + +#if TRACE_LEVEL > 0 + +void trace_ext_puts(const char *str) +{ +#ifdef __LDELF__ + _ldelf_log(str, strlen(str)); +#else + _utee_log(str, strlen(str)); +#endif +} + +int trace_ext_get_thread_id(void) +{ + return -1; +} + +/* + * printf and puts - stdio printf support + * + * 'printf()' and 'puts()' traces have the 'info' trace level. + */ +int printf(const char *fmt, ...) +{ + char to_format[MAX_PRINT_SIZE]; + va_list ap; + int s; + + if (trace_get_level() < TRACE_PRINTF_LEVEL) + return 0; + + va_start(ap, fmt); + s = vsnprintf(to_format, sizeof(to_format), fmt, ap); + va_end(ap); + + if (s < 0) + return s; + + trace_ext_puts(to_format); + + return s; +} + +int puts(const char *str) +{ + if (trace_get_level() >= TRACE_PRINTF_LEVEL) { + trace_ext_puts(str); + trace_ext_puts("\n"); + } + return 1; +} + +int putchar(int c) +{ + char str[2] = { (char)c, '\0' }; + + if (trace_get_level() >= TRACE_PRINTF_LEVEL) + trace_ext_puts(str); + /* + * From the putchar() man page: + * "fputc(), putc() and putchar() return the character written as an + * unsigned char cast to an int or EOF on error." + */ + return (int)(unsigned char)c; +} + +#else + +void trace_ext_puts(const char *str __unused) +{ +} + +int printf(const char *fmt __unused, ...) +{ + return 0; +} + +int puts(const char *str __unused) +{ + return 0; +} + +int putchar(int c) +{ + return (int)(unsigned char)c; +} + +#endif diff --git a/optee/optee_os/lib/libutee/user_ta_entry.c b/optee/optee_os/lib/libutee/user_ta_entry.c new file mode 100644 index 0000000..2ac3e25 --- /dev/null +++ b/optee/optee_os/lib/libutee/user_ta_entry.c @@ -0,0 +1,446 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022, Linaro Limited. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tee_api_private.h" + +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 bool init_done; + +/* From user_ta_header.c, built within TA */ +extern uint8_t ta_heap[]; +extern const size_t ta_heap_size; +extern struct ta_head ta_head; + +uint32_t ta_param_types; +TEE_Param ta_params[TEE_NUM_PARAMS]; + +struct malloc_ctx *__ta_no_share_malloc_ctx; + +struct __elf_phdr_info __elf_phdr_info; + +struct phdr_info { + struct dl_phdr_info info; + TAILQ_ENTRY(phdr_info) link; +}; + +static TAILQ_HEAD(phdr_info_head, phdr_info) __phdr_info_head = + TAILQ_HEAD_INITIALIZER(__phdr_info_head); +/* + * Keep track of how many modules have been initialized so that subsequent + * dlopen() calls will not run the same initializers again + */ +static size_t _num_mod_init; + +static int _init_iterate_phdr_cb(struct dl_phdr_info *info, + size_t size __unused, void *data) +{ + struct phdr_info *qe = NULL; + size_t *count = data; + + qe = malloc(sizeof(*qe)); + if (!qe) { + EMSG("init/fini: out of memory"); + abort(); + } + qe->info = *info; + TAILQ_INSERT_TAIL(&__phdr_info_head, qe, link); + (*count)++; + return 0; +} + +static void _get_fn_array(struct dl_phdr_info *info, Elf_Sword tag_a, + Elf_Sword tag_s, void (***fn)(void), size_t *num_fn) +{ + const Elf_Phdr *phdr = NULL; + Elf_Dyn *dyn = NULL; + size_t num_dyn = 0; + size_t i = 0; + size_t j = 0; + + for (i = 0; i < info->dlpi_phnum; i++) { + phdr = info->dlpi_phdr + i; + if (phdr->p_type != PT_DYNAMIC) + continue; + num_dyn = phdr->p_memsz / sizeof(Elf_Dyn); + dyn = (Elf_Dyn *)(phdr->p_vaddr + info->dlpi_addr); + for (j = 0; j < num_dyn; j++) { + if (*fn && *num_fn) + break; + if (dyn->d_tag == DT_NULL) { + break; + } else if (dyn->d_tag == tag_a) { + *fn = (void (**)(void))(dyn->d_un.d_ptr + + info->dlpi_addr); + } else if (dyn->d_tag == tag_s) { + *num_fn = dyn->d_un.d_val / sizeof(Elf_Addr); + } + dyn++; + } + } +} + +void __utee_call_elf_init_fn(void) +{ + void (**fn)(void) = NULL; + size_t num_mod = 0; + size_t num_fn = 0; + size_t mod = 0; + size_t i = 0; + struct phdr_info *qe = NULL; + struct phdr_info *qe2 = NULL; + + dl_iterate_phdr(_init_iterate_phdr_cb, &num_mod); + + /* Reverse order: dependencies first */ + TAILQ_FOREACH_REVERSE(qe, &__phdr_info_head, phdr_info_head, link) { + if (mod == num_mod - _num_mod_init) + break; + _get_fn_array(&qe->info, DT_INIT_ARRAY, DT_INIT_ARRAYSZ, &fn, + &num_fn); + for (i = 0; i < num_fn; i++) + fn[i](); + fn = NULL; + num_fn = 0; + mod++; + } + _num_mod_init += mod; + + TAILQ_FOREACH_SAFE(qe, &__phdr_info_head, link, qe2) { + TAILQ_REMOVE(&__phdr_info_head, qe, link); + free(qe); + } +} + +static int _fini_iterate_phdr_cb(struct dl_phdr_info *info, + size_t size __unused, void *data __unused) +{ + void (**fn)(void) = NULL; + size_t num_fn = 0; + size_t i = 0; + + _get_fn_array(info, DT_FINI_ARRAY, DT_FINI_ARRAYSZ, &fn, &num_fn); + + for (i = 1; i <= num_fn; i++) + fn[num_fn - i](); + + return 0; +} + +void __utee_call_elf_fini_fn(void) +{ + dl_iterate_phdr(_fini_iterate_phdr_cb, NULL); +} + +static unsigned int get_memtag_implementation(void) +{ + const char *s = "org.trustedfirmware.optee.cpu.feat_memtag_implemented"; + uint32_t v = 0; + + if (TEE_GetPropertyAsU32(TEE_PROPSET_TEE_IMPLEMENTATION, s, &v)) + return 0; + return v; +} + +static TEE_Result init_instance(void) +{ + trace_set_level(tahead_get_trace_level()); + __utee_gprof_init(); + malloc_add_pool(ta_heap, ta_heap_size); + if (__ta_no_share_heap_size) { + __ta_no_share_malloc_ctx = malloc(raw_malloc_get_ctx_size()); + if (__ta_no_share_malloc_ctx) { + raw_malloc_init_ctx(__ta_no_share_malloc_ctx); + raw_malloc_add_pool(__ta_no_share_malloc_ctx, + __ta_no_share_heap, + __ta_no_share_heap_size); + } + } + memtag_init_ops(get_memtag_implementation()); + _TEE_MathAPI_Init(); + __utee_tcb_init(); + __utee_call_elf_init_fn(); + return TA_CreateEntryPoint(); +} + +static void uninit_instance(void) +{ + __utee_gprof_fini(); + TA_DestroyEntryPoint(); + __utee_call_elf_fini_fn(); +} + +static void ta_header_save_params(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + ta_param_types = param_types; + + if (params) + 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); + TEE_Result res; + + if (itr) + return TEE_SUCCESS; + + if (!init_done) { + init_done = true; + res = init_instance(); + if (res) + return res; + } + + itr = TEE_Malloc(sizeof(struct ta_session), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!itr) + 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; + bool keep_alive; + + TAILQ_FOREACH(itr, &ta_sessions, link) { + if (itr->session_id == session_id) { + TAILQ_REMOVE(&ta_sessions, itr, link); + TEE_Free(itr); + + keep_alive = + (ta_head.flags & TA_FLAG_SINGLE_INSTANCE) && + (ta_head.flags & TA_FLAG_INSTANCE_KEEP_ALIVE); + if (TAILQ_EMPTY(&ta_sessions) && !keep_alive) + uninit_instance(); + + return; + } + } +} + +static void to_utee_params(struct utee_params *up, uint32_t param_types, + const TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t n = 0; + + up->types = param_types; + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(param_types, n)) { + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + up->vals[n * 2] = params[n].value.a; + up->vals[n * 2 + 1] = params[n].value.b; + break; + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + up->vals[n * 2] = (uintptr_t)params[n].memref.buffer; + up->vals[n * 2 + 1] = params[n].memref.size; + break; + default: + up->vals[n * 2] = 0; + up->vals[n * 2 + 1] = 0; + break; + } + } +} + +static void from_utee_params(TEE_Param params[TEE_NUM_PARAMS], + uint32_t *param_types, + const struct utee_params *up) +{ + size_t n; + uint32_t types = up->types; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + uintptr_t a = up->vals[n * 2]; + uintptr_t b = up->vals[n * 2 + 1]; + + switch (TEE_PARAM_TYPE_GET(types, n)) { + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].value.a = a; + params[n].value.b = b; + break; + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + params[n].memref.buffer = (void *)a; + params[n].memref.size = b; + break; + default: + break; + } + } + + if (param_types) + *param_types = types; +} + +static TEE_Result entry_open_session(unsigned long session_id, + struct utee_params *up) +{ + TEE_Result res; + struct ta_session *session; + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + + res = ta_header_add_session(session_id); + if (res != TEE_SUCCESS) + return res; + + session = ta_header_get_session(session_id); + if (!session) + return TEE_ERROR_BAD_STATE; + + from_utee_params(params, ¶m_types, up); + ta_header_save_params(param_types, params); + + res = TA_OpenSessionEntryPoint(param_types, params, + &session->session_ctx); + + to_utee_params(up, param_types, params); + + if (res != TEE_SUCCESS) + ta_header_remove_session(session_id); + return res; +} + +static TEE_Result entry_close_session(unsigned long session_id) +{ + struct ta_session *session = ta_header_get_session(session_id); + + if (!session) + return TEE_ERROR_BAD_STATE; + + TA_CloseSessionEntryPoint(session->session_ctx); + + ta_header_remove_session(session_id); + return TEE_SUCCESS; +} + +static TEE_Result entry_invoke_command(unsigned long session_id, + struct utee_params *up, unsigned long cmd_id) +{ + TEE_Result res; + uint32_t param_types; + TEE_Param params[TEE_NUM_PARAMS]; + struct ta_session *session = ta_header_get_session(session_id); + + if (!session) + return TEE_ERROR_BAD_STATE; + + from_utee_params(params, ¶m_types, up); + ta_header_save_params(param_types, params); + + res = TA_InvokeCommandEntryPoint(session->session_ctx, cmd_id, + param_types, params); + + to_utee_params(up, param_types, params); + return res; +} + +#if defined(CFG_TA_STATS) +static TEE_Result entry_dump_memstats(unsigned long session_id __unused, + struct utee_params *up) +{ + uint32_t param_types = 0; + TEE_Param params[TEE_NUM_PARAMS] = { }; + struct malloc_stats stats = { }; + + from_utee_params(params, ¶m_types, up); + ta_header_save_params(param_types, params); + + if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE) != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + malloc_get_stats(&stats); + params[0].value.a = stats.allocated; + params[0].value.b = stats.max_allocated; + params[1].value.a = stats.size; + params[1].value.b = stats.num_alloc_fail; + params[2].value.a = stats.biggest_alloc_fail; + params[2].value.b = stats.biggest_alloc_fail_used; + to_utee_params(up, param_types, params); + + return TEE_SUCCESS; +} +#endif + +TEE_Result __utee_entry(unsigned long func, unsigned long session_id, + struct utee_params *up, unsigned long cmd_id) +{ + TEE_Result res; + + switch (func) { + case UTEE_ENTRY_FUNC_OPEN_SESSION: + res = entry_open_session(session_id, up); + break; + case UTEE_ENTRY_FUNC_CLOSE_SESSION: + res = entry_close_session(session_id); + break; + case UTEE_ENTRY_FUNC_INVOKE_COMMAND: + res = entry_invoke_command(session_id, up, cmd_id); + break; +#if defined(CFG_TA_STATS) + case UTEE_ENTRY_FUNC_DUMP_MEMSTATS: + res = entry_dump_memstats(session_id, up); + break; +#endif + default: + res = TEE_ERROR_NOT_SUPPORTED; + break; + } + ta_header_save_params(0, NULL); + + return res; +} diff --git a/optee/optee_os/lib/libutee/user_ta_entry_compat.c b/optee/optee_os/lib/libutee/user_ta_entry_compat.c new file mode 100644 index 0000000..f7b4798 --- /dev/null +++ b/optee/optee_os/lib/libutee/user_ta_entry_compat.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022, Linaro Limited. + */ +#include +#include + +static void to_gp11_param(uint32_t pt, const TEE_Param params[TEE_NUM_PARAMS], + __GP11_TEE_Param gp11_params[TEE_NUM_PARAMS]) +{ + size_t n = 0; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(pt, n)) { + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + gp11_params[n].value.a = params[n].value.a; + gp11_params[n].value.b = params[n].value.b; + break; + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + gp11_params[n].memref.buffer = params[n].memref.buffer; + gp11_params[n].memref.size = params[n].memref.size; + break; + default: + break; + } + } +} + +static void from_gp11_param(uint32_t pt, + const __GP11_TEE_Param gp11_params[TEE_NUM_PARAMS], + TEE_Param params[TEE_NUM_PARAMS]) +{ + size_t n = 0; + + for (n = 0; n < TEE_NUM_PARAMS; n++) { + switch (TEE_PARAM_TYPE_GET(pt, n)) { + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].value.a = gp11_params[n].value.a; + params[n].value.b = gp11_params[n].value.b; + break; + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + params[n].memref.buffer = gp11_params[n].memref.buffer; + params[n].memref.size = gp11_params[n].memref.size; + break; + default: + break; + } + } +} + +/* + * Legacy TAs will due to macros define __GP11_TA_OpenSessionEntryPoint() + * instead so call that function instead. + */ + +TEE_Result __ta_open_sess(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], + void **sess_ctx, + TEE_Result (*fp)(uint32_t, + __GP11_TEE_Param [TEE_NUM_PARAMS], + void **)) +{ + __GP11_TEE_Param gp11_params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_SUCCESS; + + to_gp11_param(pt, params, gp11_params); + res = fp(pt, gp11_params, sess_ctx); + from_gp11_param(pt, gp11_params, params); + + return res; +} + +/* + * Legacy TAs will due to macros define __GP11_TA_InvokeCommandEntryPoint() + * instead so call that function instead. + */ + +TEE_Result __ta_invoke_cmd(void *sess_ctx, uint32_t cmd_id, uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS], + TEE_Result (*fp)(void *, uint32_t, uint32_t, + __GP11_TEE_Param [TEE_NUM_PARAMS])) +{ + __GP11_TEE_Param gp11_params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_SUCCESS; + + to_gp11_param(pt, params, gp11_params); + res = fp(sess_ctx, cmd_id, pt, gp11_params); + from_gp11_param(pt, gp11_params, params); + + return res; +} diff --git a/optee/optee_os/lib/libutils/ext/arch/arm/aeabi_unwind.c b/optee/optee_os/lib/libutils/ext/arch/arm/aeabi_unwind.c new file mode 100644 index 0000000..332ee45 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/arm/aeabi_unwind.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017, Linaro Limited + */ + +void __aeabi_unwind_cpp_pr0(void); +void __aeabi_unwind_cpp_pr0(void) +{ +} + +void __aeabi_unwind_cpp_pr1(void); +void __aeabi_unwind_cpp_pr1(void) +{ +} + +void __aeabi_unwind_cpp_pr2(void); +void __aeabi_unwind_cpp_pr2(void) +{ +} + diff --git a/optee/optee_os/lib/libutils/ext/arch/arm/atomic_a32.S b/optee/optee_os/lib/libutils/ext/arch/arm/atomic_a32.S new file mode 100644 index 0000000..2be73ff --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/arm/atomic_a32.S @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2016, Linaro Limited + */ + +#include + + .section .note.GNU-stack,"",%progbits + +/* uint32_t atomic_inc32(uint32_t *v); */ +FUNC atomic_inc32 , : + ldrex r1, [r0] + add r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne atomic_inc32 + mov r0, r1 + bx lr +END_FUNC atomic_inc32 + +/* uint32_t atomic_dec32(uint32_t *v); */ +FUNC atomic_dec32 , : + ldrex r1, [r0] + sub r1, r1, #1 + strex r2, r1, [r0] + cmp r2, #0 + bne atomic_dec32 + mov r0, r1 + bx lr +END_FUNC atomic_dec32 diff --git a/optee/optee_os/lib/libutils/ext/arch/arm/atomic_a64.S b/optee/optee_os/lib/libutils/ext/arch/arm/atomic_a64.S new file mode 100644 index 0000000..0b6ab8c --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/arm/atomic_a64.S @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015-2016, Linaro Limited + */ + +#include + + +/* uint32_t atomic_inc32(uint32_t *v); */ +FUNC atomic_inc32 , : + ldaxr w1, [x0] + add w1, w1, #1 + stxr w2, w1, [x0] + cmp w2, #0 + bne atomic_inc32 + mov w0, w1 + ret +END_FUNC atomic_inc32 + +/* uint32_t atomic_dec32(uint32_t *v); */ +FUNC atomic_dec32 , : + ldaxr w1, [x0] + sub w1, w1, #1 + stxr w2, w1, [x0] + cmp w2, #0 + bne atomic_dec32 + mov w0, w1 + ret +END_FUNC atomic_dec32 + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/lib/libutils/ext/arch/arm/auxval.c b/optee/optee_os/lib/libutils/ext/arch/arm/auxval.c new file mode 100644 index 0000000..98bca85 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/arm/auxval.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, EPAM Systems + */ + +#include + +unsigned long int __getauxval (unsigned long int type); +unsigned long int __getauxval (unsigned long int type __unused) +{ + return 0; +} diff --git a/optee/optee_os/lib/libutils/ext/arch/arm/mcount_a32.S b/optee/optee_os/lib/libutils/ext/arch/arm/mcount_a32.S new file mode 100644 index 0000000..54dc3c0 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/arm/mcount_a32.S @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include + +#if defined(CFG_TA_GPROF_SUPPORT) || defined(CFG_FTRACE_SUPPORT) + + .section .note.GNU-stack,"",%progbits + +/* + * Convert return address to call site address by subtracting the size of the + * mcount call instruction (blx __gnu_mcount_nc). + */ +.macro mcount_adj_pc rd, rn + bic \rd, \rn, #1 /* Clear thumb bit if present */ + sub \rd, \rd, #4 +.endm + +/* + * With the -pg option, GCC (4.4+) inserts a call to __gnu_mcount_nc into + * every function prologue. + * The caller of the instrumented function can be determined from the lr value + * stored on the top of the stack. The callee, i.e. the instrumented function + * itself, is determined from the current value of lr. Then we call: + * void __mcount_internal(void *frompc, void *selfpc); + */ +FUNC __gnu_mcount_nc, : +UNWIND( .cantunwind) + stmdb sp!, {r0-r3, lr} +#if defined(CFG_TA_GPROF_SUPPORT) && !defined(__KERNEL__) + ldr r0, [sp, #20] /* lr of instrumented func */ + mcount_adj_pc r0, r0 + mcount_adj_pc r1, lr /* instrumented func */ + bl __mcount_internal +#endif +#ifdef CFG_FTRACE_SUPPORT + /* Get instrumented function's pc value */ + ldr r0, [sp, #16] + mcount_adj_pc r0, r0 + /* Get instrumented function's lr address pointer */ + sub r1, fp, #4 + bl ftrace_enter +#endif + ldmia sp!, {r0-r3, ip, lr} + bx ip +END_FUNC __gnu_mcount_nc + +#ifdef CFG_FTRACE_SUPPORT +FUNC __ftrace_return, : + /* save return value regs */ + stmdb sp!, {r0-r3} + + /* get return address of parent func */ + bl ftrace_return + mov lr, r0 + + /* restore return value regs */ + ldmia sp!, {r0-r3} + bx lr +END_FUNC __ftrace_return +#endif + +#endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */ diff --git a/optee/optee_os/lib/libutils/ext/arch/arm/mcount_a64.S b/optee/optee_os/lib/libutils/ext/arch/arm/mcount_a64.S new file mode 100644 index 0000000..7d94b08 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/arm/mcount_a64.S @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include + +#if defined(CFG_TA_GPROF_SUPPORT) || defined(CFG_FTRACE_SUPPORT) + +/* + * Convert return address to call site address by subtracting the size of one + * instruction. + */ +.macro adjust_pc rd, rn + sub \rd, \rn, #4 +.endm + +/* Get instrumented function's pc value */ +.macro get_pc reg + ldr \reg, [x29, #8] + sub \reg, \reg, #4 +.endm + +/* Get instrumented function's lr address pointer */ +.macro get_lr_addr reg + ldr \reg, [x29] + add \reg, \reg, #8 +.endm + +/* + * void _mcount(void *return_address) + * @return_address: return address to instrumented function + * + * With the -pg option, the compiler inserts a call to _mcount into + * every function prologue. + * x0 contains the value of lr (x30) before the call, that is the return + * address to the caller of the instrumented function. The callee, i.e. the + * instrumented function itself, is determined from the current value of x30. + * Then we call: + * void __mcount_internal(void *frompc, void *selfpc); + */ +FUNC _mcount, : + stp x29, x30, [sp, #-16]! + mov x29, sp +#if defined(CFG_TA_GPROF_SUPPORT) && !defined(__KERNEL__) + adjust_pc x0, x0 + adjust_pc x1, x30 + bl __mcount_internal +#endif +#ifdef CFG_FTRACE_SUPPORT + get_pc x0 + get_lr_addr x1 + bl ftrace_enter +#endif + ldp x29, x30, [sp], #16 + ret +END_FUNC _mcount + +#ifdef CFG_FTRACE_SUPPORT +FUNC __ftrace_return, : + /* Save return value regs */ + sub sp, sp, #64 + stp x0, x1, [sp] + stp x2, x3, [sp, #16] + stp x4, x5, [sp, #32] + stp x6, x7, [sp, #48] + + /* Get return address of parent func */ + bl ftrace_return + mov x30, x0 + + /* Restore return value regs */ + ldp x0, x1, [sp] + ldp x2, x3, [sp, #16] + ldp x4, x5, [sp, #32] + ldp x6, x7, [sp, #48] + add sp, sp, #64 + + ret +END_FUNC __ftrace_return +#endif + +#endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */ + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/lib/libutils/ext/arch/arm/memtag.c b/optee/optee_os/lib/libutils/ext/arch/arm/memtag.c new file mode 100644 index 0000000..8249599 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/arm/memtag.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#if MEMTAG_IS_ENABLED + +/* This is for AArch64 only, MTE is only available in this mode */ + +static unsigned int dczid_block_size(void) +{ + return SHIFT_U32(4U, read_dczid_el0() & 0xf); +} + +static bool data_zero_prohibited(void) +{ +#ifdef __KERNEL__ + return false; +#else + return read_dczid_el0() & BIT(4); +#endif +} + +static void dc_gzva(uint64_t va) +{ + asm volatile ("dc gzva, %0" : : "r" (va)); +} + +static void dc_gva(uint64_t va) +{ + asm volatile ("dc gva, %0" : : "r" (va)); +} + +static vaddr_t stg_and_advance(vaddr_t va) +{ + asm volatile("stg %0, [%0], #16" : "+r"(va) : : "memory"); + return va; +} + +static void *insert_random_tag(void *addr) +{ + asm volatile("irg %0, %0" : "+r"(addr) : : ); + return addr; +} + +static void *load_tag(void *addr) +{ + asm volatile("ldg %0, [%0]" : "+r"(addr) : : ); + return addr; +} + +static void set_tags_dc_gva(vaddr_t va, size_t size, size_t dcsz) +{ + do { + dc_gva(va); + va += dcsz; + size -= dcsz; + } while (size); +} + +static void clear_mem_dc_gzva(vaddr_t va, size_t size, size_t dcsz) +{ + do { + dc_gzva(va); + va += dcsz; + size -= dcsz; + } while (size); +} + +static void *set_tags_helper(void *addr, size_t size) +{ + vaddr_t va = (vaddr_t)addr; + vaddr_t end = va + size; + + assert(!(va & MEMTAG_GRANULE_MASK)); + assert(!(size & MEMTAG_GRANULE_MASK)); + + while (va < end) + va = stg_and_advance(va); + + return addr; +} + +static void *set_tags_dc_helper(void *addr, size_t size) +{ + size_t dcsz = dczid_block_size(); + vaddr_t va = (vaddr_t)addr; + size_t mask = dcsz - 1; + size_t s = 0; + + if (va & mask) { + s = MIN(dcsz - (va & mask), size); + set_tags_helper((void *)va, s); + va += s; + size -= s; + } + s = size & ~mask; + if (s) { + set_tags_dc_gva(va, s, dcsz); + va += s; + size -= s; + } + if (size) + set_tags_helper((void *)va, size); + + return addr; +} + +static void *set_tags_dc(void *addr, size_t size, uint8_t tag) +{ + return set_tags_dc_helper(memtag_insert_tag(addr, tag), size); +} + +static void *set_random_tags_dc(void *addr, size_t size) +{ + return set_tags_dc_helper(insert_random_tag(addr), size); +} + +static void *set_tags(void *addr, size_t size, uint8_t tag) +{ + return set_tags_helper(memtag_insert_tag(addr, tag), size); +} + +static void *set_random_tags(void *addr, size_t size) +{ + return set_tags_helper(insert_random_tag(addr), size); +} + +static void clear_mem(void *va, size_t size) +{ + set_tags(va, size, 0); + memset(memtag_strip_tag(va), 0, size); +} + +static void clear_mem_dc(void *addr, size_t size) +{ + size_t dcsz = dczid_block_size(); + vaddr_t va = (vaddr_t)addr; + size_t mask = dcsz - 1; + size_t s = 0; + + if (va & mask) { + s = MIN(dcsz - (va & mask), size); + clear_mem((void *)va, s); + va += s; + size -= s; + } + s = size & ~mask; + if (s) { + clear_mem_dc_gzva(va, s, dcsz); + va += s; + size -= s; + } + if (size) + clear_mem((void *)va, size); +} + +static uint8_t read_tag(const void *addr) +{ + return memtag_get_tag(load_tag((void *)addr)); +} + +static const struct __memtag_ops ops_dc_enabled = { + .set_tags = set_tags_dc, + .set_random_tags = set_random_tags_dc, + .clear_mem = clear_mem_dc, + .read_tag = read_tag, +}; + +static const struct __memtag_ops ops_enabled = { + .set_tags = set_tags, + .set_random_tags = set_random_tags, + .clear_mem = clear_mem, + .read_tag = read_tag, +}; + +const struct __memtag_ops __memtag_ops_disabled = { + .set_tags = __memtag_disabled_set_tags, + .set_random_tags = __memtag_disabled_set_random_tags, + .clear_mem = __memtag_disabled_clear_mem, + .read_tag = __memtag_disabled_read_tag, +}; + +const struct __memtag_ops *__memtag_ops = &__memtag_ops_disabled; + +void memtag_init_ops(unsigned int memtag_impl) +{ + if (memtag_impl >= 2) { + /* + * Data zero is always available for S-EL1 if MTE is + * enabled, but for S-EL0 it may depend on configuration. + */ + if (data_zero_prohibited()) + __memtag_ops = &ops_enabled; + else + __memtag_ops = &ops_dc_enabled; + } else { + __memtag_ops = &__memtag_ops_disabled; + } +} +#endif diff --git a/optee/optee_os/lib/libutils/ext/arch/arm/sub.mk b/optee/optee_os/lib/libutils/ext/arch/arm/sub.mk new file mode 100644 index 0000000..6726bb0 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/arm/sub.mk @@ -0,0 +1,11 @@ +ifeq ($(CFG_UNWIND),y) +srcs-$(CFG_ARM32_$(sm)) += aeabi_unwind.c +endif +srcs-$(CFG_ARM32_$(sm)) += atomic_a32.S +srcs-$(CFG_ARM64_$(sm)) += atomic_a64.S +srcs-y += auxval.c +ifneq ($(sm),ldelf) # TA, core +srcs-$(CFG_ARM32_$(sm)) += mcount_a32.S +srcs-$(CFG_ARM64_$(sm)) += mcount_a64.S +endif +srcs-$(CFG_MEMTAG) += memtag.c diff --git a/optee/optee_os/lib/libutils/ext/arch/riscv/atomic_rv.S b/optee/optee_os/lib/libutils/ext/arch/riscv/atomic_rv.S new file mode 100644 index 0000000..cc63aee --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/riscv/atomic_rv.S @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ + +#include + +/* uint32_t atomic_inc32(uint32_t *v); */ +FUNC atomic_inc32 , : + li a1, 1 + amoadd.w.aqrl a2, a1, (a0) + add a0, a1, a2 + ret +END_FUNC atomic_inc32 + +/* uint32_t atomic_dec32(uint32_t *v); */ +FUNC atomic_dec32 , : + li a1, -1 + amoadd.w.aqrl a2, a1, (a0) + add a0, a1, a2 + ret +END_FUNC atomic_dec32 diff --git a/optee/optee_os/lib/libutils/ext/arch/riscv/sub.mk b/optee/optee_os/lib/libutils/ext/arch/riscv/sub.mk new file mode 100644 index 0000000..3fbba03 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/arch/riscv/sub.mk @@ -0,0 +1 @@ +srcs-y+= atomic_rv.S diff --git a/optee/optee_os/lib/libutils/ext/consttime_memcmp.c b/optee/optee_os/lib/libutils/ext/consttime_memcmp.c new file mode 100644 index 0000000..d0bba7e --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/consttime_memcmp.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2019 Linaro Limited + * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +/* Making a portable memcmp that has no internal branches and loops always + * once for every byte without early-out shortcut has a few challenges. + * + * Inspired by 'timingsafe_memcmp()' from the BSD system and + * https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/string/timingsafe_memcmp.c + * + * Sadly, that one is not portable C: It makes assumptions on the representation + * of negative integers and assumes sign-preserving right-shift of negative + * signed values. This is a rewrite from scratch that should not suffer from + * such issues. + * + * 2015-12-12, J. Perlinger (perlinger-at-ntp-dot-org) + */ +int consttime_memcmp(const void *p1, const void *p2, size_t nb) { + const unsigned char *ucp1 = p1; + const unsigned char *ucp2 = p2; + unsigned int isLT = 0u; + unsigned int isGT = 0u; + volatile unsigned int mask = (1u << CHAR_BIT); + + for (/*NOP*/; 0 != nb; --nb, ++ucp1, ++ucp2) { + isLT |= mask & + ((unsigned int)*ucp1 - (unsigned int)*ucp2); + isGT |= mask & + ((unsigned int)*ucp2 - (unsigned int)*ucp1); + mask &= ~(isLT | isGT); + } + return (int)(isGT >> CHAR_BIT) - (int)(isLT >> CHAR_BIT); +} diff --git a/optee/optee_os/lib/libutils/ext/fault_mitigation.c b/optee/optee_os/lib/libutils/ext/fault_mitigation.c new file mode 100644 index 0000000..9bffb4e --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/fault_mitigation.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include + +#ifndef __KERNEL__ +struct ftmn_func_arg *__ftmn_global_func_arg; +#endif + +/* + * These functions can be implemented in assembly if needed. They would + * provide the same API but an implementation more resilient to fault + * injections. + * + * For now there is no need since it's enough with the single redundancy + * provided just by having these function implemented separately from where + * they are used. + */ + +unsigned long __weak ___ftmn_return_res(struct ftmn_check *check, + unsigned long steps, unsigned long res) +{ + if (check->steps != steps) + FTMN_PANIC(); + if ((check->res ^ FTMN_DEFAULT_HASH) != res) + FTMN_PANIC(); + return res; +} + +void __weak ___ftmn_expect_state(struct ftmn_check *check, enum ftmn_incr incr, + unsigned long steps, unsigned long res) +{ + if ((check->res ^ FTMN_DEFAULT_HASH) != res) + FTMN_PANIC(); + if (check->steps != steps) + FTMN_PANIC(); + check->steps += incr; +} + +void __weak ___ftmn_callee_done(struct ftmn_func_arg *arg, + unsigned long my_hash, + unsigned long res) +{ + arg->hash ^= my_hash; + arg->res = arg->hash ^ res; +} + +void __weak ___ftmn_callee_done_not_zero(struct ftmn_func_arg *arg, + unsigned long my_hash, + unsigned long res) +{ + if (res == 0) + FTMN_PANIC(); + arg->hash ^= my_hash; + arg->res = arg->hash ^ res; +} + +void __weak ___ftmn_callee_done_memcmp(struct ftmn_func_arg *arg, + unsigned long my_hash, int res, + ftmn_memcmp_t my_memcmp, + const void *p1, const void *p2, + size_t nb) +{ + int res2 = 0; + + if (!nb) + FTMN_PANIC(); + + res2 = my_memcmp(p1, p2, nb); + if (res2 != res) + FTMN_PANIC(); + + arg->hash ^= my_hash; + arg->res = arg->hash ^ res; +} + +void __weak ___ftmn_callee_done_check(struct ftmn_func_arg *arg, + unsigned long my_hash, + struct ftmn_check *check, + enum ftmn_incr incr, unsigned long steps, + unsigned long res) +{ + if ((check->res ^ FTMN_DEFAULT_HASH) != res) + FTMN_PANIC(); + if (check->steps != steps) + FTMN_PANIC(); + + check->steps += incr; + if (arg) { + arg->hash ^= my_hash; + arg->res = check->res ^ FTMN_DEFAULT_HASH ^ arg->hash; + } + +} + +void ___ftmn_callee_update_not_zero(struct ftmn_func_arg *arg, + unsigned long res) +{ + if (!res) + FTMN_PANIC(); + arg->res = arg->hash ^ res; +} + + +void __weak ___ftmn_copy_linked_call_res(struct ftmn_check *check, + enum ftmn_incr incr, + struct ftmn_func_arg *arg, + unsigned long res) +{ + if ((arg->res ^ arg->hash) != res) + FTMN_PANIC(); + check->res = res ^ FTMN_DEFAULT_HASH; + check->steps += incr; +} + +void __weak ___ftmn_set_check_res(struct ftmn_check *check, enum ftmn_incr incr, + unsigned long res) +{ + check->steps += incr; + check->res = res ^ FTMN_DEFAULT_HASH; +} + +void __weak ___ftmn_set_check_res_not_zero(struct ftmn_check *check, + enum ftmn_incr incr, + unsigned long res) +{ + if (!res) + FTMN_PANIC(); + check->steps += incr; + check->res = res ^ FTMN_DEFAULT_HASH; +} + +void __weak ___ftmn_set_check_res_memcmp(struct ftmn_check *check, + enum ftmn_incr incr, int res, + ftmn_memcmp_t my_memcmp, + const void *p1, const void *p2, + size_t nb) +{ + int res2 = 0; + + if (!nb) + FTMN_PANIC(); + + res2 = my_memcmp(p1, p2, nb); + if (res2 != res) + FTMN_PANIC(); + + check->steps += incr; + check->res = FTMN_DEFAULT_HASH ^ res; +} diff --git a/optee/optee_os/lib/libutils/ext/ftrace/ftrace.c b/optee/optee_os/lib/libutils/ext/ftrace/ftrace.c new file mode 100644 index 0000000..d120efe --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/ftrace/ftrace.c @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019, Linaro Limited + */ + +/* + * APIs defined in this file are required to use __noprof attribute to + * avoid any circular dependency during profiling. So this requirement + * prohibits these APIs to use standard library APIs as those can be + * profiled too. + */ + +#include +#include +#if defined(__KERNEL__) +#include +#include +#include +#include +#include +#else +#include +#include +#include +#endif +#include "ftrace.h" + +#define DURATION_MAX_LEN 16 +#define ENTRY_SIZE(idx) (DURATION_MAX_LEN + (idx) + \ + (2 * sizeof(unsigned long)) + 8) +#define EXIT_SIZE(idx) (DURATION_MAX_LEN + (idx) + 3) + +static const char hex_str[] = "0123456789abcdef"; + +static __noprof struct ftrace_buf *get_fbuf(void) +{ +#if defined(__KERNEL__) + short int ct = thread_get_id_may_fail(); + struct ts_session *s = NULL; + struct thread_specific_data *tsd = NULL; + + if (ct == -1) + return NULL; + + if (!(core_mmu_user_va_range_is_defined() && + core_mmu_user_mapping_is_active())) + return NULL; + + tsd = thread_get_tsd(); + s = TAILQ_FIRST(&tsd->sess_stack); + + if (!s || tsd->ctx != s->ctx) + return NULL; + + if (s->fbuf && s->fbuf->syscall_trace_enabled && + !s->fbuf->syscall_trace_suspended) + return s->fbuf; + else + return NULL; +#else + return &__ftrace_buf_start; +#endif +} + +#if defined(_CFG_FTRACE_BUF_WHEN_FULL_shift) + +/* + * This API shifts/moves ftrace buffer to create space for new dump + * in case the buffer size falls short of actual dump. + */ +static bool __noprof fbuf_make_room(struct ftrace_buf *fbuf, size_t size) +{ + char *dst = (char *)fbuf + fbuf->buf_off; + const char *src = (char *)fbuf + fbuf->buf_off + size; + size_t n = 0; + + fbuf->curr_size -= size; + + for (n = 0; n < fbuf->curr_size; n++) + dst[n] = src[n]; + + return true; +} + +#elif defined(_CFG_FTRACE_BUF_WHEN_FULL_wrap) + +/* Makes room in the trace buffer by discarding the previously recorded data. */ +static bool __noprof fbuf_make_room(struct ftrace_buf *fbuf, + size_t size) +{ + if (fbuf->buf_off + size > fbuf->max_size) + return false; + + fbuf->curr_size = 0; + + return true; +} + +#elif defined(_CFG_FTRACE_BUF_WHEN_FULL_stop) + +static bool __noprof fbuf_make_room(struct ftrace_buf *fbuf __unused, + size_t size __unused) +{ + return false; +} + +#else +#error CFG_FTRACE_BUF_WHEN_FULL value not supported +#endif + +static size_t __noprof to_func_enter_fmt(char *buf, uint32_t ret_idx, + unsigned long pc) +{ + char *str = buf; + uint32_t addr_size = 2 * sizeof(unsigned long); + uint32_t i = 0; + + for (i = 0; i < (DURATION_MAX_LEN + ret_idx); i++) + if (i == (DURATION_MAX_LEN - 2)) + *str++ = '|'; + else + *str++ = ' '; + + *str++ = '0'; + *str++ = 'x'; + + for (i = 0; i < addr_size; i++) + *str++ = hex_str[(pc >> 4 * (addr_size - i - 1)) & 0xf]; + + *str++ = '('; + *str++ = ')'; + *str++ = ' '; + *str++ = '{'; + *str++ = '\n'; + *str = '\0'; + + return str - buf; +} + +void __noprof ftrace_enter(unsigned long pc, unsigned long *lr) +{ + struct ftrace_buf *fbuf = NULL; + size_t line_size = 0; + bool full = false; + + fbuf = get_fbuf(); + + if (!fbuf || !fbuf->buf_off || !fbuf->max_size) + return; + + line_size = ENTRY_SIZE(fbuf->ret_idx); + + /* + * Check if we have enough space in ftrace buffer. If not then try to + * make room. + */ + full = (fbuf->curr_size + line_size) > fbuf->max_size; + if (full) + full = !fbuf_make_room(fbuf, line_size); + + if (!full) + fbuf->curr_size += to_func_enter_fmt((char *)fbuf + + fbuf->buf_off + + fbuf->curr_size, + fbuf->ret_idx, + pc); + + if (fbuf->ret_idx < FTRACE_RETFUNC_DEPTH) { + fbuf->ret_stack[fbuf->ret_idx] = *lr; + fbuf->begin_time[fbuf->ret_idx] = barrier_read_counter_timer(); + fbuf->ret_idx++; + } else { + /* + * This scenario isn't expected as function call depth + * shouldn't be more than FTRACE_RETFUNC_DEPTH. + */ +#if defined(__KERNEL__) + panic(); +#else + _utee_panic(0); +#endif + } + + *lr = (unsigned long)&__ftrace_return; +} + +static void __noprof ftrace_duration(char *buf, uint64_t start, uint64_t end) +{ + uint32_t max_us = CFG_FTRACE_US_MS; + uint32_t cntfrq = read_cntfrq(); + uint64_t ticks = end - start; + uint32_t ms = 0; + uint32_t us = 0; + uint32_t ns = 0; + uint32_t frac = 0; + uint32_t in = 0; + char unit = 'u'; + int i = 0; + + ticks = ticks * 1000000000 / cntfrq; + us = ticks / 1000; + ns = ticks % 1000; + + if (max_us && us >= max_us) { + /* Display value in milliseconds */ + unit = 'm'; + ms = us / 1000; + us = us % 1000; + frac = us; + in = ms; + } else { + /* Display value in microseconds */ + frac = ns; + in = us; + } + + *buf-- = 's'; + *buf-- = unit; + *buf-- = ' '; + + COMPILE_TIME_ASSERT(DURATION_MAX_LEN == 16); + if (in > 999999) { + /* Not enough space to print the value */ + for (i = 0; i < 10; i++) + *buf-- = '-'; + return; + } + + for (i = 0; i < 3; i++) { + *buf-- = hex_str[frac % 10]; + frac /= 10; + } + + *buf-- = '.'; + + while (in) { + *buf-- = hex_str[in % 10]; + in /= 10; + } +} + +unsigned long __noprof ftrace_return(void) +{ + struct ftrace_buf *fbuf = NULL; + char *line = NULL; + size_t line_size = 0; + char *dur_loc = NULL; + uint32_t i = 0; + + fbuf = get_fbuf(); + + /* Check for valid return index */ + if (fbuf && fbuf->ret_idx && fbuf->ret_idx <= FTRACE_RETFUNC_DEPTH) + fbuf->ret_idx--; + else + return 0; + + /* + * Check if we have a minimum ftrace buffer current size. If we have + * somehow corrupted ftrace buffer formatting, the function call chain + * shouldn't get broken since we have a valid fbuf->ret_idx at this + * point which can retrieve correct return pointer from fbuf->ret_stack. + */ + line_size = ENTRY_SIZE(fbuf->ret_idx); + if (fbuf->curr_size < line_size) + goto out; + + line = (char *)fbuf + fbuf->buf_off + fbuf->curr_size - line_size; + + /* + * Check for '{' symbol as it represents if it is an exit from current + * or nested function. If exit is from current function, than exit dump + * via ';' symbol else exit dump via '}' symbol. + */ + if (line[line_size - 2] == '{') { + line[line_size - 3] = ';'; + line[line_size - 2] = '\n'; + line[line_size - 1] = '\0'; + fbuf->curr_size -= 1; + + dur_loc = &line[DURATION_MAX_LEN - 3]; + ftrace_duration(dur_loc, fbuf->begin_time[fbuf->ret_idx], + barrier_read_counter_timer()); + } else { + bool full = false; + + line_size = EXIT_SIZE(fbuf->ret_idx); + full = (fbuf->curr_size + line_size) > fbuf->max_size; + if (full) + full = !fbuf_make_room(fbuf, line_size); + + if (!full) { + line = (char *)fbuf + fbuf->buf_off + fbuf->curr_size; + + for (i = 0; i < DURATION_MAX_LEN + fbuf->ret_idx; i++) { + if (i == (DURATION_MAX_LEN - 2)) + line[i] = '|'; + else + line[i] = ' '; + } + + line[i] = '}'; + line[i + 1] = '\n'; + line[i + 2] = '\0'; + + fbuf->curr_size += line_size - 1; + + dur_loc = &line[DURATION_MAX_LEN - 4]; + ftrace_duration(dur_loc, + fbuf->begin_time[fbuf->ret_idx], + barrier_read_counter_timer()); + } + } +out: + return fbuf->ret_stack[fbuf->ret_idx]; +} + +#if !defined(__KERNEL__) +void __noprof ftrace_longjmp(unsigned int *ret_idx) +{ + while (__ftrace_buf_start.ret_idx > *ret_idx) + ftrace_return(); +} + +void __noprof ftrace_setjmp(unsigned int *ret_idx) +{ + *ret_idx = __ftrace_buf_start.ret_idx; +} +#endif diff --git a/optee/optee_os/lib/libutils/ext/ftrace/ftrace.h b/optee/optee_os/lib/libutils/ext/ftrace/ftrace.h new file mode 100644 index 0000000..f4dc04a --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/ftrace/ftrace.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019, Linaro Limited + */ + +#ifndef FTRACE_H +#define FTRACE_H + +void ftrace_enter(unsigned long pc, unsigned long *lr); + +#endif /* FTRACE_H */ diff --git a/optee/optee_os/lib/libutils/ext/ftrace/sub.mk b/optee/optee_os/lib/libutils/ext/ftrace/sub.mk new file mode 100644 index 0000000..a813617 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/ftrace/sub.mk @@ -0,0 +1,5 @@ +cppflags-y += -I$(sub-dir)/../../.. + +ifneq ($(sm),ldelf) # TA, core +srcs-$(CFG_FTRACE_SUPPORT) += ftrace.c +endif diff --git a/optee/optee_os/lib/libutils/ext/include/arm64_bti.S b/optee/optee_os/lib/libutils/ext/include/arm64_bti.S new file mode 100644 index 0000000..63f42c7 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/arm64_bti.S @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include + +/* + * This macro emits a program property note section identifying + * architecture features which require special handling, mainly for + * use in assembly files in the libraries linked with TA's. + */ + +.macro emit_aarch64_feature_1_and, feat + .pushsection .note.gnu.property, "a" + .align 3 + .long 2f - 1f /* n_namesz */ + .long 6f - 3f /* n_desc_sz */ + .long NT_GNU_PROPERTY_TYPE_0 /* n_type */ +1: .string "GNU" /* name */ +2: + .align 3 +3: .long GNU_PROPERTY_AARCH64_FEATURE_1_AND /* pr_type */ + .long 5f - 4f /* pr_datasz */ +4: + /* + * This is described with an array of char in the Linux API + * spec but the text and all other usage (including binutils, + * clang and GCC) treat this as a 32 bit value so no swizzling + * is required for big endian. + */ + .long \feat /* property */ +5: + .align 3 +6: + .popsection +.endm diff --git a/optee/optee_os/lib/libutils/ext/include/asm.S b/optee/optee_os/lib/libutils/ext/include/asm.S new file mode 100644 index 0000000..2ee1c29 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/asm.S @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#if defined(__aarch64__) +#include +#endif + +#if defined(__aarch64__) && ((defined(__KERNEL__) && defined(CFG_CORE_BTI)) || \ + (!defined(__KERNEL__) && defined(CFG_TA_BTI))) +#define BTI(...) __VA_ARGS__ +#else +#define BTI(...) +#endif + +#if defined(CFG_UNWIND) && defined(__arm__) +#define UNWIND(...) __VA_ARGS__ +#else +#define UNWIND(...) +#endif + + .macro FUNC name colon section=default align=4 _bti=default + .ifc \section\(),default + .section .text.\name + .else + .section \section , "ax" , %progbits + .endif + .global \name + .type \name , %function + .balign \align + \name \colon +UNWIND( .fnstart) + .ifc \_bti\(),default +BTI( bti c) + .endif + .endm + + .macro LOCAL_FUNC name colon section=default align=4 _bti=default + .ifc \section\(),default + .section .text.\name + .else + .section \section , "ax" , %progbits + .endif + .type \name , %function + .balign \align + \name \colon +UNWIND( .fnstart) + .ifc \_bti\(),default +BTI( bti c) + .endif + .endm + + .macro WEAK_FUNC name colon section=default align=4 _bti=default + .ifc \section\(),default + .section .text.\name + .else + .section \section , "ax" , %progbits + .endif + .weak \name + .type \name , %function + .balign \align + \name \colon +UNWIND( .fnstart) + .ifc \_bti\(),default +BTI( bti c) + .endif + .endm + + .macro END_FUNC name +UNWIND( .fnend) + .size \name , .-\name + .endm + + .macro DATA name colon + .global \name + .type \name , %object + \name \colon + .endm + + .macro LOCAL_DATA name colon + .type \name , %object + \name \colon + .endm + + .macro END_DATA name + .size \name , .-\name + .endm diff --git a/optee/optee_os/lib/libutils/ext/include/atomic.h b/optee/optee_os/lib/libutils/ext/include/atomic.h new file mode 100644 index 0000000..1c5d461 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/atomic.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016-2019, Linaro Limited + */ + +#ifndef __ATOMIC_H +#define __ATOMIC_H + +#include +#include + +uint32_t atomic_inc32(volatile uint32_t *v); +uint32_t atomic_dec32(volatile uint32_t *v); + +static inline bool atomic_cas_uint(unsigned int *p, unsigned int *oval, + unsigned int nval) +{ + return __compiler_compare_and_swap(p, oval, nval); +} + +static inline bool atomic_cas_u32(uint32_t *p, uint32_t *oval, uint32_t nval) +{ + return __compiler_compare_and_swap(p, oval, nval); +} + +static inline int atomic_load_int(int *p) +{ + return __compiler_atomic_load(p); +} + +static inline short int atomic_load_short(short int *p) +{ + return __compiler_atomic_load(p); +} + +static inline unsigned int atomic_load_uint(unsigned int *p) +{ + return __compiler_atomic_load(p); +} + +static inline uint32_t atomic_load_u32(const uint32_t *p) +{ + return __compiler_atomic_load(p); +} + +static inline void atomic_store_int(int *p, int val) +{ + __compiler_atomic_store(p, val); +} + +static inline void atomic_store_short(short int *p, short int val) +{ + __compiler_atomic_store(p, val); +} + +static inline void atomic_store_uint(unsigned int *p, unsigned int val) +{ + __compiler_atomic_store(p, val); +} + +static inline void atomic_store_u32(uint32_t *p, uint32_t val) +{ + __compiler_atomic_store(p, val); +} + +#endif /*__ATOMIC_H*/ diff --git a/optee/optee_os/lib/libutils/ext/include/bitstring.h b/optee/optee_os/lib/libutils/ext/include/bitstring.h new file mode 100644 index 0000000..bebf092 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/bitstring.h @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Paul Vixie. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_BITSTRING_H_ +#define _SYS_BITSTRING_H_ + +typedef unsigned char bitstr_t; + +/* internal macros */ + /* byte of the bitstring bit is in */ +#define _bit_byte(bit) \ + ((bit) >> 3) + + /* mask for the bit within its byte */ +#define _bit_mask(bit) \ + (1 << ((bit)&0x7)) + +/* external macros */ + /* bytes in a bitstring of nbits bits */ +#define bitstr_size(nbits) \ + (((nbits) + 7) >> 3) + + /* allocate a bitstring */ +#define bit_alloc(nbits) \ + (bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t)) + + /* allocate a bitstring on the stack */ +#define bit_decl(name, nbits) \ + ((name)[bitstr_size(nbits)]) + + /* is bit N of bitstring name set? */ +#define bit_test(name, bit) \ + ((name)[_bit_byte(bit)] & _bit_mask(bit)) + + /* set bit N of bitstring name */ +#define bit_set(name, bit) \ + ((name)[_bit_byte(bit)] |= _bit_mask(bit)) + + /* clear bit N of bitstring name */ +#define bit_clear(name, bit) \ + ((name)[_bit_byte(bit)] &= ~_bit_mask(bit)) + + /* clear bits start ... stop in bitstring */ +#define bit_nclear(name, start, stop) do { \ + register bitstr_t *_name = (name); \ + register int _start = (start), _stop = (stop); \ + register int _startbyte = _bit_byte(_start); \ + register int _stopbyte = _bit_byte(_stop); \ + if (_startbyte == _stopbyte) { \ + _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \ + (0xff << ((_stop&0x7) + 1))); \ + } else { \ + _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \ + while (++_startbyte < _stopbyte) \ + _name[_startbyte] = 0; \ + _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \ + } \ +} while (0) + + /* set bits start ... stop in bitstring */ +#define bit_nset(name, start, stop) do { \ + register bitstr_t *_name = (name); \ + register int _start = (start), _stop = (stop); \ + register int _startbyte = _bit_byte(_start); \ + register int _stopbyte = _bit_byte(_stop); \ + if (_startbyte == _stopbyte) { \ + _name[_startbyte] |= ((0xff << (_start&0x7)) & \ + (0xff >> (7 - (_stop&0x7)))); \ + } else { \ + _name[_startbyte] |= 0xff << ((_start)&0x7); \ + while (++_startbyte < _stopbyte) \ + _name[_startbyte] = 0xff; \ + _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \ + } \ +} while (0) + + /* find first bit clear in name */ +#define bit_ffc(name, nbits, value) do { \ + register bitstr_t *_name = (name); \ + register int _byte, _nbits = (nbits); \ + register int _stopbyte = _bit_byte(_nbits - 1), _value = -1; \ + if (_nbits > 0) \ + for (_byte = 0; _byte <= _stopbyte; ++_byte) \ + if (_name[_byte] != 0xff) { \ + bitstr_t _lb; \ + _value = _byte << 3; \ + for (_lb = _name[_byte]; (_lb&0x1); \ + ++_value, _lb >>= 1); \ + break; \ + } \ + if (_value >= nbits) \ + _value = -1; \ + *(value) = _value; \ +} while (0) + + /* find first bit set in name */ +#define bit_ffs_from(name, nbits, startbit, value) do { \ + bitstr_t *_name = (name); \ + int _byte = 0; \ + int _nbits = (nbits); \ + int _startbyte = _bit_byte(startbit); \ + int _stopbyte = _bit_byte(_nbits - 1), _value = -1; \ + bitstr_t _test_bit_mask = 0xff << ((startbit) % 8); \ + \ + if (_nbits > 0) { \ + for (_byte = _startbyte; _byte <= _stopbyte; ++_byte) { \ + if (_name[_byte] & _test_bit_mask) { \ + bitstr_t _lb = 0; \ + \ + _value = _byte << 3; \ + for (_lb = _name[_byte] & _test_bit_mask; \ + !(_lb&0x1); ++_value, _lb >>= 1) \ + ; \ + break; \ + } \ + _test_bit_mask = 0xff; \ + } \ + } \ + if (_value >= nbits) \ + _value = -1; \ + *(value) = _value; \ +} while (0) + +#define bit_ffs(name, nbits, value) \ + bit_ffs_from((name), (nbits), 0, (value)) + +#endif /* !_SYS_BITSTRING_H_ */ diff --git a/optee/optee_os/lib/libutils/ext/include/compiler.h b/optee/optee_os/lib/libutils/ext/include/compiler.h new file mode 100644 index 0000000..d9c0f9e --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/compiler.h @@ -0,0 +1,279 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef COMPILER_H +#define COMPILER_H + +/* + * Macros that should be used instead of using __attribute__ directly to + * ease portability and make the code easier to read. + * + * Some of the defines below is known to sometimes cause conflicts when + * this file is included from xtest in normal world. It is assumed that + * the conflicting defines has the same meaning in that environment. + * Surrounding the troublesome defines with #ifndef should be enough. + */ +#define __deprecated __attribute__((deprecated)) +#ifndef __packed +#define __packed __attribute__((packed)) +#endif +#define __weak __attribute__((weak)) +#define __alias(x) __attribute__((alias(x))) +#ifndef __noreturn +#define __noreturn __attribute__((__noreturn__)) +#endif +#define __pure __attribute__((pure)) +#define __aligned(x) __attribute__((aligned(x))) +#define __printf(a, b) __attribute__((format(printf, a, b))) +#define __noinline __attribute__((noinline)) +#define __attr_const __attribute__((__const__)) +#ifndef __unused +#define __unused __attribute__((unused)) +#endif +#define __maybe_unused __attribute__((unused)) +#ifndef __used +#define __used __attribute__((__used__)) +#endif +#define __must_check __attribute__((warn_unused_result)) +#define __cold __attribute__((__cold__)) +#define __section(x) __attribute__((section(x))) +#define __data __section(".data") +#define __bss __section(".bss") +#ifdef __clang__ +#define __SECTION_FLAGS_RODATA +#else +/* + * Override sections flags/type generated by the C compiler to make sure they + * are: "a",%progbits (thus creating an allocatable, non-writeable, non- + * executable data section). + * The trailing COMMENT_CHAR comments out the flags generated by the compiler. + * This avoids a harmless warning with GCC. + */ +#if defined(__aarch64__) || defined(__arm__) +#define COMMENT_CHAR "//" +#else +#define COMMENT_CHAR "#" +#endif +#define __SECTION_FLAGS_RODATA ",\"a\",%progbits " COMMENT_CHAR +#endif +#define __rodata __section(".rodata" __SECTION_FLAGS_RODATA) +#define __rodata_dummy __section(".rodata.dummy" __SECTION_FLAGS_RODATA) +#define __rodata_unpaged(x) \ + __section(".rodata.__unpaged." x __SECTION_FLAGS_RODATA) +#ifdef CFG_CORE_ASLR +#define __relrodata_unpaged(x) __section(".data.rel.ro.__unpaged." x) +#else +#define __relrodata_unpaged(x) __rodata_unpaged(x) +#endif +#ifdef CFG_NS_VIRTUALIZATION +#define __nex_bss __section(".nex_bss") +#define __nex_data __section(".nex_data") +#else /* CFG_NS_VIRTUALIZATION */ +#define __nex_bss +#define __nex_data +#endif /* CFG_NS_VIRTUALIZATION */ +#define __noprof __attribute__((no_instrument_function)) +#define __nostackcheck __attribute__((no_instrument_function)) + +#define __compiler_bswap64(x) __builtin_bswap64((x)) +#define __compiler_bswap32(x) __builtin_bswap32((x)) +#define __compiler_bswap16(x) __builtin_bswap16((x)) + +#define __GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + \ + __GNUC_PATCHLEVEL__) + +#if __GCC_VERSION >= 50100 && !defined(__CHECKER__) +#define __HAVE_BUILTIN_OVERFLOW 1 +#endif + +#if __GCC_VERSION >= 90100 && !defined(__CHECKER__) +#define __HAVE_SINGLE_ARGUMENT_STATIC_ASSERT 1 +#endif + +#ifdef __HAVE_BUILTIN_OVERFLOW +#define __compiler_add_overflow(a, b, res) \ + __builtin_add_overflow((a), (b), (res)) + +#define __compiler_sub_overflow(a, b, res) \ + __builtin_sub_overflow((a), (b), (res)) + +#define __compiler_mul_overflow(a, b, res) \ + __builtin_mul_overflow((a), (b), (res)) +#else /*!__HAVE_BUILTIN_OVERFLOW*/ + +/* + * Copied/inspired from https://www.fefe.de/intof.html + */ + +#define __INTOF_ASSIGN(dest, src) (__extension__({ \ + typeof(src) __intof_x = (src); \ + typeof(dest) __intof_y = __intof_x; \ + (((uintmax_t)__intof_x == (uintmax_t)__intof_y) && \ + ((__intof_x < 1) == (__intof_y < 1)) ? \ + (void)((dest) = __intof_y) , 0 : 1); \ +})) + +#define __INTOF_ADD(c, a, b) (__extension__({ \ + typeof(a) __intofa_a = (a); \ + typeof(b) __intofa_b = (b); \ + intmax_t __intofa_a_signed = __intofa_a; \ + uintmax_t __intofa_a_unsigned = __intofa_a; \ + intmax_t __intofa_b_signed = __intofa_b; \ + uintmax_t __intofa_b_unsigned = __intofa_b; \ + \ + __intofa_b < 1 ? \ + __intofa_a < 1 ? \ + ((INTMAX_MIN - __intofa_b_signed <= \ + __intofa_a_signed)) ? \ + __INTOF_ASSIGN((c), __intofa_a_signed + \ + __intofa_b_signed) : 1 \ + : \ + ((__intofa_a_unsigned >= (uintmax_t)-__intofa_b) ? \ + __INTOF_ASSIGN((c), __intofa_a_unsigned + \ + __intofa_b_signed) \ + : \ + __INTOF_ASSIGN((c), \ + (intmax_t)(__intofa_a_unsigned + \ + __intofa_b_signed))) \ + : \ + __intofa_a < 1 ? \ + ((__intofa_b_unsigned >= (uintmax_t)-__intofa_a) ? \ + __INTOF_ASSIGN((c), __intofa_a_signed + \ + __intofa_b_unsigned) \ + : \ + __INTOF_ASSIGN((c), \ + (intmax_t)(__intofa_a_signed + \ + __intofa_b_unsigned))) \ + : \ + ((UINTMAX_MAX - __intofa_b_unsigned >= \ + __intofa_a_unsigned) ? \ + __INTOF_ASSIGN((c), __intofa_a_unsigned + \ + __intofa_b_unsigned) : 1); \ +})) + +#define __INTOF_SUB(c, a, b) (__extension__({ \ + typeof(a) __intofs_a = a; \ + typeof(b) __intofs_b = b; \ + intmax_t __intofs_a_signed = __intofs_a; \ + uintmax_t __intofs_a_unsigned = __intofs_a; \ + intmax_t __intofs_b_signed = __intofs_b; \ + uintmax_t __intofs_b_unsigned = __intofs_b; \ + \ + __intofs_b < 1 ? \ + __intofs_a < 1 ? \ + ((INTMAX_MAX + __intofs_b_signed >= \ + __intofs_a_signed) ? \ + __INTOF_ASSIGN((c), __intofs_a_signed - \ + __intofs_b_signed) : 1) \ + : \ + (((uintmax_t)(UINTMAX_MAX + __intofs_b_signed) >= \ + __intofs_a_unsigned) ? \ + __INTOF_ASSIGN((c), __intofs_a - \ + __intofs_b) : 1) \ + : \ + __intofs_a < 1 ? \ + (((intmax_t)(INTMAX_MIN + __intofs_b) <= \ + __intofs_a_signed) ? \ + __INTOF_ASSIGN((c), \ + (intmax_t)(__intofs_a_signed - \ + __intofs_b_unsigned)) : 1) \ + : \ + ((__intofs_b_unsigned <= __intofs_a_unsigned) ? \ + __INTOF_ASSIGN((c), __intofs_a_unsigned - \ + __intofs_b_unsigned) \ + : \ + __INTOF_ASSIGN((c), \ + (intmax_t)(__intofs_a_unsigned - \ + __intofs_b_unsigned))); \ +})) + +/* + * Dealing with detecting overflow in multiplication of integers. + * + * First step is to remove two corner cases with the minum signed integer + * which can't be represented as a positive integer + sign. + * Multiply with 0 or 1 can't overflow, no checking needed of the operation, + * only if it can be assigned to the result. + * + * After the corner cases are eliminated we convert the two factors to + * positive unsigned values, keeping track of the original in another + * variable which is used at the end to determine the sign of the product. + * + * The two terms (a and b) are divided into upper and lower half (x1 upper + * and x0 lower), so the product is: + * ((a1 << hshift) + a0) * ((b1 << hshift) + b0) + * which also is: + * ((a1 * b1) << (hshift * 2)) + (T1) + * ((a1 * b0 + a0 * b1) << hshift) + (T2) + * (a0 * b0) (T3) + * + * From this we can tell and (a1 * b1) has to be 0 or we'll overflow, that + * is, at least one of a1 or b1 has to be 0. Once this has been checked the + * addition: ((a1 * b0) << hshift) + ((a0 * b1) << hshift) + * isn't an addition as one of the terms will be 0. + * + * Since each factor in: (a0 * b0) + * only uses half the capicity of the underlaying type it can't overflow + * + * The addition of T2 and T3 can overflow so we use __INTOF_ADD() to + * perform that addition. If the addition succeeds without overflow the + * result is assigned the required sign and checked for overflow again. + */ + +#define __intof_mul_negate ((__intof_oa < 1) != (__intof_ob < 1)) +#define __intof_mul_hshift (sizeof(uintmax_t) * 8 / 2) +#define __intof_mul_hmask (UINTMAX_MAX >> __intof_mul_hshift) +#define __intof_mul_a0 ((uintmax_t)(__intof_a) >> __intof_mul_hshift) +#define __intof_mul_b0 ((uintmax_t)(__intof_b) >> __intof_mul_hshift) +#define __intof_mul_a1 ((uintmax_t)(__intof_a) & __intof_mul_hmask) +#define __intof_mul_b1 ((uintmax_t)(__intof_b) & __intof_mul_hmask) +#define __intof_mul_t (__intof_mul_a1 * __intof_mul_b0 + \ + __intof_mul_a0 * __intof_mul_b1) + +#define __INTOF_MUL(c, a, b) (__extension__({ \ + typeof(a) __intof_oa = (a); \ + typeof(a) __intof_a = __intof_oa < 1 ? -__intof_oa : __intof_oa; \ + typeof(b) __intof_ob = (b); \ + typeof(b) __intof_b = __intof_ob < 1 ? -__intof_ob : __intof_ob; \ + typeof(c) __intof_c; \ + \ + __intof_oa == 0 || __intof_ob == 0 || \ + __intof_oa == 1 || __intof_ob == 1 ? \ + __INTOF_ASSIGN((c), __intof_oa * __intof_ob) : \ + (__intof_mul_a0 && __intof_mul_b0) || \ + __intof_mul_t > __intof_mul_hmask ? 1 : \ + __INTOF_ADD((__intof_c), __intof_mul_t << __intof_mul_hshift, \ + __intof_mul_a1 * __intof_mul_b1) ? 1 : \ + __intof_mul_negate ? __INTOF_ASSIGN((c), -__intof_c) : \ + __INTOF_ASSIGN((c), __intof_c); \ +})) + +#define __compiler_add_overflow(a, b, res) __INTOF_ADD(*(res), (a), (b)) +#define __compiler_sub_overflow(a, b, res) __INTOF_SUB(*(res), (a), (b)) +#define __compiler_mul_overflow(a, b, res) __INTOF_MUL(*(res), (a), (b)) + +#endif /*!__HAVE_BUILTIN_OVERFLOW*/ + +#define __compiler_compare_and_swap(p, oval, nval) \ + __atomic_compare_exchange_n((p), (oval), (nval), true, \ + __ATOMIC_ACQUIRE, __ATOMIC_RELAXED) \ + +#define __compiler_atomic_load(p) __atomic_load_n((p), __ATOMIC_RELAXED) +#define __compiler_atomic_store(p, val) \ + __atomic_store_n((p), (val), __ATOMIC_RELAXED) + +#define barrier() asm volatile ("" : : : "memory") + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#if __has_attribute(__fallthrough__) +#define fallthrough __attribute__((__fallthrough__)) +#else +#define fallthrough do {} while (0) /* fallthrough */ +#endif + +#endif /*COMPILER_H*/ diff --git a/optee/optee_os/lib/libutils/ext/include/config.h b/optee/optee_os/lib/libutils/ext/include/config.h new file mode 100644 index 0000000..86fe92e --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/config.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2017 Intel Corporation + * + */ +#ifndef __CONFIG_H_ +#define __CONFIG_H_ + +/** + * @brief Check for macro definition in compiler-visible expressions + * + * This trick was pioneered in Linux as the config_enabled() macro. + * The madness has the effect of taking a macro value that may be + * defined to "1" (e.g. CONFIG_MYFEATURE), or may not be defined at + * all and turning it into a literal expression that can be used at + * "runtime". That is, it works similarly to + * "defined(CONFIG_MYFEATURE)" does except that it is an expansion + * that can exist in a standard expression and be seen by the compiler + * and optimizer. Thus much ifdef usage can be replaced with cleaner + * expressions like: + * + * if (IS_ENABLED(CONFIG_MYFEATURE)) + * myfeature_enable(); + * + * INTERNAL + * First pass just to expand any existing macros, we need the macro + * value to be e.g. a literal "1" at expansion time in the next macro, + * not "(1)", etc... Standard recursive expansion does not work. + */ +#define IS_ENABLED(config_macro) Z_IS_ENABLED1(config_macro) + +/** + * @brief As IS_ENABLED() but to be used with _CFG_* internal switches + * to avoid triggering false positives with checkpatch. + */ +#define IS_ENABLED2(config_macro) IS_ENABLED(config_macro) + +/* Now stick on a "_XXXX" prefix, it will now be "_XXXX1" if config_macro + * is "1", or just "_XXXX" if it's undefined. + * ENABLED: Z_IS_ENABLED2(_XXXX1) + * DISABLED Z_IS_ENABLED2(_XXXX) + */ +#define Z_IS_ENABLED1(config_macro) Z_IS_ENABLED2(_XXXX##config_macro) + +/* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string + * with a trailing comma), so it has the effect of making this a + * two-argument tuple to the preprocessor only in the case where the + * value is defined to "1" + * ENABLED: _YYYY, <--- note comma! + * DISABLED: _XXXX + */ +#define _XXXX1 _YYYY, + +/* Then we append an extra argument to fool the gcc preprocessor into + * accepting it as a varargs macro. + * arg1 arg2 arg3 + * ENABLED: Z_IS_ENABLED3(_YYYY, 1, 0) + * DISABLED Z_IS_ENABLED3(_XXXX 1, 0) + */ +#define Z_IS_ENABLED2(one_or_two_args) \ + Z_IS_ENABLED3(one_or_two_args true, false) + +/* And our second argument is thus now cooked to be 1 in the case + * where the value is defined to 1, and 0 if not: + */ +#define Z_IS_ENABLED3(ignore_this, val, ...) val + +#endif // __CONFIG_H_ diff --git a/optee/optee_os/lib/libutils/ext/include/confine_array_index.h b/optee/optee_os/lib/libutils/ext/include/confine_array_index.h new file mode 100644 index 0000000..cf831dc --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/confine_array_index.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2020 Linaro Limited */ +// Copyright 2019 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/* + * Content of LICENSE file mentioned above: +Copyright 2019 The Fuchsia Authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. 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 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(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 FBL_CONFINE_ARRAY_INDEX_H_ +#define FBL_CONFINE_ARRAY_INDEX_H_ + +#include + +// confine_array_index() bounds-checks and sanitizes an array index safely in the presence of +// speculative execution information leak bugs such as Spectre V1. confine_array_index() always +// returns a sanitized index, even in speculative-path execution. +// +// Callers need to combine confine_array_index with a conventional bounds check; the bounds +// check will return any necessary errors in the nonspeculative path, confine_array_index will +// confine indexes in the speculative path. +// +// Use: +// confine_array_index() returns |index|, if it is < size, or 0 if |index| is >= size. +// +// Example (may leak table1 contents): +// 1: int lookup3(size_t index) { +// 2: if (index >= table1_size) { +// 3: return -1; +// 4: } +// 5: size_t index2 = table1[index]; +// 6: return table2[index2]; +// 7: } +// +// Converted: +// +// 1: int lookup3(size_t index) { +// 2: if (index >= table1_size) { +// 3: return -1; +// 4: } +// 5: size_t safe_index = confine_array_index(index, table1_size); +// 6: size_t index2 = table1[safe_index]; +// 7: return table2[index2]; +// 8: } +#ifdef __aarch64__ +static inline size_t confine_array_index(size_t index, size_t size) { + size_t safe_index; + // Use a conditional select and a CSDB barrier to enforce validation of |index|. + // See "Cache Speculation Side-channels" whitepaper, section "Software Mitigation". + // "" The combination of both a conditional select/conditional move and the new barrier are + // sufficient to address this problem on ALL Arm implementations... "" + asm( + "cmp %1, %2\n" // %1 holds the unsanitized index + "csel %0, %1, xzr, lo\n" // Select index or zero based on carry (%1 within range) + "hint #20\n" // csdb + : "=r"(safe_index) + : "r"(index), "r"(size) + : "cc"); + return safe_index; +} +#endif +#ifdef __arm__ +static inline size_t confine_array_index(size_t index, size_t size) +{ + size_t ret_val = index; + + /* + * For the ARMv7/AArch32 case we're basing the select and barrier + * code on __load_no_speculate1() in as we + * lack the csel instruction. + */ + +#ifdef __thumb2__ + asm volatile ( + ".syntax unified\n" + "cmp %0, %1\n" + "it cs\n" +#ifdef __clang__ +#pragma clang diagnostic push + /* Avoid 'deprecated instruction in IT block [-Werror,-Winline-asm]' */ +#pragma clang diagnostic ignored "-Winline-asm" +#endif + "movcs %0, #0\n" +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + ".inst.n 0xf3af\t@ CSDB\n" + ".inst.n 0x8014\t@ CSDB" + : "+r" (ret_val) : "r" (size) : "cc"); +#else + asm volatile ( + ".syntax unified\n" + "cmp %0, %1\n" /* %0 holds the unsanitized index */ + "movcs %0, #0\n" + ".inst 0xe320f014\t@ CSDB" + : "+r" (ret_val) : "r" (size) : "cc"); +#endif + + return ret_val; +} +#endif /* __arm__ */ + +#ifdef __x86_64__ +static inline size_t confine_array_index(size_t index, size_t size) { + size_t safe_index = 0; + // Use a conditional move to enforce validation of |index|. + // The conditional move has a data dependency on the result of a comparison and cannot + // execute until the comparison is resolved. + // See "Software Techniques for Managing Speculation on AMD Processors", Mitigation V1-2. + // See "Analyzing potential bounds check bypass vulnerabilities", Revision 002, + // Section 5.2 Bounds clipping + __asm__( + "cmp %1, %2\n" + "cmova %1, %0\n" // Select between $0 and |index| + : "+r"(safe_index) + : "r"(index), "r"(size) + : "cc"); + return safe_index; +} +#endif + +#ifdef __riscv +static inline size_t confine_array_index(size_t index, size_t size) { + /* + * The naive C implementation without protection + * against side-channel attacks. + */ + if (index < size) + return index; + return 0; +} +#endif +#endif // FBL_CONFINE_ARRAY_INDEX_H_ diff --git a/optee/optee_os/lib/libutils/ext/include/fault_mitigation.h b/optee/optee_os/lib/libutils/ext/include/fault_mitigation.h new file mode 100644 index 0000000..4a18230 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/fault_mitigation.h @@ -0,0 +1,687 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ +#ifndef __FAULT_MITIGATION_H +#define __FAULT_MITIGATION_H + +#include +#include +#include +#include + +#ifdef __KERNEL__ +#include +#include +#else +#include +#endif + +/* + * Fault migitigation helpers to make successful Hardware Fault Attacks + * harder to achieve. The paper [1] by Riscure gives background to the + * problem. + * + * These helpers aim to make it hard for a single glitch attack to succeed + * while the protected function or one of the ftmn_*() functions are + * executed. + * + * To have something to work with we assume that a single glitch may affect + * a few instructions in sequence to do nothing or to corrupt the content + * of a few registers. + * + * Using the terminology from [1] we are implementing the following patterns: + * 3 FAULT.VALUE.CHECK + * 5 FAULT.DECISION.CHECK + * 9 FAULT.FLOW.CONTROL + * + * Additionally are the following patterns also acknowledged with a few + * comments: + * 1. FAULT.CONSTANT.CODING + * Zero is normally a success code in OP-TEE so special functions are + * added to record anything but a zero result. + * 8. FAULT.NESTED.CHECK + * The linked calls performed by for instance FTMN_CALL_FUNC() addresses + * this by relying on the called function to update a state in + * struct ftmn_func_arg which is checked when the function has returned. + * 11. FAULT.PENALTY + * This is implicit since we're normally trying to protect things post + * boot and booting takes quite some time. + * + * [1] https://web.archive.org/web/20220616035354/https://www.riscure.com/uploads/2020/05/Riscure_Whitepaper_Fault_Mitigation_Patterns_final.pdf + */ + +#include +#include + +/* + * struct ftmn_check - track current checked state + * @steps: accumulated checkpoints + * @res: last stored result or return value + * + * While a function is executed it can update its state as a way of keeping + * track of important passages inside the function. When the function + * returns with for instance ftmn_return_res() it is checked that the + * accumulated state matches the expected state. + * + * @res is xored with FTMN_DEFAULT_HASH in order to retrieve the saved + * result or return value. + */ +struct ftmn_check { + unsigned long steps; + unsigned long res; +}; + +/* + * struct ftmn_func_arg - track a called function + * @hash: xor bitmask + * @res: stored result xored with @hash + * + * When the call of a function is tracked @hash is initialized to hash of + * caller xored with hash of called function. Before the called function + * updates @res it first xors @hash with its own hash, which is supposed to + * restore @hash to the hash of the calling function. This allows the + * calling function to confirm that the correct function has been called. + */ +struct ftmn_func_arg { + unsigned long hash; + unsigned long res; +}; + +/* + * struct ftmn - link a tracked call chain + * @check: local checked state + * @arg: argument for the next called tracked function + * @saved_arg: pointer to an optional argument passed to this function + * @arg_pp: cached return value from __ftmn_get_tsd_func_arg_pp() + * @my_hash: the hash of the calling function + * @called_hash:the hash of the called function + * + * In order to maintain the linked call chain of tracked functions the + * struct ftmn_func_arg passed to this function is saved in @saved_arg + * before updating the argument pointer with @arg. + */ +struct ftmn { + struct ftmn_check check; + struct ftmn_func_arg arg; + struct ftmn_func_arg *saved_arg; + struct ftmn_func_arg **arg_pp; + unsigned long my_hash; + unsigned long called_hash; +}; + +/* + * enum ftmn_incr - increase counter values + * + * Prime numbers to be used when increasing the accumulated state. + * Different increase counters can be used to keep apart different + * checkpoints. + */ +enum ftmn_incr { + FTMN_INCR0 = 7873, + FTMN_INCR1 = 7877, + FTMN_INCR2 = 7879, + FTMN_INCR3 = 7883, + FTMN_INCR4 = 7901, + FTMN_INCR5 = 7907, + FTMN_INCR_RESERVED = 7919, +}; + +typedef int (*ftmn_memcmp_t)(const void *p1, const void *p2, size_t nb); + +/* The default hash used when xoring the result in struct ftmn_check */ +#ifdef __ILP32__ +#define FTMN_DEFAULT_HASH 0x9c478bf6UL +#else +#define FTMN_DEFAULT_HASH 0xc478bf63e9500cb5UL +#endif + +/* + * FTMN_PANIC() - FTMN specific panic function + * + * This function is called whenever the FTMN function detects an + * inconsistency. An inconsistency is able to occur if the system is + * subject to a fault injection attack, in this case doing a panic() isn't + * an extreme measure. + */ +#ifdef __KERNEL__ +#define FTMN_PANIC() panic(); +#else +#define FTMN_PANIC() TEE_Panic(0); +#endif + +#define __FTMN_MAX_FUNC_NAME_LEN 256 + +#define __FTMN_FUNC_BYTE(f, o, l) ((o) < (l) ? (uint8_t)(f)[(o)] : 0) + +#define __FTMN_GET_FUNC_U64(f, o, l) \ + (SHIFT_U64(__FTMN_FUNC_BYTE((f), (o), (l)), 0) | \ + SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 1, (l)), 8) | \ + SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 2, (l)), 16) | \ + SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 3, (l)), 24) | \ + SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 4, (l)), 32) | \ + SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 5, (l)), 40) | \ + SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 6, (l)), 48) | \ + SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 7, (l)), 56)) + +#define __FTMN_FUNC_HASH32(f, o, l) \ + (__FTMN_GET_FUNC_U64((f), (o), (l)) ^ \ + __FTMN_GET_FUNC_U64((f), (o) + 8, (l))) + +#define __FTMN_FUNC_HASH16(f, o, l) \ + (__FTMN_FUNC_HASH32((f), (o), (l)) ^ \ + __FTMN_FUNC_HASH32((f), (o) + __FTMN_MAX_FUNC_NAME_LEN / 16, (l))) + +#define __FTMN_FUNC_HASH8(f, o, l) \ + (__FTMN_FUNC_HASH16((f), (o), (l)) ^ \ + __FTMN_FUNC_HASH16((f), (o) + __FTMN_MAX_FUNC_NAME_LEN / 8, (l))) + +#define __FTMN_FUNC_HASH4(f, o, l) \ + (__FTMN_FUNC_HASH8((f), (o), (l)) ^ \ + __FTMN_FUNC_HASH8((f), (o) + __FTMN_MAX_FUNC_NAME_LEN / 4, (l))) + +#define __FTMN_FUNC_HASH2(f, l) \ + (__FTMN_FUNC_HASH4(f, 0, l) ^ \ + __FTMN_FUNC_HASH4(f, __FTMN_MAX_FUNC_NAME_LEN / 2, l)) + +#ifdef __ILP32__ +#define __FTMN_FUNC_HASH(f, l) \ + (unsigned long)(__FTMN_FUNC_HASH2((f), (l)) ^ \ + (__FTMN_FUNC_HASH2((f), (l)) >> 32)) +#else +#define __FTMN_FUNC_HASH(f, l) (unsigned long)__FTMN_FUNC_HASH2((f), (l)) +#endif + +#define __ftmn_step_count_1(c0) ((c0) * FTMN_INCR0) +#define __ftmn_step_count_2(c0, c1) \ + (__ftmn_step_count_1(c0) + (c1) * FTMN_INCR1) +#define __ftmn_step_count_3(c0, c1, c2) \ + (__ftmn_step_count_2(c0, c1) + (c2) * FTMN_INCR2) +#define __ftmn_step_count_4(c0, c1, c2, c3) \ + (__ftmn_step_count_3(c0, c1, c2) + (c3) * FTMN_INCR3) +#define __ftmn_step_count_5(c0, c1, c2, c3, c4) \ + (__ftmn_step_count_4(c0, c1, c2, c3) + (c4) * FTMN_INCR4) +#define __ftmn_step_count_6(c0, c1, c2, c3, c4, c5) \ + (__ftmn_step_count_5(c0, c1, c2, c3, c4) + (c5) * FTMN_INCR5) +#define ___ftmn_args_count(_0, _1, _2, _3, _4, _5, x, ...) x +#define __ftmn_args_count(...) \ + ___ftmn_args_count(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0) +#define ___ftmn_step_count(count, ...) __ftmn_step_count_ ## count(__VA_ARGS__) +#define __ftmn_step_count(count, ...) ___ftmn_step_count(count, __VA_ARGS__) + +unsigned long ___ftmn_return_res(struct ftmn_check *check, unsigned long steps, + unsigned long res); +void ___ftmn_expect_state(struct ftmn_check *check, enum ftmn_incr incr, + unsigned long steps, unsigned long res); + +void ___ftmn_callee_done(struct ftmn_func_arg *arg, unsigned long my_hash, + unsigned long res); +void ___ftmn_callee_done_not_zero(struct ftmn_func_arg *arg, + unsigned long my_hash, + unsigned long res); +void ___ftmn_callee_done_memcmp(struct ftmn_func_arg *arg, + unsigned long my_hash, int res, + ftmn_memcmp_t my_memcmp, + const void *p1, const void *p2, size_t nb); +void ___ftmn_callee_done_check(struct ftmn_func_arg *arg, unsigned long my_hash, + struct ftmn_check *check, enum ftmn_incr incr, + unsigned long steps, unsigned long res); + +void ___ftmn_callee_update_not_zero(struct ftmn_func_arg *arg, + unsigned long res); + +void ___ftmn_set_check_res(struct ftmn_check *check, enum ftmn_incr incr, + unsigned long res); +void ___ftmn_set_check_res_not_zero(struct ftmn_check *check, + enum ftmn_incr incr, + unsigned long res); +void ___ftmn_set_check_res_memcmp(struct ftmn_check *check, enum ftmn_incr incr, + int res, ftmn_memcmp_t my_memcmp, + const void *p1, const void *p2, size_t nb); + +void ___ftmn_copy_linked_call_res(struct ftmn_check *check, enum ftmn_incr incr, + struct ftmn_func_arg *arg, unsigned long res); + + +#ifndef __KERNEL__ +extern struct ftmn_func_arg *__ftmn_global_func_arg; +#endif + +static inline struct ftmn_func_arg **__ftmn_get_tsd_func_arg_pp(void) +{ +#if defined(CFG_FAULT_MITIGATION) && defined(__KERNEL__) + return &thread_get_tsd()->ftmn_arg; +#elif defined(CFG_FAULT_MITIGATION) + return &__ftmn_global_func_arg; +#else + return NULL; +#endif +} + +static inline struct ftmn_func_arg *__ftmn_get_tsd_func_arg(void) +{ + struct ftmn_func_arg **pp = __ftmn_get_tsd_func_arg_pp(); + + if (!pp) + return NULL; + + return *pp; +} + +static inline void __ftmn_push_linked_call(struct ftmn *ftmn, + unsigned long my_hash, + unsigned long called_hash) +{ + struct ftmn_func_arg **arg_pp = __ftmn_get_tsd_func_arg_pp(); + + if (arg_pp) { + ftmn->arg_pp = arg_pp; + ftmn->my_hash = my_hash; + ftmn->called_hash = called_hash; + ftmn->saved_arg = *ftmn->arg_pp; + *ftmn->arg_pp = &ftmn->arg; + ftmn->arg.hash = my_hash; + } +} + +static inline void __ftmn_pop_linked_call(struct ftmn *ftmn) +{ + if (ftmn->arg_pp) + *ftmn->arg_pp = ftmn->saved_arg; +} + +static inline void __ftmn_copy_linked_call_res(struct ftmn *f, + enum ftmn_incr incr, + unsigned long res) +{ + if (f->arg_pp) { + assert(f->arg.hash == (f->my_hash ^ f->called_hash)); + assert(&f->arg == *f->arg_pp); + assert((f->arg.hash ^ f->arg.res) == res); + ___ftmn_copy_linked_call_res(&f->check, incr, &f->arg, res); + } +} + +static inline void __ftmn_calle_swap_hash(struct ftmn_func_arg *arg, + unsigned long my_old_hash, + unsigned long my_new_hash) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) + arg->hash ^= my_old_hash ^ my_new_hash; +} + +static inline void __ftmn_callee_done(struct ftmn_func_arg *arg, + unsigned long my_hash, unsigned long res) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) + ___ftmn_callee_done(arg, my_hash, res); +} + +static inline void __ftmn_callee_done_not_zero(struct ftmn_func_arg *arg, + unsigned long hash, + unsigned long res) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) + ___ftmn_callee_done_not_zero(arg, hash, res); +} + +static inline int +__ftmn_callee_done_memcmp(struct ftmn_func_arg *arg, unsigned long hash, + ftmn_memcmp_t my_memcmp, + const void *p1, const void *p2, size_t nb) +{ + int res = my_memcmp(p1, p2, nb); + + if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) + ___ftmn_callee_done_memcmp(arg, hash, res, my_memcmp, + p1, p2, nb); + + return res; +} + +static inline void __ftmn_callee_done_check(struct ftmn *ftmn, + unsigned long my_hash, + enum ftmn_incr incr, + unsigned long steps, + unsigned long res) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION)) + ___ftmn_callee_done_check(__ftmn_get_tsd_func_arg(), my_hash, + &ftmn->check, incr, steps, res); +} + +static inline void __ftmn_callee_update_not_zero(struct ftmn_func_arg *arg, + unsigned long res) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) + ___ftmn_callee_update_not_zero(arg, res); +} + +static inline void __ftmn_set_check_res(struct ftmn *ftmn, enum ftmn_incr incr, + unsigned long res) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION)) + ___ftmn_set_check_res(&ftmn->check, incr, res); +} + +static inline void __ftmn_set_check_res_not_zero(struct ftmn *ftmn, + enum ftmn_incr incr, + unsigned long res) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION)) + ___ftmn_set_check_res_not_zero(&ftmn->check, incr, res); +} + + + +/* + * FTMN_FUNC_HASH() - "hash" a function name + * + * Function names are "hashed" into an unsigned long. The "hashing" is done + * by xoring each 32/64 bit word of the function name producing a bit + * pattern that should be mostly unique for each function. Only the first + * 256 characters of the name are used when xoring as this is expected to + * be optimized to be calculated when compiling the source code in order to + * minimize the overhead. + */ +#define FTMN_FUNC_HASH(name) __FTMN_FUNC_HASH(name, sizeof(name)) + +/* + * FTMN_PUSH_LINKED_CALL() - push call into a linked call chain + * @ftmn: The local struct ftmn + * @called_func_hash: The hash of the called function + * + * Inserts a call into a linked call chain or starts a new call chain if + * the passed struct ftmn_func_arg pointer was NULL. + * + * Each FTMN_PUSH_LINKED_CALL() is supposed to be matched by a + * FTMN_POP_LINKED_CALL(). + */ +#define FTMN_PUSH_LINKED_CALL(ftmn, called_func_hash) \ + __ftmn_push_linked_call((ftmn), FTMN_FUNC_HASH(__func__), \ + (called_func_hash)) + +/* + * FTMN_SET_CHECK_RES_FROM_CALL() - copy the result from a linked call + * @ftmn: The struct ftmn used during the linked call + * @incr: Value to increase the checked state with + * @res: Returned result to be match against the saved/copied result + * + * This macro is called just after a checked linked function has returned. + * The return value from the function is copied from the struct ftmn_func_arg + * passed to the called function into the local checked state. The checked + * state is increased with @incr. @res is checked against the saved result + * of the called function. + */ +#define FTMN_SET_CHECK_RES_FROM_CALL(ftmn, incr, res) \ + __ftmn_copy_linked_call_res((ftmn), (incr), (res)) + +/* + * FTMN_POP_LINKED_CALL() - remove a call from a linked call chain + * @ftmn: The local struct ftmn + * + * Supposed to match a call to FTMN_PUSH_LINKED_CALL() + */ +#define FTMN_POP_LINKED_CALL(ftmn) __ftmn_pop_linked_call((ftmn)) + +/* + * FTMN_CALL_FUNC() - Do a linked call to a function + * @res: Variable to be assigned the result of the called function + * @ftmn: The local struct ftmn + * @incr: Value to increase the checked state with + * @func: Function to be called + * @...: Arguments to pass to @func + * + * This macro can be used to make a linked call to another function, the + * callee. This macro depends on the callee to always update the struct + * ftmn_func_arg (part of struct ftmn) even when returning an error. + * + * Note that in the cases where the callee may skip updating the struct + * ftmn_func_arg this macro cannot be used as + * FTMN_SET_CHECK_RES_FROM_CALL() would cause a panic due to mismatching + * return value and saved result. + */ +#define FTMN_CALL_FUNC(res, ftmn, incr, func, ...) \ + do { \ + FTMN_PUSH_LINKED_CALL((ftmn), FTMN_FUNC_HASH(#func)); \ + (res) = func(__VA_ARGS__); \ + FTMN_SET_CHECK_RES_FROM_CALL((ftmn), (incr), (res)); \ + FTMN_POP_LINKED_CALL((ftmn)); \ + } while (0) + +/* + * FTMN_CALLEE_DONE() - Record result of callee + * @res: Result or return value + * + * The passed result will be stored in the struct ftmn_func_arg struct + * supplied by the caller. This function must only be called once by the + * callee. + * + * Note that this function is somewhat dangerous as any passed value will + * be stored so if the value has been tampered with there is no additional + * redundant checks to rely on. + */ +#define FTMN_CALLEE_DONE(res) \ + __ftmn_callee_done(__ftmn_get_tsd_func_arg(), \ + FTMN_FUNC_HASH(__func__), (res)) +/* + * FTMN_CALLEE_DONE_NOT_ZERO() - Record non-zero result of callee + * @res: Result or return value + * + * The passed result will be stored in the struct ftmn_func_arg struct + * supplied by the caller. This function must only be called once by the + * callee. + * + * Note that this function is somewhat dangerous as any passed value will + * be stored so if the value has been tampered with there is no additional + * redundant checks to rely on. However, there are extra checks against + * unintentionally storing a zero which often is interpreted as a + * successful return value. + */ +#define FTMN_CALLEE_DONE_NOT_ZERO(res) \ + __ftmn_callee_done_not_zero(__ftmn_get_tsd_func_arg(), \ + FTMN_FUNC_HASH(__func__), (res)) + +/* + * FTMN_CALLEE_DONE_CHECK() - Record result of callee with checked state + * @ftmn: The local struct ftmn + * @incr: Value to increase the checked state with + * @exp_steps: Expected recorded checkpoints + * @res: Result or return value + * + * The passed result will be stored in the struct ftmn_func_arg struct + * supplied by the caller. This function must only be called once by the + * callee. + * + * @res is double checked against the value stored in local checked state. + * @exp_steps is checked against the locate checked state. The local + * checked state is increased by @incr. + */ +#define FTMN_CALLEE_DONE_CHECK(ftmn, incr, exp_steps, res) \ + __ftmn_callee_done_check((ftmn), FTMN_FUNC_HASH(__func__), \ + (incr), (exp_steps), (res)) + +/* + * FTMN_CALLEE_DONE_MEMCMP() - Record result of memcmp() in a callee + * @my_memcmp: Function pointer of custom memcmp() + * @p1: Pointer to first buffer + * @p2: Pointer to second buffer + * @nb: Number of bytes + * + * The result from the mem compare is saved in the local checked state. + * This function must only be called once by the callee. + */ +#define FTMN_CALLEE_DONE_MEMCMP(my_memcmp, p1, p2, nb) \ + __ftmn_callee_done_memcmp(__ftmn_get_tsd_func_arg(), \ + FTMN_FUNC_HASH(__func__), (my_memcmp), \ + (p1), (p2), (nb)) + +/* + * FTMN_CALLEE_UPDATE_NOT_ZERO() - Update the result of a callee with a + * non-zero value + * @res: Result or return value + * + * The passed result will be stored in the struct ftmn_func_arg struct + * supplied by the caller. This function can be called any number of times + * by the callee, provided that one of the FTMN_CALLEE_DONE_XXX() functions + * has been called first. + * + * Note that this function is somewhat dangerous as any passed value will + * be stored so if the value has been tampered with there is no additional + * redundant checks to rely on. However, there are extra checks against + * unintentionally storing a zero which often is interpreted as a + * successful return value. + */ +#define FTMN_CALLEE_UPDATE_NOT_ZERO(res) \ + __ftmn_callee_update_not_zero(__ftmn_get_tsd_func_arg(), res) + +/* + * FTMN_CALLEE_SWAP_HASH() - Remove old hash and add new hash + * @my_old_hash: The old hash to remove + * + * This macro replaces the old expected function hash with the hash of the + * current function. + * + * If a function is called using an alias the caller uses the hash of the + * alias not the real function name. This hash is recoded in the field + * "hash" in struct ftmn_func_arg which can be found with + * __ftmn_get_tsd_func_arg(). + * + * The FTMN_CALLE_* functions only work with the real function name so the + * old hash must be removed and replaced with the new for the calling + * function to be able to verify the result. + */ +#define FTMN_CALLEE_SWAP_HASH(my_old_hash) \ + __ftmn_calle_swap_hash(__ftmn_get_tsd_func_arg(), \ + (my_old_hash), FTMN_FUNC_HASH(__func__)) + +/* + * FTMN_SET_CHECK_RES() - Records a result in local checked state + * @ftmn: The local struct ftmn + * @incr: Value to increase the checked state with + * @res: Result or return value + * + * Note that this function is somewhat dangerous as any passed value will + * be stored so if the value has been tampered with there is no additional + * redundant checks to rely on. + */ +#define FTMN_SET_CHECK_RES(ftmn, incr, res) \ + __ftmn_set_check_res((ftmn), (incr), (res)) + +/* + * FTMN_SET_CHECK_RES_NOT_ZERO() - Records a non-zero result in local checked + * state + * @ftmn: The local struct ftmn + * @incr: Value to increase the checked state with + * @res: Result or return value + * + * Note that this function is somewhat dangerous as any passed value will + * be stored so if the value has been tampered with there is no additional + * redundant checks to rely on. However, there are extra checks against + * unintentionally storing a zero which often is interpreted as a + * successful return value. + */ +#define FTMN_SET_CHECK_RES_NOT_ZERO(ftmn, incr, res) \ + __ftmn_set_check_res_not_zero((ftmn), (incr), (res)) + +static inline int ftmn_set_check_res_memcmp(struct ftmn *ftmn, + enum ftmn_incr incr, + ftmn_memcmp_t my_memcmp, + const void *p1, const void *p2, + size_t nb) +{ + int res = my_memcmp(p1, p2, nb); + + if (IS_ENABLED(CFG_FAULT_MITIGATION)) + ___ftmn_set_check_res_memcmp(&ftmn->check, incr, res, + my_memcmp, p1, p2, nb); + + return res; +} + +/* + * FTMN_STEP_COUNT() - Calculate total step count + * + * Takes variable number of arguments, up to a total of 6. Where arg0 + * is the number of times the counter has been increased by FTMN_INCR0, + * arg1 FTMN_INCR1 and so on. + */ +#define FTMN_STEP_COUNT(...) \ + __ftmn_step_count(__ftmn_args_count(__VA_ARGS__), __VA_ARGS__) + +/* + * ftmn_checkpoint() - Add a checkpoint + * @ftmn: The local struct ftmn + * @incr: Value to increase the checked state with + * + * Adds a checkpoint by increasing the internal checked state. This + * can be checked at a later point in the calling function, for instance + * with ftmn_return_res(). + */ +static inline void ftmn_checkpoint(struct ftmn *ftmn, enum ftmn_incr incr) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION)) { + /* + * The purpose of the barriers is to prevent the compiler + * from optimizing this increase to some other location + * in the calling function. + */ + barrier(); + ftmn->check.steps += incr; + barrier(); + } +} + +/* + * ftmn_expect_state() - Check expected state + * @ftmn: The local struct ftmn + * @incr: Value to increase the checked state with + * @steps: Expected accumulated steps + * @res: Expected saved result or return value + * + * This is a more advanced version of ftmn_checkpoint() which before + * increasing the accumulated steps first checks the accumulated steps and + * saved result or return value. + */ +static inline void ftmn_expect_state(struct ftmn *ftmn, + enum ftmn_incr incr, unsigned long steps, + unsigned long res) +{ + if (IS_ENABLED(CFG_FAULT_MITIGATION)) { + assert((ftmn->check.res ^ FTMN_DEFAULT_HASH) == res); + assert(ftmn->check.steps == steps); + + ___ftmn_expect_state(&ftmn->check, incr, steps, res); + } +} + +/* + * ftmn_return_res() - Check and return result + * @ftmn: The local struct ftmn + * @steps: Expected accumulated steps + * @res: Expected saved result or return value + * + * Checks that the internal accumulated state matches the supplied @steps + * and that the saved result or return value matches the supplied one. + * + * Returns @res. + */ +static inline unsigned long ftmn_return_res(struct ftmn *ftmn, + unsigned long steps, + unsigned long res) +{ + /* + * We're expecting that the compiler does a tail call optimization + * allowing ___ftmn_return_res() to have full control over the + * returned value. Thus trying to reduce the window where the + * return value can be tampered with. + */ + if (IS_ENABLED(CFG_FAULT_MITIGATION)) { + assert((ftmn->check.res ^ FTMN_DEFAULT_HASH) == res); + assert(ftmn->check.steps == steps); + + return ___ftmn_return_res(&ftmn->check, steps, res); + } + return res; +} +#endif /*__FAULT_MITIGATION_H*/ diff --git a/optee/optee_os/lib/libutils/ext/include/mempool.h b/optee/optee_os/lib/libutils/ext/include/mempool.h new file mode 100644 index 0000000..4a73171 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/mempool.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef __MEMPOOL_H +#define __MEMPOOL_H + +#include + +/* + * Memory pool for large temporary memory allocations that must not fail. + * With the first allocation from an unused (idle or free) pool the pool + * becomes reserved for that particular thread, until all allocations are + * freed again. In order to avoid dead-lock and ease code review it is good + * practise to free everything allocated by a certain function before + * returning. + */ + +/* + * struct mempool_item - internal struct to keep track of an item + */ +struct mempool_item { + size_t size; + ssize_t prev_item_offset; + ssize_t next_item_offset; +}; + +struct mempool; + +#define MEMPOOL_ALIGN __alignof__(long) + +#if defined(__KERNEL__) +/* + * System wide memory pool for large temporary memory allocation. + */ +extern struct mempool *mempool_default; +#endif + +/* + * mempool_alloc_pool() - Allocate a new memory pool + * @data: a block of memory to carve out items from, must + * have an alignment of MEMPOOL_ALIGN. + * @size: size fo the block of memory + * @release_mem: function to call when the pool has been emptied, + * ignored if NULL. + * returns a pointer to a valid pool on success or NULL on failure. + */ +struct mempool *mempool_alloc_pool(void *data, size_t size, + void (*release_mem)(void *ptr, size_t size)); + +/* + * mempool_alloc() - Allocate an item from a memory pool + * @pool: A memory pool created with mempool_alloc_pool() + * @size: Size in bytes of the item to allocate + * return a valid pointer on success or NULL on failure. + */ +void *mempool_alloc(struct mempool *pool, size_t size); + +/* + * mempool_calloc() - Allocate and zero initialize an array of elements from a + * memory pool + * @pool: A memory pool created with mempool_alloc_pool() + * @nmemb: Number of elements in the array + * @size: Size in bytes of each element in the array + * return a valid pointer on success or NULL on failure. + */ +void *mempool_calloc(struct mempool *pool, size_t nmemb, size_t size); + +/* + * mempool_free() - Frees a previously allocated item + * @pool: A memory pool create with mempool_alloc_pool() + * @ptr: A pointer to a previously allocated item + */ +void mempool_free(struct mempool *pool, void *ptr); + +#endif /*__MEMPOOL_H*/ diff --git a/optee/optee_os/lib/libutils/ext/include/memtag.h b/optee/optee_os/lib/libutils/ext/include/memtag.h new file mode 100644 index 0000000..d55d8c0 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/memtag.h @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef __MEMTAG_H +#define __MEMTAG_H + +#include +#include +#include +#include + +#if defined(CFG_MEMTAG) && defined(__aarch64__) +#define MEMTAG_IS_ENABLED 1 +#define MEMTAG_TAG_SHIFT 56 +#define MEMTAG_TAG_WIDTH 4 +#define MEMTAG_TAG_MASK (BIT(MEMTAG_TAG_WIDTH) - 1) + +#define MEMTAG_GRANULE_SIZE 16 +#else +#define MEMTAG_IS_ENABLED 0 +#define MEMTAG_GRANULE_SIZE 1 +#define MEMTAG_TAG_WIDTH 0 +#endif + +#define MEMTAG_GRANULE_MASK (MEMTAG_GRANULE_SIZE - 1) + +struct __memtag_ops { + void *(*set_tags)(void *addr, size_t size, uint8_t tag); + void *(*set_random_tags)(void *addr, size_t size); + void (*clear_mem)(void *addr, size_t size); + uint8_t (*read_tag)(const void *addr); +}; + +extern const struct __memtag_ops __memtag_ops_disabled; +extern const struct __memtag_ops *__memtag_ops; + +static inline void *__memtag_disabled_set_tags(void *addr, size_t size __unused, + uint8_t tag __unused) +{ + return addr; +} + +static inline void *__memtag_disabled_set_random_tags(void *addr, + size_t size __unused) +{ + return addr; +} + +static inline void __memtag_disabled_clear_mem(void *addr, size_t size) +{ + memset(addr, 0, size); +} + +static inline uint8_t __memtag_disabled_read_tag(const void *addr __unused) +{ + return 0; +} + +/* + * memtag_set_tags() - Tag a memory range + * @addr: Start of memory range + * @size: Size of memory range + * @tag: Tag to use + * + * The memory range is updated with the supplied tag. An eventual tag + * already present in the upper bits of the address in @addr is ignored. + * + * @addr and @size must be aligned/multiple of MEMTAG_GRANULE_SIZE. + * + * Returns an address with the new tag inserted to be used to access this + * memory area. + */ +static inline void *memtag_set_tags(void *addr, size_t size, uint8_t tag) +{ +#if MEMTAG_IS_ENABLED + return __memtag_ops->set_tags(addr, size, tag); +#else + return __memtag_disabled_set_tags(addr, size, tag); +#endif +} + +/* + * memtag_set_random_tags() - Tag a memory range with a random tag + * @addr: Start of memory range + * @size: Size of memory range + * + * The memory range is updated with a randomly generated tag. An eventual + * tag already present in the upper bits of the address in @addr is + * ignored. + * + * @addr and @size must be aligned/multiple of MEMTAG_GRANULE_SIZE. + * + * Returns an address with the new tag inserted to be used to access this + * memory area. + */ +static inline void *memtag_set_random_tags(void *addr, size_t size) +{ +#if MEMTAG_IS_ENABLED + return __memtag_ops->set_random_tags(addr, size); +#else + return __memtag_disabled_set_random_tags(addr, size); +#endif +} + +static inline void memtag_clear_mem(void *addr, size_t size) +{ +#if MEMTAG_IS_ENABLED + __memtag_ops->clear_mem(addr, size); +#else + __memtag_disabled_clear_mem(addr, size); +#endif +} + +/* + * memtag_strip_tag_vaddr() - Removes an eventual tag from an address + * @addr: Address to strip + * + * Returns a vaddr_t without an eventual tag. + */ +static inline vaddr_t memtag_strip_tag_vaddr(const void *addr) +{ + vaddr_t va = (vaddr_t)addr; + +#if MEMTAG_IS_ENABLED + va &= ~SHIFT_U64(MEMTAG_TAG_MASK, MEMTAG_TAG_SHIFT); +#endif + + return va; +} + +/* + * memtag_strip_tag_const() - Removes an eventual tag from an address + * @addr: Address to strip + * + * Returns the address without an eventual tag. + */ +static inline const void *memtag_strip_tag_const(const void *addr) +{ + return (const void *)memtag_strip_tag_vaddr(addr); +} + +/* + * memtag_strip_tag() - Removes an eventual tag from an address + * @addr: Address to strip + * + * Returns the address without an eventual tag. + */ +static inline void *memtag_strip_tag(void *addr) +{ + return (void *)memtag_strip_tag_vaddr(addr); +} + +/* + * memtag_insert_tag_vaddr() - Inserts a tag into an address + * @addr: Address to transform + * @tag: Tag to insert + * + * Returns the address with the new tag inserted. + */ +static inline vaddr_t memtag_insert_tag_vaddr(vaddr_t addr, + uint8_t tag __maybe_unused) +{ + vaddr_t va = memtag_strip_tag_vaddr((void *)addr); + +#if MEMTAG_IS_ENABLED + va |= SHIFT_U64(tag, MEMTAG_TAG_SHIFT); +#endif + + return va; +} + +/* + * memtag_insert_tag() - Inserts a tag into an address + * @addr: Address to transform + * @tag: Tag to insert + * + * Returns the address with the new tag inserted. + */ +static inline void *memtag_insert_tag(void *addr, uint8_t tag) +{ + return (void *)memtag_insert_tag_vaddr((vaddr_t)addr, tag); +} + +/* + * memtag_get_tag() - Extract a tag from an address + * @addr: Address with an eventual tag + * + * Returns the extracted tag. + */ +static inline uint8_t memtag_get_tag(const void *addr __maybe_unused) +{ +#if MEMTAG_IS_ENABLED + uint64_t va = (vaddr_t)addr; + + return (va >> MEMTAG_TAG_SHIFT) & MEMTAG_TAG_MASK; +#else + return 0; +#endif +} + +static inline uint8_t memtag_read_tag(const void *addr) +{ +#if MEMTAG_IS_ENABLED + return __memtag_ops->read_tag(addr); +#else + return __memtag_disabled_read_tag(addr); +#endif +} + +static inline void memtag_assert_tag(const void *addr __maybe_unused) +{ + assert(memtag_get_tag(addr) == memtag_read_tag(addr)); +} + +#if MEMTAG_IS_ENABLED +void memtag_init_ops(unsigned int memtag_impl); +#else +static inline void memtag_init_ops(unsigned int memtag_impl __unused) +{ +} +#endif + +static inline bool memtag_is_enabled(void) +{ +#if MEMTAG_IS_ENABLED + return __memtag_ops != &__memtag_ops_disabled; +#else + return false; +#endif +} + +#endif /*__MEMTAG_H*/ diff --git a/optee/optee_os/lib/libutils/ext/include/printk.h b/optee/optee_os/lib/libutils/ext/include/printk.h new file mode 100644 index 0000000..4f21b25 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/printk.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015 Linaro Limited + */ + +/* + * This file provides extensions to the standard snprintf() and vsnprintf() + * functions. These 'k' variants support additional formats. + */ + +#ifndef PRINTK_H +#define PRINTK_H + +#include +#include +#include + +int snprintk(char *str, size_t size, const char *fmt, ...) + __attribute__((__format__(__printf__, 3, 4))); +int vsnprintk(char *str, size_t size, const char *fmt, va_list ap) + __attribute__((__format__(__printf__, 3, 0))); + +int __vsnprintf(char *str, size_t size, const char *fmt, va_list ap, + bool ext) __attribute__((__format__(__printf__, 3, 0))); +int __vsprintf(char *bf, const char *fmt, va_list ap) + __attribute__((__format__(__printf__, 2, 0))); + +#endif /* PRINTK_H */ diff --git a/optee/optee_os/lib/libutils/ext/include/speculation_barrier.h b/optee/optee_os/lib/libutils/ext/include/speculation_barrier.h new file mode 100644 index 0000000..ef74e36 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/speculation_barrier.h @@ -0,0 +1,508 @@ +/* SPDX-License-Identifier: BSL-1.0 */ +/* Copyright (c) 2017 Arm Limited. All rights reserved. + + Boost Software License - Version 1.0 - August 17th, 2003 + + Permission is hereby granted, free of charge, to any person or organization + obtaining a copy of the software and accompanying documentation covered by + this license (the "Software") to use, reproduce, display, distribute, + execute, and transmit the Software, and to prepare derivative works of the + Software, and to permit third-parties to whom the Software is furnished to do + so, all subject to the following: + + The copyright notices in the Software and this entire statement, including + the above license grant, this restriction and the following disclaimer, must + be included in all copies of the Software, in whole or in part, and all + derivative works of the Software, unless such copies or derivative works are + solely in the form of machine-executable object code generated by a source + language processor. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR + ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. */ + + +#ifdef __HAVE_LOAD_NO_SPECULATE +#define load_no_speculate(__ptr, __low, __high) \ +(__extension__ ({ \ + __typeof__ ((__ptr)) __ptr_once = (__ptr); \ + __builtin_load_no_speculate (__ptr_once, __low, __high, \ + 0, __ptr_once); \ +})) + +#define load_no_speculate_fail(__ptr, __low, __high, __failval) \ +(__extension__ ({ \ + __typeof__ ((__ptr)) __ptr_once = (__ptr); \ + __builtin_load_no_speculate (__ptr_once, __low, __high, \ + __failval, __ptr_once); \ +})) + +#define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ + (__builtin_load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) + +#else + +#ifdef __GNUC__ +#define __UNUSED __attribute__((unused)) +#else +#define __UNUSED +#endif + +#ifdef __aarch64__ + +#define __load_no_speculate1(__ptr, __low, __high, __failval, \ + __cmpptr, __w, __sz) \ +(__extension__ ({ \ + __typeof__ (0 + (*(__ptr))) __nln_val; \ + /* This typecasting is required to ensure correct handling of upper \ + bits of failval, to ensure a clean return from the CSEL below. */ \ + __typeof__(*(__ptr)) __fv \ + = (__typeof__(*(__ptr)))(unsigned long long) (__failval); \ + /* If __high is explicitly NULL, we must not emit the \ + upper-bound comparison. We need to cast __high to an \ + unsigned long long before handing it to __builtin_constant_p to \ + ensure that clang/llvm correctly detects NULL as a constant if it \ + is defined as (void*) 0. */ \ + if (__builtin_constant_p ((unsigned long long)__high) \ + && __high == ((void *)0)) \ + { \ + __asm__ volatile ( \ + "cmp\t%[__c], %[__l]\n\t" \ + "bcc\t.ns%=\n\t" \ + "ldr" __sz "\t%" __w "[__v], %[__p]\n" \ + ".ns%=:\n\t" \ + "csel\t%" __w "[__v], %" __w "[__v], %" __w "[__f], cs\n\t" \ + "hint\t#0x14 // CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&r" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + /* The memory location from which we will load. */ \ + [__p] "m" (*(__ptr)), \ + /* The value to return if the condition check fails. */ \ + [__f] "rZ" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + else \ + { \ + __asm__ volatile ( \ + "cmp\t%[__c], %[__l]\n\t" \ + "ccmp\t%[__c], %[__h], 2, cs\n\t" \ + "bcs\t.ns%=\n\t" \ + "ldr" __sz "\t%" __w "[__v], %[__p]\n" \ + ".ns%=:\n\t" \ + "csel\t%" __w "[__v], %" __w "[__v], %" __w "[__f], cc\n\t" \ + "hint\t#0x14 // CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&r" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + [__h] "r" (__high), \ + /* The memory location from which we will load. */ \ + [__p] "m" (*(__ptr)), \ + /* The value to return if the condition check fails. */ \ + [__f] "rZ" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + (__typeof__ (*(__ptr))) __nln_val; \ +})) + +#define __load_no_speculate(__ptr, __low, __high, __failval, __cmpptr) \ +(__extension__ ({ \ + __typeof__ (0 + *(__ptr)) __nl_val; \ + \ + switch (sizeof(*(__ptr))) { \ + case 1: \ + __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ + __failval, __cmpptr, "w", "b"); \ + break; \ + case 2: \ + __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ + __failval, __cmpptr, "w", "h"); \ + break; \ + case 4: \ + __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ + __failval, __cmpptr, "w", ""); \ + break; \ + case 8: \ + __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ + __failval, __cmpptr, "x", ""); \ + break; \ + default: \ + { \ + char __static_assert_no_speculate_load_size_too_big \ + [sizeof (__nl_val) > 8 ? -1 : 1] __UNUSED; \ + break; \ + } \ + } \ + \ + (__typeof__ (*(__ptr))) __nl_val; \ +})) + +#define load_no_speculate(__ptr, __low, __high) \ +(__extension__ ({ \ + __typeof__ ((__ptr)) __ptr_once = (__ptr); \ + __load_no_speculate (__ptr_once, __low, __high, 0, __ptr_once); \ +})) + +#define load_no_speculate_fail(__ptr, __low, __high, __failval) \ +(__extension__ ({ \ + __typeof__ ((__ptr)) __ptr_once = (__ptr); \ + __load_no_speculate (__ptr_once, __low, __high, \ + __failval, __ptr_once); \ +})) + +#define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ + (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) + +/* AArch32 support for ARM and Thumb-2. Thumb-1 is not supported. */ +#elif defined (__ARM_32BIT_STATE) && (defined (__thumb2__) || !defined (__thumb__)) +#ifdef __thumb2__ +/* Thumb2 case. */ + +#define __load_no_speculate1(__ptr, __low, __high, __failval, \ + __cmpptr, __sz) \ +(__extension__ ({ \ + __typeof__ (0 + *(__ptr)) __nln_val; \ + __typeof__(*(__ptr)) __fv \ + = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ + /* If __high is explicitly NULL, we must not emit the \ + upper-bound comparison. We need to cast __high to an \ + unsigned long before handing it to __builtin_constant_p to \ + ensure that clang/llvm correctly detects NULL as a constant if it \ + is defined as (void*) 0. */ \ + if (__builtin_constant_p ((unsigned long)__high) \ + && __high == ((void *)0)) \ + { \ + __asm__ volatile ( \ + ".syntax unified\n\t" \ + "cmp\t%[__c], %[__l]\n\t" \ + "bcc\t.ns%=\n\t" \ + "ldr" __sz "\t%[__v], %[__p]\n" \ + ".ns%=:\n\t" \ + "it\tcc\n\t" \ + "movcc\t%[__v], %[__f]\n\t" \ + ".inst.n 0xf3af\t@ CSDB\n\t" \ + ".inst.n 0x8014\t@ CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&l" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + /* The memory location from which we will load. */ \ + [__p] "m" (*(__ptr)), \ + /* The value to return if the condition check fails. */ \ + [__f] "r" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + else \ + { \ + __asm__ volatile ( \ + ".syntax unified\n\t" \ + "cmp\t%[__c], %[__l]\n\t" \ + "it\tcs\n\t" \ + "cmpcs\t%[__h], %[__c]\n\t" \ + "bls\t.ns%=\n\t" \ + "ldr" __sz "\t%[__v], %[__p]\n" \ + ".ns%=:\n\t" \ + "it\tls\n\t" \ + "movls\t%[__v], %[__f]\n\t" \ + ".inst.n 0xf3af\t@ CSDB\n\t" \ + ".inst.n 0x8014\t@ CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&l" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + [__h] "r" (__high), \ + /* The memory location from which we will load. */ \ + [__p] "m" (*(__ptr)), \ + /* The value to return if the condition check fails. */ \ + [__f] "r" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + (__typeof__ (*(__ptr))) __nln_val; \ +})) \ + \ +/* Double-word version. */ +#define __load_no_speculate2(__ptr, __low, __high, __failval, \ + __cmpptr) \ +(__extension__ ({ \ + __typeof__ (0 + *(__ptr)) __nln_val; \ + __typeof__(*(__ptr)) __fv \ + = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ + /* If __high is explicitly NULL, we must not emit the \ + upper-bound comparison. We need to cast __high to an \ + unsigned long before handing it to __builtin_constant_p to \ + ensure that clang/llvm correctly detects NULL as a constant if it \ + is defined as (void*) 0. */ \ + if (__builtin_constant_p ((unsigned long)__high) \ + && __high == ((void *)0)) \ + { \ + __asm__ volatile ( \ + ".syntax unified\n\t" \ + "cmp\t%[__c], %[__l]\n\t" \ + "bcc\t.ns%=\n\t" \ + "ldr\t%Q[__v], [%[__p]]\n\t" \ + "ldr\t%R[__v], [%[__p], #4]\n" \ + ".ns%=:\n\t" \ + "it\tcc\n\t" \ + "movcc\t%Q[__v], %Q[__f]\n\t" \ + "it\tcc\n\t" \ + "movcc\t%R[__v], %R[__f]\n\t" \ + ".inst.n 0xf3af\t@ CSDB\n\t" \ + ".inst.n 0x8014\t@ CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&l" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + /* The memory location from which we will load. */ \ + [__p] "r" (__ptr), \ + /* The value to return if the condition check fails. */ \ + [__f] "r" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + else \ + { \ + __asm__ volatile ( \ + ".syntax unified\n\t" \ + "cmp\t%[__c], %[__l]\n\t" \ + "it\tcs\n\t" \ + "cmpcs\t%[__h], %[__c]\n\t" \ + "bls\t.ns%=\n\t" \ + "ldr\t%Q[__v], [%[__p]]\n\t" \ + "ldr\t%R[__v], [%[__p], #4]\n" \ + ".ns%=:\n\t" \ + "it\tls\n\t" \ + "movls\t%Q[__v], %Q[__f]\n\t" \ + "it\tls\n\t" \ + "movls\t%R[__v], %R[__f]\n\t" \ + ".inst.n 0xf3af\t@ CSDB\n\t" \ + ".inst.n 0x8014\t@ CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&l" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + [__h] "r" (__high), \ + /* The memory location from which we will load. */ \ + [__p] "r" (__ptr), \ + /* The value to return if the condition check fails. */ \ + [__f] "r" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + (__typeof__ (*(__ptr))) __nln_val; \ +})) + +#else +/* ARM case. */ + +#define __load_no_speculate1(__ptr, __low, __high, __failval, \ + __cmpptr, __sz) \ +(__extension__ ({ \ + __typeof__ (0 + *(__ptr)) __nln_val; \ + __typeof__(*(__ptr)) __fv \ + = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ + /* If __high is explicitly NULL, we must not emit the \ + upper-bound comparison. We need to cast __high to an \ + unsigned long before handing it to __builtin_constant_p to \ + ensure that clang/llvm correctly detects NULL as a constant if it \ + is defined as (void*) 0. */ \ + if (__builtin_constant_p ((unsigned long)__high) \ + && __high == ((void *)0)) \ + { \ + __asm__ volatile ( \ + ".syntax unified\n\t" \ + "cmp\t%[__c], %[__l]\n\t" \ + "ldr" __sz "cs\t%[__v], %[__p]\n\t" \ + "movcc\t%[__v], %[__f]\n\t" \ + ".inst 0xe320f014\t@ CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&r" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + /* The memory location from which we will load. */ \ + [__p] "m" (*(__ptr)), \ + /* The value to return if the condition check fails. */ \ + [__f] "rKI" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + else \ + { \ + __asm__ volatile ( \ + ".syntax unified\n\t" \ + "cmp\t%[__c], %[__l]\n\t" \ + "cmpcs\t%[__h], %[__c]\n\t" \ + "ldr" __sz "hi\t%[__v], %[__p]\n\t" \ + "movls\t%[__v], %[__f]\n\t" \ + ".inst 0xe320f014\t@ CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&r" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + [__h] "r" (__high), \ + /* The memory location from which we will load. */ \ + [__p] "m" (*(__ptr)), \ + /* The value to return if the condition check fails. */ \ + [__f] "rKI" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + (__typeof__ (*(__ptr))) __nln_val; \ +})) + +/* Double-word version. */ +#define __load_no_speculate2(__ptr, __low, __high, __failval, \ + __cmpptr) \ +(__extension__ ({ \ + __typeof__ (0 + *(__ptr)) __nln_val; \ + __typeof__(*(__ptr)) __fv \ + = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ + /* If __high is explicitly NULL, we must not emit the \ + upper-bound comparison. We need to cast __high to an \ + unsigned long before handing it to __builtin_constant_p to \ + ensure that clang/llvm correctly detects NULL as a constant if it \ + is defined as (void*) 0. */ \ + if (__builtin_constant_p ((unsigned long)__high) \ + && __high == ((void *)0)) \ + { \ + __asm__ volatile ( \ + ".syntax unified\n\t" \ + "cmp\t%[__c], %[__l]\n\t" \ + "ldrcs\t%Q[__v], [%[__p]]\n\t" \ + "ldrcs\t%R[__v], [%[__p], #4]\n\t" \ + "movcc\t%Q[__v], %Q[__f]\n\t" \ + "movcc\t%R[__v], %R[__f]\n\t" \ + ".inst 0xe320f014\t@ CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&r" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + /* The memory location from which we will load. */ \ + [__p] "r" (__ptr), \ + /* The value to return if the condition check fails. */ \ + [__f] "r" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + else \ + { \ + __asm__ volatile ( \ + ".syntax unified\n\t" \ + "cmp\t%[__c], %[__l]\n\t" \ + "cmpcs\t%[__h], %[__c]\n\t" \ + "ldrhi\t%Q[__v], [%[__p]]\n\t" \ + "ldrhi\t%R[__v], [%[__p], #4]\n\t" \ + "movls\t%Q[__v], %Q[__f]\n\t" \ + "movls\t%R[__v], %R[__f]\n\t" \ + ".inst 0xe320f014\t@ CSDB" \ + /* The value we have loaded, or failval if the condition check \ + fails. */ \ + : [__v] "=&r" (__nln_val) \ + /* The pointer we wish to use for comparisons, and the low and \ + high bounds to use in that comparison. Note that this need \ + not be the same as the pointer from which we will load. */ \ + : [__c] "r" (__cmpptr), [__l] "r" (__low), \ + [__h] "r" (__high), \ + /* The memory location from which we will load. */ \ + [__p] "r" (__ptr), \ + /* The value to return if the condition check fails. */ \ + [__f] "r" (__fv) \ + /* We always clobber the condition codes. */ \ + : "cc"); \ + } \ + (__typeof__ (*(__ptr))) __nln_val; \ +})) + +#endif // __thumb2__ + +/* Common to ARM and Thumb2. */ + +#define __load_no_speculate(__ptr, __low, __high, __failval, __cmpptr) \ +(__extension__ ({ \ + __typeof__ (0 + *(__ptr)) __nl_val; \ + \ + switch (sizeof(*(__ptr))) { \ + case 1: \ + __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ + __failval, __cmpptr, "b"); \ + break; \ + case 2: \ + __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ + __failval, __cmpptr, "h"); \ + break; \ + case 4: \ + __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ + __failval, __cmpptr, ""); \ + break; \ + case 8: \ + __nl_val = __load_no_speculate2 (__ptr, __low, __high, \ + __failval, __cmpptr); \ + break; \ + default: \ + { \ + char __static_assert_no_speculate_load_size_too_big \ + [sizeof (__nl_val) > 8 ? -1 : 1] __UNUSED; \ + break; \ + } \ + } \ + \ + (__typeof__ (*(__ptr))) __nl_val; \ +})) + +#define load_no_speculate(__ptr, __low, __high) \ +(__extension__ ({ \ + __typeof__ ((__ptr)) __ptr_once = (__ptr); \ + __load_no_speculate (__ptr_once, __low, __high, 0, __ptr_once); \ +})) + +#define load_no_speculate_fail(__ptr, __low, __high, __failval) \ +(__extension__ ({ \ + __typeof__ ((__ptr)) __ptr_once = (__ptr); \ + __load_no_speculate (__ptr_once, __low, __high, \ + __failval, __ptr_once); \ +})) + +#define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ + (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) + +#else +#error "No fallback provided for load_no_speculate" +#endif + +#endif diff --git a/optee/optee_os/lib/libutils/ext/include/stdlib_ext.h b/optee/optee_os/lib/libutils/ext/include/stdlib_ext.h new file mode 100644 index 0000000..26b5c1e --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/stdlib_ext.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +/* + * This file provides extensions to functions defined in + */ + +#ifndef __STDLIB_EXT_H +#define __STDLIB_EXT_H + +#include + +/* Overwrite buffer with a fixed pattern and free it. @ptr may be NULL. */ +void free_wipe(void *ptr); + +#endif /* __STDLIB_EXT_H */ diff --git a/optee/optee_os/lib/libutils/ext/include/string_ext.h b/optee/optee_os/lib/libutils/ext/include/string_ext.h new file mode 100644 index 0000000..0ee908e --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/string_ext.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* + * 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); + +/* A constant-time version of memcmp() */ +int consttime_memcmp(const void *p1, const void *p2, size_t nb); + +/* Deprecated. For backward compatibility. */ +static inline int buf_compare_ct(const void *s1, const void *s2, size_t n) +{ + return consttime_memcmp(s1, s2, n); +} + +/* Variant of strdup() that uses nex_malloc() instead of malloc() */ +char *nex_strdup(const char *s); + +/* + * Like memset(s, 0, count) but prevents the compiler from optimizing the call + * away. Such "dead store elimination" optimizations typically occur when + * clearing a *local* variable that is not used after it is cleared; but + * link-time optimization (LTO) can also trigger code elimination in other + * circumstances. See "Dead Store Elimination (Still) Considered Harmful" [1] + * for details and examples (and note that the Cland compiler enables LTO by + * default!). + * + * [1] https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang.pdf + * + * Practically speaking: + * + * - Use memzero_explicit() to *clear* (as opposed to initialize) *sensitive* + * data (such as keys, passwords, cryptographic state); + * - Otherwise, use memset(). + */ +void memzero_explicit(void *s, size_t count); + +#endif /* __STRING_EXT_H */ diff --git a/optee/optee_os/lib/libutils/ext/include/trace.h b/optee/optee_os/lib/libutils/ext/include/trace.h new file mode 100644 index 0000000..6f28bdb --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/trace.h @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef TRACE_H +#define TRACE_H + +#include +#include +#include +#include +#include + +#define MAX_PRINT_SIZE 256 +#define MAX_FUNC_PRINT_SIZE 32 + +#ifndef TRACE_LEVEL +#define TRACE_LEVEL TRACE_MAX +#endif + +/* + * Symbols provided by the entity that uses this API. + */ +extern int trace_level; +extern const char trace_ext_prefix[]; +void trace_ext_puts(const char *str); +int trace_ext_get_thread_id(void); +int trace_ext_get_core_id(void); +void trace_set_level(int level); +int trace_get_level(void); +void plat_trace_ext_puts(const char *str); + +/* Internal functions used by the macros below */ +void trace_vprintf(const char *func, int line, int level, bool level_ok, + const char *fmt, va_list args) __printf(5, 0); +void trace_printf(const char *func, int line, int level, bool level_ok, + const char *fmt, ...) __printf(5, 6); + +#define trace_printf_helper(level, level_ok, ...) \ + trace_printf(__func__, __LINE__, (level), (level_ok), \ + __VA_ARGS__) + +/* Formatted trace tagged with level independent */ +#if (TRACE_LEVEL <= 0) +#define MSG(...) (void)0 +#else +#define MSG(...) trace_printf_helper(0, false, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_ERROR level */ +#if (TRACE_LEVEL < TRACE_ERROR) +#define EMSG(...) (void)0 +#else +#define EMSG(...) trace_printf_helper(TRACE_ERROR, true, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_INFO level */ +#if (TRACE_LEVEL < TRACE_INFO) +#define IMSG(...) (void)0 +#else +#define IMSG(...) trace_printf_helper(TRACE_INFO, true, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_DEBUG level */ +#if (TRACE_LEVEL < TRACE_DEBUG) +#define DMSG(...) (void)0 +#else +#define DMSG(...) trace_printf_helper(TRACE_DEBUG, true, __VA_ARGS__) +#endif + +/* Formatted trace tagged with TRACE_FLOW level */ +#if (TRACE_LEVEL < TRACE_FLOW) +#define FMSG(...) (void)0 +#else +#define FMSG(...) trace_printf_helper(TRACE_FLOW, true, __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=[%x]", r); \ + return r; \ + } while (0) + +void dhex_dump(const char *function, int line, int level, + const void *buf, int len); +#if (TRACE_LEVEL < TRACE_DEBUG) +#define DHEXDUMP(buf, len) (void)0 +#else +#define DHEXDUMP(buf, len) dhex_dump(__func__, __LINE__, TRACE_DEBUG, \ + buf, len) +#endif + + +/* Trace api without trace formatting */ + +#define trace_printf_helper_raw(level, level_ok, ...) \ + trace_printf(NULL, 0, (level), (level_ok), __VA_ARGS__) + +/* No formatted trace tagged with level independent */ +#if (TRACE_LEVEL <= 0) +#define MSG_RAW(...) (void)0 +#else +#define MSG_RAW(...) trace_printf_helper_raw(0, false, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_ERROR level */ +#if (TRACE_LEVEL < TRACE_ERROR) +#define EMSG_RAW(...) (void)0 +#else +#define EMSG_RAW(...) trace_printf_helper_raw(TRACE_ERROR, true, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_INFO level */ +#if (TRACE_LEVEL < TRACE_INFO) +#define IMSG_RAW(...) (void)0 +#else +#define IMSG_RAW(...) trace_printf_helper_raw(TRACE_INFO, true, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_DEBUG level */ +#if (TRACE_LEVEL < TRACE_DEBUG) +#define DMSG_RAW(...) (void)0 +#else +#define DMSG_RAW(...) trace_printf_helper_raw(TRACE_DEBUG, true, __VA_ARGS__) +#endif + +/* No formatted trace tagged with TRACE_FLOW level */ +#if (TRACE_LEVEL < TRACE_FLOW) +#define FMSG_RAW(...) (void)0 +#else +#define FMSG_RAW(...) trace_printf_helper_raw(TRACE_FLOW, true, __VA_ARGS__) +#endif + +#if (TRACE_LEVEL <= 0) +#define SMSG(...) (void)0 +#else +/* + * Synchronised flushed trace, an Always message straight to HW trace IP. + * Current only supported inside OP-TEE kernel, will be just like an EMSG() + * in another context. + */ +#define SMSG(...) \ + trace_printf(__func__, __LINE__, TRACE_ERROR, true, __VA_ARGS__) + +#endif /* TRACE_LEVEL */ +#endif /* TRACE_H */ diff --git a/optee/optee_os/lib/libutils/ext/include/trace_levels.h b/optee/optee_os/lib/libutils/ext/include/trace_levels.h new file mode 100644 index 0000000..7fd5181 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/trace_levels.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef TRACE_LEVELS_H +#define TRACE_LEVELS_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 0 +#define TRACE_ERROR 1 +#define TRACE_INFO 2 +#define TRACE_DEBUG 3 +#define TRACE_FLOW 4 +#define TRACE_MAX TRACE_FLOW + +/* Trace level of the casual printf */ +#define TRACE_PRINTF_LEVEL TRACE_ERROR + +#endif /*TRACE_LEVELS_H*/ diff --git a/optee/optee_os/lib/libutils/ext/include/types_ext.h b/optee/optee_os/lib/libutils/ext/include/types_ext.h new file mode 100644 index 0000000..0bbade5 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/types_ext.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __TYPES_EXT_H +#define __TYPES_EXT_H + +#include +#include +#include +#include +#include + +typedef uintptr_t uaddr_t; +#define PRIxUA PRIxPTR + +typedef uintptr_t vaddr_t; +#define PRIxVA PRIxPTR + +#if defined(__ILP32__) && defined(CFG_CORE_LARGE_PHYS_ADDR) +typedef uint64_t paddr_t; +typedef uint64_t paddr_size_t; +#define PRIxPA PRIx64 +#define PRIxPASZ PRIx64 +#define __SIZEOF_PADDR__ 8 +#else +typedef uintptr_t paddr_t; +typedef uintptr_t paddr_size_t; +#define PRIxPA PRIxPTR +#define PRIxPASZ PRIxPTR +#define __SIZEOF_PADDR__ __SIZEOF_POINTER__ +#endif + +#define PRIxVA_WIDTH ((int)(sizeof(vaddr_t) * 2)) +#define PRIxPA_WIDTH ((int)(sizeof(paddr_t) * 2)) + +#endif /* __TYPES_EXT_H */ diff --git a/optee/optee_os/lib/libutils/ext/include/util.h b/optee/optee_os/lib/libutils/ext/include/util.h new file mode 100644 index 0000000..64236c8 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/include/util.h @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef UTIL_H +#define UTIL_H + +#include +#include + +#define SIZE_4K UINTPTR_C(0x1000) +#define SIZE_1M UINTPTR_C(0x100000) +#define SIZE_2M UINTPTR_C(0x200000) +#define SIZE_4M UINTPTR_C(0x400000) +#define SIZE_8M UINTPTR_C(0x800000) +#define SIZE_2G UINTPTR_C(0x80000000) + +#ifndef MAX +#ifndef __ASSEMBLER__ +#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; })) +#else +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#endif + +/* + * In some particular conditions MAX and MIN macros fail to + * build from C source file implmentation. In such case one + * need to use MAX_UNSAFE/MIN_UNSAFE instead. + */ +#define MAX_UNSAFE(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN_UNSAFE(a, b) (((a) < (b)) ? (a) : (b)) + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#ifndef __ASSEMBLER__ +/* Round up the even multiple of size, size has to be a multiple of 2 */ +#define ROUNDUP(v, size) (((v) + ((__typeof__(v))(size) - 1)) & \ + ~((__typeof__(v))(size) - 1)) + +#define ROUNDUP_OVERFLOW(v, size, res) (__extension__({ \ + typeof(*(res)) __roundup_tmp = 0; \ + typeof(v) __roundup_mask = (typeof(v))(size) - 1; \ + \ + ADD_OVERFLOW((v), __roundup_mask, &__roundup_tmp) ? 1 : \ + ((void)(*(res) = __roundup_tmp & ~__roundup_mask), 0); \ +})) + +/* + * Rounds up to the nearest multiple of y and then divides by y. Safe + * against overflow, y has to be a multiple of 2. + * + * This macro is intended to be used to convert from "number of bytes" to + * "number of pages" or similar units. Example: + * num_pages = ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE); + */ +#define ROUNDUP_DIV(x, y) (__extension__({ \ + typeof(x) __roundup_x = (x); \ + typeof(y) __roundup_mask = (typeof(x))(y) - 1; \ + \ + (__roundup_x / (y)) + (__roundup_x & __roundup_mask ? 1 : 0); \ +})) + +/* Round down the even multiple of size, size has to be a multiple of 2 */ +#define ROUNDDOWN(v, size) ((v) & ~((__typeof__(v))(size) - 1)) + +/* + * Round up the result of x / y to the nearest upper integer if result is not + * already an integer. + */ +#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) + +/* Unsigned integer division with nearest rounding variant */ +#define UDIV_ROUND_NEAREST(x, y) \ + (__extension__ ({ __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (_x + (_y / 2)) / _y; })) +#else +#define ROUNDUP(x, y) ((((x) + (y) - 1) / (y)) * (y)) +#define ROUNDDOWN(x, y) (((x) / (y)) * (y)) +#define UDIV_ROUND_NEAREST(x, y) (((x) + ((y) / 2)) / (y)) +#endif + +/* x has to be of an unsigned type */ +#define IS_POWER_OF_TWO(x) (((x) != 0) && (((x) & (~(x) + 1)) == (x))) + +#define IS_ALIGNED(x, a) (((x) & ((a) - 1)) == 0) +#define IS_ALIGNED_WITH_TYPE(x, type) \ + (__extension__({ \ + type __is_aligned_y; \ + IS_ALIGNED((uintptr_t)(x), __alignof__(__is_aligned_y)); \ + })) + +#define TO_STR(x) _TO_STR(x) +#define _TO_STR(x) #x + +#define CONCAT(x, y) _CONCAT(x, y) +#define _CONCAT(x, y) x##y + +#define container_of(ptr, type, member) \ + (__extension__({ \ + const typeof(((type *)0)->member) *__ptr = (ptr); \ + (type *)((unsigned long)(__ptr) - offsetof(type, member)); \ + })) + +#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) + +#ifdef __ASSEMBLER__ +#define BIT32(nr) (1 << (nr)) +#define BIT64(nr) (1 << (nr)) +#define SHIFT_U32(v, shift) ((v) << (shift)) +#define SHIFT_U64(v, shift) ((v) << (shift)) +#else +#define BIT32(nr) (UINT32_C(1) << (nr)) +#define BIT64(nr) (UINT64_C(1) << (nr)) +#define SHIFT_U32(v, shift) ((uint32_t)(v) << (shift)) +#define SHIFT_U64(v, shift) ((uint64_t)(v) << (shift)) +#endif +#define BIT(nr) BIT32(nr) + +/* + * Create a contiguous bitmask starting at bit position @l and ending at + * position @h. For example + * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +#define GENMASK_32(h, l) \ + (((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h)))) + +#define GENMASK_64(h, l) \ + (((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h)))) + +/* + * Checking overflow for addition, subtraction and multiplication. Result + * of operation is stored in res which is a pointer to some kind of + * integer. + * + * The macros return true if an overflow occurred and *res is undefined. + */ +#define ADD_OVERFLOW(a, b, res) __compiler_add_overflow((a), (b), (res)) +#define SUB_OVERFLOW(a, b, res) __compiler_sub_overflow((a), (b), (res)) +#define MUL_OVERFLOW(a, b, res) __compiler_mul_overflow((a), (b), (res)) + +/* Return a signed +1, 0 or -1 value based on data comparison */ +#define CMP_TRILEAN(a, b) \ + (__extension__({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + \ + _a > _b ? 1 : _a < _b ? -1 : 0; \ + })) + +#ifndef __ASSEMBLER__ +static inline uint64_t reg_pair_to_64(uint32_t reg0, uint32_t reg1) +{ + return (uint64_t)reg0 << 32 | reg1; +} + +static inline void reg_pair_from_64(uint64_t val, uint32_t *reg0, + uint32_t *reg1) +{ + *reg0 = val >> 32; + *reg1 = val; +} + +/* Get and set bit fields */ +static inline uint32_t get_field_u32(uint32_t reg, uint32_t mask) +{ + return (reg & mask) / (mask & ~(mask - 1)); +} + +static inline uint32_t set_field_u32(uint32_t reg, uint32_t mask, uint32_t val) +{ + return (reg & ~mask) | (val * (mask & ~(mask - 1))); +} + +static inline uint64_t get_field_u64(uint64_t reg, uint64_t mask) +{ + return (reg & mask) / (mask & ~(mask - 1)); +} + +static inline uint64_t set_field_u64(uint64_t reg, uint64_t mask, uint64_t val) +{ + return (reg & ~mask) | (val * (mask & ~(mask - 1))); +} +#endif + +#endif /*UTIL_H*/ diff --git a/optee/optee_os/lib/libutils/ext/mempool.c b/optee/optee_os/lib/libutils/ext/mempool.c new file mode 100644 index 0000000..e551305 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/mempool.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2018-2019, Linaro Limited + */ + + +#include +#include +#include +#include +#include +#include + +#if defined(__KERNEL__) +#include +#include +#endif + +/* + * Allocation of temporary memory buffers which are used in a stack like + * fashion. One exmaple is when a Big Number is needed for a temporary + * variable in a Big Number computation: Big Number operations (add,...), + * crypto algorithms (rsa, ecc,,...). + * + * The allocation algorithm takes memory buffers from a pool, + * characterized by (cf. struct mempool): + * - the total size (in bytes) of the pool + * - the offset of the last item allocated in the pool (struct + * mempool_item). This offset is -1 is nothing is allocated yet. + * + * Each item consists of (struct mempool_item) + * - the size of the item + * - the offsets, in the pool, of the previous and next items + * + * The allocation allocates an item for a given size. + * The allocation is performed in the pool after the last + * allocated items. This means: + * - the heap is never used. + * - there is no assumption on the size of the allocated memory buffers. Only + * the size of the pool will limit the allocation. + * - a constant time allocation and free as there is no list scan + * - but a potentially fragmented memory as the allocation does not take into + * account "holes" in the pool (allocation is performed after the last + * allocated variable). Indeed, this interface is supposed to be used + * with stack like allocations to avoid this issue. This means that + * allocated items: + * - should have a short life cycle + * - if an item A is allocated before another item B, then A should be + * released after B. + * So the potential fragmentation is mitigated. + */ + + +struct mempool { + size_t size; /* size of the memory pool, in bytes */ + vaddr_t data; + struct malloc_ctx *mctx; +#ifdef CFG_MEMPOOL_REPORT_LAST_OFFSET + size_t max_allocated; +#endif +#if defined(__KERNEL__) + void (*release_mem)(void *ptr, size_t size); + struct recursive_mutex mu; +#endif +}; + +#if defined(__KERNEL__) +struct mempool *mempool_default; +#endif + +static void init_mpool(struct mempool *pool) +{ + size_t sz = pool->size - raw_malloc_get_ctx_size(); + vaddr_t v = ROUNDDOWN(pool->data + sz, sizeof(long) * 2); + + /* + * v is the placed as close to the end of the data pool as possible + * where the struct malloc_ctx can be placed. This location is selected + * as an optimization for the pager case to get better data + * locality since raw_malloc() starts to allocate from the end of + * the supplied data pool. + */ + assert(v > pool->data); + pool->mctx = (struct malloc_ctx *)v; + raw_malloc_init_ctx(pool->mctx); + raw_malloc_add_pool(pool->mctx, (void *)pool->data, v - pool->data); +} + +static void get_pool(struct mempool *pool __maybe_unused) +{ +#if defined(__KERNEL__) + mutex_lock_recursive(&pool->mu); + if (!pool->mctx) + init_mpool(pool); + +#endif +} + +static void put_pool(struct mempool *pool __maybe_unused) +{ +#if defined(__KERNEL__) + if (mutex_get_recursive_lock_depth(&pool->mu) == 1) { + /* + * As the refcount is about to become 0 there should be no items + * left + */ + if (pool->release_mem) { + pool->mctx = NULL; + pool->release_mem((void *)pool->data, pool->size); + } + } + mutex_unlock_recursive(&pool->mu); +#endif +} + +struct mempool * +mempool_alloc_pool(void *data, size_t size, + void (*release_mem)(void *ptr, size_t size) __maybe_unused) +{ + struct mempool *pool = calloc(1, sizeof(*pool)); + + COMPILE_TIME_ASSERT(MEMPOOL_ALIGN >= __alignof__(struct mempool_item)); + assert(!((vaddr_t)data & (MEMPOOL_ALIGN - 1))); + + if (pool) { + pool->size = size; + pool->data = (vaddr_t)data; +#if defined(__KERNEL__) + pool->release_mem = release_mem; + mutex_init_recursive(&pool->mu); +#else + init_mpool(pool); +#endif + } + + return pool; +} + +void *mempool_alloc(struct mempool *pool, size_t size) +{ + void *p = NULL; + + get_pool(pool); + + p = raw_malloc(0, 0, size, pool->mctx); + if (p) { +#ifdef CFG_MEMPOOL_REPORT_LAST_OFFSET + struct malloc_stats stats = { }; + + raw_malloc_get_stats(pool->mctx, &stats); + if (stats.max_allocated > pool->max_allocated) { + pool->max_allocated = stats.max_allocated; + DMSG("Max memory usage increased to %zu", + pool->max_allocated); + } +#endif + return p; + } + + EMSG("Failed to allocate %zu bytes, please tune the pool size", size); + put_pool(pool); + return NULL; +} + +void *mempool_calloc(struct mempool *pool, size_t nmemb, size_t size) +{ + size_t sz; + void *p; + + if (MUL_OVERFLOW(nmemb, size, &sz)) + return NULL; + + p = mempool_alloc(pool, sz); + if (p) + memset(p, 0, sz); + + return p; +} + +void mempool_free(struct mempool *pool, void *ptr) +{ + raw_free(ptr, pool->mctx, false /*!wipe*/); + put_pool(pool); +} diff --git a/optee/optee_os/lib/libutils/ext/memzero_explicit.c b/optee/optee_os/lib/libutils/ext/memzero_explicit.c new file mode 100644 index 0000000..36e8e66 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/memzero_explicit.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019 Linaro Limited + */ + +#include +#include + +/* + * This method prevents dead store elimination, which could happen in case + * link-time optimization (LTO) is used. + * See "Dead Store Elimination (Still) Considered Harmful" [1] section 3.3.3. + * + * [1] + * http://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang.pdf + */ +static volatile void * (*memset_func)(void *, int, size_t) = + (volatile void * (*)(void *, int, size_t))&memset; + +void memzero_explicit(void *s, size_t count) +{ + memset_func(s, 0, count); +} diff --git a/optee/optee_os/lib/libutils/ext/nex_strdup.c b/optee/optee_os/lib/libutils/ext/nex_strdup.c new file mode 100644 index 0000000..0710327 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/nex_strdup.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018 EPAM Systems + */ +#include +#include +#include + +char *nex_strdup(const char *s) +{ + size_t l = strlen(s) + 1; + char *p = nex_malloc(l); + + if (p) + memcpy(p, s, l); + return p; +} diff --git a/optee/optee_os/lib/libutils/ext/pthread_stubs.c b/optee/optee_os/lib/libutils/ext/pthread_stubs.c new file mode 100644 index 0000000..4f5555d --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/pthread_stubs.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2023, Linaro Limited + */ + +#include + +#define pthread_mutex_t void + +int pthread_mutex_lock(pthread_mutex_t *mutex __unused); +int pthread_mutex_unlock(pthread_mutex_t *mutex __unused); + +int __weak pthread_mutex_lock(pthread_mutex_t *mutex __unused) +{ + return 0; +} + +int __weak pthread_mutex_unlock(pthread_mutex_t *mutex __unused) +{ + return 0; +} diff --git a/optee/optee_os/lib/libutils/ext/snprintk.c b/optee/optee_os/lib/libutils/ext/snprintk.c new file mode 100644 index 0000000..c8fa531 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/snprintk.c @@ -0,0 +1,622 @@ +// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) +/* + * Imported from NetBSD 5.1 with modifications to make it a vsnprintf(3) + * function + */ + +/* $NetBSD: subr_prf.c,v 1.156 2014/08/15 11:05:35 apb 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 + * + * Copyright (c) 2015 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 +#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 snprintk] */ +#define TODDB 0x0010 /* to ddb console */ +#define NOLOCK 0x1000 /* don't acquire a tty lock */ + +/* max size buffer kprintf needs to print a UUID */ +#define KPRINTF_BUFSIZE 37 + +/* + * 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, bool ext); + +static const char hexdigits[] = "0123456789abcdef"; +static const char HEXDIGITS[] = "0123456789ABCDEF"; + +/* + * snprintk: print a message to a buffer. Same as snprintf but supports + * format extensions. + */ +int +snprintk(char *bf, size_t size, const char *fmt, ...) +{ + int retval; + va_list ap; + + va_start(ap, fmt); + retval = vsnprintk(bf, size, fmt, ap); + va_end(ap); + + return retval; +} + +/* + * vsnprintk: print a message to a buffer [already have va_list] + * Same as vsnprintf but supports format extensions. + */ +int +vsnprintk(char *bf, size_t size, const char *fmt, va_list ap) +{ + return __vsnprintf(bf, size, fmt, ap, true); +} + +int +__vsnprintf(char *bf, size_t size, const char *fmt, va_list ap, + bool ext) + +{ + int retval; + char *p; + + p = bf + size; + retval = kprintf(fmt, TOBUFONLY, &p, bf, ap, ext); + if (bf && size > 0) { + /* nul terminate */ + if (size <= (size_t)retval) + bf[size - 1] = '\0'; + else + bf[retval] = '\0'; + } + return retval; +} + +int __vsprintf(char *bf, const char *fmt, va_list ap) +{ + return kprintf(fmt, TOBUFONLY, NULL, bf, ap, false); +} + +/* + * 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 QUADINT 0x020 /* quad 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&QUADINT ? va_arg(ap, int64_t) : \ + 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&QUADINT ? va_arg(ap, uint64_t) : \ + flags&LONGINT ? va_arg(ap, unsigned long) : \ + flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \ + (unsigned long)va_arg(ap, unsigned int)) + +#define KPRINTF_PUTCHAR(C) { \ + if (oflags == TOBUFONLY) { \ + if (sbuf && ((vp == NULL) || (sbuf < tailp))) \ + *sbuf++ = (C); \ + } else { \ + putchar((C), oflags, vp); \ + } \ +} + +static int uuid2str(char *dst, size_t size, void *ptr) +{ + struct { + uint32_t lo; + uint16_t mid; + uint16_t hi_ver; + uint8_t seq_n[8]; + } *uuid = ptr; + + return snprintk(dst, size, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid->lo, uuid->mid, uuid->hi_ver, + uuid->seq_n[0], uuid->seq_n[1], + uuid->seq_n[2], uuid->seq_n[3], + uuid->seq_n[4], uuid->seq_n[5], + uuid->seq_n[6], uuid->seq_n[7]); +} + +/* + * 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, + bool ext) +{ + 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) */ + + uint64_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], possibly %pUl */ + char *tailp; /* tail pointer for snprintk */ + + if (oflags == TOBUFONLY && (vp != NULL)) + tailp = *(char **)vp; + else + tailp = NULL; + + 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 (;;) { + for (; *fmt != '%' && *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': + if (*fmt == 'l') { + fmt++; + flags |= QUADINT; + } else { + flags |= LONGINT; + } + goto rflag; + case 'q': + flags |= QUADINT; + 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 ((int64_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 & QUADINT) + *va_arg(ap, int64_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': + if (ext && *fmt == 'U' && *(fmt+1) == 'l') { + /* + * Non-standard format available in [v]snprintk + * only + */ + fmt += 2; + size = uuid2str(bf, sizeof(bf), + va_arg(ap, void *)); + cp = bf; + sign = '\0'; + break; + } + /* + * ``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 */ + for (; size--; cp++) + 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; + return ret; +} diff --git a/optee/optee_os/lib/libutils/ext/strlcat.c b/optee/optee_os/lib/libutils/ext/strlcat.c new file mode 100644 index 0000000..3bb09df --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/strlcat.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* 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/optee/optee_os/lib/libutils/ext/strlcpy.c b/optee/optee_os/lib/libutils/ext/strlcpy.c new file mode 100644 index 0000000..5f3ef06 --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/strlcpy.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* 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/optee/optee_os/lib/libutils/ext/sub.mk b/optee/optee_os/lib/libutils/ext/sub.mk new file mode 100644 index 0000000..3ab5afd --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/sub.mk @@ -0,0 +1,18 @@ +global-incdirs-y += include + +srcs-y += snprintk.c +srcs-y += strlcat.c +srcs-y += strlcpy.c +srcs-y += trace.c +srcs-y += mempool.c +srcs-y += nex_strdup.c +srcs-y += consttime_memcmp.c +srcs-y += memzero_explicit.c +srcs-y += fault_mitigation.c + +ifneq (,$(filter ta_%,$(sm))) +srcs-y += pthread_stubs.c +endif + +subdirs-y += arch/$(ARCH) +subdirs-y += ftrace diff --git a/optee/optee_os/lib/libutils/ext/trace.c b/optee/optee_os/lib/libutils/ext/trace.c new file mode 100644 index 0000000..33c099d --- /dev/null +++ b/optee/optee_os/lib/libutils/ext/trace.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#if defined(__KERNEL__) +#include +#endif + +#include +#include +#include +#include +#include +#include + +#if (TRACE_LEVEL < TRACE_MIN) || (TRACE_LEVEL > TRACE_MAX) +#error "Invalid value of TRACE_LEVEL" +#endif + +#if (TRACE_LEVEL >= TRACE_ERROR) + +void trace_set_level(int level) +{ + if (((int)level >= TRACE_MIN) && (level <= TRACE_MAX)) + trace_level = level; + else + trace_level = TRACE_MAX; +} + +int trace_get_level(void) +{ + return trace_level; +} + +static char trace_level_to_string(int level, bool level_ok) +{ + /* + * U = Unused + * E = Error + * I = Information + * D = Debug + * F = Flow + */ + static const char lvl_strs[] = { 'U', 'E', 'I', 'D', 'F' }; + int l = 0; + + if (!level_ok) + return 'M'; + + if ((level >= TRACE_MIN) && (level <= TRACE_MAX)) + l = level; + + return lvl_strs[l]; +} + +static int print_thread_id(char *buf, size_t bs) +{ +#if CFG_NUM_THREADS > 100 + int num_thread_digits = 3; +#elif CFG_NUM_THREADS > 10 + int num_thread_digits = 2; +#else + int num_thread_digits = 1; +#endif + int thread_id = trace_ext_get_thread_id(); + + if (thread_id >= 0) + return snprintk(buf, bs, "%0*d ", num_thread_digits, thread_id); + else + return snprintk(buf, bs, "%*s ", num_thread_digits, ""); +} + +#if defined(__KERNEL__) +static int print_core_id(char *buf, size_t bs) +{ +#if CFG_TEE_CORE_NB_CORE > 100 + const int num_digits = 3; + const char qm[] = "???"; +#elif CFG_TEE_CORE_NB_CORE > 10 + const int num_digits = 2; + const char qm[] = "??"; +#else + const int num_digits = 1; + const char qm[] = "?"; +#endif + int core_id = trace_ext_get_core_id(); + + if (core_id >= 0) + return snprintk(buf, bs, "%0*u ", num_digits, core_id); + else + return snprintk(buf, bs, "%s ", qm); +} +#else /* defined(__KERNEL__) */ +static int print_core_id(char *buf __unused, size_t bs __unused) +{ + return 0; +} +#endif + +/* Format trace of user ta. Inline with kernel ta */ +void trace_printf(const char *function, int line, int level, bool level_ok, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + trace_vprintf(function, line, level, level_ok, fmt, ap); + va_end(ap); +} +void trace_vprintf(const char *function, int line, int level, bool level_ok, + const char *fmt, va_list ap) +{ + char buf[MAX_PRINT_SIZE]; + size_t boffs = 0; + int res; + + if (level_ok && level > trace_level) + return; + + /* Print the type of message */ + res = snprintk(buf, sizeof(buf), "%c/", + trace_level_to_string(level, level_ok)); + if (res < 0) + return; + boffs += res; + + /* Print the location, i.e., TEE core or TA */ + res = snprintk(buf + boffs, sizeof(buf) - boffs, "%s:", + trace_ext_prefix); + if (res < 0) + return; + boffs += res; + + if (level_ok && (BIT(level) & CFG_MSG_LONG_PREFIX_MASK)) { + /* Print the core ID if in atomic context */ + res = print_core_id(buf + boffs, sizeof(buf) - boffs); + if (res < 0) + return; + boffs += res; + + /* Print the Thread ID */ + res = print_thread_id(buf + boffs, sizeof(buf) - boffs); + if (res < 0) + return; + boffs += res; + + if (function) { + res = snprintk(buf + boffs, sizeof(buf) - boffs, "%s:%d ", + function, line); + if (res < 0) + return; + boffs += res; + } + } else { + /* Add space after location info */ + if (boffs >= sizeof(buf) - 1) + return; + buf[boffs++] = ' '; + buf[boffs] = 0; + } + + res = vsnprintk(buf + boffs, sizeof(buf) - boffs, fmt, ap); + if (res > 0) + boffs += res; + + if (boffs >= (sizeof(buf) - 1)) + boffs = sizeof(buf) - 2; + + buf[boffs] = '\n'; + while (boffs && buf[boffs] == '\n') + boffs--; + boffs++; + buf[boffs + 1] = '\0'; + + trace_ext_puts(buf); +} + +#else + +/* + * In case we have a zero or negative trace level when compiling optee_os, we + * have to add stubs to trace functions in case they are used with TA having a + * non-zero trace level + */ + +void trace_set_level(int level __unused) +{ +} + +int trace_get_level(void) +{ + return 0; +} + +void trace_printf(const char *function __unused, int line __unused, + int level __unused, bool level_ok __unused, + const char *fmt __unused, ...) +{ +} + +#endif + +#if (TRACE_LEVEL >= TRACE_DEBUG) +struct strbuf { + char buf[MAX_PRINT_SIZE]; + char *ptr; +}; + +static int __printf(2, 3) append(struct strbuf *sbuf, const char *fmt, ...) +{ + int left; + int len; + va_list ap; + + if (sbuf->ptr == NULL) + sbuf->ptr = sbuf->buf; + left = sizeof(sbuf->buf) - (sbuf->ptr - sbuf->buf); + va_start(ap, fmt); + len = vsnprintk(sbuf->ptr, left, fmt, ap); + va_end(ap); + if (len < 0) { + /* Format error */ + return 0; + } + if (len >= left) { + /* Output was truncated */ + return 0; + } + sbuf->ptr += MIN(left, len); + return 1; +} + +void dhex_dump(const char *function, int line, int level, + const void *buf, int len) +{ + int i; + int ok; + struct strbuf sbuf; + char *in = (char *)buf; + + if (level <= trace_level) { + sbuf.ptr = NULL; + for (i = 0; i < len; i++) { + if ((i % 16) == 0) { + ok = append(&sbuf, "%0*" PRIxVA " ", + PRIxVA_WIDTH, (vaddr_t)(in + i)); + if (!ok) + goto err; + } + ok = append(&sbuf, "%02x ", in[i]); + if (!ok) + goto err; + if ((i % 16) == 7) { + ok = append(&sbuf, " "); + if (!ok) + goto err; + } else if ((i % 16) == 15) { + trace_printf(function, line, level, true, "%s", + sbuf.buf); + sbuf.ptr = NULL; + } + } + if (sbuf.ptr) { + /* Buffer is not empty: flush it */ + trace_printf(function, line, level, true, "%s", + sbuf.buf); + + } + } + return; +err: + DMSG("Hex dump error"); +} +#else + +/* + * In case we have trace level less than debug when compiling optee_os, we have + * to add stubs to trace functions in case they are used with TA having a + * a higher trace level + */ + +void dhex_dump(const char *function __unused, int line __unused, + int level __unused, + const void *buf __unused, int len __unused) +{ +} + +#endif diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c new file mode 100644 index 0000000..7b429b1 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* + * 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); + +/* 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); + +/* + * __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(unsigned n, unsigned p, struct qr *qr) +{ + unsigned i = 1, q = 0; + if (p == 0) { + qr->r = 0xFFFFFFFF; /* division by 0 */ + return; + } + + while ((p >> 31) == 0) { + i = i << 1; /* count the max division steps */ + p = p << 1; /* increase p until it has maximum size*/ + } + + while (i > 0) { + q = q << 1; /* write bit in q at index (size-1) */ + if (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) +{ + + 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_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_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/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S new file mode 100644 index 0000000..37ae9ec --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include + + .section .note.GNU-stack,"",%progbits + +/* + * signed ret_idivmod_values(signed quot, signed rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +FUNC ret_idivmod_values , : + bx lr +END_FUNC ret_idivmod_values + +/* + * unsigned ret_uidivmod_values(unsigned quot, unsigned rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +FUNC ret_uidivmod_values , : + bx lr +END_FUNC ret_uidivmod_values diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c new file mode 100644 index 0000000..043d296 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, STMicroelectronics International N.V. + */ + +/* struct lqr - stores qutient/remainder to handle divmod EABI interfaces. */ +struct lqr { + unsigned long long q; /* computed quotient */ + unsigned long long r; /* computed remainder */ + unsigned q_n; /* specficies if quotient shall be negative */ + unsigned r_n; /* specficies if remainder shall be negative */ +}; + +static void ul_div_qr(unsigned long long numerator, + unsigned long long denominator, struct lqr *qr); + + +static void division_lqr(unsigned long long n, unsigned long long p, + struct lqr *qr) +{ + unsigned long long i = 1, q = 0; + if (p == 0) { + qr->r = 0xFFFFFFFFFFFFFFFFULL; /* division by 0 */ + return; + } + + while ((p >> 63) == 0) { + i = i << 1; /* count the max division steps */ + p = p << 1; /* increase p until it has maximum size*/ + } + + while (i > 0) { + q = q << 1; /* write bit in q at index (size-1) */ + if (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 ul_div_qr(unsigned long long numerator, + unsigned long long denominator, struct lqr *qr) +{ + + division_lqr(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; +} + +struct asm_ulqr { + unsigned long long v0; + unsigned long long v1; +}; + +/* called from assembly function __aeabi_uldivmod */ +void __ul_divmod(struct asm_ulqr *asm_ulqr); +void __ul_divmod(struct asm_ulqr *asm_ulqr) +{ + unsigned long long numerator = asm_ulqr->v0; + unsigned long long denominator = asm_ulqr->v1; + struct lqr qr = { .q_n = 0, .r_n = 0 }; + + ul_div_qr(numerator, denominator, &qr); + + asm_ulqr->v0 = qr.q; + asm_ulqr->v1 = qr.r; +} + +struct asm_lqr { + long long v0; + long long v1; +}; + +/* called from assembly function __aeabi_ldivmod */ +void __l_divmod(struct asm_lqr *asm_lqr); +void __l_divmod(struct asm_lqr *asm_lqr) +{ + long long numerator = asm_lqr->v0; + long long denominator = asm_lqr->v1; + struct lqr 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; + + ul_div_qr(numerator, denominator, &qr); + + asm_lqr->v0 = qr.q; + asm_lqr->v1 = qr.r; +} diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S new file mode 100644 index 0000000..5c3353e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include + + .section .note.GNU-stack,"",%progbits + +/* + * __value_in_regs lldiv_t __aeabi_ldivmod( long long n, long long d) + */ +FUNC __aeabi_ldivmod , : + push {ip, lr} +UNWIND( .save {ip, lr}) + push {r0-r3} +UNWIND( .save {r0-r3}) + mov r0, sp + bl __l_divmod + pop {r0-r3} + pop {ip, pc} +END_FUNC __aeabi_ldivmod + +/* + * __value_in_regs ulldiv_t __aeabi_uldivmod( + * unsigned long long n, unsigned long long d) + */ +FUNC __aeabi_uldivmod , : + push {ip, lr} +UNWIND( .save {ip, lr}) + push {r0-r3} +UNWIND( .save {r0-r3}) + mov r0, sp + bl __ul_divmod + pop {r0-r3} + pop {ip, pc} +END_FUNC __aeabi_uldivmod diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c new file mode 100644 index 0000000..cf68962 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +union dword { + unsigned long long dw; + unsigned long w[2]; +}; + +long long __aeabi_llsl(long long a, int shift); +long long __aeabi_llsl(long long a, int shift) +{ + union dword dword = { .dw = a }; + unsigned long hi = dword.w[1]; + unsigned long lo = dword.w[0]; + + if (shift >= 32) { + hi = lo << (shift - 32); + lo = 0; + } else if (shift > 0) { + hi = (hi << shift) | (lo >> (32 - shift)); + lo = lo << shift; + } + + dword.w[1] = hi; + dword.w[0] = lo; + return dword.dw; +} + +long long __aeabi_llsr(long long a, int shift); +long long __aeabi_llsr(long long a, int shift) +{ + union dword dword = { .dw = a }; + unsigned long hi = dword.w[1]; + unsigned long lo = dword.w[0]; + + if (shift >= 32) { + lo = hi >> (shift - 32); + hi = 0; + } else if (shift > 0) { + lo = (lo >> shift) | (hi << (32 - shift)); + hi = hi >> shift; + } + + dword.w[1] = hi; + dword.w[0] = lo; + return dword.dw; +} diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c new file mode 100644 index 0000000..ef92ab8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include "platform.h" +#include + +/* + * On ARM32 EABI defines both a soft-float ABI and a hard-float ABI, + * hard-float is basically a super set of soft-float. Hard-float requires + * all the support routines provided for soft-float, but the compiler may + * choose to optimize to not use some of them. + * + * The AEABI functions uses soft-float calling convention even if the + * functions are compiled for hard-float. So where float and double would + * have been expected we use aeabi_float_t and aeabi_double_t respectively + * instead. + */ +typedef unsigned aeabi_float_t; +typedef unsigned long long aeabi_double_t; + +/* + * Helpers to convert between float32 and aeabi_float_t, and float64 and + * aeabi_double_t used by the AEABI functions below. + */ +static aeabi_float_t f32_to_f(float32_t val) +{ + union { + float32_t from; + aeabi_float_t to; + } res = { .from = val }; + + return res.to; +} + +static float32_t f32_from_f(aeabi_float_t val) +{ + union { + aeabi_float_t from; + float32_t to; + } res = { .from = val }; + + return res.to; +} + +static aeabi_double_t f64_to_d(float64_t val) +{ + union { + float64_t from; + aeabi_double_t to; + } res = { .from = val }; + + return res.to; +} + +static float64_t f64_from_d(aeabi_double_t val) +{ + union { + aeabi_double_t from; + float64_t to; + } res = { .from = val }; + + return res.to; +} + +/* + * From ARM Run-time ABI for ARM Architecture + * ARM IHI 0043D, current through ABI release 2.09 + * + * 4.1.2 The floating-point helper functions + */ + +/* + * Table 2, Standard aeabi_double_t precision floating-point arithmetic helper + * functions + */ + +aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_add(f64_from_d(a), f64_from_d(b))); +} + +aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_div(f64_from_d(a), f64_from_d(b))); +} + +aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_mul(f64_from_d(a), f64_from_d(b))); +} + + +aeabi_double_t __aeabi_drsub(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_sub(f64_from_d(b), f64_from_d(a))); +} + +aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b) +{ + return f64_to_d(f64_sub(f64_from_d(a), f64_from_d(b))); +} + +/* + * Table 3, double precision floating-point comparison helper functions + */ + +int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b) +{ + return f64_eq(f64_from_d(a), f64_from_d(b)); +} + +int __aeabi_dcmplt(aeabi_double_t a, aeabi_double_t b) +{ + return f64_lt(f64_from_d(a), f64_from_d(b)); +} + +int __aeabi_dcmple(aeabi_double_t a, aeabi_double_t b) +{ + return f64_le(f64_from_d(a), f64_from_d(b)); +} + +int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b) +{ + return f64_le(f64_from_d(b), f64_from_d(a)); +} + +int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b) +{ + return f64_lt(f64_from_d(b), f64_from_d(a)); +} + +/* + * Table 4, Standard single precision floating-point arithmetic helper + * functions + */ + +aeabi_float_t __aeabi_fadd(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_add(f32_from_f(a), f32_from_f(b))); +} + +aeabi_float_t __aeabi_fdiv(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_div(f32_from_f(a), f32_from_f(b))); +} + +aeabi_float_t __aeabi_fmul(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_mul(f32_from_f(a), f32_from_f(b))); +} + +aeabi_float_t __aeabi_frsub(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_sub(f32_from_f(b), f32_from_f(a))); +} + +aeabi_float_t __aeabi_fsub(aeabi_float_t a, aeabi_float_t b) +{ + return f32_to_f(f32_sub(f32_from_f(a), f32_from_f(b))); +} + +/* + * Table 5, Standard single precision floating-point comparison helper + * functions + */ + +int __aeabi_fcmpeq(aeabi_float_t a, aeabi_float_t b) +{ + return f32_eq(f32_from_f(a), f32_from_f(b)); +} + +int __aeabi_fcmplt(aeabi_float_t a, aeabi_float_t b) +{ + return f32_lt(f32_from_f(a), f32_from_f(b)); +} + +int __aeabi_fcmple(aeabi_float_t a, aeabi_float_t b) +{ + return f32_le(f32_from_f(a), f32_from_f(b)); +} + +int __aeabi_fcmpge(aeabi_float_t a, aeabi_float_t b) +{ + return f32_le(f32_from_f(b), f32_from_f(a)); +} + +int __aeabi_fcmpgt(aeabi_float_t a, aeabi_float_t b) +{ + return f32_lt(f32_from_f(b), f32_from_f(a)); +} + +/* + * Table 6, Standard floating-point to integer conversions + */ + +int __aeabi_d2iz(aeabi_double_t a) +{ + return f64_to_i32_r_minMag(f64_from_d(a), false); +} + +unsigned __aeabi_d2uiz(aeabi_double_t a) +{ + return f64_to_ui32_r_minMag(f64_from_d(a), false); +} + +long long __aeabi_d2lz(aeabi_double_t a) +{ + return f64_to_i64_r_minMag(f64_from_d(a), false); +} + +unsigned long long __aeabi_d2ulz(aeabi_double_t a) +{ + return f64_to_ui64_r_minMag(f64_from_d(a), false); +} + +int __aeabi_f2iz(aeabi_float_t a) +{ + return f32_to_i32_r_minMag(f32_from_f(a), false); +} + +unsigned __aeabi_f2uiz(aeabi_float_t a) +{ + return f32_to_ui32_r_minMag(f32_from_f(a), false); +} + +long long __aeabi_f2lz(aeabi_float_t a) +{ + return f32_to_i64_r_minMag(f32_from_f(a), false); +} + +unsigned long long __aeabi_f2ulz(aeabi_float_t a) +{ + return f32_to_ui64_r_minMag(f32_from_f(a), false); +} + +/* + * Table 7, Standard conversions between floating types + */ + +aeabi_float_t __aeabi_d2f(aeabi_double_t a) +{ + return f32_to_f(f64_to_f32(f64_from_d(a))); +} + +aeabi_double_t __aeabi_f2d(aeabi_float_t a) +{ + return f64_to_d(f32_to_f64(f32_from_f(a))); +} + +/* + * Table 8, Standard integer to floating-point conversions + */ + +aeabi_double_t __aeabi_i2d(int a) +{ + return f64_to_d(i32_to_f64(a)); +} + +aeabi_double_t __aeabi_ui2d(unsigned a) +{ + return f64_to_d(ui32_to_f64(a)); +} + +aeabi_double_t __aeabi_l2d(long long a) +{ + return f64_to_d(i64_to_f64(a)); +} + +aeabi_double_t __aeabi_ul2d(unsigned long long a) +{ + return f64_to_d(ui64_to_f64(a)); +} + +aeabi_float_t __aeabi_i2f(int a) +{ + return f32_to_f(i32_to_f32(a)); +} + +aeabi_float_t __aeabi_ui2f(unsigned a) +{ + return f32_to_f(ui32_to_f32(a)); +} + +aeabi_float_t __aeabi_l2f(long long a) +{ + return f32_to_f(i64_to_f32(a)); +} + +aeabi_float_t __aeabi_ul2f(unsigned long long a) +{ + return f32_to_f(ui64_to_f32(a)); +} diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S b/optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S new file mode 100644 index 0000000..f8a0b70 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * 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 is a simple version of setjmp and longjmp. + + Nick Clifton, Cygnus Solutions, 13 June 1997. */ + +/* ANSI concatenation macros. */ +#define CONCAT(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a##b + +#ifndef __USER_LABEL_PREFIX__ +#error __USER_LABEL_PREFIX__ not defined +#endif + +#define SYM(x) CONCAT (__USER_LABEL_PREFIX__, x) + +#ifdef __ELF__ +#define TYPE(x) .type SYM(x),function +#define SIZE(x) .size SYM(x), . - SYM(x) +#else +#define TYPE(x) +#define SIZE(x) +#endif + + .section .note.GNU-stack,"",%progbits + +/* Arm/Thumb interworking support: + + The interworking scheme expects functions to use a BX instruction + to return control to their parent. Since we need this code to work + in both interworked and non-interworked environments as well as with + older processors which do not have the BX instruction we do the + following: + Test the return address. + If the bottom bit is clear perform an "old style" function exit. + (We know that we are in ARM mode and returning to an ARM mode caller). + Otherwise use the BX instruction to perform the function exit. + + We know that we will never attempt to perform the BX instruction on + an older processor, because that kind of processor will never be + interworked, and a return address with the bottom bit set will never + be generated. + + In addition, we do not actually assemble the BX instruction as this would + require us to tell the assembler that the processor is an ARM7TDMI and + it would store this information in the binary. We want this binary to be + able to be linked with binaries compiled for older processors however, so + we do not want such information stored there. + + If we are running using the APCS-26 convention however, then we never + test the bottom bit, because this is part of the processor status. + Instead we just do a normal return, since we know that we cannot be + returning to a Thumb caller - the Thumb does not support APCS-26. + + Function entry is much simpler. If we are compiling for the Thumb we + just switch into ARM mode and then drop through into the rest of the + function. The function exit code will take care of the restore to + Thumb mode. + + For Thumb-2 do everything in Thumb mode. */ + +#if defined(__ARM_ARCH_6M__) +/* ARMv6-M has to be implemented in Thumb mode. */ + +.thumb +.thumb_func + .globl SYM (setjmp) + TYPE (setjmp) +SYM (setjmp): + /* Save registers in jump buffer. */ + stmia r0!, {r4, r5, r6, r7} + mov r1, r8 + mov r2, r9 + mov r3, r10 + mov r4, fp + mov r5, sp + mov r6, lr + stmia r0!, {r1, r2, r3, r4, r5, r6} + sub r0, r0, #40 + /* Restore callee-saved low regs. */ + ldmia r0!, {r4, r5, r6, r7} + /* Return zero. */ + mov r0, #0 + bx lr + +.thumb_func + .globl SYM (longjmp) + TYPE (longjmp) +SYM (longjmp): + /* Restore High regs. */ + add r0, r0, #16 + ldmia r0!, {r2, r3, r4, r5, r6} + mov r8, r2 + mov r9, r3 + mov r10, r4 + mov fp, r5 + mov sp, r6 + ldmia r0!, {r3} /* lr */ + /* Restore low regs. */ + sub r0, r0, #40 + ldmia r0!, {r4, r5, r6, r7} + /* Return the result argument, or 1 if it is zero. */ + mov r0, r1 + bne 1f + mov r0, #1 +1: + bx r3 + +#else + +#ifdef __APCS_26__ +#define RET movs pc, lr +#elif defined(__thumb2__) +#define RET bx lr +#else +#define RET tst lr, #1; \ + moveq pc, lr ; \ +.word 0xe12fff1e /* bx lr */ +#endif + +#ifdef __thumb2__ +.macro COND where when + i\where \when +.endm +#else +.macro COND where when +.endm +#endif + +#if defined(__thumb2__) +.syntax unified +.macro MODE + .thumb + .thumb_func +.endm +.macro PROLOGUE name +.endm + +#elif defined(__thumb__) +#define MODE .thumb_func +.macro PROLOGUE name + .code 16 + bx pc + nop + .code 32 +SYM (.arm_start_of.\name): +.endm +#else /* Arm */ +#define MODE .code 32 +.macro PROLOGUE name +.endm +#endif + +.macro FUNC_START name + .text + .align 2 + MODE + .globl SYM (\name) + TYPE (\name) +SYM (\name): + PROLOGUE \name +.endm + +.macro FUNC_END name + RET + SIZE (\name) +.endm + +/* -------------------------------------------------------------------- + int setjmp (jmp_buf); + -------------------------------------------------------------------- */ + + FUNC_START setjmp + + /* Save all the callee-preserved registers into the jump buffer. */ +#ifdef __thumb2__ + mov ip, sp + stmea a1!, { v1-v7, fp, ip, lr } +#else + stmea a1!, { v1-v7, fp, ip} + str sp, [a1], #4 + str lr, [a1], #4 +#endif + +#if 0 /* Simulator does not cope with FP instructions yet. */ +#ifndef __SOFTFP__ + /* Save the floating point registers. */ + sfmea f4, 4, [a1] +#endif +#endif + +#ifdef CFG_FTRACE_SUPPORT + stmdb sp!, { lr } + /* + * As ftrace is supported in ARM mode only, so hardcode jmp_buf + * offset used to save ftrace return index. + */ + add a1, a1, #48 + bl ftrace_setjmp + ldmia sp!, { lr } +#endif + + /* When setting up the jump buffer return 0. */ + mov a1, #0 + + FUNC_END setjmp + +/* -------------------------------------------------------------------- + volatile void longjmp (jmp_buf, int); + -------------------------------------------------------------------- */ + + FUNC_START longjmp + + /* If we have stack extension code it ought to be handled here. */ + +#ifdef CFG_FTRACE_SUPPORT + stmdb sp!, { a1, a2, lr } + /* + * As ftrace is supported in ARM mode only, so hardcode jmp_buf + * offset used to restore ftrace return stack. + */ + add a1, a1, #92 + bl ftrace_longjmp + ldmia sp!, { a1, a2, lr } +#endif + + /* Restore the registers, retrieving the state when setjmp() was called. */ +#ifdef __thumb2__ + ldmfd a1!, { v1-v7, fp, ip, lr } + mov sp, ip +#else + ldmfd a1!, { v1-v7, fp, ip } + ldr sp, [a1], #4 + ldr lr, [a1], #4 +#endif + +#if 0 /* Simulator does not cope with FP instructions yet. */ +#ifndef __SOFTFP__ + /* Restore floating point registers as well. */ + lfmfd f4, 4, [a1] +#endif +#endif + /* Put the return value into the integer result register. + But if it is zero then return 1 instead. */ + movs a1, a2 +#ifdef __thumb2__ + it eq +#endif + moveq a1, #1 + + FUNC_END longjmp +#endif diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a64.S b/optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a64.S new file mode 100644 index 0000000..0b2e068 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/setjmp_a64.S @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + Copyright (c) 2011, 2012 ARM Ltd + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must 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 company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 + +#define GPR_LAYOUT \ + REG_PAIR (x19, x20, 0); \ + REG_PAIR (x21, x22, 16); \ + REG_PAIR (x23, x24, 32); \ + REG_PAIR (x25, x26, 48); \ + REG_PAIR (x27, x28, 64); \ + REG_PAIR (x29, x30, 80); \ + REG_ONE (x16, 96) + +#define FPR_LAYOUT \ + REG_PAIR ( d8, d9, 112); \ + REG_PAIR (d10, d11, 128); \ + REG_PAIR (d12, d13, 144); \ + REG_PAIR (d14, d15, 160); + +// int setjmp (jmp_buf) + .global setjmp + .type setjmp, %function +setjmp: +BTI( bti c) + mov x16, sp +#define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS] +#define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS] + GPR_LAYOUT + FPR_LAYOUT +#ifdef CFG_FTRACE_SUPPORT + stp x29, x30, [sp, #-16]! + mov x29, sp + add x0, x0, #104 + bl ftrace_setjmp + ldp x29, x30, [sp], #16 +#endif +#undef REG_PAIR +#undef REG_ONE + mov w0, #0 + ret + .size setjmp, .-setjmp + +// void longjmp (jmp_buf, int) __attribute__ ((noreturn)) + .global longjmp + .type longjmp, %function +longjmp: +BTI( bti c) +#define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS] +#define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS] +#ifdef CFG_FTRACE_SUPPORT + stp x0, x1, [sp, #-16]! + stp x29, x30, [sp, #-16]! + mov x29, sp + add x0, x0, #104 + bl ftrace_longjmp + ldp x29, x30, [sp], #16 + ldp x0, x1, [sp], #16 +#endif + GPR_LAYOUT + FPR_LAYOUT +#undef REG_PAIR +#undef REG_ONE + mov sp, x16 + cmp w1, #0 + cinc w0, w1, eq +/* + * clang has a bug and doesn't insert bti after setjmp + * causing BTI ecxception. Remove this when the bug is fixed. + * https://bugs.llvm.org/show_bug.cgi?id=49544 + */ +#if defined(__clang__) && defined(CFG_TA_BTI) + ret +#else + // use br not ret, as ret is guaranteed to mispredict + br x30 +#endif + .size longjmp, .-longjmp + +BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/COPYING.txt b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/COPYING.txt new file mode 100644 index 0000000..869e6da --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/COPYING.txt @@ -0,0 +1,37 @@ + +License for Berkeley SoftFloat Release 3a + +John R. Hauser +2015 October 23 + +The following applies to the whole of SoftFloat Release 3a as well as to +each source file individually. + +Copyright 2011, 2012, 2013, 2014, 2015 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. + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.html b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.html new file mode 100644 index 0000000..ec64db7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.html @@ -0,0 +1,49 @@ + + + + +Berkeley SoftFloat Package Overview + + + + +

Package Overview for Berkeley SoftFloat Release 3a

+ +

+John R. Hauser
+2015 October 23
+

+ +

+Berkeley SoftFloat is a software implementation of binary floating-point that +conforms to the IEEE Standard for Floating-Point Arithmetic. +SoftFloat is distributed in the form of C source code. +Building the SoftFloat sources generates a library file (typically +softfloat.a or libsoftfloat.a) containing the +floating-point subroutines. +

+ +

+The SoftFloat package is documented in the following files in the +doc subdirectory: +

+ + + + + + + + + + + + + +
SoftFloat.htmlDocumentation for using the SoftFloat functions.
SoftFloat-source.htmlDocumentation for building SoftFloat.
SoftFloat-history.html   History of the major changes to SoftFloat.
+
+Other files in the package comprise the source code for SoftFloat. +

+ + + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.txt b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.txt new file mode 100644 index 0000000..0011b11 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/README.txt @@ -0,0 +1,21 @@ + +Package Overview for Berkeley SoftFloat Release 3a + +John R. Hauser +2015 October 23 + +Berkeley SoftFloat is a software implementation of binary floating-point +that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat +is distributed in the form of C source code. Building the SoftFloat sources +generates a library file (typically "softfloat.a" or "libsoftfloat.a") +containing the floating-point subroutines. + +The SoftFloat package is documented in the following files in the "doc" +subdirectory: + + SoftFloat.html Documentation for using the SoftFloat functions. + SoftFloat-source.html Documentation for building SoftFloat. + SoftFloat-history.html History of the major changes to SoftFloat. + +Other files in the package comprise the source code for SoftFloat. + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/arm32_include/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/arm32_include/platform.h new file mode 100644 index 0000000..d8d39da --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/arm32_include/platform.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header template is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +#define LITTLEENDIAN 1 +#define INLINE static inline +#define SOFTFLOAT_FAST_DIV64TO32 +#define SOFTFLOAT_FAST_INT64 diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/Makefile b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/Makefile new file mode 100644 index 0000000..62d1e45 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/Makefile @@ -0,0 +1,275 @@ +# SPDX-License-Identifier: BSD-3-Clause + +#============================================================================= +# +# This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic +# Package, Release 3a, by John R. Hauser. +# +# Copyright 2011, 2012, 2013, 2014 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. +# +#============================================================================= + +SOURCE_DIR = ../../source +SPECIALIZE_TYPE = 8086 + +SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 + +DELETE = rm -f +C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +COMPILE_C = \ + gcc -c -Werror-implicit-function-declaration $(SOFTFLOAT_OPTS) \ + $(C_INCLUDES) -O2 -o $@ +MAKELIB = ar crs $@ + +OBJ = .o +LIB = .a + +.PHONY: all +all: softfloat$(LIB) + +OBJS_PRIMITIVES = \ + s_compare96M$(OBJ) \ + s_compare128M$(OBJ) \ + s_shortShiftLeft64To96M$(OBJ) \ + s_shortShiftLeftM$(OBJ) \ + s_shiftLeftM$(OBJ) \ + s_shortShiftRightM$(OBJ) \ + s_shortShiftRightJam64$(OBJ) \ + s_shortShiftRightJamM$(OBJ) \ + s_shiftRightJam32$(OBJ) \ + s_shiftRightJam64$(OBJ) \ + s_shiftRightJamM$(OBJ) \ + s_shiftRightM$(OBJ) \ + s_countLeadingZeros8$(OBJ) \ + s_countLeadingZeros32$(OBJ) \ + s_countLeadingZeros64$(OBJ) \ + s_addM$(OBJ) \ + s_addCarryM$(OBJ) \ + s_addComplCarryM$(OBJ) \ + s_negXM$(OBJ) \ + s_sub1XM$(OBJ) \ + s_subM$(OBJ) \ + s_mul64To128M$(OBJ) \ + s_mul128MTo256M$(OBJ) \ + s_approxRecip32_1$(OBJ) \ + s_approxRecipSqrt32_1$(OBJ) \ + s_remStepMBy32$(OBJ) \ + +OBJS_SPECIALIZE = \ + softfloat_raiseFlags$(OBJ) \ + s_f32UIToCommonNaN$(OBJ) \ + s_commonNaNToF32UI$(OBJ) \ + s_propagateNaNF32UI$(OBJ) \ + s_f64UIToCommonNaN$(OBJ) \ + s_commonNaNToF64UI$(OBJ) \ + s_propagateNaNF64UI$(OBJ) \ + extF80M_isSignalingNaN$(OBJ) \ + s_extF80MToCommonNaN$(OBJ) \ + s_commonNaNToExtF80M$(OBJ) \ + s_propagateNaNExtF80M$(OBJ) \ + f128M_isSignalingNaN$(OBJ) \ + s_f128MToCommonNaN$(OBJ) \ + s_commonNaNToF128M$(OBJ) \ + s_propagateNaNF128M$(OBJ) \ + +OBJS_OTHERS = \ + s_roundPackToUI32$(OBJ) \ + s_roundPackMToUI64$(OBJ) \ + s_roundPackToI32$(OBJ) \ + s_roundPackMToI64$(OBJ) \ + s_normSubnormalF32Sig$(OBJ) \ + s_roundPackToF32$(OBJ) \ + s_normRoundPackToF32$(OBJ) \ + s_addMagsF32$(OBJ) \ + s_subMagsF32$(OBJ) \ + s_mulAddF32$(OBJ) \ + s_normSubnormalF64Sig$(OBJ) \ + s_roundPackToF64$(OBJ) \ + s_normRoundPackToF64$(OBJ) \ + s_addMagsF64$(OBJ) \ + s_subMagsF64$(OBJ) \ + s_mulAddF64$(OBJ) \ + s_tryPropagateNaNExtF80M$(OBJ) \ + s_invalidExtF80M$(OBJ) \ + s_normExtF80SigM$(OBJ) \ + s_roundPackMToExtF80M$(OBJ) \ + s_normRoundPackMToExtF80M$(OBJ) \ + s_addExtF80M$(OBJ) \ + s_compareNonnormExtF80M$(OBJ) \ + s_isNaNF128M$(OBJ) \ + s_tryPropagateNaNF128M$(OBJ) \ + s_invalidF128M$(OBJ) \ + s_shiftNormSigF128M$(OBJ) \ + s_roundPackMToF128M$(OBJ) \ + s_normRoundPackMToF128M$(OBJ) \ + s_addF128M$(OBJ) \ + s_mulAddF128M$(OBJ) \ + softfloat_state$(OBJ) \ + ui32_to_f32$(OBJ) \ + ui32_to_f64$(OBJ) \ + ui32_to_extF80M$(OBJ) \ + ui32_to_f128M$(OBJ) \ + ui64_to_f32$(OBJ) \ + ui64_to_f64$(OBJ) \ + ui64_to_extF80M$(OBJ) \ + ui64_to_f128M$(OBJ) \ + i32_to_f32$(OBJ) \ + i32_to_f64$(OBJ) \ + i32_to_extF80M$(OBJ) \ + i32_to_f128M$(OBJ) \ + i64_to_f32$(OBJ) \ + i64_to_f64$(OBJ) \ + i64_to_extF80M$(OBJ) \ + i64_to_f128M$(OBJ) \ + f32_to_ui32$(OBJ) \ + f32_to_ui64$(OBJ) \ + f32_to_i32$(OBJ) \ + f32_to_i64$(OBJ) \ + f32_to_ui32_r_minMag$(OBJ) \ + f32_to_ui64_r_minMag$(OBJ) \ + f32_to_i32_r_minMag$(OBJ) \ + f32_to_i64_r_minMag$(OBJ) \ + f32_to_f64$(OBJ) \ + f32_to_extF80M$(OBJ) \ + f32_to_f128M$(OBJ) \ + f32_roundToInt$(OBJ) \ + f32_add$(OBJ) \ + f32_sub$(OBJ) \ + f32_mul$(OBJ) \ + f32_mulAdd$(OBJ) \ + f32_div$(OBJ) \ + f32_rem$(OBJ) \ + f32_sqrt$(OBJ) \ + f32_eq$(OBJ) \ + f32_le$(OBJ) \ + f32_lt$(OBJ) \ + f32_eq_signaling$(OBJ) \ + f32_le_quiet$(OBJ) \ + f32_lt_quiet$(OBJ) \ + f32_isSignalingNaN$(OBJ) \ + f64_to_ui32$(OBJ) \ + f64_to_ui64$(OBJ) \ + f64_to_i32$(OBJ) \ + f64_to_i64$(OBJ) \ + f64_to_ui32_r_minMag$(OBJ) \ + f64_to_ui64_r_minMag$(OBJ) \ + f64_to_i32_r_minMag$(OBJ) \ + f64_to_i64_r_minMag$(OBJ) \ + f64_to_f32$(OBJ) \ + f64_to_extF80M$(OBJ) \ + f64_to_f128M$(OBJ) \ + f64_roundToInt$(OBJ) \ + f64_add$(OBJ) \ + f64_sub$(OBJ) \ + f64_mul$(OBJ) \ + f64_mulAdd$(OBJ) \ + f64_div$(OBJ) \ + f64_rem$(OBJ) \ + f64_sqrt$(OBJ) \ + f64_eq$(OBJ) \ + f64_le$(OBJ) \ + f64_lt$(OBJ) \ + f64_eq_signaling$(OBJ) \ + f64_le_quiet$(OBJ) \ + f64_lt_quiet$(OBJ) \ + f64_isSignalingNaN$(OBJ) \ + extF80M_to_ui32$(OBJ) \ + extF80M_to_ui64$(OBJ) \ + extF80M_to_i32$(OBJ) \ + extF80M_to_i64$(OBJ) \ + extF80M_to_ui32_r_minMag$(OBJ) \ + extF80M_to_ui64_r_minMag$(OBJ) \ + extF80M_to_i32_r_minMag$(OBJ) \ + extF80M_to_i64_r_minMag$(OBJ) \ + extF80M_to_f32$(OBJ) \ + extF80M_to_f64$(OBJ) \ + extF80M_to_f128M$(OBJ) \ + extF80M_roundToInt$(OBJ) \ + extF80M_add$(OBJ) \ + extF80M_sub$(OBJ) \ + extF80M_mul$(OBJ) \ + extF80M_div$(OBJ) \ + extF80M_rem$(OBJ) \ + extF80M_sqrt$(OBJ) \ + extF80M_eq$(OBJ) \ + extF80M_le$(OBJ) \ + extF80M_lt$(OBJ) \ + extF80M_eq_signaling$(OBJ) \ + extF80M_le_quiet$(OBJ) \ + extF80M_lt_quiet$(OBJ) \ + f128M_to_ui32$(OBJ) \ + f128M_to_ui64$(OBJ) \ + f128M_to_i32$(OBJ) \ + f128M_to_i64$(OBJ) \ + f128M_to_ui32_r_minMag$(OBJ) \ + f128M_to_ui64_r_minMag$(OBJ) \ + f128M_to_i32_r_minMag$(OBJ) \ + f128M_to_i64_r_minMag$(OBJ) \ + f128M_to_f32$(OBJ) \ + f128M_to_f64$(OBJ) \ + f128M_to_extF80M$(OBJ) \ + f128M_roundToInt$(OBJ) \ + f128M_add$(OBJ) \ + f128M_sub$(OBJ) \ + f128M_mul$(OBJ) \ + f128M_mulAdd$(OBJ) \ + f128M_div$(OBJ) \ + f128M_rem$(OBJ) \ + f128M_sqrt$(OBJ) \ + f128M_eq$(OBJ) \ + f128M_le$(OBJ) \ + f128M_lt$(OBJ) \ + f128M_eq_signaling$(OBJ) \ + f128M_le_quiet$(OBJ) \ + f128M_lt_quiet$(OBJ) \ + +OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) + +$(OBJS_ALL): \ + platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ + $(SOURCE_DIR)/include/primitives.h +$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ + $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ + $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/softfloat.h + +$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$*.c + +$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c + +softfloat$(LIB): $(OBJS_ALL) + $(DELETE) $@ + $(MAKELIB) $^ + +.PHONY: clean +clean: + $(DELETE) $(OBJS_ALL) softfloat$(LIB) + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/platform.h new file mode 100644 index 0000000..6121db8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/platform.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define LITTLEENDIAN 1 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define INLINE extern inline + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/Makefile b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/Makefile new file mode 100644 index 0000000..93bc566 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/Makefile @@ -0,0 +1,275 @@ +# SPDX-License-Identifier: BSD-3-Clause + +#============================================================================= +# +# This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic +# Package, Release 3a, by John R. Hauser. +# +# Copyright 2011, 2012, 2013, 2014 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. +# +#============================================================================= + +SOURCE_DIR = ../../source +SPECIALIZE_TYPE = 8086-SSE + +SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 + +DELETE = rm -f +C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +COMPILE_C = \ + gcc -c -Werror-implicit-function-declaration $(SOFTFLOAT_OPTS) \ + $(C_INCLUDES) -O2 -o $@ +MAKELIB = ar crs $@ + +OBJ = .o +LIB = .a + +.PHONY: all +all: softfloat$(LIB) + +OBJS_PRIMITIVES = \ + s_compare96M$(OBJ) \ + s_compare128M$(OBJ) \ + s_shortShiftLeft64To96M$(OBJ) \ + s_shortShiftLeftM$(OBJ) \ + s_shiftLeftM$(OBJ) \ + s_shortShiftRightM$(OBJ) \ + s_shortShiftRightJam64$(OBJ) \ + s_shortShiftRightJamM$(OBJ) \ + s_shiftRightJam32$(OBJ) \ + s_shiftRightJam64$(OBJ) \ + s_shiftRightJamM$(OBJ) \ + s_shiftRightM$(OBJ) \ + s_countLeadingZeros8$(OBJ) \ + s_countLeadingZeros32$(OBJ) \ + s_countLeadingZeros64$(OBJ) \ + s_addM$(OBJ) \ + s_addCarryM$(OBJ) \ + s_addComplCarryM$(OBJ) \ + s_negXM$(OBJ) \ + s_sub1XM$(OBJ) \ + s_subM$(OBJ) \ + s_mul64To128M$(OBJ) \ + s_mul128MTo256M$(OBJ) \ + s_approxRecip32_1$(OBJ) \ + s_approxRecipSqrt32_1$(OBJ) \ + s_remStepMBy32$(OBJ) \ + +OBJS_SPECIALIZE = \ + softfloat_raiseFlags$(OBJ) \ + s_f32UIToCommonNaN$(OBJ) \ + s_commonNaNToF32UI$(OBJ) \ + s_propagateNaNF32UI$(OBJ) \ + s_f64UIToCommonNaN$(OBJ) \ + s_commonNaNToF64UI$(OBJ) \ + s_propagateNaNF64UI$(OBJ) \ + extF80M_isSignalingNaN$(OBJ) \ + s_extF80MToCommonNaN$(OBJ) \ + s_commonNaNToExtF80M$(OBJ) \ + s_propagateNaNExtF80M$(OBJ) \ + f128M_isSignalingNaN$(OBJ) \ + s_f128MToCommonNaN$(OBJ) \ + s_commonNaNToF128M$(OBJ) \ + s_propagateNaNF128M$(OBJ) \ + +OBJS_OTHERS = \ + s_roundPackToUI32$(OBJ) \ + s_roundPackMToUI64$(OBJ) \ + s_roundPackToI32$(OBJ) \ + s_roundPackMToI64$(OBJ) \ + s_normSubnormalF32Sig$(OBJ) \ + s_roundPackToF32$(OBJ) \ + s_normRoundPackToF32$(OBJ) \ + s_addMagsF32$(OBJ) \ + s_subMagsF32$(OBJ) \ + s_mulAddF32$(OBJ) \ + s_normSubnormalF64Sig$(OBJ) \ + s_roundPackToF64$(OBJ) \ + s_normRoundPackToF64$(OBJ) \ + s_addMagsF64$(OBJ) \ + s_subMagsF64$(OBJ) \ + s_mulAddF64$(OBJ) \ + s_tryPropagateNaNExtF80M$(OBJ) \ + s_invalidExtF80M$(OBJ) \ + s_normExtF80SigM$(OBJ) \ + s_roundPackMToExtF80M$(OBJ) \ + s_normRoundPackMToExtF80M$(OBJ) \ + s_addExtF80M$(OBJ) \ + s_compareNonnormExtF80M$(OBJ) \ + s_isNaNF128M$(OBJ) \ + s_tryPropagateNaNF128M$(OBJ) \ + s_invalidF128M$(OBJ) \ + s_shiftNormSigF128M$(OBJ) \ + s_roundPackMToF128M$(OBJ) \ + s_normRoundPackMToF128M$(OBJ) \ + s_addF128M$(OBJ) \ + s_mulAddF128M$(OBJ) \ + softfloat_state$(OBJ) \ + ui32_to_f32$(OBJ) \ + ui32_to_f64$(OBJ) \ + ui32_to_extF80M$(OBJ) \ + ui32_to_f128M$(OBJ) \ + ui64_to_f32$(OBJ) \ + ui64_to_f64$(OBJ) \ + ui64_to_extF80M$(OBJ) \ + ui64_to_f128M$(OBJ) \ + i32_to_f32$(OBJ) \ + i32_to_f64$(OBJ) \ + i32_to_extF80M$(OBJ) \ + i32_to_f128M$(OBJ) \ + i64_to_f32$(OBJ) \ + i64_to_f64$(OBJ) \ + i64_to_extF80M$(OBJ) \ + i64_to_f128M$(OBJ) \ + f32_to_ui32$(OBJ) \ + f32_to_ui64$(OBJ) \ + f32_to_i32$(OBJ) \ + f32_to_i64$(OBJ) \ + f32_to_ui32_r_minMag$(OBJ) \ + f32_to_ui64_r_minMag$(OBJ) \ + f32_to_i32_r_minMag$(OBJ) \ + f32_to_i64_r_minMag$(OBJ) \ + f32_to_f64$(OBJ) \ + f32_to_extF80M$(OBJ) \ + f32_to_f128M$(OBJ) \ + f32_roundToInt$(OBJ) \ + f32_add$(OBJ) \ + f32_sub$(OBJ) \ + f32_mul$(OBJ) \ + f32_mulAdd$(OBJ) \ + f32_div$(OBJ) \ + f32_rem$(OBJ) \ + f32_sqrt$(OBJ) \ + f32_eq$(OBJ) \ + f32_le$(OBJ) \ + f32_lt$(OBJ) \ + f32_eq_signaling$(OBJ) \ + f32_le_quiet$(OBJ) \ + f32_lt_quiet$(OBJ) \ + f32_isSignalingNaN$(OBJ) \ + f64_to_ui32$(OBJ) \ + f64_to_ui64$(OBJ) \ + f64_to_i32$(OBJ) \ + f64_to_i64$(OBJ) \ + f64_to_ui32_r_minMag$(OBJ) \ + f64_to_ui64_r_minMag$(OBJ) \ + f64_to_i32_r_minMag$(OBJ) \ + f64_to_i64_r_minMag$(OBJ) \ + f64_to_f32$(OBJ) \ + f64_to_extF80M$(OBJ) \ + f64_to_f128M$(OBJ) \ + f64_roundToInt$(OBJ) \ + f64_add$(OBJ) \ + f64_sub$(OBJ) \ + f64_mul$(OBJ) \ + f64_mulAdd$(OBJ) \ + f64_div$(OBJ) \ + f64_rem$(OBJ) \ + f64_sqrt$(OBJ) \ + f64_eq$(OBJ) \ + f64_le$(OBJ) \ + f64_lt$(OBJ) \ + f64_eq_signaling$(OBJ) \ + f64_le_quiet$(OBJ) \ + f64_lt_quiet$(OBJ) \ + f64_isSignalingNaN$(OBJ) \ + extF80M_to_ui32$(OBJ) \ + extF80M_to_ui64$(OBJ) \ + extF80M_to_i32$(OBJ) \ + extF80M_to_i64$(OBJ) \ + extF80M_to_ui32_r_minMag$(OBJ) \ + extF80M_to_ui64_r_minMag$(OBJ) \ + extF80M_to_i32_r_minMag$(OBJ) \ + extF80M_to_i64_r_minMag$(OBJ) \ + extF80M_to_f32$(OBJ) \ + extF80M_to_f64$(OBJ) \ + extF80M_to_f128M$(OBJ) \ + extF80M_roundToInt$(OBJ) \ + extF80M_add$(OBJ) \ + extF80M_sub$(OBJ) \ + extF80M_mul$(OBJ) \ + extF80M_div$(OBJ) \ + extF80M_rem$(OBJ) \ + extF80M_sqrt$(OBJ) \ + extF80M_eq$(OBJ) \ + extF80M_le$(OBJ) \ + extF80M_lt$(OBJ) \ + extF80M_eq_signaling$(OBJ) \ + extF80M_le_quiet$(OBJ) \ + extF80M_lt_quiet$(OBJ) \ + f128M_to_ui32$(OBJ) \ + f128M_to_ui64$(OBJ) \ + f128M_to_i32$(OBJ) \ + f128M_to_i64$(OBJ) \ + f128M_to_ui32_r_minMag$(OBJ) \ + f128M_to_ui64_r_minMag$(OBJ) \ + f128M_to_i32_r_minMag$(OBJ) \ + f128M_to_i64_r_minMag$(OBJ) \ + f128M_to_f32$(OBJ) \ + f128M_to_f64$(OBJ) \ + f128M_to_extF80M$(OBJ) \ + f128M_roundToInt$(OBJ) \ + f128M_add$(OBJ) \ + f128M_sub$(OBJ) \ + f128M_mul$(OBJ) \ + f128M_mulAdd$(OBJ) \ + f128M_div$(OBJ) \ + f128M_rem$(OBJ) \ + f128M_sqrt$(OBJ) \ + f128M_eq$(OBJ) \ + f128M_le$(OBJ) \ + f128M_lt$(OBJ) \ + f128M_eq_signaling$(OBJ) \ + f128M_le_quiet$(OBJ) \ + f128M_lt_quiet$(OBJ) \ + +OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) + +$(OBJS_ALL): \ + platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ + $(SOURCE_DIR)/include/primitives.h +$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ + $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ + $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/softfloat.h + +$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$*.c + +$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c + +softfloat$(LIB): $(OBJS_ALL) + $(DELETE) $@ + $(MAKELIB) $^ + +.PHONY: clean +clean: + $(DELETE) $(OBJS_ALL) softfloat$(LIB) + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/platform.h new file mode 100644 index 0000000..6121db8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/platform.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define LITTLEENDIAN 1 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define INLINE extern inline + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/Makefile b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/Makefile new file mode 100644 index 0000000..63f8c2f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/Makefile @@ -0,0 +1,336 @@ +# SPDX-License-Identifier: BSD-3-Clause + +#============================================================================= +# +# This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic +# Package, Release 3a, by John R. Hauser. +# +# Copyright 2011, 2012, 2013, 2014 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. +# +#============================================================================= + +SOURCE_DIR = ../../source +SPECIALIZE_TYPE = 8086-SSE + +SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 + +DELETE = rm -f +C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +COMPILE_C = \ + gcc -c -Werror-implicit-function-declaration -DSOFTFLOAT_FAST_INT64 \ + $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@ +MAKELIB = ar crs $@ + +OBJ = .o +LIB = .a + +.PHONY: all +all: softfloat$(LIB) + +OBJS_PRIMITIVES = \ + s_eq128$(OBJ) \ + s_le128$(OBJ) \ + s_lt128$(OBJ) \ + s_shortShiftLeft128$(OBJ) \ + s_shortShiftRight128$(OBJ) \ + s_shortShiftRightJam64$(OBJ) \ + s_shortShiftRightJam64Extra$(OBJ) \ + s_shortShiftRightJam128$(OBJ) \ + s_shortShiftRightJam128Extra$(OBJ) \ + s_shiftRightJam32$(OBJ) \ + s_shiftRightJam64$(OBJ) \ + s_shiftRightJam64Extra$(OBJ) \ + s_shiftRightJam128$(OBJ) \ + s_shiftRightJam128Extra$(OBJ) \ + s_shiftRightJam256M$(OBJ) \ + s_countLeadingZeros8$(OBJ) \ + s_countLeadingZeros32$(OBJ) \ + s_countLeadingZeros64$(OBJ) \ + s_add128$(OBJ) \ + s_add256M$(OBJ) \ + s_sub128$(OBJ) \ + s_sub256M$(OBJ) \ + s_mul64ByShifted32To128$(OBJ) \ + s_mul64To128$(OBJ) \ + s_mul128By32$(OBJ) \ + s_mul128To256M$(OBJ) \ + s_approxRecip32_1$(OBJ) \ + s_approxRecipSqrt32_1$(OBJ) \ + +OBJS_SPECIALIZE = \ + softfloat_raiseFlags$(OBJ) \ + s_f32UIToCommonNaN$(OBJ) \ + s_commonNaNToF32UI$(OBJ) \ + s_propagateNaNF32UI$(OBJ) \ + s_f64UIToCommonNaN$(OBJ) \ + s_commonNaNToF64UI$(OBJ) \ + s_propagateNaNF64UI$(OBJ) \ + extF80M_isSignalingNaN$(OBJ) \ + s_extF80UIToCommonNaN$(OBJ) \ + s_commonNaNToExtF80UI$(OBJ) \ + s_propagateNaNExtF80UI$(OBJ) \ + f128M_isSignalingNaN$(OBJ) \ + s_f128UIToCommonNaN$(OBJ) \ + s_commonNaNToF128UI$(OBJ) \ + s_propagateNaNF128UI$(OBJ) \ + +OBJS_OTHERS = \ + s_roundPackToUI32$(OBJ) \ + s_roundPackToUI64$(OBJ) \ + s_roundPackToI32$(OBJ) \ + s_roundPackToI64$(OBJ) \ + s_normSubnormalF32Sig$(OBJ) \ + s_roundPackToF32$(OBJ) \ + s_normRoundPackToF32$(OBJ) \ + s_addMagsF32$(OBJ) \ + s_subMagsF32$(OBJ) \ + s_mulAddF32$(OBJ) \ + s_normSubnormalF64Sig$(OBJ) \ + s_roundPackToF64$(OBJ) \ + s_normRoundPackToF64$(OBJ) \ + s_addMagsF64$(OBJ) \ + s_subMagsF64$(OBJ) \ + s_mulAddF64$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_roundPackToExtF80$(OBJ) \ + s_normRoundPackToExtF80$(OBJ) \ + s_addMagsExtF80$(OBJ) \ + s_subMagsExtF80$(OBJ) \ + s_normSubnormalF128Sig$(OBJ) \ + s_roundPackToF128$(OBJ) \ + s_normRoundPackToF128$(OBJ) \ + s_addMagsF128$(OBJ) \ + s_subMagsF128$(OBJ) \ + s_mulAddF128$(OBJ) \ + softfloat_state$(OBJ) \ + ui32_to_f32$(OBJ) \ + ui32_to_f64$(OBJ) \ + ui32_to_extF80$(OBJ) \ + ui32_to_extF80M$(OBJ) \ + ui32_to_f128$(OBJ) \ + ui32_to_f128M$(OBJ) \ + ui64_to_f32$(OBJ) \ + ui64_to_f64$(OBJ) \ + ui64_to_extF80$(OBJ) \ + ui64_to_extF80M$(OBJ) \ + ui64_to_f128$(OBJ) \ + ui64_to_f128M$(OBJ) \ + i32_to_f32$(OBJ) \ + i32_to_f64$(OBJ) \ + i32_to_extF80$(OBJ) \ + i32_to_extF80M$(OBJ) \ + i32_to_f128$(OBJ) \ + i32_to_f128M$(OBJ) \ + i64_to_f32$(OBJ) \ + i64_to_f64$(OBJ) \ + i64_to_extF80$(OBJ) \ + i64_to_extF80M$(OBJ) \ + i64_to_f128$(OBJ) \ + i64_to_f128M$(OBJ) \ + f32_to_ui32$(OBJ) \ + f32_to_ui64$(OBJ) \ + f32_to_i32$(OBJ) \ + f32_to_i64$(OBJ) \ + f32_to_ui32_r_minMag$(OBJ) \ + f32_to_ui64_r_minMag$(OBJ) \ + f32_to_i32_r_minMag$(OBJ) \ + f32_to_i64_r_minMag$(OBJ) \ + f32_to_f64$(OBJ) \ + f32_to_extF80$(OBJ) \ + f32_to_extF80M$(OBJ) \ + f32_to_f128$(OBJ) \ + f32_to_f128M$(OBJ) \ + f32_roundToInt$(OBJ) \ + f32_add$(OBJ) \ + f32_sub$(OBJ) \ + f32_mul$(OBJ) \ + f32_mulAdd$(OBJ) \ + f32_div$(OBJ) \ + f32_rem$(OBJ) \ + f32_sqrt$(OBJ) \ + f32_eq$(OBJ) \ + f32_le$(OBJ) \ + f32_lt$(OBJ) \ + f32_eq_signaling$(OBJ) \ + f32_le_quiet$(OBJ) \ + f32_lt_quiet$(OBJ) \ + f32_isSignalingNaN$(OBJ) \ + f64_to_ui32$(OBJ) \ + f64_to_ui64$(OBJ) \ + f64_to_i32$(OBJ) \ + f64_to_i64$(OBJ) \ + f64_to_ui32_r_minMag$(OBJ) \ + f64_to_ui64_r_minMag$(OBJ) \ + f64_to_i32_r_minMag$(OBJ) \ + f64_to_i64_r_minMag$(OBJ) \ + f64_to_f32$(OBJ) \ + f64_to_extF80$(OBJ) \ + f64_to_extF80M$(OBJ) \ + f64_to_f128$(OBJ) \ + f64_to_f128M$(OBJ) \ + f64_roundToInt$(OBJ) \ + f64_add$(OBJ) \ + f64_sub$(OBJ) \ + f64_mul$(OBJ) \ + f64_mulAdd$(OBJ) \ + f64_div$(OBJ) \ + f64_rem$(OBJ) \ + f64_sqrt$(OBJ) \ + f64_eq$(OBJ) \ + f64_le$(OBJ) \ + f64_lt$(OBJ) \ + f64_eq_signaling$(OBJ) \ + f64_le_quiet$(OBJ) \ + f64_lt_quiet$(OBJ) \ + f64_isSignalingNaN$(OBJ) \ + extF80_to_ui32$(OBJ) \ + extF80_to_ui64$(OBJ) \ + extF80_to_i32$(OBJ) \ + extF80_to_i64$(OBJ) \ + extF80_to_ui32_r_minMag$(OBJ) \ + extF80_to_ui64_r_minMag$(OBJ) \ + extF80_to_i32_r_minMag$(OBJ) \ + extF80_to_i64_r_minMag$(OBJ) \ + extF80_to_f32$(OBJ) \ + extF80_to_f64$(OBJ) \ + extF80_to_f128$(OBJ) \ + extF80_roundToInt$(OBJ) \ + extF80_add$(OBJ) \ + extF80_sub$(OBJ) \ + extF80_mul$(OBJ) \ + extF80_div$(OBJ) \ + extF80_rem$(OBJ) \ + extF80_sqrt$(OBJ) \ + extF80_eq$(OBJ) \ + extF80_le$(OBJ) \ + extF80_lt$(OBJ) \ + extF80_eq_signaling$(OBJ) \ + extF80_le_quiet$(OBJ) \ + extF80_lt_quiet$(OBJ) \ + extF80_isSignalingNaN$(OBJ) \ + extF80M_to_ui32$(OBJ) \ + extF80M_to_ui64$(OBJ) \ + extF80M_to_i32$(OBJ) \ + extF80M_to_i64$(OBJ) \ + extF80M_to_ui32_r_minMag$(OBJ) \ + extF80M_to_ui64_r_minMag$(OBJ) \ + extF80M_to_i32_r_minMag$(OBJ) \ + extF80M_to_i64_r_minMag$(OBJ) \ + extF80M_to_f32$(OBJ) \ + extF80M_to_f64$(OBJ) \ + extF80M_to_f128M$(OBJ) \ + extF80M_roundToInt$(OBJ) \ + extF80M_add$(OBJ) \ + extF80M_sub$(OBJ) \ + extF80M_mul$(OBJ) \ + extF80M_div$(OBJ) \ + extF80M_rem$(OBJ) \ + extF80M_sqrt$(OBJ) \ + extF80M_eq$(OBJ) \ + extF80M_le$(OBJ) \ + extF80M_lt$(OBJ) \ + extF80M_eq_signaling$(OBJ) \ + extF80M_le_quiet$(OBJ) \ + extF80M_lt_quiet$(OBJ) \ + f128_to_ui32$(OBJ) \ + f128_to_ui64$(OBJ) \ + f128_to_i32$(OBJ) \ + f128_to_i64$(OBJ) \ + f128_to_ui32_r_minMag$(OBJ) \ + f128_to_ui64_r_minMag$(OBJ) \ + f128_to_i32_r_minMag$(OBJ) \ + f128_to_i64_r_minMag$(OBJ) \ + f128_to_f32$(OBJ) \ + f128_to_extF80$(OBJ) \ + f128_to_f64$(OBJ) \ + f128_roundToInt$(OBJ) \ + f128_add$(OBJ) \ + f128_sub$(OBJ) \ + f128_mul$(OBJ) \ + f128_mulAdd$(OBJ) \ + f128_div$(OBJ) \ + f128_rem$(OBJ) \ + f128_sqrt$(OBJ) \ + f128_eq$(OBJ) \ + f128_le$(OBJ) \ + f128_lt$(OBJ) \ + f128_eq_signaling$(OBJ) \ + f128_le_quiet$(OBJ) \ + f128_lt_quiet$(OBJ) \ + f128_isSignalingNaN$(OBJ) \ + f128M_to_ui32$(OBJ) \ + f128M_to_ui64$(OBJ) \ + f128M_to_i32$(OBJ) \ + f128M_to_i64$(OBJ) \ + f128M_to_ui32_r_minMag$(OBJ) \ + f128M_to_ui64_r_minMag$(OBJ) \ + f128M_to_i32_r_minMag$(OBJ) \ + f128M_to_i64_r_minMag$(OBJ) \ + f128M_to_f32$(OBJ) \ + f128M_to_extF80M$(OBJ) \ + f128M_to_f64$(OBJ) \ + f128M_roundToInt$(OBJ) \ + f128M_add$(OBJ) \ + f128M_sub$(OBJ) \ + f128M_mul$(OBJ) \ + f128M_mulAdd$(OBJ) \ + f128M_div$(OBJ) \ + f128M_rem$(OBJ) \ + f128M_sqrt$(OBJ) \ + f128M_eq$(OBJ) \ + f128M_le$(OBJ) \ + f128M_lt$(OBJ) \ + f128M_eq_signaling$(OBJ) \ + f128M_le_quiet$(OBJ) \ + f128M_lt_quiet$(OBJ) \ + +OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) + +$(OBJS_ALL): \ + platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ + $(SOURCE_DIR)/include/primitives.h +$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ + $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ + $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/softfloat.h + +$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$*.c + +$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c + +softfloat$(LIB): $(OBJS_ALL) + $(DELETE) $@ + $(MAKELIB) $^ + +.PHONY: clean +clean: + $(DELETE) $(OBJS_ALL) softfloat$(LIB) + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/platform.h new file mode 100644 index 0000000..6121db8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/platform.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define LITTLEENDIAN 1 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define INLINE extern inline + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/Makefile b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/Makefile new file mode 100644 index 0000000..62d1e45 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/Makefile @@ -0,0 +1,275 @@ +# SPDX-License-Identifier: BSD-3-Clause + +#============================================================================= +# +# This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic +# Package, Release 3a, by John R. Hauser. +# +# Copyright 2011, 2012, 2013, 2014 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. +# +#============================================================================= + +SOURCE_DIR = ../../source +SPECIALIZE_TYPE = 8086 + +SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 + +DELETE = rm -f +C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +COMPILE_C = \ + gcc -c -Werror-implicit-function-declaration $(SOFTFLOAT_OPTS) \ + $(C_INCLUDES) -O2 -o $@ +MAKELIB = ar crs $@ + +OBJ = .o +LIB = .a + +.PHONY: all +all: softfloat$(LIB) + +OBJS_PRIMITIVES = \ + s_compare96M$(OBJ) \ + s_compare128M$(OBJ) \ + s_shortShiftLeft64To96M$(OBJ) \ + s_shortShiftLeftM$(OBJ) \ + s_shiftLeftM$(OBJ) \ + s_shortShiftRightM$(OBJ) \ + s_shortShiftRightJam64$(OBJ) \ + s_shortShiftRightJamM$(OBJ) \ + s_shiftRightJam32$(OBJ) \ + s_shiftRightJam64$(OBJ) \ + s_shiftRightJamM$(OBJ) \ + s_shiftRightM$(OBJ) \ + s_countLeadingZeros8$(OBJ) \ + s_countLeadingZeros32$(OBJ) \ + s_countLeadingZeros64$(OBJ) \ + s_addM$(OBJ) \ + s_addCarryM$(OBJ) \ + s_addComplCarryM$(OBJ) \ + s_negXM$(OBJ) \ + s_sub1XM$(OBJ) \ + s_subM$(OBJ) \ + s_mul64To128M$(OBJ) \ + s_mul128MTo256M$(OBJ) \ + s_approxRecip32_1$(OBJ) \ + s_approxRecipSqrt32_1$(OBJ) \ + s_remStepMBy32$(OBJ) \ + +OBJS_SPECIALIZE = \ + softfloat_raiseFlags$(OBJ) \ + s_f32UIToCommonNaN$(OBJ) \ + s_commonNaNToF32UI$(OBJ) \ + s_propagateNaNF32UI$(OBJ) \ + s_f64UIToCommonNaN$(OBJ) \ + s_commonNaNToF64UI$(OBJ) \ + s_propagateNaNF64UI$(OBJ) \ + extF80M_isSignalingNaN$(OBJ) \ + s_extF80MToCommonNaN$(OBJ) \ + s_commonNaNToExtF80M$(OBJ) \ + s_propagateNaNExtF80M$(OBJ) \ + f128M_isSignalingNaN$(OBJ) \ + s_f128MToCommonNaN$(OBJ) \ + s_commonNaNToF128M$(OBJ) \ + s_propagateNaNF128M$(OBJ) \ + +OBJS_OTHERS = \ + s_roundPackToUI32$(OBJ) \ + s_roundPackMToUI64$(OBJ) \ + s_roundPackToI32$(OBJ) \ + s_roundPackMToI64$(OBJ) \ + s_normSubnormalF32Sig$(OBJ) \ + s_roundPackToF32$(OBJ) \ + s_normRoundPackToF32$(OBJ) \ + s_addMagsF32$(OBJ) \ + s_subMagsF32$(OBJ) \ + s_mulAddF32$(OBJ) \ + s_normSubnormalF64Sig$(OBJ) \ + s_roundPackToF64$(OBJ) \ + s_normRoundPackToF64$(OBJ) \ + s_addMagsF64$(OBJ) \ + s_subMagsF64$(OBJ) \ + s_mulAddF64$(OBJ) \ + s_tryPropagateNaNExtF80M$(OBJ) \ + s_invalidExtF80M$(OBJ) \ + s_normExtF80SigM$(OBJ) \ + s_roundPackMToExtF80M$(OBJ) \ + s_normRoundPackMToExtF80M$(OBJ) \ + s_addExtF80M$(OBJ) \ + s_compareNonnormExtF80M$(OBJ) \ + s_isNaNF128M$(OBJ) \ + s_tryPropagateNaNF128M$(OBJ) \ + s_invalidF128M$(OBJ) \ + s_shiftNormSigF128M$(OBJ) \ + s_roundPackMToF128M$(OBJ) \ + s_normRoundPackMToF128M$(OBJ) \ + s_addF128M$(OBJ) \ + s_mulAddF128M$(OBJ) \ + softfloat_state$(OBJ) \ + ui32_to_f32$(OBJ) \ + ui32_to_f64$(OBJ) \ + ui32_to_extF80M$(OBJ) \ + ui32_to_f128M$(OBJ) \ + ui64_to_f32$(OBJ) \ + ui64_to_f64$(OBJ) \ + ui64_to_extF80M$(OBJ) \ + ui64_to_f128M$(OBJ) \ + i32_to_f32$(OBJ) \ + i32_to_f64$(OBJ) \ + i32_to_extF80M$(OBJ) \ + i32_to_f128M$(OBJ) \ + i64_to_f32$(OBJ) \ + i64_to_f64$(OBJ) \ + i64_to_extF80M$(OBJ) \ + i64_to_f128M$(OBJ) \ + f32_to_ui32$(OBJ) \ + f32_to_ui64$(OBJ) \ + f32_to_i32$(OBJ) \ + f32_to_i64$(OBJ) \ + f32_to_ui32_r_minMag$(OBJ) \ + f32_to_ui64_r_minMag$(OBJ) \ + f32_to_i32_r_minMag$(OBJ) \ + f32_to_i64_r_minMag$(OBJ) \ + f32_to_f64$(OBJ) \ + f32_to_extF80M$(OBJ) \ + f32_to_f128M$(OBJ) \ + f32_roundToInt$(OBJ) \ + f32_add$(OBJ) \ + f32_sub$(OBJ) \ + f32_mul$(OBJ) \ + f32_mulAdd$(OBJ) \ + f32_div$(OBJ) \ + f32_rem$(OBJ) \ + f32_sqrt$(OBJ) \ + f32_eq$(OBJ) \ + f32_le$(OBJ) \ + f32_lt$(OBJ) \ + f32_eq_signaling$(OBJ) \ + f32_le_quiet$(OBJ) \ + f32_lt_quiet$(OBJ) \ + f32_isSignalingNaN$(OBJ) \ + f64_to_ui32$(OBJ) \ + f64_to_ui64$(OBJ) \ + f64_to_i32$(OBJ) \ + f64_to_i64$(OBJ) \ + f64_to_ui32_r_minMag$(OBJ) \ + f64_to_ui64_r_minMag$(OBJ) \ + f64_to_i32_r_minMag$(OBJ) \ + f64_to_i64_r_minMag$(OBJ) \ + f64_to_f32$(OBJ) \ + f64_to_extF80M$(OBJ) \ + f64_to_f128M$(OBJ) \ + f64_roundToInt$(OBJ) \ + f64_add$(OBJ) \ + f64_sub$(OBJ) \ + f64_mul$(OBJ) \ + f64_mulAdd$(OBJ) \ + f64_div$(OBJ) \ + f64_rem$(OBJ) \ + f64_sqrt$(OBJ) \ + f64_eq$(OBJ) \ + f64_le$(OBJ) \ + f64_lt$(OBJ) \ + f64_eq_signaling$(OBJ) \ + f64_le_quiet$(OBJ) \ + f64_lt_quiet$(OBJ) \ + f64_isSignalingNaN$(OBJ) \ + extF80M_to_ui32$(OBJ) \ + extF80M_to_ui64$(OBJ) \ + extF80M_to_i32$(OBJ) \ + extF80M_to_i64$(OBJ) \ + extF80M_to_ui32_r_minMag$(OBJ) \ + extF80M_to_ui64_r_minMag$(OBJ) \ + extF80M_to_i32_r_minMag$(OBJ) \ + extF80M_to_i64_r_minMag$(OBJ) \ + extF80M_to_f32$(OBJ) \ + extF80M_to_f64$(OBJ) \ + extF80M_to_f128M$(OBJ) \ + extF80M_roundToInt$(OBJ) \ + extF80M_add$(OBJ) \ + extF80M_sub$(OBJ) \ + extF80M_mul$(OBJ) \ + extF80M_div$(OBJ) \ + extF80M_rem$(OBJ) \ + extF80M_sqrt$(OBJ) \ + extF80M_eq$(OBJ) \ + extF80M_le$(OBJ) \ + extF80M_lt$(OBJ) \ + extF80M_eq_signaling$(OBJ) \ + extF80M_le_quiet$(OBJ) \ + extF80M_lt_quiet$(OBJ) \ + f128M_to_ui32$(OBJ) \ + f128M_to_ui64$(OBJ) \ + f128M_to_i32$(OBJ) \ + f128M_to_i64$(OBJ) \ + f128M_to_ui32_r_minMag$(OBJ) \ + f128M_to_ui64_r_minMag$(OBJ) \ + f128M_to_i32_r_minMag$(OBJ) \ + f128M_to_i64_r_minMag$(OBJ) \ + f128M_to_f32$(OBJ) \ + f128M_to_f64$(OBJ) \ + f128M_to_extF80M$(OBJ) \ + f128M_roundToInt$(OBJ) \ + f128M_add$(OBJ) \ + f128M_sub$(OBJ) \ + f128M_mul$(OBJ) \ + f128M_mulAdd$(OBJ) \ + f128M_div$(OBJ) \ + f128M_rem$(OBJ) \ + f128M_sqrt$(OBJ) \ + f128M_eq$(OBJ) \ + f128M_le$(OBJ) \ + f128M_lt$(OBJ) \ + f128M_eq_signaling$(OBJ) \ + f128M_le_quiet$(OBJ) \ + f128M_lt_quiet$(OBJ) \ + +OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) + +$(OBJS_ALL): \ + platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ + $(SOURCE_DIR)/include/primitives.h +$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ + $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ + $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/softfloat.h + +$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$*.c + +$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c + +softfloat$(LIB): $(OBJS_ALL) + $(DELETE) $@ + $(MAKELIB) $^ + +.PHONY: clean +clean: + $(DELETE) $(OBJS_ALL) softfloat$(LIB) + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/platform.h new file mode 100644 index 0000000..6121db8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/platform.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define LITTLEENDIAN 1 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define INLINE extern inline + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/Makefile b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/Makefile new file mode 100644 index 0000000..93bc566 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/Makefile @@ -0,0 +1,275 @@ +# SPDX-License-Identifier: BSD-3-Clause + +#============================================================================= +# +# This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic +# Package, Release 3a, by John R. Hauser. +# +# Copyright 2011, 2012, 2013, 2014 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. +# +#============================================================================= + +SOURCE_DIR = ../../source +SPECIALIZE_TYPE = 8086-SSE + +SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 + +DELETE = rm -f +C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +COMPILE_C = \ + gcc -c -Werror-implicit-function-declaration $(SOFTFLOAT_OPTS) \ + $(C_INCLUDES) -O2 -o $@ +MAKELIB = ar crs $@ + +OBJ = .o +LIB = .a + +.PHONY: all +all: softfloat$(LIB) + +OBJS_PRIMITIVES = \ + s_compare96M$(OBJ) \ + s_compare128M$(OBJ) \ + s_shortShiftLeft64To96M$(OBJ) \ + s_shortShiftLeftM$(OBJ) \ + s_shiftLeftM$(OBJ) \ + s_shortShiftRightM$(OBJ) \ + s_shortShiftRightJam64$(OBJ) \ + s_shortShiftRightJamM$(OBJ) \ + s_shiftRightJam32$(OBJ) \ + s_shiftRightJam64$(OBJ) \ + s_shiftRightJamM$(OBJ) \ + s_shiftRightM$(OBJ) \ + s_countLeadingZeros8$(OBJ) \ + s_countLeadingZeros32$(OBJ) \ + s_countLeadingZeros64$(OBJ) \ + s_addM$(OBJ) \ + s_addCarryM$(OBJ) \ + s_addComplCarryM$(OBJ) \ + s_negXM$(OBJ) \ + s_sub1XM$(OBJ) \ + s_subM$(OBJ) \ + s_mul64To128M$(OBJ) \ + s_mul128MTo256M$(OBJ) \ + s_approxRecip32_1$(OBJ) \ + s_approxRecipSqrt32_1$(OBJ) \ + s_remStepMBy32$(OBJ) \ + +OBJS_SPECIALIZE = \ + softfloat_raiseFlags$(OBJ) \ + s_f32UIToCommonNaN$(OBJ) \ + s_commonNaNToF32UI$(OBJ) \ + s_propagateNaNF32UI$(OBJ) \ + s_f64UIToCommonNaN$(OBJ) \ + s_commonNaNToF64UI$(OBJ) \ + s_propagateNaNF64UI$(OBJ) \ + extF80M_isSignalingNaN$(OBJ) \ + s_extF80MToCommonNaN$(OBJ) \ + s_commonNaNToExtF80M$(OBJ) \ + s_propagateNaNExtF80M$(OBJ) \ + f128M_isSignalingNaN$(OBJ) \ + s_f128MToCommonNaN$(OBJ) \ + s_commonNaNToF128M$(OBJ) \ + s_propagateNaNF128M$(OBJ) \ + +OBJS_OTHERS = \ + s_roundPackToUI32$(OBJ) \ + s_roundPackMToUI64$(OBJ) \ + s_roundPackToI32$(OBJ) \ + s_roundPackMToI64$(OBJ) \ + s_normSubnormalF32Sig$(OBJ) \ + s_roundPackToF32$(OBJ) \ + s_normRoundPackToF32$(OBJ) \ + s_addMagsF32$(OBJ) \ + s_subMagsF32$(OBJ) \ + s_mulAddF32$(OBJ) \ + s_normSubnormalF64Sig$(OBJ) \ + s_roundPackToF64$(OBJ) \ + s_normRoundPackToF64$(OBJ) \ + s_addMagsF64$(OBJ) \ + s_subMagsF64$(OBJ) \ + s_mulAddF64$(OBJ) \ + s_tryPropagateNaNExtF80M$(OBJ) \ + s_invalidExtF80M$(OBJ) \ + s_normExtF80SigM$(OBJ) \ + s_roundPackMToExtF80M$(OBJ) \ + s_normRoundPackMToExtF80M$(OBJ) \ + s_addExtF80M$(OBJ) \ + s_compareNonnormExtF80M$(OBJ) \ + s_isNaNF128M$(OBJ) \ + s_tryPropagateNaNF128M$(OBJ) \ + s_invalidF128M$(OBJ) \ + s_shiftNormSigF128M$(OBJ) \ + s_roundPackMToF128M$(OBJ) \ + s_normRoundPackMToF128M$(OBJ) \ + s_addF128M$(OBJ) \ + s_mulAddF128M$(OBJ) \ + softfloat_state$(OBJ) \ + ui32_to_f32$(OBJ) \ + ui32_to_f64$(OBJ) \ + ui32_to_extF80M$(OBJ) \ + ui32_to_f128M$(OBJ) \ + ui64_to_f32$(OBJ) \ + ui64_to_f64$(OBJ) \ + ui64_to_extF80M$(OBJ) \ + ui64_to_f128M$(OBJ) \ + i32_to_f32$(OBJ) \ + i32_to_f64$(OBJ) \ + i32_to_extF80M$(OBJ) \ + i32_to_f128M$(OBJ) \ + i64_to_f32$(OBJ) \ + i64_to_f64$(OBJ) \ + i64_to_extF80M$(OBJ) \ + i64_to_f128M$(OBJ) \ + f32_to_ui32$(OBJ) \ + f32_to_ui64$(OBJ) \ + f32_to_i32$(OBJ) \ + f32_to_i64$(OBJ) \ + f32_to_ui32_r_minMag$(OBJ) \ + f32_to_ui64_r_minMag$(OBJ) \ + f32_to_i32_r_minMag$(OBJ) \ + f32_to_i64_r_minMag$(OBJ) \ + f32_to_f64$(OBJ) \ + f32_to_extF80M$(OBJ) \ + f32_to_f128M$(OBJ) \ + f32_roundToInt$(OBJ) \ + f32_add$(OBJ) \ + f32_sub$(OBJ) \ + f32_mul$(OBJ) \ + f32_mulAdd$(OBJ) \ + f32_div$(OBJ) \ + f32_rem$(OBJ) \ + f32_sqrt$(OBJ) \ + f32_eq$(OBJ) \ + f32_le$(OBJ) \ + f32_lt$(OBJ) \ + f32_eq_signaling$(OBJ) \ + f32_le_quiet$(OBJ) \ + f32_lt_quiet$(OBJ) \ + f32_isSignalingNaN$(OBJ) \ + f64_to_ui32$(OBJ) \ + f64_to_ui64$(OBJ) \ + f64_to_i32$(OBJ) \ + f64_to_i64$(OBJ) \ + f64_to_ui32_r_minMag$(OBJ) \ + f64_to_ui64_r_minMag$(OBJ) \ + f64_to_i32_r_minMag$(OBJ) \ + f64_to_i64_r_minMag$(OBJ) \ + f64_to_f32$(OBJ) \ + f64_to_extF80M$(OBJ) \ + f64_to_f128M$(OBJ) \ + f64_roundToInt$(OBJ) \ + f64_add$(OBJ) \ + f64_sub$(OBJ) \ + f64_mul$(OBJ) \ + f64_mulAdd$(OBJ) \ + f64_div$(OBJ) \ + f64_rem$(OBJ) \ + f64_sqrt$(OBJ) \ + f64_eq$(OBJ) \ + f64_le$(OBJ) \ + f64_lt$(OBJ) \ + f64_eq_signaling$(OBJ) \ + f64_le_quiet$(OBJ) \ + f64_lt_quiet$(OBJ) \ + f64_isSignalingNaN$(OBJ) \ + extF80M_to_ui32$(OBJ) \ + extF80M_to_ui64$(OBJ) \ + extF80M_to_i32$(OBJ) \ + extF80M_to_i64$(OBJ) \ + extF80M_to_ui32_r_minMag$(OBJ) \ + extF80M_to_ui64_r_minMag$(OBJ) \ + extF80M_to_i32_r_minMag$(OBJ) \ + extF80M_to_i64_r_minMag$(OBJ) \ + extF80M_to_f32$(OBJ) \ + extF80M_to_f64$(OBJ) \ + extF80M_to_f128M$(OBJ) \ + extF80M_roundToInt$(OBJ) \ + extF80M_add$(OBJ) \ + extF80M_sub$(OBJ) \ + extF80M_mul$(OBJ) \ + extF80M_div$(OBJ) \ + extF80M_rem$(OBJ) \ + extF80M_sqrt$(OBJ) \ + extF80M_eq$(OBJ) \ + extF80M_le$(OBJ) \ + extF80M_lt$(OBJ) \ + extF80M_eq_signaling$(OBJ) \ + extF80M_le_quiet$(OBJ) \ + extF80M_lt_quiet$(OBJ) \ + f128M_to_ui32$(OBJ) \ + f128M_to_ui64$(OBJ) \ + f128M_to_i32$(OBJ) \ + f128M_to_i64$(OBJ) \ + f128M_to_ui32_r_minMag$(OBJ) \ + f128M_to_ui64_r_minMag$(OBJ) \ + f128M_to_i32_r_minMag$(OBJ) \ + f128M_to_i64_r_minMag$(OBJ) \ + f128M_to_f32$(OBJ) \ + f128M_to_f64$(OBJ) \ + f128M_to_extF80M$(OBJ) \ + f128M_roundToInt$(OBJ) \ + f128M_add$(OBJ) \ + f128M_sub$(OBJ) \ + f128M_mul$(OBJ) \ + f128M_mulAdd$(OBJ) \ + f128M_div$(OBJ) \ + f128M_rem$(OBJ) \ + f128M_sqrt$(OBJ) \ + f128M_eq$(OBJ) \ + f128M_le$(OBJ) \ + f128M_lt$(OBJ) \ + f128M_eq_signaling$(OBJ) \ + f128M_le_quiet$(OBJ) \ + f128M_lt_quiet$(OBJ) \ + +OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) + +$(OBJS_ALL): \ + platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ + $(SOURCE_DIR)/include/primitives.h +$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ + $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ + $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/softfloat.h + +$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$*.c + +$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c + +softfloat$(LIB): $(OBJS_ALL) + $(DELETE) $@ + $(MAKELIB) $^ + +.PHONY: clean +clean: + $(DELETE) $(OBJS_ALL) softfloat$(LIB) + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/platform.h new file mode 100644 index 0000000..6121db8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/platform.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define LITTLEENDIAN 1 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define INLINE extern inline + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/Makefile b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/Makefile new file mode 100644 index 0000000..ac16ed9 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/Makefile @@ -0,0 +1,336 @@ +# SPDX-License-Identifier: BSD-3-Clause + +#============================================================================= +# +# This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic +# Package, Release 3a, by John R. Hauser. +# +# Copyright 2011, 2012, 2013, 2014 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. +# +#============================================================================= + +SOURCE_DIR = ../../source +SPECIALIZE_TYPE = 8086-SSE + +SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 + +DELETE = rm -f +C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +COMPILE_C = \ + x86_64-w64-mingw32-gcc -c -Werror-implicit-function-declaration \ + -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@ +MAKELIB = x86_64-w64-mingw32-ar crs $@ + +OBJ = .o +LIB = .a + +.PHONY: all +all: softfloat$(LIB) + +OBJS_PRIMITIVES = \ + s_eq128$(OBJ) \ + s_le128$(OBJ) \ + s_lt128$(OBJ) \ + s_shortShiftLeft128$(OBJ) \ + s_shortShiftRight128$(OBJ) \ + s_shortShiftRightJam64$(OBJ) \ + s_shortShiftRightJam64Extra$(OBJ) \ + s_shortShiftRightJam128$(OBJ) \ + s_shortShiftRightJam128Extra$(OBJ) \ + s_shiftRightJam32$(OBJ) \ + s_shiftRightJam64$(OBJ) \ + s_shiftRightJam64Extra$(OBJ) \ + s_shiftRightJam128$(OBJ) \ + s_shiftRightJam128Extra$(OBJ) \ + s_shiftRightJam256M$(OBJ) \ + s_countLeadingZeros8$(OBJ) \ + s_countLeadingZeros32$(OBJ) \ + s_countLeadingZeros64$(OBJ) \ + s_add128$(OBJ) \ + s_add256M$(OBJ) \ + s_sub128$(OBJ) \ + s_sub256M$(OBJ) \ + s_mul64ByShifted32To128$(OBJ) \ + s_mul64To128$(OBJ) \ + s_mul128By32$(OBJ) \ + s_mul128To256M$(OBJ) \ + s_approxRecip32_1$(OBJ) \ + s_approxRecipSqrt32_1$(OBJ) \ + +OBJS_SPECIALIZE = \ + softfloat_raiseFlags$(OBJ) \ + s_f32UIToCommonNaN$(OBJ) \ + s_commonNaNToF32UI$(OBJ) \ + s_propagateNaNF32UI$(OBJ) \ + s_f64UIToCommonNaN$(OBJ) \ + s_commonNaNToF64UI$(OBJ) \ + s_propagateNaNF64UI$(OBJ) \ + extF80M_isSignalingNaN$(OBJ) \ + s_extF80UIToCommonNaN$(OBJ) \ + s_commonNaNToExtF80UI$(OBJ) \ + s_propagateNaNExtF80UI$(OBJ) \ + f128M_isSignalingNaN$(OBJ) \ + s_f128UIToCommonNaN$(OBJ) \ + s_commonNaNToF128UI$(OBJ) \ + s_propagateNaNF128UI$(OBJ) \ + +OBJS_OTHERS = \ + s_roundPackToUI32$(OBJ) \ + s_roundPackToUI64$(OBJ) \ + s_roundPackToI32$(OBJ) \ + s_roundPackToI64$(OBJ) \ + s_normSubnormalF32Sig$(OBJ) \ + s_roundPackToF32$(OBJ) \ + s_normRoundPackToF32$(OBJ) \ + s_addMagsF32$(OBJ) \ + s_subMagsF32$(OBJ) \ + s_mulAddF32$(OBJ) \ + s_normSubnormalF64Sig$(OBJ) \ + s_roundPackToF64$(OBJ) \ + s_normRoundPackToF64$(OBJ) \ + s_addMagsF64$(OBJ) \ + s_subMagsF64$(OBJ) \ + s_mulAddF64$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_roundPackToExtF80$(OBJ) \ + s_normRoundPackToExtF80$(OBJ) \ + s_addMagsExtF80$(OBJ) \ + s_subMagsExtF80$(OBJ) \ + s_normSubnormalF128Sig$(OBJ) \ + s_roundPackToF128$(OBJ) \ + s_normRoundPackToF128$(OBJ) \ + s_addMagsF128$(OBJ) \ + s_subMagsF128$(OBJ) \ + s_mulAddF128$(OBJ) \ + softfloat_state$(OBJ) \ + ui32_to_f32$(OBJ) \ + ui32_to_f64$(OBJ) \ + ui32_to_extF80$(OBJ) \ + ui32_to_extF80M$(OBJ) \ + ui32_to_f128$(OBJ) \ + ui32_to_f128M$(OBJ) \ + ui64_to_f32$(OBJ) \ + ui64_to_f64$(OBJ) \ + ui64_to_extF80$(OBJ) \ + ui64_to_extF80M$(OBJ) \ + ui64_to_f128$(OBJ) \ + ui64_to_f128M$(OBJ) \ + i32_to_f32$(OBJ) \ + i32_to_f64$(OBJ) \ + i32_to_extF80$(OBJ) \ + i32_to_extF80M$(OBJ) \ + i32_to_f128$(OBJ) \ + i32_to_f128M$(OBJ) \ + i64_to_f32$(OBJ) \ + i64_to_f64$(OBJ) \ + i64_to_extF80$(OBJ) \ + i64_to_extF80M$(OBJ) \ + i64_to_f128$(OBJ) \ + i64_to_f128M$(OBJ) \ + f32_to_ui32$(OBJ) \ + f32_to_ui64$(OBJ) \ + f32_to_i32$(OBJ) \ + f32_to_i64$(OBJ) \ + f32_to_ui32_r_minMag$(OBJ) \ + f32_to_ui64_r_minMag$(OBJ) \ + f32_to_i32_r_minMag$(OBJ) \ + f32_to_i64_r_minMag$(OBJ) \ + f32_to_f64$(OBJ) \ + f32_to_extF80$(OBJ) \ + f32_to_extF80M$(OBJ) \ + f32_to_f128$(OBJ) \ + f32_to_f128M$(OBJ) \ + f32_roundToInt$(OBJ) \ + f32_add$(OBJ) \ + f32_sub$(OBJ) \ + f32_mul$(OBJ) \ + f32_mulAdd$(OBJ) \ + f32_div$(OBJ) \ + f32_rem$(OBJ) \ + f32_sqrt$(OBJ) \ + f32_eq$(OBJ) \ + f32_le$(OBJ) \ + f32_lt$(OBJ) \ + f32_eq_signaling$(OBJ) \ + f32_le_quiet$(OBJ) \ + f32_lt_quiet$(OBJ) \ + f32_isSignalingNaN$(OBJ) \ + f64_to_ui32$(OBJ) \ + f64_to_ui64$(OBJ) \ + f64_to_i32$(OBJ) \ + f64_to_i64$(OBJ) \ + f64_to_ui32_r_minMag$(OBJ) \ + f64_to_ui64_r_minMag$(OBJ) \ + f64_to_i32_r_minMag$(OBJ) \ + f64_to_i64_r_minMag$(OBJ) \ + f64_to_f32$(OBJ) \ + f64_to_extF80$(OBJ) \ + f64_to_extF80M$(OBJ) \ + f64_to_f128$(OBJ) \ + f64_to_f128M$(OBJ) \ + f64_roundToInt$(OBJ) \ + f64_add$(OBJ) \ + f64_sub$(OBJ) \ + f64_mul$(OBJ) \ + f64_mulAdd$(OBJ) \ + f64_div$(OBJ) \ + f64_rem$(OBJ) \ + f64_sqrt$(OBJ) \ + f64_eq$(OBJ) \ + f64_le$(OBJ) \ + f64_lt$(OBJ) \ + f64_eq_signaling$(OBJ) \ + f64_le_quiet$(OBJ) \ + f64_lt_quiet$(OBJ) \ + f64_isSignalingNaN$(OBJ) \ + extF80_to_ui32$(OBJ) \ + extF80_to_ui64$(OBJ) \ + extF80_to_i32$(OBJ) \ + extF80_to_i64$(OBJ) \ + extF80_to_ui32_r_minMag$(OBJ) \ + extF80_to_ui64_r_minMag$(OBJ) \ + extF80_to_i32_r_minMag$(OBJ) \ + extF80_to_i64_r_minMag$(OBJ) \ + extF80_to_f32$(OBJ) \ + extF80_to_f64$(OBJ) \ + extF80_to_f128$(OBJ) \ + extF80_roundToInt$(OBJ) \ + extF80_add$(OBJ) \ + extF80_sub$(OBJ) \ + extF80_mul$(OBJ) \ + extF80_div$(OBJ) \ + extF80_rem$(OBJ) \ + extF80_sqrt$(OBJ) \ + extF80_eq$(OBJ) \ + extF80_le$(OBJ) \ + extF80_lt$(OBJ) \ + extF80_eq_signaling$(OBJ) \ + extF80_le_quiet$(OBJ) \ + extF80_lt_quiet$(OBJ) \ + extF80_isSignalingNaN$(OBJ) \ + extF80M_to_ui32$(OBJ) \ + extF80M_to_ui64$(OBJ) \ + extF80M_to_i32$(OBJ) \ + extF80M_to_i64$(OBJ) \ + extF80M_to_ui32_r_minMag$(OBJ) \ + extF80M_to_ui64_r_minMag$(OBJ) \ + extF80M_to_i32_r_minMag$(OBJ) \ + extF80M_to_i64_r_minMag$(OBJ) \ + extF80M_to_f32$(OBJ) \ + extF80M_to_f64$(OBJ) \ + extF80M_to_f128M$(OBJ) \ + extF80M_roundToInt$(OBJ) \ + extF80M_add$(OBJ) \ + extF80M_sub$(OBJ) \ + extF80M_mul$(OBJ) \ + extF80M_div$(OBJ) \ + extF80M_rem$(OBJ) \ + extF80M_sqrt$(OBJ) \ + extF80M_eq$(OBJ) \ + extF80M_le$(OBJ) \ + extF80M_lt$(OBJ) \ + extF80M_eq_signaling$(OBJ) \ + extF80M_le_quiet$(OBJ) \ + extF80M_lt_quiet$(OBJ) \ + f128_to_ui32$(OBJ) \ + f128_to_ui64$(OBJ) \ + f128_to_i32$(OBJ) \ + f128_to_i64$(OBJ) \ + f128_to_ui32_r_minMag$(OBJ) \ + f128_to_ui64_r_minMag$(OBJ) \ + f128_to_i32_r_minMag$(OBJ) \ + f128_to_i64_r_minMag$(OBJ) \ + f128_to_f32$(OBJ) \ + f128_to_extF80$(OBJ) \ + f128_to_f64$(OBJ) \ + f128_roundToInt$(OBJ) \ + f128_add$(OBJ) \ + f128_sub$(OBJ) \ + f128_mul$(OBJ) \ + f128_mulAdd$(OBJ) \ + f128_div$(OBJ) \ + f128_rem$(OBJ) \ + f128_sqrt$(OBJ) \ + f128_eq$(OBJ) \ + f128_le$(OBJ) \ + f128_lt$(OBJ) \ + f128_eq_signaling$(OBJ) \ + f128_le_quiet$(OBJ) \ + f128_lt_quiet$(OBJ) \ + f128_isSignalingNaN$(OBJ) \ + f128M_to_ui32$(OBJ) \ + f128M_to_ui64$(OBJ) \ + f128M_to_i32$(OBJ) \ + f128M_to_i64$(OBJ) \ + f128M_to_ui32_r_minMag$(OBJ) \ + f128M_to_ui64_r_minMag$(OBJ) \ + f128M_to_i32_r_minMag$(OBJ) \ + f128M_to_i64_r_minMag$(OBJ) \ + f128M_to_f32$(OBJ) \ + f128M_to_extF80M$(OBJ) \ + f128M_to_f64$(OBJ) \ + f128M_roundToInt$(OBJ) \ + f128M_add$(OBJ) \ + f128M_sub$(OBJ) \ + f128M_mul$(OBJ) \ + f128M_mulAdd$(OBJ) \ + f128M_div$(OBJ) \ + f128M_rem$(OBJ) \ + f128M_sqrt$(OBJ) \ + f128M_eq$(OBJ) \ + f128M_le$(OBJ) \ + f128M_lt$(OBJ) \ + f128M_eq_signaling$(OBJ) \ + f128M_le_quiet$(OBJ) \ + f128M_lt_quiet$(OBJ) \ + +OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) + +$(OBJS_ALL): \ + platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ + $(SOURCE_DIR)/include/primitives.h +$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ + $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ + $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/softfloat.h + +$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$*.c + +$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c + +softfloat$(LIB): $(OBJS_ALL) + $(DELETE) $@ + $(MAKELIB) $^ + +.PHONY: clean +clean: + $(DELETE) $(OBJS_ALL) softfloat$(LIB) + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/platform.h new file mode 100644 index 0000000..6121db8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/platform.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define LITTLEENDIAN 1 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define INLINE extern inline + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/Makefile b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/Makefile new file mode 100644 index 0000000..5be1ca0 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/Makefile @@ -0,0 +1,337 @@ +# SPDX-License-Identifier: BSD-3-Clause + +#============================================================================= +# +# This Makefile template is part of the SoftFloat IEEE Floating-Point +# Arithmetic Package, Release 3a, by John R. Hauser. +# +# Copyright 2011, 2012, 2013, 2014 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. +# +#============================================================================= + +# Edit lines marked with `==>'. See "SoftFloat-source.html". + +==> SOURCE_DIR = ../../source +==> SPECIALIZE_TYPE = 8086 + +==> SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 + +==> DELETE = rm -f +==> C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +==> COMPILE_C = \ +==> cc -c -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@ +==> MAKELIB = ar crs $@ + +==> OBJ = .o +==> LIB = .a + +.PHONY: all +all: softfloat$(LIB) + +OBJS_PRIMITIVES = \ + s_eq128$(OBJ) \ + s_le128$(OBJ) \ + s_lt128$(OBJ) \ + s_shortShiftLeft128$(OBJ) \ + s_shortShiftRight128$(OBJ) \ + s_shortShiftRightJam64$(OBJ) \ + s_shortShiftRightJam64Extra$(OBJ) \ + s_shortShiftRightJam128$(OBJ) \ + s_shortShiftRightJam128Extra$(OBJ) \ + s_shiftRightJam32$(OBJ) \ + s_shiftRightJam64$(OBJ) \ + s_shiftRightJam64Extra$(OBJ) \ + s_shiftRightJam128$(OBJ) \ + s_shiftRightJam128Extra$(OBJ) \ + s_shiftRightJam256M$(OBJ) \ + s_countLeadingZeros8$(OBJ) \ + s_countLeadingZeros32$(OBJ) \ + s_countLeadingZeros64$(OBJ) \ + s_add128$(OBJ) \ + s_add256M$(OBJ) \ + s_sub128$(OBJ) \ + s_sub256M$(OBJ) \ + s_mul64ByShifted32To128$(OBJ) \ + s_mul64To128$(OBJ) \ + s_mul128By32$(OBJ) \ + s_mul128To256M$(OBJ) \ + s_approxRecip32_1$(OBJ) \ + s_approxRecipSqrt32_1$(OBJ) \ + +OBJS_SPECIALIZE = \ + softfloat_raiseFlags$(OBJ) \ + s_f32UIToCommonNaN$(OBJ) \ + s_commonNaNToF32UI$(OBJ) \ + s_propagateNaNF32UI$(OBJ) \ + s_f64UIToCommonNaN$(OBJ) \ + s_commonNaNToF64UI$(OBJ) \ + s_propagateNaNF64UI$(OBJ) \ + extF80M_isSignalingNaN$(OBJ) \ + s_extF80UIToCommonNaN$(OBJ) \ + s_commonNaNToExtF80UI$(OBJ) \ + s_propagateNaNExtF80UI$(OBJ) \ + f128M_isSignalingNaN$(OBJ) \ + s_f128UIToCommonNaN$(OBJ) \ + s_commonNaNToF128UI$(OBJ) \ + s_propagateNaNF128UI$(OBJ) \ + +OBJS_OTHERS = \ + s_roundPackToUI32$(OBJ) \ + s_roundPackToUI64$(OBJ) \ + s_roundPackToI32$(OBJ) \ + s_roundPackToI64$(OBJ) \ + s_normSubnormalF32Sig$(OBJ) \ + s_roundPackToF32$(OBJ) \ + s_normRoundPackToF32$(OBJ) \ + s_addMagsF32$(OBJ) \ + s_subMagsF32$(OBJ) \ + s_mulAddF32$(OBJ) \ + s_normSubnormalF64Sig$(OBJ) \ + s_roundPackToF64$(OBJ) \ + s_normRoundPackToF64$(OBJ) \ + s_addMagsF64$(OBJ) \ + s_subMagsF64$(OBJ) \ + s_mulAddF64$(OBJ) \ + s_normSubnormalExtF80Sig$(OBJ) \ + s_roundPackToExtF80$(OBJ) \ + s_normRoundPackToExtF80$(OBJ) \ + s_addMagsExtF80$(OBJ) \ + s_subMagsExtF80$(OBJ) \ + s_normSubnormalF128Sig$(OBJ) \ + s_roundPackToF128$(OBJ) \ + s_normRoundPackToF128$(OBJ) \ + s_addMagsF128$(OBJ) \ + s_subMagsF128$(OBJ) \ + s_mulAddF128$(OBJ) \ + softfloat_state$(OBJ) \ + ui32_to_f32$(OBJ) \ + ui32_to_f64$(OBJ) \ + ui32_to_extF80$(OBJ) \ + ui32_to_extF80M$(OBJ) \ + ui32_to_f128$(OBJ) \ + ui32_to_f128M$(OBJ) \ + ui64_to_f32$(OBJ) \ + ui64_to_f64$(OBJ) \ + ui64_to_extF80$(OBJ) \ + ui64_to_extF80M$(OBJ) \ + ui64_to_f128$(OBJ) \ + ui64_to_f128M$(OBJ) \ + i32_to_f32$(OBJ) \ + i32_to_f64$(OBJ) \ + i32_to_extF80$(OBJ) \ + i32_to_extF80M$(OBJ) \ + i32_to_f128$(OBJ) \ + i32_to_f128M$(OBJ) \ + i64_to_f32$(OBJ) \ + i64_to_f64$(OBJ) \ + i64_to_extF80$(OBJ) \ + i64_to_extF80M$(OBJ) \ + i64_to_f128$(OBJ) \ + i64_to_f128M$(OBJ) \ + f32_to_ui32$(OBJ) \ + f32_to_ui64$(OBJ) \ + f32_to_i32$(OBJ) \ + f32_to_i64$(OBJ) \ + f32_to_ui32_r_minMag$(OBJ) \ + f32_to_ui64_r_minMag$(OBJ) \ + f32_to_i32_r_minMag$(OBJ) \ + f32_to_i64_r_minMag$(OBJ) \ + f32_to_f64$(OBJ) \ + f32_to_extF80$(OBJ) \ + f32_to_extF80M$(OBJ) \ + f32_to_f128$(OBJ) \ + f32_to_f128M$(OBJ) \ + f32_roundToInt$(OBJ) \ + f32_add$(OBJ) \ + f32_sub$(OBJ) \ + f32_mul$(OBJ) \ + f32_mulAdd$(OBJ) \ + f32_div$(OBJ) \ + f32_rem$(OBJ) \ + f32_sqrt$(OBJ) \ + f32_eq$(OBJ) \ + f32_le$(OBJ) \ + f32_lt$(OBJ) \ + f32_eq_signaling$(OBJ) \ + f32_le_quiet$(OBJ) \ + f32_lt_quiet$(OBJ) \ + f32_isSignalingNaN$(OBJ) \ + f64_to_ui32$(OBJ) \ + f64_to_ui64$(OBJ) \ + f64_to_i32$(OBJ) \ + f64_to_i64$(OBJ) \ + f64_to_ui32_r_minMag$(OBJ) \ + f64_to_ui64_r_minMag$(OBJ) \ + f64_to_i32_r_minMag$(OBJ) \ + f64_to_i64_r_minMag$(OBJ) \ + f64_to_f32$(OBJ) \ + f64_to_extF80$(OBJ) \ + f64_to_extF80M$(OBJ) \ + f64_to_f128$(OBJ) \ + f64_to_f128M$(OBJ) \ + f64_roundToInt$(OBJ) \ + f64_add$(OBJ) \ + f64_sub$(OBJ) \ + f64_mul$(OBJ) \ + f64_mulAdd$(OBJ) \ + f64_div$(OBJ) \ + f64_rem$(OBJ) \ + f64_sqrt$(OBJ) \ + f64_eq$(OBJ) \ + f64_le$(OBJ) \ + f64_lt$(OBJ) \ + f64_eq_signaling$(OBJ) \ + f64_le_quiet$(OBJ) \ + f64_lt_quiet$(OBJ) \ + f64_isSignalingNaN$(OBJ) \ + extF80_to_ui32$(OBJ) \ + extF80_to_ui64$(OBJ) \ + extF80_to_i32$(OBJ) \ + extF80_to_i64$(OBJ) \ + extF80_to_ui32_r_minMag$(OBJ) \ + extF80_to_ui64_r_minMag$(OBJ) \ + extF80_to_i32_r_minMag$(OBJ) \ + extF80_to_i64_r_minMag$(OBJ) \ + extF80_to_f32$(OBJ) \ + extF80_to_f64$(OBJ) \ + extF80_to_f128$(OBJ) \ + extF80_roundToInt$(OBJ) \ + extF80_add$(OBJ) \ + extF80_sub$(OBJ) \ + extF80_mul$(OBJ) \ + extF80_div$(OBJ) \ + extF80_rem$(OBJ) \ + extF80_sqrt$(OBJ) \ + extF80_eq$(OBJ) \ + extF80_le$(OBJ) \ + extF80_lt$(OBJ) \ + extF80_eq_signaling$(OBJ) \ + extF80_le_quiet$(OBJ) \ + extF80_lt_quiet$(OBJ) \ + extF80_isSignalingNaN$(OBJ) \ + extF80M_to_ui32$(OBJ) \ + extF80M_to_ui64$(OBJ) \ + extF80M_to_i32$(OBJ) \ + extF80M_to_i64$(OBJ) \ + extF80M_to_ui32_r_minMag$(OBJ) \ + extF80M_to_ui64_r_minMag$(OBJ) \ + extF80M_to_i32_r_minMag$(OBJ) \ + extF80M_to_i64_r_minMag$(OBJ) \ + extF80M_to_f32$(OBJ) \ + extF80M_to_f64$(OBJ) \ + extF80M_to_f128M$(OBJ) \ + extF80M_roundToInt$(OBJ) \ + extF80M_add$(OBJ) \ + extF80M_sub$(OBJ) \ + extF80M_mul$(OBJ) \ + extF80M_div$(OBJ) \ + extF80M_rem$(OBJ) \ + extF80M_sqrt$(OBJ) \ + extF80M_eq$(OBJ) \ + extF80M_le$(OBJ) \ + extF80M_lt$(OBJ) \ + extF80M_eq_signaling$(OBJ) \ + extF80M_le_quiet$(OBJ) \ + extF80M_lt_quiet$(OBJ) \ + f128_to_ui32$(OBJ) \ + f128_to_ui64$(OBJ) \ + f128_to_i32$(OBJ) \ + f128_to_i64$(OBJ) \ + f128_to_ui32_r_minMag$(OBJ) \ + f128_to_ui64_r_minMag$(OBJ) \ + f128_to_i32_r_minMag$(OBJ) \ + f128_to_i64_r_minMag$(OBJ) \ + f128_to_f32$(OBJ) \ + f128_to_extF80$(OBJ) \ + f128_to_f64$(OBJ) \ + f128_roundToInt$(OBJ) \ + f128_add$(OBJ) \ + f128_sub$(OBJ) \ + f128_mul$(OBJ) \ + f128_mulAdd$(OBJ) \ + f128_div$(OBJ) \ + f128_rem$(OBJ) \ + f128_sqrt$(OBJ) \ + f128_eq$(OBJ) \ + f128_le$(OBJ) \ + f128_lt$(OBJ) \ + f128_eq_signaling$(OBJ) \ + f128_le_quiet$(OBJ) \ + f128_lt_quiet$(OBJ) \ + f128_isSignalingNaN$(OBJ) \ + f128M_to_ui32$(OBJ) \ + f128M_to_ui64$(OBJ) \ + f128M_to_i32$(OBJ) \ + f128M_to_i64$(OBJ) \ + f128M_to_ui32_r_minMag$(OBJ) \ + f128M_to_ui64_r_minMag$(OBJ) \ + f128M_to_i32_r_minMag$(OBJ) \ + f128M_to_i64_r_minMag$(OBJ) \ + f128M_to_f32$(OBJ) \ + f128M_to_extF80M$(OBJ) \ + f128M_to_f64$(OBJ) \ + f128M_roundToInt$(OBJ) \ + f128M_add$(OBJ) \ + f128M_sub$(OBJ) \ + f128M_mul$(OBJ) \ + f128M_mulAdd$(OBJ) \ + f128M_div$(OBJ) \ + f128M_rem$(OBJ) \ + f128M_sqrt$(OBJ) \ + f128M_eq$(OBJ) \ + f128M_le$(OBJ) \ + f128M_lt$(OBJ) \ + f128M_eq_signaling$(OBJ) \ + f128M_le_quiet$(OBJ) \ + f128M_lt_quiet$(OBJ) \ + +OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) + +$(OBJS_ALL): \ + platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ + $(SOURCE_DIR)/include/primitives.h +$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ + $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ + $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/softfloat.h + +$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$*.c + +$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c + +softfloat$(LIB): $(OBJS_ALL) + $(DELETE) $@ + $(MAKELIB) $^ + +.PHONY: clean +clean: + $(DELETE) $(OBJS_ALL) softfloat$(LIB) + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/platform.h new file mode 100644 index 0000000..cea3332 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/platform.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header template is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +// Edit lines marked with `==>'. See "SoftFloat-source.html". + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +==> #define LITTLEENDIAN 1 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +==> #define INLINE inline + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/Makefile b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/Makefile new file mode 100644 index 0000000..e827222 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/Makefile @@ -0,0 +1,275 @@ +# SPDX-License-Identifier: BSD-3-Clause + +#============================================================================= +# +# This Makefile template is part of the SoftFloat IEEE Floating-Point +# Arithmetic Package, Release 3a, by John R. Hauser. +# +# Copyright 2011, 2012, 2013, 2014 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. +# +#============================================================================= + +# Edit lines marked with `==>'. See "SoftFloat-source.html". + +==> SOURCE_DIR = ../../source +==> SPECIALIZE_TYPE = 8086 + +==> SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 + +==> DELETE = rm -f +==> C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include +==> COMPILE_C = cc -c $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@ +==> MAKELIB = ar crs $@ + +==> OBJ = .o +==> LIB = .a + +.PHONY: all +all: softfloat$(LIB) + +OBJS_PRIMITIVES = \ + s_compare96M$(OBJ) \ + s_compare128M$(OBJ) \ + s_shortShiftLeft64To96M$(OBJ) \ + s_shortShiftLeftM$(OBJ) \ + s_shiftLeftM$(OBJ) \ + s_shortShiftRightM$(OBJ) \ + s_shortShiftRightJam64$(OBJ) \ + s_shortShiftRightJamM$(OBJ) \ + s_shiftRightJam32$(OBJ) \ + s_shiftRightJam64$(OBJ) \ + s_shiftRightJamM$(OBJ) \ + s_shiftRightM$(OBJ) \ + s_countLeadingZeros8$(OBJ) \ + s_countLeadingZeros32$(OBJ) \ + s_countLeadingZeros64$(OBJ) \ + s_addM$(OBJ) \ + s_addCarryM$(OBJ) \ + s_addComplCarryM$(OBJ) \ + s_negXM$(OBJ) \ + s_sub1XM$(OBJ) \ + s_subM$(OBJ) \ + s_mul64To128M$(OBJ) \ + s_mul128MTo256M$(OBJ) \ + s_approxRecip32_1$(OBJ) \ + s_approxRecipSqrt32_1$(OBJ) \ + s_remStepMBy32$(OBJ) \ + +OBJS_SPECIALIZE = \ + softfloat_raiseFlags$(OBJ) \ + s_f32UIToCommonNaN$(OBJ) \ + s_commonNaNToF32UI$(OBJ) \ + s_propagateNaNF32UI$(OBJ) \ + s_f64UIToCommonNaN$(OBJ) \ + s_commonNaNToF64UI$(OBJ) \ + s_propagateNaNF64UI$(OBJ) \ + extF80M_isSignalingNaN$(OBJ) \ + s_extF80MToCommonNaN$(OBJ) \ + s_commonNaNToExtF80M$(OBJ) \ + s_propagateNaNExtF80M$(OBJ) \ + f128M_isSignalingNaN$(OBJ) \ + s_f128MToCommonNaN$(OBJ) \ + s_commonNaNToF128M$(OBJ) \ + s_propagateNaNF128M$(OBJ) \ + +OBJS_OTHERS = \ + s_roundPackToUI32$(OBJ) \ + s_roundPackMToUI64$(OBJ) \ + s_roundPackToI32$(OBJ) \ + s_roundPackMToI64$(OBJ) \ + s_normSubnormalF32Sig$(OBJ) \ + s_roundPackToF32$(OBJ) \ + s_normRoundPackToF32$(OBJ) \ + s_addMagsF32$(OBJ) \ + s_subMagsF32$(OBJ) \ + s_mulAddF32$(OBJ) \ + s_normSubnormalF64Sig$(OBJ) \ + s_roundPackToF64$(OBJ) \ + s_normRoundPackToF64$(OBJ) \ + s_addMagsF64$(OBJ) \ + s_subMagsF64$(OBJ) \ + s_mulAddF64$(OBJ) \ + s_tryPropagateNaNExtF80M$(OBJ) \ + s_invalidExtF80M$(OBJ) \ + s_normExtF80SigM$(OBJ) \ + s_roundPackMToExtF80M$(OBJ) \ + s_normRoundPackMToExtF80M$(OBJ) \ + s_addExtF80M$(OBJ) \ + s_compareNonnormExtF80M$(OBJ) \ + s_isNaNF128M$(OBJ) \ + s_tryPropagateNaNF128M$(OBJ) \ + s_invalidF128M$(OBJ) \ + s_shiftNormSigF128M$(OBJ) \ + s_roundPackMToF128M$(OBJ) \ + s_normRoundPackMToF128M$(OBJ) \ + s_addF128M$(OBJ) \ + s_mulAddF128M$(OBJ) \ + softfloat_state$(OBJ) \ + ui32_to_f32$(OBJ) \ + ui32_to_f64$(OBJ) \ + ui32_to_extF80M$(OBJ) \ + ui32_to_f128M$(OBJ) \ + ui64_to_f32$(OBJ) \ + ui64_to_f64$(OBJ) \ + ui64_to_extF80M$(OBJ) \ + ui64_to_f128M$(OBJ) \ + i32_to_f32$(OBJ) \ + i32_to_f64$(OBJ) \ + i32_to_extF80M$(OBJ) \ + i32_to_f128M$(OBJ) \ + i64_to_f32$(OBJ) \ + i64_to_f64$(OBJ) \ + i64_to_extF80M$(OBJ) \ + i64_to_f128M$(OBJ) \ + f32_to_ui32$(OBJ) \ + f32_to_ui64$(OBJ) \ + f32_to_i32$(OBJ) \ + f32_to_i64$(OBJ) \ + f32_to_ui32_r_minMag$(OBJ) \ + f32_to_ui64_r_minMag$(OBJ) \ + f32_to_i32_r_minMag$(OBJ) \ + f32_to_i64_r_minMag$(OBJ) \ + f32_to_f64$(OBJ) \ + f32_to_extF80M$(OBJ) \ + f32_to_f128M$(OBJ) \ + f32_roundToInt$(OBJ) \ + f32_add$(OBJ) \ + f32_sub$(OBJ) \ + f32_mul$(OBJ) \ + f32_mulAdd$(OBJ) \ + f32_div$(OBJ) \ + f32_rem$(OBJ) \ + f32_sqrt$(OBJ) \ + f32_eq$(OBJ) \ + f32_le$(OBJ) \ + f32_lt$(OBJ) \ + f32_eq_signaling$(OBJ) \ + f32_le_quiet$(OBJ) \ + f32_lt_quiet$(OBJ) \ + f32_isSignalingNaN$(OBJ) \ + f64_to_ui32$(OBJ) \ + f64_to_ui64$(OBJ) \ + f64_to_i32$(OBJ) \ + f64_to_i64$(OBJ) \ + f64_to_ui32_r_minMag$(OBJ) \ + f64_to_ui64_r_minMag$(OBJ) \ + f64_to_i32_r_minMag$(OBJ) \ + f64_to_i64_r_minMag$(OBJ) \ + f64_to_f32$(OBJ) \ + f64_to_extF80M$(OBJ) \ + f64_to_f128M$(OBJ) \ + f64_roundToInt$(OBJ) \ + f64_add$(OBJ) \ + f64_sub$(OBJ) \ + f64_mul$(OBJ) \ + f64_mulAdd$(OBJ) \ + f64_div$(OBJ) \ + f64_rem$(OBJ) \ + f64_sqrt$(OBJ) \ + f64_eq$(OBJ) \ + f64_le$(OBJ) \ + f64_lt$(OBJ) \ + f64_eq_signaling$(OBJ) \ + f64_le_quiet$(OBJ) \ + f64_lt_quiet$(OBJ) \ + f64_isSignalingNaN$(OBJ) \ + extF80M_to_ui32$(OBJ) \ + extF80M_to_ui64$(OBJ) \ + extF80M_to_i32$(OBJ) \ + extF80M_to_i64$(OBJ) \ + extF80M_to_ui32_r_minMag$(OBJ) \ + extF80M_to_ui64_r_minMag$(OBJ) \ + extF80M_to_i32_r_minMag$(OBJ) \ + extF80M_to_i64_r_minMag$(OBJ) \ + extF80M_to_f32$(OBJ) \ + extF80M_to_f64$(OBJ) \ + extF80M_to_f128M$(OBJ) \ + extF80M_roundToInt$(OBJ) \ + extF80M_add$(OBJ) \ + extF80M_sub$(OBJ) \ + extF80M_mul$(OBJ) \ + extF80M_div$(OBJ) \ + extF80M_rem$(OBJ) \ + extF80M_sqrt$(OBJ) \ + extF80M_eq$(OBJ) \ + extF80M_le$(OBJ) \ + extF80M_lt$(OBJ) \ + extF80M_eq_signaling$(OBJ) \ + extF80M_le_quiet$(OBJ) \ + extF80M_lt_quiet$(OBJ) \ + f128M_to_ui32$(OBJ) \ + f128M_to_ui64$(OBJ) \ + f128M_to_i32$(OBJ) \ + f128M_to_i64$(OBJ) \ + f128M_to_ui32_r_minMag$(OBJ) \ + f128M_to_ui64_r_minMag$(OBJ) \ + f128M_to_i32_r_minMag$(OBJ) \ + f128M_to_i64_r_minMag$(OBJ) \ + f128M_to_f32$(OBJ) \ + f128M_to_f64$(OBJ) \ + f128M_to_extF80M$(OBJ) \ + f128M_roundToInt$(OBJ) \ + f128M_add$(OBJ) \ + f128M_sub$(OBJ) \ + f128M_mul$(OBJ) \ + f128M_mulAdd$(OBJ) \ + f128M_div$(OBJ) \ + f128M_rem$(OBJ) \ + f128M_sqrt$(OBJ) \ + f128M_eq$(OBJ) \ + f128M_le$(OBJ) \ + f128M_lt$(OBJ) \ + f128M_eq_signaling$(OBJ) \ + f128M_le_quiet$(OBJ) \ + f128M_lt_quiet$(OBJ) \ + +OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) + +$(OBJS_ALL): \ + platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ + $(SOURCE_DIR)/include/primitives.h +$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ + $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ + $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ + $(SOURCE_DIR)/include/softfloat.h + +$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$*.c + +$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c + $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c + +softfloat$(LIB): $(OBJS_ALL) + $(DELETE) $@ + $(MAKELIB) $^ + +.PHONY: clean +clean: + $(DELETE) $(OBJS_ALL) softfloat$(LIB) + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/platform.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/platform.h new file mode 100644 index 0000000..cea3332 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/platform.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header template is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +// Edit lines marked with `==>'. See "SoftFloat-source.html". + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +==> #define LITTLEENDIAN 1 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +==> #define INLINE inline + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.html b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.html new file mode 100644 index 0000000..08cab39 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.html @@ -0,0 +1,155 @@ + + + + +Berkeley SoftFloat History + + + + +

History of Berkeley SoftFloat, to Release 3a

+ +

+John R. Hauser
+2015 October 23
+

+ + +

Release 3a (2015 October)

+ +
    + +
  • +Replaced the license text supplied by the University of California, Berkeley. + +
+ + +

Release 3 (2015 February)

+ +
    + +
  • +Complete rewrite, funded by the University of California, Berkeley, and +consequently having a different use license than earlier releases. +Major changes included renaming most types and functions, upgrading some +algorithms, restructuring the source files, and making SoftFloat into a true +library. + +
  • +Added functions to convert between floating-point and unsigned integers, both +32-bit and 64-bit (uint32_t and +uint64_t). + +
  • +Added functions for fused multiply-add, for all supported floating-point +formats except 80-bit double-extended-precision. + +
  • +Added support for a fifth rounding mode, near_maxMag (round to +nearest, with ties to maximum magnitude, away from zero). + +
  • +Dropped the timesoftfloat program (now part of the Berkeley +TestFloat package). + +
+ + +

Release 2c (2015 January)

+ +
    + +
  • +Fixed mistakes affecting some 64-bit processors. + +
  • +Further improved the documentation and the wording for the legal restrictions +on using SoftFloat releases through 2c (not applicable to +Release 3 or later). + +
+ + +

Release 2b (2002 May)

+ +
    + +
  • +Made minor updates to the documentation, including improved wording for the +legal restrictions on using SoftFloat. + +
+ + +

Release 2a (1998 December)

+ +
    + +
  • +Added functions to convert between 64-bit integers +(int64) and all supported floating-point formats. + +
  • +Fixed a bug in all 64-bit-version square root functions except +float32_sqrt that caused the result sometimes to be off by +1 unit in the last place (1 ulp) from what it should +be. +(Bug discovered by Paul Donahue.) + +
  • +Improved the Makefiles. +
+ + +

Release 2 (1997 June)

+ +
    + +
  • +Created the 64-bit (bits64) version, adding the +floatx80 and float128 formats. + +
  • +Changed the source directory structure, splitting the sources into a +bits32 and a bits64 version. +Renamed environment.h to milieu.h to avoid confusion +with environment variables. + +
  • +Fixed a small error that caused float64_round_to_int often to +round the wrong way in nearest/even mode when the operand was between +220 and 221 and halfway between two integers. + +
+ + +

Release 1a (1996 July)

+ +
    + +
  • +Corrected a mistake that caused borderline underflow cases not to raise the +underflow flag when they should have. +(Problem reported by Doug Priest.) + +
  • +Added the float_detect_tininess variable to control whether +tininess is detected before or after rounding. + +
+ + +

Release 1 (1996 July)

+ +
    + +
  • +Original release, based on work done for the International Computer Science +Institute (ICSI) in Berkeley, California. + +
+ + + + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-source.html b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-source.html new file mode 100644 index 0000000..dff77aa --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-source.html @@ -0,0 +1,590 @@ + + + + +Berkeley SoftFloat Source Documentation + + + + +

Berkeley SoftFloat Release 3a: Source Documentation

+ +

+John R. Hauser
+2015 October 23
+

+ + +

Contents

+ +
+ +++ + + + + + + + + + + + + + + + + + + + +
1. Introduction
2. Limitations
3. Acknowledgments and License
4. SoftFloat Package Directory Structure
5. Issues for Porting SoftFloat to a New Target
5.1. Standard Headers <stdbool.h> and + <stdint.h>
5.2. Specializing Floating-Point Behavior
5.3. Macros for Build Options
5.4. Adapting a Template Target Directory
5.5. Target-Specific Optimization of Primitive Functions
6. Testing SoftFloat
7. Providing SoftFloat as a Common Library for Applications
8. Contact Information
+
+ + +

1. Introduction

+ +

+This document gives information needed for compiling and/or porting Berkeley +SoftFloat, a library of C functions implementing binary floating-point +conforming to the IEEE Standard for Floating-Point Arithmetic. +For basic documentation about SoftFloat refer to +SoftFloat.html. +

+ +

+The source code for SoftFloat is intended to be relatively machine-independent +and should be compilable with any ISO-Standard C compiler that also supports +64-bit integers. +SoftFloat has been successfully compiled with the GNU C Compiler +(gcc) for several platforms. +

+ +

+Release 3 of SoftFloat was a complete rewrite relative to +Release 2 or earlier. +Changes to the interface of SoftFloat functions are documented in +SoftFloat.html. +The current version of SoftFloat is Release 3a. +

+ + +

2. Limitations

+ +

+SoftFloat assumes the computer has an addressable byte size of either 8 or +16 bits. +(Nearly all computers in use today have 8-bit bytes.) +

+ +

+SoftFloat is written in C and is designed to work with other C code. +The C compiler used must conform at a minimum to the 1989 ANSI standard for the +C language (same as the 1990 ISO standard) and must in addition support basic +arithmetic on 64-bit integers. +Earlier releases of SoftFloat included implementations of 32-bit +single-precision and 64-bit double-precision floating-point that +did not require 64-bit integers, but this option is not supported +starting with Release 3. +Since 1999, ISO standards for C have mandated compiler support for +64-bit integers. +A compiler conforming to the 1999 C Standard or later is recommended but not +strictly required. +

+ +

+C Standard header files <stdbool.h> and +<stdint.h> are required for defining standard Boolean and +integer types. +If these headers are not supplied with the C compiler, minimal substitutes must +be provided. +SoftFloat’s dependence on these headers is detailed later in +section 5.1, Standard Headers <stdbool.h> and +<stdint.h>. +

+ + +

3. Acknowledgments and License

+ +

+The SoftFloat package was written by me, John R. Hauser. +Release 3 of SoftFloat was a completely new implementation +supplanting earlier releases. +The project to create Release 3 (and now 3a) was done +in the employ of the University of California, Berkeley, within the Department +of Electrical Engineering and Computer Sciences, first for the Parallel +Computing Laboratory (Par Lab) and then for the ASPIRE Lab. +The work was officially overseen by Prof. Krste Asanovic, with funding provided +by these sources: +

+ ++++ + + + + + + + + + +
Par Lab: +Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery +(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, +NVIDIA, Oracle, and Samsung. +
ASPIRE Lab: +DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from +ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, +Oracle, and Samsung. +
+
+

+ +

+The following applies to the whole of SoftFloat Release 3a as well +as to each source file individually. +

+ +

+Copyright 2011, 2012, 2013, 2014, 2015 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. +

+ + +

4. SoftFloat Package Directory Structure

+ +

+Because SoftFloat is targeted to multiple platforms, its source code is +slightly scattered between target-specific and target-independent directories +and files. +The supplied directory structure is as follows: +

+
+doc
+source
+    include
+    8086
+    8086-SSE
+build
+    template-FAST_INT64
+    template-not-FAST_INT64
+    Linux-386-GCC
+    Linux-386-SSE2-GCC
+    Linux-x86_64-GCC
+    Win32-MinGW
+    Win32-SSE2-MinGW
+    Win64-MinGW-w64
+
+
+The majority of the SoftFloat sources are provided in the source +directory. +The include subdirectory of source contains several +header files (unsurprisingly), while the 8086 and +8086-SSE subdirectories contain source files that +specialize the floating-point behavior to match the Intel x86 line of +processors. +The files in directory 8086 give floating-point behavior +consistent solely with Intel’s older, 8087-derived floating-point, while +those in 8086-SSE update the behavior of the +non-extended formats (float32_t, float64_t, and +float128_t) to mirror Intel’s more recent Streaming SIMD +Extensions (SSE) and other compatible extensions. +If other specializations are attempted, these would be expected to be other +subdirectories of source alongside 8086 and +8086-SSE. +Specialization is covered later, in section 5.2, Specializing +Floating-Point Behavior. +

+ +

+The build directory is intended to contain a subdirectory for each +target platform for which a build of the SoftFloat library may be created. +For each build target, the target’s subdirectory is where all derived +object files and the completed SoftFloat library (typically +softfloat.a or libsoftfloat.a) are created. +The two template subdirectories are not actual build targets but +contain sample files for creating new target directories. +(The meaning of FAST_INT64 will be explained later.) +

+ +

+Ignoring the template directories, the supplied target directories +are intended to follow a naming system of +<execution-environment>-<compiler>. +For the example targets, +<execution-environment> is +Linux-386, Linux-386-SSE2, +Linux-x86_64, Win32, +Win32-SSE2, or Win64, and +<compiler> is GCC, +MinGW, or MinGW-w64. +

+ +

+As supplied, each target directory contains two files: +

+
+Makefile
+platform.h
+
+
+The provided Makefile is written for GNU make. +A build of SoftFloat for the specific target is begun by executing the +make command with the target directory as the current directory. +A completely different build tool can be used if an appropriate +Makefile equivalent is created. +

+ +

+The platform.h header file exists to provide a location for +additional C declarations specific to the build target. +Every C source file of SoftFloat contains a #include for +platform.h. +In many cases, the contents of platform.h can be as simple as one +or two lines of code. +At the other extreme, to get maximal performance from SoftFloat, it may be +desirable to include in header platform.h (directly or via +#include) declarations for numerous target-specific optimizations. +Such possibilities are discussed in the next section, Issues for Porting +SoftFloat to a New Target. +If the target’s compiler or library has bugs or other shortcomings, +workarounds for these issues may also be possible with target-specific +declarations in platform.h, avoiding the need to modify the main +SoftFloat sources. +

+ + +

5. Issues for Porting SoftFloat to a New Target

+ +

5.1. Standard Headers <stdbool.h> and <stdint.h>

+ +

+The SoftFloat sources make use of standard headers +<stdbool.h> and <stdint.h>, which have +been part of the ISO C Standard Library since 1999. +With any recent compiler, these standard headers are likely to be supported, +even if the compiler does not claim complete conformance to the latest ISO C +Standard. +For older or nonstandard compilers, substitutes for +<stdbool.h> and <stdint.h> may need to be +created. +SoftFloat depends on these names from <stdbool.h>: +

+
+bool
+true
+false
+
+
+and on these names from <stdint.h>: +
+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+UINT64_C
+INT64_C
+uint_least8_t
+uint_fast8_t
+uint_fast16_t
+uint_fast32_t
+uint_fast64_t
+int_fast8_t
+int_fast16_t
+int_fast32_t
+int_fast64_t
+
+
+

+ + +

5.2. Specializing Floating-Point Behavior

+ +

+The IEEE Floating-Point Standard allows for some flexibility in a conforming +implementation, particularly concerning NaNs. +The SoftFloat source directory is supplied with some +specialization subdirectories containing possible definitions for this +implementation-specific behavior. +For example, the 8086 and 8086-SSE +subdirectories have source files that specialize SoftFloat’s behavior to +match that of Intel’s x86 line of processors. +The files in a specialization subdirectory must determine: +

    +
  • +whether tininess for underflow is detected before or after rounding by default; +
  • +what (if anything) special happens when exceptions are raised; +
  • +how signaling NaNs are distinguished from quiet NaNs; +
  • +the default generated quiet NaNs; and +
  • +how NaNs are propagated from function inputs to output. +
+

+ +

+As provided, the build process for a target expects to involve exactly +one specialization directory that defines all of these +implementation-specific details for the target. +A specialization directory such as 8086 is expected to contain a +header file called specialize.h, together with whatever other +source files are needed to complete the specialization. +

+ +

+A new build target may use an existing specialization, such as the ones +provided by the 8086 and 8086-SSE +subdirectories. +If a build target needs a new specialization, different from any existing ones, +it is recommended that a new specialization subdirectory be created in the +source directory for this purpose. +The specialize.h header file from any of the provided +specialization subdirectories can be used as a model for what definitions are +needed. +

+ + +

5.3. Macros for Build Options

+ +

+The SoftFloat source files adapt the floating-point implementation according to +a few C preprocessor macros: +

+
+
LITTLEENDIAN +
+Must be defined for little-endian machines; must not be defined for big-endian +machines. +
SOFTFLOAT_FAST_INT64 +
+Can be defined to indicate that the build target’s implementation of +64-bit arithmetic is efficient. +For newer 64-bit processors, this macro should usually be defined. +For very small microprocessors whose buses and registers are 8-bit +or 16-bit in size, this macro should usually not be defined. +Whether this macro should be defined for a 32-bit processor may +depend on the target machine and the applications that will use SoftFloat. +
SOFTFLOAT_FAST_DIV64TO32 +
+Can be defined to indicate that the target’s division operator +in C (written as /) is reasonably efficient for +dividing a 64-bit unsigned integer by a 32-bit +unsigned integer. +Setting this macro may affect the performance of division, remainder, and +square root operations. +
INLINE_LEVEL +
+Can be defined to an integer to determine the degree of inlining requested of +the compiler. +Larger numbers request that more inlining be done. +If this macro is not defined or is defined to a value less than 1 +(zero or negative), no inlining is requested. +The maximum effective value is no higher than 5. +Defining this macro to a value greater than 5 is the same as defining it +to 5. +
INLINE +
+Specifies the sequence of tokens used to indicate that a C function should be +inlined. +If macro INLINE_LEVEL is defined with a value of 1 or higher, this +macro must be defined; otherwise, this macro is ignored and need not be +defined. +For some compilers, this macro can be defined as the single keyword +inline. +Historically, the gcc compiler has required that this macro be +defined to extern inline. +
+
+

+ +

+Following the usual custom for C, for the first three macros (all +except INLINE_LEVEL and INLINE), the content of any +definition is irrelevant; +what matters is a macro’s effect on #ifdef directives. +

+ +

+It is recommended that any definitions of macros LITTLEENDIAN and +INLINE be made in a build target’s platform.h +header file, because these macros are expected to be determined inflexibly by +the target machine and compiler. +The other three macros control optimization and might be better located in the +target’s Makefile (or its equivalent). +

+ + +

5.4. Adapting a Template Target Directory

+ +

+In the build directory, two template subdirectories +provide models for new target directories. +Two different templates exist because different functions are needed in the +SoftFloat library depending on whether macro SOFTFLOAT_FAST_INT64 +is defined. +If macro SOFTFLOAT_FAST_INT64 will be defined, +template-FAST_INT64 is the template to use; +otherwise, template-not-FAST_INT64 is the appropriate +template. +A new target directory can be created by copying the correct template directory +and editing the files inside. +To avoid confusion, it would be wise to refrain from editing the files within a +template directory directly. +

+ + +

5.5. Target-Specific Optimization of Primitive Functions

+ +

+Header file primitives.h (in directory +source/include) declares macros and functions for numerous +underlying arithmetic operations upon which many of SoftFloat’s +floating-point functions are ultimately built. +The SoftFloat sources include implementations of all of these functions/macros, +written as standard C code, so a complete and correct SoftFloat library can be +built using only the supplied code for all functions. +However, for many targets, SoftFloat’s performance can be improved by +substituting target-specific implementations of some of the functions/macros +declared in primitives.h. +

+ +

+For example, primitives.h declares a function called +softfloat_countLeadingZeros32 that takes an unsigned +32-bit integer as an argument and returns the maximal number of +the integer’s most-significant bits that are all zeros. +While the SoftFloat sources include an implementation of this function written +in standard C, many processors can perform this same function +directly in only one or two machine instructions. +An alternative, target-specific implementation that maps to those instructions +is likely to be more efficient than the generic C code from the SoftFloat +package. +

+ +

+A build target can replace the supplied version of any function or macro of +primitives.h by defining a macro with the same name in the +target’s platform.h header file. +For this purpose, it may be helpful for platform.h to +#include header file primitiveTypes.h, which defines +types used for arguments and results of functions declared in +primitives.h. +When a desired replacement implementation is a function, not a macro, it is +sufficient for platform.h to include the line +

+
+#define <function-name> <function-name>
+
+
+where <function-name> is the name of the +function. +This technically defines <function-name> as a +macro, but one that resolves to the same name, which may then be a function. +(A preprocessor conforming to the C Standard must limit recursive macro +expansion from being applied more than once.) +

+ + +

6. Testing SoftFloat

+ +

+SoftFloat can be tested using the testsoftfloat program by the +same author. +This program is part of the Berkeley TestFloat package available at the Web +page +http://www.jhauser.us/arithmetic/TestFloat.html. +The TestFloat package also has a program called timesoftfloat that +measures the speed of SoftFloat’s floating-point functions. +

+ + +

7. Providing SoftFloat as a Common Library for Applications

+ +

+Header file softfloat.h defines the SoftFloat interface as seen by +clients. +If the SoftFloat library will be made a common library for programs on a +particular system, the supplied softfloat.h has a couple of +deficiencies for this purpose: +

    +
  • +As supplied, softfloat.h depends on another header, +softfloat_types.h, that is not intended for public use but which +must also be visible to the programmer’s compiler. +
  • +More troubling, at the time softfloat.h is included in a C +source file, macro SOFTFLOAT_FAST_INT64 must be defined, or not +defined, consistent with whether this macro was defined when the SoftFloat +library was built. +
+In the situation that new programs may regularly #include header +file softfloat.h, it is recommended that a custom, self-contained +version of this header file be created that eliminates these issues. +

+ + +

8. Contact Information

+ +

+At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page +http://www.jhauser.us/arithmetic/SoftFloat.html. +

+ + + + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html new file mode 100644 index 0000000..19176dc --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html @@ -0,0 +1,1453 @@ + + + + +Berkeley SoftFloat Library Interface + + + + +

Berkeley SoftFloat Release 3a: Library Interface

+ +

+John R. Hauser
+2015 October 23
+

+ + +

Contents

+ +
+ +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1. Introduction
2. Limitations
3. Acknowledgments and License
4. Types and Functions
4.1. Boolean and Integer Types
4.2. Floating-Point Types
4.3. Supported Floating-Point Functions
4.4. Non-canonical Representations in extFloat80_t
4.5. Conventions for Passing Arguments and Results
5. Reserved Names
6. Mode Variables
6.1. Rounding Mode
6.2. Underflow Detection
6.3. Rounding Precision for the 80-Bit Extended Format
7. Exceptions and Exception Flags
8. Function Details
8.1. Conversions from Integer to Floating-Point
8.2. Conversions from Floating-Point to Integer
8.3. Conversions Among Floating-Point Types
8.4. Basic Arithmetic Functions
8.5. Fused Multiply-Add Functions
8.6. Remainder Functions
8.7. Round-to-Integer Functions
8.8. Comparison Functions
8.9. Signaling NaN Test Functions
8.10. Raise-Exception Function
9. Changes from SoftFloat Release 2
9.1. Name Changes
9.2. Changes to Function Arguments
9.3. Added Capabilities
9.4. Better Compatibility with the C Language
9.5. New Organization as a Library
9.6. Optimization Gains (and Losses)
10. Future Directions
11. Contact Information
+
+ + +

1. Introduction

+ +

+Berkeley SoftFloat is a software implementation of binary floating-point that +conforms to the IEEE Standard for Floating-Point Arithmetic. +The current release supports four binary formats: 32-bit +single-precision, 64-bit double-precision, 80-bit +double-extended-precision, and 128-bit quadruple-precision. +The following functions are supported for each format: +

    +
  • +addition, subtraction, multiplication, division, and square root; +
  • +fused multiply-add as defined by the IEEE Standard, except for +80-bit double-extended-precision; +
  • +remainder as defined by the IEEE Standard; +
  • +round to integral value; +
  • +comparisons; +
  • +conversions to/from other supported formats; and +
  • +conversions to/from 32-bit and 64-bit integers, +signed and unsigned. +
+All operations required by the original 1985 version of the IEEE Floating-Point +Standard are implemented, except for conversions to and from decimal. +

+ +

+This document gives information about the types defined and the routines +implemented by SoftFloat. +It does not attempt to define or explain the IEEE Floating-Point Standard. +Information about the standard is available elsewhere. +

+ +

+The current version of SoftFloat is Release 3a. +The only difference between this version and the previous +Release 3 is the replacement of the license text supplied by the +University of California. +

+ +

+The functional interface of SoftFloat Release 3 and afterward +differs in many details from that of earlier releases. +For specifics of these differences, see section 9 below, +Changes from SoftFloat Release 2. +

+ + +

2. Limitations

+ +

+SoftFloat assumes the computer has an addressable byte size of 8 or +16 bits. +(Nearly all computers in use today have 8-bit bytes.) +

+ +

+SoftFloat is written in C and is designed to work with other C code. +The C compiler used must conform at a minimum to the 1989 ANSI standard for the +C language (same as the 1990 ISO standard) and must in addition support basic +arithmetic on 64-bit integers. +Earlier releases of SoftFloat included implementations of 32-bit +single-precision and 64-bit double-precision floating-point that +did not require 64-bit integers, but this option is not supported +starting with Release 3. +Since 1999, ISO standards for C have mandated compiler support for +64-bit integers. +A compiler conforming to the 1999 C Standard or later is recommended but not +strictly required. +

+ +

+Most operations not required by the original 1985 version of the IEEE +Floating-Point Standard but added in the 2008 version are not yet supported in +SoftFloat Release 3a. +

+ + +

3. Acknowledgments and License

+ +

+The SoftFloat package was written by me, John R. Hauser. +Release 3 of SoftFloat was a completely new implementation +supplanting earlier releases. +The project to create Release 3 (and now 3a) was done +in the employ of the University of California, Berkeley, within the Department +of Electrical Engineering and Computer Sciences, first for the Parallel +Computing Laboratory (Par Lab) and then for the ASPIRE Lab. +The work was officially overseen by Prof. Krste Asanovic, with funding provided +by these sources: +

+ ++++ + + + + + + + + + +
Par Lab: +Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery +(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, +NVIDIA, Oracle, and Samsung. +
ASPIRE Lab: +DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from +ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, +Oracle, and Samsung. +
+
+

+ +

+The following applies to the whole of SoftFloat Release 3a as well +as to each source file individually. +

+ +

+Copyright 2011, 2012, 2013, 2014, 2015 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. +

+ + +

4. Types and Functions

+ +

+The types and functions of SoftFloat are declared in header file +softfloat.h. +

+ +

4.1. Boolean and Integer Types

+ +

+Header file softfloat.h depends on standard headers +<stdbool.h> and <stdint.h> to define type +bool and several integer types. +These standard headers have been part of the ISO C Standard Library since 1999. +With any recent compiler, they are likely to be supported, even if the compiler +does not claim complete conformance to the ISO C Standard. +For older or nonstandard compilers, a port of SoftFloat may have substitutes +for these headers. +Header softfloat.h depends only on the name bool from +<stdbool.h> and on these type names from +<stdint.h>: +

+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+uint_fast8_t
+uint_fast32_t
+uint_fast64_t
+
+
+

+ + +

4.2. Floating-Point Types

+ +

+The softfloat.h header defines four floating-point types: +

+ + + + + + + + + + + + + + + + + +
float32_t32-bit single-precision binary format
float64_t64-bit double-precision binary format
extFloat80_t   80-bit double-extended-precision binary format (old Intel or +Motorola format)
float128_t128-bit quadruple-precision binary format
+
+The non-extended types are each exactly the size specified: +32 bits for float32_t, 64 bits for +float64_t, and 128 bits for float128_t. +Aside from these size requirements, the definitions of all these types may +differ for different ports of SoftFloat to specific systems. +A given port of SoftFloat may or may not define some of the floating-point +types as aliases for the C standard types float, +double, and long double. +

+ +

+Header file softfloat.h also defines a structure, +struct extFloat80M, for the representation of +80-bit double-extended-precision floating-point values in memory. +This structure is the same size as type extFloat80_t and contains +at least these two fields (not necessarily in this order): +

+
+uint16_t signExp;
+uint64_t signif;
+
+
+Field signExp contains the sign and exponent of the floating-point +value, with the sign in the most significant bit (bit 15) and the +encoded exponent in the other 15 bits. +Field signif is the complete 64-bit significand of +the floating-point value. +(In the usual encoding for 80-bit extended floating-point, the +leading 1 bit of normalized numbers is not implicit but is stored +in the most significant bit of the significand.) +

+ +

4.3. Supported Floating-Point Functions

+ +

+SoftFloat implements these arithmetic operations for its floating-point types: +

    +
  • +conversions between any two floating-point formats; +
  • +for each floating-point format, conversions to and from signed and unsigned +32-bit and 64-bit integers; +
  • +for each format, the usual addition, subtraction, multiplication, division, and +square root operations; +
  • +for each format except extFloat80_t, the fused multiply-add +operation defined by the IEEE Standard; +
  • +for each format, the floating-point remainder operation defined by the IEEE +Standard; +
  • +for each format, a “round to integer” operation that rounds to the +nearest integer value in the same format; and +
  • +comparisons between two values in the same floating-point format. +
+

+ +

+The following operations required by the 2008 IEEE Floating-Point Standard are +not supported in SoftFloat Release 3a: +

    +
  • +nextUp, nextDown, minNum, maxNum, minNumMag, +maxNumMag, scaleB, and logB; +
  • +conversions between floating-point formats and decimal or hexadecimal character +sequences; +
  • +all “quiet-computation” operations (copy, negate, +abs, and copySign, which all involve only simple copying and/or +manipulation of the floating-point sign bit); and +
  • +all “non-computational” operations other than isSignaling +(which is supported). +
+

+ +

4.4. Non-canonical Representations in extFloat80_t

+ +

+Because the 80-bit double-extended-precision format, +extFloat80_t, stores an explicit leading significand bit, many +floating-point numbers are encodable in this type in equivalent normalized and +denormalized forms. +Zeros and values in the subnormal range have each only a single possible +encoding, for which the leading significand bit must be 0. +For other finite values (outside the subnormal range), a unique normalized +representation, with leading significand bit set to 1, always +exists, and is considered the canonical representation of the value. +Any equivalent denormalized representations (having leading significand bit +of 0) are non-canonical. +Similarly, the leading significand bit is expected to be 1 for +infinities and NaNs as well; +any infinity or NaN with a leading significand bit of 0 is again +considered non-canonical. +In short, for an extFloat80_t representation to be canonical, the +leading significand bit must be 1 unless it is required to +be 0 because the encoded value is zero or a subnormal. +

+ +

+Functions are not guaranteed to operate as expected when inputs of type +extFloat80_t are non-canonical. +Assuming all of a function’s extFloat80_t inputs (if any) +are canonical, function outputs of type extFloat80_t will always +be canonical. +

+ +

4.5. Conventions for Passing Arguments and Results

+ +

+Values that are at most 64 bits in size (i.e., not the +80-bit or 128-bit floating-point formats) are in all +cases passed as function arguments by value. +Likewise, when an output of a function is no more than 64 bits, it +is always returned directly as the function result. +Thus, for example, the SoftFloat function for adding two 64-bit +floating-point values has this simple signature: +

+float64_t f64_add( float64_t, float64_t ); +
+

+ +

+The story is more complex when function inputs and outputs are +80-bit and 128-bit floating-point. +For these types, SoftFloat always provides a function that passes these larger +values into or out of the function indirectly, via pointers. +For example, for adding two 128-bit floating-point values, +SoftFloat supplies this function: +

+void f128M_add( const float128_t *, const float128_t *, float128_t * ); +
+The first two arguments point to the values to be added, and the last argument +points to the location where the sum will be stored. +The M in the name f128M_add is mnemonic for the fact +that the 128-bit inputs and outputs are “in memory”, +pointed to by pointer arguments. +

+ +

+All ports of SoftFloat implement these pass-by-pointer functions for +types extFloat80_t and float128_t. +At the same time, SoftFloat ports may also implement alternate versions of +these same functions that pass extFloat80_t and +float128_t by value, like the smaller formats. +Thus, besides the function with name f128M_add shown above, a +SoftFloat port may also supply an equivalent function with this signature: +

+float128_t f128_add( float128_t, float128_t ); +
+

+ +

+As a general rule, on computers where the machine word size is +32 bits or smaller, only the pass-by-pointer versions of functions +(e.g., f128M_add) are provided for types extFloat80_t +and float128_t, because passing such large types directly can have +significant extra cost. +On computers where the word size is 64 bits or larger, both +function versions (f128M_add and f128_add) are +provided, because the cost of passing by value is then more reasonable. +Applications that must be portable accross both classes of computers must use +the pointer-based functions, as these are always implemented. +However, if it is known that SoftFloat includes the by-value functions for all +platforms of interest, programmers can use whichever version they prefer. +

+ + +

5. Reserved Names

+ +

+In addition to the variables and functions documented here, SoftFloat defines +some symbol names for its own private use. +These private names always begin with the prefix +‘softfloat_’. +When a program includes header softfloat.h or links with the +SoftFloat library, all names with prefix ‘softfloat_’ +are reserved for possible use by SoftFloat. +Applications that use SoftFloat should not define their own names with this +prefix, and should reference only such names as are documented. +

+ + +

6. Mode Variables

+ +

+The following variables control rounding mode, underflow detection, and the +80-bit extended format’s rounding precision: +

+softfloat_roundingMode
+softfloat_detectTininess
+extF80_roundingPrecision +
+These mode variables are covered in the next several subsections. +

+ +

6.1. Rounding Mode

+ +

+All five rounding modes defined by the 2008 IEEE Floating-Point Standard are +implemented for all operations that require rounding. +The rounding mode is selected by the global variable +

+uint_fast8_t softfloat_roundingMode; +
+This variable may be set to one of the values +
+ + + + + + + + + + + + + + + + + + + + + +
softfloat_round_near_evenround to nearest, with ties to even
softfloat_round_near_maxMag  round to nearest, with ties to maximum magnitude (away from zero)
softfloat_round_minMaground to minimum magnitude (toward zero)
softfloat_round_minround to minimum (down)
softfloat_round_maxround to maximum (up)
+
+Variable softfloat_roundingMode is initialized to +softfloat_round_near_even. +

+ +

6.2. Underflow Detection

+ +

+In the terminology of the IEEE Standard, SoftFloat can detect tininess for +underflow either before or after rounding. +The choice is made by the global variable +

+uint_fast8_t softfloat_detectTininess; +
+which can be set to either +
+softfloat_tininess_beforeRounding
+softfloat_tininess_afterRounding +
+Detecting tininess after rounding is better because it results in fewer +spurious underflow signals. +The other option is provided for compatibility with some systems. +Like most systems (and as required by the newer 2008 IEEE Standard), SoftFloat +always detects loss of accuracy for underflow as an inexact result. +

+ +

6.3. Rounding Precision for the 80-Bit Extended Format

+ +

+For extFloat80_t only, the rounding precision of the basic +arithmetic operations is controlled by the global variable +

+uint_fast8_t extF80_roundingPrecision; +
+The operations affected are: +
+extF80_add
+extF80_sub
+extF80_mul
+extF80_div
+extF80_sqrt +
+When extF80_roundingPrecision is set to its default value of 80, +these operations are rounded to the full precision of the 80-bit +double-extended-precision format, like occurs for other formats. +Setting extF80_roundingPrecision to 32 or to 64 causes the +operations listed to be rounded to 32-bit precision (equivalent to +float32_t) or to 64-bit precision (equivalent to +float64_t), respectively. +When rounding to reduced precision, additional bits in the result significand +beyond the rounding point are set to zero. +The consequences of setting extF80_roundingPrecision to a value +other than 32, 64, or 80 is not specified. +Operations other than the ones listed above are not affected by +extF80_roundingPrecision. +

+ + +

7. Exceptions and Exception Flags

+ +

+All five exception flags required by the IEEE Floating-Point Standard are +implemented. +Each flag is stored as a separate bit in the global variable +

+uint_fast8_t softfloat_exceptionFlags; +
+The positions of the exception flag bits within this variable are determined by +the bit masks +
+softfloat_flag_inexact
+softfloat_flag_underflow
+softfloat_flag_overflow
+softfloat_flag_infinite
+softfloat_flag_invalid +
+Variable softfloat_exceptionFlags is initialized to all zeros, +meaning no exceptions. +

+ +

+An individual exception flag can be cleared with the statement +

+softfloat_exceptionFlags &= ~softfloat_flag_<exception>; +
+where <exception> is the appropriate name. +To raise a floating-point exception, function softfloat_raise +should normally be used. +

+ +

+When SoftFloat detects an exception other than inexact, it calls +softfloat_raise. +The default version of this function simply raises the corresponding exception +flags. +Particular ports of SoftFloat may support alternate behavior, such as exception +traps, by modifying the default softfloat_raise. +A program may also supply its own softfloat_raise function to +override the one from the SoftFloat library. +

+ +

+Because inexact results occur frequently under most circumstances (and thus are +hardly exceptional), SoftFloat does not ordinarily call +softfloat_raise for inexact exceptions. +It does always raise the inexact exception flag as required. +

+ + +

8. Function Details

+ +

+In this section, <float> appears in function names as +a substitute for one of these abbreviations: +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
f32indicates float32_t, passed by value
f64indicates float64_t, passed by value
extF80M   indicates extFloat80_t, passed indirectly via pointers
extF80indicates extFloat80_t, passed by value
f128Mindicates float128_t, passed indirectly via pointers
f128indicates float128_t, passed by value
+
+The circumstances under which values of floating-point types +extFloat80_t and float128_t may be passed either by +value or indirectly via pointers was discussed earlier in +section 4.5, Conventions for Passing Arguments and Results. +

+ +

8.1. Conversions from Integer to Floating-Point

+ +

+All conversions from a 32-bit or 64-bit integer, +signed or unsigned, to a floating-point format are supported. +Functions performing these conversions have these names: +

+ui32_to_<float>
+ui64_to_<float>
+i32_to_<float>
+i64_to_<float> +
+Conversions from 32-bit integers to 64-bit +double-precision and larger formats are always exact, and likewise conversions +from 64-bit integers to 80-bit +double-extended-precision and 128-bit quadruple-precision are also +always exact. +

+ +

+Each conversion function takes one input of the appropriate type and generates +one output. +The following illustrates the signatures of these functions in cases when the +floating-point result is passed either by value or via pointers: +

+
+float64_t i32_to_f64( int32_t a );
+
+
+void i32_to_f128M( int32_t a, float128_t *destPtr );
+
+
+

+ +

8.2. Conversions from Floating-Point to Integer

+ +

+Conversions from a floating-point format to a 32-bit or +64-bit integer, signed or unsigned, are supported with these +functions: +

+<float>_to_ui32
+<float>_to_ui64
+<float>_to_i32
+<float>_to_i64 +
+The functions have signatures as follows, depending on whether the +floating-point input is passed by value or via pointers: +
+
+int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+int_fast32_t
+ f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact );
+
+
+The roundingMode argument specifies the rounding mode for +the conversion. +The variable that usually indicates rounding mode, +softfloat_roundingMode, is ignored. +Argument exact determines whether the inexact +exception flag is raised if the conversion is not exact. +If exact is true, the inexact flag may +be raised; +otherwise, it will not be, even if the conversion is inexact. +

+ +

+Conversions from floating-point to integer raise the invalid exception +if the source value cannot be rounded to a representable integer of the desired +size (32 or 64 bits). +In such a circumstance, if the floating-point input is a NaN or if the +conversion is to an unsigned integer type, the largest positive integer is +returned; +otherwise, the largest integer with the same sign as the input is returned. +The functions that convert to integer types never raise the overflow +exception. +

+ +

+Note that, when converting to an unsigned integer type, if the invalid +exception is raised because the input floating-point value would round to a +negative integer, the value returned is the maximum positive unsigned +integer. +Zero is not returned when the invalid exception is raised, even when +zero is the closest integer to the original floating-point value. +

+ +

+Because languages such as C require that conversions to integers +be rounded toward zero, the following functions are provided for improved speed +and convenience: +

+<float>_to_ui32_r_minMag
+<float>_to_ui64_r_minMag
+<float>_to_i32_r_minMag
+<float>_to_i64_r_minMag +
+These functions round only toward zero (to minimum magnitude). +The signatures for these functions are the same as above without the redundant +roundingMode argument: +
+
+int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact );
+
+
+int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact );
+
+
+

+ +

8.3. Conversions Among Floating-Point Types

+ +

+Conversions between floating-point formats are done by functions with these +names: +

+<float>_to_<float> +
+All combinations of source and result type are supported where the source and +result are different formats. +There are four different styles of signature for these functions, depending on +whether the input and the output floating-point values are passed by value or +via pointers: +
+
+float32_t f64_to_f32( float64_t a );
+
+
+float32_t f128M_to_f32( const float128_t *aPtr );
+
+
+void f32_to_f128M( float32_t a, float128_t *destPtr );
+
+
+void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *destPtr );
+
+
+

+ +

+Conversions from a smaller to a larger floating-point format are always exact +and so require no rounding. +

+ +

8.4. Basic Arithmetic Functions

+ +

+The following basic arithmetic functions are provided: +

+<float>_add
+<float>_sub
+<float>_mul
+<float>_div
+<float>_sqrt +
+Each floating-point operation takes two operands, except for sqrt +(square root) which takes only one. +The operands and result are all of the same floating-point format. +Signatures for these functions take the following forms: +
+
+float64_t f64_add( float64_t a, float64_t b );
+
+
+void
+ f128M_add(
+     const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+float64_t f64_sqrt( float64_t a );
+
+
+void f128M_sqrt( const float128_t *aPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments +aPtr and bPtr point to the input +operands, and the last argument, destPtr, points to the +location where the result is stored. +

+ +

+Rounding of the 80-bit double-extended-precision +(extFloat80_t) functions is affected by variable +extF80_roundingPrecision, as explained earlier in +section 6.3, +Rounding Precision for the 80-Bit Extended Format. +

+ +

8.5. Fused Multiply-Add Functions

+ +

+The 2008 version of the IEEE Floating-Point Standard defines a fused +multiply-add operation that does a combined multiplication and addition +with only a single rounding. +SoftFloat implements fused multiply-add with functions +

+<float>_mulAdd +
+Unlike other operations, fused multiple-add is supported only for the +non-extended formats, float32_t, float64_t, and +float128_t. +No fused multiple-add function is currently provided for the +80-bit double-extended-precision type, extFloat80_t. +

+ +

+Depending on whether floating-point values are passed by value or via pointers, +the fused multiply-add functions have signatures of these forms: +

+
+float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c );
+
+
+void
+ f128M_mulAdd(
+     const float128_t *aPtr,
+     const float128_t *bPtr,
+     const float128_t *cPtr,
+     float128_t *destPtr
+ );
+
+
+The functions compute +(a × b) + + c +with a single rounding. +When floating-point values are passed indirectly through pointers, arguments +aPtr, bPtr, and +cPtr point to operands a, +b, and c respectively, and +destPtr points to the location where the result is stored. +

+ +

+If one of the multiplication operands a and +b is infinite and the other is zero, these functions raise +the invalid exception even if operand c is a quiet NaN. +

+ +

8.6. Remainder Functions

+ +

+For each format, SoftFloat implements the remainder operation defined by the +IEEE Floating-Point Standard. +The remainder functions have names +

+<float>_rem +
+Each remainder operation takes two floating-point operands of the same format +and returns a result in the same format. +Depending on whether floating-point values are passed by value or via pointers, +the remainder functions have signatures of these forms: +
+
+float64_t f64_rem( float64_t a, float64_t b );
+
+
+void
+ f128M_rem(
+     const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments +aPtr and bPtr point to operands +a and b respectively, and +destPtr points to the location where the result is stored. +

+ +

+The IEEE Standard remainder operation computes the value +a + − n × b, +where n is the integer closest to +a ÷ b. +If a ÷ b is exactly +halfway between two integers, n is the even integer closest to +a ÷ b. +The IEEE Standard’s remainder operation is always exact and so requires +no rounding. +

+ +

+Depending on the relative magnitudes of the operands, the remainder +functions can take considerably longer to execute than the other SoftFloat +functions. +This is inherent in the remainder operation itself and is not a flaw in the +SoftFloat implementation. +

+ +

8.7. Round-to-Integer Functions

+ +

+For each format, SoftFloat implements the round-to-integer operation specified +by the IEEE Floating-Point Standard. +These functions are named +

+<float>_roundToInt +
+Each round-to-integer operation takes a single floating-point operand. +This operand is rounded to an integer according to a specified rounding mode, +and the resulting integer value is returned in the same floating-point format. +(Note that the result is not an integer type.) +

+ +

+The signatures of the round-to-integer functions are similar to those for +conversions to an integer type: +

+
+float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+void
+ f128M_roundToInt(
+     const float128_t *aPtr,
+     uint_fast8_t roundingMode,
+     bool exact,
+     float128_t *destPtr
+ );
+
+
+The roundingMode argument specifies the rounding mode to +apply. +The variable that usually indicates rounding mode, +softfloat_roundingMode, is ignored. +Argument exact determines whether the inexact +exception flag is raised if the conversion is not exact. +If exact is true, the inexact flag may +be raised; +otherwise, it will not be, even if the conversion is inexact. +When floating-point values are passed indirectly through pointers, +aPtr points to the input operand and +destPtr points to the location where the result is stored. +

+ +

8.8. Comparison Functions

+ +

+For each format, the following floating-point comparison functions are +provided: +

+<float>_eq
+<float>_le
+<float>_lt +
+Each comparison takes two operands of the same type and returns a Boolean. +The abbreviation eq stands for “equal” (=); +le stands for “less than or equal” (≤); +and lt stands for “less than” (<). +Depending on whether the floating-point operands are passed by value or via +pointers, the comparison functions have signatures of these forms: +
+
+bool f64_eq( float64_t a, float64_t b );
+
+
+bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr );
+
+
+

+ +

+The usual greater-than (>), greater-than-or-equal (≥), and not-equal +(≠) comparisons are easily obtained from the functions provided. +The not-equal function is just the logical complement of the equal function. +The greater-than-or-equal function is identical to the less-than-or-equal +function with the arguments in reverse order, and likewise the greater-than +function is identical to the less-than function with the arguments reversed. +

+ +

+The IEEE Floating-Point Standard specifies that the less-than-or-equal and +less-than comparisons by default raise the invalid exception if either +operand is any kind of NaN. +Equality comparisons, on the other hand, are defined by default to raise the +invalid exception only for signaling NaNs, not quiet NaNs. +For completeness, SoftFloat provides these complementary functions: +

+<float>_eq_signaling
+<float>_le_quiet
+<float>_lt_quiet +
+The signaling equality comparisons are identical to the default +equality comparisons except that the invalid exception is raised for any +NaN input, not just for signaling NaNs. +Similarly, the quiet comparison functions are identical to their +default counterparts except that the invalid exception is not raised for +quiet NaNs. +

+ +

8.9. Signaling NaN Test Functions

+ +

+Functions for testing whether a floating-point value is a signaling NaN are +provided with these names: +

+<float>_isSignalingNaN +
+The functions take one floating-point operand and return a Boolean indicating +whether the operand is a signaling NaN. +Accordingly, the functions have the forms +
+
+bool f64_isSignalingNaN( float64_t a );
+
+
+bool f128M_isSignalingNaN( const float128_t *aPtr );
+
+
+

+ +

8.10. Raise-Exception Function

+ +

+SoftFloat provides a single function for raising floating-point exceptions: +

+
+void softfloat_raise( uint_fast8_t exceptions );
+
+
+The exceptions argument is a mask indicating the set of +exceptions to raise. +(See earlier section 7, Exceptions and Exception Flags.) +In addition to setting the specified exception flags in variable +softfloat_exceptionFlags, the softfloat_raise +function may cause a trap or abort appropriate for the current system. +

+ + +

9. Changes from SoftFloat Release 2

+ +

+Apart from a change in the legal use license, Release 3 of +SoftFloat introduced numerous technical differences compared to earlier +releases. +

+ +

9.1. Name Changes

+ +

+The most obvious and pervasive difference compared to Release 2 +is that the names of most functions and variables have changed, even when the +behavior has not. +First, the floating-point types, the mode variables, the exception flags +variable, the function to raise exceptions, and various associated constants +have been renamed as follows: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
old name, Release 2:new name, Release 3:
float32float32_t
float64float64_t
floatx80extFloat80_t
float128float128_t
float_rounding_modesoftfloat_roundingMode
float_round_nearest_evensoftfloat_round_near_even
float_round_to_zerosoftfloat_round_minMag
float_round_downsoftfloat_round_min
float_round_upsoftfloat_round_max
float_detect_tininesssoftfloat_detectTininess
float_tininess_before_rounding    softfloat_tininess_beforeRounding
float_tininess_after_roundingsoftfloat_tininess_afterRounding
floatx80_rounding_precisionextF80_roundingPrecision
float_exception_flagssoftfloat_exceptionFlags
float_flag_inexactsoftfloat_flag_inexact
float_flag_underflowsoftfloat_flag_underflow
float_flag_overflowsoftfloat_flag_overflow
float_flag_divbyzerosoftfloat_flag_infinite
float_flag_invalidsoftfloat_flag_invalid
float_raisesoftfloat_raise
+
+

+ +

+Furthermore, Release 3 adopted the following new abbreviations for +function names: +

+ + + + + + + + + + + +
used in names in Release 2:    used in names in Release 3:
int32 i32
int64 i64
float32 f32
float64 f64
floatx80 extF80
float128 f128
+
+Thus, for example, the function to add two 32-bit floating-point +numbers, previously called float32_add in Release 2, +is now f32_add. +Lastly, there have been a few other changes to function names: +
+ + + + + + + + + + + + + + + + + + + + + +
used in names in Release 2:   used in names in Release 3:   relevant functions:
_round_to_zero_r_minMagconversions from floating-point to integer (section 8.2)
round_to_introundToIntround-to-integer functions (section 8.7)
is_signaling_nan    isSignalingNaNsignaling NaN test functions (section 8.9)
+
+

+ +

9.2. Changes to Function Arguments

+ +

+Besides simple name changes, some operations were given a different interface +in Release 3 than they had in Release 2: +

    + +
  • +

    +Since Release 3, integer arguments and results of functions have +standard types from header <stdint.h>, such as +uint32_t, whereas previously their types could be defined +differently for each port of SoftFloat, usually using traditional C types such +as unsigned int. +Likewise, functions in Release 3 and later pass Booleans as +standard type bool from <stdbool.h>, whereas +previously these were again passed as a port-specific type (usually +int). +

    + +
  • +

    +As explained earlier in section 4.5, Conventions for Passing +Arguments and Results, SoftFloat functions in Release 3 and +later may pass 80-bit and 128-bit floating-point +values through pointers, meaning that functions take pointer arguments and then +read or write floating-point values at the locations indicated by the pointers. +In Release 2, floating-point arguments and results were always +passed by value, regardless of their size. +

    + +
  • +

    +Functions that round to an integer have additional +roundingMode and exact arguments that +they did not have in Release 2. +Refer to sections 8.2 and 8.7 for descriptions of these functions +since Release 3. +For Release 2, the rounding mode, when needed, was taken from the +same global variable that affects the basic arithmetic operations (now called +softfloat_roundingMode but previously known as +float_rounding_mode). +Also, for Release 2, if the original floating-point input was not +an exact integer value, and if the invalid exception was not raised by +the function, the inexact exception was always raised. +Release 2 had no option to suppress raising inexact in this +case. +Applications using SoftFloat Release 3 or later can get the same +effect as Release 2 by passing variable +softfloat_roundingMode for argument +roundingMode and true for argument +exact. +

    + +
+

+ +

9.3. Added Capabilities

+ +

+With Release 3, some new features have been added that were not +present in Release 2: +

    + +
  • +

    +A port of SoftFloat can now define any of the floating-point types +float32_t, float64_t, extFloat80_t, and +float128_t as aliases for C’s standard floating-point types +float, double, and long +double, using either #define or typedef. +This potential convenience was not supported under Release 2. +

    + +

    +(Note, however, that there may be a performance cost to defining +SoftFloat’s floating-point types this way, depending on the platform and +the applications using SoftFloat. +Ports of SoftFloat may choose to forgo the convenience in favor of better +speed.) +

    + +

    +

  • +Functions have been added for converting between the floating-point types and +unsigned integers. +Release 2 supported only signed integers, not unsigned. +

    + +

    +

  • +A new, fifth rounding mode, softfloat_round_near_maxMag (round to +nearest, with ties to maximum magnitude, away from zero) is now supported for +all cases involving rounding. +

    + +

    +

  • +Fused multiply-add functions have been added for the non-extended formats, +float32_t, float64_t, and float128_t. +

    + +
+

+ +

9.4. Better Compatibility with the C Language

+ +

+Release 3 of SoftFloat was written to conform better to the ISO C +Standard’s rules for portability. +For example, older releases of SoftFloat employed type conversions in ways +that, while commonly practiced, are not fully defined by the C Standard. +Such problematic type conversions have generally been replaced by the use of +unions, the behavior around which is more strictly regulated these days. +

+ +

9.5. New Organization as a Library

+ +

+Starting with Release 3, SoftFloat now builds as a library. +Previously, SoftFloat compiled into a single, monolithic object file containing +all the SoftFloat functions, with the consequence that a program linking with +SoftFloat would get every SoftFloat function in its binary file even if only a +few functions were actually used. +With SoftFloat in the form of a library, a program that is linked by a standard +linker will include only those functions of SoftFloat that it needs and no +others. +

+ +

9.6. Optimization Gains (and Losses)

+ +

+Individual SoftFloat functions have been variously improved in +Release 3 compared to earlier releases. +In particular, better, faster algorithms have been deployed for the operations +of division, square root, and remainder. +For functions operating on the larger 80-bit and +128-bit formats, extFloat80_t and +float128_t, code size has also generally been reduced. +

+ +

+However, because Release 2 compiled all of SoftFloat together as a +single object file, compilers could make optimizations across function calls +when one SoftFloat function calls another. +Now that the functions of SoftFloat are compiled separately and only afterward +linked together into a program, there is not usually the same opportunity to +optimize across function calls. +Some loss of speed has been observed due to this change. +

+ + +

10. Future Directions

+ +

+The following improvements are anticipated for future releases of SoftFloat: +

    +
  • +support for the common 16-bit “half-precision” +floating-point format; +
  • +more functions from the 2008 version of the IEEE Floating-Point Standard; +
  • +consistent, defined behavior for non-canonical representations of extended +format extFloat80_t (discussed in section 4.4, +Non-canonical Representations in extFloat80_t). + +
+

+ + +

11. Contact Information

+ +

+At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page +http://www.jhauser.us/arithmetic/SoftFloat.html. +

+ + + + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c new file mode 100644 index 0000000..31bb286 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +bool extF80M_isSignalingNaN( const extFloat80_t *aPtr ) +{ + const struct extFloat80M *aSPtr; + uint64_t uiA0; + + aSPtr = (const struct extFloat80M *) aPtr; + if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false; + uiA0 = aSPtr->signif; + return + ! (uiA0 & UINT64_C( 0x4000000000000000 )) + && (uiA0 & UINT64_C( 0x3FFFFFFFFFFFFFFF)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c new file mode 100644 index 0000000..d962049 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "primitives.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +bool f128M_isSignalingNaN( const float128_t *aPtr ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false; + return + ((uiA96 & 0x00007FFF) != 0) + || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] + | aWPtr[indexWord( 4, 0 )]) + != 0); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c new file mode 100644 index 0000000..4573e44 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and stores this NaN at the location pointed to by +| `zSPtr'. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToExtF80M( + const struct commonNaN *aPtr, struct extFloat80M *zSPtr ) +{ + + zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF ); + zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c new file mode 100644 index 0000000..6f6083d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ) +{ + struct uint128 uiZ; + + uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF; + uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1; + return uiZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c new file mode 100644 index 0000000..50545c8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument +| `zWPtr' points to an array of four 32-bit elements that concatenate in the +| platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ) +{ + + softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr ); + zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c new file mode 100644 index 0000000..22585f9 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr ) +{ + struct uint128 uiZ; + + uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 ); + uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 ); + return uiZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c new file mode 100644 index 0000000..568930d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ) +{ + + return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c new file mode 100644 index 0000000..dfb7090 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ) +{ + + return + (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 ) + | aPtr->v64>>12; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c new file mode 100644 index 0000000..e2b448b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is +| a NaN, converts this NaN to the common NaN form, and stores the resulting +| common NaN at the location pointed to by `zPtr'. If the NaN is a signaling +| NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80MToCommonNaN( + const struct extFloat80M *aSPtr, struct commonNaN *zPtr ) +{ + + if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = signExtF80UI64( aSPtr->signExp ); + zPtr->v64 = aSPtr->signif<<1; + zPtr->v0 = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c new file mode 100644 index 0000000..e6476cf --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80UIToCommonNaN( + uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA64>>15; + zPtr->v64 = uiA0<<1; + zPtr->v0 = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c new file mode 100644 index 0000000..5cb8577 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, +| converts this NaN to the common NaN form, and stores the resulting common +| NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, +| the invalid exception is raised. Argument `aWPtr' points to an array of +| four 32-bit elements that concatenate in the platform's normal endian order +| to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ) +{ + + if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = aWPtr[indexWordHi( 4 )]>>31; + softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c new file mode 100644 index 0000000..556c349 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_f128UIToCommonNaN( + uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ) +{ + struct uint128 NaNSig; + + if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 ); + zPtr->sign = uiA64>>63; + zPtr->v64 = NaNSig.v64; + zPtr->v0 = NaNSig.v0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c new file mode 100644 index 0000000..6df9df4 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNF32UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA>>31; + zPtr->v64 = (uint_fast64_t) uiA<<41; + zPtr->v0 = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c new file mode 100644 index 0000000..3312852 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNF64UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA>>63; + zPtr->v64 = uiA<<12; + zPtr->v0 = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c new file mode 100644 index 0000000..36babff --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 80-bit extended floating-point values +| pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result +| at the location pointed to by `zSPtr'. If either original floating-point +| value is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNExtF80M( + const struct extFloat80M *aSPtr, + const struct extFloat80M *bSPtr, + struct extFloat80M *zSPtr + ) +{ + bool isSigNaNA; + const struct extFloat80M *sPtr; + bool isSigNaNB; + uint_fast16_t uiB64; + uint64_t uiB0; + uint_fast16_t uiA64; + uint64_t uiA0; + uint_fast16_t uiMagA64, uiMagB64; + + isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ); + sPtr = aSPtr; + if ( ! bSPtr ) { + if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid ); + goto copy; + } + isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr ); + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) { + uiB64 = bSPtr->signExp; + if ( isSigNaNB ) goto returnLargerUIMag; + uiB0 = bSPtr->signif; + if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB; + goto copy; + } else { + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy; + goto copyB; + } + } + uiB64 = bSPtr->signExp; + returnLargerUIMag: + uiA64 = aSPtr->signExp; + uiMagA64 = uiA64 & 0x7FFF; + uiMagB64 = uiB64 & 0x7FFF; + if ( uiMagA64 < uiMagB64 ) goto copyB; + if ( uiMagB64 < uiMagA64 ) goto copy; + uiA0 = aSPtr->signif; + uiB0 = bSPtr->signif; + if ( uiA0 < uiB0 ) goto copyB; + if ( uiB0 < uiA0 ) goto copy; + if ( uiA64 < uiB64 ) goto copy; + copyB: + sPtr = bSPtr; + copy: + zSPtr->signExp = sPtr->signExp; + zSPtr->signif = sPtr->signif | UINT64_C( 0xC000000000000000 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c new file mode 100644 index 0000000..fe80d5f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNExtF80UI( + uint_fast16_t uiA64, + uint_fast64_t uiA0, + uint_fast16_t uiB64, + uint_fast64_t uiB0 + ) +{ + bool isSigNaNA, isSigNaNB; + uint_fast64_t uiNonsigA0, uiNonsigB0; + uint_fast16_t uiMagA64, uiMagB64; + struct uint128 uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 ); + isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiNonsigA0 = uiA0 | UINT64_C( 0xC000000000000000 ); + uiNonsigB0 = uiB0 | UINT64_C( 0xC000000000000000 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerMag; + if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB; + goto returnA; + } else { + if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA; + goto returnB; + } + } + returnLargerMag: + uiMagA64 = uiA64 & 0x7FFF; + uiMagB64 = uiB64 & 0x7FFF; + if ( uiMagA64 < uiMagB64 ) goto returnB; + if ( uiMagB64 < uiMagA64 ) goto returnA; + if ( uiNonsigA0 < uiNonsigB0 ) goto returnB; + if ( uiNonsigB0 < uiNonsigA0 ) goto returnA; + if ( uiA64 < uiB64 ) goto returnA; + returnB: + uiZ.v64 = uiB64; + uiZ.v0 = uiNonsigB0; + return uiZ; + returnA: + uiZ.v64 = uiA64; + uiZ.v0 = uiNonsigA0; + return uiZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c new file mode 100644 index 0000000..ec6936a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 128-bit floating-point values pointed to by +| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location +| pointed to by `zWPtr'. If either original floating-point value is a +| signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', +| and `zWPtr' points to an array of four 32-bit elements that concatenate in +| the platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNF128M( + const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ) +{ + bool isSigNaNA; + const uint32_t *ptr; + + ptr = aWPtr; + isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr ); + if ( + isSigNaNA + || (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr )) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) goto copy; + } + if ( ! softfloat_isNaNF128M( aWPtr ) ) ptr = bWPtr; + copy: + zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000; + zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )]; + zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )]; + zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )]; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c new file mode 100644 index 0000000..654250f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint_fast64_t uiA64, + uint_fast64_t uiA0, + uint_fast64_t uiB64, + uint_fast64_t uiB0 + ) +{ + bool isSigNaNA; + struct uint128 uiZ; + + isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 ); + if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) goto returnNonsigA; + } + if ( isNaNF128UI( uiA64, uiA0 ) ) { + returnNonsigA: + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + } else { + uiZ.v64 = uiB64; + uiZ.v0 = uiB0; + } + uiZ.v64 |= UINT64_C( 0x0000800000000000 ); + return uiZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c new file mode 100644 index 0000000..f1910c7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF32UI( uiA ); + if ( isSigNaNA || softfloat_isSigNaNF32UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) return uiA | 0x00400000; + } + return (isNaNF32UI( uiA ) ? uiA : uiB) | 0x00400000; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c new file mode 100644 index 0000000..40fc9dd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast64_t + softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF64UI( uiA ); + if ( isSigNaNA || softfloat_isSigNaNF64UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) return uiA | UINT64_C( 0x0008000000000000 ); + } + return (isNaNF64UI( uiA ) ? uiA : uiB) | UINT64_C( 0x0008000000000000 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c new file mode 100644 index 0000000..2b5aba8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Raises the exceptions specified by `flags'. Floating-point traps can be +| defined here if desired. It is currently not possible for such a trap +| to substitute a result value. If traps are not implemented, this routine +| should be simply `softfloat_exceptionFlags |= flags;'. +*----------------------------------------------------------------------------*/ +void softfloat_raiseFlags( uint_fast8_t flags ) +{ + + softfloat_exceptionFlags |= flags; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h new file mode 100644 index 0000000..f8888e5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +#ifndef specialize_h +#define specialize_h 1 + +#include +#include +#include "softfloat_types.h" + +/*---------------------------------------------------------------------------- +| Default value for `softfloat_detectTininess'. +*----------------------------------------------------------------------------*/ +#define init_detectTininess softfloat_tininess_afterRounding + +/*---------------------------------------------------------------------------- +| "Common NaN" structure, used to transfer NaN representations from one format +| to another. +*----------------------------------------------------------------------------*/ +struct commonNaN { + bool sign; +#ifdef LITTLEENDIAN + uint64_t v0, v64; +#else + uint64_t v64, v0; +#endif +}; + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 32-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF32UI 0xFFC00000 + +/*---------------------------------------------------------------------------- +| Returns true when 32-bit unsigned integer `uiA' has the bit pattern of a +| 32-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 64-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns true when 64-bit unsigned integer `uiA' has the bit pattern of a +| 64-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast64_t + softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 80-bit extended floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNExtF80UI64 0xFFFF +#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns true when the 80-bit unsigned integer formed from concatenating +| 16-bit `uiA64' and 64-bit `uiA0' has the bit pattern of an 80-bit extended +| floating-point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) + +#ifdef SOFTFLOAT_FAST_INT64 + +/*---------------------------------------------------------------------------- +| The following functions are needed only when `SOFTFLOAT_FAST_INT64' is +| defined. +*----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80UIToCommonNaN( + uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNExtF80UI( + uint_fast16_t uiA64, + uint_fast64_t uiA0, + uint_fast16_t uiB64, + uint_fast64_t uiB0 + ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 128-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) +#define defaultNaNF128UI0 UINT64_C( 0 ) + +/*---------------------------------------------------------------------------- +| Returns true when the 128-bit unsigned integer formed from concatenating +| 64-bit `uiA64' and 64-bit `uiA0' has the bit pattern of a 128-bit floating- +| point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_f128UIToCommonNaN( + uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint_fast64_t uiA64, + uint_fast64_t uiA0, + uint_fast64_t uiB64, + uint_fast64_t uiB0 + ); + +#else + +/*---------------------------------------------------------------------------- +| The following functions are needed only when `SOFTFLOAT_FAST_INT64' is not +| defined. +*----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is +| a NaN, converts this NaN to the common NaN form, and stores the resulting +| common NaN at the location pointed to by `zPtr'. If the NaN is a signaling +| NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80MToCommonNaN( + const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and stores this NaN at the location pointed to by +| `zSPtr'. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToExtF80M( + const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 80-bit extended floating-point values +| pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result +| at the location pointed to by `zSPtr'. If either original floating-point +| value is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNExtF80M( + const struct extFloat80M *aSPtr, + const struct extFloat80M *bSPtr, + struct extFloat80M *zSPtr + ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 128-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF128UI96 0xFFFF8000 +#define defaultNaNF128UI64 0 +#define defaultNaNF128UI32 0 +#define defaultNaNF128UI0 0 + +/*---------------------------------------------------------------------------- +| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, +| converts this NaN to the common NaN form, and stores the resulting common +| NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, +| the invalid exception is raised. Argument `aWPtr' points to an array of +| four 32-bit elements that concatenate in the platform's normal endian order +| to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument +| `zWPtr' points to an array of four 32-bit elements that concatenate in the +| platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 128-bit floating-point values pointed to by +| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location +| pointed to by `zWPtr'. If either original floating-point value is a +| signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', +| and `zWPtr' points to an array of four 32-bit elements that concatenate in +| the platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNF128M( + const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); + +#endif + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/sub.mk b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/sub.mk new file mode 100644 index 0000000..175c1c3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/sub.mk @@ -0,0 +1,7 @@ +srcs-y += softfloat_raiseFlags.c +srcs-y += s_propagateNaNF32UI.c +srcs-y += s_f32UIToCommonNaN.c +srcs-y += s_commonNaNToF64UI.c +srcs-y += s_f64UIToCommonNaN.c +srcs-y += s_propagateNaNF64UI.c +srcs-y += s_commonNaNToF32UI.c diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c new file mode 100644 index 0000000..31bb286 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +bool extF80M_isSignalingNaN( const extFloat80_t *aPtr ) +{ + const struct extFloat80M *aSPtr; + uint64_t uiA0; + + aSPtr = (const struct extFloat80M *) aPtr; + if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false; + uiA0 = aSPtr->signif; + return + ! (uiA0 & UINT64_C( 0x4000000000000000 )) + && (uiA0 & UINT64_C( 0x3FFFFFFFFFFFFFFF)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c new file mode 100644 index 0000000..d962049 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "primitives.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +bool f128M_isSignalingNaN( const float128_t *aPtr ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false; + return + ((uiA96 & 0x00007FFF) != 0) + || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] + | aWPtr[indexWord( 4, 0 )]) + != 0); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c new file mode 100644 index 0000000..4573e44 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and stores this NaN at the location pointed to by +| `zSPtr'. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToExtF80M( + const struct commonNaN *aPtr, struct extFloat80M *zSPtr ) +{ + + zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF ); + zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c new file mode 100644 index 0000000..6f6083d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ) +{ + struct uint128 uiZ; + + uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF; + uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1; + return uiZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c new file mode 100644 index 0000000..50545c8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument +| `zWPtr' points to an array of four 32-bit elements that concatenate in the +| platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ) +{ + + softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr ); + zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c new file mode 100644 index 0000000..22585f9 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr ) +{ + struct uint128 uiZ; + + uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 ); + uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 ); + return uiZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c new file mode 100644 index 0000000..568930d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ) +{ + + return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c new file mode 100644 index 0000000..dfb7090 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ) +{ + + return + (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 ) + | aPtr->v64>>12; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c new file mode 100644 index 0000000..e2b448b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is +| a NaN, converts this NaN to the common NaN form, and stores the resulting +| common NaN at the location pointed to by `zPtr'. If the NaN is a signaling +| NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80MToCommonNaN( + const struct extFloat80M *aSPtr, struct commonNaN *zPtr ) +{ + + if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = signExtF80UI64( aSPtr->signExp ); + zPtr->v64 = aSPtr->signif<<1; + zPtr->v0 = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c new file mode 100644 index 0000000..e6476cf --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80UIToCommonNaN( + uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA64>>15; + zPtr->v64 = uiA0<<1; + zPtr->v0 = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c new file mode 100644 index 0000000..5cb8577 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, +| converts this NaN to the common NaN form, and stores the resulting common +| NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, +| the invalid exception is raised. Argument `aWPtr' points to an array of +| four 32-bit elements that concatenate in the platform's normal endian order +| to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ) +{ + + if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = aWPtr[indexWordHi( 4 )]>>31; + softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c new file mode 100644 index 0000000..556c349 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_f128UIToCommonNaN( + uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ) +{ + struct uint128 NaNSig; + + if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 ); + zPtr->sign = uiA64>>63; + zPtr->v64 = NaNSig.v64; + zPtr->v0 = NaNSig.v0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c new file mode 100644 index 0000000..6df9df4 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNF32UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA>>31; + zPtr->v64 = (uint_fast64_t) uiA<<41; + zPtr->v0 = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c new file mode 100644 index 0000000..3312852 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ) +{ + + if ( softfloat_isSigNaNF64UI( uiA ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + zPtr->sign = uiA>>63; + zPtr->v64 = uiA<<12; + zPtr->v0 = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c new file mode 100644 index 0000000..36babff --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 80-bit extended floating-point values +| pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result +| at the location pointed to by `zSPtr'. If either original floating-point +| value is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNExtF80M( + const struct extFloat80M *aSPtr, + const struct extFloat80M *bSPtr, + struct extFloat80M *zSPtr + ) +{ + bool isSigNaNA; + const struct extFloat80M *sPtr; + bool isSigNaNB; + uint_fast16_t uiB64; + uint64_t uiB0; + uint_fast16_t uiA64; + uint64_t uiA0; + uint_fast16_t uiMagA64, uiMagB64; + + isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ); + sPtr = aSPtr; + if ( ! bSPtr ) { + if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid ); + goto copy; + } + isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr ); + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) { + uiB64 = bSPtr->signExp; + if ( isSigNaNB ) goto returnLargerUIMag; + uiB0 = bSPtr->signif; + if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB; + goto copy; + } else { + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy; + goto copyB; + } + } + uiB64 = bSPtr->signExp; + returnLargerUIMag: + uiA64 = aSPtr->signExp; + uiMagA64 = uiA64 & 0x7FFF; + uiMagB64 = uiB64 & 0x7FFF; + if ( uiMagA64 < uiMagB64 ) goto copyB; + if ( uiMagB64 < uiMagA64 ) goto copy; + uiA0 = aSPtr->signif; + uiB0 = bSPtr->signif; + if ( uiA0 < uiB0 ) goto copyB; + if ( uiB0 < uiA0 ) goto copy; + if ( uiA64 < uiB64 ) goto copy; + copyB: + sPtr = bSPtr; + copy: + zSPtr->signExp = sPtr->signExp; + zSPtr->signif = sPtr->signif | UINT64_C( 0xC000000000000000 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c new file mode 100644 index 0000000..fe80d5f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNExtF80UI( + uint_fast16_t uiA64, + uint_fast64_t uiA0, + uint_fast16_t uiB64, + uint_fast64_t uiB0 + ) +{ + bool isSigNaNA, isSigNaNB; + uint_fast64_t uiNonsigA0, uiNonsigB0; + uint_fast16_t uiMagA64, uiMagB64; + struct uint128 uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 ); + isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiNonsigA0 = uiA0 | UINT64_C( 0xC000000000000000 ); + uiNonsigB0 = uiB0 | UINT64_C( 0xC000000000000000 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerMag; + if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB; + goto returnA; + } else { + if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA; + goto returnB; + } + } + returnLargerMag: + uiMagA64 = uiA64 & 0x7FFF; + uiMagB64 = uiB64 & 0x7FFF; + if ( uiMagA64 < uiMagB64 ) goto returnB; + if ( uiMagB64 < uiMagA64 ) goto returnA; + if ( uiNonsigA0 < uiNonsigB0 ) goto returnB; + if ( uiNonsigB0 < uiNonsigA0 ) goto returnA; + if ( uiA64 < uiB64 ) goto returnA; + returnB: + uiZ.v64 = uiB64; + uiZ.v0 = uiNonsigB0; + return uiZ; + returnA: + uiZ.v64 = uiA64; + uiZ.v0 = uiNonsigA0; + return uiZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c new file mode 100644 index 0000000..43ce632 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 128-bit floating-point values pointed to by +| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location +| pointed to by `zWPtr'. If either original floating-point value is a +| signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', +| and `zWPtr' points to an array of four 32-bit elements that concatenate in +| the platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNF128M( + const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ) +{ + bool isSigNaNA; + const uint32_t *ptr; + bool isSigNaNB; + uint32_t uiA96, uiB96, wordMagA, wordMagB; + + isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr ); + ptr = aWPtr; + if ( ! bWPtr ) { + if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid ); + goto copy; + } + isSigNaNB = f128M_isSignalingNaN( (const float128_t *) bWPtr ); + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerUIMag; + if ( softfloat_isNaNF128M( bWPtr ) ) goto copyB; + goto copy; + } else { + if ( softfloat_isNaNF128M( aWPtr ) ) goto copy; + goto copyB; + } + } + returnLargerUIMag: + uiA96 = aWPtr[indexWordHi( 4 )]; + uiB96 = bWPtr[indexWordHi( 4 )]; + wordMagA = uiA96 & 0x7FFFFFFF; + wordMagB = uiB96 & 0x7FFFFFFF; + if ( wordMagA < wordMagB ) goto copyB; + if ( wordMagB < wordMagA ) goto copy; + wordMagA = aWPtr[indexWord( 4, 2 )]; + wordMagB = bWPtr[indexWord( 4, 2 )]; + if ( wordMagA < wordMagB ) goto copyB; + if ( wordMagB < wordMagA ) goto copy; + wordMagA = aWPtr[indexWord( 4, 1 )]; + wordMagB = bWPtr[indexWord( 4, 1 )]; + if ( wordMagA < wordMagB ) goto copyB; + if ( wordMagB < wordMagA ) goto copy; + wordMagA = aWPtr[indexWord( 4, 0 )]; + wordMagB = bWPtr[indexWord( 4, 0 )]; + if ( wordMagA < wordMagB ) goto copyB; + if ( wordMagB < wordMagA ) goto copy; + if ( uiA96 < uiB96 ) goto copy; + copyB: + ptr = bWPtr; + copy: + zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000; + zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )]; + zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )]; + zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )]; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c new file mode 100644 index 0000000..f7e0f76 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint_fast64_t uiA64, + uint_fast64_t uiA0, + uint_fast64_t uiB64, + uint_fast64_t uiB0 + ) +{ + bool isSigNaNA, isSigNaNB; + uint_fast64_t uiNonsigA64, uiNonsigB64, uiMagA64, uiMagB64; + struct uint128 uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 ); + isSigNaNB = softfloat_isSigNaNF128UI( uiB64, uiB0 ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiNonsigA64 = uiA64 | UINT64_C( 0x0000800000000000 ); + uiNonsigB64 = uiB64 | UINT64_C( 0x0000800000000000 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerMag; + if ( isNaNF128UI( uiB64, uiB0 ) ) goto returnB; + goto returnA; + } else { + if ( isNaNF128UI( uiA64, uiA0 ) ) goto returnA; + goto returnB; + } + } + returnLargerMag: + uiMagA64 = uiNonsigA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + uiMagB64 = uiNonsigB64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + if ( uiMagA64 < uiMagB64 ) goto returnB; + if ( uiMagB64 < uiMagA64 ) goto returnA; + if ( uiA0 < uiB0 ) goto returnB; + if ( uiB0 < uiA0 ) goto returnA; + if ( uiNonsigA64 < uiNonsigB64 ) goto returnA; + returnB: + uiZ.v64 = uiNonsigB64; + uiZ.v0 = uiB0; + return uiZ; + returnA: + uiZ.v64 = uiNonsigA64; + uiZ.v0 = uiA0; + return uiZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c new file mode 100644 index 0000000..22ed68e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) +{ + bool isSigNaNA, isSigNaNB; + uint_fast32_t uiNonsigA, uiNonsigB, uiMagA, uiMagB; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isSigNaNA = softfloat_isSigNaNF32UI( uiA ); + isSigNaNB = softfloat_isSigNaNF32UI( uiB ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiNonsigA = uiA | 0x00400000; + uiNonsigB = uiB | 0x00400000; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerMag; + return isNaNF32UI( uiB ) ? uiNonsigB : uiNonsigA; + } else { + return isNaNF32UI( uiA ) ? uiNonsigA : uiNonsigB; + } + } + returnLargerMag: + uiMagA = uiNonsigA & 0x7FFFFFFF; + uiMagB = uiNonsigB & 0x7FFFFFFF; + if ( uiMagA < uiMagB ) return uiNonsigB; + if ( uiMagB < uiMagA ) return uiNonsigA; + return (uiNonsigA < uiNonsigB) ? uiNonsigA : uiNonsigB; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c new file mode 100644 index 0000000..bb76f56 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast64_t + softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) +{ + bool isSigNaNA, isSigNaNB; + uint_fast64_t uiNonsigA, uiNonsigB, uiMagA, uiMagB; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isSigNaNA = softfloat_isSigNaNF64UI( uiA ); + isSigNaNB = softfloat_isSigNaNF64UI( uiB ); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiNonsigA = uiA | UINT64_C( 0x0008000000000000 ); + uiNonsigB = uiB | UINT64_C( 0x0008000000000000 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isSigNaNA | isSigNaNB ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( isSigNaNA ) { + if ( isSigNaNB ) goto returnLargerMag; + return isNaNF64UI( uiB ) ? uiNonsigB : uiNonsigA; + } else { + return isNaNF64UI( uiA ) ? uiNonsigA : uiNonsigB; + } + } + returnLargerMag: + uiMagA = uiNonsigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + uiMagB = uiNonsigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + if ( uiMagA < uiMagB ) return uiNonsigB; + if ( uiMagB < uiMagA ) return uiNonsigA; + return (uiNonsigA < uiNonsigB) ? uiNonsigA : uiNonsigB; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c new file mode 100644 index 0000000..2b5aba8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Raises the exceptions specified by `flags'. Floating-point traps can be +| defined here if desired. It is currently not possible for such a trap +| to substitute a result value. If traps are not implemented, this routine +| should be simply `softfloat_exceptionFlags |= flags;'. +*----------------------------------------------------------------------------*/ +void softfloat_raiseFlags( uint_fast8_t flags ) +{ + + softfloat_exceptionFlags |= flags; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h new file mode 100644 index 0000000..8f4d6c8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +#ifndef specialize_h +#define specialize_h 1 + +#include +#include +#include "softfloat_types.h" + +/*---------------------------------------------------------------------------- +| Default value for `softfloat_detectTininess'. +*----------------------------------------------------------------------------*/ +#define init_detectTininess softfloat_tininess_afterRounding; + +/*---------------------------------------------------------------------------- +| "Common NaN" structure, used to transfer NaN representations from one format +| to another. +*----------------------------------------------------------------------------*/ +struct commonNaN { + bool sign; +#ifdef LITTLEENDIAN + uint64_t v0, v64; +#else + uint64_t v64, v0; +#endif +}; + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 32-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF32UI 0xFFC00000 + +/*---------------------------------------------------------------------------- +| Returns true when 32-bit unsigned integer `uiA' has the bit pattern of a +| 32-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast32_t + softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 64-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns true when 64-bit unsigned integer `uiA' has the bit pattern of a +| 64-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint_fast64_t + softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 80-bit extended floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNExtF80UI64 0xFFFF +#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) + +/*---------------------------------------------------------------------------- +| Returns true when the 80-bit unsigned integer formed from concatenating +| 16-bit `uiA64' and 64-bit `uiA0' has the bit pattern of an 80-bit extended +| floating-point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) + +#ifdef SOFTFLOAT_FAST_INT64 + +/*---------------------------------------------------------------------------- +| The following functions are needed only when `SOFTFLOAT_FAST_INT64' is +| defined. +*----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80UIToCommonNaN( + uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNExtF80UI( + uint_fast16_t uiA64, + uint_fast64_t uiA0, + uint_fast16_t uiB64, + uint_fast64_t uiB0 + ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 128-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) +#define defaultNaNF128UI0 UINT64_C( 0 ) + +/*---------------------------------------------------------------------------- +| Returns true when the 128-bit unsigned integer formed from concatenating +| 64-bit `uiA64' and 64-bit `uiA0' has the bit pattern of a 128-bit floating- +| point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_f128UIToCommonNaN( + uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint_fast64_t uiA64, + uint_fast64_t uiA0, + uint_fast64_t uiB64, + uint_fast64_t uiB0 + ); + +#else + +/*---------------------------------------------------------------------------- +| The following functions are needed only when `SOFTFLOAT_FAST_INT64' is not +| defined. +*----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is +| a NaN, converts this NaN to the common NaN form, and stores the resulting +| common NaN at the location pointed to by `zPtr'. If the NaN is a signaling +| NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_extF80MToCommonNaN( + const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and stores this NaN at the location pointed to by +| `zSPtr'. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToExtF80M( + const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 80-bit extended floating-point values +| pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result +| at the location pointed to by `zSPtr'. If either original floating-point +| value is a signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNExtF80M( + const struct extFloat80M *aSPtr, + const struct extFloat80M *bSPtr, + struct extFloat80M *zSPtr + ); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 128-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF128UI96 0xFFFF8000 +#define defaultNaNF128UI64 0 +#define defaultNaNF128UI32 0 +#define defaultNaNF128UI0 0 + +/*---------------------------------------------------------------------------- +| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, +| converts this NaN to the common NaN form, and stores the resulting common +| NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, +| the invalid exception is raised. Argument `aWPtr' points to an array of +| four 32-bit elements that concatenate in the platform's normal endian order +| to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument +| `zWPtr' points to an array of four 32-bit elements that concatenate in the +| platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); + +/*---------------------------------------------------------------------------- +| Assuming at least one of the two 128-bit floating-point values pointed to by +| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location +| pointed to by `zWPtr'. If either original floating-point value is a +| signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', +| and `zWPtr' points to an array of four 32-bit elements that concatenate in +| the platform's normal endian order to form a 128-bit floating-point value. +*----------------------------------------------------------------------------*/ +void + softfloat_propagateNaNF128M( + const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); + +#endif + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c new file mode 100644 index 0000000..25f4e96 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + extF80M_add( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool signA; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + extFloat80_t + (*magsFuncPtr)( + uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); +#endif + + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + signA = signExtF80UI64( uiA64 ); + uiB64 = bSPtr->signExp; + uiB0 = bSPtr->signif; + signB = signExtF80UI64( uiB64 ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + *zPtr = softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); + } else { + *zPtr = softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_addMagsExtF80 : softfloat_subMagsExtF80; + *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); +#endif + +} + +#else + +void + extF80M_add( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + + softfloat_addExtF80M( + (const struct extFloat80M *) aPtr, + (const struct extFloat80M *) bPtr, + (struct extFloat80M *) zPtr, + false + ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c new file mode 100644 index 0000000..ef600c5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + extF80M_div( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + + *zPtr = extF80_div( *aPtr, *bPtr ); + +} + +#else + +void + extF80M_div( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + struct extFloat80M *zSPtr; + uint_fast16_t uiA64; + int32_t expA; + uint_fast16_t uiB64; + int32_t expB; + bool signZ; + uint64_t sigA, x64; + int32_t expZ; + int shiftCount; + uint32_t y[3], recip32, sigB[3]; + int ix; + uint32_t q, qs[2]; + uint_fast16_t uiZ64; + uint64_t uiZ0; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + zSPtr = (struct extFloat80M *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + expA = expExtF80UI64( uiA64 ); + uiB64 = bSPtr->signExp; + expB = expExtF80UI64( uiB64 ); + signZ = signExtF80UI64( uiA64 ) ^ signExtF80UI64( uiB64 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; + if ( expA == 0x7FFF ) { + if ( expB == 0x7FFF ) goto invalid; + goto infinity; + } + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigA = aSPtr->signif; + x64 = bSPtr->signif; + if ( ! expB ) expB = 1; + if ( ! (x64 & UINT64_C( 0x8000000000000000 )) ) { + if ( ! x64 ) { + if ( ! sigA ) goto invalid; + softfloat_raiseFlags( softfloat_flag_infinite ); + goto infinity; + } + expB += softfloat_normExtF80SigM( &x64 ); + } + if ( ! expA ) expA = 1; + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigA ) goto zero; + expA += softfloat_normExtF80SigM( &sigA ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FFF; + shiftCount = 29; + if ( sigA < x64 ) { + --expZ; + shiftCount = 30; + } + softfloat_shortShiftLeft64To96M( sigA, shiftCount, y ); + recip32 = softfloat_approxRecip32_1( x64>>32 ); + sigB[indexWord( 3, 0 )] = (uint32_t) x64<<30; + x64 >>= 2; + sigB[indexWord( 3, 2 )] = x64>>32; + sigB[indexWord( 3, 1 )] = x64; + ix = 2; + for (;;) { + x64 = (uint64_t) y[indexWordHi( 3 )] * recip32; + q = (x64 + 0x80000000)>>32; + --ix; + if ( ix < 0 ) break; + softfloat_remStep96MBy32( y, 29, sigB, q, y ); + if ( y[indexWordHi( 3 )] & 0x80000000 ) { + --q; + softfloat_add96M( y, sigB, y ); + } + qs[ix] = q; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ((q + 1) & 0x3FFFFF) < 2 ) { + softfloat_remStep96MBy32( y, 29, sigB, q, y ); + if ( y[indexWordHi( 3 )] & 0x80000000 ) { + --q; + softfloat_add96M( y, sigB, y ); + } else if ( softfloat_compare96M( sigB, y ) <= 0 ) { + ++q; + softfloat_sub96M( y, sigB, y ); + } + if ( + y[indexWordLo( 3 )] || y[indexWord( 3, 1 )] || y[indexWord( 3, 2 )] + ) { + q |= 1; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + x64 = (uint64_t) q<<9; + y[indexWord( 3, 0 )] = x64; + x64 = ((uint64_t) qs[0]<<6) + (x64>>32); + y[indexWord( 3, 1 )] = x64; + y[indexWord( 3, 2 )] = (qs[1]<<3) + (x64>>32); + softfloat_roundPackMToExtF80M( + signZ, expZ, y, extF80_roundingPrecision, zSPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_invalidExtF80M( zSPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ64 = packToExtF80UI64( signZ, 0 ); + uiZ0 = 0; + uiZ: + zSPtr->signExp = uiZ64; + zSPtr->signif = uiZ0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c new file mode 100644 index 0000000..bbf828d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + + return extF80_eq( *aPtr, *bPtr ); + +} + +#else + +bool extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + uint_fast16_t uiA64; + uint64_t uiA0; + uint_fast16_t uiB64; + uint64_t uiB0; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + uiB64 = bSPtr->signExp; + uiB0 = bSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) + || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( uiA0 == uiB0 ) { + return (uiA64 == uiB64) || ! uiA0; + } else { + if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { + return ! softfloat_compareNonnormExtF80M( aSPtr, bSPtr ); + } + return false; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c new file mode 100644 index 0000000..d8879f3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool extF80M_eq_signaling( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + + return extF80_eq_signaling( *aPtr, *bPtr ); + +} + +#else + +bool extF80M_eq_signaling( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + uint_fast16_t uiA64; + uint64_t uiA0; + uint_fast16_t uiB64; + uint64_t uiB0; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + uiB64 = bSPtr->signExp; + uiB0 = bSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( uiA0 == uiB0 ) { + return (uiA64 == uiB64) || ! uiA0; + } else { + if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { + return ! softfloat_compareNonnormExtF80M( aSPtr, bSPtr ); + } + return false; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c new file mode 100644 index 0000000..fff29ba --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + + return extF80_le( *aPtr, *bPtr ); + +} + +#else + +bool extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + uint_fast16_t uiA64; + uint64_t uiA0; + uint_fast16_t uiB64; + uint64_t uiB0; + bool signA, ltMags; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + uiB64 = bSPtr->signExp; + uiB0 = bSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signExtF80UI64( uiA64 ); + if ( (uiA64 ^ uiB64) & 0x8000 ) { + /*-------------------------------------------------------------------- + | Signs are different. + *--------------------------------------------------------------------*/ + return signA || ! (uiA0 | uiB0); + } else { + /*-------------------------------------------------------------------- + | Signs are the same. + *--------------------------------------------------------------------*/ + if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { + return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) <= 0); + } + if ( uiA64 == uiB64 ) { + if ( uiA0 == uiB0 ) return true; + ltMags = (uiA0 < uiB0); + } else { + ltMags = (uiA64 < uiB64); + } + return signA ^ ltMags; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c new file mode 100644 index 0000000..5661064 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool extF80M_le_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + + return extF80_le_quiet( *aPtr, *bPtr ); + +} + +#else + +bool extF80M_le_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + uint_fast16_t uiA64; + uint64_t uiA0; + uint_fast16_t uiB64; + uint64_t uiB0; + bool signA, ltMags; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + uiB64 = bSPtr->signExp; + uiB0 = bSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) + || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signExtF80UI64( uiA64 ); + if ( (uiA64 ^ uiB64) & 0x8000 ) { + /*-------------------------------------------------------------------- + | Signs are different. + *--------------------------------------------------------------------*/ + return signA || ! (uiA0 | uiB0); + } else { + /*-------------------------------------------------------------------- + | Signs are the same. + *--------------------------------------------------------------------*/ + if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { + return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) <= 0); + } + if ( uiA64 == uiB64 ) { + if ( uiA0 == uiB0 ) return true; + ltMags = (uiA0 < uiB0); + } else { + ltMags = (uiA64 < uiB64); + } + return signA ^ ltMags; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c new file mode 100644 index 0000000..d9d2293 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + + return extF80_lt( *aPtr, *bPtr ); + +} + +#else + +bool extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + uint_fast16_t uiA64; + uint64_t uiA0; + uint_fast16_t uiB64; + uint64_t uiB0; + bool signA, ltMags; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + uiB64 = bSPtr->signExp; + uiB0 = bSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signExtF80UI64( uiA64 ); + if ( (uiA64 ^ uiB64) & 0x8000 ) { + /*-------------------------------------------------------------------- + | Signs are different. + *--------------------------------------------------------------------*/ + return signA && ((uiA0 | uiB0) != 0); + } else { + /*-------------------------------------------------------------------- + | Signs are the same. + *--------------------------------------------------------------------*/ + if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { + return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) < 0); + } + if ( uiA64 == uiB64 ) { + if ( uiA0 == uiB0 ) return false; + ltMags = (uiA0 < uiB0); + } else { + ltMags = (uiA64 < uiB64); + } + return signA ^ ltMags; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c new file mode 100644 index 0000000..a650b9a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + + return extF80_lt_quiet( *aPtr, *bPtr ); + +} + +#else + +bool extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + uint_fast16_t uiA64; + uint64_t uiA0; + uint_fast16_t uiB64; + uint64_t uiB0; + bool signA, ltMags; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + uiB64 = bSPtr->signExp; + uiB0 = bSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) + || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signExtF80UI64( uiA64 ); + if ( (uiA64 ^ uiB64) & 0x8000 ) { + /*-------------------------------------------------------------------- + | Signs are different. + *--------------------------------------------------------------------*/ + return signA && ((uiA0 | uiB0) != 0); + } else { + /*-------------------------------------------------------------------- + | Signs are the same. + *--------------------------------------------------------------------*/ + if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { + return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) < 0); + } + if ( uiA64 == uiB64 ) { + if ( uiA0 == uiB0 ) return false; + ltMags = (uiA0 < uiB0); + } else { + ltMags = (uiA64 < uiB64); + } + return signA ^ ltMags; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c new file mode 100644 index 0000000..4edaf2c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + extF80M_mul( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + + *zPtr = extF80_mul( *aPtr, *bPtr ); + +} + +#else + +void + extF80M_mul( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + struct extFloat80M *zSPtr; + uint_fast16_t uiA64; + int32_t expA; + uint_fast16_t uiB64; + int32_t expB; + bool signZ; + uint_fast16_t exp, uiZ64; + uint64_t uiZ0, sigA, sigB; + int32_t expZ; + uint32_t sigProd[4], *extSigZPtr; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + zSPtr = (struct extFloat80M *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + expA = expExtF80UI64( uiA64 ); + uiB64 = bSPtr->signExp; + expB = expExtF80UI64( uiB64 ); + signZ = signExtF80UI64( uiA64 ) ^ signExtF80UI64( uiB64 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; + if ( + (! aSPtr->signif && (expA != 0x7FFF)) + || (! bSPtr->signif && (expB != 0x7FFF)) + ) { + softfloat_invalidExtF80M( zSPtr ); + return; + } + uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) expA = 1; + sigA = aSPtr->signif; + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigA ) goto zero; + expA += softfloat_normExtF80SigM( &sigA ); + } + if ( ! expB ) expB = 1; + sigB = bSPtr->signif; + if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigB ) goto zero; + expB += softfloat_normExtF80SigM( &sigB ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FFE; + softfloat_mul64To128M( sigA, sigB, sigProd ); + if ( sigProd[indexWordLo( 4 )] ) sigProd[indexWord( 4, 1 )] |= 1; + extSigZPtr = &sigProd[indexMultiwordHi( 4, 3 )]; + if ( sigProd[indexWordHi( 4 )] < 0x80000000 ) { + --expZ; + softfloat_add96M( extSigZPtr, extSigZPtr, extSigZPtr ); + } + softfloat_roundPackMToExtF80M( + signZ, expZ, extSigZPtr, extF80_roundingPrecision, zSPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ64 = packToExtF80UI64( signZ, 0 ); + uiZ0 = 0; + uiZ: + zSPtr->signExp = uiZ64; + zSPtr->signif = uiZ0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c new file mode 100644 index 0000000..c497141 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + extF80M_rem( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + + *zPtr = extF80_rem( *aPtr, *bPtr ); + +} + +#else + +void + extF80M_rem( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + struct extFloat80M *zSPtr; + uint_fast16_t uiA64; + int32_t expA, expB; + uint64_t x64; + bool signRem; + uint64_t sigA; + int32_t expDiff; + uint32_t rem[3], x[3], sig32B, q, recip32, rem2[3], *remPtr, *altRemPtr; + uint32_t *newRemPtr, wordMeanRem; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + zSPtr = (struct extFloat80M *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + expA = expExtF80UI64( uiA64 ); + expB = expExtF80UI64( bSPtr->signExp ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; + if ( expA == 0x7FFF ) goto invalid; + /*-------------------------------------------------------------------- + | If we get here, then argument b is an infinity and `expB' is 0x7FFF; + | Doubling `expB' is an easy way to ensure that `expDiff' later is + | less than -1, which will result in returning a canonicalized version + | of argument a. + *--------------------------------------------------------------------*/ + expB += expB; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) expB = 1; + x64 = bSPtr->signif; + if ( ! (x64 & UINT64_C( 0x8000000000000000 )) ) { + if ( ! x64 ) goto invalid; + expB += softfloat_normExtF80SigM( &x64 ); + } + signRem = signExtF80UI64( uiA64 ); + if ( ! expA ) expA = 1; + sigA = aSPtr->signif; + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigA ) { + expA = 0; + goto copyA; + } + expA += softfloat_normExtF80SigM( &sigA ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if ( expDiff < -1 ) goto copyA; + rem[indexWord( 3, 2 )] = sigA>>34; + rem[indexWord( 3, 1 )] = sigA>>2; + rem[indexWord( 3, 0 )] = (uint32_t) sigA<<30; + x[indexWord( 3, 0 )] = (uint32_t) x64<<30; + sig32B = x64>>32; + x64 >>= 2; + x[indexWord( 3, 2 )] = x64>>32; + x[indexWord( 3, 1 )] = x64; + if ( expDiff < 1 ) { + if ( expDiff ) { + --expB; + softfloat_add96M( x, x, x ); + q = 0; + } else { + q = (softfloat_compare96M( x, rem ) <= 0); + if ( q ) softfloat_sub96M( rem, x, rem ); + } + } else { + recip32 = softfloat_approxRecip32_1( sig32B ); + expDiff -= 30; + for (;;) { + x64 = (uint64_t) rem[indexWordHi( 3 )] * recip32; + if ( expDiff < 0 ) break; + q = (x64 + 0x80000000)>>32; + softfloat_remStep96MBy32( rem, 29, x, q, rem ); + if ( rem[indexWordHi( 3 )] & 0x80000000 ) { + softfloat_add96M( rem, x, rem ); + } + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -29 here.) + *--------------------------------------------------------------------*/ + q = (uint32_t) (x64>>32)>>(~expDiff & 31); + softfloat_remStep96MBy32( rem, expDiff + 30, x, q, rem ); + if ( rem[indexWordHi( 3 )] & 0x80000000 ) { + remPtr = rem; + altRemPtr = rem2; + softfloat_add96M( remPtr, x, altRemPtr ); + goto selectRem; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + remPtr = rem; + altRemPtr = rem2; + do { + ++q; + newRemPtr = altRemPtr; + softfloat_sub96M( remPtr, x, newRemPtr ); + altRemPtr = remPtr; + remPtr = newRemPtr; + } while ( ! (remPtr[indexWordHi( 3 )] & 0x80000000) ); + selectRem: + softfloat_add96M( remPtr, altRemPtr, x ); + wordMeanRem = x[indexWordHi( 3 )]; + if ( + (wordMeanRem & 0x80000000) + || (! wordMeanRem && (q & 1) && ! x[indexWord( 3, 0 )] + && ! x[indexWord( 3, 1 )]) + ) { + remPtr = altRemPtr; + } + if ( remPtr[indexWordHi( 3 )] & 0x80000000 ) { + signRem = ! signRem; + softfloat_negX96M( remPtr ); + } + softfloat_normRoundPackMToExtF80M( signRem, expB + 2, remPtr, 80, zSPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_invalidExtF80M( zSPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + copyA: + if ( expA < 1 ) { + sigA >>= 1 - expA; + expA = 0; + } + zSPtr->signExp = packToExtF80UI64( signRem, expA ); + zSPtr->signif = sigA; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c new file mode 100644 index 0000000..b89af5e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + extF80M_roundToInt( + const extFloat80_t *aPtr, + uint_fast8_t roundingMode, + bool exact, + extFloat80_t *zPtr + ) +{ + + *zPtr = extF80_roundToInt( *aPtr, roundingMode, exact ); + +} + +#else + +void + extF80M_roundToInt( + const extFloat80_t *aPtr, + uint_fast8_t roundingMode, + bool exact, + extFloat80_t *zPtr + ) +{ + const struct extFloat80M *aSPtr; + struct extFloat80M *zSPtr; + uint_fast16_t uiA64, signUI64; + int32_t exp; + uint64_t sigA; + uint_fast16_t uiZ64; + uint64_t sigZ, lastBitMask, roundBitsMask; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + zSPtr = (struct extFloat80M *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + signUI64 = uiA64 & packToExtF80UI64( 1, 0 ); + exp = expExtF80UI64( uiA64 ); + sigA = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) && (exp != 0x7FFF) ) { + if ( ! sigA ) { + uiZ64 = signUI64; + sigZ = 0; + goto uiZ; + } + exp += softfloat_normExtF80SigM( &sigA ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp <= 0x3FFE ) { + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + switch ( roundingMode ) { + case softfloat_round_near_even: + if ( ! (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) break; + case softfloat_round_near_maxMag: + if ( exp == 0x3FFE ) goto mag1; + break; + case softfloat_round_min: + if ( signUI64 ) goto mag1; + break; + case softfloat_round_max: + if ( ! signUI64 ) goto mag1; + break; + } + uiZ64 = signUI64; + sigZ = 0; + goto uiZ; + mag1: + uiZ64 = signUI64 | 0x3FFF; + sigZ = UINT64_C( 0x8000000000000000 ); + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x403E <= exp ) { + if ( exp == 0x7FFF ) { + if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + softfloat_propagateNaNExtF80M( aSPtr, 0, zSPtr ); + return; + } + sigZ = UINT64_C( 0x8000000000000000 ); + } else { + sigZ = sigA; + } + uiZ64 = signUI64 | exp; + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = signUI64 | exp; + lastBitMask = (uint64_t) 1<<(0x403E - exp); + roundBitsMask = lastBitMask - 1; + sigZ = sigA; + if ( roundingMode == softfloat_round_near_maxMag ) { + sigZ += lastBitMask>>1; + } else if ( roundingMode == softfloat_round_near_even ) { + sigZ += lastBitMask>>1; + if ( ! (sigZ & roundBitsMask) ) sigZ &= ~lastBitMask; + } else if ( roundingMode != softfloat_round_minMag ) { + if ( (signUI64 != 0) ^ (roundingMode == softfloat_round_max) ) { + sigZ += roundBitsMask; + } + } + sigZ &= ~roundBitsMask; + if ( ! sigZ ) { + ++uiZ64; + sigZ = UINT64_C( 0x8000000000000000 ); + } + if ( exact && (sigZ != sigA) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + uiZ: + zSPtr->signExp = uiZ64; + zSPtr->signif = sigZ; + return; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c new file mode 100644 index 0000000..2be7f03 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void extF80M_sqrt( const extFloat80_t *aPtr, extFloat80_t *zPtr ) +{ + + *zPtr = extF80_sqrt( *aPtr ); + +} + +#else + +void extF80M_sqrt( const extFloat80_t *aPtr, extFloat80_t *zPtr ) +{ + const struct extFloat80M *aSPtr; + struct extFloat80M *zSPtr; + uint_fast16_t uiA64, signUI64; + int32_t expA; + uint64_t rem64; + int32_t expZ; + uint32_t rem[4], sig32A, recipSqrt32, sig32Z, q; + uint64_t sig64Z, x64; + uint32_t term[4], extSigZ[3]; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + zSPtr = (struct extFloat80M *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + signUI64 = uiA64 & packToExtF80UI64( 1, 0 ); + expA = expExtF80UI64( uiA64 ); + rem64 = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( rem64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + softfloat_propagateNaNExtF80M( aSPtr, 0, zSPtr ); + return; + } + if ( signUI64 ) goto invalid; + rem64 = UINT64_C( 0x8000000000000000 ); + goto copyA; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) expA = 1; + if ( ! (rem64 & UINT64_C( 0x8000000000000000 )) ) { + if ( ! rem64 ) { + uiA64 = signUI64; + goto copyA; + } + expA += softfloat_normExtF80SigM( &rem64 ); + } + if ( signUI64 ) goto invalid; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FFF)>>1) + 0x3FFF; + expA &= 1; + softfloat_shortShiftLeft64To96M( + rem64, 30 - expA, &rem[indexMultiwordHi( 4, 3 )] ); + sig32A = rem64>>32; + recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); + sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; + if ( expA ) sig32Z >>= 1; + rem64 = + ((uint64_t) rem[indexWord( 4, 3 )]<<32 | rem[indexWord( 4, 2 )]) + - (uint64_t) sig32Z * sig32Z; + rem[indexWord( 4, 3 )] = rem64>>32; + rem[indexWord( 4, 2 )] = rem64; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32; + sig64Z = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<3); + x64 = ((uint64_t) sig32Z<<32) + sig64Z; + term[indexWord( 3, 2 )] = 0; + term[indexWord( 3, 1 )] = x64>>32; + term[indexWord( 3, 0 )] = x64; + softfloat_remStep96MBy32( + &rem[indexMultiwordHi( 4, 3 )], + 29, + term, + q, + &rem[indexMultiwordHi( 4, 3 )] + ); + rem64 = (uint64_t) rem[indexWord( 4, 3 )]<<32 | rem[indexWord( 4, 2 )]; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = (((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32) + 2; + x64 = (uint64_t) q<<7; + extSigZ[indexWord( 3, 0 )] = x64; + x64 = (sig64Z<<1) + (x64>>32); + extSigZ[indexWord( 3, 2 )] = x64>>32; + extSigZ[indexWord( 3, 1 )] = x64; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (q & 0xFFFFFF) <= 2 ) { + q &= ~(uint32_t) 0xFFFF; + extSigZ[indexWordLo( 3 )] = q<<7; + x64 = sig64Z + (q>>27); + term[indexWord( 4, 3 )] = 0; + term[indexWord( 4, 2 )] = x64>>32; + term[indexWord( 4, 1 )] = x64; + term[indexWord( 4, 0 )] = q<<5; + rem[indexWord( 4, 0 )] = 0; + softfloat_remStep128MBy32( rem, 28, term, q, rem ); + q = rem[indexWordHi( 4 )]; + if ( q & 0x80000000 ) { + softfloat_sub1X96M( extSigZ ); + } else { + if ( q || rem[indexWord( 4, 1 )] || rem[indexWord( 4, 2 )] ) { + extSigZ[indexWordLo( 3 )] |= 1; + } + } + } + softfloat_roundPackMToExtF80M( + 0, expZ, extSigZ, extF80_roundingPrecision, zSPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_invalidExtF80M( zSPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + copyA: + zSPtr->signExp = uiA64; + zSPtr->signif = rem64; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c new file mode 100644 index 0000000..1688635 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + extF80M_sub( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + const struct extFloat80M *aSPtr, *bSPtr; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool signA; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + extFloat80_t + (*magsFuncPtr)( + uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); +#endif + + aSPtr = (const struct extFloat80M *) aPtr; + bSPtr = (const struct extFloat80M *) bPtr; + uiA64 = aSPtr->signExp; + uiA0 = aSPtr->signif; + signA = signExtF80UI64( uiA64 ); + uiB64 = bSPtr->signExp; + uiB0 = bSPtr->signif; + signB = signExtF80UI64( uiB64 ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + *zPtr = softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); + } else { + *zPtr = softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_subMagsExtF80 : softfloat_addMagsExtF80; + *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); +#endif + +} + +#else + +void + extF80M_sub( + const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) +{ + + softfloat_addExtF80M( + (const struct extFloat80M *) aPtr, + (const struct extFloat80M *) bPtr, + (struct extFloat80M *) zPtr, + true + ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c new file mode 100644 index 0000000..ef6be5e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr ) +{ + + *zPtr = extF80_to_f128( *aPtr ); + +} + +#else + +void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr ) +{ + const struct extFloat80M *aSPtr; + uint32_t *zWPtr; + uint_fast16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint32_t uiZ96; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + zWPtr = (uint32_t *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zWPtr[indexWord( 4, 0 )] = 0; + if ( exp == 0x7FFF ) { + if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); + softfloat_commonNaNToF128M( &commonNaN, zWPtr ); + return; + } + uiZ96 = packToF128UI96( sign, 0x7FFF, 0 ); + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp ) --exp; + if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sig ) { + uiZ96 = packToF128UI96( sign, 0, 0 ); + goto uiZ; + } + exp += softfloat_normExtF80SigM( &sig ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zWPtr[indexWord( 4, 1 )] = (uint32_t) sig<<17; + sig >>= 15; + zWPtr[indexWord( 4, 2 )] = sig; + if ( exp < 0 ) { + zWPtr[indexWordHi( 4 )] = sig>>32; + softfloat_shiftRight96M( + &zWPtr[indexMultiwordHi( 4, 3 )], + -exp, + &zWPtr[indexMultiwordHi( 4, 3 )] + ); + exp = 0; + sig = (uint64_t) zWPtr[indexWordHi( 4 )]<<32; + } + zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp, sig>>32 ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ: + zWPtr[indexWord( 4, 3 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c new file mode 100644 index 0000000..e666d49 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +float32_t extF80M_to_f32( const extFloat80_t *aPtr ) +{ + + return extF80_to_f32( *aPtr ); + +} + +#else + +float32_t extF80M_to_f32( const extFloat80_t *aPtr ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint32_t uiZ, sig32; + union ui32_f32 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp == 0x7FFF ) { + if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); + uiZ = softfloat_commonNaNToF32UI( &commonNaN ); + } else { + uiZ = packToF32UI( sign, 0xFF, 0 ); + } + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sig ) { + uiZ = packToF32UI( sign, 0, 0 ); + goto uiZ; + } + exp += softfloat_normExtF80SigM( &sig ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = softfloat_shortShiftRightJam64( sig, 33 ); + exp -= 0x3F81; + if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { + if ( exp < -0x1000 ) exp = -0x1000; + } + return softfloat_roundPackToF32( sign, exp, sig32 | 0x40000000 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c new file mode 100644 index 0000000..2080d80 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +float64_t extF80M_to_f64( const extFloat80_t *aPtr ) +{ + + return extF80_to_f64( *aPtr ); + +} + +#else + +float64_t extF80M_to_f64( const extFloat80_t *aPtr ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint64_t uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp == 0x7FFF ) { + if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); + uiZ = softfloat_commonNaNToF64UI( &commonNaN ); + } else { + uiZ = packToF64UI( sign, 0x7FF, 0 ); + } + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sig ) { + uiZ = packToF64UI( sign, 0, 0 ); + goto uiZ; + } + exp += softfloat_normExtF80SigM( &sig ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = softfloat_shortShiftRightJam64( sig, 1 ); + exp -= 0x3C01; + if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { + if ( exp < -0x1000 ) exp = -0x1000; + } + return + softfloat_roundPackToF64( + sign, exp, sig | UINT64_C( 0x4000000000000000 ) ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c new file mode 100644 index 0000000..223dccb --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +int_fast32_t + extF80M_to_i32( + const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + + return extF80_to_i32( *aPtr, roundingMode, exact ); + +} + +#else + +int_fast32_t + extF80M_to_i32( + const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftCount; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) sign = 0; + shiftCount = 0x4037 - exp; + if ( shiftCount <= 0 ) { + if ( sig>>32 ) goto invalid; + if ( -32 < shiftCount ) { + sig <<= -shiftCount; + } else { + if ( (uint32_t) sig ) goto invalid; + } + } else { + sig = softfloat_shiftRightJam64( sig, shiftCount ); + } + return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return sign ? -0x7FFFFFFF - 1 : 0x7FFFFFFF; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c new file mode 100644 index 0000000..78127d5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *aPtr, bool exact ) +{ + + return extF80_to_i32_r_minMag( *aPtr, exact ); + +} + +#else + +int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *aPtr, bool exact ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftCount; + bool raiseInexact; + int32_t z; + uint64_t shiftedSig; + uint32_t absZ; + union { uint32_t ui; int32_t i; } u; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! sig && (exp != 0x7FFF) ) return 0; + shiftCount = 0x403E - exp; + if ( 64 <= shiftCount ) { + raiseInexact = exact; + z = 0; + } else { + raiseInexact = false; + if ( shiftCount < 0 ) { + if ( sig>>32 || (shiftCount <= -31) ) goto invalid; + shiftedSig = (uint64_t) (uint32_t) sig<<-shiftCount; + if ( shiftedSig>>32 ) goto invalid; + absZ = shiftedSig; + } else { + shiftedSig = sig; + if ( shiftCount ) shiftedSig >>= shiftCount; + if ( shiftedSig>>32 ) goto invalid; + absZ = shiftedSig; + if ( exact && shiftCount ) { + raiseInexact = ((uint64_t) absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +int_fast64_t + extF80M_to_i64( + const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + + return extF80_to_i64( *aPtr, roundingMode, exact ); + +} + +#else + +int_fast64_t + extF80M_to_i64( + const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftCount; + uint32_t extSig[3]; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftCount = 0x403E - exp; + if ( shiftCount < 0 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + ! sign + || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + ? INT64_C( 0x7FFFFFFFFFFFFFFF ) + : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + extSig[indexWord( 3, 0 )] = 0; + if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); + return softfloat_roundPackMToI64( sign, extSig, roundingMode, exact ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c new file mode 100644 index 0000000..c9ce172 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *aPtr, bool exact ) +{ + + return extF80_to_i64_r_minMag( *aPtr, exact ); + +} + +#else + +int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *aPtr, bool exact ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftCount; + bool raiseInexact; + int64_t z; + uint64_t absZ; + union { uint64_t ui; int64_t i; } u; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! sig && (exp != 0x7FFF) ) return 0; + shiftCount = 0x403E - exp; + if ( 64 <= shiftCount ) { + raiseInexact = exact; + z = 0; + } else { + raiseInexact = false; + if ( shiftCount < 0 ) { + if ( shiftCount <= -63 ) goto invalid; + shiftCount = -shiftCount; + absZ = sig<>shiftCount != sig ) goto invalid; + } else { + absZ = sig; + if ( shiftCount ) absZ >>= shiftCount; + if ( exact && shiftCount ) { + raiseInexact = (absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast32_t + extF80M_to_ui32( + const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + + return extF80_to_ui32( *aPtr, roundingMode, exact ); + +} + +#else + +uint_fast32_t + extF80M_to_ui32( + const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftCount; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftCount = 0x4037 - exp; + if ( shiftCount <= 0 ) { + if ( sig>>32 ) goto invalid; + if ( -32 < shiftCount ) { + sig <<= -shiftCount; + } else { + if ( (uint32_t) sig ) goto invalid; + } + } else { + sig = softfloat_shiftRightJam64( sig, shiftCount ); + } + return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return 0xFFFFFFFF; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c new file mode 100644 index 0000000..6d0a6cd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *aPtr, bool exact ) +{ + + return extF80_to_ui32_r_minMag( *aPtr, exact ); + +} + +#else + +uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *aPtr, bool exact ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftCount; + bool sign; + uint64_t shiftedSig; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! sig && (exp != 0x7FFF) ) return 0; + shiftCount = 0x403E - exp; + if ( 64 <= shiftCount ) { + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + return 0; + } + sign = signExtF80UI64( uiA64 ); + if ( shiftCount < 0 ) { + if ( sign || sig>>32 || (shiftCount <= -31) ) goto invalid; + shiftedSig = (uint64_t) (uint32_t) sig<<-shiftCount; + if ( shiftedSig>>32 ) goto invalid; + z = shiftedSig; + } else { + shiftedSig = sig; + if ( shiftCount ) shiftedSig >>= shiftCount; + if ( shiftedSig>>32 ) goto invalid; + z = shiftedSig; + if ( sign && z ) goto invalid; + if ( exact && shiftCount && ((uint64_t) z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast64_t + extF80M_to_ui64( + const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + + return extF80_to_ui64( *aPtr, roundingMode, exact ); + +} + +#else + +uint_fast64_t + extF80M_to_ui64( + const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + int32_t exp, shiftCount; + bool sign; + uint64_t sig; + uint32_t extSig[3]; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + exp = expExtF80UI64( uiA64 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftCount = 0x403E - exp; + if ( shiftCount < 0 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + sign = signExtF80UI64( uiA64 ); + sig = aSPtr->signif; + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + extSig[indexWord( 3, 0 )] = 0; + if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); + return softfloat_roundPackMToUI64( sign, extSig, roundingMode, exact ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c new file mode 100644 index 0000000..1e3e673 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *aPtr, bool exact ) +{ + + return extF80_to_ui64_r_minMag( *aPtr, exact ); + +} + +#else + +uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *aPtr, bool exact ) +{ + const struct extFloat80M *aSPtr; + uint_fast16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftCount; + bool sign; + uint64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aSPtr = (const struct extFloat80M *) aPtr; + uiA64 = aSPtr->signExp; + exp = expExtF80UI64( uiA64 ); + sig = aSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! sig && (exp != 0x7FFF) ) return 0; + shiftCount = 0x403E - exp; + if ( 64 <= shiftCount ) { + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + return 0; + } + sign = signExtF80UI64( uiA64 ); + if ( shiftCount < 0 ) { + if ( sign || (shiftCount <= -63) ) goto invalid; + shiftCount = -shiftCount; + z = sig<>shiftCount != sig ) goto invalid; + } else { + z = sig; + if ( shiftCount ) z >>= shiftCount; + if ( sign && z ) goto invalid; + if ( exact && shiftCount && (z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +extFloat80_t extF80_add( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool signA; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + extFloat80_t + (*magsFuncPtr)( + uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); +#endif + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + signA = signExtF80UI64( uiA64 ); + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + signB = signExtF80UI64( uiB64 ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); + } else { + return softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_addMagsExtF80 : softfloat_subMagsExtF80; + return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c new file mode 100644 index 0000000..45a7bb4 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_div( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool signA; + int_fast32_t expA; + uint_fast64_t sigA; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signB; + int_fast32_t expB; + uint_fast64_t sigB; + bool signZ; + struct exp32_sig64 normExpSig; + int_fast32_t expZ; + struct uint128 rem; + uint_fast32_t recip32; + uint_fast64_t sigZ; + int ix; + uint_fast64_t q64; + uint_fast32_t q; + struct uint128 term; + uint_fast64_t sigZExtra; + struct uint128 uiZ; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + signA = signExtF80UI64( uiA64 ); + expA = expExtF80UI64( uiA64 ); + sigA = uiA0; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + signB = signExtF80UI64( uiB64 ); + expB = expExtF80UI64( uiB64 ); + sigB = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + if ( expB == 0x7FFF ) { + if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + goto invalid; + } + goto infinity; + } + if ( expB == 0x7FFF ) { + if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) expB = 1; + if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigB ) { + if ( ! sigA ) goto invalid; + softfloat_raiseFlags( softfloat_flag_infinite ); + goto infinity; + } + normExpSig = softfloat_normSubnormalExtF80Sig( sigB ); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) expA = 1; + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FFF; + if ( sigA < sigB ) { + --expZ; + rem = softfloat_shortShiftLeft128( 0, sigA, 32 ); + } else { + rem = softfloat_shortShiftLeft128( 0, sigA, 31 ); + } + recip32 = softfloat_approxRecip32_1( sigB>>32 ); + sigZ = 0; + ix = 2; + for (;;) { + q64 = (uint_fast64_t) (uint32_t) (rem.v64>>2) * recip32; + q = (q64 + 0x80000000)>>32; + --ix; + if ( ix < 0 ) break; + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + term = softfloat_mul64ByShifted32To128( sigB, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + --q; + rem = softfloat_add128( rem.v64, rem.v0, sigB>>32, sigB<<32 ); + } + sigZ = (sigZ<<29) + q; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ((q + 1) & 0x3FFFFF) < 2 ) { + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + term = softfloat_mul64ByShifted32To128( sigB, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + term = softfloat_shortShiftLeft128( 0, sigB, 32 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + --q; + rem = softfloat_add128( rem.v64, rem.v0, term.v64, term.v0 ); + } else if ( softfloat_le128( term.v64, term.v0, rem.v64, rem.v0 ) ) { + ++q; + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + } + if ( rem.v64 | rem.v0 ) q |= 1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZ = (sigZ<<6) + (q>>23); + sigZExtra = (uint64_t) ((uint_fast64_t) q<<41); + return + softfloat_roundPackToExtF80( + signZ, expZ, sigZ, sigZExtra, extF80_roundingPrecision ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ64 = defaultNaNExtF80UI64; + uiZ0 = defaultNaNExtF80UI0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ64 = packToExtF80UI64( signZ, 0 ); + uiZ0 = 0; + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c new file mode 100644 index 0000000..fd66662 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool extF80_eq( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) + || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + return + (uiA0 == uiB0) + && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF))); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c new file mode 100644 index 0000000..d684701 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool extF80_eq_signaling( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + return + (uiA0 == uiB0) + && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF))); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c new file mode 100644 index 0000000..f6cea98 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool extF80_isSignalingNaN( extFloat80_t a ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + + uA.f = a; + return softfloat_isSigNaNExtF80UI( uA.s.signExp, uA.s.signif ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c new file mode 100644 index 0000000..fc5ed46 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool extF80_le( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signA, signB; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signExtF80UI64( uiA64 ); + signB = signExtF80UI64( uiB64 ); + return + (signA != signB) + ? signA || ! (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) + : ((uiA64 == uiB64) && (uiA0 == uiB0)) + || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c new file mode 100644 index 0000000..d526ecb --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool extF80_le_quiet( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signA, signB; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) + || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signExtF80UI64( uiA64 ); + signB = signExtF80UI64( uiB64 ); + return + (signA != signB) + ? signA || ! (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) + : ((uiA64 == uiB64) && (uiA0 == uiB0)) + || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c new file mode 100644 index 0000000..d9a1a8d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool extF80_lt( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signA, signB; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signExtF80UI64( uiA64 ); + signB = signExtF80UI64( uiB64 ); + return + (signA != signB) + ? signA && (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) + : ((uiA64 != uiB64) || (uiA0 != uiB0)) + && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c new file mode 100644 index 0000000..bcaaf0c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool extF80_lt_quiet( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signA, signB; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) + || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signExtF80UI64( uiA64 ); + signB = signExtF80UI64( uiB64 ); + return + (signA != signB) + ? signA && (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) + : ((uiA64 != uiB64) || (uiA0 != uiB0)) + && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c new file mode 100644 index 0000000..272352c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_mul( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool signA; + int_fast32_t expA; + uint_fast64_t sigA; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signB; + int_fast32_t expB; + uint_fast64_t sigB; + bool signZ; + uint_fast64_t magBits; + struct exp32_sig64 normExpSig; + int_fast32_t expZ; + struct uint128 sig128Z, uiZ; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + signA = signExtF80UI64( uiA64 ); + expA = expExtF80UI64( uiA64 ); + sigA = uiA0; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + signB = signExtF80UI64( uiB64 ); + expB = expExtF80UI64( uiB64 ); + sigB = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( + (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + ) { + goto propagateNaN; + } + magBits = expB | sigB; + goto infArg; + } + if ( expB == 0x7FFF ) { + if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + magBits = expA | sigA; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) expA = 1; + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) expB = 1; + if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigB ) goto zero; + normExpSig = softfloat_normSubnormalExtF80Sig( sigB ); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FFE; + sig128Z = softfloat_mul64To128( sigA, sigB ); + if ( sig128Z.v64 < UINT64_C( 0x8000000000000000 ) ) { + --expZ; + sig128Z = + softfloat_add128( + sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 ); + } + return + softfloat_roundPackToExtF80( + signZ, expZ, sig128Z.v64, sig128Z.v0, extF80_roundingPrecision ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if ( ! magBits ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ64 = defaultNaNExtF80UI64; + uiZ0 = defaultNaNExtF80UI0; + } else { + uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + } + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ64 = packToExtF80UI64( signZ, 0 ); + uiZ0 = 0; + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c new file mode 100644 index 0000000..9dfb6f4 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_rem( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool signA; + int_fast32_t expA; + uint_fast64_t sigA; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signB; + int_fast32_t expB; + uint_fast64_t sigB; + struct exp32_sig64 normExpSig; + int_fast32_t expDiff; + struct uint128 rem, shiftedSigB; + uint_fast32_t q, recip32; + uint_fast64_t q64; + struct uint128 term, altRem, meanRem; + bool signRem; + struct uint128 uiZ; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + signA = signExtF80UI64( uiA64 ); + expA = expExtF80UI64( uiA64 ); + sigA = uiA0; + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + signB = signExtF80UI64( uiB64 ); + expB = expExtF80UI64( uiB64 ); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( + (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + ) { + goto propagateNaN; + } + goto invalid; + } + if ( expB == 0x7FFF ) { + if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + /*-------------------------------------------------------------------- + | Argument b is an infinity. Doubling `expB' is an easy way to ensure + | that `expDiff' later is less than -1, which will result in returning + | a canonicalized version of argument a. + *--------------------------------------------------------------------*/ + expB += expB; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) expB = 1; + if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigB ) goto invalid; + normExpSig = softfloat_normSubnormalExtF80Sig( sigB ); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) expA = 1; + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigA ) { + expA = 0; + goto copyA; + } + normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if ( expDiff < -1 ) goto copyA; + rem = softfloat_shortShiftLeft128( 0, sigA, 32 ); + shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 32 ); + if ( expDiff < 1 ) { + if ( expDiff ) { + --expB; + shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 33 ); + q = 0; + } else { + q = (sigB <= sigA); + if ( q ) { + rem = + softfloat_sub128( + rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 ); + } + } + } else { + recip32 = softfloat_approxRecip32_1( sigB>>32 ); + expDiff -= 30; + for (;;) { + q64 = (uint_fast64_t) (uint32_t) (rem.v64>>2) * recip32; + if ( expDiff < 0 ) break; + q = (q64 + 0x80000000)>>32; + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + term = softfloat_mul64ByShifted32To128( sigB, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + rem = + softfloat_add128( + rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 ); + } + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -29 here.) + *--------------------------------------------------------------------*/ + q = (uint32_t) (q64>>32)>>(~expDiff & 31); + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 ); + term = softfloat_mul64ByShifted32To128( sigB, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + altRem = + softfloat_add128( + rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 ); + goto selectRem; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + do { + altRem = rem; + ++q; + rem = + softfloat_sub128( + rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 ); + } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ); + selectRem: + meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 ); + if ( + (meanRem.v64 & UINT64_C( 0x8000000000000000 )) + || (! (meanRem.v64 | meanRem.v0) && (q & 1)) + ) { + rem = altRem; + } + signRem = signA; + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + signRem = ! signRem; + rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 ); + } + return + softfloat_normRoundPackToExtF80( + signRem, expB + 32, rem.v64, rem.v0, 80 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ64 = defaultNaNExtF80UI64; + uiZ0 = defaultNaNExtF80UI0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + copyA: + if ( expA < 1 ) { + sigA >>= 1 - expA; + expA = 0; + } + uiZ64 = packToExtF80UI64( signA, expA ); + uiZ0 = sigA; + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c new file mode 100644 index 0000000..0598e17 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t + extF80_roundToInt( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64, signUI64; + int_fast32_t exp; + uint_fast64_t sigA; + uint_fast16_t uiZ64; + uint_fast64_t sigZ; + struct exp32_sig64 normExpSig; + struct uint128 uiZ; + uint_fast64_t lastBitMask, roundBitsMask; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.s.signExp; + signUI64 = uiA64 & packToExtF80UI64( 1, 0 ); + exp = expExtF80UI64( uiA64 ); + sigA = uA.s.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) && (exp != 0x7FFF) ) { + if ( ! sigA ) { + uiZ64 = signUI64; + sigZ = 0; + goto uiZ; + } + normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); + exp += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x403E <= exp ) { + if ( exp == 0x7FFF ) { + if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + uiZ = softfloat_propagateNaNExtF80UI( uiA64, sigA, 0, 0 ); + uiZ64 = uiZ.v64; + sigZ = uiZ.v0; + goto uiZ; + } + sigZ = UINT64_C( 0x8000000000000000 ); + } else { + sigZ = sigA; + } + uiZ64 = signUI64 | exp; + goto uiZ; + } + if ( exp <= 0x3FFE ) { + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + switch ( roundingMode ) { + case softfloat_round_near_even: + if ( ! (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) break; + case softfloat_round_near_maxMag: + if ( exp == 0x3FFE ) goto mag1; + break; + case softfloat_round_min: + if ( signUI64 ) goto mag1; + break; + case softfloat_round_max: + if ( ! signUI64 ) goto mag1; + break; + } + uiZ64 = signUI64; + sigZ = 0; + goto uiZ; + mag1: + uiZ64 = signUI64 | 0x3FFF; + sigZ = UINT64_C( 0x8000000000000000 ); + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = signUI64 | exp; + lastBitMask = (uint_fast64_t) 1<<(0x403E - exp); + roundBitsMask = lastBitMask - 1; + sigZ = sigA; + if ( roundingMode == softfloat_round_near_maxMag ) { + sigZ += lastBitMask>>1; + } else if ( roundingMode == softfloat_round_near_even ) { + sigZ += lastBitMask>>1; + if ( ! (sigZ & roundBitsMask) ) sigZ &= ~lastBitMask; + } else if ( roundingMode != softfloat_round_minMag ) { + if ( (signUI64 != 0) ^ (roundingMode == softfloat_round_max) ) { + sigZ += roundBitsMask; + } + } + sigZ &= ~roundBitsMask; + if ( ! sigZ ) { + ++uiZ64; + sigZ = UINT64_C( 0x8000000000000000 ); + } + if ( exact && (sigZ != sigA) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = sigZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c new file mode 100644 index 0000000..a53808a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_sqrt( extFloat80_t a ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool signA; + int_fast32_t expA; + uint_fast64_t sigA; + struct uint128 uiZ; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0; + struct exp32_sig64 normExpSig; + int_fast32_t expZ; + uint_fast32_t sig32A, recipSqrt32, sig32Z; + struct uint128 rem; + uint_fast64_t q, sigZ, x64; + struct uint128 term; + uint_fast64_t sigZExtra; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + signA = signExtF80UI64( uiA64 ); + expA = expExtF80UI64( uiA64 ); + sigA = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, 0, 0 ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + goto uiZ; + } + if ( ! signA ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signA ) { + if ( ! sigA ) goto zero; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) expA = 1; + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FFF)>>1) + 0x3FFF; + expA &= 1; + sig32A = sigA>>32; + recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); + sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32; + if ( expA ) { + sig32Z >>= 1; + rem = softfloat_shortShiftLeft128( 0, sigA, 61 ); + } else { + rem = softfloat_shortShiftLeft128( 0, sigA, 62 ); + } + rem.v64 -= (uint_fast64_t) sig32Z * sig32Z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = ((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32; + sigZ = ((uint_fast64_t) sig32Z<<32) + (q<<3); + x64 = ((uint_fast64_t) sig32Z<<32) + sigZ; + term = softfloat_mul64ByShifted32To128( x64, q ); + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = (((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32) + 2; + x64 = sigZ; + sigZ = (sigZ<<1) + (q>>25); + sigZExtra = (uint64_t) (q<<39); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (q & 0xFFFFFF) <= 2 ) { + q &= ~(uint_fast64_t) 0xFFFF; + sigZExtra = (uint64_t) (q<<39); + term = softfloat_mul64ByShifted32To128( x64 + (q>>27), q ); + x64 = (uint_fast64_t) (uint32_t) (q<<5) * (uint32_t) q; + term = softfloat_add128( term.v64, term.v0, 0, x64 ); + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 28 ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + if ( ! sigZExtra ) --sigZ; + --sigZExtra; + } else { + if ( rem.v64 | rem.v0 ) sigZExtra |= 1; + } + } + return + softfloat_roundPackToExtF80( + 0, expZ, sigZ, sigZExtra, extF80_roundingPrecision ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ64 = defaultNaNExtF80UI64; + uiZ0 = defaultNaNExtF80UI0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ64 = packToExtF80UI64( signA, 0 ); + uiZ0 = 0; + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c new file mode 100644 index 0000000..1c348e8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +extFloat80_t extF80_sub( extFloat80_t a, extFloat80_t b ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool signA; + union { struct extFloat80M s; extFloat80_t f; } uB; + uint_fast16_t uiB64; + uint_fast64_t uiB0; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + extFloat80_t + (*magsFuncPtr)( + uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); +#endif + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + signA = signExtF80UI64( uiA64 ); + uB.f = b; + uiB64 = uB.s.signExp; + uiB0 = uB.s.signif; + signB = signExtF80UI64( uiB64 ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); + } else { + return softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_subMagsExtF80 : softfloat_addMagsExtF80; + return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c new file mode 100644 index 0000000..01c3cd2 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t extF80_to_f128( extFloat80_t a ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + uint_fast16_t exp; + uint_fast64_t sig; + struct commonNaN commonNaN; + struct uint128 uiZ; + bool sign; + struct uint128 sig128; + union ui128_f128 uZ; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + exp = expExtF80UI64( uiA64 ); + sig = uiA0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); + if ( (exp == 0x7FFF) && sig ) { + softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); + uiZ = softfloat_commonNaNToF128UI( &commonNaN ); + } else { + sign = signExtF80UI64( uiA64 ); + sig128 = softfloat_shortShiftLeft128( 0, sig, 49 ); + uiZ.v64 = packToF128UI64( sign, exp, sig128.v64 ); + uiZ.v0 = sig128.v0; + } + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c new file mode 100644 index 0000000..56482c2 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t extF80_to_f32( extFloat80_t a ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig; + struct commonNaN commonNaN; + uint_fast32_t uiZ, sig32; + union ui32_f32 uZ; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = uiA0; + if ( exp == 0x7FFF ) { + if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); + uiZ = softfloat_commonNaNToF32UI( &commonNaN ); + } else { + uiZ = packToF32UI( sign, 0xFF, 0 ); + } + goto uiZ; + } + sig32 = softfloat_shortShiftRightJam64( sig, 33 ); + if ( ! (exp | sig32) ) { + uiZ = packToF32UI( sign, 0, 0 ); + goto uiZ; + } + exp -= 0x3F81; + if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { + if ( exp < -0x1000 ) exp = -0x1000; + } + return softfloat_roundPackToF32( sign, exp, sig32 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f64.c new file mode 100644 index 0000000..0d3d897 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f64.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t extF80_to_f64( extFloat80_t a ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + uint_fast64_t uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig; + struct commonNaN commonNaN; + uint_fast64_t uiZ; + union ui64_f64 uZ; + + uA.f = a; + uiA64 = uA.s.signExp; + uiA0 = uA.s.signif; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = uiA0; + if ( ! (exp | sig) ) { + uiZ = packToF64UI( sign, 0, 0 ); + goto uiZ; + } + if ( exp == 0x7FFF ) { + if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); + uiZ = softfloat_commonNaNToF64UI( &commonNaN ); + } else { + uiZ = packToF64UI( sign, 0x7FF, 0 ); + } + goto uiZ; + } + sig = softfloat_shortShiftRightJam64( sig, 1 ); + exp -= 0x3C01; + if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { + if ( exp < -0x1000 ) exp = -0x1000; + } + return softfloat_roundPackToF64( sign, exp, sig ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c new file mode 100644 index 0000000..f698b98 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t + extF80_to_i32( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + bool sign; + int_fast32_t exp; + uint_fast64_t sig; + int_fast32_t shiftCount; + + uA.f = a; + uiA64 = uA.s.signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = uA.s.signif; + if ( (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) sign = 0; + shiftCount = 0x4037 - exp; + if ( shiftCount <= 0 ) shiftCount = 1; + sig = softfloat_shiftRightJam64( sig, shiftCount ); + return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c new file mode 100644 index 0000000..d66cfe9 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t extF80_to_i32_r_minMag( extFloat80_t a, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + int_fast32_t exp; + uint_fast64_t sig; + int_fast32_t shiftCount; + bool sign; + int_fast32_t absZ; + + uA.f = a; + uiA64 = uA.s.signExp; + exp = expExtF80UI64( uiA64 ); + sig = uA.s.signif; + shiftCount = 0x403E - exp; + if ( 64 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signExtF80UI64( uiA64 ); + if ( shiftCount < 33 ) { + if ( + (uiA64 == packToExtF80UI64( 1, 0x401E )) + && (sig < UINT64_C( 0x8000000100000000 )) + ) { + if ( exact && (sig & UINT64_C( 0x00000000FFFFFFFF )) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } else { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( + ! sign + || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + ) { + return 0x7FFFFFFF; + } + } + return -0x7FFFFFFF - 1; + } + absZ = sig>>shiftCount; + if ( + exact && ((uint_fast64_t) (uint_fast32_t) absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t + extF80_to_i64( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + bool sign; + int_fast32_t exp; + uint_fast64_t sig; + int_fast32_t shiftCount; + uint_fast64_t sigExtra; + struct uint64_extra sig64Extra; + + uA.f = a; + uiA64 = uA.s.signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = uA.s.signif; + shiftCount = 0x403E - exp; + if ( shiftCount <= 0 ) { + if ( shiftCount ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + ! sign + || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + ? INT64_C( 0x7FFFFFFFFFFFFFFF ) + : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sigExtra = 0; + } else { + sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + } + return + softfloat_roundPackToI64( sign, sig, sigExtra, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c new file mode 100644 index 0000000..9ed5455 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t extF80_to_i64_r_minMag( extFloat80_t a, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + int_fast32_t exp; + uint_fast64_t sig; + int_fast32_t shiftCount; + bool sign; + int_fast64_t absZ; + + uA.f = a; + uiA64 = uA.s.signExp; + exp = expExtF80UI64( uiA64 ); + sig = uA.s.signif; + shiftCount = 0x403E - exp; + if ( 64 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signExtF80UI64( uiA64 ); + if ( shiftCount <= 0 ) { + if ( + (uiA64 != packToExtF80UI64( 1, 0x403E )) + || (sig != UINT64_C( 0x8000000000000000 )) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( + ! sign + || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + ) { + return INT64_C( 0x7FFFFFFFFFFFFFFF ); + } + } + return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + absZ = sig>>shiftCount; + if ( exact && (uint64_t) (sig<<(-shiftCount & 63)) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return sign ? -absZ : absZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c new file mode 100644 index 0000000..516a6fd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t + extF80_to_ui32( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + bool sign; + int_fast32_t exp; + uint_fast64_t sig; + int_fast32_t shiftCount; + + uA.f = a; + uiA64 = uA.s.signExp; + sign = signExtF80UI64( uiA64 ); + exp = expExtF80UI64( uiA64 ); + sig = uA.s.signif; + shiftCount = 0x4037 - exp; + if ( shiftCount <= 0 ) shiftCount = 1; + sig = softfloat_shiftRightJam64( sig, shiftCount ); + return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c new file mode 100644 index 0000000..4a2c119 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t a, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + int_fast32_t exp; + uint_fast64_t sig; + int_fast32_t shiftCount; + uint_fast32_t z; + + uA.f = a; + uiA64 = uA.s.signExp; + exp = expExtF80UI64( uiA64 ); + sig = uA.s.signif; + shiftCount = 0x403E - exp; + if ( 64 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signExtF80UI64( uiA64 ) || (shiftCount < 32) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return 0xFFFFFFFF; + } + z = sig>>shiftCount; + if ( exact && ((uint_fast64_t) z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t + extF80_to_ui64( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + int_fast32_t exp, shiftCount; + bool sign; + uint_fast64_t sig, sigExtra; + struct uint64_extra sig64Extra; + + uA.f = a; + uiA64 = uA.s.signExp; + exp = expExtF80UI64( uiA64 ); + shiftCount = 0x403E - exp; + if ( shiftCount < 0 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + sign = signExtF80UI64( uiA64 ); + sig = uA.s.signif; + sigExtra = 0; + if ( shiftCount ) { + sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + } + return + softfloat_roundPackToUI64( sign, sig, sigExtra, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c new file mode 100644 index 0000000..4d48b08 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t a, bool exact ) +{ + union { struct extFloat80M s; extFloat80_t f; } uA; + uint_fast16_t uiA64; + int_fast32_t exp; + uint_fast64_t sig; + int_fast32_t shiftCount; + uint_fast64_t z; + + uA.f = a; + uiA64 = uA.s.signExp; + exp = expExtF80UI64( uiA64 ); + sig = uA.s.signif; + shiftCount = 0x403E - exp; + if ( 64 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signExtF80UI64( uiA64 ) || (shiftCount < 0) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + z = sig>>shiftCount; + if ( exact && (z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + f128M_add( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + const uint64_t *aWPtr, *bWPtr; + uint_fast64_t uiA64, uiA0; + bool signA; + uint_fast64_t uiB64, uiB0; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + float128_t + (*magsFuncPtr)( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); +#endif + + aWPtr = (const uint64_t *) aPtr; + bWPtr = (const uint64_t *) bPtr; + uiA64 = aWPtr[indexWord( 2, 1 )]; + uiA0 = aWPtr[indexWord( 2, 0 )]; + signA = signF128UI64( uiA64 ); + uiB64 = bWPtr[indexWord( 2, 1 )]; + uiB0 = bWPtr[indexWord( 2, 0 )]; + signB = signF128UI64( uiB64 ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); + } else { + *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128; + *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); +#endif + +} + +#else + +void + f128M_add( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + + softfloat_addF128M( + (const uint32_t *) aPtr, + (const uint32_t *) bPtr, + (uint32_t *) zPtr, + false + ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c new file mode 100644 index 0000000..5c9135f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + f128M_div( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + + *zPtr = f128_div( *aPtr, *bPtr ); + +} + +#else + +void + f128M_div( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t *zWPtr, uiA96; + bool signA; + int32_t expA; + uint32_t uiB96; + bool signB; + int32_t expB; + bool signZ; + uint32_t y[5], sigB[4]; + int32_t expZ; + uint32_t recip32; + int ix; + uint64_t q64; + uint32_t q, qs[3], uiZ96; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + zWPtr = (uint32_t *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA96 = aWPtr[indexWordHi( 4 )]; + signA = signF128UI96( uiA96 ); + expA = expF128UI96( uiA96 ); + uiB96 = bWPtr[indexWordHi( 4 )]; + signB = signF128UI96( uiB96 ); + expB = expF128UI96( uiB96 ); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; + if ( expA == 0x7FFF ) { + if ( expB == 0x7FFF ) goto invalid; + goto infinity; + } + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = softfloat_shiftNormSigF128M( aWPtr, 13, y ); + expB = softfloat_shiftNormSigF128M( bWPtr, 13, sigB ); + if ( expA == -128 ) { + if ( expB == -128 ) goto invalid; + goto zero; + } + if ( expB == -128 ) { + softfloat_raiseFlags( softfloat_flag_infinite ); + goto infinity; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FFE; + if ( softfloat_compare128M( y, sigB ) < 0 ) { + --expZ; + softfloat_add128M( y, y, y ); + } + recip32 = + softfloat_approxRecip32_1( + ((uint64_t) sigB[indexWord( 4, 3 )]<<32 | sigB[indexWord( 4, 2 )]) + >>30 + ); + ix = 3; + for (;;) { + q64 = (uint64_t) y[indexWordHi( 4 )] * recip32; + q = (q64 + 0x80000000)>>32; + --ix; + if ( ix < 0 ) break; + softfloat_remStep128MBy32( y, 29, sigB, q, y ); + if ( y[indexWordHi( 4 )] & 0x80000000 ) { + --q; + softfloat_add128M( y, sigB, y ); + } + qs[ix] = q; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ((q + 1) & 7) < 2 ) { + softfloat_remStep128MBy32( y, 29, sigB, q, y ); + if ( y[indexWordHi( 4 )] & 0x80000000 ) { + --q; + softfloat_add128M( y, sigB, y ); + } else if ( softfloat_compare128M( sigB, y ) <= 0 ) { + ++q; + softfloat_sub128M( y, sigB, y ); + } + if ( + y[indexWordLo( 4 )] || y[indexWord( 4, 1 )] + || (y[indexWord( 4, 2 )] | y[indexWord( 4, 3 )]) + ) { + q |= 1; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q64 = (uint64_t) q<<28; + y[indexWord( 5, 0 )] = q64; + q64 = ((uint64_t) qs[0]<<25) + (q64>>32); + y[indexWord( 5, 1 )] = q64; + q64 = ((uint64_t) qs[1]<<22) + (q64>>32); + y[indexWord( 5, 2 )] = q64; + q64 = ((uint64_t) qs[2]<<19) + (q64>>32); + y[indexWord( 5, 3 )] = q64; + y[indexWord( 5, 4 )] = q64>>32; + softfloat_roundPackMToF128M( signZ, expZ, y, zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_invalidF128M( zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ96 = packToF128UI96( signZ, 0x7FFF, 0 ); + goto uiZ96; + zero: + uiZ96 = packToF128UI96( signZ, 0, 0 ); + uiZ96: + zWPtr[indexWordHi( 4 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c new file mode 100644 index 0000000..6c9de8d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr ) +{ + + return f128_eq( *aPtr, *bPtr ); + +} + +#else + +bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t wordA, wordB, uiA96, uiB96; + bool possibleOppositeZeros; + uint32_t mashWord; + + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + wordA = aWPtr[indexWord( 4, 2 )]; + wordB = bWPtr[indexWord( 4, 2 )]; + if ( wordA != wordB ) goto false_checkSigNaNs; + uiA96 = aWPtr[indexWordHi( 4 )]; + uiB96 = bWPtr[indexWordHi( 4 )]; + possibleOppositeZeros = false; + if ( uiA96 != uiB96 ) { + possibleOppositeZeros = (((uiA96 | uiB96) & 0x7FFFFFFF) == 0); + if ( ! possibleOppositeZeros ) goto false_checkSigNaNs; + } + mashWord = wordA | wordB; + wordA = aWPtr[indexWord( 4, 1 )]; + wordB = bWPtr[indexWord( 4, 1 )]; + if ( wordA != wordB ) goto false_checkSigNaNs; + mashWord |= wordA | wordB; + wordA = aWPtr[indexWord( 4, 0 )]; + wordB = bWPtr[indexWord( 4, 0 )]; + if ( wordA != wordB ) goto false_checkSigNaNs; + if ( possibleOppositeZeros && ((mashWord | wordA | wordB) != 0) ) { + goto false_checkSigNaNs; + } + if ( ! softfloat_isNaNF128M( aWPtr ) && ! softfloat_isNaNF128M( bWPtr ) ) { + return true; + } + false_checkSigNaNs: + if ( + f128M_isSignalingNaN( (const float128_t *) aWPtr ) + || f128M_isSignalingNaN( (const float128_t *) bWPtr ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c new file mode 100644 index 0000000..2f90147 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool f128M_eq_signaling( const float128_t *aPtr, const float128_t *bPtr ) +{ + + return f128_eq_signaling( *aPtr, *bPtr ); + +} + +#else + +bool f128M_eq_signaling( const float128_t *aPtr, const float128_t *bPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t wordA, wordB, uiA96, uiB96; + bool possibleOppositeZeros; + uint32_t mashWord; + + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + wordA = aWPtr[indexWord( 4, 2 )]; + wordB = bWPtr[indexWord( 4, 2 )]; + if ( wordA != wordB ) return false; + uiA96 = aWPtr[indexWordHi( 4 )]; + uiB96 = bWPtr[indexWordHi( 4 )]; + possibleOppositeZeros = false; + if ( uiA96 != uiB96 ) { + possibleOppositeZeros = (((uiA96 | uiB96) & 0x7FFFFFFF) == 0); + if ( ! possibleOppositeZeros ) return false; + } + mashWord = wordA | wordB; + wordA = aWPtr[indexWord( 4, 1 )]; + wordB = bWPtr[indexWord( 4, 1 )]; + if ( wordA != wordB ) return false; + mashWord |= wordA | wordB; + wordA = aWPtr[indexWord( 4, 0 )]; + wordB = bWPtr[indexWord( 4, 0 )]; + return + (wordA == wordB) + && (! possibleOppositeZeros || ((mashWord | wordA | wordB) == 0)); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c new file mode 100644 index 0000000..55fe9d5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool f128M_le( const float128_t *aPtr, const float128_t *bPtr ) +{ + + return f128_le( *aPtr, *bPtr ); + +} + +#else + +bool f128M_le( const float128_t *aPtr, const float128_t *bPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t uiA96, uiB96; + bool signA, signB; + uint32_t wordA, wordB; + + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + uiA96 = aWPtr[indexWordHi( 4 )]; + uiB96 = bWPtr[indexWordHi( 4 )]; + signA = signF128UI96( uiA96 ); + signB = signF128UI96( uiB96 ); + if ( signA != signB ) { + if ( signA ) return true; + if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return false; + wordA = aWPtr[indexWord( 4, 2 )]; + wordB = bWPtr[indexWord( 4, 2 )]; + if ( wordA | wordB ) return false; + wordA = aWPtr[indexWord( 4, 1 )]; + wordB = bWPtr[indexWord( 4, 1 )]; + if ( wordA | wordB ) return false; + wordA = aWPtr[indexWord( 4, 0 )]; + wordB = bWPtr[indexWord( 4, 0 )]; + return ((wordA | wordB) == 0); + } + if ( signA ) { + aWPtr = (const uint32_t *) bPtr; + bWPtr = (const uint32_t *) aPtr; + } + return (softfloat_compare128M( aWPtr, bWPtr ) <= 0); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c new file mode 100644 index 0000000..39baf75 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool f128M_le_quiet( const float128_t *aPtr, const float128_t *bPtr ) +{ + + return f128_le_quiet( *aPtr, *bPtr ); + +} + +#else + +bool f128M_le_quiet( const float128_t *aPtr, const float128_t *bPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t uiA96, uiB96; + bool signA, signB; + uint32_t wordA, wordB; + + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { + if ( f128M_isSignalingNaN( aPtr ) || f128M_isSignalingNaN( bPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + uiA96 = aWPtr[indexWordHi( 4 )]; + uiB96 = bWPtr[indexWordHi( 4 )]; + signA = signF128UI96( uiA96 ); + signB = signF128UI96( uiB96 ); + if ( signA != signB ) { + if ( signA ) return true; + if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return false; + wordA = aWPtr[indexWord( 4, 2 )]; + wordB = bWPtr[indexWord( 4, 2 )]; + if ( wordA | wordB ) return false; + wordA = aWPtr[indexWord( 4, 1 )]; + wordB = bWPtr[indexWord( 4, 1 )]; + if ( wordA | wordB ) return false; + wordA = aWPtr[indexWord( 4, 0 )]; + wordB = bWPtr[indexWord( 4, 0 )]; + return ((wordA | wordB) == 0); + } + if ( signA ) { + aWPtr = (const uint32_t *) bPtr; + bWPtr = (const uint32_t *) aPtr; + } + return (softfloat_compare128M( aWPtr, bWPtr ) <= 0); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c new file mode 100644 index 0000000..4102485 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool f128M_lt( const float128_t *aPtr, const float128_t *bPtr ) +{ + + return f128_lt( *aPtr, *bPtr ); + +} + +#else + +bool f128M_lt( const float128_t *aPtr, const float128_t *bPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t uiA96, uiB96; + bool signA, signB; + uint32_t wordA, wordB; + + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + uiA96 = aWPtr[indexWordHi( 4 )]; + uiB96 = bWPtr[indexWordHi( 4 )]; + signA = signF128UI96( uiA96 ); + signB = signF128UI96( uiB96 ); + if ( signA != signB ) { + if ( signB ) return false; + if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return true; + wordA = aWPtr[indexWord( 4, 2 )]; + wordB = bWPtr[indexWord( 4, 2 )]; + if ( wordA | wordB ) return true; + wordA = aWPtr[indexWord( 4, 1 )]; + wordB = bWPtr[indexWord( 4, 1 )]; + if ( wordA | wordB ) return true; + wordA = aWPtr[indexWord( 4, 0 )]; + wordB = bWPtr[indexWord( 4, 0 )]; + return ((wordA | wordB) != 0); + } + if ( signA ) { + aWPtr = (const uint32_t *) bPtr; + bWPtr = (const uint32_t *) aPtr; + } + return (softfloat_compare128M( aWPtr, bWPtr ) < 0); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c new file mode 100644 index 0000000..cb2b114 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +bool f128M_lt_quiet( const float128_t *aPtr, const float128_t *bPtr ) +{ + + return f128_lt_quiet( *aPtr, *bPtr ); + +} + +#else + +bool f128M_lt_quiet( const float128_t *aPtr, const float128_t *bPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t uiA96, uiB96; + bool signA, signB; + uint32_t wordA, wordB; + + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { + if ( f128M_isSignalingNaN( aPtr ) || f128M_isSignalingNaN( bPtr ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + uiA96 = aWPtr[indexWordHi( 4 )]; + uiB96 = bWPtr[indexWordHi( 4 )]; + signA = signF128UI96( uiA96 ); + signB = signF128UI96( uiB96 ); + if ( signA != signB ) { + if ( signB ) return false; + if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return true; + wordA = aWPtr[indexWord( 4, 2 )]; + wordB = bWPtr[indexWord( 4, 2 )]; + if ( wordA | wordB ) return true; + wordA = aWPtr[indexWord( 4, 1 )]; + wordB = bWPtr[indexWord( 4, 1 )]; + if ( wordA | wordB ) return true; + wordA = aWPtr[indexWord( 4, 0 )]; + wordB = bWPtr[indexWord( 4, 0 )]; + return ((wordA | wordB) != 0); + } + if ( signA ) { + aWPtr = (const uint32_t *) bPtr; + bWPtr = (const uint32_t *) aPtr; + } + return (softfloat_compare128M( aWPtr, bWPtr ) < 0); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c new file mode 100644 index 0000000..4d99e42 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + f128M_mul( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + + *zPtr = f128_mul( *aPtr, *bPtr ); + +} + +#else + +void + f128M_mul( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t *zWPtr; + uint32_t uiA96; + int32_t expA; + uint32_t uiB96; + int32_t expB; + bool signZ; + const uint32_t *ptr; + uint32_t uiZ96, sigA[4]; + uint_fast8_t shiftCount; + uint32_t sigB[4]; + int32_t expZ; + uint32_t sigProd[8], *extSigZPtr; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + zWPtr = (uint32_t *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA96 = aWPtr[indexWordHi( 4 )]; + expA = expF128UI96( uiA96 ); + uiB96 = bWPtr[indexWordHi( 4 )]; + expB = expF128UI96( uiB96 ); + signZ = signF128UI96( uiA96 ) ^ signF128UI96( uiB96 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; + ptr = aWPtr; + if ( ! expA ) goto possiblyInvalid; + if ( ! expB ) { + ptr = bWPtr; + possiblyInvalid: + if ( + ! fracF128UI96( ptr[indexWordHi( 4 )] ) + && ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )] + | ptr[indexWord( 4, 0 )]) + ) { + softfloat_invalidF128M( zWPtr ); + return; + } + } + uiZ96 = packToF128UI96( signZ, 0x7FFF, 0 ); + goto uiZ96; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA ) { + sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000; + sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + } else { + expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA ); + if ( expA == -128 ) goto zero; + } + if ( expB ) { + sigB[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000; + sigB[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )]; + sigB[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )]; + sigB[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )]; + } else { + expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigB ); + if ( expB == -128 ) goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x4000; + softfloat_mul128MTo256M( sigA, sigB, sigProd ); + if ( + sigProd[indexWord( 8, 2 )] + || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) + ) { + sigProd[indexWord( 8, 3 )] |= 1; + } + extSigZPtr = &sigProd[indexMultiwordHi( 8, 5 )]; + shiftCount = 16; + if ( extSigZPtr[indexWordHi( 5 )] & 2 ) { + ++expZ; + shiftCount = 15; + } + softfloat_shortShiftLeft160M( extSigZPtr, shiftCount, extSigZPtr ); + softfloat_roundPackMToF128M( signZ, expZ, extSigZPtr, zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ96 = packToF128UI96( signZ, 0, 0 ); + uiZ96: + zWPtr[indexWordHi( 4 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c new file mode 100644 index 0000000..193ed9d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + f128M_mulAdd( + const float128_t *aPtr, + const float128_t *bPtr, + const float128_t *cPtr, + float128_t *zPtr + ) +{ + const uint64_t *aWPtr, *bWPtr, *cWPtr; + uint_fast64_t uiA64, uiA0; + uint_fast64_t uiB64, uiB0; + uint_fast64_t uiC64, uiC0; + + aWPtr = (const uint64_t *) aPtr; + bWPtr = (const uint64_t *) bPtr; + cWPtr = (const uint64_t *) cPtr; + uiA64 = aWPtr[indexWord( 2, 1 )]; + uiA0 = aWPtr[indexWord( 2, 0 )]; + uiB64 = bWPtr[indexWord( 2, 1 )]; + uiB0 = bWPtr[indexWord( 2, 0 )]; + uiC64 = cWPtr[indexWord( 2, 1 )]; + uiC0 = cWPtr[indexWord( 2, 0 )]; + *zPtr = softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 ); + +} + +#else + +void + f128M_mulAdd( + const float128_t *aPtr, + const float128_t *bPtr, + const float128_t *cPtr, + float128_t *zPtr + ) +{ + + softfloat_mulAddF128M( + (const uint32_t *) aPtr, + (const uint32_t *) bPtr, + (const uint32_t *) cPtr, + (uint32_t *) zPtr, + 0 + ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c new file mode 100644 index 0000000..52c038d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + f128M_rem( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + + *zPtr = f128_rem( *aPtr, *bPtr ); + +} + +#else + +void + f128M_rem( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + const uint32_t *aWPtr, *bWPtr; + uint32_t *zWPtr, uiA96; + int32_t expA, expB; + uint32_t x[4], rem1[5], *remPtr; + bool signRem; + int32_t expDiff; + uint32_t q, recip32; + uint64_t q64; + uint32_t rem2[5], *altRemPtr, *newRemPtr, wordMeanRem; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aWPtr = (const uint32_t *) aPtr; + bWPtr = (const uint32_t *) bPtr; + zWPtr = (uint32_t *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA96 = aWPtr[indexWordHi( 4 )]; + expA = expF128UI96( uiA96 ); + expB = expF128UI96( bWPtr[indexWordHi( 4 )] ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; + if ( expA == 0x7FFF ) goto invalid; + goto copyA; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA < expB - 1 ) goto copyA; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expB = softfloat_shiftNormSigF128M( bWPtr, 13, x ); + if ( expB == -128 ) goto invalid; + remPtr = &rem1[indexMultiwordLo( 5, 4 )]; + expA = softfloat_shiftNormSigF128M( aWPtr, 13, remPtr ); + if ( expA == -128 ) goto copyA; + signRem = signF128UI96( uiA96 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if ( expDiff < 1 ) { + if ( expDiff < -1 ) goto copyA; + if ( expDiff ) { + --expB; + softfloat_add128M( x, x, x ); + q = 0; + } else { + q = (softfloat_compare128M( x, remPtr ) <= 0); + if ( q ) softfloat_sub128M( remPtr, x, remPtr ); + } + } else { + recip32 = + softfloat_approxRecip32_1( + ((uint64_t) x[indexWord( 4, 3 )]<<32 | x[indexWord( 4, 2 )]) + >>30 + ); + expDiff -= 30; + for (;;) { + q64 = (uint64_t) remPtr[indexWordHi( 4 )] * recip32; + if ( expDiff < 0 ) break; + q = (q64 + 0x80000000)>>32; + softfloat_remStep128MBy32( remPtr, 29, x, q, remPtr ); + if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) { + softfloat_add128M( remPtr, x, remPtr ); + } + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -29 here.) + *--------------------------------------------------------------------*/ + q = (uint32_t) (q64>>32)>>(~expDiff & 31); + softfloat_remStep128MBy32( remPtr, expDiff + 30, x, q, remPtr ); + if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) { + altRemPtr = &rem2[indexMultiwordLo( 5, 4 )]; + softfloat_add128M( remPtr, x, altRemPtr ); + goto selectRem; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + altRemPtr = &rem2[indexMultiwordLo( 5, 4 )]; + do { + ++q; + newRemPtr = altRemPtr; + softfloat_sub128M( remPtr, x, newRemPtr ); + altRemPtr = remPtr; + remPtr = newRemPtr; + } while ( ! (remPtr[indexWordHi( 4 )] & 0x80000000) ); + selectRem: + softfloat_add128M( remPtr, altRemPtr, x ); + wordMeanRem = x[indexWordHi( 4 )]; + if ( + (wordMeanRem & 0x80000000) + || (! wordMeanRem && (q & 1) && ! x[indexWord( 4, 0 )] + && ! (x[indexWord( 4, 2 )] | x[indexWord( 4, 1 )])) + ) { + remPtr = altRemPtr; + } + if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) { + signRem = ! signRem; + softfloat_negX128M( remPtr ); + } + remPtr -= indexMultiwordLo( 5, 4 ); + remPtr[indexWordHi( 5 )] = 0; + softfloat_normRoundPackMToF128M( signRem, expB + 18, remPtr, zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_invalidF128M( zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + copyA: + zWPtr[indexWordHi( 4 )] = uiA96; + zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c new file mode 100644 index 0000000..170e070 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + f128M_roundToInt( + const float128_t *aPtr, + uint_fast8_t roundingMode, + bool exact, + float128_t *zPtr + ) +{ + + *zPtr = f128_roundToInt( *aPtr, roundingMode, exact ); + +} + +#else + +void + f128M_roundToInt( + const float128_t *aPtr, + uint_fast8_t roundingMode, + bool exact, + float128_t *zPtr + ) +{ + const uint32_t *aWPtr; + uint32_t *zWPtr; + uint32_t ui96; + int32_t exp; + uint32_t sigExtra; + bool sign; + uint_fast8_t bitPos; + bool roundNear; + unsigned int index, lastIndex; + bool extra; + uint32_t wordA, bit, wordZ; + uint_fast8_t carry; + uint32_t extrasMask; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aWPtr = (const uint32_t *) aPtr; + zWPtr = (uint32_t *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + ui96 = aWPtr[indexWordHi( 4 )]; + exp = expF128UI96( ui96 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp < 0x3FFF ) { + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + sigExtra = aWPtr[indexWord( 4, 2 )]; + if ( ! sigExtra ) { + sigExtra = aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]; + } + if ( ! sigExtra && ! (ui96 & 0x7FFFFFFF) ) goto ui96; + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + sign = signF128UI96( ui96 ); + switch ( roundingMode ) { + case softfloat_round_near_even: + if ( ! fracF128UI96( ui96 ) && ! sigExtra ) break; + case softfloat_round_near_maxMag: + if ( exp == 0x3FFE ) goto mag1; + break; + case softfloat_round_min: + if ( sign ) goto mag1; + break; + case softfloat_round_max: + if ( ! sign ) goto mag1; + break; + } + ui96 = packToF128UI96( sign, 0, 0 ); + goto ui96; + mag1: + ui96 = packToF128UI96( sign, 0x3FFF, 0 ); + goto ui96; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x406F <= exp ) { + if ( + (exp == 0x7FFF) + && (fracF128UI96( ui96 ) + || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] + | aWPtr[indexWord( 4, 0 )])) + ) { + softfloat_propagateNaNF128M( aWPtr, 0, zWPtr ); + return; + } + zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + goto ui96; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bitPos = 0x406F - exp; + roundNear = + (roundingMode == softfloat_round_near_maxMag) + || (roundingMode == softfloat_round_near_even); + bitPos -= roundNear; + index = indexWordLo( 4 ); + lastIndex = indexWordHi( 4 ); + extra = 0; + for (;;) { + wordA = aWPtr[index]; + if ( bitPos < 32 ) break; + if ( wordA ) extra = 1; + zWPtr[index] = 0; + index += wordIncr; + bitPos -= 32; + } + bit = (uint32_t) 1< +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void f128M_sqrt( const float128_t *aPtr, float128_t *zPtr ) +{ + + *zPtr = f128_sqrt( *aPtr ); + +} + +#else + +void f128M_sqrt( const float128_t *aPtr, float128_t *zPtr ) +{ + const uint32_t *aWPtr; + uint32_t *zWPtr; + uint32_t uiA96; + bool signA; + int32_t rawExpA; + uint32_t rem[6]; + int32_t expA, expZ; + uint64_t rem64; + uint32_t sig32A, recipSqrt32, sig32Z, qs[3], q; + uint64_t sig64Z, x64; + uint32_t term[5], y[5], rem32; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aWPtr = (const uint32_t *) aPtr; + zWPtr = (uint32_t *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA96 = aWPtr[indexWordHi( 4 )]; + signA = signF128UI96( uiA96 ); + rawExpA = expF128UI96( uiA96 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( rawExpA == 0x7FFF ) { + if ( + fracF128UI96( uiA96 ) + || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] + | aWPtr[indexWord( 4, 0 )]) + ) { + softfloat_propagateNaNF128M( aWPtr, 0, zWPtr ); + return; + } + if ( ! signA ) goto copyA; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = softfloat_shiftNormSigF128M( aWPtr, 13 - (rawExpA & 1), rem ); + if ( expA == -128 ) goto copyA; + if ( signA ) goto invalid; + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FFF)>>1) + 0x3FFE; + expA &= 1; + rem64 = (uint64_t) rem[indexWord( 4, 3 )]<<32 | rem[indexWord( 4, 2 )]; + if ( expA ) { + if ( ! rawExpA ) { + softfloat_shortShiftRight128M( rem, 1, rem ); + rem64 >>= 1; + } + sig32A = rem64>>29; + } else { + sig32A = rem64>>30; + } + recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); + sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; + if ( expA ) sig32Z >>= 1; + qs[2] = sig32Z; + rem64 -= (uint64_t) sig32Z * sig32Z; + rem[indexWord( 4, 3 )] = rem64>>32; + rem[indexWord( 4, 2 )] = rem64; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32; + qs[1] = q; + sig64Z = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<3); + x64 = ((uint64_t) sig32Z<<32) + sig64Z; + term[indexWord( 4, 3 )] = 0; + term[indexWord( 4, 2 )] = x64>>32; + term[indexWord( 4, 1 )] = x64; + term[indexWord( 4, 0 )] = 0; + softfloat_remStep128MBy32( rem, 29, term, q, y ); + rem64 = (uint64_t) y[indexWord( 4, 3 )]<<32 | y[indexWord( 4, 2 )]; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32; + sig64Z <<= 1; + /*------------------------------------------------------------------------ + | (Repeating this loop is a rare occurrence.) + *------------------------------------------------------------------------*/ + for (;;) { + x64 = sig64Z + (q>>26); + term[indexWord( 4, 2 )] = x64>>32; + term[indexWord( 4, 1 )] = x64; + term[indexWord( 4, 0 )] = q<<6; + term[indexWord( 4, 3 )] = 0; + softfloat_remStep128MBy32( + y, 29, term, q, &rem[indexMultiwordHi( 6, 4 )] ); + rem32 = rem[indexWordHi( 6 )]; + if ( ! (rem32 & 0x80000000) ) break; + --q; + } + qs[0] = q; + rem64 = (uint64_t) rem32<<32 | rem[indexWord( 6, 4 )]; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = (((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32) + 2; + x64 = (uint64_t) q<<27; + y[indexWord( 5, 0 )] = x64; + x64 = ((uint64_t) qs[0]<<24) + (x64>>32); + y[indexWord( 5, 1 )] = x64; + x64 = ((uint64_t) qs[1]<<21) + (x64>>32); + y[indexWord( 5, 2 )] = x64; + x64 = ((uint64_t) qs[2]<<18) + (x64>>32); + y[indexWord( 5, 3 )] = x64; + y[indexWord( 5, 4 )] = x64>>32; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (q & 0xF) <= 2 ) { + q &= ~3; + y[indexWordLo( 5 )] = q<<27; + term[indexWord( 5, 4 )] = 0; + term[indexWord( 5, 3 )] = 0; + term[indexWord( 5, 2 )] = 0; + term[indexWord( 5, 1 )] = q>>6; + term[indexWord( 5, 0 )] = q<<26; + softfloat_sub160M( y, term, term ); + rem[indexWord( 6, 1 )] = 0; + rem[indexWord( 6, 0 )] = 0; + softfloat_remStep160MBy32( + &rem[indexMultiwordLo( 6, 5 )], + 14, + term, + q, + &rem[indexMultiwordLo( 6, 5 )] + ); + rem32 = rem[indexWord( 6, 4 )]; + if ( rem32 & 0x80000000 ) { + softfloat_sub1X160M( y ); + } else { + if ( + rem32 || rem[indexWord( 6, 0 )] || rem[indexWord( 6, 1 )] + || (rem[indexWord( 6, 3 )] | rem[indexWord( 6, 2 )]) + ) { + y[indexWordLo( 5 )] |= 1; + } + } + } + softfloat_roundPackMToF128M( 0, expZ, y, zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_invalidF128M( zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + copyA: + zWPtr[indexWordHi( 4 )] = uiA96; + zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c new file mode 100644 index 0000000..c55f455 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void + f128M_sub( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + const uint64_t *aWPtr, *bWPtr; + uint_fast64_t uiA64, uiA0; + bool signA; + uint_fast64_t uiB64, uiB0; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + float128_t + (*magsFuncPtr)( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); +#endif + + aWPtr = (const uint64_t *) aPtr; + bWPtr = (const uint64_t *) bPtr; + uiA64 = aWPtr[indexWord( 2, 1 )]; + uiA0 = aWPtr[indexWord( 2, 0 )]; + signA = signF128UI64( uiA64 ); + uiB64 = bWPtr[indexWord( 2, 1 )]; + uiB0 = bWPtr[indexWord( 2, 0 )]; + signB = signF128UI64( uiB64 ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); + } else { + *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128; + *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); +#endif + +} + +#else + +void + f128M_sub( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) +{ + + softfloat_addF128M( + (const uint32_t *) aPtr, + (const uint32_t *) bPtr, + (uint32_t *) zPtr, + true + ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c new file mode 100644 index 0000000..ff2ae39 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr ) +{ + + *zPtr = f128_to_extF80( *aPtr ); + +} + +#else + +void f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr ) +{ + const uint32_t *aWPtr; + struct extFloat80M *zSPtr; + uint32_t uiA96; + bool sign; + int32_t exp; + struct commonNaN commonNaN; + uint32_t sig[4]; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + aWPtr = (const uint32_t *) aPtr; + zSPtr = (struct extFloat80M *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA96 = aWPtr[indexWordHi( 4 )]; + sign = signF128UI96( uiA96 ); + exp = expF128UI96( uiA96 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp == 0x7FFF ) { + if ( softfloat_isNaNF128M( aWPtr ) ) { + softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); + softfloat_commonNaNToExtF80M( &commonNaN, zSPtr ); + return; + } + zSPtr->signExp = packToExtF80UI64( sign, 0x7FFF ); + zSPtr->signif = UINT64_C( 0x8000000000000000 ); + return; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = softfloat_shiftNormSigF128M( aWPtr, 15, sig ); + if ( exp == -128 ) { + zSPtr->signExp = packToExtF80UI64( sign, 0 ); + zSPtr->signif = 0; + return; + } + if ( sig[indexWord( 4, 0 )] ) sig[indexWord( 4, 1 )] |= 1; + softfloat_roundPackMToExtF80M( + sign, exp, &sig[indexMultiwordHi( 4, 3 )], 80, zSPtr ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c new file mode 100644 index 0000000..a2c0e27 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +float32_t f128M_to_f32( const float128_t *aPtr ) +{ + + return f128_to_f32( *aPtr ); + +} + +#else + +float32_t f128M_to_f32( const float128_t *aPtr ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + bool sign; + int32_t exp; + uint64_t sig64; + struct commonNaN commonNaN; + uint32_t uiZ, sig32; + union ui32_f32 uZ; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + sign = signF128UI96( uiA96 ); + exp = expF128UI96( uiA96 ); + sig64 = + (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )] + | ((aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); + if ( exp == 0x7FFF ) { + if ( sig64 ) { + softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); + uiZ = softfloat_commonNaNToF32UI( &commonNaN ); + } else { + uiZ = packToF32UI( sign, 0xFF, 0 ); + } + goto uiZ; + } + sig32 = softfloat_shortShiftRightJam64( sig64, 18 ); + if ( ! (exp | sig32) ) { + uiZ = packToF32UI( sign, 0, 0 ); + goto uiZ; + } + exp -= 0x3F81; + if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { + if ( exp < -0x1000 ) exp = -0x1000; + } + return softfloat_roundPackToF32( sign, exp, sig32 | 0x40000000 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c new file mode 100644 index 0000000..f5c6048 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +float64_t f128M_to_f64( const float128_t *aPtr ) +{ + + return f128_to_f64( *aPtr ); + +} + +#else + +float64_t f128M_to_f64( const float128_t *aPtr ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + bool sign; + int32_t exp; + uint64_t sig64; + struct commonNaN commonNaN; + uint64_t uiZ; + uint32_t sig32; + union ui64_f64 uZ; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + sign = signF128UI96( uiA96 ); + exp = expF128UI96( uiA96 ); + sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; + if ( exp == 0x7FFF ) { + if ( sig64 || aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) { + softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); + uiZ = softfloat_commonNaNToF64UI( &commonNaN ); + } else { + uiZ = packToF64UI( sign, 0x7FF, 0 ); + } + goto uiZ; + } + sig32 = aWPtr[indexWord( 4, 1 )]; + sig64 = sig64<<14 | sig32>>18; + if ( (sig32 & 0x0003FFFF) || aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; + if ( ! exp && ! sig64 ) { + uiZ = packToF64UI( sign, 0, 0 ); + goto uiZ; + } + exp -= 0x3C01; + if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { + if ( exp < -0x1000 ) exp = -0x1000; + } + return + softfloat_roundPackToF64( + sign, exp, sig64 | UINT64_C( 0x4000000000000000 ) ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c new file mode 100644 index 0000000..bfea0d7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +int_fast32_t + f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + + return f128_to_i32( *aPtr, roundingMode, exact ); + +} + +#else + +int_fast32_t + f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + bool sign; + int32_t exp; + uint64_t sig64; + bool notZeroSig0; + int32_t shiftCount; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + sign = signF128UI96( uiA96 ); + exp = expF128UI96( uiA96 ); + sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; + notZeroSig0 = false; + if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) { + sig64 |= 1; + notZeroSig0 = true; + } + if ( (exp == 0x7FFF) && (notZeroSig0 || sig64) ) sign = 0; + if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); + shiftCount = 0x4028 - exp; + if ( 0 < shiftCount ) { + sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); + } + return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c new file mode 100644 index 0000000..93fe6f2 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact ) +{ + + return f128_to_i32_r_minMag( *aPtr, exact ); + +} + +#else + +int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + bool sign; + int32_t exp; + uint64_t sig64; + int32_t shiftCount; + uint32_t absZ, uiZ; + union { uint32_t ui; int32_t i; } uZ; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + sign = signF128UI96( uiA96 ); + exp = expF128UI96( uiA96 ); + sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; + if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; + if ( exp < 0x3FFF ) { + if ( exact && (exp | sig64) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( 0x401F <= exp ) goto invalid; + shiftCount = 0x402F - exp; + sig64 |= UINT64_C( 0x0001000000000000 ); + absZ = sig64>>shiftCount; + uiZ = sign ? -absZ : absZ; + if ( uiZ>>31 != sign ) goto invalid; + if ( exact && ((uint64_t) absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +int_fast64_t + f128M_to_i64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + + return f128_to_i64( *aPtr, roundingMode, exact ); + +} + +#else + +int_fast64_t + f128M_to_i64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + int32_t exp; + bool sign; + uint32_t sig96; + int32_t shiftCount; + uint32_t sig[4]; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + exp = expF128UI96( uiA96 ); + sign = signF128UI96( uiA96 ); + sig96 = fracF128UI96( uiA96 ); + shiftCount = 0x404F - exp; + if ( shiftCount < 17 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + ! sign + || ((exp == 0x7FFF) + && (sig96 + || ( aWPtr[indexWord( 4, 2 )] + | aWPtr[indexWord( 4, 1 )] + | aWPtr[indexWord( 4, 0 )] + ))) + ? INT64_C( 0x7FFFFFFFFFFFFFFF ) + : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + if ( exp ) sig96 |= 0x00010000; + sig[indexWord( 4, 3 )] = sig96; + sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + softfloat_shiftRightJam128M( sig, shiftCount, sig ); + return + softfloat_roundPackMToI64( + sign, sig + indexMultiwordLo( 4, 3 ), roundingMode, exact ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c new file mode 100644 index 0000000..5b18bc3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +int_fast64_t f128M_to_i64_r_minMag( const float128_t *aPtr, bool exact ) +{ + + return f128_to_i64_r_minMag( *aPtr, exact ); + +} + +#else + +int_fast64_t f128M_to_i64_r_minMag( const float128_t *aPtr, bool exact ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + bool sign; + int32_t exp, shiftCount; + uint32_t sig96, sig[4]; + uint64_t uiZ; + union { uint64_t ui; int64_t i; } uZ; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + sign = signF128UI96( uiA96 ); + exp = expF128UI96( uiA96 ); + shiftCount = 0x403E - exp; + if ( shiftCount < 0 ) goto invalid; + if ( exact ) { + sig96 = fracF128UI96( uiA96 ); + if ( exp ) sig96 |= 0x00010000; + sig[indexWord( 4, 3 )] = sig96; + sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + softfloat_shiftRightJam128M( sig, shiftCount + 17, sig ); + uiZ = (uint64_t) sig[indexWord( 4, 2 )]<<32 | sig[indexWord( 4, 1 )]; + if ( uiZ>>63 && (! sign || (uiZ != UINT64_C( 0x8000000000000000 ))) ) { + goto invalid; + } + if ( sig[indexWordLo( 4 )] ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } else { + if ( 64 <= shiftCount ) return 0; + uiZ = + (uint64_t) fracF128UI96( uiA96 )<<47 + | (uint64_t) aWPtr[indexWord( 4, 2 )]<<15 + | aWPtr[indexWord( 4, 1 )]>>17; + if ( shiftCount ) { + uiZ |= UINT64_C( 0x8000000000000000 ); + uiZ >>= shiftCount; + } else { + if ( uiZ || ! sign ) goto invalid; + uiZ |= UINT64_C( 0x8000000000000000 ); + } + } + if ( sign ) uiZ = -uiZ; + uZ.ui = uiZ; + return uZ.i; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return + sign && ! softfloat_isNaNF128M( aWPtr ) + ? -UINT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 + : UINT64_C( 0x7FFFFFFFFFFFFFFF ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c new file mode 100644 index 0000000..493b028 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast32_t + f128M_to_ui32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + + return f128_to_ui32( *aPtr, roundingMode, exact ); + +} + +#else + +uint_fast32_t + f128M_to_ui32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + int32_t exp; + uint64_t sig64; + int32_t shiftCount; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + exp = expF128UI96( uiA96 ); + sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; + if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); + if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; + shiftCount = 0x4028 - exp; + if ( 0 < shiftCount ) { + sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); + } + return + softfloat_roundPackToUI32( + signF128UI96( uiA96 ), sig64, roundingMode, exact ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c new file mode 100644 index 0000000..fde3930 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *aPtr, bool exact ) +{ + + return f128_to_ui32_r_minMag( *aPtr, exact ); + +} + +#else + +uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *aPtr, bool exact ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + int32_t exp; + uint64_t sig64; + int32_t shiftCount; + uint32_t z; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + exp = expF128UI96( uiA96 ); + sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; + if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; + shiftCount = 0x402F - exp; + if ( 49 <= shiftCount ) { + if ( exact && (exp | sig64) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF128UI96( uiA96 ) || (shiftCount < 17) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return 0xFFFFFFFF; + } + sig64 |= UINT64_C( 0x0001000000000000 ); + z = sig64>>shiftCount; + if ( exact && ((uint64_t) z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast64_t + f128M_to_ui64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + + return f128_to_ui64( *aPtr, roundingMode, exact ); + +} + +#else + +uint_fast64_t + f128M_to_ui64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + int32_t exp, shiftCount; + uint32_t sig96, sig[4]; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + exp = expF128UI96( uiA96 ); + shiftCount = 0x404F - exp; + if ( shiftCount < 17 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + sig96 = fracF128UI96( uiA96 ); + if ( exp ) sig96 |= 0x00010000; + sig[indexWord( 4, 3 )] = sig96; + sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + softfloat_shiftRightJam128M( sig, shiftCount, sig ); + return + softfloat_roundPackMToUI64( + signF128UI96( uiA96 ), + sig + indexMultiwordLo( 4, 3 ), + roundingMode, + exact + ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c new file mode 100644 index 0000000..8807431 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *aPtr, bool exact ) +{ + + return f128_to_ui64_r_minMag( *aPtr, exact ); + +} + +#else + +uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *aPtr, bool exact ) +{ + const uint32_t *aWPtr; + uint32_t uiA96; + int32_t exp, shiftCount; + uint32_t sig96, sig[4]; + uint64_t z; + + aWPtr = (const uint32_t *) aPtr; + uiA96 = aWPtr[indexWordHi( 4 )]; + exp = expF128UI96( uiA96 ); + shiftCount = 0x403E - exp; + if ( shiftCount < 0 ) goto invalid; + if ( exact ) { + sig96 = fracF128UI96( uiA96 ); + if ( exp ) sig96 |= 0x00010000; + sig[indexWord( 4, 3 )] = sig96; + sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + softfloat_shiftRightJam128M( sig, shiftCount + 17, sig ); + z = (uint64_t) sig[indexWord( 4, 2 )]<<32 | sig[indexWord( 4, 1 )]; + if ( signF128UI96( uiA96 ) && z ) goto invalid; + if ( sig[indexWordLo( 4 )] ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } else { + if ( 64 <= shiftCount ) return 0; + if ( signF128UI96( uiA96 ) ) goto invalid; + z = UINT64_C( 0x8000000000000000 ) + | (uint64_t) fracF128UI96( uiA96 )<<47 + | (uint64_t) aWPtr[indexWord( 4, 2 )]<<15 + | aWPtr[indexWord( 4, 1 )]>>17; + z >>= shiftCount; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c new file mode 100644 index 0000000..7151116 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float128_t f128_add( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool signA; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + float128_t + (*magsFuncPtr)( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); +#endif + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + signA = signF128UI64( uiA64 ); + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + signB = signF128UI64( uiB64 ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); + } else { + return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128; + return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c new file mode 100644 index 0000000..f8581b5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f128_div( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool signA; + int_fast32_t expA; + struct uint128 sigA; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signB; + int_fast32_t expB; + struct uint128 sigB; + bool signZ; + struct exp32_sig128 normExpSig; + int_fast32_t expZ; + struct uint128 rem; + uint_fast32_t recip32; + int ix; + uint_fast64_t q64; + uint_fast32_t q; + struct uint128 term; + uint_fast32_t qs[3]; + uint_fast64_t sigZExtra; + struct uint128 sigZ, uiZ; + union ui128_f128 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + signA = signF128UI64( uiA64 ); + expA = expF128UI64( uiA64 ); + sigA.v64 = fracF128UI64( uiA64 ); + sigA.v0 = uiA0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + signB = signF128UI64( uiB64 ); + expB = expF128UI64( uiB64 ); + sigB.v64 = fracF128UI64( uiB64 ); + sigB.v0 = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( sigA.v64 | sigA.v0 ) goto propagateNaN; + if ( expB == 0x7FFF ) { + if ( sigB.v64 | sigB.v0 ) goto propagateNaN; + goto invalid; + } + goto infinity; + } + if ( expB == 0x7FFF ) { + if ( sigB.v64 | sigB.v0 ) goto propagateNaN; + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) { + if ( ! (sigB.v64 | sigB.v0) ) { + if ( ! (expA | sigA.v64 | sigA.v0) ) goto invalid; + softfloat_raiseFlags( softfloat_flag_infinite ); + goto infinity; + } + normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! (sigA.v64 | sigA.v0) ) goto zero; + normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FFE; + sigA.v64 |= UINT64_C( 0x0001000000000000 ); + sigB.v64 |= UINT64_C( 0x0001000000000000 ); + rem = sigA; + if ( softfloat_lt128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ) ) { + --expZ; + rem = softfloat_add128( sigA.v64, sigA.v0, sigA.v64, sigA.v0 ); + } + recip32 = softfloat_approxRecip32_1( sigB.v64>>17 ); + ix = 3; + for (;;) { + q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32; + q = (q64 + 0x80000000)>>32; + --ix; + if ( ix < 0 ) break; + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + term = softfloat_mul128By32( sigB.v64, sigB.v0, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + --q; + rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); + } + qs[ix] = q; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ((q + 1) & 7) < 2 ) { + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + term = softfloat_mul128By32( sigB.v64, sigB.v0, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + --q; + rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); + } else if ( softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ) ) { + ++q; + rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); + } + if ( rem.v64 | rem.v0 ) q |= 1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZExtra = (uint64_t) ((uint_fast64_t) q<<60); + term = softfloat_shortShiftLeft128( 0, qs[1], 54 ); + sigZ = + softfloat_add128( + (uint_fast64_t) qs[2]<<19, ((uint_fast64_t) qs[0]<<25) + (q>>4), + term.v64, term.v0 + ); + return + softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); + goto uiZ0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ.v64 = packToF128UI64( signZ, 0, 0 ); + uiZ0: + uiZ.v0 = 0; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c new file mode 100644 index 0000000..069f2a0 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f128_eq( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNF128UI( uiA64, uiA0 ) + || softfloat_isSigNaNF128UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + return + (uiA0 == uiB0) + && ( (uiA64 == uiB64) + || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c new file mode 100644 index 0000000..7c18ebd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f128_eq_signaling( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + return + (uiA0 == uiB0) + && ( (uiA64 == uiB64) + || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c new file mode 100644 index 0000000..0faa58a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f128_isSignalingNaN( float128_t a ) +{ + union ui128_f128 uA; + + uA.f = a; + return softfloat_isSigNaNF128UI( uA.ui.v64, uA.ui.v0 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c new file mode 100644 index 0000000..115501f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f128_le( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signA, signB; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF128UI64( uiA64 ); + signB = signF128UI64( uiB64 ); + return + (signA != signB) + ? signA + || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + | uiA0 | uiB0) + : ((uiA64 == uiB64) && (uiA0 == uiB0)) + || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c new file mode 100644 index 0000000..e026501 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f128_le_quiet( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signA, signB; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNF128UI( uiA64, uiA0 ) + || softfloat_isSigNaNF128UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF128UI64( uiA64 ); + signB = signF128UI64( uiB64 ); + return + (signA != signB) + ? signA + || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + | uiA0 | uiB0) + : ((uiA64 == uiB64) && (uiA0 == uiB0)) + || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c new file mode 100644 index 0000000..b35c762 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f128_lt( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signA, signB; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF128UI64( uiA64 ); + signB = signF128UI64( uiB64 ); + return + (signA != signB) + ? signA + && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + | uiA0 | uiB0) + : ((uiA64 != uiB64) || (uiA0 != uiB0)) + && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c new file mode 100644 index 0000000..90d1388 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f128_lt_quiet( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signA, signB; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { + if ( + softfloat_isSigNaNF128UI( uiA64, uiA0 ) + || softfloat_isSigNaNF128UI( uiB64, uiB0 ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF128UI64( uiA64 ); + signB = signF128UI64( uiB64 ); + return + (signA != signB) + ? signA + && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + | uiA0 | uiB0) + : ((uiA64 != uiB64) || (uiA0 != uiB0)) + && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c new file mode 100644 index 0000000..61c0e73 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f128_mul( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool signA; + int_fast32_t expA; + struct uint128 sigA; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signB; + int_fast32_t expB; + struct uint128 sigB; + bool signZ; + uint_fast64_t magBits; + struct exp32_sig128 normExpSig; + int_fast32_t expZ; + uint64_t sig256Z[4]; + uint_fast64_t sigZExtra; + struct uint128 sigZ; + struct uint128_extra sig128Extra; + struct uint128 uiZ; + union ui128_f128 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + signA = signF128UI64( uiA64 ); + expA = expF128UI64( uiA64 ); + sigA.v64 = fracF128UI64( uiA64 ); + sigA.v0 = uiA0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + signB = signF128UI64( uiB64 ); + expB = expF128UI64( uiB64 ); + sigB.v64 = fracF128UI64( uiB64 ); + sigB.v0 = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( + (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0)) + ) { + goto propagateNaN; + } + magBits = expB | sigB.v64 | sigB.v0; + goto infArg; + } + if ( expB == 0x7FFF ) { + if ( sigB.v64 | sigB.v0 ) goto propagateNaN; + magBits = expA | sigA.v64 | sigA.v0; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! (sigA.v64 | sigA.v0) ) goto zero; + normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! (sigB.v64 | sigB.v0) ) goto zero; + normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x4000; + sigA.v64 |= UINT64_C( 0x0001000000000000 ); + sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 16 ); + softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z ); + sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0); + sigZ = + softfloat_add128( + sig256Z[indexWord( 4, 3 )], sig256Z[indexWord( 4, 2 )], + sigA.v64, sigA.v0 + ); + if ( UINT64_C( 0x0002000000000000 ) <= sigZ.v64 ) { + ++expZ; + sig128Extra = + softfloat_shortShiftRightJam128Extra( + sigZ.v64, sigZ.v0, sigZExtra, 1 ); + sigZ = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } + return + softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if ( ! magBits ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + goto uiZ; + } + uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); + goto uiZ0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ.v64 = packToF128UI64( signZ, 0, 0 ); + uiZ0: + uiZ.v0 = 0; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c new file mode 100644 index 0000000..c34cae2 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float128_t f128_mulAdd( float128_t a, float128_t b, float128_t c ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + union ui128_f128 uC; + uint_fast64_t uiC64, uiC0; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + uC.f = c; + uiC64 = uC.ui.v64; + uiC0 = uC.ui.v0; + return softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c new file mode 100644 index 0000000..08b9f44 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f128_rem( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool signA; + int_fast32_t expA; + struct uint128 sigA; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signB; + int_fast32_t expB; + struct uint128 sigB; + struct exp32_sig128 normExpSig; + struct uint128 rem; + int_fast32_t expDiff; + uint_fast32_t q, recip32; + uint_fast64_t q64; + struct uint128 term, altRem, meanRem; + bool signRem; + struct uint128 uiZ; + union ui128_f128 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + signA = signF128UI64( uiA64 ); + expA = expF128UI64( uiA64 ); + sigA.v64 = fracF128UI64( uiA64 ); + sigA.v0 = uiA0; + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + signB = signF128UI64( uiB64 ); + expB = expF128UI64( uiB64 ); + sigB.v64 = fracF128UI64( uiB64 ); + sigB.v0 = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( + (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0)) + ) { + goto propagateNaN; + } + goto invalid; + } + if ( expB == 0x7FFF ) { + if ( sigB.v64 | sigB.v0 ) goto propagateNaN; + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) { + if ( ! (sigB.v64 | sigB.v0) ) goto invalid; + normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! (sigA.v64 | sigA.v0) ) return a; + normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigA.v64 |= UINT64_C( 0x0001000000000000 ); + sigB.v64 |= UINT64_C( 0x0001000000000000 ); + rem = sigA; + expDiff = expA - expB; + if ( expDiff < 1 ) { + if ( expDiff < -1 ) return a; + if ( expDiff ) { + --expB; + sigB = softfloat_add128( sigB.v64, sigB.v0, sigB.v64, sigB.v0 ); + q = 0; + } else { + q = softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ); + if ( q ) { + rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); + } + } + } else { + recip32 = softfloat_approxRecip32_1( sigB.v64>>17 ); + expDiff -= 30; + for (;;) { + q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32; + if ( expDiff < 0 ) break; + q = (q64 + 0x80000000)>>32; + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + term = softfloat_mul128By32( sigB.v64, sigB.v0, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); + } + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -29 here.) + *--------------------------------------------------------------------*/ + q = (uint32_t) (q64>>32)>>(~expDiff & 31); + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 ); + term = softfloat_mul128By32( sigB.v64, sigB.v0, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + altRem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); + goto selectRem; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + do { + altRem = rem; + ++q; + rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); + } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ); + selectRem: + meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 ); + if ( + (meanRem.v64 & UINT64_C( 0x8000000000000000 )) + || (! (meanRem.v64 | meanRem.v0) && (q & 1)) + ) { + rem = altRem; + } + signRem = signA; + if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { + signRem = ! signRem; + rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 ); + } + return softfloat_normRoundPackToF128( signRem, expB - 1, rem.v64, rem.v0 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c new file mode 100644 index 0000000..392bddc --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t + f128_roundToInt( float128_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + int_fast32_t exp; + struct uint128 uiZ; + uint_fast64_t lastBitMask, roundBitsMask; + bool roundNearEven; + union ui128_f128 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + exp = expF128UI64( uiA64 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x402F <= exp ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( 0x406F <= exp ) { + if ( (exp == 0x7FFF) && (fracF128UI64( uiA64 ) | uiA0) ) { + uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 ); + goto uiZ; + } + return a; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + lastBitMask = (uint_fast64_t) 2<<(0x406E - exp); + roundBitsMask = lastBitMask - 1; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + roundNearEven = (roundingMode == softfloat_round_near_even); + if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) ) { + if ( exp == 0x402F ) { + if ( UINT64_C( 0x8000000000000000 ) <= uiZ.v0 ) { + ++uiZ.v64; + if ( + roundNearEven + && (uiZ.v0 == UINT64_C( 0x8000000000000000 )) + ) { + uiZ.v64 &= ~1; + } + } + } else { + uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, lastBitMask>>1 ); + if ( roundNearEven && ! (uiZ.v0 & roundBitsMask) ) { + uiZ.v0 &= ~lastBitMask; + } + } + } else if ( roundingMode != softfloat_round_minMag ) { + if ( + signF128UI64( uiZ.v64 ) ^ (roundingMode == softfloat_round_max) + ) { + uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, roundBitsMask ); + } + } + uiZ.v0 &= ~roundBitsMask; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( exp < 0x3FFF ) { + if ( ! ((uiA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0) ) { + return a; + } + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + uiZ.v64 = uiA64 & packToF128UI64( 1, 0, 0 ); + uiZ.v0 = 0; + switch ( roundingMode ) { + case softfloat_round_near_even: + if ( ! (fracF128UI64( uiA64 ) | uiA0) ) break; + case softfloat_round_near_maxMag: + if ( exp == 0x3FFE ) uiZ.v64 |= packToF128UI64( 0, 0x3FFF, 0 ); + break; + case softfloat_round_min: + if ( uiZ.v64 ) uiZ.v64 = packToF128UI64( 1, 0x3FFF, 0 ); + break; + case softfloat_round_max: + if ( ! uiZ.v64 ) uiZ.v64 = packToF128UI64( 0, 0x3FFF, 0 ); + break; + } + goto uiZ; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + uiZ.v64 = uiA64; + uiZ.v0 = 0; + lastBitMask = (uint_fast64_t) 1<<(0x402F - exp); + roundBitsMask = lastBitMask - 1; + if ( roundingMode == softfloat_round_near_maxMag ) { + uiZ.v64 += lastBitMask>>1; + } else if ( roundingMode == softfloat_round_near_even ) { + uiZ.v64 += lastBitMask>>1; + if ( ! ((uiZ.v64 & roundBitsMask) | uiA0) ) { + uiZ.v64 &= ~lastBitMask; + } + } else if ( roundingMode != softfloat_round_minMag ) { + if ( + signF128UI64( uiZ.v64 ) ^ (roundingMode == softfloat_round_max) + ) { + uiZ.v64 = (uiZ.v64 | (uiA0 != 0)) + roundBitsMask; + } + } + uiZ.v64 &= ~roundBitsMask; + } + if ( exact && ((uiZ.v64 != uiA64) || (uiZ.v0 != uiA0)) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c new file mode 100644 index 0000000..2eb072e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f128_sqrt( float128_t a ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool signA; + int_fast32_t expA; + struct uint128 sigA, uiZ; + struct exp32_sig128 normExpSig; + int_fast32_t expZ; + uint_fast32_t sig32A, recipSqrt32, sig32Z; + struct uint128 rem; + uint32_t qs[3]; + uint_fast32_t q; + uint_fast64_t x64, sig64Z; + struct uint128 term, y; + uint_fast64_t sigZExtra; + struct uint128 sigZ; + union ui128_f128 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + signA = signF128UI64( uiA64 ); + expA = expF128UI64( uiA64 ); + sigA.v64 = fracF128UI64( uiA64 ); + sigA.v0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( sigA.v64 | sigA.v0 ) { + uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 ); + goto uiZ; + } + if ( ! signA ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signA ) { + if ( ! (expA | sigA.v64 | sigA.v0) ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! (sigA.v64 | sigA.v0) ) return a; + normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FFF)>>1) + 0x3FFE; + expA &= 1; + sigA.v64 |= UINT64_C( 0x0001000000000000 ); + sig32A = sigA.v64>>17; + recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); + sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32; + if ( expA ) { + sig32Z >>= 1; + rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 12 ); + } else { + rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 13 ); + } + qs[2] = sig32Z; + rem.v64 -= (uint_fast64_t) sig32Z * sig32Z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = ((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32; + qs[1] = q; + x64 = (uint_fast64_t) sig32Z<<32; + sig64Z = x64 + ((uint_fast64_t) q<<3); + x64 += sig64Z; + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + term = softfloat_mul64ByShifted32To128( x64, q ); + rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = ((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32; + y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); + sig64Z <<= 1; + /*------------------------------------------------------------------------ + | (Repeating this loop is a rare occurrence.) + *------------------------------------------------------------------------*/ + for (;;) { + term = softfloat_shortShiftLeft128( 0, sig64Z, 32 ); + term = softfloat_add128( term.v64, term.v0, 0, (uint_fast64_t) q<<6 ); + term = softfloat_mul128By32( term.v64, term.v0, q ); + rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 ); + if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break; + --q; + } + qs[0] = q; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = (((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32) + 2; + sigZExtra = (uint64_t) ((uint_fast64_t) q<<59); + term = softfloat_shortShiftLeft128( 0, qs[1], 53 ); + sigZ = + softfloat_add128( + (uint_fast64_t) qs[2]<<18, ((uint_fast64_t) qs[0]<<24) + (q>>5), + term.v64, term.v0 + ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (q & 0xF) <= 2 ) { + q &= ~3; + sigZExtra = (uint64_t) ((uint_fast64_t) q<<59); + y = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, 6 ); + y.v0 |= sigZExtra>>58; + term = softfloat_sub128( y.v64, y.v0, 0, q ); + y = softfloat_mul64ByShifted32To128( term.v0, q ); + term = softfloat_mul64ByShifted32To128( term.v64, q ); + term = softfloat_add128( term.v64, term.v0, 0, y.v64 ); + rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 20 ); + term = softfloat_sub128( term.v64, term.v0, rem.v64, rem.v0 ); + /*-------------------------------------------------------------------- + | The concatenation of `term' and `y.v0' is now the negative remainder + | (3 words altogether). + *--------------------------------------------------------------------*/ + if ( term.v64 & UINT64_C( 0x8000000000000000 ) ) { + sigZExtra |= 1; + } else { + if ( term.v64 | term.v0 | y.v0 ) { + if ( sigZExtra ) { + --sigZExtra; + } else { + sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 ); + sigZExtra = ~0; + } + } + } + } + return softfloat_roundPackToF128( 0, expZ, sigZ.v64, sigZ.v0, sigZExtra ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c new file mode 100644 index 0000000..0ec2461 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float128_t f128_sub( float128_t a, float128_t b ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool signA; + union ui128_f128 uB; + uint_fast64_t uiB64, uiB0; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + float128_t + (*magsFuncPtr)( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); +#endif + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + signA = signF128UI64( uiA64 ); + uB.f = b; + uiB64 = uB.ui.v64; + uiB0 = uB.ui.v0; + signB = signF128UI64( uiB64 ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); + } else { + return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128; + return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c new file mode 100644 index 0000000..53a01e3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f128_to_extF80( float128_t a ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig64, sig0; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0; + struct exp32_sig128 normExpSig; + struct uint128 sig128; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + sign = signF128UI64( uiA64 ); + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ); + sig0 = uiA0; + if ( exp == 0x7FFF ) { + if ( sig64 | sig0 ) { + softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN ); + uiZ = softfloat_commonNaNToExtF80UI( &commonNaN ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64( sign, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + } + goto uiZ; + } + if ( ! exp ) { + if ( ! (sig64 | sig0) ) { + uiZ64 = packToExtF80UI64( sign, 0 ); + uiZ0 = 0; + goto uiZ; + } + normExpSig = softfloat_normSubnormalF128Sig( sig64, sig0 ); + exp = normExpSig.exp; + sig64 = normExpSig.sig.v64; + sig0 = normExpSig.sig.v0; + } else { + sig64 |= UINT64_C( 0x0001000000000000 ); + } + sig128 = softfloat_shortShiftLeft128( sig64, sig0, 15 ); + return softfloat_roundPackToExtF80( sign, exp, sig128.v64, sig128.v0, 80 ); + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c new file mode 100644 index 0000000..d700602 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f128_to_f32( float128_t a ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig64; + struct commonNaN commonNaN; + uint_fast32_t uiZ, sig32; + union ui32_f32 uZ; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + sign = signF128UI64( uiA64 ); + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0); + if ( exp == 0x7FFF ) { + if ( sig64 ) { + softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN ); + uiZ = softfloat_commonNaNToF32UI( &commonNaN ); + } else { + uiZ = packToF32UI( sign, 0xFF, 0 ); + } + goto uiZ; + } + sig32 = softfloat_shortShiftRightJam64( sig64, 18 ); + if ( ! (exp | sig32) ) { + uiZ = packToF32UI( sign, 0, 0 ); + goto uiZ; + } + exp -= 0x3F81; + if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { + if ( exp < -0x1000 ) exp = -0x1000; + } + return softfloat_roundPackToF32( sign, exp, sig32 | 0x40000000 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c new file mode 100644 index 0000000..a592d8f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f128_to_f64( float128_t a ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig64, sig0; + struct commonNaN commonNaN; + uint_fast64_t uiZ; + struct uint128 sig128; + union ui64_f64 uZ; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + sign = signF128UI64( uiA64 ); + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ); + sig0 = uiA0; + if ( exp == 0x7FFF ) { + if ( sig64 | sig0 ) { + softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN ); + uiZ = softfloat_commonNaNToF64UI( &commonNaN ); + } else { + uiZ = packToF64UI( sign, 0x7FF, 0 ); + } + goto uiZ; + } + sig128 = softfloat_shortShiftLeft128( sig64, sig0, 14 ); + sig64 = sig128.v64 | (sig128.v0 != 0); + if ( ! (exp | sig64) ) { + uiZ = packToF64UI( sign, 0, 0 ); + goto uiZ; + } + exp -= 0x3C01; + if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { + if ( exp < -0x1000 ) exp = -0x1000; + } + return + softfloat_roundPackToF64( + sign, exp, sig64 | UINT64_C( 0x4000000000000000 ) ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c new file mode 100644 index 0000000..5ac4b08 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f128_to_i32( float128_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig64, sig0; + int_fast32_t shiftCount; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + sign = signF128UI64( uiA64 ); + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ); + sig0 = uiA0; + if ( (exp == 0x7FFF) && (sig64 | sig0) ) sign = 0; + if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); + sig64 |= (sig0 != 0); + shiftCount = 0x4028 - exp; + if ( 0 < shiftCount ) { + sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); + } + return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c new file mode 100644 index 0000000..c03e822 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f128_to_i32_r_minMag( float128_t a, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + int_fast32_t exp; + uint_fast64_t sig64; + int_fast32_t shiftCount; + bool sign; + int_fast32_t absZ; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0); + shiftCount = 0x402F - exp; + if ( 49 <= shiftCount ) { + if ( exact && (exp | sig64) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signF128UI64( uiA64 ); + if ( shiftCount < 18 ) { + if ( + sign && (shiftCount == 17) + && (sig64 < UINT64_C( 0x0000000000020000 )) + ) { + if ( exact && sig64 ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } else { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ((exp == 0x7FFF) && sig64) ) return 0x7FFFFFFF; + } + return -0x7FFFFFFF - 1; + } + sig64 |= UINT64_C( 0x0001000000000000 ); + absZ = sig64>>shiftCount; + if ( + exact && ((uint_fast64_t) (uint_fast32_t) absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f128_to_i64( float128_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig64, sig0; + int_fast32_t shiftCount; + struct uint128 sig128; + struct uint64_extra sigExtra; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + sign = signF128UI64( uiA64 ); + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ); + sig0 = uiA0; + shiftCount = 0x402F - exp; + if ( shiftCount <= 0 ) { + if ( shiftCount < -15 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + ! sign || ((exp == 0x7FFF) && (sig64 | sig0)) + ? INT64_C( 0x7FFFFFFFFFFFFFFF ) + : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sig64 |= UINT64_C( 0x0001000000000000 ); + if ( shiftCount ) { + sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftCount ); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + } else { + if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); + sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftCount ); + sig64 = sigExtra.v; + sig0 = sigExtra.extra; + } + return softfloat_roundPackToI64( sign, sig64, sig0, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c new file mode 100644 index 0000000..0bd8c9a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f128_to_i64_r_minMag( float128_t a, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig64, sig0; + int_fast32_t shiftCount; + int_fast16_t negShiftCount; + int_fast64_t absZ; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + sign = signF128UI64( uiA64 ); + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ); + sig0 = uiA0; + shiftCount = 0x402F - exp; + if ( shiftCount < 0 ) { + if ( shiftCount < -14 ) { + if ( + (uiA64 == UINT64_C( 0xC03E000000000000 )) + && (sig0 < UINT64_C( 0x0002000000000000 )) + ) { + if ( exact && sig0 ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } else { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ((exp == 0x7FFF) && (sig64 | sig0)) ) { + return UINT64_C( 0x7FFFFFFFFFFFFFFF ); + } + } + return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sig64 |= UINT64_C( 0x0001000000000000 ); + negShiftCount = -shiftCount; + absZ = sig64<>(shiftCount & 63); + if ( exact && (uint64_t) (sig0<>shiftCount; + if ( exact && (sig0 || (absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t + f128_to_ui32( float128_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool sign; + int_fast32_t exp; + uint_fast64_t sig64, sig0; + int_fast32_t shiftCount; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + sign = signF128UI64( uiA64 ); + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ); + sig0 = uiA0; + if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); + sig64 |= (sig0 != 0); + shiftCount = 0x4028 - exp; + if ( 0 < shiftCount ) { + sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); + } + return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c new file mode 100644 index 0000000..075cc7d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t f128_to_ui32_r_minMag( float128_t a, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + int_fast32_t exp; + uint_fast64_t sig64; + int_fast32_t shiftCount; + uint_fast32_t z; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + exp = expF128UI64( uiA64 ); + sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0); + shiftCount = 0x402F - exp; + if ( 49 <= shiftCount ) { + if ( exact && (exp | sig64) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF128UI64( uiA64 ) || (shiftCount < 17) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return 0xFFFFFFFF; + } + sig64 |= UINT64_C( 0x0001000000000000 ); + z = sig64>>shiftCount; + if ( exact && ((uint_fast64_t) z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t + f128_to_ui64( float128_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + bool sign; + int_fast32_t exp, shiftCount; + uint_fast64_t sig64, sig0; + struct uint128 sig128; + struct uint64_extra sigExtra; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + sign = signF128UI64( uiA64 ); + exp = expF128UI64( uiA64 ); + shiftCount = 0x402F - exp; + if ( shiftCount <= 0 ) { + if ( shiftCount < -15 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + sig64 = fracF128UI64( uiA64 ) | UINT64_C( 0x0001000000000000 ); + sig0 = uiA0; + if ( shiftCount ) { + sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftCount ); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + } else { + sig64 = fracF128UI64( uiA64 ); + sig0 = uiA0; + if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); + sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftCount ); + sig64 = sigExtra.v; + sig0 = sigExtra.extra; + } + return softfloat_roundPackToUI64( sign, sig64, sig0, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c new file mode 100644 index 0000000..756ee12 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t f128_to_ui64_r_minMag( float128_t a, bool exact ) +{ + union ui128_f128 uA; + uint_fast64_t uiA64, uiA0; + int_fast32_t exp, shiftCount; + uint_fast64_t sig64, sig0; + int_fast16_t negShiftCount; + uint_fast64_t z; + + uA.f = a; + uiA64 = uA.ui.v64; + uiA0 = uA.ui.v0; + exp = expF128UI64( uiA64 ); + shiftCount = 0x402F - exp; + if ( shiftCount < 0 ) { + if ( signF128UI64( uiA64 ) || (shiftCount < -15) ) goto invalid; + sig64 = fracF128UI64( uiA64 ) | UINT64_C( 0x0001000000000000 ); + sig0 = uiA0; + negShiftCount = -shiftCount; + z = sig64<>(shiftCount & 63); + if ( exact && (uint64_t) (sig0<>shiftCount; + if ( exact && (sig0 || (z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t f32_add( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1) + float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t, bool ); +#endif + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); +#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_addMagsF32( uiA, uiB, signA ); + } else { + return softfloat_subMagsF32( uiA, uiB, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_addMagsF32 : softfloat_subMagsF32; + return (*magsFuncPtr)( uiA, uiB, signA ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c new file mode 100644 index 0000000..a8c10ea --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_div( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + int_fast16_t expA; + uint_fast32_t sigA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; + int_fast16_t expB; + uint_fast32_t sigB; + bool signZ; + struct exp16_sig32 normExpSig; + int_fast16_t expZ; +#ifdef SOFTFLOAT_FAST_DIV64TO32 + uint_fast64_t sig64A; + uint_fast32_t sigZ; +#else + uint_fast32_t sigZ; + uint_fast64_t rem; +#endif + uint_fast32_t uiZ; + union ui32_f32 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0xFF ) { + if ( sigA ) goto propagateNaN; + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + goto invalid; + } + goto infinity; + } + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) { + if ( ! sigB ) { + if ( ! (expA | sigA) ) goto invalid; + softfloat_raiseFlags( softfloat_flag_infinite ); + goto infinity; + } + normExpSig = softfloat_normSubnormalF32Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x7E; + sigA |= 0x00800000; + sigB |= 0x00800000; +#ifdef SOFTFLOAT_FAST_DIV64TO32 + if ( sigA < sigB ) { + --expZ; + sig64A = (uint_fast64_t) sigA<<31; + } else { + sig64A = (uint_fast64_t) sigA<<30; + } + sigZ = sig64A / sigB; + if ( ! (sigZ & 0x3F) ) sigZ |= ((uint_fast64_t) sigB * sigZ != sig64A); +#else + if ( sigA < sigB ) { + --expZ; + sigA <<= 8; + } else { + sigA <<= 7; + } + sigB <<= 8; + sigZ = ((uint_fast64_t) sigA * softfloat_approxRecip32_1( sigB ))>>32; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZ += 2; + if ( (sigZ & 0x3F) < 2 ) { + sigZ &= ~3; +#ifdef SOFTFLOAT_FAST_INT64 + rem = ((uint_fast64_t) sigA<<31) - (uint_fast64_t) sigZ * sigB; +#else + rem = ((uint_fast64_t) sigA<<32) - (uint_fast64_t) (sigZ<<1) * sigB; +#endif + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + sigZ -= 4; + } else { + if ( rem ) sigZ |= 1; + } + } +#endif + return softfloat_roundPackToF32( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ = packToF32UI( signZ, 0xFF, 0 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ = packToF32UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c new file mode 100644 index 0000000..d01f498 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f32_eq( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { + if ( + softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c new file mode 100644 index 0000000..de0e7c1 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f32_eq_signaling( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c new file mode 100644 index 0000000..44061a3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f32_isSignalingNaN( float32_t a ) +{ + union ui32_f32 uA; + + uA.f = a; + return softfloat_isSigNaNF32UI( uA.ui ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c new file mode 100644 index 0000000..3b018fc --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f32_le( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF32UI( uiA ); + signB = signF32UI( uiB ); + return + (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1) + : (uiA == uiB) || (signA ^ (uiA < uiB)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c new file mode 100644 index 0000000..dd6701e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f32_le_quiet( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { + if ( + softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF32UI( uiA ); + signB = signF32UI( uiB ); + return + (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1) + : (uiA == uiB) || (signA ^ (uiA < uiB)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c new file mode 100644 index 0000000..9bc4787 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f32_lt( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF32UI( uiA ); + signB = signF32UI( uiB ); + return + (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0) + : (uiA != uiB) && (signA ^ (uiA < uiB)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c new file mode 100644 index 0000000..f5dbe5d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f32_lt_quiet( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { + if ( + softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF32UI( uiA ); + signB = signF32UI( uiB ); + return + (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0) + : (uiA != uiB) && (signA ^ (uiA < uiB)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c new file mode 100644 index 0000000..d14c43b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_mul( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + int_fast16_t expA; + uint_fast32_t sigA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; + int_fast16_t expB; + uint_fast32_t sigB; + bool signZ; + uint_fast32_t magBits; + struct exp16_sig32 normExpSig; + int_fast16_t expZ; + uint_fast32_t sigZ, uiZ; + union ui32_f32 uZ; + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + signZ = signA ^ signB; + if ( expA == 0xFF ) { + if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN; + magBits = expB | sigB; + goto infArg; + } + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + magBits = expA | sigA; + goto infArg; + } + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zero; + normExpSig = softfloat_normSubnormalF32Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + expZ = expA + expB - 0x7F; + sigA = (sigA | 0x00800000)<<7; + sigB = (sigB | 0x00800000)<<8; + sigZ = softfloat_shortShiftRightJam64( (uint_fast64_t) sigA * sigB, 32 ); + if ( sigZ < 0x40000000 ) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF32( signZ, expZ, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + goto uiZ; + infArg: + if ( ! magBits ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + } else { + uiZ = packToF32UI( signZ, 0xFF, 0 ); + } + goto uiZ; + zero: + uiZ = packToF32UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c new file mode 100644 index 0000000..825aee1 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t f32_mulAdd( float32_t a, float32_t b, float32_t c ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + union ui32_f32 uB; + uint_fast32_t uiB; + union ui32_f32 uC; + uint_fast32_t uiC; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + uC.f = c; + uiC = uC.ui; + return softfloat_mulAddF32( uiA, uiB, uiC, 0 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c new file mode 100644 index 0000000..fc7c5fa --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_rem( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + int_fast16_t expA; + uint_fast32_t sigA; + union ui32_f32 uB; + uint_fast32_t uiB; + int_fast16_t expB; + uint_fast32_t sigB; + struct exp16_sig32 normExpSig; + uint32_t rem; + int_fast16_t expDiff; + uint32_t q, recip32, altRem, meanRem; + bool signRem; + uint_fast32_t uiZ; + union ui32_f32 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0xFF ) { + if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN; + goto invalid; + } + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) { + if ( ! sigB ) goto invalid; + normExpSig = softfloat_normSubnormalF32Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! sigA ) return a; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + rem = sigA | 0x00800000; + sigB |= 0x00800000; + expDiff = expA - expB; + if ( expDiff < 1 ) { + if ( expDiff < -1 ) return a; + sigB <<= 6; + if ( expDiff ) { + rem <<= 5; + q = 0; + } else { + rem <<= 6; + q = (sigB <= rem); + if ( q ) rem -= sigB; + } + } else { + recip32 = softfloat_approxRecip32_1( sigB<<8 ); + /*-------------------------------------------------------------------- + | Changing the shift of `rem' here requires also changing the initial + | subtraction from `expDiff'. + *--------------------------------------------------------------------*/ + rem <<= 7; + expDiff -= 31; + /*-------------------------------------------------------------------- + | The scale of `sigB' affects how many bits are obtained during each + | cycle of the loop. Currently this is 29 bits per loop iteration, + | which is believed to be the maximum possible. + *--------------------------------------------------------------------*/ + sigB <<= 6; + for (;;) { + q = (rem * (uint_fast64_t) recip32)>>32; + if ( expDiff < 0 ) break; + rem = -(q * (uint32_t) sigB); + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -30 here.) + *--------------------------------------------------------------------*/ + q >>= ~expDiff & 31; + rem = (rem<<(expDiff + 30)) - q * (uint32_t) sigB; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + do { + altRem = rem; + ++q; + rem -= sigB; + } while ( ! (rem & 0x80000000) ); + meanRem = rem + altRem; + if ( (meanRem & 0x80000000) || (! meanRem && (q & 1)) ) rem = altRem; + signRem = signA; + if ( 0x80000000 <= rem ) { + signRem = ! signRem; + rem = -rem; + } + return softfloat_normRoundPackToF32( signRem, expB, rem ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + goto uiZ; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c new file mode 100644 index 0000000..3dc945d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_roundToInt( float32_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t uiZ, lastBitMask, roundBitsMask; + union ui32_f32 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp <= 0x7E ) { + if ( ! (uint32_t) (uiA<<1) ) return a; + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + uiZ = uiA & packToF32UI( 1, 0, 0 ); + switch ( roundingMode ) { + case softfloat_round_near_even: + if ( ! fracF32UI( uiA ) ) break; + case softfloat_round_near_maxMag: + if ( exp == 0x7E ) uiZ |= packToF32UI( 0, 0x7F, 0 ); + break; + case softfloat_round_min: + if ( uiZ ) uiZ = packToF32UI( 1, 0x7F, 0 ); + break; + case softfloat_round_max: + if ( ! uiZ ) uiZ = packToF32UI( 0, 0x7F, 0 ); + break; + } + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x96 <= exp ) { + if ( (exp == 0xFF) && fracF32UI( uiA ) ) { + uiZ = softfloat_propagateNaNF32UI( uiA, 0 ); + goto uiZ; + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = uiA; + lastBitMask = (uint_fast32_t) 1<<(0x96 - exp); + roundBitsMask = lastBitMask - 1; + if ( roundingMode == softfloat_round_near_maxMag ) { + uiZ += lastBitMask>>1; + } else if ( roundingMode == softfloat_round_near_even ) { + uiZ += lastBitMask>>1; + if ( ! (uiZ & roundBitsMask) ) uiZ &= ~lastBitMask; + } else if ( roundingMode != softfloat_round_minMag ) { + if ( signF32UI( uiZ ) ^ (roundingMode == softfloat_round_max) ) { + uiZ += roundBitsMask; + } + } + uiZ &= ~roundBitsMask; + if ( exact && (uiZ != uiA) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c new file mode 100644 index 0000000..3526578 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f32_sqrt( float32_t a ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + int_fast16_t expA; + uint_fast32_t sigA, uiZ; + struct exp16_sig32 normExpSig; + int_fast16_t expZ; + uint_fast32_t sigZ, shiftedSigZ; + uint32_t negRem; + union ui32_f32 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0xFF ) { + if ( sigA ) { + uiZ = softfloat_propagateNaNF32UI( uiA, 0 ); + goto uiZ; + } + if ( ! signA ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signA ) { + if ( ! (expA | sigA) ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) return a; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x7F)>>1) + 0x7E; + expA &= 1; + sigA = (sigA | 0x00800000)<<8; + sigZ = + ((uint_fast64_t) sigA * softfloat_approxRecipSqrt32_1( expA, sigA )) + >>32; + if ( expA ) sigZ >>= 1; + sigZ += 2; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (sigZ & 0x3F) < 2 ) { + shiftedSigZ = sigZ>>2; + negRem = shiftedSigZ * shiftedSigZ; + sigZ = shiftedSigZ<<2; + if ( negRem & 0x80000000 ) { + sigZ |= 1; + } else { + if ( negRem ) --sigZ; + } + } + return softfloat_roundPackToF32( 0, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c new file mode 100644 index 0000000..d0dd638 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t f32_sub( float32_t a, float32_t b ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool signA; + union ui32_f32 uB; + uint_fast32_t uiB; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1) + float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t, bool ); +#endif + + uA.f = a; + uiA = uA.ui; + signA = signF32UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF32UI( uiB ); +#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_subMagsF32( uiA, uiB, signA ); + } else { + return softfloat_addMagsF32( uiA, uiB, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_subMagsF32 : softfloat_addMagsF32; + return (*magsFuncPtr)( uiA, uiB, signA ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c new file mode 100644 index 0000000..a500fcd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f32_to_extF80( float32_t a ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0; + struct exp16_sig32 normExpSig; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp == 0xFF ) { + if ( sig ) { + softfloat_f32UIToCommonNaN( uiA, &commonNaN ); + uiZ = softfloat_commonNaNToExtF80UI( &commonNaN ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64( sign, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + } + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ64 = packToExtF80UI64( sign, 0 ); + uiZ0 = 0; + goto uiZ; + } + normExpSig = softfloat_normSubnormalF32Sig( sig ); + exp = normExpSig.exp; + sig = normExpSig.sig; + } + uiZ64 = packToExtF80UI64( sign, exp + 0x3F80 ); + uiZ0 = (uint_fast64_t) (sig | 0x00800000)<<40; + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c new file mode 100644 index 0000000..88327c1 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void f32_to_extF80M( float32_t a, extFloat80_t *zPtr ) +{ + + *zPtr = f32_to_extF80( a ); + +} + +#else + +void f32_to_extF80M( float32_t a, extFloat80_t *zPtr ) +{ + struct extFloat80M *zSPtr; + union ui32_f32 uA; + uint32_t uiA; + bool sign; + int_fast16_t exp; + uint32_t sig; + struct commonNaN commonNaN; + uint_fast16_t uiZ64; + uint64_t uiZ0; + struct exp16_sig32 normExpSig; + + zSPtr = (struct extFloat80M *) zPtr; + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp == 0xFF ) { + if ( sig ) { + softfloat_f32UIToCommonNaN( uiA, &commonNaN ); + softfloat_commonNaNToExtF80M( &commonNaN, zSPtr ); + return; + } + uiZ64 = packToExtF80UI64( sign, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ64 = packToExtF80UI64( sign, 0 ); + uiZ0 = 0; + goto uiZ; + } + normExpSig = softfloat_normSubnormalF32Sig( sig ); + exp = normExpSig.exp; + sig = normExpSig.sig; + } + uiZ64 = packToExtF80UI64( sign, exp + 0x3F80 ); + uiZ0 = UINT64_C( 0x8000000000000000 ) | (uint64_t) sig<<40; + uiZ: + zSPtr->signExp = uiZ64; + zSPtr->signif = uiZ0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c new file mode 100644 index 0000000..bcd29f6 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f32_to_f128( float32_t a ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + struct commonNaN commonNaN; + struct uint128 uiZ; + struct exp16_sig32 normExpSig; + union ui128_f128 uZ; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp == 0xFF ) { + if ( sig ) { + softfloat_f32UIToCommonNaN( uiA, &commonNaN ); + uiZ = softfloat_commonNaNToF128UI( &commonNaN ); + } else { + uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 ); + uiZ.v0 = 0; + } + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ.v64 = packToF128UI64( sign, 0, 0 ); + uiZ.v0 = 0; + goto uiZ; + } + normExpSig = softfloat_normSubnormalF32Sig( sig ); + exp = normExpSig.exp - 1; + sig = normExpSig.sig; + } + uiZ.v64 = packToF128UI64( sign, exp + 0x3F80, (uint_fast64_t) sig<<25 ); + uiZ.v0 = 0; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c new file mode 100644 index 0000000..f9c2a44 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void f32_to_f128M( float32_t a, float128_t *zPtr ) +{ + + *zPtr = f32_to_f128( a ); + +} + +#else + +void f32_to_f128M( float32_t a, float128_t *zPtr ) +{ + uint32_t *zWPtr; + union ui32_f32 uA; + uint32_t uiA; + bool sign; + int_fast16_t exp; + uint32_t sig, uiZ64; + struct commonNaN commonNaN; + uint32_t uiZ96; + struct exp16_sig32 normExpSig; + uint64_t sig64; + + zWPtr = (uint32_t *) zPtr; + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + uiZ64 = 0; + if ( exp == 0xFF ) { + if ( sig ) { + softfloat_f32UIToCommonNaN( uiA, &commonNaN ); + softfloat_commonNaNToF128M( &commonNaN, zWPtr ); + return; + } + uiZ96 = packToF128UI96( sign, 0x7FFF, 0 ); + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ96 = packToF128UI96( sign, 0, 0 ); + goto uiZ; + } + normExpSig = softfloat_normSubnormalF32Sig( sig ); + exp = normExpSig.exp - 1; + sig = normExpSig.sig; + } + sig64 = (uint64_t) sig<<25; + uiZ96 = packToF128UI96( sign, exp + 0x3F80, sig64>>32 ); + uiZ64 = sig64; + uiZ: + zWPtr[indexWord( 4, 3 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = uiZ64; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c new file mode 100644 index 0000000..6e38abd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f32_to_f64( float32_t a ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + struct commonNaN commonNaN; + uint_fast64_t uiZ; + struct exp16_sig32 normExpSig; + union ui64_f64 uZ; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp == 0xFF ) { + if ( sig ) { + softfloat_f32UIToCommonNaN( uiA, &commonNaN ); + uiZ = softfloat_commonNaNToF64UI( &commonNaN ); + } else { + uiZ = packToF64UI( sign, 0x7FF, 0 ); + } + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ = packToF64UI( sign, 0, 0 ); + goto uiZ; + } + normExpSig = softfloat_normSubnormalF32Sig( sig ); + exp = normExpSig.exp - 1; + sig = normExpSig.sig; + } + uiZ = packToF64UI( sign, exp + 0x380, (uint_fast64_t) sig<<29 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c new file mode 100644 index 0000000..99bb045 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f32_to_i32( float32_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + uint_fast64_t sig64; + int_fast16_t shiftCount; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( (exp == 0xFF) && sig ) sign = 0; + if ( exp ) sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<32; + shiftCount = 0xAF - exp; + if ( 0 < shiftCount ) { + sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); + } + return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c new file mode 100644 index 0000000..20fa808 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f32_to_i32_r_minMag( float32_t a, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + bool sign; + int_fast32_t absZ; + + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0x9E - exp; + if ( 32 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signF32UI( uiA ); + if ( shiftCount <= 0 ) { + if ( uiA != packToF32UI( 1, 0x9E, 0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ((exp == 0xFF) && sig) ) return 0x7FFFFFFF; + } + return -0x7FFFFFFF - 1; + } + sig = (sig | 0x00800000)<<8; + absZ = sig>>shiftCount; + if ( exact && ((uint_fast32_t) absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f32_to_i64( float32_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; +#ifdef SOFTFLOAT_FAST_INT64 + uint_fast64_t sig64, extra; + struct uint64_extra sig64Extra; +#else + uint32_t extSig[3]; +#endif + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0xBE - exp; + if ( shiftCount < 0 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ((exp == 0xFF) && sig) ) { + return INT64_C( 0x7FFFFFFFFFFFFFFF ); + } + return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + if ( exp ) sig |= 0x00800000; +#ifdef SOFTFLOAT_FAST_INT64 + sig64 = (uint_fast64_t) sig<<40; + extra = 0; + if ( shiftCount ) { + sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, shiftCount ); + sig64 = sig64Extra.v; + extra = sig64Extra.extra; + } + return softfloat_roundPackToI64( sign, sig64, extra, roundingMode, exact ); +#else + extSig[indexWord( 3, 2 )] = sig<<8; + extSig[indexWord( 3, 1 )] = 0; + extSig[indexWord( 3, 0 )] = 0; + if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); + return softfloat_roundPackMToI64( sign, extSig, roundingMode, exact ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c new file mode 100644 index 0000000..bbf5b53 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f32_to_i64_r_minMag( float32_t a, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + bool sign; + uint_fast64_t sig64; + int_fast64_t absZ; + + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0xBE - exp; + if ( 64 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signF32UI( uiA ); + if ( shiftCount <= 0 ) { + if ( uiA != packToF32UI( 1, 0xBE, 0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ((exp == 0xFF) && sig) ) { + return INT64_C( 0x7FFFFFFFFFFFFFFF ); + } + } + return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<40; + absZ = sig64>>shiftCount; + shiftCount = 40 - shiftCount; + if ( exact && (shiftCount < 0) && (uint32_t) (sig<<(shiftCount & 31)) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return sign ? -absZ : absZ; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c new file mode 100644 index 0000000..a6267ff --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t f32_to_ui32( float32_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + uint_fast64_t sig64; + int_fast16_t shiftCount; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + if ( exp ) sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<32; + shiftCount = 0xAF - exp; + if ( 0 < shiftCount ) { + sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); + } + return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c new file mode 100644 index 0000000..090ceff --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t f32_to_ui32_r_minMag( float32_t a, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + uint_fast32_t z; + + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0x9E - exp; + if ( 32 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF32UI( uiA ) || (shiftCount < 0) ) goto invalid; + sig = (sig | 0x00800000)<<8; + z = sig>>shiftCount; + if ( exact && (z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +uint_fast64_t f32_to_ui64( float32_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + bool sign; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + uint_fast64_t sig64, extra; + struct uint64_extra sig64Extra; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0xBE - exp; + if ( shiftCount < 0 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + if ( exp ) sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<40; + extra = 0; + if ( shiftCount ) { + sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, shiftCount ); + sig64 = sig64Extra.v; + extra = sig64Extra.extra; + } + return + softfloat_roundPackToUI64( sign, sig64, extra, roundingMode, exact ); + +} + +#else + +uint_fast64_t f32_to_ui64( float32_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui32_f32 uA; + uint32_t uiA; + bool sign; + int_fast16_t exp; + uint32_t sig; + int_fast16_t shiftCount; + uint32_t extSig[3]; + + uA.f = a; + uiA = uA.ui; + sign = signF32UI( uiA ); + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0xBE - exp; + if ( shiftCount < 0 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + if ( exp ) sig |= 0x00800000; + extSig[indexWord( 3, 2 )] = sig<<8; + extSig[indexWord( 3, 1 )] = 0; + extSig[indexWord( 3, 0 )] = 0; + if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); + return softfloat_roundPackMToUI64( sign, extSig, roundingMode, exact ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c new file mode 100644 index 0000000..7d08797 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact ) +{ + union ui32_f32 uA; + uint_fast32_t uiA; + int_fast16_t exp; + uint_fast32_t sig; + int_fast16_t shiftCount; + uint_fast64_t sig64, z; + + uA.f = a; + uiA = uA.ui; + exp = expF32UI( uiA ); + sig = fracF32UI( uiA ); + shiftCount = 0xBE - exp; + if ( 64 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF32UI( uiA ) || (shiftCount < 0) ) goto invalid; + sig |= 0x00800000; + sig64 = (uint_fast64_t) sig<<40; + z = sig64>>shiftCount; + shiftCount = 40 - shiftCount; + if ( exact && (shiftCount < 0) && (uint32_t) (sig<<(shiftCount & 31)) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c new file mode 100644 index 0000000..29ff80a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t f64_add( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool ); +#endif + + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_addMagsF64( uiA, uiB, signA ); + } else { + return softfloat_subMagsF64( uiA, uiB, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_addMagsF64 : softfloat_subMagsF64; + return (*magsFuncPtr)( uiA, uiB, signA ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c new file mode 100644 index 0000000..a73947a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_div( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; + int_fast16_t expB; + uint_fast64_t sigB; + bool signZ; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; + uint32_t recip32, sig32Z, doubleTerm; + uint_fast64_t rem; + uint32_t q; + uint_fast64_t sigZ; + uint_fast64_t uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA ) goto propagateNaN; + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + goto invalid; + } + goto infinity; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) { + if ( ! sigB ) { + if ( ! (expA | sigA) ) goto invalid; + softfloat_raiseFlags( softfloat_flag_infinite ); + goto infinity; + } + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FE; + sigA |= UINT64_C( 0x0010000000000000 ); + sigB |= UINT64_C( 0x0010000000000000 ); + if ( sigA < sigB ) { + --expZ; + sigA <<= 11; + } else { + sigA <<= 10; + } + sigB <<= 11; + recip32 = softfloat_approxRecip32_1( sigB>>32 ) - 2; + sig32Z = ((uint32_t) (sigA>>32) * (uint_fast64_t) recip32)>>32; + doubleTerm = sig32Z<<1; + rem = + ((sigA - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4); + q = (((uint32_t) (rem>>32) * (uint_fast64_t) recip32)>>32) + 4; + sigZ = ((uint_fast64_t) sig32Z<<32) + ((uint_fast64_t) q<<4); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (sigZ & 0x1FF) < 4<<4 ) { + q &= ~7; + sigZ &= ~(uint_fast64_t) 0x7F; + doubleTerm = q<<1; + rem = + ((rem - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4); + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + sigZ -= 1<<7; + } else { + if ( rem ) sigZ |= 1; + } + } + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ = packToF64UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c new file mode 100644 index 0000000..901626d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f64_eq( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { + if ( + softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + return (uiA == uiB) || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c new file mode 100644 index 0000000..c58c509 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f64_eq_signaling( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + return (uiA == uiB) || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c new file mode 100644 index 0000000..32b2a94 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f64_isSignalingNaN( float64_t a ) +{ + union ui64_f64 uA; + + uA.f = a; + return softfloat_isSigNaNF64UI( uA.ui ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c new file mode 100644 index 0000000..03bcb59 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f64_le( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF64UI( uiA ); + signB = signF64UI( uiB ); + return + (signA != signB) + ? signA || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + : (uiA == uiB) || (signA ^ (uiA < uiB)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c new file mode 100644 index 0000000..0601f81 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f64_le_quiet( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { + if ( + softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF64UI( uiA ); + signB = signF64UI( uiB ); + return + (signA != signB) + ? signA || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + : (uiA == uiB) || (signA ^ (uiA < uiB)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c new file mode 100644 index 0000000..72ab2cc --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bool f64_lt( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return false; + } + signA = signF64UI( uiA ); + signB = signF64UI( uiB ); + return + (signA != signB) + ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + : (uiA != uiB) && (signA ^ (uiA < uiB)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c new file mode 100644 index 0000000..2a6addd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f64_lt_quiet( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signA, signB; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { + if ( + softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) + ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + } + return false; + } + signA = signF64UI( uiA ); + signB = signF64UI( uiB ); + return + (signA != signB) + ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + : (uiA != uiB) && (signA ^ (uiA < uiB)); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c new file mode 100644 index 0000000..441158e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_mul( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; + int_fast16_t expB; + uint_fast64_t sigB; + bool signZ; + uint_fast64_t magBits; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; +#ifdef SOFTFLOAT_FAST_INT64 + struct uint128 sig128Z; +#else + uint32_t sig128Z[4]; +#endif + uint_fast64_t sigZ, uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN; + magBits = expB | sigB; + goto infArg; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + magBits = expA | sigA; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) goto zero; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zero; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FF; + sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; + sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11; +#ifdef SOFTFLOAT_FAST_INT64 + sig128Z = softfloat_mul64To128( sigA, sigB ); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); +#else + softfloat_mul64To128M( sigA, sigB, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; + if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1; +#endif + if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if ( ! magBits ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + } else { + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + } + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ = packToF64UI( signZ, 0, 0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c new file mode 100644 index 0000000..50ff155 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + union ui64_f64 uB; + uint_fast64_t uiB; + union ui64_f64 uC; + uint_fast64_t uiC; + + uA.f = a; + uiA = uA.ui; + uB.f = b; + uiB = uB.ui; + uC.f = c; + uiC = uC.ui; + return softfloat_mulAddF64( uiA, uiB, uiC, 0 ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c new file mode 100644 index 0000000..a87fdd8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_rem( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + union ui64_f64 uB; + uint_fast64_t uiB; + int_fast16_t expB; + uint_fast64_t sigB; + struct exp16_sig64 normExpSig; + uint64_t rem; + int_fast16_t expDiff; + uint32_t q, recip32; + uint_fast64_t q64; + uint64_t altRem, meanRem; + bool signRem; + uint_fast64_t uiZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN; + goto invalid; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA < expB - 1 ) return a; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expB ) { + if ( ! sigB ) goto invalid; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if ( ! expA ) { + if ( ! sigA ) return a; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + rem = sigA | UINT64_C( 0x0010000000000000 ); + sigB |= UINT64_C( 0x0010000000000000 ); + expDiff = expA - expB; + if ( expDiff < 1 ) { + if ( expDiff < -1 ) return a; + sigB <<= 9; + if ( expDiff ) { + rem <<= 8; + q = 0; + } else { + rem <<= 9; + q = (sigB <= rem); + if ( q ) rem -= sigB; + } + } else { + recip32 = softfloat_approxRecip32_1( sigB>>21 ); + /*-------------------------------------------------------------------- + | Changing the shift of `rem' here requires also changing the initial + | subtraction from `expDiff'. + *--------------------------------------------------------------------*/ + rem <<= 9; + expDiff -= 30; + /*-------------------------------------------------------------------- + | The scale of `sigB' affects how many bits are obtained during each + | cycle of the loop. Currently this is 29 bits per loop iteration, + | the maximum possible. + *--------------------------------------------------------------------*/ + sigB <<= 9; + for (;;) { + q64 = (uint32_t) (rem>>32) * (uint_fast64_t) recip32; + if ( expDiff < 0 ) break; + q = (q64 + 0x80000000)>>32; +#ifdef SOFTFLOAT_FAST_INT64 + rem <<= 29; +#else + rem = (uint_fast64_t) (uint32_t) (rem>>3)<<32; +#endif + rem -= q * (uint64_t) sigB; + if ( rem & UINT64_C( 0x8000000000000000 ) ) rem += sigB; + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -29 here.) + *--------------------------------------------------------------------*/ + q = (uint32_t) (q64>>32)>>(~expDiff & 31); + rem = (rem<<(expDiff + 30)) - q * (uint64_t) sigB; + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + altRem = rem + sigB; + goto selectRem; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + do { + altRem = rem; + ++q; + rem -= sigB; + } while ( ! (rem & UINT64_C( 0x8000000000000000 )) ); + selectRem: + meanRem = rem + altRem; + if ( + (meanRem & UINT64_C( 0x8000000000000000 )) || (! meanRem && (q & 1)) + ) { + rem = altRem; + } + signRem = signA; + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + signRem = ! signRem; + rem = -rem; + } + return softfloat_normRoundPackToF64( signRem, expB, rem ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto uiZ; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c new file mode 100644 index 0000000..7c02a08 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t exp; + uint_fast64_t uiZ, lastBitMask, roundBitsMask; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( exp <= 0x3FE ) { + if ( ! (uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) return a; + if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; + uiZ = uiA & packToF64UI( 1, 0, 0 ); + switch ( roundingMode ) { + case softfloat_round_near_even: + if ( ! fracF64UI( uiA ) ) break; + case softfloat_round_near_maxMag: + if ( exp == 0x3FE ) uiZ |= packToF64UI( 0, 0x3FF, 0 ); + break; + case softfloat_round_min: + if ( uiZ ) uiZ = packToF64UI( 1, 0x3FF, 0 ); + break; + case softfloat_round_max: + if ( ! uiZ ) uiZ = packToF64UI( 0, 0x3FF, 0 ); + break; + } + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x433 <= exp ) { + if ( (exp == 0x7FF) && fracF64UI( uiA ) ) { + uiZ = softfloat_propagateNaNF64UI( uiA, 0 ); + goto uiZ; + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = uiA; + lastBitMask = (uint_fast64_t) 1<<(0x433 - exp); + roundBitsMask = lastBitMask - 1; + if ( roundingMode == softfloat_round_near_maxMag ) { + uiZ += lastBitMask>>1; + } else if ( roundingMode == softfloat_round_near_even ) { + uiZ += lastBitMask>>1; + if ( ! (uiZ & roundBitsMask) ) uiZ &= ~lastBitMask; + } else if ( roundingMode != softfloat_round_minMag ) { + if ( signF64UI( uiZ ) ^ (roundingMode == softfloat_round_max) ) { + uiZ += roundBitsMask; + } + } + uiZ &= ~roundBitsMask; + if ( exact && (uiZ != uiA) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c new file mode 100644 index 0000000..f2ffe2b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t f64_sqrt( float64_t a ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + int_fast16_t expA; + uint_fast64_t sigA, uiZ; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; + uint32_t sig32A, recipSqrt32, sig32Z; + uint_fast64_t rem; + uint32_t q; + uint_fast64_t sigZ, shiftedSigZ; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA ) { + uiZ = softfloat_propagateNaNF64UI( uiA, 0 ); + goto uiZ; + } + if ( ! signA ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signA ) { + if ( ! (expA | sigA) ) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) return a; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FF)>>1) + 0x3FE; + expA &= 1; + sigA |= UINT64_C( 0x0010000000000000 ); + sig32A = sigA>>21; + recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); + sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32; + if ( expA ) { + sigA <<= 8; + sig32Z >>= 1; + } else { + sigA <<= 9; + } + rem = sigA - (uint_fast64_t) sig32Z * sig32Z; + q = ((uint32_t) (rem>>2) * (uint_fast64_t) recipSqrt32)>>32; + sigZ = ((uint_fast64_t) sig32Z<<32 | 1<<5) + ((uint_fast64_t) q<<3); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (sigZ & 0x1FF) < 1<<5 ) { + sigZ &= ~(uint_fast64_t) 0x3F; + shiftedSigZ = sigZ>>6; + rem = (sigA<<52) - shiftedSigZ * shiftedSigZ; + if ( rem & UINT64_C( 0x8000000000000000 ) ) { + --sigZ; + } else { + if ( rem ) sigZ |= 1; + } + } + return softfloat_roundPackToF64( 0, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c new file mode 100644 index 0000000..c5b65b6 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t f64_sub( float64_t a, float64_t b ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool signA; + union ui64_f64 uB; + uint_fast64_t uiB; + bool signB; +#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) + float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool ); +#endif + + uA.f = a; + uiA = uA.ui; + signA = signF64UI( uiA ); + uB.f = b; + uiB = uB.ui; + signB = signF64UI( uiB ); +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) + if ( signA == signB ) { + return softfloat_subMagsF64( uiA, uiB, signA ); + } else { + return softfloat_addMagsF64( uiA, uiB, signA ); + } +#else + magsFuncPtr = + (signA == signB) ? softfloat_subMagsF64 : softfloat_addMagsF64; + return (*magsFuncPtr)( uiA, uiB, signA ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c new file mode 100644 index 0000000..0aec3e3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f64_to_extF80( float64_t a ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0; + struct exp16_sig64 normExpSig; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp == 0x7FF ) { + if ( sig ) { + softfloat_f64UIToCommonNaN( uiA, &commonNaN ); + uiZ = softfloat_commonNaNToExtF80UI( &commonNaN ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64( sign, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + } + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ64 = packToExtF80UI64( sign, 0 ); + uiZ0 = 0; + goto uiZ; + } + normExpSig = softfloat_normSubnormalF64Sig( sig ); + exp = normExpSig.exp; + sig = normExpSig.sig; + } + uiZ64 = packToExtF80UI64( sign, exp + 0x3C00 ); + uiZ0 = (sig | UINT64_C( 0x0010000000000000 ))<<11; + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c new file mode 100644 index 0000000..d0fbb17 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void f64_to_extF80M( float64_t a, extFloat80_t *zPtr ) +{ + + *zPtr = f64_to_extF80( a ); + +} + +#else + +void f64_to_extF80M( float64_t a, extFloat80_t *zPtr ) +{ + struct extFloat80M *zSPtr; + union ui64_f64 uA; + uint64_t uiA; + bool sign; + int_fast16_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint_fast16_t uiZ64; + uint64_t uiZ0; + struct exp16_sig64 normExpSig; + + zSPtr = (struct extFloat80M *) zPtr; + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp == 0x7FF ) { + if ( sig ) { + softfloat_f64UIToCommonNaN( uiA, &commonNaN ); + softfloat_commonNaNToExtF80M( &commonNaN, zSPtr ); + return; + } + uiZ64 = packToExtF80UI64( sign, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ64 = packToExtF80UI64( sign, 0 ); + uiZ0 = 0; + goto uiZ; + } + normExpSig = softfloat_normSubnormalF64Sig( sig ); + exp = normExpSig.exp; + sig = normExpSig.sig; + } + uiZ64 = packToExtF80UI64( sign, exp + 0x3C00 ); + uiZ0 = UINT64_C( 0x8000000000000000 ) | sig<<11; + uiZ: + zSPtr->signExp = uiZ64; + zSPtr->signif = uiZ0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c new file mode 100644 index 0000000..319c3c6 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f64_to_f128( float64_t a ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + struct commonNaN commonNaN; + struct uint128 uiZ; + struct exp16_sig64 normExpSig; + struct uint128 sig128; + union ui128_f128 uZ; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp == 0x7FF ) { + if ( sig ) { + softfloat_f64UIToCommonNaN( uiA, &commonNaN ); + uiZ = softfloat_commonNaNToF128UI( &commonNaN ); + } else { + uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 ); + uiZ.v0 = 0; + } + goto uiZ; + } + if ( ! exp ) { + if ( ! sig ) { + uiZ.v64 = packToF128UI64( sign, 0, 0 ); + uiZ.v0 = 0; + goto uiZ; + } + normExpSig = softfloat_normSubnormalF64Sig( sig ); + exp = normExpSig.exp - 1; + sig = normExpSig.sig; + } + sig128 = softfloat_shortShiftLeft128( 0, sig, 60 ); + uiZ.v64 = packToF128UI64( sign, exp + 0x3C00, sig128.v64 ); + uiZ.v0 = sig128.v0; + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c new file mode 100644 index 0000000..f3d59d6 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void f64_to_f128M( float64_t a, float128_t *zPtr ) +{ + + *zPtr = f64_to_f128( a ); + +} + +#else + +void f64_to_f128M( float64_t a, float128_t *zPtr ) +{ + uint32_t *zWPtr; + union ui64_f64 uA; + uint64_t uiA; + bool sign; + int_fast16_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint32_t uiZ96; + struct exp16_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zWPtr = (uint32_t *) zPtr; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zWPtr[indexWord( 4, 0 )] = 0; + if ( exp == 0x7FF ) { + if ( sig ) { + softfloat_f64UIToCommonNaN( uiA, &commonNaN ); + softfloat_commonNaNToF128M( &commonNaN, zWPtr ); + return; + } + uiZ96 = packToF128UI96( sign, 0x7FFF, 0 ); + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! exp ) { + if ( ! sig ) { + uiZ96 = packToF128UI96( sign, 0, 0 ); + goto uiZ; + } + normExpSig = softfloat_normSubnormalF64Sig( sig ); + exp = normExpSig.exp - 1; + sig = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zWPtr[indexWord( 4, 1 )] = (uint32_t) sig<<28; + sig >>= 4; + zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp + 0x3C00, sig>>32 ); + zWPtr[indexWord( 4, 2 )] = sig; + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ: + zWPtr[indexWord( 4, 3 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c new file mode 100644 index 0000000..5697dc8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t f64_to_f32( float64_t a ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + struct commonNaN commonNaN; + uint_fast32_t uiZ, sig32; + union ui32_f32 uZ; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp == 0x7FF ) { + if ( sig ) { + softfloat_f64UIToCommonNaN( uiA, &commonNaN ); + uiZ = softfloat_commonNaNToF32UI( &commonNaN ); + } else { + uiZ = packToF32UI( sign, 0xFF, 0 ); + } + goto uiZ; + } + sig32 = softfloat_shortShiftRightJam64( sig, 22 ); + if ( ! (exp | sig32) ) { + uiZ = packToF32UI( sign, 0, 0 ); + goto uiZ; + } + return softfloat_roundPackToF32( sign, exp - 0x381, sig32 | 0x40000000 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c new file mode 100644 index 0000000..8375bc8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftCount; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( (exp == 0x7FF) && sig ) sign = 0; + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x42C - exp; + if ( 0 < shiftCount ) sig = softfloat_shiftRightJam64( sig, shiftCount ); + return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c new file mode 100644 index 0000000..464b289 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftCount; + bool sign; + int_fast32_t absZ; + + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + shiftCount = 0x433 - exp; + if ( 53 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sign = signF64UI( uiA ); + if ( shiftCount < 22 ) { + if ( + sign && (exp == 0x41E) && (sig < UINT64_C( 0x0000000000200000 )) + ) { + if ( exact && sig ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } else { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ((exp == 0x7FF) && sig) ) return 0x7FFFFFFF; + } + return -0x7FFFFFFF - 1; + } + sig |= UINT64_C( 0x0010000000000000 ); + absZ = sig>>shiftCount; + if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftCount; +#ifdef SOFTFLOAT_FAST_INT64 + struct uint64_extra sigExtra; +#else + uint32_t extSig[3]; +#endif + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x433 - exp; +#ifdef SOFTFLOAT_FAST_INT64 + if ( shiftCount <= 0 ) { + if ( shiftCount < -11 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + ! sign + || ((exp == 0x7FF) + && (sig != UINT64_C( 0x0010000000000000 ))) + ? INT64_C( 0x7FFFFFFFFFFFFFFF ) + : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sigExtra.v = sig<<-shiftCount; + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); + } + return + softfloat_roundPackToI64( + sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); +#else + extSig[indexWord( 3, 0 )] = 0; + if ( shiftCount <= 0 ) { + if ( shiftCount < -11 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return + ! sign + || ((exp == 0x7FF) + && (sig != UINT64_C( 0x0010000000000000 ))) + ? INT64_C( 0x7FFFFFFFFFFFFFFF ) + : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sig <<= -shiftCount; + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + } else { + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); + } + return softfloat_roundPackMToI64( sign, extSig, roundingMode, exact ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c new file mode 100644 index 0000000..8d9b9f1 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t f64_to_i64_r_minMag( float64_t a, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftCount; + int_fast64_t absZ; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + shiftCount = 0x433 - exp; + if ( shiftCount <= 0 ) { + if ( shiftCount < -10 ) { + if ( uiA != packToF64UI( 1, 0x43E, 0 ) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + if ( ! sign || ((exp == 0x7FF) && sig) ) { + return INT64_C( 0x7FFFFFFFFFFFFFFF ); + } + } + return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; + } + sig |= UINT64_C( 0x0010000000000000 ); + absZ = sig<<-shiftCount; + } else { + if ( 53 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + sig |= UINT64_C( 0x0010000000000000 ); + absZ = sig>>shiftCount; + if ( exact && (absZ< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t f64_to_ui32( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftCount; + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x42C - exp; + if ( 0 < shiftCount ) sig = softfloat_shiftRightJam64( sig, shiftCount ); + return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c new file mode 100644 index 0000000..298e453 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t f64_to_ui32_r_minMag( float64_t a, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftCount; + uint_fast32_t z; + + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + shiftCount = 0x433 - exp; + if ( 53 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF64UI( uiA ) || (shiftCount < 21) ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return 0xFFFFFFFF; + } + sig |= UINT64_C( 0x0010000000000000 ); + z = sig>>shiftCount; + if ( exact && ((uint_fast64_t) z< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t f64_to_ui64( float64_t a, uint_fast8_t roundingMode, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + bool sign; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftCount; +#ifdef SOFTFLOAT_FAST_INT64 + struct uint64_extra sigExtra; +#else + uint32_t extSig[3]; +#endif + + uA.f = a; + uiA = uA.ui; + sign = signF64UI( uiA ); + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); + shiftCount = 0x433 - exp; +#ifdef SOFTFLOAT_FAST_INT64 + if ( shiftCount <= 0 ) { + if ( shiftCount < -11 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + sigExtra.v = sig<<-shiftCount; + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); + } + return + softfloat_roundPackToUI64( + sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); +#else + extSig[indexWord( 3, 0 )] = 0; + if ( shiftCount <= 0 ) { + if ( shiftCount < -11 ) { + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + sig <<= -shiftCount; + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + } else { + extSig[indexWord( 3, 2 )] = sig>>32; + extSig[indexWord( 3, 1 )] = sig; + softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); + } + return softfloat_roundPackMToUI64( sign, extSig, roundingMode, exact ); +#endif + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c new file mode 100644 index 0000000..9a7d43c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t f64_to_ui64_r_minMag( float64_t a, bool exact ) +{ + union ui64_f64 uA; + uint_fast64_t uiA; + int_fast16_t exp; + uint_fast64_t sig; + int_fast16_t shiftCount; + uint_fast64_t z; + + uA.f = a; + uiA = uA.ui; + exp = expF64UI( uiA ); + sig = fracF64UI( uiA ); + shiftCount = 0x433 - exp; + if ( 53 <= shiftCount ) { + if ( exact && (exp | sig) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return 0; + } + if ( signF64UI( uiA ) ) goto invalid; + if ( shiftCount <= 0 ) { + if ( shiftCount < -11 ) goto invalid; + z = (sig | UINT64_C( 0x0010000000000000 ))<<-shiftCount; + } else { + sig |= UINT64_C( 0x0010000000000000 ); + z = sig>>shiftCount; + if ( exact && (uint64_t) (sig<<(-shiftCount & 63)) ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c new file mode 100644 index 0000000..dd7beab --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +extFloat80_t i32_to_extF80( int32_t a ) +{ + uint_fast16_t uiZ64; + uint_fast32_t absA; + bool sign; + int_fast8_t shiftCount; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + uiZ64 = 0; + absA = 0; + if ( a ) { + sign = (a < 0); + absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; + shiftCount = softfloat_countLeadingZeros32( absA ); + uiZ64 = packToExtF80UI64( sign, 0x401E - shiftCount ); + absA <<= shiftCount; + } + uZ.s.signExp = uiZ64; + uZ.s.signif = (uint_fast64_t) absA<<32; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c new file mode 100644 index 0000000..f81a639 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void i32_to_extF80M( int32_t a, extFloat80_t *zPtr ) +{ + + *zPtr = i32_to_extF80( a ); + +} + +#else + +void i32_to_extF80M( int32_t a, extFloat80_t *zPtr ) +{ + struct extFloat80M *zSPtr; + uint_fast16_t uiZ64; + uint64_t sigZ; + bool sign; + uint32_t absA; + int_fast8_t shiftCount; + + zSPtr = (struct extFloat80M *) zPtr; + uiZ64 = 0; + sigZ = 0; + if ( a ) { + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftCount = softfloat_countLeadingZeros32( absA ); + uiZ64 = packToExtF80UI64( sign, 0x401E - shiftCount ); + sigZ = (uint64_t) (absA<signExp = uiZ64; + zSPtr->signif = sigZ; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c new file mode 100644 index 0000000..56a6256 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float128_t i32_to_f128( int32_t a ) +{ + uint_fast64_t uiZ64; + bool sign; + uint_fast32_t absA; + int_fast8_t shiftCount; + union ui128_f128 uZ; + + uiZ64 = 0; + if ( a ) { + sign = (a < 0); + absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; + shiftCount = softfloat_countLeadingZeros32( absA ) + 17; + uiZ64 = + packToF128UI64( + sign, 0x402E - shiftCount, (uint_fast64_t) absA< +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void i32_to_f128M( int32_t a, float128_t *zPtr ) +{ + + *zPtr = i32_to_f128( a ); + +} + +#else + +void i32_to_f128M( int32_t a, float128_t *zPtr ) +{ + uint32_t *zWPtr; + uint32_t uiZ96, uiZ64; + bool sign; + uint32_t absA; + int_fast8_t shiftCount; + uint64_t normAbsA; + + zWPtr = (uint32_t *) zPtr; + uiZ96 = 0; + uiZ64 = 0; + if ( a ) { + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftCount = softfloat_countLeadingZeros32( absA ) + 17; + normAbsA = (uint64_t) absA<>32 ); + uiZ64 = normAbsA; + } + zWPtr[indexWord( 4, 3 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = uiZ64; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c new file mode 100644 index 0000000..25dd5ba --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t i32_to_f32( int32_t a ) +{ + bool sign; + union ui32_f32 uZ; + uint_fast32_t absA; + + sign = (a < 0); + if ( ! (a & 0x7FFFFFFF) ) { + uZ.ui = sign ? packToF32UI( 1, 0x9E, 0 ) : 0; + return uZ.f; + } + absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; + return softfloat_normRoundPackToF32( sign, 0x9C, absA ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c new file mode 100644 index 0000000..1976ef7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t i32_to_f64( int32_t a ) +{ + uint_fast64_t uiZ; + bool sign; + uint_fast32_t absA; + int_fast8_t shiftCount; + union ui64_f64 uZ; + + if ( ! a ) { + uiZ = 0; + } else { + sign = (a < 0); + absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; + shiftCount = softfloat_countLeadingZeros32( absA ) + 21; + uiZ = + packToF64UI( + sign, 0x432 - shiftCount, (uint_fast64_t) absA< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +extFloat80_t i64_to_extF80( int64_t a ) +{ + uint_fast16_t uiZ64; + uint_fast64_t absA; + bool sign; + int_fast8_t shiftCount; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + uiZ64 = 0; + absA = 0; + if ( a ) { + sign = (a < 0); + absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; + shiftCount = softfloat_countLeadingZeros64( absA ); + uiZ64 = packToExtF80UI64( sign, 0x403E - shiftCount ); + absA <<= shiftCount; + } + uZ.s.signExp = uiZ64; + uZ.s.signif = absA; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c new file mode 100644 index 0000000..1eb1ae4 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void i64_to_extF80M( int64_t a, extFloat80_t *zPtr ) +{ + + *zPtr = i64_to_extF80( a ); + +} + +#else + +void i64_to_extF80M( int64_t a, extFloat80_t *zPtr ) +{ + struct extFloat80M *zSPtr; + uint_fast16_t uiZ64; + uint64_t sigZ; + bool sign; + uint64_t absA; + int_fast8_t shiftCount; + + zSPtr = (struct extFloat80M *) zPtr; + uiZ64 = 0; + sigZ = 0; + if ( a ) { + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftCount = softfloat_countLeadingZeros64( absA ); + uiZ64 = packToExtF80UI64( sign, 0x403E - shiftCount ); + sigZ = absA<signExp = uiZ64; + zSPtr->signif = sigZ; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c new file mode 100644 index 0000000..058850c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float128_t i64_to_f128( int64_t a ) +{ + uint_fast64_t uiZ64, uiZ0; + bool sign; + uint_fast64_t absA; + int_fast8_t shiftCount; + struct uint128 zSig; + union ui128_f128 uZ; + + if ( ! a ) { + uiZ64 = 0; + uiZ0 = 0; + } else { + sign = (a < 0); + absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; + shiftCount = softfloat_countLeadingZeros64( absA ) + 49; + if ( 64 <= shiftCount ) { + zSig.v64 = absA<<(shiftCount - 64); + zSig.v0 = 0; + } else { + zSig = softfloat_shortShiftLeft128( 0, absA, shiftCount ); + } + uiZ64 = packToF128UI64( sign, 0x406E - shiftCount, zSig.v64 ); + uiZ0 = zSig.v0; + } + uZ.ui.v64 = uiZ64; + uZ.ui.v0 = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c new file mode 100644 index 0000000..15bba34 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void i64_to_f128M( int64_t a, float128_t *zPtr ) +{ + + *zPtr = i64_to_f128( a ); + +} + +#else + +void i64_to_f128M( int64_t a, float128_t *zPtr ) +{ + uint32_t *zWPtr; + uint32_t uiZ96, uiZ64; + bool sign; + uint64_t absA; + uint_fast8_t shiftCount; + uint32_t *ptr; + + zWPtr = (uint32_t *) zPtr; + uiZ96 = 0; + uiZ64 = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + if ( a ) { + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftCount = softfloat_countLeadingZeros64( absA ) + 17; + if ( shiftCount < 32 ) { + ptr = zWPtr + indexMultiwordHi( 4, 3 ); + ptr[indexWord( 3, 2 )] = 0; + ptr[indexWord( 3, 1 )] = absA>>32; + ptr[indexWord( 3, 0 )] = absA; + softfloat_shortShiftLeft96M( ptr, shiftCount, ptr ); + ptr[indexWordHi( 3 )] = + packToF128UI96( + sign, 0x404E - shiftCount, ptr[indexWordHi( 3 )] ); + return; + } + absA <<= shiftCount - 32; + uiZ96 = packToF128UI96( sign, 0x404E - shiftCount, absA>>32 ); + uiZ64 = absA; + } + zWPtr[indexWord( 4, 3 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = uiZ64; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c new file mode 100644 index 0000000..3bd36c1 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t i64_to_f32( int64_t a ) +{ + bool sign; + uint_fast64_t absA; + int_fast8_t shiftCount; + union ui32_f32 u; + uint_fast32_t sig; + + sign = (a < 0); + absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; + shiftCount = softfloat_countLeadingZeros64( absA ) - 40; + if ( 0 <= shiftCount ) { + u.ui = + a ? packToF32UI( + sign, 0x95 - shiftCount, (uint_fast32_t) absA< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t i64_to_f64( int64_t a ) +{ + bool sign; + union ui64_f64 uZ; + uint_fast64_t absA; + + sign = (a < 0); + if ( ! (a & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) { + uZ.ui = sign ? packToF64UI( 1, 0x43E, 0 ) : 0; + return uZ.f; + } + absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; + return softfloat_normRoundPackToF64( sign, 0x43C, absA ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h new file mode 100644 index 0000000..36dbd9f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h @@ -0,0 +1,260 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +#ifndef internals_h +#define internals_h 1 + +#include +#include +#include "primitives.h" +#include "softfloat_types.h" + +union ui32_f32 { uint32_t ui; float32_t f; }; +union ui64_f64 { uint64_t ui; float64_t f; }; + +#ifdef SOFTFLOAT_FAST_INT64 +union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; }; +union ui128_f128 { struct uint128 ui; float128_t f; }; +#endif + +enum { + softfloat_mulAdd_subC = 1, + softfloat_mulAdd_subProd = 2 +}; + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +uint_fast32_t + softfloat_roundPackToUI32( bool, uint_fast64_t, uint_fast8_t, bool ); + +#ifdef SOFTFLOAT_FAST_INT64 +uint_fast64_t + softfloat_roundPackToUI64( + bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); +#else +uint_fast64_t + softfloat_roundPackMToUI64( bool, uint32_t *, uint_fast8_t, bool ); +#endif + +int_fast32_t + softfloat_roundPackToI32( bool, uint_fast64_t, uint_fast8_t, bool ); + +#ifdef SOFTFLOAT_FAST_INT64 +int_fast64_t + softfloat_roundPackToI64( + bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); +#else +int_fast64_t softfloat_roundPackMToI64( bool, uint32_t *, uint_fast8_t, bool ); +#endif + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF32UI( a ) ((bool) ((uint32_t) (a)>>31)) +#define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF) +#define fracF32UI( a ) ((a) & 0x007FFFFF) +#define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) + +#define isNaNF32UI( a ) ((((a) & 0x7F800000) == 0x7F800000) && ((a) & 0x007FFFFF)) + +struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; +struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t ); + +float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); +float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); + +float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t, bool ); +float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t, bool ); +float32_t + softfloat_mulAddF32( + uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF64UI( a ) ((bool) ((uint64_t) (a)>>63)) +#define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF) +#define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )) +#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) + +#define isNaNF64UI( a ) ((((a) & UINT64_C( 0x7FF0000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))) + +struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }; +struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t ); + +float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); +float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); + +float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); +float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); +float64_t + softfloat_mulAddF64( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15)) +#define expExtF80UI64( a64 ) ((a64) & 0x7FFF) +#define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp)) + +#define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) + +#ifdef SOFTFLOAT_FAST_INT64 + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + +struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; +struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t ); + +extFloat80_t + softfloat_roundPackToExtF80( + bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); +extFloat80_t + softfloat_normRoundPackToExtF80( + bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); + +extFloat80_t + softfloat_addMagsExtF80( + uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); +extFloat80_t + softfloat_subMagsExtF80( + uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63)) +#define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF) +#define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )) +#define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64)) + +#define isNaNF128UI( a64, a0 ) ((((a64) & UINT64_C( 0x7FFF000000000000 )) == UINT64_C( 0x7FFF000000000000 )) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )))) + +struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; }; +struct exp32_sig128 + softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t ); + +float128_t + softfloat_roundPackToF128( + bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t ); +float128_t + softfloat_normRoundPackToF128( + bool, int_fast32_t, uint_fast64_t, uint_fast64_t ); + +float128_t + softfloat_addMagsF128( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); +float128_t + softfloat_subMagsF128( + uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); +float128_t + softfloat_mulAddF128( + uint_fast64_t, + uint_fast64_t, + uint_fast64_t, + uint_fast64_t, + uint_fast64_t, + uint_fast64_t, + uint_fast8_t + ); + +#else + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + +bool + softfloat_tryPropagateNaNExtF80M( + const struct extFloat80M *, + const struct extFloat80M *, + struct extFloat80M * + ); +void softfloat_invalidExtF80M( struct extFloat80M * ); + +int softfloat_normExtF80SigM( uint64_t * ); + +void + softfloat_roundPackMToExtF80M( + bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); +void + softfloat_normRoundPackMToExtF80M( + bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); + +void + softfloat_addExtF80M( + const struct extFloat80M *, + const struct extFloat80M *, + struct extFloat80M *, + bool + ); + +int + softfloat_compareNonnormExtF80M( + const struct extFloat80M *, const struct extFloat80M * ); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31)) +#define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF) +#define fracF128UI96( a96 ) ((a96) & 0x0000FFFF) +#define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96)) + +bool softfloat_isNaNF128M( const uint32_t * ); + +bool + softfloat_tryPropagateNaNF128M( + const uint32_t *, const uint32_t *, uint32_t * ); +void softfloat_invalidF128M( uint32_t * ); + +int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * ); + +void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); +void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); + +void + softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool ); +void + softfloat_mulAddF128M( + const uint32_t *, + const uint32_t *, + const uint32_t *, + uint32_t *, + uint_fast8_t + ); + +#endif + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.h new file mode 100644 index 0000000..50570c0 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +#ifndef primitiveTypes_h +#define primitiveTypes_h 1 + +#include + +#ifdef SOFTFLOAT_FAST_INT64 + +#ifdef LITTLEENDIAN +struct uint128 { uint64_t v0, v64; }; +struct uint64_extra { uint64_t extra, v; }; +struct uint128_extra { uint64_t extra; struct uint128 v; }; +#else +struct uint128 { uint64_t v64, v0; }; +struct uint64_extra { uint64_t v, extra; }; +struct uint128_extra { struct uint128 v; uint64_t extra; }; +#endif + +#endif + +/*---------------------------------------------------------------------------- +| These macros are used to isolate the differences in word order between big- +| endian and little-endian platforms. +*----------------------------------------------------------------------------*/ +#ifdef LITTLEENDIAN +#define wordIncr 1 +#define indexWord( total, n ) (n) +#define indexWordHi( total ) ((total) - 1) +#define indexWordLo( total ) 0 +#define indexMultiword( total, m, n ) (n) +#define indexMultiwordHi( total, n ) ((total) - (n)) +#define indexMultiwordLo( total, n ) 0 +#define indexMultiwordHiBut( total, n ) (n) +#define indexMultiwordLoBut( total, n ) 0 +#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 } +#else +#define wordIncr -1 +#define indexWord( total, n ) ((total) - 1 - (n)) +#define indexWordHi( total ) 0 +#define indexWordLo( total ) ((total) - 1) +#define indexMultiword( total, m, n ) ((total) - 1 - (m)) +#define indexMultiwordHi( total, n ) 0 +#define indexMultiwordLo( total, n ) ((total) - (n)) +#define indexMultiwordHiBut( total, n ) 0 +#define indexMultiwordLoBut( total, n ) (n) +#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 } +#endif + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitives.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitives.h new file mode 100644 index 0000000..486c63c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/primitives.h @@ -0,0 +1,1136 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +#ifndef primitives_h +#define primitives_h 1 + +#include +#include +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightJam64 +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count', which must be in +| the range 1 to 63. If any nonzero bits are shifted off, they are "jammed" +| into the least-significant bit of the shifted value by setting the least- +| significant bit to 1. This shifted-and-jammed value is returned. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE + uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t count ) + { return a>>count | ((a & (((uint_fast64_t) 1<>count | ((uint32_t) (a<<(-count & 31)) != 0) + : (a != 0); +} +#else +uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t count ); +#endif +#endif + +#ifndef softfloat_shiftRightJam64 +/*---------------------------------------------------------------------------- +| Shifts `a' right by the number of bits given in `count', which must not +| be zero. If any nonzero bits are shifted off, they are "jammed" into the +| least-significant bit of the shifted value by setting the least-significant +| bit to 1. This shifted-and-jammed value is returned. +| The value of `count' can be arbitrarily large. In particular, if `count' +| is greater than 64, the result will be either 0 or 1, depending on whether +| `a' is zero or nonzero. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t count ) +{ + return + (count < 63) ? a>>count | ((uint64_t) (a<<(-count & 63)) != 0) + : (a != 0); +} +#else +uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t count ); +#endif +#endif + +/*---------------------------------------------------------------------------- +| A constant table that translates an 8-bit unsigned integer (the array index) +| into the number of leading 0 bits before the most-significant 1 of that +| integer. For integer zero (index 0), the corresponding table element is 8. +*----------------------------------------------------------------------------*/ +extern const uint_least8_t softfloat_countLeadingZeros8[256]; + +#ifndef softfloat_countLeadingZeros32 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 32 is returned. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) +{ + uint_fast8_t count = 0; + if ( a < 0x10000 ) { + count = 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; +} +#else +uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ); +#endif +#endif + +#ifndef softfloat_countLeadingZeros64 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| `a'. If `a' is zero, 64 is returned. +*----------------------------------------------------------------------------*/ +uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ); +#endif + +#ifndef softfloat_approxRecip32_1 +/*---------------------------------------------------------------------------- +| Returns an approximation to the reciprocal of the number represented by `a', +| where `a' is interpreted as an unsigned fixed-point number with one integer +| bit and 31 fraction bits. The `a' input must be "normalized", meaning that +| its most-significant bit (bit 31) must be 1. Thus, if A is the value of +| the fixed-point interpretation of `a', then 1 <= A < 2. The returned value +| is interpreted as a pure unsigned fraction, having no integer bits and 32 +| fraction bits. The approximation returned is never greater than the true +| reciprocal 1/A, and it differs from the true reciprocal by at most 2.006 ulp +| (units in the last place). +*----------------------------------------------------------------------------*/ +#ifdef SOFTFLOAT_FAST_DIV64TO32 +#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a))) +#else +uint32_t softfloat_approxRecip32_1( uint32_t a ); +#endif +#endif + +#ifndef softfloat_approxRecipSqrt32_1 +/*---------------------------------------------------------------------------- +| Returns an approximation to the reciprocal of the square root of the number +| represented by `a', where `a' is interpreted as an unsigned fixed-point +| number either with one integer bit and 31 fraction bits or with two integer +| bits and 30 fraction bits. The format of `a' is determined by `oddExpA', +| which must be either 0 or 1. If `oddExpA' is 1, `a' is interpreted as +| having one integer bit, and if `oddExpA' is 0, `a' is interpreted as having +| two integer bits. The `a' input must be "normalized", meaning that its +| most-significant bit (bit 31) must be 1. Thus, if A is the value of the +| fixed-point interpretation of `a', it follows that 1 <= A < 2 when `oddExpA' +| is 1, and 2 <= A < 4 when `oddExpA' is 0. +| The returned value is interpreted as a pure unsigned fraction, having +| no integer bits and 32 fraction bits. The approximation returned is never +| greater than the true reciprocal 1/sqrt(A), and it differs from the true +| reciprocal by at most 2.06 ulp (units in the last place). The approximation +| returned is also always within the range 0.5 to 1; thus, the most- +| significant bit of the result is always set. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ); +#endif + +#ifdef SOFTFLOAT_FAST_INT64 + +/*---------------------------------------------------------------------------- +| The following functions are needed only when `SOFTFLOAT_FAST_INT64' is +| defined. +*----------------------------------------------------------------------------*/ + +#ifndef softfloat_eq128 +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating `a64' +| and `a0' is equal to the 128-bit unsigned integer formed by concatenating +| `b64' and `b0'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) +INLINE + bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) + { return (a64 == b64) && (a0 == b0); } +#else +bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_le128 +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating `a64' +| and `a0' is less than or equal to the 128-bit unsigned integer formed by +| concatenating `b64' and `b0'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE + bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) + { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } +#else +bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_lt128 +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating `a64' +| and `a0' is less than the 128-bit unsigned integer formed by concatenating +| `b64' and `b0'. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE + bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) + { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } +#else +bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_shortShiftLeft128 +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating `a64' and `a0' left by the +| number of bits given in `count', which must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE + struct uint128 + softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t count ) +{ + struct uint128 z; + z.v64 = a64<>(-count & 63); + z.v0 = a0<>count; + z.v0 = a64<<(-count & 63) | a0>>count; + return z; +} +#else +struct uint128 + softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t count ); +#endif +#endif + +#ifndef softfloat_shortShiftRightJam64Extra +/*---------------------------------------------------------------------------- +| This function is the same as `softfloat_shiftRightJam64Extra' (below), +| except that `count' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE + struct uint64_extra + softfloat_shortShiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast8_t count ) +{ + struct uint64_extra z; + z.v = a>>count; + z.extra = a<<(-count & 63) | (extra != 0); + return z; +} +#else +struct uint64_extra + softfloat_shortShiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast8_t count ); +#endif +#endif + +#ifndef softfloat_shortShiftRightJam128 +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating `a64' and `a0' right by the +| number of bits given in `count', which must be in the range 1 to 63. If any +| nonzero bits are shifted off, they are "jammed" into the least-significant +| bit of the shifted value by setting the least-significant bit to 1. This +| shifted-and-jammed value is returned. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE + struct uint128 + softfloat_shortShiftRightJam128( + uint64_t a64, uint64_t a0, uint_fast8_t count ) +{ + uint_fast8_t negCount = -count; + struct uint128 z; + z.v64 = a64>>count; + z.v0 = + a64<<(negCount & 63) | a0>>count + | ((uint64_t) (a0<<(negCount & 63)) != 0); + return z; +} +#else +struct uint128 + softfloat_shortShiftRightJam128( + uint64_t a64, uint64_t a0, uint_fast8_t count ); +#endif +#endif + +#ifndef softfloat_shortShiftRightJam128Extra +/*---------------------------------------------------------------------------- +| This function is the same as `softfloat_shiftRightJam128Extra' (below), +| except that `count' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE + struct uint128_extra + softfloat_shortShiftRightJam128Extra( + uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t count ) +{ + uint_fast8_t negCount = -count; + struct uint128_extra z; + z.v.v64 = a64>>count; + z.v.v0 = a64<<(negCount & 63) | a0>>count; + z.extra = a0<<(negCount & 63) | (extra != 0); + return z; +} +#else +struct uint128_extra + softfloat_shortShiftRightJam128Extra( + uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t count ); +#endif +#endif + +#ifndef softfloat_shiftRightJam64Extra +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating `a' and `extra' right by 64 +| _plus_ the number of bits given in `count', which must not be zero. This +| shifted value is at most 64 nonzero bits and is returned in the `v' field +| of the `struct uint64_extra' result. The 64-bit `extra' field of the result +| contains a value formed as follows from the bits that were shifted off: The +| _last_ bit shifted off is the most-significant bit of the `extra' field, and +| the other 63 bits of the `extra' field are all zero if and only if _all_but_ +| _the_last_ bits shifted off were all zero. +| (This function makes more sense if `a' and `extra' are considered to form +| an unsigned fixed-point number with binary point between `a' and `extra'. +| This fixed-point value is shifted right by the number of bits given in +| `count', and the integer part of this shifted value is returned in the `v' +| field of the result. The fractional part of the shifted value is modified +| as described above and returned in the `extra' field of the result.) +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) +INLINE + struct uint64_extra + softfloat_shiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast32_t count ) +{ + struct uint64_extra z; + if ( count < 64 ) { + z.v = a>>count; + z.extra = a<<(-count & 63); + } else { + z.v = 0; + z.extra = (count == 64) ? a : (a != 0); + } + z.extra |= (extra != 0); + return z; +} +#else +struct uint64_extra + softfloat_shiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast32_t count ); +#endif +#endif + +#ifndef softfloat_shiftRightJam128 +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating `a64' and `a0' right by the +| number of bits given in `count', which must not be zero. If any nonzero +| bits are shifted off, they are "jammed" into the least-significant bit of +| the shifted value by setting the least-significant bit to 1. This shifted- +| and-jammed value is returned. +| The value of `count' can be arbitrarily large. In particular, if `count' +| is greater than 128, the result will be either 0 or 1, depending on whether +| the original 128 bits are all zeros. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t count ); +#endif + +#ifndef softfloat_shiftRightJam128Extra +/*---------------------------------------------------------------------------- +| Shifts the 192 bits formed by concatenating `a64', `a0', and `extra' right +| by 64 _plus_ the number of bits given in `count', which must not be zero. +| This shifted value is at most 128 nonzero bits and is returned in the `v' +| field of the `struct uint128_extra' result. The 64-bit `extra' field of the +| result contains a value formed as follows from the bits that were shifted +| off: The _last_ bit shifted off is the most-significant bit of the `extra' +| field, and the other 63 bits of the `extra' field are all zero if and only +| if _all_but_the_last_ bits shifted off were all zero. +| (This function makes more sense if `a64', `a0', and `extra' are considered +| to form an unsigned fixed-point number with binary point between `a0' and +| `extra'. This fixed-point value is shifted right by the number of bits +| given in `count', and the integer part of this shifted value is returned +| in the `v' field of the result. The fractional part of the shifted value +| is modified as described above and returned in the `extra' field of the +| result.) +*----------------------------------------------------------------------------*/ +struct uint128_extra + softfloat_shiftRightJam128Extra( + uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t count ); +#endif + +#ifndef softfloat_shiftRightJam256M +/*---------------------------------------------------------------------------- +| Shifts the 256-bit unsigned integer pointed to by `aPtr' right by the number +| of bits given in `count', which must not be zero. If any nonzero bits are +| shifted off, they are "jammed" into the least-significant bit of the shifted +| value by setting the least-significant bit to 1. This shifted-and-jammed +| value is stored at the location pointed to by `zPtr'. Each of `aPtr' and +| `zPtr' points to an array of four 64-bit elements that concatenate in the +| platform's normal endian order to form a 256-bit integer. +| The value of `count' can be arbitrarily large. In particular, if `count' +| is greater than 256, the stored result will be either 0 or 1, depending on +| whether the original 256 bits are all zeros. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftRightJam256M( + const uint64_t *aPtr, uint_fast32_t count, uint64_t *zPtr ); +#endif + +#ifndef softfloat_add128 +/*---------------------------------------------------------------------------- +| Returns the sum of the 128-bit integer formed by concatenating `a64' and +| `a0' and the 128-bit integer formed by concatenating `b64' and `b0'. The +| addition is modulo 2^128, so any carry out is lost. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE + struct uint128 + softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + struct uint128 z; + z.v0 = a0 + b0; + z.v64 = a64 + b64 + (z.v0 < a0); + return z; +} +#else +struct uint128 + softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_add256M +/*---------------------------------------------------------------------------- +| Adds the two 256-bit integers pointed to by `aPtr' and `bPtr'. The addition +| is modulo 2^256, so any carry out is lost. The sum is stored at the +| location pointed to by `zPtr'. Each of `aPtr', `bPtr', and `zPtr' points to +| an array of four 64-bit elements that concatenate in the platform's normal +| endian order to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_add256M( + const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); +#endif + +#ifndef softfloat_sub128 +/*---------------------------------------------------------------------------- +| Returns the difference of the 128-bit integer formed by concatenating `a64' +| and `a0' and the 128-bit integer formed by concatenating `b64' and `b0'. +| The subtraction is modulo 2^128, so any borrow out (carry out) is lost. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE + struct uint128 + softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + struct uint128 z; + z.v0 = a0 - b0; + z.v64 = a64 - b64; + z.v64 -= (a0 < b0); + return z; +} +#else +struct uint128 + softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); +#endif +#endif + +#ifndef softfloat_sub256M +/*---------------------------------------------------------------------------- +| Subtracts the 256-bit integer pointed to by `bPtr' from the 256-bit integer +| pointed to by `aPtr'. The addition is modulo 2^256, so any borrow out +| (carry out) is lost. The difference is stored at the location pointed to +| by `zPtr'. Each of `aPtr', `bPtr', and `zPtr' points to an array of four +| 64-bit elements that concatenate in the platform's normal endian order to +| form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_sub256M( + const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); +#endif + +#ifndef softfloat_mul64ByShifted32To128 +/*---------------------------------------------------------------------------- +| Returns the 128-bit product of `a', `b', and 2^32. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) +INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) +{ + uint_fast64_t mid; + struct uint128 z; + mid = (uint_fast64_t) (uint32_t) a * b; + z.v0 = mid<<32; + z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32); + return z; +} +#else +struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ); +#endif +#endif + +#ifndef softfloat_mul64To128 +/*---------------------------------------------------------------------------- +| Returns the 128-bit product of `a' and `b'. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ); +#endif + +#ifndef softfloat_mul128By32 +/*---------------------------------------------------------------------------- +| Returns the product of the 128-bit integer formed by concatenating `a64' and +| `a0', multiplied by `b'. The multiplication is modulo 2^128; any overflow +| bits are discarded. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) +INLINE + struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) +{ + struct uint128 z; + uint_fast64_t mid; + uint_fast32_t carry; + z.v0 = a0 * b; + mid = (uint_fast64_t) (uint32_t) (a0>>32) * b; + carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid); + z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32); + return z; +} +#else +struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ); +#endif +#endif + +#ifndef softfloat_mul128To256M +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit unsigned integer formed by concatenating `a64' and +| `a0' by the 128-bit unsigned integer formed by concatenating `b64' and +| `b0'. The 256-bit product is stored at the location pointed to by `zPtr'. +| Argument `zPtr' points to an array of four 64-bit elements that concatenate +| in the platform's normal endian order to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_mul128To256M( + uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ); +#endif + +#else + +/*---------------------------------------------------------------------------- +| The following functions are needed only when `SOFTFLOAT_FAST_INT64' is not +| defined. +*----------------------------------------------------------------------------*/ + +#ifndef softfloat_compare96M +/*---------------------------------------------------------------------------- +| Compares the two 96-bit unsigned integers pointed to by `aPtr' and `bPtr'. +| Returns -1 if the first integer (A) is less than the second (B); returns 0 +| if the two integers are equal; and returns +1 if the first integer (A) +| is greater than the second (B). (The result is thus the signum of A - B.) +| Each of `aPtr' and `bPtr' points to an array of three 32-bit elements that +| concatenate in the platform's normal endian order to form a 96-bit integer. +*----------------------------------------------------------------------------*/ +int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ); +#endif + +#ifndef softfloat_compare128M +/*---------------------------------------------------------------------------- +| Compares the two 128-bit unsigned integers pointed to by `aPtr' and `bPtr'. +| Returns -1 if the first integer (A) is less than the second (B); returns 0 +| if the two integers are equal; and returns +1 if the first integer (A) +| is greater than the second (B). (The result is thus the signum of A - B.) +| Each of `aPtr' and `bPtr' points to an array of four 32-bit elements that +| concatenate in the platform's normal endian order to form a 128-bit integer. +*----------------------------------------------------------------------------*/ +int_fast8_t + softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr ); +#endif + +#ifndef softfloat_shortShiftLeft64To96M +/*---------------------------------------------------------------------------- +| Extends `a' to 96 bits and shifts the value left by the number of bits given +| in `count', which must be in the range 1 to 31. The result is stored at the +| location pointed to by `zPtr'. Argument `zPtr' points to an array of three +| 32-bit elements that concatenate in the platform's normal endian order to +| form a 96-bit integer. +*----------------------------------------------------------------------------*/ +#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) +INLINE + void + softfloat_shortShiftLeft64To96M( + uint64_t a, uint_fast8_t count, uint32_t *zPtr ) +{ + zPtr[indexWord( 3, 0 )] = (uint32_t) a<>= 32 - count; + zPtr[indexWord( 3, 2 )] = a>>32; + zPtr[indexWord( 3, 1 )] = a; +} +#else +void + softfloat_shortShiftLeft64To96M( + uint64_t a, uint_fast8_t count, uint32_t *zPtr ); +#endif +#endif + +#ifndef softfloat_shortShiftLeftM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by `aPtr' left by the number +| of bits given in `count', where N = `size_words' * 32. The value of `count' +| must be in the range 1 to 31. Any nonzero bits shifted off are lost. The +| shifted N-bit result is stored at the location pointed to by `zPtr'. Each +| of `aPtr' and `zPtr' points to a `size_words'-long array of 32-bit elements +| that concatenate in the platform's normal endian order to form an N-bit +| integer. +*----------------------------------------------------------------------------*/ +void + softfloat_shortShiftLeftM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t count, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shortShiftLeft96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shortShiftLeftM' with +| `size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftLeft96M( aPtr, count, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shortShiftLeft128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shortShiftLeftM' with +| `size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftLeft128M( aPtr, count, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shortShiftLeft160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shortShiftLeftM' with +| `size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftLeft160M( aPtr, count, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shiftLeftM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by `aPtr' left by the number +| of bits given in `count', where N = `size_words' * 32. The value of `count' +| must not be zero. Any nonzero bits shifted off are lost. The shifted +| N-bit result is stored at the location pointed to by `zPtr'. Each of `aPtr' +| and `zPtr' points to a `size_words'-long array of 32-bit elements that +| concatenate in the platform's normal endian order to form an N-bit integer. +| The value of `count' can be arbitrarily large. In particular, if `count' +| is greater than N, the stored result will be 0. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftLeftM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t count, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shiftLeft96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shiftLeftM' with +| `size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftLeft96M( aPtr, count, zPtr ) softfloat_shiftLeftM( 3, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shiftLeft128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shiftLeftM' with +| `size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftLeft128M( aPtr, count, zPtr ) softfloat_shiftLeftM( 4, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shiftLeft160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shiftLeftM' with +| `size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftLeft160M( aPtr, count, zPtr ) softfloat_shiftLeftM( 5, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shortShiftRightM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by `aPtr' right by the number +| of bits given in `count', where N = `size_words' * 32. The value of `count' +| must be in the range 1 to 31. Any nonzero bits shifted off are lost. The +| shifted N-bit result is stored at the location pointed to by `zPtr'. Each +| of `aPtr' and `zPtr' points to a `size_words'-long array of 32-bit elements +| that concatenate in the platform's normal endian order to form an N-bit +| integer. +*----------------------------------------------------------------------------*/ +void + softfloat_shortShiftRightM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t count, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shortShiftRight128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shortShiftRightM' with +| `size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftRight128M( aPtr, count, zPtr ) softfloat_shortShiftRightM( 4, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shortShiftRight160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shortShiftRightM' with +| `size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftRight160M( aPtr, count, zPtr ) softfloat_shortShiftRightM( 5, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shortShiftRightJamM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by `aPtr' right by the number +| of bits given in `count', where N = `size_words' * 32. The value of `count' +| must be in the range 1 to 31. If any nonzero bits are shifted off, they are +| "jammed" into the least-significant bit of the shifted value by setting the +| least-significant bit to 1. This shifted-and-jammed N-bit result is stored +| at the location pointed to by `zPtr'. Each of `aPtr' and `zPtr' points +| to a `size_words'-long array of 32-bit elements that concatenate in the +| platform's normal endian order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_shortShiftRightJamM( + uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * ); +#endif + +#ifndef softfloat_shortShiftRightJam160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shortShiftRightJamM' with +| `size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shortShiftRightJam160M( aPtr, count, zPtr ) softfloat_shortShiftRightJamM( 5, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shiftRightM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by `aPtr' right by the number +| of bits given in `count', where N = `size_words' * 32. The value of `count' +| must not be zero. Any nonzero bits shifted off are lost. The shifted +| N-bit result is stored at the location pointed to by `zPtr'. Each of `aPtr' +| and `zPtr' points to a `size_words'-long array of 32-bit elements that +| concatenate in the platform's normal endian order to form an N-bit integer. +| The value of `count' can be arbitrarily large. In particular, if `count' +| is greater than N, the stored result will be 0. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftRightM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t count, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shiftRight96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shiftRightM' with +| `size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftRight96M( aPtr, count, zPtr ) softfloat_shiftRightM( 3, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shiftRightJamM +/*---------------------------------------------------------------------------- +| Shifts the N-bit unsigned integer pointed to by `aPtr' right by the number +| of bits given in `count', where N = `size_words' * 32. The value of `count' +| must not be zero. If any nonzero bits are shifted off, they are "jammed" +| into the least-significant bit of the shifted value by setting the least- +| significant bit to 1. This shifted-and-jammed N-bit result is stored +| at the location pointed to by `zPtr'. Each of `aPtr' and `zPtr' points +| to a `size_words'-long array of 32-bit elements that concatenate in the +| platform's normal endian order to form an N-bit integer. +| The value of `count' can be arbitrarily large. In particular, if `count' +| is greater than N, the stored result will be either 0 or 1, depending on +| whether the original N bits are all zeros. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftRightJamM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t count, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_shiftRightJam96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shiftRightJamM' with +| `size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftRightJam96M( aPtr, count, zPtr ) softfloat_shiftRightJamM( 3, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shiftRightJam128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shiftRightJamM' with +| `size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftRightJam128M( aPtr, count, zPtr ) softfloat_shiftRightJamM( 4, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_shiftRightJam160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_shiftRightJamM' with +| `size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_shiftRightJam160M( aPtr, count, zPtr ) softfloat_shiftRightJamM( 5, aPtr, count, zPtr ) +#endif + +#ifndef softfloat_addM +/*---------------------------------------------------------------------------- +| Adds the two N-bit integers pointed to by `aPtr' and `bPtr', where N = +| `size_words' * 32. The addition is modulo 2^N, so any carry out is lost. +| The N-bit sum is stored at the location pointed to by `zPtr'. Each of +| `aPtr', `bPtr', and `zPtr' points to a `size_words'-long array of 32-bit +| elements that concatenate in the platform's normal endian order to form an +| N-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_addM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_add96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_addM' with `size_words' +| = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_add96M( aPtr, bPtr, zPtr ) softfloat_addM( 3, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_add128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_addM' with `size_words' +| = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_add128M( aPtr, bPtr, zPtr ) softfloat_addM( 4, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_add160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_addM' with `size_words' +| = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_add160M( aPtr, bPtr, zPtr ) softfloat_addM( 5, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_addCarryM +/*---------------------------------------------------------------------------- +| Adds the two N-bit unsigned integers pointed to by `aPtr' and `bPtr', where +| N = `size_words' * 32, plus `carry', which must be either 0 or 1. The N-bit +| sum (modulo 2^N) is stored at the location pointed to by `zPtr', and any +| carry out is returned as the result. Each of `aPtr', `bPtr', and `zPtr' +| points to a `size_words'-long array of 32-bit elements that concatenate in +| the platform's normal endian order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +uint_fast8_t + softfloat_addCarryM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint_fast8_t carry, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_addComplCarryM +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_addCarryM', except that +| the value of the unsigned integer pointed to by `bPtr' is bit-wise completed +| before the addition. +*----------------------------------------------------------------------------*/ +uint_fast8_t + softfloat_addComplCarryM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint_fast8_t carry, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_addComplCarry96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_addComplCarryM' with +| `size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_addComplCarry96M( aPtr, bPtr, carry, zPtr ) softfloat_addComplCarryM( 3, aPtr, bPtr, carry, zPtr ) +#endif + +#ifndef softfloat_negXM +/*---------------------------------------------------------------------------- +| Replaces the N-bit unsigned integer pointed to by `zPtr' by the +| 2s-complement of itself, where N = `size_words' * 32. Argument `zPtr' +| points to a `size_words'-long array of 32-bit elements that concatenate in +| the platform's normal endian order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); +#endif + +#ifndef softfloat_negX96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_negXM' with `size_words' +| = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_negX96M( zPtr ) softfloat_negXM( 3, zPtr ) +#endif + +#ifndef softfloat_negX128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_negXM' with `size_words' +| = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_negX128M( zPtr ) softfloat_negXM( 4, zPtr ) +#endif + +#ifndef softfloat_negX160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_negXM' with `size_words' +| = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_negX160M( zPtr ) softfloat_negXM( 5, zPtr ) +#endif + +#ifndef softfloat_negX256M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_negXM' with `size_words' +| = 8 (N = 256). +*----------------------------------------------------------------------------*/ +#define softfloat_negX256M( zPtr ) softfloat_negXM( 8, zPtr ) +#endif + +#ifndef softfloat_sub1XM +/*---------------------------------------------------------------------------- +| Subtracts 1 from the N-bit integer pointed to by `zPtr', where N = +| `size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry +| out) is lost. Argument `zPtr' points to a `size_words'-long array of 32-bit +| elements that concatenate in the platform's normal endian order to form an +| N-bit integer. +*----------------------------------------------------------------------------*/ +void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); +#endif + +#ifndef softfloat_sub1X96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_sub1XM' with `size_words' +| = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_sub1X96M( zPtr ) softfloat_sub1XM( 3, zPtr ) +#endif + +#ifndef softfloat_sub1X160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_sub1XM' with `size_words' +| = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_sub1X160M( zPtr ) softfloat_sub1XM( 5, zPtr ) +#endif + +#ifndef softfloat_subM +/*---------------------------------------------------------------------------- +| Subtracts the two N-bit integers pointed to by `aPtr' and `bPtr', where N = +| `size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry +| out) is lost. The N-bit difference is stored at the location pointed to by +| `zPtr'. Each of `aPtr', `bPtr', and `zPtr' points to a `size_words'-long +| array of 32-bit elements that concatenate in the platform's normal endian +| order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_subM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_sub96M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_subM' with `size_words' +| = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_sub96M( aPtr, bPtr, zPtr ) softfloat_subM( 3, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_sub128M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_subM' with `size_words' +| = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_sub128M( aPtr, bPtr, zPtr ) softfloat_subM( 4, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_sub160M +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_subM' with `size_words' +| = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_sub160M( aPtr, bPtr, zPtr ) softfloat_subM( 5, aPtr, bPtr, zPtr ) +#endif + +#ifndef softfloat_mul64To128M +/*---------------------------------------------------------------------------- +| Multiplies `a' and `b' and stores the 128-bit product at the location +| pointed to by `zPtr'. Argument `zPtr' points to an array of four 32-bit +| elements that concatenate in the platform's normal endian order to form a +| 128-bit integer. +*----------------------------------------------------------------------------*/ +void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ); +#endif + +#ifndef softfloat_mul128MTo256M +/*---------------------------------------------------------------------------- +| Multiplies the two 128-bit unsigned integers pointed to by `aPtr' and +| `bPtr', and stores the 256-bit product at the location pointed to by `zPtr'. +| Each of `aPtr' and `bPtr' points to an array of four 32-bit elements that +| concatenate in the platform's normal endian order to form a 128-bit integer. +| Argument `zPtr' points to an array of eight 32-bit elements that concatenate +| to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_mul128MTo256M( + const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ); +#endif + +#ifndef softfloat_remStepMBy32 +/*---------------------------------------------------------------------------- +| Performs a "remainder reduction step" as follows: Arguments `remPtr' and +| `bPtr' both point to N-bit unsigned integers, where N = `size_words' * 32. +| Defining R and B as the values of those integers, the expression (R<<`count') +| - B * q is computed modulo 2^N, and the N-bit result is stored at the +| location pointed to by `zPtr'. Each of `remPtr', `bPtr', and `zPtr' points +| to a `size_words'-long array of 32-bit elements that concatenate in the +| platform's normal endian order to form an N-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_remStepMBy32( + uint_fast8_t size_words, + const uint32_t *remPtr, + uint_fast8_t count, + const uint32_t *bPtr, + uint32_t q, + uint32_t *zPtr + ); +#endif + +#ifndef softfloat_remStep96MBy32 +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_remStepMBy32' with +| `size_words' = 3 (N = 96). +*----------------------------------------------------------------------------*/ +#define softfloat_remStep96MBy32( remPtr, count, bPtr, q, zPtr ) softfloat_remStepMBy32( 3, remPtr, count, bPtr, q, zPtr ) +#endif + +#ifndef softfloat_remStep128MBy32 +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_remStepMBy32' with +| `size_words' = 4 (N = 128). +*----------------------------------------------------------------------------*/ +#define softfloat_remStep128MBy32( remPtr, count, bPtr, q, zPtr ) softfloat_remStepMBy32( 4, remPtr, count, bPtr, q, zPtr ) +#endif + +#ifndef softfloat_remStep160MBy32 +/*---------------------------------------------------------------------------- +| This function or macro is the same as `softfloat_remStepMBy32' with +| `size_words' = 5 (N = 160). +*----------------------------------------------------------------------------*/ +#define softfloat_remStep160MBy32( remPtr, count, bPtr, q, zPtr ) softfloat_remStepMBy32( 5, remPtr, count, bPtr, q, zPtr ) +#endif + +#endif + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat.h new file mode 100644 index 0000000..2f3851f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat.h @@ -0,0 +1,323 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + + +/*============================================================================ +| Note: If SoftFloat is made available as a general library for programs to +| use, it is strongly recommended that a platform-specific version of this +| header, "softfloat.h", be created that folds in "softfloat_types.h" and that +| eliminates all dependencies on compile-time macros. +*============================================================================*/ + + +#ifndef softfloat_h +#define softfloat_h 1 + +#include +#include + +#include "softfloat_types.h" + +/*---------------------------------------------------------------------------- +| Software floating-point underflow tininess-detection mode. +*----------------------------------------------------------------------------*/ +extern uint_fast8_t softfloat_detectTininess; +enum { + softfloat_tininess_beforeRounding = 0, + softfloat_tininess_afterRounding = 1 +}; + +/*---------------------------------------------------------------------------- +| Software floating-point rounding mode. +*----------------------------------------------------------------------------*/ +extern uint_fast8_t softfloat_roundingMode; +enum { + softfloat_round_near_even = 0, + softfloat_round_minMag = 1, + softfloat_round_min = 2, + softfloat_round_max = 3, + softfloat_round_near_maxMag = 4 +}; + +/*---------------------------------------------------------------------------- +| Software floating-point exception flags. +*----------------------------------------------------------------------------*/ +extern uint_fast8_t softfloat_exceptionFlags; +enum { + softfloat_flag_inexact = 1, + softfloat_flag_underflow = 2, + softfloat_flag_overflow = 4, + softfloat_flag_infinite = 8, + softfloat_flag_invalid = 16 +}; + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software floating-point exception flags. +*----------------------------------------------------------------------------*/ +void softfloat_raiseFlags( uint_fast8_t ); + +/*---------------------------------------------------------------------------- +| Integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float32_t ui32_to_f32( uint32_t ); +float64_t ui32_to_f64( uint32_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t ui32_to_extF80( uint32_t ); +float128_t ui32_to_f128( uint32_t ); +#endif +void ui32_to_extF80M( uint32_t, extFloat80_t * ); +void ui32_to_f128M( uint32_t, float128_t * ); +float32_t ui64_to_f32( uint64_t ); +float64_t ui64_to_f64( uint64_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t ui64_to_extF80( uint64_t ); +float128_t ui64_to_f128( uint64_t ); +#endif +void ui64_to_extF80M( uint64_t, extFloat80_t * ); +void ui64_to_f128M( uint64_t, float128_t * ); +float32_t i32_to_f32( int32_t ); +float64_t i32_to_f64( int32_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t i32_to_extF80( int32_t ); +float128_t i32_to_f128( int32_t ); +#endif +void i32_to_extF80M( int32_t, extFloat80_t * ); +void i32_to_f128M( int32_t, float128_t * ); +float32_t i64_to_f32( int64_t ); +float64_t i64_to_f64( int64_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t i64_to_extF80( int64_t ); +float128_t i64_to_f128( int64_t ); +#endif +void i64_to_extF80M( int64_t, extFloat80_t * ); +void i64_to_f128M( int64_t, float128_t * ); + +/*---------------------------------------------------------------------------- +| 32-bit (single-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool ); +uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool ); +int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool ); +int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool ); +uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool ); +uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool ); +int_fast32_t f32_to_i32_r_minMag( float32_t, bool ); +int_fast64_t f32_to_i64_r_minMag( float32_t, bool ); +float64_t f32_to_f64( float32_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t f32_to_extF80( float32_t ); +float128_t f32_to_f128( float32_t ); +#endif +void f32_to_extF80M( float32_t, extFloat80_t * ); +void f32_to_f128M( float32_t, float128_t * ); +float32_t f32_roundToInt( float32_t, uint_fast8_t, bool ); +float32_t f32_add( float32_t, float32_t ); +float32_t f32_sub( float32_t, float32_t ); +float32_t f32_mul( float32_t, float32_t ); +float32_t f32_mulAdd( float32_t, float32_t, float32_t ); +float32_t f32_div( float32_t, float32_t ); +float32_t f32_rem( float32_t, float32_t ); +float32_t f32_sqrt( float32_t ); +bool f32_eq( float32_t, float32_t ); +bool f32_le( float32_t, float32_t ); +bool f32_lt( float32_t, float32_t ); +bool f32_eq_signaling( float32_t, float32_t ); +bool f32_le_quiet( float32_t, float32_t ); +bool f32_lt_quiet( float32_t, float32_t ); +bool f32_isSignalingNaN( float32_t ); + +/*---------------------------------------------------------------------------- +| 64-bit (double-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool ); +uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool ); +int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool ); +int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool ); +uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool ); +uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool ); +int_fast32_t f64_to_i32_r_minMag( float64_t, bool ); +int_fast64_t f64_to_i64_r_minMag( float64_t, bool ); +float32_t f64_to_f32( float64_t ); +#ifdef SOFTFLOAT_FAST_INT64 +extFloat80_t f64_to_extF80( float64_t ); +float128_t f64_to_f128( float64_t ); +#endif +void f64_to_extF80M( float64_t, extFloat80_t * ); +void f64_to_f128M( float64_t, float128_t * ); +float64_t f64_roundToInt( float64_t, uint_fast8_t, bool ); +float64_t f64_add( float64_t, float64_t ); +float64_t f64_sub( float64_t, float64_t ); +float64_t f64_mul( float64_t, float64_t ); +float64_t f64_mulAdd( float64_t, float64_t, float64_t ); +float64_t f64_div( float64_t, float64_t ); +float64_t f64_rem( float64_t, float64_t ); +float64_t f64_sqrt( float64_t ); +bool f64_eq( float64_t, float64_t ); +bool f64_le( float64_t, float64_t ); +bool f64_lt( float64_t, float64_t ); +bool f64_eq_signaling( float64_t, float64_t ); +bool f64_le_quiet( float64_t, float64_t ); +bool f64_lt_quiet( float64_t, float64_t ); +bool f64_isSignalingNaN( float64_t ); + +/*---------------------------------------------------------------------------- +| Rounding precision for 80-bit extended double-precision floating-point. +| Valid values are 32, 64, and 80. +*----------------------------------------------------------------------------*/ +extern uint_fast8_t extF80_roundingPrecision; + +/*---------------------------------------------------------------------------- +| 80-bit extended double-precision floating-point operations. +*----------------------------------------------------------------------------*/ +#ifdef SOFTFLOAT_FAST_INT64 +uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool ); +uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool ); +int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool ); +int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool ); +uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool ); +uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool ); +int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool ); +int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool ); +float32_t extF80_to_f32( extFloat80_t ); +float64_t extF80_to_f64( extFloat80_t ); +float128_t extF80_to_f128( extFloat80_t ); +extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool ); +extFloat80_t extF80_add( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_sub( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_mul( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_div( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_rem( extFloat80_t, extFloat80_t ); +extFloat80_t extF80_sqrt( extFloat80_t ); +bool extF80_eq( extFloat80_t, extFloat80_t ); +bool extF80_le( extFloat80_t, extFloat80_t ); +bool extF80_lt( extFloat80_t, extFloat80_t ); +bool extF80_eq_signaling( extFloat80_t, extFloat80_t ); +bool extF80_le_quiet( extFloat80_t, extFloat80_t ); +bool extF80_lt_quiet( extFloat80_t, extFloat80_t ); +bool extF80_isSignalingNaN( extFloat80_t ); +#endif +uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool ); +uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool ); +int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool ); +int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool ); +uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool ); +uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool ); +int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool ); +int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool ); +float32_t extF80M_to_f32( const extFloat80_t * ); +float64_t extF80M_to_f64( const extFloat80_t * ); +void extF80M_to_f128M( const extFloat80_t *, float128_t * ); +void + extF80M_roundToInt( + const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * ); +void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); +void extF80M_sqrt( const extFloat80_t *, extFloat80_t * ); +bool extF80M_eq( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_le( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_lt( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * ); +bool extF80M_isSignalingNaN( const extFloat80_t * ); + +/*---------------------------------------------------------------------------- +| 128-bit (quadruple-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +#ifdef SOFTFLOAT_FAST_INT64 +uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool ); +uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool ); +int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool ); +int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool ); +uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool ); +uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool ); +int_fast32_t f128_to_i32_r_minMag( float128_t, bool ); +int_fast64_t f128_to_i64_r_minMag( float128_t, bool ); +float32_t f128_to_f32( float128_t ); +float64_t f128_to_f64( float128_t ); +extFloat80_t f128_to_extF80( float128_t ); +float128_t f128_roundToInt( float128_t, uint_fast8_t, bool ); +float128_t f128_add( float128_t, float128_t ); +float128_t f128_sub( float128_t, float128_t ); +float128_t f128_mul( float128_t, float128_t ); +float128_t f128_mulAdd( float128_t, float128_t, float128_t ); +float128_t f128_div( float128_t, float128_t ); +float128_t f128_rem( float128_t, float128_t ); +float128_t f128_sqrt( float128_t ); +bool f128_eq( float128_t, float128_t ); +bool f128_le( float128_t, float128_t ); +bool f128_lt( float128_t, float128_t ); +bool f128_eq_signaling( float128_t, float128_t ); +bool f128_le_quiet( float128_t, float128_t ); +bool f128_lt_quiet( float128_t, float128_t ); +bool f128_isSignalingNaN( float128_t ); +#endif +uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool ); +uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool ); +int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool ); +int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool ); +uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool ); +uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool ); +int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool ); +int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool ); +float32_t f128M_to_f32( const float128_t * ); +float64_t f128M_to_f64( const float128_t * ); +void f128M_to_extF80M( const float128_t *, extFloat80_t * ); +void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * ); +void f128M_add( const float128_t *, const float128_t *, float128_t * ); +void f128M_sub( const float128_t *, const float128_t *, float128_t * ); +void f128M_mul( const float128_t *, const float128_t *, float128_t * ); +void + f128M_mulAdd( + const float128_t *, const float128_t *, const float128_t *, float128_t * + ); +void f128M_div( const float128_t *, const float128_t *, float128_t * ); +void f128M_rem( const float128_t *, const float128_t *, float128_t * ); +void f128M_sqrt( const float128_t *, float128_t * ); +bool f128M_eq( const float128_t *, const float128_t * ); +bool f128M_le( const float128_t *, const float128_t * ); +bool f128M_lt( const float128_t *, const float128_t * ); +bool f128M_eq_signaling( const float128_t *, const float128_t * ); +bool f128M_le_quiet( const float128_t *, const float128_t * ); +bool f128M_lt_quiet( const float128_t *, const float128_t * ); +bool f128M_isSignalingNaN( const float128_t * ); + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h new file mode 100644 index 0000000..ec918ae --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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. + +=============================================================================*/ + +#ifndef softfloat_types_h +#define softfloat_types_h 1 + +#include + +/*---------------------------------------------------------------------------- +| Types used to pass 32-bit, 64-bit, and 128-bit floating-point arguments and +| results to/from functions. These types must be exactly 32 bits, 64 bits, +| and 128 bits in size, respectively. Where a platform has "native" support +| for IEEE-Standard floating-point formats, the types below may, if desired, +| be defined as aliases for the native types (typically `float' and `double', +| and possibly `long double'). +*----------------------------------------------------------------------------*/ +typedef struct { uint32_t v; } float32_t; +typedef struct { uint64_t v; } float64_t; +typedef struct { uint64_t v[2]; } float128_t; + +/*---------------------------------------------------------------------------- +| The format of an 80-bit extended floating-point number in memory. This +| structure must contain a 16-bit field named `signExp' and a 64-bit field +| named `signif'. +*----------------------------------------------------------------------------*/ +#ifdef LITTLEENDIAN +struct extFloat80M { uint64_t signif; uint16_t signExp; }; +#else +struct extFloat80M { uint16_t signExp; uint64_t signif; }; +#endif + +/*---------------------------------------------------------------------------- +| The type used to pass 80-bit extended floating-point arguments and +| results to/from functions. This type must have size identical to +| `struct extFloat80M'. Type `extFloat80_t' can be defined as an alias for +| `struct extFloat80M'. Alternatively, if a platform has "native" support +| for IEEE-Standard 80-bit extended floating-point, it may be possible, +| if desired, to define `extFloat80_t' as an alias for the native type +| (presumably either `long double' or a nonstandard compiler-intrinsic type). +| In that case, the `signif' and `signExp' fields of `struct extFloat80M' +| must align exactly with the locations in memory of the sign, exponent, and +| significand of the native type. +*----------------------------------------------------------------------------*/ +typedef struct extFloat80M extFloat80_t; + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add128.c new file mode 100644 index 0000000..fdfee4e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add128.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_add128 + +struct uint128 + softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + struct uint128 z; + + z.v0 = a0 + b0; + z.v64 = a64 + b64 + (z.v0 < a0); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c new file mode 100644 index 0000000..bc2f9ae --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_add256M + +void + softfloat_add256M( + const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ) +{ + unsigned int index; + uint_fast8_t carry; + uint64_t wordA, wordZ; + + index = indexWordLo( 4 ); + carry = 0; + for (;;) { + wordA = aPtr[index]; + wordZ = wordA + bPtr[index] + carry; + zPtr[index] = wordZ; + if ( index == indexWordHi( 4 ) ) break; + carry = carry ? (wordZ <= wordA) : (wordZ < wordA); + index += wordIncr; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c new file mode 100644 index 0000000..de24208 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_addCarryM + +uint_fast8_t + softfloat_addCarryM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint_fast8_t carry, + uint32_t *zPtr + ) +{ + unsigned int index, lastIndex; + uint32_t wordA, wordZ; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + for (;;) { + wordA = aPtr[index]; + wordZ = wordA + bPtr[index] + carry; + zPtr[index] = wordZ; + carry = carry ? (wordZ <= wordA) : (wordZ < wordA); + if ( index == lastIndex ) break; + index += wordIncr; + } + return carry; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c new file mode 100644 index 0000000..9b17275 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_addComplCarryM + +uint_fast8_t + softfloat_addComplCarryM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint_fast8_t carry, + uint32_t *zPtr + ) +{ + unsigned int index, lastIndex; + uint32_t wordA, wordZ; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + for (;;) { + wordA = aPtr[index]; + wordZ = wordA + ~bPtr[index] + carry; + zPtr[index] = wordZ; + carry = carry ? (wordZ <= wordA) : (wordZ < wordA); + if ( index == lastIndex ) break; + index += wordIncr; + } + return carry; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c new file mode 100644 index 0000000..16c5944 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +void + softfloat_addExtF80M( + const struct extFloat80M *aSPtr, + const struct extFloat80M *bSPtr, + struct extFloat80M *zSPtr, + bool negateB + ) +{ + uint32_t uiA64; + int32_t expA; + uint32_t uiB64; + int32_t expB; + uint32_t uiZ64; + bool signZ, signB; + const struct extFloat80M *tempSPtr; + uint64_t sigZ, sigB; + void + (*roundPackRoutinePtr)( + bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); + int32_t expDiff; + uint32_t extSigX[3], sigZExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + expA = expExtF80UI64( uiA64 ); + uiB64 = bSPtr->signExp; + expB = expExtF80UI64( uiB64 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; + uiZ64 = uiA64; + if ( expB == 0x7FFF ) { + uiZ64 = uiB64 ^ packToExtF80UI64( negateB, 0 ); + if ( (expA == 0x7FFF) && (uiZ64 != uiA64) ) { + softfloat_invalidExtF80M( zSPtr ); + return; + } + } + zSPtr->signExp = uiZ64; + zSPtr->signif = UINT64_C( 0x8000000000000000 ); + return; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signZ = signExtF80UI64( uiA64 ); + signB = signExtF80UI64( uiB64 ) ^ negateB; + negateB = (signZ != signB); + if ( expA < expB ) { + signZ = signB; + expA = expB; + expB = expExtF80UI64( uiA64 ); + tempSPtr = aSPtr; + aSPtr = bSPtr; + bSPtr = tempSPtr; + } + if ( ! expB ) { + expB = 1; + if ( ! expA ) expA = 1; + } + sigZ = aSPtr->signif; + sigB = bSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundPackRoutinePtr = softfloat_roundPackMToExtF80M; + expDiff = expA - expB; + if ( expDiff ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + extSigX[indexWord( 3, 2 )] = sigB>>32; + extSigX[indexWord( 3, 1 )] = sigB; + extSigX[indexWord( 3, 0 )] = 0; + softfloat_shiftRightJam96M( extSigX, expDiff, extSigX ); + sigB = + (uint64_t) extSigX[indexWord( 3, 2 )]<<32 + | extSigX[indexWord( 3, 1 )]; + if ( negateB ) { + sigZ -= sigB; + sigZExtra = extSigX[indexWordLo( 3 )]; + if ( sigZExtra ) { + --sigZ; + sigZExtra = -sigZExtra; + } + if ( ! (sigZ & UINT64_C( 0x8000000000000000 )) ) { + if ( sigZ & UINT64_C( 0x4000000000000000 ) ) { + --expA; + sigZ = sigZ<<1 | sigZExtra>>31; + sigZExtra <<= 1; + } else { + roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M; + } + } + } else { + sigZ += sigB; + if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto sigZ; + sigZExtra = (uint32_t) sigZ<<31 | (extSigX[indexWordLo( 3 )] != 0); + goto completeNormAfterAdd; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigZExtra = 0; + if ( negateB ) { + if ( sigZ < sigB ) { + signZ = ! signZ; + sigZ = sigB - sigZ; + } else { + sigZ -= sigB; + if ( ! sigZ ) { + signZ = (softfloat_roundingMode == softfloat_round_min); + zSPtr->signExp = packToExtF80UI64( signZ, 0 ); + zSPtr->signif = 0; + return; + } + } + roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M; + } else { + sigZ += sigB; + if ( sigZ < sigB ) { + sigZExtra = (uint32_t) sigZ<<31; + completeNormAfterAdd: + ++expA; + sigZ = UINT64_C( 0x8000000000000000 ) | sigZ>>1; + } else { + if ( ! (sigZ & UINT64_C( 0x8000000000000000 )) ) { + roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M; + } + } + } + } + extSigX[indexWord( 3, 0 )] = sigZExtra; + sigZ: + extSigX[indexWord( 3, 2 )] = sigZ>>32; + extSigX[indexWord( 3, 1 )] = sigZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundPack: + (*roundPackRoutinePtr)( + signZ, expA, extSigX, extF80_roundingPrecision, zSPtr ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c new file mode 100644 index 0000000..73c4fb3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +void + softfloat_addF128M( + const uint32_t *aWPtr, + const uint32_t *bWPtr, + uint32_t *zWPtr, + bool negateB + ) +{ + uint32_t uiA96; + int32_t expA; + uint32_t uiB96; + int32_t expB; + uint32_t uiZ96; + bool signZ, signB; + const uint32_t *tempPtr; + uint32_t sig96A, sig96B; + int32_t expDiff; + uint_fast8_t + (*addCarryMRoutinePtr)( + uint_fast8_t, + const uint32_t *, + const uint32_t *, + uint_fast8_t, + uint32_t * + ); + uint32_t extSigZ[5], wordSigZ; + uint_fast8_t carry; + void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * ); + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA96 = aWPtr[indexWordHi( 4 )]; + expA = expF128UI96( uiA96 ); + uiB96 = bWPtr[indexWordHi( 4 )]; + expB = expF128UI96( uiB96 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; + uiZ96 = uiA96; + if ( expB == 0x7FFF ) { + uiZ96 = uiB96 ^ packToF128UI96( negateB, 0, 0 ); + if ( (expA == 0x7FFF) && (uiZ96 != uiA96) ) { + softfloat_invalidF128M( zWPtr ); + return; + } + } + zWPtr[indexWordHi( 4 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + return; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signZ = signF128UI96( uiA96 ); + signB = signF128UI96( uiB96 ) ^ negateB; + negateB = (signZ != signB); + if ( (uint32_t) (uiA96<<1) < (uint32_t) (uiB96<<1) ) { + signZ = signB; + expA = expB; + expB = expF128UI96( uiA96 ); + tempPtr = aWPtr; + aWPtr = bWPtr; + bWPtr = tempPtr; + uiA96 = uiB96; + uiB96 = bWPtr[indexWordHi( 4 )]; + } + sig96A = fracF128UI96( uiA96 ); + sig96B = fracF128UI96( uiB96 ); + if ( expA ) { + --expA; + sig96A |= 0x00010000; + if ( expB ) { + --expB; + sig96B |= 0x00010000; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + addCarryMRoutinePtr = + negateB ? softfloat_addComplCarryM : softfloat_addCarryM; + expDiff = expA - expB; + if ( expDiff ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + extSigZ[indexWordHi( 5 )] = sig96B; + extSigZ[indexWord( 5, 3 )] = bWPtr[indexWord( 4, 2 )]; + extSigZ[indexWord( 5, 2 )] = bWPtr[indexWord( 4, 1 )]; + extSigZ[indexWord( 5, 1 )] = bWPtr[indexWord( 4, 0 )]; + extSigZ[indexWord( 5, 0 )] = 0; + softfloat_shiftRightJam160M( extSigZ, expDiff, extSigZ ); + sig96B = extSigZ[indexWordHi( 5 )]; + carry = 0; + if ( negateB ) { + sig96B = ~sig96B; + wordSigZ = extSigZ[indexWordLo( 5 )]; + extSigZ[indexWordLo( 5 )] = -wordSigZ; + carry = ! wordSigZ; + } + carry = + (*addCarryMRoutinePtr)( + 3, + &aWPtr[indexMultiwordLo( 4, 3 )], + &extSigZ[indexMultiword( 5, 3, 1 )], + carry, + &extSigZ[indexMultiword( 5, 3, 1 )] + ); + wordSigZ = sig96A + sig96B + carry; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + extSigZ[indexWordLo( 5 )] = 0; + carry = + (*addCarryMRoutinePtr)( + 3, + &aWPtr[indexMultiwordLo( 4, 3 )], + &bWPtr[indexMultiwordLo( 4, 3 )], + negateB, + &extSigZ[indexMultiword( 5, 3, 1 )] + ); + if ( negateB ) { + wordSigZ = sig96A + ~sig96B + carry; + if ( wordSigZ & 0x80000000 ) { + signZ = ! signZ; + carry = + softfloat_addComplCarry96M( + &bWPtr[indexMultiwordLo( 4, 3 )], + &aWPtr[indexMultiwordLo( 4, 3 )], + 1, + &extSigZ[indexMultiword( 5, 3, 1 )] + ); + wordSigZ = sig96B + ~sig96A + carry; + } else { + if ( + ! wordSigZ && ! extSigZ[indexWord( 5, 3 )] + && ! ( extSigZ[indexWord( 5, 2 )] + | extSigZ[indexWord( 5, 1 )] + | extSigZ[indexWord( 5, 0 )] + ) + ) { + signZ = (softfloat_roundingMode == softfloat_round_min); + zWPtr[indexWordHi( 4 )] = packToF128UI96( signZ, 0, 0 ); + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + return; + } + } + } else { + wordSigZ = sig96A + sig96B + carry; + } + } + extSigZ[indexWordHi( 5 )] = wordSigZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundPackRoutinePtr = softfloat_normRoundPackMToF128M; + if ( 0x00010000 <= wordSigZ ) { + if ( 0x00020000 <= wordSigZ ) { + ++expA; + softfloat_shortShiftRightJam160M( extSigZ, 1, extSigZ ); + } + roundPackRoutinePtr = softfloat_roundPackMToF128M; + } + (*roundPackRoutinePtr)( signZ, expA, extSigZ, zWPtr ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c new file mode 100644 index 0000000..2309a0b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_addM + +void + softfloat_addM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint32_t *zPtr + ) +{ + unsigned int index, lastIndex; + uint_fast8_t carry; + uint32_t wordA, wordZ; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + carry = 0; + for (;;) { + wordA = aPtr[index]; + wordZ = wordA + bPtr[index] + carry; + zPtr[index] = wordZ; + if ( index == lastIndex ) break; + carry = carry ? (wordZ <= wordA) : (wordZ < wordA); + index += wordIncr; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c new file mode 100644 index 0000000..3fb4b57 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t + softfloat_addMagsExtF80( + uint_fast16_t uiA64, + uint_fast64_t uiA0, + uint_fast16_t uiB64, + uint_fast64_t uiB0, + bool signZ + ) +{ + int_fast32_t expA; + uint_fast64_t sigA; + int_fast32_t expB; + uint_fast64_t sigB; + int_fast32_t expDiff; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0, sigZ, sigZExtra; + struct exp32_sig64 normExpSig; + int_fast32_t expZ; + struct uint64_extra sig64Extra; + struct uint128 uiZ; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expExtF80UI64( uiA64 ); + sigA = uiA0; + expB = expExtF80UI64( uiB64 ); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if ( ! expDiff ) { + if ( expA == 0x7FFF ) { + if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + goto propagateNaN; + } + uiZ64 = uiA64; + uiZ0 = uiA0; + goto uiZ; + } + sigZ = sigA + sigB; + sigZExtra = 0; + if ( ! expA ) { + normExpSig = softfloat_normSubnormalExtF80Sig( sigZ ); + expZ = normExpSig.exp + 1; + sigZ = normExpSig.sig; + goto roundAndPack; + } + expZ = expA; + goto shiftRight1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expDiff < 0 ) { + if ( expB == 0x7FFF ) { + if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); + uiZ0 = uiB0; + goto uiZ; + } + expZ = expB; + if ( ! expA ) { + ++expDiff; + sigZExtra = 0; + if ( ! expDiff ) goto newlyAligned; + } + sig64Extra = softfloat_shiftRightJam64Extra( sigA, 0, -expDiff ); + sigA = sig64Extra.v; + sigZExtra = sig64Extra.extra; + } else { + if ( expA == 0x7FFF ) { + if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + uiZ64 = uiA64; + uiZ0 = uiA0; + goto uiZ; + } + expZ = expA; + if ( ! expB ) { + --expDiff; + sigZExtra = 0; + if ( ! expDiff ) goto newlyAligned; + } + sig64Extra = softfloat_shiftRightJam64Extra( sigB, 0, expDiff ); + sigB = sig64Extra.v; + sigZExtra = sig64Extra.extra; + } + newlyAligned: + sigZ = sigA + sigB; + if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto roundAndPack; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftRight1: + sig64Extra = softfloat_shortShiftRightJam64Extra( sigZ, sigZExtra, 1 ); + sigZ = sig64Extra.v | UINT64_C( 0x8000000000000000 ); + sigZExtra = sig64Extra.extra; + ++expZ; + roundAndPack: + return + softfloat_roundPackToExtF80( + signZ, expZ, sigZ, sigZExtra, extF80_roundingPrecision ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c new file mode 100644 index 0000000..7ceca87 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" + +float128_t + softfloat_addMagsF128( + uint_fast64_t uiA64, + uint_fast64_t uiA0, + uint_fast64_t uiB64, + uint_fast64_t uiB0, + bool signZ + ) +{ + int_fast32_t expA; + struct uint128 sigA; + int_fast32_t expB; + struct uint128 sigB; + int_fast32_t expDiff; + struct uint128 uiZ, sigZ; + int_fast32_t expZ; + uint_fast64_t sigZExtra; + struct uint128_extra sig128Extra; + union ui128_f128 uZ; + + expA = expF128UI64( uiA64 ); + sigA.v64 = fracF128UI64( uiA64 ); + sigA.v0 = uiA0; + expB = expF128UI64( uiB64 ); + sigB.v64 = fracF128UI64( uiB64 ); + sigB.v0 = uiB0; + expDiff = expA - expB; + if ( ! expDiff ) { + if ( expA == 0x7FFF ) { + if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + goto uiZ; + } + sigZ = softfloat_add128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ); + if ( ! expA ) { + uiZ.v64 = packToF128UI64( signZ, 0, sigZ.v64 ); + uiZ.v0 = sigZ.v0; + goto uiZ; + } + expZ = expA; + sigZ.v64 |= UINT64_C( 0x0002000000000000 ); + sigZExtra = 0; + goto shiftRight1; + } + if ( expDiff < 0 ) { + if ( expB == 0x7FFF ) { + if ( sigB.v64 | sigB.v0 ) goto propagateNaN; + uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); + uiZ.v0 = 0; + goto uiZ; + } + expZ = expB; + if ( expA ) { + sigA.v64 |= UINT64_C( 0x0001000000000000 ); + } else { + ++expDiff; + sigZExtra = 0; + if ( ! expDiff ) goto newlyAligned; + } + sig128Extra = + softfloat_shiftRightJam128Extra( sigA.v64, sigA.v0, 0, -expDiff ); + sigA = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } else { + if ( expA == 0x7FFF ) { + if ( sigA.v64 | sigA.v0 ) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + goto uiZ; + } + expZ = expA; + if ( expB ) { + sigB.v64 |= UINT64_C( 0x0001000000000000 ); + } else { + --expDiff; + sigZExtra = 0; + if ( ! expDiff ) goto newlyAligned; + } + sig128Extra = + softfloat_shiftRightJam128Extra( sigB.v64, sigB.v0, 0, expDiff ); + sigB = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } + newlyAligned: + sigZ = + softfloat_add128( + sigA.v64 | UINT64_C( 0x0001000000000000 ), + sigA.v0, + sigB.v64, + sigB.v0 + ); + --expZ; + if ( sigZ.v64 < UINT64_C( 0x0002000000000000 ) ) goto roundAndPack; + ++expZ; + shiftRight1: + sig128Extra = + softfloat_shortShiftRightJam128Extra( + sigZ.v64, sigZ.v0, sigZExtra, 1 ); + sigZ = sig128Extra.v; + sigZExtra = sig128Extra.extra; + roundAndPack: + return + softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra ); + propagateNaN: + uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c new file mode 100644 index 0000000..c63ccd3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" + +float32_t + softfloat_addMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) +{ + int_fast16_t expA; + uint_fast32_t sigA; + int_fast16_t expB; + uint_fast32_t sigB; + int_fast16_t expDiff; + uint_fast32_t uiZ; + int_fast16_t expZ; + uint_fast32_t sigZ; + union ui32_f32 uZ; + + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + expDiff = expA - expB; + sigA <<= 6; + sigB <<= 6; + if ( ! expDiff ) { + if ( expA == 0xFF ) { + if ( sigA | sigB ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + if ( ! expA ) { + uiZ = packToF32UI( signZ, 0, (uiA + uiB) & 0x7FFFFFFF ); + goto uiZ; + } + expZ = expA; + sigZ = 0x40000000 + sigA + sigB; + } else { + if ( expDiff < 0 ) { + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF32UI( signZ, 0xFF, 0 ); + goto uiZ; + } + expZ = expB; + sigA += expA ? 0x20000000 : sigA; + sigA = softfloat_shiftRightJam32( sigA, -expDiff ); + } else { + if ( expA == 0xFF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + expZ = expA; + sigB += expB ? 0x20000000 : sigB; + sigB = softfloat_shiftRightJam32( sigB, expDiff ); + } + sigZ = 0x20000000 + sigA + sigB; + if ( sigZ < 0x40000000 ) { + --expZ; + sigZ <<= 1; + } + } + return softfloat_roundPackToF32( signZ, expZ, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c new file mode 100644 index 0000000..f651f7e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" + +float64_t + softfloat_addMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ ) +{ + int_fast16_t expA; + uint_fast64_t sigA; + int_fast16_t expB; + uint_fast64_t sigB; + int_fast16_t expDiff; + uint_fast64_t uiZ; + int_fast16_t expZ; + uint_fast64_t sigZ; + union ui64_f64 uZ; + + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + expDiff = expA - expB; + sigA <<= 9; + sigB <<= 9; + if ( ! expDiff ) { + if ( expA == 0x7FF ) { + if ( sigA | sigB ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + if ( ! expA ) { + uiZ = + packToF64UI( + signZ, 0, (uiA + uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); + goto uiZ; + } + expZ = expA; + sigZ = UINT64_C( 0x4000000000000000 ) + sigA + sigB; + } else { + if ( expDiff < 0 ) { + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + goto uiZ; + } + expZ = expB; + sigA += expA ? UINT64_C( 0x2000000000000000 ) : sigA; + sigA = softfloat_shiftRightJam64( sigA, -expDiff ); + } else { + if ( expA == 0x7FF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + expZ = expA; + sigB += expB ? UINT64_C( 0x2000000000000000 ) : sigB; + sigB = softfloat_shiftRightJam64( sigB, expDiff ); + } + sigZ = UINT64_C( 0x2000000000000000 ) + sigA + sigB; + if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { + --expZ; + sigZ <<= 1; + } + } + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c new file mode 100644 index 0000000..94d5532 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_approxRecip32_1 + +uint32_t softfloat_approxRecip32_1( uint32_t a ) +{ + int index; + uint16_t eps; + static const uint16_t k0s[] = { + 0xFFC4, 0xF0BE, 0xE363, 0xD76F, 0xCCAD, 0xC2F0, 0xBA16, 0xB201, + 0xAA97, 0xA3C6, 0x9D7A, 0x97A6, 0x923C, 0x8D32, 0x887E, 0x8417 + }; + static const uint16_t k1s[] = { + 0xF0F1, 0xD62C, 0xBFA1, 0xAC77, 0x9C0A, 0x8DDB, 0x8185, 0x76BA, + 0x6D3B, 0x64D4, 0x5D5C, 0x56B1, 0x50B6, 0x4B55, 0x4679, 0x4211 + }; + uint16_t r0; + uint32_t delta0; + uint_fast32_t r; + uint32_t sqrDelta0; + + index = a>>27 & 0xF; + eps = (uint16_t) (a>>11); + r0 = k0s[index] - ((k1s[index] * (uint_fast32_t) eps)>>20); + delta0 = ~(uint_fast32_t) ((r0 * (uint_fast64_t) a)>>7); + r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) delta0)>>24); + sqrDelta0 = ((uint_fast64_t) delta0 * delta0)>>32; + r += ((uint32_t) r * (uint_fast64_t) sqrDelta0)>>48; + return r; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c new file mode 100644 index 0000000..b5cb328 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_approxRecipSqrt32_1 + +uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ) +{ + int index; + uint16_t eps; + static const uint16_t k0s[] = { + 0xB4C9, 0xFFAB, 0xAA7D, 0xF11C, 0xA1C5, 0xE4C7, 0x9A43, 0xDA29, + 0x93B5, 0xD0E5, 0x8DED, 0xC8B7, 0x88C6, 0xC16D, 0x8424, 0xBAE1 + }; + static const uint16_t k1s[] = { + 0xA5A5, 0xEA42, 0x8C21, 0xC62D, 0x788F, 0xAA7F, 0x6928, 0x94B6, + 0x5CC7, 0x8335, 0x52A6, 0x74E2, 0x4A3E, 0x68FE, 0x432B, 0x5EFD + }; + uint16_t r0; + uint_fast32_t ESqrR0; + uint32_t delta0; + uint_fast32_t r; + uint32_t sqrDelta0; + + index = (a>>27 & 0xE) + oddExpA; + eps = (uint16_t) (a>>12); + r0 = k0s[index] - ((k1s[index] * (uint_fast32_t) eps)>>20); + ESqrR0 = (uint_fast32_t) r0 * r0; + if ( ! oddExpA ) ESqrR0 <<= 1; + delta0 = ~(uint_fast32_t) (((uint32_t) ESqrR0 * (uint_fast64_t) a)>>23); + r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) delta0)>>25); + sqrDelta0 = ((uint_fast64_t) delta0 * delta0)>>32; + r += ((uint32_t) ((r>>1) + (r>>3) - ((uint_fast32_t) r0<<14)) + * (uint_fast64_t) sqrDelta0) + >>48; + if ( ! (r & 0x80000000) ) r = 0x80000000; + return r; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c new file mode 100644 index 0000000..ac10845 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_compare128M + +int_fast8_t softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr ) +{ + unsigned int index, lastIndex; + uint32_t wordA, wordB; + + index = indexWordHi( 4 ); + lastIndex = indexWordLo( 4 ); + for (;;) { + wordA = aPtr[index]; + wordB = bPtr[index]; + if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1; + if ( index == lastIndex ) break; + index -= wordIncr; + } + return 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c new file mode 100644 index 0000000..061c1e5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_compare96M + +int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ) +{ + unsigned int index, lastIndex; + uint32_t wordA, wordB; + + index = indexWordHi( 3 ); + lastIndex = indexWordLo( 3 ); + for (;;) { + wordA = aPtr[index]; + wordB = bPtr[index]; + if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1; + if ( index == lastIndex ) break; + index -= wordIncr; + } + return 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c new file mode 100644 index 0000000..1f6b154 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat_types.h" + +int + softfloat_compareNonnormExtF80M( + const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr ) +{ + uint_fast16_t uiA64, uiB64; + uint64_t sigA; + bool signB; + uint64_t sigB; + int32_t expA, expB; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = aSPtr->signExp; + uiB64 = bSPtr->signExp; + sigA = aSPtr->signif; + signB = signExtF80UI64( uiB64 ); + sigB = bSPtr->signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( (uiA64 ^ uiB64) & 0x8000 ) { + if ( ! (sigA | sigB) ) return 0; + goto resultFromSignB; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expExtF80UI64( uiA64 ); + expB = expExtF80UI64( uiB64 ); + if ( expA == 0x7FFF ) { + if (expB == 0x7FFF) return 0; + signB = ! signB; + goto resultFromSignB; + } + if ( expB == 0x7FFF ) { + goto resultFromSignB; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) expA = 1; + if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { + if ( sigA ) { + expA += softfloat_normExtF80SigM( &sigA ); + } else { + expA = -128; + } + } + if ( ! expB ) expB = 1; + if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { + if ( sigB ) { + expB += softfloat_normExtF80SigM( &sigB ); + } else { + expB = -128; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signB ) { + if ( expA < expB ) return 1; + if ( (expB < expA) || (sigB < sigA) ) return -1; + } else { + if ( expB < expA ) return 1; + if ( (expA < expB) || (sigA < sigB) ) return -1; + } + return (sigA != sigB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + resultFromSignB: + return signB ? 1 : -1; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c new file mode 100644 index 0000000..75735b2 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_countLeadingZeros32 + +#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 +#include "primitives.h" + +uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) +{ + uint_fast8_t count; + + count = 0; + if ( a < 0x10000 ) { + count = 16; + a <<= 16; + } + if ( a < 0x1000000 ) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c new file mode 100644 index 0000000..fe28125 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_countLeadingZeros64 + +#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 +#include "primitives.h" + +uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ) +{ + uint_fast8_t count; + uint32_t a32; + + count = 0; + a32 = a>>32; + if ( ! a32 ) { + count = 32; + a32 = a; + } + /*------------------------------------------------------------------------ + | From here, result is current count + count leading zeros of `a32'. + *------------------------------------------------------------------------*/ + if ( a32 < 0x10000 ) { + count += 16; + a32 <<= 16; + } + if ( a32 < 0x1000000 ) { + count += 8; + a32 <<= 8; + } + count += softfloat_countLeadingZeros8[a32>>24]; + return count; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c new file mode 100644 index 0000000..3dd7719 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" + +const uint_least8_t softfloat_countLeadingZeros8[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c new file mode 100644 index 0000000..ee8d18a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" + +#ifndef softfloat_eq128 + +bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + + return (a64 == b64) && (a0 == b0); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c new file mode 100644 index 0000000..8c09b2a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "specialize.h" +#include "softfloat.h" + +void softfloat_invalidExtF80M( struct extFloat80M *zSPtr ) +{ + + softfloat_raiseFlags( softfloat_flag_invalid ); + zSPtr->signExp = defaultNaNExtF80UI64; + zSPtr->signif = defaultNaNExtF80UI0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c new file mode 100644 index 0000000..5c0b8e7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +void softfloat_invalidF128M( uint32_t *zWPtr ) +{ + + softfloat_raiseFlags( softfloat_flag_invalid ); + zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96; + zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64; + zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32; + zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c new file mode 100644 index 0000000..d98a9bb --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "primitives.h" + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +bool softfloat_isNaNF128M( const uint32_t *aWPtr ) +{ + uint32_t uiA96; + + uiA96 = aWPtr[indexWordHi( 4 )]; + if ( (uiA96 & 0x7FFF0000) != 0x7FFF0000 ) return false; + return + ((uiA96 & 0x0000FFFF) != 0) + || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] + | aWPtr[indexWord( 4, 0 )]) + != 0); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c new file mode 100644 index 0000000..56e1d25 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" + +#ifndef softfloat_le128 + +bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + + return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c new file mode 100644 index 0000000..d976e17 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" + +#ifndef softfloat_lt128 + +bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + + return (a64 < b64) || ((a64 == b64) && (a0 < b0)); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c new file mode 100644 index 0000000..baf67d2 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_mul128By32 + +struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) +{ + struct uint128 z; + uint_fast64_t mid; + uint_fast32_t carry; + + z.v0 = a0 * b; + mid = (uint_fast64_t) (uint32_t) (a0>>32) * b; + carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid); + z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c new file mode 100644 index 0000000..b42b208 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_mul128MTo256M + +void + softfloat_mul128MTo256M( + const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ) +{ + uint32_t *lastZPtr, wordB; + uint64_t dwordProd; + uint32_t wordZ; + uint_fast8_t carry; + + bPtr += indexWordLo( 4 ); + lastZPtr = zPtr + indexMultiwordHi( 8, 5 ); + zPtr += indexMultiwordLo( 8, 5 ); + wordB = *bPtr; + dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB; + zPtr[indexWord( 5, 0 )] = dwordProd; + dwordProd = (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32); + zPtr[indexWord( 5, 1 )] = dwordProd; + dwordProd = (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32); + zPtr[indexWord( 5, 2 )] = dwordProd; + dwordProd = (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32); + zPtr[indexWord( 5, 3 )] = dwordProd; + zPtr[indexWord( 5, 4 )] = dwordProd>>32; + do { + bPtr += wordIncr; + zPtr += wordIncr; + wordB = *bPtr; + dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB; + wordZ = zPtr[indexWord( 5, 0 )] + (uint32_t) dwordProd; + zPtr[indexWord( 5, 0 )] = wordZ; + carry = (wordZ < (uint32_t) dwordProd); + dwordProd = + (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32); + wordZ = zPtr[indexWord( 5, 1 )] + (uint32_t) dwordProd + carry; + zPtr[indexWord( 5, 1 )] = wordZ; + carry = + carry ? (wordZ <= (uint32_t) dwordProd) + : (wordZ < (uint32_t) dwordProd); + dwordProd = + (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32); + wordZ = zPtr[indexWord( 5, 2 )] + (uint32_t) dwordProd + carry; + zPtr[indexWord( 5, 2 )] = wordZ; + carry = + carry ? (wordZ <= (uint32_t) dwordProd) + : (wordZ < (uint32_t) dwordProd); + dwordProd = + (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32); + wordZ = zPtr[indexWord( 5, 3 )] + (uint32_t) dwordProd + carry; + zPtr[indexWord( 5, 3 )] = wordZ; + carry = + carry ? (wordZ <= (uint32_t) dwordProd) + : (wordZ < (uint32_t) dwordProd); + zPtr[indexWord( 5, 4 )] = (dwordProd>>32) + carry; + } while ( zPtr != lastZPtr ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c new file mode 100644 index 0000000..f210937 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_mul128To256M + +#define softfloat_mul128To256M softfloat_mul128To256M +#include "primitives.h" + +void + softfloat_mul128To256M( + uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ) +{ + struct uint128 p0, p64, p128; + uint_fast64_t z64, z128, z192; + + p0 = softfloat_mul64To128( a0, b0 ); + zPtr[indexWord( 4, 0 )] = p0.v0; + p64 = softfloat_mul64To128( a64, b0 ); + z64 = p64.v0 + p0.v64; + z128 = p64.v64 + (z64 < p64.v0); + p128 = softfloat_mul64To128( a64, b64 ); + z128 += p128.v0; + z192 = p128.v64 + (z128 < p128.v0); + p64 = softfloat_mul64To128( a0, b64 ); + z64 += p64.v0; + zPtr[indexWord( 4, 1 )] = z64; + p64.v64 += (z64 < p64.v0); + z128 += p64.v64; + zPtr[indexWord( 4, 2 )] = z128; + zPtr[indexWord( 4, 3 )] = z192 + (z128 < p64.v64); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c new file mode 100644 index 0000000..a16a609 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_mul64ByShifted32To128 + +struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) +{ + uint_fast64_t mid; + struct uint128 z; + + mid = (uint_fast64_t) (uint32_t) a * b; + z.v0 = mid<<32; + z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c new file mode 100644 index 0000000..d05c0b8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_mul64To128 + +struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) +{ + uint32_t a32, a0, b32, b0; + struct uint128 z; + uint64_t mid1, mid; + + a32 = a>>32; + a0 = a; + b32 = b>>32; + b0 = b; + z.v0 = (uint_fast64_t) a0 * b0; + mid1 = (uint_fast64_t) a32 * b0; + mid = mid1 + (uint_fast64_t) a0 * b32; + z.v64 = (uint_fast64_t) a32 * b32; + z.v64 += (uint_fast64_t) (mid < mid1)<<32 | mid>>32; + mid <<= 32; + z.v0 += mid; + z.v64 += (z.v0 < mid); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c new file mode 100644 index 0000000..0ee736a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_mul64To128M + +void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ) +{ + uint32_t a32, a0, b32, b0; + uint64_t z0, mid1, z64, mid; + + a32 = a>>32; + a0 = a; + b32 = b>>32; + b0 = b; + z0 = (uint64_t) a0 * b0; + mid1 = (uint64_t) a32 * b0; + mid = mid1 + (uint64_t) a0 * b32; + z64 = (uint64_t) a32 * b32; + z64 += (uint64_t) (mid < mid1)<<32 | mid>>32; + mid <<= 32; + z0 += mid; + zPtr[indexWord( 4, 1 )] = z0>>32; + zPtr[indexWord( 4, 0 )] = z0; + z64 += (z0 < mid); + zPtr[indexWord( 4, 3 )] = z64>>32; + zPtr[indexWord( 4, 2 )] = z64; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c new file mode 100644 index 0000000..c9b5bbe --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c @@ -0,0 +1,354 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t + softfloat_mulAddF128( + uint_fast64_t uiA64, + uint_fast64_t uiA0, + uint_fast64_t uiB64, + uint_fast64_t uiB0, + uint_fast64_t uiC64, + uint_fast64_t uiC0, + uint_fast8_t op + ) +{ + bool signA; + int_fast32_t expA; + struct uint128 sigA; + bool signB; + int_fast32_t expB; + struct uint128 sigB; + bool signC; + int_fast32_t expC; + struct uint128 sigC; + bool signZ; + uint_fast64_t magBits; + struct uint128 uiZ; + struct exp32_sig128 normExpSig; + int_fast32_t expZ; + uint64_t sig256Z[4]; + struct uint128 sigZ; + int_fast32_t shiftCount, expDiff; + struct uint128 x128; + uint64_t sig256C[4]; + static uint64_t zero256[4] = INIT_UINTM4( 0, 0, 0, 0 ); + uint_fast64_t sigZExtra, sig256Z0; + union ui128_f128 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF128UI64( uiA64 ); + expA = expF128UI64( uiA64 ); + sigA.v64 = fracF128UI64( uiA64 ); + sigA.v0 = uiA0; + signB = signF128UI64( uiB64 ); + expB = expF128UI64( uiB64 ); + sigB.v64 = fracF128UI64( uiB64 ); + sigB.v0 = uiB0; + signC = signF128UI64( uiC64 ) ^ (op == softfloat_mulAdd_subC); + expC = expF128UI64( uiC64 ); + sigC.v64 = fracF128UI64( uiC64 ); + sigC.v0 = uiC0; + signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FFF ) { + if ( + (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0)) + ) { + goto propagateNaN_ABC; + } + magBits = expB | sigB.v64 | sigB.v0; + goto infProdArg; + } + if ( expB == 0x7FFF ) { + if ( sigB.v64 | sigB.v0 ) goto propagateNaN_ABC; + magBits = expA | sigA.v64 | sigA.v0; + goto infProdArg; + } + if ( expC == 0x7FFF ) { + if ( sigC.v64 | sigC.v0 ) { + uiZ.v64 = 0; + uiZ.v0 = 0; + goto propagateNaN_ZC; + } + uiZ.v64 = uiC64; + uiZ.v0 = uiC0; + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! (sigA.v64 | sigA.v0) ) goto zeroProd; + normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! (sigB.v64 | sigB.v0) ) goto zeroProd; + normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FFE; + sigA.v64 |= UINT64_C( 0x0001000000000000 ); + sigB.v64 |= UINT64_C( 0x0001000000000000 ); + sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 8 ); + sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 15 ); + softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z ); + sigZ.v64 = sig256Z[indexWord( 4, 3 )]; + sigZ.v0 = sig256Z[indexWord( 4, 2 )]; + shiftCount = 0; + if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) { + --expZ; + shiftCount = -1; + } + if ( ! expC ) { + if ( ! (sigC.v64 | sigC.v0) ) { + shiftCount += 8; + goto sigZ; + } + normExpSig = softfloat_normSubnormalF128Sig( sigC.v64, sigC.v0 ); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC.v64 |= UINT64_C( 0x0001000000000000 ); + sigC = softfloat_shortShiftLeft128( sigC.v64, sigC.v0, 8 ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if ( expDiff < 0 ) { + expZ = expC; + if ( (signZ == signC) || (expDiff < -1) ) { + shiftCount -= expDiff; + if ( shiftCount ) { + sigZ = + softfloat_shiftRightJam128( + sigZ.v64, sigZ.v0, shiftCount ); + } + } else { + if ( ! shiftCount ) { + x128 = + softfloat_shortShiftRight128( + sig256Z[indexWord( 4, 1 )], sig256Z[indexWord( 4, 0 )], + 1 + ); + sig256Z[indexWord( 4, 1 )] = (sigZ.v0<<63) | x128.v64; + sig256Z[indexWord( 4, 0 )] = x128.v0; + sigZ = softfloat_shortShiftRight128( sigZ.v64, sigZ.v0, 1 ); + sig256Z[indexWord( 4, 3 )] = sigZ.v64; + sig256Z[indexWord( 4, 2 )] = sigZ.v0; + } + } + } else { + if ( shiftCount ) softfloat_add256M( sig256Z, sig256Z, sig256Z ); + if ( ! expDiff ) { + sigZ.v64 = sig256Z[indexWord( 4, 3 )]; + sigZ.v0 = sig256Z[indexWord( 4, 2 )]; + } else { + sig256C[indexWord( 4, 3 )] = sigC.v64; + sig256C[indexWord( 4, 2 )] = sigC.v0; + sig256C[indexWord( 4, 1 )] = 0; + sig256C[indexWord( 4, 0 )] = 0; + softfloat_shiftRightJam256M( sig256C, expDiff, sig256C ); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftCount = 8; + if ( signZ == signC ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff <= 0 ) { + sigZ = softfloat_add128( sigC.v64, sigC.v0, sigZ.v64, sigZ.v0 ); + } else { + softfloat_add256M( sig256Z, sig256C, sig256Z ); + sigZ.v64 = sig256Z[indexWord( 4, 3 )]; + sigZ.v0 = sig256Z[indexWord( 4, 2 )]; + } + if ( sigZ.v64 & UINT64_C( 0x0200000000000000 ) ) { + ++expZ; + shiftCount = 9; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff < 0 ) { + signZ = signC; + if ( expDiff < -1 ) { + sigZ = + softfloat_sub128( sigC.v64, sigC.v0, sigZ.v64, sigZ.v0 ); + sigZExtra = + sig256Z[indexWord( 4, 1 )] | sig256Z[indexWord( 4, 0 )]; + if ( sigZExtra ) { + sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 ); + } + if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) { + --expZ; + shiftCount = 7; + } + goto shiftRightRoundPack; + } else { + sig256C[indexWord( 4, 3 )] = sigC.v64; + sig256C[indexWord( 4, 2 )] = sigC.v0; + sig256C[indexWord( 4, 1 )] = 0; + sig256C[indexWord( 4, 0 )] = 0; + softfloat_sub256M( sig256C, sig256Z, sig256Z ); + } + } else if ( ! expDiff ) { + sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, sigC.v64, sigC.v0 ); + if ( + ! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord( 4, 1 )] + && ! sig256Z[indexWord( 4, 0 )] + ) { + goto completeCancellation; + } + sig256Z[indexWord( 4, 3 )] = sigZ.v64; + sig256Z[indexWord( 4, 2 )] = sigZ.v0; + if ( sigZ.v64 & UINT64_C( 0x8000000000000000 ) ) { + signZ ^= 1; + softfloat_sub256M( zero256, sig256Z, sig256Z ); + } + } else { + softfloat_sub256M( sig256Z, sig256C, sig256Z ); + if ( 1 < expDiff ) { + sigZ.v64 = sig256Z[indexWord( 4, 3 )]; + sigZ.v0 = sig256Z[indexWord( 4, 2 )]; + if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) { + --expZ; + shiftCount = 7; + } + goto sigZ; + } + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigZ.v64 = sig256Z[indexWord( 4, 3 )]; + sigZ.v0 = sig256Z[indexWord( 4, 2 )]; + sigZExtra = sig256Z[indexWord( 4, 1 )]; + sig256Z0 = sig256Z[indexWord( 4, 0 )]; + if ( sigZ.v64 ) { + if ( sig256Z0 ) sigZExtra |= 1; + } else { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = sigZExtra; + sigZExtra = sig256Z0; + if ( ! sigZ.v64 ) { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = sigZExtra; + sigZExtra = 0; + if ( ! sigZ.v64 ) { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = 0; + } + } + } + shiftCount = softfloat_countLeadingZeros64( sigZ.v64 ); + expZ += 7 - shiftCount; + shiftCount = 15 - shiftCount; + if ( 0 < shiftCount ) goto shiftRightRoundPack; + if ( shiftCount ) { + shiftCount = -shiftCount; + sigZ = + softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, shiftCount ); + x128 = softfloat_shortShiftLeft128( 0, sigZExtra, shiftCount ); + sigZ.v0 |= x128.v64; + sigZExtra = x128.v0; + } + goto roundPack; + } + sigZ: + sigZExtra = sig256Z[indexWord( 4, 1 )] | sig256Z[indexWord( 4, 0 )]; + shiftRightRoundPack: + sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftCount)) | (sigZExtra != 0); + sigZ = softfloat_shortShiftRight128( sigZ.v64, sigZ.v0, shiftCount ); + roundPack: + return + softfloat_roundPackToF128( + signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); + goto propagateNaN_ZC; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if ( magBits ) { + uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); + uiZ.v0 = 0; + if ( expC != 0x7FFF ) goto uiZ; + if ( sigC.v64 | sigC.v0 ) goto propagateNaN_ZC; + if ( signZ == signC ) goto uiZ; + } + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF128UI( uiZ.v64, uiZ.v0, uiC64, uiC0 ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ.v64 = uiC64; + uiZ.v0 = uiC0; + if ( ! (expC | sigC.v64 | sigC.v0) && (signZ != signC) ) { + completeCancellation: + uiZ.v64 = + packToF128UI64( + softfloat_roundingMode == softfloat_round_min, 0, 0 ); + uiZ.v0 = 0; + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c new file mode 100644 index 0000000..8ab8888 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +void + softfloat_mulAddF128M( + const uint32_t *aWPtr, + const uint32_t *bWPtr, + const uint32_t *cWPtr, + uint32_t *zWPtr, + uint_fast8_t op + ) +{ + uint32_t uiA96; + int32_t expA; + uint32_t uiB96; + int32_t expB; + uint32_t uiC96; + bool signC; + int32_t expC; + bool signProd, prodIsInfinite; + uint32_t *ptr, uiZ96, sigA[4]; + uint_fast8_t shiftCount; + uint32_t sigX[5]; + int32_t expProd; + uint32_t sigProd[8], wordSig; + bool doSub; + uint_fast8_t + (*addCarryMRoutinePtr)( + uint_fast8_t, + const uint32_t *, + const uint32_t *, + uint_fast8_t, + uint32_t * + ); + int32_t expDiff; + bool signZ; + int32_t expZ; + uint32_t *extSigPtr; + uint_fast8_t carry; + void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * ); + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA96 = aWPtr[indexWordHi( 4 )]; + expA = expF128UI96( uiA96 ); + uiB96 = bWPtr[indexWordHi( 4 )]; + expB = expF128UI96( uiB96 ); + uiC96 = cWPtr[indexWordHi( 4 )]; + signC = signF128UI96( uiC96 ) ^ (op == softfloat_mulAdd_subC); + expC = expF128UI96( uiC96 ); + signProd = + signF128UI96( uiA96 ) ^ signF128UI96( uiB96 ) + ^ (op == softfloat_mulAdd_subProd); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + prodIsInfinite = false; + if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { + if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) { + goto propagateNaN_ZC; + } + ptr = (uint32_t *) aWPtr; + if ( ! (uint32_t) (uiA96<<1) ) goto possibleInvalidProd; + if ( ! (uint32_t) (uiB96<<1) ) { + ptr = (uint32_t *) bWPtr; + possibleInvalidProd: + if ( + ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )] + | ptr[indexWord( 4, 0 )]) + ) { + goto invalid; + } + } + prodIsInfinite = true; + } + if ( expC == 0x7FFF ) { + if ( + fracF128UI96( uiC96 ) + || (cWPtr[indexWord( 4, 2 )] | cWPtr[indexWord( 4, 1 )] + | cWPtr[indexWord( 4, 0 )]) + ) { + zWPtr[indexWordHi( 4 )] = 0; + goto propagateNaN_ZC; + } + if ( prodIsInfinite && (signProd != signC) ) goto invalid; + goto copyC; + } + if ( prodIsInfinite ) { + uiZ96 = packToF128UI96( signProd, 0x7FFF, 0 ); + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA ) { + sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000; + sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; + sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; + sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; + } else { + expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA ); + if ( expA == -128 ) goto zeroProd; + } + if ( expB ) { + sigX[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000; + sigX[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )]; + sigX[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )]; + sigX[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )]; + } else { + expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigX ); + if ( expB == -128 ) goto zeroProd; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expProd = expA + expB - 0x3FF0; + softfloat_mul128MTo256M( sigA, sigX, sigProd ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + wordSig = fracF128UI96( uiC96 ); + if ( expC ) { + --expC; + wordSig |= 0x00010000; + } + sigX[indexWordHi( 5 )] = wordSig; + sigX[indexWord( 5, 3 )] = cWPtr[indexWord( 4, 2 )]; + sigX[indexWord( 5, 2 )] = cWPtr[indexWord( 4, 1 )]; + sigX[indexWord( 5, 1 )] = cWPtr[indexWord( 4, 0 )]; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + doSub = (signProd != signC); + addCarryMRoutinePtr = + doSub ? softfloat_addComplCarryM : softfloat_addCarryM; + expDiff = expProd - expC; + if ( expDiff <= 0 ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + signZ = signC; + expZ = expC; + if ( + sigProd[indexWord( 8, 2 )] + || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) + ) { + sigProd[indexWord( 8, 3 )] |= 1; + } + extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )]; + if ( expDiff ) { + softfloat_shiftRightJam160M( extSigPtr, -expDiff, extSigPtr ); + } + carry = 0; + if ( doSub ) { + wordSig = extSigPtr[indexWordLo( 5 )]; + extSigPtr[indexWordLo( 5 )] = -wordSig; + carry = ! wordSig; + } + (*addCarryMRoutinePtr)( + 4, + &sigX[indexMultiwordHi( 5, 4 )], + extSigPtr + indexMultiwordHi( 5, 4 ), + carry, + extSigPtr + indexMultiwordHi( 5, 4 ) + ); + wordSig = extSigPtr[indexWordHi( 5 )]; + if ( ! expZ ) { + if ( wordSig & 0x80000000 ) { + signZ = ! signZ; + softfloat_negX160M( extSigPtr ); + wordSig = extSigPtr[indexWordHi( 5 )]; + } + goto checkCancellation; + } + if ( wordSig < 0x00010000 ) { + --expZ; + softfloat_add160M( extSigPtr, extSigPtr, extSigPtr ); + goto roundPack; + } + goto extSigReady_noCancellation; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + signZ = signProd; + expZ = expProd; + sigX[indexWordLo( 5 )] = 0; + expDiff -= 128; + if ( 0 <= expDiff ) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + if ( expDiff ) softfloat_shiftRightJam160M( sigX, expDiff, sigX ); + wordSig = sigX[indexWordLo( 5 )]; + carry = 0; + if ( doSub ) { + carry = ! wordSig; + wordSig = -wordSig; + } + carry = + (*addCarryMRoutinePtr)( + 4, + &sigProd[indexMultiwordLo( 8, 4 )], + &sigX[indexMultiwordHi( 5, 4 )], + carry, + &sigProd[indexMultiwordLo( 8, 4 )] + ); + sigProd[indexWord( 8, 2 )] |= wordSig; + ptr = &sigProd[indexWord( 8, 4 )]; + } else { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + shiftCount = expDiff & 31; + if ( shiftCount ) { + softfloat_shortShiftRight160M( sigX, shiftCount, sigX ); + } + expDiff >>= 5; + extSigPtr = + &sigProd[indexMultiwordLo( 8, 5 )] - wordIncr + + expDiff * -wordIncr; + carry = + (*addCarryMRoutinePtr)( 5, extSigPtr, sigX, doSub, extSigPtr ); + if ( expDiff == -4 ) { + /*------------------------------------------------------------ + *------------------------------------------------------------*/ + wordSig = sigProd[indexWordHi( 8 )]; + if ( wordSig & 0x80000000 ) { + signZ = ! signZ; + softfloat_negX256M( sigProd ); + wordSig = sigProd[indexWordHi( 8 )]; + } + /*------------------------------------------------------------ + *------------------------------------------------------------*/ + if ( wordSig ) goto expProdBigger_noWordShift; + wordSig = sigProd[indexWord( 8, 6 )]; + if ( 0x00040000 <= wordSig ) goto expProdBigger_noWordShift; + expZ -= 32; + extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )] - wordIncr; + for (;;) { + if ( wordSig ) break; + wordSig = extSigPtr[indexWord( 5, 3 )]; + if ( 0x00040000 <= wordSig ) break; + expZ -= 32; + extSigPtr -= wordIncr; + if ( extSigPtr == &sigProd[indexMultiwordLo( 8, 5 )] ) { + goto checkCancellation; + } + } + /*------------------------------------------------------------ + *------------------------------------------------------------*/ + ptr = extSigPtr + indexWordLo( 5 ); + do { + ptr -= wordIncr; + if ( *ptr ) { + extSigPtr[indexWordLo( 5 )] |= 1; + break; + } + } while ( ptr != &sigProd[indexWordLo( 8 )] ); + wordSig = extSigPtr[indexWordHi( 5 )]; + goto extSigReady; + } + ptr = extSigPtr + indexWordHi( 5 ) + wordIncr; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( carry != doSub ) { + if ( doSub ) { + do { + wordSig = *ptr; + *ptr = wordSig - 1; + ptr += wordIncr; + } while ( ! wordSig ); + } else { + do { + wordSig = *ptr + 1; + *ptr = wordSig; + ptr += wordIncr; + } while ( ! wordSig ); + } + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + expProdBigger_noWordShift: + if ( + sigProd[indexWord( 8, 2 )] + || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) + ) { + sigProd[indexWord( 8, 3 )] |= 1; + } + extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )]; + wordSig = extSigPtr[indexWordHi( 5 )]; + } + extSigReady: + roundPackRoutinePtr = softfloat_normRoundPackMToF128M; + if ( wordSig < 0x00010000 ) goto doRoundPack; + extSigReady_noCancellation: + if ( 0x00020000 <= wordSig ) { + ++expZ; + softfloat_shortShiftRightJam160M( extSigPtr, 1, extSigPtr ); + } + roundPack: + roundPackRoutinePtr = softfloat_roundPackMToF128M; + doRoundPack: + (*roundPackRoutinePtr)( signZ, expZ, extSigPtr, zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_invalidF128M( zWPtr ); + propagateNaN_ZC: + softfloat_propagateNaNF128M( zWPtr, cWPtr, zWPtr ); + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + if ( + ! (uint32_t) (uiC96<<1) && (signProd != signC) + && ! cWPtr[indexWord( 4, 2 )] + && ! (cWPtr[indexWord( 4, 1 )] | cWPtr[indexWord( 4, 0 )]) + ) { + goto completeCancellation; + } + copyC: + zWPtr[indexWordHi( 4 )] = uiC96; + zWPtr[indexWord( 4, 2 )] = cWPtr[indexWord( 4, 2 )]; + zWPtr[indexWord( 4, 1 )] = cWPtr[indexWord( 4, 1 )]; + zWPtr[indexWord( 4, 0 )] = cWPtr[indexWord( 4, 0 )]; + return; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + checkCancellation: + if ( + wordSig + || (extSigPtr[indexWord( 5, 3 )] | extSigPtr[indexWord( 5, 2 )]) + || (extSigPtr[indexWord( 5, 1 )] | extSigPtr[indexWord( 5, 0 )]) + ) { + goto extSigReady; + } + completeCancellation: + uiZ96 = + packToF128UI96( + (softfloat_roundingMode == softfloat_round_min), 0, 0 ); + uiZ: + zWPtr[indexWordHi( 4 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c new file mode 100644 index 0000000..fa9a95a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t + softfloat_mulAddF32( + uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC, uint_fast8_t op ) +{ + bool signA; + int_fast16_t expA; + uint_fast32_t sigA; + bool signB; + int_fast16_t expB; + uint_fast32_t sigB; + bool signC; + int_fast16_t expC; + uint_fast32_t sigC; + bool signProd; + uint_fast32_t magBits, uiZ; + struct exp16_sig32 normExpSig; + int_fast16_t expProd; + uint_fast64_t sigProd; + bool signZ; + int_fast16_t expZ; + uint_fast32_t sigZ; + int_fast16_t expDiff; + uint_fast64_t sig64Z, sig64C; + int_fast8_t shiftCount; + union ui32_f32 uZ; + + signA = signF32UI( uiA ); + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + signB = signF32UI( uiB ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + signC = signF32UI( uiC ) ^ (op == softfloat_mulAdd_subC); + expC = expF32UI( uiC ); + sigC = fracF32UI( uiC ); + signProd = signA ^ signB ^ (op == softfloat_mulAdd_subProd); + if ( expA == 0xFF ) { + if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN_ABC; + magBits = expB | sigB; + goto infProdArg; + } + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN_ABC; + magBits = expA | sigA; + goto infProdArg; + } + if ( expC == 0xFF ) { + if ( sigC ) { + uiZ = 0; + goto propagateNaN_ZC; + } + uiZ = uiC; + goto uiZ; + } + if ( ! expA ) { + if ( ! sigA ) goto zeroProd; + normExpSig = softfloat_normSubnormalF32Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zeroProd; + normExpSig = softfloat_normSubnormalF32Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + expProd = expA + expB - 0x7E; + sigA = (sigA | 0x00800000)<<7; + sigB = (sigB | 0x00800000)<<7; + sigProd = (uint_fast64_t) sigA * sigB; + if ( sigProd < UINT64_C( 0x2000000000000000 ) ) { + --expProd; + sigProd <<= 1; + } + signZ = signProd; + if ( ! expC ) { + if ( ! sigC ) { + expZ = expProd - 1; + sigZ = softfloat_shortShiftRightJam64( sigProd, 31 ); + goto roundPack; + } + normExpSig = softfloat_normSubnormalF32Sig( sigC ); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | 0x00800000)<<6; + expDiff = expProd - expC; + if ( signProd == signC ) { + if ( expDiff <= 0 ) { + expZ = expC; + sigZ = sigC + softfloat_shiftRightJam64( sigProd, 32 - expDiff ); + } else { + expZ = expProd; + sig64Z = + sigProd + + softfloat_shiftRightJam64( + (uint_fast64_t) sigC<<32, expDiff ); + sigZ = softfloat_shortShiftRightJam64( sig64Z, 32 ); + } + if ( sigZ < 0x40000000 ) { + --expZ; + sigZ <<= 1; + } + } else { + sig64C = (uint_fast64_t) sigC<<32; + if ( expDiff < 0 ) { + signZ = signC; + expZ = expC; + sig64Z = sig64C - softfloat_shiftRightJam64( sigProd, -expDiff ); + } else if ( ! expDiff ) { + expZ = expProd; + sig64Z = sigProd - sig64C; + if ( ! sig64Z ) goto completeCancellation; + if ( sig64Z & UINT64_C( 0x8000000000000000 ) ) { + signZ ^= 1; + sig64Z = -sig64Z; + } + } else { + expZ = expProd; + sig64Z = sigProd - softfloat_shiftRightJam64( sig64C, expDiff ); + } + shiftCount = softfloat_countLeadingZeros64( sig64Z ) - 1; + expZ -= shiftCount; + shiftCount -= 32; + if ( shiftCount < 0 ) { + sigZ = softfloat_shortShiftRightJam64( sig64Z, -shiftCount ); + } else { + sigZ = (uint_fast32_t) sig64Z< +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +float64_t + softfloat_mulAddF64( + uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op ) +{ + bool signA; + int_fast16_t expA; + uint_fast64_t sigA; + bool signB; + int_fast16_t expB; + uint_fast64_t sigB; + bool signC; + int_fast16_t expC; + uint_fast64_t sigC; + bool signZ; + uint_fast64_t magBits, uiZ; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; + struct uint128 sig128Z; + uint_fast64_t sigZ; + int_fast16_t expDiff; + struct uint128 sig128C; + int_fast8_t shiftCount; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC); + expC = expF64UI( uiC ); + sigC = fracF64UI( uiC ); + signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC; + magBits = expB | sigB; + goto infProdArg; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN_ABC; + magBits = expA | sigA; + goto infProdArg; + } + if ( expC == 0x7FF ) { + if ( sigC ) { + uiZ = 0; + goto propagateNaN_ZC; + } + uiZ = uiC; + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) goto zeroProd; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zeroProd; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FE; + sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; + sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<10; + sig128Z = softfloat_mul64To128( sigA, sigB ); + if ( sig128Z.v64 < UINT64_C( 0x2000000000000000 ) ) { + --expZ; + sig128Z = + softfloat_add128( + sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 ); + } + if ( ! expC ) { + if ( ! sigC ) { + --expZ; + sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0); + goto roundPack; + } + normExpSig = softfloat_normSubnormalF64Sig( sigC ); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<9; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if ( expDiff < 0 ) { + expZ = expC; + if ( (signZ == signC) || (expDiff < -1) ) { + sig128Z.v64 = softfloat_shiftRightJam64( sig128Z.v64, -expDiff ); + } else { + sig128Z = + softfloat_shortShiftRightJam128( sig128Z.v64, sig128Z.v0, 1 ); + } + } else if ( expDiff ) { + sig128C = softfloat_shiftRightJam128( sigC, 0, expDiff ); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signZ == signC ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff <= 0 ) { + sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0); + } else { + sig128Z = + softfloat_add128( + sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 ); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); + } + if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff < 0 ) { + signZ = signC; + sig128Z = softfloat_sub128( sigC, 0, sig128Z.v64, sig128Z.v0 ); + } else if ( ! expDiff ) { + sig128Z.v64 = sig128Z.v64 - sigC; + if ( ! (sig128Z.v64 | sig128Z.v0) ) goto completeCancellation; + if ( sig128Z.v64 & UINT64_C( 0x8000000000000000 ) ) { + signZ ^= 1; + sig128Z = softfloat_sub128( 0, 0, sig128Z.v64, sig128Z.v0 ); + } + } else { + sig128Z = + softfloat_sub128( + sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 ); + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( ! sig128Z.v64 ) { + expZ -= 64; + sig128Z.v64 = sig128Z.v0; + sig128Z.v0 = 0; + } + shiftCount = softfloat_countLeadingZeros64( sig128Z.v64 ) - 1; + expZ -= shiftCount; + if ( shiftCount < 0 ) { + sigZ = softfloat_shortShiftRightJam64( sig128Z.v64, -shiftCount ); + } else { + sig128Z = + softfloat_shortShiftLeft128( + sig128Z.v64, sig128Z.v0, shiftCount ); + sigZ = sig128Z.v64; + } + sigZ |= (sig128Z.v0 != 0); + } + roundPack: + return softfloat_roundPackToF64( signZ, expZ, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto propagateNaN_ZC; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if ( magBits ) { + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + if ( expC != 0x7FF ) goto uiZ; + if ( sigC ) goto propagateNaN_ZC; + if ( signZ == signC ) goto uiZ; + } + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF64UI( uiZ, uiC ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ = uiC; + if ( ! (expC | sigC) && (signZ != signC) ) { + completeCancellation: + uiZ = + packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + +#else + +float64_t + softfloat_mulAddF64( + uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op ) +{ + bool signA; + int_fast16_t expA; + uint64_t sigA; + bool signB; + int_fast16_t expB; + uint64_t sigB; + bool signC; + int_fast16_t expC; + uint64_t sigC; + bool signZ; + uint64_t magBits, uiZ; + struct exp16_sig64 normExpSig; + int_fast16_t expZ; + uint32_t sig128Z[4]; + uint64_t sigZ; + int_fast16_t shiftCount, expDiff; + uint32_t sig128C[4]; + union ui64_f64 uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI( uiA ); + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + signB = signF64UI( uiB ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC); + expC = expF64UI( uiC ); + sigC = fracF64UI( uiC ); + signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( expA == 0x7FF ) { + if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC; + magBits = expB | sigB; + goto infProdArg; + } + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN_ABC; + magBits = expA | sigA; + goto infProdArg; + } + if ( expC == 0x7FF ) { + if ( sigC ) { + uiZ = 0; + goto propagateNaN_ZC; + } + uiZ = uiC; + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( ! expA ) { + if ( ! sigA ) goto zeroProd; + normExpSig = softfloat_normSubnormalF64Sig( sigA ); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if ( ! expB ) { + if ( ! sigB ) goto zeroProd; + normExpSig = softfloat_normSubnormalF64Sig( sigB ); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FE; + sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; + sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11; + softfloat_mul64To128M( sigA, sigB, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; + shiftCount = 0; + if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { + --expZ; + shiftCount = -1; + } + if ( ! expC ) { + if ( ! sigC ) { + if ( shiftCount ) sigZ <<= 1; + goto sigZ; + } + normExpSig = softfloat_normSubnormalF64Sig( sigC ); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<10; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if ( expDiff < 0 ) { + expZ = expC; + if ( (signZ == signC) || (expDiff < -1) ) { + shiftCount -= expDiff; + if ( shiftCount) { + sigZ = softfloat_shiftRightJam64( sigZ, shiftCount ); + } + } else { + if ( ! shiftCount ) { + softfloat_shortShiftRight128M( sig128Z, 1, sig128Z ); + } + } + } else { + if ( shiftCount ) softfloat_add128M( sig128Z, sig128Z, sig128Z ); + if ( ! expDiff ) { + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + } else { + sig128C[indexWord( 4, 3 )] = sigC>>32; + sig128C[indexWord( 4, 2 )] = sigC; + sig128C[indexWord( 4, 1 )] = 0; + sig128C[indexWord( 4, 0 )] = 0; + softfloat_shiftRightJam128M( sig128C, expDiff, sig128C ); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( signZ == signC ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff <= 0 ) { + sigZ += sigC; + } else { + softfloat_add128M( sig128Z, sig128C, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + } + if ( sigZ & UINT64_C( 0x8000000000000000 ) ) { + ++expZ; + sigZ = softfloat_shortShiftRightJam64( sigZ, 1 ); + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( expDiff < 0 ) { + signZ = signC; + if ( expDiff < -1 ) { + sigZ = sigC - sigZ; + if ( + sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] + ) { + sigZ = (sigZ - 1) | 1; + } + if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { + --expZ; + sigZ <<= 1; + } + goto roundPack; + } else { + sig128C[indexWord( 4, 3 )] = sigC>>32; + sig128C[indexWord( 4, 2 )] = sigC; + sig128C[indexWord( 4, 1 )] = 0; + sig128C[indexWord( 4, 0 )] = 0; + softfloat_sub128M( sig128C, sig128Z, sig128Z ); + } + } else if ( ! expDiff ) { + sigZ -= sigC; + if ( + ! sigZ && ! sig128Z[indexWord( 4, 1 )] + && ! sig128Z[indexWord( 4, 0 )] + ) { + goto completeCancellation; + } + sig128Z[indexWord( 4, 3 )] = sigZ>>32; + sig128Z[indexWord( 4, 2 )] = sigZ; + if ( sigZ & UINT64_C( 0x8000000000000000 ) ) { + signZ ^= 1; + softfloat_negX128M( sig128Z ); + } + } else { + softfloat_sub128M( sig128Z, sig128C, sig128Z ); + if ( 1 < expDiff ) { + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { + --expZ; + sigZ <<= 1; + } + goto sigZ; + } + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + shiftCount = 0; + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + if ( ! sigZ ) { + shiftCount = 64; + sigZ = + (uint64_t) sig128Z[indexWord( 4, 1 )]<<32 + | sig128Z[indexWord( 4, 0 )]; + } + shiftCount += softfloat_countLeadingZeros64( sigZ ) - 1; + if ( shiftCount ) { + expZ -= shiftCount; + softfloat_shiftLeft128M( sig128Z, shiftCount, sig128Z ); + sigZ = + (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 + | sig128Z[indexWord( 4, 2 )]; + } + } + sigZ: + if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1; + roundPack: + return softfloat_roundPackToF64( signZ, expZ - 1, sigZ ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + goto propagateNaN_ZC; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if ( magBits ) { + uiZ = packToF64UI( signZ, 0x7FF, 0 ); + if ( expC != 0x7FF ) goto uiZ; + if ( sigC ) goto propagateNaN_ZC; + if ( signZ == signC ) goto uiZ; + } + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF64UI( uiZ, uiC ); + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ = uiC; + if ( ! (expC | sigC) && (signZ != signC) ) { + completeCancellation: + uiZ = + packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); + } + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c new file mode 100644 index 0000000..8a01edc --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_negXM + +void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ) +{ + unsigned int index, lastIndex; + uint_fast8_t carry; + uint32_t word; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + carry = 1; + for (;;) { + word = ~zPtr[index] + carry; + zPtr[index] = word; + if ( index == lastIndex ) break; + index += wordIncr; + if ( word ) carry = 0; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c new file mode 100644 index 0000000..1547900 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" + +int softfloat_normExtF80SigM( uint64_t *sigPtr ) +{ + uint64_t sig; + int_fast8_t shiftCount; + + sig = *sigPtr; + shiftCount = softfloat_countLeadingZeros64( sig ); + *sigPtr = sig< +#include +#include "platform.h" +#include "internals.h" + +void + softfloat_normRoundPackMToExtF80M( + bool sign, + int32_t exp, + uint32_t *extSigPtr, + uint_fast8_t roundingPrecision, + struct extFloat80M *zSPtr + ) +{ + int_fast16_t shiftCount; + uint32_t wordSig; + + shiftCount = 0; + wordSig = extSigPtr[indexWord( 3, 2 )]; + if ( ! wordSig ) { + shiftCount = 32; + wordSig = extSigPtr[indexWord( 3, 1 )]; + if ( ! wordSig ) { + shiftCount = 64; + wordSig = extSigPtr[indexWord( 3, 0 )]; + if ( ! wordSig ) { + zSPtr->signExp = packToExtF80UI64( sign, 0 ); + zSPtr->signif = 0; + return; + } + } + } + shiftCount += softfloat_countLeadingZeros32( wordSig ); + if ( shiftCount ) { + exp -= shiftCount; + softfloat_shiftLeft96M( extSigPtr, shiftCount, extSigPtr ); + } + softfloat_roundPackMToExtF80M( + sign, exp, extSigPtr, roundingPrecision, zSPtr ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c new file mode 100644 index 0000000..24cd5fb --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" + +void + softfloat_normRoundPackMToF128M( + bool sign, int32_t exp, uint32_t *extSigPtr, uint32_t *zWPtr ) +{ + const uint32_t *ptr; + int_fast16_t shiftCount; + uint32_t wordSig; + + ptr = extSigPtr + indexWordHi( 5 ); + shiftCount = 0; + for (;;) { + wordSig = *ptr; + if ( wordSig ) break; + shiftCount += 32; + if ( 160 <= shiftCount ) { + zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, 0, 0 ); + zWPtr[indexWord( 4, 2 )] = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + return; + } + ptr -= wordIncr; + } + shiftCount += softfloat_countLeadingZeros32( wordSig ) - 15; + if ( shiftCount ) { + exp -= shiftCount; + softfloat_shiftLeft160M( extSigPtr, shiftCount, extSigPtr ); + } + softfloat_roundPackMToF128M( sign, exp, extSigPtr, zWPtr ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c new file mode 100644 index 0000000..e446942 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" + +extFloat80_t + softfloat_normRoundPackToExtF80( + bool sign, + int_fast32_t exp, + uint_fast64_t sig, + uint_fast64_t sigExtra, + uint_fast8_t roundingPrecision + ) +{ + int_fast8_t shiftCount; + struct uint128 sig128; + + if ( ! sig ) { + exp -= 64; + sig = sigExtra; + sigExtra = 0; + } + shiftCount = softfloat_countLeadingZeros64( sig ); + exp -= shiftCount; + if ( shiftCount ) { + sig128 = softfloat_shortShiftLeft128( sig, sigExtra, shiftCount ); + sig = sig128.v64; + sigExtra = sig128.v0; + } + return + softfloat_roundPackToExtF80( + sign, exp, sig, sigExtra, roundingPrecision ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c new file mode 100644 index 0000000..fa293cd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" + +float128_t + softfloat_normRoundPackToF128( + bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0 ) +{ + int_fast8_t shiftCount; + struct uint128 sig128; + union ui128_f128 uZ; + uint_fast64_t sigExtra; + struct uint128_extra sig128Extra; + + if ( ! sig64 ) { + exp -= 64; + sig64 = sig0; + sig0 = 0; + } + shiftCount = softfloat_countLeadingZeros64( sig64 ) - 15; + exp -= shiftCount; + if ( 0 <= shiftCount ) { + if ( shiftCount ) { + sig128 = softfloat_shortShiftLeft128( sig64, sig0, shiftCount ); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + if ( (uint32_t) exp < 0x7FFD ) { + uZ.ui.v64 = packToF128UI64( sign, sig64 | sig0 ? exp : 0, sig64 ); + uZ.ui.v0 = sig0; + return uZ.f; + } + sigExtra = 0; + } else { + sig128Extra = + softfloat_shortShiftRightJam128Extra( + sig64, sig0, 0, -shiftCount ); + sig64 = sig128Extra.v.v64; + sig0 = sig128Extra.v.v0; + sigExtra = sig128Extra.extra; + } + return softfloat_roundPackToF128( sign, exp, sig64, sig0, sigExtra ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c new file mode 100644 index 0000000..8d1d0df --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" + +float32_t + softfloat_normRoundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) +{ + int_fast8_t shiftCount; + union ui32_f32 uZ; + + shiftCount = softfloat_countLeadingZeros32( sig ) - 1; + exp -= shiftCount; + if ( (7 <= shiftCount) && ((uint16_t) exp < 0xFD) ) { + uZ.ui = packToF32UI( sign, sig ? exp : 0, sig<<(shiftCount - 7) ); + return uZ.f; + } else { + return softfloat_roundPackToF32( sign, exp, sig< +#include +#include "platform.h" +#include "internals.h" + +float64_t + softfloat_normRoundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) +{ + int_fast8_t shiftCount; + union ui64_f64 uZ; + + shiftCount = softfloat_countLeadingZeros64( sig ) - 1; + exp -= shiftCount; + if ( (10 <= shiftCount) && ((uint16_t) exp < 0x7FD) ) { + uZ.ui = packToF64UI( sign, sig ? exp : 0, sig<<(shiftCount - 10) ); + return uZ.f; + } else { + return softfloat_roundPackToF64( sign, exp, sig< +#include "platform.h" +#include "internals.h" + +struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t sig ) +{ + int_fast8_t shiftCount; + struct exp32_sig64 z; + + shiftCount = softfloat_countLeadingZeros64( sig ); + z.exp = -shiftCount; + z.sig = sig< +#include "platform.h" +#include "internals.h" + +struct exp32_sig128 + softfloat_normSubnormalF128Sig( uint_fast64_t sig64, uint_fast64_t sig0 ) +{ + int_fast8_t shiftCount; + struct exp32_sig128 z; + + if ( ! sig64 ) { + shiftCount = softfloat_countLeadingZeros64( sig0 ) - 15; + z.exp = -63 - shiftCount; + if ( shiftCount < 0 ) { + z.sig.v64 = sig0>>-shiftCount; + z.sig.v0 = sig0<<(shiftCount & 63); + } else { + z.sig.v64 = sig0< +#include "platform.h" +#include "internals.h" + +int softfloat_normSubnormalF128SigM( uint32_t *sigPtr ) +{ + const uint32_t *ptr; + int_fast16_t shiftCount; + uint32_t wordSig; + + ptr = sigPtr + indexWordHi( 4 ); + shiftCount = 0; + for (;;) { + wordSig = *ptr; + if ( wordSig ) break; + shiftCount += 32; + if ( 128 <= shiftCount ) return 1; + ptr -= wordIncr; + } + shiftCount += softfloat_countLeadingZeros32( wordSig ) - 15; + if ( shiftCount ) softfloat_shiftLeft128M( sigPtr, shiftCount, sigPtr ); + return 1 - shiftCount; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c new file mode 100644 index 0000000..ad69631 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" + +struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig ) +{ + int_fast8_t shiftCount; + struct exp16_sig32 z; + + shiftCount = softfloat_countLeadingZeros32( sig ) - 8; + z.exp = 1 - shiftCount; + z.sig = sig< +#include "platform.h" +#include "internals.h" + +struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig ) +{ + int_fast8_t shiftCount; + struct exp16_sig64 z; + + shiftCount = softfloat_countLeadingZeros64( sig ) - 11; + z.exp = 1 - shiftCount; + z.sig = sig< +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_remStepMBy32 + +void + softfloat_remStepMBy32( + uint_fast8_t size_words, + const uint32_t *remPtr, + uint_fast8_t count, + const uint32_t *bPtr, + uint32_t q, + uint32_t *zPtr + ) +{ + uint_fast8_t negCount; + unsigned int index, lastIndex; + uint64_t dwordProd; + uint32_t wordRem, wordShiftedRem, wordProd; + uint_fast8_t borrow; + + negCount = -count; + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + dwordProd = (uint64_t) bPtr[index] * q; + wordRem = remPtr[index]; + wordShiftedRem = wordRem<>(negCount & 31); + index += wordIncr; + dwordProd = (uint64_t) bPtr[index] * q + (dwordProd>>32); + wordRem = remPtr[index]; + wordShiftedRem |= wordRem< +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +void + softfloat_roundPackMToExtF80M( + bool sign, + int32_t exp, + uint32_t *extSigPtr, + uint_fast8_t roundingPrecision, + struct extFloat80M *zSPtr + ) +{ + uint_fast8_t roundingMode; + bool roundNearEven; + uint64_t sig, roundIncrement, roundMask, roundBits; + bool isTiny; + uint32_t sigExtra; + bool doIncrement; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_roundingMode; + roundNearEven = (roundingMode == softfloat_round_near_even); + sig = + (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 + | extSigPtr[indexWord( 3, 1 )]; + if ( roundingPrecision == 80 ) goto precision80; + if ( roundingPrecision == 64 ) { + roundIncrement = UINT64_C( 0x0000000000000400 ); + roundMask = UINT64_C( 0x00000000000007FF ); + } else if ( roundingPrecision == 32 ) { + roundIncrement = UINT64_C( 0x0000008000000000 ); + roundMask = UINT64_C( 0x000000FFFFFFFFFF ); + } else { + goto precision80; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( extSigPtr[indexWordLo( 3 )] ) sig |= 1; + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + roundIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ? roundMask + : 0; + } + roundBits = sig & roundMask; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x7FFD <= (uint32_t) (exp - 1) ) { + if ( exp <= 0 ) { + isTiny = + (softfloat_detectTininess + == softfloat_tininess_beforeRounding) + || (exp < 0) + || (sig <= (uint64_t) (sig + roundIncrement)); + sig = softfloat_shiftRightJam64( sig, 1 - exp ); + roundBits = sig & roundMask; + if ( roundBits ) { + if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow ); + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + sig += roundIncrement; + exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); + roundIncrement = roundMask + 1; + if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + goto packReturn; + } + if ( + (0x7FFE < exp) + || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig)) + ) { + goto overflow; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; + sig += roundIncrement; + if ( sig < roundIncrement ) { + ++exp; + sig = UINT64_C( 0x8000000000000000 ); + } + roundIncrement = roundMask + 1; + if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + goto packReturn; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + precision80: + sigExtra = extSigPtr[indexWordLo( 3 )]; + doIncrement = (0x80000000 <= sigExtra); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( 0x7FFD <= (uint32_t) (exp - 1) ) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( exp <= 0 ) { + isTiny = + (softfloat_detectTininess + == softfloat_tininess_beforeRounding) + || (exp < 0) + || ! doIncrement + || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF )); + softfloat_shiftRightJam96M( extSigPtr, 1 - exp, extSigPtr ); + sigExtra = extSigPtr[indexWordLo( 3 )]; + if ( sigExtra ) { + if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow ); + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + doIncrement = (0x80000000 <= sigExtra); + if ( + ! roundNearEven + && (roundingMode != softfloat_round_near_maxMag) + ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + exp = 0; + sig = + (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 + | extSigPtr[indexWord( 3, 1 )]; + if ( doIncrement ) { + ++sig; + sig &= ~(uint64_t) (! (sigExtra & 0x7FFFFFFF) & roundNearEven); + exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); + } + goto packReturn; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if ( + (0x7FFE < exp) + || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF )) + && doIncrement) + ) { + roundMask = 0; + overflow: + softfloat_raiseFlags( + softfloat_flag_overflow | softfloat_flag_inexact ); + if ( + roundNearEven + || (roundingMode == softfloat_round_near_maxMag) + || (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ) { + exp = 0x7FFF; + sig = UINT64_C( 0x8000000000000000 ); + } else { + exp = 0x7FFE; + sig = ~roundMask; + } + goto packReturn; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; + if ( doIncrement ) { + ++sig; + if ( ! sig ) { + ++exp; + sig = UINT64_C( 0x8000000000000000 ); + } else { + sig &= ~(uint64_t) (! (sigExtra & 0x7FFFFFFF) & roundNearEven); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + packReturn: + zSPtr->signExp = packToExtF80UI64( sign, exp ); + zSPtr->signif = sig; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c new file mode 100644 index 0000000..91b750f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +void + softfloat_roundPackMToF128M( + bool sign, int32_t exp, uint32_t *extSigPtr, uint32_t *zWPtr ) +{ + uint_fast8_t roundingMode; + bool roundNearEven; + uint32_t sigExtra; + bool doIncrement, isTiny; + static const uint32_t maxSig[4] = + INIT_UINTM4( 0x0001FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ); + uint32_t ui, uj; + + roundingMode = softfloat_roundingMode; + roundNearEven = (roundingMode == softfloat_round_near_even); + sigExtra = extSigPtr[indexWordLo( 5 )]; + doIncrement = (0x80000000 <= sigExtra); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + if ( 0x7FFD <= (uint32_t) exp ) { + if ( exp < 0 ) { + isTiny = + (softfloat_detectTininess + == softfloat_tininess_beforeRounding) + || (exp < -1) + || ! doIncrement + || (softfloat_compare128M( + extSigPtr + indexMultiwordHi( 5, 4 ), maxSig ) + < 0); + softfloat_shiftRightJam160M( extSigPtr, -exp, extSigPtr ); + exp = 0; + sigExtra = extSigPtr[indexWordLo( 5 )]; + if ( isTiny && sigExtra ) { + softfloat_raiseFlags( softfloat_flag_underflow ); + } + doIncrement = (0x80000000 <= sigExtra); + if ( + ! roundNearEven + && (roundingMode != softfloat_round_near_maxMag) + ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + } else if ( + (0x7FFD < exp) + || ((exp == 0x7FFD) && doIncrement + && (softfloat_compare128M( + extSigPtr + indexMultiwordHi( 5, 4 ), maxSig ) + == 0)) + ) { + softfloat_raiseFlags( + softfloat_flag_overflow | softfloat_flag_inexact ); + if ( + roundNearEven + || (roundingMode == softfloat_round_near_maxMag) + || (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ) { + ui = packToF128UI96( sign, 0x7FFF, 0 ); + uj = 0; + } else { + ui = packToF128UI96( sign, 0x7FFE, 0x0000FFFF ); + uj = 0xFFFFFFFF; + } + zWPtr[indexWordHi( 4 )] = ui; + zWPtr[indexWord( 4, 2 )] = uj; + zWPtr[indexWord( 4, 1 )] = uj; + zWPtr[indexWord( 4, 0 )] = uj; + return; + } + } + if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; + uj = extSigPtr[indexWord( 5, 1 )]; + if ( doIncrement ) { + ++uj; + if ( uj ) { + if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) uj &= ~1; + zWPtr[indexWord( 4, 2 )] = extSigPtr[indexWord( 5, 3 )]; + zWPtr[indexWord( 4, 1 )] = extSigPtr[indexWord( 5, 2 )]; + zWPtr[indexWord( 4, 0 )] = uj; + ui = extSigPtr[indexWordHi( 5 )]; + } else { + zWPtr[indexWord( 4, 0 )] = uj; + ui = extSigPtr[indexWord( 5, 2 )] + 1; + zWPtr[indexWord( 4, 1 )] = ui; + uj = extSigPtr[indexWord( 5, 3 )]; + if ( ui ) { + zWPtr[indexWord( 4, 2 )] = uj; + ui = extSigPtr[indexWordHi( 5 )]; + } else { + ++uj; + zWPtr[indexWord( 4, 2 )] = uj; + ui = extSigPtr[indexWordHi( 5 )]; + if ( ! uj ) ++ui; + } + } + } else { + zWPtr[indexWord( 4, 0 )] = uj; + ui = extSigPtr[indexWord( 5, 2 )]; + zWPtr[indexWord( 4, 1 )] = ui; + uj |= ui; + ui = extSigPtr[indexWord( 5, 3 )]; + zWPtr[indexWord( 4, 2 )] = ui; + uj |= ui; + ui = extSigPtr[indexWordHi( 5 )]; + uj |= ui; + if ( ! uj ) exp = 0; + } + zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp, ui ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c new file mode 100644 index 0000000..196b268 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t + softfloat_roundPackMToI64( + bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact ) +{ + bool roundNearEven; + uint32_t sigExtra; + bool doIncrement; + uint64_t sig; + union { uint64_t ui; int64_t i; } uZ; + int64_t z; + + roundNearEven = (roundingMode == softfloat_round_near_even); + sigExtra = extSigPtr[indexWordLo( 3 )]; + doIncrement = (0x80000000 <= sigExtra); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + sig = + (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 + | extSigPtr[indexWord( 3, 1 )]; + if ( doIncrement ) { + ++sig; + if ( ! sig ) goto invalid; + if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) sig &= ~1; + } + uZ.ui = sign ? -sig : sig; + z = uZ.i; + if ( z && ((z < 0) ^ sign) ) goto invalid; + if ( exact && sigExtra ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return + sign ? -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 + : INT64_C( 0x7FFFFFFFFFFFFFFF ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c new file mode 100644 index 0000000..033baee --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t + softfloat_roundPackMToUI64( + bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact ) +{ + bool roundNearEven; + uint32_t sigExtra; + bool doIncrement; + uint64_t sig; + + roundNearEven = (roundingMode == softfloat_round_near_even); + sigExtra = extSigPtr[indexWordLo( 3 )]; + doIncrement = (0x80000000 <= sigExtra); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + sig = + (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 + | extSigPtr[indexWord( 3, 1 )]; + if ( doIncrement ) { + ++sig; + if ( ! sig ) goto invalid; + if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) sig &= ~1; + } + if ( sign && sig ) goto invalid; + if ( exact && sigExtra ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return sig; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c new file mode 100644 index 0000000..77c6c69 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +extFloat80_t + softfloat_roundPackToExtF80( + bool sign, + int_fast32_t exp, + uint_fast64_t sig, + uint_fast64_t sigExtra, + uint_fast8_t roundingPrecision + ) +{ + uint_fast8_t roundingMode; + bool roundNearEven; + uint_fast64_t roundIncrement, roundMask, roundBits; + bool isTiny, doIncrement; + struct uint64_extra sig64Extra; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + roundingMode = softfloat_roundingMode; + roundNearEven = (roundingMode == softfloat_round_near_even); + if ( roundingPrecision == 80 ) goto precision80; + if ( roundingPrecision == 64 ) { + roundIncrement = UINT64_C( 0x0000000000000400 ); + roundMask = UINT64_C( 0x00000000000007FF ); + } else if ( roundingPrecision == 32 ) { + roundIncrement = UINT64_C( 0x0000008000000000 ); + roundMask = UINT64_C( 0x000000FFFFFFFFFF ); + } else { + goto precision80; + } + sig |= (sigExtra != 0); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + roundIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ? roundMask + : 0; + } + roundBits = sig & roundMask; + if ( 0x7FFD <= (uint32_t) (exp - 1) ) { + if ( exp <= 0 ) { + isTiny = + (softfloat_detectTininess + == softfloat_tininess_beforeRounding) + || (exp < 0) + || (sig <= (uint64_t) (sig + roundIncrement)); + sig = softfloat_shiftRightJam64( sig, 1 - exp ); + roundBits = sig & roundMask; + if ( isTiny && roundBits ) { + softfloat_raiseFlags( softfloat_flag_underflow ); + } + if ( roundBits ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + sig += roundIncrement; + exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); + roundIncrement = roundMask + 1; + if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + goto packReturn; + } + if ( + (0x7FFE < exp) + || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig)) + ) { + goto overflow; + } + } + if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; + sig = (uint64_t) (sig + roundIncrement); + if ( sig < roundIncrement ) { + ++exp; + sig = UINT64_C( 0x8000000000000000 ); + } + roundIncrement = roundMask + 1; + if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + if ( ! sig ) exp = 0; + goto packReturn; + precision80: + doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + if ( 0x7FFD <= (uint32_t) (exp - 1) ) { + if ( exp <= 0 ) { + isTiny = + (softfloat_detectTininess + == softfloat_tininess_beforeRounding) + || (exp < 0) + || ! doIncrement + || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF )); + sig64Extra = + softfloat_shiftRightJam64Extra( sig, sigExtra, 1 - exp ); + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + if ( isTiny && sigExtra ) { + softfloat_raiseFlags( softfloat_flag_underflow ); + } + if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; + doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); + if ( + ! roundNearEven + && (roundingMode != softfloat_round_near_maxMag) + ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + exp = 0; + if ( doIncrement ) { + ++sig; + sig &= + ~(uint_fast64_t) + (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + & roundNearEven); + exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); + } + goto packReturn; + } + if ( + (0x7FFE < exp) + || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF )) + && doIncrement) + ) { + roundMask = 0; + overflow: + softfloat_raiseFlags( + softfloat_flag_overflow | softfloat_flag_inexact ); + if ( + roundNearEven + || (roundingMode == softfloat_round_near_maxMag) + || (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ) { + exp = 0x7FFF; + sig = UINT64_C( 0x8000000000000000 ); + } else { + exp = 0x7FFE; + sig = ~roundMask; + } + goto packReturn; + } + } + if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; + if ( doIncrement ) { + ++sig; + if ( ! sig ) { + ++exp; + sig = UINT64_C( 0x8000000000000000 ); + } else { + sig &= + ~(uint_fast64_t) + (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + & roundNearEven); + } + } else { + if ( ! sig ) exp = 0; + } + packReturn: + uZ.s.signExp = packToExtF80UI64( sign, exp ); + uZ.s.signif = sig; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c new file mode 100644 index 0000000..3d76da2 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float128_t + softfloat_roundPackToF128( + bool sign, + int_fast32_t exp, + uint_fast64_t sig64, + uint_fast64_t sig0, + uint_fast64_t sigExtra + ) +{ + uint_fast8_t roundingMode; + bool roundNearEven, doIncrement, isTiny; + struct uint128_extra sig128Extra; + uint_fast64_t uiZ64, uiZ0; + struct uint128 sig128; + union ui128_f128 uZ; + + roundingMode = softfloat_roundingMode; + roundNearEven = (roundingMode == softfloat_round_near_even); + doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + if ( 0x7FFD <= (uint32_t) exp ) { + if ( exp < 0 ) { + isTiny = + (softfloat_detectTininess + == softfloat_tininess_beforeRounding) + || (exp < -1) + || ! doIncrement + || softfloat_lt128( + sig64, + sig0, + UINT64_C( 0x0001FFFFFFFFFFFF ), + UINT64_C( 0xFFFFFFFFFFFFFFFF ) + ); + sig128Extra = + softfloat_shiftRightJam128Extra( sig64, sig0, sigExtra, -exp ); + sig64 = sig128Extra.v.v64; + sig0 = sig128Extra.v.v0; + sigExtra = sig128Extra.extra; + exp = 0; + if ( isTiny && sigExtra ) { + softfloat_raiseFlags( softfloat_flag_underflow ); + } + doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); + if ( + ! roundNearEven + && (roundingMode != softfloat_round_near_maxMag) + ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + } else if ( + (0x7FFD < exp) + || ((exp == 0x7FFD) + && softfloat_eq128( + sig64, + sig0, + UINT64_C( 0x0001FFFFFFFFFFFF ), + UINT64_C( 0xFFFFFFFFFFFFFFFF ) + ) + && doIncrement) + ) { + softfloat_raiseFlags( + softfloat_flag_overflow | softfloat_flag_inexact ); + if ( + roundNearEven + || (roundingMode == softfloat_round_near_maxMag) + || (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ) { + uiZ64 = packToF128UI64( sign, 0x7FFF, 0 ); + uiZ0 = 0; + } else { + uiZ64 = + packToF128UI64( + sign, 0x7FFE, UINT64_C( 0x0000FFFFFFFFFFFF ) ); + uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF ); + } + goto uiZ; + } + } + if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; + if ( doIncrement ) { + sig128 = softfloat_add128( sig64, sig0, 0, 1 ); + sig64 = sig128.v64; + sig0 = + sig128.v0 + & ~(uint64_t) + (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + & roundNearEven); + } else { + if ( ! (sig64 | sig0) ) exp = 0; + } + uiZ64 = packToF128UI64( sign, exp, sig64 ); + uiZ0 = sig0; + uiZ: + uZ.ui.v64 = uiZ64; + uZ.ui.v0 = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c new file mode 100644 index 0000000..bc27915 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t + softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) +{ + uint_fast8_t roundingMode; + bool roundNearEven; + uint_fast8_t roundIncrement, roundBits; + bool isTiny; + uint_fast32_t uiZ; + union ui32_f32 uZ; + + roundingMode = softfloat_roundingMode; + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x40; + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + roundIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ? 0x7F + : 0; + } + roundBits = sig & 0x7F; + if ( 0xFD <= (uint16_t) exp ) { + if ( exp < 0 ) { + isTiny = + (softfloat_detectTininess + == softfloat_tininess_beforeRounding) + || (exp < -1) + || (sig + roundIncrement < 0x80000000); + sig = softfloat_shiftRightJam32( sig, -exp ); + exp = 0; + roundBits = sig & 0x7F; + if ( isTiny && roundBits ) { + softfloat_raiseFlags( softfloat_flag_underflow ); + } + } else if ( (0xFD < exp) || (0x80000000 <= sig + roundIncrement) ) { + softfloat_raiseFlags( + softfloat_flag_overflow | softfloat_flag_inexact ); + uiZ = packToF32UI( sign, 0xFF, 0 ) - ! roundIncrement; + goto uiZ; + } + } + if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; + sig = (sig + roundIncrement)>>7; + sig &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven); + uiZ = packToF32UI( sign, sig ? exp : 0, sig ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c new file mode 100644 index 0000000..b0d96ce --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t + softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) +{ + uint_fast8_t roundingMode; + bool roundNearEven; + uint_fast16_t roundIncrement, roundBits; + bool isTiny; + uint_fast64_t uiZ; + union ui64_f64 uZ; + + roundingMode = softfloat_roundingMode; + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x200; + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + roundIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ? 0x3FF + : 0; + } + roundBits = sig & 0x3FF; + if ( 0x7FD <= (uint16_t) exp ) { + if ( exp < 0 ) { + isTiny = + (softfloat_detectTininess + == softfloat_tininess_beforeRounding) + || (exp < -1) + || (sig + roundIncrement < UINT64_C( 0x8000000000000000 )); + sig = softfloat_shiftRightJam64( sig, -exp ); + exp = 0; + roundBits = sig & 0x3FF; + if ( isTiny && roundBits ) { + softfloat_raiseFlags( softfloat_flag_underflow ); + } + } else if ( + (0x7FD < exp) + || (UINT64_C( 0x8000000000000000 ) <= sig + roundIncrement) + ) { + softfloat_raiseFlags( + softfloat_flag_overflow | softfloat_flag_inexact ); + uiZ = packToF64UI( sign, 0x7FF, 0 ) - ! roundIncrement; + goto uiZ; + } + } + if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; + sig = (sig + roundIncrement)>>10; + sig &= ~(uint_fast64_t) (! (roundBits ^ 0x200) & roundNearEven); + uiZ = packToF64UI( sign, sig ? exp : 0, sig ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.c new file mode 100644 index 0000000..9b23223 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast32_t + softfloat_roundPackToI32( + bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact ) +{ + bool roundNearEven; + uint_fast8_t roundIncrement, roundBits; + uint_fast32_t sig32; + union { uint32_t ui; int32_t i; } uZ; + int_fast32_t z; + + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x40; + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + roundIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ? 0x7F + : 0; + } + roundBits = sig & 0x7F; + sig += roundIncrement; + if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; + sig32 = sig>>7; + sig32 &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven); + uZ.ui = sign ? -sig32 : sig32; + z = uZ.i; + if ( z && ((z < 0) ^ sign) ) goto invalid; + if ( exact && roundBits ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return sign ? -0x7FFFFFFF - 1 : 0x7FFFFFFF; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c new file mode 100644 index 0000000..52c2a35 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +int_fast64_t + softfloat_roundPackToI64( + bool sign, + uint_fast64_t sig, + uint_fast64_t sigExtra, + uint_fast8_t roundingMode, + bool exact + ) +{ + bool roundNearEven, doIncrement; + union { uint64_t ui; int64_t i; } uZ; + int_fast64_t z; + + roundNearEven = (roundingMode == softfloat_round_near_even); + doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + if ( doIncrement ) { + ++sig; + if ( ! sig ) goto invalid; + sig &= + ~(uint_fast64_t) + (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + & roundNearEven); + } + uZ.ui = sign ? -sig : sig; + z = uZ.i; + if ( z && ((z < 0) ^ sign) ) goto invalid; + if ( exact && sigExtra ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return + sign ? -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 + : INT64_C( 0x7FFFFFFFFFFFFFFF ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c new file mode 100644 index 0000000..613a28e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast32_t + softfloat_roundPackToUI32( + bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact ) +{ + bool roundNearEven; + uint_fast8_t roundIncrement, roundBits; + uint_fast32_t z; + + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x40; + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + roundIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + ? 0x7F + : 0; + } + roundBits = sig & 0x7F; + sig += roundIncrement; + if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; + z = sig>>7; + z &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven); + if ( sign && z ) goto invalid; + if ( exact && roundBits ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return z; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return 0xFFFFFFFF; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c new file mode 100644 index 0000000..5a82b8c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +uint_fast64_t + softfloat_roundPackToUI64( + bool sign, + uint_fast64_t sig, + uint_fast64_t sigExtra, + uint_fast8_t roundingMode, + bool exact + ) +{ + bool roundNearEven, doIncrement; + + roundNearEven = (roundingMode == softfloat_round_near_even); + doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); + if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { + doIncrement = + (roundingMode + == (sign ? softfloat_round_min : softfloat_round_max)) + && sigExtra; + } + if ( doIncrement ) { + ++sig; + if ( ! sig ) goto invalid; + sig &= + ~(uint_fast64_t) + (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) + & roundNearEven); + } + if ( sign && sig ) goto invalid; + if ( exact && sigExtra ) { + softfloat_exceptionFlags |= softfloat_flag_inexact; + } + return sig; + invalid: + softfloat_raiseFlags( softfloat_flag_invalid ); + return UINT64_C( 0xFFFFFFFFFFFFFFFF ); + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c new file mode 100644 index 0000000..f80f29c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_shiftLeftM + +#define softfloat_shiftLeftM softfloat_shiftLeftM +#include "primitives.h" + +void + softfloat_shiftLeftM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t count, + uint32_t *zPtr + ) +{ + uint32_t wordCount; + uint_fast8_t innerCount; + uint32_t *destPtr; + uint_fast8_t i; + + wordCount = count>>5; + if ( wordCount < size_words ) { + aPtr += indexMultiwordLoBut( size_words, wordCount ); + innerCount = count & 31; + if ( innerCount ) { + softfloat_shortShiftLeftM( + size_words - wordCount, + aPtr, + innerCount, + zPtr + indexMultiwordHiBut( size_words, wordCount ) + ); + if ( ! wordCount ) return; + } else { + aPtr += indexWordHi( size_words - wordCount ); + destPtr = zPtr + indexWordHi( size_words ); + for ( i = size_words - wordCount; i; --i ) { + *destPtr = *aPtr; + aPtr -= wordIncr; + destPtr -= wordIncr; + } + } + zPtr += indexMultiwordLo( size_words, wordCount ); + } else { + wordCount = size_words; + } + do { + *zPtr++ = 0; + --wordCount; + } while ( wordCount ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c new file mode 100644 index 0000000..ea68d60 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" + +int + softfloat_shiftNormSigF128M( + const uint32_t *wPtr, uint_fast8_t shiftCount, uint32_t *sigPtr ) +{ + uint32_t wordSig; + int32_t exp; + uint32_t leadingBit; + + wordSig = wPtr[indexWordHi( 4 )]; + exp = expF128UI96( wordSig ); + if ( exp ) { + softfloat_shortShiftLeft128M( wPtr, shiftCount, sigPtr ); + leadingBit = 0x00010000< +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shiftRightJam128 + +struct uint128 + softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t count ) +{ + int_fast32_t negCount; + struct uint128 z; + + if ( count < 64 ) { + negCount = -count; + z.v64 = a64>>count; + z.v0 = + a64<<(negCount & 63) | a0>>count + | ((uint64_t) (a0<<(negCount & 63)) != 0); + } else { + z.v64 = 0; + z.v0 = + (count < 127) + ? a64>>(count & 63) + | (((a64 & (((uint_fast64_t) 1<<(count & 63)) - 1)) | a0) + != 0) + : ((a64 | a0) != 0); + } + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c new file mode 100644 index 0000000..b322924 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shiftRightJam128Extra + +struct uint128_extra + softfloat_shiftRightJam128Extra( + uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t count ) +{ + int_fast32_t negCount; + struct uint128_extra z; + + negCount = -count; + if ( count < 64 ) { + z.v.v64 = a64>>count; + z.v.v0 = a64<<(negCount & 63) | a0>>count; + z.extra = a0<<(negCount & 63); + } else { + z.v.v64 = 0; + if ( count == 64 ) { + z.v.v0 = a64; + z.extra = a0; + } else { + extra |= a0; + if ( count < 128 ) { + z.v.v0 = a64>>(count & 63); + z.extra = a64<<(negCount & 63); + } else { + z.v.v0 = 0; + z.extra = (count == 128) ? a64 : (a64 != 0); + } + } + } + z.extra |= (extra != 0); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c new file mode 100644 index 0000000..965fb33 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shiftRightJam256M + +static + void + softfloat_shortShiftRightJamM( + uint_fast8_t size_words, + const uint64_t *aPtr, + uint_fast8_t count, + uint64_t *zPtr + ) +{ + uint_fast8_t negCount; + unsigned int index, lastIndex; + uint64_t partWordZ, wordA; + + negCount = -count; + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + wordA = aPtr[index]; + partWordZ = wordA>>count; + if ( partWordZ<>count; + } + zPtr[index] = partWordZ; + +} + +void + softfloat_shiftRightJam256M( + const uint64_t *aPtr, uint_fast32_t count, uint64_t *zPtr ) +{ + uint64_t wordJam; + uint_fast32_t wordCount; + uint64_t *ptr; + uint_fast8_t i, innerCount; + + wordJam = 0; + wordCount = count>>6; + if ( wordCount ) { + if ( 4 < wordCount ) wordCount = 4; + ptr = (uint64_t *) (aPtr + indexMultiwordLo( 4, wordCount )); + i = wordCount; + do { + wordJam = *ptr++; + if ( wordJam ) break; + --i; + } while ( i ); + ptr = zPtr; + } + if ( wordCount < 4 ) { + aPtr += indexMultiwordHiBut( 4, wordCount ); + innerCount = count & 63; + if ( innerCount ) { + softfloat_shortShiftRightJamM( + 4 - wordCount, + aPtr, + innerCount, + zPtr + indexMultiwordLoBut( 4, wordCount ) + ); + if ( ! wordCount ) goto wordJam; + } else { + aPtr += indexWordLo( 4 - wordCount ); + ptr = zPtr + indexWordLo( 4 ); + for ( i = 4 - wordCount; i; --i ) { + *ptr = *aPtr; + aPtr += wordIncr; + ptr += wordIncr; + } + } + ptr = zPtr + indexMultiwordHi( 4, wordCount ); + } + do { + *ptr++ = 0; + --wordCount; + } while ( wordCount ); + wordJam: + if ( wordJam ) zPtr[indexWordLo( 4 )] |= 1; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c new file mode 100644 index 0000000..44c1f2f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_shiftRightJam32 + +uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t count ) +{ + + return + (count < 31) ? a>>count | ((uint32_t) (a<<(-count & 31)) != 0) + : (a != 0); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c new file mode 100644 index 0000000..9387887 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_shiftRightJam64 + +uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t count ) +{ + + return + (count < 63) ? a>>count | ((uint64_t) (a<<(-count & 63)) != 0) + : (a != 0); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c new file mode 100644 index 0000000..e656a3f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shiftRightJam64Extra + +struct uint64_extra + softfloat_shiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast32_t count ) +{ + struct uint64_extra z; + + if ( count < 64 ) { + z.v = a>>count; + z.extra = a<<(-count & 63); + } else { + z.v = 0; + z.extra = (count == 64) ? a : (a != 0); + } + z.extra |= (extra != 0); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c new file mode 100644 index 0000000..ef394bd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_shiftRightJamM + +#define softfloat_shiftRightJamM softfloat_shiftRightJamM +#include "primitives.h" + +void + softfloat_shiftRightJamM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t count, + uint32_t *zPtr + ) +{ + uint32_t wordJam, wordCount, *ptr; + uint_fast8_t i, innerCount; + + wordJam = 0; + wordCount = count>>5; + if ( wordCount ) { + if ( size_words < wordCount ) wordCount = size_words; + ptr = (uint32_t *) (aPtr + indexMultiwordLo( size_words, wordCount )); + i = wordCount; + do { + wordJam = *ptr++; + if ( wordJam ) break; + --i; + } while ( i ); + ptr = zPtr; + } + if ( wordCount < size_words ) { + aPtr += indexMultiwordHiBut( size_words, wordCount ); + innerCount = count & 31; + if ( innerCount ) { + softfloat_shortShiftRightJamM( + size_words - wordCount, + aPtr, + innerCount, + zPtr + indexMultiwordLoBut( size_words, wordCount ) + ); + if ( ! wordCount ) goto wordJam; + } else { + aPtr += indexWordLo( size_words - wordCount ); + ptr = zPtr + indexWordLo( size_words ); + for ( i = size_words - wordCount; i; --i ) { + *ptr = *aPtr; + aPtr += wordIncr; + ptr += wordIncr; + } + } + ptr = zPtr + indexMultiwordHi( size_words, wordCount ); + } + do { + *ptr++ = 0; + --wordCount; + } while ( wordCount ); + wordJam: + if ( wordJam ) zPtr[indexWordLo( size_words )] |= 1; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c new file mode 100644 index 0000000..50b35e4 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_shiftRightM + +#define softfloat_shiftRightM softfloat_shiftRightM +#include "primitives.h" + +void + softfloat_shiftRightM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint32_t count, + uint32_t *zPtr + ) +{ + uint32_t wordCount; + uint_fast8_t innerCount; + uint32_t *destPtr; + uint_fast8_t i; + + wordCount = count>>5; + if ( wordCount < size_words ) { + aPtr += indexMultiwordHiBut( size_words, wordCount ); + innerCount = count & 31; + if ( innerCount ) { + softfloat_shortShiftRightM( + size_words - wordCount, + aPtr, + innerCount, + zPtr + indexMultiwordLoBut( size_words, wordCount ) + ); + if ( ! wordCount ) return; + } else { + aPtr += indexWordLo( size_words - wordCount ); + destPtr = zPtr + indexWordLo( size_words ); + for ( i = size_words - wordCount; i; --i ) { + *destPtr = *aPtr; + aPtr += wordIncr; + destPtr += wordIncr; + } + } + zPtr += indexMultiwordHi( size_words, wordCount ); + } else { + wordCount = size_words; + } + do { + *zPtr++ = 0; + --wordCount; + } while ( wordCount ); + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c new file mode 100644 index 0000000..4af115d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftLeft128 + +struct uint128 + softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t count ) +{ + struct uint128 z; + + z.v64 = a64<>(-count & 63); + z.v0 = a0< +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftLeft64To96M + +void + softfloat_shortShiftLeft64To96M( + uint64_t a, uint_fast8_t count, uint32_t *zPtr ) +{ + + zPtr[indexWord( 3, 0 )] = (uint32_t) a<>= 32 - count; + zPtr[indexWord( 3, 2 )] = a>>32; + zPtr[indexWord( 3, 1 )] = a; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c new file mode 100644 index 0000000..01e97c7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftLeftM + +void + softfloat_shortShiftLeftM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t count, + uint32_t *zPtr + ) +{ + uint_fast8_t negCount; + unsigned int index, lastIndex; + uint32_t partWordZ, wordA; + + negCount = -count; + index = indexWordHi( size_words ); + lastIndex = indexWordLo( size_words ); + partWordZ = aPtr[index]<>(negCount & 31); + index -= wordIncr; + partWordZ = wordA< +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRight128 + +struct uint128 + softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t count ) +{ + struct uint128 z; + + z.v64 = a64>>count; + z.v0 = a64<<(-count & 63) | a0>>count; + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c new file mode 100644 index 0000000..38b6fcd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightExtendM + +void + softfloat_shortShiftRightExtendM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t count, + uint32_t *zPtr + ) +{ + uint_fast8_t negCount; + unsigned int indexA, lastIndexA; + uint32_t partWordZ, wordA; + + negCount = -count; + indexA = indexWordLo( size_words ); + lastIndexA = indexWordHi( size_words ); + zPtr += indexWordLo( size_words + 1 ); + partWordZ = 0; + for (;;) { + wordA = aPtr[indexA]; + *zPtr = wordA<<(negCount & 31) | partWordZ; + zPtr += wordIncr; + partWordZ = wordA>>count; + if ( indexA == lastIndexA ) break; + indexA += wordIncr; + } + *zPtr = partWordZ; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c new file mode 100644 index 0000000..ea630e6 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightJam128 + +struct uint128 + softfloat_shortShiftRightJam128( + uint64_t a64, uint64_t a0, uint_fast8_t count ) +{ + int_fast8_t negCount; + struct uint128 z; + + negCount = -count; + z.v64 = a64>>count; + z.v0 = + a64<<(negCount & 63) | a0>>count + | ((uint64_t) (a0<<(negCount & 63)) != 0); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c new file mode 100644 index 0000000..0bdc6b6 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightJam128Extra + +struct uint128_extra + softfloat_shortShiftRightJam128Extra( + uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t count ) +{ + uint_fast8_t negCount; + struct uint128_extra z; + + negCount = -count; + z.v.v64 = a64>>count; + z.v.v0 = a64<<(negCount & 63) | a0>>count; + z.extra = a0<<(negCount & 63) | (extra != 0); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c new file mode 100644 index 0000000..8f6b042 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" + +#ifndef softfloat_shortShiftRightJam64 + +uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t count ) +{ + + return a>>count | ((a & (((uint_fast64_t) 1< +#include "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightJam64Extra + +struct uint64_extra + softfloat_shortShiftRightJam64Extra( + uint64_t a, uint64_t extra, uint_fast8_t count ) +{ + struct uint64_extra z; + + z.v = a>>count; + z.extra = a<<(-count & 63) | (extra != 0); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c new file mode 100644 index 0000000..96ff2ab --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightJamM + +void + softfloat_shortShiftRightJamM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t count, + uint32_t *zPtr + ) +{ + uint_fast8_t negCount; + unsigned int index, lastIndex; + uint32_t partWordZ, wordA; + + negCount = -count; + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + wordA = aPtr[index]; + partWordZ = wordA>>count; + if ( partWordZ<>count; + } + zPtr[index] = partWordZ; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c new file mode 100644 index 0000000..2563d28 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_shortShiftRightM + +void + softfloat_shortShiftRightM( + uint_fast8_t size_words, + const uint32_t *aPtr, + uint_fast8_t count, + uint32_t *zPtr + ) +{ + uint_fast8_t negCount; + unsigned int index, lastIndex; + uint32_t partWordZ, wordA; + + negCount = -count; + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + partWordZ = aPtr[index]>>count; + while ( index != lastIndex ) { + wordA = aPtr[index + wordIncr]; + zPtr[index] = wordA<<(negCount & 31) | partWordZ; + index += wordIncr; + partWordZ = wordA>>count; + } + zPtr[index] = partWordZ; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c new file mode 100644 index 0000000..fb6000b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_sub128 + +struct uint128 + softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) +{ + struct uint128 z; + + z.v0 = a0 - b0; + z.v64 = a64 - b64 - (a0 < b0); + return z; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c new file mode 100644 index 0000000..492a0b2 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_sub1XM + +void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ) +{ + unsigned int index, lastIndex; + uint32_t wordA; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + for (;;) { + wordA = zPtr[index]; + zPtr[index] = wordA - 1; + if ( wordA || (index == lastIndex) ) break; + index += wordIncr; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c new file mode 100644 index 0000000..06fe75e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_sub256M + +void + softfloat_sub256M( + const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ) +{ + unsigned int index; + uint_fast8_t borrow; + uint64_t wordA, wordB; + + index = indexWordLo( 4 ); + borrow = 0; + for (;;) { + wordA = aPtr[index]; + wordB = bPtr[index]; + zPtr[index] = wordA - wordB - borrow; + if ( index == indexWordHi( 4 ) ) break; + borrow = borrow ? (wordA <= wordB) : (wordA < wordB); + index += wordIncr; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c new file mode 100644 index 0000000..3dfe355 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 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 "platform.h" +#include "primitiveTypes.h" + +#ifndef softfloat_subM + +void + softfloat_subM( + uint_fast8_t size_words, + const uint32_t *aPtr, + const uint32_t *bPtr, + uint32_t *zPtr + ) +{ + unsigned int index, lastIndex; + uint_fast8_t borrow; + uint32_t wordA, wordB; + + index = indexWordLo( size_words ); + lastIndex = indexWordHi( size_words ); + borrow = 0; + for (;;) { + wordA = aPtr[index]; + wordB = bPtr[index]; + zPtr[index] = wordA - wordB - borrow; + if ( index == lastIndex ) break; + borrow = borrow ? (wordA <= wordB) : (wordA < wordB); + index += wordIncr; + } + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c new file mode 100644 index 0000000..bc0e612 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t + softfloat_subMagsExtF80( + uint_fast16_t uiA64, + uint_fast64_t uiA0, + uint_fast16_t uiB64, + uint_fast64_t uiB0, + bool signZ + ) +{ + int_fast32_t expA; + uint_fast64_t sigA; + int_fast32_t expB; + uint_fast64_t sigB; + int_fast32_t expDiff; + uint_fast16_t uiZ64; + uint_fast64_t uiZ0; + int_fast32_t expZ; + uint_fast64_t sigExtra; + struct uint128 sig128, uiZ; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expExtF80UI64( uiA64 ); + sigA = uiA0; + expB = expExtF80UI64( uiB64 ); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if ( 0 < expDiff ) goto expABigger; + if ( expDiff < 0 ) goto expBBigger; + if ( expA == 0x7FFF ) { + if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { + goto propagateNaN; + } + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ64 = defaultNaNExtF80UI64; + uiZ0 = defaultNaNExtF80UI0; + goto uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA; + if ( ! expZ ) expZ = 1; + sigExtra = 0; + if ( sigB < sigA ) goto aBigger; + if ( sigA < sigB ) goto bBigger; + uiZ64 = + packToExtF80UI64( (softfloat_roundingMode == softfloat_round_min), 0 ); + uiZ0 = 0; + goto uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expBBigger: + if ( expB == 0x7FFF ) { + if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + uiZ64 = packToExtF80UI64( signZ ^ 1, 0x7FFF ); + uiZ0 = UINT64_C( 0x8000000000000000 ); + goto uiZ; + } + if ( ! expA ) { + ++expDiff; + sigExtra = 0; + if ( ! expDiff ) goto newlyAlignedBBigger; + } + sig128 = softfloat_shiftRightJam128( sigA, 0, -expDiff ); + sigA = sig128.v64; + sigExtra = sig128.v0; + newlyAlignedBBigger: + expZ = expB; + bBigger: + signZ ^= 1; + sig128 = softfloat_sub128( sigB, 0, sigA, sigExtra ); + goto normRoundPack; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expABigger: + if ( expA == 0x7FFF ) { + if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; + uiZ64 = uiA64; + uiZ0 = uiA0; + goto uiZ; + } + if ( ! expB ) { + --expDiff; + sigExtra = 0; + if ( ! expDiff ) goto newlyAlignedABigger; + } + sig128 = softfloat_shiftRightJam128( sigB, 0, expDiff ); + sigB = sig128.v64; + sigExtra = sig128.v0; + newlyAlignedABigger: + expZ = expA; + aBigger: + sig128 = softfloat_sub128( sigA, 0, sigB, sigExtra ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + normRoundPack: + return + softfloat_normRoundPackToExtF80( + signZ, expZ, sig128.v64, sig128.v0, extF80_roundingPrecision ); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + uiZ: + uZ.s.signExp = uiZ64; + uZ.s.signif = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c new file mode 100644 index 0000000..92c13b7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t + softfloat_subMagsF128( + uint_fast64_t uiA64, + uint_fast64_t uiA0, + uint_fast64_t uiB64, + uint_fast64_t uiB0, + bool signZ + ) +{ + int_fast32_t expA; + struct uint128 sigA; + int_fast32_t expB; + struct uint128 sigB, sigZ; + int_fast32_t expDiff, expZ; + struct uint128 uiZ; + union ui128_f128 uZ; + + expA = expF128UI64( uiA64 ); + sigA.v64 = fracF128UI64( uiA64 ); + sigA.v0 = uiA0; + expB = expF128UI64( uiB64 ); + sigB.v64 = fracF128UI64( uiB64 ); + sigB.v0 = uiB0; + sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 4 ); + sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 4 ); + expDiff = expA - expB; + if ( 0 < expDiff ) goto expABigger; + if ( expDiff < 0 ) goto expBBigger; + if ( expA == 0x7FFF ) { + if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN; + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + goto uiZ; + } + expZ = expA; + if ( ! expZ ) expZ = 1; + if ( sigB.v64 < sigA.v64 ) goto aBigger; + if ( sigA.v64 < sigB.v64 ) goto bBigger; + if ( sigB.v0 < sigA.v0 ) goto aBigger; + if ( sigA.v0 < sigB.v0 ) goto bBigger; + uiZ.v64 = + packToF128UI64( + (softfloat_roundingMode == softfloat_round_min), 0, 0 ); + uiZ.v0 = 0; + goto uiZ; + expBBigger: + if ( expB == 0x7FFF ) { + if ( sigB.v64 | sigB.v0 ) goto propagateNaN; + uiZ.v64 = packToF128UI64( signZ ^ 1, 0x7FFF, 0 ); + uiZ.v0 = 0; + goto uiZ; + } + if ( expA ) { + sigA.v64 |= UINT64_C( 0x0010000000000000 ); + } else { + ++expDiff; + if ( ! expDiff ) goto newlyAlignedBBigger; + } + sigA = softfloat_shiftRightJam128( sigA.v64, sigA.v0, -expDiff ); + newlyAlignedBBigger: + expZ = expB; + sigB.v64 |= UINT64_C( 0x0010000000000000 ); + bBigger: + signZ ^= 1; + sigZ = softfloat_sub128( sigB.v64, sigB.v0, sigA.v64, sigA.v0 ); + goto normRoundPack; + expABigger: + if ( expA == 0x7FFF ) { + if ( sigA.v64 | sigA.v0 ) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + goto uiZ; + } + if ( expB ) { + sigB.v64 |= UINT64_C( 0x0010000000000000 ); + } else { + --expDiff; + if ( ! expDiff ) goto newlyAlignedABigger; + } + sigB = softfloat_shiftRightJam128( sigB.v64, sigB.v0, expDiff ); + newlyAlignedABigger: + expZ = expA; + sigA.v64 |= UINT64_C( 0x0010000000000000 ); + aBigger: + sigZ = softfloat_sub128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ); + normRoundPack: + return softfloat_normRoundPackToF128( signZ, expZ - 5, sigZ.v64, sigZ.v0 ); + propagateNaN: + uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c new file mode 100644 index 0000000..5a7effc --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32_t + softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) +{ + int_fast16_t expA; + uint_fast32_t sigA; + int_fast16_t expB; + uint_fast32_t sigB; + int_fast16_t expDiff; + uint_fast32_t uiZ; + int_fast16_t expZ; + uint_fast32_t sigZ; + union ui32_f32 uZ; + + expA = expF32UI( uiA ); + sigA = fracF32UI( uiA ); + expB = expF32UI( uiB ); + sigB = fracF32UI( uiB ); + expDiff = expA - expB; + sigA <<= 7; + sigB <<= 7; + if ( 0 < expDiff ) goto expABigger; + if ( expDiff < 0 ) goto expBBigger; + if ( expA == 0xFF ) { + if ( sigA | sigB ) goto propagateNaN; + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF32UI; + goto uiZ; + } + if ( ! expA ) { + expA = 1; + expB = 1; + } + if ( sigB < sigA ) goto aBigger; + if ( sigA < sigB ) goto bBigger; + uiZ = packToF32UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); + goto uiZ; + expBBigger: + if ( expB == 0xFF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF32UI( signZ ^ 1, 0xFF, 0 ); + goto uiZ; + } + sigA += expA ? 0x40000000 : sigA; + sigA = softfloat_shiftRightJam32( sigA, -expDiff ); + sigB |= 0x40000000; + bBigger: + signZ ^= 1; + expZ = expB; + sigZ = sigB - sigA; + goto normRoundPack; + expABigger: + if ( expA == 0xFF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + sigB += expB ? 0x40000000 : sigB; + sigB = softfloat_shiftRightJam32( sigB, expDiff ); + sigA |= 0x40000000; + aBigger: + expZ = expA; + sigZ = sigA - sigB; + normRoundPack: + return softfloat_normRoundPackToF32( signZ, expZ - 1, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c new file mode 100644 index 0000000..462ed55 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t + softfloat_subMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ ) +{ + int_fast16_t expA; + uint_fast64_t sigA; + int_fast16_t expB; + uint_fast64_t sigB; + int_fast16_t expDiff; + uint_fast64_t uiZ; + int_fast16_t expZ; + uint_fast64_t sigZ; + union ui64_f64 uZ; + + expA = expF64UI( uiA ); + sigA = fracF64UI( uiA ); + expB = expF64UI( uiB ); + sigB = fracF64UI( uiB ); + expDiff = expA - expB; + sigA <<= 10; + sigB <<= 10; + if ( 0 < expDiff ) goto expABigger; + if ( expDiff < 0 ) goto expBBigger; + if ( expA == 0x7FF ) { + if ( sigA | sigB ) goto propagateNaN; + softfloat_raiseFlags( softfloat_flag_invalid ); + uiZ = defaultNaNF64UI; + goto uiZ; + } + if ( ! expA ) { + expA = 1; + expB = 1; + } + if ( sigB < sigA ) goto aBigger; + if ( sigA < sigB ) goto bBigger; + uiZ = packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); + goto uiZ; + expBBigger: + if ( expB == 0x7FF ) { + if ( sigB ) goto propagateNaN; + uiZ = packToF64UI( signZ ^ 1, 0x7FF, 0 ); + goto uiZ; + } + sigA += expA ? UINT64_C( 0x4000000000000000 ) : sigA; + sigA = softfloat_shiftRightJam64( sigA, -expDiff ); + sigB |= UINT64_C( 0x4000000000000000 ); + bBigger: + signZ ^= 1; + expZ = expB; + sigZ = sigB - sigA; + goto normRoundPack; + expABigger: + if ( expA == 0x7FF ) { + if ( sigA ) goto propagateNaN; + uiZ = uiA; + goto uiZ; + } + sigB += expB ? UINT64_C( 0x4000000000000000 ) : sigB; + sigB = softfloat_shiftRightJam64( sigB, expDiff ); + sigA |= UINT64_C( 0x4000000000000000 ); + aBigger: + expZ = expA; + sigZ = sigA - sigB; + normRoundPack: + return softfloat_normRoundPackToF64( signZ, expZ - 1, sigZ ); + propagateNaN: + uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); + uiZ: + uZ.ui = uiZ; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c new file mode 100644 index 0000000..40ede0a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" + +bool + softfloat_tryPropagateNaNExtF80M( + const struct extFloat80M *aSPtr, + const struct extFloat80M *bSPtr, + struct extFloat80M *zSPtr + ) +{ + uint_fast16_t ui64; + uint64_t ui0; + + ui64 = aSPtr->signExp; + ui0 = aSPtr->signif; + if ( isNaNExtF80UI( ui64, ui0 ) ) goto propagateNaN; + ui64 = bSPtr->signExp; + ui0 = bSPtr->signif; + if ( isNaNExtF80UI( ui64, ui0 ) ) goto propagateNaN; + return false; + propagateNaN: + softfloat_propagateNaNExtF80M( aSPtr, bSPtr, zSPtr ); + return true; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c new file mode 100644 index 0000000..17bba25 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 +#include "platform.h" +#include "internals.h" +#include "specialize.h" + +bool + softfloat_tryPropagateNaNF128M( + const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ) +{ + + if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { + softfloat_propagateNaNF128M( aWPtr, bWPtr, zWPtr ); + return true; + } + return false; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c new file mode 100644 index 0000000..37b101f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint_fast8_t softfloat_roundingMode = softfloat_round_near_even; +uint_fast8_t softfloat_detectTininess = init_detectTininess; +uint_fast8_t softfloat_exceptionFlags = 0; + +uint_fast8_t extF80_roundingPrecision = 80; + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/sub.mk b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/sub.mk new file mode 100644 index 0000000..c1d29cb --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/sub.mk @@ -0,0 +1,65 @@ +incdirs-lib-y += include +incdirs-lib-y += 8086-SSE +subdirs-y += 8086-SSE + +cflags-y += -Wno-aggregate-return +cflags-y += -Wno-sign-compare +cflags-y += -Wno-missing-prototypes +cflags-y += -Wno-missing-declarations + +srcs-y += f32_add.c +srcs-y += f32_div.c +srcs-y += f32_eq.c +srcs-y += f32_le.c +srcs-y += f32_lt.c +srcs-y += f32_mul.c +srcs-y += f32_sub.c +srcs-y += f32_to_f64.c +srcs-y += f32_to_i32_r_minMag.c +srcs-y += f32_to_i64_r_minMag.c +srcs-y += f32_to_ui32_r_minMag.c +srcs-y += f32_to_ui64_r_minMag.c + +srcs-y += f64_add.c +srcs-y += f64_div.c +srcs-y += f64_eq.c +srcs-y += f64_le.c +srcs-y += f64_lt.c +srcs-y += f64_mul.c +srcs-y += f64_sub.c +srcs-y += f64_to_f32.c +srcs-y += f64_to_i32_r_minMag.c +srcs-y += f64_to_i64_r_minMag.c +srcs-y += f64_to_ui32_r_minMag.c +srcs-y += f64_to_ui64_r_minMag.c + +srcs-y += i32_to_f32.c +srcs-y += i32_to_f64.c +srcs-y += i64_to_f32.c +srcs-y += i64_to_f64.c +srcs-y += ui32_to_f32.c +srcs-y += ui32_to_f64.c +srcs-y += ui64_to_f32.c +srcs-y += ui64_to_f64.c + +srcs-y += s_subMagsF32.c +srcs-y += s_subMagsF64.c +srcs-y += s_addMagsF32.c +srcs-y += s_addMagsF64.c +srcs-y += s_normSubnormalF64Sig.c +srcs-y += s_normSubnormalF32Sig.c +srcs-y += s_roundPackToF32.c +srcs-y += s_roundPackToF64.c +srcs-y += s_shortShiftRightJam64.c +srcs-y += s_shiftRightJam32.c +srcs-y += s_normRoundPackToF32.c +srcs-y += s_normRoundPackToF64.c +srcs-y += s_shiftRightJam64.c + +srcs-y += s_countLeadingZeros8.c +srcs-y += s_countLeadingZeros32.c +srcs-y += s_countLeadingZeros64.c + +srcs-y += s_mul64To128.c + +srcs-y += softfloat_state.c diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c new file mode 100644 index 0000000..0af7e31 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +extFloat80_t ui32_to_extF80( uint32_t a ) +{ + uint_fast16_t uiZ64; + int_fast8_t shiftCount; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + uiZ64 = 0; + if ( a ) { + shiftCount = softfloat_countLeadingZeros32( a ); + uiZ64 = 0x401E - shiftCount; + a <<= shiftCount; + } + uZ.s.signExp = uiZ64; + uZ.s.signif = (uint_fast64_t) a<<32; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c new file mode 100644 index 0000000..8957b2f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr ) +{ + + *zPtr = ui32_to_extF80( a ); + +} + +#else + +void ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr ) +{ + struct extFloat80M *zSPtr; + uint_fast16_t uiZ64; + uint64_t sigZ; + int_fast8_t shiftCount; + + zSPtr = (struct extFloat80M *) zPtr; + uiZ64 = 0; + sigZ = 0; + if ( a ) { + shiftCount = softfloat_countLeadingZeros32( a ); + uiZ64 = packToExtF80UI64( 0, 0x401E - shiftCount ); + sigZ = (uint64_t) (a<signExp = uiZ64; + zSPtr->signif = sigZ; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c new file mode 100644 index 0000000..d7416ab --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float128_t ui32_to_f128( uint32_t a ) +{ + uint_fast64_t uiZ64; + int_fast8_t shiftCount; + union ui128_f128 uZ; + + uiZ64 = 0; + if ( a ) { + shiftCount = softfloat_countLeadingZeros32( a ) + 17; + uiZ64 = + packToF128UI64( + 0, 0x402E - shiftCount, (uint_fast64_t) a< +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void ui32_to_f128M( uint32_t a, float128_t *zPtr ) +{ + + *zPtr = ui32_to_f128( a ); + +} + +#else + +void ui32_to_f128M( uint32_t a, float128_t *zPtr ) +{ + uint32_t *zWPtr, uiZ96, uiZ64; + int_fast8_t shiftCount; + uint64_t normA; + + zWPtr = (uint32_t *) zPtr; + uiZ96 = 0; + uiZ64 = 0; + if ( a ) { + shiftCount = softfloat_countLeadingZeros32( a ) + 17; + normA = (uint64_t) a<>32 ); + uiZ64 = normA; + } + zWPtr[indexWord( 4, 3 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = uiZ64; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c new file mode 100644 index 0000000..0335b6f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t ui32_to_f32( uint32_t a ) +{ + union ui32_f32 uZ; + + if ( ! a ) { + uZ.ui = 0; + return uZ.f; + } + if ( a & 0x80000000 ) { + return softfloat_roundPackToF32( 0, 0x9D, a>>1 | (a & 1) ); + } else { + return softfloat_normRoundPackToF32( 0, 0x9C, a ); + } + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c new file mode 100644 index 0000000..47b0d86 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t ui32_to_f64( uint32_t a ) +{ + uint_fast64_t uiZ; + int_fast8_t shiftCount; + union ui64_f64 uZ; + + if ( ! a ) { + uiZ = 0; + } else { + shiftCount = softfloat_countLeadingZeros32( a ) + 21; + uiZ = + packToF64UI( + 0, 0x432 - shiftCount, (uint_fast64_t) a< +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +extFloat80_t ui64_to_extF80( uint64_t a ) +{ + uint_fast16_t uiZ64; + int_fast8_t shiftCount; + union { struct extFloat80M s; extFloat80_t f; } uZ; + + uiZ64 = 0; + if ( a ) { + shiftCount = softfloat_countLeadingZeros64( a ); + uiZ64 = 0x403E - shiftCount; + a <<= shiftCount; + } + uZ.s.signExp = uiZ64; + uZ.s.signif = a; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c new file mode 100644 index 0000000..35566b0 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr ) +{ + + *zPtr = ui64_to_extF80( a ); + +} + +#else + +void ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr ) +{ + struct extFloat80M *zSPtr; + uint_fast16_t uiZ64; + uint64_t sigZ; + int_fast8_t shiftCount; + + zSPtr = (struct extFloat80M *) zPtr; + uiZ64 = 0; + sigZ = 0; + if ( a ) { + shiftCount = softfloat_countLeadingZeros64( a ); + uiZ64 = packToExtF80UI64( 0, 0x403E - shiftCount ); + sigZ = a<signExp = uiZ64; + zSPtr->signif = sigZ; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c new file mode 100644 index 0000000..cfd6de4 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float128_t ui64_to_f128( uint64_t a ) +{ + uint_fast64_t uiZ64, uiZ0; + int_fast8_t shiftCount; + struct uint128 zSig; + union ui128_f128 uZ; + + if ( ! a ) { + uiZ64 = 0; + uiZ0 = 0; + } else { + shiftCount = softfloat_countLeadingZeros64( a ) + 49; + if ( 64 <= shiftCount ) { + zSig.v64 = a<<(shiftCount - 64); + zSig.v0 = 0; + } else { + zSig = softfloat_shortShiftLeft128( 0, a, shiftCount ); + } + uiZ64 = packToF128UI64( 0, 0x406E - shiftCount, zSig.v64 ); + uiZ0 = zSig.v0; + } + uZ.ui.v64 = uiZ64; + uZ.ui.v0 = uiZ0; + return uZ.f; + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c new file mode 100644 index 0000000..b4821cd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +#ifdef SOFTFLOAT_FAST_INT64 + +void ui64_to_f128M( uint64_t a, float128_t *zPtr ) +{ + + *zPtr = ui64_to_f128( a ); + +} + +#else + +void ui64_to_f128M( uint64_t a, float128_t *zPtr ) +{ + uint32_t *zWPtr, uiZ96, uiZ64; + uint_fast8_t shiftCount; + uint32_t *ptr; + + zWPtr = (uint32_t *) zPtr; + uiZ96 = 0; + uiZ64 = 0; + zWPtr[indexWord( 4, 1 )] = 0; + zWPtr[indexWord( 4, 0 )] = 0; + if ( a ) { + shiftCount = softfloat_countLeadingZeros64( a ) + 17; + if ( shiftCount < 32 ) { + ptr = zWPtr + indexMultiwordHi( 4, 3 ); + ptr[indexWord( 3, 2 )] = 0; + ptr[indexWord( 3, 1 )] = a>>32; + ptr[indexWord( 3, 0 )] = a; + softfloat_shortShiftLeft96M( ptr, shiftCount, ptr ); + ptr[indexWordHi( 3 )] = + packToF128UI96( + 0, 0x404E - shiftCount, ptr[indexWordHi( 3 )] ); + return; + } + a <<= shiftCount - 32; + uiZ96 = packToF128UI96( 0, 0x404E - shiftCount, a>>32 ); + uiZ64 = a; + } + zWPtr[indexWord( 4, 3 )] = uiZ96; + zWPtr[indexWord( 4, 2 )] = uiZ64; + +} + +#endif + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c new file mode 100644 index 0000000..cb12496 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-3-Clause + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3a, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 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 "platform.h" +#include "internals.h" +#include "softfloat.h" + +float32_t ui64_to_f32( uint64_t a ) +{ + int_fast8_t shiftCount; + union ui32_f32 u; + uint_fast32_t sig; + + shiftCount = softfloat_countLeadingZeros64( a ) - 40; + if ( 0 <= shiftCount ) { + u.ui = + a ? packToF32UI( + 0, 0x95 - shiftCount, (uint_fast32_t) a< +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +float64_t ui64_to_f64( uint64_t a ) +{ + union ui64_f64 uZ; + + if ( ! a ) { + uZ.ui = 0; + return uZ.f; + } + if ( a & UINT64_C( 0x8000000000000000 ) ) { + return + softfloat_roundPackToF64( + 0, 0x43D, softfloat_shortShiftRightJam64( a, 1 ) ); + } else { + return softfloat_normRoundPackToF64( 0, 0x43C, a ); + } + +} + diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/sub.mk b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/sub.mk new file mode 100644 index 0000000..1175052 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/softfloat/sub.mk @@ -0,0 +1,3 @@ +incdirs-lib-y += arm32_include + +subdirs-y += source diff --git a/optee/optee_os/lib/libutils/isoc/arch/arm/sub.mk b/optee/optee_os/lib/libutils/isoc/arch/arm/sub.mk new file mode 100644 index 0000000..1e11502 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/arm/sub.mk @@ -0,0 +1,32 @@ +# These files implements the__aeabi functions we need instead of +# relying on libgcc or equivalent as we need implementations suitable +# for bare metal. +srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_divmod_a32.S +srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_divmod.c +srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_ldivmod_a32.S +srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_ldivmod.c +srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_shift.c + +ifeq ($(CFG_ULIBS_MCOUNT),y) +# We would not like to profile __aeabi functions as these provide +# internal implementations for "/ %" operations. Also, "/ %" operations +# could be used inside profiling code which could create an incorrect +# cyclic behaviour. +cflags-remove-arm32_aeabi_divmod.c-y += -pg +cflags-remove-arm32_aeabi_ldivmod.c-y += -pg +cflags-remove-arm32_aeabi_shift.c-y += -pg +endif + +srcs-$(CFG_ARM32_$(sm)) += setjmp_a32.S +srcs-$(CFG_ARM64_$(sm)) += setjmp_a64.S + +ifeq ($(CFG_TA_FLOAT_SUPPORT),y) +# Floating point is only supported for user TAs +ifneq ($(sm),core) +srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_softfloat.c +cflags-arm32_aeabi_softfloat.c-y += -Wno-aggregate-return +cflags-arm32_aeabi_softfloat.c-y += -Wno-missing-prototypes +cflags-arm32_aeabi_softfloat.c-y += -Wno-missing-declarations +subdirs-$(CFG_ARM32_$(sm)) += softfloat +endif +endif diff --git a/optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S b/optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S new file mode 100644 index 0000000..c1a1498 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/riscv/setjmp_rv.S @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright 2022-2023 NXP + */ +#include + +#ifdef RV32 +#define STR sw +#define LDR lw +#define REGOFF(x) ((x) * 4) +#else +#define STR sd +#define LDR ld +#define REGOFF(x) ((x) * 8) +#endif /*RV32*/ + +/* int setjmp (jmp_buf) */ +FUNC setjmp , : + STR s0, REGOFF(0)(a0) + STR s1, REGOFF(1)(a0) + STR s2, REGOFF(2)(a0) + STR s3, REGOFF(3)(a0) + STR s4, REGOFF(4)(a0) + STR s5, REGOFF(5)(a0) + STR s6, REGOFF(6)(a0) + STR s7, REGOFF(7)(a0) + STR s8, REGOFF(8)(a0) + STR s9, REGOFF(9)(a0) + STR s10, REGOFF(10)(a0) + STR s11, REGOFF(11)(a0) + STR ra, REGOFF(12)(a0) + STR sp, REGOFF(13)(a0) +#ifdef CFG_FTRACE_SUPPORT + addi sp, sp, -16 + STR ra, (sp) + mov x29, sp + addi a0, a0, REGOFF(12) + jal ftrace_setjmp + LDR ra, (sp) + addi sp, sp, 16 +#endif + li a0, 0 + ret +END_FUNC setjmp + +/* void longjmp (jmp_buf, int) __attribute__ ((noreturn)) */ +FUNC longjmp , : +#ifdef CFG_FTRACE_SUPPORT + addi sp, sp, -16 + STR a0, REGOFF(0)(sp) + STR a1, REGOFF(1)(sp) + STR ra, REGOFF(2)(sp) + addi a0, a0, REGOFF(12) + jal ftrace_longjmp + LDR a0, REGOFF(0)(sp) + LDR a1, REGOFF(1)(sp) + LDR ra, REGOFF(2)(sp) + addi sp, sp, 16 +#endif + LDR s0, REGOFF(0)(a0) + LDR s1, REGOFF(1)(a0) + LDR s2, REGOFF(2)(a0) + LDR s3, REGOFF(3)(a0) + LDR s4, REGOFF(4)(a0) + LDR s5, REGOFF(5)(a0) + LDR s6, REGOFF(6)(a0) + LDR s7, REGOFF(7)(a0) + LDR s8, REGOFF(8)(a0) + LDR s9, REGOFF(9)(a0) + LDR s10, REGOFF(10)(a0) + LDR s11, REGOFF(11)(a0) + LDR ra, REGOFF(12)(a0) + LDR sp, REGOFF(13)(a0) + seqz a0, a1 + add a0, a0, a1 + ret +END_FUNC longjmp diff --git a/optee/optee_os/lib/libutils/isoc/arch/riscv/sub.mk b/optee/optee_os/lib/libutils/isoc/arch/riscv/sub.mk new file mode 100644 index 0000000..91a66e4 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/arch/riscv/sub.mk @@ -0,0 +1 @@ +srcs-y += setjmp_rv.S diff --git a/optee/optee_os/lib/libutils/isoc/bget.c b/optee/optee_os/lib/libutils/isoc/bget.c new file mode 100644 index 0000000..724763c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/bget.c @@ -0,0 +1,1764 @@ +/* + + 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 +#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 + +#ifdef __KERNEL__ +#ifdef CFG_CORE_BGET_BESTFIT +#define BestFit 1 +#endif +#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 */ + bufsize offs; /* Offset from allocated buffer */ + 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)) + +/* Poolset definition */ +struct bpoolset { + struct bfhead freelist; +#ifdef BufStats + bufsize totalloc; /* Total space currently allocated */ + long numget; /* Number of bget() calls */ + long numrel; /* Number of brel() calls */ +#ifdef BECtl + long numpblk; /* Number of pool blocks */ + long numpget; /* Number of block gets and rels */ + long numprel; + long numdget; /* Number of direct gets and rels */ + long numdrel; +#endif /* BECtl */ +#endif /* BufStats */ + +#ifdef BECtl + /* Automatic expansion block management functions */ + + int (*compfcn) _((bufsize sizereq, int sequence)); + void *(*acqfcn) _((bufsize size)); + void (*relfcn) _((void *buf)); + + bufsize exp_incr; /* Expansion block size */ + bufsize pool_len; /* 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)) + +static bufsize buf_get_pos(struct bfhead *bf, bufsize align, bufsize hdr_size, + bufsize size) +{ + unsigned long buf = 0; + bufsize pos = 0; + + if (bf->bh.bsize < size) + return -1; + + /* + * plus sizeof(struct bhead) and hdr_size since buf will follow just + * after a struct bhead and an eventual extra header. + */ + buf = (unsigned long)bf + bf->bh.bsize - size + sizeof(struct bhead) + + hdr_size; + buf &= ~(align - 1); + pos = buf - (unsigned long)bf - sizeof(struct bhead) - hdr_size; + + if (pos == 0) /* exact match */ + return pos; + if (pos >= SizeQ + sizeof(struct bhead)) /* room for an empty buffer */ + return pos; + + return -1; +} + +/* BGET -- Allocate a buffer. */ + +void *bget(requested_align, hdr_size, requested_size, poolset) + bufsize requested_align; + bufsize hdr_size; + bufsize requested_size; + struct bpoolset *poolset; +{ + bufsize align = requested_align; + bufsize size = requested_size; + bufsize pos; + struct bfhead *b; +#ifdef BestFit + struct bfhead *best; +#endif + void *buf; +#ifdef BECtl + int compactseq = 0; +#endif + + assert(size > 0); + COMPILE_TIME_ASSERT(BGET_HDR_QUANTUM == SizeQ); + + if (align < 0 || (align > 0 && !IS_POWER_OF_TWO((unsigned long)align))) + return NULL; + if (hdr_size % BGET_HDR_QUANTUM != 0) + return NULL; + + if (size < SizeQ) { /* Need at least room for the */ + size = SizeQ; /* queue links. */ + } + if (align < SizeQ) + align = SizeQ; +#ifdef SizeQuant +#if SizeQuant > 1 + if (ADD_OVERFLOW(size, SizeQuant - 1, &size)) + return NULL; + + size = ROUNDDOWN(size, SizeQuant); +#endif +#endif + + /* Add overhead in allocated buffer to size required. */ + if (ADD_OVERFLOW(size, sizeof(struct bhead), &size)) + return NULL; + if (ADD_OVERFLOW(size, hdr_size, &size)) + return NULL; + +#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 = poolset->freelist.ql.flink; +#ifdef BestFit + best = &poolset->freelist; +#endif + + + /* Scan the free list searching for the first buffer big enough + to hold the requested size buffer. */ + +#ifdef BestFit + while (b != &poolset->freelist) { + assert(b->bh.prevfree == 0); + pos = buf_get_pos(b, align, hdr_size, size); + if (pos >= 0) { + if ((best == &poolset->freelist) || + (b->bh.bsize < best->bh.bsize)) { + best = b; + } + } + b = b->ql.flink; /* Link to next buffer */ + } + b = best; +#endif /* BestFit */ + + while (b != &poolset->freelist) { + pos = buf_get_pos(b, align, hdr_size, size); + if (pos >= 0) { + struct bhead *b_alloc = BH((char *)b + pos); + struct bhead *b_next = BH((char *)b + b->bh.bsize); + + assert(b_next->prevfree == b->bh.bsize); + + /* + * Zero the back pointer in the next buffer in memory + * to indicate that this buffer is allocated. + */ + b_next->prevfree = 0; + + assert(b->ql.blink->ql.flink == b); + assert(b->ql.flink->ql.blink == b); + + if (pos == 0) { + /* + * Need to allocate from the beginning of this free block. + * Unlink the block and mark it as allocated. + */ + b->ql.blink->ql.flink = b->ql.flink; + b->ql.flink->ql.blink = b->ql.blink; + + /* Negate size to mark buffer allocated. */ + b->bh.bsize = -b->bh.bsize; + } else { + /* + * Carve out the memory allocation from the end of this + * free block. Negative size to mark buffer allocated. + */ + b_alloc->bsize = -(b->bh.bsize - pos); + b_alloc->prevfree = pos; + b->bh.bsize = pos; + } + + assert(b_alloc->bsize < 0); + /* + * At this point is b_alloc pointing to the allocated + * buffer and b_next at the buffer following. b might be a + * free block or a used block now. + */ + if (-b_alloc->bsize - size > SizeQ + sizeof(struct bhead)) { + /* + * b_alloc has too much unused memory at the + * end we need to split the block and register that + * last part as free. + */ + b = BFH((char *)b_alloc + size); + b->bh.bsize = -b_alloc->bsize - size; + b->bh.prevfree = 0; + b_alloc->bsize += b->bh.bsize; + + assert(poolset->freelist.ql.blink->ql.flink == + &poolset->freelist); + assert(poolset->freelist.ql.flink->ql.blink == + &poolset->freelist); + b->ql.flink = &poolset->freelist; + b->ql.blink = poolset->freelist.ql.blink; + poolset->freelist.ql.blink = b; + b->ql.blink->ql.flink = b; + + assert(BH((char *)b + b->bh.bsize) == b_next); + b_next->prevfree = b->bh.bsize; + } + +#ifdef BufStats + poolset->totalloc -= b_alloc->bsize; + poolset->numget++; /* Increment number of bget() calls */ +#endif + buf = (char *)b_alloc + sizeof(struct bhead); + 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 ((poolset->compfcn == NULL) || + (!(poolset->compfcn)(size, ++compactseq))) { + break; + } + } + + /* No buffer available with requested size free. */ + + /* Don't give up yet -- look in the reserve supply. */ + + if (poolset->acqfcn != NULL) { + if (size > exp_incr - sizeof(struct bfhead) - align) { + + /* Request is too large to fit in a single expansion + block. Try to satisy it by a direct buffer acquisition. */ + char *p; + + size += sizeof(struct bdhead) - sizeof(struct bhead); + if (align > QLSize) + size += align; + p = poolset->acqfcn(size); + if (p != NULL) { + struct bdhead *bdh; + + if (align <= QLSize) { + bdh = BDH(p); + buf = bdh + 1; + } else { + unsigned long tp = (unsigned long)p; + + tp += sizeof(*bdh) + hdr_size + align; + tp &= ~(align - 1); + tp -= hdr_size; + buf = (void *)tp; + bdh = BDH((char *)buf - sizeof(*bdh)); + } + + /* 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; + bdh->offs = (unsigned long)bdh - (unsigned long)p; +#ifdef BufStats + poolset->totalloc += size; + poolset->numget++; /* Increment number of bget() calls */ + poolset->numdget++; /* Direct bget() call count */ +#endif + return buf; + } + + } else { + + /* Try to obtain a new expansion block */ + + void *newpool; + + if ((newpool = poolset->acqfcn((bufsize) exp_incr)) != NULL) { + bpool(newpool, exp_incr, poolset); + buf = bget(align, hdr_size, requested_size, pool); /* 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(align, hdr_size, size, poolset) + bufsize align; + bufsize hdr_size; + bufsize size; + struct bpoolset *poolset; +{ + char *buf = (char *) bget(align, hdr_size, size, poolset); + + 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) - bd->offs; + } else { + rsize -= sizeof(struct bhead); + } + assert(rsize >= size); + V memset_unchecked(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, align, hdr_size, size, poolset) + void *buf; + bufsize align; + bufsize hdr_size; + bufsize size; + struct bpoolset *poolset; +{ + void *nbuf; + bufsize osize; /* Old size of buffer */ + struct bhead *b; + + if ((nbuf = bget(align, hdr_size, size, poolset)) == 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) - bd->offs; + } else +#endif + osize -= sizeof(struct bhead); + assert(osize > 0); + V memcpy_unchecked((char *) nbuf, (char *) buf, /* Copy the data */ + (MemSize) ((size < osize) ? size : osize)); +#ifndef __KERNEL__ + /* User space reallocations are always zeroed */ + if (size > osize) + V memset_unchecked((char *) nbuf + osize, 0, size - osize); +#endif + brel(buf, poolset, false /* !wipe */); + return nbuf; +} + +/* BREL -- Release a buffer. */ + +void brel(buf, poolset, wipe) + void *buf; + struct bpoolset *poolset; + int wipe; +{ + struct bfhead *b, *bn; + char *wipe_start; + bufsize wipe_size; + + b = BFH(((char *) buf) - sizeof(struct bhead)); +#ifdef BufStats + poolset->numrel++; /* Increment number of brel() calls */ +#endif + assert(buf != NULL); + +#ifdef FreeWipe + wipe = true; +#endif +#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 + poolset->totalloc -= bdh->tsize; + assert(poolset->totalloc >= 0); + poolset->numdrel++; /* Number of direct releases */ +#endif /* BufStats */ + if (wipe) { + V memset_unchecked((char *) buf, 0x55, + (MemSize) (bdh->tsize - + sizeof(struct bdhead))); + } + assert(poolset->relfcn != NULL); + poolset->relfcn((char *)buf - sizeof(struct bdhead) - bdh->offs); /* 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 + poolset->totalloc += b->bh.bsize; + assert(poolset->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; + + /* Only wipe the current buffer, including bfhead. */ + wipe_start = (char *)b; + wipe_size = -size; + + /* 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(poolset->freelist.ql.blink->ql.flink == &poolset->freelist); + assert(poolset->freelist.ql.flink->ql.blink == &poolset->freelist); + b->ql.flink = &poolset->freelist; + b->ql.blink = poolset->freelist.ql.blink; + poolset->freelist.ql.blink = b; + b->ql.blink->ql.flink = b; + b->bh.bsize = -b->bh.bsize; + + wipe_start = (char *)b + sizeof(struct bfhead); + wipe_size = b->bh.bsize - sizeof(struct bfhead); + } + + /* 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); + /* Only bfhead of next buffer needs to be wiped */ + wipe_size += sizeof(struct bfhead); + } + if (wipe) { + V memset_unchecked(wipe_start, 0x55, wipe_size); + } + 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 (poolset->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; + + poolset->relfcn(b); +#ifdef BufStats + poolset->numprel++; /* Nr of expansion block releases */ + poolset->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, poolset) + int (*compact) _((bufsize sizereq, int sequence)); + void *(*acquire) _((bufsize size)); + void (*release) _((void *buf)); + bufsize pool_incr; + struct bpoolset *poolset; +{ + poolset->compfcn = compact; + poolset->acqfcn = acquire; + poolset->relfcn = release; + poolset->exp_incr = pool_incr; +} +#endif + +/* BPOOL -- Add a region of memory to the buffer pool. */ + +void bpool(buf, len, poolset) + void *buf; + bufsize len; + struct bpoolset *poolset; +{ + struct bfhead *b = BFH(buf); + struct bhead *bn; + +#ifdef SizeQuant + len &= ~(SizeQuant - 1); +#endif +#ifdef BECtl + if (poolset->pool_len == 0) { + pool_len = len; + } else if (len != poolset->pool_len) { + poolset->pool_len = -1; + } +#ifdef BufStats + poolset->numpget++; /* Number of block acquisitions */ + poolset->numpblk++; /* Number of blocks total */ + assert(poolset->numpblk == poolset->numpget - poolset->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(poolset->freelist.ql.blink->ql.flink == &poolset->freelist); + assert(poolset->freelist.ql.flink->ql.blink == &poolset->freelist); + b->ql.flink = &poolset->freelist; + b->ql.blink = poolset->freelist.ql.blink; + poolset->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_unchecked(((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, poolset) + bufsize *curalloc, *totfree, *maxfree; + long *nget, *nrel; + struct bpoolset *poolset; +{ + struct bfhead *b = poolset->freelist.ql.flink; + + *nget = poolset->numget; + *nrel = poolset->numrel; + *curalloc = poolset->totalloc; + *totfree = 0; + *maxfree = -1; + while (b != &poolset->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, poolset) + bufsize *pool_incr; + long *npool, *npget, *nprel, *ndget, *ndrel; + struct bpoolset *poolset; +{ + *pool_incr = (poolset->pool_len < 0) ? + -poolset->exp_incr : poolset->exp_incr; + *npool = poolset->numpblk; + *npget = poolset->numpget; + *nprel = poolset->numprel; + *ndget = poolset->numdget; + *ndrel = poolset->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 * + * * + \***********************/ + +#if !defined(__KERNEL__) && !defined(__LDELF__) && defined(CFG_TA_BGET_TEST) + +#define TestProg 20000 + +#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 ? */ + +static char *bchain = NULL; /* Our private buffer chain */ +static char *bp = NULL; /* Our initial buffer pool */ + +#ifdef UsingFloat +#include +#endif + +static unsigned long int next = 1; + +static void *(*mymalloc)(size_t size); +static void (*myfree)(void *ptr); + +static struct bpoolset mypoolset = { + .freelist = { + .bh = { 0, 0}, + .ql = { &mypoolset.freelist, &mypoolset.freelist}, + } +}; + +/* Return next random integer */ + +static int myrand(void) +{ + next = next * 1103515245L + 12345; + return (unsigned int) (next / 65536L) % 32768L; +} + +/* Set seed for random generator */ + +static void mysrand(unsigned int seed) +{ + next = seed; +} + +/* STATS -- Edit statistics returned by bstats() or bstatse(). */ + +static void stats(const char *when __maybe_unused, + struct bpoolset *poolset __maybe_unused) +{ +#ifdef BufStats + bufsize cural, totfree, maxfree; + long nget, nfree; +#endif +#ifdef BECtl + bufsize pincr; + long totblocks, npget, nprel, ndget, ndrel; +#endif + +#ifdef BufStats + bstats(&cural, &totfree, &maxfree, &nget, &nfree, poolset); + V printf( + "%s: %ld gets, %ld releases. %ld in use, %ld free, largest = %ld\n", + when, nget, nfree, (long) cural, (long) totfree, (long) maxfree); +#endif +#ifdef BECtl + bstatse(&pincr, &totblocks, &npget, &nprel, &ndget, &ndrel, poolset); + 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 = myrand() & 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 *) mymalloc((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 + myfree((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(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 bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *)) +{ + int i; +#ifdef UsingFloat + double x; +#endif + + mymalloc = malloc_func; + myfree = free_func; + + /* 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. */ + + mysrand(1234); + + /* 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. */ + +#ifdef UsingFloat + x = 4.0 * ExpIncr; + x = log(x); + x = exp(log(4.0 * ExpIncr) / (ExpIncr - 1.0)); +#endif + +#ifdef BECtl + bectl(bcompact, bexpand, bshrink, (bufsize) ExpIncr, &mypoolset); + bp = mymalloc(ExpIncr); + assert(bp != NULL); + bpool((void *) bp, (bufsize) ExpIncr); +#else + bp = mymalloc(PoolSize); + assert(bp != NULL); + bpool((void *) bp, (bufsize) PoolSize, &mypoolset); +#endif + + stats("Create pool", &mypoolset); +#ifdef BufValid + V bpoolv((void *) bp); +#endif +#ifdef BufDump + bpoold((void *) bp, dumpAlloc, dumpFree); +#endif + + for (i = 0; i < TestProg; i++) { + char *cb; +#ifdef UsingFloat + bufsize bs = pow(x, (double) (myrand() & (ExpIncr - 1))); +#else + bufsize bs = (myrand() & (ExpIncr * 4 - 1)) / (1 << (myrand() & 0x7)); +#endif + bufsize align = 0; + bufsize hdr_size = 0; + + switch (rand() & 0x3) { + case 1: + align = 32; + break; + case 2: + align = 64; + break; + case 3: + align = 128; + break; + default: + break; + } + + hdr_size = (rand() & 0x3) * BGET_HDR_QUANTUM; + + assert(bs <= (((bufsize) 4) * ExpIncr)); + bs = blimit(bs); + if (myrand() & 0x400) { + cb = (char *) bgetz(align, hdr_size, bs, &mypoolset); + } else { + cb = (char *) bget(align, hdr_size, bs, &mypoolset); + } + 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, &mypoolset, true/*wipe*/); + } + } + continue; +#endif + } + assert(!align || !(((unsigned long)cb + hdr_size) & (align - 1))); + *((char **) cb) = (char *) bchain; + bchain = cb; + + /* Based on a random cast, release a random buffer in the list + of allocated buffers. */ + + if ((myrand() & 0x10) == 0) { + char *bc = bchain; + int j = myrand() & 0x3; + + while (j > 0 && bc != NULL) { + bc = *((char **) bc); + j--; + } + if (bc != NULL) { + char *fb; + + fb = *((char **) bc); + if (fb != NULL) { + *((char **) bc) = *((char **) fb); + brel((void *) fb, &mypoolset, true/*wipe*/); + } + } + } + + /* Based on a random cast, reallocate a random buffer in the list + to a random size */ + + if ((myrand() & 0x20) == 0) { + char *bc = bchain; + int j = myrand() & 0x3; + + while (j > 0 && bc != NULL) { + bc = *((char **) bc); + j--; + } + if (bc != NULL) { + char *fb; + + fb = *((char **) bc); + if (fb != NULL) { + char *newb; + +#ifdef UsingFloat + bs = pow(x, (double) (myrand() & (ExpIncr - 1))); +#else + bs = (rand() & (ExpIncr * 4 - 1)) / (1 << (rand() & 0x7)); +#endif + bs = blimit(bs); +#ifdef BECtl + protect = 1; /* Protect against compaction */ +#endif + newb = (char *) bgetr((void *) fb, align, hdr_size, bs, &mypoolset); +#ifdef BECtl + protect = 0; +#endif + if (newb != NULL) { + assert(!align || !(((unsigned long)newb + hdr_size) & + (align - 1))); + *((char **) bc) = newb; + } + } + } + } + } + stats("\nAfter allocation", &mypoolset); + if (bp != NULL) { +#ifdef BufValid + V bpoolv((void *) bp); +#endif +#ifdef BufDump + bpoold((void *) bp, dumpAlloc, dumpFree); +#endif + } + + while (bchain != NULL) { + char *buf = bchain; + + bchain = *((char **) buf); + brel((void *) buf, &mypoolset, true/*wipe*/); + } + stats("\nAfter release", &mypoolset); +#ifndef BECtl + if (bp != NULL) { +#ifdef BufValid + V bpoolv((void *) bp); +#endif +#ifdef BufDump + bpoold((void *) bp, dumpAlloc, dumpFree); +#endif + } +#endif + + return 0; +} +#endif diff --git a/optee/optee_os/lib/libutils/isoc/bget.doc b/optee/optee_os/lib/libutils/isoc/bget.doc new file mode 100644 index 0000000..aaa1bd9 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/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/optee/optee_os/lib/libutils/isoc/bget.h b/optee/optee_os/lib/libutils/isoc/bget.h new file mode 100644 index 0000000..abef853 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/bget.h @@ -0,0 +1,55 @@ +/* + * 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 + +#define BGET_HDR_QUANTUM (2 * sizeof(long)) + +typedef long bufsize; +struct bpoolset; + +void bpool _((void *buffer, bufsize len, struct bpoolset *poolset)); +void *bget _((bufsize align, bufsize hdr_size, bufsize size, struct bpoolset *poolset)); +void *bgetz _((bufsize align, bufsize hdr_size, bufsize size, struct bpoolset *poolset)); +void *bgetr _((void *buffer, bufsize align, bufsize hdr_size, bufsize newsize, + struct bpoolset *poolset)); +void brel _((void *buf, struct bpoolset *poolset, int wipe)); +void bectl _((int (*compact)(bufsize sizereq, int sequence), + void *(*acquire)(bufsize size), + void (*release)(void *buf), bufsize pool_incr, + struct bpoolset *poolset)); +void bstats _((bufsize *curalloc, bufsize *totfree, bufsize *maxfree, + long *nget, long *nrel, struct bpoolset *poolset)); +void bstatse _((bufsize *pool_incr, long *npool, long *npget, + long *nprel, long *ndget, long *ndrel, + struct bpoolset *poolset)); +void bufdump _((void *buf)); +void bpoold _((void *pool, int dumpalloc, int dumpfree)); +int bpoolv _((void *pool)); + +#if !defined(__KERNEL__) && !defined(__LDELF__) && defined(CFG_TA_BGET_TEST) +int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *)); +#endif diff --git a/optee/optee_os/lib/libutils/isoc/bget_malloc.c b/optee/optee_os/lib/libutils/isoc/bget_malloc.c new file mode 100644 index 0000000..cd22f13 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/bget_malloc.c @@ -0,0 +1,1140 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022, Linaro Limited. + */ + +#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 + + +#ifdef __LP64__ +#define SizeQuant 16 +#endif +#ifdef __ILP32__ +#define SizeQuant 8 +#endif + /* 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 + +#ifdef CFG_WITH_STATS +#define BufStats 1 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__KERNEL__) +/* Compiling for TEE Core */ +#include +#include +#include + +static void *memset_unchecked(void *s, int c, size_t n) +{ + return asan_memset_unchecked(s, c, n); +} + +static __maybe_unused void *memcpy_unchecked(void *dst, const void *src, + size_t n) +{ + return asan_memcpy_unchecked(dst, src, n); +} + +#else /*__KERNEL__*/ +/* Compiling for TA */ + +static void *memset_unchecked(void *s, int c, size_t n) +{ + return memset(s, c, n); +} + +static __maybe_unused void *memcpy_unchecked(void *dst, const void *src, + size_t n) +{ + return memcpy(dst, src, n); +} + +#endif /*__KERNEL__*/ + +#include "bget.c" /* this is ugly, but this is bget */ + +struct malloc_pool { + void *buf; + size_t len; +}; + +struct malloc_ctx { + struct bpoolset poolset; + struct malloc_pool *pool; + size_t pool_len; +#ifdef BufStats + struct malloc_stats mstats; +#endif +#ifdef __KERNEL__ + unsigned int spinlock; +#endif +}; + +#ifdef __KERNEL__ + +static uint32_t malloc_lock(struct malloc_ctx *ctx) +{ + return cpu_spin_lock_xsave(&ctx->spinlock); +} + +static void malloc_unlock(struct malloc_ctx *ctx, uint32_t exceptions) +{ + cpu_spin_unlock_xrestore(&ctx->spinlock, exceptions); +} + +#else /* __KERNEL__ */ + +static uint32_t malloc_lock(struct malloc_ctx *ctx __unused) +{ + return 0; +} + +static void malloc_unlock(struct malloc_ctx *ctx __unused, + uint32_t exceptions __unused) +{ +} + +#endif /* __KERNEL__ */ + +#define DEFINE_CTX(name) struct malloc_ctx name = \ + { .poolset = { .freelist = { {0, 0}, \ + {&name.poolset.freelist, \ + &name.poolset.freelist}}}} + +static DEFINE_CTX(malloc_ctx); + +#ifdef CFG_NS_VIRTUALIZATION +static __nex_data DEFINE_CTX(nex_malloc_ctx); +#endif + +static void print_oom(size_t req_size __maybe_unused, void *ctx __maybe_unused) +{ +#if defined(__KERNEL__) && defined(CFG_CORE_DUMP_OOM) + EMSG("Memory allocation failed: size %zu context %p", req_size, ctx); + print_kernel_stack(); +#endif +} + +/* Most of the stuff in this function is copied from bgetr() in bget.c */ +static __maybe_unused 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) - bd->offs; + } else +#endif + osize -= sizeof(struct bhead); + assert(osize > 0); + return osize; +} + +static void *maybe_tag_buf(uint8_t *buf, size_t hdr_size, size_t requested_size) +{ + if (!buf) + return NULL; + + COMPILE_TIME_ASSERT(MEMTAG_GRANULE_SIZE <= SizeQuant); + + if (MEMTAG_IS_ENABLED) { + size_t sz = ROUNDUP(requested_size, MEMTAG_GRANULE_SIZE); + + /* + * Allocated buffer can be larger than requested when + * allocating with memalign(), but we should never tag more + * than allocated. + */ + assert(bget_buf_size(buf) >= sz + hdr_size); + return memtag_set_random_tags(buf, sz + hdr_size); + } + +#if defined(__KERNEL__) + if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS)) + asan_tag_access(buf, buf + hdr_size + requested_size); +#endif + return buf; +} + +static void *maybe_untag_buf(void *buf) +{ + if (!buf) + return NULL; + + if (MEMTAG_IS_ENABLED) { + size_t sz = 0; + + memtag_assert_tag(buf); /* Trying to catch double free early */ + sz = bget_buf_size(memtag_strip_tag(buf)); + return memtag_set_tags(buf, sz, 0); + } + +#if defined(__KERNEL__) + if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS)) + asan_tag_heap_free(buf, (uint8_t *)buf + bget_buf_size(buf)); +#endif + return buf; +} + +static void *strip_tag(void *buf) +{ + if (MEMTAG_IS_ENABLED) + return memtag_strip_tag(buf); + return buf; +} + +static void tag_asan_free(void *buf __maybe_unused, size_t len __maybe_unused) +{ +#if defined(__KERNEL__) + asan_tag_heap_free(buf, (uint8_t *)buf + len); +#endif +} + +#ifdef BufStats + +static void *raw_malloc_return_hook(void *p, size_t hdr_size, + size_t requested_size, + struct malloc_ctx *ctx) +{ + if (ctx->poolset.totalloc > ctx->mstats.max_allocated) + ctx->mstats.max_allocated = ctx->poolset.totalloc; + + if (!p) { + ctx->mstats.num_alloc_fail++; + print_oom(requested_size, ctx); + if (requested_size > ctx->mstats.biggest_alloc_fail) { + ctx->mstats.biggest_alloc_fail = requested_size; + ctx->mstats.biggest_alloc_fail_used = + ctx->poolset.totalloc; + } + } + + return maybe_tag_buf(p, hdr_size, MAX(SizeQuant, requested_size)); +} + +static void gen_malloc_reset_stats(struct malloc_ctx *ctx) +{ + uint32_t exceptions = malloc_lock(ctx); + + ctx->mstats.max_allocated = 0; + ctx->mstats.num_alloc_fail = 0; + ctx->mstats.biggest_alloc_fail = 0; + ctx->mstats.biggest_alloc_fail_used = 0; + malloc_unlock(ctx, exceptions); +} + +void malloc_reset_stats(void) +{ + gen_malloc_reset_stats(&malloc_ctx); +} + +static void gen_malloc_get_stats(struct malloc_ctx *ctx, + struct malloc_stats *stats) +{ + uint32_t exceptions = malloc_lock(ctx); + + raw_malloc_get_stats(ctx, stats); + malloc_unlock(ctx, exceptions); +} + +void malloc_get_stats(struct malloc_stats *stats) +{ + gen_malloc_get_stats(&malloc_ctx, stats); +} + +#else /* BufStats */ + +static void *raw_malloc_return_hook(void *p, size_t hdr_size, + size_t requested_size, + struct malloc_ctx *ctx ) +{ + if (!p) + print_oom(requested_size, ctx); + + return maybe_tag_buf(p, hdr_size, MAX(SizeQuant, requested_size)); +} + +#endif /* BufStats */ + +#ifdef BufValid +static void raw_malloc_validate_pools(struct malloc_ctx *ctx) +{ + size_t n; + + for (n = 0; n < ctx->pool_len; n++) + bpoolv(ctx->pool[n].buf); +} +#else +static void raw_malloc_validate_pools(struct malloc_ctx *ctx __unused) +{ +} +#endif + +struct bpool_iterator { + struct bfhead *next_buf; + size_t pool_idx; +}; + +static void bpool_foreach_iterator_init(struct malloc_ctx *ctx, + struct bpool_iterator *iterator) +{ + iterator->pool_idx = 0; + iterator->next_buf = BFH(ctx->pool[0].buf); +} + +static bool bpool_foreach_pool(struct bpool_iterator *iterator, void **buf, + size_t *len, bool *isfree) +{ + struct bfhead *b = iterator->next_buf; + bufsize bs = b->bh.bsize; + + if (bs == ESent) + return false; + + if (bs < 0) { + /* Allocated buffer */ + bs = -bs; + + *isfree = false; + } else { + /* Free Buffer */ + *isfree = true; + + /* Assert that the free list links are intact */ + assert(b->ql.blink->ql.flink == b); + assert(b->ql.flink->ql.blink == b); + } + + *buf = (uint8_t *)b + sizeof(struct bhead); + *len = bs - sizeof(struct bhead); + + iterator->next_buf = BFH((uint8_t *)b + bs); + return true; +} + +static bool bpool_foreach(struct malloc_ctx *ctx, + struct bpool_iterator *iterator, void **buf) +{ + while (true) { + size_t len; + bool isfree; + + if (bpool_foreach_pool(iterator, buf, &len, &isfree)) { + if (isfree) + continue; + return true; + } + + if ((iterator->pool_idx + 1) >= ctx->pool_len) + return false; + + iterator->pool_idx++; + iterator->next_buf = BFH(ctx->pool[iterator->pool_idx].buf); + } +} + +/* Convenience macro for looping over all allocated buffers */ +#define BPOOL_FOREACH(ctx, iterator, bp) \ + for (bpool_foreach_iterator_init((ctx),(iterator)); \ + bpool_foreach((ctx),(iterator), (bp));) + +void *raw_memalign(size_t hdr_size, size_t ftr_size, size_t alignment, + size_t pl_size, struct malloc_ctx *ctx) +{ + void *ptr = NULL; + bufsize s; + + if (!alignment || !IS_POWER_OF_TWO(alignment)) + return NULL; + + raw_malloc_validate_pools(ctx); + + /* Compute total size, excluding the header */ + if (ADD_OVERFLOW(pl_size, ftr_size, &s)) + goto out; + + /* BGET doesn't like 0 sized allocations */ + if (!s) + s++; + + ptr = bget(alignment, hdr_size, s, &ctx->poolset); +out: + return raw_malloc_return_hook(ptr, hdr_size, pl_size, ctx); +} + +void *raw_malloc(size_t hdr_size, size_t ftr_size, size_t pl_size, + struct malloc_ctx *ctx) +{ + /* + * Note that we're feeding SizeQ as alignment, this is the smallest + * alignment that bget() can use. + */ + return raw_memalign(hdr_size, ftr_size, SizeQ, pl_size, ctx); +} + +void raw_free(void *ptr, struct malloc_ctx *ctx, bool wipe) +{ + raw_malloc_validate_pools(ctx); + + if (ptr) + brel(maybe_untag_buf(ptr), &ctx->poolset, wipe); +} + +void *raw_calloc(size_t hdr_size, size_t ftr_size, size_t pl_nmemb, + size_t pl_size, struct malloc_ctx *ctx) +{ + void *ptr = NULL; + bufsize s; + + raw_malloc_validate_pools(ctx); + + /* Compute total size, excluding hdr_size */ + if (MUL_OVERFLOW(pl_nmemb, pl_size, &s)) + goto out; + if (ADD_OVERFLOW(s, ftr_size, &s)) + goto out; + + /* BGET doesn't like 0 sized allocations */ + if (!s) + s++; + + ptr = bgetz(0, hdr_size, s, &ctx->poolset); +out: + return raw_malloc_return_hook(ptr, hdr_size, pl_nmemb * pl_size, ctx); +} + +void *raw_realloc(void *ptr, size_t hdr_size, size_t ftr_size, + size_t pl_size, struct malloc_ctx *ctx) +{ + void *p = NULL; + bufsize s; + + /* Compute total size */ + if (ADD_OVERFLOW(pl_size, hdr_size, &s)) + goto out; + if (ADD_OVERFLOW(s, ftr_size, &s)) + goto out; + + raw_malloc_validate_pools(ctx); + + /* BGET doesn't like 0 sized allocations */ + if (!s) + s++; + + p = bget(0, 0, s, &ctx->poolset); + + if (p && ptr) { + void *old_ptr = maybe_untag_buf(ptr); + bufsize old_sz = bget_buf_size(old_ptr); + + if (old_sz < s) { + memcpy(p, old_ptr, old_sz); +#ifndef __KERNEL__ + /* User space reallocations are always zeroed */ + memset((uint8_t *)p + old_sz, 0, s - old_sz); +#endif + } else { + memcpy(p, old_ptr, s); + } + + brel(old_ptr, &ctx->poolset, false /*!wipe*/); + } +out: + return raw_malloc_return_hook(p, hdr_size, pl_size, ctx); +} + +#ifdef ENABLE_MDBG + +struct mdbg_hdr { + const char *fname; + uint16_t line; + uint32_t pl_size; + uint32_t magic; +#if defined(ARM64) + uint64_t pad; +#endif +}; + +#define MDBG_HEADER_MAGIC 0xadadadad +#define MDBG_FOOTER_MAGIC 0xecececec + +static size_t mdbg_get_ftr_size(size_t pl_size) +{ + size_t ftr_pad = ROUNDUP(pl_size, sizeof(uint32_t)) - pl_size; + + return ftr_pad + sizeof(uint32_t); +} + +static uint32_t *mdbg_get_footer(struct mdbg_hdr *hdr) +{ + uint32_t *footer; + + footer = (uint32_t *)((uint8_t *)(hdr + 1) + hdr->pl_size + + mdbg_get_ftr_size(hdr->pl_size)); + footer--; + return strip_tag(footer); +} + +static void mdbg_update_hdr(struct mdbg_hdr *hdr, const char *fname, + int lineno, size_t pl_size) +{ + uint32_t *footer; + + hdr->fname = fname; + hdr->line = lineno; + hdr->pl_size = pl_size; + hdr->magic = MDBG_HEADER_MAGIC; + + footer = mdbg_get_footer(hdr); + *footer = MDBG_FOOTER_MAGIC; +} + +static void *gen_mdbg_malloc(struct malloc_ctx *ctx, const char *fname, + int lineno, size_t size) +{ + struct mdbg_hdr *hdr; + uint32_t exceptions = malloc_lock(ctx); + + /* + * Check struct mdbg_hdr works with BGET_HDR_QUANTUM. + */ + COMPILE_TIME_ASSERT((sizeof(struct mdbg_hdr) % BGET_HDR_QUANTUM) == 0); + + hdr = raw_malloc(sizeof(struct mdbg_hdr), + mdbg_get_ftr_size(size), size, ctx); + if (hdr) { + mdbg_update_hdr(hdr, fname, lineno, size); + hdr++; + } + + malloc_unlock(ctx, exceptions); + return hdr; +} + +static void assert_header(struct mdbg_hdr *hdr __maybe_unused) +{ + assert(hdr->magic == MDBG_HEADER_MAGIC); + assert(*mdbg_get_footer(hdr) == MDBG_FOOTER_MAGIC); +} + +static void gen_mdbg_free(struct malloc_ctx *ctx, void *ptr, bool wipe) +{ + struct mdbg_hdr *hdr = ptr; + + if (hdr) { + hdr--; + assert_header(hdr); + hdr->magic = 0; + *mdbg_get_footer(hdr) = 0; + raw_free(hdr, ctx, wipe); + } +} + +static void free_helper(void *ptr, bool wipe) +{ + uint32_t exceptions = malloc_lock(&malloc_ctx); + + gen_mdbg_free(&malloc_ctx, ptr, wipe); + malloc_unlock(&malloc_ctx, exceptions); +} + +static void *gen_mdbg_calloc(struct malloc_ctx *ctx, const char *fname, int lineno, + size_t nmemb, size_t size) +{ + struct mdbg_hdr *hdr; + uint32_t exceptions = malloc_lock(ctx); + + hdr = raw_calloc(sizeof(struct mdbg_hdr), + mdbg_get_ftr_size(nmemb * size), nmemb, size, + ctx); + if (hdr) { + mdbg_update_hdr(hdr, fname, lineno, nmemb * size); + hdr++; + } + malloc_unlock(ctx, exceptions); + return hdr; +} + +static void *gen_mdbg_realloc_unlocked(struct malloc_ctx *ctx, const char *fname, + int lineno, void *ptr, size_t size) +{ + struct mdbg_hdr *hdr = ptr; + + if (hdr) { + hdr--; + assert_header(hdr); + } + hdr = raw_realloc(hdr, sizeof(struct mdbg_hdr), + mdbg_get_ftr_size(size), size, ctx); + if (hdr) { + mdbg_update_hdr(hdr, fname, lineno, size); + hdr++; + } + return hdr; +} + +static void *gen_mdbg_realloc(struct malloc_ctx *ctx, const char *fname, + int lineno, void *ptr, size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(ctx); + + p = gen_mdbg_realloc_unlocked(ctx, fname, lineno, ptr, size); + malloc_unlock(ctx, exceptions); + return p; +} + +#define realloc_unlocked(ctx, ptr, size) \ + gen_mdbg_realloc_unlocked(ctx, __FILE__, __LINE__, (ptr), (size)) + +static void *gen_mdbg_memalign(struct malloc_ctx *ctx, const char *fname, + int lineno, size_t alignment, size_t size) +{ + struct mdbg_hdr *hdr; + uint32_t exceptions = malloc_lock(ctx); + + hdr = raw_memalign(sizeof(struct mdbg_hdr), mdbg_get_ftr_size(size), + alignment, size, ctx); + if (hdr) { + mdbg_update_hdr(hdr, fname, lineno, size); + hdr++; + } + malloc_unlock(ctx, exceptions); + return hdr; +} + + +static void *get_payload_start_size(void *raw_buf, size_t *size) +{ + struct mdbg_hdr *hdr = raw_buf; + + assert(bget_buf_size(hdr) >= hdr->pl_size); + *size = hdr->pl_size; + return hdr + 1; +} + +static void gen_mdbg_check(struct malloc_ctx *ctx, int bufdump) +{ + struct bpool_iterator itr; + void *b; + uint32_t exceptions = malloc_lock(ctx); + + raw_malloc_validate_pools(ctx); + + BPOOL_FOREACH(ctx, &itr, &b) { + struct mdbg_hdr *hdr = (struct mdbg_hdr *)b; + + assert_header(hdr); + + if (bufdump > 0) { + const char *fname = hdr->fname; + + if (!fname) + fname = "unknown"; + + IMSG("buffer: %d bytes %s:%d\n", + hdr->pl_size, fname, hdr->line); + } + } + + malloc_unlock(ctx, exceptions); +} + +void *mdbg_malloc(const char *fname, int lineno, size_t size) +{ + return gen_mdbg_malloc(&malloc_ctx, fname, lineno, size); +} + +void *mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size) +{ + return gen_mdbg_calloc(&malloc_ctx, fname, lineno, nmemb, size); +} + +void *mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size) +{ + return gen_mdbg_realloc(&malloc_ctx, fname, lineno, ptr, size); +} + +void *mdbg_memalign(const char *fname, int lineno, size_t alignment, + size_t size) +{ + return gen_mdbg_memalign(&malloc_ctx, fname, lineno, alignment, size); +} + +#if __STDC_VERSION__ >= 201112L +void *mdbg_aligned_alloc(const char *fname, int lineno, size_t alignment, + size_t size) +{ + if (size % alignment) + return NULL; + + return gen_mdbg_memalign(&malloc_ctx, fname, lineno, alignment, size); +} +#endif /* __STDC_VERSION__ */ + +void mdbg_check(int bufdump) +{ + gen_mdbg_check(&malloc_ctx, bufdump); +} + +/* + * Since malloc debug is enabled, malloc() and friends are redirected by macros + * to mdbg_malloc() etc. + * We still want to export the standard entry points in case they are referenced + * by the application, either directly or via external libraries. + */ +#undef malloc +void *malloc(size_t size) +{ + return mdbg_malloc(__FILE__, __LINE__, size); +} + +#undef calloc +void *calloc(size_t nmemb, size_t size) +{ + return mdbg_calloc(__FILE__, __LINE__, nmemb, size); +} + +#undef realloc +void *realloc(void *ptr, size_t size) +{ + return mdbg_realloc(__FILE__, __LINE__, ptr, size); +} + +#else /* ENABLE_MDBG */ + +void *malloc(size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(&malloc_ctx); + + p = raw_malloc(0, 0, size, &malloc_ctx); + malloc_unlock(&malloc_ctx, exceptions); + return p; +} + +static void free_helper(void *ptr, bool wipe) +{ + uint32_t exceptions = malloc_lock(&malloc_ctx); + + raw_free(ptr, &malloc_ctx, wipe); + malloc_unlock(&malloc_ctx, exceptions); +} + +void *calloc(size_t nmemb, size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(&malloc_ctx); + + p = raw_calloc(0, 0, nmemb, size, &malloc_ctx); + malloc_unlock(&malloc_ctx, exceptions); + return p; +} + +static void *realloc_unlocked(struct malloc_ctx *ctx, void *ptr, + size_t size) +{ + return raw_realloc(ptr, 0, 0, size, ctx); +} + +void *realloc(void *ptr, size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(&malloc_ctx); + + p = realloc_unlocked(&malloc_ctx, ptr, size); + malloc_unlock(&malloc_ctx, exceptions); + return p; +} + +void *memalign(size_t alignment, size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(&malloc_ctx); + + p = raw_memalign(0, 0, alignment, size, &malloc_ctx); + malloc_unlock(&malloc_ctx, exceptions); + return p; +} + +#if __STDC_VERSION__ >= 201112L +void *aligned_alloc(size_t alignment, size_t size) +{ + if (size % alignment) + return NULL; + + return memalign(alignment, size); +} +#endif /* __STDC_VERSION__ */ + +static void *get_payload_start_size(void *ptr, size_t *size) +{ + *size = bget_buf_size(ptr); + return ptr; +} + +#endif + +void free(void *ptr) +{ + free_helper(ptr, false); +} + +void free_wipe(void *ptr) +{ + free_helper(ptr, true); +} + +static void gen_malloc_add_pool(struct malloc_ctx *ctx, void *buf, size_t len) +{ + uint32_t exceptions = malloc_lock(ctx); + + raw_malloc_add_pool(ctx, buf, len); + malloc_unlock(ctx, exceptions); +} + +static bool gen_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, + void *buf, size_t len) +{ + uint32_t exceptions = malloc_lock(ctx); + bool ret = false; + + ret = raw_malloc_buffer_is_within_alloced(ctx, buf, len); + malloc_unlock(ctx, exceptions); + + return ret; +} + +static bool gen_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx, + void *buf, size_t len) +{ + bool ret = false; + uint32_t exceptions = malloc_lock(ctx); + + ret = raw_malloc_buffer_overlaps_heap(ctx, buf, len); + malloc_unlock(ctx, exceptions); + return ret; +} + +size_t raw_malloc_get_ctx_size(void) +{ + return sizeof(struct malloc_ctx); +} + +void raw_malloc_init_ctx(struct malloc_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + ctx->poolset.freelist.ql.flink = &ctx->poolset.freelist; + ctx->poolset.freelist.ql.blink = &ctx->poolset.freelist; +} + +void raw_malloc_add_pool(struct malloc_ctx *ctx, void *buf, size_t len) +{ + const size_t min_len = sizeof(struct bhead) + sizeof(struct bfhead); + uintptr_t start = (uintptr_t)buf; + uintptr_t end = start + len; + void *p = NULL; + size_t l = 0; + + start = ROUNDUP(start, SizeQuant); + end = ROUNDDOWN(end, SizeQuant); + + if (start > end || (end - start) < min_len) { + DMSG("Skipping too small pool"); + return; + } + + /* First pool requires a bigger size */ + if (!ctx->pool_len && (end - start) < MALLOC_INITIAL_POOL_MIN_SIZE) { + DMSG("Skipping too small initial pool"); + return; + } + + tag_asan_free((void *)start, end - start); + bpool((void *)start, end - start, &ctx->poolset); + l = ctx->pool_len + 1; + p = realloc_unlocked(ctx, ctx->pool, sizeof(struct malloc_pool) * l); + assert(p); + ctx->pool = p; + ctx->pool[ctx->pool_len].buf = (void *)start; + ctx->pool[ctx->pool_len].len = end - start; +#ifdef BufStats + ctx->mstats.size += ctx->pool[ctx->pool_len].len; +#endif + ctx->pool_len = l; +} + +bool raw_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx, + void *buf, size_t len) +{ + uintptr_t buf_start = (uintptr_t)strip_tag(buf); + uintptr_t buf_end = buf_start + len; + size_t n = 0; + + raw_malloc_validate_pools(ctx); + + for (n = 0; n < ctx->pool_len; n++) { + uintptr_t pool_start = (uintptr_t)strip_tag(ctx->pool[n].buf); + uintptr_t pool_end = pool_start + ctx->pool[n].len; + + if (buf_start > buf_end || pool_start > pool_end) + return true; /* Wrapping buffers, shouldn't happen */ + + if ((buf_start >= pool_start && buf_start < pool_end) || + (buf_end >= pool_start && buf_end < pool_end)) + return true; + } + + return false; +} + +bool raw_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, + void *buf, size_t len) +{ + struct bpool_iterator itr = { }; + void *b = NULL; + uint8_t *start_buf = strip_tag(buf); + uint8_t *end_buf = start_buf + len; + + raw_malloc_validate_pools(ctx); + + /* Check for wrapping */ + if (start_buf > end_buf) + return false; + + BPOOL_FOREACH(ctx, &itr, &b) { + uint8_t *start_b = NULL; + uint8_t *end_b = NULL; + size_t s = 0; + + start_b = strip_tag(get_payload_start_size(b, &s)); + end_b = start_b + s; + if (start_buf >= start_b && end_buf <= end_b) + return true; + } + + return false; +} + +#ifdef CFG_WITH_STATS +void raw_malloc_get_stats(struct malloc_ctx *ctx, struct malloc_stats *stats) +{ + memcpy_unchecked(stats, &ctx->mstats, sizeof(*stats)); + stats->allocated = ctx->poolset.totalloc; +} +#endif + +void malloc_add_pool(void *buf, size_t len) +{ + gen_malloc_add_pool(&malloc_ctx, buf, len); +} + +bool malloc_buffer_is_within_alloced(void *buf, size_t len) +{ + return gen_malloc_buffer_is_within_alloced(&malloc_ctx, buf, len); +} + +bool malloc_buffer_overlaps_heap(void *buf, size_t len) +{ + return gen_malloc_buffer_overlaps_heap(&malloc_ctx, buf, len); +} + +#ifdef CFG_NS_VIRTUALIZATION + +#ifndef ENABLE_MDBG + +void *nex_malloc(size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(&nex_malloc_ctx); + + p = raw_malloc(0, 0, size, &nex_malloc_ctx); + malloc_unlock(&nex_malloc_ctx, exceptions); + return p; +} + +void *nex_calloc(size_t nmemb, size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(&nex_malloc_ctx); + + p = raw_calloc(0, 0, nmemb, size, &nex_malloc_ctx); + malloc_unlock(&nex_malloc_ctx, exceptions); + return p; +} + +void *nex_realloc(void *ptr, size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(&nex_malloc_ctx); + + p = realloc_unlocked(&nex_malloc_ctx, ptr, size); + malloc_unlock(&nex_malloc_ctx, exceptions); + return p; +} + +void *nex_memalign(size_t alignment, size_t size) +{ + void *p; + uint32_t exceptions = malloc_lock(&nex_malloc_ctx); + + p = raw_memalign(0, 0, alignment, size, &nex_malloc_ctx); + malloc_unlock(&nex_malloc_ctx, exceptions); + return p; +} + +void nex_free(void *ptr) +{ + uint32_t exceptions = malloc_lock(&nex_malloc_ctx); + + raw_free(ptr, &nex_malloc_ctx, false /* !wipe */); + malloc_unlock(&nex_malloc_ctx, exceptions); +} + +#else /* ENABLE_MDBG */ + +void *nex_mdbg_malloc(const char *fname, int lineno, size_t size) +{ + return gen_mdbg_malloc(&nex_malloc_ctx, fname, lineno, size); +} + +void *nex_mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size) +{ + return gen_mdbg_calloc(&nex_malloc_ctx, fname, lineno, nmemb, size); +} + +void *nex_mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size) +{ + return gen_mdbg_realloc(&nex_malloc_ctx, fname, lineno, ptr, size); +} + +void *nex_mdbg_memalign(const char *fname, int lineno, size_t alignment, + size_t size) +{ + return gen_mdbg_memalign(&nex_malloc_ctx, fname, lineno, alignment, size); +} + +void nex_mdbg_check(int bufdump) +{ + gen_mdbg_check(&nex_malloc_ctx, bufdump); +} + +void nex_free(void *ptr) +{ + uint32_t exceptions = malloc_lock(&nex_malloc_ctx); + + gen_mdbg_free(&nex_malloc_ctx, ptr, false /* !wipe */); + malloc_unlock(&nex_malloc_ctx, exceptions); +} + +#endif /* ENABLE_MDBG */ + +void nex_malloc_add_pool(void *buf, size_t len) +{ + gen_malloc_add_pool(&nex_malloc_ctx, buf, len); +} + +bool nex_malloc_buffer_is_within_alloced(void *buf, size_t len) +{ + return gen_malloc_buffer_is_within_alloced(&nex_malloc_ctx, buf, len); +} + +bool nex_malloc_buffer_overlaps_heap(void *buf, size_t len) +{ + return gen_malloc_buffer_overlaps_heap(&nex_malloc_ctx, buf, len); +} + +#ifdef BufStats + +void nex_malloc_reset_stats(void) +{ + gen_malloc_reset_stats(&nex_malloc_ctx); +} + +void nex_malloc_get_stats(struct malloc_stats *stats) +{ + gen_malloc_get_stats(&nex_malloc_ctx, stats); +} + +#endif + +#endif diff --git a/optee/optee_os/lib/libutils/isoc/fp.c b/optee/optee_os/lib/libutils/isoc/fp.c new file mode 100644 index 0000000..ee7445b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/fp.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ + +#include + +struct _FILE { + char dummy; +}; + +static struct _FILE _fake_stdout; +static struct _FILE _fake_stderr; + +FILE *stdout = &_fake_stdout; +FILE *stderr = &_fake_stderr; diff --git a/optee/optee_os/lib/libutils/isoc/fputc.c b/optee/optee_os/lib/libutils/isoc/fputc.c new file mode 100644 index 0000000..3f154d7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/fputc.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ + +#include +#include + +int fputc(int c, FILE *stream) +{ + if (stream != stdout && stream != stderr) + abort(); + + return putchar(c); +} diff --git a/optee/optee_os/lib/libutils/isoc/fputs.c b/optee/optee_os/lib/libutils/isoc/fputs.c new file mode 100644 index 0000000..1c9cd87 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/fputs.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ + +#include +#include +#include + +int fputs(const char *s, FILE *stream) +{ + if (stream != stdout && stream != stderr) + abort(); + + trace_ext_puts(s); + return 0; +} diff --git a/optee/optee_os/lib/libutils/isoc/fwrite.c b/optee/optee_os/lib/libutils/isoc/fwrite.c new file mode 100644 index 0000000..0e8fee9 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/fwrite.c @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ + +#include +#include +#include + +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) +{ + int fd = 0; + + if (stream == stdout) + fd = 1; + else if (stream == stderr) + fd = 2; + else + abort(); + + return write(fd, ptr, size * nmemb); +} diff --git a/optee/optee_os/lib/libutils/isoc/include/assert.h b/optee/optee_os/lib/libutils/isoc/include/assert.h new file mode 100644 index 0000000..120413f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/assert.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __ASSERT_H +#define __ASSERT_H + +#include +#include + +void __noreturn _assert_break(void); +void _assert_log(const char *expr, const char *file, const int line, + const char *func); + +static inline void __noreturn _assert_trap(const char *expr_str, + const char *file, const int line, + const char *func) +{ + _assert_log(expr_str, file, line, func); + _assert_break(); +} + +#ifdef NDEBUG +#define assert(expr) ((void)0) +#else +#define assert(expr) \ + ((expr) ? (void)0 : _assert_trap(#expr, __FILE__, __LINE__, __func__)) +#endif + +/* This macro is deprecated, please use static_assert instead */ +#define COMPILE_TIME_ASSERT(x) \ + do { \ + switch (0) { case 0: case ((x) ? 1: 0): default : break; } \ + } while (0) + +#endif + +#if !defined(__cplusplus) || (__cplusplus < 201103L) +#if defined(__HAVE_SINGLE_ARGUMENT_STATIC_ASSERT) +#define static_assert _Static_assert +#else +/* + * In gcc prior to 9.1 _Static_assert requires two arguments. To allow + * passing a single argument to static_assert() add a workaround with + * macros. + */ +#define ___args_count(_0, _1, x, ...) x +#define __args_count(...) ___args_count(__VA_ARGS__, 2, 1, 0) + +#define __static_assert_1(expr) _Static_assert(expr, "") +#define __static_assert_2(expr, msg) _Static_assert(expr, msg) +#define ___static_assert(count, ...) __static_assert_ ## count(__VA_ARGS__) +#define __static_assert(count, ...) ___static_assert(count, __VA_ARGS__) + +#define static_assert(...) \ + __static_assert(__args_count(__VA_ARGS__), __VA_ARGS__) +#endif +#endif /* __ASSERT_H */ diff --git a/optee/optee_os/lib/libutils/isoc/include/ctype.h b/optee/optee_os/lib/libutils/isoc/include/ctype.h new file mode 100644 index 0000000..bf3e588 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/ctype.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ +#ifndef __CTYPE_H +#define __CTYPE_H + +int isalnum(int c); +int isalpha(int c); +int iscntrl(int c); +int isdigit(int c); +int isgraph(int c); +int islower(int c); +int isprint(int c); +int ispunct(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); +int tolower(int c); +int toupper(int c); + +#endif /*__CTYPE_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/inttypes.h b/optee/optee_os/lib/libutils/isoc/include/inttypes.h new file mode 100644 index 0000000..5915a9d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/inttypes.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __INTTYPES_H +#define __INTTYPES_H + +#include + +#ifdef __ILP32__ +#define __PRI64_PREFIX "ll" +#endif +#ifdef __LP64__ +#define __PRI64_PREFIX "l" +#endif +#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/optee/optee_os/lib/libutils/isoc/include/limits.h b/optee/optee_os/lib/libutils/isoc/include/limits.h new file mode 100644 index 0000000..4dbec54 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/limits.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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/optee/optee_os/lib/libutils/isoc/include/malloc.h b/optee/optee_os/lib/libutils/isoc/include/malloc.h new file mode 100644 index 0000000..d261955 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/malloc.h @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __MALLOC_H +#define __MALLOC_H + +#include +#include + +/* + * Due to bget implementation, the first memory pool registered shall have + * a min size. Choose 1kB which is reasonable. + */ +#define MALLOC_INITIAL_POOL_MIN_SIZE 1024 + +void *malloc(size_t size); +void *calloc(size_t nmemb, size_t size); +void *realloc(void *ptr, size_t size); +void *memalign(size_t alignment, size_t size); +void free(void *ptr); + +#if __STDC_VERSION__ >= 201112L +void *aligned_alloc(size_t alignment, size_t size); +#endif + +#ifdef ENABLE_MDBG + +void *mdbg_malloc(const char *fname, int lineno, size_t size); +void *mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size); +void *mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size); +void *mdbg_memalign(const char *fname, int lineno, size_t alignment, + size_t size); + +#if __STDC_VERSION__ >= 201112L +void *mdbg_aligned_alloc(const char *fname, int lineno, size_t alignment, + size_t size); +#endif + +void mdbg_check(int bufdump); + +#define malloc(size) mdbg_malloc(__FILE__, __LINE__, (size)) +#define calloc(nmemb, size) \ + mdbg_calloc(__FILE__, __LINE__, (nmemb), (size)) +#define realloc(ptr, size) \ + mdbg_realloc(__FILE__, __LINE__, (ptr), (size)) +#define memalign(alignment, size) \ + mdbg_memalign(__FILE__, __LINE__, (alignment), (size)) + +#if __STDC_VERSION__ >= 201112L +#define aligned_alloc(alignment, size) \ + mdbg_aligned_alloc(__FILE__, __LINE__, (alignment), (size)) +#endif /* __STDC_VERSION__ */ + +#else + +#define mdbg_check(x) do { } while (0) + +#endif + +/* + * Returns true if the supplied memory area is within a buffer + * previously allocated (and not freed yet). + * + * Used internally by TAs + */ +bool malloc_buffer_is_within_alloced(void *buf, size_t len); + +/* + * Returns true if the supplied memory area is overlapping the area used + * for heap. + * + * Used internally by TAs + */ +bool malloc_buffer_overlaps_heap(void *buf, size_t len); + +/* + * Adds a pool of memory to allocate from. + */ +void malloc_add_pool(void *buf, size_t len); + +#ifdef CFG_WITH_STATS +/* + * Get/reset allocation statistics + */ + +#define TEE_ALLOCATOR_DESC_LENGTH 32 +struct malloc_stats { + char desc[TEE_ALLOCATOR_DESC_LENGTH]; + uint32_t allocated; /* Bytes currently allocated */ + uint32_t max_allocated; /* Tracks max value of allocated */ + uint32_t size; /* Total size for this allocator */ + uint32_t num_alloc_fail; /* Number of failed alloc requests */ + uint32_t biggest_alloc_fail; /* Size of biggest failed alloc */ + uint32_t biggest_alloc_fail_used; /* Alloc bytes when above occurred */ +}; + +void malloc_get_stats(struct malloc_stats *stats); +void malloc_reset_stats(void); +#endif /* CFG_WITH_STATS */ + + +#ifdef CFG_NS_VIRTUALIZATION + +void nex_free(void *ptr); + +#ifdef ENABLE_MDBG + +void *nex_mdbg_malloc(const char *fname, int lineno, size_t size); +void *nex_mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size); +void *nex_mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size); +void *nex_mdbg_memalign(const char *fname, int lineno, size_t alignment, + size_t size); + +void nex_mdbg_check(int bufdump); + +#define nex_malloc(size) nex_mdbg_malloc(__FILE__, __LINE__, (size)) +#define nex_calloc(nmemb, size) \ + nex_mdbg_calloc(__FILE__, __LINE__, (nmemb), (size)) +#define nex_realloc(ptr, size) \ + nex_mdbg_realloc(__FILE__, __LINE__, (ptr), (size)) +#define nex_memalign(alignment, size) \ + nex_mdbg_memalign(__FILE__, __LINE__, (alignment), (size)) + +#else /* ENABLE_MDBG */ + +void *nex_malloc(size_t size); +void *nex_calloc(size_t nmemb, size_t size); +void *nex_realloc(void *ptr, size_t size); +void *nex_memalign(size_t alignment, size_t size); + +#define nex_mdbg_check(x) do { } while (0) + +#endif /* ENABLE_MDBG */ + +bool nex_malloc_buffer_is_within_alloced(void *buf, size_t len); +bool nex_malloc_buffer_overlaps_heap(void *buf, size_t len); +void nex_malloc_add_pool(void *buf, size_t len); + +#ifdef CFG_WITH_STATS +/* + * Get/reset allocation statistics + */ + +void nex_malloc_get_stats(struct malloc_stats *stats); +void nex_malloc_reset_stats(void); + +#endif /* CFG_WITH_STATS */ +#else /* CFG_NS_VIRTUALIZATION */ + +#define nex_free(ptr) free(ptr) +#define nex_malloc(size) malloc(size) +#define nex_calloc(nmemb, size) calloc(nmemb, size) +#define nex_realloc(ptr, size) realloc(ptr, size) +#define nex_memalign(alignment, size) memalign(alignment, size) + +#endif /* CFG_NS_VIRTUALIZATION */ + +struct malloc_ctx; +void *raw_memalign(size_t hdr_size, size_t ftr_size, size_t alignment, + size_t pl_size, struct malloc_ctx *ctx); +void *raw_malloc(size_t hdr_size, size_t ftr_size, size_t pl_size, + struct malloc_ctx *ctx); +void raw_free(void *ptr, struct malloc_ctx *ctx, bool wipe); +void *raw_calloc(size_t hdr_size, size_t ftr_size, size_t pl_nmemb, + size_t pl_size, struct malloc_ctx *ctx); +void *raw_realloc(void *ptr, size_t hdr_size, size_t ftr_size, + size_t pl_size, struct malloc_ctx *ctx); +size_t raw_malloc_get_ctx_size(void); +void raw_malloc_init_ctx(struct malloc_ctx *ctx); +void raw_malloc_add_pool(struct malloc_ctx *ctx, void *buf, size_t len); +bool raw_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx, + void *buf, size_t len); +bool raw_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, + void *buf, size_t len); +#ifdef CFG_WITH_STATS +void raw_malloc_get_stats(struct malloc_ctx *ctx, struct malloc_stats *stats); +#endif + +#endif /* __MALLOC_H */ diff --git a/optee/optee_os/lib/libutils/isoc/include/memory.h b/optee/optee_os/lib/libutils/isoc/include/memory.h new file mode 100644 index 0000000..06ecdc7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/memory.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __MEMORY_H +#define __MEMORY_H +#include + +#endif /*__MEMORY_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/setjmp.h b/optee/optee_os/lib/libutils/isoc/include/setjmp.h new file mode 100644 index 0000000..c12bb15 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/setjmp.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 1994-2009 Red Hat, Inc. + * Copyright (c) 2016, Linaro Limited + * Copyright 2022-2023 NXP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. + */ + +#ifndef __SETJMP_H +#define __SETJMP_H + +#include + +#if defined(ARM32) +/* + * All callee preserved registers: + * v1 - v7, fp, ip, sp, lr, f4, f5, f6, f7 + * One additional 32-bit value used in case ftrace + * is enabled to restore ftrace return stack. + */ +#define _JBLEN 24 +#define _JBTYPE int +#endif + +#if defined(ARM64) +#define _JBLEN 22 +#define _JBTYPE long long +#endif +/* + * Callee preserved registers: + * s0-s11, ra, sp + */ +#if defined(RV64) || defined(RV32) +#define _JBLEN 14 +#define _JBTYPE unsigned long +#endif + +#ifdef _JBLEN +typedef _JBTYPE jmp_buf[_JBLEN]; +#endif + +void __noreturn longjmp(jmp_buf env, int val); +int setjmp(jmp_buf env); + +#ifdef CFG_FTRACE_SUPPORT +void ftrace_longjmp(unsigned int *ret_idx); +void ftrace_setjmp(unsigned int *ret_idx); +#endif + +#endif /*__SETJMP_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/signal.h b/optee/optee_os/lib/libutils/isoc/include/signal.h new file mode 100644 index 0000000..ee0bbdd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/signal.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __SIGNAL_H +#define __SIGNAL_H + +#endif /*__SIGNAL_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/stdint.h b/optee/optee_os/lib/libutils/isoc/include/stdint.h new file mode 100644 index 0000000..687fe7e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/stdint.h @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include + +/* + * This file provides what C99 standard requires in + * 7.18 interger types + */ + +#ifndef __STDINT_H +#define __STDINT_H + +/* + * If compiler supplies neither __ILP32__ or __LP64__, try to figure it out + * here. + */ +#if !defined(__ILP32__) && !defined(__LP64__) +#if defined(__SIZEOF_INT__) && defined(__SIZEOF_POINTER__) && \ + defined(__SIZEOF_LONG__) +#if __SIZEOF_INT__ == 4 && __SIZEOF_POINTER__ == 4 && __SIZEOF_LONG__ == 4 +#define __ILP32__ 1 +#endif +#if __SIZEOF_INT__ == 4 && __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 8 +#define __LP64__ 1 +#endif +#endif +#endif /* !defined(__ILP32__) && !defined(__LP64__) */ + +#if !defined(__ILP32__) && !defined(__LP64__) +#error Neither __ILP32__ nor __LP64__ is defined +#endif + +#ifndef __ASSEMBLER__ + +/* 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; +#ifdef __ILP32__ +__extension__ +typedef long long int int64_t; +#endif /*__ILP32__*/ +#ifdef __LP64__ +typedef long int int64_t; +#endif /*__LP64__*/ +#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 +#ifdef __ILP32__ +__extension__ +typedef unsigned long long int uint64_t; +#endif /*__ILP32__*/ +#ifdef __LP64__ +typedef unsigned long int uint64_t; +#endif /*__LP64__*/ + +/* 7.18.1.2 Minimum-width integer types */ +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ +typedef long intptr_t; +typedef unsigned long uintptr_t; + +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + +#endif /*__ASSEMBLER__*/ + +/* + * 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.2 Limits of minimum-width integer types */ + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ + +#define INTPTR_MIN LONG_MIN +#define INTPTR_MAX LONG_MAX +#define UINTPTR_MAX ULONG_MAX + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MAX INT64_MAX +#define INTMAX_MIN INT64_MIN +#define UINTMAX_MAX UINT64_MAX + +/* 7.18.3 Limits of other integer types */ +#define SIZE_MAX ULONG_MAX + +/* + * 7.18.4 Macros for integer constants + */ + +#ifdef __ASSEMBLER__ +#define U(v) v +#define UL(v) v +#define ULL(v) v +#define L(v) v +#define LL(v) v +#else +#define U(v) v ## U +#define UL(v) v ## UL +#define ULL(v) v ## ULL +#define L(v) v ## L +#define LL(v) v ## LL +#endif + +/* 7.18.4.1 Macros for minimum-width integer constants */ + +#define INT8_C(v) v +#define UINT8_C(v) v +#define INT16_C(v) v +#define UINT16_C(v) v +#define INT32_C(v) v +#define UINT32_C(v) U(v) +#ifdef __ILP32__ +#define INT64_C(v) LL(v) +#define UINT64_C(v) ULL(v) +#endif +#ifdef __LP64__ +#define INT64_C(v) L(v) +#define UINT64_C(v) UL(v) +#endif + +#define UINTPTR_C(v) UL(v) + +/* 7.18.4.2 Macros for greatest-width integer constants */ + +#define INTMAX_C(v) INT64_C(v) +#define UINTMAX_C(v) UINT64_C(v) + +#endif /* __STDINT_H */ diff --git a/optee/optee_os/lib/libutils/isoc/include/stdio.h b/optee/optee_os/lib/libutils/isoc/include/stdio.h new file mode 100644 index 0000000..c73e6a8 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/stdio.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __STDIO_H +#define __STDIO_H + +#include +#include + +typedef struct _FILE FILE; + +int printf(const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +/* sprintf() is unsafe and should not be used. Prefer snprintf(). */ +int sprintf(char *str, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))) + __attribute__ ((deprecated)); +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 __sprintf_chk(char *str, int flag, size_t slen, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 4, 5))); + +int puts(const char *str); +int putchar(int c); + +#ifndef __KERNEL__ + +extern FILE *stdout; +extern FILE *stderr; + +/* + * The functions below send their output synchronously to the secure console. + * They treat stdout and stderr the same, and will abort if stream is not one or + * the other. + */ + +int fputc(int c, FILE *stream); +int fputs(const char *s, FILE *stream); +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); +#endif + +#endif /*__STDIO_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/stdlib.h b/optee/optee_os/lib/libutils/isoc/include/stdlib.h new file mode 100644 index 0000000..78b192f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/stdlib.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* + * This file provides what C99 standard requires for in + * 7.20.3 Memory management functions + */ + +#ifndef __STDLIB_H +#define __STDLIB_H + +#include +#include +#include + +void +qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)); + +void abort(void) __noreturn; + +int abs(int i); + +/* The largest number returned by rand() */ +#define RAND_MAX __INT_MAX__ +int rand(void); + +unsigned long _strtoul (const char *nptr, char **endptr, int base); +unsigned long strtoul (const char *s, char **ptr, int base); + +#endif /* __STDLIB_H */ diff --git a/optee/optee_os/lib/libutils/isoc/include/string.h b/optee/optee_os/lib/libutils/isoc/include/string.h new file mode 100644 index 0000000..c6dbbf3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/string.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/* + * 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); +int strncmp(const char *s1, const char *s2, size_t n); +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); +char *strchr(const char *s, int c); +char *strstr(const char *big, const char *little); +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); +char *strrchr(const char *s, int i); +char *strtok_r(char *str, const char *delim, char **saveptr); + +void *memchr(const void *buf, int c, size_t length); + +#endif /* __STRING_H */ diff --git a/optee/optee_os/lib/libutils/isoc/include/strings.h b/optee/optee_os/lib/libutils/isoc/include/strings.h new file mode 100644 index 0000000..32917c5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/strings.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ +#ifndef __STRINGS_H +#define __STRINGS_H + +int bcmp(const void *s1, const void *s2, size_t n); + +#endif /*__STRINGS_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/sys/cdefs.h b/optee/optee_os/lib/libutils/isoc/include/sys/cdefs.h new file mode 100644 index 0000000..be71531 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/sys/cdefs.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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 + +#define __always_inline __attribute__((always_inline)) inline + +#endif /*SYS_CDEFS_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/sys/queue.h b/optee/optee_os/lib/libutils/isoc/include/sys/queue.h new file mode 100644 index 0000000..48c4bb5 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/sys/queue.h @@ -0,0 +1,721 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* $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) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +/* + * 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) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +/* + * 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_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->stqh_first); \ + (var); \ + (var) = ((var)->field.stqe_next)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#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/optee/optee_os/lib/libutils/isoc/include/sys/types.h b/optee/optee_os/lib/libutils/isoc/include/sys/types.h new file mode 100644 index 0000000..b03778e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/sys/types.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef SYS_TYPES_H +#define SYS_TYPES_H + +#include + +#endif /*SYS_TYPES_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/time.h b/optee/optee_os/lib/libutils/isoc/include/time.h new file mode 100644 index 0000000..9284159 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/time.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __TIME_H +#define __TIME_H + +#include +#include + +typedef int64_t time_t; + +#endif /*__TIME_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/include/unistd.h b/optee/optee_os/lib/libutils/isoc/include/unistd.h new file mode 100644 index 0000000..4fe0316 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/unistd.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __UNISTD_H +#define __UNISTD_H + +#include +#include + +#define __ssize_t_defined +typedef intptr_t ssize_t; + +/* @fd must be 1 or 2. Writes to the secure console. */ +ssize_t write(int fd, const void *buf, size_t count); + +#endif /* __UNISTD_H */ diff --git a/optee/optee_os/lib/libutils/isoc/include/wchar.h b/optee/optee_os/lib/libutils/isoc/include/wchar.h new file mode 100644 index 0000000..d473bdd --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/include/wchar.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#ifndef __WCHAR_H +#define __WCHAR_H + +#endif /*__WCHAR_H*/ diff --git a/optee/optee_os/lib/libutils/isoc/isalnum.c b/optee/optee_os/lib/libutils/isoc/isalnum.c new file mode 100644 index 0000000..827572d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/isalnum.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, KAIST + */ +#include + +int isalnum(int c) +{ + return isalpha(c) || isdigit(c); +} diff --git a/optee/optee_os/lib/libutils/isoc/isalpha.c b/optee/optee_os/lib/libutils/isoc/isalpha.c new file mode 100644 index 0000000..340c084 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/isalpha.c @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ +#include + +int isalpha(int c) +{ + if (c >= 'A' && c <= 'Z') + return 1; + if (c >= 'a' && c <= 'z') + return 1; + return 0; +} diff --git a/optee/optee_os/lib/libutils/isoc/iscntrl.c b/optee/optee_os/lib/libutils/isoc/iscntrl.c new file mode 100644 index 0000000..93d2277 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/iscntrl.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, KAIST + */ +#include + +int iscntrl(int c) +{ + if (c < 0x20 || c == 0x7f) + return 1; + return 0; +} diff --git a/optee/optee_os/lib/libutils/isoc/isdigit.c b/optee/optee_os/lib/libutils/isoc/isdigit.c new file mode 100644 index 0000000..9bb6694 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/isdigit.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ +#include + +int isdigit(int c) +{ + if (c >= '0' && c <= '9') + return 1; + return 0; +} diff --git a/optee/optee_os/lib/libutils/isoc/isgraph.c b/optee/optee_os/lib/libutils/isoc/isgraph.c new file mode 100644 index 0000000..4e9de9f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/isgraph.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, KAIST + */ +#include + +int isgraph(int c) +{ + if (c >= 0x21 && c < 0x7f) + return 1; + return 0; +} diff --git a/optee/optee_os/lib/libutils/isoc/islower.c b/optee/optee_os/lib/libutils/isoc/islower.c new file mode 100644 index 0000000..fabba3d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/islower.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, KAIST + */ +#include + +int islower(int c) +{ + return (c >= 'a' && c <= 'z'); +} diff --git a/optee/optee_os/lib/libutils/isoc/isprint.c b/optee/optee_os/lib/libutils/isoc/isprint.c new file mode 100644 index 0000000..2735fd0 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/isprint.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, KAIST + */ +#include + +int isprint(int c) +{ + if (c >= 0x20 && c < 0x7f) + return 1; + return 0; +} diff --git a/optee/optee_os/lib/libutils/isoc/ispunct.c b/optee/optee_os/lib/libutils/isoc/ispunct.c new file mode 100644 index 0000000..44ddf34 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/ispunct.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, KAIST + */ +#include + +int ispunct(int c) +{ + return isgraph(c) && !isalnum(c); +} diff --git a/optee/optee_os/lib/libutils/isoc/isspace.c b/optee/optee_os/lib/libutils/isoc/isspace.c new file mode 100644 index 0000000..395a832 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/isspace.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ +#include + +int isspace(int c) +{ + return (c == ' '); +} diff --git a/optee/optee_os/lib/libutils/isoc/isupper.c b/optee/optee_os/lib/libutils/isoc/isupper.c new file mode 100644 index 0000000..385c5de --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/isupper.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ +#include + +int isupper(int c) +{ + return (c >= 'A' && c <= 'Z'); +} diff --git a/optee/optee_os/lib/libutils/isoc/isxdigit.c b/optee/optee_os/lib/libutils/isoc/isxdigit.c new file mode 100644 index 0000000..d121d41 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/isxdigit.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ +#include + +int isxdigit(int c) +{ + if (isdigit(c)) + return 1; + if (c >= 'A' && c <= 'F') + return 1; + if (c >= 'a' && c <= 'f') + return 1; + return 0; +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/_ansi.h b/optee/optee_os/lib/libutils/isoc/newlib/_ansi.h new file mode 100644 index 0000000..c1c0b0a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/_ansi.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * 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/optee/optee_os/lib/libutils/isoc/newlib/abs.c b/optee/optee_os/lib/libutils/isoc/newlib/abs.c new file mode 100644 index 0000000..03179b3 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/abs.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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 +<>---integer absolute value (magnitude) + +INDEX + abs + +ANSI_SYNOPSIS + #include + int abs(int <[i]>); + +TRAD_SYNOPSIS + #include + int abs(<[i]>) + int <[i]>; + +DESCRIPTION +<> returns +@tex +$|x|$, +@end tex +the absolute value of <[i]> (also called the magnitude +of <[i]>). That is, if <[i]> is negative, the result is the opposite +of <[i]>, but if <[i]> is nonnegative the result is <[i]>. + +The similar function <> uses and returns <> rather than <> values. + +RETURNS +The result is a nonnegative integer. + +PORTABILITY +<> is ANSI. + +No supporting OS subroutines are required. +*/ + +#include "_ansi.h" +#include + +int +_DEFUN (abs, (i), int i) +{ + return (i < 0) ? -i : i; +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/bcmp.c b/optee/optee_os/lib/libutils/isoc/newlib/bcmp.c new file mode 100644 index 0000000..893c3c7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/bcmp.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* +FUNCTION + <>---compare two memory areas + +INDEX + bcmp + +SYNOPSIS + #include + int bcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>); + +DESCRIPTION + This function compares not more than <[n]> bytes of the + object pointed to by <[s1]> with the object pointed to by <[s2]>. + + This function is identical to <>. + +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 +<> requires no supporting OS subroutines. + +QUICKREF + bcmp ansi pure +*/ + +#include +#include + +int +bcmp (const void *m1, + const void *m2, + size_t n) + +{ + return memcmp (m1, m2, n); +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/memchr.c b/optee/optee_os/lib/libutils/isoc/newlib/memchr.c new file mode 100644 index 0000000..81dd055 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/memchr.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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) - 0x01010101L) & ~(X) & 0x80808080UL) +#else +#if LONG_MAX == 9223372036854775807L +/* Nonzero if X (a long int) contains a NULL byte. */ +#define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ + 0x8080808080808080UL) +#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/optee/optee_os/lib/libutils/isoc/newlib/memcmp.c b/optee/optee_os/lib/libutils/isoc/newlib/memcmp.c new file mode 100644 index 0000000..d4932ae --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/memcmp.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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/optee/optee_os/lib/libutils/isoc/newlib/memcpy.c b/optee/optee_os/lib/libutils/isoc/newlib/memcpy.c new file mode 100644 index 0000000..7c4953a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/memcpy.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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/optee/optee_os/lib/libutils/isoc/newlib/memmove.c b/optee/optee_os/lib/libutils/isoc/newlib/memmove.c new file mode 100644 index 0000000..c913e66 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/memmove.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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/optee/optee_os/lib/libutils/isoc/newlib/memset.c b/optee/optee_os/lib/libutils/isoc/newlib/memset.c new file mode 100644 index 0000000..ade5142 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/memset.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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/optee/optee_os/lib/libutils/isoc/newlib/str-two-way.h b/optee/optee_os/lib/libutils/isoc/newlib/str-two-way.h new file mode 100644 index 0000000..e0c7757 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/str-two-way.h @@ -0,0 +1,447 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * 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. + */ + +/* Byte-wise substring search, using the Two-Way algorithm. + * Copyright (C) 2008, 2010 Eric Blake + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + + +/* Before including this file, you need to include , and define: + RESULT_TYPE A macro that expands to the return type. + AVAILABLE(h, h_l, j, n_l) A macro that returns nonzero if there are + at least N_L bytes left starting at + H[J]. H is 'unsigned char *', H_L, J, + and N_L are 'size_t'; H_L is an + lvalue. For NUL-terminated searches, + H_L can be modified each iteration to + avoid having to compute the end of H + up front. + + For case-insensitivity, you may optionally define: + CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L + characters of P1 and P2 are equal. + CANON_ELEMENT(c) A macro that canonicalizes an element + right after it has been fetched from + one of the two strings. The argument + is an 'unsigned char'; the result must + be an 'unsigned char' as well. + + This file undefines the macros documented above, and defines + LONG_NEEDLE_THRESHOLD. +*/ + +#include +#include + +/* We use the Two-Way string matching algorithm, which guarantees + linear complexity with constant space. Additionally, for long + needles, we also use a bad character shift table similar to the + Boyer-Moore algorithm to achieve improved (potentially sub-linear) + performance. + + See http://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260 + and http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm +*/ + +/* Point at which computing a bad-byte shift table is likely to be + worthwhile. Small needles should not compute a table, since it + adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a + speedup no greater than a factor of NEEDLE_LEN. The larger the + needle, the better the potential performance gain. On the other + hand, on non-POSIX systems with CHAR_BIT larger than eight, the + memory required for the table is prohibitive. */ +#if CHAR_BIT < 10 +# define LONG_NEEDLE_THRESHOLD 32U +#else +# define LONG_NEEDLE_THRESHOLD SIZE_MAX +#endif + +#define MAX(a, b) ((a < b) ? (b) : (a)) + +#ifndef CANON_ELEMENT +# define CANON_ELEMENT(c) c +#endif +#ifndef CMP_FUNC +# define CMP_FUNC memcmp +#endif + +/* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN. + Return the index of the first byte in the right half, and set + *PERIOD to the global period of the right half. + + The global period of a string is the smallest index (possibly its + length) at which all remaining bytes in the string are repetitions + of the prefix (the last repetition may be a subset of the prefix). + + When NEEDLE is factored into two halves, a local period is the + length of the smallest word that shares a suffix with the left half + and shares a prefix with the right half. All factorizations of a + non-empty NEEDLE have a local period of at least 1 and no greater + than NEEDLE_LEN. + + A critical factorization has the property that the local period + equals the global period. All strings have at least one critical + factorization with the left half smaller than the global period. + + Given an ordered alphabet, a critical factorization can be computed + in linear time, with 2 * NEEDLE_LEN comparisons, by computing the + larger of two ordered maximal suffixes. The ordered maximal + suffixes are determined by lexicographic comparison of + periodicity. */ +static size_t +critical_factorization (const unsigned char *needle, size_t needle_len, + size_t *period) +{ + /* Index of last byte of left half, or SIZE_MAX. */ + size_t max_suffix, max_suffix_rev; + size_t j; /* Index into NEEDLE for current candidate suffix. */ + size_t k; /* Offset into current period. */ + size_t p; /* Intermediate period. */ + unsigned char a, b; /* Current comparison bytes. */ + + /* Invariants: + 0 <= j < NEEDLE_LEN - 1 + -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed) + min(max_suffix, max_suffix_rev) < global period of NEEDLE + 1 <= p <= global period of NEEDLE + p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j] + 1 <= k <= p + */ + + /* Perform lexicographic search. */ + max_suffix = SIZE_MAX; + j = 0; + k = p = 1; + while (j + k < needle_len) + { + a = CANON_ELEMENT (needle[j + k]); + b = CANON_ELEMENT (needle[(size_t)(max_suffix + k)]); + if (a < b) + { + /* Suffix is smaller, period is entire prefix so far. */ + j += k; + k = 1; + p = j - max_suffix; + } + else if (a == b) + { + /* Advance through repetition of the current period. */ + if (k != p) + ++k; + else + { + j += p; + k = 1; + } + } + else /* b < a */ + { + /* Suffix is larger, start over from current location. */ + max_suffix = j++; + k = p = 1; + } + } + *period = p; + + /* Perform reverse lexicographic search. */ + max_suffix_rev = SIZE_MAX; + j = 0; + k = p = 1; + while (j + k < needle_len) + { + a = CANON_ELEMENT (needle[j + k]); + b = CANON_ELEMENT (needle[max_suffix_rev + k]); + if (b < a) + { + /* Suffix is smaller, period is entire prefix so far. */ + j += k; + k = 1; + p = j - max_suffix_rev; + } + else if (a == b) + { + /* Advance through repetition of the current period. */ + if (k != p) + ++k; + else + { + j += p; + k = 1; + } + } + else /* a < b */ + { + /* Suffix is larger, start over from current location. */ + max_suffix_rev = j++; + k = p = 1; + } + } + + /* Choose the longer suffix. Return the first byte of the right + half, rather than the last byte of the left half. */ + if (max_suffix_rev + 1 < max_suffix + 1) + return max_suffix + 1; + *period = p; + return max_suffix_rev + 1; +} + +/* Return the first location of non-empty NEEDLE within HAYSTACK, or + NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This + method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD. + Performance is guaranteed to be linear, with an initialization cost + of 2 * NEEDLE_LEN comparisons. + + If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at + most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. + If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * + HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */ +static RETURN_TYPE +two_way_short_needle (const unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) +{ + size_t i; /* Index into current byte of NEEDLE. */ + size_t j; /* Index into current window of HAYSTACK. */ + size_t period; /* The period of the right half of needle. */ + size_t suffix; /* The index of the right half of needle. */ + + /* Factor the needle into two halves, such that the left half is + smaller than the global period, and the right half is + periodic (with a period as large as NEEDLE_LEN - suffix). */ + suffix = critical_factorization (needle, needle_len, &period); + + /* Perform the search. Each iteration compares the right half + first. */ + if (CMP_FUNC (needle, needle + period, suffix) == 0) + { + /* Entire needle is periodic; a mismatch can only advance by the + period, so use memory to avoid rescanning known occurrences + of the period. */ + size_t memory = 0; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Scan for matches in right half. */ + i = MAX (suffix, memory); + while (i < needle_len && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (memory < i + 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i + 1 < memory + 1) + return (RETURN_TYPE) (haystack + j); + /* No match, so remember how many repetitions of period + on the right half were scanned. */ + j += period; + memory = needle_len - period; + } + else + { + j += i - suffix + 1; + memory = 0; + } + } + } + else + { + /* The two halves of needle are distinct; no extra memory is + required, and any mismatch results in a maximal shift. */ + period = MAX (suffix, needle_len - suffix) + 1; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Scan for matches in right half. */ + i = suffix; + while (i < needle_len && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i == SIZE_MAX) + return (RETURN_TYPE) (haystack + j); + j += period; + } + else + j += i - suffix + 1; + } + } + return NULL; +} + +/* Return the first location of non-empty NEEDLE within HAYSTACK, or + NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This + method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN. + Performance is guaranteed to be linear, with an initialization cost + of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations. + + If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at + most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, + and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible. + If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * + HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and + sublinear performance is not possible. */ +static RETURN_TYPE +two_way_long_needle (const unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) +{ + size_t i; /* Index into current byte of NEEDLE. */ + size_t j; /* Index into current window of HAYSTACK. */ + size_t period; /* The period of the right half of needle. */ + size_t suffix; /* The index of the right half of needle. */ + size_t shift_table[1U << CHAR_BIT]; /* See below. */ + + /* Factor the needle into two halves, such that the left half is + smaller than the global period, and the right half is + periodic (with a period as large as NEEDLE_LEN - suffix). */ + suffix = critical_factorization (needle, needle_len, &period); + + /* Populate shift_table. For each possible byte value c, + shift_table[c] is the distance from the last occurrence of c to + the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE. + shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */ + for (i = 0; i < 1U << CHAR_BIT; i++) + shift_table[i] = needle_len; + for (i = 0; i < needle_len; i++) + shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1; + + /* Perform the search. Each iteration compares the right half + first. */ + if (CMP_FUNC (needle, needle + period, suffix) == 0) + { + /* Entire needle is periodic; a mismatch can only advance by the + period, so use memory to avoid rescanning known occurrences + of the period. */ + size_t memory = 0; + size_t shift; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Check the last byte first; if it does not match, then + shift to the next possible match location. */ + shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; + if (0 < shift) + { + if (memory && shift < period) + { + /* Since needle is periodic, but the last period has + a byte out of place, there can be no match until + after the mismatch. */ + shift = needle_len - period; + } + memory = 0; + j += shift; + continue; + } + /* Scan for matches in right half. The last byte has + already been matched, by virtue of the shift table. */ + i = MAX (suffix, memory); + while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len - 1 <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (memory < i + 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i + 1 < memory + 1) + return (RETURN_TYPE) (haystack + j); + /* No match, so remember how many repetitions of period + on the right half were scanned. */ + j += period; + memory = needle_len - period; + } + else + { + j += i - suffix + 1; + memory = 0; + } + } + } + else + { + /* The two halves of needle are distinct; no extra memory is + required, and any mismatch results in a maximal shift. */ + size_t shift; + period = MAX (suffix, needle_len - suffix) + 1; + j = 0; + while (AVAILABLE (haystack, haystack_len, j, needle_len)) + { + /* Check the last byte first; if it does not match, then + shift to the next possible match location. */ + shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; + if (0 < shift) + { + j += shift; + continue; + } + /* Scan for matches in right half. The last byte has + already been matched, by virtue of the shift table. */ + i = suffix; + while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + ++i; + if (needle_len - 1 <= i) + { + /* Scan for matches in left half. */ + i = suffix - 1; + while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) + == CANON_ELEMENT (haystack[i + j]))) + --i; + if (i == SIZE_MAX) + return (RETURN_TYPE) (haystack + j); + j += period; + } + else + j += i - suffix + 1; + } + } + return NULL; +} + +#undef AVAILABLE +#undef CANON_ELEMENT +#undef CMP_FUNC +#undef MAX +#undef RETURN_TYPE diff --git a/optee/optee_os/lib/libutils/isoc/newlib/strchr.c b/optee/optee_os/lib/libutils/isoc/newlib/strchr.c new file mode 100644 index 0000000..1a1af15 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strchr.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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 + <>---search for character in string + +INDEX + strchr + +ANSI_SYNOPSIS + #include + char * strchr(const char *<[string]>, int <[c]>); + +TRAD_SYNOPSIS + #include + char * strchr(<[string]>, <[c]>); + const char *<[string]>; + int <[c]>; + +DESCRIPTION + This function finds the first occurence of <[c]> (converted to + a char) in the string pointed to by <[string]> (including the + terminating null character). + +RETURNS + Returns a pointer to the located character, or a null pointer + if <[c]> does not occur in <[string]>. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strchr ansi pure +*/ + +#include +#include +#include "_ansi.h" + +/* Nonzero if X 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)) + +#if LONG_MAX == 2147483647L +#define DETECTNULL(X) (((X) - 0x01010101L) & ~(X) & 0x80808080UL) +#else +#if LONG_MAX == 9223372036854775807L +/* Nonzero if X (a long int) contains a NULL byte. */ +#define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ + 0x8080808080808080UL) +#else +#error long int is not a 32bit or 64bit type. +#endif +#endif + +/* DETECTCHAR returns nonzero if (long)X contains the byte used + to fill (long)MASK. */ +#define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) + +char * +_DEFUN (strchr, (s1, i), + _CONST char *s1 _AND + int i) +{ + _CONST unsigned char *s = (_CONST unsigned char *)s1; + unsigned char c = i; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned long mask,j; + unsigned long *aligned_addr; + + /* Special case for finding 0. */ + if (!c) + { + while (UNALIGNED (s)) + { + if (!*s) + return (char *) s; + s++; + } + /* Operate a word at a time. */ + aligned_addr = (unsigned long *) s; + while (!DETECTNULL (*aligned_addr)) + aligned_addr++; + /* Found the end of string. */ + s = (const unsigned char *) aligned_addr; + while (*s) + s++; + return (char *) s; + } + + /* All other bytes. Align the pointer, then search a long at a time. */ + while (UNALIGNED (s)) + { + if (!*s) + return NULL; + if (*s == c) + return (char *) s; + s++; + } + + mask = c; + for (j = 8; j < LBLOCKSIZE * 8; j <<= 1) + mask = (mask << j) | mask; + + aligned_addr = (unsigned long *) s; + while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) + aligned_addr++; + + /* The block of bytes currently pointed to by aligned_addr + contains either a null or the target char, or both. We + catch it using the bytewise search. */ + + s = (unsigned char *) aligned_addr; + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (*s && *s != c) + s++; + if (*s == c) + return (char *)s; + return NULL; +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/strcmp.c b/optee/optee_os/lib/libutils/isoc/newlib/strcmp.c new file mode 100644 index 0000000..2f36e27 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strcmp.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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) - 0x01010101L) & ~(X) & 0x80808080UL) +#else +#if LONG_MAX == 9223372036854775807L +#define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ + 0x8080808080808080UL) +#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/optee/optee_os/lib/libutils/isoc/newlib/strcpy.c b/optee/optee_os/lib/libutils/isoc/newlib/strcpy.c new file mode 100644 index 0000000..9fc9ea1 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strcpy.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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 string + +INDEX + strcpy + +ANSI_SYNOPSIS + #include + char *strcpy(char *<[dst]>, const char *<[src]>); + +TRAD_SYNOPSIS + #include + char *strcpy(<[dst]>, <[src]>) + char *<[dst]>; + char *<[src]>; + +DESCRIPTION + <> copies the string pointed to by <[src]> + (including the terminating null character) to the array + pointed to by <[dst]>. + +RETURNS + This function returns the initial value of <[dst]>. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strcpy ansi pure +*/ + +#include "_ansi.h" +#include +#include + +/*SUPPRESS 560*/ +/*SUPPRESS 530*/ + +/* 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))) + +#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 + +char* +_DEFUN (strcpy, (dst0, src0), + char *dst0 _AND + _CONST char *src0) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *s = dst0; + + while (*dst0++ = *src0++) + ; + + return s; +#else + char *dst = dst0; + _CONST char *src = src0; + long *aligned_dst; + _CONST long *aligned_src; + + /* If SRC or DEST is unaligned, then copy bytes. */ + if (!UNALIGNED (src, dst)) + { + aligned_dst = (long*)dst; + aligned_src = (long*)src; + + /* SRC and DEST are both "long int" aligned, try to do "long int" + sized copies. */ + while (!DETECTNULL(*aligned_src)) + { + *aligned_dst++ = *aligned_src++; + } + + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while ((*dst++ = *src++)) + ; + return dst0; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/strlen.c b/optee/optee_os/lib/libutils/isoc/newlib/strlen.c new file mode 100644 index 0000000..0a9d549 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strlen.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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) - 0x01010101L) & ~(X) & 0x80808080UL) +#else +#if LONG_MAX == 9223372036854775807L +/* Nonzero if X (a long int) contains a NULL byte. */ +#define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ + 0x8080808080808080UL) +#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/optee/optee_os/lib/libutils/isoc/newlib/strncmp.c b/optee/optee_os/lib/libutils/isoc/newlib/strncmp.c new file mode 100644 index 0000000..3cf2b9c --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strncmp.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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 compare + +INDEX + strncmp + +ANSI_SYNOPSIS + #include + int strncmp(const char *<[a]>, const char * <[b]>, size_t <[length]>); + +TRAD_SYNOPSIS + #include + int strncmp(<[a]>, <[b]>, <[length]>) + char *<[a]>; + char *<[b]>; + size_t <[length]> + +DESCRIPTION + <> compares up to <[length]> characters + from 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 are equivalent, <> returns zero. If <<*<[a]>>> + sorts lexicographically before <<*<[b]>>>, <> returns a + number less than zero. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strncmp 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) - 0x01010101L) & ~(X) & 0x80808080UL) +#else +#if LONG_MAX == 9223372036854775807L +#define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ + 0x8080808080808080UL) +#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 (strncmp, (s1, s2, n), + _CONST char *s1 _AND + _CONST char *s2 _AND + size_t n) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + if (n == 0) + return 0; + + while (n-- != 0 && *s1 == *s2) + { + if (n == 0 || *s1 == '\0') + break; + s1++; + s2++; + } + + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +#else + unsigned long *a1; + unsigned long *a2; + + if (n == 0) + return 0; + + /* 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 (n >= sizeof (long) && *a1 == *a2) + { + n -= sizeof (long); + + /* If we've run out of bytes or hit a null, return zero + since we already know *a1 == *a2. */ + if (n == 0 || 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 (n-- > 0 && *s1 == *s2) + { + /* If we've run out of bytes or hit a null, return zero + since we already know *s1 == *s2. */ + if (n == 0 || *s1 == '\0') + return 0; + s1++; + s2++; + } + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/strncpy.c b/optee/optee_os/lib/libutils/isoc/newlib/strncpy.c new file mode 100644 index 0000000..2148434 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strncpy.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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 + <>---counted copy string + +INDEX + strncpy + +ANSI_SYNOPSIS + #include + char *strncpy(char *restrict <[dst]>, const char *restrict <[src]>, + size_t <[length]>); + +TRAD_SYNOPSIS + #include + char *strncpy(<[dst]>, <[src]>, <[length]>) + char *<[dst]>; + char *<[src]>; + size_t <[length]>; + +DESCRIPTION + <> copies not more than <[length]> characters from the + the string pointed to by <[src]> (including the terminating + null character) to the array pointed to by <[dst]>. If the + string pointed to by <[src]> is shorter than <[length]> + characters, null characters are appended to the destination + array until a total of <[length]> characters have been + written. + +RETURNS + This function returns the initial value of <[dst]>. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strncpy ansi pure +*/ + +#include "_ansi.h" +#include +#include + +/*SUPPRESS 560*/ +/*SUPPRESS 530*/ + +/* 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))) + +#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 + +#define TOO_SMALL(LEN) ((LEN) < sizeof (long)) + +char * +_DEFUN (strncpy, (dst0, src0), + char *__restrict dst0 _AND + _CONST char *__restrict src0 _AND + size_t count) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *dscan; + _CONST char *sscan; + + dscan = dst0; + sscan = src0; + while (count > 0) + { + --count; + if ((*dscan++ = *sscan++) == '\0') + break; + } + while (count-- > 0) + *dscan++ = '\0'; + + return dst0; +#else + char *dst = dst0; + _CONST char *src = src0; + long *aligned_dst; + _CONST long *aligned_src; + + /* If SRC and DEST is aligned and count large enough, then copy words. */ + if (!UNALIGNED (src, dst) && !TOO_SMALL (count)) + { + aligned_dst = (long*)dst; + aligned_src = (long*)src; + + /* SRC and DEST are both "long int" aligned, try to do "long int" + sized copies. */ + while (count >= sizeof (long int) && !DETECTNULL(*aligned_src)) + { + count -= sizeof (long int); + *aligned_dst++ = *aligned_src++; + } + + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while (count > 0) + { + --count; + if ((*dst++ = *src++) == '\0') + break; + } + + while (count-- > 0) + *dst++ = '\0'; + + return dst0; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/strnlen.c b/optee/optee_os/lib/libutils/isoc/newlib/strnlen.c new file mode 100644 index 0000000..1927127 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strnlen.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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/optee/optee_os/lib/libutils/isoc/newlib/strrchr.c b/optee/optee_os/lib/libutils/isoc/newlib/strrchr.c new file mode 100644 index 0000000..6e69acc --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strrchr.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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 + <>---reverse search for character in string + +INDEX + strrchr + +ANSI_SYNOPSIS + #include + char * strrchr(const char *<[string]>, int <[c]>); + +TRAD_SYNOPSIS + #include + char * strrchr(<[string]>, <[c]>); + char *<[string]>; + int *<[c]>; + +DESCRIPTION + This function finds the last occurence of <[c]> (converted to + a char) in the string pointed to by <[string]> (including the + terminating null character). + +RETURNS + Returns a pointer to the located character, or a null pointer + if <[c]> does not occur in <[string]>. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strrchr ansi pure +*/ +#include "_ansi.h" +#include + +char * +_DEFUN (strrchr, (s, i), + _CONST char *s _AND + int i) +{ + _CONST char *last = NULL; + + if (i) + { + while ((s=strchr(s, i))) + { + last = s; + s++; + } + } + else + { + last = strchr(s, i); + } + + return (char *) last; +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/strstr.c b/optee/optee_os/lib/libutils/isoc/newlib/strstr.c new file mode 100644 index 0000000..349ae4f --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strstr.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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 string segment + +INDEX + strstr + +ANSI_SYNOPSIS + #include + char *strstr(const char *<[s1]>, const char *<[s2]>); + +TRAD_SYNOPSIS + #include + char *strstr(<[s1]>, <[s2]>) + char *<[s1]>; + char *<[s2]>; + +DESCRIPTION + Locates the first occurrence in the string pointed to by <[s1]> of + the sequence of characters in the string pointed to by <[s2]> + (excluding the terminating null character). + +RETURNS + Returns a pointer to the located string segment, or a null + pointer if the string <[s2]> is not found. If <[s2]> points to + a string with zero length, <[s1]> is returned. + +PORTABILITY +<> is ANSI C. + +<> requires no supporting OS subroutines. + +QUICKREF + strstr ansi pure +*/ + +#include "_ansi.h" +#include + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) +# define RETURN_TYPE char * +# define AVAILABLE(h, h_l, j, n_l) \ + (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \ + && ((h_l) = (j) + (n_l))) +# include "str-two-way.h" +#endif + +char * +_DEFUN (strstr, (searchee, lookfor), + _CONST char *searchee _AND + _CONST char *lookfor) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + + /* Less code size, but quadratic performance in the worst case. */ + if (*searchee == 0) + { + if (*lookfor) + return (char *) NULL; + return (char *) searchee; + } + + while (*searchee) + { + size_t i; + i = 0; + + while (1) + { + if (lookfor[i] == 0) + { + return (char *) searchee; + } + + if (lookfor[i] != searchee[i]) + { + break; + } + i++; + } + searchee++; + } + + return (char *) NULL; + +#else /* compilation for speed */ + + /* Larger code size, but guaranteed linear performance. */ + const char *haystack = searchee; + const char *needle = lookfor; + size_t needle_len; /* Length of NEEDLE. */ + size_t haystack_len; /* Known minimum length of HAYSTACK. */ + int ok = 1; /* True if NEEDLE is prefix of HAYSTACK. */ + + /* Determine length of NEEDLE, and in the process, make sure + HAYSTACK is at least as long (no point processing all of a long + NEEDLE if HAYSTACK is too short). */ + while (*haystack && *needle) + ok &= *haystack++ == *needle++; + if (*needle) + return NULL; + if (ok) + return (char *) searchee; + + /* Reduce the size of haystack using strchr, since it has a smaller + linear coefficient than the Two-Way algorithm. */ + needle_len = needle - lookfor; + haystack = strchr (searchee + 1, *lookfor); + if (!haystack || needle_len == 1) + return (char *) haystack; + haystack_len = (haystack > searchee + needle_len ? 1 + : needle_len + searchee - haystack); + + /* Perform the search. */ + if (needle_len < LONG_NEEDLE_THRESHOLD) + return two_way_short_needle ((const unsigned char *) haystack, + haystack_len, + (const unsigned char *) lookfor, needle_len); + return two_way_long_needle ((const unsigned char *) haystack, haystack_len, + (const unsigned char *) lookfor, needle_len); +#endif /* compilation for speed */ +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/strtok_r.c b/optee/optee_os/lib/libutils/isoc/newlib/strtok_r.c new file mode 100644 index 0000000..084f794 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strtok_r.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1988 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 + +static char * +__strtok_r (register char *s, + register const char *delim, + char **lasts, + int skip_leading_delim) +{ + register char *spanp; + register int c, sc; + char *tok; + + + if (s == NULL && (s = *lasts) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) { + if (skip_leading_delim) { + goto cont; + } + else { + *lasts = s; + s[-1] = 0; + return (s - 1); + } + } + } + + if (c == 0) { /* no non-delimiter characters */ + *lasts = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *lasts = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +char * +strtok_r (register char *__restrict s, + register const char *__restrict delim, + char **__restrict lasts) +{ + return __strtok_r (s, delim, lasts, 1); +} diff --git a/optee/optee_os/lib/libutils/isoc/newlib/strtoul.c b/optee/optee_os/lib/libutils/isoc/newlib/strtoul.c new file mode 100644 index 0000000..6ab4a32 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/strtoul.c @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * 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 + <>---string to unsigned long + +INDEX + strtoul +INDEX + _strtoul_r + +ANSI_SYNOPSIS + #include + unsigned long strtoul(const char *<[s]>, char **<[ptr]>, + int <[base]>); + + unsigned long _strtoul(const char *<[s]>, + char **<[ptr]>, int <[base]>); + +TRAD_SYNOPSIS + #include + unsigned long strtoul(<[s]>, <[ptr]>, <[base]>) + char *<[s]>; + char **<[ptr]>; + int <[base]>; + + unsigned long _strtoul(<[s]>, <[ptr]>, <[base]>) + char *<[s]>; + char **<[ptr]>; + int <[base]>; + +DESCRIPTION +The function <> converts the string <<*<[s]>>> to +an <>. First, it breaks down the string into three parts: +leading whitespace, which is ignored; a subject string consisting +of the digits meaningful in the radix specified by <[base]> +(for example, <<0>> through <<7>> if the value of <[base]> is 8); +and a trailing portion consisting of one or more unparseable characters, +which always includes the terminating null character. Then, it attempts +to convert the subject string into an unsigned long integer, and returns the +result. + +If the value of <[base]> is zero, the subject string is expected to look +like a normal C integer constant (save that no optional sign is permitted): +a possible <<0x>> indicating hexadecimal radix, and a number. +If <[base]> is between 2 and 36, the expected form of the subject is a +sequence of digits (which may include letters, depending on the +base) representing an integer in the radix specified by <[base]>. +The letters <>--<> (or <>--<>) are used as digits valued from +10 to 35. If <[base]> is 16, a leading <<0x>> is permitted. + +The subject sequence is the longest initial sequence of the input +string that has the expected form, starting with the first +non-whitespace character. If the string is empty or consists entirely +of whitespace, or if the first non-whitespace character is not a +permissible digit, the subject string is empty. + +If the subject string is acceptable, and the value of <[base]> is zero, +<> attempts to determine the radix from the input string. A +string with a leading <<0x>> is treated as a hexadecimal value; a string with +a leading <<0>> and no <> is treated as octal; all other strings are +treated as decimal. If <[base]> is between 2 and 36, it is used as the +conversion radix, as described above. Finally, a pointer to the first +character past the converted subject string is stored in <[ptr]>, if +<[ptr]> is not <>. + +If the subject string is empty (that is, if <<*>><[s]> does not start +with a substring in acceptable form), no conversion +is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is +not <>). + + + +RETURNS +<> returns the converted value, if any. If no conversion was +made, <<0>> is returned. + +<> returns <> if the magnitude of the converted +value is too large, and sets <> to <>. + +PORTABILITY +<> is ANSI. + +<> requires no supporting OS subroutines. +*/ + +/* + * Copyright (c) 1990 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 "_ansi.h" +#include +#include +#include + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long +_DEFUN (_strtoul, (nptr, endptr, base), + _CONST char *nptr _AND + char **endptr _AND + int base) +{ + register const unsigned char *s = (const unsigned char *)nptr; + register unsigned long acc; + register int c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *) (any ? (char *)s - 1 : nptr); + return (acc); +} + +#ifndef _REENT_ONLY + +unsigned long +_DEFUN (strtoul, (s, ptr, base), + _CONST char *s _AND + char **ptr _AND + int base) +{ + return _strtoul (s, ptr, base); +} + +#endif diff --git a/optee/optee_os/lib/libutils/isoc/newlib/sub.mk b/optee/optee_os/lib/libutils/isoc/newlib/sub.mk new file mode 100644 index 0000000..20031c7 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/newlib/sub.mk @@ -0,0 +1,28 @@ +cflags-y += -Wno-sign-compare +cflags-y += -Wno-parentheses +cflags-remove-y += -Wcast-align + +srcs-y += abs.c +srcs-y += bcmp.c +srcs-y += memchr.c +srcs-y += memcmp.c +srcs-y += memcpy.c +ifeq (s,$(CFG_CC_OPT_LEVEL)) +cflags-memcpy.c-y += -O2 +endif +cflags-memcpy.c-y += $(call cc-option,-fno-tree-loop-distribute-patterns) +srcs-y += memmove.c +cflags-memmove.c-y += $(call cc-option,-fno-tree-loop-distribute-patterns) +srcs-y += memset.c +cflags-memset.c-y += $(call cc-option,-fno-tree-loop-distribute-patterns) +srcs-y += strchr.c +srcs-y += strcmp.c +srcs-y += strcpy.c +srcs-y += strlen.c +srcs-y += strncmp.c +srcs-y += strncpy.c +srcs-y += strnlen.c +srcs-y += strrchr.c +srcs-y += strstr.c +srcs-y += strtoul.c +srcs-y += strtok_r.c diff --git a/optee/optee_os/lib/libutils/isoc/qsort.c b/optee/optee_os/lib/libutils/isoc/qsort.c new file mode 100644 index 0000000..d2d8127 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/qsort.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* $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 = (uintptr_t)a % 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/optee/optee_os/lib/libutils/isoc/snprintf.c b/optee/optee_os/lib/libutils/isoc/snprintf.c new file mode 100644 index 0000000..f5cf74a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/snprintf.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include + +int snprintf(char *bf, size_t size, const char *fmt, ...) +{ + int retval; + va_list ap; + + va_start(ap, fmt); + retval = __vsnprintf(bf, size, fmt, ap, false); + va_end(ap); + + return retval; +} + +int vsnprintf(char *bf, size_t size, const char *fmt, va_list ap) +{ + return __vsnprintf(bf, size, fmt, ap, false); +} diff --git a/optee/optee_os/lib/libutils/isoc/sprintf.c b/optee/optee_os/lib/libutils/isoc/sprintf.c new file mode 100644 index 0000000..d88fe41 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/sprintf.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ + +#include +#include +#include +#include + +int sprintf(char *str, const char *fmt, ...) +{ + int retval; + va_list ap; + + va_start(ap, fmt); + retval = __vsprintf(str, fmt, ap); + va_end(ap); + + return retval; +} + +int __sprintf_chk(char *str, int flag __unused, size_t slen, + const char *fmt, ...) +{ + int retval; + va_list ap; + + if (slen == 0) + abort(); + + va_start(ap, fmt); + retval = __vsnprintf(str, slen, fmt, ap, false); + va_end(ap); + + if (retval > 0 && (size_t)retval >= slen) + abort(); + + return retval; +} diff --git a/optee/optee_os/lib/libutils/isoc/stack_check.c b/optee/optee_os/lib/libutils/isoc/stack_check.c new file mode 100644 index 0000000..f800a2b --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/stack_check.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include +#include + +#if defined(__KERNEL__) +# include +# define PANIC() panic() +#elif defined(__LDELF__) +# include +# define PANIC() _ldelf_panic(2) +#else +# include +# define PANIC() _utee_panic(TEE_ERROR_OVERFLOW) +#endif + +void *__stack_chk_guard __nex_data = (void *)0x00000aff; + +void __attribute__((noreturn)) __stack_chk_fail(void); + +void __stack_chk_fail(void) +{ + EMSG_RAW("stack smashing detected"); + while (1) + PANIC(); +} + diff --git a/optee/optee_os/lib/libutils/isoc/strdup.c b/optee/optee_os/lib/libutils/isoc/strdup.c new file mode 100644 index 0000000..be7f59a --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/strdup.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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/optee/optee_os/lib/libutils/isoc/strndup.c b/optee/optee_os/lib/libutils/isoc/strndup.c new file mode 100644 index 0000000..dd2934e --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/strndup.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#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/optee/optee_os/lib/libutils/isoc/sub.mk b/optee/optee_os/lib/libutils/isoc/sub.mk new file mode 100644 index 0000000..ef1ca5d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/sub.mk @@ -0,0 +1,40 @@ +global-incdirs-y += include + +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 +ifeq ($(sm),core) +cflags-remove-bget_malloc.c-y += $(cflags_kasan) +endif +srcs-y += isdigit.c +srcs-y += isxdigit.c +srcs-y += qsort.c +cflags-qsort.c-y += -Wno-inline +cflags-remove-qsort.c-y += -Wcast-align +srcs-y += sprintf.c +srcs-y += snprintf.c +srcs-y += stack_check.c +srcs-y += strdup.c +srcs-y += strndup.c +srcs-y += tolower.c +srcs-y += isalpha.c +srcs-y += isspace.c +srcs-y += isupper.c +srcs-y += isalnum.c +srcs-y += iscntrl.c +srcs-y += isgraph.c +srcs-y += islower.c +srcs-y += isprint.c +srcs-y += ispunct.c +srcs-y += toupper.c + +ifneq (,$(filter ta_%,$(sm))) +srcs-y += fp.c +srcs-y += fputc.c +srcs-y += fputs.c +srcs-y += fwrite.c +srcs-y += write.c +endif + +subdirs-y += newlib +subdirs-y += arch/$(ARCH) diff --git a/optee/optee_os/lib/libutils/isoc/tolower.c b/optee/optee_os/lib/libutils/isoc/tolower.c new file mode 100644 index 0000000..1700b9d --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/tolower.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + */ +#include + +int tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + return c; +} diff --git a/optee/optee_os/lib/libutils/isoc/toupper.c b/optee/optee_os/lib/libutils/isoc/toupper.c new file mode 100644 index 0000000..8cfa0d1 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/toupper.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, KAIST + */ +#include + +int toupper(int c) +{ + if (c >= 'a' && c <= 'z') + return c - 'a' + 'A'; + return c; +} diff --git a/optee/optee_os/lib/libutils/isoc/write.c b/optee/optee_os/lib/libutils/isoc/write.c new file mode 100644 index 0000000..987de95 --- /dev/null +++ b/optee/optee_os/lib/libutils/isoc/write.c @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020, Huawei Technologies Co., Ltd + */ + +#include +#include +#include + +ssize_t write(int fd, const void *buf, size_t count) +{ + if (fd != 1 && fd != 2) + abort(); + + return printf("%*s", (int)count, (char *)buf); +} diff --git a/optee/optee_os/lib/libutils/sub.mk b/optee/optee_os/lib/libutils/sub.mk new file mode 100644 index 0000000..e49bd89 --- /dev/null +++ b/optee/optee_os/lib/libutils/sub.mk @@ -0,0 +1,2 @@ +subdirs-$(CFG_LIBUTILS_WITH_ISOC) += isoc +subdirs-y += ext diff --git a/optee/optee_os/mk/aosp_optee.mk b/optee/optee_os/mk/aosp_optee.mk new file mode 100644 index 0000000..1a9b175 --- /dev/null +++ b/optee/optee_os/mk/aosp_optee.mk @@ -0,0 +1,136 @@ +########################################################## +## Common mk file used for Android to compile and ## +## integrate OP-TEE related components ## +## Following flags need to be defined in optee*.mk ## +## OPTEE_OS_DIR ## +## OPTEE_TA_TARGETS ## +## OPTEE_CFG_ARM64_CORE ## +## OPTEE_PLATFORM ## +## OPTEE_PLATFORM_FLAVOR ## +## OPTEE_EXTRA_FLAGS (optional) ## +## OPTEE_EXTRA_TA_FLAGS (optional) ## +## And BUILD_OPTEE_MK needs to be defined in optee*.mk ## +## to point to this file ## +## ## +## local_module needs to be defined before including ## +## this file to build TAs ## +## ## +########################################################## + +########################################################## +## define common variables, like TA_DEV_KIT_DIR ## +########################################################## +TOP_ROOT_ABS := $(realpath $(TOP)) + +PREBUILT_MAKE ?= prebuilts/build-tools/linux-x86/bin/make +# we need this check because the Pie build does not have +# this prebuilt make tool +ifneq (,$(wildcard $(PREBUILT_MAKE))) +# for master and versions which has prebuilt make +HOST_MAKE := $(PREBUILT_MAKE) + +# The AOSP build tool is not the regular make, +# that it adds -jN to $(MAKE), and that we should preserve +# the flag or we would lose parallel build +# The MAKE is redefined here in AOSP ckati: +# https://android.googlesource.com/platform/build/kati/+/master/main.cc#100 +ifneq (,$(filter -j%, $(MAKE))) +HOST_MAKE += $(filter -j%, $(MAKE)) +endif + +else +# For P and old versions which does not have prebuilt make, +# let's use MAKE as what we did before +HOST_MAKE := $(MAKE) +endif + + +# OPTEE_OUT_DIR could be exported explicitly +# if PRODUCT_OUT is not the default out directory in aosp workspace +OPTEE_OUT_DIR ?= $(PRODUCT_OUT)/optee +ABS_OPTEE_OUT_DIR ?= $(realpath $(PRODUCT_OUT))/optee +OPTEE_TA_OUT_DIR ?= $(OPTEE_OUT_DIR)/ta +ABS_OPTEE_TA_OUT_DIR ?= $(ABS_OPTEE_OUT_DIR)/ta +# Set so that OP-TEE clients can find the installed dev-kit, which +# depends on platform and its OP-TEE word-size. +OPTEE_OS_OUT_DIR ?= $(OPTEE_OUT_DIR)/arm-plat-$(OPTEE_PLATFORM) +ABS_OPTEE_OS_OUT_DIR := $(ABS_OPTEE_OUT_DIR)/arm-plat-$(OPTEE_PLATFORM) +TA_DEV_KIT_DIR := $(ABS_OPTEE_OS_OUT_DIR)/export-${OPTEE_TA_TARGETS} + +CROSS_COMPILE64 ?= $(TOP_ROOT_ABS)/$(TARGET_TOOLS_PREFIX) +CROSS_COMPILE_LINE := CROSS_COMPILE64="$(CROSS_COMPILE64)" +ifneq ($(strip $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)),) +CROSS_COMPILE32 ?= $(TOP_ROOT_ABS)/$($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX) +CROSS_COMPILE_LINE += CROSS_COMPILE32="$(CROSS_COMPILE32)" +endif + +OPTEE_BIN := $(OPTEE_OS_OUT_DIR)/core/tee.bin + +$(OPTEE_BIN) : $(sort $(shell find -L $(OPTEE_OS_DIR))) + +########################################################### +## define making rules for $(OPTEE_BIN) target, and add ## +## condition check to make it only be defined once ## +## even though this mk file might be included multiple ## +## times. The process to generate $(OPTEE_BIN) file will ## +## generate the header files under ## +## $(TA_DEV_KIT_DIR)/host_include too. ## +## And the $(OPTEE_BIN) will be used as dependency for ## +## other projects ## +########################################################### +ifneq (true,$(BUILD_OPTEE_OS_DEFINED)) +BUILD_OPTEE_OS_DEFINED := true +$(OPTEE_BIN): + @echo "Start building optee_os..." + +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \ + O=$(ABS_OPTEE_OS_OUT_DIR) \ + CFG_USER_TA_TARGETS=$(OPTEE_TA_TARGETS) \ + CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \ + PLATFORM=$(OPTEE_PLATFORM) \ + PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \ + $(CROSS_COMPILE_LINE) \ + $(OPTEE_EXTRA_FLAGS) + @echo "Finished building optee_os..." + +endif + +########################################################## +## Lines for building TAs automatically ## +## will only be included in Android.mk for TAs ## +## local_module: ## +## need to be defined before include for this ## +########################################################## +ifneq (false,$(INCLUDE_FOR_BUILD_TA)) +include $(CLEAR_VARS) + +LOCAL_MODULE := $(local_module) +LOCAL_PREBUILT_MODULE_FILE := $(OPTEE_TA_OUT_DIR)/$(LOCAL_MODULE) +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/optee_armtz +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_MODULE_TAGS := optional + +TA_TMP_DIR := $(subst /,_,$(LOCAL_PATH)) +TA_TMP_FILE := $(OPTEE_TA_OUT_DIR)/$(TA_TMP_DIR)/$(LOCAL_MODULE) +$(LOCAL_PREBUILT_MODULE_FILE): $(TA_TMP_FILE) + @mkdir -p $(dir $@) + cp -vf $< $@ + +TA_TMP_FILE_DEPS := +ifneq ($(local_module_deps), ) +$(foreach dep,$(local_module_deps), $(eval TA_TMP_FILE_DEPS += $(TARGET_OUT_VENDOR)/lib/optee_armtz/$(dep))) +endif +$(TA_TMP_FILE): $(TA_TMP_FILE_DEPS) +$(TA_TMP_FILE): PRIVATE_TA_SRC_DIR := $(LOCAL_PATH) +$(TA_TMP_FILE): PRIVATE_TA_TMP_FILE := $(TA_TMP_FILE) +$(TA_TMP_FILE): PRIVATE_TA_TMP_DIR := $(TA_TMP_DIR) +$(TA_TMP_FILE): $(OPTEE_BIN) + @echo "Start building TA for $(PRIVATE_TA_SRC_DIR) $(PRIVATE_TA_TMP_FILE)..." + +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(PRIVATE_TA_SRC_DIR) O=$(ABS_OPTEE_TA_OUT_DIR)/$(PRIVATE_TA_TMP_DIR) \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + $(CROSS_COMPILE_LINE) \ + $(OPTEE_EXTRA_TA_FLAGS) + @echo "Finished building TA for $(PRIVATE_TA_SRC_DIR) $(PRIVATE_TA_TMP_FILE)..." + +include $(BUILD_PREBUILT) +local_module_deps := +endif diff --git a/optee/optee_os/mk/cc-option.mk b/optee/optee_os/mk/cc-option.mk new file mode 100644 index 0000000..622346a --- /dev/null +++ b/optee/optee_os/mk/cc-option.mk @@ -0,0 +1,17 @@ +_cc-option-supported = $(if $(shell $(CC$(sm)) $(1) -c -x c /dev/null -o /dev/null 2>/dev/null >/dev/null || echo "Not supported"),,1) +_cc-opt-cached-var-name = $(subst =,~,$(strip cached-cc-option-$(1)-$(subst $(empty) $(empty),,$(CC$(sm))))) +define _cc-option +$(eval _var_name := $(call _cc-opt-cached-var-name,$(1))) +$(eval $(_var_name) := $(if $(filter $(origin $(_var_name)),undefined),$(call _cc-option-supported,$(1)),$($(_var_name)))) +$(if $($(_var_name)),$(1),$(2)) +endef +cc-option = $(strip $(call _cc-option,$(1),$(2))) + +_ld-option-supported = $(if $(shell ($(LD$(sm)) -v $(1) 2>&1 || echo warning) | grep warning),,1) +_ld-opt-cached-var-name = $(subst =,~,$(subst $(empty) $(empty),,$(strip cached-ld-option-$(1)-$(LD$(sm))))) +define _ld-option +$(eval _var_name := $(call _ld-opt-cached-var-name,$(1))) +$(eval $(_var_name) := $(if $(filter $(origin $(_var_name)),undefined),$(call _ld-option-supported,$(1)),$($(_var_name)))) +$(if $($(_var_name)),$(1),$(2)) +endef +ld-option = $(strip $(call _ld-option,$(1),$(2))) diff --git a/optee/optee_os/mk/checkconf.mk b/optee/optee_os/mk/checkconf.mk new file mode 100644 index 0000000..77b3748 --- /dev/null +++ b/optee/optee_os/mk/checkconf.mk @@ -0,0 +1,193 @@ +# Generate/check/update a .h file to reflect the values of Makefile +# variables +# +# Example usage (by default, check-conf-h will consider all CFG_* +# and _CFG_* variables plus PLATFORM_*): +# +# path/to/conf.h: FORCE +# $(call check-conf-h) +# +# Or, to include only the variables with the given prefix(es): +# +# path/to/crypto_config.h: FORCE +# $(call check-conf-h,CFG_CRYPTO_ CRYPTO_) +define check-conf-h + $(q)set -e; \ + $(cmd-echo-silent) ' CHK $@'; \ + cnf='$(strip $(foreach var, \ + $(call cfg-vars-by-prefix,$1), \ + $(call cfg-make-define,$(var))))'; \ + guard="_`echo $@ | tr -- -/.+ _`_"; \ + mkdir -p $(dir $@); \ + echo "#ifndef $${guard}" >$@.tmp; \ + echo "#define $${guard}" >>$@.tmp; \ + echo -n "$${cnf}" | sed 's/_nl_ */\n/g' >>$@.tmp; \ + echo "#endif" >>$@.tmp; \ + $(call mv-if-changed,$@.tmp,$@) +endef + +define check-conf-cmake + $(q)set -e; \ + $(cmd-echo-silent) ' CHK $@'; \ + cnf='$(strip $(foreach var, \ + $(call cfg-vars-by-prefix,$1), \ + $(call cfg-cmake-set,$(var))))'; \ + mkdir -p $(dir $@); \ + echo "# auto-generated TEE configuration file" >$@.tmp; \ + echo "# TEE version ${TEE_IMPL_VERSION}" >>$@.tmp; \ + echo -n "$${cnf}" | sed 's/_nl_ */\n/g' >>$@.tmp; \ + $(call mv-if-changed,$@.tmp,$@) +endef + +define check-conf-mk + $(q)set -e; \ + $(cmd-echo-silent) ' CHK $@'; \ + cnf='$(strip $(foreach var, \ + $(call cfg-vars-by-prefix,CFG_), \ + $(strip $(var)=$($(var))_nl_)))'; \ + mkdir -p $(dir $@); \ + echo "# auto-generated TEE configuration file" >$@.tmp; \ + echo "# TEE version ${TEE_IMPL_VERSION}" >>$@.tmp; \ + echo "ARCH=${ARCH}" >>$@.tmp; \ + echo "PLATFORM=${PLATFORM}" >>$@.tmp; \ + echo "PLATFORM_FLAVOR=${PLATFORM_FLAVOR}" >>$@.tmp; \ + echo -n "$${cnf}" | sed 's/_nl_ */\n/g' >>$@.tmp; \ + $(call mv-if-changed,$@.tmp,$@) +endef + +# Rename $1 to $2 only if file content differs. Otherwise just delete $1. +define mv-if-changed + if cmp -s $2 $1; then \ + rm -f $1; \ + else \ + $(cmd-echo-silent) ' UPD $2'; \ + mv $1 $2; \ + fi +endef + +define cfg-vars-by-prefix + $(strip $(if $(1),$(call _cfg-vars-by-prefix,$(1)), + $(call _cfg-vars-by-prefix,CFG_ _CFG_ PLATFORM_))) +endef + +define _cfg-vars-by-prefix + $(sort $(foreach prefix,$(1),$(filter $(prefix)%,$(.VARIABLES)))) +endef + +# Convert a makefile variable to a #define +# , n => +# y => 1 +# => +define cfg-make-define + $(strip $(if $(filter y,$($1)), + #define $1 1_nl_, + $(if $(filter xn x,x$($1)), + /* $1 is not set */_nl_, + #define $1 $($1)_nl_))) +endef + +# Convert a makefile variable to a cmake set statement +# , n => +# => +define cfg-cmake-set + $(strip $(if $(filter xn x,x$($1)), + # $1 is not set _nl_, + set($1 $($1))_nl_)) +endef + +# Returns 'y' if at least one variable is 'y', 'n' otherwise +# Example: +# FOO_OR_BAR := $(call cfg-one-enabled, FOO BAR) +cfg-one-enabled = $(if $(filter y, $(foreach var,$(1),$($(var)))),y,n) + +# Returns 'y' if all variables are 'y', 'n' otherwise +# Example: +# FOO_AND_BAR := $(call cfg-all-enabled, FOO BAR) +cfg-all-enabled = $(if $(strip $(1)),$(if $(call _cfg-all-enabled,$(1)),y,n),n) +_cfg-all-enabled = \ + $(strip \ + $(if $(1), \ + $(if $(filter y,$($(firstword $(1)))), \ + $(call _cfg-all-enabled,$(filter-out $(firstword $(1)),$(1))), \ + ), \ + y \ + ) \ + ) + +# Disable a configuration variable if some dependency is disabled +# Example: +# $(eval $(call cfg-depends-all,FOO,BAR BAZ)) +# Will set FOO to 'n' if it is initially 'y' and BAR or BAZ are not 'y' +cfg-depends-all = \ + $(strip \ + $(if $(filter y, $($(1))), \ + $(if $(filter y,$(call cfg-all-enabled,$(2))), \ + , \ + $(warning Warning: Disabling $(1) [requires $(strip $(2))]) \ + override $(1) := n \ + ) \ + ) \ + ) + +# Disable a configuration variable if all dependencies are disabled +# Example: +# $(eval $(call cfg-depends-one,FOO,BAR BAZ)) +# Will set FOO to 'n' if it is initially 'y' and both BAR and BAZ are not 'y' +cfg-depends-one = \ + $(strip \ + $(if $(filter y, $($(1))), \ + $(if $(filter y,$(call cfg-one-enabled,$(2))), \ + , \ + $(warning Warning: Disabling $(1) [requires (one of) $(strip $(2))]) \ + override $(1) := n \ + ) \ + ) \ + ) + + +# Enable all depend variables +# Example: +# $(eval $(call cfg-enable-all-depends,FOO,BAR BAZ)) +# Will enable BAR and BAZ if FOO is initially 'y' +cfg-enable-all-depends = \ + $(strip \ + $(if $(2), \ + $(if $(filter y, $($(1))), \ + $(if $(filter y,$($(firstword $(2)))), \ + , \ + $(warning Warning: Enabling $(firstword $(2)) [required by $(1)]) \ + $(eval override $(firstword $(2)) := y) \ + ) \ + $(call cfg-enable-all-depends,$(1),$(filter-out $(firstword $(2)),$(2))), \ + ) \ + , \ + ) \ + ) + +# Check if a configuration variable has an acceptable value +# Example: +# $(call cfg-check-value,FOO,foo bar) +# Will do nothing if $(CFG_FOO) is either foo or bar, and error out otherwise. +cfg-check-value = \ + $(if $(filter-out $(2),$(CFG_$(1))), \ + $(error CFG_$(1) is set to '$(CFG_$(1))', valid values are: $(2))) + +# Set a variable or error out if it was previously set to a different value +# The reason message (3rd parameter) is optional +# Example: +# $(call force,CFG_FOO,foo,required by CFG_BAR) +define force +$(eval $(call _force,$(strip $(1)),$(2),$(3))) +endef + +define _force +ifdef $(1) +ifneq ($($(1)),$(2)) +ifneq (,$(3)) +_reason := $$(_empty) [$(3)] +endif +$$(error $(1) is set to '$($(1))' (from $(origin $(1))) but its value must be '$(2)'$$(_reason)) +endif +endif +$(1) := $(2) +endef diff --git a/optee/optee_os/mk/clang.mk b/optee/optee_os/mk/clang.mk new file mode 100644 index 0000000..a045bee --- /dev/null +++ b/optee/optee_os/mk/clang.mk @@ -0,0 +1,53 @@ +# CROSS_COMPILE_$(sm) is derived from CROSS_COMPILE/CROSS_COMPILE32/ +# CROSS_COMPILE64 and indicates the target that should be passed to clang. Path +# components are ignored, as well as any command before the compiler name (for +# instance "/some/path/ccache /other/path/arm-linux-gnueabihf-"). +# We try to extract any ccache command if present. +clang-target := $(patsubst %-,%,$(notdir $(lastword $(CROSS_COMPILE_$(sm))))) +ifeq ($(clang-target),aarch64-linux) +clang-target := aarch64-linux-gnu +endif +ccache-cmd := $(if $(findstring ccache,$(CROSS_COMPILE_$(sm))),$(firstword $(CROSS_COMPILE_$(sm))) ,) + +CC$(sm) := $(ccache-cmd)$(OPTEE_CLANG_COMPILER_PATH)clang --target=$(clang-target) +CXX$(sm) := false # Untested yet +# Due to the absence of clang-cpp in AOSP's prebuilt version of clang, +# use the equivalent command of 'clang -E' +CPP$(sm) := $(ccache-cmd)$(OPTEE_CLANG_COMPILER_PATH)clang --target=$(clang-target) -E +LD$(sm) := $(ccache-cmd)$(OPTEE_CLANG_COMPILER_PATH)ld.lld + +AR$(sm) := $(ccache-cmd)$(OPTEE_CLANG_COMPILER_PATH)llvm-ar +NM$(sm) := $(OPTEE_CLANG_COMPILER_PATH)llvm-nm +OBJCOPY$(sm) := $(OPTEE_CLANG_COMPILER_PATH)llvm-objcopy +OBJDUMP$(sm) := $(OPTEE_CLANG_COMPILER_PATH)llvm-objdump +READELF$(sm) := $(OPTEE_CLANG_COMPILER_PATH)llvm-readelf + +nostdinc$(sm) := -nostdinc -isystem $(shell $(CC$(sm)) \ + -print-file-name=include 2> /dev/null) + +comp-cflags-warns-clang := -Wno-language-extension-token \ + -Wno-gnu-zero-variadic-macro-arguments + +# Note, use the compiler runtime library (libclang_rt.builtins.*.a) instead of +# libgcc for clang +libgcc$(sm) := $(shell $(CC$(sm)) $(CFLAGS$(arch-bits-$(sm))) \ + -rtlib=compiler-rt -print-libgcc-file-name 2> /dev/null) + +# Core ASLR relies on the executable being ready to run from its preferred load +# address, because some symbols are used before the MMU is enabled and the +# relocations are applied. +ldflag-apply-dynamic-relocs := --apply-dynamic-relocs + +# Define these to something to discover accidental use +CC := false +CXX := false +CPP := false +LD := false +AR := false +NM := false +OBJCOPY := false +OBJDUMP := false +READELF := false +nostdinc := --bad-nostdinc-variable +libgcc := --bad-libgcc-variable + diff --git a/optee/optee_os/mk/cleandirs.mk b/optee/optee_os/mk/cleandirs.mk new file mode 100644 index 0000000..6c42b53 --- /dev/null +++ b/optee/optee_os/mk/cleandirs.mk @@ -0,0 +1,42 @@ +# Cleaning directories generated during a previous build, +# a failed previous build or even no previous build. +# Track build directories through 'cleanfiles'. + +define _enum-parent-dirs +$(if $(1),$(1) $(if $(filter / ./,$(dir $(1))),,$(call enum-parent-dirs,$(dir $(1)))),) +endef + +define enum-parent-dirs +$(call _enum-parent-dirs,$(patsubst %/,%,$(1))) +endef + +define _reverse +$(if $(1),$(call _reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1)) +endef + +# Returns the list of all existing output directories up to $(O) including all +# intermediate levels, in depth first order so that rmdir can process them in +# order. May return an empty string. +# Example: if cleanfiles is "foo/a/file1 foo/b/c/d/file2" and O=foo, this will +# return "foo/b/c/d foo/b/c foo/b foo/a" (assuming all exist). +define cleandirs-for-rmdir +$(eval _O:=$(if $(O),$(O),.))$(wildcard $(addprefix $(_O)/,$(call _reverse, + $(sort $(foreach d,$(patsubst $(_O)/%,%,$(dir $(cleanfiles))), + $(call enum-parent-dirs,$(d))))))) +endef + +RMDIR := rmdir --ignore-fail-on-non-empty + +# Remove files with "rm -f". +# Split (possibly huge) file list into more manageable lines +# (200 files at a time), to minimize the odds of having: +# "/bin/bash: Argument list too long" +define do-rm-f + $(call _do-rm-f, $(wordlist 1, 200, $(1))) \ + $(eval _tail := $(wordlist 201, $(words $(1)), $(1))) + $(if $(_tail), $(call do-rm-f, $(_tail))) +endef + +define _do-rm-f + ${q}rm -f $1 +endef diff --git a/optee/optee_os/mk/cleanvars.mk b/optee/optee_os/mk/cleanvars.mk new file mode 100644 index 0000000..57ed631 --- /dev/null +++ b/optee/optee_os/mk/cleanvars.mk @@ -0,0 +1,12 @@ +# Cleans all output variables from other make files to allow for a new start + +gen-srcs := +spec-srcs := +srcs := +objs := +libfiles := +libdirs := +libnames := +libdeps := +sm-$(sm) := +incdirs := diff --git a/optee/optee_os/mk/compile.mk b/optee/optee_os/mk/compile.mk new file mode 100644 index 0000000..2c29deb --- /dev/null +++ b/optee/optee_os/mk/compile.mk @@ -0,0 +1,306 @@ +# Input +# +# The output from mk/sub.mk +# base-prefix +# conf-file [optional] if set, all objects will depend on $(conf-file) +# additional-compile-deps [optional] additional dependencies +# +# Output +# +# set objs +# update cleanfiles +# +# Generates explicit rules for all objs + +objs := + +# Disable all builtin rules +.SUFFIXES: + +comp-cflags$(sm) = -std=gnu11 +comp-aflags$(sm) = +comp-cppflags$(sm) = + +ifeq ($(CFG_WERROR),y) +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 \ + -Wno-c2x-extensions +ifeq ($(CFG_WARN_DECL_AFTER_STATEMENT),y) +comp-cflags-warns-high += $(call cc-option,-Wdeclaration-after-statement) +endif +comp-cflags-warns-medium = \ + -Wredundant-decls +comp-cflags-warns-low = \ + -Wold-style-definition -Wstrict-aliasing=2 \ + -Wundef + +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)) \ + $(comp-cflags-warns-$(COMPILER_$(sm))) + +CHECK ?= sparse + +.PHONY: FORCE +.PHONY: FORCE-GENSRC$(sm) +FORCE: +FORCE-GENSRC$(sm): + + +define process_srcs +objs += $2 +comp-dep-$2 := $$(dir $2).$$(notdir $2).d +comp-cmd-file-$2:= $$(dir $2).$$(notdir $2).cmd +comp-sm-$2 := $(sm) +comp-lib-$2 := $(libname)-$(sm) + +cleanfiles := $$(cleanfiles) $$(comp-dep-$2) $$(comp-cmd-file-$2) $2 + +ifeq ($$(filter %.c,$1),$1) +comp-q-$2 := CC # one trailing space +comp-compiler-$2 := $$(CC$(sm)) +comp-flags-$2 = $$(filter-out $$(CFLAGS_REMOVE) $$(cflags-remove) \ + $$(cflags-remove-$$(comp-sm-$2)) \ + $$(cflags-remove-$2), \ + $$(CFLAGS$$(arch-bits-$$(comp-sm-$2))) $$(CFLAGS_WARNS) \ + $$(comp-cflags$$(comp-sm-$2)) $$(cflags$$(comp-sm-$2)) \ + $$(cflags-lib$$(comp-lib-$2)) $$(cflags-$2)) +ifeq ($C,1) +check-cmd-$2 = $(CHECK) $$(comp-cppflags-$2) $$< +echo-check-$2 := $(cmd-echo-silent) +echo-check-cmd-$2 = $(cmd-echo) $$(subst \",\\\",$$(check-cmd-$2)) +endif + +else ifeq ($$(filter %.S,$1),$1) +comp-q-$2 := AS # one trailing space +comp-compiler-$2 := $$(CC$(sm)) +comp-flags-$2 = $$(filter-out $$(AFLAGS_REMOVE) $$(aflags-remove) \ + $$(aflags-remove-$$(comp-sm-$2)) \ + $$(aflags-remove-$2), \ + $$(AFLAGS) $$(comp-aflags$$(comp-sm-$2)) \ + $$(aflags$$(comp-sm-$2)) $$(aflags-$2)) + +else ifeq ($$(filter %.cpp,$1),$1) +comp-q-$2 := CXX +comp-compiler-$2 := $$(CXX$(sm)) +comp-flags-$2 = $$(filter-out $$(CXXFLAGS_REMOVE) $$(cxxflags-remove) \ + $$(cxxflags-remove-$$(comp-sm-$2)) \ + $$(cxxflags-remove-$2), \ + $$(CXXFLAGS) $$(comp-cxxflags$$(comp-sm-$2)) \ + $$(cxxflags$$(comp-sm-$2)) $$(cxxflags-$2)) + +else +$$(error "Don't know what to do with $1") +endif + +comp-cppflags-$2 = $$(filter-out $$(CPPFLAGS_REMOVE) $$(cppflags-remove) \ + $$(cppflags-remove-$$(comp-sm-$2)) \ + $$(cppflags-remove-$2), \ + $$(nostdinc$$(comp-sm-$2)) $$(CPPFLAGS) \ + $$(addprefix -I,$$(incdirs$$(comp-sm-$2))) \ + $$(addprefix -I,$$(incdirs-lib$$(comp-lib-$2))) \ + $$(addprefix -I,$$(incdirs-$2)) \ + $$(cppflags$$(comp-sm-$2)) \ + $$(cppflags-lib$$(comp-lib-$2)) $$(cppflags-$2)) \ + -D__FILE_ID__=$$(subst -,_,$$(subst /,_,$$(subst .,_,$1))) + +comp-flags-$2 += -MD -MF $$(comp-dep-$2) -MT $$@ +comp-flags-$2 += $$(comp-cppflags-$2) + +comp-cmd-$2 = $$(comp-compiler-$2) $$(comp-flags-$2) -c $$< -o $$@ +comp-objcpy-cmd-$2 = $$(OBJCOPY$(sm)) \ + --rename-section .rodata=.rodata.$1 \ + --rename-section .rodata.str1.1=.rodata.str1.1.$1 \ + $2 + +# Assign defaults if unassigned +echo-check-$2 ?= true +echo-check-cmd-$2 ?= true +check-cmd-$2 ?= true + +-include $$(comp-cmd-file-$2) +-include $$(comp-dep-$2) + + +$2: $1 FORCE-GENSRC$(sm) +# Check if any prerequisites are newer than the target and +# check if command line has changed + $$(if $$(strip $$(filter-out FORCE-GENSRC$(sm), $$?) \ + $$(filter-out $$(comp-cmd-$2), $$(old-cmd-$2)) \ + $$(filter-out $$(old-cmd-$2), $$(comp-cmd-$2))), \ + @set -e ;\ + mkdir -p $$(dir $2) ;\ + $$(echo-check-$2) ' CHECK $$<' ;\ + $$(echo-check-cmd-$2) ;\ + $$(check-cmd-$2) ;\ + $(cmd-echo-silent) ' $$(comp-q-$2) $$@' ;\ + $(cmd-echo) $$(subst \",\\\",$$(comp-cmd-$2)) ;\ + $$(comp-cmd-$2) ;\ + $(cmd-echo) $$(comp-objcpy-cmd-$2) ;\ + $$(comp-objcpy-cmd-$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))) + +# Handle generated source files, that is, files that are compiled from out-dir +$(foreach f, $(gen-srcs), $(eval $(call process_srcs,$(f),$$(basename $f).o))) + +# Handle specified source files, that is, files that have a specified path +# but where the object file should go into a specified out directory +$(foreach f, $(spec-srcs), $(eval $(call \ + process_srcs,$(f),$(spec-out-dir)/$$(notdir $$(basename $f)).o))) + +$(objs): $(conf-file) $(additional-compile-deps) + +define _gen-asm-defines-file +# c-filename in $1 +# h-filename in $2 +# s-filename in $3 +# Dependencies in $4 + +FORCE-GENSRC$(sm): $(2) + +comp-dep-$3 := $$(dir $3)$$(notdir $3).d +comp-cmd-file-$3:= $$(dir $3)$$(notdir $3).cmd +comp-sm-$3 := $(sm) + +cleanfiles := $$(cleanfiles) $$(comp-dep-$3) $$(comp-cmd-file-$3) $3 $2 + +comp-flags-$3 = $$(filter-out $$(CFLAGS_REMOVE) $$(cflags-remove) \ + $$(cflags-remove-$$(comp-sm-$3)) \ + $$(cflags-remove-$3), \ + $$(CFLAGS) $$(CFLAGS_WARNS) \ + $$(comp-cflags$$(comp-sm-$3)) $$(cflags$$(comp-sm-$3)) \ + $$(cflags-lib$$(comp-lib-$3)) $$(cflags-$3)) + +comp-cppflags-$3 = $$(filter-out $$(CPPFLAGS_REMOVE) $$(cppflags-remove) \ + $$(cppflags-remove-$$(comp-sm-$3)) \ + $$(cppflags-remove-$3), \ + $$(nostdinc$$(comp-sm-$3)) $$(CPPFLAGS) \ + $$(addprefix -I,$$(incdirs$$(comp-sm-$3))) \ + $$(addprefix -I,$$(incdirs-lib$$(comp-lib-$3))) \ + $$(addprefix -I,$$(incdirs-$3)) \ + $$(cppflags$$(comp-sm-$3)) \ + $$(cppflags-lib$$(comp-lib-$3)) $$(cppflags-$3)) + +comp-flags-$3 += -MD -MF $$(comp-dep-$3) -MT $$@ +comp-flags-$3 += $$(comp-cppflags-$3) + +comp-cmd-$3 = $$(CC$(sm)) $$(comp-flags-$3) -fverbose-asm -S $$< -o $$@ + + +-include $$(comp-cmd-file-$3) +-include $$(comp-dep-$3) + +$3: $1 $(conf-file) $(4) FORCE +# Check if any prerequisites are newer than the target and +# check if command line has changed + $$(if $$(strip $$(filter-out FORCE, $$?) \ + $$(filter-out $$(comp-cmd-$3), $$(old-cmd-$3)) \ + $$(filter-out $$(old-cmd-$3), $$(comp-cmd-$3))), \ + @set -e ;\ + mkdir -p $$(dir $2) $$(dir $3) ;\ + $(cmd-echo-silent) ' CC $$@'; \ + $(cmd-echo) $$(subst \",\\\",$$(comp-cmd-$3)) ;\ + $$(comp-cmd-$3) ;\ + echo "old-cmd-$3 := $$(subst \",\\\",$$(comp-cmd-$3))" > \ + $$(comp-cmd-file-$3) ;\ + ) + +guard-$2 := $$(subst -,_,$$(subst .,_,$$(subst /,_,$$(subst +,_,$2)))) + +$(2): $(3) + $(q)set -e; \ + $(cmd-echo-silent) ' CHK $$@'; \ + mkdir -p $$(dir $$@); \ + echo "#ifndef $$(guard-$2)" >$$@.tmp; \ + echo "#define $$(guard-$2)" >>$$@.tmp; \ + sed -ne 's|^.*==>\([^ ]*\) [\$$$$#]*\([-0-9]*\) \([^@/]*\).*|#define \1\t\2\t/* \3*/|p' \ + < $$< >>$$@.tmp; \ + echo "#endif" >>$$@.tmp; \ + $$(call mv-if-changed,$$@.tmp,$$@) + +endef + +define gen-asm-defines-file +$(call _gen-asm-defines-file,$1,$2,$(dir $2).$(notdir $(2:.h=.s)),$(asm-defines-$(notdir $(1))-deps)) +endef + +$(foreach f,$(asm-defines-files),$(eval $(call gen-asm-defines-file,$(f),$(out-dir)/$(sm)/include/generated/$(basename $(notdir $(f))).h))) + +# Device tree source file compilation +DTC := dtc +DTC_FLAGS += -I dts -O dtb +DTC_FLAGS += -Wno-unit_address_vs_reg + +define gen-dtb-file +# dts file path/name in $1 +# dtb file path/name in $2 + +dtb-basename-$2 := $$(basename $$(notdir $2)) +dtb-predts-$2 := $$(dir $2)$$(dtb-basename-$2).pre.dts +dtb-predep-$2 := $$(dir $2).$$(dtb-basename-$2).pre.dts.d +dtb-dep-$2 := $$(dir $2).$$(notdir $2).d +dtb-cmd-file-$2 := $$(dir $2).$$(notdir $2).cmd + +cleanfiles := $$(cleanfiles) $2 \ + $$(dtb-predts-$2) $$(dtb-predep-$2) \ + $$(dtb-dep-$2) $$(dtb-cmd-file-$2) + +dtb-cppflags-$2 := -Icore/include/ -x assembler-with-cpp -Ulinux -Uunix \ + -E -ffreestanding $$(CPPFLAGS) \ + -MD -MF $$(dtb-predep-$2) -MT $2 + +dtb-dtcflags-$2 := $$(DTC_FLAGS) -d $$(dtb-dep-$2) + +-include $$(dtb-dep-$2) +-include $$(dtb-predep-$2) +-include $$(dtb-cmd-file-$2) + +dtb-precmd-$2 = $$(CPP$(sm)) $$(dtb-cppflags-$2) -o $$(dtb-predts-$2) $$< +dtb-cmd-$2 = $$(DTC) $$(dtb-dtcflags-$2) -o $$@ $$(dtb-predts-$2) + +$2: $1 FORCE +# Check if any prerequisites are newer than the target and +# check if command line has changed + $$(if $$(strip $$(filter-out FORCE, $$?) \ + $$(filter-out $$(dtb-precmd-$2), $$(dtb-old-precmd-$2)) \ + $$(filter-out $$(dtb-old-precmd-$2), $$(dtb-precmd-$2)) \ + $$(filter-out $$(dtb-cmd-$2), $$(dtb-old-cmd-$2)) \ + $$(filter-out $$(dtb-old-cmd-$2), $$(dtb-cmd-$2))), \ + @set -e; \ + mkdir -p $$(dir $2); \ + $(cmd-echo-silent) ' CPP $$(dtb-predts-$2)'; \ + $$(dtb-precmd-$2); \ + $(cmd-echo-silent) ' DTC $$@'; \ + $$(dtb-cmd-$2); \ + echo "dtb-old-precmd-$2 := $$(subst \",\\\",$$(dtb-precmd-$2))" > \ + $$(dtb-cmd-file-$2) ;\ + echo "dtb-old-cmd-$2 := $$(subst \",\\\",$$(dtb-cmd-$2))" >> \ + $$(dtb-cmd-file-$2) ;\ + ) + +endef + +additional-compile-deps := diff --git a/optee/optee_os/mk/config.mk b/optee/optee_os/mk/config.mk new file mode 100644 index 0000000..dc878b8 --- /dev/null +++ b/optee/optee_os/mk/config.mk @@ -0,0 +1,1084 @@ +# Default configuration values for OP-TEE core (all platforms). +# +# Platform-specific overrides are in core/arch/arm32/plat-*/conf.mk. +# Some subsystem-specific defaults are not here but rather in */sub.mk. +# +# Configuration values may be assigned from multiple sources. +# From higher to lower priority: +# +# 1. Make arguments ('make CFG_FOO=bar...') +# 2. The file specified by $(CFG_OPTEE_CONFIG) (if defined) +# 3. The environment ('CFG_FOO=bar make...') +# 4. The platform-specific configuration file: core/arch/arm32/plat-*/conf.mk +# 5. This file +# 6. Subsystem-specific makefiles (*/sub.mk) +# +# Actual values used during the build are output to $(out-dir)/conf.mk +# (CFG_* variables only). + +# Cross-compiler prefix and suffix +CROSS_COMPILE ?= arm-linux-gnueabihf- +CROSS_COMPILE32 ?= $(CROSS_COMPILE) +CROSS_COMPILE64 ?= aarch64-linux-gnu- +COMPILER ?= gcc + +# For convenience +ifdef CFLAGS +CFLAGS32 ?= $(CFLAGS) +CFLAGS64 ?= $(CFLAGS) +endif + +# Compiler warning level. +# Supported values: undefined, 1, 2 and 3. 3 gives more warnings. +WARNS ?= 3 + +# Path to the Python interpreter used by the build system. +# This variable is set to the default python3 interpreter in the user's +# path. But build environments that require more explicit control can +# set the path to a specific interpreter through this variable. +PYTHON3 ?= python3 + +# Define DEBUG=1 to compile without optimization (forces -O0) +# DEBUG=1 +ifeq ($(DEBUG),1) +# For backwards compatibility +$(call force,CFG_CC_OPT_LEVEL,0) +$(call force,CFG_DEBUG_INFO,y) +endif + +# CFG_CC_OPT_LEVEL sets compiler optimization level passed with -O directive. +# Optimize for size by default, usually gives good performance too. +CFG_CC_OPT_LEVEL ?= s + +# Enabling CFG_DEBUG_INFO makes debug information embedded in core. +CFG_DEBUG_INFO ?= y + +# If y, enable debug features of the TEE core (assertions and lock checks +# are enabled, panic and assert messages are more verbose, data and prefetch +# aborts show a stack dump). When disabled, the NDEBUG directive is defined +# so assertions are disabled. +CFG_TEE_CORE_DEBUG ?= y + +# Log levels for the TEE core. Defines which core messages are displayed +# on the secure console. Disabling core log (level set to 0) also disables +# logs from the TAs. +# 0: none +# 1: error +# 2: error + info +# 3: error + info + debug +# 4: error + info + debug + flow +CFG_TEE_CORE_LOG_LEVEL ?= 2 + +# TA log level +# If user-mode library libutils.a is built with CFG_TEE_TA_LOG_LEVEL=0, +# TA tracing is disabled regardless of the value of CFG_TEE_TA_LOG_LEVEL +# when the TA is built. +CFG_TEE_TA_LOG_LEVEL ?= 1 + +# TA enablement +# When defined to "y", TA traces are output according to +# CFG_TEE_TA_LOG_LEVEL. Otherwise, they are not output at all +CFG_TEE_CORE_TA_TRACE ?= y + +# If y, enable the memory leak detection feature in the bget memory allocator. +# When this feature is enabled, calling mdbg_check(1) will print a list of all +# the currently allocated buffers and the location of the allocation (file and +# line number). +# Note: make sure the log level is high enough for the messages to show up on +# the secure console! For instance: +# - To debug user-mode (TA) allocations: build OP-TEE *and* the TA with: +# $ make CFG_TEE_TA_MALLOC_DEBUG=y CFG_TEE_TA_LOG_LEVEL=3 +# - To debug TEE core allocations: build OP-TEE with: +# $ make CFG_TEE_CORE_MALLOC_DEBUG=y CFG_TEE_CORE_LOG_LEVEL=3 +CFG_TEE_CORE_MALLOC_DEBUG ?= n +CFG_TEE_TA_MALLOC_DEBUG ?= n +# Prints an error message and dumps the stack on failed memory allocations +# using malloc() and friends. +CFG_CORE_DUMP_OOM ?= $(CFG_TEE_CORE_MALLOC_DEBUG) + +# Mask to select which messages are prefixed with long debugging information +# (severity, core ID, thread ID, component name, function name, line number) +# based on the message level. If BIT(level) is set, the long prefix is shown. +# Otherwise a short prefix is used (severity and component name only). +# Levels: 0=none 1=error 2=info 3=debug 4=flow +CFG_MSG_LONG_PREFIX_MASK ?= 0x1a + +# Number of threads +CFG_NUM_THREADS ?= 2 + +# API implementation version +CFG_TEE_API_VERSION ?= GPD-1.1-dev + +# Implementation description (implementation-dependent) +CFG_TEE_IMPL_DESCR ?= OPTEE + +# Should OPTEE_SMC_CALL_GET_OS_REVISION return a build identifier to Normal +# World? +CFG_OS_REV_REPORTS_GIT_SHA1 ?= y + +# The following values are not extracted from the "git describe" output because +# we might be outside of a Git environment, or the tree may have been cloned +# with limited depth not including any tag, so there is really no guarantee +# that TEE_IMPL_VERSION contains the major and minor revision numbers. +CFG_OPTEE_REVISION_MAJOR ?= 3 +CFG_OPTEE_REVISION_MINOR ?= 21 +CFG_OPTEE_REVISION_EXTRA ?= + +# Trusted OS implementation version +TEE_IMPL_VERSION ?= $(shell git describe --always --dirty=-dev 2>/dev/null || \ + echo Unknown_$(CFG_OPTEE_REVISION_MAJOR).$(CFG_OPTEE_REVISION_MINOR))$(CFG_OPTEE_REVISION_EXTRA) +ifeq ($(CFG_OS_REV_REPORTS_GIT_SHA1),y) +TEE_IMPL_GIT_SHA1 := 0x$(shell git rev-parse --short=8 HEAD 2>/dev/null || echo 0) +else +TEE_IMPL_GIT_SHA1 := 0x0 +endif + +# Trusted OS implementation manufacturer name +CFG_TEE_MANUFACTURER ?= LINARO + +# Trusted firmware version +CFG_TEE_FW_IMPL_VERSION ?= FW_IMPL_UNDEF + +# Trusted OS implementation manufacturer name +CFG_TEE_FW_MANUFACTURER ?= FW_MAN_UNDEF + +# Rich Execution Environment (REE) file system support: normal world OS +# provides the actual storage. +# This is the default FS when enabled (i.e., the one used when +# TEE_STORAGE_PRIVATE is passed to the trusted storage API) +CFG_REE_FS ?= y + +# NVMe RPMB file system support +CFG_NVME_RPMB_FS ?= n + +# Device identifier used when CFG_NVME_RPMB_FS = y. +# The exact meaning of this value is platform-dependent. On Linux, the +# tee-supplicant process will open /dev/nvme +CFG_NVME_RPMB_FS_DEV_ID ?= 0 + +# This config variable determines the number of entries read in from RPMB at +# once whenever a function traverses the NVMe RPMB FS. Increasing the default +# value has the following consequences: +# - More memory required on heap. A single FAT entry currently has a size of +# 256 bytes. +# - Potentially significant speed-ups for RPMB I/O. Depending on how many +# entries a function needs to traverse, the number of time-consuming RPMB +# read-in operations can be reduced. +# Chosing a proper value is both platform- (available memory) and use-case- +# dependent (potential number of FAT fs entries), so overwrite in platform +# config files +CFG_NVME_RPMB_FS_RD_ENTRIES ?= 8 + +# Enables caching of FAT FS entries when set to a value greater than zero. +# When enabled, the cache stores the first 'CFG_NVME_RPMB_FS_CACHE_ENTRIES' FAT +# FS entries. The cache is populated when FAT FS entries are initially read in. +# When traversing the FAT FS entries, we read from the cache instead of reading +# in the entries from RPMB storage. Consequently, when a FAT FS entry is +# written, the cache is updated. In scenarios where an estimate of the number +# of FAT FS entries can be made, the cache may be specifically tailored to +# store all entries. The caching can improve RPMB I/O at the cost +# of additional memory. +# Without caching, we temporarily require +# CFG_NVME_RPMB_FS_RD_ENTRIES*sizeof(struct nvme_rpmb_fat_entry) bytes of heap memory +# while traversing the FAT FS (e.g. in read_fat). +# For example 8*256 bytes = 2kB while in read_fat. +# With caching, we constantly require up to +# CFG_NVME_RPMB_FS_CACHE_ENTRIES*sizeof(struct nvme_rpmb_fat_entry) bytes of heap memory +# depending on how many elements are in the cache, and additional temporary +# CFG_NVME_RPMB_FS_RD_ENTRIES*sizeof(struct nvme_rpmb_fat_entry) bytes of heap memory +# in case the cache is too small to hold all elements when traversing. +CFG_NVME_RPMB_FS_CACHE_ENTRIES ?= 0 + +# Print NVMe RPMB data frames sent to and received from the RPMB device +CFG_NVME_RPMB_FS_DEBUG_DATA ?= n + +# Clear NVMe RPMB content at cold boot +CFG_NVME_RPMB_RESET_FAT ?= n + +# Use a hard coded NVMe RPMB key instead of deriving it from the platform HUK +CFG_NVME_RPMB_TESTKEY ?= n + +# RPMB file system support +CFG_RPMB_FS ?= n + +# Enable roll-back protection of REE file system using RPMB. +# Roll-back protection only works if CFG_RPMB_FS = y or CFG_NVME_RPMB_FS = y. +CFG_REE_FS_INTEGRITY_RPMB ?= $(call cfg-one-enabled, CFG_RPMB_FS CFG_NVME_RPMB_FS) +$(eval $(call cfg-depends-one,CFG_REE_FS_INTEGRITY_RPMB,CFG_RPMB_FS CFG_NVME_RPMB_FS)) + +# Device identifier used when CFG_RPMB_FS = y. +# The exact meaning of this value is platform-dependent. On Linux, the +# tee-supplicant process will open /dev/mmcblkrpmb +CFG_RPMB_FS_DEV_ID ?= 0 + +# This config variable determines the number of entries read in from RPMB at +# once whenever a function traverses the RPMB FS. Increasing the default value +# has the following consequences: +# - More memory required on heap. A single FAT entry currently has a size of +# 256 bytes. +# - Potentially significant speed-ups for RPMB I/O. Depending on how many +# entries a function needs to traverse, the number of time-consuming RPMB +# read-in operations can be reduced. +# Chosing a proper value is both platform- (available memory) and use-case- +# dependent (potential number of FAT fs entries), so overwrite in platform +# config files +CFG_RPMB_FS_RD_ENTRIES ?= 8 + +# Enables caching of FAT FS entries when set to a value greater than zero. +# When enabled, the cache stores the first 'CFG_RPMB_FS_CACHE_ENTRIES' FAT FS +# entries. The cache is populated when FAT FS entries are initially read in. +# When traversing the FAT FS entries, we read from the cache instead of reading +# in the entries from RPMB storage. Consequently, when a FAT FS entry is +# written, the cache is updated. In scenarios where an estimate of the number +# of FAT FS entries can be made, the cache may be specifically tailored to +# store all entries. The caching can improve RPMB I/O at the cost +# of additional memory. +# Without caching, we temporarily require +# CFG_RPMB_FS_RD_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory +# while traversing the FAT FS (e.g. in read_fat). +# For example 8*256 bytes = 2kB while in read_fat. +# With caching, we constantly require up to +# CFG_RPMB_FS_CACHE_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory +# depending on how many elements are in the cache, and additional temporary +# CFG_RPMB_FS_RD_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory +# in case the cache is too small to hold all elements when traversing. +CFG_RPMB_FS_CACHE_ENTRIES ?= 0 + +# Print RPMB data frames sent to and received from the RPMB device +CFG_RPMB_FS_DEBUG_DATA ?= n + +# Clear RPMB content at cold boot +CFG_RPMB_RESET_FAT ?= n + +# Use a hard coded RPMB key instead of deriving it from the platform HUK +CFG_RPMB_TESTKEY ?= n + +# Enables RPMB key programming by the TEE, in case the RPMB partition has not +# been configured yet. +# !!! Security warning !!! +# Do *NOT* enable this in product builds, as doing so would allow the TEE to +# leak the RPMB key. +# This option is useful in the following situations: +# - Testing +# - RPMB key provisioning in a controlled environment (factory setup) +CFG_RPMB_WRITE_KEY ?= n + +_CFG_WITH_SECURE_STORAGE := $(call cfg-one-enabled,CFG_REE_FS CFG_RPMB_FS CFG_NVME_RPMB_FS) + +# Signing key for OP-TEE TA's +# When performing external HSM signing for TA's TA_SIGN_KEY can be set to dummy +# key and then set TA_PUBLIC_KEY to match public key from the HSM. +# TA_PUBLIC_KEY's public key will be embedded into OP-TEE OS. +TA_SIGN_KEY ?= keys/default_ta.pem +TA_PUBLIC_KEY ?= $(TA_SIGN_KEY) + +# Subkeys is a complement to the normal TA_SIGN_KEY where a subkey is used +# to verify a TA instead. To sign a TA using a previously prepared subkey +# two new options are added, TA_SUBKEY_ARGS and TA_SUBKEY_DEPS. It is +# typically used by assigning the following in the TA Makefile: +# BINARY = +# TA_SIGN_KEY = subkey.pem +# TA_SUBKEY_ARGS = --subkey subkey.bin --name subkey_ta +# TA_SUBKEY_DEPS = subkey.bin +# See the documentation for more details on subkeys. + +# Include lib/libutils/isoc in the build? Most platforms need this, but some +# may not because they obtain the isoc functions from elsewhere +CFG_LIBUTILS_WITH_ISOC ?= y + +# Enables floating point support for user TAs +# ARM32: EABI defines both a soft-float ABI and a hard-float ABI, +# hard-float is basically a super set of soft-float. Hard-float +# requires all the support routines provided for soft-float, but the +# compiler may choose to optimize to not use some of them and use +# the floating-point registers instead. +# ARM64: EABI doesn't define a soft-float ABI, everything is hard-float (or +# nothing with ` -mgeneral-regs-only`) +# With CFG_TA_FLOAT_SUPPORT enabled TA code is free use floating point types +CFG_TA_FLOAT_SUPPORT ?= y + +# Stack unwinding: print a stack dump to the console on core or TA abort, or +# when a TA panics. +# If CFG_UNWIND is enabled, both the kernel and user mode call stacks can be +# unwound (not paged TAs, however). +# Note that 32-bit ARM code needs unwind tables for this to work, so enabling +# this option will increase the size of the 32-bit TEE binary by a few KB. +# Similarly, TAs have to be compiled with -funwind-tables (default when the +# option is set) otherwise they can't be unwound. +# Warning: since the unwind sequence for user-mode (TA) code is implemented in +# the privileged layer of OP-TEE, enabling this feature will weaken the +# user/kernel isolation. Therefore it should be disabled in release builds. +ifeq ($(CFG_TEE_CORE_DEBUG),y) +CFG_UNWIND ?= y +endif + +# Enable support for dynamically loaded user TAs +CFG_WITH_USER_TA ?= y + +# Build user TAs included in this source tree +CFG_BUILD_IN_TREE_TA ?= y + +# Choosing the architecture(s) of user-mode libraries (used by TAs) +# +# Platforms may define a list of supported architectures for user-mode code +# by setting $(supported-ta-targets). Valid values are "ta_arm32", "ta_arm64", +# "ta_arm32 ta_arm64" and "ta_arm64 ta_arm32". +# $(supported-ta-targets) defaults to "ta_arm32" when the TEE core is 32-bits, +# and "ta_arm32 ta_arm64" when it is 64-bits (that is, when CFG_ARM64_core=y). +# The first entry in $(supported-ta-targets) has a special role, see +# CFG_USER_TA_TARGET_ below. +# +# CFG_USER_TA_TARGETS may be defined to restrict $(supported-ta-targets) or +# change the order of the values. +# +# The list of TA architectures is ultimately stored in $(ta-targets). + +# CFG_USER_TA_TARGET_ (for example, CFG_USER_TA_TARGET_avb), if +# defined, selects the unique TA architecture mode for building the in-tree TA +# . Can be either ta_arm32 or ta_arm64. +# By default, in-tree TAs are built using the first architecture specified in +# $(ta-targets). + +# Address Space Layout Randomization for user-mode Trusted Applications +# +# When this flag is enabled, the ELF loader will introduce a random offset +# when mapping the application in user space. ASLR makes the exploitation of +# memory corruption vulnerabilities more difficult. +CFG_TA_ASLR ?= y + +# How much ASLR may shift the base address (in pages). The base address is +# randomly shifted by an integer number of pages comprised between these two +# values. Bigger ranges are more secure because they make the addresses harder +# to guess at the expense of using more memory for the page tables. +CFG_TA_ASLR_MIN_OFFSET_PAGES ?= 0 +CFG_TA_ASLR_MAX_OFFSET_PAGES ?= 128 + +# Address Space Layout Randomization for TEE Core +# +# When this flag is enabled, the early init code will introduce a random +# offset when mapping TEE Core. ASLR makes the exploitation of memory +# corruption vulnerabilities more difficult. +CFG_CORE_ASLR ?= y + +# Stack Protection for TEE Core +# This flag enables the compiler stack protection mechanisms -fstack-protector. +# It will check the stack canary value before returning from a function to +# prevent buffer overflow attacks. Stack protector canary logic will be added +# for vulnerable functions that contain: +# - A character array larger than 8 bytes. +# - An 8-bit integer array larger than 8 bytes. +# - A call to alloca() with either a variable size or a constant size bigger +# than 8 bytes. +CFG_CORE_STACK_PROTECTOR ?= n +# This enable stack protector flag -fstack-protector-strong. Stack protector +# canary logic will be added for vulnerable functions that contain: +# - An array of any size and type. +# - A call to alloca(). +# - A local variable that has its address taken. +CFG_CORE_STACK_PROTECTOR_STRONG ?= y +# This enable stack protector flag -fstack-protector-all. Stack protector canary +# logic will be added to all functions regardless of their vulnerability. +CFG_CORE_STACK_PROTECTOR_ALL ?= n +# Stack Protection for TA +CFG_TA_STACK_PROTECTOR ?= n +CFG_TA_STACK_PROTECTOR_STRONG ?= y +CFG_TA_STACK_PROTECTOR_ALL ?= n + +_CFG_CORE_STACK_PROTECTOR := $(call cfg-one-enabled, CFG_CORE_STACK_PROTECTOR \ + CFG_CORE_STACK_PROTECTOR_STRONG \ + CFG_CORE_STACK_PROTECTOR_ALL) +_CFG_TA_STACK_PROTECTOR := $(call cfg-one-enabled, CFG_TA_STACK_PROTECTOR \ + CFG_TA_STACK_PROTECTOR_STRONG \ + CFG_TA_STACK_PROTECTOR_ALL) + +# Load user TAs from the REE filesystem via tee-supplicant +CFG_REE_FS_TA ?= y + +# Pre-authentication of TA binaries loaded from the REE filesystem +# +# - If CFG_REE_FS_TA_BUFFERED=y: load TA binary into a temporary buffer in the +# "Secure DDR" pool, check the signature, then process the file only if it is +# valid. +# - If disabled: hash the binaries as they are being processed and verify the +# signature as a last step. +CFG_REE_FS_TA_BUFFERED ?= n +$(eval $(call cfg-depends-all,CFG_REE_FS_TA_BUFFERED,CFG_REE_FS_TA)) + +# When CFG_REE_FS=y and CFG_RPMB_FS=y: +# Allow secure storage in the REE FS to be entirely deleted without causing +# anti-rollback errors. That is, rm /data/tee/dirf.db or rm -rf /data/tee (or +# whatever path is configured in tee-supplicant as CFG_TEE_FS_PARENT_PATH) +# can be used to reset the secure storage to a clean, empty state. +# Typically used for testing only since it weakens storage security. +CFG_REE_FS_ALLOW_RESET ?= n + +# Support for loading user TAs from a special section in the TEE binary. +# Such TAs are available even before tee-supplicant is available (hence their +# name), but note that many services exported to TAs may need tee-supplicant, +# so early use is limited to a subset of the TEE Internal Core API (crypto...) +# To use this feature, set EARLY_TA_PATHS to the paths to one or more TA ELF +# file(s). For example: +# $ make ... \ +# EARLY_TA_PATHS="path/to/8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf \ +# path/to/cb3e5ba0-adf1-11e0-998b-0002a5d5c51b.stripped.elf" +# Typical build steps: +# $ make ta_dev_kit CFG_EARLY_TA=y # Create the dev kit (user mode libraries, +# # headers, makefiles), ready to build TAs. +# # CFG_EARLY_TA=y is optional, it prevents +# # later library recompilations. +# +# $ make EARLY_TA_PATHS= # Build OP-TEE and embbed the TA(s) +# +# Another option is CFG_IN_TREE_EARLY_TAS which is used to point at +# in-tree TAs. CFG_IN_TREE_EARLY_TAS is formatted as: +# / +# for instance avb/023f8f1a-292a-432b-8fc4-de8471358067 +ifneq ($(EARLY_TA_PATHS)$(CFG_IN_TREE_EARLY_TAS),) +$(call force,CFG_EARLY_TA,y) +else +CFG_EARLY_TA ?= n +endif + +ifeq ($(CFG_EARLY_TA),y) +$(call force,CFG_EMBEDDED_TS,y) +endif + +ifneq ($(SP_PATHS),) +$(call force,CFG_EMBEDDED_TS,y) +else +CFG_SECURE_PARTITION ?= n +endif + +ifeq ($(CFG_SECURE_PARTITION),y) +$(call force,CFG_EMBEDDED_TS,y) +endif + +ifeq ($(CFG_EMBEDDED_TS),y) +$(call force,CFG_ZLIB,y) +endif + +# By default the early TAs are compressed in the TEE binary, it is possible to +# not compress them with CFG_EARLY_TA_COMPRESS=n +CFG_EARLY_TA_COMPRESS ?= y + +# Enable paging, requires SRAM, can't be enabled by default +CFG_WITH_PAGER ?= n + +# Use the pager for user TAs +CFG_PAGED_USER_TA ?= $(CFG_WITH_PAGER) + +# If paging of user TAs, that is, R/W paging default to enable paging of +# TAG and IV in order to reduce heap usage. +CFG_CORE_PAGE_TAG_AND_IV ?= $(CFG_PAGED_USER_TA) + +# Runtime lock dependency checker: ensures that a proper locking hierarchy is +# used in the TEE core when acquiring and releasing mutexes. Any violation will +# cause a panic as soon as the invalid locking condition is detected. If +# CFG_UNWIND and CFG_LOCKDEP_RECORD_STACK are both enabled, the algorithm +# records the call stacks when locks are taken, and prints them when a +# potential deadlock is found. +# Expect a significant performance impact when enabling this. +CFG_LOCKDEP ?= n +CFG_LOCKDEP_RECORD_STACK ?= y + +# BestFit algorithm in bget reduces the fragmentation of the heap when running +# with the pager enabled or lockdep +CFG_CORE_BGET_BESTFIT ?= $(call cfg-one-enabled, CFG_WITH_PAGER CFG_LOCKDEP) + +# Enable support for detected undefined behavior in C +# Uses a lot of memory, can't be enabled by default +CFG_CORE_SANITIZE_UNDEFINED ?= n + +# Enable Kernel Address sanitizer, has a huge performance impact, uses a +# lot of memory and need platform specific adaptations, can't be enabled by +# default +CFG_CORE_SANITIZE_KADDRESS ?= n + +# Add stack guards before/after stacks and periodically check them +CFG_WITH_STACK_CANARIES ?= y + +# Use compiler instrumentation to troubleshoot stack overflows. +# When enabled, most C functions check the stack pointer against the current +# stack limits on entry and panic immediately if it is out of range. +CFG_CORE_DEBUG_CHECK_STACKS ?= n + +# Use when the default stack allocations are not sufficient. +CFG_STACK_THREAD_EXTRA ?= 0 +CFG_STACK_TMP_EXTRA ?= 0 + +# Device Tree support +# +# When CFG_DT is enabled core embeds the FDT library (libfdt) allowing +# device tree blob (DTB) parsing from the core. +# +# When CFG_DT is enabled, the TEE _start function expects to find +# the address of a DTB in register X2/R2 provided by the early boot stage +# or value 0 if boot stage provides no DTB. +# +# When CFG_EXTERNAL_DT is enabled, the external device tree ABI is implemented +# and the external device tree is expected to be used/modified. Its value +# defaults to CFG_DT. +# +# When CFG_MAP_EXT_DT_SECURE is enabled the external device tree is expected to +# be in the secure memory. +# +# When CFG_EMBED_DTB is enabled, CFG_EMBED_DTB_SOURCE_FILE shall define the +# relative path of a DTS file located in core/arch/$(ARCH)/dts. +# The DTS file is compiled into a DTB file which content is embedded in a +# read-only section of the core. +ifneq ($(strip $(CFG_EMBED_DTB_SOURCE_FILE)),) +CFG_EMBED_DTB ?= y +endif +ifeq ($(CFG_EMBED_DTB),y) +$(call force,CFG_DT,y) +endif +CFG_EMBED_DTB ?= n +CFG_DT ?= n +CFG_EXTERNAL_DT ?= $(CFG_DT) +CFG_MAP_EXT_DT_SECURE ?= n +ifeq ($(CFG_MAP_EXT_DT_SECURE),y) +$(call force,CFG_DT,y) +endif + +# Maximum size of the Device Tree Blob, has to be large enough to allow +# editing of the supplied DTB. +CFG_DTB_MAX_SIZE ?= 0x10000 + +# Maximum size of the init info data passed to Secure Partitions. +CFG_SP_INIT_INFO_MAX_SIZE ?= 0x1000 + +# Device Tree Overlay support. +# CFG_EXTERNAL_DTB_OVERLAY allows to append a DTB overlay into an existing +# external DTB. The overlay is created when no valid DTB overlay is found. +# CFG_GENERATE_DTB_OVERLAY allows to create a DTB overlay at external +# DTB location. +# External DTB location (physical address) is provided either by boot +# argument arg2 or from CFG_DT_ADDR if defined. +# A subsequent boot stage can then merge the generated overlay DTB into a main +# DTB using the standard fdt_overlay_apply() method. +CFG_EXTERNAL_DTB_OVERLAY ?= n +CFG_GENERATE_DTB_OVERLAY ?= n + +ifeq (y-y,$(CFG_EXTERNAL_DTB_OVERLAY)-$(CFG_GENERATE_DTB_OVERLAY)) +$(error CFG_EXTERNAL_DTB_OVERLAY and CFG_GENERATE_DTB_OVERLAY are exclusive) +endif +_CFG_USE_DTB_OVERLAY := $(call cfg-one-enabled,CFG_EXTERNAL_DTB_OVERLAY \ + CFG_GENERATE_DTB_OVERLAY) + +# All embedded tests are supposed to be disabled by default, this flag +# is used to control the default value of all other embedded tests +CFG_ENABLE_EMBEDDED_TESTS ?= n + +# Enable core self tests and related pseudo TAs +CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= $(CFG_ENABLE_EMBEDDED_TESTS) + +# Compiles bget_main_test() to be called from a test TA +CFG_TA_BGET_TEST ?= $(CFG_ENABLE_EMBEDDED_TESTS) + +# CFG_DT_DRIVER_EMBEDDED_TEST when enabled embedb DT driver probing tests. +# This also requires embeddeding a DTB with expected content. +# Defautl disable CFG_DRIVERS_CLK_EARLY_PROBE to probe clocks as other drivers. +# A probe deferral test mandates CFG_DRIVERS_DT_RECURSIVE_PROBE=n. +CFG_DT_DRIVER_EMBEDDED_TEST ?= n +ifeq ($(CFG_DT_DRIVER_EMBEDDED_TEST),y) +CFG_DRIVERS_CLK ?= y +CFG_DRIVERS_RSTCTRL ?= y +CFG_DRIVERS_CLK_EARLY_PROBE ?= n +$(call force,CFG_DRIVERS_DT_RECURSIVE_PROBE,n,Mandated by CFG_DT_DRIVER_EMBEDDED_TEST) +endif + +# CFG_DRIVERS_DT_RECURSIVE_PROBE when enabled forces a recursive subnode +# parsing in the embedded DTB for driver probing. The alternative is +# an exploration based on compatible drivers found. It is default disabled. +CFG_DRIVERS_DT_RECURSIVE_PROBE ?= n + +# This option enables OP-TEE to respond to SMP boot request: the Rich OS +# issues this to request OP-TEE to release secondaries cores out of reset, +# with specific core number and non-secure entry address. +CFG_BOOT_SECONDARY_REQUEST ?= n + +# Default heap size for Core, 64 kB +CFG_CORE_HEAP_SIZE ?= 65536 + +# Default size of nexus heap. 16 kB. Used only if CFG_NS_VIRTUALIZATION +# is enabled +CFG_CORE_NEX_HEAP_SIZE ?= 16384 + +# TA profiling. +# When this option is enabled, OP-TEE can execute Trusted Applications +# instrumented with GCC's -pg flag and will output profiling information +# in gmon.out format to /tmp/gmon-.out (path is defined in +# tee-supplicant) +# Note: this does not work well with shared libraries at the moment for a +# couple of reasons: +# 1. The profiling code assumes a unique executable section in the TA VA space. +# 2. The code used to detect at run time if the TA is intrumented assumes that +# the TA is linked statically. +CFG_TA_GPROF_SUPPORT ?= n + +# TA function tracing. +# When this option is enabled, OP-TEE can execute Trusted Applications +# instrumented with GCC's -pg flag and will output function tracing +# information in ftrace.out format to /tmp/ftrace-.out (path is +# defined in tee-supplicant) +CFG_FTRACE_SUPPORT ?= n + +# How to make room when the function tracing buffer is full? +# 'shift': shift the previously stored data by the amount needed in order +# to always keep the latest logs (slower, especially with big buffer sizes) +# 'wrap': discard the previous data and start at the beginning of the buffer +# again (fast, but can result in a mostly empty buffer) +# 'stop': stop logging new data +CFG_FTRACE_BUF_WHEN_FULL ?= shift +$(call cfg-check-value,FTRACE_BUF_WHEN_FULL,shift stop wrap) +$(call force,_CFG_FTRACE_BUF_WHEN_FULL_$(CFG_FTRACE_BUF_WHEN_FULL),y) + +# Function tracing: unit to be used when displaying durations +# 0: always display durations in microseconds +# >0: if duration is greater or equal to the specified value (in microseconds), +# display it in milliseconds +CFG_FTRACE_US_MS ?= 10000 + +# Core syscall function tracing. +# When this option is enabled, OP-TEE core is instrumented with GCC's +# -pg flag and will output syscall function graph in user TA ftrace +# buffer +CFG_SYSCALL_FTRACE ?= n +$(call cfg-depends-all,CFG_SYSCALL_FTRACE,CFG_FTRACE_SUPPORT) + +# Enable to compile user TA libraries with profiling (-pg). +# Depends on CFG_TA_GPROF_SUPPORT or CFG_FTRACE_SUPPORT. +CFG_ULIBS_MCOUNT ?= n +# Profiling/tracing of syscall wrapper (utee_*) +CFG_SYSCALL_WRAPPERS_MCOUNT ?= $(CFG_ULIBS_MCOUNT) + +ifeq (y,$(filter y,$(CFG_ULIBS_MCOUNT) $(CFG_SYSCALL_WRAPPERS_MCOUNT))) +ifeq (,$(filter y,$(CFG_TA_GPROF_SUPPORT) $(CFG_FTRACE_SUPPORT))) +$(error Cannot instrument user libraries if user mode profiling is disabled) +endif +endif + +# Build libutee, libutils, libmbedtls as shared libraries. +# - Static libraries are still generated when this is enabled, but TAs will use +# the shared libraries unless explicitly linked with the -static flag. +# - Shared libraries are made of two files: for example, libutee is +# libutee.so and 527f1a47-b92c-4a74-95bd-72f19f4a6f74.ta. The '.so' file +# is a totally standard shared object, and should be used to link against. +# The '.ta' file is a signed version of the '.so' and should be installed +# in the same way as TAs so that they can be found at runtime. +CFG_ULIBS_SHARED ?= n + +ifeq (y-y,$(CFG_TA_GPROF_SUPPORT)-$(CFG_ULIBS_SHARED)) +$(error CFG_TA_GPROF_SUPPORT and CFG_ULIBS_SHARED are currently incompatible) +endif + +# CFG_GP_SOCKETS +# Enable Global Platform Sockets support +CFG_GP_SOCKETS ?= y + +# Enable Secure Data Path support in OP-TEE core (TA may be invoked with +# invocation parameters referring to specific secure memories). +CFG_SECURE_DATA_PATH ?= n + +# Enable storage for TAs in secure storage, depends on CFG_REE_FS=y +# TA binaries are stored encrypted in the REE FS and are protected by +# metadata in secure storage. +CFG_SECSTOR_TA ?= $(call cfg-all-enabled,CFG_REE_FS CFG_WITH_USER_TA) +$(eval $(call cfg-depends-all,CFG_SECSTOR_TA,CFG_REE_FS CFG_WITH_USER_TA)) + +# Enable the pseudo TA that managages TA storage in secure storage +CFG_SECSTOR_TA_MGMT_PTA ?= $(call cfg-all-enabled,CFG_SECSTOR_TA) +$(eval $(call cfg-depends-all,CFG_SECSTOR_TA_MGMT_PTA,CFG_SECSTOR_TA)) + +# Enable the pseudo TA for misc. auxilary services, extending existing +# GlobalPlatform TEE Internal Core API (for example, re-seeding RNG entropy +# pool etc...) +CFG_SYSTEM_PTA ?= $(CFG_WITH_USER_TA) +$(eval $(call cfg-depends-all,CFG_SYSTEM_PTA,CFG_WITH_USER_TA)) + +# Enable the pseudo TA for enumeration of TEE based devices for the normal +# world OS. +CFG_DEVICE_ENUM_PTA ?= y + +# The attestation pseudo TA provides an interface to request measurements of +# a TA or the TEE binary. +CFG_ATTESTATION_PTA ?= n +$(eval $(call cfg-depends-all,CFG_ATTESTATION_PTA,_CFG_WITH_SECURE_STORAGE)) + +# RSA key size (in bits) for the attestation PTA. Must be at least 528 given +# other algorithm parameters (RSA PSS with SHA-256 and 32-byte salt), but +# note that such a low value is not secure. +# See https://tools.ietf.org/html/rfc8017#section-8.1.1 and +# https://tools.ietf.org/html/rfc8017#section-9.1.1 +# emLen >= hlen + sLen + 2 = 32 + 32 + 2 = 66 +# emLen = ceil((modBits - 1) / 8) => emLen is the key size in bytes +CFG_ATTESTATION_PTA_KEY_SIZE ?= 3072 + +# Define the number of cores per cluster used in calculating core position. +# The cluster number is shifted by this value and added to the core ID, +# so its value represents log2(cores/cluster). +# Default is 2**(2) = 4 cores per cluster. +CFG_CORE_CLUSTER_SHIFT ?= 2 + +# Define the number of threads per core used in calculating processing +# element's position. The core number is shifted by this value and added to +# the thread ID, so its value represents log2(threads/core). +# Default is 2**(0) = 1 threads per core. +CFG_CORE_THREAD_SHIFT ?= 0 + +# Enable support for dynamic shared memory (shared memory anywhere in +# non-secure memory). +CFG_CORE_DYN_SHM ?= y + +# Enable support for reserved shared memory (shared memory in a carved out +# memory area). +CFG_CORE_RESERVED_SHM ?= y + +# Enables support for larger physical addresses, that is, it will define +# paddr_t as a 64-bit type. +CFG_CORE_LARGE_PHYS_ADDR ?= n + +# Define the maximum size, in bits, for big numbers in the Internal Core API +# Arithmetical functions. This does *not* influence the key size that may be +# manipulated through the Cryptographic API. +# Set this to a lower value to reduce the TA memory footprint. +CFG_TA_BIGNUM_MAX_BITS ?= 2048 + +# Define the maximum size, in bits, for big numbers in the TEE core (privileged +# layer). +# This value is an upper limit for the key size in any cryptographic algorithm +# implemented by the TEE core. +# Set this to a lower value to reduce the memory footprint. +CFG_CORE_BIGNUM_MAX_BITS ?= 4096 + +# Not used since libmpa was removed. Force the values to catch build scripts +# that would set = n. +$(call force,CFG_TA_MBEDTLS_MPI,y) +$(call force,CFG_TA_MBEDTLS,y) + +# Compile the TA library mbedTLS with self test functions, the functions +# need to be called to test anything +CFG_TA_MBEDTLS_SELF_TEST ?= y + +# By default use tomcrypt as the main crypto lib providing an implementation +# for the API in +# CFG_CRYPTOLIB_NAME is used as libname and +# CFG_CRYPTOLIB_DIR is used as libdir when compiling the library +# +# It's also possible to configure to use mbedtls instead of tomcrypt. +# Then the variables should be assigned as "CFG_CRYPTOLIB_NAME=mbedtls" and +# "CFG_CRYPTOLIB_DIR=lib/libmbedtls" respectively. +CFG_CRYPTOLIB_NAME ?= tomcrypt +CFG_CRYPTOLIB_DIR ?= core/lib/libtomcrypt + +# Not used since libmpa was removed. Force the value to catch build scripts +# that would set = n. +$(call force,CFG_CORE_MBEDTLS_MPI,y) + +# Enable virtualization support. OP-TEE will not work without compatible +# hypervisor if this option is enabled. +CFG_NS_VIRTUALIZATION ?= $(CFG_VIRTUALIZATION) +CFG_NS_VIRTUALIZATION ?= n + +ifeq ($(CFG_NS_VIRTUALIZATION),y) +$(call force,CFG_CORE_RODATA_NOEXEC,y) +$(call force,CFG_CORE_RWDATA_NOEXEC,y) + +# Default number of virtual guests +CFG_VIRT_GUEST_COUNT ?= 2 +endif + +# Enables backwards compatible derivation of RPMB and SSK keys +CFG_CORE_HUK_SUBKEY_COMPAT ?= y + +# Use SoC specific tee_otp_get_die_id() implementation for SSK key generation. +# This option depends on CFG_CORE_HUK_SUBKEY_COMPAT=y. +CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID ?= n + +# Compress and encode conf.mk into the TEE core, and show the encoded string on +# boot (with severity TRACE_INFO). +CFG_SHOW_CONF_ON_BOOT ?= n + +# Enables support for passing a TPM Event Log stored in secure memory +# to a TA or FF-A SP, so a TPM Service could use it to extend any measurement +# taken before the service was up and running. +CFG_CORE_TPM_EVENT_LOG ?= n + +# When enabled, CFG_SCMI_MSG_DRIVERS embeds SCMI message drivers in the core. +# Refer to the supported SCMI features embedded upon CFG_SCMI_MSG_* +# +# CFG_SCMI_MSG_CLOCK embeds SCMI clock protocol support. +# CFG_SCMI_MSG_RESET_DOMAIN embeds SCMI reset domain protocol support. +# CFG_SCMI_MSG_SMT embeds a SMT header in shared device memory buffers +# CFG_SCMI_MSG_VOLTAGE_DOMAIN embeds SCMI voltage domain protocol support. +# CFG_SCMI_MSG_SMT_FASTCALL_ENTRY embeds fastcall SMC entry with SMT memory +# CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY embeds interrupt entry with SMT memory +# CFG_SCMI_MSG_SMT_THREAD_ENTRY embeds threaded entry with SMT memory +# CFG_SCMI_MSG_SHM_MSG embeds a MSG header in cached shared memory buffer +CFG_SCMI_MSG_DRIVERS ?= n +ifeq ($(CFG_SCMI_MSG_DRIVERS),y) +CFG_SCMI_MSG_CLOCK ?= n +CFG_SCMI_MSG_RESET_DOMAIN ?= n +CFG_SCMI_MSG_SHM_MSG ?= n +CFG_SCMI_MSG_SMT ?= n +CFG_SCMI_MSG_SMT_FASTCALL_ENTRY ?= n +CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY ?= n +CFG_SCMI_MSG_SMT_THREAD_ENTRY ?= n +CFG_SCMI_MSG_THREAD_ENTRY ?= n +CFG_SCMI_MSG_VOLTAGE_DOMAIN ?= n +$(eval $(call cfg-depends-all,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,CFG_SCMI_MSG_SMT)) +$(eval $(call cfg-depends-all,CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY,CFG_SCMI_MSG_SMT)) +$(eval $(call cfg-depends-one,CFG_SCMI_MSG_SMT_THREAD_ENTRY,CFG_SCMI_MSG_SMT CFG_SCMI_MSG_SHM_MSG)) +ifeq ($(CFG_SCMI_MSG_SMT),y) +_CFG_SCMI_PTA_SMT_HEADER := y +endif +ifeq ($(CFG_SCMI_MSG_SHM_MSG),y) +_CFG_SCMI_PTA_MSG_HEADER := y +endif +endif + +# CFG_SCMI_SCPFW, when enabled, embeds the reference SCMI server implementation +# from SCP-firmware package as an built-in SCMI stack in core. This +# configuration mandates target product identifier is configured with +# CFG_SCMI_SCPFW_PRODUCT and the SCP-firmware source tree path with +# CFG_SCP_FIRMWARE. +CFG_SCMI_SCPFW ?= n + +ifeq ($(CFG_SCMI_SCPFW),y) +$(call force,CFG_SCMI_PTA,y,Required by CFG_SCMI_SCPFW) +ifeq (,$(CFG_SCMI_SCPFW_PRODUCT)) +$(error CFG_SCMI_SCPFW=y requires CFG_SCMI_SCPFW_PRODUCT configuration) +endif +ifeq (,$(wildcard $(CFG_SCP_FIRMWARE)/CMakeLists.txt)) +$(error CFG_SCMI_SCPFW=y requires CFG_SCP_FIRMWARE configuration) +endif +endif #CFG_SCMI_SCPFW + +ifeq ($(CFG_SCMI_MSG_DRIVERS)-$(CFG_SCMI_SCPFW),y-y) +$(error CFG_SCMI_MSG_DRIVERS=y and CFG_SCMI_SCPFW=y are mutually exclusive) +endif + +# Enable SCMI PTA interface for REE SCMI agents +CFG_SCMI_PTA ?= n +ifeq ($(CFG_SCMI_PTA),y) +_CFG_SCMI_PTA_SMT_HEADER ?= n +_CFG_SCMI_PTA_MSG_HEADER ?= n +endif + +ifneq ($(CFG_STMM_PATH),) +$(call force,CFG_WITH_STMM_SP,y) +else +CFG_WITH_STMM_SP ?= n +endif +ifeq ($(CFG_WITH_STMM_SP),y) +$(call force,CFG_ZLIB,y) +endif + +# When enabled checks that buffers passed to the GP Internal Core API +# comply with the rules added as annotations as part of the definition of +# the API. For example preventing buffers in non-secure shared memory when +# not allowed. +CFG_TA_STRICT_ANNOTATION_CHECKS ?= y + +# When enabled accepts the DES key sizes excluding parity bits as in +# the GP Internal API Specification v1.0 +CFG_COMPAT_GP10_DES ?= y + +# Defines a limit for many levels TAs may call each others. +CFG_CORE_MAX_SYSCALL_RECURSION ?= 4 + +# Pseudo-TA to export hardware RNG output to Normal World +# RNG characteristics are platform specific +CFG_HWRNG_PTA ?= n +ifeq ($(CFG_HWRNG_PTA),y) +# Output rate of hw_get_random_bytes() in bytes per second, 0: not rate-limited +CFG_HWRNG_RATE ?= 0 +# Quality/entropy of hw_get_random_bytes() per 1024 bits of output data, in bits +ifeq (,$(CFG_HWRNG_QUALITY)) +$(error CFG_HWRNG_QUALITY not defined) +endif +endif + +# CFG_PREALLOC_RPC_CACHE, when enabled, makes core to preallocate +# shared memory for each secure thread. When disabled, RPC shared +# memory is released once the secure thread has completed is execution. +ifeq ($(CFG_WITH_PAGER),y) +CFG_PREALLOC_RPC_CACHE ?= n +endif +CFG_PREALLOC_RPC_CACHE ?= y + +# When enabled, CFG_DRIVERS_CLK embeds a clock framework in OP-TEE core. +# This clock framework allows to describe clock tree and provides functions to +# get and configure the clocks. +# CFG_DRIVERS_CLK_DT embeds devicetree clock parsing support +# CFG_DRIVERS_CLK_FIXED add support for "fixed-clock" compatible clocks +# CFG_DRIVERS_CLK_EARLY_PROBE makes clocks probed at early_init initcall level. +CFG_DRIVERS_CLK ?= n +CFG_DRIVERS_CLK_DT ?= $(call cfg-all-enabled,CFG_DRIVERS_CLK CFG_DT) +CFG_DRIVERS_CLK_FIXED ?= $(CFG_DRIVERS_CLK_DT) +CFG_DRIVERS_CLK_EARLY_PROBE ?= $(CFG_DRIVERS_CLK_DT) + +$(eval $(call cfg-depends-all,CFG_DRIVERS_CLK_DT,CFG_DRIVERS_CLK CFG_DT)) +$(eval $(call cfg-depends-all,CFG_DRIVERS_CLK_FIXED,CFG_DRIVERS_CLK_DT)) + +# When enabled, CFG_DRIVERS_RSTCTRL embeds a reset controller framework in +# OP-TEE core to provide reset controls on subsystems of the devices. +CFG_DRIVERS_RSTCTRL ?= n + +# When enabled, CFG_DRIVERS_I2C provides I2C controller and devices support. +CFG_DRIVERS_I2C ?= n + +# The purpose of this flag is to show a print when booting up the device that +# indicates whether the board runs a standard developer configuration or not. +# A developer configuration doesn't necessarily has to be secure. The intention +# is that the one making products based on OP-TEE should override this flag in +# plat-xxx/conf.mk for the platform they're basing their products on after +# they've finalized implementing stubbed functionality (see OP-TEE +# documentation/Porting guidelines) as well as vendor specific security +# configuration. +CFG_WARN_INSECURE ?= y + +# Enables warnings for declarations mixed with statements +CFG_WARN_DECL_AFTER_STATEMENT ?= y + +# Branch Target Identification (part of the ARMv8.5 Extensions) provides a +# mechanism to limit the set of locations to which computed branch instructions +# such as BR or BLR can jump. To make use of BTI in TEE core and ldelf on CPU's +# that support it, enable this option. A GCC toolchain built with +# --enable-standard-branch-protection is needed to use this option. +CFG_CORE_BTI ?= n + +$(eval $(call cfg-depends-all,CFG_CORE_BTI,CFG_ARM64_core)) + +# To make use of BTI in user space libraries and TA's on CPU's that support it, +# enable this option. +CFG_TA_BTI ?= $(CFG_CORE_BTI) + +$(eval $(call cfg-depends-all,CFG_TA_BTI,CFG_ARM64_core)) + +ifeq (y-y,$(CFG_NS_VIRTUALIZATION)-$(call cfg-one-enabled, CFG_TA_BTI CFG_CORE_BTI)) +$(error CFG_NS_VIRTUALIZATION and BTI are currently incompatible) +endif + +ifeq (y-y,$(CFG_PAGED_USER_TA)-$(CFG_TA_BTI)) +$(error CFG_PAGED_USER_TA and CFG_TA_BTI are currently incompatible) +endif + +# Memory Tagging Extension (part of the ARMv8.5 Extensions) implements lock +# and key access to memory. This is a hardware supported alternative to +# CFG_CORE_SANITIZE_KADDRESS which covers both S-EL1 and S-EL0. +CFG_MEMTAG ?= n + +$(eval $(call cfg-depends-all,CFG_MEMTAG,CFG_ARM64_core)) +ifeq (y-y,$(CFG_CORE_SANITIZE_KADDRESS)-$(CFG_MEMTAG)) +$(error CFG_CORE_SANITIZE_KADDRESS and CFG_MEMTAG are not compatible) +endif +ifeq (y-y,$(CFG_WITH_PAGER)-$(CFG_MEMTAG)) +$(error CFG_WITH_PAGER and CFG_MEMTAG are not compatible) +endif + +# CFG_CORE_ASYNC_NOTIF is defined by the platform to enable support +# for sending asynchronous notifications to normal world. Note that an +# interrupt ID must be configurged by the platform too. Currently is only +# CFG_CORE_ASYNC_NOTIF_GIC_INTID defined. +CFG_CORE_ASYNC_NOTIF ?= n + +$(eval $(call cfg-enable-all-depends,CFG_MEMPOOL_REPORT_LAST_OFFSET, \ + CFG_WITH_STATS)) + +# Pointer Authentication (part of ARMv8.3 Extensions) provides instructions +# for signing and authenticating pointers against secret keys. These can +# be used to mitigate ROP (Return oriented programming) attacks. This is +# currently done by instructing the compiler to add paciasp/autiasp at the +# begging and end of functions to sign and verify ELR. +# +# The CFG_CORE_PAUTH enables these instructions for the core parts +# executing at EL1, with one secret key per thread and one secret key per +# physical CPU. +# +# The CFG_TA_PAUTH option enables these instructions for TA's at EL0. When +# this option is enabled, TEE core will initialize secret keys per TA. +CFG_CORE_PAUTH ?= n +CFG_TA_PAUTH ?= $(CFG_CORE_PAUTH) + +$(eval $(call cfg-depends-all,CFG_CORE_PAUTH,CFG_ARM64_core)) +$(eval $(call cfg-depends-all,CFG_TA_PAUTH,CFG_ARM64_core)) + +ifeq (y-y,$(CFG_NS_VIRTUALIZATION)-$(CFG_CORE_PAUTH)) +$(error CFG_NS_VIRTUALIZATION and CFG_CORE_PAUTH are currently incompatible) +endif +ifeq (y-y,$(CFG_NS_VIRTUALIZATION)-$(CFG_TA_PAUTH)) +$(error CFG_NS_VIRTUALIZATION and CFG_TA_PAUTH are currently incompatible) +endif + +ifeq (y-y,$(CFG_TA_GPROF_SUPPORT)-$(CFG_TA_PAUTH)) +$(error CFG_TA_GPROF_SUPPORT and CFG_TA_PAUTH are currently incompatible) +endif + +ifeq (y-y,$(CFG_FTRACE_SUPPORT)-$(CFG_TA_PAUTH)) +$(error CFG_FTRACE_SUPPORT and CFG_TA_PAUTH are currently incompatible) +endif + +# Enable support for generic watchdog registration +# This watchdog will then be usable by non-secure world through SMC calls. +CFG_WDT ?= n + +# Enable watchdog SMC handling compatible with arm-smc-wdt Linux driver +# When enabled, CFG_WDT_SM_HANDLER_ID must be defined with a SMC ID +CFG_WDT_SM_HANDLER ?= n + +$(eval $(call cfg-enable-all-depends,CFG_WDT_SM_HANDLER,CFG_WDT)) +ifeq (y-,$(CFG_WDT_SM_HANDLER)-$(CFG_WDT_SM_HANDLER_ID)) +$(error CFG_WDT_SM_HANDLER_ID must be defined when enabling CFG_WDT_SM_HANDLER) +endif + +# Allow using the udelay/mdelay function for platforms without ARM generic timer +# extension. When set to 'n', the plat_get_freq() function must be defined by +# the platform code +CFG_CORE_HAS_GENERIC_TIMER ?= y + +# Enable RTC API +CFG_DRIVERS_RTC ?= n + +# Enable PTA for RTC access from non-secure world +CFG_RTC_PTA ?= n + +# Enable the FF-A SPMC tests in xtests +CFG_SPMC_TESTS ?= n + +# Allocate the translation tables needed to map the S-EL0 application +# loaded +CFG_CORE_PREALLOC_EL0_TBLS ?= n +ifeq (y-y,$(CFG_CORE_PREALLOC_EL0_TBLS)-$(CFG_WITH_PAGER)) +$(error "CFG_WITH_PAGER can't support CFG_CORE_PREALLOC_EL0_TBLS") +endif + +# User TA runtime context dump. +# When this option is enabled, OP-TEE provides a debug method for +# developer to dump user TA's runtime context, including TA's heap stats. +# Developer can open a stats PTA session and then invoke command +# STATS_CMD_TA_STATS to get the context of loaded TAs. +CFG_TA_STATS ?= n + +# Enables best effort mitigations against fault injected when the hardware +# is tampered with. Details in lib/libutils/ext/include/fault_mitigation.h +CFG_FAULT_MITIGATION ?= y + +# Enables TEE Internal Core API v1.1 compatibility for in-tree TAs. Note +# that this doesn't affect libutee itself, it's only the TAs compiled with +# this set that are affected. Each out-of-tree must set this if to enable +# compatibility with version v1.1 as the value of this variable is not +# preserved in the TA dev-kit. +CFG_TA_OPTEE_CORE_API_COMPAT_1_1 ?= n + +# Change supported HMAC key size range, from 64 to 1024. +# This is needed to pass AOSP Keymaster VTS tests: +# Link to tests : https://android.googlesource.com/platform/hardware/interfaces/+/master/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp +# Module: VtsHalKeymasterV3_0TargetTest +# Testcases: - PerInstance/SigningOperationsTest# +# - PerInstance/NewKeyGenerationTest# +# - PerInstance/ImportKeyTest# +# - PerInstance/EncryptionOperationsTest# +# - PerInstance/AttestationTest# +# Note that this violates GP requirements of HMAC size range. +CFG_HMAC_64_1024_RANGE ?= n diff --git a/optee/optee_os/mk/gcc.mk b/optee/optee_os/mk/gcc.mk new file mode 100644 index 0000000..adc77a2 --- /dev/null +++ b/optee/optee_os/mk/gcc.mk @@ -0,0 +1,36 @@ + +CC$(sm) := $(CROSS_COMPILE_$(sm))gcc +CXX$(sm) := $(CROSS_COMPILE_$(sm))g++ +CPP$(sm) := $(CROSS_COMPILE_$(sm))cpp +LD$(sm) := $(CROSS_COMPILE_$(sm))ld.bfd +AR$(sm) := $(CROSS_COMPILE_$(sm))ar +NM$(sm) := $(CROSS_COMPILE_$(sm))nm +OBJCOPY$(sm) := $(CROSS_COMPILE_$(sm))objcopy +OBJDUMP$(sm) := $(CROSS_COMPILE_$(sm))objdump +READELF$(sm) := $(CROSS_COMPILE_$(sm))readelf + +nostdinc$(sm) := -nostdinc -isystem $(shell $(CC$(sm)) \ + -print-file-name=include 2> /dev/null) + +# Get location of libgcc from gcc +libgcc$(sm) := $(shell $(CC$(sm)) $(CFLAGS$(arch-bits-$(sm))) \ + -print-libgcc-file-name 2> /dev/null) +libstdc++$(sm) := $(shell $(CXX$(sm)) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \ + -print-file-name=libstdc++.a 2> /dev/null) +libgcc_eh$(sm) := $(shell $(CXX$(sm)) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \ + -print-file-name=libgcc_eh.a 2> /dev/null) + +# Define these to something to discover accidental use +CC := false +CXX := false +CPP := false +LD := false +AR := false +NM := false +OBJCOPY := false +OBJDUMP := false +READELF := false +nostdinc := --bad-nostdinc-variable +libgcc := --bad-libgcc-variable + + diff --git a/optee/optee_os/mk/lib.mk b/optee/optee_os/mk/lib.mk new file mode 100644 index 0000000..029260d --- /dev/null +++ b/optee/optee_os/mk/lib.mk @@ -0,0 +1,101 @@ +# Input +# +# libname the name of the lib +# libdir directory of lib which also is used as input to +# mk/subdir.mk +# conf-file [optional] if set, all objects will depend on $(conf-file) +# [if CFG_ULIBS_SHARED==y] +# libuuid the UUID of the shared lib +# libl other libraries this library depends on; used to generate the +# proper link arguments (-Lxxx -lyyy) and to add dependencies +# on the needed .so files +# [endif] +# +# Output +# +# updated cleanfiles and +# updated libfiles, libdirs, libnames and libdeps + + +subdirs = $(libdir) +include mk/subdir.mk +ifeq ($(filter $(sm), core ldelf),) # TA +ifeq ($(CFG_ULIBS_MCOUNT),y) +cflags-lib$(libname)-$(sm) += -pg +endif +endif +include mk/compile.mk + +lib-libfile := $(out-dir)/$(base-prefix)$(libdir)/lib$(libname).a +ifeq ($(CFG_ULIBS_SHARED),y) +lib-shlibfile := $(out-dir)/$(base-prefix)$(libdir)/lib$(libname).so +lib-shlibstrippedfile := $(out-dir)/$(base-prefix)$(libdir)/lib$(libname).stripped.so +lib-shlibtafile := $(out-dir)/$(base-prefix)$(libdir)/$(libuuid).ta +lib-libuuidln := $(out-dir)/$(base-prefix)$(libdir)/$(libuuid).elf +lib-shlibfile-$(libname)-$(sm) := $(lib-shlibfile) +lib-libdir-$(libname)-$(sm) := $(out-dir)/$(base-prefix)$(libdir) +lib-needed-so-files := $(foreach l,$(libl),$(lib-shlibfile-$(l)-$(sm))) +lib-Ll-args := $(foreach l,$(libl),-L$(lib-libdir-$(l)-$(sm)) -l$(l)) +endif +cleanfiles := $(lib-libfile) $(lib-shlibfile) $(lib-shlibstrippedfile) $(lib-shlibtafile) $(lib-libuuidln) $(cleanfiles) +libfiles := $(lib-libfile) $(lib-shlibfile) $(lib-shlibstrippedfile) $(lib-shlibtafile) $(lib-libuuidln) $(libfiles) +libdirs := $(out-dir)/$(base-prefix)$(libdir) $(libdirs) +libnames := $(libname) $(libnames) +libdeps := $(lib-libfile) $(libdeps) + +SIGN = scripts/sign_encrypt.py +TA_SIGN_KEY ?= keys/default_ta.pem + +define process-lib +ifeq ($(lib-use-ld), y) +$(lib-libfile): $(objs) + @echo ' LD $$@' + @mkdir -p $$(dir $$@) + $$(q)$$(LD$(sm)) $(lib-ldflags) -o $$@ $$^ +else +$(lib-libfile): $(objs) + @$(cmd-echo-silent) ' AR $$@' + @mkdir -p $$(dir $$@) + $$(q)rm -f $$@ && $$(AR$(sm)) rcs $$@ $$^ +endif +ifeq ($(CFG_ULIBS_SHARED),y) +ifeq ($(sm)-$(CFG_TA_BTI),ta_arm64-y) +lib-ldflags$(lib-shlibfile) += $$(call ld-option,-z force-bti) --fatal-warnings +endif +$(lib-shlibfile): $(objs) $(lib-needed-so-files) + @$(cmd-echo-silent) ' LD $$@' + @mkdir -p $$(dir $$@) + $$(q)$$(LD$(sm)) $(lib-ldflags) -shared -z max-page-size=4096 \ + $(call ld-option,-z separate-loadable-segments) \ + $$(lib-ldflags$(lib-shlibfile)) \ + --soname=$(libuuid) -o $$@ $$(filter-out %.so,$$^) $(lib-Ll-args) + +$(lib-shlibstrippedfile): $(lib-shlibfile) + @$(cmd-echo-silent) ' OBJCOPY $$@' + $$(q)$$(OBJCOPY$(sm)) --strip-unneeded $$< $$@ + +$(lib-shlibtafile): $(lib-shlibstrippedfile) $(TA_SIGN_KEY) + @$(cmd-echo-silent) ' SIGN $$@' + $$(q)$$(PYTHON3) $$(SIGN) --key $(TA_SIGN_KEY) --uuid $(libuuid) --in $$< --out $$@ + +$(lib-libuuidln): $(lib-shlibfile) + @$(cmd-echo-silent) ' LN $$@' + $$(q)ln -sf lib$(libname).so $$@ +endif +endef #process-lib + +$(eval $(call process-lib)) + +$(objs): $(conf-file) + +# Clean residues from processing +objs := +libname := +libuuid := +lib-use-ld := +lib-shlibfile := +lib-shlibstrippedfile := +lib-shlibtafile := +lib-libuuidln := +lib-needed-so-files := +libl := diff --git a/optee/optee_os/mk/subdir.mk b/optee/optee_os/mk/subdir.mk new file mode 100644 index 0000000..7383233 --- /dev/null +++ b/optee/optee_os/mk/subdir.mk @@ -0,0 +1,184 @@ +# Input +# +# subdirs tells the subdirectories to descend +# +# Output +# +# set srcs gen-srcs +# set cflags-$(oname) cflags-remove-$(oname) +# cxxflags-$(oname) cxxflags-remove-$(oname) +# aflags-$(oname) aflags-remove-$(oname) +# cppflags-$(oname) cppflags-remove-$(oname) +# incdirs-$(oname) +# incdirs-lib$(libname)-$(sm) [if libname is defined] +# cppflags-lib$(libname)-$(sm) [if libname is defined] +# cflags-lib$(libname)-$(sm) [if libname is defined] +# cxxflags-lib$(libname)-$(sm) [if libname is defined] +# for each file found, oname is the name of the object file for corresponding +# source file + +srcs := +gen-srcs := +asm-defines-files := + +uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) + +define process-subdir-srcs-y +ifeq ($$(sub-dir),.) +srcs += $1 +oname := $(out-dir)/$(base-prefix)$(basename $1).o +else +ifneq ($(filter /%,$(1)),) +# $1 is an absolute path - start with "/" +srcs += $1 +oname := $(out-dir)/$(base-prefix)$(basename $1).o +else +srcs += $(sub-dir)/$1 +oname := $(out-dir)/$(base-prefix)$(basename $$(sub-dir)/$1).o +endif +endif +cflags-$$(oname) := $$(cflags-y) $$(cflags-$(1)-y) +cflags-remove-$$(oname) := $$(cflags-remove-y) \ + $$(cflags-remove-$(1)-y) +cxxflags-$$(oname) := $$(cxxflags-y) $$(cxxflags-$(1)-y) +cxxflags-remove-$$(oname) := $$(cxxflags-remove-y) \ + $$(cxxflags-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) +incdirs-$$(oname) := $$(thissubdir-incdirs) $$(addprefix $(sub-dir)/,$$(incdirs-$(1)-y)) +# Clear local filename specific variables to avoid accidental reuse +# in another subdirectory +cflags-$(1)-y := +cflags-remove-$(1)-y := +cflags-lib-y := +cxxflags-$(1)-y := +cxxflags-remove-$(1)-y := +cxxflags-lib-y := +cppflags-$(1)-y := +cppflags-remove-$(1)-y := +cppflags-lib-y := +aflags-$(1)-y := +aflags-remove-$(1)-y := +incdirs-$(1)-y := +fname := +oname := +endef #process-subdir-srcs-y + +define process-subdir-gensrcs-helper +# $1 gensrc-y element +# $2 full path and name of generated source file +# $3 full path and name of object file compiled from source file +# $4 full path to out directory +# $5 y if $2 must be generated before $(sm) starts building (e.g., .h file) + +gen-srcs += $2 +cleanfiles += $2 +oname := $3 + +FORCE-GENSRC$(sm): $(if $(filter y,$5),$2,) + +$$(addprefix $4,$$(produce-additional-$1)): $2 + +subdir-$2 := $$(sub-dir) +recipe-$2 := $$(recipe-$1) +$2: $$(depends-$1) + @$(cmd-echo-silent) ' GEN $2' + $(q)mkdir -p $4 + $(q)$$(recipe-$2) + +cflags-$$(oname) := $$(cflags-y) $$(cflags-$(1)-y) +cflags-remove-$$(oname) := $$(cflags-remove-y) \ + $$(cflags-remove-$(1)-y) +cxxflags-$$(oname) := $$(cxxflags-y) $$(cxxflags-$(1)-y) +cxxflags-remove-$$(oname) := $$(cxxflags-remove-y) \ + $$(cxxflags-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) +incdirs-$$(oname) := $$(thissubdir-incdirs) $$(addprefix $(sub-dir)/,$$(incdirs-$(1)-y)) +# Clear local filename specific variables to avoid accidental reuse +# in another subdirectory +cflags-$(1)-y := +cflags-remove-$(1)-y := +cflags-lib-y := +cxxflags-$(1)-y := +cxxflags-remove-$(1)-y := +cxxflags-lib-y := +cppflags-$(1)-y := +cppflags-remove-$(1)-y := +cppflags-lib-y := +aflags-$(1)-y := +aflags-remove-$(1)-y := +incdirs-$(1)-y := +fname := +oname := + +endef #process-subdir-gensrcs-helper + +define process-subdir-gensrcs-y +$$(eval $$(call process-subdir-gensrcs-helper,$1,$(sub-dir-out)/$$(produce-$1),$(sub-dir-out)/$(basename $(produce-$1)).o,$(sub-dir-out),$(force-gensrc-$1))) +endef #process-subdir-gensrcs-y + +define process-subdir-asm-defines-y +asm-defines-files += $(sub-dir)/$1 +endef #process-subdir-asm-defines-y + +define process-subdir +sub-dir := $1 +ifeq ($1,.) +sub-dir-out := $(patsubst %/,%,$(out-dir)/$(base-prefix)) +else +sub-dir-out := $(out-dir)/$(base-prefix)$1 +endif + +include $1/sub.mk +sub-subdirs := $$(addprefix $1/,$$(subdirs-y)) $$(subdirs_ext-y) +incdirs$(sm) := $(incdirs$(sm)) $$(addprefix $1/,$$(global-incdirs-y)) $$(global-incdirs_ext-y) +thissubdir-incdirs := $(out-dir)/$(base-prefix)$1 $$(addprefix $1/,$$(incdirs-y)) $$(incdirs_ext-y) +ifneq ($$(libname),) +incdirs-lib$$(libname)-$$(sm) := $$(incdirs-lib$$(libname)-$$(sm)) $$(addprefix $1/,$$(incdirs-lib-y)) +cflags-lib$$(libname)-$$(sm) := $$(cflags-lib$$(libname)-$$(sm)) $$(cflags-lib-y) +cxxflags-lib$$(libname)-$$(sm) := $$(cxxflags-lib$$(libname)-$$(sm)) $$(cxxflags-lib-y) +cppflags-lib$$(libname)-$$(sm) := $$(cppflags-lib$$(libname)-$$(sm)) $$(cppflags-lib-y) +endif + +# Process files in current directory +$$(foreach g, $$(gensrcs-y), $$(eval $$(call process-subdir-gensrcs-y,$$(g)))) +$$(foreach s, $$(srcs-y), $$(eval $$(call process-subdir-srcs-y,$$(s)))) +$$(foreach a, $$(asm-defines-y), $$(eval $$(call process-subdir-asm-defines-y,$$(a)))) +# Clear flags used when processing current directory +srcs-y := +cflags-y := +cflags-lib-y := +cxxflags-y := +cxxflags-lib-y := +cppflags-y := +cppflags-lib-y := +aflags-y := +cflags-remove-y := +cxxflags-remove-y := +aflags-remove-y := +subdirs-y := +subdirs_ext-y := +global-incdirs-y := +global-incdirs_ext-y := +incdirs-lib-y := +incdirs-y := +incdirs_ext-y := +gensrcs-y := +this-out-dir := +asm-defines-y := + +# Process subdirectories in current directory +$$(foreach sd, $$(call uniq,$$(sub-subdirs)), $$(eval $$(call process-subdir,$$(sd)))) +endef #process-subdir + +# Top subdirectories +$(foreach sd, $(call uniq,$(subdirs)), $(eval $(call process-subdir,$(sd)))) diff --git a/optee/optee_os/prebuilt/t234/libcommon_crypto.a b/optee/optee_os/prebuilt/t234/libcommon_crypto.a new file mode 100644 index 0000000000000000000000000000000000000000..f47b546d83658183f77f888d95e319f92866f8c5 GIT binary patch literal 387062 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

6Pd86K_2Zw^ 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 literal 0 HcmV?d00001 diff --git a/optee/optee_os/scripts/arm32_sysreg.py b/optee/optee_os/scripts/arm32_sysreg.py new file mode 100755 index 0000000..4b6f9cf --- /dev/null +++ b/optee/optee_os/scripts/arm32_sysreg.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2018, Linaro Limited +# + + +import argparse +import sys +import re + + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + + +def my_err(line_number, msg): + eprint('Error: line:' + repr(line_number) + ' ' + msg) + sys.exit(1) + + +def gen_read64_macro(reg_name, opc1, crm, descr): + print('') + if len(descr): + print('\t# ' + descr) + print('\t.macro read_' + reg_name.lower() + ' reg0, reg1') + print('\tmrrc\tp15, ' + opc1 + ', \\reg0, \\reg1, ' + crm) + print('\t.endm') + + +def gen_write64_macro(reg_name, opc1, crm, descr): + print('') + if len(descr): + print('\t# ' + descr) + print('\t.macro write_' + reg_name.lower() + ' reg0, reg1') + print('\tmcrr\tp15, ' + opc1 + ', \\reg0, \\reg1, ' + crm) + print('\t.endm') + + +def gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr): + print('') + if len(descr): + print('\t# ' + descr) + print('\t.macro read_' + reg_name.lower() + ' reg') + print('\tmrc p15, ' + opc1 + ', \\reg, ' + crn + ', ' + crm + ', ' + opc2) + print('\t.endm') + + +def gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr): + print('') + if len(descr): + print('\t# ' + descr) + print('\t.macro write_' + reg_name.lower() + ' reg') + print('\tmcr p15, ' + opc1 + ', \\reg, ' + crn + ', ' + crm + ', ' + opc2) + print('\t.endm') + + +def gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2, descr): + print('') + if len(descr): + print('\t# ' + descr) + print('\t.macro write_' + reg_name.lower()) + print('\t# Register ignored') + print('\tmcr p15, ' + opc1 + ', r0, ' + crn + ', ' + crm + ', ' + opc2) + print('\t.endm') + + +def gen_read64_func(reg_name, opc1, crm, descr): + print('') + if len(descr): + print('/* ' + descr + ' */') + print('static inline __noprof uint64_t read_' + reg_name.lower() + + '(void)') + print('{') + print('\tuint64_t v;') + print('') + print('\tasm volatile ("mrrc p15, ' + opc1 + ', %Q0, %R0, ' + + crm + '"' + ' : "=r" (v));') + print('') + print('\treturn v;') + print('}') + + +def gen_write64_func(reg_name, opc1, crm, descr): + print('') + if len(descr): + print('/* ' + descr + ' */') + print('static inline __noprof void write_' + reg_name.lower() + + '(uint64_t v)') + print('{') + print('\tasm volatile ("mcrr p15, ' + opc1 + ', %Q0, %R0, ' + + crm + '"' + ' : : "r" (v));') + print('}') + + +def gen_read32_func(reg_name, crn, opc1, crm, opc2, descr): + print('') + if len(descr): + print('/* ' + descr + ' */') + print('static inline __noprof uint32_t read_' + reg_name.lower() + + '(void)') + print('{') + print('\tuint32_t v;') + print('') + print('\tasm volatile ("mrc p15, ' + opc1 + ', %0, ' + crn + ', ' + + crm + ', ' + opc2 + '"' + ' : "=r" (v));') + print('') + print('\treturn v;') + print('}') + + +def gen_write32_func(reg_name, crn, opc1, crm, opc2, descr): + print('') + if len(descr): + print('/* ' + descr + ' */') + print('static inline __noprof void write_' + reg_name.lower() + + '(uint32_t v)') + print('{') + print('\tasm volatile ("mcr p15, ' + opc1 + ', %0, ' + crn + ', ' + + crm + ', ' + opc2 + '"' + ' : : "r" (v));') + print('}') + + +def gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, descr): + print('') + if len(descr): + print('/* ' + descr + ' */') + print('static inline __noprof void write_' + reg_name.lower() + '(void)') + print('{') + print('\t/* Register ignored */') + print('\tasm volatile ("mcr p15, ' + opc1 + ', r0, ' + crn + ', ' + + crm + ', ' + opc2 + '");') + print('}') + + +def gen_file(line, line_number, s_file): + words = line.split() + if len(words) == 0: + return + + if len(re.findall('^ *#', line)): + return + + if len(re.findall('^ *@', line)): + comment = re.sub('^ *@', '', line) + comment = re.sub('^ *', '', comment) + comment = re.sub('[ \n]*$', '', comment) + if len(comment) == 0: + print('') + return + if s_file: + print('# ' + comment) + else: + print('/* ' + comment + ' */') + return + + reg_name = words[0] + crn = words[1] + opc1 = words[2] + crm = words[3] + opc2 = words[4] + access_type = words[5] + descr = " ".join(words[6:]) + + read_access = access_type == 'RO' or access_type == 'RW' + write_access = (access_type == 'WO' or access_type == 'RW' or + access_type == 'WOD') + dummy_access = access_type == 'WOD' + + if not read_access and not write_access: + my_err(line_number, 'bad Access Type "' + access_type + '"') + + if crn == '-': + if opc2 != '-': + my_err(line_number, 'bad opc2, expected -') + + if read_access: + if s_file: + gen_read64_macro(reg_name, opc1, crm, descr) + else: + gen_read64_func(reg_name, opc1, crm, descr) + + if s_file: + gen_write64_macro(reg_name, opc1, crm, descr) + else: + gen_write64_func(reg_name, opc1, crm, descr) + else: + if read_access: + if s_file: + gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr) + else: + gen_read32_func(reg_name, crn, opc1, crm, opc2, descr) + + if write_access: + if dummy_access: + if s_file: + gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2, + descr) + else: + gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, + descr) + else: + if s_file: + gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr) + else: + gen_write32_func(reg_name, crn, opc1, crm, opc2, descr) + + +def get_args(): + parser = argparse.ArgumentParser(description='Generates instructions to ' + 'access ARM32 system registers.') + + parser.add_argument('--s_file', action='store_true', + help='Generate an Assembly instead of a C file') + parser.add_argument('--guard', + help='Provide #ifdef in C file') + + return parser.parse_args() + + +def main(): + args = get_args() + + cmnt = 'Automatically generated, do not edit' + if args.s_file: + print('# ' + cmnt) + else: + print('/* ' + cmnt + ' */') + if args.guard is not None: + print('#ifndef ' + args.guard.upper().replace('.', '_')) + print('#define ' + args.guard.upper().replace('.', '_')) + print('#include ') + + line_number = 0 + for line in sys.stdin: + line_number = line_number + 1 + gen_file(line, line_number, args.s_file) + + if not args.s_file and args.guard is not None: + print('#endif /*' + args.guard.upper().replace('.', '_') + '*/') + + +if __name__ == '__main__': + main() diff --git a/optee/optee_os/scripts/bin_to_c.py b/optee/optee_os/scripts/bin_to_c.py new file mode 100755 index 0000000..8ac6d30 --- /dev/null +++ b/optee/optee_os/scripts/bin_to_c.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2018, Linaro Limited +# + +import argparse +import array +import os +import re +import sys + + +def get_args(): + + parser = argparse.ArgumentParser(description='Converts a binary file ' + 'into C source file defining binary ' + 'data as a constant byte array.') + + parser.add_argument('--bin', required=True, + help='Path to the input binary file') + + parser.add_argument('--vname', required=True, + help='Variable name for the generated table in ' + 'the output C source file.') + + parser.add_argument('--out', required=True, + help='Path for the generated C file') + + parser.add_argument('--text', required=False, action='store_true', + help='Treat input as a text file') + + return parser.parse_args() + + +def main(): + + args = get_args() + + with open(args.bin, 'rb') as indata: + bytes = indata.read() + if args.text: + bytes += b'\0' + size = len(bytes) + + f = open(args.out, 'w') + f.write('/* Generated from ' + args.bin + ' by ' + + os.path.basename(__file__) + ' */\n\n') + f.write('#include \n') + f.write('#include \n') + if args.text: + f.write('__extension__ const char ' + args.vname + '[] = {\n') + else: + f.write('__extension__ const uint8_t ' + args.vname + '[] ' + + ' __aligned(__alignof__(uint64_t)) = {\n') + i = 0 + while i < size: + if i % 8 == 0: + f.write('\t\t') + if args.text and i != size - 1 and bytes[i] == b'\0': + print('Error: null byte encountered in text file') + sys.exit(1) + f.write(hex(bytes[i]) + ',') + i = i + 1 + if i % 8 == 0 or i == size: + f.write('\n') + else: + f.write(' ') + f.write('};\n') + f.close() + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/checkpatch.sh b/optee/optee_os/scripts/checkpatch.sh new file mode 100755 index 0000000..c403dd2 --- /dev/null +++ b/optee/optee_os/scripts/checkpatch.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +DIR="${BASH_SOURCE%/*}" + +# if no CHECKPATCH is explicitly given by the environment, try to +# locate checkpatch.pl: first take the one from the path, then check +# for a local copy of the linux headers, finally try sources downloaded +# with OP-TEE (for QEMU) +if [ -z "$CHECKPATCH" ]; then + CHECKPATCH=$(command -v checkpatch.pl) +fi +if [ -z "$CHECKPATCH" ]; then + CHECKPATCH=$(find /usr/src/linux-headers* -name checkpatch.pl -print -quit) +fi +if [ -z "$CHECKPATCH" ]; then + CHECKPATCH=$(find "$PWD/../linux" -name checkpatch.pl -print -quit) +fi + +source "$DIR/checkpatch_inc.sh" + +hash $CHECKPATCH 2>/dev/null || + { echo >&2 "Could not find checkpatch.pl, aborting"; exit 1; } + +help() { + cat <<-EOF +Usage: + checkpatch.sh [--working] + checkpatch.sh ... + checkpatch.sh ... + checkpatch.sh --diff + checkpatch.sh --cached + checkpatch.sh --help + +Args: + Any commit or any number of commits. + Any number of Git Revision Selections. (requires git v2.19) + https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection + +Options: + --working Check the working area [Default]. + --cached Check the staging area. + --diff Check the diff between commit1 and commit2. + --help Print this help message. + +Examples: + checkpatch.sh commit1 commit2 commit3 Check commit1, commit2, and commit3. + + checkpatch.sh HEAD~5 Check the commit 5 revisions before + the current HEAD. + + checkpatch.sh commit1..^commit2 Check each commit from commit1 to + commit2 inclusively. + (requires git v2.19) + + checkpatch.sh HEAD~5..HEAD~1 Check each commit from HEAD~5 to + HEAD~1 exclusively, aka not including + HEAD~1. (requires git v2.19) + + checkpatch.sh commit1...tags/tag1 Check each commit that exists + exclusively within the history of + only one of each given revision. + (requires git v2.19) + + checkpatch.sh HEAD~10-5 Check 5 commits moving forward in + history starting from HEAD~10. + (requires git v2.19) + + checkpatch.sh branch1 tags/tag1 Check the HEAD of branch1 and the + HEAD of tag1. (requires git v2.19) +EOF + exit 1 +} + +op=${1:---working} +case "$op" in + --cached) + echo "Checking staging area: " + checkstaging + ;; + --diff) + echo "Checking diff (diff $1...$2)" + checkdiff "$2" "$3" + ;; + --working) + echo "Checking working area: " + checkworking + ;; + --help|-h) + help + ;; + *) + echo "Checking commit(s):" + read -r MAJOR MINOR < <(git --version | awk -F '[. ]' '{print $3, $4}') + if (( MAJOR < 2 )) || (( MAJOR == 2 && MINOR < 19 )); then + for c in "$@"; do checkpatch "$c"; done + else + for arg in "$@"; do + # parse the argument into a git object or list of git objects + object="$(git rev-parse "${arg}")" || continue + # run checkpatch if the parsed argument represents a single commit hash + if git cat-file -e "${object}" 2>/dev/null; then + checkpatch "${object}" + else + # expand the object list and run checkpatch on each commit id + commits="$(echo "${object}" | git rev-list --stdin)" + for c in ${commits}; do checkpatch "$c"; done + fi + done + fi + ;; + +esac diff --git a/optee/optee_os/scripts/checkpatch_inc.sh b/optee/optee_os/scripts/checkpatch_inc.sh new file mode 100644 index 0000000..fb77d5c --- /dev/null +++ b/optee/optee_os/scripts/checkpatch_inc.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +CHECKPATCH="${CHECKPATCH:-checkpatch.pl}" +CHECKPATCH_OPT="${CHECKPATCH_OPT:-}" +# checkpatch.pl will ignore the following paths +CHECKPATCH_IGNORE=$(echo \ + core/include/gen-asm-defines.h \ + core/lib/lib{fdt,tomcrypt} core/lib/zlib \ + lib/libutils lib/libmbedtls \ + lib/libutee/include/elf.h \ + lib/libutee/include/elf_common.h \ + core/arch/arm/include/arm{32,64}.h \ + core/arch/arm/plat-ti/api_monitor_index_a{9,15}.h \ + core/arch/arm/dts \ + ta/pkcs11/scripts/verify-helpers.sh \ + core/arch/riscv/include/encoding.h ) +_CP_EXCL=$(for p in $CHECKPATCH_IGNORE; do echo ":(exclude)$p" ; done) + +function _checkpatch() { + # Use --typedefsfile if supported by the checkpatch tool + typedefs_opt="--typedefsfile typedefs.checkpatch" + $CHECKPATCH --help 2>&1 | grep -q -- --typedefsfile || \ + typedefs_opt=""; + # Ignore NOT_UNIFIED_DIFF in case patch has no diff + # (e.g., all paths filtered out) + $CHECKPATCH $CHECKPATCH_OPT $typedefs_opt - +} + +function checkpatch() { + git show --oneline --no-patch $1 + # The first git 'format-patch' shows the commit message + # The second one produces the diff (might be empty if _CP_EXCL + # filters out all diffs) + (git format-patch $1^..$1 --stdout | sed -n '/^diff --git/q;p'; \ + git format-patch $1^..$1 --stdout -- $_CP_EXCL . | \ + sed -n '/^diff --git/,$p') | _checkpatch +} + +function checkstaging() { + git diff --cached -- . $_CP_EXCL | _checkpatch +} + +function checkworking() { + git diff -- . $_CP_EXCL | _checkpatch +} + +function checkdiff() { + git diff $1...$2 -- . $_CP_EXCL | _checkpatch +} + diff --git a/optee/optee_os/scripts/gen_ld_sects.py b/optee/optee_os/scripts/gen_ld_sects.py new file mode 100755 index 0000000..bc82dd8 --- /dev/null +++ b/optee/optee_os/scripts/gen_ld_sects.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2017, Linaro Limited +# + +import sys +import re + + +def usage(): + print("Usage: {0}

[...]".format( + sys.argv[0])) + sys.exit(1) + + +def main(): + if len(sys.argv) < 2: + usage() + + in_shdr = False + section_headers = re.compile("Section Headers:") + key_to_flags = re.compile("Key to Flags:") + match_rule = re.compile(sys.argv[1]) + skip_sections = sys.argv[2:] + + for line in sys.stdin: + if section_headers.match(line): + in_shdr = True + continue + if key_to_flags.match(line): + in_shdr = False + continue + + if not in_shdr: + continue + + words = line.split() + + if len(words) < 3: + continue + + if words[0] == "[": + name_offs = 2 + else: + name_offs = 1 + + sect_name = words[name_offs] + sect_type = words[name_offs + 1] + + if sect_type != "PROGBITS": + continue + + if not match_rule.match(sect_name): + continue + + if sect_name in skip_sections: + continue + + print('\t*({0})'.format(sect_name)) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/gen_ldelf_hex.py b/optee/optee_os/scripts/gen_ldelf_hex.py new file mode 100755 index 0000000..a6123b2 --- /dev/null +++ b/optee/optee_os/scripts/gen_ldelf_hex.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019, Linaro Limited +# + +from __future__ import print_function +from __future__ import division + +import argparse +import sys +try: + from elftools.elf.elffile import ELFFile + from elftools.elf.sections import SymbolTableSection + from elftools.elf.constants import P_FLAGS +except ImportError: + print(""" +*** +Can't find elftools module. Probably it is not installed on your system. +You can install this module with + +$ apt install python3-pyelftools + +if you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in +your package manager if you are using some other distribution. +*** +""") + raise + + +def round_up(n, m): + if n == 0: + return 0 + else: + return (((n - 1) // m) + 1) * m + + +def emit_load_segments(elffile, outf): + load_size = 0 + code_size = 0 + data_size = 0 + load_segments = [s for s in elffile.iter_segments() + if s['p_type'] == 'PT_LOAD'] + prev_segment = None + pad = 0 + pad_size = [] + w_found = False + n = 0 + # Check that load segments ordered by VA have the expected layout: + # read only first, then read-write. Compute padding at end of each segment, + # 0 if none is required. + for segment in load_segments: + if prev_segment: + pad = segment['p_vaddr'] - (prev_segment['p_vaddr'] + + prev_segment['p_filesz']) + else: + if segment['p_flags'] & P_FLAGS.PF_W: + print('Expected RO load segment(s) first') + sys.exit(1) + if segment['p_flags'] & P_FLAGS.PF_W: + if not w_found: + # End of RO segments, discard padding for the last one (it + # would just take up space in the generated C file) + pad = 0 + w_found = True + else: + if w_found: + print('RO load segment found after RW one(s) (m={})'.format(n)) + sys.exit(1) + if prev_segment: + if pad > 31: + # We expect segments to be tightly packed together for memory + # efficiency. 31 is an arbitrary, "sounds reasonable" value + # which might need to be adjusted -- who knows what the + # compiler/linker can do. + print('Warning: suspiciously large padding ({}) after load ' + 'segment {}, please check'.format(pad, n-1)) + pad_size.append(pad) + prev_segment = segment + n = n + 1 + pad_size.append(0) + n = 0 + # Compute code_size, data_size and load_size + for segment in load_segments: + sz = segment['p_filesz'] + pad_size[n] + if segment['p_flags'] & P_FLAGS.PF_W: + data_size += sz + else: + code_size += sz + load_size += sz + n = n + 1 + n = 0 + i = 0 + # Output data to C file + outf.write(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096)) + outf.write(b' __aligned(4096) = {\n') + for segment in load_segments: + data = segment.data() + if pad_size[n]: + # Pad with zeros if needed + data += bytearray(pad_size[n]) + for j in range(len(data)): + if i % 8 == 0: + outf.write(b'\t') + outf.write(b'0x' + '{:02x}'.format(data[j]).encode('utf-8') + + b',') + i = i + 1 + if i % 8 == 0 or i == load_size: + outf.write(b'\n') + else: + outf.write(b' ') + n = n + 1 + outf.write(b'};\n') + + outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size) + outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size) + + +def get_args(): + parser = argparse.ArgumentParser() + + parser.add_argument('--input', + required=True, type=argparse.FileType('rb'), + help='The input ldelf.elf') + + parser.add_argument('--output', + required=True, type=argparse.FileType('wb'), + help='The output ldelf_hex.c') + + return parser.parse_args() + + +def main(): + args = get_args() + inf = args.input + outf = args.output + + elffile = ELFFile(inf) + + outf.write(b'/* Automatically generated, do no edit */\n') + outf.write(b'#include \n') + outf.write(b'#include \n') + emit_load_segments(elffile, outf) + outf.write(b'const unsigned long ldelf_entry = %lu;\n' % + elffile.header['e_entry']) + + inf.close() + outf.close() + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/gen_stmm_hex.py b/optee/optee_os/scripts/gen_stmm_hex.py new file mode 100755 index 0000000..ea16fdd --- /dev/null +++ b/optee/optee_os/scripts/gen_stmm_hex.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019, Linaro Limited +# + +import argparse +import sys +import zlib + + +def get_args(): + parser = argparse.ArgumentParser() + + parser.add_argument('--input', + required=True, type=argparse.FileType('rb'), + help='The input StMM binary (BL32_AP_MM.fd)') + + parser.add_argument('--output', + required=True, type=argparse.FileType('w'), + help='The output stmm_hex.c') + + return parser.parse_args() + + +def main(): + args = get_args() + inf = args.input + outf = args.output + + bytes = inf.read() + uncompressed_size = len(bytes) + bytes = zlib.compress(bytes) + size = len(bytes) + + outf.write('/* Automatically generated, do no edit */\n') + outf.write('const unsigned char stmm_image[] = {\n') + i = 0 + while i < size: + if i % 8 == 0: + outf.write('\t') + outf.write('0x{:02x},'.format(bytes[i])) + i = i + 1 + if i % 8 == 0 or i == size: + outf.write('\n') + else: + outf.write(' ') + outf.write('};\n') + + outf.write('const unsigned int stmm_image_size = sizeof(stmm_image);\n') + outf.write('const unsigned int stmm_image_uncompressed_size = ' + '{:d};\n'.format(uncompressed_size)) + + inf.close() + outf.close() + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/gen_tee_bin.py b/optee/optee_os/scripts/gen_tee_bin.py new file mode 100755 index 0000000..a4aa532 --- /dev/null +++ b/optee/optee_os/scripts/gen_tee_bin.py @@ -0,0 +1,411 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019, Linaro Limited +# + +from __future__ import print_function +from __future__ import division + +import argparse +import sys +import struct +import re +import hashlib +try: + from elftools.elf.elffile import ELFFile + from elftools.elf.constants import SH_FLAGS + from elftools.elf.enums import ENUM_RELOC_TYPE_ARM + from elftools.elf.enums import ENUM_RELOC_TYPE_AARCH64 + from elftools.elf.sections import SymbolTableSection + from elftools.elf.relocation import RelocationSection + +except ImportError: + print(""" +*** +Can't find elftools module. Probably it is not installed on your system. +You can install this module with + +$ apt install python3-pyelftools + +if you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in +your package manager if you are using some other distribution. +*** +""") + raise + +small_page_size = 4 * 1024 +elffile_symbols = None +tee_pageable_bin = None +tee_pager_bin = None +tee_embdata_bin = None + + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + + +def round_up(n, m): + if n == 0: + return 0 + else: + return (((n - 1) // m) + 1) * m + + +def get_arch_id(elffile): + e_machine = elffile.header['e_machine'] + if e_machine == 'EM_ARM': + return 0 + if e_machine == 'EM_AARCH64': + return 1 + eprint('Unknown e_machine "%s"' % e_machine) + sys.exit(1) + + +def get_name(obj): + # Symbol or section .name might be a byte array or a string, we want a + # string + try: + name = obj.name.decode() + except (UnicodeDecodeError, AttributeError): + name = obj.name + return name + + +def get_symbol(elffile, name): + global elffile_symbols + global lsyms_def + if elffile_symbols is None: + elffile_symbols = dict() + lsyms_def = dict() + symbol_tables = [s for s in elffile.iter_sections() + if isinstance(s, SymbolTableSection)] + for section in symbol_tables: + for symbol in section.iter_symbols(): + symbol_name = get_name(symbol) + if symbol['st_info']['bind'] == 'STB_GLOBAL': + elffile_symbols[symbol_name] = symbol + elif symbol['st_info']['bind'] == 'STB_LOCAL': + if symbol_name not in elffile_symbols.keys(): + elffile_symbols[symbol_name] = symbol + if symbol_name not in lsyms_def.keys(): + lsyms_def[symbol_name] = 1 + else: + lsyms_def[symbol_name] += 1 + + if name in lsyms_def.keys() and lsyms_def[name] > 1: + eprint("Multiple definitions of local symbol %s" % name) + sys.exit(1) + if name not in elffile_symbols.keys(): + eprint("Cannot find symbol %s" % name) + sys.exit(1) + + return elffile_symbols[name] + + +def get_sections(elffile, pad_to, dump_names): + last_end = 0 + bin_data = bytearray() + + for section in elffile.iter_sections(): + section_name = get_name(section) + if (section['sh_type'] == 'SHT_NOBITS' or + not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or + not dump_names.match(section_name)): + continue + + if last_end == 0: + bin_data = section.data() + else: + if section['sh_addr'] > last_end: + bin_data += bytearray(section['sh_addr'] - last_end) + bin_data += section.data() + + last_end = section['sh_addr'] + section['sh_size'] + + if pad_to > last_end: + bin_data += bytearray(pad_to - last_end) + last_end = pad_to + + return bin_data + + +def get_pageable_bin(elffile): + global tee_pageable_bin + if tee_pageable_bin is None: + pad_to = 0 + dump_names = re.compile(r'^\..*_(pageable|init)$') + tee_pageable_bin = get_sections(elffile, pad_to, dump_names) + return tee_pageable_bin + + +def get_pager_bin(elffile): + global tee_pager_bin + if tee_pager_bin is None: + pad_to = get_symbol(elffile, '__data_end')['st_value'] + dump_names = re.compile(r'^\.(text|nex_data|rodata|ctors|got|data|' + r'data\.rel\.ro|ARM\.exidx|ARM\.extab)$') + tee_pager_bin = get_sections(elffile, pad_to, dump_names) + + return tee_pager_bin + + +def get_reloc_bin(elffile): + if get_arch_id(elffile) == 0: + exp_rel_type = ENUM_RELOC_TYPE_ARM['R_ARM_RELATIVE'] + else: + exp_rel_type = ENUM_RELOC_TYPE_AARCH64['R_AARCH64_RELATIVE'] + + link_address = get_symbol(elffile, '__text_start')['st_value'] + + addrs = [] + for section in elffile.iter_sections(): + if not isinstance(section, RelocationSection): + continue + for rel in section.iter_relocations(): + if rel['r_info_type'] == 0: + continue + if rel['r_info_type'] != exp_rel_type: + eprint("Unexpected relocation type 0x%x" % + rel['r_info_type']) + sys.exit(1) + addrs.append(rel['r_offset'] - link_address) + + addrs.sort() + data = bytearray() + for a in addrs: + data += struct.pack('> 32 + init_load_addr_lo = init_load_addr & 0xffffffff + return init_load_addr_hi, init_load_addr_lo + + +def output_raw_bin(elffile, outf): + pager_bin = get_pager_bin(elffile) + pageable_bin = get_pageable_bin(elffile) + embdata_bin = get_embdata_bin(elffile) + init_bin_size = get_symbol(elffile, '__init_size')['st_value'] + + outf.write(pager_bin) + outf.write(pageable_bin[:init_bin_size]) + outf.write(embdata_bin) + outf.write(pageable_bin[init_bin_size:]) + + +def output_header_v1(elffile, outf): + arch_id = get_arch_id(elffile) + pager_bin = get_pager_bin(elffile) + pageable_bin = get_pageable_bin(elffile) + embdata_bin = get_embdata_bin(elffile) + init_load_addr = get_init_load_addr(elffile) + init_bin_size = get_symbol(elffile, '__init_size')['st_value'] + pager_bin_size = len(pager_bin) + paged_area_size = len(pageable_bin) + + init_mem_usage = (get_symbol(elffile, '__get_tee_init_end')['st_value'] - + get_symbol(elffile, '__text_start')['st_value'] + + len(embdata_bin)) + + init_size = (pager_bin_size + min(init_bin_size, paged_area_size) + + len(embdata_bin)) + paged_size = paged_area_size - min(init_bin_size, paged_area_size) + + magic = 0x4554504f # 'OPTE' + version = 1 + flags = 0 + outf.write(struct.pack('.*) ') +REVIEWED_RE = re.compile(r'^Reviewed-by: (?P.*>)') +ACKED_RE = re.compile(r'^Acked-by: (?P.*>)') +PATCH_START = re.compile(r'^From [0-9a-f]{40}') + + +def get_args(): + parser = argparse.ArgumentParser(description='Print the maintainers for ' + 'the given source files or directories; ' + 'or for the files modified by a patch or ' + 'a pull request. ' + '(With -m) Check if a patch or pull ' + 'request is properly Acked/Reviewed for ' + 'merging.') + parser.add_argument('-m', '--merge-check', action='store_true', + help='use Reviewed-by: and Acked-by: tags found in ' + 'patches to prevent display of information for all ' + 'the approved paths.') + parser.add_argument('-p', '--show-paths', action='store_true', + help='show all paths that are not approved.') + parser.add_argument('-s', '--strict', action='store_true', + help='stricter conditions for patch approval check: ' + 'subsystem "THE REST" is ignored for paths that ' + 'match some other subsystem.') + parser.add_argument('arg', nargs='*', help='file or patch') + parser.add_argument('-f', '--file', action='append', + help='treat following argument as a file path, not ' + 'a patch.') + parser.add_argument('-g', '--github-pr', action='append', type=int, + help='Github pull request ID. The script will ' + 'download the patchset from Github to a temporary ' + 'file and process it.') + parser.add_argument('-r', '--release-to', action='store_true', + help='show all the recipients to be used in release ' + 'announcement emails (i.e., maintainers, reviewers ' + 'and OP-TEE mailing list(s)) and exit.') + return parser.parse_args() + + +def check_cwd(): + cwd = os.getcwd() + parent = os.path.dirname(os.path.realpath(__file__)) + "/../" + if (os.path.realpath(cwd) != os.path.realpath(parent)): + print("Error: this script must be run from the top-level of the " + "optee_os tree") + exit(1) + + +# Parse MAINTAINERS and return a dictionary of subsystems such as: +# {'Subsystem name': {'R': ['foo', 'bar'], 'S': ['Maintained'], +# 'F': [ 'path1', 'path2' ]}, ...} +def parse_maintainers(): + subsystems = {} + check_cwd() + with open("MAINTAINERS", "r") as f: + start_found = False + ss = {} + name = '' + for line in f: + line = line.strip() + if not line: + continue + if not start_found: + if line.startswith("----------"): + start_found = True + continue + + if line[1] == ':': + letter = line[0] + if (not ss.get(letter)): + ss[letter] = [] + ss[letter].append(line[3:]) + else: + if name: + subsystems[name] = ss + name = line + ss = {} + if name: + subsystems[name] = ss + + return subsystems + + +# If @patchset is a patchset files and contains 2 patches or more, write +# individual patches to temporary files and return the paths. +# Otherwise return []. +def split_patchset(patchset): + psname = os.path.basename(patchset).replace('.', '_') + patchnum = 0 + of = None + ret = [] + f = None + try: + f = open(patchset, "r") + except OSError: + return [] + for line in f: + match = re.search(PATCH_START, line) + if match: + # New patch found: create new file + patchnum += 1 + prefix = "{}_{}_".format(patchnum, psname) + of = tempfile.NamedTemporaryFile(mode="w", prefix=prefix, + suffix=".patch", + delete=False) + ret.append(of.name) + if of: + of.write(line) + if len(ret) >= 2: + return ret + if len(ret) == 1: + os.remove(ret[0]) + return [] + + +# If @path is a patch file, returns the paths touched by the patch as well +# as the content of the review/ack tags +def get_paths_from_patch(patch): + paths = [] + approvers = [] + try: + with open(patch, "r") as f: + for line in f: + match = re.search(DIFF_GIT_RE, line) + if match: + p = match.group('path') + if p not in paths: + paths.append(p) + continue + match = re.search(REVIEWED_RE, line) + if match: + a = match.group('approver') + if a not in approvers: + approvers.append(a) + continue + match = re.search(ACKED_RE, line) + if match: + a = match.group('approver') + if a not in approvers: + approvers.append(a) + continue + except Exception: + pass + return (paths, approvers) + + +# Does @path match @pattern? +# @pattern has the syntax defined in the Linux MAINTAINERS file -- mostly a +# shell glob pattern, except that a trailing slash means a directory and +# everything below. Matching can easily be done by converting to a regexp. +def match_pattern(path, pattern): + # Append a trailing slash if path is an existing directory, so that it + # matches F: entries such as 'foo/bar/' + if not path.endswith('/') and os.path.isdir(path): + path += '/' + rep = "^" + pattern + rep = rep.replace('*', '[^/]+') + rep = rep.replace('?', '[^/]') + if rep.endswith('/'): + rep += '.*' + rep += '$' + return not not re.match(rep, path) + + +def get_subsystems_for_path(subsystems, path, strict): + found = {} + for key in subsystems: + def inner(): + excluded = subsystems[key].get('X') + if excluded: + for pattern in excluded: + if match_pattern(path, pattern): + return # next key + included = subsystems[key].get('F') + if not included: + return # next key + for pattern in included: + if match_pattern(path, pattern): + found[key] = subsystems[key] + inner() + if strict and len(found) > 1: + found.pop('THE REST', None) + return found + + +def get_ss_maintainers(subsys): + return subsys.get('M') or [] + + +def get_ss_reviewers(subsys): + return subsys.get('R') or [] + + +def get_ss_approvers(ss): + return get_ss_maintainers(ss) + get_ss_reviewers(ss) + + +def get_ss_lists(subsys): + return subsys.get('L') or [] + + +def approvers_have_approved(approved_by, approvers): + for n in approvers: + # Ignore anything after the email (Github ID...) + n = n.split('>', 1)[0] + for m in approved_by: + m = m.split('>', 1)[0] + if n == m: + return True + return False + + +def download(pr): + url = "https://github.com/OP-TEE/optee_os/pull/{}.patch".format(pr) + f = tempfile.NamedTemporaryFile(mode="wb", prefix="pr{}_".format(pr), + suffix=".patch", delete=False) + print("Downloading {}...".format(url), end='', flush=True) + f.write(urlopen(url).read()) + print(" Done.") + return f.name + + +def show_release_to(subsystems): + check_cwd() + with open("MAINTAINERS", "r") as f: + emails = sorted(set(re.findall(r'[RM]:\t(.*[\w]*<[\w\.-]+@[\w\.-]+>)', + f.read()))) + emails += get_ss_lists(subsystems["THE REST"]) + print(*emails, sep=', ') + + +def main(): + global args + + args = get_args() + + all_subsystems = parse_maintainers() + + if args.release_to: + show_release_to(all_subsystems) + return + + paths = [] + arglist = [] + downloads = [] + split_patches = [] + + for pr in args.github_pr or []: + downloads += [download(pr)] + + for arg in args.arg + downloads: + if os.path.exists(arg): + patches = split_patchset(arg) + if patches: + split_patches += patches + continue + arglist.append(arg) + + for arg in arglist + split_patches: + patch_paths = [] + approved_by = [] + if os.path.exists(arg): + # Try to parse as a patch + (patch_paths, approved_by) = get_paths_from_patch(arg) + if not patch_paths: + # Not a patch, consider the path itself + # as_posix() cleans the path a little bit (suppress leading ./ and + # duplicate slashes...) + patch_paths = [PurePath(arg).as_posix()] + for path in patch_paths: + approved = False + if args.merge_check: + ss_for_path = get_subsystems_for_path(all_subsystems, path, + args.strict) + for key in ss_for_path: + ss_approvers = get_ss_approvers(ss_for_path[key]) + if approvers_have_approved(approved_by, ss_approvers): + approved = True + if not approved: + paths += [path] + + for f in downloads + split_patches: + os.remove(f) + + if args.file: + paths += args.file + + if (args.show_paths): + print(paths) + + ss = {} + for path in paths: + ss.update(get_subsystems_for_path(all_subsystems, path, args.strict)) + for key in ss: + ss_name = key[:50] + (key[50:] and '...') + for name in ss[key].get('M') or []: + print("{} (maintainer:{})".format(name, ss_name)) + for name in ss[key].get('R') or []: + print("{} (reviewer:{})".format(name, ss_name)) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/mem_usage.py b/optee/optee_os/scripts/mem_usage.py new file mode 100755 index 0000000..e4c4c97 --- /dev/null +++ b/optee/optee_os/scripts/mem_usage.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2014-2017, Linaro Limited +# +# SPDX-License-Identifier: BSD-3-Clause + +import argparse +import os +import subprocess +import sys + + +def get_args(): + parser = argparse.ArgumentParser(description='Shows the memory usage ' + 'of an OP-TEE based on ELF sections') + parser.add_argument('tee_elf', help='the OP-TEE ELF file (tee.elf)') + parser.add_argument('-a', '--all', action='store_true', + help=' same as -i -p -u -U') + parser.add_argument('-n', '--no-map', action='store_true', + help=' do not show the detailed section mappings and ' + 'RAM usage') + parser.add_argument('-i', '--init', action='store_true', + help='report the total size of the .*_init sections') + parser.add_argument('-p', '--paged', action='store_true', + help='report the total size of the .*_pageable ' + 'sections') + parser.add_argument('-u', '--unpaged', action='store_true', + help='report the total size of the unpaged sections, ' + 'that is, all sections but the ones in --init or ' + '--paged') + parser.add_argument('-U', '--unpaged-no-heap', action='store_true', + help='report the size of all unpaged sections ' + 'excluding heap space. Reflects the size of unpaged ' + 'code and data (.text, .rodata, .data, .bss, .nozi ' + 'and possibly unwind tables)') + parser.add_argument('-r', '--raw', action='store_true', + help='when processing -i, -p, -u, or -U, show only ' + 'the size (in decimal) and no other text') + return parser.parse_args() + + +def printf(format, *args): + sys.stdout.write(format % args) + + +def print_sect(name, addr, size, round_up=False, print_num_pages=False): + if args.no_map: + return + if size == 0: + size_kib = 0 + num_pages = 0 + else: + if round_up: + size_kib = (size - 1) / 1024 + 1 + else: + size_kib = size / 1024 + num_pages = (size - 1) / 4096 + 1 + + printf('%-16s %.8X - %.8X size %.8X %3d KiB', name, addr, addr + size, + size, size_kib) + if print_num_pages: + printf(' %d pages', num_pages) + printf('\n') + + +def print_pager_stat(name, size): + size_kib = size / 1024 + if args.raw: + printf('%d ', size) + else: + printf('%-36s size %.8X %3d KiB\n', name, size, size_kib) + + +def readelf_cmd(): + return os.getenv('CROSS_COMPILE', '') + 'readelf' + + +def main(): + global args + + in_shdr = False + sects = [] + init_size = 0 + paged_size = 0 + unpaged_size = 0 + unpaged_no_heap_size = 0 + + args = get_args() + env = os.environ.copy() + env['LC_ALL'] = 'C' + readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-s', + args.tee_elf], + stdout=subprocess.PIPE, env=env, + universal_newlines=True) + for line in iter(readelf.stdout.readline, ''): + words = line.split() + if len(words) == 8 and words[7] == '_end_of_ram': + end_of_ram = int(words[1], 16) + break + readelf.terminate() + readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-S', '-W', + args.tee_elf], + stdout=subprocess.PIPE, env=env, + universal_newlines=True) + for line in iter(readelf.stdout.readline, ''): + if 'Section Headers:' in line: + in_shdr = True + continue + if 'Key to Flags:' in line: + in_shdr = False + continue + if in_shdr: + words = line.split() + if words[0] == '[': + words.pop(0) + try: + (_, name, _, addr, offs, size, _, + flags) = words[:8] + except BaseException: + continue + if ('A' in flags): + sects.append({'name': name, 'addr': addr, + 'offs': offs, 'size': size}) + first_addr = None + for sect in sects: + if sect['addr'] != 0: + addr = sect['addr'] + if not first_addr: + first_addr = addr + if int(addr, 16) >= end_of_ram: + break + last_addr = addr + last_size = sect['size'] + + ram_usage = int(last_addr, 16) + int(last_size, 16) - int(first_addr, 16) + print_sect('RAM Usage', int(first_addr, 16), ram_usage, True, True) + + last_addr = 0 + last_size = 0 + for sect in sects: + name = sect['name'] + addr = int(sect['addr'], 16) + size = int(sect['size'], 16) + + if addr >= end_of_ram: + break + if last_addr != 0 and addr != last_addr + last_size: + print_sect('*hole*', last_addr + last_size, + addr - (last_addr + last_size)) + print_sect(name, addr, size) + if name.endswith('_init'): + init_size += size + elif name.endswith('_pageable'): + paged_size += size + else: + if not name.startswith('.heap'): + unpaged_no_heap_size += size + unpaged_size += size + last_addr = addr + last_size = size + + if args.all or args.init: + print_pager_stat('Init sections (.*_init)', init_size) + if args.all or args.paged: + print_pager_stat('Paged sections (.*_pageable)', paged_size) + if args.all or args.unpaged: + print_pager_stat('Unpaged sections ', unpaged_size) + if args.all or args.unpaged_no_heap: + print_pager_stat('Unpaged sections (heap excluded)', + unpaged_no_heap_size) + if (args.raw and (args.all or args.init or args.paged or + args.unpaged or args.unpaged_no_heap)): + printf('\n') + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/pem_to_pub_c.py b/optee/optee_os/scripts/pem_to_pub_c.py new file mode 100755 index 0000000..dbdf2c4 --- /dev/null +++ b/optee/optee_os/scripts/pem_to_pub_c.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2015, Linaro Limited + + +def get_args(): + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument( + '--prefix', required=True, + help='Prefix for the public key exponent and modulus in c file') + parser.add_argument( + '--out', required=True, + help='Name of c file for the public key') + parser.add_argument('--key', required=True, help='Name of key file') + + return parser.parse_args() + + +def main(): + import array + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import serialization + from cryptography.hazmat.primitives.asymmetric import rsa + + args = get_args() + + with open(args.key, 'rb') as f: + data = f.read() + + try: + key = serialization.load_pem_private_key(data, password=None, + backend=default_backend()) + key = key.public_key() + except ValueError: + key = serialization.load_pem_public_key(data, + backend=default_backend()) + + # Refuse public exponent with more than 32 bits. Otherwise the C + # compiler may simply truncate the value and proceed. + # This will lead to TAs seemingly having invalid signatures with a + # possible security issue for any e = k*2^32 + 1 (for any integer k). + if key.public_numbers().e > 0xffffffff: + raise ValueError( + 'Unsupported large public exponent detected. ' + + 'OP-TEE handles only public exponents up to 2^32 - 1.') + + with open(args.out, 'w') as f: + f.write("#include \n") + f.write("#include \n\n") + f.write("const uint32_t " + args.prefix + "_exponent = " + + str(key.public_numbers().e) + ";\n\n") + f.write("const uint8_t " + args.prefix + "_modulus[] = {\n") + i = 0 + nbuf = key.public_numbers().n.to_bytes(key.key_size >> 3, 'big') + for x in array.array("B", nbuf): + f.write("0x" + '{0:02x}'.format(x) + ",") + i = i + 1 + if i % 8 == 0: + f.write("\n") + else: + f.write(" ") + f.write("};\n") + f.write("const size_t " + args.prefix + "_modulus_size = sizeof(" + + args.prefix + "_modulus);\n") + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/print_tee_hash.py b/optee/optee_os/scripts/print_tee_hash.py new file mode 100755 index 0000000..7b4aac1 --- /dev/null +++ b/optee/optee_os/scripts/print_tee_hash.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2021, Huawei Technologies Co., Ltd +# + +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection +import codecs +import sys + +verbose = False + + +def dump(buf): + print(codecs.encode(buf, 'hex').decode('utf-8')) + + +def resolve_symbol(elf, name): + for section in elf.iter_sections(): + if isinstance(section, SymbolTableSection): + for symbol in section.iter_symbols(): + if symbol.name == name: + return symbol.entry['st_value'] + raise RuntimeError(f'Symbol {name} not found') + + +def hash_range(h, elf, start, end): + global verbose + start_addr = resolve_symbol(elf, start) + end_addr = resolve_symbol(elf, end) + size = end_addr - start_addr + if verbose: + print(f'[{start}(0x{start_addr:x}), {end}(0x{end_addr:x})]: ' + f'{size} bytes') + for segment in elf.iter_segments(): + if (segment['p_type'] == 'PT_LOAD' and + segment['p_vaddr'] <= start_addr and + end_addr <= segment['p_vaddr'] + segment['p_filesz']): + begin_offs = start_addr - segment['p_vaddr'] + h.update(segment.data()[begin_offs:begin_offs + size]) + + +def hash_section(h, elf, name): + global verbose + s = elf.get_section_by_name(name) + if s is None: + return + d = s.data() + if verbose: + print(f'{name}: {len(d)} bytes') + h.update(d) + + +def main(): + global verbose + argc = len(sys.argv) + if argc != 2 and argc != 3: + print('Usage:', sys.argv[0], '') + return 1 + + if argc == 3 and sys.argv[1] == '-v': + verbose = True + + with open(sys.argv[argc - 1], 'rb') as f: + elf = ELFFile(f) + h = hashes.Hash(hashes.SHA256(), default_backend()) + hash_range(h, elf, '__text_start', '__text_data_start') + hash_range(h, elf, '__text_data_end', '__text_end') + hash_section(h, elf, '.text_init') + hash_section(h, elf, '.text_pageable') + hash_section(h, elf, '.rodata') + hash_section(h, elf, '.rodata_init') + hash_section(h, elf, '.rodata_pageable') + dump(h.finalize()) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/sign_encrypt.py b/optee/optee_os/scripts/sign_encrypt.py new file mode 100755 index 0000000..435d63b --- /dev/null +++ b/optee/optee_os/scripts/sign_encrypt.py @@ -0,0 +1,968 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2015, 2017, 2019, Linaro Limited +# + +import sys +import math + + +sig_tee_alg = {'TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256': 0x70414930, + 'TEE_ALG_RSASSA_PKCS1_V1_5_SHA256': 0x70004830} + +enc_tee_alg = {'TEE_ALG_AES_GCM': 0x40000810} + +enc_key_type = {'SHDR_ENC_KEY_DEV_SPECIFIC': 0x0, + 'SHDR_ENC_KEY_CLASS_WIDE': 0x1} + +TEE_ATTR_RSA_MODULUS = 0xD0000130 +TEE_ATTR_RSA_PUBLIC_EXPONENT = 0xD0000230 + +SHDR_BOOTSTRAP_TA = 1 +SHDR_ENCRYPTED_TA = 2 +SHDR_SUBKEY = 3 +SHDR_MAGIC = 0x4f545348 +SHDR_SIZE = 20 +SK_HDR_SIZE = 20 +EHDR_SIZE = 12 +UUID_SIZE = 16 +# Use 12 bytes for nonce per recommendation +NONCE_SIZE = 12 +TAG_SIZE = 16 + + +def value_to_key(db, val): + for k, v in db.items(): + if v == val: + return k + + +def uuid_v5_sha512(namespace_bytes, name): + from cryptography.hazmat.primitives import hashes + from uuid import UUID + + h = hashes.Hash(hashes.SHA512()) + h.update(namespace_bytes + bytes(name, 'utf-8')) + digest = h.finalize() + return UUID(bytes=digest[:16], version=5) + + +def name_img_to_str(name_img): + return name_img.decode().split('\x00', 1)[0] + + +def uuid_parse(s): + from uuid import UUID + return UUID(s) + + +def int_parse(str): + return int(str, 0) + + +def get_args(): + import argparse + import textwrap + + class OnlyOne(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + a = self.dest + '_assigned' + if getattr(namespace, a, False): + raise argparse.ArgumentError(self, 'Can only be given once') + setattr(namespace, a, True) + setattr(namespace, self.dest, values) + + def arg_add_uuid(parser): + parser.add_argument( + '--uuid', required=True, type=uuid_parse, + help='String UUID of the TA') + + def arg_add_key(parser): + parser.add_argument( + '--key', required=True, help=''' + Name of signing and verification key file (PEM format) or an + Amazon Resource Name (arn:) of an AWS KMS asymmetric key. + At least public key for the commands digest, stitch, and + verify, else a private key''') + + def arg_add_enc_key(parser): + parser.add_argument( + '--enc-key', required=False, help='Encryption key string') + + def arg_add_enc_key_type(parser): + parser.add_argument( + '--enc-key-type', required=False, + default='SHDR_ENC_KEY_DEV_SPECIFIC', + choices=list(enc_key_type.keys()), help=''' + Encryption key type, + Defaults to SHDR_ENC_KEY_DEV_SPECIFIC.''') + + def arg_add_ta_version(parser): + parser.add_argument( + '--ta-version', required=False, type=int_parse, default=0, help=''' + TA version stored as a 32-bit unsigned integer and used for + rollback protection of TA install in the secure database. + Defaults to 0.''') + + def arg_add_sig(parser): + parser.add_argument( + '--sig', required=True, dest='sigf', + help='Name of signature input file, defaults to .sig') + + def arg_add_dig(parser): + parser.add_argument( + '--dig', required=True, dest='digf', + help='Name of digest output file, defaults to .dig') + + def arg_add_in(parser): + parser.add_argument( + '--in', required=False, dest='inf', help=''' + Name of application input file, defaults to + .stripped.elf''') + + def arg_add_out(parser): + parser.add_argument( + '--out', required=True, dest='outf', + help='Name of application output file, defaults to .ta') + + def arg_add_algo(parser): + parser.add_argument( + '--algo', required=False, choices=list(sig_tee_alg.keys()), + default='TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256', help=''' + The hash and signature algorithm. + Defaults to TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256.''') + + def arg_add_subkey(parser): + parser.add_argument( + '--subkey', action=OnlyOne, help='Name of subkey input file') + + def arg_add_name(parser): + parser.add_argument('--name', + help='Input name for subspace of a subkey') + + def arg_add_subkey_uuid_in(parser): + parser.add_argument( + '--in', required=True, dest='inf', + help='Name of subkey input file') + + def arg_add_max_depth(parser): + parser.add_argument( + '--max-depth', required=False, type=int_parse, help=''' + Max depth of subkeys below this subkey''') + + def arg_add_name_size(parser): + parser.add_argument( + '--name-size', required=True, type=int_parse, help=''' + Size of (unsigned) input name for subspace of a subkey. + Set to 0 to create an identity subkey (a subkey having + the same UUID as the next subkey or TA)''') + + def arg_add_subkey_version(parser): + parser.add_argument( + '--subkey-version', required=False, type=int_parse, default=0, + help='Subkey version used for rollback protection') + + def arg_add_subkey_in(parser): + parser.add_argument( + '--in', required=True, dest='inf', help=''' + Name of PEM file with the public key of the new subkey''') + + def arg_add_subkey_out(parser): + parser.add_argument( + '--out', required=True, dest='outf', + help='Name of subkey output file') + + def get_outf_default(parsed): + return str(parsed.uuid) + '.ta' + + def get_inf_default(parsed): + return str(parsed.uuid) + '.stripped.elf' + + def get_sigf_default(parsed): + return str(parsed.uuid) + '.sig' + + def get_digf_default(parsed): + return str(parsed.uuid) + '.dig' + + def assign_default_value(parsed, attr, func): + if hasattr(parsed, attr) and getattr(parsed, attr) is None: + setattr(parsed, attr, func(parsed)) + + parser = argparse.ArgumentParser( + description='Sign and encrypt (optional) a Trusted Application ' + + ' for OP-TEE.', + usage='%(prog)s ...', + epilog=' -h for detailed help') + subparsers = parser.add_subparsers( + title='valid commands, with possible aliases in ()', + dest='command', metavar='') + + parser_sign_enc = subparsers.add_parser( + 'sign-enc', prog=parser.prog + ' sign-enc', + help='Generate signed and optionally encrypted loadable TA image file') + parser_sign_enc.set_defaults(func=command_sign_enc) + arg_add_uuid(parser_sign_enc) + arg_add_ta_version(parser_sign_enc) + arg_add_in(parser_sign_enc) + arg_add_out(parser_sign_enc) + arg_add_key(parser_sign_enc) + arg_add_subkey(parser_sign_enc) + arg_add_name(parser_sign_enc) + arg_add_enc_key(parser_sign_enc) + arg_add_enc_key_type(parser_sign_enc) + arg_add_algo(parser_sign_enc) + + parser_digest = subparsers.add_parser( + 'digest', aliases=['generate-digest'], prog=parser.prog + ' digest', + formatter_class=argparse.RawDescriptionHelpFormatter, + help='Generate loadable TA binary image digest for offline signing', + epilog=textwrap.dedent('''\ + example offline signing command using OpenSSL for algorithm + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + base64 -d .dig | \\ + openssl pkeyutl -sign -inkey .pem \\ + -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pss \\ + -pkeyopt rsa_pss_saltlen:digest \\ + -pkeyopt rsa_mgf1_md:sha256 | \\ + base64 > .sig + + example offline signing command using OpenSSL for algorithm + TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + base64 -d .dig | \\ + openssl pkeyutl -sign -inkey .pem \\ + -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pkcs1 | \\ + base64 > .sig + ''')) + parser_digest.set_defaults(func=command_digest) + arg_add_uuid(parser_digest) + arg_add_ta_version(parser_digest) + arg_add_in(parser_digest) + arg_add_key(parser_digest) + arg_add_enc_key(parser_digest) + arg_add_enc_key_type(parser_digest) + arg_add_algo(parser_digest) + arg_add_dig(parser_digest) + + parser_stitch = subparsers.add_parser( + 'stitch', aliases=['stitch-ta'], prog=parser.prog + ' stich', + help='Generate loadable signed and encrypted TA binary image file' + + ' from TA raw image and its signature') + parser_stitch.set_defaults(func=command_stitch) + arg_add_uuid(parser_stitch) + arg_add_ta_version(parser_stitch) + arg_add_in(parser_stitch) + arg_add_key(parser_stitch) + arg_add_out(parser_stitch) + arg_add_enc_key(parser_stitch) + arg_add_enc_key_type(parser_stitch) + arg_add_algo(parser_stitch) + arg_add_sig(parser_stitch) + + parser_verify = subparsers.add_parser( + 'verify', prog=parser.prog + ' verify', + help='Verify signed TA binary') + parser_verify.set_defaults(func=command_verify) + arg_add_uuid(parser_verify) + arg_add_in(parser_verify) + arg_add_key(parser_verify) + + parser_display = subparsers.add_parser( + 'display', prog=parser.prog + ' display', + help='Parses and displays a signed TA binary') + parser_display.set_defaults(func=command_display) + arg_add_in(parser_display) + + parser_subkey_uuid = subparsers.add_parser( + 'subkey-uuid', prog=parser.prog + ' subkey-uuid', + help='calculate the UUID of next TA or subkey') + parser_subkey_uuid.set_defaults(func=command_subkey_uuid) + arg_add_subkey_uuid_in(parser_subkey_uuid) + arg_add_name(parser_subkey_uuid) + + parser_sign_subkey = subparsers.add_parser( + 'sign-subkey', prog=parser.prog + ' sign-subkey', + help='Sign a subkey') + parser_sign_subkey.set_defaults(func=command_sign_subkey) + arg_add_name(parser_sign_subkey) + arg_add_subkey_in(parser_sign_subkey) + arg_add_uuid(parser_sign_subkey) + arg_add_key(parser_sign_subkey) + arg_add_subkey_out(parser_sign_subkey) + arg_add_max_depth(parser_sign_subkey) + arg_add_name_size(parser_sign_subkey) + arg_add_subkey(parser_sign_subkey) + arg_add_subkey_version(parser_sign_subkey) + arg_add_algo(parser_sign_subkey) + + argv = sys.argv[1:] + if (len(argv) > 0 and argv[0][0] == '-' and + argv[0] != '-h' and argv[0] != '--help'): + # The default sub-command is 'sign-enc' so add it to the parser + # if one is missing + argv = ['sign-enc'] + argv + + parsed = parser.parse_args(argv) + + if parsed.command is None: + parser.print_help() + sys.exit(1) + + # Set a few defaults if defined for the current command + assign_default_value(parsed, 'inf', get_inf_default) + assign_default_value(parsed, 'outf', get_outf_default) + assign_default_value(parsed, 'sigf', get_sigf_default) + assign_default_value(parsed, 'digf', get_digf_default) + + return parsed + + +def load_asymmetric_key_img(data): + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives.serialization import ( + load_pem_private_key, load_pem_public_key) + + try: + return load_pem_private_key(data, password=None, + backend=default_backend()) + except ValueError: + return load_pem_public_key(data, backend=default_backend()) + + +def load_asymmetric_key(arg_key): + if arg_key.startswith('arn:'): + from sign_helper_kms import _RSAPrivateKeyInKMS + return _RSAPrivateKeyInKMS(arg_key) + else: + with open(arg_key, 'rb') as f: + return load_asymmetric_key_img(f.read()) + + +class BinaryImage: + def __init__(self, arg_inf, arg_key): + from cryptography.hazmat.primitives import hashes + + # Exactly what inf is holding isn't determined a this stage + if isinstance(arg_inf, str): + with open(arg_inf, 'rb') as f: + self.inf = f.read() + else: + self.inf = arg_inf + + if arg_key is None: + self.key = None + else: + if isinstance(arg_key, str): + self.key = load_asymmetric_key(arg_key) + else: + self.key = arg_key + self.sig_size = math.ceil(self.key.key_size / 8) + + self.chosen_hash = hashes.SHA256() + self.hash_size = self.chosen_hash.digest_size + + def __pack_img(self, img_type, sign_algo): + import struct + + self.sig_algo = sign_algo + self.img_type = img_type + self.shdr = struct.pack('= getattr(self, 'previous_max_depth')): + logger.error('Max depth of previous subkey is {} ' + .format(self.previous_max_depth) + + 'and the next value must be smaller') + sys.exit(1) + + def int_to_bytes(x: int) -> bytes: + return x.to_bytes((x.bit_length() + 8) // 8, 'big') + + n_bytes = int_to_bytes(subkey_pkey.public_numbers().n) + e_bytes = int_to_bytes(subkey_pkey.public_numbers().e) + attrs_end_offs = 16 + 5 * 4 + 2 * 3 * 4 + shdr_subkey = struct.pack(' 0: + # name_size is the previous subkey header + name_img = self.inf[offs:offs + name_size] + print(' next name: "{}"'.format(name_img_to_str(name_img))) + offs += name_size + print('Next header at offset: {} (0x{:x})' + .format(offs, offs)) + + shdr = self.inf[offs:offs + SHDR_SIZE] + [magic, img_type, img_size, algo_value, hash_size, + sig_size] = struct.unpack(' 0: + sk_image = BinaryImage(sk_image.next_inf, None) + sk_image.parse() + + if name is None: + name = '' + self.previous_max_depth = sk_image.max_depth + self.name_img = str.encode(name).ljust(sk_image.name_size, b'\0') + + def write(self, outf): + with open(outf, 'wb') as f: + if hasattr(self, 'subkey_img'): + f.write(self.subkey_img) + f.write(self.name_img) + f.write(self.shdr) + f.write(self.img_digest) + f.write(self.sig) + if hasattr(self, 'ta_uuid'): + f.write(self.ta_uuid) + f.write(self.ta_version) + if hasattr(self, 'ehdr'): + f.write(self.ehdr) + f.write(self.nonce) + f.write(self.tag) + f.write(self.ciphertext) + else: + f.write(self.img) + + +def load_ta_image(args): + ta_image = BinaryImage(args.inf, args.key) + + if args.enc_key: + ta_image.encrypt_ta(args.enc_key, args.enc_key_type, + args.algo, args.uuid, args.ta_version) + else: + ta_image.set_bootstrap_ta(args.algo, args.uuid, args.ta_version) + + return ta_image + + +def command_sign_enc(args): + ta_image = load_ta_image(args) + if args.subkey: + ta_image.add_subkey(args.subkey, args.name) + ta_image.sign() + ta_image.write(args.outf) + logger.info('Successfully signed application.') + + +def command_sign_subkey(args): + image = BinaryImage(args.inf, args.key) + if args.subkey: + image.add_subkey(args.subkey, args.name) + image.set_subkey(args.algo, args.name, args.uuid, args.subkey_version, + args.max_depth, args.name_size) + image.sign() + image.write(args.outf) + logger.info('Successfully signed subkey.') + + +def command_digest(args): + import base64 + + ta_image = load_ta_image(args) + with open(args.digf, 'wb+') as digfile: + digfile.write(base64.b64encode(ta_image.img_digest)) + + +def command_stitch(args): + ta_image = load_ta_image(args) + ta_image.add_signature(args.sigf) + ta_image.verify_signature() + ta_image.write(args.outf) + logger.info('Successfully applied signature.') + + +def command_verify(args): + import uuid + + image = BinaryImage(args.inf, args.key) + next_uuid = None + max_depth = -1 + while True: + image.parse() + if hasattr(image, 'subkey_hdr'): # Subkey + print('Subkey UUID: {}'.format(uuid.UUID(bytes=image.uuid))) + image.verify_signature() + image.verify_digest() + if next_uuid: + if uuid.UUID(bytes=image.uuid) != next_uuid: + raise Exception('UUID {} does not match {}' + .format(uuid.UUID(bytes=image.uuid), + next_uuid)) + if max_depth >= 0: + if image.max_depth < 0 or image.max_depth >= max_depth: + raise Exception('Invalid max_depth {} not less than {}' + .format(image.max_depth, max_depth)) + max_depth = image.max_depth + if len(image.next_inf) == 0: + logger.info('Subkey is correctly verified.') + return + if image.name_size > 0: + next_uuid = uuid_v5_sha512(image.uuid, + name_img_to_str(image.name_img)) + else: + next_uuid = image.uuid + image = BinaryImage(image.next_inf, image.subkey_key) + else: # TA + print('TA UUID: {}'.format(uuid.UUID(bytes=image.ta_uuid))) + if next_uuid: + if uuid.UUID(bytes=image.ta_uuid) != next_uuid: + raise Exception('UUID {} does not match {}' + .format(uuid.UUID(bytes=image.ta_uuid), + next_uuid)) + if hasattr(image, 'ciphertext'): + if args.enc_key is None: + logger.error('--enc_key needed to decrypt TA') + sys.exit(1) + image.decrypt_ta(args.enc_key) + image.verify_signature() + image.verify_digest() + image.verify_uuid(args.uuid) + logger.info('Trusted application is correctly verified.') + return + + +def command_display(args): + ta_image = BinaryImage(args.inf, None) + ta_image.display() + + +def command_subkey_uuid(args): + import uuid + + sk_image = BinaryImage(args.inf, None) + sk_image.parse() + if not hasattr(sk_image, 'next_inf'): + logger.error('Invalid subkey file') + sys.exit(1) + print('Subkey UUID: {}'.format(uuid.UUID(bytes=sk_image.uuid))) + while len(sk_image.next_inf) > 0: + sk_image = BinaryImage(sk_image.next_inf, None) + sk_image.parse() + print('Subkey UUID: {}'.format(uuid.UUID(bytes=sk_image.uuid))) + if args.name: + if len(args.name) > sk_image.name_size: + logger.error('Length of name ({}) '.format(len(args.name)) + + 'is larger than max name size ({})' + .format(sk_image.name_size)) + sys.exit(1) + print('Next subkey UUID: {}' + .format(uuid_v5_sha512(sk_image.uuid, args.name))) + else: + print('Next subkey UUID unchanged: {}' + .format(uuid.UUID(bytes=sk_image.uuid))) + + +def main(): + import logging + import os + + global logger + logging.basicConfig() + logger = logging.getLogger(os.path.basename(__file__)) + + args = get_args() + args.func(args) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/sign_helper_kms.py b/optee/optee_os/scripts/sign_helper_kms.py new file mode 100755 index 0000000..115795f --- /dev/null +++ b/optee/optee_os/scripts/sign_helper_kms.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright Amazon.com Inc. or its affiliates +# +import typing + +import boto3 + +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ( + AsymmetricSignatureContext, + utils as asym_utils, +) +from cryptography.hazmat.primitives.asymmetric.padding import ( + AsymmetricPadding, + PKCS1v15, + PSS, +) +from cryptography.hazmat.primitives.asymmetric.rsa import ( + RSAPrivateKey, + RSAPrivateNumbers, + RSAPublicKey, +) + + +class _RSAPrivateKeyInKMS(RSAPrivateKey): + + def __init__(self, arn): + self.arn = arn + self.client = boto3.client('kms') + response = self.client.get_public_key(KeyId=self.arn) + + # Parse public key + self.public_key = serialization.load_der_public_key( + response['PublicKey']) + + @property + def key_size(self): + return self.public_key.key_size + + def public_key(self) -> RSAPublicKey: + return self.public_key + + def sign(self, data: bytes, padding: AsymmetricPadding, + algorithm: typing.Union[asym_utils.Prehashed, + hashes.HashAlgorithm] + ) -> bytes: + if isinstance(algorithm, asym_utils.Prehashed): + message_type = 'DIGEST' + else: + message_type = 'RAW' + + if isinstance(padding, PSS): + signing_alg = 'RSASSA_PSS_' + elif isinstance(padding, PKCS1v15): + signing_alg = 'RSASSA_PKCS1_V1_5_' + else: + raise TypeError("Unsupported padding") + + if (isinstance(algorithm._algorithm, hashes.SHA256) or + isinstance(algorithm, hashes.SHA256)): + signing_alg += 'SHA_256' + elif (isinstance(algorithm._algorithm, hashes.SHA384) or + isinstance(algorithm, hashes.SHA384)): + signing_alg += 'SHA_384' + elif (isinstance(algorithm._algorithm, hashes.SHA512) or + isinstance(algorithm, hashes.SHA512)): + signing_alg += 'SHA_512' + else: + raise TypeError("Unsupported hashing algorithm") + + response = self.client.sign( + KeyId=self.arn, Message=data, + MessageType=message_type, + SigningAlgorithm=signing_alg) + + return response['Signature'] + + # No need to implement these functions so we raise an exception + def signer( + self, padding: AsymmetricPadding, algorithm: hashes.HashAlgorithm + ) -> AsymmetricSignatureContext: + raise NotImplementedError + + def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: + raise NotImplementedError + + def private_numbers(self) -> RSAPrivateNumbers: + raise NotImplementedError + + def private_bytes( + self, + encoding: serialization.Encoding, + format: serialization.PrivateFormat, + encryption_algorithm: serialization.KeySerializationEncryption + ) -> bytes: + raise NotImplementedError diff --git a/optee/optee_os/scripts/symbolize.py b/optee/optee_os/scripts/symbolize.py new file mode 100755 index 0000000..998bada --- /dev/null +++ b/optee/optee_os/scripts/symbolize.py @@ -0,0 +1,568 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2017, Linaro Limited +# + + +import argparse +import errno +import glob +import os +import re +import subprocess +import sys +import termios + +CALL_STACK_RE = re.compile('Call stack:') +TEE_LOAD_ADDR_RE = re.compile(r'TEE load address @ (?P0x[0-9a-f]+)') +# This gets the address from lines looking like this: +# E/TC:0 0x001044a8 +STACK_ADDR_RE = re.compile( + r'[UEIDFM]/(TC|LD):(\?*|[0-9]*) [0-9]* +(?P0x[0-9a-f]+)') +ABORT_ADDR_RE = re.compile(r'-abort at address (?P0x[0-9a-f]+)') +TA_PANIC_RE = re.compile(r'TA panicked with code (?P0x[0-9a-f]+)') +REGION_RE = re.compile(r'region +[0-9]+: va (?P0x[0-9a-f]+) ' + r'pa 0x[0-9a-f]+ size (?P0x[0-9a-f]+)' + r'( flags .{4} (\[(?P[0-9]+)\])?)?') +ELF_LIST_RE = re.compile(r'\[(?P[0-9]+)\] (?P[0-9a-f\-]+)' + r' @ (?P0x[0-9a-f\-]+)') +FUNC_GRAPH_RE = re.compile(r'Function graph') +GRAPH_ADDR_RE = re.compile(r'(?P0x[0-9a-f]+)') +GRAPH_RE = re.compile(r'}') + +epilog = ''' +This scripts reads an OP-TEE abort or panic message from stdin and adds debug +information to the output, such as ' at :' next to each +address in the call stack. Any message generated by OP-TEE and containing a +call stack can in principle be processed by this script. This currently +includes aborts and panics from the TEE core as well as from any TA. +The paths provided on the command line are used to locate the appropriate ELF +binary (tee.elf or Trusted Application). The GNU binutils (addr2line, objdump, +nm) are used to extract the debug info. If the CROSS_COMPILE environment +variable is set, it is used as a prefix to the binutils tools. That is, the +script will invoke $(CROSS_COMPILE)addr2line etc. If it is not set however, +the prefix will be determined automatically for each ELF file based on its +architecture (arm-linux-gnueabihf-, aarch64-linux-gnu-). The resulting command +is then expected to be found in the user's PATH. + +OP-TEE abort and panic messages are sent to the secure console. They look like +the following: + + E/TC:0 User TA data-abort at address 0xffffdecd (alignment fault) + ... + E/TC:0 Call stack: + E/TC:0 0x4000549e + E/TC:0 0x40001f4b + E/TC:0 0x4000273f + E/TC:0 0x40005da7 + +Inspired by a script of the same name by the Chromium project. + +Sample usage: + + $ scripts/symbolize.py -d out/arm-plat-hikey/core -d ../optee_test/out/ta/* + + ^D + +Also, this script reads function graph generated for OP-TEE user TA from +/tmp/ftrace-.out file and resolves function addresses to corresponding +symbols. + +Sample usage: + + $ cat /tmp/ftrace-.out | scripts/symbolize.py -d .elf + + ^D +''' + +tee_result_names = { + '0xf0100001': 'TEE_ERROR_CORRUPT_OBJECT', + '0xf0100002': 'TEE_ERROR_CORRUPT_OBJECT_2', + '0xf0100003': 'TEE_ERROR_STORAGE_NOT_AVAILABLE', + '0xf0100004': 'TEE_ERROR_STORAGE_NOT_AVAILABLE_2', + '0xf0100006': 'TEE_ERROR_CIPHERTEXT_INVALID ', + '0xffff0000': 'TEE_ERROR_GENERIC', + '0xffff0001': 'TEE_ERROR_ACCESS_DENIED', + '0xffff0002': 'TEE_ERROR_CANCEL', + '0xffff0003': 'TEE_ERROR_ACCESS_CONFLICT', + '0xffff0004': 'TEE_ERROR_EXCESS_DATA', + '0xffff0005': 'TEE_ERROR_BAD_FORMAT', + '0xffff0006': 'TEE_ERROR_BAD_PARAMETERS', + '0xffff0007': 'TEE_ERROR_BAD_STATE', + '0xffff0008': 'TEE_ERROR_ITEM_NOT_FOUND', + '0xffff0009': 'TEE_ERROR_NOT_IMPLEMENTED', + '0xffff000a': 'TEE_ERROR_NOT_SUPPORTED', + '0xffff000b': 'TEE_ERROR_NO_DATA', + '0xffff000c': 'TEE_ERROR_OUT_OF_MEMORY', + '0xffff000d': 'TEE_ERROR_BUSY', + '0xffff000e': 'TEE_ERROR_COMMUNICATION', + '0xffff000f': 'TEE_ERROR_SECURITY', + '0xffff0010': 'TEE_ERROR_SHORT_BUFFER', + '0xffff0011': 'TEE_ERROR_EXTERNAL_CANCEL', + '0xffff300f': 'TEE_ERROR_OVERFLOW', + '0xffff3024': 'TEE_ERROR_TARGET_DEAD', + '0xffff3041': 'TEE_ERROR_STORAGE_NO_SPACE', + '0xffff3071': 'TEE_ERROR_MAC_INVALID', + '0xffff3072': 'TEE_ERROR_SIGNATURE_INVALID', + '0xffff5000': 'TEE_ERROR_TIME_NOT_SET', + '0xffff5001': 'TEE_ERROR_TIME_NEEDS_RESET', + } + + +def get_args(): + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='Symbolizes OP-TEE abort dumps or function graphs', + epilog=epilog) + parser.add_argument('-d', '--dir', action='append', nargs='+', + help='Search for ELF file in DIR. tee.elf is needed ' + 'to decode a TEE Core or pseudo-TA abort, while ' + '.elf is required if a user-mode TA has ' + 'crashed. For convenience, ELF files may also be ' + 'given.') + parser.add_argument('-s', '--strip_path', nargs='?', + help='Strip STRIP_PATH from file paths (default: ' + 'current directory, use -s with no argument to show ' + 'full paths)', default=os.getcwd()) + + return parser.parse_args() + + +class Symbolizer(object): + def __init__(self, out, dirs, strip_path): + self._out = out + self._dirs = dirs + self._strip_path = strip_path + self._addr2line = None + self.reset() + + def my_Popen(self, cmd): + try: + return subprocess.Popen(cmd, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + universal_newlines=True, + bufsize=1) + except OSError as e: + if e.errno == errno.ENOENT: + print("*** Error:{}: command not found".format(cmd[0]), + file=sys.stderr) + sys.exit(1) + + def get_elf(self, elf_or_uuid): + if not elf_or_uuid.endswith('.elf'): + elf_or_uuid += '.elf' + for d in self._dirs: + if d.endswith(elf_or_uuid) and os.path.isfile(d): + return d + elf = glob.glob(d + '/' + elf_or_uuid) + if elf: + return elf[0] + + def set_arch(self, elf): + self._arch = os.getenv('CROSS_COMPILE') + if self._arch: + return + p = subprocess.Popen(['file', '-L', elf], stdout=subprocess.PIPE) + output = p.stdout.readlines() + p.terminate() + if b'ARM aarch64,' in output[0]: + self._arch = 'aarch64-linux-gnu-' + elif b'ARM,' in output[0]: + self._arch = 'arm-linux-gnueabihf-' + + def arch_prefix(self, cmd, elf): + self.set_arch(elf) + if self._arch is None: + return '' + return self._arch + cmd + + def spawn_addr2line(self, elf_name): + if elf_name is None: + return + if self._addr2line_elf_name is elf_name: + return + if self._addr2line: + self._addr2line.terminate + self._addr2line = None + elf = self.get_elf(elf_name) + if not elf: + return + cmd = self.arch_prefix('addr2line', elf) + if not cmd: + return + self._addr2line = self.my_Popen([cmd, '-f', '-p', '-e', elf]) + self._addr2line_elf_name = elf_name + + # If addr falls into a region that maps a TA ELF file, return the load + # address of that file. + def elf_load_addr(self, addr): + if self._regions: + for r in self._regions: + r_addr = int(r[0], 16) + r_size = int(r[1], 16) + i_addr = int(addr, 16) + if (i_addr >= r_addr and i_addr < (r_addr + r_size)): + # Found region + elf_idx = r[2] + if elf_idx is not None: + return self._elfs[int(elf_idx)][1] + # In case address is not found in TA ELF file, fallback to tee.elf + # especially to symbolize mixed (user-space and kernel) addresses + # which is true when syscall ftrace is enabled along with TA + # ftrace. + return self._tee_load_addr + else: + # tee.elf + return self._tee_load_addr + + def elf_for_addr(self, addr): + l_addr = self.elf_load_addr(addr) + if l_addr == self._tee_load_addr: + return 'tee.elf' + for k in self._elfs: + e = self._elfs[k] + if int(e[1], 16) == int(l_addr, 16): + return e[0] + return None + + def subtract_load_addr(self, addr): + l_addr = self.elf_load_addr(addr) + if l_addr is None: + return None + if int(l_addr, 16) > int(addr, 16): + return '' + return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16)) + + def resolve(self, addr): + reladdr = self.subtract_load_addr(addr) + self.spawn_addr2line(self.elf_for_addr(addr)) + if not reladdr or not self._addr2line: + return '???' + if self.elf_for_addr(addr) == 'tee.elf': + reladdr = '0x{:x}'.format(int(reladdr, 16) + + int(self.first_vma('tee.elf'), 16)) + try: + print(reladdr, file=self._addr2line.stdin) + ret = self._addr2line.stdout.readline().rstrip('\n') + except IOError: + ret = '!!!' + return ret + + # Armv8.5 with Memory Tagging Extension (MTE) + def strip_armv85_mte_tag(self, addr): + i_addr = int(addr, 16) + i_addr &= ~(0xf << 56) + return '0x{:x}'.format(i_addr) + + def symbol_plus_offset(self, addr): + ret = '' + prevsize = 0 + addr = self.strip_armv85_mte_tag(addr) + reladdr = self.subtract_load_addr(addr) + elf_name = self.elf_for_addr(addr) + if elf_name is None: + return '' + elf = self.get_elf(elf_name) + cmd = self.arch_prefix('nm', elf) + if not reladdr or not elf or not cmd: + return '' + ireladdr = int(reladdr, 16) + nm = self.my_Popen([cmd, '--numeric-sort', '--print-size', elf]) + for line in iter(nm.stdout.readline, ''): + try: + addr, size, _, name = line.split() + except ValueError: + # Size is missing + try: + addr, _, name = line.split() + size = '0' + except ValueError: + # E.g., undefined (external) symbols (line = "U symbol") + continue + iaddr = int(addr, 16) + isize = int(size, 16) + if iaddr == ireladdr: + ret = name + break + if iaddr < ireladdr and iaddr + isize >= ireladdr: + offs = ireladdr - iaddr + ret = name + '+' + str(offs) + break + if iaddr > ireladdr and prevsize == 0: + offs = iaddr + ireladdr + ret = prevname + '+' + str(offs) + break + prevsize = size + prevname = name + nm.terminate() + return ret + + def section_plus_offset(self, addr): + ret = '' + reladdr = self.subtract_load_addr(addr) + elf_name = self.elf_for_addr(addr) + if elf_name is None: + return '' + elf = self.get_elf(elf_name) + cmd = self.arch_prefix('objdump', elf) + if not reladdr or not elf or not cmd: + return '' + iaddr = int(reladdr, 16) + objdump = self.my_Popen([cmd, '--section-headers', elf]) + for line in iter(objdump.stdout.readline, ''): + try: + idx, name, size, vma, lma, offs, algn = line.split() + except ValueError: + continue + ivma = int(vma, 16) + isize = int(size, 16) + if ivma == iaddr: + ret = name + break + if ivma < iaddr and ivma + isize >= iaddr: + offs = iaddr - ivma + ret = name + '+' + str(offs) + break + objdump.terminate() + return ret + + def process_abort(self, line): + ret = '' + match = re.search(ABORT_ADDR_RE, line) + addr = match.group('addr') + pre = match.start('addr') + post = match.end('addr') + sym = self.symbol_plus_offset(addr) + sec = self.section_plus_offset(addr) + if sym or sec: + ret += line[:pre] + ret += addr + if sym: + ret += ' ' + sym + if sec: + ret += ' ' + sec + ret += line[post:] + return ret + + # Return all ELF sections with the ALLOC flag + def read_sections(self, elf_name): + if elf_name is None: + return + if elf_name in self._sections: + return + elf = self.get_elf(elf_name) + if not elf: + return + cmd = self.arch_prefix('objdump', elf) + if not elf or not cmd: + return + self._sections[elf_name] = [] + objdump = self.my_Popen([cmd, '--section-headers', elf]) + for line in iter(objdump.stdout.readline, ''): + try: + _, name, size, vma, _, _, _ = line.split() + except ValueError: + if 'ALLOC' in line: + self._sections[elf_name].append([name, int(vma, 16), + int(size, 16)]) + + def first_vma(self, elf_name): + self.read_sections(elf_name) + return '0x{:x}'.format(self._sections[elf_name][0][1]) + + def overlaps(self, section, addr, size): + sec_addr = section[1] + sec_size = section[2] + if not size or not sec_size: + return False + return ((addr <= (sec_addr + sec_size - 1)) and + ((addr + size - 1) >= sec_addr)) + + def sections_in_region(self, addr, size, elf_idx): + ret = '' + addr = self.subtract_load_addr(addr) + if not addr: + return '' + iaddr = int(addr, 16) + isize = int(size, 16) + elf = self._elfs[int(elf_idx)][0] + if elf is None: + return '' + self.read_sections(elf) + if elf not in self._sections: + return '' + for s in self._sections[elf]: + if self.overlaps(s, iaddr, isize): + ret += ' ' + s[0] + return ret + + def reset(self): + self._call_stack_found = False + if self._addr2line: + self._addr2line.terminate() + self._addr2line = None + self._addr2line_elf_name = None + self._arch = None + self._saved_abort_line = '' + self._sections = {} # {elf_name: [[name, addr, size], ...], ...} + self._regions = [] # [[addr, size, elf_idx, saved line], ...] + self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...} + self._tee_load_addr = '0x0' + self._func_graph_found = False + self._func_graph_skip_line = True + + def pretty_print_path(self, path): + if self._strip_path: + return re.sub(re.escape(self._strip_path) + '/*', '', path) + return path + + def write(self, line): + if self._call_stack_found: + match = re.search(STACK_ADDR_RE, line) + if match: + addr = match.group('addr') + pre = match.start('addr') + post = match.end('addr') + self._out.write(line[:pre]) + self._out.write(addr) + # The call stack contains return addresses (LR/ELR values). + # Heuristic: subtract 2 to obtain the call site of the function + # or the location of the exception. This value works for A64, + # A32 as well as Thumb. + pc = 0 + lr = int(addr, 16) + if lr: + pc = lr - 2 + res = self.resolve('0x{:x}'.format(pc)) + res = self.pretty_print_path(res) + self._out.write(' ' + res) + self._out.write(line[post:]) + return + else: + self.reset() + if self._func_graph_found: + match = re.search(GRAPH_ADDR_RE, line) + match_re = re.search(GRAPH_RE, line) + if match: + addr = match.group('addr') + pre = match.start('addr') + post = match.end('addr') + self._out.write(line[:pre]) + res = self.resolve(addr) + res_arr = re.split(' ', res) + self._out.write(res_arr[0]) + self._out.write(line[post:]) + self._func_graph_skip_line = False + return + elif match_re: + self._out.write(line) + return + elif self._func_graph_skip_line: + return + else: + self.reset() + match = re.search(REGION_RE, line) + if match: + # Region table: save info for later processing once + # we know which UUID corresponds to which ELF index + addr = match.group('addr') + size = match.group('size') + elf_idx = match.group('elf_idx') + self._regions.append([addr, size, elf_idx, line]) + return + match = re.search(ELF_LIST_RE, line) + if match: + # ELF list: save info for later. Region table and ELF list + # will be displayed when the call stack is reached + i = int(match.group('idx')) + self._elfs[i] = [match.group('uuid'), match.group('load_addr'), + line] + return + match = re.search(TA_PANIC_RE, line) + if match: + code = match.group('code') + if code in tee_result_names: + line = line.strip() + ' (' + tee_result_names[code] + ')\n' + self._out.write(line) + return + match = re.search(TEE_LOAD_ADDR_RE, line) + if match: + self._tee_load_addr = match.group('load_addr') + match = re.search(CALL_STACK_RE, line) + if match: + self._call_stack_found = True + if self._regions: + for r in self._regions: + r_addr = r[0] + r_size = r[1] + elf_idx = r[2] + saved_line = r[3] + if elf_idx is None: + self._out.write(saved_line) + else: + self._out.write(saved_line.strip() + + self.sections_in_region(r_addr, + r_size, + elf_idx) + + '\n') + if self._elfs: + for k in self._elfs: + e = self._elfs[k] + if (len(e) >= 3): + # TA executable or library + self._out.write(e[2].strip()) + elf = self.get_elf(e[0]) + if elf: + rpath = os.path.realpath(elf) + path = self.pretty_print_path(rpath) + self._out.write(' (' + path + ')') + self._out.write('\n') + # Here is a good place to resolve the abort address because we + # have all the information we need + if self._saved_abort_line: + self._out.write(self.process_abort(self._saved_abort_line)) + match = re.search(FUNC_GRAPH_RE, line) + if match: + self._func_graph_found = True + match = re.search(ABORT_ADDR_RE, line) + if match: + self.reset() + # At this point the arch and TA load address are unknown. + # Save the line so We can translate the abort address later. + self._saved_abort_line = line + self._out.write(line) + + def flush(self): + self._out.flush() + + +def main(): + args = get_args() + if args.dir: + # Flatten list in case -d is used several times *and* with multiple + # arguments + args.dirs = [item for sublist in args.dir for item in sublist] + else: + args.dirs = [] + symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path) + + fd = sys.stdin.fileno() + isatty = os.isatty(fd) + if isatty: + old = termios.tcgetattr(fd) + new = termios.tcgetattr(fd) + new[3] = new[3] & ~termios.ECHO # lflags + try: + if isatty: + termios.tcsetattr(fd, termios.TCSADRAIN, new) + for line in sys.stdin: + symbolizer.write(line) + finally: + symbolizer.flush() + if isatty: + termios.tcsetattr(fd, termios.TCSADRAIN, old) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/tee_bin_parser.py b/optee/optee_os/scripts/tee_bin_parser.py new file mode 100755 index 0000000..04bfb9f --- /dev/null +++ b/optee/optee_os/scripts/tee_bin_parser.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2016, Linaro Limited +import struct +import argparse + + +def get_args(): + parser = argparse.ArgumentParser() + + parser.add_argument('--input', required=False, dest='inf', + default='../out/arm/core/tee.bin', + help='The input tee.bin') + + return parser.parse_args() + + +def main(): + args = get_args() + + with open(args.inf, "rb") as f: + data = f.read(4) + magic = struct.unpack('\n\n') + f.write('#include \n\n') + f.write('const uint8_t ts_bin_' + ts_uuid.hex + '[] = {\n') + ts_size, ts_uncompressed_size = dump_bin(f, ts, args.compress) + f.write('};\n') + + if is_sp: + + f.write('#include \n\n') + f.write('const uint8_t fdt_bin_' + ts_uuid.hex + '[] = {\n') + dump_bin(f, args.manifest, False) + f.write('};\n') + f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(sp_images, struct \ + sp_image) = {\n') + f.write('\t.fdt = fdt_bin_' + ts_uuid.hex + ',\n') + + f.write('. image = {') + f.write('\t.flags = 0x{:04x},\n'.format(sp_get_flags(ts))) + else: + f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(early_tas, struct \ + embedded_ts) = {\n') + f.write('\t.flags = 0x{:04x},\n'.format(ta_get_flags(ts))) + f.write('\t.uuid = {\n') + f.write('\t\t.timeLow = 0x{:08x},\n'.format(ts_uuid.time_low)) + f.write('\t\t.timeMid = 0x{:04x},\n'.format(ts_uuid.time_mid)) + f.write('\t\t.timeHiAndVersion = ' + + '0x{:04x},\n'.format(ts_uuid.time_hi_version)) + f.write('\t\t.clockSeqAndNode = {\n') + csn = '{0:02x}{1:02x}{2:012x}'.format(ts_uuid.clock_seq_hi_variant, + ts_uuid.clock_seq_low, ts_uuid.node) + f.write('\t\t\t') + f.write(', '.join('0x' + csn[i:i + 2] for i in range(0, len(csn), 2))) + f.write('\n\t\t},\n\t},\n') + f.write('\t.size = sizeof(ts_bin_' + ts_uuid.hex + + '), /* {:d} */\n'.format(ts_size)) + f.write('\t.ts = ts_bin_' + ts_uuid.hex + ',\n') + if args.compress: + f.write('\t.uncompressed_size = ' + '{:d},\n'.format(ts_uncompressed_size)) + if is_sp: + f.write('}\n') + f.write('};\n') + f.close() + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/scripts/update_changelog.py b/optee/optee_os/scripts/update_changelog.py new file mode 100755 index 0000000..89e78ff --- /dev/null +++ b/optee/optee_os/scripts/update_changelog.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2019, Linaro Limited +# + +from subprocess import Popen, PIPE +import argparse + + +def get_args(): + parser = argparse.ArgumentParser(description='Helper script that updates ' + 'the CHANGELOG.md file.\n' + 'Usage example:\n' + ' ./update_changelog.py ' + ' --changelog-file CHANGELOG.md' + ' --release-version 3.7.0' + ' --previous-release-version 3.6.0' + ' --release-date 2019-10-11') + + parser.add_argument('--changelog-file', action='store', required=False, + default='CHANGELOG.md', + help='Changelog file to be updated.') + + parser.add_argument('--release-date', action='store', required=True, + help='The release date (yyyy-mm-dd).') + + parser.add_argument('--release-version', action='store', required=True, + help='Release version (MAJOR.MINOR.PATCH).') + + parser.add_argument('--previous-release-version', action='store', + required=True, + help='Previous release version (MAJOR.MINOR.PATCH).') + + return parser.parse_args() + + +def prepend_write(filename, text): + with open(filename, 'r+') as f: + current_content = f.read() + f.seek(0, 0) + f.write(text + '\n' + current_content) + f.flush() + + +def get_previous_release_date(tag): + cmd = "git log -1 --date=format:%Y-%m-%d --format=format:%cd " \ + "{}".format(tag) + process = Popen(cmd.split(), stdout=PIPE) + (output, err) = process.communicate() + return output.decode("utf-8") + + +def main(): + global args + + args = get_args() + + gits = ["OP-TEE/optee_os", "OP-TEE/optee_client", "OP-TEE/optee_test", + "OP-TEE/build", "linaro-swg/optee_examples"] + + # Shorten name + clf = args.changelog_file + rv = args.release_version + prv = args.previous_release_version + rd = args.release_date + prd = get_previous_release_date(prv) + + # In some cases we need underscore in string + rvu = rv.replace('.', '_') + + text = "# OP-TEE - version {} ({})\n".format(rv, rd) + text += "\n" + text += "- Links to the release pages, commits and pull requests merged " \ + "into this release for:\n" + + for g in gits: + gu = g.replace('/', '_') + gu = gu.replace('-', '_') + text += " - {}: [release page][{}_release_{}], " \ + "[commits][{}_commits_{}] and [pull requests]" \ + "[{}_pr_{}]\n".format(g, gu, rvu, gu, rvu, gu, rvu) + + text += "\n" + + for g in gits: + gu = g.replace('/', '_') + gu = gu.replace('-', '_') + text += "\n[{}_release_{}]: https://github.com/{}/releases/tag/" \ + "{}\n".format(gu, rvu, g, rv) + text += "[{}_commits_{}]: https://github.com/{}/compare/" \ + "{}...{}\n".format(gu, rvu, g, prv, rv) + text += "[{}_pr_{}]: https://github.com/{}/pulls?q=is%3Apr+is%3A" \ + "merged+base%3Amaster+merged%3A{}..{}\n".format( + gu, rvu, g, prd, rd) + + prepend_write(args.changelog_file, text) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_os/ta/arch/arm/ta.ld.S b/optee/optee_os/ta/arch/arm/ta.ld.S new file mode 100644 index 0000000..1ec760a --- /dev/null +++ b/optee/optee_os/ta/arch/arm/ta.ld.S @@ -0,0 +1,104 @@ +#ifdef ARM32 +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) +#define MCOUNT_SYM __gnu_mcount_nc +#endif +#ifdef ARM64 +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +#define MCOUNT_SYM _mcount +#endif + +#ifndef CFG_FTRACE_BUF_SIZE +#define CFG_FTRACE_BUF_SIZE 2048 +#endif + +SECTIONS { + .ta_head : {*(.ta_head)} + .text : { + __text_start = .; + *(.text .text.*) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + /* Workaround for an erratum in ARM's VFP11 coprocessor */ + *(.vfp11_veneer) + __text_end = .; + } + .note.gnu.property : { *(.note.gnu.property) } + .plt : { *(.plt) } + + .eh_frame_hdr : { + *(.eh_frame_hdr) + *(.eh_frame_entry .eh_frame_entry.*) + } + .eh_frame : { KEEP(*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + .rodata : { + *(.gnu.linkonce.r.*) + *(.rodata .rodata.*) + } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN(__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN(__exidx_end = .); + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .hash : { *(.hash) } + + /* Page align to allow dropping execute bit for RW data */ + . = ALIGN(4096); + + .dynamic : { *(.dynamic) } + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .got : { *(.got.plt) *(.got) } + .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.dyn : { *(.rel.dyn) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + .data : { *(.data .data.* .gnu.linkonce.d.*) } + .bss : { + *(.bss .bss.* .gnu.linkonce.b.* COMMON) + + /* + * TA tracing using ftrace + * Reserve some space for the ftrace buffer, only if the + * TA is instrumented (i.e., some files were built with -pg). + */ + . = ALIGN(8); + __ftrace_buf_start = .; + . += DEFINED(MCOUNT_SYM) ? + CFG_FTRACE_BUF_SIZE : 0; + __ftrace_buf_end = .; + } + + /DISCARD/ : { *(.interp) } +} + diff --git a/optee/optee_os/ta/arch/arm/ta_entry_a32.S b/optee/optee_os/ta/arch/arm/ta_entry_a32.S new file mode 100644 index 0000000..cd9a12f --- /dev/null +++ b/optee/optee_os/ta/arch/arm/ta_entry_a32.S @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include + + .section .note.GNU-stack,"",%progbits + +/* + * This function is the bottom of the user call stack. Mark it as such so that + * the unwinding code won't try to go further down. + * We need an assembly wrapper because Clang does not accept asm(".cantunwind") + * in a C function: + * + * user_ta_header.c:44:6: error: .fnstart must precede .cantunwind directive + * asm(".cantunwind"); + * ^ + */ +FUNC __ta_entry, : +UNWIND( .cantunwind) + bl __ta_entry_c +END_FUNC __ta_entry diff --git a/optee/optee_os/ta/arch/riscv/ta.ld.S b/optee/optee_os/ta/arch/riscv/ta.ld.S new file mode 100644 index 0000000..b823def --- /dev/null +++ b/optee/optee_os/ta/arch/riscv/ta.ld.S @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +#ifdef RV32 +OUTPUT_FORMAT("elf32-littleriscv") +OUTPUT_ARCH(riscv) +#endif +#ifdef RV64 +OUTPUT_FORMAT("elf64-littleriscv") +OUTPUT_ARCH(riscv) +#endif + +#ifndef CFG_FTRACE_BUF_SIZE +#define CFG_FTRACE_BUF_SIZE 2048 +#endif + +SECTIONS { + .ta_head : {*(.ta_head)} + .text : { + __text_start = .; + *(.text .text.*) + *(.stub) + *(.gnu.linkonce.t.*) + __text_end = .; + } + .note.gnu.property : { *(.note.gnu.property) } + .plt : { *(.plt) } + + .eh_frame_hdr : { + *(.eh_frame_hdr) + *(.eh_frame_entry .eh_frame_entry.*) + } + .eh_frame : { KEEP(*(.eh_frame)) *(.eh_frame.*) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + .rodata : { + *(.gnu.linkonce.r.*) + *(.rodata .rodata.*) + } + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .hash : { *(.hash) } + + /* Page align to allow dropping execute bit for RW data */ + . = ALIGN(4096); + + .dynamic : { *(.dynamic) } + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .got : { *(.got.plt) *(.got) } + .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.dyn : { *(.rel.dyn) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + .data : { *(.data .data.* .gnu.linkonce.d.*) } + .bss : { + *(.bss .bss.* .gnu.linkonce.b.* COMMON) + + /* + * TA tracing using ftrace + * Reserve some space for the ftrace buffer, only if the + * TA is instrumented (i.e., some files were built with -pg). + */ + . = ALIGN(8); + __ftrace_buf_start = .; + . += DEFINED(MCOUNT_SYM) ? + CFG_FTRACE_BUF_SIZE : 0; + __ftrace_buf_end = .; + } + + /DISCARD/ : { *(.interp) } +} + diff --git a/optee/optee_os/ta/avb/Makefile b/optee/optee_os/ta/avb/Makefile new file mode 100644 index 0000000..7c8d2bd --- /dev/null +++ b/optee/optee_os/ta/avb/Makefile @@ -0,0 +1,18 @@ +# The UUID for the Trusted Application +BINARY=023f8f1a-292a-432b-8fc4-de8471358067 + +ifdef TA_CROSS_COMPILE +CROSS_COMPILE ?= $(TA_CROSS_COMPILE) +endif +export CROSS_COMPILE + +CFG_TEE_TA_LOG_LEVEL ?= 2 +CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) + +-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk + +ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), ) +clean: + @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA' + @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)' +endif diff --git a/optee/optee_os/ta/avb/entry.c b/optee/optee_os/ta/avb/entry.c new file mode 100644 index 0000000..a257c11 --- /dev/null +++ b/optee/optee_os/ta/avb/entry.c @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* Copyright (c) 2018, Linaro Limited */ + +#include +#include +#include + +#include +#include + +#define DEFAULT_LOCK_STATE 0 + +static const uint32_t storageid = TEE_STORAGE_PRIVATE_RPMB; +static const char rb_obj_name[] = "rb_state"; +static const char *named_value_prefix = "named_value_"; + +static TEE_Result get_slot_offset(size_t slot, size_t *offset) +{ + if (slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS) + return TEE_ERROR_BAD_PARAMETERS; + + *offset = sizeof(uint32_t) /* lock_state */ + slot * sizeof(uint64_t); + return TEE_SUCCESS; +} + +static TEE_Result create_rb_state(uint32_t lock_state, TEE_ObjectHandle *h) +{ + const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_OVERWRITE; + + return TEE_CreatePersistentObject(storageid, rb_obj_name, + sizeof(rb_obj_name), flags, NULL, + &lock_state, sizeof(lock_state), h); +} + +static TEE_Result open_rb_state(uint32_t default_lock_state, + TEE_ObjectHandle *h) +{ + uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE; + TEE_Result res; + + res = TEE_OpenPersistentObject(storageid, rb_obj_name, + sizeof(rb_obj_name), flags, h); + if (!res) + return TEE_SUCCESS; + + return create_rb_state(default_lock_state, h); +} + +static TEE_Result get_named_object_name(char *name_orig, + uint32_t name_orig_size, + char *name, uint32_t *name_size) +{ + size_t pref_len = strlen(named_value_prefix); + + if (name_orig_size + pref_len > + TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_BAD_PARAMETERS; + + /* Start with prefix */ + TEE_MemMove(name, named_value_prefix, pref_len); + + /* Concatenate provided object name */ + TEE_MemMove(name + pref_len, name_orig, name_orig_size); + + *name_size = name_orig_size + pref_len; + + return TEE_SUCCESS; +} + +static TEE_Result read_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + size_t slot_offset; + uint64_t idx; + size_t count; + TEE_Result res; + TEE_ObjectHandle h; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + res = get_slot_offset(params[0].value.a, &slot_offset); + if (res) + return res; + + res = open_rb_state(DEFAULT_LOCK_STATE, &h); + if (res) + return res; + + res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); + if (res) + goto out; + + res = TEE_ReadObjectData(h, &idx, sizeof(idx), &count); + if (res) + goto out; + if (count != sizeof(idx)) { + idx = 0; /* Not yet written slots are reported as 0 */ + + if (count) { + /* + * Somehow the file didn't even hold a complete + * slot index entry. Write it as 0. + */ + res = TEE_SeekObjectData(h, slot_offset, + TEE_DATA_SEEK_SET); + if (res) + goto out; + res = TEE_WriteObjectData(h, &idx, sizeof(idx)); + if (res) + goto out; + } + } + + params[1].value.a = idx >> 32; + params[1].value.b = idx; +out: + TEE_CloseObject(h); + return res; +} + +static TEE_Result write_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + size_t slot_offset; + uint64_t widx; + uint64_t idx; + size_t count; + TEE_Result res; + TEE_ObjectHandle h; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + res = get_slot_offset(params[0].value.a, &slot_offset); + if (res) + return res; + widx = ((uint64_t)params[1].value.a << 32) | params[1].value.b; + + res = open_rb_state(DEFAULT_LOCK_STATE, &h); + if (res) + return res; + + res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); + if (res) + goto out; + + res = TEE_ReadObjectData(h, &idx, sizeof(idx), &count); + if (res) + goto out; + if (count != sizeof(idx)) + idx = 0; /* Not yet written slots are reported as 0 */ + + if (widx < idx) { + res = TEE_ERROR_SECURITY; + goto out; + } + + res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); + if (res) + goto out; + + res = TEE_WriteObjectData(h, &widx, sizeof(widx)); +out: + TEE_CloseObject(h); + return res; +} + +static TEE_Result read_lock_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint32_t lock_state; + size_t count; + TEE_Result res; + TEE_ObjectHandle h; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + res = open_rb_state(DEFAULT_LOCK_STATE, &h); + if (res) + return res; + + res = TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count); + if (res) + goto out; + if (count != sizeof(lock_state)) { + /* + * Client need write the lock state to recover, this can + * normally not happen. + */ + res = TEE_ERROR_CORRUPT_OBJECT; + goto out; + } + + params[0].value.a = lock_state; +out: + TEE_CloseObject(h); + return res; +} + +static TEE_Result write_lock_state(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint32_t wlock_state; + uint32_t lock_state; + size_t count; + TEE_Result res; + TEE_ObjectHandle h; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + wlock_state = params[0].value.a; + + res = open_rb_state(wlock_state, &h); + if (res) + return res; + + res = TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count); + if (res) + goto out; + if (count == sizeof(lock_state) && lock_state == wlock_state) + goto out; + + res = TEE_SeekObjectData(h, 0, TEE_DATA_SEEK_SET); + if (res) + goto out; + + res = TEE_WriteObjectData(h, &wlock_state, sizeof(wlock_state)); +out: + TEE_CloseObject(h); + return res; +} + +static TEE_Result write_persist_value(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_OVERWRITE; + char name_full[TEE_OBJECT_ID_MAX_LEN] = { }; + TEE_ObjectHandle h = TEE_HANDLE_NULL; + TEE_Result res = TEE_SUCCESS; + uint32_t name_full_sz = 0; + uint32_t name_buf_sz = 0; + uint32_t value_sz = 0; + char *name_buf = NULL; + char *value = NULL; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + name_buf = params[0].memref.buffer; + name_buf_sz = params[0].memref.size; + value_sz = params[1].memref.size; + value = TEE_Malloc(value_sz, 0); + if (!value) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_MemMove(value, params[1].memref.buffer, value_sz); + + res = get_named_object_name(name_buf, name_buf_sz, + name_full, &name_full_sz); + if (res) + goto out; + + res = TEE_CreatePersistentObject(storageid, name_full, + name_full_sz, + flags, NULL, value, + value_sz, &h); + if (res) + EMSG("Can't create named object value, res = 0x%x", res); + + TEE_CloseObject(h); +out: + TEE_Free(value); + + return res; +} + +static TEE_Result read_persist_value(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE; + TEE_Result res = TEE_SUCCESS; + TEE_ObjectHandle h = TEE_HANDLE_NULL; + char name_full[TEE_OBJECT_ID_MAX_LEN]; + uint32_t name_full_sz = 0; + uint32_t name_buf_sz = 0; + char *name_buf = NULL; + uint32_t value_sz = 0; + char *value = NULL; + size_t count = 0; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + name_buf = params[0].memref.buffer; + name_buf_sz = params[0].memref.size; + value_sz = params[1].memref.size; + value = TEE_Malloc(value_sz, 0); + if (!value) + return TEE_ERROR_OUT_OF_MEMORY; + + res = get_named_object_name(name_buf, name_buf_sz, + name_full, &name_full_sz); + if (res) + goto out_free; + + res = TEE_OpenPersistentObject(storageid, name_full, + name_full_sz, flags, &h); + if (res) { + EMSG("Can't open named object value, res = 0x%x", res); + goto out_free; + } + + res = TEE_ReadObjectData(h, value, value_sz, &count); + if (res) { + EMSG("Can't read named object value, res = 0x%x", res); + goto out; + } + + TEE_MemMove(params[1].memref.buffer, value, + value_sz); + + params[1].memref.size = count; +out: + TEE_CloseObject(h); +out_free: + TEE_Free(value); + + return res; +} + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused, + TEE_Param params[4] __unused, + void **session __unused) +{ + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *sess __unused) +{ +} + +TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd, + uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd) { + case TA_AVB_CMD_READ_ROLLBACK_INDEX: + return read_rb_idx(pt, params); + case TA_AVB_CMD_WRITE_ROLLBACK_INDEX: + return write_rb_idx(pt, params); + case TA_AVB_CMD_READ_LOCK_STATE: + return read_lock_state(pt, params); + case TA_AVB_CMD_WRITE_LOCK_STATE: + return write_lock_state(pt, params); + case TA_AVB_CMD_READ_PERSIST_VALUE: + return read_persist_value(pt, params); + case TA_AVB_CMD_WRITE_PERSIST_VALUE: + return write_persist_value(pt, params); + default: + EMSG("Command ID 0x%x is not supported", cmd); + return TEE_ERROR_NOT_SUPPORTED; + } +} diff --git a/optee/optee_os/ta/avb/include/ta_avb.h b/optee/optee_os/ta/avb/include/ta_avb.h new file mode 100644 index 0000000..45521f7 --- /dev/null +++ b/optee/optee_os/ta/avb/include/ta_avb.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited */ + +#ifndef __TA_AVB_H +#define __TA_AVB_H + +#define TA_AVB_UUID { 0x023f8f1a, 0x292a, 0x432b, \ + { 0x8f, 0xc4, 0xde, 0x84, 0x71, 0x35, 0x80, 0x67 } } + +#define TA_AVB_MAX_ROLLBACK_LOCATIONS 256 + +/* + * Gets the rollback index corresponding to the given rollback index slot. + * + * in params[0].value.a: rollback index slot + * out params[1].value.a: upper 32 bits of rollback index + * out params[1].value.b: lower 32 bits of rollback index + */ +#define TA_AVB_CMD_READ_ROLLBACK_INDEX 0 + +/* + * Updates the rollback index corresponding to the given rollback index slot. + * + * Will refuse to update a slot with a lower value. + * + * in params[0].value.a: rollback index slot + * in params[1].value.a: upper 32 bits of rollback index + * in params[1].value.b: lower 32 bits of rollback index + */ +#define TA_AVB_CMD_WRITE_ROLLBACK_INDEX 1 + +/* + * Gets the lock state of the device. + * + * out params[0].value.a: lock state + */ +#define TA_AVB_CMD_READ_LOCK_STATE 2 + +/* + * Sets the lock state of the device. + * + * If the lock state is changed all rollback slots will be reset to 0 + * + * in params[0].value.a: lock state + */ +#define TA_AVB_CMD_WRITE_LOCK_STATE 3 + +/* + * Reads a persistent value corresponding to the given name. + * + * in params[0].memref: persistent value name + * out params[1].memref: read persistent value buffer + */ +#define TA_AVB_CMD_READ_PERSIST_VALUE 4 + +/* + * Writes a persistent value corresponding to the given name. + * + * in params[0].memref: persistent value name + * in params[1].memref: persistent value buffer to write + */ +#define TA_AVB_CMD_WRITE_PERSIST_VALUE 5 + +#endif /*__TA_AVB_H*/ diff --git a/optee/optee_os/ta/avb/sub.mk b/optee/optee_os/ta/avb/sub.mk new file mode 100644 index 0000000..f1b35c0 --- /dev/null +++ b/optee/optee_os/ta/avb/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +global-incdirs-y += . +srcs-y += entry.c diff --git a/optee/optee_os/ta/avb/user_ta.mk b/optee/optee_os/ta/avb/user_ta.mk new file mode 100644 index 0000000..c4cb2f7 --- /dev/null +++ b/optee/optee_os/ta/avb/user_ta.mk @@ -0,0 +1,2 @@ +user-ta-uuid := 023f8f1a-292a-432b-8fc4-de8471358067 +user-ta-version := 0 diff --git a/optee/optee_os/ta/avb/user_ta_header_defines.h b/optee/optee_os/ta/avb/user_ta_header_defines.h new file mode 100644 index 0000000..21e49a7 --- /dev/null +++ b/optee/optee_os/ta/avb/user_ta_header_defines.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited */ + +#ifndef __USER_TA_HEADER_DEFINES_H +#define __USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_AVB_UUID + +#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_MULTI_SESSION) + +#define TA_STACK_SIZE (16 * 1024) +#define TA_DATA_SIZE (16 * 1024) + +#endif /*__USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_os/ta/link.mk b/optee/optee_os/ta/link.mk new file mode 100644 index 0000000..40bdc9f --- /dev/null +++ b/optee/optee_os/ta/link.mk @@ -0,0 +1,122 @@ +link-script$(sm) = $(ta-dev-kit-dir$(sm))/src/ta.ld.S +link-script-pp$(sm) = $(link-out-dir$(sm))/ta.lds +link-script-dep$(sm) = $(link-out-dir$(sm))/.ta.ld.d + +SIGN_ENC ?= $(PYTHON3) $(ta-dev-kit-dir$(sm))/scripts/sign_encrypt.py +TA_SIGN_KEY ?= $(ta-dev-kit-dir$(sm))/keys/default_ta.pem + +ifeq ($(CFG_ENCRYPT_TA),y) +# Default TA encryption key is a dummy key derived from default +# hardware unique key (an array of 16 zero bytes) to demonstrate +# usage of REE-FS TAs encryption feature. +# +# Note that a user of this TA encryption feature needs to provide +# encryption key and its handling corresponding to their security +# requirements. +TA_ENC_KEY ?= 'b64d239b1f3c7d3b06506229cd8ff7c8af2bb4db2168621ac62c84948468c4f4' +endif + +all: $(link-out-dir$(sm))/$(user-ta-uuid).dmp \ + $(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf \ + $(link-out-dir$(sm))/$(user-ta-uuid).ta +cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).elf +cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).dmp +cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).map +cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf +cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).ta +cleanfiles += $(link-script-pp$(sm)) $(link-script-dep$(sm)) + +link-ldflags = -e__ta_entry -pie +link-ldflags += -T $(link-script-pp$(sm)) +link-ldflags += -Map=$(link-out-dir$(sm))/$(user-ta-uuid).map +link-ldflags += --sort-section=alignment +link-ldflags += -z max-page-size=4096 # OP-TEE always uses 4K alignment +ifeq ($(sm)-$(CFG_TA_BTI),ta_arm64-y) +link-ldflags += $(call ld-option,-z force-bti) --fatal-warnings +endif +link-ldflags += --as-needed # Do not add dependency on unused shlib +link-ldflags += $(link-ldflags$(sm)) + +$(link-out-dir$(sm))/dyn_list: + @$(cmd-echo-silent) ' GEN $@' + $(q)mkdir -p $(dir $@) + $(q)echo "{" >$@ + $(q)echo "__elf_phdr_info;" >>$@ +ifeq ($(CFG_FTRACE_SUPPORT),y) + $(q)echo "__ftrace_info;" >>$@ +endif + $(q)echo "trace_ext_prefix;" >>$@ + $(q)echo "trace_level;" >>$@ + $(q)echo "};" >>$@ +link-ldflags += --dynamic-list $(link-out-dir$(sm))/dyn_list +dynlistdep = $(link-out-dir$(sm))/dyn_list +cleanfiles += $(link-out-dir$(sm))/dyn_list + +link-ldadd = $(user-ta-ldadd) $(addprefix -L,$(libdirs)) +link-ldadd += --start-group +link-ldadd += $(addprefix -l,$(libnames)) +ifneq (,$(filter %.cpp,$(srcs))) +link-ldflags += --eh-frame-hdr +link-ldadd += $(libstdc++$(sm)) $(libgcc_eh$(sm)) +endif +link-ldadd += --end-group + +link-ldadd-after-libgcc += $(addprefix -l,$(libnames-after-libgcc)) + +ldargs-$(user-ta-uuid).elf := $(link-ldflags) $(objs) $(link-ldadd) \ + $(libgcc$(sm)) $(link-ldadd-after-libgcc) + +link-script-cppflags-$(sm) := \ + $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \ + $(nostdinc$(sm)) $(CPPFLAGS) \ + $(addprefix -I,$(incdirs$(sm)) $(link-out-dir$(sm))) \ + $(cppflags$(sm))) + +-include $(link-script-dep$(sm)) + +link-script-pp-makefiles$(sm) = $(filter-out %.d %.cmd,$(MAKEFILE_LIST)) + +define gen-link-t +$(link-script-pp$(sm)): $(link-script$(sm)) $(conf-file) $(link-script-pp-makefiles$(sm)) + @$(cmd-echo-silent) ' CPP $$@' + $(q)mkdir -p $$(dir $$@) + $(q)$(CPP$(sm)) -P -MT $$@ -MD -MF $(link-script-dep$(sm)) \ + $(link-script-cppflags-$(sm)) $$< -o $$@ + +$(link-out-dir$(sm))/$(user-ta-uuid).elf: $(objs) $(libdeps) \ + $(libdeps-after-libgcc) \ + $(link-script-pp$(sm)) \ + $(dynlistdep) \ + $(additional-link-deps) + @$(cmd-echo-silent) ' LD $$@' + $(q)$(LD$(sm)) $(ldargs-$(user-ta-uuid).elf) -o $$@ + +$(link-out-dir$(sm))/$(user-ta-uuid).dmp: \ + $(link-out-dir$(sm))/$(user-ta-uuid).elf + @$(cmd-echo-silent) ' OBJDUMP $$@' + $(q)$(OBJDUMP$(sm)) -l -x -d $$< > $$@ + +$(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf: \ + $(link-out-dir$(sm))/$(user-ta-uuid).elf + @$(cmd-echo-silent) ' OBJCOPY $$@' + $(q)$(OBJCOPY$(sm)) --strip-unneeded $$< $$@ + +cmd-echo$(user-ta-uuid) := SIGN # +ifeq ($(CFG_ENCRYPT_TA),y) +crypt-args$(user-ta-uuid) := --enc-key $(TA_ENC_KEY) +cmd-echo$(user-ta-uuid) := SIGNENC +endif +$(link-out-dir$(sm))/$(user-ta-uuid).ta: \ + $(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf \ + $(TA_SIGN_KEY) $(TA_SUBKEY_DEPS) \ + $(lastword $(SIGN_ENC)) + @$(cmd-echo-silent) ' $$(cmd-echo$(user-ta-uuid)) $$@' + $(q)$(SIGN_ENC) --key $(TA_SIGN_KEY) $(TA_SUBKEY_ARGS) \ + $$(crypt-args$(user-ta-uuid)) \ + --uuid $(user-ta-uuid) --ta-version $(user-ta-version) \ + --in $$< --out $$@ +endef + +$(eval $(call gen-link-t)) + +additional-link-deps := diff --git a/optee/optee_os/ta/link_shlib.mk b/optee/optee_os/ta/link_shlib.mk new file mode 100644 index 0000000..fdb6315 --- /dev/null +++ b/optee/optee_os/ta/link_shlib.mk @@ -0,0 +1,54 @@ +ifeq (,$(shlibuuid)) +$(error SHLIBUUID not set) +endif +link-out-dir = $(out-dir) + +SIGN ?= $(TA_DEV_KIT_DIR)/scripts/sign_encrypt.py +TA_SIGN_KEY ?= $(TA_DEV_KIT_DIR)/keys/default_ta.pem + +all: $(link-out-dir)/$(shlibname).so $(link-out-dir)/$(shlibname).dmp \ + $(link-out-dir)/$(shlibname).stripped.so \ + $(link-out-dir)/$(shlibuuid).elf \ + $(link-out-dir)/$(shlibuuid).ta + +cleanfiles += $(link-out-dir)/$(shlibname).so +cleanfiles += $(link-out-dir)/$(shlibname).dmp +cleanfiles += $(link-out-dir)/$(shlibname).stripped.so +cleanfiles += $(link-out-dir)/$(shlibuuid).elf +cleanfiles += $(link-out-dir)/$(shlibuuid).ta + +shlink-ldflags = $(LDFLAGS) +shlink-ldflags += -shared -z max-page-size=4096 +shlink-ldflags += $(call ld-option,-z separate-loadable-segments) +ifeq ($(sm)-$(CFG_TA_BTI),ta_arm64-y) +shlink-ldflags += $(call ld-option,-z force-bti) --fatal-warnings +endif +shlink-ldflags += --as-needed # Do not add dependency on unused shlib + +shlink-ldadd = $(LDADD) +shlink-ldadd += $(addprefix -L,$(libdirs)) +shlink-ldadd += --start-group $(addprefix -l,$(libnames)) --end-group +ldargs-$(shlibname).so := $(shlink-ldflags) $(objs) $(shlink-ldadd) $(libgcc$(sm)) + + +$(link-out-dir)/$(shlibname).so: $(objs) $(libdeps) + @$(cmd-echo-silent) ' LD $@' + $(q)$(LD$(sm)) $(ldargs-$(shlibname).so) --soname=$(shlibuuid) -o $@ + +$(link-out-dir)/$(shlibname).dmp: $(link-out-dir)/$(shlibname).so + @$(cmd-echo-silent) ' OBJDUMP $@' + $(q)$(OBJDUMP$(sm)) -l -x -d $< > $@ + +$(link-out-dir)/$(shlibname).stripped.so: $(link-out-dir)/$(shlibname).so + @$(cmd-echo-silent) ' OBJCOPY $@' + $(q)$(OBJCOPY$(sm)) --strip-unneeded $< $@ + +$(link-out-dir)/$(shlibuuid).elf: $(link-out-dir)/$(shlibname).so + @$(cmd-echo-silent) ' LN $@' + $(q)ln -sf $( +#include + +#define PKCS11_TA_UUID { 0xfd02c9da, 0x306c, 0x48c7, \ + { 0xa4, 0x9c, 0xbb, 0xd8, 0x27, 0xae, 0x86, 0xee } } + +/* PKCS11 trusted application version information */ +#define PKCS11_TA_VERSION_MAJOR 0 +#define PKCS11_TA_VERSION_MINOR 1 +#define PKCS11_TA_VERSION_PATCH 0 + +/* Attribute specific values */ +#define PKCS11_CK_UNAVAILABLE_INFORMATION UINT32_C(0xFFFFFFFF) +#define PKCS11_UNDEFINED_ID UINT32_C(0xFFFFFFFF) +#define PKCS11_FALSE false +#define PKCS11_TRUE true + +/* + * Note on PKCS#11 TA commands ABI + * + * For evolution of the TA API and to not mess with the GPD TEE 4 parameters + * constraint, all the PKCS11 TA invocation commands use a subset of available + * the GPD TEE invocation parameter types. + * + * Param#0 is used for the so-called control arguments of the invoked command + * and for providing a PKCS#11 compliant status code for the request command. + * Param#0 is an in/out memory reference (aka memref[0]). The input buffer + * stores serialized arguments for the command. The output buffer store the + * 32bit TA return code for the command. As a consequence, param#0 shall + * always be an input/output memory reference of at least 32bit, more if + * the command expects more input arguments. + * + * When the TA returns with TEE_SUCCESS result, client shall always get the + * 32bit value stored in param#0 output buffer and use the value as TA + * return code for the invoked command. + * + * Param#1 can be used for input data arguments of the invoked command. + * It is unused or is an input memory reference, aka memref[1]. + * Evolution of the API may use memref[1] for output data as well. + * + * Param#2 is mostly used for output data arguments of the invoked command + * and for output handles generated from invoked commands. + * Few commands uses it for a secondary input data buffer argument. + * It is unused or is an input/output/in-out memory reference, aka memref[2]. + * + * Param#3 is currently unused and reserved for evolution of the API. + */ + +enum pkcs11_ta_cmd { + /* + * PKCS11_CMD_PING Ack TA presence and return version info + * + * [in] memref[0] = 32bit, unused, must be 0 + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = [ + * 32bit version major value, + * 32bit version minor value + * 32bit version patch value + * ] + */ + PKCS11_CMD_PING = 0, + + /* + * PKCS11_CMD_SLOT_LIST - Get the table of the valid slot IDs + * + * [in] memref[0] = 32bit, unused, must be 0 + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit array slot_ids[slot counts] + * + * The TA instance may represent several PKCS#11 slots and + * associated tokens. This commadn reports the IDs of embedded tokens. + * This command relates the PKCS#11 API function C_GetSlotList(). + */ + PKCS11_CMD_SLOT_LIST = 1, + + /* + * PKCS11_CMD_SLOT_INFO - Get cryptoki structured slot information + * + * [in] memref[0] = 32bit slot ID + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_slot_info)info + * + * The TA instance may represent several PKCS#11 slots/tokens. + * This command relates the PKCS#11 API function C_GetSlotInfo(). + */ + PKCS11_CMD_SLOT_INFO = 2, + + /* + * PKCS11_CMD_TOKEN_INFO - Get cryptoki structured token information + * + * [in] memref[0] = 32bit slot ID + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_token_info)info + * + * The TA instance may represent several PKCS#11 slots/tokens. + * This command relates the PKCS#11 API function C_GetTokenInfo(). + */ + PKCS11_CMD_TOKEN_INFO = 3, + + /* + * PKCS11_CMD_MECHANISM_IDS - Get list of the supported mechanisms + * + * [in] memref[0] = 32bit slot ID + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit array mechanism IDs + * + * This command relates to the PKCS#11 API function + * C_GetMechanismList(). + */ + PKCS11_CMD_MECHANISM_IDS = 4, + + /* + * PKCS11_CMD_MECHANISM_INFO - Get information on a specific mechanism + * + * [in] memref[0] = [ + * 32bit slot ID, + * 32bit mechanism ID (PKCS11_CKM_*) + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_mechanism_info)info + * + * This command relates to the PKCS#11 API function + * C_GetMechanismInfo(). + */ + PKCS11_CMD_MECHANISM_INFO = 5, + + /* + * PKCS11_CMD_OPEN_SESSION - Open a session + * + * [in] memref[0] = [ + * 32bit slot ID, + * 32bit session flags, + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit session handle + * + * This command relates to the PKCS#11 API function C_OpenSession(). + */ + PKCS11_CMD_OPEN_SESSION = 6, + + /* + * PKCS11_CMD_CLOSE_SESSION - Close an opened session + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_CloseSession(). + */ + PKCS11_CMD_CLOSE_SESSION = 7, + + /* + * PKCS11_CMD_CLOSE_ALL_SESSIONS - Close all client sessions on token + * + * [in] memref[0] = 32bit slot ID + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function + * C_CloseAllSessions(). + */ + PKCS11_CMD_CLOSE_ALL_SESSIONS = 8, + + /* + * PKCS11_CMD_SESSION_INFO - Get Cryptoki information on a session + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_session_info)info + * + * This command relates to the PKCS#11 API function C_GetSessionInfo(). + */ + PKCS11_CMD_SESSION_INFO = 9, + + /* + * PKCS11_CMD_INIT_TOKEN - Initialize PKCS#11 token + * + * [in] memref[0] = [ + * 32bit slot ID, + * 32bit PIN length, + * byte array label[32] + * byte array PIN[PIN length], + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_InitToken(). + */ + PKCS11_CMD_INIT_TOKEN = 10, + + /* + * PKCS11_CMD_INIT_PIN - Initialize user PIN + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit PIN byte size, + * byte array: PIN data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_InitPIN(). + */ + PKCS11_CMD_INIT_PIN = 11, + + /* + * PKCS11_CMD_SET_PIN - Change user PIN + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit old PIN byte size, + * 32bit new PIN byte size, + * byte array: PIN data, + * byte array: new PIN data, + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_SetPIN(). + */ + PKCS11_CMD_SET_PIN = 12, + + /* + * PKCS11_CMD_LOGIN - Initialize user PIN + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit user identifier, enum pkcs11_user_type + * 32bit PIN byte size, + * byte array: PIN data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_Login(). + */ + PKCS11_CMD_LOGIN = 13, + + /* + * PKCS11_CMD_LOGOUT - Log out from token + * + * [in] memref[0] = [ + * 32bit session handle, + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_Logout(). + */ + PKCS11_CMD_LOGOUT = 14, + + /* + * PKCS11_CMD_CREATE_OBJECT - Create a raw client assembled object in + * the session or token + * + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_CreateObject(). + */ + PKCS11_CMD_CREATE_OBJECT = 15, + + /* + * PKCS11_CMD_DESTROY_OBJECT - Destroy an object + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_DestroyObject(). + */ + PKCS11_CMD_DESTROY_OBJECT = 16, + + /* + * PKCS11_CMD_ENCRYPT_INIT - Initialize encryption processing + * PKCS11_CMD_DECRYPT_INIT - Initialize decryption processing + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle of the key, + * (struct pkcs11_attribute_head)mechanism + mecha params + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * These commands relate to the PKCS#11 API functions + * C_EncryptInit() and C_DecryptInit(). + */ + PKCS11_CMD_ENCRYPT_INIT = 17, + PKCS11_CMD_DECRYPT_INIT = 18, + + /* + * PKCS11_CMD_ENCRYPT_UPDATE - Update encryption processing + * PKCS11_CMD_DECRYPT_UPDATE - Update decryption processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [out] memref[2] = output processed data + * + * These commands relate to the PKCS#11 API functions + * C_EncryptUpdate() and C_DecryptUpdate(). + */ + PKCS11_CMD_ENCRYPT_UPDATE = 19, + PKCS11_CMD_DECRYPT_UPDATE = 20, + + /* + * PKCS11_CMD_ENCRYPT_FINAL - Finalize encryption processing + * PKCS11_CMD_DECRYPT_FINAL - Finalize decryption processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = output processed data + * + * These commands relate to the PKCS#11 API functions + * C_EncryptFinal() and C_DecryptFinal(). + */ + PKCS11_CMD_ENCRYPT_FINAL = 21, + PKCS11_CMD_DECRYPT_FINAL = 22, + + /* + * PKCS11_CMD_ENCRYPT_ONESHOT - Update and finalize encryption + * processing + * PKCS11_CMD_DECRYPT_ONESHOT - Update and finalize decryption + * processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [out] memref[2] = output processed data + * + * These commands relate to the PKCS#11 API functions C_Encrypt and + * C_Decrypt. + */ + PKCS11_CMD_ENCRYPT_ONESHOT = 23, + PKCS11_CMD_DECRYPT_ONESHOT = 24, + + /* + * PKCS11_CMD_SIGN_INIT - Initialize a signature computation + * processing + * PKCS11_CMD_VERIFY_INIT - Initialize a signature verification + * processing + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit key handle, + * (struct pkcs11_attribute_head)mechanism + + * mechanism params, + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * These commands relate to the PKCS#11 API functions C_SignInit() and + * C_VerifyInit(). + */ + PKCS11_CMD_SIGN_INIT = 25, + PKCS11_CMD_VERIFY_INIT = 26, + + /* + * PKCS11_CMD_SIGN_UPDATE - Update a signature computation processing + * PKCS11_CMD_VERIFY_UPDATE - Update a signature verification processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * + * These commands relate to the PKCS#11 API functions C_SignUpdate() and + * C_VerifyUpdate(). + */ + PKCS11_CMD_SIGN_UPDATE = 27, + PKCS11_CMD_VERIFY_UPDATE = 28, + + /* + * PKCS11_CMD_SIGN_FINAL - Finalize a signature computation processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = output signature + * + * This command relates to the PKCS#11 API functions C_SignFinal(). + */ + PKCS11_CMD_SIGN_FINAL = 29, + + /* + * PKCS11_CMD_VERIFY_FINAL - Finalize a signature verification + * processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[2] = input signature to be processed + * + * This command relates to the PKCS#11 API functions C_VerifyFinal(). + */ + PKCS11_CMD_VERIFY_FINAL = 30, + + /* + * PKCS11_CMD_SIGN_ONESHOT - Compute a signature + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [out] memref[2] = byte array: generated signature + * + * This command relates to the PKCS#11 API function C_Sign(). + */ + PKCS11_CMD_SIGN_ONESHOT = 31, + + /* + * PKCS11_CMD_VERIFY_ONESHOT - Compute and compare a signature + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [in] memref[2] = input signature to be processed + * + * This command relates to the PKCS#11 API function C_Verify(). + */ + PKCS11_CMD_VERIFY_ONESHOT = 32, + + /* + * PKCS11_CMD_GENERATE_KEY - Generate a symmetric key or domain + * parameters + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_attribute_head)mechanism + mecha params, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_GenerateKey(). + */ + PKCS11_CMD_GENERATE_KEY = 33, + + /* + * PKCS11_CMD_FIND_OBJECTS_INIT - Initialize an object search + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_FindOjectsInit(). + */ + PKCS11_CMD_FIND_OBJECTS_INIT = 34, + + /* + * PKCS11_CMD_FIND_OBJECTS - Get handles of matching objects + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit array object_handle_array[N] + * + * This command relates to the PKCS#11 API function C_FindOjects(). + * The size of object_handle_array depends on the size of the output + * buffer provided by the client. + */ + PKCS11_CMD_FIND_OBJECTS = 35, + + /* + * PKCS11_CMD_FIND_OBJECTS_FINAL - Finalize current objects search + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_FindOjectsFinal(). + */ + PKCS11_CMD_FIND_OBJECTS_FINAL = 36, + + /* + * PKCS11_CMD_GET_OBJECT_SIZE - Get byte size used by object in the TEE + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object_byte_size + * + * This command relates to the PKCS#11 API function C_GetObjectSize(). + */ + PKCS11_CMD_GET_OBJECT_SIZE = 37, + + /* + * PKCS11_CMD_GET_ATTRIBUTE_VALUE - Get the value of object attribute(s) + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = (struct pkcs11_object_head)attribs + attributes + * data + * + * This command relates to the PKCS#11 API function C_GetAttributeValue. + * Caller provides an attribute template as 3rd argument in memref[0] + * (referred here as attribs + attributes data). Upon successful + * completion, the TA returns the provided template filled with expected + * data through output argument memref[2] (referred here again as + * attribs + attributes data). + */ + PKCS11_CMD_GET_ATTRIBUTE_VALUE = 38, + + /* + * PKCS11_CMD_SET_ATTRIBUTE_VALUE - Set the value of object attribute(s) + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_SetAttributeValue. + * Caller provides an attribute template as 3rd argument in memref[0] + * (referred here as attribs + attributes data). + */ + PKCS11_CMD_SET_ATTRIBUTE_VALUE = 39, + + /* + * PKCS11_CMD_COPY_OBJECT - Copies an object, creating a new object for + * the copy. + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit object handle, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_CopyObject(). + * Caller provides an attribute template as 3rd argument in memref[0] + * (referred here as attribs + attributes data). + */ + PKCS11_CMD_COPY_OBJECT = 40, + + /* + * PKCS11_CMD_SEED_RANDOM - Seed random data generator + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = byte array: seed material to feed into the RNG + * + * This command relates to the PKCS#11 API function C_SeedRandom(). + */ + PKCS11_CMD_SEED_RANDOM = 41, + + /* + * PKCS11_CMD_GENERATE_RANDOM - Generate random data + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = byte array: generated random + * + * This command relates to the PKCS#11 API function C_GenerateRandom(). + */ + PKCS11_CMD_GENERATE_RANDOM = 42, + + /* + * PKCS11_CMD_DERIVE_KEY - Derive a key from a parent key. + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit parent key handle, + * (struct pkcs11_attribute_head)mechanism + mecha params, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_DeriveKey(). + */ + PKCS11_CMD_DERIVE_KEY = 43, + + /* + * PKCS11_CMD_RELEASE_ACTIVE_PROCESSING - Release active processing + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit enum pkcs11_ta_cmd + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command is used to release active processing in case of + * Cryptoki API invocation error is detected in user space processing. + * Function derived from pkcs11_ta_cmd is used to verify that active + * processing matches. + */ + PKCS11_CMD_RELEASE_ACTIVE_PROCESSING = 44, + + /* + * PKCS11_CMD_DIGEST_INIT - Initialize a digest computation processing + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_attribute_head)mechanism + mecha params + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_DigestInit(). + */ + PKCS11_CMD_DIGEST_INIT = 45, + + /* + * PKCS11_CMD_DIGEST_KEY - Update digest with a key + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit key handle + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * + * This command relates to the PKCS#11 API function C_DigestKey(). + */ + PKCS11_CMD_DIGEST_KEY = 46, + + /* + * PKCS11_CMD_DIGEST_UPDATE - Update digest with data + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * + * This command relates to the PKCS#11 API function C_DigestUpdate(). + */ + PKCS11_CMD_DIGEST_UPDATE = 47, + + /* + * PKCS11_CMD_DIGEST_FINAL - Finalize a digest computation processing + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = output digest + * + * This command relates to the PKCS#11 API function C_DigestFinal(). + */ + PKCS11_CMD_DIGEST_FINAL = 48, + + /* + * PKCS11_CMD_DIGEST_ONESHOT - Compute a digest + * + * [in] memref[0] = 32bit session handle + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = input data to be processed + * [out] memref[2] = byte array: generated digest + * + * This command relates to the PKCS#11 API function C_Digest(). + */ + PKCS11_CMD_DIGEST_ONESHOT = 49, + + /* + * PKCS11_CMD_GENERATE_KEY_PAIR - Generate an asymmetric key pair + * + * [in] memref[0] = [ + * 32bit session handle, + * (struct pkcs11_attribute_head)mechanism + mecha params, + * (struct pkcs11_object_head)public key attribs + + * attributes data, + * (struct pkcs11_object_head)private key attribs + + * attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = [ + * 32bit public key object handle, + * 32bit private key object handle + * ] + * + * This command relates to the PKCS#11 API function + * C_GenerateKeyPair(). + */ + PKCS11_CMD_GENERATE_KEY_PAIR = 50, + + /* + * PKCS11_CMD_WRAP_KEY - Wraps a private or secret key. + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit wrapping key handle, + * 32bit key handle, + * (struct pkcs11_attribute_head)mechanism + mecha params + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [out] memref[2] = wrapped key + * + * This command relates to the PKCS#11 API function C_WrapKey(). + */ + PKCS11_CMD_WRAP_KEY = 51, + + /* + * PKCS11_CMD_UNWRAP_KEY - Unwraps a wrapped key, creating a new + * private or secret key object. + * + * [in] memref[0] = [ + * 32bit session handle, + * 32bit unwrapping key handle, + * (struct pkcs11_attribute_head)mechanism + mecha params, + * (struct pkcs11_object_head)attribs + attributes data + * ] + * [out] memref[0] = 32bit return code, enum pkcs11_rc + * [in] memref[1] = wrapped key + * [out] memref[2] = 32bit object handle + * + * This command relates to the PKCS#11 API function C_UnwrapKey(). + */ + PKCS11_CMD_UNWRAP_KEY = 52, +}; + +/* + * Command return codes + * PKCS11_ relates CryptoKi client API CKR_ + */ +enum pkcs11_rc { + PKCS11_CKR_OK = 0, + PKCS11_CKR_CANCEL = 0x0001, + PKCS11_CKR_SLOT_ID_INVALID = 0x0003, + PKCS11_CKR_GENERAL_ERROR = 0x0005, + PKCS11_CKR_FUNCTION_FAILED = 0x0006, + PKCS11_CKR_ARGUMENTS_BAD = 0x0007, + PKCS11_CKR_ATTRIBUTE_READ_ONLY = 0x0010, + PKCS11_CKR_ATTRIBUTE_SENSITIVE = 0x0011, + PKCS11_CKR_ATTRIBUTE_TYPE_INVALID = 0x0012, + PKCS11_CKR_ATTRIBUTE_VALUE_INVALID = 0x0013, + PKCS11_CKR_ACTION_PROHIBITED = 0x001b, + PKCS11_CKR_DATA_INVALID = 0x0020, + PKCS11_CKR_DATA_LEN_RANGE = 0x0021, + PKCS11_CKR_DEVICE_ERROR = 0x0030, + PKCS11_CKR_DEVICE_MEMORY = 0x0031, + PKCS11_CKR_DEVICE_REMOVED = 0x0032, + PKCS11_CKR_ENCRYPTED_DATA_INVALID = 0x0040, + PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE = 0x0041, + PKCS11_CKR_KEY_HANDLE_INVALID = 0x0060, + PKCS11_CKR_KEY_SIZE_RANGE = 0x0062, + PKCS11_CKR_KEY_TYPE_INCONSISTENT = 0x0063, + PKCS11_CKR_KEY_INDIGESTIBLE = 0x0067, + PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED = 0x0068, + PKCS11_CKR_KEY_NOT_WRAPPABLE = 0x0069, + PKCS11_CKR_KEY_UNEXTRACTABLE = 0x006a, + PKCS11_CKR_MECHANISM_INVALID = 0x0070, + PKCS11_CKR_MECHANISM_PARAM_INVALID = 0x0071, + PKCS11_CKR_OBJECT_HANDLE_INVALID = 0x0082, + PKCS11_CKR_OPERATION_ACTIVE = 0x0090, + PKCS11_CKR_OPERATION_NOT_INITIALIZED = 0x0091, + PKCS11_CKR_PIN_INCORRECT = 0x00a0, + PKCS11_CKR_PIN_INVALID = 0x00a1, + PKCS11_CKR_PIN_LEN_RANGE = 0x00a2, + PKCS11_CKR_PIN_EXPIRED = 0x00a3, + PKCS11_CKR_PIN_LOCKED = 0x00a4, + PKCS11_CKR_SESSION_CLOSED = 0x00b0, + PKCS11_CKR_SESSION_COUNT = 0x00b1, + PKCS11_CKR_SESSION_HANDLE_INVALID = 0x00b3, + PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED = 0x00b4, + PKCS11_CKR_SESSION_READ_ONLY = 0x00b5, + PKCS11_CKR_SESSION_EXISTS = 0x00b6, + PKCS11_CKR_SESSION_READ_ONLY_EXISTS = 0x00b7, + PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS = 0x00b8, + PKCS11_CKR_SIGNATURE_INVALID = 0x00c0, + PKCS11_CKR_SIGNATURE_LEN_RANGE = 0x00c1, + PKCS11_CKR_TEMPLATE_INCOMPLETE = 0x00d0, + PKCS11_CKR_TEMPLATE_INCONSISTENT = 0x00d1, + PKCS11_CKR_TOKEN_NOT_PRESENT = 0x00e0, + PKCS11_CKR_TOKEN_NOT_RECOGNIZED = 0x00e1, + PKCS11_CKR_TOKEN_WRITE_PROTECTED = 0x00e2, + PKCS11_CKR_UNWRAPPING_KEY_HANDLE_INVALID = 0x00f0, + PKCS11_CKR_UNWRAPPING_KEY_SIZE_RANGE = 0x00f1, + PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT = 0x00f2, + PKCS11_CKR_USER_ALREADY_LOGGED_IN = 0x0100, + PKCS11_CKR_USER_NOT_LOGGED_IN = 0x0101, + PKCS11_CKR_USER_PIN_NOT_INITIALIZED = 0x0102, + PKCS11_CKR_USER_TYPE_INVALID = 0x0103, + PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN = 0x0104, + PKCS11_CKR_USER_TOO_MANY_TYPES = 0x0105, + PKCS11_CKR_WRAPPED_KEY_INVALID = 0x0110, + PKCS11_CKR_WRAPPED_KEY_LEN_RANGE = 0x0112, + PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID = 0x0113, + PKCS11_CKR_WRAPPING_KEY_SIZE_RANGE = 0x0114, + PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT = 0x0115, + PKCS11_CKR_RANDOM_SEED_NOT_SUPPORTED = 0x0120, + PKCS11_CKR_RANDOM_NO_RNG = 0x0121, + PKCS11_CKR_DOMAIN_PARAMS_INVALID = 0x0130, + PKCS11_CKR_CURVE_NOT_SUPPORTED = 0x0140, + PKCS11_CKR_BUFFER_TOO_SMALL = 0x0150, + PKCS11_CKR_SAVED_STATE_INVALID = 0x0160, + PKCS11_CKR_INFORMATION_SENSITIVE = 0x0170, + PKCS11_CKR_STATE_UNSAVEABLE = 0x0180, + PKCS11_CKR_PIN_TOO_WEAK = 0x01b8, + PKCS11_CKR_PUBLIC_KEY_INVALID = 0x01b9, + PKCS11_CKR_FUNCTION_REJECTED = 0x0200, + /* Vendor specific IDs not returned to client */ + PKCS11_RV_NOT_FOUND = 0x80000000, + PKCS11_RV_NOT_IMPLEMENTED = 0x80000001, +}; + +/* + * Arguments for PKCS11_CMD_SLOT_INFO + */ +#define PKCS11_SLOT_DESC_SIZE 64 +#define PKCS11_SLOT_MANUFACTURER_SIZE 32 +#define PKCS11_SLOT_VERSION_SIZE 2 + +struct pkcs11_slot_info { + uint8_t slot_description[PKCS11_SLOT_DESC_SIZE]; + uint8_t manufacturer_id[PKCS11_SLOT_MANUFACTURER_SIZE]; + uint32_t flags; + uint8_t hardware_version[PKCS11_SLOT_VERSION_SIZE]; + uint8_t firmware_version[PKCS11_SLOT_VERSION_SIZE]; +}; + +/* + * Values for pkcs11_slot_info::flags. + * PKCS11_CKFS_ reflects CryptoKi client API slot flags CKF_. + */ +#define PKCS11_CKFS_TOKEN_PRESENT (1U << 0) +#define PKCS11_CKFS_REMOVABLE_DEVICE (1U << 1) +#define PKCS11_CKFS_HW_SLOT (1U << 2) + +/* + * Arguments for PKCS11_CMD_TOKEN_INFO + */ +#define PKCS11_TOKEN_LABEL_SIZE 32 +#define PKCS11_TOKEN_MANUFACTURER_SIZE 32 +#define PKCS11_TOKEN_MODEL_SIZE 16 +#define PKCS11_TOKEN_SERIALNUM_SIZE 16 + +struct pkcs11_token_info { + uint8_t label[PKCS11_TOKEN_LABEL_SIZE]; + uint8_t manufacturer_id[PKCS11_TOKEN_MANUFACTURER_SIZE]; + uint8_t model[PKCS11_TOKEN_MODEL_SIZE]; + uint8_t serial_number[PKCS11_TOKEN_SERIALNUM_SIZE]; + uint32_t flags; + uint32_t max_session_count; + uint32_t session_count; + uint32_t max_rw_session_count; + uint32_t rw_session_count; + uint32_t max_pin_len; + uint32_t min_pin_len; + uint32_t total_public_memory; + uint32_t free_public_memory; + uint32_t total_private_memory; + uint32_t free_private_memory; + uint8_t hardware_version[2]; + uint8_t firmware_version[2]; + uint8_t utc_time[16]; +}; + +/* + * Values for pkcs11_token_info::flags. + * PKCS11_CKFT_ reflects CryptoKi client API token flags CKF_. + */ +#define PKCS11_CKFT_RNG (1U << 0) +#define PKCS11_CKFT_WRITE_PROTECTED (1U << 1) +#define PKCS11_CKFT_LOGIN_REQUIRED (1U << 2) +#define PKCS11_CKFT_USER_PIN_INITIALIZED (1U << 3) +#define PKCS11_CKFT_RESTORE_KEY_NOT_NEEDED (1U << 5) +#define PKCS11_CKFT_CLOCK_ON_TOKEN (1U << 6) +#define PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH (1U << 8) +#define PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS (1U << 9) +#define PKCS11_CKFT_TOKEN_INITIALIZED (1U << 10) +#define PKCS11_CKFT_SECONDARY_AUTHENTICATION (1U << 11) +#define PKCS11_CKFT_USER_PIN_COUNT_LOW (1U << 16) +#define PKCS11_CKFT_USER_PIN_FINAL_TRY (1U << 17) +#define PKCS11_CKFT_USER_PIN_LOCKED (1U << 18) +#define PKCS11_CKFT_USER_PIN_TO_BE_CHANGED (1U << 19) +#define PKCS11_CKFT_SO_PIN_COUNT_LOW (1U << 20) +#define PKCS11_CKFT_SO_PIN_FINAL_TRY (1U << 21) +#define PKCS11_CKFT_SO_PIN_LOCKED (1U << 22) +#define PKCS11_CKFT_SO_PIN_TO_BE_CHANGED (1U << 23) +#define PKCS11_CKFT_ERROR_STATE (1U << 24) + +/* Values for user identity */ +enum pkcs11_user_type { + PKCS11_CKU_SO = 0x000, + PKCS11_CKU_USER = 0x001, + PKCS11_CKU_CONTEXT_SPECIFIC = 0x002, +}; + +/* + * TEE Identity based authentication for tokens + * + * When configuration CFG_PKCS11_TA_AUTH_TEE_IDENTITY is enabled TEE Identity + * based authentication scheme is enabled. + * + * Feature enablement per token basis is controlled by token flag: + * pkcs11_token_info->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH + * + * When calling C_InitToken() mode is determined based on SO PIN value. + * - If the PIN is empty (or NULL_PTR) then active client TEE Identity will be + * used as SO TEE Identity + * - If the PIN is given then normal PIN behavior is used + * + * Once TEE Identity based authentication is activated following operational + * changes happen: + * - PIN failure counters are disabled to prevent token authentication lockups + * - When C_Login() or so is performed actual PIN value is ignored and active + * client TEE Identity will be used + * + * After a successful call to C_InitToken(), one can switch authentication + * mode as user credentials have been cleared. After user credentials has been + * set authentication mode switching is protected. + * + * To switch the authentication mode from PIN to TEE Identity: + * - Make sure active TEE Identity is set for the TA connection + * - Login as SO so that PIN change affects SO + * - Call C_SetPIN() with empty PIN to capture current TEE Identity as SO + * credential + * - Optional: Successive call to C_SetPIN() can be used for change to other + * TEE Identity vs. current TA connection + * + * To switch the authentication mode from TEE Identity to PIN: + * - Make sure SO's TEE Identity is set for the TA connection + * - Login as SO so that PIN change affects SO + * - Call C_SetPIN() with any PIN that does not match TEE Identity PIN syntax + * - Optional: Successive call to C_SetPIN() can be used to change SO + * credential to any valid PIN if there was collision with TEE Identity PIN + * syntax + * + * Different types of TEE Identity authentication methods can be configured: + * - Configured with C_InitToken(), C_InitPIN() or by C_SetPIN() + * - PIN value follows below PIN syntax + * + * TEE Identity based authenticate PIN syntax: + * - PIN value: NULL_PTR or empty + * - Use active client TEE Identity + * - PIN value: public + * - TEE public login + * - PIN value: user: + * - TEE user login with client UUID matching user credentials + * - PIN value: group: + * - TEE group login with client UUID matching group credentials + */ + +/* Keywords for protected authenticated path PIN parser */ +#define PKCS11_AUTH_TEE_IDENTITY_PUBLIC "public" +#define PKCS11_AUTH_TEE_IDENTITY_USER "user:" +#define PKCS11_AUTH_TEE_IDENTITY_GROUP "group:" + +/* + * Values for 32bit session flags argument to PKCS11_CMD_OPEN_SESSION + * and pkcs11_session_info::flags. + * PKCS11_CKFSS_ reflects CryptoKi client API session flags CKF_. + */ +#define PKCS11_CKFSS_RW_SESSION (1U << 1) +#define PKCS11_CKFSS_SERIAL_SESSION (1U << 2) + +/* + * Arguments for PKCS11_CMD_SESSION_INFO + */ + +struct pkcs11_session_info { + uint32_t slot_id; + uint32_t state; + uint32_t flags; + uint32_t device_error; +}; + +/* Valid values for pkcs11_session_info::state */ +enum pkcs11_session_state { + PKCS11_CKS_RO_PUBLIC_SESSION = 0, + PKCS11_CKS_RO_USER_FUNCTIONS = 1, + PKCS11_CKS_RW_PUBLIC_SESSION = 2, + PKCS11_CKS_RW_USER_FUNCTIONS = 3, + PKCS11_CKS_RW_SO_FUNCTIONS = 4, +}; + +/* + * Arguments for PKCS11_CMD_MECHANISM_INFO + */ + +struct pkcs11_mechanism_info { + uint32_t min_key_size; + uint32_t max_key_size; + uint32_t flags; +}; + +/* + * Values for pkcs11_mechanism_info::flags. + * PKCS11_CKFM_ reflects CryptoKi client API mechanism flags CKF_. + */ +#define PKCS11_CKFM_HW (1U << 0) +#define PKCS11_CKFM_ENCRYPT (1U << 8) +#define PKCS11_CKFM_DECRYPT (1U << 9) +#define PKCS11_CKFM_DIGEST (1U << 10) +#define PKCS11_CKFM_SIGN (1U << 11) +#define PKCS11_CKFM_SIGN_RECOVER (1U << 12) +#define PKCS11_CKFM_VERIFY (1U << 13) +#define PKCS11_CKFM_VERIFY_RECOVER (1U << 14) +#define PKCS11_CKFM_GENERATE (1U << 15) +#define PKCS11_CKFM_GENERATE_KEY_PAIR (1U << 16) +#define PKCS11_CKFM_WRAP (1U << 17) +#define PKCS11_CKFM_UNWRAP (1U << 18) +#define PKCS11_CKFM_DERIVE (1U << 19) +#define PKCS11_CKFM_EC_F_P (1U << 20) +#define PKCS11_CKFM_EC_F_2M (1U << 21) +#define PKCS11_CKFM_EC_ECPARAMETERS (1U << 22) +#define PKCS11_CKFM_EC_NAMEDCURVE (1U << 23) +#define PKCS11_CKFM_EC_UNCOMPRESS (1U << 24) +#define PKCS11_CKFM_EC_COMPRESS (1U << 25) + +/* + * pkcs11_object_head - Header of object whose data are serialized in memory + * + * An object is made of several attributes. Attributes are stored one next to + * the other with byte alignment as a serialized byte array. The byte array + * of serialized attributes is prepended with the size of the attrs[] array + * in bytes and the number of attributes in the array, yielding the struct + * pkcs11_object_head. + * + * @attrs_size - byte size of whole byte array attrs[] + * @attrs_count - number of attribute items stored in attrs[] + * @attrs - then starts the attributes data + */ +struct pkcs11_object_head { + uint32_t attrs_size; + uint32_t attrs_count; + uint8_t attrs[]; +}; + +/* + * Attribute reference in the TA ABI. Each attribute starts with a header + * structure followed by the attribute value. The attribute byte size is + * defined in the attribute header. + * + * @id - the 32bit identifier of the attribute, see PKCS11_CKA_ + * @size - the 32bit value attribute byte size + * @data - then starts the attribute value + */ +struct pkcs11_attribute_head { + uint32_t id; + uint32_t size; + uint8_t data[]; +}; + +/* + * Attribute identification IDs as of v2.40 excluding deprecated IDs. + * Valid values for struct pkcs11_attribute_head::id + * PKCS11_CKA_ reflects CryptoKi client API attribute IDs CKA_. + */ +enum pkcs11_attr_id { + PKCS11_CKA_CLASS = 0x0000, + PKCS11_CKA_TOKEN = 0x0001, + PKCS11_CKA_PRIVATE = 0x0002, + PKCS11_CKA_LABEL = 0x0003, + PKCS11_CKA_APPLICATION = 0x0010, + PKCS11_CKA_VALUE = 0x0011, + PKCS11_CKA_OBJECT_ID = 0x0012, + PKCS11_CKA_CERTIFICATE_TYPE = 0x0080, + PKCS11_CKA_ISSUER = 0x0081, + PKCS11_CKA_SERIAL_NUMBER = 0x0082, + PKCS11_CKA_AC_ISSUER = 0x0083, + PKCS11_CKA_OWNER = 0x0084, + PKCS11_CKA_ATTR_TYPES = 0x0085, + PKCS11_CKA_TRUSTED = 0x0086, + PKCS11_CKA_CERTIFICATE_CATEGORY = 0x0087, + PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN = 0x0088, + PKCS11_CKA_URL = 0x0089, + PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY = 0x008a, + PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY = 0x008b, + PKCS11_CKA_NAME_HASH_ALGORITHM = 0x008c, + PKCS11_CKA_CHECK_VALUE = 0x0090, + PKCS11_CKA_KEY_TYPE = 0x0100, + PKCS11_CKA_SUBJECT = 0x0101, + PKCS11_CKA_ID = 0x0102, + PKCS11_CKA_SENSITIVE = 0x0103, + PKCS11_CKA_ENCRYPT = 0x0104, + PKCS11_CKA_DECRYPT = 0x0105, + PKCS11_CKA_WRAP = 0x0106, + PKCS11_CKA_UNWRAP = 0x0107, + PKCS11_CKA_SIGN = 0x0108, + PKCS11_CKA_SIGN_RECOVER = 0x0109, + PKCS11_CKA_VERIFY = 0x010a, + PKCS11_CKA_VERIFY_RECOVER = 0x010b, + PKCS11_CKA_DERIVE = 0x010c, + PKCS11_CKA_START_DATE = 0x0110, + PKCS11_CKA_END_DATE = 0x0111, + PKCS11_CKA_MODULUS = 0x0120, + PKCS11_CKA_MODULUS_BITS = 0x0121, + PKCS11_CKA_PUBLIC_EXPONENT = 0x0122, + PKCS11_CKA_PRIVATE_EXPONENT = 0x0123, + PKCS11_CKA_PRIME_1 = 0x0124, + PKCS11_CKA_PRIME_2 = 0x0125, + PKCS11_CKA_EXPONENT_1 = 0x0126, + PKCS11_CKA_EXPONENT_2 = 0x0127, + PKCS11_CKA_COEFFICIENT = 0x0128, + PKCS11_CKA_PUBLIC_KEY_INFO = 0x0129, + PKCS11_CKA_PRIME = 0x0130, + PKCS11_CKA_SUBPRIME = 0x0131, + PKCS11_CKA_BASE = 0x0132, + PKCS11_CKA_PRIME_BITS = 0x0133, + PKCS11_CKA_SUBPRIME_BITS = 0x0134, + PKCS11_CKA_VALUE_BITS = 0x0160, + PKCS11_CKA_VALUE_LEN = 0x0161, + PKCS11_CKA_EXTRACTABLE = 0x0162, + PKCS11_CKA_LOCAL = 0x0163, + PKCS11_CKA_NEVER_EXTRACTABLE = 0x0164, + PKCS11_CKA_ALWAYS_SENSITIVE = 0x0165, + PKCS11_CKA_KEY_GEN_MECHANISM = 0x0166, + PKCS11_CKA_MODIFIABLE = 0x0170, + PKCS11_CKA_COPYABLE = 0x0171, + PKCS11_CKA_DESTROYABLE = 0x0172, + PKCS11_CKA_EC_PARAMS = 0x0180, + PKCS11_CKA_EC_POINT = 0x0181, + PKCS11_CKA_ALWAYS_AUTHENTICATE = 0x0202, + PKCS11_CKA_WRAP_WITH_TRUSTED = 0x0210, + /* + * The leading 4 comes from the PKCS#11 spec or:ing with + * CKF_ARRAY_ATTRIBUTE = 0x40000000. + */ + PKCS11_CKA_WRAP_TEMPLATE = 0x40000211, + PKCS11_CKA_UNWRAP_TEMPLATE = 0x40000212, + PKCS11_CKA_DERIVE_TEMPLATE = 0x40000213, + PKCS11_CKA_OTP_FORMAT = 0x0220, + PKCS11_CKA_OTP_LENGTH = 0x0221, + PKCS11_CKA_OTP_TIME_INTERVAL = 0x0222, + PKCS11_CKA_OTP_USER_FRIENDLY_MODE = 0x0223, + PKCS11_CKA_OTP_CHALLENGE_REQUIREMENT = 0x0224, + PKCS11_CKA_OTP_TIME_REQUIREMENT = 0x0225, + PKCS11_CKA_OTP_COUNTER_REQUIREMENT = 0x0226, + PKCS11_CKA_OTP_PIN_REQUIREMENT = 0x0227, + PKCS11_CKA_OTP_COUNTER = 0x022e, + PKCS11_CKA_OTP_TIME = 0x022f, + PKCS11_CKA_OTP_USER_IDENTIFIER = 0x022a, + PKCS11_CKA_OTP_SERVICE_IDENTIFIER = 0x022b, + PKCS11_CKA_OTP_SERVICE_LOGO = 0x022c, + PKCS11_CKA_OTP_SERVICE_LOGO_TYPE = 0x022d, + PKCS11_CKA_GOSTR3410_PARAMS = 0x0250, + PKCS11_CKA_GOSTR3411_PARAMS = 0x0251, + PKCS11_CKA_GOST28147_PARAMS = 0x0252, + PKCS11_CKA_HW_FEATURE_TYPE = 0x0300, + PKCS11_CKA_RESET_ON_INIT = 0x0301, + PKCS11_CKA_HAS_RESET = 0x0302, + PKCS11_CKA_PIXEL_X = 0x0400, + PKCS11_CKA_PIXEL_Y = 0x0401, + PKCS11_CKA_RESOLUTION = 0x0402, + PKCS11_CKA_CHAR_ROWS = 0x0403, + PKCS11_CKA_CHAR_COLUMNS = 0x0404, + PKCS11_CKA_COLOR = 0x0405, + PKCS11_CKA_BITS_PER_PIXEL = 0x0406, + PKCS11_CKA_CHAR_SETS = 0x0480, + PKCS11_CKA_ENCODING_METHODS = 0x0481, + PKCS11_CKA_MIME_TYPES = 0x0482, + PKCS11_CKA_MECHANISM_TYPE = 0x0500, + PKCS11_CKA_REQUIRED_CMS_ATTRIBUTES = 0x0501, + PKCS11_CKA_DEFAULT_CMS_ATTRIBUTES = 0x0502, + PKCS11_CKA_SUPPORTED_CMS_ATTRIBUTES = 0x0503, + /* + * The leading 4 comes from the PKCS#11 spec or:ing with + * CKF_ARRAY_ATTRIBUTE = 0x40000000. + */ + PKCS11_CKA_ALLOWED_MECHANISMS = 0x40000600, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKA_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for attribute PKCS11_CKA_CLASS + * PKCS11_CKO_ reflects CryptoKi client API object class IDs CKO_. + */ +enum pkcs11_class_id { + PKCS11_CKO_DATA = 0x000, + PKCS11_CKO_CERTIFICATE = 0x001, + PKCS11_CKO_PUBLIC_KEY = 0x002, + PKCS11_CKO_PRIVATE_KEY = 0x003, + PKCS11_CKO_SECRET_KEY = 0x004, + PKCS11_CKO_HW_FEATURE = 0x005, + PKCS11_CKO_DOMAIN_PARAMETERS = 0x006, + PKCS11_CKO_MECHANISM = 0x007, + PKCS11_CKO_OTP_KEY = 0x008, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKO_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for attribute PKCS11_CKA_KEY_TYPE + * PKCS11_CKK_ reflects CryptoKi client API key type IDs CKK_. + * Note that this is only a subset of the PKCS#11 specification. + */ +enum pkcs11_key_type { + PKCS11_CKK_RSA = 0x000, + PKCS11_CKK_DSA = 0x001, + PKCS11_CKK_DH = 0x002, + PKCS11_CKK_EC = 0x003, + PKCS11_CKK_EDDSA = 0x004, + PKCS11_CKK_GENERIC_SECRET = 0x010, + PKCS11_CKK_AES = 0x01f, + PKCS11_CKK_MD5_HMAC = 0x027, + PKCS11_CKK_SHA_1_HMAC = 0x028, + PKCS11_CKK_SHA256_HMAC = 0x02b, + PKCS11_CKK_SHA384_HMAC = 0x02c, + PKCS11_CKK_SHA512_HMAC = 0x02d, + PKCS11_CKK_SHA224_HMAC = 0x02e, + PKCS11_CKK_EC_EDWARDS = 0x040, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKK_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for attribute PKCS11_CKA_CERTIFICATE_TYPE + */ +enum pkcs11_certificate_type { + PKCS11_CKC_X_509 = 0x00000000UL, + PKCS11_CKC_X_509_ATTR_CERT = 0x00000001UL, + PKCS11_CKC_WTLS = 0x00000002UL, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKC_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for attribute PKCS11_CKA_CERTIFICATE_CATEGORY + */ +enum pkcs11_certificate_category { + PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0UL, + PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1UL, + PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY = 2UL, + PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 3UL, +}; + +/* + * Valid values for mechanism IDs + * PKCS11_CKM_ reflects CryptoKi client API mechanism IDs CKM_. + * Note that this will be extended as needed. + */ +enum pkcs11_mechanism_id { + PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000, + PKCS11_CKM_RSA_PKCS = 0x00001, + PKCS11_CKM_MD5_RSA_PKCS = 0x00005, + PKCS11_CKM_SHA1_RSA_PKCS = 0x00006, + PKCS11_CKM_RSA_PKCS_OAEP = 0x00009, + PKCS11_CKM_RSA_PKCS_PSS = 0x0000d, + PKCS11_CKM_SHA1_RSA_PKCS_PSS = 0x0000e, + PKCS11_CKM_SHA256_RSA_PKCS = 0x00040, + PKCS11_CKM_SHA384_RSA_PKCS = 0x00041, + PKCS11_CKM_SHA512_RSA_PKCS = 0x00042, + PKCS11_CKM_SHA256_RSA_PKCS_PSS = 0x00043, + PKCS11_CKM_SHA384_RSA_PKCS_PSS = 0x00044, + PKCS11_CKM_SHA512_RSA_PKCS_PSS = 0x00045, + PKCS11_CKM_SHA224_RSA_PKCS = 0x00046, + PKCS11_CKM_SHA224_RSA_PKCS_PSS = 0x00047, + PKCS11_CKM_MD5 = 0x00210, + PKCS11_CKM_MD5_HMAC = 0x00211, + PKCS11_CKM_MD5_HMAC_GENERAL = 0x00212, + PKCS11_CKM_SHA_1 = 0x00220, + PKCS11_CKM_SHA_1_HMAC = 0x00221, + PKCS11_CKM_SHA_1_HMAC_GENERAL = 0x00222, + PKCS11_CKM_SHA256 = 0x00250, + PKCS11_CKM_SHA256_HMAC = 0x00251, + PKCS11_CKM_SHA256_HMAC_GENERAL = 0x00252, + PKCS11_CKM_SHA224 = 0x00255, + PKCS11_CKM_SHA224_HMAC = 0x00256, + PKCS11_CKM_SHA224_HMAC_GENERAL = 0x00257, + PKCS11_CKM_SHA384 = 0x00260, + PKCS11_CKM_SHA384_HMAC = 0x00261, + PKCS11_CKM_SHA384_HMAC_GENERAL = 0x00262, + PKCS11_CKM_SHA512 = 0x00270, + PKCS11_CKM_SHA512_HMAC = 0x00271, + PKCS11_CKM_SHA512_HMAC_GENERAL = 0x00272, + PKCS11_CKM_GENERIC_SECRET_KEY_GEN = 0x00350, + PKCS11_CKM_EC_KEY_PAIR_GEN = 0x01040, + PKCS11_CKM_ECDSA = 0x01041, + PKCS11_CKM_ECDSA_SHA1 = 0x01042, + PKCS11_CKM_ECDSA_SHA224 = 0x01043, + PKCS11_CKM_ECDSA_SHA256 = 0x01044, + PKCS11_CKM_ECDSA_SHA384 = 0x01045, + PKCS11_CKM_ECDSA_SHA512 = 0x01046, + PKCS11_CKM_ECDH1_DERIVE = 0x01050, + PKCS11_CKM_RSA_AES_KEY_WRAP = 0x01054, + PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN = 0x01055, + PKCS11_CKM_EDDSA = 0x01057, + PKCS11_CKM_AES_KEY_GEN = 0x01080, + PKCS11_CKM_AES_ECB = 0x01081, + PKCS11_CKM_AES_CBC = 0x01082, + PKCS11_CKM_AES_CBC_PAD = 0x01085, + PKCS11_CKM_AES_CTR = 0x01086, + PKCS11_CKM_AES_CTS = 0x01089, + PKCS11_CKM_AES_CMAC = 0x0108a, + PKCS11_CKM_AES_CMAC_GENERAL = 0x0108b, + PKCS11_CKM_AES_ECB_ENCRYPT_DATA = 0x01104, + PKCS11_CKM_AES_CBC_ENCRYPT_DATA = 0x01105, + /* + * Vendor extensions below. + * PKCS11 added IDs for operation not related to a CK mechanism ID + */ + PKCS11_PROCESSING_IMPORT = 0x80000000, + PKCS11_CKM_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * PKCS11_CKD_ reflects CryptoKi client API key diff function IDs CKD_. + */ +enum pkcs11_keydiff_id { + PKCS11_CKD_NULL = 0x0001, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKD_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values MG function identifiers + * PKCS11_CKG_ reflects CryptoKi client API MG function IDs CKG_. + */ +enum pkcs11_mgf_id { + PKCS11_CKG_MGF1_SHA1 = 0x0001, + PKCS11_CKG_MGF1_SHA224 = 0x0005, + PKCS11_CKG_MGF1_SHA256 = 0x0002, + PKCS11_CKG_MGF1_SHA384 = 0x0003, + PKCS11_CKG_MGF1_SHA512 = 0x0004, + /* Vendor extension: reserved for undefined ID (~0U) */ + PKCS11_CKG_UNDEFINED_ID = PKCS11_UNDEFINED_ID, +}; + +/* + * Valid values for RSA PKCS/OAEP source type identifier + * PKCS11_CKZ_ reflects CryptoKi client API source type IDs CKZ_. + */ +#define PKCS11_CKZ_DATA_SPECIFIED 0x0001 + +#endif /*PKCS11_TA_H*/ diff --git a/optee/optee_os/ta/pkcs11/scripts/dump_ec_curve_params.sh b/optee/optee_os/ta/pkcs11/scripts/dump_ec_curve_params.sh new file mode 100755 index 0000000..61709db --- /dev/null +++ b/optee/optee_os/ta/pkcs11/scripts/dump_ec_curve_params.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-2-Clause + +EC_CURVES="prime192v1 secp224r1 prime256v1 secp384r1 secp521r1" + +echo "/*" +echo " * DER encoded EC parameters generated with script:" +echo " * ta/pkcs11/scripts/dump_ec_params.sh" +echo " */" +echo "" + +for EC_CURVE in ${EC_CURVES} ; do + echo "static const uint8_t ${EC_CURVE}_name_der[] = {" + openssl ecparam -name ${EC_CURVE} -param_enc named_curve | \ + openssl asn1parse -noout -out /dev/stdout | \ + hexdump -v -e '/8 "\t"' -e '/1 "0x%02x, " ' -e '/8 "\n"' | \ + sed 's/0x ,//g' + echo "};" + echo "" +done + +for EC_CURVE in ${EC_CURVES} ; do + echo "static const uint8_t ${EC_CURVE}_oid_der[] = {" + openssl ecparam -name ${EC_CURVE} -param_enc explicit | \ + openssl asn1parse -noout -out /dev/stdout | \ + hexdump -v -e '/8 "\t"' -e '/1 "0x%02x, " ' -e '/8 "\n"' | \ + sed 's/0x ,//g' + echo "};" + echo "" +done diff --git a/optee/optee_os/ta/pkcs11/scripts/verify-helpers.sh b/optee/optee_os/ta/pkcs11/scripts/verify-helpers.sh new file mode 100755 index 0000000..32b8da2 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/scripts/verify-helpers.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# SPDX-License-Identifier: BSD-2-Clause + +SHOW_DETAILS=1 +ERRORS="" +basepath="$(dirname $(dirname $(readlink -f "$0")))" + +details () [[ ${SHOW_DETAILS} -ne 0 ]] + +verify_enum () { + PREFIX=$1 + SYMBOL_LIST="$(grep PKCS11\_$PREFIX\_ ${basepath}/include/pkcs11_ta.h | cut -f2 | cut '-d ' -f1)" + details && echo -e "\e[4m${PREFIX}\e[0m" + details && echo "" + details && echo -e "symbol\tuses\tstatus" + for symbol in $SYMBOL_LIST ; do + details && echo -n "$symbol" + COUNT="$(grep ${symbol} ${basepath}/src/* | wc -l)" + details && echo -n -e "\t${COUNT}\t" + PRESENT="$(grep PKCS11_ID.*\($symbol.*\) ${basepath}/src/pkcs11_helpers.c | wc -l)" + if [ ${PRESENT} -ne 0 ] ; then + details && echo -e "\e[32mOK\e[0m" + elif [ $COUNT -eq 0 ] ; then + details && echo -e "\e[33mmissing but unused\e[0m" + else + details && echo -e "\e[31mMISSING!\e[0m" + ERRORS+=" ${symbol}" + fi + done + details && echo "" +} + +verify_define () { + PREFIX=$1 + SYMBOL_LIST="$(grep PKCS11\_$PREFIX\_ ${basepath}/include/pkcs11_ta.h | grep ^#define | cut '-d ' -f2 | cut -f1)" + details && echo -e "\e[4m${PREFIX}\e[0m" + details && echo "" + details && echo -e "symbol\tuses\tstatus" + for symbol in $SYMBOL_LIST ; do + details && echo -n "$symbol" + COUNT="$(grep ${symbol} ${basepath}/src/* | wc -l)" + details && echo -n -e "\t${COUNT}\t" + PRESENT="$(grep PKCS11_ID.*\($symbol.*\) ${basepath}/src/pkcs11_helpers.c | wc -l)" + if [ ${PRESENT} -ne 0 ] ; then + details && echo -e "\e[32mOK\e[0m" + elif [ $COUNT -eq 0 ] ; then + details && echo -e "\e[33mmissing but unused\e[0m" + else + details && echo -e "\e[31mMISSING!\e[0m" + ERRORS+=" ${symbol}" + fi + done + details && echo "" +} + +usage() { + SCR=$(basename "$0") + echo "Usage: $SCR Verify that helpers are up to date" + echo " $SCR --quiet Only print errors" + echo " $SCR --help This help" + echo "" + echo "Verification checks that all PKCS11_* enums or defines from \ +include/pkcs11_ta.h are either present in src/pkcs11_helpers.c or not used at \ +all." + exit 1 +} + +while [[ $# -gt 0 ]]; do + arg="$1" + shift + + case $arg in + -q|--quiet) + SHOW_DETAILS=0 + ;; + -h|--help) + usage + ;; + *) + echo "error: invalid argument: ${arg}" 1>&2 + exit 1 + esac +done + +# check that symbols exists +verify_enum CKA +verify_define CKFS +verify_define CKFT +verify_define CKFSS +verify_enum CKS +verify_enum CKR +verify_enum CKO +verify_enum CKK + +if [ -n "${ERRORS}" ] ; then + SCR=$(basename "$0") + for symbol in $ERRORS ; do + echo "${SCR}: error: missing symbol ${symbol} in ${basepath}/src/pkcs11_helpers.c" 1>&2 + done + exit 1 +fi + +exit 0 diff --git a/optee/optee_os/ta/pkcs11/src/attributes.c b/optee/optee_os/ta/pkcs11/src/attributes.c new file mode 100644 index 0000000..af2d5a7 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/attributes.c @@ -0,0 +1,457 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "pkcs11_helpers.h" +#include "serializer.h" + +enum pkcs11_rc init_attributes_head(struct obj_attrs **head) +{ + *head = TEE_Malloc(sizeof(**head), TEE_MALLOC_FILL_ZERO); + if (!*head) + return PKCS11_CKR_DEVICE_MEMORY; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc add_attribute(struct obj_attrs **head, uint32_t attribute, + void *data, size_t size) +{ + size_t buf_len = sizeof(struct obj_attrs) + (*head)->attrs_size; + char **bstart = (void *)head; + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint32_t data32 = 0; + + data32 = attribute; + rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t)); + if (rc) + return rc; + + data32 = size; + rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialize(bstart, &buf_len, data, size); + if (rc) + return rc; + + /* Alloced buffer is always well aligned */ + head = (void *)bstart; + (*head)->attrs_size += 2 * sizeof(uint32_t) + size; + (*head)->attrs_count++; + + return rc; +} + +static enum pkcs11_rc _remove_attribute(struct obj_attrs **head, + uint32_t attribute, bool empty) +{ + struct obj_attrs *h = *head; + char *cur = NULL; + char *end = NULL; + size_t next_off = 0; + + /* Let's find the target attribute */ + cur = (char *)h + sizeof(struct obj_attrs); + end = cur + h->attrs_size; + for (; cur < end; cur += next_off) { + struct pkcs11_attribute_head pkcs11_ref = { }; + + TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); + next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; + + if (pkcs11_ref.id != attribute) + continue; + + if (empty && pkcs11_ref.size) + return PKCS11_CKR_FUNCTION_FAILED; + + TEE_MemMove(cur, cur + next_off, end - (cur + next_off)); + + h->attrs_count--; + h->attrs_size -= next_off; + end -= next_off; + next_off = 0; + + return PKCS11_CKR_OK; + } + + DMSG("Attribute %s (%#x) not found", id2str_attr(attribute), attribute); + return PKCS11_RV_NOT_FOUND; +} + +enum pkcs11_rc remove_empty_attribute(struct obj_attrs **head, + uint32_t attribute) +{ + return _remove_attribute(head, attribute, true /* empty */); +} + +void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute, + void **attr, uint32_t *attr_size, size_t *count) +{ + char *cur = (char *)head + sizeof(struct obj_attrs); + char *end = cur + head->attrs_size; + size_t next_off = 0; + size_t max_found = *count; + size_t found = 0; + void **attr_ptr = attr; + uint32_t *attr_size_ptr = attr_size; + + for (; cur < end; cur += next_off) { + /* Structure aligned copy of the pkcs11_ref in the object */ + struct pkcs11_attribute_head pkcs11_ref = { }; + + TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); + next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; + + if (pkcs11_ref.id != attribute) + continue; + + found++; + + if (!max_found) + continue; /* only count matching attributes */ + + if (attr) { + if (pkcs11_ref.size) + *attr_ptr++ = cur + sizeof(pkcs11_ref); + else + *attr_ptr++ = NULL; + } + + if (attr_size) + *attr_size_ptr++ = pkcs11_ref.size; + + if (found == max_found) + break; + } + + /* Sanity */ + if (cur > end) { + DMSG("Exceeding serial object length"); + TEE_Panic(0); + } + + *count = found; +} + +enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute, + void **attr_ptr, uint32_t *attr_size) +{ + size_t count = 1; + + get_attribute_ptrs(head, attribute, attr_ptr, attr_size, &count); + + if (!count) + return PKCS11_RV_NOT_FOUND; + + if (count != 1) + return PKCS11_CKR_GENERAL_ERROR; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute, + void *attr, uint32_t *attr_size) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + void *attr_ptr = NULL; + uint32_t size = 0; + + rc = get_attribute_ptr(head, attribute, &attr_ptr, &size); + if (rc) + return rc; + + if (attr_size && *attr_size < size) { + *attr_size = size; + /* This reuses buffer-to-small for any bad size matching */ + return PKCS11_CKR_BUFFER_TOO_SMALL; + } + + if (attr) + TEE_MemMove(attr, attr_ptr, size); + + if (attr_size) + *attr_size = size; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc set_attribute(struct obj_attrs **head, uint32_t attribute, + void *data, size_t size) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = _remove_attribute(head, attribute, false); + if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) + return rc; + + return add_attribute(head, attribute, data, size); +} + +enum pkcs11_rc modify_attributes_list(struct obj_attrs **dst, + struct obj_attrs *head) +{ + char *cur = (char *)head + sizeof(struct obj_attrs); + char *end = cur + head->attrs_size; + size_t len = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + for (; cur < end; cur += len) { + struct pkcs11_attribute_head *cli_ref = (void *)cur; + /* Structure aligned copy of the pkcs11_ref in the object */ + struct pkcs11_attribute_head cli_head = { }; + + TEE_MemMove(&cli_head, cur, sizeof(cli_head)); + len = sizeof(cli_head) + cli_head.size; + + rc = set_attribute(dst, cli_head.id, + cli_head.size ? cli_ref->data : NULL, + cli_head.size); + if (rc) + return rc; + } + + return PKCS11_CKR_OK; +} + +bool get_bool(struct obj_attrs *head, uint32_t attribute) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint8_t bbool = 0; + uint32_t size = sizeof(bbool); + + rc = get_attribute(head, attribute, &bbool, &size); + + if (rc == PKCS11_RV_NOT_FOUND) + return false; + + assert(rc == PKCS11_CKR_OK); + return bbool; +} + +bool attributes_match_reference(struct obj_attrs *candidate, + struct obj_attrs *ref) +{ + size_t count = ref->attrs_count; + unsigned char *ref_attr = ref->attrs; + uint32_t rc = PKCS11_CKR_GENERAL_ERROR; + + if (!ref->attrs_count) { + DMSG("Empty reference match all"); + return true; + } + + for (count = 0; count < ref->attrs_count; count++) { + struct pkcs11_attribute_head pkcs11_ref = { }; + void *value = NULL; + uint32_t size = 0; + + TEE_MemMove(&pkcs11_ref, ref_attr, sizeof(pkcs11_ref)); + + rc = get_attribute_ptr(candidate, pkcs11_ref.id, &value, &size); + + if (rc || !value || size != pkcs11_ref.size || + TEE_MemCompare(ref_attr + sizeof(pkcs11_ref), value, size)) + return false; + + ref_attr += sizeof(pkcs11_ref) + pkcs11_ref.size; + } + + return true; +} + +enum pkcs11_rc attributes_match_add_reference(struct obj_attrs **head, + struct obj_attrs *ref) +{ + size_t count = ref->attrs_count; + unsigned char *ref_attr = ref->attrs; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + if (!ref->attrs_count) + return PKCS11_CKR_OK; + + for (count = 0; count < ref->attrs_count; count++) { + struct pkcs11_attribute_head pkcs11_ref = { }; + void *value = NULL; + uint32_t size = 0; + + TEE_MemMove(&pkcs11_ref, ref_attr, sizeof(pkcs11_ref)); + + rc = get_attribute_ptr(*head, pkcs11_ref.id, &value, &size); + if (rc == PKCS11_RV_NOT_FOUND) { + rc = add_attribute(head, pkcs11_ref.id, + ref_attr + sizeof(pkcs11_ref), + pkcs11_ref.size); + if (rc) + return rc; + } else { + if (rc || !value || size != pkcs11_ref.size || + TEE_MemCompare(ref_attr + sizeof(pkcs11_ref), value, + size)) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + ref_attr += sizeof(pkcs11_ref) + pkcs11_ref.size; + } + + return PKCS11_CKR_OK; +} + +#if CFG_TEE_TA_LOG_LEVEL > 0 +/* + * Debug: dump CK attribute array to output trace + */ +#define ATTR_TRACE_FMT "%s attr %s / %s\t(0x%04"PRIx32" %"PRIu32"-byte" +#define ATTR_FMT_0BYTE ATTR_TRACE_FMT ")" +#define ATTR_FMT_1BYTE ATTR_TRACE_FMT ": %02x)" +#define ATTR_FMT_2BYTE ATTR_TRACE_FMT ": %02x %02x)" +#define ATTR_FMT_3BYTE ATTR_TRACE_FMT ": %02x %02x %02x)" +#define ATTR_FMT_4BYTE ATTR_TRACE_FMT ": %02x %02x %02x %02x)" +#define ATTR_FMT_ARRAY ATTR_TRACE_FMT ": %02x %02x %02x %02x ...)" + +static void __trace_attributes(char *prefix, void *src, void *end) +{ + size_t next_off = 0; + char *prefix2 = NULL; + size_t prefix_len = strlen(prefix); + char *cur = src; + + /* append 4 spaces to the prefix plus terminal '\0' */ + prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO); + if (!prefix2) + return; + + TEE_MemMove(prefix2, prefix, prefix_len + 1); + TEE_MemFill(prefix2 + prefix_len, ' ', 4); + *(prefix2 + prefix_len + 4) = '\0'; + + for (; cur < (char *)end; cur += next_off) { + struct pkcs11_attribute_head pkcs11_ref = { }; + uint8_t data[4] = { 0 }; + + TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); + TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref), + MIN(pkcs11_ref.size, sizeof(data))); + + next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; + + switch (pkcs11_ref.size) { + case 0: + IMSG_RAW(ATTR_FMT_0BYTE, + prefix, id2str_attr(pkcs11_ref.id), "*", + pkcs11_ref.id, pkcs11_ref.size); + break; + case 1: + IMSG_RAW(ATTR_FMT_1BYTE, + prefix, id2str_attr(pkcs11_ref.id), + id2str_attr_value(pkcs11_ref.id, + pkcs11_ref.size, + cur + sizeof(pkcs11_ref)), + pkcs11_ref.id, pkcs11_ref.size, data[0]); + break; + case 2: + IMSG_RAW(ATTR_FMT_2BYTE, + prefix, id2str_attr(pkcs11_ref.id), + id2str_attr_value(pkcs11_ref.id, + pkcs11_ref.size, + cur + sizeof(pkcs11_ref)), + pkcs11_ref.id, pkcs11_ref.size, data[0], + data[1]); + break; + case 3: + IMSG_RAW(ATTR_FMT_3BYTE, + prefix, id2str_attr(pkcs11_ref.id), + id2str_attr_value(pkcs11_ref.id, + pkcs11_ref.size, + cur + sizeof(pkcs11_ref)), + pkcs11_ref.id, pkcs11_ref.size, + data[0], data[1], data[2]); + break; + case 4: + IMSG_RAW(ATTR_FMT_4BYTE, + prefix, id2str_attr(pkcs11_ref.id), + id2str_attr_value(pkcs11_ref.id, + pkcs11_ref.size, + cur + sizeof(pkcs11_ref)), + pkcs11_ref.id, pkcs11_ref.size, + data[0], data[1], data[2], data[3]); + break; + default: + IMSG_RAW(ATTR_FMT_ARRAY, + prefix, id2str_attr(pkcs11_ref.id), + id2str_attr_value(pkcs11_ref.id, + pkcs11_ref.size, + cur + sizeof(pkcs11_ref)), + pkcs11_ref.id, pkcs11_ref.size, + data[0], data[1], data[2], data[3]); + break; + } + + switch (pkcs11_ref.id) { + case PKCS11_CKA_WRAP_TEMPLATE: + case PKCS11_CKA_UNWRAP_TEMPLATE: + case PKCS11_CKA_DERIVE_TEMPLATE: + if (pkcs11_ref.size) + trace_attributes(prefix2, + cur + sizeof(pkcs11_ref)); + break; + default: + break; + } + } + + /* Sanity */ + if (cur != end) + EMSG("Warning: unexpected alignment in object attributes"); + + TEE_Free(prefix2); +} + +void trace_attributes(const char *prefix, void *ref) +{ + struct obj_attrs head = { }; + char *pre = NULL; + + TEE_MemMove(&head, ref, sizeof(head)); + + if (!head.attrs_count) + return; + + pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO); + if (!pre) { + EMSG("%s: out of memory", prefix); + return; + } + + if (prefix) + TEE_MemMove(pre, prefix, strlen(prefix)); + + IMSG_RAW("%s,--- (serial object) Attributes list --------", pre); + IMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes", + pre, head.attrs_count, head.attrs_size); + + pre[prefix ? strlen(prefix) : 0] = '|'; + __trace_attributes(pre, (char *)ref + sizeof(head), + (char *)ref + sizeof(head) + head.attrs_size); + + IMSG_RAW("%s`-----------------------", prefix ? prefix : ""); + + TEE_Free(pre); +} +#endif /*CFG_TEE_TA_LOG_LEVEL*/ diff --git a/optee/optee_os/ta/pkcs11/src/attributes.h b/optee/optee_os/ta/pkcs11/src/attributes.h new file mode 100644 index 0000000..2746ab6 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/attributes.h @@ -0,0 +1,322 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#ifndef PKCS11_TA_ATTRIBUTES_H +#define PKCS11_TA_ATTRIBUTES_H + +#include +#include +#include +#include + +#include "pkcs11_helpers.h" + +/* + * Boolean property attributes (BPA): bit position in a 64 bit mask + * for boolean properties object can mandate as attribute, depending + * on the object. These attributes are often accessed and it is + * quicker to get them from a 64 bit field in the object instance + * rather than searching into the object attributes. + */ +#define PKCS11_BOOLPROPS_BASE 0 +#define PKCS11_BOOLPROPS_MAX_COUNT 64 + +enum boolprop_attr { + BPA_TOKEN = 0, + BPA_PRIVATE, + BPA_TRUSTED, + BPA_SENSITIVE, + BPA_ENCRYPT, + BPA_DECRYPT, + BPA_WRAP, + BPA_UNWRAP, + BPA_SIGN, + BPA_SIGN_RECOVER, + BPA_VERIFY, + BPA_VERIFY_RECOVER, + BPA_DERIVE, + BPA_EXTRACTABLE, + BPA_LOCAL, + BPA_NEVER_EXTRACTABLE, + BPA_ALWAYS_SENSITIVE, + BPA_MODIFIABLE, + BPA_COPYABLE, + BPA_DESTROYABLE, + BPA_ALWAYS_AUTHENTICATE, + BPA_WRAP_WITH_TRUSTED, +}; + +/* + * Header of a serialized memory object inside PKCS11 TA. + * + * @attrs_size: byte size of the serialized data + * @attrs_count: number of items in the blob + * @attrs: then starts the blob binary data + */ +struct obj_attrs { + uint32_t attrs_size; + uint32_t attrs_count; + uint8_t attrs[]; +}; + +/* + * init_attributes_head() - Allocate a reference for serialized attributes + * @head: *@head holds the retrieved pointer + * + * Retrieved pointer can be freed from a simple TEE_Free(reference). + * + * Return PKCS11_CKR_OK on success or a PKCS11 return code. + */ +enum pkcs11_rc init_attributes_head(struct obj_attrs **head); + +/* + * add_attribute() - Update serialized attributes to add an entry. + * + * @head: *@head points to serialized attributes, + * can be reallocated as attributes are added + * @attribute: Attribute ID to add + * @data: Opaque data of attribute + * @size: Size of data + * + * Return PKCS11_CKR_OK on success or a PKCS11 return code. + */ +enum pkcs11_rc add_attribute(struct obj_attrs **head, uint32_t attribute, + void *data, size_t size); + +/* + * Update serialized attributes to remove an empty entry. Can relocate the + * attribute list buffer. Only 1 instance of the entry is expected. + * + * Return PKCS11_CKR_OK on success or a PKCS11 return code. + */ +enum pkcs11_rc remove_empty_attribute(struct obj_attrs **head, uint32_t attrib); + +/* + * get_attribute_ptrs() - Get pointers to attributes with a given ID + * @head: Pointer to serialized attributes + * @attribute: Attribute ID to look for + * @attr: Array of pointers to the data inside @head + * @attr_size: Array of uint32_t holding the sizes of each value pointed to + * by @attr + * @count: Number of elements in the arrays above + * + * If *count == 0, count and return in *count the number of attributes matching + * the input attribute ID. + * + * If *count != 0, return the address and size of the attributes found, up to + * the occurrence number *count. attr and attr_size are expected large + * enough. attr is the output array of the values found. attr_size is the + * output array of the size of each value found. + * + * If attr_size != NULL, return in *attr_size attribute value size. + * If attr != NULL return in *attr the address of the attribute value. + */ +void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute, + void **attr, uint32_t *attr_size, size_t *count); + +/* + * get_attribute_ptrs() - Get pointer to the attribute of a given ID + * @head: Pointer to serialized attributes + * @attribute: Attribute ID + * @attr: *@attr holds the retrieved pointer to the attribute value + * @attr_size: Size of the attribute value + * + * If no matching attributes is found return PKCS11_RV_NOT_FOUND. + * If attr_size != NULL, return in *attr_size attribute value size. + * If attr != NULL, return in *attr the address of the attribute value. + * + * Return PKCS11_CKR_OK or PKCS11_RV_NOT_FOUND on success, or a PKCS11 return + * code. + */ +enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute, + void **attr_ptr, uint32_t *attr_size); + +/* + * get_attribute() - Copy out the attribute of a given ID + * @head: Pointer to serialized attributes + * @attribute: Attribute ID to look for + * @attr: holds the retrieved attribute value + * @attr_size: Size of the attribute value + * + * If attribute is not found, return PKCS11_RV_NOT_FOUND. + * + * If attr_size != NULL, check that attr has enough room for value (compare + * against *attr_size), copy attribute value to attr and finally return actual + * value size in *attr_size. + * + * If there is not enough room return PKCS11_CKR_BUFFER_TOO_SMALL with expected + * size in *attr_size. + * + * If attr is NULL and attr_size != NULL return expected buffer size in + * *attr_size. + * + * Return PKCS11_CKR_OK or PKCS11_RV_NOT_FOUND on success, or a PKCS11 return + * code. + */ +enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute, + void *attr, uint32_t *attr_size); + +/* + * set_attribute() - Set the attribute of a given ID with value + * @head: Pointer to serialized attributes where attribute is to be set, + * can be relocated as attributes are modified/added + * @attribute: Attribute ID to look for + * @data: Holds the attribute value to be set + * @size: Size of the attribute value + * + * Return PKCS11_CKR_OK on success or a PKCS11 return code. + */ +enum pkcs11_rc set_attribute(struct obj_attrs **head, uint32_t attribute, + void *data, size_t size); + +/* + * modify_attributes_list() - Modify the value of attributes in destination + * attribute list (serialized attributes) based on the value of attributes in + * the source attribute list + * @dst: Pointer to serialized attrbutes where attributes are to be + * modified, can be relocated as attributes are modified + * @head: Serialized attributes containing attributes which need to be + * modified in the destination attribute list + * + * Return PKCS11_CKR_OK on success + */ +enum pkcs11_rc modify_attributes_list(struct obj_attrs **dst, + struct obj_attrs *head); + +/* + * get_u32_attribute() - Copy out the 32-bit attribute value of a given ID + * @head: Pointer to serialized attributes + * @attribute: Attribute ID + * @attr: holds the retrieved 32-bit attribute value + * + * If attribute is not found, return PKCS11_RV_NOT_FOUND. + * If the retreived attribute doesn't have a 4 byte sized value + * PKCS11_CKR_GENERAL_ERROR is returned. + * + * Return PKCS11_CKR_OK or PKCS11_RV_NOT_FOUND on success, or a PKCS11 return + * code. + */ + +static inline enum pkcs11_rc get_u32_attribute(struct obj_attrs *head, + uint32_t attribute, + uint32_t *attr) +{ + uint32_t size = sizeof(uint32_t); + enum pkcs11_rc rc = get_attribute(head, attribute, attr, &size); + + if (!rc && size != sizeof(uint32_t)) + return PKCS11_CKR_GENERAL_ERROR; + + return rc; +} + +/* + * Return true if all attributes from the reference are found and match value + * in the candidate attribute list. + */ +bool attributes_match_reference(struct obj_attrs *ref, + struct obj_attrs *candidate); + +/* + * Check attributes from @ref are all found or added in @head + * + * Return PKCS11_CKR_OK on success, or a PKCS11 return code. + */ +enum pkcs11_rc attributes_match_add_reference(struct obj_attrs **head, + struct obj_attrs *ref); +/* + * get_class() - Get class ID of an object + * @head: Pointer to serialized attributes + * + * Returns the class ID of an object on succes or returns + * PKCS11_CKO_UNDEFINED_ID on error. + */ +static inline enum pkcs11_class_id get_class(struct obj_attrs *head) +{ + uint32_t class = 0; + uint32_t size = sizeof(class); + + if (get_attribute(head, PKCS11_CKA_CLASS, &class, &size)) + return PKCS11_CKO_UNDEFINED_ID; + + return class; +} + +/* + * get_key_type() - Get the key type of an object + * @head: Pointer to serialized attributes + * + * Returns the key type of an object on success or returns + * PKCS11_CKK_UNDEFINED_ID on error. + */ +static inline enum pkcs11_key_type get_key_type(struct obj_attrs *head) +{ + uint32_t type = 0; + uint32_t size = sizeof(type); + + if (get_attribute(head, PKCS11_CKA_KEY_TYPE, &type, &size)) + return PKCS11_CKK_UNDEFINED_ID; + + return type; +} + +/* + * get_certificate_type() - Get the certificate type of an object + * @head: Pointer to serialized attributes + * + * Returns the certificate type of an object on success or returns + * PKCS11_CKC_UNDEFINED_ID on error. + */ +static inline +enum pkcs11_certificate_type get_certificate_type(struct obj_attrs *head) +{ + uint32_t type = 0; + + if (get_u32_attribute(head, PKCS11_CKA_CERTIFICATE_TYPE, &type)) + return PKCS11_CKC_UNDEFINED_ID; + + return type; +} + +/* + * get_mechanism_type() - Get the mechanism type of an object + * @head: Pointer to serialized attributes + * + * Returns the mechanism type of an object on success or returns + * PKCS11_CKM_UNDEFINED_ID on error. + */ +static inline enum pkcs11_mechanism_id get_mechanism_type(struct obj_attrs *head) +{ + uint32_t type = 0; + uint32_t size = sizeof(type); + + if (get_attribute(head, PKCS11_CKA_MECHANISM_TYPE, &type, &size)) + return PKCS11_CKM_UNDEFINED_ID; + + return type; +} + +/* + * get_bool() - Get the bool value of an attribute + * @head: Pointer to serialized attributes + * @attribute: Attribute ID to look for + * + * May assert if attribute ID isn't of the boolean type. + * + * Returns the bool value of the supplied attribute ID on success if found + * else false. + */ +bool get_bool(struct obj_attrs *head, uint32_t attribute); + +#if CFG_TEE_TA_LOG_LEVEL > 0 +/* Debug: dump object attributes to IMSG() trace console */ +void trace_attributes(const char *prefix, void *ref); +#else +static inline void trace_attributes(const char *prefix __unused, + void *ref __unused) +{ +} +#endif /*CFG_TEE_TA_LOG_LEVEL*/ +#endif /*PKCS11_TA_ATTRIBUTES_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/entry.c b/optee/optee_os/ta/pkcs11/src/entry.c new file mode 100644 index 0000000..0e36b91 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/entry.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "object.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.h" + +TEE_Result TA_CreateEntryPoint(void) +{ + return pkcs11_init(); +} + +void TA_DestroyEntryPoint(void) +{ + pkcs11_deinit(); +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types, + TEE_Param __unused params[4], + void **tee_session) +{ + struct pkcs11_client *client = register_client(); + + if (!client) + return TEE_ERROR_OUT_OF_MEMORY; + + *tee_session = client; + + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *tee_session) +{ + struct pkcs11_client *client = tee_session2client(tee_session); + + unregister_client(client); +} + +/* + * Entry point for invocation command PKCS11_CMD_PING + * + * Return a PKCS11_CKR_* value which is also loaded into the output param#0 + */ +static enum pkcs11_rc entry_ping(uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *out = params + 2; + const uint32_t ver[] = { + PKCS11_TA_VERSION_MAJOR, + PKCS11_TA_VERSION_MINOR, + PKCS11_TA_VERSION_PATCH, + }; + + if (ptypes != exp_pt || + params[0].memref.size != TEE_PARAM0_SIZE_MIN || + out->memref.size != sizeof(ver)) + return PKCS11_CKR_ARGUMENTS_BAD; + + TEE_MemMove(out->memref.buffer, ver, sizeof(ver)); + + return PKCS11_CKR_OK; +} + +static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index) +{ + return TEE_PARAM_TYPE_GET(ptypes, index) == + TEE_PARAM_TYPE_NONE; +} + +static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index) +{ + switch (TEE_PARAM_TYPE_GET(ptypes, index)) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + return true; + default: + return false; + } +} + +static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index) +{ + return TEE_PARAM_TYPE_GET(ptypes, index) == + TEE_PARAM_TYPE_MEMREF_INPUT; +} + +static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index) +{ + return TEE_PARAM_TYPE_GET(ptypes, index) == + TEE_PARAM_TYPE_MEMREF_OUTPUT; +} + +/* + * Entry point for PKCS11 TA commands + * + * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized + * arguments for the invoked command while the output data is used to send + * back to the client a PKCS11 finer status ID than the GPD TEE result codes + * Client shall check the status ID from the parameter #0 output buffer together + * with the GPD TEE result code. + */ +TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd, + uint32_t ptypes, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct pkcs11_client *client = tee_session2client(tee_session); + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + if (!client) + return TEE_ERROR_SECURITY; + + /* All command handlers will check only against 4 parameters */ + COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4); + + /* + * Param#0 must be either an output or an inout memref as used to + * store the output return value for the invoked command. + */ + switch (TEE_PARAM_TYPE_GET(ptypes, 0)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + if (params[0].memref.size < sizeof(rc)) + return TEE_ERROR_BAD_PARAMETERS; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + DMSG("%s p#0 %zu@%p, p#1 %s %zu@%p, p#2 %s %zu@%p", + id2str_ta_cmd(cmd), + params[0].memref.size, params[0].memref.buffer, + param_is_input(ptypes, 1) ? "in" : + param_is_output(ptypes, 1) ? "out" : "---", + param_is_memref(ptypes, 1) ? params[1].memref.size : 0, + param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL, + param_is_input(ptypes, 2) ? "in" : + param_is_output(ptypes, 2) ? "out" : "---", + param_is_memref(ptypes, 2) ? params[2].memref.size : 0, + param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL); + + switch (cmd) { + case PKCS11_CMD_PING: + rc = entry_ping(ptypes, params); + break; + + case PKCS11_CMD_SLOT_LIST: + rc = entry_ck_slot_list(ptypes, params); + break; + case PKCS11_CMD_SLOT_INFO: + rc = entry_ck_slot_info(ptypes, params); + break; + case PKCS11_CMD_TOKEN_INFO: + rc = entry_ck_token_info(ptypes, params); + break; + case PKCS11_CMD_MECHANISM_IDS: + rc = entry_ck_token_mecha_ids(ptypes, params); + break; + case PKCS11_CMD_MECHANISM_INFO: + rc = entry_ck_token_mecha_info(ptypes, params); + break; + + case PKCS11_CMD_OPEN_SESSION: + rc = entry_ck_open_session(client, ptypes, params); + break; + case PKCS11_CMD_CLOSE_SESSION: + rc = entry_ck_close_session(client, ptypes, params); + break; + case PKCS11_CMD_CLOSE_ALL_SESSIONS: + rc = entry_ck_close_all_sessions(client, ptypes, params); + break; + case PKCS11_CMD_SESSION_INFO: + rc = entry_ck_session_info(client, ptypes, params); + break; + + case PKCS11_CMD_INIT_TOKEN: + rc = entry_ck_token_initialize(ptypes, params); + break; + case PKCS11_CMD_INIT_PIN: + rc = entry_ck_init_pin(client, ptypes, params); + break; + case PKCS11_CMD_SET_PIN: + rc = entry_ck_set_pin(client, ptypes, params); + break; + case PKCS11_CMD_LOGIN: + rc = entry_ck_login(client, ptypes, params); + break; + case PKCS11_CMD_LOGOUT: + rc = entry_ck_logout(client, ptypes, params); + break; + + case PKCS11_CMD_CREATE_OBJECT: + rc = entry_create_object(client, ptypes, params); + break; + case PKCS11_CMD_DESTROY_OBJECT: + rc = entry_destroy_object(client, ptypes, params); + break; + + case PKCS11_CMD_ENCRYPT_INIT: + rc = entry_processing_init(client, ptypes, params, + PKCS11_FUNCTION_ENCRYPT); + break; + case PKCS11_CMD_DECRYPT_INIT: + rc = entry_processing_init(client, ptypes, params, + PKCS11_FUNCTION_DECRYPT); + break; + case PKCS11_CMD_ENCRYPT_UPDATE: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_ENCRYPT, + PKCS11_FUNC_STEP_UPDATE); + break; + case PKCS11_CMD_DECRYPT_UPDATE: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_DECRYPT, + PKCS11_FUNC_STEP_UPDATE); + break; + case PKCS11_CMD_ENCRYPT_ONESHOT: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_ENCRYPT, + PKCS11_FUNC_STEP_ONESHOT); + break; + case PKCS11_CMD_DECRYPT_ONESHOT: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_DECRYPT, + PKCS11_FUNC_STEP_ONESHOT); + break; + case PKCS11_CMD_ENCRYPT_FINAL: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_ENCRYPT, + PKCS11_FUNC_STEP_FINAL); + break; + case PKCS11_CMD_DECRYPT_FINAL: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_DECRYPT, + PKCS11_FUNC_STEP_FINAL); + break; + case PKCS11_CMD_SIGN_INIT: + rc = entry_processing_init(client, ptypes, params, + PKCS11_FUNCTION_SIGN); + break; + case PKCS11_CMD_VERIFY_INIT: + rc = entry_processing_init(client, ptypes, params, + PKCS11_FUNCTION_VERIFY); + break; + case PKCS11_CMD_SIGN_ONESHOT: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_SIGN, + PKCS11_FUNC_STEP_ONESHOT); + break; + case PKCS11_CMD_VERIFY_ONESHOT: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_VERIFY, + PKCS11_FUNC_STEP_ONESHOT); + break; + case PKCS11_CMD_SIGN_UPDATE: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_SIGN, + PKCS11_FUNC_STEP_UPDATE); + break; + case PKCS11_CMD_VERIFY_UPDATE: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_VERIFY, + PKCS11_FUNC_STEP_UPDATE); + break; + case PKCS11_CMD_SIGN_FINAL: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_SIGN, + PKCS11_FUNC_STEP_FINAL); + break; + case PKCS11_CMD_VERIFY_FINAL: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_VERIFY, + PKCS11_FUNC_STEP_FINAL); + break; + case PKCS11_CMD_GENERATE_KEY: + rc = entry_generate_secret(client, ptypes, params); + break; + case PKCS11_CMD_FIND_OBJECTS_INIT: + rc = entry_find_objects_init(client, ptypes, params); + break; + case PKCS11_CMD_FIND_OBJECTS: + rc = entry_find_objects(client, ptypes, params); + break; + case PKCS11_CMD_FIND_OBJECTS_FINAL: + rc = entry_find_objects_final(client, ptypes, params); + break; + case PKCS11_CMD_GET_ATTRIBUTE_VALUE: + rc = entry_get_attribute_value(client, ptypes, params); + break; + case PKCS11_CMD_GET_OBJECT_SIZE: + rc = entry_get_object_size(client, ptypes, params); + break; + case PKCS11_CMD_SET_ATTRIBUTE_VALUE: + rc = entry_set_attribute_value(client, ptypes, params); + break; + case PKCS11_CMD_COPY_OBJECT: + rc = entry_copy_object(client, ptypes, params); + break; + case PKCS11_CMD_SEED_RANDOM: + rc = entry_ck_seed_random(client, ptypes, params); + break; + case PKCS11_CMD_GENERATE_RANDOM: + rc = entry_ck_generate_random(client, ptypes, params); + break; + case PKCS11_CMD_DERIVE_KEY: + rc = entry_processing_key(client, ptypes, params, + PKCS11_FUNCTION_DERIVE); + break; + case PKCS11_CMD_RELEASE_ACTIVE_PROCESSING: + rc = entry_release_active_processing(client, ptypes, params); + break; + case PKCS11_CMD_DIGEST_INIT: + rc = entry_processing_init(client, ptypes, params, + PKCS11_FUNCTION_DIGEST); + break; + case PKCS11_CMD_DIGEST_UPDATE: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_DIGEST, + PKCS11_FUNC_STEP_UPDATE); + break; + case PKCS11_CMD_DIGEST_KEY: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_DIGEST, + PKCS11_FUNC_STEP_UPDATE_KEY); + break; + case PKCS11_CMD_DIGEST_ONESHOT: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_DIGEST, + PKCS11_FUNC_STEP_ONESHOT); + break; + case PKCS11_CMD_DIGEST_FINAL: + rc = entry_processing_step(client, ptypes, params, + PKCS11_FUNCTION_DIGEST, + PKCS11_FUNC_STEP_FINAL); + break; + case PKCS11_CMD_GENERATE_KEY_PAIR: + rc = entry_generate_key_pair(client, ptypes, params); + break; + case PKCS11_CMD_WRAP_KEY: + rc = entry_wrap_key(client, ptypes, params); + break; + case PKCS11_CMD_UNWRAP_KEY: + rc = entry_processing_key(client, ptypes, params, + PKCS11_FUNCTION_UNWRAP); + break; + default: + EMSG("Command %#"PRIx32" is not supported", cmd); + return TEE_ERROR_NOT_SUPPORTED; + } + + DMSG("%s rc %#"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc)); + + TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc)); + params[0].memref.size = sizeof(rc); + + if (rc == PKCS11_CKR_BUFFER_TOO_SMALL) + return TEE_ERROR_SHORT_BUFFER; + else + return TEE_SUCCESS; +} diff --git a/optee/optee_os/ta/pkcs11/src/handle.c b/optee/optee_os/ta/pkcs11/src/handle.c new file mode 100644 index 0000000..80b6759 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/handle.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014-2020, Linaro Limited + */ + +#include +#include +#include + +#include "handle.h" + +/* + * Define the initial capacity of the database. It should be a low number + * multiple of 2 since some databases a likely to only use a few handles. + * Since the algorithm is to doubles up when growing it shouldn't cause a + * noticeable overhead on large databases. + */ +#define HANDLE_DB_INITIAL_MAX_PTRS 4 + +void handle_db_init(struct handle_db *db) +{ + TEE_MemFill(db, 0, sizeof(*db)); +} + +void handle_db_destroy(struct handle_db *db) +{ + if (db) { + TEE_Free(db->ptrs); + db->ptrs = NULL; + db->max_ptrs = 0; + } +} + +uint32_t handle_get(struct handle_db *db, void *ptr) +{ + uint32_t n = 0; + void *p = NULL; + uint32_t new_max_ptrs = 0; + + if (!db || !ptr) + return 0; + + /* Try to find an empty location (index 0 is reserved as invalid) */ + for (n = 1; n < db->max_ptrs; n++) { + if (!db->ptrs[n]) { + db->ptrs[n] = ptr; + return n; + } + } + + /* No location available, grow the ptrs array */ + if (db->max_ptrs) + new_max_ptrs = db->max_ptrs * 2; + else + new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; + + p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *)); + if (!p) + return 0; + db->ptrs = p; + TEE_MemFill(db->ptrs + db->max_ptrs, 0, + (new_max_ptrs - db->max_ptrs) * sizeof(void *)); + db->max_ptrs = new_max_ptrs; + + /* Since n stopped at db->max_ptrs there is an empty location there */ + db->ptrs[n] = ptr; + return n; +} + +void *handle_put(struct handle_db *db, uint32_t handle) +{ + void *p = NULL; + + if (!db || !handle || handle >= db->max_ptrs) + return NULL; + + p = db->ptrs[handle]; + db->ptrs[handle] = NULL; + return p; +} + +void *handle_lookup(struct handle_db *db, uint32_t handle) +{ + if (!db || !handle || handle >= db->max_ptrs) + return NULL; + + return db->ptrs[handle]; +} + +uint32_t handle_lookup_handle(struct handle_db *db, void *ptr) +{ + uint32_t n = 0; + + if (ptr) { + for (n = 1; n < db->max_ptrs; n++) + if (db->ptrs[n] == ptr) + return n; + } + + return 0; +} diff --git a/optee/optee_os/ta/pkcs11/src/handle.h b/optee/optee_os/ta/pkcs11/src/handle.h new file mode 100644 index 0000000..8936331 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/handle.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014-2020, Linaro Limited + */ + +#ifndef PKCS11_TA_HANDLE_H +#define PKCS11_TA_HANDLE_H + +#include + +struct handle_db { + void **ptrs; + uint32_t max_ptrs; +}; + +/* + * Initialize the handle database + */ +void handle_db_init(struct handle_db *db); + +/* + * Free all internal data structures of the database, but does not free + * the db pointer. The database is safe to reuse after it's destroyed, it + * just be empty again. + */ +void handle_db_destroy(struct handle_db *db); + +/* + * Allocate a new handle ID and assigns the supplied pointer to it, + * The function returns > 0 on success and 0 on failure. + */ +uint32_t handle_get(struct handle_db *db, void *ptr); + +/* + * Deallocate a handle. Returns the associated pointer of the handle + * if the handle was valid or NULL if it's invalid. + */ +void *handle_put(struct handle_db *db, uint32_t handle); + +/* + * Return the associated pointer of the handle if the handle is a valid + * handle. + * Returns NULL on failure. + */ +void *handle_lookup(struct handle_db *db, uint32_t handle); + +/* Return the handle associated to a pointer if found, else return 0 */ +uint32_t handle_lookup_handle(struct handle_db *db, void *ptr); + +#endif /*PKCS11_TA_HANDLE_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/object.c b/optee/optee_os/ta/pkcs11/src/object.c new file mode 100644 index 0000000..7c1d3ac --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/object.c @@ -0,0 +1,1237 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "handle.h" +#include "object.h" +#include "pkcs11_attributes.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "sanitize_object.h" +#include "serializer.h" + +/* + * Temporary list used to register allocated struct pkcs11_object instances + * so that destroy_object() can unconditionally remove the object from its + * list, being from an object destruction request or because object creation + * failed before being completed. Objects are moved to their target list at + * creation completion. + */ +LIST_HEAD(temp_obj_list, pkcs11_object) temporary_object_list = + LIST_HEAD_INITIALIZER(temp_obj_list); + +static struct ck_token *get_session_token(void *session); + +struct pkcs11_object *pkcs11_handle2object(uint32_t handle, + struct pkcs11_session *session) +{ + struct pkcs11_object *object = NULL; + + object = handle_lookup(get_object_handle_db(session), handle); + if (!object) + return NULL; + + /* + * If object is session only then no extra checks are needed as session + * objects has flat access control space + */ + if (!object->token) + return object; + + /* + * Only allow access to token object if session is associated with + * the token + */ + if (object->token != get_session_token(session)) + return NULL; + + return object; +} + +uint32_t pkcs11_object2handle(struct pkcs11_object *obj, + struct pkcs11_session *session) +{ + return handle_lookup_handle(get_object_handle_db(session), obj); +} + +/* Currently handle pkcs11 sessions and tokens */ + +static struct object_list *get_session_objects(void *session) +{ + /* Currently supporting only pkcs11 session */ + struct pkcs11_session *ck_session = session; + + return pkcs11_get_session_objects(ck_session); +} + +static struct ck_token *get_session_token(void *session) +{ + struct pkcs11_session *ck_session = session; + + return pkcs11_session2token(ck_session); +} + +/* Release resources of a non-persistent object */ +static void cleanup_volatile_obj_ref(struct pkcs11_object *obj) +{ + if (!obj) + return; + + LIST_REMOVE(obj, link); + + if (obj->key_handle != TEE_HANDLE_NULL) + TEE_FreeTransientObject(obj->key_handle); + + if (obj->attribs_hdl != TEE_HANDLE_NULL) + TEE_CloseObject(obj->attribs_hdl); + + TEE_Free(obj->attributes); + TEE_Free(obj->uuid); + TEE_Free(obj); +} + +/* Release resources of a persistent object including volatile resources */ +void cleanup_persistent_object(struct pkcs11_object *obj, + struct ck_token *token) +{ + TEE_Result res = TEE_SUCCESS; + + if (!obj) + return; + + /* Open handle with write properties to destroy the object */ + if (obj->attribs_hdl != TEE_HANDLE_NULL) + TEE_CloseObject(obj->attribs_hdl); + + res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, + obj->uuid, sizeof(TEE_UUID), + TEE_DATA_FLAG_ACCESS_WRITE_META, + &obj->attribs_hdl); + if (!res) + TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl); + + obj->attribs_hdl = TEE_HANDLE_NULL; + destroy_object_uuid(token, obj); + + cleanup_volatile_obj_ref(obj); +} + +/* + * destroy_object - destroy an PKCS11 TA object + * + * @session - session requesting object destruction + * @obj - reference to the PKCS11 TA object + * @session_only - true if only session object shall be destroyed + */ +void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj, + bool session_only) +{ +#ifdef DEBUG + trace_attributes("[destroy]", obj->attributes); + if (obj->uuid) + MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid); +#endif + + if (session_only) { + /* Destroy object due to session closure */ + handle_put(get_object_handle_db(session), + pkcs11_object2handle(obj, session)); + cleanup_volatile_obj_ref(obj); + + return; + } + + /* Destroy target object (persistent or not) */ + if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { + assert(obj->uuid); + /* Try twice otherwise panic! */ + if (unregister_persistent_object(session->token, obj->uuid) && + unregister_persistent_object(session->token, obj->uuid)) + TEE_Panic(0); + + handle_put(get_object_handle_db(session), + pkcs11_object2handle(obj, session)); + cleanup_persistent_object(obj, session->token); + } else { + handle_put(get_object_handle_db(session), + pkcs11_object2handle(obj, session)); + cleanup_volatile_obj_ref(obj); + } +} + +static struct pkcs11_object *create_obj_instance(struct obj_attrs *head, + struct ck_token *token) +{ + struct pkcs11_object *obj = NULL; + + obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO); + if (!obj) + return NULL; + + obj->key_handle = TEE_HANDLE_NULL; + obj->attribs_hdl = TEE_HANDLE_NULL; + obj->attributes = head; + obj->token = token; + + return obj; +} + +struct pkcs11_object *create_token_object(struct obj_attrs *head, + TEE_UUID *uuid, + struct ck_token *token) +{ + struct pkcs11_object *obj = create_obj_instance(head, token); + + if (obj) + obj->uuid = uuid; + + return obj; +} + +/* + * create_object - create an PKCS11 TA object from its attributes and value + * + * @sess - session requesting object creation + * @head - reference to serialized attributes + * @out_handle - generated handle for the created object + */ +enum pkcs11_rc create_object(void *sess, struct obj_attrs *head, + uint32_t *out_handle) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct pkcs11_object *obj = NULL; + struct pkcs11_session *session = (struct pkcs11_session *)sess; + uint32_t obj_handle = 0; + +#ifdef DEBUG + trace_attributes("[create]", head); +#endif + + /* + * We do not check the key attributes. At this point, key attributes + * are expected consistent and reliable. + */ + + obj = create_obj_instance(head, NULL); + if (!obj) + return PKCS11_CKR_DEVICE_MEMORY; + + LIST_INSERT_HEAD(&temporary_object_list, obj, link); + + /* Create a handle for the object in the session database */ + obj_handle = handle_get(get_object_handle_db(session), obj); + if (!obj_handle) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto err; + } + + if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { + TEE_Result res = TEE_SUCCESS; + + /* + * Get an ID for the persistent object + * Create the file + * Register the object in the persistent database + * (move the full sequence to persisent_db.c?) + */ + size_t size = sizeof(struct obj_attrs) + + obj->attributes->attrs_size; + uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META; + + rc = create_object_uuid(get_session_token(session), obj); + if (rc) + goto err; + + res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, + obj->uuid, sizeof(TEE_UUID), + tee_obj_flags, + TEE_HANDLE_NULL, + obj->attributes, size, + &obj->attribs_hdl); + if (res) { + rc = tee2pkcs_error(res); + goto err; + } + + rc = register_persistent_object(get_session_token(session), + obj->uuid); + if (rc) + goto err; + + TEE_CloseObject(obj->attribs_hdl); + obj->attribs_hdl = TEE_HANDLE_NULL; + + /* Move object from temporary list to target token list */ + LIST_REMOVE(obj, link); + LIST_INSERT_HEAD(&session->token->object_list, obj, link); + } else { + /* Move object from temporary list to target session list */ + LIST_REMOVE(obj, link); + LIST_INSERT_HEAD(get_session_objects(session), obj, link); + } + + *out_handle = obj_handle; + + return PKCS11_CKR_OK; +err: + /* make sure that supplied "head" isn't freed */ + obj->attributes = NULL; + handle_put(get_object_handle_db(session), obj_handle); + if (get_bool(head, PKCS11_CKA_TOKEN)) + cleanup_persistent_object(obj, session->token); + else + cleanup_volatile_obj_ref(obj); + + return rc; +} + +enum pkcs11_rc entry_create_object(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + enum pkcs11_rc rc = PKCS11_CKR_OK; + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct obj_attrs *head = NULL; + struct pkcs11_object_head *template = NULL; + size_t template_size = 0; + uint32_t obj_handle = 0; + + /* + * Collect the arguments of the request + */ + + if (!client || ptypes != exp_pt || + out->memref.size != sizeof(obj_handle)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &template); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + template_size = sizeof(*template) + template->attrs_size; + + /* + * Prepare a clean initial state for the requested object attributes. + * Free temporary template once done. + */ + rc = create_attributes_from_template(&head, template, template_size, + NULL, PKCS11_FUNCTION_IMPORT, + PKCS11_PROCESSING_IMPORT, + PKCS11_CKO_UNDEFINED_ID); + TEE_Free(template); + template = NULL; + if (rc) + goto out; + + /* + * Check target object attributes match target processing + * Check target object attributes match token state + */ + rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT, + head); + if (rc) + goto out; + + rc = check_created_attrs_against_token(session, head); + if (rc) + goto out; + + rc = check_access_attrs_against_token(session, head); + if (rc) + goto out; + + /* + * At this stage the object is almost created: all its attributes are + * referenced in @head, including the key value and are assumed + * reliable. Now need to register it and get a handle for it. + */ + rc = create_object(session, head, &obj_handle); + if (rc) + goto out; + + /* + * Now obj_handle (through the related struct pkcs11_object + * instance) owns the serialized buffer that holds the object + * attributes. We clear reference in head to NULL as the serializer + * object is now referred from obj_handle. This allows smooth pass + * through free at function exit. + */ + head = NULL; + + TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); + out->memref.size = sizeof(obj_handle); + + DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32, + session->handle, obj_handle); + +out: + TEE_Free(template); + TEE_Free(head); + + return rc; +} + +enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + enum pkcs11_rc rc = PKCS11_CKR_OK; + TEE_Param *ctrl = params; + struct serialargs ctrlargs = { }; + uint32_t object_handle = 0; + struct pkcs11_session *session = NULL; + struct pkcs11_object *object = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get_u32(&ctrlargs, &object_handle); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + object = pkcs11_handle2object(object_handle, session); + if (!object) + return PKCS11_CKR_OBJECT_HANDLE_INVALID; + + /* Only session objects can be destroyed during a read-only session */ + if (get_bool(object->attributes, PKCS11_CKA_TOKEN) && + !pkcs11_session_is_read_write(session)) { + DMSG("Can't destroy persistent object"); + return PKCS11_CKR_SESSION_READ_ONLY; + } + + /* + * Only public objects can be destroyed unless normal user is logged in + */ + rc = check_access_attrs_against_token(session, object->attributes); + if (rc) + return PKCS11_CKR_USER_NOT_LOGGED_IN; + + /* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */ + if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE)) + return PKCS11_CKR_ACTION_PROHIBITED; + + destroy_object(session, object, false); + + DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32, + session->handle, object_handle); + + return rc; +} + +static void release_find_obj_context(struct pkcs11_find_objects *find_ctx) +{ + if (!find_ctx) + return; + + TEE_Free(find_ctx->attributes); + TEE_Free(find_ctx->handles); + TEE_Free(find_ctx); +} + +static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx, + uint32_t handle) +{ + uint32_t *hdls = TEE_Realloc(find_ctx->handles, + (find_ctx->count + 1) * sizeof(*hdls)); + + if (!hdls) + return PKCS11_CKR_DEVICE_MEMORY; + + find_ctx->handles = hdls; + + *(find_ctx->handles + find_ctx->count) = handle; + find_ctx->count++; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_session *sess = NULL; + struct pkcs11_object_head *template = NULL; + struct obj_attrs *req_attrs = NULL; + struct pkcs11_object *obj = NULL; + struct pkcs11_find_objects *find_ctx = NULL; + struct handle_db *object_db = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &template); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + /* Search objects only if no operation is on-going */ + if (session_is_active(session)) { + rc = PKCS11_CKR_OPERATION_ACTIVE; + goto out; + } + + if (session->find_ctx) { + EMSG("Active object search already in progress"); + rc = PKCS11_CKR_FUNCTION_FAILED; + goto out; + } + + rc = sanitize_client_object(&req_attrs, template, + sizeof(*template) + template->attrs_size, + PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID); + if (rc) + goto out; + + /* Must zero init the structure */ + find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO); + if (!find_ctx) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + TEE_Free(template); + template = NULL; + + switch (get_class(req_attrs)) { + case PKCS11_CKO_UNDEFINED_ID: + /* Unspecified class searches among data objects */ + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_PRIVATE_KEY: + case PKCS11_CKO_DATA: + case PKCS11_CKO_CERTIFICATE: + break; + default: + EMSG("Find object of class %s (%"PRIu32") is not supported", + id2str_class(get_class(req_attrs)), + get_class(req_attrs)); + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + /* + * Scan all objects (sessions and persistent ones) and set a list of + * candidates that match caller attributes. + */ + + /* Scan all session objects first */ + TAILQ_FOREACH(sess, get_session_list(session), link) { + LIST_FOREACH(obj, &sess->object_list, link) { + /* + * Skip all token objects as they could be from + * different token which the session does not have + * access + */ + if (obj->token) + continue; + + if (!attributes_match_reference(obj->attributes, + req_attrs)) + continue; + + rc = find_ctx_add(find_ctx, + pkcs11_object2handle(obj, session)); + if (rc) + goto out; + } + } + + object_db = get_object_handle_db(session); + + /* Scan token objects */ + LIST_FOREACH(obj, &session->token->object_list, link) { + uint32_t handle = 0; + bool new_load = false; + + if (!obj->attributes) { + rc = load_persistent_object_attributes(obj); + if (rc) { + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + new_load = true; + } + + if (!obj->attributes || + check_access_attrs_against_token(session, + obj->attributes) || + !attributes_match_reference(obj->attributes, req_attrs)) { + if (new_load) + release_persistent_object_attributes(obj); + + continue; + } + + /* Resolve object handle for object */ + handle = pkcs11_object2handle(obj, session); + if (!handle) { + handle = handle_get(object_db, obj); + if (!handle) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + } + + rc = find_ctx_add(find_ctx, handle); + if (rc) + goto out; + } + + find_ctx->attributes = req_attrs; + req_attrs = NULL; + session->find_ctx = find_ctx; + find_ctx = NULL; + rc = PKCS11_CKR_OK; + +out: + TEE_Free(req_attrs); + TEE_Free(template); + release_find_obj_context(find_ctx); + + return rc; +} + +enum pkcs11_rc entry_find_objects(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_find_objects *ctx = NULL; + uint8_t *out_handles = NULL; + size_t out_count = 0; + size_t count = 0; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + out_count = out->memref.size / sizeof(uint32_t); + out_handles = out->memref.buffer; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + ctx = session->find_ctx; + + if (!ctx) + return PKCS11_CKR_OPERATION_NOT_INITIALIZED; + + for (count = 0; ctx->next < ctx->count && count < out_count; + ctx->next++, count++) + TEE_MemMove(out_handles + count * sizeof(uint32_t), + ctx->handles + ctx->next, sizeof(uint32_t)); + + /* Update output buffer according the number of handles provided */ + out->memref.size = count * sizeof(uint32_t); + + DMSG("PKCS11 session %"PRIu32": finding objects", session->handle); + + return PKCS11_CKR_OK; +} + +void release_session_find_obj_context(struct pkcs11_session *session) +{ + release_find_obj_context(session->find_ctx); + session->find_ctx = NULL; +} + +enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!session->find_ctx) + return PKCS11_CKR_OPERATION_NOT_INITIALIZED; + + release_session_find_obj_context(session); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_object_head *template = NULL; + struct pkcs11_object *obj = NULL; + uint32_t object_handle = 0; + char *cur = NULL; + size_t len = 0; + char *end = NULL; + bool attr_sensitive = 0; + bool attr_type_invalid = 0; + bool buffer_too_small = 0; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &template); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + obj = pkcs11_handle2object(object_handle, session); + if (!obj) { + rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; + goto out; + } + + rc = check_access_attrs_against_token(session, obj->attributes); + if (rc) { + rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; + goto out; + } + + /* Iterate over attributes and set their values */ + /* + * 1. If the specified attribute (i.e., the attribute specified by the + * type field) for the object cannot be revealed because the object is + * sensitive or unextractable, then the ulValueLen field in that triple + * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION. + * + * 2. Otherwise, if the specified value for the object is invalid (the + * object does not possess such an attribute), then the ulValueLen field + * in that triple is modified to hold the value + * PKCS11_CK_UNAVAILABLE_INFORMATION. + * + * 3. Otherwise, if the pValue field has the value NULL_PTR, then the + * ulValueLen field is modified to hold the exact length of the + * specified attribute for the object. + * + * 4. Otherwise, if the length specified in ulValueLen is large enough + * to hold the value of the specified attribute for the object, then + * that attribute is copied into the buffer located at pValue, and the + * ulValueLen field is modified to hold the exact length of the + * attribute. + * + * 5. Otherwise, the ulValueLen field is modified to hold the value + * PKCS11_CK_UNAVAILABLE_INFORMATION. + */ + cur = (char *)template + sizeof(struct pkcs11_object_head); + end = cur + template->attrs_size; + + for (; cur < end; cur += len) { + struct pkcs11_attribute_head *cli_ref = (void *)cur; + struct pkcs11_attribute_head cli_head = { }; + void *data_ptr = NULL; + + /* Make copy of header so that is aligned properly. */ + TEE_MemMove(&cli_head, cli_ref, sizeof(cli_head)); + + len = sizeof(*cli_ref) + cli_head.size; + + /* We don't support getting value of indirect templates */ + if (pkcs11_attr_has_indirect_attributes(cli_head.id)) { + attr_type_invalid = 1; + continue; + } + + /* Check 1. */ + if (!attribute_is_exportable(&cli_head, obj)) { + cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; + TEE_MemMove(&cli_ref->size, &cli_head.size, + sizeof(cli_head.size)); + attr_sensitive = 1; + continue; + } + + /* Get real data pointer from template data */ + data_ptr = cli_head.size ? cli_ref->data : NULL; + + /* + * We assume that if size is 0, pValue was NULL, so we return + * the size of the required buffer for it (3., 4.) + */ + rc = get_attribute(obj->attributes, cli_head.id, data_ptr, + &cli_head.size); + /* Check 2. */ + switch (rc) { + case PKCS11_CKR_OK: + break; + case PKCS11_RV_NOT_FOUND: + cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; + attr_type_invalid = 1; + break; + case PKCS11_CKR_BUFFER_TOO_SMALL: + if (data_ptr) + buffer_too_small = 1; + break; + default: + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + TEE_MemMove(&cli_ref->size, &cli_head.size, + sizeof(cli_head.size)); + } + + /* + * If case 1 applies to any of the requested attributes, then the call + * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to + * any of the requested attributes, then the call should return the + * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the + * requested attributes, then the call should return the value + * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes + * is applicable, Cryptoki may return any of them. Only if none of them + * applies to any of the requested attributes will CKR_OK be returned. + */ + + rc = PKCS11_CKR_OK; + if (attr_sensitive) + rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE; + if (attr_type_invalid) + rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + if (buffer_too_small) + rc = PKCS11_CKR_BUFFER_TOO_SMALL; + + /* Move updated template to out buffer */ + TEE_MemMove(out->memref.buffer, template, out->memref.size); + + DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32, + session->handle, object_handle); + +out: + TEE_Free(template); + + return rc; +} + +enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + uint32_t object_handle = 0; + struct pkcs11_object *obj = NULL; + uint32_t obj_size = 0; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + obj = pkcs11_handle2object(object_handle, session); + if (!obj) + return PKCS11_CKR_OBJECT_HANDLE_INVALID; + + rc = check_access_attrs_against_token(session, obj->attributes); + if (rc) + return PKCS11_CKR_OBJECT_HANDLE_INVALID; + + if (out->memref.size != sizeof(uint32_t)) + return PKCS11_CKR_ARGUMENTS_BAD; + + obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size + + sizeof(struct obj_attrs); + TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size)); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_object_head *template = NULL; + size_t template_size = 0; + struct pkcs11_object *obj = NULL; + struct obj_attrs *head = NULL; + uint32_t object_handle = 0; + enum processing_func function = PKCS11_FUNCTION_MODIFY; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &template); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + obj = pkcs11_handle2object(object_handle, session); + if (!obj) { + rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; + goto out; + } + + /* Only session objects can be modified during a read-only session */ + if (object_is_token(obj->attributes) && + !pkcs11_session_is_read_write(session)) { + DMSG("Can't modify persistent object in a RO session"); + rc = PKCS11_CKR_SESSION_READ_ONLY; + goto out; + } + + /* + * Only public objects can be modified unless normal user is logged in + */ + rc = check_access_attrs_against_token(session, obj->attributes); + if (rc) { + rc = PKCS11_CKR_USER_NOT_LOGGED_IN; + goto out; + } + + /* Objects with PKCS11_CKA_MODIFIABLE as false aren't modifiable */ + if (!object_is_modifiable(obj->attributes)) { + rc = PKCS11_CKR_ACTION_PROHIBITED; + goto out; + } + + template_size = sizeof(*template) + template->attrs_size; + + /* + * Prepare a clean initial state (@head) for the template. Helps in + * removing any duplicates or inconsistent values from the + * template. + */ + rc = create_attributes_from_template(&head, template, template_size, + NULL, function, + PKCS11_CKM_UNDEFINED_ID, + PKCS11_CKO_UNDEFINED_ID); + if (rc) + goto out; + + /* Check the attributes in @head to see if they are modifiable */ + rc = check_attrs_against_modification(session, head, obj, function); + if (rc) + goto out; + + /* + * All checks complete. The attributes in @head have been checked and + * can now be used to set/modify the object attributes. + */ + rc = modify_attributes_list(&obj->attributes, head); + if (rc) + goto out; + + if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { + rc = update_persistent_object_attributes(obj); + if (rc) + goto out; + } + + DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32, + session->handle, object_handle); + +out: + TEE_Free(head); + TEE_Free(template); + return rc; +} + +enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes, + TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_object_head *template = NULL; + struct obj_attrs *head = NULL; + struct obj_attrs *head_new = NULL; + size_t template_size = 0; + struct pkcs11_object *obj = NULL; + uint32_t object_handle = 0; + uint32_t obj_handle = 0; + enum processing_func function = PKCS11_FUNCTION_COPY; + enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; + + if (!client || ptypes != exp_pt || + out->memref.size != sizeof(obj_handle)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &template); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + obj = pkcs11_handle2object(object_handle, session); + if (!obj) { + rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; + goto out; + } + + /* Only session objects can be modified during a read-only session */ + if (object_is_token(obj->attributes) && + !pkcs11_session_is_read_write(session)) { + DMSG("Can't modify persistent object in a RO session"); + rc = PKCS11_CKR_SESSION_READ_ONLY; + goto out; + } + + /* + * Only public objects can be modified unless normal user is logged in + */ + rc = check_access_attrs_against_token(session, obj->attributes); + if (rc) { + rc = PKCS11_CKR_USER_NOT_LOGGED_IN; + goto out; + } + + /* Objects with PKCS11_CKA_COPYABLE as false can't be copied */ + if (!object_is_copyable(obj->attributes)) { + rc = PKCS11_CKR_ACTION_PROHIBITED; + goto out; + } + + template_size = sizeof(*template) + template->attrs_size; + + /* + * Prepare a clean initial state (@head) for the template. Helps in + * removing any duplicates or inconsistent values from the + * template. + */ + rc = create_attributes_from_template(&head, template, template_size, + NULL, function, + PKCS11_CKM_UNDEFINED_ID, + PKCS11_CKO_UNDEFINED_ID); + if (rc) + goto out; + + /* Check the attributes in @head to see if they are modifiable */ + rc = check_attrs_against_modification(session, head, obj, function); + if (rc) + goto out; + + class = get_class(obj->attributes); + + if (class == PKCS11_CKO_SECRET_KEY || + class == PKCS11_CKO_PRIVATE_KEY) { + /* + * If CKA_EXTRACTABLE attribute in passed template (@head) is + * modified to CKA_FALSE, CKA_NEVER_EXTRACTABLE should also + * change to CKA_FALSE in copied obj. So, add it to the + * passed template. + */ + uint8_t bbool = 0; + uint32_t size = sizeof(bbool); + + rc = get_attribute(head, PKCS11_CKA_EXTRACTABLE, &bbool, &size); + if (!rc && !bbool) { + rc = add_attribute(&head, PKCS11_CKA_NEVER_EXTRACTABLE, + &bbool, sizeof(uint8_t)); + if (rc) + goto out; + } + rc = PKCS11_CKR_OK; + } + + /* + * All checks have passed. Create a copy of the serialized buffer which + * holds the object attributes in @head_new for the new object + */ + template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size; + head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO); + if (!head_new) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + TEE_MemMove(head_new, obj->attributes, template_size); + + /* + * Modify the copied attribute @head_new based on the template @head + * given by the callee + */ + rc = modify_attributes_list(&head_new, head); + if (rc) + goto out; + + /* + * At this stage the object is almost created: all its attributes are + * referenced in @head_new, including the key value and are assumed + * reliable. Now need to register it and get a handle for it. + */ + rc = create_object(session, head_new, &obj_handle); + if (rc) + goto out; + + /* + * Now obj_handle (through the related struct pkcs11_object + * instance) owns the serialized buffer that holds the object + * attributes. We clear reference in head to NULL as the serializer + * object is now referred from obj_handle. This allows smooth pass + * through free at function exit. + */ + head_new = NULL; + + TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); + out->memref.size = sizeof(obj_handle); + + DMSG("PKCS11 session %"PRIu32": copy object %#"PRIx32, + session->handle, obj_handle); + +out: + TEE_Free(head_new); + TEE_Free(head); + TEE_Free(template); + return rc; +} diff --git a/optee/optee_os/ta/pkcs11/src/object.h b/optee/optee_os/ta/pkcs11/src/object.h new file mode 100644 index 0000000..d1b791e --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/object.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#ifndef PKCS11_TA_OBJECT_H +#define PKCS11_TA_OBJECT_H + +#include +#include +#include + +struct ck_token; +struct obj_attrs; +struct pkcs11_client; +struct pkcs11_session; + +/* + * link: objects are referenced in a double-linked list + * attributes: pointer to the serialized object attributes + * key_handle: GPD TEE object handle if used in an operation + * key_type: GPD TEE key type (shortcut used for processing) + * token: associated token for the object + * uuid: object UUID in the persistent database if a persistent object, or NULL + * attribs_hdl: GPD TEE attributes handles if persistent object + */ +struct pkcs11_object { + LIST_ENTRY(pkcs11_object) link; + struct obj_attrs *attributes; + TEE_ObjectHandle key_handle; + uint32_t key_type; + struct ck_token *token; + TEE_UUID *uuid; + TEE_ObjectHandle attribs_hdl; +}; + +LIST_HEAD(object_list, pkcs11_object); + +struct pkcs11_object *pkcs11_handle2object(uint32_t client_handle, + struct pkcs11_session *session); + +uint32_t pkcs11_object2handle(struct pkcs11_object *obj, + struct pkcs11_session *session); + +struct pkcs11_object *create_token_object(struct obj_attrs *head, + TEE_UUID *uuid, + struct ck_token *token); + +enum pkcs11_rc create_object(void *session, struct obj_attrs *attributes, + uint32_t *handle); + +void cleanup_persistent_object(struct pkcs11_object *obj, + struct ck_token *token); + +void destroy_object(struct pkcs11_session *session, + struct pkcs11_object *object, bool session_object_only); + +/* + * Entry function called from the PKCS11 command parser + */ +enum pkcs11_rc entry_create_object(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_find_objects(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes, + TEE_Param *params); + +void release_session_find_obj_context(struct pkcs11_session *session); + +#endif /*PKCS11_TA_OBJECT_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/persistent_token.c b/optee/optee_os/ta/pkcs11/src/persistent_token.c new file mode 100644 index 0000000..4efc742 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/persistent_token.c @@ -0,0 +1,714 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "pkcs11_token.h" +#include "pkcs11_helpers.h" + +#define PERSISTENT_OBJECT_ID_LEN 32 + +/* + * Token persistent objects + * + * The persistent objects are each identified by a UUID. + * The persistent object database stores the list of the UUIDs registered. For + * each it is expected that a file of ID "UUID" is stored in the TA secure + * storage. + */ +static TEE_Result get_db_file_name(struct ck_token *token, + char *name, size_t size) +{ + int n = snprintf(name, size, "token.db.%u", get_token_id(token)); + + if (n < 0 || (size_t)n >= size) + return TEE_ERROR_SECURITY; + else + return TEE_SUCCESS; +} + +static TEE_Result open_db_file(struct ck_token *token, + TEE_ObjectHandle *out_hdl) +{ + char file[PERSISTENT_OBJECT_ID_LEN] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + + res = get_db_file_name(token, file, sizeof(file)); + if (res) + return res; + + return TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE, + out_hdl); +} + +void update_persistent_db(struct ck_token *token) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; + + res = open_db_file(token, &db_hdl); + if (res) { + EMSG("Failed to open token persistent db: %#"PRIx32, res); + TEE_Panic(0); + } + res = TEE_WriteObjectData(db_hdl, token->db_main, + sizeof(*token->db_main)); + if (res) { + EMSG("Failed to write to token persistent db: %#"PRIx32, res); + TEE_Panic(0); + } + + TEE_CloseObject(db_hdl); +} + +static enum pkcs11_rc do_hash(uint32_t user, const uint8_t *pin, + size_t pin_size, uint32_t salt, + uint8_t hash[TEE_MAX_HASH_SIZE]) +{ + TEE_Result res = TEE_SUCCESS; + TEE_OperationHandle oh = TEE_HANDLE_NULL; + size_t sz = TEE_MAX_HASH_SIZE; + + res = TEE_AllocateOperation(&oh, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); + if (res) + return tee2pkcs_error(res); + + TEE_DigestUpdate(oh, &user, sizeof(user)); + TEE_DigestUpdate(oh, &salt, sizeof(salt)); + res = TEE_DigestDoFinal(oh, pin, pin_size, hash, &sz); + TEE_FreeOperation(oh); + + if (res) + return PKCS11_CKR_GENERAL_ERROR; + + memset(hash + sz, 0, TEE_MAX_HASH_SIZE - sz); + return PKCS11_CKR_OK; +} + +enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin, + size_t pin_size, uint32_t *salt, + uint8_t hash[TEE_MAX_HASH_SIZE]) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint32_t s = 0; + + TEE_GenerateRandom(&s, sizeof(s)); + if (!s) + s++; + + rc = do_hash(user, pin, pin_size, s, hash); + if (!rc) + *salt = s; + return rc; +} + +enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin, + size_t pin_size, uint32_t salt, + const uint8_t hash[TEE_MAX_HASH_SIZE]) +{ + uint8_t tmp_hash[TEE_MAX_HASH_SIZE] = { 0 }; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = do_hash(user, pin, pin_size, salt, tmp_hash); + if (rc) + return rc; + + if (buf_compare_ct(tmp_hash, hash, TEE_MAX_HASH_SIZE)) + rc = PKCS11_CKR_PIN_INCORRECT; + + return rc; +} + +#if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) +enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token) +{ + TEE_Identity identity = { }; + TEE_Result res = TEE_SUCCESS; + + res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, + "gpd.client.identity", &identity); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); + return PKCS11_CKR_PIN_INVALID; + } + + TEE_MemMove(&token->db_main->so_identity, &identity, sizeof(identity)); + token->db_main->flags |= PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; + + token->db_main->so_pin_salt = 0; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token, + enum pkcs11_user_type user_type, + const uint8_t *pin, + size_t pin_size) +{ + TEE_Identity identity = { }; + TEE_Result res = TEE_SUCCESS; + uint32_t flags_clear = 0; + uint32_t flags_set = 0; + char *acl_string = NULL; + char *uuid_str = NULL; + + assert(token->db_main->flags & + PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); + + if (!pin) { + /* Use client identity */ + res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, + "gpd.client.identity", + &identity); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, + res); + return PKCS11_CKR_PIN_INVALID; + } + } else { + /* Parse PIN ACL string: : */ + acl_string = TEE_Malloc(pin_size + 1, TEE_MALLOC_FILL_ZERO); + if (!acl_string) + return PKCS11_CKR_DEVICE_MEMORY; + TEE_MemMove(acl_string, pin, pin_size); + + uuid_str = strstr(acl_string, ":"); + if (uuid_str) + uuid_str++; + if (strcmp(PKCS11_AUTH_TEE_IDENTITY_PUBLIC, acl_string) == 0) { + identity.login = TEE_LOGIN_PUBLIC; + } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_USER) == + acl_string) { + identity.login = TEE_LOGIN_USER; + } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_GROUP) == + acl_string) { + identity.login = TEE_LOGIN_GROUP; + } else { + EMSG("Invalid PIN ACL string - login"); + TEE_Free(acl_string); + return PKCS11_CKR_PIN_INVALID; + } + + if (identity.login != TEE_LOGIN_PUBLIC) { + if (!uuid_str) { + EMSG("Invalid PIN ACL string - colon"); + TEE_Free(acl_string); + return PKCS11_CKR_PIN_INVALID; + } + + res = tee_uuid_from_str(&identity.uuid, uuid_str); + if (res) { + EMSG("Invalid PIN ACL string - client id"); + TEE_Free(acl_string); + return PKCS11_CKR_PIN_INVALID; + } + } + + TEE_Free(acl_string); + } + + switch (user_type) { + case PKCS11_CKU_SO: + token->db_main->so_pin_count = 0; + token->db_main->so_pin_salt = 0; + flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW | + PKCS11_CKFT_SO_PIN_FINAL_TRY | + PKCS11_CKFT_SO_PIN_LOCKED | + PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; + + TEE_MemMove(&token->db_main->so_identity, &identity, + sizeof(identity)); + break; + case PKCS11_CKU_USER: + token->db_main->user_pin_count = 0; + token->db_main->user_pin_salt = 0; + flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW | + PKCS11_CKFT_USER_PIN_FINAL_TRY | + PKCS11_CKFT_USER_PIN_LOCKED | + PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; + flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED; + + TEE_MemMove(&token->db_main->user_identity, &identity, + sizeof(identity)); + break; + default: + return PKCS11_CKR_FUNCTION_FAILED; + } + + token->db_main->flags &= ~flags_clear; + token->db_main->flags |= flags_set; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc verify_identity_auth(struct ck_token *token, + enum pkcs11_user_type user_type) +{ + TEE_Identity identity = { }; + TEE_Result res = TEE_SUCCESS; + + assert(token->db_main->flags & + PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); + + res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, + "gpd.client.identity", &identity); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); + return PKCS11_CKR_PIN_INVALID; + } + + if (user_type == PKCS11_CKU_SO) { + if (TEE_MemCompare(&token->db_main->so_identity, &identity, + sizeof(identity))) + return PKCS11_CKR_PIN_INCORRECT; + } else if (user_type == PKCS11_CKU_USER) { + if (TEE_MemCompare(&token->db_main->user_identity, &identity, + sizeof(identity))) + return PKCS11_CKR_PIN_INCORRECT; + } else { + return PKCS11_CKR_PIN_INCORRECT; + } + + return PKCS11_CKR_OK; +} +#endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ + +/* + * Release resources relate to persistent database + */ +void close_persistent_db(struct ck_token *token __unused) +{ +} + +static int get_persistent_obj_idx(struct ck_token *token, TEE_UUID *uuid) +{ + size_t i = 0; + + if (!uuid) + return -1; + + for (i = 0; i < token->db_objs->count; i++) + if (!TEE_MemCompare(token->db_objs->uuids + i, + uuid, sizeof(TEE_UUID))) + return i; + + return -1; +} + +/* UUID for persistent object */ +enum pkcs11_rc create_object_uuid(struct ck_token *token, + struct pkcs11_object *obj) +{ + assert(!obj->uuid); + + obj->uuid = TEE_Malloc(sizeof(TEE_UUID), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!obj->uuid) + return PKCS11_CKR_DEVICE_MEMORY; + + obj->token = token; + + do { + TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID)); + } while (get_persistent_obj_idx(token, obj->uuid) >= 0); + + return PKCS11_CKR_OK; +} + +void destroy_object_uuid(struct ck_token *token __maybe_unused, + struct pkcs11_object *obj) +{ + assert(get_persistent_obj_idx(token, obj->uuid) < 0); + + TEE_Free(obj->uuid); + obj->uuid = NULL; +} + +enum pkcs11_rc get_persistent_objects_list(struct ck_token *token, + TEE_UUID *array, size_t *size) +{ + size_t out_size = *size; + + *size = token->db_objs->count * sizeof(TEE_UUID); + + if (out_size < *size) + return PKCS11_CKR_BUFFER_TOO_SMALL; + + if (array) + TEE_MemMove(array, token->db_objs->uuids, *size); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc unregister_persistent_object(struct ck_token *token, + TEE_UUID *uuid) +{ + TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; + struct token_persistent_objs *ptr = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + int count = 0; + int idx = 0; + + if (!uuid) + return PKCS11_CKR_OK; + + idx = get_persistent_obj_idx(token, uuid); + if (idx < 0) { + DMSG("Cannot unregister an invalid persistent object"); + return PKCS11_RV_NOT_FOUND; + } + + ptr = TEE_Malloc(sizeof(struct token_persistent_objs) + + ((token->db_objs->count - 1) * sizeof(TEE_UUID)), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!ptr) + return PKCS11_CKR_DEVICE_MEMORY; + + res = open_db_file(token, &db_hdl); + if (res) + goto out; + + res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main), + TEE_DATA_SEEK_SET); + if (res) { + DMSG("Failed to read database"); + goto out; + } + + TEE_MemMove(ptr, token->db_objs, + sizeof(struct token_persistent_objs) + + idx * sizeof(TEE_UUID)); + + ptr->count--; + count = ptr->count - idx; + + TEE_MemMove(&ptr->uuids[idx], + &token->db_objs->uuids[idx + 1], + count * sizeof(TEE_UUID)); + + res = TEE_WriteObjectData(db_hdl, ptr, + sizeof(struct token_persistent_objs) + + ptr->count * sizeof(TEE_UUID)); + if (res) + DMSG("Failed to update database"); + TEE_Free(token->db_objs); + token->db_objs = ptr; + ptr = NULL; + +out: + TEE_CloseObject(db_hdl); + TEE_Free(ptr); + + return tee2pkcs_error(res); +} + +enum pkcs11_rc register_persistent_object(struct ck_token *token, + TEE_UUID *uuid) +{ + TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + void *ptr = NULL; + size_t size = 0; + int count = 0; + + if (get_persistent_obj_idx(token, uuid) >= 0) + TEE_Panic(0); + + count = token->db_objs->count; + ptr = TEE_Realloc(token->db_objs, + sizeof(struct token_persistent_objs) + + ((count + 1) * sizeof(TEE_UUID))); + if (!ptr) + return PKCS11_CKR_DEVICE_MEMORY; + + token->db_objs = ptr; + TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID)); + + size = sizeof(struct token_persistent_main) + + sizeof(struct token_persistent_objs) + + count * sizeof(TEE_UUID); + + res = open_db_file(token, &db_hdl); + if (res) + goto out; + + res = TEE_TruncateObjectData(db_hdl, size + sizeof(TEE_UUID)); + if (res) + goto out; + + res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main), + TEE_DATA_SEEK_SET); + if (res) + goto out; + + token->db_objs->count++; + + res = TEE_WriteObjectData(db_hdl, token->db_objs, + sizeof(struct token_persistent_objs) + + token->db_objs->count * sizeof(TEE_UUID)); + if (res) + token->db_objs->count--; + +out: + TEE_CloseObject(db_hdl); + + return tee2pkcs_error(res); +} + +enum pkcs11_rc load_persistent_object_attributes(struct pkcs11_object *obj) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle hdl = obj->attribs_hdl; + TEE_ObjectInfo info = { }; + struct obj_attrs *attr = NULL; + size_t read_bytes = 0; + + if (obj->attributes) + return PKCS11_CKR_OK; + + if (hdl == TEE_HANDLE_NULL) { + res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, + obj->uuid, sizeof(*obj->uuid), + TEE_DATA_FLAG_ACCESS_READ, &hdl); + if (res) { + EMSG("OpenPersistent failed %#"PRIx32, res); + return tee2pkcs_error(res); + } + } + + TEE_MemFill(&info, 0, sizeof(info)); + res = TEE_GetObjectInfo1(hdl, &info); + if (res) { + EMSG("GetObjectInfo failed %#"PRIx32, res); + rc = tee2pkcs_error(res); + goto out; + } + + attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO); + if (!attr) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes); + if (!res) { + res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET); + if (res) + EMSG("Seek to 0 failed %#"PRIx32, res); + } + + if (res) { + rc = tee2pkcs_error(res); + EMSG("Read %zu bytes, failed %#"PRIx32, + read_bytes, res); + goto out; + } + if (read_bytes != info.dataSize) { + EMSG("Read %zu bytes, expected %zu", + read_bytes, info.dataSize); + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + obj->attributes = attr; + attr = NULL; + + rc = PKCS11_CKR_OK; + +out: + TEE_Free(attr); + /* Close object only if it was open from this function */ + if (obj->attribs_hdl == TEE_HANDLE_NULL) + TEE_CloseObject(hdl); + + return rc; +} + +void release_persistent_object_attributes(struct pkcs11_object *obj) +{ + TEE_Free(obj->attributes); + obj->attributes = NULL; +} + +enum pkcs11_rc update_persistent_object_attributes(struct pkcs11_object *obj) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle hdl = TEE_HANDLE_NULL; + uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_WRITE; + size_t size = 0; + + assert(obj && obj->attributes); + + res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, + obj->uuid, sizeof(*obj->uuid), + tee_obj_flags, &hdl); + if (res) { + EMSG("OpenPersistent failed %#"PRIx32, res); + return tee2pkcs_error(res); + } + + size = sizeof(struct obj_attrs) + obj->attributes->attrs_size; + + res = TEE_WriteObjectData(hdl, obj->attributes, size); + if (res) + goto out; + + res = TEE_TruncateObjectData(hdl, size); + +out: + TEE_CloseObject(hdl); + return tee2pkcs_error(res); +} + +/* + * Return the token instance, either initialized from reset or initialized + * from the token persistent state if found. + */ +struct ck_token *init_persistent_db(unsigned int token_id) +{ + struct ck_token *token = get_token(token_id); + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; + /* Copy persistent database: main db and object db */ + struct token_persistent_main *db_main = NULL; + struct token_persistent_objs *db_objs = NULL; + void *ptr = NULL; + + if (!token) + return NULL; + + LIST_INIT(&token->object_list); + + db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO); + db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO); + if (!db_main || !db_objs) + goto error; + + res = open_db_file(token, &db_hdl); + + if (res == TEE_SUCCESS) { + size_t size = 0; + size_t idx = 0; + + IMSG("PKCS11 token %u: load db", token_id); + + size = sizeof(*db_main); + res = TEE_ReadObjectData(db_hdl, db_main, size, &size); + if (res || size != sizeof(*db_main)) + TEE_Panic(0); + + size = sizeof(*db_objs); + res = TEE_ReadObjectData(db_hdl, db_objs, size, &size); + if (res || size != sizeof(*db_objs)) + TEE_Panic(0); + + if (db_objs->count > 0) { + size += db_objs->count * sizeof(TEE_UUID); + ptr = TEE_Realloc(db_objs, size); + if (!ptr) + goto error; + + db_objs = ptr; + size -= sizeof(*db_objs); + res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size, + &size); + if (res || size != (db_objs->count * sizeof(TEE_UUID))) + TEE_Panic(0); + } + + for (idx = 0; idx < db_objs->count; idx++) { + /* Create an empty object instance */ + struct pkcs11_object *obj = NULL; + TEE_UUID *uuid = NULL; + + uuid = TEE_Malloc(sizeof(TEE_UUID), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!uuid) + goto error; + + TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid)); + + obj = create_token_object(NULL, uuid, token); + if (!obj) + TEE_Panic(0); + + LIST_INSERT_HEAD(&token->object_list, obj, link); + } + + } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { + char file[PERSISTENT_OBJECT_ID_LEN] = { }; + + IMSG("PKCS11 token %u: init db", token_id); + + TEE_MemFill(db_main, 0, sizeof(*db_main)); + TEE_MemFill(db_main->label, '*', sizeof(db_main->label)); + + db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED | + PKCS11_CKFT_USER_PIN_TO_BE_CHANGED | + PKCS11_CKFT_RNG | + PKCS11_CKFT_LOGIN_REQUIRED; + + res = get_db_file_name(token, file, sizeof(file)); + if (res) + TEE_Panic(0); + + /* + * Object stores persistent state + persistent object + * references. + */ + res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, + file, sizeof(file), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE, + TEE_HANDLE_NULL, + db_main, sizeof(*db_main), + &db_hdl); + if (res) { + EMSG("Failed to create db: %#"PRIx32, res); + goto error; + } + + res = TEE_TruncateObjectData(db_hdl, sizeof(*db_main) + + sizeof(*db_objs)); + if (res) + TEE_Panic(0); + + res = TEE_SeekObjectData(db_hdl, sizeof(*db_main), + TEE_DATA_SEEK_SET); + if (res) + TEE_Panic(0); + + db_objs->count = 0; + res = TEE_WriteObjectData(db_hdl, db_objs, sizeof(*db_objs)); + if (res) + TEE_Panic(0); + + } else { + goto error; + } + + token->db_main = db_main; + token->db_objs = db_objs; + TEE_CloseObject(db_hdl); + + return token; + +error: + TEE_Free(db_main); + TEE_Free(db_objs); + if (db_hdl != TEE_HANDLE_NULL) + TEE_CloseObject(db_hdl); + + return NULL; +} diff --git a/optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c b/optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c new file mode 100644 index 0000000..2bdfd7e --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_attributes.c @@ -0,0 +1,2576 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "handle.h" +#include "pkcs11_attributes.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "sanitize_object.h" +#include "serializer.h" +#include "token_capabilities.h" + +static uint32_t pkcs11_func2ckfm(enum processing_func function) +{ + switch (function) { + case PKCS11_FUNCTION_DIGEST: + return PKCS11_CKFM_DIGEST; + case PKCS11_FUNCTION_GENERATE: + return PKCS11_CKFM_GENERATE; + case PKCS11_FUNCTION_GENERATE_PAIR: + return PKCS11_CKFM_GENERATE_KEY_PAIR; + case PKCS11_FUNCTION_DERIVE: + return PKCS11_CKFM_DERIVE; + case PKCS11_FUNCTION_WRAP: + return PKCS11_CKFM_WRAP; + case PKCS11_FUNCTION_UNWRAP: + return PKCS11_CKFM_UNWRAP; + case PKCS11_FUNCTION_ENCRYPT: + return PKCS11_CKFM_ENCRYPT; + case PKCS11_FUNCTION_DECRYPT: + return PKCS11_CKFM_DECRYPT; + case PKCS11_FUNCTION_SIGN: + return PKCS11_CKFM_SIGN; + case PKCS11_FUNCTION_VERIFY: + return PKCS11_CKFM_VERIFY; + case PKCS11_FUNCTION_SIGN_RECOVER: + return PKCS11_CKFM_SIGN_RECOVER; + case PKCS11_FUNCTION_VERIFY_RECOVER: + return PKCS11_CKFM_VERIFY_RECOVER; + default: + return 0; + } +} + +enum pkcs11_rc +check_mechanism_against_processing(struct pkcs11_session *session, + enum pkcs11_mechanism_id mechanism_type, + enum processing_func function, + enum processing_step step) +{ + bool allowed = false; + + switch (step) { + case PKCS11_FUNC_STEP_INIT: + switch (function) { + case PKCS11_FUNCTION_IMPORT: + case PKCS11_FUNCTION_COPY: + case PKCS11_FUNCTION_MODIFY: + case PKCS11_FUNCTION_DESTROY: + return PKCS11_CKR_OK; + default: + break; + } + /* + * Check that the returned PKCS11_CKFM_* flag from + * pkcs11_func2ckfm() is among the ones from + * mechanism_supported_flags(). + */ + allowed = mechanism_supported_flags(mechanism_type) & + pkcs11_func2ckfm(function); + break; + + case PKCS11_FUNC_STEP_ONESHOT: + if (session->processing->always_authen && + !session->processing->relogged) + return PKCS11_CKR_USER_NOT_LOGGED_IN; + + if (session->processing->step == PKCS11_FUNC_STEP_UPDATE || + session->processing->step == PKCS11_FUNC_STEP_FINAL) { + EMSG("Cannot perform one-shot on active processing"); + return PKCS11_CKR_OPERATION_ACTIVE; + } + + allowed = true; + break; + + case PKCS11_FUNC_STEP_UPDATE: + if (session->processing->always_authen && + !session->processing->relogged) + return PKCS11_CKR_USER_NOT_LOGGED_IN; + + if (session->processing->step == PKCS11_FUNC_STEP_ONESHOT || + session->processing->step == PKCS11_FUNC_STEP_FINAL) { + EMSG("Cannot perform update on finalized processing"); + return PKCS11_CKR_OPERATION_ACTIVE; + } + + allowed = !mechanism_is_one_shot_only(mechanism_type); + break; + + case PKCS11_FUNC_STEP_UPDATE_KEY: + assert(function == PKCS11_FUNCTION_DIGEST); + + if (session->processing->always_authen && + !session->processing->relogged) + return PKCS11_CKR_USER_NOT_LOGGED_IN; + + allowed = true; + break; + + case PKCS11_FUNC_STEP_FINAL: + if (session->processing->always_authen && + !session->processing->relogged) + return PKCS11_CKR_USER_NOT_LOGGED_IN; + + if (session->processing->step == PKCS11_FUNC_STEP_ONESHOT) { + EMSG("Cannot perform final on oneshot processing"); + return PKCS11_CKR_OPERATION_ACTIVE; + } + return PKCS11_CKR_OK; + + default: + TEE_Panic(step); + break; + } + + if (!allowed) { + EMSG("Processing %#x/%s not permitted (%u/%u)", + (unsigned int)mechanism_type, id2str_proc(mechanism_type), + function, step); + return PKCS11_CKR_MECHANISM_INVALID; + } + + return PKCS11_CKR_OK; +} + +/* + * Object default boolean attributes as per PKCS#11 + */ +static uint8_t *pkcs11_object_default_boolprop(uint32_t attribute) +{ + static const uint8_t bool_true = 1; + static const uint8_t bool_false; + + switch (attribute) { + /* As per PKCS#11 default value */ + case PKCS11_CKA_MODIFIABLE: + case PKCS11_CKA_COPYABLE: + case PKCS11_CKA_DESTROYABLE: + return (uint8_t *)&bool_true; + case PKCS11_CKA_TOKEN: + case PKCS11_CKA_PRIVATE: + case PKCS11_CKA_WRAP_WITH_TRUSTED: + case PKCS11_CKA_ALWAYS_AUTHENTICATE: + case PKCS11_CKA_SENSITIVE: + return (uint8_t *)&bool_false; + /* Token specific default value */ + case PKCS11_CKA_SIGN: + case PKCS11_CKA_VERIFY: + case PKCS11_CKA_DERIVE: + case PKCS11_CKA_ENCRYPT: + case PKCS11_CKA_DECRYPT: + case PKCS11_CKA_SIGN_RECOVER: + case PKCS11_CKA_VERIFY_RECOVER: + case PKCS11_CKA_WRAP: + case PKCS11_CKA_UNWRAP: + case PKCS11_CKA_EXTRACTABLE: + case PKCS11_CKA_TRUSTED: + return (uint8_t *)&bool_false; + default: + DMSG("No default for boolprop attribute %#"PRIx32, attribute); + return NULL; + } +} + +/* + * Object expects several boolean attributes to be set to a default value + * or to a validate client configuration value. This function append the input + * attribute (id/size/value) in the serialized object. + */ +static enum pkcs11_rc pkcs11_import_object_boolprop(struct obj_attrs **out, + struct obj_attrs *templ, + uint32_t attribute) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint8_t bbool = 0; + uint32_t size = sizeof(uint8_t); + void *attr = NULL; + + rc = get_attribute(templ, attribute, &bbool, &size); + if (rc) { + if (rc != PKCS11_RV_NOT_FOUND) + return rc; + attr = pkcs11_object_default_boolprop(attribute); + if (!attr) + return PKCS11_CKR_TEMPLATE_INCOMPLETE; + } else { + attr = &bbool; + } + + /* Boolean attributes are 1byte in the ABI, no alignment issue */ + return add_attribute(out, attribute, attr, sizeof(uint8_t)); +} + +static enum pkcs11_rc set_mandatory_boolprops(struct obj_attrs **out, + struct obj_attrs *temp, + uint32_t const *bp, + size_t bp_count) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + size_t n = 0; + + for (n = 0; n < bp_count; n++) { + rc = pkcs11_import_object_boolprop(out, temp, bp[n]); + if (rc) + return rc; + } + + return rc; +} + +static enum pkcs11_rc set_mandatory_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + uint32_t const *attrs, + size_t attrs_count) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + size_t n = 0; + + for (n = 0; n < attrs_count; n++) { + uint32_t size = 0; + void *value = NULL; + + if (get_attribute_ptr(temp, attrs[n], &value, &size)) + return PKCS11_CKR_TEMPLATE_INCOMPLETE; + + rc = add_attribute(out, attrs[n], value, size); + if (rc) + return rc; + } + + return rc; +} + +static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id, void **value, + uint32_t *size) +{ + /* should have been taken care of already */ + assert(!pkcs11_attr_is_boolean(id)); + + /* All other attributes have an empty default value */ + *value = NULL; + *size = 0; + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc set_optional_attributes_with_def(struct obj_attrs **out, + struct obj_attrs *temp, + uint32_t const *attrs, + size_t attrs_count, + bool default_to_null) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + size_t n = 0; + + for (n = 0; n < attrs_count; n++) { + uint32_t size = 0; + void *value = NULL; + + rc = get_attribute_ptr(temp, attrs[n], &value, &size); + if (rc == PKCS11_RV_NOT_FOUND) { + if (default_to_null) { + rc = get_default_value(attrs[n], &value, &size); + } else { + rc = PKCS11_CKR_OK; + continue; + } + } + if (rc) + return rc; + + rc = add_attribute(out, attrs[n], value, size); + if (rc) + return rc; + } + + return rc; +} + +static enum pkcs11_rc set_attributes_opt_or_null(struct obj_attrs **out, + struct obj_attrs *temp, + uint32_t const *attrs, + size_t attrs_count) +{ + return set_optional_attributes_with_def(out, temp, attrs, attrs_count, + true /* defaults to empty */); +} + +static enum pkcs11_rc set_optional_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + uint32_t const *attrs, + size_t attrs_count) +{ + return set_optional_attributes_with_def(out, temp, attrs, attrs_count, + false /* no default value */); +} + +/* + * Below are listed the mandated or optional expected attributes for + * PKCS#11 storage objects. + * + * Note: boolprops (mandated boolean attributes) PKCS11_CKA_ALWAYS_SENSITIVE, + * and PKCS11_CKA_NEVER_EXTRACTABLE are set by the token, not provided + * in the client template. + */ + +/* PKCS#11 specification for any object (session/token) of the storage */ +static const uint32_t any_object_boolprops[] = { + PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE, + PKCS11_CKA_MODIFIABLE, PKCS11_CKA_COPYABLE, PKCS11_CKA_DESTROYABLE, +}; + +static const uint32_t any_object_opt_or_null[] = { + PKCS11_CKA_LABEL, +}; + +/* PKCS#11 specification for raw data object (+any_object_xxx) */ +const uint32_t raw_data_opt_or_null[] = { + PKCS11_CKA_OBJECT_ID, PKCS11_CKA_APPLICATION, PKCS11_CKA_VALUE, +}; + +/* PKCS#11 specification for certificate object (+pkcs11_any_object_xxx) */ +static const uint32_t pkcs11_certificate_mandated[] = { + PKCS11_CKA_CERTIFICATE_TYPE, +}; + +static const uint32_t pkcs11_certificate_boolprops[] = { + PKCS11_CKA_TRUSTED, +}; + +static const uint32_t pkcs11_certificate_optional[] = { + PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_CHECK_VALUE, + PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO, +}; + +/* + * PKCS#11 specification for X.509 certificate object (+pkcs11_certificate_xxx) + */ +static const uint32_t pkcs11_x509_certificate_mandated[] = { + PKCS11_CKA_SUBJECT, +}; + +static const uint32_t pkcs11_x509_certificate_optional[] = { + PKCS11_CKA_ID, PKCS11_CKA_ISSUER, PKCS11_CKA_SERIAL_NUMBER, + PKCS11_CKA_VALUE, PKCS11_CKA_URL, + PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY, + PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY, + PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, PKCS11_CKA_NAME_HASH_ALGORITHM, +}; + +/* PKCS#11 specification for any key object (+any_object_xxx) */ +static const uint32_t any_key_boolprops[] = { + PKCS11_CKA_DERIVE, +}; + +static const uint32_t any_key_opt_or_null[] = { + PKCS11_CKA_ID, + PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, +}; + +static const uint32_t any_key_optional[] = { + PKCS11_CKA_ALLOWED_MECHANISMS, +}; + +/* PKCS#11 specification for any symmetric key (+any_key_xxx) */ +static const uint32_t symm_key_boolprops[] = { + PKCS11_CKA_ENCRYPT, PKCS11_CKA_DECRYPT, + PKCS11_CKA_SIGN, PKCS11_CKA_VERIFY, + PKCS11_CKA_WRAP, PKCS11_CKA_UNWRAP, + PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE, + PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_TRUSTED, +}; + +static const uint32_t symm_key_opt_or_null[] = { + PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_UNWRAP_TEMPLATE, + PKCS11_CKA_DERIVE_TEMPLATE, PKCS11_CKA_VALUE, +}; + +static const uint32_t symm_key_optional[] = { + PKCS11_CKA_VALUE_LEN, +}; + +/* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */ +static const uint32_t public_key_boolprops[] = { + PKCS11_CKA_ENCRYPT, PKCS11_CKA_VERIFY, PKCS11_CKA_VERIFY_RECOVER, + PKCS11_CKA_WRAP, + PKCS11_CKA_TRUSTED, +}; + +static const uint32_t public_key_mandated[] = { +}; + +static const uint32_t public_key_opt_or_null[] = { + PKCS11_CKA_SUBJECT, PKCS11_CKA_WRAP_TEMPLATE, + PKCS11_CKA_PUBLIC_KEY_INFO, +}; + +/* PKCS#11 specification for any asymmetric private key (+any_key_xxx) */ +static const uint32_t private_key_boolprops[] = { + PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_SIGN_RECOVER, + PKCS11_CKA_UNWRAP, + PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE, + PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_ALWAYS_AUTHENTICATE, +}; + +static const uint32_t private_key_mandated[] = { +}; + +static const uint32_t private_key_opt_or_null[] = { + PKCS11_CKA_SUBJECT, PKCS11_CKA_UNWRAP_TEMPLATE, + PKCS11_CKA_PUBLIC_KEY_INFO, +}; + +/* PKCS#11 specification for any RSA key (+public/private_key_xxx) */ +static const uint32_t rsa_pub_key_gen_mand[] = { + PKCS11_CKA_MODULUS_BITS, +}; + +static const uint32_t rsa_pub_key_create_mand[] = { + PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT, +}; + +static const uint32_t rsa_pub_key_gen_opt_or_null[] = { + PKCS11_CKA_PUBLIC_EXPONENT, +}; + +static const uint32_t rsa_priv_key_opt_or_null[] = { + PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT, + PKCS11_CKA_PRIVATE_EXPONENT, + PKCS11_CKA_PRIME_1, PKCS11_CKA_PRIME_2, + PKCS11_CKA_EXPONENT_1, PKCS11_CKA_EXPONENT_2, PKCS11_CKA_COEFFICIENT, +}; + +/* PKCS#11 specification for any EC key (+public/private_key_xxx) */ +static const uint32_t ec_public_key_mandated[] = { + PKCS11_CKA_EC_PARAMS, +}; + +static const uint32_t ec_public_key_opt_or_null[] = { + PKCS11_CKA_EC_POINT, +}; + +static const uint32_t ec_private_key_mandated[] = { +}; + +static const uint32_t ec_private_key_opt_or_null[] = { + PKCS11_CKA_EC_PARAMS, + PKCS11_CKA_VALUE, +}; + +static const uint32_t eddsa_private_key_opt_or_null[] = { + PKCS11_CKA_EC_PARAMS, + PKCS11_CKA_VALUE, + PKCS11_CKA_EC_POINT, +}; + +static enum pkcs11_rc create_storage_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = init_attributes_head(out); + if (rc) + return rc; + + /* Object class is mandatory */ + class = get_class(temp); + if (class == PKCS11_CKO_UNDEFINED_ID) { + EMSG("Class attribute not found"); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + rc = add_attribute(out, PKCS11_CKA_CLASS, &class, sizeof(uint32_t)); + if (rc) + return rc; + + rc = set_mandatory_boolprops(out, temp, any_object_boolprops, + ARRAY_SIZE(any_object_boolprops)); + if (rc) + return rc; + + return set_attributes_opt_or_null(out, temp, any_object_opt_or_null, + ARRAY_SIZE(any_object_opt_or_null)); +} + +static enum pkcs11_rc create_genkey_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + uint32_t type = PKCS11_CKO_UNDEFINED_ID; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = create_storage_attributes(out, temp); + if (rc) + return rc; + + type = get_key_type(temp); + if (type == PKCS11_CKK_UNDEFINED_ID) { + EMSG("Key type attribute not found"); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + rc = add_attribute(out, PKCS11_CKA_KEY_TYPE, &type, sizeof(uint32_t)); + if (rc) + return rc; + + rc = set_mandatory_boolprops(out, temp, any_key_boolprops, + ARRAY_SIZE(any_key_boolprops)); + if (rc) + return rc; + + rc = set_attributes_opt_or_null(out, temp, any_key_opt_or_null, + ARRAY_SIZE(any_key_opt_or_null)); + if (rc) + return rc; + + return set_optional_attributes(out, temp, any_key_optional, + ARRAY_SIZE(any_key_optional)); + +} + +static enum pkcs11_rc create_symm_key_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_SECRET_KEY); + + rc = create_genkey_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_SECRET_KEY); + + switch (get_key_type(*out)) { + case PKCS11_CKK_GENERIC_SECRET: + case PKCS11_CKK_AES: + case PKCS11_CKK_MD5_HMAC: + case PKCS11_CKK_SHA_1_HMAC: + case PKCS11_CKK_SHA256_HMAC: + case PKCS11_CKK_SHA384_HMAC: + case PKCS11_CKK_SHA512_HMAC: + case PKCS11_CKK_SHA224_HMAC: + break; + default: + EMSG("Invalid key type %#"PRIx32"/%s", + get_key_type(*out), id2str_key_type(get_key_type(*out))); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + rc = set_mandatory_boolprops(out, temp, symm_key_boolprops, + ARRAY_SIZE(symm_key_boolprops)); + if (rc) + return rc; + + rc = set_attributes_opt_or_null(out, temp, symm_key_opt_or_null, + ARRAY_SIZE(symm_key_opt_or_null)); + if (rc) + return rc; + + return set_optional_attributes(out, temp, symm_key_optional, + ARRAY_SIZE(symm_key_optional)); +} + +static enum pkcs11_rc create_data_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_DATA); + + rc = create_storage_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_DATA); + + return set_attributes_opt_or_null(out, temp, raw_data_opt_or_null, + ARRAY_SIZE(raw_data_opt_or_null)); +} + +static enum pkcs11_rc create_certificate_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + uint32_t const *mandated = NULL; + uint32_t const *optional = NULL; + size_t mandated_count = 0; + size_t optional_count = 0; + void *attr_value = NULL; + uint32_t attr_size = 0; + uint32_t default_cert_category = + PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED; + uint32_t default_name_hash_alg = PKCS11_CKM_SHA_1; + uint32_t cert_category = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_CERTIFICATE); + + rc = create_storage_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_CERTIFICATE); + + rc = set_mandatory_boolprops(out, temp, pkcs11_certificate_boolprops, + ARRAY_SIZE(pkcs11_certificate_boolprops)); + if (rc) + return rc; + + rc = set_mandatory_attributes(out, temp, pkcs11_certificate_mandated, + ARRAY_SIZE(pkcs11_certificate_mandated)); + if (rc) + return rc; + + rc = set_optional_attributes(out, temp, pkcs11_certificate_optional, + ARRAY_SIZE(pkcs11_certificate_optional)); + if (rc) + return rc; + + switch (get_certificate_type(*out)) { + case PKCS11_CKC_X_509: + mandated = pkcs11_x509_certificate_mandated; + optional = pkcs11_x509_certificate_optional; + mandated_count = ARRAY_SIZE(pkcs11_x509_certificate_mandated); + optional_count = ARRAY_SIZE(pkcs11_x509_certificate_optional); + break; + default: + EMSG("Invalid certificate type %#"PRIx32"/%s", + get_certificate_type(*out), + id2str_certificate_type(get_certificate_type(*out))); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + rc = set_mandatory_attributes(out, temp, mandated, mandated_count); + if (rc) + return rc; + + rc = set_optional_attributes(out, temp, optional, optional_count); + if (rc) + return rc; + + attr_size = 0; + rc = get_attribute_ptr(*out, PKCS11_CKA_CERTIFICATE_CATEGORY, + &attr_value, &attr_size); + if (rc == PKCS11_CKR_OK && attr_size == sizeof(cert_category)) { + /* Sanitize certificate category */ + TEE_MemMove(&cert_category, attr_value, sizeof(cert_category)); + + switch (cert_category) { + case PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED: + case PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER: + case PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY: + case PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY: + break; + default: + EMSG("Invalid certificate category %#"PRIx32, + cert_category); + + return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; + } + } else if (rc == PKCS11_RV_NOT_FOUND) { + /* Set default category when missing */ + rc = set_attribute(out, PKCS11_CKA_CERTIFICATE_CATEGORY, + &default_cert_category, + sizeof(default_cert_category)); + if (rc) + return rc; + } else { + /* All other cases are errors */ + EMSG("Invalid certificate category"); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + attr_size = 0; + rc = get_attribute_ptr(*out, PKCS11_CKA_NAME_HASH_ALGORITHM, NULL, + &attr_size); + if (rc == PKCS11_CKR_OK && attr_size == sizeof(uint32_t)) { + /* We accept any algorithm what caller wanted to specify */ + } else if (rc == PKCS11_RV_NOT_FOUND) { + /* Set default hash algorithm when missing */ + rc = set_attribute(out, PKCS11_CKA_NAME_HASH_ALGORITHM, + &default_name_hash_alg, + sizeof(default_name_hash_alg)); + if (rc) + return rc; + } else { + /* All other cases are errors */ + EMSG("Invalid name hash algorithm"); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + return rc; +} + +static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + enum processing_func function) +{ + uint32_t const *mandated = NULL; + uint32_t const *oon = NULL; + size_t mandated_count = 0; + size_t oon_count = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_PUBLIC_KEY); + + rc = create_genkey_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_PUBLIC_KEY); + + rc = set_mandatory_boolprops(out, temp, public_key_boolprops, + ARRAY_SIZE(public_key_boolprops)); + if (rc) + return rc; + + rc = set_mandatory_attributes(out, temp, public_key_mandated, + ARRAY_SIZE(public_key_mandated)); + if (rc) + return rc; + + rc = set_attributes_opt_or_null(out, temp, + public_key_opt_or_null, + ARRAY_SIZE(public_key_opt_or_null)); + if (rc) + return rc; + + switch (get_key_type(*out)) { + case PKCS11_CKK_RSA: + switch (function) { + case PKCS11_FUNCTION_GENERATE_PAIR: + mandated = rsa_pub_key_gen_mand; + oon = rsa_pub_key_gen_opt_or_null; + mandated_count = ARRAY_SIZE(rsa_pub_key_gen_mand); + oon_count = ARRAY_SIZE(rsa_pub_key_gen_opt_or_null); + break; + case PKCS11_FUNCTION_IMPORT: + mandated = rsa_pub_key_create_mand; + mandated_count = ARRAY_SIZE(rsa_pub_key_create_mand); + break; + default: + EMSG("Unsupported function %#"PRIx32"/%s", function, + id2str_function(function)); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + break; + case PKCS11_CKK_EC: + case PKCS11_CKK_EC_EDWARDS: + mandated = ec_public_key_mandated; + oon = ec_public_key_opt_or_null; + mandated_count = ARRAY_SIZE(ec_public_key_mandated); + oon_count = ARRAY_SIZE(ec_public_key_opt_or_null); + break; + default: + EMSG("Invalid key type %#"PRIx32"/%s", + get_key_type(*out), id2str_key_type(get_key_type(*out))); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + rc = set_mandatory_attributes(out, temp, mandated, mandated_count); + if (rc) + return rc; + + return set_attributes_opt_or_null(out, temp, oon, oon_count); +} + +static enum pkcs11_rc create_priv_key_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + uint32_t const *mandated = NULL; + uint32_t const *oon = NULL; + size_t mandated_count = 0; + size_t oon_count = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_PRIVATE_KEY); + + rc = create_genkey_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_PRIVATE_KEY); + + rc = set_mandatory_boolprops(out, temp, private_key_boolprops, + ARRAY_SIZE(private_key_boolprops)); + if (rc) + return rc; + + rc = set_mandatory_attributes(out, temp, private_key_mandated, + ARRAY_SIZE(private_key_mandated)); + if (rc) + return rc; + + rc = set_attributes_opt_or_null(out, temp, private_key_opt_or_null, + ARRAY_SIZE(private_key_opt_or_null)); + if (rc) + return rc; + + switch (get_key_type(*out)) { + case PKCS11_CKK_RSA: + oon = rsa_priv_key_opt_or_null; + oon_count = ARRAY_SIZE(rsa_priv_key_opt_or_null); + break; + case PKCS11_CKK_EC: + mandated = ec_private_key_mandated; + oon = ec_private_key_opt_or_null; + mandated_count = ARRAY_SIZE(ec_private_key_mandated); + oon_count = ARRAY_SIZE(ec_private_key_opt_or_null); + break; + case PKCS11_CKK_EC_EDWARDS: + mandated = ec_private_key_mandated; + oon = eddsa_private_key_opt_or_null; + mandated_count = ARRAY_SIZE(ec_private_key_mandated); + oon_count = ARRAY_SIZE(eddsa_private_key_opt_or_null); + break; + default: + EMSG("Invalid key type %#"PRIx32"/%s", + get_key_type(*out), id2str_key_type(get_key_type(*out))); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + rc = set_mandatory_attributes(out, temp, mandated, mandated_count); + if (rc) + return rc; + + return set_attributes_opt_or_null(out, temp, oon, oon_count); +} + +static enum pkcs11_rc +sanitize_symm_key_attributes(struct obj_attrs **temp, + enum processing_func function) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint32_t a_size = 0; + + assert(get_class(*temp) == PKCS11_CKO_SECRET_KEY); + + rc = get_attribute_ptr(*temp, PKCS11_CKA_VALUE, NULL, &a_size); + + switch (get_key_type(*temp)) { + case PKCS11_CKK_GENERIC_SECRET: + case PKCS11_CKK_AES: + case PKCS11_CKK_MD5_HMAC: + case PKCS11_CKK_SHA_1_HMAC: + case PKCS11_CKK_SHA256_HMAC: + case PKCS11_CKK_SHA384_HMAC: + case PKCS11_CKK_SHA512_HMAC: + case PKCS11_CKK_SHA224_HMAC: + switch (function) { + case PKCS11_FUNCTION_IMPORT: + /* CKA_VALUE is a mandatory with C_CreateObject */ + if (rc || a_size == 0) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + + if (get_attribute_ptr(*temp, PKCS11_CKA_VALUE_LEN, NULL, + NULL) != PKCS11_RV_NOT_FOUND) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + + return add_attribute(temp, PKCS11_CKA_VALUE_LEN, + &a_size, sizeof(uint32_t)); + case PKCS11_FUNCTION_GENERATE: + if (rc != PKCS11_RV_NOT_FOUND) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + break; + default: + break; + } + break; + default: + EMSG("Invalid key type %#"PRIx32"/%s", + get_key_type(*temp), id2str_key_type(get_key_type(*temp))); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + return PKCS11_CKR_OK; +} + +/* + * Create an attribute list for a new object from a template and a parent + * object (optional) for an object generation function (generate, copy, + * derive...). + * + * PKCS#11 directives on the supplied template and expected return value: + * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID + * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID + * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY + * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT + * + * INFO on PKCS11_CMD_COPY_OBJECT: + * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED. + * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE, + * PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE. + * - SENSITIVE can change from false to true, not from true to false. + * - LOCAL is the parent LOCAL + */ +enum pkcs11_rc +create_attributes_from_template(struct obj_attrs **out, void *template, + size_t template_size, + struct obj_attrs *parent, + enum processing_func function, + enum pkcs11_mechanism_id mecha, + enum pkcs11_class_id template_class) +{ + struct obj_attrs *temp = NULL; + struct obj_attrs *attrs = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint8_t local = 0; + uint8_t always_sensitive = 0; + uint8_t never_extract = 0; + uint8_t extractable = 0; + uint32_t class = PKCS11_UNDEFINED_ID; + uint32_t type = PKCS11_UNDEFINED_ID; + uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID; + struct obj_attrs *req_attrs = NULL; + uint32_t size = 0; + uint32_t indirect_template = PKCS11_CKA_UNDEFINED_ID; + +#ifdef DEBUG /* Sanity: check function argument */ + trace_attributes_from_api_head("template", template, template_size); + switch (function) { + case PKCS11_FUNCTION_GENERATE: + case PKCS11_FUNCTION_GENERATE_PAIR: + case PKCS11_FUNCTION_IMPORT: + case PKCS11_FUNCTION_MODIFY: + case PKCS11_FUNCTION_DERIVE: + case PKCS11_FUNCTION_UNWRAP: + case PKCS11_FUNCTION_COPY: + break; + default: + TEE_Panic(TEE_ERROR_NOT_SUPPORTED); + } +#endif + + /* + * For PKCS11_FUNCTION_GENERATE, find the class and type + * based on the mechanism. These will be passed as hint + * sanitize_client_object() and added in temp if not + * already present + */ + if (function == PKCS11_FUNCTION_GENERATE) { + switch (mecha) { + case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: + class = PKCS11_CKO_SECRET_KEY; + type = PKCS11_CKK_GENERIC_SECRET; + break; + case PKCS11_CKM_AES_KEY_GEN: + class = PKCS11_CKO_SECRET_KEY; + type = PKCS11_CKK_AES; + break; + default: + TEE_Panic(TEE_ERROR_NOT_SUPPORTED); + } + } + + /* + * For PKCS11_FUNCTION_GENERATE_PAIR, find the class and type + * based on the mechanism. These will be passed as hint + * sanitize_client_object() and added in temp if not + * already present + */ + if (function == PKCS11_FUNCTION_GENERATE_PAIR) { + switch (mecha) { + case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: + class = template_class; + type = PKCS11_CKK_EDDSA; + break; + case PKCS11_CKM_EC_KEY_PAIR_GEN: + class = template_class; + type = PKCS11_CKK_EC; + break; + case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: + class = template_class; + type = PKCS11_CKK_RSA; + break; + default: + TEE_Panic(TEE_ERROR_NOT_SUPPORTED); + } + } + + /* + * Check and remove duplicates if any and create a new temporary + * template + */ + rc = sanitize_client_object(&temp, template, template_size, class, + type); + if (rc) + goto out; + + /* + * For function type modify and copy return the created template + * from here. Rest of the code below is for creating objects + * or generating keys. + */ + switch (function) { + case PKCS11_FUNCTION_MODIFY: + case PKCS11_FUNCTION_COPY: + *out = temp; + return rc; + case PKCS11_FUNCTION_DERIVE: + case PKCS11_FUNCTION_UNWRAP: + if (function == PKCS11_FUNCTION_UNWRAP) + indirect_template = PKCS11_CKA_UNWRAP_TEMPLATE; + else + indirect_template = PKCS11_CKA_DERIVE_TEMPLATE; + + rc = get_attribute_ptr(parent, indirect_template, + (void *)&req_attrs, &size); + if (rc == PKCS11_CKR_OK && size != 0) { + rc = attributes_match_add_reference(&temp, req_attrs); + if (rc) + goto out; + } + break; + default: + break; + } + + /* + * Check if class and type in temp are consistent with the mechanism + */ + switch (mecha) { + case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: + if (get_class(temp) != PKCS11_CKO_SECRET_KEY || + get_key_type(temp) != PKCS11_CKK_GENERIC_SECRET) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + break; + case PKCS11_CKM_AES_KEY_GEN: + if (get_class(temp) != PKCS11_CKO_SECRET_KEY || + get_key_type(temp) != PKCS11_CKK_AES) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + break; + case PKCS11_CKM_EC_KEY_PAIR_GEN: + if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY && + get_class(temp) != PKCS11_CKO_PRIVATE_KEY) || + get_key_type(temp) != PKCS11_CKK_EC) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + break; + case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: + if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY && + get_class(temp) != PKCS11_CKO_PRIVATE_KEY) || + get_key_type(temp) != PKCS11_CKK_EC_EDWARDS) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + break; + case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: + if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY && + get_class(temp) != PKCS11_CKO_PRIVATE_KEY) || + get_key_type(temp) != PKCS11_CKK_RSA) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + break; + default: + break; + } + + if (!sanitize_consistent_class_and_type(temp)) { + EMSG("Inconsistent class/type"); + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + + /* + * TBD - Add a check to see if temp contains any attribute which + * is not consistent with the object class or type and return error. + * In current implementation such attributes are ignored and not + * added to final object while PKCS#11 specification expects a + * failure and an error code be returned. + */ + + switch (get_class(temp)) { + case PKCS11_CKO_DATA: + rc = create_data_attributes(&attrs, temp); + break; + case PKCS11_CKO_CERTIFICATE: + rc = create_certificate_attributes(&attrs, temp); + break; + case PKCS11_CKO_SECRET_KEY: + rc = sanitize_symm_key_attributes(&temp, function); + if (rc) + goto out; + rc = create_symm_key_attributes(&attrs, temp); + break; + case PKCS11_CKO_PUBLIC_KEY: + rc = create_pub_key_attributes(&attrs, temp, function); + break; + case PKCS11_CKO_PRIVATE_KEY: + rc = create_priv_key_attributes(&attrs, temp); + break; + default: + DMSG("Invalid object class %#"PRIx32"/%s", + get_class(temp), id2str_class(get_class(temp))); + + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + break; + } + if (rc) + goto out; + + if (get_attribute_ptr(temp, PKCS11_CKA_LOCAL, NULL, NULL) != + PKCS11_RV_NOT_FOUND) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + + if (get_attribute_ptr(temp, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) != + PKCS11_RV_NOT_FOUND) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + + switch (function) { + case PKCS11_FUNCTION_GENERATE: + case PKCS11_FUNCTION_GENERATE_PAIR: + local = PKCS11_TRUE; + break; + case PKCS11_FUNCTION_IMPORT: + case PKCS11_FUNCTION_DERIVE: + case PKCS11_FUNCTION_UNWRAP: + default: + local = PKCS11_FALSE; + break; + } + rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local)); + if (rc) + goto out; + + switch (get_class(attrs)) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PRIVATE_KEY: + case PKCS11_CKO_PUBLIC_KEY: + always_sensitive = PKCS11_FALSE; + never_extract = PKCS11_FALSE; + + switch (function) { + case PKCS11_FUNCTION_DERIVE: + always_sensitive = + get_bool(parent, PKCS11_CKA_ALWAYS_SENSITIVE) && + get_bool(attrs, PKCS11_CKA_SENSITIVE); + never_extract = + get_bool(parent, PKCS11_CKA_NEVER_EXTRACTABLE) && + !get_bool(attrs, PKCS11_CKA_EXTRACTABLE); + break; + case PKCS11_FUNCTION_UNWRAP: + always_sensitive = PKCS11_FALSE; + never_extract = PKCS11_FALSE; + extractable = PKCS11_TRUE; + + /* + * Check if template passed by user has CKA_EXTRACTABLE. + * If not, by default value of CKA_EXTRACTABLE is set as + * TRUE. + */ + if (get_attribute_ptr(temp, PKCS11_CKA_EXTRACTABLE, + NULL, + NULL) == PKCS11_RV_NOT_FOUND) { + rc = set_attribute(&attrs, + PKCS11_CKA_EXTRACTABLE, + &extractable, + sizeof(extractable)); + if (rc) + goto out; + } + break; + case PKCS11_FUNCTION_GENERATE: + case PKCS11_FUNCTION_GENERATE_PAIR: + always_sensitive = get_bool(attrs, + PKCS11_CKA_SENSITIVE); + never_extract = !get_bool(attrs, + PKCS11_CKA_EXTRACTABLE); + break; + default: + break; + } + + rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE, + &always_sensitive, sizeof(always_sensitive)); + if (rc) + goto out; + + rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE, + &never_extract, sizeof(never_extract)); + if (rc) + goto out; + + /* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */ + if (local) + mechanism_id = mecha; + else + mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION; + + rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM, + &mechanism_id, sizeof(mechanism_id)); + if (rc) + goto out; + break; + + default: + break; + } + + *out = attrs; + +#ifdef DEBUG + trace_attributes("object", attrs); +#endif + +out: + TEE_Free(temp); + if (rc) + TEE_Free(attrs); + + return rc; +} + +static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head) +{ + if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) && + get_bool(head, PKCS11_CKA_EXTRACTABLE)) { + DMSG("Never/Extractable attributes mismatch %d/%d", + get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE), + get_bool(head, PKCS11_CKA_EXTRACTABLE)); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) && + !get_bool(head, PKCS11_CKA_SENSITIVE)) { + DMSG("Sensitive/always attributes mismatch %d/%d", + get_bool(head, PKCS11_CKA_SENSITIVE), + get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE)); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + return PKCS11_CKR_OK; +} + +bool object_is_private(struct obj_attrs *head) +{ + return get_bool(head, PKCS11_CKA_PRIVATE); +} + +bool object_is_token(struct obj_attrs *head) +{ + return get_bool(head, PKCS11_CKA_TOKEN); +} + +bool object_is_modifiable(struct obj_attrs *head) +{ + return get_bool(head, PKCS11_CKA_MODIFIABLE); +} + +bool object_is_copyable(struct obj_attrs *head) +{ + return get_bool(head, PKCS11_CKA_COPYABLE); +} + +/* + * Check access to object against authentication to token + */ +enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session, + struct obj_attrs *head) +{ + bool private = true; + + switch (get_class(head)) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PRIVATE_KEY: + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_DATA: + case PKCS11_CKO_CERTIFICATE: + private = object_is_private(head); + break; + default: + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + + if (private && (pkcs11_session_is_public(session) || + pkcs11_session_is_so(session))) { + DMSG("Private object access from a public or SO session"); + + return PKCS11_CKR_USER_NOT_LOGGED_IN; + } + + return PKCS11_CKR_OK; +} + +/* + * Check the attributes of a to-be-created object matches the token state + */ +enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session, + struct obj_attrs *head) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = check_attrs_misc_integrity(head); + if (rc) + return rc; + + if (get_bool(head, PKCS11_CKA_TRUSTED) && + !pkcs11_session_is_so(session)) { + DMSG("Can't create trusted object"); + + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + + if (get_bool(head, PKCS11_CKA_TOKEN) && + !pkcs11_session_is_read_write(session)) { + DMSG("Can't create persistent object"); + + return PKCS11_CKR_SESSION_READ_ONLY; + } + + /* + * TODO: START_DATE and END_DATE: complies with current time? + */ + return PKCS11_CKR_OK; +} + +#define DMSG_BAD_BBOOL(attr, proc, head) \ + do { \ + uint32_t __maybe_unused _attr = (attr); \ + uint8_t __maybe_unused _bvalue = 0; \ + enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK; \ + \ + _rc = get_attribute((head), _attr, &_bvalue, NULL); \ + DMSG("%s issue for %s: %sfound, value %"PRIu8, \ + id2str_attr(_attr), id2str_proc((proc)), \ + _rc ? "not " : "", _bvalue); \ + } while (0) + +static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused, + struct obj_attrs *head, + uint32_t attribute, bool val) +{ + uint8_t bbool = 0; + uint32_t sz = sizeof(bbool); + + if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val) + return true; + + DMSG_BAD_BBOOL(attribute, proc_id, head); + return false; +} + +/* + * Check the attributes of a new secret match the processing/mechanism + * used to create it. + * + * @proc_id - PKCS11_CKM_xxx + * @head - head of the attributes of the to-be-created object. + */ +enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id, + struct obj_attrs *head) +{ + /* + * Processings that do not create secrets are not expected to call + * this function which would panic. + */ + switch (proc_id) { + case PKCS11_PROCESSING_IMPORT: + case PKCS11_CKM_ECDH1_DERIVE: + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: + case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: + case PKCS11_CKM_RSA_AES_KEY_WRAP: + assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false)); + break; + case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: + case PKCS11_CKM_AES_KEY_GEN: + case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: + case PKCS11_CKM_EC_KEY_PAIR_GEN: + case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: + assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, true)); + break; + default: + TEE_Panic(proc_id); + break; + } + + switch (proc_id) { + case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: + assert(get_key_type(head) == PKCS11_CKK_GENERIC_SECRET); + break; + case PKCS11_CKM_AES_KEY_GEN: + assert(get_key_type(head) == PKCS11_CKK_AES); + break; + case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: + assert(get_key_type(head) == PKCS11_CKK_EC_EDWARDS); + break; + case PKCS11_CKM_EC_KEY_PAIR_GEN: + assert(get_key_type(head) == PKCS11_CKK_EC); + break; + case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: + assert(get_key_type(head) == PKCS11_CKK_RSA); + break; + case PKCS11_PROCESSING_IMPORT: + case PKCS11_CKM_ECDH1_DERIVE: + default: + break; + } + + return PKCS11_CKR_OK; +} + +/* Return min and max key size supported for a key_type in bytes */ +static void get_key_min_max_sizes(enum pkcs11_key_type key_type, + uint32_t *min_key_size, + uint32_t *max_key_size) +{ + enum pkcs11_mechanism_id mechanism = PKCS11_CKM_UNDEFINED_ID; + + switch (key_type) { + case PKCS11_CKK_GENERIC_SECRET: + mechanism = PKCS11_CKM_GENERIC_SECRET_KEY_GEN; + break; + case PKCS11_CKK_AES: + mechanism = PKCS11_CKM_AES_KEY_GEN; + break; + case PKCS11_CKK_MD5_HMAC: + mechanism = PKCS11_CKM_MD5_HMAC; + break; + case PKCS11_CKK_SHA_1_HMAC: + mechanism = PKCS11_CKM_SHA_1_HMAC; + break; + case PKCS11_CKK_SHA224_HMAC: + mechanism = PKCS11_CKM_SHA224_HMAC; + break; + case PKCS11_CKK_SHA256_HMAC: + mechanism = PKCS11_CKM_SHA256_HMAC; + break; + case PKCS11_CKK_SHA384_HMAC: + mechanism = PKCS11_CKM_SHA384_HMAC; + break; + case PKCS11_CKK_SHA512_HMAC: + mechanism = PKCS11_CKM_SHA512_HMAC; + break; + case PKCS11_CKK_EC: + mechanism = PKCS11_CKM_EC_KEY_PAIR_GEN; + break; + case PKCS11_CKK_EDDSA: + mechanism = PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN; + break; + case PKCS11_CKK_RSA: + mechanism = PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN; + break; + default: + TEE_Panic(key_type); + break; + } + + mechanism_supported_key_sizes_bytes(mechanism, min_key_size, + max_key_size); +} + +enum pkcs11_rc check_created_attrs(struct obj_attrs *key1, + struct obj_attrs *key2) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct obj_attrs *secret = NULL; + struct obj_attrs *private = NULL; + struct obj_attrs *public = NULL; + uint32_t max_key_size = 0; + uint32_t min_key_size = 0; + uint32_t key_length = 0; + + switch (get_class(key1)) { + case PKCS11_CKO_SECRET_KEY: + secret = key1; + break; + case PKCS11_CKO_PUBLIC_KEY: + public = key1; + break; + case PKCS11_CKO_PRIVATE_KEY: + private = key1; + break; + default: + return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; + } + + if (key2) { + switch (get_class(key2)) { + case PKCS11_CKO_PUBLIC_KEY: + public = key2; + if (private == key1) + break; + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + case PKCS11_CKO_PRIVATE_KEY: + private = key2; + if (public == key1) + break; + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + default: + return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; + } + + if (get_key_type(private) != get_key_type(public)) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + if (secret) { + switch (get_key_type(secret)) { + case PKCS11_CKK_AES: + case PKCS11_CKK_GENERIC_SECRET: + case PKCS11_CKK_MD5_HMAC: + case PKCS11_CKK_SHA_1_HMAC: + case PKCS11_CKK_SHA224_HMAC: + case PKCS11_CKK_SHA256_HMAC: + case PKCS11_CKK_SHA384_HMAC: + case PKCS11_CKK_SHA512_HMAC: + break; + default: + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + /* Get key size */ + rc = get_u32_attribute(secret, PKCS11_CKA_VALUE_LEN, + &key_length); + if (rc) + return PKCS11_CKR_TEMPLATE_INCOMPLETE; + } + if (public) { + switch (get_key_type(public)) { + case PKCS11_CKK_RSA: + /* Get key size */ + rc = get_u32_attribute(public, PKCS11_CKA_MODULUS_BITS, + &key_length); + if (rc) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + key_length = ROUNDUP(key_length, 8) / 8; + break; + case PKCS11_CKK_EC: + case PKCS11_CKK_EC_EDWARDS: + break; + default: + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + } + if (private) { + switch (get_key_type(private)) { + case PKCS11_CKK_RSA: + case PKCS11_CKK_EC: + case PKCS11_CKK_EC_EDWARDS: + break; + default: + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + } + + /* + * Check key size for symmetric keys and RSA keys + * EC is bound to domains, no need to check here. + */ + switch (get_key_type(key1)) { + case PKCS11_CKK_EC: + case PKCS11_CKK_EC_EDWARDS: + return PKCS11_CKR_OK; + default: + break; + } + + get_key_min_max_sizes(get_key_type(key1), &min_key_size, &max_key_size); + if (key_length < min_key_size || key_length > max_key_size) { + EMSG("Length %"PRIu32" vs range [%"PRIu32" %"PRIu32"]", + key_length, min_key_size, max_key_size); + + return PKCS11_CKR_KEY_SIZE_RANGE; + } + + if (secret && get_key_type(secret) == PKCS11_CKK_AES) { + if (key_length != 16 && key_length != 24 && key_length != 32) + return PKCS11_CKR_KEY_SIZE_RANGE; + } + + return PKCS11_CKR_OK; +} + +/* Check processing ID against attribute ALLOWED_MECHANISMS if any */ +static bool parent_key_complies_allowed_processings(uint32_t proc_id, + struct obj_attrs *head) +{ + char *attr = NULL; + uint32_t size = 0; + uint32_t proc = 0; + size_t count = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + rc = get_attribute_ptr(head, PKCS11_CKA_ALLOWED_MECHANISMS, + (void *)&attr, &size); + if (rc == PKCS11_RV_NOT_FOUND) + return true; + if (rc) { + EMSG("unexpected attributes state"); + TEE_Panic(TEE_ERROR_BAD_STATE); + } + + for (count = size / sizeof(uint32_t); count; count--) { + TEE_MemMove(&proc, attr, sizeof(uint32_t)); + attr += sizeof(uint32_t); + + if (proc == proc_id) + return true; + } + + DMSG("can't find %s in allowed list", id2str_proc(proc_id)); + return false; +} + +static enum pkcs11_attr_id func_to_attr(enum processing_func func) +{ + switch (func) { + case PKCS11_FUNCTION_ENCRYPT: + return PKCS11_CKA_ENCRYPT; + case PKCS11_FUNCTION_DECRYPT: + return PKCS11_CKA_DECRYPT; + case PKCS11_FUNCTION_SIGN: + return PKCS11_CKA_SIGN; + case PKCS11_FUNCTION_VERIFY: + return PKCS11_CKA_VERIFY; + case PKCS11_FUNCTION_WRAP: + return PKCS11_CKA_WRAP; + case PKCS11_FUNCTION_UNWRAP: + return PKCS11_CKA_UNWRAP; + case PKCS11_FUNCTION_DERIVE: + return PKCS11_CKA_DERIVE; + default: + return PKCS11_CKA_UNDEFINED_ID; + } +} + +enum pkcs11_rc +check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id, + enum processing_func function, + struct obj_attrs *head) +{ + enum pkcs11_class_id key_class = get_class(head); + enum pkcs11_key_type key_type = get_key_type(head); + enum pkcs11_attr_id attr = func_to_attr(function); + + if (!get_bool(head, attr)) { + DMSG("%s not permitted", id2str_attr(attr)); + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + + /* Check processing complies with parent key family */ + switch (proc_id) { + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + case PKCS11_CKM_AES_CTS: + case PKCS11_CKM_AES_CTR: + case PKCS11_CKM_AES_CMAC: + case PKCS11_CKM_AES_CMAC_GENERAL: + if (key_class == PKCS11_CKO_SECRET_KEY && + key_type == PKCS11_CKK_AES) + break; + + DMSG("%s invalid key %s/%s", id2str_proc(proc_id), + id2str_class(key_class), id2str_key_type(key_type)); + + if (function == PKCS11_FUNCTION_WRAP) + return PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + else if (function == PKCS11_FUNCTION_UNWRAP) + return PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + else + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + + case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: + case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: + if (key_class != PKCS11_CKO_SECRET_KEY && + key_type != PKCS11_CKK_AES) + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + + if (get_bool(head, PKCS11_CKA_ENCRYPT)) { + /* + * Intentionally refuse to proceed despite + * PKCS#11 specifications v2.40 and v3.0 not expecting + * this behavior to avoid potential security issue + * where keys derived by these mechanisms can be + * revealed by doing data encryption using parent key. + */ + return PKCS11_CKR_FUNCTION_FAILED; + } + + break; + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA512_HMAC: + case PKCS11_CKM_MD5_HMAC_GENERAL: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + if (key_class != PKCS11_CKO_SECRET_KEY) + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + + if (key_type == PKCS11_CKK_GENERIC_SECRET) + break; + + switch (proc_id) { + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_MD5_HMAC_GENERAL: + if (key_type == PKCS11_CKK_MD5_HMAC) + break; + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + if (key_type == PKCS11_CKK_SHA_1_HMAC) + break; + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + if (key_type == PKCS11_CKK_SHA224_HMAC) + break; + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + if (key_type == PKCS11_CKK_SHA256_HMAC) + break; + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + if (key_type == PKCS11_CKK_SHA384_HMAC) + break; + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + case PKCS11_CKM_SHA512_HMAC: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + if (key_type == PKCS11_CKK_SHA512_HMAC) + break; + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + default: + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + break; + + case PKCS11_CKM_EDDSA: + if (key_type != PKCS11_CKK_EC_EDWARDS) { + EMSG("Invalid key %s for mechanism %s", + id2str_type(key_type, key_class), + id2str_proc(proc_id)); + return PKCS11_CKR_KEY_TYPE_INCONSISTENT; + } + if (key_class != PKCS11_CKO_PUBLIC_KEY && + key_class != PKCS11_CKO_PRIVATE_KEY) { + EMSG("Invalid key class for mechanism %s", + id2str_proc(proc_id)); + + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + break; + + case PKCS11_CKM_ECDSA: + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + case PKCS11_CKM_ECDH1_DERIVE: + if (key_type != PKCS11_CKK_EC) { + EMSG("Invalid key %s for mechanism %s", + id2str_type(key_type, key_class), + id2str_proc(proc_id)); + + return PKCS11_CKR_KEY_TYPE_INCONSISTENT; + } + if (key_class != PKCS11_CKO_PUBLIC_KEY && + key_class != PKCS11_CKO_PRIVATE_KEY) { + EMSG("Invalid key class for mechanism %s", + id2str_proc(proc_id)); + + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + break; + case PKCS11_CKM_RSA_PKCS: + case PKCS11_CKM_MD5_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS: + case PKCS11_CKM_SHA224_RSA_PKCS: + case PKCS11_CKM_SHA256_RSA_PKCS: + case PKCS11_CKM_SHA384_RSA_PKCS: + case PKCS11_CKM_SHA512_RSA_PKCS: + case PKCS11_CKM_RSA_AES_KEY_WRAP: + case PKCS11_CKM_RSA_PKCS_OAEP: + case PKCS11_CKM_RSA_PKCS_PSS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + if (key_type != PKCS11_CKK_RSA) { + EMSG("Invalid key %s for mechanism %s", + id2str_type(key_type, key_class), + id2str_proc(proc_id)); + + return PKCS11_CKR_KEY_TYPE_INCONSISTENT; + } + if (key_class != PKCS11_CKO_PUBLIC_KEY && + key_class != PKCS11_CKO_PRIVATE_KEY) { + EMSG("Invalid key class for mechanism %s", + id2str_proc(proc_id)); + + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + break; + default: + DMSG("Invalid processing %#"PRIx32"/%s", proc_id, + id2str_proc(proc_id)); + + return PKCS11_CKR_MECHANISM_INVALID; + } + + if (!parent_key_complies_allowed_processings(proc_id, head)) { + DMSG("Allowed mechanism failed"); + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + + return PKCS11_CKR_OK; +} + +bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr, + struct pkcs11_object *obj) +{ + uint8_t boolval = 0; + uint32_t boolsize = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + enum pkcs11_class_id key_class = get_class(obj->attributes); + + if (key_class != PKCS11_CKO_SECRET_KEY && + key_class != PKCS11_CKO_PRIVATE_KEY) + return true; + + switch (req_attr->id) { + case PKCS11_CKA_PRIVATE_EXPONENT: + case PKCS11_CKA_PRIME_1: + case PKCS11_CKA_PRIME_2: + case PKCS11_CKA_EXPONENT_1: + case PKCS11_CKA_EXPONENT_2: + case PKCS11_CKA_COEFFICIENT: + case PKCS11_CKA_VALUE: + boolsize = sizeof(boolval); + rc = get_attribute(obj->attributes, PKCS11_CKA_EXTRACTABLE, + &boolval, &boolsize); + if (rc || boolval == PKCS11_FALSE) + return false; + + boolsize = sizeof(boolval); + rc = get_attribute(obj->attributes, PKCS11_CKA_SENSITIVE, + &boolval, &boolsize); + if (rc || boolval == PKCS11_TRUE) + return false; + break; + default: + break; + } + + return true; +} + +static bool attr_is_modifiable_any_key(struct pkcs11_attribute_head *attr) +{ + switch (attr->id) { + case PKCS11_CKA_ID: + case PKCS11_CKA_START_DATE: + case PKCS11_CKA_END_DATE: + case PKCS11_CKA_DERIVE: + return true; + default: + return false; + } +} + +static bool attr_is_modifiable_secret_key(struct pkcs11_attribute_head *attr, + struct pkcs11_session *session, + struct pkcs11_object *obj) +{ + switch (attr->id) { + case PKCS11_CKA_ENCRYPT: + case PKCS11_CKA_DECRYPT: + case PKCS11_CKA_SIGN: + case PKCS11_CKA_VERIFY: + case PKCS11_CKA_WRAP: + case PKCS11_CKA_UNWRAP: + return true; + /* Can't be modified once set to CK_FALSE - 12 in Table 10 */ + case PKCS11_CKA_EXTRACTABLE: + return get_bool(obj->attributes, attr->id); + /* Can't be modified once set to CK_TRUE - 11 in Table 10 */ + case PKCS11_CKA_SENSITIVE: + case PKCS11_CKA_WRAP_WITH_TRUSTED: + return !get_bool(obj->attributes, attr->id); + /* Change in CKA_TRUSTED can only be done by SO */ + case PKCS11_CKA_TRUSTED: + return pkcs11_session_is_so(session); + case PKCS11_CKA_NEVER_EXTRACTABLE: + case PKCS11_CKA_ALWAYS_SENSITIVE: + return false; + default: + return false; + } +} + +static bool attr_is_modifiable_public_key(struct pkcs11_attribute_head *attr, + struct pkcs11_session *session, + struct pkcs11_object *obj __unused) +{ + switch (attr->id) { + case PKCS11_CKA_SUBJECT: + case PKCS11_CKA_ENCRYPT: + case PKCS11_CKA_VERIFY: + case PKCS11_CKA_VERIFY_RECOVER: + case PKCS11_CKA_WRAP: + return true; + case PKCS11_CKA_TRUSTED: + /* Change in CKA_TRUSTED can only be done by SO */ + return pkcs11_session_is_so(session); + default: + return false; + } +} + +static bool attr_is_modifiable_private_key(struct pkcs11_attribute_head *attr, + struct pkcs11_session *sess __unused, + struct pkcs11_object *obj) +{ + switch (attr->id) { + case PKCS11_CKA_SUBJECT: + case PKCS11_CKA_DECRYPT: + case PKCS11_CKA_SIGN: + case PKCS11_CKA_SIGN_RECOVER: + case PKCS11_CKA_UNWRAP: + /* + * TBD: Revisit if we don't support PKCS11_CKA_PUBLIC_KEY_INFO + * Specification mentions that if this attribute is + * supplied as part of a template for C_CreateObject, C_CopyObject or + * C_SetAttributeValue for a private key, the token MUST verify + * correspondence between the private key data and the public key data + * as supplied in CKA_PUBLIC_KEY_INFO. This needs to be + * taken care of when this object type will be implemented + */ + case PKCS11_CKA_PUBLIC_KEY_INFO: + return true; + /* Can't be modified once set to CK_FALSE - 12 in Table 10 */ + case PKCS11_CKA_EXTRACTABLE: + return get_bool(obj->attributes, attr->id); + /* Can't be modified once set to CK_TRUE - 11 in Table 10 */ + case PKCS11_CKA_SENSITIVE: + case PKCS11_CKA_WRAP_WITH_TRUSTED: + return !get_bool(obj->attributes, attr->id); + case PKCS11_CKA_NEVER_EXTRACTABLE: + case PKCS11_CKA_ALWAYS_SENSITIVE: + return false; + default: + return false; + } +} + +static bool attr_is_modifiable_certificate(struct pkcs11_attribute_head *attr, + struct pkcs11_session *session, + struct pkcs11_object *obj) +{ + uint8_t boolval = 0; + uint32_t boolsize = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + /* Trusted certificates cannot be modified. */ + rc = get_attribute(obj->attributes, PKCS11_CKA_TRUSTED, + &boolval, &boolsize); + if (rc || boolval == PKCS11_TRUE) + return false; + + /* Common certificate attributes */ + switch (attr->id) { + case PKCS11_CKA_TRUSTED: + /* + * The CKA_TRUSTED attribute cannot be set to CK_TRUE by an + * application. It MUST be set by a token initialization + * application or by the token’s SO. + */ + return pkcs11_session_is_so(session); + case PKCS11_CKA_CERTIFICATE_TYPE: + case PKCS11_CKA_CERTIFICATE_CATEGORY: + return false; + default: + break; + } + + /* Certificate type specific attributes */ + switch (get_certificate_type(obj->attributes)) { + case PKCS11_CKC_X_509: + /* + * Only the CKA_ID, CKA_ISSUER, and CKA_SERIAL_NUMBER + * attributes may be modified after the object is created. + */ + switch (attr->id) { + case PKCS11_CKA_ID: + case PKCS11_CKA_ISSUER: + case PKCS11_CKA_SERIAL_NUMBER: + return true; + default: + break; + } + break; + default: + /* Unsupported certificate type */ + break; + } + + return false; +} + +static bool attribute_is_modifiable(struct pkcs11_session *session, + struct pkcs11_attribute_head *req_attr, + struct pkcs11_object *obj, + enum pkcs11_class_id class, + enum processing_func function) +{ + /* Check modifiable attributes common to any object */ + switch (req_attr->id) { + case PKCS11_CKA_LABEL: + return true; + case PKCS11_CKA_TOKEN: + case PKCS11_CKA_MODIFIABLE: + case PKCS11_CKA_DESTROYABLE: + case PKCS11_CKA_PRIVATE: + return function == PKCS11_FUNCTION_COPY; + case PKCS11_CKA_COPYABLE: + /* + * Specification mentions that if the attribute value is false + * it can't be set to true. Reading this we assume that it + * should be possible to modify this attribute even though this + * is not marked as modifiable in Table 10 if done in right + * direction i.e from TRUE -> FALSE. + */ + return get_bool(obj->attributes, req_attr->id); + default: + break; + } + + /* Attribute checking based on class type */ + switch (class) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_PRIVATE_KEY: + if (attr_is_modifiable_any_key(req_attr)) + return true; + if (class == PKCS11_CKO_SECRET_KEY && + attr_is_modifiable_secret_key(req_attr, session, obj)) + return true; + if (class == PKCS11_CKO_PUBLIC_KEY && + attr_is_modifiable_public_key(req_attr, session, obj)) + return true; + if (class == PKCS11_CKO_PRIVATE_KEY && + attr_is_modifiable_private_key(req_attr, session, obj)) + return true; + break; + case PKCS11_CKO_DATA: + /* None of the data object attributes are modifiable */ + return false; + case PKCS11_CKO_CERTIFICATE: + return attr_is_modifiable_certificate(req_attr, session, obj); + default: + break; + } + + return false; +} + +enum pkcs11_rc check_attrs_against_modification(struct pkcs11_session *session, + struct obj_attrs *head, + struct pkcs11_object *obj, + enum processing_func function) +{ + enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; + char *cur = NULL; + char *end = NULL; + size_t len = 0; + + class = get_class(obj->attributes); + + cur = (char *)head + sizeof(struct obj_attrs); + end = cur + head->attrs_size; + + for (; cur < end; cur += len) { + /* Structure aligned copy of the pkcs11_ref in the object */ + struct pkcs11_attribute_head cli_ref = { }; + + TEE_MemMove(&cli_ref, cur, sizeof(cli_ref)); + len = sizeof(cli_ref) + cli_ref.size; + + /* + * Check 1 - Check if attribute belongs to the object + * The obj->attributes has all the attributes in + * it which are allowed for an object. + */ + if (get_attribute_ptr(obj->attributes, cli_ref.id, NULL, + NULL) == PKCS11_RV_NOT_FOUND) + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + + /* Check 2 - Is attribute modifiable */ + if (!attribute_is_modifiable(session, &cli_ref, obj, class, + function)) + return PKCS11_CKR_ATTRIBUTE_READ_ONLY; + + /* + * Checks for modification in PKCS11_CKA_TOKEN and + * PKCS11_CKA_PRIVATE are required for PKCS11_FUNCTION_COPY + * only, so skip them for PKCS11_FUNCTION_MODIFY. + */ + if (function == PKCS11_FUNCTION_MODIFY) + continue; + + /* + * An attempt to copy an object to a token will fail for + * RO session + */ + if (cli_ref.id == PKCS11_CKA_TOKEN && + get_bool(head, PKCS11_CKA_TOKEN)) { + if (!pkcs11_session_is_read_write(session)) { + DMSG("Can't copy to token in a RO session"); + return PKCS11_CKR_SESSION_READ_ONLY; + } + } + + if (cli_ref.id == PKCS11_CKA_PRIVATE) { + bool parent_priv = + get_bool(obj->attributes, cli_ref.id); + bool obj_priv = get_bool(head, cli_ref.id); + + /* + * If PKCS11_CKA_PRIVATE is being set to TRUE from + * FALSE, user has to be logged in + */ + if (!parent_priv && obj_priv) { + if ((pkcs11_session_is_public(session) || + pkcs11_session_is_so(session))) + return PKCS11_CKR_USER_NOT_LOGGED_IN; + } + + /* + * Restriction added - Even for Copy, do not allow + * modification of CKA_PRIVATE from TRUE to FALSE + */ + if (parent_priv && !obj_priv) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + } + + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data, + size_t key_size) +{ + uint32_t size = sizeof(uint32_t); + uint32_t key_length = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + /* Get key size if present in template */ + rc = get_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_length, &size); + if (rc && rc != PKCS11_RV_NOT_FOUND) + return rc; + + if (key_length) { + if (key_size < key_length) + return PKCS11_CKR_DATA_LEN_RANGE; + } else { + key_length = key_size; + rc = set_attribute(head, PKCS11_CKA_VALUE_LEN, &key_length, + sizeof(uint32_t)); + if (rc) + return rc; + } + + /* Now we can check the VALUE_LEN field */ + rc = check_created_attrs(*head, NULL); + if (rc) + return rc; + + /* Remove the default empty value attribute if found */ + rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); + if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) + return PKCS11_CKR_GENERAL_ERROR; + + return add_attribute(head, PKCS11_CKA_VALUE, data, key_length); +} + +static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head, + void *data, + size_t key_size) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + int mbedtls_rc = 0; + uint32_t key_bits = 0; + uint32_t size = 0; + uint32_t buffer_size = 0; + void *buffer = NULL; + mbedtls_pk_context pk = { }; + mbedtls_rsa_context *rsa = NULL; + mbedtls_mpi n = { }; + mbedtls_mpi e = { }; + mbedtls_mpi d = { }; + mbedtls_mpi p = { }; + mbedtls_mpi q = { }; + + rc = get_u32_attribute(*head, PKCS11_CKA_MODULUS_BITS, &key_bits); + if (rc && rc != PKCS11_RV_NOT_FOUND) + return rc; + + if (remove_empty_attribute(head, PKCS11_CKA_MODULUS) || + remove_empty_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT) || + remove_empty_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT) || + remove_empty_attribute(head, PKCS11_CKA_PRIME_1) || + remove_empty_attribute(head, PKCS11_CKA_PRIME_2)) + return PKCS11_CKR_GENERAL_ERROR; + + mbedtls_pk_init(&pk); + mbedtls_mpi_init(&n); + mbedtls_mpi_init(&e); + mbedtls_mpi_init(&d); + mbedtls_mpi_init(&p); + mbedtls_mpi_init(&q); + + mbedtls_rc = mbedtls_pk_parse_key(&pk, data, key_size, NULL, 0); + if (mbedtls_rc) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + rsa = mbedtls_pk_rsa(pk); + mbedtls_rc = mbedtls_rsa_export(rsa, &n, &p, &q, &d, &e); + if (mbedtls_rc) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + if (key_bits && mbedtls_mpi_bitlen(&n) != key_bits) { + rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; + goto out; + } + + size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&n), 8); + buffer_size = size; + buffer = TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!buffer) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + mbedtls_rc = mbedtls_mpi_write_binary(&n, buffer, size); + if (mbedtls_rc) { + rc = PKCS11_CKR_WRAPPED_KEY_INVALID; + goto out; + } + + rc = add_attribute(head, PKCS11_CKA_MODULUS, buffer, size); + if (rc) + goto out; + + size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&e), 8); + if (buffer_size < size) { + rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; + goto out; + } + + mbedtls_rc = mbedtls_mpi_write_binary(&e, buffer, size); + if (mbedtls_rc) { + rc = PKCS11_CKR_WRAPPED_KEY_INVALID; + goto out; + } + + rc = add_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT, buffer, size); + if (rc) + goto out; + + size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&d), 8); + if (buffer_size < size) { + rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; + goto out; + } + + mbedtls_rc = mbedtls_mpi_write_binary(&d, buffer, size); + if (mbedtls_rc) { + rc = PKCS11_CKR_WRAPPED_KEY_INVALID; + goto out; + } + + rc = add_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT, buffer, size); + if (rc) + goto out; + + size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&p), 8); + if (buffer_size < size) { + rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; + goto out; + } + + mbedtls_rc = mbedtls_mpi_write_binary(&p, buffer, size); + if (mbedtls_rc) { + rc = PKCS11_CKR_WRAPPED_KEY_INVALID; + goto out; + } + + rc = add_attribute(head, PKCS11_CKA_PRIME_1, buffer, size); + if (rc) + goto out; + + size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&q), 8); + if (buffer_size < size) { + rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; + goto out; + } + + mbedtls_rc = mbedtls_mpi_write_binary(&q, buffer, size); + if (mbedtls_rc) { + rc = PKCS11_CKR_WRAPPED_KEY_INVALID; + goto out; + } + + rc = add_attribute(head, PKCS11_CKA_PRIME_2, buffer, size); + +out: + mbedtls_pk_free(&pk); + mbedtls_mpi_free(&n); + mbedtls_mpi_free(&e); + mbedtls_mpi_free(&d); + mbedtls_mpi_free(&p); + mbedtls_mpi_free(&q); + TEE_Free(buffer); + return rc; +} + +enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data, + size_t key_size) +{ + switch (get_class(*head)) { + case PKCS11_CKO_SECRET_KEY: + return set_secret_key_data(head, data, key_size); + case PKCS11_CKO_PRIVATE_KEY: + if (get_key_type(*head) == PKCS11_CKK_RSA) + return set_private_key_data_rsa(head, data, key_size); + break; + default: + return PKCS11_CKR_GENERAL_ERROR; + } + + return PKCS11_CKR_GENERAL_ERROR; +} + +static enum pkcs11_rc alloc_copy_attribute_value(struct obj_attrs *head, + void **data, uint32_t *sz) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *buffer = NULL; + void *value = NULL; + + rc = get_attribute_ptr(head, PKCS11_CKA_VALUE, &value, sz); + if (rc) + return PKCS11_CKR_ARGUMENTS_BAD; + + buffer = TEE_Malloc(*sz, TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!buffer) + return PKCS11_CKR_DEVICE_MEMORY; + + TEE_MemMove(buffer, value, *sz); + *data = buffer; + + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc +encode_rsa_private_key_der(struct obj_attrs *head, void **data, uint32_t *sz) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + int i = 0; + int mbedtls_rc = 0; + int start = 0; + int der_size = 0; + void *n = NULL; + void *p = NULL; + void *q = NULL; + void *d = NULL; + void *e = NULL; + uint32_t n_len = 0; + uint32_t p_len = 0; + uint32_t q_len = 0; + uint32_t d_len = 0; + uint32_t e_len = 0; + uint8_t *buffer = NULL; + mbedtls_pk_context pk = { }; + mbedtls_rsa_context *rsa = NULL; + const mbedtls_pk_info_t *pk_info = NULL; + + mbedtls_pk_init(&pk); + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if (mbedtls_pk_setup(&pk, pk_info)) { + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + rc = get_attribute_ptr(head, PKCS11_CKA_MODULUS, &n, &n_len); + if (rc) + goto out; + + rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_1, &p, &p_len); + if (rc) + goto out; + + rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_2, &q, &q_len); + if (rc) + goto out; + + rc = get_attribute_ptr(head, PKCS11_CKA_PRIVATE_EXPONENT, &d, &d_len); + if (rc) + goto out; + + rc = get_attribute_ptr(head, PKCS11_CKA_PUBLIC_EXPONENT, &e, &e_len); + if (rc) + goto out; + + rsa = mbedtls_pk_rsa(pk); + mbedtls_rc = mbedtls_rsa_import_raw(rsa, n, n_len, p, p_len, + q, q_len, d, d_len, e, e_len); + if (mbedtls_rc) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + if (mbedtls_rsa_complete(rsa)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + if (mbedtls_rsa_check_privkey(rsa)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + der_size = n_len * 8; + buffer = TEE_Malloc(der_size, TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!buffer) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + mbedtls_rc = mbedtls_pk_write_key_der(&pk, buffer, der_size); + if (mbedtls_rc < 0) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + start = der_size - mbedtls_rc; + for (i = 0; i < mbedtls_rc; i++) { + buffer[i] = buffer[i + start]; + buffer[i + start] = 0; + } + + *data = buffer; + *sz = mbedtls_rc; +out: + mbedtls_pk_free(&pk); + + if (rc) + TEE_Free(buffer); + + return rc; +} + +enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data, + uint32_t *sz) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + switch (get_class(head)) { + case PKCS11_CKO_SECRET_KEY: + rc = alloc_copy_attribute_value(head, data, sz); + break; + case PKCS11_CKO_PRIVATE_KEY: + if (get_key_type(head) == PKCS11_CKK_RSA) + rc = encode_rsa_private_key_der(head, data, sz); + break; + default: + break; + } + + return rc; +} + +enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head, + struct obj_attrs **priv_head) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *id1 = NULL; + uint32_t id1_size = 0; + void *id2 = NULL; + uint32_t id2_size = 0; + + assert(pub_head); + assert(priv_head); + + rc = get_attribute_ptr(*pub_head, PKCS11_CKA_ID, &id1, &id1_size); + if (rc) { + if (rc != PKCS11_RV_NOT_FOUND) + return rc; + id1 = NULL; + } else if (!id1_size) { + id1 = NULL; + } + + rc = get_attribute_ptr(*priv_head, PKCS11_CKA_ID, &id2, &id2_size); + if (rc) { + if (rc != PKCS11_RV_NOT_FOUND) + return rc; + id2 = NULL; + } else if (!id2_size) { + id2 = NULL; + } + + /* Both have value -- let them be what caller has specified them */ + if (id1 && id2) + return PKCS11_CKR_OK; + + /* Both are empty -- leave empty values */ + if (!id1 && !id2) + return PKCS11_CKR_OK; + + /* Cross copy CKA_ID value */ + if (id1) + return set_attribute(priv_head, PKCS11_CKA_ID, id1, id1_size); + else + return set_attribute(pub_head, PKCS11_CKA_ID, id2, id2_size); +} diff --git a/optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h b/optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h new file mode 100644 index 0000000..270ccf2 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_attributes.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#ifndef PKCS11_TA_PKCS11_ATTRIBUTES_H +#define PKCS11_TA_PKCS11_ATTRIBUTES_H + +#include + +#include "serializer.h" + +struct obj_attrs; +struct pkcs11_object; +struct pkcs11_session; + +/* + * PKCS#11 directives on object attributes. + * Those with a '*' are optional, other must be defined, either by caller + * or by some known default value. + * + * [all] objects: class + * + * [stored] objects: persistent, need_authen, modifiable, copyable, + * destroyable, label*. + * + * [data] objects: [all], [stored], application_id*, object_id*, value. + * + * [key] objects: [all], [stored], type, id*, start_date/end_date*, + * derive, local, allowed_mechanisms*. + * + * [symm-key]: [key], sensitive, encrypt, decrypt, sign, verify, wrap, + * unwrap, extractable, wrap_with_trusted, trusted, + * wrap_template, unwrap_template, derive_template. + */ + +/* + * Utils to check compliance of attributes at various processing steps. + * Any processing operation is exclusively one of the following. + * + * Case 1: Create a secret from some local random value (C_CreateKey & friends) + * - client provides an attributes list template, PKCS11 TA completes with + * default attribute values. Object is created if attributes are + * consistent and comply token/session state. + * - PKCS11 sequence: + * - check/set token/session state + * - create an attribute list from client template and default values. + * - check new secret attributes complies requested mechanism. + * - check new secret attributes complies token/session state. + * - Generate the value for the secret. + * - Set some runtime attributes in the new secret. + * - Register the new secret and return a handle for it. + * + * Case 2: Create a secret from a client clear data (C_CreateObject) + * - client provides an attributes list template, PKCS11 TA completes with + * default attribute values. Object is created if attributes are + * consistent and comply token/session state. + * - check/set token/session state + * - create an attribute list from client template and default values. + * - check new secret attributes complies requested mechanism (raw-import). + * - check new secret attributes complies token/session state. + * - Set some runtime attributes in the new secret. + * - Register the new secret and return a handle for it. + + * Case 3: Use a secret for data processing + * - client provides a mechanism ID and the secret handle. + * - PKCS11 checks mechanism and secret comply, if mechanism and token/session + * state comply and last if secret and token/session state comply. + * - check/set token/session state + * - check secret's parent attributes complies requested processing. + * - check secret's parent attributes complies token/session state. + * - check new secret attributes complies secret's parent attributes. + * - check new secret attributes complies requested mechanism. + * - check new secret attributes complies token/session state. + * + * Case 4: Create a secret from a client template and a secret's parent + * (i.e derive a symmetric key) + * - client args: new-key template, mechanism ID, parent-key handle. + * - PKCS11 create a new-key attribute list based on template + default values + + * inheritance from the parent key attributes. + * - PKCS11 checks: + * - token/session state + * - parent-key vs mechanism + * - parent-key vs token/session state + * - parent-key vs new-key + * - new-key vs mechanism + * - new-key vs token/session state + * - then do processing + * - then finalize object creation + */ + +enum processing_func { + PKCS11_FUNCTION_DIGEST, + PKCS11_FUNCTION_GENERATE, + PKCS11_FUNCTION_GENERATE_PAIR, + PKCS11_FUNCTION_DERIVE, + PKCS11_FUNCTION_WRAP, + PKCS11_FUNCTION_UNWRAP, + PKCS11_FUNCTION_ENCRYPT, + PKCS11_FUNCTION_DECRYPT, + PKCS11_FUNCTION_SIGN, + PKCS11_FUNCTION_VERIFY, + PKCS11_FUNCTION_SIGN_RECOVER, + PKCS11_FUNCTION_VERIFY_RECOVER, + PKCS11_FUNCTION_IMPORT, + PKCS11_FUNCTION_COPY, + PKCS11_FUNCTION_MODIFY, + PKCS11_FUNCTION_DESTROY, + PKCS11_FUNCTION_UNKNOWN, +}; + +enum processing_step { + PKCS11_FUNC_STEP_INIT, + PKCS11_FUNC_STEP_ONESHOT, + PKCS11_FUNC_STEP_UPDATE, + PKCS11_FUNC_STEP_UPDATE_KEY, + PKCS11_FUNC_STEP_FINAL, +}; + +/* Create an attribute list for a new object */ +enum pkcs11_rc +create_attributes_from_template(struct obj_attrs **out, void *template, + size_t template_size, struct obj_attrs *parent, + enum processing_func func, + enum pkcs11_mechanism_id proc_mecha, + enum pkcs11_class_id template_class); + +/* + * The various checks to be performed before a processing: + * - create a new object in the current token state + * - use a parent object in the processing + * - use a mechanism with provided configuration + */ +enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session, + struct obj_attrs *head); + +enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id, + struct obj_attrs *head); + +enum pkcs11_rc check_created_attrs(struct obj_attrs *key1, + struct obj_attrs *key2); + +/* + * Check the attributes of the parent secret (key) used in the processing + * do match the target processing. + * + * @proc_id - PKCS11_CKM_xxx + * @func - identifier of the processing function operated with @proc_id. + * @head - head of the attributes of parent object. + */ +enum pkcs11_rc +check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id, + enum processing_func func, + struct obj_attrs *head); + +enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session, + struct obj_attrs *head); + +enum pkcs11_rc +check_mechanism_against_processing(struct pkcs11_session *session, + enum pkcs11_mechanism_id mechanism_type, + enum processing_func function, + enum processing_step step); + +bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr, + struct pkcs11_object *obj); + +bool object_is_private(struct obj_attrs *head); + +bool object_is_token(struct obj_attrs *head); + +bool object_is_modifiable(struct obj_attrs *head); + +bool object_is_copyable(struct obj_attrs *head); + +/* + * Check the attributes passed in template against the attributes which can be + * modified. These are the attributes marked with * 8,10,11 or 12 in Table 10 + * in PKCS #11 Cryptographic Token InterfaceBase Specification Version 2.40. + * Few attributes not with this marking but explicitly specified as modifiable + * in footnote of their tables are also considered to be modifiable + */ +enum pkcs11_rc check_attrs_against_modification(struct pkcs11_session *session, + struct obj_attrs *head, + struct pkcs11_object *obj, + enum processing_func function); + +enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data, + size_t key_size); + +/* + * Get an allocated copy of key data to be wrapped from @head + * @head: Object attribute where to find key data to be wrapped + * @data: Output allocated and filled buffer upon success + * @sz: Key output data size in bytes upon success + * Return a pkcs11_rv compliant value + */ +enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data, + uint32_t *sz); + +/* + * Adds CKA_ID attribute from paired object if missing. + * + * @pub_head - Public key object attributes + * @priv_head - Private key object attributes + * Return a PKCS11 return code + */ +enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head, + struct obj_attrs **priv_head); + +#endif /*PKCS11_TA_PKCS11_ATTRIBUTES_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c b/optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c new file mode 100644 index 0000000..fc68c11 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_helpers.c @@ -0,0 +1,833 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#include +#include +#include +#include + +#include "attributes.h" +#include "object.h" +#include "pkcs11_attributes.h" +#include "pkcs11_helpers.h" +#include "processing.h" + +static const char __maybe_unused unknown[] = ""; + +struct attr_size { + uint32_t id; + uint32_t size; +#if CFG_TEE_TA_LOG_LEVEL > 0 + const char *string; +#endif +}; + +#if CFG_TEE_TA_LOG_LEVEL > 0 +#define PKCS11_ID_SZ(_id, _sz) \ + { .id = (uint32_t)(_id), .size = (_sz), .string = #_id } +#else +#define PKCS11_ID_SZ(_id, _sz) \ + { .id = (uint32_t)(_id), .size = (_sz) } +#endif + +static const struct attr_size attr_ids[] = { + PKCS11_ID_SZ(PKCS11_CKA_CLASS, 4), + PKCS11_ID_SZ(PKCS11_CKA_KEY_TYPE, 4), + PKCS11_ID_SZ(PKCS11_CKA_VALUE, 0), + PKCS11_ID_SZ(PKCS11_CKA_VALUE_LEN, 4), + PKCS11_ID_SZ(PKCS11_CKA_KEY_GEN_MECHANISM, 4), + PKCS11_ID_SZ(PKCS11_CKA_LABEL, 0), + PKCS11_ID_SZ(PKCS11_CKA_CERTIFICATE_TYPE, 4), + PKCS11_ID_SZ(PKCS11_CKA_ISSUER, 0), + PKCS11_ID_SZ(PKCS11_CKA_SERIAL_NUMBER, 0), + PKCS11_ID_SZ(PKCS11_CKA_CERTIFICATE_CATEGORY, 4), + PKCS11_ID_SZ(PKCS11_CKA_URL, 0), + PKCS11_ID_SZ(PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY, 0), + PKCS11_ID_SZ(PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY, 0), + PKCS11_ID_SZ(PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, 4), + PKCS11_ID_SZ(PKCS11_CKA_NAME_HASH_ALGORITHM, 4), + PKCS11_ID_SZ(PKCS11_CKA_CHECK_VALUE, 0), + PKCS11_ID_SZ(PKCS11_CKA_WRAP_TEMPLATE, 0), + PKCS11_ID_SZ(PKCS11_CKA_UNWRAP_TEMPLATE, 0), + PKCS11_ID_SZ(PKCS11_CKA_DERIVE_TEMPLATE, 0), + PKCS11_ID_SZ(PKCS11_CKA_START_DATE, 4), + PKCS11_ID_SZ(PKCS11_CKA_END_DATE, 4), + PKCS11_ID_SZ(PKCS11_CKA_OBJECT_ID, 0), + PKCS11_ID_SZ(PKCS11_CKA_APPLICATION, 0), + PKCS11_ID_SZ(PKCS11_CKA_MECHANISM_TYPE, 4), + PKCS11_ID_SZ(PKCS11_CKA_ID, 0), + PKCS11_ID_SZ(PKCS11_CKA_ALLOWED_MECHANISMS, 0), + PKCS11_ID_SZ(PKCS11_CKA_EC_POINT, 0), + PKCS11_ID_SZ(PKCS11_CKA_EC_PARAMS, 0), + PKCS11_ID_SZ(PKCS11_CKA_MODULUS, 0), + PKCS11_ID_SZ(PKCS11_CKA_MODULUS_BITS, 4), + PKCS11_ID_SZ(PKCS11_CKA_PUBLIC_EXPONENT, 0), + PKCS11_ID_SZ(PKCS11_CKA_PRIVATE_EXPONENT, 0), + PKCS11_ID_SZ(PKCS11_CKA_PRIME_1, 0), + PKCS11_ID_SZ(PKCS11_CKA_PRIME_2, 0), + PKCS11_ID_SZ(PKCS11_CKA_EXPONENT_1, 0), + PKCS11_ID_SZ(PKCS11_CKA_EXPONENT_2, 0), + PKCS11_ID_SZ(PKCS11_CKA_COEFFICIENT, 0), + PKCS11_ID_SZ(PKCS11_CKA_SUBJECT, 0), + PKCS11_ID_SZ(PKCS11_CKA_PUBLIC_KEY_INFO, 0), + PKCS11_ID_SZ(PKCS11_CKA_KEY_GEN_MECHANISM, 4), + /* Below are boolean attributes */ + PKCS11_ID_SZ(PKCS11_CKA_TOKEN, 1), + PKCS11_ID_SZ(PKCS11_CKA_PRIVATE, 1), + PKCS11_ID_SZ(PKCS11_CKA_TRUSTED, 1), + PKCS11_ID_SZ(PKCS11_CKA_SENSITIVE, 1), + PKCS11_ID_SZ(PKCS11_CKA_ENCRYPT, 1), + PKCS11_ID_SZ(PKCS11_CKA_DECRYPT, 1), + PKCS11_ID_SZ(PKCS11_CKA_WRAP, 1), + PKCS11_ID_SZ(PKCS11_CKA_UNWRAP, 1), + PKCS11_ID_SZ(PKCS11_CKA_SIGN, 1), + PKCS11_ID_SZ(PKCS11_CKA_SIGN_RECOVER, 1), + PKCS11_ID_SZ(PKCS11_CKA_VERIFY, 1), + PKCS11_ID_SZ(PKCS11_CKA_VERIFY_RECOVER, 1), + PKCS11_ID_SZ(PKCS11_CKA_DERIVE, 1), + PKCS11_ID_SZ(PKCS11_CKA_EXTRACTABLE, 1), + PKCS11_ID_SZ(PKCS11_CKA_LOCAL, 1), + PKCS11_ID_SZ(PKCS11_CKA_NEVER_EXTRACTABLE, 1), + PKCS11_ID_SZ(PKCS11_CKA_ALWAYS_SENSITIVE, 1), + PKCS11_ID_SZ(PKCS11_CKA_MODIFIABLE, 1), + PKCS11_ID_SZ(PKCS11_CKA_COPYABLE, 1), + PKCS11_ID_SZ(PKCS11_CKA_DESTROYABLE, 1), + PKCS11_ID_SZ(PKCS11_CKA_ALWAYS_AUTHENTICATE, 1), + PKCS11_ID_SZ(PKCS11_CKA_WRAP_WITH_TRUSTED, 1), + /* Specific PKCS11 TA internal attribute ID */ + PKCS11_ID_SZ(PKCS11_CKA_UNDEFINED_ID, 0), +}; + +struct any_id { + uint32_t id; +#if CFG_TEE_TA_LOG_LEVEL > 0 + const char *string; +#endif +}; + +/* + * Macro PKCS11_ID() can be used to define cells in ID list arrays + * or ID/string conversion arrays. + */ +#if CFG_TEE_TA_LOG_LEVEL > 0 +#define PKCS11_ID(_id) { .id = _id, .string = #_id } +#else +#define PKCS11_ID(_id) { .id = _id } +#endif + +#define ID2STR(id, table, prefix) \ + id2str(id, table, ARRAY_SIZE(table), prefix) + +#if CFG_TEE_TA_LOG_LEVEL > 0 +/* Convert a PKCS11 ID into its label string */ +static const char *id2str(uint32_t id, const struct any_id *table, + size_t count, const char *prefix) +{ + size_t n = 0; + const char *str = NULL; + + for (n = 0; n < count; n++) { + if (id != table[n].id) + continue; + + str = table[n].string; + + /* Skip prefix provided matches found */ + if (prefix && !TEE_MemCompare(str, prefix, strlen(prefix))) + str += strlen(prefix); + + return str; + } + + return unknown; +} +#endif /* CFG_TEE_TA_LOG_LEVEL > 0 */ + +/* + * TA command IDs: used only as ID/string conversion for debug trace support + */ +static const struct any_id __maybe_unused string_ta_cmd[] = { + PKCS11_ID(PKCS11_CMD_PING), + PKCS11_ID(PKCS11_CMD_SLOT_LIST), + PKCS11_ID(PKCS11_CMD_SLOT_INFO), + PKCS11_ID(PKCS11_CMD_TOKEN_INFO), + PKCS11_ID(PKCS11_CMD_MECHANISM_IDS), + PKCS11_ID(PKCS11_CMD_MECHANISM_INFO), + PKCS11_ID(PKCS11_CMD_OPEN_SESSION), + PKCS11_ID(PKCS11_CMD_SESSION_INFO), + PKCS11_ID(PKCS11_CMD_CLOSE_SESSION), + PKCS11_ID(PKCS11_CMD_CLOSE_ALL_SESSIONS), + PKCS11_ID(PKCS11_CMD_INIT_TOKEN), + PKCS11_ID(PKCS11_CMD_INIT_PIN), + PKCS11_ID(PKCS11_CMD_SET_PIN), + PKCS11_ID(PKCS11_CMD_LOGIN), + PKCS11_ID(PKCS11_CMD_LOGOUT), + PKCS11_ID(PKCS11_CMD_CREATE_OBJECT), + PKCS11_ID(PKCS11_CMD_DESTROY_OBJECT), + PKCS11_ID(PKCS11_CMD_ENCRYPT_INIT), + PKCS11_ID(PKCS11_CMD_DECRYPT_INIT), + PKCS11_ID(PKCS11_CMD_ENCRYPT_UPDATE), + PKCS11_ID(PKCS11_CMD_DECRYPT_UPDATE), + PKCS11_ID(PKCS11_CMD_ENCRYPT_FINAL), + PKCS11_ID(PKCS11_CMD_DECRYPT_FINAL), + PKCS11_ID(PKCS11_CMD_ENCRYPT_ONESHOT), + PKCS11_ID(PKCS11_CMD_DECRYPT_ONESHOT), + PKCS11_ID(PKCS11_CMD_SIGN_INIT), + PKCS11_ID(PKCS11_CMD_VERIFY_INIT), + PKCS11_ID(PKCS11_CMD_SIGN_UPDATE), + PKCS11_ID(PKCS11_CMD_VERIFY_UPDATE), + PKCS11_ID(PKCS11_CMD_SIGN_FINAL), + PKCS11_ID(PKCS11_CMD_VERIFY_FINAL), + PKCS11_ID(PKCS11_CMD_SIGN_ONESHOT), + PKCS11_ID(PKCS11_CMD_VERIFY_ONESHOT), + PKCS11_ID(PKCS11_CMD_GENERATE_KEY), + PKCS11_ID(PKCS11_CMD_FIND_OBJECTS_INIT), + PKCS11_ID(PKCS11_CMD_FIND_OBJECTS), + PKCS11_ID(PKCS11_CMD_FIND_OBJECTS_FINAL), + PKCS11_ID(PKCS11_CMD_GET_OBJECT_SIZE), + PKCS11_ID(PKCS11_CMD_GET_ATTRIBUTE_VALUE), + PKCS11_ID(PKCS11_CMD_SET_ATTRIBUTE_VALUE), + PKCS11_ID(PKCS11_CMD_COPY_OBJECT), + PKCS11_ID(PKCS11_CMD_SEED_RANDOM), + PKCS11_ID(PKCS11_CMD_GENERATE_RANDOM), + PKCS11_ID(PKCS11_CMD_DERIVE_KEY), + PKCS11_ID(PKCS11_CMD_RELEASE_ACTIVE_PROCESSING), + PKCS11_ID(PKCS11_CMD_DIGEST_INIT), + PKCS11_ID(PKCS11_CMD_DIGEST_UPDATE), + PKCS11_ID(PKCS11_CMD_DIGEST_KEY), + PKCS11_ID(PKCS11_CMD_DIGEST_ONESHOT), + PKCS11_ID(PKCS11_CMD_DIGEST_FINAL), + PKCS11_ID(PKCS11_CMD_GENERATE_KEY_PAIR), + PKCS11_ID(PKCS11_CMD_WRAP_KEY), + PKCS11_ID(PKCS11_CMD_UNWRAP_KEY), +}; + +static const struct any_id __maybe_unused string_slot_flags[] = { + PKCS11_ID(PKCS11_CKFS_TOKEN_PRESENT), + PKCS11_ID(PKCS11_CKFS_REMOVABLE_DEVICE), + PKCS11_ID(PKCS11_CKFS_HW_SLOT), +}; + +static const struct any_id __maybe_unused string_token_flags[] = { + PKCS11_ID(PKCS11_CKFT_RNG), + PKCS11_ID(PKCS11_CKFT_WRITE_PROTECTED), + PKCS11_ID(PKCS11_CKFT_LOGIN_REQUIRED), + PKCS11_ID(PKCS11_CKFT_USER_PIN_INITIALIZED), + PKCS11_ID(PKCS11_CKFT_RESTORE_KEY_NOT_NEEDED), + PKCS11_ID(PKCS11_CKFT_CLOCK_ON_TOKEN), + PKCS11_ID(PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH), + PKCS11_ID(PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS), + PKCS11_ID(PKCS11_CKFT_TOKEN_INITIALIZED), + PKCS11_ID(PKCS11_CKFT_USER_PIN_COUNT_LOW), + PKCS11_ID(PKCS11_CKFT_USER_PIN_FINAL_TRY), + PKCS11_ID(PKCS11_CKFT_USER_PIN_LOCKED), + PKCS11_ID(PKCS11_CKFT_USER_PIN_TO_BE_CHANGED), + PKCS11_ID(PKCS11_CKFT_SO_PIN_COUNT_LOW), + PKCS11_ID(PKCS11_CKFT_SO_PIN_FINAL_TRY), + PKCS11_ID(PKCS11_CKFT_SO_PIN_LOCKED), + PKCS11_ID(PKCS11_CKFT_SO_PIN_TO_BE_CHANGED), + PKCS11_ID(PKCS11_CKFT_ERROR_STATE), +}; + +static const struct any_id __maybe_unused string_session_flags[] = { + PKCS11_ID(PKCS11_CKFSS_RW_SESSION), + PKCS11_ID(PKCS11_CKFSS_SERIAL_SESSION), +}; + +static const struct any_id __maybe_unused string_session_state[] = { + PKCS11_ID(PKCS11_CKS_RO_PUBLIC_SESSION), + PKCS11_ID(PKCS11_CKS_RO_USER_FUNCTIONS), + PKCS11_ID(PKCS11_CKS_RW_PUBLIC_SESSION), + PKCS11_ID(PKCS11_CKS_RW_USER_FUNCTIONS), + PKCS11_ID(PKCS11_CKS_RW_SO_FUNCTIONS), +}; + +static const struct any_id __maybe_unused string_rc[] = { + PKCS11_ID(PKCS11_CKR_OK), + PKCS11_ID(PKCS11_CKR_SLOT_ID_INVALID), + PKCS11_ID(PKCS11_CKR_GENERAL_ERROR), + PKCS11_ID(PKCS11_CKR_FUNCTION_FAILED), + PKCS11_ID(PKCS11_CKR_ARGUMENTS_BAD), + PKCS11_ID(PKCS11_CKR_ATTRIBUTE_READ_ONLY), + PKCS11_ID(PKCS11_CKR_ATTRIBUTE_SENSITIVE), + PKCS11_ID(PKCS11_CKR_ATTRIBUTE_TYPE_INVALID), + PKCS11_ID(PKCS11_CKR_ATTRIBUTE_VALUE_INVALID), + PKCS11_ID(PKCS11_CKR_ACTION_PROHIBITED), + PKCS11_ID(PKCS11_CKR_DATA_LEN_RANGE), + PKCS11_ID(PKCS11_CKR_DEVICE_MEMORY), + PKCS11_ID(PKCS11_CKR_ENCRYPTED_DATA_INVALID), + PKCS11_ID(PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE), + PKCS11_ID(PKCS11_CKR_KEY_HANDLE_INVALID), + PKCS11_ID(PKCS11_CKR_KEY_SIZE_RANGE), + PKCS11_ID(PKCS11_CKR_KEY_TYPE_INCONSISTENT), + PKCS11_ID(PKCS11_CKR_KEY_INDIGESTIBLE), + PKCS11_ID(PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED), + PKCS11_ID(PKCS11_CKR_KEY_NOT_WRAPPABLE), + PKCS11_ID(PKCS11_CKR_KEY_UNEXTRACTABLE), + PKCS11_ID(PKCS11_CKR_MECHANISM_INVALID), + PKCS11_ID(PKCS11_CKR_MECHANISM_PARAM_INVALID), + PKCS11_ID(PKCS11_CKR_OBJECT_HANDLE_INVALID), + PKCS11_ID(PKCS11_CKR_OPERATION_ACTIVE), + PKCS11_ID(PKCS11_CKR_OPERATION_NOT_INITIALIZED), + PKCS11_ID(PKCS11_CKR_PIN_INCORRECT), + PKCS11_ID(PKCS11_CKR_PIN_INVALID), + PKCS11_ID(PKCS11_CKR_PIN_LEN_RANGE), + PKCS11_ID(PKCS11_CKR_PIN_EXPIRED), + PKCS11_ID(PKCS11_CKR_PIN_LOCKED), + PKCS11_ID(PKCS11_CKR_SESSION_HANDLE_INVALID), + PKCS11_ID(PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED), + PKCS11_ID(PKCS11_CKR_SESSION_READ_ONLY), + PKCS11_ID(PKCS11_CKR_SESSION_EXISTS), + PKCS11_ID(PKCS11_CKR_SESSION_READ_ONLY_EXISTS), + PKCS11_ID(PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS), + PKCS11_ID(PKCS11_CKR_SIGNATURE_INVALID), + PKCS11_ID(PKCS11_CKR_SIGNATURE_LEN_RANGE), + PKCS11_ID(PKCS11_CKR_TEMPLATE_INCOMPLETE), + PKCS11_ID(PKCS11_CKR_TEMPLATE_INCONSISTENT), + PKCS11_ID(PKCS11_CKR_TOKEN_NOT_PRESENT), + PKCS11_ID(PKCS11_CKR_TOKEN_NOT_RECOGNIZED), + PKCS11_ID(PKCS11_CKR_TOKEN_WRITE_PROTECTED), + PKCS11_ID(PKCS11_CKR_UNWRAPPING_KEY_HANDLE_INVALID), + PKCS11_ID(PKCS11_CKR_UNWRAPPING_KEY_SIZE_RANGE), + PKCS11_ID(PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT), + PKCS11_ID(PKCS11_CKR_USER_ALREADY_LOGGED_IN), + PKCS11_ID(PKCS11_CKR_USER_NOT_LOGGED_IN), + PKCS11_ID(PKCS11_CKR_USER_PIN_NOT_INITIALIZED), + PKCS11_ID(PKCS11_CKR_USER_TYPE_INVALID), + PKCS11_ID(PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN), + PKCS11_ID(PKCS11_CKR_USER_TOO_MANY_TYPES), + PKCS11_ID(PKCS11_CKR_WRAPPED_KEY_INVALID), + PKCS11_ID(PKCS11_CKR_WRAPPED_KEY_LEN_RANGE), + PKCS11_ID(PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID), + PKCS11_ID(PKCS11_CKR_WRAPPING_KEY_SIZE_RANGE), + PKCS11_ID(PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT), + PKCS11_ID(PKCS11_CKR_RANDOM_SEED_NOT_SUPPORTED), + PKCS11_ID(PKCS11_CKR_RANDOM_NO_RNG), + PKCS11_ID(PKCS11_CKR_DOMAIN_PARAMS_INVALID), + PKCS11_ID(PKCS11_CKR_CURVE_NOT_SUPPORTED), + PKCS11_ID(PKCS11_CKR_BUFFER_TOO_SMALL), + PKCS11_ID(PKCS11_CKR_PIN_TOO_WEAK), + PKCS11_ID(PKCS11_RV_NOT_FOUND), + PKCS11_ID(PKCS11_RV_NOT_IMPLEMENTED), +}; + +static const struct any_id __maybe_unused string_class[] = { + PKCS11_ID(PKCS11_CKO_SECRET_KEY), + PKCS11_ID(PKCS11_CKO_PUBLIC_KEY), + PKCS11_ID(PKCS11_CKO_PRIVATE_KEY), + PKCS11_ID(PKCS11_CKO_OTP_KEY), + PKCS11_ID(PKCS11_CKO_CERTIFICATE), + PKCS11_ID(PKCS11_CKO_DATA), + PKCS11_ID(PKCS11_CKO_DOMAIN_PARAMETERS), + PKCS11_ID(PKCS11_CKO_HW_FEATURE), + PKCS11_ID(PKCS11_CKO_MECHANISM), + PKCS11_ID(PKCS11_CKO_UNDEFINED_ID) +}; + +static const struct any_id __maybe_unused string_key_type[] = { + PKCS11_ID(PKCS11_CKK_AES), + PKCS11_ID(PKCS11_CKK_GENERIC_SECRET), + PKCS11_ID(PKCS11_CKK_MD5_HMAC), + PKCS11_ID(PKCS11_CKK_SHA_1_HMAC), + PKCS11_ID(PKCS11_CKK_SHA224_HMAC), + PKCS11_ID(PKCS11_CKK_SHA256_HMAC), + PKCS11_ID(PKCS11_CKK_SHA384_HMAC), + PKCS11_ID(PKCS11_CKK_SHA512_HMAC), + PKCS11_ID(PKCS11_CKK_EC), + PKCS11_ID(PKCS11_CKK_EC_EDWARDS), + PKCS11_ID(PKCS11_CKK_EDDSA), + PKCS11_ID(PKCS11_CKK_RSA), + PKCS11_ID(PKCS11_CKK_UNDEFINED_ID) +}; + +static const struct any_id __maybe_unused string_certificate_type[] = { + PKCS11_ID(PKCS11_CKC_X_509), + PKCS11_ID(PKCS11_CKC_X_509_ATTR_CERT), + PKCS11_ID(PKCS11_CKC_WTLS), + PKCS11_ID(PKCS11_CKC_UNDEFINED_ID) +}; + +/* + * Processing IDs not exported in the TA API. + * PKCS11_CKM_* mechanism IDs are looked up from mechanism_string_id(). + */ +static const struct any_id __maybe_unused string_internal_processing[] = { + PKCS11_ID(PKCS11_PROCESSING_IMPORT), +}; + +static const struct any_id __maybe_unused string_functions[] = { + PKCS11_ID(PKCS11_FUNCTION_DIGEST), + PKCS11_ID(PKCS11_FUNCTION_IMPORT), + PKCS11_ID(PKCS11_FUNCTION_ENCRYPT), + PKCS11_ID(PKCS11_FUNCTION_DECRYPT), + PKCS11_ID(PKCS11_FUNCTION_SIGN), + PKCS11_ID(PKCS11_FUNCTION_VERIFY), + PKCS11_ID(PKCS11_FUNCTION_DERIVE), + PKCS11_ID(PKCS11_FUNCTION_WRAP), + PKCS11_ID(PKCS11_FUNCTION_UNWRAP), +}; + +/* + * Conversion between PKCS11 TA and GPD TEE return codes + */ +enum pkcs11_rc tee2pkcs_error(TEE_Result res) +{ + switch (res) { + case TEE_SUCCESS: + return PKCS11_CKR_OK; + + case TEE_ERROR_BAD_PARAMETERS: + return PKCS11_CKR_ARGUMENTS_BAD; + + case TEE_ERROR_CIPHERTEXT_INVALID: + return PKCS11_CKR_ENCRYPTED_DATA_INVALID; + + case TEE_ERROR_OUT_OF_MEMORY: + return PKCS11_CKR_DEVICE_MEMORY; + + case TEE_ERROR_SHORT_BUFFER: + return PKCS11_CKR_BUFFER_TOO_SMALL; + + case TEE_ERROR_MAC_INVALID: + case TEE_ERROR_SIGNATURE_INVALID: + return PKCS11_CKR_SIGNATURE_INVALID; + + default: + return PKCS11_CKR_GENERAL_ERROR; + } +} + +/* + * Helper functions to analyse PKCS11 identifiers + */ + +/* Check attribute ID is known and size matches if fixed */ +bool valid_pkcs11_attribute_id(uint32_t id, uint32_t size) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(attr_ids); n++) + if (id == attr_ids[n].id) + return !attr_ids[n].size || size == attr_ids[n].size; + + return false; +} + +size_t pkcs11_attr_is_type(uint32_t attribute_id) +{ + enum pkcs11_attr_id id = attribute_id; + + switch (id) { + case PKCS11_CKA_KEY_TYPE: + case PKCS11_CKA_MECHANISM_TYPE: + case PKCS11_CKA_KEY_GEN_MECHANISM: + return sizeof(uint32_t); + default: + return 0; + } +} + +bool pkcs11_attr_has_indirect_attributes(uint32_t attribute_id) +{ + switch (attribute_id) { + case PKCS11_CKA_WRAP_TEMPLATE: + case PKCS11_CKA_UNWRAP_TEMPLATE: + case PKCS11_CKA_DERIVE_TEMPLATE: + return true; + default: + return false; + } +} + +bool pkcs11_class_has_type(uint32_t class) +{ + enum pkcs11_class_id class_id = class; + + switch (class_id) { + case PKCS11_CKO_CERTIFICATE: + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_PRIVATE_KEY: + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_MECHANISM: + case PKCS11_CKO_HW_FEATURE: + return true; + default: + return false; + } +} + +bool pkcs11_attr_class_is_key(uint32_t class) +{ + enum pkcs11_class_id class_id = class; + + switch (class_id) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_PRIVATE_KEY: + return true; + default: + return false; + } +} + +bool key_type_is_symm_key(uint32_t id) +{ + enum pkcs11_key_type key_type = id; + + switch (key_type) { + case PKCS11_CKK_AES: + case PKCS11_CKK_GENERIC_SECRET: + case PKCS11_CKK_MD5_HMAC: + case PKCS11_CKK_SHA_1_HMAC: + case PKCS11_CKK_SHA224_HMAC: + case PKCS11_CKK_SHA256_HMAC: + case PKCS11_CKK_SHA384_HMAC: + case PKCS11_CKK_SHA512_HMAC: + return true; + default: + return false; + } +} + +bool key_type_is_asymm_key(uint32_t id) +{ + enum pkcs11_key_type key_type = id; + + switch (key_type) { + case PKCS11_CKK_EC: + case PKCS11_CKK_EC_EDWARDS: + case PKCS11_CKK_RSA: + return true; + default: + return false; + } +} + +/* + * Returns shift position or -1 on error. + * Mainly used when PKCS11_SHEAD_WITH_BOOLPROPS is enabled + */ +int pkcs11_attr2boolprop_shift(uint32_t attr) +{ + static const uint32_t bpa[] = { + [BPA_TOKEN] = PKCS11_CKA_TOKEN, + [BPA_PRIVATE] = PKCS11_CKA_PRIVATE, + [BPA_TRUSTED] = PKCS11_CKA_TRUSTED, + [BPA_SENSITIVE] = PKCS11_CKA_SENSITIVE, + [BPA_ENCRYPT] = PKCS11_CKA_ENCRYPT, + [BPA_DECRYPT] = PKCS11_CKA_DECRYPT, + [BPA_WRAP] = PKCS11_CKA_WRAP, + [BPA_UNWRAP] = PKCS11_CKA_UNWRAP, + [BPA_SIGN] = PKCS11_CKA_SIGN, + [BPA_SIGN_RECOVER] = PKCS11_CKA_SIGN_RECOVER, + [BPA_VERIFY] = PKCS11_CKA_VERIFY, + [BPA_VERIFY_RECOVER] = PKCS11_CKA_VERIFY_RECOVER, + [BPA_DERIVE] = PKCS11_CKA_DERIVE, + [BPA_EXTRACTABLE] = PKCS11_CKA_EXTRACTABLE, + [BPA_LOCAL] = PKCS11_CKA_LOCAL, + [BPA_NEVER_EXTRACTABLE] = PKCS11_CKA_NEVER_EXTRACTABLE, + [BPA_ALWAYS_SENSITIVE] = PKCS11_CKA_ALWAYS_SENSITIVE, + [BPA_MODIFIABLE] = PKCS11_CKA_MODIFIABLE, + [BPA_COPYABLE] = PKCS11_CKA_COPYABLE, + [BPA_DESTROYABLE] = PKCS11_CKA_DESTROYABLE, + [BPA_ALWAYS_AUTHENTICATE] = PKCS11_CKA_ALWAYS_AUTHENTICATE, + [BPA_WRAP_WITH_TRUSTED] = PKCS11_CKA_WRAP_WITH_TRUSTED, + }; + size_t pos = 0; + + for (pos = 0; pos < ARRAY_SIZE(bpa); pos++) + if (bpa[pos] == attr) + return (int)pos; + + return -1; +} + +/* Initialize a TEE attribute for a target PKCS11 TA attribute in an object */ +bool pkcs2tee_load_attr(TEE_Attribute *tee_ref, uint32_t tee_id, + struct pkcs11_object *obj, + enum pkcs11_attr_id pkcs11_id) +{ + void *a_ptr = NULL; + uint8_t *der_ptr = NULL; + uint32_t a_size = 0; + uint32_t data32 = 0; + size_t hsize = 0; + size_t qsize = 0; + + switch (tee_id) { + case TEE_ATTR_ECC_PUBLIC_VALUE_X: + case TEE_ATTR_ECC_PUBLIC_VALUE_Y: + case TEE_ATTR_ECC_CURVE: + if (get_attribute_ptr(obj->attributes, PKCS11_CKA_EC_PARAMS, + &a_ptr, &a_size) || !a_ptr) { + EMSG("Missing EC_PARAMS attribute"); + return false; + } + + if (tee_id == TEE_ATTR_ECC_CURVE) { + data32 = ec_params2tee_curve(a_ptr, a_size); + TEE_InitValueAttribute(tee_ref, TEE_ATTR_ECC_CURVE, + data32, 0); + return true; + } + + data32 = (ec_params2tee_keysize(a_ptr, a_size) + 7) / 8; + + if (get_attribute_ptr(obj->attributes, PKCS11_CKA_EC_POINT, + &a_ptr, &a_size)) { + /* + * Public X/Y is required for both TEE keypair and + * public key, so abort if EC_POINT is not provided + * during object import. + */ + + EMSG("Missing EC_POINT attribute"); + return false; + } + + der_ptr = (uint8_t *)a_ptr; + + if (der_ptr[0] != 0x04) { + EMSG("Unsupported DER type"); + return false; + } + + if ((der_ptr[1] & 0x80) == 0) { + /* DER short definitive form up to 127 bytes */ + qsize = der_ptr[1] & 0x7F; + hsize = 2 /* der */ + 1 /* point compression */; + } else if (der_ptr[1] == 0x81) { + /* DER long definitive form up to 255 bytes */ + qsize = der_ptr[2]; + hsize = 3 /* der */ + 1 /* point compression */; + } else { + EMSG("Unsupported DER long form"); + return false; + } + + if (der_ptr[hsize - 1] != 0x04) { + EMSG("Unsupported EC_POINT compression"); + return false; + } + + if (a_size != (hsize - 1) + qsize) { + EMSG("Invalid EC_POINT attribute"); + return false; + } + + if (a_size != hsize + 2 * data32) { + EMSG("Invalid EC_POINT attribute"); + return false; + } + + if (tee_id == TEE_ATTR_ECC_PUBLIC_VALUE_X) + TEE_InitRefAttribute(tee_ref, tee_id, + der_ptr + hsize, data32); + else + TEE_InitRefAttribute(tee_ref, tee_id, + der_ptr + hsize + data32, + data32); + + return true; + + default: + break; + } + + if (get_attribute_ptr(obj->attributes, pkcs11_id, &a_ptr, &a_size)) + return false; + + TEE_InitRefAttribute(tee_ref, tee_id, a_ptr, a_size); + + return true; +} + +/* + * Initialize a TEE attribute with hash of a target PKCS11 TA attribute + * in an object. + */ +enum pkcs11_rc pkcs2tee_load_hashed_attr(TEE_Attribute *tee_ref, + uint32_t tee_id, + struct pkcs11_object *obj, + enum pkcs11_attr_id pkcs11_id, + uint32_t tee_algo, void *hash_ptr, + uint32_t *hash_size) +{ + TEE_OperationHandle handle = TEE_HANDLE_NULL; + void *a_ptr = NULL; + uint32_t a_size = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + TEE_Result res = TEE_ERROR_GENERIC; + size_t tmp_sz = 0; + + rc = get_attribute_ptr(obj->attributes, pkcs11_id, &a_ptr, &a_size); + if (rc) + return rc; + + res = TEE_AllocateOperation(&handle, tee_algo, TEE_MODE_DIGEST, 0); + if (res) { + EMSG("TEE_AllocateOperation() failed %#"PRIx32, tee_algo); + return tee2pkcs_error(res); + } + + tmp_sz = *hash_size; + res = TEE_DigestDoFinal(handle, a_ptr, a_size, hash_ptr, &tmp_sz); + *hash_size = tmp_sz; + TEE_FreeOperation(handle); + if (res) { + EMSG("TEE_DigestDoFinal() failed %#"PRIx32, tee_algo); + return PKCS11_CKR_FUNCTION_FAILED; + } + + TEE_InitRefAttribute(tee_ref, tee_id, hash_ptr, *hash_size); + + return PKCS11_CKR_OK; +} + +/* Easy conversion between PKCS11 TA function of TEE crypto mode */ +void pkcs2tee_mode(uint32_t *tee_id, enum processing_func function) +{ + switch (function) { + case PKCS11_FUNCTION_ENCRYPT: + *tee_id = TEE_MODE_ENCRYPT; + break; + case PKCS11_FUNCTION_DECRYPT: + *tee_id = TEE_MODE_DECRYPT; + break; + case PKCS11_FUNCTION_SIGN: + *tee_id = TEE_MODE_SIGN; + break; + case PKCS11_FUNCTION_VERIFY: + *tee_id = TEE_MODE_VERIFY; + break; + case PKCS11_FUNCTION_DERIVE: + *tee_id = TEE_MODE_DERIVE; + break; + case PKCS11_FUNCTION_DIGEST: + *tee_id = TEE_MODE_DIGEST; + break; + default: + TEE_Panic(function); + } +} + +#if CFG_TEE_TA_LOG_LEVEL > 0 +const char *id2str_rc(uint32_t id) +{ + return ID2STR(id, string_rc, "PKCS11_CKR_"); +} + +const char *id2str_ta_cmd(uint32_t id) +{ + return ID2STR(id, string_ta_cmd, NULL); +} + +const char *id2str_slot_flag(uint32_t id) +{ + return ID2STR(id, string_slot_flags, "PKCS11_CKFS_"); +} + +const char *id2str_token_flag(uint32_t id) +{ + return ID2STR(id, string_token_flags, "PKCS11_CKFT_"); +} + +const char *id2str_session_flag(uint32_t id) +{ + return ID2STR(id, string_session_flags, "PKCS11_CKFSS_"); +} + +const char *id2str_session_state(uint32_t id) +{ + return ID2STR(id, string_session_state, "PKCS11_CKS_"); +} + +const char *id2str_attr(uint32_t id) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(attr_ids); n++) { + if (id == attr_ids[n].id) { + /* Skip PKCS11_CKA_ prefix */ + return attr_ids[n].string + strlen("PKCS11_CKA_"); + } + } + + return unknown; +} + +const char *id2str_class(uint32_t id) +{ + return ID2STR(id, string_class, "PKCS11_CKO_"); +} + +const char *id2str_type(uint32_t id, uint32_t class) +{ + enum pkcs11_class_id class_id = class; + enum pkcs11_key_type key_type = id; + + switch (class_id) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_PRIVATE_KEY: + return id2str_key_type(key_type); + default: + return unknown; + } +} + +const char *id2str_key_type(uint32_t id) +{ + return ID2STR(id, string_key_type, "PKCS11_CKK_"); +} + +const char *id2str_certificate_type(uint32_t id) +{ + return ID2STR(id, string_certificate_type, "PKCS11_CKC_"); +} + +const char *id2str_attr_value(uint32_t id, size_t size, void *value) +{ + static const char str_true[] = "TRUE"; + static const char str_false[] = "FALSE"; + static const char str_unknown[] = "*"; + uint32_t type = 0; + + if (pkcs11_attr2boolprop_shift(id) >= 0) + return *(uint8_t *)value ? str_true : str_false; + + if (size < sizeof(uint32_t)) + return str_unknown; + + TEE_MemMove(&type, value, sizeof(uint32_t)); + + switch (id) { + case PKCS11_CKA_CLASS: + return id2str_class(type); + case PKCS11_CKA_KEY_TYPE: + return id2str_key_type(type); + case PKCS11_CKA_MECHANISM_TYPE: + return id2str_mechanism(type); + default: + return str_unknown; + } +} + +const char *id2str_proc(uint32_t id) +{ + const char *str = ID2STR(id, string_internal_processing, + "PKCS11_PROCESSING_"); + + if (str != unknown) + return str; + + return id2str_mechanism(id); +} + +const char *id2str_function(uint32_t id) +{ + return ID2STR(id, string_functions, "PKCS11_FUNCTION_"); +} +#endif /*CFG_TEE_TA_LOG_LEVEL*/ diff --git a/optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h b/optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h new file mode 100644 index 0000000..41b9b57 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_helpers.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#ifndef PKCS11_HELPERS_H +#define PKCS11_HELPERS_H + +#include +#include +#include +#include + +#include +#include + +struct pkcs11_object; + +/* + * TEE invocation parameter#0 is an in/out buffer of at least 32bit + * to store the TA PKCS#11 compliant return value. + */ +#define TEE_PARAM0_SIZE_MIN sizeof(uint32_t) + +/* GPD TEE to PKCS11 status conversion */ +enum pkcs11_rc tee2pkcs_error(TEE_Result res); + +/* + * Return true if and only if attribute ID with companion attribute value + * size do match a valid attribute identifier. + * + * @attribute_id - Target PKCS11 attribute ID + * @size - Byte size of the attribute value, 0 if non-constant size + */ +bool valid_pkcs11_attribute_id(uint32_t attribute_id, uint32_t size); + +/* + * Return type attribute byte size if @attribute_id is the ID of a type + * attribute or 0 if not. + */ +size_t pkcs11_attr_is_type(uint32_t attribute_id); + +/* Return true if the attribute has indirect attributes */ +bool pkcs11_attr_has_indirect_attributes(uint32_t attribute_id); + +/* Return true if the object class is related to a type-in-class */ +bool pkcs11_class_has_type(uint32_t class_id); + +/* Return true if the object class relates to a key */ +bool pkcs11_attr_class_is_key(uint32_t class_id); + +/* Return true if the key type @key_type_id relates to a symmetric key */ +bool key_type_is_symm_key(uint32_t key_type_id); + +/* Return true if the key type @key_type_id relates to an asymmetric key */ +bool key_type_is_asymm_key(uint32_t key_type_id); + +/* Boolprop flag shift position if @attribute_id is boolean, else -1 */ +int pkcs11_attr2boolprop_shift(uint32_t attribute_id); + +/* Convert PKCS11 TA function ID into a TEE crypto operation mode */ +void pkcs2tee_mode(uint32_t *tee_id, enum processing_func function); + +/* Load TEE operation attributes from a PKCS11 object, return false on error */ +bool pkcs2tee_load_attr(TEE_Attribute *tee_ref, uint32_t tee_id, + struct pkcs11_object *obj, + enum pkcs11_attr_id pkcs11_id); + +/* Hash and load TEE operation attributes from a PKCS11 object */ +enum pkcs11_rc pkcs2tee_load_hashed_attr(TEE_Attribute *tee_ref, + uint32_t tee_id, + struct pkcs11_object *obj, + enum pkcs11_attr_id pkcs11_id, + uint32_t tee_algo, void *hash_ptr, + uint32_t *hash_size); + +/* Return true if attribute is a boolean, false otherwise */ +static inline bool pkcs11_attr_is_boolean(enum pkcs11_attr_id id) +{ + return pkcs11_attr2boolprop_shift(id) >= 0; +} + +#if CFG_TEE_TA_LOG_LEVEL > 0 +/* Id-to-string conversions only for trace support */ +const char *id2str_ta_cmd(uint32_t id); +const char *id2str_rc(uint32_t id); +const char *id2str_slot_flag(uint32_t id); +const char *id2str_token_flag(uint32_t id); +const char *id2str_session_flag(uint32_t id); +const char *id2str_session_state(uint32_t id); +const char *id2str_attr(uint32_t id); +const char *id2str_class(uint32_t id); +const char *id2str_type(uint32_t id, uint32_t class); +const char *id2str_key_type(uint32_t id); +const char *id2str_certificate_type(uint32_t id); +const char *id2str_attr_value(uint32_t id, size_t size, void *value); +const char *id2str_proc(uint32_t id); +const char *id2str_function(uint32_t id); + +static inline const char *id2str_mechanism(enum pkcs11_mechanism_id id) +{ + return mechanism_string_id(id); +} +#endif /* CFG_TEE_TA_LOG_LEVEL > 0 */ +#endif /*PKCS11_HELPERS_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/pkcs11_token.c b/optee/optee_os/ta/pkcs11/src/pkcs11_token.c new file mode 100644 index 0000000..25ba778 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_token.c @@ -0,0 +1,1659 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "handle.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.h" +#include "serializer.h" +#include "token_capabilities.h" + +/* Number of tokens implemented by the TA. Token ID is the token index */ +#define TOKEN_COUNT CFG_PKCS11_TA_TOKEN_COUNT + +/* RNG chunk size used to split RNG generation to smaller sizes */ +#define RNG_CHUNK_SIZE 512U + +/* + * Structure tracking client applications + * + * @link - chained list of registered client applications + * @sessions - list of the PKCS11 sessions opened by the client application + * @object_handle_db - Database for object handles in name space of client + */ +struct pkcs11_client { + TAILQ_ENTRY(pkcs11_client) link; + struct session_list session_list; + struct handle_db session_handle_db; + struct handle_db object_handle_db; +}; + +/* Static allocation of tokens runtime instances (reset to 0 at load) */ +struct ck_token ck_token[TOKEN_COUNT]; + +static struct client_list pkcs11_client_list = + TAILQ_HEAD_INITIALIZER(pkcs11_client_list); + +static void close_ck_session(struct pkcs11_session *session); + +struct ck_token *get_token(unsigned int token_id) +{ + if (token_id < TOKEN_COUNT) + return &ck_token[confine_array_index(token_id, TOKEN_COUNT)]; + + return NULL; +} + +unsigned int get_token_id(struct ck_token *token) +{ + ptrdiff_t id = token - ck_token; + + assert(id >= 0 && id < TOKEN_COUNT); + return id; +} + +struct handle_db *get_object_handle_db(struct pkcs11_session *session) +{ + return &session->client->object_handle_db; +} + +struct session_list *get_session_list(struct pkcs11_session *session) +{ + return &session->client->session_list; +} + +struct pkcs11_client *tee_session2client(void *tee_session) +{ + struct pkcs11_client *client = NULL; + + TAILQ_FOREACH(client, &pkcs11_client_list, link) + if (client == tee_session) + break; + + return client; +} + +struct pkcs11_session *pkcs11_handle2session(uint32_t handle, + struct pkcs11_client *client) +{ + return handle_lookup(&client->session_handle_db, handle); +} + +struct pkcs11_client *register_client(void) +{ + struct pkcs11_client *client = NULL; + + client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO); + if (!client) + return NULL; + + TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link); + TAILQ_INIT(&client->session_list); + handle_db_init(&client->session_handle_db); + handle_db_init(&client->object_handle_db); + + return client; +} + +void unregister_client(struct pkcs11_client *client) +{ + struct pkcs11_session *session = NULL; + struct pkcs11_session *next = NULL; + + if (!client) { + EMSG("Invalid TEE session handle"); + return; + } + + TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) + close_ck_session(session); + + TAILQ_REMOVE(&pkcs11_client_list, client, link); + handle_db_destroy(&client->object_handle_db); + handle_db_destroy(&client->session_handle_db); + TEE_Free(client); +} + +static TEE_Result pkcs11_token_init(unsigned int id) +{ + struct ck_token *token = init_persistent_db(id); + + if (!token) + return TEE_ERROR_SECURITY; + + if (token->state == PKCS11_TOKEN_RESET) { + /* As per PKCS#11 spec, token resets to read/write state */ + token->state = PKCS11_TOKEN_READ_WRITE; + token->session_count = 0; + token->rw_session_count = 0; + } + + return TEE_SUCCESS; +} + +TEE_Result pkcs11_init(void) +{ + unsigned int id = 0; + TEE_Result ret = TEE_ERROR_GENERIC; + + for (id = 0; id < TOKEN_COUNT; id++) { + ret = pkcs11_token_init(id); + if (ret) + break; + } + + return ret; +} + +void pkcs11_deinit(void) +{ + unsigned int id = 0; + + for (id = 0; id < TOKEN_COUNT; id++) + close_persistent_db(get_token(id)); +} + +/* + * Currently no support for dual operations. + */ +enum pkcs11_rc set_processing_state(struct pkcs11_session *session, + enum processing_func function, + struct pkcs11_object *obj1, + struct pkcs11_object *obj2) +{ + enum pkcs11_proc_state state = PKCS11_SESSION_READY; + struct active_processing *proc = NULL; + + if (session->processing) + return PKCS11_CKR_OPERATION_ACTIVE; + + switch (function) { + case PKCS11_FUNCTION_ENCRYPT: + state = PKCS11_SESSION_ENCRYPTING; + break; + case PKCS11_FUNCTION_DECRYPT: + state = PKCS11_SESSION_DECRYPTING; + break; + case PKCS11_FUNCTION_SIGN: + state = PKCS11_SESSION_SIGNING; + break; + case PKCS11_FUNCTION_VERIFY: + state = PKCS11_SESSION_VERIFYING; + break; + case PKCS11_FUNCTION_DIGEST: + state = PKCS11_SESSION_DIGESTING; + break; + case PKCS11_FUNCTION_DERIVE: + case PKCS11_FUNCTION_WRAP: + case PKCS11_FUNCTION_UNWRAP: + state = PKCS11_SESSION_BUSY; + break; + default: + TEE_Panic(function); + return -1; + } + + proc = TEE_Malloc(sizeof(*proc), TEE_MALLOC_FILL_ZERO); + if (!proc) + return PKCS11_CKR_DEVICE_MEMORY; + + /* Boolean are default to false and pointers to NULL */ + proc->state = state; + proc->step = PKCS11_FUNC_STEP_INIT; + proc->tee_op_handle = TEE_HANDLE_NULL; + proc->tee_hash_algo = 0; + proc->tee_hash_op_handle = TEE_HANDLE_NULL; + + if (obj1 && get_bool(obj1->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE)) + proc->always_authen = true; + + if (obj2 && get_bool(obj2->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE)) + proc->always_authen = true; + + session->processing = proc; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_ck_slot_list(uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *out = params + 2; + uint32_t token_id = 0; + const size_t out_size = sizeof(token_id) * TOKEN_COUNT; + uint8_t *id = NULL; + + if (ptypes != exp_pt || + params[0].memref.size != TEE_PARAM0_SIZE_MIN) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (out->memref.size < out_size) { + out->memref.size = out_size; + + if (out->memref.buffer) + return PKCS11_CKR_BUFFER_TOO_SMALL; + else + return PKCS11_CKR_OK; + } + + for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT; + token_id++, id += sizeof(token_id)) + TEE_MemMove(id, &token_id, sizeof(token_id)); + + out->memref.size = out_size; + + return PKCS11_CKR_OK; +} + +static void pad_str(uint8_t *str, size_t size) +{ + int n = strnlen((char *)str, size); + + TEE_MemFill(str + n, ' ', size - n); +} + +static void set_token_description(struct pkcs11_slot_info *info) +{ + char desc[sizeof(info->slot_description) + 1] = { 0 }; + TEE_UUID dev_id = { }; + TEE_Result res = TEE_ERROR_GENERIC; + int n = 0; + + res = TEE_GetPropertyAsUUID(TEE_PROPSET_TEE_IMPLEMENTATION, + "gpd.tee.deviceID", &dev_id); + if (res == TEE_SUCCESS) { + n = snprintk(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION + " - TEE UUID %pUl", (void *)&dev_id); + } else { + n = snprintf(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION + " - No TEE UUID"); + } + if (n < 0 || n >= (int)sizeof(desc)) + TEE_Panic(0); + + TEE_MemMove(info->slot_description, desc, n); + pad_str(info->slot_description, sizeof(info->slot_description)); +} + +enum pkcs11_rc entry_ck_slot_info(uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + uint32_t token_id = 0; + struct pkcs11_slot_info info = { + .slot_description = PKCS11_SLOT_DESCRIPTION, + .manufacturer_id = PKCS11_SLOT_MANUFACTURER, + .flags = PKCS11_CKFS_TOKEN_PRESENT, + .hardware_version = PKCS11_SLOT_HW_VERSION, + .firmware_version = PKCS11_SLOT_FW_VERSION, + }; + + COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <= + sizeof(info.slot_description)); + COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <= + sizeof(info.manufacturer_id)); + + if (ptypes != exp_pt || out->memref.size != sizeof(info)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!get_token(token_id)) + return PKCS11_CKR_SLOT_ID_INVALID; + + set_token_description(&info); + + pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); + + out->memref.size = sizeof(info); + TEE_MemMove(out->memref.buffer, &info, out->memref.size); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_ck_token_info(uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + uint32_t token_id = 0; + struct ck_token *token = NULL; + struct pkcs11_token_info info = { + .manufacturer_id = PKCS11_TOKEN_MANUFACTURER, + .model = PKCS11_TOKEN_MODEL, + .max_session_count = UINT32_MAX, + .max_rw_session_count = UINT32_MAX, + .max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX, + .min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN, + .total_public_memory = UINT32_MAX, + .free_public_memory = UINT32_MAX, + .total_private_memory = UINT32_MAX, + .free_private_memory = UINT32_MAX, + .hardware_version = PKCS11_TOKEN_HW_VERSION, + .firmware_version = PKCS11_TOKEN_FW_VERSION, + }; + char sn[sizeof(info.serial_number) + 1] = { 0 }; + int n = 0; + + if (ptypes != exp_pt || out->memref.size != sizeof(info)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + token = get_token(token_id); + if (!token) + return PKCS11_CKR_SLOT_ID_INVALID; + + pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); + pad_str(info.model, sizeof(info.model)); + + n = snprintf(sn, sizeof(sn), "%0*"PRIu32, + (int)sizeof(info.serial_number), token_id); + if (n != (int)sizeof(info.serial_number)) + TEE_Panic(0); + + TEE_MemMove(info.serial_number, sn, sizeof(info.serial_number)); + pad_str(info.serial_number, sizeof(info.serial_number)); + + TEE_MemMove(info.label, token->db_main->label, sizeof(info.label)); + + info.flags = token->db_main->flags; + info.session_count = token->session_count; + info.rw_session_count = token->rw_session_count; + + TEE_MemMove(out->memref.buffer, &info, sizeof(info)); + + return PKCS11_CKR_OK; +} + +static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused, + uint32_t *array __maybe_unused, + size_t count __maybe_unused) +{ + size_t __maybe_unused n = 0; + + if (TRACE_LEVEL < TRACE_DEBUG) + return; + + for (n = 0; n < count; n++) + DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s", + token_id, array[n], id2str_mechanism(array[n])); +} + +enum pkcs11_rc entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + uint32_t token_id = 0; + struct ck_token __maybe_unused *token = NULL; + size_t count = 0; + uint32_t *array = NULL; + + if (ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + token = get_token(token_id); + if (!token) + return PKCS11_CKR_SLOT_ID_INVALID; + + count = out->memref.size / sizeof(*array); + array = tee_malloc_mechanism_list(&count); + + if (out->memref.size < count * sizeof(*array)) { + assert(!array); + out->memref.size = count * sizeof(*array); + if (out->memref.buffer) + return PKCS11_CKR_BUFFER_TOO_SMALL; + else + return PKCS11_CKR_OK; + } + + if (!array) + return PKCS11_CKR_DEVICE_MEMORY; + + dmsg_print_supported_mechanism(token_id, array, count); + + out->memref.size = count * sizeof(*array); + TEE_MemMove(out->memref.buffer, array, out->memref.size); + + TEE_Free(array); + + return rc; +} + +enum pkcs11_rc entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + uint32_t token_id = 0; + uint32_t type = 0; + struct ck_token *token = NULL; + struct pkcs11_mechanism_info info = { }; + + if (ptypes != exp_pt || out->memref.size != sizeof(info)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &type, sizeof(uint32_t)); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + token = get_token(token_id); + if (!token) + return PKCS11_CKR_SLOT_ID_INVALID; + + if (!mechanism_is_valid(type)) + return PKCS11_CKR_MECHANISM_INVALID; + + info.flags = mechanism_supported_flags(type); + + pkcs11_mechanism_supported_key_sizes(type, &info.min_key_size, + &info.max_key_size); + + TEE_MemMove(out->memref.buffer, &info, sizeof(info)); + + DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info", + token_id, type); + + return PKCS11_CKR_OK; +} + +/* Select the ReadOnly or ReadWrite state for session login state */ +static void set_session_state(struct pkcs11_client *client, + struct pkcs11_session *session, bool readonly) +{ + struct pkcs11_session *sess = NULL; + enum pkcs11_session_state state = PKCS11_CKS_RO_PUBLIC_SESSION; + + /* Default to public session if no session already registered */ + if (readonly) + state = PKCS11_CKS_RO_PUBLIC_SESSION; + else + state = PKCS11_CKS_RW_PUBLIC_SESSION; + + /* + * No need to check all client sessions, the first found in + * target token gives client login configuration. + */ + TAILQ_FOREACH(sess, &client->session_list, link) { + assert(sess != session); + + if (sess->token == session->token) { + switch (sess->state) { + case PKCS11_CKS_RW_PUBLIC_SESSION: + case PKCS11_CKS_RO_PUBLIC_SESSION: + if (readonly) + state = PKCS11_CKS_RO_PUBLIC_SESSION; + else + state = PKCS11_CKS_RW_PUBLIC_SESSION; + break; + case PKCS11_CKS_RO_USER_FUNCTIONS: + case PKCS11_CKS_RW_USER_FUNCTIONS: + if (readonly) + state = PKCS11_CKS_RO_USER_FUNCTIONS; + else + state = PKCS11_CKS_RW_USER_FUNCTIONS; + break; + case PKCS11_CKS_RW_SO_FUNCTIONS: + if (readonly) + TEE_Panic(0); + else + state = PKCS11_CKS_RW_SO_FUNCTIONS; + break; + default: + TEE_Panic(0); + } + break; + } + } + + session->state = state; +} + +enum pkcs11_rc entry_ck_open_session(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + uint32_t token_id = 0; + uint32_t flags = 0; + struct ck_token *token = NULL; + struct pkcs11_session *session = NULL; + bool readonly = false; + + if (!client || ptypes != exp_pt || + out->memref.size != sizeof(session->handle)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &flags, sizeof(flags)); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + token = get_token(token_id); + if (!token) + return PKCS11_CKR_SLOT_ID_INVALID; + + /* Sanitize session flags */ + if (!(flags & PKCS11_CKFSS_SERIAL_SESSION)) + return PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED; + + if (flags & ~(PKCS11_CKFSS_RW_SESSION | PKCS11_CKFSS_SERIAL_SESSION)) + return PKCS11_CKR_ARGUMENTS_BAD; + + readonly = !(flags & PKCS11_CKFSS_RW_SESSION); + + if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY) + return PKCS11_CKR_TOKEN_WRITE_PROTECTED; + + if (readonly) { + /* Specifically reject read-only session under SO login */ + TAILQ_FOREACH(session, &client->session_list, link) + if (pkcs11_session_is_so(session)) + return PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS; + } + + session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO); + if (!session) + return PKCS11_CKR_DEVICE_MEMORY; + + session->handle = handle_get(&client->session_handle_db, session); + if (!session->handle) { + TEE_Free(session); + return PKCS11_CKR_DEVICE_MEMORY; + } + + session->token = token; + session->client = client; + + LIST_INIT(&session->object_list); + + set_session_state(client, session, readonly); + + TAILQ_INSERT_HEAD(&client->session_list, session, link); + + session->token->session_count++; + if (!readonly) + session->token->rw_session_count++; + + TEE_MemMove(out->memref.buffer, &session->handle, + sizeof(session->handle)); + + DMSG("Open PKCS11 session %"PRIu32, session->handle); + + return PKCS11_CKR_OK; +} + +static void close_ck_session(struct pkcs11_session *session) +{ + release_active_processing(session); + release_session_find_obj_context(session); + + /* Release all session objects */ + while (!LIST_EMPTY(&session->object_list)) + destroy_object(session, + LIST_FIRST(&session->object_list), true); + + TAILQ_REMOVE(&session->client->session_list, session, link); + handle_put(&session->client->session_handle_db, session->handle); + + session->token->session_count--; + if (pkcs11_session_is_read_write(session)) + session->token->rw_session_count--; + + DMSG("Close PKCS11 session %"PRIu32, session->handle); + + TEE_Free(session); +} + +enum pkcs11_rc entry_ck_close_session(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + close_ck_session(session); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_ck_close_all_sessions(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + uint32_t token_id = 0; + struct ck_token *token = NULL; + struct pkcs11_session *session = NULL; + struct pkcs11_session *next = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + token = get_token(token_id); + if (!token) + return PKCS11_CKR_SLOT_ID_INVALID; + + DMSG("Close all sessions for PKCS11 token %"PRIu32, token_id); + + TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) + if (session->token == token) + close_ck_session(session); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_ck_session_info(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_session_info info = { + .flags = PKCS11_CKFSS_SERIAL_SESSION, + }; + + if (!client || ptypes != exp_pt || out->memref.size != sizeof(info)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + info.slot_id = get_token_id(session->token); + info.state = session->state; + if (pkcs11_session_is_read_write(session)) + info.flags |= PKCS11_CKFSS_RW_SESSION; + + TEE_MemMove(out->memref.buffer, &info, sizeof(info)); + + DMSG("Get find on PKCS11 session %"PRIu32, session->handle); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + char label[PKCS11_TOKEN_LABEL_SIZE] = { 0 }; + struct pkcs11_client *client = NULL; + struct pkcs11_session *sess = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + struct ck_token *token = NULL; + TEE_Param *ctrl = params; + uint32_t token_id = 0; + uint32_t pin_size = 0; + void *pin = NULL; + struct pkcs11_object *obj = NULL; + + if (ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &label, PKCS11_TOKEN_LABEL_SIZE); + if (rc) + return rc; + + rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + token = get_token(token_id); + if (!token) + return PKCS11_CKR_SLOT_ID_INVALID; + + if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) { + IMSG("Token %"PRIu32": SO PIN locked", token_id); + return PKCS11_CKR_PIN_LOCKED; + } + + /* Check there's no open session on this token */ + TAILQ_FOREACH(client, &pkcs11_client_list, link) + TAILQ_FOREACH(sess, &client->session_list, link) + if (sess->token == token) + return PKCS11_CKR_SESSION_EXISTS; + + /* Verify authentication if token is already initialized */ + if (token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED) { + unsigned int pin_count = 0; + + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + (token->db_main->flags & + PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)) { + /* Check TEE Identity based authentication if enabled */ + rc = verify_identity_auth(token, PKCS11_CKU_SO); + if (rc) + return rc; + + goto inited; + } + + /* Check PIN based authentication */ + rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, + token->db_main->so_pin_salt, + token->db_main->so_pin_hash); + if (!rc) + goto inited; + + if (rc != PKCS11_CKR_PIN_INCORRECT) + return rc; + + token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; + token->db_main->so_pin_count++; + + pin_count = token->db_main->so_pin_count; + if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) + token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; + if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) + token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED; + + update_persistent_db(token); + + return PKCS11_CKR_PIN_INCORRECT; + } + + /* Initialize SO's authentication */ + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && !pin) { + rc = setup_so_identity_auth_from_client(token); + if (rc) + return rc; + } else { + /* + * The spec doesn't permit returning + * PKCS11_CKR_PIN_LEN_RANGE for this function, take another + * error code. + */ + if (pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || + pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) + return PKCS11_CKR_ARGUMENTS_BAD; + + rc = hash_pin(PKCS11_CKU_SO, pin, pin_size, + &token->db_main->so_pin_salt, + token->db_main->so_pin_hash); + if (rc) + return rc; + } + +inited: + /* Make sure SO PIN counters are zeroed */ + token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW | + PKCS11_CKFT_SO_PIN_FINAL_TRY | + PKCS11_CKFT_SO_PIN_LOCKED | + PKCS11_CKFT_SO_PIN_TO_BE_CHANGED); + token->db_main->so_pin_count = 0; + + TEE_MemMove(token->db_main->label, label, PKCS11_TOKEN_LABEL_SIZE); + token->db_main->flags |= PKCS11_CKFT_TOKEN_INITIALIZED; + /* Reset user PIN */ + token->db_main->user_pin_salt = 0; + token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_INITIALIZED | + PKCS11_CKFT_USER_PIN_COUNT_LOW | + PKCS11_CKFT_USER_PIN_FINAL_TRY | + PKCS11_CKFT_USER_PIN_LOCKED | + PKCS11_CKFT_USER_PIN_TO_BE_CHANGED); + + update_persistent_db(token); + + /* Remove all persistent objects */ + while (!LIST_EMPTY(&token->object_list)) { + obj = LIST_FIRST(&token->object_list); + + /* Try twice otherwise panic! */ + if (unregister_persistent_object(token, obj->uuid) && + unregister_persistent_object(token, obj->uuid)) + TEE_Panic(0); + + cleanup_persistent_object(obj, token); + } + + IMSG("PKCS11 token %"PRIu32": initialized", token_id); + + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc set_pin(struct pkcs11_session *session, + uint8_t *new_pin, size_t new_pin_size, + enum pkcs11_user_type user_type) +{ + struct ck_token *token = session->token; + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint32_t flags_clear = 0; + uint32_t flags_set = 0; + + if (token->db_main->flags & PKCS11_CKFT_WRITE_PROTECTED) + return PKCS11_CKR_TOKEN_WRITE_PROTECTED; + + if (!pkcs11_session_is_read_write(session)) + return PKCS11_CKR_SESSION_READ_ONLY; + + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + (token->db_main->flags & + PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)) { + rc = setup_identity_auth_from_pin(token, user_type, + new_pin, new_pin_size); + if (rc == PKCS11_CKR_OK) { + goto update_db; + } else if (rc == PKCS11_CKR_PIN_INVALID && + !(token->db_main->flags & + PKCS11_CKFT_USER_PIN_INITIALIZED)) { + /* + * PIN was not compatible with TEE Identity + * Authentication syntax so let's assume it might be a + * new SO PIN to switch the authentication mode. + */ + + /* Update mode flag if all PIN checks pass */ + flags_clear |= + PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; + } else { + return rc; + } + } else if ((user_type == PKCS11_CKU_SO) && !new_pin && + IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + !(token->db_main->flags & + PKCS11_CKFT_USER_PIN_INITIALIZED)) { + /* + * Allow changing of token authentication mode before user pin + * has been initialized. + */ + + /* + * Set protected authentication path temporary until + * finalized. + */ + token->db_main->flags |= + PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; + + /* + * Setup authentication from currently active TEE Client + * Identity. + */ + rc = setup_identity_auth_from_pin(token, PKCS11_CKU_SO, + NULL, 0); + if (rc) { + /* + * Failed to setup protected authentication path so + * clear the temporary flag. + */ + token->db_main->flags &= + ~PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; + return rc; + } + + goto update_db; + } + + if (new_pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || + new_pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) + return PKCS11_CKR_PIN_LEN_RANGE; + + switch (user_type) { + case PKCS11_CKU_SO: + rc = hash_pin(user_type, new_pin, new_pin_size, + &token->db_main->so_pin_salt, + token->db_main->so_pin_hash); + if (rc) + return rc; + token->db_main->so_pin_count = 0; + flags_clear |= PKCS11_CKFT_SO_PIN_COUNT_LOW | + PKCS11_CKFT_SO_PIN_FINAL_TRY | + PKCS11_CKFT_SO_PIN_LOCKED | + PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; + break; + case PKCS11_CKU_USER: + rc = hash_pin(user_type, new_pin, new_pin_size, + &token->db_main->user_pin_salt, + token->db_main->user_pin_hash); + if (rc) + return rc; + token->db_main->user_pin_count = 0; + flags_clear |= PKCS11_CKFT_USER_PIN_COUNT_LOW | + PKCS11_CKFT_USER_PIN_FINAL_TRY | + PKCS11_CKFT_USER_PIN_LOCKED | + PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; + flags_set |= PKCS11_CKFT_USER_PIN_INITIALIZED; + break; + default: + return PKCS11_CKR_FUNCTION_FAILED; + } + +update_db: + token->db_main->flags &= ~flags_clear; + token->db_main->flags |= flags_set; + + update_persistent_db(token); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_ck_init_pin(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct pkcs11_session *session = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + TEE_Param *ctrl = params; + uint32_t pin_size = 0; + void *pin = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!pkcs11_session_is_so(session)) + return PKCS11_CKR_USER_NOT_LOGGED_IN; + + assert(session->token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); + + IMSG("PKCS11 session %"PRIu32": init PIN", session->handle); + + return set_pin(session, pin, pin_size, PKCS11_CKU_USER); +} + +static enum pkcs11_rc check_so_pin(struct pkcs11_session *session, + uint8_t *pin, size_t pin_size) +{ + struct ck_token *token = session->token; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); + + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) + return verify_identity_auth(token, PKCS11_CKU_SO); + + if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) + return PKCS11_CKR_PIN_LOCKED; + + rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, + token->db_main->so_pin_salt, + token->db_main->so_pin_hash); + if (rc) { + unsigned int pin_count = 0; + + if (rc != PKCS11_CKR_PIN_INCORRECT) + return rc; + + token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; + token->db_main->so_pin_count++; + + pin_count = token->db_main->so_pin_count; + if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) + token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; + if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) + token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED; + + update_persistent_db(token); + + if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) + return PKCS11_CKR_PIN_LOCKED; + + return PKCS11_CKR_PIN_INCORRECT; + } + + if (token->db_main->so_pin_count) { + token->db_main->so_pin_count = 0; + + update_persistent_db(token); + } + + if (token->db_main->flags & (PKCS11_CKFT_SO_PIN_COUNT_LOW | + PKCS11_CKFT_SO_PIN_FINAL_TRY)) { + token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW | + PKCS11_CKFT_SO_PIN_FINAL_TRY); + + update_persistent_db(token); + } + + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc check_user_pin(struct pkcs11_session *session, + uint8_t *pin, size_t pin_size) +{ + struct ck_token *token = session->token; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && + token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) + return verify_identity_auth(token, PKCS11_CKU_USER); + + if (!token->db_main->user_pin_salt) + return PKCS11_CKR_USER_PIN_NOT_INITIALIZED; + + if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED) + return PKCS11_CKR_PIN_LOCKED; + + rc = verify_pin(PKCS11_CKU_USER, pin, pin_size, + token->db_main->user_pin_salt, + token->db_main->user_pin_hash); + if (rc) { + unsigned int pin_count = 0; + + if (rc != PKCS11_CKR_PIN_INCORRECT) + return rc; + + token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW; + token->db_main->user_pin_count++; + + pin_count = token->db_main->user_pin_count; + if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) + token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY; + if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX) + token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED; + + update_persistent_db(token); + + if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED) + return PKCS11_CKR_PIN_LOCKED; + + return PKCS11_CKR_PIN_INCORRECT; + } + + if (token->db_main->user_pin_count) { + token->db_main->user_pin_count = 0; + + update_persistent_db(token); + } + + if (token->db_main->flags & (PKCS11_CKFT_USER_PIN_COUNT_LOW | + PKCS11_CKFT_USER_PIN_FINAL_TRY)) { + token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_COUNT_LOW | + PKCS11_CKFT_USER_PIN_FINAL_TRY); + + update_persistent_db(token); + } + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct pkcs11_session *session = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + uint32_t old_pin_size = 0; + TEE_Param *ctrl = params; + uint32_t pin_size = 0; + void *old_pin = NULL; + void *pin = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &old_pin_size, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get_ptr(&ctrlargs, &old_pin, old_pin_size); + if (rc) + return rc; + + rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!pkcs11_session_is_read_write(session)) + return PKCS11_CKR_SESSION_READ_ONLY; + + if (pkcs11_session_is_so(session)) { + if (!(session->token->db_main->flags & + PKCS11_CKFT_TOKEN_INITIALIZED)) + return PKCS11_CKR_GENERAL_ERROR; + + rc = check_so_pin(session, old_pin, old_pin_size); + if (rc) + return rc; + + IMSG("PKCS11 session %"PRIu32": set PIN", session->handle); + + return set_pin(session, pin, pin_size, PKCS11_CKU_SO); + } + + if (!(session->token->db_main->flags & + PKCS11_CKFT_USER_PIN_INITIALIZED)) + return PKCS11_CKR_GENERAL_ERROR; + + rc = check_user_pin(session, old_pin, old_pin_size); + if (rc) + return rc; + + IMSG("PKCS11 session %"PRIu32": set PIN", session->handle); + + return set_pin(session, pin, pin_size, PKCS11_CKU_USER); +} + +static void session_login_user(struct pkcs11_session *session) +{ + struct pkcs11_client *client = session->client; + struct pkcs11_session *sess = NULL; + + TAILQ_FOREACH(sess, &client->session_list, link) { + if (sess->token != session->token) + continue; + + if (pkcs11_session_is_read_write(sess)) + sess->state = PKCS11_CKS_RW_USER_FUNCTIONS; + else + sess->state = PKCS11_CKS_RO_USER_FUNCTIONS; + } +} + +static void session_login_so(struct pkcs11_session *session) +{ + struct pkcs11_client *client = session->client; + struct pkcs11_session *sess = NULL; + + TAILQ_FOREACH(sess, &client->session_list, link) { + if (sess->token != session->token) + continue; + + if (pkcs11_session_is_read_write(sess)) + sess->state = PKCS11_CKS_RW_SO_FUNCTIONS; + else + TEE_Panic(0); + } +} + +static void session_logout(struct pkcs11_session *session) +{ + struct pkcs11_client *client = session->client; + struct pkcs11_session *sess = NULL; + + TAILQ_FOREACH(sess, &client->session_list, link) { + struct pkcs11_object *obj = NULL; + struct pkcs11_object *tobj = NULL; + uint32_t handle = 0; + + if (sess->token != session->token) + continue; + + release_active_processing(session); + + /* Destroy private session objects */ + LIST_FOREACH_SAFE(obj, &sess->object_list, link, tobj) { + if (object_is_private(obj->attributes)) + destroy_object(sess, obj, true); + } + + /* + * Remove handle of token private objects from + * sessions object_handle_db + */ + LIST_FOREACH(obj, &session->token->object_list, link) { + handle = pkcs11_object2handle(obj, session); + + if (handle && object_is_private(obj->attributes)) + handle_put(get_object_handle_db(sess), handle); + } + + release_session_find_obj_context(session); + + if (pkcs11_session_is_read_write(sess)) + sess->state = PKCS11_CKS_RW_PUBLIC_SESSION; + else + sess->state = PKCS11_CKS_RO_PUBLIC_SESSION; + } +} + +enum pkcs11_rc entry_ck_login(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct pkcs11_session *session = NULL; + struct pkcs11_session *sess = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + TEE_Param *ctrl = params; + uint32_t user_type = 0; + uint32_t pin_size = 0; + void *pin = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &user_type, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + switch (user_type) { + case PKCS11_CKU_SO: + if (pkcs11_session_is_so(session)) + return PKCS11_CKR_USER_ALREADY_LOGGED_IN; + + if (pkcs11_session_is_user(session)) + return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN; + + TAILQ_FOREACH(sess, &client->session_list, link) + if (sess->token == session->token && + !pkcs11_session_is_read_write(sess)) + return PKCS11_CKR_SESSION_READ_ONLY_EXISTS; + + /* + * This is the point where we could check if another client + * has another user or SO logged in. + * + * The spec says: + * CKR_USER_TOO_MANY_TYPES: An attempt was made to have + * more distinct users simultaneously logged into the token + * than the token and/or library permits. For example, if + * some application has an open SO session, and another + * application attempts to log the normal user into a + * session, the attempt may return this error. It is not + * required to, however. Only if the simultaneous distinct + * users cannot be supported does C_Login have to return + * this value. Note that this error code generalizes to + * true multi-user tokens. + * + * So it's permitted to have another user or SO logged in + * from another client. + */ + + rc = check_so_pin(session, pin, pin_size); + if (!rc) + session_login_so(session); + + break; + + case PKCS11_CKU_USER: + if (pkcs11_session_is_so(session)) + return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN; + + if (pkcs11_session_is_user(session)) + return PKCS11_CKR_USER_ALREADY_LOGGED_IN; + + /* + * This is the point where we could check if another client + * has another user or SO logged in. + * See comment on CKR_USER_TOO_MANY_TYPES above. + */ + + rc = check_user_pin(session, pin, pin_size); + if (!rc) + session_login_user(session); + + break; + + case PKCS11_CKU_CONTEXT_SPECIFIC: + return PKCS11_CKR_OPERATION_NOT_INITIALIZED; + + default: + return PKCS11_CKR_USER_TYPE_INVALID; + } + + if (!rc) + IMSG("PKCS11 session %"PRIu32": login", session->handle); + + return rc; +} + +enum pkcs11_rc entry_ck_logout(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct pkcs11_session *session = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + TEE_Param *ctrl = params; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (pkcs11_session_is_public(session)) + return PKCS11_CKR_USER_NOT_LOGGED_IN; + + session_logout(session); + + IMSG("PKCS11 session %"PRIu32": logout", session->handle); + + return PKCS11_CKR_OK; +} + +static TEE_Result seed_rng_pool(void *seed, size_t length) +{ + static const TEE_UUID system_uuid = PTA_SYSTEM_UUID; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t ret_orig = 0; + + params[0].memref.buffer = seed; + params[0].memref.size = (uint32_t)length; + + res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("Can't open session to system PTA"); + return res; + } + + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + PTA_SYSTEM_ADD_RNG_ENTROPY, + param_types, params, &ret_orig); + if (res != TEE_SUCCESS) + EMSG("Can't invoke system PTA"); + + TEE_CloseTASession(sess); + return res; +} + +enum pkcs11_rc entry_ck_seed_random(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *in = params + 1; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + TEE_Result res = TEE_SUCCESS; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (in->memref.size && !in->memref.buffer) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!in->memref.size) + return PKCS11_CKR_OK; + + res = seed_rng_pool(in->memref.buffer, in->memref.size); + if (res != TEE_SUCCESS) + return PKCS11_CKR_FUNCTION_FAILED; + + DMSG("PKCS11 session %"PRIu32": seed random", session->handle); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_ck_generate_random(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + void *buffer = NULL; + size_t buffer_size = 0; + uint8_t *data = NULL; + size_t left = 0; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (out->memref.size && !out->memref.buffer) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!out->memref.size) + return PKCS11_CKR_OK; + + buffer_size = MIN(out->memref.size, RNG_CHUNK_SIZE); + buffer = TEE_Malloc(buffer_size, TEE_MALLOC_FILL_ZERO); + if (!buffer) + return PKCS11_CKR_DEVICE_MEMORY; + + data = out->memref.buffer; + left = out->memref.size; + + while (left) { + size_t count = MIN(left, buffer_size); + + TEE_GenerateRandom(buffer, count); + TEE_MemMove(data, buffer, count); + + data += count; + left -= count; + } + + DMSG("PKCS11 session %"PRIu32": generate random", session->handle); + + TEE_Free(buffer); + + return PKCS11_CKR_OK; +} diff --git a/optee/optee_os/ta/pkcs11/src/pkcs11_token.h b/optee/optee_os/ta/pkcs11/src/pkcs11_token.h new file mode 100644 index 0000000..6964057 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/pkcs11_token.h @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ +#ifndef PKCS11_TA_PKCS11_TOKEN_H +#define PKCS11_TA_PKCS11_TOKEN_H + +#include +#include +#include +#include + +#include "handle.h" +#include "object.h" +#include "pkcs11_attributes.h" + +/* Hard coded description */ +#define PKCS11_SLOT_DESCRIPTION "OP-TEE PKCS11 TA" +#define PKCS11_SLOT_MANUFACTURER "Linaro" +#define PKCS11_SLOT_HW_VERSION { 0, 0 } +#define PKCS11_SLOT_FW_VERSION { PKCS11_TA_VERSION_MAJOR, \ + PKCS11_TA_VERSION_MINOR } + +#define PKCS11_TOKEN_LABEL "OP-TEE PKCS#11 TA token" +#define PKCS11_TOKEN_MANUFACTURER PKCS11_SLOT_MANUFACTURER +#define PKCS11_TOKEN_MODEL "OP-TEE TA" +#define PKCS11_TOKEN_HW_VERSION PKCS11_SLOT_HW_VERSION +#define PKCS11_TOKEN_FW_VERSION PKCS11_SLOT_FW_VERSION + +enum pkcs11_token_state { + PKCS11_TOKEN_RESET = 0, + PKCS11_TOKEN_READ_WRITE, + PKCS11_TOKEN_READ_ONLY, +}; + +TAILQ_HEAD(client_list, pkcs11_client); +TAILQ_HEAD(session_list, pkcs11_session); + +struct pkcs11_client; + +#define PKCS11_MAX_USERS 2 +#define PKCS11_TOKEN_PIN_SIZE_MAX 128 +#define PKCS11_TOKEN_PIN_SIZE_MIN 4 +#define PKCS11_TOKEN_SO_PIN_COUNT_MAX 7 +#define PKCS11_TOKEN_USER_PIN_COUNT_MAX 7 + +/* + * Persistent state of the token + * + * @version - currently unused... + * @label - pkcs11 formatted token label, set by client + * @flags - pkcs11 token flags + * @so_pin_count - counter on security officer login failure + * @so_pin_salt - stores salt in hash of SO PIN, 0 if not set + * @so_pin_hash - stores hash of SO PIN + * @user_pin_count - counter on user login failure + * @user_pin_salt - stores salt in hash of user PIN, 0 if not set + * @user_pin_hash - stores hash of user PIN + */ +struct token_persistent_main { + uint32_t version; + uint8_t label[PKCS11_TOKEN_LABEL_SIZE]; + uint32_t flags; + uint32_t so_pin_count; + uint32_t so_pin_salt; + union { + uint8_t so_pin_hash[TEE_MAX_HASH_SIZE]; + TEE_Identity so_identity; + }; + uint32_t user_pin_count; + uint32_t user_pin_salt; + union { + uint8_t user_pin_hash[TEE_MAX_HASH_SIZE]; + TEE_Identity user_identity; + }; +}; + +/* + * Persistent objects in the token + * + * @count - number of objects stored in the token + * @uuids - array of object references/UUIDs (@count items) + */ +struct token_persistent_objs { + uint32_t count; + TEE_UUID uuids[]; +}; + +/* + * Runtime state of the token, complies with pkcs11 + * + * @state - Pkcs11 login is public, user, SO or custom + * @session_count - Counter for opened Pkcs11 sessions + * @rw_session_count - Count for opened Pkcs11 read/write sessions + * @object_list - List of the objects owned by the token + * @db_main - Volatile copy of the persistent main database + * @db_objs - Volatile copy of the persistent object database + */ +struct ck_token { + enum pkcs11_token_state state; + uint32_t session_count; + uint32_t rw_session_count; + struct object_list object_list; + /* Copy in RAM of the persistent database */ + struct token_persistent_main *db_main; + struct token_persistent_objs *db_objs; +}; + +/* + * A session can enter a processing state (encrypt, decrypt, digest, ...) + * only from the initialized state. A session must return the initialized + * state (from a processing finalization request) before entering another + * processing state. + */ +enum pkcs11_proc_state { + PKCS11_SESSION_READY = 0, /* No active processing */ + PKCS11_SESSION_ENCRYPTING, + PKCS11_SESSION_DECRYPTING, + PKCS11_SESSION_DIGESTING, + PKCS11_SESSION_DIGESTING_ENCRYPTING, /* case C_DigestEncryptUpdate */ + PKCS11_SESSION_DECRYPTING_DIGESTING, /* case C_DecryptDigestUpdate */ + PKCS11_SESSION_SIGNING, + PKCS11_SESSION_SIGNING_ENCRYPTING, /* case C_SignEncryptUpdate */ + PKCS11_SESSION_VERIFYING, + PKCS11_SESSION_DECRYPTING_VERIFYING, /* case C_DecryptVerifyUpdate */ + PKCS11_SESSION_SIGNING_RECOVER, + PKCS11_SESSION_VERIFYING_RECOVER, + PKCS11_SESSION_BUSY, +}; + +/* + * Context of the active processing in the session + * + * @state - ongoing active processing function or ready state + * @mecha_type - mechanism type of the active processing + * @always_authen - true if user need to login before each use + * @relogged - true once client logged since last operation update + * @op_step - last active operation step - update, final or one-shot + * @tee_op_handle - handle on active crypto operation or TEE_HANDLE_NULL + * @tee_hash_algo - hash algorithm identifier. + * @tee_hash_op_handle - handle on active hashing crypto operation or + * TEE_HANDLE_NULL + * @extra_ctx - context for the active processing + */ +struct active_processing { + enum pkcs11_proc_state state; + uint32_t mecha_type; + enum processing_step step; + bool always_authen; + bool relogged; + TEE_OperationHandle tee_op_handle; + uint32_t tee_hash_algo; + TEE_OperationHandle tee_hash_op_handle; + void *extra_ctx; +}; + +/* + * Pkcs11 objects search context + * + * @attributes - matching attributes list searched (null if no search) + * @count - number of matching handle found + * @handles - array of handle of matching objects + * @next - index of the next object handle to return to C_FindObject + */ +struct pkcs11_find_objects { + void *attributes; + size_t count; + uint32_t *handles; + size_t next; +}; + +/* + * Structure tracking the PKCS#11 sessions + * + * @link - List of the session belonging to a client + * @client - Client the session belongs to + * @token - Token this session belongs to + * @handle - Identifier of the session published to the client + * @object_list - Entry of the session objects list + * @state - R/W SO, R/W user, RO user, R/W public, RO public. + * @processing - Reference to initialized processing context if any + * @find_ctx - Reference to active search context (null if no active search) + */ +struct pkcs11_session { + TAILQ_ENTRY(pkcs11_session) link; + struct pkcs11_client *client; + struct ck_token *token; + enum pkcs11_mechanism_id handle; + struct object_list object_list; + enum pkcs11_session_state state; + struct active_processing *processing; + struct pkcs11_find_objects *find_ctx; +}; + +/* Initialize static token instance(s) from default/persistent database */ +TEE_Result pkcs11_init(void); +void pkcs11_deinit(void); + +/* Speculation safe lookup of token instance from token identifier */ +struct ck_token *get_token(unsigned int token_id); + +/* Return token identified from token instance address */ +unsigned int get_token_id(struct ck_token *token); + +/* Return client's (shared) object handle database associated with session */ +struct handle_db *get_object_handle_db(struct pkcs11_session *session); + +/* Access to persistent database */ +struct ck_token *init_persistent_db(unsigned int token_id); +void update_persistent_db(struct ck_token *token); +void close_persistent_db(struct ck_token *token); + +/* Load and release persistent object attributes in memory */ +enum pkcs11_rc load_persistent_object_attributes(struct pkcs11_object *obj); +void release_persistent_object_attributes(struct pkcs11_object *obj); +enum pkcs11_rc update_persistent_object_attributes(struct pkcs11_object *obj); + +enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin, + size_t pin_size, uint32_t *salt, + uint8_t hash[TEE_MAX_HASH_SIZE]); +enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin, + size_t pin_size, uint32_t salt, + const uint8_t hash[TEE_MAX_HASH_SIZE]); + +#if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) +enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token); +enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token, + enum pkcs11_user_type user_type, + const uint8_t *pin, + size_t pin_size); +enum pkcs11_rc verify_identity_auth(struct ck_token *token, + enum pkcs11_user_type user_type); +#else +static inline enum pkcs11_rc +setup_so_identity_auth_from_client(struct ck_token *token __unused) +{ + return PKCS11_CKR_PIN_INVALID; +} + +static inline enum pkcs11_rc +setup_identity_auth_from_pin(struct ck_token *token __unused, + enum pkcs11_user_type user_type __unused, + const uint8_t *pin __unused, + size_t pin_size __unused) +{ + return PKCS11_CKR_PIN_INVALID; +} + +static inline enum pkcs11_rc +verify_identity_auth(struct ck_token *token __unused, + enum pkcs11_user_type user_type __unused) +{ + return PKCS11_CKR_PIN_INCORRECT; +} +#endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ + +/* Token persistent objects */ +enum pkcs11_rc create_object_uuid(struct ck_token *token, + struct pkcs11_object *obj); +void destroy_object_uuid(struct ck_token *token, struct pkcs11_object *obj); +enum pkcs11_rc unregister_persistent_object(struct ck_token *token, + TEE_UUID *uuid); +enum pkcs11_rc register_persistent_object(struct ck_token *token, + TEE_UUID *uuid); +enum pkcs11_rc get_persistent_objects_list(struct ck_token *token, + TEE_UUID *array, size_t *size); + +/* + * Pkcs11 session support + */ +struct session_list *get_session_list(struct pkcs11_session *session); +struct pkcs11_client *tee_session2client(void *tee_session); +struct pkcs11_client *register_client(void); +void unregister_client(struct pkcs11_client *client); + +struct pkcs11_session *pkcs11_handle2session(uint32_t handle, + struct pkcs11_client *client); + +static inline bool session_is_active(struct pkcs11_session *session) +{ + return session->processing; +} + +enum pkcs11_rc set_processing_state(struct pkcs11_session *session, + enum processing_func function, + struct pkcs11_object *obj1, + struct pkcs11_object *obj2); + +static inline bool pkcs11_session_is_read_write(struct pkcs11_session *session) +{ + return session->state == PKCS11_CKS_RW_PUBLIC_SESSION || + session->state == PKCS11_CKS_RW_USER_FUNCTIONS || + session->state == PKCS11_CKS_RW_SO_FUNCTIONS; +} + +static inline bool pkcs11_session_is_public(struct pkcs11_session *session) +{ + return session->state == PKCS11_CKS_RO_PUBLIC_SESSION || + session->state == PKCS11_CKS_RW_PUBLIC_SESSION; +} + +static inline bool pkcs11_session_is_user(struct pkcs11_session *session) +{ + return session->state == PKCS11_CKS_RO_USER_FUNCTIONS || + session->state == PKCS11_CKS_RW_USER_FUNCTIONS; +} + +static inline bool pkcs11_session_is_so(struct pkcs11_session *session) +{ + return session->state == PKCS11_CKS_RW_SO_FUNCTIONS; +} + +static inline +struct object_list *pkcs11_get_session_objects(struct pkcs11_session *session) +{ + return &session->object_list; +} + +static inline +struct ck_token *pkcs11_session2token(struct pkcs11_session *session) +{ + return session->token; +} + +/* Entry point for the TA commands */ +enum pkcs11_rc entry_ck_slot_list(uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_slot_info(uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_token_info(uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_open_session(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_close_session(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_close_all_sessions(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_session_info(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_init_pin(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_login(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_logout(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_seed_random(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); +enum pkcs11_rc entry_ck_generate_random(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +#endif /*PKCS11_TA_PKCS11_TOKEN_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/processing.c b/optee/optee_os/ta/pkcs11/src/processing.c new file mode 100644 index 0000000..6be3482 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing.c @@ -0,0 +1,1287 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "object.h" +#include "pkcs11_attributes.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.h" +#include "serializer.h" + +static enum pkcs11_rc get_ready_session(struct pkcs11_session *session) +{ + if (session_is_active(session)) + return PKCS11_CKR_OPERATION_ACTIVE; + + return PKCS11_CKR_OK; +} + +static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd) +{ + switch (cmd) { + case PKCS11_CMD_ENCRYPT_UPDATE: + case PKCS11_CMD_ENCRYPT_ONESHOT: + case PKCS11_CMD_ENCRYPT_FINAL: + return PKCS11_FUNCTION_ENCRYPT; + case PKCS11_CMD_DECRYPT_UPDATE: + case PKCS11_CMD_DECRYPT_ONESHOT: + case PKCS11_CMD_DECRYPT_FINAL: + return PKCS11_FUNCTION_DECRYPT; + case PKCS11_CMD_SIGN_ONESHOT: + case PKCS11_CMD_SIGN_UPDATE: + case PKCS11_CMD_SIGN_FINAL: + return PKCS11_FUNCTION_SIGN; + case PKCS11_CMD_VERIFY_ONESHOT: + case PKCS11_CMD_VERIFY_UPDATE: + case PKCS11_CMD_VERIFY_FINAL: + return PKCS11_FUNCTION_VERIFY; + case PKCS11_CMD_DIGEST_UPDATE: + case PKCS11_CMD_DIGEST_KEY: + case PKCS11_CMD_DIGEST_ONESHOT: + case PKCS11_CMD_DIGEST_FINAL: + return PKCS11_FUNCTION_DIGEST; + default: + return PKCS11_FUNCTION_UNKNOWN; + } +} + +static bool func_matches_state(enum processing_func function, + enum pkcs11_proc_state state) +{ + switch (function) { + case PKCS11_FUNCTION_ENCRYPT: + return state == PKCS11_SESSION_ENCRYPTING || + state == PKCS11_SESSION_DIGESTING_ENCRYPTING || + state == PKCS11_SESSION_SIGNING_ENCRYPTING; + case PKCS11_FUNCTION_DECRYPT: + return state == PKCS11_SESSION_DECRYPTING || + state == PKCS11_SESSION_DECRYPTING_DIGESTING || + state == PKCS11_SESSION_DECRYPTING_VERIFYING; + case PKCS11_FUNCTION_DIGEST: + return state == PKCS11_SESSION_DIGESTING || + state == PKCS11_SESSION_DIGESTING_ENCRYPTING; + case PKCS11_FUNCTION_SIGN: + return state == PKCS11_SESSION_SIGNING || + state == PKCS11_SESSION_SIGNING_ENCRYPTING; + case PKCS11_FUNCTION_VERIFY: + return state == PKCS11_SESSION_VERIFYING || + state == PKCS11_SESSION_DECRYPTING_VERIFYING; + case PKCS11_FUNCTION_SIGN_RECOVER: + return state == PKCS11_SESSION_SIGNING_RECOVER; + case PKCS11_FUNCTION_VERIFY_RECOVER: + return state == PKCS11_SESSION_SIGNING_RECOVER; + default: + TEE_Panic(function); + return false; + } +} + +static enum pkcs11_rc get_active_session(struct pkcs11_session *session, + enum processing_func function) +{ + enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; + + if (session->processing && + func_matches_state(function, session->processing->state)) + rc = PKCS11_CKR_OK; + + return rc; +} + +void release_active_processing(struct pkcs11_session *session) +{ + if (!session->processing) + return; + + if (session->processing->tee_hash_op_handle != TEE_HANDLE_NULL) { + TEE_FreeOperation(session->processing->tee_hash_op_handle); + session->processing->tee_hash_op_handle = TEE_HANDLE_NULL; + session->processing->tee_hash_algo = 0; + } + + if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { + TEE_FreeOperation(session->processing->tee_op_handle); + session->processing->tee_op_handle = TEE_HANDLE_NULL; + } + + TEE_Free(session->processing->extra_ctx); + + TEE_Free(session->processing); + session->processing = NULL; +} + +size_t get_object_key_bit_size(struct pkcs11_object *obj) +{ + void *a_ptr = NULL; + uint32_t a_size = 0; + struct obj_attrs *attrs = obj->attributes; + + switch (get_key_type(attrs)) { + case PKCS11_CKK_AES: + case PKCS11_CKK_GENERIC_SECRET: + case PKCS11_CKK_MD5_HMAC: + case PKCS11_CKK_SHA_1_HMAC: + case PKCS11_CKK_SHA224_HMAC: + case PKCS11_CKK_SHA256_HMAC: + case PKCS11_CKK_SHA384_HMAC: + case PKCS11_CKK_SHA512_HMAC: + if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) + return 0; + + return a_size * 8; + case PKCS11_CKK_RSA: + if (get_attribute_ptr(attrs, PKCS11_CKA_MODULUS, NULL, &a_size)) + return 0; + + return a_size * 8; + case PKCS11_CKK_EC: + if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS, + &a_ptr, &a_size) || !a_ptr) + return 0; + + return ec_params2tee_keysize(a_ptr, a_size); + case PKCS11_CKK_EC_EDWARDS: + if (get_attribute_ptr(attrs, PKCS11_CKA_EC_POINT, NULL, + &a_size)) + return 0; + + return a_size * 8; + default: + TEE_Panic(0); + return 0; + } +} + +static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *data = NULL; + uint32_t data_size = 0; + uint32_t value_len = 0; + void *value = NULL; + + if (!*head) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + + rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size); + if (rc || data_size != sizeof(uint32_t)) { + DMSG("%s", rc ? "No attribute value_len found" : + "Invalid size for attribute VALUE_LEN"); + + return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; + } + TEE_MemMove(&value_len, data, data_size); + + /* Remove the default empty value attribute if found */ + rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); + if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) + return PKCS11_CKR_GENERAL_ERROR; + + value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!value) + return PKCS11_CKR_DEVICE_MEMORY; + + TEE_GenerateRandom(value, value_len); + + rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); + + TEE_Free(value); + + return rc; +} + +enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_attribute_head *proc_params = NULL; + struct obj_attrs *head = NULL; + struct pkcs11_object_head *template = NULL; + size_t template_size = 0; + uint32_t obj_handle = 0; + + if (!client || ptypes != exp_pt || + out->memref.size != sizeof(obj_handle)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); + if (rc) + goto out; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &template); + if (rc) + goto out; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + rc = get_ready_session(session); + if (rc) + goto out; + + template_size = sizeof(*template) + template->attrs_size; + + rc = check_mechanism_against_processing(session, proc_params->id, + PKCS11_FUNCTION_GENERATE, + PKCS11_FUNC_STEP_INIT); + if (rc) { + DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc); + goto out; + } + + /* + * Prepare a clean initial state for the requested object attributes. + * Free temporary template once done. + */ + rc = create_attributes_from_template(&head, template, template_size, + NULL, PKCS11_FUNCTION_GENERATE, + proc_params->id, + PKCS11_CKO_UNDEFINED_ID); + if (rc) + goto out; + + TEE_Free(template); + template = NULL; + + rc = check_created_attrs(head, NULL); + if (rc) + goto out; + + rc = check_created_attrs_against_processing(proc_params->id, head); + if (rc) + goto out; + + rc = check_created_attrs_against_token(session, head); + if (rc) + goto out; + + /* + * Execute target processing and add value as attribute + * PKCS11_CKA_VALUE. Symm key generation: depends on target + * processing to be used. + */ + switch (proc_params->id) { + case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: + case PKCS11_CKM_AES_KEY_GEN: + /* Generate random of size specified by attribute VALUE_LEN */ + rc = generate_random_key_value(&head); + if (rc) + goto out; + break; + + default: + rc = PKCS11_CKR_MECHANISM_INVALID; + goto out; + } + + TEE_Free(proc_params); + proc_params = NULL; + + /* + * Object is ready, register it and return a handle. + */ + rc = create_object(session, head, &obj_handle); + if (rc) + goto out; + + /* + * Now obj_handle (through the related struct pkcs11_object instance) + * owns the serialized buffer that holds the object attributes. + * We reset head to NULL as it is no more the buffer owner and would + * be freed at function out. + */ + head = NULL; + + TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); + out->memref.size = sizeof(obj_handle); + + DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32, + session->handle, obj_handle); + +out: + TEE_Free(proc_params); + TEE_Free(template); + TEE_Free(head); + + return rc; +} + +enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj, + uint32_t attribute, + void **data, size_t *size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *ptr = NULL; + size_t sz = 0; + + res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz); + if (res != TEE_ERROR_SHORT_BUFFER) + return PKCS11_CKR_FUNCTION_FAILED; + + ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!ptr) + return PKCS11_CKR_DEVICE_MEMORY; + + res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz); + if (res) { + TEE_Free(ptr); + } else { + *data = ptr; + *size = sz; + } + + return tee2pkcs_error(res); +} + +enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head, + uint32_t pkcs11_id, + TEE_ObjectHandle tee_obj, + uint32_t tee_id) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *a_ptr = NULL; + size_t a_size = 0; + + rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size); + if (rc) + goto out; + + rc = add_attribute(head, pkcs11_id, a_ptr, a_size); + + TEE_Free(a_ptr); + +out: + if (rc) + EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s", + tee_id, pkcs11_id, id2str_attr(pkcs11_id)); + return rc; +} + +enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_attribute_head *proc_params = NULL; + struct obj_attrs *pub_head = NULL; + struct obj_attrs *priv_head = NULL; + struct pkcs11_object_head *pub_template = NULL; + struct pkcs11_object_head *priv_template = NULL; + struct pkcs11_object *object = NULL; + size_t pub_template_size = 0; + size_t priv_template_size = 0; + uint32_t pubkey_handle = 0; + uint32_t privkey_handle = 0; + uint32_t *hdl_ptr = NULL; + size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle); + + if (!client || ptypes != exp_pt || out->memref.size != out_ref_size) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); + if (rc) + goto out; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template); + if (rc) + goto out; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template); + if (rc) + goto out; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + rc = get_ready_session(session); + if (rc) + goto out; + + rc = check_mechanism_against_processing(session, proc_params->id, + PKCS11_FUNCTION_GENERATE_PAIR, + PKCS11_FUNC_STEP_INIT); + if (rc) + goto out; + + pub_template_size = sizeof(*pub_template) + pub_template->attrs_size; + + rc = create_attributes_from_template(&pub_head, pub_template, + pub_template_size, NULL, + PKCS11_FUNCTION_GENERATE_PAIR, + proc_params->id, + PKCS11_CKO_PUBLIC_KEY); + if (rc) + goto out; + + TEE_Free(pub_template); + pub_template = NULL; + + priv_template_size = sizeof(*priv_template) + + priv_template->attrs_size; + + rc = create_attributes_from_template(&priv_head, priv_template, + priv_template_size, NULL, + PKCS11_FUNCTION_GENERATE_PAIR, + proc_params->id, + PKCS11_CKO_PRIVATE_KEY); + if (rc) + goto out; + + TEE_Free(priv_template); + priv_template = NULL; + + /* Generate CKA_ID for keys if not specified by the templates */ + rc = add_missing_attribute_id(&pub_head, &priv_head); + if (rc) + goto out; + + /* Check created object against processing and token state */ + rc = check_created_attrs(pub_head, priv_head); + if (rc) + goto out; + + rc = check_created_attrs_against_processing(proc_params->id, pub_head); + if (rc) + goto out; + + rc = check_created_attrs_against_processing(proc_params->id, + priv_head); + if (rc) + goto out; + + rc = check_created_attrs_against_token(session, pub_head); + if (rc) + goto out; + + rc = check_access_attrs_against_token(session, pub_head); + if (rc) + goto out; + + rc = check_created_attrs_against_token(session, priv_head); + if (rc) + goto out; + + rc = check_access_attrs_against_token(session, priv_head); + if (rc) + goto out; + + /* Generate key pair */ + switch (proc_params->id) { + case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: + rc = generate_eddsa_keys(proc_params, &pub_head, &priv_head); + break; + case PKCS11_CKM_EC_KEY_PAIR_GEN: + rc = generate_ec_keys(proc_params, &pub_head, &priv_head); + break; + case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: + rc = generate_rsa_keys(proc_params, &pub_head, &priv_head); + break; + default: + rc = PKCS11_CKR_MECHANISM_INVALID; + break; + } + if (rc) + goto out; + + TEE_Free(proc_params); + proc_params = NULL; + + /* + * Object is ready, register it and return a handle. + */ + rc = create_object(session, pub_head, &pubkey_handle); + if (rc) + goto out; + + /* + * Now obj_handle (through the related struct pkcs11_object instance) + * owns the serialized buffer that holds the object attributes. + * We reset local pub_head to NULL to mark that ownership has been + * transferred. + */ + pub_head = NULL; + + rc = create_object(session, priv_head, &privkey_handle); + if (rc) + goto out; + + /* Ownership has been transferred so mark it with NULL */ + priv_head = NULL; + + hdl_ptr = (uint32_t *)out->memref.buffer; + + TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle)); + TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle)); + + DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32, + session->handle, privkey_handle, pubkey_handle); + + pubkey_handle = 0; + privkey_handle = 0; +out: + if (pubkey_handle) { + object = pkcs11_handle2object(pubkey_handle, session); + if (!object) + TEE_Panic(0); + destroy_object(session, object, false); + } + TEE_Free(priv_head); + TEE_Free(pub_head); + TEE_Free(priv_template); + TEE_Free(pub_template); + TEE_Free(proc_params); + + return rc; +} + +/* + * entry_processing_init - Generic entry for initializing a processing + * + * @client = client reference + * @ptype = Invocation parameter types + * @params = Invocation parameters reference + * @function - encrypt, decrypt, sign, verify, digest, ... + */ +enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params, + enum processing_func function) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_attribute_head *proc_params = NULL; + uint32_t key_handle = 0; + struct pkcs11_object *obj = NULL; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (function != PKCS11_FUNCTION_DIGEST) { + rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); + if (rc) + return rc; + } + + rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out_free; + } + + rc = get_ready_session(session); + if (rc) + goto out_free; + + if (function != PKCS11_FUNCTION_DIGEST) { + obj = pkcs11_handle2object(key_handle, session); + if (!obj) { + rc = PKCS11_CKR_KEY_HANDLE_INVALID; + goto out_free; + } + } + + rc = set_processing_state(session, function, obj, NULL); + if (rc) + goto out; + + rc = check_mechanism_against_processing(session, proc_params->id, + function, + PKCS11_FUNC_STEP_INIT); + if (rc) + goto out; + + if (obj) { + rc = check_parent_attrs_against_processing(proc_params->id, + function, + obj->attributes); + if (rc) + goto out; + + rc = check_access_attrs_against_token(session, + obj->attributes); + if (rc) + goto out; + } + + if (processing_is_tee_symm(proc_params->id)) + rc = init_symm_operation(session, function, proc_params, obj); + else if (processing_is_tee_asymm(proc_params->id)) + rc = init_asymm_operation(session, function, proc_params, obj); + else if (processing_is_tee_digest(proc_params->id)) + rc = init_digest_operation(session, proc_params); + else + rc = PKCS11_CKR_MECHANISM_INVALID; + + if (rc == PKCS11_CKR_OK) { + DMSG("PKCS11 session %"PRIu32": init processing %s %s", + session->handle, id2str_proc(proc_params->id), + id2str_function(function)); + } + +out: + if (rc) + release_active_processing(session); +out_free: + TEE_Free(proc_params); + + return rc; +} + +/* + * entry_processing_step - Generic entry on active processing + * + * @client = client reference + * @ptype = Invocation parameter types + * @params = Invocation parameters reference + * @function - encrypt, decrypt, sign, verify, digest, ... + * @step - update, oneshot, final + */ +enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params, + enum processing_func function, + enum processing_step step) +{ + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; + uint32_t key_handle = 0; + struct pkcs11_object *obj = NULL; + + if (!client || + TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { + assert(function == PKCS11_FUNCTION_DIGEST); + + rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); + if (rc) + return rc; + } + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + rc = get_active_session(session, function); + if (rc) + return rc; + + if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { + assert(function == PKCS11_FUNCTION_DIGEST); + + obj = pkcs11_handle2object(key_handle, session); + if (!obj) { + rc = PKCS11_CKR_KEY_HANDLE_INVALID; + goto out; + } + + rc = check_access_attrs_against_token(session, + obj->attributes); + if (rc) { + rc = PKCS11_CKR_KEY_HANDLE_INVALID; + goto out; + } + } + + mecha_type = session->processing->mecha_type; + rc = check_mechanism_against_processing(session, mecha_type, + function, step); + if (rc) + goto out; + + if (processing_is_tee_symm(mecha_type)) + rc = step_symm_operation(session, function, step, + ptypes, params); + else if (processing_is_tee_asymm(mecha_type)) + rc = step_asymm_operation(session, function, step, + ptypes, params); + else if (processing_is_tee_digest(mecha_type)) + rc = step_digest_operation(session, step, obj, ptypes, params); + else + rc = PKCS11_CKR_MECHANISM_INVALID; + + if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE || + step == PKCS11_FUNC_STEP_UPDATE_KEY)) { + session->processing->step = PKCS11_FUNC_STEP_UPDATE; + DMSG("PKCS11 session%"PRIu32": processing %s %s", + session->handle, id2str_proc(mecha_type), + id2str_function(function)); + } + + if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && + step == PKCS11_FUNC_STEP_ONESHOT) + session->processing->step = PKCS11_FUNC_STEP_ONESHOT; + + if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && step == PKCS11_FUNC_STEP_FINAL) + session->processing->step = PKCS11_FUNC_STEP_FINAL; + +out: + switch (step) { + case PKCS11_FUNC_STEP_UPDATE: + case PKCS11_FUNC_STEP_UPDATE_KEY: + if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) + release_active_processing(session); + break; + default: + /* ONESHOT and FINAL terminates processing on success */ + if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) + release_active_processing(session); + break; + } + + return rc; +} + +enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params, + enum processing_func function) +{ + TEE_Param *ctrl = params; + TEE_Param *out = params + 2; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_attribute_head *proc_params = NULL; + struct pkcs11_object_head *template = NULL; + uint32_t parent_handle = 0; + uint32_t obj_handle = 0; + struct pkcs11_object *parent = NULL; + struct obj_attrs *head = NULL; + size_t template_size = 0; + void *in_buf = NULL; + uint32_t in_size = 0; + void *out_buf = NULL; + uint32_t out_size = 0; + enum processing_func operation = PKCS11_FUNCTION_UNKNOWN; + + if (!client || + TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT || + TEE_PARAM_TYPE_GET(ptypes, 2) != TEE_PARAM_TYPE_MEMREF_OUTPUT || + out->memref.size != sizeof(obj_handle) || + TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) + return PKCS11_CKR_ARGUMENTS_BAD; + + switch (function) { + case PKCS11_FUNCTION_UNWRAP: + if (TEE_PARAM_TYPE_GET(ptypes, 1) != + TEE_PARAM_TYPE_MEMREF_INPUT) + return PKCS11_CKR_ARGUMENTS_BAD; + + in_buf = params[1].memref.buffer; + in_size = params[1].memref.size; + if (in_size && !in_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + + /* + * Some unwrap mechanisms require encryption to be + * performed on the data passed in proc_params by parent + * key. Hence set operation as PKCS11_FUNCTION_DECRYPT + * to be used with init_symm_operation() + */ + operation = PKCS11_FUNCTION_DECRYPT; + break; + case PKCS11_FUNCTION_DERIVE: + if (TEE_PARAM_TYPE_GET(ptypes, 1) != TEE_PARAM_TYPE_NONE) + return PKCS11_CKR_ARGUMENTS_BAD; + + /* + * Some derivation mechanism require encryption to be + * performed on the data passed in proc_params by parent + * key. Hence set operation as PKCS11_FUNCTION_ENCRYPT + * to be used with init_symm_operation() + */ + operation = PKCS11_FUNCTION_ENCRYPT; + break; + default: + return PKCS11_CKR_ARGUMENTS_BAD; + } + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); + if (rc) + return rc; + + rc = serialargs_alloc_get_attributes(&ctrlargs, &template); + if (rc) + goto out_free; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out_free; + } + + /* Return error if processing already active */ + rc = get_ready_session(session); + if (rc) + goto out_free; + + /* Check parent handle */ + parent = pkcs11_handle2object(parent_handle, session); + if (!parent) { + rc = PKCS11_CKR_KEY_HANDLE_INVALID; + goto out_free; + } + + /* Check if mechanism can be used for derivation function */ + rc = check_mechanism_against_processing(session, proc_params->id, + function, + PKCS11_FUNC_STEP_INIT); + if (rc) + goto out_free; + + /* Set the processing state to active */ + rc = set_processing_state(session, function, parent, NULL); + if (rc) + goto out_free; + + /* + * Check if base/parent key has CKA_DERIVE set and its key type is + * compatible with the mechanism passed + */ + rc = check_parent_attrs_against_processing(proc_params->id, function, + parent->attributes); + if (rc) { + /* + * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors + * specified with C_Derive/Unwrap() in the specification. So + * return the next most appropriate error. + */ + if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) { + if (function == PKCS11_FUNCTION_UNWRAP) + rc = + PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; + else + rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT; + } + goto out; + } + + /* Check access of base/parent key */ + rc = check_access_attrs_against_token(session, parent->attributes); + if (rc) + goto out; + + template_size = sizeof(*template) + template->attrs_size; + /* + * Prepare a clean initial state for the requested object attributes + * using base/parent key attributes. Free temporary template once done. + */ + rc = create_attributes_from_template(&head, template, template_size, + parent->attributes, + function, + proc_params->id, + PKCS11_CKO_UNDEFINED_ID); + if (rc) + goto out; + + TEE_Free(template); + template = NULL; + + /* check_created_attrs() is called later once key size is known */ + + rc = check_created_attrs_against_processing(proc_params->id, head); + if (rc) + goto out; + + rc = check_created_attrs_against_token(session, head); + if (rc) + goto out; + + rc = check_access_attrs_against_token(session, head); + if (rc) + goto out; + + if (processing_is_tee_symm(proc_params->id)) { + rc = init_symm_operation(session, operation, proc_params, + parent); + if (rc) + goto out; + + switch (function) { + case PKCS11_FUNCTION_DERIVE: + rc = derive_key_by_symm_enc(session, &out_buf, + &out_size); + break; + case PKCS11_FUNCTION_UNWRAP: + rc = unwrap_key_by_symm(session, in_buf, in_size, + &out_buf, &out_size); + break; + default: + TEE_Panic(function); + } + if (rc) + goto out; + + } else if (processing_is_tee_asymm(proc_params->id)) { + switch (function) { + case PKCS11_FUNCTION_DERIVE: + rc = init_asymm_operation(session, function, + proc_params, parent); + if (rc) + goto out; + + rc = do_asymm_derivation(session, proc_params, &head); + if (!rc) + goto done; + break; + case PKCS11_FUNCTION_UNWRAP: + rc = init_asymm_operation(session, operation, + proc_params, parent); + if (rc) + goto out; + + rc = unwrap_key_by_asymm(session, in_buf, in_size, + &out_buf, &out_size); + break; + default: + TEE_Panic(function); + } + + if (rc) + goto out; + } else { + rc = PKCS11_CKR_MECHANISM_INVALID; + goto out; + } + + rc = set_key_data(&head, out_buf, out_size); + if (rc) + goto out; + +done: + TEE_Free(out_buf); + out_buf = NULL; + + TEE_Free(proc_params); + proc_params = NULL; + + /* + * Object is ready, register it and return a handle. + */ + rc = create_object(session, head, &obj_handle); + if (rc) + goto out; + + /* + * Now obj_handle (through the related struct pkcs11_object instance) + * owns the serialized buffer that holds the object attributes. + * We reset head to NULL as it is no more the buffer owner and would + * be freed at function out. + */ + head = NULL; + + TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); + out->memref.size = sizeof(obj_handle); + + DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, + session->handle, obj_handle); + +out: + release_active_processing(session); +out_free: + TEE_Free(proc_params); + TEE_Free(template); + TEE_Free(head); + TEE_Free(out_buf); + + return rc; +} + +enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, + uint32_t ptypes, + TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + enum processing_func function = PKCS11_FUNCTION_UNKNOWN; + uint32_t cmd = 0; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get_u32(&ctrlargs, &cmd); + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + function = func_for_cmd(cmd); + if (function == PKCS11_FUNCTION_UNKNOWN) + return PKCS11_CKR_ARGUMENTS_BAD; + + rc = get_active_session(session, function); + if (rc) + return rc; + + release_active_processing(session); + + DMSG("PKCS11 session %"PRIu32": release processing", session->handle); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_attribute_head *proc_params = NULL; + struct pkcs11_object *wrapping_key = NULL; + struct pkcs11_object *key = NULL; + void *req_attrs = NULL; + uint32_t wrapping_key_handle = 0; + uint32_t key_handle = 0; + uint32_t size = 0; + void *key_data = NULL; + uint32_t key_sz = 0; + void *out_buf = params[2].memref.buffer; + uint32_t out_size = params[2].memref.size; + const enum processing_func function = PKCS11_FUNCTION_WRAP; + + if (!client || ptypes != exp_pt || + (out_size && !out_buf)) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &wrapping_key_handle, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out_free; + } + + rc = get_ready_session(session); + if (rc) + goto out_free; + + wrapping_key = pkcs11_handle2object(wrapping_key_handle, session); + if (!wrapping_key) { + rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID; + goto out_free; + } + + key = pkcs11_handle2object(key_handle, session); + if (!key) { + rc = PKCS11_CKR_KEY_HANDLE_INVALID; + goto out_free; + } + + /* + * The wrapping key and key to be wrapped shouldn't be same. + * PKCS#11 spec doesn't explicitly state that but logically this isn't + * a use case and also acts as an attack vector, so explicitly + * disallow this. + */ + if (key == wrapping_key) { + rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID; + goto out_free; + } + + rc = set_processing_state(session, function, wrapping_key, NULL); + if (rc) + goto out_free; + + /* Check if mechanism can be used for wrapping function */ + rc = check_mechanism_against_processing(session, proc_params->id, + function, + PKCS11_FUNC_STEP_INIT); + if (rc) + goto out; + + /* + * Check if wrapping key has CKA_WRAP set and its key type is + * compatible with the mechanism passed + */ + rc = check_parent_attrs_against_processing(proc_params->id, function, + wrapping_key->attributes); + if (rc) { + /* + * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors + * specified with C_Wrap() in the specification. So + * return the next most appropriate error. + */ + if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) + rc = PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT; + + goto out; + } + + /* Check access of wrapping key */ + rc = check_access_attrs_against_token(session, + wrapping_key->attributes); + if (rc) + goto out; + + switch (get_class(key->attributes)) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PRIVATE_KEY: + break; + default: + rc = PKCS11_CKR_KEY_NOT_WRAPPABLE; + goto out; + } + + /* Check if key to be wrapped is extractable */ + if (!get_bool(key->attributes, PKCS11_CKA_EXTRACTABLE)) { + DMSG("Extractable property is false"); + rc = PKCS11_CKR_KEY_UNEXTRACTABLE; + goto out; + } + + if (get_bool(key->attributes, PKCS11_CKA_WRAP_WITH_TRUSTED) && + !get_bool(wrapping_key->attributes, PKCS11_CKA_TRUSTED)) { + DMSG("Wrap with trusted not satisfied"); + rc = PKCS11_CKR_KEY_NOT_WRAPPABLE; + goto out; + } + + rc = check_access_attrs_against_token(session, key->attributes); + if (rc) + goto out; + + rc = get_attribute_ptr(wrapping_key->attributes, + PKCS11_CKA_WRAP_TEMPLATE, &req_attrs, &size); + if (rc == PKCS11_CKR_OK && size != 0) { + if (!attributes_match_reference(key->attributes, req_attrs)) { + rc = PKCS11_CKR_KEY_HANDLE_INVALID; + goto out; + } + } + + rc = alloc_key_data_to_wrap(key->attributes, &key_data, &key_sz); + if (rc) + goto out; + + if (processing_is_tee_symm(proc_params->id)) { + rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, + proc_params, wrapping_key); + if (rc) + goto out; + + rc = wrap_data_by_symm_enc(session, key_data, key_sz, out_buf, + &out_size); + } else { + rc = init_asymm_operation(session, PKCS11_FUNCTION_ENCRYPT, + proc_params, wrapping_key); + if (rc) + goto out; + + rc = wrap_data_by_asymm_enc(session, key_data, key_sz, out_buf, + &out_size); + } + + if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL) + params[2].memref.size = out_size; + +out: + release_active_processing(session); +out_free: + TEE_Free(key_data); + TEE_Free(proc_params); + return rc; +} diff --git a/optee/optee_os/ta/pkcs11/src/processing.h b/optee/optee_os/ta/pkcs11/src/processing.h new file mode 100644 index 0000000..7201078 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing.h @@ -0,0 +1,270 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#ifndef PKCS11_TA_PROCESSING_H +#define PKCS11_TA_PROCESSING_H + +#include +#include +#include + +struct pkcs11_client; +struct pkcs11_session; +struct pkcs11_object; +struct active_processing; + +/** + * RSA PSS processing context + * + * @hash_alg: Hash algorithm mechanism + * @mgf_type: Mask generator function + * @salt_len: Length of the salt in bytes + */ +struct rsa_pss_processing_ctx { + enum pkcs11_mechanism_id hash_alg; + enum pkcs11_mgf_id mgf_type; + uint32_t salt_len; +}; + +/** + * RSA OAEP processing context + * + * @hash_alg: Hash algorithm mechanism + * @mgf_type: Mask generator function + * @source_type: Type of source. + * @source_data_len: Length of the source data. + * @source_data: Source data. + */ +struct rsa_oaep_processing_ctx { + enum pkcs11_mechanism_id hash_alg; + enum pkcs11_mgf_id mgf_type; + uint32_t source_type; + uint32_t source_data_len; + uint8_t source_data[]; +}; + +/** + * RSA AES key wrap processing context + * + * @hash_alg: Hash algorithm mechanism + * @mgf_type: Mask generator function + * @aes_key_bits: Length of AES key in bits + * @source_type: Type of source. + * @source_data_len: Length of the source data. + * @source_data: Source data. + */ +struct rsa_aes_key_wrap_processing_ctx { + enum pkcs11_mechanism_id hash_alg; + enum pkcs11_mgf_id mgf_type; + uint32_t aes_key_bits; + uint32_t source_type; + uint32_t source_data_len; + uint8_t source_data[]; +}; + +/** + * EDDSA processing context + * + * @flag: Prehash flag + * @ctx_len: Length of the context data + * @ctx: Context data + */ +struct eddsa_processing_ctx { + uint32_t flag; + uint32_t ctx_len; + uint8_t ctx[]; +}; + +/* + * Entry points from PKCS11 TA invocation commands + */ + +enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params, + enum processing_func function); + +enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params, + enum processing_func function, + enum processing_step step); + +enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params, + enum processing_func function); + +enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, + uint32_t ptypes, + TEE_Param *params); + +enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +/* + * Util + */ +size_t get_object_key_bit_size(struct pkcs11_object *obj); + +void release_active_processing(struct pkcs11_session *session); + +enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj, + uint32_t attribute, + void **data, size_t *size); + +enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head, + uint32_t pkcs11_id, + TEE_ObjectHandle tee_obj, + uint32_t tee_id); + +/* Asymmetric key operations util */ +bool processing_is_tee_asymm(uint32_t proc_id); + +enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session, + enum processing_func function, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj); + +enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session, + enum processing_func function, + enum processing_step step, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc wrap_data_by_asymm_enc(struct pkcs11_session *session, + void *data, uint32_t data_sz, + void *out_buf, uint32_t *out_sz); + +enum pkcs11_rc unwrap_key_by_asymm(struct pkcs11_session *session, void *data, + uint32_t data_sz, void **out_buf, + uint32_t *out_sz); + +/* + * Symmetric crypto algorithm specific functions + */ +bool processing_is_tee_symm(uint32_t proc_id); + +enum pkcs11_rc init_symm_operation(struct pkcs11_session *session, + enum processing_func function, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *key); + +enum pkcs11_rc step_symm_operation(struct pkcs11_session *session, + enum processing_func function, + enum processing_step step, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc tee_init_ctr_operation(struct active_processing *processing, + void *proc_params, size_t params_size); + +enum pkcs11_rc derive_key_by_symm_enc(struct pkcs11_session *session, + void **out_buf, uint32_t *out_sz); + +enum pkcs11_rc wrap_data_by_symm_enc(struct pkcs11_session *session, + void *data, uint32_t data_sz, + void *out_buf, uint32_t *out_sz); + +enum pkcs11_rc unwrap_key_by_symm(struct pkcs11_session *session, void *data, + uint32_t data_sz, void **out_buf, + uint32_t *out_sz); + +/* Digest specific functions */ +bool processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id); + +enum pkcs11_rc +init_digest_operation(struct pkcs11_session *session, + struct pkcs11_attribute_head *proc_params); + +enum pkcs11_rc step_digest_operation(struct pkcs11_session *session, + enum processing_step step, + struct pkcs11_object *obj, + uint32_t ptypes, TEE_Param *params); + +/* + * Elliptic curve crypto algorithm specific functions + */ +enum pkcs11_rc load_tee_ec_key_attrs(TEE_Attribute **tee_attrs, + size_t *tee_count, + struct pkcs11_object *obj); + +enum pkcs11_rc load_tee_eddsa_key_attrs(TEE_Attribute **tee_attrs, + size_t *tee_count, + struct pkcs11_object *obj); + +size_t ec_params2tee_keysize(void *attr, size_t size); + +uint32_t ec_params2tee_curve(void *attr, size_t size); + +enum pkcs11_rc pkcs2tee_algo_ecdsa(uint32_t *tee_id, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj); + +enum pkcs11_rc generate_ec_keys(struct pkcs11_attribute_head *proc_params, + struct obj_attrs **pub_head, + struct obj_attrs **priv_head); + +enum pkcs11_rc generate_eddsa_keys(struct pkcs11_attribute_head *proc_params, + struct obj_attrs **pub_head, + struct obj_attrs **priv_head); + +size_t ecdsa_get_input_max_byte_size(TEE_OperationHandle op); + +/* + * RSA crypto algorithm specific functions + */ +enum pkcs11_rc load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs, + size_t *tee_count, + struct pkcs11_object *obj); + +enum pkcs11_rc +pkcs2tee_proc_params_rsa_pss(struct active_processing *proc, + struct pkcs11_attribute_head *proc_params); + +enum pkcs11_rc pkcs2tee_validate_rsa_pss(struct active_processing *proc, + struct pkcs11_object *obj); + +enum pkcs11_rc pkcs2tee_algo_rsa_pss(uint32_t *tee_id, + struct pkcs11_attribute_head *params); + +enum pkcs11_rc +pkcs2tee_proc_params_rsa_oaep(struct active_processing *proc, + struct pkcs11_attribute_head *proc_params); + +enum pkcs11_rc +pkcs2tee_proc_params_rsa_aes_wrap(struct active_processing *proc, + struct pkcs11_attribute_head *proc_params); + +enum pkcs11_rc +pkcs2tee_proc_params_eddsa(struct active_processing *proc, + struct pkcs11_attribute_head *proc_params); + +enum pkcs11_rc pkcs2tee_algo_rsa_oaep(uint32_t *tee_id, uint32_t *tee_hash_id, + struct pkcs11_attribute_head *params); + +enum pkcs11_rc +pkcs2tee_algo_rsa_aes_wrap(uint32_t *tee_id, uint32_t *tee_hash_id, + struct pkcs11_attribute_head *params); + +enum pkcs11_rc generate_rsa_keys(struct pkcs11_attribute_head *proc_params, + struct obj_attrs **pub_head, + struct obj_attrs **priv_head); + +size_t rsa_get_input_max_byte_size(TEE_OperationHandle op); + +enum pkcs11_rc do_asymm_derivation(struct pkcs11_session *session, + struct pkcs11_attribute_head *proc_params, + struct obj_attrs **head); + +enum pkcs11_rc pkcs2tee_param_ecdh(struct pkcs11_attribute_head *proc_params, + void **pub_data, size_t *pub_size); + +enum pkcs11_rc pkcs2tee_algo_ecdh(uint32_t *tee_id, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj); + +#endif /*PKCS11_TA_PROCESSING_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/processing_aes.c b/optee/optee_os/ta/pkcs11/src/processing_aes.c new file mode 100644 index 0000000..f60ca4c --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_aes.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.h" +#include "serializer.h" + +enum pkcs11_rc tee_init_ctr_operation(struct active_processing *processing, + void *proc_params, size_t params_size) +{ + struct serialargs args = { }; + enum pkcs11_rc rc = PKCS11_CKR_OK; + /* CTR parameters */ + uint32_t incr_counter = 0; + void *counter_bits = NULL; + + if (!proc_params) + return PKCS11_CKR_ARGUMENTS_BAD; + + serialargs_init(&args, proc_params, params_size); + + rc = serialargs_get(&args, &incr_counter, sizeof(uint32_t)); + if (rc) + return rc; + + rc = serialargs_get_ptr(&args, &counter_bits, 16); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (incr_counter != 1) { + DMSG("Supports only 1 bit increment counter: %"PRIu32, + incr_counter); + + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + } + + TEE_CipherInit(processing->tee_op_handle, counter_bits, 16); + + return PKCS11_CKR_OK; +} diff --git a/optee/optee_os/ta/pkcs11/src/processing_asymm.c b/optee/optee_os/ta/pkcs11/src/processing_asymm.c new file mode 100644 index 0000000..30348c0 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_asymm.c @@ -0,0 +1,1112 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.h" +#include "serializer.h" + +bool processing_is_tee_asymm(uint32_t proc_id) +{ + switch (proc_id) { + /* RSA flavors */ + case PKCS11_CKM_RSA_AES_KEY_WRAP: + case PKCS11_CKM_RSA_PKCS: + case PKCS11_CKM_RSA_PKCS_OAEP: + case PKCS11_CKM_RSA_PKCS_PSS: + case PKCS11_CKM_MD5_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS: + case PKCS11_CKM_SHA224_RSA_PKCS: + case PKCS11_CKM_SHA256_RSA_PKCS: + case PKCS11_CKM_SHA384_RSA_PKCS: + case PKCS11_CKM_SHA512_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + /* EC flavors */ + case PKCS11_CKM_EDDSA: + case PKCS11_CKM_ECDSA: + case PKCS11_CKM_ECDH1_DERIVE: + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + return true; + default: + return false; + } +} + +static enum pkcs11_rc +pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id, + enum processing_func function __unused, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj) +{ + static const struct { + enum pkcs11_mechanism_id mech_id; + uint32_t tee_id; + uint32_t tee_hash_id; + } pkcs2tee_algo[] = { + /* RSA flavors */ + { PKCS11_CKM_RSA_AES_KEY_WRAP, 1, 0 }, + { PKCS11_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5, 0 }, + { PKCS11_CKM_RSA_PKCS_OAEP, 1, 0 }, + { PKCS11_CKM_RSA_PKCS_PSS, 1, 0 }, + { PKCS11_CKM_MD5_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_MD5, + TEE_ALG_MD5 }, + { PKCS11_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, + TEE_ALG_SHA1 }, + { PKCS11_CKM_SHA224_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224, + TEE_ALG_SHA224 }, + { PKCS11_CKM_SHA256_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, + TEE_ALG_SHA256 }, + { PKCS11_CKM_SHA384_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384, + TEE_ALG_SHA384 }, + { PKCS11_CKM_SHA512_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512, + TEE_ALG_SHA512 }, + { PKCS11_CKM_SHA1_RSA_PKCS_PSS, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, TEE_ALG_SHA1 }, + { PKCS11_CKM_SHA224_RSA_PKCS_PSS, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, TEE_ALG_SHA224 }, + { PKCS11_CKM_SHA256_RSA_PKCS_PSS, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, TEE_ALG_SHA256 }, + { PKCS11_CKM_SHA384_RSA_PKCS_PSS, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, TEE_ALG_SHA384 }, + { PKCS11_CKM_SHA512_RSA_PKCS_PSS, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, TEE_ALG_SHA512 }, + /* EC flavors (Must find key size from the object) */ + { PKCS11_CKM_ECDSA, 1, 0 }, + { PKCS11_CKM_ECDSA_SHA1, 1, TEE_ALG_SHA1 }, + { PKCS11_CKM_ECDSA_SHA224, 1, TEE_ALG_SHA224 }, + { PKCS11_CKM_ECDSA_SHA256, 1, TEE_ALG_SHA256 }, + { PKCS11_CKM_ECDSA_SHA384, 1, TEE_ALG_SHA384 }, + { PKCS11_CKM_ECDSA_SHA512, 1, TEE_ALG_SHA512 }, + { PKCS11_CKM_ECDH1_DERIVE, 1, 0 }, + { PKCS11_CKM_EDDSA, TEE_ALG_ED25519, 0 }, + }; + size_t n = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) { + if (pkcs2tee_algo[n].mech_id == proc_params->id) { + *tee_id = pkcs2tee_algo[n].tee_id; + *tee_hash_id = pkcs2tee_algo[n].tee_hash_id; + break; + } + } + + if (n == ARRAY_SIZE(pkcs2tee_algo)) + return PKCS11_RV_NOT_IMPLEMENTED; + + switch (proc_params->id) { + case PKCS11_CKM_RSA_PKCS_PSS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + rc = pkcs2tee_algo_rsa_pss(tee_id, proc_params); + break; + case PKCS11_CKM_RSA_PKCS_OAEP: + rc = pkcs2tee_algo_rsa_oaep(tee_id, tee_hash_id, proc_params); + break; + case PKCS11_CKM_RSA_AES_KEY_WRAP: + rc = pkcs2tee_algo_rsa_aes_wrap(tee_id, tee_hash_id, + proc_params); + break; + case PKCS11_CKM_ECDSA: + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + rc = pkcs2tee_algo_ecdsa(tee_id, proc_params, obj); + break; + case PKCS11_CKM_ECDH1_DERIVE: + rc = pkcs2tee_algo_ecdh(tee_id, proc_params, obj); + break; + default: + rc = PKCS11_CKR_OK; + break; + } + + /* + * PKCS#11 uses single mechanism CKM_RSA_PKCS for both ciphering and + * authentication whereas GPD TEE expects TEE_ALG_RSAES_PKCS1_V1_5 for + * ciphering and TEE_ALG_RSASSA_PKCS1_V1_5 for authentication. + */ + if (*tee_id == TEE_ALG_RSAES_PKCS1_V1_5 && + (function == PKCS11_FUNCTION_SIGN || + function == PKCS11_FUNCTION_VERIFY)) + *tee_id = TEE_ALG_RSASSA_PKCS1_V1_5; + + return rc; +} + +static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type, + struct pkcs11_object *obj, + enum processing_func function) +{ + enum pkcs11_class_id class = get_class(obj->attributes); + enum pkcs11_key_type type = get_key_type(obj->attributes); + + switch (class) { + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_PRIVATE_KEY: + break; + default: + TEE_Panic(class); + break; + } + + switch (type) { + case PKCS11_CKK_EC: + if (class == PKCS11_CKO_PRIVATE_KEY) { + if (function == PKCS11_FUNCTION_DERIVE) + *tee_type = TEE_TYPE_ECDH_KEYPAIR; + else + *tee_type = TEE_TYPE_ECDSA_KEYPAIR; + } else { + if (function == PKCS11_FUNCTION_DERIVE) + *tee_type = TEE_TYPE_ECDH_PUBLIC_KEY; + else + *tee_type = TEE_TYPE_ECDSA_PUBLIC_KEY; + } + break; + case PKCS11_CKK_RSA: + if (class == PKCS11_CKO_PRIVATE_KEY) + *tee_type = TEE_TYPE_RSA_KEYPAIR; + else + *tee_type = TEE_TYPE_RSA_PUBLIC_KEY; + break; + case PKCS11_CKK_EC_EDWARDS: + if (class == PKCS11_CKO_PRIVATE_KEY) + *tee_type = TEE_TYPE_ED25519_KEYPAIR; + else + *tee_type = TEE_TYPE_ED25519_PUBLIC_KEY; + break; + default: + TEE_Panic(type); + break; + } + + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc +allocate_tee_operation(struct pkcs11_session *session, + enum processing_func function, + struct pkcs11_attribute_head *params, + struct pkcs11_object *obj) +{ + uint32_t size = (uint32_t)get_object_key_bit_size(obj); + uint32_t algo = 0; + uint32_t hash_algo = 0; + uint32_t mode = 0; + uint32_t hash_mode = 0; + TEE_Result res = TEE_ERROR_GENERIC; + struct active_processing *processing = session->processing; + + assert(processing->tee_op_handle == TEE_HANDLE_NULL); + assert(processing->tee_hash_op_handle == TEE_HANDLE_NULL); + + if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj)) + return PKCS11_CKR_FUNCTION_FAILED; + + pkcs2tee_mode(&mode, function); + + if (hash_algo) { + pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST); + + res = TEE_AllocateOperation(&processing->tee_hash_op_handle, + hash_algo, hash_mode, 0); + if (res) { + EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32, + hash_algo, hash_mode); + + if (res == TEE_ERROR_NOT_SUPPORTED) + return PKCS11_CKR_MECHANISM_INVALID; + return tee2pkcs_error(res); + } + processing->tee_hash_algo = hash_algo; + } + + res = TEE_AllocateOperation(&processing->tee_op_handle, + algo, mode, size); + if (res) + EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32, + algo, mode, size); + + if (res == TEE_ERROR_NOT_SUPPORTED) + return PKCS11_CKR_MECHANISM_INVALID; + + if (res != TEE_SUCCESS && + processing->tee_hash_op_handle != TEE_HANDLE_NULL) { + TEE_FreeOperation(session->processing->tee_hash_op_handle); + processing->tee_hash_op_handle = TEE_HANDLE_NULL; + processing->tee_hash_algo = 0; + } + + return tee2pkcs_error(res); +} + +static enum pkcs11_rc load_tee_key(struct pkcs11_session *session, + struct pkcs11_object *obj, + enum processing_func function) +{ + TEE_Attribute *tee_attrs = NULL; + size_t tee_attrs_count = 0; + size_t object_size = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + enum pkcs11_class_id __maybe_unused class = get_class(obj->attributes); + enum pkcs11_key_type type = get_key_type(obj->attributes); + + assert(class == PKCS11_CKO_PUBLIC_KEY || + class == PKCS11_CKO_PRIVATE_KEY); + + if (obj->key_handle != TEE_HANDLE_NULL) { + switch (type) { + case PKCS11_CKK_RSA: + /* RSA loaded keys can be reused */ + assert((obj->key_type == TEE_TYPE_RSA_PUBLIC_KEY && + class == PKCS11_CKO_PUBLIC_KEY) || + (obj->key_type == TEE_TYPE_RSA_KEYPAIR && + class == PKCS11_CKO_PRIVATE_KEY)); + goto key_ready; + case PKCS11_CKK_EC: + /* Reuse EC TEE key only if already DSA or DH */ + switch (obj->key_type) { + case TEE_TYPE_ECDSA_PUBLIC_KEY: + case TEE_TYPE_ECDSA_KEYPAIR: + if (function != PKCS11_FUNCTION_DERIVE) + goto key_ready; + break; + case TEE_TYPE_ECDH_PUBLIC_KEY: + case TEE_TYPE_ECDH_KEYPAIR: + if (function == PKCS11_FUNCTION_DERIVE) + goto key_ready; + break; + default: + assert(0); + break; + } + break; + default: + assert(0); + break; + } + + TEE_CloseObject(obj->key_handle); + obj->key_handle = TEE_HANDLE_NULL; + } + + rc = pkcs2tee_key_type(&obj->key_type, obj, function); + if (rc) + return rc; + + object_size = get_object_key_bit_size(obj); + if (!object_size) + return PKCS11_CKR_GENERAL_ERROR; + + switch (type) { + case PKCS11_CKK_RSA: + rc = load_tee_rsa_key_attrs(&tee_attrs, &tee_attrs_count, obj); + break; + case PKCS11_CKK_EC: + rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj); + break; + case PKCS11_CKK_EC_EDWARDS: + rc = load_tee_eddsa_key_attrs(&tee_attrs, &tee_attrs_count, + obj); + break; + default: + break; + } + if (rc) + return rc; + + res = TEE_AllocateTransientObject(obj->key_type, object_size, + &obj->key_handle); + if (res) { + DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res); + + return tee2pkcs_error(res); + } + + res = TEE_PopulateTransientObject(obj->key_handle, + tee_attrs, tee_attrs_count); + + TEE_Free(tee_attrs); + + if (res) { + DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res); + + goto error; + } + +key_ready: + res = TEE_SetOperationKey(session->processing->tee_op_handle, + obj->key_handle); + if (res) { + DMSG("TEE_SetOperationKey failed, %#"PRIx32, res); + + goto error; + } + + return PKCS11_CKR_OK; + +error: + TEE_FreeTransientObject(obj->key_handle); + obj->key_handle = TEE_HANDLE_NULL; + return tee2pkcs_error(res); +} + +static enum pkcs11_rc +init_tee_operation(struct pkcs11_session *session, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct active_processing *proc = session->processing; + + switch (proc_params->id) { + case PKCS11_CKM_RSA_PKCS_PSS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + rc = pkcs2tee_proc_params_rsa_pss(proc, proc_params); + if (rc) + break; + + rc = pkcs2tee_validate_rsa_pss(proc, obj); + break; + case PKCS11_CKM_RSA_PKCS_OAEP: + rc = pkcs2tee_proc_params_rsa_oaep(proc, proc_params); + break; + case PKCS11_CKM_EDDSA: + rc = pkcs2tee_proc_params_eddsa(proc, proc_params); + break; + case PKCS11_CKM_RSA_AES_KEY_WRAP: + rc = pkcs2tee_proc_params_rsa_aes_wrap(proc, proc_params); + break; + default: + break; + } + + return rc; +} + +enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session, + enum processing_func function, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + assert(processing_is_tee_asymm(proc_params->id)); + + rc = allocate_tee_operation(session, function, proc_params, obj); + if (rc) + return rc; + + rc = load_tee_key(session, obj, function); + if (rc) + return rc; + + rc = init_tee_operation(session, proc_params, obj); + if (!rc) + session->processing->mecha_type = proc_params->id; + + return rc; +} + +/* + * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation + * + * @session - current session + * @function - processing function (encrypt, decrypt, sign, ...) + * @step - step ID in the processing (oneshot, update, final) + * @ptypes - invocation parameter types + * @params - invocation parameter references + */ +enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session, + enum processing_func function, + enum processing_step step, + uint32_t ptypes, TEE_Param *params) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + void *in_buf = NULL; + void *in2_buf = NULL; + void *out_buf = NULL; + void *hash_buf = NULL; + uint32_t in_size = 0; + uint32_t in2_size = 0; + size_t out_size = 0; + size_t hash_size = 0; + TEE_Attribute *tee_attrs = NULL; + size_t tee_attrs_count = 0; + bool output_data = false; + struct active_processing *proc = session->processing; + struct rsa_aes_key_wrap_processing_ctx *rsa_aes_ctx = NULL; + struct rsa_oaep_processing_ctx *rsa_oaep_ctx = NULL; + struct rsa_pss_processing_ctx *rsa_pss_ctx = NULL; + struct eddsa_processing_ctx *eddsa_ctx = NULL; + size_t sz = 0; + + if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) { + in_buf = params[1].memref.buffer; + in_size = params[1].memref.size; + if (in_size && !in_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + } + if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) { + in2_buf = params[2].memref.buffer; + in2_size = params[2].memref.size; + if (in2_size && !in2_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + } + if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) { + out_buf = params[2].memref.buffer; + out_size = params[2].memref.size; + if (out_size && !out_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + } + if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) + return PKCS11_CKR_ARGUMENTS_BAD; + + switch (step) { + case PKCS11_FUNC_STEP_ONESHOT: + case PKCS11_FUNC_STEP_UPDATE: + case PKCS11_FUNC_STEP_FINAL: + break; + default: + return PKCS11_CKR_GENERAL_ERROR; + } + + /* TEE attribute(s) required by the operation */ + switch (proc->mecha_type) { + case PKCS11_CKM_RSA_PKCS_PSS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + tee_attrs = TEE_Malloc(sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!tee_attrs) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + rsa_pss_ctx = proc->extra_ctx; + + TEE_InitValueAttribute(&tee_attrs[tee_attrs_count], + TEE_ATTR_RSA_PSS_SALT_LENGTH, + rsa_pss_ctx->salt_len, 0); + tee_attrs_count++; + break; + case PKCS11_CKM_EDDSA: + eddsa_ctx = proc->extra_ctx; + + tee_attrs = TEE_Malloc(2 * sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!tee_attrs) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + if (eddsa_ctx->flag) { + TEE_InitValueAttribute(&tee_attrs[tee_attrs_count], + TEE_ATTR_EDDSA_PREHASH, 0, 0); + tee_attrs_count++; + } + + if (eddsa_ctx->ctx_len > 0) { + TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], + TEE_ATTR_EDDSA_CTX, eddsa_ctx->ctx, + eddsa_ctx->ctx_len); + tee_attrs_count++; + } + break; + case PKCS11_CKM_RSA_PKCS_OAEP: + rsa_oaep_ctx = proc->extra_ctx; + + if (!rsa_oaep_ctx->source_data_len) + break; + + tee_attrs = TEE_Malloc(sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!tee_attrs) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], + TEE_ATTR_RSA_OAEP_LABEL, + rsa_oaep_ctx->source_data, + rsa_oaep_ctx->source_data_len); + tee_attrs_count++; + break; + case PKCS11_CKM_RSA_AES_KEY_WRAP: + rsa_aes_ctx = proc->extra_ctx; + + if (!rsa_aes_ctx->source_data_len) + break; + + tee_attrs = TEE_Malloc(sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!tee_attrs) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], + TEE_ATTR_RSA_OAEP_LABEL, + rsa_aes_ctx->source_data, + rsa_aes_ctx->source_data_len); + tee_attrs_count++; + break; + default: + break; + } + + /* + * Handle multi stage update step for mechas needing hash + * calculation + */ + if (step == PKCS11_FUNC_STEP_UPDATE) { + switch (proc->mecha_type) { + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + case PKCS11_CKM_MD5_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS: + case PKCS11_CKM_SHA224_RSA_PKCS: + case PKCS11_CKM_SHA256_RSA_PKCS: + case PKCS11_CKM_SHA384_RSA_PKCS: + case PKCS11_CKM_SHA512_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL); + + TEE_DigestUpdate(proc->tee_hash_op_handle, in_buf, + in_size); + rc = PKCS11_CKR_OK; + break; + default: + /* + * Other mechanism do not expect multi stage + * operation + */ + rc = PKCS11_CKR_GENERAL_ERROR; + break; + } + + goto out; + } + + /* + * Handle multi stage one shot and final steps for mechas needing hash + * calculation + */ + switch (proc->mecha_type) { + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + case PKCS11_CKM_MD5_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS: + case PKCS11_CKM_SHA224_RSA_PKCS: + case PKCS11_CKM_SHA256_RSA_PKCS: + case PKCS11_CKM_SHA384_RSA_PKCS: + case PKCS11_CKM_SHA512_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL); + + hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo); + hash_buf = TEE_Malloc(hash_size, 0); + if (!hash_buf) + return PKCS11_CKR_DEVICE_MEMORY; + + res = TEE_DigestDoFinal(proc->tee_hash_op_handle, + in_buf, in_size, hash_buf, + &hash_size); + + rc = tee2pkcs_error(res); + if (rc != PKCS11_CKR_OK) + goto out; + + break; + default: + break; + } + + /* + * Finalize either provided hash or calculated hash with signing + * operation + */ + + /* First determine amount of bytes for signing operation */ + switch (proc->mecha_type) { + case PKCS11_CKM_ECDSA: + sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle); + if (!in_size || !sz) { + rc = PKCS11_CKR_FUNCTION_FAILED; + goto out; + } + + /* + * Note 3) Input the entire raw digest. Internally, this will + * be truncated to the appropriate number of bits. + */ + if (in_size > sz) + in_size = sz; + + if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) { + rc = PKCS11_CKR_SIGNATURE_LEN_RANGE; + goto out; + } + break; + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + /* Get key size in bytes */ + sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle); + if (!sz) { + rc = PKCS11_CKR_FUNCTION_FAILED; + goto out; + } + + if (function == PKCS11_FUNCTION_VERIFY && + in2_size != 2 * sz) { + rc = PKCS11_CKR_SIGNATURE_LEN_RANGE; + goto out; + } + break; + case PKCS11_CKM_RSA_PKCS: + case PKCS11_CKM_MD5_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS: + case PKCS11_CKM_SHA224_RSA_PKCS: + case PKCS11_CKM_SHA256_RSA_PKCS: + case PKCS11_CKM_SHA384_RSA_PKCS: + case PKCS11_CKM_SHA512_RSA_PKCS: + case PKCS11_CKM_RSA_PKCS_PSS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + /* Get key size in bytes */ + sz = rsa_get_input_max_byte_size(proc->tee_op_handle); + if (!sz) { + rc = PKCS11_CKR_FUNCTION_FAILED; + goto out; + } + + if (function == PKCS11_FUNCTION_VERIFY && in2_size != sz) { + rc = PKCS11_CKR_SIGNATURE_LEN_RANGE; + goto out; + } + break; + default: + break; + } + + /* Next perform actual signing operation */ + switch (proc->mecha_type) { + case PKCS11_CKM_ECDSA: + case PKCS11_CKM_EDDSA: + case PKCS11_CKM_RSA_PKCS: + case PKCS11_CKM_RSA_PKCS_OAEP: + case PKCS11_CKM_RSA_PKCS_PSS: + /* For operations using provided input data */ + switch (function) { + case PKCS11_FUNCTION_ENCRYPT: + res = TEE_AsymmetricEncrypt(proc->tee_op_handle, + tee_attrs, tee_attrs_count, + in_buf, in_size, + out_buf, &out_size); + output_data = true; + rc = tee2pkcs_error(res); + if (rc == PKCS11_CKR_ARGUMENTS_BAD) + rc = PKCS11_CKR_DATA_LEN_RANGE; + break; + + case PKCS11_FUNCTION_DECRYPT: + res = TEE_AsymmetricDecrypt(proc->tee_op_handle, + tee_attrs, tee_attrs_count, + in_buf, in_size, + out_buf, &out_size); + output_data = true; + rc = tee2pkcs_error(res); + if (rc == PKCS11_CKR_ARGUMENTS_BAD) + rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; + break; + + case PKCS11_FUNCTION_SIGN: + res = TEE_AsymmetricSignDigest(proc->tee_op_handle, + tee_attrs, + tee_attrs_count, + in_buf, in_size, + out_buf, &out_size); + output_data = true; + rc = tee2pkcs_error(res); + break; + + case PKCS11_FUNCTION_VERIFY: + res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle, + tee_attrs, + tee_attrs_count, + in_buf, in_size, + in2_buf, in2_size); + rc = tee2pkcs_error(res); + break; + + default: + TEE_Panic(function); + break; + } + break; + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + case PKCS11_CKM_MD5_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS: + case PKCS11_CKM_SHA224_RSA_PKCS: + case PKCS11_CKM_SHA256_RSA_PKCS: + case PKCS11_CKM_SHA384_RSA_PKCS: + case PKCS11_CKM_SHA512_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + /* For operations having hash operation use calculated hash */ + switch (function) { + case PKCS11_FUNCTION_SIGN: + res = TEE_AsymmetricSignDigest(proc->tee_op_handle, + tee_attrs, + tee_attrs_count, + hash_buf, hash_size, + out_buf, &out_size); + output_data = true; + rc = tee2pkcs_error(res); + break; + + case PKCS11_FUNCTION_VERIFY: + res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle, + tee_attrs, + tee_attrs_count, + hash_buf, hash_size, + in2_buf, in2_size); + rc = tee2pkcs_error(res); + break; + + default: + TEE_Panic(function); + break; + } + break; + default: + TEE_Panic(proc->mecha_type); + break; + } + +out: + if (output_data && + (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) { + switch (TEE_PARAM_TYPE_GET(ptypes, 2)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + params[2].memref.size = out_size; + break; + default: + rc = PKCS11_CKR_GENERAL_ERROR; + break; + } + } + + TEE_Free(hash_buf); + TEE_Free(tee_attrs); + + return rc; +} + +enum pkcs11_rc do_asymm_derivation(struct pkcs11_session *session, + struct pkcs11_attribute_head *proc_params, + struct obj_attrs **head) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_ObjectHandle out_handle = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute tee_attrs[2] = { }; + size_t tee_attrs_count = 0; + uint32_t key_byte_size = 0; + uint32_t key_bit_size = 0; + void *a_ptr = NULL; + size_t a_size = 0; + + /* Remove default attribute set at template sanitization */ + if (remove_empty_attribute(head, PKCS11_CKA_VALUE)) + return PKCS11_CKR_FUNCTION_FAILED; + + rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_bit_size); + if (rc) + return rc; + + key_bit_size *= 8; + key_byte_size = (key_bit_size + 7) / 8; + + res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET, + key_byte_size * 8, &out_handle); + if (res) { + DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res); + return tee2pkcs_error(res); + } + + switch (proc_params->id) { + case PKCS11_CKM_ECDH1_DERIVE: + rc = pkcs2tee_param_ecdh(proc_params, &a_ptr, &a_size); + if (rc) + goto out; + + TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], + TEE_ATTR_ECC_PUBLIC_VALUE_X, + a_ptr, a_size / 2); + tee_attrs_count++; + TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], + TEE_ATTR_ECC_PUBLIC_VALUE_Y, + (char *)a_ptr + a_size / 2, + a_size / 2); + tee_attrs_count++; + break; + default: + TEE_Panic(proc_params->id); + break; + } + + TEE_DeriveKey(session->processing->tee_op_handle, &tee_attrs[0], + tee_attrs_count, out_handle); + + rc = alloc_get_tee_attribute_data(out_handle, TEE_ATTR_SECRET_VALUE, + &a_ptr, &a_size); + if (rc) + goto out; + + if (a_size * 8 < key_bit_size) + rc = PKCS11_CKR_KEY_SIZE_RANGE; + else + rc = add_attribute(head, PKCS11_CKA_VALUE, a_ptr, + key_byte_size); + TEE_Free(a_ptr); +out: + release_active_processing(session); + TEE_FreeTransientObject(out_handle); + + return rc; +} + +static enum pkcs11_rc wrap_rsa_aes_key(struct active_processing *proc, + void *data, uint32_t data_sz, + void *out_buf, uint32_t *out_sz) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + TEE_Result res = TEE_ERROR_GENERIC; + int mbedtls_rc = 0; + struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx; + mbedtls_nist_kw_context kw_ctx = { }; + uint8_t aes_key_value[32] = { }; + uint32_t aes_key_size = ctx->aes_key_bits / 8; + size_t aes_wrapped_size = *out_sz; + uint32_t expected_size = 0; + size_t target_key_size = 0; + const size_t kw_semiblock_len = 8; + + if (ctx->aes_key_bits != 128 && + ctx->aes_key_bits != 192 && + ctx->aes_key_bits != 256) + return PKCS11_CKR_ARGUMENTS_BAD; + + mbedtls_nist_kw_init(&kw_ctx); + TEE_GenerateRandom(aes_key_value, aes_key_size); + res = TEE_AsymmetricEncrypt(proc->tee_op_handle, + NULL, 0, + aes_key_value, aes_key_size, + out_buf, &aes_wrapped_size); + expected_size = aes_wrapped_size + data_sz + kw_semiblock_len; + if (res) { + if (res == TEE_ERROR_SHORT_BUFFER) + *out_sz = expected_size; + + rc = tee2pkcs_error(res); + goto out; + } + + if (*out_sz < expected_size) { + rc = PKCS11_CKR_BUFFER_TOO_SMALL; + *out_sz = expected_size; + goto out; + } + + mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES, + aes_key_value, ctx->aes_key_bits, + true); + if (mbedtls_rc) { + if (mbedtls_rc == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) + rc = PKCS11_CKR_KEY_SIZE_RANGE; + else + rc = PKCS11_CKR_FUNCTION_FAILED; + + goto out; + } + + mbedtls_rc = mbedtls_nist_kw_wrap(&kw_ctx, MBEDTLS_KW_MODE_KWP, + data, data_sz, + (uint8_t *)out_buf + aes_wrapped_size, + &target_key_size, + *out_sz - aes_wrapped_size); + if (mbedtls_rc) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + assert(*out_sz >= target_key_size + aes_wrapped_size); + *out_sz = target_key_size + aes_wrapped_size; + +out: + mbedtls_nist_kw_free(&kw_ctx); + TEE_MemFill(aes_key_value, 0, aes_key_size); + return rc; +} + +static enum pkcs11_rc unwrap_rsa_aes_key(struct active_processing *proc, + void *data, uint32_t data_sz, + void **out_buf, uint32_t *out_sz) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + int mbedtls_rc = 0; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationInfo info = { }; + struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx; + mbedtls_nist_kw_context kw_ctx = { }; + uint8_t aes_key_value[32] = { }; + size_t aes_key_size = ctx->aes_key_bits / 8; + uint32_t wrapped_key_size = 0; + uint32_t rsa_key_size = 0; + size_t target_key_size = 0; + + if (ctx->aes_key_bits != 128 && + ctx->aes_key_bits != 192 && + ctx->aes_key_bits != 256) + return PKCS11_CKR_ARGUMENTS_BAD; + + TEE_GetOperationInfo(proc->tee_op_handle, &info); + rsa_key_size = info.keySize / 8; + wrapped_key_size = data_sz - rsa_key_size; + target_key_size = wrapped_key_size - 8; + + *out_buf = TEE_Malloc(target_key_size, TEE_MALLOC_FILL_ZERO); + if (!*out_buf) + return PKCS11_CKR_DEVICE_MEMORY; + + mbedtls_nist_kw_init(&kw_ctx); + res = TEE_AsymmetricDecrypt(proc->tee_op_handle, + NULL, 0, + data, rsa_key_size, + aes_key_value, &aes_key_size); + if (res) { + rc = tee2pkcs_error(res); + goto out; + } + + mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES, + aes_key_value, ctx->aes_key_bits, + false); + if (mbedtls_rc) { + rc = PKCS11_CKR_WRAPPED_KEY_INVALID; + goto out; + } + + mbedtls_rc = mbedtls_nist_kw_unwrap(&kw_ctx, MBEDTLS_KW_MODE_KWP, + (uint8_t *)data + rsa_key_size, + wrapped_key_size, *out_buf, + &target_key_size, target_key_size); + if (mbedtls_rc) { + rc = PKCS11_CKR_WRAPPED_KEY_INVALID; + goto out; + } + + *out_sz = target_key_size; +out: + TEE_MemFill(aes_key_value, 0, aes_key_size); + mbedtls_nist_kw_free(&kw_ctx); + return rc; +} + +enum pkcs11_rc wrap_data_by_asymm_enc(struct pkcs11_session *session, + void *data, uint32_t data_sz, + void *out_buf, uint32_t *out_sz) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct active_processing *proc = session->processing; + + switch (proc->mecha_type) { + case PKCS11_CKM_RSA_AES_KEY_WRAP: + rc = wrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz); + break; + default: + return PKCS11_CKR_MECHANISM_INVALID; + } + + return rc; +} + +enum pkcs11_rc unwrap_key_by_asymm(struct pkcs11_session *session, + void *data, uint32_t data_sz, + void **out_buf, uint32_t *out_sz) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct active_processing *proc = session->processing; + + switch (proc->mecha_type) { + case PKCS11_CKM_RSA_AES_KEY_WRAP: + rc = unwrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz); + break; + default: + return PKCS11_CKR_MECHANISM_INVALID; + } + + return rc; +} diff --git a/optee/optee_os/ta/pkcs11/src/processing_digest.c b/optee/optee_os/ta/pkcs11/src/processing_digest.c new file mode 100644 index 0000000..c82f489 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_digest.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Vaisala Oyj + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "object.h" +#include "pkcs11_attributes.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.h" +#include "serializer.h" + +bool processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id) +{ + switch (mecha_id) { + case PKCS11_CKM_MD5: + case PKCS11_CKM_SHA_1: + case PKCS11_CKM_SHA224: + case PKCS11_CKM_SHA256: + case PKCS11_CKM_SHA384: + case PKCS11_CKM_SHA512: + return true; + default: + return false; + } +} + +static enum pkcs11_rc +pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params) +{ + static const struct { + enum pkcs11_mechanism_id mech_id; + uint32_t tee_id; + } pkcs2tee_algo[] = { + { PKCS11_CKM_MD5, TEE_ALG_MD5 }, + { PKCS11_CKM_SHA_1, TEE_ALG_SHA1 }, + { PKCS11_CKM_SHA224, TEE_ALG_SHA224 }, + { PKCS11_CKM_SHA256, TEE_ALG_SHA256 }, + { PKCS11_CKM_SHA384, TEE_ALG_SHA384 }, + { PKCS11_CKM_SHA512, TEE_ALG_SHA512 }, + }; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) { + if (proc_params->id == pkcs2tee_algo[n].mech_id) { + *tee_id = pkcs2tee_algo[n].tee_id; + return PKCS11_CKR_OK; + } + } + + return PKCS11_RV_NOT_IMPLEMENTED; +} + +static enum pkcs11_rc +allocate_tee_operation(struct pkcs11_session *session, + struct pkcs11_attribute_head *params) +{ + uint32_t algo = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + assert(session->processing->tee_op_handle == TEE_HANDLE_NULL); + + if (pkcs2tee_algorithm(&algo, params)) + return PKCS11_CKR_FUNCTION_FAILED; + + res = TEE_AllocateOperation(&session->processing->tee_op_handle, + algo, TEE_MODE_DIGEST, 0); + if (res) + EMSG("TEE_AllocateOp. failed %#"PRIx32, algo); + + if (res == TEE_ERROR_NOT_SUPPORTED) + return PKCS11_CKR_MECHANISM_INVALID; + + return tee2pkcs_error(res); +} + +enum pkcs11_rc init_digest_operation(struct pkcs11_session *session, + struct pkcs11_attribute_head *proc_params) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + assert(processing_is_tee_digest(proc_params->id)); + + rc = allocate_tee_operation(session, proc_params); + if (!rc) + session->processing->mecha_type = proc_params->id; + + return rc; +} + +/* + * step_digest_operation - processing digest operation step + * + * @session - current session + * @step - step ID in the processing (oneshot, update, final) + * @obj - PKCS#11 object for key based operations + * @ptype - invocation parameter types + * @params - invocation parameter references + */ +enum pkcs11_rc step_digest_operation(struct pkcs11_session *session, + enum processing_step step, + struct pkcs11_object *obj, + uint32_t ptypes, TEE_Param *params) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + void *in_buf = NULL; + size_t in_size = 0; + void *out_buf = NULL; + size_t out_size = 0; + void *secret_value = NULL; + uint32_t secret_value_size = 0; + enum pkcs11_key_type key_type = PKCS11_CKK_UNDEFINED_ID; + struct active_processing *proc = session->processing; + + if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) { + in_buf = params[1].memref.buffer; + in_size = params[1].memref.size; + if (in_size && !in_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + } + if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) { + out_buf = params[2].memref.buffer; + out_size = params[2].memref.size; + if (out_size && !out_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + } + if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) + return PKCS11_CKR_ARGUMENTS_BAD; + + switch (step) { + case PKCS11_FUNC_STEP_ONESHOT: + case PKCS11_FUNC_STEP_UPDATE: + case PKCS11_FUNC_STEP_UPDATE_KEY: + case PKCS11_FUNC_STEP_FINAL: + break; + default: + TEE_Panic(step); + break; + } + + assert(proc->tee_op_handle != TEE_HANDLE_NULL); + + assert(processing_is_tee_digest(proc->mecha_type)); + + /* + * Feed active operation with data + */ + + switch (step) { + case PKCS11_FUNC_STEP_UPDATE_KEY: + assert(obj); + + if (!IS_ENABLED(CFG_PKCS11_TA_ALLOW_DIGEST_KEY)) + return PKCS11_CKR_KEY_INDIGESTIBLE; + + if (get_class(obj->attributes) != PKCS11_CKO_SECRET_KEY) + return PKCS11_CKR_KEY_INDIGESTIBLE; + + key_type = get_key_type(obj->attributes); + + if (key_type != PKCS11_CKK_GENERIC_SECRET && + key_type != PKCS11_CKK_AES) + return PKCS11_CKR_KEY_INDIGESTIBLE; + + rc = get_attribute_ptr(obj->attributes, PKCS11_CKA_VALUE, + &secret_value, &secret_value_size); + assert(!rc && secret_value && secret_value_size); + + TEE_DigestUpdate(proc->tee_op_handle, secret_value, + secret_value_size); + return PKCS11_CKR_OK; + + case PKCS11_FUNC_STEP_UPDATE: + if (!in_buf || !in_size) + return PKCS11_CKR_OK; + + TEE_DigestUpdate(proc->tee_op_handle, in_buf, in_size); + return PKCS11_CKR_OK; + + case PKCS11_FUNC_STEP_ONESHOT: + if (!out_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + + goto do_final; + + case PKCS11_FUNC_STEP_FINAL: + if (in_buf || !out_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + + goto do_final; + + default: + TEE_Panic(step); + break; + } + +do_final: + res = TEE_DigestDoFinal(proc->tee_op_handle, + in_buf, in_size, out_buf, + &out_size); + rc = tee2pkcs_error(res); + + if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL) + params[2].memref.size = out_size; + + return rc; +} diff --git a/optee/optee_os/ta/pkcs11/src/processing_ec.c b/optee/optee_os/ta/pkcs11/src/processing_ec.c new file mode 100644 index 0000000..a90966a --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_ec.c @@ -0,0 +1,948 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "object.h" +#include "pkcs11_token.h" +#include "processing.h" + +/* + * DER encoded EC parameters generated with script: + * ta/pkcs11/scripts/dump_ec_curve_params.sh + */ + +static const uint8_t prime192v1_name_der[] = { + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x01, +}; + +static const uint8_t secp224r1_name_der[] = { + 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x21, +}; + +static const uint8_t prime256v1_name_der[] = { + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x07, +}; + +static const uint8_t secp384r1_name_der[] = { + 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, +}; + +static const uint8_t secp521r1_name_der[] = { + 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, +}; + +static const uint8_t prime192v1_oid_der[] = { + 0x30, 0x81, 0xc7, 0x02, 0x01, 0x01, 0x30, 0x24, + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, + 0x01, 0x02, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x30, 0x4b, 0x04, 0x18, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x04, 0x18, 0x64, 0x21, 0x05, 0x19, 0xe5, 0x9c, + 0x80, 0xe7, 0x0f, 0xa7, 0xe9, 0xab, 0x72, 0x24, + 0x30, 0x49, 0xfe, 0xb8, 0xde, 0xec, 0xc1, 0x46, + 0xb9, 0xb1, 0x03, 0x15, 0x00, 0x30, 0x45, 0xae, + 0x6f, 0xc8, 0x42, 0x2f, 0x64, 0xed, 0x57, 0x95, + 0x28, 0xd3, 0x81, 0x20, 0xea, 0xe1, 0x21, 0x96, + 0xd5, 0x04, 0x31, 0x04, 0x18, 0x8d, 0xa8, 0x0e, + 0xb0, 0x30, 0x90, 0xf6, 0x7c, 0xbf, 0x20, 0xeb, + 0x43, 0xa1, 0x88, 0x00, 0xf4, 0xff, 0x0a, 0xfd, + 0x82, 0xff, 0x10, 0x12, 0x07, 0x19, 0x2b, 0x95, + 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, + 0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, + 0x1e, 0x79, 0x48, 0x11, 0x02, 0x19, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x99, 0xde, 0xf8, 0x36, 0x14, + 0x6b, 0xc9, 0xb1, 0xb4, 0xd2, 0x28, 0x31, 0x02, + 0x01, 0x01, +}; + +static const uint8_t secp224r1_oid_der[] = { + 0x30, 0x81, 0xdf, 0x02, 0x01, 0x01, 0x30, 0x28, + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, + 0x01, 0x02, 0x1d, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x30, 0x53, 0x04, 0x1c, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x04, 0x1c, 0xb4, 0x05, 0x0a, 0x85, 0x0c, 0x04, + 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, + 0xb0, 0xb7, 0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, + 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4, 0x03, 0x15, + 0x00, 0xbd, 0x71, 0x34, 0x47, 0x99, 0xd5, 0xc7, + 0xfc, 0xdc, 0x45, 0xb5, 0x9f, 0xa3, 0xb9, 0xab, + 0x8f, 0x6a, 0x94, 0x8b, 0xc5, 0x04, 0x39, 0x04, + 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, + 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, + 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, + 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, + 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, + 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, + 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34, + 0x02, 0x1d, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x16, 0xa2, 0xe0, 0xb8, 0xf0, 0x3e, 0x13, + 0xdd, 0x29, 0x45, 0x5c, 0x5c, 0x2a, 0x3d, 0x02, + 0x01, 0x01, +}; + +static const uint8_t prime256v1_oid_der[] = { + 0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30, 0x2c, + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, + 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x30, 0x5b, 0x04, 0x20, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, + 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, + 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, + 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, + 0x60, 0x4b, 0x03, 0x15, 0x00, 0xc4, 0x9d, 0x36, + 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, + 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, + 0x90, 0x04, 0x41, 0x04, 0x6b, 0x17, 0xd1, 0xf2, + 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, + 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, + 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, + 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, + 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, + 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, + 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, + 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, + 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, + 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, 0x02, + 0x01, 0x01, +}; + +static const uint8_t secp384r1_oid_der[] = { + 0x30, 0x82, 0x01, 0x57, 0x02, 0x01, 0x01, 0x30, + 0x3c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x01, 0x01, 0x02, 0x31, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0x30, 0x7b, 0x04, + 0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xfc, 0x04, 0x30, 0xb3, 0x31, 0x2f, 0xa7, 0xe2, + 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b, 0xe3, + 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, + 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8f, 0x50, + 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d, 0x8a, + 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, + 0xec, 0x2a, 0xef, 0x03, 0x15, 0x00, 0xa3, 0x35, + 0x92, 0x6a, 0xa3, 0x19, 0xa2, 0x7a, 0x1d, 0x00, + 0x89, 0x6a, 0x67, 0x73, 0xa4, 0x82, 0x7a, 0xcd, + 0xac, 0x73, 0x04, 0x61, 0x04, 0xaa, 0x87, 0xca, + 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, + 0x1e, 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, + 0x62, 0x8b, 0xa7, 0x9b, 0x98, 0x59, 0xf7, 0x41, + 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, + 0x5d, 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, + 0x38, 0x72, 0x76, 0x0a, 0xb7, 0x36, 0x17, 0xde, + 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, + 0xbf, 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, + 0xbd, 0x28, 0x9a, 0x14, 0x7c, 0xe9, 0xda, 0x31, + 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, + 0xce, 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, + 0x7c, 0x90, 0xea, 0x0e, 0x5f, 0x02, 0x31, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, + 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, + 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73, + 0x02, 0x01, 0x01, +}; + +static const uint8_t secp521r1_oid_der[] = { + 0x30, 0x82, 0x01, 0xc3, 0x02, 0x01, 0x01, 0x30, + 0x4d, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x01, 0x01, 0x02, 0x42, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x81, + 0x9f, 0x04, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x42, 0x00, + 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a, + 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, + 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, 0x15, + 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09, + 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, + 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, 0xbf, + 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34, + 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, + 0x00, 0x03, 0x15, 0x00, 0xd0, 0x9e, 0x88, 0x00, + 0x29, 0x1c, 0xb8, 0x53, 0x96, 0xcc, 0x67, 0x17, + 0x39, 0x32, 0x84, 0xaa, 0xa0, 0xda, 0x64, 0xba, + 0x04, 0x81, 0x85, 0x04, 0x00, 0xc6, 0x85, 0x8e, + 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e, + 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, + 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 0xf8, 0x28, + 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b, + 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, + 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde, 0x33, 0x48, + 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e, + 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, 0x01, 0x18, + 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, + 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, + 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, + 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, + 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, + 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, + 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, + 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50, + 0x02, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, + 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48, + 0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, + 0x89, 0x9c, 0x47, 0xae, 0xbb, 0x6f, 0xb7, 0x1e, + 0x91, 0x38, 0x64, 0x09, 0x02, 0x01, 0x01, +}; + +/* + * Edwards curves may be specified in two flavours: + * - as a PrintableString 'edwards25519' or 'edwards448' + * - as an OID, DER encoded ASN.1 Object + */ + +static const uint8_t ed25519_name_der[] = { + 0x13, 0x0c, 'e', 'd', 'w', 'a', 'r', 'd', 's', + '2', '5', '5', '1', '9', +}; + +static const uint8_t ed25519_oid_der[] = { + 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, + 0x47, 0x0f, 0x01, +}; + +struct supported_ecc_curve { + const uint8_t *oid_der; + size_t oid_size; + const uint8_t *name_der; + size_t name_size; + size_t key_size; + uint32_t tee_id; + const char *label; + size_t label_size; +}; + +#define ECC_CURVE(_tee_id, _key_size, _label) \ + { \ + .tee_id = (_tee_id), \ + .key_size = (_key_size), \ + .oid_der = _label ## _oid_der, \ + .oid_size = sizeof(_label ## _oid_der), \ + .name_der = _label ## _name_der, \ + .name_size = sizeof(_label ## _name_der), \ + .label = #_label, \ + .label_size = sizeof(#_label) - 1, \ + } + +static const struct supported_ecc_curve ec_curve_param[] = { + ECC_CURVE(TEE_ECC_CURVE_NIST_P192, 192, prime192v1), + ECC_CURVE(TEE_ECC_CURVE_NIST_P224, 224, secp224r1), + ECC_CURVE(TEE_ECC_CURVE_NIST_P256, 256, prime256v1), + ECC_CURVE(TEE_ECC_CURVE_NIST_P384, 384, secp384r1), + ECC_CURVE(TEE_ECC_CURVE_NIST_P521, 521, secp521r1), + ECC_CURVE(TEE_ECC_CURVE_25519, 256, ed25519), +}; + +static const struct supported_ecc_curve *get_curve(void *attr, size_t size) +{ + size_t idx = 0; + + /* Weak: not a real DER parser: try by params then by named curve */ + for (idx = 0; idx < ARRAY_SIZE(ec_curve_param); idx++) { + const struct supported_ecc_curve *curve = ec_curve_param + idx; + + if (size == curve->oid_size && + !TEE_MemCompare(attr, curve->oid_der, curve->oid_size)) + return curve; + + if (size == curve->name_size && + !TEE_MemCompare(attr, curve->name_der, curve->name_size)) + return curve; + } + + return NULL; +} + +size_t ec_params2tee_keysize(void *ec_params, size_t size) +{ + const struct supported_ecc_curve *curve = get_curve(ec_params, size); + + if (!curve) + return 0; + + return curve->key_size; +} + +/* + * This function intentionally panics if the curve is not found. + * Use ec_params2tee_keysize() to check the curve is supported by + * the internal core API. + */ +uint32_t ec_params2tee_curve(void *ec_params, size_t size) +{ + const struct supported_ecc_curve *curve = get_curve(ec_params, size); + + assert(curve); + + return curve->tee_id; +} + +enum pkcs11_rc load_tee_ec_key_attrs(TEE_Attribute **tee_attrs, + size_t *tee_count, + struct pkcs11_object *obj) +{ + TEE_Attribute *attrs = NULL; + size_t count = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + assert(get_key_type(obj->attributes) == PKCS11_CKK_EC); + + switch (get_class(obj->attributes)) { + case PKCS11_CKO_PUBLIC_KEY: + attrs = TEE_Malloc(3 * sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!attrs) + return PKCS11_CKR_DEVICE_MEMORY; + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_CURVE, + obj, PKCS11_CKA_EC_PARAMS)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ECC_PUBLIC_VALUE_X, + obj, PKCS11_CKA_EC_POINT)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ECC_PUBLIC_VALUE_Y, + obj, PKCS11_CKA_EC_POINT)) + count++; + + if (count == 3) + rc = PKCS11_CKR_OK; + + break; + + case PKCS11_CKO_PRIVATE_KEY: + attrs = TEE_Malloc(4 * sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!attrs) + return PKCS11_CKR_DEVICE_MEMORY; + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_CURVE, + obj, PKCS11_CKA_EC_PARAMS)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ECC_PRIVATE_VALUE, + obj, PKCS11_CKA_VALUE)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ECC_PUBLIC_VALUE_X, + obj, PKCS11_CKA_EC_POINT)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ECC_PUBLIC_VALUE_Y, + obj, PKCS11_CKA_EC_POINT)) + count++; + + if (count == 4) + rc = PKCS11_CKR_OK; + + break; + + default: + assert(0); + break; + } + + if (rc == PKCS11_CKR_OK) { + *tee_attrs = attrs; + *tee_count = count; + } else { + TEE_Free(attrs); + } + + return rc; +} + +enum pkcs11_rc pkcs2tee_algo_ecdsa(uint32_t *tee_id, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj) +{ + switch (proc_params->id) { + case PKCS11_CKM_ECDSA: + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + break; + default: + return PKCS11_CKR_GENERAL_ERROR; + } + + /* + * TODO: Fixing this in a way to support also other EC curves would + * require OP-TEE to be updated for newer version of GlobalPlatform API + */ + switch (get_object_key_bit_size(obj)) { + case 192: + *tee_id = TEE_ALG_ECDSA_P192; + break; + case 224: + *tee_id = TEE_ALG_ECDSA_P224; + break; + case 256: + *tee_id = TEE_ALG_ECDSA_P256; + break; + case 384: + *tee_id = TEE_ALG_ECDSA_P384; + break; + case 521: + *tee_id = TEE_ALG_ECDSA_P521; + break; + default: + TEE_Panic(0); + break; + } + + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc tee2pkcs_ec_attributes(struct obj_attrs **pub_head, + struct obj_attrs **priv_head, + TEE_ObjectHandle tee_obj, + size_t tee_size) +{ + void *x_ptr = NULL; + void *y_ptr = NULL; + uint8_t *ecpoint = NULL; + size_t x_size = 0; + size_t y_size = 0; + size_t psize = 0; + size_t qsize = 0; + size_t dersize = 0; + size_t poffset = 0; + size_t hsize = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_VALUE, + tee_obj, TEE_ATTR_ECC_PRIVATE_VALUE); + if (rc) + goto out; + + rc = alloc_get_tee_attribute_data(tee_obj, TEE_ATTR_ECC_PUBLIC_VALUE_X, + &x_ptr, &x_size); + if (rc) + goto out; + + rc = alloc_get_tee_attribute_data(tee_obj, TEE_ATTR_ECC_PUBLIC_VALUE_Y, + &y_ptr, &y_size); + if (rc) + goto x_cleanup; + + psize = (tee_size + 7) / 8; + if (x_size > psize || y_size > psize) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto y_cleanup; + } + + qsize = 1 + 2 * psize; + if (qsize < 0x80) { + /* DER short definitive form up to 127 bytes */ + dersize = qsize + 2; + hsize = 2 /* der */ + 1 /* point compression */; + } else if (qsize < 0x100) { + /* DER long definitive form up to 255 bytes */ + dersize = qsize + 3; + hsize = 3 /* der */ + 1 /* point compression */; + } else { + EMSG("Too long DER value"); + rc = PKCS11_CKR_MECHANISM_PARAM_INVALID; + goto y_cleanup; + } + + ecpoint = TEE_Malloc(dersize, TEE_MALLOC_FILL_ZERO); + if (!ecpoint) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto y_cleanup; + } + + if (qsize < 0x80) { + /* DER encoding */ + ecpoint[0] = 0x04; + ecpoint[1] = qsize & 0x7f; + + /* Only UNCOMPRESSED ECPOINT is currently supported */ + ecpoint[2] = 0x04; + } else if (qsize < 0x100) { + /* DER encoding */ + ecpoint[0] = 0x04; + ecpoint[1] = 0x80 | 0x01; /* long form, one size octet */ + ecpoint[2] = qsize & 0xFF; + + /* Only UNCOMPRESSED ECPOINT is currently supported */ + ecpoint[3] = 0x04; + } + + poffset = 0; + if (x_size < psize) + poffset = psize - x_size; + TEE_MemMove(ecpoint + hsize + poffset, x_ptr, x_size); + + poffset = 0; + if (y_size < psize) + poffset = psize - y_size; + TEE_MemMove(ecpoint + hsize + psize + poffset, y_ptr, y_size); + + /* + * Add EC_POINT on both private and public key objects as + * TEE_PopulateTransientObject requires public x/y values + * for TEE_TYPE_ECDSA_KEYPAIR. + */ + rc = add_attribute(priv_head, PKCS11_CKA_EC_POINT, ecpoint, dersize); + if (rc) + goto ecpoint_cleanup; + + rc = add_attribute(pub_head, PKCS11_CKA_EC_POINT, ecpoint, dersize); + +ecpoint_cleanup: + TEE_Free(ecpoint); +y_cleanup: + TEE_Free(y_ptr); +x_cleanup: + TEE_Free(x_ptr); +out: + return rc; +} + +enum pkcs11_rc generate_ec_keys(struct pkcs11_attribute_head *proc_params, + struct obj_attrs **pub_head, + struct obj_attrs **priv_head) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *a_ptr = NULL; + uint32_t a_size = 0; + uint32_t tee_size = 0; + uint32_t tee_curve = 0; + TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL; + TEE_Attribute tee_key_attr[1] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + + if (!proc_params || !*pub_head || !*priv_head) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + + if (remove_empty_attribute(pub_head, PKCS11_CKA_EC_POINT) || + remove_empty_attribute(priv_head, PKCS11_CKA_VALUE) || + remove_empty_attribute(priv_head, PKCS11_CKA_EC_PARAMS)) { + EMSG("Unexpected attribute(s) found"); + trace_attributes("public-key", *pub_head); + trace_attributes("private-key", *priv_head); + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + if (get_attribute_ptr(*pub_head, PKCS11_CKA_EC_PARAMS, + &a_ptr, &a_size) || !a_ptr) { + EMSG("No EC_PARAMS attribute found in public key"); + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + } + + tee_size = ec_params2tee_keysize(a_ptr, a_size); + if (!tee_size) + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + + tee_curve = ec_params2tee_curve(a_ptr, a_size); + + TEE_InitValueAttribute(tee_key_attr, TEE_ATTR_ECC_CURVE, tee_curve, 0); + + /* Create an ECDSA TEE key: will match PKCS11 ECDSA and ECDH */ + res = TEE_AllocateTransientObject(TEE_TYPE_ECDSA_KEYPAIR, tee_size, + &tee_obj); + if (res) { + EMSG("Transient alloc failed with %#"PRIx32, res); + return tee2pkcs_error(res); + } + + res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE); + if (res) { + rc = tee2pkcs_error(res); + goto out; + } + + res = TEE_GenerateKey(tee_obj, tee_size, tee_key_attr, 1); + if (res) { + rc = tee2pkcs_error(res); + goto out; + } + + /* Private key needs the same EC_PARAMS as used by the public key */ + rc = add_attribute(priv_head, PKCS11_CKA_EC_PARAMS, a_ptr, a_size); + if (rc) + goto out; + + rc = tee2pkcs_ec_attributes(pub_head, priv_head, tee_obj, tee_size); + +out: + if (tee_obj != TEE_HANDLE_NULL) + TEE_CloseObject(tee_obj); + + return rc; +} + +enum pkcs11_rc load_tee_eddsa_key_attrs(TEE_Attribute **tee_attrs, + size_t *tee_count, + struct pkcs11_object *obj) +{ + TEE_Attribute *attrs = NULL; + size_t count = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + + assert(get_key_type(obj->attributes) == PKCS11_CKK_EC_EDWARDS); + + switch (get_class(obj->attributes)) { + case PKCS11_CKO_PUBLIC_KEY: + attrs = TEE_Malloc(sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!attrs) + return PKCS11_CKR_DEVICE_MEMORY; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ED25519_PUBLIC_VALUE, + obj, PKCS11_CKA_EC_POINT)) + count++; + + if (count == 1) + rc = PKCS11_CKR_OK; + + break; + + case PKCS11_CKO_PRIVATE_KEY: + attrs = TEE_Malloc(2 * sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!attrs) + return PKCS11_CKR_DEVICE_MEMORY; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ED25519_PRIVATE_VALUE, + obj, PKCS11_CKA_VALUE)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_ED25519_PUBLIC_VALUE, + obj, PKCS11_CKA_EC_POINT)) + count++; + + if (count == 2) + rc = PKCS11_CKR_OK; + + break; + + default: + assert(0); + break; + } + + if (rc == PKCS11_CKR_OK) { + *tee_attrs = attrs; + *tee_count = count; + } else { + TEE_Free(attrs); + } + + return rc; +} + +enum pkcs11_rc generate_eddsa_keys(struct pkcs11_attribute_head *proc_params, + struct obj_attrs **pub_head, + struct obj_attrs **priv_head) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *a_ptr = NULL; + uint32_t a_size = 0; + uint32_t tee_size = 0; + TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + if (!proc_params || !*pub_head || !*priv_head) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + + if (remove_empty_attribute(pub_head, PKCS11_CKA_EC_POINT) || + remove_empty_attribute(priv_head, PKCS11_CKA_VALUE) || + remove_empty_attribute(priv_head, PKCS11_CKA_EC_POINT) || + remove_empty_attribute(priv_head, PKCS11_CKA_EC_PARAMS)) { + EMSG("Unexpected attribute(s) found"); + trace_attributes("public-key", *pub_head); + trace_attributes("private-key", *priv_head); + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + if (get_attribute_ptr(*pub_head, PKCS11_CKA_EC_PARAMS, + &a_ptr, &a_size) || !a_ptr) { + EMSG("No EC_PARAMS attribute found in public key"); + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + } + + tee_size = ec_params2tee_keysize(a_ptr, a_size); + if (!tee_size) + return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; + + res = TEE_AllocateTransientObject(TEE_TYPE_ED25519_KEYPAIR, tee_size, + &tee_obj); + if (res) { + EMSG("Transient alloc failed with %#"PRIx32, res); + return tee2pkcs_error(res); + } + + res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE); + if (res) { + rc = tee2pkcs_error(res); + goto out; + } + + res = TEE_GenerateKey(tee_obj, tee_size, NULL, 0); + if (res) { + rc = tee2pkcs_error(res); + goto out; + } + + /* Private key needs the same EC_PARAMS as used by the public key */ + rc = add_attribute(priv_head, PKCS11_CKA_EC_PARAMS, a_ptr, a_size); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_VALUE, + tee_obj, TEE_ATTR_ED25519_PRIVATE_VALUE); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_EC_POINT, + tee_obj, TEE_ATTR_ED25519_PUBLIC_VALUE); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(pub_head, PKCS11_CKA_EC_POINT, + tee_obj, TEE_ATTR_ED25519_PUBLIC_VALUE); + +out: + if (tee_obj != TEE_HANDLE_NULL) + TEE_CloseObject(tee_obj); + + return rc; +} + +enum pkcs11_rc +pkcs2tee_proc_params_eddsa(struct active_processing *proc, + struct pkcs11_attribute_head *proc_params) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + uint32_t ctx_len = 0; + uint32_t flag = 0; + void *ctx_data = NULL; + struct serialargs args = { }; + struct eddsa_processing_ctx *ctx = NULL; + + serialargs_init(&args, proc_params->data, proc_params->size); + + rc = serialargs_get_u32(&args, &flag); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &ctx_len); + if (rc) + return rc; + + rc = serialargs_get_ptr(&args, &ctx_data, ctx_len); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + proc->extra_ctx = TEE_Malloc(sizeof(*ctx) + ctx_len, + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!proc->extra_ctx) + return PKCS11_CKR_DEVICE_MEMORY; + + ctx = proc->extra_ctx; + ctx->ctx_len = ctx_len; + ctx->flag = flag; + TEE_MemMove(ctx->ctx, ctx_data, ctx_len); + + return PKCS11_CKR_OK; +} + +size_t ecdsa_get_input_max_byte_size(TEE_OperationHandle op) +{ + TEE_OperationInfo info = { }; + + TEE_GetOperationInfo(op, &info); + + switch (info.algorithm) { + case TEE_ALG_ECDSA_P192: + return 24; + case TEE_ALG_ECDSA_P224: + return 28; + case TEE_ALG_ECDSA_P256: + return 32; + case TEE_ALG_ECDSA_P384: + return 48; + case TEE_ALG_ECDSA_P521: + return 66; + default: + DMSG("Unexpected ECDSA algorithm %#"PRIx32, info.algorithm); + return 0; + } +} + +enum pkcs11_rc pkcs2tee_param_ecdh(struct pkcs11_attribute_head *proc_params, + void **pub_data, size_t *pub_size) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs args = { }; + uint32_t word = 0; + uint8_t byte = 0; + + serialargs_init(&args, proc_params->data, proc_params->size); + + /* Skip KDF */ + rc = serialargs_get_u32(&args, &word); + if (rc) + return rc; + + /* Shared data size, shall be 0 */ + rc = serialargs_get_u32(&args, &word); + if (rc || word) + return rc; + + /* Public data size and content */ + rc = serialargs_get_u32(&args, &word); + if (rc || !word) + return rc; + + *pub_size = word; + + rc = serialargs_get(&args, &byte, sizeof(uint8_t)); + if (rc) + return rc; + + if (byte != 0x02 && byte != 0x03 && byte != 0x04) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (byte != 0x04) { + EMSG("DER compressed public key format not yet supported"); + return PKCS11_CKR_ARGUMENTS_BAD; + } + + *pub_size -= sizeof(uint8_t); + + if (*pub_size >= 0x80) { + EMSG("DER long definitive form not yet supported"); + return PKCS11_CKR_ARGUMENTS_BAD; + } + + rc = serialargs_get_ptr(&args, pub_data, *pub_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc pkcs2tee_algo_ecdh(uint32_t *tee_id, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs args = { }; + uint32_t kdf = 0; + + serialargs_init(&args, proc_params->data, proc_params->size); + + rc = serialargs_get_u32(&args, &kdf); + if (rc) + return rc; + + /* Remaining arguments are extracted by pkcs2tee_param_ecdh */ + if (kdf != PKCS11_CKD_NULL) { + DMSG("Only support CKD_NULL key derivation for ECDH"); + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + } + + switch (get_object_key_bit_size(obj)) { + case 192: + *tee_id = TEE_ALG_ECDH_P192; + break; + case 224: + *tee_id = TEE_ALG_ECDH_P224; + break; + case 256: + *tee_id = TEE_ALG_ECDH_P256; + break; + case 384: + *tee_id = TEE_ALG_ECDH_P384; + break; + case 521: + *tee_id = TEE_ALG_ECDH_P521; + break; + default: + TEE_Panic(0); + break; + } + + return PKCS11_CKR_OK; +} diff --git a/optee/optee_os/ta/pkcs11/src/processing_rsa.c b/optee/optee_os/ta/pkcs11/src/processing_rsa.c new file mode 100644 index 0000000..94eabbf --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_rsa.c @@ -0,0 +1,777 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2021, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "object.h" +#include "pkcs11_token.h" +#include "processing.h" + +enum pkcs11_rc +pkcs2tee_proc_params_rsa_pss(struct active_processing *proc, + struct pkcs11_attribute_head *proc_params) +{ + struct serialargs args = { }; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct rsa_pss_processing_ctx *ctx = NULL; + uint32_t hash = 0; + uint32_t mgf = 0; + uint32_t salt_len = 0; + + serialargs_init(&args, proc_params->data, proc_params->size); + + rc = serialargs_get_u32(&args, &hash); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &mgf); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &salt_len); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + proc->extra_ctx = TEE_Malloc(sizeof(struct rsa_pss_processing_ctx), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!proc->extra_ctx) + return PKCS11_CKR_DEVICE_MEMORY; + + ctx = proc->extra_ctx; + + ctx->hash_alg = hash; + ctx->mgf_type = mgf; + ctx->salt_len = salt_len; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc pkcs2tee_validate_rsa_pss(struct active_processing *proc, + struct pkcs11_object *obj) +{ + struct rsa_pss_processing_ctx *rsa_pss_ctx = NULL; + size_t modulus_size = 0; + size_t hash_size = 0; + uint32_t k = 0; + + rsa_pss_ctx = proc->extra_ctx; + assert(rsa_pss_ctx); + + switch (rsa_pss_ctx->hash_alg) { + case PKCS11_CKM_SHA_1: + hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA1); + break; + case PKCS11_CKM_SHA224: + hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA224); + break; + case PKCS11_CKM_SHA256: + hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA256); + break; + case PKCS11_CKM_SHA384: + hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA384); + break; + case PKCS11_CKM_SHA512: + hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA512); + break; + default: + assert(0); + break; + } + + modulus_size = get_object_key_bit_size(obj); + + /** + * The sLen field must be less than or equal to k*-2-hLen where + * hLen is the length in bytes of the hash value. k* is the + * length in bytes of the RSA modulus, except if the length in + * bits of the RSA modulus is one more than a multiple of 8, in + * which case k* is one less than the length in bytes of the + * RSA modulus. + */ + if ((modulus_size % 8) == 1) + k = modulus_size / 8; + else + k = ROUNDUP(modulus_size, 8) / 8; + + if (rsa_pss_ctx->salt_len > (k - 2 - hash_size)) + return PKCS11_CKR_KEY_SIZE_RANGE; + + return PKCS11_CKR_OK; +} + +/* + * Check or set TEE algorithm identifier upon PKCS11 mechanism parameters + * @tee_id: Input and/or output TEE algorithm identifier + * @proc_params: PKCS11 processing parameters + */ +enum pkcs11_rc pkcs2tee_algo_rsa_pss(uint32_t *tee_id, + struct pkcs11_attribute_head *proc_params) +{ + struct serialargs args = { }; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + uint32_t hash = 0; + uint32_t mgf = 0; + uint32_t salt_len = 0; + + serialargs_init(&args, proc_params->data, proc_params->size); + + rc = serialargs_get_u32(&args, &hash); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &mgf); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &salt_len); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (proc_params->id == PKCS11_CKM_RSA_PKCS_PSS) { + if (hash == PKCS11_CKM_SHA_1 && mgf == PKCS11_CKG_MGF1_SHA1) { + *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1; + return PKCS11_CKR_OK; + } + if (hash == PKCS11_CKM_SHA224 && + mgf == PKCS11_CKG_MGF1_SHA224) { + *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224; + return PKCS11_CKR_OK; + } + if (hash == PKCS11_CKM_SHA256 && + mgf == PKCS11_CKG_MGF1_SHA256) { + *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256; + return PKCS11_CKR_OK; + } + if (hash == PKCS11_CKM_SHA384 && + mgf == PKCS11_CKG_MGF1_SHA384) { + *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384; + return PKCS11_CKR_OK; + } + if (hash == PKCS11_CKM_SHA512 && + mgf == PKCS11_CKG_MGF1_SHA512) { + *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512; + return PKCS11_CKR_OK; + } + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + } + + switch (*tee_id) { + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + if (hash != PKCS11_CKM_SHA_1 || mgf != PKCS11_CKG_MGF1_SHA1) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + if (hash != PKCS11_CKM_SHA224 || mgf != PKCS11_CKG_MGF1_SHA224) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + if (hash != PKCS11_CKM_SHA256 || mgf != PKCS11_CKG_MGF1_SHA256) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + if (hash != PKCS11_CKM_SHA384 || mgf != PKCS11_CKG_MGF1_SHA384) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + break; + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + if (hash != PKCS11_CKM_SHA512 || mgf != PKCS11_CKG_MGF1_SHA512) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + break; + default: + return PKCS11_CKR_GENERAL_ERROR; + } + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc +pkcs2tee_proc_params_rsa_oaep(struct active_processing *proc, + struct pkcs11_attribute_head *proc_params) +{ + struct serialargs args = { }; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct rsa_oaep_processing_ctx *ctx = NULL; + uint32_t hash = 0; + uint32_t mgf = 0; + uint32_t source_type = 0; + void *source_data = NULL; + uint32_t source_size = 0; + + serialargs_init(&args, proc_params->data, proc_params->size); + + rc = serialargs_get_u32(&args, &hash); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &mgf); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &source_type); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &source_size); + if (rc) + return rc; + + rc = serialargs_get_ptr(&args, &source_data, source_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + proc->extra_ctx = TEE_Malloc(sizeof(struct rsa_oaep_processing_ctx) + + source_size, + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!proc->extra_ctx) + return PKCS11_CKR_DEVICE_MEMORY; + + ctx = proc->extra_ctx; + + ctx->hash_alg = hash; + ctx->mgf_type = mgf; + ctx->source_type = source_type; + ctx->source_data_len = source_size; + TEE_MemMove(ctx->source_data, source_data, source_size); + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc +pkcs2tee_proc_params_rsa_aes_wrap(struct active_processing *proc, + struct pkcs11_attribute_head *proc_params) +{ + struct serialargs args = { }; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct rsa_aes_key_wrap_processing_ctx *ctx = NULL; + uint32_t aes_key_bits = 0; + uint32_t hash = 0; + uint32_t mgf = 0; + uint32_t source_type = 0; + void *source_data = NULL; + uint32_t source_size = 0; + + serialargs_init(&args, proc_params->data, proc_params->size); + + rc = serialargs_get_u32(&args, &aes_key_bits); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &hash); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &mgf); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &source_type); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &source_size); + if (rc) + return rc; + + rc = serialargs_get_ptr(&args, &source_data, source_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + proc->extra_ctx = + TEE_Malloc(sizeof(struct rsa_aes_key_wrap_processing_ctx) + + source_size, + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!proc->extra_ctx) + return PKCS11_CKR_DEVICE_MEMORY; + + ctx = proc->extra_ctx; + + ctx->aes_key_bits = aes_key_bits; + ctx->hash_alg = hash; + ctx->mgf_type = mgf; + ctx->source_type = source_type; + ctx->source_data_len = source_size; + TEE_MemMove(ctx->source_data, source_data, source_size); + + return PKCS11_CKR_OK; +} + +/* + * Set TEE RSA OAEP algorithm identifier upon PKCS11 mechanism parameters + * @tee_id: output TEE RSA OAEP algorithm identifier + * @tee_hash_id: output TEE hash algorithm identifier + * @proc_params: PKCS11 processing parameters + */ +enum pkcs11_rc +pkcs2tee_algo_rsa_oaep(uint32_t *tee_id, uint32_t *tee_hash_id, + struct pkcs11_attribute_head *proc_params) +{ + struct serialargs args = { }; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + uint32_t hash = 0; + uint32_t mgf = 0; + uint32_t source_type = 0; + void *source_data = NULL; + uint32_t source_size = 0; + + serialargs_init(&args, proc_params->data, proc_params->size); + + rc = serialargs_get_u32(&args, &hash); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &mgf); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &source_type); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &source_size); + if (rc) + return rc; + + rc = serialargs_get_ptr(&args, &source_data, source_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (source_type != PKCS11_CKZ_DATA_SPECIFIED) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + + switch (proc_params->id) { + case PKCS11_CKM_RSA_PKCS_OAEP: + switch (hash) { + case PKCS11_CKM_SHA_1: + if (mgf != PKCS11_CKG_MGF1_SHA1) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1; + *tee_hash_id = TEE_ALG_SHA1; + break; + case PKCS11_CKM_SHA224: + if (mgf != PKCS11_CKG_MGF1_SHA224) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224; + *tee_hash_id = TEE_ALG_SHA224; + break; + case PKCS11_CKM_SHA256: + if (mgf != PKCS11_CKG_MGF1_SHA256) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256; + *tee_hash_id = TEE_ALG_SHA256; + break; + case PKCS11_CKM_SHA384: + if (mgf != PKCS11_CKG_MGF1_SHA384) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384; + *tee_hash_id = TEE_ALG_SHA384; + break; + case PKCS11_CKM_SHA512: + if (mgf != PKCS11_CKG_MGF1_SHA512) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512; + *tee_hash_id = TEE_ALG_SHA512; + break; + default: + EMSG("Unexpected %#"PRIx32"/%s", hash, + id2str_proc(hash)); + + return PKCS11_CKR_GENERAL_ERROR; + } + break; + default: + EMSG("Unexpected mechanism %#"PRIx32"/%s", proc_params->id, + id2str_proc(proc_params->id)); + + return PKCS11_CKR_GENERAL_ERROR; + } + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc +pkcs2tee_algo_rsa_aes_wrap(uint32_t *tee_id, uint32_t *tee_hash_id, + struct pkcs11_attribute_head *proc_params) +{ + struct serialargs args = { }; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + uint32_t aes_key_bits = 0; + uint32_t hash = 0; + uint32_t mgf = 0; + uint32_t source_type = 0; + void *source_data = NULL; + uint32_t source_size = 0; + + serialargs_init(&args, proc_params->data, proc_params->size); + + rc = serialargs_get_u32(&args, &aes_key_bits); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &hash); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &mgf); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &source_type); + if (rc) + return rc; + + rc = serialargs_get_u32(&args, &source_size); + if (rc) + return rc; + + rc = serialargs_get_ptr(&args, &source_data, source_size); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&args)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (source_type != PKCS11_CKZ_DATA_SPECIFIED) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + + switch (proc_params->id) { + case PKCS11_CKM_RSA_AES_KEY_WRAP: + switch (hash) { + case PKCS11_CKM_SHA_1: + if (mgf != PKCS11_CKG_MGF1_SHA1) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1; + *tee_hash_id = TEE_ALG_SHA1; + break; + case PKCS11_CKM_SHA224: + if (mgf != PKCS11_CKG_MGF1_SHA224) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224; + *tee_hash_id = TEE_ALG_SHA224; + break; + case PKCS11_CKM_SHA256: + if (mgf != PKCS11_CKG_MGF1_SHA256) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256; + *tee_hash_id = TEE_ALG_SHA256; + break; + case PKCS11_CKM_SHA384: + if (mgf != PKCS11_CKG_MGF1_SHA384) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384; + *tee_hash_id = TEE_ALG_SHA384; + break; + case PKCS11_CKM_SHA512: + if (mgf != PKCS11_CKG_MGF1_SHA512) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512; + *tee_hash_id = TEE_ALG_SHA512; + break; + default: + EMSG("Unexpected %#"PRIx32"/%s", hash, + id2str_proc(hash)); + + return PKCS11_CKR_GENERAL_ERROR; + } + break; + default: + EMSG("Unexpected mechanism %#"PRIx32"/%s", proc_params->id, + id2str_proc(proc_params->id)); + + return PKCS11_CKR_GENERAL_ERROR; + } + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs, + size_t *tee_count, + struct pkcs11_object *obj) +{ + TEE_Attribute *attrs = NULL; + size_t count = 0; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *a_ptr = NULL; + + assert(get_key_type(obj->attributes) == PKCS11_CKK_RSA); + + switch (get_class(obj->attributes)) { + case PKCS11_CKO_PUBLIC_KEY: + attrs = TEE_Malloc(2 * sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!attrs) + return PKCS11_CKR_DEVICE_MEMORY; + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_MODULUS, + obj, PKCS11_CKA_MODULUS)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_RSA_PUBLIC_EXPONENT, obj, + PKCS11_CKA_PUBLIC_EXPONENT)) + count++; + + if (count == 2) + rc = PKCS11_CKR_OK; + + break; + + case PKCS11_CKO_PRIVATE_KEY: + attrs = TEE_Malloc(8 * sizeof(TEE_Attribute), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + if (!attrs) + return PKCS11_CKR_DEVICE_MEMORY; + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_MODULUS, + obj, PKCS11_CKA_MODULUS)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_RSA_PUBLIC_EXPONENT, obj, + PKCS11_CKA_PUBLIC_EXPONENT)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], + TEE_ATTR_RSA_PRIVATE_EXPONENT, obj, + PKCS11_CKA_PRIVATE_EXPONENT)) + count++; + + if (count != 3) + break; + + /* If pre-computed values are present load those */ + rc = get_attribute_ptr(obj->attributes, PKCS11_CKA_PRIME_1, + &a_ptr, NULL); + if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) + break; + if (rc == PKCS11_RV_NOT_FOUND || !a_ptr) { + rc = PKCS11_CKR_OK; + break; + } + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PRIME1, obj, + PKCS11_CKA_PRIME_1)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PRIME2, obj, + PKCS11_CKA_PRIME_2)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_EXPONENT1, + obj, PKCS11_CKA_EXPONENT_1)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_EXPONENT2, + obj, PKCS11_CKA_EXPONENT_2)) + count++; + + if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_COEFFICIENT, + obj, PKCS11_CKA_COEFFICIENT)) + count++; + + if (count == 8) + rc = PKCS11_CKR_OK; + + break; + + default: + assert(0); + break; + } + + if (rc == PKCS11_CKR_OK) { + *tee_attrs = attrs; + *tee_count = count; + } else { + TEE_Free(attrs); + } + + return rc; +} + +static enum pkcs11_rc tee2pkcs_rsa_attributes(struct obj_attrs **pub_head, + struct obj_attrs **priv_head, + TEE_ObjectHandle tee_obj) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *a_ptr = NULL; + + rc = tee2pkcs_add_attribute(pub_head, PKCS11_CKA_MODULUS, tee_obj, + TEE_ATTR_RSA_MODULUS); + if (rc) + goto out; + + rc = get_attribute_ptr(*pub_head, PKCS11_CKA_PUBLIC_EXPONENT, &a_ptr, + NULL); + if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) + goto out; + + if (rc == PKCS11_CKR_OK && !a_ptr) { + rc = remove_empty_attribute(pub_head, + PKCS11_CKA_PUBLIC_EXPONENT); + if (rc) + goto out; + rc = PKCS11_RV_NOT_FOUND; + } + + if (rc == PKCS11_RV_NOT_FOUND) { + rc = tee2pkcs_add_attribute(pub_head, + PKCS11_CKA_PUBLIC_EXPONENT, + tee_obj, + TEE_ATTR_RSA_PUBLIC_EXPONENT); + if (rc) + goto out; + } + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_MODULUS, tee_obj, + TEE_ATTR_RSA_MODULUS); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PUBLIC_EXPONENT, + tee_obj, TEE_ATTR_RSA_PUBLIC_EXPONENT); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIVATE_EXPONENT, + tee_obj, TEE_ATTR_RSA_PRIVATE_EXPONENT); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIME_1, tee_obj, + TEE_ATTR_RSA_PRIME1); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIME_2, tee_obj, + TEE_ATTR_RSA_PRIME2); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_EXPONENT_1, tee_obj, + TEE_ATTR_RSA_EXPONENT1); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_EXPONENT_2, tee_obj, + TEE_ATTR_RSA_EXPONENT2); + if (rc) + goto out; + + rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_COEFFICIENT, tee_obj, + TEE_ATTR_RSA_COEFFICIENT); +out: + return rc; +} + +enum pkcs11_rc generate_rsa_keys(struct pkcs11_attribute_head *proc_params, + struct obj_attrs **pub_head, + struct obj_attrs **priv_head) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + void *a_ptr = NULL; + uint32_t a_size = 0; + TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t modulus_bits = 0; + TEE_Attribute tee_attrs[1] = { }; + uint32_t tee_count = 0; + + if (!proc_params || !*pub_head || !*priv_head) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + + rc = get_attribute_ptr(*pub_head, PKCS11_CKA_MODULUS_BITS, &a_ptr, + &a_size); + if (rc != PKCS11_CKR_OK || a_size != sizeof(uint32_t)) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + + TEE_MemMove(&modulus_bits, a_ptr, sizeof(uint32_t)); + + rc = get_attribute_ptr(*pub_head, PKCS11_CKA_PUBLIC_EXPONENT, &a_ptr, + &a_size); + if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) + return rc; + + if (rc == PKCS11_CKR_OK && a_ptr) { + TEE_InitRefAttribute(&tee_attrs[tee_count], + TEE_ATTR_RSA_PUBLIC_EXPONENT, + a_ptr, a_size); + tee_count++; + } + + if (remove_empty_attribute(priv_head, PKCS11_CKA_MODULUS) || + remove_empty_attribute(priv_head, PKCS11_CKA_PUBLIC_EXPONENT) || + remove_empty_attribute(priv_head, PKCS11_CKA_PRIVATE_EXPONENT) || + remove_empty_attribute(priv_head, PKCS11_CKA_PRIME_1) || + remove_empty_attribute(priv_head, PKCS11_CKA_PRIME_2) || + remove_empty_attribute(priv_head, PKCS11_CKA_EXPONENT_1) || + remove_empty_attribute(priv_head, PKCS11_CKA_EXPONENT_2) || + remove_empty_attribute(priv_head, PKCS11_CKA_COEFFICIENT)) { + EMSG("Unexpected attribute(s) found"); + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + + /* Create an RSA TEE key */ + res = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR, modulus_bits, + &tee_obj); + if (res) { + DMSG("TEE_AllocateTransientObject failed %#"PRIx32, res); + + rc = tee2pkcs_error(res); + goto out; + } + + res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE); + if (res) { + DMSG("TEE_RestrictObjectUsage1 failed %#"PRIx32, res); + + rc = tee2pkcs_error(res); + goto out; + } + + res = TEE_GenerateKey(tee_obj, modulus_bits, tee_attrs, tee_count); + if (res) { + DMSG("TEE_GenerateKey failed %#"PRIx32, res); + + rc = tee2pkcs_error(res); + goto out; + } + + rc = tee2pkcs_rsa_attributes(pub_head, priv_head, tee_obj); + +out: + if (tee_obj != TEE_HANDLE_NULL) + TEE_CloseObject(tee_obj); + + return rc; +} + +size_t rsa_get_input_max_byte_size(TEE_OperationHandle op) +{ + TEE_OperationInfo info = { }; + + TEE_GetOperationInfo(op, &info); + + return info.maxKeySize / 8; +} diff --git a/optee/optee_os/ta/pkcs11/src/processing_symm.c b/optee/optee_os/ta/pkcs11/src/processing_symm.c new file mode 100644 index 0000000..7363150 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/processing_symm.c @@ -0,0 +1,1145 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "object.h" +#include "pkcs11_attributes.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "processing.h" +#include "serializer.h" + +struct input_data_ref { + size_t size; + void *data; +}; + +bool processing_is_tee_symm(enum pkcs11_mechanism_id proc_id) +{ + switch (proc_id) { + /* Authentication */ + case PKCS11_CKM_AES_CMAC: + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA512_HMAC: + case PKCS11_CKM_AES_CMAC_GENERAL: + case PKCS11_CKM_MD5_HMAC_GENERAL: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + /* Ciphering */ + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + case PKCS11_CKM_AES_CTS: + case PKCS11_CKM_AES_CTR: + case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: + case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: + return true; + default: + return false; + } +} + +static enum pkcs11_rc +pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params) +{ + static const struct { + enum pkcs11_mechanism_id mech_id; + uint32_t tee_id; + } pkcs2tee_algo[] = { + /* AES flavors */ + { PKCS11_CKM_AES_ECB, TEE_ALG_AES_ECB_NOPAD }, + { PKCS11_CKM_AES_CBC, TEE_ALG_AES_CBC_NOPAD }, + { PKCS11_CKM_AES_ECB_ENCRYPT_DATA, TEE_ALG_AES_ECB_NOPAD }, + { PKCS11_CKM_AES_CBC_ENCRYPT_DATA, TEE_ALG_AES_CBC_NOPAD }, + { PKCS11_CKM_AES_CTR, TEE_ALG_AES_CTR }, + { PKCS11_CKM_AES_CTS, TEE_ALG_AES_CTS }, + { PKCS11_CKM_AES_CMAC, TEE_ALG_AES_CMAC }, + { PKCS11_CKM_AES_CMAC_GENERAL, TEE_ALG_AES_CMAC }, + /* HMAC flavors */ + { PKCS11_CKM_MD5_HMAC, TEE_ALG_HMAC_MD5 }, + { PKCS11_CKM_SHA_1_HMAC, TEE_ALG_HMAC_SHA1 }, + { PKCS11_CKM_SHA224_HMAC, TEE_ALG_HMAC_SHA224 }, + { PKCS11_CKM_SHA256_HMAC, TEE_ALG_HMAC_SHA256 }, + { PKCS11_CKM_SHA384_HMAC, TEE_ALG_HMAC_SHA384 }, + { PKCS11_CKM_SHA512_HMAC, TEE_ALG_HMAC_SHA512 }, + { PKCS11_CKM_MD5_HMAC_GENERAL, TEE_ALG_HMAC_MD5 }, + { PKCS11_CKM_SHA_1_HMAC_GENERAL, TEE_ALG_HMAC_SHA1 }, + { PKCS11_CKM_SHA224_HMAC_GENERAL, TEE_ALG_HMAC_SHA224 }, + { PKCS11_CKM_SHA256_HMAC_GENERAL, TEE_ALG_HMAC_SHA256 }, + { PKCS11_CKM_SHA384_HMAC_GENERAL, TEE_ALG_HMAC_SHA384 }, + { PKCS11_CKM_SHA512_HMAC_GENERAL, TEE_ALG_HMAC_SHA512 }, + }; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) { + if (proc_params->id == pkcs2tee_algo[n].mech_id) { + *tee_id = pkcs2tee_algo[n].tee_id; + return PKCS11_CKR_OK; + } + } + + return PKCS11_RV_NOT_IMPLEMENTED; +} + +static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type, + struct pkcs11_object *obj) +{ + static const struct { + enum pkcs11_key_type key_type; + uint32_t tee_id; + } pkcs2tee_key_type[] = { + { PKCS11_CKK_AES, TEE_TYPE_AES }, + { PKCS11_CKK_GENERIC_SECRET, TEE_TYPE_GENERIC_SECRET }, + { PKCS11_CKK_MD5_HMAC, TEE_TYPE_HMAC_MD5 }, + { PKCS11_CKK_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 }, + { PKCS11_CKK_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 }, + { PKCS11_CKK_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 }, + { PKCS11_CKK_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 }, + { PKCS11_CKK_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 }, + }; + size_t n = 0; + enum pkcs11_key_type key_type = get_key_type(obj->attributes); + + assert(get_class(obj->attributes) == PKCS11_CKO_SECRET_KEY); + + for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) { + if (pkcs2tee_key_type[n].key_type == key_type) { + *tee_type = pkcs2tee_key_type[n].tee_id; + return PKCS11_CKR_OK; + } + } + + return PKCS11_RV_NOT_FOUND; +} + +static enum pkcs11_rc pkcsmech2tee_key_type(uint32_t *tee_type, + enum pkcs11_mechanism_id mech_id) +{ + static const struct { + enum pkcs11_mechanism_id mech; + uint32_t tee_id; + } pkcs2tee_key_type[] = { + { PKCS11_CKM_MD5_HMAC, TEE_TYPE_HMAC_MD5 }, + { PKCS11_CKM_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 }, + { PKCS11_CKM_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 }, + { PKCS11_CKM_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 }, + { PKCS11_CKM_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 }, + { PKCS11_CKM_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 }, + { PKCS11_CKM_MD5_HMAC_GENERAL, TEE_TYPE_HMAC_MD5 }, + { PKCS11_CKM_SHA_1_HMAC_GENERAL, TEE_TYPE_HMAC_SHA1 }, + { PKCS11_CKM_SHA224_HMAC_GENERAL, TEE_TYPE_HMAC_SHA224 }, + { PKCS11_CKM_SHA256_HMAC_GENERAL, TEE_TYPE_HMAC_SHA256 }, + { PKCS11_CKM_SHA384_HMAC_GENERAL, TEE_TYPE_HMAC_SHA384 }, + { PKCS11_CKM_SHA512_HMAC_GENERAL, TEE_TYPE_HMAC_SHA512 }, + }; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) { + if (pkcs2tee_key_type[n].mech == mech_id) { + *tee_type = pkcs2tee_key_type[n].tee_id; + return PKCS11_CKR_OK; + } + } + + return PKCS11_RV_NOT_FOUND; +} + +static enum pkcs11_rc hmac_to_tee_hash(uint32_t *algo, + enum pkcs11_mechanism_id mech_id) +{ + static const struct { + enum pkcs11_mechanism_id mech; + uint32_t tee_id; + } hmac_hash[] = { + { PKCS11_CKM_MD5_HMAC, TEE_ALG_MD5 }, + { PKCS11_CKM_SHA_1_HMAC, TEE_ALG_SHA1 }, + { PKCS11_CKM_SHA224_HMAC, TEE_ALG_SHA224 }, + { PKCS11_CKM_SHA256_HMAC, TEE_ALG_SHA256 }, + { PKCS11_CKM_SHA384_HMAC, TEE_ALG_SHA384 }, + { PKCS11_CKM_SHA512_HMAC, TEE_ALG_SHA512 }, + { PKCS11_CKM_MD5_HMAC_GENERAL, TEE_ALG_MD5 }, + { PKCS11_CKM_SHA_1_HMAC_GENERAL, TEE_ALG_SHA1 }, + { PKCS11_CKM_SHA224_HMAC_GENERAL, TEE_ALG_SHA224 }, + { PKCS11_CKM_SHA256_HMAC_GENERAL, TEE_ALG_SHA256 }, + { PKCS11_CKM_SHA384_HMAC_GENERAL, TEE_ALG_SHA384 }, + { PKCS11_CKM_SHA512_HMAC_GENERAL, TEE_ALG_SHA512 }, + }; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(hmac_hash); n++) { + if (hmac_hash[n].mech == mech_id) { + *algo = hmac_hash[n].tee_id; + return PKCS11_CKR_OK; + } + } + + return PKCS11_RV_NOT_FOUND; +} + +static enum pkcs11_rc +allocate_tee_operation(struct pkcs11_session *session, + enum processing_func function, + struct pkcs11_attribute_head *params, + struct pkcs11_object *obj) +{ + uint32_t size = (uint32_t)get_object_key_bit_size(obj); + uint32_t key_size = size / 8; + uint32_t algo = 0; + uint32_t mode = 0; + uint32_t max_key_size = 0; + uint32_t min_key_size = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + assert(session->processing->tee_op_handle == TEE_HANDLE_NULL); + + if (pkcs2tee_algorithm(&algo, params)) + return PKCS11_CKR_FUNCTION_FAILED; + + /* Sign/Verify with AES or generic key relate to TEE MAC operation */ + switch (params->id) { + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA512_HMAC: + case PKCS11_CKM_MD5_HMAC_GENERAL: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + mechanism_supported_key_sizes_bytes(params->id, &min_key_size, + &max_key_size); + if (key_size < min_key_size) + return PKCS11_CKR_KEY_SIZE_RANGE; + + /* + * If size of generic key is greater than the size + * supported by TEE API, this is not considered an + * error. When loading TEE key, we will hash the key + * to generate the appropriate key for HMAC operation. + * This key size will not be greater than the + * max_key_size. So we can use max_key_size for + * TEE_AllocateOperation(). + */ + if (key_size > max_key_size) + size = max_key_size * 8; + + mode = TEE_MODE_MAC; + break; + case PKCS11_CKM_AES_CMAC: + case PKCS11_CKM_AES_CMAC_GENERAL: + mode = TEE_MODE_MAC; + break; + default: + pkcs2tee_mode(&mode, function); + break; + } + + res = TEE_AllocateOperation(&session->processing->tee_op_handle, + algo, mode, size); + if (res) + EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32, + algo, mode, size); + + if (res == TEE_ERROR_NOT_SUPPORTED) + return PKCS11_CKR_MECHANISM_INVALID; + + return tee2pkcs_error(res); +} + +static enum pkcs11_rc hash_secret_helper(enum pkcs11_mechanism_id mech_id, + struct pkcs11_object *obj, + TEE_Attribute *tee_attr, + void **ctx, + size_t *object_size_bits) +{ + uint32_t algo = 0; + void *hash_ptr = NULL; + uint32_t hash_size = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = hmac_to_tee_hash(&algo, mech_id); + if (rc) + return rc; + + hash_size = TEE_ALG_GET_DIGEST_SIZE(algo); + hash_ptr = TEE_Malloc(hash_size, 0); + if (!hash_ptr) + return PKCS11_CKR_DEVICE_MEMORY; + + rc = pkcs2tee_load_hashed_attr(tee_attr, TEE_ATTR_SECRET_VALUE, obj, + PKCS11_CKA_VALUE, algo, hash_ptr, + &hash_size); + if (rc) { + EMSG("No secret/hash error"); + TEE_Free(hash_ptr); + return rc; + } + + *ctx = hash_ptr; + + *object_size_bits = hash_size * 8; + + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc load_tee_key(struct pkcs11_session *session, + struct pkcs11_object *obj, + struct pkcs11_attribute_head *proc_params) +{ + TEE_Attribute tee_attr = { }; + size_t object_size = 0; + uint32_t tee_key_type = 0; + enum pkcs11_key_type key_type = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t max_key_size = 0; + uint32_t min_key_size = 0; + + if (obj->key_handle != TEE_HANDLE_NULL) { + /* Key was already loaded and fits current need */ + goto key_ready; + } + + object_size = get_object_key_bit_size(obj); + if (!object_size) + return PKCS11_CKR_GENERAL_ERROR; + + switch (proc_params->id) { + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA512_HMAC: + case PKCS11_CKM_MD5_HMAC_GENERAL: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + key_type = get_key_type(obj->attributes); + /* + * If Object Key type is PKCS11_CKK_GENERIC_SECRET, + * determine the tee_key_type using the + * mechanism instead of object key_type. + */ + if (key_type == PKCS11_CKK_GENERIC_SECRET) + rc = pkcsmech2tee_key_type(&tee_key_type, + proc_params->id); + else + rc = pkcs2tee_key_type(&tee_key_type, obj); + + if (rc) + return rc; + + mechanism_supported_key_sizes_bytes(proc_params->id, + &min_key_size, + &max_key_size); + + if ((object_size / 8) > max_key_size) { + rc = hash_secret_helper(proc_params->id, obj, &tee_attr, + &session->processing->extra_ctx, + &object_size); + if (rc) + return rc; + } else { + if (!pkcs2tee_load_attr(&tee_attr, + TEE_ATTR_SECRET_VALUE, + obj, + PKCS11_CKA_VALUE)) { + EMSG("No secret found"); + return PKCS11_CKR_FUNCTION_FAILED; + } + } + break; + + default: + rc = pkcs2tee_key_type(&tee_key_type, obj); + if (rc) + return rc; + + if (!pkcs2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE, + obj, PKCS11_CKA_VALUE)) { + EMSG("No secret found"); + return PKCS11_CKR_FUNCTION_FAILED; + } + break; + } + + res = TEE_AllocateTransientObject(tee_key_type, object_size, + &obj->key_handle); + if (res) { + DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res); + return tee2pkcs_error(res); + } + + res = TEE_PopulateTransientObject(obj->key_handle, &tee_attr, 1); + if (res) { + DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res); + goto error; + } + +key_ready: + res = TEE_SetOperationKey(session->processing->tee_op_handle, + obj->key_handle); + if (res) { + DMSG("TEE_SetOperationKey failed, %#"PRIx32, res); + goto error; + } + + return PKCS11_CKR_OK; + +error: + TEE_FreeTransientObject(obj->key_handle); + obj->key_handle = TEE_HANDLE_NULL; + + return tee2pkcs_error(res); +} + +static enum pkcs11_rc +tee_init_derive_symm(struct active_processing *processing, + struct pkcs11_attribute_head *proc_params) +{ + struct serialargs args = { }; + enum pkcs11_rc rc = PKCS11_CKR_OK; + struct input_data_ref *param = NULL; + void *iv = NULL; + + if (!proc_params) + return PKCS11_CKR_ARGUMENTS_BAD; + + param = TEE_Malloc(sizeof(struct input_data_ref), TEE_MALLOC_FILL_ZERO); + if (!param) + return PKCS11_CKR_DEVICE_MEMORY; + + serialargs_init(&args, proc_params->data, proc_params->size); + + switch (proc_params->id) { + case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: + rc = serialargs_get_ptr(&args, &iv, 16); + if (rc) + goto err; + break; + default: + break; + } + + rc = serialargs_get(&args, ¶m->size, sizeof(uint32_t)); + if (rc) + goto err; + + rc = serialargs_get_ptr(&args, ¶m->data, param->size); + if (rc) + goto err; + + if (serialargs_remaining_bytes(&args)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto err; + } + + processing->extra_ctx = param; + + switch (proc_params->id) { + case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: + if (param->size % TEE_AES_BLOCK_SIZE) { + rc = PKCS11_CKR_DATA_LEN_RANGE; + goto err; + } + TEE_CipherInit(processing->tee_op_handle, NULL, 0); + break; + case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: + if (param->size % TEE_AES_BLOCK_SIZE) { + rc = PKCS11_CKR_DATA_LEN_RANGE; + goto err; + } + TEE_CipherInit(processing->tee_op_handle, iv, 16); + break; + default: + TEE_Panic(proc_params->id); + break; + } + + return PKCS11_CKR_OK; + +err: + processing->extra_ctx = NULL; + TEE_Free(param); + return rc; +} + +static enum pkcs11_rc +input_hmac_len_is_valid(struct pkcs11_attribute_head *proc_params, + uint32_t hmac_len) +{ + uint32_t sign_sz = 0; + + switch (proc_params->id) { + case PKCS11_CKM_MD5_HMAC_GENERAL: + sign_sz = TEE_MD5_HASH_SIZE; + break; + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + sign_sz = TEE_SHA1_HASH_SIZE; + break; + case PKCS11_CKM_SHA224_HMAC_GENERAL: + sign_sz = TEE_SHA224_HASH_SIZE; + break; + case PKCS11_CKM_SHA256_HMAC_GENERAL: + sign_sz = TEE_SHA256_HASH_SIZE; + break; + case PKCS11_CKM_SHA384_HMAC_GENERAL: + sign_sz = TEE_SHA384_HASH_SIZE; + break; + case PKCS11_CKM_SHA512_HMAC_GENERAL: + sign_sz = TEE_SHA512_HASH_SIZE; + break; + case PKCS11_CKM_AES_CMAC_GENERAL: + sign_sz = TEE_AES_BLOCK_SIZE; + break; + default: + return PKCS11_CKR_MECHANISM_INVALID; + } + + if (!hmac_len || hmac_len > sign_sz) + return PKCS11_CKR_SIGNATURE_LEN_RANGE; + + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc +init_tee_operation(struct pkcs11_session *session, + struct pkcs11_attribute_head *proc_params) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + uint32_t *pkcs11_data = NULL; + + switch (proc_params->id) { + case PKCS11_CKM_AES_CMAC: + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA512_HMAC: + if (proc_params->size) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + + TEE_MACInit(session->processing->tee_op_handle, NULL, 0); + rc = PKCS11_CKR_OK; + break; + case PKCS11_CKM_AES_CMAC_GENERAL: + case PKCS11_CKM_MD5_HMAC_GENERAL: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + if (proc_params->size != sizeof(uint32_t)) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + + pkcs11_data = TEE_Malloc(sizeof(uint32_t), + TEE_MALLOC_FILL_ZERO); + if (!pkcs11_data) + return PKCS11_CKR_DEVICE_MEMORY; + + TEE_MemMove(pkcs11_data, proc_params->data, sizeof(uint32_t)); + + rc = input_hmac_len_is_valid(proc_params, *pkcs11_data); + if (rc) { + TEE_Free(pkcs11_data); + return rc; + } + + session->processing->extra_ctx = (void *)pkcs11_data; + + TEE_MACInit(session->processing->tee_op_handle, NULL, 0); + rc = PKCS11_CKR_OK; + break; + case PKCS11_CKM_AES_ECB: + if (proc_params->size) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + + TEE_CipherInit(session->processing->tee_op_handle, NULL, 0); + rc = PKCS11_CKR_OK; + break; + case PKCS11_CKM_AES_CBC: + case PKCS11_CKM_AES_CTS: + if (proc_params->size != 16) + return PKCS11_CKR_MECHANISM_PARAM_INVALID; + + TEE_CipherInit(session->processing->tee_op_handle, + proc_params->data, 16); + rc = PKCS11_CKR_OK; + break; + case PKCS11_CKM_AES_CTR: + rc = tee_init_ctr_operation(session->processing, + proc_params->data, + proc_params->size); + break; + case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: + case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: + rc = tee_init_derive_symm(session->processing, proc_params); + break; + default: + TEE_Panic(proc_params->id); + break; + } + + return rc; +} + +enum pkcs11_rc init_symm_operation(struct pkcs11_session *session, + enum processing_func function, + struct pkcs11_attribute_head *proc_params, + struct pkcs11_object *obj) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(processing_is_tee_symm(proc_params->id)); + + rc = allocate_tee_operation(session, function, proc_params, obj); + if (rc) + return rc; + + rc = load_tee_key(session, obj, proc_params); + if (rc) + return rc; + + rc = init_tee_operation(session, proc_params); + if (!rc) + session->processing->mecha_type = proc_params->id; + + return rc; +} + +/* Validate input buffer size as per PKCS#11 constraints */ +static enum pkcs11_rc input_data_size_is_valid(struct active_processing *proc, + enum processing_func function, + size_t in_size) +{ + switch (proc->mecha_type) { + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + if (function == PKCS11_FUNCTION_ENCRYPT && + in_size % TEE_AES_BLOCK_SIZE) + return PKCS11_CKR_DATA_LEN_RANGE; + if (function == PKCS11_FUNCTION_DECRYPT && + in_size % TEE_AES_BLOCK_SIZE) + return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; + break; + case PKCS11_CKM_AES_CTS: + if (function == PKCS11_FUNCTION_ENCRYPT && + in_size < TEE_AES_BLOCK_SIZE) + return PKCS11_CKR_DATA_LEN_RANGE; + if (function == PKCS11_FUNCTION_DECRYPT && + in_size < TEE_AES_BLOCK_SIZE) + return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; + break; + default: + break; + } + + return PKCS11_CKR_OK; +} + +/* Validate input buffer size as per PKCS#11 constraints */ +static enum pkcs11_rc input_sign_size_is_valid(struct active_processing *proc, + size_t in_size) +{ + size_t sign_sz = 0; + + switch (proc->mecha_type) { + case PKCS11_CKM_MD5_HMAC: + sign_sz = TEE_MD5_HASH_SIZE; + break; + case PKCS11_CKM_SHA_1_HMAC: + sign_sz = TEE_SHA1_HASH_SIZE; + break; + case PKCS11_CKM_SHA224_HMAC: + sign_sz = TEE_SHA224_HASH_SIZE; + break; + case PKCS11_CKM_SHA256_HMAC: + sign_sz = TEE_SHA256_HASH_SIZE; + break; + case PKCS11_CKM_SHA384_HMAC: + sign_sz = TEE_SHA384_HASH_SIZE; + break; + case PKCS11_CKM_SHA512_HMAC: + sign_sz = TEE_SHA512_HASH_SIZE; + break; + case PKCS11_CKM_AES_CMAC: + sign_sz = TEE_AES_BLOCK_SIZE; + break; + default: + return PKCS11_CKR_GENERAL_ERROR; + } + + if (in_size != sign_sz) + return PKCS11_CKR_SIGNATURE_LEN_RANGE; + + return PKCS11_CKR_OK; +} + +/* + * step_sym_cipher - processing symmetric (and related) cipher operation step + * + * @session - current session + * @function - processing function (encrypt, decrypt, sign, ...) + * @step - step ID in the processing (oneshot, update, final) + * @ptype - invocation parameter types + * @params - invocation parameter references + */ +enum pkcs11_rc step_symm_operation(struct pkcs11_session *session, + enum processing_func function, + enum processing_step step, + uint32_t ptypes, TEE_Param *params) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + void *in_buf = NULL; + size_t in_size = 0; + void *out_buf = NULL; + size_t out_size = 0; + void *in2_buf = NULL; + uint32_t in2_size = 0; + bool output_data = false; + struct active_processing *proc = session->processing; + uint32_t hmac_len = 0; + uint8_t computed_mac[TEE_MAX_HASH_SIZE] = { 0 }; + size_t computed_mac_size = TEE_MAX_HASH_SIZE; + + if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) { + in_buf = params[1].memref.buffer; + in_size = params[1].memref.size; + if (in_size && !in_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + } + if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) { + in2_buf = params[2].memref.buffer; + in2_size = params[2].memref.size; + if (in2_size && !in2_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + } + if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) { + out_buf = params[2].memref.buffer; + out_size = params[2].memref.size; + if (out_size && !out_buf) + return PKCS11_CKR_ARGUMENTS_BAD; + } + if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) + return PKCS11_CKR_ARGUMENTS_BAD; + + switch (step) { + case PKCS11_FUNC_STEP_ONESHOT: + case PKCS11_FUNC_STEP_UPDATE: + case PKCS11_FUNC_STEP_FINAL: + break; + default: + return PKCS11_CKR_GENERAL_ERROR; + } + + if (step != PKCS11_FUNC_STEP_FINAL) { + rc = input_data_size_is_valid(proc, function, in_size); + if (rc) + return rc; + } + + /* + * Feed active operation with data + */ + switch (proc->mecha_type) { + case PKCS11_CKM_AES_CMAC: + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA512_HMAC: + case PKCS11_CKM_AES_CMAC_GENERAL: + case PKCS11_CKM_MD5_HMAC_GENERAL: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + if (step == PKCS11_FUNC_STEP_FINAL || + step == PKCS11_FUNC_STEP_ONESHOT) + break; + + if (!in_buf) { + DMSG("No input data"); + return PKCS11_CKR_ARGUMENTS_BAD; + } + + switch (function) { + case PKCS11_FUNCTION_SIGN: + case PKCS11_FUNCTION_VERIFY: + TEE_MACUpdate(proc->tee_op_handle, in_buf, in_size); + rc = PKCS11_CKR_OK; + break; + default: + TEE_Panic(function); + break; + } + break; + + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + case PKCS11_CKM_AES_CTS: + case PKCS11_CKM_AES_CTR: + if (step == PKCS11_FUNC_STEP_FINAL || + step == PKCS11_FUNC_STEP_ONESHOT) + break; + + if (!in_buf) { + EMSG("No input data"); + return PKCS11_CKR_ARGUMENTS_BAD; + } + + switch (function) { + case PKCS11_FUNCTION_ENCRYPT: + case PKCS11_FUNCTION_DECRYPT: + res = TEE_CipherUpdate(proc->tee_op_handle, + in_buf, in_size, + out_buf, &out_size); + output_data = true; + rc = tee2pkcs_error(res); + break; + default: + TEE_Panic(function); + break; + } + break; + + default: + TEE_Panic(proc->mecha_type); + break; + } + + if (step == PKCS11_FUNC_STEP_UPDATE) + goto out; + + /* + * Finalize (PKCS11_FUNC_STEP_ONESHOT/_FINAL) operation + */ + switch (session->processing->mecha_type) { + case PKCS11_CKM_AES_CMAC: + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA512_HMAC: + switch (function) { + case PKCS11_FUNCTION_SIGN: + res = TEE_MACComputeFinal(proc->tee_op_handle, + in_buf, in_size, out_buf, + &out_size); + output_data = true; + rc = tee2pkcs_error(res); + break; + case PKCS11_FUNCTION_VERIFY: + rc = input_sign_size_is_valid(proc, in2_size); + if (rc) + return rc; + res = TEE_MACCompareFinal(proc->tee_op_handle, + in_buf, in_size, in2_buf, + in2_size); + rc = tee2pkcs_error(res); + break; + default: + TEE_Panic(function); + break; + } + + break; + + case PKCS11_CKM_AES_CMAC_GENERAL: + case PKCS11_CKM_MD5_HMAC_GENERAL: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + assert(session->processing->extra_ctx); + hmac_len = *(uint32_t *)session->processing->extra_ctx; + + switch (function) { + case PKCS11_FUNCTION_SIGN: + if (out_size < hmac_len) { + /* inform client of required size */ + out_size = hmac_len; + output_data = true; + rc = PKCS11_CKR_BUFFER_TOO_SMALL; + goto out; + } + + res = TEE_MACComputeFinal(proc->tee_op_handle, + in_buf, in_size, + computed_mac, + &computed_mac_size); + if (res == TEE_SUCCESS) { + /* truncate to hmac_len */ + TEE_MemMove(out_buf, computed_mac, hmac_len); + output_data = true; + } + + /* inform client of required size */ + out_size = hmac_len; + rc = tee2pkcs_error(res); + break; + case PKCS11_FUNCTION_VERIFY: + /* must compute full MAC before comparing partial */ + res = TEE_MACComputeFinal(proc->tee_op_handle, in_buf, + in_size, computed_mac, + &computed_mac_size); + + if (!in2_size || in2_size > computed_mac_size) { + EMSG("Invalid signature size: %"PRIu32, + in2_size); + return PKCS11_CKR_SIGNATURE_LEN_RANGE; + } + + if (res == TEE_SUCCESS) { + /* + * Only the first in2_size bytes of the + * signature to be verified is passed in from + * caller + */ + if (TEE_MemCompare(in2_buf, computed_mac, + in2_size)) { + res = TEE_ERROR_MAC_INVALID; + } + } + + rc = tee2pkcs_error(res); + break; + default: + TEE_Panic(function); + break; + } + + break; + + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + case PKCS11_CKM_AES_CTS: + case PKCS11_CKM_AES_CTR: + if (step == PKCS11_FUNC_STEP_ONESHOT && !in_buf) { + EMSG("No input data"); + return PKCS11_CKR_ARGUMENTS_BAD; + } + + switch (function) { + case PKCS11_FUNCTION_ENCRYPT: + case PKCS11_FUNCTION_DECRYPT: + res = TEE_CipherDoFinal(proc->tee_op_handle, + in_buf, in_size, + out_buf, &out_size); + output_data = true; + rc = tee2pkcs_error(res); + break; + default: + TEE_Panic(function); + break; + } + break; + default: + TEE_Panic(proc->mecha_type); + break; + } + +out: + if (output_data && + (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) { + switch (TEE_PARAM_TYPE_GET(ptypes, 2)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + params[2].memref.size = out_size; + break; + default: + rc = PKCS11_CKR_ARGUMENTS_BAD; + break; + } + } + + return rc; +} + +enum pkcs11_rc derive_key_by_symm_enc(struct pkcs11_session *session, + void **out_buf, uint32_t *out_size) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + struct active_processing *proc = session->processing; + struct input_data_ref *input = proc->extra_ctx; + void *in_buf = NULL; + void *dest_buf = NULL; + uint32_t in_size = 0; + size_t tmp_sz = 0; + + switch (proc->mecha_type) { + case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: + case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: + if (!proc->extra_ctx) + return PKCS11_CKR_ARGUMENTS_BAD; + + in_buf = input->data; + in_size = input->size; + + *out_size = in_size; + dest_buf = TEE_Malloc(*out_size, 0); + if (!dest_buf) + return PKCS11_CKR_DEVICE_MEMORY; + + tmp_sz = *out_size; + res = TEE_CipherDoFinal(proc->tee_op_handle, in_buf, in_size, + dest_buf, &tmp_sz); + *out_size = tmp_sz; + rc = tee2pkcs_error(res); + if (rc) { + TEE_Free(dest_buf); + return rc; + } + + *out_buf = dest_buf; + break; + default: + return PKCS11_CKR_MECHANISM_INVALID; + } + + return rc; +} + +enum pkcs11_rc wrap_data_by_symm_enc(struct pkcs11_session *session, + void *data, uint32_t data_sz, + void *out_buf, uint32_t *out_sz) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct active_processing *proc = session->processing; + void *in_buf = NULL; + uint32_t align = 0; + uint32_t in_sz = data_sz; + size_t tmp_sz = *out_sz; + uint8_t *tmp_buf = out_buf; + + switch (proc->mecha_type) { + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + align = data_sz % TEE_AES_BLOCK_SIZE; + if (align) + in_sz = data_sz + (TEE_AES_BLOCK_SIZE - align); + + if (*out_sz < in_sz) { + *out_sz = in_sz; + return PKCS11_CKR_BUFFER_TOO_SMALL; + } + + if (align) { + if (data_sz > TEE_AES_BLOCK_SIZE) { + in_sz = data_sz - align; + res = TEE_CipherUpdate(proc->tee_op_handle, + data, in_sz, tmp_buf, + &tmp_sz); + if (res) { + assert(res != TEE_ERROR_SHORT_BUFFER); + return tee2pkcs_error(res); + } + tmp_buf += tmp_sz; + tmp_sz = *out_sz - tmp_sz; + } else { + in_sz = 0; + } + + in_buf = TEE_Malloc(TEE_AES_BLOCK_SIZE, + TEE_MALLOC_FILL_ZERO); + if (!in_buf) + return PKCS11_CKR_DEVICE_MEMORY; + + TEE_MemMove(in_buf, (uint8_t *)data + in_sz, align); + in_sz = TEE_AES_BLOCK_SIZE; + } else { + in_buf = data; + in_sz = data_sz; + } + + res = TEE_CipherDoFinal(proc->tee_op_handle, in_buf, in_sz, + tmp_buf, &tmp_sz); + if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { + *out_sz = tmp_sz; + if (align) + *out_sz += tmp_buf - (uint8_t *)out_buf; + } + + if (align) + TEE_Free(in_buf); + + return tee2pkcs_error(res); + default: + return PKCS11_CKR_MECHANISM_INVALID; + } + + return PKCS11_CKR_GENERAL_ERROR; +} + +enum pkcs11_rc unwrap_key_by_symm(struct pkcs11_session *session, void *data, + uint32_t data_sz, void **out_buf, + uint32_t *out_sz) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct active_processing *proc = session->processing; + size_t tmp_sz = 0; + + if (input_data_size_is_valid(proc, PKCS11_FUNCTION_DECRYPT, data_sz)) + return PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; + + switch (proc->mecha_type) { + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + *out_sz = 0; + res = TEE_CipherDoFinal(proc->tee_op_handle, data, data_sz, + NULL, &tmp_sz); + *out_sz = tmp_sz; + if (res != TEE_ERROR_SHORT_BUFFER) { + DMSG("TEE_CipherDoFinal() issue: %#"PRIx32, res); + return PKCS11_CKR_GENERAL_ERROR; + } + + *out_buf = TEE_Malloc(*out_sz, TEE_MALLOC_FILL_ZERO); + if (!*out_buf) + return PKCS11_CKR_DEVICE_MEMORY; + + res = TEE_CipherDoFinal(proc->tee_op_handle, data, data_sz, + *out_buf, &tmp_sz); + *out_sz = tmp_sz; + if (tee2pkcs_error(res)) { + TEE_Free(*out_buf); + *out_buf = NULL; + return PKCS11_CKR_WRAPPED_KEY_INVALID; + } + break; + default: + return PKCS11_CKR_MECHANISM_INVALID; + } + + return PKCS11_CKR_OK; +} diff --git a/optee/optee_os/ta/pkcs11/src/sanitize_object.c b/optee/optee_os/ta/pkcs11/src/sanitize_object.c new file mode 100644 index 0000000..5fdde55 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/sanitize_object.c @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "attributes.h" +#include "pkcs11_helpers.h" +#include "sanitize_object.h" +#include "serializer.h" +#include "token_capabilities.h" + +/* + * Functions to generate a serialized object. + * References are pointers to struct serializer. + */ + +bool sanitize_consistent_class_and_type(struct obj_attrs *attrs) +{ + switch (get_class(attrs)) { + case PKCS11_CKO_DATA: + case PKCS11_CKO_CERTIFICATE: + return true; + case PKCS11_CKO_SECRET_KEY: + return key_type_is_symm_key(get_key_type(attrs)); + case PKCS11_CKO_MECHANISM: + return mechanism_is_valid(get_mechanism_type(attrs)); + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_PRIVATE_KEY: + return key_type_is_asymm_key(get_key_type(attrs)); + case PKCS11_CKO_OTP_KEY: + case PKCS11_CKO_DOMAIN_PARAMETERS: + case PKCS11_CKO_HW_FEATURE: + default: + return false; + } + + return false; +} + +static enum pkcs11_rc read_attr_advance(void *buf, size_t blen, size_t *pos, + struct pkcs11_attribute_head *attr, + void **data) +{ + uint8_t *b = buf; + size_t data_pos = 0; + size_t next_pos = 0; + + if (ADD_OVERFLOW(*pos, sizeof(*attr), &data_pos) || data_pos > blen) + return PKCS11_CKR_FUNCTION_FAILED; + TEE_MemMove(attr, b + *pos, sizeof(*attr)); + + if (ADD_OVERFLOW(data_pos, attr->size, &next_pos) || next_pos > blen) + return PKCS11_CKR_FUNCTION_FAILED; + + *data = b + data_pos; + *pos = next_pos; + + return PKCS11_CKR_OK; +} + +/* Sanitize class/type in a client attribute list */ +static enum pkcs11_rc sanitize_class_and_type(struct obj_attrs **dst, void *src, + size_t src_size, + uint32_t class_hint, + uint32_t type_hint) +{ + uint32_t class_found = PKCS11_CKO_UNDEFINED_ID; + size_t pos = sizeof(struct pkcs11_object_head); + struct pkcs11_attribute_head cli_ref = { }; + uint32_t type_found = PKCS11_UNDEFINED_ID; + enum pkcs11_rc rc = PKCS11_CKR_OK; + void *data = NULL; + + while (pos != src_size) { + rc = read_attr_advance(src, src_size, &pos, &cli_ref, &data); + if (rc) + goto err; + + if (cli_ref.id == PKCS11_CKA_CLASS) { + uint32_t class = 0; + + if (cli_ref.size != sizeof(class)) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto err; + } + + TEE_MemMove(&class, data, sizeof(class)); + + if (class_found != PKCS11_CKO_UNDEFINED_ID && + class_found != class) { + EMSG("Conflicting class value"); + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto err; + } + + class_found = class; + continue; + } + + /* The attribute is a type-in-class */ + if (pkcs11_attr_is_type(cli_ref.id)) { + uint32_t type = 0; + + if (cli_ref.size != sizeof(type)) { + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto err; + } + + TEE_MemMove(&type, data, sizeof(type)); + + if (type_found != PKCS11_CKK_UNDEFINED_ID && + type_found != type) { + EMSG("Conflicting type-in-class value"); + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto err; + } + + type_found = type; + } + } + + if (class_found != PKCS11_CKO_UNDEFINED_ID) { + rc = add_attribute(dst, PKCS11_CKA_CLASS, + &class_found, sizeof(class_found)); + if (rc) + return rc; + } else { + if (class_hint != PKCS11_CKO_UNDEFINED_ID) { + rc = add_attribute(dst, PKCS11_CKA_CLASS, + &class_hint, sizeof(class_hint)); + if (rc) + return rc; + } + } + + if (type_found != PKCS11_UNDEFINED_ID) { + rc = add_attribute(dst, PKCS11_CKA_KEY_TYPE, + &type_found, sizeof(type_found)); + if (rc) + return rc; + } else { + if (type_hint != PKCS11_UNDEFINED_ID) { + rc = add_attribute(dst, PKCS11_CKA_KEY_TYPE, + &type_hint, sizeof(type_hint)); + if (rc) + return rc; + } + } + + return PKCS11_CKR_OK; + +err: + trace_attributes_from_api_head("bad-template", src, src_size); + + return rc; +} + +static enum pkcs11_rc sanitize_boolprops(struct obj_attrs **dst, void *src, + size_t src_size) +{ + bitstr_t bit_decl(seen_attrs, PKCS11_BOOLPROPS_MAX_COUNT) = { 0 }; + bitstr_t bit_decl(boolprops, PKCS11_BOOLPROPS_MAX_COUNT) = { 0 }; + size_t pos = sizeof(struct pkcs11_object_head); + struct pkcs11_attribute_head cli_ref = { }; + enum pkcs11_rc rc = PKCS11_CKR_OK; + bool value = false; + void *data = NULL; + int idx = 0; + + /* + * We're keeping track of seen boolean attributes in the bitstring + * seen_attrs. The bitstring boolprops holds the recorded value + * once seen_attrs has been updated. + */ + + while (pos != src_size) { + rc = read_attr_advance(src, src_size, &pos, &cli_ref, &data); + if (rc) + return rc; + + idx = pkcs11_attr2boolprop_shift(cli_ref.id); + if (idx < 0) + continue; /* skipping non-boolean attributes */ + + if (idx >= PKCS11_BOOLPROPS_MAX_COUNT || + cli_ref.size != sizeof(uint8_t)) + return PKCS11_CKR_FUNCTION_FAILED; + + value = *(uint8_t *)data; + + /* + * If this attribute has already been seen, check that it + * still holds the same value as last time. + */ + if (bit_test(seen_attrs, idx) && + value != (bool)bit_test(boolprops, idx)) + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + + if (value) + bit_set(boolprops, idx); + + if (!bit_test(seen_attrs, idx)) { + uint8_t pkcs11_bool = value; + + rc = add_attribute(dst, cli_ref.id, &pkcs11_bool, + sizeof(pkcs11_bool)); + if (rc) + return rc; + } + bit_set(seen_attrs, idx); + } + + return PKCS11_CKR_OK; +} + +static uint32_t sanitize_indirect_attr(struct obj_attrs **dst, + struct pkcs11_attribute_head *cli_ref, + char *data) +{ + struct obj_attrs *obj2 = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(pkcs11_attr_has_indirect_attributes(cli_ref->id)); + + /* Build a new serial object while sanitizing the attributes list */ + rc = sanitize_client_object(&obj2, data, cli_ref->size, + PKCS11_CKO_UNDEFINED_ID, + PKCS11_UNDEFINED_ID); + if (rc) + goto out; + + rc = add_attribute(dst, cli_ref->id, obj2, + sizeof(*obj2) + obj2->attrs_size); +out: + TEE_Free(obj2); + return rc; +} + +enum pkcs11_rc sanitize_client_object(struct obj_attrs **dst, void *src, + size_t size, uint32_t class_hint, + uint32_t type_hint) +{ + struct pkcs11_attribute_head cli_ref = { }; + struct pkcs11_object_head head = { }; + enum pkcs11_rc rc = PKCS11_CKR_OK; + size_t pos = sizeof(head); + size_t sz_from_hdr = 0; + void *data = NULL; + + if (size < sizeof(head)) + return PKCS11_CKR_ARGUMENTS_BAD; + + TEE_MemMove(&head, src, sizeof(head)); + + if (ADD_OVERFLOW(sizeof(head), head.attrs_size, &sz_from_hdr) || + size < sz_from_hdr) + return PKCS11_CKR_ARGUMENTS_BAD; + + rc = init_attributes_head(dst); + if (rc) + return rc; + + rc = sanitize_class_and_type(dst, src, sz_from_hdr, class_hint, + type_hint); + if (rc) + return rc; + + rc = sanitize_boolprops(dst, src, sz_from_hdr); + if (rc) + return rc; + + while (pos != sz_from_hdr) { + rc = read_attr_advance(src, sz_from_hdr, &pos, &cli_ref, &data); + if (rc) + return rc; + + if (cli_ref.id == PKCS11_CKA_CLASS || + pkcs11_attr_is_type(cli_ref.id) || + pkcs11_attr_is_boolean(cli_ref.id)) + continue; + + if (pkcs11_attr_has_indirect_attributes(cli_ref.id)) { + rc = sanitize_indirect_attr(dst, &cli_ref, data); + if (rc) + return rc; + + continue; + } + + if (!valid_pkcs11_attribute_id(cli_ref.id, cli_ref.size)) { + EMSG("Invalid attribute id %#"PRIx32, cli_ref.id); + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + rc = add_attribute(dst, cli_ref.id, data, cli_ref.size); + if (rc) + return rc; + } + + return rc; +} + +/* + * Debug: dump object attribute array to output trace + */ + +static void __trace_attributes(char *prefix, void *src, void *end) +{ + size_t next = 0; + char *prefix2 = NULL; + size_t prefix_len = strlen(prefix); + char *cur = src; + + /* append 4 spaces to the prefix plus terminal '\0' */ + prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO); + if (!prefix2) + return; + + TEE_MemMove(prefix2, prefix, prefix_len + 1); + TEE_MemFill(prefix2 + prefix_len, ' ', 4); + *(prefix2 + prefix_len + 4) = '\0'; + + for (; cur < (char *)end; cur += next) { + struct pkcs11_attribute_head pkcs11_ref; + uint8_t data[4] = { 0 }; + uint32_t data_u32 = 0; + char *start = NULL; + + TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); + TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref), + MIN(pkcs11_ref.size, sizeof(data))); + TEE_MemMove(&data_u32, cur + sizeof(pkcs11_ref), + sizeof(data_u32)); + + next = sizeof(pkcs11_ref) + pkcs11_ref.size; + + DMSG_RAW("%s Attr %s / %s (%#04"PRIx32" %"PRIu32"-byte)", + prefix, id2str_attr(pkcs11_ref.id), + id2str_attr_value(pkcs11_ref.id, pkcs11_ref.size, + cur + sizeof(pkcs11_ref)), + pkcs11_ref.id, pkcs11_ref.size); + + switch (pkcs11_ref.size) { + case 0: + break; + case 1: + DMSG_RAW("%s Attr byte value: %02x", prefix, data[0]); + break; + case 2: + DMSG_RAW("%s Attr byte value: %02x %02x", + prefix, data[0], data[1]); + break; + case 3: + DMSG_RAW("%s Attr byte value: %02x %02x %02x", + prefix, data[0], data[1], data[2]); + break; + case 4: + DMSG_RAW("%s Attr byte value: %02x %02x %02x %02x", + prefix, data[0], data[1], data[2], data[3]); + break; + default: + DMSG_RAW("%s Attr byte value: %02x %02x %02x %02x ...", + prefix, data[0], data[1], data[2], data[3]); + break; + } + + switch (pkcs11_ref.id) { + case PKCS11_CKA_WRAP_TEMPLATE: + case PKCS11_CKA_UNWRAP_TEMPLATE: + case PKCS11_CKA_DERIVE_TEMPLATE: + start = cur + sizeof(pkcs11_ref); + trace_attributes_from_api_head(prefix2, start, + (char *)end - start); + break; + default: + break; + } + } + + /* Sanity */ + if (cur != (char *)end) + EMSG("Warning: unexpected alignment issue"); + + TEE_Free(prefix2); +} + +void trace_attributes_from_api_head(const char *prefix, void *ref, size_t size) +{ + struct pkcs11_object_head head = { }; + char *pre = NULL; + size_t offset = 0; + + TEE_MemMove(&head, ref, sizeof(head)); + + if (size > sizeof(head) + head.attrs_size) { + EMSG("template overflows client buffer (%zu/%zu)", + size, sizeof(head) + head.attrs_size); + return; + } + + pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO); + if (!pre) { + EMSG("%s: out of memory", prefix); + return; + } + if (prefix) + TEE_MemMove(pre, prefix, strlen(prefix)); + + DMSG_RAW("%s,--- (serial object) Attributes list --------", pre); + DMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes", + pre, head.attrs_count, head.attrs_size); + + offset = sizeof(head); + pre[prefix ? strlen(prefix) : 0] = '|'; + __trace_attributes(pre, (char *)ref + offset, + (char *)ref + offset + head.attrs_size); + + DMSG_RAW("%s`-----------------------", prefix ? prefix : ""); + + TEE_Free(pre); +} diff --git a/optee/optee_os/ta/pkcs11/src/sanitize_object.h b/optee/optee_os/ta/pkcs11/src/sanitize_object.h new file mode 100644 index 0000000..6b170a2 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/sanitize_object.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#ifndef PKCS11_TA_SANITIZE_OBJECT_H +#define PKCS11_TA_SANITIZE_OBJECT_H + +#include "serializer.h" + +/* + * sanitize_consistent_class_and_type - Check object type matches object class + * + * @attrs - object attributes + * Return true if class/type matches, else return false + */ +bool sanitize_consistent_class_and_type(struct obj_attrs *attrs); + +/** + * sanitize_client_object - Setup a serializer from a serialized object + * + * @dst - output structure tracking the generated serial object + * @head - pointer to the formatted serialized object (its head) + * @size - byte size of the serialized binary blob + * @class_hint - Hint for class to be added to template if not presnet + * in serialized object. + * @type_hint - Hint for type to be added to template if not presnet + * in serialized object. + * + * This function copies an attribute list from a client API attribute head + * into a PKCS11 TA internal attribute structure. It generates a serialized + * attribute list with a consistent format and identified attribute IDs. + * + * @head points to a blob starting with a pkcs11 attribute header. + * @head may point to an unaligned address. + * This function allocates, fills and returns a serialized attribute list + * into a serializer container. + */ +enum pkcs11_rc sanitize_client_object(struct obj_attrs **dst, void *head, + size_t size, uint32_t class_hint, + uint32_t type_hint); + +/* Debug: dump attribute content as debug traces */ +void trace_attributes_from_api_head(const char *prefix, void *ref, size_t size); + +#endif /*PKCS11_TA_SANITIZE_OBJECT_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/serializer.c b/optee/optee_os/ta/pkcs11/src/serializer.c new file mode 100644 index 0000000..dac930a --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/serializer.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pkcs11_token.h" +#include "serializer.h" + +/* + * Util routines for serializes unformatted arguments in a client memref + */ +void serialargs_init(struct serialargs *args, void *in, size_t size) +{ + args->start = in; + args->next = in; + args->size = size; +} + +enum pkcs11_rc serialargs_get(struct serialargs *args, void *out, size_t size) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + void *src = NULL; + + rc = serialargs_get_ptr(args, &src, size); + if (!rc) + TEE_MemMove(out, src, size); + + return rc; +} + +static enum pkcs11_rc alloc_and_get(struct serialargs *args, char *orig_next, + const void *buf0, size_t buf0_sz, + void **out, size_t size) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint8_t *ptr = NULL; + void *src = NULL; + size_t sz = 0; + + if (ADD_OVERFLOW(buf0_sz, size, &sz)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!sz) { + *out = NULL; + return PKCS11_CKR_OK; + } + + rc = serialargs_get_ptr(args, &src, size); + if (rc) + return rc; + + ptr = TEE_Malloc(sz, TEE_MALLOC_FILL_ZERO); + if (!ptr) { + args->next = orig_next; + return PKCS11_CKR_DEVICE_MEMORY; + } + + TEE_MemMove(ptr, buf0, buf0_sz); + TEE_MemMove(ptr + buf0_sz, src, size); + + *out = ptr; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc serialargs_alloc_and_get(struct serialargs *args, + void **out, size_t size) +{ + return alloc_and_get(args, args->next, NULL, 0, out, size); +} + +enum pkcs11_rc serialargs_get_ptr(struct serialargs *args, void **out, + size_t size) +{ + void *ptr = args->next; + vaddr_t next_end = 0; + + if (ADD_OVERFLOW((vaddr_t)args->next, size, &next_end)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!size) { + *out = NULL; + return PKCS11_CKR_OK; + } + + if ((char *)next_end > args->start + args->size) { + EMSG("arg too short: full %zd, remain %zd, expect %zd", + args->size, args->size - (args->next - args->start), size); + return PKCS11_CKR_ARGUMENTS_BAD; + } + + args->next += size; + *out = ptr; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc +serialargs_alloc_get_one_attribute(struct serialargs *args, + struct pkcs11_attribute_head **out) +{ + struct pkcs11_attribute_head head = { }; + enum pkcs11_rc rc = PKCS11_CKR_OK; + char *orig_next = args->next; + void *p = NULL; + + rc = serialargs_get(args, &head, sizeof(head)); + if (rc) + return rc; + + rc = alloc_and_get(args, orig_next, &head, sizeof(head), &p, head.size); + if (rc) + return rc; + + *out = p; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc serialargs_alloc_get_attributes(struct serialargs *args, + struct pkcs11_object_head **out) +{ + struct pkcs11_object_head attr = { }; + enum pkcs11_rc rc = PKCS11_CKR_OK; + char *orig_next = args->next; + void *p = NULL; + + rc = serialargs_get(args, &attr, sizeof(attr)); + if (rc) + return rc; + + rc = alloc_and_get(args, orig_next, &attr, sizeof(attr), &p, + attr.attrs_size); + if (rc) + return rc; + + *out = p; + + return PKCS11_CKR_OK; +} + +bool serialargs_remaining_bytes(struct serialargs *args) +{ + return args->next < args->start + args->size; +} + +enum pkcs11_rc serialargs_get_session_from_handle(struct serialargs *args, + struct pkcs11_client *client, + struct pkcs11_session **sess) +{ + uint32_t rv = PKCS11_CKR_GENERAL_ERROR; + uint32_t session_handle = 0; + struct pkcs11_session *session = NULL; + + rv = serialargs_get(args, &session_handle, sizeof(uint32_t)); + if (rv) + return rv; + + session = pkcs11_handle2session(session_handle, client); + if (!session) + return PKCS11_CKR_SESSION_HANDLE_INVALID; + + *sess = session; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc serialize(char **bstart, size_t *blen, void *data, size_t len) +{ + char *buf = NULL; + size_t nlen = 0; + + if (ADD_OVERFLOW(*blen, len, &nlen)) + return PKCS11_CKR_ARGUMENTS_BAD; + + buf = TEE_Realloc(*bstart, nlen); + if (!buf) + return PKCS11_CKR_DEVICE_MEMORY; + + TEE_MemMove(buf + *blen, data, len); + + *blen = nlen; + *bstart = buf; + + return PKCS11_CKR_OK; +} + diff --git a/optee/optee_os/ta/pkcs11/src/serializer.h b/optee/optee_os/ta/pkcs11/src/serializer.h new file mode 100644 index 0000000..3e6fe09 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/serializer.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#ifndef PKCS11_TA_SERIALIZER_H +#define PKCS11_TA_SERIALIZER_H + +#include +#include +#include + +struct pkcs11_client; +struct pkcs11_session; + +/* + * Util routines for serializes unformated arguments in a client memref + */ +struct serialargs { + char *start; + char *next; + size_t size; +}; + +struct pkcs11_client; +struct pkcs11_session; + +/* + * serialargs_init() - Initialize with a new input buffer + * @args: serializing state + * @in: input buffer + * @size: size of the input buffer + */ +void serialargs_init(struct serialargs *args, void *in, size_t size); + +/* + * serialargs_get() - copy out a chunk of data and advance + * @args: serializing state + * @out: output buffer + * @sz: number of bytes to copy to output buffer + * + * Returns PKCS11_CKR_OK on success or PKCS11_CKR_ARGUMENTS_BAD on failure. + */ +enum pkcs11_rc serialargs_get(struct serialargs *args, void *out, size_t sz); + +/* + * serialargs_get_u32() - copy out a uint32_t and advance + * @args: serializing state + * @out: output buffer + * + * Returns PKCS11_CKR_OK on success or PKCS11_CKR_ARGUMENTS_BAD on failure. + */ +static inline enum pkcs11_rc serialargs_get_u32(struct serialargs *args, + uint32_t *out) +{ + return serialargs_get(args, out, sizeof(*out)); +} + +/* + * serialargs_get_ptr() - get a pointer to a chunk of data and advance + * @args: serializing state + * @out: Pointer to the data retrieved in *@out + * @size: Number of bytes to advance + * + * Returns PKCS11_CKR_OK on success or PKCS11_CKR_ARGUMENTS_BAD on failure. + */ +enum pkcs11_rc serialargs_get_ptr(struct serialargs *args, void **out, + size_t size); + +/* + * serialargs_alloc_get_one_attribute() - allocate and extract one attribute + * @args: serializing state + * @out: Pointer to the allocated and extracted attribute in *@out + * + * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on + * failure. + */ +enum pkcs11_rc +serialargs_alloc_get_one_attribute(struct serialargs *args, + struct pkcs11_attribute_head **out); + +/* + * serialargs_alloc_get_attributes() - allocate and extract an object + * @args: serializing state + * @out: Pointer to the allocated and extracted object in *@out + * + * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on + * failure. + */ +enum pkcs11_rc serialargs_alloc_get_attributes(struct serialargs *args, + struct pkcs11_object_head **out); + +/* + * serialargs_alloc_and_get() - allocate and extract data + * @args: serializing state + * @out: Pointer to the allocated and extracted data in *@out + * @size: Number of bytes to extract + * + * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on + * failure. + */ +enum pkcs11_rc serialargs_alloc_and_get(struct serialargs *args, + void **out, size_t size); + +/* + * serialargs_remaining_bytes() - check for remaining bytes + * @args: serializing state + * + * Returns true if there are remaining bytes in @args or false if all bytes + * are consumed. + */ +bool serialargs_remaining_bytes(struct serialargs *args); + +/* + * serialargs_get_session_from_handle() - extract and verify session + * @args: serializing state + * @client: client state + * @sess: The retrieved session handle is available in *@sess + * + * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on + * failure. + */ +enum pkcs11_rc serialargs_get_session_from_handle(struct serialargs *args, + struct pkcs11_client *client, + struct pkcs11_session **sess); + +/* + * serialize() - append data into a serialized buffer + * @bstart: points to start of a buffer or NULL, *@bstart is updated + * with the new buffer if changed + * @blen: size of the *@bstart buffer, updated when data is added + * @data: data to appen to the buffer + * @len: size of the @data buffer + * + * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on + * failure. + */ +enum pkcs11_rc serialize(char **bstart, size_t *blen, void *data, size_t len); + +#endif /*PKCS11_TA_SERIALIZER_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/sub.mk b/optee/optee_os/ta/pkcs11/src/sub.mk new file mode 100644 index 0000000..5dfbc2b --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/sub.mk @@ -0,0 +1,18 @@ +srcs-y += attributes.c +srcs-y += entry.c +srcs-y += handle.c +srcs-y += object.c +srcs-y += persistent_token.c +srcs-y += pkcs11_attributes.c +srcs-y += pkcs11_helpers.c +srcs-y += pkcs11_token.c +srcs-y += processing.c +srcs-y += processing_aes.c +srcs-y += processing_asymm.c +srcs-y += processing_digest.c +srcs-y += processing_ec.c +srcs-y += processing_rsa.c +srcs-y += processing_symm.c +srcs-y += sanitize_object.c +srcs-y += serializer.c +srcs-y += token_capabilities.c diff --git a/optee/optee_os/ta/pkcs11/src/token_capabilities.c b/optee/optee_os/ta/pkcs11/src/token_capabilities.c new file mode 100644 index 0000000..e76c1df --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/token_capabilities.c @@ -0,0 +1,462 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include + +#include "pkcs11_helpers.h" +#include "token_capabilities.h" + +#define ALLOWED_PKCS11_CKFM \ + (PKCS11_CKFM_ENCRYPT | PKCS11_CKFM_DECRYPT | \ + PKCS11_CKFM_DERIVE | PKCS11_CKFM_DIGEST | \ + PKCS11_CKFM_SIGN | PKCS11_CKFM_SIGN_RECOVER | \ + PKCS11_CKFM_VERIFY | PKCS11_CKFM_VERIFY_RECOVER | \ + PKCS11_CKFM_GENERATE | PKCS11_CKFM_GENERATE_KEY_PAIR | \ + PKCS11_CKFM_WRAP | PKCS11_CKFM_UNWRAP) + +/* + * Definition of supported processings for a PKCS#11 mechanisms + * @id: Mechanism ID + * @flags: Valid PKCS11_CKFM_* for a mechanism as per PKCS#11 + * @one_shot: true of mechanism can be used for a one-short processing + * @string: Helper string of the mechanism ID for debug purpose + */ +struct pkcs11_mechachism_modes { + uint32_t id; + uint32_t flags; + bool one_shot; +#if CFG_TEE_TA_LOG_LEVEL > 0 + const char *string; +#endif +}; + +#if CFG_TEE_TA_LOG_LEVEL > 0 +#define MECHANISM(_label, _flags, _single_part) \ + { \ + .id = _label, \ + .one_shot = (_single_part), \ + .flags = (_flags), \ + .string = #_label, \ + } +#else +#define MECHANISM(_label, _flags, _single_part) \ + { \ + .id = _label, \ + .one_shot = (_single_part), \ + .flags = (_flags), \ + } +#endif + +#define SINGLE_PART_ONLY true +#define ANY_PART false + +#define CKFM_CIPHER (PKCS11_CKFM_ENCRYPT | PKCS11_CKFM_DECRYPT) +#define CKFM_WRAP_UNWRAP (PKCS11_CKFM_WRAP | PKCS11_CKFM_UNWRAP) +#define CKFM_CIPHER_WRAP (CKFM_CIPHER | CKFM_WRAP_UNWRAP) +#define CKFM_CIPHER_WRAP_DERIVE (CKFM_CIPHER_WRAP | PKCS11_CKFM_DERIVE) +#define CKFM_AUTH_NO_RECOVER (PKCS11_CKFM_SIGN | PKCS11_CKFM_VERIFY) +#define CKFM_AUTH_WITH_RECOVER (PKCS11_CKFM_SIGN_RECOVER | \ + PKCS11_CKFM_VERIFY_RECOVER) + +/* PKCS#11 specificies permitted operation for each mechanism */ +static const struct pkcs11_mechachism_modes pkcs11_modes[] = { + /* AES */ + MECHANISM(PKCS11_CKM_AES_ECB, CKFM_CIPHER_WRAP, ANY_PART), + MECHANISM(PKCS11_CKM_AES_CBC, CKFM_CIPHER_WRAP, ANY_PART), + MECHANISM(PKCS11_CKM_AES_CBC_PAD, CKFM_CIPHER_WRAP, ANY_PART), + MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER_WRAP, ANY_PART), + MECHANISM(PKCS11_CKM_AES_CTR, CKFM_CIPHER_WRAP, ANY_PART), + MECHANISM(PKCS11_CKM_AES_CMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_AES_CMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE, + ANY_PART), + MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE, + ANY_PART), + MECHANISM(PKCS11_CKM_AES_KEY_GEN, PKCS11_CKFM_GENERATE, ANY_PART), + MECHANISM(PKCS11_CKM_GENERIC_SECRET_KEY_GEN, PKCS11_CKFM_GENERATE, + ANY_PART), + /* Digest */ + MECHANISM(PKCS11_CKM_MD5, PKCS11_CKFM_DIGEST, ANY_PART), + MECHANISM(PKCS11_CKM_SHA_1, PKCS11_CKFM_DIGEST, ANY_PART), + MECHANISM(PKCS11_CKM_SHA224, PKCS11_CKFM_DIGEST, ANY_PART), + MECHANISM(PKCS11_CKM_SHA256, PKCS11_CKFM_DIGEST, ANY_PART), + MECHANISM(PKCS11_CKM_SHA384, PKCS11_CKFM_DIGEST, ANY_PART), + MECHANISM(PKCS11_CKM_SHA512, PKCS11_CKFM_DIGEST, ANY_PART), + /* HMAC */ + MECHANISM(PKCS11_CKM_MD5_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA_1_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA224_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA256_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA384_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA512_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_MD5_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA_1_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, + ANY_PART), + MECHANISM(PKCS11_CKM_SHA224_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, + ANY_PART), + MECHANISM(PKCS11_CKM_SHA256_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, + ANY_PART), + MECHANISM(PKCS11_CKM_SHA384_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, + ANY_PART), + MECHANISM(PKCS11_CKM_SHA512_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, + ANY_PART), + /* EC */ + MECHANISM(PKCS11_CKM_EC_KEY_PAIR_GEN, PKCS11_CKFM_GENERATE_KEY_PAIR, + ANY_PART), + MECHANISM(PKCS11_CKM_ECDH1_DERIVE, PKCS11_CKFM_DERIVE, + ANY_PART), + MECHANISM(PKCS11_CKM_ECDSA, CKFM_AUTH_NO_RECOVER, SINGLE_PART_ONLY), + MECHANISM(PKCS11_CKM_ECDSA_SHA1, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_ECDSA_SHA224, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_ECDSA_SHA256, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_ECDSA_SHA384, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_ECDSA_SHA512, CKFM_AUTH_NO_RECOVER, ANY_PART), + /* EDDSA */ + MECHANISM(PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN, + PKCS11_CKFM_GENERATE_KEY_PAIR, ANY_PART), + MECHANISM(PKCS11_CKM_EDDSA, CKFM_AUTH_NO_RECOVER, ANY_PART), + /* RSA */ + MECHANISM(PKCS11_CKM_RSA_AES_KEY_WRAP, CKFM_CIPHER_WRAP, + SINGLE_PART_ONLY), + MECHANISM(PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN, + PKCS11_CKFM_GENERATE_KEY_PAIR, ANY_PART), + MECHANISM(PKCS11_CKM_RSA_PKCS, CKFM_CIPHER_WRAP | CKFM_AUTH_NO_RECOVER | + CKFM_AUTH_WITH_RECOVER, SINGLE_PART_ONLY), + MECHANISM(PKCS11_CKM_RSA_PKCS_OAEP, CKFM_CIPHER_WRAP, + SINGLE_PART_ONLY), + MECHANISM(PKCS11_CKM_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, + SINGLE_PART_ONLY), + MECHANISM(PKCS11_CKM_MD5_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA256_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA384_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA512_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA256_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, + ANY_PART), + MECHANISM(PKCS11_CKM_SHA384_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, + ANY_PART), + MECHANISM(PKCS11_CKM_SHA512_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, + ANY_PART), + MECHANISM(PKCS11_CKM_SHA224_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), + MECHANISM(PKCS11_CKM_SHA224_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, + ANY_PART), +}; + +#if CFG_TEE_TA_LOG_LEVEL > 0 +const char *mechanism_string_id(enum pkcs11_mechanism_id id) +{ + const size_t offset = sizeof("PKCS11_CKM_") - 1; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) + if (pkcs11_modes[n].id == id) + return pkcs11_modes[n].string + offset; + + return "Unknown ID"; +} +#endif /*CFG_TEE_TA_LOG_LEVEL*/ + +/* + * Return true if @id is a valid mechanism ID + */ +bool mechanism_is_valid(enum pkcs11_mechanism_id id) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) + if (id == pkcs11_modes[n].id) + return true; + + return false; +} + +/* + * Return true if mechanism ID is valid and flags matches PKCS#11 compliancy + */ +bool __maybe_unused mechanism_flags_complies_pkcs11(uint32_t mechanism_type, + uint32_t flags) +{ + size_t n = 0; + + assert((flags & ~ALLOWED_PKCS11_CKFM) == 0); + + for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) { + if (pkcs11_modes[n].id == mechanism_type) { + if (flags & ~pkcs11_modes[n].flags) + EMSG("%s flags: 0x%"PRIx32" vs 0x%"PRIx32, + id2str_mechanism(mechanism_type), + flags, pkcs11_modes[n].flags); + + return (flags & ~pkcs11_modes[n].flags) == 0; + } + } + + /* Mechanism ID unexpectedly not found */ + return false; +} + +bool mechanism_is_one_shot_only(uint32_t mechanism_type) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) + if (pkcs11_modes[n].id == mechanism_type) + return pkcs11_modes[n].one_shot; + + /* Mechanism ID unexpectedly not found */ + TEE_Panic(PKCS11_RV_NOT_FOUND); + /* Dummy return to keep compiler happy */ + return false; +} + +/* + * Field single_part_only is unused from array token_mechanism[], hence + * simply use ANY_PART for all mechanism there. + */ +#define TA_MECHANISM(_label, _flags) MECHANISM((_label), (_flags), ANY_PART) + +/* + * Arrays that centralizes the IDs and processing flags for mechanisms + * supported by each embedded token. + */ +const struct pkcs11_mechachism_modes token_mechanism[] = { + TA_MECHANISM(PKCS11_CKM_AES_ECB, CKFM_CIPHER_WRAP), + TA_MECHANISM(PKCS11_CKM_AES_CBC, CKFM_CIPHER_WRAP), + TA_MECHANISM(PKCS11_CKM_AES_CTR, CKFM_CIPHER), + TA_MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER), + TA_MECHANISM(PKCS11_CKM_AES_CMAC, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_AES_CMAC_GENERAL, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE), + TA_MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE), + TA_MECHANISM(PKCS11_CKM_ECDH1_DERIVE, PKCS11_CKFM_DERIVE), + TA_MECHANISM(PKCS11_CKM_AES_KEY_GEN, PKCS11_CKFM_GENERATE), + TA_MECHANISM(PKCS11_CKM_GENERIC_SECRET_KEY_GEN, PKCS11_CKFM_GENERATE), + TA_MECHANISM(PKCS11_CKM_MD5, PKCS11_CKFM_DIGEST), + TA_MECHANISM(PKCS11_CKM_SHA_1, PKCS11_CKFM_DIGEST), + TA_MECHANISM(PKCS11_CKM_SHA224, PKCS11_CKFM_DIGEST), + TA_MECHANISM(PKCS11_CKM_SHA256, PKCS11_CKFM_DIGEST), + TA_MECHANISM(PKCS11_CKM_SHA384, PKCS11_CKFM_DIGEST), + TA_MECHANISM(PKCS11_CKM_SHA512, PKCS11_CKFM_DIGEST), + TA_MECHANISM(PKCS11_CKM_MD5_HMAC, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA_1_HMAC, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA224_HMAC, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA256_HMAC, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA384_HMAC, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA512_HMAC, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_MD5_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA_1_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA224_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA256_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA384_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA512_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_EC_KEY_PAIR_GEN, + PKCS11_CKFM_GENERATE_KEY_PAIR), + TA_MECHANISM(PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN, + PKCS11_CKFM_GENERATE_KEY_PAIR), + TA_MECHANISM(PKCS11_CKM_ECDSA, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_ECDSA_SHA1, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_ECDSA_SHA224, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_ECDSA_SHA256, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_ECDSA_SHA384, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_ECDSA_SHA512, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_EDDSA, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_RSA_AES_KEY_WRAP, CKFM_CIPHER_WRAP), + TA_MECHANISM(PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN, + PKCS11_CKFM_GENERATE_KEY_PAIR), + TA_MECHANISM(PKCS11_CKM_RSA_PKCS, CKFM_CIPHER | CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_MD5_RSA_PKCS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_RSA_PKCS_OAEP, CKFM_CIPHER), + TA_MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA256_RSA_PKCS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA384_RSA_PKCS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA512_RSA_PKCS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA256_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA384_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA512_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA224_RSA_PKCS, CKFM_AUTH_NO_RECOVER), + TA_MECHANISM(PKCS11_CKM_SHA224_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), +}; + +/* + * tee_malloc_mechanism_array - Allocate and fill array of supported mechanisms + * @count: [in] [out] Pointer to number of mechanism IDs in client resource + * Return allocated array of the supported mechanism IDs + * + * Allocates array with 32bit cells mechanism IDs for the supported ones only + * if *@count covers number mechanism IDs exposed. + */ +uint32_t *tee_malloc_mechanism_list(size_t *out_count) +{ + size_t n = 0; + size_t count = 0; + uint32_t *array = NULL; + + for (n = 0; n < ARRAY_SIZE(token_mechanism); n++) + if (token_mechanism[n].flags) + count++; + + if (*out_count >= count) + array = TEE_Malloc(count * sizeof(*array), + TEE_USER_MEM_HINT_NO_FILL_ZERO); + + *out_count = count; + + if (!array) + return NULL; + + for (n = 0; n < ARRAY_SIZE(token_mechanism); n++) { + if (token_mechanism[n].flags) { + count--; + array[count] = token_mechanism[n].id; + } + } + assert(!count); + + return array; +} + +uint32_t mechanism_supported_flags(enum pkcs11_mechanism_id id) +{ + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(token_mechanism); n++) { + if (id == token_mechanism[n].id) { + uint32_t flags = token_mechanism[n].flags; + + assert(mechanism_flags_complies_pkcs11(id, flags)); + return flags; + } + } + + return 0; +} + +void pkcs11_mechanism_supported_key_sizes(uint32_t proc_id, + uint32_t *min_key_size, + uint32_t *max_key_size) +{ + switch (proc_id) { + case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: + /* This mechanism expects the keysize to be returned in bits */ + *min_key_size = 1; /* in bits */ + *max_key_size = 4096; /* in bits */ + break; + case PKCS11_CKM_MD5_HMAC: + case PKCS11_CKM_MD5_HMAC_GENERAL: + *min_key_size = 8; + *max_key_size = 64; + break; + case PKCS11_CKM_SHA_1_HMAC: + case PKCS11_CKM_SHA_1_HMAC_GENERAL: + *min_key_size = 10; + *max_key_size = 64; + break; + case PKCS11_CKM_SHA224_HMAC: + case PKCS11_CKM_SHA224_HMAC_GENERAL: + *min_key_size = 14; + *max_key_size = 64; + break; + case PKCS11_CKM_SHA256_HMAC: + case PKCS11_CKM_SHA256_HMAC_GENERAL: + *min_key_size = 24; + *max_key_size = 128; + break; + case PKCS11_CKM_SHA384_HMAC: + case PKCS11_CKM_SHA384_HMAC_GENERAL: + *min_key_size = 32; + *max_key_size = 128; + break; + case PKCS11_CKM_SHA512_HMAC: + case PKCS11_CKM_SHA512_HMAC_GENERAL: + *min_key_size = 32; + *max_key_size = 128; + break; + case PKCS11_CKM_AES_KEY_GEN: + case PKCS11_CKM_AES_ECB: + case PKCS11_CKM_AES_CBC: + case PKCS11_CKM_AES_CBC_PAD: + case PKCS11_CKM_AES_CTR: + case PKCS11_CKM_AES_CTS: + case PKCS11_CKM_AES_CMAC: + case PKCS11_CKM_AES_CMAC_GENERAL: + *min_key_size = 16; + *max_key_size = 32; + break; + case PKCS11_CKM_EC_KEY_PAIR_GEN: + case PKCS11_CKM_ECDSA: + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + case PKCS11_CKM_ECDH1_DERIVE: + *min_key_size = 160; /* in bits */ + *max_key_size = 521; /* in bits */ + break; + case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: + case PKCS11_CKM_EDDSA: + *min_key_size = 256; /* in bits */ + *max_key_size = 448; /* in bits */ + break; + case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: + case PKCS11_CKM_RSA_PKCS: + case PKCS11_CKM_MD5_RSA_PKCS: + case PKCS11_CKM_SHA1_RSA_PKCS: + case PKCS11_CKM_RSA_PKCS_OAEP: + case PKCS11_CKM_SHA1_RSA_PKCS_PSS: + case PKCS11_CKM_SHA256_RSA_PKCS: + case PKCS11_CKM_SHA384_RSA_PKCS: + case PKCS11_CKM_SHA512_RSA_PKCS: + case PKCS11_CKM_SHA256_RSA_PKCS_PSS: + case PKCS11_CKM_SHA384_RSA_PKCS_PSS: + case PKCS11_CKM_SHA512_RSA_PKCS_PSS: + case PKCS11_CKM_SHA224_RSA_PKCS: + case PKCS11_CKM_SHA224_RSA_PKCS_PSS: + *min_key_size = 256; /* in bits */ + *max_key_size = 4096; /* in bits */ + break; + default: + *min_key_size = 0; + *max_key_size = 0; + break; + } +} + +void mechanism_supported_key_sizes_bytes(uint32_t proc_id, + uint32_t *min_key_size, + uint32_t *max_key_size) +{ + pkcs11_mechanism_supported_key_sizes(proc_id, min_key_size, + max_key_size); + + switch (proc_id) { + case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: + case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: + case PKCS11_CKM_EC_KEY_PAIR_GEN: + case PKCS11_CKM_ECDSA: + case PKCS11_CKM_EDDSA: + case PKCS11_CKM_ECDSA_SHA1: + case PKCS11_CKM_ECDSA_SHA224: + case PKCS11_CKM_ECDSA_SHA256: + case PKCS11_CKM_ECDSA_SHA384: + case PKCS11_CKM_ECDSA_SHA512: + case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: + /* Size is in bits -> convert to bytes and ceil */ + *min_key_size = ROUNDUP(*min_key_size, 8) / 8; + *max_key_size = ROUNDUP(*max_key_size, 8) / 8; + break; + default: + /* Size is already in bytes */ + break; + } +} diff --git a/optee/optee_os/ta/pkcs11/src/token_capabilities.h b/optee/optee_os/ta/pkcs11/src/token_capabilities.h new file mode 100644 index 0000000..7614006 --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/token_capabilities.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#ifndef TOKEN_CAPABILITIES_H +#define TOKEN_CAPABILITIES_H + +#include +#include +#include + +bool mechanism_flags_complies_pkcs11(uint32_t mechanism_type, uint32_t flags); + +bool mechanism_is_one_shot_only(uint32_t mechanism_type); + +bool mechanism_is_valid(enum pkcs11_mechanism_id id); + +#if CFG_TEE_TA_LOG_LEVEL > 0 +const char *mechanism_string_id(enum pkcs11_mechanism_id id); +#endif + +uint32_t *tee_malloc_mechanism_list(size_t *out_count); + +uint32_t mechanism_supported_flags(enum pkcs11_mechanism_id id); + +void pkcs11_mechanism_supported_key_sizes(uint32_t proc_id, + uint32_t *min_key_size, + uint32_t *max_key_size); + +void mechanism_supported_key_sizes_bytes(uint32_t proc_id, + uint32_t *min_key_size, + uint32_t *max_key_size); + +static inline bool mechanism_is_supported(enum pkcs11_mechanism_id id) +{ + return mechanism_supported_flags(id) != 0; +} + +#endif /*TOKEN_CAPABILITIES_H*/ diff --git a/optee/optee_os/ta/pkcs11/src/user_ta_header_defines.h b/optee/optee_os/ta/pkcs11/src/user_ta_header_defines.h new file mode 100644 index 0000000..4d468ca --- /dev/null +++ b/optee/optee_os/ta/pkcs11/src/user_ta_header_defines.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018-2019, Linaro Limited + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID PKCS11_TA_UUID + +#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_MULTI_SESSION | \ + TA_FLAG_INSTANCE_KEEP_ALIVE) + +#define TA_STACK_SIZE (4 * 1024) + +#define TA_DATA_SIZE CFG_PKCS11_TA_HEAP_SIZE + +#define TA_DESCRIPTION "PKCS#11 trusted application" +#define TA_VERSION TO_STR(PKCS11_TA_VERSION_MAJOR) "." \ + TO_STR(PKCS11_TA_VERSION_MINOR) "." \ + TO_STR(PKCS11_TA_VERSION_PATCH) + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_os/ta/pkcs11/sub.mk b/optee/optee_os/ta/pkcs11/sub.mk new file mode 100644 index 0000000..30dd13c --- /dev/null +++ b/optee/optee_os/ta/pkcs11/sub.mk @@ -0,0 +1,15 @@ +# Enable PKCS#11 TA's C_DigestKey support +CFG_PKCS11_TA_ALLOW_DIGEST_KEY ?= y + +# Enable PKCS#11 TA's TEE Identity based authentication support +CFG_PKCS11_TA_AUTH_TEE_IDENTITY ?= y + +# PKCS#11 TA heap size can be customized if 32kB is not enough +CFG_PKCS11_TA_HEAP_SIZE ?= (32 * 1024) + +# Defines the number of PKCS11 token implemented by the PKCS11 TA +CFG_PKCS11_TA_TOKEN_COUNT ?= 3 + +global-incdirs-y += include +global-incdirs-y += src +subdirs-y += src diff --git a/optee/optee_os/ta/pkcs11/user_ta.mk b/optee/optee_os/ta/pkcs11/user_ta.mk new file mode 100644 index 0000000..dda50cf --- /dev/null +++ b/optee/optee_os/ta/pkcs11/user_ta.mk @@ -0,0 +1,8 @@ +user-ta-uuid := fd02c9da-306c-48c7-a49c-bbd827ae86ee + +all: pkcs11-ta-verify-helpers + +.PHONY: pkcs11-ta-verify-helpers +pkcs11-ta-verify-helpers: + @$(cmd-echo-silent) ' CHK ' $@ + ${q}ta/pkcs11/scripts/verify-helpers.sh --quiet diff --git a/optee/optee_os/ta/ta.mk b/optee/optee_os/ta/ta.mk new file mode 100644 index 0000000..057a6ea --- /dev/null +++ b/optee/optee_os/ta/ta.mk @@ -0,0 +1,215 @@ +include mk/cleanvars.mk + +# Set current submodule (used for module specific flags compile result etc) +sm := $(ta-target) +sm-$(sm) := y + +# Setup compiler for this sub module +COMPILER_$(sm) ?= $(COMPILER) +include mk/$(COMPILER_$(sm)).mk + +# +# Config flags from mk/config.mk +# + +ta-stackp-cflags-$(CFG_TA_STACK_PROTECTOR) := -fstack-protector +ta-stackp-cflags-$(CFG_TA_STACK_PROTECTOR_STRONG) := -fstack-protector-strong +ta-stackp-cflags-$(CFG_TA_STACK_PROTECTOR_ALL) := -fstack-protector-all +$(sm)-platform-cflags += $(ta-stackp-cflags-y) + +ifeq ($(CFG_TA_MBEDTLS_SELF_TEST),y) +$(sm)-platform-cppflags += -DMBEDTLS_SELF_TEST +endif + +ifeq ($(CFG_TEE_TA_MALLOC_DEBUG),y) +# Build malloc debug code into libutils: (mdbg_malloc(), mdbg_free(), +# mdbg_check(), etc.). +$(sm)-platform-cppflags += -DENABLE_MDBG=1 +endif + +# Config variables to be explicitly exported to the dev kit conf.mk +ta-mk-file-export-vars-$(sm) += CFG_TA_FLOAT_SUPPORT +ta-mk-file-export-vars-$(sm) += CFG_CACHE_API +ta-mk-file-export-vars-$(sm) += CFG_SECURE_DATA_PATH +ta-mk-file-export-vars-$(sm) += CFG_TA_MBEDTLS_SELF_TEST +ta-mk-file-export-vars-$(sm) += CFG_TA_MBEDTLS +ta-mk-file-export-vars-$(sm) += CFG_TA_MBEDTLS_MPI +ta-mk-file-export-vars-$(sm) += CFG_SYSTEM_PTA +ta-mk-file-export-vars-$(sm) += CFG_FTRACE_SUPPORT +ta-mk-file-export-vars-$(sm) += CFG_UNWIND +ta-mk-file-export-vars-$(sm) += CFG_TA_MCOUNT +ta-mk-file-export-vars-$(sm) += CFG_TA_BTI +ta-mk-file-export-vars-$(sm) += CFG_TA_PAUTH +ta-mk-file-export-vars-$(sm) += CFG_CORE_TPM_EVENT_LOG +ta-mk-file-export-add-$(sm) += CFG_TEE_TA_LOG_LEVEL ?= $(CFG_TEE_TA_LOG_LEVEL)_nl_ +ta-mk-file-export-vars-$(sm) += CFG_TA_BGET_TEST +ta-mk-file-export-vars-$(sm) += CFG_ATTESTATION_PTA +ta-mk-file-export-vars-$(sm) += CFG_MEMTAG + +# Expand platform flags here as $(sm) will change if we have several TA +# targets. Platform flags should not change after inclusion of ta/ta.mk. +cppflags$(sm) := $(platform-cppflags) $($(sm)-platform-cppflags) +cflags$(sm) := $(platform-cflags) $($(sm)-platform-cflags) +aflags$(sm) := $(platform-aflags) $($(sm)-platform-aflags) + +# Changes to cppflags$(sm) will only affect how TA dev kit libraries are +# compiled, these flags are not propagated to the TA +cppflags$(sm) += -include $(conf-file) +cppflags$(sm) += -DTRACE_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) + +ifeq ($(ta-target),ta_arm32) +arm32-user-sysreg-txt = lib/libutee/arch/arm/arm32_user_sysreg.txt +arm32-user-sysregs-$(arm32-user-sysreg-txt)-h := arm32_user_sysreg.h +arm32-user-sysregs += $(arm32-user-sysreg-txt) + +arm32-user-sysregs-out := $(out-dir)/include/generated + +define process-arm32-user-sysreg +FORCE-GENSRC$(sm): $$(arm32-user-sysregs-out)/$$(arm32-user-sysregs-$(1)-h) +cleanfiles := $$(cleanfiles) \ + $$(arm32-user-sysregs-out)/$$(arm32-user-sysregs-$(1)-h) + +$$(arm32-user-sysregs-out)/$$(arm32-user-sysregs-$(1)-h): \ + $(1) scripts/arm32_sysreg.py + @$(cmd-echo-silent) ' GEN $$@' + $(q)mkdir -p $$(dir $$@) + $(q)$(PYTHON3) scripts/arm32_sysreg.py --guard __$$(arm32-user-sysregs-$(1)-h) \ + < $$< > $$@ + +endef #process-arm32-user-sysreg + +$(foreach sr, $(arm32-user-sysregs), \ + $(eval $(call process-arm32-user-sysreg,$(sr)))) + +cppflags$(sm) += -I$(arm32-user-sysregs-out) +endif + +base-prefix := $(sm)- + +libname = utils +libdir = lib/libutils +libuuid = 71855bba-6055-4293-a63f-b0963a737360 +include mk/lib.mk + +libname = mbedtls +libdir = lib/libmbedtls +libuuid = 87bb6ae8-4b1d-49fe-9986-2b966132c309 +libl = utils +include mk/lib.mk +ta-mk-file-export-vars-$(sm) += CFG_TA_MBEDTLS + +libname = utee +libdir = lib/libutee +libuuid = 4b3d937e-d57e-418b-8673-1c04f2420226 +libl = mbedtls utils +include mk/lib.mk + +libname = dl +libdir = lib/libdl +libuuid = be807bbd-81e1-4dc4-bd99-3d363f240ece +libl = utee utils +include mk/lib.mk + +base-prefix := + +incdirs-host := $(filter-out lib/libutils%, $(incdirs$(sm))) +incfiles-extra-host := lib/libutils/ext/include/compiler.h +incfiles-extra-host += lib/libutils/ext/include/util.h +incfiles-extra-host += lib/libutils/ext/include/types_ext.h +incfiles-extra-host += $(conf-file) +incfiles-extra-host += $(conf-mk-file) +incfiles-extra-host += $(conf-cmake-file) +incfiles-extra-host += core/include/tee/tee_fs_key_manager.h +incfiles-extra-host += core/include/tee/fs_htree.h +incfiles-extra-host += core/include/signed_hdr.h +ifeq ($(ta-target),ta_arm32) +incfiles-extra-host += $(out-dir)/include/generated/arm32_user_sysreg.h +endif +ifeq ($(CFG_SPMC_TESTS),y) +incfiles-extra-host += core/arch/arm/include/ffa.h +incfiles-extra-host += core/arch/arm/include/smccc.h +endif +# +# Copy lib files and exported headers from each lib +# + +define copy-file +$2/$$(notdir $1): $1 + @set -e; \ + mkdir -p $$(dir $$@) ; \ + $(cmd-echo-silent) ' INSTALL $$@' ; \ + cp -P $$< $$@ + +cleanfiles += $2/$$(notdir $1) +ta_dev_kit: $2/$$(notdir $1) +ta_dev_kit-files += $2/$$(notdir $1) +ta_dev_kit-files-$3 += $2/$$(notdir $1) +endef + +# Copy the .a files +$(foreach f, $(libfiles), \ + $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/lib,lib))) + +# Copy .mk files +ta-mkfiles = mk/compile.mk mk/subdir.mk mk/gcc.mk mk/clang.mk mk/cleandirs.mk \ + mk/cc-option.mk \ + ta/link.mk ta/link_shlib.mk \ + ta/mk/ta_dev_kit.mk + +$(foreach f, $(ta-mkfiles), \ + $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/mk))) + +# Copy the .h files for TAs +define copy-incdir +sf := $(subst $1/, , $(shell find $1 -name "*.[hS]")) +$$(foreach h, $$(sf), $$(eval $$(call copy-file, $1/$$(h), \ + $$(patsubst %/,%,$$(subst /./,/,$2/$$(dir $$(h)))),$3))) +endef +$(foreach d, $(incdirs$(sm)), \ + $(eval $(call copy-incdir,$(d),$(out-dir)/export-$(sm)/include,include))) + +# Copy the .h files needed by host +$(foreach d, $(incdirs-host), \ + $(eval $(call copy-incdir, $(d), $(out-dir)/export-$(sm)/host_include))) +$(foreach f, $(incfiles-extra-host), \ + $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/host_include))) + +# Copy the src files +ta-srcfiles = ta/user_ta_header.c ta/arch/$(ARCH)/ta.ld.S +ifeq ($(ta-target),ta_arm32) +ta-srcfiles += ta/arch/$(ARCH)/ta_entry_a32.S +endif +$(foreach f, $(ta-srcfiles), \ + $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/src))) + +# Copy keys +ta-keys = keys/default_ta.pem +$(foreach f, $(ta-keys), \ + $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/keys))) + +# Copy the scripts +ta-scripts = scripts/sign_encrypt.py scripts/symbolize.py +$(foreach f, $(ta-scripts), \ + $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/scripts))) + +# Create config file +conf-mk-file-export := $(out-dir)/export-$(sm)/mk/conf.mk +sm-$(conf-mk-file-export) := $(sm) +define mk-file-export +.PHONY: $(conf-mk-file-export) +$(conf-mk-file-export): + @$$(cmd-echo-silent) ' CHK ' $$@ + $(q)mkdir -p $$(dir $$@) + $(q)echo sm := $$(sm-$(conf-mk-file-export)) > $$@.tmp + $(q)echo sm-$$(sm-$(conf-mk-file-export)) := y >> $$@.tmp + $(q)($$(foreach v, $$(ta-mk-file-export-vars-$$(sm-$(conf-mk-file-export))), \ + $$(if $$($$(v)),echo $$(v) := $$($$(v));,))) >> $$@.tmp + $(q)echo '$$(ta-mk-file-export-add-$$(sm-$(conf-mk-file-export)))' | sed 's/_nl_ */\n/g' >> $$@.tmp + $(q)$(call mv-if-changed,$$@.tmp,$$@) +endef +$(eval $(mk-file-export)) + +cleanfiles := $(cleanfiles) $(conf-mk-file-export) +ta_dev_kit: $(conf-mk-file-export) + +all: ta_dev_kit diff --git a/optee/optee_os/ta/trusted_keys/entry.c b/optee/optee_os/ta/trusted_keys/entry.c new file mode 100644 index 0000000..a806e72 --- /dev/null +++ b/optee/optee_os/ta/trusted_keys/entry.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2019-2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define IV_SIZE 16 +#define TAG_SIZE 16 +#define MAX_BUF_SIZE 512 + +/* + * Acronym: + * + * TK - Trusted Key + */ + +struct tk_blob_hdr { + uint8_t reserved; + uint8_t iv[IV_SIZE]; + uint8_t tag[TAG_SIZE]; + uint8_t enc_key[]; +}; + +static TEE_Result get_random(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) +{ + uint8_t *rng_buf = NULL; + + DMSG("Invoked TA_CMD_GET_RANDOM"); + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!params[0].memref.buffer || !params[0].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + rng_buf = TEE_Malloc(params[0].memref.size, TEE_MALLOC_FILL_ZERO); + if (!rng_buf) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_GenerateRandom(rng_buf, params[0].memref.size); + memcpy(params[0].memref.buffer, rng_buf, params[0].memref.size); + memzero_explicit(rng_buf, params[0].memref.size); + + TEE_Free(rng_buf); + + return TEE_SUCCESS; +} + +static TEE_Result derive_unique_key(uint8_t *key, uint16_t key_size, + uint8_t *extra, uint16_t extra_size) +{ + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t ret_orig = 0; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + res = TEE_OpenTASession(&(const TEE_UUID)PTA_SYSTEM_UUID, + TEE_TIMEOUT_INFINITE, 0, NULL, &sess, + &ret_orig); + if (res) + return res; + + if (extra && extra_size) { + params[0].memref.buffer = extra; + params[0].memref.size = extra_size; + } + + params[1].memref.buffer = key; + params[1].memref.size = key_size; + + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY, + param_types, params, &ret_orig); + + TEE_CloseTASession(sess); + + return res; +} + +static TEE_Result huk_ae_encrypt(TEE_OperationHandle crypto_op, uint8_t *in, + size_t in_sz, uint8_t *out, size_t *out_sz) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tk_blob_hdr *hdr = (struct tk_blob_hdr *)out; + uint8_t iv[IV_SIZE] = { 0 }; + size_t enc_key_len = in_sz; + size_t tag_len = TAG_SIZE; + + hdr->reserved = 0; + TEE_GenerateRandom(iv, IV_SIZE); + memcpy(hdr->iv, iv, IV_SIZE); + + res = TEE_AEInit(crypto_op, hdr->iv, IV_SIZE, TAG_SIZE * 8, 0, 0); + if (res) + return res; + + res = TEE_AEEncryptFinal(crypto_op, in, in_sz, hdr->enc_key, + &enc_key_len, hdr->tag, &tag_len); + if (res || tag_len != TAG_SIZE) + return TEE_ERROR_SECURITY; + + if (ADD_OVERFLOW(enc_key_len, sizeof(*hdr), out_sz)) + return TEE_ERROR_SECURITY; + + return res; +} + +static TEE_Result huk_ae_decrypt(TEE_OperationHandle crypto_op, uint8_t *in, + size_t in_sz, uint8_t *out, size_t *out_sz) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct tk_blob_hdr *hdr = (struct tk_blob_hdr *)in; + uint8_t tag[TAG_SIZE] = { 0 }; + size_t enc_key_len = 0; + + if (SUB_OVERFLOW(in_sz, sizeof(*hdr), &enc_key_len)) + return TEE_ERROR_SECURITY; + + res = TEE_AEInit(crypto_op, hdr->iv, IV_SIZE, TAG_SIZE * 8, 0, 0); + if (res) + return res; + + memcpy(tag, hdr->tag, TAG_SIZE); + res = TEE_AEDecryptFinal(crypto_op, hdr->enc_key, enc_key_len, out, + out_sz, tag, TAG_SIZE); + if (res) + res = TEE_ERROR_SECURITY; + + return res; +} + +static TEE_Result huk_crypt(TEE_OperationMode mode, uint8_t *in, size_t in_sz, + uint8_t *out, size_t *out_sz) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle crypto_op = TEE_HANDLE_NULL; + TEE_ObjectHandle hkey = TEE_HANDLE_NULL; + uint8_t huk_key[TA_DERIVED_KEY_MAX_SIZE] = { }; + TEE_Attribute attr = { }; + + res = TEE_AllocateOperation(&crypto_op, TEE_ALG_AES_GCM, mode, + sizeof(huk_key) * 8); + if (res) + return res; + + res = derive_unique_key(huk_key, sizeof(huk_key), NULL, 0); + if (res) { + EMSG("derive_unique_key failed: returned %#"PRIx32, res); + goto out_op; + } + + res = TEE_AllocateTransientObject(TEE_TYPE_AES, sizeof(huk_key) * 8, + &hkey); + if (res) + goto out_op; + + attr.attributeID = TEE_ATTR_SECRET_VALUE; + attr.content.ref.buffer = huk_key; + attr.content.ref.length = sizeof(huk_key); + + res = TEE_PopulateTransientObject(hkey, &attr, 1); + if (res) + goto out_key; + + res = TEE_SetOperationKey(crypto_op, hkey); + if (res) + goto out_key; + + if (mode == TEE_MODE_ENCRYPT) { + res = huk_ae_encrypt(crypto_op, in, in_sz, out, out_sz); + if (res) + EMSG("huk_AE_encrypt failed: returned %#"PRIx32, res); + } else if (mode == TEE_MODE_DECRYPT) { + res = huk_ae_decrypt(crypto_op, in, in_sz, out, out_sz); + if (res) + EMSG("huk_AE_decrypt failed: returned %#"PRIx32, res); + } else { + TEE_Panic(0); + } + +out_key: + TEE_FreeTransientObject(hkey); +out_op: + TEE_FreeOperation(crypto_op); + memzero_explicit(huk_key, sizeof(huk_key)); + return res; +} + +static TEE_Result seal_trusted_key(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t *in = NULL; + size_t in_sz = 0; + uint8_t *out = NULL; + size_t out_sz = 0; + + DMSG("Invoked TA_CMD_SEAL"); + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + in = params[0].memref.buffer; + in_sz = params[0].memref.size; + out = params[1].memref.buffer; + out_sz = params[1].memref.size; + + if (!in || !in_sz || in_sz > MAX_BUF_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + if ((!out && out_sz) || + (out && !IS_ALIGNED_WITH_TYPE(out, struct tk_blob_hdr)) || + out_sz > MAX_BUF_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + if ((in_sz + sizeof(struct tk_blob_hdr)) > out_sz) { + params[1].memref.size = in_sz + sizeof(struct tk_blob_hdr); + return TEE_ERROR_SHORT_BUFFER; + } + + res = huk_crypt(TEE_MODE_ENCRYPT, in, in_sz, out, &out_sz); + if (res == TEE_SUCCESS) { + assert(out_sz == in_sz + sizeof(struct tk_blob_hdr)); + params[1].memref.size = out_sz; + } + + return res; +} + +static TEE_Result unseal_trusted_key(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + uint8_t *in = NULL; + size_t in_sz = 0; + uint8_t *out = NULL; + size_t out_sz = 0; + + DMSG("Invoked TA_CMD_UNSEAL"); + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + in = params[0].memref.buffer; + in_sz = params[0].memref.size; + out = params[1].memref.buffer; + out_sz = params[1].memref.size; + + if (!in || !IS_ALIGNED_WITH_TYPE(in, struct tk_blob_hdr) || + in_sz <= sizeof(struct tk_blob_hdr) || in_sz > MAX_BUF_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + if ((!out && out_sz) || out_sz > MAX_BUF_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + if (in_sz > (out_sz + sizeof(struct tk_blob_hdr))) { + params[1].memref.size = in_sz - sizeof(struct tk_blob_hdr); + return TEE_ERROR_SHORT_BUFFER; + } + + res = huk_crypt(TEE_MODE_DECRYPT, in, in_sz, out, &out_sz); + if (res == TEE_SUCCESS) { + assert(out_sz == in_sz - sizeof(struct tk_blob_hdr)); + params[1].memref.size = out_sz; + } + + return res; +} + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **session __unused) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_PropSetHandle h = TEE_HANDLE_NULL; + TEE_Identity id = { }; + + res = TEE_AllocatePropertyEnumerator(&h); + if (res) + goto out; + + TEE_StartPropertyEnumerator(h, TEE_PROPSET_CURRENT_CLIENT); + + res = TEE_GetPropertyAsIdentity(h, NULL, &id); + if (res) + goto out; + + if (id.login != TEE_LOGIN_REE_KERNEL) + res = TEE_ERROR_ACCESS_DENIED; + +out: + if (h) + TEE_FreePropertyEnumerator(h); + return res; +} + +void TA_CloseSessionEntryPoint(void *sess __unused) +{ +} + +TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd, + uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd) { + case TA_CMD_GET_RANDOM: + return get_random(pt, params); + case TA_CMD_SEAL: + return seal_trusted_key(pt, params); + case TA_CMD_UNSEAL: + return unseal_trusted_key(pt, params); + default: + EMSG("Command ID %#"PRIx32" is not supported", cmd); + return TEE_ERROR_NOT_SUPPORTED; + } +} diff --git a/optee/optee_os/ta/trusted_keys/include/trusted_keys.h b/optee/optee_os/ta/trusted_keys/include/trusted_keys.h new file mode 100644 index 0000000..1571b37 --- /dev/null +++ b/optee/optee_os/ta/trusted_keys/include/trusted_keys.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2019-2020, Linaro Limited + */ + +#ifndef TRUSTED_KEYS_H +#define TRUSTED_KEYS_H + +#define TRUSTED_KEYS_UUID { 0xf04a0fe7, 0x1f5d, 0x4b9b, \ + { 0xab, 0xf7, 0x61, 0x9b, 0x85, 0xb4, 0xce, 0x8c } } + +/* + * Get random data for symmetric key + * + * [out] memref[0] Random data + */ +#define TA_CMD_GET_RANDOM 0x0 + +/* + * Seal trusted key using hardware unique key + * + * [in] memref[0] Plain key + * [out] memref[1] Sealed key datablob + */ +#define TA_CMD_SEAL 0x1 + +/* + * Unseal trusted key using hardware unique key + * + * [in] memref[0] Sealed key datablob + * [out] memref[1] Plain key + */ +#define TA_CMD_UNSEAL 0x2 + +#endif /* TRUSTED_KEYS_H */ diff --git a/optee/optee_os/ta/trusted_keys/sub.mk b/optee/optee_os/ta/trusted_keys/sub.mk new file mode 100644 index 0000000..f1b35c0 --- /dev/null +++ b/optee/optee_os/ta/trusted_keys/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +global-incdirs-y += . +srcs-y += entry.c diff --git a/optee/optee_os/ta/trusted_keys/user_ta.mk b/optee/optee_os/ta/trusted_keys/user_ta.mk new file mode 100644 index 0000000..bcb59c0 --- /dev/null +++ b/optee/optee_os/ta/trusted_keys/user_ta.mk @@ -0,0 +1 @@ +user-ta-uuid := f04a0fe7-1f5d-4b9b-abf7-619b85b4ce8c diff --git a/optee/optee_os/ta/trusted_keys/user_ta_header_defines.h b/optee/optee_os/ta/trusted_keys/user_ta_header_defines.h new file mode 100644 index 0000000..2fc6689 --- /dev/null +++ b/optee/optee_os/ta/trusted_keys/user_ta_header_defines.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TRUSTED_KEYS_UUID + +#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_MULTI_SESSION | \ + TA_FLAG_DEVICE_ENUM) + +#define TA_STACK_SIZE (4 * 1024) +#define TA_DATA_SIZE (16 * 1024) + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_os/ta/user_ta_header.c b/optee/optee_os/ta/user_ta_header.c new file mode 100644 index 0000000..d602f92 --- /dev/null +++ b/optee/optee_os/ta/user_ta_header.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void *__stack_chk_guard; + +int trace_level = TRACE_LEVEL; + +const char trace_ext_prefix[] = "TA"; + +#ifndef TA_VERSION +#define TA_VERSION "Undefined version" +#endif + +#ifndef TA_DESCRIPTION +#define TA_DESCRIPTION "Undefined description" +#endif + +/* exprted to user_ta_header.c, built within TA */ +struct utee_params; + +#ifdef ARM32 +#define _C_FUNCTION(name) name##_c +#else +#define _C_FUNCTION(name) name +#endif /* ARM32 */ + +/* From libutee */ +TEE_Result __utee_entry(unsigned long func, unsigned long session_id, + struct utee_params *up, unsigned long cmd_id); + +void __noreturn _C_FUNCTION(__ta_entry)(unsigned long func, + unsigned long session_id, + struct utee_params *up, + unsigned long cmd_id); + +void __noreturn _C_FUNCTION(__ta_entry)(unsigned long func, + unsigned long session_id, + struct utee_params *up, + unsigned long cmd_id) +{ + static bool stack_canary_inited; + TEE_Result res = TEE_ERROR_GENERIC; + + if (IS_ENABLED(_CFG_TA_STACK_PROTECTOR) && !stack_canary_inited) { + uintptr_t canary = 0; + + res = _utee_cryp_random_number_generate(&canary, + sizeof(canary)); + if (res != TEE_SUCCESS) + _utee_return(res); + + /* Leave null byte in canary to prevent string base exploit */ + canary &= ~0xffUL; + + __stack_chk_guard = (void *)canary; + stack_canary_inited = true; + } + + res = __utee_entry(func, session_id, up, cmd_id); + +#if defined(CFG_FTRACE_SUPPORT) + /* + * __ta_entry is the first TA API called from TEE core. As it being + * __noreturn API, we need to call ftrace_return in this API just + * before _utee_return syscall to get proper ftrace call graph. + */ + ftrace_return(); +#endif + + _utee_return(res); +} + +/* + * According to GP Internal API, TA_STACK_SIZE corresponds to the stack + * size used by the TA code itself and does not include stack space + * possibly used by the Trusted Core Framework. + * Hence, stack_size which is the size of the stack to use, + * must be enlarged + * It has been set to 2048 to include trace framework and invoke commands + */ +#define TA_FRAMEWORK_STACK_SIZE 2048 + +const struct ta_head ta_head __section(".ta_head") = { + /* UUID, unique to each TA */ + .uuid = TA_UUID, + /* + * According to GP Internal API, TA_FRAMEWORK_STACK_SIZE corresponds to + * the stack size used by the TA code itself and does not include stack + * space possibly used by the Trusted Core Framework. + * Hence, stack_size which is the size of the stack to use, + * must be enlarged + */ + .stack_size = TA_STACK_SIZE + TA_FRAMEWORK_STACK_SIZE, + .flags = TA_FLAGS, + /* + * The TA entry doesn't go via this field any longer, to be able to + * reliably check that an old TA isn't loaded set this field to a + * fixed value. + */ + .depr_entry = UINT64_MAX, +}; + +/* Keeping the heap in bss */ +#if TA_DATA_SIZE < MALLOC_INITIAL_POOL_MIN_SIZE +#error TA_DATA_SIZE too small +#endif + +uint8_t ta_heap[TA_DATA_SIZE]; +const size_t ta_heap_size = sizeof(ta_heap); + +#ifndef TA_NO_SHARE_DATA_SIZE +#define TA_NO_SHARE_DATA_SIZE 0 +#endif +#if TA_NO_SHARE_DATA_SIZE && \ + TA_NO_SHARE_DATA_SIZE < MALLOC_INITIAL_POOL_MIN_SIZE +#error TA_NO_SHARE_DATA_SIZE too small +#endif + +uint8_t __ta_no_share_heap[TA_NO_SHARE_DATA_SIZE]; +const size_t __ta_no_share_heap_size = sizeof(__ta_no_share_heap); + +const struct user_ta_property ta_props[] = { + {TA_PROP_STR_SINGLE_INSTANCE, USER_TA_PROP_TYPE_BOOL, + &(const bool){(TA_FLAGS & TA_FLAG_SINGLE_INSTANCE) != 0}}, + + {TA_PROP_STR_MULTI_SESSION, USER_TA_PROP_TYPE_BOOL, + &(const bool){(TA_FLAGS & TA_FLAG_MULTI_SESSION) != 0}}, + + {TA_PROP_STR_KEEP_ALIVE, USER_TA_PROP_TYPE_BOOL, + &(const bool){(TA_FLAGS & TA_FLAG_INSTANCE_KEEP_ALIVE) != 0}}, + + {TA_PROP_STR_DATA_SIZE, USER_TA_PROP_TYPE_U32, + &(const uint32_t){TA_DATA_SIZE}}, + + {TA_PROP_STR_STACK_SIZE, USER_TA_PROP_TYPE_U32, + &(const uint32_t){TA_STACK_SIZE}}, + + {TA_PROP_STR_VERSION, USER_TA_PROP_TYPE_STRING, + TA_VERSION}, + + {TA_PROP_STR_DESCRIPTION, USER_TA_PROP_TYPE_STRING, + TA_DESCRIPTION}, + + /* Only little-endian supported */ + {TA_PROP_STR_ENDIAN, USER_TA_PROP_TYPE_U32, &(const uint32_t){0}}, + + {TA_PROP_STR_DOES_NOT_CLOSE_HANDLE_ON_CORRUPT_OBJECT, + USER_TA_PROP_TYPE_BOOL, + &(const bool){TA_FLAGS & TA_FLAG_DONT_CLOSE_HANDLE_ON_CORRUPT_OBJECT}}, + +/* + * 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]); + +#ifdef CFG_FTRACE_SUPPORT +struct __ftrace_info __ftrace_info = { +#ifdef __ILP32__ + .buf_start.ptr32 = { .lo = (uint32_t)&__ftrace_buf_start }, + .buf_end.ptr32 = { .lo = (uint32_t)__ftrace_buf_end }, + .ret_ptr.ptr32 = { .lo = (uint32_t)&__ftrace_return }, +#else + .buf_start.ptr64 = (uint64_t)&__ftrace_buf_start, + .buf_end.ptr64 = (uint64_t)__ftrace_buf_end, + .ret_ptr.ptr64 = (uint64_t)&__ftrace_return, +#endif +}; +#endif + +int tahead_get_trace_level(void) +{ + /* + * Store trace level in TA head structure, as ta_head.prop_tracelevel + */ + return TRACE_LEVEL; +} + +#if __OPTEE_CORE_API_COMPAT_1_1 +#undef TA_OpenSessionEntryPoint +#undef TA_InvokeCommandEntryPoint +#undef TEE_Param +TEE_Result TA_OpenSessionEntryPoint(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS], + void **sess_ctx) +{ + return __ta_open_sess(pt, params, sess_ctx, + __GP11_TA_OpenSessionEntryPoint); +} + +TEE_Result TA_InvokeCommandEntryPoint(void *sess_ctx, uint32_t cmd_id, + uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return __ta_invoke_cmd(sess_ctx, cmd_id, pt, params, + __GP11_TA_InvokeCommandEntryPoint); +} +#endif diff --git a/optee/optee_os/typedefs.checkpatch b/optee/optee_os/typedefs.checkpatch new file mode 100644 index 0000000..2c96568 --- /dev/null +++ b/optee/optee_os/typedefs.checkpatch @@ -0,0 +1,41 @@ +# Note: please keep the entries in this file sorted in reverse alphabetical +# order (sort -r) +TEE_Whence +TEE_UUID +TEE_Time +TEE_TASessionHandle +TEE_Session +TEE_SESessionHandle +TEE_SEServiceHandle +TEE_SEReaderProperties +TEE_SEReaderHandle +TEE_SEChannelHandle +TEE_SEAID +TEE_Result +TEE_PropSetHandle +TEE_Param +TEE_OperationMode +TEE_OperationInfoMultiple +TEE_OperationInfoKey +TEE_OperationInfo +TEE_OperationHandle +TEE_ObjectType +TEE_ObjectInfo +TEE_ObjectHandle +TEE_ObjectEnumHandle +TEE_Identity +TEE_ErrorOrigin +TEE_BigIntFMMContext +TEE_BigIntFMM +TEE_BigInt +TEE_Attribute +TAILQ_ENTRY\(.*\) +STAILQ_HEAD\(.*\) +STAILQ_ENTRY\(.*\) +SLIST_HEAD\(.*\) +SLIST_ENTRY\(.*\) +mbedtls_mpi_uint +mbedtls_mpi +Elf_Phdr +Elf_Half +Elf_Addr diff --git a/optee/optee_test/.github/issue_template.md b/optee/optee_test/.github/issue_template.md new file mode 100644 index 0000000..923efb3 --- /dev/null +++ b/optee/optee_test/.github/issue_template.md @@ -0,0 +1,21 @@ + diff --git a/optee/optee_test/.github/pull_request_template.md b/optee/optee_test/.github/pull_request_template.md new file mode 100644 index 0000000..0b31f83 --- /dev/null +++ b/optee/optee_test/.github/pull_request_template.md @@ -0,0 +1,19 @@ + diff --git a/optee/optee_test/.github/workflows/ci.yml b/optee/optee_test/.github/workflows/ci.yml new file mode 100644 index 0000000..10e6f9f --- /dev/null +++ b/optee/optee_test/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +name: CI +on: [push, pull_request] +permissions: + contents: read # to fetch code (actions/checkout) +jobs: + QEMUv8_check: + name: make check (QEMUv8) + runs-on: ubuntu-latest + container: jforissier/optee_os_ci:qemuv8_check2 + steps: + - name: Restore build cache + uses: actions/cache@v3 + with: + path: /github/home/.cache/ccache + key: qemuv8_check-cache-${{ github.sha }} + restore-keys: | + qemuv8_check-cache- + - name: Checkout + uses: actions/checkout@v3 + - shell: bash + run: | + # make check task + set -e -v + export LC_ALL=C + export BR2_CCACHE_DIR=/github/home/.cache/ccache + WD=$(pwd) + cd .. + TOP=$(pwd)/optee_repo_qemu_v8 + /root/get_optee_qemuv8.sh ${TOP} + mv ${TOP}/optee_test ${TOP}/optee_test_old + ln -s ${WD} ${TOP}/optee_test + cd ${TOP}/build + + make -j$(nproc) check diff --git a/optee/optee_test/.github/workflows/stale_issue.yml b/optee/optee_test/.github/workflows/stale_issue.yml new file mode 100644 index 0000000..9efda6a --- /dev/null +++ b/optee/optee_test/.github/workflows/stale_issue.yml @@ -0,0 +1,28 @@ +name: 'Close stale issues and pull requests with no recent activity' +on: + schedule: + - cron: "16 00 * * *" + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4.1.0 + + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'This issue has been marked as a stale issue because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this issue will automatically be closed in 5 days. Note that you can always re-open a closed issue at any time.' + stale-pr-message: 'This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note that you can always re-open a closed pull request at any time.' + stale-issue-label: Stale + stale-pr-label: Stale + exempt-issue-labels: bug,enhancement + exempt-pr-labels: bug,enhancement + days-before-stale: 30 + days-before-close: 5 + remove-stale-when-updated: true + remove-issue-stale-when-updated: true + remove-pr-stale-when-updated: true diff --git a/optee/optee_test/Android.mk b/optee/optee_test/Android.mk new file mode 100644 index 0000000..feb05c6 --- /dev/null +++ b/optee/optee_test/Android.mk @@ -0,0 +1,170 @@ +LOCAL_PATH := $(call my-dir) + +## include variants like TA_DEV_KIT_DIR +## and OPTEE_BIN +INCLUDE_FOR_BUILD_TA := false +include $(BUILD_OPTEE_MK) +INCLUDE_FOR_BUILD_TA := + +VERSION = $(shell git describe --always --dirty=-dev 2>/dev/null || echo Unknown) + +# TA_DEV_KIT_DIR must be set to non-empty value to +# avoid the Android build scripts complaining about +# includes pointing outside the Android source tree. +# This var is expected to be set when OPTEE OS built. +# We set the default value to an invalid path. +TA_DEV_KIT_DIR ?= ../invalid_include_path + +-include $(TA_DEV_KIT_DIR)/host_include/conf.mk +include $(LOCAL_PATH)/scripts/common.mk + +################################################################################ +# Build xtest # +################################################################################ +include $(CLEAR_VARS) +LOCAL_MODULE := xtest +LOCAL_VENDOR_MODULE := true +LOCAL_SHARED_LIBRARIES := libteec + +TA_DIR ?= /vendor/lib/optee_armtz + +srcs := regression_1000.c + +ifeq ($(CFG_GP_SOCKETS),y) +srcs += regression_2000.c \ + sock_server.c \ + rand_stream.c +endif + +srcs += adbg/src/adbg_case.c \ + adbg/src/adbg_enum.c \ + adbg/src/adbg_expect.c \ + adbg/src/adbg_log.c \ + adbg/src/adbg_run.c \ + adbg/src/security_utils_hex.c \ + aes_perf.c \ + benchmark_1000.c \ + benchmark_2000.c \ + regression_4000.c \ + regression_4100.c \ + regression_5000.c \ + regression_6000.c \ + regression_8000.c \ + regression_8100.c \ + hash_perf.c \ + stats.c \ + xtest_helpers.c \ + xtest_main.c \ + xtest_test.c \ + xtest_uuid_helpers.c + +ifeq ($(CFG_SECURE_PARTITION)-$(CFG_SPMC_TESTS),y-y) +srcs += ffa_spmc_1000.c +endif + +ifeq ($(CFG_SECSTOR_TA_MGMT_PTA),y) +srcs += install_ta.c +endif + +ifeq ($(CFG_SECURE_DATA_PATH),y) +srcs += sdp_basic.c +endif + +ifeq ($(CFG_PKCS11_TA),y) +srcs += pkcs11_1000.c +LOCAL_CFLAGS += -DCFG_PKCS11_TA +LOCAL_SHARED_LIBRARIES += libckteec +endif + +define my-embed-file +$(TARGET_OUT_HEADERS)/$(1).h: $(LOCAL_PATH)/$(2) + @echo ' GEN $$@' + @$(PYTHON3) $(LOCAL_PATH)/scripts/file_to_c.py --inf $$< --out $$@ --name $(1) + +LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_HEADERS)/$(1).h + +endef + +$(eval $(call my-embed-file,regression_8100_ca_crt,cert/ca.crt)) +$(eval $(call my-embed-file,regression_8100_mid_crt,cert/mid.crt)) +$(eval $(call my-embed-file,regression_8100_my_crt,cert/my.crt)) +$(eval $(call my-embed-file,regression_8100_my_csr,cert/my.csr)) + +LOCAL_SRC_FILES := $(patsubst %,host/xtest/%,$(srcs)) + +LOCAL_C_INCLUDES += $(LOCAL_PATH)/host/xtest \ + $(LOCAL_PATH)/host/xtest/adbg/include \ + $(LOCAL_PATH)/ta/include \ + $(LOCAL_PATH)/ta/supp_plugin/include \ + $(LOCAL_PATH)/ta/create_fail_test/include \ + $(LOCAL_PATH)/ta/crypt/include \ + $(LOCAL_PATH)/ta/enc_fs/include \ + $(LOCAL_PATH)/ta/os_test/include \ + $(LOCAL_PATH)/ta/rpc_test/include \ + $(LOCAL_PATH)/ta/sims/include \ + $(LOCAL_PATH)/ta/miss/include \ + $(LOCAL_PATH)/ta/sims_keepalive/include \ + $(LOCAL_PATH)/ta/storage_benchmark/include \ + $(LOCAL_PATH)/ta/concurrent/include \ + $(LOCAL_PATH)/ta/concurrent_large/include \ + $(LOCAL_PATH)/ta/hash_perf/include \ + $(LOCAL_PATH)/ta/aes_perf/include \ + $(LOCAL_PATH)/ta/socket/include \ + $(LOCAL_PATH)/ta/sdp_basic/include \ + $(LOCAL_PATH)/ta/tpm_log_test/include \ + $(LOCAL_PATH)/ta/large/include \ + $(LOCAL_PATH)/ta/bti_test/include \ + $(LOCAL_PATH)/host/supp_plugin/include + +# Include configuration file generated by OP-TEE OS (CFG_* macros) +LOCAL_CFLAGS += -I $(TA_DEV_KIT_DIR)/host_include -include conf.h +LOCAL_CFLAGS += -pthread +LOCAL_CFLAGS += -g3 +LOCAL_CFLAGS += -Wno-missing-field-initializers -Wno-format-zero-length + +ifneq ($(TA_DIR),) +LOCAL_CFLAGS += -DTA_DIR=\"$(TA_DIR)\" +endif + +## $(OPTEE_BIN) is the path of tee.bin like +## out/target/product/hikey/optee/arm-plat-hikey/core/tee.bin +## it will be generated after build the optee_os with target BUILD_OPTEE_OS +## which is defined in the common ta build mk file included before, +LOCAL_ADDITIONAL_DEPENDENCIES += $(OPTEE_BIN) + +include $(BUILD_EXECUTABLE) + +################################################################################ +# Build tee-supplicant test plugin # +################################################################################ +include $(CLEAR_VARS) + +PLUGIN_UUID = f07bfc66-958c-4a15-99c0-260e4e7375dd + +PLUGIN = $(PLUGIN_UUID).plugin +PLUGIN_INCLUDES_DIR = $(LOCAL_PATH)/host/supp_plugin/include + +LOCAL_MODULE := $(PLUGIN) +LOCAL_MODULE_RELATIVE_PATH := tee-supplicant/plugins +LOCAL_VENDOR_MODULE := true +# below is needed to locate optee_client exported headers +LOCAL_SHARED_LIBRARIES := libteec + +LOCAL_SRC_FILES += host/supp_plugin/test_supp_plugin.c +LOCAL_C_INCLUDES += $(PLUGIN_INCLUDES_DIR) +LOCAL_CFLAGS += -Wno-unused-parameter + +$(info $$LOCAL_SRC_FILES = ${LOCAL_SRC_FILES}) + +LOCAL_MODULE_TAGS := optional + +# Build the 32-bit and 64-bit versions. +LOCAL_MULTILIB := both +LOCAL_MODULE_TARGET_ARCH := arm arm64 + +include $(BUILD_SHARED_LIBRARY) + +################################################################################ +# Build TAs # +################################################################################ +include $(LOCAL_PATH)/ta/Android.mk diff --git a/optee/optee_test/CMakeLists.txt b/optee/optee_test/CMakeLists.txt new file mode 100644 index 0000000..6b91f23 --- /dev/null +++ b/optee/optee_test/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required (VERSION 3.4) +project (optee_test C) + +# Default cross compile settings +set (CMAKE_TOOLCHAIN_FILE CMakeToolchain.txt) + +set (OPTEE_TEST_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +################################################################################ +# Compiler flags: +# We want to use the same flags in the entire optee_client git +################################################################################ +add_compile_options ( + -Wall -Wbad-function-cast -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-prototypes -Wnested-externs + -Wpointer-arith -Wshadow -Wstrict-prototypes + -Wswitch-default -Wunsafe-loop-optimizations + -Wwrite-strings -Werror -fPIC + -Wno-missing-field-initializers + -Wno-unused-parameter +) + +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) +endif(CCACHE_FOUND) + +add_subdirectory (ta) +add_subdirectory (host/xtest) +add_subdirectory (host/supp_plugin) diff --git a/optee/optee_test/CMakeToolchain.txt b/optee/optee_test/CMakeToolchain.txt new file mode 100644 index 0000000..71eb52f --- /dev/null +++ b/optee/optee_test/CMakeToolchain.txt @@ -0,0 +1,3 @@ +set (CMAKE_SYSTEM_NAME Linux) + +set (CMAKE_SYSTEM_PROCESSOR arm) diff --git a/optee/optee_test/LICENSE.md b/optee/optee_test/LICENSE.md new file mode 100644 index 0000000..d509d29 --- /dev/null +++ b/optee/optee_test/LICENSE.md @@ -0,0 +1,5 @@ +The client applications (`optee_test/host/*`) are provided under the +[GPL-2.0](http://opensource.org/licenses/GPL-2.0) license. + +The user TAs (`optee_test/ta/*`) are provided under the +[BSD 2-Clause](http://opensource.org/licenses/BSD-2-Clause) license. diff --git a/optee/optee_test/Makefile b/optee/optee_test/Makefile new file mode 100644 index 0000000..9892064 --- /dev/null +++ b/optee/optee_test/Makefile @@ -0,0 +1,95 @@ +ifeq ($O,) +out-dir := $(CURDIR)/out +else +include scripts/common.mk +out-dir := $(call strip-trailing-slashes-and-dots,$(O)) +ifeq ($(out-dir),) +$(error invalid output directory (O=$(O))) +endif +endif + +bindir ?= /bin +libdir ?= /lib + +-include $(TA_DEV_KIT_DIR)/host_include/conf.mk +-include $(OPTEE_CLIENT_EXPORT)/include/optee_client_config.mk + +ifneq ($V,1) + q := @ + echo := @echo +else + q := + echo := @: +endif +# export 'q', used by sub-makefiles. +export q + +# If _HOST or _TA specific compilers are not specified, then use CROSS_COMPILE +CROSS_COMPILE_HOST ?= $(CROSS_COMPILE) +CROSS_COMPILE_TA ?= $(CROSS_COMPILE) + +.PHONY: all +ifneq ($(wildcard $(TA_DEV_KIT_DIR)/host_include/conf.mk),) +all: xtest ta test_plugin +else +all: + $(q)echo "TA_DEV_KIT_DIR is not correctly defined" && false +endif + +.PHONY: xtest +xtest: + $(q)$(MAKE) -C host/xtest CROSS_COMPILE="$(CROSS_COMPILE_HOST)" \ + --no-builtin-variables \ + O=$(out-dir) \ + $@ + +.PHONY: ta +ta: + $(q)$(MAKE) -C ta CROSS_COMPILE="$(CROSS_COMPILE_TA)" \ + O=$(out-dir) \ + $@ + +.PHONY: test_plugin +test_plugin: + $(q)$(MAKE) -C host/supp_plugin CROSS_COMPILE="$(CROSS_COMPILE_HOST)" \ + --no-builtin-variables \ + O=$(out-dir) + +.PHONY: clean +ifneq ($(wildcard $(TA_DEV_KIT_DIR)/host_include/conf.mk),) +clean: + $(q)$(MAKE) -C host/xtest O=$(out-dir) $@ + $(q)$(MAKE) -C ta O=$(out-dir) $@ + $(q)$(MAKE) -C host/supp_plugin O=$(out-dir) $@ +else +clean: + $(q)echo "TA_DEV_KIT_DIR is not correctly defined" + $(q)echo "You can remove manually $(out-dir)" +endif + +.PHONY: checkpatch checkpatch-staging checkpatch-working +checkpatch: checkpatch-staging checkpatch-working + +checkpatch-working: + @./scripts/checkpatch.sh + +checkpatch-staging: + @./scripts/checkpatch.sh --cached + +install: + $(echo) ' INSTALL ${DESTDIR}${libdir}/optee_armtz' + $(q)mkdir -p ${DESTDIR}${libdir}/optee_armtz + $(q)find $(out-dir) -name \*.ta -exec cp {} ${DESTDIR}${libdir}/optee_armtz \; + $(echo) ' INSTALL ${DESTDIR}${bindir}' + $(q)mkdir -p ${DESTDIR}${bindir} + $(q)cp $(out-dir)/xtest/xtest ${DESTDIR}${bindir} + $(echo) ' INSTALL ${DESTDIR}/$(CFG_TEE_PLUGIN_LOAD_PATH)' + $(q)mkdir -p ${DESTDIR}/$(CFG_TEE_PLUGIN_LOAD_PATH) + $(q)cp $(out-dir)/supp_plugin/*.plugin ${DESTDIR}/$(CFG_TEE_PLUGIN_LOAD_PATH) + +.PHONY: cscope +cscope: + $(echo) ' CSCOPE .' + ${q}rm -f cscope.* + ${q}find $(PWD) -name "*.[ch]" -o -name "*.cpp" | grep -v /package/ > cscope.files + ${q}cscope -b -q -k diff --git a/optee/optee_test/README.md b/optee/optee_test/README.md new file mode 100644 index 0000000..18d084e --- /dev/null +++ b/optee/optee_test/README.md @@ -0,0 +1,10 @@ +# OP-TEE sanity testsuite +This git contains source code for the test suite (xtest) used to test the +OP-TEE project. + +All official OP-TEE documentation has moved to http://optee.readthedocs.io. The +information that used to be here in this git can be found under [optee_test]. + +// OP-TEE core maintainers + +[optee_test]: https://optee.readthedocs.io/en/latest/building/gits/optee_test.html diff --git a/optee/optee_test/cert/README.txt b/optee/optee_test/cert/README.txt new file mode 100644 index 0000000..bed5c16 --- /dev/null +++ b/optee/optee_test/cert/README.txt @@ -0,0 +1,20 @@ +This is a Test Ceritificate Authority, only to be used for testing. + +#Root private key +openssl genrsa -out ca.key 2048 + +#Root certificate +openssl req -new -x509 -key ca.key -out ca.crt -days 10000 -batch + +#Mid CSR and key +openssl req -new -out mid.csr -config mid.conf + +#Sign mid.crt +openssl x509 -req -in mid.csr -extfile mid.ext -CA ca.crt -CAkey ca.key -CAcreateserial -out mid.crt -days 10000 + +#My CSR and key +openssl req -new -out my.csr -config my.conf +# View it with: openssl req -in my.csr -noout -text + +#Sign my.crt +openssl x509 -req -in my.csr -CA mid.crt -CAkey mid.key -CAcreateserial -out my.crt -days 10000 diff --git a/optee/optee_test/cert/ca.crt b/optee/optee_test/cert/ca.crt new file mode 100644 index 0000000..e5c59ae --- /dev/null +++ b/optee/optee_test/cert/ca.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJAL1dyL/W0KDOMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTgwNDI2MDk0NjEwWhcNNDUwOTExMDk0NjEwWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAlqY3pRejG//K79bY3v4sqSdHU2q1ir8mVBZDiZu5l+qGqmaxvgpSsKVL +5kxrXUcpL8oeMjsEkt8YxxL7w/XGA65/UPJe9Jn5/0fPQ7HD+S33/8oEO+hOa1pi +speqY2YWvdSsX/wuDaz6r9PXkrjftz9+cY/J9HGGXhmrez2tDKjiUyx7vwqirln1 +WcEiizucca2sgivm7032U6Tkmchk5YlU0Zd0kugV417zGCEY8H393ASV0oFyKbAR +A18m7iTSSMUnjWcLdp5UT6RM1O11xXHxPxT3hTMwBnq6W56feWO7BfVoYhNk8S8V +QRPq2T6PlEUDRs0UIhaKYCmYwLEv5QIDAQABo1AwTjAdBgNVHQ4EFgQUud0GJjG0 +tEs58qZXUQv33SJuSmswHwYDVR0jBBgwFoAUud0GJjG0tEs58qZXUQv33SJuSmsw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQ6r7zfKQIKIwyl3i/KTM +APxRoqsJqnBfuBuE4VwFaRTSoqe14hw6HXxcRuKexiaDuSniTirAxdMKYGZgfXyH +lClntTJ4+ak33CGOniU0HFZd79Hct0/DDrzQ/yEr4zvCv6wbQ8EjHOycFT14/Edv +sgVmf4erjnSN/ntC0R0VpDmy4eRuvNk0y3lvXwm9kW6RQftvIJsckJFvxrUvdIoP +KWK/og407DXX7xb2JqF6Eb8IvA2xAFZxOcztFTweRKHxk9vXRIVIe7/JufLtw0bx ++VCurEZ9FjNiIde1LdU3dpFBuAAlqiLbbSc2TVjBAYn9LFQGbsCoZ7PXDWBJnS9c +9g== +-----END CERTIFICATE----- diff --git a/optee/optee_test/cert/ca.key b/optee/optee_test/cert/ca.key new file mode 100644 index 0000000..8257079 --- /dev/null +++ b/optee/optee_test/cert/ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAlqY3pRejG//K79bY3v4sqSdHU2q1ir8mVBZDiZu5l+qGqmax +vgpSsKVL5kxrXUcpL8oeMjsEkt8YxxL7w/XGA65/UPJe9Jn5/0fPQ7HD+S33/8oE +O+hOa1pispeqY2YWvdSsX/wuDaz6r9PXkrjftz9+cY/J9HGGXhmrez2tDKjiUyx7 +vwqirln1WcEiizucca2sgivm7032U6Tkmchk5YlU0Zd0kugV417zGCEY8H393ASV +0oFyKbARA18m7iTSSMUnjWcLdp5UT6RM1O11xXHxPxT3hTMwBnq6W56feWO7BfVo +YhNk8S8VQRPq2T6PlEUDRs0UIhaKYCmYwLEv5QIDAQABAoIBADMnshF/W0WwsEqM +3Ausp6Gw0smCnK7Ghc9b2AcsN/NcEepfANAVVUridkl3faWo+lVd/q7z13PACfvf +eFpsZJbvdBAanR/WAUwsKDdGb9N3RpU3FgT5t1dA0+7tDVC/Y82GIBpf2YuPR3jZ +KISL/nuNNfR97QfyXLwrX01z/gUj9n95ish54jfsaD/JWN8xrDRgEQABlyEF+hBA +y9gZgIB4FrF5Lvqy0xejVhHBGjSJH3Owq9QbScWeOiEyYkq0TYqHCDCMD0lnwIbg +4YkOzYhAOa60UAqQB4Pk+4WN9wlWMMW2elfPwNN6+bdRwTtB4cjSBvGjnUwzMl7I +SNuF1+kCgYEAyKh2KeTDyoKgB4YOiRKj1nIMqjLsRM5pLwJDxI/ig+qE9Q+xYvXz +VZkMJKGX+TxFC2aFq5JMKHML/uKp8PnNpvD1YcNYn2ldN4OBW83SR5OUDtY+Z5D1 +YiKHZKIWwm7CCn6t4QzEO77TxZ/eWZpMW5+t4Dl6uGgLrt6heJIzShMCgYEAwDLe +JF4NwXzvJHdxnq/82bzzhQj6ZFMJUwmQeP8vJkc7mclO8/VUHjMyRx9q0u73oU23 +DtK6P1OqFBztxKHIwKZIQKbr77RdsCaPqxY9ry74ezwojRFvxlhQkPwegdOPviZW +C6TMMno1y7QgjjhmNzzEDKuDGX3N2+ucJWIoXScCgYBRfdk/emDpxdMoOxF8Kc3Q +MdFi7ft2lj2xkcHj+muMF5qXzB/GiQyiHt4HonkOB6Qi1ShEXc4AP3kHsxZBf7I9 +sm51ndhIJYpuGUJX/mcAGrduryP4+64shMln3UxQ+ppjmL8VPxITEZUAFcU/rqKE +M31yKuXkLp1QD6qURQv/cQKBgGeBfXycYlAXVjqPUNMi98rTJVo50Y8B4P2lIvbm +hp/YsNJLRYfAUQLKk4MV+lOKejWWQsVq2v6LsgaO5cWFUzXc1wBqZJl8yw+4VJrQ +qXuUkiDb7wK5pzZsDUdnX46PPtQqlSBEKevtQNdpNDcjTHjm8rXYEAxEYf7Tzg2b +5Rz1AoGAOe1uQ83F/vDik+6Pl/U14HaqVoMvtfgxKtvWxOjyVLMIyutqayLXSxxk +tvwtzfqD218g3OGVdneVTGVHFPMQNgaqFuFUpk0SVNh1xVu1LTbU3QMO/rZjrxMM +Y2Qyft5Z0HQtEHpsl1GUGYU4YDHTBxwk3gTqMJXEFD6KZCW/rDk= +-----END RSA PRIVATE KEY----- diff --git a/optee/optee_test/cert/ca.srl b/optee/optee_test/cert/ca.srl new file mode 100644 index 0000000..b685c22 --- /dev/null +++ b/optee/optee_test/cert/ca.srl @@ -0,0 +1 @@ +B7C435A31BDC8BEF diff --git a/optee/optee_test/cert/mid.conf b/optee/optee_test/cert/mid.conf new file mode 100644 index 0000000..2102b1c --- /dev/null +++ b/optee/optee_test/cert/mid.conf @@ -0,0 +1,14 @@ +[ req ] +default_bits = 2048 +default_keyfile = mid.key +encrypt_key = no +prompt = no +distinguished_name = my_req_distinguished_name +req_extensions = my_extensions +[ my_req_distinguished_name ] +C = AU +ST = Some-State +O = Be Bop - Originalaskkopp +[ my_extensions ] +basicConstraints = CA:TRUE +subjectKeyIdentifier = hash diff --git a/optee/optee_test/cert/mid.crt b/optee/optee_test/cert/mid.crt new file mode 100644 index 0000000..ccab002 --- /dev/null +++ b/optee/optee_test/cert/mid.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIJALfENaMb3IvvMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTgwNDI2MTUyNTU2WhcNNDUwOTExMTUyNTU2WjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYQmUg +Qm9wIC0gT3JpZ2luYWxhc2trb3BwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA3ZRPpDGU2iZuvv2v6KECPvP0F5y3g6EH+F/uqdYHS9tyCBPzW3hOIQPg +azYFO7JYqglaMxoiTaFrjPVpT72gAi+HGkiuh7hPZFVjx10LoVwJ8CwR78WXXQiZ +9rz9glnZycORHGgKoHun4yEDchtO1H1N6zdZWHEE6O4fFOq6mtgNCQzwxHpQERv+ +QCyzWnBEWFRJXGQx7wTGvoKwyCvsrREMxYvw8+LnJ5zM7MX8LAVeQ+9U3w17OjRa +QC69dAQ85cu+kv9z6ubN5NG298qT5mwkcSZzoZb6mfx3cJj1ubnQk2DvLSynG6sD +gevoK7hsKuvwMK6WxTCrzHzkMmA7OwIDAQABoxMwETAPBgNVHRMECDAGAQH/AgEB +MA0GCSqGSIb3DQEBCwUAA4IBAQAWMx659Yh7GQQZ4blR0YMr3JYtSRHu9bY2EfRr +sX9NvXXRBBsrtlUoWJhDwJIsTlLVQDRDdTQxWjNGgnHfR0UMgym2h/mOsNVuqxU+ +6D8q5KiCSxemEwx/6DVjbCwt8vgh7Ygr1Nzbl7c9qVbm0WBTFW6hjeF5ceQo7+2+ +VbSQV0Iql/m4fWoPBYhjU+Z47xnRQ1PtS/ohaV/9TD2uRJC+IW1zU25rj1w1whdY +SeMZRODod0KmIEfnpVN24eofJNhD1GyG+sWYyT6xBx29ZBIQT3g25uekVbTv0UmJ +RBk/5shpQVDWKNxZRhOdZOEu1M7Za94lp61yPIdbWXIQp0DG +-----END CERTIFICATE----- diff --git a/optee/optee_test/cert/mid.csr b/optee/optee_test/cert/mid.csr new file mode 100644 index 0000000..a53424f --- /dev/null +++ b/optee/optee_test/cert/mid.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICyDCCAbACAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEJlIEJvcCAtIE9yaWdpbmFsYXNra29wcDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAN2UT6QxlNombr79r+ihAj7z9Bect4OhB/hf7qnW +B0vbcggT81t4TiED4Gs2BTuyWKoJWjMaIk2ha4z1aU+9oAIvhxpIroe4T2RVY8dd +C6FcCfAsEe/Fl10Imfa8/YJZ2cnDkRxoCqB7p+MhA3IbTtR9Tes3WVhxBOjuHxTq +uprYDQkM8MR6UBEb/kAss1pwRFhUSVxkMe8Exr6CsMgr7K0RDMWL8PPi5yeczOzF +/CwFXkPvVN8Nezo0WkAuvXQEPOXLvpL/c+rmzeTRtvfKk+ZsJHEmc6GW+pn8d3CY +9bm50JNg7y0spxurA4Hr6Cu4bCrr8DCulsUwq8x85DJgOzsCAwEAAaA+MDwGCSqG +SIb3DQEJDjEvMC0wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUV/lNw8OrCMD7qd39 +f/248O6+80wwDQYJKoZIhvcNAQELBQADggEBAMn9sUKGKz7CdZPKeLdiUm60mIs4 +IIwjdLYrlRGzRh06B9WRIIFYHNPGDaK5KUMdyMYeqoSHYi6MlHE/d9VxGms4YNGz +gpGEN3MmaOqObSJEy+MSf1yjp1ydfGTDjGxzBaSca442+mXblp+fIoUHmfiIHdD8 +skR0fhdN5BkLU55XdbFAIuVTdTpIg0W1ItoIQ2HM62C1ktDprdqsdnzZysw/JkLb +EMqmu8zft9yK7rfJZzdrIjVx3ogF1SvKtzqm5+o/a9eDTgTmySysf/GzZ1muZ3af +JBwgAibknLxkZVP1S3rlgN9CTyu46O4BSU/WxLeItgqyKpM1KtoV95hCEOA= +-----END CERTIFICATE REQUEST----- diff --git a/optee/optee_test/cert/mid.ext b/optee/optee_test/cert/mid.ext new file mode 100644 index 0000000..47f9ebb --- /dev/null +++ b/optee/optee_test/cert/mid.ext @@ -0,0 +1 @@ +basicConstraints=CA:TRUE,pathlen:1 diff --git a/optee/optee_test/cert/mid.key b/optee/optee_test/cert/mid.key new file mode 100644 index 0000000..2c23f7b --- /dev/null +++ b/optee/optee_test/cert/mid.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDdlE+kMZTaJm6+ +/a/ooQI+8/QXnLeDoQf4X+6p1gdL23IIE/NbeE4hA+BrNgU7sliqCVozGiJNoWuM +9WlPvaACL4caSK6HuE9kVWPHXQuhXAnwLBHvxZddCJn2vP2CWdnJw5EcaAqge6fj +IQNyG07UfU3rN1lYcQTo7h8U6rqa2A0JDPDEelARG/5ALLNacERYVElcZDHvBMa+ +grDIK+ytEQzFi/Dz4ucnnMzsxfwsBV5D71TfDXs6NFpALr10BDzly76S/3Pq5s3k +0bb3ypPmbCRxJnOhlvqZ/HdwmPW5udCTYO8tLKcbqwOB6+gruGwq6/AwrpbFMKvM +fOQyYDs7AgMBAAECggEAMGN7IPhS8XEDLmJoT/0ZaHYOEDoBOZWpD+yjSiObZE2A +EZOJyaf0J/GYyND7Q5YnFrsEH7TNWPavbhEJ9ogKsW9/qZXFx43QiLC9IYSITayz +3udA44PbEk4WkXOkSRsmHJHA1ttBttpKR6emAP1FsdHLelqUAGRuFhAqaX75UWcF +KQ0aK+KBPkr3CGTZXQH/4Bt7KWL0iFfch8f4CAzLu2T20fWPyHW8zSFYVIq7972P +PXcs4tijXpTCazcjzEWZlhXvihOy+Ho7Dbg1DdnkeTYZyAf8ELkGfYJ9WCGiZTcw +5SgkLSpuyVUeoZ2xNN0F6m5y/SvEPVw711EAhRZogQKBgQDxbF+7ie1QDL0WIPYG +Ce0a5ajjgWsVMS9aXH12D4BiSfhaAhP5dr0oN23dmcGhAL9dEmXDGIgr13WXn8M7 +sXZrJhMUMCfD3h+tfWeYi62xvmVR+QnSh5/YicNOWnfCAa1hz/exlpJGQ5xF/Rn6 +r39eSlsuZ1ibXSlll5RcSftcKQKBgQDq9TaF6ufGVbesrT06X+gZ0A03sO+0ghVx +im+yWZFJRlJTn522ju+Pqj4BZGuFDVbD5N2rEULx9SF6pkJQC119r2q4aMtvJwO8 +hfqYzgKDFaoKvVbL3+uOae1pSjwzvVCUmy6wr6t6rVhK68W2xs7TpYgTACoGsNst +0RVStcHIwwKBgCCSaJAa2cO1FEXKCKdj63N3jMO1EEd5rVPZqqulB8M7C6DJKvy7 +QmYMpGwDdJZOTYM3GjeqNaUEmr7sNSD2nm1yY5yTqqnIbCmyA6oXHkYe0/itSt/2 +oGBMpecKWaH5K/VIY7i4AeAs+waOUVT7HIoSKh8mnlPHy/AC9WdGK/2RAoGAe+4r +fCeTaUH9R8945DmCK1taHW3ugb+7n8/tap1jzMqS0hj3DzwFkDmzyvg03lFS2rD1 +Wy4XqZgquI7Jm37jKVBFck+UPmTNy7q/m6nOGWZr8o48If1SOiQVXdwSNRg+UKQp +1HhUcrjMQXhrKSVkIq7FP4BuqmjOszP9k0rblBECgYBxaoIrBQpTrbSjB5s7SI7e +5h/n6pk+MSXXPvGtWHxab+yYZYh8iIA22rtMCIU8kuld5s81cXofKPQgzqPJBmS5 +nLLx6P5PbgwCJI+QZnXmh79l/xqePnvslzr2sG6PTjKI5v5BuvRrqrS1fqTl00uf +hZ3KOU3lh3TgsgdcYkERCw== +-----END PRIVATE KEY----- diff --git a/optee/optee_test/cert/mid.srl b/optee/optee_test/cert/mid.srl new file mode 100644 index 0000000..066ce8c --- /dev/null +++ b/optee/optee_test/cert/mid.srl @@ -0,0 +1 @@ +F16A44AAA2D04980 diff --git a/optee/optee_test/cert/my.conf b/optee/optee_test/cert/my.conf new file mode 100644 index 0000000..25d8135 --- /dev/null +++ b/optee/optee_test/cert/my.conf @@ -0,0 +1,13 @@ +[ req ] +default_bits = 2048 +default_keyfile = my.key +encrypt_key = no +prompt = no +distinguished_name = my_req_distinguished_name +req_extensions = my_extensions +[ my_req_distinguished_name ] +C = AU +ST = Some-State +O = Testing testers +[ my_extensions ] +basicConstraints=CA:FALSE diff --git a/optee/optee_test/cert/my.crt b/optee/optee_test/cert/my.crt new file mode 100644 index 0000000..99437b2 --- /dev/null +++ b/optee/optee_test/cert/my.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/TCCAeUCCQDxakSqotBJgDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYQmUgQm9wIC0gT3JpZ2lu +YWxhc2trb3BwMB4XDTE4MDQyNjE1MjYwOVoXDTQ1MDkxMTE1MjYwOVowPDELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxGDAWBgNVBAoMD1Rlc3Rpbmcg +dGVzdGVyczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOeglExQo4UC +OjWo5B4hNdW4a5eClziHPku5xMFaKWtCwI/zURjk3Di2jcUP7T60Gc9E+yHkaV+E +/O33s5qaNNrG055WhidJl4/Rvs4EF7ka3W44m0J0EACxgfWa11UWD5o+942V1Plc +Iwj1k+owkuiZfpSFxVjTB8ZE6U9qB+9rX+/ET7wTBOVbLHNfzw954ymENUPKUFwh +eUSntso+WbOWQJxElfElAh5z55WjdiwPSaV2q2lnW1Pa3yin2cbl3PvKIAkAhegB +IHTU05DfJiIRNsetCoVygNNZZMk7SG53hwFmKJg9+l3uxa7syeDVmOi+sM7tpwWD +eFRxdc28C+0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAOoNJWFFveTCbvqSGGC77 +WVve09qOVwcXJ6AxeWFIdfBsBW1sYqlN3ZOh7jYQwHbXIbxLNYWCWVgujHTzodvv +LJInvnDDjMZUZScR5/g/PiWe/8u7W2nL0PvAJeP5HXg3SxR0OIpDLBjnc6HY8oej +XvuiLEgvmtjiiSdXoD8WUExe6uBqTNQl/NH5uqJzTuQUYFZihtgdGAfiB7uXHgWi +OS67rHGfewn+So2IYpY0O8iDFc1s/p3En8uEBkpJVwWmb++xaeYZwpASupzMZXWV +ONzOjg/T18NRTV9OozphyRLjwotWTACMbtkrWNyZ5YJDrGW0gzo8nrpck2VoRBPV +kg== +-----END CERTIFICATE----- diff --git a/optee/optee_test/cert/my.csr b/optee/optee_test/cert/my.csr new file mode 100644 index 0000000..37e59fb --- /dev/null +++ b/optee/optee_test/cert/my.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICnTCCAYUCAQAwPDELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +GDAWBgNVBAoMD1Rlc3RpbmcgdGVzdGVyczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAOeglExQo4UCOjWo5B4hNdW4a5eClziHPku5xMFaKWtCwI/zURjk +3Di2jcUP7T60Gc9E+yHkaV+E/O33s5qaNNrG055WhidJl4/Rvs4EF7ka3W44m0J0 +EACxgfWa11UWD5o+942V1PlcIwj1k+owkuiZfpSFxVjTB8ZE6U9qB+9rX+/ET7wT +BOVbLHNfzw954ymENUPKUFwheUSntso+WbOWQJxElfElAh5z55WjdiwPSaV2q2ln +W1Pa3yin2cbl3PvKIAkAhegBIHTU05DfJiIRNsetCoVygNNZZMk7SG53hwFmKJg9 ++l3uxa7syeDVmOi+sM7tpwWDeFRxdc28C+0CAwEAAaAcMBoGCSqGSIb3DQEJDjEN +MAswCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAF5MmqF7qiRrPjywYvFxs +QOAB4aJFAuk/8BMS9TskRaCmDfMLjoWZ1sjy2zRkyanPE5+4LwHpUBUfGnaLWa8q +wXGj+5ImWxgcjRHIvH54IyYodnKnJaHA7GzghrsGd3Jck+xhBWmx5tVQmLvjkNvI +cHY7lpJqbXYb+2awiYG56GvYi7ytO7HLKHbpL8qW8bBEnARVkYU9zt1x6Zgpzd2p +IDuMbPl0JlpXejRJJM+cRQrEOrebnJ+tYnxi3Y+MJwWn7UmiLXRoW47ZOh+5/WDq +xWP76bR4rPCRIU5augV6xnu8Y3Bv2dMvfWnaOsPDYVsz0gl+sGDsIc4ZNUGEQ0wS +7g== +-----END CERTIFICATE REQUEST----- diff --git a/optee/optee_test/cert/my.key b/optee/optee_test/cert/my.key new file mode 100644 index 0000000..6dc247d --- /dev/null +++ b/optee/optee_test/cert/my.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDnoJRMUKOFAjo1 +qOQeITXVuGuXgpc4hz5LucTBWilrQsCP81EY5Nw4to3FD+0+tBnPRPsh5GlfhPzt +97OamjTaxtOeVoYnSZeP0b7OBBe5Gt1uOJtCdBAAsYH1mtdVFg+aPveNldT5XCMI +9ZPqMJLomX6UhcVY0wfGROlPagfva1/vxE+8EwTlWyxzX88PeeMphDVDylBcIXlE +p7bKPlmzlkCcRJXxJQIec+eVo3YsD0mldqtpZ1tT2t8op9nG5dz7yiAJAIXoASB0 +1NOQ3yYiETbHrQqFcoDTWWTJO0hud4cBZiiYPfpd7sWu7Mng1ZjovrDO7acFg3hU +cXXNvAvtAgMBAAECggEAG1+FxxMMkA54VJkWBF2GYDCAPpKHTn3lJcvZbcQ6+tsT +qK9nmRqK0AT68hv0vKFKH42WZCX7MfekcHcCebXZozU2ExNEnWX8DFoMQ4qGRzDe +lEUKTCstLPfNVPosknid9WuVk9zuI135IfjrtxRweB6Tr/ezH9EorQy9yc3NDEUZ +qClQHh5/xsFyOfvar0ktrlAfm16NKF1jvNlr3eoFhjv2W5gqFPnsA+bseD2BYyZI +IT4xp2Z9IDMwWtnrx+4xSsViwzKTrXMGatKft6Fs8qwmVe63wq7VW1gj9wnspY47 +YVHswoCaYX6OO2uNtUfbYjrW7EJdANpNUMEmj6TnXQKBgQD6j5dnFVSqU9XHjY3E ++zymV4lU/o7EXxnvwFkHvNex003hfQF5Q0ceFVvOyc/8dpk5HHanceqLbgX+f0il +bDZ2it8eaSuTSblO9vUKeHlvx3s7KfwFH5kT48rnd5uSDjn1zRTboANBPRjIssP5 +GhRFx5JPGZ6b0ehK8c/2Qx07XwKBgQDsp8U+WFHxBRoixr9XjVGqcVZ4XeKl+KX1 +qQZOSx2gO3Yhl0umin/SD2jNKgeUhtVhw3YNob3pB17botnpXE4/kj8kpFDepy6J +aCgWw0eU1ZM0w04AsOT1vRmzdGZf9UAD6kR5Je41PcKHWRz6ZXW1j27IAXzhYbSw +aGZa29nIMwKBgAy0WS3t4/Qa+hz7LXQOdR3OFHWNzrlgRRVmAF2nEpy+pRVI3FlE +swdwd849Z2FathwyOEX3PbhCJOWpmIpiuUQ7eGK3XHFEbLP3S6dzQl0LlVEDqPat +inp6s2AXLXkzZXb0JhmYvHGDYo1SmyM3Uk3Td7SxDNzDwO6D4lKPRp0rAoGBAOGJ +eodSMLWcgS4Hb6+G9P+VCC2qfChk8fVPYr0XBWMBiDG3ONe9Qtf065IrrhG09oM3 +fri7HnyJE7QKXdbyq3gWbqsDFjc76TP22c3nyb5kVOiCAULTU0GHOIk4M6Db4Gha +yWsT5RNEirHnEaDpNOcVjSR7loJNVaCRvop03/bVAoGBANLhYvNsYC67cxXBwOkH +yg3KIXM/rbsK3aZyiv7ZNpja3Rjr0kqlvBom+0UCBVv3TsimgjB1+GocWqzdB9mi +DhPirVCQjl+63jE9YZxT1cvibkxsBAQCbl4FlqIbNa7zWKgqopwCX1FQzQuU7QUR +8tMAzwM9hIylELscVzZ13Htq +-----END PRIVATE KEY----- diff --git a/optee/optee_test/host/openssl/include/openssl/aes.h b/optee/optee_test/host/openssl/include/openssl/aes.h new file mode 100644 index 0000000..faa66c4 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/aes.h @@ -0,0 +1,149 @@ +/* crypto/aes/aes.h */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 HEADER_AES_H +# define HEADER_AES_H + +# include + +# ifdef OPENSSL_NO_AES +# error AES is disabled. +# endif + +# include + +# define AES_ENCRYPT 1 +# define AES_DECRYPT 0 + +/* + * Because array size can't be a const in C, the following two are macros. + * Both sizes are in bytes. + */ +# define AES_MAXNR 14 +# define AES_BLOCK_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + +/* This should be a hidden type, but EVP requires that the size be known */ +struct aes_key_st { +# ifdef AES_LONG + unsigned long rd_key[4 * (AES_MAXNR + 1)]; +# else + unsigned int rd_key[4 * (AES_MAXNR + 1)]; +# endif + int rounds; +}; +typedef struct aes_key_st AES_KEY; + +const char *AES_options(void); + +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc); +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num, const int enc); +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, int *num); +void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char ivec[AES_BLOCK_SIZE], + unsigned char ecount_buf[AES_BLOCK_SIZE], + unsigned int *num); +/* NB: the IV is _two_ blocks long */ +void AES_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + unsigned char *ivec, const int enc); +/* NB: the IV is _four_ blocks long */ +void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, + const AES_KEY *key2, const unsigned char *ivec, + const int enc); + +int AES_wrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); +int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, unsigned int inlen); + + +#ifdef __cplusplus +} +#endif + +#endif /* !HEADER_AES_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/asn1.h b/optee/optee_test/host/openssl/include/openssl/asn1.h new file mode 100644 index 0000000..35a2b2a --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/asn1.h @@ -0,0 +1,1420 @@ +/* crypto/asn1/asn1.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ASN1_H +# define HEADER_ASN1_H + +# include +# include +# ifndef OPENSSL_NO_BIO +# include +# endif +# include +# include + +# include + +# include +# ifndef OPENSSL_NO_DEPRECATED +# include +# endif + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# define V_ASN1_UNIVERSAL 0x00 +# define V_ASN1_APPLICATION 0x40 +# define V_ASN1_CONTEXT_SPECIFIC 0x80 +# define V_ASN1_PRIVATE 0xc0 + +# define V_ASN1_CONSTRUCTED 0x20 +# define V_ASN1_PRIMITIVE_TAG 0x1f +# define V_ASN1_PRIMATIVE_TAG 0x1f + +# define V_ASN1_APP_CHOOSE -2/* let the recipient choose */ +# define V_ASN1_OTHER -3/* used in ASN1_TYPE */ +# define V_ASN1_ANY -4/* used in ASN1 template code */ + +# define V_ASN1_NEG 0x100/* negative flag */ + +# define V_ASN1_UNDEF -1 +# define V_ASN1_EOC 0 +# define V_ASN1_BOOLEAN 1 /**/ +# define V_ASN1_INTEGER 2 +# define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) +# define V_ASN1_BIT_STRING 3 +# define V_ASN1_OCTET_STRING 4 +# define V_ASN1_NULL 5 +# define V_ASN1_OBJECT 6 +# define V_ASN1_OBJECT_DESCRIPTOR 7 +# define V_ASN1_EXTERNAL 8 +# define V_ASN1_REAL 9 +# define V_ASN1_ENUMERATED 10 +# define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) +# define V_ASN1_UTF8STRING 12 +# define V_ASN1_SEQUENCE 16 +# define V_ASN1_SET 17 +# define V_ASN1_NUMERICSTRING 18 /**/ +# define V_ASN1_PRINTABLESTRING 19 +# define V_ASN1_T61STRING 20 +# define V_ASN1_TELETEXSTRING 20/* alias */ +# define V_ASN1_VIDEOTEXSTRING 21 /**/ +# define V_ASN1_IA5STRING 22 +# define V_ASN1_UTCTIME 23 +# define V_ASN1_GENERALIZEDTIME 24 /**/ +# define V_ASN1_GRAPHICSTRING 25 /**/ +# define V_ASN1_ISO64STRING 26 /**/ +# define V_ASN1_VISIBLESTRING 26/* alias */ +# define V_ASN1_GENERALSTRING 27 /**/ +# define V_ASN1_UNIVERSALSTRING 28 /**/ +# define V_ASN1_BMPSTRING 30 +/* For use with d2i_ASN1_type_bytes() */ +# define B_ASN1_NUMERICSTRING 0x0001 +# define B_ASN1_PRINTABLESTRING 0x0002 +# define B_ASN1_T61STRING 0x0004 +# define B_ASN1_TELETEXSTRING 0x0004 +# define B_ASN1_VIDEOTEXSTRING 0x0008 +# define B_ASN1_IA5STRING 0x0010 +# define B_ASN1_GRAPHICSTRING 0x0020 +# define B_ASN1_ISO64STRING 0x0040 +# define B_ASN1_VISIBLESTRING 0x0040 +# define B_ASN1_GENERALSTRING 0x0080 +# define B_ASN1_UNIVERSALSTRING 0x0100 +# define B_ASN1_OCTET_STRING 0x0200 +# define B_ASN1_BIT_STRING 0x0400 +# define B_ASN1_BMPSTRING 0x0800 +# define B_ASN1_UNKNOWN 0x1000 +# define B_ASN1_UTF8STRING 0x2000 +# define B_ASN1_UTCTIME 0x4000 +# define B_ASN1_GENERALIZEDTIME 0x8000 +# define B_ASN1_SEQUENCE 0x10000 +/* For use with ASN1_mbstring_copy() */ +# define MBSTRING_FLAG 0x1000 +# define MBSTRING_UTF8 (MBSTRING_FLAG) +# define MBSTRING_ASC (MBSTRING_FLAG|1) +# define MBSTRING_BMP (MBSTRING_FLAG|2) +# define MBSTRING_UNIV (MBSTRING_FLAG|4) +# define SMIME_OLDMIME 0x400 +# define SMIME_CRLFEOL 0x800 +# define SMIME_STREAM 0x1000 + struct X509_algor_st; +DECLARE_STACK_OF(X509_ALGOR) + +# define DECLARE_ASN1_SET_OF(type)/* filled in by mkstack.pl */ +# define IMPLEMENT_ASN1_SET_OF(type)/* nothing, no longer needed */ + +/* + * We MUST make sure that, except for constness, asn1_ctx_st and + * asn1_const_ctx are exactly the same. Fortunately, as soon as the old ASN1 + * parsing macros are gone, we can throw this away as well... + */ +typedef struct asn1_ctx_st { + unsigned char *p; /* work char pointer */ + int eos; /* end of sequence read for indefinite + * encoding */ + int error; /* error code to use when returning an error */ + int inf; /* constructed if 0x20, indefinite is 0x21 */ + int tag; /* tag from last 'get object' */ + int xclass; /* class from last 'get object' */ + long slen; /* length of last 'get object' */ + unsigned char *max; /* largest value of p allowed */ + unsigned char *q; /* temporary variable */ + unsigned char **pp; /* variable */ + int line; /* used in error processing */ +} ASN1_CTX; + +typedef struct asn1_const_ctx_st { + const unsigned char *p; /* work char pointer */ + int eos; /* end of sequence read for indefinite + * encoding */ + int error; /* error code to use when returning an error */ + int inf; /* constructed if 0x20, indefinite is 0x21 */ + int tag; /* tag from last 'get object' */ + int xclass; /* class from last 'get object' */ + long slen; /* length of last 'get object' */ + const unsigned char *max; /* largest value of p allowed */ + const unsigned char *q; /* temporary variable */ + const unsigned char **pp; /* variable */ + int line; /* used in error processing */ +} ASN1_const_CTX; + +/* + * These are used internally in the ASN1_OBJECT to keep track of whether the + * names and data need to be free()ed + */ +# define ASN1_OBJECT_FLAG_DYNAMIC 0x01/* internal use */ +# define ASN1_OBJECT_FLAG_CRITICAL 0x02/* critical x509v3 object id */ +# define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04/* internal use */ +# define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08/* internal use */ +struct asn1_object_st { + const char *sn, *ln; + int nid; + int length; + const unsigned char *data; /* data remains const after init */ + int flags; /* Should we free this one */ +}; + +# define ASN1_STRING_FLAG_BITS_LEFT 0x08/* Set if 0x07 has bits left value */ +/* + * This indicates that the ASN1_STRING is not a real value but just a place + * holder for the location where indefinite length constructed data should be + * inserted in the memory buffer + */ +# define ASN1_STRING_FLAG_NDEF 0x010 + +/* + * This flag is used by the CMS code to indicate that a string is not + * complete and is a place holder for content when it had all been accessed. + * The flag will be reset when content has been written to it. + */ + +# define ASN1_STRING_FLAG_CONT 0x020 +/* + * This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING + * type. + */ +# define ASN1_STRING_FLAG_MSTRING 0x040 +/* This is the base type that holds just about everything :-) */ +struct asn1_string_st { + int length; + int type; + unsigned char *data; + /* + * The value of the following field depends on the type being held. It + * is mostly being used for BIT_STRING so if the input data has a + * non-zero 'unused bits' value, it will be handled correctly + */ + long flags; +}; + +/* + * ASN1_ENCODING structure: this is used to save the received encoding of an + * ASN1 type. This is useful to get round problems with invalid encodings + * which can break signatures. + */ + +typedef struct ASN1_ENCODING_st { + unsigned char *enc; /* DER encoding */ + long len; /* Length of encoding */ + int modified; /* set to 1 if 'enc' is invalid */ +} ASN1_ENCODING; + +/* Used with ASN1 LONG type: if a long is set to this it is omitted */ +# define ASN1_LONG_UNDEF 0x7fffffffL + +# define STABLE_FLAGS_MALLOC 0x01 +# define STABLE_NO_MASK 0x02 +# define DIRSTRING_TYPE \ + (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING) +# define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING) + +typedef struct asn1_string_table_st { + int nid; + long minsize; + long maxsize; + unsigned long mask; + unsigned long flags; +} ASN1_STRING_TABLE; + +DECLARE_STACK_OF(ASN1_STRING_TABLE) + +/* size limits: this stuff is taken straight from RFC2459 */ + +# define ub_name 32768 +# define ub_common_name 64 +# define ub_locality_name 128 +# define ub_state_name 128 +# define ub_organization_name 64 +# define ub_organization_unit_name 64 +# define ub_title 64 +# define ub_email_address 128 + +/* + * Declarations for template structures: for full definitions see asn1t.h + */ +typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; +typedef struct ASN1_TLC_st ASN1_TLC; +/* This is just an opaque pointer */ +typedef struct ASN1_VALUE_st ASN1_VALUE; + +/* Declare ASN1 functions: the implement macro in in asn1t.h */ + +# define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type) + +# define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type) + +# define DECLARE_ASN1_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) + +# define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) + +# define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(itname) + +# define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(const type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(name) + +# define DECLARE_ASN1_NDEF_FUNCTION(name) \ + int i2d_##name##_NDEF(name *a, unsigned char **out); + +# define DECLARE_ASN1_FUNCTIONS_const(name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS(name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name) + +# define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + type *name##_new(void); \ + void name##_free(type *a); + +# define DECLARE_ASN1_PRINT_FUNCTION(stname) \ + DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname) + +# define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \ + int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx); + +# define D2I_OF(type) type *(*)(type **,const unsigned char **,long) +# define I2D_OF(type) int (*)(type *,unsigned char **) +# define I2D_OF_const(type) int (*)(const type *,unsigned char **) + +# define CHECKED_D2I_OF(type, d2i) \ + ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0))) +# define CHECKED_I2D_OF(type, i2d) \ + ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0))) +# define CHECKED_NEW_OF(type, xnew) \ + ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0))) +# define CHECKED_PTR_OF(type, p) \ + ((void*) (1 ? p : (type*)0)) +# define CHECKED_PPTR_OF(type, p) \ + ((void**) (1 ? p : (type**)0)) + +# define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long) +# define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **) +# define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type) + +TYPEDEF_D2I2D_OF(void); + +/*- + * The following macros and typedefs allow an ASN1_ITEM + * to be embedded in a structure and referenced. Since + * the ASN1_ITEM pointers need to be globally accessible + * (possibly from shared libraries) they may exist in + * different forms. On platforms that support it the + * ASN1_ITEM structure itself will be globally exported. + * Other platforms will export a function that returns + * an ASN1_ITEM pointer. + * + * To handle both cases transparently the macros below + * should be used instead of hard coding an ASN1_ITEM + * pointer in a structure. + * + * The structure will look like this: + * + * typedef struct SOMETHING_st { + * ... + * ASN1_ITEM_EXP *iptr; + * ... + * } SOMETHING; + * + * It would be initialised as e.g.: + * + * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...}; + * + * and the actual pointer extracted with: + * + * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr); + * + * Finally an ASN1_ITEM pointer can be extracted from an + * appropriate reference with: ASN1_ITEM_rptr(X509). This + * would be used when a function takes an ASN1_ITEM * argument. + * + */ + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM ASN1_ITEM_EXP; + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +# define ASN1_ITEM_ptr(iptr) (iptr) + +/* Macro to include ASN1_ITEM pointer from base type */ +# define ASN1_ITEM_ref(iptr) (&(iptr##_it)) + +# define ASN1_ITEM_rptr(ref) (&(ref##_it)) + +# define DECLARE_ASN1_ITEM(name) \ + OPENSSL_EXTERN const ASN1_ITEM name##_it; + +# else + +/* + * Platforms that can't easily handle shared global variables are declared as + * functions returning ASN1_ITEM pointers. + */ + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM *ASN1_ITEM_EXP (void); + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +# define ASN1_ITEM_ptr(iptr) (iptr()) + +/* Macro to include ASN1_ITEM pointer from base type */ +# define ASN1_ITEM_ref(iptr) (iptr##_it) + +# define ASN1_ITEM_rptr(ref) (ref##_it()) + +# define DECLARE_ASN1_ITEM(name) \ + const ASN1_ITEM * name##_it(void); + +# endif + +/* Parameters used by ASN1_STRING_print_ex() */ + +/* + * These determine which characters to escape: RFC2253 special characters, + * control characters and MSB set characters + */ + +# define ASN1_STRFLGS_ESC_2253 1 +# define ASN1_STRFLGS_ESC_CTRL 2 +# define ASN1_STRFLGS_ESC_MSB 4 + +/* + * This flag determines how we do escaping: normally RC2253 backslash only, + * set this to use backslash and quote. + */ + +# define ASN1_STRFLGS_ESC_QUOTE 8 + +/* These three flags are internal use only. */ + +/* Character is a valid PrintableString character */ +# define CHARTYPE_PRINTABLESTRING 0x10 +/* Character needs escaping if it is the first character */ +# define CHARTYPE_FIRST_ESC_2253 0x20 +/* Character needs escaping if it is the last character */ +# define CHARTYPE_LAST_ESC_2253 0x40 + +/* + * NB the internal flags are safely reused below by flags handled at the top + * level. + */ + +/* + * If this is set we convert all character strings to UTF8 first + */ + +# define ASN1_STRFLGS_UTF8_CONVERT 0x10 + +/* + * If this is set we don't attempt to interpret content: just assume all + * strings are 1 byte per character. This will produce some pretty odd + * looking output! + */ + +# define ASN1_STRFLGS_IGNORE_TYPE 0x20 + +/* If this is set we include the string type in the output */ +# define ASN1_STRFLGS_SHOW_TYPE 0x40 + +/* + * This determines which strings to display and which to 'dump' (hex dump of + * content octets or DER encoding). We can only dump non character strings or + * everything. If we don't dump 'unknown' they are interpreted as character + * strings with 1 octet per character and are subject to the usual escaping + * options. + */ + +# define ASN1_STRFLGS_DUMP_ALL 0x80 +# define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 + +/* + * These determine what 'dumping' does, we can dump the content octets or the + * DER encoding: both use the RFC2253 #XXXXX notation. + */ + +# define ASN1_STRFLGS_DUMP_DER 0x200 + +/* + * All the string flags consistent with RFC2253, escaping control characters + * isn't essential in RFC2253 but it is advisable anyway. + */ + +# define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | \ + ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +DECLARE_STACK_OF(ASN1_INTEGER) +DECLARE_ASN1_SET_OF(ASN1_INTEGER) + +DECLARE_STACK_OF(ASN1_GENERALSTRING) + +typedef struct asn1_type_st { + int type; + union { + char *ptr; + ASN1_BOOLEAN boolean; + ASN1_STRING *asn1_string; + ASN1_OBJECT *object; + ASN1_INTEGER *integer; + ASN1_ENUMERATED *enumerated; + ASN1_BIT_STRING *bit_string; + ASN1_OCTET_STRING *octet_string; + ASN1_PRINTABLESTRING *printablestring; + ASN1_T61STRING *t61string; + ASN1_IA5STRING *ia5string; + ASN1_GENERALSTRING *generalstring; + ASN1_BMPSTRING *bmpstring; + ASN1_UNIVERSALSTRING *universalstring; + ASN1_UTCTIME *utctime; + ASN1_GENERALIZEDTIME *generalizedtime; + ASN1_VISIBLESTRING *visiblestring; + ASN1_UTF8STRING *utf8string; + /* + * set and sequence are left complete and still contain the set or + * sequence bytes + */ + ASN1_STRING *set; + ASN1_STRING *sequence; + ASN1_VALUE *asn1_value; + } value; +} ASN1_TYPE; + +DECLARE_STACK_OF(ASN1_TYPE) +DECLARE_ASN1_SET_OF(ASN1_TYPE) + +typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY; + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(ASN1_SEQUENCE_ANY, ASN1_SET_ANY) + +typedef struct NETSCAPE_X509_st { + ASN1_OCTET_STRING *header; + X509 *cert; +} NETSCAPE_X509; + +/* This is used to contain a list of bit names */ +typedef struct BIT_STRING_BITNAME_st { + int bitnum; + const char *lname; + const char *sname; +} BIT_STRING_BITNAME; + +# define M_ASN1_STRING_length(x) ((x)->length) +# define M_ASN1_STRING_length_set(x, n) ((x)->length = (n)) +# define M_ASN1_STRING_type(x) ((x)->type) +# define M_ASN1_STRING_data(x) ((x)->data) + +/* Macros for string operations */ +# define M_ASN1_BIT_STRING_new() (ASN1_BIT_STRING *)\ + ASN1_STRING_type_new(V_ASN1_BIT_STRING) +# define M_ASN1_BIT_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_ASN1_BIT_STRING_dup(a) (ASN1_BIT_STRING *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) +# define M_ASN1_BIT_STRING_cmp(a,b) ASN1_STRING_cmp(\ + (const ASN1_STRING *)a,(const ASN1_STRING *)b) +# define M_ASN1_BIT_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) + +# define M_ASN1_INTEGER_new() (ASN1_INTEGER *)\ + ASN1_STRING_type_new(V_ASN1_INTEGER) +# define M_ASN1_INTEGER_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_ASN1_INTEGER_dup(a) (ASN1_INTEGER *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) +# define M_ASN1_INTEGER_cmp(a,b) ASN1_STRING_cmp(\ + (const ASN1_STRING *)a,(const ASN1_STRING *)b) + +# define M_ASN1_ENUMERATED_new() (ASN1_ENUMERATED *)\ + ASN1_STRING_type_new(V_ASN1_ENUMERATED) +# define M_ASN1_ENUMERATED_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_ASN1_ENUMERATED_dup(a) (ASN1_ENUMERATED *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) +# define M_ASN1_ENUMERATED_cmp(a,b) ASN1_STRING_cmp(\ + (const ASN1_STRING *)a,(const ASN1_STRING *)b) + +# define M_ASN1_OCTET_STRING_new() (ASN1_OCTET_STRING *)\ + ASN1_STRING_type_new(V_ASN1_OCTET_STRING) +# define M_ASN1_OCTET_STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_ASN1_OCTET_STRING_dup(a) (ASN1_OCTET_STRING *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) +# define M_ASN1_OCTET_STRING_cmp(a,b) ASN1_STRING_cmp(\ + (const ASN1_STRING *)a,(const ASN1_STRING *)b) +# define M_ASN1_OCTET_STRING_set(a,b,c) ASN1_STRING_set((ASN1_STRING *)a,b,c) +# define M_ASN1_OCTET_STRING_print(a,b) ASN1_STRING_print(a,(ASN1_STRING *)b) +# define M_i2d_ASN1_OCTET_STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\ + V_ASN1_UNIVERSAL) + +# define B_ASN1_TIME \ + B_ASN1_UTCTIME | \ + B_ASN1_GENERALIZEDTIME + +# define B_ASN1_PRINTABLE \ + B_ASN1_NUMERICSTRING| \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_T61STRING| \ + B_ASN1_IA5STRING| \ + B_ASN1_BIT_STRING| \ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING|\ + B_ASN1_SEQUENCE|\ + B_ASN1_UNKNOWN + +# define B_ASN1_DIRECTORYSTRING \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_TELETEXSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_UTF8STRING + +# define B_ASN1_DISPLAYTEXT \ + B_ASN1_IA5STRING| \ + B_ASN1_VISIBLESTRING| \ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING + +# define M_ASN1_PRINTABLE_new() ASN1_STRING_type_new(V_ASN1_T61STRING) +# define M_ASN1_PRINTABLE_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_PRINTABLE(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_PRINTABLE) + +# define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING) +# define M_DIRECTORYSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +# define M_d2i_DIRECTORYSTRING(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_DIRECTORYSTRING) + +# define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING) +# define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\ + pp,a->type,V_ASN1_UNIVERSAL) +# define M_d2i_DISPLAYTEXT(a,pp,l) \ + d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \ + B_ASN1_DISPLAYTEXT) + +# define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\ + ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING) +# define M_ASN1_PRINTABLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_ASN1_PRINTABLESTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\ + V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \ + (ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING) + +# define M_ASN1_T61STRING_new() (ASN1_T61STRING *)\ + ASN1_STRING_type_new(V_ASN1_T61STRING) +# define M_ASN1_T61STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_ASN1_T61STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\ + V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_T61STRING(a,pp,l) \ + (ASN1_T61STRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING) + +# define M_ASN1_IA5STRING_new() (ASN1_IA5STRING *)\ + ASN1_STRING_type_new(V_ASN1_IA5STRING) +# define M_ASN1_IA5STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_ASN1_IA5STRING_dup(a) \ + (ASN1_IA5STRING *)ASN1_STRING_dup((const ASN1_STRING *)a) +# define M_i2d_ASN1_IA5STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\ + V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_IA5STRING(a,pp,l) \ + (ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\ + B_ASN1_IA5STRING) + +# define M_ASN1_UTCTIME_new() (ASN1_UTCTIME *)\ + ASN1_STRING_type_new(V_ASN1_UTCTIME) +# define M_ASN1_UTCTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_ASN1_UTCTIME_dup(a) (ASN1_UTCTIME *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) + +# define M_ASN1_GENERALIZEDTIME_new() (ASN1_GENERALIZEDTIME *)\ + ASN1_STRING_type_new(V_ASN1_GENERALIZEDTIME) +# define M_ASN1_GENERALIZEDTIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_ASN1_GENERALIZEDTIME_dup(a) (ASN1_GENERALIZEDTIME *)ASN1_STRING_dup(\ + (const ASN1_STRING *)a) + +# define M_ASN1_TIME_new() (ASN1_TIME *)\ + ASN1_STRING_type_new(V_ASN1_UTCTIME) +# define M_ASN1_TIME_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_ASN1_TIME_dup(a) (ASN1_TIME *)\ + ASN1_STRING_dup((const ASN1_STRING *)a) + +# define M_ASN1_GENERALSTRING_new() (ASN1_GENERALSTRING *)\ + ASN1_STRING_type_new(V_ASN1_GENERALSTRING) +# define M_ASN1_GENERALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_ASN1_GENERALSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\ + V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_GENERALSTRING(a,pp,l) \ + (ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING) + +# define M_ASN1_UNIVERSALSTRING_new() (ASN1_UNIVERSALSTRING *)\ + ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING) +# define M_ASN1_UNIVERSALSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\ + V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \ + (ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING) + +# define M_ASN1_BMPSTRING_new() (ASN1_BMPSTRING *)\ + ASN1_STRING_type_new(V_ASN1_BMPSTRING) +# define M_ASN1_BMPSTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_ASN1_BMPSTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\ + V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_BMPSTRING(a,pp,l) \ + (ASN1_BMPSTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING) + +# define M_ASN1_VISIBLESTRING_new() (ASN1_VISIBLESTRING *)\ + ASN1_STRING_type_new(V_ASN1_VISIBLESTRING) +# define M_ASN1_VISIBLESTRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_ASN1_VISIBLESTRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\ + V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \ + (ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING) + +# define M_ASN1_UTF8STRING_new() (ASN1_UTF8STRING *)\ + ASN1_STRING_type_new(V_ASN1_UTF8STRING) +# define M_ASN1_UTF8STRING_free(a) ASN1_STRING_free((ASN1_STRING *)a) +# define M_i2d_ASN1_UTF8STRING(a,pp) \ + i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\ + V_ASN1_UNIVERSAL) +# define M_d2i_ASN1_UTF8STRING(a,pp,l) \ + (ASN1_UTF8STRING *)d2i_ASN1_type_bytes\ + ((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING) + + /* for the is_set parameter to i2d_ASN1_SET */ +# define IS_SEQUENCE 0 +# define IS_SET 1 + +DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) + +int ASN1_TYPE_get(ASN1_TYPE *a); +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); +int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b); + +ASN1_OBJECT *ASN1_OBJECT_new(void); +void ASN1_OBJECT_free(ASN1_OBJECT *a); +int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp); +ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length); +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length); + +DECLARE_ASN1_ITEM(ASN1_OBJECT) + +DECLARE_STACK_OF(ASN1_OBJECT) +DECLARE_ASN1_SET_OF(ASN1_OBJECT) + +ASN1_STRING *ASN1_STRING_new(void); +void ASN1_STRING_free(ASN1_STRING *a); +void ASN1_STRING_clear_free(ASN1_STRING *a); +int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str); +ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a); +ASN1_STRING *ASN1_STRING_type_new(int type); +int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b); + /* + * Since this is used to store all sorts of things, via macros, for now, + * make its data void * + */ +int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); +int ASN1_STRING_length(const ASN1_STRING *x); +void ASN1_STRING_length_set(ASN1_STRING *x, int n); +int ASN1_STRING_type(ASN1_STRING *x); +unsigned char *ASN1_STRING_data(ASN1_STRING *x); + +DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING) +int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp); +ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, + const unsigned char **pp, long length); +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length); +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value); +int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n); +int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a, + unsigned char *flags, int flags_len); + +# ifndef OPENSSL_NO_BIO +int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, + BIT_STRING_BITNAME *tbl, int indent); +# endif +int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl); +int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value, + BIT_STRING_BITNAME *tbl); + +int i2d_ASN1_BOOLEAN(int a, unsigned char **pp); +int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length); + +DECLARE_ASN1_FUNCTIONS(ASN1_INTEGER) +int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp); +ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length); +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length); +ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x); +int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y); + +DECLARE_ASN1_FUNCTIONS(ASN1_ENUMERATED) + +int ASN1_UTCTIME_check(const ASN1_UTCTIME *a); +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t); +ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, + int offset_day, long offset_sec); +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str); +int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t); +# if 0 +time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s); +# endif + +int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, + time_t t); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, + time_t t, int offset_day, + long offset_sec); +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str); +int ASN1_TIME_diff(int *pday, int *psec, + const ASN1_TIME *from, const ASN1_TIME *to); + +DECLARE_ASN1_FUNCTIONS(ASN1_OCTET_STRING) +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a); +int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, + const ASN1_OCTET_STRING *b); +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, + int len); + +DECLARE_ASN1_FUNCTIONS(ASN1_VISIBLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTF8STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_NULL) +DECLARE_ASN1_FUNCTIONS(ASN1_BMPSTRING) + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val); +int UTF8_putc(unsigned char *str, int len, unsigned long value); + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) + +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) +DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) +DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING) +DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME) +DECLARE_ASN1_FUNCTIONS(ASN1_TIME) + +DECLARE_ASN1_ITEM(ASN1_OCTET_STRING_NDEF) + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t); +ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, + int offset_day, long offset_sec); +int ASN1_TIME_check(ASN1_TIME *t); +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME + **out); +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str); + +int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp, + i2d_of_void *i2d, int ex_tag, int ex_class, int is_set); +STACK_OF(OPENSSL_BLOCK) *d2i_ASN1_SET(STACK_OF(OPENSSL_BLOCK) **a, + const unsigned char **pp, + long length, d2i_of_void *d2i, + void (*free_func) (OPENSSL_BLOCK), + int ex_tag, int ex_class); + +# ifndef OPENSSL_NO_BIO +int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a); +int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size); +int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a); +int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size); +int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a); +int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size); +int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type); +# endif +int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a); + +int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num); +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, + const char *sn, const char *ln); + +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); +long ASN1_INTEGER_get(const ASN1_INTEGER *a); +ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); +BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn); + +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v); +long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a); +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai); +BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn); + +/* General */ +/* given a string, return the correct type, max is the maximum length */ +int ASN1_PRINTABLE_type(const unsigned char *s, int max); + +int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass); +ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, + long length, int Ptag, int Pclass); +unsigned long ASN1_tag2bit(int tag); +/* type is one or more of the B_ASN1_ values. */ +ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp, + long length, int type); + +/* PARSING */ +int asn1_Finish(ASN1_CTX *c); +int asn1_const_Finish(ASN1_const_CTX *c); + +/* SPECIALS */ +int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, + int *pclass, long omax); +int ASN1_check_infinite_end(unsigned char **p, long len); +int ASN1_const_check_infinite_end(const unsigned char **p, long len); +void ASN1_put_object(unsigned char **pp, int constructed, int length, + int tag, int xclass); +int ASN1_put_eoc(unsigned char **pp); +int ASN1_object_size(int constructed, int length, int tag); + +/* Used to implement other functions */ +void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x); + +# define ASN1_dup_of(type,i2d,d2i,x) \ + ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_dup_of_const(type,i2d,d2i,x) \ + ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \ + CHECKED_D2I_OF(type, d2i), \ + CHECKED_PTR_OF(const type, x))) + +void *ASN1_item_dup(const ASN1_ITEM *it, void *x); + +/* ASN1 alloc/free macros for when a type is only used internally */ + +# define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type)) +# define M_ASN1_free_of(x, type) \ + ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type)) + +# ifndef OPENSSL_NO_FP_API +void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x); + +# define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x); +int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x); + +# define ASN1_i2d_fp_of(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_i2d_fp_of_const(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x); +int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags); +# endif + +int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in); + +# ifndef OPENSSL_NO_BIO +void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x); + +# define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x); +int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x); + +# define ASN1_i2d_bio_of(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +# define ASN1_i2d_bio_of_const(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x); +int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a); +int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a); +int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a); +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v); +int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags); +int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, + unsigned char *buf, int off); +int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent); +int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, + int dump); +# endif +const char *ASN1_tag2str(int tag); + +/* Used to load and write netscape format cert */ + +DECLARE_ASN1_FUNCTIONS(NETSCAPE_X509) + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s); + +int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len); +int ASN1_TYPE_get_octetstring(ASN1_TYPE *a, unsigned char *data, int max_len); +int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, + unsigned char *data, int len); +int ASN1_TYPE_get_int_octetstring(ASN1_TYPE *a, long *num, + unsigned char *data, int max_len); + +STACK_OF(OPENSSL_BLOCK) *ASN1_seq_unpack(const unsigned char *buf, int len, + d2i_of_void *d2i, + void (*free_func) (OPENSSL_BLOCK)); +unsigned char *ASN1_seq_pack(STACK_OF(OPENSSL_BLOCK) *safes, i2d_of_void *i2d, + unsigned char **buf, int *len); +void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i); +void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it); +ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d, + ASN1_OCTET_STRING **oct); + +# define ASN1_pack_string_of(type,obj,i2d,oct) \ + (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \ + CHECKED_I2D_OF(type, i2d), \ + oct)) + +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, + ASN1_OCTET_STRING **oct); + +void ASN1_STRING_set_default_mask(unsigned long mask); +int ASN1_STRING_set_default_mask_asc(const char *p); +unsigned long ASN1_STRING_get_default_mask(void); +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask); +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask, + long minsize, long maxsize); + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, + const unsigned char *in, int inlen, + int inform, int nid); +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid); +int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long); +void ASN1_STRING_TABLE_cleanup(void); + +/* ASN1 template functions */ + +/* Old API compatible functions */ +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, + long len, const ASN1_ITEM *it); +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it); +int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, + const ASN1_ITEM *it); + +void ASN1_add_oid_module(void); + +ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf); +ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf); + +/* ASN1 Print flags */ + +/* Indicate missing OPTIONAL fields */ +# define ASN1_PCTX_FLAGS_SHOW_ABSENT 0x001 +/* Mark start and end of SEQUENCE */ +# define ASN1_PCTX_FLAGS_SHOW_SEQUENCE 0x002 +/* Mark start and end of SEQUENCE/SET OF */ +# define ASN1_PCTX_FLAGS_SHOW_SSOF 0x004 +/* Show the ASN1 type of primitives */ +# define ASN1_PCTX_FLAGS_SHOW_TYPE 0x008 +/* Don't show ASN1 type of ANY */ +# define ASN1_PCTX_FLAGS_NO_ANY_TYPE 0x010 +/* Don't show ASN1 type of MSTRINGs */ +# define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE 0x020 +/* Don't show field names in SEQUENCE */ +# define ASN1_PCTX_FLAGS_NO_FIELD_NAME 0x040 +/* Show structure names of each SEQUENCE field */ +# define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME 0x080 +/* Don't show structure name even at top level */ +# define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100 + +int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, + const ASN1_ITEM *it, const ASN1_PCTX *pctx); +ASN1_PCTX *ASN1_PCTX_new(void); +void ASN1_PCTX_free(ASN1_PCTX *p); +unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p); +void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p); +void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p); +void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p); +void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p); +void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags); + +BIO_METHOD *BIO_f_asn1(void); + +BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it); + +int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const ASN1_ITEM *it); +int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, + const char *hdr, const ASN1_ITEM *it); +int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, + int ctype_nid, int econt_nid, + STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it); +ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it); +int SMIME_crlf_copy(BIO *in, BIO *out, int flags); +int SMIME_text(BIO *in, BIO *out); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_ASN1_strings(void); + +/* Error codes for the ASN1 functions. */ + +/* Function codes. */ +# define ASN1_F_A2D_ASN1_OBJECT 100 +# define ASN1_F_A2I_ASN1_ENUMERATED 101 +# define ASN1_F_A2I_ASN1_INTEGER 102 +# define ASN1_F_A2I_ASN1_STRING 103 +# define ASN1_F_APPEND_EXP 176 +# define ASN1_F_ASN1_BIT_STRING_SET_BIT 183 +# define ASN1_F_ASN1_CB 177 +# define ASN1_F_ASN1_CHECK_TLEN 104 +# define ASN1_F_ASN1_COLLATE_PRIMITIVE 105 +# define ASN1_F_ASN1_COLLECT 106 +# define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108 +# define ASN1_F_ASN1_D2I_FP 109 +# define ASN1_F_ASN1_D2I_READ_BIO 107 +# define ASN1_F_ASN1_DIGEST 184 +# define ASN1_F_ASN1_DO_ADB 110 +# define ASN1_F_ASN1_DUP 111 +# define ASN1_F_ASN1_ENUMERATED_SET 112 +# define ASN1_F_ASN1_ENUMERATED_TO_BN 113 +# define ASN1_F_ASN1_EX_C2I 204 +# define ASN1_F_ASN1_FIND_END 190 +# define ASN1_F_ASN1_GENERALIZEDTIME_ADJ 216 +# define ASN1_F_ASN1_GENERALIZEDTIME_SET 185 +# define ASN1_F_ASN1_GENERATE_V3 178 +# define ASN1_F_ASN1_GET_OBJECT 114 +# define ASN1_F_ASN1_HEADER_NEW 115 +# define ASN1_F_ASN1_I2D_BIO 116 +# define ASN1_F_ASN1_I2D_FP 117 +# define ASN1_F_ASN1_INTEGER_SET 118 +# define ASN1_F_ASN1_INTEGER_TO_BN 119 +# define ASN1_F_ASN1_ITEM_D2I_FP 206 +# define ASN1_F_ASN1_ITEM_DUP 191 +# define ASN1_F_ASN1_ITEM_EX_COMBINE_NEW 121 +# define ASN1_F_ASN1_ITEM_EX_D2I 120 +# define ASN1_F_ASN1_ITEM_I2D_BIO 192 +# define ASN1_F_ASN1_ITEM_I2D_FP 193 +# define ASN1_F_ASN1_ITEM_PACK 198 +# define ASN1_F_ASN1_ITEM_SIGN 195 +# define ASN1_F_ASN1_ITEM_SIGN_CTX 220 +# define ASN1_F_ASN1_ITEM_UNPACK 199 +# define ASN1_F_ASN1_ITEM_VERIFY 197 +# define ASN1_F_ASN1_MBSTRING_NCOPY 122 +# define ASN1_F_ASN1_OBJECT_NEW 123 +# define ASN1_F_ASN1_OUTPUT_DATA 214 +# define ASN1_F_ASN1_PACK_STRING 124 +# define ASN1_F_ASN1_PCTX_NEW 205 +# define ASN1_F_ASN1_PKCS5_PBE_SET 125 +# define ASN1_F_ASN1_SEQ_PACK 126 +# define ASN1_F_ASN1_SEQ_UNPACK 127 +# define ASN1_F_ASN1_SIGN 128 +# define ASN1_F_ASN1_STR2TYPE 179 +# define ASN1_F_ASN1_STRING_SET 186 +# define ASN1_F_ASN1_STRING_TABLE_ADD 129 +# define ASN1_F_ASN1_STRING_TYPE_NEW 130 +# define ASN1_F_ASN1_TEMPLATE_EX_D2I 132 +# define ASN1_F_ASN1_TEMPLATE_NEW 133 +# define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 131 +# define ASN1_F_ASN1_TIME_ADJ 217 +# define ASN1_F_ASN1_TIME_SET 175 +# define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134 +# define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135 +# define ASN1_F_ASN1_UNPACK_STRING 136 +# define ASN1_F_ASN1_UTCTIME_ADJ 218 +# define ASN1_F_ASN1_UTCTIME_SET 187 +# define ASN1_F_ASN1_VERIFY 137 +# define ASN1_F_B64_READ_ASN1 209 +# define ASN1_F_B64_WRITE_ASN1 210 +# define ASN1_F_BIO_NEW_NDEF 208 +# define ASN1_F_BITSTR_CB 180 +# define ASN1_F_BN_TO_ASN1_ENUMERATED 138 +# define ASN1_F_BN_TO_ASN1_INTEGER 139 +# define ASN1_F_C2I_ASN1_BIT_STRING 189 +# define ASN1_F_C2I_ASN1_INTEGER 194 +# define ASN1_F_C2I_ASN1_OBJECT 196 +# define ASN1_F_COLLECT_DATA 140 +# define ASN1_F_D2I_ASN1_BIT_STRING 141 +# define ASN1_F_D2I_ASN1_BOOLEAN 142 +# define ASN1_F_D2I_ASN1_BYTES 143 +# define ASN1_F_D2I_ASN1_GENERALIZEDTIME 144 +# define ASN1_F_D2I_ASN1_HEADER 145 +# define ASN1_F_D2I_ASN1_INTEGER 146 +# define ASN1_F_D2I_ASN1_OBJECT 147 +# define ASN1_F_D2I_ASN1_SET 148 +# define ASN1_F_D2I_ASN1_TYPE_BYTES 149 +# define ASN1_F_D2I_ASN1_UINTEGER 150 +# define ASN1_F_D2I_ASN1_UTCTIME 151 +# define ASN1_F_D2I_AUTOPRIVATEKEY 207 +# define ASN1_F_D2I_NETSCAPE_RSA 152 +# define ASN1_F_D2I_NETSCAPE_RSA_2 153 +# define ASN1_F_D2I_PRIVATEKEY 154 +# define ASN1_F_D2I_PUBLICKEY 155 +# define ASN1_F_D2I_RSA_NET 200 +# define ASN1_F_D2I_RSA_NET_2 201 +# define ASN1_F_D2I_X509 156 +# define ASN1_F_D2I_X509_CINF 157 +# define ASN1_F_D2I_X509_PKEY 159 +# define ASN1_F_I2D_ASN1_BIO_STREAM 211 +# define ASN1_F_I2D_ASN1_SET 188 +# define ASN1_F_I2D_ASN1_TIME 160 +# define ASN1_F_I2D_DSA_PUBKEY 161 +# define ASN1_F_I2D_EC_PUBKEY 181 +# define ASN1_F_I2D_PRIVATEKEY 163 +# define ASN1_F_I2D_PUBLICKEY 164 +# define ASN1_F_I2D_RSA_NET 162 +# define ASN1_F_I2D_RSA_PUBKEY 165 +# define ASN1_F_LONG_C2I 166 +# define ASN1_F_OID_MODULE_INIT 174 +# define ASN1_F_PARSE_TAGGING 182 +# define ASN1_F_PKCS5_PBE2_SET_IV 167 +# define ASN1_F_PKCS5_PBE_SET 202 +# define ASN1_F_PKCS5_PBE_SET0_ALGOR 215 +# define ASN1_F_PKCS5_PBKDF2_SET 219 +# define ASN1_F_SMIME_READ_ASN1 212 +# define ASN1_F_SMIME_TEXT 213 +# define ASN1_F_X509_CINF_NEW 168 +# define ASN1_F_X509_CRL_ADD0_REVOKED 169 +# define ASN1_F_X509_INFO_NEW 170 +# define ASN1_F_X509_NAME_ENCODE 203 +# define ASN1_F_X509_NAME_EX_D2I 158 +# define ASN1_F_X509_NAME_EX_NEW 171 +# define ASN1_F_X509_NEW 172 +# define ASN1_F_X509_PKEY_NEW 173 + +/* Reason codes. */ +# define ASN1_R_ADDING_OBJECT 171 +# define ASN1_R_ASN1_PARSE_ERROR 203 +# define ASN1_R_ASN1_SIG_PARSE_ERROR 204 +# define ASN1_R_AUX_ERROR 100 +# define ASN1_R_BAD_CLASS 101 +# define ASN1_R_BAD_OBJECT_HEADER 102 +# define ASN1_R_BAD_PASSWORD_READ 103 +# define ASN1_R_BAD_TAG 104 +# define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 214 +# define ASN1_R_BN_LIB 105 +# define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106 +# define ASN1_R_BUFFER_TOO_SMALL 107 +# define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108 +# define ASN1_R_CONTEXT_NOT_INITIALISED 217 +# define ASN1_R_DATA_IS_WRONG 109 +# define ASN1_R_DECODE_ERROR 110 +# define ASN1_R_DECODING_ERROR 111 +# define ASN1_R_DEPTH_EXCEEDED 174 +# define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 198 +# define ASN1_R_ENCODE_ERROR 112 +# define ASN1_R_ERROR_GETTING_TIME 173 +# define ASN1_R_ERROR_LOADING_SECTION 172 +# define ASN1_R_ERROR_PARSING_SET_ELEMENT 113 +# define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114 +# define ASN1_R_EXPECTING_AN_INTEGER 115 +# define ASN1_R_EXPECTING_AN_OBJECT 116 +# define ASN1_R_EXPECTING_A_BOOLEAN 117 +# define ASN1_R_EXPECTING_A_TIME 118 +# define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119 +# define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120 +# define ASN1_R_FIELD_MISSING 121 +# define ASN1_R_FIRST_NUM_TOO_LARGE 122 +# define ASN1_R_HEADER_TOO_LONG 123 +# define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175 +# define ASN1_R_ILLEGAL_BOOLEAN 176 +# define ASN1_R_ILLEGAL_CHARACTERS 124 +# define ASN1_R_ILLEGAL_FORMAT 177 +# define ASN1_R_ILLEGAL_HEX 178 +# define ASN1_R_ILLEGAL_IMPLICIT_TAG 179 +# define ASN1_R_ILLEGAL_INTEGER 180 +# define ASN1_R_ILLEGAL_NESTED_TAGGING 181 +# define ASN1_R_ILLEGAL_NULL 125 +# define ASN1_R_ILLEGAL_NULL_VALUE 182 +# define ASN1_R_ILLEGAL_OBJECT 183 +# define ASN1_R_ILLEGAL_OPTIONAL_ANY 126 +# define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170 +# define ASN1_R_ILLEGAL_TAGGED_ANY 127 +# define ASN1_R_ILLEGAL_TIME_VALUE 184 +# define ASN1_R_INTEGER_NOT_ASCII_FORMAT 185 +# define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128 +# define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 220 +# define ASN1_R_INVALID_BMPSTRING_LENGTH 129 +# define ASN1_R_INVALID_DIGIT 130 +# define ASN1_R_INVALID_MIME_TYPE 205 +# define ASN1_R_INVALID_MODIFIER 186 +# define ASN1_R_INVALID_NUMBER 187 +# define ASN1_R_INVALID_OBJECT_ENCODING 216 +# define ASN1_R_INVALID_SEPARATOR 131 +# define ASN1_R_INVALID_TIME_FORMAT 132 +# define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133 +# define ASN1_R_INVALID_UTF8STRING 134 +# define ASN1_R_IV_TOO_LARGE 135 +# define ASN1_R_LENGTH_ERROR 136 +# define ASN1_R_LIST_ERROR 188 +# define ASN1_R_MIME_NO_CONTENT_TYPE 206 +# define ASN1_R_MIME_PARSE_ERROR 207 +# define ASN1_R_MIME_SIG_PARSE_ERROR 208 +# define ASN1_R_MISSING_EOC 137 +# define ASN1_R_MISSING_SECOND_NUMBER 138 +# define ASN1_R_MISSING_VALUE 189 +# define ASN1_R_MSTRING_NOT_UNIVERSAL 139 +# define ASN1_R_MSTRING_WRONG_TAG 140 +# define ASN1_R_NESTED_ASN1_STRING 197 +# define ASN1_R_NESTED_TOO_DEEP 219 +# define ASN1_R_NON_HEX_CHARACTERS 141 +# define ASN1_R_NOT_ASCII_FORMAT 190 +# define ASN1_R_NOT_ENOUGH_DATA 142 +# define ASN1_R_NO_CONTENT_TYPE 209 +# define ASN1_R_NO_DEFAULT_DIGEST 201 +# define ASN1_R_NO_MATCHING_CHOICE_TYPE 143 +# define ASN1_R_NO_MULTIPART_BODY_FAILURE 210 +# define ASN1_R_NO_MULTIPART_BOUNDARY 211 +# define ASN1_R_NO_SIG_CONTENT_TYPE 212 +# define ASN1_R_NULL_IS_WRONG_LENGTH 144 +# define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191 +# define ASN1_R_ODD_NUMBER_OF_CHARS 145 +# define ASN1_R_PRIVATE_KEY_HEADER_MISSING 146 +# define ASN1_R_SECOND_NUMBER_TOO_LARGE 147 +# define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148 +# define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149 +# define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192 +# define ASN1_R_SHORT_LINE 150 +# define ASN1_R_SIG_INVALID_MIME_TYPE 213 +# define ASN1_R_STREAMING_NOT_SUPPORTED 202 +# define ASN1_R_STRING_TOO_LONG 151 +# define ASN1_R_STRING_TOO_SHORT 152 +# define ASN1_R_TAG_VALUE_TOO_HIGH 153 +# define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154 +# define ASN1_R_TIME_NOT_ASCII_FORMAT 193 +# define ASN1_R_TOO_LONG 155 +# define ASN1_R_TYPE_NOT_CONSTRUCTED 156 +# define ASN1_R_TYPE_NOT_PRIMITIVE 218 +# define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 157 +# define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 158 +# define ASN1_R_UNEXPECTED_EOC 159 +# define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215 +# define ASN1_R_UNKNOWN_FORMAT 160 +# define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161 +# define ASN1_R_UNKNOWN_OBJECT_TYPE 162 +# define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163 +# define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 199 +# define ASN1_R_UNKNOWN_TAG 194 +# define ASN1_R_UNKOWN_FORMAT 195 +# define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164 +# define ASN1_R_UNSUPPORTED_CIPHER 165 +# define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 166 +# define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167 +# define ASN1_R_UNSUPPORTED_TYPE 196 +# define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200 +# define ASN1_R_WRONG_TAG 168 +# define ASN1_R_WRONG_TYPE 169 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/asn1_mac.h b/optee/optee_test/host/openssl/include/openssl/asn1_mac.h new file mode 100644 index 0000000..abc6dc3 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/asn1_mac.h @@ -0,0 +1,579 @@ +/* crypto/asn1/asn1_mac.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ASN1_MAC_H +# define HEADER_ASN1_MAC_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifndef ASN1_MAC_ERR_LIB +# define ASN1_MAC_ERR_LIB ERR_LIB_ASN1 +# endif + +# define ASN1_MAC_H_err(f,r,line) \ + ERR_PUT_error(ASN1_MAC_ERR_LIB,(f),(r),__FILE__,(line)) + +# define M_ASN1_D2I_vars(a,type,func) \ + ASN1_const_CTX c; \ + type ret=NULL; \ + \ + c.pp=(const unsigned char **)pp; \ + c.q= *(const unsigned char **)pp; \ + c.error=ERR_R_NESTED_ASN1_ERROR; \ + if ((a == NULL) || ((*a) == NULL)) \ + { if ((ret=(type)func()) == NULL) \ + { c.line=__LINE__; goto err; } } \ + else ret=(*a); + +# define M_ASN1_D2I_Init() \ + c.p= *(const unsigned char **)pp; \ + c.max=(length == 0)?0:(c.p+length); + +# define M_ASN1_D2I_Finish_2(a) \ + if (!asn1_const_Finish(&c)) \ + { c.line=__LINE__; goto err; } \ + *(const unsigned char **)pp=c.p; \ + if (a != NULL) (*a)=ret; \ + return(ret); + +# define M_ASN1_D2I_Finish(a,func,e) \ + M_ASN1_D2I_Finish_2(a); \ +err:\ + ASN1_MAC_H_err((e),c.error,c.line); \ + asn1_add_error(*(const unsigned char **)pp,(int)(c.q- *pp)); \ + if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \ + return(NULL) + +# define M_ASN1_D2I_start_sequence() \ + if (!asn1_GetSequence(&c,&length)) \ + { c.line=__LINE__; goto err; } +/* Begin reading ASN1 without a surrounding sequence */ +# define M_ASN1_D2I_begin() \ + c.slen = length; + +/* End reading ASN1 with no check on length */ +# define M_ASN1_D2I_Finish_nolen(a, func, e) \ + *pp=c.p; \ + if (a != NULL) (*a)=ret; \ + return(ret); \ +err:\ + ASN1_MAC_H_err((e),c.error,c.line); \ + asn1_add_error(*pp,(int)(c.q- *pp)); \ + if ((ret != NULL) && ((a == NULL) || (*a != ret))) func(ret); \ + return(NULL) + +# define M_ASN1_D2I_end_sequence() \ + (((c.inf&1) == 0)?(c.slen <= 0): \ + (c.eos=ASN1_const_check_infinite_end(&c.p,c.slen))) + +/* Don't use this with d2i_ASN1_BOOLEAN() */ +# define M_ASN1_D2I_get(b, func) \ + c.q=c.p; \ + if (func(&(b),&c.p,c.slen) == NULL) \ + {c.line=__LINE__; goto err; } \ + c.slen-=(c.p-c.q); + +/* Don't use this with d2i_ASN1_BOOLEAN() */ +# define M_ASN1_D2I_get_x(type,b,func) \ + c.q=c.p; \ + if (((D2I_OF(type))func)(&(b),&c.p,c.slen) == NULL) \ + {c.line=__LINE__; goto err; } \ + c.slen-=(c.p-c.q); + +/* use this instead () */ +# define M_ASN1_D2I_get_int(b,func) \ + c.q=c.p; \ + if (func(&(b),&c.p,c.slen) < 0) \ + {c.line=__LINE__; goto err; } \ + c.slen-=(c.p-c.q); + +# define M_ASN1_D2I_get_opt(b,func,type) \ + if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \ + == (V_ASN1_UNIVERSAL|(type)))) \ + { \ + M_ASN1_D2I_get(b,func); \ + } + +# define M_ASN1_D2I_get_int_opt(b,func,type) \ + if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) \ + == (V_ASN1_UNIVERSAL|(type)))) \ + { \ + M_ASN1_D2I_get_int(b,func); \ + } + +# define M_ASN1_D2I_get_imp(b,func, type) \ + M_ASN1_next=(_tmp& V_ASN1_CONSTRUCTED)|type; \ + c.q=c.p; \ + if (func(&(b),&c.p,c.slen) == NULL) \ + {c.line=__LINE__; M_ASN1_next_prev = _tmp; goto err; } \ + c.slen-=(c.p-c.q);\ + M_ASN1_next_prev=_tmp; + +# define M_ASN1_D2I_get_IMP_opt(b,func,tag,type) \ + if ((c.slen != 0) && ((M_ASN1_next & (~V_ASN1_CONSTRUCTED)) == \ + (V_ASN1_CONTEXT_SPECIFIC|(tag)))) \ + { \ + unsigned char _tmp = M_ASN1_next; \ + M_ASN1_D2I_get_imp(b,func, type);\ + } + +# define M_ASN1_D2I_get_set(r,func,free_func) \ + M_ASN1_D2I_get_imp_set(r,func,free_func, \ + V_ASN1_SET,V_ASN1_UNIVERSAL); + +# define M_ASN1_D2I_get_set_type(type,r,func,free_func) \ + M_ASN1_D2I_get_imp_set_type(type,r,func,free_func, \ + V_ASN1_SET,V_ASN1_UNIVERSAL); + +# define M_ASN1_D2I_get_set_opt(r,func,free_func) \ + if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \ + V_ASN1_CONSTRUCTED|V_ASN1_SET)))\ + { M_ASN1_D2I_get_set(r,func,free_func); } + +# define M_ASN1_D2I_get_set_opt_type(type,r,func,free_func) \ + if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \ + V_ASN1_CONSTRUCTED|V_ASN1_SET)))\ + { M_ASN1_D2I_get_set_type(type,r,func,free_func); } + +# define M_ASN1_I2D_len_SET_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_len_SET(a,f); + +# define M_ASN1_I2D_put_SET_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_put_SET(a,f); + +# define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_put_SEQUENCE(a,f); + +# define M_ASN1_I2D_put_SEQUENCE_opt_type(type,a,f) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + M_ASN1_I2D_put_SEQUENCE_type(type,a,f); + +# define M_ASN1_D2I_get_IMP_set_opt(b,func,free_func,tag) \ + if ((c.slen != 0) && \ + (M_ASN1_next == \ + (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\ + { \ + M_ASN1_D2I_get_imp_set(b,func,free_func,\ + tag,V_ASN1_CONTEXT_SPECIFIC); \ + } + +# define M_ASN1_D2I_get_IMP_set_opt_type(type,b,func,free_func,tag) \ + if ((c.slen != 0) && \ + (M_ASN1_next == \ + (V_ASN1_CONTEXT_SPECIFIC|V_ASN1_CONSTRUCTED|(tag))))\ + { \ + M_ASN1_D2I_get_imp_set_type(type,b,func,free_func,\ + tag,V_ASN1_CONTEXT_SPECIFIC); \ + } + +# define M_ASN1_D2I_get_seq(r,func,free_func) \ + M_ASN1_D2I_get_imp_set(r,func,free_func,\ + V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL); + +# define M_ASN1_D2I_get_seq_type(type,r,func,free_func) \ + M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\ + V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL) + +# define M_ASN1_D2I_get_seq_opt(r,func,free_func) \ + if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \ + V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\ + { M_ASN1_D2I_get_seq(r,func,free_func); } + +# define M_ASN1_D2I_get_seq_opt_type(type,r,func,free_func) \ + if ((c.slen != 0) && (M_ASN1_next == (V_ASN1_UNIVERSAL| \ + V_ASN1_CONSTRUCTED|V_ASN1_SEQUENCE)))\ + { M_ASN1_D2I_get_seq_type(type,r,func,free_func); } + +# define M_ASN1_D2I_get_IMP_set(r,func,free_func,x) \ + M_ASN1_D2I_get_imp_set(r,func,free_func,\ + x,V_ASN1_CONTEXT_SPECIFIC); + +# define M_ASN1_D2I_get_IMP_set_type(type,r,func,free_func,x) \ + M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,\ + x,V_ASN1_CONTEXT_SPECIFIC); + +# define M_ASN1_D2I_get_imp_set(r,func,free_func,a,b) \ + c.q=c.p; \ + if (d2i_ASN1_SET(&(r),&c.p,c.slen,(char *(*)())func,\ + (void (*)())free_func,a,b) == NULL) \ + { c.line=__LINE__; goto err; } \ + c.slen-=(c.p-c.q); + +# define M_ASN1_D2I_get_imp_set_type(type,r,func,free_func,a,b) \ + c.q=c.p; \ + if (d2i_ASN1_SET_OF_##type(&(r),&c.p,c.slen,func,\ + free_func,a,b) == NULL) \ + { c.line=__LINE__; goto err; } \ + c.slen-=(c.p-c.q); + +# define M_ASN1_D2I_get_set_strings(r,func,a,b) \ + c.q=c.p; \ + if (d2i_ASN1_STRING_SET(&(r),&c.p,c.slen,a,b) == NULL) \ + { c.line=__LINE__; goto err; } \ + c.slen-=(c.p-c.q); + +# define M_ASN1_D2I_get_EXP_opt(r,func,tag) \ + if ((c.slen != 0L) && (M_ASN1_next == \ + (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \ + { \ + int Tinf,Ttag,Tclass; \ + long Tlen; \ + \ + c.q=c.p; \ + Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \ + if (Tinf & 0x80) \ + { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \ + c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) \ + Tlen = c.slen - (c.p - c.q) - 2; \ + if (func(&(r),&c.p,Tlen) == NULL) \ + { c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \ + Tlen = c.slen - (c.p - c.q); \ + if(!ASN1_const_check_infinite_end(&c.p, Tlen)) \ + { c.error=ERR_R_MISSING_ASN1_EOS; \ + c.line=__LINE__; goto err; } \ + }\ + c.slen-=(c.p-c.q); \ + } + +# define M_ASN1_D2I_get_EXP_set_opt(r,func,free_func,tag,b) \ + if ((c.slen != 0) && (M_ASN1_next == \ + (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \ + { \ + int Tinf,Ttag,Tclass; \ + long Tlen; \ + \ + c.q=c.p; \ + Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \ + if (Tinf & 0x80) \ + { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \ + c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) \ + Tlen = c.slen - (c.p - c.q) - 2; \ + if (d2i_ASN1_SET(&(r),&c.p,Tlen,(char *(*)())func, \ + (void (*)())free_func, \ + b,V_ASN1_UNIVERSAL) == NULL) \ + { c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \ + Tlen = c.slen - (c.p - c.q); \ + if(!ASN1_check_infinite_end(&c.p, Tlen)) \ + { c.error=ERR_R_MISSING_ASN1_EOS; \ + c.line=__LINE__; goto err; } \ + }\ + c.slen-=(c.p-c.q); \ + } + +# define M_ASN1_D2I_get_EXP_set_opt_type(type,r,func,free_func,tag,b) \ + if ((c.slen != 0) && (M_ASN1_next == \ + (V_ASN1_CONSTRUCTED|V_ASN1_CONTEXT_SPECIFIC|tag))) \ + { \ + int Tinf,Ttag,Tclass; \ + long Tlen; \ + \ + c.q=c.p; \ + Tinf=ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen); \ + if (Tinf & 0x80) \ + { c.error=ERR_R_BAD_ASN1_OBJECT_HEADER; \ + c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) \ + Tlen = c.slen - (c.p - c.q) - 2; \ + if (d2i_ASN1_SET_OF_##type(&(r),&c.p,Tlen,func, \ + free_func,b,V_ASN1_UNIVERSAL) == NULL) \ + { c.line=__LINE__; goto err; } \ + if (Tinf == (V_ASN1_CONSTRUCTED+1)) { \ + Tlen = c.slen - (c.p - c.q); \ + if(!ASN1_check_infinite_end(&c.p, Tlen)) \ + { c.error=ERR_R_MISSING_ASN1_EOS; \ + c.line=__LINE__; goto err; } \ + }\ + c.slen-=(c.p-c.q); \ + } + +/* New macros */ +# define M_ASN1_New_Malloc(ret,type) \ + if ((ret=(type *)OPENSSL_malloc(sizeof(type))) == NULL) \ + { c.line=__LINE__; goto err2; } + +# define M_ASN1_New(arg,func) \ + if (((arg)=func()) == NULL) return(NULL) + +# define M_ASN1_New_Error(a) \ +/*- err: ASN1_MAC_H_err((a),ERR_R_NESTED_ASN1_ERROR,c.line); \ + return(NULL);*/ \ + err2: ASN1_MAC_H_err((a),ERR_R_MALLOC_FAILURE,c.line); \ + return(NULL) + +/* + * BIG UGLY WARNING! This is so damn ugly I wanna puke. Unfortunately, some + * macros that use ASN1_const_CTX still insist on writing in the input + * stream. ARGH! ARGH! ARGH! Let's get rid of this macro package. Please? -- + * Richard Levitte + */ +# define M_ASN1_next (*((unsigned char *)(c.p))) +# define M_ASN1_next_prev (*((unsigned char *)(c.q))) + +/*************************************************/ + +# define M_ASN1_I2D_vars(a) int r=0,ret=0; \ + unsigned char *p; \ + if (a == NULL) return(0) + +/* Length Macros */ +# define M_ASN1_I2D_len(a,f) ret+=f(a,NULL) +# define M_ASN1_I2D_len_IMP_opt(a,f) if (a != NULL) M_ASN1_I2D_len(a,f) + +# define M_ASN1_I2D_len_SET(a,f) \ + ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET); + +# define M_ASN1_I2D_len_SET_type(type,a,f) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SET, \ + V_ASN1_UNIVERSAL,IS_SET); + +# define M_ASN1_I2D_len_SEQUENCE(a,f) \ + ret+=i2d_ASN1_SET(a,NULL,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \ + IS_SEQUENCE); + +# define M_ASN1_I2D_len_SEQUENCE_type(type,a,f) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,V_ASN1_SEQUENCE, \ + V_ASN1_UNIVERSAL,IS_SEQUENCE) + +# define M_ASN1_I2D_len_SEQUENCE_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_len_SEQUENCE(a,f); + +# define M_ASN1_I2D_len_SEQUENCE_opt_type(type,a,f) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + M_ASN1_I2D_len_SEQUENCE_type(type,a,f); + +# define M_ASN1_I2D_len_IMP_SET(a,f,x) \ + ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET); + +# define M_ASN1_I2D_len_IMP_SET_type(type,a,f,x) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \ + V_ASN1_CONTEXT_SPECIFIC,IS_SET); + +# define M_ASN1_I2D_len_IMP_SET_opt(a,f,x) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SET); + +# define M_ASN1_I2D_len_IMP_SET_opt_type(type,a,f,x) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \ + V_ASN1_CONTEXT_SPECIFIC,IS_SET); + +# define M_ASN1_I2D_len_IMP_SEQUENCE(a,f,x) \ + ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); + +# define M_ASN1_I2D_len_IMP_SEQUENCE_opt(a,f,x) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + ret+=i2d_ASN1_SET(a,NULL,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); + +# define M_ASN1_I2D_len_IMP_SEQUENCE_opt_type(type,a,f,x) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + ret+=i2d_ASN1_SET_OF_##type(a,NULL,f,x, \ + V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); + +# define M_ASN1_I2D_len_EXP_opt(a,f,mtag,v) \ + if (a != NULL)\ + { \ + v=f(a,NULL); \ + ret+=ASN1_object_size(1,v,mtag); \ + } + +# define M_ASN1_I2D_len_EXP_SET_opt(a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_num(a) != 0))\ + { \ + v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL,IS_SET); \ + ret+=ASN1_object_size(1,v,mtag); \ + } + +# define M_ASN1_I2D_len_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_num(a) != 0))\ + { \ + v=i2d_ASN1_SET(a,NULL,f,tag,V_ASN1_UNIVERSAL, \ + IS_SEQUENCE); \ + ret+=ASN1_object_size(1,v,mtag); \ + } + +# define M_ASN1_I2D_len_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_##type##_num(a) != 0))\ + { \ + v=i2d_ASN1_SET_OF_##type(a,NULL,f,tag, \ + V_ASN1_UNIVERSAL, \ + IS_SEQUENCE); \ + ret+=ASN1_object_size(1,v,mtag); \ + } + +/* Put Macros */ +# define M_ASN1_I2D_put(a,f) f(a,&p) + +# define M_ASN1_I2D_put_IMP_opt(a,f,t) \ + if (a != NULL) \ + { \ + unsigned char *q=p; \ + f(a,&p); \ + *q=(V_ASN1_CONTEXT_SPECIFIC|t|(*q&V_ASN1_CONSTRUCTED));\ + } + +# define M_ASN1_I2D_put_SET(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SET,\ + V_ASN1_UNIVERSAL,IS_SET) +# define M_ASN1_I2D_put_SET_type(type,a,f) \ + i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET) +# define M_ASN1_I2D_put_IMP_SET(a,f,x) i2d_ASN1_SET(a,&p,f,x,\ + V_ASN1_CONTEXT_SPECIFIC,IS_SET) +# define M_ASN1_I2D_put_IMP_SET_type(type,a,f,x) \ + i2d_ASN1_SET_OF_##type(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC,IS_SET) +# define M_ASN1_I2D_put_IMP_SEQUENCE(a,f,x) i2d_ASN1_SET(a,&p,f,x,\ + V_ASN1_CONTEXT_SPECIFIC,IS_SEQUENCE) + +# define M_ASN1_I2D_put_SEQUENCE(a,f) i2d_ASN1_SET(a,&p,f,V_ASN1_SEQUENCE,\ + V_ASN1_UNIVERSAL,IS_SEQUENCE) + +# define M_ASN1_I2D_put_SEQUENCE_type(type,a,f) \ + i2d_ASN1_SET_OF_##type(a,&p,f,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL, \ + IS_SEQUENCE) + +# define M_ASN1_I2D_put_SEQUENCE_opt(a,f) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + M_ASN1_I2D_put_SEQUENCE(a,f); + +# define M_ASN1_I2D_put_IMP_SET_opt(a,f,x) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SET); } + +# define M_ASN1_I2D_put_IMP_SET_opt_type(type,a,f,x) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + { i2d_ASN1_SET_OF_##type(a,&p,f,x, \ + V_ASN1_CONTEXT_SPECIFIC, \ + IS_SET); } + +# define M_ASN1_I2D_put_IMP_SEQUENCE_opt(a,f,x) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + { i2d_ASN1_SET(a,&p,f,x,V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); } + +# define M_ASN1_I2D_put_IMP_SEQUENCE_opt_type(type,a,f,x) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + { i2d_ASN1_SET_OF_##type(a,&p,f,x, \ + V_ASN1_CONTEXT_SPECIFIC, \ + IS_SEQUENCE); } + +# define M_ASN1_I2D_put_EXP_opt(a,f,tag,v) \ + if (a != NULL) \ + { \ + ASN1_put_object(&p,1,v,tag,V_ASN1_CONTEXT_SPECIFIC); \ + f(a,&p); \ + } + +# define M_ASN1_I2D_put_EXP_SET_opt(a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + { \ + ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \ + i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SET); \ + } + +# define M_ASN1_I2D_put_EXP_SEQUENCE_opt(a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_num(a) != 0)) \ + { \ + ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \ + i2d_ASN1_SET(a,&p,f,tag,V_ASN1_UNIVERSAL,IS_SEQUENCE); \ + } + +# define M_ASN1_I2D_put_EXP_SEQUENCE_opt_type(type,a,f,mtag,tag,v) \ + if ((a != NULL) && (sk_##type##_num(a) != 0)) \ + { \ + ASN1_put_object(&p,1,v,mtag,V_ASN1_CONTEXT_SPECIFIC); \ + i2d_ASN1_SET_OF_##type(a,&p,f,tag,V_ASN1_UNIVERSAL, \ + IS_SEQUENCE); \ + } + +# define M_ASN1_I2D_seq_total() \ + r=ASN1_object_size(1,ret,V_ASN1_SEQUENCE); \ + if (pp == NULL) return(r); \ + p= *pp; \ + ASN1_put_object(&p,1,ret,V_ASN1_SEQUENCE,V_ASN1_UNIVERSAL) + +# define M_ASN1_I2D_INF_seq_start(tag,ctx) \ + *(p++)=(V_ASN1_CONSTRUCTED|(tag)|(ctx)); \ + *(p++)=0x80 + +# define M_ASN1_I2D_INF_seq_end() *(p++)=0x00; *(p++)=0x00 + +# define M_ASN1_I2D_finish() *pp=p; \ + return(r); + +int asn1_GetSequence(ASN1_const_CTX *c, long *length); +void asn1_add_error(const unsigned char *address, int offset); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/asn1t.h b/optee/optee_test/host/openssl/include/openssl/asn1t.h new file mode 100644 index 0000000..99bc0ee --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/asn1t.h @@ -0,0 +1,973 @@ +/* asn1t.h */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef HEADER_ASN1T_H +# define HEADER_ASN1T_H + +# include +# include +# include + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +/* ASN1 template defines, structures and functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr)) + +/* Macros for start and end of ASN1_ITEM definition */ + +# define ASN1_ITEM_start(itname) \ + OPENSSL_GLOBAL const ASN1_ITEM itname##_it = { + +# define ASN1_ITEM_end(itname) \ + }; + +# else + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +# define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr())) + +/* Macros for start and end of ASN1_ITEM definition */ + +# define ASN1_ITEM_start(itname) \ + const ASN1_ITEM * itname##_it(void) \ + { \ + static const ASN1_ITEM local_it = { + +# define ASN1_ITEM_end(itname) \ + }; \ + return &local_it; \ + } + +# endif + +/* Macros to aid ASN1 template writing */ + +# define ASN1_ITEM_TEMPLATE(tname) \ + static const ASN1_TEMPLATE tname##_item_tt + +# define ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) + +/* This is a ASN1 type which just embeds a template */ + +/*- + * This pair helps declare a SEQUENCE. We can do: + * + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END(stname) + * + * This will produce an ASN1_ITEM called stname_it + * for a structure called stname. + * + * If you want the same structure but a different + * name then use: + * + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END_name(stname, itname) + * + * This will create an item called itname_it using + * a structure called stname. + */ + +# define ASN1_SEQUENCE(tname) \ + static const ASN1_TEMPLATE tname##_seq_tt[] + +# define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) + +# define ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_NDEF_SEQUENCE(tname) \ + ASN1_SEQUENCE(tname) + +# define ASN1_NDEF_SEQUENCE_cb(tname, cb) \ + ASN1_SEQUENCE_cb(tname, cb) + +# define ASN1_SEQUENCE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_BROKEN_SEQUENCE(tname) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_SEQUENCE_ref(tname, cb, lck) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_SEQUENCE_enc(tname, enc, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \ + ASN1_SEQUENCE(tname) + +# define ASN1_NDEF_SEQUENCE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(tname),\ + #tname \ + ASN1_ITEM_end(tname) + +# define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname) + +# define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +# define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +# define ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/*- + * This pair helps declare a CHOICE type. We can do: + * + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname) + * + * This will produce an ASN1_ITEM called chname_it + * for a structure called chname. The structure + * definition must look like this: + * typedef struct { + * int type; + * union { + * ASN1_SOMETHING *opt1; + * ASN1_SOMEOTHER *opt2; + * } value; + * } chname; + * + * the name of the selector must be 'type'. + * to use an alternative selector name use the + * ASN1_CHOICE_END_selector() version. + */ + +# define ASN1_CHOICE(tname) \ + static const ASN1_TEMPLATE tname##_ch_tt[] + +# define ASN1_CHOICE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_CHOICE(tname) + +# define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) + +# define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type) + +# define ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +# define ASN1_CHOICE_END_cb(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/* This helps with the template wrapper form of ASN1_ITEM */ + +# define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \ + (flags), (tag), 0,\ + #name, ASN1_ITEM_ref(type) } + +/* These help with SEQUENCE or CHOICE components */ + +/* used to declare other types */ + +# define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ + (flags), (tag), offsetof(stname, field),\ + #field, ASN1_ITEM_ref(type) } + +/* used when the structure is combined with the parent */ + +# define ASN1_EX_COMBINE(flags, tag, type) { \ + (flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) } + +/* implicit and explicit helper macros */ + +# define ASN1_IMP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type) + +# define ASN1_EXP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type) + +/* Any defined by macros: the field used is in the table itself */ + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION +# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +# else +# define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb } +# define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb } +# endif +/* Plain simple type */ +# define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) + +/* OPTIONAL simple type */ +# define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* IMPLICIT tagged simple type */ +# define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) + +/* IMPLICIT tagged OPTIONAL simple type */ +# define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* Same as above but EXPLICIT */ + +# define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) +# define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* SEQUENCE OF type */ +# define ASN1_SEQUENCE_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) + +/* OPTIONAL SEQUENCE OF */ +# define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Same as above but for SET OF */ + +# define ASN1_SET_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) + +# define ASN1_SET_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ + +# define ASN1_IMP_SET_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +# define ASN1_EXP_SET_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +# define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +# define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +# define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +# define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +/* EXPLICIT using indefinite length constructed form */ +# define ASN1_NDEF_EXP(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF) + +/* EXPLICIT OPTIONAL using indefinite length constructed form */ +# define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF) + +/* Macros for the ASN1_ADB structure */ + +# define ASN1_ADB(name) \ + static const ASN1_ADB_TABLE name##_adbtbl[] + +# ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION + +# define ASN1_ADB_END(name, flags, field, app_table, def, none) \ + ;\ + static const ASN1_ADB name##_adb = {\ + flags,\ + offsetof(name, field),\ + app_table,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + } + +# else + +# define ASN1_ADB_END(name, flags, field, app_table, def, none) \ + ;\ + static const ASN1_ITEM *name##_adb(void) \ + { \ + static const ASN1_ADB internal_adb = \ + {\ + flags,\ + offsetof(name, field),\ + app_table,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + }; \ + return (const ASN1_ITEM *) &internal_adb; \ + } \ + void dummy_function(void) + +# endif + +# define ADB_ENTRY(val, template) {val, template} + +# define ASN1_ADB_TEMPLATE(name) \ + static const ASN1_TEMPLATE name##_tt + +/* + * This is the ASN1 template structure that defines a wrapper round the + * actual type. It determines the actual position of the field in the value + * structure, various flags such as OPTIONAL and the field name. + */ + +struct ASN1_TEMPLATE_st { + unsigned long flags; /* Various flags */ + long tag; /* tag, not used if no tagging */ + unsigned long offset; /* Offset of this field in structure */ +# ifndef NO_ASN1_FIELD_NAMES + const char *field_name; /* Field name */ +# endif + ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ +}; + +/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ + +# define ASN1_TEMPLATE_item(t) (t->item_ptr) +# define ASN1_TEMPLATE_adb(t) (t->item_ptr) + +typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; +typedef struct ASN1_ADB_st ASN1_ADB; + +struct ASN1_ADB_st { + unsigned long flags; /* Various flags */ + unsigned long offset; /* Offset of selector field */ + STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */ + const ASN1_ADB_TABLE *tbl; /* Table of possible types */ + long tblcount; /* Number of entries in tbl */ + const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ + const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ +}; + +struct ASN1_ADB_TABLE_st { + long value; /* NID for an object or value for an int */ + const ASN1_TEMPLATE tt; /* item for this value */ +}; + +/* template flags */ + +/* Field is optional */ +# define ASN1_TFLG_OPTIONAL (0x1) + +/* Field is a SET OF */ +# define ASN1_TFLG_SET_OF (0x1 << 1) + +/* Field is a SEQUENCE OF */ +# define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) + +/* + * Special case: this refers to a SET OF that will be sorted into DER order + * when encoded *and* the corresponding STACK will be modified to match the + * new order. + */ +# define ASN1_TFLG_SET_ORDER (0x3 << 1) + +/* Mask for SET OF or SEQUENCE OF */ +# define ASN1_TFLG_SK_MASK (0x3 << 1) + +/* + * These flags mean the tag should be taken from the tag field. If EXPLICIT + * then the underlying type is used for the inner tag. + */ + +/* IMPLICIT tagging */ +# define ASN1_TFLG_IMPTAG (0x1 << 3) + +/* EXPLICIT tagging, inner tag from underlying type */ +# define ASN1_TFLG_EXPTAG (0x2 << 3) + +# define ASN1_TFLG_TAG_MASK (0x3 << 3) + +/* context specific IMPLICIT */ +# define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT + +/* context specific EXPLICIT */ +# define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT + +/* + * If tagging is in force these determine the type of tag to use. Otherwise + * the tag is determined by the underlying type. These values reflect the + * actual octet format. + */ + +/* Universal tag */ +# define ASN1_TFLG_UNIVERSAL (0x0<<6) +/* Application tag */ +# define ASN1_TFLG_APPLICATION (0x1<<6) +/* Context specific tag */ +# define ASN1_TFLG_CONTEXT (0x2<<6) +/* Private tag */ +# define ASN1_TFLG_PRIVATE (0x3<<6) + +# define ASN1_TFLG_TAG_CLASS (0x3<<6) + +/* + * These are for ANY DEFINED BY type. In this case the 'item' field points to + * an ASN1_ADB structure which contains a table of values to decode the + * relevant type + */ + +# define ASN1_TFLG_ADB_MASK (0x3<<8) + +# define ASN1_TFLG_ADB_OID (0x1<<8) + +# define ASN1_TFLG_ADB_INT (0x1<<9) + +/* + * This flag means a parent structure is passed instead of the field: this is + * useful is a SEQUENCE is being combined with a CHOICE for example. Since + * this means the structure and item name will differ we need to use the + * ASN1_CHOICE_END_name() macro for example. + */ + +# define ASN1_TFLG_COMBINE (0x1<<10) + +/* + * This flag when present in a SEQUENCE OF, SET OF or EXPLICIT causes + * indefinite length constructed encoding to be used if required. + */ + +# define ASN1_TFLG_NDEF (0x1<<11) + +/* This is the actual ASN1 item itself */ + +struct ASN1_ITEM_st { + char itype; /* The item type, primitive, SEQUENCE, CHOICE + * or extern */ + long utype; /* underlying type */ + const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains + * the contents */ + long tcount; /* Number of templates if SEQUENCE or CHOICE */ + const void *funcs; /* functions that handle this type */ + long size; /* Structure size (usually) */ +# ifndef NO_ASN1_FIELD_NAMES + const char *sname; /* Structure name */ +# endif +}; + +/*- + * These are values for the itype field and + * determine how the type is interpreted. + * + * For PRIMITIVE types the underlying type + * determines the behaviour if items is NULL. + * + * Otherwise templates must contain a single + * template and the type is treated in the + * same way as the type specified in the template. + * + * For SEQUENCE types the templates field points + * to the members, the size field is the + * structure size. + * + * For CHOICE types the templates field points + * to each possible member (typically a union) + * and the 'size' field is the offset of the + * selector. + * + * The 'funcs' field is used for application + * specific functions. + * + * For COMPAT types the funcs field gives a + * set of functions that handle this type, this + * supports the old d2i, i2d convention. + * + * The EXTERN type uses a new style d2i/i2d. + * The new style should be used where possible + * because it avoids things like the d2i IMPLICIT + * hack. + * + * MSTRING is a multiple string type, it is used + * for a CHOICE of character strings where the + * actual strings all occupy an ASN1_STRING + * structure. In this case the 'utype' field + * has a special meaning, it is used as a mask + * of acceptable types using the B_ASN1 constants. + * + * NDEF_SEQUENCE is the same as SEQUENCE except + * that it will use indefinite length constructed + * encoding if requested. + * + */ + +# define ASN1_ITYPE_PRIMITIVE 0x0 + +# define ASN1_ITYPE_SEQUENCE 0x1 + +# define ASN1_ITYPE_CHOICE 0x2 + +# define ASN1_ITYPE_COMPAT 0x3 + +# define ASN1_ITYPE_EXTERN 0x4 + +# define ASN1_ITYPE_MSTRING 0x5 + +# define ASN1_ITYPE_NDEF_SEQUENCE 0x6 + +/* + * Cache for ASN1 tag and length, so we don't keep re-reading it for things + * like CHOICE + */ + +struct ASN1_TLC_st { + char valid; /* Values below are valid */ + int ret; /* return value */ + long plen; /* length */ + int ptag; /* class value */ + int pclass; /* class value */ + int hdrlen; /* header length */ +}; + +/* Typedefs for ASN1 function pointers */ + +typedef ASN1_VALUE *ASN1_new_func(void); +typedef void ASN1_free_func(ASN1_VALUE *a); +typedef ASN1_VALUE *ASN1_d2i_func(ASN1_VALUE **a, const unsigned char **in, + long length); +typedef int ASN1_i2d_func(ASN1_VALUE *a, unsigned char **in); + +typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, char opt, + ASN1_TLC *ctx); + +typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); +typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); + +typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval, + int indent, const char *fname, + const ASN1_PCTX *pctx); + +typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, + int *putype, const ASN1_ITEM *it); +typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, + int len, int utype, char *free_cont, + const ASN1_ITEM *it); +typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval, + const ASN1_ITEM *it, int indent, + const ASN1_PCTX *pctx); + +typedef struct ASN1_COMPAT_FUNCS_st { + ASN1_new_func *asn1_new; + ASN1_free_func *asn1_free; + ASN1_d2i_func *asn1_d2i; + ASN1_i2d_func *asn1_i2d; +} ASN1_COMPAT_FUNCS; + +typedef struct ASN1_EXTERN_FUNCS_st { + void *app_data; + ASN1_ex_new_func *asn1_ex_new; + ASN1_ex_free_func *asn1_ex_free; + ASN1_ex_free_func *asn1_ex_clear; + ASN1_ex_d2i *asn1_ex_d2i; + ASN1_ex_i2d *asn1_ex_i2d; + ASN1_ex_print_func *asn1_ex_print; +} ASN1_EXTERN_FUNCS; + +typedef struct ASN1_PRIMITIVE_FUNCS_st { + void *app_data; + unsigned long flags; + ASN1_ex_new_func *prim_new; + ASN1_ex_free_func *prim_free; + ASN1_ex_free_func *prim_clear; + ASN1_primitive_c2i *prim_c2i; + ASN1_primitive_i2c *prim_i2c; + ASN1_primitive_print *prim_print; +} ASN1_PRIMITIVE_FUNCS; + +/* + * This is the ASN1_AUX structure: it handles various miscellaneous + * requirements. For example the use of reference counts and an informational + * callback. The "informational callback" is called at various points during + * the ASN1 encoding and decoding. It can be used to provide minor + * customisation of the structures used. This is most useful where the + * supplied routines *almost* do the right thing but need some extra help at + * a few points. If the callback returns zero then it is assumed a fatal + * error has occurred and the main operation should be abandoned. If major + * changes in the default behaviour are required then an external type is + * more appropriate. + */ + +typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it, + void *exarg); + +typedef struct ASN1_AUX_st { + void *app_data; + int flags; + int ref_offset; /* Offset of reference value */ + int ref_lock; /* Lock type to use */ + ASN1_aux_cb *asn1_cb; + int enc_offset; /* Offset of ASN1_ENCODING structure */ +} ASN1_AUX; + +/* For print related callbacks exarg points to this structure */ +typedef struct ASN1_PRINT_ARG_st { + BIO *out; + int indent; + const ASN1_PCTX *pctx; +} ASN1_PRINT_ARG; + +/* For streaming related callbacks exarg points to this structure */ +typedef struct ASN1_STREAM_ARG_st { + /* BIO to stream through */ + BIO *out; + /* BIO with filters appended */ + BIO *ndef_bio; + /* Streaming I/O boundary */ + unsigned char **boundary; +} ASN1_STREAM_ARG; + +/* Flags in ASN1_AUX */ + +/* Use a reference count */ +# define ASN1_AFLG_REFCOUNT 1 +/* Save the encoding of structure (useful for signatures) */ +# define ASN1_AFLG_ENCODING 2 +/* The Sequence length is invalid */ +# define ASN1_AFLG_BROKEN 4 + +/* operation values for asn1_cb */ + +# define ASN1_OP_NEW_PRE 0 +# define ASN1_OP_NEW_POST 1 +# define ASN1_OP_FREE_PRE 2 +# define ASN1_OP_FREE_POST 3 +# define ASN1_OP_D2I_PRE 4 +# define ASN1_OP_D2I_POST 5 +# define ASN1_OP_I2D_PRE 6 +# define ASN1_OP_I2D_POST 7 +# define ASN1_OP_PRINT_PRE 8 +# define ASN1_OP_PRINT_POST 9 +# define ASN1_OP_STREAM_PRE 10 +# define ASN1_OP_STREAM_POST 11 +# define ASN1_OP_DETACHED_PRE 12 +# define ASN1_OP_DETACHED_POST 13 + +/* Macro to implement a primitive type */ +# define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0) +# define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement a multi string type */ +# define IMPLEMENT_ASN1_MSTRING(itname, mask) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement an ASN1_ITEM in terms of old style funcs */ + +# define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE) + +# define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \ + static const ASN1_COMPAT_FUNCS sname##_ff = { \ + (ASN1_new_func *)sname##_new, \ + (ASN1_free_func *)sname##_free, \ + (ASN1_d2i_func *)d2i_##sname, \ + (ASN1_i2d_func *)i2d_##sname, \ + }; \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_COMPAT, \ + tag, \ + NULL, \ + 0, \ + &sname##_ff, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +# define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_EXTERN, \ + tag, \ + NULL, \ + 0, \ + &fptrs, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +/* Macro to implement standard functions in terms of ASN1_ITEM structures */ + +# define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname) + +# define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \ + IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname) + +# define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname) + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \ + pre stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + pre void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +# define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ + stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +# define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +# define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \ + int i2d_##stname##_NDEF(stname *a, unsigned char **out) \ + { \ + return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\ + } + +/* + * This includes evil casts to remove const: they will go away when full ASN1 + * constification is done. + */ +# define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(const stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +# define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ + stname * stname##_dup(stname *x) \ + { \ + return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \ + } + +# define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \ + IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname) + +# define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \ + int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx) \ + { \ + return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \ + ASN1_ITEM_rptr(itname), pctx); \ + } + +# define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ + IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) + +# define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +/* external definitions for primitive types */ + +DECLARE_ASN1_ITEM(ASN1_BOOLEAN) +DECLARE_ASN1_ITEM(ASN1_TBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_FBOOLEAN) +DECLARE_ASN1_ITEM(ASN1_SEQUENCE) +DECLARE_ASN1_ITEM(CBIGNUM) +DECLARE_ASN1_ITEM(BIGNUM) +DECLARE_ASN1_ITEM(LONG) +DECLARE_ASN1_ITEM(ZLONG) + +DECLARE_STACK_OF(ASN1_VALUE) + +/* Functions used internally by the ASN1 code */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it); + +void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_TEMPLATE *tt); +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, + const ASN1_ITEM *it, int tag, int aclass, char opt, + ASN1_TLC *ctx); + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_ITEM *it, int tag, int aclass); +int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, + const ASN1_TEMPLATE *tt); +void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, + const ASN1_ITEM *it); +int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, + int utype, char *free_cont, const ASN1_ITEM *it); + +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, + const ASN1_ITEM *it); + +ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, + int nullerr); + +int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it); + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, + const ASN1_ITEM *it); +int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, + const ASN1_ITEM *it); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/bio.h b/optee/optee_test/host/openssl/include/openssl/bio.h new file mode 100644 index 0000000..8f2438c --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/bio.h @@ -0,0 +1,883 @@ +/* crypto/bio/bio.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BIO_H +# define HEADER_BIO_H + +# include + +# ifndef OPENSSL_NO_FP_API +# include +# endif +# include + +# include + +# ifndef OPENSSL_NO_SCTP +# ifndef OPENSSL_SYS_VMS +# include +# else +# include +# endif +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* These are the 'types' of BIOs */ +# define BIO_TYPE_NONE 0 +# define BIO_TYPE_MEM (1|0x0400) +# define BIO_TYPE_FILE (2|0x0400) + +# define BIO_TYPE_FD (4|0x0400|0x0100) +# define BIO_TYPE_SOCKET (5|0x0400|0x0100) +# define BIO_TYPE_NULL (6|0x0400) +# define BIO_TYPE_SSL (7|0x0200) +# define BIO_TYPE_MD (8|0x0200)/* passive filter */ +# define BIO_TYPE_BUFFER (9|0x0200)/* filter */ +# define BIO_TYPE_CIPHER (10|0x0200)/* filter */ +# define BIO_TYPE_BASE64 (11|0x0200)/* filter */ +# define BIO_TYPE_CONNECT (12|0x0400|0x0100)/* socket - connect */ +# define BIO_TYPE_ACCEPT (13|0x0400|0x0100)/* socket for accept */ +# define BIO_TYPE_PROXY_CLIENT (14|0x0200)/* client proxy BIO */ +# define BIO_TYPE_PROXY_SERVER (15|0x0200)/* server proxy BIO */ +# define BIO_TYPE_NBIO_TEST (16|0x0200)/* server proxy BIO */ +# define BIO_TYPE_NULL_FILTER (17|0x0200) +# define BIO_TYPE_BER (18|0x0200)/* BER -> bin filter */ +# define BIO_TYPE_BIO (19|0x0400)/* (half a) BIO pair */ +# define BIO_TYPE_LINEBUFFER (20|0x0200)/* filter */ +# define BIO_TYPE_DGRAM (21|0x0400|0x0100) +# ifndef OPENSSL_NO_SCTP +# define BIO_TYPE_DGRAM_SCTP (24|0x0400|0x0100) +# endif +# define BIO_TYPE_ASN1 (22|0x0200)/* filter */ +# define BIO_TYPE_COMP (23|0x0200)/* filter */ + +# define BIO_TYPE_DESCRIPTOR 0x0100/* socket, fd, connect or accept */ +# define BIO_TYPE_FILTER 0x0200 +# define BIO_TYPE_SOURCE_SINK 0x0400 + +/* + * BIO_FILENAME_READ|BIO_CLOSE to open or close on free. + * BIO_set_fp(in,stdin,BIO_NOCLOSE); + */ +# define BIO_NOCLOSE 0x00 +# define BIO_CLOSE 0x01 + +/* + * These are used in the following macros and are passed to BIO_ctrl() + */ +# define BIO_CTRL_RESET 1/* opt - rewind/zero etc */ +# define BIO_CTRL_EOF 2/* opt - are we at the eof */ +# define BIO_CTRL_INFO 3/* opt - extra tit-bits */ +# define BIO_CTRL_SET 4/* man - set the 'IO' type */ +# define BIO_CTRL_GET 5/* man - get the 'IO' type */ +# define BIO_CTRL_PUSH 6/* opt - internal, used to signify change */ +# define BIO_CTRL_POP 7/* opt - internal, used to signify change */ +# define BIO_CTRL_GET_CLOSE 8/* man - set the 'close' on free */ +# define BIO_CTRL_SET_CLOSE 9/* man - set the 'close' on free */ +# define BIO_CTRL_PENDING 10/* opt - is their more data buffered */ +# define BIO_CTRL_FLUSH 11/* opt - 'flush' buffered output */ +# define BIO_CTRL_DUP 12/* man - extra stuff for 'duped' BIO */ +# define BIO_CTRL_WPENDING 13/* opt - number of bytes still to write */ +/* callback is int cb(BIO *bio,state,ret); */ +# define BIO_CTRL_SET_CALLBACK 14/* opt - set callback function */ +# define BIO_CTRL_GET_CALLBACK 15/* opt - set callback function */ + +# define BIO_CTRL_SET_FILENAME 30/* BIO_s_file special */ + +/* dgram BIO stuff */ +# define BIO_CTRL_DGRAM_CONNECT 31/* BIO dgram special */ +# define BIO_CTRL_DGRAM_SET_CONNECTED 32/* allow for an externally connected + * socket to be passed in */ +# define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33/* setsockopt, essentially */ +# define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34/* getsockopt, essentially */ +# define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35/* setsockopt, essentially */ +# define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36/* getsockopt, essentially */ + +# define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37/* flag whether the last */ +# define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38/* I/O operation tiemd out */ + +/* #ifdef IP_MTU_DISCOVER */ +# define BIO_CTRL_DGRAM_MTU_DISCOVER 39/* set DF bit on egress packets */ +/* #endif */ + +# define BIO_CTRL_DGRAM_QUERY_MTU 40/* as kernel for current MTU */ +# define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 +# define BIO_CTRL_DGRAM_GET_MTU 41/* get cached value for MTU */ +# define BIO_CTRL_DGRAM_SET_MTU 42/* set cached value for MTU. + * want to use this if asking + * the kernel fails */ + +# define BIO_CTRL_DGRAM_MTU_EXCEEDED 43/* check whether the MTU was + * exceed in the previous write + * operation */ + +# define BIO_CTRL_DGRAM_GET_PEER 46 +# define BIO_CTRL_DGRAM_SET_PEER 44/* Destination for the data */ + +# define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45/* Next DTLS handshake timeout + * to adjust socket timeouts */ +# define BIO_CTRL_DGRAM_SET_DONT_FRAG 48 + +# define BIO_CTRL_DGRAM_GET_MTU_OVERHEAD 49 + +# ifndef OPENSSL_NO_SCTP +/* SCTP stuff */ +# define BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE 50 +# define BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY 51 +# define BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY 52 +# define BIO_CTRL_DGRAM_SCTP_AUTH_CCS_RCVD 53 +# define BIO_CTRL_DGRAM_SCTP_GET_SNDINFO 60 +# define BIO_CTRL_DGRAM_SCTP_SET_SNDINFO 61 +# define BIO_CTRL_DGRAM_SCTP_GET_RCVINFO 62 +# define BIO_CTRL_DGRAM_SCTP_SET_RCVINFO 63 +# define BIO_CTRL_DGRAM_SCTP_GET_PRINFO 64 +# define BIO_CTRL_DGRAM_SCTP_SET_PRINFO 65 +# define BIO_CTRL_DGRAM_SCTP_SAVE_SHUTDOWN 70 +# endif + +/* modifiers */ +# define BIO_FP_READ 0x02 +# define BIO_FP_WRITE 0x04 +# define BIO_FP_APPEND 0x08 +# define BIO_FP_TEXT 0x10 + +# define BIO_FLAGS_READ 0x01 +# define BIO_FLAGS_WRITE 0x02 +# define BIO_FLAGS_IO_SPECIAL 0x04 +# define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL) +# define BIO_FLAGS_SHOULD_RETRY 0x08 +# ifndef BIO_FLAGS_UPLINK +/* + * "UPLINK" flag denotes file descriptors provided by application. It + * defaults to 0, as most platforms don't require UPLINK interface. + */ +# define BIO_FLAGS_UPLINK 0 +# endif + +/* Used in BIO_gethostbyname() */ +# define BIO_GHBN_CTRL_HITS 1 +# define BIO_GHBN_CTRL_MISSES 2 +# define BIO_GHBN_CTRL_CACHE_SIZE 3 +# define BIO_GHBN_CTRL_GET_ENTRY 4 +# define BIO_GHBN_CTRL_FLUSH 5 + +/* Mostly used in the SSL BIO */ +/*- + * Not used anymore + * #define BIO_FLAGS_PROTOCOL_DELAYED_READ 0x10 + * #define BIO_FLAGS_PROTOCOL_DELAYED_WRITE 0x20 + * #define BIO_FLAGS_PROTOCOL_STARTUP 0x40 + */ + +# define BIO_FLAGS_BASE64_NO_NL 0x100 + +/* + * This is used with memory BIOs: it means we shouldn't free up or change the + * data in any way. + */ +# define BIO_FLAGS_MEM_RDONLY 0x200 + +typedef struct bio_st BIO; + +void BIO_set_flags(BIO *b, int flags); +int BIO_test_flags(const BIO *b, int flags); +void BIO_clear_flags(BIO *b, int flags); + +# define BIO_get_flags(b) BIO_test_flags(b, ~(0x0)) +# define BIO_set_retry_special(b) \ + BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_set_retry_read(b) \ + BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_set_retry_write(b) \ + BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY)) + +/* These are normally used internally in BIOs */ +# define BIO_clear_retry_flags(b) \ + BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) +# define BIO_get_retry_flags(b) \ + BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) + +/* These should be used by the application to tell why we should retry */ +# define BIO_should_read(a) BIO_test_flags(a, BIO_FLAGS_READ) +# define BIO_should_write(a) BIO_test_flags(a, BIO_FLAGS_WRITE) +# define BIO_should_io_special(a) BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL) +# define BIO_retry_type(a) BIO_test_flags(a, BIO_FLAGS_RWS) +# define BIO_should_retry(a) BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY) + +/* + * The next three are used in conjunction with the BIO_should_io_special() + * condition. After this returns true, BIO *BIO_get_retry_BIO(BIO *bio, int + * *reason); will walk the BIO stack and return the 'reason' for the special + * and the offending BIO. Given a BIO, BIO_get_retry_reason(bio) will return + * the code. + */ +/* + * Returned from the SSL bio when the certificate retrieval code had an error + */ +# define BIO_RR_SSL_X509_LOOKUP 0x01 +/* Returned from the connect BIO when a connect would have blocked */ +# define BIO_RR_CONNECT 0x02 +/* Returned from the accept BIO when an accept would have blocked */ +# define BIO_RR_ACCEPT 0x03 + +/* These are passed by the BIO callback */ +# define BIO_CB_FREE 0x01 +# define BIO_CB_READ 0x02 +# define BIO_CB_WRITE 0x03 +# define BIO_CB_PUTS 0x04 +# define BIO_CB_GETS 0x05 +# define BIO_CB_CTRL 0x06 + +/* + * The callback is called before and after the underling operation, The + * BIO_CB_RETURN flag indicates if it is after the call + */ +# define BIO_CB_RETURN 0x80 +# define BIO_CB_return(a) ((a)|BIO_CB_RETURN) +# define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN)) +# define BIO_cb_post(a) ((a)&BIO_CB_RETURN) + +long (*BIO_get_callback(const BIO *b)) (struct bio_st *, int, const char *, + int, long, long); +void BIO_set_callback(BIO *b, + long (*callback) (struct bio_st *, int, const char *, + int, long, long)); +char *BIO_get_callback_arg(const BIO *b); +void BIO_set_callback_arg(BIO *b, char *arg); + +const char *BIO_method_name(const BIO *b); +int BIO_method_type(const BIO *b); + +typedef void bio_info_cb (struct bio_st *, int, const char *, int, long, + long); + +typedef struct bio_method_st { + int type; + const char *name; + int (*bwrite) (BIO *, const char *, int); + int (*bread) (BIO *, char *, int); + int (*bputs) (BIO *, const char *); + int (*bgets) (BIO *, char *, int); + long (*ctrl) (BIO *, int, long, void *); + int (*create) (BIO *); + int (*destroy) (BIO *); + long (*callback_ctrl) (BIO *, int, bio_info_cb *); +} BIO_METHOD; + +struct bio_st { + BIO_METHOD *method; + /* bio, mode, argp, argi, argl, ret */ + long (*callback) (struct bio_st *, int, const char *, int, long, long); + char *cb_arg; /* first argument for the callback */ + int init; + int shutdown; + int flags; /* extra storage */ + int retry_reason; + int num; + void *ptr; + struct bio_st *next_bio; /* used by filter BIOs */ + struct bio_st *prev_bio; /* used by filter BIOs */ + int references; + unsigned long num_read; + unsigned long num_write; + CRYPTO_EX_DATA ex_data; +}; + +DECLARE_STACK_OF(BIO) + +typedef struct bio_f_buffer_ctx_struct { + /*- + * Buffers are setup like this: + * + * <---------------------- size -----------------------> + * +---------------------------------------------------+ + * | consumed | remaining | free space | + * +---------------------------------------------------+ + * <-- off --><------- len -------> + */ + /*- BIO *bio; *//* + * this is now in the BIO struct + */ + int ibuf_size; /* how big is the input buffer */ + int obuf_size; /* how big is the output buffer */ + char *ibuf; /* the char array */ + int ibuf_len; /* how many bytes are in it */ + int ibuf_off; /* write/read offset */ + char *obuf; /* the char array */ + int obuf_len; /* how many bytes are in it */ + int obuf_off; /* write/read offset */ +} BIO_F_BUFFER_CTX; + +/* Prefix and suffix callback in ASN1 BIO */ +typedef int asn1_ps_func (BIO *b, unsigned char **pbuf, int *plen, + void *parg); + +# ifndef OPENSSL_NO_SCTP +/* SCTP parameter structs */ +struct bio_dgram_sctp_sndinfo { + uint16_t snd_sid; + uint16_t snd_flags; + uint32_t snd_ppid; + uint32_t snd_context; +}; + +struct bio_dgram_sctp_rcvinfo { + uint16_t rcv_sid; + uint16_t rcv_ssn; + uint16_t rcv_flags; + uint32_t rcv_ppid; + uint32_t rcv_tsn; + uint32_t rcv_cumtsn; + uint32_t rcv_context; +}; + +struct bio_dgram_sctp_prinfo { + uint16_t pr_policy; + uint32_t pr_value; +}; +# endif + +/* connect BIO stuff */ +# define BIO_CONN_S_BEFORE 1 +# define BIO_CONN_S_GET_IP 2 +# define BIO_CONN_S_GET_PORT 3 +# define BIO_CONN_S_CREATE_SOCKET 4 +# define BIO_CONN_S_CONNECT 5 +# define BIO_CONN_S_OK 6 +# define BIO_CONN_S_BLOCKED_CONNECT 7 +# define BIO_CONN_S_NBIO 8 +/* + * #define BIO_CONN_get_param_hostname BIO_ctrl + */ + +# define BIO_C_SET_CONNECT 100 +# define BIO_C_DO_STATE_MACHINE 101 +# define BIO_C_SET_NBIO 102 +# define BIO_C_SET_PROXY_PARAM 103 +# define BIO_C_SET_FD 104 +# define BIO_C_GET_FD 105 +# define BIO_C_SET_FILE_PTR 106 +# define BIO_C_GET_FILE_PTR 107 +# define BIO_C_SET_FILENAME 108 +# define BIO_C_SET_SSL 109 +# define BIO_C_GET_SSL 110 +# define BIO_C_SET_MD 111 +# define BIO_C_GET_MD 112 +# define BIO_C_GET_CIPHER_STATUS 113 +# define BIO_C_SET_BUF_MEM 114 +# define BIO_C_GET_BUF_MEM_PTR 115 +# define BIO_C_GET_BUFF_NUM_LINES 116 +# define BIO_C_SET_BUFF_SIZE 117 +# define BIO_C_SET_ACCEPT 118 +# define BIO_C_SSL_MODE 119 +# define BIO_C_GET_MD_CTX 120 +# define BIO_C_GET_PROXY_PARAM 121 +# define BIO_C_SET_BUFF_READ_DATA 122/* data to read first */ +# define BIO_C_GET_CONNECT 123 +# define BIO_C_GET_ACCEPT 124 +# define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125 +# define BIO_C_GET_SSL_NUM_RENEGOTIATES 126 +# define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127 +# define BIO_C_FILE_SEEK 128 +# define BIO_C_GET_CIPHER_CTX 129 +# define BIO_C_SET_BUF_MEM_EOF_RETURN 130/* return end of input + * value */ +# define BIO_C_SET_BIND_MODE 131 +# define BIO_C_GET_BIND_MODE 132 +# define BIO_C_FILE_TELL 133 +# define BIO_C_GET_SOCKS 134 +# define BIO_C_SET_SOCKS 135 + +# define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */ +# define BIO_C_GET_WRITE_BUF_SIZE 137 +# define BIO_C_MAKE_BIO_PAIR 138 +# define BIO_C_DESTROY_BIO_PAIR 139 +# define BIO_C_GET_WRITE_GUARANTEE 140 +# define BIO_C_GET_READ_REQUEST 141 +# define BIO_C_SHUTDOWN_WR 142 +# define BIO_C_NREAD0 143 +# define BIO_C_NREAD 144 +# define BIO_C_NWRITE0 145 +# define BIO_C_NWRITE 146 +# define BIO_C_RESET_READ_REQUEST 147 +# define BIO_C_SET_MD_CTX 148 + +# define BIO_C_SET_PREFIX 149 +# define BIO_C_GET_PREFIX 150 +# define BIO_C_SET_SUFFIX 151 +# define BIO_C_GET_SUFFIX 152 + +# define BIO_C_SET_EX_ARG 153 +# define BIO_C_GET_EX_ARG 154 + +# define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg) +# define BIO_get_app_data(s) BIO_get_ex_data(s,0) + +/* BIO_s_connect() and BIO_s_socks4a_connect() */ +# define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0,(char *)name) +# define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port) +# define BIO_set_conn_ip(b,ip) BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip) +# define BIO_set_conn_int_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,3,(char *)port) +# define BIO_get_conn_hostname(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0) +# define BIO_get_conn_port(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1) +# define BIO_get_conn_ip(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2) +# define BIO_get_conn_int_port(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL) + +# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) + +/* BIO_s_accept() */ +# define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name) +# define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0) +/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */ +# define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?(void *)"a":NULL) +# define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char *)bio) + +# define BIO_BIND_NORMAL 0 +# define BIO_BIND_REUSEADDR_IF_UNUSED 1 +# define BIO_BIND_REUSEADDR 2 +# define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL) +# define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL) + +/* BIO_s_accept() and BIO_s_connect() */ +# define BIO_do_connect(b) BIO_do_handshake(b) +# define BIO_do_accept(b) BIO_do_handshake(b) +# define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL) + +/* BIO_s_proxy_client() */ +# define BIO_set_url(b,url) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,0,(char *)(url)) +# define BIO_set_proxies(b,p) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,1,(char *)(p)) +/* BIO_set_nbio(b,n) */ +# define BIO_set_filter_bio(b,s) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,2,(char *)(s)) +/* BIO *BIO_get_filter_bio(BIO *bio); */ +# define BIO_set_proxy_cb(b,cb) BIO_callback_ctrl(b,BIO_C_SET_PROXY_PARAM,3,(void *(*cb)())) +# define BIO_set_proxy_header(b,sk) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,4,(char *)sk) +# define BIO_set_no_connect_return(b,bool) BIO_int_ctrl(b,BIO_C_SET_PROXY_PARAM,5,bool) + +# define BIO_get_proxy_header(b,skp) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,0,(char *)skp) +# define BIO_get_proxies(b,pxy_p) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,1,(char *)(pxy_p)) +# define BIO_get_url(b,url) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url)) +# define BIO_get_no_connect_return(b) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL) + +/* BIO_s_datagram(), BIO_s_fd(), BIO_s_socket(), BIO_s_accept() and BIO_s_connect() */ +# define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd) +# define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c) + +/* BIO_s_file() */ +# define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp) +# define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp) + +/* BIO_s_fd() and BIO_s_file() */ +# define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL) +# define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL) + +/* + * name is cast to lose const, but might be better to route through a + * function so we can do it safely + */ +# ifdef CONST_STRICT +/* + * If you are wondering why this isn't defined, its because CONST_STRICT is + * purely a compile-time kludge to allow const to be checked. + */ +int BIO_read_filename(BIO *b, const char *name); +# else +# define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ,(char *)name) +# endif +# define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_WRITE,name) +# define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_APPEND,name) +# define BIO_rw_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name) + +/* + * WARNING WARNING, this ups the reference count on the read bio of the SSL + * structure. This is because the ssl read BIO is now pointed to by the + * next_bio field in the bio. So when you free the BIO, make sure you are + * doing a BIO_free_all() to catch the underlying BIO. + */ +# define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)ssl) +# define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)sslp) +# define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL) +# define BIO_set_ssl_renegotiate_bytes(b,num) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL) +# define BIO_get_num_renegotiates(b) \ + BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL) +# define BIO_set_ssl_renegotiate_timeout(b,seconds) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL) + +/* defined in evp.h */ +/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)md) */ + +# define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp) +# define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm) +# define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0,(char *)pp) +# define BIO_set_mem_eof_return(b,v) \ + BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL) + +/* For the BIO_f_buffer() type */ +# define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL) +# define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL) +# define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0) +# define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1) +# define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf) + +/* Don't use the next one unless you know what you are doing :-) */ +# define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret)) + +# define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL) +# define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL) +# define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL) +# define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL) +# define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL) +# define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL) +/* ...pending macros have inappropriate return type */ +size_t BIO_ctrl_pending(BIO *b); +size_t BIO_ctrl_wpending(BIO *b); +# define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL) +# define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \ + cbp) +# define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb) + +/* For the BIO_f_buffer() type */ +# define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL) + +/* For BIO_s_bio() */ +# define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL) +# define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL) +# define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2) +# define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL) +# define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL) +/* macros with inappropriate type -- but ...pending macros use int too: */ +# define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL) +# define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL) +size_t BIO_ctrl_get_write_guarantee(BIO *b); +size_t BIO_ctrl_get_read_request(BIO *b); +int BIO_ctrl_reset_read_request(BIO *b); + +/* ctrl macros for dgram */ +# define BIO_ctrl_dgram_connect(b,peer) \ + (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)peer) +# define BIO_ctrl_set_connected(b, state, peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, state, (char *)peer) +# define BIO_dgram_recv_timedout(b) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL) +# define BIO_dgram_send_timedout(b) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL) +# define BIO_dgram_get_peer(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)peer) +# define BIO_dgram_set_peer(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)peer) +# define BIO_dgram_get_mtu_overhead(b) \ + (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL) + +/* These two aren't currently implemented */ +/* int BIO_get_ex_num(BIO *bio); */ +/* void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); */ +int BIO_set_ex_data(BIO *bio, int idx, void *data); +void *BIO_get_ex_data(BIO *bio, int idx); +int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +unsigned long BIO_number_read(BIO *bio); +unsigned long BIO_number_written(BIO *bio); + +/* For BIO_f_asn1() */ +int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, + asn1_ps_func *prefix_free); +int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, + asn1_ps_func **pprefix_free); +int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, + asn1_ps_func *suffix_free); +int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, + asn1_ps_func **psuffix_free); + +# ifndef OPENSSL_NO_FP_API +BIO_METHOD *BIO_s_file(void); +BIO *BIO_new_file(const char *filename, const char *mode); +BIO *BIO_new_fp(FILE *stream, int close_flag); +# define BIO_s_file_internal BIO_s_file +# endif +BIO *BIO_new(BIO_METHOD *type); +int BIO_set(BIO *a, BIO_METHOD *type); +int BIO_free(BIO *a); +void BIO_vfree(BIO *a); +int BIO_read(BIO *b, void *data, int len); +int BIO_gets(BIO *bp, char *buf, int size); +int BIO_write(BIO *b, const void *data, int len); +int BIO_puts(BIO *bp, const char *buf); +int BIO_indent(BIO *b, int indent, int max); +long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); +long BIO_callback_ctrl(BIO *b, int cmd, + void (*fp) (struct bio_st *, int, const char *, int, + long, long)); +char *BIO_ptr_ctrl(BIO *bp, int cmd, long larg); +long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); +BIO *BIO_push(BIO *b, BIO *append); +BIO *BIO_pop(BIO *b); +void BIO_free_all(BIO *a); +BIO *BIO_find_type(BIO *b, int bio_type); +BIO *BIO_next(BIO *b); +BIO *BIO_get_retry_BIO(BIO *bio, int *reason); +int BIO_get_retry_reason(BIO *bio); +BIO *BIO_dup_chain(BIO *in); + +int BIO_nread0(BIO *bio, char **buf); +int BIO_nread(BIO *bio, char **buf, int num); +int BIO_nwrite0(BIO *bio, char **buf); +int BIO_nwrite(BIO *bio, char **buf, int num); + +long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, + long argl, long ret); + +BIO_METHOD *BIO_s_mem(void); +BIO *BIO_new_mem_buf(const void *buf, int len); +BIO_METHOD *BIO_s_socket(void); +BIO_METHOD *BIO_s_connect(void); +BIO_METHOD *BIO_s_accept(void); +BIO_METHOD *BIO_s_fd(void); +# ifndef OPENSSL_SYS_OS2 +BIO_METHOD *BIO_s_log(void); +# endif +BIO_METHOD *BIO_s_bio(void); +BIO_METHOD *BIO_s_null(void); +BIO_METHOD *BIO_f_null(void); +BIO_METHOD *BIO_f_buffer(void); +# ifdef OPENSSL_SYS_VMS +BIO_METHOD *BIO_f_linebuffer(void); +# endif +BIO_METHOD *BIO_f_nbio_test(void); +# ifndef OPENSSL_NO_DGRAM +BIO_METHOD *BIO_s_datagram(void); +# ifndef OPENSSL_NO_SCTP +BIO_METHOD *BIO_s_datagram_sctp(void); +# endif +# endif + +/* BIO_METHOD *BIO_f_ber(void); */ + +int BIO_sock_should_retry(int i); +int BIO_sock_non_fatal_error(int error); +int BIO_dgram_non_fatal_error(int error); + +int BIO_fd_should_retry(int i); +int BIO_fd_non_fatal_error(int error); +int BIO_dump_cb(int (*cb) (const void *data, size_t len, void *u), + void *u, const char *s, int len); +int BIO_dump_indent_cb(int (*cb) (const void *data, size_t len, void *u), + void *u, const char *s, int len, int indent); +int BIO_dump(BIO *b, const char *bytes, int len); +int BIO_dump_indent(BIO *b, const char *bytes, int len, int indent); +# ifndef OPENSSL_NO_FP_API +int BIO_dump_fp(FILE *fp, const char *s, int len); +int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent); +# endif +int BIO_hex_string(BIO *out, int indent, int width, unsigned char *data, + int datalen); + +struct hostent *BIO_gethostbyname(const char *name); +/*- + * We might want a thread-safe interface too: + * struct hostent *BIO_gethostbyname_r(const char *name, + * struct hostent *result, void *buffer, size_t buflen); + * or something similar (caller allocates a struct hostent, + * pointed to by "result", and additional buffer space for the various + * substructures; if the buffer does not suffice, NULL is returned + * and an appropriate error code is set). + */ +int BIO_sock_error(int sock); +int BIO_socket_ioctl(int fd, long type, void *arg); +int BIO_socket_nbio(int fd, int mode); +int BIO_get_port(const char *str, unsigned short *port_ptr); +int BIO_get_host_ip(const char *str, unsigned char *ip); +int BIO_get_accept_socket(char *host_port, int mode); +int BIO_accept(int sock, char **ip_port); +int BIO_sock_init(void); +void BIO_sock_cleanup(void); +int BIO_set_tcp_ndelay(int sock, int turn_on); + +BIO *BIO_new_socket(int sock, int close_flag); +BIO *BIO_new_dgram(int fd, int close_flag); +# ifndef OPENSSL_NO_SCTP +BIO *BIO_new_dgram_sctp(int fd, int close_flag); +int BIO_dgram_is_sctp(BIO *bio); +int BIO_dgram_sctp_notification_cb(BIO *b, + void (*handle_notifications) (BIO *bio, + void + *context, + void *buf), + void *context); +int BIO_dgram_sctp_wait_for_dry(BIO *b); +int BIO_dgram_sctp_msg_waiting(BIO *b); +# endif +BIO *BIO_new_fd(int fd, int close_flag); +BIO *BIO_new_connect(const char *host_port); +BIO *BIO_new_accept(const char *host_port); + +int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, + BIO **bio2, size_t writebuf2); +/* + * If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints. + * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default + * value. + */ + +void BIO_copy_next_retry(BIO *b); + +/* + * long BIO_ghbn_ctrl(int cmd,int iarg,char *parg); + */ + +# ifdef __GNUC__ +# define __bio_h__attr__ __attribute__ +# else +# define __bio_h__attr__(x) +# endif +int BIO_printf(BIO *bio, const char *format, ...) +__bio_h__attr__((__format__(__printf__, 2, 3))); +int BIO_vprintf(BIO *bio, const char *format, va_list args) +__bio_h__attr__((__format__(__printf__, 2, 0))); +int BIO_snprintf(char *buf, size_t n, const char *format, ...) +__bio_h__attr__((__format__(__printf__, 3, 4))); +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) +__bio_h__attr__((__format__(__printf__, 3, 0))); +# undef __bio_h__attr__ + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_BIO_strings(void); + +/* Error codes for the BIO functions. */ + +/* Function codes. */ +# define BIO_F_ACPT_STATE 100 +# define BIO_F_BIO_ACCEPT 101 +# define BIO_F_BIO_BER_GET_HEADER 102 +# define BIO_F_BIO_CALLBACK_CTRL 131 +# define BIO_F_BIO_CTRL 103 +# define BIO_F_BIO_GETHOSTBYNAME 120 +# define BIO_F_BIO_GETS 104 +# define BIO_F_BIO_GET_ACCEPT_SOCKET 105 +# define BIO_F_BIO_GET_HOST_IP 106 +# define BIO_F_BIO_GET_PORT 107 +# define BIO_F_BIO_MAKE_PAIR 121 +# define BIO_F_BIO_NEW 108 +# define BIO_F_BIO_NEW_FILE 109 +# define BIO_F_BIO_NEW_MEM_BUF 126 +# define BIO_F_BIO_NREAD 123 +# define BIO_F_BIO_NREAD0 124 +# define BIO_F_BIO_NWRITE 125 +# define BIO_F_BIO_NWRITE0 122 +# define BIO_F_BIO_PUTS 110 +# define BIO_F_BIO_READ 111 +# define BIO_F_BIO_SOCK_INIT 112 +# define BIO_F_BIO_WRITE 113 +# define BIO_F_BUFFER_CTRL 114 +# define BIO_F_CONN_CTRL 127 +# define BIO_F_CONN_STATE 115 +# define BIO_F_DGRAM_SCTP_READ 132 +# define BIO_F_DGRAM_SCTP_WRITE 133 +# define BIO_F_FILE_CTRL 116 +# define BIO_F_FILE_READ 130 +# define BIO_F_LINEBUFFER_CTRL 129 +# define BIO_F_MEM_READ 128 +# define BIO_F_MEM_WRITE 117 +# define BIO_F_SSL_NEW 118 +# define BIO_F_WSASTARTUP 119 + +/* Reason codes. */ +# define BIO_R_ACCEPT_ERROR 100 +# define BIO_R_BAD_FOPEN_MODE 101 +# define BIO_R_BAD_HOSTNAME_LOOKUP 102 +# define BIO_R_BROKEN_PIPE 124 +# define BIO_R_CONNECT_ERROR 103 +# define BIO_R_EOF_ON_MEMORY_BIO 127 +# define BIO_R_ERROR_SETTING_NBIO 104 +# define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET 105 +# define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET 106 +# define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107 +# define BIO_R_INVALID_ARGUMENT 125 +# define BIO_R_INVALID_IP_ADDRESS 108 +# define BIO_R_IN_USE 123 +# define BIO_R_KEEPALIVE 109 +# define BIO_R_NBIO_CONNECT_ERROR 110 +# define BIO_R_NO_ACCEPT_PORT_SPECIFIED 111 +# define BIO_R_NO_HOSTNAME_SPECIFIED 112 +# define BIO_R_NO_PORT_DEFINED 113 +# define BIO_R_NO_PORT_SPECIFIED 114 +# define BIO_R_NO_SUCH_FILE 128 +# define BIO_R_NULL_PARAMETER 115 +# define BIO_R_TAG_MISMATCH 116 +# define BIO_R_UNABLE_TO_BIND_SOCKET 117 +# define BIO_R_UNABLE_TO_CREATE_SOCKET 118 +# define BIO_R_UNABLE_TO_LISTEN_SOCKET 119 +# define BIO_R_UNINITIALIZED 120 +# define BIO_R_UNSUPPORTED_METHOD 121 +# define BIO_R_WRITE_TO_READ_ONLY_BIO 126 +# define BIO_R_WSASTARTUP 122 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/blowfish.h b/optee/optee_test/host/openssl/include/openssl/blowfish.h new file mode 100644 index 0000000..8329302 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/blowfish.h @@ -0,0 +1,130 @@ +/* crypto/bf/blowfish.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BLOWFISH_H +# define HEADER_BLOWFISH_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef OPENSSL_NO_BF +# error BF is disabled. +# endif + +# define BF_ENCRYPT 1 +# define BF_DECRYPT 0 + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! BF_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! BF_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +# if defined(__LP32__) +# define BF_LONG unsigned long +# elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) +# define BF_LONG unsigned long +# define BF_LONG_LOG2 3 +/* + * _CRAY note. I could declare short, but I have no idea what impact + * does it have on performance on none-T3E machines. I could declare + * int, but at least on C90 sizeof(int) can be chosen at compile time. + * So I've chosen long... + * + */ +# else +# define BF_LONG unsigned int +# endif + +# define BF_ROUNDS 16 +# define BF_BLOCK 8 + +typedef struct bf_key_st { + BF_LONG P[BF_ROUNDS + 2]; + BF_LONG S[4 * 256]; +} BF_KEY; + +# ifdef OPENSSL_FIPS +void private_BF_set_key(BF_KEY *key, int len, const unsigned char *data); +# endif +void BF_set_key(BF_KEY *key, int len, const unsigned char *data); + +void BF_encrypt(BF_LONG *data, const BF_KEY *key); +void BF_decrypt(BF_LONG *data, const BF_KEY *key); + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int enc); +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int enc); +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const BF_KEY *schedule, + unsigned char *ivec, int *num); +const char *BF_options(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/bn.h b/optee/optee_test/host/openssl/include/openssl/bn.h new file mode 100644 index 0000000..633d1b1 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/bn.h @@ -0,0 +1,951 @@ +/* crypto/bn/bn.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the Eric Young open source + * license provided above. + * + * The binary polynomial arithmetic software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * + */ + +#ifndef HEADER_BN_H +# define HEADER_BN_H + +# include +# include +# ifndef OPENSSL_NO_FP_API +# include /* FILE */ +# endif +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * These preprocessor symbols control various aspects of the bignum headers + * and library code. They're not defined by any "normal" configuration, as + * they are intended for development and testing purposes. NB: defining all + * three can be useful for debugging application code as well as openssl + * itself. BN_DEBUG - turn on various debugging alterations to the bignum + * code BN_DEBUG_RAND - uses random poisoning of unused words to trip up + * mismanagement of bignum internals. You must also define BN_DEBUG. + */ +/* #define BN_DEBUG */ +/* #define BN_DEBUG_RAND */ + +# ifndef OPENSSL_SMALL_FOOTPRINT +# define BN_MUL_COMBA +# define BN_SQR_COMBA +# define BN_RECURSION +# endif + +/* + * This next option uses the C libraries (2 word)/(1 word) function. If it is + * not defined, I use my C version (which is slower). The reason for this + * flag is that when the particular C compiler library routine is used, and + * the library is linked with a different compiler, the library is missing. + * This mostly happens when the library is built with gcc and then linked + * using normal cc. This would be a common occurrence because gcc normally + * produces code that is 2 times faster than system compilers for the big + * number stuff. For machines with only one compiler (or shared libraries), + * this should be on. Again this in only really a problem on machines using + * "long long's", are 32bit, and are not using my assembler code. + */ +# if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WINDOWS) || \ + defined(OPENSSL_SYS_WIN32) || defined(linux) +# ifndef BN_DIV2W +# define BN_DIV2W +# endif +# endif + +/* + * assuming long is 64bit - this is the DEC Alpha unsigned long long is only + * 64 bits :-(, don't define BN_LLONG for the DEC Alpha + */ +# ifdef SIXTY_FOUR_BIT_LONG +# define BN_ULLONG unsigned long long +# define BN_ULONG unsigned long +# define BN_LONG long +# define BN_BITS 128 +# define BN_BYTES 8 +# define BN_BITS2 64 +# define BN_BITS4 32 +# define BN_MASK (0xffffffffffffffffffffffffffffffffLL) +# define BN_MASK2 (0xffffffffffffffffL) +# define BN_MASK2l (0xffffffffL) +# define BN_MASK2h (0xffffffff00000000L) +# define BN_MASK2h1 (0xffffffff80000000L) +# define BN_TBIT (0x8000000000000000L) +# define BN_DEC_CONV (10000000000000000000UL) +# define BN_DEC_FMT1 "%lu" +# define BN_DEC_FMT2 "%019lu" +# define BN_DEC_NUM 19 +# define BN_HEX_FMT1 "%lX" +# define BN_HEX_FMT2 "%016lX" +# endif + +/* + * This is where the long long data type is 64 bits, but long is 32. For + * machines where there are 64bit registers, this is the mode to use. IRIX, + * on R4000 and above should use this mode, along with the relevant assembler + * code :-). Do NOT define BN_LLONG. + */ +# ifdef SIXTY_FOUR_BIT +# undef BN_LLONG +# undef BN_ULLONG +# define BN_ULONG unsigned long long +# define BN_LONG long long +# define BN_BITS 128 +# define BN_BYTES 8 +# define BN_BITS2 64 +# define BN_BITS4 32 +# define BN_MASK2 (0xffffffffffffffffLL) +# define BN_MASK2l (0xffffffffL) +# define BN_MASK2h (0xffffffff00000000LL) +# define BN_MASK2h1 (0xffffffff80000000LL) +# define BN_TBIT (0x8000000000000000LL) +# define BN_DEC_CONV (10000000000000000000ULL) +# define BN_DEC_FMT1 "%llu" +# define BN_DEC_FMT2 "%019llu" +# define BN_DEC_NUM 19 +# define BN_HEX_FMT1 "%llX" +# define BN_HEX_FMT2 "%016llX" +# endif + +# ifdef THIRTY_TWO_BIT +# ifdef BN_LLONG +# if defined(_WIN32) && !defined(__GNUC__) +# define BN_ULLONG unsigned __int64 +# define BN_MASK (0xffffffffffffffffI64) +# else +# define BN_ULLONG unsigned long long +# define BN_MASK (0xffffffffffffffffLL) +# endif +# endif +# define BN_ULONG unsigned int +# define BN_LONG int +# define BN_BITS 64 +# define BN_BYTES 4 +# define BN_BITS2 32 +# define BN_BITS4 16 +# define BN_MASK2 (0xffffffffL) +# define BN_MASK2l (0xffff) +# define BN_MASK2h1 (0xffff8000L) +# define BN_MASK2h (0xffff0000L) +# define BN_TBIT (0x80000000L) +# define BN_DEC_CONV (1000000000L) +# define BN_DEC_FMT1 "%u" +# define BN_DEC_FMT2 "%09u" +# define BN_DEC_NUM 9 +# define BN_HEX_FMT1 "%X" +# define BN_HEX_FMT2 "%08X" +# endif + +# define BN_DEFAULT_BITS 1280 + +# define BN_FLG_MALLOCED 0x01 +# define BN_FLG_STATIC_DATA 0x02 + +/* + * avoid leaking exponent information through timing, + * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime, + * BN_div() will call BN_div_no_branch, + * BN_mod_inverse() will call BN_mod_inverse_no_branch. + */ +# define BN_FLG_CONSTTIME 0x04 + +# ifdef OPENSSL_NO_DEPRECATED +/* deprecated name for the flag */ +# define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME +/* + * avoid leaking exponent information through timings + * (BN_mod_exp_mont() will call BN_mod_exp_mont_consttime) + */ +# endif + +# ifndef OPENSSL_NO_DEPRECATED +# define BN_FLG_FREE 0x8000 + /* used for debuging */ +# endif +# define BN_set_flags(b,n) ((b)->flags|=(n)) +# define BN_get_flags(b,n) ((b)->flags&(n)) + +/* + * get a clone of a BIGNUM with changed flags, for *temporary* use only (the + * two BIGNUMs cannot not be used in parallel!) + */ +# define BN_with_flags(dest,b,n) ((dest)->d=(b)->d, \ + (dest)->top=(b)->top, \ + (dest)->dmax=(b)->dmax, \ + (dest)->neg=(b)->neg, \ + (dest)->flags=(((dest)->flags & BN_FLG_MALLOCED) \ + | ((b)->flags & ~BN_FLG_MALLOCED) \ + | BN_FLG_STATIC_DATA \ + | (n))) + +/* Already declared in ossl_typ.h */ +# if 0 +typedef struct bignum_st BIGNUM; +/* Used for temp variables (declaration hidden in bn_lcl.h) */ +typedef struct bignum_ctx BN_CTX; +typedef struct bn_blinding_st BN_BLINDING; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct bn_recp_ctx_st BN_RECP_CTX; +typedef struct bn_gencb_st BN_GENCB; +# endif + +struct bignum_st { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit + * chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int dmax; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; +}; + +/* Used for montgomery multiplication */ +struct bn_mont_ctx_st { + int ri; /* number of bits in R */ + BIGNUM RR; /* used to convert to montgomery form */ + BIGNUM N; /* The modulus */ + BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 (Ni is only + * stored for bignum algorithm) */ + BN_ULONG n0[2]; /* least significant word(s) of Ni; (type + * changed with 0.9.9, was "BN_ULONG n0;" + * before) */ + int flags; +}; + +/* + * Used for reciprocal division/mod functions It cannot be shared between + * threads + */ +struct bn_recp_ctx_st { + BIGNUM N; /* the divisor */ + BIGNUM Nr; /* the reciprocal */ + int num_bits; + int shift; + int flags; +}; + +/* Used for slow "generation" functions. */ +struct bn_gencb_st { + unsigned int ver; /* To handle binary (in)compatibility */ + void *arg; /* callback-specific data */ + union { + /* if(ver==1) - handles old style callbacks */ + void (*cb_1) (int, int, void *); + /* if(ver==2) - new callback style */ + int (*cb_2) (int, int, BN_GENCB *); + } cb; +}; +/* Wrapper function to make using BN_GENCB easier, */ +int BN_GENCB_call(BN_GENCB *cb, int a, int b); +/* Macro to populate a BN_GENCB structure with an "old"-style callback */ +# define BN_GENCB_set_old(gencb, callback, cb_arg) { \ + BN_GENCB *tmp_gencb = (gencb); \ + tmp_gencb->ver = 1; \ + tmp_gencb->arg = (cb_arg); \ + tmp_gencb->cb.cb_1 = (callback); } +/* Macro to populate a BN_GENCB structure with a "new"-style callback */ +# define BN_GENCB_set(gencb, callback, cb_arg) { \ + BN_GENCB *tmp_gencb = (gencb); \ + tmp_gencb->ver = 2; \ + tmp_gencb->arg = (cb_arg); \ + tmp_gencb->cb.cb_2 = (callback); } + +# define BN_prime_checks 0 /* default: select number of iterations based + * on the size of the number */ + +/* + * number of Miller-Rabin iterations for an error rate of less than 2^-80 for + * random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook of + * Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996]; + * original paper: Damgaard, Landrock, Pomerance: Average case error + * estimates for the strong probable prime test. -- Math. Comp. 61 (1993) + * 177-194) + */ +# define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \ + (b) >= 850 ? 3 : \ + (b) >= 650 ? 4 : \ + (b) >= 550 ? 5 : \ + (b) >= 450 ? 6 : \ + (b) >= 400 ? 7 : \ + (b) >= 350 ? 8 : \ + (b) >= 300 ? 9 : \ + (b) >= 250 ? 12 : \ + (b) >= 200 ? 15 : \ + (b) >= 150 ? 18 : \ + /* b >= 100 */ 27) + +# define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) + +/* Note that BN_abs_is_word didn't work reliably for w == 0 until 0.9.8 */ +# define BN_abs_is_word(a,w) ((((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) || \ + (((w) == 0) && ((a)->top == 0))) +# define BN_is_zero(a) ((a)->top == 0) +# define BN_is_one(a) (BN_abs_is_word((a),1) && !(a)->neg) +# define BN_is_word(a,w) (BN_abs_is_word((a),(w)) && (!(w) || !(a)->neg)) +# define BN_is_odd(a) (((a)->top > 0) && ((a)->d[0] & 1)) + +# define BN_one(a) (BN_set_word((a),1)) +# define BN_zero_ex(a) \ + do { \ + BIGNUM *_tmp_bn = (a); \ + _tmp_bn->top = 0; \ + _tmp_bn->neg = 0; \ + } while(0) +# ifdef OPENSSL_NO_DEPRECATED +# define BN_zero(a) BN_zero_ex(a) +# else +# define BN_zero(a) (BN_set_word((a),0)) +# endif + +const BIGNUM *BN_value_one(void); +char *BN_options(void); +BN_CTX *BN_CTX_new(void); +# ifndef OPENSSL_NO_DEPRECATED +void BN_CTX_init(BN_CTX *c); +# endif +void BN_CTX_free(BN_CTX *c); +void BN_CTX_start(BN_CTX *ctx); +BIGNUM *BN_CTX_get(BN_CTX *ctx); +void BN_CTX_end(BN_CTX *ctx); +int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_num_bits(const BIGNUM *a); +int BN_num_bits_word(BN_ULONG); +BIGNUM *BN_new(void); +void BN_init(BIGNUM *); +void BN_clear_free(BIGNUM *a); +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b); +void BN_swap(BIGNUM *a, BIGNUM *b); +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2mpi(const BIGNUM *a, unsigned char *to); +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); +/** BN_set_negative sets sign of a BIGNUM + * \param b pointer to the BIGNUM object + * \param n 0 if the BIGNUM b should be positive and a value != 0 otherwise + */ +void BN_set_negative(BIGNUM *b, int n); +/** BN_is_negative returns 1 if the BIGNUM is negative + * \param a pointer to the BIGNUM object + * \return 1 if a < 0 and 0 otherwise + */ +# define BN_is_negative(a) ((a)->neg != 0) + +int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, + BN_CTX *ctx); +# define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx)) +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx); +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m); +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m); + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); +int BN_mul_word(BIGNUM *a, BN_ULONG w); +int BN_add_word(BIGNUM *a, BN_ULONG w); +int BN_sub_word(BIGNUM *a, BN_ULONG w); +int BN_set_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_get_word(const BIGNUM *a); + +int BN_cmp(const BIGNUM *a, const BIGNUM *b); +void BN_free(BIGNUM *a); +int BN_is_bit_set(const BIGNUM *a, int n); +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_lshift1(BIGNUM *r, const BIGNUM *a); +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); + +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont); +int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +int BN_mask_bits(BIGNUM *a, int n); +# ifndef OPENSSL_NO_FP_API +int BN_print_fp(FILE *fp, const BIGNUM *a); +# endif +# ifdef HEADER_BIO_H +int BN_print(BIO *fp, const BIGNUM *a); +# else +int BN_print(void *fp, const BIGNUM *a); +# endif +int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx); +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, const BIGNUM *a); +void BN_clear(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +int BN_ucmp(const BIGNUM *a, const BIGNUM *b); +int BN_set_bit(BIGNUM *a, int n); +int BN_clear_bit(BIGNUM *a, int n); +char *BN_bn2hex(const BIGNUM *a); +char *BN_bn2dec(const BIGNUM *a); +int BN_hex2bn(BIGNUM **a, const char *str); +int BN_dec2bn(BIGNUM **a, const char *str); +int BN_asc2bn(BIGNUM **a, const char *str); +int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); /* returns + * -2 for + * error */ +BIGNUM *BN_mod_inverse(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); +BIGNUM *BN_mod_sqrt(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); + +void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords); + +/* Deprecated versions */ +# ifndef OPENSSL_NO_DEPRECATED +BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, + const BIGNUM *add, const BIGNUM *rem, + void (*callback) (int, int, void *), void *cb_arg); +int BN_is_prime(const BIGNUM *p, int nchecks, + void (*callback) (int, int, void *), + BN_CTX *ctx, void *cb_arg); +int BN_is_prime_fasttest(const BIGNUM *p, int nchecks, + void (*callback) (int, int, void *), BN_CTX *ctx, + void *cb_arg, int do_trial_division); +# endif /* !defined(OPENSSL_NO_DEPRECATED) */ + +/* Newer versions */ +int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add, + const BIGNUM *rem, BN_GENCB *cb); +int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb); +int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb); + +int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx); + +int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, + const BIGNUM *Xp, const BIGNUM *Xp1, + const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx, + BN_GENCB *cb); +int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, BIGNUM *Xp1, + BIGNUM *Xp2, const BIGNUM *Xp, const BIGNUM *e, + BN_CTX *ctx, BN_GENCB *cb); + +BN_MONT_CTX *BN_MONT_CTX_new(void); +void BN_MONT_CTX_init(BN_MONT_CTX *ctx); +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx); +# define BN_to_montgomery(r,a,mont,ctx) BN_mod_mul_montgomery(\ + (r),(a),&((mont)->RR),(mont),(ctx)) +int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, + BN_MONT_CTX *mont, BN_CTX *ctx); +void BN_MONT_CTX_free(BN_MONT_CTX *mont); +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx); +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from); +BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock, + const BIGNUM *mod, BN_CTX *ctx); + +/* BN_BLINDING flags */ +# define BN_BLINDING_NO_UPDATE 0x00000001 +# define BN_BLINDING_NO_RECREATE 0x00000002 + +BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod); +void BN_BLINDING_free(BN_BLINDING *b); +int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *); +int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, + BN_CTX *); +# ifndef OPENSSL_NO_DEPRECATED +unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *); +void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long); +# endif +CRYPTO_THREADID *BN_BLINDING_thread_id(BN_BLINDING *); +unsigned long BN_BLINDING_get_flags(const BN_BLINDING *); +void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long); +BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, + const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, + int (*bn_mod_exp) (BIGNUM *r, + const BIGNUM *a, + const BIGNUM *p, + const BIGNUM *m, + BN_CTX *ctx, + BN_MONT_CTX *m_ctx), + BN_MONT_CTX *m_ctx); + +# ifndef OPENSSL_NO_DEPRECATED +void BN_set_params(int mul, int high, int low, int mont); +int BN_get_params(int which); /* 0, mul, 1 high, 2 low, 3 mont */ +# endif + +void BN_RECP_CTX_init(BN_RECP_CTX *recp); +BN_RECP_CTX *BN_RECP_CTX_new(void); +void BN_RECP_CTX_free(BN_RECP_CTX *recp); +int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *rdiv, BN_CTX *ctx); +int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx); +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx); + +# ifndef OPENSSL_NO_EC2M + +/* + * Functions for arithmetic over binary polynomials represented by BIGNUMs. + * The BIGNUM::neg property of BIGNUMs representing binary polynomials is + * ignored. Note that input arguments are not const so that their bit arrays + * can be expanded to the appropriate size if needed. + */ + +/* + * r = a + b + */ +int BN_GF2m_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +# define BN_GF2m_sub(r, a, b) BN_GF2m_add(r, a, b) +/* + * r=a mod p + */ +int BN_GF2m_mod(BIGNUM *r, const BIGNUM *a, const BIGNUM *p); +/* r = (a * b) mod p */ +int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = (a * a) mod p */ +int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +/* r = (1 / b) mod p */ +int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *b, const BIGNUM *p, BN_CTX *ctx); +/* r = (a / b) mod p */ +int BN_GF2m_mod_div(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = (a ^ b) mod p */ +int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *p, BN_CTX *ctx); +/* r = sqrt(a) mod p */ +int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); +/* r^2 + r = a mod p */ +int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + BN_CTX *ctx); +# define BN_GF2m_cmp(a, b) BN_ucmp((a), (b)) +/*- + * Some functions allow for representation of the irreducible polynomials + * as an unsigned int[], say p. The irreducible f(t) is then of the form: + * t^p[0] + t^p[1] + ... + t^p[k] + * where m = p[0] > p[1] > ... > p[k] = 0. + */ +/* r = a mod p */ +int BN_GF2m_mod_arr(BIGNUM *r, const BIGNUM *a, const int p[]); +/* r = (a * b) mod p */ +int BN_GF2m_mod_mul_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = (a * a) mod p */ +int BN_GF2m_mod_sqr_arr(BIGNUM *r, const BIGNUM *a, const int p[], + BN_CTX *ctx); +/* r = (1 / b) mod p */ +int BN_GF2m_mod_inv_arr(BIGNUM *r, const BIGNUM *b, const int p[], + BN_CTX *ctx); +/* r = (a / b) mod p */ +int BN_GF2m_mod_div_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = (a ^ b) mod p */ +int BN_GF2m_mod_exp_arr(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const int p[], BN_CTX *ctx); +/* r = sqrt(a) mod p */ +int BN_GF2m_mod_sqrt_arr(BIGNUM *r, const BIGNUM *a, + const int p[], BN_CTX *ctx); +/* r^2 + r = a mod p */ +int BN_GF2m_mod_solve_quad_arr(BIGNUM *r, const BIGNUM *a, + const int p[], BN_CTX *ctx); +int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max); +int BN_GF2m_arr2poly(const int p[], BIGNUM *a); + +# endif + +/* + * faster mod functions for the 'NIST primes' 0 <= a < p^2 + */ +int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); +int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); + +const BIGNUM *BN_get0_nist_prime_192(void); +const BIGNUM *BN_get0_nist_prime_224(void); +const BIGNUM *BN_get0_nist_prime_256(void); +const BIGNUM *BN_get0_nist_prime_384(void); +const BIGNUM *BN_get0_nist_prime_521(void); + +/* library internal functions */ + +# define bn_expand(a,bits) \ + ( \ + bits > (INT_MAX - BN_BITS2 + 1) ? \ + NULL \ + : \ + (((bits+BN_BITS2-1)/BN_BITS2) <= (a)->dmax) ? \ + (a) \ + : \ + bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2) \ + ) + +# define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words))) +BIGNUM *bn_expand2(BIGNUM *a, int words); +# ifndef OPENSSL_NO_DEPRECATED +BIGNUM *bn_dup_expand(const BIGNUM *a, int words); /* unused */ +# endif + +/*- + * Bignum consistency macros + * There is one "API" macro, bn_fix_top(), for stripping leading zeroes from + * bignum data after direct manipulations on the data. There is also an + * "internal" macro, bn_check_top(), for verifying that there are no leading + * zeroes. Unfortunately, some auditing is required due to the fact that + * bn_fix_top() has become an overabused duct-tape because bignum data is + * occasionally passed around in an inconsistent state. So the following + * changes have been made to sort this out; + * - bn_fix_top()s implementation has been moved to bn_correct_top() + * - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and + * bn_check_top() is as before. + * - if BN_DEBUG *is* defined; + * - bn_check_top() tries to pollute unused words even if the bignum 'top' is + * consistent. (ed: only if BN_DEBUG_RAND is defined) + * - bn_fix_top() maps to bn_check_top() rather than "fixing" anything. + * The idea is to have debug builds flag up inconsistent bignums when they + * occur. If that occurs in a bn_fix_top(), we examine the code in question; if + * the use of bn_fix_top() was appropriate (ie. it follows directly after code + * that manipulates the bignum) it is converted to bn_correct_top(), and if it + * was not appropriate, we convert it permanently to bn_check_top() and track + * down the cause of the bug. Eventually, no internal code should be using the + * bn_fix_top() macro. External applications and libraries should try this with + * their own code too, both in terms of building against the openssl headers + * with BN_DEBUG defined *and* linking with a version of OpenSSL built with it + * defined. This not only improves external code, it provides more test + * coverage for openssl's own code. + */ + +# ifdef BN_DEBUG + +/* We only need assert() when debugging */ +# include + +# ifdef BN_DEBUG_RAND +/* To avoid "make update" cvs wars due to BN_DEBUG, use some tricks */ +# ifndef RAND_pseudo_bytes +int RAND_pseudo_bytes(unsigned char *buf, int num); +# define BN_DEBUG_TRIX +# endif +# define bn_pollute(a) \ + do { \ + const BIGNUM *_bnum1 = (a); \ + if(_bnum1->top < _bnum1->dmax) { \ + unsigned char _tmp_char; \ + /* We cast away const without the compiler knowing, any \ + * *genuinely* constant variables that aren't mutable \ + * wouldn't be constructed with top!=dmax. */ \ + BN_ULONG *_not_const; \ + memcpy(&_not_const, &_bnum1->d, sizeof(BN_ULONG*)); \ + /* Debug only - safe to ignore error return */ \ + RAND_pseudo_bytes(&_tmp_char, 1); \ + memset((unsigned char *)(_not_const + _bnum1->top), _tmp_char, \ + (_bnum1->dmax - _bnum1->top) * sizeof(BN_ULONG)); \ + } \ + } while(0) +# ifdef BN_DEBUG_TRIX +# undef RAND_pseudo_bytes +# endif +# else +# define bn_pollute(a) +# endif +# define bn_check_top(a) \ + do { \ + const BIGNUM *_bnum2 = (a); \ + if (_bnum2 != NULL) { \ + assert((_bnum2->top == 0) || \ + (_bnum2->d[_bnum2->top - 1] != 0)); \ + bn_pollute(_bnum2); \ + } \ + } while(0) + +# define bn_fix_top(a) bn_check_top(a) + +# define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2) +# define bn_wcheck_size(bn, words) \ + do { \ + const BIGNUM *_bnum2 = (bn); \ + assert((words) <= (_bnum2)->dmax && (words) >= (_bnum2)->top); \ + /* avoid unused variable warning with NDEBUG */ \ + (void)(_bnum2); \ + } while(0) + +# else /* !BN_DEBUG */ + +# define bn_pollute(a) +# define bn_check_top(a) +# define bn_fix_top(a) bn_correct_top(a) +# define bn_check_size(bn, bits) +# define bn_wcheck_size(bn, words) + +# endif + +# define bn_correct_top(a) \ + { \ + BN_ULONG *ftl; \ + int tmp_top = (a)->top; \ + if (tmp_top > 0) \ + { \ + for (ftl= &((a)->d[tmp_top-1]); tmp_top > 0; tmp_top--) \ + if (*(ftl--)) break; \ + (a)->top = tmp_top; \ + } \ + if ((a)->top == 0) \ + (a)->neg = 0; \ + bn_pollute(a); \ + } + +BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, + BN_ULONG w); +BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w); +void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num); +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d); +BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int num); +BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + int num); + +/* Primes from RFC 2409 */ +BIGNUM *get_rfc2409_prime_768(BIGNUM *bn); +BIGNUM *get_rfc2409_prime_1024(BIGNUM *bn); + +/* Primes from RFC 3526 */ +BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn); +BIGNUM *get_rfc3526_prime_2048(BIGNUM *bn); +BIGNUM *get_rfc3526_prime_3072(BIGNUM *bn); +BIGNUM *get_rfc3526_prime_4096(BIGNUM *bn); +BIGNUM *get_rfc3526_prime_6144(BIGNUM *bn); +BIGNUM *get_rfc3526_prime_8192(BIGNUM *bn); + +int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_BN_strings(void); + +/* Error codes for the BN functions. */ + +/* Function codes. */ +# define BN_F_BNRAND 127 +# define BN_F_BN_BLINDING_CONVERT_EX 100 +# define BN_F_BN_BLINDING_CREATE_PARAM 128 +# define BN_F_BN_BLINDING_INVERT_EX 101 +# define BN_F_BN_BLINDING_NEW 102 +# define BN_F_BN_BLINDING_UPDATE 103 +# define BN_F_BN_BN2DEC 104 +# define BN_F_BN_BN2HEX 105 +# define BN_F_BN_CTX_GET 116 +# define BN_F_BN_CTX_NEW 106 +# define BN_F_BN_CTX_START 129 +# define BN_F_BN_DIV 107 +# define BN_F_BN_DIV_NO_BRANCH 138 +# define BN_F_BN_DIV_RECP 130 +# define BN_F_BN_EXP 123 +# define BN_F_BN_EXPAND2 108 +# define BN_F_BN_EXPAND_INTERNAL 120 +# define BN_F_BN_GF2M_MOD 131 +# define BN_F_BN_GF2M_MOD_EXP 132 +# define BN_F_BN_GF2M_MOD_MUL 133 +# define BN_F_BN_GF2M_MOD_SOLVE_QUAD 134 +# define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135 +# define BN_F_BN_GF2M_MOD_SQR 136 +# define BN_F_BN_GF2M_MOD_SQRT 137 +# define BN_F_BN_LSHIFT 145 +# define BN_F_BN_MOD_EXP2_MONT 118 +# define BN_F_BN_MOD_EXP_MONT 109 +# define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124 +# define BN_F_BN_MOD_EXP_MONT_WORD 117 +# define BN_F_BN_MOD_EXP_RECP 125 +# define BN_F_BN_MOD_EXP_SIMPLE 126 +# define BN_F_BN_MOD_INVERSE 110 +# define BN_F_BN_MOD_INVERSE_NO_BRANCH 139 +# define BN_F_BN_MOD_LSHIFT_QUICK 119 +# define BN_F_BN_MOD_MUL_RECIPROCAL 111 +# define BN_F_BN_MOD_SQRT 121 +# define BN_F_BN_MPI2BN 112 +# define BN_F_BN_NEW 113 +# define BN_F_BN_RAND 114 +# define BN_F_BN_RAND_RANGE 122 +# define BN_F_BN_RSHIFT 146 +# define BN_F_BN_USUB 115 + +/* Reason codes. */ +# define BN_R_ARG2_LT_ARG3 100 +# define BN_R_BAD_RECIPROCAL 101 +# define BN_R_BIGNUM_TOO_LONG 114 +# define BN_R_BITS_TOO_SMALL 118 +# define BN_R_CALLED_WITH_EVEN_MODULUS 102 +# define BN_R_DIV_BY_ZERO 103 +# define BN_R_ENCODING_ERROR 104 +# define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105 +# define BN_R_INPUT_NOT_REDUCED 110 +# define BN_R_INVALID_LENGTH 106 +# define BN_R_INVALID_RANGE 115 +# define BN_R_INVALID_SHIFT 119 +# define BN_R_NOT_A_SQUARE 111 +# define BN_R_NOT_INITIALIZED 107 +# define BN_R_NO_INVERSE 108 +# define BN_R_NO_SOLUTION 116 +# define BN_R_P_IS_NOT_PRIME 112 +# define BN_R_TOO_MANY_ITERATIONS 113 +# define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/buffer.h b/optee/optee_test/host/openssl/include/openssl/buffer.h new file mode 100644 index 0000000..efd240a --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/buffer.h @@ -0,0 +1,125 @@ +/* crypto/buffer/buffer.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BUFFER_H +# define HEADER_BUFFER_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# include + +# if !defined(NO_SYS_TYPES_H) +# include +# endif + +/* Already declared in ossl_typ.h */ +/* typedef struct buf_mem_st BUF_MEM; */ + +struct buf_mem_st { + size_t length; /* current number of bytes */ + char *data; + size_t max; /* size of buffer */ +}; + +BUF_MEM *BUF_MEM_new(void); +void BUF_MEM_free(BUF_MEM *a); +int BUF_MEM_grow(BUF_MEM *str, size_t len); +int BUF_MEM_grow_clean(BUF_MEM *str, size_t len); +size_t BUF_strnlen(const char *str, size_t maxlen); +char *BUF_strdup(const char *str); + +/* + * Like strndup, but in addition, explicitly guarantees to never read past the + * first |siz| bytes of |str|. + */ +char *BUF_strndup(const char *str, size_t siz); + +void *BUF_memdup(const void *data, size_t siz); +void BUF_reverse(unsigned char *out, const unsigned char *in, size_t siz); + +/* safe string functions */ +size_t BUF_strlcpy(char *dst, const char *src, size_t siz); +size_t BUF_strlcat(char *dst, const char *src, size_t siz); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_BUF_strings(void); + +/* Error codes for the BUF functions. */ + +/* Function codes. */ +# define BUF_F_BUF_MEMDUP 103 +# define BUF_F_BUF_MEM_GROW 100 +# define BUF_F_BUF_MEM_GROW_CLEAN 105 +# define BUF_F_BUF_MEM_NEW 101 +# define BUF_F_BUF_STRDUP 102 +# define BUF_F_BUF_STRNDUP 104 + +/* Reason codes. */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/camellia.h b/optee/optee_test/host/openssl/include/openssl/camellia.h new file mode 100644 index 0000000..45e8d25 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/camellia.h @@ -0,0 +1,132 @@ +/* crypto/camellia/camellia.h */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 HEADER_CAMELLIA_H +# define HEADER_CAMELLIA_H + +# include + +# ifdef OPENSSL_NO_CAMELLIA +# error CAMELLIA is disabled. +# endif + +# include + +# define CAMELLIA_ENCRYPT 1 +# define CAMELLIA_DECRYPT 0 + +/* + * Because array size can't be a const in C, the following two are macros. + * Both sizes are in bytes. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* This should be a hidden type, but EVP requires that the size be known */ + +# define CAMELLIA_BLOCK_SIZE 16 +# define CAMELLIA_TABLE_BYTE_LEN 272 +# define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; /* to match + * with WORD */ + +struct camellia_key_st { + union { + double d; /* ensures 64-bit align */ + KEY_TABLE_TYPE rd_key; + } u; + int grand_rounds; +}; +typedef struct camellia_key_st CAMELLIA_KEY; + +# ifdef OPENSSL_FIPS +int private_Camellia_set_key(const unsigned char *userKey, const int bits, + CAMELLIA_KEY *key); +# endif +int Camellia_set_key(const unsigned char *userKey, const int bits, + CAMELLIA_KEY *key); + +void Camellia_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); +void Camellia_decrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); + +void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key, const int enc); +void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, const int enc); +void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num); +void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char ivec[CAMELLIA_BLOCK_SIZE], + unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE], + unsigned int *num); + +#ifdef __cplusplus +} +#endif + +#endif /* !HEADER_Camellia_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/cast.h b/optee/optee_test/host/openssl/include/openssl/cast.h new file mode 100644 index 0000000..0003ec9 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/cast.h @@ -0,0 +1,107 @@ +/* crypto/cast/cast.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CAST_H +# define HEADER_CAST_H + +#ifdef __cplusplus +extern "C" { +#endif + +# include + +# ifdef OPENSSL_NO_CAST +# error CAST is disabled. +# endif + +# define CAST_ENCRYPT 1 +# define CAST_DECRYPT 0 + +# define CAST_LONG unsigned int + +# define CAST_BLOCK 8 +# define CAST_KEY_LENGTH 16 + +typedef struct cast_key_st { + CAST_LONG data[32]; + int short_key; /* Use reduced rounds for short key */ +} CAST_KEY; + +# ifdef OPENSSL_FIPS +void private_CAST_set_key(CAST_KEY *key, int len, const unsigned char *data); +# endif +void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data); +void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAST_KEY *key, int enc); +void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key); +void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key); +void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *ks, unsigned char *iv, + int enc); +void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, + unsigned char *ivec, int *num, int enc); +void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, + unsigned char *ivec, int *num); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/cmac.h b/optee/optee_test/host/openssl/include/openssl/cmac.h new file mode 100644 index 0000000..175be83 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/cmac.h @@ -0,0 +1,82 @@ +/* crypto/cmac/cmac.h */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2010 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 HEADER_CMAC_H +# define HEADER_CMAC_H + +#ifdef __cplusplus +extern "C" { +#endif + +# include + +/* Opaque */ +typedef struct CMAC_CTX_st CMAC_CTX; + +CMAC_CTX *CMAC_CTX_new(void); +void CMAC_CTX_cleanup(CMAC_CTX *ctx); +void CMAC_CTX_free(CMAC_CTX *ctx); +EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx); +int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in); + +int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, + const EVP_CIPHER *cipher, ENGINE *impl); +int CMAC_Update(CMAC_CTX *ctx, const void *data, size_t dlen); +int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen); +int CMAC_resume(CMAC_CTX *ctx); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/cms.h b/optee/optee_test/host/openssl/include/openssl/cms.h new file mode 100644 index 0000000..e6c7f96 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/cms.h @@ -0,0 +1,555 @@ +/* crypto/cms/cms.h */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 HEADER_CMS_H +# define HEADER_CMS_H + +# include + +# ifdef OPENSSL_NO_CMS +# error CMS is disabled. +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CMS_ContentInfo_st CMS_ContentInfo; +typedef struct CMS_SignerInfo_st CMS_SignerInfo; +typedef struct CMS_CertificateChoices CMS_CertificateChoices; +typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice; +typedef struct CMS_RecipientInfo_st CMS_RecipientInfo; +typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest; +typedef struct CMS_Receipt_st CMS_Receipt; +typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey; +typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute; + +DECLARE_STACK_OF(CMS_SignerInfo) +DECLARE_STACK_OF(GENERAL_NAMES) +DECLARE_STACK_OF(CMS_RecipientEncryptedKey) +DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo) +DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest) +DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo) + +# define CMS_SIGNERINFO_ISSUER_SERIAL 0 +# define CMS_SIGNERINFO_KEYIDENTIFIER 1 + +# define CMS_RECIPINFO_NONE -1 +# define CMS_RECIPINFO_TRANS 0 +# define CMS_RECIPINFO_AGREE 1 +# define CMS_RECIPINFO_KEK 2 +# define CMS_RECIPINFO_PASS 3 +# define CMS_RECIPINFO_OTHER 4 + +/* S/MIME related flags */ + +# define CMS_TEXT 0x1 +# define CMS_NOCERTS 0x2 +# define CMS_NO_CONTENT_VERIFY 0x4 +# define CMS_NO_ATTR_VERIFY 0x8 +# define CMS_NOSIGS \ + (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY) +# define CMS_NOINTERN 0x10 +# define CMS_NO_SIGNER_CERT_VERIFY 0x20 +# define CMS_NOVERIFY 0x20 +# define CMS_DETACHED 0x40 +# define CMS_BINARY 0x80 +# define CMS_NOATTR 0x100 +# define CMS_NOSMIMECAP 0x200 +# define CMS_NOOLDMIMETYPE 0x400 +# define CMS_CRLFEOL 0x800 +# define CMS_STREAM 0x1000 +# define CMS_NOCRL 0x2000 +# define CMS_PARTIAL 0x4000 +# define CMS_REUSE_DIGEST 0x8000 +# define CMS_USE_KEYID 0x10000 +# define CMS_DEBUG_DECRYPT 0x20000 +# define CMS_KEY_PARAM 0x40000 + +const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms); + +BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont); +int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio); + +ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms); +int CMS_is_detached(CMS_ContentInfo *cms); +int CMS_set_detached(CMS_ContentInfo *cms, int detached); + +# ifdef HEADER_PEM_H +DECLARE_PEM_rw_const(CMS, CMS_ContentInfo) +# endif +int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms); +CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms); +int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms); + +BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms); +int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags); +int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, + int flags); +CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont); +int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags); + +int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, + unsigned int flags); + +CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, BIO *data, + unsigned int flags); + +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, + X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, unsigned int flags); + +int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags); +CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags); + +int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, + unsigned int flags); + +int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, + const unsigned char *key, size_t keylen, + BIO *dcont, BIO *out, unsigned int flags); + +CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, + const unsigned char *key, + size_t keylen, unsigned int flags); + +int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, + const unsigned char *key, size_t keylen); + +int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags); + +int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms, + STACK_OF(X509) *certs, + X509_STORE *store, unsigned int flags); + +STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms); + +CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, + const EVP_CIPHER *cipher, unsigned int flags); + +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, + BIO *dcont, BIO *out, unsigned int flags); + +int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert); +int CMS_decrypt_set1_key(CMS_ContentInfo *cms, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen); +int CMS_decrypt_set1_password(CMS_ContentInfo *cms, + unsigned char *pass, ossl_ssize_t passlen); + +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms); +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); +EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri); +CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher); +CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, + X509 *recip, unsigned int flags); +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey); +int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert); +int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, + EVP_PKEY **pk, X509 **recip, + X509_ALGOR **palg); +int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno); + +CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, + unsigned char *key, size_t keylen, + unsigned char *id, size_t idlen, + ASN1_GENERALIZEDTIME *date, + ASN1_OBJECT *otherTypeId, + ASN1_TYPE *otherType); + +int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pid, + ASN1_GENERALIZEDTIME **pdate, + ASN1_OBJECT **potherid, + ASN1_TYPE **pothertype); + +int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, + unsigned char *key, size_t keylen); + +int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, + const unsigned char *id, size_t idlen); + +int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, + unsigned char *pass, + ossl_ssize_t passlen); + +CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, + int iter, int wrap_nid, + int pbe_nid, + unsigned char *pass, + ossl_ssize_t passlen, + const EVP_CIPHER *kekciph); + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); +int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags); + +int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid); +const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms); + +CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms); +int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert); +int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert); +STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms); + +CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms); +int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl); +int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl); +STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms); + +int CMS_SignedData_init(CMS_ContentInfo *cms); +CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, + X509 *signer, EVP_PKEY *pk, const EVP_MD *md, + unsigned int flags); +EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si); +EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si); +STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms); + +void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer); +int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert); +int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + unsigned int flags); +void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, + X509 **signer, X509_ALGOR **pdig, + X509_ALGOR **psig); +ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si); +int CMS_SignerInfo_sign(CMS_SignerInfo *si); +int CMS_SignerInfo_verify(CMS_SignerInfo *si); +int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain); + +int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs); +int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, + int algnid, int keysize); +int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap); + +int CMS_signed_get_attr_count(const CMS_SignerInfo *si); +int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len); +void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type); + +int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si); +int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si, + int nid, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, + const void *bytes, int len); +void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type); + +# ifdef HEADER_X509V3_H + +int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr); +CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen, + int allorfirst, + STACK_OF(GENERAL_NAMES) + *receiptList, STACK_OF(GENERAL_NAMES) + *receiptsTo); +int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr); +void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, + ASN1_STRING **pcid, + int *pallorfirst, + STACK_OF(GENERAL_NAMES) **plist, + STACK_OF(GENERAL_NAMES) **prto); +# endif +int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, + X509_ALGOR **palg, + ASN1_OCTET_STRING **pukm); +STACK_OF(CMS_RecipientEncryptedKey) +*CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri); + +int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, + X509_ALGOR **pubalg, + ASN1_BIT_STRING **pubkey, + ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, + ASN1_INTEGER **sno); + +int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert); + +int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, + ASN1_OCTET_STRING **keyid, + ASN1_GENERALIZEDTIME **tm, + CMS_OtherKeyAttribute **other, + X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, + X509 *cert); +int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk); +EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri); +int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri, + CMS_RecipientEncryptedKey *rek); + +int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg, + ASN1_OCTET_STRING *ukm, int keylen); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_CMS_strings(void); + +/* Error codes for the CMS functions. */ + +/* Function codes. */ +# define CMS_F_CHECK_CONTENT 99 +# define CMS_F_CMS_ADD0_CERT 164 +# define CMS_F_CMS_ADD0_RECIPIENT_KEY 100 +# define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 165 +# define CMS_F_CMS_ADD1_RECEIPTREQUEST 158 +# define CMS_F_CMS_ADD1_RECIPIENT_CERT 101 +# define CMS_F_CMS_ADD1_SIGNER 102 +# define CMS_F_CMS_ADD1_SIGNINGTIME 103 +# define CMS_F_CMS_COMPRESS 104 +# define CMS_F_CMS_COMPRESSEDDATA_CREATE 105 +# define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 106 +# define CMS_F_CMS_COPY_CONTENT 107 +# define CMS_F_CMS_COPY_MESSAGEDIGEST 108 +# define CMS_F_CMS_DATA 109 +# define CMS_F_CMS_DATAFINAL 110 +# define CMS_F_CMS_DATAINIT 111 +# define CMS_F_CMS_DECRYPT 112 +# define CMS_F_CMS_DECRYPT_SET1_KEY 113 +# define CMS_F_CMS_DECRYPT_SET1_PASSWORD 166 +# define CMS_F_CMS_DECRYPT_SET1_PKEY 114 +# define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115 +# define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116 +# define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117 +# define CMS_F_CMS_DIGEST_VERIFY 118 +# define CMS_F_CMS_ENCODE_RECEIPT 161 +# define CMS_F_CMS_ENCRYPT 119 +# define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120 +# define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121 +# define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 122 +# define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 123 +# define CMS_F_CMS_ENVELOPEDDATA_CREATE 124 +# define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125 +# define CMS_F_CMS_ENVELOPED_DATA_INIT 126 +# define CMS_F_CMS_ENV_ASN1_CTRL 171 +# define CMS_F_CMS_FINAL 127 +# define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 128 +# define CMS_F_CMS_GET0_CONTENT 129 +# define CMS_F_CMS_GET0_ECONTENT_TYPE 130 +# define CMS_F_CMS_GET0_ENVELOPED 131 +# define CMS_F_CMS_GET0_REVOCATION_CHOICES 132 +# define CMS_F_CMS_GET0_SIGNED 133 +# define CMS_F_CMS_MSGSIGDIGEST_ADD1 162 +# define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159 +# define CMS_F_CMS_RECEIPT_VERIFY 160 +# define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134 +# define CMS_F_CMS_RECIPIENTINFO_ENCRYPT 169 +# define CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT 178 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG 175 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID 173 +# define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS 172 +# define CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP 174 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 135 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 136 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 137 +# define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 138 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 139 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 140 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 141 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 142 +# define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 143 +# define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT 167 +# define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144 +# define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 168 +# define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145 +# define CMS_F_CMS_SD_ASN1_CTRL 170 +# define CMS_F_CMS_SET1_IAS 176 +# define CMS_F_CMS_SET1_KEYID 177 +# define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146 +# define CMS_F_CMS_SET_DETACHED 147 +# define CMS_F_CMS_SIGN 148 +# define CMS_F_CMS_SIGNED_DATA_INIT 149 +# define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 150 +# define CMS_F_CMS_SIGNERINFO_SIGN 151 +# define CMS_F_CMS_SIGNERINFO_VERIFY 152 +# define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153 +# define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154 +# define CMS_F_CMS_SIGN_RECEIPT 163 +# define CMS_F_CMS_STREAM 155 +# define CMS_F_CMS_UNCOMPRESS 156 +# define CMS_F_CMS_VERIFY 157 + +/* Reason codes. */ +# define CMS_R_ADD_SIGNER_ERROR 99 +# define CMS_R_CERTIFICATE_ALREADY_PRESENT 175 +# define CMS_R_CERTIFICATE_HAS_NO_KEYID 160 +# define CMS_R_CERTIFICATE_VERIFY_ERROR 100 +# define CMS_R_CIPHER_INITIALISATION_ERROR 101 +# define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 102 +# define CMS_R_CMS_DATAFINAL_ERROR 103 +# define CMS_R_CMS_LIB 104 +# define CMS_R_CONTENTIDENTIFIER_MISMATCH 170 +# define CMS_R_CONTENT_NOT_FOUND 105 +# define CMS_R_CONTENT_TYPE_MISMATCH 171 +# define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 106 +# define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 107 +# define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA 108 +# define CMS_R_CONTENT_VERIFY_ERROR 109 +# define CMS_R_CTRL_ERROR 110 +# define CMS_R_CTRL_FAILURE 111 +# define CMS_R_DECRYPT_ERROR 112 +# define CMS_R_DIGEST_ERROR 161 +# define CMS_R_ERROR_GETTING_PUBLIC_KEY 113 +# define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114 +# define CMS_R_ERROR_SETTING_KEY 115 +# define CMS_R_ERROR_SETTING_RECIPIENTINFO 116 +# define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117 +# define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176 +# define CMS_R_INVALID_KEY_LENGTH 118 +# define CMS_R_MD_BIO_INIT_ERROR 119 +# define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120 +# define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 121 +# define CMS_R_MSGSIGDIGEST_ERROR 172 +# define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE 162 +# define CMS_R_MSGSIGDIGEST_WRONG_LENGTH 163 +# define CMS_R_NEED_ONE_SIGNER 164 +# define CMS_R_NOT_A_SIGNED_RECEIPT 165 +# define CMS_R_NOT_ENCRYPTED_DATA 122 +# define CMS_R_NOT_KEK 123 +# define CMS_R_NOT_KEY_AGREEMENT 181 +# define CMS_R_NOT_KEY_TRANSPORT 124 +# define CMS_R_NOT_PWRI 177 +# define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 125 +# define CMS_R_NO_CIPHER 126 +# define CMS_R_NO_CONTENT 127 +# define CMS_R_NO_CONTENT_TYPE 173 +# define CMS_R_NO_DEFAULT_DIGEST 128 +# define CMS_R_NO_DIGEST_SET 129 +# define CMS_R_NO_KEY 130 +# define CMS_R_NO_KEY_OR_CERT 174 +# define CMS_R_NO_MATCHING_DIGEST 131 +# define CMS_R_NO_MATCHING_RECIPIENT 132 +# define CMS_R_NO_MATCHING_SIGNATURE 166 +# define CMS_R_NO_MSGSIGDIGEST 167 +# define CMS_R_NO_PASSWORD 178 +# define CMS_R_NO_PRIVATE_KEY 133 +# define CMS_R_NO_PUBLIC_KEY 134 +# define CMS_R_NO_RECEIPT_REQUEST 168 +# define CMS_R_NO_SIGNERS 135 +# define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136 +# define CMS_R_RECEIPT_DECODE_ERROR 169 +# define CMS_R_RECIPIENT_ERROR 137 +# define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 138 +# define CMS_R_SIGNFINAL_ERROR 139 +# define CMS_R_SMIME_TEXT_ERROR 140 +# define CMS_R_STORE_INIT_ERROR 141 +# define CMS_R_TYPE_NOT_COMPRESSED_DATA 142 +# define CMS_R_TYPE_NOT_DATA 143 +# define CMS_R_TYPE_NOT_DIGESTED_DATA 144 +# define CMS_R_TYPE_NOT_ENCRYPTED_DATA 145 +# define CMS_R_TYPE_NOT_ENVELOPED_DATA 146 +# define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 147 +# define CMS_R_UNKNOWN_CIPHER 148 +# define CMS_R_UNKNOWN_DIGEST_ALGORIHM 149 +# define CMS_R_UNKNOWN_ID 150 +# define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151 +# define CMS_R_UNSUPPORTED_CONTENT_TYPE 152 +# define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153 +# define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179 +# define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154 +# define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE 155 +# define CMS_R_UNSUPPORTED_TYPE 156 +# define CMS_R_UNWRAP_ERROR 157 +# define CMS_R_UNWRAP_FAILURE 180 +# define CMS_R_VERIFICATION_FAILURE 158 +# define CMS_R_WRAP_ERROR 159 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/comp.h b/optee/optee_test/host/openssl/include/openssl/comp.h new file mode 100644 index 0000000..df599ba --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/comp.h @@ -0,0 +1,83 @@ + +#ifndef HEADER_COMP_H +# define HEADER_COMP_H + +# include + +# ifdef OPENSSL_NO_COMP +# error COMP is disabled. +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct comp_ctx_st COMP_CTX; + +struct comp_method_st { + int type; /* NID for compression library */ + const char *name; /* A text string to identify the library */ + int (*init) (COMP_CTX *ctx); + void (*finish) (COMP_CTX *ctx); + int (*compress) (COMP_CTX *ctx, + unsigned char *out, unsigned int olen, + unsigned char *in, unsigned int ilen); + int (*expand) (COMP_CTX *ctx, + unsigned char *out, unsigned int olen, + unsigned char *in, unsigned int ilen); + /* + * The following two do NOTHING, but are kept for backward compatibility + */ + long (*ctrl) (void); + long (*callback_ctrl) (void); +}; + +struct comp_ctx_st { + COMP_METHOD *meth; + unsigned long compress_in; + unsigned long compress_out; + unsigned long expand_in; + unsigned long expand_out; + CRYPTO_EX_DATA ex_data; +}; + +COMP_CTX *COMP_CTX_new(COMP_METHOD *meth); +void COMP_CTX_free(COMP_CTX *ctx); +int COMP_compress_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen); +int COMP_expand_block(COMP_CTX *ctx, unsigned char *out, int olen, + unsigned char *in, int ilen); +COMP_METHOD *COMP_rle(void); +COMP_METHOD *COMP_zlib(void); +void COMP_zlib_cleanup(void); + +# ifdef HEADER_BIO_H +# ifdef ZLIB +BIO_METHOD *BIO_f_zlib(void); +# endif +# endif + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_COMP_strings(void); + +/* Error codes for the COMP functions. */ + +/* Function codes. */ +# define COMP_F_BIO_ZLIB_FLUSH 99 +# define COMP_F_BIO_ZLIB_NEW 100 +# define COMP_F_BIO_ZLIB_READ 101 +# define COMP_F_BIO_ZLIB_WRITE 102 + +/* Reason codes. */ +# define COMP_R_ZLIB_DEFLATE_ERROR 99 +# define COMP_R_ZLIB_INFLATE_ERROR 100 +# define COMP_R_ZLIB_NOT_SUPPORTED 101 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/conf.h b/optee/optee_test/host/openssl/include/openssl/conf.h new file mode 100644 index 0000000..fe49113 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/conf.h @@ -0,0 +1,268 @@ +/* crypto/conf/conf.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CONF_H +# define HEADER_CONF_H + +# include +# include +# include +# include +# include + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *section; + char *name; + char *value; +} CONF_VALUE; + +DECLARE_STACK_OF(CONF_VALUE) +DECLARE_LHASH_OF(CONF_VALUE); + +struct conf_st; +struct conf_method_st; +typedef struct conf_method_st CONF_METHOD; + +struct conf_method_st { + const char *name; + CONF *(*create) (CONF_METHOD *meth); + int (*init) (CONF *conf); + int (*destroy) (CONF *conf); + int (*destroy_data) (CONF *conf); + int (*load_bio) (CONF *conf, BIO *bp, long *eline); + int (*dump) (const CONF *conf, BIO *bp); + int (*is_number) (const CONF *conf, char c); + int (*to_int) (const CONF *conf, char c); + int (*load) (CONF *conf, const char *name, long *eline); +}; + +/* Module definitions */ + +typedef struct conf_imodule_st CONF_IMODULE; +typedef struct conf_module_st CONF_MODULE; + +DECLARE_STACK_OF(CONF_MODULE) +DECLARE_STACK_OF(CONF_IMODULE) + +/* DSO module function typedefs */ +typedef int conf_init_func (CONF_IMODULE *md, const CONF *cnf); +typedef void conf_finish_func (CONF_IMODULE *md); + +# define CONF_MFLAGS_IGNORE_ERRORS 0x1 +# define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2 +# define CONF_MFLAGS_SILENT 0x4 +# define CONF_MFLAGS_NO_DSO 0x8 +# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +# define CONF_MFLAGS_DEFAULT_SECTION 0x20 + +int CONF_set_default_method(CONF_METHOD *meth); +void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash); +LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file, + long *eline); +# ifndef OPENSSL_NO_FP_API +LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp, + long *eline); +# endif +LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp, + long *eline); +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf, + const char *section); +char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name); +long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name); +void CONF_free(LHASH_OF(CONF_VALUE) *conf); +int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out); +int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out); + +void OPENSSL_config(const char *config_name); +void OPENSSL_no_config(void); + +/* + * New conf code. The semantics are different from the functions above. If + * that wasn't the case, the above functions would have been replaced + */ + +struct conf_st { + CONF_METHOD *meth; + void *meth_data; + LHASH_OF(CONF_VALUE) *data; +}; + +CONF *NCONF_new(CONF_METHOD *meth); +CONF_METHOD *NCONF_default(void); +CONF_METHOD *NCONF_WIN32(void); +# if 0 /* Just to give you an idea of what I have in + * mind */ +CONF_METHOD *NCONF_XML(void); +# endif +void NCONF_free(CONF *conf); +void NCONF_free_data(CONF *conf); + +int NCONF_load(CONF *conf, const char *file, long *eline); +# ifndef OPENSSL_NO_FP_API +int NCONF_load_fp(CONF *conf, FILE *fp, long *eline); +# endif +int NCONF_load_bio(CONF *conf, BIO *bp, long *eline); +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, + const char *section); +char *NCONF_get_string(const CONF *conf, const char *group, const char *name); +int NCONF_get_number_e(const CONF *conf, const char *group, const char *name, + long *result); +int NCONF_dump_fp(const CONF *conf, FILE *out); +int NCONF_dump_bio(const CONF *conf, BIO *out); + +# if 0 /* The following function has no error + * checking, and should therefore be avoided */ +long NCONF_get_number(CONF *conf, char *group, char *name); +# else +# define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r) +# endif + +/* Module functions */ + +int CONF_modules_load(const CONF *cnf, const char *appname, + unsigned long flags); +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags); +void CONF_modules_unload(int all); +void CONF_modules_finish(void); +void CONF_modules_free(void); +int CONF_module_add(const char *name, conf_init_func *ifunc, + conf_finish_func *ffunc); + +const char *CONF_imodule_get_name(const CONF_IMODULE *md); +const char *CONF_imodule_get_value(const CONF_IMODULE *md); +void *CONF_imodule_get_usr_data(const CONF_IMODULE *md); +void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data); +CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md); +unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md); +void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags); +void *CONF_module_get_usr_data(CONF_MODULE *pmod); +void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data); + +char *CONF_get1_default_config_file(void); + +int CONF_parse_list(const char *list, int sep, int nospc, + int (*list_cb) (const char *elem, int len, void *usr), + void *arg); + +void OPENSSL_load_builtin_modules(void); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_CONF_strings(void); + +/* Error codes for the CONF functions. */ + +/* Function codes. */ +# define CONF_F_CONF_DUMP_FP 104 +# define CONF_F_CONF_LOAD 100 +# define CONF_F_CONF_LOAD_BIO 102 +# define CONF_F_CONF_LOAD_FP 103 +# define CONF_F_CONF_MODULES_LOAD 116 +# define CONF_F_CONF_PARSE_LIST 119 +# define CONF_F_DEF_LOAD 120 +# define CONF_F_DEF_LOAD_BIO 121 +# define CONF_F_MODULE_INIT 115 +# define CONF_F_MODULE_LOAD_DSO 117 +# define CONF_F_MODULE_RUN 118 +# define CONF_F_NCONF_DUMP_BIO 105 +# define CONF_F_NCONF_DUMP_FP 106 +# define CONF_F_NCONF_GET_NUMBER 107 +# define CONF_F_NCONF_GET_NUMBER_E 112 +# define CONF_F_NCONF_GET_SECTION 108 +# define CONF_F_NCONF_GET_STRING 109 +# define CONF_F_NCONF_LOAD 113 +# define CONF_F_NCONF_LOAD_BIO 110 +# define CONF_F_NCONF_LOAD_FP 114 +# define CONF_F_NCONF_NEW 111 +# define CONF_F_STR_COPY 101 + +/* Reason codes. */ +# define CONF_R_ERROR_LOADING_DSO 110 +# define CONF_R_LIST_CANNOT_BE_NULL 115 +# define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100 +# define CONF_R_MISSING_EQUAL_SIGN 101 +# define CONF_R_MISSING_FINISH_FUNCTION 111 +# define CONF_R_MISSING_INIT_FUNCTION 112 +# define CONF_R_MODULE_INITIALIZATION_ERROR 109 +# define CONF_R_NO_CLOSE_BRACE 102 +# define CONF_R_NO_CONF 105 +# define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE 106 +# define CONF_R_NO_SECTION 107 +# define CONF_R_NO_SUCH_FILE 114 +# define CONF_R_NO_VALUE 108 +# define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 103 +# define CONF_R_UNKNOWN_MODULE_NAME 113 +# define CONF_R_VARIABLE_EXPANSION_TOO_LONG 116 +# define CONF_R_VARIABLE_HAS_NO_VALUE 104 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/conf_api.h b/optee/optee_test/host/openssl/include/openssl/conf_api.h new file mode 100644 index 0000000..e478f7d --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/conf_api.h @@ -0,0 +1,89 @@ +/* conf_api.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CONF_API_H +# define HEADER_CONF_API_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Up until OpenSSL 0.9.5a, this was new_section */ +CONF_VALUE *_CONF_new_section(CONF *conf, const char *section); +/* Up until OpenSSL 0.9.5a, this was get_section */ +CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section); +/* Up until OpenSSL 0.9.5a, this was CONF_get_section */ +STACK_OF(CONF_VALUE) *_CONF_get_section_values(const CONF *conf, + const char *section); + +int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value); +char *_CONF_get_string(const CONF *conf, const char *section, + const char *name); +long _CONF_get_number(const CONF *conf, const char *section, + const char *name); + +int _CONF_new_data(CONF *conf); +void _CONF_free_data(CONF *conf); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/crypto.h b/optee/optee_test/host/openssl/include/openssl/crypto.h new file mode 100644 index 0000000..6c644ce --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/crypto.h @@ -0,0 +1,661 @@ +/* crypto/crypto.h */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_CRYPTO_H +# define HEADER_CRYPTO_H + +# include + +# include + +# ifndef OPENSSL_NO_FP_API +# include +# endif + +# include +# include +# include +# include + +# ifdef CHARSET_EBCDIC +# include +# endif + +/* + * Resolve problems on some operating systems with symbol names that clash + * one way or another + */ +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Backward compatibility to SSLeay */ +/* + * This is more to be used to check the correct DLL is being used in the MS + * world. + */ +# define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER +# define SSLEAY_VERSION 0 +/* #define SSLEAY_OPTIONS 1 no longer supported */ +# define SSLEAY_CFLAGS 2 +# define SSLEAY_BUILT_ON 3 +# define SSLEAY_PLATFORM 4 +# define SSLEAY_DIR 5 + +/* Already declared in ossl_typ.h */ +# if 0 +typedef struct crypto_ex_data_st CRYPTO_EX_DATA; +/* Called when a new object is created */ +typedef int CRYPTO_EX_new (void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +/* Called when an object is free()ed */ +typedef void CRYPTO_EX_free (void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +/* Called when we need to dup an object */ +typedef int CRYPTO_EX_dup (CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, + void *from_d, int idx, long argl, void *argp); +# endif + +/* A generic structure to pass assorted data in a expandable way */ +typedef struct openssl_item_st { + int code; + void *value; /* Not used for flag attributes */ + size_t value_size; /* Max size of value for output, length for + * input */ + size_t *value_length; /* Returned length of value for output */ +} OPENSSL_ITEM; + +/* + * When changing the CRYPTO_LOCK_* list, be sure to maintin the text lock + * names in cryptlib.c + */ + +# define CRYPTO_LOCK_ERR 1 +# define CRYPTO_LOCK_EX_DATA 2 +# define CRYPTO_LOCK_X509 3 +# define CRYPTO_LOCK_X509_INFO 4 +# define CRYPTO_LOCK_X509_PKEY 5 +# define CRYPTO_LOCK_X509_CRL 6 +# define CRYPTO_LOCK_X509_REQ 7 +# define CRYPTO_LOCK_DSA 8 +# define CRYPTO_LOCK_RSA 9 +# define CRYPTO_LOCK_EVP_PKEY 10 +# define CRYPTO_LOCK_X509_STORE 11 +# define CRYPTO_LOCK_SSL_CTX 12 +# define CRYPTO_LOCK_SSL_CERT 13 +# define CRYPTO_LOCK_SSL_SESSION 14 +# define CRYPTO_LOCK_SSL_SESS_CERT 15 +# define CRYPTO_LOCK_SSL 16 +# define CRYPTO_LOCK_SSL_METHOD 17 +# define CRYPTO_LOCK_RAND 18 +# define CRYPTO_LOCK_RAND2 19 +# define CRYPTO_LOCK_MALLOC 20 +# define CRYPTO_LOCK_BIO 21 +# define CRYPTO_LOCK_GETHOSTBYNAME 22 +# define CRYPTO_LOCK_GETSERVBYNAME 23 +# define CRYPTO_LOCK_READDIR 24 +# define CRYPTO_LOCK_RSA_BLINDING 25 +# define CRYPTO_LOCK_DH 26 +# define CRYPTO_LOCK_MALLOC2 27 +# define CRYPTO_LOCK_DSO 28 +# define CRYPTO_LOCK_DYNLOCK 29 +# define CRYPTO_LOCK_ENGINE 30 +# define CRYPTO_LOCK_UI 31 +# define CRYPTO_LOCK_ECDSA 32 +# define CRYPTO_LOCK_EC 33 +# define CRYPTO_LOCK_ECDH 34 +# define CRYPTO_LOCK_BN 35 +# define CRYPTO_LOCK_EC_PRE_COMP 36 +# define CRYPTO_LOCK_STORE 37 +# define CRYPTO_LOCK_COMP 38 +# define CRYPTO_LOCK_FIPS 39 +# define CRYPTO_LOCK_FIPS2 40 +# define CRYPTO_NUM_LOCKS 41 + +# define CRYPTO_LOCK 1 +# define CRYPTO_UNLOCK 2 +# define CRYPTO_READ 4 +# define CRYPTO_WRITE 8 + +# ifndef OPENSSL_NO_LOCKING +# ifndef CRYPTO_w_lock +# define CRYPTO_w_lock(type) \ + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__) +# define CRYPTO_w_unlock(type) \ + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__) +# define CRYPTO_r_lock(type) \ + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__) +# define CRYPTO_r_unlock(type) \ + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__) +# define CRYPTO_add(addr,amount,type) \ + CRYPTO_add_lock(addr,amount,type,__FILE__,__LINE__) +# endif +# else +# define CRYPTO_w_lock(a) +# define CRYPTO_w_unlock(a) +# define CRYPTO_r_lock(a) +# define CRYPTO_r_unlock(a) +# define CRYPTO_add(a,b,c) ((*(a))+=(b)) +# endif + +/* + * Some applications as well as some parts of OpenSSL need to allocate and + * deallocate locks in a dynamic fashion. The following typedef makes this + * possible in a type-safe manner. + */ +/* struct CRYPTO_dynlock_value has to be defined by the application. */ +typedef struct { + int references; + struct CRYPTO_dynlock_value *data; +} CRYPTO_dynlock; + +/* + * The following can be used to detect memory leaks in the SSLeay library. It + * used, it turns on malloc checking + */ + +# define CRYPTO_MEM_CHECK_OFF 0x0/* an enume */ +# define CRYPTO_MEM_CHECK_ON 0x1/* a bit */ +# define CRYPTO_MEM_CHECK_ENABLE 0x2/* a bit */ +# define CRYPTO_MEM_CHECK_DISABLE 0x3/* an enume */ + +/* + * The following are bit values to turn on or off options connected to the + * malloc checking functionality + */ + +/* Adds time to the memory checking information */ +# define V_CRYPTO_MDEBUG_TIME 0x1/* a bit */ +/* Adds thread number to the memory checking information */ +# define V_CRYPTO_MDEBUG_THREAD 0x2/* a bit */ + +# define V_CRYPTO_MDEBUG_ALL (V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD) + +/* predec of the BIO type */ +typedef struct bio_st BIO_dummy; + +struct crypto_ex_data_st { + STACK_OF(void) *sk; + /* gcc is screwing up this data structure :-( */ + int dummy; +}; +DECLARE_STACK_OF(void) + +/* + * This stuff is basically class callback functions The current classes are + * SSL_CTX, SSL, SSL_SESSION, and a few more + */ + +typedef struct crypto_ex_data_func_st { + long argl; /* Arbitary long */ + void *argp; /* Arbitary void * */ + CRYPTO_EX_new *new_func; + CRYPTO_EX_free *free_func; + CRYPTO_EX_dup *dup_func; +} CRYPTO_EX_DATA_FUNCS; + +DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS) + +/* + * Per class, we have a STACK of CRYPTO_EX_DATA_FUNCS for each CRYPTO_EX_DATA + * entry. + */ + +# define CRYPTO_EX_INDEX_BIO 0 +# define CRYPTO_EX_INDEX_SSL 1 +# define CRYPTO_EX_INDEX_SSL_CTX 2 +# define CRYPTO_EX_INDEX_SSL_SESSION 3 +# define CRYPTO_EX_INDEX_X509_STORE 4 +# define CRYPTO_EX_INDEX_X509_STORE_CTX 5 +# define CRYPTO_EX_INDEX_RSA 6 +# define CRYPTO_EX_INDEX_DSA 7 +# define CRYPTO_EX_INDEX_DH 8 +# define CRYPTO_EX_INDEX_ENGINE 9 +# define CRYPTO_EX_INDEX_X509 10 +# define CRYPTO_EX_INDEX_UI 11 +# define CRYPTO_EX_INDEX_ECDSA 12 +# define CRYPTO_EX_INDEX_ECDH 13 +# define CRYPTO_EX_INDEX_COMP 14 +# define CRYPTO_EX_INDEX_STORE 15 + +/* + * Dynamically assigned indexes start from this value (don't use directly, + * use via CRYPTO_ex_data_new_class). + */ +# define CRYPTO_EX_INDEX_USER 100 + +/* + * This is the default callbacks, but we can have others as well: this is + * needed in Win32 where the application malloc and the library malloc may + * not be the same. + */ +# define CRYPTO_malloc_init() CRYPTO_set_mem_functions(\ + malloc, realloc, free) + +# if defined CRYPTO_MDEBUG_ALL || defined CRYPTO_MDEBUG_TIME || defined CRYPTO_MDEBUG_THREAD +# ifndef CRYPTO_MDEBUG /* avoid duplicate #define */ +# define CRYPTO_MDEBUG +# endif +# endif + +/* + * Set standard debugging functions (not done by default unless CRYPTO_MDEBUG + * is defined) + */ +# define CRYPTO_malloc_debug_init() do {\ + CRYPTO_set_mem_debug_functions(\ + CRYPTO_dbg_malloc,\ + CRYPTO_dbg_realloc,\ + CRYPTO_dbg_free,\ + CRYPTO_dbg_set_options,\ + CRYPTO_dbg_get_options);\ + } while(0) + +int CRYPTO_mem_ctrl(int mode); +int CRYPTO_is_mem_check_on(void); + +/* for applications */ +# define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) +# define MemCheck_stop() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) + +/* for library-internal use */ +# define MemCheck_on() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE) +# define MemCheck_off() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE) +# define is_MemCheck_on() CRYPTO_is_mem_check_on() + +# define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__) +# define OPENSSL_strdup(str) CRYPTO_strdup((str),__FILE__,__LINE__) +# define OPENSSL_realloc(addr,num) \ + CRYPTO_realloc((char *)addr,(int)num,__FILE__,__LINE__) +# define OPENSSL_realloc_clean(addr,old_num,num) \ + CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__) +# define OPENSSL_remalloc(addr,num) \ + CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__) +# define OPENSSL_freeFunc CRYPTO_free +# define OPENSSL_free(addr) CRYPTO_free(addr) + +# define OPENSSL_malloc_locked(num) \ + CRYPTO_malloc_locked((int)num,__FILE__,__LINE__) +# define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr) + +const char *SSLeay_version(int type); +unsigned long SSLeay(void); + +int OPENSSL_issetugid(void); + +/* An opaque type representing an implementation of "ex_data" support */ +typedef struct st_CRYPTO_EX_DATA_IMPL CRYPTO_EX_DATA_IMPL; +/* Return an opaque pointer to the current "ex_data" implementation */ +const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void); +/* Sets the "ex_data" implementation to be used (if it's not too late) */ +int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *i); +/* Get a new "ex_data" class, and return the corresponding "class_index" */ +int CRYPTO_ex_data_new_class(void); +/* Within a given class, get/register a new index */ +int CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +/* + * Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a + * given class (invokes whatever per-class callbacks are applicable) + */ +int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); +int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from); +void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); +/* + * Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular + * index (relative to the class type involved) + */ +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val); +void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx); +/* + * This function cleans up all "ex_data" state. It mustn't be called under + * potential race-conditions. + */ +void CRYPTO_cleanup_all_ex_data(void); + +int CRYPTO_get_new_lockid(char *name); + +int CRYPTO_num_locks(void); /* return CRYPTO_NUM_LOCKS (shared libs!) */ +void CRYPTO_lock(int mode, int type, const char *file, int line); +void CRYPTO_set_locking_callback(void (*func) (int mode, int type, + const char *file, int line)); +void (*CRYPTO_get_locking_callback(void)) (int mode, int type, + const char *file, int line); +void CRYPTO_set_add_lock_callback(int (*func) + (int *num, int mount, int type, + const char *file, int line)); +int (*CRYPTO_get_add_lock_callback(void)) (int *num, int mount, int type, + const char *file, int line); + +/* Don't use this structure directly. */ +typedef struct crypto_threadid_st { + void *ptr; + unsigned long val; +} CRYPTO_THREADID; +/* Only use CRYPTO_THREADID_set_[numeric|pointer]() within callbacks */ +void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val); +void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr); +int CRYPTO_THREADID_set_callback(void (*threadid_func) (CRYPTO_THREADID *)); +void (*CRYPTO_THREADID_get_callback(void)) (CRYPTO_THREADID *); +void CRYPTO_THREADID_current(CRYPTO_THREADID *id); +int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b); +void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src); +unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id); +# ifndef OPENSSL_NO_DEPRECATED +void CRYPTO_set_id_callback(unsigned long (*func) (void)); +unsigned long (*CRYPTO_get_id_callback(void)) (void); +unsigned long CRYPTO_thread_id(void); +# endif + +const char *CRYPTO_get_lock_name(int type); +int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, + int line); + +int CRYPTO_get_new_dynlockid(void); +void CRYPTO_destroy_dynlockid(int i); +struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i); +void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value + *(*dyn_create_function) (const char + *file, + int line)); +void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function) + (int mode, + struct CRYPTO_dynlock_value *l, + const char *file, int line)); +void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function) + (struct CRYPTO_dynlock_value *l, + const char *file, int line)); +struct CRYPTO_dynlock_value +*(*CRYPTO_get_dynlock_create_callback(void)) (const char *file, int line); +void (*CRYPTO_get_dynlock_lock_callback(void)) (int mode, + struct CRYPTO_dynlock_value + *l, const char *file, + int line); +void (*CRYPTO_get_dynlock_destroy_callback(void)) (struct CRYPTO_dynlock_value + *l, const char *file, + int line); + +/* + * CRYPTO_set_mem_functions includes CRYPTO_set_locked_mem_functions -- call + * the latter last if you need different functions + */ +int CRYPTO_set_mem_functions(void *(*m) (size_t), void *(*r) (void *, size_t), + void (*f) (void *)); +int CRYPTO_set_locked_mem_functions(void *(*m) (size_t), + void (*free_func) (void *)); +int CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, + int), void (*f) (void *)); +int CRYPTO_set_locked_mem_ex_functions(void *(*m) (size_t, const char *, int), + void (*free_func) (void *)); +int CRYPTO_set_mem_debug_functions(void (*m) + (void *, int, const char *, int, int), + void (*r) (void *, void *, int, + const char *, int, int), + void (*f) (void *, int), void (*so) (long), + long (*go) (void)); +void CRYPTO_get_mem_functions(void *(**m) (size_t), + void *(**r) (void *, size_t), + void (**f) (void *)); +void CRYPTO_get_locked_mem_functions(void *(**m) (size_t), + void (**f) (void *)); +void CRYPTO_get_mem_ex_functions(void *(**m) (size_t, const char *, int), + void *(**r) (void *, size_t, const char *, + int), void (**f) (void *)); +void CRYPTO_get_locked_mem_ex_functions(void + *(**m) (size_t, const char *, int), + void (**f) (void *)); +void CRYPTO_get_mem_debug_functions(void (**m) + (void *, int, const char *, int, int), + void (**r) (void *, void *, int, + const char *, int, int), + void (**f) (void *, int), + void (**so) (long), long (**go) (void)); + +void *CRYPTO_malloc_locked(int num, const char *file, int line); +void CRYPTO_free_locked(void *ptr); +void *CRYPTO_malloc(int num, const char *file, int line); +char *CRYPTO_strdup(const char *str, const char *file, int line); +void CRYPTO_free(void *ptr); +void *CRYPTO_realloc(void *addr, int num, const char *file, int line); +void *CRYPTO_realloc_clean(void *addr, int old_num, int num, const char *file, + int line); +void *CRYPTO_remalloc(void *addr, int num, const char *file, int line); + +void OPENSSL_cleanse(void *ptr, size_t len); + +void CRYPTO_set_mem_debug_options(long bits); +long CRYPTO_get_mem_debug_options(void); + +# define CRYPTO_push_info(info) \ + CRYPTO_push_info_(info, __FILE__, __LINE__); +int CRYPTO_push_info_(const char *info, const char *file, int line); +int CRYPTO_pop_info(void); +int CRYPTO_remove_all_info(void); + +/* + * Default debugging functions (enabled by CRYPTO_malloc_debug_init() macro; + * used as default in CRYPTO_MDEBUG compilations): + */ +/*- + * The last argument has the following significance: + * + * 0: called before the actual memory allocation has taken place + * 1: called after the actual memory allocation has taken place + */ +void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, + int before_p); +void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, const char *file, + int line, int before_p); +void CRYPTO_dbg_free(void *addr, int before_p); +/*- + * Tell the debugging code about options. By default, the following values + * apply: + * + * 0: Clear all options. + * V_CRYPTO_MDEBUG_TIME (1): Set the "Show Time" option. + * V_CRYPTO_MDEBUG_THREAD (2): Set the "Show Thread Number" option. + * V_CRYPTO_MDEBUG_ALL (3): 1 + 2 + */ +void CRYPTO_dbg_set_options(long bits); +long CRYPTO_dbg_get_options(void); + +# ifndef OPENSSL_NO_FP_API +void CRYPTO_mem_leaks_fp(FILE *); +# endif +void CRYPTO_mem_leaks(struct bio_st *bio); +/* unsigned long order, char *file, int line, int num_bytes, char *addr */ +typedef void *CRYPTO_MEM_LEAK_CB (unsigned long, const char *, int, int, + void *); +void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb); + +/* die if we have to */ +void OpenSSLDie(const char *file, int line, const char *assertion); +# define OPENSSL_assert(e) (void)((e) ? 0 : (OpenSSLDie(__FILE__, __LINE__, #e),1)) + +unsigned long *OPENSSL_ia32cap_loc(void); +# define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc())) +int OPENSSL_isservice(void); + +int FIPS_mode(void); +int FIPS_mode_set(int r); + +void OPENSSL_init(void); + +# define fips_md_init(alg) fips_md_init_ctx(alg, alg) + +# ifdef OPENSSL_FIPS +# define fips_md_init_ctx(alg, cx) \ + int alg##_Init(cx##_CTX *c) \ + { \ + if (FIPS_mode()) OpenSSLDie(__FILE__, __LINE__, \ + "Low level API call to digest " #alg " forbidden in FIPS mode!"); \ + return private_##alg##_Init(c); \ + } \ + int private_##alg##_Init(cx##_CTX *c) + +# define fips_cipher_abort(alg) \ + if (FIPS_mode()) OpenSSLDie(__FILE__, __LINE__, \ + "Low level API call to cipher " #alg " forbidden in FIPS mode!") + +# else +# define fips_md_init_ctx(alg, cx) \ + int alg##_Init(cx##_CTX *c) +# define fips_cipher_abort(alg) while(0) +# endif + +/* + * CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. + * It takes an amount of time dependent on |len|, but independent of the + * contents of |a| and |b|. Unlike memcmp, it cannot be used to put elements + * into a defined order as the return value when a != b is undefined, other + * than to be non-zero. + */ +int CRYPTO_memcmp(const volatile void *a, const volatile void *b, size_t len); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_CRYPTO_strings(void); + +/* Error codes for the CRYPTO functions. */ + +/* Function codes. */ +# define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100 +# define CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID 103 +# define CRYPTO_F_CRYPTO_GET_NEW_LOCKID 101 +# define CRYPTO_F_CRYPTO_SET_EX_DATA 102 +# define CRYPTO_F_DEF_ADD_INDEX 104 +# define CRYPTO_F_DEF_GET_CLASS 105 +# define CRYPTO_F_FIPS_MODE_SET 109 +# define CRYPTO_F_INT_DUP_EX_DATA 106 +# define CRYPTO_F_INT_FREE_EX_DATA 107 +# define CRYPTO_F_INT_NEW_EX_DATA 108 + +/* Reason codes. */ +# define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101 +# define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/des.h b/optee/optee_test/host/openssl/include/openssl/des.h new file mode 100644 index 0000000..1b40144 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/des.h @@ -0,0 +1,257 @@ +/* crypto/des/des.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_NEW_DES_H +# define HEADER_NEW_DES_H + +# include /* OPENSSL_EXTERN, OPENSSL_NO_DES, DES_LONG + * (via openssl/opensslconf.h */ + +# ifdef OPENSSL_NO_DES +# error DES is disabled. +# endif + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char DES_cblock[8]; +typedef /* const */ unsigned char const_DES_cblock[8]; +/* + * With "const", gcc 2.8.1 on Solaris thinks that DES_cblock * and + * const_DES_cblock * are incompatible pointer types. + */ + +typedef struct DES_ks { + union { + DES_cblock cblock; + /* + * make sure things are correct size on machines with 8 byte longs + */ + DES_LONG deslong[2]; + } ks[16]; +} DES_key_schedule; + +# ifndef OPENSSL_DISABLE_OLD_DES_SUPPORT +# ifndef OPENSSL_ENABLE_OLD_DES_SUPPORT +# define OPENSSL_ENABLE_OLD_DES_SUPPORT +# endif +# endif + +# ifdef OPENSSL_ENABLE_OLD_DES_SUPPORT +# include +# endif + +# define DES_KEY_SZ (sizeof(DES_cblock)) +# define DES_SCHEDULE_SZ (sizeof(DES_key_schedule)) + +# define DES_ENCRYPT 1 +# define DES_DECRYPT 0 + +# define DES_CBC_MODE 0 +# define DES_PCBC_MODE 1 + +# define DES_ecb2_encrypt(i,o,k1,k2,e) \ + DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +# define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +# define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +# define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +OPENSSL_DECLARE_GLOBAL(int, DES_check_key); /* defaults to false */ +# define DES_check_key OPENSSL_GLOBAL_REF(DES_check_key) +OPENSSL_DECLARE_GLOBAL(int, DES_rw_mode); /* defaults to DES_PCBC_MODE */ +# define DES_rw_mode OPENSSL_GLOBAL_REF(DES_rw_mode) + +const char *DES_options(void); +void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, int enc); +DES_LONG DES_cbc_cksum(const unsigned char *input, DES_cblock *output, + long length, DES_key_schedule *schedule, + const_DES_cblock *ivec); +/* DES_cbc_encrypt does not update the IV! Use DES_ncbc_encrypt instead. */ +void DES_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_xcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, const_DES_cblock *inw, + const_DES_cblock *outw, int enc); +void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks, int enc); + +/* + * This is the DES encryption function that gets called by just about every + * other DES routine in the library. You should not use this function except + * to implement 'modes' of DES. I say this because the functions that call + * this routine do the conversion from 'char *' to long, and this needs to be + * done to make sure 'non-aligned' memory access do not occur. The + * characters are loaded 'little endian'. Data is a pointer to 2 unsigned + * long's and ks is the DES_key_schedule to use. enc, is non zero specifies + * encryption, zero if decryption. + */ +void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc); + +/* + * This functions is the same as DES_encrypt1() except that the DES initial + * permutation (IP) and final permutation (FP) have been left out. As for + * DES_encrypt1(), you should not use this function. It is used by the + * routines in the library that implement triple DES. IP() DES_encrypt2() + * DES_encrypt2() DES_encrypt2() FP() is the same as DES_encrypt1() + * DES_encrypt1() DES_encrypt1() except faster :-). + */ +void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc); + +void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, DES_cblock *ivec, int enc); +void DES_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, + long length, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, + DES_cblock *ivec1, DES_cblock *ivec2, int enc); +void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc); +void DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out, + int numbits, long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc); +void DES_ede3_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num); +# if 0 +void DES_xwhite_in2out(const_DES_cblock *DES_key, const_DES_cblock *in_white, + DES_cblock *out_white); +# endif + +int DES_enc_read(int fd, void *buf, int len, DES_key_schedule *sched, + DES_cblock *iv); +int DES_enc_write(int fd, const void *buf, int len, DES_key_schedule *sched, + DES_cblock *iv); +char *DES_fcrypt(const char *buf, const char *salt, char *ret); +char *DES_crypt(const char *buf, const char *salt); +void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, + DES_cblock *ivec); +void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int enc); +DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[], + long length, int out_count, DES_cblock *seed); +int DES_random_key(DES_cblock *ret); +void DES_set_odd_parity(DES_cblock *key); +int DES_check_key_parity(const_DES_cblock *key); +int DES_is_weak_key(const_DES_cblock *key); +/* + * DES_set_key (= set_key = DES_key_sched = key_sched) calls + * DES_set_key_checked if global variable DES_check_key is set, + * DES_set_key_unchecked otherwise. + */ +int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule); +int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule); +int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule); +void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule); +# ifdef OPENSSL_FIPS +void private_DES_set_key_unchecked(const_DES_cblock *key, + DES_key_schedule *schedule); +# endif +void DES_string_to_key(const char *str, DES_cblock *key); +void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2); +void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num, int enc); +void DES_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *schedule, + DES_cblock *ivec, int *num); + +int DES_read_password(DES_cblock *key, const char *prompt, int verify); +int DES_read_2passwords(DES_cblock *key1, DES_cblock *key2, + const char *prompt, int verify); + +# define DES_fixup_key_parity DES_set_odd_parity + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/des_old.h b/optee/optee_test/host/openssl/include/openssl/des_old.h new file mode 100644 index 0000000..ee7607a --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/des_old.h @@ -0,0 +1,497 @@ +/* crypto/des/des_old.h */ + +/*- + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + * + * The function names in here are deprecated and are only present to + * provide an interface compatible with openssl 0.9.6 and older as + * well as libdes. OpenSSL now provides functions where "des_" has + * been replaced with "DES_" in the names, to make it possible to + * make incompatible changes that are needed for C type security and + * other stuff. + * + * This include files has two compatibility modes: + * + * - If OPENSSL_DES_LIBDES_COMPATIBILITY is defined, you get an API + * that is compatible with libdes and SSLeay. + * - If OPENSSL_DES_LIBDES_COMPATIBILITY isn't defined, you get an + * API that is compatible with OpenSSL 0.9.5x to 0.9.6x. + * + * Note that these modes break earlier snapshots of OpenSSL, where + * libdes compatibility was the only available mode or (later on) the + * prefered compatibility mode. However, after much consideration + * (and more or less violent discussions with external parties), it + * was concluded that OpenSSL should be compatible with earlier versions + * of itself before anything else. Also, in all honesty, libdes is + * an old beast that shouldn't really be used any more. + * + * Please consider starting to use the DES_ functions rather than the + * des_ ones. The des_ functions will disappear completely before + * OpenSSL 1.0! + * + * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING + */ + +/* + * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project + * 2001. + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_DES_H +# define HEADER_DES_H + +# include /* OPENSSL_EXTERN, OPENSSL_NO_DES, DES_LONG */ + +# ifdef OPENSSL_NO_DES +# error DES is disabled. +# endif + +# ifndef HEADER_NEW_DES_H +# error You must include des.h, not des_old.h directly. +# endif + +# ifdef _KERBEROS_DES_H +# error replaces . +# endif + +# include + +# ifdef OPENSSL_BUILD_SHLIBCRYPTO +# undef OPENSSL_EXTERN +# define OPENSSL_EXTERN OPENSSL_EXPORT +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef _ +# undef _ +# endif + +typedef unsigned char _ossl_old_des_cblock[8]; +typedef struct _ossl_old_des_ks_struct { + union { + _ossl_old_des_cblock _; + /* + * make sure things are correct size on machines with 8 byte longs + */ + DES_LONG pad[2]; + } ks; +} _ossl_old_des_key_schedule[16]; + +# ifndef OPENSSL_DES_LIBDES_COMPATIBILITY +# define des_cblock DES_cblock +# define const_des_cblock const_DES_cblock +# define des_key_schedule DES_key_schedule +# define des_ecb3_encrypt(i,o,k1,k2,k3,e)\ + DES_ecb3_encrypt((i),(o),&(k1),&(k2),&(k3),(e)) +# define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\ + DES_ede3_cbc_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(e)) +# define des_ede3_cbcm_encrypt(i,o,l,k1,k2,k3,iv1,iv2,e)\ + DES_ede3_cbcm_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv1),(iv2),(e)) +# define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\ + DES_ede3_cfb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n),(e)) +# define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\ + DES_ede3_ofb64_encrypt((i),(o),(l),&(k1),&(k2),&(k3),(iv),(n)) +# define des_options()\ + DES_options() +# define des_cbc_cksum(i,o,l,k,iv)\ + DES_cbc_cksum((i),(o),(l),&(k),(iv)) +# define des_cbc_encrypt(i,o,l,k,iv,e)\ + DES_cbc_encrypt((i),(o),(l),&(k),(iv),(e)) +# define des_ncbc_encrypt(i,o,l,k,iv,e)\ + DES_ncbc_encrypt((i),(o),(l),&(k),(iv),(e)) +# define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\ + DES_xcbc_encrypt((i),(o),(l),&(k),(iv),(inw),(outw),(e)) +# define des_cfb_encrypt(i,o,n,l,k,iv,e)\ + DES_cfb_encrypt((i),(o),(n),(l),&(k),(iv),(e)) +# define des_ecb_encrypt(i,o,k,e)\ + DES_ecb_encrypt((i),(o),&(k),(e)) +# define des_encrypt1(d,k,e)\ + DES_encrypt1((d),&(k),(e)) +# define des_encrypt2(d,k,e)\ + DES_encrypt2((d),&(k),(e)) +# define des_encrypt3(d,k1,k2,k3)\ + DES_encrypt3((d),&(k1),&(k2),&(k3)) +# define des_decrypt3(d,k1,k2,k3)\ + DES_decrypt3((d),&(k1),&(k2),&(k3)) +# define des_xwhite_in2out(k,i,o)\ + DES_xwhite_in2out((k),(i),(o)) +# define des_enc_read(f,b,l,k,iv)\ + DES_enc_read((f),(b),(l),&(k),(iv)) +# define des_enc_write(f,b,l,k,iv)\ + DES_enc_write((f),(b),(l),&(k),(iv)) +# define des_fcrypt(b,s,r)\ + DES_fcrypt((b),(s),(r)) +# if 0 +# define des_crypt(b,s)\ + DES_crypt((b),(s)) +# if !defined(PERL5) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__) +# define crypt(b,s)\ + DES_crypt((b),(s)) +# endif +# endif +# define des_ofb_encrypt(i,o,n,l,k,iv)\ + DES_ofb_encrypt((i),(o),(n),(l),&(k),(iv)) +# define des_pcbc_encrypt(i,o,l,k,iv,e)\ + DES_pcbc_encrypt((i),(o),(l),&(k),(iv),(e)) +# define des_quad_cksum(i,o,l,c,s)\ + DES_quad_cksum((i),(o),(l),(c),(s)) +# define des_random_seed(k)\ + _ossl_096_des_random_seed((k)) +# define des_random_key(r)\ + DES_random_key((r)) +# define des_read_password(k,p,v) \ + DES_read_password((k),(p),(v)) +# define des_read_2passwords(k1,k2,p,v) \ + DES_read_2passwords((k1),(k2),(p),(v)) +# define des_set_odd_parity(k)\ + DES_set_odd_parity((k)) +# define des_check_key_parity(k)\ + DES_check_key_parity((k)) +# define des_is_weak_key(k)\ + DES_is_weak_key((k)) +# define des_set_key(k,ks)\ + DES_set_key((k),&(ks)) +# define des_key_sched(k,ks)\ + DES_key_sched((k),&(ks)) +# define des_set_key_checked(k,ks)\ + DES_set_key_checked((k),&(ks)) +# define des_set_key_unchecked(k,ks)\ + DES_set_key_unchecked((k),&(ks)) +# define des_string_to_key(s,k)\ + DES_string_to_key((s),(k)) +# define des_string_to_2keys(s,k1,k2)\ + DES_string_to_2keys((s),(k1),(k2)) +# define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\ + DES_cfb64_encrypt((i),(o),(l),&(ks),(iv),(n),(e)) +# define des_ofb64_encrypt(i,o,l,ks,iv,n)\ + DES_ofb64_encrypt((i),(o),(l),&(ks),(iv),(n)) + +# define des_ecb2_encrypt(i,o,k1,k2,e) \ + des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +# define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +# define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +# define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +# define des_check_key DES_check_key +# define des_rw_mode DES_rw_mode +# else /* libdes compatibility */ +/* + * Map all symbol names to _ossl_old_des_* form, so we avoid all clashes with + * libdes + */ +# define des_cblock _ossl_old_des_cblock +# define des_key_schedule _ossl_old_des_key_schedule +# define des_ecb3_encrypt(i,o,k1,k2,k3,e)\ + _ossl_old_des_ecb3_encrypt((i),(o),(k1),(k2),(k3),(e)) +# define des_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e)\ + _ossl_old_des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(e)) +# define des_ede3_cfb64_encrypt(i,o,l,k1,k2,k3,iv,n,e)\ + _ossl_old_des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n),(e)) +# define des_ede3_ofb64_encrypt(i,o,l,k1,k2,k3,iv,n)\ + _ossl_old_des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k3),(iv),(n)) +# define des_options()\ + _ossl_old_des_options() +# define des_cbc_cksum(i,o,l,k,iv)\ + _ossl_old_des_cbc_cksum((i),(o),(l),(k),(iv)) +# define des_cbc_encrypt(i,o,l,k,iv,e)\ + _ossl_old_des_cbc_encrypt((i),(o),(l),(k),(iv),(e)) +# define des_ncbc_encrypt(i,o,l,k,iv,e)\ + _ossl_old_des_ncbc_encrypt((i),(o),(l),(k),(iv),(e)) +# define des_xcbc_encrypt(i,o,l,k,iv,inw,outw,e)\ + _ossl_old_des_xcbc_encrypt((i),(o),(l),(k),(iv),(inw),(outw),(e)) +# define des_cfb_encrypt(i,o,n,l,k,iv,e)\ + _ossl_old_des_cfb_encrypt((i),(o),(n),(l),(k),(iv),(e)) +# define des_ecb_encrypt(i,o,k,e)\ + _ossl_old_des_ecb_encrypt((i),(o),(k),(e)) +# define des_encrypt(d,k,e)\ + _ossl_old_des_encrypt((d),(k),(e)) +# define des_encrypt2(d,k,e)\ + _ossl_old_des_encrypt2((d),(k),(e)) +# define des_encrypt3(d,k1,k2,k3)\ + _ossl_old_des_encrypt3((d),(k1),(k2),(k3)) +# define des_decrypt3(d,k1,k2,k3)\ + _ossl_old_des_decrypt3((d),(k1),(k2),(k3)) +# define des_xwhite_in2out(k,i,o)\ + _ossl_old_des_xwhite_in2out((k),(i),(o)) +# define des_enc_read(f,b,l,k,iv)\ + _ossl_old_des_enc_read((f),(b),(l),(k),(iv)) +# define des_enc_write(f,b,l,k,iv)\ + _ossl_old_des_enc_write((f),(b),(l),(k),(iv)) +# define des_fcrypt(b,s,r)\ + _ossl_old_des_fcrypt((b),(s),(r)) +# define des_crypt(b,s)\ + _ossl_old_des_crypt((b),(s)) +# if 0 +# define crypt(b,s)\ + _ossl_old_crypt((b),(s)) +# endif +# define des_ofb_encrypt(i,o,n,l,k,iv)\ + _ossl_old_des_ofb_encrypt((i),(o),(n),(l),(k),(iv)) +# define des_pcbc_encrypt(i,o,l,k,iv,e)\ + _ossl_old_des_pcbc_encrypt((i),(o),(l),(k),(iv),(e)) +# define des_quad_cksum(i,o,l,c,s)\ + _ossl_old_des_quad_cksum((i),(o),(l),(c),(s)) +# define des_random_seed(k)\ + _ossl_old_des_random_seed((k)) +# define des_random_key(r)\ + _ossl_old_des_random_key((r)) +# define des_read_password(k,p,v) \ + _ossl_old_des_read_password((k),(p),(v)) +# define des_read_2passwords(k1,k2,p,v) \ + _ossl_old_des_read_2passwords((k1),(k2),(p),(v)) +# define des_set_odd_parity(k)\ + _ossl_old_des_set_odd_parity((k)) +# define des_is_weak_key(k)\ + _ossl_old_des_is_weak_key((k)) +# define des_set_key(k,ks)\ + _ossl_old_des_set_key((k),(ks)) +# define des_key_sched(k,ks)\ + _ossl_old_des_key_sched((k),(ks)) +# define des_string_to_key(s,k)\ + _ossl_old_des_string_to_key((s),(k)) +# define des_string_to_2keys(s,k1,k2)\ + _ossl_old_des_string_to_2keys((s),(k1),(k2)) +# define des_cfb64_encrypt(i,o,l,ks,iv,n,e)\ + _ossl_old_des_cfb64_encrypt((i),(o),(l),(ks),(iv),(n),(e)) +# define des_ofb64_encrypt(i,o,l,ks,iv,n)\ + _ossl_old_des_ofb64_encrypt((i),(o),(l),(ks),(iv),(n)) + +# define des_ecb2_encrypt(i,o,k1,k2,e) \ + des_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +# define des_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + des_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +# define des_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + des_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +# define des_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + des_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +# define des_check_key DES_check_key +# define des_rw_mode DES_rw_mode +# endif + +const char *_ossl_old_des_options(void); +void _ossl_old_des_ecb3_encrypt(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, + _ossl_old_des_key_schedule ks1, + _ossl_old_des_key_schedule ks2, + _ossl_old_des_key_schedule ks3, int enc); +DES_LONG _ossl_old_des_cbc_cksum(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec); +void _ossl_old_des_cbc_encrypt(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec, int enc); +void _ossl_old_des_ncbc_encrypt(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec, int enc); +void _ossl_old_des_xcbc_encrypt(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec, + _ossl_old_des_cblock *inw, + _ossl_old_des_cblock *outw, int enc); +void _ossl_old_des_cfb_encrypt(unsigned char *in, unsigned char *out, + int numbits, long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec, int enc); +void _ossl_old_des_ecb_encrypt(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, + _ossl_old_des_key_schedule ks, int enc); +void _ossl_old_des_encrypt(DES_LONG *data, _ossl_old_des_key_schedule ks, + int enc); +void _ossl_old_des_encrypt2(DES_LONG *data, _ossl_old_des_key_schedule ks, + int enc); +void _ossl_old_des_encrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1, + _ossl_old_des_key_schedule ks2, + _ossl_old_des_key_schedule ks3); +void _ossl_old_des_decrypt3(DES_LONG *data, _ossl_old_des_key_schedule ks1, + _ossl_old_des_key_schedule ks2, + _ossl_old_des_key_schedule ks3); +void _ossl_old_des_ede3_cbc_encrypt(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, long length, + _ossl_old_des_key_schedule ks1, + _ossl_old_des_key_schedule ks2, + _ossl_old_des_key_schedule ks3, + _ossl_old_des_cblock *ivec, int enc); +void _ossl_old_des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, + long length, + _ossl_old_des_key_schedule ks1, + _ossl_old_des_key_schedule ks2, + _ossl_old_des_key_schedule ks3, + _ossl_old_des_cblock *ivec, int *num, + int enc); +void _ossl_old_des_ede3_ofb64_encrypt(unsigned char *in, unsigned char *out, + long length, + _ossl_old_des_key_schedule ks1, + _ossl_old_des_key_schedule ks2, + _ossl_old_des_key_schedule ks3, + _ossl_old_des_cblock *ivec, int *num); +# if 0 +void _ossl_old_des_xwhite_in2out(_ossl_old_des_cblock (*des_key), + _ossl_old_des_cblock (*in_white), + _ossl_old_des_cblock (*out_white)); +# endif + +int _ossl_old_des_enc_read(int fd, char *buf, int len, + _ossl_old_des_key_schedule sched, + _ossl_old_des_cblock *iv); +int _ossl_old_des_enc_write(int fd, char *buf, int len, + _ossl_old_des_key_schedule sched, + _ossl_old_des_cblock *iv); +char *_ossl_old_des_fcrypt(const char *buf, const char *salt, char *ret); +char *_ossl_old_des_crypt(const char *buf, const char *salt); +# if !defined(PERL5) && !defined(NeXT) +char *_ossl_old_crypt(const char *buf, const char *salt); +# endif +void _ossl_old_des_ofb_encrypt(unsigned char *in, unsigned char *out, + int numbits, long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec); +void _ossl_old_des_pcbc_encrypt(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec, int enc); +DES_LONG _ossl_old_des_quad_cksum(_ossl_old_des_cblock *input, + _ossl_old_des_cblock *output, long length, + int out_count, _ossl_old_des_cblock *seed); +void _ossl_old_des_random_seed(_ossl_old_des_cblock key); +void _ossl_old_des_random_key(_ossl_old_des_cblock ret); +int _ossl_old_des_read_password(_ossl_old_des_cblock *key, const char *prompt, + int verify); +int _ossl_old_des_read_2passwords(_ossl_old_des_cblock *key1, + _ossl_old_des_cblock *key2, + const char *prompt, int verify); +void _ossl_old_des_set_odd_parity(_ossl_old_des_cblock *key); +int _ossl_old_des_is_weak_key(_ossl_old_des_cblock *key); +int _ossl_old_des_set_key(_ossl_old_des_cblock *key, + _ossl_old_des_key_schedule schedule); +int _ossl_old_des_key_sched(_ossl_old_des_cblock *key, + _ossl_old_des_key_schedule schedule); +void _ossl_old_des_string_to_key(char *str, _ossl_old_des_cblock *key); +void _ossl_old_des_string_to_2keys(char *str, _ossl_old_des_cblock *key1, + _ossl_old_des_cblock *key2); +void _ossl_old_des_cfb64_encrypt(unsigned char *in, unsigned char *out, + long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec, int *num, + int enc); +void _ossl_old_des_ofb64_encrypt(unsigned char *in, unsigned char *out, + long length, + _ossl_old_des_key_schedule schedule, + _ossl_old_des_cblock *ivec, int *num); + +void _ossl_096_des_random_seed(des_cblock *key); + +/* + * The following definitions provide compatibility with the MIT Kerberos + * library. The _ossl_old_des_key_schedule structure is not binary + * compatible. + */ + +# define _KERBEROS_DES_H + +# define KRBDES_ENCRYPT DES_ENCRYPT +# define KRBDES_DECRYPT DES_DECRYPT + +# ifdef KERBEROS +# define ENCRYPT DES_ENCRYPT +# define DECRYPT DES_DECRYPT +# endif + +# ifndef NCOMPAT +# define C_Block des_cblock +# define Key_schedule des_key_schedule +# define KEY_SZ DES_KEY_SZ +# define string_to_key des_string_to_key +# define read_pw_string des_read_pw_string +# define random_key des_random_key +# define pcbc_encrypt des_pcbc_encrypt +# define set_key des_set_key +# define key_sched des_key_sched +# define ecb_encrypt des_ecb_encrypt +# define cbc_encrypt des_cbc_encrypt +# define ncbc_encrypt des_ncbc_encrypt +# define xcbc_encrypt des_xcbc_encrypt +# define cbc_cksum des_cbc_cksum +# define quad_cksum des_quad_cksum +# define check_parity des_check_key_parity +# endif + +# define des_fixup_key_parity DES_fixup_key_parity + +#ifdef __cplusplus +} +#endif + +/* for DES_read_pw_string et al */ +# include + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/dh.h b/optee/optee_test/host/openssl/include/openssl/dh.h new file mode 100644 index 0000000..80b28fb --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/dh.h @@ -0,0 +1,412 @@ +/* crypto/dh/dh.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_DH_H +# define HEADER_DH_H + +# include + +# ifdef OPENSSL_NO_DH +# error DH is disabled. +# endif + +# ifndef OPENSSL_NO_BIO +# include +# endif +# include +# ifndef OPENSSL_NO_DEPRECATED +# include +# endif + +# ifndef OPENSSL_DH_MAX_MODULUS_BITS +# define OPENSSL_DH_MAX_MODULUS_BITS 10000 +# endif + +# define DH_FLAG_CACHE_MONT_P 0x01 + +/* + * new with 0.9.7h; the built-in DH + * implementation now uses constant time + * modular exponentiation for secret exponents + * by default. This flag causes the + * faster variable sliding window method to + * be used for all exponents. + */ +# define DH_FLAG_NO_EXP_CONSTTIME 0x02 + +/* + * If this flag is set the DH method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its reposibility to ensure the + * result is compliant. + */ + +# define DH_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define DH_FLAG_NON_FIPS_ALLOW 0x0400 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Already defined in ossl_typ.h */ +/* typedef struct dh_st DH; */ +/* typedef struct dh_method DH_METHOD; */ + +struct dh_method { + const char *name; + /* Methods here */ + int (*generate_key) (DH *dh); + int (*compute_key) (unsigned char *key, const BIGNUM *pub_key, DH *dh); + /* Can be null */ + int (*bn_mod_exp) (const DH *dh, BIGNUM *r, const BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); + int (*init) (DH *dh); + int (*finish) (DH *dh); + int flags; + char *app_data; + /* If this is non-NULL, it will be used to generate parameters */ + int (*generate_params) (DH *dh, int prime_len, int generator, + BN_GENCB *cb); +}; + +struct dh_st { + /* + * This first argument is used to pick up errors when a DH is passed + * instead of a EVP_PKEY + */ + int pad; + int version; + BIGNUM *p; + BIGNUM *g; + long length; /* optional */ + BIGNUM *pub_key; /* g^x % p */ + BIGNUM *priv_key; /* x */ + int flags; + BN_MONT_CTX *method_mont_p; + /* Place holders if we want to do X9.42 DH */ + BIGNUM *q; + BIGNUM *j; + unsigned char *seed; + int seedlen; + BIGNUM *counter; + int references; + CRYPTO_EX_DATA ex_data; + const DH_METHOD *meth; + ENGINE *engine; +}; + +# define DH_GENERATOR_2 2 +/* #define DH_GENERATOR_3 3 */ +# define DH_GENERATOR_5 5 + +/* DH_check error codes */ +# define DH_CHECK_P_NOT_PRIME 0x01 +# define DH_CHECK_P_NOT_SAFE_PRIME 0x02 +# define DH_UNABLE_TO_CHECK_GENERATOR 0x04 +# define DH_NOT_SUITABLE_GENERATOR 0x08 +# define DH_CHECK_Q_NOT_PRIME 0x10 +# define DH_CHECK_INVALID_Q_VALUE 0x20 +# define DH_CHECK_INVALID_J_VALUE 0x40 + +/* DH_check_pub_key error codes */ +# define DH_CHECK_PUBKEY_TOO_SMALL 0x01 +# define DH_CHECK_PUBKEY_TOO_LARGE 0x02 +# define DH_CHECK_PUBKEY_INVALID 0x04 + +/* + * primes p where (p-1)/2 is prime too are called "safe"; we define this for + * backward compatibility: + */ +# define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME + +# define d2i_DHparams_fp(fp,x) \ + (DH *)ASN1_d2i_fp((char *(*)())DH_new, \ + (char *(*)())d2i_DHparams, \ + (fp), \ + (unsigned char **)(x)) +# define i2d_DHparams_fp(fp,x) \ + ASN1_i2d_fp(i2d_DHparams,(fp), (unsigned char *)(x)) +# define d2i_DHparams_bio(bp,x) \ + ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, x) +# define i2d_DHparams_bio(bp,x) \ + ASN1_i2d_bio_of_const(DH,i2d_DHparams,bp,x) + +# define d2i_DHxparams_fp(fp,x) \ + (DH *)ASN1_d2i_fp((char *(*)())DH_new, \ + (char *(*)())d2i_DHxparams, \ + (fp), \ + (unsigned char **)(x)) +# define i2d_DHxparams_fp(fp,x) \ + ASN1_i2d_fp(i2d_DHxparams,(fp), (unsigned char *)(x)) +# define d2i_DHxparams_bio(bp,x) \ + ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x) +# define i2d_DHxparams_bio(bp,x) \ + ASN1_i2d_bio_of_const(DH, i2d_DHxparams, bp, x) + +DH *DHparams_dup(DH *); + +const DH_METHOD *DH_OpenSSL(void); + +void DH_set_default_method(const DH_METHOD *meth); +const DH_METHOD *DH_get_default_method(void); +int DH_set_method(DH *dh, const DH_METHOD *meth); +DH *DH_new_method(ENGINE *engine); + +DH *DH_new(void); +void DH_free(DH *dh); +int DH_up_ref(DH *dh); +int DH_size(const DH *dh); +int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int DH_set_ex_data(DH *d, int idx, void *arg); +void *DH_get_ex_data(DH *d, int idx); + +/* Deprecated version */ +# ifndef OPENSSL_NO_DEPRECATED +DH *DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, void *), void *cb_arg); +# endif /* !defined(OPENSSL_NO_DEPRECATED) */ + +/* New version */ +int DH_generate_parameters_ex(DH *dh, int prime_len, int generator, + BN_GENCB *cb); + +int DH_check(const DH *dh, int *codes); +int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *codes); +int DH_generate_key(DH *dh); +int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh); +int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh); +DH *d2i_DHparams(DH **a, const unsigned char **pp, long length); +int i2d_DHparams(const DH *a, unsigned char **pp); +DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length); +int i2d_DHxparams(const DH *a, unsigned char **pp); +# ifndef OPENSSL_NO_FP_API +int DHparams_print_fp(FILE *fp, const DH *x); +# endif +# ifndef OPENSSL_NO_BIO +int DHparams_print(BIO *bp, const DH *x); +# else +int DHparams_print(char *bp, const DH *x); +# endif + +/* RFC 5114 parameters */ +DH *DH_get_1024_160(void); +DH *DH_get_2048_224(void); +DH *DH_get_2048_256(void); + +# ifndef OPENSSL_NO_CMS +/* RFC2631 KDF */ +int DH_KDF_X9_42(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + ASN1_OBJECT *key_oid, + const unsigned char *ukm, size_t ukmlen, const EVP_MD *md); +# endif + +# define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, len, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, len, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL) + +# define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL) + +# define EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_RFC5114, gen, NULL) + +# define EVP_PKEY_CTX_set_dhx_rfc5114(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_RFC5114, gen, NULL) + +# define EVP_PKEY_CTX_set_dh_kdf_type(ctx, kdf) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL) + +# define EVP_PKEY_CTX_get_dh_kdf_type(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL) + +# define EVP_PKEY_CTX_set0_dh_kdf_oid(ctx, oid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)oid) + +# define EVP_PKEY_CTX_get0_dh_kdf_oid(ctx, poid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)poid) + +# define EVP_PKEY_CTX_set_dh_kdf_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)md) + +# define EVP_PKEY_CTX_get_dh_kdf_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)pmd) + +# define EVP_PKEY_CTX_set_dh_kdf_outlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_OUTLEN, len, NULL) + +# define EVP_PKEY_CTX_get_dh_kdf_outlen(ctx, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN, 0, (void *)plen) + +# define EVP_PKEY_CTX_set0_dh_kdf_ukm(ctx, p, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_DH_KDF_UKM, plen, (void *)p) + +# define EVP_PKEY_CTX_get0_dh_kdf_ukm(ctx, p) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_DH_KDF_UKM, 0, (void *)p) + +# define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_DH_RFC5114 (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_DH_PARAMGEN_TYPE (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_DH_KDF_TYPE (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_DH_KDF_MD (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 10) +# define EVP_PKEY_CTRL_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET_DH_KDF_UKM (EVP_PKEY_ALG_CTRL + 12) +# define EVP_PKEY_CTRL_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 13) +# define EVP_PKEY_CTRL_GET_DH_KDF_OID (EVP_PKEY_ALG_CTRL + 14) + +/* KDF types */ +# define EVP_PKEY_DH_KDF_NONE 1 +# define EVP_PKEY_DH_KDF_X9_42 2 + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_DH_strings(void); + +/* Error codes for the DH functions. */ + +/* Function codes. */ +# define DH_F_COMPUTE_KEY 102 +# define DH_F_DHPARAMS_PRINT_FP 101 +# define DH_F_DH_BUILTIN_GENPARAMS 106 +# define DH_F_DH_CMS_DECRYPT 117 +# define DH_F_DH_CMS_SET_PEERKEY 118 +# define DH_F_DH_CMS_SET_SHARED_INFO 119 +# define DH_F_DH_COMPUTE_KEY 114 +# define DH_F_DH_GENERATE_KEY 115 +# define DH_F_DH_GENERATE_PARAMETERS_EX 116 +# define DH_F_DH_NEW_METHOD 105 +# define DH_F_DH_PARAM_DECODE 107 +# define DH_F_DH_PRIV_DECODE 110 +# define DH_F_DH_PRIV_ENCODE 111 +# define DH_F_DH_PUB_DECODE 108 +# define DH_F_DH_PUB_ENCODE 109 +# define DH_F_DO_DH_PRINT 100 +# define DH_F_GENERATE_KEY 103 +# define DH_F_GENERATE_PARAMETERS 104 +# define DH_F_PKEY_DH_DERIVE 112 +# define DH_F_PKEY_DH_KEYGEN 113 + +/* Reason codes. */ +# define DH_R_BAD_GENERATOR 101 +# define DH_R_BN_DECODE_ERROR 109 +# define DH_R_BN_ERROR 106 +# define DH_R_DECODE_ERROR 104 +# define DH_R_INVALID_PUBKEY 102 +# define DH_R_KDF_PARAMETER_ERROR 112 +# define DH_R_KEYS_NOT_SET 108 +# define DH_R_KEY_SIZE_TOO_SMALL 110 +# define DH_R_MODULUS_TOO_LARGE 103 +# define DH_R_NON_FIPS_METHOD 111 +# define DH_R_NO_PARAMETERS_SET 107 +# define DH_R_NO_PRIVATE_VALUE 100 +# define DH_R_PARAMETER_ENCODING_ERROR 105 +# define DH_R_PEER_KEY_ERROR 113 +# define DH_R_SHARED_INFO_ERROR 114 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/dsa.h b/optee/optee_test/host/openssl/include/openssl/dsa.h new file mode 100644 index 0000000..545358f --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/dsa.h @@ -0,0 +1,332 @@ +/* crypto/dsa/dsa.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* + * The DSS routines are based on patches supplied by + * Steven Schoch . He basically did the + * work and I have just tweaked them a little to fit into my + * stylistic vision for SSLeay :-) */ + +#ifndef HEADER_DSA_H +# define HEADER_DSA_H + +# include + +# ifdef OPENSSL_NO_DSA +# error DSA is disabled. +# endif + +# ifndef OPENSSL_NO_BIO +# include +# endif +# include +# include + +# ifndef OPENSSL_NO_DEPRECATED +# include +# ifndef OPENSSL_NO_DH +# include +# endif +# endif + +# ifndef OPENSSL_DSA_MAX_MODULUS_BITS +# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 +# endif + +# define DSA_FLAG_CACHE_MONT_P 0x01 +/* + * new with 0.9.7h; the built-in DSA implementation now uses constant time + * modular exponentiation for secret exponents by default. This flag causes + * the faster variable sliding window method to be used for all exponents. + */ +# define DSA_FLAG_NO_EXP_CONSTTIME 0x02 + +/* + * If this flag is set the DSA method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its reposibility to ensure the + * result is compliant. + */ + +# define DSA_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define DSA_FLAG_NON_FIPS_ALLOW 0x0400 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Already defined in ossl_typ.h */ +/* typedef struct dsa_st DSA; */ +/* typedef struct dsa_method DSA_METHOD; */ + +typedef struct DSA_SIG_st { + BIGNUM *r; + BIGNUM *s; +} DSA_SIG; + +struct dsa_method { + const char *name; + DSA_SIG *(*dsa_do_sign) (const unsigned char *dgst, int dlen, DSA *dsa); + int (*dsa_sign_setup) (DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); + int (*dsa_do_verify) (const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + int (*dsa_mod_exp) (DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1, + BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont); + /* Can be null */ + int (*bn_mod_exp) (DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + int (*init) (DSA *dsa); + int (*finish) (DSA *dsa); + int flags; + char *app_data; + /* If this is non-NULL, it is used to generate DSA parameters */ + int (*dsa_paramgen) (DSA *dsa, int bits, + const unsigned char *seed, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb); + /* If this is non-NULL, it is used to generate DSA keys */ + int (*dsa_keygen) (DSA *dsa); +}; + +struct dsa_st { + /* + * This first variable is used to pick up errors where a DSA is passed + * instead of of a EVP_PKEY + */ + int pad; + long version; + int write_params; + BIGNUM *p; + BIGNUM *q; /* == 20 */ + BIGNUM *g; + BIGNUM *pub_key; /* y public key */ + BIGNUM *priv_key; /* x private key */ + BIGNUM *kinv; /* Signing pre-calc */ + BIGNUM *r; /* Signing pre-calc */ + int flags; + /* Normally used to cache montgomery values */ + BN_MONT_CTX *method_mont_p; + int references; + CRYPTO_EX_DATA ex_data; + const DSA_METHOD *meth; + /* functional reference if 'meth' is ENGINE-provided */ + ENGINE *engine; +}; + +# define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \ + (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x)) +# define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \ + (unsigned char *)(x)) +# define d2i_DSAparams_bio(bp,x) ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAparams,bp,x) +# define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio_of_const(DSA,i2d_DSAparams,bp,x) + +DSA *DSAparams_dup(DSA *x); +DSA_SIG *DSA_SIG_new(void); +void DSA_SIG_free(DSA_SIG *a); +int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp); +DSA_SIG *d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length); + +DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); +int DSA_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +const DSA_METHOD *DSA_OpenSSL(void); + +void DSA_set_default_method(const DSA_METHOD *); +const DSA_METHOD *DSA_get_default_method(void); +int DSA_set_method(DSA *dsa, const DSA_METHOD *); + +DSA *DSA_new(void); +DSA *DSA_new_method(ENGINE *engine); +void DSA_free(DSA *r); +/* "up" the DSA object's reference count */ +int DSA_up_ref(DSA *r); +int DSA_size(const DSA *); + /* next 4 return -1 on error */ +int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); +int DSA_sign(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, DSA *dsa); +int DSA_verify(int type, const unsigned char *dgst, int dgst_len, + const unsigned char *sigbuf, int siglen, DSA *dsa); +int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int DSA_set_ex_data(DSA *d, int idx, void *arg); +void *DSA_get_ex_data(DSA *d, int idx); + +DSA *d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length); +DSA *d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length); +DSA *d2i_DSAparams(DSA **a, const unsigned char **pp, long length); + +/* Deprecated version */ +# ifndef OPENSSL_NO_DEPRECATED +DSA *DSA_generate_parameters(int bits, + unsigned char *seed, int seed_len, + int *counter_ret, unsigned long *h_ret, void + (*callback) (int, int, void *), void *cb_arg); +# endif /* !defined(OPENSSL_NO_DEPRECATED) */ + +/* New version */ +int DSA_generate_parameters_ex(DSA *dsa, int bits, + const unsigned char *seed, int seed_len, + int *counter_ret, unsigned long *h_ret, + BN_GENCB *cb); + +int DSA_generate_key(DSA *a); +int i2d_DSAPublicKey(const DSA *a, unsigned char **pp); +int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp); +int i2d_DSAparams(const DSA *a, unsigned char **pp); + +# ifndef OPENSSL_NO_BIO +int DSAparams_print(BIO *bp, const DSA *x); +int DSA_print(BIO *bp, const DSA *x, int off); +# endif +# ifndef OPENSSL_NO_FP_API +int DSAparams_print_fp(FILE *fp, const DSA *x); +int DSA_print_fp(FILE *bp, const DSA *x, int off); +# endif + +# define DSS_prime_checks 50 +/* + * Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of + * Rabin-Miller + */ +# define DSA_is_prime(n, callback, cb_arg) \ + BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg) + +# ifndef OPENSSL_NO_DH +/* + * Convert DSA structure (key or just parameters) into DH structure (be + * careful to avoid small subgroup attacks when using this!) + */ +DH *DSA_dup_DH(const DSA *r); +# endif + +# define EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL) + +# define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_DSA_PARAMGEN_MD (EVP_PKEY_ALG_CTRL + 3) + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_DSA_strings(void); + +/* Error codes for the DSA functions. */ + +/* Function codes. */ +# define DSA_F_D2I_DSA_SIG 110 +# define DSA_F_DO_DSA_PRINT 104 +# define DSA_F_DSAPARAMS_PRINT 100 +# define DSA_F_DSAPARAMS_PRINT_FP 101 +# define DSA_F_DSA_BUILTIN_PARAMGEN2 126 +# define DSA_F_DSA_DO_SIGN 112 +# define DSA_F_DSA_DO_VERIFY 113 +# define DSA_F_DSA_GENERATE_KEY 124 +# define DSA_F_DSA_GENERATE_PARAMETERS_EX 123 +# define DSA_F_DSA_NEW_METHOD 103 +# define DSA_F_DSA_PARAM_DECODE 119 +# define DSA_F_DSA_PRINT_FP 105 +# define DSA_F_DSA_PRIV_DECODE 115 +# define DSA_F_DSA_PRIV_ENCODE 116 +# define DSA_F_DSA_PUB_DECODE 117 +# define DSA_F_DSA_PUB_ENCODE 118 +# define DSA_F_DSA_SIGN 106 +# define DSA_F_DSA_SIGN_SETUP 107 +# define DSA_F_DSA_SIG_NEW 109 +# define DSA_F_DSA_SIG_PRINT 125 +# define DSA_F_DSA_VERIFY 108 +# define DSA_F_I2D_DSA_SIG 111 +# define DSA_F_OLD_DSA_PRIV_DECODE 122 +# define DSA_F_PKEY_DSA_CTRL 120 +# define DSA_F_PKEY_DSA_KEYGEN 121 +# define DSA_F_SIG_CB 114 + +/* Reason codes. */ +# define DSA_R_BAD_Q_VALUE 102 +# define DSA_R_BN_DECODE_ERROR 108 +# define DSA_R_BN_ERROR 109 +# define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 100 +# define DSA_R_DECODE_ERROR 104 +# define DSA_R_INVALID_DIGEST_TYPE 106 +# define DSA_R_INVALID_PARAMETERS 112 +# define DSA_R_MISSING_PARAMETERS 101 +# define DSA_R_MODULUS_TOO_LARGE 103 +# define DSA_R_NEED_NEW_SETUP_VALUES 110 +# define DSA_R_NON_FIPS_DSA_METHOD 111 +# define DSA_R_NO_PARAMETERS_SET 107 +# define DSA_R_PARAMETER_ENCODING_ERROR 105 +# define DSA_R_Q_NOT_PRIME 113 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/dso.h b/optee/optee_test/host/openssl/include/openssl/dso.h new file mode 100644 index 0000000..c9013f5 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/dso.h @@ -0,0 +1,451 @@ +/* dso.h */ +/* + * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project + * 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_DSO_H +# define HEADER_DSO_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* These values are used as commands to DSO_ctrl() */ +# define DSO_CTRL_GET_FLAGS 1 +# define DSO_CTRL_SET_FLAGS 2 +# define DSO_CTRL_OR_FLAGS 3 + +/* + * By default, DSO_load() will translate the provided filename into a form + * typical for the platform (more specifically the DSO_METHOD) using the + * dso_name_converter function of the method. Eg. win32 will transform "blah" + * into "blah.dll", and dlfcn will transform it into "libblah.so". The + * behaviour can be overriden by setting the name_converter callback in the + * DSO object (using DSO_set_name_converter()). This callback could even + * utilise the DSO_METHOD's converter too if it only wants to override + * behaviour for one or two possible DSO methods. However, the following flag + * can be set in a DSO to prevent *any* native name-translation at all - eg. + * if the caller has prompted the user for a path to a driver library so the + * filename should be interpreted as-is. + */ +# define DSO_FLAG_NO_NAME_TRANSLATION 0x01 +/* + * An extra flag to give if only the extension should be added as + * translation. This is obviously only of importance on Unix and other + * operating systems where the translation also may prefix the name with + * something, like 'lib', and ignored everywhere else. This flag is also + * ignored if DSO_FLAG_NO_NAME_TRANSLATION is used at the same time. + */ +# define DSO_FLAG_NAME_TRANSLATION_EXT_ONLY 0x02 + +/* + * The following flag controls the translation of symbol names to upper case. + * This is currently only being implemented for OpenVMS. + */ +# define DSO_FLAG_UPCASE_SYMBOL 0x10 + +/* + * This flag loads the library with public symbols. Meaning: The exported + * symbols of this library are public to all libraries loaded after this + * library. At the moment only implemented in unix. + */ +# define DSO_FLAG_GLOBAL_SYMBOLS 0x20 + +typedef void (*DSO_FUNC_TYPE) (void); + +typedef struct dso_st DSO; + +/* + * The function prototype used for method functions (or caller-provided + * callbacks) that transform filenames. They are passed a DSO structure + * pointer (or NULL if they are to be used independantly of a DSO object) and + * a filename to transform. They should either return NULL (if there is an + * error condition) or a newly allocated string containing the transformed + * form that the caller will need to free with OPENSSL_free() when done. + */ +typedef char *(*DSO_NAME_CONVERTER_FUNC)(DSO *, const char *); +/* + * The function prototype used for method functions (or caller-provided + * callbacks) that merge two file specifications. They are passed a DSO + * structure pointer (or NULL if they are to be used independantly of a DSO + * object) and two file specifications to merge. They should either return + * NULL (if there is an error condition) or a newly allocated string + * containing the result of merging that the caller will need to free with + * OPENSSL_free() when done. Here, merging means that bits and pieces are + * taken from each of the file specifications and added together in whatever + * fashion that is sensible for the DSO method in question. The only rule + * that really applies is that if the two specification contain pieces of the + * same type, the copy from the first string takes priority. One could see + * it as the first specification is the one given by the user and the second + * being a bunch of defaults to add on if they're missing in the first. + */ +typedef char *(*DSO_MERGER_FUNC)(DSO *, const char *, const char *); + +typedef struct dso_meth_st { + const char *name; + /* + * Loads a shared library, NB: new DSO_METHODs must ensure that a + * successful load populates the loaded_filename field, and likewise a + * successful unload OPENSSL_frees and NULLs it out. + */ + int (*dso_load) (DSO *dso); + /* Unloads a shared library */ + int (*dso_unload) (DSO *dso); + /* Binds a variable */ + void *(*dso_bind_var) (DSO *dso, const char *symname); + /* + * Binds a function - assumes a return type of DSO_FUNC_TYPE. This should + * be cast to the real function prototype by the caller. Platforms that + * don't have compatible representations for different prototypes (this + * is possible within ANSI C) are highly unlikely to have shared + * libraries at all, let alone a DSO_METHOD implemented for them. + */ + DSO_FUNC_TYPE (*dso_bind_func) (DSO *dso, const char *symname); +/* I don't think this would actually be used in any circumstances. */ +# if 0 + /* Unbinds a variable */ + int (*dso_unbind_var) (DSO *dso, char *symname, void *symptr); + /* Unbinds a function */ + int (*dso_unbind_func) (DSO *dso, char *symname, DSO_FUNC_TYPE symptr); +# endif + /* + * The generic (yuck) "ctrl()" function. NB: Negative return values + * (rather than zero) indicate errors. + */ + long (*dso_ctrl) (DSO *dso, int cmd, long larg, void *parg); + /* + * The default DSO_METHOD-specific function for converting filenames to a + * canonical native form. + */ + DSO_NAME_CONVERTER_FUNC dso_name_converter; + /* + * The default DSO_METHOD-specific function for converting filenames to a + * canonical native form. + */ + DSO_MERGER_FUNC dso_merger; + /* [De]Initialisation handlers. */ + int (*init) (DSO *dso); + int (*finish) (DSO *dso); + /* Return pathname of the module containing location */ + int (*pathbyaddr) (void *addr, char *path, int sz); + /* Perform global symbol lookup, i.e. among *all* modules */ + void *(*globallookup) (const char *symname); +} DSO_METHOD; + +/**********************************************************************/ +/* The low-level handle type used to refer to a loaded shared library */ + +struct dso_st { + DSO_METHOD *meth; + /* + * Standard dlopen uses a (void *). Win32 uses a HANDLE. VMS doesn't use + * anything but will need to cache the filename for use in the dso_bind + * handler. All in all, let each method control its own destiny. + * "Handles" and such go in a STACK. + */ + STACK_OF(void) *meth_data; + int references; + int flags; + /* + * For use by applications etc ... use this for your bits'n'pieces, don't + * touch meth_data! + */ + CRYPTO_EX_DATA ex_data; + /* + * If this callback function pointer is set to non-NULL, then it will be + * used in DSO_load() in place of meth->dso_name_converter. NB: This + * should normally set using DSO_set_name_converter(). + */ + DSO_NAME_CONVERTER_FUNC name_converter; + /* + * If this callback function pointer is set to non-NULL, then it will be + * used in DSO_load() in place of meth->dso_merger. NB: This should + * normally set using DSO_set_merger(). + */ + DSO_MERGER_FUNC merger; + /* + * This is populated with (a copy of) the platform-independant filename + * used for this DSO. + */ + char *filename; + /* + * This is populated with (a copy of) the translated filename by which + * the DSO was actually loaded. It is NULL iff the DSO is not currently + * loaded. NB: This is here because the filename translation process may + * involve a callback being invoked more than once not only to convert to + * a platform-specific form, but also to try different filenames in the + * process of trying to perform a load. As such, this variable can be + * used to indicate (a) whether this DSO structure corresponds to a + * loaded library or not, and (b) the filename with which it was actually + * loaded. + */ + char *loaded_filename; +}; + +DSO *DSO_new(void); +DSO *DSO_new_method(DSO_METHOD *method); +int DSO_free(DSO *dso); +int DSO_flags(DSO *dso); +int DSO_up_ref(DSO *dso); +long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg); + +/* + * This function sets the DSO's name_converter callback. If it is non-NULL, + * then it will be used instead of the associated DSO_METHOD's function. If + * oldcb is non-NULL then it is set to the function pointer value being + * replaced. Return value is non-zero for success. + */ +int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb, + DSO_NAME_CONVERTER_FUNC *oldcb); +/* + * These functions can be used to get/set the platform-independant filename + * used for a DSO. NB: set will fail if the DSO is already loaded. + */ +const char *DSO_get_filename(DSO *dso); +int DSO_set_filename(DSO *dso, const char *filename); +/* + * This function will invoke the DSO's name_converter callback to translate a + * filename, or if the callback isn't set it will instead use the DSO_METHOD's + * converter. If "filename" is NULL, the "filename" in the DSO itself will be + * used. If the DSO_FLAG_NO_NAME_TRANSLATION flag is set, then the filename is + * simply duplicated. NB: This function is usually called from within a + * DSO_METHOD during the processing of a DSO_load() call, and is exposed so + * that caller-created DSO_METHODs can do the same thing. A non-NULL return + * value will need to be OPENSSL_free()'d. + */ +char *DSO_convert_filename(DSO *dso, const char *filename); +/* + * This function will invoke the DSO's merger callback to merge two file + * specifications, or if the callback isn't set it will instead use the + * DSO_METHOD's merger. A non-NULL return value will need to be + * OPENSSL_free()'d. + */ +char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2); +/* + * If the DSO is currently loaded, this returns the filename that it was + * loaded under, otherwise it returns NULL. So it is also useful as a test as + * to whether the DSO is currently loaded. NB: This will not necessarily + * return the same value as DSO_convert_filename(dso, dso->filename), because + * the DSO_METHOD's load function may have tried a variety of filenames (with + * and/or without the aid of the converters) before settling on the one it + * actually loaded. + */ +const char *DSO_get_loaded_filename(DSO *dso); + +void DSO_set_default_method(DSO_METHOD *meth); +DSO_METHOD *DSO_get_default_method(void); +DSO_METHOD *DSO_get_method(DSO *dso); +DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth); + +/* + * The all-singing all-dancing load function, you normally pass NULL for the + * first and third parameters. Use DSO_up and DSO_free for subsequent + * reference count handling. Any flags passed in will be set in the + * constructed DSO after its init() function but before the load operation. + * If 'dso' is non-NULL, 'flags' is ignored. + */ +DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags); + +/* This function binds to a variable inside a shared library. */ +void *DSO_bind_var(DSO *dso, const char *symname); + +/* This function binds to a function inside a shared library. */ +DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname); + +/* + * This method is the default, but will beg, borrow, or steal whatever method + * should be the default on any particular platform (including + * DSO_METH_null() if necessary). + */ +DSO_METHOD *DSO_METHOD_openssl(void); + +/* + * This method is defined for all platforms - if a platform has no DSO + * support then this will be the only method! + */ +DSO_METHOD *DSO_METHOD_null(void); + +/* + * If DSO_DLFCN is defined, the standard dlfcn.h-style functions (dlopen, + * dlclose, dlsym, etc) will be used and incorporated into this method. If + * not, this method will return NULL. + */ +DSO_METHOD *DSO_METHOD_dlfcn(void); + +/* + * If DSO_DL is defined, the standard dl.h-style functions (shl_load, + * shl_unload, shl_findsym, etc) will be used and incorporated into this + * method. If not, this method will return NULL. + */ +DSO_METHOD *DSO_METHOD_dl(void); + +/* If WIN32 is defined, use DLLs. If not, return NULL. */ +DSO_METHOD *DSO_METHOD_win32(void); + +/* If VMS is defined, use shared images. If not, return NULL. */ +DSO_METHOD *DSO_METHOD_vms(void); + +/* + * This function writes null-terminated pathname of DSO module containing + * 'addr' into 'sz' large caller-provided 'path' and returns the number of + * characters [including trailing zero] written to it. If 'sz' is 0 or + * negative, 'path' is ignored and required amount of charachers [including + * trailing zero] to accomodate pathname is returned. If 'addr' is NULL, then + * pathname of cryptolib itself is returned. Negative or zero return value + * denotes error. + */ +int DSO_pathbyaddr(void *addr, char *path, int sz); + +/* + * This function should be used with caution! It looks up symbols in *all* + * loaded modules and if module gets unloaded by somebody else attempt to + * dereference the pointer is doomed to have fatal consequences. Primary + * usage for this function is to probe *core* system functionality, e.g. + * check if getnameinfo(3) is available at run-time without bothering about + * OS-specific details such as libc.so.versioning or where does it actually + * reside: in libc itself or libsocket. + */ +void *DSO_global_lookup(const char *name); + +/* If BeOS is defined, use shared images. If not, return NULL. */ +DSO_METHOD *DSO_METHOD_beos(void); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_DSO_strings(void); + +/* Error codes for the DSO functions. */ + +/* Function codes. */ +# define DSO_F_BEOS_BIND_FUNC 144 +# define DSO_F_BEOS_BIND_VAR 145 +# define DSO_F_BEOS_LOAD 146 +# define DSO_F_BEOS_NAME_CONVERTER 147 +# define DSO_F_BEOS_UNLOAD 148 +# define DSO_F_DLFCN_BIND_FUNC 100 +# define DSO_F_DLFCN_BIND_VAR 101 +# define DSO_F_DLFCN_LOAD 102 +# define DSO_F_DLFCN_MERGER 130 +# define DSO_F_DLFCN_NAME_CONVERTER 123 +# define DSO_F_DLFCN_UNLOAD 103 +# define DSO_F_DL_BIND_FUNC 104 +# define DSO_F_DL_BIND_VAR 105 +# define DSO_F_DL_LOAD 106 +# define DSO_F_DL_MERGER 131 +# define DSO_F_DL_NAME_CONVERTER 124 +# define DSO_F_DL_UNLOAD 107 +# define DSO_F_DSO_BIND_FUNC 108 +# define DSO_F_DSO_BIND_VAR 109 +# define DSO_F_DSO_CONVERT_FILENAME 126 +# define DSO_F_DSO_CTRL 110 +# define DSO_F_DSO_FREE 111 +# define DSO_F_DSO_GET_FILENAME 127 +# define DSO_F_DSO_GET_LOADED_FILENAME 128 +# define DSO_F_DSO_GLOBAL_LOOKUP 139 +# define DSO_F_DSO_LOAD 112 +# define DSO_F_DSO_MERGE 132 +# define DSO_F_DSO_NEW_METHOD 113 +# define DSO_F_DSO_PATHBYADDR 140 +# define DSO_F_DSO_SET_FILENAME 129 +# define DSO_F_DSO_SET_NAME_CONVERTER 122 +# define DSO_F_DSO_UP_REF 114 +# define DSO_F_GLOBAL_LOOKUP_FUNC 138 +# define DSO_F_PATHBYADDR 137 +# define DSO_F_VMS_BIND_SYM 115 +# define DSO_F_VMS_LOAD 116 +# define DSO_F_VMS_MERGER 133 +# define DSO_F_VMS_UNLOAD 117 +# define DSO_F_WIN32_BIND_FUNC 118 +# define DSO_F_WIN32_BIND_VAR 119 +# define DSO_F_WIN32_GLOBALLOOKUP 142 +# define DSO_F_WIN32_GLOBALLOOKUP_FUNC 143 +# define DSO_F_WIN32_JOINER 135 +# define DSO_F_WIN32_LOAD 120 +# define DSO_F_WIN32_MERGER 134 +# define DSO_F_WIN32_NAME_CONVERTER 125 +# define DSO_F_WIN32_PATHBYADDR 141 +# define DSO_F_WIN32_SPLITTER 136 +# define DSO_F_WIN32_UNLOAD 121 + +/* Reason codes. */ +# define DSO_R_CTRL_FAILED 100 +# define DSO_R_DSO_ALREADY_LOADED 110 +# define DSO_R_EMPTY_FILE_STRUCTURE 113 +# define DSO_R_FAILURE 114 +# define DSO_R_FILENAME_TOO_BIG 101 +# define DSO_R_FINISH_FAILED 102 +# define DSO_R_INCORRECT_FILE_SYNTAX 115 +# define DSO_R_LOAD_FAILED 103 +# define DSO_R_NAME_TRANSLATION_FAILED 109 +# define DSO_R_NO_FILENAME 111 +# define DSO_R_NO_FILE_SPECIFICATION 116 +# define DSO_R_NULL_HANDLE 104 +# define DSO_R_SET_FILENAME_FAILED 112 +# define DSO_R_STACK_ERROR 105 +# define DSO_R_SYM_FAILURE 106 +# define DSO_R_UNLOAD_FAILED 107 +# define DSO_R_UNSUPPORTED 108 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/dtls1.h b/optee/optee_test/host/openssl/include/openssl/dtls1.h new file mode 100644 index 0000000..30bbcf2 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/dtls1.h @@ -0,0 +1,272 @@ +/* ssl/dtls1.h */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_DTLS1_H +# define HEADER_DTLS1_H + +# include +# include +# ifdef OPENSSL_SYS_VMS +# include +# include +# endif +# ifdef OPENSSL_SYS_WIN32 +/* Needed for struct timeval */ +# include +# elif defined(OPENSSL_SYS_NETWARE) && !defined(_WINSOCK2API_) +# include +# else +# if defined(OPENSSL_SYS_VXWORKS) +# include +# else +# include +# endif +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# define DTLS1_VERSION 0xFEFF +# define DTLS1_2_VERSION 0xFEFD +# define DTLS_MAX_VERSION DTLS1_2_VERSION +# define DTLS1_VERSION_MAJOR 0xFE + +# define DTLS1_BAD_VER 0x0100 + +/* Special value for method supporting multiple versions */ +# define DTLS_ANY_VERSION 0x1FFFF + +# if 0 +/* this alert description is not specified anywhere... */ +# define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110 +# endif + +/* lengths of messages */ +# define DTLS1_COOKIE_LENGTH 256 + +# define DTLS1_RT_HEADER_LENGTH 13 + +# define DTLS1_HM_HEADER_LENGTH 12 + +# define DTLS1_HM_BAD_FRAGMENT -2 +# define DTLS1_HM_FRAGMENT_RETRY -3 + +# define DTLS1_CCS_HEADER_LENGTH 1 + +# ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE +# define DTLS1_AL_HEADER_LENGTH 7 +# else +# define DTLS1_AL_HEADER_LENGTH 2 +# endif + +# ifndef OPENSSL_NO_SSL_INTERN + +# ifndef OPENSSL_NO_SCTP +# define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP" +# endif + +/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */ +# define DTLS1_MAX_MTU_OVERHEAD 48 + +typedef struct dtls1_bitmap_st { + unsigned long map; /* track 32 packets on 32-bit systems and 64 + * - on 64-bit systems */ + unsigned char max_seq_num[8]; /* max record number seen so far, 64-bit + * value in big-endian encoding */ +} DTLS1_BITMAP; + +struct dtls1_retransmit_state { + EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ + EVP_MD_CTX *write_hash; /* used for mac generation */ +# ifndef OPENSSL_NO_COMP + COMP_CTX *compress; /* compression */ +# else + char *compress; +# endif + SSL_SESSION *session; + unsigned short epoch; +}; + +struct hm_header_st { + unsigned char type; + unsigned long msg_len; + unsigned short seq; + unsigned long frag_off; + unsigned long frag_len; + unsigned int is_ccs; + struct dtls1_retransmit_state saved_retransmit_state; +}; + +struct ccs_header_st { + unsigned char type; + unsigned short seq; +}; + +struct dtls1_timeout_st { + /* Number of read timeouts so far */ + unsigned int read_timeouts; + /* Number of write timeouts so far */ + unsigned int write_timeouts; + /* Number of alerts received so far */ + unsigned int num_alerts; +}; + +typedef struct record_pqueue_st { + unsigned short epoch; + pqueue q; +} record_pqueue; + +typedef struct hm_fragment_st { + struct hm_header_st msg_header; + unsigned char *fragment; + unsigned char *reassembly; +} hm_fragment; + +typedef struct dtls1_state_st { + unsigned int send_cookie; + unsigned char cookie[DTLS1_COOKIE_LENGTH]; + unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH]; + unsigned int cookie_len; + /* + * The current data and handshake epoch. This is initially + * undefined, and starts at zero once the initial handshake is + * completed + */ + unsigned short r_epoch; + unsigned short w_epoch; + /* records being received in the current epoch */ + DTLS1_BITMAP bitmap; + /* renegotiation starts a new set of sequence numbers */ + DTLS1_BITMAP next_bitmap; + /* handshake message numbers */ + unsigned short handshake_write_seq; + unsigned short next_handshake_write_seq; + unsigned short handshake_read_seq; + /* save last sequence number for retransmissions */ + unsigned char last_write_sequence[8]; + /* Received handshake records (processed and unprocessed) */ + record_pqueue unprocessed_rcds; + record_pqueue processed_rcds; + /* Buffered handshake messages */ + pqueue buffered_messages; + /* Buffered (sent) handshake records */ + pqueue sent_messages; + /* + * Buffered application records. Only for records between CCS and + * Finished to prevent either protocol violation or unnecessary message + * loss. + */ + record_pqueue buffered_app_data; + /* Is set when listening for new connections with dtls1_listen() */ + unsigned int listen; + unsigned int link_mtu; /* max on-the-wire DTLS packet size */ + unsigned int mtu; /* max DTLS packet size */ + struct hm_header_st w_msg_hdr; + struct hm_header_st r_msg_hdr; + struct dtls1_timeout_st timeout; + /* + * Indicates when the last handshake msg or heartbeat sent will timeout + */ + struct timeval next_timeout; + /* Timeout duration */ + unsigned short timeout_duration; + /* + * storage for Alert/Handshake protocol data received but not yet + * processed by ssl3_read_bytes: + */ + unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH]; + unsigned int alert_fragment_len; + unsigned char handshake_fragment[DTLS1_HM_HEADER_LENGTH]; + unsigned int handshake_fragment_len; + unsigned int retransmitting; + /* + * Set when the handshake is ready to process peer's ChangeCipherSpec message. + * Cleared after the message has been processed. + */ + unsigned int change_cipher_spec_ok; +# ifndef OPENSSL_NO_SCTP + /* used when SSL_ST_XX_FLUSH is entered */ + int next_state; + int shutdown_received; +# endif +} DTLS1_STATE; + +typedef struct dtls1_record_data_st { + unsigned char *packet; + unsigned int packet_length; + SSL3_BUFFER rbuf; + SSL3_RECORD rrec; +# ifndef OPENSSL_NO_SCTP + struct bio_dgram_sctp_rcvinfo recordinfo; +# endif +} DTLS1_RECORD_DATA; + +# endif + +/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */ +# define DTLS1_TMO_READ_COUNT 2 +# define DTLS1_TMO_WRITE_COUNT 2 + +# define DTLS1_TMO_ALERT_COUNT 12 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/e_os2.h b/optee/optee_test/host/openssl/include/openssl/e_os2.h new file mode 100644 index 0000000..7be9989 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/e_os2.h @@ -0,0 +1,328 @@ +/* e_os2.h */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#ifndef HEADER_E_OS2_H +# define HEADER_E_OS2_H + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * Detect operating systems. This probably needs completing. + * The result is that at least one OPENSSL_SYS_os macro should be defined. + * However, if none is defined, Unix is assumed. + **/ + +# define OPENSSL_SYS_UNIX + +/* ---------------------- Macintosh, before MacOS X ----------------------- */ +# if defined(__MWERKS__) && defined(macintosh) || defined(OPENSSL_SYSNAME_MAC) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_MACINTOSH_CLASSIC +# endif + +/* ---------------------- NetWare ----------------------------------------- */ +# if defined(NETWARE) || defined(OPENSSL_SYSNAME_NETWARE) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_NETWARE +# endif + +/* --------------------- Microsoft operating systems ---------------------- */ + +/* + * Note that MSDOS actually denotes 32-bit environments running on top of + * MS-DOS, such as DJGPP one. + */ +# if defined(OPENSSL_SYSNAME_MSDOS) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_MSDOS +# endif + +/* + * For 32 bit environment, there seems to be the CygWin environment and then + * all the others that try to do the same thing Microsoft does... + */ +# if defined(OPENSSL_SYSNAME_UWIN) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WIN32_UWIN +# else +# if defined(__CYGWIN__) || defined(OPENSSL_SYSNAME_CYGWIN) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WIN32_CYGWIN +# else +# if defined(_WIN32) || defined(OPENSSL_SYSNAME_WIN32) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WIN32 +# endif +# if defined(_WIN64) || defined(OPENSSL_SYSNAME_WIN64) +# undef OPENSSL_SYS_UNIX +# if !defined(OPENSSL_SYS_WIN64) +# define OPENSSL_SYS_WIN64 +# endif +# endif +# if defined(OPENSSL_SYSNAME_WINNT) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WINNT +# endif +# if defined(OPENSSL_SYSNAME_WINCE) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WINCE +# endif +# endif +# endif + +/* Anything that tries to look like Microsoft is "Windows" */ +# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN64) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_WINDOWS +# ifndef OPENSSL_SYS_MSDOS +# define OPENSSL_SYS_MSDOS +# endif +# endif + +/* + * DLL settings. This part is a bit tough, because it's up to the + * application implementor how he or she will link the application, so it + * requires some macro to be used. + */ +# ifdef OPENSSL_SYS_WINDOWS +# ifndef OPENSSL_OPT_WINDLL +# if defined(_WINDLL) /* This is used when building OpenSSL to + * indicate that DLL linkage should be used */ +# define OPENSSL_OPT_WINDLL +# endif +# endif +# endif + +/* ------------------------------- OpenVMS -------------------------------- */ +# if defined(__VMS) || defined(VMS) || defined(OPENSSL_SYSNAME_VMS) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_VMS +# if defined(__DECC) +# define OPENSSL_SYS_VMS_DECC +# elif defined(__DECCXX) +# define OPENSSL_SYS_VMS_DECC +# define OPENSSL_SYS_VMS_DECCXX +# else +# define OPENSSL_SYS_VMS_NODECC +# endif +# endif + +/* -------------------------------- OS/2 ---------------------------------- */ +# if defined(__EMX__) || defined(__OS2__) +# undef OPENSSL_SYS_UNIX +# define OPENSSL_SYS_OS2 +# endif + +/* -------------------------------- Unix ---------------------------------- */ +# ifdef OPENSSL_SYS_UNIX +# if defined(linux) || defined(__linux__) || defined(OPENSSL_SYSNAME_LINUX) +# define OPENSSL_SYS_LINUX +# endif +# ifdef OPENSSL_SYSNAME_MPE +# define OPENSSL_SYS_MPE +# endif +# ifdef OPENSSL_SYSNAME_SNI +# define OPENSSL_SYS_SNI +# endif +# ifdef OPENSSL_SYSNAME_ULTRASPARC +# define OPENSSL_SYS_ULTRASPARC +# endif +# ifdef OPENSSL_SYSNAME_NEWS4 +# define OPENSSL_SYS_NEWS4 +# endif +# ifdef OPENSSL_SYSNAME_MACOSX +# define OPENSSL_SYS_MACOSX +# endif +# ifdef OPENSSL_SYSNAME_MACOSX_RHAPSODY +# define OPENSSL_SYS_MACOSX_RHAPSODY +# define OPENSSL_SYS_MACOSX +# endif +# ifdef OPENSSL_SYSNAME_SUNOS +# define OPENSSL_SYS_SUNOS +# endif +# if defined(_CRAY) || defined(OPENSSL_SYSNAME_CRAY) +# define OPENSSL_SYS_CRAY +# endif +# if defined(_AIX) || defined(OPENSSL_SYSNAME_AIX) +# define OPENSSL_SYS_AIX +# endif +# endif + +/* -------------------------------- VOS ----------------------------------- */ +# if defined(__VOS__) || defined(OPENSSL_SYSNAME_VOS) +# define OPENSSL_SYS_VOS +# ifdef __HPPA__ +# define OPENSSL_SYS_VOS_HPPA +# endif +# ifdef __IA32__ +# define OPENSSL_SYS_VOS_IA32 +# endif +# endif + +/* ------------------------------ VxWorks --------------------------------- */ +# ifdef OPENSSL_SYSNAME_VXWORKS +# define OPENSSL_SYS_VXWORKS +# endif + +/* -------------------------------- BeOS ---------------------------------- */ +# if defined(__BEOS__) +# define OPENSSL_SYS_BEOS +# include +# if defined(BONE_VERSION) +# define OPENSSL_SYS_BEOS_BONE +# else +# define OPENSSL_SYS_BEOS_R5 +# endif +# endif + +/** + * That's it for OS-specific stuff + *****************************************************************************/ + +/* Specials for I/O an exit */ +# ifdef OPENSSL_SYS_MSDOS +# define OPENSSL_UNISTD_IO +# define OPENSSL_DECLARE_EXIT extern void exit(int); +# else +# define OPENSSL_UNISTD_IO OPENSSL_UNISTD +# define OPENSSL_DECLARE_EXIT /* declared in unistd.h */ +# endif + +/*- + * Definitions of OPENSSL_GLOBAL and OPENSSL_EXTERN, to define and declare + * certain global symbols that, with some compilers under VMS, have to be + * defined and declared explicitely with globaldef and globalref. + * Definitions of OPENSSL_EXPORT and OPENSSL_IMPORT, to define and declare + * DLL exports and imports for compilers under Win32. These are a little + * more complicated to use. Basically, for any library that exports some + * global variables, the following code must be present in the header file + * that declares them, before OPENSSL_EXTERN is used: + * + * #ifdef SOME_BUILD_FLAG_MACRO + * # undef OPENSSL_EXTERN + * # define OPENSSL_EXTERN OPENSSL_EXPORT + * #endif + * + * The default is to have OPENSSL_EXPORT, OPENSSL_IMPORT and OPENSSL_GLOBAL + * have some generally sensible values, and for OPENSSL_EXTERN to have the + * value OPENSSL_IMPORT. + */ + +# if defined(OPENSSL_SYS_VMS_NODECC) +# define OPENSSL_EXPORT globalref +# define OPENSSL_IMPORT globalref +# define OPENSSL_GLOBAL globaldef +# elif defined(OPENSSL_SYS_WINDOWS) && defined(OPENSSL_OPT_WINDLL) +# define OPENSSL_EXPORT extern __declspec(dllexport) +# define OPENSSL_IMPORT extern __declspec(dllimport) +# define OPENSSL_GLOBAL +# else +# define OPENSSL_EXPORT extern +# define OPENSSL_IMPORT extern +# define OPENSSL_GLOBAL +# endif +# define OPENSSL_EXTERN OPENSSL_IMPORT + +/*- + * Macros to allow global variables to be reached through function calls when + * required (if a shared library version requires it, for example. + * The way it's done allows definitions like this: + * + * // in foobar.c + * OPENSSL_IMPLEMENT_GLOBAL(int,foobar,0) + * // in foobar.h + * OPENSSL_DECLARE_GLOBAL(int,foobar); + * #define foobar OPENSSL_GLOBAL_REF(foobar) + */ +# ifdef OPENSSL_EXPORT_VAR_AS_FUNCTION +# define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) \ + type *_shadow_##name(void) \ + { static type _hide_##name=value; return &_hide_##name; } +# define OPENSSL_DECLARE_GLOBAL(type,name) type *_shadow_##name(void) +# define OPENSSL_GLOBAL_REF(name) (*(_shadow_##name())) +# else +# define OPENSSL_IMPLEMENT_GLOBAL(type,name,value) OPENSSL_GLOBAL type _shadow_##name=value; +# define OPENSSL_DECLARE_GLOBAL(type,name) OPENSSL_EXPORT type _shadow_##name +# define OPENSSL_GLOBAL_REF(name) _shadow_##name +# endif + +# if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) && macintosh==1 && !defined(MAC_OS_GUSI_SOURCE) +# define ossl_ssize_t long +# endif + +# ifdef OPENSSL_SYS_MSDOS +# define ossl_ssize_t long +# endif + +# if defined(NeXT) || defined(OPENSSL_SYS_NEWS4) || defined(OPENSSL_SYS_SUNOS) +# define ssize_t int +# endif + +# if defined(__ultrix) && !defined(ssize_t) +# define ossl_ssize_t int +# endif + +# ifndef ossl_ssize_t +# define ossl_ssize_t ssize_t +# endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ebcdic.h b/optee/optee_test/host/openssl/include/openssl/ebcdic.h new file mode 100644 index 0000000..4cbdfeb --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ebcdic.h @@ -0,0 +1,26 @@ +/* crypto/ebcdic.h */ + +#ifndef HEADER_EBCDIC_H +# define HEADER_EBCDIC_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Avoid name clashes with other applications */ +# define os_toascii _openssl_os_toascii +# define os_toebcdic _openssl_os_toebcdic +# define ebcdic2ascii _openssl_ebcdic2ascii +# define ascii2ebcdic _openssl_ascii2ebcdic + +extern const unsigned char os_toascii[256]; +extern const unsigned char os_toebcdic[256]; +void *ebcdic2ascii(void *dest, const void *srce, size_t count); +void *ascii2ebcdic(void *dest, const void *srce, size_t count); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ec.h b/optee/optee_test/host/openssl/include/openssl/ec.h new file mode 100644 index 0000000..81e6faf --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ec.h @@ -0,0 +1,1282 @@ +/* crypto/ec/ec.h */ +/* + * Originally written by Bodo Moeller for the OpenSSL project. + */ +/** + * \file crypto/ec/ec.h Include file for the OpenSSL EC functions + * \author Originally written by Bodo Moeller for the OpenSSL project + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * + */ + +#ifndef HEADER_EC_H +# define HEADER_EC_H + +# include + +# ifdef OPENSSL_NO_EC +# error EC is disabled. +# endif + +# include +# include +# ifndef OPENSSL_NO_DEPRECATED +# include +# endif + +# ifdef __cplusplus +extern "C" { +# elif defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif +# endif + +# ifndef OPENSSL_ECC_MAX_FIELD_BITS +# define OPENSSL_ECC_MAX_FIELD_BITS 661 +# endif + +/** Enum for the point conversion form as defined in X9.62 (ECDSA) + * for the encoding of a elliptic curve point (x,y) */ +typedef enum { + /** the point is encoded as z||x, where the octet z specifies + * which solution of the quadratic equation y is */ + POINT_CONVERSION_COMPRESSED = 2, + /** the point is encoded as z||x||y, where z is the octet 0x04 */ + POINT_CONVERSION_UNCOMPRESSED = 4, + /** the point is encoded as z||x||y, where the octet z specifies + * which solution of the quadratic equation y is */ + POINT_CONVERSION_HYBRID = 6 +} point_conversion_form_t; + +typedef struct ec_method_st EC_METHOD; + +typedef struct ec_group_st + /*- + EC_METHOD *meth; + -- field definition + -- curve coefficients + -- optional generator with associated information (order, cofactor) + -- optional extra data (precomputed table for fast computation of multiples of generator) + -- ASN1 stuff + */ + EC_GROUP; + +typedef struct ec_point_st EC_POINT; + +/********************************************************************/ +/* EC_METHODs for curves over GF(p) */ +/********************************************************************/ + +/** Returns the basic GFp ec methods which provides the basis for the + * optimized methods. + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_simple_method(void); + +/** Returns GFp methods using montgomery multiplication. + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_mont_method(void); + +/** Returns GFp methods using optimized methods for NIST recommended curves + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nist_method(void); + +# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +/** Returns 64-bit optimized methods for nistp224 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp224_method(void); + +/** Returns 64-bit optimized methods for nistp256 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp256_method(void); + +/** Returns 64-bit optimized methods for nistp521 + * \return EC_METHOD object + */ +const EC_METHOD *EC_GFp_nistp521_method(void); +# endif + +# ifndef OPENSSL_NO_EC2M +/********************************************************************/ +/* EC_METHOD for curves over GF(2^m) */ +/********************************************************************/ + +/** Returns the basic GF2m ec method + * \return EC_METHOD object + */ +const EC_METHOD *EC_GF2m_simple_method(void); + +# endif + +/********************************************************************/ +/* EC_GROUP functions */ +/********************************************************************/ + +/** Creates a new EC_GROUP object + * \param meth EC_METHOD to use + * \return newly created EC_GROUP object or NULL in case of an error. + */ +EC_GROUP *EC_GROUP_new(const EC_METHOD *meth); + +/** Frees a EC_GROUP object + * \param group EC_GROUP object to be freed. + */ +void EC_GROUP_free(EC_GROUP *group); + +/** Clears and frees a EC_GROUP object + * \param group EC_GROUP object to be cleared and freed. + */ +void EC_GROUP_clear_free(EC_GROUP *group); + +/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD. + * \param dst destination EC_GROUP object + * \param src source EC_GROUP object + * \return 1 on success and 0 if an error occurred. + */ +int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src); + +/** Creates a new EC_GROUP object and copies the copies the content + * form src to the newly created EC_KEY object + * \param src source EC_GROUP object + * \return newly created EC_GROUP object or NULL in case of an error. + */ +EC_GROUP *EC_GROUP_dup(const EC_GROUP *src); + +/** Returns the EC_METHOD of the EC_GROUP object. + * \param group EC_GROUP object + * \return EC_METHOD used in this EC_GROUP object. + */ +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group); + +/** Returns the field type of the EC_METHOD. + * \param meth EC_METHOD object + * \return NID of the underlying field type OID. + */ +int EC_METHOD_get_field_type(const EC_METHOD *meth); + +/** Sets the generator and it's order/cofactor of a EC_GROUP object. + * \param group EC_GROUP object + * \param generator EC_POINT object with the generator. + * \param order the order of the group generated by the generator. + * \param cofactor the index of the sub-group generated by the generator + * in the group of all points on the elliptic curve. + * \return 1 on success and 0 if an error occured + */ +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); + +/** Returns the generator of a EC_GROUP object. + * \param group EC_GROUP object + * \return the currently used generator (possibly NULL). + */ +const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group); + +/** Returns the montgomery data for order(Generator) + * \param group EC_GROUP object + * \return the currently used generator (possibly NULL). +*/ +BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group); + +/** Gets the order of a EC_GROUP + * \param group EC_GROUP object + * \param order BIGNUM to which the order is copied + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); + +/** Gets the cofactor of a EC_GROUP + * \param group EC_GROUP object + * \param cofactor BIGNUM to which the cofactor is copied + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, + BN_CTX *ctx); + +/** Sets the name of a EC_GROUP object + * \param group EC_GROUP object + * \param nid NID of the curve name OID + */ +void EC_GROUP_set_curve_name(EC_GROUP *group, int nid); + +/** Returns the curve name of a EC_GROUP object + * \param group EC_GROUP object + * \return NID of the curve name OID or 0 if not set. + */ +int EC_GROUP_get_curve_name(const EC_GROUP *group); + +void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); +int EC_GROUP_get_asn1_flag(const EC_GROUP *group); + +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, + point_conversion_form_t form); +point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *); + +unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x); +size_t EC_GROUP_get_seed_len(const EC_GROUP *); +size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len); + +/** Sets the parameter of a ec over GFp defined by y^2 = x^3 + a*x + b + * \param group EC_GROUP object + * \param p BIGNUM with the prime number + * \param a BIGNUM with parameter a of the equation + * \param b BIGNUM with parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); + +/** Gets the parameter of the ec over GFp defined by y^2 = x^3 + a*x + b + * \param group EC_GROUP object + * \param p BIGNUM for the prime number + * \param a BIGNUM for parameter a of the equation + * \param b BIGNUM for parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx); + +# ifndef OPENSSL_NO_EC2M +/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b + * \param group EC_GROUP object + * \param p BIGNUM with the polynomial defining the underlying field + * \param a BIGNUM with parameter a of the equation + * \param b BIGNUM with parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); + +/** Gets the parameter of the ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b + * \param group EC_GROUP object + * \param p BIGNUM for the polynomial defining the underlying field + * \param a BIGNUM for parameter a of the equation + * \param b BIGNUM for parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx); +# endif +/** Returns the number of bits needed to represent a field element + * \param group EC_GROUP object + * \return number of bits needed to represent a field element + */ +int EC_GROUP_get_degree(const EC_GROUP *group); + +/** Checks whether the parameter in the EC_GROUP define a valid ec group + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 if group is a valid ec group and 0 otherwise + */ +int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx); + +/** Checks whether the discriminant of the elliptic curve is zero or not + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 if the discriminant is not zero and 0 otherwise + */ +int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx); + +/** Compares two EC_GROUP objects + * \param a first EC_GROUP object + * \param b second EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 0 if both groups are equal and 1 otherwise + */ +int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx); + +/* + * EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*() after + * choosing an appropriate EC_METHOD + */ + +/** Creates a new EC_GROUP object with the specified parameters defined + * over GFp (defined by the equation y^2 = x^3 + a*x + b) + * \param p BIGNUM with the prime number + * \param a BIGNUM with the parameter a of the equation + * \param b BIGNUM with the parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return newly created EC_GROUP object with the specified parameters + */ +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +# ifndef OPENSSL_NO_EC2M +/** Creates a new EC_GROUP object with the specified parameters defined + * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b) + * \param p BIGNUM with the polynomial defining the underlying field + * \param a BIGNUM with the parameter a of the equation + * \param b BIGNUM with the parameter b of the equation + * \param ctx BN_CTX object (optional) + * \return newly created EC_GROUP object with the specified parameters + */ +EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +# endif +/** Creates a EC_GROUP object with a curve specified by a NID + * \param nid NID of the OID of the curve name + * \return newly created EC_GROUP object with specified curve or NULL + * if an error occurred + */ +EC_GROUP *EC_GROUP_new_by_curve_name(int nid); + +/********************************************************************/ +/* handling of internal curves */ +/********************************************************************/ + +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; + +/* + * EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number of all + * available curves or zero if a error occurred. In case r ist not zero + * nitems EC_builtin_curve structures are filled with the data of the first + * nitems internal groups + */ +size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems); + +const char *EC_curve_nid2nist(int nid); +int EC_curve_nist2nid(const char *name); + +/********************************************************************/ +/* EC_POINT functions */ +/********************************************************************/ + +/** Creates a new EC_POINT object for the specified EC_GROUP + * \param group EC_GROUP the underlying EC_GROUP object + * \return newly created EC_POINT object or NULL if an error occurred + */ +EC_POINT *EC_POINT_new(const EC_GROUP *group); + +/** Frees a EC_POINT object + * \param point EC_POINT object to be freed + */ +void EC_POINT_free(EC_POINT *point); + +/** Clears and frees a EC_POINT object + * \param point EC_POINT object to be cleared and freed + */ +void EC_POINT_clear_free(EC_POINT *point); + +/** Copies EC_POINT object + * \param dst destination EC_POINT object + * \param src source EC_POINT object + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src); + +/** Creates a new EC_POINT object and copies the content of the supplied + * EC_POINT + * \param src source EC_POINT object + * \param group underlying the EC_GROUP object + * \return newly created EC_POINT object or NULL if an error occurred + */ +EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group); + +/** Returns the EC_METHOD used in EC_POINT object + * \param point EC_POINT object + * \return the EC_METHOD used + */ +const EC_METHOD *EC_POINT_method_of(const EC_POINT *point); + +/** Sets a point to infinity (neutral element) + * \param group underlying EC_GROUP object + * \param point EC_POINT to set to infinity + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point); + +/** Sets the jacobian projective coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param z BIGNUM with the z-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, const BIGNUM *x, + const BIGNUM *y, const BIGNUM *z, + BN_CTX *ctx); + +/** Gets the jacobian projective coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param z BIGNUM for the z-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *p, BIGNUM *x, + BIGNUM *y, BIGNUM *z, + BN_CTX *ctx); + +/** Sets the affine coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); + +/** Gets the affine coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *p, BIGNUM *x, + BIGNUM *y, BN_CTX *ctx); + +/** Sets the x9.62 compressed coordinates of a EC_POINT over GFp + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with x-coordinate + * \param y_bit integer with the y-Bit (either 0 or 1) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, + EC_POINT *p, const BIGNUM *x, + int y_bit, BN_CTX *ctx); +# ifndef OPENSSL_NO_EC2M +/** Sets the affine coordinates of a EC_POINT over GF2m + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with the x-coordinate + * \param y BIGNUM with the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, + BN_CTX *ctx); + +/** Gets the affine coordinates of a EC_POINT over GF2m + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM for the x-coordinate + * \param y BIGNUM for the y-coordinate + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, + const EC_POINT *p, BIGNUM *x, + BIGNUM *y, BN_CTX *ctx); + +/** Sets the x9.62 compressed coordinates of a EC_POINT over GF2m + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param x BIGNUM with x-coordinate + * \param y_bit integer with the y-Bit (either 0 or 1) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, + EC_POINT *p, const BIGNUM *x, + int y_bit, BN_CTX *ctx); +# endif +/** Encodes a EC_POINT object to a octet string + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param form point conversion form + * \param buf memory buffer for the result. If NULL the function returns + * required buffer size. + * \param len length of the memory buffer + * \param ctx BN_CTX object (optional) + * \return the length of the encoded octet string or 0 if an error occurred + */ +size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p, + point_conversion_form_t form, + unsigned char *buf, size_t len, BN_CTX *ctx); + +/** Decodes a EC_POINT from a octet string + * \param group underlying EC_GROUP object + * \param p EC_POINT object + * \param buf memory buffer with the encoded ec point + * \param len length of the encoded ec point + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p, + const unsigned char *buf, size_t len, BN_CTX *ctx); + +/* other interfaces to point2oct/oct2point: */ +BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, BIGNUM *, BN_CTX *); +EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *, + EC_POINT *, BN_CTX *); +char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, BN_CTX *); +EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *, + EC_POINT *, BN_CTX *); + +/********************************************************************/ +/* functions for doing EC_POINT arithmetic */ +/********************************************************************/ + +/** Computes the sum of two EC_POINT + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result (r = a + b) + * \param a EC_POINT object with the first summand + * \param b EC_POINT object with the second summand + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx); + +/** Computes the double of a EC_POINT + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result (r = 2 * a) + * \param a EC_POINT object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx); + +/** Computes the inverse of a EC_POINT + * \param group underlying EC_GROUP object + * \param a EC_POINT object to be inverted (it's used for the result as well) + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx); + +/** Checks whether the point is the neutral element of the group + * \param group the underlying EC_GROUP object + * \param p EC_POINT object + * \return 1 if the point is the neutral element and 0 otherwise + */ +int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p); + +/** Checks whether the point is on the curve + * \param group underlying EC_GROUP object + * \param point EC_POINT object to check + * \param ctx BN_CTX object (optional) + * \return 1 if point if on the curve and 0 otherwise + */ +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx); + +/** Compares two EC_POINTs + * \param group underlying EC_GROUP object + * \param a first EC_POINT object + * \param b second EC_POINT object + * \param ctx BN_CTX object (optional) + * \return 0 if both points are equal and a value != 0 otherwise + */ +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx); + +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx); +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, + EC_POINT *points[], BN_CTX *ctx); + +/** Computes r = generator * n sum_{i=0}^{num-1} p[i] * m[i] + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result + * \param n BIGNUM with the multiplier for the group generator (optional) + * \param num number futher summands + * \param p array of size num of EC_POINT objects + * \param m array of size num of BIGNUM objects + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + size_t num, const EC_POINT *p[], const BIGNUM *m[], + BN_CTX *ctx); + +/** Computes r = generator * n + q * m + * \param group underlying EC_GROUP object + * \param r EC_POINT object for the result + * \param n BIGNUM with the multiplier for the group generator (optional) + * \param q EC_POINT object with the first factor of the second summand + * \param m BIGNUM with the second factor of the second summand + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); + +/** Stores multiples of generator for faster point multiplication + * \param group EC_GROUP object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occured + */ +int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx); + +/** Reports whether a precomputation has been done + * \param group EC_GROUP object + * \return 1 if a pre-computation has been done and 0 otherwise + */ +int EC_GROUP_have_precompute_mult(const EC_GROUP *group); + +/********************************************************************/ +/* ASN1 stuff */ +/********************************************************************/ + +/* + * EC_GROUP_get_basis_type() returns the NID of the basis type used to + * represent the field elements + */ +int EC_GROUP_get_basis_type(const EC_GROUP *); +# ifndef OPENSSL_NO_EC2M +int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k); +int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, + unsigned int *k2, unsigned int *k3); +# endif + +# define OPENSSL_EC_NAMED_CURVE 0x001 + +typedef struct ecpk_parameters_st ECPKPARAMETERS; + +EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len); +int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out); + +# define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x) +# define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x) +# define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \ + (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x)) +# define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \ + (unsigned char *)(x)) + +# ifndef OPENSSL_NO_BIO +int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off); +# endif +# ifndef OPENSSL_NO_FP_API +int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off); +# endif + +/********************************************************************/ +/* EC_KEY functions */ +/********************************************************************/ + +typedef struct ec_key_st EC_KEY; + +/* some values for the encoding_flag */ +# define EC_PKEY_NO_PARAMETERS 0x001 +# define EC_PKEY_NO_PUBKEY 0x002 + +/* some values for the flags field */ +# define EC_FLAG_NON_FIPS_ALLOW 0x1 +# define EC_FLAG_FIPS_CHECKED 0x2 + +/** Creates a new EC_KEY object. + * \return EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_new(void); + +int EC_KEY_get_flags(const EC_KEY *key); + +void EC_KEY_set_flags(EC_KEY *key, int flags); + +void EC_KEY_clear_flags(EC_KEY *key, int flags); + +/** Creates a new EC_KEY object using a named curve as underlying + * EC_GROUP object. + * \param nid NID of the named curve. + * \return EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_new_by_curve_name(int nid); + +/** Frees a EC_KEY object. + * \param key EC_KEY object to be freed. + */ +void EC_KEY_free(EC_KEY *key); + +/** Copies a EC_KEY object. + * \param dst destination EC_KEY object + * \param src src EC_KEY object + * \return dst or NULL if an error occurred. + */ +EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src); + +/** Creates a new EC_KEY object and copies the content from src to it. + * \param src the source EC_KEY object + * \return newly created EC_KEY object or NULL if an error occurred. + */ +EC_KEY *EC_KEY_dup(const EC_KEY *src); + +/** Increases the internal reference count of a EC_KEY object. + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_up_ref(EC_KEY *key); + +/** Returns the EC_GROUP object of a EC_KEY object + * \param key EC_KEY object + * \return the EC_GROUP object (possibly NULL). + */ +const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); + +/** Sets the EC_GROUP of a EC_KEY object. + * \param key EC_KEY object + * \param group EC_GROUP to use in the EC_KEY object (note: the EC_KEY + * object will use an own copy of the EC_GROUP). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group); + +/** Returns the private key of a EC_KEY object. + * \param key EC_KEY object + * \return a BIGNUM with the private key (possibly NULL). + */ +const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key); + +/** Sets the private key of a EC_KEY object. + * \param key EC_KEY object + * \param prv BIGNUM with the private key (note: the EC_KEY object + * will use an own copy of the BIGNUM). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); + +/** Returns the public key of a EC_KEY object. + * \param key the EC_KEY object + * \return a EC_POINT object with the public key (possibly NULL) + */ +const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); + +/** Sets the public key of a EC_KEY object. + * \param key EC_KEY object + * \param pub EC_POINT object with the public key (note: the EC_KEY object + * will use an own copy of the EC_POINT object). + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); + +unsigned EC_KEY_get_enc_flags(const EC_KEY *key); +void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags); +point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); +void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); +/* functions to set/get method specific data */ +void *EC_KEY_get_key_method_data(EC_KEY *key, + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)); +/** Sets the key method data of an EC_KEY object, if none has yet been set. + * \param key EC_KEY object + * \param data opaque data to install. + * \param dup_func a function that duplicates |data|. + * \param free_func a function that frees |data|. + * \param clear_free_func a function that wipes and frees |data|. + * \return the previously set data pointer, or NULL if |data| was inserted. + */ +void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, + void *(*dup_func) (void *), + void (*free_func) (void *), + void (*clear_free_func) (void *)); +/* wrapper functions for the underlying EC_GROUP object */ +void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); + +/** Creates a table of pre-computed multiples of the generator to + * accelerate further EC_KEY operations. + * \param key EC_KEY object + * \param ctx BN_CTX object (optional) + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx); + +/** Creates a new ec private (and optional a new public) key. + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred. + */ +int EC_KEY_generate_key(EC_KEY *key); + +/** Verifies that a private and/or public key is valid. + * \param key the EC_KEY object + * \return 1 on success and 0 otherwise. + */ +int EC_KEY_check_key(const EC_KEY *key); + +/** Sets a public key from affine coordindates performing + * neccessary NIST PKV tests. + * \param key the EC_KEY object + * \param x public key x coordinate + * \param y public key y coordinate + * \return 1 on success and 0 otherwise. + */ +int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, + BIGNUM *y); + +/********************************************************************/ +/* de- and encoding functions for SEC1 ECPrivateKey */ +/********************************************************************/ + +/** Decodes a private key from a memory buffer. + * \param key a pointer to a EC_KEY object which should be used (or NULL) + * \param in pointer to memory with the DER encoded private key + * \param len length of the DER encoded private key + * \return the decoded private key or NULL if an error occurred. + */ +EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes a private key object and stores the result in a buffer. + * \param key the EC_KEY object to encode + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred. + */ +int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out); + +/********************************************************************/ +/* de- and encoding functions for EC parameters */ +/********************************************************************/ + +/** Decodes ec parameter from a memory buffer. + * \param key a pointer to a EC_KEY object which should be used (or NULL) + * \param in pointer to memory with the DER encoded ec parameters + * \param len length of the DER encoded ec parameters + * \return a EC_KEY object with the decoded parameters or NULL if an error + * occurred. + */ +EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes ec parameter and stores the result in a buffer. + * \param key the EC_KEY object with ec paramters to encode + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred. + */ +int i2d_ECParameters(EC_KEY *key, unsigned char **out); + +/********************************************************************/ +/* de- and encoding functions for EC public key */ +/* (octet string, not DER -- hence 'o2i' and 'i2o') */ +/********************************************************************/ + +/** Decodes a ec public key from a octet string. + * \param key a pointer to a EC_KEY object which should be used + * \param in memory buffer with the encoded public key + * \param len length of the encoded public key + * \return EC_KEY object with decoded public key or NULL if an error + * occurred. + */ +EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len); + +/** Encodes a ec public key in an octet string. + * \param key the EC_KEY object with the public key + * \param out the buffer for the result (if NULL the function returns number + * of bytes needed). + * \return 1 on success and 0 if an error occurred + */ +int i2o_ECPublicKey(EC_KEY *key, unsigned char **out); + +# ifndef OPENSSL_NO_BIO +/** Prints out the ec parameters on human readable form. + * \param bp BIO object to which the information is printed + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred + */ +int ECParameters_print(BIO *bp, const EC_KEY *key); + +/** Prints out the contents of a EC_KEY object + * \param bp BIO object to which the information is printed + * \param key EC_KEY object + * \param off line offset + * \return 1 on success and 0 if an error occurred + */ +int EC_KEY_print(BIO *bp, const EC_KEY *key, int off); + +# endif +# ifndef OPENSSL_NO_FP_API +/** Prints out the ec parameters on human readable form. + * \param fp file descriptor to which the information is printed + * \param key EC_KEY object + * \return 1 on success and 0 if an error occurred + */ +int ECParameters_print_fp(FILE *fp, const EC_KEY *key); + +/** Prints out the contents of a EC_KEY object + * \param fp file descriptor to which the information is printed + * \param key EC_KEY object + * \param off line offset + * \return 1 on success and 0 if an error occurred + */ +int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); + +# endif + +# define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x) + +# ifndef __cplusplus +# if defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif +# endif +# endif + +# define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL) + +# define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL) + +# define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL) + +# define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL) + +# define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL) + +# define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL) + +# define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)md) + +# define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)pmd) + +# define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL) + +# define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, (void *)plen) + +# define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)p) + +# define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)p) + +# define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) +# define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) +# define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) +/* KDF types */ +# define EVP_PKEY_ECDH_KDF_NONE 1 +# define EVP_PKEY_ECDH_KDF_X9_62 2 + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_EC_strings(void); + +/* Error codes for the EC functions. */ + +/* Function codes. */ +# define EC_F_BN_TO_FELEM 224 +# define EC_F_COMPUTE_WNAF 143 +# define EC_F_D2I_ECPARAMETERS 144 +# define EC_F_D2I_ECPKPARAMETERS 145 +# define EC_F_D2I_ECPRIVATEKEY 146 +# define EC_F_DO_EC_KEY_PRINT 221 +# define EC_F_ECDH_CMS_DECRYPT 238 +# define EC_F_ECDH_CMS_SET_SHARED_INFO 239 +# define EC_F_ECKEY_PARAM2TYPE 223 +# define EC_F_ECKEY_PARAM_DECODE 212 +# define EC_F_ECKEY_PRIV_DECODE 213 +# define EC_F_ECKEY_PRIV_ENCODE 214 +# define EC_F_ECKEY_PUB_DECODE 215 +# define EC_F_ECKEY_PUB_ENCODE 216 +# define EC_F_ECKEY_TYPE2PARAM 220 +# define EC_F_ECPARAMETERS_PRINT 147 +# define EC_F_ECPARAMETERS_PRINT_FP 148 +# define EC_F_ECPKPARAMETERS_PRINT 149 +# define EC_F_ECPKPARAMETERS_PRINT_FP 150 +# define EC_F_ECP_NISTZ256_GET_AFFINE 240 +# define EC_F_ECP_NISTZ256_MULT_PRECOMPUTE 243 +# define EC_F_ECP_NISTZ256_POINTS_MUL 241 +# define EC_F_ECP_NISTZ256_PRE_COMP_NEW 244 +# define EC_F_ECP_NISTZ256_SET_WORDS 245 +# define EC_F_ECP_NISTZ256_WINDOWED_MUL 242 +# define EC_F_ECP_NIST_MOD_192 203 +# define EC_F_ECP_NIST_MOD_224 204 +# define EC_F_ECP_NIST_MOD_256 205 +# define EC_F_ECP_NIST_MOD_521 206 +# define EC_F_EC_ASN1_GROUP2CURVE 153 +# define EC_F_EC_ASN1_GROUP2FIELDID 154 +# define EC_F_EC_ASN1_GROUP2PARAMETERS 155 +# define EC_F_EC_ASN1_GROUP2PKPARAMETERS 156 +# define EC_F_EC_ASN1_PARAMETERS2GROUP 157 +# define EC_F_EC_ASN1_PKPARAMETERS2GROUP 158 +# define EC_F_EC_EX_DATA_SET_DATA 211 +# define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208 +# define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159 +# define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195 +# define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160 +# define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161 +# define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162 +# define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163 +# define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164 +# define EC_F_EC_GFP_MONT_FIELD_DECODE 133 +# define EC_F_EC_GFP_MONT_FIELD_ENCODE 134 +# define EC_F_EC_GFP_MONT_FIELD_MUL 131 +# define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209 +# define EC_F_EC_GFP_MONT_FIELD_SQR 132 +# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189 +# define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135 +# define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225 +# define EC_F_EC_GFP_NISTP224_POINTS_MUL 228 +# define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226 +# define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230 +# define EC_F_EC_GFP_NISTP256_POINTS_MUL 231 +# define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232 +# define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233 +# define EC_F_EC_GFP_NISTP521_POINTS_MUL 234 +# define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235 +# define EC_F_EC_GFP_NIST_FIELD_MUL 200 +# define EC_F_EC_GFP_NIST_FIELD_SQR 201 +# define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202 +# define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165 +# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166 +# define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100 +# define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101 +# define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102 +# define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 +# define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 +# define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 +# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167 +# define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105 +# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168 +# define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128 +# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169 +# define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129 +# define EC_F_EC_GROUP_CHECK 170 +# define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171 +# define EC_F_EC_GROUP_COPY 106 +# define EC_F_EC_GROUP_GET0_GENERATOR 139 +# define EC_F_EC_GROUP_GET_COFACTOR 140 +# define EC_F_EC_GROUP_GET_CURVE_GF2M 172 +# define EC_F_EC_GROUP_GET_CURVE_GFP 130 +# define EC_F_EC_GROUP_GET_DEGREE 173 +# define EC_F_EC_GROUP_GET_ORDER 141 +# define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193 +# define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194 +# define EC_F_EC_GROUP_NEW 108 +# define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174 +# define EC_F_EC_GROUP_NEW_FROM_DATA 175 +# define EC_F_EC_GROUP_PRECOMPUTE_MULT 142 +# define EC_F_EC_GROUP_SET_CURVE_GF2M 176 +# define EC_F_EC_GROUP_SET_CURVE_GFP 109 +# define EC_F_EC_GROUP_SET_EXTRA_DATA 110 +# define EC_F_EC_GROUP_SET_GENERATOR 111 +# define EC_F_EC_KEY_CHECK_KEY 177 +# define EC_F_EC_KEY_COPY 178 +# define EC_F_EC_KEY_GENERATE_KEY 179 +# define EC_F_EC_KEY_NEW 182 +# define EC_F_EC_KEY_PRINT 180 +# define EC_F_EC_KEY_PRINT_FP 181 +# define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229 +# define EC_F_EC_POINTS_MAKE_AFFINE 136 +# define EC_F_EC_POINT_ADD 112 +# define EC_F_EC_POINT_CMP 113 +# define EC_F_EC_POINT_COPY 114 +# define EC_F_EC_POINT_DBL 115 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183 +# define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116 +# define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117 +# define EC_F_EC_POINT_INVERT 210 +# define EC_F_EC_POINT_IS_AT_INFINITY 118 +# define EC_F_EC_POINT_IS_ON_CURVE 119 +# define EC_F_EC_POINT_MAKE_AFFINE 120 +# define EC_F_EC_POINT_MUL 184 +# define EC_F_EC_POINT_NEW 121 +# define EC_F_EC_POINT_OCT2POINT 122 +# define EC_F_EC_POINT_POINT2OCT 123 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185 +# define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186 +# define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125 +# define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126 +# define EC_F_EC_POINT_SET_TO_INFINITY 127 +# define EC_F_EC_PRE_COMP_DUP 207 +# define EC_F_EC_PRE_COMP_NEW 196 +# define EC_F_EC_WNAF_MUL 187 +# define EC_F_EC_WNAF_PRECOMPUTE_MULT 188 +# define EC_F_I2D_ECPARAMETERS 190 +# define EC_F_I2D_ECPKPARAMETERS 191 +# define EC_F_I2D_ECPRIVATEKEY 192 +# define EC_F_I2O_ECPUBLICKEY 151 +# define EC_F_NISTP224_PRE_COMP_NEW 227 +# define EC_F_NISTP256_PRE_COMP_NEW 236 +# define EC_F_NISTP521_PRE_COMP_NEW 237 +# define EC_F_O2I_ECPUBLICKEY 152 +# define EC_F_OLD_EC_PRIV_DECODE 222 +# define EC_F_PKEY_EC_CTRL 197 +# define EC_F_PKEY_EC_CTRL_STR 198 +# define EC_F_PKEY_EC_DERIVE 217 +# define EC_F_PKEY_EC_KEYGEN 199 +# define EC_F_PKEY_EC_PARAMGEN 219 +# define EC_F_PKEY_EC_SIGN 218 + +/* Reason codes. */ +# define EC_R_ASN1_ERROR 115 +# define EC_R_ASN1_UNKNOWN_FIELD 116 +# define EC_R_BIGNUM_OUT_OF_RANGE 144 +# define EC_R_BUFFER_TOO_SMALL 100 +# define EC_R_COORDINATES_OUT_OF_RANGE 146 +# define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 +# define EC_R_DECODE_ERROR 142 +# define EC_R_DISCRIMINANT_IS_ZERO 118 +# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 +# define EC_R_FIELD_TOO_LARGE 143 +# define EC_R_GF2M_NOT_SUPPORTED 147 +# define EC_R_GROUP2PKPARAMETERS_FAILURE 120 +# define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 +# define EC_R_INCOMPATIBLE_OBJECTS 101 +# define EC_R_INVALID_ARGUMENT 112 +# define EC_R_INVALID_COMPRESSED_POINT 110 +# define EC_R_INVALID_COMPRESSION_BIT 109 +# define EC_R_INVALID_CURVE 141 +# define EC_R_INVALID_DIGEST 151 +# define EC_R_INVALID_DIGEST_TYPE 138 +# define EC_R_INVALID_ENCODING 102 +# define EC_R_INVALID_FIELD 103 +# define EC_R_INVALID_FORM 104 +# define EC_R_INVALID_GROUP_ORDER 122 +# define EC_R_INVALID_PENTANOMIAL_BASIS 132 +# define EC_R_INVALID_PRIVATE_KEY 123 +# define EC_R_INVALID_TRINOMIAL_BASIS 137 +# define EC_R_KDF_PARAMETER_ERROR 148 +# define EC_R_KEYS_NOT_SET 140 +# define EC_R_MISSING_PARAMETERS 124 +# define EC_R_MISSING_PRIVATE_KEY 125 +# define EC_R_NOT_A_NIST_PRIME 135 +# define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136 +# define EC_R_NOT_IMPLEMENTED 126 +# define EC_R_NOT_INITIALIZED 111 +# define EC_R_NO_FIELD_MOD 133 +# define EC_R_NO_PARAMETERS_SET 139 +# define EC_R_PASSED_NULL_PARAMETER 134 +# define EC_R_PEER_KEY_ERROR 149 +# define EC_R_PKPARAMETERS2GROUP_FAILURE 127 +# define EC_R_POINT_AT_INFINITY 106 +# define EC_R_POINT_IS_NOT_ON_CURVE 107 +# define EC_R_SHARED_INFO_ERROR 150 +# define EC_R_SLOT_FULL 108 +# define EC_R_UNDEFINED_GENERATOR 113 +# define EC_R_UNDEFINED_ORDER 128 +# define EC_R_UNKNOWN_GROUP 129 +# define EC_R_UNKNOWN_ORDER 114 +# define EC_R_UNSUPPORTED_FIELD 131 +# define EC_R_WRONG_CURVE_PARAMETERS 145 +# define EC_R_WRONG_ORDER 130 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ecdh.h b/optee/optee_test/host/openssl/include/openssl/ecdh.h new file mode 100644 index 0000000..25348b3 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ecdh.h @@ -0,0 +1,134 @@ +/* crypto/ecdh/ecdh.h */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * The Elliptic Curve Public-Key Crypto Library (ECC Code) included + * herein is developed by SUN MICROSYSTEMS, INC., and is contributed + * to the OpenSSL project. + * + * The ECC Code is licensed pursuant to the OpenSSL open source + * license provided below. + * + * The ECDH software is originally written by Douglas Stebila of + * Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef HEADER_ECDH_H +# define HEADER_ECDH_H + +# include + +# ifdef OPENSSL_NO_ECDH +# error ECDH is disabled. +# endif + +# include +# include +# ifndef OPENSSL_NO_DEPRECATED +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# define EC_FLAG_COFACTOR_ECDH 0x1000 + +const ECDH_METHOD *ECDH_OpenSSL(void); + +void ECDH_set_default_method(const ECDH_METHOD *); +const ECDH_METHOD *ECDH_get_default_method(void); +int ECDH_set_method(EC_KEY *, const ECDH_METHOD *); + +int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, + EC_KEY *ecdh, void *(*KDF) (const void *in, size_t inlen, + void *out, size_t *outlen)); + +int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new + *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +int ECDH_set_ex_data(EC_KEY *d, int idx, void *arg); +void *ECDH_get_ex_data(EC_KEY *d, int idx); + +int ECDH_KDF_X9_62(unsigned char *out, size_t outlen, + const unsigned char *Z, size_t Zlen, + const unsigned char *sinfo, size_t sinfolen, + const EVP_MD *md); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_ECDH_strings(void); + +/* Error codes for the ECDH functions. */ + +/* Function codes. */ +# define ECDH_F_ECDH_CHECK 102 +# define ECDH_F_ECDH_COMPUTE_KEY 100 +# define ECDH_F_ECDH_DATA_NEW_METHOD 101 + +/* Reason codes. */ +# define ECDH_R_KDF_FAILED 102 +# define ECDH_R_NON_FIPS_METHOD 103 +# define ECDH_R_NO_PRIVATE_VALUE 100 +# define ECDH_R_POINT_ARITHMETIC_FAILURE 101 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ecdsa.h b/optee/optee_test/host/openssl/include/openssl/ecdsa.h new file mode 100644 index 0000000..a6f0930 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ecdsa.h @@ -0,0 +1,335 @@ +/* crypto/ecdsa/ecdsa.h */ +/** + * \file crypto/ecdsa/ecdsa.h Include file for the OpenSSL ECDSA functions + * \author Written by Nils Larsch for the OpenSSL project + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef HEADER_ECDSA_H +# define HEADER_ECDSA_H + +# include + +# ifdef OPENSSL_NO_ECDSA +# error ECDSA is disabled. +# endif + +# include +# include +# ifndef OPENSSL_NO_DEPRECATED +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ECDSA_SIG_st { + BIGNUM *r; + BIGNUM *s; +} ECDSA_SIG; + +/** Allocates and initialize a ECDSA_SIG structure + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_SIG_new(void); + +/** frees a ECDSA_SIG structure + * \param sig pointer to the ECDSA_SIG structure + */ +void ECDSA_SIG_free(ECDSA_SIG *sig); + +/** DER encode content of ECDSA_SIG object (note: this function modifies *pp + * (*pp += length of the DER encoded signature)). + * \param sig pointer to the ECDSA_SIG object + * \param pp pointer to a unsigned char pointer for the output or NULL + * \return the length of the DER encoded ECDSA_SIG object or 0 + */ +int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp); + +/** Decodes a DER encoded ECDSA signature (note: this function changes *pp + * (*pp += len)). + * \param sig pointer to ECDSA_SIG pointer (may be NULL) + * \param pp memory buffer with the DER encoded signature + * \param len length of the buffer + * \return pointer to the decoded ECDSA_SIG structure (or NULL) + */ +ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len); + +/** Computes the ECDSA signature of the given hash value using + * the supplied private key and returns the created signature. + * \param dgst pointer to the hash value + * \param dgst_len length of the hash value + * \param eckey EC_KEY object containing a private EC key + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len, + EC_KEY *eckey); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param kinv BIGNUM with a pre-computed inverse k (optional) + * \param rp BIGNUM with a pre-computed rp value (optioanl), + * see ECDSA_sign_setup + * \param eckey EC_KEY object containing a private EC key + * \return pointer to a ECDSA_SIG structure or NULL if an error occurred + */ +ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen, + const BIGNUM *kinv, const BIGNUM *rp, + EC_KEY *eckey); + +/** Verifies that the supplied signature is a valid ECDSA + * signature of the supplied hash value using the supplied public key. + * \param dgst pointer to the hash value + * \param dgst_len length of the hash value + * \param sig ECDSA_SIG structure + * \param eckey EC_KEY object containing a public EC key + * \return 1 if the signature is valid, 0 if the signature is invalid + * and -1 on error + */ +int ECDSA_do_verify(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); + +const ECDSA_METHOD *ECDSA_OpenSSL(void); + +/** Sets the default ECDSA method + * \param meth new default ECDSA_METHOD + */ +void ECDSA_set_default_method(const ECDSA_METHOD *meth); + +/** Returns the default ECDSA method + * \return pointer to ECDSA_METHOD structure containing the default method + */ +const ECDSA_METHOD *ECDSA_get_default_method(void); + +/** Sets method to be used for the ECDSA operations + * \param eckey EC_KEY object + * \param meth new method + * \return 1 on success and 0 otherwise + */ +int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth); + +/** Returns the maximum length of the DER encoded signature + * \param eckey EC_KEY object + * \return numbers of bytes required for the DER encoded signature + */ +int ECDSA_size(const EC_KEY *eckey); + +/** Precompute parts of the signing operation + * \param eckey EC_KEY object containing a private EC key + * \param ctx BN_CTX object (optional) + * \param kinv BIGNUM pointer for the inverse of k + * \param rp BIGNUM pointer for x coordinate of k * generator + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param type this parameter is ignored + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param sig memory for the DER encoded created signature + * \param siglen pointer to the length of the returned signature + * \param eckey EC_KEY object containing a private EC key + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); + +/** Computes ECDSA signature of a given hash value using the supplied + * private key (note: sig must point to ECDSA_size(eckey) bytes of memory). + * \param type this parameter is ignored + * \param dgst pointer to the hash value to sign + * \param dgstlen length of the hash value + * \param sig buffer to hold the DER encoded signature + * \param siglen pointer to the length of the returned signature + * \param kinv BIGNUM with a pre-computed inverse k (optional) + * \param rp BIGNUM with a pre-computed rp value (optioanl), + * see ECDSA_sign_setup + * \param eckey EC_KEY object containing a private EC key + * \return 1 on success and 0 otherwise + */ +int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey); + +/** Verifies that the given signature is valid ECDSA signature + * of the supplied hash value using the specified public key. + * \param type this parameter is ignored + * \param dgst pointer to the hash value + * \param dgstlen length of the hash value + * \param sig pointer to the DER encoded signature + * \param siglen length of the DER encoded signature + * \param eckey EC_KEY object containing a public EC key + * \return 1 if the signature is valid, 0 if the signature is invalid + * and -1 on error + */ +int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + const unsigned char *sig, int siglen, EC_KEY *eckey); + +/* the standard ex_data functions */ +int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new + *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg); +void *ECDSA_get_ex_data(EC_KEY *d, int idx); + +/** Allocates and initialize a ECDSA_METHOD structure + * \param ecdsa_method pointer to ECDSA_METHOD to copy. (May be NULL) + * \return pointer to a ECDSA_METHOD structure or NULL if an error occurred + */ + +ECDSA_METHOD *ECDSA_METHOD_new(const ECDSA_METHOD *ecdsa_method); + +/** frees a ECDSA_METHOD structure + * \param ecdsa_method pointer to the ECDSA_METHOD structure + */ +void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method); + +/** Sets application specific data in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param app application specific data to set + */ + +void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app); + +/** Returns application specific data from a ECDSA_METHOD structure + * \param ecdsa_method pointer to ECDSA_METHOD structure + * \return pointer to application specific data. + */ + +void *ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method); + +/** Set the ECDSA_do_sign function in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param ecdsa_do_sign a funtion of type ECDSA_do_sign + */ + +void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method, + ECDSA_SIG *(*ecdsa_do_sign) (const unsigned char + *dgst, int dgst_len, + const BIGNUM *inv, + const BIGNUM *rp, + EC_KEY *eckey)); + +/** Set the ECDSA_sign_setup function in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param ecdsa_sign_setup a funtion of type ECDSA_sign_setup + */ + +void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method, + int (*ecdsa_sign_setup) (EC_KEY *eckey, + BN_CTX *ctx, + BIGNUM **kinv, + BIGNUM **r)); + +/** Set the ECDSA_do_verify function in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param ecdsa_do_verify a funtion of type ECDSA_do_verify + */ + +void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method, + int (*ecdsa_do_verify) (const unsigned char + *dgst, int dgst_len, + const ECDSA_SIG *sig, + EC_KEY *eckey)); + +void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags); + +/** Set the flags field in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param flags flags value to set + */ + +void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name); + +/** Set the name field in the ECDSA_METHOD + * \param ecdsa_method pointer to existing ECDSA_METHOD + * \param name name to set + */ + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_ECDSA_strings(void); + +/* Error codes for the ECDSA functions. */ + +/* Function codes. */ +# define ECDSA_F_ECDSA_CHECK 104 +# define ECDSA_F_ECDSA_DATA_NEW_METHOD 100 +# define ECDSA_F_ECDSA_DO_SIGN 101 +# define ECDSA_F_ECDSA_DO_VERIFY 102 +# define ECDSA_F_ECDSA_METHOD_NEW 105 +# define ECDSA_F_ECDSA_SIGN_SETUP 103 + +/* Reason codes. */ +# define ECDSA_R_BAD_SIGNATURE 100 +# define ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 101 +# define ECDSA_R_ERR_EC_LIB 102 +# define ECDSA_R_MISSING_PARAMETERS 103 +# define ECDSA_R_NEED_NEW_SETUP_VALUES 106 +# define ECDSA_R_NON_FIPS_METHOD 107 +# define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED 104 +# define ECDSA_R_SIGNATURE_MALLOC_FAILED 105 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/engine.h b/optee/optee_test/host/openssl/include/openssl/engine.h new file mode 100644 index 0000000..bd7b591 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/engine.h @@ -0,0 +1,960 @@ +/* openssl/engine.h */ +/* + * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project + * 2000. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_ENGINE_H +# define HEADER_ENGINE_H + +# include + +# ifdef OPENSSL_NO_ENGINE +# error ENGINE is disabled. +# endif + +# ifndef OPENSSL_NO_DEPRECATED +# include +# ifndef OPENSSL_NO_RSA +# include +# endif +# ifndef OPENSSL_NO_DSA +# include +# endif +# ifndef OPENSSL_NO_DH +# include +# endif +# ifndef OPENSSL_NO_ECDH +# include +# endif +# ifndef OPENSSL_NO_ECDSA +# include +# endif +# include +# include +# include +# endif + +# include +# include + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * These flags are used to control combinations of algorithm (methods) by + * bitwise "OR"ing. + */ +# define ENGINE_METHOD_RSA (unsigned int)0x0001 +# define ENGINE_METHOD_DSA (unsigned int)0x0002 +# define ENGINE_METHOD_DH (unsigned int)0x0004 +# define ENGINE_METHOD_RAND (unsigned int)0x0008 +# define ENGINE_METHOD_ECDH (unsigned int)0x0010 +# define ENGINE_METHOD_ECDSA (unsigned int)0x0020 +# define ENGINE_METHOD_CIPHERS (unsigned int)0x0040 +# define ENGINE_METHOD_DIGESTS (unsigned int)0x0080 +# define ENGINE_METHOD_STORE (unsigned int)0x0100 +# define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200 +# define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400 +/* Obvious all-or-nothing cases. */ +# define ENGINE_METHOD_ALL (unsigned int)0xFFFF +# define ENGINE_METHOD_NONE (unsigned int)0x0000 + +/* + * This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used + * internally to control registration of ENGINE implementations, and can be + * set by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to + * initialise registered ENGINEs if they are not already initialised. + */ +# define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001 + +/* ENGINE flags that can be set by ENGINE_set_flags(). */ +/* Not used */ +/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ + +/* + * This flag is for ENGINEs that wish to handle the various 'CMD'-related + * control commands on their own. Without this flag, ENGINE_ctrl() handles + * these control commands on behalf of the ENGINE using their "cmd_defns" + * data. + */ +# define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002 + +/* + * This flag is for ENGINEs who return new duplicate structures when found + * via "ENGINE_by_id()". When an ENGINE must store state (eg. if + * ENGINE_ctrl() commands are called in sequence as part of some stateful + * process like key-generation setup and execution), it can set this flag - + * then each attempt to obtain the ENGINE will result in it being copied into + * a new structure. Normally, ENGINEs don't declare this flag so + * ENGINE_by_id() just increments the existing ENGINE's structural reference + * count. + */ +# define ENGINE_FLAGS_BY_ID_COPY (int)0x0004 + +/* + * This flag if for an ENGINE that does not want its methods registered as + * part of ENGINE_register_all_complete() for example if the methods are not + * usable as default methods. + */ + +# define ENGINE_FLAGS_NO_REGISTER_ALL (int)0x0008 + +/* + * ENGINEs can support their own command types, and these flags are used in + * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input + * each command expects. Currently only numeric and string input is + * supported. If a control command supports none of the _NUMERIC, _STRING, or + * _NO_INPUT options, then it is regarded as an "internal" control command - + * and not for use in config setting situations. As such, they're not + * available to the ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() + * access. Changes to this list of 'command types' should be reflected + * carefully in ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). + */ + +/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */ +# define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001 +/* + * accepts string input (cast from 'void*' to 'const char *', 4th parameter + * to ENGINE_ctrl) + */ +# define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002 +/* + * Indicates that the control command takes *no* input. Ie. the control + * command is unparameterised. + */ +# define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004 +/* + * Indicates that the control command is internal. This control command won't + * be shown in any output, and is only usable through the ENGINE_ctrl_cmd() + * function. + */ +# define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008 + +/* + * NB: These 3 control commands are deprecated and should not be used. + * ENGINEs relying on these commands should compile conditional support for + * compatibility (eg. if these symbols are defined) but should also migrate + * the same functionality to their own ENGINE-specific control functions that + * can be "discovered" by calling applications. The fact these control + * commands wouldn't be "executable" (ie. usable by text-based config) + * doesn't change the fact that application code can find and use them + * without requiring per-ENGINE hacking. + */ + +/* + * These flags are used to tell the ctrl function what should be done. All + * command numbers are shared between all engines, even if some don't make + * sense to some engines. In such a case, they do nothing but return the + * error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. + */ +# define ENGINE_CTRL_SET_LOGSTREAM 1 +# define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2 +# define ENGINE_CTRL_HUP 3/* Close and reinitialise + * any handles/connections + * etc. */ +# define ENGINE_CTRL_SET_USER_INTERFACE 4/* Alternative to callback */ +# define ENGINE_CTRL_SET_CALLBACK_DATA 5/* User-specific data, used + * when calling the password + * callback and the user + * interface */ +# define ENGINE_CTRL_LOAD_CONFIGURATION 6/* Load a configuration, + * given a string that + * represents a file name + * or so */ +# define ENGINE_CTRL_LOAD_SECTION 7/* Load data from a given + * section in the already + * loaded configuration */ + +/* + * These control commands allow an application to deal with an arbitrary + * engine in a dynamic way. Warn: Negative return values indicate errors FOR + * THESE COMMANDS because zero is used to indicate 'end-of-list'. Other + * commands, including ENGINE-specific command types, return zero for an + * error. An ENGINE can choose to implement these ctrl functions, and can + * internally manage things however it chooses - it does so by setting the + * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise + * the ENGINE_ctrl() code handles this on the ENGINE's behalf using the + * cmd_defns data (set using ENGINE_set_cmd_defns()). This means an ENGINE's + * ctrl() handler need only implement its own commands - the above "meta" + * commands will be taken care of. + */ + +/* + * Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", + * then all the remaining control commands will return failure, so it is + * worth checking this first if the caller is trying to "discover" the + * engine's capabilities and doesn't want errors generated unnecessarily. + */ +# define ENGINE_CTRL_HAS_CTRL_FUNCTION 10 +/* + * Returns a positive command number for the first command supported by the + * engine. Returns zero if no ctrl commands are supported. + */ +# define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11 +/* + * The 'long' argument specifies a command implemented by the engine, and the + * return value is the next command supported, or zero if there are no more. + */ +# define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12 +/* + * The 'void*' argument is a command name (cast from 'const char *'), and the + * return value is the command that corresponds to it. + */ +# define ENGINE_CTRL_GET_CMD_FROM_NAME 13 +/* + * The next two allow a command to be converted into its corresponding string + * form. In each case, the 'long' argument supplies the command. In the + * NAME_LEN case, the return value is the length of the command name (not + * counting a trailing EOL). In the NAME case, the 'void*' argument must be a + * string buffer large enough, and it will be populated with the name of the + * command (WITH a trailing EOL). + */ +# define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14 +# define ENGINE_CTRL_GET_NAME_FROM_CMD 15 +/* The next two are similar but give a "short description" of a command. */ +# define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16 +# define ENGINE_CTRL_GET_DESC_FROM_CMD 17 +/* + * With this command, the return value is the OR'd combination of + * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given + * engine-specific ctrl command expects. + */ +# define ENGINE_CTRL_GET_CMD_FLAGS 18 + +/* + * ENGINE implementations should start the numbering of their own control + * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). + */ +# define ENGINE_CMD_BASE 200 + +/* + * NB: These 2 nCipher "chil" control commands are deprecated, and their + * functionality is now available through ENGINE-specific control commands + * (exposed through the above-mentioned 'CMD'-handling). Code using these 2 + * commands should be migrated to the more general command handling before + * these are removed. + */ + +/* Flags specific to the nCipher "chil" engine */ +# define ENGINE_CTRL_CHIL_SET_FORKCHECK 100 + /* + * Depending on the value of the (long)i argument, this sets or + * unsets the SimpleForkCheck flag in the CHIL API to enable or + * disable checking and workarounds for applications that fork(). + */ +# define ENGINE_CTRL_CHIL_NO_LOCKING 101 + /* + * This prevents the initialisation function from providing mutex + * callbacks to the nCipher library. + */ + +/* + * If an ENGINE supports its own specific control commands and wishes the + * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on + * its behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN + * entries to ENGINE_set_cmd_defns(). It should also implement a ctrl() + * handler that supports the stated commands (ie. the "cmd_num" entries as + * described by the array). NB: The array must be ordered in increasing order + * of cmd_num. "null-terminated" means that the last ENGINE_CMD_DEFN element + * has cmd_num set to zero and/or cmd_name set to NULL. + */ +typedef struct ENGINE_CMD_DEFN_st { + unsigned int cmd_num; /* The command number */ + const char *cmd_name; /* The command name itself */ + const char *cmd_desc; /* A short description of the command */ + unsigned int cmd_flags; /* The input the command expects */ +} ENGINE_CMD_DEFN; + +/* Generic function pointer */ +typedef int (*ENGINE_GEN_FUNC_PTR) (void); +/* Generic function pointer taking no arguments */ +typedef int (*ENGINE_GEN_INT_FUNC_PTR) (ENGINE *); +/* Specific control function pointer */ +typedef int (*ENGINE_CTRL_FUNC_PTR) (ENGINE *, int, long, void *, + void (*f) (void)); +/* Generic load_key function pointer */ +typedef EVP_PKEY *(*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *, + UI_METHOD *ui_method, + void *callback_data); +typedef int (*ENGINE_SSL_CLIENT_CERT_PTR) (ENGINE *, SSL *ssl, + STACK_OF(X509_NAME) *ca_dn, + X509 **pcert, EVP_PKEY **pkey, + STACK_OF(X509) **pother, + UI_METHOD *ui_method, + void *callback_data); +/*- + * These callback types are for an ENGINE's handler for cipher and digest logic. + * These handlers have these prototypes; + * int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid); + * int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid); + * Looking at how to implement these handlers in the case of cipher support, if + * the framework wants the EVP_CIPHER for 'nid', it will call; + * foo(e, &p_evp_cipher, NULL, nid); (return zero for failure) + * If the framework wants a list of supported 'nid's, it will call; + * foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error) + */ +/* + * Returns to a pointer to the array of supported cipher 'nid's. If the + * second parameter is non-NULL it is set to the size of the returned array. + */ +typedef int (*ENGINE_CIPHERS_PTR) (ENGINE *, const EVP_CIPHER **, + const int **, int); +typedef int (*ENGINE_DIGESTS_PTR) (ENGINE *, const EVP_MD **, const int **, + int); +typedef int (*ENGINE_PKEY_METHS_PTR) (ENGINE *, EVP_PKEY_METHOD **, + const int **, int); +typedef int (*ENGINE_PKEY_ASN1_METHS_PTR) (ENGINE *, EVP_PKEY_ASN1_METHOD **, + const int **, int); +/* + * STRUCTURE functions ... all of these functions deal with pointers to + * ENGINE structures where the pointers have a "structural reference". This + * means that their reference is to allowed access to the structure but it + * does not imply that the structure is functional. To simply increment or + * decrement the structural reference count, use ENGINE_by_id and + * ENGINE_free. NB: This is not required when iterating using ENGINE_get_next + * as it will automatically decrement the structural reference count of the + * "current" ENGINE and increment the structural reference count of the + * ENGINE it returns (unless it is NULL). + */ + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void); +ENGINE *ENGINE_get_last(void); +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e); +ENGINE *ENGINE_get_prev(ENGINE *e); +/* Add another "ENGINE" type into the array. */ +int ENGINE_add(ENGINE *e); +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e); +/* Retrieve an engine from the list by its unique "id" value. */ +ENGINE *ENGINE_by_id(const char *id); +/* Add all the built-in engines. */ +void ENGINE_load_openssl(void); +void ENGINE_load_dynamic(void); +# ifndef OPENSSL_NO_STATIC_ENGINE +void ENGINE_load_4758cca(void); +void ENGINE_load_aep(void); +void ENGINE_load_atalla(void); +void ENGINE_load_chil(void); +void ENGINE_load_cswift(void); +void ENGINE_load_nuron(void); +void ENGINE_load_sureware(void); +void ENGINE_load_ubsec(void); +void ENGINE_load_padlock(void); +void ENGINE_load_capi(void); +# ifndef OPENSSL_NO_GMP +void ENGINE_load_gmp(void); +# endif +# ifndef OPENSSL_NO_GOST +void ENGINE_load_gost(void); +# endif +# endif +void ENGINE_load_cryptodev(void); +void ENGINE_load_rdrand(void); +void ENGINE_load_builtin_engines(void); + +/* + * Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation + * "registry" handling. + */ +unsigned int ENGINE_get_table_flags(void); +void ENGINE_set_table_flags(unsigned int flags); + +/*- Manage registration of ENGINEs per "table". For each type, there are 3 + * functions; + * ENGINE_register_***(e) - registers the implementation from 'e' (if it has one) + * ENGINE_unregister_***(e) - unregister the implementation from 'e' + * ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list + * Cleanup is automatically registered from each table when required, so + * ENGINE_cleanup() will reverse any "register" operations. + */ + +int ENGINE_register_RSA(ENGINE *e); +void ENGINE_unregister_RSA(ENGINE *e); +void ENGINE_register_all_RSA(void); + +int ENGINE_register_DSA(ENGINE *e); +void ENGINE_unregister_DSA(ENGINE *e); +void ENGINE_register_all_DSA(void); + +int ENGINE_register_ECDH(ENGINE *e); +void ENGINE_unregister_ECDH(ENGINE *e); +void ENGINE_register_all_ECDH(void); + +int ENGINE_register_ECDSA(ENGINE *e); +void ENGINE_unregister_ECDSA(ENGINE *e); +void ENGINE_register_all_ECDSA(void); + +int ENGINE_register_DH(ENGINE *e); +void ENGINE_unregister_DH(ENGINE *e); +void ENGINE_register_all_DH(void); + +int ENGINE_register_RAND(ENGINE *e); +void ENGINE_unregister_RAND(ENGINE *e); +void ENGINE_register_all_RAND(void); + +int ENGINE_register_STORE(ENGINE *e); +void ENGINE_unregister_STORE(ENGINE *e); +void ENGINE_register_all_STORE(void); + +int ENGINE_register_ciphers(ENGINE *e); +void ENGINE_unregister_ciphers(ENGINE *e); +void ENGINE_register_all_ciphers(void); + +int ENGINE_register_digests(ENGINE *e); +void ENGINE_unregister_digests(ENGINE *e); +void ENGINE_register_all_digests(void); + +int ENGINE_register_pkey_meths(ENGINE *e); +void ENGINE_unregister_pkey_meths(ENGINE *e); +void ENGINE_register_all_pkey_meths(void); + +int ENGINE_register_pkey_asn1_meths(ENGINE *e); +void ENGINE_unregister_pkey_asn1_meths(ENGINE *e); +void ENGINE_register_all_pkey_asn1_meths(void); + +/* + * These functions register all support from the above categories. Note, use + * of these functions can result in static linkage of code your application + * may not need. If you only need a subset of functionality, consider using + * more selective initialisation. + */ +int ENGINE_register_complete(ENGINE *e); +int ENGINE_register_all_complete(void); + +/* + * Send parametrised control commands to the engine. The possibilities to + * send down an integer, a pointer to data or a function pointer are + * provided. Any of the parameters may or may not be NULL, depending on the + * command number. In actuality, this function only requires a structural + * (rather than functional) reference to an engine, but many control commands + * may require the engine be functional. The caller should be aware of trying + * commands that require an operational ENGINE, and only use functional + * references in such situations. + */ +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)); + +/* + * This function tests if an ENGINE-specific command is usable as a + * "setting". Eg. in an application's config file that gets processed through + * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to + * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). + */ +int ENGINE_cmd_is_executable(ENGINE *e, int cmd); + +/* + * This function works like ENGINE_ctrl() with the exception of taking a + * command name instead of a command number, and can handle optional + * commands. See the comment on ENGINE_ctrl_cmd_string() for an explanation + * on how to use the cmd_name and cmd_optional. + */ +int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, + long i, void *p, void (*f) (void), int cmd_optional); + +/* + * This function passes a command-name and argument to an ENGINE. The + * cmd_name is converted to a command number and the control command is + * called using 'arg' as an argument (unless the ENGINE doesn't support such + * a command, in which case no control command is called). The command is + * checked for input flags, and if necessary the argument will be converted + * to a numeric value. If cmd_optional is non-zero, then if the ENGINE + * doesn't support the given cmd_name the return value will be success + * anyway. This function is intended for applications to use so that users + * (or config files) can supply engine-specific config data to the ENGINE at + * run-time to control behaviour of specific engines. As such, it shouldn't + * be used for calling ENGINE_ctrl() functions that return data, deal with + * binary data, or that are otherwise supposed to be used directly through + * ENGINE_ctrl() in application code. Any "return" data from an ENGINE_ctrl() + * operation in this function will be lost - the return value is interpreted + * as failure if the return value is zero, success otherwise, and this + * function returns a boolean value as a result. In other words, vendors of + * 'ENGINE'-enabled devices should write ENGINE implementations with + * parameterisations that work in this scheme, so that compliant ENGINE-based + * applications can work consistently with the same configuration for the + * same ENGINE-enabled devices, across applications. + */ +int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, + int cmd_optional); + +/* + * These functions are useful for manufacturing new ENGINE structures. They + * don't address reference counting at all - one uses them to populate an + * ENGINE structure with personalised implementations of things prior to + * using it directly or adding it to the builtin ENGINE list in OpenSSL. + * These are also here so that the ENGINE structure doesn't have to be + * exposed and break binary compatibility! + */ +ENGINE *ENGINE_new(void); +int ENGINE_free(ENGINE *e); +int ENGINE_up_ref(ENGINE *e); +int ENGINE_set_id(ENGINE *e, const char *id); +int ENGINE_set_name(ENGINE *e, const char *name); +int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth); +int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth); +int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth); +int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth); +int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth); +int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth); +int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth); +int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f); +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f); +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f); +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f); +int ENGINE_set_load_privkey_function(ENGINE *e, + ENGINE_LOAD_KEY_PTR loadpriv_f); +int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f); +int ENGINE_set_load_ssl_client_cert_function(ENGINE *e, + ENGINE_SSL_CLIENT_CERT_PTR + loadssl_f); +int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f); +int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f); +int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f); +int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f); +int ENGINE_set_flags(ENGINE *e, int flags); +int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns); +/* These functions allow control over any per-structure ENGINE data. */ +int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg); +void *ENGINE_get_ex_data(const ENGINE *e, int idx); + +/* + * This function cleans up anything that needs it. Eg. the ENGINE_add() + * function automatically ensures the list cleanup function is registered to + * be called from ENGINE_cleanup(). Similarly, all ENGINE_register_*** + * functions ensure ENGINE_cleanup() will clean up after them. + */ +void ENGINE_cleanup(void); + +/* + * These return values from within the ENGINE structure. These can be useful + * with functional references as well as structural references - it depends + * which you obtained. Using the result for functional purposes if you only + * obtained a structural reference may be problematic! + */ +const char *ENGINE_get_id(const ENGINE *e); +const char *ENGINE_get_name(const ENGINE *e); +const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e); +const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e); +const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e); +const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e); +const DH_METHOD *ENGINE_get_DH(const ENGINE *e); +const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e); +const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e); +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e); +ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE + *e); +ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e); +ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e); +ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e); +ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e); +const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid); +const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid); +const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid); +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid); +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e, + const char *str, + int len); +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, + const char *str, + int len); +const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e); +int ENGINE_get_flags(const ENGINE *e); + +/* + * FUNCTIONAL functions. These functions deal with ENGINE structures that + * have (or will) be initialised for use. Broadly speaking, the structural + * functions are useful for iterating the list of available engine types, + * creating new engine types, and other "list" operations. These functions + * actually deal with ENGINEs that are to be used. As such these functions + * can fail (if applicable) when particular engines are unavailable - eg. if + * a hardware accelerator is not attached or not functioning correctly. Each + * ENGINE has 2 reference counts; structural and functional. Every time a + * functional reference is obtained or released, a corresponding structural + * reference is automatically obtained or released too. + */ + +/* + * Initialise a engine type for use (or up its reference count if it's + * already in use). This will fail if the engine is not currently operational + * and cannot initialise. + */ +int ENGINE_init(ENGINE *e); +/* + * Free a functional reference to a engine type. This does not require a + * corresponding call to ENGINE_free as it also releases a structural + * reference. + */ +int ENGINE_finish(ENGINE *e); + +/* + * The following functions handle keys that are stored in some secondary + * location, handled by the engine. The storage may be on a card or + * whatever. + */ +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s, + STACK_OF(X509_NAME) *ca_dn, X509 **pcert, + EVP_PKEY **ppkey, STACK_OF(X509) **pother, + UI_METHOD *ui_method, void *callback_data); + +/* + * This returns a pointer for the current ENGINE structure that is (by + * default) performing any RSA operations. The value returned is an + * incremented reference, so it should be free'd (ENGINE_finish) before it is + * discarded. + */ +ENGINE *ENGINE_get_default_RSA(void); +/* Same for the other "methods" */ +ENGINE *ENGINE_get_default_DSA(void); +ENGINE *ENGINE_get_default_ECDH(void); +ENGINE *ENGINE_get_default_ECDSA(void); +ENGINE *ENGINE_get_default_DH(void); +ENGINE *ENGINE_get_default_RAND(void); +/* + * These functions can be used to get a functional reference to perform + * ciphering or digesting corresponding to "nid". + */ +ENGINE *ENGINE_get_cipher_engine(int nid); +ENGINE *ENGINE_get_digest_engine(int nid); +ENGINE *ENGINE_get_pkey_meth_engine(int nid); +ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid); + +/* + * This sets a new default ENGINE structure for performing RSA operations. If + * the result is non-zero (success) then the ENGINE structure will have had + * its reference count up'd so the caller should still free their own + * reference 'e'. + */ +int ENGINE_set_default_RSA(ENGINE *e); +int ENGINE_set_default_string(ENGINE *e, const char *def_list); +/* Same for the other "methods" */ +int ENGINE_set_default_DSA(ENGINE *e); +int ENGINE_set_default_ECDH(ENGINE *e); +int ENGINE_set_default_ECDSA(ENGINE *e); +int ENGINE_set_default_DH(ENGINE *e); +int ENGINE_set_default_RAND(ENGINE *e); +int ENGINE_set_default_ciphers(ENGINE *e); +int ENGINE_set_default_digests(ENGINE *e); +int ENGINE_set_default_pkey_meths(ENGINE *e); +int ENGINE_set_default_pkey_asn1_meths(ENGINE *e); + +/* + * The combination "set" - the flags are bitwise "OR"d from the + * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()" + * function, this function can result in unnecessary static linkage. If your + * application requires only specific functionality, consider using more + * selective functions. + */ +int ENGINE_set_default(ENGINE *e, unsigned int flags); + +void ENGINE_add_conf_module(void); + +/* Deprecated functions ... */ +/* int ENGINE_clear_defaults(void); */ + +/**************************/ +/* DYNAMIC ENGINE SUPPORT */ +/**************************/ + +/* Binary/behaviour compatibility levels */ +# define OSSL_DYNAMIC_VERSION (unsigned long)0x00020000 +/* + * Binary versions older than this are too old for us (whether we're a loader + * or a loadee) + */ +# define OSSL_DYNAMIC_OLDEST (unsigned long)0x00020000 + +/* + * When compiling an ENGINE entirely as an external shared library, loadable + * by the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' + * structure type provides the calling application's (or library's) error + * functionality and memory management function pointers to the loaded + * library. These should be used/set in the loaded library code so that the + * loading application's 'state' will be used/changed in all operations. The + * 'static_state' pointer allows the loaded library to know if it shares the + * same static data as the calling application (or library), and thus whether + * these callbacks need to be set or not. + */ +typedef void *(*dyn_MEM_malloc_cb) (size_t); +typedef void *(*dyn_MEM_realloc_cb) (void *, size_t); +typedef void (*dyn_MEM_free_cb) (void *); +typedef struct st_dynamic_MEM_fns { + dyn_MEM_malloc_cb malloc_cb; + dyn_MEM_realloc_cb realloc_cb; + dyn_MEM_free_cb free_cb; +} dynamic_MEM_fns; +/* + * FIXME: Perhaps the memory and locking code (crypto.h) should declare and + * use these types so we (and any other dependant code) can simplify a bit?? + */ +typedef void (*dyn_lock_locking_cb) (int, int, const char *, int); +typedef int (*dyn_lock_add_lock_cb) (int *, int, int, const char *, int); +typedef struct CRYPTO_dynlock_value *(*dyn_dynlock_create_cb) (const char *, + int); +typedef void (*dyn_dynlock_lock_cb) (int, struct CRYPTO_dynlock_value *, + const char *, int); +typedef void (*dyn_dynlock_destroy_cb) (struct CRYPTO_dynlock_value *, + const char *, int); +typedef struct st_dynamic_LOCK_fns { + dyn_lock_locking_cb lock_locking_cb; + dyn_lock_add_lock_cb lock_add_lock_cb; + dyn_dynlock_create_cb dynlock_create_cb; + dyn_dynlock_lock_cb dynlock_lock_cb; + dyn_dynlock_destroy_cb dynlock_destroy_cb; +} dynamic_LOCK_fns; +/* The top-level structure */ +typedef struct st_dynamic_fns { + void *static_state; + const ERR_FNS *err_fns; + const CRYPTO_EX_DATA_IMPL *ex_data_fns; + dynamic_MEM_fns mem_fns; + dynamic_LOCK_fns lock_fns; +} dynamic_fns; + +/* + * The version checking function should be of this prototype. NB: The + * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading + * code. If this function returns zero, it indicates a (potential) version + * incompatibility and the loaded library doesn't believe it can proceed. + * Otherwise, the returned value is the (latest) version supported by the + * loading library. The loader may still decide that the loaded code's + * version is unsatisfactory and could veto the load. The function is + * expected to be implemented with the symbol name "v_check", and a default + * implementation can be fully instantiated with + * IMPLEMENT_DYNAMIC_CHECK_FN(). + */ +typedef unsigned long (*dynamic_v_check_fn) (unsigned long ossl_version); +# define IMPLEMENT_DYNAMIC_CHECK_FN() \ + OPENSSL_EXPORT unsigned long v_check(unsigned long v); \ + OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \ + if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \ + return 0; } + +/* + * This function is passed the ENGINE structure to initialise with its own + * function and command settings. It should not adjust the structural or + * functional reference counts. If this function returns zero, (a) the load + * will be aborted, (b) the previous ENGINE state will be memcpy'd back onto + * the structure, and (c) the shared library will be unloaded. So + * implementations should do their own internal cleanup in failure + * circumstances otherwise they could leak. The 'id' parameter, if non-NULL, + * represents the ENGINE id that the loader is looking for. If this is NULL, + * the shared library can choose to return failure or to initialise a + * 'default' ENGINE. If non-NULL, the shared library must initialise only an + * ENGINE matching the passed 'id'. The function is expected to be + * implemented with the symbol name "bind_engine". A standard implementation + * can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where the parameter + * 'fn' is a callback function that populates the ENGINE structure and + * returns an int value (zero for failure). 'fn' should have prototype; + * [static] int fn(ENGINE *e, const char *id); + */ +typedef int (*dynamic_bind_engine) (ENGINE *e, const char *id, + const dynamic_fns *fns); +# define IMPLEMENT_DYNAMIC_BIND_FN(fn) \ + OPENSSL_EXPORT \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); \ + OPENSSL_EXPORT \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \ + if(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \ + if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \ + fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \ + return 0; \ + CRYPTO_set_locking_callback(fns->lock_fns.lock_locking_cb); \ + CRYPTO_set_add_lock_callback(fns->lock_fns.lock_add_lock_cb); \ + CRYPTO_set_dynlock_create_callback(fns->lock_fns.dynlock_create_cb); \ + CRYPTO_set_dynlock_lock_callback(fns->lock_fns.dynlock_lock_cb); \ + CRYPTO_set_dynlock_destroy_callback(fns->lock_fns.dynlock_destroy_cb); \ + if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \ + return 0; \ + if(!ERR_set_implementation(fns->err_fns)) return 0; \ + skip_cbs: \ + if(!fn(e,id)) return 0; \ + return 1; } + +/* + * If the loading application (or library) and the loaded ENGINE library + * share the same static data (eg. they're both dynamically linked to the + * same libcrypto.so) we need a way to avoid trying to set system callbacks - + * this would fail, and for the same reason that it's unnecessary to try. If + * the loaded ENGINE has (or gets from through the loader) its own copy of + * the libcrypto static data, we will need to set the callbacks. The easiest + * way to detect this is to have a function that returns a pointer to some + * static data and let the loading application and loaded ENGINE compare + * their respective values. + */ +void *ENGINE_get_static_state(void); + +# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV) +void ENGINE_setup_bsd_cryptodev(void); +# endif + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_ENGINE_strings(void); + +/* Error codes for the ENGINE functions. */ + +/* Function codes. */ +# define ENGINE_F_DYNAMIC_CTRL 180 +# define ENGINE_F_DYNAMIC_GET_DATA_CTX 181 +# define ENGINE_F_DYNAMIC_LOAD 182 +# define ENGINE_F_DYNAMIC_SET_DATA_CTX 183 +# define ENGINE_F_ENGINE_ADD 105 +# define ENGINE_F_ENGINE_BY_ID 106 +# define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170 +# define ENGINE_F_ENGINE_CTRL 142 +# define ENGINE_F_ENGINE_CTRL_CMD 178 +# define ENGINE_F_ENGINE_CTRL_CMD_STRING 171 +# define ENGINE_F_ENGINE_FINISH 107 +# define ENGINE_F_ENGINE_FREE_UTIL 108 +# define ENGINE_F_ENGINE_GET_CIPHER 185 +# define ENGINE_F_ENGINE_GET_DEFAULT_TYPE 177 +# define ENGINE_F_ENGINE_GET_DIGEST 186 +# define ENGINE_F_ENGINE_GET_NEXT 115 +# define ENGINE_F_ENGINE_GET_PKEY_ASN1_METH 193 +# define ENGINE_F_ENGINE_GET_PKEY_METH 192 +# define ENGINE_F_ENGINE_GET_PREV 116 +# define ENGINE_F_ENGINE_INIT 119 +# define ENGINE_F_ENGINE_LIST_ADD 120 +# define ENGINE_F_ENGINE_LIST_REMOVE 121 +# define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150 +# define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151 +# define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 194 +# define ENGINE_F_ENGINE_NEW 122 +# define ENGINE_F_ENGINE_REMOVE 123 +# define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189 +# define ENGINE_F_ENGINE_SET_DEFAULT_TYPE 126 +# define ENGINE_F_ENGINE_SET_ID 129 +# define ENGINE_F_ENGINE_SET_NAME 130 +# define ENGINE_F_ENGINE_TABLE_REGISTER 184 +# define ENGINE_F_ENGINE_UNLOAD_KEY 152 +# define ENGINE_F_ENGINE_UNLOCKED_FINISH 191 +# define ENGINE_F_ENGINE_UP_REF 190 +# define ENGINE_F_INT_CTRL_HELPER 172 +# define ENGINE_F_INT_ENGINE_CONFIGURE 188 +# define ENGINE_F_INT_ENGINE_MODULE_INIT 187 +# define ENGINE_F_LOG_MESSAGE 141 + +/* Reason codes. */ +# define ENGINE_R_ALREADY_LOADED 100 +# define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133 +# define ENGINE_R_CMD_NOT_EXECUTABLE 134 +# define ENGINE_R_COMMAND_TAKES_INPUT 135 +# define ENGINE_R_COMMAND_TAKES_NO_INPUT 136 +# define ENGINE_R_CONFLICTING_ENGINE_ID 103 +# define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119 +# define ENGINE_R_DH_NOT_IMPLEMENTED 139 +# define ENGINE_R_DSA_NOT_IMPLEMENTED 140 +# define ENGINE_R_DSO_FAILURE 104 +# define ENGINE_R_DSO_NOT_FOUND 132 +# define ENGINE_R_ENGINES_SECTION_ERROR 148 +# define ENGINE_R_ENGINE_CONFIGURATION_ERROR 102 +# define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105 +# define ENGINE_R_ENGINE_SECTION_ERROR 149 +# define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128 +# define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129 +# define ENGINE_R_FINISH_FAILED 106 +# define ENGINE_R_GET_HANDLE_FAILED 107 +# define ENGINE_R_ID_OR_NAME_MISSING 108 +# define ENGINE_R_INIT_FAILED 109 +# define ENGINE_R_INTERNAL_LIST_ERROR 110 +# define ENGINE_R_INVALID_ARGUMENT 143 +# define ENGINE_R_INVALID_CMD_NAME 137 +# define ENGINE_R_INVALID_CMD_NUMBER 138 +# define ENGINE_R_INVALID_INIT_VALUE 151 +# define ENGINE_R_INVALID_STRING 150 +# define ENGINE_R_NOT_INITIALISED 117 +# define ENGINE_R_NOT_LOADED 112 +# define ENGINE_R_NO_CONTROL_FUNCTION 120 +# define ENGINE_R_NO_INDEX 144 +# define ENGINE_R_NO_LOAD_FUNCTION 125 +# define ENGINE_R_NO_REFERENCE 130 +# define ENGINE_R_NO_SUCH_ENGINE 116 +# define ENGINE_R_NO_UNLOAD_FUNCTION 126 +# define ENGINE_R_PROVIDE_PARAMETERS 113 +# define ENGINE_R_RSA_NOT_IMPLEMENTED 141 +# define ENGINE_R_UNIMPLEMENTED_CIPHER 146 +# define ENGINE_R_UNIMPLEMENTED_DIGEST 147 +# define ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD 101 +# define ENGINE_R_VERSION_INCOMPATIBILITY 145 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/err.h b/optee/optee_test/host/openssl/include/openssl/err.h new file mode 100644 index 0000000..f423656 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/err.h @@ -0,0 +1,390 @@ +/* crypto/err/err.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_ERR_H +# define HEADER_ERR_H + +# include + +# ifndef OPENSSL_NO_FP_API +# include +# include +# endif + +# include +# ifndef OPENSSL_NO_BIO +# include +# endif +# ifndef OPENSSL_NO_LHASH +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# ifndef OPENSSL_NO_ERR +# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e) +# else +# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0) +# endif + +# include + +# define ERR_TXT_MALLOCED 0x01 +# define ERR_TXT_STRING 0x02 + +# define ERR_FLAG_MARK 0x01 + +# define ERR_NUM_ERRORS 16 +typedef struct err_state_st { + CRYPTO_THREADID tid; + int err_flags[ERR_NUM_ERRORS]; + unsigned long err_buffer[ERR_NUM_ERRORS]; + char *err_data[ERR_NUM_ERRORS]; + int err_data_flags[ERR_NUM_ERRORS]; + const char *err_file[ERR_NUM_ERRORS]; + int err_line[ERR_NUM_ERRORS]; + int top, bottom; +} ERR_STATE; + +/* library */ +# define ERR_LIB_NONE 1 +# define ERR_LIB_SYS 2 +# define ERR_LIB_BN 3 +# define ERR_LIB_RSA 4 +# define ERR_LIB_DH 5 +# define ERR_LIB_EVP 6 +# define ERR_LIB_BUF 7 +# define ERR_LIB_OBJ 8 +# define ERR_LIB_PEM 9 +# define ERR_LIB_DSA 10 +# define ERR_LIB_X509 11 +/* #define ERR_LIB_METH 12 */ +# define ERR_LIB_ASN1 13 +# define ERR_LIB_CONF 14 +# define ERR_LIB_CRYPTO 15 +# define ERR_LIB_EC 16 +# define ERR_LIB_SSL 20 +/* #define ERR_LIB_SSL23 21 */ +/* #define ERR_LIB_SSL2 22 */ +/* #define ERR_LIB_SSL3 23 */ +/* #define ERR_LIB_RSAREF 30 */ +/* #define ERR_LIB_PROXY 31 */ +# define ERR_LIB_BIO 32 +# define ERR_LIB_PKCS7 33 +# define ERR_LIB_X509V3 34 +# define ERR_LIB_PKCS12 35 +# define ERR_LIB_RAND 36 +# define ERR_LIB_DSO 37 +# define ERR_LIB_ENGINE 38 +# define ERR_LIB_OCSP 39 +# define ERR_LIB_UI 40 +# define ERR_LIB_COMP 41 +# define ERR_LIB_ECDSA 42 +# define ERR_LIB_ECDH 43 +# define ERR_LIB_STORE 44 +# define ERR_LIB_FIPS 45 +# define ERR_LIB_CMS 46 +# define ERR_LIB_TS 47 +# define ERR_LIB_HMAC 48 +# define ERR_LIB_JPAKE 49 + +# define ERR_LIB_USER 128 + +# define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),__FILE__,__LINE__) +# define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),__FILE__,__LINE__) +# define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),__FILE__,__LINE__) +# define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),__FILE__,__LINE__) +# define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),__FILE__,__LINE__) +# define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),__FILE__,__LINE__) +# define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),__FILE__,__LINE__) +# define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),__FILE__,__LINE__) +# define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),__FILE__,__LINE__) +# define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),__FILE__,__LINE__) +# define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),__FILE__,__LINE__) +# define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),__FILE__,__LINE__) +# define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),__FILE__,__LINE__) +# define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),__FILE__,__LINE__) +# define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__) +# define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),__FILE__,__LINE__) +# define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),__FILE__,__LINE__) +# define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),__FILE__,__LINE__) +# define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),__FILE__,__LINE__) +# define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),__FILE__,__LINE__) +# define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),__FILE__,__LINE__) +# define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),__FILE__,__LINE__) +# define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),__FILE__,__LINE__) +# define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),__FILE__,__LINE__) +# define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),__FILE__,__LINE__) +# define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),__FILE__,__LINE__) +# define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),__FILE__,__LINE__) +# define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__) +# define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),__FILE__,__LINE__) +# define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),__FILE__,__LINE__) +# define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),__FILE__,__LINE__) +# define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),__FILE__,__LINE__) +# define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__) + +/* + * Borland C seems too stupid to be able to shift and do longs in the + * pre-processor :-( + */ +# define ERR_PACK(l,f,r) (((((unsigned long)l)&0xffL)*0x1000000)| \ + ((((unsigned long)f)&0xfffL)*0x1000)| \ + ((((unsigned long)r)&0xfffL))) +# define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL) +# define ERR_GET_FUNC(l) (int)((((unsigned long)l)>>12L)&0xfffL) +# define ERR_GET_REASON(l) (int)((l)&0xfffL) +# define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL) + +/* OS functions */ +# define SYS_F_FOPEN 1 +# define SYS_F_CONNECT 2 +# define SYS_F_GETSERVBYNAME 3 +# define SYS_F_SOCKET 4 +# define SYS_F_IOCTLSOCKET 5 +# define SYS_F_BIND 6 +# define SYS_F_LISTEN 7 +# define SYS_F_ACCEPT 8 +# define SYS_F_WSASTARTUP 9/* Winsock stuff */ +# define SYS_F_OPENDIR 10 +# define SYS_F_FREAD 11 +# define SYS_F_FFLUSH 18 + +/* reasons */ +# define ERR_R_SYS_LIB ERR_LIB_SYS/* 2 */ +# define ERR_R_BN_LIB ERR_LIB_BN/* 3 */ +# define ERR_R_RSA_LIB ERR_LIB_RSA/* 4 */ +# define ERR_R_DH_LIB ERR_LIB_DH/* 5 */ +# define ERR_R_EVP_LIB ERR_LIB_EVP/* 6 */ +# define ERR_R_BUF_LIB ERR_LIB_BUF/* 7 */ +# define ERR_R_OBJ_LIB ERR_LIB_OBJ/* 8 */ +# define ERR_R_PEM_LIB ERR_LIB_PEM/* 9 */ +# define ERR_R_DSA_LIB ERR_LIB_DSA/* 10 */ +# define ERR_R_X509_LIB ERR_LIB_X509/* 11 */ +# define ERR_R_ASN1_LIB ERR_LIB_ASN1/* 13 */ +# define ERR_R_CONF_LIB ERR_LIB_CONF/* 14 */ +# define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO/* 15 */ +# define ERR_R_EC_LIB ERR_LIB_EC/* 16 */ +# define ERR_R_SSL_LIB ERR_LIB_SSL/* 20 */ +# define ERR_R_BIO_LIB ERR_LIB_BIO/* 32 */ +# define ERR_R_PKCS7_LIB ERR_LIB_PKCS7/* 33 */ +# define ERR_R_X509V3_LIB ERR_LIB_X509V3/* 34 */ +# define ERR_R_PKCS12_LIB ERR_LIB_PKCS12/* 35 */ +# define ERR_R_RAND_LIB ERR_LIB_RAND/* 36 */ +# define ERR_R_DSO_LIB ERR_LIB_DSO/* 37 */ +# define ERR_R_ENGINE_LIB ERR_LIB_ENGINE/* 38 */ +# define ERR_R_OCSP_LIB ERR_LIB_OCSP/* 39 */ +# define ERR_R_UI_LIB ERR_LIB_UI/* 40 */ +# define ERR_R_COMP_LIB ERR_LIB_COMP/* 41 */ +# define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */ +# define ERR_R_ECDH_LIB ERR_LIB_ECDH/* 43 */ +# define ERR_R_STORE_LIB ERR_LIB_STORE/* 44 */ +# define ERR_R_TS_LIB ERR_LIB_TS/* 45 */ + +# define ERR_R_NESTED_ASN1_ERROR 58 +# define ERR_R_BAD_ASN1_OBJECT_HEADER 59 +# define ERR_R_BAD_GET_ASN1_OBJECT_CALL 60 +# define ERR_R_EXPECTING_AN_ASN1_SEQUENCE 61 +# define ERR_R_ASN1_LENGTH_MISMATCH 62 +# define ERR_R_MISSING_ASN1_EOS 63 + +/* fatal error */ +# define ERR_R_FATAL 64 +# define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL) +# define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL) +# define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL) +# define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL) +# define ERR_R_DISABLED (5|ERR_R_FATAL) + +/* + * 99 is the maximum possible ERR_R_... code, higher values are reserved for + * the individual libraries + */ + +typedef struct ERR_string_data_st { + unsigned long error; + const char *string; +} ERR_STRING_DATA; + +void ERR_put_error(int lib, int func, int reason, const char *file, int line); +void ERR_set_error_data(char *data, int flags); + +unsigned long ERR_get_error(void); +unsigned long ERR_get_error_line(const char **file, int *line); +unsigned long ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags); +unsigned long ERR_peek_error(void); +unsigned long ERR_peek_error_line(const char **file, int *line); +unsigned long ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags); +unsigned long ERR_peek_last_error(void); +unsigned long ERR_peek_last_error_line(const char **file, int *line); +unsigned long ERR_peek_last_error_line_data(const char **file, int *line, + const char **data, int *flags); +void ERR_clear_error(void); +char *ERR_error_string(unsigned long e, char *buf); +void ERR_error_string_n(unsigned long e, char *buf, size_t len); +const char *ERR_lib_error_string(unsigned long e); +const char *ERR_func_error_string(unsigned long e); +const char *ERR_reason_error_string(unsigned long e); +void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u), + void *u); +# ifndef OPENSSL_NO_FP_API +void ERR_print_errors_fp(FILE *fp); +# endif +# ifndef OPENSSL_NO_BIO +void ERR_print_errors(BIO *bp); +# endif +void ERR_add_error_data(int num, ...); +void ERR_add_error_vdata(int num, va_list args); +void ERR_load_strings(int lib, ERR_STRING_DATA str[]); +void ERR_unload_strings(int lib, ERR_STRING_DATA str[]); +void ERR_load_ERR_strings(void); +void ERR_load_crypto_strings(void); +void ERR_free_strings(void); + +void ERR_remove_thread_state(const CRYPTO_THREADID *tid); +# ifndef OPENSSL_NO_DEPRECATED +void ERR_remove_state(unsigned long pid); /* if zero we look it up */ +# endif +ERR_STATE *ERR_get_state(void); + +# ifndef OPENSSL_NO_LHASH +LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void); +LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void); +void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash); +# endif + +int ERR_get_next_error_library(void); + +int ERR_set_mark(void); +int ERR_pop_to_mark(void); + +/* Already defined in ossl_typ.h */ +/* typedef struct st_ERR_FNS ERR_FNS; */ +/* + * An application can use this function and provide the return value to + * loaded modules that should use the application's ERR state/functionality + */ +const ERR_FNS *ERR_get_implementation(void); +/* + * A loaded module should call this function prior to any ERR operations + * using the application's "ERR_FNS". + */ +int ERR_set_implementation(const ERR_FNS *fns); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/evp.h b/optee/optee_test/host/openssl/include/openssl/evp.h new file mode 100644 index 0000000..cf1de15 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/evp.h @@ -0,0 +1,1628 @@ +/* crypto/evp/evp.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ENVELOPE_H +# define HEADER_ENVELOPE_H + +# ifdef OPENSSL_ALGORITHM_DEFINES +# include +# else +# define OPENSSL_ALGORITHM_DEFINES +# include +# undef OPENSSL_ALGORITHM_DEFINES +# endif + +# include + +# include + +# ifndef OPENSSL_NO_BIO +# include +# endif + +/*- +#define EVP_RC2_KEY_SIZE 16 +#define EVP_RC4_KEY_SIZE 16 +#define EVP_BLOWFISH_KEY_SIZE 16 +#define EVP_CAST5_KEY_SIZE 16 +#define EVP_RC5_32_12_16_KEY_SIZE 16 +*/ +# define EVP_MAX_MD_SIZE 64/* longest known is SHA512 */ +# define EVP_MAX_KEY_LENGTH 64 +# define EVP_MAX_IV_LENGTH 16 +# define EVP_MAX_BLOCK_LENGTH 32 + +# define PKCS5_SALT_LEN 8 +/* Default PKCS#5 iteration count */ +# define PKCS5_DEFAULT_ITER 2048 + +# include + +# define EVP_PK_RSA 0x0001 +# define EVP_PK_DSA 0x0002 +# define EVP_PK_DH 0x0004 +# define EVP_PK_EC 0x0008 +# define EVP_PKT_SIGN 0x0010 +# define EVP_PKT_ENC 0x0020 +# define EVP_PKT_EXCH 0x0040 +# define EVP_PKS_RSA 0x0100 +# define EVP_PKS_DSA 0x0200 +# define EVP_PKS_EC 0x0400 + +# define EVP_PKEY_NONE NID_undef +# define EVP_PKEY_RSA NID_rsaEncryption +# define EVP_PKEY_RSA2 NID_rsa +# define EVP_PKEY_DSA NID_dsa +# define EVP_PKEY_DSA1 NID_dsa_2 +# define EVP_PKEY_DSA2 NID_dsaWithSHA +# define EVP_PKEY_DSA3 NID_dsaWithSHA1 +# define EVP_PKEY_DSA4 NID_dsaWithSHA1_2 +# define EVP_PKEY_DH NID_dhKeyAgreement +# define EVP_PKEY_DHX NID_dhpublicnumber +# define EVP_PKEY_EC NID_X9_62_id_ecPublicKey +# define EVP_PKEY_HMAC NID_hmac +# define EVP_PKEY_CMAC NID_cmac + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Type needs to be a bit field Sub-type needs to be for variations on the + * method, as in, can it do arbitrary encryption.... + */ +struct evp_pkey_st { + int type; + int save_type; + int references; + const EVP_PKEY_ASN1_METHOD *ameth; + ENGINE *engine; + union { + char *ptr; +# ifndef OPENSSL_NO_RSA + struct rsa_st *rsa; /* RSA */ +# endif +# ifndef OPENSSL_NO_DSA + struct dsa_st *dsa; /* DSA */ +# endif +# ifndef OPENSSL_NO_DH + struct dh_st *dh; /* DH */ +# endif +# ifndef OPENSSL_NO_EC + struct ec_key_st *ec; /* ECC */ +# endif + } pkey; + int save_parameters; + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ +} /* EVP_PKEY */ ; + +# define EVP_PKEY_MO_SIGN 0x0001 +# define EVP_PKEY_MO_VERIFY 0x0002 +# define EVP_PKEY_MO_ENCRYPT 0x0004 +# define EVP_PKEY_MO_DECRYPT 0x0008 + +# ifndef EVP_MD +struct env_md_st { + int type; + int pkey_type; + int md_size; + unsigned long flags; + int (*init) (EVP_MD_CTX *ctx); + int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count); + int (*final) (EVP_MD_CTX *ctx, unsigned char *md); + int (*copy) (EVP_MD_CTX *to, const EVP_MD_CTX *from); + int (*cleanup) (EVP_MD_CTX *ctx); + /* FIXME: prototype these some day */ + int (*sign) (int type, const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, void *key); + int (*verify) (int type, const unsigned char *m, unsigned int m_length, + const unsigned char *sigbuf, unsigned int siglen, + void *key); + int required_pkey_type[5]; /* EVP_PKEY_xxx */ + int block_size; + int ctx_size; /* how big does the ctx->md_data need to be */ + /* control function */ + int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2); +} /* EVP_MD */ ; + +typedef int evp_sign_method(int type, const unsigned char *m, + unsigned int m_length, unsigned char *sigret, + unsigned int *siglen, void *key); +typedef int evp_verify_method(int type, const unsigned char *m, + unsigned int m_length, + const unsigned char *sigbuf, + unsigned int siglen, void *key); + +/* digest can only handle a single block */ +# define EVP_MD_FLAG_ONESHOT 0x0001 + +/* + * digest is a "clone" digest used + * which is a copy of an existing + * one for a specific public key type. + * EVP_dss1() etc + */ +# define EVP_MD_FLAG_PKEY_DIGEST 0x0002 + +/* Digest uses EVP_PKEY_METHOD for signing instead of MD specific signing */ + +# define EVP_MD_FLAG_PKEY_METHOD_SIGNATURE 0x0004 + +/* DigestAlgorithmIdentifier flags... */ + +# define EVP_MD_FLAG_DIGALGID_MASK 0x0018 + +/* NULL or absent parameter accepted. Use NULL */ + +# define EVP_MD_FLAG_DIGALGID_NULL 0x0000 + +/* NULL or absent parameter accepted. Use NULL for PKCS#1 otherwise absent */ + +# define EVP_MD_FLAG_DIGALGID_ABSENT 0x0008 + +/* Custom handling via ctrl */ + +# define EVP_MD_FLAG_DIGALGID_CUSTOM 0x0018 + +/* Note if suitable for use in FIPS mode */ +# define EVP_MD_FLAG_FIPS 0x0400 + +/* Digest ctrls */ + +# define EVP_MD_CTRL_DIGALGID 0x1 +# define EVP_MD_CTRL_MICALG 0x2 + +/* Minimum Algorithm specific ctrl value */ + +# define EVP_MD_CTRL_ALG_CTRL 0x1000 + +# define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0} + +# ifndef OPENSSL_NO_DSA +# define EVP_PKEY_DSA_method (evp_sign_method *)DSA_sign, \ + (evp_verify_method *)DSA_verify, \ + {EVP_PKEY_DSA,EVP_PKEY_DSA2,EVP_PKEY_DSA3, \ + EVP_PKEY_DSA4,0} +# else +# define EVP_PKEY_DSA_method EVP_PKEY_NULL_method +# endif + +# ifndef OPENSSL_NO_ECDSA +# define EVP_PKEY_ECDSA_method (evp_sign_method *)ECDSA_sign, \ + (evp_verify_method *)ECDSA_verify, \ + {EVP_PKEY_EC,0,0,0} +# else +# define EVP_PKEY_ECDSA_method EVP_PKEY_NULL_method +# endif + +# ifndef OPENSSL_NO_RSA +# define EVP_PKEY_RSA_method (evp_sign_method *)RSA_sign, \ + (evp_verify_method *)RSA_verify, \ + {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0} +# define EVP_PKEY_RSA_ASN1_OCTET_STRING_method \ + (evp_sign_method *)RSA_sign_ASN1_OCTET_STRING, \ + (evp_verify_method *)RSA_verify_ASN1_OCTET_STRING, \ + {EVP_PKEY_RSA,EVP_PKEY_RSA2,0,0} +# else +# define EVP_PKEY_RSA_method EVP_PKEY_NULL_method +# define EVP_PKEY_RSA_ASN1_OCTET_STRING_method EVP_PKEY_NULL_method +# endif + +# endif /* !EVP_MD */ + +struct env_md_ctx_st { + const EVP_MD *digest; + ENGINE *engine; /* functional reference if 'digest' is + * ENGINE-provided */ + unsigned long flags; + void *md_data; + /* Public key context for sign/verify */ + EVP_PKEY_CTX *pctx; + /* Update function: usually copied from EVP_MD */ + int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count); +} /* EVP_MD_CTX */ ; + +/* values for EVP_MD_CTX flags */ + +# define EVP_MD_CTX_FLAG_ONESHOT 0x0001/* digest update will be + * called once only */ +# define EVP_MD_CTX_FLAG_CLEANED 0x0002/* context has already been + * cleaned */ +# define EVP_MD_CTX_FLAG_REUSE 0x0004/* Don't free up ctx->md_data + * in EVP_MD_CTX_cleanup */ +/* + * FIPS and pad options are ignored in 1.0.0, definitions are here so we + * don't accidentally reuse the values for other purposes. + */ + +# define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008/* Allow use of non FIPS + * digest in FIPS mode */ + +/* + * The following PAD options are also currently ignored in 1.0.0, digest + * parameters are handled through EVP_DigestSign*() and EVP_DigestVerify*() + * instead. + */ +# define EVP_MD_CTX_FLAG_PAD_MASK 0xF0/* RSA mode to use */ +# define EVP_MD_CTX_FLAG_PAD_PKCS1 0x00/* PKCS#1 v1.5 mode */ +# define EVP_MD_CTX_FLAG_PAD_X931 0x10/* X9.31 mode */ +# define EVP_MD_CTX_FLAG_PAD_PSS 0x20/* PSS mode */ + +# define EVP_MD_CTX_FLAG_NO_INIT 0x0100/* Don't initialize md_data */ + +struct evp_cipher_st { + int nid; + int block_size; + /* Default value for variable length ciphers */ + int key_len; + int iv_len; + /* Various flags */ + unsigned long flags; + /* init key */ + int (*init) (EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); + /* encrypt/decrypt data */ + int (*do_cipher) (EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); + /* cleanup ctx */ + int (*cleanup) (EVP_CIPHER_CTX *); + /* how big ctx->cipher_data needs to be */ + int ctx_size; + /* Populate a ASN1_TYPE with parameters */ + int (*set_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *); + /* Get parameters from a ASN1_TYPE */ + int (*get_asn1_parameters) (EVP_CIPHER_CTX *, ASN1_TYPE *); + /* Miscellaneous operations */ + int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr); + /* Application data */ + void *app_data; +} /* EVP_CIPHER */ ; + +/* Values for cipher flags */ + +/* Modes for ciphers */ + +# define EVP_CIPH_STREAM_CIPHER 0x0 +# define EVP_CIPH_ECB_MODE 0x1 +# define EVP_CIPH_CBC_MODE 0x2 +# define EVP_CIPH_CFB_MODE 0x3 +# define EVP_CIPH_OFB_MODE 0x4 +# define EVP_CIPH_CTR_MODE 0x5 +# define EVP_CIPH_GCM_MODE 0x6 +# define EVP_CIPH_CCM_MODE 0x7 +# define EVP_CIPH_XTS_MODE 0x10001 +# define EVP_CIPH_WRAP_MODE 0x10002 +# define EVP_CIPH_MODE 0xF0007 +/* Set if variable length cipher */ +# define EVP_CIPH_VARIABLE_LENGTH 0x8 +/* Set if the iv handling should be done by the cipher itself */ +# define EVP_CIPH_CUSTOM_IV 0x10 +/* Set if the cipher's init() function should be called if key is NULL */ +# define EVP_CIPH_ALWAYS_CALL_INIT 0x20 +/* Call ctrl() to init cipher parameters */ +# define EVP_CIPH_CTRL_INIT 0x40 +/* Don't use standard key length function */ +# define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80 +/* Don't use standard block padding */ +# define EVP_CIPH_NO_PADDING 0x100 +/* cipher handles random key generation */ +# define EVP_CIPH_RAND_KEY 0x200 +/* cipher has its own additional copying logic */ +# define EVP_CIPH_CUSTOM_COPY 0x400 +/* Allow use default ASN1 get/set iv */ +# define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000 +/* Buffer length in bits not bytes: CFB1 mode only */ +# define EVP_CIPH_FLAG_LENGTH_BITS 0x2000 +/* Note if suitable for use in FIPS mode */ +# define EVP_CIPH_FLAG_FIPS 0x4000 +/* Allow non FIPS cipher in FIPS mode */ +# define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0x8000 +/* + * Cipher handles any and all padding logic as well as finalisation. + */ +# define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000 +# define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 +# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0x400000 + +/* + * Cipher context flag to indicate we can handle wrap mode: if allowed in + * older applications it could overflow buffers. + */ + +# define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0x1 + +/* ctrl() values */ + +# define EVP_CTRL_INIT 0x0 +# define EVP_CTRL_SET_KEY_LENGTH 0x1 +# define EVP_CTRL_GET_RC2_KEY_BITS 0x2 +# define EVP_CTRL_SET_RC2_KEY_BITS 0x3 +# define EVP_CTRL_GET_RC5_ROUNDS 0x4 +# define EVP_CTRL_SET_RC5_ROUNDS 0x5 +# define EVP_CTRL_RAND_KEY 0x6 +# define EVP_CTRL_PBE_PRF_NID 0x7 +# define EVP_CTRL_COPY 0x8 +# define EVP_CTRL_GCM_SET_IVLEN 0x9 +# define EVP_CTRL_GCM_GET_TAG 0x10 +# define EVP_CTRL_GCM_SET_TAG 0x11 +# define EVP_CTRL_GCM_SET_IV_FIXED 0x12 +# define EVP_CTRL_GCM_IV_GEN 0x13 +# define EVP_CTRL_CCM_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN +# define EVP_CTRL_CCM_GET_TAG EVP_CTRL_GCM_GET_TAG +# define EVP_CTRL_CCM_SET_TAG EVP_CTRL_GCM_SET_TAG +# define EVP_CTRL_CCM_SET_L 0x14 +# define EVP_CTRL_CCM_SET_MSGLEN 0x15 +/* + * AEAD cipher deduces payload length and returns number of bytes required to + * store MAC and eventual padding. Subsequent call to EVP_Cipher even + * appends/verifies MAC. + */ +# define EVP_CTRL_AEAD_TLS1_AAD 0x16 +/* Used by composite AEAD ciphers, no-op in GCM, CCM... */ +# define EVP_CTRL_AEAD_SET_MAC_KEY 0x17 +/* Set the GCM invocation field, decrypt only */ +# define EVP_CTRL_GCM_SET_IV_INV 0x18 + +# define EVP_CTRL_TLS1_1_MULTIBLOCK_AAD 0x19 +# define EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT 0x1a +# define EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT 0x1b +# define EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE 0x1c + +/* RFC 5246 defines additional data to be 13 bytes in length */ +# define EVP_AEAD_TLS1_AAD_LEN 13 + +typedef struct { + unsigned char *out; + const unsigned char *inp; + size_t len; + unsigned int interleave; +} EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM; + +/* GCM TLS constants */ +/* Length of fixed part of IV derived from PRF */ +# define EVP_GCM_TLS_FIXED_IV_LEN 4 +/* Length of explicit part of IV part of TLS records */ +# define EVP_GCM_TLS_EXPLICIT_IV_LEN 8 +/* Length of tag for TLS */ +# define EVP_GCM_TLS_TAG_LEN 16 + +typedef struct evp_cipher_info_st { + const EVP_CIPHER *cipher; + unsigned char iv[EVP_MAX_IV_LENGTH]; +} EVP_CIPHER_INFO; + +struct evp_cipher_ctx_st { + const EVP_CIPHER *cipher; + ENGINE *engine; /* functional reference if 'cipher' is + * ENGINE-provided */ + int encrypt; /* encrypt or decrypt */ + int buf_len; /* number we have left */ + unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */ + unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */ + unsigned char buf[EVP_MAX_BLOCK_LENGTH]; /* saved partial block */ + int num; /* used by cfb/ofb/ctr mode */ + void *app_data; /* application stuff */ + int key_len; /* May change for variable length cipher */ + unsigned long flags; /* Various flags */ + void *cipher_data; /* per EVP data */ + int final_used; + int block_mask; + unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */ +} /* EVP_CIPHER_CTX */ ; + +typedef struct evp_Encode_Ctx_st { + /* number saved in a partial encode/decode */ + int num; + /* + * The length is either the output line length (in input bytes) or the + * shortest input line length that is ok. Once decoding begins, the + * length is adjusted up each time a longer line is decoded + */ + int length; + /* data to encode */ + unsigned char enc_data[80]; + /* number read on current line */ + int line_num; + int expect_nl; +} EVP_ENCODE_CTX; + +/* Password based encryption function */ +typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass, + int passlen, ASN1_TYPE *param, + const EVP_CIPHER *cipher, const EVP_MD *md, + int en_de); + +# ifndef OPENSSL_NO_RSA +# define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ + (char *)(rsa)) +# endif + +# ifndef OPENSSL_NO_DSA +# define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ + (char *)(dsa)) +# endif + +# ifndef OPENSSL_NO_DH +# define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\ + (char *)(dh)) +# endif + +# ifndef OPENSSL_NO_EC +# define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\ + (char *)(eckey)) +# endif + +/* Add some extra combinations */ +# define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a)) +# define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a)) +# define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a)) +# define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a)) + +int EVP_MD_type(const EVP_MD *md); +# define EVP_MD_nid(e) EVP_MD_type(e) +# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e)) +int EVP_MD_pkey_type(const EVP_MD *md); +int EVP_MD_size(const EVP_MD *md); +int EVP_MD_block_size(const EVP_MD *md); +unsigned long EVP_MD_flags(const EVP_MD *md); + +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); +# define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e)) +# define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e)) +# define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e)) + +int EVP_CIPHER_nid(const EVP_CIPHER *cipher); +# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) +int EVP_CIPHER_block_size(const EVP_CIPHER *cipher); +int EVP_CIPHER_key_length(const EVP_CIPHER *cipher); +int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher); +unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher); +# define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE) + +const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); +void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); +void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data); +# define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c)) +unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx); +# define EVP_CIPHER_CTX_mode(e) (EVP_CIPHER_CTX_flags(e) & EVP_CIPH_MODE) + +# define EVP_ENCODE_LENGTH(l) (((l+2)/3*4)+(l/48+1)*2+80) +# define EVP_DECODE_LENGTH(l) ((l+3)/4*3+80) + +# define EVP_SignInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c) +# define EVP_SignInit(a,b) EVP_DigestInit(a,b) +# define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_VerifyInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c) +# define EVP_VerifyInit(a,b) EVP_DigestInit(a,b) +# define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e) +# define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e) +# define EVP_DigestSignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +# define EVP_DigestVerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) + +# ifdef CONST_STRICT +void BIO_set_md(BIO *, const EVP_MD *md); +# else +# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md) +# endif +# define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp) +# define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp) +# define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0,(char *)mdcp) +# define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL) +# define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp) + +int EVP_Cipher(EVP_CIPHER_CTX *c, + unsigned char *out, const unsigned char *in, unsigned int inl); + +# define EVP_add_cipher_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n)) +# define EVP_add_digest_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n)) +# define EVP_delete_cipher_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS); +# define EVP_delete_digest_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS); + +void EVP_MD_CTX_init(EVP_MD_CTX *ctx); +int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); +EVP_MD_CTX *EVP_MD_CTX_create(void); +void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); +int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); +void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags); +void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags); +int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags); +int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); +int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); +int EVP_Digest(const void *data, size_t count, + unsigned char *md, unsigned int *size, const EVP_MD *type, + ENGINE *impl); + +int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in); +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); +int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); + +int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify); +int EVP_read_pw_string_min(char *buf, int minlen, int maxlen, + const char *prompt, int verify); +void EVP_set_pw_prompt(const char *prompt); +char *EVP_get_pw_prompt(void); + +int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const unsigned char *salt, const unsigned char *data, + int datal, int count, unsigned char *key, + unsigned char *iv); + +void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags); +void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags); +int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags); + +int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, + const unsigned char *iv); +int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); +int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, + const unsigned char *iv); +int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); +int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); + +int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv, + int enc); +int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, + const unsigned char *iv, int enc); +int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); +int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); + +int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, + EVP_PKEY *pkey); + +int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, + unsigned int siglen, EVP_PKEY *pkey); + +int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); +int EVP_DigestSignFinal(EVP_MD_CTX *ctx, + unsigned char *sigret, size_t *siglen); + +int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, + const unsigned char *sig, size_t siglen); + +int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + const unsigned char *ek, int ekl, const unsigned char *iv, + EVP_PKEY *priv); +int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + unsigned char **ek, int *ekl, unsigned char *iv, + EVP_PKEY **pubk, int npubk); +int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); +void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl); +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n); + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned + char *out, int *outl); +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n); + +void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); +int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a); +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad); +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key); + +# ifndef OPENSSL_NO_BIO +BIO_METHOD *BIO_f_md(void); +BIO_METHOD *BIO_f_base64(void); +BIO_METHOD *BIO_f_cipher(void); +BIO_METHOD *BIO_f_reliable(void); +void BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, + const unsigned char *i, int enc); +# endif + +const EVP_MD *EVP_md_null(void); +# ifndef OPENSSL_NO_MD2 +const EVP_MD *EVP_md2(void); +# endif +# ifndef OPENSSL_NO_MD4 +const EVP_MD *EVP_md4(void); +# endif +# ifndef OPENSSL_NO_MD5 +const EVP_MD *EVP_md5(void); +# endif +# ifndef OPENSSL_NO_SHA +const EVP_MD *EVP_sha(void); +const EVP_MD *EVP_sha1(void); +const EVP_MD *EVP_dss(void); +const EVP_MD *EVP_dss1(void); +const EVP_MD *EVP_ecdsa(void); +# endif +# ifndef OPENSSL_NO_SHA256 +const EVP_MD *EVP_sha224(void); +const EVP_MD *EVP_sha256(void); +# endif +# ifndef OPENSSL_NO_SHA512 +const EVP_MD *EVP_sha384(void); +const EVP_MD *EVP_sha512(void); +# endif +# ifndef OPENSSL_NO_MDC2 +const EVP_MD *EVP_mdc2(void); +# endif +# ifndef OPENSSL_NO_RIPEMD +const EVP_MD *EVP_ripemd160(void); +# endif +# ifndef OPENSSL_NO_WHIRLPOOL +const EVP_MD *EVP_whirlpool(void); +# endif +const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ +# ifndef OPENSSL_NO_DES +const EVP_CIPHER *EVP_des_ecb(void); +const EVP_CIPHER *EVP_des_ede(void); +const EVP_CIPHER *EVP_des_ede3(void); +const EVP_CIPHER *EVP_des_ede_ecb(void); +const EVP_CIPHER *EVP_des_ede3_ecb(void); +const EVP_CIPHER *EVP_des_cfb64(void); +# define EVP_des_cfb EVP_des_cfb64 +const EVP_CIPHER *EVP_des_cfb1(void); +const EVP_CIPHER *EVP_des_cfb8(void); +const EVP_CIPHER *EVP_des_ede_cfb64(void); +# define EVP_des_ede_cfb EVP_des_ede_cfb64 +# if 0 +const EVP_CIPHER *EVP_des_ede_cfb1(void); +const EVP_CIPHER *EVP_des_ede_cfb8(void); +# endif +const EVP_CIPHER *EVP_des_ede3_cfb64(void); +# define EVP_des_ede3_cfb EVP_des_ede3_cfb64 +const EVP_CIPHER *EVP_des_ede3_cfb1(void); +const EVP_CIPHER *EVP_des_ede3_cfb8(void); +const EVP_CIPHER *EVP_des_ofb(void); +const EVP_CIPHER *EVP_des_ede_ofb(void); +const EVP_CIPHER *EVP_des_ede3_ofb(void); +const EVP_CIPHER *EVP_des_cbc(void); +const EVP_CIPHER *EVP_des_ede_cbc(void); +const EVP_CIPHER *EVP_des_ede3_cbc(void); +const EVP_CIPHER *EVP_desx_cbc(void); +const EVP_CIPHER *EVP_des_ede3_wrap(void); +/* + * This should now be supported through the dev_crypto ENGINE. But also, why + * are rc4 and md5 declarations made here inside a "NO_DES" precompiler + * branch? + */ +# if 0 +# ifdef OPENSSL_OPENBSD_DEV_CRYPTO +const EVP_CIPHER *EVP_dev_crypto_des_ede3_cbc(void); +const EVP_CIPHER *EVP_dev_crypto_rc4(void); +const EVP_MD *EVP_dev_crypto_md5(void); +# endif +# endif +# endif +# ifndef OPENSSL_NO_RC4 +const EVP_CIPHER *EVP_rc4(void); +const EVP_CIPHER *EVP_rc4_40(void); +# ifndef OPENSSL_NO_MD5 +const EVP_CIPHER *EVP_rc4_hmac_md5(void); +# endif +# endif +# ifndef OPENSSL_NO_IDEA +const EVP_CIPHER *EVP_idea_ecb(void); +const EVP_CIPHER *EVP_idea_cfb64(void); +# define EVP_idea_cfb EVP_idea_cfb64 +const EVP_CIPHER *EVP_idea_ofb(void); +const EVP_CIPHER *EVP_idea_cbc(void); +# endif +# ifndef OPENSSL_NO_RC2 +const EVP_CIPHER *EVP_rc2_ecb(void); +const EVP_CIPHER *EVP_rc2_cbc(void); +const EVP_CIPHER *EVP_rc2_40_cbc(void); +const EVP_CIPHER *EVP_rc2_64_cbc(void); +const EVP_CIPHER *EVP_rc2_cfb64(void); +# define EVP_rc2_cfb EVP_rc2_cfb64 +const EVP_CIPHER *EVP_rc2_ofb(void); +# endif +# ifndef OPENSSL_NO_BF +const EVP_CIPHER *EVP_bf_ecb(void); +const EVP_CIPHER *EVP_bf_cbc(void); +const EVP_CIPHER *EVP_bf_cfb64(void); +# define EVP_bf_cfb EVP_bf_cfb64 +const EVP_CIPHER *EVP_bf_ofb(void); +# endif +# ifndef OPENSSL_NO_CAST +const EVP_CIPHER *EVP_cast5_ecb(void); +const EVP_CIPHER *EVP_cast5_cbc(void); +const EVP_CIPHER *EVP_cast5_cfb64(void); +# define EVP_cast5_cfb EVP_cast5_cfb64 +const EVP_CIPHER *EVP_cast5_ofb(void); +# endif +# ifndef OPENSSL_NO_RC5 +const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void); +const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void); +const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void); +# define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64 +const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void); +# endif +# ifndef OPENSSL_NO_AES +const EVP_CIPHER *EVP_aes_128_ecb(void); +const EVP_CIPHER *EVP_aes_128_cbc(void); +const EVP_CIPHER *EVP_aes_128_cfb1(void); +const EVP_CIPHER *EVP_aes_128_cfb8(void); +const EVP_CIPHER *EVP_aes_128_cfb128(void); +# define EVP_aes_128_cfb EVP_aes_128_cfb128 +const EVP_CIPHER *EVP_aes_128_ofb(void); +const EVP_CIPHER *EVP_aes_128_ctr(void); +const EVP_CIPHER *EVP_aes_128_ccm(void); +const EVP_CIPHER *EVP_aes_128_gcm(void); +const EVP_CIPHER *EVP_aes_128_xts(void); +const EVP_CIPHER *EVP_aes_128_wrap(void); +const EVP_CIPHER *EVP_aes_192_ecb(void); +const EVP_CIPHER *EVP_aes_192_cbc(void); +const EVP_CIPHER *EVP_aes_192_cfb1(void); +const EVP_CIPHER *EVP_aes_192_cfb8(void); +const EVP_CIPHER *EVP_aes_192_cfb128(void); +# define EVP_aes_192_cfb EVP_aes_192_cfb128 +const EVP_CIPHER *EVP_aes_192_ofb(void); +const EVP_CIPHER *EVP_aes_192_ctr(void); +const EVP_CIPHER *EVP_aes_192_ccm(void); +const EVP_CIPHER *EVP_aes_192_gcm(void); +const EVP_CIPHER *EVP_aes_192_wrap(void); +const EVP_CIPHER *EVP_aes_256_ecb(void); +const EVP_CIPHER *EVP_aes_256_cbc(void); +const EVP_CIPHER *EVP_aes_256_cfb1(void); +const EVP_CIPHER *EVP_aes_256_cfb8(void); +const EVP_CIPHER *EVP_aes_256_cfb128(void); +# define EVP_aes_256_cfb EVP_aes_256_cfb128 +const EVP_CIPHER *EVP_aes_256_ofb(void); +const EVP_CIPHER *EVP_aes_256_ctr(void); +const EVP_CIPHER *EVP_aes_256_ccm(void); +const EVP_CIPHER *EVP_aes_256_gcm(void); +const EVP_CIPHER *EVP_aes_256_xts(void); +const EVP_CIPHER *EVP_aes_256_wrap(void); +# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1) +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void); +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void); +# endif +# ifndef OPENSSL_NO_SHA256 +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void); +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void); +# endif +# endif +# ifndef OPENSSL_NO_CAMELLIA +const EVP_CIPHER *EVP_camellia_128_ecb(void); +const EVP_CIPHER *EVP_camellia_128_cbc(void); +const EVP_CIPHER *EVP_camellia_128_cfb1(void); +const EVP_CIPHER *EVP_camellia_128_cfb8(void); +const EVP_CIPHER *EVP_camellia_128_cfb128(void); +# define EVP_camellia_128_cfb EVP_camellia_128_cfb128 +const EVP_CIPHER *EVP_camellia_128_ofb(void); +const EVP_CIPHER *EVP_camellia_192_ecb(void); +const EVP_CIPHER *EVP_camellia_192_cbc(void); +const EVP_CIPHER *EVP_camellia_192_cfb1(void); +const EVP_CIPHER *EVP_camellia_192_cfb8(void); +const EVP_CIPHER *EVP_camellia_192_cfb128(void); +# define EVP_camellia_192_cfb EVP_camellia_192_cfb128 +const EVP_CIPHER *EVP_camellia_192_ofb(void); +const EVP_CIPHER *EVP_camellia_256_ecb(void); +const EVP_CIPHER *EVP_camellia_256_cbc(void); +const EVP_CIPHER *EVP_camellia_256_cfb1(void); +const EVP_CIPHER *EVP_camellia_256_cfb8(void); +const EVP_CIPHER *EVP_camellia_256_cfb128(void); +# define EVP_camellia_256_cfb EVP_camellia_256_cfb128 +const EVP_CIPHER *EVP_camellia_256_ofb(void); +# endif + +# ifndef OPENSSL_NO_SEED +const EVP_CIPHER *EVP_seed_ecb(void); +const EVP_CIPHER *EVP_seed_cbc(void); +const EVP_CIPHER *EVP_seed_cfb128(void); +# define EVP_seed_cfb EVP_seed_cfb128 +const EVP_CIPHER *EVP_seed_ofb(void); +# endif + +void OPENSSL_add_all_algorithms_noconf(void); +void OPENSSL_add_all_algorithms_conf(void); + +# ifdef OPENSSL_LOAD_CONF +# define OpenSSL_add_all_algorithms() \ + OPENSSL_add_all_algorithms_conf() +# else +# define OpenSSL_add_all_algorithms() \ + OPENSSL_add_all_algorithms_noconf() +# endif + +void OpenSSL_add_all_ciphers(void); +void OpenSSL_add_all_digests(void); +# define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms() +# define SSLeay_add_all_ciphers() OpenSSL_add_all_ciphers() +# define SSLeay_add_all_digests() OpenSSL_add_all_digests() + +int EVP_add_cipher(const EVP_CIPHER *cipher); +int EVP_add_digest(const EVP_MD *digest); + +const EVP_CIPHER *EVP_get_cipherbyname(const char *name); +const EVP_MD *EVP_get_digestbyname(const char *name); +void EVP_cleanup(void); + +void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph, + const char *from, const char *to, void *x), + void *arg); +void EVP_CIPHER_do_all_sorted(void (*fn) + (const EVP_CIPHER *ciph, const char *from, + const char *to, void *x), void *arg); + +void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph, + const char *from, const char *to, void *x), + void *arg); +void EVP_MD_do_all_sorted(void (*fn) + (const EVP_MD *ciph, const char *from, + const char *to, void *x), void *arg); + +int EVP_PKEY_decrypt_old(unsigned char *dec_key, + const unsigned char *enc_key, int enc_key_len, + EVP_PKEY *private_key); +int EVP_PKEY_encrypt_old(unsigned char *enc_key, + const unsigned char *key, int key_len, + EVP_PKEY *pub_key); +int EVP_PKEY_type(int type); +int EVP_PKEY_id(const EVP_PKEY *pkey); +int EVP_PKEY_base_id(const EVP_PKEY *pkey); +int EVP_PKEY_bits(EVP_PKEY *pkey); +int EVP_PKEY_size(EVP_PKEY *pkey); +int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); +int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); +void *EVP_PKEY_get0(EVP_PKEY *pkey); + +# ifndef OPENSSL_NO_RSA +struct rsa_st; +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key); +struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_DSA +struct dsa_st; +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, struct dsa_st *key); +struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_DH +struct dh_st; +int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key); +struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey); +# endif +# ifndef OPENSSL_NO_EC +struct ec_key_st; +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key); +struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); +# endif + +EVP_PKEY *EVP_PKEY_new(void); +void EVP_PKEY_free(EVP_PKEY *pkey); + +EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length); +int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp); + +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length); +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, + long length); +int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp); + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); +int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey); +int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode); +int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b); + +int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); + +int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); +int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); +int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx); + +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid); + +int EVP_CIPHER_type(const EVP_CIPHER *ctx); + +/* calls methods */ +int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* These are used by EVP_CIPHER methods */ +int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* PKCS5 password based encryption */ +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de); +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + int keylen, unsigned char *out); +int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, + const EVP_MD *digest, int keylen, unsigned char *out); +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md, int en_de); + +void PKCS5_PBE_add(void); + +int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de); + +/* PBE type */ + +/* Can appear as the outermost AlgorithmIdentifier */ +# define EVP_PBE_TYPE_OUTER 0x0 +/* Is an PRF type OID */ +# define EVP_PBE_TYPE_PRF 0x1 + +int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, + int md_nid, EVP_PBE_KEYGEN *keygen); +int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, + EVP_PBE_KEYGEN *keygen); +int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid, + EVP_PBE_KEYGEN **pkeygen); +void EVP_PBE_cleanup(void); + +# define ASN1_PKEY_ALIAS 0x1 +# define ASN1_PKEY_DYNAMIC 0x2 +# define ASN1_PKEY_SIGPARAM_NULL 0x4 + +# define ASN1_PKEY_CTRL_PKCS7_SIGN 0x1 +# define ASN1_PKEY_CTRL_PKCS7_ENCRYPT 0x2 +# define ASN1_PKEY_CTRL_DEFAULT_MD_NID 0x3 +# define ASN1_PKEY_CTRL_CMS_SIGN 0x5 +# define ASN1_PKEY_CTRL_CMS_ENVELOPE 0x7 +# define ASN1_PKEY_CTRL_CMS_RI_TYPE 0x8 + +int EVP_PKEY_asn1_get_count(void); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, + const char *str, int len); +int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth); +int EVP_PKEY_asn1_add_alias(int to, int from); +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id, + int *ppkey_flags, const char **pinfo, + const char **ppem_str, + const EVP_PKEY_ASN1_METHOD *ameth); + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(EVP_PKEY *pkey); +EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags, + const char *pem_str, + const char *info); +void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, + const EVP_PKEY_ASN1_METHOD *src); +void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth); +void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, + int (*pub_decode) (EVP_PKEY *pk, + X509_PUBKEY *pub), + int (*pub_encode) (X509_PUBKEY *pub, + const EVP_PKEY *pk), + int (*pub_cmp) (const EVP_PKEY *a, + const EVP_PKEY *b), + int (*pub_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, ASN1_PCTX *pctx), + int (*pkey_size) (const EVP_PKEY *pk), + int (*pkey_bits) (const EVP_PKEY *pk)); +void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, + int (*priv_decode) (EVP_PKEY *pk, + PKCS8_PRIV_KEY_INFO + *p8inf), + int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8, + const EVP_PKEY *pk), + int (*priv_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, + ASN1_PCTX *pctx)); +void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, + int (*param_decode) (EVP_PKEY *pkey, + const unsigned char **pder, + int derlen), + int (*param_encode) (const EVP_PKEY *pkey, + unsigned char **pder), + int (*param_missing) (const EVP_PKEY *pk), + int (*param_copy) (EVP_PKEY *to, + const EVP_PKEY *from), + int (*param_cmp) (const EVP_PKEY *a, + const EVP_PKEY *b), + int (*param_print) (BIO *out, + const EVP_PKEY *pkey, + int indent, + ASN1_PCTX *pctx)); + +void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, + void (*pkey_free) (EVP_PKEY *pkey)); +void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_ctrl) (EVP_PKEY *pkey, int op, + long arg1, void *arg2)); +void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth, + int (*item_verify) (EVP_MD_CTX *ctx, + const ASN1_ITEM *it, + void *asn, + X509_ALGOR *a, + ASN1_BIT_STRING *sig, + EVP_PKEY *pkey), + int (*item_sign) (EVP_MD_CTX *ctx, + const ASN1_ITEM *it, + void *asn, + X509_ALGOR *alg1, + X509_ALGOR *alg2, + ASN1_BIT_STRING *sig)); + +# define EVP_PKEY_OP_UNDEFINED 0 +# define EVP_PKEY_OP_PARAMGEN (1<<1) +# define EVP_PKEY_OP_KEYGEN (1<<2) +# define EVP_PKEY_OP_SIGN (1<<3) +# define EVP_PKEY_OP_VERIFY (1<<4) +# define EVP_PKEY_OP_VERIFYRECOVER (1<<5) +# define EVP_PKEY_OP_SIGNCTX (1<<6) +# define EVP_PKEY_OP_VERIFYCTX (1<<7) +# define EVP_PKEY_OP_ENCRYPT (1<<8) +# define EVP_PKEY_OP_DECRYPT (1<<9) +# define EVP_PKEY_OP_DERIVE (1<<10) + +# define EVP_PKEY_OP_TYPE_SIG \ + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER \ + | EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX) + +# define EVP_PKEY_OP_TYPE_CRYPT \ + (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT) + +# define EVP_PKEY_OP_TYPE_NOGEN \ + (EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE) + +# define EVP_PKEY_OP_TYPE_GEN \ + (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN) + +# define EVP_PKEY_CTX_set_signature_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ + EVP_PKEY_CTRL_MD, 0, (void *)md) + +# define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ + EVP_PKEY_CTRL_GET_MD, 0, (void *)pmd) + +# define EVP_PKEY_CTRL_MD 1 +# define EVP_PKEY_CTRL_PEER_KEY 2 + +# define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3 +# define EVP_PKEY_CTRL_PKCS7_DECRYPT 4 + +# define EVP_PKEY_CTRL_PKCS7_SIGN 5 + +# define EVP_PKEY_CTRL_SET_MAC_KEY 6 + +# define EVP_PKEY_CTRL_DIGESTINIT 7 + +/* Used by GOST key encryption in TLS */ +# define EVP_PKEY_CTRL_SET_IV 8 + +# define EVP_PKEY_CTRL_CMS_ENCRYPT 9 +# define EVP_PKEY_CTRL_CMS_DECRYPT 10 +# define EVP_PKEY_CTRL_CMS_SIGN 11 + +# define EVP_PKEY_CTRL_CIPHER 12 + +# define EVP_PKEY_CTRL_GET_MD 13 + +# define EVP_PKEY_ALG_CTRL 0x1000 + +# define EVP_PKEY_FLAG_AUTOARGLEN 2 +/* + * Method handles all operations: don't assume any digest related defaults. + */ +# define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4 + +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type); +EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags); +void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, + const EVP_PKEY_METHOD *meth); +void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src); +void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth); +int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth); + +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); +EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx); +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, + int cmd, int p1, void *p2); +int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value); + +int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx); +void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen); + +EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, + const unsigned char *key, int keylen); + +void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data); +void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx); +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); + +EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx); + +void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data); +void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, + unsigned char *rout, size_t *routlen, + const unsigned char *sig, size_t siglen); +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + +int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); +int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + +typedef int EVP_PKEY_gen_cb (EVP_PKEY_CTX *ctx); + +int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); + +void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb); +EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx); + +void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth, + int (*init) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth, + int (*copy) (EVP_PKEY_CTX *dst, + EVP_PKEY_CTX *src)); + +void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth, + void (*cleanup) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth, + int (*paramgen_init) (EVP_PKEY_CTX *ctx), + int (*paramgen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth, + int (*keygen_init) (EVP_PKEY_CTX *ctx), + int (*keygen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, + int (*sign_init) (EVP_PKEY_CTX *ctx), + int (*sign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, + int (*verify_init) (EVP_PKEY_CTX *ctx), + int (*verify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, + int (*verify_recover_init) (EVP_PKEY_CTX + *ctx), + int (*verify_recover) (EVP_PKEY_CTX + *ctx, + unsigned char + *sig, + size_t *siglen, + const unsigned + char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth, + int (*signctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (*signctx) (EVP_PKEY_CTX *ctx, + unsigned char *sig, + size_t *siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth, + int (*verifyctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (*verifyctx) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + int siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, + int (*encrypt_init) (EVP_PKEY_CTX *ctx), + int (*encryptfn) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, + int (*decrypt_init) (EVP_PKEY_CTX *ctx), + int (*decrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth, + int (*derive_init) (EVP_PKEY_CTX *ctx), + int (*derive) (EVP_PKEY_CTX *ctx, + unsigned char *key, + size_t *keylen)); + +void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, + int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, + void *p2), + int (*ctrl_str) (EVP_PKEY_CTX *ctx, + const char *type, + const char *value)); + +void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth, + int (**pinit) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_get_copy(EVP_PKEY_METHOD *pmeth, + int (**pcopy) (EVP_PKEY_CTX *dst, + EVP_PKEY_CTX *src)); + +void EVP_PKEY_meth_get_cleanup(EVP_PKEY_METHOD *pmeth, + void (**pcleanup) (EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_get_paramgen(EVP_PKEY_METHOD *pmeth, + int (**pparamgen_init) (EVP_PKEY_CTX *ctx), + int (**pparamgen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_keygen(EVP_PKEY_METHOD *pmeth, + int (**pkeygen_init) (EVP_PKEY_CTX *ctx), + int (**pkeygen) (EVP_PKEY_CTX *ctx, + EVP_PKEY *pkey)); + +void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, + int (**psign_init) (EVP_PKEY_CTX *ctx), + int (**psign) (EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_verify(EVP_PKEY_METHOD *pmeth, + int (**pverify_init) (EVP_PKEY_CTX *ctx), + int (**pverify) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + size_t siglen, + const unsigned char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_verify_recover(EVP_PKEY_METHOD *pmeth, + int (**pverify_recover_init) (EVP_PKEY_CTX + *ctx), + int (**pverify_recover) (EVP_PKEY_CTX + *ctx, + unsigned char + *sig, + size_t *siglen, + const unsigned + char *tbs, + size_t tbslen)); + +void EVP_PKEY_meth_get_signctx(EVP_PKEY_METHOD *pmeth, + int (**psignctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (**psignctx) (EVP_PKEY_CTX *ctx, + unsigned char *sig, + size_t *siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_get_verifyctx(EVP_PKEY_METHOD *pmeth, + int (**pverifyctx_init) (EVP_PKEY_CTX *ctx, + EVP_MD_CTX *mctx), + int (**pverifyctx) (EVP_PKEY_CTX *ctx, + const unsigned char *sig, + int siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_get_encrypt(EVP_PKEY_METHOD *pmeth, + int (**pencrypt_init) (EVP_PKEY_CTX *ctx), + int (**pencryptfn) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth, + int (**pdecrypt_init) (EVP_PKEY_CTX *ctx), + int (**pdecrypt) (EVP_PKEY_CTX *ctx, + unsigned char *out, + size_t *outlen, + const unsigned char *in, + size_t inlen)); + +void EVP_PKEY_meth_get_derive(EVP_PKEY_METHOD *pmeth, + int (**pderive_init) (EVP_PKEY_CTX *ctx), + int (**pderive) (EVP_PKEY_CTX *ctx, + unsigned char *key, + size_t *keylen)); + +void EVP_PKEY_meth_get_ctrl(EVP_PKEY_METHOD *pmeth, + int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1, + void *p2), + int (**pctrl_str) (EVP_PKEY_CTX *ctx, + const char *type, + const char *value)); + +void EVP_add_alg_module(void); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +void ERR_load_EVP_strings(void); + +/* Error codes for the EVP functions. */ + +/* Function codes. */ +# define EVP_F_AESNI_INIT_KEY 165 +# define EVP_F_AESNI_XTS_CIPHER 176 +# define EVP_F_AES_INIT_KEY 133 +# define EVP_F_AES_T4_INIT_KEY 178 +# define EVP_F_AES_XTS 172 +# define EVP_F_AES_XTS_CIPHER 175 +# define EVP_F_ALG_MODULE_INIT 177 +# define EVP_F_CAMELLIA_INIT_KEY 159 +# define EVP_F_CMAC_INIT 173 +# define EVP_F_CMLL_T4_INIT_KEY 179 +# define EVP_F_D2I_PKEY 100 +# define EVP_F_DO_SIGVER_INIT 161 +# define EVP_F_DSAPKEY2PKCS8 134 +# define EVP_F_DSA_PKEY2PKCS8 135 +# define EVP_F_ECDSA_PKEY2PKCS8 129 +# define EVP_F_ECKEY_PKEY2PKCS8 132 +# define EVP_F_EVP_CIPHERINIT_EX 123 +# define EVP_F_EVP_CIPHER_CTX_COPY 163 +# define EVP_F_EVP_CIPHER_CTX_CTRL 124 +# define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122 +# define EVP_F_EVP_DECRYPTFINAL_EX 101 +# define EVP_F_EVP_DIGESTINIT_EX 128 +# define EVP_F_EVP_ENCRYPTFINAL_EX 127 +# define EVP_F_EVP_MD_CTX_COPY_EX 110 +# define EVP_F_EVP_MD_SIZE 162 +# define EVP_F_EVP_OPENINIT 102 +# define EVP_F_EVP_PBE_ALG_ADD 115 +# define EVP_F_EVP_PBE_ALG_ADD_TYPE 160 +# define EVP_F_EVP_PBE_CIPHERINIT 116 +# define EVP_F_EVP_PKCS82PKEY 111 +# define EVP_F_EVP_PKCS82PKEY_BROKEN 136 +# define EVP_F_EVP_PKEY2PKCS8_BROKEN 113 +# define EVP_F_EVP_PKEY_COPY_PARAMETERS 103 +# define EVP_F_EVP_PKEY_CTX_CTRL 137 +# define EVP_F_EVP_PKEY_CTX_CTRL_STR 150 +# define EVP_F_EVP_PKEY_CTX_DUP 156 +# define EVP_F_EVP_PKEY_DECRYPT 104 +# define EVP_F_EVP_PKEY_DECRYPT_INIT 138 +# define EVP_F_EVP_PKEY_DECRYPT_OLD 151 +# define EVP_F_EVP_PKEY_DERIVE 153 +# define EVP_F_EVP_PKEY_DERIVE_INIT 154 +# define EVP_F_EVP_PKEY_DERIVE_SET_PEER 155 +# define EVP_F_EVP_PKEY_ENCRYPT 105 +# define EVP_F_EVP_PKEY_ENCRYPT_INIT 139 +# define EVP_F_EVP_PKEY_ENCRYPT_OLD 152 +# define EVP_F_EVP_PKEY_GET1_DH 119 +# define EVP_F_EVP_PKEY_GET1_DSA 120 +# define EVP_F_EVP_PKEY_GET1_ECDSA 130 +# define EVP_F_EVP_PKEY_GET1_EC_KEY 131 +# define EVP_F_EVP_PKEY_GET1_RSA 121 +# define EVP_F_EVP_PKEY_KEYGEN 146 +# define EVP_F_EVP_PKEY_KEYGEN_INIT 147 +# define EVP_F_EVP_PKEY_NEW 106 +# define EVP_F_EVP_PKEY_PARAMGEN 148 +# define EVP_F_EVP_PKEY_PARAMGEN_INIT 149 +# define EVP_F_EVP_PKEY_SIGN 140 +# define EVP_F_EVP_PKEY_SIGN_INIT 141 +# define EVP_F_EVP_PKEY_VERIFY 142 +# define EVP_F_EVP_PKEY_VERIFY_INIT 143 +# define EVP_F_EVP_PKEY_VERIFY_RECOVER 144 +# define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT 145 +# define EVP_F_EVP_RIJNDAEL 126 +# define EVP_F_EVP_SIGNFINAL 107 +# define EVP_F_EVP_VERIFYFINAL 108 +# define EVP_F_FIPS_CIPHERINIT 166 +# define EVP_F_FIPS_CIPHER_CTX_COPY 170 +# define EVP_F_FIPS_CIPHER_CTX_CTRL 167 +# define EVP_F_FIPS_CIPHER_CTX_SET_KEY_LENGTH 171 +# define EVP_F_FIPS_DIGESTINIT 168 +# define EVP_F_FIPS_MD_CTX_COPY 169 +# define EVP_F_HMAC_INIT_EX 174 +# define EVP_F_INT_CTX_NEW 157 +# define EVP_F_PKCS5_PBE_KEYIVGEN 117 +# define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118 +# define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN 164 +# define EVP_F_PKCS8_SET_BROKEN 112 +# define EVP_F_PKEY_SET_TYPE 158 +# define EVP_F_RC2_MAGIC_TO_METH 109 +# define EVP_F_RC5_CTRL 125 + +/* Reason codes. */ +# define EVP_R_AES_IV_SETUP_FAILED 162 +# define EVP_R_AES_KEY_SETUP_FAILED 143 +# define EVP_R_ASN1_LIB 140 +# define EVP_R_BAD_BLOCK_LENGTH 136 +# define EVP_R_BAD_DECRYPT 100 +# define EVP_R_BAD_KEY_LENGTH 137 +# define EVP_R_BN_DECODE_ERROR 112 +# define EVP_R_BN_PUBKEY_ERROR 113 +# define EVP_R_BUFFER_TOO_SMALL 155 +# define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157 +# define EVP_R_CIPHER_PARAMETER_ERROR 122 +# define EVP_R_COMMAND_NOT_SUPPORTED 147 +# define EVP_R_CTRL_NOT_IMPLEMENTED 132 +# define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133 +# define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138 +# define EVP_R_DECODE_ERROR 114 +# define EVP_R_DIFFERENT_KEY_TYPES 101 +# define EVP_R_DIFFERENT_PARAMETERS 153 +# define EVP_R_DISABLED_FOR_FIPS 163 +# define EVP_R_ENCODE_ERROR 115 +# define EVP_R_ERROR_LOADING_SECTION 165 +# define EVP_R_ERROR_SETTING_FIPS_MODE 166 +# define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119 +# define EVP_R_EXPECTING_AN_RSA_KEY 127 +# define EVP_R_EXPECTING_A_DH_KEY 128 +# define EVP_R_EXPECTING_A_DSA_KEY 129 +# define EVP_R_EXPECTING_A_ECDSA_KEY 141 +# define EVP_R_EXPECTING_A_EC_KEY 142 +# define EVP_R_FIPS_MODE_NOT_SUPPORTED 167 +# define EVP_R_INITIALIZATION_ERROR 134 +# define EVP_R_INPUT_NOT_INITIALIZED 111 +# define EVP_R_INVALID_DIGEST 152 +# define EVP_R_INVALID_FIPS_MODE 168 +# define EVP_R_INVALID_KEY 171 +# define EVP_R_INVALID_KEY_LENGTH 130 +# define EVP_R_INVALID_OPERATION 148 +# define EVP_R_IV_TOO_LARGE 102 +# define EVP_R_KEYGEN_FAILURE 120 +# define EVP_R_MESSAGE_DIGEST_IS_NULL 159 +# define EVP_R_METHOD_NOT_SUPPORTED 144 +# define EVP_R_MISSING_PARAMETERS 103 +# define EVP_R_NO_CIPHER_SET 131 +# define EVP_R_NO_DEFAULT_DIGEST 158 +# define EVP_R_NO_DIGEST_SET 139 +# define EVP_R_NO_DSA_PARAMETERS 116 +# define EVP_R_NO_KEY_SET 154 +# define EVP_R_NO_OPERATION_SET 149 +# define EVP_R_NO_SIGN_FUNCTION_CONFIGURED 104 +# define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED 105 +# define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 150 +# define EVP_R_OPERATON_NOT_INITIALIZED 151 +# define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE 117 +# define EVP_R_PRIVATE_KEY_DECODE_ERROR 145 +# define EVP_R_PRIVATE_KEY_ENCODE_ERROR 146 +# define EVP_R_PUBLIC_KEY_NOT_RSA 106 +# define EVP_R_TOO_LARGE 164 +# define EVP_R_UNKNOWN_CIPHER 160 +# define EVP_R_UNKNOWN_DIGEST 161 +# define EVP_R_UNKNOWN_OPTION 169 +# define EVP_R_UNKNOWN_PBE_ALGORITHM 121 +# define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS 135 +# define EVP_R_UNSUPPORTED_ALGORITHM 156 +# define EVP_R_UNSUPPORTED_CIPHER 107 +# define EVP_R_UNSUPPORTED_KEYLENGTH 123 +# define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124 +# define EVP_R_UNSUPPORTED_KEY_SIZE 108 +# define EVP_R_UNSUPPORTED_PRF 125 +# define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118 +# define EVP_R_UNSUPPORTED_SALT_TYPE 126 +# define EVP_R_WRAP_MODE_NOT_ALLOWED 170 +# define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109 +# define EVP_R_WRONG_PUBLIC_KEY_TYPE 110 + +# ifdef __cplusplus +} +# endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/hmac.h b/optee/optee_test/host/openssl/include/openssl/hmac.h new file mode 100644 index 0000000..b8b55cd --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/hmac.h @@ -0,0 +1,109 @@ +/* crypto/hmac/hmac.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +#ifndef HEADER_HMAC_H +# define HEADER_HMAC_H + +# include + +# ifdef OPENSSL_NO_HMAC +# error HMAC is disabled. +# endif + +# include + +# define HMAC_MAX_MD_CBLOCK 128/* largest known is SHA512 */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct hmac_ctx_st { + const EVP_MD *md; + EVP_MD_CTX md_ctx; + EVP_MD_CTX i_ctx; + EVP_MD_CTX o_ctx; + unsigned int key_length; + unsigned char key[HMAC_MAX_MD_CBLOCK]; +} HMAC_CTX; + +# define HMAC_size(e) (EVP_MD_size((e)->md)) + +void HMAC_CTX_init(HMAC_CTX *ctx); +void HMAC_CTX_cleanup(HMAC_CTX *ctx); + +/* deprecated */ +# define HMAC_cleanup(ctx) HMAC_CTX_cleanup(ctx) + +/* deprecated */ +int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md); +int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md, ENGINE *impl); +int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len); +int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len); +unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, + const unsigned char *d, size_t n, unsigned char *md, + unsigned int *md_len); +int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx); + +void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/idea.h b/optee/optee_test/host/openssl/include/openssl/idea.h new file mode 100644 index 0000000..6075984 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/idea.h @@ -0,0 +1,105 @@ +/* crypto/idea/idea.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_IDEA_H +# define HEADER_IDEA_H + +# include /* IDEA_INT, OPENSSL_NO_IDEA */ + +# ifdef OPENSSL_NO_IDEA +# error IDEA is disabled. +# endif + +# define IDEA_ENCRYPT 1 +# define IDEA_DECRYPT 0 + +# define IDEA_BLOCK 8 +# define IDEA_KEY_LENGTH 16 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct idea_key_st { + IDEA_INT data[9][6]; +} IDEA_KEY_SCHEDULE; + +const char *idea_options(void); +void idea_ecb_encrypt(const unsigned char *in, unsigned char *out, + IDEA_KEY_SCHEDULE *ks); +# ifdef OPENSSL_FIPS +void private_idea_set_encrypt_key(const unsigned char *key, + IDEA_KEY_SCHEDULE *ks); +# endif +void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks); +void idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk); +void idea_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int enc); +void idea_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num, int enc); +void idea_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num); +void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/krb5_asn.h b/optee/optee_test/host/openssl/include/openssl/krb5_asn.h new file mode 100644 index 0000000..9cf5a26 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/krb5_asn.h @@ -0,0 +1,240 @@ +/* krb5_asn.h */ +/* + * Written by Vern Staats for the OpenSSL project, ** + * using ocsp/{*.h,*asn*.c} as a starting point + */ + +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_KRB5_ASN_H +# define HEADER_KRB5_ASN_H + +/* + * #include + */ +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ASN.1 from Kerberos RFC 1510 + */ + +/*- EncryptedData ::= SEQUENCE { + * etype[0] INTEGER, -- EncryptionType + * kvno[1] INTEGER OPTIONAL, + * cipher[2] OCTET STRING -- ciphertext + * } + */ +typedef struct krb5_encdata_st { + ASN1_INTEGER *etype; + ASN1_INTEGER *kvno; + ASN1_OCTET_STRING *cipher; +} KRB5_ENCDATA; + +DECLARE_STACK_OF(KRB5_ENCDATA) + +/*- PrincipalName ::= SEQUENCE { + * name-type[0] INTEGER, + * name-string[1] SEQUENCE OF GeneralString + * } + */ +typedef struct krb5_princname_st { + ASN1_INTEGER *nametype; + STACK_OF(ASN1_GENERALSTRING) *namestring; +} KRB5_PRINCNAME; + +DECLARE_STACK_OF(KRB5_PRINCNAME) + +/*- Ticket ::= [APPLICATION 1] SEQUENCE { + * tkt-vno[0] INTEGER, + * realm[1] Realm, + * sname[2] PrincipalName, + * enc-part[3] EncryptedData + * } + */ +typedef struct krb5_tktbody_st { + ASN1_INTEGER *tktvno; + ASN1_GENERALSTRING *realm; + KRB5_PRINCNAME *sname; + KRB5_ENCDATA *encdata; +} KRB5_TKTBODY; + +typedef STACK_OF(KRB5_TKTBODY) KRB5_TICKET; +DECLARE_STACK_OF(KRB5_TKTBODY) + +/*- AP-REQ ::= [APPLICATION 14] SEQUENCE { + * pvno[0] INTEGER, + * msg-type[1] INTEGER, + * ap-options[2] APOptions, + * ticket[3] Ticket, + * authenticator[4] EncryptedData + * } + * + * APOptions ::= BIT STRING { + * reserved(0), use-session-key(1), mutual-required(2) } + */ +typedef struct krb5_ap_req_st { + ASN1_INTEGER *pvno; + ASN1_INTEGER *msgtype; + ASN1_BIT_STRING *apoptions; + KRB5_TICKET *ticket; + KRB5_ENCDATA *authenticator; +} KRB5_APREQBODY; + +typedef STACK_OF(KRB5_APREQBODY) KRB5_APREQ; +DECLARE_STACK_OF(KRB5_APREQBODY) + +/* Authenticator Stuff */ + +/*- Checksum ::= SEQUENCE { + * cksumtype[0] INTEGER, + * checksum[1] OCTET STRING + * } + */ +typedef struct krb5_checksum_st { + ASN1_INTEGER *ctype; + ASN1_OCTET_STRING *checksum; +} KRB5_CHECKSUM; + +DECLARE_STACK_OF(KRB5_CHECKSUM) + +/*- EncryptionKey ::= SEQUENCE { + * keytype[0] INTEGER, + * keyvalue[1] OCTET STRING + * } + */ +typedef struct krb5_encryptionkey_st { + ASN1_INTEGER *ktype; + ASN1_OCTET_STRING *keyvalue; +} KRB5_ENCKEY; + +DECLARE_STACK_OF(KRB5_ENCKEY) + +/*- AuthorizationData ::= SEQUENCE OF SEQUENCE { + * ad-type[0] INTEGER, + * ad-data[1] OCTET STRING + * } + */ +typedef struct krb5_authorization_st { + ASN1_INTEGER *adtype; + ASN1_OCTET_STRING *addata; +} KRB5_AUTHDATA; + +DECLARE_STACK_OF(KRB5_AUTHDATA) + +/*- -- Unencrypted authenticator + * Authenticator ::= [APPLICATION 2] SEQUENCE { + * authenticator-vno[0] INTEGER, + * crealm[1] Realm, + * cname[2] PrincipalName, + * cksum[3] Checksum OPTIONAL, + * cusec[4] INTEGER, + * ctime[5] KerberosTime, + * subkey[6] EncryptionKey OPTIONAL, + * seq-number[7] INTEGER OPTIONAL, + * authorization-data[8] AuthorizationData OPTIONAL + * } + */ +typedef struct krb5_authenticator_st { + ASN1_INTEGER *avno; + ASN1_GENERALSTRING *crealm; + KRB5_PRINCNAME *cname; + KRB5_CHECKSUM *cksum; + ASN1_INTEGER *cusec; + ASN1_GENERALIZEDTIME *ctime; + KRB5_ENCKEY *subkey; + ASN1_INTEGER *seqnum; + KRB5_AUTHDATA *authorization; +} KRB5_AUTHENTBODY; + +typedef STACK_OF(KRB5_AUTHENTBODY) KRB5_AUTHENT; +DECLARE_STACK_OF(KRB5_AUTHENTBODY) + +/*- DECLARE_ASN1_FUNCTIONS(type) = DECLARE_ASN1_FUNCTIONS_name(type, type) = + * type *name##_new(void); + * void name##_free(type *a); + * DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) = + * DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) = + * type *d2i_##name(type **a, const unsigned char **in, long len); + * int i2d_##name(type *a, unsigned char **out); + * DECLARE_ASN1_ITEM(itname) = OPENSSL_EXTERN const ASN1_ITEM itname##_it + */ + +DECLARE_ASN1_FUNCTIONS(KRB5_ENCDATA) +DECLARE_ASN1_FUNCTIONS(KRB5_PRINCNAME) +DECLARE_ASN1_FUNCTIONS(KRB5_TKTBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_APREQBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_TICKET) +DECLARE_ASN1_FUNCTIONS(KRB5_APREQ) + +DECLARE_ASN1_FUNCTIONS(KRB5_CHECKSUM) +DECLARE_ASN1_FUNCTIONS(KRB5_ENCKEY) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHDATA) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENTBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENT) + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/kssl.h b/optee/optee_test/host/openssl/include/openssl/kssl.h new file mode 100644 index 0000000..ae8a51f --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/kssl.h @@ -0,0 +1,197 @@ +/* ssl/kssl.h */ +/* + * Written by Vern Staats for the OpenSSL project + * 2000. project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + ** 19990701 VRS Started. + */ + +#ifndef KSSL_H +# define KSSL_H + +# include + +# ifndef OPENSSL_NO_KRB5 + +# include +# include +# include +# ifdef OPENSSL_SYS_WIN32 +/* + * These can sometimes get redefined indirectly by krb5 header files after + * they get undefed in ossl_typ.h + */ +# undef X509_NAME +# undef X509_EXTENSIONS +# undef OCSP_REQUEST +# undef OCSP_RESPONSE +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Depending on which KRB5 implementation used, some types from + * the other may be missing. Resolve that here and now + */ +# ifdef KRB5_HEIMDAL +typedef unsigned char krb5_octet; +# define FAR +# else + +# ifndef FAR +# define FAR +# endif + +# endif + +/*- + * Uncomment this to debug kssl problems or + * to trace usage of the Kerberos session key + * + * #define KSSL_DEBUG + */ + +# ifndef KRB5SVC +# define KRB5SVC "host" +# endif + +# ifndef KRB5KEYTAB +# define KRB5KEYTAB "/etc/krb5.keytab" +# endif + +# ifndef KRB5SENDAUTH +# define KRB5SENDAUTH 1 +# endif + +# ifndef KRB5CHECKAUTH +# define KRB5CHECKAUTH 1 +# endif + +# ifndef KSSL_CLOCKSKEW +# define KSSL_CLOCKSKEW 300; +# endif + +# define KSSL_ERR_MAX 255 +typedef struct kssl_err_st { + int reason; + char text[KSSL_ERR_MAX + 1]; +} KSSL_ERR; + +/*- Context for passing + * (1) Kerberos session key to SSL, and + * (2) Config data between application and SSL lib + */ +typedef struct kssl_ctx_st { + /* used by: disposition: */ + char *service_name; /* C,S default ok (kssl) */ + char *service_host; /* C input, REQUIRED */ + char *client_princ; /* S output from krb5 ticket */ + char *keytab_file; /* S NULL (/etc/krb5.keytab) */ + char *cred_cache; /* C NULL (default) */ + krb5_enctype enctype; + int length; + krb5_octet FAR *key; +} KSSL_CTX; + +# define KSSL_CLIENT 1 +# define KSSL_SERVER 2 +# define KSSL_SERVICE 3 +# define KSSL_KEYTAB 4 + +# define KSSL_CTX_OK 0 +# define KSSL_CTX_ERR 1 +# define KSSL_NOMEM 2 + +/* Public (for use by applications that use OpenSSL with Kerberos 5 support */ +krb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text); +KSSL_CTX *kssl_ctx_new(void); +KSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx); +void kssl_ctx_show(KSSL_CTX *kssl_ctx); +krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, + krb5_data *realm, krb5_data *entity, + int nentities); +krb5_error_code kssl_cget_tkt(KSSL_CTX *kssl_ctx, krb5_data **enc_tktp, + krb5_data *authenp, KSSL_ERR *kssl_err); +krb5_error_code kssl_sget_tkt(KSSL_CTX *kssl_ctx, krb5_data *indata, + krb5_ticket_times *ttimes, KSSL_ERR *kssl_err); +krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session); +void kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text); +void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data); +krb5_error_code kssl_build_principal_2(krb5_context context, + krb5_principal *princ, int rlen, + const char *realm, int slen, + const char *svc, int hlen, + const char *host); +krb5_error_code kssl_validate_times(krb5_timestamp atime, + krb5_ticket_times *ttimes); +krb5_error_code kssl_check_authent(KSSL_CTX *kssl_ctx, krb5_data *authentp, + krb5_timestamp *atimep, + KSSL_ERR *kssl_err); +unsigned char *kssl_skip_confound(krb5_enctype enctype, unsigned char *authn); + +void SSL_set0_kssl_ctx(SSL *s, KSSL_CTX *kctx); +KSSL_CTX *SSL_get0_kssl_ctx(SSL *s); +char *kssl_ctx_get0_client_princ(KSSL_CTX *kctx); + +#ifdef __cplusplus +} +#endif +# endif /* OPENSSL_NO_KRB5 */ +#endif /* KSSL_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/lhash.h b/optee/optee_test/host/openssl/include/openssl/lhash.h new file mode 100644 index 0000000..b6c328b --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/lhash.h @@ -0,0 +1,240 @@ +/* crypto/lhash/lhash.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* + * Header for dynamic hash table routines Author - Eric Young + */ + +#ifndef HEADER_LHASH_H +# define HEADER_LHASH_H + +# include +# ifndef OPENSSL_NO_FP_API +# include +# endif + +# ifndef OPENSSL_NO_BIO +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct lhash_node_st { + void *data; + struct lhash_node_st *next; +# ifndef OPENSSL_NO_HASH_COMP + unsigned long hash; +# endif +} LHASH_NODE; + +typedef int (*LHASH_COMP_FN_TYPE) (const void *, const void *); +typedef unsigned long (*LHASH_HASH_FN_TYPE) (const void *); +typedef void (*LHASH_DOALL_FN_TYPE) (void *); +typedef void (*LHASH_DOALL_ARG_FN_TYPE) (void *, void *); + +/* + * Macros for declaring and implementing type-safe wrappers for LHASH + * callbacks. This way, callbacks can be provided to LHASH structures without + * function pointer casting and the macro-defined callbacks provide + * per-variable casting before deferring to the underlying type-specific + * callbacks. NB: It is possible to place a "static" in front of both the + * DECLARE and IMPLEMENT macros if the functions are strictly internal. + */ + +/* First: "hash" functions */ +# define DECLARE_LHASH_HASH_FN(name, o_type) \ + unsigned long name##_LHASH_HASH(const void *); +# define IMPLEMENT_LHASH_HASH_FN(name, o_type) \ + unsigned long name##_LHASH_HASH(const void *arg) { \ + const o_type *a = arg; \ + return name##_hash(a); } +# define LHASH_HASH_FN(name) name##_LHASH_HASH + +/* Second: "compare" functions */ +# define DECLARE_LHASH_COMP_FN(name, o_type) \ + int name##_LHASH_COMP(const void *, const void *); +# define IMPLEMENT_LHASH_COMP_FN(name, o_type) \ + int name##_LHASH_COMP(const void *arg1, const void *arg2) { \ + const o_type *a = arg1; \ + const o_type *b = arg2; \ + return name##_cmp(a,b); } +# define LHASH_COMP_FN(name) name##_LHASH_COMP + +/* Third: "doall" functions */ +# define DECLARE_LHASH_DOALL_FN(name, o_type) \ + void name##_LHASH_DOALL(void *); +# define IMPLEMENT_LHASH_DOALL_FN(name, o_type) \ + void name##_LHASH_DOALL(void *arg) { \ + o_type *a = arg; \ + name##_doall(a); } +# define LHASH_DOALL_FN(name) name##_LHASH_DOALL + +/* Fourth: "doall_arg" functions */ +# define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ + void name##_LHASH_DOALL_ARG(void *, void *); +# define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ + void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \ + o_type *a = arg1; \ + a_type *b = arg2; \ + name##_doall_arg(a, b); } +# define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG + +typedef struct lhash_st { + LHASH_NODE **b; + LHASH_COMP_FN_TYPE comp; + LHASH_HASH_FN_TYPE hash; + unsigned int num_nodes; + unsigned int num_alloc_nodes; + unsigned int p; + unsigned int pmax; + unsigned long up_load; /* load times 256 */ + unsigned long down_load; /* load times 256 */ + unsigned long num_items; + unsigned long num_expands; + unsigned long num_expand_reallocs; + unsigned long num_contracts; + unsigned long num_contract_reallocs; + unsigned long num_hash_calls; + unsigned long num_comp_calls; + unsigned long num_insert; + unsigned long num_replace; + unsigned long num_delete; + unsigned long num_no_delete; + unsigned long num_retrieve; + unsigned long num_retrieve_miss; + unsigned long num_hash_comps; + int error; +} _LHASH; /* Do not use _LHASH directly, use LHASH_OF + * and friends */ + +# define LH_LOAD_MULT 256 + +/* + * Indicates a malloc() error in the last call, this is only bad in + * lh_insert(). + */ +# define lh_error(lh) ((lh)->error) + +_LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c); +void lh_free(_LHASH *lh); +void *lh_insert(_LHASH *lh, void *data); +void *lh_delete(_LHASH *lh, const void *data); +void *lh_retrieve(_LHASH *lh, const void *data); +void lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func); +void lh_doall_arg(_LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg); +unsigned long lh_strhash(const char *c); +unsigned long lh_num_items(const _LHASH *lh); + +# ifndef OPENSSL_NO_FP_API +void lh_stats(const _LHASH *lh, FILE *out); +void lh_node_stats(const _LHASH *lh, FILE *out); +void lh_node_usage_stats(const _LHASH *lh, FILE *out); +# endif + +# ifndef OPENSSL_NO_BIO +void lh_stats_bio(const _LHASH *lh, BIO *out); +void lh_node_stats_bio(const _LHASH *lh, BIO *out); +void lh_node_usage_stats_bio(const _LHASH *lh, BIO *out); +# endif + +/* Type checking... */ + +# define LHASH_OF(type) struct lhash_st_##type + +# define DECLARE_LHASH_OF(type) LHASH_OF(type) { int dummy; } + +# define CHECKED_LHASH_OF(type,lh) \ + ((_LHASH *)CHECKED_PTR_OF(LHASH_OF(type),lh)) + +/* Define wrapper functions. */ +# define LHM_lh_new(type, name) \ + ((LHASH_OF(type) *)lh_new(LHASH_HASH_FN(name), LHASH_COMP_FN(name))) +# define LHM_lh_error(type, lh) \ + lh_error(CHECKED_LHASH_OF(type,lh)) +# define LHM_lh_insert(type, lh, inst) \ + ((type *)lh_insert(CHECKED_LHASH_OF(type, lh), \ + CHECKED_PTR_OF(type, inst))) +# define LHM_lh_retrieve(type, lh, inst) \ + ((type *)lh_retrieve(CHECKED_LHASH_OF(type, lh), \ + CHECKED_PTR_OF(type, inst))) +# define LHM_lh_delete(type, lh, inst) \ + ((type *)lh_delete(CHECKED_LHASH_OF(type, lh), \ + CHECKED_PTR_OF(type, inst))) +# define LHM_lh_doall(type, lh,fn) lh_doall(CHECKED_LHASH_OF(type, lh), fn) +# define LHM_lh_doall_arg(type, lh, fn, arg_type, arg) \ + lh_doall_arg(CHECKED_LHASH_OF(type, lh), fn, CHECKED_PTR_OF(arg_type, arg)) +# define LHM_lh_num_items(type, lh) lh_num_items(CHECKED_LHASH_OF(type, lh)) +# define LHM_lh_down_load(type, lh) (CHECKED_LHASH_OF(type, lh)->down_load) +# define LHM_lh_node_stats_bio(type, lh, out) \ + lh_node_stats_bio(CHECKED_LHASH_OF(type, lh), out) +# define LHM_lh_node_usage_stats_bio(type, lh, out) \ + lh_node_usage_stats_bio(CHECKED_LHASH_OF(type, lh), out) +# define LHM_lh_stats_bio(type, lh, out) \ + lh_stats_bio(CHECKED_LHASH_OF(type, lh), out) +# define LHM_lh_free(type, lh) lh_free(CHECKED_LHASH_OF(type, lh)) + +DECLARE_LHASH_OF(OPENSSL_STRING); +DECLARE_LHASH_OF(OPENSSL_CSTRING); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/md4.h b/optee/optee_test/host/openssl/include/openssl/md4.h new file mode 100644 index 0000000..11fd712 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/md4.h @@ -0,0 +1,119 @@ +/* crypto/md4/md4.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_MD4_H +# define HEADER_MD4_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef OPENSSL_NO_MD4 +# error MD4 is disabled. +# endif + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD4_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! MD4_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +# if defined(__LP32__) +# define MD4_LONG unsigned long +# elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) +# define MD4_LONG unsigned long +# define MD4_LONG_LOG2 3 +/* + * _CRAY note. I could declare short, but I have no idea what impact + * does it have on performance on none-T3E machines. I could declare + * int, but at least on C90 sizeof(int) can be chosen at compile time. + * So I've chosen long... + * + */ +# else +# define MD4_LONG unsigned int +# endif + +# define MD4_CBLOCK 64 +# define MD4_LBLOCK (MD4_CBLOCK/4) +# define MD4_DIGEST_LENGTH 16 + +typedef struct MD4state_st { + MD4_LONG A, B, C, D; + MD4_LONG Nl, Nh; + MD4_LONG data[MD4_LBLOCK]; + unsigned int num; +} MD4_CTX; + +# ifdef OPENSSL_FIPS +int private_MD4_Init(MD4_CTX *c); +# endif +int MD4_Init(MD4_CTX *c); +int MD4_Update(MD4_CTX *c, const void *data, size_t len); +int MD4_Final(unsigned char *md, MD4_CTX *c); +unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md); +void MD4_Transform(MD4_CTX *c, const unsigned char *b); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/md5.h b/optee/optee_test/host/openssl/include/openssl/md5.h new file mode 100644 index 0000000..2659038 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/md5.h @@ -0,0 +1,119 @@ +/* crypto/md5/md5.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_MD5_H +# define HEADER_MD5_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef OPENSSL_NO_MD5 +# error MD5 is disabled. +# endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD5_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! MD5_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +# if defined(__LP32__) +# define MD5_LONG unsigned long +# elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) +# define MD5_LONG unsigned long +# define MD5_LONG_LOG2 3 +/* + * _CRAY note. I could declare short, but I have no idea what impact + * does it have on performance on none-T3E machines. I could declare + * int, but at least on C90 sizeof(int) can be chosen at compile time. + * So I've chosen long... + * + */ +# else +# define MD5_LONG unsigned int +# endif + +# define MD5_CBLOCK 64 +# define MD5_LBLOCK (MD5_CBLOCK/4) +# define MD5_DIGEST_LENGTH 16 + +typedef struct MD5state_st { + MD5_LONG A, B, C, D; + MD5_LONG Nl, Nh; + MD5_LONG data[MD5_LBLOCK]; + unsigned int num; +} MD5_CTX; + +# ifdef OPENSSL_FIPS +int private_MD5_Init(MD5_CTX *c); +# endif +int MD5_Init(MD5_CTX *c); +int MD5_Update(MD5_CTX *c, const void *data, size_t len); +int MD5_Final(unsigned char *md, MD5_CTX *c); +unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md); +void MD5_Transform(MD5_CTX *c, const unsigned char *b); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/mdc2.h b/optee/optee_test/host/openssl/include/openssl/mdc2.h new file mode 100644 index 0000000..7efe53b --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/mdc2.h @@ -0,0 +1,94 @@ +/* crypto/mdc2/mdc2.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_MDC2_H +# define HEADER_MDC2_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef OPENSSL_NO_MDC2 +# error MDC2 is disabled. +# endif + +# define MDC2_BLOCK 8 +# define MDC2_DIGEST_LENGTH 16 + +typedef struct mdc2_ctx_st { + unsigned int num; + unsigned char data[MDC2_BLOCK]; + DES_cblock h, hh; + int pad_type; /* either 1 or 2, default 1 */ +} MDC2_CTX; + +# ifdef OPENSSL_FIPS +int private_MDC2_Init(MDC2_CTX *c); +# endif +int MDC2_Init(MDC2_CTX *c); +int MDC2_Update(MDC2_CTX *c, const unsigned char *data, size_t len); +int MDC2_Final(unsigned char *md, MDC2_CTX *c); +unsigned char *MDC2(const unsigned char *d, size_t n, unsigned char *md); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/modes.h b/optee/optee_test/host/openssl/include/openssl/modes.h new file mode 100644 index 0000000..fd48849 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/modes.h @@ -0,0 +1,163 @@ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Rights for redistribution and usage in source and binary + * forms are granted according to the OpenSSL license. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef void (*block128_f) (const unsigned char in[16], + unsigned char out[16], const void *key); + +typedef void (*cbc128_f) (const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int enc); + +typedef void (*ctr128_f) (const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16]); + +typedef void (*ccm128_f) (const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16], + unsigned char cmac[16]); + +void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); + +void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], + unsigned char ecount_buf[16], unsigned int *num, + block128_f block); + +void CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], + unsigned char ecount_buf[16], + unsigned int *num, ctr128_f ctr); + +void CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + block128_f block); + +void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, + size_t bits, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); + +size_t CRYPTO_cts128_encrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], + block128_f block); +size_t CRYPTO_cts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); +size_t CRYPTO_cts128_decrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, unsigned char ivec[16], + block128_f block); +size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); + +size_t CRYPTO_nistcts128_encrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, + unsigned char ivec[16], + block128_f block); +size_t CRYPTO_nistcts128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); +size_t CRYPTO_nistcts128_decrypt_block(const unsigned char *in, + unsigned char *out, size_t len, + const void *key, + unsigned char ivec[16], + block128_f block); +size_t CRYPTO_nistcts128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], cbc128_f cbc); + +typedef struct gcm128_context GCM128_CONTEXT; + +GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block); +void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block); +void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv, + size_t len); +int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad, + size_t len); +int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag, + size_t len); +void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len); +void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx); + +typedef struct ccm128_context CCM128_CONTEXT; + +void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, + unsigned int M, unsigned int L, void *key, + block128_f block); +int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, const unsigned char *nonce, + size_t nlen, size_t mlen); +void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, const unsigned char *aad, + size_t alen); +int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len); +int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len); +int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len, + ccm128_f stream); +int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, const unsigned char *inp, + unsigned char *out, size_t len, + ccm128_f stream); +size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len); + +typedef struct xts128_context XTS128_CONTEXT; + +int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, + const unsigned char iv[16], + const unsigned char *inp, unsigned char *out, + size_t len, int enc); + +size_t CRYPTO_128_wrap(void *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block); + +size_t CRYPTO_128_unwrap(void *key, const unsigned char *iv, + unsigned char *out, + const unsigned char *in, size_t inlen, + block128_f block); + +#ifdef __cplusplus +} +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/obj_mac.h b/optee/optee_test/host/openssl/include/openssl/obj_mac.h new file mode 100644 index 0000000..779c309 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/obj_mac.h @@ -0,0 +1,4194 @@ +/* crypto/objects/obj_mac.h */ + +/* + * THIS FILE IS GENERATED FROM objects.txt by objects.pl via the following + * command: perl objects.pl objects.txt obj_mac.num obj_mac.h + */ + +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L + +#define SN_itu_t "ITU-T" +#define LN_itu_t "itu-t" +#define NID_itu_t 645 +#define OBJ_itu_t 0L + +#define NID_ccitt 404 +#define OBJ_ccitt OBJ_itu_t + +#define SN_iso "ISO" +#define LN_iso "iso" +#define NID_iso 181 +#define OBJ_iso 1L + +#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T" +#define LN_joint_iso_itu_t "joint-iso-itu-t" +#define NID_joint_iso_itu_t 646 +#define OBJ_joint_iso_itu_t 2L + +#define NID_joint_iso_ccitt 393 +#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t + +#define SN_member_body "member-body" +#define LN_member_body "ISO Member Body" +#define NID_member_body 182 +#define OBJ_member_body OBJ_iso,2L + +#define SN_identified_organization "identified-organization" +#define NID_identified_organization 676 +#define OBJ_identified_organization OBJ_iso,3L + +#define SN_hmac_md5 "HMAC-MD5" +#define LN_hmac_md5 "hmac-md5" +#define NID_hmac_md5 780 +#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L + +#define SN_hmac_sha1 "HMAC-SHA1" +#define LN_hmac_sha1 "hmac-sha1" +#define NID_hmac_sha1 781 +#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L + +#define SN_certicom_arc "certicom-arc" +#define NID_certicom_arc 677 +#define OBJ_certicom_arc OBJ_identified_organization,132L + +#define SN_international_organizations "international-organizations" +#define LN_international_organizations "International Organizations" +#define NID_international_organizations 647 +#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L + +#define SN_wap "wap" +#define NID_wap 678 +#define OBJ_wap OBJ_international_organizations,43L + +#define SN_wap_wsg "wap-wsg" +#define NID_wap_wsg 679 +#define OBJ_wap_wsg OBJ_wap,1L + +#define SN_selected_attribute_types "selected-attribute-types" +#define LN_selected_attribute_types "Selected Attribute Types" +#define NID_selected_attribute_types 394 +#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L + +#define SN_clearance "clearance" +#define NID_clearance 395 +#define OBJ_clearance OBJ_selected_attribute_types,55L + +#define SN_ISO_US "ISO-US" +#define LN_ISO_US "ISO US Member Body" +#define NID_ISO_US 183 +#define OBJ_ISO_US OBJ_member_body,840L + +#define SN_X9_57 "X9-57" +#define LN_X9_57 "X9.57" +#define NID_X9_57 184 +#define OBJ_X9_57 OBJ_ISO_US,10040L + +#define SN_X9cm "X9cm" +#define LN_X9cm "X9.57 CM ?" +#define NID_X9cm 185 +#define OBJ_X9cm OBJ_X9_57,4L + +#define SN_dsa "DSA" +#define LN_dsa "dsaEncryption" +#define NID_dsa 116 +#define OBJ_dsa OBJ_X9cm,1L + +#define SN_dsaWithSHA1 "DSA-SHA1" +#define LN_dsaWithSHA1 "dsaWithSHA1" +#define NID_dsaWithSHA1 113 +#define OBJ_dsaWithSHA1 OBJ_X9cm,3L + +#define SN_ansi_X9_62 "ansi-X9-62" +#define LN_ansi_X9_62 "ANSI X9.62" +#define NID_ansi_X9_62 405 +#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L + +#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L + +#define SN_X9_62_prime_field "prime-field" +#define NID_X9_62_prime_field 406 +#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L + +#define SN_X9_62_characteristic_two_field "characteristic-two-field" +#define NID_X9_62_characteristic_two_field 407 +#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L + +#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis" +#define NID_X9_62_id_characteristic_two_basis 680 +#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L + +#define SN_X9_62_onBasis "onBasis" +#define NID_X9_62_onBasis 681 +#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L + +#define SN_X9_62_tpBasis "tpBasis" +#define NID_X9_62_tpBasis 682 +#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L + +#define SN_X9_62_ppBasis "ppBasis" +#define NID_X9_62_ppBasis 683 +#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L + +#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L + +#define SN_X9_62_id_ecPublicKey "id-ecPublicKey" +#define NID_X9_62_id_ecPublicKey 408 +#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L + +#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L + +#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L + +#define SN_X9_62_c2pnb163v1 "c2pnb163v1" +#define NID_X9_62_c2pnb163v1 684 +#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L + +#define SN_X9_62_c2pnb163v2 "c2pnb163v2" +#define NID_X9_62_c2pnb163v2 685 +#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L + +#define SN_X9_62_c2pnb163v3 "c2pnb163v3" +#define NID_X9_62_c2pnb163v3 686 +#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L + +#define SN_X9_62_c2pnb176v1 "c2pnb176v1" +#define NID_X9_62_c2pnb176v1 687 +#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L + +#define SN_X9_62_c2tnb191v1 "c2tnb191v1" +#define NID_X9_62_c2tnb191v1 688 +#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L + +#define SN_X9_62_c2tnb191v2 "c2tnb191v2" +#define NID_X9_62_c2tnb191v2 689 +#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L + +#define SN_X9_62_c2tnb191v3 "c2tnb191v3" +#define NID_X9_62_c2tnb191v3 690 +#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L + +#define SN_X9_62_c2onb191v4 "c2onb191v4" +#define NID_X9_62_c2onb191v4 691 +#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L + +#define SN_X9_62_c2onb191v5 "c2onb191v5" +#define NID_X9_62_c2onb191v5 692 +#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L + +#define SN_X9_62_c2pnb208w1 "c2pnb208w1" +#define NID_X9_62_c2pnb208w1 693 +#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L + +#define SN_X9_62_c2tnb239v1 "c2tnb239v1" +#define NID_X9_62_c2tnb239v1 694 +#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L + +#define SN_X9_62_c2tnb239v2 "c2tnb239v2" +#define NID_X9_62_c2tnb239v2 695 +#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L + +#define SN_X9_62_c2tnb239v3 "c2tnb239v3" +#define NID_X9_62_c2tnb239v3 696 +#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L + +#define SN_X9_62_c2onb239v4 "c2onb239v4" +#define NID_X9_62_c2onb239v4 697 +#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L + +#define SN_X9_62_c2onb239v5 "c2onb239v5" +#define NID_X9_62_c2onb239v5 698 +#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L + +#define SN_X9_62_c2pnb272w1 "c2pnb272w1" +#define NID_X9_62_c2pnb272w1 699 +#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L + +#define SN_X9_62_c2pnb304w1 "c2pnb304w1" +#define NID_X9_62_c2pnb304w1 700 +#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L + +#define SN_X9_62_c2tnb359v1 "c2tnb359v1" +#define NID_X9_62_c2tnb359v1 701 +#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L + +#define SN_X9_62_c2pnb368w1 "c2pnb368w1" +#define NID_X9_62_c2pnb368w1 702 +#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L + +#define SN_X9_62_c2tnb431r1 "c2tnb431r1" +#define NID_X9_62_c2tnb431r1 703 +#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L + +#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L + +#define SN_X9_62_prime192v1 "prime192v1" +#define NID_X9_62_prime192v1 409 +#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L + +#define SN_X9_62_prime192v2 "prime192v2" +#define NID_X9_62_prime192v2 410 +#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L + +#define SN_X9_62_prime192v3 "prime192v3" +#define NID_X9_62_prime192v3 411 +#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L + +#define SN_X9_62_prime239v1 "prime239v1" +#define NID_X9_62_prime239v1 412 +#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L + +#define SN_X9_62_prime239v2 "prime239v2" +#define NID_X9_62_prime239v2 413 +#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L + +#define SN_X9_62_prime239v3 "prime239v3" +#define NID_X9_62_prime239v3 414 +#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L + +#define SN_X9_62_prime256v1 "prime256v1" +#define NID_X9_62_prime256v1 415 +#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L + +#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L + +#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1" +#define NID_ecdsa_with_SHA1 416 +#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L + +#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended" +#define NID_ecdsa_with_Recommended 791 +#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L + +#define SN_ecdsa_with_Specified "ecdsa-with-Specified" +#define NID_ecdsa_with_Specified 792 +#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L + +#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224" +#define NID_ecdsa_with_SHA224 793 +#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L + +#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256" +#define NID_ecdsa_with_SHA256 794 +#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L + +#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384" +#define NID_ecdsa_with_SHA384 795 +#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L + +#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512" +#define NID_ecdsa_with_SHA512 796 +#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L + +#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L + +#define SN_secp112r1 "secp112r1" +#define NID_secp112r1 704 +#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L + +#define SN_secp112r2 "secp112r2" +#define NID_secp112r2 705 +#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L + +#define SN_secp128r1 "secp128r1" +#define NID_secp128r1 706 +#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L + +#define SN_secp128r2 "secp128r2" +#define NID_secp128r2 707 +#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L + +#define SN_secp160k1 "secp160k1" +#define NID_secp160k1 708 +#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L + +#define SN_secp160r1 "secp160r1" +#define NID_secp160r1 709 +#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L + +#define SN_secp160r2 "secp160r2" +#define NID_secp160r2 710 +#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L + +#define SN_secp192k1 "secp192k1" +#define NID_secp192k1 711 +#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L + +#define SN_secp224k1 "secp224k1" +#define NID_secp224k1 712 +#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L + +#define SN_secp224r1 "secp224r1" +#define NID_secp224r1 713 +#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L + +#define SN_secp256k1 "secp256k1" +#define NID_secp256k1 714 +#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L + +#define SN_secp384r1 "secp384r1" +#define NID_secp384r1 715 +#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L + +#define SN_secp521r1 "secp521r1" +#define NID_secp521r1 716 +#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L + +#define SN_sect113r1 "sect113r1" +#define NID_sect113r1 717 +#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L + +#define SN_sect113r2 "sect113r2" +#define NID_sect113r2 718 +#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L + +#define SN_sect131r1 "sect131r1" +#define NID_sect131r1 719 +#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L + +#define SN_sect131r2 "sect131r2" +#define NID_sect131r2 720 +#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L + +#define SN_sect163k1 "sect163k1" +#define NID_sect163k1 721 +#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L + +#define SN_sect163r1 "sect163r1" +#define NID_sect163r1 722 +#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L + +#define SN_sect163r2 "sect163r2" +#define NID_sect163r2 723 +#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L + +#define SN_sect193r1 "sect193r1" +#define NID_sect193r1 724 +#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L + +#define SN_sect193r2 "sect193r2" +#define NID_sect193r2 725 +#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L + +#define SN_sect233k1 "sect233k1" +#define NID_sect233k1 726 +#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L + +#define SN_sect233r1 "sect233r1" +#define NID_sect233r1 727 +#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L + +#define SN_sect239k1 "sect239k1" +#define NID_sect239k1 728 +#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L + +#define SN_sect283k1 "sect283k1" +#define NID_sect283k1 729 +#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L + +#define SN_sect283r1 "sect283r1" +#define NID_sect283r1 730 +#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L + +#define SN_sect409k1 "sect409k1" +#define NID_sect409k1 731 +#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L + +#define SN_sect409r1 "sect409r1" +#define NID_sect409r1 732 +#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L + +#define SN_sect571k1 "sect571k1" +#define NID_sect571k1 733 +#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L + +#define SN_sect571r1 "sect571r1" +#define NID_sect571r1 734 +#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L + +#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L + +#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1" +#define NID_wap_wsg_idm_ecid_wtls1 735 +#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L + +#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3" +#define NID_wap_wsg_idm_ecid_wtls3 736 +#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L + +#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4" +#define NID_wap_wsg_idm_ecid_wtls4 737 +#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L + +#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5" +#define NID_wap_wsg_idm_ecid_wtls5 738 +#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L + +#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6" +#define NID_wap_wsg_idm_ecid_wtls6 739 +#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L + +#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7" +#define NID_wap_wsg_idm_ecid_wtls7 740 +#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L + +#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8" +#define NID_wap_wsg_idm_ecid_wtls8 741 +#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L + +#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9" +#define NID_wap_wsg_idm_ecid_wtls9 742 +#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L + +#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10" +#define NID_wap_wsg_idm_ecid_wtls10 743 +#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L + +#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11" +#define NID_wap_wsg_idm_ecid_wtls11 744 +#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L + +#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12" +#define NID_wap_wsg_idm_ecid_wtls12 745 +#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L + +#define SN_cast5_cbc "CAST5-CBC" +#define LN_cast5_cbc "cast5-cbc" +#define NID_cast5_cbc 108 +#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L + +#define SN_cast5_ecb "CAST5-ECB" +#define LN_cast5_ecb "cast5-ecb" +#define NID_cast5_ecb 109 + +#define SN_cast5_cfb64 "CAST5-CFB" +#define LN_cast5_cfb64 "cast5-cfb" +#define NID_cast5_cfb64 110 + +#define SN_cast5_ofb64 "CAST5-OFB" +#define LN_cast5_ofb64 "cast5-ofb" +#define NID_cast5_ofb64 111 + +#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC" +#define NID_pbeWithMD5AndCast5_CBC 112 +#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L + +#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC" +#define LN_id_PasswordBasedMAC "password based MAC" +#define NID_id_PasswordBasedMAC 782 +#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L + +#define SN_id_DHBasedMac "id-DHBasedMac" +#define LN_id_DHBasedMac "Diffie-Hellman based MAC" +#define NID_id_DHBasedMac 783 +#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L + +#define SN_rsadsi "rsadsi" +#define LN_rsadsi "RSA Data Security, Inc." +#define NID_rsadsi 1 +#define OBJ_rsadsi OBJ_ISO_US,113549L + +#define SN_pkcs "pkcs" +#define LN_pkcs "RSA Data Security, Inc. PKCS" +#define NID_pkcs 2 +#define OBJ_pkcs OBJ_rsadsi,1L + +#define SN_pkcs1 "pkcs1" +#define NID_pkcs1 186 +#define OBJ_pkcs1 OBJ_pkcs,1L + +#define LN_rsaEncryption "rsaEncryption" +#define NID_rsaEncryption 6 +#define OBJ_rsaEncryption OBJ_pkcs1,1L + +#define SN_md2WithRSAEncryption "RSA-MD2" +#define LN_md2WithRSAEncryption "md2WithRSAEncryption" +#define NID_md2WithRSAEncryption 7 +#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L + +#define SN_md4WithRSAEncryption "RSA-MD4" +#define LN_md4WithRSAEncryption "md4WithRSAEncryption" +#define NID_md4WithRSAEncryption 396 +#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L + +#define SN_md5WithRSAEncryption "RSA-MD5" +#define LN_md5WithRSAEncryption "md5WithRSAEncryption" +#define NID_md5WithRSAEncryption 8 +#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L + +#define SN_sha1WithRSAEncryption "RSA-SHA1" +#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption" +#define NID_sha1WithRSAEncryption 65 +#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L + +#define SN_rsaesOaep "RSAES-OAEP" +#define LN_rsaesOaep "rsaesOaep" +#define NID_rsaesOaep 919 +#define OBJ_rsaesOaep OBJ_pkcs1,7L + +#define SN_mgf1 "MGF1" +#define LN_mgf1 "mgf1" +#define NID_mgf1 911 +#define OBJ_mgf1 OBJ_pkcs1,8L + +#define SN_pSpecified "PSPECIFIED" +#define LN_pSpecified "pSpecified" +#define NID_pSpecified 935 +#define OBJ_pSpecified OBJ_pkcs1,9L + +#define SN_rsassaPss "RSASSA-PSS" +#define LN_rsassaPss "rsassaPss" +#define NID_rsassaPss 912 +#define OBJ_rsassaPss OBJ_pkcs1,10L + +#define SN_sha256WithRSAEncryption "RSA-SHA256" +#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption" +#define NID_sha256WithRSAEncryption 668 +#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L + +#define SN_sha384WithRSAEncryption "RSA-SHA384" +#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption" +#define NID_sha384WithRSAEncryption 669 +#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L + +#define SN_sha512WithRSAEncryption "RSA-SHA512" +#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption" +#define NID_sha512WithRSAEncryption 670 +#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L + +#define SN_sha224WithRSAEncryption "RSA-SHA224" +#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption" +#define NID_sha224WithRSAEncryption 671 +#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L + +#define SN_pkcs3 "pkcs3" +#define NID_pkcs3 27 +#define OBJ_pkcs3 OBJ_pkcs,3L + +#define LN_dhKeyAgreement "dhKeyAgreement" +#define NID_dhKeyAgreement 28 +#define OBJ_dhKeyAgreement OBJ_pkcs3,1L + +#define SN_pkcs5 "pkcs5" +#define NID_pkcs5 187 +#define OBJ_pkcs5 OBJ_pkcs,5L + +#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES" +#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC" +#define NID_pbeWithMD2AndDES_CBC 9 +#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L + +#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES" +#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC" +#define NID_pbeWithMD5AndDES_CBC 10 +#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L + +#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64" +#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC" +#define NID_pbeWithMD2AndRC2_CBC 168 +#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L + +#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64" +#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC" +#define NID_pbeWithMD5AndRC2_CBC 169 +#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L + +#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES" +#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC" +#define NID_pbeWithSHA1AndDES_CBC 170 +#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L + +#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64" +#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC" +#define NID_pbeWithSHA1AndRC2_CBC 68 +#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L + +#define LN_id_pbkdf2 "PBKDF2" +#define NID_id_pbkdf2 69 +#define OBJ_id_pbkdf2 OBJ_pkcs5,12L + +#define LN_pbes2 "PBES2" +#define NID_pbes2 161 +#define OBJ_pbes2 OBJ_pkcs5,13L + +#define LN_pbmac1 "PBMAC1" +#define NID_pbmac1 162 +#define OBJ_pbmac1 OBJ_pkcs5,14L + +#define SN_pkcs7 "pkcs7" +#define NID_pkcs7 20 +#define OBJ_pkcs7 OBJ_pkcs,7L + +#define LN_pkcs7_data "pkcs7-data" +#define NID_pkcs7_data 21 +#define OBJ_pkcs7_data OBJ_pkcs7,1L + +#define LN_pkcs7_signed "pkcs7-signedData" +#define NID_pkcs7_signed 22 +#define OBJ_pkcs7_signed OBJ_pkcs7,2L + +#define LN_pkcs7_enveloped "pkcs7-envelopedData" +#define NID_pkcs7_enveloped 23 +#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L + +#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData" +#define NID_pkcs7_signedAndEnveloped 24 +#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L + +#define LN_pkcs7_digest "pkcs7-digestData" +#define NID_pkcs7_digest 25 +#define OBJ_pkcs7_digest OBJ_pkcs7,5L + +#define LN_pkcs7_encrypted "pkcs7-encryptedData" +#define NID_pkcs7_encrypted 26 +#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L + +#define SN_pkcs9 "pkcs9" +#define NID_pkcs9 47 +#define OBJ_pkcs9 OBJ_pkcs,9L + +#define LN_pkcs9_emailAddress "emailAddress" +#define NID_pkcs9_emailAddress 48 +#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L + +#define LN_pkcs9_unstructuredName "unstructuredName" +#define NID_pkcs9_unstructuredName 49 +#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L + +#define LN_pkcs9_contentType "contentType" +#define NID_pkcs9_contentType 50 +#define OBJ_pkcs9_contentType OBJ_pkcs9,3L + +#define LN_pkcs9_messageDigest "messageDigest" +#define NID_pkcs9_messageDigest 51 +#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L + +#define LN_pkcs9_signingTime "signingTime" +#define NID_pkcs9_signingTime 52 +#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L + +#define LN_pkcs9_countersignature "countersignature" +#define NID_pkcs9_countersignature 53 +#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L + +#define LN_pkcs9_challengePassword "challengePassword" +#define NID_pkcs9_challengePassword 54 +#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L + +#define LN_pkcs9_unstructuredAddress "unstructuredAddress" +#define NID_pkcs9_unstructuredAddress 55 +#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L + +#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes" +#define NID_pkcs9_extCertAttributes 56 +#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L + +#define SN_ext_req "extReq" +#define LN_ext_req "Extension Request" +#define NID_ext_req 172 +#define OBJ_ext_req OBJ_pkcs9,14L + +#define SN_SMIMECapabilities "SMIME-CAPS" +#define LN_SMIMECapabilities "S/MIME Capabilities" +#define NID_SMIMECapabilities 167 +#define OBJ_SMIMECapabilities OBJ_pkcs9,15L + +#define SN_SMIME "SMIME" +#define LN_SMIME "S/MIME" +#define NID_SMIME 188 +#define OBJ_SMIME OBJ_pkcs9,16L + +#define SN_id_smime_mod "id-smime-mod" +#define NID_id_smime_mod 189 +#define OBJ_id_smime_mod OBJ_SMIME,0L + +#define SN_id_smime_ct "id-smime-ct" +#define NID_id_smime_ct 190 +#define OBJ_id_smime_ct OBJ_SMIME,1L + +#define SN_id_smime_aa "id-smime-aa" +#define NID_id_smime_aa 191 +#define OBJ_id_smime_aa OBJ_SMIME,2L + +#define SN_id_smime_alg "id-smime-alg" +#define NID_id_smime_alg 192 +#define OBJ_id_smime_alg OBJ_SMIME,3L + +#define SN_id_smime_cd "id-smime-cd" +#define NID_id_smime_cd 193 +#define OBJ_id_smime_cd OBJ_SMIME,4L + +#define SN_id_smime_spq "id-smime-spq" +#define NID_id_smime_spq 194 +#define OBJ_id_smime_spq OBJ_SMIME,5L + +#define SN_id_smime_cti "id-smime-cti" +#define NID_id_smime_cti 195 +#define OBJ_id_smime_cti OBJ_SMIME,6L + +#define SN_id_smime_mod_cms "id-smime-mod-cms" +#define NID_id_smime_mod_cms 196 +#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L + +#define SN_id_smime_mod_ess "id-smime-mod-ess" +#define NID_id_smime_mod_ess 197 +#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L + +#define SN_id_smime_mod_oid "id-smime-mod-oid" +#define NID_id_smime_mod_oid 198 +#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L + +#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3" +#define NID_id_smime_mod_msg_v3 199 +#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L + +#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88" +#define NID_id_smime_mod_ets_eSignature_88 200 +#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L + +#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97" +#define NID_id_smime_mod_ets_eSignature_97 201 +#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L + +#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88" +#define NID_id_smime_mod_ets_eSigPolicy_88 202 +#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L + +#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97" +#define NID_id_smime_mod_ets_eSigPolicy_97 203 +#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L + +#define SN_id_smime_ct_receipt "id-smime-ct-receipt" +#define NID_id_smime_ct_receipt 204 +#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L + +#define SN_id_smime_ct_authData "id-smime-ct-authData" +#define NID_id_smime_ct_authData 205 +#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L + +#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert" +#define NID_id_smime_ct_publishCert 206 +#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L + +#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo" +#define NID_id_smime_ct_TSTInfo 207 +#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L + +#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo" +#define NID_id_smime_ct_TDTInfo 208 +#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L + +#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo" +#define NID_id_smime_ct_contentInfo 209 +#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L + +#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData" +#define NID_id_smime_ct_DVCSRequestData 210 +#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L + +#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData" +#define NID_id_smime_ct_DVCSResponseData 211 +#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L + +#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData" +#define NID_id_smime_ct_compressedData 786 +#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L + +#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF" +#define NID_id_ct_asciiTextWithCRLF 787 +#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L + +#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest" +#define NID_id_smime_aa_receiptRequest 212 +#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L + +#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel" +#define NID_id_smime_aa_securityLabel 213 +#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L + +#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory" +#define NID_id_smime_aa_mlExpandHistory 214 +#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L + +#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint" +#define NID_id_smime_aa_contentHint 215 +#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L + +#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest" +#define NID_id_smime_aa_msgSigDigest 216 +#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L + +#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType" +#define NID_id_smime_aa_encapContentType 217 +#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L + +#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier" +#define NID_id_smime_aa_contentIdentifier 218 +#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L + +#define SN_id_smime_aa_macValue "id-smime-aa-macValue" +#define NID_id_smime_aa_macValue 219 +#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L + +#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels" +#define NID_id_smime_aa_equivalentLabels 220 +#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L + +#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference" +#define NID_id_smime_aa_contentReference 221 +#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L + +#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref" +#define NID_id_smime_aa_encrypKeyPref 222 +#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L + +#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate" +#define NID_id_smime_aa_signingCertificate 223 +#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L + +#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts" +#define NID_id_smime_aa_smimeEncryptCerts 224 +#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L + +#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken" +#define NID_id_smime_aa_timeStampToken 225 +#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L + +#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId" +#define NID_id_smime_aa_ets_sigPolicyId 226 +#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L + +#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType" +#define NID_id_smime_aa_ets_commitmentType 227 +#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L + +#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation" +#define NID_id_smime_aa_ets_signerLocation 228 +#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L + +#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr" +#define NID_id_smime_aa_ets_signerAttr 229 +#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L + +#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert" +#define NID_id_smime_aa_ets_otherSigCert 230 +#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L + +#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp" +#define NID_id_smime_aa_ets_contentTimestamp 231 +#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L + +#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs" +#define NID_id_smime_aa_ets_CertificateRefs 232 +#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L + +#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs" +#define NID_id_smime_aa_ets_RevocationRefs 233 +#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L + +#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues" +#define NID_id_smime_aa_ets_certValues 234 +#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L + +#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues" +#define NID_id_smime_aa_ets_revocationValues 235 +#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L + +#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp" +#define NID_id_smime_aa_ets_escTimeStamp 236 +#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L + +#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp" +#define NID_id_smime_aa_ets_certCRLTimestamp 237 +#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L + +#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp" +#define NID_id_smime_aa_ets_archiveTimeStamp 238 +#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L + +#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType" +#define NID_id_smime_aa_signatureType 239 +#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L + +#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc" +#define NID_id_smime_aa_dvcs_dvc 240 +#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L + +#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES" +#define NID_id_smime_alg_ESDHwith3DES 241 +#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L + +#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2" +#define NID_id_smime_alg_ESDHwithRC2 242 +#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L + +#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap" +#define NID_id_smime_alg_3DESwrap 243 +#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L + +#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap" +#define NID_id_smime_alg_RC2wrap 244 +#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L + +#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH" +#define NID_id_smime_alg_ESDH 245 +#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L + +#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap" +#define NID_id_smime_alg_CMS3DESwrap 246 +#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L + +#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap" +#define NID_id_smime_alg_CMSRC2wrap 247 +#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L + +#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK" +#define NID_id_alg_PWRI_KEK 893 +#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L + +#define SN_id_smime_cd_ldap "id-smime-cd-ldap" +#define NID_id_smime_cd_ldap 248 +#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L + +#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri" +#define NID_id_smime_spq_ets_sqt_uri 249 +#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L + +#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice" +#define NID_id_smime_spq_ets_sqt_unotice 250 +#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L + +#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin" +#define NID_id_smime_cti_ets_proofOfOrigin 251 +#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L + +#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt" +#define NID_id_smime_cti_ets_proofOfReceipt 252 +#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L + +#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery" +#define NID_id_smime_cti_ets_proofOfDelivery 253 +#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L + +#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender" +#define NID_id_smime_cti_ets_proofOfSender 254 +#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L + +#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval" +#define NID_id_smime_cti_ets_proofOfApproval 255 +#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L + +#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation" +#define NID_id_smime_cti_ets_proofOfCreation 256 +#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L + +#define LN_friendlyName "friendlyName" +#define NID_friendlyName 156 +#define OBJ_friendlyName OBJ_pkcs9,20L + +#define LN_localKeyID "localKeyID" +#define NID_localKeyID 157 +#define OBJ_localKeyID OBJ_pkcs9,21L + +#define SN_ms_csp_name "CSPName" +#define LN_ms_csp_name "Microsoft CSP Name" +#define NID_ms_csp_name 417 +#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L + +#define SN_LocalKeySet "LocalKeySet" +#define LN_LocalKeySet "Microsoft Local Key set" +#define NID_LocalKeySet 856 +#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L + +#define OBJ_certTypes OBJ_pkcs9,22L + +#define LN_x509Certificate "x509Certificate" +#define NID_x509Certificate 158 +#define OBJ_x509Certificate OBJ_certTypes,1L + +#define LN_sdsiCertificate "sdsiCertificate" +#define NID_sdsiCertificate 159 +#define OBJ_sdsiCertificate OBJ_certTypes,2L + +#define OBJ_crlTypes OBJ_pkcs9,23L + +#define LN_x509Crl "x509Crl" +#define NID_x509Crl 160 +#define OBJ_x509Crl OBJ_crlTypes,1L + +#define OBJ_pkcs12 OBJ_pkcs,12L + +#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L + +#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128" +#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4" +#define NID_pbe_WithSHA1And128BitRC4 144 +#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L + +#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40" +#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4" +#define NID_pbe_WithSHA1And40BitRC4 145 +#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L + +#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES" +#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146 +#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L + +#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES" +#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147 +#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L + +#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128" +#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC" +#define NID_pbe_WithSHA1And128BitRC2_CBC 148 +#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L + +#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40" +#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC" +#define NID_pbe_WithSHA1And40BitRC2_CBC 149 +#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L + +#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L + +#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L + +#define LN_keyBag "keyBag" +#define NID_keyBag 150 +#define OBJ_keyBag OBJ_pkcs12_BagIds,1L + +#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag" +#define NID_pkcs8ShroudedKeyBag 151 +#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L + +#define LN_certBag "certBag" +#define NID_certBag 152 +#define OBJ_certBag OBJ_pkcs12_BagIds,3L + +#define LN_crlBag "crlBag" +#define NID_crlBag 153 +#define OBJ_crlBag OBJ_pkcs12_BagIds,4L + +#define LN_secretBag "secretBag" +#define NID_secretBag 154 +#define OBJ_secretBag OBJ_pkcs12_BagIds,5L + +#define LN_safeContentsBag "safeContentsBag" +#define NID_safeContentsBag 155 +#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L + +#define SN_md2 "MD2" +#define LN_md2 "md2" +#define NID_md2 3 +#define OBJ_md2 OBJ_rsadsi,2L,2L + +#define SN_md4 "MD4" +#define LN_md4 "md4" +#define NID_md4 257 +#define OBJ_md4 OBJ_rsadsi,2L,4L + +#define SN_md5 "MD5" +#define LN_md5 "md5" +#define NID_md5 4 +#define OBJ_md5 OBJ_rsadsi,2L,5L + +#define SN_md5_sha1 "MD5-SHA1" +#define LN_md5_sha1 "md5-sha1" +#define NID_md5_sha1 114 + +#define LN_hmacWithMD5 "hmacWithMD5" +#define NID_hmacWithMD5 797 +#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L + +#define LN_hmacWithSHA1 "hmacWithSHA1" +#define NID_hmacWithSHA1 163 +#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L + +#define LN_hmacWithSHA224 "hmacWithSHA224" +#define NID_hmacWithSHA224 798 +#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L + +#define LN_hmacWithSHA256 "hmacWithSHA256" +#define NID_hmacWithSHA256 799 +#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L + +#define LN_hmacWithSHA384 "hmacWithSHA384" +#define NID_hmacWithSHA384 800 +#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L + +#define LN_hmacWithSHA512 "hmacWithSHA512" +#define NID_hmacWithSHA512 801 +#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L + +#define SN_rc2_cbc "RC2-CBC" +#define LN_rc2_cbc "rc2-cbc" +#define NID_rc2_cbc 37 +#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L + +#define SN_rc2_ecb "RC2-ECB" +#define LN_rc2_ecb "rc2-ecb" +#define NID_rc2_ecb 38 + +#define SN_rc2_cfb64 "RC2-CFB" +#define LN_rc2_cfb64 "rc2-cfb" +#define NID_rc2_cfb64 39 + +#define SN_rc2_ofb64 "RC2-OFB" +#define LN_rc2_ofb64 "rc2-ofb" +#define NID_rc2_ofb64 40 + +#define SN_rc2_40_cbc "RC2-40-CBC" +#define LN_rc2_40_cbc "rc2-40-cbc" +#define NID_rc2_40_cbc 98 + +#define SN_rc2_64_cbc "RC2-64-CBC" +#define LN_rc2_64_cbc "rc2-64-cbc" +#define NID_rc2_64_cbc 166 + +#define SN_rc4 "RC4" +#define LN_rc4 "rc4" +#define NID_rc4 5 +#define OBJ_rc4 OBJ_rsadsi,3L,4L + +#define SN_rc4_40 "RC4-40" +#define LN_rc4_40 "rc4-40" +#define NID_rc4_40 97 + +#define SN_des_ede3_cbc "DES-EDE3-CBC" +#define LN_des_ede3_cbc "des-ede3-cbc" +#define NID_des_ede3_cbc 44 +#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L + +#define SN_rc5_cbc "RC5-CBC" +#define LN_rc5_cbc "rc5-cbc" +#define NID_rc5_cbc 120 +#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L + +#define SN_rc5_ecb "RC5-ECB" +#define LN_rc5_ecb "rc5-ecb" +#define NID_rc5_ecb 121 + +#define SN_rc5_cfb64 "RC5-CFB" +#define LN_rc5_cfb64 "rc5-cfb" +#define NID_rc5_cfb64 122 + +#define SN_rc5_ofb64 "RC5-OFB" +#define LN_rc5_ofb64 "rc5-ofb" +#define NID_rc5_ofb64 123 + +#define SN_ms_ext_req "msExtReq" +#define LN_ms_ext_req "Microsoft Extension Request" +#define NID_ms_ext_req 171 +#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L + +#define SN_ms_code_ind "msCodeInd" +#define LN_ms_code_ind "Microsoft Individual Code Signing" +#define NID_ms_code_ind 134 +#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L + +#define SN_ms_code_com "msCodeCom" +#define LN_ms_code_com "Microsoft Commercial Code Signing" +#define NID_ms_code_com 135 +#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L + +#define SN_ms_ctl_sign "msCTLSign" +#define LN_ms_ctl_sign "Microsoft Trust List Signing" +#define NID_ms_ctl_sign 136 +#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L + +#define SN_ms_sgc "msSGC" +#define LN_ms_sgc "Microsoft Server Gated Crypto" +#define NID_ms_sgc 137 +#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L + +#define SN_ms_efs "msEFS" +#define LN_ms_efs "Microsoft Encrypted File System" +#define NID_ms_efs 138 +#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L + +#define SN_ms_smartcard_login "msSmartcardLogin" +#define LN_ms_smartcard_login "Microsoft Smartcardlogin" +#define NID_ms_smartcard_login 648 +#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L + +#define SN_ms_upn "msUPN" +#define LN_ms_upn "Microsoft Universal Principal Name" +#define NID_ms_upn 649 +#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L + +#define SN_idea_cbc "IDEA-CBC" +#define LN_idea_cbc "idea-cbc" +#define NID_idea_cbc 34 +#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L + +#define SN_idea_ecb "IDEA-ECB" +#define LN_idea_ecb "idea-ecb" +#define NID_idea_ecb 36 + +#define SN_idea_cfb64 "IDEA-CFB" +#define LN_idea_cfb64 "idea-cfb" +#define NID_idea_cfb64 35 + +#define SN_idea_ofb64 "IDEA-OFB" +#define LN_idea_ofb64 "idea-ofb" +#define NID_idea_ofb64 46 + +#define SN_bf_cbc "BF-CBC" +#define LN_bf_cbc "bf-cbc" +#define NID_bf_cbc 91 +#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L + +#define SN_bf_ecb "BF-ECB" +#define LN_bf_ecb "bf-ecb" +#define NID_bf_ecb 92 + +#define SN_bf_cfb64 "BF-CFB" +#define LN_bf_cfb64 "bf-cfb" +#define NID_bf_cfb64 93 + +#define SN_bf_ofb64 "BF-OFB" +#define LN_bf_ofb64 "bf-ofb" +#define NID_bf_ofb64 94 + +#define SN_id_pkix "PKIX" +#define NID_id_pkix 127 +#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L + +#define SN_id_pkix_mod "id-pkix-mod" +#define NID_id_pkix_mod 258 +#define OBJ_id_pkix_mod OBJ_id_pkix,0L + +#define SN_id_pe "id-pe" +#define NID_id_pe 175 +#define OBJ_id_pe OBJ_id_pkix,1L + +#define SN_id_qt "id-qt" +#define NID_id_qt 259 +#define OBJ_id_qt OBJ_id_pkix,2L + +#define SN_id_kp "id-kp" +#define NID_id_kp 128 +#define OBJ_id_kp OBJ_id_pkix,3L + +#define SN_id_it "id-it" +#define NID_id_it 260 +#define OBJ_id_it OBJ_id_pkix,4L + +#define SN_id_pkip "id-pkip" +#define NID_id_pkip 261 +#define OBJ_id_pkip OBJ_id_pkix,5L + +#define SN_id_alg "id-alg" +#define NID_id_alg 262 +#define OBJ_id_alg OBJ_id_pkix,6L + +#define SN_id_cmc "id-cmc" +#define NID_id_cmc 263 +#define OBJ_id_cmc OBJ_id_pkix,7L + +#define SN_id_on "id-on" +#define NID_id_on 264 +#define OBJ_id_on OBJ_id_pkix,8L + +#define SN_id_pda "id-pda" +#define NID_id_pda 265 +#define OBJ_id_pda OBJ_id_pkix,9L + +#define SN_id_aca "id-aca" +#define NID_id_aca 266 +#define OBJ_id_aca OBJ_id_pkix,10L + +#define SN_id_qcs "id-qcs" +#define NID_id_qcs 267 +#define OBJ_id_qcs OBJ_id_pkix,11L + +#define SN_id_cct "id-cct" +#define NID_id_cct 268 +#define OBJ_id_cct OBJ_id_pkix,12L + +#define SN_id_ppl "id-ppl" +#define NID_id_ppl 662 +#define OBJ_id_ppl OBJ_id_pkix,21L + +#define SN_id_ad "id-ad" +#define NID_id_ad 176 +#define OBJ_id_ad OBJ_id_pkix,48L + +#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88" +#define NID_id_pkix1_explicit_88 269 +#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L + +#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88" +#define NID_id_pkix1_implicit_88 270 +#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L + +#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93" +#define NID_id_pkix1_explicit_93 271 +#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L + +#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93" +#define NID_id_pkix1_implicit_93 272 +#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L + +#define SN_id_mod_crmf "id-mod-crmf" +#define NID_id_mod_crmf 273 +#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L + +#define SN_id_mod_cmc "id-mod-cmc" +#define NID_id_mod_cmc 274 +#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L + +#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88" +#define NID_id_mod_kea_profile_88 275 +#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L + +#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93" +#define NID_id_mod_kea_profile_93 276 +#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L + +#define SN_id_mod_cmp "id-mod-cmp" +#define NID_id_mod_cmp 277 +#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L + +#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88" +#define NID_id_mod_qualified_cert_88 278 +#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L + +#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93" +#define NID_id_mod_qualified_cert_93 279 +#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L + +#define SN_id_mod_attribute_cert "id-mod-attribute-cert" +#define NID_id_mod_attribute_cert 280 +#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L + +#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol" +#define NID_id_mod_timestamp_protocol 281 +#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L + +#define SN_id_mod_ocsp "id-mod-ocsp" +#define NID_id_mod_ocsp 282 +#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L + +#define SN_id_mod_dvcs "id-mod-dvcs" +#define NID_id_mod_dvcs 283 +#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L + +#define SN_id_mod_cmp2000 "id-mod-cmp2000" +#define NID_id_mod_cmp2000 284 +#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L + +#define SN_info_access "authorityInfoAccess" +#define LN_info_access "Authority Information Access" +#define NID_info_access 177 +#define OBJ_info_access OBJ_id_pe,1L + +#define SN_biometricInfo "biometricInfo" +#define LN_biometricInfo "Biometric Info" +#define NID_biometricInfo 285 +#define OBJ_biometricInfo OBJ_id_pe,2L + +#define SN_qcStatements "qcStatements" +#define NID_qcStatements 286 +#define OBJ_qcStatements OBJ_id_pe,3L + +#define SN_ac_auditEntity "ac-auditEntity" +#define NID_ac_auditEntity 287 +#define OBJ_ac_auditEntity OBJ_id_pe,4L + +#define SN_ac_targeting "ac-targeting" +#define NID_ac_targeting 288 +#define OBJ_ac_targeting OBJ_id_pe,5L + +#define SN_aaControls "aaControls" +#define NID_aaControls 289 +#define OBJ_aaControls OBJ_id_pe,6L + +#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock" +#define NID_sbgp_ipAddrBlock 290 +#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L + +#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum" +#define NID_sbgp_autonomousSysNum 291 +#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L + +#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier" +#define NID_sbgp_routerIdentifier 292 +#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L + +#define SN_ac_proxying "ac-proxying" +#define NID_ac_proxying 397 +#define OBJ_ac_proxying OBJ_id_pe,10L + +#define SN_sinfo_access "subjectInfoAccess" +#define LN_sinfo_access "Subject Information Access" +#define NID_sinfo_access 398 +#define OBJ_sinfo_access OBJ_id_pe,11L + +#define SN_proxyCertInfo "proxyCertInfo" +#define LN_proxyCertInfo "Proxy Certificate Information" +#define NID_proxyCertInfo 663 +#define OBJ_proxyCertInfo OBJ_id_pe,14L + +#define SN_id_qt_cps "id-qt-cps" +#define LN_id_qt_cps "Policy Qualifier CPS" +#define NID_id_qt_cps 164 +#define OBJ_id_qt_cps OBJ_id_qt,1L + +#define SN_id_qt_unotice "id-qt-unotice" +#define LN_id_qt_unotice "Policy Qualifier User Notice" +#define NID_id_qt_unotice 165 +#define OBJ_id_qt_unotice OBJ_id_qt,2L + +#define SN_textNotice "textNotice" +#define NID_textNotice 293 +#define OBJ_textNotice OBJ_id_qt,3L + +#define SN_server_auth "serverAuth" +#define LN_server_auth "TLS Web Server Authentication" +#define NID_server_auth 129 +#define OBJ_server_auth OBJ_id_kp,1L + +#define SN_client_auth "clientAuth" +#define LN_client_auth "TLS Web Client Authentication" +#define NID_client_auth 130 +#define OBJ_client_auth OBJ_id_kp,2L + +#define SN_code_sign "codeSigning" +#define LN_code_sign "Code Signing" +#define NID_code_sign 131 +#define OBJ_code_sign OBJ_id_kp,3L + +#define SN_email_protect "emailProtection" +#define LN_email_protect "E-mail Protection" +#define NID_email_protect 132 +#define OBJ_email_protect OBJ_id_kp,4L + +#define SN_ipsecEndSystem "ipsecEndSystem" +#define LN_ipsecEndSystem "IPSec End System" +#define NID_ipsecEndSystem 294 +#define OBJ_ipsecEndSystem OBJ_id_kp,5L + +#define SN_ipsecTunnel "ipsecTunnel" +#define LN_ipsecTunnel "IPSec Tunnel" +#define NID_ipsecTunnel 295 +#define OBJ_ipsecTunnel OBJ_id_kp,6L + +#define SN_ipsecUser "ipsecUser" +#define LN_ipsecUser "IPSec User" +#define NID_ipsecUser 296 +#define OBJ_ipsecUser OBJ_id_kp,7L + +#define SN_time_stamp "timeStamping" +#define LN_time_stamp "Time Stamping" +#define NID_time_stamp 133 +#define OBJ_time_stamp OBJ_id_kp,8L + +#define SN_OCSP_sign "OCSPSigning" +#define LN_OCSP_sign "OCSP Signing" +#define NID_OCSP_sign 180 +#define OBJ_OCSP_sign OBJ_id_kp,9L + +#define SN_dvcs "DVCS" +#define LN_dvcs "dvcs" +#define NID_dvcs 297 +#define OBJ_dvcs OBJ_id_kp,10L + +#define SN_id_it_caProtEncCert "id-it-caProtEncCert" +#define NID_id_it_caProtEncCert 298 +#define OBJ_id_it_caProtEncCert OBJ_id_it,1L + +#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes" +#define NID_id_it_signKeyPairTypes 299 +#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L + +#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes" +#define NID_id_it_encKeyPairTypes 300 +#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L + +#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg" +#define NID_id_it_preferredSymmAlg 301 +#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L + +#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo" +#define NID_id_it_caKeyUpdateInfo 302 +#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L + +#define SN_id_it_currentCRL "id-it-currentCRL" +#define NID_id_it_currentCRL 303 +#define OBJ_id_it_currentCRL OBJ_id_it,6L + +#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs" +#define NID_id_it_unsupportedOIDs 304 +#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L + +#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest" +#define NID_id_it_subscriptionRequest 305 +#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L + +#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse" +#define NID_id_it_subscriptionResponse 306 +#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L + +#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq" +#define NID_id_it_keyPairParamReq 307 +#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L + +#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep" +#define NID_id_it_keyPairParamRep 308 +#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L + +#define SN_id_it_revPassphrase "id-it-revPassphrase" +#define NID_id_it_revPassphrase 309 +#define OBJ_id_it_revPassphrase OBJ_id_it,12L + +#define SN_id_it_implicitConfirm "id-it-implicitConfirm" +#define NID_id_it_implicitConfirm 310 +#define OBJ_id_it_implicitConfirm OBJ_id_it,13L + +#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime" +#define NID_id_it_confirmWaitTime 311 +#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L + +#define SN_id_it_origPKIMessage "id-it-origPKIMessage" +#define NID_id_it_origPKIMessage 312 +#define OBJ_id_it_origPKIMessage OBJ_id_it,15L + +#define SN_id_it_suppLangTags "id-it-suppLangTags" +#define NID_id_it_suppLangTags 784 +#define OBJ_id_it_suppLangTags OBJ_id_it,16L + +#define SN_id_regCtrl "id-regCtrl" +#define NID_id_regCtrl 313 +#define OBJ_id_regCtrl OBJ_id_pkip,1L + +#define SN_id_regInfo "id-regInfo" +#define NID_id_regInfo 314 +#define OBJ_id_regInfo OBJ_id_pkip,2L + +#define SN_id_regCtrl_regToken "id-regCtrl-regToken" +#define NID_id_regCtrl_regToken 315 +#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L + +#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator" +#define NID_id_regCtrl_authenticator 316 +#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L + +#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo" +#define NID_id_regCtrl_pkiPublicationInfo 317 +#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L + +#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions" +#define NID_id_regCtrl_pkiArchiveOptions 318 +#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L + +#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID" +#define NID_id_regCtrl_oldCertID 319 +#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L + +#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey" +#define NID_id_regCtrl_protocolEncrKey 320 +#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L + +#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs" +#define NID_id_regInfo_utf8Pairs 321 +#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L + +#define SN_id_regInfo_certReq "id-regInfo-certReq" +#define NID_id_regInfo_certReq 322 +#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L + +#define SN_id_alg_des40 "id-alg-des40" +#define NID_id_alg_des40 323 +#define OBJ_id_alg_des40 OBJ_id_alg,1L + +#define SN_id_alg_noSignature "id-alg-noSignature" +#define NID_id_alg_noSignature 324 +#define OBJ_id_alg_noSignature OBJ_id_alg,2L + +#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1" +#define NID_id_alg_dh_sig_hmac_sha1 325 +#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L + +#define SN_id_alg_dh_pop "id-alg-dh-pop" +#define NID_id_alg_dh_pop 326 +#define OBJ_id_alg_dh_pop OBJ_id_alg,4L + +#define SN_id_cmc_statusInfo "id-cmc-statusInfo" +#define NID_id_cmc_statusInfo 327 +#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L + +#define SN_id_cmc_identification "id-cmc-identification" +#define NID_id_cmc_identification 328 +#define OBJ_id_cmc_identification OBJ_id_cmc,2L + +#define SN_id_cmc_identityProof "id-cmc-identityProof" +#define NID_id_cmc_identityProof 329 +#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L + +#define SN_id_cmc_dataReturn "id-cmc-dataReturn" +#define NID_id_cmc_dataReturn 330 +#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L + +#define SN_id_cmc_transactionId "id-cmc-transactionId" +#define NID_id_cmc_transactionId 331 +#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L + +#define SN_id_cmc_senderNonce "id-cmc-senderNonce" +#define NID_id_cmc_senderNonce 332 +#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L + +#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce" +#define NID_id_cmc_recipientNonce 333 +#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L + +#define SN_id_cmc_addExtensions "id-cmc-addExtensions" +#define NID_id_cmc_addExtensions 334 +#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L + +#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP" +#define NID_id_cmc_encryptedPOP 335 +#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L + +#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP" +#define NID_id_cmc_decryptedPOP 336 +#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L + +#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness" +#define NID_id_cmc_lraPOPWitness 337 +#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L + +#define SN_id_cmc_getCert "id-cmc-getCert" +#define NID_id_cmc_getCert 338 +#define OBJ_id_cmc_getCert OBJ_id_cmc,15L + +#define SN_id_cmc_getCRL "id-cmc-getCRL" +#define NID_id_cmc_getCRL 339 +#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L + +#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest" +#define NID_id_cmc_revokeRequest 340 +#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L + +#define SN_id_cmc_regInfo "id-cmc-regInfo" +#define NID_id_cmc_regInfo 341 +#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L + +#define SN_id_cmc_responseInfo "id-cmc-responseInfo" +#define NID_id_cmc_responseInfo 342 +#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L + +#define SN_id_cmc_queryPending "id-cmc-queryPending" +#define NID_id_cmc_queryPending 343 +#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L + +#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom" +#define NID_id_cmc_popLinkRandom 344 +#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L + +#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness" +#define NID_id_cmc_popLinkWitness 345 +#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L + +#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance" +#define NID_id_cmc_confirmCertAcceptance 346 +#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L + +#define SN_id_on_personalData "id-on-personalData" +#define NID_id_on_personalData 347 +#define OBJ_id_on_personalData OBJ_id_on,1L + +#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier" +#define LN_id_on_permanentIdentifier "Permanent Identifier" +#define NID_id_on_permanentIdentifier 858 +#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L + +#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth" +#define NID_id_pda_dateOfBirth 348 +#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L + +#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth" +#define NID_id_pda_placeOfBirth 349 +#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L + +#define SN_id_pda_gender "id-pda-gender" +#define NID_id_pda_gender 351 +#define OBJ_id_pda_gender OBJ_id_pda,3L + +#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship" +#define NID_id_pda_countryOfCitizenship 352 +#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L + +#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence" +#define NID_id_pda_countryOfResidence 353 +#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L + +#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo" +#define NID_id_aca_authenticationInfo 354 +#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L + +#define SN_id_aca_accessIdentity "id-aca-accessIdentity" +#define NID_id_aca_accessIdentity 355 +#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L + +#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity" +#define NID_id_aca_chargingIdentity 356 +#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L + +#define SN_id_aca_group "id-aca-group" +#define NID_id_aca_group 357 +#define OBJ_id_aca_group OBJ_id_aca,4L + +#define SN_id_aca_role "id-aca-role" +#define NID_id_aca_role 358 +#define OBJ_id_aca_role OBJ_id_aca,5L + +#define SN_id_aca_encAttrs "id-aca-encAttrs" +#define NID_id_aca_encAttrs 399 +#define OBJ_id_aca_encAttrs OBJ_id_aca,6L + +#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1" +#define NID_id_qcs_pkixQCSyntax_v1 359 +#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L + +#define SN_id_cct_crs "id-cct-crs" +#define NID_id_cct_crs 360 +#define OBJ_id_cct_crs OBJ_id_cct,1L + +#define SN_id_cct_PKIData "id-cct-PKIData" +#define NID_id_cct_PKIData 361 +#define OBJ_id_cct_PKIData OBJ_id_cct,2L + +#define SN_id_cct_PKIResponse "id-cct-PKIResponse" +#define NID_id_cct_PKIResponse 362 +#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L + +#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage" +#define LN_id_ppl_anyLanguage "Any language" +#define NID_id_ppl_anyLanguage 664 +#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L + +#define SN_id_ppl_inheritAll "id-ppl-inheritAll" +#define LN_id_ppl_inheritAll "Inherit all" +#define NID_id_ppl_inheritAll 665 +#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L + +#define SN_Independent "id-ppl-independent" +#define LN_Independent "Independent" +#define NID_Independent 667 +#define OBJ_Independent OBJ_id_ppl,2L + +#define SN_ad_OCSP "OCSP" +#define LN_ad_OCSP "OCSP" +#define NID_ad_OCSP 178 +#define OBJ_ad_OCSP OBJ_id_ad,1L + +#define SN_ad_ca_issuers "caIssuers" +#define LN_ad_ca_issuers "CA Issuers" +#define NID_ad_ca_issuers 179 +#define OBJ_ad_ca_issuers OBJ_id_ad,2L + +#define SN_ad_timeStamping "ad_timestamping" +#define LN_ad_timeStamping "AD Time Stamping" +#define NID_ad_timeStamping 363 +#define OBJ_ad_timeStamping OBJ_id_ad,3L + +#define SN_ad_dvcs "AD_DVCS" +#define LN_ad_dvcs "ad dvcs" +#define NID_ad_dvcs 364 +#define OBJ_ad_dvcs OBJ_id_ad,4L + +#define SN_caRepository "caRepository" +#define LN_caRepository "CA Repository" +#define NID_caRepository 785 +#define OBJ_caRepository OBJ_id_ad,5L + +#define OBJ_id_pkix_OCSP OBJ_ad_OCSP + +#define SN_id_pkix_OCSP_basic "basicOCSPResponse" +#define LN_id_pkix_OCSP_basic "Basic OCSP Response" +#define NID_id_pkix_OCSP_basic 365 +#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L + +#define SN_id_pkix_OCSP_Nonce "Nonce" +#define LN_id_pkix_OCSP_Nonce "OCSP Nonce" +#define NID_id_pkix_OCSP_Nonce 366 +#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L + +#define SN_id_pkix_OCSP_CrlID "CrlID" +#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID" +#define NID_id_pkix_OCSP_CrlID 367 +#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L + +#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses" +#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses" +#define NID_id_pkix_OCSP_acceptableResponses 368 +#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L + +#define SN_id_pkix_OCSP_noCheck "noCheck" +#define LN_id_pkix_OCSP_noCheck "OCSP No Check" +#define NID_id_pkix_OCSP_noCheck 369 +#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L + +#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff" +#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff" +#define NID_id_pkix_OCSP_archiveCutoff 370 +#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L + +#define SN_id_pkix_OCSP_serviceLocator "serviceLocator" +#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator" +#define NID_id_pkix_OCSP_serviceLocator 371 +#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L + +#define SN_id_pkix_OCSP_extendedStatus "extendedStatus" +#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status" +#define NID_id_pkix_OCSP_extendedStatus 372 +#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L + +#define SN_id_pkix_OCSP_valid "valid" +#define NID_id_pkix_OCSP_valid 373 +#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L + +#define SN_id_pkix_OCSP_path "path" +#define NID_id_pkix_OCSP_path 374 +#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L + +#define SN_id_pkix_OCSP_trustRoot "trustRoot" +#define LN_id_pkix_OCSP_trustRoot "Trust Root" +#define NID_id_pkix_OCSP_trustRoot 375 +#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L + +#define SN_algorithm "algorithm" +#define LN_algorithm "algorithm" +#define NID_algorithm 376 +#define OBJ_algorithm 1L,3L,14L,3L,2L + +#define SN_md5WithRSA "RSA-NP-MD5" +#define LN_md5WithRSA "md5WithRSA" +#define NID_md5WithRSA 104 +#define OBJ_md5WithRSA OBJ_algorithm,3L + +#define SN_des_ecb "DES-ECB" +#define LN_des_ecb "des-ecb" +#define NID_des_ecb 29 +#define OBJ_des_ecb OBJ_algorithm,6L + +#define SN_des_cbc "DES-CBC" +#define LN_des_cbc "des-cbc" +#define NID_des_cbc 31 +#define OBJ_des_cbc OBJ_algorithm,7L + +#define SN_des_ofb64 "DES-OFB" +#define LN_des_ofb64 "des-ofb" +#define NID_des_ofb64 45 +#define OBJ_des_ofb64 OBJ_algorithm,8L + +#define SN_des_cfb64 "DES-CFB" +#define LN_des_cfb64 "des-cfb" +#define NID_des_cfb64 30 +#define OBJ_des_cfb64 OBJ_algorithm,9L + +#define SN_rsaSignature "rsaSignature" +#define NID_rsaSignature 377 +#define OBJ_rsaSignature OBJ_algorithm,11L + +#define SN_dsa_2 "DSA-old" +#define LN_dsa_2 "dsaEncryption-old" +#define NID_dsa_2 67 +#define OBJ_dsa_2 OBJ_algorithm,12L + +#define SN_dsaWithSHA "DSA-SHA" +#define LN_dsaWithSHA "dsaWithSHA" +#define NID_dsaWithSHA 66 +#define OBJ_dsaWithSHA OBJ_algorithm,13L + +#define SN_shaWithRSAEncryption "RSA-SHA" +#define LN_shaWithRSAEncryption "shaWithRSAEncryption" +#define NID_shaWithRSAEncryption 42 +#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L + +#define SN_des_ede_ecb "DES-EDE" +#define LN_des_ede_ecb "des-ede" +#define NID_des_ede_ecb 32 +#define OBJ_des_ede_ecb OBJ_algorithm,17L + +#define SN_des_ede3_ecb "DES-EDE3" +#define LN_des_ede3_ecb "des-ede3" +#define NID_des_ede3_ecb 33 + +#define SN_des_ede_cbc "DES-EDE-CBC" +#define LN_des_ede_cbc "des-ede-cbc" +#define NID_des_ede_cbc 43 + +#define SN_des_ede_cfb64 "DES-EDE-CFB" +#define LN_des_ede_cfb64 "des-ede-cfb" +#define NID_des_ede_cfb64 60 + +#define SN_des_ede3_cfb64 "DES-EDE3-CFB" +#define LN_des_ede3_cfb64 "des-ede3-cfb" +#define NID_des_ede3_cfb64 61 + +#define SN_des_ede_ofb64 "DES-EDE-OFB" +#define LN_des_ede_ofb64 "des-ede-ofb" +#define NID_des_ede_ofb64 62 + +#define SN_des_ede3_ofb64 "DES-EDE3-OFB" +#define LN_des_ede3_ofb64 "des-ede3-ofb" +#define NID_des_ede3_ofb64 63 + +#define SN_desx_cbc "DESX-CBC" +#define LN_desx_cbc "desx-cbc" +#define NID_desx_cbc 80 + +#define SN_sha "SHA" +#define LN_sha "sha" +#define NID_sha 41 +#define OBJ_sha OBJ_algorithm,18L + +#define SN_sha1 "SHA1" +#define LN_sha1 "sha1" +#define NID_sha1 64 +#define OBJ_sha1 OBJ_algorithm,26L + +#define SN_dsaWithSHA1_2 "DSA-SHA1-old" +#define LN_dsaWithSHA1_2 "dsaWithSHA1-old" +#define NID_dsaWithSHA1_2 70 +#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L + +#define SN_sha1WithRSA "RSA-SHA1-2" +#define LN_sha1WithRSA "sha1WithRSA" +#define NID_sha1WithRSA 115 +#define OBJ_sha1WithRSA OBJ_algorithm,29L + +#define SN_ripemd160 "RIPEMD160" +#define LN_ripemd160 "ripemd160" +#define NID_ripemd160 117 +#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L + +#define SN_ripemd160WithRSA "RSA-RIPEMD160" +#define LN_ripemd160WithRSA "ripemd160WithRSA" +#define NID_ripemd160WithRSA 119 +#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L + +#define SN_sxnet "SXNetID" +#define LN_sxnet "Strong Extranet ID" +#define NID_sxnet 143 +#define OBJ_sxnet 1L,3L,101L,1L,4L,1L + +#define SN_X500 "X500" +#define LN_X500 "directory services (X.500)" +#define NID_X500 11 +#define OBJ_X500 2L,5L + +#define SN_X509 "X509" +#define NID_X509 12 +#define OBJ_X509 OBJ_X500,4L + +#define SN_commonName "CN" +#define LN_commonName "commonName" +#define NID_commonName 13 +#define OBJ_commonName OBJ_X509,3L + +#define SN_surname "SN" +#define LN_surname "surname" +#define NID_surname 100 +#define OBJ_surname OBJ_X509,4L + +#define LN_serialNumber "serialNumber" +#define NID_serialNumber 105 +#define OBJ_serialNumber OBJ_X509,5L + +#define SN_countryName "C" +#define LN_countryName "countryName" +#define NID_countryName 14 +#define OBJ_countryName OBJ_X509,6L + +#define SN_localityName "L" +#define LN_localityName "localityName" +#define NID_localityName 15 +#define OBJ_localityName OBJ_X509,7L + +#define SN_stateOrProvinceName "ST" +#define LN_stateOrProvinceName "stateOrProvinceName" +#define NID_stateOrProvinceName 16 +#define OBJ_stateOrProvinceName OBJ_X509,8L + +#define SN_streetAddress "street" +#define LN_streetAddress "streetAddress" +#define NID_streetAddress 660 +#define OBJ_streetAddress OBJ_X509,9L + +#define SN_organizationName "O" +#define LN_organizationName "organizationName" +#define NID_organizationName 17 +#define OBJ_organizationName OBJ_X509,10L + +#define SN_organizationalUnitName "OU" +#define LN_organizationalUnitName "organizationalUnitName" +#define NID_organizationalUnitName 18 +#define OBJ_organizationalUnitName OBJ_X509,11L + +#define SN_title "title" +#define LN_title "title" +#define NID_title 106 +#define OBJ_title OBJ_X509,12L + +#define LN_description "description" +#define NID_description 107 +#define OBJ_description OBJ_X509,13L + +#define LN_searchGuide "searchGuide" +#define NID_searchGuide 859 +#define OBJ_searchGuide OBJ_X509,14L + +#define LN_businessCategory "businessCategory" +#define NID_businessCategory 860 +#define OBJ_businessCategory OBJ_X509,15L + +#define LN_postalAddress "postalAddress" +#define NID_postalAddress 861 +#define OBJ_postalAddress OBJ_X509,16L + +#define LN_postalCode "postalCode" +#define NID_postalCode 661 +#define OBJ_postalCode OBJ_X509,17L + +#define LN_postOfficeBox "postOfficeBox" +#define NID_postOfficeBox 862 +#define OBJ_postOfficeBox OBJ_X509,18L + +#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName" +#define NID_physicalDeliveryOfficeName 863 +#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L + +#define LN_telephoneNumber "telephoneNumber" +#define NID_telephoneNumber 864 +#define OBJ_telephoneNumber OBJ_X509,20L + +#define LN_telexNumber "telexNumber" +#define NID_telexNumber 865 +#define OBJ_telexNumber OBJ_X509,21L + +#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier" +#define NID_teletexTerminalIdentifier 866 +#define OBJ_teletexTerminalIdentifier OBJ_X509,22L + +#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber" +#define NID_facsimileTelephoneNumber 867 +#define OBJ_facsimileTelephoneNumber OBJ_X509,23L + +#define LN_x121Address "x121Address" +#define NID_x121Address 868 +#define OBJ_x121Address OBJ_X509,24L + +#define LN_internationaliSDNNumber "internationaliSDNNumber" +#define NID_internationaliSDNNumber 869 +#define OBJ_internationaliSDNNumber OBJ_X509,25L + +#define LN_registeredAddress "registeredAddress" +#define NID_registeredAddress 870 +#define OBJ_registeredAddress OBJ_X509,26L + +#define LN_destinationIndicator "destinationIndicator" +#define NID_destinationIndicator 871 +#define OBJ_destinationIndicator OBJ_X509,27L + +#define LN_preferredDeliveryMethod "preferredDeliveryMethod" +#define NID_preferredDeliveryMethod 872 +#define OBJ_preferredDeliveryMethod OBJ_X509,28L + +#define LN_presentationAddress "presentationAddress" +#define NID_presentationAddress 873 +#define OBJ_presentationAddress OBJ_X509,29L + +#define LN_supportedApplicationContext "supportedApplicationContext" +#define NID_supportedApplicationContext 874 +#define OBJ_supportedApplicationContext OBJ_X509,30L + +#define SN_member "member" +#define NID_member 875 +#define OBJ_member OBJ_X509,31L + +#define SN_owner "owner" +#define NID_owner 876 +#define OBJ_owner OBJ_X509,32L + +#define LN_roleOccupant "roleOccupant" +#define NID_roleOccupant 877 +#define OBJ_roleOccupant OBJ_X509,33L + +#define SN_seeAlso "seeAlso" +#define NID_seeAlso 878 +#define OBJ_seeAlso OBJ_X509,34L + +#define LN_userPassword "userPassword" +#define NID_userPassword 879 +#define OBJ_userPassword OBJ_X509,35L + +#define LN_userCertificate "userCertificate" +#define NID_userCertificate 880 +#define OBJ_userCertificate OBJ_X509,36L + +#define LN_cACertificate "cACertificate" +#define NID_cACertificate 881 +#define OBJ_cACertificate OBJ_X509,37L + +#define LN_authorityRevocationList "authorityRevocationList" +#define NID_authorityRevocationList 882 +#define OBJ_authorityRevocationList OBJ_X509,38L + +#define LN_certificateRevocationList "certificateRevocationList" +#define NID_certificateRevocationList 883 +#define OBJ_certificateRevocationList OBJ_X509,39L + +#define LN_crossCertificatePair "crossCertificatePair" +#define NID_crossCertificatePair 884 +#define OBJ_crossCertificatePair OBJ_X509,40L + +#define SN_name "name" +#define LN_name "name" +#define NID_name 173 +#define OBJ_name OBJ_X509,41L + +#define SN_givenName "GN" +#define LN_givenName "givenName" +#define NID_givenName 99 +#define OBJ_givenName OBJ_X509,42L + +#define SN_initials "initials" +#define LN_initials "initials" +#define NID_initials 101 +#define OBJ_initials OBJ_X509,43L + +#define LN_generationQualifier "generationQualifier" +#define NID_generationQualifier 509 +#define OBJ_generationQualifier OBJ_X509,44L + +#define LN_x500UniqueIdentifier "x500UniqueIdentifier" +#define NID_x500UniqueIdentifier 503 +#define OBJ_x500UniqueIdentifier OBJ_X509,45L + +#define SN_dnQualifier "dnQualifier" +#define LN_dnQualifier "dnQualifier" +#define NID_dnQualifier 174 +#define OBJ_dnQualifier OBJ_X509,46L + +#define LN_enhancedSearchGuide "enhancedSearchGuide" +#define NID_enhancedSearchGuide 885 +#define OBJ_enhancedSearchGuide OBJ_X509,47L + +#define LN_protocolInformation "protocolInformation" +#define NID_protocolInformation 886 +#define OBJ_protocolInformation OBJ_X509,48L + +#define LN_distinguishedName "distinguishedName" +#define NID_distinguishedName 887 +#define OBJ_distinguishedName OBJ_X509,49L + +#define LN_uniqueMember "uniqueMember" +#define NID_uniqueMember 888 +#define OBJ_uniqueMember OBJ_X509,50L + +#define LN_houseIdentifier "houseIdentifier" +#define NID_houseIdentifier 889 +#define OBJ_houseIdentifier OBJ_X509,51L + +#define LN_supportedAlgorithms "supportedAlgorithms" +#define NID_supportedAlgorithms 890 +#define OBJ_supportedAlgorithms OBJ_X509,52L + +#define LN_deltaRevocationList "deltaRevocationList" +#define NID_deltaRevocationList 891 +#define OBJ_deltaRevocationList OBJ_X509,53L + +#define SN_dmdName "dmdName" +#define NID_dmdName 892 +#define OBJ_dmdName OBJ_X509,54L + +#define LN_pseudonym "pseudonym" +#define NID_pseudonym 510 +#define OBJ_pseudonym OBJ_X509,65L + +#define SN_role "role" +#define LN_role "role" +#define NID_role 400 +#define OBJ_role OBJ_X509,72L + +#define SN_X500algorithms "X500algorithms" +#define LN_X500algorithms "directory services - algorithms" +#define NID_X500algorithms 378 +#define OBJ_X500algorithms OBJ_X500,8L + +#define SN_rsa "RSA" +#define LN_rsa "rsa" +#define NID_rsa 19 +#define OBJ_rsa OBJ_X500algorithms,1L,1L + +#define SN_mdc2WithRSA "RSA-MDC2" +#define LN_mdc2WithRSA "mdc2WithRSA" +#define NID_mdc2WithRSA 96 +#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L + +#define SN_mdc2 "MDC2" +#define LN_mdc2 "mdc2" +#define NID_mdc2 95 +#define OBJ_mdc2 OBJ_X500algorithms,3L,101L + +#define SN_id_ce "id-ce" +#define NID_id_ce 81 +#define OBJ_id_ce OBJ_X500,29L + +#define SN_subject_directory_attributes "subjectDirectoryAttributes" +#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes" +#define NID_subject_directory_attributes 769 +#define OBJ_subject_directory_attributes OBJ_id_ce,9L + +#define SN_subject_key_identifier "subjectKeyIdentifier" +#define LN_subject_key_identifier "X509v3 Subject Key Identifier" +#define NID_subject_key_identifier 82 +#define OBJ_subject_key_identifier OBJ_id_ce,14L + +#define SN_key_usage "keyUsage" +#define LN_key_usage "X509v3 Key Usage" +#define NID_key_usage 83 +#define OBJ_key_usage OBJ_id_ce,15L + +#define SN_private_key_usage_period "privateKeyUsagePeriod" +#define LN_private_key_usage_period "X509v3 Private Key Usage Period" +#define NID_private_key_usage_period 84 +#define OBJ_private_key_usage_period OBJ_id_ce,16L + +#define SN_subject_alt_name "subjectAltName" +#define LN_subject_alt_name "X509v3 Subject Alternative Name" +#define NID_subject_alt_name 85 +#define OBJ_subject_alt_name OBJ_id_ce,17L + +#define SN_issuer_alt_name "issuerAltName" +#define LN_issuer_alt_name "X509v3 Issuer Alternative Name" +#define NID_issuer_alt_name 86 +#define OBJ_issuer_alt_name OBJ_id_ce,18L + +#define SN_basic_constraints "basicConstraints" +#define LN_basic_constraints "X509v3 Basic Constraints" +#define NID_basic_constraints 87 +#define OBJ_basic_constraints OBJ_id_ce,19L + +#define SN_crl_number "crlNumber" +#define LN_crl_number "X509v3 CRL Number" +#define NID_crl_number 88 +#define OBJ_crl_number OBJ_id_ce,20L + +#define SN_crl_reason "CRLReason" +#define LN_crl_reason "X509v3 CRL Reason Code" +#define NID_crl_reason 141 +#define OBJ_crl_reason OBJ_id_ce,21L + +#define SN_invalidity_date "invalidityDate" +#define LN_invalidity_date "Invalidity Date" +#define NID_invalidity_date 142 +#define OBJ_invalidity_date OBJ_id_ce,24L + +#define SN_delta_crl "deltaCRL" +#define LN_delta_crl "X509v3 Delta CRL Indicator" +#define NID_delta_crl 140 +#define OBJ_delta_crl OBJ_id_ce,27L + +#define SN_issuing_distribution_point "issuingDistributionPoint" +#define LN_issuing_distribution_point "X509v3 Issuing Distrubution Point" +#define NID_issuing_distribution_point 770 +#define OBJ_issuing_distribution_point OBJ_id_ce,28L + +#define SN_certificate_issuer "certificateIssuer" +#define LN_certificate_issuer "X509v3 Certificate Issuer" +#define NID_certificate_issuer 771 +#define OBJ_certificate_issuer OBJ_id_ce,29L + +#define SN_name_constraints "nameConstraints" +#define LN_name_constraints "X509v3 Name Constraints" +#define NID_name_constraints 666 +#define OBJ_name_constraints OBJ_id_ce,30L + +#define SN_crl_distribution_points "crlDistributionPoints" +#define LN_crl_distribution_points "X509v3 CRL Distribution Points" +#define NID_crl_distribution_points 103 +#define OBJ_crl_distribution_points OBJ_id_ce,31L + +#define SN_certificate_policies "certificatePolicies" +#define LN_certificate_policies "X509v3 Certificate Policies" +#define NID_certificate_policies 89 +#define OBJ_certificate_policies OBJ_id_ce,32L + +#define SN_any_policy "anyPolicy" +#define LN_any_policy "X509v3 Any Policy" +#define NID_any_policy 746 +#define OBJ_any_policy OBJ_certificate_policies,0L + +#define SN_policy_mappings "policyMappings" +#define LN_policy_mappings "X509v3 Policy Mappings" +#define NID_policy_mappings 747 +#define OBJ_policy_mappings OBJ_id_ce,33L + +#define SN_authority_key_identifier "authorityKeyIdentifier" +#define LN_authority_key_identifier "X509v3 Authority Key Identifier" +#define NID_authority_key_identifier 90 +#define OBJ_authority_key_identifier OBJ_id_ce,35L + +#define SN_policy_constraints "policyConstraints" +#define LN_policy_constraints "X509v3 Policy Constraints" +#define NID_policy_constraints 401 +#define OBJ_policy_constraints OBJ_id_ce,36L + +#define SN_ext_key_usage "extendedKeyUsage" +#define LN_ext_key_usage "X509v3 Extended Key Usage" +#define NID_ext_key_usage 126 +#define OBJ_ext_key_usage OBJ_id_ce,37L + +#define SN_freshest_crl "freshestCRL" +#define LN_freshest_crl "X509v3 Freshest CRL" +#define NID_freshest_crl 857 +#define OBJ_freshest_crl OBJ_id_ce,46L + +#define SN_inhibit_any_policy "inhibitAnyPolicy" +#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy" +#define NID_inhibit_any_policy 748 +#define OBJ_inhibit_any_policy OBJ_id_ce,54L + +#define SN_target_information "targetInformation" +#define LN_target_information "X509v3 AC Targeting" +#define NID_target_information 402 +#define OBJ_target_information OBJ_id_ce,55L + +#define SN_no_rev_avail "noRevAvail" +#define LN_no_rev_avail "X509v3 No Revocation Available" +#define NID_no_rev_avail 403 +#define OBJ_no_rev_avail OBJ_id_ce,56L + +#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage" +#define LN_anyExtendedKeyUsage "Any Extended Key Usage" +#define NID_anyExtendedKeyUsage 910 +#define OBJ_anyExtendedKeyUsage OBJ_ext_key_usage,0L + +#define SN_netscape "Netscape" +#define LN_netscape "Netscape Communications Corp." +#define NID_netscape 57 +#define OBJ_netscape 2L,16L,840L,1L,113730L + +#define SN_netscape_cert_extension "nsCertExt" +#define LN_netscape_cert_extension "Netscape Certificate Extension" +#define NID_netscape_cert_extension 58 +#define OBJ_netscape_cert_extension OBJ_netscape,1L + +#define SN_netscape_data_type "nsDataType" +#define LN_netscape_data_type "Netscape Data Type" +#define NID_netscape_data_type 59 +#define OBJ_netscape_data_type OBJ_netscape,2L + +#define SN_netscape_cert_type "nsCertType" +#define LN_netscape_cert_type "Netscape Cert Type" +#define NID_netscape_cert_type 71 +#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L + +#define SN_netscape_base_url "nsBaseUrl" +#define LN_netscape_base_url "Netscape Base Url" +#define NID_netscape_base_url 72 +#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L + +#define SN_netscape_revocation_url "nsRevocationUrl" +#define LN_netscape_revocation_url "Netscape Revocation Url" +#define NID_netscape_revocation_url 73 +#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L + +#define SN_netscape_ca_revocation_url "nsCaRevocationUrl" +#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url" +#define NID_netscape_ca_revocation_url 74 +#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L + +#define SN_netscape_renewal_url "nsRenewalUrl" +#define LN_netscape_renewal_url "Netscape Renewal Url" +#define NID_netscape_renewal_url 75 +#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L + +#define SN_netscape_ca_policy_url "nsCaPolicyUrl" +#define LN_netscape_ca_policy_url "Netscape CA Policy Url" +#define NID_netscape_ca_policy_url 76 +#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L + +#define SN_netscape_ssl_server_name "nsSslServerName" +#define LN_netscape_ssl_server_name "Netscape SSL Server Name" +#define NID_netscape_ssl_server_name 77 +#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L + +#define SN_netscape_comment "nsComment" +#define LN_netscape_comment "Netscape Comment" +#define NID_netscape_comment 78 +#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L + +#define SN_netscape_cert_sequence "nsCertSequence" +#define LN_netscape_cert_sequence "Netscape Certificate Sequence" +#define NID_netscape_cert_sequence 79 +#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L + +#define SN_ns_sgc "nsSGC" +#define LN_ns_sgc "Netscape Server Gated Crypto" +#define NID_ns_sgc 139 +#define OBJ_ns_sgc OBJ_netscape,4L,1L + +#define SN_org "ORG" +#define LN_org "org" +#define NID_org 379 +#define OBJ_org OBJ_iso,3L + +#define SN_dod "DOD" +#define LN_dod "dod" +#define NID_dod 380 +#define OBJ_dod OBJ_org,6L + +#define SN_iana "IANA" +#define LN_iana "iana" +#define NID_iana 381 +#define OBJ_iana OBJ_dod,1L + +#define OBJ_internet OBJ_iana + +#define SN_Directory "directory" +#define LN_Directory "Directory" +#define NID_Directory 382 +#define OBJ_Directory OBJ_internet,1L + +#define SN_Management "mgmt" +#define LN_Management "Management" +#define NID_Management 383 +#define OBJ_Management OBJ_internet,2L + +#define SN_Experimental "experimental" +#define LN_Experimental "Experimental" +#define NID_Experimental 384 +#define OBJ_Experimental OBJ_internet,3L + +#define SN_Private "private" +#define LN_Private "Private" +#define NID_Private 385 +#define OBJ_Private OBJ_internet,4L + +#define SN_Security "security" +#define LN_Security "Security" +#define NID_Security 386 +#define OBJ_Security OBJ_internet,5L + +#define SN_SNMPv2 "snmpv2" +#define LN_SNMPv2 "SNMPv2" +#define NID_SNMPv2 387 +#define OBJ_SNMPv2 OBJ_internet,6L + +#define LN_Mail "Mail" +#define NID_Mail 388 +#define OBJ_Mail OBJ_internet,7L + +#define SN_Enterprises "enterprises" +#define LN_Enterprises "Enterprises" +#define NID_Enterprises 389 +#define OBJ_Enterprises OBJ_Private,1L + +#define SN_dcObject "dcobject" +#define LN_dcObject "dcObject" +#define NID_dcObject 390 +#define OBJ_dcObject OBJ_Enterprises,1466L,344L + +#define SN_mime_mhs "mime-mhs" +#define LN_mime_mhs "MIME MHS" +#define NID_mime_mhs 504 +#define OBJ_mime_mhs OBJ_Mail,1L + +#define SN_mime_mhs_headings "mime-mhs-headings" +#define LN_mime_mhs_headings "mime-mhs-headings" +#define NID_mime_mhs_headings 505 +#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L + +#define SN_mime_mhs_bodies "mime-mhs-bodies" +#define LN_mime_mhs_bodies "mime-mhs-bodies" +#define NID_mime_mhs_bodies 506 +#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L + +#define SN_id_hex_partial_message "id-hex-partial-message" +#define LN_id_hex_partial_message "id-hex-partial-message" +#define NID_id_hex_partial_message 507 +#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L + +#define SN_id_hex_multipart_message "id-hex-multipart-message" +#define LN_id_hex_multipart_message "id-hex-multipart-message" +#define NID_id_hex_multipart_message 508 +#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L + +#define SN_rle_compression "RLE" +#define LN_rle_compression "run length compression" +#define NID_rle_compression 124 +#define OBJ_rle_compression 1L,1L,1L,1L,666L,1L + +#define SN_zlib_compression "ZLIB" +#define LN_zlib_compression "zlib compression" +#define NID_zlib_compression 125 +#define OBJ_zlib_compression OBJ_id_smime_alg,8L + +#define OBJ_csor 2L,16L,840L,1L,101L,3L + +#define OBJ_nistAlgorithms OBJ_csor,4L + +#define OBJ_aes OBJ_nistAlgorithms,1L + +#define SN_aes_128_ecb "AES-128-ECB" +#define LN_aes_128_ecb "aes-128-ecb" +#define NID_aes_128_ecb 418 +#define OBJ_aes_128_ecb OBJ_aes,1L + +#define SN_aes_128_cbc "AES-128-CBC" +#define LN_aes_128_cbc "aes-128-cbc" +#define NID_aes_128_cbc 419 +#define OBJ_aes_128_cbc OBJ_aes,2L + +#define SN_aes_128_ofb128 "AES-128-OFB" +#define LN_aes_128_ofb128 "aes-128-ofb" +#define NID_aes_128_ofb128 420 +#define OBJ_aes_128_ofb128 OBJ_aes,3L + +#define SN_aes_128_cfb128 "AES-128-CFB" +#define LN_aes_128_cfb128 "aes-128-cfb" +#define NID_aes_128_cfb128 421 +#define OBJ_aes_128_cfb128 OBJ_aes,4L + +#define SN_id_aes128_wrap "id-aes128-wrap" +#define NID_id_aes128_wrap 788 +#define OBJ_id_aes128_wrap OBJ_aes,5L + +#define SN_aes_128_gcm "id-aes128-GCM" +#define LN_aes_128_gcm "aes-128-gcm" +#define NID_aes_128_gcm 895 +#define OBJ_aes_128_gcm OBJ_aes,6L + +#define SN_aes_128_ccm "id-aes128-CCM" +#define LN_aes_128_ccm "aes-128-ccm" +#define NID_aes_128_ccm 896 +#define OBJ_aes_128_ccm OBJ_aes,7L + +#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad" +#define NID_id_aes128_wrap_pad 897 +#define OBJ_id_aes128_wrap_pad OBJ_aes,8L + +#define SN_aes_192_ecb "AES-192-ECB" +#define LN_aes_192_ecb "aes-192-ecb" +#define NID_aes_192_ecb 422 +#define OBJ_aes_192_ecb OBJ_aes,21L + +#define SN_aes_192_cbc "AES-192-CBC" +#define LN_aes_192_cbc "aes-192-cbc" +#define NID_aes_192_cbc 423 +#define OBJ_aes_192_cbc OBJ_aes,22L + +#define SN_aes_192_ofb128 "AES-192-OFB" +#define LN_aes_192_ofb128 "aes-192-ofb" +#define NID_aes_192_ofb128 424 +#define OBJ_aes_192_ofb128 OBJ_aes,23L + +#define SN_aes_192_cfb128 "AES-192-CFB" +#define LN_aes_192_cfb128 "aes-192-cfb" +#define NID_aes_192_cfb128 425 +#define OBJ_aes_192_cfb128 OBJ_aes,24L + +#define SN_id_aes192_wrap "id-aes192-wrap" +#define NID_id_aes192_wrap 789 +#define OBJ_id_aes192_wrap OBJ_aes,25L + +#define SN_aes_192_gcm "id-aes192-GCM" +#define LN_aes_192_gcm "aes-192-gcm" +#define NID_aes_192_gcm 898 +#define OBJ_aes_192_gcm OBJ_aes,26L + +#define SN_aes_192_ccm "id-aes192-CCM" +#define LN_aes_192_ccm "aes-192-ccm" +#define NID_aes_192_ccm 899 +#define OBJ_aes_192_ccm OBJ_aes,27L + +#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad" +#define NID_id_aes192_wrap_pad 900 +#define OBJ_id_aes192_wrap_pad OBJ_aes,28L + +#define SN_aes_256_ecb "AES-256-ECB" +#define LN_aes_256_ecb "aes-256-ecb" +#define NID_aes_256_ecb 426 +#define OBJ_aes_256_ecb OBJ_aes,41L + +#define SN_aes_256_cbc "AES-256-CBC" +#define LN_aes_256_cbc "aes-256-cbc" +#define NID_aes_256_cbc 427 +#define OBJ_aes_256_cbc OBJ_aes,42L + +#define SN_aes_256_ofb128 "AES-256-OFB" +#define LN_aes_256_ofb128 "aes-256-ofb" +#define NID_aes_256_ofb128 428 +#define OBJ_aes_256_ofb128 OBJ_aes,43L + +#define SN_aes_256_cfb128 "AES-256-CFB" +#define LN_aes_256_cfb128 "aes-256-cfb" +#define NID_aes_256_cfb128 429 +#define OBJ_aes_256_cfb128 OBJ_aes,44L + +#define SN_id_aes256_wrap "id-aes256-wrap" +#define NID_id_aes256_wrap 790 +#define OBJ_id_aes256_wrap OBJ_aes,45L + +#define SN_aes_256_gcm "id-aes256-GCM" +#define LN_aes_256_gcm "aes-256-gcm" +#define NID_aes_256_gcm 901 +#define OBJ_aes_256_gcm OBJ_aes,46L + +#define SN_aes_256_ccm "id-aes256-CCM" +#define LN_aes_256_ccm "aes-256-ccm" +#define NID_aes_256_ccm 902 +#define OBJ_aes_256_ccm OBJ_aes,47L + +#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad" +#define NID_id_aes256_wrap_pad 903 +#define OBJ_id_aes256_wrap_pad OBJ_aes,48L + +#define SN_aes_128_cfb1 "AES-128-CFB1" +#define LN_aes_128_cfb1 "aes-128-cfb1" +#define NID_aes_128_cfb1 650 + +#define SN_aes_192_cfb1 "AES-192-CFB1" +#define LN_aes_192_cfb1 "aes-192-cfb1" +#define NID_aes_192_cfb1 651 + +#define SN_aes_256_cfb1 "AES-256-CFB1" +#define LN_aes_256_cfb1 "aes-256-cfb1" +#define NID_aes_256_cfb1 652 + +#define SN_aes_128_cfb8 "AES-128-CFB8" +#define LN_aes_128_cfb8 "aes-128-cfb8" +#define NID_aes_128_cfb8 653 + +#define SN_aes_192_cfb8 "AES-192-CFB8" +#define LN_aes_192_cfb8 "aes-192-cfb8" +#define NID_aes_192_cfb8 654 + +#define SN_aes_256_cfb8 "AES-256-CFB8" +#define LN_aes_256_cfb8 "aes-256-cfb8" +#define NID_aes_256_cfb8 655 + +#define SN_aes_128_ctr "AES-128-CTR" +#define LN_aes_128_ctr "aes-128-ctr" +#define NID_aes_128_ctr 904 + +#define SN_aes_192_ctr "AES-192-CTR" +#define LN_aes_192_ctr "aes-192-ctr" +#define NID_aes_192_ctr 905 + +#define SN_aes_256_ctr "AES-256-CTR" +#define LN_aes_256_ctr "aes-256-ctr" +#define NID_aes_256_ctr 906 + +#define SN_aes_128_xts "AES-128-XTS" +#define LN_aes_128_xts "aes-128-xts" +#define NID_aes_128_xts 913 + +#define SN_aes_256_xts "AES-256-XTS" +#define LN_aes_256_xts "aes-256-xts" +#define NID_aes_256_xts 914 + +#define SN_des_cfb1 "DES-CFB1" +#define LN_des_cfb1 "des-cfb1" +#define NID_des_cfb1 656 + +#define SN_des_cfb8 "DES-CFB8" +#define LN_des_cfb8 "des-cfb8" +#define NID_des_cfb8 657 + +#define SN_des_ede3_cfb1 "DES-EDE3-CFB1" +#define LN_des_ede3_cfb1 "des-ede3-cfb1" +#define NID_des_ede3_cfb1 658 + +#define SN_des_ede3_cfb8 "DES-EDE3-CFB8" +#define LN_des_ede3_cfb8 "des-ede3-cfb8" +#define NID_des_ede3_cfb8 659 + +#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L + +#define SN_sha256 "SHA256" +#define LN_sha256 "sha256" +#define NID_sha256 672 +#define OBJ_sha256 OBJ_nist_hashalgs,1L + +#define SN_sha384 "SHA384" +#define LN_sha384 "sha384" +#define NID_sha384 673 +#define OBJ_sha384 OBJ_nist_hashalgs,2L + +#define SN_sha512 "SHA512" +#define LN_sha512 "sha512" +#define NID_sha512 674 +#define OBJ_sha512 OBJ_nist_hashalgs,3L + +#define SN_sha224 "SHA224" +#define LN_sha224 "sha224" +#define NID_sha224 675 +#define OBJ_sha224 OBJ_nist_hashalgs,4L + +#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L + +#define SN_dsa_with_SHA224 "dsa_with_SHA224" +#define NID_dsa_with_SHA224 802 +#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L + +#define SN_dsa_with_SHA256 "dsa_with_SHA256" +#define NID_dsa_with_SHA256 803 +#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L + +#define SN_hold_instruction_code "holdInstructionCode" +#define LN_hold_instruction_code "Hold Instruction Code" +#define NID_hold_instruction_code 430 +#define OBJ_hold_instruction_code OBJ_id_ce,23L + +#define OBJ_holdInstruction OBJ_X9_57,2L + +#define SN_hold_instruction_none "holdInstructionNone" +#define LN_hold_instruction_none "Hold Instruction None" +#define NID_hold_instruction_none 431 +#define OBJ_hold_instruction_none OBJ_holdInstruction,1L + +#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer" +#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer" +#define NID_hold_instruction_call_issuer 432 +#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L + +#define SN_hold_instruction_reject "holdInstructionReject" +#define LN_hold_instruction_reject "Hold Instruction Reject" +#define NID_hold_instruction_reject 433 +#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L + +#define SN_data "data" +#define NID_data 434 +#define OBJ_data OBJ_itu_t,9L + +#define SN_pss "pss" +#define NID_pss 435 +#define OBJ_pss OBJ_data,2342L + +#define SN_ucl "ucl" +#define NID_ucl 436 +#define OBJ_ucl OBJ_pss,19200300L + +#define SN_pilot "pilot" +#define NID_pilot 437 +#define OBJ_pilot OBJ_ucl,100L + +#define LN_pilotAttributeType "pilotAttributeType" +#define NID_pilotAttributeType 438 +#define OBJ_pilotAttributeType OBJ_pilot,1L + +#define LN_pilotAttributeSyntax "pilotAttributeSyntax" +#define NID_pilotAttributeSyntax 439 +#define OBJ_pilotAttributeSyntax OBJ_pilot,3L + +#define LN_pilotObjectClass "pilotObjectClass" +#define NID_pilotObjectClass 440 +#define OBJ_pilotObjectClass OBJ_pilot,4L + +#define LN_pilotGroups "pilotGroups" +#define NID_pilotGroups 441 +#define OBJ_pilotGroups OBJ_pilot,10L + +#define LN_iA5StringSyntax "iA5StringSyntax" +#define NID_iA5StringSyntax 442 +#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L + +#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax" +#define NID_caseIgnoreIA5StringSyntax 443 +#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L + +#define LN_pilotObject "pilotObject" +#define NID_pilotObject 444 +#define OBJ_pilotObject OBJ_pilotObjectClass,3L + +#define LN_pilotPerson "pilotPerson" +#define NID_pilotPerson 445 +#define OBJ_pilotPerson OBJ_pilotObjectClass,4L + +#define SN_account "account" +#define NID_account 446 +#define OBJ_account OBJ_pilotObjectClass,5L + +#define SN_document "document" +#define NID_document 447 +#define OBJ_document OBJ_pilotObjectClass,6L + +#define SN_room "room" +#define NID_room 448 +#define OBJ_room OBJ_pilotObjectClass,7L + +#define LN_documentSeries "documentSeries" +#define NID_documentSeries 449 +#define OBJ_documentSeries OBJ_pilotObjectClass,9L + +#define SN_Domain "domain" +#define LN_Domain "Domain" +#define NID_Domain 392 +#define OBJ_Domain OBJ_pilotObjectClass,13L + +#define LN_rFC822localPart "rFC822localPart" +#define NID_rFC822localPart 450 +#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L + +#define LN_dNSDomain "dNSDomain" +#define NID_dNSDomain 451 +#define OBJ_dNSDomain OBJ_pilotObjectClass,15L + +#define LN_domainRelatedObject "domainRelatedObject" +#define NID_domainRelatedObject 452 +#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L + +#define LN_friendlyCountry "friendlyCountry" +#define NID_friendlyCountry 453 +#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L + +#define LN_simpleSecurityObject "simpleSecurityObject" +#define NID_simpleSecurityObject 454 +#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L + +#define LN_pilotOrganization "pilotOrganization" +#define NID_pilotOrganization 455 +#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L + +#define LN_pilotDSA "pilotDSA" +#define NID_pilotDSA 456 +#define OBJ_pilotDSA OBJ_pilotObjectClass,21L + +#define LN_qualityLabelledData "qualityLabelledData" +#define NID_qualityLabelledData 457 +#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L + +#define SN_userId "UID" +#define LN_userId "userId" +#define NID_userId 458 +#define OBJ_userId OBJ_pilotAttributeType,1L + +#define LN_textEncodedORAddress "textEncodedORAddress" +#define NID_textEncodedORAddress 459 +#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L + +#define SN_rfc822Mailbox "mail" +#define LN_rfc822Mailbox "rfc822Mailbox" +#define NID_rfc822Mailbox 460 +#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L + +#define SN_info "info" +#define NID_info 461 +#define OBJ_info OBJ_pilotAttributeType,4L + +#define LN_favouriteDrink "favouriteDrink" +#define NID_favouriteDrink 462 +#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L + +#define LN_roomNumber "roomNumber" +#define NID_roomNumber 463 +#define OBJ_roomNumber OBJ_pilotAttributeType,6L + +#define SN_photo "photo" +#define NID_photo 464 +#define OBJ_photo OBJ_pilotAttributeType,7L + +#define LN_userClass "userClass" +#define NID_userClass 465 +#define OBJ_userClass OBJ_pilotAttributeType,8L + +#define SN_host "host" +#define NID_host 466 +#define OBJ_host OBJ_pilotAttributeType,9L + +#define SN_manager "manager" +#define NID_manager 467 +#define OBJ_manager OBJ_pilotAttributeType,10L + +#define LN_documentIdentifier "documentIdentifier" +#define NID_documentIdentifier 468 +#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L + +#define LN_documentTitle "documentTitle" +#define NID_documentTitle 469 +#define OBJ_documentTitle OBJ_pilotAttributeType,12L + +#define LN_documentVersion "documentVersion" +#define NID_documentVersion 470 +#define OBJ_documentVersion OBJ_pilotAttributeType,13L + +#define LN_documentAuthor "documentAuthor" +#define NID_documentAuthor 471 +#define OBJ_documentAuthor OBJ_pilotAttributeType,14L + +#define LN_documentLocation "documentLocation" +#define NID_documentLocation 472 +#define OBJ_documentLocation OBJ_pilotAttributeType,15L + +#define LN_homeTelephoneNumber "homeTelephoneNumber" +#define NID_homeTelephoneNumber 473 +#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L + +#define SN_secretary "secretary" +#define NID_secretary 474 +#define OBJ_secretary OBJ_pilotAttributeType,21L + +#define LN_otherMailbox "otherMailbox" +#define NID_otherMailbox 475 +#define OBJ_otherMailbox OBJ_pilotAttributeType,22L + +#define LN_lastModifiedTime "lastModifiedTime" +#define NID_lastModifiedTime 476 +#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L + +#define LN_lastModifiedBy "lastModifiedBy" +#define NID_lastModifiedBy 477 +#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L + +#define SN_domainComponent "DC" +#define LN_domainComponent "domainComponent" +#define NID_domainComponent 391 +#define OBJ_domainComponent OBJ_pilotAttributeType,25L + +#define LN_aRecord "aRecord" +#define NID_aRecord 478 +#define OBJ_aRecord OBJ_pilotAttributeType,26L + +#define LN_pilotAttributeType27 "pilotAttributeType27" +#define NID_pilotAttributeType27 479 +#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L + +#define LN_mXRecord "mXRecord" +#define NID_mXRecord 480 +#define OBJ_mXRecord OBJ_pilotAttributeType,28L + +#define LN_nSRecord "nSRecord" +#define NID_nSRecord 481 +#define OBJ_nSRecord OBJ_pilotAttributeType,29L + +#define LN_sOARecord "sOARecord" +#define NID_sOARecord 482 +#define OBJ_sOARecord OBJ_pilotAttributeType,30L + +#define LN_cNAMERecord "cNAMERecord" +#define NID_cNAMERecord 483 +#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L + +#define LN_associatedDomain "associatedDomain" +#define NID_associatedDomain 484 +#define OBJ_associatedDomain OBJ_pilotAttributeType,37L + +#define LN_associatedName "associatedName" +#define NID_associatedName 485 +#define OBJ_associatedName OBJ_pilotAttributeType,38L + +#define LN_homePostalAddress "homePostalAddress" +#define NID_homePostalAddress 486 +#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L + +#define LN_personalTitle "personalTitle" +#define NID_personalTitle 487 +#define OBJ_personalTitle OBJ_pilotAttributeType,40L + +#define LN_mobileTelephoneNumber "mobileTelephoneNumber" +#define NID_mobileTelephoneNumber 488 +#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L + +#define LN_pagerTelephoneNumber "pagerTelephoneNumber" +#define NID_pagerTelephoneNumber 489 +#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L + +#define LN_friendlyCountryName "friendlyCountryName" +#define NID_friendlyCountryName 490 +#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L + +#define LN_organizationalStatus "organizationalStatus" +#define NID_organizationalStatus 491 +#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L + +#define LN_janetMailbox "janetMailbox" +#define NID_janetMailbox 492 +#define OBJ_janetMailbox OBJ_pilotAttributeType,46L + +#define LN_mailPreferenceOption "mailPreferenceOption" +#define NID_mailPreferenceOption 493 +#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L + +#define LN_buildingName "buildingName" +#define NID_buildingName 494 +#define OBJ_buildingName OBJ_pilotAttributeType,48L + +#define LN_dSAQuality "dSAQuality" +#define NID_dSAQuality 495 +#define OBJ_dSAQuality OBJ_pilotAttributeType,49L + +#define LN_singleLevelQuality "singleLevelQuality" +#define NID_singleLevelQuality 496 +#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L + +#define LN_subtreeMinimumQuality "subtreeMinimumQuality" +#define NID_subtreeMinimumQuality 497 +#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L + +#define LN_subtreeMaximumQuality "subtreeMaximumQuality" +#define NID_subtreeMaximumQuality 498 +#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L + +#define LN_personalSignature "personalSignature" +#define NID_personalSignature 499 +#define OBJ_personalSignature OBJ_pilotAttributeType,53L + +#define LN_dITRedirect "dITRedirect" +#define NID_dITRedirect 500 +#define OBJ_dITRedirect OBJ_pilotAttributeType,54L + +#define SN_audio "audio" +#define NID_audio 501 +#define OBJ_audio OBJ_pilotAttributeType,55L + +#define LN_documentPublisher "documentPublisher" +#define NID_documentPublisher 502 +#define OBJ_documentPublisher OBJ_pilotAttributeType,56L + +#define SN_id_set "id-set" +#define LN_id_set "Secure Electronic Transactions" +#define NID_id_set 512 +#define OBJ_id_set OBJ_international_organizations,42L + +#define SN_set_ctype "set-ctype" +#define LN_set_ctype "content types" +#define NID_set_ctype 513 +#define OBJ_set_ctype OBJ_id_set,0L + +#define SN_set_msgExt "set-msgExt" +#define LN_set_msgExt "message extensions" +#define NID_set_msgExt 514 +#define OBJ_set_msgExt OBJ_id_set,1L + +#define SN_set_attr "set-attr" +#define NID_set_attr 515 +#define OBJ_set_attr OBJ_id_set,3L + +#define SN_set_policy "set-policy" +#define NID_set_policy 516 +#define OBJ_set_policy OBJ_id_set,5L + +#define SN_set_certExt "set-certExt" +#define LN_set_certExt "certificate extensions" +#define NID_set_certExt 517 +#define OBJ_set_certExt OBJ_id_set,7L + +#define SN_set_brand "set-brand" +#define NID_set_brand 518 +#define OBJ_set_brand OBJ_id_set,8L + +#define SN_setct_PANData "setct-PANData" +#define NID_setct_PANData 519 +#define OBJ_setct_PANData OBJ_set_ctype,0L + +#define SN_setct_PANToken "setct-PANToken" +#define NID_setct_PANToken 520 +#define OBJ_setct_PANToken OBJ_set_ctype,1L + +#define SN_setct_PANOnly "setct-PANOnly" +#define NID_setct_PANOnly 521 +#define OBJ_setct_PANOnly OBJ_set_ctype,2L + +#define SN_setct_OIData "setct-OIData" +#define NID_setct_OIData 522 +#define OBJ_setct_OIData OBJ_set_ctype,3L + +#define SN_setct_PI "setct-PI" +#define NID_setct_PI 523 +#define OBJ_setct_PI OBJ_set_ctype,4L + +#define SN_setct_PIData "setct-PIData" +#define NID_setct_PIData 524 +#define OBJ_setct_PIData OBJ_set_ctype,5L + +#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned" +#define NID_setct_PIDataUnsigned 525 +#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L + +#define SN_setct_HODInput "setct-HODInput" +#define NID_setct_HODInput 526 +#define OBJ_setct_HODInput OBJ_set_ctype,7L + +#define SN_setct_AuthResBaggage "setct-AuthResBaggage" +#define NID_setct_AuthResBaggage 527 +#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L + +#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage" +#define NID_setct_AuthRevReqBaggage 528 +#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L + +#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage" +#define NID_setct_AuthRevResBaggage 529 +#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L + +#define SN_setct_CapTokenSeq "setct-CapTokenSeq" +#define NID_setct_CapTokenSeq 530 +#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L + +#define SN_setct_PInitResData "setct-PInitResData" +#define NID_setct_PInitResData 531 +#define OBJ_setct_PInitResData OBJ_set_ctype,12L + +#define SN_setct_PI_TBS "setct-PI-TBS" +#define NID_setct_PI_TBS 532 +#define OBJ_setct_PI_TBS OBJ_set_ctype,13L + +#define SN_setct_PResData "setct-PResData" +#define NID_setct_PResData 533 +#define OBJ_setct_PResData OBJ_set_ctype,14L + +#define SN_setct_AuthReqTBS "setct-AuthReqTBS" +#define NID_setct_AuthReqTBS 534 +#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L + +#define SN_setct_AuthResTBS "setct-AuthResTBS" +#define NID_setct_AuthResTBS 535 +#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L + +#define SN_setct_AuthResTBSX "setct-AuthResTBSX" +#define NID_setct_AuthResTBSX 536 +#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L + +#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS" +#define NID_setct_AuthTokenTBS 537 +#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L + +#define SN_setct_CapTokenData "setct-CapTokenData" +#define NID_setct_CapTokenData 538 +#define OBJ_setct_CapTokenData OBJ_set_ctype,20L + +#define SN_setct_CapTokenTBS "setct-CapTokenTBS" +#define NID_setct_CapTokenTBS 539 +#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L + +#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg" +#define NID_setct_AcqCardCodeMsg 540 +#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L + +#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS" +#define NID_setct_AuthRevReqTBS 541 +#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L + +#define SN_setct_AuthRevResData "setct-AuthRevResData" +#define NID_setct_AuthRevResData 542 +#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L + +#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS" +#define NID_setct_AuthRevResTBS 543 +#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L + +#define SN_setct_CapReqTBS "setct-CapReqTBS" +#define NID_setct_CapReqTBS 544 +#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L + +#define SN_setct_CapReqTBSX "setct-CapReqTBSX" +#define NID_setct_CapReqTBSX 545 +#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L + +#define SN_setct_CapResData "setct-CapResData" +#define NID_setct_CapResData 546 +#define OBJ_setct_CapResData OBJ_set_ctype,28L + +#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS" +#define NID_setct_CapRevReqTBS 547 +#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L + +#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX" +#define NID_setct_CapRevReqTBSX 548 +#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L + +#define SN_setct_CapRevResData "setct-CapRevResData" +#define NID_setct_CapRevResData 549 +#define OBJ_setct_CapRevResData OBJ_set_ctype,31L + +#define SN_setct_CredReqTBS "setct-CredReqTBS" +#define NID_setct_CredReqTBS 550 +#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L + +#define SN_setct_CredReqTBSX "setct-CredReqTBSX" +#define NID_setct_CredReqTBSX 551 +#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L + +#define SN_setct_CredResData "setct-CredResData" +#define NID_setct_CredResData 552 +#define OBJ_setct_CredResData OBJ_set_ctype,34L + +#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS" +#define NID_setct_CredRevReqTBS 553 +#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L + +#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX" +#define NID_setct_CredRevReqTBSX 554 +#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L + +#define SN_setct_CredRevResData "setct-CredRevResData" +#define NID_setct_CredRevResData 555 +#define OBJ_setct_CredRevResData OBJ_set_ctype,37L + +#define SN_setct_PCertReqData "setct-PCertReqData" +#define NID_setct_PCertReqData 556 +#define OBJ_setct_PCertReqData OBJ_set_ctype,38L + +#define SN_setct_PCertResTBS "setct-PCertResTBS" +#define NID_setct_PCertResTBS 557 +#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L + +#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData" +#define NID_setct_BatchAdminReqData 558 +#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L + +#define SN_setct_BatchAdminResData "setct-BatchAdminResData" +#define NID_setct_BatchAdminResData 559 +#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L + +#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS" +#define NID_setct_CardCInitResTBS 560 +#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L + +#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS" +#define NID_setct_MeAqCInitResTBS 561 +#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L + +#define SN_setct_RegFormResTBS "setct-RegFormResTBS" +#define NID_setct_RegFormResTBS 562 +#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L + +#define SN_setct_CertReqData "setct-CertReqData" +#define NID_setct_CertReqData 563 +#define OBJ_setct_CertReqData OBJ_set_ctype,45L + +#define SN_setct_CertReqTBS "setct-CertReqTBS" +#define NID_setct_CertReqTBS 564 +#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L + +#define SN_setct_CertResData "setct-CertResData" +#define NID_setct_CertResData 565 +#define OBJ_setct_CertResData OBJ_set_ctype,47L + +#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS" +#define NID_setct_CertInqReqTBS 566 +#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L + +#define SN_setct_ErrorTBS "setct-ErrorTBS" +#define NID_setct_ErrorTBS 567 +#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L + +#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE" +#define NID_setct_PIDualSignedTBE 568 +#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L + +#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE" +#define NID_setct_PIUnsignedTBE 569 +#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L + +#define SN_setct_AuthReqTBE "setct-AuthReqTBE" +#define NID_setct_AuthReqTBE 570 +#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L + +#define SN_setct_AuthResTBE "setct-AuthResTBE" +#define NID_setct_AuthResTBE 571 +#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L + +#define SN_setct_AuthResTBEX "setct-AuthResTBEX" +#define NID_setct_AuthResTBEX 572 +#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L + +#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE" +#define NID_setct_AuthTokenTBE 573 +#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L + +#define SN_setct_CapTokenTBE "setct-CapTokenTBE" +#define NID_setct_CapTokenTBE 574 +#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L + +#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX" +#define NID_setct_CapTokenTBEX 575 +#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L + +#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE" +#define NID_setct_AcqCardCodeMsgTBE 576 +#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L + +#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE" +#define NID_setct_AuthRevReqTBE 577 +#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L + +#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE" +#define NID_setct_AuthRevResTBE 578 +#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L + +#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB" +#define NID_setct_AuthRevResTBEB 579 +#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L + +#define SN_setct_CapReqTBE "setct-CapReqTBE" +#define NID_setct_CapReqTBE 580 +#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L + +#define SN_setct_CapReqTBEX "setct-CapReqTBEX" +#define NID_setct_CapReqTBEX 581 +#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L + +#define SN_setct_CapResTBE "setct-CapResTBE" +#define NID_setct_CapResTBE 582 +#define OBJ_setct_CapResTBE OBJ_set_ctype,64L + +#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE" +#define NID_setct_CapRevReqTBE 583 +#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L + +#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX" +#define NID_setct_CapRevReqTBEX 584 +#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L + +#define SN_setct_CapRevResTBE "setct-CapRevResTBE" +#define NID_setct_CapRevResTBE 585 +#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L + +#define SN_setct_CredReqTBE "setct-CredReqTBE" +#define NID_setct_CredReqTBE 586 +#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L + +#define SN_setct_CredReqTBEX "setct-CredReqTBEX" +#define NID_setct_CredReqTBEX 587 +#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L + +#define SN_setct_CredResTBE "setct-CredResTBE" +#define NID_setct_CredResTBE 588 +#define OBJ_setct_CredResTBE OBJ_set_ctype,70L + +#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE" +#define NID_setct_CredRevReqTBE 589 +#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L + +#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX" +#define NID_setct_CredRevReqTBEX 590 +#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L + +#define SN_setct_CredRevResTBE "setct-CredRevResTBE" +#define NID_setct_CredRevResTBE 591 +#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L + +#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE" +#define NID_setct_BatchAdminReqTBE 592 +#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L + +#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE" +#define NID_setct_BatchAdminResTBE 593 +#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L + +#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE" +#define NID_setct_RegFormReqTBE 594 +#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L + +#define SN_setct_CertReqTBE "setct-CertReqTBE" +#define NID_setct_CertReqTBE 595 +#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L + +#define SN_setct_CertReqTBEX "setct-CertReqTBEX" +#define NID_setct_CertReqTBEX 596 +#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L + +#define SN_setct_CertResTBE "setct-CertResTBE" +#define NID_setct_CertResTBE 597 +#define OBJ_setct_CertResTBE OBJ_set_ctype,79L + +#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS" +#define NID_setct_CRLNotificationTBS 598 +#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L + +#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS" +#define NID_setct_CRLNotificationResTBS 599 +#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L + +#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS" +#define NID_setct_BCIDistributionTBS 600 +#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L + +#define SN_setext_genCrypt "setext-genCrypt" +#define LN_setext_genCrypt "generic cryptogram" +#define NID_setext_genCrypt 601 +#define OBJ_setext_genCrypt OBJ_set_msgExt,1L + +#define SN_setext_miAuth "setext-miAuth" +#define LN_setext_miAuth "merchant initiated auth" +#define NID_setext_miAuth 602 +#define OBJ_setext_miAuth OBJ_set_msgExt,3L + +#define SN_setext_pinSecure "setext-pinSecure" +#define NID_setext_pinSecure 603 +#define OBJ_setext_pinSecure OBJ_set_msgExt,4L + +#define SN_setext_pinAny "setext-pinAny" +#define NID_setext_pinAny 604 +#define OBJ_setext_pinAny OBJ_set_msgExt,5L + +#define SN_setext_track2 "setext-track2" +#define NID_setext_track2 605 +#define OBJ_setext_track2 OBJ_set_msgExt,7L + +#define SN_setext_cv "setext-cv" +#define LN_setext_cv "additional verification" +#define NID_setext_cv 606 +#define OBJ_setext_cv OBJ_set_msgExt,8L + +#define SN_set_policy_root "set-policy-root" +#define NID_set_policy_root 607 +#define OBJ_set_policy_root OBJ_set_policy,0L + +#define SN_setCext_hashedRoot "setCext-hashedRoot" +#define NID_setCext_hashedRoot 608 +#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L + +#define SN_setCext_certType "setCext-certType" +#define NID_setCext_certType 609 +#define OBJ_setCext_certType OBJ_set_certExt,1L + +#define SN_setCext_merchData "setCext-merchData" +#define NID_setCext_merchData 610 +#define OBJ_setCext_merchData OBJ_set_certExt,2L + +#define SN_setCext_cCertRequired "setCext-cCertRequired" +#define NID_setCext_cCertRequired 611 +#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L + +#define SN_setCext_tunneling "setCext-tunneling" +#define NID_setCext_tunneling 612 +#define OBJ_setCext_tunneling OBJ_set_certExt,4L + +#define SN_setCext_setExt "setCext-setExt" +#define NID_setCext_setExt 613 +#define OBJ_setCext_setExt OBJ_set_certExt,5L + +#define SN_setCext_setQualf "setCext-setQualf" +#define NID_setCext_setQualf 614 +#define OBJ_setCext_setQualf OBJ_set_certExt,6L + +#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities" +#define NID_setCext_PGWYcapabilities 615 +#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L + +#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier" +#define NID_setCext_TokenIdentifier 616 +#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L + +#define SN_setCext_Track2Data "setCext-Track2Data" +#define NID_setCext_Track2Data 617 +#define OBJ_setCext_Track2Data OBJ_set_certExt,9L + +#define SN_setCext_TokenType "setCext-TokenType" +#define NID_setCext_TokenType 618 +#define OBJ_setCext_TokenType OBJ_set_certExt,10L + +#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities" +#define NID_setCext_IssuerCapabilities 619 +#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L + +#define SN_setAttr_Cert "setAttr-Cert" +#define NID_setAttr_Cert 620 +#define OBJ_setAttr_Cert OBJ_set_attr,0L + +#define SN_setAttr_PGWYcap "setAttr-PGWYcap" +#define LN_setAttr_PGWYcap "payment gateway capabilities" +#define NID_setAttr_PGWYcap 621 +#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L + +#define SN_setAttr_TokenType "setAttr-TokenType" +#define NID_setAttr_TokenType 622 +#define OBJ_setAttr_TokenType OBJ_set_attr,2L + +#define SN_setAttr_IssCap "setAttr-IssCap" +#define LN_setAttr_IssCap "issuer capabilities" +#define NID_setAttr_IssCap 623 +#define OBJ_setAttr_IssCap OBJ_set_attr,3L + +#define SN_set_rootKeyThumb "set-rootKeyThumb" +#define NID_set_rootKeyThumb 624 +#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L + +#define SN_set_addPolicy "set-addPolicy" +#define NID_set_addPolicy 625 +#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L + +#define SN_setAttr_Token_EMV "setAttr-Token-EMV" +#define NID_setAttr_Token_EMV 626 +#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L + +#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime" +#define NID_setAttr_Token_B0Prime 627 +#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L + +#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM" +#define NID_setAttr_IssCap_CVM 628 +#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L + +#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2" +#define NID_setAttr_IssCap_T2 629 +#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L + +#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig" +#define NID_setAttr_IssCap_Sig 630 +#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L + +#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm" +#define LN_setAttr_GenCryptgrm "generate cryptogram" +#define NID_setAttr_GenCryptgrm 631 +#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L + +#define SN_setAttr_T2Enc "setAttr-T2Enc" +#define LN_setAttr_T2Enc "encrypted track 2" +#define NID_setAttr_T2Enc 632 +#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L + +#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt" +#define LN_setAttr_T2cleartxt "cleartext track 2" +#define NID_setAttr_T2cleartxt 633 +#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L + +#define SN_setAttr_TokICCsig "setAttr-TokICCsig" +#define LN_setAttr_TokICCsig "ICC or token signature" +#define NID_setAttr_TokICCsig 634 +#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L + +#define SN_setAttr_SecDevSig "setAttr-SecDevSig" +#define LN_setAttr_SecDevSig "secure device signature" +#define NID_setAttr_SecDevSig 635 +#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L + +#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA" +#define NID_set_brand_IATA_ATA 636 +#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L + +#define SN_set_brand_Diners "set-brand-Diners" +#define NID_set_brand_Diners 637 +#define OBJ_set_brand_Diners OBJ_set_brand,30L + +#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress" +#define NID_set_brand_AmericanExpress 638 +#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L + +#define SN_set_brand_JCB "set-brand-JCB" +#define NID_set_brand_JCB 639 +#define OBJ_set_brand_JCB OBJ_set_brand,35L + +#define SN_set_brand_Visa "set-brand-Visa" +#define NID_set_brand_Visa 640 +#define OBJ_set_brand_Visa OBJ_set_brand,4L + +#define SN_set_brand_MasterCard "set-brand-MasterCard" +#define NID_set_brand_MasterCard 641 +#define OBJ_set_brand_MasterCard OBJ_set_brand,5L + +#define SN_set_brand_Novus "set-brand-Novus" +#define NID_set_brand_Novus 642 +#define OBJ_set_brand_Novus OBJ_set_brand,6011L + +#define SN_des_cdmf "DES-CDMF" +#define LN_des_cdmf "des-cdmf" +#define NID_des_cdmf 643 +#define OBJ_des_cdmf OBJ_rsadsi,3L,10L + +#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET" +#define NID_rsaOAEPEncryptionSET 644 +#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L + +#define SN_ipsec3 "Oakley-EC2N-3" +#define LN_ipsec3 "ipsec3" +#define NID_ipsec3 749 + +#define SN_ipsec4 "Oakley-EC2N-4" +#define LN_ipsec4 "ipsec4" +#define NID_ipsec4 750 + +#define SN_whirlpool "whirlpool" +#define NID_whirlpool 804 +#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L + +#define SN_cryptopro "cryptopro" +#define NID_cryptopro 805 +#define OBJ_cryptopro OBJ_member_body,643L,2L,2L + +#define SN_cryptocom "cryptocom" +#define NID_cryptocom 806 +#define OBJ_cryptocom OBJ_member_body,643L,2L,9L + +#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001" +#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001" +#define NID_id_GostR3411_94_with_GostR3410_2001 807 +#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L + +#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94" +#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94" +#define NID_id_GostR3411_94_with_GostR3410_94 808 +#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L + +#define SN_id_GostR3411_94 "md_gost94" +#define LN_id_GostR3411_94 "GOST R 34.11-94" +#define NID_id_GostR3411_94 809 +#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L + +#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94" +#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94" +#define NID_id_HMACGostR3411_94 810 +#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L + +#define SN_id_GostR3410_2001 "gost2001" +#define LN_id_GostR3410_2001 "GOST R 34.10-2001" +#define NID_id_GostR3410_2001 811 +#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L + +#define SN_id_GostR3410_94 "gost94" +#define LN_id_GostR3410_94 "GOST R 34.10-94" +#define NID_id_GostR3410_94 812 +#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L + +#define SN_id_Gost28147_89 "gost89" +#define LN_id_Gost28147_89 "GOST 28147-89" +#define NID_id_Gost28147_89 813 +#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L + +#define SN_gost89_cnt "gost89-cnt" +#define NID_gost89_cnt 814 + +#define SN_id_Gost28147_89_MAC "gost-mac" +#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC" +#define NID_id_Gost28147_89_MAC 815 +#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L + +#define SN_id_GostR3411_94_prf "prf-gostr3411-94" +#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF" +#define NID_id_GostR3411_94_prf 816 +#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L + +#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH" +#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH" +#define NID_id_GostR3410_2001DH 817 +#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L + +#define SN_id_GostR3410_94DH "id-GostR3410-94DH" +#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH" +#define NID_id_GostR3410_94DH 818 +#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L + +#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing" +#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819 +#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L + +#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing" +#define NID_id_Gost28147_89_None_KeyMeshing 820 +#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L + +#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet" +#define NID_id_GostR3411_94_TestParamSet 821 +#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L + +#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet" +#define NID_id_GostR3411_94_CryptoProParamSet 822 +#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L + +#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet" +#define NID_id_Gost28147_89_TestParamSet 823 +#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L + +#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824 +#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L + +#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825 +#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L + +#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826 +#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L + +#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827 +#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L + +#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830 +#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L + +#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet" +#define NID_id_GostR3410_94_TestParamSet 831 +#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L + +#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832 +#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L + +#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833 +#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L + +#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834 +#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L + +#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835 +#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L + +#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836 +#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L + +#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837 +#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L + +#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838 +#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L + +#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet" +#define NID_id_GostR3410_2001_TestParamSet 839 +#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L + +#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840 +#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L + +#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841 +#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L + +#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842 +#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L + +#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843 +#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L + +#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844 +#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L + +#define SN_id_GostR3410_94_a "id-GostR3410-94-a" +#define NID_id_GostR3410_94_a 845 +#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L + +#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis" +#define NID_id_GostR3410_94_aBis 846 +#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L + +#define SN_id_GostR3410_94_b "id-GostR3410-94-b" +#define NID_id_GostR3410_94_b 847 +#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L + +#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis" +#define NID_id_GostR3410_94_bBis 848 +#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L + +#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc" +#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet" +#define NID_id_Gost28147_89_cc 849 +#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L + +#define SN_id_GostR3410_94_cc "gost94cc" +#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom" +#define NID_id_GostR3410_94_cc 850 +#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L + +#define SN_id_GostR3410_2001_cc "gost2001cc" +#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom" +#define NID_id_GostR3410_2001_cc 851 +#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L + +#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc" +#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_94_cc 852 +#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L + +#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc" +#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853 +#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L + +#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc" +#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom" +#define NID_id_GostR3410_2001_ParamSet_cc 854 +#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L + +#define SN_camellia_128_cbc "CAMELLIA-128-CBC" +#define LN_camellia_128_cbc "camellia-128-cbc" +#define NID_camellia_128_cbc 751 +#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L + +#define SN_camellia_192_cbc "CAMELLIA-192-CBC" +#define LN_camellia_192_cbc "camellia-192-cbc" +#define NID_camellia_192_cbc 752 +#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L + +#define SN_camellia_256_cbc "CAMELLIA-256-CBC" +#define LN_camellia_256_cbc "camellia-256-cbc" +#define NID_camellia_256_cbc 753 +#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L + +#define SN_id_camellia128_wrap "id-camellia128-wrap" +#define NID_id_camellia128_wrap 907 +#define OBJ_id_camellia128_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,2L + +#define SN_id_camellia192_wrap "id-camellia192-wrap" +#define NID_id_camellia192_wrap 908 +#define OBJ_id_camellia192_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,3L + +#define SN_id_camellia256_wrap "id-camellia256-wrap" +#define NID_id_camellia256_wrap 909 +#define OBJ_id_camellia256_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,4L + +#define OBJ_ntt_ds 0L,3L,4401L,5L + +#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L + +#define SN_camellia_128_ecb "CAMELLIA-128-ECB" +#define LN_camellia_128_ecb "camellia-128-ecb" +#define NID_camellia_128_ecb 754 +#define OBJ_camellia_128_ecb OBJ_camellia,1L + +#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB" +#define LN_camellia_128_ofb128 "camellia-128-ofb" +#define NID_camellia_128_ofb128 766 +#define OBJ_camellia_128_ofb128 OBJ_camellia,3L + +#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB" +#define LN_camellia_128_cfb128 "camellia-128-cfb" +#define NID_camellia_128_cfb128 757 +#define OBJ_camellia_128_cfb128 OBJ_camellia,4L + +#define SN_camellia_192_ecb "CAMELLIA-192-ECB" +#define LN_camellia_192_ecb "camellia-192-ecb" +#define NID_camellia_192_ecb 755 +#define OBJ_camellia_192_ecb OBJ_camellia,21L + +#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB" +#define LN_camellia_192_ofb128 "camellia-192-ofb" +#define NID_camellia_192_ofb128 767 +#define OBJ_camellia_192_ofb128 OBJ_camellia,23L + +#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB" +#define LN_camellia_192_cfb128 "camellia-192-cfb" +#define NID_camellia_192_cfb128 758 +#define OBJ_camellia_192_cfb128 OBJ_camellia,24L + +#define SN_camellia_256_ecb "CAMELLIA-256-ECB" +#define LN_camellia_256_ecb "camellia-256-ecb" +#define NID_camellia_256_ecb 756 +#define OBJ_camellia_256_ecb OBJ_camellia,41L + +#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB" +#define LN_camellia_256_ofb128 "camellia-256-ofb" +#define NID_camellia_256_ofb128 768 +#define OBJ_camellia_256_ofb128 OBJ_camellia,43L + +#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB" +#define LN_camellia_256_cfb128 "camellia-256-cfb" +#define NID_camellia_256_cfb128 759 +#define OBJ_camellia_256_cfb128 OBJ_camellia,44L + +#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1" +#define LN_camellia_128_cfb1 "camellia-128-cfb1" +#define NID_camellia_128_cfb1 760 + +#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1" +#define LN_camellia_192_cfb1 "camellia-192-cfb1" +#define NID_camellia_192_cfb1 761 + +#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1" +#define LN_camellia_256_cfb1 "camellia-256-cfb1" +#define NID_camellia_256_cfb1 762 + +#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8" +#define LN_camellia_128_cfb8 "camellia-128-cfb8" +#define NID_camellia_128_cfb8 763 + +#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8" +#define LN_camellia_192_cfb8 "camellia-192-cfb8" +#define NID_camellia_192_cfb8 764 + +#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8" +#define LN_camellia_256_cfb8 "camellia-256-cfb8" +#define NID_camellia_256_cfb8 765 + +#define SN_kisa "KISA" +#define LN_kisa "kisa" +#define NID_kisa 773 +#define OBJ_kisa OBJ_member_body,410L,200004L + +#define SN_seed_ecb "SEED-ECB" +#define LN_seed_ecb "seed-ecb" +#define NID_seed_ecb 776 +#define OBJ_seed_ecb OBJ_kisa,1L,3L + +#define SN_seed_cbc "SEED-CBC" +#define LN_seed_cbc "seed-cbc" +#define NID_seed_cbc 777 +#define OBJ_seed_cbc OBJ_kisa,1L,4L + +#define SN_seed_cfb128 "SEED-CFB" +#define LN_seed_cfb128 "seed-cfb" +#define NID_seed_cfb128 779 +#define OBJ_seed_cfb128 OBJ_kisa,1L,5L + +#define SN_seed_ofb128 "SEED-OFB" +#define LN_seed_ofb128 "seed-ofb" +#define NID_seed_ofb128 778 +#define OBJ_seed_ofb128 OBJ_kisa,1L,6L + +#define SN_hmac "HMAC" +#define LN_hmac "hmac" +#define NID_hmac 855 + +#define SN_cmac "CMAC" +#define LN_cmac "cmac" +#define NID_cmac 894 + +#define SN_rc4_hmac_md5 "RC4-HMAC-MD5" +#define LN_rc4_hmac_md5 "rc4-hmac-md5" +#define NID_rc4_hmac_md5 915 + +#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1" +#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1" +#define NID_aes_128_cbc_hmac_sha1 916 + +#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1" +#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1" +#define NID_aes_192_cbc_hmac_sha1 917 + +#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1" +#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1" +#define NID_aes_256_cbc_hmac_sha1 918 + +#define SN_aes_128_cbc_hmac_sha256 "AES-128-CBC-HMAC-SHA256" +#define LN_aes_128_cbc_hmac_sha256 "aes-128-cbc-hmac-sha256" +#define NID_aes_128_cbc_hmac_sha256 948 + +#define SN_aes_192_cbc_hmac_sha256 "AES-192-CBC-HMAC-SHA256" +#define LN_aes_192_cbc_hmac_sha256 "aes-192-cbc-hmac-sha256" +#define NID_aes_192_cbc_hmac_sha256 949 + +#define SN_aes_256_cbc_hmac_sha256 "AES-256-CBC-HMAC-SHA256" +#define LN_aes_256_cbc_hmac_sha256 "aes-256-cbc-hmac-sha256" +#define NID_aes_256_cbc_hmac_sha256 950 + +#define SN_dhpublicnumber "dhpublicnumber" +#define LN_dhpublicnumber "X9.42 DH" +#define NID_dhpublicnumber 920 +#define OBJ_dhpublicnumber OBJ_ISO_US,10046L,2L,1L + +#define SN_brainpoolP160r1 "brainpoolP160r1" +#define NID_brainpoolP160r1 921 +#define OBJ_brainpoolP160r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,1L + +#define SN_brainpoolP160t1 "brainpoolP160t1" +#define NID_brainpoolP160t1 922 +#define OBJ_brainpoolP160t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,2L + +#define SN_brainpoolP192r1 "brainpoolP192r1" +#define NID_brainpoolP192r1 923 +#define OBJ_brainpoolP192r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,3L + +#define SN_brainpoolP192t1 "brainpoolP192t1" +#define NID_brainpoolP192t1 924 +#define OBJ_brainpoolP192t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,4L + +#define SN_brainpoolP224r1 "brainpoolP224r1" +#define NID_brainpoolP224r1 925 +#define OBJ_brainpoolP224r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,5L + +#define SN_brainpoolP224t1 "brainpoolP224t1" +#define NID_brainpoolP224t1 926 +#define OBJ_brainpoolP224t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,6L + +#define SN_brainpoolP256r1 "brainpoolP256r1" +#define NID_brainpoolP256r1 927 +#define OBJ_brainpoolP256r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,7L + +#define SN_brainpoolP256t1 "brainpoolP256t1" +#define NID_brainpoolP256t1 928 +#define OBJ_brainpoolP256t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,8L + +#define SN_brainpoolP320r1 "brainpoolP320r1" +#define NID_brainpoolP320r1 929 +#define OBJ_brainpoolP320r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,9L + +#define SN_brainpoolP320t1 "brainpoolP320t1" +#define NID_brainpoolP320t1 930 +#define OBJ_brainpoolP320t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,10L + +#define SN_brainpoolP384r1 "brainpoolP384r1" +#define NID_brainpoolP384r1 931 +#define OBJ_brainpoolP384r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,11L + +#define SN_brainpoolP384t1 "brainpoolP384t1" +#define NID_brainpoolP384t1 932 +#define OBJ_brainpoolP384t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,12L + +#define SN_brainpoolP512r1 "brainpoolP512r1" +#define NID_brainpoolP512r1 933 +#define OBJ_brainpoolP512r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,13L + +#define SN_brainpoolP512t1 "brainpoolP512t1" +#define NID_brainpoolP512t1 934 +#define OBJ_brainpoolP512t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,14L + +#define OBJ_x9_63_scheme 1L,3L,133L,16L,840L,63L,0L + +#define OBJ_secg_scheme OBJ_certicom_arc,1L + +#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme" +#define NID_dhSinglePass_stdDH_sha1kdf_scheme 936 +#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme OBJ_x9_63_scheme,2L + +#define SN_dhSinglePass_stdDH_sha224kdf_scheme "dhSinglePass-stdDH-sha224kdf-scheme" +#define NID_dhSinglePass_stdDH_sha224kdf_scheme 937 +#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme OBJ_secg_scheme,11L,0L + +#define SN_dhSinglePass_stdDH_sha256kdf_scheme "dhSinglePass-stdDH-sha256kdf-scheme" +#define NID_dhSinglePass_stdDH_sha256kdf_scheme 938 +#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme OBJ_secg_scheme,11L,1L + +#define SN_dhSinglePass_stdDH_sha384kdf_scheme "dhSinglePass-stdDH-sha384kdf-scheme" +#define NID_dhSinglePass_stdDH_sha384kdf_scheme 939 +#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme OBJ_secg_scheme,11L,2L + +#define SN_dhSinglePass_stdDH_sha512kdf_scheme "dhSinglePass-stdDH-sha512kdf-scheme" +#define NID_dhSinglePass_stdDH_sha512kdf_scheme 940 +#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme OBJ_secg_scheme,11L,3L + +#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme "dhSinglePass-cofactorDH-sha1kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 941 +#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme OBJ_x9_63_scheme,3L + +#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme "dhSinglePass-cofactorDH-sha224kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 942 +#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme OBJ_secg_scheme,14L,0L + +#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme "dhSinglePass-cofactorDH-sha256kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 943 +#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme OBJ_secg_scheme,14L,1L + +#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme "dhSinglePass-cofactorDH-sha384kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 944 +#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme OBJ_secg_scheme,14L,2L + +#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme "dhSinglePass-cofactorDH-sha512kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 945 +#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme OBJ_secg_scheme,14L,3L + +#define SN_dh_std_kdf "dh-std-kdf" +#define NID_dh_std_kdf 946 + +#define SN_dh_cofactor_kdf "dh-cofactor-kdf" +#define NID_dh_cofactor_kdf 947 + +#define SN_ct_precert_scts "ct_precert_scts" +#define LN_ct_precert_scts "CT Precertificate SCTs" +#define NID_ct_precert_scts 951 +#define OBJ_ct_precert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,2L + +#define SN_ct_precert_poison "ct_precert_poison" +#define LN_ct_precert_poison "CT Precertificate Poison" +#define NID_ct_precert_poison 952 +#define OBJ_ct_precert_poison 1L,3L,6L,1L,4L,1L,11129L,2L,4L,3L + +#define SN_ct_precert_signer "ct_precert_signer" +#define LN_ct_precert_signer "CT Precertificate Signer" +#define NID_ct_precert_signer 953 +#define OBJ_ct_precert_signer 1L,3L,6L,1L,4L,1L,11129L,2L,4L,4L + +#define SN_ct_cert_scts "ct_cert_scts" +#define LN_ct_cert_scts "CT Certificate SCTs" +#define NID_ct_cert_scts 954 +#define OBJ_ct_cert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,5L + +#define SN_jurisdictionLocalityName "jurisdictionL" +#define LN_jurisdictionLocalityName "jurisdictionLocalityName" +#define NID_jurisdictionLocalityName 955 +#define OBJ_jurisdictionLocalityName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,1L + +#define SN_jurisdictionStateOrProvinceName "jurisdictionST" +#define LN_jurisdictionStateOrProvinceName "jurisdictionStateOrProvinceName" +#define NID_jurisdictionStateOrProvinceName 956 +#define OBJ_jurisdictionStateOrProvinceName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,2L + +#define SN_jurisdictionCountryName "jurisdictionC" +#define LN_jurisdictionCountryName "jurisdictionCountryName" +#define NID_jurisdictionCountryName 957 +#define OBJ_jurisdictionCountryName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L diff --git a/optee/optee_test/host/openssl/include/openssl/objects.h b/optee/optee_test/host/openssl/include/openssl/objects.h new file mode 100644 index 0000000..b8dafa8 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/objects.h @@ -0,0 +1,1143 @@ +/* crypto/objects/objects.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_OBJECTS_H +# define HEADER_OBJECTS_H + +# define USE_OBJ_MAC + +# ifdef USE_OBJ_MAC +# include +# else +# define SN_undef "UNDEF" +# define LN_undef "undefined" +# define NID_undef 0 +# define OBJ_undef 0L + +# define SN_Algorithm "Algorithm" +# define LN_algorithm "algorithm" +# define NID_algorithm 38 +# define OBJ_algorithm 1L,3L,14L,3L,2L + +# define LN_rsadsi "rsadsi" +# define NID_rsadsi 1 +# define OBJ_rsadsi 1L,2L,840L,113549L + +# define LN_pkcs "pkcs" +# define NID_pkcs 2 +# define OBJ_pkcs OBJ_rsadsi,1L + +# define SN_md2 "MD2" +# define LN_md2 "md2" +# define NID_md2 3 +# define OBJ_md2 OBJ_rsadsi,2L,2L + +# define SN_md5 "MD5" +# define LN_md5 "md5" +# define NID_md5 4 +# define OBJ_md5 OBJ_rsadsi,2L,5L + +# define SN_rc4 "RC4" +# define LN_rc4 "rc4" +# define NID_rc4 5 +# define OBJ_rc4 OBJ_rsadsi,3L,4L + +# define LN_rsaEncryption "rsaEncryption" +# define NID_rsaEncryption 6 +# define OBJ_rsaEncryption OBJ_pkcs,1L,1L + +# define SN_md2WithRSAEncryption "RSA-MD2" +# define LN_md2WithRSAEncryption "md2WithRSAEncryption" +# define NID_md2WithRSAEncryption 7 +# define OBJ_md2WithRSAEncryption OBJ_pkcs,1L,2L + +# define SN_md5WithRSAEncryption "RSA-MD5" +# define LN_md5WithRSAEncryption "md5WithRSAEncryption" +# define NID_md5WithRSAEncryption 8 +# define OBJ_md5WithRSAEncryption OBJ_pkcs,1L,4L + +# define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES" +# define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC" +# define NID_pbeWithMD2AndDES_CBC 9 +# define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs,5L,1L + +# define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES" +# define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC" +# define NID_pbeWithMD5AndDES_CBC 10 +# define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs,5L,3L + +# define LN_X500 "X500" +# define NID_X500 11 +# define OBJ_X500 2L,5L + +# define LN_X509 "X509" +# define NID_X509 12 +# define OBJ_X509 OBJ_X500,4L + +# define SN_commonName "CN" +# define LN_commonName "commonName" +# define NID_commonName 13 +# define OBJ_commonName OBJ_X509,3L + +# define SN_countryName "C" +# define LN_countryName "countryName" +# define NID_countryName 14 +# define OBJ_countryName OBJ_X509,6L + +# define SN_localityName "L" +# define LN_localityName "localityName" +# define NID_localityName 15 +# define OBJ_localityName OBJ_X509,7L + +/* Postal Address? PA */ + +/* should be "ST" (rfc1327) but MS uses 'S' */ +# define SN_stateOrProvinceName "ST" +# define LN_stateOrProvinceName "stateOrProvinceName" +# define NID_stateOrProvinceName 16 +# define OBJ_stateOrProvinceName OBJ_X509,8L + +# define SN_organizationName "O" +# define LN_organizationName "organizationName" +# define NID_organizationName 17 +# define OBJ_organizationName OBJ_X509,10L + +# define SN_organizationalUnitName "OU" +# define LN_organizationalUnitName "organizationalUnitName" +# define NID_organizationalUnitName 18 +# define OBJ_organizationalUnitName OBJ_X509,11L + +# define SN_rsa "RSA" +# define LN_rsa "rsa" +# define NID_rsa 19 +# define OBJ_rsa OBJ_X500,8L,1L,1L + +# define LN_pkcs7 "pkcs7" +# define NID_pkcs7 20 +# define OBJ_pkcs7 OBJ_pkcs,7L + +# define LN_pkcs7_data "pkcs7-data" +# define NID_pkcs7_data 21 +# define OBJ_pkcs7_data OBJ_pkcs7,1L + +# define LN_pkcs7_signed "pkcs7-signedData" +# define NID_pkcs7_signed 22 +# define OBJ_pkcs7_signed OBJ_pkcs7,2L + +# define LN_pkcs7_enveloped "pkcs7-envelopedData" +# define NID_pkcs7_enveloped 23 +# define OBJ_pkcs7_enveloped OBJ_pkcs7,3L + +# define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData" +# define NID_pkcs7_signedAndEnveloped 24 +# define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L + +# define LN_pkcs7_digest "pkcs7-digestData" +# define NID_pkcs7_digest 25 +# define OBJ_pkcs7_digest OBJ_pkcs7,5L + +# define LN_pkcs7_encrypted "pkcs7-encryptedData" +# define NID_pkcs7_encrypted 26 +# define OBJ_pkcs7_encrypted OBJ_pkcs7,6L + +# define LN_pkcs3 "pkcs3" +# define NID_pkcs3 27 +# define OBJ_pkcs3 OBJ_pkcs,3L + +# define LN_dhKeyAgreement "dhKeyAgreement" +# define NID_dhKeyAgreement 28 +# define OBJ_dhKeyAgreement OBJ_pkcs3,1L + +# define SN_des_ecb "DES-ECB" +# define LN_des_ecb "des-ecb" +# define NID_des_ecb 29 +# define OBJ_des_ecb OBJ_algorithm,6L + +# define SN_des_cfb64 "DES-CFB" +# define LN_des_cfb64 "des-cfb" +# define NID_des_cfb64 30 +/* IV + num */ +# define OBJ_des_cfb64 OBJ_algorithm,9L + +# define SN_des_cbc "DES-CBC" +# define LN_des_cbc "des-cbc" +# define NID_des_cbc 31 +/* IV */ +# define OBJ_des_cbc OBJ_algorithm,7L + +# define SN_des_ede "DES-EDE" +# define LN_des_ede "des-ede" +# define NID_des_ede 32 +/* ?? */ +# define OBJ_des_ede OBJ_algorithm,17L + +# define SN_des_ede3 "DES-EDE3" +# define LN_des_ede3 "des-ede3" +# define NID_des_ede3 33 + +# define SN_idea_cbc "IDEA-CBC" +# define LN_idea_cbc "idea-cbc" +# define NID_idea_cbc 34 +# define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L + +# define SN_idea_cfb64 "IDEA-CFB" +# define LN_idea_cfb64 "idea-cfb" +# define NID_idea_cfb64 35 + +# define SN_idea_ecb "IDEA-ECB" +# define LN_idea_ecb "idea-ecb" +# define NID_idea_ecb 36 + +# define SN_rc2_cbc "RC2-CBC" +# define LN_rc2_cbc "rc2-cbc" +# define NID_rc2_cbc 37 +# define OBJ_rc2_cbc OBJ_rsadsi,3L,2L + +# define SN_rc2_ecb "RC2-ECB" +# define LN_rc2_ecb "rc2-ecb" +# define NID_rc2_ecb 38 + +# define SN_rc2_cfb64 "RC2-CFB" +# define LN_rc2_cfb64 "rc2-cfb" +# define NID_rc2_cfb64 39 + +# define SN_rc2_ofb64 "RC2-OFB" +# define LN_rc2_ofb64 "rc2-ofb" +# define NID_rc2_ofb64 40 + +# define SN_sha "SHA" +# define LN_sha "sha" +# define NID_sha 41 +# define OBJ_sha OBJ_algorithm,18L + +# define SN_shaWithRSAEncryption "RSA-SHA" +# define LN_shaWithRSAEncryption "shaWithRSAEncryption" +# define NID_shaWithRSAEncryption 42 +# define OBJ_shaWithRSAEncryption OBJ_algorithm,15L + +# define SN_des_ede_cbc "DES-EDE-CBC" +# define LN_des_ede_cbc "des-ede-cbc" +# define NID_des_ede_cbc 43 + +# define SN_des_ede3_cbc "DES-EDE3-CBC" +# define LN_des_ede3_cbc "des-ede3-cbc" +# define NID_des_ede3_cbc 44 +# define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L + +# define SN_des_ofb64 "DES-OFB" +# define LN_des_ofb64 "des-ofb" +# define NID_des_ofb64 45 +# define OBJ_des_ofb64 OBJ_algorithm,8L + +# define SN_idea_ofb64 "IDEA-OFB" +# define LN_idea_ofb64 "idea-ofb" +# define NID_idea_ofb64 46 + +# define LN_pkcs9 "pkcs9" +# define NID_pkcs9 47 +# define OBJ_pkcs9 OBJ_pkcs,9L + +# define SN_pkcs9_emailAddress "Email" +# define LN_pkcs9_emailAddress "emailAddress" +# define NID_pkcs9_emailAddress 48 +# define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L + +# define LN_pkcs9_unstructuredName "unstructuredName" +# define NID_pkcs9_unstructuredName 49 +# define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L + +# define LN_pkcs9_contentType "contentType" +# define NID_pkcs9_contentType 50 +# define OBJ_pkcs9_contentType OBJ_pkcs9,3L + +# define LN_pkcs9_messageDigest "messageDigest" +# define NID_pkcs9_messageDigest 51 +# define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L + +# define LN_pkcs9_signingTime "signingTime" +# define NID_pkcs9_signingTime 52 +# define OBJ_pkcs9_signingTime OBJ_pkcs9,5L + +# define LN_pkcs9_countersignature "countersignature" +# define NID_pkcs9_countersignature 53 +# define OBJ_pkcs9_countersignature OBJ_pkcs9,6L + +# define LN_pkcs9_challengePassword "challengePassword" +# define NID_pkcs9_challengePassword 54 +# define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L + +# define LN_pkcs9_unstructuredAddress "unstructuredAddress" +# define NID_pkcs9_unstructuredAddress 55 +# define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L + +# define LN_pkcs9_extCertAttributes "extendedCertificateAttributes" +# define NID_pkcs9_extCertAttributes 56 +# define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L + +# define SN_netscape "Netscape" +# define LN_netscape "Netscape Communications Corp." +# define NID_netscape 57 +# define OBJ_netscape 2L,16L,840L,1L,113730L + +# define SN_netscape_cert_extension "nsCertExt" +# define LN_netscape_cert_extension "Netscape Certificate Extension" +# define NID_netscape_cert_extension 58 +# define OBJ_netscape_cert_extension OBJ_netscape,1L + +# define SN_netscape_data_type "nsDataType" +# define LN_netscape_data_type "Netscape Data Type" +# define NID_netscape_data_type 59 +# define OBJ_netscape_data_type OBJ_netscape,2L + +# define SN_des_ede_cfb64 "DES-EDE-CFB" +# define LN_des_ede_cfb64 "des-ede-cfb" +# define NID_des_ede_cfb64 60 + +# define SN_des_ede3_cfb64 "DES-EDE3-CFB" +# define LN_des_ede3_cfb64 "des-ede3-cfb" +# define NID_des_ede3_cfb64 61 + +# define SN_des_ede_ofb64 "DES-EDE-OFB" +# define LN_des_ede_ofb64 "des-ede-ofb" +# define NID_des_ede_ofb64 62 + +# define SN_des_ede3_ofb64 "DES-EDE3-OFB" +# define LN_des_ede3_ofb64 "des-ede3-ofb" +# define NID_des_ede3_ofb64 63 + +/* I'm not sure about the object ID */ +# define SN_sha1 "SHA1" +# define LN_sha1 "sha1" +# define NID_sha1 64 +# define OBJ_sha1 OBJ_algorithm,26L +/* 28 Jun 1996 - eay */ +/* #define OBJ_sha1 1L,3L,14L,2L,26L,05L <- wrong */ + +# define SN_sha1WithRSAEncryption "RSA-SHA1" +# define LN_sha1WithRSAEncryption "sha1WithRSAEncryption" +# define NID_sha1WithRSAEncryption 65 +# define OBJ_sha1WithRSAEncryption OBJ_pkcs,1L,5L + +# define SN_dsaWithSHA "DSA-SHA" +# define LN_dsaWithSHA "dsaWithSHA" +# define NID_dsaWithSHA 66 +# define OBJ_dsaWithSHA OBJ_algorithm,13L + +# define SN_dsa_2 "DSA-old" +# define LN_dsa_2 "dsaEncryption-old" +# define NID_dsa_2 67 +# define OBJ_dsa_2 OBJ_algorithm,12L + +/* proposed by microsoft to RSA */ +# define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64" +# define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC" +# define NID_pbeWithSHA1AndRC2_CBC 68 +# define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs,5L,11L + +/* + * proposed by microsoft to RSA as pbeWithSHA1AndRC4: it is now defined + * explicitly in PKCS#5 v2.0 as id-PBKDF2 which is something completely + * different. + */ +# define LN_id_pbkdf2 "PBKDF2" +# define NID_id_pbkdf2 69 +# define OBJ_id_pbkdf2 OBJ_pkcs,5L,12L + +# define SN_dsaWithSHA1_2 "DSA-SHA1-old" +# define LN_dsaWithSHA1_2 "dsaWithSHA1-old" +# define NID_dsaWithSHA1_2 70 +/* Got this one from 'sdn706r20.pdf' which is actually an NSA document :-) */ +# define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L + +# define SN_netscape_cert_type "nsCertType" +# define LN_netscape_cert_type "Netscape Cert Type" +# define NID_netscape_cert_type 71 +# define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L + +# define SN_netscape_base_url "nsBaseUrl" +# define LN_netscape_base_url "Netscape Base Url" +# define NID_netscape_base_url 72 +# define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L + +# define SN_netscape_revocation_url "nsRevocationUrl" +# define LN_netscape_revocation_url "Netscape Revocation Url" +# define NID_netscape_revocation_url 73 +# define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L + +# define SN_netscape_ca_revocation_url "nsCaRevocationUrl" +# define LN_netscape_ca_revocation_url "Netscape CA Revocation Url" +# define NID_netscape_ca_revocation_url 74 +# define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L + +# define SN_netscape_renewal_url "nsRenewalUrl" +# define LN_netscape_renewal_url "Netscape Renewal Url" +# define NID_netscape_renewal_url 75 +# define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L + +# define SN_netscape_ca_policy_url "nsCaPolicyUrl" +# define LN_netscape_ca_policy_url "Netscape CA Policy Url" +# define NID_netscape_ca_policy_url 76 +# define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L + +# define SN_netscape_ssl_server_name "nsSslServerName" +# define LN_netscape_ssl_server_name "Netscape SSL Server Name" +# define NID_netscape_ssl_server_name 77 +# define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L + +# define SN_netscape_comment "nsComment" +# define LN_netscape_comment "Netscape Comment" +# define NID_netscape_comment 78 +# define OBJ_netscape_comment OBJ_netscape_cert_extension,13L + +# define SN_netscape_cert_sequence "nsCertSequence" +# define LN_netscape_cert_sequence "Netscape Certificate Sequence" +# define NID_netscape_cert_sequence 79 +# define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L + +# define SN_desx_cbc "DESX-CBC" +# define LN_desx_cbc "desx-cbc" +# define NID_desx_cbc 80 + +# define SN_id_ce "id-ce" +# define NID_id_ce 81 +# define OBJ_id_ce 2L,5L,29L + +# define SN_subject_key_identifier "subjectKeyIdentifier" +# define LN_subject_key_identifier "X509v3 Subject Key Identifier" +# define NID_subject_key_identifier 82 +# define OBJ_subject_key_identifier OBJ_id_ce,14L + +# define SN_key_usage "keyUsage" +# define LN_key_usage "X509v3 Key Usage" +# define NID_key_usage 83 +# define OBJ_key_usage OBJ_id_ce,15L + +# define SN_private_key_usage_period "privateKeyUsagePeriod" +# define LN_private_key_usage_period "X509v3 Private Key Usage Period" +# define NID_private_key_usage_period 84 +# define OBJ_private_key_usage_period OBJ_id_ce,16L + +# define SN_subject_alt_name "subjectAltName" +# define LN_subject_alt_name "X509v3 Subject Alternative Name" +# define NID_subject_alt_name 85 +# define OBJ_subject_alt_name OBJ_id_ce,17L + +# define SN_issuer_alt_name "issuerAltName" +# define LN_issuer_alt_name "X509v3 Issuer Alternative Name" +# define NID_issuer_alt_name 86 +# define OBJ_issuer_alt_name OBJ_id_ce,18L + +# define SN_basic_constraints "basicConstraints" +# define LN_basic_constraints "X509v3 Basic Constraints" +# define NID_basic_constraints 87 +# define OBJ_basic_constraints OBJ_id_ce,19L + +# define SN_crl_number "crlNumber" +# define LN_crl_number "X509v3 CRL Number" +# define NID_crl_number 88 +# define OBJ_crl_number OBJ_id_ce,20L + +# define SN_certificate_policies "certificatePolicies" +# define LN_certificate_policies "X509v3 Certificate Policies" +# define NID_certificate_policies 89 +# define OBJ_certificate_policies OBJ_id_ce,32L + +# define SN_authority_key_identifier "authorityKeyIdentifier" +# define LN_authority_key_identifier "X509v3 Authority Key Identifier" +# define NID_authority_key_identifier 90 +# define OBJ_authority_key_identifier OBJ_id_ce,35L + +# define SN_bf_cbc "BF-CBC" +# define LN_bf_cbc "bf-cbc" +# define NID_bf_cbc 91 +# define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L + +# define SN_bf_ecb "BF-ECB" +# define LN_bf_ecb "bf-ecb" +# define NID_bf_ecb 92 + +# define SN_bf_cfb64 "BF-CFB" +# define LN_bf_cfb64 "bf-cfb" +# define NID_bf_cfb64 93 + +# define SN_bf_ofb64 "BF-OFB" +# define LN_bf_ofb64 "bf-ofb" +# define NID_bf_ofb64 94 + +# define SN_mdc2 "MDC2" +# define LN_mdc2 "mdc2" +# define NID_mdc2 95 +# define OBJ_mdc2 2L,5L,8L,3L,101L +/* An alternative? 1L,3L,14L,3L,2L,19L */ + +# define SN_mdc2WithRSA "RSA-MDC2" +# define LN_mdc2WithRSA "mdc2withRSA" +# define NID_mdc2WithRSA 96 +# define OBJ_mdc2WithRSA 2L,5L,8L,3L,100L + +# define SN_rc4_40 "RC4-40" +# define LN_rc4_40 "rc4-40" +# define NID_rc4_40 97 + +# define SN_rc2_40_cbc "RC2-40-CBC" +# define LN_rc2_40_cbc "rc2-40-cbc" +# define NID_rc2_40_cbc 98 + +# define SN_givenName "G" +# define LN_givenName "givenName" +# define NID_givenName 99 +# define OBJ_givenName OBJ_X509,42L + +# define SN_surname "S" +# define LN_surname "surname" +# define NID_surname 100 +# define OBJ_surname OBJ_X509,4L + +# define SN_initials "I" +# define LN_initials "initials" +# define NID_initials 101 +# define OBJ_initials OBJ_X509,43L + +# define SN_uniqueIdentifier "UID" +# define LN_uniqueIdentifier "uniqueIdentifier" +# define NID_uniqueIdentifier 102 +# define OBJ_uniqueIdentifier OBJ_X509,45L + +# define SN_crl_distribution_points "crlDistributionPoints" +# define LN_crl_distribution_points "X509v3 CRL Distribution Points" +# define NID_crl_distribution_points 103 +# define OBJ_crl_distribution_points OBJ_id_ce,31L + +# define SN_md5WithRSA "RSA-NP-MD5" +# define LN_md5WithRSA "md5WithRSA" +# define NID_md5WithRSA 104 +# define OBJ_md5WithRSA OBJ_algorithm,3L + +# define SN_serialNumber "SN" +# define LN_serialNumber "serialNumber" +# define NID_serialNumber 105 +# define OBJ_serialNumber OBJ_X509,5L + +# define SN_title "T" +# define LN_title "title" +# define NID_title 106 +# define OBJ_title OBJ_X509,12L + +# define SN_description "D" +# define LN_description "description" +# define NID_description 107 +# define OBJ_description OBJ_X509,13L + +/* CAST5 is CAST-128, I'm just sticking with the documentation */ +# define SN_cast5_cbc "CAST5-CBC" +# define LN_cast5_cbc "cast5-cbc" +# define NID_cast5_cbc 108 +# define OBJ_cast5_cbc 1L,2L,840L,113533L,7L,66L,10L + +# define SN_cast5_ecb "CAST5-ECB" +# define LN_cast5_ecb "cast5-ecb" +# define NID_cast5_ecb 109 + +# define SN_cast5_cfb64 "CAST5-CFB" +# define LN_cast5_cfb64 "cast5-cfb" +# define NID_cast5_cfb64 110 + +# define SN_cast5_ofb64 "CAST5-OFB" +# define LN_cast5_ofb64 "cast5-ofb" +# define NID_cast5_ofb64 111 + +# define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC" +# define NID_pbeWithMD5AndCast5_CBC 112 +# define OBJ_pbeWithMD5AndCast5_CBC 1L,2L,840L,113533L,7L,66L,12L + +/*- + * This is one sun will soon be using :-( + * id-dsa-with-sha1 ID ::= { + * iso(1) member-body(2) us(840) x9-57 (10040) x9cm(4) 3 } + */ +# define SN_dsaWithSHA1 "DSA-SHA1" +# define LN_dsaWithSHA1 "dsaWithSHA1" +# define NID_dsaWithSHA1 113 +# define OBJ_dsaWithSHA1 1L,2L,840L,10040L,4L,3L + +# define NID_md5_sha1 114 +# define SN_md5_sha1 "MD5-SHA1" +# define LN_md5_sha1 "md5-sha1" + +# define SN_sha1WithRSA "RSA-SHA1-2" +# define LN_sha1WithRSA "sha1WithRSA" +# define NID_sha1WithRSA 115 +# define OBJ_sha1WithRSA OBJ_algorithm,29L + +# define SN_dsa "DSA" +# define LN_dsa "dsaEncryption" +# define NID_dsa 116 +# define OBJ_dsa 1L,2L,840L,10040L,4L,1L + +# define SN_ripemd160 "RIPEMD160" +# define LN_ripemd160 "ripemd160" +# define NID_ripemd160 117 +# define OBJ_ripemd160 1L,3L,36L,3L,2L,1L + +/* + * The name should actually be rsaSignatureWithripemd160, but I'm going to + * continue using the convention I'm using with the other ciphers + */ +# define SN_ripemd160WithRSA "RSA-RIPEMD160" +# define LN_ripemd160WithRSA "ripemd160WithRSA" +# define NID_ripemd160WithRSA 119 +# define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L + +/*- + * Taken from rfc2040 + * RC5_CBC_Parameters ::= SEQUENCE { + * version INTEGER (v1_0(16)), + * rounds INTEGER (8..127), + * blockSizeInBits INTEGER (64, 128), + * iv OCTET STRING OPTIONAL + * } + */ +# define SN_rc5_cbc "RC5-CBC" +# define LN_rc5_cbc "rc5-cbc" +# define NID_rc5_cbc 120 +# define OBJ_rc5_cbc OBJ_rsadsi,3L,8L + +# define SN_rc5_ecb "RC5-ECB" +# define LN_rc5_ecb "rc5-ecb" +# define NID_rc5_ecb 121 + +# define SN_rc5_cfb64 "RC5-CFB" +# define LN_rc5_cfb64 "rc5-cfb" +# define NID_rc5_cfb64 122 + +# define SN_rc5_ofb64 "RC5-OFB" +# define LN_rc5_ofb64 "rc5-ofb" +# define NID_rc5_ofb64 123 + +# define SN_rle_compression "RLE" +# define LN_rle_compression "run length compression" +# define NID_rle_compression 124 +# define OBJ_rle_compression 1L,1L,1L,1L,666L,1L + +# define SN_zlib_compression "ZLIB" +# define LN_zlib_compression "zlib compression" +# define NID_zlib_compression 125 +# define OBJ_zlib_compression 1L,1L,1L,1L,666L,2L + +# define SN_ext_key_usage "extendedKeyUsage" +# define LN_ext_key_usage "X509v3 Extended Key Usage" +# define NID_ext_key_usage 126 +# define OBJ_ext_key_usage OBJ_id_ce,37 + +# define SN_id_pkix "PKIX" +# define NID_id_pkix 127 +# define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L + +# define SN_id_kp "id-kp" +# define NID_id_kp 128 +# define OBJ_id_kp OBJ_id_pkix,3L + +/* PKIX extended key usage OIDs */ + +# define SN_server_auth "serverAuth" +# define LN_server_auth "TLS Web Server Authentication" +# define NID_server_auth 129 +# define OBJ_server_auth OBJ_id_kp,1L + +# define SN_client_auth "clientAuth" +# define LN_client_auth "TLS Web Client Authentication" +# define NID_client_auth 130 +# define OBJ_client_auth OBJ_id_kp,2L + +# define SN_code_sign "codeSigning" +# define LN_code_sign "Code Signing" +# define NID_code_sign 131 +# define OBJ_code_sign OBJ_id_kp,3L + +# define SN_email_protect "emailProtection" +# define LN_email_protect "E-mail Protection" +# define NID_email_protect 132 +# define OBJ_email_protect OBJ_id_kp,4L + +# define SN_time_stamp "timeStamping" +# define LN_time_stamp "Time Stamping" +# define NID_time_stamp 133 +# define OBJ_time_stamp OBJ_id_kp,8L + +/* Additional extended key usage OIDs: Microsoft */ + +# define SN_ms_code_ind "msCodeInd" +# define LN_ms_code_ind "Microsoft Individual Code Signing" +# define NID_ms_code_ind 134 +# define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L + +# define SN_ms_code_com "msCodeCom" +# define LN_ms_code_com "Microsoft Commercial Code Signing" +# define NID_ms_code_com 135 +# define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L + +# define SN_ms_ctl_sign "msCTLSign" +# define LN_ms_ctl_sign "Microsoft Trust List Signing" +# define NID_ms_ctl_sign 136 +# define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L + +# define SN_ms_sgc "msSGC" +# define LN_ms_sgc "Microsoft Server Gated Crypto" +# define NID_ms_sgc 137 +# define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L + +# define SN_ms_efs "msEFS" +# define LN_ms_efs "Microsoft Encrypted File System" +# define NID_ms_efs 138 +# define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L + +/* Additional usage: Netscape */ + +# define SN_ns_sgc "nsSGC" +# define LN_ns_sgc "Netscape Server Gated Crypto" +# define NID_ns_sgc 139 +# define OBJ_ns_sgc OBJ_netscape,4L,1L + +# define SN_delta_crl "deltaCRL" +# define LN_delta_crl "X509v3 Delta CRL Indicator" +# define NID_delta_crl 140 +# define OBJ_delta_crl OBJ_id_ce,27L + +# define SN_crl_reason "CRLReason" +# define LN_crl_reason "CRL Reason Code" +# define NID_crl_reason 141 +# define OBJ_crl_reason OBJ_id_ce,21L + +# define SN_invalidity_date "invalidityDate" +# define LN_invalidity_date "Invalidity Date" +# define NID_invalidity_date 142 +# define OBJ_invalidity_date OBJ_id_ce,24L + +# define SN_sxnet "SXNetID" +# define LN_sxnet "Strong Extranet ID" +# define NID_sxnet 143 +# define OBJ_sxnet 1L,3L,101L,1L,4L,1L + +/* PKCS12 and related OBJECT IDENTIFIERS */ + +# define OBJ_pkcs12 OBJ_pkcs,12L +# define OBJ_pkcs12_pbeids OBJ_pkcs12, 1 + +# define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128" +# define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4" +# define NID_pbe_WithSHA1And128BitRC4 144 +# define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids, 1L + +# define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40" +# define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4" +# define NID_pbe_WithSHA1And40BitRC4 145 +# define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids, 2L + +# define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES" +# define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC" +# define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146 +# define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids, 3L + +# define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES" +# define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC" +# define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147 +# define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids, 4L + +# define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128" +# define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC" +# define NID_pbe_WithSHA1And128BitRC2_CBC 148 +# define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids, 5L + +# define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40" +# define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC" +# define NID_pbe_WithSHA1And40BitRC2_CBC 149 +# define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids, 6L + +# define OBJ_pkcs12_Version1 OBJ_pkcs12, 10L + +# define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1, 1L + +# define LN_keyBag "keyBag" +# define NID_keyBag 150 +# define OBJ_keyBag OBJ_pkcs12_BagIds, 1L + +# define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag" +# define NID_pkcs8ShroudedKeyBag 151 +# define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds, 2L + +# define LN_certBag "certBag" +# define NID_certBag 152 +# define OBJ_certBag OBJ_pkcs12_BagIds, 3L + +# define LN_crlBag "crlBag" +# define NID_crlBag 153 +# define OBJ_crlBag OBJ_pkcs12_BagIds, 4L + +# define LN_secretBag "secretBag" +# define NID_secretBag 154 +# define OBJ_secretBag OBJ_pkcs12_BagIds, 5L + +# define LN_safeContentsBag "safeContentsBag" +# define NID_safeContentsBag 155 +# define OBJ_safeContentsBag OBJ_pkcs12_BagIds, 6L + +# define LN_friendlyName "friendlyName" +# define NID_friendlyName 156 +# define OBJ_friendlyName OBJ_pkcs9, 20L + +# define LN_localKeyID "localKeyID" +# define NID_localKeyID 157 +# define OBJ_localKeyID OBJ_pkcs9, 21L + +# define OBJ_certTypes OBJ_pkcs9, 22L + +# define LN_x509Certificate "x509Certificate" +# define NID_x509Certificate 158 +# define OBJ_x509Certificate OBJ_certTypes, 1L + +# define LN_sdsiCertificate "sdsiCertificate" +# define NID_sdsiCertificate 159 +# define OBJ_sdsiCertificate OBJ_certTypes, 2L + +# define OBJ_crlTypes OBJ_pkcs9, 23L + +# define LN_x509Crl "x509Crl" +# define NID_x509Crl 160 +# define OBJ_x509Crl OBJ_crlTypes, 1L + +/* PKCS#5 v2 OIDs */ + +# define LN_pbes2 "PBES2" +# define NID_pbes2 161 +# define OBJ_pbes2 OBJ_pkcs,5L,13L + +# define LN_pbmac1 "PBMAC1" +# define NID_pbmac1 162 +# define OBJ_pbmac1 OBJ_pkcs,5L,14L + +# define LN_hmacWithSHA1 "hmacWithSHA1" +# define NID_hmacWithSHA1 163 +# define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L + +/* Policy Qualifier Ids */ + +# define LN_id_qt_cps "Policy Qualifier CPS" +# define SN_id_qt_cps "id-qt-cps" +# define NID_id_qt_cps 164 +# define OBJ_id_qt_cps OBJ_id_pkix,2L,1L + +# define LN_id_qt_unotice "Policy Qualifier User Notice" +# define SN_id_qt_unotice "id-qt-unotice" +# define NID_id_qt_unotice 165 +# define OBJ_id_qt_unotice OBJ_id_pkix,2L,2L + +# define SN_rc2_64_cbc "RC2-64-CBC" +# define LN_rc2_64_cbc "rc2-64-cbc" +# define NID_rc2_64_cbc 166 + +# define SN_SMIMECapabilities "SMIME-CAPS" +# define LN_SMIMECapabilities "S/MIME Capabilities" +# define NID_SMIMECapabilities 167 +# define OBJ_SMIMECapabilities OBJ_pkcs9,15L + +# define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64" +# define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC" +# define NID_pbeWithMD2AndRC2_CBC 168 +# define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs,5L,4L + +# define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64" +# define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC" +# define NID_pbeWithMD5AndRC2_CBC 169 +# define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs,5L,6L + +# define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES" +# define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC" +# define NID_pbeWithSHA1AndDES_CBC 170 +# define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs,5L,10L + +/* Extension request OIDs */ + +# define LN_ms_ext_req "Microsoft Extension Request" +# define SN_ms_ext_req "msExtReq" +# define NID_ms_ext_req 171 +# define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L + +# define LN_ext_req "Extension Request" +# define SN_ext_req "extReq" +# define NID_ext_req 172 +# define OBJ_ext_req OBJ_pkcs9,14L + +# define SN_name "name" +# define LN_name "name" +# define NID_name 173 +# define OBJ_name OBJ_X509,41L + +# define SN_dnQualifier "dnQualifier" +# define LN_dnQualifier "dnQualifier" +# define NID_dnQualifier 174 +# define OBJ_dnQualifier OBJ_X509,46L + +# define SN_id_pe "id-pe" +# define NID_id_pe 175 +# define OBJ_id_pe OBJ_id_pkix,1L + +# define SN_id_ad "id-ad" +# define NID_id_ad 176 +# define OBJ_id_ad OBJ_id_pkix,48L + +# define SN_info_access "authorityInfoAccess" +# define LN_info_access "Authority Information Access" +# define NID_info_access 177 +# define OBJ_info_access OBJ_id_pe,1L + +# define SN_ad_OCSP "OCSP" +# define LN_ad_OCSP "OCSP" +# define NID_ad_OCSP 178 +# define OBJ_ad_OCSP OBJ_id_ad,1L + +# define SN_ad_ca_issuers "caIssuers" +# define LN_ad_ca_issuers "CA Issuers" +# define NID_ad_ca_issuers 179 +# define OBJ_ad_ca_issuers OBJ_id_ad,2L + +# define SN_OCSP_sign "OCSPSigning" +# define LN_OCSP_sign "OCSP Signing" +# define NID_OCSP_sign 180 +# define OBJ_OCSP_sign OBJ_id_kp,9L +# endif /* USE_OBJ_MAC */ + +# include +# include + +# define OBJ_NAME_TYPE_UNDEF 0x00 +# define OBJ_NAME_TYPE_MD_METH 0x01 +# define OBJ_NAME_TYPE_CIPHER_METH 0x02 +# define OBJ_NAME_TYPE_PKEY_METH 0x03 +# define OBJ_NAME_TYPE_COMP_METH 0x04 +# define OBJ_NAME_TYPE_NUM 0x05 + +# define OBJ_NAME_ALIAS 0x8000 + +# define OBJ_BSEARCH_VALUE_ON_NOMATCH 0x01 +# define OBJ_BSEARCH_FIRST_VALUE_ON_MATCH 0x02 + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct obj_name_st { + int type; + int alias; + const char *name; + const char *data; +} OBJ_NAME; + +# define OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c) + +int OBJ_NAME_init(void); +int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *), + int (*cmp_func) (const char *, const char *), + void (*free_func) (const char *, int, const char *)); +const char *OBJ_NAME_get(const char *name, int type); +int OBJ_NAME_add(const char *name, int type, const char *data); +int OBJ_NAME_remove(const char *name, int type); +void OBJ_NAME_cleanup(int type); /* -1 for everything */ +void OBJ_NAME_do_all(int type, void (*fn) (const OBJ_NAME *, void *arg), + void *arg); +void OBJ_NAME_do_all_sorted(int type, + void (*fn) (const OBJ_NAME *, void *arg), + void *arg); + +ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o); +ASN1_OBJECT *OBJ_nid2obj(int n); +const char *OBJ_nid2ln(int n); +const char *OBJ_nid2sn(int n); +int OBJ_obj2nid(const ASN1_OBJECT *o); +ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name); +int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name); +int OBJ_txt2nid(const char *s); +int OBJ_ln2nid(const char *s); +int OBJ_sn2nid(const char *s); +int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); +const void *OBJ_bsearch_(const void *key, const void *base, int num, int size, + int (*cmp) (const void *, const void *)); +const void *OBJ_bsearch_ex_(const void *key, const void *base, int num, + int size, + int (*cmp) (const void *, const void *), + int flags); + +# define _DECLARE_OBJ_BSEARCH_CMP_FN(scope, type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *, const void *); \ + static int nm##_cmp(type1 const *, type2 const *); \ + scope type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) + +# define DECLARE_OBJ_BSEARCH_CMP_FN(type1, type2, cmp) \ + _DECLARE_OBJ_BSEARCH_CMP_FN(static, type1, type2, cmp) +# define DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm) \ + type2 * OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) + +/*- + * Unsolved problem: if a type is actually a pointer type, like + * nid_triple is, then its impossible to get a const where you need + * it. Consider: + * + * typedef int nid_triple[3]; + * const void *a_; + * const nid_triple const *a = a_; + * + * The assignement discards a const because what you really want is: + * + * const int const * const *a = a_; + * + * But if you do that, you lose the fact that a is an array of 3 ints, + * which breaks comparison functions. + * + * Thus we end up having to cast, sadly, or unpack the + * declarations. Or, as I finally did in this case, delcare nid_triple + * to be a struct, which it should have been in the first place. + * + * Ben, August 2008. + * + * Also, strictly speaking not all types need be const, but handling + * the non-constness means a lot of complication, and in practice + * comparison routines do always not touch their arguments. + */ + +# define IMPLEMENT_OBJ_BSEARCH_CMP_FN(type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) \ + { \ + type1 const *a = a_; \ + type2 const *b = b_; \ + return nm##_cmp(a,b); \ + } \ + static type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \ + { \ + return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \ + nm##_cmp_BSEARCH_CMP_FN); \ + } \ + extern void dummy_prototype(void) + +# define IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(type1, type2, nm) \ + static int nm##_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) \ + { \ + type1 const *a = a_; \ + type2 const *b = b_; \ + return nm##_cmp(a,b); \ + } \ + type2 *OBJ_bsearch_##nm(type1 *key, type2 const *base, int num) \ + { \ + return (type2 *)OBJ_bsearch_(key, base, num, sizeof(type2), \ + nm##_cmp_BSEARCH_CMP_FN); \ + } \ + extern void dummy_prototype(void) + +# define OBJ_bsearch(type1,key,type2,base,num,cmp) \ + ((type2 *)OBJ_bsearch_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \ + num,sizeof(type2), \ + ((void)CHECKED_PTR_OF(type1,cmp##_type_1), \ + (void)CHECKED_PTR_OF(type2,cmp##_type_2), \ + cmp##_BSEARCH_CMP_FN))) + +# define OBJ_bsearch_ex(type1,key,type2,base,num,cmp,flags) \ + ((type2 *)OBJ_bsearch_ex_(CHECKED_PTR_OF(type1,key),CHECKED_PTR_OF(type2,base), \ + num,sizeof(type2), \ + ((void)CHECKED_PTR_OF(type1,cmp##_type_1), \ + (void)type_2=CHECKED_PTR_OF(type2,cmp##_type_2), \ + cmp##_BSEARCH_CMP_FN)),flags) + +int OBJ_new_nid(int num); +int OBJ_add_object(const ASN1_OBJECT *obj); +int OBJ_create(const char *oid, const char *sn, const char *ln); +void OBJ_cleanup(void); +int OBJ_create_objects(BIO *in); + +int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid); +int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid); +int OBJ_add_sigid(int signid, int dig_id, int pkey_id); +void OBJ_sigid_free(void); + +extern int obj_cleanup_defer; +void check_defer(int nid); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_OBJ_strings(void); + +/* Error codes for the OBJ functions. */ + +/* Function codes. */ +# define OBJ_F_OBJ_ADD_OBJECT 105 +# define OBJ_F_OBJ_CREATE 100 +# define OBJ_F_OBJ_DUP 101 +# define OBJ_F_OBJ_NAME_NEW_INDEX 106 +# define OBJ_F_OBJ_NID2LN 102 +# define OBJ_F_OBJ_NID2OBJ 103 +# define OBJ_F_OBJ_NID2SN 104 + +/* Reason codes. */ +# define OBJ_R_MALLOC_FAILURE 100 +# define OBJ_R_UNKNOWN_NID 101 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ocsp.h b/optee/optee_test/host/openssl/include/openssl/ocsp.h new file mode 100644 index 0000000..ca2ee76 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ocsp.h @@ -0,0 +1,637 @@ +/* ocsp.h */ +/* + * Written by Tom Titchener for the OpenSSL + * project. + */ + +/* + * History: This file was transfered to Richard Levitte from CertCo by Kathy + * Weinhold in mid-spring 2000 to be included in OpenSSL or released as a + * patch kit. + */ + +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_OCSP_H +# define HEADER_OCSP_H + +# include +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Various flags and values */ + +# define OCSP_DEFAULT_NONCE_LENGTH 16 + +# define OCSP_NOCERTS 0x1 +# define OCSP_NOINTERN 0x2 +# define OCSP_NOSIGS 0x4 +# define OCSP_NOCHAIN 0x8 +# define OCSP_NOVERIFY 0x10 +# define OCSP_NOEXPLICIT 0x20 +# define OCSP_NOCASIGN 0x40 +# define OCSP_NODELEGATED 0x80 +# define OCSP_NOCHECKS 0x100 +# define OCSP_TRUSTOTHER 0x200 +# define OCSP_RESPID_KEY 0x400 +# define OCSP_NOTIME 0x800 + +/*- CertID ::= SEQUENCE { + * hashAlgorithm AlgorithmIdentifier, + * issuerNameHash OCTET STRING, -- Hash of Issuer's DN + * issuerKeyHash OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields) + * serialNumber CertificateSerialNumber } + */ +typedef struct ocsp_cert_id_st { + X509_ALGOR *hashAlgorithm; + ASN1_OCTET_STRING *issuerNameHash; + ASN1_OCTET_STRING *issuerKeyHash; + ASN1_INTEGER *serialNumber; +} OCSP_CERTID; + +DECLARE_STACK_OF(OCSP_CERTID) + +/*- Request ::= SEQUENCE { + * reqCert CertID, + * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } + */ +typedef struct ocsp_one_request_st { + OCSP_CERTID *reqCert; + STACK_OF(X509_EXTENSION) *singleRequestExtensions; +} OCSP_ONEREQ; + +DECLARE_STACK_OF(OCSP_ONEREQ) +DECLARE_ASN1_SET_OF(OCSP_ONEREQ) + +/*- TBSRequest ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * requestorName [1] EXPLICIT GeneralName OPTIONAL, + * requestList SEQUENCE OF Request, + * requestExtensions [2] EXPLICIT Extensions OPTIONAL } + */ +typedef struct ocsp_req_info_st { + ASN1_INTEGER *version; + GENERAL_NAME *requestorName; + STACK_OF(OCSP_ONEREQ) *requestList; + STACK_OF(X509_EXTENSION) *requestExtensions; +} OCSP_REQINFO; + +/*- Signature ::= SEQUENCE { + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ +typedef struct ocsp_signature_st { + X509_ALGOR *signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; +} OCSP_SIGNATURE; + +/*- OCSPRequest ::= SEQUENCE { + * tbsRequest TBSRequest, + * optionalSignature [0] EXPLICIT Signature OPTIONAL } + */ +typedef struct ocsp_request_st { + OCSP_REQINFO *tbsRequest; + OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */ +} OCSP_REQUEST; + +/*- OCSPResponseStatus ::= ENUMERATED { + * successful (0), --Response has valid confirmations + * malformedRequest (1), --Illegal confirmation request + * internalError (2), --Internal error in issuer + * tryLater (3), --Try again later + * --(4) is not used + * sigRequired (5), --Must sign the request + * unauthorized (6) --Request unauthorized + * } + */ +# define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +# define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1 +# define OCSP_RESPONSE_STATUS_INTERNALERROR 2 +# define OCSP_RESPONSE_STATUS_TRYLATER 3 +# define OCSP_RESPONSE_STATUS_SIGREQUIRED 5 +# define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6 + +/*- ResponseBytes ::= SEQUENCE { + * responseType OBJECT IDENTIFIER, + * response OCTET STRING } + */ +typedef struct ocsp_resp_bytes_st { + ASN1_OBJECT *responseType; + ASN1_OCTET_STRING *response; +} OCSP_RESPBYTES; + +/*- OCSPResponse ::= SEQUENCE { + * responseStatus OCSPResponseStatus, + * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } + */ +struct ocsp_response_st { + ASN1_ENUMERATED *responseStatus; + OCSP_RESPBYTES *responseBytes; +}; + +/*- ResponderID ::= CHOICE { + * byName [1] Name, + * byKey [2] KeyHash } + */ +# define V_OCSP_RESPID_NAME 0 +# define V_OCSP_RESPID_KEY 1 +struct ocsp_responder_id_st { + int type; + union { + X509_NAME *byName; + ASN1_OCTET_STRING *byKey; + } value; +}; + +DECLARE_STACK_OF(OCSP_RESPID) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPID) + +/*- KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key + * --(excluding the tag and length fields) + */ + +/*- RevokedInfo ::= SEQUENCE { + * revocationTime GeneralizedTime, + * revocationReason [0] EXPLICIT CRLReason OPTIONAL } + */ +typedef struct ocsp_revoked_info_st { + ASN1_GENERALIZEDTIME *revocationTime; + ASN1_ENUMERATED *revocationReason; +} OCSP_REVOKEDINFO; + +/*- CertStatus ::= CHOICE { + * good [0] IMPLICIT NULL, + * revoked [1] IMPLICIT RevokedInfo, + * unknown [2] IMPLICIT UnknownInfo } + */ +# define V_OCSP_CERTSTATUS_GOOD 0 +# define V_OCSP_CERTSTATUS_REVOKED 1 +# define V_OCSP_CERTSTATUS_UNKNOWN 2 +typedef struct ocsp_cert_status_st { + int type; + union { + ASN1_NULL *good; + OCSP_REVOKEDINFO *revoked; + ASN1_NULL *unknown; + } value; +} OCSP_CERTSTATUS; + +/*- SingleResponse ::= SEQUENCE { + * certID CertID, + * certStatus CertStatus, + * thisUpdate GeneralizedTime, + * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, + * singleExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +typedef struct ocsp_single_response_st { + OCSP_CERTID *certId; + OCSP_CERTSTATUS *certStatus; + ASN1_GENERALIZEDTIME *thisUpdate; + ASN1_GENERALIZEDTIME *nextUpdate; + STACK_OF(X509_EXTENSION) *singleExtensions; +} OCSP_SINGLERESP; + +DECLARE_STACK_OF(OCSP_SINGLERESP) +DECLARE_ASN1_SET_OF(OCSP_SINGLERESP) + +/*- ResponseData ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * responderID ResponderID, + * producedAt GeneralizedTime, + * responses SEQUENCE OF SingleResponse, + * responseExtensions [1] EXPLICIT Extensions OPTIONAL } + */ +typedef struct ocsp_response_data_st { + ASN1_INTEGER *version; + OCSP_RESPID *responderId; + ASN1_GENERALIZEDTIME *producedAt; + STACK_OF(OCSP_SINGLERESP) *responses; + STACK_OF(X509_EXTENSION) *responseExtensions; +} OCSP_RESPDATA; + +/*- BasicOCSPResponse ::= SEQUENCE { + * tbsResponseData ResponseData, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING, + * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + */ + /* + * Note 1: The value for "signature" is specified in the OCSP rfc2560 as + * follows: "The value for the signature SHALL be computed on the hash of + * the DER encoding ResponseData." This means that you must hash the + * DER-encoded tbsResponseData, and then run it through a crypto-signing + * function, which will (at least w/RSA) do a hash-'n'-private-encrypt + * operation. This seems a bit odd, but that's the spec. Also note that + * the data structures do not leave anywhere to independently specify the + * algorithm used for the initial hash. So, we look at the + * signature-specification algorithm, and try to do something intelligent. + * -- Kathy Weinhold, CertCo + */ + /* + * Note 2: It seems that the mentioned passage from RFC 2560 (section + * 4.2.1) is open for interpretation. I've done tests against another + * responder, and found that it doesn't do the double hashing that the RFC + * seems to say one should. Therefore, all relevant functions take a flag + * saying which variant should be used. -- Richard Levitte, OpenSSL team + * and CeloCom + */ +typedef struct ocsp_basic_response_st { + OCSP_RESPDATA *tbsResponseData; + X509_ALGOR *signatureAlgorithm; + ASN1_BIT_STRING *signature; + STACK_OF(X509) *certs; +} OCSP_BASICRESP; + +/*- + * CRLReason ::= ENUMERATED { + * unspecified (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6), + * removeFromCRL (8) } + */ +# define OCSP_REVOKED_STATUS_NOSTATUS -1 +# define OCSP_REVOKED_STATUS_UNSPECIFIED 0 +# define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1 +# define OCSP_REVOKED_STATUS_CACOMPROMISE 2 +# define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3 +# define OCSP_REVOKED_STATUS_SUPERSEDED 4 +# define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5 +# define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6 +# define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8 + +/*- + * CrlID ::= SEQUENCE { + * crlUrl [0] EXPLICIT IA5String OPTIONAL, + * crlNum [1] EXPLICIT INTEGER OPTIONAL, + * crlTime [2] EXPLICIT GeneralizedTime OPTIONAL } + */ +typedef struct ocsp_crl_id_st { + ASN1_IA5STRING *crlUrl; + ASN1_INTEGER *crlNum; + ASN1_GENERALIZEDTIME *crlTime; +} OCSP_CRLID; + +/*- + * ServiceLocator ::= SEQUENCE { + * issuer Name, + * locator AuthorityInfoAccessSyntax OPTIONAL } + */ +typedef struct ocsp_service_locator_st { + X509_NAME *issuer; + STACK_OF(ACCESS_DESCRIPTION) *locator; +} OCSP_SERVICELOC; + +# define PEM_STRING_OCSP_REQUEST "OCSP REQUEST" +# define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE" + +# define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p) + +# define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p) + +# define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \ + (char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,bp,(char **)x,cb,NULL) + +# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\ + (char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,bp,(char **)x,cb,NULL) + +# define PEM_write_bio_OCSP_REQUEST(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\ + bp,(char *)o, NULL,NULL,0,NULL,NULL) + +# define PEM_write_bio_OCSP_RESPONSE(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\ + bp,(char *)o, NULL,NULL,0,NULL,NULL) + +# define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o) + +# define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o) + +# define OCSP_REQUEST_sign(o,pkey,md) \ + ASN1_item_sign(ASN1_ITEM_rptr(OCSP_REQINFO),\ + o->optionalSignature->signatureAlgorithm,NULL,\ + o->optionalSignature->signature,o->tbsRequest,pkey,md) + +# define OCSP_BASICRESP_sign(o,pkey,md,d) \ + ASN1_item_sign(ASN1_ITEM_rptr(OCSP_RESPDATA),o->signatureAlgorithm,NULL,\ + o->signature,o->tbsResponseData,pkey,md) + +# define OCSP_REQUEST_verify(a,r) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_REQINFO),\ + a->optionalSignature->signatureAlgorithm,\ + a->optionalSignature->signature,a->tbsRequest,r) + +# define OCSP_BASICRESP_verify(a,r,d) ASN1_item_verify(ASN1_ITEM_rptr(OCSP_RESPDATA),\ + a->signatureAlgorithm,a->signature,a->tbsResponseData,r) + +# define ASN1_BIT_STRING_digest(data,type,md,len) \ + ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len) + +# define OCSP_CERTSTATUS_dup(cs)\ + (OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\ + (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs)) + +OCSP_CERTID *OCSP_CERTID_dup(OCSP_CERTID *id); + +OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req); +OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, + int maxline); +int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx); +int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx); +OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline); +void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx); +void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len); +int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, + ASN1_VALUE *val); +int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, ASN1_VALUE **pval, + const ASN1_ITEM *it); +BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx); +int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, + ASN1_VALUE *val); +int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path); +int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req); +int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, + const char *name, const char *value); + +OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer); + +OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, + X509_NAME *issuerName, + ASN1_BIT_STRING *issuerKey, + ASN1_INTEGER *serialNumber); + +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid); + +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len); +int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len); +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs); +int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req); + +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm); +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert); + +int OCSP_request_sign(OCSP_REQUEST *req, + X509 *signer, + EVP_PKEY *key, + const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags); + +int OCSP_response_status(OCSP_RESPONSE *resp); +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp); + +int OCSP_resp_count(OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx); +int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last); +int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status, + int *reason, + ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, + ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec); + +int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, + X509_STORE *store, unsigned long flags); + +int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath, + int *pssl); + +int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b); +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); + +int OCSP_request_onereq_count(OCSP_REQUEST *req); +OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i); +OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one); +int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, + ASN1_OCTET_STRING **pikeyHash, + ASN1_INTEGER **pserial, OCSP_CERTID *cid); +int OCSP_request_is_signed(OCSP_REQUEST *req); +OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp, + OCSP_CERTID *cid, + int status, int reason, + ASN1_TIME *revtime, + ASN1_TIME *thisupd, + ASN1_TIME *nextupd); +int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert); +int OCSP_basic_sign(OCSP_BASICRESP *brsp, + X509 *signer, EVP_PKEY *key, const EVP_MD *dgst, + STACK_OF(X509) *certs, unsigned long flags); + +X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim); + +X509_EXTENSION *OCSP_accept_responses_new(char **oids); + +X509_EXTENSION *OCSP_archive_cutoff_new(char *tim); + +X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, char **urls); + +int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x); +int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos); +int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, ASN1_OBJECT *obj, + int lastpos); +int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos); +X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc); +X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc); +void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, + int *idx); +int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc); + +int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x); +int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos); +int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, ASN1_OBJECT *obj, int lastpos); +int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos); +X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc); +X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc); +void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx); +int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc); + +int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x); +int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos); +int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, ASN1_OBJECT *obj, + int lastpos); +int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc); +X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc); +void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, + int *idx); +int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc); + +int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x); +int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos); +int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, ASN1_OBJECT *obj, + int lastpos); +int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc); +X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc); +void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, + int *idx); +int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc); + +DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP) +DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS) +DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO) +DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPID) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE) +DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES) +DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ) +DECLARE_ASN1_FUNCTIONS(OCSP_CERTID) +DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST) +DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE) +DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO) +DECLARE_ASN1_FUNCTIONS(OCSP_CRLID) +DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC) + +const char *OCSP_response_status_str(long s); +const char *OCSP_cert_status_str(long s); +const char *OCSP_crl_reason_str(long s); + +int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *a, unsigned long flags); +int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags); + +int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_OCSP_strings(void); + +/* Error codes for the OCSP functions. */ + +/* Function codes. */ +# define OCSP_F_ASN1_STRING_ENCODE 100 +# define OCSP_F_D2I_OCSP_NONCE 102 +# define OCSP_F_OCSP_BASIC_ADD1_STATUS 103 +# define OCSP_F_OCSP_BASIC_SIGN 104 +# define OCSP_F_OCSP_BASIC_VERIFY 105 +# define OCSP_F_OCSP_CERT_ID_NEW 101 +# define OCSP_F_OCSP_CHECK_DELEGATED 106 +# define OCSP_F_OCSP_CHECK_IDS 107 +# define OCSP_F_OCSP_CHECK_ISSUER 108 +# define OCSP_F_OCSP_CHECK_VALIDITY 115 +# define OCSP_F_OCSP_MATCH_ISSUERID 109 +# define OCSP_F_OCSP_PARSE_URL 114 +# define OCSP_F_OCSP_REQUEST_SIGN 110 +# define OCSP_F_OCSP_REQUEST_VERIFY 116 +# define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111 +# define OCSP_F_OCSP_SENDREQ_BIO 112 +# define OCSP_F_OCSP_SENDREQ_NBIO 117 +# define OCSP_F_PARSE_HTTP_LINE1 118 +# define OCSP_F_REQUEST_VERIFY 113 + +/* Reason codes. */ +# define OCSP_R_BAD_DATA 100 +# define OCSP_R_CERTIFICATE_VERIFY_ERROR 101 +# define OCSP_R_DIGEST_ERR 102 +# define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122 +# define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123 +# define OCSP_R_ERROR_PARSING_URL 121 +# define OCSP_R_MISSING_OCSPSIGNING_USAGE 103 +# define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124 +# define OCSP_R_NOT_BASIC_RESPONSE 104 +# define OCSP_R_NO_CERTIFICATES_IN_CHAIN 105 +# define OCSP_R_NO_CONTENT 106 +# define OCSP_R_NO_PUBLIC_KEY 107 +# define OCSP_R_NO_RESPONSE_DATA 108 +# define OCSP_R_NO_REVOKED_TIME 109 +# define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 110 +# define OCSP_R_REQUEST_NOT_SIGNED 128 +# define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111 +# define OCSP_R_ROOT_CA_NOT_TRUSTED 112 +# define OCSP_R_SERVER_READ_ERROR 113 +# define OCSP_R_SERVER_RESPONSE_ERROR 114 +# define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115 +# define OCSP_R_SERVER_WRITE_ERROR 116 +# define OCSP_R_SIGNATURE_FAILURE 117 +# define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118 +# define OCSP_R_STATUS_EXPIRED 125 +# define OCSP_R_STATUS_NOT_YET_VALID 126 +# define OCSP_R_STATUS_TOO_OLD 127 +# define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119 +# define OCSP_R_UNKNOWN_NID 120 +# define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE 129 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/opensslconf.h b/optee/optee_test/host/openssl/include/openssl/opensslconf.h new file mode 100644 index 0000000..126651a --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/opensslconf.h @@ -0,0 +1,270 @@ +/* opensslconf.h */ +/* WARNING: Generated automatically from opensslconf.h.in by Configure. */ + +#ifdef __cplusplus +extern "C" { +#endif +/* OpenSSL was configured with the following options: */ +#ifndef OPENSSL_DOING_MAKEDEPEND + + +#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +# define OPENSSL_NO_EC_NISTP_64_GCC_128 +#endif +#ifndef OPENSSL_NO_GMP +# define OPENSSL_NO_GMP +#endif +#ifndef OPENSSL_NO_JPAKE +# define OPENSSL_NO_JPAKE +#endif +#ifndef OPENSSL_NO_KRB5 +# define OPENSSL_NO_KRB5 +#endif +#ifndef OPENSSL_NO_LIBUNBOUND +# define OPENSSL_NO_LIBUNBOUND +#endif +#ifndef OPENSSL_NO_MD2 +# define OPENSSL_NO_MD2 +#endif +#ifndef OPENSSL_NO_RC5 +# define OPENSSL_NO_RC5 +#endif +#ifndef OPENSSL_NO_RFC3779 +# define OPENSSL_NO_RFC3779 +#endif +#ifndef OPENSSL_NO_SCTP +# define OPENSSL_NO_SCTP +#endif +#ifndef OPENSSL_NO_SSL_TRACE +# define OPENSSL_NO_SSL_TRACE +#endif +#ifndef OPENSSL_NO_SSL2 +# define OPENSSL_NO_SSL2 +#endif +#ifndef OPENSSL_NO_STORE +# define OPENSSL_NO_STORE +#endif +#ifndef OPENSSL_NO_UNIT_TEST +# define OPENSSL_NO_UNIT_TEST +#endif +#ifndef OPENSSL_NO_WEAK_SSL_CIPHERS +# define OPENSSL_NO_WEAK_SSL_CIPHERS +#endif + +#endif /* OPENSSL_DOING_MAKEDEPEND */ + +#ifndef OPENSSL_THREADS +# define OPENSSL_THREADS +#endif +#ifndef OPENSSL_NO_STATIC_ENGINE +# define OPENSSL_NO_STATIC_ENGINE +#endif + +/* The OPENSSL_NO_* macros are also defined as NO_* if the application + asks for it. This is a transient feature that is provided for those + who haven't had the time to do the appropriate changes in their + applications. */ +#ifdef OPENSSL_ALGORITHM_DEFINES +# if defined(OPENSSL_NO_EC_NISTP_64_GCC_128) && !defined(NO_EC_NISTP_64_GCC_128) +# define NO_EC_NISTP_64_GCC_128 +# endif +# if defined(OPENSSL_NO_GMP) && !defined(NO_GMP) +# define NO_GMP +# endif +# if defined(OPENSSL_NO_JPAKE) && !defined(NO_JPAKE) +# define NO_JPAKE +# endif +# if defined(OPENSSL_NO_KRB5) && !defined(NO_KRB5) +# define NO_KRB5 +# endif +# if defined(OPENSSL_NO_LIBUNBOUND) && !defined(NO_LIBUNBOUND) +# define NO_LIBUNBOUND +# endif +# if defined(OPENSSL_NO_MD2) && !defined(NO_MD2) +# define NO_MD2 +# endif +# if defined(OPENSSL_NO_RC5) && !defined(NO_RC5) +# define NO_RC5 +# endif +# if defined(OPENSSL_NO_RFC3779) && !defined(NO_RFC3779) +# define NO_RFC3779 +# endif +# if defined(OPENSSL_NO_SCTP) && !defined(NO_SCTP) +# define NO_SCTP +# endif +# if defined(OPENSSL_NO_SSL_TRACE) && !defined(NO_SSL_TRACE) +# define NO_SSL_TRACE +# endif +# if defined(OPENSSL_NO_SSL2) && !defined(NO_SSL2) +# define NO_SSL2 +# endif +# if defined(OPENSSL_NO_STORE) && !defined(NO_STORE) +# define NO_STORE +# endif +# if defined(OPENSSL_NO_UNIT_TEST) && !defined(NO_UNIT_TEST) +# define NO_UNIT_TEST +# endif +# if defined(OPENSSL_NO_WEAK_SSL_CIPHERS) && !defined(NO_WEAK_SSL_CIPHERS) +# define NO_WEAK_SSL_CIPHERS +# endif +#endif + +#define OPENSSL_CPUID_OBJ + +/* crypto/opensslconf.h.in */ + +/* Generate 80386 code? */ +#undef I386_ONLY + +#if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */ +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define ENGINESDIR "/usr//lib/engines" +#define OPENSSLDIR "/etc/ssl" +#endif +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned char +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#define BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#define BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependancies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +#error YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very mucy CPU dependant */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( __sun ) || defined ( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ +#ifdef __cplusplus +} +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/opensslv.h b/optee/optee_test/host/openssl/include/openssl/opensslv.h new file mode 100644 index 0000000..77f124e --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/opensslv.h @@ -0,0 +1,97 @@ +#ifndef HEADER_OPENSSLV_H +# define HEADER_OPENSSLV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*- + * Numeric release version identifier: + * MNNFFPPS: major minor fix patch status + * The status nibble has one of the values 0 for development, 1 to e for betas + * 1 to 14, and f for release. The patch level is exactly that. + * For example: + * 0.9.3-dev 0x00903000 + * 0.9.3-beta1 0x00903001 + * 0.9.3-beta2-dev 0x00903002 + * 0.9.3-beta2 0x00903002 (same as ...beta2-dev) + * 0.9.3 0x0090300f + * 0.9.3a 0x0090301f + * 0.9.4 0x0090400f + * 1.2.3z 0x102031af + * + * For continuity reasons (because 0.9.5 is already out, and is coded + * 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level + * part is slightly different, by setting the highest bit. This means + * that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start + * with 0x0090600S... + * + * (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.) + * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for + * major minor fix final patch/beta) + */ +# define OPENSSL_VERSION_NUMBER 0x100020ffL +# ifdef OPENSSL_FIPS +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2o-fips 27 Mar 2018" +# else +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2o 27 Mar 2018" +# endif +# define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT + +/*- + * The macros below are to be used for shared library (.so, .dll, ...) + * versioning. That kind of versioning works a bit differently between + * operating systems. The most usual scheme is to set a major and a minor + * number, and have the runtime loader check that the major number is equal + * to what it was at application link time, while the minor number has to + * be greater or equal to what it was at application link time. With this + * scheme, the version number is usually part of the file name, like this: + * + * libcrypto.so.0.9 + * + * Some unixen also make a softlink with the major verson number only: + * + * libcrypto.so.0 + * + * On Tru64 and IRIX 6.x it works a little bit differently. There, the + * shared library version is stored in the file, and is actually a series + * of versions, separated by colons. The rightmost version present in the + * library when linking an application is stored in the application to be + * matched at run time. When the application is run, a check is done to + * see if the library version stored in the application matches any of the + * versions in the version string of the library itself. + * This version string can be constructed in any way, depending on what + * kind of matching is desired. However, to implement the same scheme as + * the one used in the other unixen, all compatible versions, from lowest + * to highest, should be part of the string. Consecutive builds would + * give the following versions strings: + * + * 3.0 + * 3.0:3.1 + * 3.0:3.1:3.2 + * 4.0 + * 4.0:4.1 + * + * Notice how version 4 is completely incompatible with version, and + * therefore give the breach you can see. + * + * There may be other schemes as well that I haven't yet discovered. + * + * So, here's the way it works here: first of all, the library version + * number doesn't need at all to match the overall OpenSSL version. + * However, it's nice and more understandable if it actually does. + * The current library version is stored in the macro SHLIB_VERSION_NUMBER, + * which is just a piece of text in the format "M.m.e" (Major, minor, edit). + * For the sake of Tru64, IRIX, and any other OS that behaves in similar ways, + * we need to keep a history of version numbers, which is done in the + * macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and + * should only keep the versions that are binary compatible with the current. + */ +# define SHLIB_VERSION_HISTORY "" +# define SHLIB_VERSION_NUMBER "1.0.0" + + +#ifdef __cplusplus +} +#endif +#endif /* HEADER_OPENSSLV_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/ossl_typ.h b/optee/optee_test/host/openssl/include/openssl/ossl_typ.h new file mode 100644 index 0000000..364d262 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ossl_typ.h @@ -0,0 +1,213 @@ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_OPENSSL_TYPES_H +# define HEADER_OPENSSL_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +# include + +# ifdef NO_ASN1_TYPEDEFS +# define ASN1_INTEGER ASN1_STRING +# define ASN1_ENUMERATED ASN1_STRING +# define ASN1_BIT_STRING ASN1_STRING +# define ASN1_OCTET_STRING ASN1_STRING +# define ASN1_PRINTABLESTRING ASN1_STRING +# define ASN1_T61STRING ASN1_STRING +# define ASN1_IA5STRING ASN1_STRING +# define ASN1_UTCTIME ASN1_STRING +# define ASN1_GENERALIZEDTIME ASN1_STRING +# define ASN1_TIME ASN1_STRING +# define ASN1_GENERALSTRING ASN1_STRING +# define ASN1_UNIVERSALSTRING ASN1_STRING +# define ASN1_BMPSTRING ASN1_STRING +# define ASN1_VISIBLESTRING ASN1_STRING +# define ASN1_UTF8STRING ASN1_STRING +# define ASN1_BOOLEAN int +# define ASN1_NULL int +# else +typedef struct asn1_string_st ASN1_INTEGER; +typedef struct asn1_string_st ASN1_ENUMERATED; +typedef struct asn1_string_st ASN1_BIT_STRING; +typedef struct asn1_string_st ASN1_OCTET_STRING; +typedef struct asn1_string_st ASN1_PRINTABLESTRING; +typedef struct asn1_string_st ASN1_T61STRING; +typedef struct asn1_string_st ASN1_IA5STRING; +typedef struct asn1_string_st ASN1_GENERALSTRING; +typedef struct asn1_string_st ASN1_UNIVERSALSTRING; +typedef struct asn1_string_st ASN1_BMPSTRING; +typedef struct asn1_string_st ASN1_UTCTIME; +typedef struct asn1_string_st ASN1_TIME; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; +typedef struct asn1_string_st ASN1_VISIBLESTRING; +typedef struct asn1_string_st ASN1_UTF8STRING; +typedef struct asn1_string_st ASN1_STRING; +typedef int ASN1_BOOLEAN; +typedef int ASN1_NULL; +# endif + +typedef struct asn1_object_st ASN1_OBJECT; + +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct asn1_pctx_st ASN1_PCTX; + +# ifdef OPENSSL_SYS_WIN32 +# undef X509_NAME +# undef X509_EXTENSIONS +# undef X509_CERT_PAIR +# undef PKCS7_ISSUER_AND_SERIAL +# undef OCSP_REQUEST +# undef OCSP_RESPONSE +# endif + +# ifdef BIGNUM +# undef BIGNUM +# endif +typedef struct bignum_st BIGNUM; +typedef struct bignum_ctx BN_CTX; +typedef struct bn_blinding_st BN_BLINDING; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct bn_recp_ctx_st BN_RECP_CTX; +typedef struct bn_gencb_st BN_GENCB; + +typedef struct buf_mem_st BUF_MEM; + +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; +typedef struct env_md_st EVP_MD; +typedef struct env_md_ctx_st EVP_MD_CTX; +typedef struct evp_pkey_st EVP_PKEY; + +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; + +typedef struct evp_pkey_method_st EVP_PKEY_METHOD; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; + +typedef struct dh_st DH; +typedef struct dh_method DH_METHOD; + +typedef struct dsa_st DSA; +typedef struct dsa_method DSA_METHOD; + +typedef struct rsa_st RSA; +typedef struct rsa_meth_st RSA_METHOD; + +typedef struct rand_meth_st RAND_METHOD; + +typedef struct ecdh_method ECDH_METHOD; +typedef struct ecdsa_method ECDSA_METHOD; + +typedef struct x509_st X509; +typedef struct X509_algor_st X509_ALGOR; +typedef struct X509_crl_st X509_CRL; +typedef struct x509_crl_method_st X509_CRL_METHOD; +typedef struct x509_revoked_st X509_REVOKED; +typedef struct X509_name_st X509_NAME; +typedef struct X509_pubkey_st X509_PUBKEY; +typedef struct x509_store_st X509_STORE; +typedef struct x509_store_ctx_st X509_STORE_CTX; + +typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; + +typedef struct v3_ext_ctx X509V3_CTX; +typedef struct conf_st CONF; + +typedef struct store_st STORE; +typedef struct store_method_st STORE_METHOD; + +typedef struct ui_st UI; +typedef struct ui_method_st UI_METHOD; + +typedef struct st_ERR_FNS ERR_FNS; + +typedef struct engine_st ENGINE; +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; + +typedef struct comp_method_st COMP_METHOD; + +typedef struct X509_POLICY_NODE_st X509_POLICY_NODE; +typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL; +typedef struct X509_POLICY_TREE_st X509_POLICY_TREE; +typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE; + +typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID; +typedef struct DIST_POINT_st DIST_POINT; +typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT; +typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS; + + /* If placed in pkcs12.h, we end up with a circular depency with pkcs7.h */ +# define DECLARE_PKCS12_STACK_OF(type)/* Nothing */ +# define IMPLEMENT_PKCS12_STACK_OF(type)/* Nothing */ + +typedef struct crypto_ex_data_st CRYPTO_EX_DATA; +/* Callback types for crypto.h */ +typedef int CRYPTO_EX_new (void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +typedef void CRYPTO_EX_free (void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +typedef int CRYPTO_EX_dup (CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, + void *from_d, int idx, long argl, void *argp); + +typedef struct ocsp_req_ctx_st OCSP_REQ_CTX; +typedef struct ocsp_response_st OCSP_RESPONSE; +typedef struct ocsp_responder_id_st OCSP_RESPID; + +#ifdef __cplusplus +} +#endif +#endif /* def HEADER_OPENSSL_TYPES_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/pem.h b/optee/optee_test/host/openssl/include/openssl/pem.h new file mode 100644 index 0000000..aac72fb --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/pem.h @@ -0,0 +1,617 @@ +/* crypto/pem/pem.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_PEM_H +# define HEADER_PEM_H + +# include +# ifndef OPENSSL_NO_BIO +# include +# endif +# ifndef OPENSSL_NO_STACK +# include +# endif +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define PEM_BUFSIZE 1024 + +# define PEM_OBJ_UNDEF 0 +# define PEM_OBJ_X509 1 +# define PEM_OBJ_X509_REQ 2 +# define PEM_OBJ_CRL 3 +# define PEM_OBJ_SSL_SESSION 4 +# define PEM_OBJ_PRIV_KEY 10 +# define PEM_OBJ_PRIV_RSA 11 +# define PEM_OBJ_PRIV_DSA 12 +# define PEM_OBJ_PRIV_DH 13 +# define PEM_OBJ_PUB_RSA 14 +# define PEM_OBJ_PUB_DSA 15 +# define PEM_OBJ_PUB_DH 16 +# define PEM_OBJ_DHPARAMS 17 +# define PEM_OBJ_DSAPARAMS 18 +# define PEM_OBJ_PRIV_RSA_PUBLIC 19 +# define PEM_OBJ_PRIV_ECDSA 20 +# define PEM_OBJ_PUB_ECDSA 21 +# define PEM_OBJ_ECPARAMETERS 22 + +# define PEM_ERROR 30 +# define PEM_DEK_DES_CBC 40 +# define PEM_DEK_IDEA_CBC 45 +# define PEM_DEK_DES_EDE 50 +# define PEM_DEK_DES_ECB 60 +# define PEM_DEK_RSA 70 +# define PEM_DEK_RSA_MD2 80 +# define PEM_DEK_RSA_MD5 90 + +# define PEM_MD_MD2 NID_md2 +# define PEM_MD_MD5 NID_md5 +# define PEM_MD_SHA NID_sha +# define PEM_MD_MD2_RSA NID_md2WithRSAEncryption +# define PEM_MD_MD5_RSA NID_md5WithRSAEncryption +# define PEM_MD_SHA_RSA NID_sha1WithRSAEncryption + +# define PEM_STRING_X509_OLD "X509 CERTIFICATE" +# define PEM_STRING_X509 "CERTIFICATE" +# define PEM_STRING_X509_PAIR "CERTIFICATE PAIR" +# define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" +# define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" +# define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" +# define PEM_STRING_X509_CRL "X509 CRL" +# define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" +# define PEM_STRING_PUBLIC "PUBLIC KEY" +# define PEM_STRING_RSA "RSA PRIVATE KEY" +# define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" +# define PEM_STRING_DSA "DSA PRIVATE KEY" +# define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY" +# define PEM_STRING_PKCS7 "PKCS7" +# define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA" +# define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY" +# define PEM_STRING_PKCS8INF "PRIVATE KEY" +# define PEM_STRING_DHPARAMS "DH PARAMETERS" +# define PEM_STRING_DHXPARAMS "X9.42 DH PARAMETERS" +# define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS" +# define PEM_STRING_DSAPARAMS "DSA PARAMETERS" +# define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY" +# define PEM_STRING_ECPARAMETERS "EC PARAMETERS" +# define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY" +# define PEM_STRING_PARAMETERS "PARAMETERS" +# define PEM_STRING_CMS "CMS" + + /* + * Note that this structure is initialised by PEM_SealInit and cleaned up + * by PEM_SealFinal (at least for now) + */ +typedef struct PEM_Encode_Seal_st { + EVP_ENCODE_CTX encode; + EVP_MD_CTX md; + EVP_CIPHER_CTX cipher; +} PEM_ENCODE_SEAL_CTX; + +/* enc_type is one off */ +# define PEM_TYPE_ENCRYPTED 10 +# define PEM_TYPE_MIC_ONLY 20 +# define PEM_TYPE_MIC_CLEAR 30 +# define PEM_TYPE_CLEAR 40 + +typedef struct pem_recip_st { + char *name; + X509_NAME *dn; + int cipher; + int key_enc; + /* char iv[8]; unused and wrong size */ +} PEM_USER; + +typedef struct pem_ctx_st { + int type; /* what type of object */ + struct { + int version; + int mode; + } proc_type; + + char *domain; + + struct { + int cipher; + /*- + unused, and wrong size + unsigned char iv[8]; */ + } DEK_info; + + PEM_USER *originator; + + int num_recipient; + PEM_USER **recipient; +/*- + XXX(ben): don#t think this is used! + STACK *x509_chain; / * certificate chain */ + EVP_MD *md; /* signature type */ + + int md_enc; /* is the md encrypted or not? */ + int md_len; /* length of md_data */ + char *md_data; /* message digest, could be pkey encrypted */ + + EVP_CIPHER *dec; /* date encryption cipher */ + int key_len; /* key length */ + unsigned char *key; /* key */ + /*- + unused, and wrong size + unsigned char iv[8]; */ + + int data_enc; /* is the data encrypted */ + int data_len; + unsigned char *data; +} PEM_CTX; + +/* + * These macros make the PEM_read/PEM_write functions easier to maintain and + * write. Now they are all implemented with either: IMPLEMENT_PEM_rw(...) or + * IMPLEMENT_PEM_rw_cb(...) + */ + +# ifdef OPENSSL_NO_FP_API + +# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) /**/ +# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) /**/ +# else + +# define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ +type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \ +} + +# define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, const type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +# endif + +# define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ +type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \ +} + +# define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, const type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +# define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,enc,kstr,klen,cb,u); \ + } + +# define IMPLEMENT_PEM_write(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_read_fp(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_const(name, type, str, asn1) + +# define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb(name, type, str, asn1) + +/* These are the same except they are for the declarations */ + +# if defined(OPENSSL_NO_FP_API) + +# define DECLARE_PEM_read_fp(name, type) /**/ +# define DECLARE_PEM_write_fp(name, type) /**/ +# define DECLARE_PEM_write_cb_fp(name, type) /**/ +# else + +# define DECLARE_PEM_read_fp(name, type) \ + type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u); + +# define DECLARE_PEM_write_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x); + +# define DECLARE_PEM_write_fp_const(name, type) \ + int PEM_write_##name(FILE *fp, const type *x); + +# define DECLARE_PEM_write_cb_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +# endif + +# ifndef OPENSSL_NO_BIO +# define DECLARE_PEM_read_bio(name, type) \ + type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u); + +# define DECLARE_PEM_write_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x); + +# define DECLARE_PEM_write_bio_const(name, type) \ + int PEM_write_bio_##name(BIO *bp, const type *x); + +# define DECLARE_PEM_write_cb_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +# else + +# define DECLARE_PEM_read_bio(name, type) /**/ +# define DECLARE_PEM_write_bio(name, type) /**/ +# define DECLARE_PEM_write_bio_const(name, type) /**/ +# define DECLARE_PEM_write_cb_bio(name, type) /**/ +# endif +# define DECLARE_PEM_write(name, type) \ + DECLARE_PEM_write_bio(name, type) \ + DECLARE_PEM_write_fp(name, type) +# define DECLARE_PEM_write_const(name, type) \ + DECLARE_PEM_write_bio_const(name, type) \ + DECLARE_PEM_write_fp_const(name, type) +# define DECLARE_PEM_write_cb(name, type) \ + DECLARE_PEM_write_cb_bio(name, type) \ + DECLARE_PEM_write_cb_fp(name, type) +# define DECLARE_PEM_read(name, type) \ + DECLARE_PEM_read_bio(name, type) \ + DECLARE_PEM_read_fp(name, type) +# define DECLARE_PEM_rw(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write(name, type) +# define DECLARE_PEM_rw_const(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_const(name, type) +# define DECLARE_PEM_rw_cb(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_cb(name, type) +# if 1 +/* "userdata": new with OpenSSL 0.9.4 */ +typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata); +# else +/* OpenSSL 0.9.3, 0.9.3a */ +typedef int pem_password_cb (char *buf, int size, int rwflag); +# endif + +int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher); +int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *len, + pem_password_cb *callback, void *u); + +# ifndef OPENSSL_NO_BIO +int PEM_read_bio(BIO *bp, char **name, char **header, + unsigned char **data, long *len); +int PEM_write_bio(BIO *bp, const char *name, const char *hdr, + const unsigned char *data, long len); +int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, + void *u); +void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); + +STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); +int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cd, void *u); +# endif + +int PEM_read(FILE *fp, char **name, char **header, + unsigned char **data, long *len); +int PEM_write(FILE *fp, const char *name, const char *hdr, + const unsigned char *data, long len); +void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, + void *x, const EVP_CIPHER *enc, unsigned char *kstr, + int klen, pem_password_cb *callback, void *u); +STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); + +int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, + EVP_MD *md_type, unsigned char **ek, int *ekl, + unsigned char *iv, EVP_PKEY **pubk, int npubk); +void PEM_SealUpdate(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *out, int *outl, + unsigned char *in, int inl); +int PEM_SealFinal(PEM_ENCODE_SEAL_CTX *ctx, unsigned char *sig, int *sigl, + unsigned char *out, int *outl, EVP_PKEY *priv); + +void PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type); +void PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *d, unsigned int cnt); +int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, EVP_PKEY *pkey); + +int PEM_def_callback(char *buf, int num, int w, void *key); +void PEM_proc_type(char *buf, int type); +void PEM_dek_info(char *buf, const char *type, int len, char *str); + +# include + +DECLARE_PEM_rw(X509, X509) +DECLARE_PEM_rw(X509_AUX, X509) +DECLARE_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR) +DECLARE_PEM_rw(X509_REQ, X509_REQ) +DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) +DECLARE_PEM_rw(X509_CRL, X509_CRL) +DECLARE_PEM_rw(PKCS7, PKCS7) +DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE) +DECLARE_PEM_rw(PKCS8, X509_SIG) +DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) +# ifndef OPENSSL_NO_RSA +DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) +DECLARE_PEM_rw_const(RSAPublicKey, RSA) +DECLARE_PEM_rw(RSA_PUBKEY, RSA) +# endif +# ifndef OPENSSL_NO_DSA +DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) +DECLARE_PEM_rw(DSA_PUBKEY, DSA) +DECLARE_PEM_rw_const(DSAparams, DSA) +# endif +# ifndef OPENSSL_NO_EC +DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP) +DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY) +DECLARE_PEM_rw(EC_PUBKEY, EC_KEY) +# endif +# ifndef OPENSSL_NO_DH +DECLARE_PEM_rw_const(DHparams, DH) +DECLARE_PEM_write_const(DHxparams, DH) +# endif +DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) +DECLARE_PEM_rw(PUBKEY, EVP_PKEY) + +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, + char *, int, pem_password_cb *, void *); +int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, + void *u); + +int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); + +EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, + void *u); + +int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cd, + void *u); + +EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x); +int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x); + +EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length); +EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length); +EVP_PKEY *b2i_PrivateKey_bio(BIO *in); +EVP_PKEY *b2i_PublicKey_bio(BIO *in); +int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk); +int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk); +# ifndef OPENSSL_NO_RC4 +EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u); +int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, + pem_password_cb *cb, void *u); +# endif + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +void ERR_load_PEM_strings(void); + +/* Error codes for the PEM functions. */ + +/* Function codes. */ +# define PEM_F_B2I_DSS 127 +# define PEM_F_B2I_PVK_BIO 128 +# define PEM_F_B2I_RSA 129 +# define PEM_F_CHECK_BITLEN_DSA 130 +# define PEM_F_CHECK_BITLEN_RSA 131 +# define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120 +# define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121 +# define PEM_F_DO_B2I 132 +# define PEM_F_DO_B2I_BIO 133 +# define PEM_F_DO_BLOB_HEADER 134 +# define PEM_F_DO_PK8PKEY 126 +# define PEM_F_DO_PK8PKEY_FP 125 +# define PEM_F_DO_PVK_BODY 135 +# define PEM_F_DO_PVK_HEADER 136 +# define PEM_F_I2B_PVK 137 +# define PEM_F_I2B_PVK_BIO 138 +# define PEM_F_LOAD_IV 101 +# define PEM_F_PEM_ASN1_READ 102 +# define PEM_F_PEM_ASN1_READ_BIO 103 +# define PEM_F_PEM_ASN1_WRITE 104 +# define PEM_F_PEM_ASN1_WRITE_BIO 105 +# define PEM_F_PEM_DEF_CALLBACK 100 +# define PEM_F_PEM_DO_HEADER 106 +# define PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY 118 +# define PEM_F_PEM_GET_EVP_CIPHER_INFO 107 +# define PEM_F_PEM_PK8PKEY 119 +# define PEM_F_PEM_READ 108 +# define PEM_F_PEM_READ_BIO 109 +# define PEM_F_PEM_READ_BIO_DHPARAMS 141 +# define PEM_F_PEM_READ_BIO_PARAMETERS 140 +# define PEM_F_PEM_READ_BIO_PRIVATEKEY 123 +# define PEM_F_PEM_READ_DHPARAMS 142 +# define PEM_F_PEM_READ_PRIVATEKEY 124 +# define PEM_F_PEM_SEALFINAL 110 +# define PEM_F_PEM_SEALINIT 111 +# define PEM_F_PEM_SIGNFINAL 112 +# define PEM_F_PEM_WRITE 113 +# define PEM_F_PEM_WRITE_BIO 114 +# define PEM_F_PEM_WRITE_PRIVATEKEY 139 +# define PEM_F_PEM_X509_INFO_READ 115 +# define PEM_F_PEM_X509_INFO_READ_BIO 116 +# define PEM_F_PEM_X509_INFO_WRITE_BIO 117 + +/* Reason codes. */ +# define PEM_R_BAD_BASE64_DECODE 100 +# define PEM_R_BAD_DECRYPT 101 +# define PEM_R_BAD_END_LINE 102 +# define PEM_R_BAD_IV_CHARS 103 +# define PEM_R_BAD_MAGIC_NUMBER 116 +# define PEM_R_BAD_PASSWORD_READ 104 +# define PEM_R_BAD_VERSION_NUMBER 117 +# define PEM_R_BIO_WRITE_FAILURE 118 +# define PEM_R_CIPHER_IS_NULL 127 +# define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115 +# define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 119 +# define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 120 +# define PEM_R_HEADER_TOO_LONG 128 +# define PEM_R_INCONSISTENT_HEADER 121 +# define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 122 +# define PEM_R_KEYBLOB_TOO_SHORT 123 +# define PEM_R_NOT_DEK_INFO 105 +# define PEM_R_NOT_ENCRYPTED 106 +# define PEM_R_NOT_PROC_TYPE 107 +# define PEM_R_NO_START_LINE 108 +# define PEM_R_PROBLEMS_GETTING_PASSWORD 109 +# define PEM_R_PUBLIC_KEY_NO_RSA 110 +# define PEM_R_PVK_DATA_TOO_SHORT 124 +# define PEM_R_PVK_TOO_SHORT 125 +# define PEM_R_READ_KEY 111 +# define PEM_R_SHORT_HEADER 112 +# define PEM_R_UNSUPPORTED_CIPHER 113 +# define PEM_R_UNSUPPORTED_ENCRYPTION 114 +# define PEM_R_UNSUPPORTED_KEY_COMPONENTS 126 + +# ifdef __cplusplus +} +# endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/pem2.h b/optee/optee_test/host/openssl/include/openssl/pem2.h new file mode 100644 index 0000000..84897d5 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/pem2.h @@ -0,0 +1,70 @@ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + * This header only exists to break a circular dependency between pem and err + * Ben 30 Jan 1999. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HEADER_PEM_H +void ERR_load_PEM_strings(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/pkcs12.h b/optee/optee_test/host/openssl/include/openssl/pkcs12.h new file mode 100644 index 0000000..21f1f62 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/pkcs12.h @@ -0,0 +1,342 @@ +/* pkcs12.h */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_PKCS12_H +# define HEADER_PKCS12_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define PKCS12_KEY_ID 1 +# define PKCS12_IV_ID 2 +# define PKCS12_MAC_ID 3 + +/* Default iteration count */ +# ifndef PKCS12_DEFAULT_ITER +# define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER +# endif + +# define PKCS12_MAC_KEY_LENGTH 20 + +# define PKCS12_SALT_LEN 8 + +/* Uncomment out next line for unicode password and names, otherwise ASCII */ + +/* + * #define PBE_UNICODE + */ + +# ifdef PBE_UNICODE +# define PKCS12_key_gen PKCS12_key_gen_uni +# define PKCS12_add_friendlyname PKCS12_add_friendlyname_uni +# else +# define PKCS12_key_gen PKCS12_key_gen_asc +# define PKCS12_add_friendlyname PKCS12_add_friendlyname_asc +# endif + +/* MS key usage constants */ + +# define KEY_EX 0x10 +# define KEY_SIG 0x80 + +typedef struct { + X509_SIG *dinfo; + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *iter; /* defaults to 1 */ +} PKCS12_MAC_DATA; + +typedef struct { + ASN1_INTEGER *version; + PKCS12_MAC_DATA *mac; + PKCS7 *authsafes; +} PKCS12; + +typedef struct { + ASN1_OBJECT *type; + union { + struct pkcs12_bag_st *bag; /* secret, crl and certbag */ + struct pkcs8_priv_key_info_st *keybag; /* keybag */ + X509_SIG *shkeybag; /* shrouded key bag */ + STACK_OF(PKCS12_SAFEBAG) *safes; + ASN1_TYPE *other; + } value; + STACK_OF(X509_ATTRIBUTE) *attrib; +} PKCS12_SAFEBAG; + +DECLARE_STACK_OF(PKCS12_SAFEBAG) +DECLARE_ASN1_SET_OF(PKCS12_SAFEBAG) +DECLARE_PKCS12_STACK_OF(PKCS12_SAFEBAG) + +typedef struct pkcs12_bag_st { + ASN1_OBJECT *type; + union { + ASN1_OCTET_STRING *x509cert; + ASN1_OCTET_STRING *x509crl; + ASN1_OCTET_STRING *octet; + ASN1_IA5STRING *sdsicert; + ASN1_TYPE *other; /* Secret or other bag */ + } value; +} PKCS12_BAGS; + +# define PKCS12_ERROR 0 +# define PKCS12_OK 1 + +/* Compatibility macros */ + +# define M_PKCS12_x5092certbag PKCS12_x5092certbag +# define M_PKCS12_x509crl2certbag PKCS12_x509crl2certbag + +# define M_PKCS12_certbag2x509 PKCS12_certbag2x509 +# define M_PKCS12_certbag2x509crl PKCS12_certbag2x509crl + +# define M_PKCS12_unpack_p7data PKCS12_unpack_p7data +# define M_PKCS12_pack_authsafes PKCS12_pack_authsafes +# define M_PKCS12_unpack_authsafes PKCS12_unpack_authsafes +# define M_PKCS12_unpack_p7encdata PKCS12_unpack_p7encdata + +# define M_PKCS12_decrypt_skey PKCS12_decrypt_skey +# define M_PKCS8_decrypt PKCS8_decrypt + +# define M_PKCS12_bag_type(bg) OBJ_obj2nid((bg)->type) +# define M_PKCS12_cert_bag_type(bg) OBJ_obj2nid((bg)->value.bag->type) +# define M_PKCS12_crl_bag_type M_PKCS12_cert_bag_type + +# define PKCS12_get_attr(bag, attr_nid) \ + PKCS12_get_attr_gen(bag->attrib, attr_nid) + +# define PKCS8_get_attr(p8, attr_nid) \ + PKCS12_get_attr_gen(p8->attributes, attr_nid) + +# define PKCS12_mac_present(p12) ((p12)->mac ? 1 : 0) + +PKCS12_SAFEBAG *PKCS12_x5092certbag(X509 *x509); +PKCS12_SAFEBAG *PKCS12_x509crl2certbag(X509_CRL *crl); +X509 *PKCS12_certbag2x509(PKCS12_SAFEBAG *bag); +X509_CRL *PKCS12_certbag2x509crl(PKCS12_SAFEBAG *bag); + +PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, + int nid1, int nid2); +PKCS12_SAFEBAG *PKCS12_MAKE_KEYBAG(PKCS8_PRIV_KEY_INFO *p8); +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *p8, const char *pass, + int passlen); +PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(PKCS12_SAFEBAG *bag, + const char *pass, int passlen); +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int passlen, unsigned char *salt, + int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8); +PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass, + int passlen, unsigned char *salt, + int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8); +PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7); +PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + STACK_OF(PKCS12_SAFEBAG) *bags); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, + int passlen); + +int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes); +STACK_OF(PKCS7) *PKCS12_unpack_authsafes(PKCS12 *p12); + +int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, + int namelen); +int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, + const unsigned char *name, int namelen); +int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage); +ASN1_TYPE *PKCS12_get_attr_gen(STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid); +char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag); +unsigned char *PKCS12_pbe_crypt(X509_ALGOR *algor, const char *pass, + int passlen, unsigned char *in, int inlen, + unsigned char **data, int *datalen, + int en_de); +void *PKCS12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it, + const char *pass, int passlen, + ASN1_OCTET_STRING *oct, int zbuf); +ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, + const ASN1_ITEM *it, + const char *pass, int passlen, + void *obj, int zbuf); +PKCS12 *PKCS12_init(int mode); +int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, + unsigned char *out, const EVP_MD *md_type); +int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, + const EVP_MD *md_type, int en_de); +int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen); +int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen); +int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + const EVP_MD *md_type); +int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, + int saltlen, const EVP_MD *md_type); +unsigned char *OPENSSL_asc2uni(const char *asc, int asclen, + unsigned char **uni, int *unilen); +char *OPENSSL_uni2asc(unsigned char *uni, int unilen); + +DECLARE_ASN1_FUNCTIONS(PKCS12) +DECLARE_ASN1_FUNCTIONS(PKCS12_MAC_DATA) +DECLARE_ASN1_FUNCTIONS(PKCS12_SAFEBAG) +DECLARE_ASN1_FUNCTIONS(PKCS12_BAGS) + +DECLARE_ASN1_ITEM(PKCS12_SAFEBAGS) +DECLARE_ASN1_ITEM(PKCS12_AUTHSAFES) + +void PKCS12_PBE_add(void); +int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, + STACK_OF(X509) **ca); +PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, + STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, + int mac_iter, int keytype); + +PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert); +PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, + EVP_PKEY *key, int key_usage, int iter, + int key_nid, char *pass); +int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, + int safe_nid, int iter, char *pass); +PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid); + +int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12); +int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); +PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12); +PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); +int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_PKCS12_strings(void); + +/* Error codes for the PKCS12 functions. */ + +/* Function codes. */ +# define PKCS12_F_PARSE_BAG 129 +# define PKCS12_F_PARSE_BAGS 103 +# define PKCS12_F_PKCS12_ADD_FRIENDLYNAME 100 +# define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC 127 +# define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI 102 +# define PKCS12_F_PKCS12_ADD_LOCALKEYID 104 +# define PKCS12_F_PKCS12_CREATE 105 +# define PKCS12_F_PKCS12_GEN_MAC 107 +# define PKCS12_F_PKCS12_INIT 109 +# define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I 106 +# define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT 108 +# define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG 117 +# define PKCS12_F_PKCS12_KEY_GEN_ASC 110 +# define PKCS12_F_PKCS12_KEY_GEN_UNI 111 +# define PKCS12_F_PKCS12_MAKE_KEYBAG 112 +# define PKCS12_F_PKCS12_MAKE_SHKEYBAG 113 +# define PKCS12_F_PKCS12_NEWPASS 128 +# define PKCS12_F_PKCS12_PACK_P7DATA 114 +# define PKCS12_F_PKCS12_PACK_P7ENCDATA 115 +# define PKCS12_F_PKCS12_PARSE 118 +# define PKCS12_F_PKCS12_PBE_CRYPT 119 +# define PKCS12_F_PKCS12_PBE_KEYIVGEN 120 +# define PKCS12_F_PKCS12_SETUP_MAC 122 +# define PKCS12_F_PKCS12_SET_MAC 123 +# define PKCS12_F_PKCS12_UNPACK_AUTHSAFES 130 +# define PKCS12_F_PKCS12_UNPACK_P7DATA 131 +# define PKCS12_F_PKCS12_VERIFY_MAC 126 +# define PKCS12_F_PKCS8_ADD_KEYUSAGE 124 +# define PKCS12_F_PKCS8_ENCRYPT 125 + +/* Reason codes. */ +# define PKCS12_R_CANT_PACK_STRUCTURE 100 +# define PKCS12_R_CONTENT_TYPE_NOT_DATA 121 +# define PKCS12_R_DECODE_ERROR 101 +# define PKCS12_R_ENCODE_ERROR 102 +# define PKCS12_R_ENCRYPT_ERROR 103 +# define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE 120 +# define PKCS12_R_INVALID_NULL_ARGUMENT 104 +# define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105 +# define PKCS12_R_IV_GEN_ERROR 106 +# define PKCS12_R_KEY_GEN_ERROR 107 +# define PKCS12_R_MAC_ABSENT 108 +# define PKCS12_R_MAC_GENERATION_ERROR 109 +# define PKCS12_R_MAC_SETUP_ERROR 110 +# define PKCS12_R_MAC_STRING_SET_ERROR 111 +# define PKCS12_R_MAC_VERIFY_ERROR 112 +# define PKCS12_R_MAC_VERIFY_FAILURE 113 +# define PKCS12_R_PARSE_ERROR 114 +# define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR 115 +# define PKCS12_R_PKCS12_CIPHERFINAL_ERROR 116 +# define PKCS12_R_PKCS12_PBE_CRYPT_ERROR 117 +# define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM 118 +# define PKCS12_R_UNSUPPORTED_PKCS12_MODE 119 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/pkcs7.h b/optee/optee_test/host/openssl/include/openssl/pkcs7.h new file mode 100644 index 0000000..b51b386 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/pkcs7.h @@ -0,0 +1,481 @@ +/* crypto/pkcs7/pkcs7.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_PKCS7_H +# define HEADER_PKCS7_H + +# include +# include +# include + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef OPENSSL_SYS_WIN32 +/* Under Win32 thes are defined in wincrypt.h */ +# undef PKCS7_ISSUER_AND_SERIAL +# undef PKCS7_SIGNER_INFO +# endif + +/*- +Encryption_ID DES-CBC +Digest_ID MD5 +Digest_Encryption_ID rsaEncryption +Key_Encryption_ID rsaEncryption +*/ + +typedef struct pkcs7_issuer_and_serial_st { + X509_NAME *issuer; + ASN1_INTEGER *serial; +} PKCS7_ISSUER_AND_SERIAL; + +typedef struct pkcs7_signer_info_st { + ASN1_INTEGER *version; /* version 1 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *digest_alg; + STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */ + X509_ALGOR *digest_enc_alg; + ASN1_OCTET_STRING *enc_digest; + STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */ + /* The private key to sign with */ + EVP_PKEY *pkey; +} PKCS7_SIGNER_INFO; + +DECLARE_STACK_OF(PKCS7_SIGNER_INFO) +DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO) + +typedef struct pkcs7_recip_info_st { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *key_enc_algor; + ASN1_OCTET_STRING *enc_key; + X509 *cert; /* get the pub-key from this */ +} PKCS7_RECIP_INFO; + +DECLARE_STACK_OF(PKCS7_RECIP_INFO) +DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO) + +typedef struct pkcs7_signed_st { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + struct pkcs7_st *contents; +} PKCS7_SIGNED; +/* + * The above structure is very very similar to PKCS7_SIGN_ENVELOPE. How about + * merging the two + */ + +typedef struct pkcs7_enc_content_st { + ASN1_OBJECT *content_type; + X509_ALGOR *algorithm; + ASN1_OCTET_STRING *enc_data; /* [ 0 ] */ + const EVP_CIPHER *cipher; +} PKCS7_ENC_CONTENT; + +typedef struct pkcs7_enveloped_st { + ASN1_INTEGER *version; /* version 0 */ + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; + PKCS7_ENC_CONTENT *enc_data; +} PKCS7_ENVELOPE; + +typedef struct pkcs7_signedandenveloped_st { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + PKCS7_ENC_CONTENT *enc_data; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; +} PKCS7_SIGN_ENVELOPE; + +typedef struct pkcs7_digest_st { + ASN1_INTEGER *version; /* version 0 */ + X509_ALGOR *md; /* md used */ + struct pkcs7_st *contents; + ASN1_OCTET_STRING *digest; +} PKCS7_DIGEST; + +typedef struct pkcs7_encrypted_st { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ENC_CONTENT *enc_data; +} PKCS7_ENCRYPT; + +typedef struct pkcs7_st { + /* + * The following is non NULL if it contains ASN1 encoding of this + * structure + */ + unsigned char *asn1; + long length; +# define PKCS7_S_HEADER 0 +# define PKCS7_S_BODY 1 +# define PKCS7_S_TAIL 2 + int state; /* used during processing */ + int detached; + ASN1_OBJECT *type; + /* content as defined by the type */ + /* + * all encryption/message digests are applied to the 'contents', leaving + * out the 'type' field. + */ + union { + char *ptr; + /* NID_pkcs7_data */ + ASN1_OCTET_STRING *data; + /* NID_pkcs7_signed */ + PKCS7_SIGNED *sign; + /* NID_pkcs7_enveloped */ + PKCS7_ENVELOPE *enveloped; + /* NID_pkcs7_signedAndEnveloped */ + PKCS7_SIGN_ENVELOPE *signed_and_enveloped; + /* NID_pkcs7_digest */ + PKCS7_DIGEST *digest; + /* NID_pkcs7_encrypted */ + PKCS7_ENCRYPT *encrypted; + /* Anything else */ + ASN1_TYPE *other; + } d; +} PKCS7; + +DECLARE_STACK_OF(PKCS7) +DECLARE_ASN1_SET_OF(PKCS7) +DECLARE_PKCS12_STACK_OF(PKCS7) + +# define PKCS7_OP_SET_DETACHED_SIGNATURE 1 +# define PKCS7_OP_GET_DETACHED_SIGNATURE 2 + +# define PKCS7_get_signed_attributes(si) ((si)->auth_attr) +# define PKCS7_get_attributes(si) ((si)->unauth_attr) + +# define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed) +# define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted) +# define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped) +# define PKCS7_type_is_signedAndEnveloped(a) \ + (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped) +# define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data) +# define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest) + +# define PKCS7_set_detached(p,v) \ + PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL) +# define PKCS7_get_detached(p) \ + PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL) + +# define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7)) + +/* S/MIME related flags */ + +# define PKCS7_TEXT 0x1 +# define PKCS7_NOCERTS 0x2 +# define PKCS7_NOSIGS 0x4 +# define PKCS7_NOCHAIN 0x8 +# define PKCS7_NOINTERN 0x10 +# define PKCS7_NOVERIFY 0x20 +# define PKCS7_DETACHED 0x40 +# define PKCS7_BINARY 0x80 +# define PKCS7_NOATTR 0x100 +# define PKCS7_NOSMIMECAP 0x200 +# define PKCS7_NOOLDMIMETYPE 0x400 +# define PKCS7_CRLFEOL 0x800 +# define PKCS7_STREAM 0x1000 +# define PKCS7_NOCRL 0x2000 +# define PKCS7_PARTIAL 0x4000 +# define PKCS7_REUSE_DIGEST 0x8000 + +/* Flags: for compatibility with older code */ + +# define SMIME_TEXT PKCS7_TEXT +# define SMIME_NOCERTS PKCS7_NOCERTS +# define SMIME_NOSIGS PKCS7_NOSIGS +# define SMIME_NOCHAIN PKCS7_NOCHAIN +# define SMIME_NOINTERN PKCS7_NOINTERN +# define SMIME_NOVERIFY PKCS7_NOVERIFY +# define SMIME_DETACHED PKCS7_DETACHED +# define SMIME_BINARY PKCS7_BINARY +# define SMIME_NOATTR PKCS7_NOATTR + +DECLARE_ASN1_FUNCTIONS(PKCS7_ISSUER_AND_SERIAL) + +int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, + const EVP_MD *type, unsigned char *md, + unsigned int *len); +# ifndef OPENSSL_NO_FP_API +PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7); +int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7); +# endif +PKCS7 *PKCS7_dup(PKCS7 *p7); +PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7); +int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7); +int i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags); +int PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags); + +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNER_INFO) +DECLARE_ASN1_FUNCTIONS(PKCS7_RECIP_INFO) +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGNED) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENC_CONTENT) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENVELOPE) +DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE) +DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST) +DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT) +DECLARE_ASN1_FUNCTIONS(PKCS7) + +DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN) +DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY) + +DECLARE_ASN1_NDEF_FUNCTION(PKCS7) +DECLARE_ASN1_PRINT_FUNCTION(PKCS7) + +long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg); + +int PKCS7_set_type(PKCS7 *p7, int type); +int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other); +int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); +int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, + const EVP_MD *dgst); +int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si); +int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i); +int PKCS7_add_certificate(PKCS7 *p7, X509 *x509); +int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509); +int PKCS7_content_new(PKCS7 *p7, int nid); +int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, + BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + X509 *x509); + +BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio); +int PKCS7_dataFinal(PKCS7 *p7, BIO *bio); +BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert); + +PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, + EVP_PKEY *pkey, const EVP_MD *dgst); +X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md); +STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7); + +PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509); +void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, + X509_ALGOR **pdig, X509_ALGOR **psig); +void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc); +int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri); +int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509); +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher); +int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7); + +PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx); +ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int type, + void *data); +int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value); +ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid); +ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid); +int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk); + +PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags); + +PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, + X509 *signcert, EVP_PKEY *pkey, + const EVP_MD *md, int flags); + +int PKCS7_final(PKCS7 *p7, BIO *data, int flags); +int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, + BIO *indata, BIO *out, int flags); +STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, + int flags); +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, + int flags); +int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, + int flags); + +int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, + STACK_OF(X509_ALGOR) *cap); +STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si); +int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg); + +int PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid); +int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t); +int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si, + const unsigned char *md, int mdlen); + +int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags); +PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont); + +BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_PKCS7_strings(void); + +/* Error codes for the PKCS7 functions. */ + +/* Function codes. */ +# define PKCS7_F_B64_READ_PKCS7 120 +# define PKCS7_F_B64_WRITE_PKCS7 121 +# define PKCS7_F_DO_PKCS7_SIGNED_ATTRIB 136 +# define PKCS7_F_I2D_PKCS7_BIO_STREAM 140 +# define PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME 135 +# define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 118 +# define PKCS7_F_PKCS7_ADD_CERTIFICATE 100 +# define PKCS7_F_PKCS7_ADD_CRL 101 +# define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102 +# define PKCS7_F_PKCS7_ADD_SIGNATURE 131 +# define PKCS7_F_PKCS7_ADD_SIGNER 103 +# define PKCS7_F_PKCS7_BIO_ADD_DIGEST 125 +# define PKCS7_F_PKCS7_COPY_EXISTING_DIGEST 138 +# define PKCS7_F_PKCS7_CTRL 104 +# define PKCS7_F_PKCS7_DATADECODE 112 +# define PKCS7_F_PKCS7_DATAFINAL 128 +# define PKCS7_F_PKCS7_DATAINIT 105 +# define PKCS7_F_PKCS7_DATASIGN 106 +# define PKCS7_F_PKCS7_DATAVERIFY 107 +# define PKCS7_F_PKCS7_DECRYPT 114 +# define PKCS7_F_PKCS7_DECRYPT_RINFO 133 +# define PKCS7_F_PKCS7_ENCODE_RINFO 132 +# define PKCS7_F_PKCS7_ENCRYPT 115 +# define PKCS7_F_PKCS7_FINAL 134 +# define PKCS7_F_PKCS7_FIND_DIGEST 127 +# define PKCS7_F_PKCS7_GET0_SIGNERS 124 +# define PKCS7_F_PKCS7_RECIP_INFO_SET 130 +# define PKCS7_F_PKCS7_SET_CIPHER 108 +# define PKCS7_F_PKCS7_SET_CONTENT 109 +# define PKCS7_F_PKCS7_SET_DIGEST 126 +# define PKCS7_F_PKCS7_SET_TYPE 110 +# define PKCS7_F_PKCS7_SIGN 116 +# define PKCS7_F_PKCS7_SIGNATUREVERIFY 113 +# define PKCS7_F_PKCS7_SIGNER_INFO_SET 129 +# define PKCS7_F_PKCS7_SIGNER_INFO_SIGN 139 +# define PKCS7_F_PKCS7_SIGN_ADD_SIGNER 137 +# define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119 +# define PKCS7_F_PKCS7_VERIFY 117 +# define PKCS7_F_SMIME_READ_PKCS7 122 +# define PKCS7_F_SMIME_TEXT 123 + +/* Reason codes. */ +# define PKCS7_R_CERTIFICATE_VERIFY_ERROR 117 +# define PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 144 +# define PKCS7_R_CIPHER_NOT_INITIALIZED 116 +# define PKCS7_R_CONTENT_AND_DATA_PRESENT 118 +# define PKCS7_R_CTRL_ERROR 152 +# define PKCS7_R_DECODE_ERROR 130 +# define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH 100 +# define PKCS7_R_DECRYPT_ERROR 119 +# define PKCS7_R_DIGEST_FAILURE 101 +# define PKCS7_R_ENCRYPTION_CTRL_FAILURE 149 +# define PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 150 +# define PKCS7_R_ERROR_ADDING_RECIPIENT 120 +# define PKCS7_R_ERROR_SETTING_CIPHER 121 +# define PKCS7_R_INVALID_MIME_TYPE 131 +# define PKCS7_R_INVALID_NULL_POINTER 143 +# define PKCS7_R_INVALID_SIGNED_DATA_TYPE 155 +# define PKCS7_R_MIME_NO_CONTENT_TYPE 132 +# define PKCS7_R_MIME_PARSE_ERROR 133 +# define PKCS7_R_MIME_SIG_PARSE_ERROR 134 +# define PKCS7_R_MISSING_CERIPEND_INFO 103 +# define PKCS7_R_NO_CONTENT 122 +# define PKCS7_R_NO_CONTENT_TYPE 135 +# define PKCS7_R_NO_DEFAULT_DIGEST 151 +# define PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND 154 +# define PKCS7_R_NO_MULTIPART_BODY_FAILURE 136 +# define PKCS7_R_NO_MULTIPART_BOUNDARY 137 +# define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115 +# define PKCS7_R_NO_RECIPIENT_MATCHES_KEY 146 +# define PKCS7_R_NO_SIGNATURES_ON_DATA 123 +# define PKCS7_R_NO_SIGNERS 142 +# define PKCS7_R_NO_SIG_CONTENT_TYPE 138 +# define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104 +# define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR 124 +# define PKCS7_R_PKCS7_ADD_SIGNER_ERROR 153 +# define PKCS7_R_PKCS7_DATAFINAL 126 +# define PKCS7_R_PKCS7_DATAFINAL_ERROR 125 +# define PKCS7_R_PKCS7_DATASIGN 145 +# define PKCS7_R_PKCS7_PARSE_ERROR 139 +# define PKCS7_R_PKCS7_SIG_PARSE_ERROR 140 +# define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 127 +# define PKCS7_R_SIGNATURE_FAILURE 105 +# define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND 128 +# define PKCS7_R_SIGNING_CTRL_FAILURE 147 +# define PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 148 +# define PKCS7_R_SIG_INVALID_MIME_TYPE 141 +# define PKCS7_R_SMIME_TEXT_ERROR 129 +# define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 106 +# define PKCS7_R_UNABLE_TO_FIND_MEM_BIO 107 +# define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST 108 +# define PKCS7_R_UNKNOWN_DIGEST_TYPE 109 +# define PKCS7_R_UNKNOWN_OPERATION 110 +# define PKCS7_R_UNSUPPORTED_CIPHER_TYPE 111 +# define PKCS7_R_UNSUPPORTED_CONTENT_TYPE 112 +# define PKCS7_R_WRONG_CONTENT_TYPE 113 +# define PKCS7_R_WRONG_PKCS7_TYPE 114 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/pqueue.h b/optee/optee_test/host/openssl/include/openssl/pqueue.h new file mode 100644 index 0000000..d40d9c7 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/pqueue.h @@ -0,0 +1,99 @@ +/* crypto/pqueue/pqueue.h */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_PQUEUE_H +# define HEADER_PQUEUE_H + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct _pqueue *pqueue; + +typedef struct _pitem { + unsigned char priority[8]; /* 64-bit value in big-endian encoding */ + void *data; + struct _pitem *next; +} pitem; + +typedef struct _pitem *piterator; + +pitem *pitem_new(unsigned char *prio64be, void *data); +void pitem_free(pitem *item); + +pqueue pqueue_new(void); +void pqueue_free(pqueue pq); + +pitem *pqueue_insert(pqueue pq, pitem *item); +pitem *pqueue_peek(pqueue pq); +pitem *pqueue_pop(pqueue pq); +pitem *pqueue_find(pqueue pq, unsigned char *prio64be); +pitem *pqueue_iterator(pqueue pq); +pitem *pqueue_next(piterator *iter); + +void pqueue_print(pqueue pq); +int pqueue_size(pqueue pq); + +#ifdef __cplusplus +} +#endif +#endif /* ! HEADER_PQUEUE_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/rand.h b/optee/optee_test/host/openssl/include/openssl/rand.h new file mode 100644 index 0000000..2553afd --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/rand.h @@ -0,0 +1,150 @@ +/* crypto/rand/rand.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RAND_H +# define HEADER_RAND_H + +# include +# include +# include + +# if defined(OPENSSL_SYS_WINDOWS) +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# if defined(OPENSSL_FIPS) +# define FIPS_RAND_SIZE_T size_t +# endif + +/* Already defined in ossl_typ.h */ +/* typedef struct rand_meth_st RAND_METHOD; */ + +struct rand_meth_st { + void (*seed) (const void *buf, int num); + int (*bytes) (unsigned char *buf, int num); + void (*cleanup) (void); + void (*add) (const void *buf, int num, double entropy); + int (*pseudorand) (unsigned char *buf, int num); + int (*status) (void); +}; + +# ifdef BN_DEBUG +extern int rand_predictable; +# endif + +int RAND_set_rand_method(const RAND_METHOD *meth); +const RAND_METHOD *RAND_get_rand_method(void); +# ifndef OPENSSL_NO_ENGINE +int RAND_set_rand_engine(ENGINE *engine); +# endif +RAND_METHOD *RAND_SSLeay(void); +void RAND_cleanup(void); +int RAND_bytes(unsigned char *buf, int num); +int RAND_pseudo_bytes(unsigned char *buf, int num); +void RAND_seed(const void *buf, int num); +void RAND_add(const void *buf, int num, double entropy); +int RAND_load_file(const char *file, long max_bytes); +int RAND_write_file(const char *file); +const char *RAND_file_name(char *file, size_t num); +int RAND_status(void); +int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes); +int RAND_egd(const char *path); +int RAND_egd_bytes(const char *path, int bytes); +int RAND_poll(void); + +# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) + +void RAND_screen(void); +int RAND_event(UINT, WPARAM, LPARAM); + +# endif + +# ifdef OPENSSL_FIPS +void RAND_set_fips_drbg_type(int type, int flags); +int RAND_init_fips(void); +# endif + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_RAND_strings(void); + +/* Error codes for the RAND functions. */ + +/* Function codes. */ +# define RAND_F_RAND_GET_RAND_METHOD 101 +# define RAND_F_RAND_INIT_FIPS 102 +# define RAND_F_SSLEAY_RAND_BYTES 100 + +/* Reason codes. */ +# define RAND_R_DUAL_EC_DRBG_DISABLED 104 +# define RAND_R_ERROR_INITIALISING_DRBG 102 +# define RAND_R_ERROR_INSTANTIATING_DRBG 103 +# define RAND_R_NO_FIPS_RANDOM_METHOD_SET 101 +# define RAND_R_PRNG_NOT_SEEDED 100 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/rc2.h b/optee/optee_test/host/openssl/include/openssl/rc2.h new file mode 100644 index 0000000..29d02d7 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/rc2.h @@ -0,0 +1,103 @@ +/* crypto/rc2/rc2.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RC2_H +# define HEADER_RC2_H + +# include /* OPENSSL_NO_RC2, RC2_INT */ +# ifdef OPENSSL_NO_RC2 +# error RC2 is disabled. +# endif + +# define RC2_ENCRYPT 1 +# define RC2_DECRYPT 0 + +# define RC2_BLOCK 8 +# define RC2_KEY_LENGTH 16 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rc2_key_st { + RC2_INT data[64]; +} RC2_KEY; + +# ifdef OPENSSL_FIPS +void private_RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, + int bits); +# endif +void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits); +void RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, + RC2_KEY *key, int enc); +void RC2_encrypt(unsigned long *data, RC2_KEY *key); +void RC2_decrypt(unsigned long *data, RC2_KEY *key); +void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + RC2_KEY *ks, unsigned char *iv, int enc); +void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num, int enc); +void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/rc4.h b/optee/optee_test/host/openssl/include/openssl/rc4.h new file mode 100644 index 0000000..39162b1 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/rc4.h @@ -0,0 +1,88 @@ +/* crypto/rc4/rc4.h */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RC4_H +# define HEADER_RC4_H + +# include /* OPENSSL_NO_RC4, RC4_INT */ +# ifdef OPENSSL_NO_RC4 +# error RC4 is disabled. +# endif + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rc4_key_st { + RC4_INT x, y; + RC4_INT data[256]; +} RC4_KEY; + +const char *RC4_options(void); +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void private_RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void RC4(RC4_KEY *key, size_t len, const unsigned char *indata, + unsigned char *outdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ripemd.h b/optee/optee_test/host/openssl/include/openssl/ripemd.h new file mode 100644 index 0000000..b88ef25 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ripemd.h @@ -0,0 +1,105 @@ +/* crypto/ripemd/ripemd.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RIPEMD_H +# define HEADER_RIPEMD_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef OPENSSL_NO_RIPEMD +# error RIPEMD is disabled. +# endif + +# if defined(__LP32__) +# define RIPEMD160_LONG unsigned long +# elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) +# define RIPEMD160_LONG unsigned long +# define RIPEMD160_LONG_LOG2 3 +# else +# define RIPEMD160_LONG unsigned int +# endif + +# define RIPEMD160_CBLOCK 64 +# define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4) +# define RIPEMD160_DIGEST_LENGTH 20 + +typedef struct RIPEMD160state_st { + RIPEMD160_LONG A, B, C, D, E; + RIPEMD160_LONG Nl, Nh; + RIPEMD160_LONG data[RIPEMD160_LBLOCK]; + unsigned int num; +} RIPEMD160_CTX; + +# ifdef OPENSSL_FIPS +int private_RIPEMD160_Init(RIPEMD160_CTX *c); +# endif +int RIPEMD160_Init(RIPEMD160_CTX *c); +int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len); +int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c); +unsigned char *RIPEMD160(const unsigned char *d, size_t n, unsigned char *md); +void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/rsa.h b/optee/optee_test/host/openssl/include/openssl/rsa.h new file mode 100644 index 0000000..d2ee374 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/rsa.h @@ -0,0 +1,664 @@ +/* crypto/rsa/rsa.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RSA_H +# define HEADER_RSA_H + +# include + +# ifndef OPENSSL_NO_BIO +# include +# endif +# include +# include +# ifndef OPENSSL_NO_DEPRECATED +# include +# endif + +# ifdef OPENSSL_NO_RSA +# error RSA is disabled. +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Declared already in ossl_typ.h */ +/* typedef struct rsa_st RSA; */ +/* typedef struct rsa_meth_st RSA_METHOD; */ + +struct rsa_meth_st { + const char *name; + int (*rsa_pub_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_pub_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_priv_enc) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + int (*rsa_priv_dec) (int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); + /* Can be null */ + int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx); + /* Can be null */ + int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); + /* called at new */ + int (*init) (RSA *rsa); + /* called at free */ + int (*finish) (RSA *rsa); + /* RSA_METHOD_FLAG_* things */ + int flags; + /* may be needed! */ + char *app_data; + /* + * New sign and verify functions: some libraries don't allow arbitrary + * data to be signed/verified: this allows them to be used. Note: for + * this to work the RSA_public_decrypt() and RSA_private_encrypt() should + * *NOT* be used RSA_sign(), RSA_verify() should be used instead. Note: + * for backwards compatibility this functionality is only enabled if the + * RSA_FLAG_SIGN_VER option is set in 'flags'. + */ + int (*rsa_sign) (int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa); + int (*rsa_verify) (int dtype, const unsigned char *m, + unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa); + /* + * If this callback is NULL, the builtin software RSA key-gen will be + * used. This is for behavioural compatibility whilst the code gets + * rewired, but one day it would be nice to assume there are no such + * things as "builtin software" implementations. + */ + int (*rsa_keygen) (RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); +}; + +struct rsa_st { + /* + * The first parameter is used to pickup errors where this is passed + * instead of aEVP_PKEY, it is set to 0 + */ + int pad; + long version; + const RSA_METHOD *meth; + /* functional reference if 'meth' is ENGINE-provided */ + ENGINE *engine; + BIGNUM *n; + BIGNUM *e; + BIGNUM *d; + BIGNUM *p; + BIGNUM *q; + BIGNUM *dmp1; + BIGNUM *dmq1; + BIGNUM *iqmp; + /* be careful using this if the RSA structure is shared */ + CRYPTO_EX_DATA ex_data; + int references; + int flags; + /* Used to cache montgomery values */ + BN_MONT_CTX *_method_mod_n; + BN_MONT_CTX *_method_mod_p; + BN_MONT_CTX *_method_mod_q; + /* + * all BIGNUM values are actually in the following data, if it is not + * NULL + */ + char *bignum_data; + BN_BLINDING *blinding; + BN_BLINDING *mt_blinding; +}; + +# ifndef OPENSSL_RSA_MAX_MODULUS_BITS +# define OPENSSL_RSA_MAX_MODULUS_BITS 16384 +# endif + +# ifndef OPENSSL_RSA_SMALL_MODULUS_BITS +# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072 +# endif +# ifndef OPENSSL_RSA_MAX_PUBEXP_BITS + +/* exponent limit enforced for "large" modulus only */ +# define OPENSSL_RSA_MAX_PUBEXP_BITS 64 +# endif + +# define RSA_3 0x3L +# define RSA_F4 0x10001L + +# define RSA_METHOD_FLAG_NO_CHECK 0x0001/* don't check pub/private + * match */ + +# define RSA_FLAG_CACHE_PUBLIC 0x0002 +# define RSA_FLAG_CACHE_PRIVATE 0x0004 +# define RSA_FLAG_BLINDING 0x0008 +# define RSA_FLAG_THREAD_SAFE 0x0010 +/* + * This flag means the private key operations will be handled by rsa_mod_exp + * and that they do not depend on the private key components being present: + * for example a key stored in external hardware. Without this flag + * bn_mod_exp gets called when private key components are absent. + */ +# define RSA_FLAG_EXT_PKEY 0x0020 + +/* + * This flag in the RSA_METHOD enables the new rsa_sign, rsa_verify + * functions. + */ +# define RSA_FLAG_SIGN_VER 0x0040 + +/* + * new with 0.9.6j and 0.9.7b; the built-in + * RSA implementation now uses blinding by + * default (ignoring RSA_FLAG_BLINDING), + * but other engines might not need it + */ +# define RSA_FLAG_NO_BLINDING 0x0080 +/* + * new with 0.9.8f; the built-in RSA + * implementation now uses constant time + * operations by default in private key operations, + * e.g., constant time modular exponentiation, + * modular inverse without leaking branches, + * division without leaking branches. This + * flag disables these constant time + * operations and results in faster RSA + * private key operations. + */ +# define RSA_FLAG_NO_CONSTTIME 0x0100 +# ifdef OPENSSL_USE_DEPRECATED +/* deprecated name for the flag*/ +/* + * new with 0.9.7h; the built-in RSA + * implementation now uses constant time + * modular exponentiation for secret exponents + * by default. This flag causes the + * faster variable sliding window method to + * be used for all exponents. + */ +# define RSA_FLAG_NO_EXP_CONSTTIME RSA_FLAG_NO_CONSTTIME +# endif + +# define EVP_PKEY_CTX_set_rsa_padding(ctx, pad) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, \ + pad, NULL) + +# define EVP_PKEY_CTX_get_rsa_padding(ctx, ppad) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, \ + EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad) + +# define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \ + (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, \ + len, NULL) + +# define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \ + (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ + EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, \ + 0, plen) + +# define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL) + +# define EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp) + +# define EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \ + EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md) + +# define EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)md) + +# define EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, \ + EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)pmd) + +# define EVP_PKEY_CTX_get_rsa_oaep_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)pmd) + +# define EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, l, llen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_OAEP_LABEL, llen, (void *)l) + +# define EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, l) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *)l) + +# define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1) +# define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 2) + +# define EVP_PKEY_CTRL_RSA_KEYGEN_BITS (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 5) + +# define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 7) +# define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 8) + +# define EVP_PKEY_CTRL_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 9) +# define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 10) + +# define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 11) +# define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12) + +# define RSA_PKCS1_PADDING 1 +# define RSA_SSLV23_PADDING 2 +# define RSA_NO_PADDING 3 +# define RSA_PKCS1_OAEP_PADDING 4 +# define RSA_X931_PADDING 5 +/* EVP_PKEY_ only */ +# define RSA_PKCS1_PSS_PADDING 6 + +# define RSA_PKCS1_PADDING_SIZE 11 + +# define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg) +# define RSA_get_app_data(s) RSA_get_ex_data(s,0) + +RSA *RSA_new(void); +RSA *RSA_new_method(ENGINE *engine); +int RSA_size(const RSA *rsa); + +/* Deprecated version */ +# ifndef OPENSSL_NO_DEPRECATED +RSA *RSA_generate_key(int bits, unsigned long e, void + (*callback) (int, int, void *), void *cb_arg); +# endif /* !defined(OPENSSL_NO_DEPRECATED) */ + +/* New version */ +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); + +int RSA_check_key(const RSA *); + /* next 4 return -1 on error */ +int RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +void RSA_free(RSA *r); +/* "up" the RSA object's reference count */ +int RSA_up_ref(RSA *r); + +int RSA_flags(const RSA *r); + +void RSA_set_default_method(const RSA_METHOD *meth); +const RSA_METHOD *RSA_get_default_method(void); +const RSA_METHOD *RSA_get_method(const RSA *rsa); +int RSA_set_method(RSA *rsa, const RSA_METHOD *meth); + +/* This function needs the memory locking malloc callbacks to be installed */ +int RSA_memory_lock(RSA *r); + +/* these are the actual SSLeay RSA functions */ +const RSA_METHOD *RSA_PKCS1_SSLeay(void); + +const RSA_METHOD *RSA_null_method(void); + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPublicKey) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(RSA, RSAPrivateKey) + +typedef struct rsa_pss_params_st { + X509_ALGOR *hashAlgorithm; + X509_ALGOR *maskGenAlgorithm; + ASN1_INTEGER *saltLength; + ASN1_INTEGER *trailerField; +} RSA_PSS_PARAMS; + +DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS) + +typedef struct rsa_oaep_params_st { + X509_ALGOR *hashFunc; + X509_ALGOR *maskGenFunc; + X509_ALGOR *pSourceFunc; +} RSA_OAEP_PARAMS; + +DECLARE_ASN1_FUNCTIONS(RSA_OAEP_PARAMS) + +# ifndef OPENSSL_NO_FP_API +int RSA_print_fp(FILE *fp, const RSA *r, int offset); +# endif + +# ifndef OPENSSL_NO_BIO +int RSA_print(BIO *bp, const RSA *r, int offset); +# endif + +# ifndef OPENSSL_NO_RC4 +int i2d_RSA_NET(const RSA *a, unsigned char **pp, + int (*cb) (char *buf, int len, const char *prompt, + int verify), int sgckey); +RSA *d2i_RSA_NET(RSA **a, const unsigned char **pp, long length, + int (*cb) (char *buf, int len, const char *prompt, + int verify), int sgckey); + +int i2d_Netscape_RSA(const RSA *a, unsigned char **pp, + int (*cb) (char *buf, int len, const char *prompt, + int verify)); +RSA *d2i_Netscape_RSA(RSA **a, const unsigned char **pp, long length, + int (*cb) (char *buf, int len, const char *prompt, + int verify)); +# endif + +/* + * The following 2 functions sign and verify a X509_SIG ASN1 object inside + * PKCS#1 padded RSA encryption + */ +int RSA_sign(int type, const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); +int RSA_verify(int type, const unsigned char *m, unsigned int m_length, + const unsigned char *sigbuf, unsigned int siglen, RSA *rsa); + +/* + * The following 2 function sign and verify a ASN1_OCTET_STRING object inside + * PKCS#1 padded RSA encryption + */ +int RSA_sign_ASN1_OCTET_STRING(int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + RSA *rsa); +int RSA_verify_ASN1_OCTET_STRING(int type, const unsigned char *m, + unsigned int m_length, unsigned char *sigbuf, + unsigned int siglen, RSA *rsa); + +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); +void RSA_blinding_off(RSA *rsa); +BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx); + +int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *f, int fl, + int rsa_len); +int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *f, int fl, + int rsa_len); +int PKCS1_MGF1(unsigned char *mask, long len, const unsigned char *seed, + long seedlen, const EVP_MD *dgst); +int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *f, int fl, + const unsigned char *p, int pl); +int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len, + const unsigned char *p, int pl); +int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + const unsigned char *param, int plen, + const EVP_MD *md, const EVP_MD *mgf1md); +int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, + int num, const unsigned char *param, + int plen, const EVP_MD *md, + const EVP_MD *mgf1md); +int RSA_padding_add_SSLv23(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_SSLv23(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_padding_add_none(unsigned char *to, int tlen, const unsigned char *f, + int fl); +int RSA_padding_check_none(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_padding_add_X931(unsigned char *to, int tlen, const unsigned char *f, + int fl); +int RSA_padding_check_X931(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_X931_hash_id(int nid); + +int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const unsigned char *EM, + int sLen); +int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, const EVP_MD *Hash, + int sLen); + +int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + const unsigned char *EM, int sLen); + +int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + int sLen); + +int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int RSA_set_ex_data(RSA *r, int idx, void *arg); +void *RSA_get_ex_data(const RSA *r, int idx); + +RSA *RSAPublicKey_dup(RSA *rsa); +RSA *RSAPrivateKey_dup(RSA *rsa); + +/* + * If this flag is set the RSA method is FIPS compliant and can be used in + * FIPS mode. This is set in the validated module method. If an application + * sets this flag in its own methods it is its responsibility to ensure the + * result is compliant. + */ + +# define RSA_FLAG_FIPS_METHOD 0x0400 + +/* + * If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +# define RSA_FLAG_NON_FIPS_ALLOW 0x0400 +/* + * Application has decided PRNG is good enough to generate a key: don't + * check. + */ +# define RSA_FLAG_CHECKED 0x0800 + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_RSA_strings(void); + +/* Error codes for the RSA functions. */ + +/* Function codes. */ +# define RSA_F_CHECK_PADDING_MD 140 +# define RSA_F_DO_RSA_PRINT 146 +# define RSA_F_INT_RSA_VERIFY 145 +# define RSA_F_MEMORY_LOCK 100 +# define RSA_F_OLD_RSA_PRIV_DECODE 147 +# define RSA_F_PKEY_RSA_CTRL 143 +# define RSA_F_PKEY_RSA_CTRL_STR 144 +# define RSA_F_PKEY_RSA_SIGN 142 +# define RSA_F_PKEY_RSA_VERIFY 154 +# define RSA_F_PKEY_RSA_VERIFYRECOVER 141 +# define RSA_F_RSA_ALGOR_TO_MD 157 +# define RSA_F_RSA_BUILTIN_KEYGEN 129 +# define RSA_F_RSA_CHECK_KEY 123 +# define RSA_F_RSA_CMS_DECRYPT 158 +# define RSA_F_RSA_EAY_PRIVATE_DECRYPT 101 +# define RSA_F_RSA_EAY_PRIVATE_ENCRYPT 102 +# define RSA_F_RSA_EAY_PUBLIC_DECRYPT 103 +# define RSA_F_RSA_EAY_PUBLIC_ENCRYPT 104 +# define RSA_F_RSA_GENERATE_KEY 105 +# define RSA_F_RSA_GENERATE_KEY_EX 155 +# define RSA_F_RSA_ITEM_VERIFY 156 +# define RSA_F_RSA_MEMORY_LOCK 130 +# define RSA_F_RSA_MGF1_TO_MD 159 +# define RSA_F_RSA_NEW_METHOD 106 +# define RSA_F_RSA_NULL 124 +# define RSA_F_RSA_NULL_MOD_EXP 131 +# define RSA_F_RSA_NULL_PRIVATE_DECRYPT 132 +# define RSA_F_RSA_NULL_PRIVATE_ENCRYPT 133 +# define RSA_F_RSA_NULL_PUBLIC_DECRYPT 134 +# define RSA_F_RSA_NULL_PUBLIC_ENCRYPT 135 +# define RSA_F_RSA_PADDING_ADD_NONE 107 +# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 121 +# define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1 160 +# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS 125 +# define RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1 148 +# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 108 +# define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 109 +# define RSA_F_RSA_PADDING_ADD_SSLV23 110 +# define RSA_F_RSA_PADDING_ADD_X931 127 +# define RSA_F_RSA_PADDING_CHECK_NONE 111 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 122 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1 161 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 112 +# define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 113 +# define RSA_F_RSA_PADDING_CHECK_SSLV23 114 +# define RSA_F_RSA_PADDING_CHECK_X931 128 +# define RSA_F_RSA_PRINT 115 +# define RSA_F_RSA_PRINT_FP 116 +# define RSA_F_RSA_PRIVATE_DECRYPT 150 +# define RSA_F_RSA_PRIVATE_ENCRYPT 151 +# define RSA_F_RSA_PRIV_DECODE 137 +# define RSA_F_RSA_PRIV_ENCODE 138 +# define RSA_F_RSA_PSS_TO_CTX 162 +# define RSA_F_RSA_PUBLIC_DECRYPT 152 +# define RSA_F_RSA_PUBLIC_ENCRYPT 153 +# define RSA_F_RSA_PUB_DECODE 139 +# define RSA_F_RSA_SETUP_BLINDING 136 +# define RSA_F_RSA_SIGN 117 +# define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118 +# define RSA_F_RSA_VERIFY 119 +# define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120 +# define RSA_F_RSA_VERIFY_PKCS1_PSS 126 +# define RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1 149 + +/* Reason codes. */ +# define RSA_R_ALGORITHM_MISMATCH 100 +# define RSA_R_BAD_E_VALUE 101 +# define RSA_R_BAD_FIXED_HEADER_DECRYPT 102 +# define RSA_R_BAD_PAD_BYTE_COUNT 103 +# define RSA_R_BAD_SIGNATURE 104 +# define RSA_R_BLOCK_TYPE_IS_NOT_01 106 +# define RSA_R_BLOCK_TYPE_IS_NOT_02 107 +# define RSA_R_DATA_GREATER_THAN_MOD_LEN 108 +# define RSA_R_DATA_TOO_LARGE 109 +# define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 110 +# define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 132 +# define RSA_R_DATA_TOO_SMALL 111 +# define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 122 +# define RSA_R_DIGEST_DOES_NOT_MATCH 166 +# define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 112 +# define RSA_R_DMP1_NOT_CONGRUENT_TO_D 124 +# define RSA_R_DMQ1_NOT_CONGRUENT_TO_D 125 +# define RSA_R_D_E_NOT_CONGRUENT_TO_1 123 +# define RSA_R_FIRST_OCTET_INVALID 133 +# define RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 144 +# define RSA_R_INVALID_DIGEST 160 +# define RSA_R_INVALID_DIGEST_LENGTH 143 +# define RSA_R_INVALID_HEADER 137 +# define RSA_R_INVALID_KEYBITS 145 +# define RSA_R_INVALID_LABEL 161 +# define RSA_R_INVALID_MESSAGE_LENGTH 131 +# define RSA_R_INVALID_MGF1_MD 156 +# define RSA_R_INVALID_OAEP_PARAMETERS 162 +# define RSA_R_INVALID_PADDING 138 +# define RSA_R_INVALID_PADDING_MODE 141 +# define RSA_R_INVALID_PSS_PARAMETERS 149 +# define RSA_R_INVALID_PSS_SALTLEN 146 +# define RSA_R_INVALID_SALT_LENGTH 150 +# define RSA_R_INVALID_TRAILER 139 +# define RSA_R_INVALID_X931_DIGEST 142 +# define RSA_R_IQMP_NOT_INVERSE_OF_Q 126 +# define RSA_R_KEY_SIZE_TOO_SMALL 120 +# define RSA_R_LAST_OCTET_INVALID 134 +# define RSA_R_MODULUS_TOO_LARGE 105 +# define RSA_R_NON_FIPS_RSA_METHOD 157 +# define RSA_R_NO_PUBLIC_EXPONENT 140 +# define RSA_R_NULL_BEFORE_BLOCK_MISSING 113 +# define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 +# define RSA_R_OAEP_DECODING_ERROR 121 +# define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 158 +# define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148 +# define RSA_R_PADDING_CHECK_FAILED 114 +# define RSA_R_PKCS_DECODING_ERROR 159 +# define RSA_R_P_NOT_PRIME 128 +# define RSA_R_Q_NOT_PRIME 129 +# define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130 +# define RSA_R_SLEN_CHECK_FAILED 136 +# define RSA_R_SLEN_RECOVERY_FAILED 135 +# define RSA_R_SSLV3_ROLLBACK_ATTACK 115 +# define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116 +# define RSA_R_UNKNOWN_ALGORITHM_TYPE 117 +# define RSA_R_UNKNOWN_DIGEST 163 +# define RSA_R_UNKNOWN_MASK_DIGEST 151 +# define RSA_R_UNKNOWN_PADDING_TYPE 118 +# define RSA_R_UNKNOWN_PSS_DIGEST 152 +# define RSA_R_UNSUPPORTED_ENCRYPTION_TYPE 164 +# define RSA_R_UNSUPPORTED_LABEL_SOURCE 165 +# define RSA_R_UNSUPPORTED_MASK_ALGORITHM 153 +# define RSA_R_UNSUPPORTED_MASK_PARAMETER 154 +# define RSA_R_UNSUPPORTED_SIGNATURE_TYPE 155 +# define RSA_R_VALUE_MISSING 147 +# define RSA_R_WRONG_SIGNATURE_LENGTH 119 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/safestack.h b/optee/optee_test/host/openssl/include/openssl/safestack.h new file mode 100644 index 0000000..1d4f87e --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/safestack.h @@ -0,0 +1,2672 @@ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_SAFESTACK_H +# define HEADER_SAFESTACK_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifndef CHECKED_PTR_OF +# define CHECKED_PTR_OF(type, p) \ + ((void*) (1 ? p : (type*)0)) +# endif + +/* + * In C++ we get problems because an explicit cast is needed from (void *) we + * use CHECKED_STACK_OF to ensure the correct type is passed in the macros + * below. + */ + +# define CHECKED_STACK_OF(type, p) \ + ((_STACK*) (1 ? p : (STACK_OF(type)*)0)) + +# define CHECKED_SK_COPY_FUNC(type, p) \ + ((void *(*)(void *)) ((1 ? p : (type *(*)(const type *))0))) + +# define CHECKED_SK_FREE_FUNC(type, p) \ + ((void (*)(void *)) ((1 ? p : (void (*)(type *))0))) + +# define CHECKED_SK_CMP_FUNC(type, p) \ + ((int (*)(const void *, const void *)) \ + ((1 ? p : (int (*)(const type * const *, const type * const *))0))) + +# define STACK_OF(type) struct stack_st_##type +# define PREDECLARE_STACK_OF(type) STACK_OF(type); + +# define DECLARE_STACK_OF(type) \ +STACK_OF(type) \ + { \ + _STACK stack; \ + }; +# define DECLARE_SPECIAL_STACK_OF(type, type2) \ +STACK_OF(type) \ + { \ + _STACK stack; \ + }; + +/* nada (obsolete in new safestack approach)*/ +# define IMPLEMENT_STACK_OF(type) + +/*- + * Strings are special: normally an lhash entry will point to a single + * (somewhat) mutable object. In the case of strings: + * + * a) Instead of a single char, there is an array of chars, NUL-terminated. + * b) The string may have be immutable. + * + * So, they need their own declarations. Especially important for + * type-checking tools, such as Deputy. + * + * In practice, however, it appears to be hard to have a const + * string. For now, I'm settling for dealing with the fact it is a + * string at all. + */ +typedef char *OPENSSL_STRING; + +typedef const char *OPENSSL_CSTRING; + +/* + * Confusingly, LHASH_OF(STRING) deals with char ** throughout, but + * STACK_OF(STRING) is really more like STACK_OF(char), only, as mentioned + * above, instead of a single char each entry is a NUL-terminated array of + * chars. So, we have to implement STRING specially for STACK_OF. This is + * dealt with in the autogenerated macros below. + */ + +DECLARE_SPECIAL_STACK_OF(OPENSSL_STRING, char) + +/* + * Similarly, we sometimes use a block of characters, NOT nul-terminated. + * These should also be distinguished from "normal" stacks. + */ +typedef void *OPENSSL_BLOCK; +DECLARE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void) + +/* + * SKM_sk_... stack macros are internal to safestack.h: never use them + * directly, use sk__... instead + */ +# define SKM_sk_new(type, cmp) \ + ((STACK_OF(type) *)sk_new(CHECKED_SK_CMP_FUNC(type, cmp))) +# define SKM_sk_new_null(type) \ + ((STACK_OF(type) *)sk_new_null()) +# define SKM_sk_free(type, st) \ + sk_free(CHECKED_STACK_OF(type, st)) +# define SKM_sk_num(type, st) \ + sk_num(CHECKED_STACK_OF(type, st)) +# define SKM_sk_value(type, st,i) \ + ((type *)sk_value(CHECKED_STACK_OF(type, st), i)) +# define SKM_sk_set(type, st,i,val) \ + sk_set(CHECKED_STACK_OF(type, st), i, CHECKED_PTR_OF(type, val)) +# define SKM_sk_zero(type, st) \ + sk_zero(CHECKED_STACK_OF(type, st)) +# define SKM_sk_push(type, st, val) \ + sk_push(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, val)) +# define SKM_sk_unshift(type, st, val) \ + sk_unshift(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, val)) +# define SKM_sk_find(type, st, val) \ + sk_find(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, val)) +# define SKM_sk_find_ex(type, st, val) \ + sk_find_ex(CHECKED_STACK_OF(type, st), \ + CHECKED_PTR_OF(type, val)) +# define SKM_sk_delete(type, st, i) \ + (type *)sk_delete(CHECKED_STACK_OF(type, st), i) +# define SKM_sk_delete_ptr(type, st, ptr) \ + (type *)sk_delete_ptr(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, ptr)) +# define SKM_sk_insert(type, st,val, i) \ + sk_insert(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, val), i) +# define SKM_sk_set_cmp_func(type, st, cmp) \ + ((int (*)(const type * const *,const type * const *)) \ + sk_set_cmp_func(CHECKED_STACK_OF(type, st), CHECKED_SK_CMP_FUNC(type, cmp))) +# define SKM_sk_dup(type, st) \ + (STACK_OF(type) *)sk_dup(CHECKED_STACK_OF(type, st)) +# define SKM_sk_pop_free(type, st, free_func) \ + sk_pop_free(CHECKED_STACK_OF(type, st), CHECKED_SK_FREE_FUNC(type, free_func)) +# define SKM_sk_deep_copy(type, st, copy_func, free_func) \ + (STACK_OF(type) *)sk_deep_copy(CHECKED_STACK_OF(type, st), CHECKED_SK_COPY_FUNC(type, copy_func), CHECKED_SK_FREE_FUNC(type, free_func)) +# define SKM_sk_shift(type, st) \ + (type *)sk_shift(CHECKED_STACK_OF(type, st)) +# define SKM_sk_pop(type, st) \ + (type *)sk_pop(CHECKED_STACK_OF(type, st)) +# define SKM_sk_sort(type, st) \ + sk_sort(CHECKED_STACK_OF(type, st)) +# define SKM_sk_is_sorted(type, st) \ + sk_is_sorted(CHECKED_STACK_OF(type, st)) +# define SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + (STACK_OF(type) *)d2i_ASN1_SET( \ + (STACK_OF(OPENSSL_BLOCK) **)CHECKED_PTR_OF(STACK_OF(type)*, st), \ + pp, length, \ + CHECKED_D2I_OF(type, d2i_func), \ + CHECKED_SK_FREE_FUNC(type, free_func), \ + ex_tag, ex_class) +# define SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \ + i2d_ASN1_SET((STACK_OF(OPENSSL_BLOCK) *)CHECKED_STACK_OF(type, st), pp, \ + CHECKED_I2D_OF(type, i2d_func), \ + ex_tag, ex_class, is_set) +# define SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \ + ASN1_seq_pack(CHECKED_PTR_OF(STACK_OF(type), st), \ + CHECKED_I2D_OF(type, i2d_func), buf, len) +# define SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \ + (STACK_OF(type) *)ASN1_seq_unpack(buf, len, CHECKED_D2I_OF(type, d2i_func), CHECKED_SK_FREE_FUNC(type, free_func)) +# define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \ + (STACK_OF(type) *)PKCS12_decrypt_d2i(algor, \ + CHECKED_D2I_OF(type, d2i_func), \ + CHECKED_SK_FREE_FUNC(type, free_func), \ + pass, passlen, oct, seq) +/* + * This block of defines is updated by util/mkstack.pl, please do not touch! + */ +# define sk_ACCESS_DESCRIPTION_new(cmp) SKM_sk_new(ACCESS_DESCRIPTION, (cmp)) +# define sk_ACCESS_DESCRIPTION_new_null() SKM_sk_new_null(ACCESS_DESCRIPTION) +# define sk_ACCESS_DESCRIPTION_free(st) SKM_sk_free(ACCESS_DESCRIPTION, (st)) +# define sk_ACCESS_DESCRIPTION_num(st) SKM_sk_num(ACCESS_DESCRIPTION, (st)) +# define sk_ACCESS_DESCRIPTION_value(st, i) SKM_sk_value(ACCESS_DESCRIPTION, (st), (i)) +# define sk_ACCESS_DESCRIPTION_set(st, i, val) SKM_sk_set(ACCESS_DESCRIPTION, (st), (i), (val)) +# define sk_ACCESS_DESCRIPTION_zero(st) SKM_sk_zero(ACCESS_DESCRIPTION, (st)) +# define sk_ACCESS_DESCRIPTION_push(st, val) SKM_sk_push(ACCESS_DESCRIPTION, (st), (val)) +# define sk_ACCESS_DESCRIPTION_unshift(st, val) SKM_sk_unshift(ACCESS_DESCRIPTION, (st), (val)) +# define sk_ACCESS_DESCRIPTION_find(st, val) SKM_sk_find(ACCESS_DESCRIPTION, (st), (val)) +# define sk_ACCESS_DESCRIPTION_find_ex(st, val) SKM_sk_find_ex(ACCESS_DESCRIPTION, (st), (val)) +# define sk_ACCESS_DESCRIPTION_delete(st, i) SKM_sk_delete(ACCESS_DESCRIPTION, (st), (i)) +# define sk_ACCESS_DESCRIPTION_delete_ptr(st, ptr) SKM_sk_delete_ptr(ACCESS_DESCRIPTION, (st), (ptr)) +# define sk_ACCESS_DESCRIPTION_insert(st, val, i) SKM_sk_insert(ACCESS_DESCRIPTION, (st), (val), (i)) +# define sk_ACCESS_DESCRIPTION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ACCESS_DESCRIPTION, (st), (cmp)) +# define sk_ACCESS_DESCRIPTION_dup(st) SKM_sk_dup(ACCESS_DESCRIPTION, st) +# define sk_ACCESS_DESCRIPTION_pop_free(st, free_func) SKM_sk_pop_free(ACCESS_DESCRIPTION, (st), (free_func)) +# define sk_ACCESS_DESCRIPTION_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ACCESS_DESCRIPTION, (st), (copy_func), (free_func)) +# define sk_ACCESS_DESCRIPTION_shift(st) SKM_sk_shift(ACCESS_DESCRIPTION, (st)) +# define sk_ACCESS_DESCRIPTION_pop(st) SKM_sk_pop(ACCESS_DESCRIPTION, (st)) +# define sk_ACCESS_DESCRIPTION_sort(st) SKM_sk_sort(ACCESS_DESCRIPTION, (st)) +# define sk_ACCESS_DESCRIPTION_is_sorted(st) SKM_sk_is_sorted(ACCESS_DESCRIPTION, (st)) +# define sk_ASIdOrRange_new(cmp) SKM_sk_new(ASIdOrRange, (cmp)) +# define sk_ASIdOrRange_new_null() SKM_sk_new_null(ASIdOrRange) +# define sk_ASIdOrRange_free(st) SKM_sk_free(ASIdOrRange, (st)) +# define sk_ASIdOrRange_num(st) SKM_sk_num(ASIdOrRange, (st)) +# define sk_ASIdOrRange_value(st, i) SKM_sk_value(ASIdOrRange, (st), (i)) +# define sk_ASIdOrRange_set(st, i, val) SKM_sk_set(ASIdOrRange, (st), (i), (val)) +# define sk_ASIdOrRange_zero(st) SKM_sk_zero(ASIdOrRange, (st)) +# define sk_ASIdOrRange_push(st, val) SKM_sk_push(ASIdOrRange, (st), (val)) +# define sk_ASIdOrRange_unshift(st, val) SKM_sk_unshift(ASIdOrRange, (st), (val)) +# define sk_ASIdOrRange_find(st, val) SKM_sk_find(ASIdOrRange, (st), (val)) +# define sk_ASIdOrRange_find_ex(st, val) SKM_sk_find_ex(ASIdOrRange, (st), (val)) +# define sk_ASIdOrRange_delete(st, i) SKM_sk_delete(ASIdOrRange, (st), (i)) +# define sk_ASIdOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASIdOrRange, (st), (ptr)) +# define sk_ASIdOrRange_insert(st, val, i) SKM_sk_insert(ASIdOrRange, (st), (val), (i)) +# define sk_ASIdOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASIdOrRange, (st), (cmp)) +# define sk_ASIdOrRange_dup(st) SKM_sk_dup(ASIdOrRange, st) +# define sk_ASIdOrRange_pop_free(st, free_func) SKM_sk_pop_free(ASIdOrRange, (st), (free_func)) +# define sk_ASIdOrRange_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASIdOrRange, (st), (copy_func), (free_func)) +# define sk_ASIdOrRange_shift(st) SKM_sk_shift(ASIdOrRange, (st)) +# define sk_ASIdOrRange_pop(st) SKM_sk_pop(ASIdOrRange, (st)) +# define sk_ASIdOrRange_sort(st) SKM_sk_sort(ASIdOrRange, (st)) +# define sk_ASIdOrRange_is_sorted(st) SKM_sk_is_sorted(ASIdOrRange, (st)) +# define sk_ASN1_GENERALSTRING_new(cmp) SKM_sk_new(ASN1_GENERALSTRING, (cmp)) +# define sk_ASN1_GENERALSTRING_new_null() SKM_sk_new_null(ASN1_GENERALSTRING) +# define sk_ASN1_GENERALSTRING_free(st) SKM_sk_free(ASN1_GENERALSTRING, (st)) +# define sk_ASN1_GENERALSTRING_num(st) SKM_sk_num(ASN1_GENERALSTRING, (st)) +# define sk_ASN1_GENERALSTRING_value(st, i) SKM_sk_value(ASN1_GENERALSTRING, (st), (i)) +# define sk_ASN1_GENERALSTRING_set(st, i, val) SKM_sk_set(ASN1_GENERALSTRING, (st), (i), (val)) +# define sk_ASN1_GENERALSTRING_zero(st) SKM_sk_zero(ASN1_GENERALSTRING, (st)) +# define sk_ASN1_GENERALSTRING_push(st, val) SKM_sk_push(ASN1_GENERALSTRING, (st), (val)) +# define sk_ASN1_GENERALSTRING_unshift(st, val) SKM_sk_unshift(ASN1_GENERALSTRING, (st), (val)) +# define sk_ASN1_GENERALSTRING_find(st, val) SKM_sk_find(ASN1_GENERALSTRING, (st), (val)) +# define sk_ASN1_GENERALSTRING_find_ex(st, val) SKM_sk_find_ex(ASN1_GENERALSTRING, (st), (val)) +# define sk_ASN1_GENERALSTRING_delete(st, i) SKM_sk_delete(ASN1_GENERALSTRING, (st), (i)) +# define sk_ASN1_GENERALSTRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_GENERALSTRING, (st), (ptr)) +# define sk_ASN1_GENERALSTRING_insert(st, val, i) SKM_sk_insert(ASN1_GENERALSTRING, (st), (val), (i)) +# define sk_ASN1_GENERALSTRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_GENERALSTRING, (st), (cmp)) +# define sk_ASN1_GENERALSTRING_dup(st) SKM_sk_dup(ASN1_GENERALSTRING, st) +# define sk_ASN1_GENERALSTRING_pop_free(st, free_func) SKM_sk_pop_free(ASN1_GENERALSTRING, (st), (free_func)) +# define sk_ASN1_GENERALSTRING_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASN1_GENERALSTRING, (st), (copy_func), (free_func)) +# define sk_ASN1_GENERALSTRING_shift(st) SKM_sk_shift(ASN1_GENERALSTRING, (st)) +# define sk_ASN1_GENERALSTRING_pop(st) SKM_sk_pop(ASN1_GENERALSTRING, (st)) +# define sk_ASN1_GENERALSTRING_sort(st) SKM_sk_sort(ASN1_GENERALSTRING, (st)) +# define sk_ASN1_GENERALSTRING_is_sorted(st) SKM_sk_is_sorted(ASN1_GENERALSTRING, (st)) +# define sk_ASN1_INTEGER_new(cmp) SKM_sk_new(ASN1_INTEGER, (cmp)) +# define sk_ASN1_INTEGER_new_null() SKM_sk_new_null(ASN1_INTEGER) +# define sk_ASN1_INTEGER_free(st) SKM_sk_free(ASN1_INTEGER, (st)) +# define sk_ASN1_INTEGER_num(st) SKM_sk_num(ASN1_INTEGER, (st)) +# define sk_ASN1_INTEGER_value(st, i) SKM_sk_value(ASN1_INTEGER, (st), (i)) +# define sk_ASN1_INTEGER_set(st, i, val) SKM_sk_set(ASN1_INTEGER, (st), (i), (val)) +# define sk_ASN1_INTEGER_zero(st) SKM_sk_zero(ASN1_INTEGER, (st)) +# define sk_ASN1_INTEGER_push(st, val) SKM_sk_push(ASN1_INTEGER, (st), (val)) +# define sk_ASN1_INTEGER_unshift(st, val) SKM_sk_unshift(ASN1_INTEGER, (st), (val)) +# define sk_ASN1_INTEGER_find(st, val) SKM_sk_find(ASN1_INTEGER, (st), (val)) +# define sk_ASN1_INTEGER_find_ex(st, val) SKM_sk_find_ex(ASN1_INTEGER, (st), (val)) +# define sk_ASN1_INTEGER_delete(st, i) SKM_sk_delete(ASN1_INTEGER, (st), (i)) +# define sk_ASN1_INTEGER_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_INTEGER, (st), (ptr)) +# define sk_ASN1_INTEGER_insert(st, val, i) SKM_sk_insert(ASN1_INTEGER, (st), (val), (i)) +# define sk_ASN1_INTEGER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_INTEGER, (st), (cmp)) +# define sk_ASN1_INTEGER_dup(st) SKM_sk_dup(ASN1_INTEGER, st) +# define sk_ASN1_INTEGER_pop_free(st, free_func) SKM_sk_pop_free(ASN1_INTEGER, (st), (free_func)) +# define sk_ASN1_INTEGER_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASN1_INTEGER, (st), (copy_func), (free_func)) +# define sk_ASN1_INTEGER_shift(st) SKM_sk_shift(ASN1_INTEGER, (st)) +# define sk_ASN1_INTEGER_pop(st) SKM_sk_pop(ASN1_INTEGER, (st)) +# define sk_ASN1_INTEGER_sort(st) SKM_sk_sort(ASN1_INTEGER, (st)) +# define sk_ASN1_INTEGER_is_sorted(st) SKM_sk_is_sorted(ASN1_INTEGER, (st)) +# define sk_ASN1_OBJECT_new(cmp) SKM_sk_new(ASN1_OBJECT, (cmp)) +# define sk_ASN1_OBJECT_new_null() SKM_sk_new_null(ASN1_OBJECT) +# define sk_ASN1_OBJECT_free(st) SKM_sk_free(ASN1_OBJECT, (st)) +# define sk_ASN1_OBJECT_num(st) SKM_sk_num(ASN1_OBJECT, (st)) +# define sk_ASN1_OBJECT_value(st, i) SKM_sk_value(ASN1_OBJECT, (st), (i)) +# define sk_ASN1_OBJECT_set(st, i, val) SKM_sk_set(ASN1_OBJECT, (st), (i), (val)) +# define sk_ASN1_OBJECT_zero(st) SKM_sk_zero(ASN1_OBJECT, (st)) +# define sk_ASN1_OBJECT_push(st, val) SKM_sk_push(ASN1_OBJECT, (st), (val)) +# define sk_ASN1_OBJECT_unshift(st, val) SKM_sk_unshift(ASN1_OBJECT, (st), (val)) +# define sk_ASN1_OBJECT_find(st, val) SKM_sk_find(ASN1_OBJECT, (st), (val)) +# define sk_ASN1_OBJECT_find_ex(st, val) SKM_sk_find_ex(ASN1_OBJECT, (st), (val)) +# define sk_ASN1_OBJECT_delete(st, i) SKM_sk_delete(ASN1_OBJECT, (st), (i)) +# define sk_ASN1_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_OBJECT, (st), (ptr)) +# define sk_ASN1_OBJECT_insert(st, val, i) SKM_sk_insert(ASN1_OBJECT, (st), (val), (i)) +# define sk_ASN1_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_OBJECT, (st), (cmp)) +# define sk_ASN1_OBJECT_dup(st) SKM_sk_dup(ASN1_OBJECT, st) +# define sk_ASN1_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(ASN1_OBJECT, (st), (free_func)) +# define sk_ASN1_OBJECT_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASN1_OBJECT, (st), (copy_func), (free_func)) +# define sk_ASN1_OBJECT_shift(st) SKM_sk_shift(ASN1_OBJECT, (st)) +# define sk_ASN1_OBJECT_pop(st) SKM_sk_pop(ASN1_OBJECT, (st)) +# define sk_ASN1_OBJECT_sort(st) SKM_sk_sort(ASN1_OBJECT, (st)) +# define sk_ASN1_OBJECT_is_sorted(st) SKM_sk_is_sorted(ASN1_OBJECT, (st)) +# define sk_ASN1_STRING_TABLE_new(cmp) SKM_sk_new(ASN1_STRING_TABLE, (cmp)) +# define sk_ASN1_STRING_TABLE_new_null() SKM_sk_new_null(ASN1_STRING_TABLE) +# define sk_ASN1_STRING_TABLE_free(st) SKM_sk_free(ASN1_STRING_TABLE, (st)) +# define sk_ASN1_STRING_TABLE_num(st) SKM_sk_num(ASN1_STRING_TABLE, (st)) +# define sk_ASN1_STRING_TABLE_value(st, i) SKM_sk_value(ASN1_STRING_TABLE, (st), (i)) +# define sk_ASN1_STRING_TABLE_set(st, i, val) SKM_sk_set(ASN1_STRING_TABLE, (st), (i), (val)) +# define sk_ASN1_STRING_TABLE_zero(st) SKM_sk_zero(ASN1_STRING_TABLE, (st)) +# define sk_ASN1_STRING_TABLE_push(st, val) SKM_sk_push(ASN1_STRING_TABLE, (st), (val)) +# define sk_ASN1_STRING_TABLE_unshift(st, val) SKM_sk_unshift(ASN1_STRING_TABLE, (st), (val)) +# define sk_ASN1_STRING_TABLE_find(st, val) SKM_sk_find(ASN1_STRING_TABLE, (st), (val)) +# define sk_ASN1_STRING_TABLE_find_ex(st, val) SKM_sk_find_ex(ASN1_STRING_TABLE, (st), (val)) +# define sk_ASN1_STRING_TABLE_delete(st, i) SKM_sk_delete(ASN1_STRING_TABLE, (st), (i)) +# define sk_ASN1_STRING_TABLE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_STRING_TABLE, (st), (ptr)) +# define sk_ASN1_STRING_TABLE_insert(st, val, i) SKM_sk_insert(ASN1_STRING_TABLE, (st), (val), (i)) +# define sk_ASN1_STRING_TABLE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_STRING_TABLE, (st), (cmp)) +# define sk_ASN1_STRING_TABLE_dup(st) SKM_sk_dup(ASN1_STRING_TABLE, st) +# define sk_ASN1_STRING_TABLE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_STRING_TABLE, (st), (free_func)) +# define sk_ASN1_STRING_TABLE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASN1_STRING_TABLE, (st), (copy_func), (free_func)) +# define sk_ASN1_STRING_TABLE_shift(st) SKM_sk_shift(ASN1_STRING_TABLE, (st)) +# define sk_ASN1_STRING_TABLE_pop(st) SKM_sk_pop(ASN1_STRING_TABLE, (st)) +# define sk_ASN1_STRING_TABLE_sort(st) SKM_sk_sort(ASN1_STRING_TABLE, (st)) +# define sk_ASN1_STRING_TABLE_is_sorted(st) SKM_sk_is_sorted(ASN1_STRING_TABLE, (st)) +# define sk_ASN1_TYPE_new(cmp) SKM_sk_new(ASN1_TYPE, (cmp)) +# define sk_ASN1_TYPE_new_null() SKM_sk_new_null(ASN1_TYPE) +# define sk_ASN1_TYPE_free(st) SKM_sk_free(ASN1_TYPE, (st)) +# define sk_ASN1_TYPE_num(st) SKM_sk_num(ASN1_TYPE, (st)) +# define sk_ASN1_TYPE_value(st, i) SKM_sk_value(ASN1_TYPE, (st), (i)) +# define sk_ASN1_TYPE_set(st, i, val) SKM_sk_set(ASN1_TYPE, (st), (i), (val)) +# define sk_ASN1_TYPE_zero(st) SKM_sk_zero(ASN1_TYPE, (st)) +# define sk_ASN1_TYPE_push(st, val) SKM_sk_push(ASN1_TYPE, (st), (val)) +# define sk_ASN1_TYPE_unshift(st, val) SKM_sk_unshift(ASN1_TYPE, (st), (val)) +# define sk_ASN1_TYPE_find(st, val) SKM_sk_find(ASN1_TYPE, (st), (val)) +# define sk_ASN1_TYPE_find_ex(st, val) SKM_sk_find_ex(ASN1_TYPE, (st), (val)) +# define sk_ASN1_TYPE_delete(st, i) SKM_sk_delete(ASN1_TYPE, (st), (i)) +# define sk_ASN1_TYPE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_TYPE, (st), (ptr)) +# define sk_ASN1_TYPE_insert(st, val, i) SKM_sk_insert(ASN1_TYPE, (st), (val), (i)) +# define sk_ASN1_TYPE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_TYPE, (st), (cmp)) +# define sk_ASN1_TYPE_dup(st) SKM_sk_dup(ASN1_TYPE, st) +# define sk_ASN1_TYPE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_TYPE, (st), (free_func)) +# define sk_ASN1_TYPE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASN1_TYPE, (st), (copy_func), (free_func)) +# define sk_ASN1_TYPE_shift(st) SKM_sk_shift(ASN1_TYPE, (st)) +# define sk_ASN1_TYPE_pop(st) SKM_sk_pop(ASN1_TYPE, (st)) +# define sk_ASN1_TYPE_sort(st) SKM_sk_sort(ASN1_TYPE, (st)) +# define sk_ASN1_TYPE_is_sorted(st) SKM_sk_is_sorted(ASN1_TYPE, (st)) +# define sk_ASN1_UTF8STRING_new(cmp) SKM_sk_new(ASN1_UTF8STRING, (cmp)) +# define sk_ASN1_UTF8STRING_new_null() SKM_sk_new_null(ASN1_UTF8STRING) +# define sk_ASN1_UTF8STRING_free(st) SKM_sk_free(ASN1_UTF8STRING, (st)) +# define sk_ASN1_UTF8STRING_num(st) SKM_sk_num(ASN1_UTF8STRING, (st)) +# define sk_ASN1_UTF8STRING_value(st, i) SKM_sk_value(ASN1_UTF8STRING, (st), (i)) +# define sk_ASN1_UTF8STRING_set(st, i, val) SKM_sk_set(ASN1_UTF8STRING, (st), (i), (val)) +# define sk_ASN1_UTF8STRING_zero(st) SKM_sk_zero(ASN1_UTF8STRING, (st)) +# define sk_ASN1_UTF8STRING_push(st, val) SKM_sk_push(ASN1_UTF8STRING, (st), (val)) +# define sk_ASN1_UTF8STRING_unshift(st, val) SKM_sk_unshift(ASN1_UTF8STRING, (st), (val)) +# define sk_ASN1_UTF8STRING_find(st, val) SKM_sk_find(ASN1_UTF8STRING, (st), (val)) +# define sk_ASN1_UTF8STRING_find_ex(st, val) SKM_sk_find_ex(ASN1_UTF8STRING, (st), (val)) +# define sk_ASN1_UTF8STRING_delete(st, i) SKM_sk_delete(ASN1_UTF8STRING, (st), (i)) +# define sk_ASN1_UTF8STRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_UTF8STRING, (st), (ptr)) +# define sk_ASN1_UTF8STRING_insert(st, val, i) SKM_sk_insert(ASN1_UTF8STRING, (st), (val), (i)) +# define sk_ASN1_UTF8STRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_UTF8STRING, (st), (cmp)) +# define sk_ASN1_UTF8STRING_dup(st) SKM_sk_dup(ASN1_UTF8STRING, st) +# define sk_ASN1_UTF8STRING_pop_free(st, free_func) SKM_sk_pop_free(ASN1_UTF8STRING, (st), (free_func)) +# define sk_ASN1_UTF8STRING_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASN1_UTF8STRING, (st), (copy_func), (free_func)) +# define sk_ASN1_UTF8STRING_shift(st) SKM_sk_shift(ASN1_UTF8STRING, (st)) +# define sk_ASN1_UTF8STRING_pop(st) SKM_sk_pop(ASN1_UTF8STRING, (st)) +# define sk_ASN1_UTF8STRING_sort(st) SKM_sk_sort(ASN1_UTF8STRING, (st)) +# define sk_ASN1_UTF8STRING_is_sorted(st) SKM_sk_is_sorted(ASN1_UTF8STRING, (st)) +# define sk_ASN1_VALUE_new(cmp) SKM_sk_new(ASN1_VALUE, (cmp)) +# define sk_ASN1_VALUE_new_null() SKM_sk_new_null(ASN1_VALUE) +# define sk_ASN1_VALUE_free(st) SKM_sk_free(ASN1_VALUE, (st)) +# define sk_ASN1_VALUE_num(st) SKM_sk_num(ASN1_VALUE, (st)) +# define sk_ASN1_VALUE_value(st, i) SKM_sk_value(ASN1_VALUE, (st), (i)) +# define sk_ASN1_VALUE_set(st, i, val) SKM_sk_set(ASN1_VALUE, (st), (i), (val)) +# define sk_ASN1_VALUE_zero(st) SKM_sk_zero(ASN1_VALUE, (st)) +# define sk_ASN1_VALUE_push(st, val) SKM_sk_push(ASN1_VALUE, (st), (val)) +# define sk_ASN1_VALUE_unshift(st, val) SKM_sk_unshift(ASN1_VALUE, (st), (val)) +# define sk_ASN1_VALUE_find(st, val) SKM_sk_find(ASN1_VALUE, (st), (val)) +# define sk_ASN1_VALUE_find_ex(st, val) SKM_sk_find_ex(ASN1_VALUE, (st), (val)) +# define sk_ASN1_VALUE_delete(st, i) SKM_sk_delete(ASN1_VALUE, (st), (i)) +# define sk_ASN1_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_VALUE, (st), (ptr)) +# define sk_ASN1_VALUE_insert(st, val, i) SKM_sk_insert(ASN1_VALUE, (st), (val), (i)) +# define sk_ASN1_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_VALUE, (st), (cmp)) +# define sk_ASN1_VALUE_dup(st) SKM_sk_dup(ASN1_VALUE, st) +# define sk_ASN1_VALUE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_VALUE, (st), (free_func)) +# define sk_ASN1_VALUE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASN1_VALUE, (st), (copy_func), (free_func)) +# define sk_ASN1_VALUE_shift(st) SKM_sk_shift(ASN1_VALUE, (st)) +# define sk_ASN1_VALUE_pop(st) SKM_sk_pop(ASN1_VALUE, (st)) +# define sk_ASN1_VALUE_sort(st) SKM_sk_sort(ASN1_VALUE, (st)) +# define sk_ASN1_VALUE_is_sorted(st) SKM_sk_is_sorted(ASN1_VALUE, (st)) +# define sk_BIO_new(cmp) SKM_sk_new(BIO, (cmp)) +# define sk_BIO_new_null() SKM_sk_new_null(BIO) +# define sk_BIO_free(st) SKM_sk_free(BIO, (st)) +# define sk_BIO_num(st) SKM_sk_num(BIO, (st)) +# define sk_BIO_value(st, i) SKM_sk_value(BIO, (st), (i)) +# define sk_BIO_set(st, i, val) SKM_sk_set(BIO, (st), (i), (val)) +# define sk_BIO_zero(st) SKM_sk_zero(BIO, (st)) +# define sk_BIO_push(st, val) SKM_sk_push(BIO, (st), (val)) +# define sk_BIO_unshift(st, val) SKM_sk_unshift(BIO, (st), (val)) +# define sk_BIO_find(st, val) SKM_sk_find(BIO, (st), (val)) +# define sk_BIO_find_ex(st, val) SKM_sk_find_ex(BIO, (st), (val)) +# define sk_BIO_delete(st, i) SKM_sk_delete(BIO, (st), (i)) +# define sk_BIO_delete_ptr(st, ptr) SKM_sk_delete_ptr(BIO, (st), (ptr)) +# define sk_BIO_insert(st, val, i) SKM_sk_insert(BIO, (st), (val), (i)) +# define sk_BIO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BIO, (st), (cmp)) +# define sk_BIO_dup(st) SKM_sk_dup(BIO, st) +# define sk_BIO_pop_free(st, free_func) SKM_sk_pop_free(BIO, (st), (free_func)) +# define sk_BIO_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(BIO, (st), (copy_func), (free_func)) +# define sk_BIO_shift(st) SKM_sk_shift(BIO, (st)) +# define sk_BIO_pop(st) SKM_sk_pop(BIO, (st)) +# define sk_BIO_sort(st) SKM_sk_sort(BIO, (st)) +# define sk_BIO_is_sorted(st) SKM_sk_is_sorted(BIO, (st)) +# define sk_BY_DIR_ENTRY_new(cmp) SKM_sk_new(BY_DIR_ENTRY, (cmp)) +# define sk_BY_DIR_ENTRY_new_null() SKM_sk_new_null(BY_DIR_ENTRY) +# define sk_BY_DIR_ENTRY_free(st) SKM_sk_free(BY_DIR_ENTRY, (st)) +# define sk_BY_DIR_ENTRY_num(st) SKM_sk_num(BY_DIR_ENTRY, (st)) +# define sk_BY_DIR_ENTRY_value(st, i) SKM_sk_value(BY_DIR_ENTRY, (st), (i)) +# define sk_BY_DIR_ENTRY_set(st, i, val) SKM_sk_set(BY_DIR_ENTRY, (st), (i), (val)) +# define sk_BY_DIR_ENTRY_zero(st) SKM_sk_zero(BY_DIR_ENTRY, (st)) +# define sk_BY_DIR_ENTRY_push(st, val) SKM_sk_push(BY_DIR_ENTRY, (st), (val)) +# define sk_BY_DIR_ENTRY_unshift(st, val) SKM_sk_unshift(BY_DIR_ENTRY, (st), (val)) +# define sk_BY_DIR_ENTRY_find(st, val) SKM_sk_find(BY_DIR_ENTRY, (st), (val)) +# define sk_BY_DIR_ENTRY_find_ex(st, val) SKM_sk_find_ex(BY_DIR_ENTRY, (st), (val)) +# define sk_BY_DIR_ENTRY_delete(st, i) SKM_sk_delete(BY_DIR_ENTRY, (st), (i)) +# define sk_BY_DIR_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(BY_DIR_ENTRY, (st), (ptr)) +# define sk_BY_DIR_ENTRY_insert(st, val, i) SKM_sk_insert(BY_DIR_ENTRY, (st), (val), (i)) +# define sk_BY_DIR_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BY_DIR_ENTRY, (st), (cmp)) +# define sk_BY_DIR_ENTRY_dup(st) SKM_sk_dup(BY_DIR_ENTRY, st) +# define sk_BY_DIR_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(BY_DIR_ENTRY, (st), (free_func)) +# define sk_BY_DIR_ENTRY_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(BY_DIR_ENTRY, (st), (copy_func), (free_func)) +# define sk_BY_DIR_ENTRY_shift(st) SKM_sk_shift(BY_DIR_ENTRY, (st)) +# define sk_BY_DIR_ENTRY_pop(st) SKM_sk_pop(BY_DIR_ENTRY, (st)) +# define sk_BY_DIR_ENTRY_sort(st) SKM_sk_sort(BY_DIR_ENTRY, (st)) +# define sk_BY_DIR_ENTRY_is_sorted(st) SKM_sk_is_sorted(BY_DIR_ENTRY, (st)) +# define sk_BY_DIR_HASH_new(cmp) SKM_sk_new(BY_DIR_HASH, (cmp)) +# define sk_BY_DIR_HASH_new_null() SKM_sk_new_null(BY_DIR_HASH) +# define sk_BY_DIR_HASH_free(st) SKM_sk_free(BY_DIR_HASH, (st)) +# define sk_BY_DIR_HASH_num(st) SKM_sk_num(BY_DIR_HASH, (st)) +# define sk_BY_DIR_HASH_value(st, i) SKM_sk_value(BY_DIR_HASH, (st), (i)) +# define sk_BY_DIR_HASH_set(st, i, val) SKM_sk_set(BY_DIR_HASH, (st), (i), (val)) +# define sk_BY_DIR_HASH_zero(st) SKM_sk_zero(BY_DIR_HASH, (st)) +# define sk_BY_DIR_HASH_push(st, val) SKM_sk_push(BY_DIR_HASH, (st), (val)) +# define sk_BY_DIR_HASH_unshift(st, val) SKM_sk_unshift(BY_DIR_HASH, (st), (val)) +# define sk_BY_DIR_HASH_find(st, val) SKM_sk_find(BY_DIR_HASH, (st), (val)) +# define sk_BY_DIR_HASH_find_ex(st, val) SKM_sk_find_ex(BY_DIR_HASH, (st), (val)) +# define sk_BY_DIR_HASH_delete(st, i) SKM_sk_delete(BY_DIR_HASH, (st), (i)) +# define sk_BY_DIR_HASH_delete_ptr(st, ptr) SKM_sk_delete_ptr(BY_DIR_HASH, (st), (ptr)) +# define sk_BY_DIR_HASH_insert(st, val, i) SKM_sk_insert(BY_DIR_HASH, (st), (val), (i)) +# define sk_BY_DIR_HASH_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BY_DIR_HASH, (st), (cmp)) +# define sk_BY_DIR_HASH_dup(st) SKM_sk_dup(BY_DIR_HASH, st) +# define sk_BY_DIR_HASH_pop_free(st, free_func) SKM_sk_pop_free(BY_DIR_HASH, (st), (free_func)) +# define sk_BY_DIR_HASH_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(BY_DIR_HASH, (st), (copy_func), (free_func)) +# define sk_BY_DIR_HASH_shift(st) SKM_sk_shift(BY_DIR_HASH, (st)) +# define sk_BY_DIR_HASH_pop(st) SKM_sk_pop(BY_DIR_HASH, (st)) +# define sk_BY_DIR_HASH_sort(st) SKM_sk_sort(BY_DIR_HASH, (st)) +# define sk_BY_DIR_HASH_is_sorted(st) SKM_sk_is_sorted(BY_DIR_HASH, (st)) +# define sk_CMS_CertificateChoices_new(cmp) SKM_sk_new(CMS_CertificateChoices, (cmp)) +# define sk_CMS_CertificateChoices_new_null() SKM_sk_new_null(CMS_CertificateChoices) +# define sk_CMS_CertificateChoices_free(st) SKM_sk_free(CMS_CertificateChoices, (st)) +# define sk_CMS_CertificateChoices_num(st) SKM_sk_num(CMS_CertificateChoices, (st)) +# define sk_CMS_CertificateChoices_value(st, i) SKM_sk_value(CMS_CertificateChoices, (st), (i)) +# define sk_CMS_CertificateChoices_set(st, i, val) SKM_sk_set(CMS_CertificateChoices, (st), (i), (val)) +# define sk_CMS_CertificateChoices_zero(st) SKM_sk_zero(CMS_CertificateChoices, (st)) +# define sk_CMS_CertificateChoices_push(st, val) SKM_sk_push(CMS_CertificateChoices, (st), (val)) +# define sk_CMS_CertificateChoices_unshift(st, val) SKM_sk_unshift(CMS_CertificateChoices, (st), (val)) +# define sk_CMS_CertificateChoices_find(st, val) SKM_sk_find(CMS_CertificateChoices, (st), (val)) +# define sk_CMS_CertificateChoices_find_ex(st, val) SKM_sk_find_ex(CMS_CertificateChoices, (st), (val)) +# define sk_CMS_CertificateChoices_delete(st, i) SKM_sk_delete(CMS_CertificateChoices, (st), (i)) +# define sk_CMS_CertificateChoices_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_CertificateChoices, (st), (ptr)) +# define sk_CMS_CertificateChoices_insert(st, val, i) SKM_sk_insert(CMS_CertificateChoices, (st), (val), (i)) +# define sk_CMS_CertificateChoices_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_CertificateChoices, (st), (cmp)) +# define sk_CMS_CertificateChoices_dup(st) SKM_sk_dup(CMS_CertificateChoices, st) +# define sk_CMS_CertificateChoices_pop_free(st, free_func) SKM_sk_pop_free(CMS_CertificateChoices, (st), (free_func)) +# define sk_CMS_CertificateChoices_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_CertificateChoices, (st), (copy_func), (free_func)) +# define sk_CMS_CertificateChoices_shift(st) SKM_sk_shift(CMS_CertificateChoices, (st)) +# define sk_CMS_CertificateChoices_pop(st) SKM_sk_pop(CMS_CertificateChoices, (st)) +# define sk_CMS_CertificateChoices_sort(st) SKM_sk_sort(CMS_CertificateChoices, (st)) +# define sk_CMS_CertificateChoices_is_sorted(st) SKM_sk_is_sorted(CMS_CertificateChoices, (st)) +# define sk_CMS_RecipientEncryptedKey_new(cmp) SKM_sk_new(CMS_RecipientEncryptedKey, (cmp)) +# define sk_CMS_RecipientEncryptedKey_new_null() SKM_sk_new_null(CMS_RecipientEncryptedKey) +# define sk_CMS_RecipientEncryptedKey_free(st) SKM_sk_free(CMS_RecipientEncryptedKey, (st)) +# define sk_CMS_RecipientEncryptedKey_num(st) SKM_sk_num(CMS_RecipientEncryptedKey, (st)) +# define sk_CMS_RecipientEncryptedKey_value(st, i) SKM_sk_value(CMS_RecipientEncryptedKey, (st), (i)) +# define sk_CMS_RecipientEncryptedKey_set(st, i, val) SKM_sk_set(CMS_RecipientEncryptedKey, (st), (i), (val)) +# define sk_CMS_RecipientEncryptedKey_zero(st) SKM_sk_zero(CMS_RecipientEncryptedKey, (st)) +# define sk_CMS_RecipientEncryptedKey_push(st, val) SKM_sk_push(CMS_RecipientEncryptedKey, (st), (val)) +# define sk_CMS_RecipientEncryptedKey_unshift(st, val) SKM_sk_unshift(CMS_RecipientEncryptedKey, (st), (val)) +# define sk_CMS_RecipientEncryptedKey_find(st, val) SKM_sk_find(CMS_RecipientEncryptedKey, (st), (val)) +# define sk_CMS_RecipientEncryptedKey_find_ex(st, val) SKM_sk_find_ex(CMS_RecipientEncryptedKey, (st), (val)) +# define sk_CMS_RecipientEncryptedKey_delete(st, i) SKM_sk_delete(CMS_RecipientEncryptedKey, (st), (i)) +# define sk_CMS_RecipientEncryptedKey_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RecipientEncryptedKey, (st), (ptr)) +# define sk_CMS_RecipientEncryptedKey_insert(st, val, i) SKM_sk_insert(CMS_RecipientEncryptedKey, (st), (val), (i)) +# define sk_CMS_RecipientEncryptedKey_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientEncryptedKey, (st), (cmp)) +# define sk_CMS_RecipientEncryptedKey_dup(st) SKM_sk_dup(CMS_RecipientEncryptedKey, st) +# define sk_CMS_RecipientEncryptedKey_pop_free(st, free_func) SKM_sk_pop_free(CMS_RecipientEncryptedKey, (st), (free_func)) +# define sk_CMS_RecipientEncryptedKey_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_RecipientEncryptedKey, (st), (copy_func), (free_func)) +# define sk_CMS_RecipientEncryptedKey_shift(st) SKM_sk_shift(CMS_RecipientEncryptedKey, (st)) +# define sk_CMS_RecipientEncryptedKey_pop(st) SKM_sk_pop(CMS_RecipientEncryptedKey, (st)) +# define sk_CMS_RecipientEncryptedKey_sort(st) SKM_sk_sort(CMS_RecipientEncryptedKey, (st)) +# define sk_CMS_RecipientEncryptedKey_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientEncryptedKey, (st)) +# define sk_CMS_RecipientInfo_new(cmp) SKM_sk_new(CMS_RecipientInfo, (cmp)) +# define sk_CMS_RecipientInfo_new_null() SKM_sk_new_null(CMS_RecipientInfo) +# define sk_CMS_RecipientInfo_free(st) SKM_sk_free(CMS_RecipientInfo, (st)) +# define sk_CMS_RecipientInfo_num(st) SKM_sk_num(CMS_RecipientInfo, (st)) +# define sk_CMS_RecipientInfo_value(st, i) SKM_sk_value(CMS_RecipientInfo, (st), (i)) +# define sk_CMS_RecipientInfo_set(st, i, val) SKM_sk_set(CMS_RecipientInfo, (st), (i), (val)) +# define sk_CMS_RecipientInfo_zero(st) SKM_sk_zero(CMS_RecipientInfo, (st)) +# define sk_CMS_RecipientInfo_push(st, val) SKM_sk_push(CMS_RecipientInfo, (st), (val)) +# define sk_CMS_RecipientInfo_unshift(st, val) SKM_sk_unshift(CMS_RecipientInfo, (st), (val)) +# define sk_CMS_RecipientInfo_find(st, val) SKM_sk_find(CMS_RecipientInfo, (st), (val)) +# define sk_CMS_RecipientInfo_find_ex(st, val) SKM_sk_find_ex(CMS_RecipientInfo, (st), (val)) +# define sk_CMS_RecipientInfo_delete(st, i) SKM_sk_delete(CMS_RecipientInfo, (st), (i)) +# define sk_CMS_RecipientInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RecipientInfo, (st), (ptr)) +# define sk_CMS_RecipientInfo_insert(st, val, i) SKM_sk_insert(CMS_RecipientInfo, (st), (val), (i)) +# define sk_CMS_RecipientInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientInfo, (st), (cmp)) +# define sk_CMS_RecipientInfo_dup(st) SKM_sk_dup(CMS_RecipientInfo, st) +# define sk_CMS_RecipientInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_RecipientInfo, (st), (free_func)) +# define sk_CMS_RecipientInfo_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_RecipientInfo, (st), (copy_func), (free_func)) +# define sk_CMS_RecipientInfo_shift(st) SKM_sk_shift(CMS_RecipientInfo, (st)) +# define sk_CMS_RecipientInfo_pop(st) SKM_sk_pop(CMS_RecipientInfo, (st)) +# define sk_CMS_RecipientInfo_sort(st) SKM_sk_sort(CMS_RecipientInfo, (st)) +# define sk_CMS_RecipientInfo_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientInfo, (st)) +# define sk_CMS_RevocationInfoChoice_new(cmp) SKM_sk_new(CMS_RevocationInfoChoice, (cmp)) +# define sk_CMS_RevocationInfoChoice_new_null() SKM_sk_new_null(CMS_RevocationInfoChoice) +# define sk_CMS_RevocationInfoChoice_free(st) SKM_sk_free(CMS_RevocationInfoChoice, (st)) +# define sk_CMS_RevocationInfoChoice_num(st) SKM_sk_num(CMS_RevocationInfoChoice, (st)) +# define sk_CMS_RevocationInfoChoice_value(st, i) SKM_sk_value(CMS_RevocationInfoChoice, (st), (i)) +# define sk_CMS_RevocationInfoChoice_set(st, i, val) SKM_sk_set(CMS_RevocationInfoChoice, (st), (i), (val)) +# define sk_CMS_RevocationInfoChoice_zero(st) SKM_sk_zero(CMS_RevocationInfoChoice, (st)) +# define sk_CMS_RevocationInfoChoice_push(st, val) SKM_sk_push(CMS_RevocationInfoChoice, (st), (val)) +# define sk_CMS_RevocationInfoChoice_unshift(st, val) SKM_sk_unshift(CMS_RevocationInfoChoice, (st), (val)) +# define sk_CMS_RevocationInfoChoice_find(st, val) SKM_sk_find(CMS_RevocationInfoChoice, (st), (val)) +# define sk_CMS_RevocationInfoChoice_find_ex(st, val) SKM_sk_find_ex(CMS_RevocationInfoChoice, (st), (val)) +# define sk_CMS_RevocationInfoChoice_delete(st, i) SKM_sk_delete(CMS_RevocationInfoChoice, (st), (i)) +# define sk_CMS_RevocationInfoChoice_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RevocationInfoChoice, (st), (ptr)) +# define sk_CMS_RevocationInfoChoice_insert(st, val, i) SKM_sk_insert(CMS_RevocationInfoChoice, (st), (val), (i)) +# define sk_CMS_RevocationInfoChoice_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RevocationInfoChoice, (st), (cmp)) +# define sk_CMS_RevocationInfoChoice_dup(st) SKM_sk_dup(CMS_RevocationInfoChoice, st) +# define sk_CMS_RevocationInfoChoice_pop_free(st, free_func) SKM_sk_pop_free(CMS_RevocationInfoChoice, (st), (free_func)) +# define sk_CMS_RevocationInfoChoice_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_RevocationInfoChoice, (st), (copy_func), (free_func)) +# define sk_CMS_RevocationInfoChoice_shift(st) SKM_sk_shift(CMS_RevocationInfoChoice, (st)) +# define sk_CMS_RevocationInfoChoice_pop(st) SKM_sk_pop(CMS_RevocationInfoChoice, (st)) +# define sk_CMS_RevocationInfoChoice_sort(st) SKM_sk_sort(CMS_RevocationInfoChoice, (st)) +# define sk_CMS_RevocationInfoChoice_is_sorted(st) SKM_sk_is_sorted(CMS_RevocationInfoChoice, (st)) +# define sk_CMS_SignerInfo_new(cmp) SKM_sk_new(CMS_SignerInfo, (cmp)) +# define sk_CMS_SignerInfo_new_null() SKM_sk_new_null(CMS_SignerInfo) +# define sk_CMS_SignerInfo_free(st) SKM_sk_free(CMS_SignerInfo, (st)) +# define sk_CMS_SignerInfo_num(st) SKM_sk_num(CMS_SignerInfo, (st)) +# define sk_CMS_SignerInfo_value(st, i) SKM_sk_value(CMS_SignerInfo, (st), (i)) +# define sk_CMS_SignerInfo_set(st, i, val) SKM_sk_set(CMS_SignerInfo, (st), (i), (val)) +# define sk_CMS_SignerInfo_zero(st) SKM_sk_zero(CMS_SignerInfo, (st)) +# define sk_CMS_SignerInfo_push(st, val) SKM_sk_push(CMS_SignerInfo, (st), (val)) +# define sk_CMS_SignerInfo_unshift(st, val) SKM_sk_unshift(CMS_SignerInfo, (st), (val)) +# define sk_CMS_SignerInfo_find(st, val) SKM_sk_find(CMS_SignerInfo, (st), (val)) +# define sk_CMS_SignerInfo_find_ex(st, val) SKM_sk_find_ex(CMS_SignerInfo, (st), (val)) +# define sk_CMS_SignerInfo_delete(st, i) SKM_sk_delete(CMS_SignerInfo, (st), (i)) +# define sk_CMS_SignerInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_SignerInfo, (st), (ptr)) +# define sk_CMS_SignerInfo_insert(st, val, i) SKM_sk_insert(CMS_SignerInfo, (st), (val), (i)) +# define sk_CMS_SignerInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_SignerInfo, (st), (cmp)) +# define sk_CMS_SignerInfo_dup(st) SKM_sk_dup(CMS_SignerInfo, st) +# define sk_CMS_SignerInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_SignerInfo, (st), (free_func)) +# define sk_CMS_SignerInfo_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CMS_SignerInfo, (st), (copy_func), (free_func)) +# define sk_CMS_SignerInfo_shift(st) SKM_sk_shift(CMS_SignerInfo, (st)) +# define sk_CMS_SignerInfo_pop(st) SKM_sk_pop(CMS_SignerInfo, (st)) +# define sk_CMS_SignerInfo_sort(st) SKM_sk_sort(CMS_SignerInfo, (st)) +# define sk_CMS_SignerInfo_is_sorted(st) SKM_sk_is_sorted(CMS_SignerInfo, (st)) +# define sk_CONF_IMODULE_new(cmp) SKM_sk_new(CONF_IMODULE, (cmp)) +# define sk_CONF_IMODULE_new_null() SKM_sk_new_null(CONF_IMODULE) +# define sk_CONF_IMODULE_free(st) SKM_sk_free(CONF_IMODULE, (st)) +# define sk_CONF_IMODULE_num(st) SKM_sk_num(CONF_IMODULE, (st)) +# define sk_CONF_IMODULE_value(st, i) SKM_sk_value(CONF_IMODULE, (st), (i)) +# define sk_CONF_IMODULE_set(st, i, val) SKM_sk_set(CONF_IMODULE, (st), (i), (val)) +# define sk_CONF_IMODULE_zero(st) SKM_sk_zero(CONF_IMODULE, (st)) +# define sk_CONF_IMODULE_push(st, val) SKM_sk_push(CONF_IMODULE, (st), (val)) +# define sk_CONF_IMODULE_unshift(st, val) SKM_sk_unshift(CONF_IMODULE, (st), (val)) +# define sk_CONF_IMODULE_find(st, val) SKM_sk_find(CONF_IMODULE, (st), (val)) +# define sk_CONF_IMODULE_find_ex(st, val) SKM_sk_find_ex(CONF_IMODULE, (st), (val)) +# define sk_CONF_IMODULE_delete(st, i) SKM_sk_delete(CONF_IMODULE, (st), (i)) +# define sk_CONF_IMODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_IMODULE, (st), (ptr)) +# define sk_CONF_IMODULE_insert(st, val, i) SKM_sk_insert(CONF_IMODULE, (st), (val), (i)) +# define sk_CONF_IMODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_IMODULE, (st), (cmp)) +# define sk_CONF_IMODULE_dup(st) SKM_sk_dup(CONF_IMODULE, st) +# define sk_CONF_IMODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_IMODULE, (st), (free_func)) +# define sk_CONF_IMODULE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CONF_IMODULE, (st), (copy_func), (free_func)) +# define sk_CONF_IMODULE_shift(st) SKM_sk_shift(CONF_IMODULE, (st)) +# define sk_CONF_IMODULE_pop(st) SKM_sk_pop(CONF_IMODULE, (st)) +# define sk_CONF_IMODULE_sort(st) SKM_sk_sort(CONF_IMODULE, (st)) +# define sk_CONF_IMODULE_is_sorted(st) SKM_sk_is_sorted(CONF_IMODULE, (st)) +# define sk_CONF_MODULE_new(cmp) SKM_sk_new(CONF_MODULE, (cmp)) +# define sk_CONF_MODULE_new_null() SKM_sk_new_null(CONF_MODULE) +# define sk_CONF_MODULE_free(st) SKM_sk_free(CONF_MODULE, (st)) +# define sk_CONF_MODULE_num(st) SKM_sk_num(CONF_MODULE, (st)) +# define sk_CONF_MODULE_value(st, i) SKM_sk_value(CONF_MODULE, (st), (i)) +# define sk_CONF_MODULE_set(st, i, val) SKM_sk_set(CONF_MODULE, (st), (i), (val)) +# define sk_CONF_MODULE_zero(st) SKM_sk_zero(CONF_MODULE, (st)) +# define sk_CONF_MODULE_push(st, val) SKM_sk_push(CONF_MODULE, (st), (val)) +# define sk_CONF_MODULE_unshift(st, val) SKM_sk_unshift(CONF_MODULE, (st), (val)) +# define sk_CONF_MODULE_find(st, val) SKM_sk_find(CONF_MODULE, (st), (val)) +# define sk_CONF_MODULE_find_ex(st, val) SKM_sk_find_ex(CONF_MODULE, (st), (val)) +# define sk_CONF_MODULE_delete(st, i) SKM_sk_delete(CONF_MODULE, (st), (i)) +# define sk_CONF_MODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_MODULE, (st), (ptr)) +# define sk_CONF_MODULE_insert(st, val, i) SKM_sk_insert(CONF_MODULE, (st), (val), (i)) +# define sk_CONF_MODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_MODULE, (st), (cmp)) +# define sk_CONF_MODULE_dup(st) SKM_sk_dup(CONF_MODULE, st) +# define sk_CONF_MODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_MODULE, (st), (free_func)) +# define sk_CONF_MODULE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CONF_MODULE, (st), (copy_func), (free_func)) +# define sk_CONF_MODULE_shift(st) SKM_sk_shift(CONF_MODULE, (st)) +# define sk_CONF_MODULE_pop(st) SKM_sk_pop(CONF_MODULE, (st)) +# define sk_CONF_MODULE_sort(st) SKM_sk_sort(CONF_MODULE, (st)) +# define sk_CONF_MODULE_is_sorted(st) SKM_sk_is_sorted(CONF_MODULE, (st)) +# define sk_CONF_VALUE_new(cmp) SKM_sk_new(CONF_VALUE, (cmp)) +# define sk_CONF_VALUE_new_null() SKM_sk_new_null(CONF_VALUE) +# define sk_CONF_VALUE_free(st) SKM_sk_free(CONF_VALUE, (st)) +# define sk_CONF_VALUE_num(st) SKM_sk_num(CONF_VALUE, (st)) +# define sk_CONF_VALUE_value(st, i) SKM_sk_value(CONF_VALUE, (st), (i)) +# define sk_CONF_VALUE_set(st, i, val) SKM_sk_set(CONF_VALUE, (st), (i), (val)) +# define sk_CONF_VALUE_zero(st) SKM_sk_zero(CONF_VALUE, (st)) +# define sk_CONF_VALUE_push(st, val) SKM_sk_push(CONF_VALUE, (st), (val)) +# define sk_CONF_VALUE_unshift(st, val) SKM_sk_unshift(CONF_VALUE, (st), (val)) +# define sk_CONF_VALUE_find(st, val) SKM_sk_find(CONF_VALUE, (st), (val)) +# define sk_CONF_VALUE_find_ex(st, val) SKM_sk_find_ex(CONF_VALUE, (st), (val)) +# define sk_CONF_VALUE_delete(st, i) SKM_sk_delete(CONF_VALUE, (st), (i)) +# define sk_CONF_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_VALUE, (st), (ptr)) +# define sk_CONF_VALUE_insert(st, val, i) SKM_sk_insert(CONF_VALUE, (st), (val), (i)) +# define sk_CONF_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_VALUE, (st), (cmp)) +# define sk_CONF_VALUE_dup(st) SKM_sk_dup(CONF_VALUE, st) +# define sk_CONF_VALUE_pop_free(st, free_func) SKM_sk_pop_free(CONF_VALUE, (st), (free_func)) +# define sk_CONF_VALUE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CONF_VALUE, (st), (copy_func), (free_func)) +# define sk_CONF_VALUE_shift(st) SKM_sk_shift(CONF_VALUE, (st)) +# define sk_CONF_VALUE_pop(st) SKM_sk_pop(CONF_VALUE, (st)) +# define sk_CONF_VALUE_sort(st) SKM_sk_sort(CONF_VALUE, (st)) +# define sk_CONF_VALUE_is_sorted(st) SKM_sk_is_sorted(CONF_VALUE, (st)) +# define sk_CRYPTO_EX_DATA_FUNCS_new(cmp) SKM_sk_new(CRYPTO_EX_DATA_FUNCS, (cmp)) +# define sk_CRYPTO_EX_DATA_FUNCS_new_null() SKM_sk_new_null(CRYPTO_EX_DATA_FUNCS) +# define sk_CRYPTO_EX_DATA_FUNCS_free(st) SKM_sk_free(CRYPTO_EX_DATA_FUNCS, (st)) +# define sk_CRYPTO_EX_DATA_FUNCS_num(st) SKM_sk_num(CRYPTO_EX_DATA_FUNCS, (st)) +# define sk_CRYPTO_EX_DATA_FUNCS_value(st, i) SKM_sk_value(CRYPTO_EX_DATA_FUNCS, (st), (i)) +# define sk_CRYPTO_EX_DATA_FUNCS_set(st, i, val) SKM_sk_set(CRYPTO_EX_DATA_FUNCS, (st), (i), (val)) +# define sk_CRYPTO_EX_DATA_FUNCS_zero(st) SKM_sk_zero(CRYPTO_EX_DATA_FUNCS, (st)) +# define sk_CRYPTO_EX_DATA_FUNCS_push(st, val) SKM_sk_push(CRYPTO_EX_DATA_FUNCS, (st), (val)) +# define sk_CRYPTO_EX_DATA_FUNCS_unshift(st, val) SKM_sk_unshift(CRYPTO_EX_DATA_FUNCS, (st), (val)) +# define sk_CRYPTO_EX_DATA_FUNCS_find(st, val) SKM_sk_find(CRYPTO_EX_DATA_FUNCS, (st), (val)) +# define sk_CRYPTO_EX_DATA_FUNCS_find_ex(st, val) SKM_sk_find_ex(CRYPTO_EX_DATA_FUNCS, (st), (val)) +# define sk_CRYPTO_EX_DATA_FUNCS_delete(st, i) SKM_sk_delete(CRYPTO_EX_DATA_FUNCS, (st), (i)) +# define sk_CRYPTO_EX_DATA_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_EX_DATA_FUNCS, (st), (ptr)) +# define sk_CRYPTO_EX_DATA_FUNCS_insert(st, val, i) SKM_sk_insert(CRYPTO_EX_DATA_FUNCS, (st), (val), (i)) +# define sk_CRYPTO_EX_DATA_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_EX_DATA_FUNCS, (st), (cmp)) +# define sk_CRYPTO_EX_DATA_FUNCS_dup(st) SKM_sk_dup(CRYPTO_EX_DATA_FUNCS, st) +# define sk_CRYPTO_EX_DATA_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_EX_DATA_FUNCS, (st), (free_func)) +# define sk_CRYPTO_EX_DATA_FUNCS_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CRYPTO_EX_DATA_FUNCS, (st), (copy_func), (free_func)) +# define sk_CRYPTO_EX_DATA_FUNCS_shift(st) SKM_sk_shift(CRYPTO_EX_DATA_FUNCS, (st)) +# define sk_CRYPTO_EX_DATA_FUNCS_pop(st) SKM_sk_pop(CRYPTO_EX_DATA_FUNCS, (st)) +# define sk_CRYPTO_EX_DATA_FUNCS_sort(st) SKM_sk_sort(CRYPTO_EX_DATA_FUNCS, (st)) +# define sk_CRYPTO_EX_DATA_FUNCS_is_sorted(st) SKM_sk_is_sorted(CRYPTO_EX_DATA_FUNCS, (st)) +# define sk_CRYPTO_dynlock_new(cmp) SKM_sk_new(CRYPTO_dynlock, (cmp)) +# define sk_CRYPTO_dynlock_new_null() SKM_sk_new_null(CRYPTO_dynlock) +# define sk_CRYPTO_dynlock_free(st) SKM_sk_free(CRYPTO_dynlock, (st)) +# define sk_CRYPTO_dynlock_num(st) SKM_sk_num(CRYPTO_dynlock, (st)) +# define sk_CRYPTO_dynlock_value(st, i) SKM_sk_value(CRYPTO_dynlock, (st), (i)) +# define sk_CRYPTO_dynlock_set(st, i, val) SKM_sk_set(CRYPTO_dynlock, (st), (i), (val)) +# define sk_CRYPTO_dynlock_zero(st) SKM_sk_zero(CRYPTO_dynlock, (st)) +# define sk_CRYPTO_dynlock_push(st, val) SKM_sk_push(CRYPTO_dynlock, (st), (val)) +# define sk_CRYPTO_dynlock_unshift(st, val) SKM_sk_unshift(CRYPTO_dynlock, (st), (val)) +# define sk_CRYPTO_dynlock_find(st, val) SKM_sk_find(CRYPTO_dynlock, (st), (val)) +# define sk_CRYPTO_dynlock_find_ex(st, val) SKM_sk_find_ex(CRYPTO_dynlock, (st), (val)) +# define sk_CRYPTO_dynlock_delete(st, i) SKM_sk_delete(CRYPTO_dynlock, (st), (i)) +# define sk_CRYPTO_dynlock_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_dynlock, (st), (ptr)) +# define sk_CRYPTO_dynlock_insert(st, val, i) SKM_sk_insert(CRYPTO_dynlock, (st), (val), (i)) +# define sk_CRYPTO_dynlock_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_dynlock, (st), (cmp)) +# define sk_CRYPTO_dynlock_dup(st) SKM_sk_dup(CRYPTO_dynlock, st) +# define sk_CRYPTO_dynlock_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_dynlock, (st), (free_func)) +# define sk_CRYPTO_dynlock_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(CRYPTO_dynlock, (st), (copy_func), (free_func)) +# define sk_CRYPTO_dynlock_shift(st) SKM_sk_shift(CRYPTO_dynlock, (st)) +# define sk_CRYPTO_dynlock_pop(st) SKM_sk_pop(CRYPTO_dynlock, (st)) +# define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st)) +# define sk_CRYPTO_dynlock_is_sorted(st) SKM_sk_is_sorted(CRYPTO_dynlock, (st)) +# define sk_DIST_POINT_new(cmp) SKM_sk_new(DIST_POINT, (cmp)) +# define sk_DIST_POINT_new_null() SKM_sk_new_null(DIST_POINT) +# define sk_DIST_POINT_free(st) SKM_sk_free(DIST_POINT, (st)) +# define sk_DIST_POINT_num(st) SKM_sk_num(DIST_POINT, (st)) +# define sk_DIST_POINT_value(st, i) SKM_sk_value(DIST_POINT, (st), (i)) +# define sk_DIST_POINT_set(st, i, val) SKM_sk_set(DIST_POINT, (st), (i), (val)) +# define sk_DIST_POINT_zero(st) SKM_sk_zero(DIST_POINT, (st)) +# define sk_DIST_POINT_push(st, val) SKM_sk_push(DIST_POINT, (st), (val)) +# define sk_DIST_POINT_unshift(st, val) SKM_sk_unshift(DIST_POINT, (st), (val)) +# define sk_DIST_POINT_find(st, val) SKM_sk_find(DIST_POINT, (st), (val)) +# define sk_DIST_POINT_find_ex(st, val) SKM_sk_find_ex(DIST_POINT, (st), (val)) +# define sk_DIST_POINT_delete(st, i) SKM_sk_delete(DIST_POINT, (st), (i)) +# define sk_DIST_POINT_delete_ptr(st, ptr) SKM_sk_delete_ptr(DIST_POINT, (st), (ptr)) +# define sk_DIST_POINT_insert(st, val, i) SKM_sk_insert(DIST_POINT, (st), (val), (i)) +# define sk_DIST_POINT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(DIST_POINT, (st), (cmp)) +# define sk_DIST_POINT_dup(st) SKM_sk_dup(DIST_POINT, st) +# define sk_DIST_POINT_pop_free(st, free_func) SKM_sk_pop_free(DIST_POINT, (st), (free_func)) +# define sk_DIST_POINT_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(DIST_POINT, (st), (copy_func), (free_func)) +# define sk_DIST_POINT_shift(st) SKM_sk_shift(DIST_POINT, (st)) +# define sk_DIST_POINT_pop(st) SKM_sk_pop(DIST_POINT, (st)) +# define sk_DIST_POINT_sort(st) SKM_sk_sort(DIST_POINT, (st)) +# define sk_DIST_POINT_is_sorted(st) SKM_sk_is_sorted(DIST_POINT, (st)) +# define sk_ENGINE_new(cmp) SKM_sk_new(ENGINE, (cmp)) +# define sk_ENGINE_new_null() SKM_sk_new_null(ENGINE) +# define sk_ENGINE_free(st) SKM_sk_free(ENGINE, (st)) +# define sk_ENGINE_num(st) SKM_sk_num(ENGINE, (st)) +# define sk_ENGINE_value(st, i) SKM_sk_value(ENGINE, (st), (i)) +# define sk_ENGINE_set(st, i, val) SKM_sk_set(ENGINE, (st), (i), (val)) +# define sk_ENGINE_zero(st) SKM_sk_zero(ENGINE, (st)) +# define sk_ENGINE_push(st, val) SKM_sk_push(ENGINE, (st), (val)) +# define sk_ENGINE_unshift(st, val) SKM_sk_unshift(ENGINE, (st), (val)) +# define sk_ENGINE_find(st, val) SKM_sk_find(ENGINE, (st), (val)) +# define sk_ENGINE_find_ex(st, val) SKM_sk_find_ex(ENGINE, (st), (val)) +# define sk_ENGINE_delete(st, i) SKM_sk_delete(ENGINE, (st), (i)) +# define sk_ENGINE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE, (st), (ptr)) +# define sk_ENGINE_insert(st, val, i) SKM_sk_insert(ENGINE, (st), (val), (i)) +# define sk_ENGINE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE, (st), (cmp)) +# define sk_ENGINE_dup(st) SKM_sk_dup(ENGINE, st) +# define sk_ENGINE_pop_free(st, free_func) SKM_sk_pop_free(ENGINE, (st), (free_func)) +# define sk_ENGINE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ENGINE, (st), (copy_func), (free_func)) +# define sk_ENGINE_shift(st) SKM_sk_shift(ENGINE, (st)) +# define sk_ENGINE_pop(st) SKM_sk_pop(ENGINE, (st)) +# define sk_ENGINE_sort(st) SKM_sk_sort(ENGINE, (st)) +# define sk_ENGINE_is_sorted(st) SKM_sk_is_sorted(ENGINE, (st)) +# define sk_ENGINE_CLEANUP_ITEM_new(cmp) SKM_sk_new(ENGINE_CLEANUP_ITEM, (cmp)) +# define sk_ENGINE_CLEANUP_ITEM_new_null() SKM_sk_new_null(ENGINE_CLEANUP_ITEM) +# define sk_ENGINE_CLEANUP_ITEM_free(st) SKM_sk_free(ENGINE_CLEANUP_ITEM, (st)) +# define sk_ENGINE_CLEANUP_ITEM_num(st) SKM_sk_num(ENGINE_CLEANUP_ITEM, (st)) +# define sk_ENGINE_CLEANUP_ITEM_value(st, i) SKM_sk_value(ENGINE_CLEANUP_ITEM, (st), (i)) +# define sk_ENGINE_CLEANUP_ITEM_set(st, i, val) SKM_sk_set(ENGINE_CLEANUP_ITEM, (st), (i), (val)) +# define sk_ENGINE_CLEANUP_ITEM_zero(st) SKM_sk_zero(ENGINE_CLEANUP_ITEM, (st)) +# define sk_ENGINE_CLEANUP_ITEM_push(st, val) SKM_sk_push(ENGINE_CLEANUP_ITEM, (st), (val)) +# define sk_ENGINE_CLEANUP_ITEM_unshift(st, val) SKM_sk_unshift(ENGINE_CLEANUP_ITEM, (st), (val)) +# define sk_ENGINE_CLEANUP_ITEM_find(st, val) SKM_sk_find(ENGINE_CLEANUP_ITEM, (st), (val)) +# define sk_ENGINE_CLEANUP_ITEM_find_ex(st, val) SKM_sk_find_ex(ENGINE_CLEANUP_ITEM, (st), (val)) +# define sk_ENGINE_CLEANUP_ITEM_delete(st, i) SKM_sk_delete(ENGINE_CLEANUP_ITEM, (st), (i)) +# define sk_ENGINE_CLEANUP_ITEM_delete_ptr(st, ptr) SKM_sk_delete_ptr(ENGINE_CLEANUP_ITEM, (st), (ptr)) +# define sk_ENGINE_CLEANUP_ITEM_insert(st, val, i) SKM_sk_insert(ENGINE_CLEANUP_ITEM, (st), (val), (i)) +# define sk_ENGINE_CLEANUP_ITEM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ENGINE_CLEANUP_ITEM, (st), (cmp)) +# define sk_ENGINE_CLEANUP_ITEM_dup(st) SKM_sk_dup(ENGINE_CLEANUP_ITEM, st) +# define sk_ENGINE_CLEANUP_ITEM_pop_free(st, free_func) SKM_sk_pop_free(ENGINE_CLEANUP_ITEM, (st), (free_func)) +# define sk_ENGINE_CLEANUP_ITEM_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ENGINE_CLEANUP_ITEM, (st), (copy_func), (free_func)) +# define sk_ENGINE_CLEANUP_ITEM_shift(st) SKM_sk_shift(ENGINE_CLEANUP_ITEM, (st)) +# define sk_ENGINE_CLEANUP_ITEM_pop(st) SKM_sk_pop(ENGINE_CLEANUP_ITEM, (st)) +# define sk_ENGINE_CLEANUP_ITEM_sort(st) SKM_sk_sort(ENGINE_CLEANUP_ITEM, (st)) +# define sk_ENGINE_CLEANUP_ITEM_is_sorted(st) SKM_sk_is_sorted(ENGINE_CLEANUP_ITEM, (st)) +# define sk_ESS_CERT_ID_new(cmp) SKM_sk_new(ESS_CERT_ID, (cmp)) +# define sk_ESS_CERT_ID_new_null() SKM_sk_new_null(ESS_CERT_ID) +# define sk_ESS_CERT_ID_free(st) SKM_sk_free(ESS_CERT_ID, (st)) +# define sk_ESS_CERT_ID_num(st) SKM_sk_num(ESS_CERT_ID, (st)) +# define sk_ESS_CERT_ID_value(st, i) SKM_sk_value(ESS_CERT_ID, (st), (i)) +# define sk_ESS_CERT_ID_set(st, i, val) SKM_sk_set(ESS_CERT_ID, (st), (i), (val)) +# define sk_ESS_CERT_ID_zero(st) SKM_sk_zero(ESS_CERT_ID, (st)) +# define sk_ESS_CERT_ID_push(st, val) SKM_sk_push(ESS_CERT_ID, (st), (val)) +# define sk_ESS_CERT_ID_unshift(st, val) SKM_sk_unshift(ESS_CERT_ID, (st), (val)) +# define sk_ESS_CERT_ID_find(st, val) SKM_sk_find(ESS_CERT_ID, (st), (val)) +# define sk_ESS_CERT_ID_find_ex(st, val) SKM_sk_find_ex(ESS_CERT_ID, (st), (val)) +# define sk_ESS_CERT_ID_delete(st, i) SKM_sk_delete(ESS_CERT_ID, (st), (i)) +# define sk_ESS_CERT_ID_delete_ptr(st, ptr) SKM_sk_delete_ptr(ESS_CERT_ID, (st), (ptr)) +# define sk_ESS_CERT_ID_insert(st, val, i) SKM_sk_insert(ESS_CERT_ID, (st), (val), (i)) +# define sk_ESS_CERT_ID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ESS_CERT_ID, (st), (cmp)) +# define sk_ESS_CERT_ID_dup(st) SKM_sk_dup(ESS_CERT_ID, st) +# define sk_ESS_CERT_ID_pop_free(st, free_func) SKM_sk_pop_free(ESS_CERT_ID, (st), (free_func)) +# define sk_ESS_CERT_ID_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ESS_CERT_ID, (st), (copy_func), (free_func)) +# define sk_ESS_CERT_ID_shift(st) SKM_sk_shift(ESS_CERT_ID, (st)) +# define sk_ESS_CERT_ID_pop(st) SKM_sk_pop(ESS_CERT_ID, (st)) +# define sk_ESS_CERT_ID_sort(st) SKM_sk_sort(ESS_CERT_ID, (st)) +# define sk_ESS_CERT_ID_is_sorted(st) SKM_sk_is_sorted(ESS_CERT_ID, (st)) +# define sk_EVP_MD_new(cmp) SKM_sk_new(EVP_MD, (cmp)) +# define sk_EVP_MD_new_null() SKM_sk_new_null(EVP_MD) +# define sk_EVP_MD_free(st) SKM_sk_free(EVP_MD, (st)) +# define sk_EVP_MD_num(st) SKM_sk_num(EVP_MD, (st)) +# define sk_EVP_MD_value(st, i) SKM_sk_value(EVP_MD, (st), (i)) +# define sk_EVP_MD_set(st, i, val) SKM_sk_set(EVP_MD, (st), (i), (val)) +# define sk_EVP_MD_zero(st) SKM_sk_zero(EVP_MD, (st)) +# define sk_EVP_MD_push(st, val) SKM_sk_push(EVP_MD, (st), (val)) +# define sk_EVP_MD_unshift(st, val) SKM_sk_unshift(EVP_MD, (st), (val)) +# define sk_EVP_MD_find(st, val) SKM_sk_find(EVP_MD, (st), (val)) +# define sk_EVP_MD_find_ex(st, val) SKM_sk_find_ex(EVP_MD, (st), (val)) +# define sk_EVP_MD_delete(st, i) SKM_sk_delete(EVP_MD, (st), (i)) +# define sk_EVP_MD_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_MD, (st), (ptr)) +# define sk_EVP_MD_insert(st, val, i) SKM_sk_insert(EVP_MD, (st), (val), (i)) +# define sk_EVP_MD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(EVP_MD, (st), (cmp)) +# define sk_EVP_MD_dup(st) SKM_sk_dup(EVP_MD, st) +# define sk_EVP_MD_pop_free(st, free_func) SKM_sk_pop_free(EVP_MD, (st), (free_func)) +# define sk_EVP_MD_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(EVP_MD, (st), (copy_func), (free_func)) +# define sk_EVP_MD_shift(st) SKM_sk_shift(EVP_MD, (st)) +# define sk_EVP_MD_pop(st) SKM_sk_pop(EVP_MD, (st)) +# define sk_EVP_MD_sort(st) SKM_sk_sort(EVP_MD, (st)) +# define sk_EVP_MD_is_sorted(st) SKM_sk_is_sorted(EVP_MD, (st)) +# define sk_EVP_PBE_CTL_new(cmp) SKM_sk_new(EVP_PBE_CTL, (cmp)) +# define sk_EVP_PBE_CTL_new_null() SKM_sk_new_null(EVP_PBE_CTL) +# define sk_EVP_PBE_CTL_free(st) SKM_sk_free(EVP_PBE_CTL, (st)) +# define sk_EVP_PBE_CTL_num(st) SKM_sk_num(EVP_PBE_CTL, (st)) +# define sk_EVP_PBE_CTL_value(st, i) SKM_sk_value(EVP_PBE_CTL, (st), (i)) +# define sk_EVP_PBE_CTL_set(st, i, val) SKM_sk_set(EVP_PBE_CTL, (st), (i), (val)) +# define sk_EVP_PBE_CTL_zero(st) SKM_sk_zero(EVP_PBE_CTL, (st)) +# define sk_EVP_PBE_CTL_push(st, val) SKM_sk_push(EVP_PBE_CTL, (st), (val)) +# define sk_EVP_PBE_CTL_unshift(st, val) SKM_sk_unshift(EVP_PBE_CTL, (st), (val)) +# define sk_EVP_PBE_CTL_find(st, val) SKM_sk_find(EVP_PBE_CTL, (st), (val)) +# define sk_EVP_PBE_CTL_find_ex(st, val) SKM_sk_find_ex(EVP_PBE_CTL, (st), (val)) +# define sk_EVP_PBE_CTL_delete(st, i) SKM_sk_delete(EVP_PBE_CTL, (st), (i)) +# define sk_EVP_PBE_CTL_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_PBE_CTL, (st), (ptr)) +# define sk_EVP_PBE_CTL_insert(st, val, i) SKM_sk_insert(EVP_PBE_CTL, (st), (val), (i)) +# define sk_EVP_PBE_CTL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(EVP_PBE_CTL, (st), (cmp)) +# define sk_EVP_PBE_CTL_dup(st) SKM_sk_dup(EVP_PBE_CTL, st) +# define sk_EVP_PBE_CTL_pop_free(st, free_func) SKM_sk_pop_free(EVP_PBE_CTL, (st), (free_func)) +# define sk_EVP_PBE_CTL_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(EVP_PBE_CTL, (st), (copy_func), (free_func)) +# define sk_EVP_PBE_CTL_shift(st) SKM_sk_shift(EVP_PBE_CTL, (st)) +# define sk_EVP_PBE_CTL_pop(st) SKM_sk_pop(EVP_PBE_CTL, (st)) +# define sk_EVP_PBE_CTL_sort(st) SKM_sk_sort(EVP_PBE_CTL, (st)) +# define sk_EVP_PBE_CTL_is_sorted(st) SKM_sk_is_sorted(EVP_PBE_CTL, (st)) +# define sk_EVP_PKEY_ASN1_METHOD_new(cmp) SKM_sk_new(EVP_PKEY_ASN1_METHOD, (cmp)) +# define sk_EVP_PKEY_ASN1_METHOD_new_null() SKM_sk_new_null(EVP_PKEY_ASN1_METHOD) +# define sk_EVP_PKEY_ASN1_METHOD_free(st) SKM_sk_free(EVP_PKEY_ASN1_METHOD, (st)) +# define sk_EVP_PKEY_ASN1_METHOD_num(st) SKM_sk_num(EVP_PKEY_ASN1_METHOD, (st)) +# define sk_EVP_PKEY_ASN1_METHOD_value(st, i) SKM_sk_value(EVP_PKEY_ASN1_METHOD, (st), (i)) +# define sk_EVP_PKEY_ASN1_METHOD_set(st, i, val) SKM_sk_set(EVP_PKEY_ASN1_METHOD, (st), (i), (val)) +# define sk_EVP_PKEY_ASN1_METHOD_zero(st) SKM_sk_zero(EVP_PKEY_ASN1_METHOD, (st)) +# define sk_EVP_PKEY_ASN1_METHOD_push(st, val) SKM_sk_push(EVP_PKEY_ASN1_METHOD, (st), (val)) +# define sk_EVP_PKEY_ASN1_METHOD_unshift(st, val) SKM_sk_unshift(EVP_PKEY_ASN1_METHOD, (st), (val)) +# define sk_EVP_PKEY_ASN1_METHOD_find(st, val) SKM_sk_find(EVP_PKEY_ASN1_METHOD, (st), (val)) +# define sk_EVP_PKEY_ASN1_METHOD_find_ex(st, val) SKM_sk_find_ex(EVP_PKEY_ASN1_METHOD, (st), (val)) +# define sk_EVP_PKEY_ASN1_METHOD_delete(st, i) SKM_sk_delete(EVP_PKEY_ASN1_METHOD, (st), (i)) +# define sk_EVP_PKEY_ASN1_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_PKEY_ASN1_METHOD, (st), (ptr)) +# define sk_EVP_PKEY_ASN1_METHOD_insert(st, val, i) SKM_sk_insert(EVP_PKEY_ASN1_METHOD, (st), (val), (i)) +# define sk_EVP_PKEY_ASN1_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(EVP_PKEY_ASN1_METHOD, (st), (cmp)) +# define sk_EVP_PKEY_ASN1_METHOD_dup(st) SKM_sk_dup(EVP_PKEY_ASN1_METHOD, st) +# define sk_EVP_PKEY_ASN1_METHOD_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY_ASN1_METHOD, (st), (free_func)) +# define sk_EVP_PKEY_ASN1_METHOD_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(EVP_PKEY_ASN1_METHOD, (st), (copy_func), (free_func)) +# define sk_EVP_PKEY_ASN1_METHOD_shift(st) SKM_sk_shift(EVP_PKEY_ASN1_METHOD, (st)) +# define sk_EVP_PKEY_ASN1_METHOD_pop(st) SKM_sk_pop(EVP_PKEY_ASN1_METHOD, (st)) +# define sk_EVP_PKEY_ASN1_METHOD_sort(st) SKM_sk_sort(EVP_PKEY_ASN1_METHOD, (st)) +# define sk_EVP_PKEY_ASN1_METHOD_is_sorted(st) SKM_sk_is_sorted(EVP_PKEY_ASN1_METHOD, (st)) +# define sk_EVP_PKEY_METHOD_new(cmp) SKM_sk_new(EVP_PKEY_METHOD, (cmp)) +# define sk_EVP_PKEY_METHOD_new_null() SKM_sk_new_null(EVP_PKEY_METHOD) +# define sk_EVP_PKEY_METHOD_free(st) SKM_sk_free(EVP_PKEY_METHOD, (st)) +# define sk_EVP_PKEY_METHOD_num(st) SKM_sk_num(EVP_PKEY_METHOD, (st)) +# define sk_EVP_PKEY_METHOD_value(st, i) SKM_sk_value(EVP_PKEY_METHOD, (st), (i)) +# define sk_EVP_PKEY_METHOD_set(st, i, val) SKM_sk_set(EVP_PKEY_METHOD, (st), (i), (val)) +# define sk_EVP_PKEY_METHOD_zero(st) SKM_sk_zero(EVP_PKEY_METHOD, (st)) +# define sk_EVP_PKEY_METHOD_push(st, val) SKM_sk_push(EVP_PKEY_METHOD, (st), (val)) +# define sk_EVP_PKEY_METHOD_unshift(st, val) SKM_sk_unshift(EVP_PKEY_METHOD, (st), (val)) +# define sk_EVP_PKEY_METHOD_find(st, val) SKM_sk_find(EVP_PKEY_METHOD, (st), (val)) +# define sk_EVP_PKEY_METHOD_find_ex(st, val) SKM_sk_find_ex(EVP_PKEY_METHOD, (st), (val)) +# define sk_EVP_PKEY_METHOD_delete(st, i) SKM_sk_delete(EVP_PKEY_METHOD, (st), (i)) +# define sk_EVP_PKEY_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_PKEY_METHOD, (st), (ptr)) +# define sk_EVP_PKEY_METHOD_insert(st, val, i) SKM_sk_insert(EVP_PKEY_METHOD, (st), (val), (i)) +# define sk_EVP_PKEY_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(EVP_PKEY_METHOD, (st), (cmp)) +# define sk_EVP_PKEY_METHOD_dup(st) SKM_sk_dup(EVP_PKEY_METHOD, st) +# define sk_EVP_PKEY_METHOD_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY_METHOD, (st), (free_func)) +# define sk_EVP_PKEY_METHOD_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(EVP_PKEY_METHOD, (st), (copy_func), (free_func)) +# define sk_EVP_PKEY_METHOD_shift(st) SKM_sk_shift(EVP_PKEY_METHOD, (st)) +# define sk_EVP_PKEY_METHOD_pop(st) SKM_sk_pop(EVP_PKEY_METHOD, (st)) +# define sk_EVP_PKEY_METHOD_sort(st) SKM_sk_sort(EVP_PKEY_METHOD, (st)) +# define sk_EVP_PKEY_METHOD_is_sorted(st) SKM_sk_is_sorted(EVP_PKEY_METHOD, (st)) +# define sk_GENERAL_NAME_new(cmp) SKM_sk_new(GENERAL_NAME, (cmp)) +# define sk_GENERAL_NAME_new_null() SKM_sk_new_null(GENERAL_NAME) +# define sk_GENERAL_NAME_free(st) SKM_sk_free(GENERAL_NAME, (st)) +# define sk_GENERAL_NAME_num(st) SKM_sk_num(GENERAL_NAME, (st)) +# define sk_GENERAL_NAME_value(st, i) SKM_sk_value(GENERAL_NAME, (st), (i)) +# define sk_GENERAL_NAME_set(st, i, val) SKM_sk_set(GENERAL_NAME, (st), (i), (val)) +# define sk_GENERAL_NAME_zero(st) SKM_sk_zero(GENERAL_NAME, (st)) +# define sk_GENERAL_NAME_push(st, val) SKM_sk_push(GENERAL_NAME, (st), (val)) +# define sk_GENERAL_NAME_unshift(st, val) SKM_sk_unshift(GENERAL_NAME, (st), (val)) +# define sk_GENERAL_NAME_find(st, val) SKM_sk_find(GENERAL_NAME, (st), (val)) +# define sk_GENERAL_NAME_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAME, (st), (val)) +# define sk_GENERAL_NAME_delete(st, i) SKM_sk_delete(GENERAL_NAME, (st), (i)) +# define sk_GENERAL_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAME, (st), (ptr)) +# define sk_GENERAL_NAME_insert(st, val, i) SKM_sk_insert(GENERAL_NAME, (st), (val), (i)) +# define sk_GENERAL_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAME, (st), (cmp)) +# define sk_GENERAL_NAME_dup(st) SKM_sk_dup(GENERAL_NAME, st) +# define sk_GENERAL_NAME_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAME, (st), (free_func)) +# define sk_GENERAL_NAME_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(GENERAL_NAME, (st), (copy_func), (free_func)) +# define sk_GENERAL_NAME_shift(st) SKM_sk_shift(GENERAL_NAME, (st)) +# define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME, (st)) +# define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st)) +# define sk_GENERAL_NAME_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAME, (st)) +# define sk_GENERAL_NAMES_new(cmp) SKM_sk_new(GENERAL_NAMES, (cmp)) +# define sk_GENERAL_NAMES_new_null() SKM_sk_new_null(GENERAL_NAMES) +# define sk_GENERAL_NAMES_free(st) SKM_sk_free(GENERAL_NAMES, (st)) +# define sk_GENERAL_NAMES_num(st) SKM_sk_num(GENERAL_NAMES, (st)) +# define sk_GENERAL_NAMES_value(st, i) SKM_sk_value(GENERAL_NAMES, (st), (i)) +# define sk_GENERAL_NAMES_set(st, i, val) SKM_sk_set(GENERAL_NAMES, (st), (i), (val)) +# define sk_GENERAL_NAMES_zero(st) SKM_sk_zero(GENERAL_NAMES, (st)) +# define sk_GENERAL_NAMES_push(st, val) SKM_sk_push(GENERAL_NAMES, (st), (val)) +# define sk_GENERAL_NAMES_unshift(st, val) SKM_sk_unshift(GENERAL_NAMES, (st), (val)) +# define sk_GENERAL_NAMES_find(st, val) SKM_sk_find(GENERAL_NAMES, (st), (val)) +# define sk_GENERAL_NAMES_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAMES, (st), (val)) +# define sk_GENERAL_NAMES_delete(st, i) SKM_sk_delete(GENERAL_NAMES, (st), (i)) +# define sk_GENERAL_NAMES_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAMES, (st), (ptr)) +# define sk_GENERAL_NAMES_insert(st, val, i) SKM_sk_insert(GENERAL_NAMES, (st), (val), (i)) +# define sk_GENERAL_NAMES_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAMES, (st), (cmp)) +# define sk_GENERAL_NAMES_dup(st) SKM_sk_dup(GENERAL_NAMES, st) +# define sk_GENERAL_NAMES_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAMES, (st), (free_func)) +# define sk_GENERAL_NAMES_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(GENERAL_NAMES, (st), (copy_func), (free_func)) +# define sk_GENERAL_NAMES_shift(st) SKM_sk_shift(GENERAL_NAMES, (st)) +# define sk_GENERAL_NAMES_pop(st) SKM_sk_pop(GENERAL_NAMES, (st)) +# define sk_GENERAL_NAMES_sort(st) SKM_sk_sort(GENERAL_NAMES, (st)) +# define sk_GENERAL_NAMES_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAMES, (st)) +# define sk_GENERAL_SUBTREE_new(cmp) SKM_sk_new(GENERAL_SUBTREE, (cmp)) +# define sk_GENERAL_SUBTREE_new_null() SKM_sk_new_null(GENERAL_SUBTREE) +# define sk_GENERAL_SUBTREE_free(st) SKM_sk_free(GENERAL_SUBTREE, (st)) +# define sk_GENERAL_SUBTREE_num(st) SKM_sk_num(GENERAL_SUBTREE, (st)) +# define sk_GENERAL_SUBTREE_value(st, i) SKM_sk_value(GENERAL_SUBTREE, (st), (i)) +# define sk_GENERAL_SUBTREE_set(st, i, val) SKM_sk_set(GENERAL_SUBTREE, (st), (i), (val)) +# define sk_GENERAL_SUBTREE_zero(st) SKM_sk_zero(GENERAL_SUBTREE, (st)) +# define sk_GENERAL_SUBTREE_push(st, val) SKM_sk_push(GENERAL_SUBTREE, (st), (val)) +# define sk_GENERAL_SUBTREE_unshift(st, val) SKM_sk_unshift(GENERAL_SUBTREE, (st), (val)) +# define sk_GENERAL_SUBTREE_find(st, val) SKM_sk_find(GENERAL_SUBTREE, (st), (val)) +# define sk_GENERAL_SUBTREE_find_ex(st, val) SKM_sk_find_ex(GENERAL_SUBTREE, (st), (val)) +# define sk_GENERAL_SUBTREE_delete(st, i) SKM_sk_delete(GENERAL_SUBTREE, (st), (i)) +# define sk_GENERAL_SUBTREE_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_SUBTREE, (st), (ptr)) +# define sk_GENERAL_SUBTREE_insert(st, val, i) SKM_sk_insert(GENERAL_SUBTREE, (st), (val), (i)) +# define sk_GENERAL_SUBTREE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_SUBTREE, (st), (cmp)) +# define sk_GENERAL_SUBTREE_dup(st) SKM_sk_dup(GENERAL_SUBTREE, st) +# define sk_GENERAL_SUBTREE_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_SUBTREE, (st), (free_func)) +# define sk_GENERAL_SUBTREE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(GENERAL_SUBTREE, (st), (copy_func), (free_func)) +# define sk_GENERAL_SUBTREE_shift(st) SKM_sk_shift(GENERAL_SUBTREE, (st)) +# define sk_GENERAL_SUBTREE_pop(st) SKM_sk_pop(GENERAL_SUBTREE, (st)) +# define sk_GENERAL_SUBTREE_sort(st) SKM_sk_sort(GENERAL_SUBTREE, (st)) +# define sk_GENERAL_SUBTREE_is_sorted(st) SKM_sk_is_sorted(GENERAL_SUBTREE, (st)) +# define sk_IPAddressFamily_new(cmp) SKM_sk_new(IPAddressFamily, (cmp)) +# define sk_IPAddressFamily_new_null() SKM_sk_new_null(IPAddressFamily) +# define sk_IPAddressFamily_free(st) SKM_sk_free(IPAddressFamily, (st)) +# define sk_IPAddressFamily_num(st) SKM_sk_num(IPAddressFamily, (st)) +# define sk_IPAddressFamily_value(st, i) SKM_sk_value(IPAddressFamily, (st), (i)) +# define sk_IPAddressFamily_set(st, i, val) SKM_sk_set(IPAddressFamily, (st), (i), (val)) +# define sk_IPAddressFamily_zero(st) SKM_sk_zero(IPAddressFamily, (st)) +# define sk_IPAddressFamily_push(st, val) SKM_sk_push(IPAddressFamily, (st), (val)) +# define sk_IPAddressFamily_unshift(st, val) SKM_sk_unshift(IPAddressFamily, (st), (val)) +# define sk_IPAddressFamily_find(st, val) SKM_sk_find(IPAddressFamily, (st), (val)) +# define sk_IPAddressFamily_find_ex(st, val) SKM_sk_find_ex(IPAddressFamily, (st), (val)) +# define sk_IPAddressFamily_delete(st, i) SKM_sk_delete(IPAddressFamily, (st), (i)) +# define sk_IPAddressFamily_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressFamily, (st), (ptr)) +# define sk_IPAddressFamily_insert(st, val, i) SKM_sk_insert(IPAddressFamily, (st), (val), (i)) +# define sk_IPAddressFamily_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressFamily, (st), (cmp)) +# define sk_IPAddressFamily_dup(st) SKM_sk_dup(IPAddressFamily, st) +# define sk_IPAddressFamily_pop_free(st, free_func) SKM_sk_pop_free(IPAddressFamily, (st), (free_func)) +# define sk_IPAddressFamily_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(IPAddressFamily, (st), (copy_func), (free_func)) +# define sk_IPAddressFamily_shift(st) SKM_sk_shift(IPAddressFamily, (st)) +# define sk_IPAddressFamily_pop(st) SKM_sk_pop(IPAddressFamily, (st)) +# define sk_IPAddressFamily_sort(st) SKM_sk_sort(IPAddressFamily, (st)) +# define sk_IPAddressFamily_is_sorted(st) SKM_sk_is_sorted(IPAddressFamily, (st)) +# define sk_IPAddressOrRange_new(cmp) SKM_sk_new(IPAddressOrRange, (cmp)) +# define sk_IPAddressOrRange_new_null() SKM_sk_new_null(IPAddressOrRange) +# define sk_IPAddressOrRange_free(st) SKM_sk_free(IPAddressOrRange, (st)) +# define sk_IPAddressOrRange_num(st) SKM_sk_num(IPAddressOrRange, (st)) +# define sk_IPAddressOrRange_value(st, i) SKM_sk_value(IPAddressOrRange, (st), (i)) +# define sk_IPAddressOrRange_set(st, i, val) SKM_sk_set(IPAddressOrRange, (st), (i), (val)) +# define sk_IPAddressOrRange_zero(st) SKM_sk_zero(IPAddressOrRange, (st)) +# define sk_IPAddressOrRange_push(st, val) SKM_sk_push(IPAddressOrRange, (st), (val)) +# define sk_IPAddressOrRange_unshift(st, val) SKM_sk_unshift(IPAddressOrRange, (st), (val)) +# define sk_IPAddressOrRange_find(st, val) SKM_sk_find(IPAddressOrRange, (st), (val)) +# define sk_IPAddressOrRange_find_ex(st, val) SKM_sk_find_ex(IPAddressOrRange, (st), (val)) +# define sk_IPAddressOrRange_delete(st, i) SKM_sk_delete(IPAddressOrRange, (st), (i)) +# define sk_IPAddressOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressOrRange, (st), (ptr)) +# define sk_IPAddressOrRange_insert(st, val, i) SKM_sk_insert(IPAddressOrRange, (st), (val), (i)) +# define sk_IPAddressOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressOrRange, (st), (cmp)) +# define sk_IPAddressOrRange_dup(st) SKM_sk_dup(IPAddressOrRange, st) +# define sk_IPAddressOrRange_pop_free(st, free_func) SKM_sk_pop_free(IPAddressOrRange, (st), (free_func)) +# define sk_IPAddressOrRange_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(IPAddressOrRange, (st), (copy_func), (free_func)) +# define sk_IPAddressOrRange_shift(st) SKM_sk_shift(IPAddressOrRange, (st)) +# define sk_IPAddressOrRange_pop(st) SKM_sk_pop(IPAddressOrRange, (st)) +# define sk_IPAddressOrRange_sort(st) SKM_sk_sort(IPAddressOrRange, (st)) +# define sk_IPAddressOrRange_is_sorted(st) SKM_sk_is_sorted(IPAddressOrRange, (st)) +# define sk_KRB5_APREQBODY_new(cmp) SKM_sk_new(KRB5_APREQBODY, (cmp)) +# define sk_KRB5_APREQBODY_new_null() SKM_sk_new_null(KRB5_APREQBODY) +# define sk_KRB5_APREQBODY_free(st) SKM_sk_free(KRB5_APREQBODY, (st)) +# define sk_KRB5_APREQBODY_num(st) SKM_sk_num(KRB5_APREQBODY, (st)) +# define sk_KRB5_APREQBODY_value(st, i) SKM_sk_value(KRB5_APREQBODY, (st), (i)) +# define sk_KRB5_APREQBODY_set(st, i, val) SKM_sk_set(KRB5_APREQBODY, (st), (i), (val)) +# define sk_KRB5_APREQBODY_zero(st) SKM_sk_zero(KRB5_APREQBODY, (st)) +# define sk_KRB5_APREQBODY_push(st, val) SKM_sk_push(KRB5_APREQBODY, (st), (val)) +# define sk_KRB5_APREQBODY_unshift(st, val) SKM_sk_unshift(KRB5_APREQBODY, (st), (val)) +# define sk_KRB5_APREQBODY_find(st, val) SKM_sk_find(KRB5_APREQBODY, (st), (val)) +# define sk_KRB5_APREQBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_APREQBODY, (st), (val)) +# define sk_KRB5_APREQBODY_delete(st, i) SKM_sk_delete(KRB5_APREQBODY, (st), (i)) +# define sk_KRB5_APREQBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_APREQBODY, (st), (ptr)) +# define sk_KRB5_APREQBODY_insert(st, val, i) SKM_sk_insert(KRB5_APREQBODY, (st), (val), (i)) +# define sk_KRB5_APREQBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_APREQBODY, (st), (cmp)) +# define sk_KRB5_APREQBODY_dup(st) SKM_sk_dup(KRB5_APREQBODY, st) +# define sk_KRB5_APREQBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_APREQBODY, (st), (free_func)) +# define sk_KRB5_APREQBODY_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(KRB5_APREQBODY, (st), (copy_func), (free_func)) +# define sk_KRB5_APREQBODY_shift(st) SKM_sk_shift(KRB5_APREQBODY, (st)) +# define sk_KRB5_APREQBODY_pop(st) SKM_sk_pop(KRB5_APREQBODY, (st)) +# define sk_KRB5_APREQBODY_sort(st) SKM_sk_sort(KRB5_APREQBODY, (st)) +# define sk_KRB5_APREQBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_APREQBODY, (st)) +# define sk_KRB5_AUTHDATA_new(cmp) SKM_sk_new(KRB5_AUTHDATA, (cmp)) +# define sk_KRB5_AUTHDATA_new_null() SKM_sk_new_null(KRB5_AUTHDATA) +# define sk_KRB5_AUTHDATA_free(st) SKM_sk_free(KRB5_AUTHDATA, (st)) +# define sk_KRB5_AUTHDATA_num(st) SKM_sk_num(KRB5_AUTHDATA, (st)) +# define sk_KRB5_AUTHDATA_value(st, i) SKM_sk_value(KRB5_AUTHDATA, (st), (i)) +# define sk_KRB5_AUTHDATA_set(st, i, val) SKM_sk_set(KRB5_AUTHDATA, (st), (i), (val)) +# define sk_KRB5_AUTHDATA_zero(st) SKM_sk_zero(KRB5_AUTHDATA, (st)) +# define sk_KRB5_AUTHDATA_push(st, val) SKM_sk_push(KRB5_AUTHDATA, (st), (val)) +# define sk_KRB5_AUTHDATA_unshift(st, val) SKM_sk_unshift(KRB5_AUTHDATA, (st), (val)) +# define sk_KRB5_AUTHDATA_find(st, val) SKM_sk_find(KRB5_AUTHDATA, (st), (val)) +# define sk_KRB5_AUTHDATA_find_ex(st, val) SKM_sk_find_ex(KRB5_AUTHDATA, (st), (val)) +# define sk_KRB5_AUTHDATA_delete(st, i) SKM_sk_delete(KRB5_AUTHDATA, (st), (i)) +# define sk_KRB5_AUTHDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHDATA, (st), (ptr)) +# define sk_KRB5_AUTHDATA_insert(st, val, i) SKM_sk_insert(KRB5_AUTHDATA, (st), (val), (i)) +# define sk_KRB5_AUTHDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHDATA, (st), (cmp)) +# define sk_KRB5_AUTHDATA_dup(st) SKM_sk_dup(KRB5_AUTHDATA, st) +# define sk_KRB5_AUTHDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHDATA, (st), (free_func)) +# define sk_KRB5_AUTHDATA_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(KRB5_AUTHDATA, (st), (copy_func), (free_func)) +# define sk_KRB5_AUTHDATA_shift(st) SKM_sk_shift(KRB5_AUTHDATA, (st)) +# define sk_KRB5_AUTHDATA_pop(st) SKM_sk_pop(KRB5_AUTHDATA, (st)) +# define sk_KRB5_AUTHDATA_sort(st) SKM_sk_sort(KRB5_AUTHDATA, (st)) +# define sk_KRB5_AUTHDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHDATA, (st)) +# define sk_KRB5_AUTHENTBODY_new(cmp) SKM_sk_new(KRB5_AUTHENTBODY, (cmp)) +# define sk_KRB5_AUTHENTBODY_new_null() SKM_sk_new_null(KRB5_AUTHENTBODY) +# define sk_KRB5_AUTHENTBODY_free(st) SKM_sk_free(KRB5_AUTHENTBODY, (st)) +# define sk_KRB5_AUTHENTBODY_num(st) SKM_sk_num(KRB5_AUTHENTBODY, (st)) +# define sk_KRB5_AUTHENTBODY_value(st, i) SKM_sk_value(KRB5_AUTHENTBODY, (st), (i)) +# define sk_KRB5_AUTHENTBODY_set(st, i, val) SKM_sk_set(KRB5_AUTHENTBODY, (st), (i), (val)) +# define sk_KRB5_AUTHENTBODY_zero(st) SKM_sk_zero(KRB5_AUTHENTBODY, (st)) +# define sk_KRB5_AUTHENTBODY_push(st, val) SKM_sk_push(KRB5_AUTHENTBODY, (st), (val)) +# define sk_KRB5_AUTHENTBODY_unshift(st, val) SKM_sk_unshift(KRB5_AUTHENTBODY, (st), (val)) +# define sk_KRB5_AUTHENTBODY_find(st, val) SKM_sk_find(KRB5_AUTHENTBODY, (st), (val)) +# define sk_KRB5_AUTHENTBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_AUTHENTBODY, (st), (val)) +# define sk_KRB5_AUTHENTBODY_delete(st, i) SKM_sk_delete(KRB5_AUTHENTBODY, (st), (i)) +# define sk_KRB5_AUTHENTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_AUTHENTBODY, (st), (ptr)) +# define sk_KRB5_AUTHENTBODY_insert(st, val, i) SKM_sk_insert(KRB5_AUTHENTBODY, (st), (val), (i)) +# define sk_KRB5_AUTHENTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_AUTHENTBODY, (st), (cmp)) +# define sk_KRB5_AUTHENTBODY_dup(st) SKM_sk_dup(KRB5_AUTHENTBODY, st) +# define sk_KRB5_AUTHENTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_AUTHENTBODY, (st), (free_func)) +# define sk_KRB5_AUTHENTBODY_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(KRB5_AUTHENTBODY, (st), (copy_func), (free_func)) +# define sk_KRB5_AUTHENTBODY_shift(st) SKM_sk_shift(KRB5_AUTHENTBODY, (st)) +# define sk_KRB5_AUTHENTBODY_pop(st) SKM_sk_pop(KRB5_AUTHENTBODY, (st)) +# define sk_KRB5_AUTHENTBODY_sort(st) SKM_sk_sort(KRB5_AUTHENTBODY, (st)) +# define sk_KRB5_AUTHENTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_AUTHENTBODY, (st)) +# define sk_KRB5_CHECKSUM_new(cmp) SKM_sk_new(KRB5_CHECKSUM, (cmp)) +# define sk_KRB5_CHECKSUM_new_null() SKM_sk_new_null(KRB5_CHECKSUM) +# define sk_KRB5_CHECKSUM_free(st) SKM_sk_free(KRB5_CHECKSUM, (st)) +# define sk_KRB5_CHECKSUM_num(st) SKM_sk_num(KRB5_CHECKSUM, (st)) +# define sk_KRB5_CHECKSUM_value(st, i) SKM_sk_value(KRB5_CHECKSUM, (st), (i)) +# define sk_KRB5_CHECKSUM_set(st, i, val) SKM_sk_set(KRB5_CHECKSUM, (st), (i), (val)) +# define sk_KRB5_CHECKSUM_zero(st) SKM_sk_zero(KRB5_CHECKSUM, (st)) +# define sk_KRB5_CHECKSUM_push(st, val) SKM_sk_push(KRB5_CHECKSUM, (st), (val)) +# define sk_KRB5_CHECKSUM_unshift(st, val) SKM_sk_unshift(KRB5_CHECKSUM, (st), (val)) +# define sk_KRB5_CHECKSUM_find(st, val) SKM_sk_find(KRB5_CHECKSUM, (st), (val)) +# define sk_KRB5_CHECKSUM_find_ex(st, val) SKM_sk_find_ex(KRB5_CHECKSUM, (st), (val)) +# define sk_KRB5_CHECKSUM_delete(st, i) SKM_sk_delete(KRB5_CHECKSUM, (st), (i)) +# define sk_KRB5_CHECKSUM_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_CHECKSUM, (st), (ptr)) +# define sk_KRB5_CHECKSUM_insert(st, val, i) SKM_sk_insert(KRB5_CHECKSUM, (st), (val), (i)) +# define sk_KRB5_CHECKSUM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_CHECKSUM, (st), (cmp)) +# define sk_KRB5_CHECKSUM_dup(st) SKM_sk_dup(KRB5_CHECKSUM, st) +# define sk_KRB5_CHECKSUM_pop_free(st, free_func) SKM_sk_pop_free(KRB5_CHECKSUM, (st), (free_func)) +# define sk_KRB5_CHECKSUM_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(KRB5_CHECKSUM, (st), (copy_func), (free_func)) +# define sk_KRB5_CHECKSUM_shift(st) SKM_sk_shift(KRB5_CHECKSUM, (st)) +# define sk_KRB5_CHECKSUM_pop(st) SKM_sk_pop(KRB5_CHECKSUM, (st)) +# define sk_KRB5_CHECKSUM_sort(st) SKM_sk_sort(KRB5_CHECKSUM, (st)) +# define sk_KRB5_CHECKSUM_is_sorted(st) SKM_sk_is_sorted(KRB5_CHECKSUM, (st)) +# define sk_KRB5_ENCDATA_new(cmp) SKM_sk_new(KRB5_ENCDATA, (cmp)) +# define sk_KRB5_ENCDATA_new_null() SKM_sk_new_null(KRB5_ENCDATA) +# define sk_KRB5_ENCDATA_free(st) SKM_sk_free(KRB5_ENCDATA, (st)) +# define sk_KRB5_ENCDATA_num(st) SKM_sk_num(KRB5_ENCDATA, (st)) +# define sk_KRB5_ENCDATA_value(st, i) SKM_sk_value(KRB5_ENCDATA, (st), (i)) +# define sk_KRB5_ENCDATA_set(st, i, val) SKM_sk_set(KRB5_ENCDATA, (st), (i), (val)) +# define sk_KRB5_ENCDATA_zero(st) SKM_sk_zero(KRB5_ENCDATA, (st)) +# define sk_KRB5_ENCDATA_push(st, val) SKM_sk_push(KRB5_ENCDATA, (st), (val)) +# define sk_KRB5_ENCDATA_unshift(st, val) SKM_sk_unshift(KRB5_ENCDATA, (st), (val)) +# define sk_KRB5_ENCDATA_find(st, val) SKM_sk_find(KRB5_ENCDATA, (st), (val)) +# define sk_KRB5_ENCDATA_find_ex(st, val) SKM_sk_find_ex(KRB5_ENCDATA, (st), (val)) +# define sk_KRB5_ENCDATA_delete(st, i) SKM_sk_delete(KRB5_ENCDATA, (st), (i)) +# define sk_KRB5_ENCDATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCDATA, (st), (ptr)) +# define sk_KRB5_ENCDATA_insert(st, val, i) SKM_sk_insert(KRB5_ENCDATA, (st), (val), (i)) +# define sk_KRB5_ENCDATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCDATA, (st), (cmp)) +# define sk_KRB5_ENCDATA_dup(st) SKM_sk_dup(KRB5_ENCDATA, st) +# define sk_KRB5_ENCDATA_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCDATA, (st), (free_func)) +# define sk_KRB5_ENCDATA_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(KRB5_ENCDATA, (st), (copy_func), (free_func)) +# define sk_KRB5_ENCDATA_shift(st) SKM_sk_shift(KRB5_ENCDATA, (st)) +# define sk_KRB5_ENCDATA_pop(st) SKM_sk_pop(KRB5_ENCDATA, (st)) +# define sk_KRB5_ENCDATA_sort(st) SKM_sk_sort(KRB5_ENCDATA, (st)) +# define sk_KRB5_ENCDATA_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCDATA, (st)) +# define sk_KRB5_ENCKEY_new(cmp) SKM_sk_new(KRB5_ENCKEY, (cmp)) +# define sk_KRB5_ENCKEY_new_null() SKM_sk_new_null(KRB5_ENCKEY) +# define sk_KRB5_ENCKEY_free(st) SKM_sk_free(KRB5_ENCKEY, (st)) +# define sk_KRB5_ENCKEY_num(st) SKM_sk_num(KRB5_ENCKEY, (st)) +# define sk_KRB5_ENCKEY_value(st, i) SKM_sk_value(KRB5_ENCKEY, (st), (i)) +# define sk_KRB5_ENCKEY_set(st, i, val) SKM_sk_set(KRB5_ENCKEY, (st), (i), (val)) +# define sk_KRB5_ENCKEY_zero(st) SKM_sk_zero(KRB5_ENCKEY, (st)) +# define sk_KRB5_ENCKEY_push(st, val) SKM_sk_push(KRB5_ENCKEY, (st), (val)) +# define sk_KRB5_ENCKEY_unshift(st, val) SKM_sk_unshift(KRB5_ENCKEY, (st), (val)) +# define sk_KRB5_ENCKEY_find(st, val) SKM_sk_find(KRB5_ENCKEY, (st), (val)) +# define sk_KRB5_ENCKEY_find_ex(st, val) SKM_sk_find_ex(KRB5_ENCKEY, (st), (val)) +# define sk_KRB5_ENCKEY_delete(st, i) SKM_sk_delete(KRB5_ENCKEY, (st), (i)) +# define sk_KRB5_ENCKEY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_ENCKEY, (st), (ptr)) +# define sk_KRB5_ENCKEY_insert(st, val, i) SKM_sk_insert(KRB5_ENCKEY, (st), (val), (i)) +# define sk_KRB5_ENCKEY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_ENCKEY, (st), (cmp)) +# define sk_KRB5_ENCKEY_dup(st) SKM_sk_dup(KRB5_ENCKEY, st) +# define sk_KRB5_ENCKEY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_ENCKEY, (st), (free_func)) +# define sk_KRB5_ENCKEY_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(KRB5_ENCKEY, (st), (copy_func), (free_func)) +# define sk_KRB5_ENCKEY_shift(st) SKM_sk_shift(KRB5_ENCKEY, (st)) +# define sk_KRB5_ENCKEY_pop(st) SKM_sk_pop(KRB5_ENCKEY, (st)) +# define sk_KRB5_ENCKEY_sort(st) SKM_sk_sort(KRB5_ENCKEY, (st)) +# define sk_KRB5_ENCKEY_is_sorted(st) SKM_sk_is_sorted(KRB5_ENCKEY, (st)) +# define sk_KRB5_PRINCNAME_new(cmp) SKM_sk_new(KRB5_PRINCNAME, (cmp)) +# define sk_KRB5_PRINCNAME_new_null() SKM_sk_new_null(KRB5_PRINCNAME) +# define sk_KRB5_PRINCNAME_free(st) SKM_sk_free(KRB5_PRINCNAME, (st)) +# define sk_KRB5_PRINCNAME_num(st) SKM_sk_num(KRB5_PRINCNAME, (st)) +# define sk_KRB5_PRINCNAME_value(st, i) SKM_sk_value(KRB5_PRINCNAME, (st), (i)) +# define sk_KRB5_PRINCNAME_set(st, i, val) SKM_sk_set(KRB5_PRINCNAME, (st), (i), (val)) +# define sk_KRB5_PRINCNAME_zero(st) SKM_sk_zero(KRB5_PRINCNAME, (st)) +# define sk_KRB5_PRINCNAME_push(st, val) SKM_sk_push(KRB5_PRINCNAME, (st), (val)) +# define sk_KRB5_PRINCNAME_unshift(st, val) SKM_sk_unshift(KRB5_PRINCNAME, (st), (val)) +# define sk_KRB5_PRINCNAME_find(st, val) SKM_sk_find(KRB5_PRINCNAME, (st), (val)) +# define sk_KRB5_PRINCNAME_find_ex(st, val) SKM_sk_find_ex(KRB5_PRINCNAME, (st), (val)) +# define sk_KRB5_PRINCNAME_delete(st, i) SKM_sk_delete(KRB5_PRINCNAME, (st), (i)) +# define sk_KRB5_PRINCNAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_PRINCNAME, (st), (ptr)) +# define sk_KRB5_PRINCNAME_insert(st, val, i) SKM_sk_insert(KRB5_PRINCNAME, (st), (val), (i)) +# define sk_KRB5_PRINCNAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_PRINCNAME, (st), (cmp)) +# define sk_KRB5_PRINCNAME_dup(st) SKM_sk_dup(KRB5_PRINCNAME, st) +# define sk_KRB5_PRINCNAME_pop_free(st, free_func) SKM_sk_pop_free(KRB5_PRINCNAME, (st), (free_func)) +# define sk_KRB5_PRINCNAME_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(KRB5_PRINCNAME, (st), (copy_func), (free_func)) +# define sk_KRB5_PRINCNAME_shift(st) SKM_sk_shift(KRB5_PRINCNAME, (st)) +# define sk_KRB5_PRINCNAME_pop(st) SKM_sk_pop(KRB5_PRINCNAME, (st)) +# define sk_KRB5_PRINCNAME_sort(st) SKM_sk_sort(KRB5_PRINCNAME, (st)) +# define sk_KRB5_PRINCNAME_is_sorted(st) SKM_sk_is_sorted(KRB5_PRINCNAME, (st)) +# define sk_KRB5_TKTBODY_new(cmp) SKM_sk_new(KRB5_TKTBODY, (cmp)) +# define sk_KRB5_TKTBODY_new_null() SKM_sk_new_null(KRB5_TKTBODY) +# define sk_KRB5_TKTBODY_free(st) SKM_sk_free(KRB5_TKTBODY, (st)) +# define sk_KRB5_TKTBODY_num(st) SKM_sk_num(KRB5_TKTBODY, (st)) +# define sk_KRB5_TKTBODY_value(st, i) SKM_sk_value(KRB5_TKTBODY, (st), (i)) +# define sk_KRB5_TKTBODY_set(st, i, val) SKM_sk_set(KRB5_TKTBODY, (st), (i), (val)) +# define sk_KRB5_TKTBODY_zero(st) SKM_sk_zero(KRB5_TKTBODY, (st)) +# define sk_KRB5_TKTBODY_push(st, val) SKM_sk_push(KRB5_TKTBODY, (st), (val)) +# define sk_KRB5_TKTBODY_unshift(st, val) SKM_sk_unshift(KRB5_TKTBODY, (st), (val)) +# define sk_KRB5_TKTBODY_find(st, val) SKM_sk_find(KRB5_TKTBODY, (st), (val)) +# define sk_KRB5_TKTBODY_find_ex(st, val) SKM_sk_find_ex(KRB5_TKTBODY, (st), (val)) +# define sk_KRB5_TKTBODY_delete(st, i) SKM_sk_delete(KRB5_TKTBODY, (st), (i)) +# define sk_KRB5_TKTBODY_delete_ptr(st, ptr) SKM_sk_delete_ptr(KRB5_TKTBODY, (st), (ptr)) +# define sk_KRB5_TKTBODY_insert(st, val, i) SKM_sk_insert(KRB5_TKTBODY, (st), (val), (i)) +# define sk_KRB5_TKTBODY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(KRB5_TKTBODY, (st), (cmp)) +# define sk_KRB5_TKTBODY_dup(st) SKM_sk_dup(KRB5_TKTBODY, st) +# define sk_KRB5_TKTBODY_pop_free(st, free_func) SKM_sk_pop_free(KRB5_TKTBODY, (st), (free_func)) +# define sk_KRB5_TKTBODY_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(KRB5_TKTBODY, (st), (copy_func), (free_func)) +# define sk_KRB5_TKTBODY_shift(st) SKM_sk_shift(KRB5_TKTBODY, (st)) +# define sk_KRB5_TKTBODY_pop(st) SKM_sk_pop(KRB5_TKTBODY, (st)) +# define sk_KRB5_TKTBODY_sort(st) SKM_sk_sort(KRB5_TKTBODY, (st)) +# define sk_KRB5_TKTBODY_is_sorted(st) SKM_sk_is_sorted(KRB5_TKTBODY, (st)) +# define sk_MEM_OBJECT_DATA_new(cmp) SKM_sk_new(MEM_OBJECT_DATA, (cmp)) +# define sk_MEM_OBJECT_DATA_new_null() SKM_sk_new_null(MEM_OBJECT_DATA) +# define sk_MEM_OBJECT_DATA_free(st) SKM_sk_free(MEM_OBJECT_DATA, (st)) +# define sk_MEM_OBJECT_DATA_num(st) SKM_sk_num(MEM_OBJECT_DATA, (st)) +# define sk_MEM_OBJECT_DATA_value(st, i) SKM_sk_value(MEM_OBJECT_DATA, (st), (i)) +# define sk_MEM_OBJECT_DATA_set(st, i, val) SKM_sk_set(MEM_OBJECT_DATA, (st), (i), (val)) +# define sk_MEM_OBJECT_DATA_zero(st) SKM_sk_zero(MEM_OBJECT_DATA, (st)) +# define sk_MEM_OBJECT_DATA_push(st, val) SKM_sk_push(MEM_OBJECT_DATA, (st), (val)) +# define sk_MEM_OBJECT_DATA_unshift(st, val) SKM_sk_unshift(MEM_OBJECT_DATA, (st), (val)) +# define sk_MEM_OBJECT_DATA_find(st, val) SKM_sk_find(MEM_OBJECT_DATA, (st), (val)) +# define sk_MEM_OBJECT_DATA_find_ex(st, val) SKM_sk_find_ex(MEM_OBJECT_DATA, (st), (val)) +# define sk_MEM_OBJECT_DATA_delete(st, i) SKM_sk_delete(MEM_OBJECT_DATA, (st), (i)) +# define sk_MEM_OBJECT_DATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(MEM_OBJECT_DATA, (st), (ptr)) +# define sk_MEM_OBJECT_DATA_insert(st, val, i) SKM_sk_insert(MEM_OBJECT_DATA, (st), (val), (i)) +# define sk_MEM_OBJECT_DATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MEM_OBJECT_DATA, (st), (cmp)) +# define sk_MEM_OBJECT_DATA_dup(st) SKM_sk_dup(MEM_OBJECT_DATA, st) +# define sk_MEM_OBJECT_DATA_pop_free(st, free_func) SKM_sk_pop_free(MEM_OBJECT_DATA, (st), (free_func)) +# define sk_MEM_OBJECT_DATA_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(MEM_OBJECT_DATA, (st), (copy_func), (free_func)) +# define sk_MEM_OBJECT_DATA_shift(st) SKM_sk_shift(MEM_OBJECT_DATA, (st)) +# define sk_MEM_OBJECT_DATA_pop(st) SKM_sk_pop(MEM_OBJECT_DATA, (st)) +# define sk_MEM_OBJECT_DATA_sort(st) SKM_sk_sort(MEM_OBJECT_DATA, (st)) +# define sk_MEM_OBJECT_DATA_is_sorted(st) SKM_sk_is_sorted(MEM_OBJECT_DATA, (st)) +# define sk_MIME_HEADER_new(cmp) SKM_sk_new(MIME_HEADER, (cmp)) +# define sk_MIME_HEADER_new_null() SKM_sk_new_null(MIME_HEADER) +# define sk_MIME_HEADER_free(st) SKM_sk_free(MIME_HEADER, (st)) +# define sk_MIME_HEADER_num(st) SKM_sk_num(MIME_HEADER, (st)) +# define sk_MIME_HEADER_value(st, i) SKM_sk_value(MIME_HEADER, (st), (i)) +# define sk_MIME_HEADER_set(st, i, val) SKM_sk_set(MIME_HEADER, (st), (i), (val)) +# define sk_MIME_HEADER_zero(st) SKM_sk_zero(MIME_HEADER, (st)) +# define sk_MIME_HEADER_push(st, val) SKM_sk_push(MIME_HEADER, (st), (val)) +# define sk_MIME_HEADER_unshift(st, val) SKM_sk_unshift(MIME_HEADER, (st), (val)) +# define sk_MIME_HEADER_find(st, val) SKM_sk_find(MIME_HEADER, (st), (val)) +# define sk_MIME_HEADER_find_ex(st, val) SKM_sk_find_ex(MIME_HEADER, (st), (val)) +# define sk_MIME_HEADER_delete(st, i) SKM_sk_delete(MIME_HEADER, (st), (i)) +# define sk_MIME_HEADER_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_HEADER, (st), (ptr)) +# define sk_MIME_HEADER_insert(st, val, i) SKM_sk_insert(MIME_HEADER, (st), (val), (i)) +# define sk_MIME_HEADER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_HEADER, (st), (cmp)) +# define sk_MIME_HEADER_dup(st) SKM_sk_dup(MIME_HEADER, st) +# define sk_MIME_HEADER_pop_free(st, free_func) SKM_sk_pop_free(MIME_HEADER, (st), (free_func)) +# define sk_MIME_HEADER_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(MIME_HEADER, (st), (copy_func), (free_func)) +# define sk_MIME_HEADER_shift(st) SKM_sk_shift(MIME_HEADER, (st)) +# define sk_MIME_HEADER_pop(st) SKM_sk_pop(MIME_HEADER, (st)) +# define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st)) +# define sk_MIME_HEADER_is_sorted(st) SKM_sk_is_sorted(MIME_HEADER, (st)) +# define sk_MIME_PARAM_new(cmp) SKM_sk_new(MIME_PARAM, (cmp)) +# define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM) +# define sk_MIME_PARAM_free(st) SKM_sk_free(MIME_PARAM, (st)) +# define sk_MIME_PARAM_num(st) SKM_sk_num(MIME_PARAM, (st)) +# define sk_MIME_PARAM_value(st, i) SKM_sk_value(MIME_PARAM, (st), (i)) +# define sk_MIME_PARAM_set(st, i, val) SKM_sk_set(MIME_PARAM, (st), (i), (val)) +# define sk_MIME_PARAM_zero(st) SKM_sk_zero(MIME_PARAM, (st)) +# define sk_MIME_PARAM_push(st, val) SKM_sk_push(MIME_PARAM, (st), (val)) +# define sk_MIME_PARAM_unshift(st, val) SKM_sk_unshift(MIME_PARAM, (st), (val)) +# define sk_MIME_PARAM_find(st, val) SKM_sk_find(MIME_PARAM, (st), (val)) +# define sk_MIME_PARAM_find_ex(st, val) SKM_sk_find_ex(MIME_PARAM, (st), (val)) +# define sk_MIME_PARAM_delete(st, i) SKM_sk_delete(MIME_PARAM, (st), (i)) +# define sk_MIME_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_PARAM, (st), (ptr)) +# define sk_MIME_PARAM_insert(st, val, i) SKM_sk_insert(MIME_PARAM, (st), (val), (i)) +# define sk_MIME_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_PARAM, (st), (cmp)) +# define sk_MIME_PARAM_dup(st) SKM_sk_dup(MIME_PARAM, st) +# define sk_MIME_PARAM_pop_free(st, free_func) SKM_sk_pop_free(MIME_PARAM, (st), (free_func)) +# define sk_MIME_PARAM_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(MIME_PARAM, (st), (copy_func), (free_func)) +# define sk_MIME_PARAM_shift(st) SKM_sk_shift(MIME_PARAM, (st)) +# define sk_MIME_PARAM_pop(st) SKM_sk_pop(MIME_PARAM, (st)) +# define sk_MIME_PARAM_sort(st) SKM_sk_sort(MIME_PARAM, (st)) +# define sk_MIME_PARAM_is_sorted(st) SKM_sk_is_sorted(MIME_PARAM, (st)) +# define sk_NAME_FUNCS_new(cmp) SKM_sk_new(NAME_FUNCS, (cmp)) +# define sk_NAME_FUNCS_new_null() SKM_sk_new_null(NAME_FUNCS) +# define sk_NAME_FUNCS_free(st) SKM_sk_free(NAME_FUNCS, (st)) +# define sk_NAME_FUNCS_num(st) SKM_sk_num(NAME_FUNCS, (st)) +# define sk_NAME_FUNCS_value(st, i) SKM_sk_value(NAME_FUNCS, (st), (i)) +# define sk_NAME_FUNCS_set(st, i, val) SKM_sk_set(NAME_FUNCS, (st), (i), (val)) +# define sk_NAME_FUNCS_zero(st) SKM_sk_zero(NAME_FUNCS, (st)) +# define sk_NAME_FUNCS_push(st, val) SKM_sk_push(NAME_FUNCS, (st), (val)) +# define sk_NAME_FUNCS_unshift(st, val) SKM_sk_unshift(NAME_FUNCS, (st), (val)) +# define sk_NAME_FUNCS_find(st, val) SKM_sk_find(NAME_FUNCS, (st), (val)) +# define sk_NAME_FUNCS_find_ex(st, val) SKM_sk_find_ex(NAME_FUNCS, (st), (val)) +# define sk_NAME_FUNCS_delete(st, i) SKM_sk_delete(NAME_FUNCS, (st), (i)) +# define sk_NAME_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(NAME_FUNCS, (st), (ptr)) +# define sk_NAME_FUNCS_insert(st, val, i) SKM_sk_insert(NAME_FUNCS, (st), (val), (i)) +# define sk_NAME_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(NAME_FUNCS, (st), (cmp)) +# define sk_NAME_FUNCS_dup(st) SKM_sk_dup(NAME_FUNCS, st) +# define sk_NAME_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(NAME_FUNCS, (st), (free_func)) +# define sk_NAME_FUNCS_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(NAME_FUNCS, (st), (copy_func), (free_func)) +# define sk_NAME_FUNCS_shift(st) SKM_sk_shift(NAME_FUNCS, (st)) +# define sk_NAME_FUNCS_pop(st) SKM_sk_pop(NAME_FUNCS, (st)) +# define sk_NAME_FUNCS_sort(st) SKM_sk_sort(NAME_FUNCS, (st)) +# define sk_NAME_FUNCS_is_sorted(st) SKM_sk_is_sorted(NAME_FUNCS, (st)) +# define sk_OCSP_CERTID_new(cmp) SKM_sk_new(OCSP_CERTID, (cmp)) +# define sk_OCSP_CERTID_new_null() SKM_sk_new_null(OCSP_CERTID) +# define sk_OCSP_CERTID_free(st) SKM_sk_free(OCSP_CERTID, (st)) +# define sk_OCSP_CERTID_num(st) SKM_sk_num(OCSP_CERTID, (st)) +# define sk_OCSP_CERTID_value(st, i) SKM_sk_value(OCSP_CERTID, (st), (i)) +# define sk_OCSP_CERTID_set(st, i, val) SKM_sk_set(OCSP_CERTID, (st), (i), (val)) +# define sk_OCSP_CERTID_zero(st) SKM_sk_zero(OCSP_CERTID, (st)) +# define sk_OCSP_CERTID_push(st, val) SKM_sk_push(OCSP_CERTID, (st), (val)) +# define sk_OCSP_CERTID_unshift(st, val) SKM_sk_unshift(OCSP_CERTID, (st), (val)) +# define sk_OCSP_CERTID_find(st, val) SKM_sk_find(OCSP_CERTID, (st), (val)) +# define sk_OCSP_CERTID_find_ex(st, val) SKM_sk_find_ex(OCSP_CERTID, (st), (val)) +# define sk_OCSP_CERTID_delete(st, i) SKM_sk_delete(OCSP_CERTID, (st), (i)) +# define sk_OCSP_CERTID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_CERTID, (st), (ptr)) +# define sk_OCSP_CERTID_insert(st, val, i) SKM_sk_insert(OCSP_CERTID, (st), (val), (i)) +# define sk_OCSP_CERTID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_CERTID, (st), (cmp)) +# define sk_OCSP_CERTID_dup(st) SKM_sk_dup(OCSP_CERTID, st) +# define sk_OCSP_CERTID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_CERTID, (st), (free_func)) +# define sk_OCSP_CERTID_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(OCSP_CERTID, (st), (copy_func), (free_func)) +# define sk_OCSP_CERTID_shift(st) SKM_sk_shift(OCSP_CERTID, (st)) +# define sk_OCSP_CERTID_pop(st) SKM_sk_pop(OCSP_CERTID, (st)) +# define sk_OCSP_CERTID_sort(st) SKM_sk_sort(OCSP_CERTID, (st)) +# define sk_OCSP_CERTID_is_sorted(st) SKM_sk_is_sorted(OCSP_CERTID, (st)) +# define sk_OCSP_ONEREQ_new(cmp) SKM_sk_new(OCSP_ONEREQ, (cmp)) +# define sk_OCSP_ONEREQ_new_null() SKM_sk_new_null(OCSP_ONEREQ) +# define sk_OCSP_ONEREQ_free(st) SKM_sk_free(OCSP_ONEREQ, (st)) +# define sk_OCSP_ONEREQ_num(st) SKM_sk_num(OCSP_ONEREQ, (st)) +# define sk_OCSP_ONEREQ_value(st, i) SKM_sk_value(OCSP_ONEREQ, (st), (i)) +# define sk_OCSP_ONEREQ_set(st, i, val) SKM_sk_set(OCSP_ONEREQ, (st), (i), (val)) +# define sk_OCSP_ONEREQ_zero(st) SKM_sk_zero(OCSP_ONEREQ, (st)) +# define sk_OCSP_ONEREQ_push(st, val) SKM_sk_push(OCSP_ONEREQ, (st), (val)) +# define sk_OCSP_ONEREQ_unshift(st, val) SKM_sk_unshift(OCSP_ONEREQ, (st), (val)) +# define sk_OCSP_ONEREQ_find(st, val) SKM_sk_find(OCSP_ONEREQ, (st), (val)) +# define sk_OCSP_ONEREQ_find_ex(st, val) SKM_sk_find_ex(OCSP_ONEREQ, (st), (val)) +# define sk_OCSP_ONEREQ_delete(st, i) SKM_sk_delete(OCSP_ONEREQ, (st), (i)) +# define sk_OCSP_ONEREQ_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_ONEREQ, (st), (ptr)) +# define sk_OCSP_ONEREQ_insert(st, val, i) SKM_sk_insert(OCSP_ONEREQ, (st), (val), (i)) +# define sk_OCSP_ONEREQ_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_ONEREQ, (st), (cmp)) +# define sk_OCSP_ONEREQ_dup(st) SKM_sk_dup(OCSP_ONEREQ, st) +# define sk_OCSP_ONEREQ_pop_free(st, free_func) SKM_sk_pop_free(OCSP_ONEREQ, (st), (free_func)) +# define sk_OCSP_ONEREQ_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(OCSP_ONEREQ, (st), (copy_func), (free_func)) +# define sk_OCSP_ONEREQ_shift(st) SKM_sk_shift(OCSP_ONEREQ, (st)) +# define sk_OCSP_ONEREQ_pop(st) SKM_sk_pop(OCSP_ONEREQ, (st)) +# define sk_OCSP_ONEREQ_sort(st) SKM_sk_sort(OCSP_ONEREQ, (st)) +# define sk_OCSP_ONEREQ_is_sorted(st) SKM_sk_is_sorted(OCSP_ONEREQ, (st)) +# define sk_OCSP_RESPID_new(cmp) SKM_sk_new(OCSP_RESPID, (cmp)) +# define sk_OCSP_RESPID_new_null() SKM_sk_new_null(OCSP_RESPID) +# define sk_OCSP_RESPID_free(st) SKM_sk_free(OCSP_RESPID, (st)) +# define sk_OCSP_RESPID_num(st) SKM_sk_num(OCSP_RESPID, (st)) +# define sk_OCSP_RESPID_value(st, i) SKM_sk_value(OCSP_RESPID, (st), (i)) +# define sk_OCSP_RESPID_set(st, i, val) SKM_sk_set(OCSP_RESPID, (st), (i), (val)) +# define sk_OCSP_RESPID_zero(st) SKM_sk_zero(OCSP_RESPID, (st)) +# define sk_OCSP_RESPID_push(st, val) SKM_sk_push(OCSP_RESPID, (st), (val)) +# define sk_OCSP_RESPID_unshift(st, val) SKM_sk_unshift(OCSP_RESPID, (st), (val)) +# define sk_OCSP_RESPID_find(st, val) SKM_sk_find(OCSP_RESPID, (st), (val)) +# define sk_OCSP_RESPID_find_ex(st, val) SKM_sk_find_ex(OCSP_RESPID, (st), (val)) +# define sk_OCSP_RESPID_delete(st, i) SKM_sk_delete(OCSP_RESPID, (st), (i)) +# define sk_OCSP_RESPID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_RESPID, (st), (ptr)) +# define sk_OCSP_RESPID_insert(st, val, i) SKM_sk_insert(OCSP_RESPID, (st), (val), (i)) +# define sk_OCSP_RESPID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_RESPID, (st), (cmp)) +# define sk_OCSP_RESPID_dup(st) SKM_sk_dup(OCSP_RESPID, st) +# define sk_OCSP_RESPID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_RESPID, (st), (free_func)) +# define sk_OCSP_RESPID_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(OCSP_RESPID, (st), (copy_func), (free_func)) +# define sk_OCSP_RESPID_shift(st) SKM_sk_shift(OCSP_RESPID, (st)) +# define sk_OCSP_RESPID_pop(st) SKM_sk_pop(OCSP_RESPID, (st)) +# define sk_OCSP_RESPID_sort(st) SKM_sk_sort(OCSP_RESPID, (st)) +# define sk_OCSP_RESPID_is_sorted(st) SKM_sk_is_sorted(OCSP_RESPID, (st)) +# define sk_OCSP_SINGLERESP_new(cmp) SKM_sk_new(OCSP_SINGLERESP, (cmp)) +# define sk_OCSP_SINGLERESP_new_null() SKM_sk_new_null(OCSP_SINGLERESP) +# define sk_OCSP_SINGLERESP_free(st) SKM_sk_free(OCSP_SINGLERESP, (st)) +# define sk_OCSP_SINGLERESP_num(st) SKM_sk_num(OCSP_SINGLERESP, (st)) +# define sk_OCSP_SINGLERESP_value(st, i) SKM_sk_value(OCSP_SINGLERESP, (st), (i)) +# define sk_OCSP_SINGLERESP_set(st, i, val) SKM_sk_set(OCSP_SINGLERESP, (st), (i), (val)) +# define sk_OCSP_SINGLERESP_zero(st) SKM_sk_zero(OCSP_SINGLERESP, (st)) +# define sk_OCSP_SINGLERESP_push(st, val) SKM_sk_push(OCSP_SINGLERESP, (st), (val)) +# define sk_OCSP_SINGLERESP_unshift(st, val) SKM_sk_unshift(OCSP_SINGLERESP, (st), (val)) +# define sk_OCSP_SINGLERESP_find(st, val) SKM_sk_find(OCSP_SINGLERESP, (st), (val)) +# define sk_OCSP_SINGLERESP_find_ex(st, val) SKM_sk_find_ex(OCSP_SINGLERESP, (st), (val)) +# define sk_OCSP_SINGLERESP_delete(st, i) SKM_sk_delete(OCSP_SINGLERESP, (st), (i)) +# define sk_OCSP_SINGLERESP_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_SINGLERESP, (st), (ptr)) +# define sk_OCSP_SINGLERESP_insert(st, val, i) SKM_sk_insert(OCSP_SINGLERESP, (st), (val), (i)) +# define sk_OCSP_SINGLERESP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_SINGLERESP, (st), (cmp)) +# define sk_OCSP_SINGLERESP_dup(st) SKM_sk_dup(OCSP_SINGLERESP, st) +# define sk_OCSP_SINGLERESP_pop_free(st, free_func) SKM_sk_pop_free(OCSP_SINGLERESP, (st), (free_func)) +# define sk_OCSP_SINGLERESP_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(OCSP_SINGLERESP, (st), (copy_func), (free_func)) +# define sk_OCSP_SINGLERESP_shift(st) SKM_sk_shift(OCSP_SINGLERESP, (st)) +# define sk_OCSP_SINGLERESP_pop(st) SKM_sk_pop(OCSP_SINGLERESP, (st)) +# define sk_OCSP_SINGLERESP_sort(st) SKM_sk_sort(OCSP_SINGLERESP, (st)) +# define sk_OCSP_SINGLERESP_is_sorted(st) SKM_sk_is_sorted(OCSP_SINGLERESP, (st)) +# define sk_PKCS12_SAFEBAG_new(cmp) SKM_sk_new(PKCS12_SAFEBAG, (cmp)) +# define sk_PKCS12_SAFEBAG_new_null() SKM_sk_new_null(PKCS12_SAFEBAG) +# define sk_PKCS12_SAFEBAG_free(st) SKM_sk_free(PKCS12_SAFEBAG, (st)) +# define sk_PKCS12_SAFEBAG_num(st) SKM_sk_num(PKCS12_SAFEBAG, (st)) +# define sk_PKCS12_SAFEBAG_value(st, i) SKM_sk_value(PKCS12_SAFEBAG, (st), (i)) +# define sk_PKCS12_SAFEBAG_set(st, i, val) SKM_sk_set(PKCS12_SAFEBAG, (st), (i), (val)) +# define sk_PKCS12_SAFEBAG_zero(st) SKM_sk_zero(PKCS12_SAFEBAG, (st)) +# define sk_PKCS12_SAFEBAG_push(st, val) SKM_sk_push(PKCS12_SAFEBAG, (st), (val)) +# define sk_PKCS12_SAFEBAG_unshift(st, val) SKM_sk_unshift(PKCS12_SAFEBAG, (st), (val)) +# define sk_PKCS12_SAFEBAG_find(st, val) SKM_sk_find(PKCS12_SAFEBAG, (st), (val)) +# define sk_PKCS12_SAFEBAG_find_ex(st, val) SKM_sk_find_ex(PKCS12_SAFEBAG, (st), (val)) +# define sk_PKCS12_SAFEBAG_delete(st, i) SKM_sk_delete(PKCS12_SAFEBAG, (st), (i)) +# define sk_PKCS12_SAFEBAG_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS12_SAFEBAG, (st), (ptr)) +# define sk_PKCS12_SAFEBAG_insert(st, val, i) SKM_sk_insert(PKCS12_SAFEBAG, (st), (val), (i)) +# define sk_PKCS12_SAFEBAG_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS12_SAFEBAG, (st), (cmp)) +# define sk_PKCS12_SAFEBAG_dup(st) SKM_sk_dup(PKCS12_SAFEBAG, st) +# define sk_PKCS12_SAFEBAG_pop_free(st, free_func) SKM_sk_pop_free(PKCS12_SAFEBAG, (st), (free_func)) +# define sk_PKCS12_SAFEBAG_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(PKCS12_SAFEBAG, (st), (copy_func), (free_func)) +# define sk_PKCS12_SAFEBAG_shift(st) SKM_sk_shift(PKCS12_SAFEBAG, (st)) +# define sk_PKCS12_SAFEBAG_pop(st) SKM_sk_pop(PKCS12_SAFEBAG, (st)) +# define sk_PKCS12_SAFEBAG_sort(st) SKM_sk_sort(PKCS12_SAFEBAG, (st)) +# define sk_PKCS12_SAFEBAG_is_sorted(st) SKM_sk_is_sorted(PKCS12_SAFEBAG, (st)) +# define sk_PKCS7_new(cmp) SKM_sk_new(PKCS7, (cmp)) +# define sk_PKCS7_new_null() SKM_sk_new_null(PKCS7) +# define sk_PKCS7_free(st) SKM_sk_free(PKCS7, (st)) +# define sk_PKCS7_num(st) SKM_sk_num(PKCS7, (st)) +# define sk_PKCS7_value(st, i) SKM_sk_value(PKCS7, (st), (i)) +# define sk_PKCS7_set(st, i, val) SKM_sk_set(PKCS7, (st), (i), (val)) +# define sk_PKCS7_zero(st) SKM_sk_zero(PKCS7, (st)) +# define sk_PKCS7_push(st, val) SKM_sk_push(PKCS7, (st), (val)) +# define sk_PKCS7_unshift(st, val) SKM_sk_unshift(PKCS7, (st), (val)) +# define sk_PKCS7_find(st, val) SKM_sk_find(PKCS7, (st), (val)) +# define sk_PKCS7_find_ex(st, val) SKM_sk_find_ex(PKCS7, (st), (val)) +# define sk_PKCS7_delete(st, i) SKM_sk_delete(PKCS7, (st), (i)) +# define sk_PKCS7_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7, (st), (ptr)) +# define sk_PKCS7_insert(st, val, i) SKM_sk_insert(PKCS7, (st), (val), (i)) +# define sk_PKCS7_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7, (st), (cmp)) +# define sk_PKCS7_dup(st) SKM_sk_dup(PKCS7, st) +# define sk_PKCS7_pop_free(st, free_func) SKM_sk_pop_free(PKCS7, (st), (free_func)) +# define sk_PKCS7_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(PKCS7, (st), (copy_func), (free_func)) +# define sk_PKCS7_shift(st) SKM_sk_shift(PKCS7, (st)) +# define sk_PKCS7_pop(st) SKM_sk_pop(PKCS7, (st)) +# define sk_PKCS7_sort(st) SKM_sk_sort(PKCS7, (st)) +# define sk_PKCS7_is_sorted(st) SKM_sk_is_sorted(PKCS7, (st)) +# define sk_PKCS7_RECIP_INFO_new(cmp) SKM_sk_new(PKCS7_RECIP_INFO, (cmp)) +# define sk_PKCS7_RECIP_INFO_new_null() SKM_sk_new_null(PKCS7_RECIP_INFO) +# define sk_PKCS7_RECIP_INFO_free(st) SKM_sk_free(PKCS7_RECIP_INFO, (st)) +# define sk_PKCS7_RECIP_INFO_num(st) SKM_sk_num(PKCS7_RECIP_INFO, (st)) +# define sk_PKCS7_RECIP_INFO_value(st, i) SKM_sk_value(PKCS7_RECIP_INFO, (st), (i)) +# define sk_PKCS7_RECIP_INFO_set(st, i, val) SKM_sk_set(PKCS7_RECIP_INFO, (st), (i), (val)) +# define sk_PKCS7_RECIP_INFO_zero(st) SKM_sk_zero(PKCS7_RECIP_INFO, (st)) +# define sk_PKCS7_RECIP_INFO_push(st, val) SKM_sk_push(PKCS7_RECIP_INFO, (st), (val)) +# define sk_PKCS7_RECIP_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_RECIP_INFO, (st), (val)) +# define sk_PKCS7_RECIP_INFO_find(st, val) SKM_sk_find(PKCS7_RECIP_INFO, (st), (val)) +# define sk_PKCS7_RECIP_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_RECIP_INFO, (st), (val)) +# define sk_PKCS7_RECIP_INFO_delete(st, i) SKM_sk_delete(PKCS7_RECIP_INFO, (st), (i)) +# define sk_PKCS7_RECIP_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_RECIP_INFO, (st), (ptr)) +# define sk_PKCS7_RECIP_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_RECIP_INFO, (st), (val), (i)) +# define sk_PKCS7_RECIP_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_RECIP_INFO, (st), (cmp)) +# define sk_PKCS7_RECIP_INFO_dup(st) SKM_sk_dup(PKCS7_RECIP_INFO, st) +# define sk_PKCS7_RECIP_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_RECIP_INFO, (st), (free_func)) +# define sk_PKCS7_RECIP_INFO_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(PKCS7_RECIP_INFO, (st), (copy_func), (free_func)) +# define sk_PKCS7_RECIP_INFO_shift(st) SKM_sk_shift(PKCS7_RECIP_INFO, (st)) +# define sk_PKCS7_RECIP_INFO_pop(st) SKM_sk_pop(PKCS7_RECIP_INFO, (st)) +# define sk_PKCS7_RECIP_INFO_sort(st) SKM_sk_sort(PKCS7_RECIP_INFO, (st)) +# define sk_PKCS7_RECIP_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_RECIP_INFO, (st)) +# define sk_PKCS7_SIGNER_INFO_new(cmp) SKM_sk_new(PKCS7_SIGNER_INFO, (cmp)) +# define sk_PKCS7_SIGNER_INFO_new_null() SKM_sk_new_null(PKCS7_SIGNER_INFO) +# define sk_PKCS7_SIGNER_INFO_free(st) SKM_sk_free(PKCS7_SIGNER_INFO, (st)) +# define sk_PKCS7_SIGNER_INFO_num(st) SKM_sk_num(PKCS7_SIGNER_INFO, (st)) +# define sk_PKCS7_SIGNER_INFO_value(st, i) SKM_sk_value(PKCS7_SIGNER_INFO, (st), (i)) +# define sk_PKCS7_SIGNER_INFO_set(st, i, val) SKM_sk_set(PKCS7_SIGNER_INFO, (st), (i), (val)) +# define sk_PKCS7_SIGNER_INFO_zero(st) SKM_sk_zero(PKCS7_SIGNER_INFO, (st)) +# define sk_PKCS7_SIGNER_INFO_push(st, val) SKM_sk_push(PKCS7_SIGNER_INFO, (st), (val)) +# define sk_PKCS7_SIGNER_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_SIGNER_INFO, (st), (val)) +# define sk_PKCS7_SIGNER_INFO_find(st, val) SKM_sk_find(PKCS7_SIGNER_INFO, (st), (val)) +# define sk_PKCS7_SIGNER_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_SIGNER_INFO, (st), (val)) +# define sk_PKCS7_SIGNER_INFO_delete(st, i) SKM_sk_delete(PKCS7_SIGNER_INFO, (st), (i)) +# define sk_PKCS7_SIGNER_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_SIGNER_INFO, (st), (ptr)) +# define sk_PKCS7_SIGNER_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_SIGNER_INFO, (st), (val), (i)) +# define sk_PKCS7_SIGNER_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_SIGNER_INFO, (st), (cmp)) +# define sk_PKCS7_SIGNER_INFO_dup(st) SKM_sk_dup(PKCS7_SIGNER_INFO, st) +# define sk_PKCS7_SIGNER_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_SIGNER_INFO, (st), (free_func)) +# define sk_PKCS7_SIGNER_INFO_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(PKCS7_SIGNER_INFO, (st), (copy_func), (free_func)) +# define sk_PKCS7_SIGNER_INFO_shift(st) SKM_sk_shift(PKCS7_SIGNER_INFO, (st)) +# define sk_PKCS7_SIGNER_INFO_pop(st) SKM_sk_pop(PKCS7_SIGNER_INFO, (st)) +# define sk_PKCS7_SIGNER_INFO_sort(st) SKM_sk_sort(PKCS7_SIGNER_INFO, (st)) +# define sk_PKCS7_SIGNER_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_SIGNER_INFO, (st)) +# define sk_POLICYINFO_new(cmp) SKM_sk_new(POLICYINFO, (cmp)) +# define sk_POLICYINFO_new_null() SKM_sk_new_null(POLICYINFO) +# define sk_POLICYINFO_free(st) SKM_sk_free(POLICYINFO, (st)) +# define sk_POLICYINFO_num(st) SKM_sk_num(POLICYINFO, (st)) +# define sk_POLICYINFO_value(st, i) SKM_sk_value(POLICYINFO, (st), (i)) +# define sk_POLICYINFO_set(st, i, val) SKM_sk_set(POLICYINFO, (st), (i), (val)) +# define sk_POLICYINFO_zero(st) SKM_sk_zero(POLICYINFO, (st)) +# define sk_POLICYINFO_push(st, val) SKM_sk_push(POLICYINFO, (st), (val)) +# define sk_POLICYINFO_unshift(st, val) SKM_sk_unshift(POLICYINFO, (st), (val)) +# define sk_POLICYINFO_find(st, val) SKM_sk_find(POLICYINFO, (st), (val)) +# define sk_POLICYINFO_find_ex(st, val) SKM_sk_find_ex(POLICYINFO, (st), (val)) +# define sk_POLICYINFO_delete(st, i) SKM_sk_delete(POLICYINFO, (st), (i)) +# define sk_POLICYINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYINFO, (st), (ptr)) +# define sk_POLICYINFO_insert(st, val, i) SKM_sk_insert(POLICYINFO, (st), (val), (i)) +# define sk_POLICYINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYINFO, (st), (cmp)) +# define sk_POLICYINFO_dup(st) SKM_sk_dup(POLICYINFO, st) +# define sk_POLICYINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYINFO, (st), (free_func)) +# define sk_POLICYINFO_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(POLICYINFO, (st), (copy_func), (free_func)) +# define sk_POLICYINFO_shift(st) SKM_sk_shift(POLICYINFO, (st)) +# define sk_POLICYINFO_pop(st) SKM_sk_pop(POLICYINFO, (st)) +# define sk_POLICYINFO_sort(st) SKM_sk_sort(POLICYINFO, (st)) +# define sk_POLICYINFO_is_sorted(st) SKM_sk_is_sorted(POLICYINFO, (st)) +# define sk_POLICYQUALINFO_new(cmp) SKM_sk_new(POLICYQUALINFO, (cmp)) +# define sk_POLICYQUALINFO_new_null() SKM_sk_new_null(POLICYQUALINFO) +# define sk_POLICYQUALINFO_free(st) SKM_sk_free(POLICYQUALINFO, (st)) +# define sk_POLICYQUALINFO_num(st) SKM_sk_num(POLICYQUALINFO, (st)) +# define sk_POLICYQUALINFO_value(st, i) SKM_sk_value(POLICYQUALINFO, (st), (i)) +# define sk_POLICYQUALINFO_set(st, i, val) SKM_sk_set(POLICYQUALINFO, (st), (i), (val)) +# define sk_POLICYQUALINFO_zero(st) SKM_sk_zero(POLICYQUALINFO, (st)) +# define sk_POLICYQUALINFO_push(st, val) SKM_sk_push(POLICYQUALINFO, (st), (val)) +# define sk_POLICYQUALINFO_unshift(st, val) SKM_sk_unshift(POLICYQUALINFO, (st), (val)) +# define sk_POLICYQUALINFO_find(st, val) SKM_sk_find(POLICYQUALINFO, (st), (val)) +# define sk_POLICYQUALINFO_find_ex(st, val) SKM_sk_find_ex(POLICYQUALINFO, (st), (val)) +# define sk_POLICYQUALINFO_delete(st, i) SKM_sk_delete(POLICYQUALINFO, (st), (i)) +# define sk_POLICYQUALINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYQUALINFO, (st), (ptr)) +# define sk_POLICYQUALINFO_insert(st, val, i) SKM_sk_insert(POLICYQUALINFO, (st), (val), (i)) +# define sk_POLICYQUALINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYQUALINFO, (st), (cmp)) +# define sk_POLICYQUALINFO_dup(st) SKM_sk_dup(POLICYQUALINFO, st) +# define sk_POLICYQUALINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYQUALINFO, (st), (free_func)) +# define sk_POLICYQUALINFO_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(POLICYQUALINFO, (st), (copy_func), (free_func)) +# define sk_POLICYQUALINFO_shift(st) SKM_sk_shift(POLICYQUALINFO, (st)) +# define sk_POLICYQUALINFO_pop(st) SKM_sk_pop(POLICYQUALINFO, (st)) +# define sk_POLICYQUALINFO_sort(st) SKM_sk_sort(POLICYQUALINFO, (st)) +# define sk_POLICYQUALINFO_is_sorted(st) SKM_sk_is_sorted(POLICYQUALINFO, (st)) +# define sk_POLICY_MAPPING_new(cmp) SKM_sk_new(POLICY_MAPPING, (cmp)) +# define sk_POLICY_MAPPING_new_null() SKM_sk_new_null(POLICY_MAPPING) +# define sk_POLICY_MAPPING_free(st) SKM_sk_free(POLICY_MAPPING, (st)) +# define sk_POLICY_MAPPING_num(st) SKM_sk_num(POLICY_MAPPING, (st)) +# define sk_POLICY_MAPPING_value(st, i) SKM_sk_value(POLICY_MAPPING, (st), (i)) +# define sk_POLICY_MAPPING_set(st, i, val) SKM_sk_set(POLICY_MAPPING, (st), (i), (val)) +# define sk_POLICY_MAPPING_zero(st) SKM_sk_zero(POLICY_MAPPING, (st)) +# define sk_POLICY_MAPPING_push(st, val) SKM_sk_push(POLICY_MAPPING, (st), (val)) +# define sk_POLICY_MAPPING_unshift(st, val) SKM_sk_unshift(POLICY_MAPPING, (st), (val)) +# define sk_POLICY_MAPPING_find(st, val) SKM_sk_find(POLICY_MAPPING, (st), (val)) +# define sk_POLICY_MAPPING_find_ex(st, val) SKM_sk_find_ex(POLICY_MAPPING, (st), (val)) +# define sk_POLICY_MAPPING_delete(st, i) SKM_sk_delete(POLICY_MAPPING, (st), (i)) +# define sk_POLICY_MAPPING_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICY_MAPPING, (st), (ptr)) +# define sk_POLICY_MAPPING_insert(st, val, i) SKM_sk_insert(POLICY_MAPPING, (st), (val), (i)) +# define sk_POLICY_MAPPING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICY_MAPPING, (st), (cmp)) +# define sk_POLICY_MAPPING_dup(st) SKM_sk_dup(POLICY_MAPPING, st) +# define sk_POLICY_MAPPING_pop_free(st, free_func) SKM_sk_pop_free(POLICY_MAPPING, (st), (free_func)) +# define sk_POLICY_MAPPING_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(POLICY_MAPPING, (st), (copy_func), (free_func)) +# define sk_POLICY_MAPPING_shift(st) SKM_sk_shift(POLICY_MAPPING, (st)) +# define sk_POLICY_MAPPING_pop(st) SKM_sk_pop(POLICY_MAPPING, (st)) +# define sk_POLICY_MAPPING_sort(st) SKM_sk_sort(POLICY_MAPPING, (st)) +# define sk_POLICY_MAPPING_is_sorted(st) SKM_sk_is_sorted(POLICY_MAPPING, (st)) +# define sk_SCT_new(cmp) SKM_sk_new(SCT, (cmp)) +# define sk_SCT_new_null() SKM_sk_new_null(SCT) +# define sk_SCT_free(st) SKM_sk_free(SCT, (st)) +# define sk_SCT_num(st) SKM_sk_num(SCT, (st)) +# define sk_SCT_value(st, i) SKM_sk_value(SCT, (st), (i)) +# define sk_SCT_set(st, i, val) SKM_sk_set(SCT, (st), (i), (val)) +# define sk_SCT_zero(st) SKM_sk_zero(SCT, (st)) +# define sk_SCT_push(st, val) SKM_sk_push(SCT, (st), (val)) +# define sk_SCT_unshift(st, val) SKM_sk_unshift(SCT, (st), (val)) +# define sk_SCT_find(st, val) SKM_sk_find(SCT, (st), (val)) +# define sk_SCT_find_ex(st, val) SKM_sk_find_ex(SCT, (st), (val)) +# define sk_SCT_delete(st, i) SKM_sk_delete(SCT, (st), (i)) +# define sk_SCT_delete_ptr(st, ptr) SKM_sk_delete_ptr(SCT, (st), (ptr)) +# define sk_SCT_insert(st, val, i) SKM_sk_insert(SCT, (st), (val), (i)) +# define sk_SCT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SCT, (st), (cmp)) +# define sk_SCT_dup(st) SKM_sk_dup(SCT, st) +# define sk_SCT_pop_free(st, free_func) SKM_sk_pop_free(SCT, (st), (free_func)) +# define sk_SCT_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(SCT, (st), (copy_func), (free_func)) +# define sk_SCT_shift(st) SKM_sk_shift(SCT, (st)) +# define sk_SCT_pop(st) SKM_sk_pop(SCT, (st)) +# define sk_SCT_sort(st) SKM_sk_sort(SCT, (st)) +# define sk_SCT_is_sorted(st) SKM_sk_is_sorted(SCT, (st)) +# define sk_SRP_gN_new(cmp) SKM_sk_new(SRP_gN, (cmp)) +# define sk_SRP_gN_new_null() SKM_sk_new_null(SRP_gN) +# define sk_SRP_gN_free(st) SKM_sk_free(SRP_gN, (st)) +# define sk_SRP_gN_num(st) SKM_sk_num(SRP_gN, (st)) +# define sk_SRP_gN_value(st, i) SKM_sk_value(SRP_gN, (st), (i)) +# define sk_SRP_gN_set(st, i, val) SKM_sk_set(SRP_gN, (st), (i), (val)) +# define sk_SRP_gN_zero(st) SKM_sk_zero(SRP_gN, (st)) +# define sk_SRP_gN_push(st, val) SKM_sk_push(SRP_gN, (st), (val)) +# define sk_SRP_gN_unshift(st, val) SKM_sk_unshift(SRP_gN, (st), (val)) +# define sk_SRP_gN_find(st, val) SKM_sk_find(SRP_gN, (st), (val)) +# define sk_SRP_gN_find_ex(st, val) SKM_sk_find_ex(SRP_gN, (st), (val)) +# define sk_SRP_gN_delete(st, i) SKM_sk_delete(SRP_gN, (st), (i)) +# define sk_SRP_gN_delete_ptr(st, ptr) SKM_sk_delete_ptr(SRP_gN, (st), (ptr)) +# define sk_SRP_gN_insert(st, val, i) SKM_sk_insert(SRP_gN, (st), (val), (i)) +# define sk_SRP_gN_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SRP_gN, (st), (cmp)) +# define sk_SRP_gN_dup(st) SKM_sk_dup(SRP_gN, st) +# define sk_SRP_gN_pop_free(st, free_func) SKM_sk_pop_free(SRP_gN, (st), (free_func)) +# define sk_SRP_gN_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(SRP_gN, (st), (copy_func), (free_func)) +# define sk_SRP_gN_shift(st) SKM_sk_shift(SRP_gN, (st)) +# define sk_SRP_gN_pop(st) SKM_sk_pop(SRP_gN, (st)) +# define sk_SRP_gN_sort(st) SKM_sk_sort(SRP_gN, (st)) +# define sk_SRP_gN_is_sorted(st) SKM_sk_is_sorted(SRP_gN, (st)) +# define sk_SRP_gN_cache_new(cmp) SKM_sk_new(SRP_gN_cache, (cmp)) +# define sk_SRP_gN_cache_new_null() SKM_sk_new_null(SRP_gN_cache) +# define sk_SRP_gN_cache_free(st) SKM_sk_free(SRP_gN_cache, (st)) +# define sk_SRP_gN_cache_num(st) SKM_sk_num(SRP_gN_cache, (st)) +# define sk_SRP_gN_cache_value(st, i) SKM_sk_value(SRP_gN_cache, (st), (i)) +# define sk_SRP_gN_cache_set(st, i, val) SKM_sk_set(SRP_gN_cache, (st), (i), (val)) +# define sk_SRP_gN_cache_zero(st) SKM_sk_zero(SRP_gN_cache, (st)) +# define sk_SRP_gN_cache_push(st, val) SKM_sk_push(SRP_gN_cache, (st), (val)) +# define sk_SRP_gN_cache_unshift(st, val) SKM_sk_unshift(SRP_gN_cache, (st), (val)) +# define sk_SRP_gN_cache_find(st, val) SKM_sk_find(SRP_gN_cache, (st), (val)) +# define sk_SRP_gN_cache_find_ex(st, val) SKM_sk_find_ex(SRP_gN_cache, (st), (val)) +# define sk_SRP_gN_cache_delete(st, i) SKM_sk_delete(SRP_gN_cache, (st), (i)) +# define sk_SRP_gN_cache_delete_ptr(st, ptr) SKM_sk_delete_ptr(SRP_gN_cache, (st), (ptr)) +# define sk_SRP_gN_cache_insert(st, val, i) SKM_sk_insert(SRP_gN_cache, (st), (val), (i)) +# define sk_SRP_gN_cache_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SRP_gN_cache, (st), (cmp)) +# define sk_SRP_gN_cache_dup(st) SKM_sk_dup(SRP_gN_cache, st) +# define sk_SRP_gN_cache_pop_free(st, free_func) SKM_sk_pop_free(SRP_gN_cache, (st), (free_func)) +# define sk_SRP_gN_cache_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(SRP_gN_cache, (st), (copy_func), (free_func)) +# define sk_SRP_gN_cache_shift(st) SKM_sk_shift(SRP_gN_cache, (st)) +# define sk_SRP_gN_cache_pop(st) SKM_sk_pop(SRP_gN_cache, (st)) +# define sk_SRP_gN_cache_sort(st) SKM_sk_sort(SRP_gN_cache, (st)) +# define sk_SRP_gN_cache_is_sorted(st) SKM_sk_is_sorted(SRP_gN_cache, (st)) +# define sk_SRP_user_pwd_new(cmp) SKM_sk_new(SRP_user_pwd, (cmp)) +# define sk_SRP_user_pwd_new_null() SKM_sk_new_null(SRP_user_pwd) +# define sk_SRP_user_pwd_free(st) SKM_sk_free(SRP_user_pwd, (st)) +# define sk_SRP_user_pwd_num(st) SKM_sk_num(SRP_user_pwd, (st)) +# define sk_SRP_user_pwd_value(st, i) SKM_sk_value(SRP_user_pwd, (st), (i)) +# define sk_SRP_user_pwd_set(st, i, val) SKM_sk_set(SRP_user_pwd, (st), (i), (val)) +# define sk_SRP_user_pwd_zero(st) SKM_sk_zero(SRP_user_pwd, (st)) +# define sk_SRP_user_pwd_push(st, val) SKM_sk_push(SRP_user_pwd, (st), (val)) +# define sk_SRP_user_pwd_unshift(st, val) SKM_sk_unshift(SRP_user_pwd, (st), (val)) +# define sk_SRP_user_pwd_find(st, val) SKM_sk_find(SRP_user_pwd, (st), (val)) +# define sk_SRP_user_pwd_find_ex(st, val) SKM_sk_find_ex(SRP_user_pwd, (st), (val)) +# define sk_SRP_user_pwd_delete(st, i) SKM_sk_delete(SRP_user_pwd, (st), (i)) +# define sk_SRP_user_pwd_delete_ptr(st, ptr) SKM_sk_delete_ptr(SRP_user_pwd, (st), (ptr)) +# define sk_SRP_user_pwd_insert(st, val, i) SKM_sk_insert(SRP_user_pwd, (st), (val), (i)) +# define sk_SRP_user_pwd_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SRP_user_pwd, (st), (cmp)) +# define sk_SRP_user_pwd_dup(st) SKM_sk_dup(SRP_user_pwd, st) +# define sk_SRP_user_pwd_pop_free(st, free_func) SKM_sk_pop_free(SRP_user_pwd, (st), (free_func)) +# define sk_SRP_user_pwd_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(SRP_user_pwd, (st), (copy_func), (free_func)) +# define sk_SRP_user_pwd_shift(st) SKM_sk_shift(SRP_user_pwd, (st)) +# define sk_SRP_user_pwd_pop(st) SKM_sk_pop(SRP_user_pwd, (st)) +# define sk_SRP_user_pwd_sort(st) SKM_sk_sort(SRP_user_pwd, (st)) +# define sk_SRP_user_pwd_is_sorted(st) SKM_sk_is_sorted(SRP_user_pwd, (st)) +# define sk_SRTP_PROTECTION_PROFILE_new(cmp) SKM_sk_new(SRTP_PROTECTION_PROFILE, (cmp)) +# define sk_SRTP_PROTECTION_PROFILE_new_null() SKM_sk_new_null(SRTP_PROTECTION_PROFILE) +# define sk_SRTP_PROTECTION_PROFILE_free(st) SKM_sk_free(SRTP_PROTECTION_PROFILE, (st)) +# define sk_SRTP_PROTECTION_PROFILE_num(st) SKM_sk_num(SRTP_PROTECTION_PROFILE, (st)) +# define sk_SRTP_PROTECTION_PROFILE_value(st, i) SKM_sk_value(SRTP_PROTECTION_PROFILE, (st), (i)) +# define sk_SRTP_PROTECTION_PROFILE_set(st, i, val) SKM_sk_set(SRTP_PROTECTION_PROFILE, (st), (i), (val)) +# define sk_SRTP_PROTECTION_PROFILE_zero(st) SKM_sk_zero(SRTP_PROTECTION_PROFILE, (st)) +# define sk_SRTP_PROTECTION_PROFILE_push(st, val) SKM_sk_push(SRTP_PROTECTION_PROFILE, (st), (val)) +# define sk_SRTP_PROTECTION_PROFILE_unshift(st, val) SKM_sk_unshift(SRTP_PROTECTION_PROFILE, (st), (val)) +# define sk_SRTP_PROTECTION_PROFILE_find(st, val) SKM_sk_find(SRTP_PROTECTION_PROFILE, (st), (val)) +# define sk_SRTP_PROTECTION_PROFILE_find_ex(st, val) SKM_sk_find_ex(SRTP_PROTECTION_PROFILE, (st), (val)) +# define sk_SRTP_PROTECTION_PROFILE_delete(st, i) SKM_sk_delete(SRTP_PROTECTION_PROFILE, (st), (i)) +# define sk_SRTP_PROTECTION_PROFILE_delete_ptr(st, ptr) SKM_sk_delete_ptr(SRTP_PROTECTION_PROFILE, (st), (ptr)) +# define sk_SRTP_PROTECTION_PROFILE_insert(st, val, i) SKM_sk_insert(SRTP_PROTECTION_PROFILE, (st), (val), (i)) +# define sk_SRTP_PROTECTION_PROFILE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SRTP_PROTECTION_PROFILE, (st), (cmp)) +# define sk_SRTP_PROTECTION_PROFILE_dup(st) SKM_sk_dup(SRTP_PROTECTION_PROFILE, st) +# define sk_SRTP_PROTECTION_PROFILE_pop_free(st, free_func) SKM_sk_pop_free(SRTP_PROTECTION_PROFILE, (st), (free_func)) +# define sk_SRTP_PROTECTION_PROFILE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(SRTP_PROTECTION_PROFILE, (st), (copy_func), (free_func)) +# define sk_SRTP_PROTECTION_PROFILE_shift(st) SKM_sk_shift(SRTP_PROTECTION_PROFILE, (st)) +# define sk_SRTP_PROTECTION_PROFILE_pop(st) SKM_sk_pop(SRTP_PROTECTION_PROFILE, (st)) +# define sk_SRTP_PROTECTION_PROFILE_sort(st) SKM_sk_sort(SRTP_PROTECTION_PROFILE, (st)) +# define sk_SRTP_PROTECTION_PROFILE_is_sorted(st) SKM_sk_is_sorted(SRTP_PROTECTION_PROFILE, (st)) +# define sk_SSL_CIPHER_new(cmp) SKM_sk_new(SSL_CIPHER, (cmp)) +# define sk_SSL_CIPHER_new_null() SKM_sk_new_null(SSL_CIPHER) +# define sk_SSL_CIPHER_free(st) SKM_sk_free(SSL_CIPHER, (st)) +# define sk_SSL_CIPHER_num(st) SKM_sk_num(SSL_CIPHER, (st)) +# define sk_SSL_CIPHER_value(st, i) SKM_sk_value(SSL_CIPHER, (st), (i)) +# define sk_SSL_CIPHER_set(st, i, val) SKM_sk_set(SSL_CIPHER, (st), (i), (val)) +# define sk_SSL_CIPHER_zero(st) SKM_sk_zero(SSL_CIPHER, (st)) +# define sk_SSL_CIPHER_push(st, val) SKM_sk_push(SSL_CIPHER, (st), (val)) +# define sk_SSL_CIPHER_unshift(st, val) SKM_sk_unshift(SSL_CIPHER, (st), (val)) +# define sk_SSL_CIPHER_find(st, val) SKM_sk_find(SSL_CIPHER, (st), (val)) +# define sk_SSL_CIPHER_find_ex(st, val) SKM_sk_find_ex(SSL_CIPHER, (st), (val)) +# define sk_SSL_CIPHER_delete(st, i) SKM_sk_delete(SSL_CIPHER, (st), (i)) +# define sk_SSL_CIPHER_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_CIPHER, (st), (ptr)) +# define sk_SSL_CIPHER_insert(st, val, i) SKM_sk_insert(SSL_CIPHER, (st), (val), (i)) +# define sk_SSL_CIPHER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_CIPHER, (st), (cmp)) +# define sk_SSL_CIPHER_dup(st) SKM_sk_dup(SSL_CIPHER, st) +# define sk_SSL_CIPHER_pop_free(st, free_func) SKM_sk_pop_free(SSL_CIPHER, (st), (free_func)) +# define sk_SSL_CIPHER_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(SSL_CIPHER, (st), (copy_func), (free_func)) +# define sk_SSL_CIPHER_shift(st) SKM_sk_shift(SSL_CIPHER, (st)) +# define sk_SSL_CIPHER_pop(st) SKM_sk_pop(SSL_CIPHER, (st)) +# define sk_SSL_CIPHER_sort(st) SKM_sk_sort(SSL_CIPHER, (st)) +# define sk_SSL_CIPHER_is_sorted(st) SKM_sk_is_sorted(SSL_CIPHER, (st)) +# define sk_SSL_COMP_new(cmp) SKM_sk_new(SSL_COMP, (cmp)) +# define sk_SSL_COMP_new_null() SKM_sk_new_null(SSL_COMP) +# define sk_SSL_COMP_free(st) SKM_sk_free(SSL_COMP, (st)) +# define sk_SSL_COMP_num(st) SKM_sk_num(SSL_COMP, (st)) +# define sk_SSL_COMP_value(st, i) SKM_sk_value(SSL_COMP, (st), (i)) +# define sk_SSL_COMP_set(st, i, val) SKM_sk_set(SSL_COMP, (st), (i), (val)) +# define sk_SSL_COMP_zero(st) SKM_sk_zero(SSL_COMP, (st)) +# define sk_SSL_COMP_push(st, val) SKM_sk_push(SSL_COMP, (st), (val)) +# define sk_SSL_COMP_unshift(st, val) SKM_sk_unshift(SSL_COMP, (st), (val)) +# define sk_SSL_COMP_find(st, val) SKM_sk_find(SSL_COMP, (st), (val)) +# define sk_SSL_COMP_find_ex(st, val) SKM_sk_find_ex(SSL_COMP, (st), (val)) +# define sk_SSL_COMP_delete(st, i) SKM_sk_delete(SSL_COMP, (st), (i)) +# define sk_SSL_COMP_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_COMP, (st), (ptr)) +# define sk_SSL_COMP_insert(st, val, i) SKM_sk_insert(SSL_COMP, (st), (val), (i)) +# define sk_SSL_COMP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_COMP, (st), (cmp)) +# define sk_SSL_COMP_dup(st) SKM_sk_dup(SSL_COMP, st) +# define sk_SSL_COMP_pop_free(st, free_func) SKM_sk_pop_free(SSL_COMP, (st), (free_func)) +# define sk_SSL_COMP_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(SSL_COMP, (st), (copy_func), (free_func)) +# define sk_SSL_COMP_shift(st) SKM_sk_shift(SSL_COMP, (st)) +# define sk_SSL_COMP_pop(st) SKM_sk_pop(SSL_COMP, (st)) +# define sk_SSL_COMP_sort(st) SKM_sk_sort(SSL_COMP, (st)) +# define sk_SSL_COMP_is_sorted(st) SKM_sk_is_sorted(SSL_COMP, (st)) +# define sk_STACK_OF_X509_NAME_ENTRY_new(cmp) SKM_sk_new(STACK_OF_X509_NAME_ENTRY, (cmp)) +# define sk_STACK_OF_X509_NAME_ENTRY_new_null() SKM_sk_new_null(STACK_OF_X509_NAME_ENTRY) +# define sk_STACK_OF_X509_NAME_ENTRY_free(st) SKM_sk_free(STACK_OF_X509_NAME_ENTRY, (st)) +# define sk_STACK_OF_X509_NAME_ENTRY_num(st) SKM_sk_num(STACK_OF_X509_NAME_ENTRY, (st)) +# define sk_STACK_OF_X509_NAME_ENTRY_value(st, i) SKM_sk_value(STACK_OF_X509_NAME_ENTRY, (st), (i)) +# define sk_STACK_OF_X509_NAME_ENTRY_set(st, i, val) SKM_sk_set(STACK_OF_X509_NAME_ENTRY, (st), (i), (val)) +# define sk_STACK_OF_X509_NAME_ENTRY_zero(st) SKM_sk_zero(STACK_OF_X509_NAME_ENTRY, (st)) +# define sk_STACK_OF_X509_NAME_ENTRY_push(st, val) SKM_sk_push(STACK_OF_X509_NAME_ENTRY, (st), (val)) +# define sk_STACK_OF_X509_NAME_ENTRY_unshift(st, val) SKM_sk_unshift(STACK_OF_X509_NAME_ENTRY, (st), (val)) +# define sk_STACK_OF_X509_NAME_ENTRY_find(st, val) SKM_sk_find(STACK_OF_X509_NAME_ENTRY, (st), (val)) +# define sk_STACK_OF_X509_NAME_ENTRY_find_ex(st, val) SKM_sk_find_ex(STACK_OF_X509_NAME_ENTRY, (st), (val)) +# define sk_STACK_OF_X509_NAME_ENTRY_delete(st, i) SKM_sk_delete(STACK_OF_X509_NAME_ENTRY, (st), (i)) +# define sk_STACK_OF_X509_NAME_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(STACK_OF_X509_NAME_ENTRY, (st), (ptr)) +# define sk_STACK_OF_X509_NAME_ENTRY_insert(st, val, i) SKM_sk_insert(STACK_OF_X509_NAME_ENTRY, (st), (val), (i)) +# define sk_STACK_OF_X509_NAME_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STACK_OF_X509_NAME_ENTRY, (st), (cmp)) +# define sk_STACK_OF_X509_NAME_ENTRY_dup(st) SKM_sk_dup(STACK_OF_X509_NAME_ENTRY, st) +# define sk_STACK_OF_X509_NAME_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(STACK_OF_X509_NAME_ENTRY, (st), (free_func)) +# define sk_STACK_OF_X509_NAME_ENTRY_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(STACK_OF_X509_NAME_ENTRY, (st), (copy_func), (free_func)) +# define sk_STACK_OF_X509_NAME_ENTRY_shift(st) SKM_sk_shift(STACK_OF_X509_NAME_ENTRY, (st)) +# define sk_STACK_OF_X509_NAME_ENTRY_pop(st) SKM_sk_pop(STACK_OF_X509_NAME_ENTRY, (st)) +# define sk_STACK_OF_X509_NAME_ENTRY_sort(st) SKM_sk_sort(STACK_OF_X509_NAME_ENTRY, (st)) +# define sk_STACK_OF_X509_NAME_ENTRY_is_sorted(st) SKM_sk_is_sorted(STACK_OF_X509_NAME_ENTRY, (st)) +# define sk_STORE_ATTR_INFO_new(cmp) SKM_sk_new(STORE_ATTR_INFO, (cmp)) +# define sk_STORE_ATTR_INFO_new_null() SKM_sk_new_null(STORE_ATTR_INFO) +# define sk_STORE_ATTR_INFO_free(st) SKM_sk_free(STORE_ATTR_INFO, (st)) +# define sk_STORE_ATTR_INFO_num(st) SKM_sk_num(STORE_ATTR_INFO, (st)) +# define sk_STORE_ATTR_INFO_value(st, i) SKM_sk_value(STORE_ATTR_INFO, (st), (i)) +# define sk_STORE_ATTR_INFO_set(st, i, val) SKM_sk_set(STORE_ATTR_INFO, (st), (i), (val)) +# define sk_STORE_ATTR_INFO_zero(st) SKM_sk_zero(STORE_ATTR_INFO, (st)) +# define sk_STORE_ATTR_INFO_push(st, val) SKM_sk_push(STORE_ATTR_INFO, (st), (val)) +# define sk_STORE_ATTR_INFO_unshift(st, val) SKM_sk_unshift(STORE_ATTR_INFO, (st), (val)) +# define sk_STORE_ATTR_INFO_find(st, val) SKM_sk_find(STORE_ATTR_INFO, (st), (val)) +# define sk_STORE_ATTR_INFO_find_ex(st, val) SKM_sk_find_ex(STORE_ATTR_INFO, (st), (val)) +# define sk_STORE_ATTR_INFO_delete(st, i) SKM_sk_delete(STORE_ATTR_INFO, (st), (i)) +# define sk_STORE_ATTR_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(STORE_ATTR_INFO, (st), (ptr)) +# define sk_STORE_ATTR_INFO_insert(st, val, i) SKM_sk_insert(STORE_ATTR_INFO, (st), (val), (i)) +# define sk_STORE_ATTR_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STORE_ATTR_INFO, (st), (cmp)) +# define sk_STORE_ATTR_INFO_dup(st) SKM_sk_dup(STORE_ATTR_INFO, st) +# define sk_STORE_ATTR_INFO_pop_free(st, free_func) SKM_sk_pop_free(STORE_ATTR_INFO, (st), (free_func)) +# define sk_STORE_ATTR_INFO_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(STORE_ATTR_INFO, (st), (copy_func), (free_func)) +# define sk_STORE_ATTR_INFO_shift(st) SKM_sk_shift(STORE_ATTR_INFO, (st)) +# define sk_STORE_ATTR_INFO_pop(st) SKM_sk_pop(STORE_ATTR_INFO, (st)) +# define sk_STORE_ATTR_INFO_sort(st) SKM_sk_sort(STORE_ATTR_INFO, (st)) +# define sk_STORE_ATTR_INFO_is_sorted(st) SKM_sk_is_sorted(STORE_ATTR_INFO, (st)) +# define sk_STORE_OBJECT_new(cmp) SKM_sk_new(STORE_OBJECT, (cmp)) +# define sk_STORE_OBJECT_new_null() SKM_sk_new_null(STORE_OBJECT) +# define sk_STORE_OBJECT_free(st) SKM_sk_free(STORE_OBJECT, (st)) +# define sk_STORE_OBJECT_num(st) SKM_sk_num(STORE_OBJECT, (st)) +# define sk_STORE_OBJECT_value(st, i) SKM_sk_value(STORE_OBJECT, (st), (i)) +# define sk_STORE_OBJECT_set(st, i, val) SKM_sk_set(STORE_OBJECT, (st), (i), (val)) +# define sk_STORE_OBJECT_zero(st) SKM_sk_zero(STORE_OBJECT, (st)) +# define sk_STORE_OBJECT_push(st, val) SKM_sk_push(STORE_OBJECT, (st), (val)) +# define sk_STORE_OBJECT_unshift(st, val) SKM_sk_unshift(STORE_OBJECT, (st), (val)) +# define sk_STORE_OBJECT_find(st, val) SKM_sk_find(STORE_OBJECT, (st), (val)) +# define sk_STORE_OBJECT_find_ex(st, val) SKM_sk_find_ex(STORE_OBJECT, (st), (val)) +# define sk_STORE_OBJECT_delete(st, i) SKM_sk_delete(STORE_OBJECT, (st), (i)) +# define sk_STORE_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(STORE_OBJECT, (st), (ptr)) +# define sk_STORE_OBJECT_insert(st, val, i) SKM_sk_insert(STORE_OBJECT, (st), (val), (i)) +# define sk_STORE_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STORE_OBJECT, (st), (cmp)) +# define sk_STORE_OBJECT_dup(st) SKM_sk_dup(STORE_OBJECT, st) +# define sk_STORE_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(STORE_OBJECT, (st), (free_func)) +# define sk_STORE_OBJECT_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(STORE_OBJECT, (st), (copy_func), (free_func)) +# define sk_STORE_OBJECT_shift(st) SKM_sk_shift(STORE_OBJECT, (st)) +# define sk_STORE_OBJECT_pop(st) SKM_sk_pop(STORE_OBJECT, (st)) +# define sk_STORE_OBJECT_sort(st) SKM_sk_sort(STORE_OBJECT, (st)) +# define sk_STORE_OBJECT_is_sorted(st) SKM_sk_is_sorted(STORE_OBJECT, (st)) +# define sk_SXNETID_new(cmp) SKM_sk_new(SXNETID, (cmp)) +# define sk_SXNETID_new_null() SKM_sk_new_null(SXNETID) +# define sk_SXNETID_free(st) SKM_sk_free(SXNETID, (st)) +# define sk_SXNETID_num(st) SKM_sk_num(SXNETID, (st)) +# define sk_SXNETID_value(st, i) SKM_sk_value(SXNETID, (st), (i)) +# define sk_SXNETID_set(st, i, val) SKM_sk_set(SXNETID, (st), (i), (val)) +# define sk_SXNETID_zero(st) SKM_sk_zero(SXNETID, (st)) +# define sk_SXNETID_push(st, val) SKM_sk_push(SXNETID, (st), (val)) +# define sk_SXNETID_unshift(st, val) SKM_sk_unshift(SXNETID, (st), (val)) +# define sk_SXNETID_find(st, val) SKM_sk_find(SXNETID, (st), (val)) +# define sk_SXNETID_find_ex(st, val) SKM_sk_find_ex(SXNETID, (st), (val)) +# define sk_SXNETID_delete(st, i) SKM_sk_delete(SXNETID, (st), (i)) +# define sk_SXNETID_delete_ptr(st, ptr) SKM_sk_delete_ptr(SXNETID, (st), (ptr)) +# define sk_SXNETID_insert(st, val, i) SKM_sk_insert(SXNETID, (st), (val), (i)) +# define sk_SXNETID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SXNETID, (st), (cmp)) +# define sk_SXNETID_dup(st) SKM_sk_dup(SXNETID, st) +# define sk_SXNETID_pop_free(st, free_func) SKM_sk_pop_free(SXNETID, (st), (free_func)) +# define sk_SXNETID_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(SXNETID, (st), (copy_func), (free_func)) +# define sk_SXNETID_shift(st) SKM_sk_shift(SXNETID, (st)) +# define sk_SXNETID_pop(st) SKM_sk_pop(SXNETID, (st)) +# define sk_SXNETID_sort(st) SKM_sk_sort(SXNETID, (st)) +# define sk_SXNETID_is_sorted(st) SKM_sk_is_sorted(SXNETID, (st)) +# define sk_UI_STRING_new(cmp) SKM_sk_new(UI_STRING, (cmp)) +# define sk_UI_STRING_new_null() SKM_sk_new_null(UI_STRING) +# define sk_UI_STRING_free(st) SKM_sk_free(UI_STRING, (st)) +# define sk_UI_STRING_num(st) SKM_sk_num(UI_STRING, (st)) +# define sk_UI_STRING_value(st, i) SKM_sk_value(UI_STRING, (st), (i)) +# define sk_UI_STRING_set(st, i, val) SKM_sk_set(UI_STRING, (st), (i), (val)) +# define sk_UI_STRING_zero(st) SKM_sk_zero(UI_STRING, (st)) +# define sk_UI_STRING_push(st, val) SKM_sk_push(UI_STRING, (st), (val)) +# define sk_UI_STRING_unshift(st, val) SKM_sk_unshift(UI_STRING, (st), (val)) +# define sk_UI_STRING_find(st, val) SKM_sk_find(UI_STRING, (st), (val)) +# define sk_UI_STRING_find_ex(st, val) SKM_sk_find_ex(UI_STRING, (st), (val)) +# define sk_UI_STRING_delete(st, i) SKM_sk_delete(UI_STRING, (st), (i)) +# define sk_UI_STRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(UI_STRING, (st), (ptr)) +# define sk_UI_STRING_insert(st, val, i) SKM_sk_insert(UI_STRING, (st), (val), (i)) +# define sk_UI_STRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(UI_STRING, (st), (cmp)) +# define sk_UI_STRING_dup(st) SKM_sk_dup(UI_STRING, st) +# define sk_UI_STRING_pop_free(st, free_func) SKM_sk_pop_free(UI_STRING, (st), (free_func)) +# define sk_UI_STRING_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(UI_STRING, (st), (copy_func), (free_func)) +# define sk_UI_STRING_shift(st) SKM_sk_shift(UI_STRING, (st)) +# define sk_UI_STRING_pop(st) SKM_sk_pop(UI_STRING, (st)) +# define sk_UI_STRING_sort(st) SKM_sk_sort(UI_STRING, (st)) +# define sk_UI_STRING_is_sorted(st) SKM_sk_is_sorted(UI_STRING, (st)) +# define sk_X509_new(cmp) SKM_sk_new(X509, (cmp)) +# define sk_X509_new_null() SKM_sk_new_null(X509) +# define sk_X509_free(st) SKM_sk_free(X509, (st)) +# define sk_X509_num(st) SKM_sk_num(X509, (st)) +# define sk_X509_value(st, i) SKM_sk_value(X509, (st), (i)) +# define sk_X509_set(st, i, val) SKM_sk_set(X509, (st), (i), (val)) +# define sk_X509_zero(st) SKM_sk_zero(X509, (st)) +# define sk_X509_push(st, val) SKM_sk_push(X509, (st), (val)) +# define sk_X509_unshift(st, val) SKM_sk_unshift(X509, (st), (val)) +# define sk_X509_find(st, val) SKM_sk_find(X509, (st), (val)) +# define sk_X509_find_ex(st, val) SKM_sk_find_ex(X509, (st), (val)) +# define sk_X509_delete(st, i) SKM_sk_delete(X509, (st), (i)) +# define sk_X509_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509, (st), (ptr)) +# define sk_X509_insert(st, val, i) SKM_sk_insert(X509, (st), (val), (i)) +# define sk_X509_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509, (st), (cmp)) +# define sk_X509_dup(st) SKM_sk_dup(X509, st) +# define sk_X509_pop_free(st, free_func) SKM_sk_pop_free(X509, (st), (free_func)) +# define sk_X509_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509, (st), (copy_func), (free_func)) +# define sk_X509_shift(st) SKM_sk_shift(X509, (st)) +# define sk_X509_pop(st) SKM_sk_pop(X509, (st)) +# define sk_X509_sort(st) SKM_sk_sort(X509, (st)) +# define sk_X509_is_sorted(st) SKM_sk_is_sorted(X509, (st)) +# define sk_X509V3_EXT_METHOD_new(cmp) SKM_sk_new(X509V3_EXT_METHOD, (cmp)) +# define sk_X509V3_EXT_METHOD_new_null() SKM_sk_new_null(X509V3_EXT_METHOD) +# define sk_X509V3_EXT_METHOD_free(st) SKM_sk_free(X509V3_EXT_METHOD, (st)) +# define sk_X509V3_EXT_METHOD_num(st) SKM_sk_num(X509V3_EXT_METHOD, (st)) +# define sk_X509V3_EXT_METHOD_value(st, i) SKM_sk_value(X509V3_EXT_METHOD, (st), (i)) +# define sk_X509V3_EXT_METHOD_set(st, i, val) SKM_sk_set(X509V3_EXT_METHOD, (st), (i), (val)) +# define sk_X509V3_EXT_METHOD_zero(st) SKM_sk_zero(X509V3_EXT_METHOD, (st)) +# define sk_X509V3_EXT_METHOD_push(st, val) SKM_sk_push(X509V3_EXT_METHOD, (st), (val)) +# define sk_X509V3_EXT_METHOD_unshift(st, val) SKM_sk_unshift(X509V3_EXT_METHOD, (st), (val)) +# define sk_X509V3_EXT_METHOD_find(st, val) SKM_sk_find(X509V3_EXT_METHOD, (st), (val)) +# define sk_X509V3_EXT_METHOD_find_ex(st, val) SKM_sk_find_ex(X509V3_EXT_METHOD, (st), (val)) +# define sk_X509V3_EXT_METHOD_delete(st, i) SKM_sk_delete(X509V3_EXT_METHOD, (st), (i)) +# define sk_X509V3_EXT_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509V3_EXT_METHOD, (st), (ptr)) +# define sk_X509V3_EXT_METHOD_insert(st, val, i) SKM_sk_insert(X509V3_EXT_METHOD, (st), (val), (i)) +# define sk_X509V3_EXT_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509V3_EXT_METHOD, (st), (cmp)) +# define sk_X509V3_EXT_METHOD_dup(st) SKM_sk_dup(X509V3_EXT_METHOD, st) +# define sk_X509V3_EXT_METHOD_pop_free(st, free_func) SKM_sk_pop_free(X509V3_EXT_METHOD, (st), (free_func)) +# define sk_X509V3_EXT_METHOD_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509V3_EXT_METHOD, (st), (copy_func), (free_func)) +# define sk_X509V3_EXT_METHOD_shift(st) SKM_sk_shift(X509V3_EXT_METHOD, (st)) +# define sk_X509V3_EXT_METHOD_pop(st) SKM_sk_pop(X509V3_EXT_METHOD, (st)) +# define sk_X509V3_EXT_METHOD_sort(st) SKM_sk_sort(X509V3_EXT_METHOD, (st)) +# define sk_X509V3_EXT_METHOD_is_sorted(st) SKM_sk_is_sorted(X509V3_EXT_METHOD, (st)) +# define sk_X509_ALGOR_new(cmp) SKM_sk_new(X509_ALGOR, (cmp)) +# define sk_X509_ALGOR_new_null() SKM_sk_new_null(X509_ALGOR) +# define sk_X509_ALGOR_free(st) SKM_sk_free(X509_ALGOR, (st)) +# define sk_X509_ALGOR_num(st) SKM_sk_num(X509_ALGOR, (st)) +# define sk_X509_ALGOR_value(st, i) SKM_sk_value(X509_ALGOR, (st), (i)) +# define sk_X509_ALGOR_set(st, i, val) SKM_sk_set(X509_ALGOR, (st), (i), (val)) +# define sk_X509_ALGOR_zero(st) SKM_sk_zero(X509_ALGOR, (st)) +# define sk_X509_ALGOR_push(st, val) SKM_sk_push(X509_ALGOR, (st), (val)) +# define sk_X509_ALGOR_unshift(st, val) SKM_sk_unshift(X509_ALGOR, (st), (val)) +# define sk_X509_ALGOR_find(st, val) SKM_sk_find(X509_ALGOR, (st), (val)) +# define sk_X509_ALGOR_find_ex(st, val) SKM_sk_find_ex(X509_ALGOR, (st), (val)) +# define sk_X509_ALGOR_delete(st, i) SKM_sk_delete(X509_ALGOR, (st), (i)) +# define sk_X509_ALGOR_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ALGOR, (st), (ptr)) +# define sk_X509_ALGOR_insert(st, val, i) SKM_sk_insert(X509_ALGOR, (st), (val), (i)) +# define sk_X509_ALGOR_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ALGOR, (st), (cmp)) +# define sk_X509_ALGOR_dup(st) SKM_sk_dup(X509_ALGOR, st) +# define sk_X509_ALGOR_pop_free(st, free_func) SKM_sk_pop_free(X509_ALGOR, (st), (free_func)) +# define sk_X509_ALGOR_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_ALGOR, (st), (copy_func), (free_func)) +# define sk_X509_ALGOR_shift(st) SKM_sk_shift(X509_ALGOR, (st)) +# define sk_X509_ALGOR_pop(st) SKM_sk_pop(X509_ALGOR, (st)) +# define sk_X509_ALGOR_sort(st) SKM_sk_sort(X509_ALGOR, (st)) +# define sk_X509_ALGOR_is_sorted(st) SKM_sk_is_sorted(X509_ALGOR, (st)) +# define sk_X509_ATTRIBUTE_new(cmp) SKM_sk_new(X509_ATTRIBUTE, (cmp)) +# define sk_X509_ATTRIBUTE_new_null() SKM_sk_new_null(X509_ATTRIBUTE) +# define sk_X509_ATTRIBUTE_free(st) SKM_sk_free(X509_ATTRIBUTE, (st)) +# define sk_X509_ATTRIBUTE_num(st) SKM_sk_num(X509_ATTRIBUTE, (st)) +# define sk_X509_ATTRIBUTE_value(st, i) SKM_sk_value(X509_ATTRIBUTE, (st), (i)) +# define sk_X509_ATTRIBUTE_set(st, i, val) SKM_sk_set(X509_ATTRIBUTE, (st), (i), (val)) +# define sk_X509_ATTRIBUTE_zero(st) SKM_sk_zero(X509_ATTRIBUTE, (st)) +# define sk_X509_ATTRIBUTE_push(st, val) SKM_sk_push(X509_ATTRIBUTE, (st), (val)) +# define sk_X509_ATTRIBUTE_unshift(st, val) SKM_sk_unshift(X509_ATTRIBUTE, (st), (val)) +# define sk_X509_ATTRIBUTE_find(st, val) SKM_sk_find(X509_ATTRIBUTE, (st), (val)) +# define sk_X509_ATTRIBUTE_find_ex(st, val) SKM_sk_find_ex(X509_ATTRIBUTE, (st), (val)) +# define sk_X509_ATTRIBUTE_delete(st, i) SKM_sk_delete(X509_ATTRIBUTE, (st), (i)) +# define sk_X509_ATTRIBUTE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ATTRIBUTE, (st), (ptr)) +# define sk_X509_ATTRIBUTE_insert(st, val, i) SKM_sk_insert(X509_ATTRIBUTE, (st), (val), (i)) +# define sk_X509_ATTRIBUTE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ATTRIBUTE, (st), (cmp)) +# define sk_X509_ATTRIBUTE_dup(st) SKM_sk_dup(X509_ATTRIBUTE, st) +# define sk_X509_ATTRIBUTE_pop_free(st, free_func) SKM_sk_pop_free(X509_ATTRIBUTE, (st), (free_func)) +# define sk_X509_ATTRIBUTE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_ATTRIBUTE, (st), (copy_func), (free_func)) +# define sk_X509_ATTRIBUTE_shift(st) SKM_sk_shift(X509_ATTRIBUTE, (st)) +# define sk_X509_ATTRIBUTE_pop(st) SKM_sk_pop(X509_ATTRIBUTE, (st)) +# define sk_X509_ATTRIBUTE_sort(st) SKM_sk_sort(X509_ATTRIBUTE, (st)) +# define sk_X509_ATTRIBUTE_is_sorted(st) SKM_sk_is_sorted(X509_ATTRIBUTE, (st)) +# define sk_X509_CRL_new(cmp) SKM_sk_new(X509_CRL, (cmp)) +# define sk_X509_CRL_new_null() SKM_sk_new_null(X509_CRL) +# define sk_X509_CRL_free(st) SKM_sk_free(X509_CRL, (st)) +# define sk_X509_CRL_num(st) SKM_sk_num(X509_CRL, (st)) +# define sk_X509_CRL_value(st, i) SKM_sk_value(X509_CRL, (st), (i)) +# define sk_X509_CRL_set(st, i, val) SKM_sk_set(X509_CRL, (st), (i), (val)) +# define sk_X509_CRL_zero(st) SKM_sk_zero(X509_CRL, (st)) +# define sk_X509_CRL_push(st, val) SKM_sk_push(X509_CRL, (st), (val)) +# define sk_X509_CRL_unshift(st, val) SKM_sk_unshift(X509_CRL, (st), (val)) +# define sk_X509_CRL_find(st, val) SKM_sk_find(X509_CRL, (st), (val)) +# define sk_X509_CRL_find_ex(st, val) SKM_sk_find_ex(X509_CRL, (st), (val)) +# define sk_X509_CRL_delete(st, i) SKM_sk_delete(X509_CRL, (st), (i)) +# define sk_X509_CRL_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_CRL, (st), (ptr)) +# define sk_X509_CRL_insert(st, val, i) SKM_sk_insert(X509_CRL, (st), (val), (i)) +# define sk_X509_CRL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_CRL, (st), (cmp)) +# define sk_X509_CRL_dup(st) SKM_sk_dup(X509_CRL, st) +# define sk_X509_CRL_pop_free(st, free_func) SKM_sk_pop_free(X509_CRL, (st), (free_func)) +# define sk_X509_CRL_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_CRL, (st), (copy_func), (free_func)) +# define sk_X509_CRL_shift(st) SKM_sk_shift(X509_CRL, (st)) +# define sk_X509_CRL_pop(st) SKM_sk_pop(X509_CRL, (st)) +# define sk_X509_CRL_sort(st) SKM_sk_sort(X509_CRL, (st)) +# define sk_X509_CRL_is_sorted(st) SKM_sk_is_sorted(X509_CRL, (st)) +# define sk_X509_EXTENSION_new(cmp) SKM_sk_new(X509_EXTENSION, (cmp)) +# define sk_X509_EXTENSION_new_null() SKM_sk_new_null(X509_EXTENSION) +# define sk_X509_EXTENSION_free(st) SKM_sk_free(X509_EXTENSION, (st)) +# define sk_X509_EXTENSION_num(st) SKM_sk_num(X509_EXTENSION, (st)) +# define sk_X509_EXTENSION_value(st, i) SKM_sk_value(X509_EXTENSION, (st), (i)) +# define sk_X509_EXTENSION_set(st, i, val) SKM_sk_set(X509_EXTENSION, (st), (i), (val)) +# define sk_X509_EXTENSION_zero(st) SKM_sk_zero(X509_EXTENSION, (st)) +# define sk_X509_EXTENSION_push(st, val) SKM_sk_push(X509_EXTENSION, (st), (val)) +# define sk_X509_EXTENSION_unshift(st, val) SKM_sk_unshift(X509_EXTENSION, (st), (val)) +# define sk_X509_EXTENSION_find(st, val) SKM_sk_find(X509_EXTENSION, (st), (val)) +# define sk_X509_EXTENSION_find_ex(st, val) SKM_sk_find_ex(X509_EXTENSION, (st), (val)) +# define sk_X509_EXTENSION_delete(st, i) SKM_sk_delete(X509_EXTENSION, (st), (i)) +# define sk_X509_EXTENSION_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_EXTENSION, (st), (ptr)) +# define sk_X509_EXTENSION_insert(st, val, i) SKM_sk_insert(X509_EXTENSION, (st), (val), (i)) +# define sk_X509_EXTENSION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_EXTENSION, (st), (cmp)) +# define sk_X509_EXTENSION_dup(st) SKM_sk_dup(X509_EXTENSION, st) +# define sk_X509_EXTENSION_pop_free(st, free_func) SKM_sk_pop_free(X509_EXTENSION, (st), (free_func)) +# define sk_X509_EXTENSION_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_EXTENSION, (st), (copy_func), (free_func)) +# define sk_X509_EXTENSION_shift(st) SKM_sk_shift(X509_EXTENSION, (st)) +# define sk_X509_EXTENSION_pop(st) SKM_sk_pop(X509_EXTENSION, (st)) +# define sk_X509_EXTENSION_sort(st) SKM_sk_sort(X509_EXTENSION, (st)) +# define sk_X509_EXTENSION_is_sorted(st) SKM_sk_is_sorted(X509_EXTENSION, (st)) +# define sk_X509_INFO_new(cmp) SKM_sk_new(X509_INFO, (cmp)) +# define sk_X509_INFO_new_null() SKM_sk_new_null(X509_INFO) +# define sk_X509_INFO_free(st) SKM_sk_free(X509_INFO, (st)) +# define sk_X509_INFO_num(st) SKM_sk_num(X509_INFO, (st)) +# define sk_X509_INFO_value(st, i) SKM_sk_value(X509_INFO, (st), (i)) +# define sk_X509_INFO_set(st, i, val) SKM_sk_set(X509_INFO, (st), (i), (val)) +# define sk_X509_INFO_zero(st) SKM_sk_zero(X509_INFO, (st)) +# define sk_X509_INFO_push(st, val) SKM_sk_push(X509_INFO, (st), (val)) +# define sk_X509_INFO_unshift(st, val) SKM_sk_unshift(X509_INFO, (st), (val)) +# define sk_X509_INFO_find(st, val) SKM_sk_find(X509_INFO, (st), (val)) +# define sk_X509_INFO_find_ex(st, val) SKM_sk_find_ex(X509_INFO, (st), (val)) +# define sk_X509_INFO_delete(st, i) SKM_sk_delete(X509_INFO, (st), (i)) +# define sk_X509_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_INFO, (st), (ptr)) +# define sk_X509_INFO_insert(st, val, i) SKM_sk_insert(X509_INFO, (st), (val), (i)) +# define sk_X509_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_INFO, (st), (cmp)) +# define sk_X509_INFO_dup(st) SKM_sk_dup(X509_INFO, st) +# define sk_X509_INFO_pop_free(st, free_func) SKM_sk_pop_free(X509_INFO, (st), (free_func)) +# define sk_X509_INFO_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_INFO, (st), (copy_func), (free_func)) +# define sk_X509_INFO_shift(st) SKM_sk_shift(X509_INFO, (st)) +# define sk_X509_INFO_pop(st) SKM_sk_pop(X509_INFO, (st)) +# define sk_X509_INFO_sort(st) SKM_sk_sort(X509_INFO, (st)) +# define sk_X509_INFO_is_sorted(st) SKM_sk_is_sorted(X509_INFO, (st)) +# define sk_X509_LOOKUP_new(cmp) SKM_sk_new(X509_LOOKUP, (cmp)) +# define sk_X509_LOOKUP_new_null() SKM_sk_new_null(X509_LOOKUP) +# define sk_X509_LOOKUP_free(st) SKM_sk_free(X509_LOOKUP, (st)) +# define sk_X509_LOOKUP_num(st) SKM_sk_num(X509_LOOKUP, (st)) +# define sk_X509_LOOKUP_value(st, i) SKM_sk_value(X509_LOOKUP, (st), (i)) +# define sk_X509_LOOKUP_set(st, i, val) SKM_sk_set(X509_LOOKUP, (st), (i), (val)) +# define sk_X509_LOOKUP_zero(st) SKM_sk_zero(X509_LOOKUP, (st)) +# define sk_X509_LOOKUP_push(st, val) SKM_sk_push(X509_LOOKUP, (st), (val)) +# define sk_X509_LOOKUP_unshift(st, val) SKM_sk_unshift(X509_LOOKUP, (st), (val)) +# define sk_X509_LOOKUP_find(st, val) SKM_sk_find(X509_LOOKUP, (st), (val)) +# define sk_X509_LOOKUP_find_ex(st, val) SKM_sk_find_ex(X509_LOOKUP, (st), (val)) +# define sk_X509_LOOKUP_delete(st, i) SKM_sk_delete(X509_LOOKUP, (st), (i)) +# define sk_X509_LOOKUP_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_LOOKUP, (st), (ptr)) +# define sk_X509_LOOKUP_insert(st, val, i) SKM_sk_insert(X509_LOOKUP, (st), (val), (i)) +# define sk_X509_LOOKUP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_LOOKUP, (st), (cmp)) +# define sk_X509_LOOKUP_dup(st) SKM_sk_dup(X509_LOOKUP, st) +# define sk_X509_LOOKUP_pop_free(st, free_func) SKM_sk_pop_free(X509_LOOKUP, (st), (free_func)) +# define sk_X509_LOOKUP_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_LOOKUP, (st), (copy_func), (free_func)) +# define sk_X509_LOOKUP_shift(st) SKM_sk_shift(X509_LOOKUP, (st)) +# define sk_X509_LOOKUP_pop(st) SKM_sk_pop(X509_LOOKUP, (st)) +# define sk_X509_LOOKUP_sort(st) SKM_sk_sort(X509_LOOKUP, (st)) +# define sk_X509_LOOKUP_is_sorted(st) SKM_sk_is_sorted(X509_LOOKUP, (st)) +# define sk_X509_NAME_new(cmp) SKM_sk_new(X509_NAME, (cmp)) +# define sk_X509_NAME_new_null() SKM_sk_new_null(X509_NAME) +# define sk_X509_NAME_free(st) SKM_sk_free(X509_NAME, (st)) +# define sk_X509_NAME_num(st) SKM_sk_num(X509_NAME, (st)) +# define sk_X509_NAME_value(st, i) SKM_sk_value(X509_NAME, (st), (i)) +# define sk_X509_NAME_set(st, i, val) SKM_sk_set(X509_NAME, (st), (i), (val)) +# define sk_X509_NAME_zero(st) SKM_sk_zero(X509_NAME, (st)) +# define sk_X509_NAME_push(st, val) SKM_sk_push(X509_NAME, (st), (val)) +# define sk_X509_NAME_unshift(st, val) SKM_sk_unshift(X509_NAME, (st), (val)) +# define sk_X509_NAME_find(st, val) SKM_sk_find(X509_NAME, (st), (val)) +# define sk_X509_NAME_find_ex(st, val) SKM_sk_find_ex(X509_NAME, (st), (val)) +# define sk_X509_NAME_delete(st, i) SKM_sk_delete(X509_NAME, (st), (i)) +# define sk_X509_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME, (st), (ptr)) +# define sk_X509_NAME_insert(st, val, i) SKM_sk_insert(X509_NAME, (st), (val), (i)) +# define sk_X509_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME, (st), (cmp)) +# define sk_X509_NAME_dup(st) SKM_sk_dup(X509_NAME, st) +# define sk_X509_NAME_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME, (st), (free_func)) +# define sk_X509_NAME_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_NAME, (st), (copy_func), (free_func)) +# define sk_X509_NAME_shift(st) SKM_sk_shift(X509_NAME, (st)) +# define sk_X509_NAME_pop(st) SKM_sk_pop(X509_NAME, (st)) +# define sk_X509_NAME_sort(st) SKM_sk_sort(X509_NAME, (st)) +# define sk_X509_NAME_is_sorted(st) SKM_sk_is_sorted(X509_NAME, (st)) +# define sk_X509_NAME_ENTRY_new(cmp) SKM_sk_new(X509_NAME_ENTRY, (cmp)) +# define sk_X509_NAME_ENTRY_new_null() SKM_sk_new_null(X509_NAME_ENTRY) +# define sk_X509_NAME_ENTRY_free(st) SKM_sk_free(X509_NAME_ENTRY, (st)) +# define sk_X509_NAME_ENTRY_num(st) SKM_sk_num(X509_NAME_ENTRY, (st)) +# define sk_X509_NAME_ENTRY_value(st, i) SKM_sk_value(X509_NAME_ENTRY, (st), (i)) +# define sk_X509_NAME_ENTRY_set(st, i, val) SKM_sk_set(X509_NAME_ENTRY, (st), (i), (val)) +# define sk_X509_NAME_ENTRY_zero(st) SKM_sk_zero(X509_NAME_ENTRY, (st)) +# define sk_X509_NAME_ENTRY_push(st, val) SKM_sk_push(X509_NAME_ENTRY, (st), (val)) +# define sk_X509_NAME_ENTRY_unshift(st, val) SKM_sk_unshift(X509_NAME_ENTRY, (st), (val)) +# define sk_X509_NAME_ENTRY_find(st, val) SKM_sk_find(X509_NAME_ENTRY, (st), (val)) +# define sk_X509_NAME_ENTRY_find_ex(st, val) SKM_sk_find_ex(X509_NAME_ENTRY, (st), (val)) +# define sk_X509_NAME_ENTRY_delete(st, i) SKM_sk_delete(X509_NAME_ENTRY, (st), (i)) +# define sk_X509_NAME_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME_ENTRY, (st), (ptr)) +# define sk_X509_NAME_ENTRY_insert(st, val, i) SKM_sk_insert(X509_NAME_ENTRY, (st), (val), (i)) +# define sk_X509_NAME_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME_ENTRY, (st), (cmp)) +# define sk_X509_NAME_ENTRY_dup(st) SKM_sk_dup(X509_NAME_ENTRY, st) +# define sk_X509_NAME_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME_ENTRY, (st), (free_func)) +# define sk_X509_NAME_ENTRY_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_NAME_ENTRY, (st), (copy_func), (free_func)) +# define sk_X509_NAME_ENTRY_shift(st) SKM_sk_shift(X509_NAME_ENTRY, (st)) +# define sk_X509_NAME_ENTRY_pop(st) SKM_sk_pop(X509_NAME_ENTRY, (st)) +# define sk_X509_NAME_ENTRY_sort(st) SKM_sk_sort(X509_NAME_ENTRY, (st)) +# define sk_X509_NAME_ENTRY_is_sorted(st) SKM_sk_is_sorted(X509_NAME_ENTRY, (st)) +# define sk_X509_OBJECT_new(cmp) SKM_sk_new(X509_OBJECT, (cmp)) +# define sk_X509_OBJECT_new_null() SKM_sk_new_null(X509_OBJECT) +# define sk_X509_OBJECT_free(st) SKM_sk_free(X509_OBJECT, (st)) +# define sk_X509_OBJECT_num(st) SKM_sk_num(X509_OBJECT, (st)) +# define sk_X509_OBJECT_value(st, i) SKM_sk_value(X509_OBJECT, (st), (i)) +# define sk_X509_OBJECT_set(st, i, val) SKM_sk_set(X509_OBJECT, (st), (i), (val)) +# define sk_X509_OBJECT_zero(st) SKM_sk_zero(X509_OBJECT, (st)) +# define sk_X509_OBJECT_push(st, val) SKM_sk_push(X509_OBJECT, (st), (val)) +# define sk_X509_OBJECT_unshift(st, val) SKM_sk_unshift(X509_OBJECT, (st), (val)) +# define sk_X509_OBJECT_find(st, val) SKM_sk_find(X509_OBJECT, (st), (val)) +# define sk_X509_OBJECT_find_ex(st, val) SKM_sk_find_ex(X509_OBJECT, (st), (val)) +# define sk_X509_OBJECT_delete(st, i) SKM_sk_delete(X509_OBJECT, (st), (i)) +# define sk_X509_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_OBJECT, (st), (ptr)) +# define sk_X509_OBJECT_insert(st, val, i) SKM_sk_insert(X509_OBJECT, (st), (val), (i)) +# define sk_X509_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_OBJECT, (st), (cmp)) +# define sk_X509_OBJECT_dup(st) SKM_sk_dup(X509_OBJECT, st) +# define sk_X509_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(X509_OBJECT, (st), (free_func)) +# define sk_X509_OBJECT_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_OBJECT, (st), (copy_func), (free_func)) +# define sk_X509_OBJECT_shift(st) SKM_sk_shift(X509_OBJECT, (st)) +# define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st)) +# define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st)) +# define sk_X509_OBJECT_is_sorted(st) SKM_sk_is_sorted(X509_OBJECT, (st)) +# define sk_X509_POLICY_DATA_new(cmp) SKM_sk_new(X509_POLICY_DATA, (cmp)) +# define sk_X509_POLICY_DATA_new_null() SKM_sk_new_null(X509_POLICY_DATA) +# define sk_X509_POLICY_DATA_free(st) SKM_sk_free(X509_POLICY_DATA, (st)) +# define sk_X509_POLICY_DATA_num(st) SKM_sk_num(X509_POLICY_DATA, (st)) +# define sk_X509_POLICY_DATA_value(st, i) SKM_sk_value(X509_POLICY_DATA, (st), (i)) +# define sk_X509_POLICY_DATA_set(st, i, val) SKM_sk_set(X509_POLICY_DATA, (st), (i), (val)) +# define sk_X509_POLICY_DATA_zero(st) SKM_sk_zero(X509_POLICY_DATA, (st)) +# define sk_X509_POLICY_DATA_push(st, val) SKM_sk_push(X509_POLICY_DATA, (st), (val)) +# define sk_X509_POLICY_DATA_unshift(st, val) SKM_sk_unshift(X509_POLICY_DATA, (st), (val)) +# define sk_X509_POLICY_DATA_find(st, val) SKM_sk_find(X509_POLICY_DATA, (st), (val)) +# define sk_X509_POLICY_DATA_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_DATA, (st), (val)) +# define sk_X509_POLICY_DATA_delete(st, i) SKM_sk_delete(X509_POLICY_DATA, (st), (i)) +# define sk_X509_POLICY_DATA_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_DATA, (st), (ptr)) +# define sk_X509_POLICY_DATA_insert(st, val, i) SKM_sk_insert(X509_POLICY_DATA, (st), (val), (i)) +# define sk_X509_POLICY_DATA_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_DATA, (st), (cmp)) +# define sk_X509_POLICY_DATA_dup(st) SKM_sk_dup(X509_POLICY_DATA, st) +# define sk_X509_POLICY_DATA_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_DATA, (st), (free_func)) +# define sk_X509_POLICY_DATA_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_POLICY_DATA, (st), (copy_func), (free_func)) +# define sk_X509_POLICY_DATA_shift(st) SKM_sk_shift(X509_POLICY_DATA, (st)) +# define sk_X509_POLICY_DATA_pop(st) SKM_sk_pop(X509_POLICY_DATA, (st)) +# define sk_X509_POLICY_DATA_sort(st) SKM_sk_sort(X509_POLICY_DATA, (st)) +# define sk_X509_POLICY_DATA_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_DATA, (st)) +# define sk_X509_POLICY_NODE_new(cmp) SKM_sk_new(X509_POLICY_NODE, (cmp)) +# define sk_X509_POLICY_NODE_new_null() SKM_sk_new_null(X509_POLICY_NODE) +# define sk_X509_POLICY_NODE_free(st) SKM_sk_free(X509_POLICY_NODE, (st)) +# define sk_X509_POLICY_NODE_num(st) SKM_sk_num(X509_POLICY_NODE, (st)) +# define sk_X509_POLICY_NODE_value(st, i) SKM_sk_value(X509_POLICY_NODE, (st), (i)) +# define sk_X509_POLICY_NODE_set(st, i, val) SKM_sk_set(X509_POLICY_NODE, (st), (i), (val)) +# define sk_X509_POLICY_NODE_zero(st) SKM_sk_zero(X509_POLICY_NODE, (st)) +# define sk_X509_POLICY_NODE_push(st, val) SKM_sk_push(X509_POLICY_NODE, (st), (val)) +# define sk_X509_POLICY_NODE_unshift(st, val) SKM_sk_unshift(X509_POLICY_NODE, (st), (val)) +# define sk_X509_POLICY_NODE_find(st, val) SKM_sk_find(X509_POLICY_NODE, (st), (val)) +# define sk_X509_POLICY_NODE_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_NODE, (st), (val)) +# define sk_X509_POLICY_NODE_delete(st, i) SKM_sk_delete(X509_POLICY_NODE, (st), (i)) +# define sk_X509_POLICY_NODE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_NODE, (st), (ptr)) +# define sk_X509_POLICY_NODE_insert(st, val, i) SKM_sk_insert(X509_POLICY_NODE, (st), (val), (i)) +# define sk_X509_POLICY_NODE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_NODE, (st), (cmp)) +# define sk_X509_POLICY_NODE_dup(st) SKM_sk_dup(X509_POLICY_NODE, st) +# define sk_X509_POLICY_NODE_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_NODE, (st), (free_func)) +# define sk_X509_POLICY_NODE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_POLICY_NODE, (st), (copy_func), (free_func)) +# define sk_X509_POLICY_NODE_shift(st) SKM_sk_shift(X509_POLICY_NODE, (st)) +# define sk_X509_POLICY_NODE_pop(st) SKM_sk_pop(X509_POLICY_NODE, (st)) +# define sk_X509_POLICY_NODE_sort(st) SKM_sk_sort(X509_POLICY_NODE, (st)) +# define sk_X509_POLICY_NODE_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_NODE, (st)) +# define sk_X509_PURPOSE_new(cmp) SKM_sk_new(X509_PURPOSE, (cmp)) +# define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE) +# define sk_X509_PURPOSE_free(st) SKM_sk_free(X509_PURPOSE, (st)) +# define sk_X509_PURPOSE_num(st) SKM_sk_num(X509_PURPOSE, (st)) +# define sk_X509_PURPOSE_value(st, i) SKM_sk_value(X509_PURPOSE, (st), (i)) +# define sk_X509_PURPOSE_set(st, i, val) SKM_sk_set(X509_PURPOSE, (st), (i), (val)) +# define sk_X509_PURPOSE_zero(st) SKM_sk_zero(X509_PURPOSE, (st)) +# define sk_X509_PURPOSE_push(st, val) SKM_sk_push(X509_PURPOSE, (st), (val)) +# define sk_X509_PURPOSE_unshift(st, val) SKM_sk_unshift(X509_PURPOSE, (st), (val)) +# define sk_X509_PURPOSE_find(st, val) SKM_sk_find(X509_PURPOSE, (st), (val)) +# define sk_X509_PURPOSE_find_ex(st, val) SKM_sk_find_ex(X509_PURPOSE, (st), (val)) +# define sk_X509_PURPOSE_delete(st, i) SKM_sk_delete(X509_PURPOSE, (st), (i)) +# define sk_X509_PURPOSE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_PURPOSE, (st), (ptr)) +# define sk_X509_PURPOSE_insert(st, val, i) SKM_sk_insert(X509_PURPOSE, (st), (val), (i)) +# define sk_X509_PURPOSE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_PURPOSE, (st), (cmp)) +# define sk_X509_PURPOSE_dup(st) SKM_sk_dup(X509_PURPOSE, st) +# define sk_X509_PURPOSE_pop_free(st, free_func) SKM_sk_pop_free(X509_PURPOSE, (st), (free_func)) +# define sk_X509_PURPOSE_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_PURPOSE, (st), (copy_func), (free_func)) +# define sk_X509_PURPOSE_shift(st) SKM_sk_shift(X509_PURPOSE, (st)) +# define sk_X509_PURPOSE_pop(st) SKM_sk_pop(X509_PURPOSE, (st)) +# define sk_X509_PURPOSE_sort(st) SKM_sk_sort(X509_PURPOSE, (st)) +# define sk_X509_PURPOSE_is_sorted(st) SKM_sk_is_sorted(X509_PURPOSE, (st)) +# define sk_X509_REVOKED_new(cmp) SKM_sk_new(X509_REVOKED, (cmp)) +# define sk_X509_REVOKED_new_null() SKM_sk_new_null(X509_REVOKED) +# define sk_X509_REVOKED_free(st) SKM_sk_free(X509_REVOKED, (st)) +# define sk_X509_REVOKED_num(st) SKM_sk_num(X509_REVOKED, (st)) +# define sk_X509_REVOKED_value(st, i) SKM_sk_value(X509_REVOKED, (st), (i)) +# define sk_X509_REVOKED_set(st, i, val) SKM_sk_set(X509_REVOKED, (st), (i), (val)) +# define sk_X509_REVOKED_zero(st) SKM_sk_zero(X509_REVOKED, (st)) +# define sk_X509_REVOKED_push(st, val) SKM_sk_push(X509_REVOKED, (st), (val)) +# define sk_X509_REVOKED_unshift(st, val) SKM_sk_unshift(X509_REVOKED, (st), (val)) +# define sk_X509_REVOKED_find(st, val) SKM_sk_find(X509_REVOKED, (st), (val)) +# define sk_X509_REVOKED_find_ex(st, val) SKM_sk_find_ex(X509_REVOKED, (st), (val)) +# define sk_X509_REVOKED_delete(st, i) SKM_sk_delete(X509_REVOKED, (st), (i)) +# define sk_X509_REVOKED_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_REVOKED, (st), (ptr)) +# define sk_X509_REVOKED_insert(st, val, i) SKM_sk_insert(X509_REVOKED, (st), (val), (i)) +# define sk_X509_REVOKED_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_REVOKED, (st), (cmp)) +# define sk_X509_REVOKED_dup(st) SKM_sk_dup(X509_REVOKED, st) +# define sk_X509_REVOKED_pop_free(st, free_func) SKM_sk_pop_free(X509_REVOKED, (st), (free_func)) +# define sk_X509_REVOKED_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_REVOKED, (st), (copy_func), (free_func)) +# define sk_X509_REVOKED_shift(st) SKM_sk_shift(X509_REVOKED, (st)) +# define sk_X509_REVOKED_pop(st) SKM_sk_pop(X509_REVOKED, (st)) +# define sk_X509_REVOKED_sort(st) SKM_sk_sort(X509_REVOKED, (st)) +# define sk_X509_REVOKED_is_sorted(st) SKM_sk_is_sorted(X509_REVOKED, (st)) +# define sk_X509_TRUST_new(cmp) SKM_sk_new(X509_TRUST, (cmp)) +# define sk_X509_TRUST_new_null() SKM_sk_new_null(X509_TRUST) +# define sk_X509_TRUST_free(st) SKM_sk_free(X509_TRUST, (st)) +# define sk_X509_TRUST_num(st) SKM_sk_num(X509_TRUST, (st)) +# define sk_X509_TRUST_value(st, i) SKM_sk_value(X509_TRUST, (st), (i)) +# define sk_X509_TRUST_set(st, i, val) SKM_sk_set(X509_TRUST, (st), (i), (val)) +# define sk_X509_TRUST_zero(st) SKM_sk_zero(X509_TRUST, (st)) +# define sk_X509_TRUST_push(st, val) SKM_sk_push(X509_TRUST, (st), (val)) +# define sk_X509_TRUST_unshift(st, val) SKM_sk_unshift(X509_TRUST, (st), (val)) +# define sk_X509_TRUST_find(st, val) SKM_sk_find(X509_TRUST, (st), (val)) +# define sk_X509_TRUST_find_ex(st, val) SKM_sk_find_ex(X509_TRUST, (st), (val)) +# define sk_X509_TRUST_delete(st, i) SKM_sk_delete(X509_TRUST, (st), (i)) +# define sk_X509_TRUST_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_TRUST, (st), (ptr)) +# define sk_X509_TRUST_insert(st, val, i) SKM_sk_insert(X509_TRUST, (st), (val), (i)) +# define sk_X509_TRUST_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_TRUST, (st), (cmp)) +# define sk_X509_TRUST_dup(st) SKM_sk_dup(X509_TRUST, st) +# define sk_X509_TRUST_pop_free(st, free_func) SKM_sk_pop_free(X509_TRUST, (st), (free_func)) +# define sk_X509_TRUST_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_TRUST, (st), (copy_func), (free_func)) +# define sk_X509_TRUST_shift(st) SKM_sk_shift(X509_TRUST, (st)) +# define sk_X509_TRUST_pop(st) SKM_sk_pop(X509_TRUST, (st)) +# define sk_X509_TRUST_sort(st) SKM_sk_sort(X509_TRUST, (st)) +# define sk_X509_TRUST_is_sorted(st) SKM_sk_is_sorted(X509_TRUST, (st)) +# define sk_X509_VERIFY_PARAM_new(cmp) SKM_sk_new(X509_VERIFY_PARAM, (cmp)) +# define sk_X509_VERIFY_PARAM_new_null() SKM_sk_new_null(X509_VERIFY_PARAM) +# define sk_X509_VERIFY_PARAM_free(st) SKM_sk_free(X509_VERIFY_PARAM, (st)) +# define sk_X509_VERIFY_PARAM_num(st) SKM_sk_num(X509_VERIFY_PARAM, (st)) +# define sk_X509_VERIFY_PARAM_value(st, i) SKM_sk_value(X509_VERIFY_PARAM, (st), (i)) +# define sk_X509_VERIFY_PARAM_set(st, i, val) SKM_sk_set(X509_VERIFY_PARAM, (st), (i), (val)) +# define sk_X509_VERIFY_PARAM_zero(st) SKM_sk_zero(X509_VERIFY_PARAM, (st)) +# define sk_X509_VERIFY_PARAM_push(st, val) SKM_sk_push(X509_VERIFY_PARAM, (st), (val)) +# define sk_X509_VERIFY_PARAM_unshift(st, val) SKM_sk_unshift(X509_VERIFY_PARAM, (st), (val)) +# define sk_X509_VERIFY_PARAM_find(st, val) SKM_sk_find(X509_VERIFY_PARAM, (st), (val)) +# define sk_X509_VERIFY_PARAM_find_ex(st, val) SKM_sk_find_ex(X509_VERIFY_PARAM, (st), (val)) +# define sk_X509_VERIFY_PARAM_delete(st, i) SKM_sk_delete(X509_VERIFY_PARAM, (st), (i)) +# define sk_X509_VERIFY_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_VERIFY_PARAM, (st), (ptr)) +# define sk_X509_VERIFY_PARAM_insert(st, val, i) SKM_sk_insert(X509_VERIFY_PARAM, (st), (val), (i)) +# define sk_X509_VERIFY_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_VERIFY_PARAM, (st), (cmp)) +# define sk_X509_VERIFY_PARAM_dup(st) SKM_sk_dup(X509_VERIFY_PARAM, st) +# define sk_X509_VERIFY_PARAM_pop_free(st, free_func) SKM_sk_pop_free(X509_VERIFY_PARAM, (st), (free_func)) +# define sk_X509_VERIFY_PARAM_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(X509_VERIFY_PARAM, (st), (copy_func), (free_func)) +# define sk_X509_VERIFY_PARAM_shift(st) SKM_sk_shift(X509_VERIFY_PARAM, (st)) +# define sk_X509_VERIFY_PARAM_pop(st) SKM_sk_pop(X509_VERIFY_PARAM, (st)) +# define sk_X509_VERIFY_PARAM_sort(st) SKM_sk_sort(X509_VERIFY_PARAM, (st)) +# define sk_X509_VERIFY_PARAM_is_sorted(st) SKM_sk_is_sorted(X509_VERIFY_PARAM, (st)) +# define sk_nid_triple_new(cmp) SKM_sk_new(nid_triple, (cmp)) +# define sk_nid_triple_new_null() SKM_sk_new_null(nid_triple) +# define sk_nid_triple_free(st) SKM_sk_free(nid_triple, (st)) +# define sk_nid_triple_num(st) SKM_sk_num(nid_triple, (st)) +# define sk_nid_triple_value(st, i) SKM_sk_value(nid_triple, (st), (i)) +# define sk_nid_triple_set(st, i, val) SKM_sk_set(nid_triple, (st), (i), (val)) +# define sk_nid_triple_zero(st) SKM_sk_zero(nid_triple, (st)) +# define sk_nid_triple_push(st, val) SKM_sk_push(nid_triple, (st), (val)) +# define sk_nid_triple_unshift(st, val) SKM_sk_unshift(nid_triple, (st), (val)) +# define sk_nid_triple_find(st, val) SKM_sk_find(nid_triple, (st), (val)) +# define sk_nid_triple_find_ex(st, val) SKM_sk_find_ex(nid_triple, (st), (val)) +# define sk_nid_triple_delete(st, i) SKM_sk_delete(nid_triple, (st), (i)) +# define sk_nid_triple_delete_ptr(st, ptr) SKM_sk_delete_ptr(nid_triple, (st), (ptr)) +# define sk_nid_triple_insert(st, val, i) SKM_sk_insert(nid_triple, (st), (val), (i)) +# define sk_nid_triple_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(nid_triple, (st), (cmp)) +# define sk_nid_triple_dup(st) SKM_sk_dup(nid_triple, st) +# define sk_nid_triple_pop_free(st, free_func) SKM_sk_pop_free(nid_triple, (st), (free_func)) +# define sk_nid_triple_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(nid_triple, (st), (copy_func), (free_func)) +# define sk_nid_triple_shift(st) SKM_sk_shift(nid_triple, (st)) +# define sk_nid_triple_pop(st) SKM_sk_pop(nid_triple, (st)) +# define sk_nid_triple_sort(st) SKM_sk_sort(nid_triple, (st)) +# define sk_nid_triple_is_sorted(st) SKM_sk_is_sorted(nid_triple, (st)) +# define sk_void_new(cmp) SKM_sk_new(void, (cmp)) +# define sk_void_new_null() SKM_sk_new_null(void) +# define sk_void_free(st) SKM_sk_free(void, (st)) +# define sk_void_num(st) SKM_sk_num(void, (st)) +# define sk_void_value(st, i) SKM_sk_value(void, (st), (i)) +# define sk_void_set(st, i, val) SKM_sk_set(void, (st), (i), (val)) +# define sk_void_zero(st) SKM_sk_zero(void, (st)) +# define sk_void_push(st, val) SKM_sk_push(void, (st), (val)) +# define sk_void_unshift(st, val) SKM_sk_unshift(void, (st), (val)) +# define sk_void_find(st, val) SKM_sk_find(void, (st), (val)) +# define sk_void_find_ex(st, val) SKM_sk_find_ex(void, (st), (val)) +# define sk_void_delete(st, i) SKM_sk_delete(void, (st), (i)) +# define sk_void_delete_ptr(st, ptr) SKM_sk_delete_ptr(void, (st), (ptr)) +# define sk_void_insert(st, val, i) SKM_sk_insert(void, (st), (val), (i)) +# define sk_void_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(void, (st), (cmp)) +# define sk_void_dup(st) SKM_sk_dup(void, st) +# define sk_void_pop_free(st, free_func) SKM_sk_pop_free(void, (st), (free_func)) +# define sk_void_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(void, (st), (copy_func), (free_func)) +# define sk_void_shift(st) SKM_sk_shift(void, (st)) +# define sk_void_pop(st) SKM_sk_pop(void, (st)) +# define sk_void_sort(st) SKM_sk_sort(void, (st)) +# define sk_void_is_sorted(st) SKM_sk_is_sorted(void, (st)) +# define sk_OPENSSL_STRING_new(cmp) ((STACK_OF(OPENSSL_STRING) *)sk_new(CHECKED_SK_CMP_FUNC(char, cmp))) +# define sk_OPENSSL_STRING_new_null() ((STACK_OF(OPENSSL_STRING) *)sk_new_null()) +# define sk_OPENSSL_STRING_push(st, val) sk_push(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val)) +# define sk_OPENSSL_STRING_find(st, val) sk_find(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val)) +# define sk_OPENSSL_STRING_value(st, i) ((OPENSSL_STRING)sk_value(CHECKED_STACK_OF(OPENSSL_STRING, st), i)) +# define sk_OPENSSL_STRING_num(st) SKM_sk_num(OPENSSL_STRING, st) +# define sk_OPENSSL_STRING_pop_free(st, free_func) sk_pop_free(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_SK_FREE_FUNC(char, free_func)) +# define sk_OPENSSL_STRING_deep_copy(st, copy_func, free_func) ((STACK_OF(OPENSSL_STRING) *)sk_deep_copy(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_SK_COPY_FUNC(char, copy_func), CHECKED_SK_FREE_FUNC(char, free_func))) +# define sk_OPENSSL_STRING_insert(st, val, i) sk_insert(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val), i) +# define sk_OPENSSL_STRING_free(st) SKM_sk_free(OPENSSL_STRING, st) +# define sk_OPENSSL_STRING_set(st, i, val) sk_set(CHECKED_STACK_OF(OPENSSL_STRING, st), i, CHECKED_PTR_OF(char, val)) +# define sk_OPENSSL_STRING_zero(st) SKM_sk_zero(OPENSSL_STRING, (st)) +# define sk_OPENSSL_STRING_unshift(st, val) sk_unshift(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val)) +# define sk_OPENSSL_STRING_find_ex(st, val) sk_find_ex((_STACK *)CHECKED_CONST_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_CONST_PTR_OF(char, val)) +# define sk_OPENSSL_STRING_delete(st, i) SKM_sk_delete(OPENSSL_STRING, (st), (i)) +# define sk_OPENSSL_STRING_delete_ptr(st, ptr) (OPENSSL_STRING *)sk_delete_ptr(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, ptr)) +# define sk_OPENSSL_STRING_set_cmp_func(st, cmp) \ + ((int (*)(const char * const *,const char * const *)) \ + sk_set_cmp_func(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_SK_CMP_FUNC(char, cmp))) +# define sk_OPENSSL_STRING_dup(st) SKM_sk_dup(OPENSSL_STRING, st) +# define sk_OPENSSL_STRING_shift(st) SKM_sk_shift(OPENSSL_STRING, (st)) +# define sk_OPENSSL_STRING_pop(st) (char *)sk_pop(CHECKED_STACK_OF(OPENSSL_STRING, st)) +# define sk_OPENSSL_STRING_sort(st) SKM_sk_sort(OPENSSL_STRING, (st)) +# define sk_OPENSSL_STRING_is_sorted(st) SKM_sk_is_sorted(OPENSSL_STRING, (st)) +# define sk_OPENSSL_BLOCK_new(cmp) ((STACK_OF(OPENSSL_BLOCK) *)sk_new(CHECKED_SK_CMP_FUNC(void, cmp))) +# define sk_OPENSSL_BLOCK_new_null() ((STACK_OF(OPENSSL_BLOCK) *)sk_new_null()) +# define sk_OPENSSL_BLOCK_push(st, val) sk_push(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, val)) +# define sk_OPENSSL_BLOCK_find(st, val) sk_find(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, val)) +# define sk_OPENSSL_BLOCK_value(st, i) ((OPENSSL_BLOCK)sk_value(CHECKED_STACK_OF(OPENSSL_BLOCK, st), i)) +# define sk_OPENSSL_BLOCK_num(st) SKM_sk_num(OPENSSL_BLOCK, st) +# define sk_OPENSSL_BLOCK_pop_free(st, free_func) sk_pop_free(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_SK_FREE_FUNC(void, free_func)) +# define sk_OPENSSL_BLOCK_deep_copy(st, copy_func, free_func) ((STACK_OF(OPENSSL_BLOCK) *)sk_deep_copy(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_SK_COPY_FUNC(void, copy_func), CHECKED_SK_FREE_FUNC(void, free_func))) +# define sk_OPENSSL_BLOCK_insert(st, val, i) sk_insert(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, val), i) +# define sk_OPENSSL_BLOCK_free(st) SKM_sk_free(OPENSSL_BLOCK, st) +# define sk_OPENSSL_BLOCK_set(st, i, val) sk_set(CHECKED_STACK_OF(OPENSSL_BLOCK, st), i, CHECKED_PTR_OF(void, val)) +# define sk_OPENSSL_BLOCK_zero(st) SKM_sk_zero(OPENSSL_BLOCK, (st)) +# define sk_OPENSSL_BLOCK_unshift(st, val) sk_unshift(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, val)) +# define sk_OPENSSL_BLOCK_find_ex(st, val) sk_find_ex((_STACK *)CHECKED_CONST_PTR_OF(STACK_OF(OPENSSL_BLOCK), st), CHECKED_CONST_PTR_OF(void, val)) +# define sk_OPENSSL_BLOCK_delete(st, i) SKM_sk_delete(OPENSSL_BLOCK, (st), (i)) +# define sk_OPENSSL_BLOCK_delete_ptr(st, ptr) (OPENSSL_BLOCK *)sk_delete_ptr(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_PTR_OF(void, ptr)) +# define sk_OPENSSL_BLOCK_set_cmp_func(st, cmp) \ + ((int (*)(const void * const *,const void * const *)) \ + sk_set_cmp_func(CHECKED_STACK_OF(OPENSSL_BLOCK, st), CHECKED_SK_CMP_FUNC(void, cmp))) +# define sk_OPENSSL_BLOCK_dup(st) SKM_sk_dup(OPENSSL_BLOCK, st) +# define sk_OPENSSL_BLOCK_shift(st) SKM_sk_shift(OPENSSL_BLOCK, (st)) +# define sk_OPENSSL_BLOCK_pop(st) (void *)sk_pop(CHECKED_STACK_OF(OPENSSL_BLOCK, st)) +# define sk_OPENSSL_BLOCK_sort(st) SKM_sk_sort(OPENSSL_BLOCK, (st)) +# define sk_OPENSSL_BLOCK_is_sorted(st) SKM_sk_is_sorted(OPENSSL_BLOCK, (st)) +# define sk_OPENSSL_PSTRING_new(cmp) ((STACK_OF(OPENSSL_PSTRING) *)sk_new(CHECKED_SK_CMP_FUNC(OPENSSL_STRING, cmp))) +# define sk_OPENSSL_PSTRING_new_null() ((STACK_OF(OPENSSL_PSTRING) *)sk_new_null()) +# define sk_OPENSSL_PSTRING_push(st, val) sk_push(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val)) +# define sk_OPENSSL_PSTRING_find(st, val) sk_find(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val)) +# define sk_OPENSSL_PSTRING_value(st, i) ((OPENSSL_PSTRING)sk_value(CHECKED_STACK_OF(OPENSSL_PSTRING, st), i)) +# define sk_OPENSSL_PSTRING_num(st) SKM_sk_num(OPENSSL_PSTRING, st) +# define sk_OPENSSL_PSTRING_pop_free(st, free_func) sk_pop_free(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_SK_FREE_FUNC(OPENSSL_STRING, free_func)) +# define sk_OPENSSL_PSTRING_deep_copy(st, copy_func, free_func) ((STACK_OF(OPENSSL_PSTRING) *)sk_deep_copy(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_SK_COPY_FUNC(OPENSSL_STRING, copy_func), CHECKED_SK_FREE_FUNC(OPENSSL_STRING, free_func))) +# define sk_OPENSSL_PSTRING_insert(st, val, i) sk_insert(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val), i) +# define sk_OPENSSL_PSTRING_free(st) SKM_sk_free(OPENSSL_PSTRING, st) +# define sk_OPENSSL_PSTRING_set(st, i, val) sk_set(CHECKED_STACK_OF(OPENSSL_PSTRING, st), i, CHECKED_PTR_OF(OPENSSL_STRING, val)) +# define sk_OPENSSL_PSTRING_zero(st) SKM_sk_zero(OPENSSL_PSTRING, (st)) +# define sk_OPENSSL_PSTRING_unshift(st, val) sk_unshift(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val)) +# define sk_OPENSSL_PSTRING_find_ex(st, val) sk_find_ex((_STACK *)CHECKED_CONST_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_CONST_PTR_OF(OPENSSL_STRING, val)) +# define sk_OPENSSL_PSTRING_delete(st, i) SKM_sk_delete(OPENSSL_PSTRING, (st), (i)) +# define sk_OPENSSL_PSTRING_delete_ptr(st, ptr) (OPENSSL_PSTRING *)sk_delete_ptr(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, ptr)) +# define sk_OPENSSL_PSTRING_set_cmp_func(st, cmp) \ + ((int (*)(const OPENSSL_STRING * const *,const OPENSSL_STRING * const *)) \ + sk_set_cmp_func(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_SK_CMP_FUNC(OPENSSL_STRING, cmp))) +# define sk_OPENSSL_PSTRING_dup(st) SKM_sk_dup(OPENSSL_PSTRING, st) +# define sk_OPENSSL_PSTRING_shift(st) SKM_sk_shift(OPENSSL_PSTRING, (st)) +# define sk_OPENSSL_PSTRING_pop(st) (OPENSSL_STRING *)sk_pop(CHECKED_STACK_OF(OPENSSL_PSTRING, st)) +# define sk_OPENSSL_PSTRING_sort(st) SKM_sk_sort(OPENSSL_PSTRING, (st)) +# define sk_OPENSSL_PSTRING_is_sorted(st) SKM_sk_is_sorted(OPENSSL_PSTRING, (st)) +# define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ACCESS_DESCRIPTION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ACCESS_DESCRIPTION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_ACCESS_DESCRIPTION(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ACCESS_DESCRIPTION, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_ACCESS_DESCRIPTION(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ACCESS_DESCRIPTION, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_ASN1_INTEGER(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ASN1_INTEGER, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_ASN1_INTEGER(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ASN1_INTEGER, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_ASN1_INTEGER(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ASN1_INTEGER, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_ASN1_INTEGER(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ASN1_INTEGER, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_ASN1_OBJECT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ASN1_OBJECT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_ASN1_OBJECT(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ASN1_OBJECT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_ASN1_OBJECT(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ASN1_OBJECT, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_ASN1_OBJECT(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ASN1_OBJECT, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_ASN1_TYPE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ASN1_TYPE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_ASN1_TYPE(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ASN1_TYPE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_ASN1_TYPE(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ASN1_TYPE, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_ASN1_TYPE(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ASN1_TYPE, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_ASN1_UTF8STRING(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ASN1_UTF8STRING, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_ASN1_UTF8STRING(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ASN1_UTF8STRING, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_ASN1_UTF8STRING(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ASN1_UTF8STRING, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_ASN1_UTF8STRING(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ASN1_UTF8STRING, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_DIST_POINT(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(DIST_POINT, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_DIST_POINT(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(DIST_POINT, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_DIST_POINT(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(DIST_POINT, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_DIST_POINT(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(DIST_POINT, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_ESS_CERT_ID(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(ESS_CERT_ID, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_ESS_CERT_ID(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(ESS_CERT_ID, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_ESS_CERT_ID(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(ESS_CERT_ID, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_ESS_CERT_ID(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(ESS_CERT_ID, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_EVP_MD(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(EVP_MD, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_EVP_MD(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(EVP_MD, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_EVP_MD(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(EVP_MD, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_EVP_MD(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(EVP_MD, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_GENERAL_NAME(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(GENERAL_NAME, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_GENERAL_NAME(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(GENERAL_NAME, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_GENERAL_NAME(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(GENERAL_NAME, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_GENERAL_NAME(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(GENERAL_NAME, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_OCSP_ONEREQ(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(OCSP_ONEREQ, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_OCSP_ONEREQ(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(OCSP_ONEREQ, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_OCSP_ONEREQ(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(OCSP_ONEREQ, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_OCSP_ONEREQ(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(OCSP_ONEREQ, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(OCSP_SINGLERESP, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_OCSP_SINGLERESP(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(OCSP_SINGLERESP, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_OCSP_SINGLERESP(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(OCSP_SINGLERESP, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_OCSP_SINGLERESP(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(OCSP_SINGLERESP, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(PKCS12_SAFEBAG, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_PKCS12_SAFEBAG(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(PKCS12_SAFEBAG, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_PKCS12_SAFEBAG(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(PKCS12_SAFEBAG, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_PKCS12_SAFEBAG(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(PKCS12_SAFEBAG, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_PKCS7(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(PKCS7, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_PKCS7(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(PKCS7, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_PKCS7(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(PKCS7, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_PKCS7(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(PKCS7, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(PKCS7_RECIP_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(PKCS7_RECIP_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_PKCS7_RECIP_INFO(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(PKCS7_RECIP_INFO, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_PKCS7_RECIP_INFO(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(PKCS7_RECIP_INFO, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(PKCS7_SIGNER_INFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(PKCS7_SIGNER_INFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_PKCS7_SIGNER_INFO(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(PKCS7_SIGNER_INFO, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_PKCS7_SIGNER_INFO(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(PKCS7_SIGNER_INFO, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_POLICYINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(POLICYINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_POLICYINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(POLICYINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_POLICYINFO(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(POLICYINFO, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_POLICYINFO(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(POLICYINFO, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_POLICYQUALINFO(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(POLICYQUALINFO, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_POLICYQUALINFO(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(POLICYQUALINFO, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_POLICYQUALINFO(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(POLICYQUALINFO, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_POLICYQUALINFO(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(POLICYQUALINFO, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_SXNETID(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(SXNETID, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_SXNETID(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(SXNETID, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_SXNETID(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(SXNETID, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_SXNETID(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(SXNETID, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_X509(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_X509(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_X509(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_X509(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_X509_ALGOR(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_ALGOR, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_X509_ALGOR(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_ALGOR, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_X509_ALGOR(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_ALGOR, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_X509_ALGOR(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_ALGOR, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_ATTRIBUTE, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_X509_ATTRIBUTE(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_ATTRIBUTE, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_X509_ATTRIBUTE(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_ATTRIBUTE, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_X509_ATTRIBUTE(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_ATTRIBUTE, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_X509_CRL(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_CRL, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_X509_CRL(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_CRL, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_X509_CRL(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_CRL, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_X509_CRL(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_CRL, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_X509_EXTENSION(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_EXTENSION, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_X509_EXTENSION(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_EXTENSION, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_X509_EXTENSION(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_EXTENSION, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_X509_EXTENSION(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_EXTENSION, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_NAME_ENTRY, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_X509_NAME_ENTRY(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_NAME_ENTRY, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_X509_NAME_ENTRY(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_NAME_ENTRY, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_X509_NAME_ENTRY(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_NAME_ENTRY, (buf), (len), (d2i_func), (free_func)) +# define d2i_ASN1_SET_OF_X509_REVOKED(st, pp, length, d2i_func, free_func, ex_tag, ex_class) \ + SKM_ASN1_SET_OF_d2i(X509_REVOKED, (st), (pp), (length), (d2i_func), (free_func), (ex_tag), (ex_class)) +# define i2d_ASN1_SET_OF_X509_REVOKED(st, pp, i2d_func, ex_tag, ex_class, is_set) \ + SKM_ASN1_SET_OF_i2d(X509_REVOKED, (st), (pp), (i2d_func), (ex_tag), (ex_class), (is_set)) +# define ASN1_seq_pack_X509_REVOKED(st, i2d_func, buf, len) \ + SKM_ASN1_seq_pack(X509_REVOKED, (st), (i2d_func), (buf), (len)) +# define ASN1_seq_unpack_X509_REVOKED(buf, len, d2i_func, free_func) \ + SKM_ASN1_seq_unpack(X509_REVOKED, (buf), (len), (d2i_func), (free_func)) +# define PKCS12_decrypt_d2i_PKCS12_SAFEBAG(algor, d2i_func, free_func, pass, passlen, oct, seq) \ + SKM_PKCS12_decrypt_d2i(PKCS12_SAFEBAG, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq)) +# define PKCS12_decrypt_d2i_PKCS7(algor, d2i_func, free_func, pass, passlen, oct, seq) \ + SKM_PKCS12_decrypt_d2i(PKCS7, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq)) +# define lh_ADDED_OBJ_new() LHM_lh_new(ADDED_OBJ,added_obj) +# define lh_ADDED_OBJ_insert(lh,inst) LHM_lh_insert(ADDED_OBJ,lh,inst) +# define lh_ADDED_OBJ_retrieve(lh,inst) LHM_lh_retrieve(ADDED_OBJ,lh,inst) +# define lh_ADDED_OBJ_delete(lh,inst) LHM_lh_delete(ADDED_OBJ,lh,inst) +# define lh_ADDED_OBJ_doall(lh,fn) LHM_lh_doall(ADDED_OBJ,lh,fn) +# define lh_ADDED_OBJ_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(ADDED_OBJ,lh,fn,arg_type,arg) +# define lh_ADDED_OBJ_error(lh) LHM_lh_error(ADDED_OBJ,lh) +# define lh_ADDED_OBJ_num_items(lh) LHM_lh_num_items(ADDED_OBJ,lh) +# define lh_ADDED_OBJ_down_load(lh) LHM_lh_down_load(ADDED_OBJ,lh) +# define lh_ADDED_OBJ_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(ADDED_OBJ,lh,out) +# define lh_ADDED_OBJ_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(ADDED_OBJ,lh,out) +# define lh_ADDED_OBJ_stats_bio(lh,out) \ + LHM_lh_stats_bio(ADDED_OBJ,lh,out) +# define lh_ADDED_OBJ_free(lh) LHM_lh_free(ADDED_OBJ,lh) +# define lh_APP_INFO_new() LHM_lh_new(APP_INFO,app_info) +# define lh_APP_INFO_insert(lh,inst) LHM_lh_insert(APP_INFO,lh,inst) +# define lh_APP_INFO_retrieve(lh,inst) LHM_lh_retrieve(APP_INFO,lh,inst) +# define lh_APP_INFO_delete(lh,inst) LHM_lh_delete(APP_INFO,lh,inst) +# define lh_APP_INFO_doall(lh,fn) LHM_lh_doall(APP_INFO,lh,fn) +# define lh_APP_INFO_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(APP_INFO,lh,fn,arg_type,arg) +# define lh_APP_INFO_error(lh) LHM_lh_error(APP_INFO,lh) +# define lh_APP_INFO_num_items(lh) LHM_lh_num_items(APP_INFO,lh) +# define lh_APP_INFO_down_load(lh) LHM_lh_down_load(APP_INFO,lh) +# define lh_APP_INFO_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(APP_INFO,lh,out) +# define lh_APP_INFO_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(APP_INFO,lh,out) +# define lh_APP_INFO_stats_bio(lh,out) \ + LHM_lh_stats_bio(APP_INFO,lh,out) +# define lh_APP_INFO_free(lh) LHM_lh_free(APP_INFO,lh) +# define lh_CONF_VALUE_new() LHM_lh_new(CONF_VALUE,conf_value) +# define lh_CONF_VALUE_insert(lh,inst) LHM_lh_insert(CONF_VALUE,lh,inst) +# define lh_CONF_VALUE_retrieve(lh,inst) LHM_lh_retrieve(CONF_VALUE,lh,inst) +# define lh_CONF_VALUE_delete(lh,inst) LHM_lh_delete(CONF_VALUE,lh,inst) +# define lh_CONF_VALUE_doall(lh,fn) LHM_lh_doall(CONF_VALUE,lh,fn) +# define lh_CONF_VALUE_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(CONF_VALUE,lh,fn,arg_type,arg) +# define lh_CONF_VALUE_error(lh) LHM_lh_error(CONF_VALUE,lh) +# define lh_CONF_VALUE_num_items(lh) LHM_lh_num_items(CONF_VALUE,lh) +# define lh_CONF_VALUE_down_load(lh) LHM_lh_down_load(CONF_VALUE,lh) +# define lh_CONF_VALUE_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(CONF_VALUE,lh,out) +# define lh_CONF_VALUE_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(CONF_VALUE,lh,out) +# define lh_CONF_VALUE_stats_bio(lh,out) \ + LHM_lh_stats_bio(CONF_VALUE,lh,out) +# define lh_CONF_VALUE_free(lh) LHM_lh_free(CONF_VALUE,lh) +# define lh_ENGINE_PILE_new() LHM_lh_new(ENGINE_PILE,engine_pile) +# define lh_ENGINE_PILE_insert(lh,inst) LHM_lh_insert(ENGINE_PILE,lh,inst) +# define lh_ENGINE_PILE_retrieve(lh,inst) LHM_lh_retrieve(ENGINE_PILE,lh,inst) +# define lh_ENGINE_PILE_delete(lh,inst) LHM_lh_delete(ENGINE_PILE,lh,inst) +# define lh_ENGINE_PILE_doall(lh,fn) LHM_lh_doall(ENGINE_PILE,lh,fn) +# define lh_ENGINE_PILE_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(ENGINE_PILE,lh,fn,arg_type,arg) +# define lh_ENGINE_PILE_error(lh) LHM_lh_error(ENGINE_PILE,lh) +# define lh_ENGINE_PILE_num_items(lh) LHM_lh_num_items(ENGINE_PILE,lh) +# define lh_ENGINE_PILE_down_load(lh) LHM_lh_down_load(ENGINE_PILE,lh) +# define lh_ENGINE_PILE_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(ENGINE_PILE,lh,out) +# define lh_ENGINE_PILE_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(ENGINE_PILE,lh,out) +# define lh_ENGINE_PILE_stats_bio(lh,out) \ + LHM_lh_stats_bio(ENGINE_PILE,lh,out) +# define lh_ENGINE_PILE_free(lh) LHM_lh_free(ENGINE_PILE,lh) +# define lh_ERR_STATE_new() LHM_lh_new(ERR_STATE,err_state) +# define lh_ERR_STATE_insert(lh,inst) LHM_lh_insert(ERR_STATE,lh,inst) +# define lh_ERR_STATE_retrieve(lh,inst) LHM_lh_retrieve(ERR_STATE,lh,inst) +# define lh_ERR_STATE_delete(lh,inst) LHM_lh_delete(ERR_STATE,lh,inst) +# define lh_ERR_STATE_doall(lh,fn) LHM_lh_doall(ERR_STATE,lh,fn) +# define lh_ERR_STATE_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(ERR_STATE,lh,fn,arg_type,arg) +# define lh_ERR_STATE_error(lh) LHM_lh_error(ERR_STATE,lh) +# define lh_ERR_STATE_num_items(lh) LHM_lh_num_items(ERR_STATE,lh) +# define lh_ERR_STATE_down_load(lh) LHM_lh_down_load(ERR_STATE,lh) +# define lh_ERR_STATE_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(ERR_STATE,lh,out) +# define lh_ERR_STATE_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(ERR_STATE,lh,out) +# define lh_ERR_STATE_stats_bio(lh,out) \ + LHM_lh_stats_bio(ERR_STATE,lh,out) +# define lh_ERR_STATE_free(lh) LHM_lh_free(ERR_STATE,lh) +# define lh_ERR_STRING_DATA_new() LHM_lh_new(ERR_STRING_DATA,err_string_data) +# define lh_ERR_STRING_DATA_insert(lh,inst) LHM_lh_insert(ERR_STRING_DATA,lh,inst) +# define lh_ERR_STRING_DATA_retrieve(lh,inst) LHM_lh_retrieve(ERR_STRING_DATA,lh,inst) +# define lh_ERR_STRING_DATA_delete(lh,inst) LHM_lh_delete(ERR_STRING_DATA,lh,inst) +# define lh_ERR_STRING_DATA_doall(lh,fn) LHM_lh_doall(ERR_STRING_DATA,lh,fn) +# define lh_ERR_STRING_DATA_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(ERR_STRING_DATA,lh,fn,arg_type,arg) +# define lh_ERR_STRING_DATA_error(lh) LHM_lh_error(ERR_STRING_DATA,lh) +# define lh_ERR_STRING_DATA_num_items(lh) LHM_lh_num_items(ERR_STRING_DATA,lh) +# define lh_ERR_STRING_DATA_down_load(lh) LHM_lh_down_load(ERR_STRING_DATA,lh) +# define lh_ERR_STRING_DATA_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(ERR_STRING_DATA,lh,out) +# define lh_ERR_STRING_DATA_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(ERR_STRING_DATA,lh,out) +# define lh_ERR_STRING_DATA_stats_bio(lh,out) \ + LHM_lh_stats_bio(ERR_STRING_DATA,lh,out) +# define lh_ERR_STRING_DATA_free(lh) LHM_lh_free(ERR_STRING_DATA,lh) +# define lh_EX_CLASS_ITEM_new() LHM_lh_new(EX_CLASS_ITEM,ex_class_item) +# define lh_EX_CLASS_ITEM_insert(lh,inst) LHM_lh_insert(EX_CLASS_ITEM,lh,inst) +# define lh_EX_CLASS_ITEM_retrieve(lh,inst) LHM_lh_retrieve(EX_CLASS_ITEM,lh,inst) +# define lh_EX_CLASS_ITEM_delete(lh,inst) LHM_lh_delete(EX_CLASS_ITEM,lh,inst) +# define lh_EX_CLASS_ITEM_doall(lh,fn) LHM_lh_doall(EX_CLASS_ITEM,lh,fn) +# define lh_EX_CLASS_ITEM_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(EX_CLASS_ITEM,lh,fn,arg_type,arg) +# define lh_EX_CLASS_ITEM_error(lh) LHM_lh_error(EX_CLASS_ITEM,lh) +# define lh_EX_CLASS_ITEM_num_items(lh) LHM_lh_num_items(EX_CLASS_ITEM,lh) +# define lh_EX_CLASS_ITEM_down_load(lh) LHM_lh_down_load(EX_CLASS_ITEM,lh) +# define lh_EX_CLASS_ITEM_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(EX_CLASS_ITEM,lh,out) +# define lh_EX_CLASS_ITEM_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(EX_CLASS_ITEM,lh,out) +# define lh_EX_CLASS_ITEM_stats_bio(lh,out) \ + LHM_lh_stats_bio(EX_CLASS_ITEM,lh,out) +# define lh_EX_CLASS_ITEM_free(lh) LHM_lh_free(EX_CLASS_ITEM,lh) +# define lh_FUNCTION_new() LHM_lh_new(FUNCTION,function) +# define lh_FUNCTION_insert(lh,inst) LHM_lh_insert(FUNCTION,lh,inst) +# define lh_FUNCTION_retrieve(lh,inst) LHM_lh_retrieve(FUNCTION,lh,inst) +# define lh_FUNCTION_delete(lh,inst) LHM_lh_delete(FUNCTION,lh,inst) +# define lh_FUNCTION_doall(lh,fn) LHM_lh_doall(FUNCTION,lh,fn) +# define lh_FUNCTION_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(FUNCTION,lh,fn,arg_type,arg) +# define lh_FUNCTION_error(lh) LHM_lh_error(FUNCTION,lh) +# define lh_FUNCTION_num_items(lh) LHM_lh_num_items(FUNCTION,lh) +# define lh_FUNCTION_down_load(lh) LHM_lh_down_load(FUNCTION,lh) +# define lh_FUNCTION_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(FUNCTION,lh,out) +# define lh_FUNCTION_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(FUNCTION,lh,out) +# define lh_FUNCTION_stats_bio(lh,out) \ + LHM_lh_stats_bio(FUNCTION,lh,out) +# define lh_FUNCTION_free(lh) LHM_lh_free(FUNCTION,lh) +# define lh_MEM_new() LHM_lh_new(MEM,mem) +# define lh_MEM_insert(lh,inst) LHM_lh_insert(MEM,lh,inst) +# define lh_MEM_retrieve(lh,inst) LHM_lh_retrieve(MEM,lh,inst) +# define lh_MEM_delete(lh,inst) LHM_lh_delete(MEM,lh,inst) +# define lh_MEM_doall(lh,fn) LHM_lh_doall(MEM,lh,fn) +# define lh_MEM_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(MEM,lh,fn,arg_type,arg) +# define lh_MEM_error(lh) LHM_lh_error(MEM,lh) +# define lh_MEM_num_items(lh) LHM_lh_num_items(MEM,lh) +# define lh_MEM_down_load(lh) LHM_lh_down_load(MEM,lh) +# define lh_MEM_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(MEM,lh,out) +# define lh_MEM_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(MEM,lh,out) +# define lh_MEM_stats_bio(lh,out) \ + LHM_lh_stats_bio(MEM,lh,out) +# define lh_MEM_free(lh) LHM_lh_free(MEM,lh) +# define lh_OBJ_NAME_new() LHM_lh_new(OBJ_NAME,obj_name) +# define lh_OBJ_NAME_insert(lh,inst) LHM_lh_insert(OBJ_NAME,lh,inst) +# define lh_OBJ_NAME_retrieve(lh,inst) LHM_lh_retrieve(OBJ_NAME,lh,inst) +# define lh_OBJ_NAME_delete(lh,inst) LHM_lh_delete(OBJ_NAME,lh,inst) +# define lh_OBJ_NAME_doall(lh,fn) LHM_lh_doall(OBJ_NAME,lh,fn) +# define lh_OBJ_NAME_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(OBJ_NAME,lh,fn,arg_type,arg) +# define lh_OBJ_NAME_error(lh) LHM_lh_error(OBJ_NAME,lh) +# define lh_OBJ_NAME_num_items(lh) LHM_lh_num_items(OBJ_NAME,lh) +# define lh_OBJ_NAME_down_load(lh) LHM_lh_down_load(OBJ_NAME,lh) +# define lh_OBJ_NAME_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(OBJ_NAME,lh,out) +# define lh_OBJ_NAME_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(OBJ_NAME,lh,out) +# define lh_OBJ_NAME_stats_bio(lh,out) \ + LHM_lh_stats_bio(OBJ_NAME,lh,out) +# define lh_OBJ_NAME_free(lh) LHM_lh_free(OBJ_NAME,lh) +# define lh_OPENSSL_CSTRING_new() LHM_lh_new(OPENSSL_CSTRING,openssl_cstring) +# define lh_OPENSSL_CSTRING_insert(lh,inst) LHM_lh_insert(OPENSSL_CSTRING,lh,inst) +# define lh_OPENSSL_CSTRING_retrieve(lh,inst) LHM_lh_retrieve(OPENSSL_CSTRING,lh,inst) +# define lh_OPENSSL_CSTRING_delete(lh,inst) LHM_lh_delete(OPENSSL_CSTRING,lh,inst) +# define lh_OPENSSL_CSTRING_doall(lh,fn) LHM_lh_doall(OPENSSL_CSTRING,lh,fn) +# define lh_OPENSSL_CSTRING_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(OPENSSL_CSTRING,lh,fn,arg_type,arg) +# define lh_OPENSSL_CSTRING_error(lh) LHM_lh_error(OPENSSL_CSTRING,lh) +# define lh_OPENSSL_CSTRING_num_items(lh) LHM_lh_num_items(OPENSSL_CSTRING,lh) +# define lh_OPENSSL_CSTRING_down_load(lh) LHM_lh_down_load(OPENSSL_CSTRING,lh) +# define lh_OPENSSL_CSTRING_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(OPENSSL_CSTRING,lh,out) +# define lh_OPENSSL_CSTRING_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(OPENSSL_CSTRING,lh,out) +# define lh_OPENSSL_CSTRING_stats_bio(lh,out) \ + LHM_lh_stats_bio(OPENSSL_CSTRING,lh,out) +# define lh_OPENSSL_CSTRING_free(lh) LHM_lh_free(OPENSSL_CSTRING,lh) +# define lh_OPENSSL_STRING_new() LHM_lh_new(OPENSSL_STRING,openssl_string) +# define lh_OPENSSL_STRING_insert(lh,inst) LHM_lh_insert(OPENSSL_STRING,lh,inst) +# define lh_OPENSSL_STRING_retrieve(lh,inst) LHM_lh_retrieve(OPENSSL_STRING,lh,inst) +# define lh_OPENSSL_STRING_delete(lh,inst) LHM_lh_delete(OPENSSL_STRING,lh,inst) +# define lh_OPENSSL_STRING_doall(lh,fn) LHM_lh_doall(OPENSSL_STRING,lh,fn) +# define lh_OPENSSL_STRING_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(OPENSSL_STRING,lh,fn,arg_type,arg) +# define lh_OPENSSL_STRING_error(lh) LHM_lh_error(OPENSSL_STRING,lh) +# define lh_OPENSSL_STRING_num_items(lh) LHM_lh_num_items(OPENSSL_STRING,lh) +# define lh_OPENSSL_STRING_down_load(lh) LHM_lh_down_load(OPENSSL_STRING,lh) +# define lh_OPENSSL_STRING_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(OPENSSL_STRING,lh,out) +# define lh_OPENSSL_STRING_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(OPENSSL_STRING,lh,out) +# define lh_OPENSSL_STRING_stats_bio(lh,out) \ + LHM_lh_stats_bio(OPENSSL_STRING,lh,out) +# define lh_OPENSSL_STRING_free(lh) LHM_lh_free(OPENSSL_STRING,lh) +# define lh_SSL_SESSION_new() LHM_lh_new(SSL_SESSION,ssl_session) +# define lh_SSL_SESSION_insert(lh,inst) LHM_lh_insert(SSL_SESSION,lh,inst) +# define lh_SSL_SESSION_retrieve(lh,inst) LHM_lh_retrieve(SSL_SESSION,lh,inst) +# define lh_SSL_SESSION_delete(lh,inst) LHM_lh_delete(SSL_SESSION,lh,inst) +# define lh_SSL_SESSION_doall(lh,fn) LHM_lh_doall(SSL_SESSION,lh,fn) +# define lh_SSL_SESSION_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(SSL_SESSION,lh,fn,arg_type,arg) +# define lh_SSL_SESSION_error(lh) LHM_lh_error(SSL_SESSION,lh) +# define lh_SSL_SESSION_num_items(lh) LHM_lh_num_items(SSL_SESSION,lh) +# define lh_SSL_SESSION_down_load(lh) LHM_lh_down_load(SSL_SESSION,lh) +# define lh_SSL_SESSION_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(SSL_SESSION,lh,out) +# define lh_SSL_SESSION_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(SSL_SESSION,lh,out) +# define lh_SSL_SESSION_stats_bio(lh,out) \ + LHM_lh_stats_bio(SSL_SESSION,lh,out) +# define lh_SSL_SESSION_free(lh) LHM_lh_free(SSL_SESSION,lh) +#ifdef __cplusplus +} +#endif +#endif /* !defined HEADER_SAFESTACK_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/seed.h b/optee/optee_test/host/openssl/include/openssl/seed.h new file mode 100644 index 0000000..8cbf0d9 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/seed.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2007 KISA(Korea Information Security Agency). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of author 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_SEED_H +# define HEADER_SEED_H + +# include +# include +# include + +# ifdef OPENSSL_NO_SEED +# error SEED is disabled. +# endif + +/* look whether we need 'long' to get 32 bits */ +# ifdef AES_LONG +# ifndef SEED_LONG +# define SEED_LONG 1 +# endif +# endif + +# if !defined(NO_SYS_TYPES_H) +# include +# endif + +# define SEED_BLOCK_SIZE 16 +# define SEED_KEY_LENGTH 16 + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct seed_key_st { +# ifdef SEED_LONG + unsigned long data[32]; +# else + unsigned int data[32]; +# endif +} SEED_KEY_SCHEDULE; + +# ifdef OPENSSL_FIPS +void private_SEED_set_key(const unsigned char rawkey[SEED_KEY_LENGTH], + SEED_KEY_SCHEDULE *ks); +# endif +void SEED_set_key(const unsigned char rawkey[SEED_KEY_LENGTH], + SEED_KEY_SCHEDULE *ks); + +void SEED_encrypt(const unsigned char s[SEED_BLOCK_SIZE], + unsigned char d[SEED_BLOCK_SIZE], + const SEED_KEY_SCHEDULE *ks); +void SEED_decrypt(const unsigned char s[SEED_BLOCK_SIZE], + unsigned char d[SEED_BLOCK_SIZE], + const SEED_KEY_SCHEDULE *ks); + +void SEED_ecb_encrypt(const unsigned char *in, unsigned char *out, + const SEED_KEY_SCHEDULE *ks, int enc); +void SEED_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len, + const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int enc); +void SEED_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int *num, + int enc); +void SEED_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const SEED_KEY_SCHEDULE *ks, + unsigned char ivec[SEED_BLOCK_SIZE], int *num); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_SEED_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/sha.h b/optee/optee_test/host/openssl/include/openssl/sha.h new file mode 100644 index 0000000..e5169e4 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/sha.h @@ -0,0 +1,214 @@ +/* crypto/sha/sha.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SHA_H +# define HEADER_SHA_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# if defined(OPENSSL_NO_SHA) || (defined(OPENSSL_NO_SHA0) && defined(OPENSSL_NO_SHA1)) +# error SHA is disabled. +# endif + +# if defined(OPENSSL_FIPS) +# define FIPS_SHA_SIZE_T size_t +# endif + +/*- + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! SHA_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +# if defined(__LP32__) +# define SHA_LONG unsigned long +# elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__) +# define SHA_LONG unsigned long +# define SHA_LONG_LOG2 3 +# else +# define SHA_LONG unsigned int +# endif + +# define SHA_LBLOCK 16 +# define SHA_CBLOCK (SHA_LBLOCK*4)/* SHA treats input data as a + * contiguous array of 32 bit wide + * big-endian values. */ +# define SHA_LAST_BLOCK (SHA_CBLOCK-8) +# define SHA_DIGEST_LENGTH 20 + +typedef struct SHAstate_st { + SHA_LONG h0, h1, h2, h3, h4; + SHA_LONG Nl, Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num; +} SHA_CTX; + +# ifndef OPENSSL_NO_SHA0 +# ifdef OPENSSL_FIPS +int private_SHA_Init(SHA_CTX *c); +# endif +int SHA_Init(SHA_CTX *c); +int SHA_Update(SHA_CTX *c, const void *data, size_t len); +int SHA_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA(const unsigned char *d, size_t n, unsigned char *md); +void SHA_Transform(SHA_CTX *c, const unsigned char *data); +# endif +# ifndef OPENSSL_NO_SHA1 +# ifdef OPENSSL_FIPS +int private_SHA1_Init(SHA_CTX *c); +# endif +int SHA1_Init(SHA_CTX *c); +int SHA1_Update(SHA_CTX *c, const void *data, size_t len); +int SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); +# endif + +# define SHA256_CBLOCK (SHA_LBLOCK*4)/* SHA-256 treats input data as a + * contiguous array of 32 bit wide + * big-endian values. */ +# define SHA224_DIGEST_LENGTH 28 +# define SHA256_DIGEST_LENGTH 32 + +typedef struct SHA256state_st { + SHA_LONG h[8]; + SHA_LONG Nl, Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num, md_len; +} SHA256_CTX; + +# ifndef OPENSSL_NO_SHA256 +# ifdef OPENSSL_FIPS +int private_SHA224_Init(SHA256_CTX *c); +int private_SHA256_Init(SHA256_CTX *c); +# endif +int SHA224_Init(SHA256_CTX *c); +int SHA224_Update(SHA256_CTX *c, const void *data, size_t len); +int SHA224_Final(unsigned char *md, SHA256_CTX *c); +unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md); +int SHA256_Init(SHA256_CTX *c); +int SHA256_Update(SHA256_CTX *c, const void *data, size_t len); +int SHA256_Final(unsigned char *md, SHA256_CTX *c); +unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md); +void SHA256_Transform(SHA256_CTX *c, const unsigned char *data); +# endif + +# define SHA384_DIGEST_LENGTH 48 +# define SHA512_DIGEST_LENGTH 64 + +# ifndef OPENSSL_NO_SHA512 +/* + * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 + * being exactly 64-bit wide. See Implementation Notes in sha512.c + * for further details. + */ +/* + * SHA-512 treats input data as a + * contiguous array of 64 bit + * wide big-endian values. + */ +# define SHA512_CBLOCK (SHA_LBLOCK*8) +# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +# define SHA_LONG64 unsigned __int64 +# define U64(C) C##UI64 +# elif defined(__arch64__) +# define SHA_LONG64 unsigned long +# define U64(C) C##UL +# else +# define SHA_LONG64 unsigned long long +# define U64(C) C##ULL +# endif + +typedef struct SHA512state_st { + SHA_LONG64 h[8]; + SHA_LONG64 Nl, Nh; + union { + SHA_LONG64 d[SHA_LBLOCK]; + unsigned char p[SHA512_CBLOCK]; + } u; + unsigned int num, md_len; +} SHA512_CTX; +# endif + +# ifndef OPENSSL_NO_SHA512 +# ifdef OPENSSL_FIPS +int private_SHA384_Init(SHA512_CTX *c); +int private_SHA512_Init(SHA512_CTX *c); +# endif +int SHA384_Init(SHA512_CTX *c); +int SHA384_Update(SHA512_CTX *c, const void *data, size_t len); +int SHA384_Final(unsigned char *md, SHA512_CTX *c); +unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md); +int SHA512_Init(SHA512_CTX *c); +int SHA512_Update(SHA512_CTX *c, const void *data, size_t len); +int SHA512_Final(unsigned char *md, SHA512_CTX *c); +unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md); +void SHA512_Transform(SHA512_CTX *c, const unsigned char *data); +# endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/srp.h b/optee/optee_test/host/openssl/include/openssl/srp.h new file mode 100644 index 0000000..028892a --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/srp.h @@ -0,0 +1,179 @@ +/* crypto/srp/srp.h */ +/* + * Written by Christophe Renou (christophe.renou@edelweb.fr) with the + * precious help of Peter Sylvester (peter.sylvester@edelweb.fr) for the + * EdelKey project and contributed to the OpenSSL project 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef __SRP_H__ +# define __SRP_H__ + +# ifndef OPENSSL_NO_SRP + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# include +# include +# include + +typedef struct SRP_gN_cache_st { + char *b64_bn; + BIGNUM *bn; +} SRP_gN_cache; + + +DECLARE_STACK_OF(SRP_gN_cache) + +typedef struct SRP_user_pwd_st { + /* Owned by us. */ + char *id; + BIGNUM *s; + BIGNUM *v; + /* Not owned by us. */ + const BIGNUM *g; + const BIGNUM *N; + /* Owned by us. */ + char *info; +} SRP_user_pwd; + +DECLARE_STACK_OF(SRP_user_pwd) + +void SRP_user_pwd_free(SRP_user_pwd *user_pwd); + +typedef struct SRP_VBASE_st { + STACK_OF(SRP_user_pwd) *users_pwd; + STACK_OF(SRP_gN_cache) *gN_cache; +/* to simulate a user */ + char *seed_key; + BIGNUM *default_g; + BIGNUM *default_N; +} SRP_VBASE; + +/* + * Structure interne pour retenir les couples N et g + */ +typedef struct SRP_gN_st { + char *id; + BIGNUM *g; + BIGNUM *N; +} SRP_gN; + +DECLARE_STACK_OF(SRP_gN) + +SRP_VBASE *SRP_VBASE_new(char *seed_key); +int SRP_VBASE_free(SRP_VBASE *vb); +int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file); + +/* This method ignores the configured seed and fails for an unknown user. */ +SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username); +/* NOTE: unlike in SRP_VBASE_get_by_user, caller owns the returned pointer.*/ +SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username); + +char *SRP_create_verifier(const char *user, const char *pass, char **salt, + char **verifier, const char *N, const char *g); +int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, + BIGNUM **verifier, BIGNUM *N, BIGNUM *g); + +# define SRP_NO_ERROR 0 +# define SRP_ERR_VBASE_INCOMPLETE_FILE 1 +# define SRP_ERR_VBASE_BN_LIB 2 +# define SRP_ERR_OPEN_FILE 3 +# define SRP_ERR_MEMORY 4 + +# define DB_srptype 0 +# define DB_srpverifier 1 +# define DB_srpsalt 2 +# define DB_srpid 3 +# define DB_srpgN 4 +# define DB_srpinfo 5 +# undef DB_NUMBER +# define DB_NUMBER 6 + +# define DB_SRP_INDEX 'I' +# define DB_SRP_VALID 'V' +# define DB_SRP_REVOKED 'R' +# define DB_SRP_MODIF 'v' + +/* see srp.c */ +char *SRP_check_known_gN_param(BIGNUM *g, BIGNUM *N); +SRP_gN *SRP_get_default_gN(const char *id); + +/* server side .... */ +BIGNUM *SRP_Calc_server_key(BIGNUM *A, BIGNUM *v, BIGNUM *u, BIGNUM *b, + BIGNUM *N); +BIGNUM *SRP_Calc_B(BIGNUM *b, BIGNUM *N, BIGNUM *g, BIGNUM *v); +int SRP_Verify_A_mod_N(BIGNUM *A, BIGNUM *N); +BIGNUM *SRP_Calc_u(BIGNUM *A, BIGNUM *B, BIGNUM *N); + +/* client side .... */ +BIGNUM *SRP_Calc_x(BIGNUM *s, const char *user, const char *pass); +BIGNUM *SRP_Calc_A(BIGNUM *a, BIGNUM *N, BIGNUM *g); +BIGNUM *SRP_Calc_client_key(BIGNUM *N, BIGNUM *B, BIGNUM *g, BIGNUM *x, + BIGNUM *a, BIGNUM *u); +int SRP_Verify_B_mod_N(BIGNUM *B, BIGNUM *N); + +# define SRP_MINIMAL_N 1024 + +#ifdef __cplusplus +} +#endif + +# endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/srtp.h b/optee/optee_test/host/openssl/include/openssl/srtp.h new file mode 100644 index 0000000..2279c32 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/srtp.h @@ -0,0 +1,147 @@ +/* ssl/srtp.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* + * DTLS code by Eric Rescorla + * + * Copyright (C) 2006, Network Resonance, Inc. Copyright (C) 2011, RTFM, Inc. + */ + +#ifndef HEADER_D1_SRTP_H +# define HEADER_D1_SRTP_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define SRTP_AES128_CM_SHA1_80 0x0001 +# define SRTP_AES128_CM_SHA1_32 0x0002 +# define SRTP_AES128_F8_SHA1_80 0x0003 +# define SRTP_AES128_F8_SHA1_32 0x0004 +# define SRTP_NULL_SHA1_80 0x0005 +# define SRTP_NULL_SHA1_32 0x0006 + +# ifndef OPENSSL_NO_SRTP + +int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles); +int SSL_set_tlsext_use_srtp(SSL *ctx, const char *profiles); + +STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl); +SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s); + +# endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ssl.h b/optee/optee_test/host/openssl/include/openssl/ssl.h new file mode 100644 index 0000000..3cf96a2 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ssl.h @@ -0,0 +1,3163 @@ +/* ssl/ssl.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef HEADER_SSL_H +# define HEADER_SSL_H + +# include + +# ifndef OPENSSL_NO_COMP +# include +# endif +# ifndef OPENSSL_NO_BIO +# include +# endif +# ifndef OPENSSL_NO_DEPRECATED +# ifndef OPENSSL_NO_X509 +# include +# endif +# include +# include +# include +# endif +# include +# include + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* SSLeay version number for ASN.1 encoding of the session information */ +/*- + * Version 0 - initial version + * Version 1 - added the optional peer certificate + */ +# define SSL_SESSION_ASN1_VERSION 0x0001 + +/* text strings for the ciphers */ +# define SSL_TXT_NULL_WITH_MD5 SSL2_TXT_NULL_WITH_MD5 +# define SSL_TXT_RC4_128_WITH_MD5 SSL2_TXT_RC4_128_WITH_MD5 +# define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 +# define SSL_TXT_RC2_128_CBC_WITH_MD5 SSL2_TXT_RC2_128_CBC_WITH_MD5 +# define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 +# define SSL_TXT_IDEA_128_CBC_WITH_MD5 SSL2_TXT_IDEA_128_CBC_WITH_MD5 +# define SSL_TXT_DES_64_CBC_WITH_MD5 SSL2_TXT_DES_64_CBC_WITH_MD5 +# define SSL_TXT_DES_64_CBC_WITH_SHA SSL2_TXT_DES_64_CBC_WITH_SHA +# define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 +# define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA + +/* + * VRS Additional Kerberos5 entries + */ +# define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA +# define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA +# define SSL_TXT_KRB5_RC4_128_SHA SSL3_TXT_KRB5_RC4_128_SHA +# define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA +# define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5 +# define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5 +# define SSL_TXT_KRB5_RC4_128_MD5 SSL3_TXT_KRB5_RC4_128_MD5 +# define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5 + +# define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA +# define SSL_TXT_KRB5_RC2_40_CBC_SHA SSL3_TXT_KRB5_RC2_40_CBC_SHA +# define SSL_TXT_KRB5_RC4_40_SHA SSL3_TXT_KRB5_RC4_40_SHA +# define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5 +# define SSL_TXT_KRB5_RC2_40_CBC_MD5 SSL3_TXT_KRB5_RC2_40_CBC_MD5 +# define SSL_TXT_KRB5_RC4_40_MD5 SSL3_TXT_KRB5_RC4_40_MD5 + +# define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA +# define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5 +# define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA +# define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5 +# define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA +# define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5 +# define SSL_MAX_KRB5_PRINCIPAL_LENGTH 256 + +# define SSL_MAX_SSL_SESSION_ID_LENGTH 32 +# define SSL_MAX_SID_CTX_LENGTH 32 + +# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8) +# define SSL_MAX_KEY_ARG_LENGTH 8 +# define SSL_MAX_MASTER_KEY_LENGTH 48 + +/* These are used to specify which ciphers to use and not to use */ + +# define SSL_TXT_EXP40 "EXPORT40" +# define SSL_TXT_EXP56 "EXPORT56" +# define SSL_TXT_LOW "LOW" +# define SSL_TXT_MEDIUM "MEDIUM" +# define SSL_TXT_HIGH "HIGH" +# define SSL_TXT_FIPS "FIPS" + +# define SSL_TXT_kFZA "kFZA"/* unused! */ +# define SSL_TXT_aFZA "aFZA"/* unused! */ +# define SSL_TXT_eFZA "eFZA"/* unused! */ +# define SSL_TXT_FZA "FZA"/* unused! */ + +# define SSL_TXT_aNULL "aNULL" +# define SSL_TXT_eNULL "eNULL" +# define SSL_TXT_NULL "NULL" + +# define SSL_TXT_kRSA "kRSA" +# define SSL_TXT_kDHr "kDHr" +# define SSL_TXT_kDHd "kDHd" +# define SSL_TXT_kDH "kDH" +# define SSL_TXT_kEDH "kEDH" +# define SSL_TXT_kDHE "kDHE"/* alias for kEDH */ +# define SSL_TXT_kKRB5 "kKRB5" +# define SSL_TXT_kECDHr "kECDHr" +# define SSL_TXT_kECDHe "kECDHe" +# define SSL_TXT_kECDH "kECDH" +# define SSL_TXT_kEECDH "kEECDH" +# define SSL_TXT_kECDHE "kECDHE"/* alias for kEECDH */ +# define SSL_TXT_kPSK "kPSK" +# define SSL_TXT_kGOST "kGOST" +# define SSL_TXT_kSRP "kSRP" + +# define SSL_TXT_aRSA "aRSA" +# define SSL_TXT_aDSS "aDSS" +# define SSL_TXT_aDH "aDH" +# define SSL_TXT_aECDH "aECDH" +# define SSL_TXT_aKRB5 "aKRB5" +# define SSL_TXT_aECDSA "aECDSA" +# define SSL_TXT_aPSK "aPSK" +# define SSL_TXT_aGOST94 "aGOST94" +# define SSL_TXT_aGOST01 "aGOST01" +# define SSL_TXT_aGOST "aGOST" +# define SSL_TXT_aSRP "aSRP" + +# define SSL_TXT_DSS "DSS" +# define SSL_TXT_DH "DH" +# define SSL_TXT_EDH "EDH"/* same as "kEDH:-ADH" */ +# define SSL_TXT_DHE "DHE"/* alias for EDH */ +# define SSL_TXT_ADH "ADH" +# define SSL_TXT_RSA "RSA" +# define SSL_TXT_ECDH "ECDH" +# define SSL_TXT_EECDH "EECDH"/* same as "kEECDH:-AECDH" */ +# define SSL_TXT_ECDHE "ECDHE"/* alias for ECDHE" */ +# define SSL_TXT_AECDH "AECDH" +# define SSL_TXT_ECDSA "ECDSA" +# define SSL_TXT_KRB5 "KRB5" +# define SSL_TXT_PSK "PSK" +# define SSL_TXT_SRP "SRP" + +# define SSL_TXT_DES "DES" +# define SSL_TXT_3DES "3DES" +# define SSL_TXT_RC4 "RC4" +# define SSL_TXT_RC2 "RC2" +# define SSL_TXT_IDEA "IDEA" +# define SSL_TXT_SEED "SEED" +# define SSL_TXT_AES128 "AES128" +# define SSL_TXT_AES256 "AES256" +# define SSL_TXT_AES "AES" +# define SSL_TXT_AES_GCM "AESGCM" +# define SSL_TXT_CAMELLIA128 "CAMELLIA128" +# define SSL_TXT_CAMELLIA256 "CAMELLIA256" +# define SSL_TXT_CAMELLIA "CAMELLIA" + +# define SSL_TXT_MD5 "MD5" +# define SSL_TXT_SHA1 "SHA1" +# define SSL_TXT_SHA "SHA"/* same as "SHA1" */ +# define SSL_TXT_GOST94 "GOST94" +# define SSL_TXT_GOST89MAC "GOST89MAC" +# define SSL_TXT_SHA256 "SHA256" +# define SSL_TXT_SHA384 "SHA384" + +# define SSL_TXT_SSLV2 "SSLv2" +# define SSL_TXT_SSLV3 "SSLv3" +# define SSL_TXT_TLSV1 "TLSv1" +# define SSL_TXT_TLSV1_1 "TLSv1.1" +# define SSL_TXT_TLSV1_2 "TLSv1.2" + +# define SSL_TXT_EXP "EXP" +# define SSL_TXT_EXPORT "EXPORT" + +# define SSL_TXT_ALL "ALL" + +/*- + * COMPLEMENTOF* definitions. These identifiers are used to (de-select) + * ciphers normally not being used. + * Example: "RC4" will activate all ciphers using RC4 including ciphers + * without authentication, which would normally disabled by DEFAULT (due + * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT" + * will make sure that it is also disabled in the specific selection. + * COMPLEMENTOF* identifiers are portable between version, as adjustments + * to the default cipher setup will also be included here. + * + * COMPLEMENTOFDEFAULT does not experience the same special treatment that + * DEFAULT gets, as only selection is being done and no sorting as needed + * for DEFAULT. + */ +# define SSL_TXT_CMPALL "COMPLEMENTOFALL" +# define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT" + +/* + * The following cipher list is used by default. It also is substituted when + * an application-defined cipher list string starts with 'DEFAULT'. + */ +# define SSL_DEFAULT_CIPHER_LIST "ALL:!EXPORT:!LOW:!aNULL:!eNULL:!SSLv2" +/* + * As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always + * starts with a reasonable order, and all we have to do for DEFAULT is + * throwing out anonymous and unencrypted ciphersuites! (The latter are not + * actually enabled by ALL, but "ALL:RSA" would enable some of them.) + */ + +/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */ +# define SSL_SENT_SHUTDOWN 1 +# define SSL_RECEIVED_SHUTDOWN 2 + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +# if (defined(OPENSSL_NO_RSA) || defined(OPENSSL_NO_MD5)) && !defined(OPENSSL_NO_SSL2) +# define OPENSSL_NO_SSL2 +# endif + +# define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 +# define SSL_FILETYPE_PEM X509_FILETYPE_PEM + +/* + * This is needed to stop compilers complaining about the 'struct ssl_st *' + * function parameters used to prototype callbacks in SSL_CTX. + */ +typedef struct ssl_st *ssl_crock_st; +typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; +typedef struct ssl_method_st SSL_METHOD; +typedef struct ssl_cipher_st SSL_CIPHER; +typedef struct ssl_session_st SSL_SESSION; +typedef struct tls_sigalgs_st TLS_SIGALGS; +typedef struct ssl_conf_ctx_st SSL_CONF_CTX; + +DECLARE_STACK_OF(SSL_CIPHER) + +/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/ +typedef struct srtp_protection_profile_st { + const char *name; + unsigned long id; +} SRTP_PROTECTION_PROFILE; + +DECLARE_STACK_OF(SRTP_PROTECTION_PROFILE) + +typedef int (*tls_session_ticket_ext_cb_fn) (SSL *s, + const unsigned char *data, + int len, void *arg); +typedef int (*tls_session_secret_cb_fn) (SSL *s, void *secret, + int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, + SSL_CIPHER **cipher, void *arg); + +# ifndef OPENSSL_NO_TLSEXT + +/* Typedefs for handling custom extensions */ + +typedef int (*custom_ext_add_cb) (SSL *s, unsigned int ext_type, + const unsigned char **out, + size_t *outlen, int *al, void *add_arg); + +typedef void (*custom_ext_free_cb) (SSL *s, unsigned int ext_type, + const unsigned char *out, void *add_arg); + +typedef int (*custom_ext_parse_cb) (SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *parse_arg); + +# endif + +# ifndef OPENSSL_NO_SSL_INTERN + +/* used to hold info on the particular ciphers used */ +struct ssl_cipher_st { + int valid; + const char *name; /* text name */ + unsigned long id; /* id, 4 bytes, first is version */ + /* + * changed in 0.9.9: these four used to be portions of a single value + * 'algorithms' + */ + unsigned long algorithm_mkey; /* key exchange algorithm */ + unsigned long algorithm_auth; /* server authentication */ + unsigned long algorithm_enc; /* symmetric encryption */ + unsigned long algorithm_mac; /* symmetric authentication */ + unsigned long algorithm_ssl; /* (major) protocol version */ + unsigned long algo_strength; /* strength and export flags */ + unsigned long algorithm2; /* Extra flags */ + int strength_bits; /* Number of bits really used */ + int alg_bits; /* Number of bits for algorithm */ +}; + +/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ +struct ssl_method_st { + int version; + int (*ssl_new) (SSL *s); + void (*ssl_clear) (SSL *s); + void (*ssl_free) (SSL *s); + int (*ssl_accept) (SSL *s); + int (*ssl_connect) (SSL *s); + int (*ssl_read) (SSL *s, void *buf, int len); + int (*ssl_peek) (SSL *s, void *buf, int len); + int (*ssl_write) (SSL *s, const void *buf, int len); + int (*ssl_shutdown) (SSL *s); + int (*ssl_renegotiate) (SSL *s); + int (*ssl_renegotiate_check) (SSL *s); + long (*ssl_get_message) (SSL *s, int st1, int stn, int mt, long + max, int *ok); + int (*ssl_read_bytes) (SSL *s, int type, unsigned char *buf, int len, + int peek); + int (*ssl_write_bytes) (SSL *s, int type, const void *buf_, int len); + int (*ssl_dispatch_alert) (SSL *s); + long (*ssl_ctrl) (SSL *s, int cmd, long larg, void *parg); + long (*ssl_ctx_ctrl) (SSL_CTX *ctx, int cmd, long larg, void *parg); + const SSL_CIPHER *(*get_cipher_by_char) (const unsigned char *ptr); + int (*put_cipher_by_char) (const SSL_CIPHER *cipher, unsigned char *ptr); + int (*ssl_pending) (const SSL *s); + int (*num_ciphers) (void); + const SSL_CIPHER *(*get_cipher) (unsigned ncipher); + const struct ssl_method_st *(*get_ssl_method) (int version); + long (*get_timeout) (void); + struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */ + int (*ssl_version) (void); + long (*ssl_callback_ctrl) (SSL *s, int cb_id, void (*fp) (void)); + long (*ssl_ctx_callback_ctrl) (SSL_CTX *s, int cb_id, void (*fp) (void)); +}; + +/*- + * Lets make this into an ASN.1 type structure as follows + * SSL_SESSION_ID ::= SEQUENCE { + * version INTEGER, -- structure version number + * SSLversion INTEGER, -- SSL version number + * Cipher OCTET STRING, -- the 3 byte cipher ID + * Session_ID OCTET STRING, -- the Session ID + * Master_key OCTET STRING, -- the master key + * KRB5_principal OCTET STRING -- optional Kerberos principal + * Key_Arg [ 0 ] IMPLICIT OCTET STRING, -- the optional Key argument + * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time + * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds + * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate + * Session_ID_context [ 4 ] EXPLICIT OCTET STRING, -- the Session ID context + * Verify_result [ 5 ] EXPLICIT INTEGER, -- X509_V_... code for `Peer' + * HostName [ 6 ] EXPLICIT OCTET STRING, -- optional HostName from servername TLS extension + * PSK_identity_hint [ 7 ] EXPLICIT OCTET STRING, -- optional PSK identity hint + * PSK_identity [ 8 ] EXPLICIT OCTET STRING, -- optional PSK identity + * Ticket_lifetime_hint [9] EXPLICIT INTEGER, -- server's lifetime hint for session ticket + * Ticket [10] EXPLICIT OCTET STRING, -- session ticket (clients only) + * Compression_meth [11] EXPLICIT OCTET STRING, -- optional compression method + * SRP_username [ 12 ] EXPLICIT OCTET STRING -- optional SRP username + * } + * Look in ssl/ssl_asn1.c for more details + * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-). + */ +struct ssl_session_st { + int ssl_version; /* what ssl version session info is being + * kept in here? */ + /* only really used in SSLv2 */ + unsigned int key_arg_length; + unsigned char key_arg[SSL_MAX_KEY_ARG_LENGTH]; + int master_key_length; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + /* session_id - valid? */ + unsigned int session_id_length; + unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + /* + * this is used to determine whether the session is being reused in the + * appropriate context. It is up to the application to set this, via + * SSL_new + */ + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; +# ifndef OPENSSL_NO_KRB5 + unsigned int krb5_client_princ_len; + unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH]; +# endif /* OPENSSL_NO_KRB5 */ +# ifndef OPENSSL_NO_PSK + char *psk_identity_hint; + char *psk_identity; +# endif + /* + * Used to indicate that session resumption is not allowed. Applications + * can also set this bit for a new session via not_resumable_session_cb + * to disable session caching and tickets. + */ + int not_resumable; + /* The cert is the certificate used to establish this connection */ + struct sess_cert_st /* SESS_CERT */ *sess_cert; + /* + * This is the cert for the other end. On clients, it will be the same as + * sess_cert->peer_key->x509 (the latter is not enough as sess_cert is + * not retained in the external representation of sessions, see + * ssl_asn1.c). + */ + X509 *peer; + /* + * when app_verify_callback accepts a session where the peer's + * certificate is not ok, we must remember the error for session reuse: + */ + long verify_result; /* only for servers */ + int references; + long timeout; + long time; + unsigned int compress_meth; /* Need to lookup the method */ + const SSL_CIPHER *cipher; + unsigned long cipher_id; /* when ASN.1 loaded, this needs to be used + * to load the 'cipher' structure */ + STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */ + CRYPTO_EX_DATA ex_data; /* application specific data */ + /* + * These are used to make removal of session-ids more efficient and to + * implement a maximum cache size. + */ + struct ssl_session_st *prev, *next; +# ifndef OPENSSL_NO_TLSEXT + char *tlsext_hostname; +# ifndef OPENSSL_NO_EC + size_t tlsext_ecpointformatlist_length; + unsigned char *tlsext_ecpointformatlist; /* peer's list */ + size_t tlsext_ellipticcurvelist_length; + unsigned char *tlsext_ellipticcurvelist; /* peer's list */ +# endif /* OPENSSL_NO_EC */ + /* RFC4507 info */ + unsigned char *tlsext_tick; /* Session ticket */ + size_t tlsext_ticklen; /* Session ticket length */ + long tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */ +# endif +# ifndef OPENSSL_NO_SRP + char *srp_username; +# endif +}; + +# endif + +# define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L +# define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L +/* Allow initial connection to servers that don't support RI */ +# define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004L +# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x00000008L +# define SSL_OP_TLSEXT_PADDING 0x00000010L +# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L +# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040L +# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x00000080L +# define SSL_OP_TLS_D5_BUG 0x00000100L +# define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L + +/* Hasn't done anything since OpenSSL 0.9.7h, retained for compatibility */ +# define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0 +/* Refers to ancient SSLREF and SSLv2, retained for compatibility */ +# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x0 + +/* + * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added in + * OpenSSL 0.9.6d. Usually (depending on the application protocol) the + * workaround is not needed. Unfortunately some broken SSL/TLS + * implementations cannot handle it at all, which is why we include it in + * SSL_OP_ALL. + */ +/* added in 0.9.6e */ +# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L + +/* + * SSL_OP_ALL: various bug workarounds that should be rather harmless. This + * used to be 0x000FFFFFL before 0.9.7. + */ +# define SSL_OP_ALL 0x80000BFFL + +/* DTLS options */ +# define SSL_OP_NO_QUERY_MTU 0x00001000L +/* Turn on Cookie Exchange (on relevant for servers) */ +# define SSL_OP_COOKIE_EXCHANGE 0x00002000L +/* Don't use RFC4507 ticket extension */ +# define SSL_OP_NO_TICKET 0x00004000L +/* Use Cisco's "speshul" version of DTLS_BAD_VER (as client) */ +# define SSL_OP_CISCO_ANYCONNECT 0x00008000L + +/* As server, disallow session resumption on renegotiation */ +# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L +/* Don't use compression even if supported */ +# define SSL_OP_NO_COMPRESSION 0x00020000L +/* Permit unsafe legacy renegotiation */ +# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L +/* If set, always create a new key when using tmp_ecdh parameters */ +# define SSL_OP_SINGLE_ECDH_USE 0x00080000L +/* Does nothing: retained for compatibility */ +# define SSL_OP_SINGLE_DH_USE 0x00100000L +/* Does nothing: retained for compatibiity */ +# define SSL_OP_EPHEMERAL_RSA 0x0 +/* + * Set on servers to choose the cipher according to the server's preferences + */ +# define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L +/* + * If set, a server will allow a client to issue a SSLv3.0 version number as + * latest version supported in the premaster secret, even when TLSv1.0 + * (version 3.1) was announced in the client hello. Normally this is + * forbidden to prevent version rollback attacks. + */ +# define SSL_OP_TLS_ROLLBACK_BUG 0x00800000L + +# define SSL_OP_NO_SSLv2 0x01000000L +# define SSL_OP_NO_SSLv3 0x02000000L +# define SSL_OP_NO_TLSv1 0x04000000L +# define SSL_OP_NO_TLSv1_2 0x08000000L +# define SSL_OP_NO_TLSv1_1 0x10000000L + +# define SSL_OP_NO_DTLSv1 0x04000000L +# define SSL_OP_NO_DTLSv1_2 0x08000000L + +# define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|\ + SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2) + +/* + * These next two were never actually used for anything since SSLeay zap so + * we have some more flags. + */ +/* + * The next flag deliberately changes the ciphertest, this is a check for the + * PKCS#1 attack + */ +# define SSL_OP_PKCS1_CHECK_1 0x0 +# define SSL_OP_PKCS1_CHECK_2 0x0 + +# define SSL_OP_NETSCAPE_CA_DN_BUG 0x20000000L +# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x40000000L +/* + * Make server add server-hello extension from early version of cryptopro + * draft, when GOST ciphersuite is negotiated. Required for interoperability + * with CryptoPro CSP 3.x + */ +# define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x80000000L + +/* + * Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success + * when just a single record has been written): + */ +# define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L +/* + * Make it possible to retry SSL_write() with changed buffer location (buffer + * contents must stay the same!); this is not the default to avoid the + * misconception that non-blocking SSL_write() behaves like non-blocking + * write(): + */ +# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L +/* + * Never bother the application with retries if the transport is blocking: + */ +# define SSL_MODE_AUTO_RETRY 0x00000004L +/* Don't attempt to automatically build certificate chain */ +# define SSL_MODE_NO_AUTO_CHAIN 0x00000008L +/* + * Save RAM by releasing read and write buffers when they're empty. (SSL3 and + * TLS only.) "Released" buffers are put onto a free-list in the context or + * just freed (depending on the context's setting for freelist_max_len). + */ +# define SSL_MODE_RELEASE_BUFFERS 0x00000010L +/* + * Send the current time in the Random fields of the ClientHello and + * ServerHello records for compatibility with hypothetical implementations + * that require it. + */ +# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020L +# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040L +/* + * Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications + * that reconnect with a downgraded protocol version; see + * draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your + * application attempts a normal handshake. Only use this in explicit + * fallback retries, following the guidance in + * draft-ietf-tls-downgrade-scsv-00. + */ +# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080L + +/* Cert related flags */ +/* + * Many implementations ignore some aspects of the TLS standards such as + * enforcing certifcate chain algorithms. When this is set we enforce them. + */ +# define SSL_CERT_FLAG_TLS_STRICT 0x00000001L + +/* Suite B modes, takes same values as certificate verify flags */ +# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY 0x10000 +/* Suite B 192 bit only mode */ +# define SSL_CERT_FLAG_SUITEB_192_LOS 0x20000 +/* Suite B 128 bit mode allowing 192 bit algorithms */ +# define SSL_CERT_FLAG_SUITEB_128_LOS 0x30000 + +/* Perform all sorts of protocol violations for testing purposes */ +# define SSL_CERT_FLAG_BROKEN_PROTOCOL 0x10000000 + +/* Flags for building certificate chains */ +/* Treat any existing certificates as untrusted CAs */ +# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1 +/* Don't include root CA in chain */ +# define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2 +/* Just check certificates already there */ +# define SSL_BUILD_CHAIN_FLAG_CHECK 0x4 +/* Ignore verification errors */ +# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR 0x8 +/* Clear verification errors from queue */ +# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR 0x10 + +/* Flags returned by SSL_check_chain */ +/* Certificate can be used with this session */ +# define CERT_PKEY_VALID 0x1 +/* Certificate can also be used for signing */ +# define CERT_PKEY_SIGN 0x2 +/* EE certificate signing algorithm OK */ +# define CERT_PKEY_EE_SIGNATURE 0x10 +/* CA signature algorithms OK */ +# define CERT_PKEY_CA_SIGNATURE 0x20 +/* EE certificate parameters OK */ +# define CERT_PKEY_EE_PARAM 0x40 +/* CA certificate parameters OK */ +# define CERT_PKEY_CA_PARAM 0x80 +/* Signing explicitly allowed as opposed to SHA1 fallback */ +# define CERT_PKEY_EXPLICIT_SIGN 0x100 +/* Client CA issuer names match (always set for server cert) */ +# define CERT_PKEY_ISSUER_NAME 0x200 +/* Cert type matches client types (always set for server cert) */ +# define CERT_PKEY_CERT_TYPE 0x400 +/* Cert chain suitable to Suite B */ +# define CERT_PKEY_SUITEB 0x800 + +# define SSL_CONF_FLAG_CMDLINE 0x1 +# define SSL_CONF_FLAG_FILE 0x2 +# define SSL_CONF_FLAG_CLIENT 0x4 +# define SSL_CONF_FLAG_SERVER 0x8 +# define SSL_CONF_FLAG_SHOW_ERRORS 0x10 +# define SSL_CONF_FLAG_CERTIFICATE 0x20 +/* Configuration value types */ +# define SSL_CONF_TYPE_UNKNOWN 0x0 +# define SSL_CONF_TYPE_STRING 0x1 +# define SSL_CONF_TYPE_FILE 0x2 +# define SSL_CONF_TYPE_DIR 0x3 + +/* + * Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they + * cannot be used to clear bits. + */ + +# define SSL_CTX_set_options(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL) +# define SSL_CTX_clear_options(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL) +# define SSL_CTX_get_options(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL) +# define SSL_set_options(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL) +# define SSL_clear_options(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL) +# define SSL_get_options(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL) + +# define SSL_CTX_set_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) +# define SSL_CTX_clear_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL) +# define SSL_CTX_get_mode(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL) +# define SSL_clear_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL) +# define SSL_set_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) +# define SSL_get_mode(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL) +# define SSL_set_mtu(ssl, mtu) \ + SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL) +# define DTLS_set_link_mtu(ssl, mtu) \ + SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL) +# define DTLS_get_link_min_mtu(ssl) \ + SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL) + +# define SSL_get_secure_renegotiation_support(ssl) \ + SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL) + +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_heartbeat(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_TLS_EXT_SEND_HEARTBEAT,0,NULL) +# endif + +# define SSL_CTX_set_cert_flags(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL) +# define SSL_set_cert_flags(s,op) \ + SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL) +# define SSL_CTX_clear_cert_flags(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL) +# define SSL_clear_cert_flags(s,op) \ + SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL) + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, + void (*cb) (int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)); +void SSL_set_msg_callback(SSL *ssl, + void (*cb) (int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)); +# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) + +# ifndef OPENSSL_NO_SRP + +# ifndef OPENSSL_NO_SSL_INTERN + +typedef struct srp_ctx_st { + /* param for all the callbacks */ + void *SRP_cb_arg; + /* set client Hello login callback */ + int (*TLS_ext_srp_username_callback) (SSL *, int *, void *); + /* set SRP N/g param callback for verification */ + int (*SRP_verify_param_callback) (SSL *, void *); + /* set SRP client passwd callback */ + char *(*SRP_give_srp_client_pwd_callback) (SSL *, void *); + char *login; + BIGNUM *N, *g, *s, *B, *A; + BIGNUM *a, *b, *v; + char *info; + int strength; + unsigned long srp_Mask; +} SRP_CTX; + +# endif + +/* see tls_srp.c */ +int SSL_SRP_CTX_init(SSL *s); +int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx); +int SSL_SRP_CTX_free(SSL *ctx); +int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx); +int SSL_srp_server_param_with_username(SSL *s, int *ad); +int SRP_generate_server_master_secret(SSL *s, unsigned char *master_key); +int SRP_Calc_A_param(SSL *s); +int SRP_generate_client_master_secret(SSL *s, unsigned char *master_key); + +# endif + +# if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32) +# define SSL_MAX_CERT_LIST_DEFAULT 1024*30 + /* 30k max cert list :-) */ +# else +# define SSL_MAX_CERT_LIST_DEFAULT 1024*100 + /* 100k max cert list :-) */ +# endif + +# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20) + +/* + * This callback type is used inside SSL_CTX, SSL, and in the functions that + * set them. It is used to override the generation of SSL/TLS session IDs in + * a server. Return value should be zero on an error, non-zero to proceed. + * Also, callbacks should themselves check if the id they generate is unique + * otherwise the SSL handshake will fail with an error - callbacks can do + * this using the 'ssl' value they're passed by; + * SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in + * is set at the maximum size the session ID can be. In SSLv2 this is 16 + * bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback can alter this + * length to be less if desired, but under SSLv2 session IDs are supposed to + * be fixed at 16 bytes so the id will be padded after the callback returns + * in this case. It is also an error for the callback to set the size to + * zero. + */ +typedef int (*GEN_SESSION_CB) (const SSL *ssl, unsigned char *id, + unsigned int *id_len); + +typedef struct ssl_comp_st SSL_COMP; + +# ifndef OPENSSL_NO_SSL_INTERN + +struct ssl_comp_st { + int id; + const char *name; +# ifndef OPENSSL_NO_COMP + COMP_METHOD *method; +# else + char *method; +# endif +}; + +DECLARE_STACK_OF(SSL_COMP) +DECLARE_LHASH_OF(SSL_SESSION); + +struct ssl_ctx_st { + const SSL_METHOD *method; + STACK_OF(SSL_CIPHER) *cipher_list; + /* same as above but sorted for lookup */ + STACK_OF(SSL_CIPHER) *cipher_list_by_id; + struct x509_store_st /* X509_STORE */ *cert_store; + LHASH_OF(SSL_SESSION) *sessions; + /* + * Most session-ids that will be cached, default is + * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. + */ + unsigned long session_cache_size; + struct ssl_session_st *session_cache_head; + struct ssl_session_st *session_cache_tail; + /* + * This can have one of 2 values, ored together, SSL_SESS_CACHE_CLIENT, + * SSL_SESS_CACHE_SERVER, Default is SSL_SESSION_CACHE_SERVER, which + * means only SSL_accept which cache SSL_SESSIONS. + */ + int session_cache_mode; + /* + * If timeout is not 0, it is the default timeout value set when + * SSL_new() is called. This has been put in to make life easier to set + * things up + */ + long session_timeout; + /* + * If this callback is not null, it will be called each time a session id + * is added to the cache. If this function returns 1, it means that the + * callback will do a SSL_SESSION_free() when it has finished using it. + * Otherwise, on 0, it means the callback has finished with it. If + * remove_session_cb is not null, it will be called when a session-id is + * removed from the cache. After the call, OpenSSL will + * SSL_SESSION_free() it. + */ + int (*new_session_cb) (struct ssl_st *ssl, SSL_SESSION *sess); + void (*remove_session_cb) (struct ssl_ctx_st *ctx, SSL_SESSION *sess); + SSL_SESSION *(*get_session_cb) (struct ssl_st *ssl, + unsigned char *data, int len, int *copy); + struct { + int sess_connect; /* SSL new conn - started */ + int sess_connect_renegotiate; /* SSL reneg - requested */ + int sess_connect_good; /* SSL new conne/reneg - finished */ + int sess_accept; /* SSL new accept - started */ + int sess_accept_renegotiate; /* SSL reneg - requested */ + int sess_accept_good; /* SSL accept/reneg - finished */ + int sess_miss; /* session lookup misses */ + int sess_timeout; /* reuse attempt on timeouted session */ + int sess_cache_full; /* session removed due to full cache */ + int sess_hit; /* session reuse actually done */ + int sess_cb_hit; /* session-id that was not in the cache was + * passed back via the callback. This + * indicates that the application is + * supplying session-id's from other + * processes - spooky :-) */ + } stats; + + int references; + + /* if defined, these override the X509_verify_cert() calls */ + int (*app_verify_callback) (X509_STORE_CTX *, void *); + void *app_verify_arg; + /* + * before OpenSSL 0.9.7, 'app_verify_arg' was ignored + * ('app_verify_callback' was called with just one argument) + */ + + /* Default password callback. */ + pem_password_cb *default_passwd_callback; + + /* Default password callback user data. */ + void *default_passwd_callback_userdata; + + /* get client cert callback */ + int (*client_cert_cb) (SSL *ssl, X509 **x509, EVP_PKEY **pkey); + + /* cookie generate callback */ + int (*app_gen_cookie_cb) (SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len); + + /* verify cookie callback */ + int (*app_verify_cookie_cb) (SSL *ssl, unsigned char *cookie, + unsigned int cookie_len); + + CRYPTO_EX_DATA ex_data; + + const EVP_MD *rsa_md5; /* For SSLv2 - name is 'ssl2-md5' */ + const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */ + const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */ + + STACK_OF(X509) *extra_certs; + STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */ + + /* Default values used when no per-SSL value is defined follow */ + + /* used if SSL's info_callback is NULL */ + void (*info_callback) (const SSL *ssl, int type, int val); + + /* what we put in client cert requests */ + STACK_OF(X509_NAME) *client_CA; + + /* + * Default values to use in SSL structures follow (these are copied by + * SSL_new) + */ + + unsigned long options; + unsigned long mode; + long max_cert_list; + + struct cert_st /* CERT */ *cert; + int read_ahead; + + /* callback that allows applications to peek at protocol messages */ + void (*msg_callback) (int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); + void *msg_callback_arg; + + int verify_mode; + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + /* called 'verify_callback' in the SSL */ + int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx); + + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + + X509_VERIFY_PARAM *param; + +# if 0 + int purpose; /* Purpose setting */ + int trust; /* Trust setting */ +# endif + + int quiet_shutdown; + + /* + * Maximum amount of data to send in one fragment. actual record size can + * be more than this due to padding and MAC overheads. + */ + unsigned int max_send_fragment; + +# ifndef OPENSSL_NO_ENGINE + /* + * Engine to pass requests for client certs to + */ + ENGINE *client_cert_engine; +# endif + +# ifndef OPENSSL_NO_TLSEXT + /* TLS extensions servername callback */ + int (*tlsext_servername_callback) (SSL *, int *, void *); + void *tlsext_servername_arg; + /* RFC 4507 session ticket keys */ + unsigned char tlsext_tick_key_name[16]; + unsigned char tlsext_tick_hmac_key[16]; + unsigned char tlsext_tick_aes_key[16]; + /* Callback to support customisation of ticket key setting */ + int (*tlsext_ticket_key_cb) (SSL *ssl, + unsigned char *name, unsigned char *iv, + EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc); + + /* certificate status request info */ + /* Callback for status request */ + int (*tlsext_status_cb) (SSL *ssl, void *arg); + void *tlsext_status_arg; + + /* draft-rescorla-tls-opaque-prf-input-00.txt information */ + int (*tlsext_opaque_prf_input_callback) (SSL *, void *peerinput, + size_t len, void *arg); + void *tlsext_opaque_prf_input_callback_arg; +# endif + +# ifndef OPENSSL_NO_PSK + char *psk_identity_hint; + unsigned int (*psk_client_callback) (SSL *ssl, const char *hint, + char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len); + unsigned int (*psk_server_callback) (SSL *ssl, const char *identity, + unsigned char *psk, + unsigned int max_psk_len); +# endif + +# ifndef OPENSSL_NO_BUF_FREELISTS +# define SSL_MAX_BUF_FREELIST_LEN_DEFAULT 32 + unsigned int freelist_max_len; + struct ssl3_buf_freelist_st *wbuf_freelist; + struct ssl3_buf_freelist_st *rbuf_freelist; +# endif +# ifndef OPENSSL_NO_SRP + SRP_CTX srp_ctx; /* ctx for SRP authentication */ +# endif + +# ifndef OPENSSL_NO_TLSEXT + +# ifndef OPENSSL_NO_NEXTPROTONEG + /* Next protocol negotiation information */ + /* (for experimental NPN extension). */ + + /* + * For a server, this contains a callback function by which the set of + * advertised protocols can be provided. + */ + int (*next_protos_advertised_cb) (SSL *s, const unsigned char **buf, + unsigned int *len, void *arg); + void *next_protos_advertised_cb_arg; + /* + * For a client, this contains a callback function that selects the next + * protocol from the list provided by the server. + */ + int (*next_proto_select_cb) (SSL *s, unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, void *arg); + void *next_proto_select_cb_arg; +# endif + /* SRTP profiles we are willing to do from RFC 5764 */ + STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; + + /* + * ALPN information (we are in the process of transitioning from NPN to + * ALPN.) + */ + + /*- + * For a server, this contains a callback function that allows the + * server to select the protocol for the connection. + * out: on successful return, this must point to the raw protocol + * name (without the length prefix). + * outlen: on successful return, this contains the length of |*out|. + * in: points to the client's list of supported protocols in + * wire-format. + * inlen: the length of |in|. + */ + int (*alpn_select_cb) (SSL *s, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, void *arg); + void *alpn_select_cb_arg; + + /* + * For a client, this contains the list of supported protocols in wire + * format. + */ + unsigned char *alpn_client_proto_list; + unsigned alpn_client_proto_list_len; + +# ifndef OPENSSL_NO_EC + /* EC extension values inherited by SSL structure */ + size_t tlsext_ecpointformatlist_length; + unsigned char *tlsext_ecpointformatlist; + size_t tlsext_ellipticcurvelist_length; + unsigned char *tlsext_ellipticcurvelist; +# endif /* OPENSSL_NO_EC */ +# endif +}; + +# endif + +# define SSL_SESS_CACHE_OFF 0x0000 +# define SSL_SESS_CACHE_CLIENT 0x0001 +# define SSL_SESS_CACHE_SERVER 0x0002 +# define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER) +# define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080 +/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */ +# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100 +# define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200 +# define SSL_SESS_CACHE_NO_INTERNAL \ + (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE) + +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx); +# define SSL_CTX_sess_number(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL) +# define SSL_CTX_sess_connect(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL) +# define SSL_CTX_sess_connect_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL) +# define SSL_CTX_sess_connect_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL) +# define SSL_CTX_sess_accept(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL) +# define SSL_CTX_sess_accept_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL) +# define SSL_CTX_sess_accept_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL) +# define SSL_CTX_sess_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL) +# define SSL_CTX_sess_cb_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL) +# define SSL_CTX_sess_misses(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL) +# define SSL_CTX_sess_timeouts(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL) +# define SSL_CTX_sess_cache_full(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL) + +void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, + int (*new_session_cb) (struct ssl_st *ssl, + SSL_SESSION *sess)); +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl, + SSL_SESSION *sess); +void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, + void (*remove_session_cb) (struct ssl_ctx_st + *ctx, + SSL_SESSION + *sess)); +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx, + SSL_SESSION *sess); +void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, + SSL_SESSION *(*get_session_cb) (struct ssl_st + *ssl, + unsigned char + *data, int len, + int *copy)); +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl, + unsigned char *Data, + int len, int *copy); +void SSL_CTX_set_info_callback(SSL_CTX *ctx, + void (*cb) (const SSL *ssl, int type, + int val)); +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type, + int val); +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, + int (*client_cert_cb) (SSL *ssl, X509 **x509, + EVP_PKEY **pkey)); +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509, + EVP_PKEY **pkey); +# ifndef OPENSSL_NO_ENGINE +int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e); +# endif +void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, + int (*app_gen_cookie_cb) (SSL *ssl, + unsigned char + *cookie, + unsigned int + *cookie_len)); +void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, + int (*app_verify_cookie_cb) (SSL *ssl, + unsigned char + *cookie, + unsigned int + cookie_len)); +# ifndef OPENSSL_NO_NEXTPROTONEG +void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s, + int (*cb) (SSL *ssl, + const unsigned char + **out, + unsigned int *outlen, + void *arg), void *arg); +void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, + int (*cb) (SSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, + unsigned *len); +# endif + +# ifndef OPENSSL_NO_TLSEXT +int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const unsigned char *client, + unsigned int client_len); +# endif + +# define OPENSSL_NPN_UNSUPPORTED 0 +# define OPENSSL_NPN_NEGOTIATED 1 +# define OPENSSL_NPN_NO_OVERLAP 2 + +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, + unsigned protos_len); +int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned protos_len); +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned *len); + +# ifndef OPENSSL_NO_PSK +/* + * the maximum length of the buffer given to callbacks containing the + * resulting identity/psk + */ +# define PSK_MAX_IDENTITY_LEN 128 +# define PSK_MAX_PSK_LEN 256 +void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, + unsigned int (*psk_client_callback) (SSL + *ssl, + const + char + *hint, + char + *identity, + unsigned + int + max_identity_len, + unsigned + char + *psk, + unsigned + int + max_psk_len)); +void SSL_set_psk_client_callback(SSL *ssl, + unsigned int (*psk_client_callback) (SSL + *ssl, + const + char + *hint, + char + *identity, + unsigned + int + max_identity_len, + unsigned + char + *psk, + unsigned + int + max_psk_len)); +void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, + unsigned int (*psk_server_callback) (SSL + *ssl, + const + char + *identity, + unsigned + char + *psk, + unsigned + int + max_psk_len)); +void SSL_set_psk_server_callback(SSL *ssl, + unsigned int (*psk_server_callback) (SSL + *ssl, + const + char + *identity, + unsigned + char + *psk, + unsigned + int + max_psk_len)); +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint); +int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint); +const char *SSL_get_psk_identity_hint(const SSL *s); +const char *SSL_get_psk_identity(const SSL *s); +# endif + +# ifndef OPENSSL_NO_TLSEXT +/* Register callbacks to handle custom TLS Extensions for client or server. */ + +int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type, + custom_ext_add_cb add_cb, + custom_ext_free_cb free_cb, + void *add_arg, + custom_ext_parse_cb parse_cb, + void *parse_arg); + +int SSL_extension_supported(unsigned int ext_type); + +# endif + +# define SSL_NOTHING 1 +# define SSL_WRITING 2 +# define SSL_READING 3 +# define SSL_X509_LOOKUP 4 + +/* These will only be used when doing non-blocking IO */ +# define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING) +# define SSL_want_read(s) (SSL_want(s) == SSL_READING) +# define SSL_want_write(s) (SSL_want(s) == SSL_WRITING) +# define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP) + +# define SSL_MAC_FLAG_READ_MAC_STREAM 1 +# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2 + +# ifndef OPENSSL_NO_SSL_INTERN + +struct ssl_st { + /* + * protocol version (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, + * DTLS1_VERSION) + */ + int version; + /* SSL_ST_CONNECT or SSL_ST_ACCEPT */ + int type; + /* SSLv3 */ + const SSL_METHOD *method; + /* + * There are 2 BIO's even though they are normally both the same. This + * is so data can be read and written to different handlers + */ +# ifndef OPENSSL_NO_BIO + /* used by SSL_read */ + BIO *rbio; + /* used by SSL_write */ + BIO *wbio; + /* used during session-id reuse to concatenate messages */ + BIO *bbio; +# else + /* used by SSL_read */ + char *rbio; + /* used by SSL_write */ + char *wbio; + char *bbio; +# endif + /* + * This holds a variable that indicates what we were doing when a 0 or -1 + * is returned. This is needed for non-blocking IO so we know what + * request needs re-doing when in SSL_accept or SSL_connect + */ + int rwstate; + /* true when we are actually in SSL_accept() or SSL_connect() */ + int in_handshake; + int (*handshake_func) (SSL *); + /* + * Imagine that here's a boolean member "init" that is switched as soon + * as SSL_set_{accept/connect}_state is called for the first time, so + * that "state" and "handshake_func" are properly initialized. But as + * handshake_func is == 0 until then, we use this test instead of an + * "init" member. + */ + /* are we the server side? - mostly used by SSL_clear */ + int server; + /* + * Generate a new session or reuse an old one. + * NB: For servers, the 'new' session may actually be a previously + * cached session or even the previous session unless + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set + */ + int new_session; + /* don't send shutdown packets */ + int quiet_shutdown; + /* we have shut things down, 0x01 sent, 0x02 for received */ + int shutdown; + /* where we are */ + int state; + /* where we are when reading */ + int rstate; + BUF_MEM *init_buf; /* buffer used during init */ + void *init_msg; /* pointer to handshake message body, set by + * ssl3_get_message() */ + int init_num; /* amount read/written */ + int init_off; /* amount read/written */ + /* used internally to point at a raw packet */ + unsigned char *packet; + unsigned int packet_length; + struct ssl2_state_st *s2; /* SSLv2 variables */ + struct ssl3_state_st *s3; /* SSLv3 variables */ + struct dtls1_state_st *d1; /* DTLSv1 variables */ + int read_ahead; /* Read as many input bytes as possible (for + * non-blocking reads) */ + /* callback that allows applications to peek at protocol messages */ + void (*msg_callback) (int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); + void *msg_callback_arg; + int hit; /* reusing a previous session */ + X509_VERIFY_PARAM *param; +# if 0 + int purpose; /* Purpose setting */ + int trust; /* Trust setting */ +# endif + /* crypto */ + STACK_OF(SSL_CIPHER) *cipher_list; + STACK_OF(SSL_CIPHER) *cipher_list_by_id; + /* + * These are the ones being used, the ones in SSL_SESSION are the ones to + * be 'copied' into these ones + */ + int mac_flags; + EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */ + EVP_MD_CTX *read_hash; /* used for mac generation */ +# ifndef OPENSSL_NO_COMP + COMP_CTX *expand; /* uncompress */ +# else + char *expand; +# endif + EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ + EVP_MD_CTX *write_hash; /* used for mac generation */ +# ifndef OPENSSL_NO_COMP + COMP_CTX *compress; /* compression */ +# else + char *compress; +# endif + /* session info */ + /* client cert? */ + /* This is used to hold the server certificate used */ + struct cert_st /* CERT */ *cert; + /* + * the session_id_context is used to ensure sessions are only reused in + * the appropriate context + */ + unsigned int sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + /* This can also be in the session once a session is established */ + SSL_SESSION *session; + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + /* Used in SSL2 and SSL3 */ + /* + * 0 don't care about verify failure. + * 1 fail if verify fails + */ + int verify_mode; + /* fail if callback returns 0 */ + int (*verify_callback) (int ok, X509_STORE_CTX *ctx); + /* optional informational callback */ + void (*info_callback) (const SSL *ssl, int type, int val); + /* error bytes to be written */ + int error; + /* actual code */ + int error_code; +# ifndef OPENSSL_NO_KRB5 + /* Kerberos 5 context */ + KSSL_CTX *kssl_ctx; +# endif /* OPENSSL_NO_KRB5 */ +# ifndef OPENSSL_NO_PSK + unsigned int (*psk_client_callback) (SSL *ssl, const char *hint, + char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len); + unsigned int (*psk_server_callback) (SSL *ssl, const char *identity, + unsigned char *psk, + unsigned int max_psk_len); +# endif + SSL_CTX *ctx; + /* + * set this flag to 1 and a sleep(1) is put into all SSL_read() and + * SSL_write() calls, good for nbio debuging :-) + */ + int debug; + /* extra application data */ + long verify_result; + CRYPTO_EX_DATA ex_data; + /* for server side, keep the list of CA_dn we can use */ + STACK_OF(X509_NAME) *client_CA; + int references; + /* protocol behaviour */ + unsigned long options; + /* API behaviour */ + unsigned long mode; + long max_cert_list; + int first_packet; + /* what was passed, used for SSLv3/TLS rollback check */ + int client_version; + unsigned int max_send_fragment; +# ifndef OPENSSL_NO_TLSEXT + /* TLS extension debug callback */ + void (*tlsext_debug_cb) (SSL *s, int client_server, int type, + unsigned char *data, int len, void *arg); + void *tlsext_debug_arg; + char *tlsext_hostname; + /*- + * no further mod of servername + * 0 : call the servername extension callback. + * 1 : prepare 2, allow last ack just after in server callback. + * 2 : don't call servername callback, no ack in server hello + */ + int servername_done; + /* certificate status request info */ + /* Status type or -1 if no status type */ + int tlsext_status_type; + /* Expect OCSP CertificateStatus message */ + int tlsext_status_expected; + /* OCSP status request only */ + STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids; + X509_EXTENSIONS *tlsext_ocsp_exts; + /* OCSP response received or to be sent */ + unsigned char *tlsext_ocsp_resp; + int tlsext_ocsp_resplen; + /* RFC4507 session ticket expected to be received or sent */ + int tlsext_ticket_expected; +# ifndef OPENSSL_NO_EC + size_t tlsext_ecpointformatlist_length; + /* our list */ + unsigned char *tlsext_ecpointformatlist; + size_t tlsext_ellipticcurvelist_length; + /* our list */ + unsigned char *tlsext_ellipticcurvelist; +# endif /* OPENSSL_NO_EC */ + /* + * draft-rescorla-tls-opaque-prf-input-00.txt information to be used for + * handshakes + */ + void *tlsext_opaque_prf_input; + size_t tlsext_opaque_prf_input_len; + /* TLS Session Ticket extension override */ + TLS_SESSION_TICKET_EXT *tlsext_session_ticket; + /* TLS Session Ticket extension callback */ + tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb; + void *tls_session_ticket_ext_cb_arg; + /* TLS pre-shared secret session resumption */ + tls_session_secret_cb_fn tls_session_secret_cb; + void *tls_session_secret_cb_arg; + SSL_CTX *initial_ctx; /* initial ctx, used to store sessions */ +# ifndef OPENSSL_NO_NEXTPROTONEG + /* + * Next protocol negotiation. For the client, this is the protocol that + * we sent in NextProtocol and is set when handling ServerHello + * extensions. For a server, this is the client's selected_protocol from + * NextProtocol and is set when handling the NextProtocol message, before + * the Finished message. + */ + unsigned char *next_proto_negotiated; + unsigned char next_proto_negotiated_len; +# endif +# define session_ctx initial_ctx + /* What we'll do */ + STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; + /* What's been chosen */ + SRTP_PROTECTION_PROFILE *srtp_profile; + /*- + * Is use of the Heartbeat extension negotiated? + * 0: disabled + * 1: enabled + * 2: enabled, but not allowed to send Requests + */ + unsigned int tlsext_heartbeat; + /* Indicates if a HeartbeatRequest is in flight */ + unsigned int tlsext_hb_pending; + /* HeartbeatRequest sequence number */ + unsigned int tlsext_hb_seq; +# else +# define session_ctx ctx +# endif /* OPENSSL_NO_TLSEXT */ + /*- + * 1 if we are renegotiating. + * 2 if we are a server and are inside a handshake + * (i.e. not just sending a HelloRequest) + */ + int renegotiate; +# ifndef OPENSSL_NO_SRP + /* ctx for SRP authentication */ + SRP_CTX srp_ctx; +# endif +# ifndef OPENSSL_NO_TLSEXT + /* + * For a client, this contains the list of supported protocols in wire + * format. + */ + unsigned char *alpn_client_proto_list; + unsigned alpn_client_proto_list_len; +# endif /* OPENSSL_NO_TLSEXT */ +}; + +# endif + +#ifdef __cplusplus +} +#endif + +# include +# include +# include /* This is mostly sslv3 with a few tweaks */ +# include /* Datagram TLS */ +# include +# include /* Support for the use_srtp extension */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* compatibility */ +# define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)arg)) +# define SSL_get_app_data(s) (SSL_get_ex_data(s,0)) +# define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0,(char *)a)) +# define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0)) +# define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0)) +# define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0,(char *)arg)) + +/* + * The following are the possible values for ssl->state are are used to + * indicate where we are up to in the SSL connection establishment. The + * macros that follow are about the only things you should need to use and + * even then, only when using non-blocking IO. It can also be useful to work + * out where you were when the connection failed + */ + +# define SSL_ST_CONNECT 0x1000 +# define SSL_ST_ACCEPT 0x2000 +# define SSL_ST_MASK 0x0FFF +# define SSL_ST_INIT (SSL_ST_CONNECT|SSL_ST_ACCEPT) +# define SSL_ST_BEFORE 0x4000 +# define SSL_ST_OK 0x03 +# define SSL_ST_RENEGOTIATE (0x04|SSL_ST_INIT) +# define SSL_ST_ERR (0x05|SSL_ST_INIT) + +# define SSL_CB_LOOP 0x01 +# define SSL_CB_EXIT 0x02 +# define SSL_CB_READ 0x04 +# define SSL_CB_WRITE 0x08 +# define SSL_CB_ALERT 0x4000/* used in callback */ +# define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ) +# define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE) +# define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP) +# define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT) +# define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP) +# define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT) +# define SSL_CB_HANDSHAKE_START 0x10 +# define SSL_CB_HANDSHAKE_DONE 0x20 + +/* Is the SSL_connection established? */ +# define SSL_get_state(a) SSL_state(a) +# define SSL_is_init_finished(a) (SSL_state(a) == SSL_ST_OK) +# define SSL_in_init(a) (SSL_state(a)&SSL_ST_INIT) +# define SSL_in_before(a) (SSL_state(a)&SSL_ST_BEFORE) +# define SSL_in_connect_init(a) (SSL_state(a)&SSL_ST_CONNECT) +# define SSL_in_accept_init(a) (SSL_state(a)&SSL_ST_ACCEPT) + +/* + * The following 2 states are kept in ssl->rstate when reads fail, you should + * not need these + */ +# define SSL_ST_READ_HEADER 0xF0 +# define SSL_ST_READ_BODY 0xF1 +# define SSL_ST_READ_DONE 0xF2 + +/*- + * Obtain latest Finished message + * -- that we sent (SSL_get_finished) + * -- that we expected from peer (SSL_get_peer_finished). + * Returns length (0 == no Finished so far), copies up to 'count' bytes. + */ +size_t SSL_get_finished(const SSL *s, void *buf, size_t count); +size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); + +/* + * use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options are + * 'ored' with SSL_VERIFY_PEER if they are desired + */ +# define SSL_VERIFY_NONE 0x00 +# define SSL_VERIFY_PEER 0x01 +# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 +# define SSL_VERIFY_CLIENT_ONCE 0x04 + +# define OpenSSL_add_ssl_algorithms() SSL_library_init() +# define SSLeay_add_ssl_algorithms() SSL_library_init() + +/* this is for backward compatibility */ +# if 0 /* NEW_SSLEAY */ +# define SSL_CTX_set_default_verify(a,b,c) SSL_CTX_set_verify(a,b,c) +# define SSL_set_pref_cipher(c,n) SSL_set_cipher_list(c,n) +# define SSL_add_session(a,b) SSL_CTX_add_session((a),(b)) +# define SSL_remove_session(a,b) SSL_CTX_remove_session((a),(b)) +# define SSL_flush_sessions(a,b) SSL_CTX_flush_sessions((a),(b)) +# endif +/* More backward compatibility */ +# define SSL_get_cipher(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +# define SSL_get_cipher_bits(s,np) \ + SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np) +# define SSL_get_cipher_version(s) \ + SSL_CIPHER_get_version(SSL_get_current_cipher(s)) +# define SSL_get_cipher_name(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +# define SSL_get_time(a) SSL_SESSION_get_time(a) +# define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b)) +# define SSL_get_timeout(a) SSL_SESSION_get_timeout(a) +# define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b)) + +# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id) +# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id) + +DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) +# define SSL_AD_REASON_OFFSET 1000/* offset to get SSL_R_... value + * from SSL_AD_... */ +/* These alert types are for SSLv3 and TLSv1 */ +# define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY +/* fatal */ +# define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE +/* fatal */ +# define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC +# define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED +# define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW +/* fatal */ +# define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE +/* fatal */ +# define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE +/* Not for TLS */ +# define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE +# define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE +# define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE +# define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED +# define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED +# define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN +/* fatal */ +# define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER +/* fatal */ +# define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA +/* fatal */ +# define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED +/* fatal */ +# define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR +# define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR +/* fatal */ +# define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION +/* fatal */ +# define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION +/* fatal */ +# define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY +/* fatal */ +# define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR +# define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED +# define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION +# define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION +# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE +# define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME +# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE +# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE +/* fatal */ +# define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY +/* fatal */ +# define SSL_AD_INAPPROPRIATE_FALLBACK TLS1_AD_INAPPROPRIATE_FALLBACK +# define SSL_ERROR_NONE 0 +# define SSL_ERROR_SSL 1 +# define SSL_ERROR_WANT_READ 2 +# define SSL_ERROR_WANT_WRITE 3 +# define SSL_ERROR_WANT_X509_LOOKUP 4 +# define SSL_ERROR_SYSCALL 5/* look at error stack/return + * value/errno */ +# define SSL_ERROR_ZERO_RETURN 6 +# define SSL_ERROR_WANT_CONNECT 7 +# define SSL_ERROR_WANT_ACCEPT 8 +# define SSL_CTRL_NEED_TMP_RSA 1 +# define SSL_CTRL_SET_TMP_RSA 2 +# define SSL_CTRL_SET_TMP_DH 3 +# define SSL_CTRL_SET_TMP_ECDH 4 +# define SSL_CTRL_SET_TMP_RSA_CB 5 +# define SSL_CTRL_SET_TMP_DH_CB 6 +# define SSL_CTRL_SET_TMP_ECDH_CB 7 +# define SSL_CTRL_GET_SESSION_REUSED 8 +# define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9 +# define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10 +# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11 +# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12 +# define SSL_CTRL_GET_FLAGS 13 +# define SSL_CTRL_EXTRA_CHAIN_CERT 14 +# define SSL_CTRL_SET_MSG_CALLBACK 15 +# define SSL_CTRL_SET_MSG_CALLBACK_ARG 16 +/* only applies to datagram connections */ +# define SSL_CTRL_SET_MTU 17 +/* Stats */ +# define SSL_CTRL_SESS_NUMBER 20 +# define SSL_CTRL_SESS_CONNECT 21 +# define SSL_CTRL_SESS_CONNECT_GOOD 22 +# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23 +# define SSL_CTRL_SESS_ACCEPT 24 +# define SSL_CTRL_SESS_ACCEPT_GOOD 25 +# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26 +# define SSL_CTRL_SESS_HIT 27 +# define SSL_CTRL_SESS_CB_HIT 28 +# define SSL_CTRL_SESS_MISSES 29 +# define SSL_CTRL_SESS_TIMEOUTS 30 +# define SSL_CTRL_SESS_CACHE_FULL 31 +# define SSL_CTRL_OPTIONS 32 +# define SSL_CTRL_MODE 33 +# define SSL_CTRL_GET_READ_AHEAD 40 +# define SSL_CTRL_SET_READ_AHEAD 41 +# define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +# define SSL_CTRL_GET_SESS_CACHE_SIZE 43 +# define SSL_CTRL_SET_SESS_CACHE_MODE 44 +# define SSL_CTRL_GET_SESS_CACHE_MODE 45 +# define SSL_CTRL_GET_MAX_CERT_LIST 50 +# define SSL_CTRL_SET_MAX_CERT_LIST 51 +# define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52 +/* see tls1.h for macros based on these */ +# ifndef OPENSSL_NO_TLSEXT +# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 +# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 +# define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 +# define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56 +# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 +# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58 +# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59 +# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT 60 +# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 +# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 +# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 +# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 +# define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 +# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB 75 +# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB 76 +# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB 77 +# define SSL_CTRL_SET_SRP_ARG 78 +# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME 79 +# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH 80 +# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD 81 +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_CTRL_TLS_EXT_SEND_HEARTBEAT 85 +# define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING 86 +# define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS 87 +# endif +# endif /* OPENSSL_NO_TLSEXT */ +# define DTLS_CTRL_GET_TIMEOUT 73 +# define DTLS_CTRL_HANDLE_TIMEOUT 74 +# define DTLS_CTRL_LISTEN 75 +# define SSL_CTRL_GET_RI_SUPPORT 76 +# define SSL_CTRL_CLEAR_OPTIONS 77 +# define SSL_CTRL_CLEAR_MODE 78 +# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 +# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83 +# define SSL_CTRL_CHAIN 88 +# define SSL_CTRL_CHAIN_CERT 89 +# define SSL_CTRL_GET_CURVES 90 +# define SSL_CTRL_SET_CURVES 91 +# define SSL_CTRL_SET_CURVES_LIST 92 +# define SSL_CTRL_GET_SHARED_CURVE 93 +# define SSL_CTRL_SET_ECDH_AUTO 94 +# define SSL_CTRL_SET_SIGALGS 97 +# define SSL_CTRL_SET_SIGALGS_LIST 98 +# define SSL_CTRL_CERT_FLAGS 99 +# define SSL_CTRL_CLEAR_CERT_FLAGS 100 +# define SSL_CTRL_SET_CLIENT_SIGALGS 101 +# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102 +# define SSL_CTRL_GET_CLIENT_CERT_TYPES 103 +# define SSL_CTRL_SET_CLIENT_CERT_TYPES 104 +# define SSL_CTRL_BUILD_CERT_CHAIN 105 +# define SSL_CTRL_SET_VERIFY_CERT_STORE 106 +# define SSL_CTRL_SET_CHAIN_CERT_STORE 107 +# define SSL_CTRL_GET_PEER_SIGNATURE_NID 108 +# define SSL_CTRL_GET_SERVER_TMP_KEY 109 +# define SSL_CTRL_GET_RAW_CIPHERLIST 110 +# define SSL_CTRL_GET_EC_POINT_FORMATS 111 +# define SSL_CTRL_GET_CHAIN_CERTS 115 +# define SSL_CTRL_SELECT_CURRENT_CERT 116 +# define SSL_CTRL_SET_CURRENT_CERT 117 +# define SSL_CTRL_CHECK_PROTO_VERSION 119 +# define DTLS_CTRL_SET_LINK_MTU 120 +# define DTLS_CTRL_GET_LINK_MIN_MTU 121 +# define SSL_CERT_SET_FIRST 1 +# define SSL_CERT_SET_NEXT 2 +# define SSL_CERT_SET_SERVER 3 +# define DTLSv1_get_timeout(ssl, arg) \ + SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) +# define DTLSv1_handle_timeout(ssl) \ + SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL) +# define DTLSv1_listen(ssl, peer) \ + SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer) +# define SSL_session_reused(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL) +# define SSL_num_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL) +# define SSL_clear_num_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL) +# define SSL_total_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL) +# define SSL_CTX_need_tmp_RSA(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL) +# define SSL_CTX_set_tmp_rsa(ctx,rsa) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa) +# define SSL_CTX_set_tmp_dh(ctx,dh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh) +# define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh) +# define SSL_need_tmp_RSA(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL) +# define SSL_set_tmp_rsa(ssl,rsa) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa) +# define SSL_set_tmp_dh(ssl,dh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh) +# define SSL_set_tmp_ecdh(ssl,ecdh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh) +# define SSL_CTX_add_extra_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509) +# define SSL_CTX_get_extra_chain_certs(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509) +# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509) +# define SSL_CTX_clear_extra_chain_certs(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL) +# define SSL_CTX_set0_chain(ctx,sk) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)sk) +# define SSL_CTX_set1_chain(ctx,sk) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)sk) +# define SSL_CTX_add0_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509) +# define SSL_CTX_add1_chain_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509) +# define SSL_CTX_get0_chain_certs(ctx,px509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509) +# define SSL_CTX_clear_chain_certs(ctx) \ + SSL_CTX_set0_chain(ctx,NULL) +# define SSL_CTX_build_cert_chain(ctx, flags) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) +# define SSL_CTX_select_current_cert(ctx,x509) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509) +# define SSL_CTX_set_current_cert(ctx, op) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) +# define SSL_CTX_set0_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st) +# define SSL_CTX_set1_verify_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)st) +# define SSL_CTX_set0_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)st) +# define SSL_CTX_set1_chain_cert_store(ctx,st) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)st) +# define SSL_set0_chain(ctx,sk) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)sk) +# define SSL_set1_chain(ctx,sk) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)sk) +# define SSL_add0_chain_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509) +# define SSL_add1_chain_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509) +# define SSL_get0_chain_certs(ctx,px509) \ + SSL_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509) +# define SSL_clear_chain_certs(ctx) \ + SSL_set0_chain(ctx,NULL) +# define SSL_build_cert_chain(s, flags) \ + SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL) +# define SSL_select_current_cert(ctx,x509) \ + SSL_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)x509) +# define SSL_set_current_cert(ctx,op) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL) +# define SSL_set0_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)st) +# define SSL_set1_verify_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)st) +# define SSL_set0_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)st) +# define SSL_set1_chain_cert_store(s,st) \ + SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)st) +# define SSL_get1_curves(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_GET_CURVES,0,(char *)s) +# define SSL_CTX_set1_curves(ctx, clist, clistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURVES,clistlen,(char *)clist) +# define SSL_CTX_set1_curves_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURVES_LIST,0,(char *)s) +# define SSL_set1_curves(ctx, clist, clistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURVES,clistlen,(char *)clist) +# define SSL_set1_curves_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CURVES_LIST,0,(char *)s) +# define SSL_get_shared_curve(s, n) \ + SSL_ctrl(s,SSL_CTRL_GET_SHARED_CURVE,n,NULL) +# define SSL_CTX_set_ecdh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL) +# define SSL_set_ecdh_auto(s, onoff) \ + SSL_ctrl(s,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL) +# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)slist) +# define SSL_CTX_set1_sigalgs_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)s) +# define SSL_set1_sigalgs(ctx, slist, slistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)slist) +# define SSL_set1_sigalgs_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)s) +# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)slist) +# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)s) +# define SSL_set1_client_sigalgs(ctx, slist, slistlen) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,clistlen,(int *)slist) +# define SSL_set1_client_sigalgs_list(ctx, s) \ + SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)s) +# define SSL_get0_certificate_types(s, clist) \ + SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)clist) +# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)clist) +# define SSL_set1_client_certificate_types(s, clist, clistlen) \ + SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)clist) +# define SSL_get_peer_signature_nid(s, pn) \ + SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn) +# define SSL_get_server_tmp_key(s, pk) \ + SSL_ctrl(s,SSL_CTRL_GET_SERVER_TMP_KEY,0,pk) +# define SSL_get0_raw_cipherlist(s, plst) \ + SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,(char *)plst) +# define SSL_get0_ec_point_formats(s, plst) \ + SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,(char *)plst) +# ifndef OPENSSL_NO_BIO +BIO_METHOD *BIO_f_ssl(void); +BIO *BIO_new_ssl(SSL_CTX *ctx, int client); +BIO *BIO_new_ssl_connect(SSL_CTX *ctx); +BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx); +int BIO_ssl_copy_session_id(BIO *to, BIO *from); +void BIO_ssl_shutdown(BIO *ssl_bio); + +# endif + +int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str); +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth); +void SSL_CTX_free(SSL_CTX *); +long SSL_CTX_set_timeout(SSL_CTX *ctx, long t); +long SSL_CTX_get_timeout(const SSL_CTX *ctx); +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *); +void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *); +int SSL_want(const SSL *s); +int SSL_clear(SSL *s); + +void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm); + +const SSL_CIPHER *SSL_get_current_cipher(const SSL *s); +int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits); +char *SSL_CIPHER_get_version(const SSL_CIPHER *c); +const char *SSL_CIPHER_get_name(const SSL_CIPHER *c); +unsigned long SSL_CIPHER_get_id(const SSL_CIPHER *c); + +int SSL_get_fd(const SSL *s); +int SSL_get_rfd(const SSL *s); +int SSL_get_wfd(const SSL *s); +const char *SSL_get_cipher_list(const SSL *s, int n); +char *SSL_get_shared_ciphers(const SSL *s, char *buf, int len); +int SSL_get_read_ahead(const SSL *s); +int SSL_pending(const SSL *s); +# ifndef OPENSSL_NO_SOCK +int SSL_set_fd(SSL *s, int fd); +int SSL_set_rfd(SSL *s, int fd); +int SSL_set_wfd(SSL *s, int fd); +# endif +# ifndef OPENSSL_NO_BIO +void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio); +BIO *SSL_get_rbio(const SSL *s); +BIO *SSL_get_wbio(const SSL *s); +# endif +int SSL_set_cipher_list(SSL *s, const char *str); +void SSL_set_read_ahead(SSL *s, int yes); +int SSL_get_verify_mode(const SSL *s); +int SSL_get_verify_depth(const SSL *s); +int (*SSL_get_verify_callback(const SSL *s)) (int, X509_STORE_CTX *); +void SSL_set_verify(SSL *s, int mode, + int (*callback) (int ok, X509_STORE_CTX *ctx)); +void SSL_set_verify_depth(SSL *s, int depth); +void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg); +# ifndef OPENSSL_NO_RSA +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); +# endif +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len); +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); +int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, + long len); +int SSL_use_certificate(SSL *ssl, X509 *x); +int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len); + +# ifndef OPENSSL_NO_TLSEXT +/* Set serverinfo data for the current active cert. */ +int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, + size_t serverinfo_length); +# ifndef OPENSSL_NO_STDIO +int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file); +# endif /* NO_STDIO */ + +# endif + +# ifndef OPENSSL_NO_STDIO +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_use_certificate_file(SSL *ssl, const char *file, int type); +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); +/* PEM type */ +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *file); +# ifndef OPENSSL_SYS_VMS +/* XXXXX: Better scheme needed! [was: #ifndef MAC_OS_pre_X] */ +# ifndef OPENSSL_SYS_MACINTOSH_CLASSIC +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *dir); +# endif +# endif + +# endif + +void SSL_load_error_strings(void); +const char *SSL_state_string(const SSL *s); +const char *SSL_rstate_string(const SSL *s); +const char *SSL_state_string_long(const SSL *s); +const char *SSL_rstate_string_long(const SSL *s); +long SSL_SESSION_get_time(const SSL_SESSION *s); +long SSL_SESSION_set_time(SSL_SESSION *s, long t); +long SSL_SESSION_get_timeout(const SSL_SESSION *s); +long SSL_SESSION_set_timeout(SSL_SESSION *s, long t); +void SSL_copy_session_id(SSL *to, const SSL *from); +X509 *SSL_SESSION_get0_peer(SSL_SESSION *s); +int SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +SSL_SESSION *SSL_SESSION_new(void); +const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, + unsigned int *len); +unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s); +# ifndef OPENSSL_NO_FP_API +int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses); +# endif +# ifndef OPENSSL_NO_BIO +int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses); +# endif +void SSL_SESSION_free(SSL_SESSION *ses); +int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); +int SSL_set_session(SSL *to, SSL_SESSION *session); +int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c); +int SSL_CTX_remove_session(SSL_CTX *, SSL_SESSION *c); +int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB); +int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB); +int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, + unsigned int id_len); +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, + long length); + +# ifdef HEADER_X509_H +X509 *SSL_get_peer_certificate(const SSL *s); +# endif + +STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s); + +int SSL_CTX_get_verify_mode(const SSL_CTX *ctx); +int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); +int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx)) (int, + X509_STORE_CTX *); +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*callback) (int, X509_STORE_CTX *)); +void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, + int (*cb) (X509_STORE_CTX *, void *), + void *arg); +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), + void *arg); +# ifndef OPENSSL_NO_RSA +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +# endif +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, + long len); +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); +int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, + const unsigned char *d, long len); +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, + const unsigned char *d); + +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u); + +int SSL_CTX_check_private_key(const SSL_CTX *ctx); +int SSL_check_private_key(const SSL *ctx); + +int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +SSL *SSL_new(SSL_CTX *ctx); +int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx, + unsigned int sid_ctx_len); + +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose); +int SSL_set_purpose(SSL *s, int purpose); +int SSL_CTX_set_trust(SSL_CTX *s, int trust); +int SSL_set_trust(SSL *s, int trust); + +int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm); +int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm); + +X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx); +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); + +# ifndef OPENSSL_NO_SRP +int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name); +int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password); +int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength); +int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx, + char *(*cb) (SSL *, void *)); +int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx, + int (*cb) (SSL *, void *)); +int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx, + int (*cb) (SSL *, int *, void *)); +int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg); + +int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g, + BIGNUM *sa, BIGNUM *v, char *info); +int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass, + const char *grp); + +BIGNUM *SSL_get_srp_g(SSL *s); +BIGNUM *SSL_get_srp_N(SSL *s); + +char *SSL_get_srp_username(SSL *s); +char *SSL_get_srp_userinfo(SSL *s); +# endif + +void SSL_certs_clear(SSL *s); +void SSL_free(SSL *ssl); +int SSL_accept(SSL *ssl); +int SSL_connect(SSL *ssl); +int SSL_read(SSL *ssl, void *buf, int num); +int SSL_peek(SSL *ssl, void *buf, int num); +int SSL_write(SSL *ssl, const void *buf, int num); +long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); +long SSL_callback_ctrl(SSL *, int, void (*)(void)); +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); +long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void)); + +int SSL_get_error(const SSL *s, int ret_code); +const char *SSL_get_version(const SSL *s); + +/* This sets the 'default' SSL version that SSL_new() will create */ +int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth); + +# ifndef OPENSSL_NO_SSL2_METHOD +const SSL_METHOD *SSLv2_method(void); /* SSLv2 */ +const SSL_METHOD *SSLv2_server_method(void); /* SSLv2 */ +const SSL_METHOD *SSLv2_client_method(void); /* SSLv2 */ +# endif + +# ifndef OPENSSL_NO_SSL3_METHOD +const SSL_METHOD *SSLv3_method(void); /* SSLv3 */ +const SSL_METHOD *SSLv3_server_method(void); /* SSLv3 */ +const SSL_METHOD *SSLv3_client_method(void); /* SSLv3 */ +# endif + +const SSL_METHOD *SSLv23_method(void); /* Negotiate highest available SSL/TLS + * version */ +const SSL_METHOD *SSLv23_server_method(void); /* Negotiate highest available + * SSL/TLS version */ +const SSL_METHOD *SSLv23_client_method(void); /* Negotiate highest available + * SSL/TLS version */ + +const SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */ +const SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */ +const SSL_METHOD *TLSv1_client_method(void); /* TLSv1.0 */ + +const SSL_METHOD *TLSv1_1_method(void); /* TLSv1.1 */ +const SSL_METHOD *TLSv1_1_server_method(void); /* TLSv1.1 */ +const SSL_METHOD *TLSv1_1_client_method(void); /* TLSv1.1 */ + +const SSL_METHOD *TLSv1_2_method(void); /* TLSv1.2 */ +const SSL_METHOD *TLSv1_2_server_method(void); /* TLSv1.2 */ +const SSL_METHOD *TLSv1_2_client_method(void); /* TLSv1.2 */ + +const SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */ +const SSL_METHOD *DTLSv1_server_method(void); /* DTLSv1.0 */ +const SSL_METHOD *DTLSv1_client_method(void); /* DTLSv1.0 */ + +const SSL_METHOD *DTLSv1_2_method(void); /* DTLSv1.2 */ +const SSL_METHOD *DTLSv1_2_server_method(void); /* DTLSv1.2 */ +const SSL_METHOD *DTLSv1_2_client_method(void); /* DTLSv1.2 */ + +const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */ +const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */ +const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */ + +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s); + +int SSL_do_handshake(SSL *s); +int SSL_renegotiate(SSL *s); +int SSL_renegotiate_abbreviated(SSL *s); +int SSL_renegotiate_pending(SSL *s); +int SSL_shutdown(SSL *s); + +const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx); +const SSL_METHOD *SSL_get_ssl_method(SSL *s); +int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); +const char *SSL_alert_type_string_long(int value); +const char *SSL_alert_type_string(int value); +const char *SSL_alert_desc_string_long(int value); +const char *SSL_alert_desc_string(int value); + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); +STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s); +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s); +int SSL_add_client_CA(SSL *ssl, X509 *x); +int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x); + +void SSL_set_connect_state(SSL *s); +void SSL_set_accept_state(SSL *s); + +long SSL_get_default_timeout(const SSL *s); + +int SSL_library_init(void); + +char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size); +STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk); + +SSL *SSL_dup(SSL *ssl); + +X509 *SSL_get_certificate(const SSL *ssl); +/* + * EVP_PKEY + */ struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl); + +X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx); +EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx); + +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode); +int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx); +void SSL_set_quiet_shutdown(SSL *ssl, int mode); +int SSL_get_quiet_shutdown(const SSL *ssl); +void SSL_set_shutdown(SSL *ssl, int mode); +int SSL_get_shutdown(const SSL *ssl); +int SSL_version(const SSL *ssl); +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); +# define SSL_get0_session SSL_get_session/* just peek at pointer */ +SSL_SESSION *SSL_get_session(const SSL *ssl); +SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ +SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl); +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx); +void SSL_set_info_callback(SSL *ssl, + void (*cb) (const SSL *ssl, int type, int val)); +void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type, + int val); +int SSL_state(const SSL *ssl); +void SSL_set_state(SSL *ssl, int state); + +void SSL_set_verify_result(SSL *ssl, long v); +long SSL_get_verify_result(const SSL *ssl); + +int SSL_set_ex_data(SSL *ssl, int idx, void *data); +void *SSL_get_ex_data(const SSL *ssl, int idx); +int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + +int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data); +void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx); +int SSL_SESSION_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); + +int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data); +void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx); +int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); + +int SSL_get_ex_data_X509_STORE_CTX_idx(void); + +# define SSL_CTX_sess_set_cache_size(ctx,t) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL) +# define SSL_CTX_sess_get_cache_size(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL) +# define SSL_CTX_set_session_cache_mode(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL) +# define SSL_CTX_get_session_cache_mode(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL) + +# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx) +# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m) +# define SSL_CTX_get_read_ahead(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL) +# define SSL_CTX_set_read_ahead(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL) +# define SSL_CTX_get_max_cert_list(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +# define SSL_CTX_set_max_cert_list(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) +# define SSL_get_max_cert_list(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +# define SSL_set_max_cert_list(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) + +# define SSL_CTX_set_max_send_fragment(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) +# define SSL_set_max_send_fragment(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) + + /* NB: the keylength is only applicable when is_export is true */ +# ifndef OPENSSL_NO_RSA +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, + RSA *(*cb) (SSL *ssl, int is_export, + int keylength)); + +void SSL_set_tmp_rsa_callback(SSL *ssl, + RSA *(*cb) (SSL *ssl, int is_export, + int keylength)); +# endif +# ifndef OPENSSL_NO_DH +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*dh) (SSL *ssl, int is_export, + int keylength)); +void SSL_set_tmp_dh_callback(SSL *ssl, + DH *(*dh) (SSL *ssl, int is_export, + int keylength)); +# endif +# ifndef OPENSSL_NO_ECDH +void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx, + EC_KEY *(*ecdh) (SSL *ssl, int is_export, + int keylength)); +void SSL_set_tmp_ecdh_callback(SSL *ssl, + EC_KEY *(*ecdh) (SSL *ssl, int is_export, + int keylength)); +# endif + +const COMP_METHOD *SSL_get_current_compression(SSL *s); +const COMP_METHOD *SSL_get_current_expansion(SSL *s); +const char *SSL_COMP_get_name(const COMP_METHOD *comp); +STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP) + *meths); +void SSL_COMP_free_compression_methods(void); +int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm); + +const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr); + +/* TLS extensions functions */ +int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); + +int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, + void *arg); + +/* Pre-shared secret session resumption functions */ +int SSL_set_session_secret_cb(SSL *s, + tls_session_secret_cb_fn tls_session_secret_cb, + void *arg); + +void SSL_set_debug(SSL *s, int debug); +int SSL_cache_hit(SSL *s); +int SSL_is_server(SSL *s); + +SSL_CONF_CTX *SSL_CONF_CTX_new(void); +int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx); +void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx); +unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags); +unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx, unsigned int flags); +int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre); + +void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl); +void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx); + +int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value); +int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv); +int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd); + +# ifndef OPENSSL_NO_SSL_TRACE +void SSL_trace(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); +const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c); +# endif + +# ifndef OPENSSL_NO_UNIT_TEST +const struct openssl_ssl_test_functions *SSL_test_functions(void); +# endif + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_SSL_strings(void); + +/* Error codes for the SSL functions. */ + +/* Function codes. */ +# define SSL_F_CHECK_SUITEB_CIPHER_LIST 331 +# define SSL_F_CLIENT_CERTIFICATE 100 +# define SSL_F_CLIENT_FINISHED 167 +# define SSL_F_CLIENT_HELLO 101 +# define SSL_F_CLIENT_MASTER_KEY 102 +# define SSL_F_D2I_SSL_SESSION 103 +# define SSL_F_DO_DTLS1_WRITE 245 +# define SSL_F_DO_SSL3_WRITE 104 +# define SSL_F_DTLS1_ACCEPT 246 +# define SSL_F_DTLS1_ADD_CERT_TO_BUF 295 +# define SSL_F_DTLS1_BUFFER_RECORD 247 +# define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 316 +# define SSL_F_DTLS1_CLIENT_HELLO 248 +# define SSL_F_DTLS1_CONNECT 249 +# define SSL_F_DTLS1_ENC 250 +# define SSL_F_DTLS1_GET_HELLO_VERIFY 251 +# define SSL_F_DTLS1_GET_MESSAGE 252 +# define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT 253 +# define SSL_F_DTLS1_GET_RECORD 254 +# define SSL_F_DTLS1_HANDLE_TIMEOUT 297 +# define SSL_F_DTLS1_HEARTBEAT 305 +# define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255 +# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288 +# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424 +# define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256 +# define SSL_F_DTLS1_PROCESS_RECORD 257 +# define SSL_F_DTLS1_READ_BYTES 258 +# define SSL_F_DTLS1_READ_FAILED 259 +# define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST 260 +# define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE 261 +# define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE 262 +# define SSL_F_DTLS1_SEND_CLIENT_VERIFY 263 +# define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST 264 +# define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE 265 +# define SSL_F_DTLS1_SEND_SERVER_HELLO 266 +# define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE 267 +# define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268 +# define SSL_F_GET_CLIENT_FINISHED 105 +# define SSL_F_GET_CLIENT_HELLO 106 +# define SSL_F_GET_CLIENT_MASTER_KEY 107 +# define SSL_F_GET_SERVER_FINISHED 108 +# define SSL_F_GET_SERVER_HELLO 109 +# define SSL_F_GET_SERVER_STATIC_DH_KEY 340 +# define SSL_F_GET_SERVER_VERIFY 110 +# define SSL_F_I2D_SSL_SESSION 111 +# define SSL_F_READ_N 112 +# define SSL_F_REQUEST_CERTIFICATE 113 +# define SSL_F_SERVER_FINISH 239 +# define SSL_F_SERVER_HELLO 114 +# define SSL_F_SERVER_VERIFY 240 +# define SSL_F_SSL23_ACCEPT 115 +# define SSL_F_SSL23_CLIENT_HELLO 116 +# define SSL_F_SSL23_CONNECT 117 +# define SSL_F_SSL23_GET_CLIENT_HELLO 118 +# define SSL_F_SSL23_GET_SERVER_HELLO 119 +# define SSL_F_SSL23_PEEK 237 +# define SSL_F_SSL23_READ 120 +# define SSL_F_SSL23_WRITE 121 +# define SSL_F_SSL2_ACCEPT 122 +# define SSL_F_SSL2_CONNECT 123 +# define SSL_F_SSL2_ENC_INIT 124 +# define SSL_F_SSL2_GENERATE_KEY_MATERIAL 241 +# define SSL_F_SSL2_PEEK 234 +# define SSL_F_SSL2_READ 125 +# define SSL_F_SSL2_READ_INTERNAL 236 +# define SSL_F_SSL2_SET_CERTIFICATE 126 +# define SSL_F_SSL2_WRITE 127 +# define SSL_F_SSL3_ACCEPT 128 +# define SSL_F_SSL3_ADD_CERT_TO_BUF 296 +# define SSL_F_SSL3_CALLBACK_CTRL 233 +# define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 +# define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 +# define SSL_F_SSL3_CHECK_CLIENT_HELLO 304 +# define SSL_F_SSL3_CHECK_FINISHED 339 +# define SSL_F_SSL3_CLIENT_HELLO 131 +# define SSL_F_SSL3_CONNECT 132 +# define SSL_F_SSL3_CTRL 213 +# define SSL_F_SSL3_CTX_CTRL 133 +# define SSL_F_SSL3_DIGEST_CACHED_RECORDS 293 +# define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 292 +# define SSL_F_SSL3_ENC 134 +# define SSL_F_SSL3_GENERATE_KEY_BLOCK 238 +# define SSL_F_SSL3_GENERATE_MASTER_SECRET 388 +# define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135 +# define SSL_F_SSL3_GET_CERT_STATUS 289 +# define SSL_F_SSL3_GET_CERT_VERIFY 136 +# define SSL_F_SSL3_GET_CLIENT_CERTIFICATE 137 +# define SSL_F_SSL3_GET_CLIENT_HELLO 138 +# define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE 139 +# define SSL_F_SSL3_GET_FINISHED 140 +# define SSL_F_SSL3_GET_KEY_EXCHANGE 141 +# define SSL_F_SSL3_GET_MESSAGE 142 +# define SSL_F_SSL3_GET_NEW_SESSION_TICKET 283 +# define SSL_F_SSL3_GET_NEXT_PROTO 306 +# define SSL_F_SSL3_GET_RECORD 143 +# define SSL_F_SSL3_GET_SERVER_CERTIFICATE 144 +# define SSL_F_SSL3_GET_SERVER_DONE 145 +# define SSL_F_SSL3_GET_SERVER_HELLO 146 +# define SSL_F_SSL3_HANDSHAKE_MAC 285 +# define SSL_F_SSL3_NEW_SESSION_TICKET 287 +# define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147 +# define SSL_F_SSL3_PEEK 235 +# define SSL_F_SSL3_READ_BYTES 148 +# define SSL_F_SSL3_READ_N 149 +# define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST 150 +# define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE 151 +# define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE 152 +# define SSL_F_SSL3_SEND_CLIENT_VERIFY 153 +# define SSL_F_SSL3_SEND_SERVER_CERTIFICATE 154 +# define SSL_F_SSL3_SEND_SERVER_HELLO 242 +# define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE 155 +# define SSL_F_SSL3_SETUP_KEY_BLOCK 157 +# define SSL_F_SSL3_SETUP_READ_BUFFER 156 +# define SSL_F_SSL3_SETUP_WRITE_BUFFER 291 +# define SSL_F_SSL3_WRITE_BYTES 158 +# define SSL_F_SSL3_WRITE_PENDING 159 +# define SSL_F_SSL_ADD_CERT_CHAIN 318 +# define SSL_F_SSL_ADD_CERT_TO_BUF 319 +# define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 298 +# define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 277 +# define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT 307 +# define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215 +# define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216 +# define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 299 +# define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 278 +# define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT 308 +# define SSL_F_SSL_BAD_METHOD 160 +# define SSL_F_SSL_BUILD_CERT_CHAIN 332 +# define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +# define SSL_F_SSL_CERT_DUP 221 +# define SSL_F_SSL_CERT_INST 222 +# define SSL_F_SSL_CERT_INSTANTIATE 214 +# define SSL_F_SSL_CERT_NEW 162 +# define SSL_F_SSL_CHECK_PRIVATE_KEY 163 +# define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 280 +# define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG 279 +# define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230 +# define SSL_F_SSL_CIPHER_STRENGTH_SORT 231 +# define SSL_F_SSL_CLEAR 164 +# define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165 +# define SSL_F_SSL_CONF_CMD 334 +# define SSL_F_SSL_CREATE_CIPHER_LIST 166 +# define SSL_F_SSL_CTRL 232 +# define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168 +# define SSL_F_SSL_CTX_MAKE_PROFILES 309 +# define SSL_F_SSL_CTX_NEW 169 +# define SSL_F_SSL_CTX_SET_CIPHER_LIST 269 +# define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE 290 +# define SSL_F_SSL_CTX_SET_PURPOSE 226 +# define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219 +# define SSL_F_SSL_CTX_SET_SSL_VERSION 170 +# define SSL_F_SSL_CTX_SET_TRUST 229 +# define SSL_F_SSL_CTX_USE_CERTIFICATE 171 +# define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 +# define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE 220 +# define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY 174 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175 +# define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176 +# define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT 272 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178 +# define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179 +# define SSL_F_SSL_CTX_USE_SERVERINFO 336 +# define SSL_F_SSL_CTX_USE_SERVERINFO_FILE 337 +# define SSL_F_SSL_DO_HANDSHAKE 180 +# define SSL_F_SSL_GET_NEW_SESSION 181 +# define SSL_F_SSL_GET_PREV_SESSION 217 +# define SSL_F_SSL_GET_SERVER_CERT_INDEX 322 +# define SSL_F_SSL_GET_SERVER_SEND_CERT 182 +# define SSL_F_SSL_GET_SERVER_SEND_PKEY 317 +# define SSL_F_SSL_GET_SIGN_PKEY 183 +# define SSL_F_SSL_INIT_WBIO_BUFFER 184 +# define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 +# define SSL_F_SSL_NEW 186 +# define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 300 +# define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 302 +# define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT 310 +# define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 301 +# define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 303 +# define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT 311 +# define SSL_F_SSL_PEEK 270 +# define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT 281 +# define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT 282 +# define SSL_F_SSL_READ 223 +# define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187 +# define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188 +# define SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT 320 +# define SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT 321 +# define SSL_F_SSL_SESSION_DUP 348 +# define SSL_F_SSL_SESSION_NEW 189 +# define SSL_F_SSL_SESSION_PRINT_FP 190 +# define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312 +# define SSL_F_SSL_SESS_CERT_NEW 225 +# define SSL_F_SSL_SET_CERT 191 +# define SSL_F_SSL_SET_CIPHER_LIST 271 +# define SSL_F_SSL_SET_FD 192 +# define SSL_F_SSL_SET_PKEY 193 +# define SSL_F_SSL_SET_PURPOSE 227 +# define SSL_F_SSL_SET_RFD 194 +# define SSL_F_SSL_SET_SESSION 195 +# define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218 +# define SSL_F_SSL_SET_SESSION_TICKET_EXT 294 +# define SSL_F_SSL_SET_TRUST 228 +# define SSL_F_SSL_SET_WFD 196 +# define SSL_F_SSL_SHUTDOWN 224 +# define SSL_F_SSL_SRP_CTX_INIT 313 +# define SSL_F_SSL_UNDEFINED_CONST_FUNCTION 243 +# define SSL_F_SSL_UNDEFINED_FUNCTION 197 +# define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 244 +# define SSL_F_SSL_USE_CERTIFICATE 198 +# define SSL_F_SSL_USE_CERTIFICATE_ASN1 199 +# define SSL_F_SSL_USE_CERTIFICATE_FILE 200 +# define SSL_F_SSL_USE_PRIVATEKEY 201 +# define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202 +# define SSL_F_SSL_USE_PRIVATEKEY_FILE 203 +# define SSL_F_SSL_USE_PSK_IDENTITY_HINT 273 +# define SSL_F_SSL_USE_RSAPRIVATEKEY 204 +# define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205 +# define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206 +# define SSL_F_SSL_VERIFY_CERT_CHAIN 207 +# define SSL_F_SSL_WRITE 208 +# define SSL_F_TLS12_CHECK_PEER_SIGALG 333 +# define SSL_F_TLS1_CERT_VERIFY_MAC 286 +# define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 +# define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274 +# define SSL_F_TLS1_ENC 210 +# define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314 +# define SSL_F_TLS1_GET_CURVELIST 338 +# define SSL_F_TLS1_HEARTBEAT 315 +# define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT 275 +# define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT 276 +# define SSL_F_TLS1_PRF 284 +# define SSL_F_TLS1_SETUP_KEY_BLOCK 211 +# define SSL_F_TLS1_SET_SERVER_SIGALGS 335 +# define SSL_F_WRITE_PENDING 212 + +/* Reason codes. */ +# define SSL_R_APP_DATA_IN_HANDSHAKE 100 +# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272 +# define SSL_R_BAD_ALERT_RECORD 101 +# define SSL_R_BAD_AUTHENTICATION_TYPE 102 +# define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 +# define SSL_R_BAD_CHECKSUM 104 +# define SSL_R_BAD_DATA 390 +# define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 +# define SSL_R_BAD_DECOMPRESSION 107 +# define SSL_R_BAD_DH_G_LENGTH 108 +# define SSL_R_BAD_DH_G_VALUE 375 +# define SSL_R_BAD_DH_PUB_KEY_LENGTH 109 +# define SSL_R_BAD_DH_PUB_KEY_VALUE 393 +# define SSL_R_BAD_DH_P_LENGTH 110 +# define SSL_R_BAD_DH_P_VALUE 395 +# define SSL_R_BAD_DIGEST_LENGTH 111 +# define SSL_R_BAD_DSA_SIGNATURE 112 +# define SSL_R_BAD_ECC_CERT 304 +# define SSL_R_BAD_ECDSA_SIGNATURE 305 +# define SSL_R_BAD_ECPOINT 306 +# define SSL_R_BAD_HANDSHAKE_LENGTH 332 +# define SSL_R_BAD_HELLO_REQUEST 105 +# define SSL_R_BAD_LENGTH 271 +# define SSL_R_BAD_MAC_DECODE 113 +# define SSL_R_BAD_MAC_LENGTH 333 +# define SSL_R_BAD_MESSAGE_TYPE 114 +# define SSL_R_BAD_PACKET_LENGTH 115 +# define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116 +# define SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH 316 +# define SSL_R_BAD_RESPONSE_ARGUMENT 117 +# define SSL_R_BAD_RSA_DECRYPT 118 +# define SSL_R_BAD_RSA_ENCRYPT 119 +# define SSL_R_BAD_RSA_E_LENGTH 120 +# define SSL_R_BAD_RSA_MODULUS_LENGTH 121 +# define SSL_R_BAD_RSA_SIGNATURE 122 +# define SSL_R_BAD_SIGNATURE 123 +# define SSL_R_BAD_SRP_A_LENGTH 347 +# define SSL_R_BAD_SRP_B_LENGTH 348 +# define SSL_R_BAD_SRP_G_LENGTH 349 +# define SSL_R_BAD_SRP_N_LENGTH 350 +# define SSL_R_BAD_SRP_PARAMETERS 371 +# define SSL_R_BAD_SRP_S_LENGTH 351 +# define SSL_R_BAD_SRTP_MKI_VALUE 352 +# define SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST 353 +# define SSL_R_BAD_SSL_FILETYPE 124 +# define SSL_R_BAD_SSL_SESSION_ID_LENGTH 125 +# define SSL_R_BAD_STATE 126 +# define SSL_R_BAD_VALUE 384 +# define SSL_R_BAD_WRITE_RETRY 127 +# define SSL_R_BIO_NOT_SET 128 +# define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 129 +# define SSL_R_BN_LIB 130 +# define SSL_R_CA_DN_LENGTH_MISMATCH 131 +# define SSL_R_CA_DN_TOO_LONG 132 +# define SSL_R_CCS_RECEIVED_EARLY 133 +# define SSL_R_CERTIFICATE_VERIFY_FAILED 134 +# define SSL_R_CERT_CB_ERROR 377 +# define SSL_R_CERT_LENGTH_MISMATCH 135 +# define SSL_R_CHALLENGE_IS_DIFFERENT 136 +# define SSL_R_CIPHER_CODE_WRONG_LENGTH 137 +# define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138 +# define SSL_R_CIPHER_TABLE_SRC_ERROR 139 +# define SSL_R_CLIENTHELLO_TLSEXT 226 +# define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140 +# define SSL_R_COMPRESSION_DISABLED 343 +# define SSL_R_COMPRESSION_FAILURE 141 +# define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 307 +# define SSL_R_COMPRESSION_LIBRARY_ERROR 142 +# define SSL_R_CONNECTION_ID_IS_DIFFERENT 143 +# define SSL_R_CONNECTION_TYPE_NOT_SET 144 +# define SSL_R_COOKIE_MISMATCH 308 +# define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145 +# define SSL_R_DATA_LENGTH_TOO_LONG 146 +# define SSL_R_DECRYPTION_FAILED 147 +# define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281 +# define SSL_R_DH_KEY_TOO_SMALL 372 +# define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 +# define SSL_R_DIGEST_CHECK_FAILED 149 +# define SSL_R_DTLS_MESSAGE_TOO_BIG 334 +# define SSL_R_DUPLICATE_COMPRESSION_ID 309 +# define SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT 317 +# define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318 +# define SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE 322 +# define SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE 323 +# define SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE 374 +# define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER 310 +# define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 354 +# define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150 +# define SSL_R_ERROR_GENERATING_TMP_RSA_KEY 282 +# define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151 +# define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 +# define SSL_R_EXTRA_DATA_IN_MESSAGE 153 +# define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 +# define SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS 355 +# define SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION 356 +# define SSL_R_HTTPS_PROXY_REQUEST 155 +# define SSL_R_HTTP_REQUEST 156 +# define SSL_R_ILLEGAL_PADDING 283 +# define SSL_R_ILLEGAL_SUITEB_DIGEST 380 +# define SSL_R_INAPPROPRIATE_FALLBACK 373 +# define SSL_R_INCONSISTENT_COMPRESSION 340 +# define SSL_R_INVALID_CHALLENGE_LENGTH 158 +# define SSL_R_INVALID_COMMAND 280 +# define SSL_R_INVALID_COMPRESSION_ALGORITHM 341 +# define SSL_R_INVALID_NULL_CMD_NAME 385 +# define SSL_R_INVALID_PURPOSE 278 +# define SSL_R_INVALID_SERVERINFO_DATA 388 +# define SSL_R_INVALID_SRP_USERNAME 357 +# define SSL_R_INVALID_STATUS_RESPONSE 328 +# define SSL_R_INVALID_TICKET_KEYS_LENGTH 325 +# define SSL_R_INVALID_TRUST 279 +# define SSL_R_KEY_ARG_TOO_LONG 284 +# define SSL_R_KRB5 285 +# define SSL_R_KRB5_C_CC_PRINC 286 +# define SSL_R_KRB5_C_GET_CRED 287 +# define SSL_R_KRB5_C_INIT 288 +# define SSL_R_KRB5_C_MK_REQ 289 +# define SSL_R_KRB5_S_BAD_TICKET 290 +# define SSL_R_KRB5_S_INIT 291 +# define SSL_R_KRB5_S_RD_REQ 292 +# define SSL_R_KRB5_S_TKT_EXPIRED 293 +# define SSL_R_KRB5_S_TKT_NYV 294 +# define SSL_R_KRB5_S_TKT_SKEW 295 +# define SSL_R_LENGTH_MISMATCH 159 +# define SSL_R_LENGTH_TOO_SHORT 160 +# define SSL_R_LIBRARY_BUG 274 +# define SSL_R_LIBRARY_HAS_NO_CIPHERS 161 +# define SSL_R_MESSAGE_TOO_LONG 296 +# define SSL_R_MISSING_DH_DSA_CERT 162 +# define SSL_R_MISSING_DH_KEY 163 +# define SSL_R_MISSING_DH_RSA_CERT 164 +# define SSL_R_MISSING_DSA_SIGNING_CERT 165 +# define SSL_R_MISSING_ECDH_CERT 382 +# define SSL_R_MISSING_ECDSA_SIGNING_CERT 381 +# define SSL_R_MISSING_EXPORT_TMP_DH_KEY 166 +# define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 167 +# define SSL_R_MISSING_RSA_CERTIFICATE 168 +# define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169 +# define SSL_R_MISSING_RSA_SIGNING_CERT 170 +# define SSL_R_MISSING_SRP_PARAM 358 +# define SSL_R_MISSING_TMP_DH_KEY 171 +# define SSL_R_MISSING_TMP_ECDH_KEY 311 +# define SSL_R_MISSING_TMP_RSA_KEY 172 +# define SSL_R_MISSING_TMP_RSA_PKEY 173 +# define SSL_R_MISSING_VERIFY_MESSAGE 174 +# define SSL_R_MULTIPLE_SGC_RESTARTS 346 +# define SSL_R_NON_SSLV2_INITIAL_PACKET 175 +# define SSL_R_NO_CERTIFICATES_RETURNED 176 +# define SSL_R_NO_CERTIFICATE_ASSIGNED 177 +# define SSL_R_NO_CERTIFICATE_RETURNED 178 +# define SSL_R_NO_CERTIFICATE_SET 179 +# define SSL_R_NO_CERTIFICATE_SPECIFIED 180 +# define SSL_R_NO_CIPHERS_AVAILABLE 181 +# define SSL_R_NO_CIPHERS_PASSED 182 +# define SSL_R_NO_CIPHERS_SPECIFIED 183 +# define SSL_R_NO_CIPHER_LIST 184 +# define SSL_R_NO_CIPHER_MATCH 185 +# define SSL_R_NO_CLIENT_CERT_METHOD 331 +# define SSL_R_NO_CLIENT_CERT_RECEIVED 186 +# define SSL_R_NO_COMPRESSION_SPECIFIED 187 +# define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 330 +# define SSL_R_NO_METHOD_SPECIFIED 188 +# define SSL_R_NO_PEM_EXTENSIONS 389 +# define SSL_R_NO_PRIVATEKEY 189 +# define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190 +# define SSL_R_NO_PROTOCOLS_AVAILABLE 191 +# define SSL_R_NO_PUBLICKEY 192 +# define SSL_R_NO_RENEGOTIATION 339 +# define SSL_R_NO_REQUIRED_DIGEST 324 +# define SSL_R_NO_SHARED_CIPHER 193 +# define SSL_R_NO_SHARED_SIGATURE_ALGORITHMS 376 +# define SSL_R_NO_SRTP_PROFILES 359 +# define SSL_R_NO_VERIFY_CALLBACK 194 +# define SSL_R_NULL_SSL_CTX 195 +# define SSL_R_NULL_SSL_METHOD_PASSED 196 +# define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 +# define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344 +# define SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE 387 +# define SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE 379 +# define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 297 +# define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG 327 +# define SSL_R_PACKET_LENGTH_TOO_LONG 198 +# define SSL_R_PARSE_TLSEXT 227 +# define SSL_R_PATH_TOO_LONG 270 +# define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 +# define SSL_R_PEER_ERROR 200 +# define SSL_R_PEER_ERROR_CERTIFICATE 201 +# define SSL_R_PEER_ERROR_NO_CERTIFICATE 202 +# define SSL_R_PEER_ERROR_NO_CIPHER 203 +# define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 204 +# define SSL_R_PEM_NAME_BAD_PREFIX 391 +# define SSL_R_PEM_NAME_TOO_SHORT 392 +# define SSL_R_PRE_MAC_LENGTH_TOO_LONG 205 +# define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 206 +# define SSL_R_PROTOCOL_IS_SHUTDOWN 207 +# define SSL_R_PSK_IDENTITY_NOT_FOUND 223 +# define SSL_R_PSK_NO_CLIENT_CB 224 +# define SSL_R_PSK_NO_SERVER_CB 225 +# define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 208 +# define SSL_R_PUBLIC_KEY_IS_NOT_RSA 209 +# define SSL_R_PUBLIC_KEY_NOT_RSA 210 +# define SSL_R_READ_BIO_NOT_SET 211 +# define SSL_R_READ_TIMEOUT_EXPIRED 312 +# define SSL_R_READ_WRONG_PACKET_TYPE 212 +# define SSL_R_RECORD_LENGTH_MISMATCH 213 +# define SSL_R_RECORD_TOO_LARGE 214 +# define SSL_R_RECORD_TOO_SMALL 298 +# define SSL_R_RENEGOTIATE_EXT_TOO_LONG 335 +# define SSL_R_RENEGOTIATION_ENCODING_ERR 336 +# define SSL_R_RENEGOTIATION_MISMATCH 337 +# define SSL_R_REQUIRED_CIPHER_MISSING 215 +# define SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING 342 +# define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216 +# define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217 +# define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218 +# define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 345 +# define SSL_R_SERVERHELLO_TLSEXT 275 +# define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277 +# define SSL_R_SHORT_READ 219 +# define SSL_R_SHUTDOWN_WHILE_IN_INIT 407 +# define SSL_R_SIGNATURE_ALGORITHMS_ERROR 360 +# define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 +# define SSL_R_SRP_A_CALC 361 +# define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 362 +# define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG 363 +# define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 364 +# define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221 +# define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 299 +# define SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT 321 +# define SSL_R_SSL3_EXT_INVALID_SERVERNAME 319 +# define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 320 +# define SSL_R_SSL3_SESSION_ID_TOO_LONG 300 +# define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222 +# define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +# define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +# define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +# define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +# define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +# define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +# define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +# define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +# define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +# define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228 +# define SSL_R_SSL_HANDSHAKE_FAILURE 229 +# define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 230 +# define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 301 +# define SSL_R_SSL_SESSION_ID_CONFLICT 302 +# define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273 +# define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 303 +# define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 231 +# define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 +# define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 +# define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 +# define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 +# define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 +# define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086 +# define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 +# define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +# define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 +# define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 +# define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 +# define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 +# define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +# define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114 +# define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113 +# define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111 +# define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112 +# define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 +# define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232 +# define SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT 365 +# define SSL_R_TLS_HEARTBEAT_PENDING 366 +# define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL 367 +# define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 157 +# define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 +# define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234 +# define SSL_R_TOO_MANY_WARN_ALERTS 409 +# define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235 +# define SSL_R_UNABLE_TO_DECODE_DH_CERTS 236 +# define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS 313 +# define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 237 +# define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 238 +# define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 314 +# define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239 +# define SSL_R_UNABLE_TO_FIND_SSL_METHOD 240 +# define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 241 +# define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242 +# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243 +# define SSL_R_UNEXPECTED_MESSAGE 244 +# define SSL_R_UNEXPECTED_RECORD 245 +# define SSL_R_UNINITIALIZED 276 +# define SSL_R_UNKNOWN_ALERT_TYPE 246 +# define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247 +# define SSL_R_UNKNOWN_CIPHER_RETURNED 248 +# define SSL_R_UNKNOWN_CIPHER_TYPE 249 +# define SSL_R_UNKNOWN_CMD_NAME 386 +# define SSL_R_UNKNOWN_DIGEST 368 +# define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250 +# define SSL_R_UNKNOWN_PKEY_TYPE 251 +# define SSL_R_UNKNOWN_PROTOCOL 252 +# define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 253 +# define SSL_R_UNKNOWN_SSL_VERSION 254 +# define SSL_R_UNKNOWN_STATE 255 +# define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 338 +# define SSL_R_UNSUPPORTED_CIPHER 256 +# define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257 +# define SSL_R_UNSUPPORTED_DIGEST_TYPE 326 +# define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE 315 +# define SSL_R_UNSUPPORTED_PROTOCOL 258 +# define SSL_R_UNSUPPORTED_SSL_VERSION 259 +# define SSL_R_UNSUPPORTED_STATUS_TYPE 329 +# define SSL_R_USE_SRTP_NOT_NEGOTIATED 369 +# define SSL_R_WRITE_BIO_NOT_SET 260 +# define SSL_R_WRONG_CERTIFICATE_TYPE 383 +# define SSL_R_WRONG_CIPHER_RETURNED 261 +# define SSL_R_WRONG_CURVE 378 +# define SSL_R_WRONG_MESSAGE_TYPE 262 +# define SSL_R_WRONG_NUMBER_OF_KEY_BITS 263 +# define SSL_R_WRONG_SIGNATURE_LENGTH 264 +# define SSL_R_WRONG_SIGNATURE_SIZE 265 +# define SSL_R_WRONG_SIGNATURE_TYPE 370 +# define SSL_R_WRONG_SSL_VERSION 266 +# define SSL_R_WRONG_VERSION_NUMBER 267 +# define SSL_R_X509_LIB 268 +# define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ssl2.h b/optee/optee_test/host/openssl/include/openssl/ssl2.h new file mode 100644 index 0000000..03c7dd8 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ssl2.h @@ -0,0 +1,265 @@ +/* ssl/ssl2.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL2_H +# define HEADER_SSL2_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Protocol Version Codes */ +# define SSL2_VERSION 0x0002 +# define SSL2_VERSION_MAJOR 0x00 +# define SSL2_VERSION_MINOR 0x02 +/* #define SSL2_CLIENT_VERSION 0x0002 */ +/* #define SSL2_SERVER_VERSION 0x0002 */ + +/* Protocol Message Codes */ +# define SSL2_MT_ERROR 0 +# define SSL2_MT_CLIENT_HELLO 1 +# define SSL2_MT_CLIENT_MASTER_KEY 2 +# define SSL2_MT_CLIENT_FINISHED 3 +# define SSL2_MT_SERVER_HELLO 4 +# define SSL2_MT_SERVER_VERIFY 5 +# define SSL2_MT_SERVER_FINISHED 6 +# define SSL2_MT_REQUEST_CERTIFICATE 7 +# define SSL2_MT_CLIENT_CERTIFICATE 8 + +/* Error Message Codes */ +# define SSL2_PE_UNDEFINED_ERROR 0x0000 +# define SSL2_PE_NO_CIPHER 0x0001 +# define SSL2_PE_NO_CERTIFICATE 0x0002 +# define SSL2_PE_BAD_CERTIFICATE 0x0004 +# define SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006 + +/* Cipher Kind Values */ +# define SSL2_CK_NULL_WITH_MD5 0x02000000/* v3 */ +# define SSL2_CK_RC4_128_WITH_MD5 0x02010080 +# define SSL2_CK_RC4_128_EXPORT40_WITH_MD5 0x02020080 +# define SSL2_CK_RC2_128_CBC_WITH_MD5 0x02030080 +# define SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5 0x02040080 +# define SSL2_CK_IDEA_128_CBC_WITH_MD5 0x02050080 +# define SSL2_CK_DES_64_CBC_WITH_MD5 0x02060040 +# define SSL2_CK_DES_64_CBC_WITH_SHA 0x02060140/* v3 */ +# define SSL2_CK_DES_192_EDE3_CBC_WITH_MD5 0x020700c0 +# define SSL2_CK_DES_192_EDE3_CBC_WITH_SHA 0x020701c0/* v3 */ +# define SSL2_CK_RC4_64_WITH_MD5 0x02080080/* MS hack */ + +# define SSL2_CK_DES_64_CFB64_WITH_MD5_1 0x02ff0800/* SSLeay */ +# define SSL2_CK_NULL 0x02ff0810/* SSLeay */ + +# define SSL2_TXT_DES_64_CFB64_WITH_MD5_1 "DES-CFB-M1" +# define SSL2_TXT_NULL_WITH_MD5 "NULL-MD5" +# define SSL2_TXT_RC4_128_WITH_MD5 "RC4-MD5" +# define SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 "EXP-RC4-MD5" +# define SSL2_TXT_RC2_128_CBC_WITH_MD5 "RC2-CBC-MD5" +# define SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 "EXP-RC2-CBC-MD5" +# define SSL2_TXT_IDEA_128_CBC_WITH_MD5 "IDEA-CBC-MD5" +# define SSL2_TXT_DES_64_CBC_WITH_MD5 "DES-CBC-MD5" +# define SSL2_TXT_DES_64_CBC_WITH_SHA "DES-CBC-SHA" +# define SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 "DES-CBC3-MD5" +# define SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA "DES-CBC3-SHA" +# define SSL2_TXT_RC4_64_WITH_MD5 "RC4-64-MD5" + +# define SSL2_TXT_NULL "NULL" + +/* Flags for the SSL_CIPHER.algorithm2 field */ +# define SSL2_CF_5_BYTE_ENC 0x01 +# define SSL2_CF_8_BYTE_ENC 0x02 + +/* Certificate Type Codes */ +# define SSL2_CT_X509_CERTIFICATE 0x01 + +/* Authentication Type Code */ +# define SSL2_AT_MD5_WITH_RSA_ENCRYPTION 0x01 + +# define SSL2_MAX_SSL_SESSION_ID_LENGTH 32 + +/* Upper/Lower Bounds */ +# define SSL2_MAX_MASTER_KEY_LENGTH_IN_BITS 256 +# ifdef OPENSSL_SYS_MPE +# define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 29998u +# else +# define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 32767u + /* 2^15-1 */ +# endif +# define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER 16383/* 2^14-1 */ + +# define SSL2_CHALLENGE_LENGTH 16 +/* + * #define SSL2_CHALLENGE_LENGTH 32 + */ +# define SSL2_MIN_CHALLENGE_LENGTH 16 +# define SSL2_MAX_CHALLENGE_LENGTH 32 +# define SSL2_CONNECTION_ID_LENGTH 16 +# define SSL2_MAX_CONNECTION_ID_LENGTH 16 +# define SSL2_SSL_SESSION_ID_LENGTH 16 +# define SSL2_MAX_CERT_CHALLENGE_LENGTH 32 +# define SSL2_MIN_CERT_CHALLENGE_LENGTH 16 +# define SSL2_MAX_KEY_MATERIAL_LENGTH 24 + +# ifndef HEADER_SSL_LOCL_H +# define CERT char +# endif + +# ifndef OPENSSL_NO_SSL_INTERN + +typedef struct ssl2_state_st { + int three_byte_header; + int clear_text; /* clear text */ + int escape; /* not used in SSLv2 */ + int ssl2_rollback; /* used if SSLv23 rolled back to SSLv2 */ + /* + * non-blocking io info, used to make sure the same args were passwd + */ + unsigned int wnum; /* number of bytes sent so far */ + int wpend_tot; + const unsigned char *wpend_buf; + int wpend_off; /* offset to data to write */ + int wpend_len; /* number of bytes passwd to write */ + int wpend_ret; /* number of bytes to return to caller */ + /* buffer raw data */ + int rbuf_left; + int rbuf_offs; + unsigned char *rbuf; + unsigned char *wbuf; + unsigned char *write_ptr; /* used to point to the start due to 2/3 byte + * header. */ + unsigned int padding; + unsigned int rlength; /* passed to ssl2_enc */ + int ract_data_length; /* Set when things are encrypted. */ + unsigned int wlength; /* passed to ssl2_enc */ + int wact_data_length; /* Set when things are decrypted. */ + unsigned char *ract_data; + unsigned char *wact_data; + unsigned char *mac_data; + unsigned char *read_key; + unsigned char *write_key; + /* Stuff specifically to do with this SSL session */ + unsigned int challenge_length; + unsigned char challenge[SSL2_MAX_CHALLENGE_LENGTH]; + unsigned int conn_id_length; + unsigned char conn_id[SSL2_MAX_CONNECTION_ID_LENGTH]; + unsigned int key_material_length; + unsigned char key_material[SSL2_MAX_KEY_MATERIAL_LENGTH * 2]; + unsigned long read_sequence; + unsigned long write_sequence; + struct { + unsigned int conn_id_length; + unsigned int cert_type; + unsigned int cert_length; + unsigned int csl; + unsigned int clear; + unsigned int enc; + unsigned char ccl[SSL2_MAX_CERT_CHALLENGE_LENGTH]; + unsigned int cipher_spec_length; + unsigned int session_id_length; + unsigned int clen; + unsigned int rlen; + } tmp; +} SSL2_STATE; + +# endif + +/* SSLv2 */ +/* client */ +# define SSL2_ST_SEND_CLIENT_HELLO_A (0x10|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_HELLO_B (0x11|SSL_ST_CONNECT) +# define SSL2_ST_GET_SERVER_HELLO_A (0x20|SSL_ST_CONNECT) +# define SSL2_ST_GET_SERVER_HELLO_B (0x21|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_MASTER_KEY_A (0x30|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_MASTER_KEY_B (0x31|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_FINISHED_A (0x40|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_FINISHED_B (0x41|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_CERTIFICATE_A (0x50|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_CERTIFICATE_B (0x51|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_CERTIFICATE_C (0x52|SSL_ST_CONNECT) +# define SSL2_ST_SEND_CLIENT_CERTIFICATE_D (0x53|SSL_ST_CONNECT) +# define SSL2_ST_GET_SERVER_VERIFY_A (0x60|SSL_ST_CONNECT) +# define SSL2_ST_GET_SERVER_VERIFY_B (0x61|SSL_ST_CONNECT) +# define SSL2_ST_GET_SERVER_FINISHED_A (0x70|SSL_ST_CONNECT) +# define SSL2_ST_GET_SERVER_FINISHED_B (0x71|SSL_ST_CONNECT) +# define SSL2_ST_CLIENT_START_ENCRYPTION (0x80|SSL_ST_CONNECT) +# define SSL2_ST_X509_GET_CLIENT_CERTIFICATE (0x90|SSL_ST_CONNECT) +/* server */ +# define SSL2_ST_GET_CLIENT_HELLO_A (0x10|SSL_ST_ACCEPT) +# define SSL2_ST_GET_CLIENT_HELLO_B (0x11|SSL_ST_ACCEPT) +# define SSL2_ST_GET_CLIENT_HELLO_C (0x12|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_SERVER_HELLO_A (0x20|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_SERVER_HELLO_B (0x21|SSL_ST_ACCEPT) +# define SSL2_ST_GET_CLIENT_MASTER_KEY_A (0x30|SSL_ST_ACCEPT) +# define SSL2_ST_GET_CLIENT_MASTER_KEY_B (0x31|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_SERVER_VERIFY_A (0x40|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_SERVER_VERIFY_B (0x41|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_SERVER_VERIFY_C (0x42|SSL_ST_ACCEPT) +# define SSL2_ST_GET_CLIENT_FINISHED_A (0x50|SSL_ST_ACCEPT) +# define SSL2_ST_GET_CLIENT_FINISHED_B (0x51|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_SERVER_FINISHED_A (0x60|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_SERVER_FINISHED_B (0x61|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_REQUEST_CERTIFICATE_A (0x70|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_REQUEST_CERTIFICATE_B (0x71|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_REQUEST_CERTIFICATE_C (0x72|SSL_ST_ACCEPT) +# define SSL2_ST_SEND_REQUEST_CERTIFICATE_D (0x73|SSL_ST_ACCEPT) +# define SSL2_ST_SERVER_START_ENCRYPTION (0x80|SSL_ST_ACCEPT) +# define SSL2_ST_X509_GET_SERVER_CERTIFICATE (0x90|SSL_ST_ACCEPT) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ssl23.h b/optee/optee_test/host/openssl/include/openssl/ssl23.h new file mode 100644 index 0000000..9de4685 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ssl23.h @@ -0,0 +1,84 @@ +/* ssl/ssl23.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL23_H +# define HEADER_SSL23_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * client + */ +/* write to server */ +# define SSL23_ST_CW_CLNT_HELLO_A (0x210|SSL_ST_CONNECT) +# define SSL23_ST_CW_CLNT_HELLO_B (0x211|SSL_ST_CONNECT) +/* read from server */ +# define SSL23_ST_CR_SRVR_HELLO_A (0x220|SSL_ST_CONNECT) +# define SSL23_ST_CR_SRVR_HELLO_B (0x221|SSL_ST_CONNECT) + +/* server */ +/* read from client */ +# define SSL23_ST_SR_CLNT_HELLO_A (0x210|SSL_ST_ACCEPT) +# define SSL23_ST_SR_CLNT_HELLO_B (0x211|SSL_ST_ACCEPT) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ssl3.h b/optee/optee_test/host/openssl/include/openssl/ssl3.h new file mode 100644 index 0000000..e681d50 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ssl3.h @@ -0,0 +1,774 @@ +/* ssl/ssl3.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_SSL3_H +# define HEADER_SSL3_H + +# ifndef OPENSSL_NO_COMP +# include +# endif +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Signalling cipher suite value from RFC 5746 + * (TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + */ +# define SSL3_CK_SCSV 0x030000FF + +/* + * Signalling cipher suite value from draft-ietf-tls-downgrade-scsv-00 + * (TLS_FALLBACK_SCSV) + */ +# define SSL3_CK_FALLBACK_SCSV 0x03005600 + +# define SSL3_CK_RSA_NULL_MD5 0x03000001 +# define SSL3_CK_RSA_NULL_SHA 0x03000002 +# define SSL3_CK_RSA_RC4_40_MD5 0x03000003 +# define SSL3_CK_RSA_RC4_128_MD5 0x03000004 +# define SSL3_CK_RSA_RC4_128_SHA 0x03000005 +# define SSL3_CK_RSA_RC2_40_MD5 0x03000006 +# define SSL3_CK_RSA_IDEA_128_SHA 0x03000007 +# define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008 +# define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009 +# define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A + +# define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B +# define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C +# define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D +# define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E +# define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F +# define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010 + +# define SSL3_CK_EDH_DSS_DES_40_CBC_SHA 0x03000011 +# define SSL3_CK_DHE_DSS_DES_40_CBC_SHA SSL3_CK_EDH_DSS_DES_40_CBC_SHA +# define SSL3_CK_EDH_DSS_DES_64_CBC_SHA 0x03000012 +# define SSL3_CK_DHE_DSS_DES_64_CBC_SHA SSL3_CK_EDH_DSS_DES_64_CBC_SHA +# define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA 0x03000013 +# define SSL3_CK_DHE_DSS_DES_192_CBC3_SHA SSL3_CK_EDH_DSS_DES_192_CBC3_SHA +# define SSL3_CK_EDH_RSA_DES_40_CBC_SHA 0x03000014 +# define SSL3_CK_DHE_RSA_DES_40_CBC_SHA SSL3_CK_EDH_RSA_DES_40_CBC_SHA +# define SSL3_CK_EDH_RSA_DES_64_CBC_SHA 0x03000015 +# define SSL3_CK_DHE_RSA_DES_64_CBC_SHA SSL3_CK_EDH_RSA_DES_64_CBC_SHA +# define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA 0x03000016 +# define SSL3_CK_DHE_RSA_DES_192_CBC3_SHA SSL3_CK_EDH_RSA_DES_192_CBC3_SHA + +# define SSL3_CK_ADH_RC4_40_MD5 0x03000017 +# define SSL3_CK_ADH_RC4_128_MD5 0x03000018 +# define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019 +# define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A +# define SSL3_CK_ADH_DES_192_CBC_SHA 0x0300001B + +# if 0 +# define SSL3_CK_FZA_DMS_NULL_SHA 0x0300001C +# define SSL3_CK_FZA_DMS_FZA_SHA 0x0300001D +# if 0 /* Because it clashes with KRB5, is never + * used any more, and is safe to remove + * according to David Hopwood + * of the + * ietf-tls list */ +# define SSL3_CK_FZA_DMS_RC4_SHA 0x0300001E +# endif +# endif + +/* + * VRS Additional Kerberos5 entries + */ +# define SSL3_CK_KRB5_DES_64_CBC_SHA 0x0300001E +# define SSL3_CK_KRB5_DES_192_CBC3_SHA 0x0300001F +# define SSL3_CK_KRB5_RC4_128_SHA 0x03000020 +# define SSL3_CK_KRB5_IDEA_128_CBC_SHA 0x03000021 +# define SSL3_CK_KRB5_DES_64_CBC_MD5 0x03000022 +# define SSL3_CK_KRB5_DES_192_CBC3_MD5 0x03000023 +# define SSL3_CK_KRB5_RC4_128_MD5 0x03000024 +# define SSL3_CK_KRB5_IDEA_128_CBC_MD5 0x03000025 + +# define SSL3_CK_KRB5_DES_40_CBC_SHA 0x03000026 +# define SSL3_CK_KRB5_RC2_40_CBC_SHA 0x03000027 +# define SSL3_CK_KRB5_RC4_40_SHA 0x03000028 +# define SSL3_CK_KRB5_DES_40_CBC_MD5 0x03000029 +# define SSL3_CK_KRB5_RC2_40_CBC_MD5 0x0300002A +# define SSL3_CK_KRB5_RC4_40_MD5 0x0300002B + +# define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5" +# define SSL3_TXT_RSA_NULL_SHA "NULL-SHA" +# define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5" +# define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5" +# define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA" +# define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5" +# define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-SHA" +# define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA" +# define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA" +# define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA" + +# define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA" +# define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA" +# define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA" +# define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA" +# define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA" +# define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA" + +# define SSL3_TXT_DHE_DSS_DES_40_CBC_SHA "EXP-DHE-DSS-DES-CBC-SHA" +# define SSL3_TXT_DHE_DSS_DES_64_CBC_SHA "DHE-DSS-DES-CBC-SHA" +# define SSL3_TXT_DHE_DSS_DES_192_CBC3_SHA "DHE-DSS-DES-CBC3-SHA" +# define SSL3_TXT_DHE_RSA_DES_40_CBC_SHA "EXP-DHE-RSA-DES-CBC-SHA" +# define SSL3_TXT_DHE_RSA_DES_64_CBC_SHA "DHE-RSA-DES-CBC-SHA" +# define SSL3_TXT_DHE_RSA_DES_192_CBC3_SHA "DHE-RSA-DES-CBC3-SHA" + +/* + * This next block of six "EDH" labels is for backward compatibility with + * older versions of OpenSSL. New code should use the six "DHE" labels above + * instead: + */ +# define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA" +# define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA" +# define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA" +# define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC-SHA" +# define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA" +# define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA" + +# define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5" +# define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5" +# define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA" +# define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA" +# define SSL3_TXT_ADH_DES_192_CBC_SHA "ADH-DES-CBC3-SHA" + +# if 0 +# define SSL3_TXT_FZA_DMS_NULL_SHA "FZA-NULL-SHA" +# define SSL3_TXT_FZA_DMS_FZA_SHA "FZA-FZA-CBC-SHA" +# define SSL3_TXT_FZA_DMS_RC4_SHA "FZA-RC4-SHA" +# endif + +# define SSL3_TXT_KRB5_DES_64_CBC_SHA "KRB5-DES-CBC-SHA" +# define SSL3_TXT_KRB5_DES_192_CBC3_SHA "KRB5-DES-CBC3-SHA" +# define SSL3_TXT_KRB5_RC4_128_SHA "KRB5-RC4-SHA" +# define SSL3_TXT_KRB5_IDEA_128_CBC_SHA "KRB5-IDEA-CBC-SHA" +# define SSL3_TXT_KRB5_DES_64_CBC_MD5 "KRB5-DES-CBC-MD5" +# define SSL3_TXT_KRB5_DES_192_CBC3_MD5 "KRB5-DES-CBC3-MD5" +# define SSL3_TXT_KRB5_RC4_128_MD5 "KRB5-RC4-MD5" +# define SSL3_TXT_KRB5_IDEA_128_CBC_MD5 "KRB5-IDEA-CBC-MD5" + +# define SSL3_TXT_KRB5_DES_40_CBC_SHA "EXP-KRB5-DES-CBC-SHA" +# define SSL3_TXT_KRB5_RC2_40_CBC_SHA "EXP-KRB5-RC2-CBC-SHA" +# define SSL3_TXT_KRB5_RC4_40_SHA "EXP-KRB5-RC4-SHA" +# define SSL3_TXT_KRB5_DES_40_CBC_MD5 "EXP-KRB5-DES-CBC-MD5" +# define SSL3_TXT_KRB5_RC2_40_CBC_MD5 "EXP-KRB5-RC2-CBC-MD5" +# define SSL3_TXT_KRB5_RC4_40_MD5 "EXP-KRB5-RC4-MD5" + +# define SSL3_SSL_SESSION_ID_LENGTH 32 +# define SSL3_MAX_SSL_SESSION_ID_LENGTH 32 + +# define SSL3_MASTER_SECRET_SIZE 48 +# define SSL3_RANDOM_SIZE 32 +# define SSL3_SESSION_ID_SIZE 32 +# define SSL3_RT_HEADER_LENGTH 5 + +# define SSL3_HM_HEADER_LENGTH 4 + +# ifndef SSL3_ALIGN_PAYLOAD + /* + * Some will argue that this increases memory footprint, but it's not + * actually true. Point is that malloc has to return at least 64-bit aligned + * pointers, meaning that allocating 5 bytes wastes 3 bytes in either case. + * Suggested pre-gaping simply moves these wasted bytes from the end of + * allocated region to its front, but makes data payload aligned, which + * improves performance:-) + */ +# define SSL3_ALIGN_PAYLOAD 8 +# else +# if (SSL3_ALIGN_PAYLOAD&(SSL3_ALIGN_PAYLOAD-1))!=0 +# error "insane SSL3_ALIGN_PAYLOAD" +# undef SSL3_ALIGN_PAYLOAD +# endif +# endif + +/* + * This is the maximum MAC (digest) size used by the SSL library. Currently + * maximum of 20 is used by SHA1, but we reserve for future extension for + * 512-bit hashes. + */ + +# define SSL3_RT_MAX_MD_SIZE 64 + +/* + * Maximum block size used in all ciphersuites. Currently 16 for AES. + */ + +# define SSL_RT_MAX_CIPHER_BLOCK_SIZE 16 + +# define SSL3_RT_MAX_EXTRA (16384) + +/* Maximum plaintext length: defined by SSL/TLS standards */ +# define SSL3_RT_MAX_PLAIN_LENGTH 16384 +/* Maximum compression overhead: defined by SSL/TLS standards */ +# define SSL3_RT_MAX_COMPRESSED_OVERHEAD 1024 + +/* + * The standards give a maximum encryption overhead of 1024 bytes. In + * practice the value is lower than this. The overhead is the maximum number + * of padding bytes (256) plus the mac size. + */ +# define SSL3_RT_MAX_ENCRYPTED_OVERHEAD (256 + SSL3_RT_MAX_MD_SIZE) + +/* + * OpenSSL currently only uses a padding length of at most one block so the + * send overhead is smaller. + */ + +# define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + (SSL_RT_MAX_CIPHER_BLOCK_SIZE + SSL3_RT_MAX_MD_SIZE) + +/* If compression isn't used don't include the compression overhead */ + +# ifdef OPENSSL_NO_COMP +# define SSL3_RT_MAX_COMPRESSED_LENGTH SSL3_RT_MAX_PLAIN_LENGTH +# else +# define SSL3_RT_MAX_COMPRESSED_LENGTH \ + (SSL3_RT_MAX_PLAIN_LENGTH+SSL3_RT_MAX_COMPRESSED_OVERHEAD) +# endif +# define SSL3_RT_MAX_ENCRYPTED_LENGTH \ + (SSL3_RT_MAX_ENCRYPTED_OVERHEAD+SSL3_RT_MAX_COMPRESSED_LENGTH) +# define SSL3_RT_MAX_PACKET_SIZE \ + (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH) + +# define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54" +# define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52" + +# define SSL3_VERSION 0x0300 +# define SSL3_VERSION_MAJOR 0x03 +# define SSL3_VERSION_MINOR 0x00 + +# define SSL3_RT_CHANGE_CIPHER_SPEC 20 +# define SSL3_RT_ALERT 21 +# define SSL3_RT_HANDSHAKE 22 +# define SSL3_RT_APPLICATION_DATA 23 +# define TLS1_RT_HEARTBEAT 24 + +/* Pseudo content types to indicate additional parameters */ +# define TLS1_RT_CRYPTO 0x1000 +# define TLS1_RT_CRYPTO_PREMASTER (TLS1_RT_CRYPTO | 0x1) +# define TLS1_RT_CRYPTO_CLIENT_RANDOM (TLS1_RT_CRYPTO | 0x2) +# define TLS1_RT_CRYPTO_SERVER_RANDOM (TLS1_RT_CRYPTO | 0x3) +# define TLS1_RT_CRYPTO_MASTER (TLS1_RT_CRYPTO | 0x4) + +# define TLS1_RT_CRYPTO_READ 0x0000 +# define TLS1_RT_CRYPTO_WRITE 0x0100 +# define TLS1_RT_CRYPTO_MAC (TLS1_RT_CRYPTO | 0x5) +# define TLS1_RT_CRYPTO_KEY (TLS1_RT_CRYPTO | 0x6) +# define TLS1_RT_CRYPTO_IV (TLS1_RT_CRYPTO | 0x7) +# define TLS1_RT_CRYPTO_FIXED_IV (TLS1_RT_CRYPTO | 0x8) + +/* Pseudo content type for SSL/TLS header info */ +# define SSL3_RT_HEADER 0x100 + +# define SSL3_AL_WARNING 1 +# define SSL3_AL_FATAL 2 + +# define SSL3_AD_CLOSE_NOTIFY 0 +# define SSL3_AD_UNEXPECTED_MESSAGE 10/* fatal */ +# define SSL3_AD_BAD_RECORD_MAC 20/* fatal */ +# define SSL3_AD_DECOMPRESSION_FAILURE 30/* fatal */ +# define SSL3_AD_HANDSHAKE_FAILURE 40/* fatal */ +# define SSL3_AD_NO_CERTIFICATE 41 +# define SSL3_AD_BAD_CERTIFICATE 42 +# define SSL3_AD_UNSUPPORTED_CERTIFICATE 43 +# define SSL3_AD_CERTIFICATE_REVOKED 44 +# define SSL3_AD_CERTIFICATE_EXPIRED 45 +# define SSL3_AD_CERTIFICATE_UNKNOWN 46 +# define SSL3_AD_ILLEGAL_PARAMETER 47/* fatal */ + +# define TLS1_HB_REQUEST 1 +# define TLS1_HB_RESPONSE 2 + +# ifndef OPENSSL_NO_SSL_INTERN + +typedef struct ssl3_record_st { + /* type of record */ + /* + * r + */ int type; + /* How many bytes available */ + /* + * rw + */ unsigned int length; + /* read/write offset into 'buf' */ + /* + * r + */ unsigned int off; + /* pointer to the record data */ + /* + * rw + */ unsigned char *data; + /* where the decode bytes are */ + /* + * rw + */ unsigned char *input; + /* only used with decompression - malloc()ed */ + /* + * r + */ unsigned char *comp; + /* epoch number, needed by DTLS1 */ + /* + * r + */ unsigned long epoch; + /* sequence number, needed by DTLS1 */ + /* + * r + */ unsigned char seq_num[8]; +} SSL3_RECORD; + +typedef struct ssl3_buffer_st { + /* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */ + unsigned char *buf; + /* buffer size */ + size_t len; + /* where to 'copy from' */ + int offset; + /* how many bytes left */ + int left; +} SSL3_BUFFER; + +# endif + +# define SSL3_CT_RSA_SIGN 1 +# define SSL3_CT_DSS_SIGN 2 +# define SSL3_CT_RSA_FIXED_DH 3 +# define SSL3_CT_DSS_FIXED_DH 4 +# define SSL3_CT_RSA_EPHEMERAL_DH 5 +# define SSL3_CT_DSS_EPHEMERAL_DH 6 +# define SSL3_CT_FORTEZZA_DMS 20 +/* + * SSL3_CT_NUMBER is used to size arrays and it must be large enough to + * contain all of the cert types defined either for SSLv3 and TLSv1. + */ +# define SSL3_CT_NUMBER 9 + +# define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001 +# define SSL3_FLAGS_DELAY_CLIENT_FINISHED 0x0002 +# define SSL3_FLAGS_POP_BUFFER 0x0004 +# define TLS1_FLAGS_TLS_PADDING_BUG 0x0008 +# define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010 +# define TLS1_FLAGS_KEEP_HANDSHAKE 0x0020 +/* + * Set when the handshake is ready to process peer's ChangeCipherSpec message. + * Cleared after the message has been processed. + */ +# define SSL3_FLAGS_CCS_OK 0x0080 + +/* SSL3_FLAGS_SGC_RESTART_DONE is no longer used */ +# define SSL3_FLAGS_SGC_RESTART_DONE 0x0040 + +# ifndef OPENSSL_NO_SSL_INTERN + +typedef struct ssl3_state_st { + long flags; + int delay_buf_pop_ret; + unsigned char read_sequence[8]; + int read_mac_secret_size; + unsigned char read_mac_secret[EVP_MAX_MD_SIZE]; + unsigned char write_sequence[8]; + int write_mac_secret_size; + unsigned char write_mac_secret[EVP_MAX_MD_SIZE]; + unsigned char server_random[SSL3_RANDOM_SIZE]; + unsigned char client_random[SSL3_RANDOM_SIZE]; + /* flags for countermeasure against known-IV weakness */ + int need_empty_fragments; + int empty_fragment_done; + /* The value of 'extra' when the buffers were initialized */ + int init_extra; + SSL3_BUFFER rbuf; /* read IO goes into here */ + SSL3_BUFFER wbuf; /* write IO goes into here */ + SSL3_RECORD rrec; /* each decoded record goes in here */ + SSL3_RECORD wrec; /* goes out from here */ + /* + * storage for Alert/Handshake protocol data received but not yet + * processed by ssl3_read_bytes: + */ + unsigned char alert_fragment[2]; + unsigned int alert_fragment_len; + unsigned char handshake_fragment[4]; + unsigned int handshake_fragment_len; + /* partial write - check the numbers match */ + unsigned int wnum; /* number of bytes sent so far */ + int wpend_tot; /* number bytes written */ + int wpend_type; + int wpend_ret; /* number of bytes submitted */ + const unsigned char *wpend_buf; + /* used during startup, digest all incoming/outgoing packets */ + BIO *handshake_buffer; + /* + * When set of handshake digests is determined, buffer is hashed and + * freed and MD_CTX-es for all required digests are stored in this array + */ + EVP_MD_CTX **handshake_dgst; + /* + * Set whenever an expected ChangeCipherSpec message is processed. + * Unset when the peer's Finished message is received. + * Unexpected ChangeCipherSpec messages trigger a fatal alert. + */ + int change_cipher_spec; + int warn_alert; + int fatal_alert; + /* + * we allow one fatal and one warning alert to be outstanding, send close + * alert via the warning alert + */ + int alert_dispatch; + unsigned char send_alert[2]; + /* + * This flag is set when we should renegotiate ASAP, basically when there + * is no more data in the read or write buffers + */ + int renegotiate; + int total_renegotiations; + int num_renegotiations; + int in_read_app_data; + /* + * Opaque PRF input as used for the current handshake. These fields are + * used only if TLSEXT_TYPE_opaque_prf_input is defined (otherwise, they + * are merely present to improve binary compatibility) + */ + void *client_opaque_prf_input; + size_t client_opaque_prf_input_len; + void *server_opaque_prf_input; + size_t server_opaque_prf_input_len; + struct { + /* actually only needs to be 16+20 */ + unsigned char cert_verify_md[EVP_MAX_MD_SIZE * 2]; + /* actually only need to be 16+20 for SSLv3 and 12 for TLS */ + unsigned char finish_md[EVP_MAX_MD_SIZE * 2]; + int finish_md_len; + unsigned char peer_finish_md[EVP_MAX_MD_SIZE * 2]; + int peer_finish_md_len; + unsigned long message_size; + int message_type; + /* used to hold the new cipher we are going to use */ + const SSL_CIPHER *new_cipher; +# ifndef OPENSSL_NO_DH + DH *dh; +# endif +# ifndef OPENSSL_NO_ECDH + EC_KEY *ecdh; /* holds short lived ECDH key */ +# endif + /* used when SSL_ST_FLUSH_DATA is entered */ + int next_state; + int reuse_message; + /* used for certificate requests */ + int cert_req; + int ctype_num; + char ctype[SSL3_CT_NUMBER]; + STACK_OF(X509_NAME) *ca_names; + int use_rsa_tmp; + int key_block_length; + unsigned char *key_block; + const EVP_CIPHER *new_sym_enc; + const EVP_MD *new_hash; + int new_mac_pkey_type; + int new_mac_secret_size; +# ifndef OPENSSL_NO_COMP + const SSL_COMP *new_compression; +# else + char *new_compression; +# endif + int cert_request; + } tmp; + + /* Connection binding to prevent renegotiation attacks */ + unsigned char previous_client_finished[EVP_MAX_MD_SIZE]; + unsigned char previous_client_finished_len; + unsigned char previous_server_finished[EVP_MAX_MD_SIZE]; + unsigned char previous_server_finished_len; + int send_connection_binding; /* TODOEKR */ + +# ifndef OPENSSL_NO_NEXTPROTONEG + /* + * Set if we saw the Next Protocol Negotiation extension from our peer. + */ + int next_proto_neg_seen; +# endif + +# ifndef OPENSSL_NO_TLSEXT +# ifndef OPENSSL_NO_EC + /* + * This is set to true if we believe that this is a version of Safari + * running on OS X 10.6 or newer. We wish to know this because Safari on + * 10.8 .. 10.8.3 has broken ECDHE-ECDSA support. + */ + char is_probably_safari; +# endif /* !OPENSSL_NO_EC */ + + /* + * ALPN information (we are in the process of transitioning from NPN to + * ALPN.) + */ + + /* + * In a server these point to the selected ALPN protocol after the + * ClientHello has been processed. In a client these contain the protocol + * that the server selected once the ServerHello has been processed. + */ + unsigned char *alpn_selected; + unsigned alpn_selected_len; +# endif /* OPENSSL_NO_TLSEXT */ +} SSL3_STATE; + +# endif + +/* SSLv3 */ +/* + * client + */ +/* extra state */ +# define SSL3_ST_CW_FLUSH (0x100|SSL_ST_CONNECT) +# ifndef OPENSSL_NO_SCTP +# define DTLS1_SCTP_ST_CW_WRITE_SOCK (0x310|SSL_ST_CONNECT) +# define DTLS1_SCTP_ST_CR_READ_SOCK (0x320|SSL_ST_CONNECT) +# endif +/* write to server */ +# define SSL3_ST_CW_CLNT_HELLO_A (0x110|SSL_ST_CONNECT) +# define SSL3_ST_CW_CLNT_HELLO_B (0x111|SSL_ST_CONNECT) +/* read from server */ +# define SSL3_ST_CR_SRVR_HELLO_A (0x120|SSL_ST_CONNECT) +# define SSL3_ST_CR_SRVR_HELLO_B (0x121|SSL_ST_CONNECT) +# define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126|SSL_ST_CONNECT) +# define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127|SSL_ST_CONNECT) +# define SSL3_ST_CR_CERT_A (0x130|SSL_ST_CONNECT) +# define SSL3_ST_CR_CERT_B (0x131|SSL_ST_CONNECT) +# define SSL3_ST_CR_KEY_EXCH_A (0x140|SSL_ST_CONNECT) +# define SSL3_ST_CR_KEY_EXCH_B (0x141|SSL_ST_CONNECT) +# define SSL3_ST_CR_CERT_REQ_A (0x150|SSL_ST_CONNECT) +# define SSL3_ST_CR_CERT_REQ_B (0x151|SSL_ST_CONNECT) +# define SSL3_ST_CR_SRVR_DONE_A (0x160|SSL_ST_CONNECT) +# define SSL3_ST_CR_SRVR_DONE_B (0x161|SSL_ST_CONNECT) +/* write to server */ +# define SSL3_ST_CW_CERT_A (0x170|SSL_ST_CONNECT) +# define SSL3_ST_CW_CERT_B (0x171|SSL_ST_CONNECT) +# define SSL3_ST_CW_CERT_C (0x172|SSL_ST_CONNECT) +# define SSL3_ST_CW_CERT_D (0x173|SSL_ST_CONNECT) +# define SSL3_ST_CW_KEY_EXCH_A (0x180|SSL_ST_CONNECT) +# define SSL3_ST_CW_KEY_EXCH_B (0x181|SSL_ST_CONNECT) +# define SSL3_ST_CW_CERT_VRFY_A (0x190|SSL_ST_CONNECT) +# define SSL3_ST_CW_CERT_VRFY_B (0x191|SSL_ST_CONNECT) +# define SSL3_ST_CW_CHANGE_A (0x1A0|SSL_ST_CONNECT) +# define SSL3_ST_CW_CHANGE_B (0x1A1|SSL_ST_CONNECT) +# ifndef OPENSSL_NO_NEXTPROTONEG +# define SSL3_ST_CW_NEXT_PROTO_A (0x200|SSL_ST_CONNECT) +# define SSL3_ST_CW_NEXT_PROTO_B (0x201|SSL_ST_CONNECT) +# endif +# define SSL3_ST_CW_FINISHED_A (0x1B0|SSL_ST_CONNECT) +# define SSL3_ST_CW_FINISHED_B (0x1B1|SSL_ST_CONNECT) +/* read from server */ +# define SSL3_ST_CR_CHANGE_A (0x1C0|SSL_ST_CONNECT) +# define SSL3_ST_CR_CHANGE_B (0x1C1|SSL_ST_CONNECT) +# define SSL3_ST_CR_FINISHED_A (0x1D0|SSL_ST_CONNECT) +# define SSL3_ST_CR_FINISHED_B (0x1D1|SSL_ST_CONNECT) +# define SSL3_ST_CR_SESSION_TICKET_A (0x1E0|SSL_ST_CONNECT) +# define SSL3_ST_CR_SESSION_TICKET_B (0x1E1|SSL_ST_CONNECT) +# define SSL3_ST_CR_CERT_STATUS_A (0x1F0|SSL_ST_CONNECT) +# define SSL3_ST_CR_CERT_STATUS_B (0x1F1|SSL_ST_CONNECT) + +/* server */ +/* extra state */ +# define SSL3_ST_SW_FLUSH (0x100|SSL_ST_ACCEPT) +# ifndef OPENSSL_NO_SCTP +# define DTLS1_SCTP_ST_SW_WRITE_SOCK (0x310|SSL_ST_ACCEPT) +# define DTLS1_SCTP_ST_SR_READ_SOCK (0x320|SSL_ST_ACCEPT) +# endif +/* read from client */ +/* Do not change the number values, they do matter */ +# define SSL3_ST_SR_CLNT_HELLO_A (0x110|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CLNT_HELLO_D (0x115|SSL_ST_ACCEPT) +/* write to client */ +# define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT) +# define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT) +# define SSL3_ST_SW_HELLO_REQ_A (0x120|SSL_ST_ACCEPT) +# define SSL3_ST_SW_HELLO_REQ_B (0x121|SSL_ST_ACCEPT) +# define SSL3_ST_SW_HELLO_REQ_C (0x122|SSL_ST_ACCEPT) +# define SSL3_ST_SW_SRVR_HELLO_A (0x130|SSL_ST_ACCEPT) +# define SSL3_ST_SW_SRVR_HELLO_B (0x131|SSL_ST_ACCEPT) +# define SSL3_ST_SW_CERT_A (0x140|SSL_ST_ACCEPT) +# define SSL3_ST_SW_CERT_B (0x141|SSL_ST_ACCEPT) +# define SSL3_ST_SW_KEY_EXCH_A (0x150|SSL_ST_ACCEPT) +# define SSL3_ST_SW_KEY_EXCH_B (0x151|SSL_ST_ACCEPT) +# define SSL3_ST_SW_CERT_REQ_A (0x160|SSL_ST_ACCEPT) +# define SSL3_ST_SW_CERT_REQ_B (0x161|SSL_ST_ACCEPT) +# define SSL3_ST_SW_SRVR_DONE_A (0x170|SSL_ST_ACCEPT) +# define SSL3_ST_SW_SRVR_DONE_B (0x171|SSL_ST_ACCEPT) +/* read from client */ +# define SSL3_ST_SR_CERT_A (0x180|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CERT_B (0x181|SSL_ST_ACCEPT) +# define SSL3_ST_SR_KEY_EXCH_A (0x190|SSL_ST_ACCEPT) +# define SSL3_ST_SR_KEY_EXCH_B (0x191|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CERT_VRFY_A (0x1A0|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CERT_VRFY_B (0x1A1|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CHANGE_A (0x1B0|SSL_ST_ACCEPT) +# define SSL3_ST_SR_CHANGE_B (0x1B1|SSL_ST_ACCEPT) +# ifndef OPENSSL_NO_NEXTPROTONEG +# define SSL3_ST_SR_NEXT_PROTO_A (0x210|SSL_ST_ACCEPT) +# define SSL3_ST_SR_NEXT_PROTO_B (0x211|SSL_ST_ACCEPT) +# endif +# define SSL3_ST_SR_FINISHED_A (0x1C0|SSL_ST_ACCEPT) +# define SSL3_ST_SR_FINISHED_B (0x1C1|SSL_ST_ACCEPT) +/* write to client */ +# define SSL3_ST_SW_CHANGE_A (0x1D0|SSL_ST_ACCEPT) +# define SSL3_ST_SW_CHANGE_B (0x1D1|SSL_ST_ACCEPT) +# define SSL3_ST_SW_FINISHED_A (0x1E0|SSL_ST_ACCEPT) +# define SSL3_ST_SW_FINISHED_B (0x1E1|SSL_ST_ACCEPT) +# define SSL3_ST_SW_SESSION_TICKET_A (0x1F0|SSL_ST_ACCEPT) +# define SSL3_ST_SW_SESSION_TICKET_B (0x1F1|SSL_ST_ACCEPT) +# define SSL3_ST_SW_CERT_STATUS_A (0x200|SSL_ST_ACCEPT) +# define SSL3_ST_SW_CERT_STATUS_B (0x201|SSL_ST_ACCEPT) + +# define SSL3_MT_HELLO_REQUEST 0 +# define SSL3_MT_CLIENT_HELLO 1 +# define SSL3_MT_SERVER_HELLO 2 +# define SSL3_MT_NEWSESSION_TICKET 4 +# define SSL3_MT_CERTIFICATE 11 +# define SSL3_MT_SERVER_KEY_EXCHANGE 12 +# define SSL3_MT_CERTIFICATE_REQUEST 13 +# define SSL3_MT_SERVER_DONE 14 +# define SSL3_MT_CERTIFICATE_VERIFY 15 +# define SSL3_MT_CLIENT_KEY_EXCHANGE 16 +# define SSL3_MT_FINISHED 20 +# define SSL3_MT_CERTIFICATE_STATUS 22 +# ifndef OPENSSL_NO_NEXTPROTONEG +# define SSL3_MT_NEXT_PROTO 67 +# endif +# define DTLS1_MT_HELLO_VERIFY_REQUEST 3 + +# define SSL3_MT_CCS 1 + +/* These are used when changing over to a new cipher */ +# define SSL3_CC_READ 0x01 +# define SSL3_CC_WRITE 0x02 +# define SSL3_CC_CLIENT 0x10 +# define SSL3_CC_SERVER 0x20 +# define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE) +# define SSL3_CHANGE_CIPHER_SERVER_READ (SSL3_CC_SERVER|SSL3_CC_READ) +# define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT|SSL3_CC_READ) +# define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER|SSL3_CC_WRITE) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/stack.h b/optee/optee_test/host/openssl/include/openssl/stack.h new file mode 100644 index 0000000..eb07216 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/stack.h @@ -0,0 +1,107 @@ +/* crypto/stack/stack.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_STACK_H +# define HEADER_STACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stack_st { + int num; + char **data; + int sorted; + int num_alloc; + int (*comp) (const void *, const void *); +} _STACK; /* Use STACK_OF(...) instead */ + +# define M_sk_num(sk) ((sk) ? (sk)->num:-1) +# define M_sk_value(sk,n) ((sk) ? (sk)->data[n] : NULL) + +int sk_num(const _STACK *); +void *sk_value(const _STACK *, int); + +void *sk_set(_STACK *, int, void *); + +_STACK *sk_new(int (*cmp) (const void *, const void *)); +_STACK *sk_new_null(void); +void sk_free(_STACK *); +void sk_pop_free(_STACK *st, void (*func) (void *)); +_STACK *sk_deep_copy(_STACK *, void *(*)(void *), void (*)(void *)); +int sk_insert(_STACK *sk, void *data, int where); +void *sk_delete(_STACK *st, int loc); +void *sk_delete_ptr(_STACK *st, void *p); +int sk_find(_STACK *st, void *data); +int sk_find_ex(_STACK *st, void *data); +int sk_push(_STACK *st, void *data); +int sk_unshift(_STACK *st, void *data); +void *sk_shift(_STACK *st); +void *sk_pop(_STACK *st); +void sk_zero(_STACK *st); +int (*sk_set_cmp_func(_STACK *sk, int (*c) (const void *, const void *))) + (const void *, const void *); +_STACK *sk_dup(_STACK *st); +void sk_sort(_STACK *st); +int sk_is_sorted(const _STACK *st); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/symhacks.h b/optee/optee_test/host/openssl/include/openssl/symhacks.h new file mode 100644 index 0000000..3001957 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/symhacks.h @@ -0,0 +1,518 @@ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_SYMHACKS_H +# define HEADER_SYMHACKS_H + +# include + +/* + * Hacks to solve the problem with linkers incapable of handling very long + * symbol names. In the case of VMS, the limit is 31 characters on VMS for + * VAX. + */ +/* + * Note that this affects util/libeay.num and util/ssleay.num... you may + * change those manually, but that's not recommended, as those files are + * controlled centrally and updated on Unix, and the central definition may + * disagree with yours, which in turn may come with shareable library + * incompatibilities. + */ +# ifdef OPENSSL_SYS_VMS + +/* Hack a long name in crypto/ex_data.c */ +# undef CRYPTO_get_ex_data_implementation +# define CRYPTO_get_ex_data_implementation CRYPTO_get_ex_data_impl +# undef CRYPTO_set_ex_data_implementation +# define CRYPTO_set_ex_data_implementation CRYPTO_set_ex_data_impl + +/* Hack a long name in crypto/asn1/a_mbstr.c */ +# undef ASN1_STRING_set_default_mask_asc +# define ASN1_STRING_set_default_mask_asc ASN1_STRING_set_def_mask_asc + +# if 0 /* No longer needed, since safestack macro + * magic does the job */ +/* Hack the names created with DECLARE_ASN1_SET_OF(PKCS7_SIGNER_INFO) */ +# undef i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO +# define i2d_ASN1_SET_OF_PKCS7_SIGNER_INFO i2d_ASN1_SET_OF_PKCS7_SIGINF +# undef d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO +# define d2i_ASN1_SET_OF_PKCS7_SIGNER_INFO d2i_ASN1_SET_OF_PKCS7_SIGINF +# endif + +# if 0 /* No longer needed, since safestack macro + * magic does the job */ +/* Hack the names created with DECLARE_ASN1_SET_OF(PKCS7_RECIP_INFO) */ +# undef i2d_ASN1_SET_OF_PKCS7_RECIP_INFO +# define i2d_ASN1_SET_OF_PKCS7_RECIP_INFO i2d_ASN1_SET_OF_PKCS7_RECINF +# undef d2i_ASN1_SET_OF_PKCS7_RECIP_INFO +# define d2i_ASN1_SET_OF_PKCS7_RECIP_INFO d2i_ASN1_SET_OF_PKCS7_RECINF +# endif + +# if 0 /* No longer needed, since safestack macro + * magic does the job */ +/* Hack the names created with DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION) */ +# undef i2d_ASN1_SET_OF_ACCESS_DESCRIPTION +# define i2d_ASN1_SET_OF_ACCESS_DESCRIPTION i2d_ASN1_SET_OF_ACC_DESC +# undef d2i_ASN1_SET_OF_ACCESS_DESCRIPTION +# define d2i_ASN1_SET_OF_ACCESS_DESCRIPTION d2i_ASN1_SET_OF_ACC_DESC +# endif + +/* Hack the names created with DECLARE_PEM_rw(NETSCAPE_CERT_SEQUENCE) */ +# undef PEM_read_NETSCAPE_CERT_SEQUENCE +# define PEM_read_NETSCAPE_CERT_SEQUENCE PEM_read_NS_CERT_SEQ +# undef PEM_write_NETSCAPE_CERT_SEQUENCE +# define PEM_write_NETSCAPE_CERT_SEQUENCE PEM_write_NS_CERT_SEQ +# undef PEM_read_bio_NETSCAPE_CERT_SEQUENCE +# define PEM_read_bio_NETSCAPE_CERT_SEQUENCE PEM_read_bio_NS_CERT_SEQ +# undef PEM_write_bio_NETSCAPE_CERT_SEQUENCE +# define PEM_write_bio_NETSCAPE_CERT_SEQUENCE PEM_write_bio_NS_CERT_SEQ +# undef PEM_write_cb_bio_NETSCAPE_CERT_SEQUENCE +# define PEM_write_cb_bio_NETSCAPE_CERT_SEQUENCE PEM_write_cb_bio_NS_CERT_SEQ + +/* Hack the names created with DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO) */ +# undef PEM_read_PKCS8_PRIV_KEY_INFO +# define PEM_read_PKCS8_PRIV_KEY_INFO PEM_read_P8_PRIV_KEY_INFO +# undef PEM_write_PKCS8_PRIV_KEY_INFO +# define PEM_write_PKCS8_PRIV_KEY_INFO PEM_write_P8_PRIV_KEY_INFO +# undef PEM_read_bio_PKCS8_PRIV_KEY_INFO +# define PEM_read_bio_PKCS8_PRIV_KEY_INFO PEM_read_bio_P8_PRIV_KEY_INFO +# undef PEM_write_bio_PKCS8_PRIV_KEY_INFO +# define PEM_write_bio_PKCS8_PRIV_KEY_INFO PEM_write_bio_P8_PRIV_KEY_INFO +# undef PEM_write_cb_bio_PKCS8_PRIV_KEY_INFO +# define PEM_write_cb_bio_PKCS8_PRIV_KEY_INFO PEM_wrt_cb_bio_P8_PRIV_KEY_INFO + +/* Hack other PEM names */ +# undef PEM_write_bio_PKCS8PrivateKey_nid +# define PEM_write_bio_PKCS8PrivateKey_nid PEM_write_bio_PKCS8PrivKey_nid + +/* Hack some long X509 names */ +# undef X509_REVOKED_get_ext_by_critical +# define X509_REVOKED_get_ext_by_critical X509_REVOKED_get_ext_by_critic +# undef X509_policy_tree_get0_user_policies +# define X509_policy_tree_get0_user_policies X509_pcy_tree_get0_usr_policies +# undef X509_policy_node_get0_qualifiers +# define X509_policy_node_get0_qualifiers X509_pcy_node_get0_qualifiers +# undef X509_STORE_CTX_get_explicit_policy +# define X509_STORE_CTX_get_explicit_policy X509_STORE_CTX_get_expl_policy +# undef X509_STORE_CTX_get0_current_issuer +# define X509_STORE_CTX_get0_current_issuer X509_STORE_CTX_get0_cur_issuer + +/* Hack some long CRYPTO names */ +# undef CRYPTO_set_dynlock_destroy_callback +# define CRYPTO_set_dynlock_destroy_callback CRYPTO_set_dynlock_destroy_cb +# undef CRYPTO_set_dynlock_create_callback +# define CRYPTO_set_dynlock_create_callback CRYPTO_set_dynlock_create_cb +# undef CRYPTO_set_dynlock_lock_callback +# define CRYPTO_set_dynlock_lock_callback CRYPTO_set_dynlock_lock_cb +# undef CRYPTO_get_dynlock_lock_callback +# define CRYPTO_get_dynlock_lock_callback CRYPTO_get_dynlock_lock_cb +# undef CRYPTO_get_dynlock_destroy_callback +# define CRYPTO_get_dynlock_destroy_callback CRYPTO_get_dynlock_destroy_cb +# undef CRYPTO_get_dynlock_create_callback +# define CRYPTO_get_dynlock_create_callback CRYPTO_get_dynlock_create_cb +# undef CRYPTO_set_locked_mem_ex_functions +# define CRYPTO_set_locked_mem_ex_functions CRYPTO_set_locked_mem_ex_funcs +# undef CRYPTO_get_locked_mem_ex_functions +# define CRYPTO_get_locked_mem_ex_functions CRYPTO_get_locked_mem_ex_funcs + +/* Hack some long SSL/TLS names */ +# undef SSL_CTX_set_default_verify_paths +# define SSL_CTX_set_default_verify_paths SSL_CTX_set_def_verify_paths +# undef SSL_get_ex_data_X509_STORE_CTX_idx +# define SSL_get_ex_data_X509_STORE_CTX_idx SSL_get_ex_d_X509_STORE_CTX_idx +# undef SSL_add_file_cert_subjects_to_stack +# define SSL_add_file_cert_subjects_to_stack SSL_add_file_cert_subjs_to_stk +# undef SSL_add_dir_cert_subjects_to_stack +# define SSL_add_dir_cert_subjects_to_stack SSL_add_dir_cert_subjs_to_stk +# undef SSL_CTX_use_certificate_chain_file +# define SSL_CTX_use_certificate_chain_file SSL_CTX_use_cert_chain_file +# undef SSL_CTX_set_cert_verify_callback +# define SSL_CTX_set_cert_verify_callback SSL_CTX_set_cert_verify_cb +# undef SSL_CTX_set_default_passwd_cb_userdata +# define SSL_CTX_set_default_passwd_cb_userdata SSL_CTX_set_def_passwd_cb_ud +# undef SSL_COMP_get_compression_methods +# define SSL_COMP_get_compression_methods SSL_COMP_get_compress_methods +# undef SSL_COMP_set0_compression_methods +# define SSL_COMP_set0_compression_methods SSL_COMP_set0_compress_methods +# undef SSL_COMP_free_compression_methods +# define SSL_COMP_free_compression_methods SSL_COMP_free_compress_methods +# undef ssl_add_clienthello_renegotiate_ext +# define ssl_add_clienthello_renegotiate_ext ssl_add_clienthello_reneg_ext +# undef ssl_add_serverhello_renegotiate_ext +# define ssl_add_serverhello_renegotiate_ext ssl_add_serverhello_reneg_ext +# undef ssl_parse_clienthello_renegotiate_ext +# define ssl_parse_clienthello_renegotiate_ext ssl_parse_clienthello_reneg_ext +# undef ssl_parse_serverhello_renegotiate_ext +# define ssl_parse_serverhello_renegotiate_ext ssl_parse_serverhello_reneg_ext +# undef SSL_srp_server_param_with_username +# define SSL_srp_server_param_with_username SSL_srp_server_param_with_un +# undef SSL_CTX_set_srp_client_pwd_callback +# define SSL_CTX_set_srp_client_pwd_callback SSL_CTX_set_srp_client_pwd_cb +# undef SSL_CTX_set_srp_verify_param_callback +# define SSL_CTX_set_srp_verify_param_callback SSL_CTX_set_srp_vfy_param_cb +# undef SSL_CTX_set_srp_username_callback +# define SSL_CTX_set_srp_username_callback SSL_CTX_set_srp_un_cb +# undef ssl_add_clienthello_use_srtp_ext +# define ssl_add_clienthello_use_srtp_ext ssl_add_clihello_use_srtp_ext +# undef ssl_add_serverhello_use_srtp_ext +# define ssl_add_serverhello_use_srtp_ext ssl_add_serhello_use_srtp_ext +# undef ssl_parse_clienthello_use_srtp_ext +# define ssl_parse_clienthello_use_srtp_ext ssl_parse_clihello_use_srtp_ext +# undef ssl_parse_serverhello_use_srtp_ext +# define ssl_parse_serverhello_use_srtp_ext ssl_parse_serhello_use_srtp_ext +# undef SSL_CTX_set_next_protos_advertised_cb +# define SSL_CTX_set_next_protos_advertised_cb SSL_CTX_set_next_protos_adv_cb +# undef SSL_CTX_set_next_proto_select_cb +# define SSL_CTX_set_next_proto_select_cb SSL_CTX_set_next_proto_sel_cb + +# undef tls1_send_server_supplemental_data +# define tls1_send_server_supplemental_data tls1_send_server_suppl_data +# undef tls1_send_client_supplemental_data +# define tls1_send_client_supplemental_data tls1_send_client_suppl_data +# undef tls1_get_server_supplemental_data +# define tls1_get_server_supplemental_data tls1_get_server_suppl_data +# undef tls1_get_client_supplemental_data +# define tls1_get_client_supplemental_data tls1_get_client_suppl_data + +# undef ssl3_cbc_record_digest_supported +# define ssl3_cbc_record_digest_supported ssl3_cbc_record_digest_support +# undef ssl_check_clienthello_tlsext_late +# define ssl_check_clienthello_tlsext_late ssl_check_clihello_tlsext_late +# undef ssl_check_clienthello_tlsext_early +# define ssl_check_clienthello_tlsext_early ssl_check_clihello_tlsext_early + +/* Hack some RSA long names */ +# undef RSA_padding_check_PKCS1_OAEP_mgf1 +# define RSA_padding_check_PKCS1_OAEP_mgf1 RSA_pad_check_PKCS1_OAEP_mgf1 + +/* Hack some ENGINE long names */ +# undef ENGINE_get_default_BN_mod_exp_crt +# define ENGINE_get_default_BN_mod_exp_crt ENGINE_get_def_BN_mod_exp_crt +# undef ENGINE_set_default_BN_mod_exp_crt +# define ENGINE_set_default_BN_mod_exp_crt ENGINE_set_def_BN_mod_exp_crt +# undef ENGINE_set_load_privkey_function +# define ENGINE_set_load_privkey_function ENGINE_set_load_privkey_fn +# undef ENGINE_get_load_privkey_function +# define ENGINE_get_load_privkey_function ENGINE_get_load_privkey_fn +# undef ENGINE_unregister_pkey_asn1_meths +# define ENGINE_unregister_pkey_asn1_meths ENGINE_unreg_pkey_asn1_meths +# undef ENGINE_register_all_pkey_asn1_meths +# define ENGINE_register_all_pkey_asn1_meths ENGINE_reg_all_pkey_asn1_meths +# undef ENGINE_set_default_pkey_asn1_meths +# define ENGINE_set_default_pkey_asn1_meths ENGINE_set_def_pkey_asn1_meths +# undef ENGINE_get_pkey_asn1_meth_engine +# define ENGINE_get_pkey_asn1_meth_engine ENGINE_get_pkey_asn1_meth_eng +# undef ENGINE_set_load_ssl_client_cert_function +# define ENGINE_set_load_ssl_client_cert_function \ + ENGINE_set_ld_ssl_clnt_cert_fn +# undef ENGINE_get_ssl_client_cert_function +# define ENGINE_get_ssl_client_cert_function ENGINE_get_ssl_client_cert_fn + +/* Hack some long OCSP names */ +# undef OCSP_REQUEST_get_ext_by_critical +# define OCSP_REQUEST_get_ext_by_critical OCSP_REQUEST_get_ext_by_crit +# undef OCSP_BASICRESP_get_ext_by_critical +# define OCSP_BASICRESP_get_ext_by_critical OCSP_BASICRESP_get_ext_by_crit +# undef OCSP_SINGLERESP_get_ext_by_critical +# define OCSP_SINGLERESP_get_ext_by_critical OCSP_SINGLERESP_get_ext_by_crit + +/* Hack some long DES names */ +# undef _ossl_old_des_ede3_cfb64_encrypt +# define _ossl_old_des_ede3_cfb64_encrypt _ossl_odes_ede3_cfb64_encrypt +# undef _ossl_old_des_ede3_ofb64_encrypt +# define _ossl_old_des_ede3_ofb64_encrypt _ossl_odes_ede3_ofb64_encrypt + +/* Hack some long EVP names */ +# undef OPENSSL_add_all_algorithms_noconf +# define OPENSSL_add_all_algorithms_noconf OPENSSL_add_all_algo_noconf +# undef OPENSSL_add_all_algorithms_conf +# define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algo_conf +# undef EVP_PKEY_meth_set_verify_recover +# define EVP_PKEY_meth_set_verify_recover EVP_PKEY_meth_set_vrfy_recover +# undef EVP_PKEY_meth_get_verify_recover +# define EVP_PKEY_meth_get_verify_recover EVP_PKEY_meth_get_vrfy_recover + +/* Hack some long EC names */ +# undef EC_GROUP_set_point_conversion_form +# define EC_GROUP_set_point_conversion_form EC_GROUP_set_point_conv_form +# undef EC_GROUP_get_point_conversion_form +# define EC_GROUP_get_point_conversion_form EC_GROUP_get_point_conv_form +# undef EC_GROUP_clear_free_all_extra_data +# define EC_GROUP_clear_free_all_extra_data EC_GROUP_clr_free_all_xtra_data +# undef EC_KEY_set_public_key_affine_coordinates +# define EC_KEY_set_public_key_affine_coordinates \ + EC_KEY_set_pub_key_aff_coords +# undef EC_POINT_set_Jprojective_coordinates_GFp +# define EC_POINT_set_Jprojective_coordinates_GFp \ + EC_POINT_set_Jproj_coords_GFp +# undef EC_POINT_get_Jprojective_coordinates_GFp +# define EC_POINT_get_Jprojective_coordinates_GFp \ + EC_POINT_get_Jproj_coords_GFp +# undef EC_POINT_set_affine_coordinates_GFp +# define EC_POINT_set_affine_coordinates_GFp EC_POINT_set_affine_coords_GFp +# undef EC_POINT_get_affine_coordinates_GFp +# define EC_POINT_get_affine_coordinates_GFp EC_POINT_get_affine_coords_GFp +# undef EC_POINT_set_compressed_coordinates_GFp +# define EC_POINT_set_compressed_coordinates_GFp EC_POINT_set_compr_coords_GFp +# undef EC_POINT_set_affine_coordinates_GF2m +# define EC_POINT_set_affine_coordinates_GF2m EC_POINT_set_affine_coords_GF2m +# undef EC_POINT_get_affine_coordinates_GF2m +# define EC_POINT_get_affine_coordinates_GF2m EC_POINT_get_affine_coords_GF2m +# undef EC_POINT_set_compressed_coordinates_GF2m +# define EC_POINT_set_compressed_coordinates_GF2m \ + EC_POINT_set_compr_coords_GF2m +# undef ec_GF2m_simple_group_clear_finish +# define ec_GF2m_simple_group_clear_finish ec_GF2m_simple_grp_clr_finish +# undef ec_GF2m_simple_group_check_discriminant +# define ec_GF2m_simple_group_check_discriminant ec_GF2m_simple_grp_chk_discrim +# undef ec_GF2m_simple_point_clear_finish +# define ec_GF2m_simple_point_clear_finish ec_GF2m_simple_pt_clr_finish +# undef ec_GF2m_simple_point_set_to_infinity +# define ec_GF2m_simple_point_set_to_infinity ec_GF2m_simple_pt_set_to_inf +# undef ec_GF2m_simple_points_make_affine +# define ec_GF2m_simple_points_make_affine ec_GF2m_simple_pts_make_affine +# undef ec_GF2m_simple_point_set_affine_coordinates +# define ec_GF2m_simple_point_set_affine_coordinates \ + ec_GF2m_smp_pt_set_af_coords +# undef ec_GF2m_simple_point_get_affine_coordinates +# define ec_GF2m_simple_point_get_affine_coordinates \ + ec_GF2m_smp_pt_get_af_coords +# undef ec_GF2m_simple_set_compressed_coordinates +# define ec_GF2m_simple_set_compressed_coordinates \ + ec_GF2m_smp_set_compr_coords +# undef ec_GFp_simple_group_set_curve_GFp +# define ec_GFp_simple_group_set_curve_GFp ec_GFp_simple_grp_set_curve_GFp +# undef ec_GFp_simple_group_get_curve_GFp +# define ec_GFp_simple_group_get_curve_GFp ec_GFp_simple_grp_get_curve_GFp +# undef ec_GFp_simple_group_clear_finish +# define ec_GFp_simple_group_clear_finish ec_GFp_simple_grp_clear_finish +# undef ec_GFp_simple_group_set_generator +# define ec_GFp_simple_group_set_generator ec_GFp_simple_grp_set_generator +# undef ec_GFp_simple_group_get0_generator +# define ec_GFp_simple_group_get0_generator ec_GFp_simple_grp_gt0_generator +# undef ec_GFp_simple_group_get_cofactor +# define ec_GFp_simple_group_get_cofactor ec_GFp_simple_grp_get_cofactor +# undef ec_GFp_simple_point_clear_finish +# define ec_GFp_simple_point_clear_finish ec_GFp_simple_pt_clear_finish +# undef ec_GFp_simple_point_set_to_infinity +# define ec_GFp_simple_point_set_to_infinity ec_GFp_simple_pt_set_to_inf +# undef ec_GFp_simple_points_make_affine +# define ec_GFp_simple_points_make_affine ec_GFp_simple_pts_make_affine +# undef ec_GFp_simple_set_Jprojective_coordinates_GFp +# define ec_GFp_simple_set_Jprojective_coordinates_GFp \ + ec_GFp_smp_set_Jproj_coords_GFp +# undef ec_GFp_simple_get_Jprojective_coordinates_GFp +# define ec_GFp_simple_get_Jprojective_coordinates_GFp \ + ec_GFp_smp_get_Jproj_coords_GFp +# undef ec_GFp_simple_point_set_affine_coordinates_GFp +# define ec_GFp_simple_point_set_affine_coordinates_GFp \ + ec_GFp_smp_pt_set_af_coords_GFp +# undef ec_GFp_simple_point_get_affine_coordinates_GFp +# define ec_GFp_simple_point_get_affine_coordinates_GFp \ + ec_GFp_smp_pt_get_af_coords_GFp +# undef ec_GFp_simple_set_compressed_coordinates_GFp +# define ec_GFp_simple_set_compressed_coordinates_GFp \ + ec_GFp_smp_set_compr_coords_GFp +# undef ec_GFp_simple_point_set_affine_coordinates +# define ec_GFp_simple_point_set_affine_coordinates \ + ec_GFp_smp_pt_set_af_coords +# undef ec_GFp_simple_point_get_affine_coordinates +# define ec_GFp_simple_point_get_affine_coordinates \ + ec_GFp_smp_pt_get_af_coords +# undef ec_GFp_simple_set_compressed_coordinates +# define ec_GFp_simple_set_compressed_coordinates \ + ec_GFp_smp_set_compr_coords +# undef ec_GFp_simple_group_check_discriminant +# define ec_GFp_simple_group_check_discriminant ec_GFp_simple_grp_chk_discrim + +/* Hack som long STORE names */ +# undef STORE_method_set_initialise_function +# define STORE_method_set_initialise_function STORE_meth_set_initialise_fn +# undef STORE_method_set_cleanup_function +# define STORE_method_set_cleanup_function STORE_meth_set_cleanup_fn +# undef STORE_method_set_generate_function +# define STORE_method_set_generate_function STORE_meth_set_generate_fn +# undef STORE_method_set_modify_function +# define STORE_method_set_modify_function STORE_meth_set_modify_fn +# undef STORE_method_set_revoke_function +# define STORE_method_set_revoke_function STORE_meth_set_revoke_fn +# undef STORE_method_set_delete_function +# define STORE_method_set_delete_function STORE_meth_set_delete_fn +# undef STORE_method_set_list_start_function +# define STORE_method_set_list_start_function STORE_meth_set_list_start_fn +# undef STORE_method_set_list_next_function +# define STORE_method_set_list_next_function STORE_meth_set_list_next_fn +# undef STORE_method_set_list_end_function +# define STORE_method_set_list_end_function STORE_meth_set_list_end_fn +# undef STORE_method_set_update_store_function +# define STORE_method_set_update_store_function STORE_meth_set_update_store_fn +# undef STORE_method_set_lock_store_function +# define STORE_method_set_lock_store_function STORE_meth_set_lock_store_fn +# undef STORE_method_set_unlock_store_function +# define STORE_method_set_unlock_store_function STORE_meth_set_unlock_store_fn +# undef STORE_method_get_initialise_function +# define STORE_method_get_initialise_function STORE_meth_get_initialise_fn +# undef STORE_method_get_cleanup_function +# define STORE_method_get_cleanup_function STORE_meth_get_cleanup_fn +# undef STORE_method_get_generate_function +# define STORE_method_get_generate_function STORE_meth_get_generate_fn +# undef STORE_method_get_modify_function +# define STORE_method_get_modify_function STORE_meth_get_modify_fn +# undef STORE_method_get_revoke_function +# define STORE_method_get_revoke_function STORE_meth_get_revoke_fn +# undef STORE_method_get_delete_function +# define STORE_method_get_delete_function STORE_meth_get_delete_fn +# undef STORE_method_get_list_start_function +# define STORE_method_get_list_start_function STORE_meth_get_list_start_fn +# undef STORE_method_get_list_next_function +# define STORE_method_get_list_next_function STORE_meth_get_list_next_fn +# undef STORE_method_get_list_end_function +# define STORE_method_get_list_end_function STORE_meth_get_list_end_fn +# undef STORE_method_get_update_store_function +# define STORE_method_get_update_store_function STORE_meth_get_update_store_fn +# undef STORE_method_get_lock_store_function +# define STORE_method_get_lock_store_function STORE_meth_get_lock_store_fn +# undef STORE_method_get_unlock_store_function +# define STORE_method_get_unlock_store_function STORE_meth_get_unlock_store_fn + +/* Hack some long TS names */ +# undef TS_RESP_CTX_set_status_info_cond +# define TS_RESP_CTX_set_status_info_cond TS_RESP_CTX_set_stat_info_cond +# undef TS_RESP_CTX_set_clock_precision_digits +# define TS_RESP_CTX_set_clock_precision_digits TS_RESP_CTX_set_clk_prec_digits +# undef TS_CONF_set_clock_precision_digits +# define TS_CONF_set_clock_precision_digits TS_CONF_set_clk_prec_digits + +/* Hack some long CMS names */ +# undef CMS_RecipientInfo_ktri_get0_algs +# define CMS_RecipientInfo_ktri_get0_algs CMS_RecipInfo_ktri_get0_algs +# undef CMS_RecipientInfo_ktri_get0_signer_id +# define CMS_RecipientInfo_ktri_get0_signer_id CMS_RecipInfo_ktri_get0_sigr_id +# undef CMS_OtherRevocationInfoFormat_it +# define CMS_OtherRevocationInfoFormat_it CMS_OtherRevocInfoFormat_it +# undef CMS_KeyAgreeRecipientIdentifier_it +# define CMS_KeyAgreeRecipientIdentifier_it CMS_KeyAgreeRecipIdentifier_it +# undef CMS_OriginatorIdentifierOrKey_it +# define CMS_OriginatorIdentifierOrKey_it CMS_OriginatorIdOrKey_it +# undef cms_SignerIdentifier_get0_signer_id +# define cms_SignerIdentifier_get0_signer_id cms_SignerId_get0_signer_id +# undef CMS_RecipientInfo_kari_get0_orig_id +# define CMS_RecipientInfo_kari_get0_orig_id CMS_RecipInfo_kari_get0_orig_id +# undef CMS_RecipientInfo_kari_get0_reks +# define CMS_RecipientInfo_kari_get0_reks CMS_RecipInfo_kari_get0_reks +# undef CMS_RecipientEncryptedKey_cert_cmp +# define CMS_RecipientEncryptedKey_cert_cmp CMS_RecipEncryptedKey_cert_cmp +# undef CMS_RecipientInfo_kari_set0_pkey +# define CMS_RecipientInfo_kari_set0_pkey CMS_RecipInfo_kari_set0_pkey +# undef CMS_RecipientEncryptedKey_get0_id +# define CMS_RecipientEncryptedKey_get0_id CMS_RecipEncryptedKey_get0_id +# undef CMS_RecipientInfo_kari_orig_id_cmp +# define CMS_RecipientInfo_kari_orig_id_cmp CMS_RecipInfo_kari_orig_id_cmp + +/* Hack some long DTLS1 names */ +# undef dtls1_retransmit_buffered_messages +# define dtls1_retransmit_buffered_messages dtls1_retransmit_buffered_msgs + +/* Hack some long SRP names */ +# undef SRP_generate_server_master_secret +# define SRP_generate_server_master_secret SRP_gen_server_master_secret +# undef SRP_generate_client_master_secret +# define SRP_generate_client_master_secret SRP_gen_client_master_secret + +/* Hack some long UI names */ +# undef UI_method_get_prompt_constructor +# define UI_method_get_prompt_constructor UI_method_get_prompt_constructr +# undef UI_method_set_prompt_constructor +# define UI_method_set_prompt_constructor UI_method_set_prompt_constructr + +# endif /* defined OPENSSL_SYS_VMS */ + +/* Case insensitive linking causes problems.... */ +# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_OS2) +# undef ERR_load_CRYPTO_strings +# define ERR_load_CRYPTO_strings ERR_load_CRYPTOlib_strings +# undef OCSP_crlID_new +# define OCSP_crlID_new OCSP_crlID2_new + +# undef d2i_ECPARAMETERS +# define d2i_ECPARAMETERS d2i_UC_ECPARAMETERS +# undef i2d_ECPARAMETERS +# define i2d_ECPARAMETERS i2d_UC_ECPARAMETERS +# undef d2i_ECPKPARAMETERS +# define d2i_ECPKPARAMETERS d2i_UC_ECPKPARAMETERS +# undef i2d_ECPKPARAMETERS +# define i2d_ECPKPARAMETERS i2d_UC_ECPKPARAMETERS + +/* + * These functions do not seem to exist! However, I'm paranoid... Original + * command in x509v3.h: These functions are being redefined in another + * directory, and clash when the linker is case-insensitive, so let's hide + * them a little, by giving them an extra 'o' at the beginning of the name... + */ +# undef X509v3_cleanup_extensions +# define X509v3_cleanup_extensions oX509v3_cleanup_extensions +# undef X509v3_add_extension +# define X509v3_add_extension oX509v3_add_extension +# undef X509v3_add_netscape_extensions +# define X509v3_add_netscape_extensions oX509v3_add_netscape_extensions +# undef X509v3_add_standard_extensions +# define X509v3_add_standard_extensions oX509v3_add_standard_extensions + +/* This one clashes with CMS_data_create */ +# undef cms_Data_create +# define cms_Data_create priv_cms_Data_create + +# endif + +#endif /* ! defined HEADER_VMS_IDHACKS_H */ diff --git a/optee/optee_test/host/openssl/include/openssl/tls1.h b/optee/optee_test/host/openssl/include/openssl/tls1.h new file mode 100644 index 0000000..dd1d8c1 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/tls1.h @@ -0,0 +1,810 @@ +/* ssl/tls1.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef HEADER_TLS1_H +# define HEADER_TLS1_H + +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0 + +# define TLS1_VERSION 0x0301 +# define TLS1_1_VERSION 0x0302 +# define TLS1_2_VERSION 0x0303 +# define TLS_MAX_VERSION TLS1_2_VERSION + +# define TLS1_VERSION_MAJOR 0x03 +# define TLS1_VERSION_MINOR 0x01 + +# define TLS1_1_VERSION_MAJOR 0x03 +# define TLS1_1_VERSION_MINOR 0x02 + +# define TLS1_2_VERSION_MAJOR 0x03 +# define TLS1_2_VERSION_MINOR 0x03 + +# define TLS1_get_version(s) \ + ((s->version >> 8) == TLS1_VERSION_MAJOR ? s->version : 0) + +# define TLS1_get_client_version(s) \ + ((s->client_version >> 8) == TLS1_VERSION_MAJOR ? s->client_version : 0) + +# define TLS1_AD_DECRYPTION_FAILED 21 +# define TLS1_AD_RECORD_OVERFLOW 22 +# define TLS1_AD_UNKNOWN_CA 48/* fatal */ +# define TLS1_AD_ACCESS_DENIED 49/* fatal */ +# define TLS1_AD_DECODE_ERROR 50/* fatal */ +# define TLS1_AD_DECRYPT_ERROR 51 +# define TLS1_AD_EXPORT_RESTRICTION 60/* fatal */ +# define TLS1_AD_PROTOCOL_VERSION 70/* fatal */ +# define TLS1_AD_INSUFFICIENT_SECURITY 71/* fatal */ +# define TLS1_AD_INTERNAL_ERROR 80/* fatal */ +# define TLS1_AD_INAPPROPRIATE_FALLBACK 86/* fatal */ +# define TLS1_AD_USER_CANCELLED 90 +# define TLS1_AD_NO_RENEGOTIATION 100 +/* codes 110-114 are from RFC3546 */ +# define TLS1_AD_UNSUPPORTED_EXTENSION 110 +# define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111 +# define TLS1_AD_UNRECOGNIZED_NAME 112 +# define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113 +# define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114 +# define TLS1_AD_UNKNOWN_PSK_IDENTITY 115/* fatal */ + +/* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */ +# define TLSEXT_TYPE_server_name 0 +# define TLSEXT_TYPE_max_fragment_length 1 +# define TLSEXT_TYPE_client_certificate_url 2 +# define TLSEXT_TYPE_trusted_ca_keys 3 +# define TLSEXT_TYPE_truncated_hmac 4 +# define TLSEXT_TYPE_status_request 5 +/* ExtensionType values from RFC4681 */ +# define TLSEXT_TYPE_user_mapping 6 +/* ExtensionType values from RFC5878 */ +# define TLSEXT_TYPE_client_authz 7 +# define TLSEXT_TYPE_server_authz 8 +/* ExtensionType values from RFC6091 */ +# define TLSEXT_TYPE_cert_type 9 + +/* ExtensionType values from RFC4492 */ +# define TLSEXT_TYPE_elliptic_curves 10 +# define TLSEXT_TYPE_ec_point_formats 11 + +/* ExtensionType value from RFC5054 */ +# define TLSEXT_TYPE_srp 12 + +/* ExtensionType values from RFC5246 */ +# define TLSEXT_TYPE_signature_algorithms 13 + +/* ExtensionType value from RFC5764 */ +# define TLSEXT_TYPE_use_srtp 14 + +/* ExtensionType value from RFC5620 */ +# define TLSEXT_TYPE_heartbeat 15 + +/* ExtensionType value from RFC7301 */ +# define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +/* + * ExtensionType value for TLS padding extension. + * http://tools.ietf.org/html/draft-agl-tls-padding + */ +# define TLSEXT_TYPE_padding 21 + +/* ExtensionType value from RFC4507 */ +# define TLSEXT_TYPE_session_ticket 35 + +/* ExtensionType value from draft-rescorla-tls-opaque-prf-input-00.txt */ +# if 0 +/* + * will have to be provided externally for now , + * i.e. build with -DTLSEXT_TYPE_opaque_prf_input=38183 + * using whatever extension number you'd like to try + */ +# define TLSEXT_TYPE_opaque_prf_input ?? +# endif + +/* Temporary extension type */ +# define TLSEXT_TYPE_renegotiate 0xff01 + +# ifndef OPENSSL_NO_NEXTPROTONEG +/* This is not an IANA defined extension number */ +# define TLSEXT_TYPE_next_proto_neg 13172 +# endif + +/* NameType value from RFC3546 */ +# define TLSEXT_NAMETYPE_host_name 0 +/* status request value from RFC3546 */ +# define TLSEXT_STATUSTYPE_ocsp 1 + +/* ECPointFormat values from RFC4492 */ +# define TLSEXT_ECPOINTFORMAT_first 0 +# define TLSEXT_ECPOINTFORMAT_uncompressed 0 +# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1 +# define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2 +# define TLSEXT_ECPOINTFORMAT_last 2 + +/* Signature and hash algorithms from RFC5246 */ +# define TLSEXT_signature_anonymous 0 +# define TLSEXT_signature_rsa 1 +# define TLSEXT_signature_dsa 2 +# define TLSEXT_signature_ecdsa 3 + +/* Total number of different signature algorithms */ +# define TLSEXT_signature_num 4 + +# define TLSEXT_hash_none 0 +# define TLSEXT_hash_md5 1 +# define TLSEXT_hash_sha1 2 +# define TLSEXT_hash_sha224 3 +# define TLSEXT_hash_sha256 4 +# define TLSEXT_hash_sha384 5 +# define TLSEXT_hash_sha512 6 + +/* Total number of different digest algorithms */ + +# define TLSEXT_hash_num 7 + +/* Flag set for unrecognised algorithms */ +# define TLSEXT_nid_unknown 0x1000000 + +/* ECC curves */ + +# define TLSEXT_curve_P_256 23 +# define TLSEXT_curve_P_384 24 + +# ifndef OPENSSL_NO_TLSEXT + +# define TLSEXT_MAXLEN_host_name 255 + +const char *SSL_get_servername(const SSL *s, const int type); +int SSL_get_servername_type(const SSL *s); +/* + * SSL_export_keying_material exports a value derived from the master secret, + * as specified in RFC 5705. It writes |olen| bytes to |out| given a label and + * optional context. (Since a zero length context is allowed, the |use_context| + * flag controls whether a context is included.) It returns 1 on success and + * zero otherwise. + */ +int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, + const unsigned char *context, size_t contextlen, + int use_context); + +int SSL_get_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignandhash, + unsigned char *rsig, unsigned char *rhash); + +int SSL_get_shared_sigalgs(SSL *s, int idx, + int *psign, int *phash, int *psignandhash, + unsigned char *rsig, unsigned char *rhash); + +int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain); + +# define SSL_set_tlsext_host_name(s,name) \ +SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name) + +# define SSL_set_tlsext_debug_callback(ssl, cb) \ +SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb) + +# define SSL_set_tlsext_debug_arg(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg) + +# define SSL_set_tlsext_status_type(ssl, type) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL) + +# define SSL_get_tlsext_status_exts(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg) + +# define SSL_set_tlsext_status_exts(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg) + +# define SSL_get_tlsext_status_ids(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg) + +# define SSL_set_tlsext_status_ids(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg) + +# define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg) + +# define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg) + +# define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ +SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb) + +# define SSL_TLSEXT_ERR_OK 0 +# define SSL_TLSEXT_ERR_ALERT_WARNING 1 +# define SSL_TLSEXT_ERR_ALERT_FATAL 2 +# define SSL_TLSEXT_ERR_NOACK 3 + +# define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \ +SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg) + +# define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_GET_TLSEXT_TICKET_KEYS,(keylen),(keys)) +# define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_SET_TLSEXT_TICKET_KEYS,(keylen),(keys)) + +# define SSL_CTX_set_tlsext_status_cb(ssl, cb) \ +SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb) + +# define SSL_CTX_set_tlsext_status_arg(ssl, arg) \ +SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0, (void *)arg) + +# define SSL_set_tlsext_opaque_prf_input(s, src, len) \ +SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT, len, src) +# define SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb) \ +SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB, (void (*)(void))cb) +# define SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg) \ +SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG, 0, arg) + +# define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \ +SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) + +# ifndef OPENSSL_NO_HEARTBEATS +# define SSL_TLSEXT_HB_ENABLED 0x01 +# define SSL_TLSEXT_HB_DONT_SEND_REQUESTS 0x02 +# define SSL_TLSEXT_HB_DONT_RECV_REQUESTS 0x04 + +# define SSL_get_tlsext_heartbeat_pending(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING,0,NULL) +# define SSL_set_tlsext_heartbeat_no_requests(ssl, arg) \ + SSL_ctrl((ssl),SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS,arg,NULL) +# endif +# endif + +/* PSK ciphersuites from 4279 */ +# define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A +# define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008B +# define TLS1_CK_PSK_WITH_AES_128_CBC_SHA 0x0300008C +# define TLS1_CK_PSK_WITH_AES_256_CBC_SHA 0x0300008D + +/* + * Additional TLS ciphersuites from expired Internet Draft + * draft-ietf-tls-56-bit-ciphersuites-01.txt (available if + * TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see s3_lib.c). We + * actually treat them like SSL 3.0 ciphers, which we probably shouldn't. + * Note that the first two are actually not in the IDs. + */ +# define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5 0x03000060/* not in + * ID */ +# define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 0x03000061/* not in + * ID */ +# define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA 0x03000062 +# define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x03000063 +# define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA 0x03000064 +# define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA 0x03000065 +# define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066 + +/* AES ciphersuites from RFC3268 */ +# define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F +# define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030 +# define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031 +# define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032 +# define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033 +# define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034 + +# define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035 +# define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036 +# define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037 +# define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038 +# define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039 +# define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A + +/* TLS v1.2 ciphersuites */ +# define TLS1_CK_RSA_WITH_NULL_SHA256 0x0300003B +# define TLS1_CK_RSA_WITH_AES_128_SHA256 0x0300003C +# define TLS1_CK_RSA_WITH_AES_256_SHA256 0x0300003D +# define TLS1_CK_DH_DSS_WITH_AES_128_SHA256 0x0300003E +# define TLS1_CK_DH_RSA_WITH_AES_128_SHA256 0x0300003F +# define TLS1_CK_DHE_DSS_WITH_AES_128_SHA256 0x03000040 + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041 +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042 +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043 +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044 +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045 +# define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046 + +/* TLS v1.2 ciphersuites */ +# define TLS1_CK_DHE_RSA_WITH_AES_128_SHA256 0x03000067 +# define TLS1_CK_DH_DSS_WITH_AES_256_SHA256 0x03000068 +# define TLS1_CK_DH_RSA_WITH_AES_256_SHA256 0x03000069 +# define TLS1_CK_DHE_DSS_WITH_AES_256_SHA256 0x0300006A +# define TLS1_CK_DHE_RSA_WITH_AES_256_SHA256 0x0300006B +# define TLS1_CK_ADH_WITH_AES_128_SHA256 0x0300006C +# define TLS1_CK_ADH_WITH_AES_256_SHA256 0x0300006D + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084 +# define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085 +# define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086 +# define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087 +# define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088 +# define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089 + +/* SEED ciphersuites from RFC4162 */ +# define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096 +# define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097 +# define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098 +# define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099 +# define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A +# define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B + +/* TLS v1.2 GCM ciphersuites from RFC5288 */ +# define TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 0x0300009C +# define TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 0x0300009D +# define TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256 0x0300009E +# define TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384 0x0300009F +# define TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256 0x030000A0 +# define TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384 0x030000A1 +# define TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256 0x030000A2 +# define TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384 0x030000A3 +# define TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256 0x030000A4 +# define TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384 0x030000A5 +# define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256 0x030000A6 +# define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384 0x030000A7 + +/* + * ECC ciphersuites from draft-ietf-tls-ecc-12.txt with changes soon to be in + * draft 13 + */ +# define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001 +# define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002 +# define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005 + +# define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006 +# define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007 +# define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A + +# define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B +# define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C +# define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D +# define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E +# define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F + +# define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010 +# define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011 +# define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012 +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013 +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014 + +# define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015 +# define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016 +# define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017 +# define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018 +# define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019 + +/* SRP ciphersuites from RFC 5054 */ +# define TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0x0300C01A +# define TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0x0300C01B +# define TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0x0300C01C +# define TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA 0x0300C01D +# define TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0x0300C01E +# define TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0x0300C01F +# define TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA 0x0300C020 +# define TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0x0300C021 +# define TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0x0300C022 + +/* ECDH HMAC based ciphersuites from RFC5289 */ + +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256 0x0300C023 +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384 0x0300C024 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256 0x0300C025 +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384 0x0300C026 +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 0x0300C027 +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384 0x0300C028 +# define TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256 0x0300C029 +# define TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384 0x0300C02A + +/* ECDH GCM based ciphersuites from RFC5289 */ +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02B +# define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02C +# define TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02D +# define TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02E +# define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0x0300C02F +# define TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0x0300C030 +# define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031 +# define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032 + +/* + * XXX * Backward compatibility alert: + * Older versions of OpenSSL gave + * some DHE ciphers names with "EDH" + * instead of "DHE". Going forward, we + * should be using DHE + * everywhere, though we may indefinitely maintain + * aliases for users + * or configurations that used "EDH" + + */ +# define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 "EXP1024-RC4-MD5" +# define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 "EXP1024-RC2-CBC-MD5" +# define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DES-CBC-SHA" +# define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DHE-DSS-DES-CBC-SHA" +# define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA "EXP1024-RC4-SHA" +# define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA "EXP1024-DHE-DSS-RC4-SHA" +# define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA" + +/* AES ciphersuites from RFC3268 */ +# define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA" +# define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA" +# define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA" +# define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA" + +# define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA" +# define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA" +# define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA" +# define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA" + +/* ECC ciphersuites from RFC4492 */ +# define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA" + +# define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA" + +# define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA" + +# define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA" + +# define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA" +# define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA" +# define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA" +# define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA" +# define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA" + +/* PSK ciphersuites from RFC 4279 */ +# define TLS1_TXT_PSK_WITH_RC4_128_SHA "PSK-RC4-SHA" +# define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA "PSK-3DES-EDE-CBC-SHA" +# define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA "PSK-AES128-CBC-SHA" +# define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA "PSK-AES256-CBC-SHA" + +/* SRP ciphersuite from RFC 5054 */ +# define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA "SRP-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "SRP-RSA-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "SRP-DSS-3DES-EDE-CBC-SHA" +# define TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA "SRP-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "SRP-RSA-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "SRP-DSS-AES-128-CBC-SHA" +# define TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA "SRP-AES-256-CBC-SHA" +# define TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "SRP-RSA-AES-256-CBC-SHA" +# define TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "SRP-DSS-AES-256-CBC-SHA" + +/* Camellia ciphersuites from RFC4132 */ +# define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA" +# define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA" + +# define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA" +# define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA" +# define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA" +# define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA" +# define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA" +# define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA" + +/* SEED ciphersuites from RFC4162 */ +# define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA" +# define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA" +# define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA" +# define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA" +# define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA" +# define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA" + +/* TLS v1.2 ciphersuites */ +# define TLS1_TXT_RSA_WITH_NULL_SHA256 "NULL-SHA256" +# define TLS1_TXT_RSA_WITH_AES_128_SHA256 "AES128-SHA256" +# define TLS1_TXT_RSA_WITH_AES_256_SHA256 "AES256-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_128_SHA256 "DH-DSS-AES128-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_128_SHA256 "DH-RSA-AES128-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256 "DHE-DSS-AES128-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 "DHE-RSA-AES128-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_256_SHA256 "DH-DSS-AES256-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_256_SHA256 "DH-RSA-AES256-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256 "DHE-DSS-AES256-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 "DHE-RSA-AES256-SHA256" +# define TLS1_TXT_ADH_WITH_AES_128_SHA256 "ADH-AES128-SHA256" +# define TLS1_TXT_ADH_WITH_AES_256_SHA256 "ADH-AES256-SHA256" + +/* TLS v1.2 GCM ciphersuites from RFC5288 */ +# define TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256 "AES128-GCM-SHA256" +# define TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384 "AES256-GCM-SHA384" +# define TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 "DHE-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 "DHE-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256 "DH-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384 "DH-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256 "DHE-DSS-AES128-GCM-SHA256" +# define TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384 "DHE-DSS-AES256-GCM-SHA384" +# define TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256 "DH-DSS-AES128-GCM-SHA256" +# define TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384 "DH-DSS-AES256-GCM-SHA384" +# define TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256 "ADH-AES128-GCM-SHA256" +# define TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384 "ADH-AES256-GCM-SHA384" + +/* ECDH HMAC based ciphersuites from RFC5289 */ + +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256 "ECDHE-ECDSA-AES128-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384 "ECDHE-ECDSA-AES256-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_SHA256 "ECDH-ECDSA-AES128-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_SHA384 "ECDH-ECDSA-AES256-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 "ECDHE-RSA-AES128-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 "ECDHE-RSA-AES256-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256 "ECDH-RSA-AES128-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384 "ECDH-RSA-AES256-SHA384" + +/* ECDH GCM based ciphersuites from RFC5289 */ +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "ECDHE-ECDSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "ECDHE-ECDSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 "ECDH-ECDSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 "ECDH-ECDSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "ECDHE-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "ECDHE-RSA-AES256-GCM-SHA384" +# define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256" +# define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384" + +# define TLS_CT_RSA_SIGN 1 +# define TLS_CT_DSS_SIGN 2 +# define TLS_CT_RSA_FIXED_DH 3 +# define TLS_CT_DSS_FIXED_DH 4 +# define TLS_CT_ECDSA_SIGN 64 +# define TLS_CT_RSA_FIXED_ECDH 65 +# define TLS_CT_ECDSA_FIXED_ECDH 66 +# define TLS_CT_GOST94_SIGN 21 +# define TLS_CT_GOST01_SIGN 22 +/* + * when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see + * comment there) + */ +# define TLS_CT_NUMBER 9 + +# define TLS1_FINISH_MAC_LENGTH 12 + +# define TLS_MD_MAX_CONST_SIZE 20 +# define TLS_MD_CLIENT_FINISH_CONST "client finished" +# define TLS_MD_CLIENT_FINISH_CONST_SIZE 15 +# define TLS_MD_SERVER_FINISH_CONST "server finished" +# define TLS_MD_SERVER_FINISH_CONST_SIZE 15 +# define TLS_MD_SERVER_WRITE_KEY_CONST "server write key" +# define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16 +# define TLS_MD_KEY_EXPANSION_CONST "key expansion" +# define TLS_MD_KEY_EXPANSION_CONST_SIZE 13 +# define TLS_MD_CLIENT_WRITE_KEY_CONST "client write key" +# define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE 16 +# define TLS_MD_SERVER_WRITE_KEY_CONST "server write key" +# define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16 +# define TLS_MD_IV_BLOCK_CONST "IV block" +# define TLS_MD_IV_BLOCK_CONST_SIZE 8 +# define TLS_MD_MASTER_SECRET_CONST "master secret" +# define TLS_MD_MASTER_SECRET_CONST_SIZE 13 + +# ifdef CHARSET_EBCDIC +# undef TLS_MD_CLIENT_FINISH_CONST +/* + * client finished + */ +# define TLS_MD_CLIENT_FINISH_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x66\x69\x6e\x69\x73\x68\x65\x64" + +# undef TLS_MD_SERVER_FINISH_CONST +/* + * server finished + */ +# define TLS_MD_SERVER_FINISH_CONST "\x73\x65\x72\x76\x65\x72\x20\x66\x69\x6e\x69\x73\x68\x65\x64" + +# undef TLS_MD_SERVER_WRITE_KEY_CONST +/* + * server write key + */ +# define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_KEY_EXPANSION_CONST +/* + * key expansion + */ +# define TLS_MD_KEY_EXPANSION_CONST "\x6b\x65\x79\x20\x65\x78\x70\x61\x6e\x73\x69\x6f\x6e" + +# undef TLS_MD_CLIENT_WRITE_KEY_CONST +/* + * client write key + */ +# define TLS_MD_CLIENT_WRITE_KEY_CONST "\x63\x6c\x69\x65\x6e\x74\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_SERVER_WRITE_KEY_CONST +/* + * server write key + */ +# define TLS_MD_SERVER_WRITE_KEY_CONST "\x73\x65\x72\x76\x65\x72\x20\x77\x72\x69\x74\x65\x20\x6b\x65\x79" + +# undef TLS_MD_IV_BLOCK_CONST +/* + * IV block + */ +# define TLS_MD_IV_BLOCK_CONST "\x49\x56\x20\x62\x6c\x6f\x63\x6b" + +# undef TLS_MD_MASTER_SECRET_CONST +/* + * master secret + */ +# define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" +# endif + +/* TLS Session Ticket extension struct */ +struct tls_session_ticket_ext_st { + unsigned short length; + void *data; +}; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ts.h b/optee/optee_test/host/openssl/include/openssl/ts.h new file mode 100644 index 0000000..2daa1b2 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ts.h @@ -0,0 +1,865 @@ +/* crypto/ts/ts.h */ +/* + * Written by Zoltan Glozik (zglozik@opentsa.org) for the OpenSSL project + * 2002, 2003, 2004. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_TS_H +# define HEADER_TS_H + +# include +# include +# ifndef OPENSSL_NO_BUFFER +# include +# endif +# ifndef OPENSSL_NO_EVP +# include +# endif +# ifndef OPENSSL_NO_BIO +# include +# endif +# include +# include +# include + +# ifndef OPENSSL_NO_RSA +# include +# endif + +# ifndef OPENSSL_NO_DSA +# include +# endif + +# ifndef OPENSSL_NO_DH +# include +# endif + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef WIN32 +/* Under Win32 this is defined in wincrypt.h */ +# undef X509_NAME +# endif + +# include +# include + +/*- +MessageImprint ::= SEQUENCE { + hashAlgorithm AlgorithmIdentifier, + hashedMessage OCTET STRING } +*/ + +typedef struct TS_msg_imprint_st { + X509_ALGOR *hash_algo; + ASN1_OCTET_STRING *hashed_msg; +} TS_MSG_IMPRINT; + +/*- +TimeStampReq ::= SEQUENCE { + version INTEGER { v1(1) }, + messageImprint MessageImprint, + --a hash algorithm OID and the hash value of the data to be + --time-stamped + reqPolicy TSAPolicyId OPTIONAL, + nonce INTEGER OPTIONAL, + certReq BOOLEAN DEFAULT FALSE, + extensions [0] IMPLICIT Extensions OPTIONAL } +*/ + +typedef struct TS_req_st { + ASN1_INTEGER *version; + TS_MSG_IMPRINT *msg_imprint; + ASN1_OBJECT *policy_id; /* OPTIONAL */ + ASN1_INTEGER *nonce; /* OPTIONAL */ + ASN1_BOOLEAN cert_req; /* DEFAULT FALSE */ + STACK_OF(X509_EXTENSION) *extensions; /* [0] OPTIONAL */ +} TS_REQ; + +/*- +Accuracy ::= SEQUENCE { + seconds INTEGER OPTIONAL, + millis [0] INTEGER (1..999) OPTIONAL, + micros [1] INTEGER (1..999) OPTIONAL } +*/ + +typedef struct TS_accuracy_st { + ASN1_INTEGER *seconds; + ASN1_INTEGER *millis; + ASN1_INTEGER *micros; +} TS_ACCURACY; + +/*- +TSTInfo ::= SEQUENCE { + version INTEGER { v1(1) }, + policy TSAPolicyId, + messageImprint MessageImprint, + -- MUST have the same value as the similar field in + -- TimeStampReq + serialNumber INTEGER, + -- Time-Stamping users MUST be ready to accommodate integers + -- up to 160 bits. + genTime GeneralizedTime, + accuracy Accuracy OPTIONAL, + ordering BOOLEAN DEFAULT FALSE, + nonce INTEGER OPTIONAL, + -- MUST be present if the similar field was present + -- in TimeStampReq. In that case it MUST have the same value. + tsa [0] GeneralName OPTIONAL, + extensions [1] IMPLICIT Extensions OPTIONAL } +*/ + +typedef struct TS_tst_info_st { + ASN1_INTEGER *version; + ASN1_OBJECT *policy_id; + TS_MSG_IMPRINT *msg_imprint; + ASN1_INTEGER *serial; + ASN1_GENERALIZEDTIME *time; + TS_ACCURACY *accuracy; + ASN1_BOOLEAN ordering; + ASN1_INTEGER *nonce; + GENERAL_NAME *tsa; + STACK_OF(X509_EXTENSION) *extensions; +} TS_TST_INFO; + +/*- +PKIStatusInfo ::= SEQUENCE { + status PKIStatus, + statusString PKIFreeText OPTIONAL, + failInfo PKIFailureInfo OPTIONAL } + +From RFC 1510 - section 3.1.1: +PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String + -- text encoded as UTF-8 String (note: each UTF8String SHOULD + -- include an RFC 1766 language tag to indicate the language + -- of the contained text) +*/ + +/* Possible values for status. See ts_resp_print.c && ts_resp_verify.c. */ + +# define TS_STATUS_GRANTED 0 +# define TS_STATUS_GRANTED_WITH_MODS 1 +# define TS_STATUS_REJECTION 2 +# define TS_STATUS_WAITING 3 +# define TS_STATUS_REVOCATION_WARNING 4 +# define TS_STATUS_REVOCATION_NOTIFICATION 5 + +/* + * Possible values for failure_info. See ts_resp_print.c && ts_resp_verify.c + */ + +# define TS_INFO_BAD_ALG 0 +# define TS_INFO_BAD_REQUEST 2 +# define TS_INFO_BAD_DATA_FORMAT 5 +# define TS_INFO_TIME_NOT_AVAILABLE 14 +# define TS_INFO_UNACCEPTED_POLICY 15 +# define TS_INFO_UNACCEPTED_EXTENSION 16 +# define TS_INFO_ADD_INFO_NOT_AVAILABLE 17 +# define TS_INFO_SYSTEM_FAILURE 25 + +typedef struct TS_status_info_st { + ASN1_INTEGER *status; + STACK_OF(ASN1_UTF8STRING) *text; + ASN1_BIT_STRING *failure_info; +} TS_STATUS_INFO; + +DECLARE_STACK_OF(ASN1_UTF8STRING) +DECLARE_ASN1_SET_OF(ASN1_UTF8STRING) + +/*- +TimeStampResp ::= SEQUENCE { + status PKIStatusInfo, + timeStampToken TimeStampToken OPTIONAL } +*/ + +typedef struct TS_resp_st { + TS_STATUS_INFO *status_info; + PKCS7 *token; + TS_TST_INFO *tst_info; +} TS_RESP; + +/* The structure below would belong to the ESS component. */ + +/*- +IssuerSerial ::= SEQUENCE { + issuer GeneralNames, + serialNumber CertificateSerialNumber + } +*/ + +typedef struct ESS_issuer_serial { + STACK_OF(GENERAL_NAME) *issuer; + ASN1_INTEGER *serial; +} ESS_ISSUER_SERIAL; + +/*- +ESSCertID ::= SEQUENCE { + certHash Hash, + issuerSerial IssuerSerial OPTIONAL +} +*/ + +typedef struct ESS_cert_id { + ASN1_OCTET_STRING *hash; /* Always SHA-1 digest. */ + ESS_ISSUER_SERIAL *issuer_serial; +} ESS_CERT_ID; + +DECLARE_STACK_OF(ESS_CERT_ID) +DECLARE_ASN1_SET_OF(ESS_CERT_ID) + +/*- +SigningCertificate ::= SEQUENCE { + certs SEQUENCE OF ESSCertID, + policies SEQUENCE OF PolicyInformation OPTIONAL +} +*/ + +typedef struct ESS_signing_cert { + STACK_OF(ESS_CERT_ID) *cert_ids; + STACK_OF(POLICYINFO) *policy_info; +} ESS_SIGNING_CERT; + +TS_REQ *TS_REQ_new(void); +void TS_REQ_free(TS_REQ *a); +int i2d_TS_REQ(const TS_REQ *a, unsigned char **pp); +TS_REQ *d2i_TS_REQ(TS_REQ **a, const unsigned char **pp, long length); + +TS_REQ *TS_REQ_dup(TS_REQ *a); + +TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a); +int i2d_TS_REQ_fp(FILE *fp, TS_REQ *a); +TS_REQ *d2i_TS_REQ_bio(BIO *fp, TS_REQ **a); +int i2d_TS_REQ_bio(BIO *fp, TS_REQ *a); + +TS_MSG_IMPRINT *TS_MSG_IMPRINT_new(void); +void TS_MSG_IMPRINT_free(TS_MSG_IMPRINT *a); +int i2d_TS_MSG_IMPRINT(const TS_MSG_IMPRINT *a, unsigned char **pp); +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT(TS_MSG_IMPRINT **a, + const unsigned char **pp, long length); + +TS_MSG_IMPRINT *TS_MSG_IMPRINT_dup(TS_MSG_IMPRINT *a); + +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a); +int i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a); +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *fp, TS_MSG_IMPRINT **a); +int i2d_TS_MSG_IMPRINT_bio(BIO *fp, TS_MSG_IMPRINT *a); + +TS_RESP *TS_RESP_new(void); +void TS_RESP_free(TS_RESP *a); +int i2d_TS_RESP(const TS_RESP *a, unsigned char **pp); +TS_RESP *d2i_TS_RESP(TS_RESP **a, const unsigned char **pp, long length); +TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token); +TS_RESP *TS_RESP_dup(TS_RESP *a); + +TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a); +int i2d_TS_RESP_fp(FILE *fp, TS_RESP *a); +TS_RESP *d2i_TS_RESP_bio(BIO *fp, TS_RESP **a); +int i2d_TS_RESP_bio(BIO *fp, TS_RESP *a); + +TS_STATUS_INFO *TS_STATUS_INFO_new(void); +void TS_STATUS_INFO_free(TS_STATUS_INFO *a); +int i2d_TS_STATUS_INFO(const TS_STATUS_INFO *a, unsigned char **pp); +TS_STATUS_INFO *d2i_TS_STATUS_INFO(TS_STATUS_INFO **a, + const unsigned char **pp, long length); +TS_STATUS_INFO *TS_STATUS_INFO_dup(TS_STATUS_INFO *a); + +TS_TST_INFO *TS_TST_INFO_new(void); +void TS_TST_INFO_free(TS_TST_INFO *a); +int i2d_TS_TST_INFO(const TS_TST_INFO *a, unsigned char **pp); +TS_TST_INFO *d2i_TS_TST_INFO(TS_TST_INFO **a, const unsigned char **pp, + long length); +TS_TST_INFO *TS_TST_INFO_dup(TS_TST_INFO *a); + +TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a); +int i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a); +TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *fp, TS_TST_INFO **a); +int i2d_TS_TST_INFO_bio(BIO *fp, TS_TST_INFO *a); + +TS_ACCURACY *TS_ACCURACY_new(void); +void TS_ACCURACY_free(TS_ACCURACY *a); +int i2d_TS_ACCURACY(const TS_ACCURACY *a, unsigned char **pp); +TS_ACCURACY *d2i_TS_ACCURACY(TS_ACCURACY **a, const unsigned char **pp, + long length); +TS_ACCURACY *TS_ACCURACY_dup(TS_ACCURACY *a); + +ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_new(void); +void ESS_ISSUER_SERIAL_free(ESS_ISSUER_SERIAL *a); +int i2d_ESS_ISSUER_SERIAL(const ESS_ISSUER_SERIAL *a, unsigned char **pp); +ESS_ISSUER_SERIAL *d2i_ESS_ISSUER_SERIAL(ESS_ISSUER_SERIAL **a, + const unsigned char **pp, + long length); +ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_dup(ESS_ISSUER_SERIAL *a); + +ESS_CERT_ID *ESS_CERT_ID_new(void); +void ESS_CERT_ID_free(ESS_CERT_ID *a); +int i2d_ESS_CERT_ID(const ESS_CERT_ID *a, unsigned char **pp); +ESS_CERT_ID *d2i_ESS_CERT_ID(ESS_CERT_ID **a, const unsigned char **pp, + long length); +ESS_CERT_ID *ESS_CERT_ID_dup(ESS_CERT_ID *a); + +ESS_SIGNING_CERT *ESS_SIGNING_CERT_new(void); +void ESS_SIGNING_CERT_free(ESS_SIGNING_CERT *a); +int i2d_ESS_SIGNING_CERT(const ESS_SIGNING_CERT *a, unsigned char **pp); +ESS_SIGNING_CERT *d2i_ESS_SIGNING_CERT(ESS_SIGNING_CERT **a, + const unsigned char **pp, long length); +ESS_SIGNING_CERT *ESS_SIGNING_CERT_dup(ESS_SIGNING_CERT *a); + +void ERR_load_TS_strings(void); + +int TS_REQ_set_version(TS_REQ *a, long version); +long TS_REQ_get_version(const TS_REQ *a); + +int TS_REQ_set_msg_imprint(TS_REQ *a, TS_MSG_IMPRINT *msg_imprint); +TS_MSG_IMPRINT *TS_REQ_get_msg_imprint(TS_REQ *a); + +int TS_MSG_IMPRINT_set_algo(TS_MSG_IMPRINT *a, X509_ALGOR *alg); +X509_ALGOR *TS_MSG_IMPRINT_get_algo(TS_MSG_IMPRINT *a); + +int TS_MSG_IMPRINT_set_msg(TS_MSG_IMPRINT *a, unsigned char *d, int len); +ASN1_OCTET_STRING *TS_MSG_IMPRINT_get_msg(TS_MSG_IMPRINT *a); + +int TS_REQ_set_policy_id(TS_REQ *a, ASN1_OBJECT *policy); +ASN1_OBJECT *TS_REQ_get_policy_id(TS_REQ *a); + +int TS_REQ_set_nonce(TS_REQ *a, const ASN1_INTEGER *nonce); +const ASN1_INTEGER *TS_REQ_get_nonce(const TS_REQ *a); + +int TS_REQ_set_cert_req(TS_REQ *a, int cert_req); +int TS_REQ_get_cert_req(const TS_REQ *a); + +STACK_OF(X509_EXTENSION) *TS_REQ_get_exts(TS_REQ *a); +void TS_REQ_ext_free(TS_REQ *a); +int TS_REQ_get_ext_count(TS_REQ *a); +int TS_REQ_get_ext_by_NID(TS_REQ *a, int nid, int lastpos); +int TS_REQ_get_ext_by_OBJ(TS_REQ *a, ASN1_OBJECT *obj, int lastpos); +int TS_REQ_get_ext_by_critical(TS_REQ *a, int crit, int lastpos); +X509_EXTENSION *TS_REQ_get_ext(TS_REQ *a, int loc); +X509_EXTENSION *TS_REQ_delete_ext(TS_REQ *a, int loc); +int TS_REQ_add_ext(TS_REQ *a, X509_EXTENSION *ex, int loc); +void *TS_REQ_get_ext_d2i(TS_REQ *a, int nid, int *crit, int *idx); + +/* Function declarations for TS_REQ defined in ts/ts_req_print.c */ + +int TS_REQ_print_bio(BIO *bio, TS_REQ *a); + +/* Function declarations for TS_RESP defined in ts/ts_resp_utils.c */ + +int TS_RESP_set_status_info(TS_RESP *a, TS_STATUS_INFO *info); +TS_STATUS_INFO *TS_RESP_get_status_info(TS_RESP *a); + +/* Caller loses ownership of PKCS7 and TS_TST_INFO objects. */ +void TS_RESP_set_tst_info(TS_RESP *a, PKCS7 *p7, TS_TST_INFO *tst_info); +PKCS7 *TS_RESP_get_token(TS_RESP *a); +TS_TST_INFO *TS_RESP_get_tst_info(TS_RESP *a); + +int TS_TST_INFO_set_version(TS_TST_INFO *a, long version); +long TS_TST_INFO_get_version(const TS_TST_INFO *a); + +int TS_TST_INFO_set_policy_id(TS_TST_INFO *a, ASN1_OBJECT *policy_id); +ASN1_OBJECT *TS_TST_INFO_get_policy_id(TS_TST_INFO *a); + +int TS_TST_INFO_set_msg_imprint(TS_TST_INFO *a, TS_MSG_IMPRINT *msg_imprint); +TS_MSG_IMPRINT *TS_TST_INFO_get_msg_imprint(TS_TST_INFO *a); + +int TS_TST_INFO_set_serial(TS_TST_INFO *a, const ASN1_INTEGER *serial); +const ASN1_INTEGER *TS_TST_INFO_get_serial(const TS_TST_INFO *a); + +int TS_TST_INFO_set_time(TS_TST_INFO *a, const ASN1_GENERALIZEDTIME *gtime); +const ASN1_GENERALIZEDTIME *TS_TST_INFO_get_time(const TS_TST_INFO *a); + +int TS_TST_INFO_set_accuracy(TS_TST_INFO *a, TS_ACCURACY *accuracy); +TS_ACCURACY *TS_TST_INFO_get_accuracy(TS_TST_INFO *a); + +int TS_ACCURACY_set_seconds(TS_ACCURACY *a, const ASN1_INTEGER *seconds); +const ASN1_INTEGER *TS_ACCURACY_get_seconds(const TS_ACCURACY *a); + +int TS_ACCURACY_set_millis(TS_ACCURACY *a, const ASN1_INTEGER *millis); +const ASN1_INTEGER *TS_ACCURACY_get_millis(const TS_ACCURACY *a); + +int TS_ACCURACY_set_micros(TS_ACCURACY *a, const ASN1_INTEGER *micros); +const ASN1_INTEGER *TS_ACCURACY_get_micros(const TS_ACCURACY *a); + +int TS_TST_INFO_set_ordering(TS_TST_INFO *a, int ordering); +int TS_TST_INFO_get_ordering(const TS_TST_INFO *a); + +int TS_TST_INFO_set_nonce(TS_TST_INFO *a, const ASN1_INTEGER *nonce); +const ASN1_INTEGER *TS_TST_INFO_get_nonce(const TS_TST_INFO *a); + +int TS_TST_INFO_set_tsa(TS_TST_INFO *a, GENERAL_NAME *tsa); +GENERAL_NAME *TS_TST_INFO_get_tsa(TS_TST_INFO *a); + +STACK_OF(X509_EXTENSION) *TS_TST_INFO_get_exts(TS_TST_INFO *a); +void TS_TST_INFO_ext_free(TS_TST_INFO *a); +int TS_TST_INFO_get_ext_count(TS_TST_INFO *a); +int TS_TST_INFO_get_ext_by_NID(TS_TST_INFO *a, int nid, int lastpos); +int TS_TST_INFO_get_ext_by_OBJ(TS_TST_INFO *a, ASN1_OBJECT *obj, int lastpos); +int TS_TST_INFO_get_ext_by_critical(TS_TST_INFO *a, int crit, int lastpos); +X509_EXTENSION *TS_TST_INFO_get_ext(TS_TST_INFO *a, int loc); +X509_EXTENSION *TS_TST_INFO_delete_ext(TS_TST_INFO *a, int loc); +int TS_TST_INFO_add_ext(TS_TST_INFO *a, X509_EXTENSION *ex, int loc); +void *TS_TST_INFO_get_ext_d2i(TS_TST_INFO *a, int nid, int *crit, int *idx); + +/* + * Declarations related to response generation, defined in ts/ts_resp_sign.c. + */ + +/* Optional flags for response generation. */ + +/* Don't include the TSA name in response. */ +# define TS_TSA_NAME 0x01 + +/* Set ordering to true in response. */ +# define TS_ORDERING 0x02 + +/* + * Include the signer certificate and the other specified certificates in + * the ESS signing certificate attribute beside the PKCS7 signed data. + * Only the signer certificates is included by default. + */ +# define TS_ESS_CERT_ID_CHAIN 0x04 + +/* Forward declaration. */ +struct TS_resp_ctx; + +/* This must return a unique number less than 160 bits long. */ +typedef ASN1_INTEGER *(*TS_serial_cb) (struct TS_resp_ctx *, void *); + +/* + * This must return the seconds and microseconds since Jan 1, 1970 in the sec + * and usec variables allocated by the caller. Return non-zero for success + * and zero for failure. + */ +typedef int (*TS_time_cb) (struct TS_resp_ctx *, void *, long *sec, + long *usec); + +/* + * This must process the given extension. It can modify the TS_TST_INFO + * object of the context. Return values: !0 (processed), 0 (error, it must + * set the status info/failure info of the response). + */ +typedef int (*TS_extension_cb) (struct TS_resp_ctx *, X509_EXTENSION *, + void *); + +typedef struct TS_resp_ctx { + X509 *signer_cert; + EVP_PKEY *signer_key; + STACK_OF(X509) *certs; /* Certs to include in signed data. */ + STACK_OF(ASN1_OBJECT) *policies; /* Acceptable policies. */ + ASN1_OBJECT *default_policy; /* It may appear in policies, too. */ + STACK_OF(EVP_MD) *mds; /* Acceptable message digests. */ + ASN1_INTEGER *seconds; /* accuracy, 0 means not specified. */ + ASN1_INTEGER *millis; /* accuracy, 0 means not specified. */ + ASN1_INTEGER *micros; /* accuracy, 0 means not specified. */ + unsigned clock_precision_digits; /* fraction of seconds in time stamp + * token. */ + unsigned flags; /* Optional info, see values above. */ + /* Callback functions. */ + TS_serial_cb serial_cb; + void *serial_cb_data; /* User data for serial_cb. */ + TS_time_cb time_cb; + void *time_cb_data; /* User data for time_cb. */ + TS_extension_cb extension_cb; + void *extension_cb_data; /* User data for extension_cb. */ + /* These members are used only while creating the response. */ + TS_REQ *request; + TS_RESP *response; + TS_TST_INFO *tst_info; +} TS_RESP_CTX; + +DECLARE_STACK_OF(EVP_MD) +DECLARE_ASN1_SET_OF(EVP_MD) + +/* Creates a response context that can be used for generating responses. */ +TS_RESP_CTX *TS_RESP_CTX_new(void); +void TS_RESP_CTX_free(TS_RESP_CTX *ctx); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, ASN1_OBJECT *def_policy); + +/* No additional certs are included in the response by default. */ +int TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs); + +/* + * Adds a new acceptable policy, only the default policy is accepted by + * default. + */ +int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, ASN1_OBJECT *policy); + +/* + * Adds a new acceptable message digest. Note that no message digests are + * accepted by default. The md argument is shared with the caller. + */ +int TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md); + +/* Accuracy is not included by default. */ +int TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx, + int secs, int millis, int micros); + +/* + * Clock precision digits, i.e. the number of decimal digits: '0' means sec, + * '3' msec, '6' usec, and so on. Default is 0. + */ +int TS_RESP_CTX_set_clock_precision_digits(TS_RESP_CTX *ctx, + unsigned clock_precision_digits); +/* At most we accept usec precision. */ +# define TS_MAX_CLOCK_PRECISION_DIGITS 6 + +/* Maximum status message length */ +# define TS_MAX_STATUS_LENGTH (1024 * 1024) + +/* No flags are set by default. */ +void TS_RESP_CTX_add_flags(TS_RESP_CTX *ctx, int flags); + +/* Default callback always returns a constant. */ +void TS_RESP_CTX_set_serial_cb(TS_RESP_CTX *ctx, TS_serial_cb cb, void *data); + +/* Default callback uses the gettimeofday() and gmtime() system calls. */ +void TS_RESP_CTX_set_time_cb(TS_RESP_CTX *ctx, TS_time_cb cb, void *data); + +/* + * Default callback rejects all extensions. The extension callback is called + * when the TS_TST_INFO object is already set up and not signed yet. + */ +/* FIXME: extension handling is not tested yet. */ +void TS_RESP_CTX_set_extension_cb(TS_RESP_CTX *ctx, + TS_extension_cb cb, void *data); + +/* The following methods can be used in the callbacks. */ +int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx, + int status, const char *text); + +/* Sets the status info only if it is still TS_STATUS_GRANTED. */ +int TS_RESP_CTX_set_status_info_cond(TS_RESP_CTX *ctx, + int status, const char *text); + +int TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure); + +/* The get methods below can be used in the extension callback. */ +TS_REQ *TS_RESP_CTX_get_request(TS_RESP_CTX *ctx); + +TS_TST_INFO *TS_RESP_CTX_get_tst_info(TS_RESP_CTX *ctx); + +/* + * Creates the signed TS_TST_INFO and puts it in TS_RESP. + * In case of errors it sets the status info properly. + * Returns NULL only in case of memory allocation/fatal error. + */ +TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio); + +/* + * Declarations related to response verification, + * they are defined in ts/ts_resp_verify.c. + */ + +int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, + X509_STORE *store, X509 **signer_out); + +/* Context structure for the generic verify method. */ + +/* Verify the signer's certificate and the signature of the response. */ +# define TS_VFY_SIGNATURE (1u << 0) +/* Verify the version number of the response. */ +# define TS_VFY_VERSION (1u << 1) +/* Verify if the policy supplied by the user matches the policy of the TSA. */ +# define TS_VFY_POLICY (1u << 2) +/* + * Verify the message imprint provided by the user. This flag should not be + * specified with TS_VFY_DATA. + */ +# define TS_VFY_IMPRINT (1u << 3) +/* + * Verify the message imprint computed by the verify method from the user + * provided data and the MD algorithm of the response. This flag should not + * be specified with TS_VFY_IMPRINT. + */ +# define TS_VFY_DATA (1u << 4) +/* Verify the nonce value. */ +# define TS_VFY_NONCE (1u << 5) +/* Verify if the TSA name field matches the signer certificate. */ +# define TS_VFY_SIGNER (1u << 6) +/* Verify if the TSA name field equals to the user provided name. */ +# define TS_VFY_TSA_NAME (1u << 7) + +/* You can use the following convenience constants. */ +# define TS_VFY_ALL_IMPRINT (TS_VFY_SIGNATURE \ + | TS_VFY_VERSION \ + | TS_VFY_POLICY \ + | TS_VFY_IMPRINT \ + | TS_VFY_NONCE \ + | TS_VFY_SIGNER \ + | TS_VFY_TSA_NAME) +# define TS_VFY_ALL_DATA (TS_VFY_SIGNATURE \ + | TS_VFY_VERSION \ + | TS_VFY_POLICY \ + | TS_VFY_DATA \ + | TS_VFY_NONCE \ + | TS_VFY_SIGNER \ + | TS_VFY_TSA_NAME) + +typedef struct TS_verify_ctx { + /* Set this to the union of TS_VFY_... flags you want to carry out. */ + unsigned flags; + /* Must be set only with TS_VFY_SIGNATURE. certs is optional. */ + X509_STORE *store; + STACK_OF(X509) *certs; + /* Must be set only with TS_VFY_POLICY. */ + ASN1_OBJECT *policy; + /* + * Must be set only with TS_VFY_IMPRINT. If md_alg is NULL, the + * algorithm from the response is used. + */ + X509_ALGOR *md_alg; + unsigned char *imprint; + unsigned imprint_len; + /* Must be set only with TS_VFY_DATA. */ + BIO *data; + /* Must be set only with TS_VFY_TSA_NAME. */ + ASN1_INTEGER *nonce; + /* Must be set only with TS_VFY_TSA_NAME. */ + GENERAL_NAME *tsa_name; +} TS_VERIFY_CTX; + +int TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response); +int TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token); + +/* + * Declarations related to response verification context, + * they are defined in ts/ts_verify_ctx.c. + */ + +/* Set all fields to zero. */ +TS_VERIFY_CTX *TS_VERIFY_CTX_new(void); +void TS_VERIFY_CTX_init(TS_VERIFY_CTX *ctx); +void TS_VERIFY_CTX_free(TS_VERIFY_CTX *ctx); +void TS_VERIFY_CTX_cleanup(TS_VERIFY_CTX *ctx); + +/*- + * If ctx is NULL, it allocates and returns a new object, otherwise + * it returns ctx. It initialises all the members as follows: + * flags = TS_VFY_ALL_IMPRINT & ~(TS_VFY_TSA_NAME | TS_VFY_SIGNATURE) + * certs = NULL + * store = NULL + * policy = policy from the request or NULL if absent (in this case + * TS_VFY_POLICY is cleared from flags as well) + * md_alg = MD algorithm from request + * imprint, imprint_len = imprint from request + * data = NULL + * nonce, nonce_len = nonce from the request or NULL if absent (in this case + * TS_VFY_NONCE is cleared from flags as well) + * tsa_name = NULL + * Important: after calling this method TS_VFY_SIGNATURE should be added! + */ +TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx); + +/* Function declarations for TS_RESP defined in ts/ts_resp_print.c */ + +int TS_RESP_print_bio(BIO *bio, TS_RESP *a); +int TS_STATUS_INFO_print_bio(BIO *bio, TS_STATUS_INFO *a); +int TS_TST_INFO_print_bio(BIO *bio, TS_TST_INFO *a); + +/* Common utility functions defined in ts/ts_lib.c */ + +int TS_ASN1_INTEGER_print_bio(BIO *bio, const ASN1_INTEGER *num); +int TS_OBJ_print_bio(BIO *bio, const ASN1_OBJECT *obj); +int TS_ext_print_bio(BIO *bio, const STACK_OF(X509_EXTENSION) *extensions); +int TS_X509_ALGOR_print_bio(BIO *bio, const X509_ALGOR *alg); +int TS_MSG_IMPRINT_print_bio(BIO *bio, TS_MSG_IMPRINT *msg); + +/* + * Function declarations for handling configuration options, defined in + * ts/ts_conf.c + */ + +X509 *TS_CONF_load_cert(const char *file); +STACK_OF(X509) *TS_CONF_load_certs(const char *file); +EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass); +const char *TS_CONF_get_tsa_section(CONF *conf, const char *section); +int TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb, + TS_RESP_CTX *ctx); +int TS_CONF_set_crypto_device(CONF *conf, const char *section, + const char *device); +int TS_CONF_set_default_engine(const char *name); +int TS_CONF_set_signer_cert(CONF *conf, const char *section, + const char *cert, TS_RESP_CTX *ctx); +int TS_CONF_set_certs(CONF *conf, const char *section, const char *certs, + TS_RESP_CTX *ctx); +int TS_CONF_set_signer_key(CONF *conf, const char *section, + const char *key, const char *pass, + TS_RESP_CTX *ctx); +int TS_CONF_set_def_policy(CONF *conf, const char *section, + const char *policy, TS_RESP_CTX *ctx); +int TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section, + TS_RESP_CTX *ctx); +int TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, + TS_RESP_CTX *ctx); + +/* -------------------------------------------------- */ +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_TS_strings(void); + +/* Error codes for the TS functions. */ + +/* Function codes. */ +# define TS_F_D2I_TS_RESP 147 +# define TS_F_DEF_SERIAL_CB 110 +# define TS_F_DEF_TIME_CB 111 +# define TS_F_ESS_ADD_SIGNING_CERT 112 +# define TS_F_ESS_CERT_ID_NEW_INIT 113 +# define TS_F_ESS_SIGNING_CERT_NEW_INIT 114 +# define TS_F_INT_TS_RESP_VERIFY_TOKEN 149 +# define TS_F_PKCS7_TO_TS_TST_INFO 148 +# define TS_F_TS_ACCURACY_SET_MICROS 115 +# define TS_F_TS_ACCURACY_SET_MILLIS 116 +# define TS_F_TS_ACCURACY_SET_SECONDS 117 +# define TS_F_TS_CHECK_IMPRINTS 100 +# define TS_F_TS_CHECK_NONCES 101 +# define TS_F_TS_CHECK_POLICY 102 +# define TS_F_TS_CHECK_SIGNING_CERTS 103 +# define TS_F_TS_CHECK_STATUS_INFO 104 +# define TS_F_TS_COMPUTE_IMPRINT 145 +# define TS_F_TS_CONF_SET_DEFAULT_ENGINE 146 +# define TS_F_TS_GET_STATUS_TEXT 105 +# define TS_F_TS_MSG_IMPRINT_SET_ALGO 118 +# define TS_F_TS_REQ_SET_MSG_IMPRINT 119 +# define TS_F_TS_REQ_SET_NONCE 120 +# define TS_F_TS_REQ_SET_POLICY_ID 121 +# define TS_F_TS_RESP_CREATE_RESPONSE 122 +# define TS_F_TS_RESP_CREATE_TST_INFO 123 +# define TS_F_TS_RESP_CTX_ADD_FAILURE_INFO 124 +# define TS_F_TS_RESP_CTX_ADD_MD 125 +# define TS_F_TS_RESP_CTX_ADD_POLICY 126 +# define TS_F_TS_RESP_CTX_NEW 127 +# define TS_F_TS_RESP_CTX_SET_ACCURACY 128 +# define TS_F_TS_RESP_CTX_SET_CERTS 129 +# define TS_F_TS_RESP_CTX_SET_DEF_POLICY 130 +# define TS_F_TS_RESP_CTX_SET_SIGNER_CERT 131 +# define TS_F_TS_RESP_CTX_SET_STATUS_INFO 132 +# define TS_F_TS_RESP_GET_POLICY 133 +# define TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION 134 +# define TS_F_TS_RESP_SET_STATUS_INFO 135 +# define TS_F_TS_RESP_SET_TST_INFO 150 +# define TS_F_TS_RESP_SIGN 136 +# define TS_F_TS_RESP_VERIFY_SIGNATURE 106 +# define TS_F_TS_RESP_VERIFY_TOKEN 107 +# define TS_F_TS_TST_INFO_SET_ACCURACY 137 +# define TS_F_TS_TST_INFO_SET_MSG_IMPRINT 138 +# define TS_F_TS_TST_INFO_SET_NONCE 139 +# define TS_F_TS_TST_INFO_SET_POLICY_ID 140 +# define TS_F_TS_TST_INFO_SET_SERIAL 141 +# define TS_F_TS_TST_INFO_SET_TIME 142 +# define TS_F_TS_TST_INFO_SET_TSA 143 +# define TS_F_TS_VERIFY 108 +# define TS_F_TS_VERIFY_CERT 109 +# define TS_F_TS_VERIFY_CTX_NEW 144 + +/* Reason codes. */ +# define TS_R_BAD_PKCS7_TYPE 132 +# define TS_R_BAD_TYPE 133 +# define TS_R_CERTIFICATE_VERIFY_ERROR 100 +# define TS_R_COULD_NOT_SET_ENGINE 127 +# define TS_R_COULD_NOT_SET_TIME 115 +# define TS_R_D2I_TS_RESP_INT_FAILED 128 +# define TS_R_DETACHED_CONTENT 134 +# define TS_R_ESS_ADD_SIGNING_CERT_ERROR 116 +# define TS_R_ESS_SIGNING_CERTIFICATE_ERROR 101 +# define TS_R_INVALID_NULL_POINTER 102 +# define TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE 117 +# define TS_R_MESSAGE_IMPRINT_MISMATCH 103 +# define TS_R_NONCE_MISMATCH 104 +# define TS_R_NONCE_NOT_RETURNED 105 +# define TS_R_NO_CONTENT 106 +# define TS_R_NO_TIME_STAMP_TOKEN 107 +# define TS_R_PKCS7_ADD_SIGNATURE_ERROR 118 +# define TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR 119 +# define TS_R_PKCS7_TO_TS_TST_INFO_FAILED 129 +# define TS_R_POLICY_MISMATCH 108 +# define TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 120 +# define TS_R_RESPONSE_SETUP_ERROR 121 +# define TS_R_SIGNATURE_FAILURE 109 +# define TS_R_THERE_MUST_BE_ONE_SIGNER 110 +# define TS_R_TIME_SYSCALL_ERROR 122 +# define TS_R_TOKEN_NOT_PRESENT 130 +# define TS_R_TOKEN_PRESENT 131 +# define TS_R_TSA_NAME_MISMATCH 111 +# define TS_R_TSA_UNTRUSTED 112 +# define TS_R_TST_INFO_SETUP_ERROR 123 +# define TS_R_TS_DATASIGN 124 +# define TS_R_UNACCEPTABLE_POLICY 125 +# define TS_R_UNSUPPORTED_MD_ALGORITHM 126 +# define TS_R_UNSUPPORTED_VERSION 113 +# define TS_R_WRONG_CONTENT_TYPE 114 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/txt_db.h b/optee/optee_test/host/openssl/include/openssl/txt_db.h new file mode 100644 index 0000000..98e23a2 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/txt_db.h @@ -0,0 +1,112 @@ +/* crypto/txt_db/txt_db.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_TXT_DB_H +# define HEADER_TXT_DB_H + +# include +# ifndef OPENSSL_NO_BIO +# include +# endif +# include +# include + +# define DB_ERROR_OK 0 +# define DB_ERROR_MALLOC 1 +# define DB_ERROR_INDEX_CLASH 2 +# define DB_ERROR_INDEX_OUT_OF_RANGE 3 +# define DB_ERROR_NO_INDEX 4 +# define DB_ERROR_INSERT_INDEX_CLASH 5 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef OPENSSL_STRING *OPENSSL_PSTRING; +DECLARE_SPECIAL_STACK_OF(OPENSSL_PSTRING, OPENSSL_STRING) + +typedef struct txt_db_st { + int num_fields; + STACK_OF(OPENSSL_PSTRING) *data; + LHASH_OF(OPENSSL_STRING) **index; + int (**qual) (OPENSSL_STRING *); + long error; + long arg1; + long arg2; + OPENSSL_STRING *arg_row; +} TXT_DB; + +# ifndef OPENSSL_NO_BIO +TXT_DB *TXT_DB_read(BIO *in, int num); +long TXT_DB_write(BIO *out, TXT_DB *db); +# else +TXT_DB *TXT_DB_read(char *in, int num); +long TXT_DB_write(char *out, TXT_DB *db); +# endif +int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *), + LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp); +void TXT_DB_free(TXT_DB *db); +OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx, + OPENSSL_STRING *value); +int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ui.h b/optee/optee_test/host/openssl/include/openssl/ui.h new file mode 100644 index 0000000..0dc1633 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ui.h @@ -0,0 +1,415 @@ +/* crypto/ui/ui.h */ +/* + * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project + * 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_UI_H +# define HEADER_UI_H + +# ifndef OPENSSL_NO_DEPRECATED +# include +# endif +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Declared already in ossl_typ.h */ +/* typedef struct ui_st UI; */ +/* typedef struct ui_method_st UI_METHOD; */ + +/* + * All the following functions return -1 or NULL on error and in some cases + * (UI_process()) -2 if interrupted or in some other way cancelled. When + * everything is fine, they return 0, a positive value or a non-NULL pointer, + * all depending on their purpose. + */ + +/* Creators and destructor. */ +UI *UI_new(void); +UI *UI_new_method(const UI_METHOD *method); +void UI_free(UI *ui); + +/*- + The following functions are used to add strings to be printed and prompt + strings to prompt for data. The names are UI_{add,dup}__string + and UI_{add,dup}_input_boolean. + + UI_{add,dup}__string have the following meanings: + add add a text or prompt string. The pointers given to these + functions are used verbatim, no copying is done. + dup make a copy of the text or prompt string, then add the copy + to the collection of strings in the user interface. + + The function is a name for the functionality that the given + string shall be used for. It can be one of: + input use the string as data prompt. + verify use the string as verification prompt. This + is used to verify a previous input. + info use the string for informational output. + error use the string for error output. + Honestly, there's currently no difference between info and error for the + moment. + + UI_{add,dup}_input_boolean have the same semantics for "add" and "dup", + and are typically used when one wants to prompt for a yes/no response. + + All of the functions in this group take a UI and a prompt string. + The string input and verify addition functions also take a flag argument, + a buffer for the result to end up with, a minimum input size and a maximum + input size (the result buffer MUST be large enough to be able to contain + the maximum number of characters). Additionally, the verify addition + functions takes another buffer to compare the result against. + The boolean input functions take an action description string (which should + be safe to ignore if the expected user action is obvious, for example with + a dialog box with an OK button and a Cancel button), a string of acceptable + characters to mean OK and to mean Cancel. The two last strings are checked + to make sure they don't have common characters. Additionally, the same + flag argument as for the string input is taken, as well as a result buffer. + The result buffer is required to be at least one byte long. Depending on + the answer, the first character from the OK or the Cancel character strings + will be stored in the first byte of the result buffer. No NUL will be + added, so the result is *not* a string. + + On success, the all return an index of the added information. That index + is usefull when retrieving results with UI_get0_result(). */ +int UI_add_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_dup_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_add_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf); +int UI_dup_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf); +int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_add_info_string(UI *ui, const char *text); +int UI_dup_info_string(UI *ui, const char *text); +int UI_add_error_string(UI *ui, const char *text); +int UI_dup_error_string(UI *ui, const char *text); + +/* These are the possible flags. They can be or'ed together. */ +/* Use to have echoing of input */ +# define UI_INPUT_FLAG_ECHO 0x01 +/* + * Use a default password. Where that password is found is completely up to + * the application, it might for example be in the user data set with + * UI_add_user_data(). It is not recommended to have more than one input in + * each UI being marked with this flag, or the application might get + * confused. + */ +# define UI_INPUT_FLAG_DEFAULT_PWD 0x02 + +/*- + * The user of these routines may want to define flags of their own. The core + * UI won't look at those, but will pass them on to the method routines. They + * must use higher bits so they don't get confused with the UI bits above. + * UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good + * example of use is this: + * + * #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE) + * +*/ +# define UI_INPUT_FLAG_USER_BASE 16 + +/*- + * The following function helps construct a prompt. object_desc is a + * textual short description of the object, for example "pass phrase", + * and object_name is the name of the object (might be a card name or + * a file name. + * The returned string shall always be allocated on the heap with + * OPENSSL_malloc(), and need to be free'd with OPENSSL_free(). + * + * If the ui_method doesn't contain a pointer to a user-defined prompt + * constructor, a default string is built, looking like this: + * + * "Enter {object_desc} for {object_name}:" + * + * So, if object_desc has the value "pass phrase" and object_name has + * the value "foo.key", the resulting string is: + * + * "Enter pass phrase for foo.key:" +*/ +char *UI_construct_prompt(UI *ui_method, + const char *object_desc, const char *object_name); + +/* + * The following function is used to store a pointer to user-specific data. + * Any previous such pointer will be returned and replaced. + * + * For callback purposes, this function makes a lot more sense than using + * ex_data, since the latter requires that different parts of OpenSSL or + * applications share the same ex_data index. + * + * Note that the UI_OpenSSL() method completely ignores the user data. Other + * methods may not, however. + */ +void *UI_add_user_data(UI *ui, void *user_data); +/* We need a user data retrieving function as well. */ +void *UI_get0_user_data(UI *ui); + +/* Return the result associated with a prompt given with the index i. */ +const char *UI_get0_result(UI *ui, int i); + +/* When all strings have been added, process the whole thing. */ +int UI_process(UI *ui); + +/* + * Give a user interface parametrised control commands. This can be used to + * send down an integer, a data pointer or a function pointer, as well as be + * used to get information from a UI. + */ +int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)); + +/* The commands */ +/* + * Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the + * OpenSSL error stack before printing any info or added error messages and + * before any prompting. + */ +# define UI_CTRL_PRINT_ERRORS 1 +/* + * Check if a UI_process() is possible to do again with the same instance of + * a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0 + * if not. + */ +# define UI_CTRL_IS_REDOABLE 2 + +/* Some methods may use extra data */ +# define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg) +# define UI_get_app_data(s) UI_get_ex_data(s,0) +int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int UI_set_ex_data(UI *r, int idx, void *arg); +void *UI_get_ex_data(UI *r, int idx); + +/* Use specific methods instead of the built-in one */ +void UI_set_default_method(const UI_METHOD *meth); +const UI_METHOD *UI_get_default_method(void); +const UI_METHOD *UI_get_method(UI *ui); +const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth); + +/* The method with all the built-in thingies */ +UI_METHOD *UI_OpenSSL(void); + +/* ---------- For method writers ---------- */ +/*- + A method contains a number of functions that implement the low level + of the User Interface. The functions are: + + an opener This function starts a session, maybe by opening + a channel to a tty, or by opening a window. + a writer This function is called to write a given string, + maybe to the tty, maybe as a field label in a + window. + a flusher This function is called to flush everything that + has been output so far. It can be used to actually + display a dialog box after it has been built. + a reader This function is called to read a given prompt, + maybe from the tty, maybe from a field in a + window. Note that it's called wth all string + structures, not only the prompt ones, so it must + check such things itself. + a closer This function closes the session, maybe by closing + the channel to the tty, or closing the window. + + All these functions are expected to return: + + 0 on error. + 1 on success. + -1 on out-of-band events, for example if some prompting has + been canceled (by pressing Ctrl-C, for example). This is + only checked when returned by the flusher or the reader. + + The way this is used, the opener is first called, then the writer for all + strings, then the flusher, then the reader for all strings and finally the + closer. Note that if you want to prompt from a terminal or other command + line interface, the best is to have the reader also write the prompts + instead of having the writer do it. If you want to prompt from a dialog + box, the writer can be used to build up the contents of the box, and the + flusher to actually display the box and run the event loop until all data + has been given, after which the reader only grabs the given data and puts + them back into the UI strings. + + All method functions take a UI as argument. Additionally, the writer and + the reader take a UI_STRING. +*/ + +/* + * The UI_STRING type is the data structure that contains all the needed info + * about a string or a prompt, including test data for a verification prompt. + */ +typedef struct ui_string_st UI_STRING; +DECLARE_STACK_OF(UI_STRING) + +/* + * The different types of strings that are currently supported. This is only + * needed by method authors. + */ +enum UI_string_types { + UIT_NONE = 0, + UIT_PROMPT, /* Prompt for a string */ + UIT_VERIFY, /* Prompt for a string and verify */ + UIT_BOOLEAN, /* Prompt for a yes/no response */ + UIT_INFO, /* Send info to the user */ + UIT_ERROR /* Send an error message to the user */ +}; + +/* Create and manipulate methods */ +UI_METHOD *UI_create_method(char *name); +void UI_destroy_method(UI_METHOD *ui_method); +int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)); +int UI_method_set_writer(UI_METHOD *method, + int (*writer) (UI *ui, UI_STRING *uis)); +int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)); +int UI_method_set_reader(UI_METHOD *method, + int (*reader) (UI *ui, UI_STRING *uis)); +int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)); +int UI_method_set_prompt_constructor(UI_METHOD *method, + char *(*prompt_constructor) (UI *ui, + const char + *object_desc, + const char + *object_name)); +int (*UI_method_get_opener(UI_METHOD *method)) (UI *); +int (*UI_method_get_writer(UI_METHOD *method)) (UI *, UI_STRING *); +int (*UI_method_get_flusher(UI_METHOD *method)) (UI *); +int (*UI_method_get_reader(UI_METHOD *method)) (UI *, UI_STRING *); +int (*UI_method_get_closer(UI_METHOD *method)) (UI *); +char *(*UI_method_get_prompt_constructor(UI_METHOD *method)) (UI *, + const char *, + const char *); + +/* + * The following functions are helpers for method writers to access relevant + * data from a UI_STRING. + */ + +/* Return type of the UI_STRING */ +enum UI_string_types UI_get_string_type(UI_STRING *uis); +/* Return input flags of the UI_STRING */ +int UI_get_input_flags(UI_STRING *uis); +/* Return the actual string to output (the prompt, info or error) */ +const char *UI_get0_output_string(UI_STRING *uis); +/* + * Return the optional action string to output (the boolean promtp + * instruction) + */ +const char *UI_get0_action_string(UI_STRING *uis); +/* Return the result of a prompt */ +const char *UI_get0_result_string(UI_STRING *uis); +/* + * Return the string to test the result against. Only useful with verifies. + */ +const char *UI_get0_test_string(UI_STRING *uis); +/* Return the required minimum size of the result */ +int UI_get_result_minsize(UI_STRING *uis); +/* Return the required maximum size of the result */ +int UI_get_result_maxsize(UI_STRING *uis); +/* Set the result of a UI_STRING. */ +int UI_set_result(UI *ui, UI_STRING *uis, const char *result); + +/* A couple of popular utility functions */ +int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, + int verify); +int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt, + int verify); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_UI_strings(void); + +/* Error codes for the UI functions. */ + +/* Function codes. */ +# define UI_F_GENERAL_ALLOCATE_BOOLEAN 108 +# define UI_F_GENERAL_ALLOCATE_PROMPT 109 +# define UI_F_GENERAL_ALLOCATE_STRING 100 +# define UI_F_UI_CTRL 111 +# define UI_F_UI_DUP_ERROR_STRING 101 +# define UI_F_UI_DUP_INFO_STRING 102 +# define UI_F_UI_DUP_INPUT_BOOLEAN 110 +# define UI_F_UI_DUP_INPUT_STRING 103 +# define UI_F_UI_DUP_VERIFY_STRING 106 +# define UI_F_UI_GET0_RESULT 107 +# define UI_F_UI_NEW_METHOD 104 +# define UI_F_UI_SET_RESULT 105 + +/* Reason codes. */ +# define UI_R_COMMON_OK_AND_CANCEL_CHARACTERS 104 +# define UI_R_INDEX_TOO_LARGE 102 +# define UI_R_INDEX_TOO_SMALL 103 +# define UI_R_NO_RESULT_BUFFER 105 +# define UI_R_RESULT_TOO_LARGE 100 +# define UI_R_RESULT_TOO_SMALL 101 +# define UI_R_UNKNOWN_CONTROL_COMMAND 106 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/ui_compat.h b/optee/optee_test/host/openssl/include/openssl/ui_compat.h new file mode 100644 index 0000000..bf54154 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/ui_compat.h @@ -0,0 +1,88 @@ +/* crypto/ui/ui.h */ +/* + * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project + * 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_UI_COMPAT_H +# define HEADER_UI_COMPAT_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The following functions were previously part of the DES section, and are + * provided here for backward compatibility reasons. + */ + +# define des_read_pw_string(b,l,p,v) \ + _ossl_old_des_read_pw_string((b),(l),(p),(v)) +# define des_read_pw(b,bf,s,p,v) \ + _ossl_old_des_read_pw((b),(bf),(s),(p),(v)) + +int _ossl_old_des_read_pw_string(char *buf, int length, const char *prompt, + int verify); +int _ossl_old_des_read_pw(char *buf, char *buff, int size, const char *prompt, + int verify); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/whrlpool.h b/optee/optee_test/host/openssl/include/openssl/whrlpool.h new file mode 100644 index 0000000..73c749d --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/whrlpool.h @@ -0,0 +1,41 @@ +#ifndef HEADER_WHRLPOOL_H +# define HEADER_WHRLPOOL_H + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define WHIRLPOOL_DIGEST_LENGTH (512/8) +# define WHIRLPOOL_BBLOCK 512 +# define WHIRLPOOL_COUNTER (256/8) + +typedef struct { + union { + unsigned char c[WHIRLPOOL_DIGEST_LENGTH]; + /* double q is here to ensure 64-bit alignment */ + double q[WHIRLPOOL_DIGEST_LENGTH / sizeof(double)]; + } H; + unsigned char data[WHIRLPOOL_BBLOCK / 8]; + unsigned int bitoff; + size_t bitlen[WHIRLPOOL_COUNTER / sizeof(size_t)]; +} WHIRLPOOL_CTX; + +# ifndef OPENSSL_NO_WHIRLPOOL +# ifdef OPENSSL_FIPS +int private_WHIRLPOOL_Init(WHIRLPOOL_CTX *c); +# endif +int WHIRLPOOL_Init(WHIRLPOOL_CTX *c); +int WHIRLPOOL_Update(WHIRLPOOL_CTX *c, const void *inp, size_t bytes); +void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *inp, size_t bits); +int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c); +unsigned char *WHIRLPOOL(const void *inp, size_t bytes, unsigned char *md); +# endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/x509.h b/optee/optee_test/host/openssl/include/openssl/x509.h new file mode 100644 index 0000000..6fa28eb --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/x509.h @@ -0,0 +1,1330 @@ +/* crypto/x509/x509.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_X509_H +# define HEADER_X509_H + +# include +# include +# ifndef OPENSSL_NO_BUFFER +# include +# endif +# ifndef OPENSSL_NO_EVP +# include +# endif +# ifndef OPENSSL_NO_BIO +# include +# endif +# include +# include +# include + +# ifndef OPENSSL_NO_EC +# include +# endif + +# ifndef OPENSSL_NO_ECDSA +# include +# endif + +# ifndef OPENSSL_NO_ECDH +# include +# endif + +# ifndef OPENSSL_NO_DEPRECATED +# ifndef OPENSSL_NO_RSA +# include +# endif +# ifndef OPENSSL_NO_DSA +# include +# endif +# ifndef OPENSSL_NO_DH +# include +# endif +# endif + +# ifndef OPENSSL_NO_SHA +# include +# endif +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef OPENSSL_SYS_WIN32 +/* Under Win32 these are defined in wincrypt.h */ +# undef X509_NAME +# undef X509_CERT_PAIR +# undef X509_EXTENSIONS +# endif + +# define X509_FILETYPE_PEM 1 +# define X509_FILETYPE_ASN1 2 +# define X509_FILETYPE_DEFAULT 3 + +# define X509v3_KU_DIGITAL_SIGNATURE 0x0080 +# define X509v3_KU_NON_REPUDIATION 0x0040 +# define X509v3_KU_KEY_ENCIPHERMENT 0x0020 +# define X509v3_KU_DATA_ENCIPHERMENT 0x0010 +# define X509v3_KU_KEY_AGREEMENT 0x0008 +# define X509v3_KU_KEY_CERT_SIGN 0x0004 +# define X509v3_KU_CRL_SIGN 0x0002 +# define X509v3_KU_ENCIPHER_ONLY 0x0001 +# define X509v3_KU_DECIPHER_ONLY 0x8000 +# define X509v3_KU_UNDEF 0xffff + +typedef struct X509_objects_st { + int nid; + int (*a2i) (void); + int (*i2a) (void); +} X509_OBJECTS; + +struct X509_algor_st { + ASN1_OBJECT *algorithm; + ASN1_TYPE *parameter; +} /* X509_ALGOR */ ; + +DECLARE_ASN1_SET_OF(X509_ALGOR) + +typedef STACK_OF(X509_ALGOR) X509_ALGORS; + +typedef struct X509_val_st { + ASN1_TIME *notBefore; + ASN1_TIME *notAfter; +} X509_VAL; + +struct X509_pubkey_st { + X509_ALGOR *algor; + ASN1_BIT_STRING *public_key; + EVP_PKEY *pkey; +}; + +typedef struct X509_sig_st { + X509_ALGOR *algor; + ASN1_OCTET_STRING *digest; +} X509_SIG; + +typedef struct X509_name_entry_st { + ASN1_OBJECT *object; + ASN1_STRING *value; + int set; + int size; /* temp variable */ +} X509_NAME_ENTRY; + +DECLARE_STACK_OF(X509_NAME_ENTRY) +DECLARE_ASN1_SET_OF(X509_NAME_ENTRY) + +/* we always keep X509_NAMEs in 2 forms. */ +struct X509_name_st { + STACK_OF(X509_NAME_ENTRY) *entries; + int modified; /* true if 'bytes' needs to be built */ +# ifndef OPENSSL_NO_BUFFER + BUF_MEM *bytes; +# else + char *bytes; +# endif +/* unsigned long hash; Keep the hash around for lookups */ + unsigned char *canon_enc; + int canon_enclen; +} /* X509_NAME */ ; + +DECLARE_STACK_OF(X509_NAME) + +# define X509_EX_V_NETSCAPE_HACK 0x8000 +# define X509_EX_V_INIT 0x0001 +typedef struct X509_extension_st { + ASN1_OBJECT *object; + ASN1_BOOLEAN critical; + ASN1_OCTET_STRING *value; +} X509_EXTENSION; + +typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; + +DECLARE_STACK_OF(X509_EXTENSION) +DECLARE_ASN1_SET_OF(X509_EXTENSION) + +/* a sequence of these are used */ +typedef struct x509_attributes_st { + ASN1_OBJECT *object; + int single; /* 0 for a set, 1 for a single item (which is + * wrong) */ + union { + char *ptr; + /* + * 0 + */ STACK_OF(ASN1_TYPE) *set; + /* + * 1 + */ ASN1_TYPE *single; + } value; +} X509_ATTRIBUTE; + +DECLARE_STACK_OF(X509_ATTRIBUTE) +DECLARE_ASN1_SET_OF(X509_ATTRIBUTE) + +typedef struct X509_req_info_st { + ASN1_ENCODING enc; + ASN1_INTEGER *version; + X509_NAME *subject; + X509_PUBKEY *pubkey; + /* d=2 hl=2 l= 0 cons: cont: 00 */ + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ +} X509_REQ_INFO; + +typedef struct X509_req_st { + X509_REQ_INFO *req_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; +} X509_REQ; + +typedef struct x509_cinf_st { + ASN1_INTEGER *version; /* [ 0 ] default of v1 */ + ASN1_INTEGER *serialNumber; + X509_ALGOR *signature; + X509_NAME *issuer; + X509_VAL *validity; + X509_NAME *subject; + X509_PUBKEY *key; + ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ + ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ + STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ + ASN1_ENCODING enc; +} X509_CINF; + +/* + * This stuff is certificate "auxiliary info" it contains details which are + * useful in certificate stores and databases. When used this is tagged onto + * the end of the certificate itself + */ + +typedef struct x509_cert_aux_st { + STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */ + STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */ + ASN1_UTF8STRING *alias; /* "friendly name" */ + ASN1_OCTET_STRING *keyid; /* key id of private key */ + STACK_OF(X509_ALGOR) *other; /* other unspecified info */ +} X509_CERT_AUX; + +struct x509_st { + X509_CINF *cert_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int valid; + int references; + char *name; + CRYPTO_EX_DATA ex_data; + /* These contain copies of various extension values */ + long ex_pathlen; + long ex_pcpathlen; + unsigned long ex_flags; + unsigned long ex_kusage; + unsigned long ex_xkusage; + unsigned long ex_nscert; + ASN1_OCTET_STRING *skid; + AUTHORITY_KEYID *akid; + X509_POLICY_CACHE *policy_cache; + STACK_OF(DIST_POINT) *crldp; + STACK_OF(GENERAL_NAME) *altname; + NAME_CONSTRAINTS *nc; +# ifndef OPENSSL_NO_RFC3779 + STACK_OF(IPAddressFamily) *rfc3779_addr; + struct ASIdentifiers_st *rfc3779_asid; +# endif +# ifndef OPENSSL_NO_SHA + unsigned char sha1_hash[SHA_DIGEST_LENGTH]; +# endif + X509_CERT_AUX *aux; +} /* X509 */ ; + +DECLARE_STACK_OF(X509) +DECLARE_ASN1_SET_OF(X509) + +/* This is used for a table of trust checking functions */ + +typedef struct x509_trust_st { + int trust; + int flags; + int (*check_trust) (struct x509_trust_st *, X509 *, int); + char *name; + int arg1; + void *arg2; +} X509_TRUST; + +DECLARE_STACK_OF(X509_TRUST) + +typedef struct x509_cert_pair_st { + X509 *forward; + X509 *reverse; +} X509_CERT_PAIR; + +/* standard trust ids */ + +# define X509_TRUST_DEFAULT -1/* Only valid in purpose settings */ + +# define X509_TRUST_COMPAT 1 +# define X509_TRUST_SSL_CLIENT 2 +# define X509_TRUST_SSL_SERVER 3 +# define X509_TRUST_EMAIL 4 +# define X509_TRUST_OBJECT_SIGN 5 +# define X509_TRUST_OCSP_SIGN 6 +# define X509_TRUST_OCSP_REQUEST 7 +# define X509_TRUST_TSA 8 + +/* Keep these up to date! */ +# define X509_TRUST_MIN 1 +# define X509_TRUST_MAX 8 + +/* trust_flags values */ +# define X509_TRUST_DYNAMIC 1 +# define X509_TRUST_DYNAMIC_NAME 2 + +/* check_trust return codes */ + +# define X509_TRUST_TRUSTED 1 +# define X509_TRUST_REJECTED 2 +# define X509_TRUST_UNTRUSTED 3 + +/* Flags for X509_print_ex() */ + +# define X509_FLAG_COMPAT 0 +# define X509_FLAG_NO_HEADER 1L +# define X509_FLAG_NO_VERSION (1L << 1) +# define X509_FLAG_NO_SERIAL (1L << 2) +# define X509_FLAG_NO_SIGNAME (1L << 3) +# define X509_FLAG_NO_ISSUER (1L << 4) +# define X509_FLAG_NO_VALIDITY (1L << 5) +# define X509_FLAG_NO_SUBJECT (1L << 6) +# define X509_FLAG_NO_PUBKEY (1L << 7) +# define X509_FLAG_NO_EXTENSIONS (1L << 8) +# define X509_FLAG_NO_SIGDUMP (1L << 9) +# define X509_FLAG_NO_AUX (1L << 10) +# define X509_FLAG_NO_ATTRIBUTES (1L << 11) +# define X509_FLAG_NO_IDS (1L << 12) + +/* Flags specific to X509_NAME_print_ex() */ + +/* The field separator information */ + +# define XN_FLAG_SEP_MASK (0xf << 16) + +# define XN_FLAG_COMPAT 0/* Traditional SSLeay: use old + * X509_NAME_print */ +# define XN_FLAG_SEP_COMMA_PLUS (1 << 16)/* RFC2253 ,+ */ +# define XN_FLAG_SEP_CPLUS_SPC (2 << 16)/* ,+ spaced: more readable */ +# define XN_FLAG_SEP_SPLUS_SPC (3 << 16)/* ;+ spaced */ +# define XN_FLAG_SEP_MULTILINE (4 << 16)/* One line per field */ + +# define XN_FLAG_DN_REV (1 << 20)/* Reverse DN order */ + +/* How the field name is shown */ + +# define XN_FLAG_FN_MASK (0x3 << 21) + +# define XN_FLAG_FN_SN 0/* Object short name */ +# define XN_FLAG_FN_LN (1 << 21)/* Object long name */ +# define XN_FLAG_FN_OID (2 << 21)/* Always use OIDs */ +# define XN_FLAG_FN_NONE (3 << 21)/* No field names */ + +# define XN_FLAG_SPC_EQ (1 << 23)/* Put spaces round '=' */ + +/* + * This determines if we dump fields we don't recognise: RFC2253 requires + * this. + */ + +# define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) + +# define XN_FLAG_FN_ALIGN (1 << 25)/* Align field names to 20 + * characters */ + +/* Complete set of RFC2253 flags */ + +# define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \ + XN_FLAG_SEP_COMMA_PLUS | \ + XN_FLAG_DN_REV | \ + XN_FLAG_FN_SN | \ + XN_FLAG_DUMP_UNKNOWN_FIELDS) + +/* readable oneline form */ + +# define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + XN_FLAG_SEP_CPLUS_SPC | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_SN) + +/* readable multiline form */ + +# define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + XN_FLAG_SEP_MULTILINE | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_LN | \ + XN_FLAG_FN_ALIGN) + +struct x509_revoked_st { + ASN1_INTEGER *serialNumber; + ASN1_TIME *revocationDate; + STACK_OF(X509_EXTENSION) /* optional */ *extensions; + /* Set up if indirect CRL */ + STACK_OF(GENERAL_NAME) *issuer; + /* Revocation reason */ + int reason; + int sequence; /* load sequence */ +}; + +DECLARE_STACK_OF(X509_REVOKED) +DECLARE_ASN1_SET_OF(X509_REVOKED) + +typedef struct X509_crl_info_st { + ASN1_INTEGER *version; + X509_ALGOR *sig_alg; + X509_NAME *issuer; + ASN1_TIME *lastUpdate; + ASN1_TIME *nextUpdate; + STACK_OF(X509_REVOKED) *revoked; + STACK_OF(X509_EXTENSION) /* [0] */ *extensions; + ASN1_ENCODING enc; +} X509_CRL_INFO; + +struct X509_crl_st { + /* actual signature */ + X509_CRL_INFO *crl; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; + int flags; + /* Copies of various extensions */ + AUTHORITY_KEYID *akid; + ISSUING_DIST_POINT *idp; + /* Convenient breakdown of IDP */ + int idp_flags; + int idp_reasons; + /* CRL and base CRL numbers for delta processing */ + ASN1_INTEGER *crl_number; + ASN1_INTEGER *base_crl_number; +# ifndef OPENSSL_NO_SHA + unsigned char sha1_hash[SHA_DIGEST_LENGTH]; +# endif + STACK_OF(GENERAL_NAMES) *issuers; + const X509_CRL_METHOD *meth; + void *meth_data; +} /* X509_CRL */ ; + +DECLARE_STACK_OF(X509_CRL) +DECLARE_ASN1_SET_OF(X509_CRL) + +typedef struct private_key_st { + int version; + /* The PKCS#8 data types */ + X509_ALGOR *enc_algor; + ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */ + /* When decrypted, the following will not be NULL */ + EVP_PKEY *dec_pkey; + /* used to encrypt and decrypt */ + int key_length; + char *key_data; + int key_free; /* true if we should auto free key_data */ + /* expanded version of 'enc_algor' */ + EVP_CIPHER_INFO cipher; + int references; +} X509_PKEY; + +# ifndef OPENSSL_NO_EVP +typedef struct X509_info_st { + X509 *x509; + X509_CRL *crl; + X509_PKEY *x_pkey; + EVP_CIPHER_INFO enc_cipher; + int enc_len; + char *enc_data; + int references; +} X509_INFO; + +DECLARE_STACK_OF(X509_INFO) +# endif + +/* + * The next 2 structures and their 8 routines were sent to me by Pat Richard + * and are used to manipulate Netscapes spki structures - + * useful if you are writing a CA web page + */ +typedef struct Netscape_spkac_st { + X509_PUBKEY *pubkey; + ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */ +} NETSCAPE_SPKAC; + +typedef struct Netscape_spki_st { + NETSCAPE_SPKAC *spkac; /* signed public key and challenge */ + X509_ALGOR *sig_algor; + ASN1_BIT_STRING *signature; +} NETSCAPE_SPKI; + +/* Netscape certificate sequence structure */ +typedef struct Netscape_certificate_sequence { + ASN1_OBJECT *type; + STACK_OF(X509) *certs; +} NETSCAPE_CERT_SEQUENCE; + +/*- Unused (and iv length is wrong) +typedef struct CBCParameter_st + { + unsigned char iv[8]; + } CBC_PARAM; +*/ + +/* Password based encryption structure */ + +typedef struct PBEPARAM_st { + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *iter; +} PBEPARAM; + +/* Password based encryption V2 structures */ + +typedef struct PBE2PARAM_st { + X509_ALGOR *keyfunc; + X509_ALGOR *encryption; +} PBE2PARAM; + +typedef struct PBKDF2PARAM_st { +/* Usually OCTET STRING but could be anything */ + ASN1_TYPE *salt; + ASN1_INTEGER *iter; + ASN1_INTEGER *keylength; + X509_ALGOR *prf; +} PBKDF2PARAM; + +/* PKCS#8 private key info structure */ + +struct pkcs8_priv_key_info_st { + /* Flag for various broken formats */ + int broken; +# define PKCS8_OK 0 +# define PKCS8_NO_OCTET 1 +# define PKCS8_EMBEDDED_PARAM 2 +# define PKCS8_NS_DB 3 +# define PKCS8_NEG_PRIVKEY 4 + ASN1_INTEGER *version; + X509_ALGOR *pkeyalg; + /* Should be OCTET STRING but some are broken */ + ASN1_TYPE *pkey; + STACK_OF(X509_ATTRIBUTE) *attributes; +}; + +#ifdef __cplusplus +} +#endif + +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# define X509_EXT_PACK_UNKNOWN 1 +# define X509_EXT_PACK_STRING 2 + +# define X509_get_version(x) ASN1_INTEGER_get((x)->cert_info->version) +/* #define X509_get_serialNumber(x) ((x)->cert_info->serialNumber) */ +# define X509_get_notBefore(x) ((x)->cert_info->validity->notBefore) +# define X509_get_notAfter(x) ((x)->cert_info->validity->notAfter) +# define X509_extract_key(x) X509_get_pubkey(x)/*****/ +# define X509_REQ_get_version(x) ASN1_INTEGER_get((x)->req_info->version) +# define X509_REQ_get_subject_name(x) ((x)->req_info->subject) +# define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) +# define X509_name_cmp(a,b) X509_NAME_cmp((a),(b)) +# define X509_get_signature_type(x) EVP_PKEY_type(OBJ_obj2nid((x)->sig_alg->algorithm)) + +# define X509_CRL_get_version(x) ASN1_INTEGER_get((x)->crl->version) +# define X509_CRL_get_lastUpdate(x) ((x)->crl->lastUpdate) +# define X509_CRL_get_nextUpdate(x) ((x)->crl->nextUpdate) +# define X509_CRL_get_issuer(x) ((x)->crl->issuer) +# define X509_CRL_get_REVOKED(x) ((x)->crl->revoked) + +void X509_CRL_set_default_method(const X509_CRL_METHOD *meth); +X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), + int (*crl_free) (X509_CRL *crl), + int (*crl_lookup) (X509_CRL *crl, + X509_REVOKED **ret, + ASN1_INTEGER *ser, + X509_NAME *issuer), + int (*crl_verify) (X509_CRL *crl, + EVP_PKEY *pk)); +void X509_CRL_METHOD_free(X509_CRL_METHOD *m); + +void X509_CRL_set_meth_data(X509_CRL *crl, void *dat); +void *X509_CRL_get_meth_data(X509_CRL *crl); + +/* + * This one is only used so that a binary form can output, as in + * i2d_X509_NAME(X509_get_X509_PUBKEY(x),&buf) + */ +# define X509_get_X509_PUBKEY(x) ((x)->cert_info->key) + +const char *X509_verify_cert_error_string(long n); + +# ifndef OPENSSL_NO_EVP +int X509_verify(X509 *a, EVP_PKEY *r); + +int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); +int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r); + +NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len); +char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x); +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x); +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey); + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); + +int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent); +int X509_signature_print(BIO *bp, X509_ALGOR *alg, ASN1_STRING *sig); + +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx); +int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert); +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx); +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx); +int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl); +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md); + +int X509_pubkey_digest(const X509 *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_digest(const X509 *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, + unsigned char *md, unsigned int *len); +# endif + +# ifndef OPENSSL_NO_FP_API +X509 *d2i_X509_fp(FILE *fp, X509 **x509); +int i2d_X509_fp(FILE *fp, X509 *x509); +X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl); +int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl); +X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req); +int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req); +# ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa); +int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa); +RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa); +int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa); +RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa); +int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa); +# endif +# ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); +DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); +int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); +# endif +# ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey); +int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey); +EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey); +int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey); +# endif +X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8); +int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key); +int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a); +int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); +# endif + +# ifndef OPENSSL_NO_BIO +X509 *d2i_X509_bio(BIO *bp, X509 **x509); +int i2d_X509_bio(BIO *bp, X509 *x509); +X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl); +int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl); +X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req); +int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req); +# ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa); +int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa); +RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa); +int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa); +RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa); +int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa); +# endif +# ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); +DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); +int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); +# endif +# ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey); +int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey); +EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey); +int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey); +# endif +X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8); +int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key); +int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); +int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); +# endif + +X509 *X509_dup(X509 *x509); +X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa); +X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex); +X509_CRL *X509_CRL_dup(X509_CRL *crl); +X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev); +X509_REQ *X509_REQ_dup(X509_REQ *req); +X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn); +int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, + void *pval); +void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval, + X509_ALGOR *algor); +void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); +int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b); + +X509_NAME *X509_NAME_dup(X509_NAME *xn); +X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); + +int X509_cmp_time(const ASN1_TIME *s, time_t *t); +int X509_cmp_current_time(const ASN1_TIME *s); +ASN1_TIME *X509_time_adj(ASN1_TIME *s, long adj, time_t *t); +ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, + int offset_day, long offset_sec, time_t *t); +ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj); + +const char *X509_get_default_cert_area(void); +const char *X509_get_default_cert_dir(void); +const char *X509_get_default_cert_file(void); +const char *X509_get_default_cert_dir_env(void); +const char *X509_get_default_cert_file_env(void); +const char *X509_get_default_private_dir(void); + +X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey); + +DECLARE_ASN1_FUNCTIONS(X509_ALGOR) +DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS) +DECLARE_ASN1_FUNCTIONS(X509_VAL) + +DECLARE_ASN1_FUNCTIONS(X509_PUBKEY) + +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); +EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key); +int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain); +int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp); +EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length); +# ifndef OPENSSL_NO_RSA +int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp); +RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length); +# endif +# ifndef OPENSSL_NO_DSA +int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp); +DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length); +# endif +# ifndef OPENSSL_NO_EC +int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp); +EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length); +# endif + +DECLARE_ASN1_FUNCTIONS(X509_SIG) +DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO) +DECLARE_ASN1_FUNCTIONS(X509_REQ) + +DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE) +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value); + +DECLARE_ASN1_FUNCTIONS(X509_EXTENSION) +DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS) + +DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY) + +DECLARE_ASN1_FUNCTIONS(X509_NAME) + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name); + +DECLARE_ASN1_FUNCTIONS(X509_CINF) + +DECLARE_ASN1_FUNCTIONS(X509) +DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX) + +DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR) + +int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int X509_set_ex_data(X509 *r, int idx, void *arg); +void *X509_get_ex_data(X509 *r, int idx); +int i2d_X509_AUX(X509 *a, unsigned char **pp); +X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length); + +int i2d_re_X509_tbs(X509 *x, unsigned char **pp); + +void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, + const X509 *x); +int X509_get_signature_nid(const X509 *x); + +int X509_alias_set1(X509 *x, unsigned char *name, int len); +int X509_keyid_set1(X509 *x, unsigned char *id, int len); +unsigned char *X509_alias_get0(X509 *x, int *len); +unsigned char *X509_keyid_get0(X509 *x, int *len); +int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, + int); +int X509_TRUST_set(int *t, int trust); +int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj); +int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj); +void X509_trust_clear(X509 *x); +void X509_reject_clear(X509 *x); + +DECLARE_ASN1_FUNCTIONS(X509_REVOKED) +DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO) +DECLARE_ASN1_FUNCTIONS(X509_CRL) + +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); +int X509_CRL_get0_by_serial(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial); +int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x); + +X509_PKEY *X509_PKEY_new(void); +void X509_PKEY_free(X509_PKEY *a); +int i2d_X509_PKEY(X509_PKEY *a, unsigned char **pp); +X509_PKEY *d2i_X509_PKEY(X509_PKEY **a, const unsigned char **pp, + long length); + +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC) +DECLARE_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) + +# ifndef OPENSSL_NO_EVP +X509_INFO *X509_INFO_new(void); +void X509_INFO_free(X509_INFO *a); +char *X509_NAME_oneline(X509_NAME *a, char *buf, int size); + +int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey); + +int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, + unsigned char *md, unsigned int *len); + +int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + char *data, EVP_PKEY *pkey, const EVP_MD *type); + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *data, + unsigned char *md, unsigned int *len); + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature, void *data, EVP_PKEY *pkey); + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *data, + EVP_PKEY *pkey, const EVP_MD *type); +int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + void *asn, EVP_MD_CTX *ctx); +# endif + +int X509_set_version(X509 *x, long version); +int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); +ASN1_INTEGER *X509_get_serialNumber(X509 *x); +int X509_set_issuer_name(X509 *x, X509_NAME *name); +X509_NAME *X509_get_issuer_name(X509 *a); +int X509_set_subject_name(X509 *x, X509_NAME *name); +X509_NAME *X509_get_subject_name(X509 *a); +int X509_set_notBefore(X509 *x, const ASN1_TIME *tm); +int X509_set_notAfter(X509 *x, const ASN1_TIME *tm); +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); +EVP_PKEY *X509_get_pubkey(X509 *x); +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x); +int X509_certificate_type(X509 *x, EVP_PKEY *pubkey /* optional */ ); + +int X509_REQ_set_version(X509_REQ *x, long version); +int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); +EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req); +int X509_REQ_extension_nid(int nid); +int *X509_REQ_get_extension_nids(void); +void X509_REQ_set_extension_nids(int *nids); +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); +int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid); +int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts); +int X509_REQ_get_attr_count(const X509_REQ *req); +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos); +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr); +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_CRL_set_version(X509_CRL *x, long version); +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); +int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_sort(X509_CRL *crl); + +int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial); +int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); + +X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, + EVP_PKEY *skey, const EVP_MD *md, unsigned int flags); + +int X509_REQ_check_private_key(X509_REQ *x509, EVP_PKEY *pkey); + +int X509_check_private_key(X509 *x509, EVP_PKEY *pkey); +int X509_chain_check_suiteb(int *perror_depth, + X509 *x, STACK_OF(X509) *chain, + unsigned long flags); +int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags); +STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain); + +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); +unsigned long X509_issuer_and_serial_hash(X509 *a); + +int X509_issuer_name_cmp(const X509 *a, const X509 *b); +unsigned long X509_issuer_name_hash(X509 *a); + +int X509_subject_name_cmp(const X509 *a, const X509 *b); +unsigned long X509_subject_name_hash(X509 *x); + +# ifndef OPENSSL_NO_MD5 +unsigned long X509_issuer_name_hash_old(X509 *a); +unsigned long X509_subject_name_hash_old(X509 *x); +# endif + +int X509_cmp(const X509 *a, const X509 *b); +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); +unsigned long X509_NAME_hash(X509_NAME *x); +unsigned long X509_NAME_hash_old(X509_NAME *x); + +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b); +# ifndef OPENSSL_NO_FP_API +int X509_print_ex_fp(FILE *bp, X509 *x, unsigned long nmflag, + unsigned long cflag); +int X509_print_fp(FILE *bp, X509 *x); +int X509_CRL_print_fp(FILE *bp, X509_CRL *x); +int X509_REQ_print_fp(FILE *bp, X509_REQ *req); +int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, + unsigned long flags); +# endif + +# ifndef OPENSSL_NO_BIO +int X509_NAME_print(BIO *bp, X509_NAME *name, int obase); +int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, + unsigned long flags); +int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflag, + unsigned long cflag); +int X509_print(BIO *bp, X509 *x); +int X509_ocspid_print(BIO *bp, X509 *x); +int X509_CERT_AUX_print(BIO *bp, X509_CERT_AUX *x, int indent); +int X509_CRL_print(BIO *bp, X509_CRL *x); +int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, + unsigned long cflag); +int X509_REQ_print(BIO *bp, X509_REQ *req); +# endif + +int X509_NAME_entry_count(X509_NAME *name); +int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len); +int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, + char *buf, int len); + +/* + * NOTE: you should be passsing -1, not 0 as lastpos. The functions that use + * lastpos, search after that position on. + */ +int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos); +int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, + int lastpos); +X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc); +int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, + int loc, int set); +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, + unsigned char *bytes, int len, int loc, + int set); +int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + unsigned char *bytes, int len, int loc, + int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + const char *field, int type, + const unsigned char *bytes, + int len); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type, unsigned char *bytes, + int len); +int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, + const unsigned char *bytes, int len, int loc, + int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + ASN1_OBJECT *obj, int type, + const unsigned char *bytes, + int len); +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj); +int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + const unsigned char *bytes, int len); +ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne); +ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne); + +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); +int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, + int nid, int lastpos); +int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, + ASN1_OBJECT *obj, int lastpos); +int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, + int crit, int lastpos); +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc); +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); +STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc); + +int X509_get_ext_count(X509 *x); +int X509_get_ext_by_NID(X509 *x, int nid, int lastpos); +int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos); +int X509_get_ext_by_critical(X509 *x, int crit, int lastpos); +X509_EXTENSION *X509_get_ext(X509 *x, int loc); +X509_EXTENSION *X509_delete_ext(X509 *x, int loc); +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); +void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); +int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags); + +int X509_CRL_get_ext_count(X509_CRL *x); +int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos); +int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos); +int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos); +X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc); +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); +void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx); +int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags); + +int X509_REVOKED_get_ext_count(X509_REVOKED *x); +int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos); +int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj, + int lastpos); +int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos); +X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc); +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc); +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc); +void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx); +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags); + +X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, + int nid, int crit, + ASN1_OCTET_STRING *data); +X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, + ASN1_OBJECT *obj, int crit, + ASN1_OCTET_STRING *data); +int X509_EXTENSION_set_object(X509_EXTENSION *ex, ASN1_OBJECT *obj); +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); +int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data); +ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex); +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); +int X509_EXTENSION_get_critical(X509_EXTENSION *ex); + +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x); +int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos); +int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, + ASN1_OBJECT *obj, int lastpos); +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc); +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) + **x, const ASN1_OBJECT *obj, + int type, + const unsigned char *bytes, + int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) + **x, int nid, int type, + const unsigned char *bytes, + int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) + **x, const char *attrname, + int type, + const unsigned char *bytes, + int len); +void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, ASN1_OBJECT *obj, + int lastpos, int type); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, const void *data, + int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + const ASN1_OBJECT *obj, + int atrtype, const void *data, + int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + const char *atrname, int type, + const unsigned char *bytes, + int len); +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj); +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, + const void *data, int len); +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int atrtype, + void *data); +int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr); +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); + +int EVP_PKEY_get_attr_count(const EVP_PKEY *key); +int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos); +int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc); +X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc); +int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr); +int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, + int nid, int type, + const unsigned char *bytes, int len); +int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_verify_cert(X509_STORE_CTX *ctx); + +/* lookup a cert from a X509 STACK */ +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name, + ASN1_INTEGER *serial); +X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name); + +DECLARE_ASN1_FUNCTIONS(PBEPARAM) +DECLARE_ASN1_FUNCTIONS(PBE2PARAM) +DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM) + +int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen); + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, + const unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid); + +X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen); + +/* PKCS#8 utilities */ + +DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) + +EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8); +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken); +PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken); + +int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, + int version, int ptype, void *pval, + unsigned char *penc, int penclen); +int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8); + +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen); +int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, X509_PUBKEY *pub); + +int X509_check_trust(X509 *x, int id, int flags); +int X509_TRUST_get_count(void); +X509_TRUST *X509_TRUST_get0(int idx); +int X509_TRUST_get_by_id(int id); +int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), + char *name, int arg1, void *arg2); +void X509_TRUST_cleanup(void); +int X509_TRUST_get_flags(X509_TRUST *xp); +char *X509_TRUST_get0_name(X509_TRUST *xp); +int X509_TRUST_get_trust(X509_TRUST *xp); + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +void ERR_load_X509_strings(void); + +/* Error codes for the X509 functions. */ + +/* Function codes. */ +# define X509_F_ADD_CERT_DIR 100 +# define X509_F_BY_FILE_CTRL 101 +# define X509_F_CHECK_NAME_CONSTRAINTS 106 +# define X509_F_CHECK_POLICY 145 +# define X509_F_DIR_CTRL 102 +# define X509_F_GET_CERT_BY_SUBJECT 103 +# define X509_F_NETSCAPE_SPKI_B64_DECODE 129 +# define X509_F_NETSCAPE_SPKI_B64_ENCODE 130 +# define X509_F_X509AT_ADD1_ATTR 135 +# define X509_F_X509V3_ADD_EXT 104 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137 +# define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140 +# define X509_F_X509_ATTRIBUTE_GET0_DATA 139 +# define X509_F_X509_ATTRIBUTE_SET1_DATA 138 +# define X509_F_X509_CHECK_PRIVATE_KEY 128 +# define X509_F_X509_CRL_DIFF 105 +# define X509_F_X509_CRL_PRINT_FP 147 +# define X509_F_X509_EXTENSION_CREATE_BY_NID 108 +# define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109 +# define X509_F_X509_GET_PUBKEY_PARAMETERS 110 +# define X509_F_X509_LOAD_CERT_CRL_FILE 132 +# define X509_F_X509_LOAD_CERT_FILE 111 +# define X509_F_X509_LOAD_CRL_FILE 112 +# define X509_F_X509_NAME_ADD_ENTRY 113 +# define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114 +# define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131 +# define X509_F_X509_NAME_ENTRY_SET_OBJECT 115 +# define X509_F_X509_NAME_ONELINE 116 +# define X509_F_X509_NAME_PRINT 117 +# define X509_F_X509_PRINT_EX_FP 118 +# define X509_F_X509_PUBKEY_GET 119 +# define X509_F_X509_PUBKEY_SET 120 +# define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144 +# define X509_F_X509_REQ_PRINT_EX 121 +# define X509_F_X509_REQ_PRINT_FP 122 +# define X509_F_X509_REQ_TO_X509 123 +# define X509_F_X509_STORE_ADD_CERT 124 +# define X509_F_X509_STORE_ADD_CRL 125 +# define X509_F_X509_STORE_CTX_GET1_ISSUER 146 +# define X509_F_X509_STORE_CTX_INIT 143 +# define X509_F_X509_STORE_CTX_NEW 142 +# define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134 +# define X509_F_X509_TO_X509_REQ 126 +# define X509_F_X509_TRUST_ADD 133 +# define X509_F_X509_TRUST_SET 141 +# define X509_F_X509_VERIFY_CERT 127 + +/* Reason codes. */ +# define X509_R_AKID_MISMATCH 110 +# define X509_R_BAD_X509_FILETYPE 100 +# define X509_R_BASE64_DECODE_ERROR 118 +# define X509_R_CANT_CHECK_DH_KEY 114 +# define X509_R_CERT_ALREADY_IN_HASH_TABLE 101 +# define X509_R_CRL_ALREADY_DELTA 127 +# define X509_R_CRL_VERIFY_FAILURE 131 +# define X509_R_ERR_ASN1_LIB 102 +# define X509_R_IDP_MISMATCH 128 +# define X509_R_INVALID_DIRECTORY 113 +# define X509_R_INVALID_FIELD_NAME 119 +# define X509_R_INVALID_TRUST 123 +# define X509_R_ISSUER_MISMATCH 129 +# define X509_R_KEY_TYPE_MISMATCH 115 +# define X509_R_KEY_VALUES_MISMATCH 116 +# define X509_R_LOADING_CERT_DIR 103 +# define X509_R_LOADING_DEFAULTS 104 +# define X509_R_METHOD_NOT_SUPPORTED 124 +# define X509_R_NAME_TOO_LONG 134 +# define X509_R_NEWER_CRL_NOT_NEWER 132 +# define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105 +# define X509_R_NO_CRL_NUMBER 130 +# define X509_R_PUBLIC_KEY_DECODE_ERROR 125 +# define X509_R_PUBLIC_KEY_ENCODE_ERROR 126 +# define X509_R_SHOULD_RETRY 106 +# define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 107 +# define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108 +# define X509_R_UNKNOWN_KEY_TYPE 117 +# define X509_R_UNKNOWN_NID 109 +# define X509_R_UNKNOWN_PURPOSE_ID 121 +# define X509_R_UNKNOWN_TRUST_ID 120 +# define X509_R_UNSUPPORTED_ALGORITHM 111 +# define X509_R_WRONG_LOOKUP_TYPE 112 +# define X509_R_WRONG_TYPE 122 + +# ifdef __cplusplus +} +# endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/x509_vfy.h b/optee/optee_test/host/openssl/include/openssl/x509_vfy.h new file mode 100644 index 0000000..5062682 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/x509_vfy.h @@ -0,0 +1,652 @@ +/* crypto/x509/x509_vfy.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED 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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_X509_H +# include +/* + * openssl/x509.h ends up #include-ing this file at about the only + * appropriate moment. + */ +#endif + +#ifndef HEADER_X509_VFY_H +# define HEADER_X509_VFY_H + +# include +# ifndef OPENSSL_NO_LHASH +# include +# endif +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# if 0 +/* Outer object */ +typedef struct x509_hash_dir_st { + int num_dirs; + char **dirs; + int *dirs_type; + int num_dirs_alloced; +} X509_HASH_DIR_CTX; +# endif + +typedef struct x509_file_st { + int num_paths; /* number of paths to files or directories */ + int num_alloced; + char **paths; /* the list of paths or directories */ + int *path_type; +} X509_CERT_FILE_CTX; + +/*******************************/ +/*- +SSL_CTX -> X509_STORE + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + -> X509_LOOKUP + ->X509_LOOKUP_METHOD + +SSL -> X509_STORE_CTX + ->X509_STORE + +The X509_STORE holds the tables etc for verification stuff. +A X509_STORE_CTX is used while validating a single certificate. +The X509_STORE has X509_LOOKUPs for looking up certs. +The X509_STORE then calls a function to actually verify the +certificate chain. +*/ + +# define X509_LU_RETRY -1 +# define X509_LU_FAIL 0 +# define X509_LU_X509 1 +# define X509_LU_CRL 2 +# define X509_LU_PKEY 3 + +typedef struct x509_object_st { + /* one of the above types */ + int type; + union { + char *ptr; + X509 *x509; + X509_CRL *crl; + EVP_PKEY *pkey; + } data; +} X509_OBJECT; + +typedef struct x509_lookup_st X509_LOOKUP; + +DECLARE_STACK_OF(X509_LOOKUP) +DECLARE_STACK_OF(X509_OBJECT) + +/* This is a static that defines the function interface */ +typedef struct x509_lookup_method_st { + const char *name; + int (*new_item) (X509_LOOKUP *ctx); + void (*free) (X509_LOOKUP *ctx); + int (*init) (X509_LOOKUP *ctx); + int (*shutdown) (X509_LOOKUP *ctx); + int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret); + int (*get_by_subject) (X509_LOOKUP *ctx, int type, X509_NAME *name, + X509_OBJECT *ret); + int (*get_by_issuer_serial) (X509_LOOKUP *ctx, int type, X509_NAME *name, + ASN1_INTEGER *serial, X509_OBJECT *ret); + int (*get_by_fingerprint) (X509_LOOKUP *ctx, int type, + unsigned char *bytes, int len, + X509_OBJECT *ret); + int (*get_by_alias) (X509_LOOKUP *ctx, int type, char *str, int len, + X509_OBJECT *ret); +} X509_LOOKUP_METHOD; + +typedef struct X509_VERIFY_PARAM_ID_st X509_VERIFY_PARAM_ID; + +/* + * This structure hold all parameters associated with a verify operation by + * including an X509_VERIFY_PARAM structure in related structures the + * parameters used can be customized + */ + +typedef struct X509_VERIFY_PARAM_st { + char *name; + time_t check_time; /* Time to use */ + unsigned long inh_flags; /* Inheritance flags */ + unsigned long flags; /* Various verify flags */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + int depth; /* Verify depth */ + STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ + X509_VERIFY_PARAM_ID *id; /* opaque ID data */ +} X509_VERIFY_PARAM; + +DECLARE_STACK_OF(X509_VERIFY_PARAM) + +/* + * This is used to hold everything. It is used for all certificate + * validation. Once we have a certificate chain, the 'verify' function is + * then called to actually check the cert chain. + */ +struct x509_store_st { + /* The following is a cache of trusted certs */ + int cache; /* if true, stash any hits */ + STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ + /* These are external lookup methods */ + STACK_OF(X509_LOOKUP) *get_cert_methods; + X509_VERIFY_PARAM *param; + /* Callbacks for various operations */ + /* called to verify a certificate */ + int (*verify) (X509_STORE_CTX *ctx); + /* error callback */ + int (*verify_cb) (int ok, X509_STORE_CTX *ctx); + /* get issuers cert from ctx */ + int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + /* check issued */ + int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer); + /* Check revocation status of chain */ + int (*check_revocation) (X509_STORE_CTX *ctx); + /* retrieve CRL */ + int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); + /* Check CRL validity */ + int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl); + /* Check certificate against CRL */ + int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); + STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup) (X509_STORE_CTX *ctx); + CRYPTO_EX_DATA ex_data; + int references; +} /* X509_STORE */ ; + +int X509_STORE_set_depth(X509_STORE *store, int depth); + +# define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func)) +# define X509_STORE_set_verify_func(ctx,func) ((ctx)->verify=(func)) + +/* This is the functions plus an instance of the local variables. */ +struct x509_lookup_st { + int init; /* have we been started */ + int skip; /* don't use us. */ + X509_LOOKUP_METHOD *method; /* the functions */ + char *method_data; /* method data */ + X509_STORE *store_ctx; /* who owns us */ +} /* X509_LOOKUP */ ; + +/* + * This is a used when verifying cert chains. Since the gathering of the + * cert chain can take some time (and have to be 'retried', this needs to be + * kept and passed around. + */ +struct x509_store_ctx_st { /* X509_STORE_CTX */ + X509_STORE *ctx; + /* used when looking up certs */ + int current_method; + /* The following are set by the caller */ + /* The cert to check */ + X509 *cert; + /* chain of X509s - untrusted - passed in */ + STACK_OF(X509) *untrusted; + /* set of CRLs passed in */ + STACK_OF(X509_CRL) *crls; + X509_VERIFY_PARAM *param; + /* Other info for use with get_issuer() */ + void *other_ctx; + /* Callbacks for various operations */ + /* called to verify a certificate */ + int (*verify) (X509_STORE_CTX *ctx); + /* error callback */ + int (*verify_cb) (int ok, X509_STORE_CTX *ctx); + /* get issuers cert from ctx */ + int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + /* check issued */ + int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer); + /* Check revocation status of chain */ + int (*check_revocation) (X509_STORE_CTX *ctx); + /* retrieve CRL */ + int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); + /* Check CRL validity */ + int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl); + /* Check certificate against CRL */ + int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); + int (*check_policy) (X509_STORE_CTX *ctx); + STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm); + int (*cleanup) (X509_STORE_CTX *ctx); + /* The following is built up */ + /* if 0, rebuild chain */ + int valid; + /* index of last untrusted cert */ + int last_untrusted; + /* chain of X509s - built up and trusted */ + STACK_OF(X509) *chain; + /* Valid policy tree */ + X509_POLICY_TREE *tree; + /* Require explicit policy value */ + int explicit_policy; + /* When something goes wrong, this is why */ + int error_depth; + int error; + X509 *current_cert; + /* cert currently being tested as valid issuer */ + X509 *current_issuer; + /* current CRL */ + X509_CRL *current_crl; + /* score of current CRL */ + int current_crl_score; + /* Reason mask */ + unsigned int current_reasons; + /* For CRL path validation: parent context */ + X509_STORE_CTX *parent; + CRYPTO_EX_DATA ex_data; +} /* X509_STORE_CTX */ ; + +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); + +# define X509_STORE_CTX_set_app_data(ctx,data) \ + X509_STORE_CTX_set_ex_data(ctx,0,data) +# define X509_STORE_CTX_get_app_data(ctx) \ + X509_STORE_CTX_get_ex_data(ctx,0) + +# define X509_L_FILE_LOAD 1 +# define X509_L_ADD_DIR 2 + +# define X509_LOOKUP_load_file(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) + +# define X509_LOOKUP_add_dir(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) + +# define X509_V_OK 0 +# define X509_V_ERR_UNSPECIFIED 1 + +# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 +# define X509_V_ERR_UNABLE_TO_GET_CRL 3 +# define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4 +# define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5 +# define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6 +# define X509_V_ERR_CERT_SIGNATURE_FAILURE 7 +# define X509_V_ERR_CRL_SIGNATURE_FAILURE 8 +# define X509_V_ERR_CERT_NOT_YET_VALID 9 +# define X509_V_ERR_CERT_HAS_EXPIRED 10 +# define X509_V_ERR_CRL_NOT_YET_VALID 11 +# define X509_V_ERR_CRL_HAS_EXPIRED 12 +# define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13 +# define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14 +# define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15 +# define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16 +# define X509_V_ERR_OUT_OF_MEM 17 +# define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 +# define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 +# define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 +# define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 +# define X509_V_ERR_CERT_CHAIN_TOO_LONG 22 +# define X509_V_ERR_CERT_REVOKED 23 +# define X509_V_ERR_INVALID_CA 24 +# define X509_V_ERR_PATH_LENGTH_EXCEEDED 25 +# define X509_V_ERR_INVALID_PURPOSE 26 +# define X509_V_ERR_CERT_UNTRUSTED 27 +# define X509_V_ERR_CERT_REJECTED 28 +/* These are 'informational' when looking for issuer cert */ +# define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29 +# define X509_V_ERR_AKID_SKID_MISMATCH 30 +# define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31 +# define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32 + +# define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33 +# define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34 +# define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35 +# define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36 +# define X509_V_ERR_INVALID_NON_CA 37 +# define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38 +# define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39 +# define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40 + +# define X509_V_ERR_INVALID_EXTENSION 41 +# define X509_V_ERR_INVALID_POLICY_EXTENSION 42 +# define X509_V_ERR_NO_EXPLICIT_POLICY 43 +# define X509_V_ERR_DIFFERENT_CRL_SCOPE 44 +# define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45 + +# define X509_V_ERR_UNNESTED_RESOURCE 46 + +# define X509_V_ERR_PERMITTED_VIOLATION 47 +# define X509_V_ERR_EXCLUDED_VIOLATION 48 +# define X509_V_ERR_SUBTREE_MINMAX 49 +# define X509_V_ERR_APPLICATION_VERIFICATION 50 +# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51 +# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52 +# define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53 +# define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54 + +/* Suite B mode algorithm violation */ +# define X509_V_ERR_SUITE_B_INVALID_VERSION 56 +# define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57 +# define X509_V_ERR_SUITE_B_INVALID_CURVE 58 +# define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59 +# define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60 +# define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61 + +/* Host, email and IP check errors */ +# define X509_V_ERR_HOSTNAME_MISMATCH 62 +# define X509_V_ERR_EMAIL_MISMATCH 63 +# define X509_V_ERR_IP_ADDRESS_MISMATCH 64 + +/* Caller error */ +# define X509_V_ERR_INVALID_CALL 65 +/* Issuer lookup error */ +# define X509_V_ERR_STORE_LOOKUP 66 + +# define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION 67 + +/* Certificate verify flags */ + +/* Send issuer+subject checks to verify_cb */ +# define X509_V_FLAG_CB_ISSUER_CHECK 0x1 +/* Use check time instead of current time */ +# define X509_V_FLAG_USE_CHECK_TIME 0x2 +/* Lookup CRLs */ +# define X509_V_FLAG_CRL_CHECK 0x4 +/* Lookup CRLs for whole chain */ +# define X509_V_FLAG_CRL_CHECK_ALL 0x8 +/* Ignore unhandled critical extensions */ +# define X509_V_FLAG_IGNORE_CRITICAL 0x10 +/* Disable workarounds for broken certificates */ +# define X509_V_FLAG_X509_STRICT 0x20 +/* Enable proxy certificate validation */ +# define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40 +/* Enable policy checking */ +# define X509_V_FLAG_POLICY_CHECK 0x80 +/* Policy variable require-explicit-policy */ +# define X509_V_FLAG_EXPLICIT_POLICY 0x100 +/* Policy variable inhibit-any-policy */ +# define X509_V_FLAG_INHIBIT_ANY 0x200 +/* Policy variable inhibit-policy-mapping */ +# define X509_V_FLAG_INHIBIT_MAP 0x400 +/* Notify callback that policy is OK */ +# define X509_V_FLAG_NOTIFY_POLICY 0x800 +/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */ +# define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000 +/* Delta CRL support */ +# define X509_V_FLAG_USE_DELTAS 0x2000 +/* Check selfsigned CA signature */ +# define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 +/* Use trusted store first */ +# define X509_V_FLAG_TRUSTED_FIRST 0x8000 +/* Suite B 128 bit only mode: not normally used */ +# define X509_V_FLAG_SUITEB_128_LOS_ONLY 0x10000 +/* Suite B 192 bit only mode */ +# define X509_V_FLAG_SUITEB_192_LOS 0x20000 +/* Suite B 128 bit mode allowing 192 bit algorithms */ +# define X509_V_FLAG_SUITEB_128_LOS 0x30000 + +/* Allow partial chains if at least one certificate is in trusted store */ +# define X509_V_FLAG_PARTIAL_CHAIN 0x80000 +/* + * If the initial chain is not trusted, do not attempt to build an alternative + * chain. Alternate chain checking was introduced in 1.0.2b. Setting this flag + * will force the behaviour to match that of previous versions. + */ +# define X509_V_FLAG_NO_ALT_CHAINS 0x100000 + +# define X509_VP_FLAG_DEFAULT 0x1 +# define X509_VP_FLAG_OVERWRITE 0x2 +# define X509_VP_FLAG_RESET_FLAGS 0x4 +# define X509_VP_FLAG_LOCKED 0x8 +# define X509_VP_FLAG_ONCE 0x10 + +/* Internal use: mask of policy related options */ +# define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \ + | X509_V_FLAG_EXPLICIT_POLICY \ + | X509_V_FLAG_INHIBIT_ANY \ + | X509_V_FLAG_INHIBIT_MAP) + +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, + int type, X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, + X509_OBJECT *x); +void X509_OBJECT_up_ref_count(X509_OBJECT *a); +void X509_OBJECT_free_contents(X509_OBJECT *a); +X509_STORE *X509_STORE_new(void); +void X509_STORE_free(X509_STORE *v); + +STACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); +STACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *st, X509_NAME *nm); +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); +int X509_STORE_set_trust(X509_STORE *ctx, int trust); +int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm); + +void X509_STORE_set_verify_cb(X509_STORE *ctx, + int (*verify_cb) (int, X509_STORE_CTX *)); + +void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx, + STACK_OF(X509_CRL) *(*cb) (X509_STORE_CTX + *ctx, + X509_NAME *nm)); + +X509_STORE_CTX *X509_STORE_CTX_new(void); + +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx); +int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); +void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); + +X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); + +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); +X509_LOOKUP_METHOD *X509_LOOKUP_file(void); + +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + +int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name, + X509_OBJECT *ret); + +int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); + +# ifndef OPENSSL_NO_STDIO +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); +# endif + +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); +void X509_LOOKUP_free(X509_LOOKUP *ctx); +int X509_LOOKUP_init(X509_LOOKUP *ctx); +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name, + X509_OBJECT *ret); +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name, + ASN1_INTEGER *serial, X509_OBJECT *ret); +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type, + unsigned char *bytes, int len, + X509_OBJECT *ret); +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len, + X509_OBJECT *ret); +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); + +# ifndef OPENSSL_NO_STDIO +int X509_STORE_load_locations(X509_STORE *ctx, + const char *file, const char *dir); +int X509_STORE_set_default_paths(X509_STORE *ctx); +# endif + +int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data); +void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx); +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s); +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx); +X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_cert(X509_STORE_CTX *c, X509 *x); +void X509_STORE_CTX_set_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk); +void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk); +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust); +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags); +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, + time_t t); +void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + int (*verify_cb) (int, X509_STORE_CTX *)); + +X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx); +int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx); + +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); +int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name); + +/* X509_VERIFY_PARAM functions */ + +X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); +void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name); +int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose); +int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust); +void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth); +void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t); +int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, + ASN1_OBJECT *policy); +int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, + STACK_OF(ASN1_OBJECT) *policies); + +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen); +int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen); +void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags); +char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *); +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, + const char *email, size_t emaillen); +int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, + const unsigned char *ip, size_t iplen); +int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, + const char *ipasc); + +int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); +const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param); + +int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_get_count(void); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name); +void X509_VERIFY_PARAM_table_cleanup(void); + +int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, + STACK_OF(X509) *certs, + STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags); + +void X509_policy_tree_free(X509_POLICY_TREE *tree); + +int X509_policy_tree_level_count(const X509_POLICY_TREE *tree); +X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, + int i); + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const + X509_POLICY_TREE + *tree); + +STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const + X509_POLICY_TREE + *tree); + +int X509_policy_level_node_count(X509_POLICY_LEVEL *level); + +X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, + int i); + +const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node); + +STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const + X509_POLICY_NODE + *node); +const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE + *node); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/include/openssl/x509v3.h b/optee/optee_test/host/openssl/include/openssl/x509v3.h new file mode 100644 index 0000000..f5c6156 --- /dev/null +++ b/optee/optee_test/host/openssl/include/openssl/x509v3.h @@ -0,0 +1,1055 @@ +/* x509v3.h */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project + * 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (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 product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef HEADER_X509V3_H +# define HEADER_X509V3_H + +# include +# include +# include + +#ifdef __cplusplus +extern "C" { +#endif + +# ifdef OPENSSL_SYS_WIN32 +/* Under Win32 these are defined in wincrypt.h */ +# undef X509_NAME +# undef X509_CERT_PAIR +# undef X509_EXTENSIONS +# endif + +/* Forward reference */ +struct v3_ext_method; +struct v3_ext_ctx; + +/* Useful typedefs */ + +typedef void *(*X509V3_EXT_NEW)(void); +typedef void (*X509V3_EXT_FREE) (void *); +typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long); +typedef int (*X509V3_EXT_I2D) (void *, unsigned char **); +typedef STACK_OF(CONF_VALUE) * + (*X509V3_EXT_I2V) (const struct v3_ext_method *method, void *ext, + STACK_OF(CONF_VALUE) *extlist); +typedef void *(*X509V3_EXT_V2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE) *values); +typedef char *(*X509V3_EXT_I2S)(const struct v3_ext_method *method, + void *ext); +typedef void *(*X509V3_EXT_S2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); +typedef int (*X509V3_EXT_I2R) (const struct v3_ext_method *method, void *ext, + BIO *out, int indent); +typedef void *(*X509V3_EXT_R2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); + +/* V3 extension structure */ + +struct v3_ext_method { + int ext_nid; + int ext_flags; +/* If this is set the following four fields are ignored */ + ASN1_ITEM_EXP *it; +/* Old style ASN1 calls */ + X509V3_EXT_NEW ext_new; + X509V3_EXT_FREE ext_free; + X509V3_EXT_D2I d2i; + X509V3_EXT_I2D i2d; +/* The following pair is used for string extensions */ + X509V3_EXT_I2S i2s; + X509V3_EXT_S2I s2i; +/* The following pair is used for multi-valued extensions */ + X509V3_EXT_I2V i2v; + X509V3_EXT_V2I v2i; +/* The following are used for raw extensions */ + X509V3_EXT_I2R i2r; + X509V3_EXT_R2I r2i; + void *usr_data; /* Any extension specific data */ +}; + +typedef struct X509V3_CONF_METHOD_st { + char *(*get_string) (void *db, char *section, char *value); + STACK_OF(CONF_VALUE) *(*get_section) (void *db, char *section); + void (*free_string) (void *db, char *string); + void (*free_section) (void *db, STACK_OF(CONF_VALUE) *section); +} X509V3_CONF_METHOD; + +/* Context specific info */ +struct v3_ext_ctx { +# define CTX_TEST 0x1 + int flags; + X509 *issuer_cert; + X509 *subject_cert; + X509_REQ *subject_req; + X509_CRL *crl; + X509V3_CONF_METHOD *db_meth; + void *db; +/* Maybe more here */ +}; + +typedef struct v3_ext_method X509V3_EXT_METHOD; + +DECLARE_STACK_OF(X509V3_EXT_METHOD) + +/* ext_flags values */ +# define X509V3_EXT_DYNAMIC 0x1 +# define X509V3_EXT_CTX_DEP 0x2 +# define X509V3_EXT_MULTILINE 0x4 + +typedef BIT_STRING_BITNAME ENUMERATED_NAMES; + +typedef struct BASIC_CONSTRAINTS_st { + int ca; + ASN1_INTEGER *pathlen; +} BASIC_CONSTRAINTS; + +typedef struct PKEY_USAGE_PERIOD_st { + ASN1_GENERALIZEDTIME *notBefore; + ASN1_GENERALIZEDTIME *notAfter; +} PKEY_USAGE_PERIOD; + +typedef struct otherName_st { + ASN1_OBJECT *type_id; + ASN1_TYPE *value; +} OTHERNAME; + +typedef struct EDIPartyName_st { + ASN1_STRING *nameAssigner; + ASN1_STRING *partyName; +} EDIPARTYNAME; + +typedef struct GENERAL_NAME_st { +# define GEN_OTHERNAME 0 +# define GEN_EMAIL 1 +# define GEN_DNS 2 +# define GEN_X400 3 +# define GEN_DIRNAME 4 +# define GEN_EDIPARTY 5 +# define GEN_URI 6 +# define GEN_IPADD 7 +# define GEN_RID 8 + int type; + union { + char *ptr; + OTHERNAME *otherName; /* otherName */ + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; + ASN1_TYPE *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; + ASN1_OCTET_STRING *iPAddress; + ASN1_OBJECT *registeredID; + /* Old names */ + ASN1_OCTET_STRING *ip; /* iPAddress */ + X509_NAME *dirn; /* dirn */ + ASN1_IA5STRING *ia5; /* rfc822Name, dNSName, + * uniformResourceIdentifier */ + ASN1_OBJECT *rid; /* registeredID */ + ASN1_TYPE *other; /* x400Address */ + } d; +} GENERAL_NAME; + +typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; + +typedef struct ACCESS_DESCRIPTION_st { + ASN1_OBJECT *method; + GENERAL_NAME *location; +} ACCESS_DESCRIPTION; + +typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; + +typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE; + +DECLARE_STACK_OF(GENERAL_NAME) +DECLARE_ASN1_SET_OF(GENERAL_NAME) + +DECLARE_STACK_OF(ACCESS_DESCRIPTION) +DECLARE_ASN1_SET_OF(ACCESS_DESCRIPTION) + +typedef struct DIST_POINT_NAME_st { + int type; + union { + GENERAL_NAMES *fullname; + STACK_OF(X509_NAME_ENTRY) *relativename; + } name; +/* If relativename then this contains the full distribution point name */ + X509_NAME *dpname; +} DIST_POINT_NAME; +/* All existing reasons */ +# define CRLDP_ALL_REASONS 0x807f + +# define CRL_REASON_NONE -1 +# define CRL_REASON_UNSPECIFIED 0 +# define CRL_REASON_KEY_COMPROMISE 1 +# define CRL_REASON_CA_COMPROMISE 2 +# define CRL_REASON_AFFILIATION_CHANGED 3 +# define CRL_REASON_SUPERSEDED 4 +# define CRL_REASON_CESSATION_OF_OPERATION 5 +# define CRL_REASON_CERTIFICATE_HOLD 6 +# define CRL_REASON_REMOVE_FROM_CRL 8 +# define CRL_REASON_PRIVILEGE_WITHDRAWN 9 +# define CRL_REASON_AA_COMPROMISE 10 + +struct DIST_POINT_st { + DIST_POINT_NAME *distpoint; + ASN1_BIT_STRING *reasons; + GENERAL_NAMES *CRLissuer; + int dp_reasons; +}; + +typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS; + +DECLARE_STACK_OF(DIST_POINT) +DECLARE_ASN1_SET_OF(DIST_POINT) + +struct AUTHORITY_KEYID_st { + ASN1_OCTET_STRING *keyid; + GENERAL_NAMES *issuer; + ASN1_INTEGER *serial; +}; + +/* Strong extranet structures */ + +typedef struct SXNET_ID_st { + ASN1_INTEGER *zone; + ASN1_OCTET_STRING *user; +} SXNETID; + +DECLARE_STACK_OF(SXNETID) +DECLARE_ASN1_SET_OF(SXNETID) + +typedef struct SXNET_st { + ASN1_INTEGER *version; + STACK_OF(SXNETID) *ids; +} SXNET; + +typedef struct NOTICEREF_st { + ASN1_STRING *organization; + STACK_OF(ASN1_INTEGER) *noticenos; +} NOTICEREF; + +typedef struct USERNOTICE_st { + NOTICEREF *noticeref; + ASN1_STRING *exptext; +} USERNOTICE; + +typedef struct POLICYQUALINFO_st { + ASN1_OBJECT *pqualid; + union { + ASN1_IA5STRING *cpsuri; + USERNOTICE *usernotice; + ASN1_TYPE *other; + } d; +} POLICYQUALINFO; + +DECLARE_STACK_OF(POLICYQUALINFO) +DECLARE_ASN1_SET_OF(POLICYQUALINFO) + +typedef struct POLICYINFO_st { + ASN1_OBJECT *policyid; + STACK_OF(POLICYQUALINFO) *qualifiers; +} POLICYINFO; + +typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES; + +DECLARE_STACK_OF(POLICYINFO) +DECLARE_ASN1_SET_OF(POLICYINFO) + +typedef struct POLICY_MAPPING_st { + ASN1_OBJECT *issuerDomainPolicy; + ASN1_OBJECT *subjectDomainPolicy; +} POLICY_MAPPING; + +DECLARE_STACK_OF(POLICY_MAPPING) + +typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS; + +typedef struct GENERAL_SUBTREE_st { + GENERAL_NAME *base; + ASN1_INTEGER *minimum; + ASN1_INTEGER *maximum; +} GENERAL_SUBTREE; + +DECLARE_STACK_OF(GENERAL_SUBTREE) + +struct NAME_CONSTRAINTS_st { + STACK_OF(GENERAL_SUBTREE) *permittedSubtrees; + STACK_OF(GENERAL_SUBTREE) *excludedSubtrees; +}; + +typedef struct POLICY_CONSTRAINTS_st { + ASN1_INTEGER *requireExplicitPolicy; + ASN1_INTEGER *inhibitPolicyMapping; +} POLICY_CONSTRAINTS; + +/* Proxy certificate structures, see RFC 3820 */ +typedef struct PROXY_POLICY_st { + ASN1_OBJECT *policyLanguage; + ASN1_OCTET_STRING *policy; +} PROXY_POLICY; + +typedef struct PROXY_CERT_INFO_EXTENSION_st { + ASN1_INTEGER *pcPathLengthConstraint; + PROXY_POLICY *proxyPolicy; +} PROXY_CERT_INFO_EXTENSION; + +DECLARE_ASN1_FUNCTIONS(PROXY_POLICY) +DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION) + +struct ISSUING_DIST_POINT_st { + DIST_POINT_NAME *distpoint; + int onlyuser; + int onlyCA; + ASN1_BIT_STRING *onlysomereasons; + int indirectCRL; + int onlyattr; +}; + +/* Values in idp_flags field */ +/* IDP present */ +# define IDP_PRESENT 0x1 +/* IDP values inconsistent */ +# define IDP_INVALID 0x2 +/* onlyuser true */ +# define IDP_ONLYUSER 0x4 +/* onlyCA true */ +# define IDP_ONLYCA 0x8 +/* onlyattr true */ +# define IDP_ONLYATTR 0x10 +/* indirectCRL true */ +# define IDP_INDIRECT 0x20 +/* onlysomereasons present */ +# define IDP_REASONS 0x40 + +# define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \ +",name:", val->name, ",value:", val->value); + +# define X509V3_set_ctx_test(ctx) \ + X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST) +# define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL; + +# define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \ + 0,0,0,0, \ + 0,0, \ + (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \ + (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \ + NULL, NULL, \ + table} + +# define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \ + 0,0,0,0, \ + (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \ + (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \ + 0,0,0,0, \ + NULL} + +# define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + +/* X509_PURPOSE stuff */ + +# define EXFLAG_BCONS 0x1 +# define EXFLAG_KUSAGE 0x2 +# define EXFLAG_XKUSAGE 0x4 +# define EXFLAG_NSCERT 0x8 + +# define EXFLAG_CA 0x10 +/* Really self issued not necessarily self signed */ +# define EXFLAG_SI 0x20 +# define EXFLAG_V1 0x40 +# define EXFLAG_INVALID 0x80 +# define EXFLAG_SET 0x100 +# define EXFLAG_CRITICAL 0x200 +# define EXFLAG_PROXY 0x400 + +# define EXFLAG_INVALID_POLICY 0x800 +# define EXFLAG_FRESHEST 0x1000 +/* Self signed */ +# define EXFLAG_SS 0x2000 + +# define KU_DIGITAL_SIGNATURE 0x0080 +# define KU_NON_REPUDIATION 0x0040 +# define KU_KEY_ENCIPHERMENT 0x0020 +# define KU_DATA_ENCIPHERMENT 0x0010 +# define KU_KEY_AGREEMENT 0x0008 +# define KU_KEY_CERT_SIGN 0x0004 +# define KU_CRL_SIGN 0x0002 +# define KU_ENCIPHER_ONLY 0x0001 +# define KU_DECIPHER_ONLY 0x8000 + +# define NS_SSL_CLIENT 0x80 +# define NS_SSL_SERVER 0x40 +# define NS_SMIME 0x20 +# define NS_OBJSIGN 0x10 +# define NS_SSL_CA 0x04 +# define NS_SMIME_CA 0x02 +# define NS_OBJSIGN_CA 0x01 +# define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) + +# define XKU_SSL_SERVER 0x1 +# define XKU_SSL_CLIENT 0x2 +# define XKU_SMIME 0x4 +# define XKU_CODE_SIGN 0x8 +# define XKU_SGC 0x10 +# define XKU_OCSP_SIGN 0x20 +# define XKU_TIMESTAMP 0x40 +# define XKU_DVCS 0x80 +# define XKU_ANYEKU 0x100 + +# define X509_PURPOSE_DYNAMIC 0x1 +# define X509_PURPOSE_DYNAMIC_NAME 0x2 + +typedef struct x509_purpose_st { + int purpose; + int trust; /* Default trust ID */ + int flags; + int (*check_purpose) (const struct x509_purpose_st *, const X509 *, int); + char *name; + char *sname; + void *usr_data; +} X509_PURPOSE; + +# define X509_PURPOSE_SSL_CLIENT 1 +# define X509_PURPOSE_SSL_SERVER 2 +# define X509_PURPOSE_NS_SSL_SERVER 3 +# define X509_PURPOSE_SMIME_SIGN 4 +# define X509_PURPOSE_SMIME_ENCRYPT 5 +# define X509_PURPOSE_CRL_SIGN 6 +# define X509_PURPOSE_ANY 7 +# define X509_PURPOSE_OCSP_HELPER 8 +# define X509_PURPOSE_TIMESTAMP_SIGN 9 + +# define X509_PURPOSE_MIN 1 +# define X509_PURPOSE_MAX 9 + +/* Flags for X509V3_EXT_print() */ + +# define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +# define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +# define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +# define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +# define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +/* Flags for X509V3_add1_i2d */ + +# define X509V3_ADD_OP_MASK 0xfL +# define X509V3_ADD_DEFAULT 0L +# define X509V3_ADD_APPEND 1L +# define X509V3_ADD_REPLACE 2L +# define X509V3_ADD_REPLACE_EXISTING 3L +# define X509V3_ADD_KEEP_EXISTING 4L +# define X509V3_ADD_DELETE 5L +# define X509V3_ADD_SILENT 0x10 + +DECLARE_STACK_OF(X509_PURPOSE) + +DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS) + +DECLARE_ASN1_FUNCTIONS(SXNET) +DECLARE_ASN1_FUNCTIONS(SXNETID) + +int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen); +int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user, + int userlen); +int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, char *user, + int userlen); + +ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone); +ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone); +ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone); + +DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID) + +DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD) + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAME) +GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a); +int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b); + +ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); +STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *extlist); + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, + GENERAL_NAME *gen, + STACK_OF(CONF_VALUE) *ret); +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen); + +DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES) + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + GENERAL_NAMES *gen, + STACK_OF(CONF_VALUE) *extlist); +GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +DECLARE_ASN1_FUNCTIONS(OTHERNAME) +DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME) +int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b); +void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value); +void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype); +int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, + ASN1_OBJECT *oid, ASN1_TYPE *value); +int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, + ASN1_OBJECT **poid, ASN1_TYPE **pvalue); + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + ASN1_OCTET_STRING *ia5); +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); + +DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE) +int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION *a); + +DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES) +DECLARE_ASN1_FUNCTIONS(POLICYINFO) +DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO) +DECLARE_ASN1_FUNCTIONS(USERNOTICE) +DECLARE_ASN1_FUNCTIONS(NOTICEREF) + +DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS) +DECLARE_ASN1_FUNCTIONS(DIST_POINT) +DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME) +DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT) + +int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname); + +int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc); + +DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION) +DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS) + +DECLARE_ASN1_ITEM(POLICY_MAPPING) +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING) +DECLARE_ASN1_ITEM(POLICY_MAPPINGS) + +DECLARE_ASN1_ITEM(GENERAL_SUBTREE) +DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE) + +DECLARE_ASN1_ITEM(NAME_CONSTRAINTS) +DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS) + +DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS) +DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS) + +GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, int gen_type, char *value, + int is_nc); + +# ifdef HEADER_CONF_H +GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf); +GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, + int is_nc); +void X509V3_conf_free(CONF_VALUE *val); + +X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, + char *value); +X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, + char *value); +int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, + STACK_OF(X509_EXTENSION) **sk); +int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, + X509 *cert); +int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, + X509_REQ *req); +int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, + X509_CRL *crl); + +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, + X509V3_CTX *ctx, int ext_nid, + char *value); +X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + char *name, char *value); +int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + char *section, X509 *cert); +int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + char *section, X509_REQ *req); +int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + char *section, X509_CRL *crl); + +int X509V3_add_value_bool_nf(char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool); +int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint); +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf); +void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash); +# endif + +char *X509V3_get_string(X509V3_CTX *ctx, char *name, char *section); +STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, char *section); +void X509V3_string_free(X509V3_CTX *ctx, char *str); +void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section); +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject, + X509_REQ *req, X509_CRL *crl, int flags); + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist); +char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint); +ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, char *value); +char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, ASN1_ENUMERATED *aint); +char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, + ASN1_ENUMERATED *aint); +int X509V3_EXT_add(X509V3_EXT_METHOD *ext); +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist); +int X509V3_EXT_add_alias(int nid_to, int nid_from); +void X509V3_EXT_cleanup(void); + +const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext); +const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid); +int X509V3_add_standard_extensions(void); +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line); +void *X509V3_EXT_d2i(X509_EXTENSION *ext); +void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, + int *idx); +int X509V3_EXT_free(int nid, void *ext_data); + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); +int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, + int crit, unsigned long flags); + +char *hex_to_string(const unsigned char *buffer, long len); +unsigned char *string_to_hex(const char *str, long *len); +int name_cmp(const char *name, const char *cmp); + +void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, + int ml); +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent); +int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent); + +int X509V3_extensions_print(BIO *out, char *title, + STACK_OF(X509_EXTENSION) *exts, + unsigned long flag, int indent); + +int X509_check_ca(X509 *x); +int X509_check_purpose(X509 *x, int id, int ca); +int X509_supported_extension(X509_EXTENSION *ex); +int X509_PURPOSE_set(int *p, int purpose); +int X509_check_issued(X509 *issuer, X509 *subject); +int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid); +int X509_PURPOSE_get_count(void); +X509_PURPOSE *X509_PURPOSE_get0(int idx); +int X509_PURPOSE_get_by_sname(char *sname); +int X509_PURPOSE_get_by_id(int id); +int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck) (const X509_PURPOSE *, const X509 *, int), + char *name, char *sname, void *arg); +char *X509_PURPOSE_get0_name(X509_PURPOSE *xp); +char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp); +int X509_PURPOSE_get_trust(X509_PURPOSE *xp); +void X509_PURPOSE_cleanup(void); +int X509_PURPOSE_get_id(X509_PURPOSE *); + +STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x); +STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x); +void X509_email_free(STACK_OF(OPENSSL_STRING) *sk); +STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x); +/* Flags for X509_check_* functions */ + +/* + * Always check subject name for host match even if subject alt names present + */ +# define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 +/* Disable wildcard matching for dnsName fields and common name. */ +# define X509_CHECK_FLAG_NO_WILDCARDS 0x2 +/* Wildcards must not match a partial label. */ +# define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0x4 +/* Allow (non-partial) wildcards to match multiple labels. */ +# define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0x8 +/* Constraint verifier subdomain patterns to match a single labels. */ +# define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0x10 +/* + * Match reference identifiers starting with "." to any sub-domain. + * This is a non-public flag, turned on implicitly when the subject + * reference identity is a DNS name. + */ +# define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000 + +int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername); +int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags); +int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags); +int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags); + +ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); +ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc); +int a2i_ipadd(unsigned char *ipout, const char *ipasc); +int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, + unsigned long chtype); + +void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent); +DECLARE_STACK_OF(X509_POLICY_NODE) + +# ifndef OPENSSL_NO_RFC3779 + +typedef struct ASRange_st { + ASN1_INTEGER *min, *max; +} ASRange; + +# define ASIdOrRange_id 0 +# define ASIdOrRange_range 1 + +typedef struct ASIdOrRange_st { + int type; + union { + ASN1_INTEGER *id; + ASRange *range; + } u; +} ASIdOrRange; + +typedef STACK_OF(ASIdOrRange) ASIdOrRanges; +DECLARE_STACK_OF(ASIdOrRange) + +# define ASIdentifierChoice_inherit 0 +# define ASIdentifierChoice_asIdsOrRanges 1 + +typedef struct ASIdentifierChoice_st { + int type; + union { + ASN1_NULL *inherit; + ASIdOrRanges *asIdsOrRanges; + } u; +} ASIdentifierChoice; + +typedef struct ASIdentifiers_st { + ASIdentifierChoice *asnum, *rdi; +} ASIdentifiers; + +DECLARE_ASN1_FUNCTIONS(ASRange) +DECLARE_ASN1_FUNCTIONS(ASIdOrRange) +DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice) +DECLARE_ASN1_FUNCTIONS(ASIdentifiers) + +typedef struct IPAddressRange_st { + ASN1_BIT_STRING *min, *max; +} IPAddressRange; + +# define IPAddressOrRange_addressPrefix 0 +# define IPAddressOrRange_addressRange 1 + +typedef struct IPAddressOrRange_st { + int type; + union { + ASN1_BIT_STRING *addressPrefix; + IPAddressRange *addressRange; + } u; +} IPAddressOrRange; + +typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges; +DECLARE_STACK_OF(IPAddressOrRange) + +# define IPAddressChoice_inherit 0 +# define IPAddressChoice_addressesOrRanges 1 + +typedef struct IPAddressChoice_st { + int type; + union { + ASN1_NULL *inherit; + IPAddressOrRanges *addressesOrRanges; + } u; +} IPAddressChoice; + +typedef struct IPAddressFamily_st { + ASN1_OCTET_STRING *addressFamily; + IPAddressChoice *ipAddressChoice; +} IPAddressFamily; + +typedef STACK_OF(IPAddressFamily) IPAddrBlocks; +DECLARE_STACK_OF(IPAddressFamily) + +DECLARE_ASN1_FUNCTIONS(IPAddressRange) +DECLARE_ASN1_FUNCTIONS(IPAddressOrRange) +DECLARE_ASN1_FUNCTIONS(IPAddressChoice) +DECLARE_ASN1_FUNCTIONS(IPAddressFamily) + +/* + * API tag for elements of the ASIdentifer SEQUENCE. + */ +# define V3_ASID_ASNUM 0 +# define V3_ASID_RDI 1 + +/* + * AFI values, assigned by IANA. It'd be nice to make the AFI + * handling code totally generic, but there are too many little things + * that would need to be defined for other address families for it to + * be worth the trouble. + */ +# define IANA_AFI_IPV4 1 +# define IANA_AFI_IPV6 2 + +/* + * Utilities to construct and extract values from RFC3779 extensions, + * since some of the encodings (particularly for IP address prefixes + * and ranges) are a bit tedious to work with directly. + */ +int v3_asid_add_inherit(ASIdentifiers *asid, int which); +int v3_asid_add_id_or_range(ASIdentifiers *asid, int which, + ASN1_INTEGER *min, ASN1_INTEGER *max); +int v3_addr_add_inherit(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi); +int v3_addr_add_prefix(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi, + unsigned char *a, const int prefixlen); +int v3_addr_add_range(IPAddrBlocks *addr, + const unsigned afi, const unsigned *safi, + unsigned char *min, unsigned char *max); +unsigned v3_addr_get_afi(const IPAddressFamily *f); +int v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi, + unsigned char *min, unsigned char *max, + const int length); + +/* + * Canonical forms. + */ +int v3_asid_is_canonical(ASIdentifiers *asid); +int v3_addr_is_canonical(IPAddrBlocks *addr); +int v3_asid_canonize(ASIdentifiers *asid); +int v3_addr_canonize(IPAddrBlocks *addr); + +/* + * Tests for inheritance and containment. + */ +int v3_asid_inherits(ASIdentifiers *asid); +int v3_addr_inherits(IPAddrBlocks *addr); +int v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b); +int v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b); + +/* + * Check whether RFC 3779 extensions nest properly in chains. + */ +int v3_asid_validate_path(X509_STORE_CTX *); +int v3_addr_validate_path(X509_STORE_CTX *); +int v3_asid_validate_resource_set(STACK_OF(X509) *chain, + ASIdentifiers *ext, int allow_inheritance); +int v3_addr_validate_resource_set(STACK_OF(X509) *chain, + IPAddrBlocks *ext, int allow_inheritance); + +# endif /* OPENSSL_NO_RFC3779 */ + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_X509V3_strings(void); + +/* Error codes for the X509V3 functions. */ + +/* Function codes. */ +# define X509V3_F_A2I_GENERAL_NAME 164 +# define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 161 +# define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 162 +# define X509V3_F_COPY_EMAIL 122 +# define X509V3_F_COPY_ISSUER 123 +# define X509V3_F_DO_DIRNAME 144 +# define X509V3_F_DO_EXT_CONF 124 +# define X509V3_F_DO_EXT_I2D 135 +# define X509V3_F_DO_EXT_NCONF 151 +# define X509V3_F_DO_I2V_NAME_CONSTRAINTS 148 +# define X509V3_F_GNAMES_FROM_SECTNAME 156 +# define X509V3_F_HEX_TO_STRING 111 +# define X509V3_F_I2S_ASN1_ENUMERATED 121 +# define X509V3_F_I2S_ASN1_IA5STRING 149 +# define X509V3_F_I2S_ASN1_INTEGER 120 +# define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138 +# define X509V3_F_NOTICE_SECTION 132 +# define X509V3_F_NREF_NOS 133 +# define X509V3_F_POLICY_SECTION 131 +# define X509V3_F_PROCESS_PCI_VALUE 150 +# define X509V3_F_R2I_CERTPOL 130 +# define X509V3_F_R2I_PCI 155 +# define X509V3_F_S2I_ASN1_IA5STRING 100 +# define X509V3_F_S2I_ASN1_INTEGER 108 +# define X509V3_F_S2I_ASN1_OCTET_STRING 112 +# define X509V3_F_S2I_ASN1_SKEY_ID 114 +# define X509V3_F_S2I_SKEY_ID 115 +# define X509V3_F_SET_DIST_POINT_NAME 158 +# define X509V3_F_STRING_TO_HEX 113 +# define X509V3_F_SXNET_ADD_ID_ASC 125 +# define X509V3_F_SXNET_ADD_ID_INTEGER 126 +# define X509V3_F_SXNET_ADD_ID_ULONG 127 +# define X509V3_F_SXNET_GET_ID_ASC 128 +# define X509V3_F_SXNET_GET_ID_ULONG 129 +# define X509V3_F_V2I_ASIDENTIFIERS 163 +# define X509V3_F_V2I_ASN1_BIT_STRING 101 +# define X509V3_F_V2I_AUTHORITY_INFO_ACCESS 139 +# define X509V3_F_V2I_AUTHORITY_KEYID 119 +# define X509V3_F_V2I_BASIC_CONSTRAINTS 102 +# define X509V3_F_V2I_CRLD 134 +# define X509V3_F_V2I_EXTENDED_KEY_USAGE 103 +# define X509V3_F_V2I_GENERAL_NAMES 118 +# define X509V3_F_V2I_GENERAL_NAME_EX 117 +# define X509V3_F_V2I_IDP 157 +# define X509V3_F_V2I_IPADDRBLOCKS 159 +# define X509V3_F_V2I_ISSUER_ALT 153 +# define X509V3_F_V2I_NAME_CONSTRAINTS 147 +# define X509V3_F_V2I_POLICY_CONSTRAINTS 146 +# define X509V3_F_V2I_POLICY_MAPPINGS 145 +# define X509V3_F_V2I_SUBJECT_ALT 154 +# define X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL 160 +# define X509V3_F_V3_GENERIC_EXTENSION 116 +# define X509V3_F_X509V3_ADD1_I2D 140 +# define X509V3_F_X509V3_ADD_VALUE 105 +# define X509V3_F_X509V3_EXT_ADD 104 +# define X509V3_F_X509V3_EXT_ADD_ALIAS 106 +# define X509V3_F_X509V3_EXT_CONF 107 +# define X509V3_F_X509V3_EXT_FREE 165 +# define X509V3_F_X509V3_EXT_I2D 136 +# define X509V3_F_X509V3_EXT_NCONF 152 +# define X509V3_F_X509V3_GET_SECTION 142 +# define X509V3_F_X509V3_GET_STRING 143 +# define X509V3_F_X509V3_GET_VALUE_BOOL 110 +# define X509V3_F_X509V3_PARSE_LIST 109 +# define X509V3_F_X509_PURPOSE_ADD 137 +# define X509V3_F_X509_PURPOSE_SET 141 + +/* Reason codes. */ +# define X509V3_R_BAD_IP_ADDRESS 118 +# define X509V3_R_BAD_OBJECT 119 +# define X509V3_R_BN_DEC2BN_ERROR 100 +# define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 101 +# define X509V3_R_CANNOT_FIND_FREE_FUNCTION 168 +# define X509V3_R_DIRNAME_ERROR 149 +# define X509V3_R_DISTPOINT_ALREADY_SET 160 +# define X509V3_R_DUPLICATE_ZONE_ID 133 +# define X509V3_R_ERROR_CONVERTING_ZONE 131 +# define X509V3_R_ERROR_CREATING_EXTENSION 144 +# define X509V3_R_ERROR_IN_EXTENSION 128 +# define X509V3_R_EXPECTED_A_SECTION_NAME 137 +# define X509V3_R_EXTENSION_EXISTS 145 +# define X509V3_R_EXTENSION_NAME_ERROR 115 +# define X509V3_R_EXTENSION_NOT_FOUND 102 +# define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 103 +# define X509V3_R_EXTENSION_VALUE_ERROR 116 +# define X509V3_R_ILLEGAL_EMPTY_EXTENSION 151 +# define X509V3_R_ILLEGAL_HEX_DIGIT 113 +# define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 152 +# define X509V3_R_INVALID_ASNUMBER 162 +# define X509V3_R_INVALID_ASRANGE 163 +# define X509V3_R_INVALID_BOOLEAN_STRING 104 +# define X509V3_R_INVALID_EXTENSION_STRING 105 +# define X509V3_R_INVALID_INHERITANCE 165 +# define X509V3_R_INVALID_IPADDRESS 166 +# define X509V3_R_INVALID_MULTIPLE_RDNS 161 +# define X509V3_R_INVALID_NAME 106 +# define X509V3_R_INVALID_NULL_ARGUMENT 107 +# define X509V3_R_INVALID_NULL_NAME 108 +# define X509V3_R_INVALID_NULL_VALUE 109 +# define X509V3_R_INVALID_NUMBER 140 +# define X509V3_R_INVALID_NUMBERS 141 +# define X509V3_R_INVALID_OBJECT_IDENTIFIER 110 +# define X509V3_R_INVALID_OPTION 138 +# define X509V3_R_INVALID_POLICY_IDENTIFIER 134 +# define X509V3_R_INVALID_PROXY_POLICY_SETTING 153 +# define X509V3_R_INVALID_PURPOSE 146 +# define X509V3_R_INVALID_SAFI 164 +# define X509V3_R_INVALID_SECTION 135 +# define X509V3_R_INVALID_SYNTAX 143 +# define X509V3_R_ISSUER_DECODE_ERROR 126 +# define X509V3_R_MISSING_VALUE 124 +# define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 142 +# define X509V3_R_NO_CONFIG_DATABASE 136 +# define X509V3_R_NO_ISSUER_CERTIFICATE 121 +# define X509V3_R_NO_ISSUER_DETAILS 127 +# define X509V3_R_NO_POLICY_IDENTIFIER 139 +# define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 154 +# define X509V3_R_NO_PUBLIC_KEY 114 +# define X509V3_R_NO_SUBJECT_DETAILS 125 +# define X509V3_R_ODD_NUMBER_OF_DIGITS 112 +# define X509V3_R_OPERATION_NOT_DEFINED 148 +# define X509V3_R_OTHERNAME_ERROR 147 +# define X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED 155 +# define X509V3_R_POLICY_PATH_LENGTH 156 +# define X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED 157 +# define X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED 158 +# define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 159 +# define X509V3_R_SECTION_NOT_FOUND 150 +# define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 122 +# define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 123 +# define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 111 +# define X509V3_R_UNKNOWN_EXTENSION 129 +# define X509V3_R_UNKNOWN_EXTENSION_NAME 130 +# define X509V3_R_UNKNOWN_OPTION 120 +# define X509V3_R_UNSUPPORTED_OPTION 117 +# define X509V3_R_UNSUPPORTED_TYPE 167 +# define X509V3_R_USER_TOO_LONG 132 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/optee/optee_test/host/openssl/lib/aarch64/libcrypto.a b/optee/optee_test/host/openssl/lib/aarch64/libcrypto.a new file mode 100644 index 0000000000000000000000000000000000000000..93330b884764eaf5b4b6b44eb3392225276badb2 GIT binary patch literal 3403202 zcmeFa4Vax*bsoAU8QIuiY+2Yw{u8n>*chW3S@KU(qS4Gq9xTmFW=4ulT8_`moRN+- zGiNwwMwU%);y4Mn^=%!XE@`=mV`v{5J1NOSfB+$cIE~ZNmLyKaIa*Y6Vi_A{M3=cR7loqJF0-ubLs_X4;LU*7A){l!!6v==>B z?=G2gr`5UF?RBT^xUb&rd%~SIzNP9G7Tjs2TN!kx9XsYu`@0`IHFw{q-D#)d{^_Ic zG`e3LSNGT(-D!0H=}>b2`AK)$pI&-$hxB>T8RPCnTkflO-}4#wqCGcN-8k@vrcUfW z^e*=z>wfKO_o9FO2KSe8_G5FL%3*|Ls9_-#}Qn(>Gk3yYG3YJALTQ^={$=?sU3? zpLeJKo!R8t%kK2fBkuII$K2^Zx+l5&Am=AGse9-_cl!Ij;7C?hl`Krw8|^U3dByKjBXQpP-+_o$;#AJ8{=+b7us%`w4f(KKKv3!JRSnMt8;! z982!aXSy@ycDXYSf1&E$4nFIC@?LkwPro_2KX}xg@kfujGoE^V9CCdvS2cvlm-;O51$WlD$6Q~x?MZjm ziQEnMyR+zaKkLr={^wpe_hXyfS*PND@zd_C;C}fF?yM8J-+tPi72IdL?yUdK+)K6| zbKg<7w8y>VRNdcy%)O*^|Lk7(61tz?o7@xcb}xPD=X3XttKCa~>Rq{e_)+)Lze0ER z+1I-7h}(ISJNrB3j=b5O9o&z6!JYl@KH<*(@6cc4UbgLg7v1;1)4eRXnGd^{S$8{V z|M(N`W&h%h&)=8$n$rt zjqcoU#oc?gJNIo1x%-DVxpRN|4es2Je88RiiMP3Pzj~kBbk?=GJO3uP>4k9D>~fn* zx9gp5(+_^S>gFDGo9K>y*ljun{U>vOf1}&dyP|t~>9(_qp@_(cSL6{~NzQ^SC?j zhC^wwcFg!{pO`^b3gYx+uY`U?mwOF zHurO%KhtgQ=f1enZ7$ujZ*-ea;9kCQ!JW`;y4St@WbU%}yO*D;8@$QA{FcwVmp38z z@15^n{tu?y%in%~)&0~5+{^3S`(W=cT>ahY{vG1+9}%CY-=OZfN8S0Szb$tctas-J zckP4jeCz(!neKe+8i(BZN8jtt|Ivlqy$4u7_W|&ps{4a4x%26sexE!48y|2Nykz6a z-D}pn3xXSY%w6#9a<^`B7o3X2ob`e__jhk{7g+bx&$$bN`}sGy3r^-fvddlY>$A!I z_T%n?|NOP@3U}f4Uvd|Y+@IXU-R{B@x!bRG7d{_{e)Ga_xBICDcVX#%?ooFk*3&Nh zmG{=W-$k6Q`|MNhLhHT=na|U`V)HxQ3*vTO>s~?kw;uhgbwBZG_llFbpZ=12g>^so zHTQ}SzPH}}`!~2(Scf%-SN!R?d&QS;a1~4kGL(DzsqfT?Y(Zx z4*Y)4d)<~{{L&q`Lmk!)w=~}EwzMJVJL!JxZnx#WWw+(+vu?}JJm|JO`nbA3c+g$6 z?o;lfGv4PeI(v(|Xy1q3MTg$|SLfQW=iX@cTwqne#%`$_c6rHy5IehyXaKh zlgsX+zwQqG@kP(mU3}4kJE^Av?%>V|&ET|Bw%dvYm-?F8LPRrQ6PTFPIzJ;x2t5+-)1( zrQZqnwrAa?bU$(BsksL?xl2p;2-2@~AN+v3^j9BK_o*p&>F<2nUHS+2CikV!yGx&k zyX=Z*-DQJsQ#X8{yKMYj?y@)Co!lJ!)~&wRT~@juJ>)Jc-OucCmzD1KA?sxBvs3P} zzj1#p(qQXl8{J>p4L$C*eyi?H54x>%hX>VlpL1LPGVUjza$D*C8NyrlfveqCx{uy} za`#)0xUHr8e?IKC{^_1t_sYTdJ8_5K)p2J>!zM?+xofLd)>CBPbYT_@`L;FPq=Ntz2}W?+h5lG zSH$OkLwEUWpK_P)c{+Eue92vYB6sU^?()VRFO0kUUGDM|xqtitcln9jZ+*>OUgv)M z5qCKq=3ke8?%r>|`{vp1ikED9VceDPa#vV4@NRd-ce{J={qBl>?q~0HSM+nggmeq; zBhR`ke(w!0jC&e+@t1V3a*w(1n0wi*d({i&u6cud)!ohul?v{6=@xmv?>J+|@7nl{$JJo-ed0S7t($64)@wi#{Y6|b(4E-Kljfev(Ej}yWMN8`<3V1YkwVbPR0Gl zA9An#cDQG5aPTWf#ao3dY^84L2!3}oZH8<^5w|~96rgi3Rui=i_dN{ujc%=Ti6j z-+uPn=C*Ho%td#}lWsfRYtDb++~2v+ZMUv>t=oR8?j2{k?ZN%R*>3x(x_|$u+x~pq zA3o@|f2I3vbpsopa08p(`Q7WbpX~;MJ2>kGUP$-Qm2M!o-+Q+kDBT}F<_1dl71;0s zxWTR0y1#LK(qMLz8$1>FlMlMV6S-e|ryD$(``u5t!TZBcaXWtQ!^!>9qi#oVAHCA;p!;?3(EZk4x8rx-klY_X z?sn90L9-&Erlh3qlxvgSgMFSyPb7~pj zL3l+mpL@&kaZw*s8Jc8L&&*qtGTL) zp^x6ep6HlId?iLpD{gdZsjBq0QbE z$;Ts|Ng_c-jS5-lwp#AM$aRe|=JC?}b&c7@4wJmO+H7>X^GJ7653T@E#+hz&xwp{i zE(u|8d%3wNPsdu_Uc0l*XSkg~;LbXMJCnej4J&YGBM98tNCJ1d>6?c_5I&|L^l1=2 zNhJ6X!s2mtd92ktc`5eQLDSAjrc94{Oq-9otObdYfpQyWcq&ZN{zKO}v@#*RP zjb?XguDQ~fbYNr5Dg~#Gk=jqrcwl7MM^m1>@$#&32Oye@8vO~#;WcLF%k4^2LoS4|JdXslgd)3QN zSOrkwk-^=0q}^Ry>2wy=Y&SAG-CzoI(0r^kyY1Dx1k$FNaW`PQ*SNFQJlX&p!;xie zS=iCU2WdoWFxNn7n(y4%AYW7=p%|hENM&?ZR?*t@gwmRuZM2r>x_7OhRc6s-;E+rL zEVgIoTfK;h@Y%T-h<*s!kpXiHv%9X#kk))_N25QS@q#V$OW00TRB$;X-XO!7KFPo+nLvbqkfU3`N}LhZpB~> z&}$?bNy+{oe<`L-qtojxHad&*5-yaU9L*oE7RChP==g46*!Y$$%vFr9Nl(#Ucl_5G1Vhv!K{& zk~m4pszOdOl_Dqj>d|YVF{-7YqLlw+2#ZC5wH&jF$*h=+q5bV7{w)fhmIY6u39fKhWbTH9# zQyAIVOrSqx5T8S_6+Yjv@j0mDv(+X3tOX*H7rd$A>!A0#Sa?Db5=;87Gj=4rJ>P1E zI5_cG?FwY-1vC&W@bHl7M(F%_tYYjdf!xY$Pin*ru<0Ksdke8h_;CBtJDSTr>*3C)|6h=U%AeQJt#fjP~_Qd25sg$zd!07({W2vM^ z88%<0M@L6u=@L&6D4rlpDJD|{s0b=@LYT^2o4RdsW`cDf%gYQ6T8BMaWP8Y)mczqh%su3CB?Hb^wO%9JQ-fKLfU2U1zja8ue9 zug{Ugb4yG!S$gzI0_OW1`$C{Wyt>>Ts>06)uTmRbKVBLyU;BAtWg7ETx)11TF0~E z8e}lHIDoN!9nv@?mt-Wy9P)g4X>D;edX6-EN9frz-oPYuUVeLPv;6g5@0&-q18f~% z;SXlWe8jkMF7q#SmRGT=v)o% zg$u)=;Kx%5_U=Sd<5z_8fmQ{rv^PA@wwDKIm&q}UhqgSe&0&q1f%S*%usVth9!xF( zvppthso6U!k)ww}mRpCLsEREb2T7u_7d%KVwLy|B=0~(UblQ*=m*@O5Q^G%nL?TOX z6(R$nwJga?oSP4@0EL9P5|jerdUuYX+%=Z5bd4oz(CI_zS;M-uMuNbR_TeLeD1j3P zYyw9hE@F`?mqjGwUS38am83&i^<|mGmWI7$tvz=%(0lu-7kfwA z3#$W#HxH>ibr^%8G#tUYsXn3R^9g`2D**gcvlpJw`)dV~hsJ^wp*ZjyZ*WFODJ#9! z8uodDcXoNT)mx2T!t@-L3S)Q^Xd>55@l=!w6yy_{gjmp-LZQ$z6~i-AJ3KRo!}Ff~ zW8))Z_@}7%POY$RU@d z0SehH9)@C`izgHq@nm5_k%TM1km>8eQOpAawE&79L z5%8u(zwDX7x(KjzbHah;Fu-V8mR8z)!jEr7XePS0K{1M?eR~I&LYpYh_q49xsA zE(fAv5r#d3G%Nz%kj!#oEF|7|G#lHo1&(^B6>Z=~8A+5d_a2c46&QPwH83{_Yv7%O z(*1}wn&EXtzgLp{Dn0tW*y#82@}`1{Lpx!gV*}&ZQg#>S2Cv(GqmT6UyD-eGpaa_x zX%Fwf*Aqet?cA}e1|HmgT@+%tcWl3Yu!bAD>xAqYxUNp+4L+rAy>Z6?7Gkj0m$!?8 z$7Hy5bO4#sA5bhxo^YU1Fe3?HM1o0G_q&VmDUV07l@i4hqeF0@ZFsf`7+WE3%UBD@1=Qi>mz`C1a5;MoOzxEq z#v>f+`>|w0P9@TDr8PzE401L$vd{P zV?Yw#h@O{6hFBx#Iw6=u=~Eu!D^v zS1{!1EUm0z{0Ll%y|!IPn$mRU)YcrD_5^V`AXEYk#Wc?vyf7Cv-y`Ore#vBoFNE;Nnb92%SxZ zpdn~dT^c8Yt9884z>1dZWR1=dUy}>aRNI_l>taq3yDF8{R1j@lgL+wa)0o=QZ{WOu z8$w;_HRMXd8JhG2-fn>_rN^MAtQi!mr#x&^6@oR8dV()pT=Qcag(gG9<>?{g+G<%b za3x+st3<${jDXiDsMi=9N_4w*qYn$CJ3vhD93R>%i&^2>wwP>U176$0#>qMqhsk_Z0aR-|ZhW*HI8IR#9J@^FbO zGI4n;a>dbaW475tTVEL!H+UqXv(#?lARIX;Ck0w*Ew45+@~t;Eb`3UgIC5raeB!{^ z(0&;ORZ%RoRzVpRDLj1h(A3cI%;?nE^vu|BW9A1YjG!7~lvhLZgRMzO#57=ZYTA#? z41nNRv`7pRWPY&S0D4Qp$z;3@1Zxk@pM*(=fmt{szA-s9c4%m3^p?@vB#)vm3GdGm zMwls(kqnJo3~R08OmZ?aK|XqV%HkHBzwlA10F@vK=x7qH%`Ud*R78iV5&b?h4^ADz z0s4^Td&frikBp5FKxsn6!$_HrKC=ScsMI1dg`qE>{aBZe7>smVGToyuP9Ax-#4AdN zDLsHXxxFC`RA6C)lmWtmxuzUOF|x>511r0vfShXaiiG|eIgDoBaW(4Sfxld z%Cw_4qRdb~VXmduOr8rqjUd%j#*N9AqH`_@aez@0xIS3u(`ZSNt&5hLlZH1*VluSf zc(LTAl9Ths!DR|w85|~(od^~&i(}Hn9Y@g#N;6JbHTA{bj-e87oD2XeD_c-rJ5u3B z2401U2lm07j_dnMh=xp;QnV^_O$l3DXv$+-&$dojO2{*s-X^hDKr)N5afYc)(-LCT z>$PzFI;}VqjFRPp9lXnw3jpE=G$9pyGM-FwO4>qnA|%;Jr?hs$iFnoCe1)XHcJSHt zh@?E~NNT61hZ>W&3{MX|1kmOv9;1CIHhCG%k${jnToK`8t#ihrWC;8KT!={!o`H(x4X7@hF90BC{;*L1$q>xY0DCxeKsB!GlF$ zHxCoToPLFUCE8{;0zt8j7E~r-Y^v+{2L%nG{R>}*b1AGx6kF5GtF}rrAGm#`qt~?S z-YYVtun_R=x`bpx^MS*rtbrG*g3_QHrszkWH%4xj@Tku6Ml8z}S*OSL369@TngZ-u zOko5i`3!pkrJjOKQm;qJ`ec|rDM*jymcoO_ut&@YV;KfJUmVul^}P{ua|Net&|kH> zcn6qb$cKYJp2PcMK1f-XV0Ys!}tBU7uy zx-f;4Kw8HrN}gE9;PELIiPo=!J29j>z!)7SL1!J=$fGq!-O{{b3>iZElIQ^zup}TW zVkt-%MP!Up%oOq4x=g|hU^S66uSHplWV?)(c@YfZ^Q;mkOjiqbzolzX%|3~+5sO#T z!{plV%6ufJ*t()du(rgfP)H+SNGSzUF%mmMnbANfm{I~|L6F9Hz)Q+$CIN+DQ!SNn z6&#W-6kSEbx~SB>n|(zb@ed(7!7o*rBft40$KA-yI0DMErhzLERFo&ml2v3ypkpb} z$j$xQU`vs9^=8aEbZ4#Vl>s7Ox4k)4zng2DVd|^4!pa*O;hVEISbUVME%42;0aj62 zod6e$Xs8ephs-NoBj8Yo@Te6qJV;B$2*$B6C?SXNSlgl;!OaPA;uvyD*4&~;+l~1n zh7mbvI&P3sFP;aJ7D!{uqbUu%C(iU>Lh|rQgU4qwKaS79f6K^ToCRrIH^_2Zn;U}H z4MJuMfO7%^l8| zgM5(LRtNheA)7|W_l=E@#+>qAw%4uY!#ozjsPgcLX!aNry0Ny}#{Rzsmz4KJt{~!G z7@4vzw7b|esv#`m>}d$>0|YOVC@etA%s7BB)fqOBs)$N~iiqv~gVSKS*+B%N64di9XV3Q;nsHNZ6nE*4E z5-#i~qo7J|(a2=z+HyS}>Pg1j!)r=hbJP@2vGW}s_4e^%g^+8C&=DTv zaJ#PDE5q9C3F*9?VQ#UFP1VL6w_i#@Oo0<>N(}XyNI#j9sDLNcWw@Z}9Abc-z6xB( zv?=4)Bx|4|dqbAUSZom!<`5(j*hq4qW{F}|n1E{@#mb+unJYOJadj9~7@S!f7F7+* zWb6YQE(SJUV+{u06>I7+T4Qi)je)H-1#G+wY`n%A3_oh@sYhv1MzJp?4-4!3T^O3T=Q2z#F~ae~IFc34?!3NLd2lagTnA+R zbdP_QX;SduaKW9>RJmtNrm>E{obK^g?Zd;d_~g%n$n1bD^1`6bY`g?N-ldP3!Pg9Dn|yB; zfV4FI0K5=&Sh#Gk2TgH zV$Fhd?`J};vY-K)Z_Tb9PI;M15XJk2AyI{V!3(VvBD?ZKeZl}dD63uB^V!V9ho^(Z* z5GvY+C&tG|hi77)2>w_jaHCyk8L!_aW!ArtqP@Vh;H|if*fCj$)TA+w$9l`gmwD#b z@V>qlVBCEoLIkqU*dd{C%W9yKCVm{S^*JbBmW>tM>?T}<$N20tj z-fg{Q4TB?*EfgHHLBI+PGx+BGcC|27Gm-Dn)N1u)_vNs>7>+cfdGpaHPnFV(OCF?U zMFEjDO!yJZ>5mpbJnJb*qDV~6SmRRz%^rQycHwtzSzh5M6d%}}!GCwF+u^SifBdqa z;ZLiDrimv3;Q?!;qb(sMH*W9&cFGTn7`$xt!Y|q+K4Q_uUoAa7GcLboXpaTB zT!@#lo@5WBMq4Y%8BH|NDk09M{AiUtFNgeoo# zbFfBtS}f#E;9c(F8VfPd;t9}*$ucg|2_q-fC(JtL6WQV?Z;h{k!zdUe``l4e2>IP) zify%ynvltxf)-d2mdnVcfP@uN3PKV^`#Hc;NeDIDZQ>3FDIg(giJP+kjm$CKSU^M) z79keBrDpf2h+zweBgxS(1xu#~KEt$5NMEngF^rhiuspaLF!bIu%ksI=Lz9hBc>!vS z7r-a4+y-a-{@Uoouvcz=r+-A=lZxTho5HK#gjXPiKQNN+rJy|T_qXMX23aP`wtN^Pf z0IZt8;BtdwRRZx^v@n5RgQ%ne!HNk4D<(+r8WRGZo8VD3p*yFgAHR+3whLnuMb2hR z@CRFhKbR5xCJ`)@%UqaMy^({9fG7~+HyIK9nNpMdfnF;0nUTxPl#;_JmDKPJ0)^6V zmC|ox>QfI16mztB{BLDl>lTC%;@h zX_Gz!s38Gdij`hSCBm!g{^DhWu2jD^L7@bd$AC2*BhChLeT_kU2c$@tg_3|_gJFw4 z%fdTpVhvJHst@81c_^Nc!Dz9L$6(#L)DFmVY#!+g;rSeb^BG^f2sM}9>$XSl9EQs~ zOJ9_!)F4%TK`stI$N?Wl9$y%e)LEL}DZlvINBGsIg&&i_$v5)qcV)sOuZ!|1KUKrW z_@xr@&G)oK;a5d1&Ce-c{1A)q$q8L~;$gKote_{2f2Lc_#Ym#ZkZ=+@`3}i@I>|rD zx5#(}sAv$M98aXZ>XSQ5;=5&uZK>Vs@pT+I$EmL_$3VPZvli#FZ7qSfumqK1*s1za zlx1l+k~yf6w|6jNNr9TM21mXl7pj0Zs6onrZt({tpce?_4(P^v#v@zq0TCX35ie6U zfPHbk2%SKchTY&0R1|V^IskdBc)BN0@cusTb1^_1yh>zrMugMsIN*^2c~oB^slakV zH=)u%_;=8>p^z_;MGIOw;^zlQQlNPqtP9B1NNf)2S~ga9VKGK>iu%S%7A#}yBy%}k zj6gKwLIa+mODo(729?Vl8CJ5;<5<1SK{@PHP59JUfyaGOi1!WKtlTgj%eEPBmz31h z8Ya^Kd(-5 zYn8wMtfQX755*aEu|S)2D_F!5E)UQ&35yP;$N(Tw5}sw>(gHCLK}_il4>N#g(~tn( z$9Ps)bV;WIo83GUC%MTtlVT!QN-`uPO)CW!#M=DsfSAWu^llhrW%l0D+u#G%nC*6s z^4>PYfn-IU(ioe9Er^mV51XHS9EaOY$$TFR4#iA zIf6E3JN6nDIt6E3crXgEbX;&DOHFqyO=ZSJBrVM;ylv6<)bF(O+R)5yuO z&?G5zNScEJBww0+TE>LNo(-P>lP{QJX03z8*r(M}WF5v(u!o;Tv$i)$AC_TXwpZx1#zzX>aynf1#QZVsJKl<$IyLsNd+978J-!#=eCtgWCn;u zOQ(1_YjggN9AIp+kX$)XMNahUtB#9!1$n;IkE{Ggr-t^Ay=io$w4)@I_LTH!S4p6K ze2-OZq!zVS^dTW*fhkBF$;2RfP$PMxGLaHfKzt@G#gF7JQozV9V8$fQJ3aU@^+YxWiK1-*3rE7H4Sl*Q%#x*irI5_x?ItvHD)WQR6%iAHB|54< zG_+r7c*qoIgct*INjDY+Odj0BH4Krj&zYDSaunv-MV<}M`e^+uvDD{fvGn^#qNwV@ zON#N5iltjiHC|GAhnL#Vpvh;oGlBi`nT46o9;PHA@dAkOkflOKi1Ck?KSTjjqu<{c z8{a#jQi3lN6~KZe3Jvrkn*gT}zS|O0GeRaMNmPWK> zidrIv8Y}iBj2a8b4~PmB4KWoD?-|>NrjL*5=}r45@Vz8J;a9>+Yk_NTr~DPBB?$f; z8pEe)0mcMK0%QP?GyB?*cw{7)c-UP|jca{NsG5@{GbI>9U;vA03}Q$zNkwVOIq}AX z6d!BXaW_!)U(8B#y}~)O|1Una4)u)R4%4gZJf7^ex=h?OHY1TFJ0}f;S6ABmfw6( zHi5e>0vWEHvOcYho=1^9u9HJ!zB?1U>8-}Ljwz3?gi8?~p4u<1SypqVMh{KgGCHCr zc~7RRmLcj1A(EDWWHl$KPGut^ny10EC^*oIb`!9gO1df4jf{{*>i`hK6144XKx-B@<1}IZ}pLd@SP{s}o+b zl%mIKBunw19{v7<_(t4lQjx(GT^Y4spiFxfqQ(qnKoTU`;mcl3gBq4hg#?N@lkQ1l zK27Ql@hw=1rgvye}b1PN#1g{~wD9;`zc#RAM503(70 z&Ug(JeK9r(X&%NWV^?+M2(qvyRv3p8Z$yD52k7(5PFSiw(rM3e`Ifhe;GH}nFo|mk zI3vXq23|LgG{{=8gu$Y+jWm2c9I8p2cyS8yJ-}91ukGfGNfMsNujXg9w(>6B+VvRU zL`YuLGQ>>vR5eMO018c0e@&p|4^5tkPH=@SDo8wqj#N}NaPnt55?o=6IucKz!>$!+ zaEoMmETM)q>au)=w(*1e_iIo-Wzq{$lqQT)2V&ZDeL)*Km6iON!~|E^qV&X5SQ=N$ ztfB(Uv=uZ}S%9e_DG7N5XLb!(wb7d?jHs%L-lQZ!x%jc6omPDGX5u5N;-fc-Pf#x2 z_c&HX24!k8imJ+>q%MbZmA)s_@S$6?RlJtLlmcCv&xLx0VZl5zE`W7$3AFkEQE4H* zD1V2>rpK^WYZEbpGQ}B1)n-si#2n7!TPz0q#4J{bvqa5l^#Njh3-LvK_Z*nCagE+A zo)J}5(VOCzpge9|t=2$8iZ2%uE3Hb3-b`LZOQt9}a-<{}8JnKm zKXlv7=&du(JO{xB%E%OHXjUFRJUlZob(>Gqk+IC5M`;aTj$$l(C0gZ;>z#c=W7X!pOJ0RDsD_1Cv`XNvjcEOJIl&CJd!sDyYNB zkBx#_{)Ed|Dh?WDWL<1o=x964r&qG$5E5FVk{`4SxH;V`0Bl~8^zNjUSP zQBfWSkapW0s<)?8ld`EVtocb4Rh^xz5{TIz54Q*ctvG9kMX3U38ka|lC4dlgE?5_Y z2aIcQDPg&03d)axMERUCVAaO&s)u20lhaf?@Qob4HHZw}&w*8(Vqr2rb=xF2#F%Jl zVx8lmiay_9OxQkQQtK5NatkCAebap+mQ05Pl2qm7oEshpDl1*%xanoCi7#RRl=dhP zB{?iHre7MVEWP?$IOpC?t_@og_UfM?;5fO7F$9x-=nnw!=KYEDK@#(RNah+#J zZ^)1nGf{QUky1U!{We;ZpYOCKxD>}FJUzk7QYw$JxZ>u{h4%4;v3V#lmi8X*J}LPO zhDbEn_Pgl=JWnBSUNZH(f3CZT_ZzwY$^4LH<((a9*jlJ^lekw&FF_zER8LW9N;BeC zdHtyH>B#~t2OQf`0N8HDOPs>Aia9j|ss|^Ma1)c@@~Epf;+K;PY_mA;ZQ)SApR+>} z)~x$cnPPrDTczUV`_kX)_$2}*VBH?~(MulS$Pm9UE6=LOBKuma)4Zc(dCr@xtpgX` zH45IJww4pa_KbsPkyFp2}8+T+S25gb_Y5^O{zXec* zD)EpL)0R(`a|OU6vwYei-u)mbvQ@6Xit|v3r(Q*oikjR^5m}UKwXlGPE_12bJDSCr z`P-LRhD>W$K56uH2V`V28O$Fiw{|Eq5;0>|G@J(){&3Kvfvb4XDoP?~7@@p_5O7@TjH@6x#N5Zcb*PXrd) zfND#r=iOIk<(wi$7<`f2pLX}4G~Ng_7?tRg(NZCKJ)TjjhFZ$Q^FdC0PLd)7E90|N zJ?j^F!SJK=3xiS@0?-mKUxmpLjfcEtff>so`EDh*Fof*}`E+N*qD803F7d7MrX;>W z58I;%ZTI@*@I4BfZ)#ZkIkxrp?Xg*(4reNZ$6uTfylCvOLnOZN`d{!^&iFPUiP9;` z#*K6{JV;c93n+Fkf^$VSUTnv(xLsgQk6_U^k84h3AZSejphi1w=Tv0s9Jt4FM@^$YHS|Kv5#=#PvyB@+Mg&mi$pl9Ij@YSxM{( z=t<8>nNGkEEx{mnGVM^stg6CEZ$DZU&$NUu5T#f$K!)ZzYDkq3RzonJ3gskxFC{#<4V0;?;5l!M20oZs zQ*1bfmM=%A7oKBo)Zj^TUt(W^SCt!~0ud&Mjny_e1x^Ro@}#fBbIb=Xbfq|j55P#e zD_jFH9_hnA$%Y(@G4Mz3VyYT{(p&*O5XY|!9)_<`6fI$+m&!@>CD8>Gz0p7-a{edE z&5&GDWK=lg%q2=gDW_<1xj9})uOo_%oDjQNIT$PhEsjM}#`eXr(;dxW^0BGEAwkKT z3@fqZj}aCqA5axCYlwx0lXIBp@hxMiB`KJAV|SPnC8;w8 zpZK#zLV|*n6ztF~iRz!Fj&Oh(=AJ8R3ob?J>H?1?${KVN5$HqeA4u+Fv z%1~`Fa2jQ)xjJ_wS>)N}M%x&P-kKaQ)H^g2DyPxL<+5ZIz-0>|%gLDNtC~=f;;+kx<<56Z# zOE@hyR~|(Ei2KE%S^}>ps1R}_+G^rpuR@5yVW7VXp$f6EWV#}ASi7nZ!>bVDv`0>d zG5LH3hL;RJP#KDC8IjZyLibrx7O|Qn@8kR z^zc$1CK;vgN9e^sqD@b_%2uF;Wl5IT)r73=TzK^qN3*b|f|Z1LBs|fzKGEn3M#Raj>jfc(Kx(ewCdL|aNDwypwRE|$z8Y`oJT@1JNV*RurhGpFXmgT_$lhb$w#yHpJED5^zToWRd{ZzIXAQW%kOeZ3W z5!(F@E^E3AFI(fhWFb_F+3^+7abK+Rl`Lwhe7LtHsdU+WE#x9lcu7epVUbHb-eTDm zh=2|nY%fnX(_yM|g0`|jFD3NC{-+z^`bg@)zSoKvTM%BJ(B1#h}HL!-DFKAV5 zjasTCm6!su`%5v&0_LPLV4eh7z?`H3nS6bsM^X_zLfkg3+HWaA&#@gcs3L#LPy?Eg zL5|i40Ph?c*ESa1C0$a0;0-zJ6Ala#`H+rrV_OQZjdD)Ov@~*BN{xi4EQ_O@I%0^D zkys{u3YMpQj_3BV!jn5sW4@LXVLJ#c@Mv*?_tl|AlH5gVXBx5Yk{FQ*17aRl3o?|T z0yPl`kTu?5(Qt$1Mtg!PD2>euMi3FLu38)#%)pvTGo}#oB3Er{*U+NjHMBee1%pN; zfMtXNo<%Hx!Ri>nK&V8txhnA}<`fn+Rknab0XMMN48OOQVgn?qBhW~%yP~-r$Qq=A zl&WANRI4DAMh#h8RTs!uo&^fHu`X!}jc}G>>Aq#+J9Nsg`wVFLC@EC9J0+FN=ub*f9>e+d7%J`s5fK#`B716b z8B3(+K8Z%IH8=ePw8EqqE?E%cokPZ|$f0J@E7=tqdUSERx)=`b33X=b;Pi~ly!=L# z22z;4rWsO4aC^zb(S)Bw=*qn5h@u7?2z{gVX3JzzjqML3xZUjgM9_A8ehecUU&pyq zE<0J;tEo=?-V@U!?T-0xKrL1vvY{6@xL3d}9F*g(-d4iRG^+!5e2wkBtsw^q^^Bb) zcLv9CQ-(^Hop!uRnoX39<`3`68!S~_%t|x7$U?H$&ju6~s>#j@&5Tbfw6qeLk&ydg zy-{-{qw1K2tC4MdU#}V!q4P_YH8e;bkgr_U&=^ey>z52jB3OlMF#9JyCd^CCwqMb% z8jUY&R?W>;pDST%0!aMYD{|JjDvlZ1FUchaeXN%>*RS8z3pEuzvywtzo}L(^l!4Sbpvho*<{%FMK@AmKD?g;2xFYE$9UI)=5SSst^;!0nhG?M!cByJIj# z&Y@Ur2d@xq$oC%|LNE8?DE`n6E(!5oH@s-TB(p%=2lQZAL-AfDwgznAw7CfzaSO6P zttGHytq_?1{zSMJEC?7jk2t_p=xQ>D}~v)oiUW5MASApANl?mAdu zQQ*qm(KRg;jdpV&3P~8ew99xA7}HO`6~ipenWpds>aN*T6g$UdZc(x*mXv?y#@{9ZVrL z$ZAfgVa2v3HWZ~K@YBpVui)#VuWw~3%p;|a1X=B!7S z+A=_jtF=>DGC)|U*P_!|gyZ{qCt_i2GP=gdLUJcpiZPEIW#kHgCV0EAVi_aKP%SR} zomFg#%UGcrMrh;wj5zyIORoTV68PqUCe`LnVYpK$cG$t`PpBTYgE_m+MZl0KCgLiE-Gon$#`wgDzxh}SFiwy3c!9 z4I&ME;Scr{uoW!57;P(fQalquvd?(aqjUsP#xO`vFv?f%4+a%*g^dOkJjoy~la1jz z*rdl*p`fWssbi+TDrY6tIf$QMk=}sq)VwrLXexR~aPgOEq5Pm?^5E3u#I)Q~Zr6tl z>}QMyk?j}JprylzFsnx)01VRcO90}4CIH!zQ2@0C$wNvnSgRNt8MU}wP3o#i_Z9hWe#t&Wq9v;RJtT8e=Jv=owIfKguG*4=9Un8m% zDYZ3l6^f;J=-|xF6H{X|x9P>F%IRv+P|j+JeS)yG)$(iP7RxO5B)OQrVRVm!pV$u#qqFIQduFCaN3%h3z#z0_6N%FNT0M+W1w`ly zRv$cOJ8LW#A)=MixlT>oip5sxQ{ANTgxs@O&LAmmLx}z)lp_GGEwXkX_kgIh8cMFN zhQaHup=hp&A$8Q4O>=GMi@;nHiK68xL)dm^fSmo8;|U&K#`$W#y&yVQx!o=-SgTrW z9cyu|8}Aa3DaerkVuCVo%vYi7rnpx@b(w7fFtIb!*zx$Htj(&Ys!{PMY6v5BU-}Qr zr#6}OOG}jIUpT4?geJ^!rMVJx4Xuz?x{^oLYFeg~Bwm0LweN|i**#5yB;EdKV}xXE;ed0YrmPvuD~ zVtmvihtcblo%<%{QMP!6M>bTr2^D?miOWSPc=91l;+lg5vw#K=L@&fh9O_RDm`BYb z*IKHPK@{;yd7*DIw8j_B6B>M?3L9y17?~^Cdu1-<*Hm2v(b;&<6Ifex$;5K1(Hazq zuF0!jro8o&9CT?c!)BfOeqd~T$DkSs0?%NGp<<`r*3iS|6f!D9P|JBYO@^&4mwa58 z%Xy?+NT{|7m$Zzd*e#IP}_r!WiswG$Otx}B536l7pyWiH+ms(PVs z0J|)5oLyGD+lO@nP}FEJO;Q7!wZZV6V66me?ZwshvX1~h1w4uCq^9xu7*@^Ohog77 z6Ob9KzmDvYYaX0`W&&`SEH9gQ%%6G7FnM<}1Zpp%?OF{!$u=J}lo09Wcpyb?{J1`L zUj|}(pu6}YKqk5*>wQp433uD858n+LALZ%_xzv*h_E^r4)c6phE!wAHrlcdb0Trnc z-B8cyrAGEt!&@z)_0F z^^;?hHeC~tt4O$4k^mjMNPZizNK@Qq$JPyZsm(+yBa*8+F{_PJ5>RMkDZ-7>S<+=# zt}!Ed^D@jtF~L*DF{>#AqTVkLnJ$s=R?a5t?Nte#wM9Yd1pLx@nVnkziq zDcgPO=NZ_B-}>cTLGn{TiE)JFh^bQ9a-tdINlnjBM9#J(`xl{S*WiZgW~H!pH~35+P}C3jpZHZei{r`>&AFgE5zmQz#Gr~6}r zVM|7NIM^QJw=R=+L|?a5AWJ!@^n6See=0b=p>1el9ad~{Uc5cKhS_xzzgKU1lBA-T z3Xgn)QzIE^A#G!J9l}~UzR#P)W&o3-G$D$xIs+I>Rn=yaq8(l#21LBAO5#90vLz`B zL#d?4Ge{v&Vo--(HCZ3N)9T~Wn(N-R67nM{Z}gV%qAKphOj1jz*TyFiaQ9ixXheiM zW~v>iD7=zQl44jX&^Kb$8j$t1;Pz}diI@6yjM+I_t=`<|6Gln)>P8{ht05KOos?*Q zw17(d1_se$;le9k6o)SiEVO2uhXdij&@H3f?B6rAFN3CU&Or&ga=lDvsRuIs1$8;- z`H&5@tOXuEqRYLbpk5?2*Ko}NEY&Vd%!5cMu3X97b@3=vtw4*!9n;l{|& z%uom){I+>N5t|VmgO)mwtkXe0p9|R)vXLq5rM&5(y`vxmk=|QK?Zaebhj6i5LOi(u zM_g?5S?u{N#2UcsCKi!pSjr>g4N_y_*Yi9+EEyNNXq@L4?~>Ic?l|?Mtu41LZFqWe zoC{7SNNC+K>(RCVCKIzNf(YD6DDx+;jb2)N%mk%%a^}cbWC|h4EPp{_@W=9~vw%S6 zg@~!8fn`$PLg_|P4UB@bl-hQR{Gr#tGt6KlQNLoa0GafVX-^PKc6@p{c(p~e2-e1%=JB5@2Lq@Yqf-9@f`K>po}?b-Ac&*kZb!9rweO`xF59BXLi;1mvKWZqD# zbF^e)tKo-@HUwwPFnr;=dPlQPus@l{_Yp9a*h zMA?B}NR|`1$@u8aWJgp@kKU9z3Ca@(o93Zp$YUn9LX5^LZ!QWaB@W@7#Quq4pMcSy z2|WQ@6rXrBHL_aHK>-hu>c&JZ2}^o>nYAAcuO0TK#g~%n0_UO3OUWg(z5&j0K}NwS zBfT45QWz;^_swWcL<@?IXO$GAStaGM%;}j8WgHW05k*g^#xN051XF3OiDQ*$qghLh zF|DQMk*%<3d=p$oIZF2^EYaHb<6YMsv0kE{$@&v zG-Aut!}Lu8a!WB26#u;T(Dk=y&(>~LwVq|a-bnaEfH*YLPj!eH)QVJ zs~3lA4rAd+^1Kx9H~fuKExXvSYtOe=?+OC7^y7{`roHLNLcBdC*M2QX<%3}p1pPy>yj1@3R zSHITD`bHVfE1Dp z;l=%!0FzsG9h3>pGb=fgfmiPVV1*|ROdg~c@-zARC!%JSm`d3f{&*yk-kO=fP+ zXu9K*87UMKsA3AiiYWxErVy=|La<^A!Fp3j(W0gMMLwOixa;PebD)$)MT!vf1o;g3>n-VxdHR4UEs#r^mri!>CIfri^9lmAy-~kN~ ze3`%i7A#S0pcj%+xUkEjf%G|(T0@Q!J$n&pEa9ip$_0J;GMNGNu@5X!ZlD*I62=Jv zlV1s_$nVRTY4Ke3ijsL?t5c9Ol!BAc;RDl+VcjYp;~{6RXO~#vm%>$IlF%iXw(?1l zCQo()qtEXVy1Atu`vh*->j^lpv)h!-Vsg`?d$}=e%bPvJE31g24aD@aL@}0|Z{ZHq zBRJmfxe`FVBM^A8GiD^L!=sieim7*%t%S)qZDLz~&8#{7M zI05eb=w45RBqjNUOVY(7OrmKT@5Z*~X-l{fnfeWiZAKzft+`ekv&h^#4%Ta({`S_4H3Vkb=S~g9LcN= zG0|-w#<>C9h?N3PbP*(kP7IUrz9gSeQD96M6RxVYVpt3h-lRP$X3|hf$mc)+Hq&h` z_hN9HpwX0?>`qa!Ay`JroCl25BrQ0_C#GVJYiadtc~h`6p*0F#<47@ncwn6I(Q z2dJb@wIK*9#0Epo4H%QV*@l+qr%@}Ki+b5`2-=g#$`pg=EBu_8^{}M)<*+^^E``;Q zEaq3YsK&x*$o!q|CVT{WO0OI$?azcadg3Y#mFTolJN#+W^6}h6?8Sv(Is~DVppMgM8oQeLdLE8gWVk@x zUIK>%QV``WbKcidM_fwdB4JK}<7fphK#Fz~8*O-HDB>-PW2Pjaw7gKC*=$7Vc&MUG ztixA5>j|_%k8&1TNJwd>BZX92jIqANGIIp=gNiV!EX4XHvpIjNl~gns>G)j)ieq^Z z4;Qn<1ACq_;1gSH&IUb|F>&ZkgNZaf3o(yt>*TN^DZ{?d`cOt%LCFTvlIr-rkB+m% zDEM&DX&FP>)il7}&H-i`cWEYNkgne_mN{H4qWQ4S)Z9GaQLKb&5sRgw9|H@4)}E?< z5tEh0Tnb7i?)wVOQBFJBItm*&T*pp<&%o_$IQ%K!6NQp^qdr$H5{>miZ4;ZD5?Ux` zb)JA(eo9*a)eYDk=YG=FC99<>s~kTN_robU_7&$?u^qKkiB69Bp>AkCY_%x^$w%` z(0V9ae-dwRSLhd+6v#2YVCgCS%0brUA){>ZiZqIYoK*j?x`+(c(`3~GcC=|~PL1M3 z@3xNCRprEhN%>*+N_~`ga;zWG$XG;fk<){yVx^Fb;{^3nY&l^ijj;`VV6;M}4vM_qXCtb|9d zU4&=dOY%I>*X4{d5c$=R@GJ|_aYQnc1|)do_AC;NWl>%L^blKx0wNd6a|4~2T=8u< z3;4kFzQ))At^v=8Y<_;*f!*R%P=|Xhb?neWI9Tl8ZADQrmQ+B>)7^B#l>y|CB83e~ zE2<7dqV@t0p0!Caf{E#tX94&Iri#X64LK=rnnMhpf#VJ4c+TJ8Ubu&Jy^oU% z0kCJxi2MD_HpYh$XV%o=GgwlBUkfXFPsk`qTZ*1FBPyDHq4fO|C# zP7Mv;rn!O_ZR}zpSH?P$t&t@?i$PvDBde*P z5ew$}TB?UdwXS5fH3rB~o+;2X1~Ljm_6QOVhg-jNGZtXd`*E-g@cPg=P%BA%TU_g2 zg+x)ld4y>+gt4w+CcNa^ZO=)IY<-AvA+PT3mX>J69P|hGK+bm}9oi#nAoBUu3bZe+1ET>s9MkE8j+8bYyBQA7kVM4;&`XXr}RU<=iu2 zv_~QbeF+Q=A}Qh7kXe^B5E>VR;>v2SAV8GvsX&q8q{F^)F0;HHAx?8~uCbOLF(N@%%U%0~?MaWv)8kNjoLiJj079Tc=vfx-YV6_NFO6|w^U#oi z^yux;Wqix4ad_N+u8AhG(+WM&VGXX=QQgTmTJfD$G9AMCeZ8A4`3j=+_K8Zd7&}vx zkpL8jjScKaCNkdOZulOxpn$PJgx8nDC?k5pXd(g-kFWH$SFk7T&ujQ#VryjMiFp+{ z#+4bt{RdO!d9N&c%Oj8BVcIr_w?}o^nrAB2D~qAx9p+UU6OxiBD12dP5H&2ZYjo{ooxsbl70COSfGTKT9w~wFz`ee;$rKyofoBI;|SE(x! zWeH#NHwv0#DJwAfeu2qluKpK!%ShG0t4CyCH5IIo?mB=9uQIorI|gx*fhiteZ|)uG z+_`{#SiE%LuZ6-Z3VQFQ^QTKk+BkNlwlYh?Gj)Wr>aW>Srcf9>F}I49ph5__8ExpT zVx1u74PF?Lmn6J_;}heP_?}0X7jyDRMlgtp!*@#-u#d`*QN&sm2sol$OJl5XqM&bB zL+>YoVdq=3Yq+MX)XsFO6&(n5GD8OTGpnHY6LA8wmQb|t7LUd)Bq7_v0#d%ffZbdgjo^mfz=ooZb6=RR^Ia|9^Z+X%Y3BSoRta<6~=*5~!NYgb^u{Y=y#7&JFK z*Eqt#6OFmH^ZFVX7Ac`Scb)Ps&F>`Ak)ExGN0mCTb8y#s7w><84XSp-n2Dkg8+u(lK ztv}jyZf4t$?S6Q-yX=WiZfHF5jko^l!{6B8-tpz>bq{}egL{O04(_Yxxn~^s*KKe! zFL&#y4~Af>D)W;{B}70 zK5+X+_snijr|!#~`{HL$|CudcK8tCgHf;s{FJR9%-ukf^-#_oY=;1#{zEIcgh}&0x zaQ(yob8f@K&m2AN;b)N_&um!#$Y)*BExOhlT}+RS?t{$34Br%O=} zXOQ`6gt;AQ)uYu^2eq$|_#tI)k3>98C5!?KUEef5`-mMnMotal&$(B)t*P*QZ`Z{;rhu68C4{UUA`6SAZ zJ7f1V4?)IP)$RxG`NlVQ(vFZ$-+1e9O4^X`&n3@49&P&?>|h=vFCNjlmu#ec4)*;d z?0V{gd#2VQ4pP>TrnHgqXFcAH^n|{tppW_Tjko?Q)d?Q=+&6cA9eOYPL-+895x>oU z+ghxN1WIO*iZbP`*tHQzV8W?1xc5!(ET~c z7kNJm`ZvFM-DfwPC$uL`e3|yF&-cQHVZ`m9X?}^_!QQ7}%X=?!&ulw>&ZhTlSoe<4 zZrJe1wtsNxN2s51z2~`ae()Y+XVch8JlIM6_GqWtLOcII*n{-?;5tdm-5>oC_x0=7 zqYeB%w0}Q>xS}ojsH8jE2`xw3WYbT<%cfYjdtmt$JejB=W)t==z6x(=Na+WMOPSj*^kw!*V@*R_MM8{9sy>)L^V ztLV9QU@N@?a2mMgf7swob6@;s4GDcDsnx#?pw#_sfTZ&8ECH%=&IZ2T$VVG2f3NX) z@Uyev-}l0i|L4VrLg#`AXL%`RWbO`d5Klr>5{QQFOC;SXg`lQE$Km7h1kDufDQb-4_p)`1+|JmS9&w+?< ztl+-~B*?bJC;Q-k+z0ne)c0mwu;>q^Pb2vvhu+-xe`)^;nV=;Yy=qC$>dnh()NxDD}HpP zjq_001_gMs>xQ!Cz@2aTtclDi%}Ro-m>>}5<}Na&nLD*$*1n8MUzm9NRSll^<16rT zt%3s|mr9ZdtUb_{ZVOX!e83|Su&_shKaChwVjT#}D5U5CmlQx#QYal}TeFJ`>O*w0 zWF`;S&v`bo=ib7!Pn==(pBgBK%#t)T9cw!ByxW(%^H3gb8#&_fOACC`;}-!x-#_!` zcK=-RhxUp5oD_w>f8rmu0KYJR`2Bbv{C7NF+WGq)FZKSB$4fggW|6;=|9=>MYv+Zq zkAIZ&3VoFSw|boRZ!!3-9xv_u+a7;8er-B0dYtk@pG|Qq9;X~Om4UYEamumy@q+)8 z6oS9MTkwBUQ0MOPIQ3rQG5-7mg9n|&|CPtfc>QaSm+ARm`pEe+gJZrL|NciGIbS#Y z)}FuU!+#nR1%I^Djylfp_$3AY5|3XG+~)5&Mh@o5@sI5=|Cs(3XFJTlQvO!MZ|%9l z<7N4LjmK{&?D<}gm+3rWtQNm!EARec1k%wM%+p!By!a*h)m~;q=6;z5o4Ig!KD|;yK*f z`{zG%ROVm*^4U6sepN^xE{DA#d$^vwYzX^SYww?*cUpV@`}$=lo&!Vo^}4n9zpuAK z`f&U8?;-SVs37?ezON~^|0nkFeI01+F8!`Acd)ff{UDce_QlpN?Z^S4^q<%-9yhL8 zW9{y~oV_!ox37qat=HNm-@^91wM+VEgsyu_C>}|ti+`)N_rLBvp?KVwPojG$6i>K3 zKW6Qcp0NF?P&_e-!2bJDC>}|_8+ZOR6i?XxawwjITqL-!_lw7kgWu>EkF$Rmil;mj z&luZZ@BiGFTDyDh?v!S0?_X}$g!Cr;_Ijz1K5Xx`cDe2$E^^${L-vZ0eY3T@=jDRV zvvx_R#P9ks7g@V2C(eFZDE>+p3GP)x#P7|@ZR*M=+Hmt(-|cWd7ONAp^6WtMW|>8- zS#2z?&C2%3fygUoReH1d!mljad9%8E^66QNmdDHe0YT{6|0muUCv)qbO@0tnjrBdy zFThp{fllgLvDE|?-!nocWcb%S%6CWN$aUQN~;HJum7>UV-jco z^FOrbyLlZKvAe!ImS-sGs&WSFy7O)FgHX}RKj+q1f4Hnkc!`}lnI#9If9^czHWB9h zA(>Y(_|(e)EtB*E?p@+pWi$A=aHRPAUrUaq-1q7;eD+>;ks zBFD_*&k)!1Hjfuq=G^7JSCcl{+SXv*kF_>)zd;(?iqg0r=_}NdqBpmZZpq&o^7a|hc)RCSyZl{a^H{OQ&U#VJM^YxZ-kiPO8@s-XYs)i= zd478RG|HU4tc7^hwS;lrfHFv*z^qAnJb#({_v7~0KGyV`^B?S(>ufozgl8LC1C{%% z<+?G?8(qUSx3MlKc@SO`b!%hp`m!$ZK4tzJXGQP*##v?eN_w`HPPy-4){5jBW{rsT zS=JF>+In)Hyztkvw(RX)ed{^iyNT`FTix0eb%@O)b07XYK^$vH=bBHpKg{!%e40Sr zebo)DgFHK(buQK{y%K+|a_b?i>qNbW)=c7EEA{5Ak@crC)@NA{pE8CQ?GL}c-{zI)l3rO`ogP|SeUdW#D(9R{Sa1&qcpq*4c>BZu zAncrd`i0FTzK^y){1#!Koc83sQhsFrz#FU;%d;cztLrJJ5#Apu^V7#fZ zS=XXIHtSTkk0G7l*)?AB^(CtF2~x%*W!OhdzuB#kO1YxEe)KBqd6G+sW6hR4H}6!;<6R=1HKem) zW^p8E=)*YJMzPwTUav~IR(^|&{wXQJhsSHAkcNbjAqiqrc{ zzkHSSN?Ik&(?@tW$H<@mqx5pVq&HRJr?+l|SMAFhPtv7uuFaB);p!`rhS|fp$(YM`nasWa~^dL zZ9nbjH};`yPxd~#?OeZ3-E7N?ocC9*$NO^CdGfyCPRBi$`0ILT`*e>dm-fc$(po0KY4b`$P4rfuA9J~fUz|n z)!?2>{kF~SgZO~;VLDq>XWkas*RhrR-BvnzhC7Z?CqGE~&moUrDV;<<`s?r8@Qa51 z7&C}#hiN{Z` zZ`($lu{XBFuCR{)Li4@xpN(Tp3&Z% z_jw-9CiT)SuWkB?JjX`~d#!Yj`(7>G?Y`Thn_t>iI@RQfb194OlE3$zH?`(e*>81= z$-}AWC9QrwZZDaz?gzstuO)k2%6ql);gZRt84FK{jFR~Lw0oqjhA@fmys5RP{(xud zJ?-tnTKs}FCEfz|t{g4v{}1zy-0&~iui>BfZ>}BtSjv*OMbg23n1^mAPc|-@e^iGI`xmr2me2H6KYDb0wvh%C)v}ACg{)e=_zf$dlZ&^Df;| zGI@#YQE~q7;eY?Hg*?o2EYCfQ`~2Ux&%5E{?bWv)8F{zk!|koFQub&^UizT4WX5@; zpSfxJ>CxS{l}2aW^4#?AJ&j&;BWd?GYUcS14c6aN%tGCws=WUbo26;E7JV>4RcK`HH z4{$wGH@NgjIs89LPwbHYVR{PtSp0h4yYDvIOUZ}L^d((g;PH-#P4*B;{ax7S;qN!0 zuRi`&>J6z6rOve48B$MoQl_L`ko_mrhclk_HBz5$x&6@1E2&#%xcW?Nrf)}EyOq9P z6z!|*MSBic;@)-4ULT5P>+Urlxof(;Y_gB&S<0zgfA(d*&QGuZKD}h}|LZJ8Z(ix@ zN1IObZgSljZm$#XpsBaqKE6**d+J`fo;%O)pL%9b*9X)^A5yPMyt1#!-M`%X+q@gn zr$G38$L>|qEbXJ%WG@``nt8wd`||g;^}oMDpVNPiyn8Rn{x-R`^cA;1H{!>ioaP04 z7aw|#`!IcT*}u5?C3#m%YUG}1mu=l5_q}X5^$=s&TfZBdFX_4MxtayM8y`hBCN?I9 zO<`-`=9kVnIWhm-lE|eEdz|%?Xh&+}c_pjnt$xf~Uqiq1*{D~YVElF#?GydP1@&l3 zJCYmkh;+;&kE>rL&+D;2hd)VJ3t9<(&Fh%EnscPjKOLL&3&fRi9{F>h+>_LYZ6$>` z&)wcLk8{@N#@~9=R?WL!axQ7##&}8Uv==y6()|Ih+`HtHv~QoBR&%d=AIPt( zrN8iXnWPx8)2`l>-OcizG)xy$$hW}xbbc;?ui}3M`)Rm$ax9hQg}Ab2I0pZzxJTo9 z*gg*ra{MTVXW-t&@g=xBah!q-$Q0PlFb=j5z6#J{L{FrfiaDj zfHp`%3evC^+Mxq7a5AiePUwPe=z(5X4_U}T9=^o&l8}Z^NaqJ|KmI<#Hoz&c5jMf8 za2lKr|3P;ZMDR=DZh=;a!!d9ytb)toesovh(x>xE(3iqZ+*dot$HANUkH?kH)R|%< zT-LR&;rLp)2L2K#g(#H4Ft{7eB>XJc3}=JvgE<$@gN<-0@LqdsfU@KLg>$YT{^7VI zU?hwJ*-s*CoIAl-*coJPa~Bv7yTSyR2$NtkOo82CD(nt>z%?Ee^-Pv9Jn`gX7@@kmI~qufQo>b0chmQ{gmth;yq6n+?lgIjn$Ym;-ZR9?S>E72ct67#t2q zz^C9ysDWCjgL-IyMpy`oU@97@8{kIR3X{>wdiafU z4#!_cQ;NG8H;P*Z!(cd!fRQi?M#C7mo(nyI_FwpAp9Kx4_jhdnfq%k3U^~1I?}5j4 zKEP!#>W#oZ5=O%)XoWb)Buxt(4adL}oF;22Pr?K^1TcFM;-HV~P2=DW+&yvkf*4GP z{jf3j;2jJb;askJ4}1~61oy+2;Q{yxd=(yqhu~p&1RjOQ;Bj~Yo`k31Yw&gW27HEe z+ypnnE$~_R9NY@Kk&dabJL~~FVH*o(4<_y|Fdk%$O(y;(!X%*a_NKsYAnU!m!yfPz z?qeFRtkubW%@|CFy9smcz`5a3J>>&Ko z!DT$@9Sr3#3l4z_sDvt*4b?CQ=pcFXU_OlF9v9#q3iZ$cjj#|F!D48FqhJXvg=MfD zRzNcx4J)AqS|JX{z_G9jj)UXj1aZ0EiMS`hYFGmaXoDoAAPsBbN@#};$iT^PqdY&j z8NSN>KM3ovcfu~jJqC7yL$MzQk6?ck9)rh$@q*V2W6|skva}}4Qp`_}9&z75 z*p+ZMTm`pa`z(A8ZUxz&BI`w?;2yXaq;uQ=jc^;>4ikZXw%K1W1$Q@?3KdWZRWKW> zVGhiNc`zTo2zSF%a0|%(>3g~MeeeaijWn+!Z5QC4K-giphr>$f}7>u;j{2LxD~d-ZE!o>0e8Y(@Oiigz67@u#~pAd+yx9Y zyt804oDHAHb~oGu_rgSM=fJse9^8lR3-Cqw5=_E&K3o77!dAI|xE=0*y|L{Bi^zw? z&;&=p5?Bh$U^%RSOX0i3`91hP`~Y5rAHt8|$M6#T1bzxXgP+4M;Fs_#_%-|nUWVVo zh44H0J#2$l;8l1HUWY%xAK_2%2K*WR0&l`w@HYGv{s!;ByYP4T2fPRWg!kbIcoLq1 zuff;h8}Kwd0~f)w@Ekl3--H+7Tkvi84t$OK|2ljFo`z@OS$GaU2e-mjxC*X@Yv5Yg z0@uM8-~zZ1E`p2U67lmKE`~>W4v)d(@C5t~+dJ?sT*~ofa5+5BIp2gA;9Kx*_zrv* zz6aljAHa+7L--N=7+!*(zU#tQS0BQ53eAes;~oG9!XsSgQIL9D>hB9d##bK_b{?DsQlCkglCtE=nAC4l zzNBoKvW9yxx-GC6yS&>+!6G;m zkh=SJI18k$x)b* z$A2ue!z#EOO1ai?xR=41a2&^Pp*;qF3H}z`n>fCfIIe~_@wZ}&Lxk{^xHsZHhWj{3 zT{Io`g3BQWQde}sr#V;Z<}K(S0;!Yl;`kEmm%~LIOZ_eN^_{p^UOEirEb3lcO&lW@CT53E{p91 z?%^aj5k3w7+xAH6)Dwx%^%Gscuz#OY`j4)!DE-86A2Zyqlzyc2A=eY9)a_EYNx%6+ z_!qdowA6RfhyDou4X$4;b)fX8KZZ}h^|7T+@8mwap$mFI>V&({ltGT`&E@z8beF;= zY-eKI30nkz7494u3sR5d3ELm`18F~`J&?BLt8f9FhJ7z|(#PHt_bS}0VH*Az%!I?? zQ!pJ4h9lq_G}pqB_{(7(v=dh|?t{2rg+1^~AE5u3OZo=)!hP@s_#%u(dn)NU1^?-A zKgZIZNn868lF5T1uT`g*8?^{^0JU*I6ZCllvZ+}&`eg6r2$!C!%P zBlpsWe?I;s?u%%@3DP#-g6$N-Kf!+-Zj$3!XpRNf&m3wj^GD8+e!@$z3B9!2XTW^? z3*b;V3}(X-a5%{Lu^Q&VVrYV+U;ZH~2klgIC~bkbchl z@Bv6)$Mt{S!~YC?2w#Vn;3x1S_#ylN#*@!K#(fdK56{7N@VKW>aQ+4VhX26V;Cc8a zd>6h4-v;RyehXfJXW?V`2=<13U|*O8capb1Al@|oG}nEbeOY|5)4&xLs&R5`GW#!YH^Gw!l?zEnEZF z!PRgdG{8SN_fPO6SWR3H<30+H!0+MP@HjjLkHNR#Yw!f;?ha4F1egfB!Bm(GQ(zL@ z0EfV*iTfnDj&#b{v;%(zt|zX~z)f&7+ybA4&%v#*0nLAKAA~*OJMb*D5$ES&KR5vP zhXbJu5^yc&ZNxnlHo}$K9l5B#ed;FbXnUXFXx1FbvLwGvIVM3(kgf zU^7HvHS|I!p!3Wmc-7y$=EIgEx0 zFa~yl`LFvM2=#Cf_9Sk&-+BhNy|L{BuI-dI z@=-XS>t6uU9!eXy3YY&)yXV?GY3rn2JCArShAprFTQ{z>XJ3VfK-xEH*WM<+zk+MS zT>ItPEorZ|fV5xIZb_Ra?bvP52)DyoAnjrs?*FuHkTyZ;d1(Wr4VU&?+UzyZ0n%Q` zJ5&qu&dIwb@0q+~@_xCtqJRDC-cxx$<=vF`Qr^j@h~sXM_f6i#D?#2L`RB$wWAHx) zkAu7izaxA)>;;!Y40_?~unsoDb#MiF@E5L;#s50|0saYJA&%og#?Qy%c43@>G^0j!xuT84`)K2<0N4(;vR?lP29i0Erfl7dkD6f&;l~QHwzAil`swNK({CE zUJ!%n@BruC4_}6_z#rjP@Dgky{0ZEhap%JV*wGmFXf%V3V~@eU2r8ilYC$`mtwK8& zWK4Si#Nj|_g&83ICd;83W8TJSjk8#up!U&C+V9rzXe4qk>g;Lq^?rSb8d6 z4aD^yj{A?1WxU&ej2j-`a?1bpO7X!Of7~vmu9nJ@;G+!{AIf15Sst;A}Vt zHbWUipai0@8hW7;|h~7Bs^la5NkX$3O!#LJX$E-mnlB z!D844_J#eR38un$_!JxoyF&%ch1t*otxyefAPz^t64)OOfCFJEEQ9565X^v?uma}6 zSg3?iFdRn02sjwZVKhvDF|ZTNhXt@JOoWwC1)qlF;CMI@PJol3n)2`h~45f@bEg33zc@n}3+8jlW(M~BCwBjV9f z@#yIIh~VVmHn!pJl;JM6;iWFfMLXOkAu@cJ4RVsw$jq^&CBx)nq*Y`Y;IDT$9LO+zXkoe_`n7-z<( z?Ir2qahAoSW8zU$QrGrMg&#VqRL&FKs8W|t z(MWvS?(u08UfprQ z!z6iyc!P(DwGeOcFtHZmjTGXI6yhx@q}SE03im2Rli;t}4Onsu#Sj;NT4&`Z!l9%4vnCRI*F(z)Hp!yt@{>L8%>A5|rC!I8cruO>&M zeP@jCc=pZn?3?G=TG4YCvk`kXX3s|L*|wbzT<^P~3s zs69VwuNSq~i@NyieMaqlM(uq@?R`e=eU{nlmf7o;MV!Iid6~QQGI#G~?&izf-IuvK zxU9s+Gt5Ra%pKeN8D{TixD6j}!-w1O;V#_X?{Is+!|nYJxA*G`&2W3auGkE>_ch!; zzv0p`qErnZZ{1z3D{ZLQr3DptvUR8U?g*Q{kTUP z*=ooo(_N3tnVcR)?|5;1+P?8=^WxJ?^LYekym*9Zf^ekfdGQF-aJ+a#skQpuDLIzf zNL;Ck#FctTT&aY_mHO_*BWy~~nYWASMy5-nk-%g6lVUObN%5F|l6WRcr%^nUoM*E0 zOmUuroM(pf%ygcEQv-_z;ZT@hNBsdW;l5~9Nlnq!^z{}*%MJx(;|`SUY7$hMp5l zH^BEXfF2o-+Gg0cx)Iw8nP~fp6B(fH$+wF`%LN8O1t8>9JqnOZ)&jEM#YS-Xhh7=N?d2Rjg1*miQP6fp5NG% znt_zqWmF=r?|Kswr;6) zCtH^posscrd&H+rn{n>c%Wi7$Kj~1IBRUkmJIuO%hmFZQQ!YpN!(y5CF{MyEw!}tl zSF@rpB#IPjrzqf>KC@CEuK;S>WMu3s4bjPHy7!~#%?rR zVz1@K!6l<@^ri0QC@neghr>#}c{9#0rANZYNaHItpHcJaTSgiGuI6)s`J8AzCz;R5 z=CjRwCe7#Ai0^pD+0#0{aWDU9FMDLJTe6pb&At4K?p0>a+iRHb3^z{9KQHE=5c5xn z`6tBu6Q=udPWL6#eaSxldHeWb`}kq|_+k6{Vf*@F6RhJ)Cis#G<_aStjDaPCB4x&m zYwbJ*W9KOt*NhLOg4?AeKF!V@ji9PyGHK^{bX+_-J|5jQ9-R=6PK-w<#iNts(JArh zZt>{Ucy#x8bdPv+T0FXEJi1pr8jDA#$D@14qx;08`^KaD#iRSjqX)#J2gaj^#G@7Q zXk|QF6_3u2N2}w}Iq~RR%7vXCFjKBlwuZSPWoAUhVrE3eGt~tJ1#u5&ndLl(I8R0J z+EM)6%gDV4-YAooZYnF7=ZOR@fT<8a<P4Y10IlFA!1&jF+C~B(6XwQ5~jTag1Td3N6fz)x4u|_b~ z2*w)0SThQW{Crc18J9ZT}l zyD4>3mAc*0Y4T+cWqh))Ro>wp{gb`08lCK&)#zeM-E?%Ce|sa6cXLPo_SuoZhVQG? z?T1eDJoZ<{cYsoNpi*}bI?eN7IIq&pR9^RBbeeoAS6+9P^16p8uUmmmQy<7a1dUGi z!D@7}A4{W?eHI#>?7h|KWbdv$$m0Td69i)8r|VLx}Xg| zLaCGe{+fSBYD8#iK=WSKqSNGaoie_9rLIAF-A1Kuq4K)2pHOqZi8<&5r(UM4;)1ZQ4;pHvCkj?lh(Dbaa~gI0Kz#+;}EB&3k#4 z^17SRY0A~v=rs9!j#787Qg@zGcfL}00Xmsu+tI%Z5omN5DRmbsb(bi0m!i|u8<(Ne zl$Xnux+|2rE757{m#ffe^7(3|?i!`;TBUA_Qg@wFcRf1IdwzpbccW7G8Kv$frS4{> z?iO^Ka{5`N?sMog<>gkTZmUvv8#>K>+^*E!flgDO-l^2xrPO^Mo#x-&h&1b{Il)2=?C)O`h=ro4Prse4eVdq}B!7@g+dBZwjj z;iG6Y&*L$4ns(-KbeewH6X-Pg{G?L%6gtg&^fh#v^89tB?i)(o(@NblO5L+c-E&Ia z^XN3~b|4YeOIabo>KRHrS1nx-HS@y50$zfDRnRwXnexlU< zRH^%!QulME?iWhkFO|AqDRsYA>VBity{y#zR;l})QulkMZktl~icAQR?1Q>fTc7-d5`Vs?_~Wse4DMdsnIZyHfWLrS3hY?w?BC z`%2vhO5KM_-A78@$4cG5l)8T_b)P78|556;D|ONt*YvL<=rsLe`FlQ^agY2hAB`@m z)XCox(!?i!vq_^HuGEcC>g4YrX|5}Oqe`Qbzlo&LjZy04Z!l?|ul$WBjZXfalSVgA zsoO=V8?V&us?<$T>Lx06la#v2N}c?DYE3@xrqoSU>ULM^_E74kDRp})b@I0oHTe=# z>ZU7odngFkR^OZXJdx4sADt|jrqm#cgsF~N3zfq{s$=@&3 z=;Uu5YIO2<5jDCRrLI<~t5fRg(P{FzL8)t0>J}<>iN?nsuca&1MM5$Y<)Gbr$ zmMe8Dl)7f6?r5cMrBc_T)U_&gai#7UrS4dzZk1AZoKknZQg?zy)}qrLGH|roHS|>UxyAUZrlm zQkPZgE=m2%FGp)`?F=SE7jTG<5vG!+)nM<2wVL zX1)7Nbej8>zqPEdsZ_&Qt2nN2htd7ogLWs|(R-*5fZy>Mlm7`F9CA zO*yy}o#y#ohE8+8m!s44$FET8u2kx-LZ`XktChNIl)7t`x-IB5|E@!)DSy|a)6Co6 zpw!){)O`k>=K0>F)ZMJq-J;ZeR;l}(Qg^FTw-ue{dEACh^B&!<)ZL-f-Ko^wrPO_1 zsk>XLyGNin)>Atbei|*QKjxNrS5U1?g@07cK=DG?kT12Yf9bMmAY>zbx$jG&nR`zDs|5( zbeQ0l&=)O}m2`;JogU8U}OO5OLBx*sTYFDi9ERO)`D)cshgdr7JLiBk7d zrS4}+-OrV}Unq6IRO)`E)csni`;AifvQqb3rS5l1-S3sUZA#rMO5LkU-D^tS>q^}p zl)67Eb$?Ro-caiPtknHQse4nYdrPT%TdDi2QujBd?j5D>U8U~tO5Hz{y7!d2e=2qF zD|H{B)AUb2M5h^de}qo+{g028x__b5^zZ+z)O~_ZbHD#l>UKB)Z~`VfHS?VjM4I%K zD0QVuo&0u}=DPBGUmBhKZkR?VzgeZ3Uz6Xo(&*&(uQWROy)2DRem_g2li%0U=;SxJ zG&=cRFO5!q?@XhU-$2voG&=c>JdI9%KTo5JDRuJOdYbs;_xCh9`CUGZ zPJX*jqm$qF)9BK&@>_$N_~iEnH9GlCLXA#-hf$-G z-)Yq7xbli%{x=;Zf4H9GmNPmNA~w^O5&-}cn#YLvQKrLIn?t5@pe_f0kTA-{pD(aCS4 zYIKW~y2VOelTvq-Qny5@TdLG8Q|jdRUN!kAzXPk$$#2?fbVn<7^1HE`_~dtPHM&-% zPJSm>6QBHMuSO@o@2kN=FVj8b>9Qnya2>s0Exl)7%Eu1BfsMW>m+TCdb) zmAaf#msjfgl)4Q{-6`la^K~1Qx=l*msY=~xO5N$`H1*XPO5K@C-C0WAW~J_IrS2Sb zn(}-uI?aB8^U!Jb3!INm^X~$s?m~1-weIlWMd&p91ujWiMQl;)PrS5X2?h2*u zN~P{9rS58_?i!`;TBU9aI?a6XbxPg!=rrpFH=xtJA2%v>pHb>=LZ`Xko0ak1f==`P zepadboKknIQnyv9yG^OPU8%c6sk;-MrXIQro#wfH9v%Ph@Za6a`0hccDW~_M)0Bhz zl)5h{bzfAb?@LPE{Yu@JmAVI%y00j8UsdWJRO%j5>K<0=9#QHZRq7s7>K<3>o>1zZ zRO+5m>b|DbeO;;hhEn%5I!%A=8Kv%7rS3VU?s=u|n@ZgaO5L}Vx^F9W-%;wmtJHl@ zsr$ZC_XDNwMWybCO5Kl?x*scbFDZ3DQR;rG)cs7U`?*s03#IOtO5LxNx?d}GzftO5 zR_cDM)csDW`@K@PO{sfDse4tadrhf(U8(znQujxt?oUeH8%o`umAb#6)6AE=iB8ks zeM_l(8=dCgUzNJQq0{_bwRe=dca^%oqto=q|Dn{qr_}vZse50k`#`Dt5S`}VM@rqt zO5MMdx_>KmpD1uU0E zq*6CZsT-}-jZx}$QtHN{(~RSHR_ewnue*y zDN5aL=rrYYs#3SRQn!avH%+PAQ>oiasf#If)0Mit(P_%dK1$ub=rr}(e&{sg`2Cf- z1C-Z2P^mjeshgqH%~a|RR_e-?x>@Kn{|-^cSE1BZDs@##-E4H4`lVW_o1@gtRqEy` zb@P?F1xnqaO5I^f-Qh~z5lY>sl)598x*DafR;jB~>gtuc2Bof1savSjEmGx`a~Krqm^sx|C9vR_fL&b?r)BhfP}Yb z)+u$JN?n&y*R9m`D0RI`-Fl@itJLL`y1Y`?r_^mw>P}JWHY#@p)0Mh2 z&}rr^&P1pAcNRKLyRccQJ6owcN2xnksXI@pJ71~0K&iV>sk;cB=HJCi-6cxhrRX%} z+JL5%NrUOdVSrg^x8~!I^|_^iBvA* zt!$}{H6-$hSW7zDm(Aoi9UN=wPR{ar*Clg91;(0})VFxc8mhdmR2A+V+&SLL`f4wm zgj}MrJDJ_oo6q!gOBCf+d2A-%!Qp^FbNax*=DJ2Xv%I0P#p`WLi-5!0?i7ad`nr10 z7tARZ%n1or&8evHQkiTzneWMNisjPT4Vh#*7dvp(EJ613NZu3zXMC)e6za$LfbZAo9> z(CF(^X?IM#5CtISE+WR*Ebjzu8H zK{!#EaAJ_~752D?Ualiy3Z3;2ELY}c8yd}pYh*~aV5-tXl zaIwhSvcOAsB{H40sZ=(d%kie=^4Y#*zAu|jnJ1s@>CThct($t&UKff)d%D3qD^H$h zrn|j0Ljg3!FP#-rLeBM)9f{7)ba#8YIg!hq(vwXU#q6$@-bmc3bgDj`&1cqTl9bZg zd_J3L>&vHe-tu%lmrQV7=ZV!*tKHp?gw<*pPpHZ+pKg#a>`>~m+hOqMewTdjSzdC0D8nGl|Cr9A3N z_pJS+L7q1Cj}(PeE+K*9ZNSvinG#c>E;1IWQ6%PaDOhu>U9}@7-Zob{o9mV|EUYro z7_p7ZMqg=S^0Tryha_|T9O};1C35L_wzH7YVu*>QJGU~ufm%l%Op&5swz~R6!BnKI zuZwv(yVsl=L6T!j*! z&YJ3c!|Yg#9~L7p77AUL-V~R2&dDU$H}qyR8+czZnB(SjHq(=GvSvTf#AbqHHrytm zw$rcIr7a0v9CJF$8=TpY_H!hY%k`zR{nSmy7#kpNOXM=idS1+YHj(Mh=UieaB$*^H zYat++?Ofj1)mFIs`jty#){-pbsCkANY66?gP&MH{UkOX}q7fy zY~4chgxc1c=fjcI*c?fPEn&Ru62|Myk-Xs?$;-X0plwUfhso7=LSVnLo$iDqbRGl|ZeNA@&i$VI6Kd7qkl!nr9~ z6%HjQOt5rWmN(P)2zN|8dJjZtvo@c}cc!I1NM)HQ$Ofw;Cw!Y^jc+q8itF)6ho)YllrE1{T~gEEOr`)%|b+eQ=4t(b6bPQvBZ z%h&bFJe zr!pHdslG%f?|SG$zLttKq&3xQHc8POpyj?vZb;jj?aSq3OL-xJw0GrN7S)F&wh~`N zeVB^XODDd^>&i7Qq`My^&o-I}7G^rRl})*Px{G#8VhXDJ!6HhfJM#(NI`;${8|2;IK#x2{HARmj?KK65GK@)kEvraEQ-jx%&-Qe; zOP?j1=uVTT4Q9Mx8f>XrDy!!AYu>TcW%4qL33UTZK)nRsTgURo~F5^*hX=6iemUFEKX7zI0uBQ(dCn^jPP&bYy$_ zc!fx-*rdTQZnjgLTsoOe8$&L!HchJ|-B)@p?cUlf?@X%G9~GG)5;2g&8)*bXO^cUf zgc&|I;q*XAZc7!P%WCT@y^gL#()FF>l`k|A%-lgi9A?!0Sjd$L`oe;KoZE9zUCX?y(cNRIX>=DZT( z>N)WT6-QIc3NMqRa!5<>qr9yrwaLR4TV{@9b@sSC-eS!0mZFeV3(Dur^HwdGWj>Q# zzBg9CEOw+RnU&^qj{msqlaiauby0bichNly4wCtTKamLeJKGBf$FR9U*qi81Ev8vxmZvDprf@Oc zx*|JIj6!Wk-{H$JBuVtzn$8T~!h!C73nPwjD7DxziOxRr4*JEE#PJ$4wxFw%Hwh1w zBm!-GE7NP!Su++2M~8vdmuj^+n_gR#_?+Jd3D>LP6V0`46D^wJYX&`$)}D3g?xJ|5 z$P%|-sG34$T<(J~dTL#nybS6FN3Mg#Ot8#J3<&C>KbGZr6c@zcs{X7A z?>%#GUA+U&4&?(mS$wyWuEI!o(BLFlWS-l=Gqb@sd5 z6WL@3gO|Z$kcVuljsba{+K|kZ^AWmWXM1^LOT*$*nBOp6kwS3@h0rt=pCZyzvWakx zB1bmRD6toxT)(Vk@bd{65JfUo-kAzth$`3=sT^%RuXQ2nq5#{<2X{m7+MLy!?de&& zV(p4-racoX!u^6*4y*=?PN(xp?uRRkei5|Dgj%Sy_6x4RhFkW z_A+sk$=im)H)gs9F$T&7vt4p3%LAovG_7E^%Tzjki)a!f-gV67a@T9=_S&q|WZTnu8M!4A z(llgym{`cQwfB~1dS&{xjt=lT-#|0l)7{h6)0bmV#8iQArH{>IP-sRaPq)tYQZv1@ zY>nM1JBVs(W*H{Nu^UyH@YcTWZdyG*&>olo>F-*z@k;CJx%;O)BoobK6pevYl9DIb zq-K$3C6UQW-D0u|GwsbFR)*#@PRwApZ0hQ&^$Vwo7j2w^nP=qc_Y}n1hq7BLJ$osp z!25c8d$NorS2Q)aD=~2vOq+z7dP!PQh~G)DQLXb++?>cJx;SZ2t0@6QL%l6?<-HwQ z=2WfHm2n>6+Dx{~T4{mh=-5OiFV(QM(oJq>CSe&pKbbEi+p_8Q`aI(n-|KGKS|v1S zO`T0TT;zov)E1(U8lYMFUHM&H$hr_9!e;Q z<$d|J^W`zSNaSMXeX7L5PeTnZR}~|rh>2|0I!tXR78$bV5>%%>-F`nrj5$*s zFYl2_V|yk&-Au2{-V|9AsZ=mtGPf>gQ@mv|Bb{nq(d&zxlFdXf+{eC%_ z*WbNB?$9seawNTkb?Hz+_Koe~++c#s^mxNI26)*`&D@mKEcS-T(xsX1bt~!4GRaeH z?3X56bR}Ifi0jQKY{v9-GZ4%&fs*KS9c*4y$>sElwRM>+6JkUxrryp(vcIj}lq%O$`G`}Z>HqzAZ%qiCr{gdEVNQ)uwl!-JV9GQm=H4-^=m>ZSJEL?R=BdX z3_=*F1OHKhugHUEi{)JD=ECzM;}&6oZ_kU(#tB%Xxj>&D%p#X&!-> zNUaXq5y|@6hM2tjg&DcphSjDXO{8L`Dm9bwGWHFk@TcL;a5%8}MbOxMZ+*6tH`N%- z3|9kfiFrB)Qk45IN; zVaR+!N0%&T7wQdW?J9zx++eHk<*`usij|9GrQB;+(cq;R);HBIuk|vC?nL2CufeV0 zdtL2ad2bn^?f$wo-5F-(rQxO@))+ppYdW4?zLB{sGk)}FUwu!myQ_CYmDjR-Su@Tu zW^6s;NoP4TN2}Nv@~4vQrC@T`OC?wMo(9&!dzj_zX8M(4#fkRVYcOVSd3@Y9YtT{Z z?qSqbyFv2Q&f+fb2`@>Spad_1M@640XEtbVl~=pGr76ag5MG`E(>yHdu}Uko18o7% zIY)C^o25>Lwq~DfG!)MN^Tu?=Q5O{4&Vx8?E%c>B$|W?>Rs=E97rmg!xlXU!T&f(-)VmxUf@mnlPMml;TBmo*V*mvs?mm$egT zmqjyUU*PY9Fn0Vw{P=_T@dxqa58}rk#4mamzvylJRdePB=@-9?U;Hk9@w@oN@8TD~ zi{I#N{6+myS@TObwRiVq(@p(COx(7{F@BbwWo3khL^df=}4uD zyRd$KRTX2CL?^vw#LHW3-Q?F?E7P5H2~swCH=|$g?|x!S3d6^=t1QE5SP|Oma<&p;aCX!&P?0htiLjxLVI;E= zvUR7pv`7J}n&)+`vZ38fn;KbeMXmKEm)9<9w0;Uw4-0)fH2WY622&GBdYj3SM6d_R zbp-wU@9JTlW56Bt(wJuZ-)6t!V4@Fia!YjDuEWW)xaM*}9;i%L`qP>I2*zvc%XCT~ z*Tj)(sWnR$bpCSKI@3$jY;OxpeQo({I=zhL`>wvO{?^3Cu+`mKq34lmYF(N3cl)sd zlFIZ1Pt-ILIVKrpfvSS7c=WwPrNm!T=*W3yJ!skD7SCDAJJJbBd#+$%p+nv-8lR5z z#`0d?ES6r&nU`>5MKO2vb>=e?76j0*PG`+@khv{WIvM)+rFyzInVx{AlM{kCPia@Z$j+MXw!>x`^sXbgC~XDKTG-_=5)WQ_hVw@ zAg3g8?T)ejr?qkQl!&EAUAx@$sDmSa$QvB4=?Q{XAG%0ZmQU$#41 z#o`qWP2IhHd3z|YB^_nf8{1_V?nmbvH!$29!ro8M>Yhm`JBosIusMWyi&9hGTG!&j zi^Kd2t}le!WDRCm6-uPJYC+`E5xS}~6-2ek_4SEtN}9-JIaz;|j4#}ANNBQ#TnOJq zAj}nnT!X9{2{E-Xvet{-S!nQmW5Cz~fxP!3F! zwe*)1U6dPX>Rw-ze~sB}PquJUb5jEosZ!z5$ka8u^4jEHqk=6cv`!Qh+JOd_zap`P z)`9rN1ZNq`fOGm?E>vh6i_a{+V7S=vmbuG@&7n&L1uP^DijzCHUc!QihiN=K~vF>^qje4eGqop!q)1G#wXXO!!q$?wjn|*nyOm1NMhRJzufc;La-URm} zigLeoW2%U*I>+@AK}UjyKV@btoGD4(n7+F+m?XL?#GGX&%y}34n0heHldS zl5!~tqB95f>P+Hnl3_xuoxbBKiA}NoDKg@s%NPrn;Tr7nke#aoPBPidz`M1B{ikwC zcAljC8G|4JCeHH4Wykch)KxUg2tTm;S1PYRW?6qzt9kaJu|m|XRc7KPFWn)Tfsyh%P}H-oslJ{bi-!~I$;R@sgdUSF zj9IA-Qbl=gNN@1d$z)SHmP(u1w<2Y^>0FgJ)wb4_gPd$l4SYR^shNVImh#DZK{pdz zS(%kCgdD}z(!$X(8NOFiI9$eN>_xwJ>ta|=@}K|rSo=*q>LmxqGs$5R93s0b)b-K+%QE1HpE zrlT@El~NhZr4&N^Nf1B8&R+QE*y#&<4s$x3Gd~>L{BUeG#E;Dnv9b9fHn#bG&P%%F z+YC&BM`6+b%$&*25K4mQ;=k;{U3PjG!_xf(Hb(2-S-EEa~XET8rc&iHD+15KxW;l~o zd9({E!(P!^t7vviwluLE+r^|VW$KiCXKo1d?7`L5gPZ3J zZk{{1dEVgW`GcDm3~sKh7{Wfp4e_Q^aoH}3t$U>QvKGI$xGd2tyYhp|$q$SLW~#PK z8&zBXh^Xhp9t%adBC)PBy@`qRs^#UgJ+nb$wih;5`^IWE*e+{ay0od*EEdQFdy*=# zvon)02AO3qC}hgMNFj|(SRrjokwOeb3b#B_bQS;0C@vjD>VHqgr2|8eLLx0vh@nU! zSCPeqqN~UXL-D;7Ddb+l3Ue=Eg}Ilo!d``HqA1IxCGCHmu*SboNMo-Q(%4IdH1=Ba z2V86ZfNO;{{`#q3@}MdmMhq zk|q`s)=4L}rLnQWl(t-&22)Czu}CR57Af7vB6n*na+kiwS)^Po<_iYqdt7G!ihN1k zSZJF4uN?$iTHJSQX;0HBPGZR9f7v$HCYG3(s687N`+@{tfzGU@H7{SxYs&&evCM2` z>g|;-Q)_~%CCT(Z{jiMLpKQLI85|L*zgbxJFW9d_+2s@I0Whe_B{P{;#v{@fVXVGT z(!n~Qloz*AQw}K$p+kA_<}kF7DXR$bolMqXiqu zVvBTu+!s3J3v|wJdqd$vVhbHgRG~wOhb7q6r*PM+?a4*QoPA11CfnKD!!AI7@_~-6 z^>L$;O^fLJuAE(6Sy{fI+F#6dmWpz=1y*{CRo#m&oY{rTrCzdTGlUFsrvU*-QN4~K< zNjF=(d|QogQc6xZg(>d6*|p^ooV6J^;2xV-nzFbEjbyT)5cUZV$iJAsdAJ~4P~Bg) zpgJUS$tbUvv1kt?6!~@(+wnSN>cu{cKqL#ogME*TML&i`L)oDca8c~Brw1V&aXUi-3Pmwk!uF!~AHq{Rjt6vIu)dtJ6Ah3`f z1M_SU(ZD<#L^LqZ1`!R+vq40wSSc8g1B2^SDI>n25+`r+f5|EnyyML3CmSkJ{bc_& zO@)j8m)z(VAdH?rm3}NJ=u&en zsCG)JLFEee8?Dkjh(PY4SR$5?D3rj#+7OcLPXDisNYRCN5U0skRjfm&)vti=Da?MO5Uj(IArh=to;yQy1tx3Mu zE6>y4k4hhj36Ri)H(ObJTljA@=0nOvz|$7b{ew5izgP^+Q88Y zx?st49s5RlJ2vr`5!mr+ztrJ}nAyO5za1QMywQD)A3t-wt)wNxv}GuHYZFPfzznio zVq;}hrJGwTn)A%GG%UB#vSFLeYV3kYIVH1we1pKO{};aM9Bi(4sa}@mJDO|~AqUAU zqjnJl8|nGliQ7ER)S66G+pl1HJ*O~lY*f!~*a<}0a?V^kYd%SKn1-Gx{WJ5Wjqn6x zN_O=zv&i=l?VrivuhOtR!~Ys7TX0Bv=&=;C!RZ8zykDA9UH;$Pq5R3l_U2<( zHkB`FT;kPB=}tZ4qc6LdLwVSA|-9(L@ zEO6t{@Hiu|*`$YcE*&!E(rC9AQ+fD*VMQiMoH6w08kQ|uSjnE=wdRlbv@pxt+|nW| z5$vUDW}U;`&8pUx;BGcDjVyM#oU@Bx?DDn#V8kbXH$=u0m(O^pp+Z%Z%$O?9+T7j&Axbj5c{QVomE0DWC* zZFw%)!Ip3GYcPe(=g?1{azxc$1Qq|oL=nx<4@*S(?%v~ z!&c{#y!iF4ECHHhw}#bH-^#R0LDt*DN@e#TLguj~AS9JlTH4V;;`9TM7F{{ic*e|S zPiF6Gjz4E2yA+msMMu)3a(_%P9MIBQq?5gs{r|{dSYBVGwp(^hXUAJqUw>%qK)ytj z$o9lIh|Qf<#au__TxK{9l7m^5F*&S+9sIG+2;ouh-R*wx%T~)w_&|Fzc8TXb6YhCW zSvPI%57?ycVeO|{`}eKA#@es8_A&N%84tAfyRE(2+V{0~KRpBUt&Mmiq5O1zJKNX0 zBO3|M*B}zgXZKqi&l!7J@Y@`3?Bt*GeQSTm9=|LZ&%d8Sgnavvy-{a>+1ekNDJswF znc}#K{$JwH_g=6`*X^42v9>RXn5ccbbux}m0em{1}pF3>^+~X(5dtwOv3s%3>zN!yc z{g18v-~H?_Tl*JnksHUc{CmsVpR#}K+&zbnto?awzr~k(Wjqf_=Nc=VVDoPm?1Pn) zX+zle9l}0y2>ZMt?6pJKmknW$4`FW`!rncEeIs_shrIn`#aG$y-$n;!X{A+!5?1Ucca-)*4@`zwR-8|+Lpzu8&=fv#X#9)hH-Y0F_B_r zX0@E`OY2uGYxef#uQ~OzOFS-y%Ay$LT>j$0>bjQ3+LiT-SJy9VUcGR+*V#RoH8-f$ zT+G}7k>%u6<0AHt`Bo@@n9A$Un3OUWYgt~odPUt)jrFaonG8zv_uGzZZe8K~`P)z= zM>Zsh)7h~apX|rvJAHh!bv1v9nvRx9w4Wc=LUgNb4#`QW9@$HT$HXsz{MFLcq`(tD z36`YEw=?B1#W#kLqHrnc;_RNJ7&H9MA$CVLu3WjAZyBuS?;6PWVYxe*K2&;$Kv|Vt8~nNuilXEVM{s* zaeSS^f{yw$dtAbT`6RoidIxbj=A+|h)BR3bI(tgz*gz*6=$sblxaT*A*nIYp{+S$) z$4zzj{Kg+&35@?79hcYbV{E2DpX2!k8IP0hdHNU~`$zpQIt5H-C*T(_;e=#f=ua6t}zgbw^{&e3LR_N~fa*qEK zrQ@IOtw!$uGr953@qdx9V7vTQsJo8;M})<{Ty^R1)*I42#Q$f(g1)-@zZvMy?+xi5 z{yxy3qGSAiGQK0O`|ViXsr>$Fbbmf8Wc&i@mjdIe1nbOgIk&gYZUXk%S|4U`O z`n7cba(zz5Yky4oyy)H8-bME>S6ljexn}VDF8}&U(EZDmmhn3O17*DWv2_1(EMm#Zp$y4e zNA-JTJZ}H)_0(}0ul^7n^Vi$?q;&N5{DgGWXV2*ET>tVW=>FwBkdE!@Hg&{OGhu)#nMr~T{=hiHrYKK6F*A4DZan>6XM5; z$NBmT=6Rg>?sRv*cArYp-Tm76KGK=*(2ld>$BUmSuJb90pCIEe7T5d5wc^Lf`0K^> z@vtGT&r6>W*ZFkl{(g9l?(c^ge0>W0Q}@GsaeY2>thjFXH1U*NuA=y`_&V{q;uUed zyd&beKYuTNqI5dqZxG+GLvIC__jTg#WS=>{E^yf9#}(&0aiF`5&fT2ceb)J_IX=T< zIPSmheUF?tw(B12^PaogN>Lo0ufL`TWpQ*0T(9uh&1VJItK#TvokJ^PKoOip0DG2TO6Gqu`?x(j=P+lfX8hAVsZQV7wov#TikxQtT!x5%6RlY zN>7VpJ`b~#5y$w?a(veFFVgek=seC&Q5>Bn$Co_6pI#A1XNn#7dXc+ak8*rX#-smd zdP5wYP3(+`V|+i?o1SmO^$Brw`uX6|7Ds0@>wOp9eUf@qo9)(K&*hNpWq+>=Q-t#{~pJ8JjeUcSlsJcZvH=~ zC%5i>-Z|c%#**>;cl501|3P=JU%Adx^pZFJS$ahr*ZbAHT<&!(*ZBv>*JM0y4+DH0 zX^5lq33kTBF+RcZP0!uy{%z0G96#y#Yv~aLZj7&|x%m%seBART^rSdCpJgX4 zj`_ct`aKG zQ)QQs>&v-&{S%JP57|k^Y{eEg9{bEjuM~bnfGP$^jn{N9Pah)Wp$wkezzKN5#?k3p-75bpFha zdwtbiF6S*7k4}f3NpW-r`SoVX^V#(7m1N`4N2hN;JFq2=69IG+i&Uabz|p`(Gz_A7LH_s`ynNc{qQ))r#*MiGcw}nypkRF`m@{a*8KXH zm+|OtPcMq2^J;d=;uyax$5%YxlU@}^=QZrq#nCx{;~SnILmv}IC(X{dI680Qc=tNF zyS&cZG9I19>`aNHQ(&j#`33aYpbfIcU0+ADlMqMey&Ugehj;TCp{Hd$=5qo&8F6$z z&GA{!Z=vVK(aEt>6i4S99AEPMK6*tQoj0*l6-Vb0j<0$CB)uVy&ROh?iKFA*Uv%#m zxc##$pEpd%cy!KZr!9`o0*;^b{BU|l9G!LS#AeuvEpEG~a(vwL<@BUDI`3sCEsptI z%<)5>Uq;W0qjMQMd2w{EvBaY4vd|nc5XDhb2>nlNb??=GV`3yVmeFrywF2|?5&XM#X zadhhJxc4JmXDP?$WIX1%ie3;$=dHK`B&))adf`RPD&j6=WdQqdwwrH z=lPH5dC%SR-LmJuzG0%HB&$>9~>7E}qJb#LvF>!Q$z|OchI{)DKiGa7o z(Yc?UMBG+var=21K50wR^Ho^JD3GanR4$DTVJ+s|9``FC6#LpO1|NpWm=1 z569;`UqCO2qqEflJFulDj?NIr*F8U;J}QpRbatBJ=$ygvM6+$h7PtT1_n)zVC&bZN z#7;^a^Lc^uNqfF6zc0#&qqCTuoH#oBa(v$NMf9RLI!Ccn7Dp$?@fFX{q*uk!c^x}- zadgh(_=e{f(Z|HmIfb2ZadfWa_zBP5_qT0vbl$|ylsGz{XQ$)&C_Tm>T*38=&N6lq z;^_R0BgovJuG zujBZd=O@z};^4be`e(g6A*LOXBF#nEv;N0{^cId%%-=sd(uNgSPBwzmUY z$^jn{N9Pah)Wp%5!%jWmqvGg1$xc%ooki@72fQVY&U5TcilcKVJ5vF7zg*!SSGU>U z&SXnG(K~k6?@{a|0-h4be0F4KNF4KdJv*6z=fu%@B|8Oibl$>FG2mr!bW-e$h@(?v zryB6OI64d285KuoEjwcY9~VdGP`bn@)v#L>BloqWKH;^-`6r!0<6gPlsitK#Uqot?TkI$vX_;rZS4 zF>!R(urn@>&I24j;rV0qwm3TPW@kzqofkR2Q0De1@Gd zadd9v_@?LXb*l++bUx2cTO6Hx*qQYFhxCp(I-~5waAsTF_4Qkhj|V&{j?PAQ(&9Mz z7&}7&&x)gS7dv@zocvFA3IQ*PqjNVq6>*$=nw^n=*Tm7emz{<q<>= zbbiFngg8#VhT~fSpA<*u7wmMzanikR80~H=wz%u@Q1;{E==_$Qq&PaqaeT`2Q|LqD z==?i7S#fmU#_>7N&!U$+KZjoSd<}g>9NYafw_6j(c0a)Jbd1(Q&VPPI-O@JJBm`kS(~r(0PWPxHvlQb<#w@Q{w16$Ig&AI^X7Y zGXc+uqcbgS2euT%(Yc46qUZmMUKU4Z20J6-==_x9s{yZzqq7q`qvGg1%+6TA$Hmdv zgPoQ*I)7rP9q=h}bmp?-eu>@P@19{N#$T%OJt2 zX9srj0WXT9a{@bMaddWPrxNh0I69}WQx`{PE<25YkBOu67IwzP(K(cziGa7o(K&~m zDRFdO&rT=cG5*4lyPv*;orE|#XR?zFcv>9uxtN`dI65VEvH{PFqjNbsMR9blVy6`F zia0vguu~OB=S%F=0^Sfu=QHe#iKFu)cA5d75J#uMPFozEC)k+`ct;$aud)+M+KMgi z{uuG~@p!V!|Kv$=biU0_S{(D)iJhT=%9d>d7FNmYFGdm@5bbiB5Ip8DW=@>yE*@5p{j0e0Wj?N+MOp2qEVrMGg?vF0@_4S_r*gse7F7ds3$8dCxVt zlsM+|26l$T(OJ$;Cg3@7bn@&J#L;o@R}}+Z7Ds0}J0s%ge4O*C2D~ng&MJ0B#nHKw zow0zAi=%T9J1uc^?q{bR@F{V0E@da$+g5CG*Vlir6AO4k9G$D!Nr_`V+w%RDbigy> z=zNNuoH#oBu#*pXQ5>CH*eQ#nY>?Fj|`8qqvfTzVVpNH7Vh@cCrD_i=*>6 zJ4JDHo@J*L@QOG(e`TjCj?T_}f2bDlhB!LUvoj`+&O&yY0iO^@C$`8AY-x+5vxJ?= zfOo{vnZ-`*Rj9pmKV8jEJm5)jbmp*=7RP+t`+q|L&x)fnmz}&gI$z;@3IQ*PqjMlT z6>)Ta$j(T>YvSk}$xcHY9rr%sXuzA|=nS(nA&$=9IiFU*C&ke@ot=(2I)E1-u}R&O6yDiKCNaryTGR zadh6#PE8!0^Vq2ed{i8r_3Sjo(Rn{R;{k7pqjMcQlj7)H!_HK|qkV0VE$;fdnVq;e zI$vZb5%82a=5q%-L*nR+vy%yUP8^*vb_(L?JkCxr;AL@izQ@jpI6B+#eZFeI>*DDA zn4M8^bW-e$1$~sPin`?t?are_X>?Fj|8Dl3I@U-~0HvU!YWW>?A zo1JXH^Wx~tXQwER&iC0V1-v4T&H?OH#nHK+om#*f;^-X8&X_nlKWC>I@Ck8rj$)@R zj?S;ynGASG9GxsXv3a&)i@Tpb%1%7sNpW;eW+yF<`8>nUP{6a|=$ye$UL2i4zF%Gl zcu5?crR-G1(Mhs167ZThI_I*}5J%@Ac18o<6h~(@I}_sQ9K}v6;FIF$yo;TVI65b? z`VpR{Sh>GeSMjo z_Ga`=p z%-GcqY^i$w3VK}}ou9Dd{;q)AKXW;LOva<{d|VuzU$N5?$M}QUX$O2t9Gyqlaeutn z&F46F-0zF~?tbst?dQkYN$qD*Tip01?6}_p_B|uxF`vJ%<9;vJjejdUc^Qw(>%1tA z&a>>4#W8*rJC%S}#nE|@ow_(Wm$K6c_?S34+Z<>Iwv3CT^C@;F0^Sx!X9sqs#L>Bh zosQ=l=&=Ph$QE~f?ZS@xIeoXEzt8bW8IS%?>1lDyXAgEV;u!xh$7emCr02!a*_WN7 zI66;pe93e7b4wL*boOVbDvr+c?9>9@5J%?_cE-ffnaQ8OX$E{k9GxTCX^W$iVrMeo z9dUF{U?;|(3vk!h5$wbRo)kytWOmZxn9u3#3iKDX(4s0n0 zd_)|b>)5G@Bk@Xh>H!}WN9RU%n&L&Nc;J(crG1Uw~<`Fw+&A#o($#!e>SIdOFEW~U&I#2R*r0WXWAGtSP4I1*Q~Qw?}s z9G#!CEQI6A*$C*tcaZa%+Z$Gv{jsyI3~u~Q3pLmZtW*%=c@ z=d0{A13n>+&I#rHWVZf9pa;4N`=eY&*@izSS`2tu9G#!A zGa`=8E7++9ye^K;uh?mcqqBgWcEG2^(RqZO=nz}6#odn%XD1f$gg82nvy&3XeB93& zrvsi5N9Ql>lq=tuH|ii@N3A$F4D=E6NgSQy*eM5mL>wLW^{gh2&M-T5&rhR|ilcKY=hGBNXDP>z2fQVY z&YkQ`ilcKLJ5vFV4zoeFxX0D6vlACb=bcH6vfqdG{6onuM=5d4=bP*diKBB1$7ejh zm7Wtv=UeO)#L>BfA&$0IX>(8JL!3Gbe?6WD2~p1IldI|s^=fz_?qXRrZ>c~-9A2F923WOH*kD2 z;1lBLOk<}lj?TB)ne_Z#dPf|c7(1~eY{eFLfBX%{#{-@eM`tEGX>rWwadw70-$c)f zqq8eJd2w`R^YBroqE7W#nCy6ou)WC?)PxU1KtuxC(F*HI68mf ze5L{(Wo(cw?s4*DcH)^XZ@wP?&Q2oWDRIo_40eXZF`upYdnTEH=fu%j%1%KXoj5zi zfS1M5IhUOgaddWLryB6OI6AA@85Kw8)$EJ~d|Vuzcd^qFM`s~B?SM~-qjL#6(NVTy zi@V<)&Q2`g32}5TXD20&`JBj3+Vj)s8F6$z%1%xkopU)p@A+DKQ5>D?*eQ#na|y>+ zJin4&6-URtj#C#$=Q@sWc>Y=Xm^eDOaz5kY=zN*uCp`Zqy)BN;o$O4BqjMj}cRc?& zJ$AGWvc=s`zsXKQ9GyovKI!>?(9`0W&pqs9#L;<{ zN9Rd)V#nBuE$)80n&ac1zlWX_N9XVCq{T6x%Q=3?^H0;W;^++U^`^WyI$z=Vg6H3- zm&DQ8nw^R`I=|ug5zqfduZg3x9Xkzibav$LL5+HzqBq6Sna$3GI64`QZv}i(9G%_R z>4>9q96QmmwqlFB9-YU<(b=7yq&PaSV<#2xA#rr}U?(e%&Kuat1-u}R&a2reiKBBW zJLQ0nh@-QBotij0=de=`_^3EKhp^KWN9R54j0e0Wj*fdhdQu#n_3TUq-2HQF_qh5x z&L@7Ho!J(5{kq>9Oawe7j`=KMXGk3LaldDn33yH%oio`fh@++-G==_?Uv4D?@qw{XgrzMWgW9+m8J|&LMrR+q<+lnpj`uY!c zVgXNxqw`UAQsS7;6g%mFXT;HQ?>FSc(Rq=be87w1=-kZtl*Q56;nj9vOC{h{add8H zr!J1puIw}dJ|>RN*V!2tM`u5FCIa3TN5{R7G9`}AYuV`pJa&Q&vc=s`{}< zoe6Pte#cHL;FIF$9L-Kg93A(2&e7{^#TIuxI**H^b0RxQadh18MW+HjB#zD-*~yBd zGqA56*pdr)K^z_TK4nQ9otf;E13n^-&f7Vknm9UpvQrQEs5m<7*lCKRlV)c;;4N`< z-p9_QI66nMGZpY?*aq3+9#`G_uW@m7PG=_(@RT^_a}DP+B#zEfb}|9aiKBBpI|Xrc zR$A>V)tyD z@2At*NruPG&!bF;qvQU5L@VHv;^=&U^XZ7A^DyTVon$Mvxa-k*TpXSC>?Fm}aes#*74RW( zbUwjORvew@IGr4sO}I6A*)r!J08oSjC%$HdWjoSkuTbarEB!t;IUZE+MP{`F^e65{B%zmt*-cv>9uaX+7z5l82ZoKH63d2w`}=6s6c=$y??Dc}`xbUN%* z#nD;IPA%XKade(zXG|O&_jg{J0iO^@CpruV_HzW{=v=}1Oa{Coj?Of8VoOka>3;eN zcH#j~ilY-_CoPWoe36}@fM>NjNgSOFJLQ0nh@&%~otij0r?68G_^3EKX?B|8=$ysQ zc)(lY=p4w-q&Pb3*qI7=beava#XYVLu@e_Z=W=!u0Z)lzK8Le2B#zFf*vSMuCyq{r zoq{+zx3g0Wcv&2sW7!!IN9Q~2R0CcYM<>h9s5m;mU}r4g^lPD&i}*?vB%b~_DtMjV|yJ2`Q5_FyL;@S-?6XR=ck zM<>lrCE!(YbPDX$#nCy2okqaN#L-#7&bT-_XRtF7@U}QQMRumd(K(-;PQYVtv_ZDG z`{_z{65{Aw%uX`kX>rV_#7;&WosY7U4R~H0optOK#nEwpf2tJlia0uDcBed{pJOL0 zj?O38$pyS1j!uJ}k~lix5Uxe zz|N#NI*+n574YayHpmwDxH`s8TpXRhv6BdRN*wdKi=82Hbhch#2exDao)br>$xcBW zon6=|2D~he&OPjmh@&%?ooc}A;^>UCGb)bG;p~hBd|Vuz``KxUqjM5F?SM~-qcg!y z^k!SJ#oZs>|I3aAJRy$G1MH;4F`tV#pLD=8;^?&4$%&)$5q9zcFN&k{5IbdYbZ%m& z67Z@xI&F69;^=&xokqaN#L@XZJLBT$+{?~Hz}w>JOtLd2j?S;x=>$CX78_)XyPrP6 zPC^`=$Jt2+JS~p-OdW=*-5Cb_xM6iK7!|ry`EdHSCN8ye5v$ zY<3#r=-kTAXuzA|=p@*g5J$)ToxxVXC&kg(ot=(2IuCF@(OYfB7Wa7TJT8t-lAWYD zI`02|rUE`Bj?O;pWW~{Wmh;I4ydaKFik*@;Ib&~9G#2UNqFx5Z(vFs z^EsTIA#rqWWG55woH#leb_(L?xWB_#40u@_onzS<5l6@UKfY?f>*DBS*%=i_=YC$U zG0%TV9~VdGM0Q%@==>+gw*x*Uj!ur9XsNB(;_if-1Ov(pIpm^eBs*clf`=S+4c z0^Sx!r^wEfI6CLE(+PO2V1sON_tTZ^Bnn;Le7#@HPBP$Wam=U0PDUK_`8Ye-fak^0 zS;tOM9GyGZDFwVDj!v1KsyI4Lc4`4{h@*2cJ7ePL{EVGuz$e7fsj$-)N9WJ%Oa{Co zj?Sg*#Fp8LE$)8$cXr~QPhZpcek9;EadfU_ry-8c1?-FlyeW>(C)t@0N9R54v;saUj?NA2bi~p52s_bP zwqlFB9-YU<(fKSpNpW;O%T6lbL*nQ(*vX2c^L2J|0WXN7a|b&madh0@MJ)$>L>!$v z*{O-6^Bc~m?z#K_M5E&9e1n~)I64Cd*nutMp3kJW#L@W{JCow*?9K60o*zt)mSZa~ zJ+6L_owztU?(e83JbyDgDRIo_2kZ=qqw@}q&v^bpdQKdjpRiL9N9WTVUkrFz9GzdV zGa`=8m)NNWye^K;gY1loqvQV1#aO_{#nJgKJ1uc^9^`!50iO~_=TUZ|6}DoFyFa@B z2N4T+LL8lcXD20&`8>n9v$HdY3J3Hgz=p4)lPYS632Hue;Yk$&?o=Xr5-rm<5LN5}nL+LGtLWWOSg&i3q7#nIWs@iou4 zKFB_4%b4f0=uOYv-=%GPz8}X=dVVN9c1~|QZa<$uk9&R^J?;52`jF?V=y}iILoayl z{w{6B^N(}T9u`2;%|adf`TPB!3qadbY(PEj14U$avRctsqYo7ky}qw^R$wSYIo z(YcMCF>!SM#7;Bd6XNK6m7TUYI)7znGTz9GxfF>4>9qBs!x_=q?q zXJ=9zo%gdd74YZ+8)S=nT-}GAxHvlN*+~REC64*bXJ<$po$J`i1Ux5>&VlR{#L;no zx1<>GvN$@2voj)&&K;ajHQ;q|bdF_bR2&`m_uR(ViR`q*(fJEQI69}X z6RolpTipHe$Lz!co)AapOm=qzI=Cyvfz?BoMp6i4SAcFN-DJi$&S z;8k&S&S$4Cj?OdeGy*;*j*k1gtK;J6M2m4?-}eW+EsoBGoX?avI@8(d1U$AHTY2ez z`fhd-;^@p~CmHaxIOcN+I~j3w=CG3ucwQWxOW7%kqmyE%6!3~TI#;k$6-Q?gJGFo} z#L@XEJ7ePL9L`QN;1lBLe2ks8I6B9(Ga2xXI6Cg{?Z!&BVvD<<=Gch`JSmROXE>j< zIOg+ac7_6;6-Vc0cJkurtYD`Q@RB$>Utp&qj?OA}Mgm?FN9T5S8sg}b*%=LZQyiVI zurnc!&Ij0O1$W=`3XBsadf`T&UnCE;^;iU z&ZIax_lt3XWM*#+>M=Bz!T!=JjYH-9P@F1-y!Q~9N+YOfBJ+tI*Zt8i=%Tq$4`2G2E8MW&Oz+NF0>U}+}F)_ zaD3eJOXz9OFQX56?tVWg@A;=WzTmn0{gje8<~hW9R>XHR{}wwVp8uF$6G!J5b{gX7 zJi_s#p1YqjZ;GRH5<3&(==AaZ)|Tfx(kI2yc@sMwadh_P_~@OsVvD<8+|P@~#nD;D zPEs75@>yE`4PvDd;SQ0((@={3j`nj{CnaX>rWQJwF-p{I%R} zRveu+Jui+QK z3+YnhF?eRO{ z=IkC#obS*9o<`xdp<}{ilg(BOmBQz9P`gWarfT| zadbYy@h#79q)&>Y^LWM%Z0U%jb0^0~6@2!k>&tn((&f$f$3JI!>q&8Re#K5I;6vh= z&(j$@uq9jR9&NszJj+fl;01AX{*kc*TS}Gg(dN$VV|wf5fRBiy)6d&;O&pi&V0P*O z9~DPuTXve_=$y*Vc)(lY=)~RqP8^*wJ5vFV-fx3!agU$7uoD+Y=QHdi0-h4beCDt- zB#zE^*~tVvCyvgm*eQsk^Ef-jfS1M5na|FMI6AYBwF6tK0k4ara{xP|;^-X3&RD?5 z#nCyGot8K{Z)c|+@F{V0j$$YJfUVf#9zQQI8I67H&QsS7;?d+rjo)JgqWOj1m z==_wOe87w1=)94gvN$@=uu})dx5%9J+ zI_I-9C63Pd>~sPi`=AZ7#obTWu#*r+=VR<71D+Pgd@f=qBaY6U>|_I;7e~ka-_4>p zIuEi_3V1~voy$3&syI5)@i?&eQv%))N9UvLjESSOFFVbEPl%)Qadz6`=$yjNWWYP( z=v>cE>{45?#obTe!%jTlNpW;O%T8Jx^Z5unLjli-YQ?*32MkT^QOVkaw(&UNhMJpVSmAdb!>?3BdO z`3uLFJ>M>CpR{E}9G%D6sfnX=Fvr(DKaAe=JVPJ%{6u<79NYa1w>v40?XKYXDbL;i z<%%w|LAJQZPxt?H<9-wiLwCxtpD0 zz{}$3Y|YMyI6ChCepLfr7e{AXc1Fd~d6@GV3;4J=Iy2a5iKFubJMDl^iKDXvJJIE~ zVvBqH+~#$?^;p0Y;^^$iPD&i}*@c~Sz%%0L?8Ht^9G$({$p^eBj!uG|vN$@gWv3GG zsyI5ku~QdE=Z)+%0zM{=&K!2e#nCy7or!?A#nIW5ohfm2-px)Y;IR=KWQ)6>y6?vm z;^?erCmHaxIOel2=aUgf=O%Wt0ndx0Gmo93I652IDFwVDj*fdhp(>8fkJzaNydjQG zn)4YGN9T|1Gy^^%j?Mw>w8hbJ{~vBL;2m*v4rV8Ig{|1)?x)XiKJkDj#kaNdEoLVz zj`<7>qiV082Rti|&f)Cj#nBmLrx5UxI6Ch2oQgO)33f&TUK2;>XwIi0j!uf5(SSF_ z(K(Kt32}4|W~UYKNpW=C|8eh#qjM5F(T8ot7I!^5kBg)8dd?>)j!u!CRKSPC(K(5o ztT;OFWhWQ#f;c*-uu~F8=W2G!0Ur@Z=QMU|;^^GMPCekG;^>^gPE#D6Z?H2S@Rm3_ zZ)Rsw9G!dEnF@Gxr46#hJ+8i$owztU53rL6cuE}eDX=pnj?N@InSkfS(OJ$;K^&du z*eM3QERN1O?2L$`GwtWD~O&p!4*lCEP^Bs;K z_54Tl3C|y-w>CsiTFtzz%%0LoW@R09Gw%{$p^eBj?P=zDT||XCOegYSH;mehn>1OIxE>}1bj>! zoz?7&i=%TfI}-tKi=(soeOPgH*0a+IczMu0+h@*2oJ4w&KKu?QfJ|AW$ zBaY6U9G?w%UL2i|u~QUB=K*#~0k4Rob3Hp%adbND)B@fRN9SgC#>COt{bW0^r5W%E zadaB&w8hbJ|DSa-;2m*vzQj)KW42<8yPvM$eBuF5ileiEowPXSb0s@N0ndt~^DTDr z;^=H(rx5UxI6B{Bry`EdZ`m0McugFgAF$I9M`!Dt9oRA&@TNFAKVfG=9G(5yX$8FF z`Jo&iU5l;1bbUEbdOpnYDbLTMXFY#6J?Hr~^pfYd(aWBHmtOPy*YvvQf1;0yW54}^ z`>iRC{nmF1F1`JnyXUj$Epc=nVP{eto%tL;<@pix=;PSROOJ1VWG60;&KVq^@O%Y5 zC64(##m=eY&xsl_Go_~p67Dp#`tR2`gB96|FIlk)oL-e{h zI zF0fOk3s$aPzHFuYJaP*cEQ}T`Uwy#^XRorvs@3bxUU0%mr|-9R-LmE9<1+kDEJ=&> z*~iviEW`CDcG&V0)3#iVu}^BNo}m7R#S{Yftm`>ps`3_09t;*as|aAG$n! zSa0M4MLX@E|2#1ry4T@ur0PrOcRJHf`1=l@i=WxMMlNy#dF)rQ?q7Epn&S3z+w{)3 zogK}w4}bsRzWj3AFCWv}(*E8j{q3(l>+MTdo_E%Q)%z#A%ff>e9lUt)fd?OyP9_(o z(|UODfd?j&iw=ZgDNMiQxD$`>?|Z4(7ky*%{_V}WcUYG@XQoS;XwWXn^Y8iQtrXpOaHCUE+4pc)85gh_Vj2&Uox}t(dp5_PYp!3?QAc%+S#ss+D=Y0FtVS2n^iuCjBqv9M!i%*Bb?kij{4yK27tdGgxAX0l*?3d;a`nxt>=kYN!HX~MvQt#~*%Lfov3+kJ>=oN` zA6#gcr9H6IZP>p3%A=j$rF$Ct1~%IoU$+MK^ePv|}4TyFD;45BtyEPL@Z}3CA3BXfk!;d8?MKS)H_%CzgqJ@1)U@cy7hi6~z{}o}a9j6o&^+@%_fcre(qMNLTlwc@AlmAm(PSXv z9nSmgz(0M3vA^MLV|J8zUdm0`?KR@V_ZAg=t#~;U?wHe-t~&c&(Q!+bEG=EQZt2-;)~sF= z9kb+3xzkQwdcm@l_B0^6;Oq;Q+izsrbAXj+uX3L|XU*AXcWcWpD0N5JQFn3knPvM= z9x5VyZN##h`Sjk&?&0A)y^}ZoL^{UzuKOOW3ykNls&@PM`s9`>PoRUxUAN%Qj|GnF z-Yrd@@aHp5$9U~OB(D7@#I@fE^xaL*@6WdFVe#jmq5Jd9$#~swXNv37sA9lN0k6|v zVaND-xq10NeD3*w%X7=ydAZ!>@t@m;o?B))u*37?YdB8&U)%9`0rwyAp76G7L%NI4 z^G(tGKRy3KJ1?64b2GPny-(V(?pQs}(9%Fzp5a9QtLJ8TobxXeGW)#T6Q-9L8+vY* z;e*VZ5R=8<7S>;GQz_yo&w%}a>(IacVE(>0idsbfn;?Jtco?=v*MI%F*`h-hb)TC3 zcb=Qcm%$7s7iH`*Z@N7<`*!cS*`Ph|vFBg2>_;B#b2xpiT`6CCbYNEZ`NXpR{;QuF z%xrr8J>P9aQTKV+Y`2c*4N-M#w_6amgtwma*6ZGS!CNnR>lJUkx0TI@_BC#c?Vs(f zZyv}Ky)R(NbC#XA^1?M|M;ER-f7R-DtxB#sZ$F_VRVTuVib^Ube3H zMGapf@ul*lquy{FzCJEJZ`F#kdtW{6%!^j8>V6g{?fjchuU+*&^n41po&TGjOZC2f z$&HKq7x&3NdG1xAC+TioA2Y(w$#4(*=Vf5atGqh^J$*1Ksxm+LdoU2jI^Uas- zzyDkWua0eg{p{#h;ssq}pVP%%es_GjeG;eBI>=7n#sUA;bECKM{NCB4mfL{$ z37ycHUSqKjyS1MGetV5&&zPOpKI~F;&;N|Q4rBS*&%fuc&98^qrmGtU`mV<7Vr%WS zp=SpAZu{Fn|814+_ZTbKdb{6V2eUDk+Vipx+UrF9TUD0WF0bxs>+ZFlK0F_@*OuOC zuLJej_P^5~ZN%$Ck!`zfr}wna-|x=NUFHG1%r{Td%iMcDip!jN;l&Mj zoy_e|?8BXGo_L+{nSuU!U$t%HwMKjGZQiqX*$cK_kD{;HeDJVm&vWf{!2W1cy*o#n zr#;`@*}Cn4o#$=&+G1~i;ksI9V=FJysaOZsU%@`w&%e0gu~{$8xx&{i@miei>kVJC zF}A;N`^5CfuAj`N+S{VJk$tt(JeSx!_49@9_0jV!p3mE0yh4V%DV|^8evOAroW|FDOc?30z7{8XM;r4oFbfJA<{Cb-_ zo+IFN-HtPMT(jfr`)%Dm;GePMn|S&LJHDBxZ?xmj^7Jlzyuo=Ba(Y)gjWO_7*l9Fz zdN(_bCQk2er_sdey*M6o-kalbdS5#|*FIijA1R)mZ^x(c^b$Khou^N=F_a9*7LvVGvZI6Z0~ zI4@3r#XfLeoc{lpe{BzJ{u;FWf9RVyZq{y2|Brqz*ZZCVTiJ5KbK!n_uyaeCCtgi= z>+U(wLVAkh-0`9G93A&-EO>B2|FrH}@BYq{_IUEo-z)Z>cM2i47iq(vD|Fe|^zy z*&W|x{&Jl!1^nv)zuUa~Juok)+wL#TUv9gPaD0Q~r}6mDf&SA0@3-^4-2A5pd`EN4 z^LBeY!s2d6dj`hu7x3=)>fI-a-EY>{o_Fq2d+TB8(Wf4F)RJSeOOJU&Zt3wSMc}pP z<1;u}-r~eRk6p2}`!@6+C^2`Oe}co*wdi zgpSuPcvW^~Jsq!IsMln?z7KJ|j93309j{&B3A9^&&l7O>SOvoE6AOIT-pTIa3|q&7 z%Z2ZY-IAc=a;ak-i{H#Iq}<+=45(t&vvK*drQZi z#PfT-zsL9q=e_4KFMVxs?&j(4`_A2Z((9zT?rukJ{62K|dFSr6i6O7!-j~jJUf_Dx z^D5VKo)_(MW6Af9y5HwuKYWf}@Z5Eao|m~^^88Y+yU)AJz+5b?v7pOIr^wK-aS5!c|Oj5)AJ2nANM@Q@e`ic=q=A5ptn75a(&Ws z_ddMaPwsNLuTLFs{5tj{9=q}GeMUE5=kqx(?v2O&3`@fEW4Z3GPuI!O|G)mTpwIE~ zrnh&t{Qd)muRYW3BV!-BB>5mz!6$9O;|_LN3@f%IdPfnyPlEg3LLcq}$GhFm)$Y%` zpy?0)SI>{{$I$dHW|U#D?QPJ_-);X0p5NbolHY2j{)_W3w)4N-{;Ts%mNLWGfB0_9 zZQt#`Q@DNqHT5jNbK$!9^v{oV|GLBA5pKW0I9^YmZ6E&r!*`%BxBW?eYkH8kL2os> zV8ww;SDd?c-M{*p`hn?12PV7Azy7nJ9rs1s=9;k&9O7p|_bgnx5JLvkA8T`QCr`8= zk%~6$k&iYe?KM!mCV%v_=%=Xzu3D1KeR0j)b)Q)>_cwQ}*=9y&?$T+|SEkKAYVJ|? zZ4SoiYuWlUsPj(D%)KnyYWUu0VEP5oG&|mE_?Bqa;JwlG!PnU9=l4b13?7omY+R5# zdhQ?AT|VoMzOARfFWP$ej=pKbmqvqwxAbi_xbKY2#{Ew_cJ3W3J~Zp$f$gTRvGY7U zFfjbRXuIKi2Bz7V*@FkSkDq(PX_wAg9?hA4d*7Vl<<_`2+J10(wBz7C1G^03a$wHO z5B%V)^?d`=*Y|BV{3C0u@7sEC{e|moyECR=*0;mp9d_RLMKf&sTMfQy_sqsS&i+Vu zo7dQQY;$?Em2G?4;KOI!Fl$NwoasyYXAEO|OZo=}mmGYJwRfC;&%ln>-Od_24Whqy z;<&lk#--7W>3c?fS6>><8P4@@J$Pxf-Js23@NL$(bj78%ooUk_w)0+Nm)$Ps;C|84 zF}Izc4kQM#ttI{O!D`=jgX^u~wzs~!uXeU=#Rn&_ZQEA7f5!B9|D0j8qWHg@IZS<*jqaAyCUdFU_f-*NiF{$1xiII!cq`Ta8n zPw9&d;`pZnJ5C?&+qS#!77xsrzIb5fyi;tO>4Es*gEj`oyRNFv%Jt8f7w_NI<}!2M z)qT6po6|pMaLPW9<7(fo(;r@XgKcAuZ6iJ}Juqk9qW&ERzha-q@hK-=W0zy*^hE=6 z?EE{<``N(E=`(EGrT*9;j;nS#@3-yR<+kf{$9dP7f3j~^n_qn1oBDUPMtu6>)t|KM zWY_NJceKlKL*Jai+ie_<@3(E+KAk?t=4aRCydwr?*kzbG_%r)Fju+YGT6ogcw$El_ zpUu0bZ|1xSyIk+H`QdoZJFDH>K(%kCo!{nf4Q%(XcK+`6ZQC~Q>5J|1**?HN?9D&w z&EKx8dF$WmuB%<`yfdcHwC%Fe#fo?*BB8N-WhKYhjAnu80E?_S2? ztNLaRPw$^TSTeWnVBGfaU+ng|pg%tR*S;MGSKAz|JNTEkUN!5-eLD}7boSK4ov`RFM6Vcq74ZDZcO%iFvBk@dUdw%KxA!G1pi;|fRj zE$+KGcIvX@aU4H2x;Sxa;iSIBxGt6r+wl^9{*5nve%YJ*7I!cI+xix}{e*pq-&^Rj z`CuN)`ZF8f-yhlM`{wmMm;Jdt2V30tT<+)5bNTGK!iT8TpM6 zr-c@$l@=!+aV|j|C*ri#;JSAXgMInq3hx;28!LXl0Y`7f@aMvjFzFBM z)gMBaTQFuM;*1m#el^lpc-Q!GEWcdxhqgNXtij6~T%T9%3l?=-j`zp1QP=EM0|;5q;Oee#^^k9&YM2?zpJZ57hO z*kc98N+qcBTbdx`S9qJn(~>F5X2dBV%Td|I$sF2Ac<8+Gn2IRlsepOt&(-)~)C*0Y zhP2Gnjz9f5Da&uK1Mwb;7Htkp-!UX!lAQCNZO+ejA(SR&)nBF$$@a9kl(A6SnP!2U z=Xygj2ra82+L>gaEPsfQ}nC)W3-0KkCXK;ue(7k>j^EN&C~dCBh{2Y>1_Mx z($aYfl+U@(`DbbfdITCC(9#%Z4BiNgS*&rLv4Z>D)?sfOOeWZ?WXxT;KDeLFV>h~d zigB1VzOv3Uau1XmLrilOZC87w2vg(B@29*g`s=STe&oI|H^wa|5&lpo8OhThvro3F zGPLH@+F)plV6}TTV5ASjanxlg1a zxab)vl&Z@d+o4PMZr$0niSAAGo?1uASF2A9?F>->9^%V~>svvt7)FwS!q-#?oNXGP z(7wncpcY)Jw}9kmaJ_FFqQUj`+Vi)w|7-i8B1wk|bRH5G&ThU;HtKU^LbhF$;?OoM zTpv^;(}f1iLw{Ib%u{P-#LqS2|LHQO%9lSIst=-^>Q9aQI9ne=IS$2%NxzcmLxa$` z;rfv7k{~lAgV6N+4(&ggXG&Fmidu)(US%>>qsb z_dV~u|C`mmeXF1GUe{xZ@8fTZyx-li%D4V+zxE!C`=c)lHrx`!;VMXY-0LV_;-ft` z5_XgI|NV@2ako{zcVL6HVLq<*h{7N3KrUCoz!~oKz^xc|?qZ{r+4XWyb+HlSnh872+whWo)tt?2R(oCwZz%|EttJ2DU5Mubksx|3=>CpMm?83!e18v+OP3A>_&L#tCKK#vLmK zo(}`hEx>aN^6fZW;Nw`?s*aA2OOdUpJZ~zor7mL&tyPeRR~Ts4LJ6 z98;V2N;x#}QTIDYTWD|W+y$Fip*_+Z1N-idS>-JT+1!9PbroJ;=KdP%232;qv&!Dw zTxySW-2>Zx6~bD>ZC)LFLrPWZQ|^20En$aj>6~P530rw%v%kH$%X|5BZwp_g?@8DW zz5Kr8N%w28S(d{N`i8xQS#Ecmj{=`bogVkbzW$bPr4ftY8oN3q_D(7Hmb(YrV_me{ zpRmU|Paxl~?QYkei8H<3K3M77V{7f=_bv8VlQ@>){RD74fqahxmu?Z$yz{y)_nm+p zir)&ydy$WopWCbjF1Nf~?A^0|jjtQ><2UWK#F6+}`L#5U0gu+Be(h}?waT{#`SH7a zn1vt92X3NV;?vD6@$PwViSJ&-<9DHH;WiJn0yo5q75Lq9{Aur=u7C8kwoCjvSv(BI z?+w>I@GtYbkKG>ewPIBOTVqid;IS&`;G%Y(B-N!pK?EiH1i-Y zgFr_i=pi11=FajCTKcN5Oz6iYuEI`bZqfr;5%ToL#LSycd=q~YdGrQgUf+{$AKodK zl$&l_f8*`;)hoW%s84?13wZf2ELjT3#^t5nH(sw4GDO*>j8$b>_@Iu29?Y{n>V0GN zTS5;|wyO;A6Yb`?-$30JqV8B`S)b>;JLawQbq22dejRY)L);2c?j)4o`S>&59aEP3 z%An)?{#wI_G~a{r-D75X3-_$?eJyBi>0;d$W?6Dg`CyqXAD`zvzUK|!&EOxup90*p z^}NY!*5M}NMVW#;ShDot6W)8=OGVv5K7bo!&G(d>w4x0$2Lli9sbX)Z!GH9%!0%ps z9|PR`i$MEfmVxG#(T{kKJ@=+>64oKnmViF+GRxv6ac7yYFPPzV&t2f#0s8no2yo&v z5AWm?>FeD1S#R03fAH-<9)%MtnDMy1UFh2;l^KmsG6zm@R?hk=p0I14l0NVV%Y$WOk^9%kS)+ zQV-kQ<}vW(@T6kz6TT`R)@)om$)g)ATpqV~PTgW_X>Lcm+@WzfRQfF+)^A*|v7PQ< z;nNTJRN7+A*HPzVyO(&!zVxyWYdJ0<_Y$8mzz6GpCV7(c)O&`j<>dg{w$t$n;Qm|&zN#fu|*cUjYV4a8Z``34$ z@HRPK>5IY|m78)XaTsM!O^pH$Em3CF#}(e0Z==sdUw<6!g2LfN;BW|i)!)!}KRSG- z_sYDLzK!UI{rFb++yHzw8sG`)u3eYu-bQPe`!G&$y@u~zTc7Zb{M#B|G5TThhq&DU z+_08zQm&{wcL1LoFh<#6q^1@d;0elKa>H-DJzspo$91F;_%68RS?|H2OMPh=?-UOy zc5eWDrqK!bH!_{*zoRfNN(FC-(`?|DZEKg>2V(`KH+{h4GT*b_^%MT++l}xd85_+1XHP5r{w%C#GCjD=i{h8QVP(YBN)zCYFar}e0x)}!+OZPugGe_D^y)?w6~ zk>QWA9u><8H6GdyXe%2bzt43&YL2qgi(IU;F3d;S?|+2#C^=bI#ABi^)R&S!q3cBvk`JLax2waz2WoKL=9U)*UM}IG>ro$T z@uOuOF!)k~%UAJhgf#pSPd)x%4X(!@p}{p1hH?HjK;?J!Uuz3&sxuoLIagcY5xEES zLf4~mLdq4Dfq&Apr9Q*%p*`31$`%-EPa7!9ZyzYhdI_~9hFg!CEYqLOmKbh5>Vp}GP@czU65>*Z<(88`N{@Ui3P7xvbM1qET8|20ocs*!L&NnU|1RrM zg`@J%YdxxKTG#XTX+01QWz^#lFV=b#*N=XNa|Z)(?ts3n>#%0j0p|}o;QWCj+LKZ` zf1Y>D!B>5aMrEeFckR>O8*{3Ck=Wa+`@rVf(mO`HIcm%dH}=yyi=&DW#+%z<$GB#M zCx!Nz$|f~Km%%OtTZoh21yM8HT<1u``c4_vZPM%)xiVZeLx(!rz$O=oed_V9H^)4T zea!K$|hBy(fLT8y9_9gRj*!CP)w}BnUxe;+U zAuiUGOs*ki!~PwG-@MKz-KkioDu6xC1TDo_kLnA07-D_OSpa)eld&^#_MnOD3alMX z#F|u8lbPG%3@aS1ofVEa^XRyFZhoI|&U3f#b3;l3?5k0rtpaB- z9H5Qi6h}+v6y&jZ+*59TS2>?@e+K*M6rR5T4#h^Ia|m!KHd+hV93$HG^!N%lf3I*= zxG&4=ol*eajsR~bj-L-YB3w)Ci8#xW06xSZ9rAL`cgF!of4ppD<# z9L#+(cMfsd24qCD8vn}{<3M?o*?BhARi6^-)&8;xl572*zjNOJ^uu@!5A#o$>- z$PRfk5A^n=EgZO*kTuHE2<(+#iZxWyatrLi4+AII>|G;3XKPX4Et!W|VI;biAioNn z$02`GZ1Lu2sAIxgIvPQLqLHo%c;DLG4PBaVB%m&ugRTfyG3eqqWnl?yyD5%H#ECE? zAQPx#bExAI&-sC`NwFoEBS0tXt0U~*eI3XX^hM)Lz%0~93SfoM zqdAZpp64k99&!#8njG6o+rSkj$>zu?<1fWXLHO6jtInSVnVmgMAX+-HA?mG(s~Gew2aRlxQfzVN zJjn3nD3|p|eWYGet|`Zq=OK{Q6ZU52Skz%9@TLr}##$Zg?eD-R1NvEkGf&;Yt2prB zG4Qbxzb7~nT;0I~@{KySYV2cf!YId+!6&X$mxJ~=@HP%ITG`|=cMRnAY2=w^k8@2% zJ)zBl{I-_z+YI$+$s^CQ90h%p+ZePt{9cW^jS;fTGix!xDb6g0ynHO=Hqn&`x+rgK zn<%#?)((n+!`+C7b1_0s`(b@zHsV*pmOdMN=XVV1_HHTHIQu~zGE-r1XFX8As_gOR zt4LFY^EA{uCw@0^UgcHL3w&Keu&%lSG?BhIhtrjcdN2W_T%QE(*V&sncY_bz?afl- z9EncWL!2Wa^|rCI8M^ji4V@w7IvRZG4tbAr#G6BHF{!uV?9fo0s~d{=W|P_O+Z~Cn zc$^EG5BaTd#0y!D2i=9>+fe+LV0We_+MQ0|>16#)aU`bRKK@yTuBj-8A?3c(mf-qU z$aR8wntG4)5(GG%c z@GNzzXkSndSl_`na`Q_;yEQR_`&Z2 zvqbpc?sVN`1V8vqeei)7q#gSj1Rux)($8{k2i?rSLY9N^5YAym zyS59xu;?c*$OFb_KQI(yoLbONx?6xB{Pu!BPVgepjxh=3*lBN(Y9bx!H*J<2AcVdU zzeKdtEg=VxSMY&)VoEsx?oP%hA8v!3%tn03hHC}*!Ed(z)ECl@y)Ncb@L{Qe{t)yp zH7q$m=(-*JW>^K;=Nj1+&?)Q*F-J-{SZc&O8J~Q31^v!aAqSDJUKl^|oBH!-=+Et_ z$KRvOUiJi(10G;p#dMSd=KnF$F^q%$yoo&uSKyr6D#&Rh=qE3hqJL+6@}Uyv!Xi;W zJVV+Ga=>r)2MZQzv#S%|_uoL*=Xft%=mNpB?9Hlq<=(f_c}8|I&YcrDQO zw}wvOY$@m$blP3e0rrQHt^(+EB=|vi0s3E_gPY-SfliDYK_|aS|6-vdZJ;L(GaK!B z0s1TI!4%MQ8Ooo6an)k#JHAQ(dguq`{shKz4zz>pgGiqb^c+O_JX>1;`uOc|B%1db zZOm-YRRFpu_Y*+ZWxxYtO))O!H|x6qJfNIUGGfiepik&I=(->H&p^IIfrkV1@Ova^ zTMu0Tf04!^+HnWuoOMSz|1M#^d*hO8tP*3L8r^KwL&`Cg52v<+YEx#%6 zBk=oDl*M&k*4MM3V+rsWivEfHFTd{rU6k?9(D!nDgR!%@7<}3V`U|iYd^704I9k-( zWsqsgcO1%B^%eoXs(KtnxJeu77$NB*os{j*#yl$MdjaF1 z5ulNMburIaA|BVg4@Eud-i5Fjb!tMMZvdTrupbO->(G&S#C4hpXlE9qPI=Be66Y@2 z#%~()2ps_aW`<=5YJ@oZXCFf&D7)#eH{b z-t)tFZqvY-&EVP1;q}gL#;$0NczN>dCe9(e_d3pQmLc7zI9I^)2SvaI(|&n&(}MB4 z2>9~sW)b2hox|D9W8czGt#x)&`O!_f-LeOCnSi^oa2|qZH>aK9>}HWY^z3Hrich{h zHO~k+yQ$*kfxkSvX<)vW_Y0$%XDGzkS$>OinC=x@kp3ai!1EO9OlBU|z?o)&UEGOf zy*I);&R7b#6Yn@nDc+mo9cM(jr&WC89xd|YxORT>LVP~huCMTB-oMIcgDlqb|1dRj zIrA5HPM{(N^~wDIVjY~zD!R{3-C2J_XF4uNe9NP`c&YdAeAdUWL`rcsM6T+7Pb0IrKMzPcAtt(*0h@GdgZNtxg#gbn4xGZhWNN6CDyrtuOF|%zY7z8 zvSbG1%P1nB1!3SHYVdk|{5L%xSuE>Y5RHH5x)v~s4s`I$u>x^_5AEPeF5@IT+}V^3 zA?3>G=e!<$uIbZ|G4TprkKQE9Z?6iLp~7E*!>vajk?AjVJ^GRss)YI>an&Cd6M8O( zzn_%+ztHvQBw4<`9?g9hihfmp;m${XE`2hcZ9N(dL)!WHMC#O~OZW3V+p<+#=<<*` zhP9UPe|;L8)GSy6YzuaLyo10|35R9V)}pcu~gds=3t6#$d9>y!Rl{A zTPhTar=c;E)vx~WJ}%UliN0j(^~C~{@cS3&<3fz3Bnhg`GbOx>grAi8+>EfH{BI8f zA0zX*T6Q{WEcGkE^|4e6zQq%0B-I8940h5&#!ZZK`VdP*tT&uWJL`BVEij-;(??YB zlPA&PSV-T4w?KpIW35eL;9qKRJs;(dG&KK?lHc50sOLXf!b8VqGc~v#e}M+q$8xHV zV?KKP54HI9>i6GuEEh7!IoGk=1gV-)k{|5z`Kt6njRnGv7zG9!Sg^%9CdCwc!VzAkJ{fAV#~TIT#h_jMts6+!_1Eqq-lp;TQb_7-Mz>qNtY zFg^rq2Xb#A%?Lm3Efm#zLI0AFitU0n@C#gpERg8RMDgQ zppFV4!x|Z$tq=MC-PeT}#%i6&zq7xj|I|Lj8Y74H{>nZYs?nTF{V;t<8{{Kw;!>B2 zWEgIK*B-yu8@J2&UBbYB9tLg%g!1%GB#pg@K4S{@BWk8~n$x78{3XeX2ood${!<@v zy3f5D$*=$4`;Y;W4=M<4iJ-2X(z^y+?w!@=Ugrz&xu^X95eJVz#Ih;d_LX@TCSm;) ze)bP6c-A}ZgBOIK{R4~Udu`3}4nO?hwb&1*aPmRN61UNqfnb5;6m zu}FJtt~dF4`0J0udi}9k-poI};j<-jO}5eUX^tXq=-RApOwc#~fz1`({%gxc1Hk7?`$KdX=Fc39tzFkAJY+* zkLg7}l#glq@`vue03Xvxqx?zd0T)!i+^1mqo#uBQ@D)C$5jW{9`xFpAR_qsO$i6;G z?p0WD;d>Q`4@Tbg{7e_gJq>x_abT~)aJg5Zt+mG>?+)%yu>5S3PxbaHjPq1qI>DH@ z0DiSDEixwVw;O{uIe4{Q(e`})7L_@A5q`_RKW|ks_B1TKKWUW#-`I8Z3&}WlOZeS@ zN5g0K1mkG_sZ)cKz^l{!KsOM-$clf=%Fp{X!tba2zCnMNxOcTdf0t+Sbt!0VZu!ct z@9WYZ@OAn3GnA?O*esl0-_Pa`Q7&Z$e;j>WgU0TEbNPV9ivIb>TtlFJ$|^;?)ce=a z8iI9v_VhIb3x4{Tl;c9(uA#?+~P z#;VpXdIH|i81}|6@B*1n7iqJMz&D?X_+z=pT3ma%ym`gqZ{f@Jw27?Sz1{?M6Ws0-f{#R#pm$mfE5+NAj6# z4mzKgX>i)!)U!1V{FnyU^NEo48JfS63$CT;Yal&je8Tl|i?w{TBY6hyTM!TP*WTzX!&UL)6+Vg$DFWR*Yn+#~tqya;?U)E?oO|?X>)FYcZFs!(4JZ=90Aw9q-mI{Kx0Dm{Zo-8gVX%JKnY$)wZ3%d894* zneEf=U4wEyu1(JTyTCjDQ2F-EXI`mYxOG?UfiWip-uaQwZ=bgPt=i0SpVY2>?2v`` zCy#7jc<`m#%ojhYJ+SZvyWFGalQ%_RgiX(_-GQU6}W^ zz&pQk-uC2CZ`J0f@2kx}a!}x%{IlZiYsW9DOEjt9 zeJh4Y--031H)n|SPKGkQ-GMuN+$-`MImDem#B(QxS9!ZJ2dlyS40kYHYS<<&u;yl7 zjBjH>!}h%U^G}wyHRdK`PWJOSZcmxvJdg38N4!FNtM@EfYK{98th*Je?5#?0&(+Zs zdhgKhUBDTFCwVRc{yj@*JK6Ewsg(+c{f^cm-~HeP)Az-^`3T;Vg8TC|d&2L| zJ|{jHyaVE_bJK)|=EU1V=EMz`S#M6f4s+rkxLnSK(a8Ta7lzO^bOzyE=fWLDdRVUz zaxSdCJrd5~pP37#1uFr8~Hij7nK3wKAP!3$wP;b11 z50>ymnLqa`HC|Cg5U@EaOjRWISu} z7j7=h!Ax*2+_iJZu9ypV?VQ$`lh4lGgL7d-49tc3UT^+tjfxta3Nw$u%#{i2PoiZh z!O1eC)SE0LgVQe0LMp@~ij1!2!Yd{JL+7d+G`K!z{8)qQ{2U|4kfC!@RsW%L-p#W9 z89!EV-1_%j7y!3B|LQQSs~$}bI)a3 zx%KA48eA`Tg9g{WDHjKzv%wB=);RXxnc)etELm-rf1EJ9@Cjw*xf^lm*QE;nx^^Qj z{B!Mn#@@{t5C2j7#{Jq|F7vEHJo?$;9U)bS_c`)RDf;EfHjb{&Z|tp{f56#z(m*`R z5qG!q*Z7XYx%oEm-&3>q%=9!7^rU{Dx8o{f*vT`~$}MOsm^uT#02-Nkec=vw_^AlWApIX%a_A5= z7Eh&LfX1dyC;UXf_kxv%^0*W}H!PWq5cDpc`Y?PRM45UW;_iC*YOvB!F6n#1lFdj# z_r|G@z?WSUQ?JWI#zpXlVWpvr()WcWr;P*;4o!X3-2*=KdccQX6ntLkyr3^Bofq^S zV)3G};6>B}GvU|D1zxl?l^&+RKTn3E71CL{m;#>_C+N2g`k3;-EVqe!wLgOY3#E@H zd^Kdi2ZYi|6L z3VJIacno)pN7tiw3+U77-2#5VrH(_dZ`0Cz0`pdXyZw* zl7F3EOa6oMO!?m}{1^u1U#HiS|6u)6{^6fa(5vKMr`MAIpgdFl%OU@)U&?<4d|*z6 z4@~NTPPe58LAj>o$z-DJt-G{AuT=m$lf}2 zuf4UC`a)fY%sAP$QD3O*Ovkp3`Vt2pdE^WAMe&7tqw|G&qw|G&1Am2rFVq{w7wV7B z7wV7B7ty~!f2a@CAH^5;F*;wUM>=0b9|Jw2UQmw|U)ay+e4#$+d=dQ&^ojC9eNud3 zU!(JddZqJ4^fmDJM7~h36kpii=zO7m>3k9W4aQEC7wVVd3-wIr3-wIri|A{hXXFd@ zO!0;Njm{V9o6Z;NTNU(;d|`j1_`-fi=L_{t=L_|&9C}B-Q1299*#GE!q5kQ7q5jeL z9{EE3Q+%QR>3pI7>3pI7oj^ZCzEJ-ZU#NdNU#NdNU#Ne(p?~BH^-uAI`ls`S`ls`S z`d0=0BVVY0iZ9eZoiEfsoiEhCa_ArVLjC&~esyn$UtPr?>Y>gb>Y>gb_E&N6H%k7f z{;EzJFIfFmaJ)eMqYq5-MfF#D`)c)9!SaTQqt^O)VFZHMjdc=BH{gqCy)n5harT&yde@L$yuj%w!{Z)`& z>P?)ZiJ({YS312`e-)&c`f>vO73o#uHJx6op9<1TJ=qOCA-!t6rqgSU*Mjs?KdPV~ zq*smCbb77vT997qMLG0>^s4ciPOmjy3(`w{h=cD@%Cj1;>GWFTwIIEe{}bqkNUxHA zonA}+gY;7VcSHV3uabYAUQ7Oi^iuxm_m}ii{v%>NDLTFS*ogPgkryN_6r)-W^fx zhb0-Y!(tzKq5qPOjfUCrooBQh*7A`T`+pYKe%RX`8xLa~kBGCR|HFX&rDH@OUOMu5 z0kB6qMh4<_L0<0w7RWEU<*@Y7{Gwxrbpby0@)Pkw@nkG?3q<(ENbkJ)!vlzey55!8;M>#r}e4_)Wo*ix>4bihtjK_}8bZjLFZV zo{VPSH_jCGcxjSj*M z^5u^!ykop?Y!dz@WqSMls{7SR+1^_R4j#}uv)`bk;rAu=$e%F5H{LUT!pL!jg=0F5 z_uYBD%IFNCL+s2sJ%Xdb9WPw_3boWK+gqpw(ejrh{D;Yf3UvnC+8c-XJRGGx3O+jo zPJ1`khystyk2cU4qxO`-NQK7bldWS*me(y|1vKDri#Ea2*L&0vB}6O8pO8Bcwq;p< z1d5dAW~=D)^?eXP_@8@8LUK|cYP$6R#-}udUmgJs{tI`9x?1>A>j})CJD<+qEBTT+XD9J5m_m1+>|=eOGlpQ+LC;m$ju z6A-pEw{_VD7<>vN-(uuh>1RICxf_0&dC%-oEL+tJmT zfw>)V9Ymk>9X6SL;IkHY2)J&#axd&37OosSRN(iR^lgAyxbhB)E0fl?XWUofEgSdp zYj>I3U=#QbHhS7th-(k{6_4)lu9@O`26pclSK5^yVH{=Q3SaHOHQr1^zHt&)-h;t- zbK+^=ce`d^yVHCXcKjXoF5p>Xfvelm26_5TC+q~Ad&gY)A;wx3u2XP7a|M3C33<|v zLB8@{hm`hf+cWNjg!y7UVDxqS%(?LMyxM*pcorpa{SNbo=nn6hU%;Nvxy8|Td&HQG zd>!g&1zh9IiO3f|bOm2|7Y5@EOrYOfw=3tmy|{ZJ-dSe9)=66q`MLvhjOY%V&CRee zaJ;sy-ENHAEL>sx0IsdgxyX|?5aP;vJFe=uwmsu^On64DGhB1sN9IkAHqNPz3@2?q z>^ZGK9vU znr7d(QMPQa@A%Lhoz8Zecg47!DgD-&X0u+h-EL`4ymhCUl9B~K(e&q^06*Wd?Z(~6 zOvAf%{_65ne~J21ZTNeMkKi7P*3P?o&Tz9GA0zYt_mp(lV~*~-QP3^g^gH&LrRi+T zExOHq>&?;4ZooJ7I@X+f>ps&=$%fBq+C}5xPg=I`!XI`F){>myx2O8=s87|_f0_8G zn{9nb&tf;*`+h=SB2o5kv$XF!f^MNpckDJR)7j=*bdT=0!7OdoTlN77=Bu~vHAkoP zgwJf=qtgaz^IWR|A%f*)`L^&5vex9C2EI$)YZz~M{O_hC){ zI$S)<&3@zko{zZMcU&ZNt})8qX>RHJuAp1!;~hKA!|CilEV?WEZ8Wzu>nr<{Hs;Y= zKQt>-Zh-%M8|t?;>Rk3IxZi|nqHv$b-%;QDHT@iL@oYEymalp~>Sq74U+82M%HC%l z?&}wH3w^y~pJ{YqA7jzIrQbW|;bx}nbK=aHA$!a%DZSx4-;TQGJ=(J0!M#6BlL8#R zLVX|5^f&L~65OQ`@4TqjOgH(Na(i{ zWq)KQ_t`Ay7X23VJF81jzm1%C&E%#zLH!=G%QV{eHAlnex~|`&Q3urT(ZFFp>ieLk z--|BBogmQfOx#mW{hlH88}|S}zq9(hFX$Hi8}z%NOHjX)bNpsj(|$qy9ENH{xCa?l}nRH}6znn@|ZHK1F^1S<~;&E`CDj_l#bpLceVW!v7&v@}`qul`c8Sx3e!t!8aiQNx|M!M zr3dwUW6lTWp{7|u{l0aNxv~8KGa2o+uHVT9?Y1$lWZ=L)TJN7nCC(7~-MD9w&~K|x zwxR63W>nwxf^MbXDd|D|K9o~qMm5V0>i4a?%|q=yW)|9QUB9!?cT&HzfCKyRe^vkO zUUw>ef$N6l3$OFked3PT#(VxE<1$l{_ZxE?CuOD3Hs7Ruc8aw|OkHgxY?X12#-Jz4 zMVlq==|Y`4T|YPMU&M{Dr^JtOq#T%gYVhmupO3lT+^XBMmcLPuy}TOtE&QRd*YfYD zY!Z9gY5RKmXS1{B_UtzCgKul9mhP+i>uu|Pk#RKU=&ehp|NO~a!xCS5dPU<8ZMV&6 zvF72l%hx~9^yW#wT;uznS3fCwvC+r#Cmo%?cI{pBKYOJ2n!_8PTYJ&wg-tIXfAwFl zSy4R6{CN2*x9^=<_bcyB*FQaWW7@J!S2|vK=b>BQ`r5UBWAC{y?z*YK-{{Vil-P%z zZ(P|uIibUMW3TS#Zq|L!;6mrfKRECHRfl)iO?&ui-;)bJe{0c=cf>E7P;%qC#W#(4 zr_JY2Zo9nEGrJ#7Z+>jTg1e(ztzFV4YD~9Fa_;SOW!36ey1d>rF~eN(VgCXCirc;( z-(l2O)1R0$zF_I(*vXrUqwMdLesgNgoG-={sGj0LW zdRXSb=wTc38V_T-G}ubt4*V8_-(rUSIWJ;d0j=wDFd*rvx#gAH4cXB5BIKe_nz{)>*n=Df_vQTApf zW8uOd+g59X_0Jb=~@Fnc&XB_^a?H{lqQs{2#UbzN~M$2eO_3!q!VT z+wTNvyHqyb^R@kc8B(q)R#u<-47-o|T+@fM{mzv5U#RU@-BHk8B23#aw>F=v?YF%w zzfXWt>m`(a2p*1moQLhVbEoq@d#mi&#K0raux!6)wDHamHs0mfbG$rmMAq`QiNeOa z{6Sn4CT+aSc0B4iiFt}&*m#@P?2W$e!!p=-OB&^V=*JvmHs%+zVdE`<&0q!Q6n@;4 z>VL$y6LDfn=C<1DhmE%cwu9N2KOk)B-!^j_V2LFkBi~}=2OIA)#yxWFo-){YOAZa& zQBq0$0ofkmn|UpTfO}6H{_i>%D&1cm=MQ(<4mq z$IRLWn1$;`c4}J}SdLwvuadKk~yiHXC-a*|6~nTq%Rm=KKCi-!8<7DS5TkE&ffkdh*&-;A+Y12mbMA zl2_!bhfAsPhOh|TrGL6@q5lBuh0P{uUn8OY`j8VF;A^iGW$Y3nQbocwPbdq zzug&RmU^pX_Av6M%wi5&r{wn0dUAV_z}b@9cl?ddAh*<8CAS820XE*{lv~U(>y+${ zswcaKz}b@BP5#f%AiFW(v69_n|K$|%R}bJmtomRAVbwUc}=`6P87TxCY_5RTp-yqxeSpVGT_W8{=*?!n~OW4jUeZjqhc#kQ8jTij()WODE zr`q~2Bi<=vTVIm1p^WW)KcO#?D0{cRH2EDtx6q{*cKa)5vCX&W9({a+zx3kXvJXh` zzxv!>|L8V7{jl+tus=|GwGnl|G_diOz{Xn#8*f0jnni9ZV}I~+&f8_|6FLZeYJ{?P z`74t*3A%-@y|Bx_WfuDdi|*3nZ~H4R?j!q&c>lKNKJu5g>E(xw7xf#5I+uL~>Okln zaDa`s4mRF^{&k3aw~YP9`#BrS*mqncbgnVV-s#_x{H~x|=;I4J{fB3<|FGz;JigJt z<>J1wKWXDX`rL>9$~HInVdF*pwnm-HKE>7??=dB?@s_~GTL&9&KtBgW`pek2e3kP~ z8T*(0LMNk8_CEjNWWS(W=<5sn{Kic7F&5ohj=$qSe6cC}oH&0>#UB5bHog6@@uGfP zq0VK$W4j3NF(t6^mcYha2ODodfAb>WD`OvYQNK-P?1$D0oo#}$_xg>b_XOQSpI_MP zPoBxX$fEo3@lAds@kZGRk3uHUsZ5C9v_9z{Xn#8*f0r zr$ufS`kmD8U7_ELgnm0w_DBBYq|JhErQcaIgZgb8d)J?wm=o0Rid}vquCE_9-g^2C z8?VrB*mz4|LnVdEA04I6I>Y`k@_@dot!v&avG ze$VK)S?G5!q2J9=_HKW1(g%WWrQb_u2KBq(*k*rm;((xjSM2o{#O3&5CM2kG=0-n&=7Ycg08k z;<$c(*m&#dH*CB@zhUDofsMCL?_b+RtQGqGcE2q`zpXy?B9y(;zcFd8pj+wpp_xJb zUV3bce`8{1P`@ia^e>I;@5ijZo_@o|EA$&S-V)e&>-7G&cf>lO-+$@%fzWTO&oxl? zKL4Slb%JiC-%+!I`n~bk2mV8eSwa1NZjXOs+yFmpy!G@OHeR9Mu<@3#kJkI=Q4#Bf zemBmk5&CWQ$u^X|*B_Op9n|mVcKZ*-dHk^P*3)m;c!hq$ z#*6Wcr|w_Xf5XOG6|nJM=A?~xIc&VklWT0W@h*prw*)rc<*@OBSJc%;CD@O;95!Ci z6IB8m?{e69QK!xlY2#fE8}IUfjd#YGZM@;^k!^q5eh=-x?~gou8EwEnyRP4tv;(i+ zH)|Sg!QHF+d`)|Bo2`+*r%ibNfHuFQT{v#q*uAt3XW1Q#X&+uQenKzWh)ZAltUv9< zpRPQ$i?-tNv!>M2Ui|8>TU|$+ae9k)uAtqxyxmQ>s5XMFa;INFqVew+D6+LfyY#mt~>`K3SI@fGdM(VbRaLmTtY zlfQkMcIMBTA6`RS^SURN{TJ=cSG?#fqs@8zbjN<$ohOWI?xgMcyPs{pf%fNi@3y<0 zHt4^nZWu~C^q*dT>N(n?KPmWK3GLC#Uc0vkZPI`F?caOTE`444^jO-aM>vk=&^~SJ zn6;WV>bdhyZl#^Nu-qUp)RN+Oe1QnSX$`?1G{1zD;}fd$ThS(xzQ_u;5jx3~|`^$_G@w9cfzog(Y+PnYy$LXKY=H2qXjjz$}ebpe}LE646 z^4tAw%k@|K8?UQLerMGq+b;QH|NFZi*!#E1+s1wM(0~Vyzd63OZ^fNQ8oluJrbTZ* zP~iM+v${1APyak7p?9J?-8C_x_<@Maj^Delec9#jc&5DM@3eZ&yDgn-e$ykTS#-sQ zJ1@@ueb)8wt=ai@PU?drzpF@j=+-a4*?sLx#f=!etmr|JV@)ozCmN)6U(xp07`aO*CZ7$0I@y?)z$Nd_UzCvEP;V z#Q)x5pG&_B-@q>(_q$dfw9Wk%@87|H8hta+=NR|Hw(e-mU9jFZcR@F!&f`dU?|Fyu z1$-0_Zt(2Kl&xaTG_R8<}gK>lIxgK$b8X1#@gSI>Pd-R}k z!1L|~Y@Cs?5BKksR*nt1BeynAXNs9gX*dW>)JJa)xsz>(&QB=`WNf4a3uhqh!c>**lq z|9;Av01foPm<$?7OWq}(YU~-G7!j3qeV54y4p+l_gk%O>Rk@a_31i~bMc18-j5I?qYaQJ0sMd9tXHQAc`7>-SUE2|A75 z+1b}7wa>Y0T)uC75{i558UNle@r^(uDm{D={`6Y_m`O$vfWkGwDU zo^b`EMiz`7IYLAnIj+EW--JnNM!%lf(nXqhtMBJbfa>{7ga03iAN^Tb;}Z+;vIcj` zcLu99xaK0(P<#o^XR8)p&u6~|*Yi0d`5fwBD@pP*6t4S8lfx#F^JXo6y?Q#|b>9vJ zqVvS5CT`_t1#Rh zbK}kte-4!zimL7@HN%vzz{Ep}ngWS%g3R=3i70i8f1&&*tfBIwWc@uTatr=bbSsEx zF#ctC%>5zIAF>}mj=qq6x$YZv<@%sMR*&82aweawwuo@|l)f$cJdPK>L_h3?&)<^> z{}cK^>r|zxO)KQ^TffgkZ@Fq^vSFJe6P|A$QlknC2}9d3))(^*Z3k;)I$iz=Qf;XG*$CH%)W`@I+J}6l z3J3{9@ekLBbe9BOXdiM!mODxo$i9MOC`G@rZ-nbZ)IAa$+v-m!{-eg`7X)t;NIL5s zb6vW0Kkq$Fn=}RT2xP4L1iqiLGSG)`o*tMFV!nRdVNX5bh*)75p1N%KNI&Lqta!*U zzVKj9i22sh%s9{ef5SY>kaHu>15aSz^Y>FWi~a&*@Vb9AGODT^@Qsc>V;$}W$j6*3 zc|ul3vSBxEqtd%$@-z2R!+taqe#d|HsWF%HM9vxaW3CP~%P|*(A9c&eIenVjr+UiN zZ=UZ?bz#2KUG?)_cz06$d>7eH%Qx?v@c9i7F8ZvFdkXd*#;VTpPglkDMFp*qfQk6416ydfb&Mu zMnD|%P`9CD6;%)a4cr5^0IX-SEMvb_S9!=+q?dK~5M=Octih>yJMVL#?2d@@eDl2n z_uvWp6z+2X&XjL!3}sLC2)Tyc0eAzC)B~^!?1%i34-t?#%jU6u8On+c;392Z$3Qdj zNtQS*FbtUT>e~;d0Z)Z%(y3EjrU73iZwvnCR2Mt$4VZ@dQgv2@de1|>71=#?d7vo? z`Ee{3DElmYpj|`p!FIXuyAQmV2kOt#dxx;o9d|TZL3`dw(D4m;TPNFrKRdL$?@-UG z{ti0g!J{_dQJk>xfG6cOVysDBrVY;0-y{K}y@$NCU`00GlVH6I9Hl*p?MNNYPkcXR zj~shOuAmKwaXJ2E8N9DAKz|7D`8(Q?RK;WQ4jwBT4t^Kj4(?9s@n1>p?;1BLrSPu% zM~=UveZi#3*IbVoeu^QQW$4EbV(DR<|6|&DtUf8UXHny?&=H5_J6j*)dVrsL8oCpY zznzbt{+5WZkA1(BsI>(=bUeYl(U3O?zab3#mN4+U!@%ze1D_cN{zMq~uK_1riXJrv zSR~=G=m7XEv4X&zb*m)2yM+G%VMBa)4{+vxM8+R1zsIHo_7HgQK&3KdKsA zUSxbRAdzLO`(6lVU#gy&TK-DL`P-^6@DDY3lF9_(XJOzcC7gWF+*^Do61WOoGmZRDvRhQxH`0D-X>?_lU zL^I~d^r3K-PQlscNflHe5ss3L8`lB#Cp103Ws{{x3zQ!xGk4-wwoi(Gs{X>+aF)r4 zsy|Yhhn7ETY;OM8k&{L#JI>jBl6C6dwafYL#W=!4b@K6u(1X4m6yfed&f9<9)LQq( zioG`vdjXQ&y7YY)I5gY!MNQ5PHSsat3_RwiM-&-L_l#D@@66=9tpYvx|iI49XK z=C&l9b8^f(r`wCF^DqaU)(H3C0ak^f`!orI1eGuj(+hinoAd7V(pC^Gn>G~AH)$Jy zjUbizh&epU<{XgU==lOR2bIS{l*_p|f3LwDS=?cFcac}kACmwh&9(Zx5c6U;=Dt-$Dxkohc;-xFlmN5W%e(H;qB z(9qoZ7vlGZ8^Z8&YPLwHKaN1l75t5DqdvA(zuXxHJ}wNrI1GG#82GDU;A_Lcw*ju- zLAMp(;?V>X^F!KQa>aB{yiMSCi-JkMF~;~YBXR`@+bzbA7#aK?F;aYs-x&K2-^h`i zW?BwibI0b788f~>&G|A1^-s$kkUhB9;M_rjy?y)l&K)=MUgLDA$mDb|XOEn94!p6~ zt-1Myg?HUK?zF4v1S0u`jv7cVAlQlT|OZC*q z7sl7;Ad0_)>tp64T6}%XN!tLQ&@pEh4X%&*drCORihBMEXB*(8OU(!3MDFM%BwWQ) z{2^TL!xw1r30L~IECe1Uzh4P~E4^J60#|x|0b|;cWAZzQVXbfEm=3=29UxcvV+_3g zUmEL%j#VNg{VL$RfiRB($Z)@GqLh5F-cTih7Dv@zxUp_IBRBAbg2Rn<&ozBll)*eh zyJof5V`~TwN89ru~%+zZiJC`6~Y5pYg&*L zTwgqZ^~J9-ZjC7REMHJ$%w3Ezc{0YWZL!BSIl>xi{{z2cpKpu5BILf+Lt>n(@9VYh zCFee!mcVU4$^hyZOJlrjoP^rQF|`<%Tl;kltf%H-%#OBo<)W{Rxm1>=D?i120(55^#hMIa$BK^)&n@)&L==V!ou-71uQ>@^Y?Y zw6}OsgFHFUDFQFKF8Pq%mclY0deF9<`Iku^J#QLf{-o9{4aEO0q^^%+{$`J4eyDTg zsmeZvx>s|kBAb!U^-DWsW-apI`sG0EZ3Yghh?9C8a$v28S+XGNP0~Po7%$0gq;r0? z@Ss&UqzCh?m5Z(ueiB!xe6J1UYpvyd4t%jr=j9#iol*X00{`F~kbEEwTq}JQY4>9t z@Tpdwx=HxsI{()wGbtkLWL_gX_OM&^<^etGUCsH(o6x!DLewAXt%~(rhjJI89*eN{ zN16=C^f!S0C(Y|X7Y5C;O)M}l0yajCoXp^dS-WKZkT2u^!d#Ax2_NpEM#ghL{uqC% zgx3&==P~>d-a~e{r2=aGYiO=$t>^rBbH(RTbhL(pdW9XQLHN2b@U3CsABTY-3IqQp z4E!SSy&*h9=R`;@p0qIWGsD1X+-fNQ;bGw8!oa77fzJ*DpBo1Ld>D8o;Nj-X)*wji z@f4F}G3^vHW%0(TDRwic`Ly`3Ry48QA@`mMn6ivCf(g-H+&OZb1`zu{v1}QPB9=dc zpDZdD_I)jeSop-uyWx3rVC7U>-R1J>*b!=hQ%w6sw2+n9;Hsy#eiK+b~P9(s&@u0QC(Cfuw>TU_imx2?m0@#@(4aX?!l)-ry3hV2G#=!8c(K zpui5a#8%9;^*Q)t4c=0|Gk8UV>vQmx8eCt$`&@&^$#(`xkS9LWBih5%!}WYVgzM{c z9VMK$3pQ=4{p=#)v|Z@%JPBt$`ufz%8az>yWc{nr;QG4TehtpHUOgu@IL3*=N4C2x zHz^1;)P9W6^{hl0pLB6Pq@E-RCtW(cyOw{lii~iG25+mupO$cyKj)HsDkNOxui*N+ z?PXR}@qd3vK57m4vyglg{BsE>AM|{_)8LnD`Cl&krBJ?2*5FrY@ryOMUN5B@JV}ec zT7&CyuI7Zw=A-&k)g~*r>Nk}PE4b>HyUVf^T=nAv8B%zPU5-FNKRQTyMuOP8di?p?ZdN)k_=^PyfjH`v)g$j4^9 zaTDj9uZQ{o#tvPk4I`e96}icd@s_UF?tI9_Kr8kMpMG&wEFuR{3UK{;YTTte1Ru zfAXl;`P)k0Rsa3C_oaTn^Km~k*JgQMpL>9Lo_|qqqi$hu*rRaA;zGQ`&h;wT5a!&z zU)a2CO+6{F*;FSR5w3-WIG5hkQ+?l%8Sb6yJt+b<1u)zXxobd{^?fgBhhO+>94%c7 zpT}Yl{ zgnK3N`xql0cP`k>#NT3T!TTZ1%3B}fee|wwh`VK9&y?Sm8P&g?2U>nv>K=o%q!D@9=*V4l;urJWw-~L7ql>Mc@m0S}#icV!d+oYBrb?!;crJA;0nGw%!=D8+=^e&U1uro%cjnJi90+P=72Xsmt_5x+L|Fw zqRD#Pj5rJf@;6| zAP=U17or{=#KWq`83GTh4prR^m%LEr*b#^HSKMgT+jQ_j;g}_GXln66>SQP%EP0Z= z=yy6VE)zIdGF~vslI>7lv{if%C;Lg)|;K2QYN{$Q0Sn@C& zatQi`d{Qn*|8(3LDEI(*pj-^696~49{tF!x_0?F&v5*Vk!ZvCK+7<8{x|1kmn=-K; zcjE}z=xgyK8#;>L5yvj{em%+x$Om-_vbqR*V3pTQv;(3{=qm45(Pd;f>ej;DA@qI` zWPou3Ji@(Y)cG0E2dm7cqAehQ9JupD@F~~gQ#N&0;BL3{Uf?C=B`-X$+M+zcE2-XObUwoAl!IPxN&vPM}v zssN9yHr?V8`;H!n!*I%Yi$}MEM^@ip7wr=JphU!BI2F1^`Ki1KxTD@x|FIhPM6%sk zZM#nBd;$78)-n4j;>8BwzBzAm+*Akc0LdAB1y+ic4E49C@? z?Ne;Lfi>! zz5@6y2ENqiF~IF0eq&gQwkaFo;zy0@#c0Q0e$-RFc!p6u1MMZ-+u;~*IWT5jG#=wr zj5Eg=ZBy+S^Hxq_UjyG#g$&*3t1w>0IF{oM(#|;9#w`ALw`3HlSY^3SJB+-53{(u@irLi28?+Z5GBR8Hkf5+I5VlZ+jMf5PlnN z#kt0DZED7C&j`M<&*PZ(Wm{8MGu-XYu%Cgl!Bfg8`A~`R@nZ1kecZLh@Gl(}>81@5R#3|#>XWX|MZSZ>= zlWoN{NH0Q#AI35|et*~SQ)4)VTP0+oQsT$)%XAxbjAP@$7LMfQP$M2~euRr5`8V`N z3qSIac&x*3SqM4D$#!H29J6FQrsRJyna zf2_948nn7gWXxoKuK#tgk&A{($e>h&G zeh)|6WVIPh&3>puYcAqMy8t}VjuPKRV%%!!O%~GYGC^6*mSbPaDtUg;=CpW!m%@=_ zRtvw&MESr^(;4cg)%ICsSp0NavT)-wZnh(BMf+yqxDNTVjT=jS!8k1o?O!(9G3tpb z#~M3JUJQ8F{Vdw5Y%zAWa75Jvbr=0sL%gs9SHTC2^FsNsPUnNv*-$=MV`s^Wey8(d zvCa$VD)l0i7j1DTAZ3i>os97oFTj83sH`u@I`8gN{J0ErInmxj4#^kPHS|#N-X&xs z8}-EYnmmCX<9CZEi|wuePqHvpp>ys?i18|M+-z?O`;guI1@QV3 z?*ccpxy0>F++F(r*n1PWDyshtc<#N3EG~#UqFitV&3)l!pYXP)eC7zM|%1rJtK8`GUM4 z^f-`)R!C2MxczkAU|fi<=}pLkR!GlS${VDI^9JJroHxjW0Ho!0ls`MtL+yCVmtRpg zzbN$1JduUBmH4n7iSj^|d+NUM!;p{g~49B>=4Po1H&e4XkBO7U?xGCN0 zeAW3I2%mN3uhwPMa2JpcZ-?>PwlnS|SFLNCai7ga*J8#XxP!$$wA4Ohgv~{Hlrh?d zwOG|WLCQ~>muN$JC>=BK?pTstt<`F~*nL-$H`dL)*msw4ap0~bKdg;g$#Bi^h9=OY zsbSItK~oPJn!6ch(ljz@BA{swO(kfs1~1Lk<+!kxZ%JHO&o>ck^3Di^2J8KnXt2I- zi3V%;CSr|Wx+c~+h&UIce~-RhZtC5+Rr{7stROnUIcBI+7AJ7FYTmMW>oHDe>kiJ| zN#kju*vNlwvK~F5`ftqDqjN56PMeyWQ1$~x&+k9UWPA!#wm`VF=7in`3J4WmA8(h3 zsJ963l!-BVj!SRw0pi!}#EZUHEycBH3mo%S z@=#K**GDCX3l6W2VT>O>Hf7Whl%s3cnJ-n!>?c{-qLhyxk5&AJju}6S%cBbQszqq6 zYf$u8nu#gn(}#~4jRdZg{G&M{@|c^GU1;LzdAHt72mYNVZLHz&KoC?&V?BC+uc=9^WpURl^+&L_nN6_CA zur>e6I(PCiSK{9;9%zaV?fU%n_472RVxV0AmnbmPW{sb2U#2B+|8o7pR_)r~@cTH~ zrVMg(THH7n`VK+q8g%NN^8e);xD`CDfveWM`?s!vtL|^sE2r0>vEC8X+(+~JVCK1d zH?jsUl`(Ujox#`6Fv8%P@5Ms%TB2p~^cyRSr{6|dJWuqYLaD3NQO(;%c5s!}fu%^* zv85HJRHUVZsx7V6q)M@#%S!V+&AI4QW`pK=nt8g{(Ppi4+{`MT=054ImjG*>Incz* z)GNi@a2@sUTpPDgZuWB}ALyP&rQ3RM^Het#ia)Dk{e^g{o3wxP?}Eb8@#}DP-PBSO z;uebgS9QzH&{@+&UVj(=R>!LKRJZh%`)RBt0IPpGmaM)?d0dWC#RJtLH&nMspo6ap z_1bftH1?|LdZl%XhxvMKTHW|JZjMsoWplHu>y}OV_Ufu1OmpgBTHr)qPrsLVY3kd& zo(j#C!}?MDts8p(u4)GQ@txhpR3FhCI)s@?^XTwBoSp{e&%NMp1WxfY0uv15SQCst z(06lcV2)OGe4E7S2#zT9GTN@U*Y0`R%UCn`AxB&%M{wE!U#uQ#|;>m9+-mr$k@o7_H6wHFVXH#v1O7{?)Kf3-@0uaX%wpDSn-=uv6D`fr0p*qopiyZd2=j z9aIN?DSb~N4R-_6`RX`J;z69DxRxbxA?6Q~5Vvd;Q%XyK#IcY1ZN!yOh>roCfu-a2S3MdYxT*e-vv;k9SXV#2o-m#P!;b zcc!u4ZU1Oo2M6*VKBrd2v+7~{fW?{v`^=YzEIn#Wl02<7~mHII|*wk*0P z`{jL68oy$_SJ`^h%hl-HK$LHrFJFmIzO2@%#`sg_5R8q5;WvyhcFs%HG zbe>-OzVBP5>oxIuNvdrdZ8xpMi}!N%SekXcWO|odr-@vB-7Zc2lz*pG9**PO|Eae` zZ8(|#sJ_>3LlA8Inb*IOa`PuBJA!t4$kYK=&T~ zd-d(pr3UX>9QK(>iD>-D<>R(&(ce{1-9y$&lMAlHR>b6Y;r z1OJMNH=nQh-6?ZA_j=H`mFsIw&kz$&zX`p)AiTBjk}bTo@A8T%9BS+7?HvKhQ$eFQ!J;;E0)r0gMc4uitgo2NdC z_V3n0adrHfZUsQ;YN-ivwST&wnKwC|l5}|LquhC&>8CO&McN#Vu}IqGu~)Iz)&P_q z`H5bo94PUlO~c!b_EDU2{m`(xYSZVhN!&*H`>)rm{pg{O(z;~_S8FG2*Z)q@|s$#)yD@R7> zS8R#)$Q?#}V|*ifO&`DfhFFW`QG5BK6;-|S8&tse;%()MayuEt4X{2+F8VHwuntRu zTJGYl4)3BS!S3R`7^67X=2eu3_k&j88=K2J8pU}=rK07X@Xd9jYEj;NpZvoPpH*9p zfT9)n?&orZ^J{p7DicLC>sF!E|D9i0cok%u^^LYIcPmOqNL?2C3yb@&%iSgb+X^AKMe zG?bp@ZDL$$xHfrxVy@O9-Fb+!M0X`x>FQW?2rCcqPDXemD7;L>xgy$C%i&iVC(@sX zct_|sJH)tRDbBc=@$;r#J`1T&hR`AyYS8TqP*8}{dL|-p3!xpy#3H9hw>Yv zba$JsljK>d4(qdMmk*`w7=`Imv~r;-OgRsqadqQ-s;e?UVQ)j&d8?ycL-(Yfqw7lf zrsMnxwiV@3juK*AMGvz; z@oY4QMdkGf;-cS5D$48-gty|mXqOj$yDK*-4W;!6^3|uVQHA15MHOQ!O&VkaOI$3Fs7|5e#O4ImJH-0zJrYUWL zz4kHIBg`~}Hw=DOzE5QrnlUK5wmL;6VIprwXw4xiYtW>}xCYv4m1=OV!$lKL_DM0W z4z`*_`3{x0N01NUNMkB%hM)5x&D0oI4O@+(mGzZ|<3oN-D@lKF(M9^LPmgh}h*9NY zE6N1rJ(V5G``j^p`Fw3oMY+B*suwN)I?A=SX2pCuw+#vY`BdiUI&4M!>(VRaQ&}2{ zG_2Sdf+sa3yT%5j|(XJ10 zzg&JHs`Pxzse3bBL%Mg;y^iy6UzBSo@-Pi$a%CG;rjOwIP(JxoQDvITQy)sFztUx@ zb2@@D#X4V;Zdnut)clKG#Zptg9|ElyHiNZY^>DfVU&7$@5O=S-0q5AUd__}dt1L?jZ zX?tCjz0^IERKC$UBF^;-Q6A_wdpD&C_mxh#@5Aqg#VX9RHB|cb{j64c-MCtHlwT^d z?AH@~AVQp?ut357!#!PZ~Nm*43Ba?^NjON!df0 znmBnP;-lYhjiMuTFWQCkHG;YR+=~3BdTuDCVLj4-cGA#2lh1J)kROx4=eF?1{Rw&B znCdL}_m6h1YFs{_G%G`V`2KX(TU`s%tGJ+#LAs$|Hy!zm^ziv1-IFFyI!Ec=ZLe8G zY1&HnyqdoGId5KxzuDVZvtpJli@ujtE_F!cBdNn8^9=9UM!@8jOKlK|Hd)pZ!*&AS zQ;QF!F+B_*9awe6!@K2b+^PY_sj00x+o)EQ+Xih@tdB@-%Gqdd=Aw<+0BuxiU(Pn_ z73HEmO6^!`YtBX+l-sgs|wAAsYb}0Vs7JQCIBKzWtu| zul_!A@nQiZ1%P6PYy?;Ypw#U}y}14IMF2|OPShFg>eii5_vrAO&zuo(vj9-ckc|L~0F=6}sL#~hzkkL4xNhICUM=8z z0ic*68vzypDD{3(uipRl*Hgd#^Oe=1p#oM50L2X12(So1slOI==+|4ewAgarZ_mB( zf`I1)fMSMh1Xu*1)LTUT!j|UEH#8sh>^(6t0`3t2iW#yIU=e^)Hy3qG^PW9h^&I@b zv*FI?b_4w*5qaxmYS3raSP|T2x0E+;Wy1J;}tv+ee z=1EJ|{eJYQfZqjxVuox4SOlQdlSF-VQil$EJLDZ3J#U_X(E>m*LpA~|0#ND>qMp~` z#~)Y!IQ7o2UwTQv*8)H>LpA~|0#NE7Mg7u`OO|w9^29gwt5y|IUjQg($VPxg07|_? z)K!-pKYrx+u9}zX*B5X}04Qe2Mu0^CN_||^^^eEKwu>DxeSy;{V1WQo%#e)$ivW~5 zR@BbeZ@=yH?Mu((ckV18UjQg($VPxg080I>s5^f;=JU9G~C;LyECZN9nP|T2x z0E+;WI$YG#!u|Z3`1K8|HfWH5Y63tpLpA~|0#Ir{Q4jKa^Ucd|9_TZ@Z(jk^1%P6P zYy?;Ypww@Qy6>CW*>7hL54!iGj|AK+02DK1Bfug6rOp=hN7-pCNEc6YUE0(J`k z#SGa9un0h@(?ne@?cs-;KYY*2HNW{rKurOlm?0Yh76B;r!=nD?;dkHt^xYZh!*01n zz%T)zm?0Yh76B;ryQ043-FxpHe(%n9eO#InIUq@xUUv26!4V*P|T2x0E+;W`mm@M9&X(Dg~kmx-fp)GxLp7!X2?c>MF2|OSk(5$ zQBk#{S`VC=o-Saf08q@3jR1=PlsZb(=~0=PH8PvM=)Yox0Dl3Xm?0Yh76B-Arl?nB zu2`{rML%2IpMMI7699@CvJqerfKsmz^`9#qeDLQ7KU;AAt+xc67XXSGvJqerfKopw z>bD+z=9$sY?7h&TM-KrV1b||OYy?;Ypw!QZy2mqn_H^6x)RI^4yi>rd0zffCHUcaH zQ0hIRzH`ro3p*}kwmdd=tbk(zKrur$0xSYh>In{O&#KDc~j zol2cL38*9h6fIeYE4A}^<2tcW4iTaOO zZQ6X?=HV+t*R2yUQ~)Su$VPxg07~6P)a%+LCub#hI=S_pdjxD10E!v15nvI3QYVZ0 zo@A`gWDoH33JetBB>)sNWFx>L0Hwwo=mJ))nzzao*<=2E0X+nOVuox4SOlQdt3*A2 z)wprrjC+0M!5@AQa8Lj!X2?c>MF2`YPSih)+rGX0_DY{Uxpk|6Ck23FhHL~_1fbO0 zMZI-L0Hv-i>Mv^d=;7)ye(b!C9RW0Tux$^*5qU_~zuvKTf`1x42a+0mTA9F+(;2 zECNvKlcH{Q^3b7|5B2Q+-O7~$z7qh78L|;z5r9%367|YMci%nk?t>BQ3JL_Q699@C zvJqerfKuNr>VmuH%n6#)c3#DI-Vsny04Qe2Mu0^CNgPp$+w+YYEoyYrd%gVq1@saCiW#yIU=e^)Hxjjfqt>mrw|?^ckWHHe z3=sf|8L|;z5r9&+7WJmqZ@h8-jh|y5yz4Fj4+;Rq4A}^<2tcXd5cOSe{QUE*pX-eH z?Bq!Sp9uiP4A}^<2tcWS7WK)WD_6dy^5i!4CQTAhPXH)p$VPxg07_k1)RQWI^;P;; zKP_M1rj3C00zffCHUcaHQ0lKl-R7%|jGHqiyj}P7X#sTwfMSMh1Xu*1)ES~ao$=m# zTi$zaT2kZ20+IxPVuox4SOlQd?}@tcd!Kw#^^-MF2|OR@9HR?cV*??ho8Qw{>d)a|M86hHL~_1fbO2 zMcumll`G#}dAY%%_;>+_1b||OYy?;Ypww4H9e?G42hKcj_UY44J}Ka|08q@3jR1=P zl==ZtKl#Aixev@e{mZRGh6uP-04Qe2Mu0^CNL0HqERby3i3ug!d|cC)DU>jgv!0L2X1 z2(So1sb3TI`q$R1`DM*V_uc>Cg97ds0E!v15nvI3Qm+y9gKOgBd&fUtd*!E}3Ro!s z6fMF2`YU)0m*hlR}vtGKFjixvVp z3joCo*$A)*K&it--6CwrkSB+f|9N|IvViRZKrur$0xSYh>LH>|9&+Nup%dQ)UWteh za76$pX2?c>MF2{DLevo_($l|4-?a3nk3SahlK@c6kc|L~0F*ji)E}n@26hjeJE+0T znF1OJ0L2X12(So1sRKnlGtlj>>%RHkj0YYNkRbpRGh`#cA^@d!i~0e#kB`&G-6WuU zcL4zcKrur$0xSYhY9CQ|_j&*QrtjZ*bn!FK2v{rt6f;92FfvILYD0E!v15nvI3Qa>r`tS4{1 z_4KW0K6+sLb^#9v0L2X12(So1sc#ka_FES&9J=u16K(FkTRW0Tux$^+HkK zy^yC2|1bW0_F0|J+J8B#xLCj}0ic*68vzypDD`KeF8-`((^r~ydGyZFqXpb402DK1 zBfug6rEV(f(M=~#{BYvJ)xRD%AmCR4pqL>W0Tux$^+Zu0m^gE0>zPB|sQuGV0%{8Y z#SGa9un0h@XNvl#nY(vS-+ej%%_dC*yeR+_Gh`#cA^@e{E$Sw_>(m)pXV0Ye@4qjg zy#P?mkc|L~0F=6psNb)%cJ1$LH{U&J!UO@61b||OYy?;Ypww$cJz?$ZuRrp7mGGGN z-V+cb02DK1Bfug6rG8!1@4Y@^#M%*)_I+8mu7EEEfMSMh1Xu*1)FVV)cSPU5_x63e zV)ie;2*?%yiW#yIU=e^)_Z9UoeYMF2{Dhp4yRv2^KMOQ!_f_1$*@?h*is8L|;z5r9%J z74>&ZfBEIZb~S_#xqk_h#fICJM+A0E!v1 z5nvI3QvV?8#2a)m?0Yh76B;r{h~g9zqfZS@0Rr{v~Mq< zf&fs=kc|L~0F>HW)a|_=e?0K<28(=Odrg3^08q@3jR1=Pl=^W|zxMcBZ=HOr*gd6Z zPXSW|fMSMh1Xu*1)NhHp=UYGhwCShhyS{k%VF6zV0L2X12(So1secmn!#`E36j^C( z`{0Kj5)do^6flJMIwhfdEjW0Tux$b+M=i7k~I+n-7Qnxp3Js0Sg6yVuox4SOlQd zABuX}hYcGpXxQ$}*nj{5u>wFbLpA~|0#NFPq7G)sNWFx>L z0HwZ5)GyyPdv?U^_}8j`{<(na0zffCHUcaHQ0m#D{(ScM@n4N!zvA$R9||}u02DK1 zBfug6r5-Qp568P)hh1NNKmONW1&kK}iW#yIU=e^)yF~q~t5>g^dJRfiRHKG~MFK!E zLpA~|0#NE+qOQ^FzWY+{E9&^pf&~KJ5dexAvJqerfKuNl>IL^ro_uNYk%x~jSt8)L z08q@3jR1=PlzOtLmrRa~+#mVMn3U`-xJjyDYs~m zfN}yrF+(;2ECNvKCq%vIi7&oL{$lG}n`+h+ut@+YX2?c>MF2|ug{W(Ok(c*cUX=fU z!-oY75CDo9vJqerfKum)`f%RCgRdWq>HSSkj(~3jfMSMh1Xu*1)CWbKb1*6Cxuh27 zw%mTZfGq+*F+(;2ECNvKBvIdTkc|L~0F-*QsG~7)Z+2+) zyy&)V1w;z~#SGa9un0h@Lq**-^o18DBms{I0L2X12(So1sbfT)6titx z$88fY&VTbw0rLfbVuox4SOlQd+eH25wu=|PzPP&SkA3MF2{DQPh1d zdU*wSIji|JXdu8x04Qe2Mu0^CO6?`;244O8-PP|cpQVQm30Nus6fbE8J(kLvTmw_#xdz7+t98L|;z5r9&U z5_Q<9iWS>dOmzjNqzDKS0E!v15nvI3QdbmpO2zZ%KRZ9G-Op2|2>4k5C}zk;fJFdG zeO}a4&hOiI_r7(rmkl2-V3`0=%#e)$ivW~*pQwlLd+4DbANqRn#r%8$7X^S~hHL~_ z1fbLpi8}wG1`XymxOGkU+O-9A7XXSGvJqerfKoRQb?pWnJO0}7!>=b^zARv(08q@3 zjR1=Pl)9s+FL!+TW0Tux$brn%RSLNxay`Qe|m}Ax~ z0S*D6m?0Yh76B;r)1sdB^zFAdygfGU1uriFF9-m|4A}^<2tcWC7q!>z>(~FZ{)>L; zLx&1T7XXSGvJqerfKsn#8<~zB%RJ_vxMTl*0XqbMVuox4SOlQd$3(sV*e$mlzva@$ zlQ(Y`Fj)X7X2?c>MF2{Di>No>GGoSVGp20{xpYZDhyYN`kc|L~0F-)$s4vY}uwcZ3 zFE6)qy9Klp0E!v15nvI3QZEp-d%@YW7tS85a4I-hz$pQsm?0Yh76B;rSy2a{EhzY* zAZOT^TD1g>5dexAvJqerfKnHTx>iBes=cZ%N@$dsDWH)6P|T2x0E+;Wx~ix%t2S%) zMzaTB7}&3$fPn%)F+(;2ECNvKW}@!bY}c-|UAs4IELTpzMggFhAsYb}0Vwq@QJ33w z{d@z%v3sF+(;2ECNvK4@AA{1Bau6qgG|_I&}ni3joCo*$A)*K&c&~ zuH(4#&MtR8UiFo|dj-5A02DK1Bfug6rM^?td++Srxnk#_9&_%yPrw`jpqL>W0Tux$ zb!SoE*LnK%1Jn1tbU8a)z-0lTm?0Yh76B;rbWvwd&(D7;KeR)iIdcT`5dexAvJqer zfKum+dQN^s#L9@?GvkL16A&)|6f*h>aU}Z+vr9nxCJ5Gy$NPAsYb} z0VwrGQTuJ&yt)47t_PPq`lx^<0zffCHUcaHQ0mR1esptOT)()b_T?u|2v{xv6f+K&LpA~|0#NF`q8`5&Upw(1*tkYqoPZhvKrur$ z0xSYhYJXA3`M>z$?JvHttFg@{ps@f@%#e)$ivX1RMN!*c969pUk=-`$Y1&l49s!`3 zAsYb}0VwrIQ8yjgs?`Uro;fo(H&?)50ic*68vzypD0M4Q=eC+K;gboE792fwO2AP8 zpqL>W0Tux$^#oC$n(*hJSN=TYd!l-E0Vf22Vuox4SOlQde~P;LpIy6_>*^QtM6X@~ zo)7?v8L|;z5r9&66?Lz!ue|d3E541oL0HuCK)OoKw_E^2gZdq7) z?OFkq1%P6PYy?;Ypwy3vdhKJ?s`agw-MPt{H3FIl0L2X12(So1sjG>4O|=6DmL0e| zdf(e`3)m+B6f-g70L2X12(So1 zsXrF=!H=V(t4Bu+n4Ov`V735I%#e)$ivW~5TGXl0ixv%9v}Vgq&6)|gNdPEj$VPxg z07|_`)Xf&<=B~=^QR$A~eiLwq08q@3jR1=PlsZ?`zvVV*lHKIqIeqWHUqD|0pqL>W z0Tux$brVtF-{hWqM&0vms|}AlB4C36P|T2x0E+;W`W{g~a?iPQ+s@7J^jlh*fZqgw zVuox4SOlQd=R}=$?vY2r9_gH0Wy=-;RRn-yhHL~_1fbN9h2(ty{Wgudcnq$Md0*enlY0N>++cJq}Se~H5bj_>(J{&(wd8A-nikl z68~>}bEG6+B%`i(&BWuql?S~RA+6a*xvlfZMxB109#7vKncPb${%Xy|XvnPRL_U{`e-%pUU#r&Bnu|_ZXOPyUHE&k` zbZk9$(yx^Go#KJk38kNiK7W1v=(?7*=Hqs`{taO_Z`SzJQzj&&rA%o)rUmABVr$i| zb$geqZTof})?94YCbF$kUjLel-RY(wo10y=<|58}F7iLihIMTmsY#JBsmYNJwMKLn z)`vckgtcr69SOUwy3X5^BbOMCw9QykI~42Qke1d~r}dvnZ-{IDrdw6Sg>T4ZovCUR zW8ImoGgvd5*7~;F=-YJFv3_>7OeAdq^1Ch8D9^$=>L)^JeQLcIea(Mh@EZN z!MkH;caM&>dv%VDK5hg$z|His$GV*{vBnEVAo3$N(P_k%^NNnmgFVKp9G2}Y7kkj* zSd|hS5SM&U-(AtcwE~wJj)-#8I`7J>;1g(!Gy<0z_J|bhI{yxB9pvl6|^F6vEHeYVLXErYqxJKM;pSppBj~I@u&d{%z=ELz}y~l{<&ThLp+q@!HL5KC6IPMjRckJ3~ zl;gOM;2bFaZtzF;6@B~c!g@_vbbJVT@ILlOZo#>@9TCa51Oz6#J4bAt{7BVCvyBb> z?dQUf4F}Gua^xLQE^Zn2tzO6juPzara1G66gw|B2@NRTAt{oH<92^qjbk?umuwkP{;o%Vx&6>4n z(W+JJ)@|E%=nxs%vE!|`-gcYY9TU@~OV_SFdc?-|>eZ)DzkdDu$HxyCFmT}Aci(&O zefK3L4IVsX$gp9lscC7WMvWdlc5Hh3{r69tIAzKM4@{djeR@X5tXU5~{KzAZJ@)wH zPdxGT(^*;b<}FyTaN(jwixgGyACh4 zy#4k&?`+z%dGnSnAAGQF+xG1{c6{>5r=NcQ`L11GeYJb{H{X2w?cTln_U+$)=+KWp z{`Aw&n5p#ZuYde;;>5|5^s4f?a~CdLx^($6R{P-%t3L3C*$W|<0Z|F7Xza&K;uE&Z z>Yq5ako_V1E1jrx0!|2=O1Ay@cfxi;99zickjs_u4-Nxc2>w;FRT9Ux|MLFJC-4sr z1G)yZ(Y>;){jY3fmvx$*aGexNfC>r6HYeT01L#KXV>sdB7AhhAwhB?KsV~6X6i(}Za!^N=;-h2=r1cndd^TDw%j;W^b#j!8qgB?3u#0R?% z?AYPr*cb8nAU*^Pzi@Hvi(_9L`{EdO_-% z(@t#|>~=34V#l!)$KYYdZYLvlyU_q{1Gq|vV|Zu)9qiccUa(`wG5mRfhaEfO!|77< z(h1iI7uk#*$8ep_KzI+p9tdxEJO~$d>^O!CJK_$&9*DRDu;Up1yuder+W)!B5S4(vF_r&SH`UU0o^OppjUW24-{ zM;u@T5C7QhusN{fE&&(*VZ$-qHQ>TOt|b280(-&rf@}EV7#G+Ju9q*o`XD|Z#0S?4 zuHlPg@Lq7ed=Z}y;`2d#aN*w$|JZR17ye;Ge0a$b{;}iO7sue?A3Ng1hAgL)*rX)l zm=lF#G8qB*Lye~@-~oMbjQRvS8IdW-TFyLM0G$AKxO6f&hJWmEtH7-S9>?(S1^?K= zQwHL)QH~n6KspiZaOtFQYy^N0fLjG_74SIr!LbjHeQ?YfkITxLZwsUhzz&x(1IO@> z9c~r4RlwsI{t-7^9McJ4!-=R2Ai{h?ICNrf2|HX{OW2&);o9KZz*8QSW{~xSVS~Q_ z=&Hc20)GMU7XY^k+$t@Vcl-@N`~k=?1cx0iG7!hGII%-#gNyiaj2$lG$1z8ZB`1sk zT#x`{C?IyY$Y3194u6P00PzPPejHt6JaIu4;>w|Y=`MTI) z$FUcV;bNy^LOF*!3Kv=*8~kDS!8d0N?6C8X0d_8wu;Up1eBolJXek0LBZx@gB7XX* z`5|sQcC^Rn7i5PWujRr;+_2*qE_Oe}ZO871`0d#J5Vsw>AL6!Shusdl9d?iuH$uZzg;mT-<5p2nAozMz|C{{dQ^7yrDbsddO^2N>Up2>eG$% z)Zs%Xq_=L~p;d==#*mcsg!Ht*M&~YZ3FKwWkRb{9p!Vf`V&vT8NKQ6 z6%mi|i;_*3mk!|N6Wwe(D&a(0_|wAE_n*0gsY8--WDQ@JFVfREZOQg89Yd`q=c&&_ zmm_`b>ATGXscoPHSV##sZ4{Sz^E8H9OFowLcgIk>nm@K=iqLxgROYScPV(dOW9V=4OVH}S ztaB$_cZuIE8AA;-`mT~be|`NZd&-J`j(mjaBiPNGHU5<3!3im&ldpRWwRIc$Y|RaP zw`QQ}VTPL%o7Q;!_wKJAm)q*$sF2Qb)P) z>}5t4#wH`kZ+25R`E}VazL(@pZa|zdtyWxOCBv27!d;N$XSfmr#a^S-o)iSWp5Z#> zUpmIB^BC2I6Lr)C=a`|+K4Vix$Hnz>wrbw8dFwGwXX_5m-bv$~ty{K=G)4{|jOy*W zq{Bx~Fj}=Yl82`!8^ec8rfRWC!}MnQf4K2awcqG6(RutgzU4=8-$)xywXv@K70^$R zIuCl&_a0AeGP;-AN?Rs|Q+tH#`CEbd7iki+UOpUUq8k8H8%S?M1hj-}u2Z%BRshm# z-2^ev>fBnIm@+;ceifn0d4lFjzKcg~ zkkYGEdTwNwi8USCw$b_uZ_Uqm;VFD`ICD(l znA?nh|2edJ9^E{B!uVFrTN%y&v!5I1>yA^p`WZTo-Ev-g#MO@Z+==tlrgDq$4GJ6^ z)yV{X=m49plRdSmYKcE_3-3okUsNv7`DiPOIi;%HkS!oO;h^@CQ2$sXm;ma@n)v~=IM<{brbTyBj? zbYR-7!P2oc??}E~gy+PiF^C&!lNCy$@ICFTHf#LJgOhKpP1d@7TPJVV|6IFP8ErE4 zEy044?+sIXiM}0pr_=a?z7>5I&lu@j=I8J{_d-*nct(IbykRAy?V4ryCb<3Fx_x2B zn;Cvad?B7e<9jw)`|%CseL=>Fl@*M5xZ_gc>ULXn_lc3oxYZAy6PD>VLUtdtyTkDf z?X2DS#`ambvkfCQ)Ue0WGt8W-6~n{utnmQ8w~dTjkW;mHc+$*}$RS%oBAsZjCC(!^ zATDt!xoES!6%v_2{7!PgA0!w2$&kq1^z8e1LL_c@U*MT*oLyrlo<9qwZ%>yKoEPj9 zr}cSmM})@9oM<tw+L_z9 zZROKYxXh zj@l7JPKHE&guJ2hknU}Kk%+cF`PZ22gsJ>!j>=RiF4ZPM`#i$B>(01-eR|h1nm29I zu)eeIKiTx=``^Ez?Tzb&d#!Hy&{64DR-2jb&E__6Gr1>*g4gYv(hz|3%}}>dc??e7 zAg^tA8b+dcrnZ{t7FW`SrnZim&lWwkndpA5H}m(T&3qH77_54_vC*dE)phDX;dQ*4 z&+rh=-*036XB$;coEx&}s=ULY;if;>^mSB6SGOmL^VFu&-IYS|=nI$P(fRaOZK{z{ ze#Co;Lt&UVPi?B}_1_ACQJ8YsN`lt@Ww@n;x3=kYo66cInkwo4t2R-z#9tDDfc)z` ze@|_qLTMBI-EpcnBz~u4IJJpsw_ZQGu4N_lbIB-A=P##epsU%&+$j31xqhwMw7uar zQK9MLx;bJu&ZRuYsoqs>BGVWW&1pO2@LJ{N z#F$YS>Y2e9Qwl?U!u1r!lxUo3FvgUU{$eZ%$yo3k>Y9JDa-mE0pR8L{zt;K-x54=&?q`bH0zo&bz4wTN%yjkN<9y+*vThl{=zr6RhYae-|{n2bw;c#I zANAt?=${zFr~c>}M>+0~Qooe?qvz0HEyjI02y>d(;GRtVnMS@wy97s#V@_WqzOBP( zm&kpZ+T5q1{#v5+X{Zl^Xczo%`)e~Ea?jsC;(^Eo_i*{c zUk4e+6Y}E-MPVtc4l+u9EG2afGt_pmRyK5B8i}1YYu%!M+gAR@`v?Esx<%)gI?L`y@^QzthA@P<$C>ls#~=GzgxGQw`aRVxeI@_?Zr!5mhT{_N zjn*y4rNZ)b{<=JXtSg+O)sXx@C{41MlXD)jK?wrf%SNy&l`7=g?G# zWY2OJoN{=V)HO8bdB#zG)rItO`RCE*r#j{W>YiZKGr5OsS*KCgpnhq$#8l5DVLUU( zQ91meBWTrr_@Qr7A8^!0pF!0#IgUQuKgjLiF8(`x1Xa&W^H9&+68VCup80R2rL>+= zX`yqOUruEX+$KKZ$QjN+VK z?t*6iMtm&3XMe_Fk61RqD2~R2=cUU~f6;g~uG>8iI^xzj99f19?>?ns%+bqems6=Q zD8Vqsh2b44j4{lug}63v3C+yuWE9)LMFq@w{;Z>VS`NMseirq34))N_3kNMMZ}dYe zw`cYwqabGm#zGI-v$An*vj@0~LyX{Kj&epk;dFa&=CaK0`FJ|HBd3oWc4%;|H>TAL zM-g0brJgZvPD3N!xO>v%Bvd8Nm1<0s(p6TPDE>}JuQ_d;E~M{z)3(KK#3xSoiF1}m zzjS&)oYUWMxpAB_y;fXj>>VA3t6^osb#qn2<*Z3IXzCcQ1|gW=U>%3XwYxO+6TV*8 zeZJ*!zC9;J^7+abaMH;HHSQXWv0TA6w=E)3aHtdSE(u1yM+_Dm1--^$ZhM6G8|}1} zU_3vFSh~?&K-XdccFJ>lrm%Dq_1W#QO}x#|BPLz-Jc7o?shwtn`@Oh7P(K{U`@|)i z#x#Ci7S)M04AIhgZJKF}%l0zj zH`#6DGH_0VaZQ(&cen=Q`YrW$xT5K}Cb>ASbd&dk=vr+a;iTs> zSs{2QGUxJ@_&?x}{2##kYcvK@QVwwKlcgLu@JvSYi6|?YPd1Fwasa*7gt|-1lM{Mf zZkj?*<%IHbKb~PxUXn|{mu%!E{a&(>m-KtdMqbiyBO7^{_#lpvkBJZBnDPvHmH1$- zlHXJ|@--3HEgSiohUmj)@EK4^Etauvvm z;dI?|90S6sOefiFv5AHeJIBYMX?Hw7D!Kcl$RW6|%$id_GZD{PsNAkb9@6ulHR^iw zUn|G!#HF%Y7AC)%_ZJMV#M6@=H%bTmI%cxyO%?z9d^=TWvL9L=Xn z+ua%t-p=4nhl6$tZ+NwXH=Q2M_mxXc;h3kh=E@MPmH$$B9llcqYwQtThp+h??~DH5 zSeN3s<#DBCpPa4dXH_lzl%%he7hfC_w2rrV8tl4Nx!E)oj#9f1go(*sz>tyNQ z4P96H39?@Q*+T|w*7;M`bHz={{HW?L*QIEKPlViPpZ1(iG}7ayMB%TRzq7Vv{?2Li ze`x-W+so)jeW#F%#yH)7%I#(p&p~_qJo>UR=sP7(b5y0Z11_MhJcqvR036?ge$~#4od)5(*YpzVTXKgENoSERLeQcS-h|lTfF5d6(S+!!ZcRr1&E}L!? z406=ou@Zfgb$zN*wXk5>baz39y>{k`#a;7<`xyN?)i%bhjBytq4KwIfl)0gp9}+rn z_~gN;LZViNW;)Sk$wPcUA-)xeZ+T%Oj*t2sBX_H-QM;j^o%$3Dys?!%~aD8Fj?!mH0=MH%O?d|}u8RGdQy&S3@4 zAr<*pat_^7d5%le9CZ$QP7(E2G^YNF?YNqQMEwznha-L)ClGbhvTN}}V1Zg*v`w!3oHlU~jB&)EoW zlihUyWB3=*hsjP&I+q=16tDJ=5C0SEWt_rqBLVs0i*badhAlJP7K|ng+QF%bk=?O} zHu)&XCvdTP-gVLALWg!~nLSO%AcWGIOLb=eID8qKud^FAH zp&V(v)M;l;Q!W?&oQJfo3T|+mkL1$tCL8%kzng62BmHi&k&pB{$wof9k&oHPM>p~# z8~Nx)K4l}HoWvuasJ-neUw=fNQQqbtPqUGa)J~_oya)Z2!qgO%k4@vl>32_M)>>AN z;x~lm3cu@-+kJQ>nrs2Nb5vQS^0prNNA3nGj|JksEiTP>D+`k!;w$2s6&d9+UzKb2 zBd%Ak;faxXO+E>F0@p0hs1Wg?<(hp7f4|_G?PAx)*PrIwm6NjE5aqrc@`TE-!m2D2 z*5#h^knH$Pa=w;gr6r!qmMZ)HnWr3n5v$Nwsc7@V+tl7RFPq)A9yd_wsu*D*!RV<} zG1|3mfu2f(f2ym(_4R+UucE4MYfXt0!&cU_|4M8r$A7JVZlte5Z3%N@-}xpge&X$%>qfBwXMEJc-@wkLt}#g-Imt;K*<_wIFp6f;pjfXG~snPnh&t6 z5Vc;nX{rgY^_qXj(x-4rf(k8t3eEpp+x+^v%jp@`Hm|2S4sS?b;kbCDCLm?KZhq-} z^wj3}k-n3TSG#ig^r7LY&40cAJ+=9@|HdUTDPTQ+Pi_7dlK#Kj=D+tk&)-vlmIRasAJ+@SN+0=SWO8bxPbEu^ZJo%}-lj(&pFC zt*WD4LT&zYm@7eT{$iRV!OyR3tLS;vMLd(*jQ1cfp#6Uq&q#9XqmAvbXVpM`N#o2* z%iDQuc&R_RXfIW^W89j?k;z3n%Yk~nD%w+Z=ot18)cuYs;hXHWj@i&B_!IANQaCgR z&ePmCdhS)${5P6&!1ECBjN!D*L!h|{m!^KiZFLNCwxefihtN+s=m^F;oprd~z8igo zTs*%))?of!KRkc4yQr;B=`8DJ1N?k)QVT2`HGosXyMrbY-#*FP#$`CIa%D47ev19VK6 z4AJp)JT*B&Cfo%`QmHPKF1HHsUpB8!=a0@4>pj;~ouk(<&~*#l0x3(bx6av6_NC@9 zbXv&uROei;e_iLaGzSW-{d>A+>g0KvSND?^Si-f^p6ZMya-WR-3;z_JG>fiM9+im9 zbw1_2HUFt>nr_J@VeFAW_54w7u%;hVf)d83Bn`Rlxex7HwZ7qTBC7CYbF-_*iAv|y z(HPO6H17fL_Ebe5EYa>RR&yd8Tz8zqy_V{ZV)TXfdl_pc;2rx6Z+9^Y)Y`C08U1ly zJbsg5%%N&}0iHn?XK0p8^@y^c zW2^V6HrZ>ZMIfwv(Vv}xw1*l-rhc}$5q1II2=NXTdYKJHpT4ouk9hhTxffZ@f$Og2V7%QW?1TN<8IV9i)ANf8n4Dc)x8) zpnIGT=HD%;XPo#1;~ul{?%V?t9-N1?XHkA+x4}6eo&<++tOD$vs=CJ+$ZOZGj3C4} zw;gQAi{d5r>c=QgZo-%eu2XyRPyOP_f+>#LJ*Na21!o-9BHqGz1Yu4DjThy#!S!$$J3czWhXd2kajS+)3r&Kf`mu^=M-qrn`8fp*oxe5A1IULA194LM#<>(ySc2aLwt=Lr}T*WTU|lW5TGh zylO*at9Hid6s+SA*{YRs|7d}&6-*eJGL%him5i8}k8wt&@5<9S zh0X)w_4Tf2;cp=$HX6S$>w77h-@7wECOB=;i+v&?FYRL5nv5}g7B11b2yVt zdNZFPyfyqMOnP(r*O>J5o6=jM015|na>=$wkTpGfg}0vXVd1UmIV!w0pIah6+DKnb zLH;|?1D`9rHQ)5R@*Q9|ufz4Z=p!xsVGrRL(w3t1nAZ#Q65bkbEtB4y{$3{DoX`6G zOlv+*^AP?bQ#hCmR3dek2AA8X2Hl_8t?Dr6_UT4i3??qF*=Jb2X z{m+`84TQJme@hc@4(IQV5B^_S8${Ow`ofxjtHgQgvlU7=dXMDGjgAxQu^nrC)?-h7 zwhW2asS_@)u4gr^`)pM2nm6sA8nEU~ewN%WA>NIhxR%(>Tc*VSSAD)7@T9{u`!5jx zW{$8`>#5JTNcuTq&i$gaG$A z>Tg7U{%larmbU0W)sBF_1%tdROTL8~Y|m`mN??WmR+YE$J9@GlGeR|y&C#EC@XXAa6{3z!d{SsKGk%) zJ#91M8@zPp^9@aXtIzq$8~R4WW}M%IdPWuWT~{p_UpH_8&V~9%)5DB$|5G~DvwXyet)$E) z|G&GhLiKuC>%DpE!_;Mc=^a-8)+x{ai9SX+!ZG(Tj-x=))&YB2eT*(1cxvO8r61sd zPxHXjy}zt*rg`9>^uU`7l!>Thg2R9RKz< zslIQh+_<{`OPr@RX%m_2pyvco+l8`D-{*9jhMwOLZ!Y^dG+IhqsPqm=?6vWGYLiBa ze;uFlT^heWru!1bZ*7xm|9`hl8YA)l-8Shs@vqaVT}rEYqu+!z@5ml0?XbVwCY>zt z>+47N4!Ymy{M6UaQ=4>-T(}o0F{aI$e)X8HbP?dcdIz&rTUYxVeGW0ultFGzi+*;k zo>`#J#z-0QPUh%YLA}9^WL0UHrFXUkEoAl%Q=pU;maPix$5J2^crfD z;yE-ur=a)#bDp-j-kD{~qIFi5W!hZX^KCAAww<%kRyyBrG594m7smaMg<`C^2G(xL zabRsZJhM*x8|$`ser~OvFMMgIZ*bB3pmkP-AuY%TUT=V&TW90ED6Kg-A3Yy28|Ogd z>p7BswwIB9qozA@#*WhG)c7^UX4fzxi_lK||N1lPL@Df{$ZT_6$3>9-lobAwXVe}a zPt$$sqIje_hJJS?+rRADw9Xfue(OEnQ=M{L?n(OIL-!)eV(UH0Q=O76*F(pvT`TRW zPPtzHx=v}SBM?{n|EoH|)3fPMtqGNIt+b~)fj(YETdZD};}1Jrz|7b+J9A!$4pc?IT0&4OmS!#L3kb;N$m znWlFS_G8X8y?c<2W4u)9s*ZOL&SIWB#Ax961!XyUp?rg15X=usPT#PUA*y?~?ZpwmM7aormJPmVTn|igyq+E^_-t zXuq+c-X(Y|zMDz!RBttWVyhaynOz;;eolwYkJ2*(>7#e7(QcWG1yZwOdn8AqZyGS- zv4~8!t@IrPZ=5T=gFvqJ9R%X^I|zOru-5p=T%R~01+$CePf*?pXBz!%J{kQ(jT$}IHYyDA4&5BI*6tl) zG%O5?c5V)`V-7yn5r~+IdHJ+H!DyIR*z_B)Qq6H z3SN*rt?W+B5y~Cj-V=HT%MfHVEHwPsZy=idsDjvUX%SQKL z^Y}|Gx%Y;G_tX}+X6`py17%HBqxxmG#7E->=Gf;5PyKx}Z|--S`!xEVuEWvy@-HRJ zbU2#-yZzb!^up^-oHr%ee9n{=Zu)~w=f66-wjb%K&2dy3CzHh^)om1y&JW!dX(YU< ztHD0ZeGew&k7REN<*Chaz5aEZ!&+}^|JE{RZF9Mh5=xV`&7$82_Ecx<^N1GzB_|}{ zS!;#}ul;Ggr#4HX{1mCfV&1I&>DYSiq+cZQJH-R)10DynUO!K5mJO0op3a}*pbeiF zXniB!1ILGlZ}{0tfa&(*=2&$o{PIh$W-IpHvOn%3~RG<8kMT=mnKn@;UH%CEC^)VHfCzY-+R{sjLc@(k~AU6W^r zk!Qc6K20#nr8Px+4{Ohl8;SX6*?8`ffoDhbyoB;^y~9?Lm%BONY9im1?J!(5FRq3> z7gG6o0MD*;KB_#YxpSnk=6OwyLx-pR=)6B$ht_KUn4eW0a#Toj2N;1PuqTZe9BFiZ zd{AaZBQWF^W84T_lP7(Rz(ib!kNG-ONDG}D5;vmD*Lxa;kr=XzmMxd*CGkmqCSpoypuq}K#R}Lf2#8&< z0V?u-&+N?2X32dhkNzK@_w(#0H@kcG%*@#{^P4$)rV%DlNgX#zc2Sf%ad`GfH7Ki`Z4>q8i>|E@Ww2J}u-x$@ ztloXPTqIlhWDd_xADL^9?JA95D%)J-lB2GDQhg0lkDH^vz7T&&MMLDA=Ab)mA=AbS ze`N>1v9*Nm>~opph{qX!AFUs^pJu*;?&L2DL4VvqcgnfhL3he&Y&J>P$^UH#{(}y> z^Sw+%D)BhwG;5N$=_hUz{%6;P{McnExNV_OwxD0zBKcZxVnfKK+m;Ar3)VeOTd28? z)6IUo;f*cmw&hItP_~SIEi07&Dc}}JmwyvZ->QDP@>tjCDllLeLxh+3Tv??D*SW0aU-&$I4@W%K{>rrDK|8>#tE<+`v-<*Aw`>3FwB@yj z_!DY2v7!^p&^k@;l(B(Koe3nz1%TtjF78;fVM|IG)q=esIeTP<&m*;A`q`{^U>&v^{r zSp745W|mnq%|1>nn^62--|I7ey5P0&8G7lpHMawLw)d>@BpQ7`!u*0d!~6-@iuldMX0E&9 zIkTTkr3;mgMdz}Y%p#8`a5HwctZR_Qy8N=PK^klE%bEqU-=nO9kjA?FvJQgu1!d3| zBzYkF2+4eY(c?Js>k{%y@?r=5rPrmraqxw~FMctW1E?wEN2^qdjwH@*DJkdpn)MnwGJWhQA2+^sEn1(+ zCX?-2v}%J-X0INtEaHgG3r!dG!7#DEi;@6PfgV zS~#(L<>$`7P_{*Ptthw6<$l*OM%Ur*p_9NN1^u2jO(O6k)>Fde@uNFeR!^_9hQ-+{a<{Dy1kXZUMc5%tol?3{R8 z;!vI)jr#AUx4?azXj>xTy+AOEWwc3gJeIIBfg z`nYtfMMiG!-|T#sI#J5Gvwe|Q@XJ4r;QQFOM`<7)x`cOYc(>+vpM=+Wi2p-yda~iA zPL(*_*fr@Nt4?dH!*eQg#JUC5Pu=8Dby^i&6uXp(_2~Lj;w!Jz*3=2TufvOu%uh(B zO$t?~?bG39UZwMJ%Re@KWR^I5j=N4fyWI(YFTLe>LBA5lPyHK-j`>eCWN4ieNZ016)Ysdx=bjeMkr6AVgXy1N9<7p8I!cU>U*mpD&0ys=N+b+JkRSaoqI-_^_I$Sx$e{GsaNd|m&XtnX^G zPT!{!lrk%Na_c`-UHqjE*GtD^PHy?LvUAHHJJs6fYo*qD4gPN@yA-x++qMIbIF5h+ z=4PT~efZVc_^zH){c91G{RuK=R{Gb(Z?z;QB_Ly^3SP5fYvHSUkUfjDV!{J6{apj? zy8BlbccjnGiU@4*M+BBcrvwUiTd~E$6CECy;p-B}yw8d)piijS=M5|l?;Ob7$9*{W z(3&*!C)_ozAa3!vnQ={m0GC849o0NoRNu3iCI(A8D?eCh&Wmyu6Z)R*k?j9Ru4X+=F$K2^Us)z~e2H zxGp1%JXg=I?8~!=!Y(R}h(Ncns6fxKN`XCu{ep1C$S|zh>^KS6B`=$B5rI9VQ;ZyY z3A@({Cv0{}CiLuUg&tM75gnxD4N?4xexAIGH;{RH^7c&RKu3kcuIjseSeT@nU6PWQ zslwaghLMIhu+FL$c+ILD7=j$x$gvkW=2V*#C;Z)rn{)z0kYg`$WFkiN>$s~`3zW_ZIBM0&ZmLNxg*2g2r@rc%kgzcI) zLh%aUV8U)@JlPvom4KJ9;Yxl_;TzR%K_6Kq>q$f8DNyh04S2aHy~1eXj1CJgl=$R1 z?@PYqDBVfC>$N`CX?;+h3*R8j8^~e82w&&CkxCy+xW3V<5V+N<8fZ+|hJ=&y@k6y+ z%jl!AdgsW(1ma2{eR*#wH(m0Ek`I()o^M1}DN~fAz!yp%lq(fqn3SKw9|-#ca+q=_ zd{UOWl?pL%UMBrk=}4tE_gc>}jw zrv|RK;sQ&NV=;0FUN%yX2(KysOOZqHvI;p?A&1ZfN1GImq6%&Ojt}B%6J=g#8&tUu zD-^tJ)b)jgm3)=(cDTVMO?vrP%k>27G*xCdA$p5M6yq_}zq!4zu+l{N2Gq0l4~-_h)U{ zV0|X^Oz4{xJ*v>w^AKbaIx-TM${*sB`phkhoj*}Je?*p^3BrE^VXxP+>~hE={3gxv zWGQyYV(Z$LMdjTI=26p{y%HpjA;=>2is)sJLl(&+kwwxhPZrUa(Tkl&wk#)?M;HEs z^5~-fNFF&cVQ?hpCe?cJK= zH_`^l+#A7~tP?4Dvy|uY;9)QIZfEL2Sx>Sn&ks-DuuSSSdG;XbEFm4KZ&bTPe8t!X zQf~@gk|`U8SH?KUSDqG^72YXOfbApgM0|L7pn)$Xkc@5Ai07F;Par+Ib08ku37iC` zMboF}=Q*~OgwOPQ0vR!#0?F85ncT<6cmm#VD?xm2?RkH(hbCgDhz<@>m;6Ru(t$NO zMF#`(t|_@ZZ&C^C>IV){mvrzt?V?G_#u2+{HSgU4n`nTyWO+!CDh65L@%~&6%h<8b(QdnPHOTVjVt#`5S@6r7QLRREb?wfmdntu$Y^9az&jp~EW(Fv zi!43=L3#=NpX)`+tmx0=kXL?0UWIbM`E{0d69ZV!o`EJ4d6)ZdebHg zUGh1bvO-%^m}J!qbjq7haw&9^FO2gKoJQYoI(g3+IaOXH9CcWs#7#L0yi5Lcq1?#% z9nYzO?Vh;6V&qte9N@k%H}*CqM>gr(vPTulc)P{iW9J0z6^U1#OJ1ksjYsAh%J#@6 zF5%Bq@!8)Ox!4uC*li|^)TzRgl9yZ3kn=d~w(GFlrV(}~;i!)a#cmV+?bu}^d#*=p zMCvW%U>-=JvETX;hdh6mzVlAlZN=z-H8TR+vD<`yEp}Tx_{rsa%h+uujPUi#yH4rl zDXzzQuwy+jfiB3=N#~2$vCe$yqVvVrv0A@@2t~Jbm4Y1`q-%Y69r`eKtkFlGywQ?J zN+&I`qbqnS1gd(f2I93{FZvL>Uh-`h_PWS}?W6P&&%Nlw*!S{G@+DX4V<_(yr{dkE zzAwT8JF)9UADNU7W7iA6gtPNxl+wpy@+AlRVkF-=5rhrX-xu!TL_Uuf) z`({zDXHp-E-6-FE!fWiKS>QtKM)TcgY`A5}6^)GY4Vgl_*;(0*eD5iJP_B_f>_%+D zLi61x?W^cS+EF{)2xNkn@8E~|4$eW2EG>t82RrT894&|W4i-7sb0aWI%RyUCIn5+~ zq4WKV973Ds$QSb+?93NC+;H0bFlD<=vnnZj(b%r>G1Judg?aDt>_yRQGbNw-z9_X_ zoAORl1{>@4M(pT#+F|ssa4YtUyBR-u2 z6Yh+wIq|MI@yCcCrlHFZ(@Oj>y}Bi|>)$=$e0)C1U9C1hdiWmo*uIzm_z_=>d}F$O zG45|m+ZQwTC|^up<%@|8JjuH{eKCEtFQzZJ-N?7>iTYy3YAp1njtb?Ik@~+2I_##> zs6n~HXF}c!f40Vg=-l{XoZocz_qzCEBJjm{|L2QA4}wi8fB*Bvl=a1op^g$?OcQX@ z7|fLCi)lhzwUN5I7434XkiM8P|F$ni+Ek}6Mr;eID~<0blrLtmlFxkWm-=D`^G@>Z zZfpzrHZrz_#A(;r#ut;Td@*-m4_uEwM*JV^&_{W`m`$W7-)hFz3i?H;E9Dza>cuYD zT0y$5D>pdm%H#3Hh>as_{X$3kVy;vCC-Y;(uL*@BSE~g$6---FQ zkncyaNy_t`^bPt>uxF@;`j+E6k+4#?2yabqtnw4I#&;6SwfG56Mi%9>p+uxIw~s34gek^;-$onS*HhYt+8Bxrw5HsOjb4K9qzm8ugWzvXTQ2s0 zF>P}_Fk!xbwjM_+sQ6oo`O;zd}8N~@nCo2J84YVc*2QK%k4X9j6C8aFm|V1H;GQi5LavXrF;dYzLNxe7RGnd1K)<7FBJkk=noZrET><#Sy*(SMOgX1lQ;GE;t$8=I~j#; z{_lM!Vy7qY4yFE+3IXvgNT1U(rH|4+bMfIA--+-@SmCq#q{Md;j_<_#Ki>)8{9Y4vz?gM_UQ9cF!+yGN0YMf}uIg;kW0F z%iJXUUe+Lv3$6jjzAFj8#Q6{Th|40bhAa=|54QqgzLY>bX?dic@P!3@(L6_%czGUe z1w4NGl8}{=r-69CC(t0quik}vGGOs8%w1v(kc_Qdr{m5 zBx@>(K03wFe?|XP7t&;&KmAv{KWRw+)*{mAr2Ds$|OTkVZhz&&uUxyyH{a7g4))YXwD2-o14tu*2&!` zBxN!zGhXy#qEAW@j@0;QCCR)M+Zx_mX82K;dTx2amA3MDcS(!7J&78SV^XrtX%&$|j z)|NBxP|xPyq37f6U_PGk?If-}#3gGx?qqJ>4jrzT`yGVcL%4r6&r;?Mt`i+_Ue8&| z;RbyU4{|@o3iPlCrUxb+O=`%dgO)Y@|~*e6xJBEy_miQFgpChf&2lsx)3_nK5zZvj$n( zy!uJ`tT`rSLe?Z3H@$w+_?PP^&1Vg=aZlDy`q^7MQI!wjp?t{NWaEFVpY)5jPU5TR zL)I(Hjg&cz=$-K9T6p9-AAUoVbV{#FdB?%)pBmjy^3Xpurk~`Y#Xa+qIvgYq2TrZo z?>C)?7SC&PFL`*7JiHYd4uY-UywwwBkFCR#OM>f!gvMv2-j~d~;y1x6b6VCi?lCIH zYO``zDMlr)Onw-Q&e9katU588MLtXqfl|m12D7Z2Q|`6!8Xm!_gtO-cdlQR!?@Kja(<)j0>w;JF{-P7n$Mcz0ZOoE)ri_%u ztT(VsV>X9#D9qN4^HUxog8E%D#9A%!7q_<#31**O2-2M>)$Fq<@aQuhH@!-s~L01l} zW3@P=S>uMj)2*EB3dbwRW_WlGlOhW{*YN1D z_9>c&c6^FgqEL*AO#+gZjze8bBpfP?;^m={M@MbKK$k>CMwPf+!)(h8&AzrDDLIvF z61zN;a6BV!k;lX-am6qZP#COynXwV$=f6KDU+yixqH!H#(-n zpb?fsc-1qZ5k}&M%umsU7n+Vw;>Z`eP1C%vYk4G$PQ#`NuaZ%vD~u9`pNgaOeUz-i ziwr6*#RC`NVr1-pxD^)8k9h!W5XT>koaG{nYef)RIM0NKv+&9_G)^{4X&j12MJw?L z5B~@Ur(CNb63nKVa6*wJRopr~l{RF>qoQ%h7nDb2Q2|6Yb*a*G%5Tf6<<{w{^unXH zdQ=HgStN9SOf>3^R$0ZhQZ4r=SFTkUm6eJ|Ws4|Zl{Dg$uqrEr#!n6t7f&Q!i9>jV zuHvu z+?@IO@_A-)a29^`EFU@~#UtVJxshATug)qi;mL={k8r-=Gl^4p6-}Pm*Fsa_AaU@V z|MHADB@WV(pTy~tYv}q~J(Ku^A71D@*JpM8Xd%QNBeD;{|krmmsMGp;QOBVkn#;U_MM1G>bi!ax%qMI${q>}SFwKcV^g znP)c5gy(_%Ov!0qtMrr%B1bZD>o~M5LK9hn@@ctj`Te4-e4k}a_vPzENu29^LgaH6 zx;lLDK*b`m&q9YLVGRw63ai3Emt(s8^T8)!2_yXZkVHrmw|&olo(oN$NfdX2gzf*qrJJ*RRr9)9W^}>8x9%j*B(DS!4UYNUJJC(>FJ>>6?uT&7?Qy zQYpceQDg#XzdqxbZJMi=qSFsrJ8$d_NVBrlVk-8{Nawbp5{KG8-bu8y*p}>BW9N}A z*TeQn?OEfbKVQLqAbZ(3=?9ITT=b;a5d5{vr_a^;l{v1JwG4793PFE71pPk!V(xez z4ncoD1bwc~zc}P^mah4lZq|}9qQ0f+l5RyqUH~nEvH|gr)X+5s# zCS5~+KSVrj672X*JldSGk~H1KW9WIBF7i0n(`zQc;BeF1oKZ@*F>BwaX}U?*%+1Zx zbd#>3-xngDf3-ry*zDoyEsk0y;-9ew&s>>A>^Q<5*K!$Zj&ngGh)vRCo4?# zbj&%ac7)M|G6#VZFU*5Y5vrnggmkuCxfc(t+ zoANHzXnE6dH{dX9$(SXa+0d8L4;F~9##EvoF@iqYVT|YA8*@Wk0{yv-^M;jFV!r7x z=Bh^1Pnr;B<~T6>J{y6T^8!d&bP^rvmIY9nVvMdmdrIg9-ffiIDB6Z2~J(3c=GMrj#ku9F?l zFcnV}^2t~|Gv>W1X~>v7J01E*8E?RSVI%rOnVTJ0f}E26QsmyN$DEtFPQoMMg|89s z*Azav{?gwquv^9}SkV=8_=$X?&zZ=!n>iP=kaaon%3QGo^cY=jR-D9@K)-YW{m{#i zApyPF>4X;weIsR}6ME5fPSNaqi ztN!4K!1a>fjI-=+MOI{dqtfF>f27LqnT)-B5dI1}uSG_g3oG%6EXBlGLFIF)9)-SF z$!O1yHgjS(^PbYzEP86D^Kz5cr5S%I@yTiq8E`dg1mLhxC|N1SXQTu zl1Cz=j8&I#rFyJZu8hkVr||E{_}A*OYWXrQV1F9&NAg8vmGUTgF8M8aY4ZGE<@aBq z%Vqbnu0^n1Mwc(^owlr!KPM~eU!l`wxA|9>md_Bf-ue&G>+Ivu>ka=9z0Noey-xjy z=ymdO=yl>hM6bEWp;y_b>Yq>#3_A|JG6(OUP_K$zcRlm)+;-h&>Zj|O7q^LaLfZLA zYzL`V#io=9$%Nqn{~63zZz zVv7t>al}7-r2ods*T)r9E{K~J-Zc=f#y>Fzll?*(_&Tfk@J;9|r|+6ELOfUFr+BXB z!}FZ+MADaD;P(Wk>-q39zDnl9(}SYMEXjO+naeNp_J3FFW^Yk_#DA5)P(BCbo8<5G z8QT6I_m_|Q5aHX&>5Z{z^1nP^qI+Gq=PTL#@(phM9yUe)4}M%JXPmhkl{HEE+l(X5 zTB+H^cP8I+=6GITh>y%kKXG5ie|DWVqbKuT$LquBuD=`2x4nG(N-ny;fyE^zboY1g zA3A?{ROS#~=Ml<>alGM;55vf5;x^%r<%0;dPFtc~a7}cpzqa!l%>ME=3)SomasdE^J^J4+MUPwyoQB=+LHJ+g9cK zAX>LR8}Ec1$G=Y7!HCin{p!-J)Ar=@M$!4(zF@4O_#o^tnD%~1?14Tv(_!H5s{cNm|Ok#qsHcxclYZ?$Sdy?zsN(t&LLws!~D?ze&K zU5r`F4zt?EPw~$SXH8D#_4TBiianLXW-~TuHhX1$LjmreTHQ)I%(#u>n)Uld&d+6jKv4>9Y)TmCunzR> zY4d8>}lMSb3dW8=kaBw&lg_7bxeNWqSUYs>j-c0d$4;J zOEJ{%cYzgoH9G81nyurfg!N0ethNQ=RyE=l~1WsHKtl@ zT=i2=t5LI7?K*W&uUFp}-=JZm#`gavO`9bop3(fw7H73=)%xrTu4v9nU-e z0)MCEl+I4F+;{2Pt$U9^&t4Z^)Vt5cef#yl z-mlMgJnojjvKsO{%+c@X>klH#kCw;7yF@Esi7VTTLX`@S9-7qMf^u~}aT-D$&^_my;=xipu1IV4>t-R$R78@e;kPTW@c zXY{)mzq|dmW#3h3q555RXr-*t0i|semATu@P&Ui^TE9AY@Z=^p*KxXS9uvMy9yroB z5gMDt-R_(4YYd}48~F`6RKLqzI>Hu)QJ;Qu`kk@d(=30&ssa9l_pkIPbgRaAZua4>&76zWhSn217|Yv* zv9kl~TZJ>d5wlb4So=3u#g3_CjhV$6RjT$px%)M0KO-}qyP%RkAs$~jdoKqTUtk@I z$M=r~YR_ZvR#Wp-%(~<UtReoWXc|4`ZM+7$5&8cGi-8sj{c$)&jKdP6qIoA-!-xH*12W&H2z@Q7R4t)_vZ0uhz`H2!kNyFQ_4NIlL>DFi%F(vPidx zbayZpWO1FSu{(-{AqzNmhZ z=v?M`m^mI&PNnP}VlUbBZSovG%AVxI&))Dv*|%zOoo>rlquVfOGKV9b@*sSr*YbQMMjmBj67n4M)=Ffr zRWa=L~LOozuQetFxLXH2H6_X>A+LUE|snaVWoz<*;3Km90)EVspw6C8y2V zOxprt(>iUdVEn;Gz*vzow#pEX-q$Ke2Xxzl!!_M)3og@ivF)6$kUXs#H+_k2``mQ1 zN2E#Dw1w2M>M-dVy4hRN9nXKOEokyltFw&VE3{Cypz%4Z(E(4?7R+%P*g6h5xl48^ zTkv?phq47tcz4-#ixtWiG`7&m+JXtA1g820qoK?$rFbBKT9`vkOxy~xI z=Ou^XW3u;$Nvr5zogV8yR3BegS{485T{RZeMlWqY=lKriEEDB?@#*+zTV)Ql+3$Q0 zdrf8~TllD|tNqdq?=Q49e^q-TuOmABJN+bf{prp*Nm=~P$KQt_-xAI?Vv33Zi-NNo zXY%N*5OjQwsmFsUXbRYn8b&IGe}40{u~wwcb(%#h+2Y;Vep_H86Wa7bP5?1SiT zlaCs2I?h3NwmBzW_y1@6EKI)W*E#MwKTYGz=tt@bDK&DI!_*m}zW+_1kIh~B-(B)T z)%nL8-qiW-y2*q;R-GNH&*JM+k;`1Uy% zd$<0D?)IHX&=?(QAGvWHZu#Z&z1+PE`AQG&Dnl*JwY|4Y`<87^w9n#8hk$-1i|Mnl z*B^EERs6#Dx_ra42kqQ<=_i=Zce{MsAK;s(q+wX$0*|%-HTEt1Da=~gNxmKV?(8Jr zC46_v_e(n8nDYIRA>SK(cP8_lkip#2biO&|8zo)O8MdO=3^aYhvWB~?nZAJid>^6z zVqq-40>0P7`Tk|P4QnXWT(Kyw0^eOVf@^HdXU^>+Z;ynJssCrNSMNek^`rJbUKc34 z|8e7esnQp+wYXzUzeeVo?{0I=_`Jj>n!d4abU(wt(I1g$t~dB165A3-yzs&Q9_hKF#~N&E-(vCEazs(p?8U(eIM= z?#fWd<0gk{qmDPcX`|fryb15Ny4>#{>bqo%7W7zcTr%(FekXa=gXIy+;SJTs&DHup z+3ymQzG>s+n?!!c+s4(@=}RA(^Kicwv%FG4-w5+@67*4rXyfR$KjHm(H%FC9;8&NX zje9!iqn3F9vW8P}T=eo^@zE_=>|dP{Tq7t_}Ih;I3NGoZTQ;q@v)`xJQrF% zKDOIJ`d{raRSQ%6hs003_+0DI4%V!AE;TLzdFL-a*MI1_)P4!x$_JlL^I3)IHLXG) zYaCrr-P#|G51#Xw&8)4m2;X?8?&)Rxo*vpejMuHnw4Gt*+835+t{MN87^UfZX*&)7 zUVrJjM4#gmuSFd8x3#j@?Bng#WSO9oi=UgPgu&FlxIfuOIU{Ad}+ft<;OO<7hQ^MMxUa4 zrR$*H$pe?(<-H{QvG|JPx-OrO?_2V3DdSC-;ge@9N+2uz;M4h($7z&DjA^?(vR}3; zkJy?EU1c#{@`Q3kJ<}mw@=0IE?ZY?D^)$&RO%vaG>2)b@O`cbWzkq!G$s3*cvo|Vn zF?v(wLE{l;r@~`(@E8XU1(Q+^t5ZHq*$_-h`G})ji0yY_pnKQOD6vYV=t!!^zr?O1 zI@Nysoqh@1j&j%Bl5+WD7#Y*Vp&e7|y7b?P_`3PdDC5T%ts7ry^UJmE$}}cU`_9ZI zR?SS%2@#yKti_YTMsm1qy#Y2^jYn|W1JPO~Zd z*q(-7S+}|Fcv^;_Um1d45Q2W<{*`~mI15v5bT$I{vPUQzwvWziV*{P24g0t|A)Txn zNug}m;|(9mhBe{EALu;XVui9{U(}2zYr}r)PDl&ke*aK5>}YMbovaPJPp5D4PwZFu z8N3)jSx7&P&VSL5^Ki>A4$x7Y*>a_oUm^_UzDT|zdGB#buO#_T|e2| z{eVe|c?GOX%X8H+<&YGX(#Yn%|UJ!!JJY^5UPa`73jl z!|>n7b$R>`Ll=3>GsC|r1poV*UkaTZhW{t7O&sch{ufS0O8f?EhQA*4^7vb5e&csB z{M|$F577KRlb$}048cEH^EYzw&kMo7K=U_q@jo4cf1T!+I$aJU|A!&?_iFx@HhYji zlD5A*{nUXj`fTIk?-+u=pXN_;@sA6^KU?#6bn!0=!T*@%_q+Hvh2Vcj^LKXfe;tDV z7tP<@#a{s%r9Az_K^Oh>a`89R^gb^7c_HGtQ1kb9@#lo#pQQN*xcKLV;9scu1>bTQ zd_Nb0e}m@Fve|>>o`WO;h416}ks+{Mqp{&M**)cm7e{8xwIzgF{0 zy(I^?>bNrm|5DALr}+&33nBPl(fm_f{5wPN|DgHvUHp~!Y$;Dar$ZP06u9`$4Z+`A z^Uree4-3J6t>&NO;=eltzh#ULyAO6$ZtifgK~!h#sL|twj?$|ynd{Ut9CXK?U8X;_ z452JJf+-O*gm4qo9i_hmWDbp49Ey$qo&?@{BF$`H!(W)3df#q7K<%jxcncHX-< z9bMMJuf=j%$}Dfy+A5dFUg%24bGD18%wkx<8&^D8*=LKlG^knCTj3^_7iMrqyEf&7 zDnl+O+^8}P!PLrFL6WCX! zPu=$lE3V?fI|LO{8d5k%yER;fP?mSh`1CC4qt!h}j@z<)tcI2~YD8*oc6OH4x6?(P z?W=Nm7(AiWqJzk-ix2Ilj!w_boj7W&t!B}8DWx3l)`s0)l1=eDXk|ml)R9qH5+PY+ z%iufLDk`cOIb=;?y_hQxyw>?jc%W0?uvYGnuBIY9YS}GWij@E z(Cv9lHeY22zjKa_X|sgi@u{dj4kd`tZNHoyfw9MheyWaBPR8yQdJPBNr>})x%Rz7C zpo<^H9L@BF@SkpooSQr7jPnW}EgkguAk_-mxe`x92i@4SLT~J#8@pBL&N-oe%_DT_ z@GwVbeIfKS43Tqp2i@6+)hh(OkArUBMM%bel=xd~9yu91QRv2&7kZlf;}E)DUQ69) zssA?Jyt|Nc9CR5kV~*kaLgFzx5z=S}{d|2bCu5fhzu!U6)7L^zcF>KTC3K@hd7Q6# zgx*zO%c;OYH@X$lEC)THujMqyK{q;Aq!zi8MvP0(z!y1gtbNWgSLLs<_n#f(HCMlf zIfa`GeGcV&{8EG7^rJ_^k4l5z2{m>2CYp}9U*>qL%w6e?#Nj-eb0cw|YPpaArX)Idc)8~j^XNk}CTSm})Y+mZ`N?7QAIf)_ zq!}N=es>=3^tBn^+Bgr7)&Je9Rl5`R9Y#A|(65BCeTPB+-hYYDuCkKdtwCG6<&6!J zC!ywI$hVw1OrA=+5MzkWb1;(}A6qRuv{N5j#+9iPk0Q^Xh)&*D>>{sY+uBz zc}Fr^&fe|yB(equdngt3Jv`Y8j_Y}99rFwr+w&`9cdW>QZL1hVV2@{rTR}AQe`Z`o zK5I+t^q$7}5}PJxJU!dw`3}Y|lwMa)jES7J?eJv(a}OWR@My^DJ}hVUyd9xDhA)pp3&VcDA#&q5yg{Toh+LL8-Ypio^ZUbY`z%ZBV4<6P zQ+LSzALX?z;*Sx2^UUzeH?^U089XlKO7;;kM>BH~ER<%<93>*v^c;;IJ9I+&xa?G+ ziPKj1UntkB`yP|t*aLiX5Px}r=v`YhwwOuZ%~Be#rabJC3-Q=Jcn^vwY3qEGt4X@|$ya zO>3$7&FN-+ajZ7%VjbRuGw0{bh3jn6HRO4&A1d*3~*I)H+elw!_qgq1uQ<0va9@hdP@~R8_vz)y`gU zb+7xrr6zhvs?a9b>BYCc(V3; zzE0PS$v;v1eU?t&+24LEbzi#^Uq@q&qj31ud)aj#T@iElvL_6r>Y=Xx zDu0h8EARey+U0*&ooMQ!c;t_f7jYeDa$g=j1-jGzHt~pEQy%|t&2O-6_^%DYFCS2< z@C55zN>Z!VNyem>53%5NO5e--^zSX~ZVn-ZU@N6dR4|stT{gZ_I$(4J072++VND;*Xs0N*3Z(& zDLdCj|ArjO?!QahO7CmN6K#94OaiVm*;3|c&Yi^VsGijG;|(9G?J?m`w(Xf$M#|C~ zxBQ{np3(Y+PPXm2ODAdiOHQ=yF~PQp*Wb4RlN<}Vn<(5BG9a&S?3nyDg z=Id1dUHe>YH0R-#Uzu3r#{Ng@NT*HyzdG{YtRpkY#9$rC%`xgo7l*Tm{I8BIqYe6e zxtDs=@1p;&j&vzR-@5CV{~zkep+mBdyN*1&!->yVo?E$8mwt6=*4$aWoN?d#8`bpx zR=OUjwL-?|u%@?KU+!1N&&WFQvaX!06aR}he8oX;L}EUE->HNxAnZ=AX_CxdE^|qu zaBW33UwMB0C~M4D3? z+L9k>9g?+9&ARhpUe=g_A5Y7ceE9R>4U6(0I>?xyT;f-B!U+F-?!RCS5#m~26lpED zqU0R59NVw@LXUsB$g(=4)ADC$gcXWBon);%kF|VtMp$sHQrSJ$HmP;>ri}D27da)p zY2L6cXh$Dt=6*nY+Wrkx>|U)bx8Cia)_QpM@8-By=$$o7!!4(dfJOTo~r)k zi>ja}^z}6N&knYAw9wOO`Ey#1X_SFy2V2Wodwuyc@MKh3yKGU_$mP$sXN@EBuF;gL-YLU%U~F z2a61r^(CRodL6s09*GQ5*7frRp~`yQ((v)D>vT8e{aNyAvZvN;_I*NzxE0T*cnXhr z>UsiF`KW;mVdVy^kMzM1>7YOG?Q} zV_igVVCU67S&OHzzTev4>By1(JJ9jxjK4GcPFe8pyqbNT2m_Xm;XSYuhOlq)3w(hmM|HF zSxnj{OeeyK%$;IMOKdW>|9rNpv{&|$qk|DP2VL20%GL*hNfv}wRrSg=~ zmpxulVw#K-g!R0kQ01U zruY=SbC)u7tJ(1EkweDi_!|2pRC2H0DLqsB^%&SCK|;3tD@U&Ur+wr{_YaaMR(WGi zY`VMG%ied!*`N5W{>}^4pO`>I<@r0>hM;$XF7caqn;GY!e5l!Z+bB;tzPSl{we={Z z&O@`y_{1eUO;@B`XAG4nf}!Lc&3CelF>$_aA9=`O)=aYRXaMwu;jg9d2k5imH}o`3 zm+_Pp^|hRa>uVEFLw!G5pG`c5KF-B&;?HyO8+yK`yVITHipRX?Tvt4XKHtS};x|4_ zBd4JkX?}OQ<~v^Kc0Z2I_&E1+xalo*xe~g=G_=--peN~aV)SXp%3L;0H*y-f-^Fj_ z@9g3?^j@0oey;(pcpB;i%vxC{T|-ZE@tgSB3q>7<-_VC^x;x!GS3D-arnurUbZioJ z82y;|&Dve=bmxRf*QXt5?)0a@_g&S_t}y`xpOVW3il-2pT_Le`Aq27&**3 ztk~(QKUI^1eOyg6U1yI3QAdAQx`wXdWp34cT8Z;y!yA92dn}bne^f9f`@*De&VI;p z-O_#>{J&1ie=L7x4;?-jP+#mn&i4=XEpGOez1$VCk=u~vURObeq|OI*`h9c&sp};V z-T5apx9%kZ_K8x5XIYt^^mv7Y}`K2A~b-#N~}Zg1Qf? zk!4toRi%5Jgw^H{5lx-v?vFPzx%=a*OCSz+8`sDtD}Suh257125|5MKM$;vpGGjXb z%lh^G`aR6a=+oSX^2eIK*twcfsuU^3?mDQ6rn~E*eCXvJ5{L6>&W*%*vf)h|V)D_% zov$yB)dqwbQ}(Ed$aQwhAF2&Fs4MosF~UoH<+TBi>u{zGF!jG%|DoCd6KVD_(pP;} zqs9guvd3-%&ejtskAF@`j(ni$!>`V^KUVxxo$)cH`KLTwLD|e_$<1>3Lg^& zP3AIQ0BssRqRy-b*?FI}TJ9sl{VWaU?+{tp-$C}wSdtc=7!mF7AbVi2S4N<-Wvz~= z4o?g`bsao49X#RiG=j$mPjd%PGY3yJJZ<1<2~S4{Pm+VDvbCCh(S!bA@HMvpe{gpz zrm%S_*ZA9iSIiiAo^6g;~hRgHxXH)lkhR&X}s@n$NT0u-j{SD#-WqZ zj^}y)4%QTYl+Aqd!cY2Ze>&3NloKof#$4Yv3I;kZRcLZ`;$SGyk znv`ajWn?L`tVGdcx<9qVE~BKG&$TL}VF4+leqBb_qi4!!tdvooJ|CX^qCKCwl6B}O z>H`bEpXEK+KI=#JXv4QCbC_kF_kwZt`lWAaG<&Ay>6vOp4C{&CI1Js!qg%pAGgjC* z&AYWpQRTv>MRlRIEQ~K|Uf7JV8N^jT%roo^`UV6eKUI?b-CkC9XcP399Aj0B;2iI_ zwvu0~F<}cEQ$CtdW+Qm7NPqp3#=K9Hn%whlk@?*7UQNiqh&9}=;hub#a+FcIQ%Q7$ zRjo7n>Vdw(^Rh}R>={09 zpfh^y>+uG>v^DBXyCVFf(yAtUX-^andio&@9@-jprd<)9;c1lS~f|Tn9Y!{3+oRnFT2`*<6M(CNILF&1eG8e`3F7^EL-ecb@ z2`l`2;n{WVfbBmJzX{vr{O;R@o|!zTr0<|U>e@@WotX#5DVzHV?4QqJumf*WZwPP1q_HKhu`kyIe!_R%lo-ykr}dzc5ybnW zzR!ez4c7}iao?=s`f>Ol<^DlqW#MYDS zckEkFY=qcAEIRO$7k%qlvB@4!z#_~d>W2oEtqxt#S7Y|2=z{JVhs!y-Uo!99INItk zGjB{uGQ7puA<1HY@a|%Fa7{jqDj5~wUoG{0F}e_1gStAt7#&}A6W>Uw_lR$VE56|+ z!z)M}cAR^({vyzc9dBhj-sU=9pN_YY9dF}iRtM4Hbo8B!j9AQx4JHlYx~5zQJW|$A zp`J#@WTj(hyl;b+_P*k>PDO(@_Fm)CSJ)uQ>L7c(`8rx14o_aM{SD78??t^~#sx_I zA^Xiq9nwwLA%_~4)*+F)4vC`C2T%Iz*jy9g>?C zSEdfhm3oFcM4fdVlARV&rVc5Vc&J0vxtuy=x2{7n!IEkBs?qLMrQNGSyLSq0-ViXn zgz`IwvexXHAtgg7Z@VXDl|+Yy2iAk@rRa7&_XSo|U=zGTF9;i?o@Ws*fiO$S!y4Dt z?04$5G5sX0gh_xei~7fe9YUQUw1Q59N^+@7bh z2ru=j)MYc)4l4P~Q~4XY-VGLh1_x4)Nc-CX{H;P4^Z5xbrM+!(O;(Atxw|G!Dp@iq zPt~F8s7EBe-IKfG>}@iyHXm$)5lE#bX#J@65CE_(^h=#*Nrm-mwVT@0=9 zHDeXeF5Xe{a~-&ocpF`FwYr}%EmfU&O%i)Ro}>3kIq*aU@0Iu?rj z@*bH|9`mh2d5=mtlajhx-r3J*+>DJL&U-cjB+lQv4? z_R1&iJH)D|tp8GQ;mpe3`Z~JSR7)08D1_ z9^RbmbR5}s9Ml&o4(baD-+;QJA$7^;$m7i!tKyP)!gDf`UZzbgjc2rqry=!&l7;#~ z#Y6p|;-P-<k|Cp7H12T7SN`D&xI}F8t!53E$o`Vau&uwoI>o|MXXG^uKcLZ#P`~+YhJycKMUv zT;A=LSGw){z0$r%I(_@d+fNO7dr|7)MUQp)`my^OzI5M`eg~F}-F?T{HTPbz=9%#? zKXZ6z-NUz?_vmd+dR^V5-SC0!F1W7K1qXid9C&R;@7LPoT-m1h;-8E6Y;Ch=|Dovp zV?Mua%=-`JzTYaNU#n9SFE}+kx^noY+xu>6*fqQ1y88#MtJ$(y%{$sJyd$Dw)rfn} zT6IrUl?qX@joQWL*SRF=(%`t295e)ZW$=Nfj&7axjrZ>AB`YPs-Cp^+K_0MTj`xNc#(=o4e#|4d_U9ha@u4NZ5 z`sw1uSN*xzpTEX`Ys5{r&b#1|dH2UZe}B^G?n%Gw5C7%)%+H>Gdg9urKYVQbhw;go z@iD%ZF-P{)KJwGyDnD&|X~eeIr}cWha?R?M$T1` zT6Czf{2_Y$=7+PcdUo$swOXH1EBA}rbJNxorA@1K*R-8?&GbNi8(w;%E0Gb3&e zn{)F!Ph`Dw(S6%4THa&F^5O5V9DeD;zg_zCPfF`o}NKKIQt^H&vZ^)94*@N1s0>`TSL5)~_1;+KR#5=f229dfTg0+g|qQq03eeeQWjgH43j^d-s5~r=QdG^aq-*eqiSZNjndI z6L;{gGoHGuT7$Ez4c+$K&<~c6{@|9V8*iC^_R{(Hp852>^*T1Fcf+akZusgI-&b$k z(Bq9uRvfvcS)aUSpA}#8*&Oe!a~58HaN&&=@^3t)c8ybB%Kq@BFWzhQMRLK$yp9%b@0RM@=e=_j@ z5%>=S{-c2Z2H@Wk_=f@iA;A9(;QuG^e-HRS1pFre|1H3OI`Dr5_+JbBe*^xP1OINo ze;@FF1o*!V{1*ZL$AJHRz<&ww9}E1~0RLxz|6$;N8}M%e{M!Nl3xNLt;Qt!%Zv*^` zf&U)hzaRLI0sij;|5m{NRNx;D{5JvrhQNOv@UIE{?*RT0!2cfL9|inlfqy>m{~Y*# z1N@r;|0jX}c;H_F_|E|T&4GVy;9m#$j|Bb$fqxP3?+g6T1^({>|EGX|0`T7j{LcdZ z1;D=_@K^W;{@($AAMpPJ_&)*suK@m61OHcn|BJxC1Mm+3|6ag<0Puek_`e1Ge*pd~ zfdB8nKLz+-2>j0m{xgAp7vO&g_U3xNMJ;D0gjUkv>H!2ed@KM(ld z5B!sW|1ZG*dEoyv@c$6_#{>Tu;C}@8{{;NE0sq&5e`Vkw2mHSU{;9zKPT=1e_}2jb z>w*7L;C~(PKM(k40spIje=Xpj3;ff7|1{v=8~A?={2KuOMBqOc_|F3VU4j4iz`q3e zR|o!|0{=n4zY_5O2>9;+{;h%kIl#Xn@b3ZqBY}S-;D06Xe;N312mTKO{|w+?2>fpc z{=0$yB;dan_-_XO?ScOY;D0mle+T$q1pJo+|KY&@QsDnH@c$b4X9NFhfd8YwKN|Qy z3;gqde`Da^0{GVj{tp8GmB4=^@c$C{e**l+0ss2IzbEj20r<}b{x<>t(ZK(F;J*s^ z4+j3-fxj2{{|fx80RMF0-xl~^2K-k8|LcMOTHt>=@P7dK?*#q_f&X2=zZ&o#3j99+ z{>GvNOj@Sg+x7Xtqqf&VGM|0Ur61@KP>{yD(E z6Y#$q_@4>7%k;Qu=CzXo;J*p@4+H+qfd5k9|2*(N4fsC- z{67NzS-^iB@UIU1=K=r9z`r~2F9H4wfd31?KLz-&2mT#^e=Fd>9r*tU{NDlovw{Ce z;Qt};4+H*B0RQ`de-GgQKJb4S`2Pg_-vs_!fd9|HzZ>w60sfTl{|&%@1@P|!{ELCV7x-Te{3`(e+Q2^>_`e7I3xNMyz<)aMPXPV{fqy;VKNA@E-*Hn*slY zz`rW+Uj_Ut0RMKt|6bsK9`J7h{D%Vn*Ma{6;9m#$KLGs40sj`j|4iWjB=G+p`2P<4 ze+B**0{?X2{|4}%4E)ar{$qguoxuMW;GZM-2mZ~0e;V+w5BxU+|L=hRi@?7t@c#h# z_XPf*0{^#x|Chi&0Q`pm|3u)w2l$@`{5Jsq_kjN;z<)mQe-rq}0RKqfKMnZr1OA|IdK`THrq(_-6wDmcYL@@UH^=M*#m` zz`r{1Zwvg-0{%OJ|03Z38u0G`{4WFkKLY>hz`q;te;D}h1^#CM|J#9o5%9kY_-_UN zQ-S|r;C~(Pe+c-`0RCHme**B|4*WX;|4G3AbKrkE@Sgzu&jtRM0{@GEe?8#;5%8}F z{D%Yo-N64U;6D=h{{Z|S1pdo_{}SNe9{A4&{;h$33h=)i_&)>u=K%jK;J*#{?*RTQ zf&Xv7KMMFa2L6u$|673nSHQm}@P7yR&jS9Vfd5$F-w62c2mYIY|HZ(+A@H99{O<$) z@xcER;Qul3zaIF{1pae@e=_i25BygE|M!7^1n>_7{;|M+G4M|X{)d47Tfn~%_zwX7 zO@aSv;GYEi)qwx2!2b{6|1R)1Lj|O}9v8hDwh+VF z$Is6%pPvk;Xt(s|i~D4Ex~|`n8nxFAYI@Ec!yY>K)h_qf-#_5Dhad9p>UrC5Eq#}a znDEH26JDED*vs=v%Mu@87n6( zo%dtZPy0R}deOq4Kg@pp#fZpvGTLmd|L242Z|c{g&Hb1Bw5Vw3O%biX`E|+oZ)a5M z@I#t^#ey+|B4b9raPdv?=O2pv&^WOS6#J!OvKxf;iFFNlXm3y zyJ|K1>V2Nowe}``zj@L}6{jrhRyBFbSM>@GzCwOj z*XLK5@!c7%yN|9`@8PinhhKE0%HiLWW>&rQok!2B*Wt`|O+TnwG3&uAbK?77aqrd^ z?HZjkq+;bK_Fi^d)jPglxvlWtIuC4Eli%C-ar&a369*2h9b5ObXK(wwVq(#nJv$n7 zOsP>P_ViOKRH?LS_K%M&d-}}P%j;F&Txf*yq!VWC>W$cyD zpF6nohUBMYWq>d+Gag&u;L;MLllVv^D92wTrgQ`Loj7ceR`L%Y$!zdQEY&Tb}u_$xDx1 zu;l)8n(v;M*XNYiQm?+Z>vjDz;%@%+<&yX3etDoni$RaAoBm7wRSRCc?X96x&U|Oo z^4P|2K6UrQo6o(rX3Wye`@S6c+_@i3&TH~|g_@U-{P~%Cz74yl_l#vDZ~r3uiz6$p zd-M7D=r2$G;fs6sKKnttQGquqEcp8EDUT<-`{a^Vk2Sm?vDN(IjV%W+YP;t7i^jFz zGX0MS-^JI>vo-W7FkteE&-NGi~?O-TB=U-LC2Q*|z&G&;9X|3*M++ zb5i?Fxi7tbpx@Uk4yRr*>b%dYf7Che`kx-#GHrd%>hs$)N^0(3{Br8L(@z`Q`19v0 z_vqMc_U)$}=@hoC!FTgkwGDe%t* z{!4)WAmBd?_;&&R1AxC5`2Pm{M*#l`z`qype-HS-3j8|*|HZ(6An>mP{Hp-}HNby7 z@ZSgg?*#sbfPX6RzYq9d1N<)s{xg7oJn$b1{5J#t8-f2M;D0{w9|Qb*1OG>W|HHul z9N-@S{;h!j*}#7)@Sh0$9|itJ!2b;3p9B041OMT`{~+++4*Wg9|5o7t5b$pX{9gwC zlYxIU@V^207X$yRf&X;iUl;hV1pYq)|IdN{&%pmh;GY5f{{;U1fd3`He<$$&2Kavq z{C@!c3xIzN@V^Q8M*{x{;Qs>fzZv*n1^nLz{-*-}-+}*Ez&{1}KLGrbf&Xmae+BUW z9{5)T{#Aj$OeL{^|MkHCJK#SW_>TqtM}U74@P7yRcL4q$0RIPpe}CZL0{9OB{(FJ{ z9l*a3_-_FIKH%RI_}2#h&jSBM;J*X-*8u*f0RK(Ee;M#!4*Y8Y|0v-93Ghz?{!M`Y zFTnp?;C~(PPXPWKf&U-Ce?Rd582HZw{tbYCHQ?U}_@4*-TLb@v!2c}Z-xB!u1^&B$ z|7pN~HSq5a{Ih`n9N>Qe@NW+M=K}wWfd5wDzXTkroq+%8z<(R?zZCd)1ODm2zcTQz z4*WX;|E9qI72v-I_&)*sKLh@`!2b>4-yZnC4*XXD|53pIBjEoN@Lv!7+W>z*@Lvb~ z8w39y!2fpO9|ruN0{**!|61T*0Q{c@{#OG3%lcpd^uqvHhXHU02EeNr0Q)fj9>M^) z4Flj341ixT017bx8e;(bfdTLy20%Urz^xbnJum=;yfbAFn2^avKF#xW{0La4t7={7x2?oH^7yvae00v_Kti%AQ zi2*Pj10W3ppbG}T4h(<-41l^A0P`^b24Dcx!T`7d1K=49fQA?VpJM=Ah5?X>0T6`& z;KcyA2LqrO1K>vtfG05kp2YyT5(D5241jqU0Q)ci7GeOrjsfrv20(obfSWJ??#BQq z!T@NE0Wcl|paTZL3Jicq41kL<01jaQoQDDMC;> z0nii!APWN^9s^)22EaKO08d~5RK)<;h5_&Z20(8NfJGPpLoonO!vLs=0k8)HAO!>9 zbPRw>7yyr80IbFU*o*-%69b?Z2EcO|0EaOE7GMB8j{&d&1E38Czyu6{k1+spFaR#|g3QD8hC=2hDN;%ZAtc-k zWhR%Bp)${9jL1BOYnCx&NTv+&|E_)3K2AsHs(ao4{k`w!-Jj1nd#`6dYprJudwtjR zJnI}f0GH7LxQY(I7IXk?(E(_N4nPh%0IkpgSceY4R&)UL&;bym1MmSI04;O?nxX?R z2OWT}=m2=518^4|fCuOR)I$d#3mt&T=m038127OBfKliG*q{T@4;_G>=m0cF2cQNz z0JG5n7>^FXTyy|tp#$&|9e@_-0K7m4pe;H8ebE8vfDXVobN~*a1MmzTfd1$J)I=;J+E*e+=ON4B(#+_dT_;NKhYe-!Yq z0{HI^_+JY6KLGd_0sgN8{+|H;X951}0RB$^{$l|D&Vc_o^8Ew;V*&q-0RK9G|9*gf zEx`YD!2f2ze-preb-@1sz<+I^e$#;QuAyKN;|!1NgrM_#X@S*9H790Q{!_ z{!Ib@^#K2Bfd2%*|8Bs)A>jWt;D0pWe;MF^GT@&F_>Tnq2Lb*+1O7V#{u==PUjY6e z0{(3Q{{eviC4m1tz`q#qzYp;L5%6yX_+JV5-wybX2mBuf{OuL<}+4*357_%8$ew*&ll0{m|Q{09U6%>e&tfdBe{ z|NDUdwt)X?fd6#Bzb4>+C*Z#~;Qut>-wyB}3i!|JsW$9NvzBWe4vErMPI>dk=a>hM zQz}v`G!Jyl%FAO#jtgMkHJ`k1Ty3 z7$3Z}*5x$=&I}x~dw%Fhx9(*xvTqF1bM3Q!&hK%F*ETS-_vfpBc<7^?wZlc_LSw^u zr#e*UAKr36z^n1w@YYE>PThvydbXtG{JG+tk4G)u7-d?xsm1jBA6q>!7=1Ua^Xs}1 z^{tN03g6?em8pNQ-k09(-SaMuGhTi(=WF!Yes7I#r#GLedfaxKu6EysvCjwl_L!Ve zXP3BIlSkuMEjYR2RZ2mduA8mjZ9P%6ukAFiWq!3ADNWit_Nv9bkeUI#Of)C{cj#t8 zJ5BCVbT$Jvp+PrBhM&w1;i`onOQ&vj)(Et^9Gz3{0F+M7*kbuPBd3(!ilZA-er%}buBzzyw}B^F zJ%2MAejiHb+?Hf!4c93A2)_q5Ta!yf`C)&DrO#Gp$&4|jv$|*jM2UsfMKcRzyocD~ z*BrlQ_}Ma%0XPW4JJ1$Cya)s_5HADm8Tmsbs&c>tr{X4S8Gse+j6^(!(~qW3>A94g zel$nFEYGhaAzY($DLBoC^87TMxAOdy{)LuAZcodN=+<#nl!V|*>GI(OQo4LN!Sehxy`l2_l&%jWdE}CYFL5#klr9aQ z(tW9M0VzL~KakR;{FMGz_09k3LqCj>9#YiwbE2t}Oj;AiMlC6ceW2MVB`VSp)F%xG zu2Nc$h%Op=k$T+ij=<>)jx&Z$t(yt4jn5fTZLR%>av#Wa3P6Df&( z;N<71j(8ycn{fns*QW#9-m3)s}`nmE`q+>YKj)cN636h)iUp{_T$IxGT?9|WC?69}9H)gNO z>lkXwWRQrJM8xWuPsb70K;}fMUtUx8`B(K*NOUC4|D+zdq{)%bSvH}l8}eT^N0;f7 zNJu}N;lV+^BAYwb@TX1v%HBi@=pG8_5{yPAkgAIZ_y=MV_x;FPL?)<^&woX2`3dUJ zpLmwJ5DgS+03D;ZMhHkQ9=$8D~kvgLzLM1MC9Rq)wHT> z%Kk{*l>HeQ3$Doih)ofq-y>jR=M&v?-|CF_VBC#yZvYz6EkCU#(LbL}?lqZ6C)_)J z`KC?up&0|?Fu};X9^~wDzx2Bvz&-B**ylu<)g&DUqM*M=v5vnZkC=VI4>%| zz&uRZS2>Kk=NXu=&nDh#-2x0O!u-B|^Y)7tdC2?a__@2hzsmBHI66i%9?l|Ok_Y5& zOJybUDvi9Wsq%>FM&xylvj~f)@^>1!N>h>iM4ll^2A*pT%)*FFO1?^ABrS2Eleps8 z_*QwOmVNV{jrg3Qhl0Fj^9Op-9`~SMdj@n8r!>AQu5_)j&8*8i!5O)k-TSEIs-A7Q=DxZ**ImNJ3>!Y6n)o&k9-Oc zGCiEgGt%cAZ0SkpphcKcH+k0>aeRL-@?hVgj+%~SJSs|Oh2i@ke8?ybpSq>tOWz}W z^86>^bNS~iVqOdRv6rS9GTu)FGnXG?n1~@roAdLS`SC~_GxCJT$aIm%T79O+P;KRe zwMc6TzNfeNy~nQ*`8E{w<}vK4;I3lOFzo)PZ{9?{bjVE7#nAWY z$JFGWW#uPvb7>%PbMlL*KVN#6l_7=Fa=3SpsQ}Mx{9h#T&qRE>Xxs3;zFsF}bOZ(| zo;>`#47YoBg#8UC+{t@BXblWfSvu2?)Okx!9`2<6>*C&XyrpL`>Si9w%$UA6q3`YJ z``4uIqTN&E|0wdsIfr@eg1c+8_~nYiiNJe|Y7>GCcX$@!`;MjYO`-A4r}6P2cM5%% zO5bg#??`)|L*E^y?=I1IHSn$g&-d^v!H=Yik+hhh{6q$;Jj%Bu` zQrdP(JBB{Bl$?uV2dBAe`^iC)8f&lRJQ#j-}+4G z;l-l9v){Qk(?b*O!C)ctn)}`>`qrN}pS@hDmeY^aJ9XGd(8XP-#^|WvE(YDHzJX^5 z+5=5IJ8Lo*=fjPDAp5P$exE$lZ4-Rsy14foCQ~2bCf~jZeQ!tKOY0-tN_bEFo8wOE zO^(4jX*i^=9ERHr@8j^^9QU=jlX^nx9|^C=FiX!%;8BD8ag=X5<#R^9t0O&0aNB|} z0B&J5MrRG>TTA&yp`Eir8n;nCW2BR$|0v}hkBUp6GkC|thB%$;k-`(gfwbaTl(w}=KJq#gSP zlDdl3EtO7BkTT_{~dMdj!|l%7KAPw0I(N2l|iGii8|X>v@T!zwPBvl-*? z!=cMEWIFC>#RKQXZuH6%KUu?h5x z@?&iLN0EhsUvQBz11U90`F#&iL?12HzthN*ad{_W0yptbvsd~ySk52!g7C^-4dEc; zw7=?K(U`I!9Y-~mjSSE7@e?;!1!P${`MEJA$sbZ>h^*w|#`KEDlqqzAWQK%Y`Y#`U zWB}?wRnGKnVOQlbrGrf7idacRn7RH7jJx_p8rwCqb@*k5!%5!%d-IeP z&qu;W3dxEeuBxmtl5aqEjWLFXW`eu+4bWb<<;u z$urmZk!P8s=*_4sWbI3K{xC|0PCr`-RkDY zw7G;PDos$QQH6?u-KWDd+Kp^?am!Bfc z2&Nh80za~se6q;rI11-ARN8j2L)FitjFqXhB32j)W?*gzwgCANO4_kKO)kXMos9Vn zrP$b>)zE*Q%qR^H08I&VPOuj^d?V%uO=3g~5L9A3!zA$;UVR_`h9_EqAe9;5gV!i}ia)GTFxJdhvT@>+Yrp4BYBjCV7_Yhh9)UAE zC4638dwJh?Gj?>V;pZ}9j@p!ob_eE(isJW7&?sJHVme^B=Tz^jLl&I#-EJ_dcTUaq zvtQrR9ev8E&B2Eko!eb*mezK+Mff4D8?GU$eHxb3Pu{<;NxX+6C`*3R)?_$~XJ_gZ4xWZ(b^Sb)z=vZf1P}I)2~`zBz6Cv#B2%P$bVsy zuTM|`HdlHdluVFS!EyscEsN!5TsYE?o&#Yt0E46a{6mM3eiS=c0fp_b5$UD-HY7=5 z(2HU(>Anr>=CD_u{$~S`|I64b%`cihnP!ZoD8k+X3Z`z z{VT%WU@ju=P6gnwhm%JU_Hx+sSFv}od}n}0C?^j3mp_j62&*M6sK1K6OKJSZG(v*A zq>ss^|7YX1EL#4SL>QS%UVic!VldA^?@#x0G;j77_H&TRM=ue3mtZgKb7nljS$)>9 z%NK&Rq#b&YOzHI?%~8@Khs+KF8rXo<2L{S)C`!J^_3UXge~0ZClZNXWZj( zN1q@Q=Zj?ugiHp(a*|Khz<={EqU_fQGC=DTqwEzF!}prnm~Z`%u~aAW z<~azg5srHxBUC4MrHKMBV845uz0jJxC+T)Up5&2d&>tah$lV3$7CSK)Ng7#t49{yO zc-FR6wHELis*}9WV+8IG*m4oLcZ5Ai;?4zqD9URsqw3xn`N-ahy-B#&&fvUAL?hge*Yx#UEn~*KFEBglZj@X6lZOmLGwjoP# zZl2_Hn&CIq$YID4BL`#5QTWa$_wM<=tH~Yn6x)p)QV9JLxr2V6+(9ofav(Op z1;vBOnQIpV_K(cxbI-<@3!%@jtC^`ppW{{p=X3mVB0(ni3_G`(4B-K<3!{7r{n1k? z$b%o`#5~Fn%$2ZmVlIW16Z0pmoMb+Q$cZ@=R!+>HuySG!h45qjkL51_KjFKFupS{S z6Qt!H{1#AuYvC?{-$!Kb1vWp4z0dOJ10HARV#wMsu{%xf$8hK4o=5Mb4`0zU;pONI z^+(PR-A~F}ASrKOly}_#krgQ)k_USOR5H+vEhOc{)q_zu?~l}jg?!$rU3}$JPcVKU z^&uU1@FwDy#GpR-p*|STG)`bpAL@on!YshqgL}gzVUqem!sY4+7hddFNj-@DDyau4 za7Rrwau|KY$YJ4EpZuupMhYY{e0>&O{^Q5nHm}VsxCG=mi{OE*pj&(c_d|l4b8!i^Iux* zs~_ovT$R2w>1)XLr7ful^(mcmyHUCorH`b23GNIjtPMy&pX+-6*?gDmOh3XS*EJfR ze4qRlrOWrdYtp_5nJ1H-M&GZ9PWw*s^J-5hor{<23q7ZFE?$nVO|x7+od49Zfc&Bc zO}3;^@ULhrP)gT^awsS1j*%+Dj{^GFFvF z2Z$?wDH;oOqw@dNvB1PireD!mAd6=7UmXj?()hWxo2t&kWzq5{`6GMDmmivifFS>t z_S|6LXZrzdTQqN3)%}36^qVJgh*)7Hd%Mdf?3L-8DY1RCcfeuNH+xUcdBr*2rRbA= zL_e(+L(aS9CGEtx0ed)F9OBn5N)a;NXlGjZ@~nQX4#R5l?`vToJ6W5?FUmL4Htev#qEa2U6=v1@|msg^dj zwpPSpV@p=6TH4~rmQ%%lqz?U)So`PmSrvbn6=5)GJ7lqQB(3}=pjWh}L@-kFF|Z&> z5R!Fr3*77^6}Lu?FnsYN7r`3RzH-+?`XEoQItKl_Yd~Cnap{t8dlg|1IymgbtpSmy zkYs&jv1cnSCrK#Z|K-Vwu&1*AIqc!&FDMOIo~#Hvn$i3da{?*w zPr{?!uX3CPG@@ckC3TbJy?p)?x=hndxf$jH4V0|0%3kvF<8ukG8g?|ZuPS!<$_OZ8 zh2gLxOCffApxEIE%=kP?8RxtUG6`;w@&0sek=4FjUef+FjP)>wvNnz9cu$~gU4XTd z1{jZ~t>-zW3RE*1V2n-1q^VnY?4E(N4Lrv+JMeA~aZC0Nr0(N6rX1oq9>O{HCRnej zg}nx;g3cL!7#I0sTx5#y{4w4&rD6GDj70Vy_+$L!SHT_wGRFNlyi>;KQ7##8Y5Og) zVSj>czjyMP7WaT_1sK~QD;8b_CZ)6yeM~_bNVutxos%sEa;J0|#tH_N%s)`M3&HDq?GL5IbP$8#6s++x#+`d(yhU5)4v)nr~^8~E7 zX9f>v3*MdayMckC3OTaT@2{k?@J1OoY$*A^aqc^@t-KaS&c2 z8{s{TbqvB!wF9!J=zY`i>a*{w!Cq(WxQ z*K4dsoF?E|kG&MoAG^f)BQmXqd^qbynr2dltC7FXSid4NkbM`cvG2m!`0#Snk)%R~ zpZP!kjE=zIVovteufPGfPpnr$|SYj z3wdf9q;2g2EMnUro|-rq_0$*Zg~w4hIzXSMO5p&{q~V~h8$*}oIO<6U=!{e;9HC4& zIQy#r^JvFWXF6zCF&s^qaB!wr3f8@jqy7*Kt&%+2GU4EiF<&KwgSyl~zl!11lnDoC zloBGv-zYX9fAR+@Kox|^I zQDl!kyJ$-8+*%KLCYO)o#&Byr)cL21CjXcBcS-YsCZy71CpyX4jQS%^(w*nBl^au8 zP`b?23F~78$H=z^Atq0e0I;`~eIcfY@qPrsryopdVy&&FQpr*p&X z?~&l?Y9-UJXza!55&hLQooh6HARX0wX^p}MikI_D}{dDZ1&OkqXR*n%cwxPpJ z^dUHZu<%uZ0Xt2zEb)@C^O5EQIU-Ug8d?`ei^d-+w*Qe?tf6U_n72W zMHnKXb6*H?eZMN&N1=uAofv^KzfxZy^h-5%&aQMimknpfkQnQ07 zUFoi6@+_k$M8zanCM!MH))6d|rB{7zh|?32+-*ihMcUff{?n%D7-OW1G+*+oa3avi zrAc1OTwHoNlA<*uH`<HekE5f$Q`d5T)-DyOYT*UOw z$sioZOsKUVcSwRyt)Aa~|nk-am0y)MiCf{$hG3b&%w}eEt)< zOm~@bGfXgz$W%&^Jjll%QchdL_@`?r_V&%Iyq1zE13V&D49QxGGV~BE$)2m2?)jau zj{Sh_v5!$n7T7R51KZ-fdQr#IaiUJAE!K#vtaz#k4PiG1`WgwYc=te{%JMd7!tC^i z+ZnvhBInbV+M?`u%)uXLc}RGw$fP15cjF^|W2M?!pL9 zk@Q_Aa8ZFw2vc)`QDys@BM}S3nSuI7P?CA(^9V@G(oN~>}%V5=s4_p2! zJe5-?CbiA=)d_ z7Fq8XWp_k75P&)u!1AfHd=}s%^?WV(NIPJWLu6Gx6-WHyJ0WerS`s$mCT&4Lj8d|o zhNOL+hPERBKeMB-zX$#q2;1xgDP!dXvomDhtCF=z3_qEt%j`78duNdo+r|?8vO*Fk z?!+Ht%3O_gM^3-Y4D&5mV|B+j?w*ACZBw`*hdaI<_oZ-Kz>T>PcYIIozr)=SZhTYj zm|t;EgInSsdS#5j9k$M7{42Zfkn*d6U)eniZgcpDE}uKn>3&e^UxoF5Ta<`oAyd|EZK;75vKXFX5KRuMBzA+}}$5OXM$;`X}jE zc2~kYzl2{RzZ%@K@>hpjl75N&`fy9~Pa?mOlwTsh8Qik+TTA^*B(x1H+CO{MyC^T{20RI91J z+!3ljcZu9VzYm?e5+jEzNHeDg7jP^3yAGY`yAGYdFJG!d$MMENXO4TGCX(pS`T8<{ zu0Mx;fJ0b)IOy+TuOO>G$LhsF9#$_7bnG8w_2*c9IMAU_MfB?mD1QOvFQEJdl>fU9 z9rU#-sXs^b<}m*%)rmU}H_@Y0lA*~y%knbdA^z=AF1t|fM2D_7)uF=xzMKwSKaHGz z`uJ5wm(ER9qDv>l9o^AH{Qgvzj_A;l@F$S)sa{>hI(5if)D2dr4t0aou_JW@dT_p^ zZa@c)=+#Md>Lm4p=-6>ObtjQlSv@*g{W_w1NA%}Lql}2ooJ7CwyB?jaejTg72Obg8 zl>X-ALoxH^S3|JiI0lrgC+DI=PKlN12}yt&UOXo-pUQ!B!e(+ zGB_k~h@W(eC+m>YnG2+YK>4-IU`m%?%jDL!$i7fA_sLxzk_=+^i^|e{s6(DVj?%e! zxv}U>O6TI`=vfNF`Rnu1|L$B$x@6Ld%RbcI@|U8yl;~;_z8uOS^;nK(5%_Scu=ak;%=Q0${#W>LU zhn`ZOk_UPJ#4Vq8!f8q4H>Ms)wI)CL@+0NSebRW8UT(Dff2Q+*WZjp)ni7a6ND-riDu zIoKTlW^+1o?6bVy9ILP3lTY*+h+cujZlYU$3a2**9O9u*;s=~!-?KUmu&;=I2hp3$ zsijzN?iTRt-;@QlNKSuFzi0~d=QtgV^7(3Frx_CMLxx>Ja zSo|6Q2hyO2M)c)~?i|sfGa))@&_5#>!RpnqdT4kDJv5>>$KZVmbm)H2p9Ag?o4cm) z=MU^5`g0OJI=6gTy!oz2C&3)9?XI%^9IN98T|ZWj4)U>jbdZhHpM$I<-c%X+S$#Ul z{@`hx`#CnqT2%k}ny+n3hbr&kOsrs>A-{)H-o82yw$;fTFBvbS z!p1tWw@&P=BjY7D))kEzI2-GKGG>sovCeeqoA|6XV?6z6UZ^uBc5X{W{q_l_(a;6~Z19P;L&5 z+fgZL<^%jI9xITV@Z;u6GRMXB$w&lT8!ErIl2tCidx9Bsm@kp1%KL==Z|=E_lcYxa z&*cM0P&DVo^;6v_BbhHDb)L)9pUrt4NI7kU%3zsem2FJ< z%2aw0D~kww0#%q4*yOk`V63sedC7!HDKVz&S`9RhEDwm|C#NyYt`uJBZbl?ZLIc9; zEtoKZ(9QWoDn2B5775ACFc}EKhK}x zTa#x#bnIBV66l(gj%U6$r3*oaz8cGqXFl}KSbj~=4JaMYd}B)22HlL(@yxfR^qQbI zrgS{>n^C$x==PM3XTAfa8!*{STahClavH}nNv3d{%@kP~G0H_9V^qBY%#^H&ja5{w z>;{^m>>$vNnDJTLv3$sHioIK|pyiqgBz%y)0rqN@C6}kmG~APEh+I zd1GbpiCa2ObYQ+LH={+7UnS6SAnx1 z3m|)rP?TLDVB8t_FM!-RN-}Q9oP)HDBfOCHE+Z_u2RTyWL{{XC$JAKHDkaXxDm7N$ zipZAd%UsMsx(kqoLSNJoq_+UFJS27DU$v=K(N|5{iXU4GNgF5sWlHc6XBtSq-T~4l z5{{yEHkpr&@)MmTGFQm?=k~K(Q~G5Z#cVEo+9*h-3d4xv#1Mw<1dJLI#dQMMv#F#+ z*#oQoY`FKsi7Nl(EFi&Fk~I0=mx!j*SFVWUbIyeNmoG82TNPg4OG@&(A#S9-{;U28 zHj^;rv5kxWXV^xLu$Pw!B<5TttjT=6qI=|gQOLds zHkM`i$vzLlk3AeLKlW^79pcwu`M=vcJj&Y3nmMe4S-voBy3KEOYIGVkQef(!w&sHE zDyyZRY=pByJ)b`|v2+<*_ceMj{7A%VXZH7 zr(ZJ;2?+7*6Os1SXU(K`3*OF)T2#$v_uNRIvk4I|#d=fgukoI+t8c#}j#rwksNq{; z-C*m*W5v^bE%nDaoqFYPGi&RuadWlwTl*$xtqg7do8i{OWA*-M=x%%9M$;|Pz5{%F zy)p0gc;SX#nf^=N`iN>i2^i*hs@HDq4c7Jp&g?w*#7SpMym#t?r;#x_HDB(q-X9(? z@K{Ep_qO^`wb~CjXSiTSa`U}cw+uLM7CObtZv5EzMV3q5=C#?9?LNHTlS4-rm{Q9GqveJoM>%zZIH8i)ZF(7(w4|$zBhPTDBecw|-GqpNStrP!p_Rdw|F1c&tCLSD=(B|6c z@Pbjsho`UVR9Cca*x}y(nfab7V>`5ry!*9YJASgW*&i2Lx#_B3$bVM-W^&H!E+-?s zR43G17JF^nW%Cbrp1iNy{p*7^9^-Z&C63ms zr+U;07stUGmu`N}&pwbdu9v!F8S6Ykb&75gaTrDwW(57w% zx$}aPUZ20X>2UfEebc5*$JW+5__fLCXQ@W~gz9Hf9zBT)-*xrPM*U^?XPqnPmcDaO zL5;F0ZH~rVPv3MYX!YP)%3~MB)*N+a!PuI0O@iuAdapD|6l5zOyKFmwr zKW2?@BPQzclwIL_g+@>7^%?$raf#mbYSt!00(S5Im|bY2Z2v8=_w-`}n{4$;owq7u zS?9gNVXD)^o{k*v-pOjmE*rJcHyc>gIl6US*rthh*LTVCeYqlN`-^!IvooK6tGzrV zv}a)Ndn>mcS<7!($I3%(w5Uekl=iLlA1+_&-C@Y@&i$`GoHzVxhY!nCS6oVc*X+rw z#|}-p9v*039B+Kv!=h+pT;9{E0fWvM@;eLZ~L11OWLN695y_z#pK}l`zbw@ zy;kgLrP@8yAWpUYfX#O%KkqbgZdOUHKCN!F-datwd$E#{LGia848QI>&CT1RcD3~x zKh6AriQ27?HIgpAZ<-M^s<1l63w4=Jg?Pt?t7JT7L5S>)Dn zy|>KTvfpUz@;lnX1=n>qC+x84aQ>E2q;4;>h~YMmZ`bWU<80h2{mwq)Yu^w??O(oX z|LlqGPg_49|NK+^={JKqss&ui4LsUe-{6(-x}IIDHXU!*+Iz&TW7kyO9!G~*^O=R+ zZ$E5ZV`b^xh+dwy+E>SJoRVBeXYlLZEtG~IPy3^dzD`@UwPt-^Jf2tb>GSI)jSuZz z8P-rS?y!ZPXzUhKIvgI zY=`!Wy;^#C(a-KL^lJNM?b{~mhU+~)l(cJ9zh!j`$2z{_j?@vZZ_snMZjBFNUpEy6 z8Rb4(AtVu5W9ZCq8&S}+g^FP()L4^ zNlqON@8o4EgJ(=y_F+-_#CHD6XSOOG+vLHL!3$pKOwkRlWi_*f)>Wg&$5Zd#S-fno zPxRWjcYOjPP3wKjotC`V^+??!^&Mxuo7s3hbh|#!(suudS0zP0&%Wi^`@OLII;w5V z%j-4810U=Od{T3uwsS#^_Qt#KzjS%FAu~;{TjbL1OMA_u5 z)5>v%*N%6c9zU$J`@`=3Q`(iJ`k!~TnA1OH+RQI$yN@5vHPf3sKk9Ud#&2<*r*EI% zn>o~9?RU32o1(V)*JQM&Hn5)K?DOnhFU|IEH`VtW*`dMw;>hMslNQW*{e1A%n{7-( z`?k6h;~Vwz^!k$NqAK2xn633RmPd-H}5U$Ew*0w z(cHF!!KAl?Vr;Dv`AM_{vVovgvd58Cx1h&v|vX7o%?z_U;H|C?}H5h(xe*5PB8fI-wvk$)1TD^VxvTA!D&(@5*WBFlq6PIY+3uO!U zEbW;fKUQ`eHylO(wiitPR zX`D|=NgJeheP+`d`^+}=?{R3{!U;uJ+l<*^n?}R( z&UlR0HF#|k-O5>aSYeO(dmisgRp}n^*DgPU&1bVBYRz?!EhcYdLp{uc50R z_FVJ2^|K9EJcn)x9Go71W9HLC2fyY%4D1uT|M&Qu55=VuqJ6vi3VdCsm0jFw;-MeenYE&&TJbFHi5gvwMGH>clTaW9s)kr}j`ed?qi(y`6fbqgl-Sn8A?`;z1uf zn3VAHUD7p z{$;<<)w!ZKs`{Zx22HL`ILaI!UT^jum&8<)gWJNk?+j}>tmy`~KI6g`?!Po9E$_sU zE<;|HR`;5CXO3%q^-)*yx?b?OxzEw6yX)SJCl-q~Dm@r+4ttv1UGLGntNjD_eq3!~d9QWr_3?``+@JdQ zdX@jG>G2yMdVUBASL)DL{nJ>zjEAwj_^mTGJyuIz@Th&8er1VIm;7PB^7@|Q#yt`m z@mp`avUuXUiM*@r&tJ4`GBM`7`6{F2tddQUJFoWhcsH|O#73)v$7|~plx^JFIr-Cq z7jus0KRMHa>ig$J1+_JE|-hA}CvR>P!+V>XhYrFS1 zov}SEORuXR8QSB_hQaeUo#|2gN!PiznmPFU{N5_*qw#_xiQ}K0o6!Dq;5m~Xb_ctS zo%CRLx@$YD+z_ujZn2MR1ZoR6uQuC0;&xe+=^;TTs%q-4%Xi$)aS1$sC)8*231frX z9}e~x&GD%>nRn^Tz6U#pPa3xRw#&D^tvji=Xn*DG&i(1!veRaq)-DPiZPw&@T)b%SvW_xg2tr41t+Zu8aiyVYSqVWV-a_Z={IvA^dy zGsS(}xgL8?+BH47*C=Ju34?<77mx4H)#05#p7|uT%Z$Xj%MWzBeEQCf3l2BbuUO|g z3Wl~!%8Rl6IHy~qZ3TP!uKdt?-@A_A>Rc&V;c~rUW78#vtiL?gi};dM-CS>BvfqM7 zpNdxOKG!!e{m8}iy}E-`5AW6-ru<+?_e=qfV zx;sC=ppkt_zF|qkET<^-db91*+>Ij+9=m2YCU?%N7I$r$E=%qluJO43>j%}nZ+JXP zx^~0x{5bz};gi~*4cew(OSyjIvSXL##Vs@a{Jzhd2Jae-v0G=`B7Fh>?3v#FQ;Ik4 zDjMByNy}PcXGUF`Ip2TroeN#Er_@XA?oqRMUc`apd5_g=j<-{}aL;A=gp%AcugsH7 z^>qLHhs^iAzjUC5a)@q(DPL)O%=y#18?6{~HmALgSN;Q0E#Cth9Evw}HeX@vuy@Qk z*AK^1w~Y1m9c}FS_4M>>bDsRR^<(DvNtqu#1{`s#GyAvC{D;GGc^~f;T@5L{oS1TF zz`7>pY8_TR79O$l^W4+_{@8O5?#}D;I5M~OzdOe(KeLBf6I=o;R>)s}zK7?>xm+za zfFJ2(PL3xt_vVj7ceSnc*iBBugWIjTF!sZjy~#IfgqV zEF_9?c9mM+88Ku;z{qig@_m0PS+^z^StpjApEYKw%n$bDEGeC=6LV|bgp?ygmt8+D zRzUx=$?5;gcImkCp~?E8hACP{_N^iD!R-qm^Q@$(<>y*0C|$lr`_g(L3FZ60JXz5? za%KJ7()i`)i#h+Y^_)n-$*MO9e`wxsdPpBW=BKR(-Xo0@($S8m&?>beu$ygkVm5&6Ua z&-OHtwOu9bYa)A^;_zD|P_{}*W0KOac8mbX8A92O#Z_y`T$` z?FW55vR{>bPjn&3d!h@0_e2*$ZeP>F=U6v%4h+|mB8-vH<-b%yCH%17Dt8gwk;NpgohNM@p>ysy z>dzYYim-~TdsRdifiAoEsR`WdMJqoCVE`&_>l48&nT<~}5Qay(=t+R>N8@q`xUzeo z9H-*F=U-a?s34sDoLn5H*>MDVFQfNzbpkX_e(vr@Y0W4Q9<)YHXV{D>x);eelpM*wD~88KdGw=pmrN zEk0>5DZh*4Spzmg#Fp59^Aus6!1H5-LwNHL771e=&U(&67*A!wfLr{OhC$xJ&WG3% zdvu5#L>?jw34_Q}B{{Hf=Wok_{XTzN4(x~e+j3z4)ZdoF_!r1w_6y{&`~`9}{snS0 z`vr2?S1bqlR!Ci~)c4}>3*=~9u^d(UUPKZ(*zd0s>h zhxmTuK*u+kAAob*osnMbofMPvQY;u1u~463_s>}h-Tt|D25J7=-xc!yZ+};)1Aki% z)WyFo2fm5FEeF2Mzbyyah`%id+N!@T2inZPEeG1}zbywahDbS=|%B z{sQI}Qfqg$@`Jr0W6UiOyF|vAJMf)P?m{otW)-0myF`S3iQGZIUxCdk>_O)j4|c#{ z{$hZLZ_Pc!W|g%PrE_+wV6)1adxp&_YXZg)6t9nwKRXy`C zm%@kbGHSD`C+t*7X|m7Q>nNo&crItN3hAxTW)i_*YGti~0?iBre?8Ns_t|J4sSEVkgnMLFlAzfG)LJMc$!) zz-E;-wOM7&+N=Vd*rW1ASrC5ic^AU?!Df{VFNu@mT?k%c*Ge>5Ql_HG+FqngMU#bI zq)Zt?N0~C9OKnz>cc=$4Hmj^Z32IuuLb?5?+N}Dub6P*nQIR29MRQ%+pv%r(1=Gn4 zZtjY6b9XW~LHIAwLH|~6@|X@fW#*!|MU(O~PI5M_+LDQVT=MHFB1-3MOG&u!l~FpG zbCTqlEulgWhBKx<{!9x`q>;-j$FJn7&Z*T5%Kx)DC})H!KQBWfDywAr70p34qk{j{bs0`s)qx5}J{$6rFF#VQ+^3C4>BZU9 zB6HQUmwZ~$9F#L^_0x5kf77N_0554L`ip;R)2cs{?W-cnChIvVgBj?7)y+iu7pC<8 zlXaZIKVQe0@>gtH{eP4NGnxOjHmxL|qI}Jj)ar_`lDw&CeTjUMvKSgmgER)6;Oh^U z^y6UB68Ok|D$-pBAaK~pdJU!l5DcU6$5Q@h(@K&tTpLZ=Fp~B1ZJDC=l$?r-{)cv3 zAr@8AKZiw}oD!+A2ZZ|n8J7IF+q7!LWeB~?XDdFJaz?FwjwQd+rd2kp4@dOih&@DN z7g5%h)fBApe}WG88!ui4v1P^CF=>D?YT7i|t-_c#bso<#Z3cN3dZh}gS&=n;f;Vpj zN|~QWDQD~>W8(!pM`Gugtn=5xSTZdEcCVJeMilXr4BJ+#bULXGcE1`-wFivSd6=>!sw(7haMf$LBdT%x`>>q zNE4ASC0vx93VDf)?0ckzeJ>;be~V44e+n}=+fBy!1{7h2j8Q8W@2FWfu%e!8M@%KvOyaXD80F5k8)8fS2O6~yJebJa>p zCE-=H*8Qt&TKxEjaxF_9W0rMP~6Fx3A|V)d)*9CHpX9xtLKTbQRfrWmx!|03Is`q+iH8Qnh5io$?%dad{wMd6GYjYTlKc;++N$u$(U!odX*?UkKtMK+G%^GFA%}Lgtqm;&N!C@ zZcAUGb!xIGdt=i+Rsaxd!jJMx6!Li1CZ>kgh4ANRqG@dfH*zL1fDwI!PWDF={GhA- zaqR|`jA1@uS&e-{vl4uUXNh^5Vh^7YSqVH1u^7MMJ|nRXuOW8jsff=Ti00?V_~c)1 z>z03IK==Gc(cxL*=uugr(WBu{L!1yDCH2?HXA;&lHN>5Hs^Vh!`vgDl;pYSVyGM`A z8Wue!Yi{)TtR~T8v(E9<#bTextPKcb6HiNgin#II1!ti<;%sz>f!*`lPV~vQZs(St z937qI9z86}E;P>f-r65m`MTgAlYx#Noyhimeex55A7LC-}7x z2I05m>x%8b*M?tDoP;p)7+vvjo{o3~ubS9BIxK6SJ!3Tj@!$-2@d%``E591vR})u* z9CM;au=EYE5269tnt*>kcoL$Av-Bp&kJ;c2MLudkULuP--pwX?iFX@eOT-G#p-6WE zWE@WN8+k$UeHhYB(rk-xNm`pgUXu1@NUta2wT_O+BJq>_%0qdCK}H|^Yy?{3b8uG^ zR1@dJ?;r4&2mkJfFEKhOt1;qoMHyW|SVS(Idn=xSav|lW$=76`JrMR=QcftJSG24g z1&|5(WPv;sBm8*CN%B-o${lVoo_!FXE8_D&*gX+vFyeCsKh9JVUuWuwEuurS90kO0 zXjV3Cql}A=%(8$xkEteZ0@=rbmpre7otGfUpv|uX`lu``ULEAQ3jB{j9%-}BBn=y2 zr=}5PB6TtW=_2Ja2jLL+aL82+ZcD_Gfqd+WI0=0n?AL69teZgF0C~4V-ffU|KV-H* z*?53I8F9~M;|oWrYxFGf9_g><>%Cx)D2(7M3i(CCmX zoNFxZ3^`}vd4fO{&oNmynR;SZ`1eGdL@o>D`vl~xE8-*1WUtIDr0Xf}eiPJX zzeCct*-X^;YE+-meFl0r@HT;5jUm@(v^iTKhnTcIyt?AdW=!^P2wz_S|B&ew_@4>1 ztg8#Ei@)#;#Nnh|@g0kK)$u$kt2xs9idO@EtBYR=s#z~U-EE4W7_|NADpt<~n$|mz zH=LiQ$hUBQb;_?{J&)zBF3xPrWM{S#eLTdd7a0o}@6o41blPJD4TGZ9W%HD2RKZRhK&x`@Nmc3 zM@GP~Zn&>S_))kM)U4L5*8MNvZtpvAqiFr2*uWNhN@tC&r+fG@Q_D8o{>J-1^hTU3Xyf%(5pP!)sr5{TyMMsOxZf z`NDIXLON&pU+cfP*M&Dzhc5XXGLIed|;=6@yixm zN$?eD8Hc_fe9JM7(HK~=C1A7N)r3i!v$aQd>7Kt&>F!c1>$jRqlirR<_PRZ3rQ7r* z71c?neQaJuwb}NqY0opl&X>+MoMh17q-f3kORw8HjNe&De@r)LN8jl!3h&hZ{c($; zh7;azIhpltZ_BeokE(6co^^P_q5Ahq>z-8+=8cT-Za%0Kfllw~JAw0*qy`TP;Qp|^{s*3!HC(m8#n@7}V}6B1un7d$XtdE}Z|o1u>P zvO27L<=t#XM4R&^yPX5=R-IX+cUsA%?$$XIAHIH6PaJpaZsFdMH%>dNZ=QH|eE%nX z-uLTpWp>x|#+H}YoLkfE;<(R6@%FdQ<~R3hGkxr?FRxlf&rmt`ct`A`w^_lSlXjdq zwt8i3wV0xLjtje4*U(zDr=!8dmrW1UXlc6ol*;W!3+}d>HP!5BZqb{Kd*18yxgBl) zD%@{q$-~obhX+mRnYf|4)1V<{zwKNz`G(Cy(S#>)DRZCRdpgVKOJe@3{`so67xs3$ zx&6@}4m@6DpZ#~VM%Azl?B8ut(!#w>+jgI-8y+aW)L`_Y#bXQRjX(U+#H9cD#aS~h zc5Q88byu^;-c>Pgr@RQz*)*i@glA!qOx^j-L^@+f++h4}Yl;P~Mw_qM}y*n@X<+Ew4x6fJmF5y`nQNi?~?;17#cBo0vg5G)O!za(N);*cLAyw#m z$LNNoapC@k{90ClU76fZ`co5Lch@<+z43rTyX_^5TDsp+ow5D>{=q3vr#PL}H0gft zz-!O@Q*wj1%_@9Yc5Ump0UgT{40+wVbam=@(4qdzwn-gUte<}{Xo>Lcrk8uqAB@+n zbNbnC=7_Jw!vjM`k2f+4%(&$?HE7e0+<4y_mg#q|X_Od@XmN1XSnYF9x9^yj$yYXP zk)vV#Zg{P!-*k&~LfjtI8r?PjTk8p)^@esF+^XRHifJ3CbU7E~+z6@2w;?jKdl(nHWT zN^``G&|{h7Hr;#JmVctSN540vOINM2sAbjY+RFz`9qKR7?xq>t$8O(*>v`=n){PAt zkTB%*@n$_QCx|XK+S5MAH+qgr_FL~(X%kO0d&{q}{)FA^5!nX|FBdiWJ>j6r=W*kN zUZ#a(&yP-6Gv}3#&xvUT;nBnAtg9W+FXh94PtBPd1GgTUTcVwt{Vw*%vy|~;vV~hO zT~Dj+oIh?(L|y){=6TC~%XAt(=pNfKUARo;=!?niUNssqbxd55r}_CgZb4U0wsi6= zv^=HmcjSCVmv(ovAMAZRXYlU8Et}^*zH+>^nsWNeiM&Q7BRkYylUvL1_QyX8^k!sj z>wcx%szy`y_Vf22#~ZeyUXD%1Z*F>`!dibc?x!p=U4Ci7@DZ@pD} zbIE0&&kI+t^yq!QXVBMaOQ$FwwaN8z9Agu5l_xx$lCM>(Fm>JCl84hTwGUb9nizFk ztC2_VF{8UhH+LM^t$|(YKm)sW3-7(lv8+73Frw&@1K8$(0 zAjm5GoKd@jE{1vb8+PUI`Pk?~j=fU7p}QhI+ojF##am#yYjXOf^F#M+_8sm}Q@>sA z{$>+%QXEQDYLzAT2*^#$|J~|uVA5jctm2_Z|;kJpZDqgz0i$~hq|SC#7u5}zfgE{(aw&+ zy!``SJm2Wm%g$GA)u9*nQ}6!Xr+8X+{EL9Bb-U|29vpPX?!&w{4%=qU^6T=t`GHn- za&F|Qyqh%0|KYM{!nC#z8hD=hv&sX!!iMFqzZS3k?xlr?Y_4AihPko3qPQNgzj#Jszb;=8F zJQ)7uZ2rNhwriWTa_cnNLv(r9ja;q&$KH2I${Sa(gZ7FFJnc;-h1JHS8|RMbLAVIJNLW)o$uy( zAjv+vti8&+);Za0?>)oU)pizLe7t96=E=+60eXWw36{6*`5Fw z^8SFsx_2-C{M>QQZ@zt!=A3zYGax2w(2`Z6qWd@N%-rH@Z5}&6Bj7;u1qV%AwZ7%! zR#VgY{?8-w%AZ_3p8WRL;bzgR*GTiUmruQ>wSM8+WBn%gUc0@XnO*9Tp95#bgpHJJ zJJBjWC!lMKnV)CfIcT|W)_@%co0y&S8o9}G#)1tS243DDaQDN=yHTG8-wScvpnIrM z^SSrxt}3rGCffVs6j9OAgJpA41%|7}PB=X+$Ew$*&PyAV&pd9u=+Vk%pAI&U${Ow= z?7t+z(yVn+e(`~BhZ<+h8PK_)->dEibj)rZ9FbDGsQ2McIeE`5mi9g6nmVn@@rs5c zCOw^XWxeJhkI{DK^GB%x2A=7f!9QWlW=%Wuq;JcwN|VZ>Cz!7xkVD zXytTs#=3E@(_aL5wHOm(ut+>-$T$zJGw*l#y|d|Q?)av~j1eDvb55+8lF_(E`1+sJ zkM{jsrC_7h`Hyz_rrLX-UYi+p;Aa13o#(k18+neMQ=-vm`q^wRmxaPB%jRhpCER^9 zWpuNj^E8-?YnNKuL)R9)sCq7v&5Ru=5T)wClsB+&1He8=WSI$VAXdebbuw|Fhs$EvrGjf^R0&#ODRN#Cu`4V<{Vd*_IK@9w%> zYIV9-ZhY#?K#i``wjP-5*t4j{{zn@N7EjxGxYwR7S6}aHwY)b*U1{v<5AF0y$crCUHb68QO^aEXS+WM z-p`pUdi8qO&npl5w%&NFugtNY#+|MgZlpf*9d`P`BllMpj`uS6&)a+8sNo)9xG>AAVZX z%R4{%(5qw8n$w-U)@Rl@YCQW+#nlX7fsR-IjBV9~AFD61y!oWWWzG(1rw_a4T6{Ly zGe>RN1{a}D*E&ZB&f9bMWtT|HTIq|v!qkw+k-+_&M7sGxtsDwy&Av3rlp47bI0l3)eZ!k z6{otMi%v7TR@!^#n4G1iVGnPco+)qhAz=HX%|*r2)?3FcUDTGnYtU!uX{XP+6`l0% zYguS+?QEAZZb)`#jYWr($E;hQS+T0?lialBw;MLzwKl|c=$!^^;I%>81y%QT{q0&; z&8w21N7qjoJ9A4dla#|v!xp}s8GTPs5!}sc&;H(#v@IV&Aqz4ZMp5(Fen_KE1H2a`%zzg81BY;jWg0Lu&4N<#%gPhv$b{ z9GQDrV}wyk+_TRuCnkP4^XBfk;wc{vU;7whe|6@oU6))W4;Kw8v#K51ZFj+wz}LHb z%qbBB&i9&jbk8CEt`)bv?M1uFOLq3|)#Ut)8zY8pJTa)1+3^>R3g1l^t?1D1Xqdhr zTqG{9mv(i?>{H{rzkcyLPwjo)rKwWCv)hk$6fLN=r|S94vr*f1^geXC*zMB!t7UsF zT)OEVS$L{zcl{B!Z(KjHGd_5wg-(wgpEnEVCN{hk+;!5*XtgVOHO7Z&oF5h*y1iqv z`|77V2F(h6mb2yT)FH3!?s<1^xx#*^<1X9L)1#+L-==u0{rYrV$MV*qpG{n?H5Yoh zXZem8Z6MJ;RM@|G_RHl7Q$_}NHkxBNzR8V7b+E`Qx~Xo#PLx znJ0A{`!d5O)3d+8TD#GkS59qPG+3`UOSZ*7=kD1-V??d58FbNDwEldrx|`3|e?6h> zb$EQtSn4iE5dBuyN*4ex$@c11FyfU=bio7SWD16>xli{8lTO| z*whauvK)m!|*eA?>!L1o z-IF$lx(T~XKUG!jeZ@rUsUf@c@2qm{uPuJ|V1nB(8lSfAUK|?IAoRsGS$&KC)2dq^ z&r0hoWp2e{vphX}-P4~sw@lBu$QswHF{!#m9m9@~2X{H5@0(mP>U00vjr)gc)cO3` zNbiWKuEv|qnCd&+{nfb_;ny~LTfI7*`s<;jW-S&>ZSNN>9)J3V(=J2x zs(z7sw^e=H#P9mXtK;W9jH$o4yXWA}H&|e^;&~3@Axrnx6Qv9DDm088JKpNkc3R<} zqO}{2_3nFrNQGxJ$uv~D-T%PL~l`Pqlc#*dkNU2~_UPU9D9v$ZG0?7d%R-nyE#)8?x~Y91L=V?f;* z*LF)yOy8}jlRl|sbyhU1zEE9is9jptbN|_Hr*54cSKe8=I>qj4`J}Gv%I>p=xwrM! z?%mO`Vt=>0n}#&|%`vmq!-nSFH8YF0EKSKP>Shu%a9Hi&>ixzZojyV>N9(}&u1#|v zzHC3Uaq+?4maQL_?5-2N+oJXGIZr|ki$A6h%8RykTCUObgwCwM;*7)RS3PX{zK*ch zfSUDelLdnVCyrhAX8aikhfJ%K%Oj7q@SLrC*lXyWixYa??)JcUs9METH~$^u=Gmo3 zzpHZV_?UzT!b^{Y2R78Y_R`q)muX{m?|5UgQQR@_$>d?$O#;(gYB{Fvy8YUSkXt%L-^em;TFnbZ&y9s^f2zYaTGgmx+Q%W}VWdvKPoMXAUldI+ zPS{^%&bkOg2fff`?amvtJGSfek+X?;zv|r(*uSZm6&b$j=KWD4Ui{p^?$ptfwc@WH z8g@Wy(}h*;N4x1So1K^FEI49Uu=TjZfgPIGQ5SBmSzWE^?I|O7P5sn^-K$@cTd~=q zK!54Wf(*mOizd}$rFU<~z8<~A;3xZFX1b_xUWMtZ%{AhaCDRt~opyQqiY+#eiX{Wr z-0Wlf!hT(O`;3y5oIbPe+O9aWA+Ss@;keGZ+O_)&)Kj#^ziyR!wO_aOQP;ZNx_Y3` zQ_~r@#?J1dS+M;{UV2vPuE!U~A27cy@u-n|?a2_k4-@Zf*_I#iviF1QFUBo7c23W; z%-L!Br3Q9!GinbW&5pcvPuZ|SGEA~4*Uo$6fkE?!j2OK0(r>4i*=bC@W)fj}`Ei$i zb?;aNybizhaj5WEP4#xB?g=G5uk3Ch892f1)45|4oMT;HA8)jvV_x@Nv8C5K=}B%+ z92St>=Cio|^r>B&Ey;ZP&?s_y#py!@)7zI$eWD}HeKKcd-}jaW+a^EIDmEyum==WH z{8qMbFKm#MeB{Kh2j6WyaR11M$9}a>mj9}Ct&3)2)%ji;o1ezbX>;SOLB#x(Qw$8V zr-W*qDZ90;pLOT9;`Ljyug6|}Kig_>YLf|(u{qn?cWrd@XRn2epPbp(zF)P+A1h2h z)$JYosG#e7X;h(%B1p6AJ?Yuj4j?>FK2yd z?#k{CowWz|Z@>Tfp*I!Mk8^f6I8-`p?y}pH+zz(QT1lxo%m{+_b{m%+!wS|Jx&dzw&8zQ>W#eKRC@#P5ASNUL~a+)-|c! zrDnT>5nG~-@_IC}U(!E6Z*rvC4t<^2C)4ydfBGruR~y^D-ap@)o0WLUFZE@^_~h=J z>U-}PIibcC|JY?y_CJ}@Gji<(>H5t=k5?Y*WBR_=$ZJ<#XKYI6+#%iOyWD$X-sGA3 zhUZlp2JI>vr#5Ebr-j?5Pndu7^0?S>G2_+dq-=S+;*D3QYr})*RgM4UX519J_@di- z&0}}%{mE~x+0l!<#e}(k0&S3mX8BFYg!e+cvjOEevv5z5IAp&vAWPFS*ZRqRySM?cU+j#Yf?9mYc2L zpRsvLwN6^I+>&z^H<)#~uIRwj)CDz;IAvF~$z1$4C%5gxZFS~!sp=H^VbZa%#D@A8 zV+7vS&Q#p)JM`_;->TnC8yBX&CVSqZzVqK#IQ!iD)p?KZ>54V27rc3Ip5Q(F{k}G} zJ;n}bIPqnl*woqkgHO5EKlM_$`NaIyQ>*Qs<7yDOAu@J-e#Cs;+f%9)t?F&v`Q?B% z>GyLS9ZEIIKS*Y}#$NllBVg#R&b<#!sk*U&sKKws2?oPOpFYmCu6Sp7%xB22eTJHM zJaV;KK~j6$&y7n;f9mn%?Ir({WrKUySd`=?^VVCxD|=t;ygnYoPS0$)FsRjrV)ih= zf0Vno&kP;uzR~AR1~;Gldg>^(7F{27uCOaf%MUt;a~|5C8UAF4->IYyT8YLZSl9Nq z)ApUYlU*}fnAXgx`{Kb<#OK@2)4$qm(%Z;posVtoTaY*|b1j=BV3QV>j%D57ChmQ= zLf|^HB0bdgx?0HeMi(zf4yn8N@m0ID5siKo^&cKQam(Nt#kWfzG&q@C^dxwc<)&x3 z&aua`d`$8BZvBpLRl~S<%xIp`OoU1 zUia*iJ#Usja&g`3Yx7l2{?T(uBGGSg$CjVz1QhJnR@cpkZ8B| z&J#}tf1W5Vc)W0VV%IL3A0sC`S-06SvRwg-^C0i`(6nwnM=hgOU<{@H=+&l8%%t>tk#CYiKo}t_xL<*_SGew+Lwd0U<->NZx7S)unz&~V4Z_@xuB-AYY*5x!@k zeY`=x4J|D{j~w~3LFXSL4Jsp#r zJZ24Yi>~)+Sv~9>myq5p#In3vY^V4o(Q~TpXn*?i4IS$f>C0|3^v_*;c7NdFvfsL% zD+rAk^q`||{CL6oU8^=&U5>9lc<1%qZcj~vdX(Ibw|^QK`EsOYz^Xc{yLPy8>0sXh zJMYx(7PfHMk+{~SBN|^8oP4;a_m|KO32 zVnW^SildDB?N}CKeAR4~N#ZH1!P({OyrU;w+HGdpxNE&a6_Xwj;@_ z_vbZrhpo(9bF#*I6AgR4w2*6~5|7$l&AwM$s25Q2Shtpk=`Ba=z#VNQAuA(v zTyI2zztHc+^g;Ct1`CXYxq(Xj9Shi+;gg?T-#TKP-3S>(!y-teQtp>bK7Fic+fw>J|n_xa84kVDN?ZX;jY2R?ki{r&lA zHI7Y~{-noM|5N=w*>tAjhfTEFi-_E22fB-U(4L_zG#P8ToiYi=_8PR;uE z6YjNcxb}WUW?|OF;2~bySo;$dyIWgd5%qd~$!*Ev8*l7(*B-ZKnaRA=mI+t3o?cgT z_kz5Y4@MZRYgf3h(6wckI{U1{o}3$~?!R&T(8fNG8amc2Z4ldJL?7)B&*xu0D!Je9 z)%+gSr*-a;GHFO$;IZ|Ct-OM2Prtv(C+SR(Q{21j=2d1*bqe<`y`!TS6u+(BXvYg3 z3b$Ul-_3W^_L%+cGB;K=pRvy=^!?VIPq(M_o9F6j{Bhzib)Ee)Gds^r|0T4ai^pp7 zIQ2f+t^2l%Ty)-Ta>?+i^{-vie3Bm??wlSpD&oMw(Hi4s#65dx?r}!?!Cto_b*0_$ zhr=c&S+=)pZ(9F!N48vgTRq6Tc;(54Th1KZxqokBvQ+)%*q=(4Tu%)dQ5u|Aqu!vq zxpOPdn2l^5X5F)7T29df^NO2({l}k{=DBrCu)9`g&E&+!`%BZ#T`yi$+bg{JjN!Y3 z?eqi9ZZth$GpuG{Myt8q%t~BNrxi&r53+NPUuRd*kzFm#ZoH}e!o?R3Etc(eALqZW z<;$H<_Sk0iJk{m=qo;31Hkhd0t0ZhvY?D_HlLK=y%^Z8q-8ao{xKCQ>UOxlxL8Xmj zZXZZCYqoo3jn?-J%jWLr+q}X@n(OhY{bGmBO-f$p4~+TPb@P#}XMb(HY1Q!EXVU!i zmK}O7HA{5rJVNjM!Ll`xX}vq!)${FEJ79T1;4Sa$&qF*jXKmcI^|u~Ihdm0WhxA>b zZ+LcAK=%bg=b_hIw!O3cb)ZfEDN(I_oL&dHW&z^ZFNinYbx?jV{y@O-? zGExkZogQfHEKE9jI9|Wkd7FmSWiy5?IF+^~q0}a&v|C1y+syM-#`bZwTCsgWar`Lb z#@ktV^}RPox7l|fbwbMlfg4wNgvQQp+CKKA@%XhT(t0*wkA-)lKF{>i-q=3(b^oRs z?VVzZ3POgQ>veQo@tCD&PF68KayC}W>2;s?hYf4w%`#eX*Rdq!Qip_O{g*3TZmx3~ z(86KS%laC^*4;Da^o^F4u(-fBHci>JB=#RRfU)&|*^{}Xn`t7@zEnC+m zJ@jRZ4i~IX_xkBrhwXX#d&hpL+hvL4u@9Yxo}9gNpH71tvd;wv4Ib*O)9LQK$Da%h%THsIyWOd=H~pzl zy~i_K;gS0->j*Aq9GoL-x5qKH!pc#*{CRi%TKZ%oYF^Fup! z=+jSca?jf4rSe~^)O%g{$Kp!SMHsbCCbbBga@via@XYLe6AT+-hnU2yZptKcf}WZ zeSYCFS02Kb^Jm3y<)ip=KG}~epT?K-n`Cn3j9aA1=Z3nu1O$HBWK;enp#PZQ0pSB% zFy(KKUwv!-)wh;keQWmBx29ixbNK3;JOv{NbkeIO6iHX{QT{)S`%L9L>!_$msa&y_ zoTA{mQaP6vDK9DG$|=WAx&Lyda^?OXDwQku^Hix^dE6gg!_A*D`R`rJ&FeEaE!gna zuS(Z)OBD5TxavQea~l3_6a0s@zP9L}Oi4BG@q63zc|NM^p(FV5#oPqAHyTU%Rawqy zL_Q)ZS5jW- zxy1@){mLaO@7O7KgnSmL{0qNpr~J#8eLD%W=%u>9!DL0Tyj;N(uHaAa!TIm?9X$WJ zS$wze$l}0Q?)cI8M}0>=KcLFHD)v<7JHEGlWxk_`8<&H?FI4c@$rn`SJDzbB{;cn4 zpgK{mKh@&Od`CIQ|3B+H#N0s2`$+$Y?}*^W@4z#v68d3|%3Egsq3>{P+8q06((C*4 zh_Z-D+)FBdSNINHYpDeJZ^_u3QUZiZE<~OU5G)zF6S}w5)qU>byAa<+jq~cLW39Uy z){|3CPCEXIqe8OOvBq44HSag024uNnef_0`ayOrS1PN1xP3F3N79eF#(YiA5iH*R>Y8N`@jgK_t-e;oI|cH0ndn!N02K) ze58B~9ZrujP)2+N%^V*|4?4=_pqPik4mNOh5CR>gzIYi>f68*umdl}&yghPK^+3>lC;>d57ALtWq_Xnd%SHF96fk#|xEIu&++92(@Hm?9S@9eFu1QNdZOm;iPl z&?WlRMcn?E;0a*_;R59e0_KvnjHQzGavpV-{0eL+;`lTNpNUtbvpSexIKKPfZ^MKk zSw|*Nj>+%3I}>GL6BM?Gd@WsTi%t^C$rA~*d{lX!fwsk{51#AlaIzbUvP85eIaq`5 z+QA6gvG*P`t31lkK&(`OL+z`L%sv9IJV z>QMV~%!k^O%r()5#xF#hLR{x%J_}_;Kgk@qMcDIKTV`$HBO$C52{h$%Ana7;2jw+V zo+IfU=}aRp%G1&QqL1Dv4}*LZc~&AH8TipqER*x4TwUaI*S4rmIb=2jb;==68uK1x zdKWSz{n>!_9ij$6``q#?yxqg?43}r+=@d-TfDF%I3;tmok&_VPU zg8n014i?p;y_SneCqe&ue5XD=(I?>#XwbDW_5>DbQQn%Iei`WR0Qx;a{|wNs7$13O zpkD_12cwK=fE*zcExAl2CLR*-!RM~JmXDG-w^F-EXDkFbZyX9LVciY2zW?( zfPHUC4`dB3+$CC|fpqe&ZE>CZp#L6ZK<%lnvJ8Ibzm88s@c%w|D=~JHctgg-KMCl! z;>K6zzZJ%ofQCVsySJiG@Ly9`z8AHzEAik9|H-yUCugFbV*dZAKSUGp-`c`OLb8B; z%IPOvl;ar22`!}wf-+W z%W00FiC*+G#kZd2(BsZ;l{-~Z?paBBAj)Z9Fn&BQZrot5d@^?v|78zN#ZBnf&xA&V zL{5kp^VN?Ssy}JSp9pb3p?veFkgpycscgUrS~#-);r9^!xsmGcAv|wXf8XGLCZhVv zzgLJc2EC|0-zR;ypnrH#edXUhnk$Os^_9zs|Ma4Ml>2w$CZI}Z8>MpP-(jRm<;wlI zE0rsc8_1Qb(jTN$uH1iwQn_;fW0cC3`w!(FSE}|Op;WHif3#A$azF7(<;vrhb9%<_ zb*kVZV-LAx$+*a|>RsQUdp0)6=l1j?2aFys8B)2`Kyorb-nje>cW~IlK^W*a6 zZMbsPe*R;B?^0HFaD)>-&(2EsSk2*tn#w)9`q5{W;VR?u142Asy=?J~c(3%6hWz^X zwy*4&CEs3I7pP;^`B(PLauP>>6FD`%|KsWB-(7Ku|NMI`#x{KC{40BA8N@xO`?Jq1 zGr94XaKw>$&>yeofAo8o7bpKnRdy<-eUC+pIJKmcaK%Wg*vR-fT6)oK|@X9 zPSj+nHJQ^D>>D1a&K!f(aApAQp-+3f{&$a6;DV~gDHKxu9}t5tSG90{{X=E_sP6j4 z_rp0d#aH=%GKp{Pv1*EPJ|0o3&amc0vH!3w)TSG2hN`317R3-rHW-%T)C<*$x#`X>*gOct1@5oz3q8l z#M8--!?*tvvU`SJ{0A?^|VGH|N#rODXlo z-3opwqYoFjfu3@u6t|FHR`tzPuIiVmNfFoSANq#j;o-_l>%Q#2UCDW(4o#ai{n51% zeo7OR5^+q5dnPS5O~^*MFh-Bk=KkijshsNWU z1^VGX%RA-%Rd$9n3*m*R2#AA+4-5|<68zOE(QaP~`G<~t0sjE;cipOksVT?F{4FAqXH^ZVEKdI3_LarSeEZ66e=kqJkzP?c@;m$5_~+ z`Hx~Dzh;f-kjjZsU?EULzBUX+e;E!^_cX`h|4O*`nzWW90>YW5!|2MYQTguxufTJzu2MN4_Tq|? zJNT;h@8y_)((9k~0X$z+`{8-2>PzURh+gDN__p+&=d)@*d}^j@KVoWx7xhzB@lo;r zKP-N?P^KN9zt<;aa+rF7YyYD@iS+(kFI7ymMJ4K63AW_TzPEj4K8bJtXMGac;kRC@ z^jGGS61fTeS)a6o8$65~@JHi!{{A6DWfH3ND}2(J$nW+^P5-+1UD*%)*Z2I6SAQ;k z4}lO>e8ZT?@A3^_SNmOIRI!rB4ppoq`=!@^<97ugeiSQx70v$PzpAZPhLzvjzA~)j z+y7at{67`Hj~x^K-B{_+{DS+82OfjyIWQjs%Gt#K zlRGpLk{k;oB8Q9%9y752m$-QJz%l)Y4V=K&mSdLkvxxt+->P_i@Doz~UfDB;WKPfc zxcEmg%bg!kJH z-|=ywHBUJAu1bFhcklMym}TFrsUng0`}25{Eq^CMD*wpu0kL;O1Ew~L&IA1FEI@Pi z&Ri&UwqjCe3q7fG2+r^ugme4MMN;QDvARtma#!)(IlFOnsdGC6sk6DU)Oj<`>N^lz z-=?vN)Ooe3y3JK}by+_l%Qm-=I$Mg-kFBDgfk7HJ=GKaS($S9x&Y6=mmpV7JM?X$d zX9@ag7_4O@X@l?R=N{^K<4n0!oc(0(E_H6e)JIuM(VwrPzpx;Yjk%YiKN0dBy~G$Z z5dHa~P9H^`!9iL!<~=3$->ZYTIZ_$@2a8aYo# zx+nYJm+X(c%iObxx0HL8NO?}kZ4wFeQsS8?h3Z*Eg=Pr_LRlEf@Lv6#5Clx~DaqY~JE3A%r(mdS8&GmO%v>|c^+Na~MOq?&9fjlgs?l1oCCwE0s zPL%}o-a=iXxv{`KdkDs%z9j--3Y{7EN32Sa(d^m`Z8NlquCkAw;X|7HFputdjx$+ppAI%7&RiR6Y|PV zfDelVHDuw)Q5%NuN%%fYAWE^tnRku2^9FtB8s?FNdX6Y-gtj}?bY(usZKFIs8|V~1y5Rma%4PI}Y7z2DZz$-ad_iivPHGr%9(+0=s4si&Y8Y^8nqj~RH^YF<_$uoSD*!ZtYXuJX-Z5zqm4QkYe|^<3?mmQ%f9QLU{vUyVkBKIlGwOM8&UZo z_ZTCOKy?XS^Ymre9v;y~(omLt2jz5KI)-JNy3aE56zWT~qR>7n#wax^+Q=gUtQo(VvMAlP~HaDjg2L&%?u+ek3=JvB9^V;5pN_t#dJyxwp+Z8Bn0$G`w%Tecf65H z7|Skb6K5n1XW1bb*F(=hLgO-`C6Q&Xp=(KsYwmj0f?655!DNuAw*P4UoM!Va4; zz^VwTvkchf7OZY#6D4&vos2)Rjtz1cW%qENT%fhPWY_BH{xy&9jSOHOk~eDAA!{8v ztJ5Z1jmf%J#QX0wNsD}?Rs;IyIC~Q_lBG}War&HkO&KraDCpqEc3!6~ksnEVrJ=4N z%j)NM+E`tbLVDzcvl62O#EprmJm^~KuQ-D5vZPg{l z>h9Upk9b%b9bSdv$ z?x5Twm1Wa4m(1#tVcLs~d^WLc$L2{!tD2)N6J#ej;+mcydzj;NqZrRwMgw6(GLHq& zSLmhtLL(2RAwd#xb|ct?4{S>2K{lWzNrzs_7K%^@dg{xvgSBTFb-@{lGVSR`F3BuA z9l9-BSPi;8TdsdT6Q&!b!;Tp2$s@Xsglt#Z9J&*QeoI)ky-u`|Uj%egG{ea67;G0d zAzfZoQYcC>@|?`F1+Xot32dw#Y^Dg;q4%;YWP`~@F4u9rW4w{CP>>z(8)wvEiHRh{ zcczi_Ab!gj=nAyUQ6#uBkZJYzB`&XuQkG2)1H)JqM*HN+DIVhtNB#14#U$UKD7Y91ha5u|hmyia5d)^>9wG%mqG)-UXa5 z_d-r|B7CeS+BFhc&prlUOM5yDgPlp>?}lKX0r?rX9OjFF`DAD0KjDkyIp@Prr&#XW zg((u)B;}w}TdG6nfEL4V(;2Z;M*dI}zR+9jCK-fxqW7rysB8nu2g3(hi6pZrSG*Bu z(1Q;vL<~XW(HXCe;7=&Goa`QX`EojxX`~!|+NXf*y%4s?#KkzKx-j< zAMu0srXV`0J+(-3kYnNU1MZNB80 zV=Q_9=#R>Y-!zvEa#_HKa`6<^Vd5g3$2ug7d@!}&06C{aPU+wWl@oSZVyxTHF%jOU zV{9S*yv3dpl1(B$i@}eEpo4)9>PHLlmY9$=oez@X1ZK9{YKA1Wk$gMa}-dKU!@5HaVQxHiCm-VFk<4}feyb^45J#?0A_u8HX#Z7i5`uq}NS z1<2Pp+cReY$_MH(=fNh-d4M&pH>WaDK(G^Y4r;@kbJY8vqxk%~*2+5gA&PDzt6KuI zcno8cr!KGpe)%vqn{dfjiZj!Lgf^DIFKJj%*5E_zlo>Efj#Fa7GT;-iPL5^3Ho`o$ zAT=8?uuP73z&}^uT#$w|o8HBQZK$Ieq-i4tmdWc7c2OPhgWko2ZKxy1#4lK;VRKtu zD?Z z_7vMwj4Xof=pY8gei<@4mz&NgrgMO0(38!mLwib4TdE_YYiOg5Sewcu_>O%kVAt9* zYttg=thP*m`=<@S64G01=t~vYPF2uB`(tbdwo*Tvxv}K?WzZPtlghPWkJKOSk3xM{ z0X>^R2hJ{*V~H#Dmg>>i)Q66o{t;j3U(e}khJ~Aia1Hwz$^KpZAYKqpGAwBC4T0uDC)o&O#TbwH=>l5f@wWl{YR$yE8ElW_(g|4jBXW@eS4l1%fwR1RxB^Rg zdPzSz0$0^I{cy$HT(O^$8UDN>yF!dhIGtf3mGJyfQ_@pcjwjUak9neoGtY%7X5a%vNh5D5uXZ9SumlF>*RddnM+?(4Z zz(22PBh7YaLd5!rKkcR2hnPS|Fy)XO&#p7QqwJ&S>7d%|s1RpS!{^C_(mt>wyt4_C zLBO9d;ExnGnoD>EjLV&@z_?rv&qzyA6w zb8&HD=H}+?$&)8+*sx)2!GZ8ShQ&aZn(IZy1YE{;`b7$76Qzurh zUOhH&;6OHi{(QE7|9+N`kifFCve=d_TiCpL^VsCcli7m@4_Jc+4cLhjCs@07?U=p2 zJ-c${3hUp$KkL`8A1f#*V7j`xtWKReZ0*{$?8c27%-PwQ9XWD@ojrS&b?DH6_3hi2 zwQbv$UA%aa0eo1mUcK14bLUu>E?ro+ZrxaTcsT3Wu_K#3dp4_5r3(A`=bzc2L4(+b z4y$n>uwW8#ito)6mdh!-o%NyLazq8#ZiU4h|0N)TvXfR;^l0C={~u z=g+h1)vL1}J$kTKty;0*;9z$3>Qz>^Ze3<*Xvj=VOjy&VO_{#FK3l$gIjdQ-CJP7% zV8+JA?D_NO%*@P;eg6EJxx2fwlP6EIZQHi7yu3WNbLUPrapFXll9IwKEG(EvBx2>| z^(-hTh<*I{kqsF#g!%dTv5briR#H;JQd3jelqpl#s#UAl%$YOUfB^&8;>C+u zU|=BY-McrdU%x(Ev}h5#e*HSDsHk9}p`om_w3Hbb7_j{Oe7P=pd3mwbt5>r(Z{D!6 zW5=?~moKwfvt}`Mb#-><&K-8?(j}&?tWZ1m{SZ1CX0?Dgx{?8S>0?3Z7DVbi8fV+Ri&WH)c#Wd8pC zY}vA9?81c$%*x7&6%`e+mMvSd!oot|%r z#B_9YSc?`dn76k#v$3&ZVPRpcO`A5%$;pX5d-ja2S+j;orBY^XZOu-fKFuagn#A_* z-OGxLigKT+Lxv<6u<7VNe@jOs8N-LKsnX7*H!1&s7+XA&jOe3}!iuB>;x< z97ggP267U{kq5(=2&1roL6pN7f?xLs@@;q8@~j`a?l4Ksk$` zn1xWv7%1dOD5DV+F$79@4+^*r%C{1Vw+~7ufx^9mve`k=c0kFZpkSI%uDejIQBbNg zP^gVirbH;x94JvF6et_Y^A?J;2};uf3S$FhX#+)h1|`A0wDdHTV=olL4N6f13b7f= zFdmA4`}F8ofd4}Pe?x%&Z254{-BhUS4kiYL@|M>HxD#0J8P~v4sGzJ^(K@0GAA))eL|&7-01R zKs5~@brS%!4B%u1U}_0aY7Id831H*{AUXgLY61Y70Psly@QeWH%mv`Q0@&;V(0l^O z^aQ{x0k{kWuy_Jg_5e^U0Vb{hk~DzGdjJUT3AMTcI35EubO0FM0E;jHg%dzx4FJL# z;4lfmPz+Ew1VFe2Fn9?dI1CV20RSL4CpSedh+HK>ExBoeO>$`jCFE+!-4nc#dnNZn z?v=s@f;w`6Cl$1hWL&1ij<}DV!mzy(b(6~{mqRX}LOF6r*3Pk-{EwKja$8ty5S+p%jHjG!}VH|~36b4X;Kw%Dr2NZUY+oVv6!cz)cDKw!_lR^RtRVlonaFjw13gsyLq!5w9 zCknSH9Hg+0LSl0D6oye4L7@qSKos^-I78txg^U!|QHV?-9)%SYUQ>8XVGf02PGJGLaSG!oe4!AD+&hKg6joD6MPUQEdkWzw)S=LV z!fXnODLjUXIYIO;FsGVe*Em4HMKoUklM4b{p2Msnp_aKYtBo+1pE0Ge5T_=l(;e!Q z3U;T!WZpouI{_8NFt0RBKMCqp3Ux>ZNv|PVEs(bk@X!#ZITvi(2GYGDlB-ZRH;ADR zO#VE`JPfmM2e!NdiSqzOg8>N*05`@E=?Iw17O12hSbGzuHXYDW1!ffh5j;h7yd3I3 z5NdZHCbk-I^(!D}10j^rX)U^REi(p0uV1E>#;{u?~6>xD3s{RBjWd(D*4af)vl+=L=wTGIv z20X^Xbanv(FGDrX04A0IPRapavjItJP^$-k2pyQUEmW-@U?3AvF%qgf2PT~ewWtb} ztPPW%0Z8ry7}kY4ZGfujK|Loxl?-79(*PA_FpaxVnVx{B8-Sck5N%tSXc5e<8q7)v zco_o~3Iuf6!~CWK4tD^0tYQ9L0a;;CAwR(D0jO9BOg|qg?Ev^c3iYu8Y;J~`>I1fq zK=mSE{uO}urZ9mafH4tZ4Y#q_3k|^)VCEFe;{)J#4@~wERNVuvBnIj|8s;+`CJ+y( zS_w6L46~2{y7K^sO#my0pppWZ`yIFjOTd;FV0bBDKN}Ff9j;;$VCx;A-~=G|AY9Hh zxQ$VO5DB2=ILss*uw?|e3^s-+$!T5uu~Meew5F_kr?_8^7H|`66SsqyTss;ayYlQU2eaE3cta{+8pHYWI5 z8$X(Bpo22ndXk^NF;&8g9-{*p`mqvRg9CZWF=|4?6u;IG8z~+X! zdWL+>qWtVCwG4E#FsPaUYXq>4N0-*_ zg^D@Lue9ar^Y!>TDu%!UicsUF26tD?=}7>N6hb1@};)2oBiUpIfd;1l1_XRvzmHEO~T!laD3(Zw0%JrvOT$wM-;`sk(eW5is&=T&Qd?Eeu z^Zz4Xn4_j3n4E_4OO<{_-sJ$^75?%5g3W*Yd@Zq(vzE$vOT4IDyiS6 zl5#GmA4;H-w>co>_ndq__x=m?b7}VjLcW>X`33X8s>YXs5WILSQ_b(>b=(OoCEVg) z3O@g1ekacx>POi}@HzO@k8(M0JF53x|7kf_yngWf;rYpbugo_{Ic!MgDiXg*dwIU| z{Hg3diS+1OFX}`2Rhe)2-uAq2uvhLBpZWHGgzc5>i8V{5KmMyK{gq*R3CBMf-;jG( zZBO61s$bRQ`A&LCFVb=1y(<4JyU!`&+C@@hrI+gXqX!NQ<@2rZo5puwJAR#^isJ9j zxe9CfI{{MpN5y@P2G%{@DoXZOcit4KMr)R_ceg}4rRELzV=zrU3m@?`cUK=>7`J)I&zI}A;%#Oe```={4FB0BJ-J0 z7whVDiJqApJ+yX@>eJdiT3|;h#5WT_nxJH7EhU zk89`>ZA2&0hIOzh)Q?*WD7CfIerSPg;*m zeXhne8k73fl&?wFlFd+}m&$2e;@LWJq7mjR8$`S_Q1Fh{P!oL`;48IP@D696De;cV ziFbJ%@8UfZ{NsyOMS=(5ot7@qM6x8BNS0KeWJWn?mC7+VR!)m~vYI3=d#Qg&%L5$m zW`5xv(MhxsjYJpq8;>!;;gK&_c=l)XEgxr;n%g4Ju-SZnbN64r@a$VQO8P{yrFGqv$(Cr8 z+o%24_Q~tw|D^wi!5hj$S}jg6vK$oeKQM7$B-XO)BDYd^E%>#*5DakO-&qt68NiCjIoo>4oJEv@}dP_iRl z-lPv}@HY^8X3>UayB|yR&o{_Mo{>;Dzu97cizjO%iB4L#&+8ia0XtFiQP#KL*X-+I z?eUN-8W;1F5v`=FmQv)XaDC9aer?cnM;vEF^#(()B($zyi9RYPeI(kZFG=yAZn`ZJ z^9SEFbqT91+>r}2c&>lw)y?wxujXhB!Mq9Yh!;c$**TqaSs8t#gTOW!(Pr+&vg6PX z(MSEb1|`brQ}j_eeFe}r)Rzez;`}Y#*2sBh?u-0XCiEfs5^V~fAOu|szo6(-B&$r$ z<QFo0xqCm;vw}*{Nw49 z&q0YkWw~nLyg}ldc^~8)<|X;Z>1_q?)Zu3q_=mpuRqo4(UeZ14S0Pu0-ckSmlU%>> z4$D=Pc}L?@+y9AgdGITwcOEmA`fJoqiv$nk_Nr-`U_`X62TfQ*ET@OCgY=AYWh&D# zvRjLVdXoI81pl%-`{ld??#peJ{0zyJ^n+-l{=mOVv8WtAnrItH_8Ja6s=C16qNzgX z@}Y0*KwBF6Bpk-tdgz;uj~dRSC445C5)bcUjdz-otm!(9?EzWGqP;8HlH4tk@1{X# z*M{Sf3xV6+jcG>PooI&eDI!AVixybTi*OtgrO*cvK9~in`Znwz4&<%l3 z55W1)q$i{=KcXw7C+=ux9)&mpZ4u+hZIs4U=mM^TK3ePUiWrN^8EA~Ad=1Lgn9Q>2 zS+lmDi^S7JDrtn6E(Ecgj)7F3>opkq&&PF#@i__CWTr$kQeENr-_RM{pi{tKRO=r@I+474A4Y#qPdiFb5Yi} z_0YG<=OU8NS|1dWfMQjAzhYg5OPBc;e8rcMNS(kK@=0ZH6xe%YI z4xLF`*<6T^o+gx+p`oiS(8amU8Zs;NNpkwD=R&gJ=VBm_^Yl^-)eL0@9GwPgnlb}? zPiF@I#9Z7Y25K6*h9no73;O&k~Hu|8SWWdjdbgUft9Qxc`o`8o>@I9UB z{}Xd@mpp-7${}Bpi>8WP?r}OsSVOu=__zT+xN;q%b8IzqX&%L#j?w-H#D9JsRnZ5{ zr9@zWyc&i6oWQsz@I9SX{U_$)AvuA$ln4yva?wXt7f+K8k|fM$F62x0QiwkP3VTt- zG2%Zz7hP^H!;vGU%gu%IWryK=I#%BPc^vaX&a8&+aLAYBvle|0{ukgF@t>cI4mTHH zfgbYl6!s#+xX9DPTy*}4xp+%tn2RsuOL9s07s-YA&(B4hn+wi2myzEg-$D7*5`0fb z?EUBEBEy;C8oG@jUy{q9ze+B^up&7oQ>-OK-lXC=(0$|=@^d0AQ}%@elEz_*)Kq ztXwYSEC0M)JjER)BpZ@1$>$DYoP|`7KM>p`Eof29qJF(mKUaw!Dkpke(S~wWabKl-2W=^4;GdPyb!tmIx`Vd-{Q{Mf{?Q%+^t=vz z=z61V2W~Fpqp2O$u|)2?1bZ%YKzq8s!E+kqsw?n=Xt;@cGa5e!+hg zkke|0oK`jDw3;DrUky2}K`0X=pEU?&V&t+0p-hZ?{ZuMPzJ4l|BVRw2%8{2JP36ef zkETA5^N(kd&SK>1N7HrW>i>RE)%kCHPu1yfbWhdsUxTgCTjdz>f9Iac_iuDh+rP%|BW9(0-T&QtD%Zd1 zJ(bJf=$=aY-+QWm;+|^#s+p4bnCTj4N(*b2oX#@}^mDInVpyf#rqm=`3sVitK3zK2 zle)R78ykp>O{!I`@7Kk}@Z-~CZHjV_=mdqhnOloR*6vbwA@1qK%TwmmyM8@KeEnvw zSy4`rsJf9>tu?ErTPDTL)2F2DsL?*Hv$oG}ZD6EsR8pE-?cvQ6O(G(s_DRu6dTpBN zw_l%{Xl>tAt?89h$Lqa(Uf5zxgnRRc*N@pQOqpIoq^_$Q7|@|sA3tA{9sxde_idfi zmJ*sR#6k-b13i<7(QeI_BqthEzV5M{V|q`Y=Qh1?s<^hTSkJcX*5QT`k*-an^nK|xZnpP$qqb#+je; zqh$|&S)KgcLd~cMFQ+wW304Nx)T(V-JScp%f&;g!Sv{Ay#X9bSQ^JA+e#?I2AJwP(I$2FTA*{NMgNsd8O zq^y;@TL-O$^Al>8-6*iMFw?Z6{PRt#<}|)?`ecLDRWYWNU);QzR?AIkbDK18s@bBt zp+*g{nVOlCy~ye1)BNUZR?leY?&6{0EA`cjj)@VJ-zb*EN5=~nE|^iPxr2sdQQlGA zW4R})wz1c16EVug!N5>pn4fo8D=}uK_Lxx~j&ENaZGEBiNS(J&i<}lF$5-#s#k+QN zY^+*-PQLKti<9lWT)efN9JHN7Lpn61y$+7$ozy>b`f#nR%tR+Wb$$J$*tu1uuC8ig zb9M9Nlo-SCAYa=Hr;pZMlNxW)++NuH>9a!)UQ#bnPHwJRct~fvHV#$V+L~5rOnX1< z+cvjdo2FIU?aNGRlXK{hV13#wo2+fKTKT$msv6kEqlQy6-PTu1j+ul7d09^$-MRhp zlKf6tm@Mt5kLni?&Bc;k3ucUMo%9b2b6TAS-O3JvzKeEa-JtLwM& z%(J%6bk5uwDofI*MN1$pfXpW0-0c67Swzb zOe6?X4TMPYVe0N+Q8?5m3})B^s-J@)gD{jmrnUn^TVuMZfPm`|`x-z>30R&Ck>ck~ zO(9Ix1gzW#HE9l&^n&U>#558il5m*+dO${Xh&3P6st(n836bPLb=+Yp*8x#y023sh zHV|nN%zX*q#~PyW1zfy@nA!kt)_{F)Va9q;&npnc1+d#1svZhej)I9h&&>iQOt6$rD~M4NxWJo5p41`ypbz)w8Ho(1*&2)LLG)yjdW z?O}>9VTOqiQ5aMr6HrwGXca@9&(NMGFe@=_ngMkSgQ-M7%tEO01wij|z|0cBQ4myi zAJnG|X3_&tdIgZ}2eBtZO|L-YO8|ALfR^d1~~A7xkLe?7Q)?qgzGZ_A-&;XTaV9cKR!rr85-!4K}G9I!eWP<8>XrwGvhk@il4 zds_%N2nGDLf$P};6EB0C%mU0$h8xg>d-4OkIRSbt;2!M(o$+u3VQ>k_fZgVBZ)I?U z7J#!gfYKtk7eBZL5nMq$T;K)3t}k3)G~93!VD=aw%L(x01=qF%tXKsW#K5#lVXCJw z6+cYF5bB?bshC2YyMRq@P-g?Mpc+)E3)t}#W{?Xt2!Z*D0SQv5sF+j`tiKM^zX`R- zfhilo99Lo3IEYdmYBUoc}5B1B1%0>Vp)1YG2 z0E?@kil<<1!GOR#sAMJ}#06sZhdGae`NYtEKY$D)m}Ls-1Ju+Irpq9n0Km!%K-vwc zz%!_DBp^u+O;Eo~z)l>*t_Blb4UOfM7IM%Z^5iy z0A3D3v|c~=7js|ifSrhxAdK;i(}lLV0S45m3BuoFvr z+5q~uLro(A4<&%iNI-)dU|>GX;s#XE3{V&iNL&SYJqzQ5l&`+e8DuWPTp*4k^YycPLS#J-7QGv6e+yXK6A(GY5Q%dzlqP|#z6f?40PCs+ z8(a^O^CE^=&1G{|#Vt}mvCt#Huz@Fwp zd>se-J`9%f1Vq9Fu)4!wfkCjFd0-7)U}eW3LUu!Jh9D+Wz;-8s#mt5ndl90z93nUy zV!;EEJPD$`3#=*?tk4B^whUrmJw!`6SYZxC!F}kWBt+SV=3Wfaz8k3fB}nEMAc3_& z-#sAnA99GGsngLVKf_R;1{BQ#`EVFs2hx8QMHZtd51MutioOWV4S@wbgKqyWSjw|N z`D%2j3#6Bbp*k3-yccAW2$H-Gr29)W;~sR$Obq{fz%mA)Tlb(@i6EUl=#pnZI@2*! zc7sLj1)I2p-GeUu0fzfMU_VLdiW|T#_EJ#;ySWSKdmh91Vvy%A(G~lE?m-~+Ye34S zkp2TO)Gk4n?*>aCSrh|pdoXm1KsxPUBPAfCYr+2R#V~BbF#Q=w{re#K5Qg$4V0#^4 zDT7G{ARRB**fU^FgTTsu0kVD`?DBe$Xd~EV63BHQSk|=|7C!(hNW$=Z4y@0EuKPLI z&)w+u?}2=O33hQkNNYE`+J&L`9ERaKbWtftVl`ORZm?DXa{d{HDulI#*+YAhq zB6RZrkn(=8-tU9Wd=KoX2qgOhkk4KWldpi4{v0g32;Ck6nZAH7Uk6sV7ObTS!@C{B zaW#g>B^ct@f;|ibIX(-P`vTb4_rY3zh+%&>*!Fc`yEDOx)?m1=2HP*eQ1XBsT@NSqSj-x*sb?` z@BI)1ehl^L7(%na5)ycR8AOH$ENmJ`|N2Bsz#tB$f#p62R@;an(E%2C5m@InV5=8_ z-TeZ?)eqL}h6rkhc=$d@J^@3l17gC3A=6H!7sKlYh`jG%XkG)cRszv?7ucm2tmbbnqkFF^DS0n1qf*6D({x)(!g5QgI{4DV|pGN)mvu7TLR z7$P$PVq+HAy})q42E+d67@9L67K$NW_Jgh709Muk(epf5|Ic}@8^qgPUIf=hZAM6`I!&{Lm-~~U~dz-I)-5Yaxbz2sZl*u&hB~Po)rT-~Fuik#cX;8L?y5aSg%qXK@w~_rBSCQM>d;%u6-gJkQsg??12M`6F=h|ahjA*e&?MFJjDaVA)xEyCr+%azQ6qVxB zo*&Sy%b%?a9Ej}5Gfex<9$)rrtnz2*{x49~i2gh4&*5EGSy68GnV$13orx3kA@6aW z{~psBR_FRYK zV4lu#e7@-o4>k2Pd7Jd-;(_t@+5fTMWA4@s<%S~ra<-q(7K?~R4e7fioq)7SJUQ_n zj|bkP)3JT_GGV6xS@epwmC1Mm9F87g+yh@kC&S>OB}_^JZxAzUVgsm#unEEf=8AUN!kb_1P**Sovjr6fehVgX`bcXJLI-b_>(SKWBY57mbL; zyT`|YYhH{_w0Q9?<@PyM{Zv}RYx_r$9V7pEu9U6U8lFK~wBd#q{Qp(oeNhjl85(sL z$|H@w*@t;`=NzN)c;xw}kH;fT`cKOv|5$xD{g334A%k~~uurS+UgPKhC;lamT=GA| zBO%w<@BIspjP}rAefQ~jBs;N>N8;&RJkk**S`G0R9@&Qr-o>*C{DnvM$CG(-@|bvf zK$yi0t^l_jqu#?o@#I88>gprzCX_u z$w(gA^ghl7|L~jc$cYM1xMO_ zBjgr6%p=zG$9%rEKkPK)d^yL7jX1p%CP;DJqkxy8cXvaK9JM;5%TFq{49^>=pp1| z;;sNLCn3InfIouvMRq2Low0GWPvU6n6yjhwaF8x>O#HqA929x{J?-wY?yXaRFW{=( zoz>mGrmVYYfWPM?;-;5~W(i-D)qN0nQ2BU}&+vZvY+ZXzWR2V3vm1G_AH>?M?$zjv zHHrS7@KnH&r-To1b+1N$>_%Sy0vxcf4tYk%{8%RsXrlr2P!8I71IvL8esSF2(>uTY zwu*w#ZMg*%=$}(ay9Uo)`0d6|^<8ekYW@Bg-v7_fgRIG#9AoMaYxmZZx>YuACnq!U z&t9wL8&A}FuHx~ZORDzTYo^YUGM;er{J1GfGaD(%&1A-LE^j}JQ`DUF35NK(%6iz_ z7X<5qVq7`CbTsZyXM?A#WK*Eq^}GD~=>#ne^wHPw*UPXPubO7o8Q-nLFdgla&iKqNeL~CUBj8moOd%de|4mPok7F4Q{clF~fgyH)QQYA5ZK2*BsHjEhV$*6nJVQWOA9ud-M?AZGw#1 zn38!k1Q~J|a*48_&Yd>sggc{YCw^U?k*!@~>MIPN@9n+6!JSsU8#0+P*T~yck7%Qe zp$tB=QpuI}(%ORBL@~5wxW8ayqIjux2v`li1>QAW6i|+uvbOy&F~YnbnJRixfwPs6 zE2g}EKzX|%JN%I0+kSXW1nD~ho~-UiAUFJw;kzM2Bn&d;1>_0+AWxQgTcF?>{IVgt z58dV~=)}7-E88R>nd{ifb8i{tkI_H}$ZbNeKJ4`tuM?}*3|$j3L(rX0vD;`5;aVrUpR3?U5` z6xvn^aTVol1KL;R88N8AlT=N4ABL=T%4+bkHl@@2Ov>x_(v<}(k>6_I^#t&`@)CvD zF!1^c+W9{Ey1|`swD!JDn?jz{L8qxBh}5IykeSf4_Gbdes;+6Rrk;nPPaX0MYmHUM zuc3~$|Fx>~ggbTrPIqe4M*NtW%#1-Sk>-u>SoV<|J;78f0(84h_A;pW+d zd>zZLO2M5HMu;4|pzNK^2)JfwCI+QN!XMDjiwtwqOijvUbzioy1|RUNTV6O>-WfqH znO}6BC?>QFsU}SnpX7t|-zctS`_Cn_y$;#s#Ar5hA*vkF#55;BmZswBTN%WY+2@-+ zp3FAsKdsDOexCJ@C$r!EBV~5IF5jo=kn);(DMMc8lGzXF^5?7Q(SJkM22fE~dqFaL z(v->LFH~laH^wa#>X!wpb&@kH|1DC6`Gk?PW=>1FdJ*{Y*9QCFdmpmb?G7DyC1uT~ zdiU`CC%{)ffZR9;_}kbJibyw`_0&gx?E(qYI8&PSO?IFWO>sgRGUtxmacX618I9zbRu=$7*BUn6Ch zAH{0Jsn3g^v1rFP2m9~)2<`Z)7`2~sN6z0_f6i4^{fEhNAA~$h_Y7+qfxJca9hg7e z0k-5S4c#`S0CVnU$it&Sd~dAQJ)(*8=UVqL=m`kF%=%}@wtR?ogi!wg=Adlfsn4G+ z+sr(jxO@w37>4pblx=B?+aHwQY|DJ~$w>6a#*`m#;#~OaA`NXyXuS;bjcq!GHc|Gy zf;#S8>uP5I9fs~BfahHeiILTw5lx3t=U0Jq){pq+vzc@9nRy-YjDjrBK-!V|9pWO7 zSbbv4Y4*#BbMy=J>G|_ypCq)-7pePcJ2{Cu(?)PY>mRHG>(%a_`bsML<>3;}jZ<4| zQSTy88f+(NO&_5CUC{e>H6%bsGWDhoGD6a9wkNfT>DfnT(~+{3q-i?hIQY*2{AOHR zBoX*E^n`l8$8k}ca`z_cO2vNh632(sLp2>yUm_i$El0!9H+G_KC-7taS+6H$-7{Ku z!@gi>K0M%>NO(X(gl%e(@ZmBp^(N91bt;Yx7wYG!4i>cE7A)9;A2@w!*KOGa?&|CU z=w;1QQEwNnuCgPzRbk2FpJdt*^ z9W-NbkRa(kwbhTl-v&Iq0p3db-U%Aw_~m=Hm-Iot%y`6yp)K~u5sX=;>x(-~+V|Yv zzW6E+@CC#V0N3ZH3-G2meD?W7MH3%!3~0Jw*=p>?;^B(sNEhURCoO!CCWsHx!%Y~! z1|Q5T9zMEIf8v5|Vmw73w4o{bu<=10sJ1Jd^u;GmGr-f+q#Qe-`}swLpOs!u+5e~X z9~g-I&(`oH5c;9hDrDf+gkFKpvYYME@UaM!^}QWTjRWWUCv|<3{so=r77bsol_3Mi z{7}Zf*{vczuH*km!;Kxt_#r+4c&z&D)A7@^4rabT{EmkEb(7!4Gp~>FV?D3bC^{{n z_|wW+KYO6m*UU7dtb7r^m@Ld>qra_iapmHQrFWW_H4AI&RDN+1_sckbD)UC?rA?4A zD`L!(x_VX(Vy99yIA^Np+>PIoq|M4)8}$w0iWU`Mu*LjQlxKUL&>Xhq}j z<^f&)KAnJLnz(o3pYT}a2Q(8%cNFM&6cy4h;{4ZgCr-NXxo)>boPN}oGhVfptL&h( ze?ouFqmCwZ_)(&V^C;S7IUfvReKq`Du3IMLaqYGXzjoL#D=x)nfL)=v)GaFpw`YWN zUCnp6#Z?W$RlOKj9)FVMaa=B817Zxp|Ot@JUo-mPrJZn>T- z^>)mATK^e#<-K0uLfhVp28sEnpp!o29<{$=syLoBSj>Nr z_VywE_rjRN($4O*0nonQj(H*G64I8v8|%4m;FnXivY-XF)*{TqgH>Mw4t)ijD+5P) z?XU$CAI8qE=11;Q0o;axd)nMhomK<4cAelm8m$wUP24)I##%vqo4=Yvp4FBwi)G(~ z4hx(9OSJ93f%?jJ<%pqd*OuD?-Pu*Ex?!j9fbF=u3ouvJ)!pxzcxaQ3SCEbN)1IG= zHqp+k;(kf4B@hSCIB>u@j~_M{ww?2x2a)Hw>h~j4uCAZL`>Jl>UDh#(x&iO9erHzx zOJpqC#Q6@#(4!uAvzq5%9R~D4`wDFpT=zc>+TeNu*X>Vv67wF(bvKi?IOpE%9&ywK zyhrJyHb@E4Y2SncVjLJI# zy`Ae0VoYZS)*i6cZ{)nN$6eUvNosY&jvx8_^sr#O}QLj%4Vf}E>c_HLS5hVq@&&=P;boRFy=wW&98pkdq3;>U+9nj**QlnDM8+U zHuqPe+sWzG+Pl4uFxrZ8A?pQKfP+&vH|a;~s{OTw&(KwR2hY5|iXY>fHPaA*ytMF9 z>j<}$FYm8~k6RjCUN>%hRJrc&!DsY)1)X4$I${?@;h&_q{Wt4u=UQK|eV>RXr_PoQ z7`x8d^T(VKnHZPV&GMQ3M?K=xroU3>>D0MQ`RCHP;`szzdiJze*4J78cskcVXgy=P zOx5@2OwZ?7qsgbs_vr-05!I;k)w%q-{Kb7m%R6WJ%F*=vb*>4MF5D*oGAVlb<(<*F zl>eO3C#WY-X2jDeXhS_Eohr{NnW*Xp@;Z|v`3y;i?F##()sl$(xxwOoe}n3U_kMI6fDTFA|I z*bfim*K%91TR^sBBy{*8H{UmLAk(cl1){1Rc1BmJzp9|%<m8rB89rpqNyH9vyVHJtp`iF>}P z*X8HxcqVYx|JI7dvDa>KGQ$KM*kk=q&IfGDr#Q2rV5BKs2*14bi@}f-?yLQU5CPc3 zA)4QIg$_*5oYq-9con|c?QY7gD(`NDzwh>US9QJ(pR6&M_w{Vm|o>H>Thu5>T*eIEJlMZQ;xMC5x*_ghGR&7HS&Z%>}q z(U|OrLHG1XHu5i~Z#Kf9J0XJm zwr5;pCI{BI;3uxu3X#ux^mI?)2>~B3bx%1Kcv46osWU5|m2)Gv@Nc-x+rA;mclrRn ztGce(Thy@?Fno`9UHR~VkqU2d$2H#PHngIh*9lL@9=yBNOWY-`+Xvh=dP_PUL%0xq z_>Ur~<9dX%fY$|=4!{~yLPteLQe*(%=Ufy?L>`ML4vOGtvX1J!!4VwY)e&?Li3}72 zJA@e0F&b%eQN~!L&%vDb3*zFA&x=7F4c|$OEcxQak!*1Z^1UQdk&zr(m@_m|K0GC| zcw%a#Ixj5}bPvP)OMSn-ug#*F>uYCLJ{>6=-?z4J=3&G==bTxq1bz&?k*uYzwyZi= z+la^EBS+bfzMddSt>;!fMY89r;fA)gEB!9Mb-quZm$Ex5IbaeqT4l-?njJ`%N&Z zrTNg0`N%r}zi(fXzb!COwAFoC6jrSJdL)STMCOV4-cZI5z{X_smAWBHS2?qCkL+vK zuN-yDtqQ8h6h5EB*aEz>h1_-*W zvImHr&{CUR;>ZE|^b>Ez>-{Gm#kyV~L-Yhz6tzK67G z*Q)mr2fiIxS91@C&)o1P&TUN`)@z4H?7-Sw9@|p^+;2mhi0932_*ICa!fe>a;5S;B zjW(69aJ9j#nO0uxYoaeD;z>IXm|w~?9TzsCLh4`v#6_NSqw{WQ(^9x|1O9u&@rh6h z{Y4Nj2hd%^I7h;?Ie@j<2GlLEyr}JV(8W&lvyI0?pvAxd3y+Au5;$E&oN`V2O9Fci zMz(JL_^*zC1?$Xv-Q%0z^bE^u`4W9DQ(GUN#JwHqt=p?b8}}~UL?2S%d3&|LEjSST zA2@p${+VHXJ2(KE;=Tr{m%^8ndm0Y96ORUmfCi|m!k4t@Oz-?{@G+&&$4<9rs3)`< zYo((=Tbbz7@h=s6#y5x1*Tgydg?h8yFC~6I`p_e7RoNp%L5b`qPbvF}<2kV0(NFzs zKFU{ME$9gAbMsH5ou^Qblc1qWv~BDCiIGE?AF$nQGkr_hR{EB*ZEQQ+Og~z`2m3ef z@AI3bAFXL;0PPI9GxoQG{<5&1Jp*kHVcf9YuG7;x#k;HSgP?8RiE#f{kqM8HA+Q9SCW6bB<@j2MxUj|KsbCmTUXy_4Zr7){kCi zXnO6|^hz79O|N0p-_Wb!V}@R*je;NWKrufwsE=M5pR(&T>~Aa4?r;fs1?d)J=Bu8} z{hNFL>i97DQzgM3y!H>^59n9QMuWqX-~~R=d^cb{;2SI1&(~tCNt$Cnk7xxW9g6u@ zb0L1@Gk)FQ>}!F3Chht_&)n~1`q;-l_M}JqxQcy@IU9Mc-Nzfzw>#0d?B9nj@!yv@ zQ0!p&raxJ}&7aAagJ>uE zGj9Rd+(3SodK_bB%Q?r4vXi!y_Y#f-lwX9g|0x@I-3UJM zkZ1f$ji{>^G`m;REa$Yg55M8Dl-u-wF*IA};IS*7AwTNlv5yW>Jl4>xu_xPf8?xxu z$!AA{ZdZeMLS>H1E5;|?egOVL9!nV(20kwHKu-X#9py=AI_*wqx(B{a_k$mWpl3b+ z|8m0%j{u*PZ5;dbzuDJJuKa6oqxxqF^PzHG#_ZX6=(eE)HeULWj3rHDExw}ov z;JW2~{Hz{yLK%FIrjL`Fr_p|NzO=Cbv{3}w2q*QYjSo=oThM2>q7PPRn)teBc++J3 zsz4Jz)-=KX=dj^D(5Z|(F?=U`gp$|TztE5GlsM?2?L6t>5PUDYuJTBqTfkHAe{JoG8N)8T0jHdAj*&T%IqC~9wEluzH!KU7vEPf$%@r?>k*jk zI<6^rrft{Q662Isix4^S&Z~2bu7d4f4n5c_`i{N=`p7eY81Xc!XE2Ai@z+(-bb?t6h zUReoVrY@e>ZI5PiKg$Cm+`tIzJYJk zN4Yw>%){I>yb?d= z`DxQnKw8#IR}**YdQF!fG5{T#`WtW|ZkT?e0qF2XJxDKdz!{g931{g0@eJN2#8^(KQTt;)^j`3d99Ten)bve`X*@-(wU$4tI{zx2q98U&+ zrvHhbSmnQlnF6n{qd>=_sJOs2$Nc;YKO=dc#R&YeR(>%MI-We^Aroihz;2lhTM>N{ zi-ag#jeY&aSZ6E~;wWwRoC|n(9t6%?;9O<_;%5oZ(MFNolznKt z1OK^)@xD^ljk%LKM8Rsqk3Hwd?>H1E$PZXA)UfSs%&9JJ|J%(YR z6K7H&ys>k8{m2yec;3(Mbmudi(djM_g@@tihxQaEz(xynY!tN3uG}rxX0otecwEn0 zS@$&;bI$a1)K<&26y@{cY8{q_`4#3*TzlcZCl~Q3GA15MbQQR<4#PRJw5ehadiTdO zI)lajLNJ@=K#J(;I=C4=lj3OL8h_zFvBS*_{#Kx69+pW4WP^>pNF}T-CWiNea8MB#$JWqh>j7PJd}+d=%+XU%0? zmdUskNMFqSkas)U&ODh9^Y|&^mt%e6S!;cw$gkEWiu|IG_AY@mw5zkvV%yf;a*gpr z*pq0FqRoN!sPrSnkqqH4JSoOcabcZ+Yb63Uj{y42;MYG$q?|&%S9-*C0kO&m@SP$F`ztL>iv1oe;f0=XiZ$IH1>~CVfn>D$ri?Od1 zwxuIEqWR5~VRCJ4JI2>7upd4RAKYESd(?$~e@LEdGVJIHcV^S;_yy2c!%=n+>v4x~ zTT$=|{7VmFkDU+r04FQ;0UsQ*v^%jaU1;YH$g6nY~6=Ft~~OdI{3Udz{j0<4E;xaC+&-?LuK8pZ-8rGmn6a_09%dDe>K)( zw~ZR0U?@k~t`cRt4q<&uwH^CUb-SN~FYdNc*G9Hqa!rK!hEeYd^ta4YWOav8_tjo? zo?0M;XGK#fFCj#~ru-6NEV`oooAkszkEAEsvrmCXi~vmyd#yNfKj?~fMbZ|>Z5Mo> zyFp9oQCdom(ozfh`)pbod2}`W?Q?slb>5sSny06F;F~BV#OCaiUVUYokWTiOthbvPvHAyx7u*!B+;RWB&;;RhU)2HoB!`q>An)fsU)pr_4l z?@>cjEm-$ZG{t?oE}2I|X+Z(@It|S_i#~=czNhH}`zk&&`UrtO#Ow8)9P8}!ts@d6 z55wlq_K`NZt|ak{`x)r-)mTU3JN7sG+K06zt~L3DkhCQGU7w@JbtbMk@g3J$NWZ47 zTSr`ja{N6HYr3${;-P(xazO1t!I^>9nh4jDNf)OfbJ9T%{do=ch{xbHAAmkE4m7V( z>+9q-LG*7Wcnx@Sl-KMM!;bC-5BeltlZ5yG243^cM6rWwuaqOk_D`EW=^})B(2rs} z#=Z~hdMB`kRtWkrYj*;;3{Z3i%t5dx@8%pze9@Egx#hN#vEXA8NPDy)ME06Lf zu7jO7Z;I}rmp%p@|HjAQE%YOG5WCOW-`yA!O0KB>=34CVmy07K!3TZ~9#BcPb>BC!UKxh(40sLJEZCRo?8)z+>AnA7pQT?D?ZvdIr^Z1Bi z?e`|Xr%%M4hHr2zo_F7=wJpdU*>|*e%l?9`I~9FVJG`W`_FGx=um@#m1N0%<{og?S zcvb=15R@{Zzdf8f1;?cA z7ZsR~U)y+(>3pC(NceaVEiaS*bGT>xBMO1h{n2K!X3nmfoNtb{GITF`)BAy-N~W3yWlUo4|B&mlLXjs=z!F|w1$qk8 zoj@3?tS*5%0xDAUbVZ>pdNzr8m}f&O>x{-lgz?c>R~XnS-6Ep{Uz**d+GPd;VvpwpS4 z4^s+q1%g;I>U`5v#xYN)j56uZC8Ms==@In1-a60v$CFXe{pB^iU#_aIHi&hPRn$8g z_?nJP9GM?M=^7qSMz!nmb9FouIPrhS^59Z?b5itsvT_&#UQlC z_UogKL(O;9IcT9I|9iA=(00Xh7!N^Ct@ZI7F#11vTMsY!_7e@T;qSxVgOfS<_5ysq zX@BS0Tqt5=tq?o0Ub`N9^_!oBo$Bv!7Vu7-6A%F3odjOWvwB}g*ghnydn@iwAzi>j zU&Qp*tx_(*wgZ1cX1c`xNlEI)L*CA@e^Xj;dEZF%@etRhYvQuTPh_ zn>PSA^pE=$aKba_e2sqCx6)cemt=L*9#H$8VGk0odw@sC+?N_pmvp`sAy-(?~zi2y( z-DYLa4QCZg{0jlxXSo&bM-}(senfF$c$B*j_o;Xu!Do&8RNU9sO1tlNoLNnq#kNZZ zM8fcc=e`9$>{Qz>xfai`36Hua5~!cljedG*KV;ho;Dq0@I01aTg79H|eO7aJj>!v` zbxw|pOmM}LQA*u)j(ijU?0L3Qug`{)*V(>cMqgIt>PfK5Hu@iHeox;tTW0!o)yT_} zqbd7t%>3TOtJm?bi4*_&IB;Q@ofOJ&D_T%_OOReieLg>6g=LII$C|}URz!Vb2*16? zyrD0S@i#KgGbr;$U1jIIHlX43!LV4NSfJtb!LZ?v>-IVGF+M8Je2kBZGoNlNA3bG~ zB_?Uv!u+*6iK@vbY?l6H-;Dp+dAO1F8l4zR{V(b`g!%h}MY1OGb`7U2CCUt48yS1K zhC4@Gx5lGR9t||wqtEf?;pdxvf-c`#oJnu$YYKEe7wYs*9mz~?&!r<3>+~jn6OMBt zM89yhKc0^CqQ?JRlVP0n%+J|&Mjfxq59tD_)05Yk_M85Trz4p&P5y?NS(mf^x6)Z~ zMZp)~T3F8$GNL-tq&V~Vt0rEsjx^pPTEDD|AD$FmF=3T|=ADTYYu;KgX{3IAw&J{nv~3(n(WL8_)V-y>3V-i&a|W&mp8q}$7jE&5rECT zG^b`bo?j{+UNhm+$u+}J{;-wmv1=tBUupX=WmnTqOMMxYU4Bz(r#|}!|Oa|;-&%K)%fA*?_vL4B( z2lMb0C)ZR!N1U_jg_*3|6{uT9rmv>)@Y|^06*YGse)|THQJQJba=)jB`M0C~?@qdR z({|K-F52-7+95JW*R&jd?}pjPt2p!W8kU)zd0CB(PnN^74PIHM!7a;XeTZY0Ux7X_ zxUK+<^ls)6YL#VFzB46*&5zjXS1y_C%K>ok?KOVxF(S4f*e< zO&?EIV69DFl%@9NET7M@s%q+gOeZFONE7EPD_+#)e?g}=fwTPb8m`#HI7cboe7fLM ze9zic8kO+NikSJd?N6rs1~_+C^J;f%HqI9Cwbju2(UjfZw2Pg8}L(Ss>25c^SDFb`Su2`=kCT2INk~S zw5 z+s}@3q?pL` z?S;?5oYC-a^rF2*m^aslUeGJ@r@=RAs#h!nkHef*%%6tyPNu?l(F@1T-s?ptzz$g8c-nwFQ2G^>81-!GL529}`2JR|exT>iF_J=@Y zSvT6X6MZNBx){%gcK-xv>^*GCpGCAzPWHEz;CImNsb+gftMr3hfjW>bxzA162o$Zg zySgWHJzc@nneFXZm$3WCoO{A@!>Hd$l&#Kr=Q@K*6Z*I}pYM0!JO`Yr4dS4~D9W^WwF67%ul?9~;>i}_=2l@`YN7axM|*{(3?b~Sz+ zf7#(s2K?FN{TF~klOFBaDUjCKLQH$?Hv1$V)Sf((E}+{KK-u&&Rc)sKgsKqI_R_d%2iCcW&9z+w00ImoHzkoKPlWVj4LRGLF8M z>X3E=)fWn|&4SxYyJqj4(_Y~>ctuD#Y_9nl&ivUI=DJejg>XB6vvMKxT=tl+AdSh(N-iEb&-TaDv6Hl3`3*bM7-g|+J;eIOd{meJ zfUX>Q1aYCWJ?EO0U-$pH$_E!)uyDos>)4YDE_}_Z${LV<*-E2hKM~!tVe|s(kzAMJ znhU?zLmk`rZEq_RJy|#p>*vt74`IE;_kypf2zs0kx~dQR<^}X^zW+UR0KTWroy|B^ z!R{iL*a;d{dg;i}-13W|m*N+I{6>{F@|+CVxYBTjM_YDE@)Xwye_Ot|G-dbDK5<9(Ea^T+1G9G9lP@1@qz{JqrC)B5S?=9{Kx zR{lcnYjHupH97|Mr|cx^`Pl1#`r%ZAo$#H2Z-dw<^-Q)6di$=bobF=il-N_9mL=TP z9l(tbc*w^4sjoqQM;y%0(_9EmUhQXkckq1tUEdTvkKrAB((z8|HeIKCcRUVQK+Oy0 z1fX|5kLU0#lnuQ!JWKTK!?QsCEni0&(5q3#e2?_ucIov#kE}DliN-a)a8qfdc-89< z(k|q>H}k>pH<8z>%m=4JN1g%QdNu0o!MQ@*uk<|nZY%P|I^Ih-JEaL{^dB8V7}D^4 zG2&vM(o1{>*V#`z;X9-EwP1em2G*Ves2BX0^N6P)?zfcqd$z9hxA}mlmRo@{w4voz z>in+Oa=d4}0BDErSmqX)&+t6H=erPG4%t?;5q{D_`n;y+0uS@p2G@fvz{}N`C&_2T z3C|NfO~6m+zk2gY2d2+VcnUZ%_gq6X_dI)I1L(&*b39;PaC`y21?xYCeI6choagFv z{h=57ty<^9T&Ws8k@CuLk>XAY%^g1NM>mlsi^cHkjD8+KJ*b-t_|T9Z-SXYY)-Cq~ z#wnveur{IS+~io}7ZYEA~ZDPpAHm zv!AM4{}bmle zuj1Lp;apEM{4{2Sq1CZ~MJrfXSOgz#t(3Pl zw=XWku^hDoFRHCtc#DKCS9eR%E?&+#UY!C9=bAL}%!_lOf$CQN6K}kn`8=+`XXOKV zE-&U|&%xfY;Fby(or^QRJ-39Mj^<;pk>^`*doEXJ!R`3#zmzu81IcCje&w**bFxP1-z70=;vdD||wBgv}6BB;51s|@W$p3%^ zr(w-pp*ZkWdd|RdZG3LC;CBB$ZNY8)EYN(5`9LR*UQbzYyC47D=h%i%n}%w%n8&zt z?Ae@<;W9oGd<4p%5~<7J?s5&+-KO6nunjhSP??AI829{%^G!binXz7!AN?*}zHUbJ z7319cSL7`|~OuWzUz`tK}@&w8jv zcdJ_(7KSMSAn z^;o-TzNS96oAbppE4N4I>+~BnYY&{Wcj-Ahza_2qSo3?|ZmDPcJ>se^>YUJ9i!k5o zg06{uemxEFZQKn#w+nh|2s*c#|EhHb%tzzQm47Se%Gq+Rtm0y>l=lJZ$Iz^cJt_Aq zsx>mM$r(835S)W`LyzWn!VH|gsX*Jt!^j77b?n! zIlVOtI<<*Qoq93OXT=$?@So*55Zv3Z<{H@hkRN~^?sK#g{I#l zn+M;^xn*KxHP;hQV+}05!IgRhb>+FL=36f1zpV#qu=aAIH~$3YDERJr^%0!OpNX`; zL)~C!$ge%A%Hw&WCcRp_QQw1M`mT?AuX+^kw=CiLz3%Ep_~x2AZCQf(8}j+O7;#;C z?yDKF_vAq~PQ<)^D1AfY zVZJp5ah`s|-FzzNw;86tLzv5pW4$}L_q;E??%zMCwm*cu{0*KF)j^cC4P~_yDfVA#tzXBOba$G+WpG3dJ@Z%;;0h`9lr!%-=+=4Ru37L3O^*+Q%f)L%Ncn$NuV zin-OU+;x~2&Z(%obS`{9){V{HlaZGo<^+&msVjA0^|#A5WUngQupPe&{QiLVUhsj< z?u)Ch$C!Kz^W7mRb1>pxP5Tb|5aV%f`$@I7d}5S3r;_L8n>Ab3(}OgdvF3>H1kZmN zbMDPp%UlE>p>{oIJcv0XXmu{_G&qa5^bxGjCb13ZYvJ;(6Q~Qk2i7%W@Ay=aSbY?@ zZU=wZ>2^1H!FMXaf8Ie_oWb7eMOmy9_j$L2e|*<9uyo&R3%l=45JO*lZAo{)CDy(4 z+Jf#e_};?fB6;0j*u|EKq3e=d$r#&1@k?rb2W1a%U9s+MUG6VjqII+DqUt7$TT||k z`Y&{&Kbm9a|~kNYehXufNwzO~>1tt(qw zmS_0UZ7E+n*#cXfp>f)f%zXoFNwhb4)BPv?avfaJdKbPAU~EMv!9T;=Ht-LiiLh)l z_H?<$Wb?fP0lL8R4)T;NPe%21h}YmAepKbjbz#Lf!3&R{7_d15D~4(B1NI-l5$GUl z-xS~vrfz%jPVqnTOJ(o$_4b12rstWu1z>;RITjpuiocG;SXcYqSSQ54>Rr6!SSO#l z7P$TyaDF+$yAf6*oQ`l7>=rzy=twTc8Svc#d~@$P$BF3&<|puM&Ko+ja%WWTv47d8 zDHryf zR)4F#3j3wZ<9>Vkon$Y_nAg%E+FbY+D(!38kfD^NhfsDf8TKUL3ghGe+krLyy#E9~ zxCf5-S1^%BUyp9caDHo*u${2eBGFFX(-!H^QRnQFpPDp)<%b&}$F~hx_AbuO$=c^t z;R2TmZx+jH(U#hWH)p(x{rf)L3twkOFKllowuCamuy?iRbY|e3gFz>je{Npy$A7h~ z%k3IE6X)!}7jc8Ahm95A0_d&q?FTJ3&wu+{_Z`MJSaD{2GujiC)h#PSZSAlbGX1V^ z4jsE|1HMJ@?B-3ozL_>QdzE-_*WU~56~wn;VN)!DZ^%~I^h%I^D{P)y|4Fn}z@8QW zT)@8AHL&~10Qv~yV1MYgY{)*~2s{UUT755M@RP9Bg;5OiC*2%E9OA;@#q3#Oef%HxUd26=nKk3%044bNkgW;@^pU)=t8Ri4`Ypi_UGH)@14){TH@sw>h8-A>lJw> zzu~5Tp?6WoAur<|ri%KkdDvf*x8;&c#sWTvINfr|tg#g^)j(gG(};K>PwI8_i3$Tx z{mZ5ziz zxm*wA+=6E}oyNYZb}dsw2m?qn405&Il{}d`%A0bWQnyVQV*iq-QWsU< zCH(cHsB2mPe3fJ1`=CMc1Hm8owvh>Yt_sa14{x#73_+)H`1P+Pzvi5Xcz`~T*9BfJ zp#O6Y6a>E(;6cMs#xBjb1=ln*-!^(O^&Zxp&ukO%gDELqNZ++p+G$H65k1n>kj3taE6P$Ulg=6VJlGa;TVp5c8)ihatrLNrsp|F)T!R zZq%U*x}E2RoF?{#z_->yNst9tM=FC)*}c$V6DTL31GS)^4tZSr!TWGFTZ_W^7D1QY8y;SzT<^(VH&jDNNtcBp*L&kuVN@O@)7 zR|_ED-IzaB;v9f($PeOm`zkYUWBXHE-LF-4oAuiO=Bn@+9QulTSoI$0dFjZ9--|m0 z-C`@~VhiM%iMyrA-?kO>z&Iv?`Qf4;*Tc9lM3#-@A^npfkD zzO8-ZYzbuDW$;@FC+*&ZzC9X%-GS-81ioSNrjD`&dYPTSop%U2%68DQ{a&5TmD;); zXKSyyqz;4ULd0Xe z3?K7Dcc2Y847>Li@lKxygmI$g@6bQ$DYp>E%{u^9*7BYHZt?OAfp_wIb-nHkX%qe>;{F=->WfbuiMD&CX9)0+t1-4| zC+f<1J>%&&T+QL?K7Jm8UAXI{u?s6a@Y_+WqYrHiS7WaW^eftiv&4w%BIpwT2W7S) zKeqkH2x$|(6Cv&TdhG|(wLkBD0bJ*|zl}2!&%E;RBiuZjHSQt}Uw{b|FR!%#_gU;O z2p~_}2Y_YpT7+LLczqoBU2)*+$`1Ai!H8rR#Zx+_lL5pr-rUi8QLJJmR z!*)e*k;6|6%{$x2tah2){ey%i4}%5!dGV5(I@G78wytjB;!3``e%1~1W%c>hA^VxN z!6_=bQuJ%XTVj`WV?MVoSzNhX`m^1#e92-Pqz^aMA1^|(6~RTfSC%cQ>0hEmnDZPK z`y)n3X+55v<#?+J%dkE|OKy%~0ehLOP`HktTTw*?!yoNd8w(nYoiHz`wj?esUI_b9H zHl292Tyxex(}LUmJH~?B^gP>w+wtq-z_H#eFP3ZfyV>VOxJ{ostoWm>_TtR3Xg+p7 z9*M6JF-|_=IQg8m;5HtTwJ(+vKcg+U-M`~4 zIBYx7Ynlc3MWOgskp<7T;0rYIvD_RB-e|#dE%@kx>Vfe`TkzQ$?!@za4R_-CMk}Ao ztbA5k@XIauMhkA&=P3(*g%$rr3qHnz!$(D4tp8XG{(%Lz=@8!`kH*il;ulzOyFT~C zfxl?MZMro+fUJ+5&y{+x5pKt?x8QdC(VCbt5dTuEo_-B?_RBO4KdWCfoaNf|AF|*! zA9%`w>swiRmwsSc%+x{ap)g$4}RdVSHP@Ty4SaaWvn8+xgrR z2fodM+vC06g4^^7uPAx3K6d{3ao{&waJwH@S#UcaOeW;zq-U>&JLx%1!&x7jo)^T) zrz%c9^>Olfz=GT3;$;hN)5B>EcaDoBEks#QO&YSD$rjwkPi7qWm^kp8Ex0`{7FlrJ zrLx?6EVw-`9rlU7rG7Y0}k| zR(oe#@XuTD1s2@?M(7R=caE>8G~7A9_G!3te05uJdt8jyO12Z9H)^g4^-`-1oqQbh`}d^|Z@8#@z#R%%`FlIZd?}s1#aVj>=TZ zP{KX<*;l)xT=R}`?TcfQd4AgT6Ofj9PQ=f?O!-<}kG?YHo6wIpyzkfNcz#~je;n@Z z%cL{mSMbu@+wo4EXZtD6oo#16kN%a)?HekH{yWR!vpf2>@1|Rq|A6jrs`2DE&i*5Q zVwJyME6X=IGIy4bb&y31%g=ugOu@tp|AuPVnz;H=Um^U^1qR`4^nb_aGsSxP`AYwZ zRMDe+09<*lW4ltg_xc~OHdrA<^R{gG1;d8{{u2jW{nj2+TR%)yKJexosTQ0S(IS#2 zkIo6rW!fD0hVcxnI^3@TjB8(F>F4I5A{*&v00P*#2XL;-=U{Eq&Y!+s+u-}K2j?$v zA3lAZ-oRR>Z&JP!u(mrGJ_*nzmSuaP#f3L#@VqjyY9-E$6HRO3&+5l}o>|t8 zw!m*-SrBV;&j6XoGr1gLX1jr;rl27@7jzUe1G~wMG+xp$x z^4)-SZ;PyyVlg0(?@`X6Lj#KT`{8q$eY&9&Tw)OG-0z!cSi_$L|0>{z=iSc{uhn*= zeH%r3>Y(=r`FqZ+d`7N+v+bwRj{*4fN7L)?9x^THZ%1%Qs4W}&HkdvD`VEMrDFNwo zBR1CI+2v6_`WxMHrm%4b)^_RBz;$qzgLG-;p7oSJ><5UJhi|w^T1R;y_~-_aXA#OU z<%NZqEc4U#W_}HB`iu;n7#J?v?DjBk&|M@8G-+_MSOb3WFn%GtCr<$LRy+aYss%h@ zHO?#v!S|tJAp8@tN5_d5w#A3<0J6?KsB`IPe`GIs$BfLPNZx1>8I$RXkZ)w;N8h#G zns@Bhyo0`9QJMe^wyXVia{q@-KlBx0SrP}>cW3&s9p9y9o%oJC)dRdV5dUb0-9JoE zKa&s9CwHSykWA?7Fy-1(NwsWu17~${9 zfv?H{gpi9pW6(d|!Np?}(~8F8oTs)is2l81ZDZhHlawslFhA_MJk2$BI>z~EJTJf! zUZY6JD@IrWm^V$d6$?*Z4njlMk`|m}#~P~*=%)tslRZ9Ms0aD{W9ZY}l3&tq2mXkl zYw&{mbax`D5YqL(nr`8DLI*-J#fj4;0GJECMt z6a4NFJ#?T><1@=M;wXKix`3~=nfXn`Lz+ly3f-;F--J)A^y6KD_^+H)=exX&{5&K4 z1wo&yH30r7FfQol#kBOvciouN%`%YZT*_5@9H?_S70ruGG1Pus-D}()cI#smED&k+>5YR zBp!VSWo*aUJoh`hW3XU<*+THx5= z{qJxe2Jdj8E?FYAdNJx20NsI>+O`1ywb+A%_8oBfUfwjnsy`p*OY#P$_I$I1dPLVYDZ zStp4fmnt&{WtOo_;F3Hf8|8`D%Dctr-J8%3iPLBruOkh3GU6`}vc9^!si^1msMleP zs}h`l#CCw^HI<-#6&RnOHCaDbocehYzXbRxM%&p25Aq56c5hl+Ro)#$yI12pFZ$`3 zI)S$H+0NAnfv34Hw3Y2+n;E`=^cC>+_rlLV7eCzbB{3FS1^74-6f+7CfmJw9qsN{9-g@AAaS~gApG(v%6#MXwj3aVL7;8>q8v; z`o-}fj)vvner+b=;MXrsCgNyV4(`{cBMyH3;-n*vhUMUXZ5ra>*Dp>Q;%Hb7?$;(G z4u1XOBqNT7<=}oT&U4PeuU{OT?VPJ&Ik;a7ohApresQ3Sg0D(g4(`{2CUWrW7YB2v zTn)>?J$Y^pevIRnI20Xgg^(~jcldD6{=FNt{WfU+GK9}zZm=D3_aeL-w0^mUU8c|b zBhI@7T+vU?znvNStHwe zmy3HB2B*2qow7N3qi+m+nvM@$QeFoBH4QiRUISk!;R(_8eUpxfW1YS1>PcTp!uM%-m5xteO2WtM4i9K}zJ{;YaMqg_@x}P{nnY(Ruqe^+ zJsQ4B!{=zYKT!b!8vYFp4{Nw#1?3w4nucGgGIr{6!5vqTxOb@6vFb`7f{e8vc6?zfr>t{q$=1J`GRS^hICIq2MQGylIoI#bDt} zsT{>|oH)LPQdhaW2A+na~lWwsePF_yB#d$+fxIHeaEVx~td@VnjPmW3||HBqM z+k!uC!E-J6(-u6-f`4Ga?R>7(^45vxd<`c)M_c){Tk&oD&(?C-S^tm)x66Ikg4^x2 zeJ$Yt_^2H3y43i55bhO>WdxJl~L@Tji#slT-; zzW_n$I1YE?mMn)uH2g?Pa_`Aq~JCS|G{lb-nFkTdBGd=6kNeLI6fvLCs ztVN0e$?$Pq{uoVv9MPPNGd}nR=(I9Md8~6Hqj={bYM*0Az zvu4li&T`SL&f)xN#61djOZX6&HAJ8)<~ry!#53!lMg7jM>08s4c2d30nzhO^7BQ|xE{Zzl2U589gf(Q;`DNHKxfWylOW`(~e9PxMY7EBBy}LVK`wc*jJXdjuOb20Pbm2BocX%>zBI---3(;ykXy3~LRo zxO5)d!F5Cs<&N?^RZbA?D_->-wQfF+>*jrJ#y84(>c(Lm6>%BQjXIU1uczGTdy4%` z8sPbf=G??IFZN-hJptHt_xRX9IKKgXlZ|gQuxu`96i>Qn zV_K{qPWb=0dlT@esx58!R8{7IBxFtqsmee|2xOiJkV*nqY4jpfE3JO1FbIf>5xAmg z6GU5Ww3Q2dsA!Wgw1V=hEws{V6I8DHqt~lAw)z9C_O4nfa$2;# zPv8E}137ixv-jF-k7w_-)?T{-tcx zD9Y@{OtIV4VS=RgD8|Tw<$l+1G9>|#u{AS*$uWd))a3k+N^aJ$!duQW)UVi&j zmcdG)tEcY`2*H!6n@KUku-`i6s0X@+R<@5Q*cbeD+IBqeUNY6#4t-v)Zz#&mYb5xF zqAoI28D>EL0Xn)5`OpSX_X)mo>K&7J4CL1m6|;uC(iakShefAGA4cnY25yGcq7+jILum#< z%2oOcd(Jw&&cBg1XdkE$<|ty;Q3u$eI@>x_fiZb{f_kkEKak=VlPBb1KK}FKnn8SG z{q@1Mfm-I6;qEg3VjdBMuTwbbsO5%<>=L+IR+xz0e$U~E&x>mnIepUgLHZK+sqn;Q zJ#{HOnE#g)9?bvSf{x_>TY<|pu$FZP^K+4EKg4Bz-56+j1@oiV_QCuVtMH^F`SIG& z8L#kQI+qAKlAp%}F4yGm3tY;c{-@hl7Y8kRf*x(xaC*%?T-7V*%4`x5tV~>b4Pv*3 zyDB&#E1F3|{WNdI_)D6q`2DZWHNIZM1+Rg0eDW9DYb~CHp;l^(2$m!d5vti&|YGXR}>aY)M+Z=*50-vFGUjd)# zo1u4ahi@e6?-vioGj#PR)ajmfW6d`Fr!7_|Xy#zvN4p1?5wd!dY5(gwum!XY4<~yXT-?2>Eu?Em- zZ%5h#twZ#jp7Z(Rt{<;A%yZAGx2{Oe<*j<_K-qSIU$?5a4&;UWyH&k)fd4M=>{j*G z0iL~h)_m%EL%uZ4GSb|KbPd$yKzU%9It}M)wwY|$taWcN%hX)cu>F|tz=!`G>a`1g z7g?s}JMiRxhdS-XIRz|J^Bwrp?^vG(-f3RnLz$|4mNB2kX`IJq<+F_WY=`Z=%4Zq# zY2aDMeO0xE0r+m~?m_wk^WA3f-N1ae;k*VrzT4o3&!6@>q)nU67OWGs?11Ywu9I=D zb`kyTeuuu>YuazR=ufQ(9T&FAXdie_e{DRg{eJY{z39u!oaw8tLLJhsl70=PEvE~0 zX0CmeJtz8q(qSikPY1#RTj#s7t_OZ_+uW$}L0(Ke*A>4i6IVAvYj>OxSvNqffZO=ixz3J&SLlFWLS)7;(-X`s?zyG5XnsO{%s- zr7zA+u=Ubqb^>GC;nYnTEVnI-aqdBm(Z;f4dC}h;-)&tCUtuU)c^=AluFxXbkX=b$ zCSV=eFTI81w_E<+E#H-!#u;s2Ax~?a$h>&Ca|-6*4~JJP6X2Q~|FX|wAa1RwH9oBrWsopi#F9>bBxZWV^l zki!)vWA6q1(S7Pn_UDPRCi>f63XEa8;m6oIPlbLvEq{XVI*mz(kS^czoj!vSx)bZ)@39KcCW; z|5uiM4$9rimt|KST=w+wZWFFwS#Ll%=HD4_o!_C$?H_@!#5n=2zsLEQC}$sh!7|*x zVSIs|@Ko43LN=CJ6kOi_0KcHbWx4C{tdGu(zuHbZpP_A9?SWwfb@7nmhyB8d`taeb z5ys=W5th&5z&SQ4MoRQ%;Ozh8E71SxLpG#n8fdWJv(G2S95lxR_V@2F@A&~^O*Jh>a_4Qv!7dIspY#76GO8f-H-R| zOXp)u(0%D2(AI+c(P5;6{%g|K{vj=l=i_jUwtP^gfp@I!lI+9N2V~}sT7=VaR$!d_ zr{(Q?9PmMD`Fl_Dw^907x5fcWZcCrX8Af6>d`Ikh_V=UFcF7m}E#p{uvoQLo&D_y3 zC}lNtf0ZncA+g4;t%&n1u$8V<6_>u{Lw0P14{(Or3g5bz zWlZ`6-^qOu);=8v=Dz=VzhfD3JPGsDx6-ugj&0X^9w>}eUw0tP!z%y(<_g~->*-;P z<+86ljP|3S1L<%qPr^Q`PH&zaHU#a2eWlSn z2f}fnb-CLdZ!BA8V;#yhdWWKca*6(D{HBfgyJp`=+R=!)+&;|P8*epwK5;sZ-idij zHRyBC)OQ&7S+)#o&7)HePgu5E_He-C?Sh(`WS>_nH^2Qu<41_FuP2ma5 z%RrNRe7aFLohs}tH@5b09=+;D55hW+dJy*2KL)~{S^o6)6+;5wf1c-L>K4%Vd8U*0 zam%?7zqxaa&}jPUKa6pJ-}G6|)M(bbwYTNfM^KJQbBvHl9Q%FvUZ2L;(t&pE#-6Q{ zsQVL`C-fpNzsLVM^xw>+Sd+!*9IqKWythjQJ0S4~edI8RmG6IRe@c_rq9c zVYH*HTM>re;^$Dl97FC9W60Lq&;AzkY~v%XdD4qEI#)^})*GYJ^KL6%>C{mtJC zz91J%vWs^FJX!JBchW#loymbV(}B1*;yb{x#k<10mcDaWVr^xO6*!04=``nYf%7G- zGlrNJ%cKkM;Y%9yt^7Kj*ux7yvQ0+Pr0yo}!$>mcL>%wCFemZ?*o?T$n>98JoHx$# z2MQOQm%Ru_zUM=C6p8Wuk>3wr-QkQ}y*)P!-;4RKWkG5hB%W^mjpV+Juwu`#u+0#ga@ta)flV-Zo z&HQ)$zHT+kfH=?oU_0UWfZrt6?+X~i_>MZ74z!7<%`q*b2=gDzN9aeF-$iTQxej9_ z{i0iKEp^8}>_OIZl6EyGS?tU(=Oo-G^MW&R^}Z_?oBeU$l@&j6PV%a`KaYLes&gx! zRyn1c<<#U#o#b_;MzhX&#>gWW=RSq+YUWq>l|Ia;S?2BkI{8M(e@$At-LM_$aC=yv zh*uZag|my&7q-7O^G1$SOq*%44pVefFJEOemn?nPhThxMEf`}MNN7;Ud({%@dP9>V(1>7xD)b0YjEzrHB$ zXX$_Dc`M$X%X#E0z;ip!NaTE6&rv|@*m3Mhdj~u^kfvTcU=6;DYrMT^2QU4&W{S$N|iEN(L}%koE3s z@Vo^w0P`Kz|B%~EAzjQ-+G5RjO+D+(^*`rooC{lXxKF{So|ox8dX$s=8|IXpAL)5N z=ljeDzuSv3-#6#}kd^SfjFZR@<^ntT-L}>)iA76PTUz(Wn-8w|YpWle{C(BxcdrP9u^0Pe4|bH zU#sv>xGV~lD*RwK54-4m@^EBr`q7zHaIq*4@jpTILpDEMDAf{ zZru#bJxpBN!@2QnUP|d>>iVtCB8!*K;{FW1#Q*__aL>bHS_ZVvnG^Jyi2pUcNnf+* zI{1oaU_SMGbyiq-#a@c-3coS8Ixsj4WoNb4YFE{u!Tk^Y`C%}S3oL_!{^kY3=)l|}g5=?q8arytT_buoikT&yJ?xhW$}o`t16DB)SH(?T zc(nS>TeqqQ;?|g8y&SIEW3Uau7=<&uv>~`m;If_GWP?9wgLm2B)74N#eg+Hv_5LyP zGf3dOMEFF3f2DASS54G>8>4iT!MOH)9Bgx-?c9TH1?CGnQ6k-T8@$5?f5ry?LEy3+ zV$_gL{w40V!Et_wc`>}Kcb~vzJ6R@h8UBdCWqxDSI7s>uuN1hfm#YM>hCY+OyKL~s zZ19%^F6qB7aLK=yN^4x?Q`%}=W`i$LxNZ+>_%@a)T(<{}cL+MNJa^gPf3U&7u)#xA z;Re@xk_}!fa9Iu)30(3Cn?!&4Nc=8=OFEC);I9c>(m5hZcj*C4ozRzOun9)klc@%X+-T z2EWe+*LMD-Bgc)`M0i!SCZFF5Tr~|7k5L~#(vjiY1x^99zNByEe(8$vvV1~RCP`n? zk-n8>Ih-%TOMdPWc)Df=_m>1N_tkwQaJgUVTY;;s7ACbZsI8cN>p#<`3>$l<%-BeWfNH|&a#Z|tj~%$E9Z%Eklxy?n5> z(eJ67bwj2}*`f9$s^ztoT_9}3;3MsXY0F^g*FnG1I?u8{ZSMD?>=fBBeT3>~?m_DB z1CRM|fq!_G11-uEwT!$QeqsmWnKb`9`SgNMmT@=sVVygF{p@0ujUDV_O*=6sbTGya zo@q~;29|{`1EjS(33Z~MA*1f6&(ZtHD1+vHx=zToExQ#m4$B$hFz#tomX(90Bb>{aa_GvMuWRW?h-G zbm8xA;5NncS}nTnU!+Yre~~stdnwuHl-|O$eRM;&W!4pZA0p3YzoEQc>kPEK9_3f0 z>kqoph54wXyu85Kwl83>+aa;n?Q7HtbxMyyxA8XmGul{@?zc>@1Lv0RrryY`PfMRf z-^|vTvR40QI3Lc1rjGD6+M|NM_d)jr^fo+ySkiOjEK{5lKZUrg8?&E7zd_&Auwg3V z-aEE;Gtbx~Xtm2gd(`yI&l6q+Yx>6LB|C;Dacd6wu)u+6wbre<-~Rg z9i!>%lk!K5y|aI*y>cAe|D1FPU>`sxCYV{aK0vW1>9f8i=RR{r!_(R;rd`8 zJkJIn0i5(TT{d!F)%Z{R59SjTn(BTY?gP=EY=d8HgF~NZ($7;LUrql?g)dY11$gGQ z9RJCW-beL>i5kY=;64yPYi;nqx52mD;7n&A`cDHVKTFg^g}N19FW|pfZVK1=dK36S zbUsqy^?ocJ{+Lbp9un&6zkGcP+GMH0$!pmg0f_$V8^7C7^z_w}r^k~My16P~(@ zfzs8JE4@$AfBvRA+!DG5Q|`ZX7H>QwQX%SROWV=~vlsH+QuRVRZ(0hChmO<#XCRI~ zb5bb~engva_HmvX0b5rsp1^F_5ZqD;0PrUM;dVPHHVhkXJ50ah)-X zHlOGP3pdkk7V2WSst>M3qttKSyy|xia4B;cuW;6@#C;;X633ay91&jP_bHs|N;=Oe zoNHGlhBc8RBD`Fy>vl{!vfaevnHTABU7;_p!WmxjGe?A%>E2}%{s|FY@-O#a%H^ik zy)s?395GpnQ2m{_l$F#9T+0<1LGIU-d|oBOOBoa966QtvlFoAqXZgr_|4M`(VnsFo z#;b87xL#mG=%+8kpD%DJqnRV<$nt+sgm+sc&A-nH+#_)96Os9n`1>lnmeuMgA1PeR zYBm0qpr4~b++#wl2hz_KxLe>dUzGxv`I5RiSw7lFBk9X}d`{5G7wL8jT*~IY6}Va^ zTd{tokE2n4CO(V|r90F`pt7kSZDlpur<867EL#-uS!;ck6>(Ml_+?$*pma6Pu<|O# z!$7i{bB$ky_@r4biQ>18FWUrz==Am7tFThO6xT$>|BuOPCL)feC88VGpJV0G4b6Eh`I{0>fw&uXaY7gFn(A5p|PHnA+uRaWCx1veuo!JtP@C$7B?o-?(y=Er;h zRhQRQ|5RDcec}V)HFN33Hz(3?!Zs89-1`F7M}Y6e|24Nn!k-K7_?;xzS6mlyUG2SU z$TS3Avl-z~7ztb#A*|m&$`RmPW9PufkEfsCo}_+$btqf$K`zmO_46%Z#+r`M_Nnbo zqplS;mFQ#l-ikCluw%qtyr~7SGw*~ye9XD)xYv^FI{J1A4Tmol*x(uS=fU6m{s+Q_ z@SKXUBKVW7{N0f82PuOxV!XfooB3DNUXf?i;!L4hZ-`MxnLsY+ZgU$`_PUL-L)cfz zv_6NQbJ`cueon8Wr^BC&wwt5;14U{2-JuOD^Nqz>wBu&%$HAFPNilC{7%}@YSSI-1 zMf+gGxgp9(SeIfXoEp@XaSFcmyJ2t1csU49dsb^*nN&m!<1t4z4XWLFFE$dF4U?KXhHP#$KSjY(0P&RS+ z?^=489%V|w=^(FFv>iSKo9Aa#9PZg*xpI$(YzJ%utp8rvOt!+N7(RZcLQb7TIf2{o z*7ZWR>FevO%-#iG^{{QP!#)h`0imdPodfbrmZ#I$`j&g);@TeAExMQamU+W`HSahR zqffv`)dsZV>%*)wN6bCvkS{o{A3Cjjc1C#vY;v!{o^H<%Xg{!V_2A3{6N5}A1or!| z^L#5DZ7tgc`3W%JI7~Hf3Ypdodsi>|!Xca?kn@^*^&zA&kZm%qXYB*8`=eWvv?hj~5-_sk5758J^#F)LBO-AFU7*_d*x*LX8* zetr-7{+eA#w>89yJD+quGNv2@2HvOg9FjB3|Jgqd`0F42{`3f|4Ir;m8`HhG)%OlXeX9ja6iImnVPS+Z+92Uqx(eQJf*F8zcR&J3pxqRiwA9hXTj8k zXKZXm+q3q>ShVE+PnHGBed-Hlo&JlzPW72KIG3Te1^w1ztbG7`wCY;A(1#(<#D4a= zrezs}oA6y}@j2Qkul7Wk-^O*ANL2bTR8HyjIEF&?&~u8?LGd_(wslj;70v9HYme%B(59yiVN z))4kL*u!$%(NoQIS>7@}+Zp4!@%^U3)H<+S93|1s|GV!P)z z&xtx~#5a$))U!zWH1!LV-CN~u`6T4n%`sf-Z5;THpiXiA6mEboOG^@ zu)wIq|&`ar7Opmyk$II;rzMF40@s)RZ~`7 zVa#cTBWV1pq(Bv?0?fx-<@yd%6bf2@#9lLOXcfoHg<8;J9(mb7@1&(cRxOQ&KtQI(?HtE7^A71;-;rrXTBXM=60gdVPNe9|& zpAlOZ>kwwTMiY3r{<;NA=JKTpwOj#tGC6CxV!>5_@sq9sd7r)HIvC^Qhd!fW(X~r( zR>5Ljym};Jdyq0S{afSFDuS+4%J3LQ3Hxa3pHswKWl zgqQrkCUC5;{nrVBOIfv{#wGG2W!0EJm=|#w{w9U%{AwGrc7^NwYW!Y7N7pF{KNv(u z=dB}%j>caSbfhf2N8pmamPwQUOe-tq-*sv{Ca&8OU(8Vrm$}u53Ix7YgdZ;OCj_1=@aF`MiL3w8``lQbswtW8zEI)yc_2E1J|~I! zmEl7otq{TCBNVRdOV@FX!gaZ6e2BtXZvL_aX)SvVPWR{Ai~f0?t5B)(t;<=KEisNA z#Ju<~uk)3{@(b0kqwo?%r<uDfMYo|HA438gNy*A*X3Z^qvO$^ zzm`=)R#8OxNh9PxkQqYWsqD=l-yO(5y94L6Zit~A-qM+P!{Cn{`~UTGSEx}1c}W6w z9*}85jIELay2a`HSUq&;>b+F?|!l`XU-fH^xDhinOgVwq#9|{YZHg z<&BmPLd#dkqww>!f_9^@1@yksc%vK7GjMLTRgcD+-GA*$gkP+poCMf2nzo6_6a$!Y zS2yff;U93v9K53*>yT;-lr1sLA>`$swm8;ky^C?gC~-hfq@Phfej7^6N7}xIkJpxH zqwNr6%+GFetfB5^2f>-w4hHpV9#N{W_fY9gX(ng{*fv+J_ry`kY3c zFU(tK_|nUL(B&X(LU%UwP42fde2_sV8I@5>5axZzq#b$EL=*ZlkvP0nqn3;XCWwmRjGH)wMWdd=1-J z_Ez{ILEcsXJI&_{9BspKM(|B|=D8m$kvFq1x%XwXf?tfz@W)})Q7^#!8OR4^b{KQ+ zoekOCku=C^(SGTZi)H>U?yxB@fmWU7r80aJQN)>ay)ocxe#s|A?E0j;dGivp$bb z6Zmp@((VqW%T@t&tv!p7uO~dzsQ2kJ?Uagf3G!)0H^JVe{geh+}}h z+SL!@Y8hZ6j|g112|~}<;9m*6-#i?2c?IV;MB%~t9injZGuVo1{w)@`r0*5D43CMI zd6A9`f0Ye>MBuU<+-e*Q=08v2!TjrSlj$Z3{_$P&^CRo=T7gR$TD!od?CUOpW6t8g z+-jU;x>A->DeyFZXtXzhOBvJ!0@v$lM$>kV!R64U!Uvbb&s|ghx!Cu4)wrjNEa=g8 zEq$Nrys%L*FRq!`v~-`=bzrxaZVyh#B4g4}Kh0aQqN$SczdG0WWr#t(%Kb5|A3A<*e zjE+sP)46%=ESxpx#(Up`x7)z{TG~fAU<1K45AbXP z6|Nimu0F*aee1H;o~DqH9kZ5sdT#k)#X-DZ!!;MuQFb|jHGT!?nCnQa@1MdN*#Tad zrUzm3z(Wn}Zs?63HeF*O8>-Z9EI=lNnKdG&?n+vr(+@P*Qa+u zHqZ{c7TPX^7~j4{AGE8G|4*-M?eQAkKN`lZ4>bMIc(4g}bhD6e59|gRj=uUH!`f{< z^4|@9xeg>R;Atw$06y*plnaoqX|EB|w1efyG)R-_(66Din_ymFz?$DPxP9tYtWVK5 z%r(=eVox5^V_JHBtoOQ|L^|4Z1Aac#`D(207Z-35FYN3%};0(DFbc8k~fknb0O zKa9HvHd)#4=k&aQbz>LGiMBVPSRd!2ezw7X>1@Nf+7;tk-RSJ8If6Pw_&2XW`QHKC z%->jQQ@!o77_8hbw(0`NmqKB0ITPyPb9&>JO>6rx^KG16G z#5$Gq7*5KLbesAVd^Do0kEHzPWj&C*hqf(lw9kuC)@*~vQQm#nQ~4KYZ(XXbYS|BY zClA^eZ4!JZ8z|d#|6wG20(-4>u<2??pJm(ZKwdjw1GWjY*dM!428Yl_Uqt>Eqt13A zKbRd%+KlJ|0jl9ekj{2t7(Ul7V-t zPWSC*Da-okt1CbOR2;#kuKJ1o}%_@uV_#Tv>3 zLhw8heBAE--2;aW*xs(p?qOZ~$Hv*e&|(`6g%`)*KjoU+n%4!7^k&j1Y9(B^9{qoR z${L#UQm*0j^}hPSd77M~>-YKiVXnCq@U6P@n>|o?u0a_76_vz%b^n!3c)Kz@&_Kx*mZsP1dgfZ8mW-R{lFF3&muUoC# zS!eYAxayxn{Wt zgFmm}bf+skI9;E@NnfU`_c#!j`F%!&=RmEmi`3jLn9u*|Yk`iSIcd$_KB99QIZRPq0F*8=GS z51Ib-by{qLs!3|dylXx7&s__+Rr*h;jIwXD4$pNhpwGH%>&I1~{4|VFj?MMH@xe)p>?ip*`UDSq988~UZCoIB>c`vB5;i@qA3#@u8#=22W9G+^FF zf7YLZhuN5)G`;3oJ!}3fb3W$59EEEKBk$b@=>MS=@4459G-~Hx-$Vb;Om`M=>Hyk5 zH8wWRujx4j`{FM+4?%jtK3n!#{@;JA_pxX@-W;RrEzEU~E&wmI3npEz5$OAYdEztk zuJvR*&l=}P?J!VAv|TsAYY5gq-ZOnQn=!}bbMyQ;J-1@szWA0G*UpOC_rSE*92;ld zn^nSc_pC#Q|H>y@qkXZ5X|4 z5uUom+2)+wc_0UQbmN>79X=anm5aGDR?`Q-Q?C#EIJjn6;dCu@;EcFcs5k0!g4Zg{ zA9Z(-ktMNxu}n8(?yK9M_PdjWd{kmDk{Uoy|$Ty zHsQj&74@)Y<^0*$^W#{(a(-@4gOPmHi8W>w@`JGhdx==r?QdbvMiI(j;RVo7@_q<; z@L^7kv$_|4jrlp#1}$@~;REgD_p5uDzkSrbsrJ!@IWqU5F<-NgCziWze}|Ed)^oBA z8fZ^^-){|!y0F?iXim%yHxS;W=xe$ic;@wM z{2wU%3>*A%;Ng=Pa^B-s^+P&RuTm;- zJue^$+IaI~c(z4->A3`PS%ZDn z{Ri{YA@F2>Xv43+4W{$c=lJlge)ZgImKdY1S+r#CsPle3Vsr?lYMtTs)2lK7~{ySs}=-|)qYGqUs?0h=j0utgL=(`E%|&0_PhD#g694-+O>Fl z5oQ;Ht@Gg=8UJsb8{_|tb7J&wb6$%*YMc)uPLehM2*}5iARor&(>0vKQwFKew&tF? z&5$2+f1wd=&F486>A*VSCE)aXM%$--uvhb8-U8a@UhskBoY^-S+p}+S;J*|9UHBie zJ$ty(o9Z-ne~15CcIX>q+TiW#O!4knX~b7MlAtdzhL$^$ICpIy>>G`k&e7?AvJ++4jPsB!d!JC0tC7@*^NCyg z`gWgLzIXc(5A6J~zpxYe<2;RdL_4~7Htdg>SMW3S%<_Ha9!UBTARWj)-y$6&-rLJ^ zhVI0?8y&_PJ{xX@yDeO+v!8I7dq-i*)wU9H;+Kj8<&XoNf+Idq{}^MF*hW4;Ig>W) z#W>x!8*=DlbE3T8qa*h79e}o%Wb&!nvp(0)7iIMRLDAq@S638qO_Gd#uHN2%a2UJh z4)gZT#eLQw>s+8Nqv2iDZ>3(t>2rd#KS>>qJaIm*`xN(FYhR$V$OG!%KzsC|Zf}K+ znXYfPgF|QsjBnsw>u9V~+hNy<`S%L6NjYct;T_k)u=_02?}-^)D?sxvN8lChPG0sDU^K#(-pK`5Z$yAxj+1H;!UvP;^#*Mq2d+OAO+u)VJ zxmM8ee^3#|+k|I_8Hm2m2A^kxuK><;wJpzdJo8$Q{{zwQ0M77_s3O&2o>KTT3fFUm z*A?CsgnzE^SAy^}3jae8PB}Z%eLo22zEI-b3SXw~O}J~`K+=Crw81a7!LP8vZ?wVx z)&^e>oP1t_j&ELg=EZU}aW&_9#e$8!HgsNA;kDeANxTXsx{(AhxU!UjS zd1>yz4BAxc55)bN{cZpH>v}*?Y-XK){?rML<0p=9!C6k%ae*PzTX4;9=HfIdY=i|W zye9h7vI6vrGY?D9CG)SF+d8LZfoa|756s2sz;6adN$HBKTIZRI;eJ%kMrR|zC3AU# zRO{7b$K14PSyl#25}5;&E^N7~6()>xue)y1btX3Zs=2M#sb`gG=+ye< zaOt(!Dr_#V{Y=eXBumOXe@d34dTlj`A*x+)O(@sW98Y)!;~Y;^5JsZDB;auy= zHTfKcv;WC;-h7282jO=K`f?5bn84*)UCVaJr%RR3HmZ$yA)3PT&L+vuc^qt^=-1=6sxrsamvs1 zg?XNN5zo{h?$~qS$93BvaFf8ZtRUv!`xG9WFD>H;&X<&N$b3B~=u19761Xh?uLLgJ zE#@%h6uH(xw zny+;F`tDU&DPM|fx#EA6!1zwiWBxhj1?Qb~ylN1hDT(5@PFKTxRzrk_ z%=;56eV-!E>SP_Vta)kKAhChckLL?q9|k2D^hir~J?P%$Nt#zrE?est{pnrEI7`rG}vivq#I@@+&mLGp>{~kU_ zyG}sImKg2bgYQTcb(Ec0ZyV-$(y%qfg3O0!u0x@3h5pmBKZC5H4eQ*&lmYmh?HOE~ zOC9zKyuVw}>B5!`#(5onsk*T?MgDqyXTqyV)7oEY@#Bl&*#$gfIB=$UceGJi5dl~7 z;ISjzsMNec2mD*q)x93biYk`*p6RAd9`uy-ooC=oajwS~hpqjq6oi3}d=2Bf!;DJi z#j>Td%A^aJbzTC`g;(VSJ`SN=PQZn|1MfA@Otb4o-!qH<+Q@YB+;Y%tg08*;|21FT zF87X3JRd?nJ;y*wcf2v(6}w;T}|;C2v4R z@jKk9pMDwlZt#VAX=^2 z|1*#*!1^AaJ>YR{lfJdwekvSul=4Dg{5g)&f>ndxw@Zsn=clN@$*YUyb_+7o`5y$ZM-v7&b=4 z3J;zm>a|Vq98s@fg2SJ$=mdxNiF74DO9U?Y=@z)0Q~umJ;(zxUZ@M4p@;=wOp-*-7 z`KmlPRp8Iyxy3Mr2hT75FwlfWg~iQ(+06~lHGUZ=k+0z7bbPlzCF_UgU&D3y!T6;b zQ1@>Y!5^C&HmUeQ(T$6|;`9e++Z!n8D@wq?@kw66@dwH~!@CtxEmP#&kYm2i z|BuZL_1elbY9K*%1*ea>ArABKyAA(QTf(a9vg)5YH!Kwf1YVO5JvV#?XS@aMn;K#N z#Q7oTh4>D%(U$}LI9v^pE_^KP@M12)^WUgL;QXt@X;e4RZw7qOa{l1J9mQtq-sV6T z>4e_NBm8e*u4d{=w9T0ILv8tcc*WGwkskecXGa*vI&nYl%GmL*(3@>-fQ|}!ovjU) ztyNcr0kH_@lOf;*dvmbgMC)OoW2$O#B_3^uy_m+h@2DO5>nMk98q>hsvfZ3pS##7@ zKErm+TV_-;Ej>?V`ug_|Vs3m|{HFhJ9fm%H^=~)C=-sl>_;+^uq0t zM&+!aJa%J#%{=zc6ZKS?W*Ky2o*yXFOyJh~0P7@C4yh=IfNqQBYL%IlZWrd&0s5J$ z%&fBL4w3It@Gda-N1jk_e74HheX?&idkh2FY{vdsT%9q{9OS( zaXs4SbmQ3h(AUvcR_CJ|Woh|)N%vzY`?9~l-Xg4>j*U;8_Pq~nTJylZ_gCOS>-p&G z1@wxb!$cpl%Ek*{#uks(a|e9&bFI*Y{?rLR%szzm0qcirqfXbaw!7k2KA_hkKInJb z|D&&pd*-@eN0|rTCVD*JSb+Ie65Gc+&%4rSrpMAdL*gp7@)?v50;jblV>^K0L z%pZNcZ$`VZ{6br88~d0sKXn`4`S{;B)_e)u7=+LP)($NNN^Wc#q%YCG0j zfp#_o{Ik7U?>deJzYDapu5bG)eON!TOgWzU#G0FZ&WH77*HM`!=~{W~{{Q+a>rnU1 zALC<L8gX~lDY-M5QZ+QZlo{VhrEZ3479yZ zVHa@qS+oNEzWY>PRR!J$>eza>6+Ey$+du28+zR?HAq@KweBz{Lyx+Hr--h3zj{o^R z>-Vdc-x>3JKKmC`Z9BlkpVL|v?EIv)Dc3`CZ8}{oYcqh$H3jMN8jk-1;UzZsSQ~tz z4L-#N|6exv0vr4~8~i34{030fMx1 z)-H(cq!Iq}1OrkBzbQ26Gi9aKRZLJWan=ESWq}j=7z~!u3?^-_wbVl$LZ}WL>?bg> z6v~=mZTn3^!b1)p^$CVz-=-F(pe8Y>nt#vUr>N~rf@KF+sqmCpM5*7rJt1(Zdw50Q zm@D|Nw*@X`F<%H=%3Rz?j~COGvXx?i%l0Aly%N{564H_QMK*LUv%$3tAehcgBD^ez z2L;act-i3}F)z~TS3UxlGM6s|E|!2sh+3PIPLd{$`w)Rk8*-^nhAiBFc|~~1zuf<7 z3Vc}K_f6226 z-F_52C}9`N$0P7L3J;bc&R2NwIB>5`_;ohnA5l2dmE*=s0+;QlTi~+&3{f&T(#aA0 zj}f@+U(*FH%lR^a=L$Mk30#K1Rp7GSb_iUy!{==99)U|brAoHNe93m`6S$;*lMOEY ze9Q39i14yJyA>W>@7m9IaJ`49c^>(c^z#HR^YwFO#D6Y6sPw#6Hxbn=^`osF!L@2I z*Y)>PWyR}MdHNGlKTz!bu3|hz;J+FM{O`^+ei>qrX1PD6^+U&(eU)!?`ugrwSSeqM z>+co+KPD^Yd|uNM(T&&6G5_rA!Fea0Kd8ZErX-5r!D;bXeX9C}{DVs0r--v0ScfcY zUb^iQ8z}u!_3^9^N-*e=)7N>k1KZ96vf?VYyR5XdRQ#>3taQ7pf5yJ^TFoqY_2NJO z2HO$z-~ZrL`yVKqqFgv2|Db$R%R(rV3Q6;R-v}8D*3ghSS#|)BPx<{DN&P?fSx6b0 z&)m<=b-D7*jJ>iepr@z2YLmH_SjjRevx401IB?S7*>>%aadcoW_PeIcETzb@U$DY= zz#d=PGvK>;>^SV-&3)^L*8us(PV9$hRl4{_mr;!{ZFeId?Mhzab{N%`%rX)DS#-N0 zlhWy+&XX*;n#H?ezN0T^D=hY2^y8VjbjCH)!L(ba({U!eM#t%fY)aDf;Td~B5_tC7 zndQ69v(YHKr_9=o{W;t}aRT+D<@-I5<5Rxh3Hh7Ph_CS?OnXW^_|U$ut-B@Xwtic3 zZtJ%t=eB-#nDTP#H|5-#hE@L-P9I9%2xHet$deyb@^ACZuy|val(|Yd8fA|9tV_y1 zy@P0b5|En_>xeaWt$^&*4Ov$=>`yEil9G8ld#XEJ&NUgZMWCF~4SA6-#HeZsH_FgK zr~8!b%!l8%{$)U3bPMD~t=K!|L)&3{#y2p@4cQuH=N*#`>_y7lL0X-&oohO_7<=|U zj`ZWu#vZo#=y(+ORLHiMWe+w&vdcU0Ugx9zbYB(oh<26a15NG&>1Z}UJADWFp{%WA zHE3?Y9xBqj2Y2MHV=eBWxtVfPO&4K0pg$mw*gIa?iQkrdpZ!G153%0{_AvcqYlgW8 zCv(U5u8c{ik!~;2JcTgFA-7|_{uA1e6^CW5`pI{ek0|ntF`<|8)7I~>*B-pN@y-WX zVLQ$$m3`K5^;BDZ!0PL0&&M3bdibX@jun$Gg!t~aYMj!%!S`FWxu;CE5%=kEj3<`7HrsHwJqF(lRljec>2;(?BaA^T)TMiu=cKULvo9DQ1)sGu(-tyBP zhzB1VN>^ijAMlAy>eBqfhRxz%gonO`c305TfzQAQ*DgpWYKX$=fVEb?J_2@&k#S3bWb9mr_Hg?vYi`=a%&ao`M%O+lDXqq zyyKW{=?e6?YLy**>``ycG9?dgvu%ju^W+;l5qWFLkRrUp!OU8Y`$np+3+Gf5eQRBF0F6e{O3`-1I;U-fwN}|J~b%Z=e3| z<>S2r<$&+!TMqnI^UvA8plZY59QRMD+lT`FvuE-qh`G30U|Wy=zdyz9j_ZD@+jxu_ z!o_v7lo^^J{&;L~uFVDtUt@#g8#-Y4U)kUn+29x3;In`;UphaRsKrd1P55Ot_^meh zT{idwHux4BoCD23<@Tfv{)`RYWrM$FgTHNqe`C@0Q`exksUd(;hDh~?sVX>YSD#<$0WUJ-O6e<RJ6*;3h|i0360D!*-%A88)4faJ zGQ6FR;VThdmgfn9%W^ZE78B%0;xRUOnhmb~^9R!@wFy7Q2ERz)Qs*&8;7Ov~uC>8$ z61c4Qdu{M11TJNoM-(0`GyOv0$tX7^RyDcm5p<-kWxNs`v3#UXMe7WR3(<|SON37s z`F%y;Qg#eEfq9XR98dLmBE)6Bydi<`vV1NRxYT)EC2-llwhCP4OZ#sbczYE<85B@HEE9l7Y!vA!g zS%@6mQIcwy^_MKaA;i3X#QO2Rp5&-<;SE)8sAl1>`(X-KpEoNq{*DhySHB<)c@^V< zG=FaVGQ=g#V4ayxU$Ku6)}_#1xj;XU#^?#KISki&QuE?%bbjw>scEsiqQtO)ZS zYlKf<%4)VfbH{JJxNpAFw=87-^~;)YUPE)lOApMtBV=O>1TBw1rs|0>*6@soeXymb zj0lCkCOgD?tQF6iHoj?X^ksEsxp#Yf)GcrI+q04D?Pb2`EA23N_u}jr`s(6YCGcle zWctg6AH2necMtaicO%UeQShe)S(kzQ9anzt7=KQLw|5TwSyDv2FMU2cGky+U}Ci>mu4Nkk29EZ87qBOjz4%u#5K7 zTN2ua^VS2;kA;|a)Bg8ITx~J({Sa5%Ymnjl-%oe8&2U0C=W3t2`-S$58z86VIinY% zOnpk0+#X`oG=y9GuPKLYMY;Q^OMuLq@@>dh`{`N(`jnSVeaZ}kp)7GJ?)1aG9`}F4 zeK+oGC-2}+zg{PCr;UFy&Pt^$z6$q`a9@u*WuPZ?X13sBXH*{{KLD~6tkoA6oyCqk*^fcW+^zA~}xAZ;;ALRVKDBtuL!?cmN zWd3T81p1;Sm#3W8+NaYE`99NOKZXuumzMDobK@Q4r&ISjGZsRYHocBzr}DlWdQknl z_IMx4#?qDiZ}3MQ2+P`%|62O1F39;UKCNdjo%eceBeox&5fey@dzHj_#E|v>SX$lC zv&j6Q+^bkupSm)NbX|2o_WxJN`!1x#x~C4~%<`wVH=ut8_jx^r_F$Y~KmQ(kr>t{_ zLw9UmVeBbJe`-KKHt*=a<{kakyraLGcl1;9j{a%h(J#$A`lESAKQ!;?f9!kggY18- zTeeXn%kuH5%dg`+=$Wy%2k-C2|1~%tcq(=WK3>x}5f(B@|Vrw`4gxbv)?^|*5%&TibKKKlPZ%>pFKI zbUD~3!Ecz{R|I`r<(6hk*KO&>s8=$5aIR}do1i{j>a)-;Dl z>%BDwc=22hn%r09T(;aC8#ZGv75yucx6L*9zF<7DbZr5hT6=F_jC5Nt%MZFY zOShD!^uDBRm6I2HjjXZ@@ZN#_ME?r^kFp#LU`X362gkDO{bMA?fMXFDf0%#F$CA+J zQ04(zJP#e`e6Q)l80x`1fPOvMMlgA+Is%;%_lsFJF5*mV?8oZ*ch~@Y-B(#5+J(+5 z)<;Pl=do<9I`VzlSIPDx>4A5&C+j_UEc1SWISBM*j29e^WyCP<&-ThEd`0l-Ge)s5SmiYsHOwTx9rDiA`^2}Js6cQnC z%YvV%e5249VU*xVhk9eI(QKS&Of)7N(~Ox$t1;J@XDl?X#&LQpj8(>+#%lOH++aLp zY%v}-b{bFN*nqvpK4ZV}vT@M(#5inxW_)RUV;nP18xBXfBi0e;NOq(Dtamm#Cpo7$FLus!wm9cH7dRI>uXnC= zu5#Y)yxY0fx!&37+~$1L`IPf{=YHoK&i9-jI}bZQcYfnM>FjknT%oQ+SC*^LHNsWp zs&Uo3#=6dP&2Y_hUFvFaUF~XfEp}b+TJ5^WwZYZt+V0xvddjuO^|I@L>rK~tu1{Q_ zxsJI`x=y>!xWYpsL*hcxLo!41LkdDhhBSmUhfD~W7&19zM#$wMvqKhytO!{dvN~jK z$U`ApLbiuI8S;F{zL1wgUJrRAqA$D-V?eubbaXkp_@V<4t+FqXXsO*dqZChJrMdv=$oPMgnk(MdFb)b z)1l#Ev0({esbSe+xnU#1O2Wp5HHMuRHZknNuxVj4!Y&P)8+Jq3im+8-w}m|v))}@X zY-iY>uxG>ehrJ$lFzkb{Pr{CcoeDc0b|x$`JTW{wydb)~&N9}NF6{80GO@UO#9g@;DOMI=XfB61@N zA_^laA{rtZBc?=5iqr+pOV-jNWV@hJmVj5#EjcJK#jk!8zam@8Gt77hqSrfB9=AoFUVs^*uiFr2W z<(R`UpT!)FITmv&=5&lB))gBUn;4rN>xmr^J2G}`Y(wni*cq`4VsD6D8GBpo?Xjz4 z?~dIP`)KUbvCqf89Q$hQ>#+x8---P&_OsZ}V~@w4iS3Jx9F#gJYmjG9!Jv{sRfFmW zO&WCZpqYa%AGB~#+n}X`ZXR^|pnC?bAGC4MlY^cfv}e$ZgWeqU&Y%wmeLd)#LA`^* zX4}#7~J|5WhJ7hWO?2x5eKczb1Zd z{6q0u;=9{*(gv+?`lUyc7f{#g9+_%rdL3DF732?Yrw6Y3HsB%GHpGodA6cEW;$ zMF}etRwdk>urZ-CVOzq(36Cbcn6N+L&4l+7K2P{2;bg+;gxJAZgR=+c4lW!#VsP2u zn!$~O&l@~#aLeGf!HWmqF!<)d_YB@J`0>F{4c7%Cf%KMf6}I;&ZH-k zo=$o`=|IvuNr#g@PYO+rPEJTpP0mivPcBRzkzA8JHn}mmIeB7oOY+?0dC3ctZ%$s3 zyej#gZ_>-Qr}5El=@}r@zj&4 zeW~GTiD_ABRcSS8^=Zv%6VonCn~^pztu5{Pw42jbq}`TwPuj+`hteKS+nM%M+Mcw1 zX)mX}nf6}V2Wg+AeU^4K?PS`SwB+>6^s@Ad^a<$`)2F0gntnt2%JjAA8`AGj-;%yP z{n7L%(|4!8oc>1ohv{FZpGkLRgk~gUq-JI# zo^fZ!+Kh)Y9?jU9@npuHj8`+>$ap8?y^O;d$1_f6^ksx*=4R$+mSmP?)@0UaHfEle zIXQDi=FH5wnF}))XRgRxmANMKq0EOf_h#D z%Bst1$ZE`*lr=5u@~qie3$og>mS!!_x;g9itUI&TXWgH*DQjES!&y&dJ)N~b>%FWG zvkqmQ%<9c@3=JO|Jv4D>>d^e5BZig?9XoX5&_gd~XCKWzp52$7;LdbsxeMHd?vd^a_j&FM-Ba8x?%D3S?gj4a z-8Z}Mba%QRbwBCe<9^Y--+kEqx%+GPH}2E!K6k7q(NpDV^i1?j_RREL>S^&T_T22b z&9mOK!PDt^-1C%Yw`ZT{WzTz_k3FAxzVsaPob;UbxN;(M;&L)`JURI}BXY`e>T)LK zOwO5|GcRXx&eEI}Ik)B9p0g(Bp`1-QTXLSxc|PaEoI^RE<$RrUD#w)@nH!y3kXx8r zl3S5ml{+DKO767WnYpub7v`?Yy(f2l?!&n|bDzxJo4Y^v)!cV-Kh8az`%Uig+}_;K zyy(2ty!5=nys>$WdChqj=C$O_%UhUtL*C7KEAnp3+nCpx_jum!yl3{KWk9{DSDHe z{O9vu&wnHTgZxAJr}BIALx)8ViyM|atYBE-u&QD8!y1N78a8d%%wcnfEf}_F*z#d3 zhpifR&#;ZdHVxZ3?5SZd4tsUjfno0q`*_$l!%hxMEl4k@DyS*AuwYujjDnVeg#}j^ zEH1ddU`4_Df{g_a6+B$@Rq;;Bdh=1+L-Y!()dh4$mB(J=`GAHHw+JHtO1{^9UXhJQW$)Nof}XkkL3 zr!cp$q42!I%M0fgE+|}7xU_Ip;q8U@6mBf+EPS}|(ZaojFBZO2_+H`R!Y>QIE<9f7 zC`v5KD#|Y^DVkg~qo}25ZqdS`tBV#Fttz^+Xm!zsqKAt16g^wCzv%U%kBbf$9W6Rm zbh;>UM8Sx%5fvlGj%XM$X~g6aGe#^JarKBrBbJZ2d&Gtj_m9{zV%v!ABc31e`iRd* z9363dMDK_*BO;6Aic^boi%W{DitCCSi!UyoS-hb5`r?(vw->K1-c-D^_^INjiw_jP zQT$=?q2j~EUlxB;+*cevGHYb^$oi4ZBPWi$aAfPqxg*;~-Z}E2k)0#Ak9=z6?veXP zzC7~a$WKN(M!80XkBS|YJ}P@u{-}|oDn`|esvFfX>f%wCj#@P8hEXd<-8O3Ns12hY z8ntEAwoy-xdV18pQ7?{qebm8GpN~2^DzqfBB)TM_q@bj*q_Jc|$)u7COQw`uT(YQS zY01qcD@#_DY%6)RCDng zOXrogmEKT#bLnlRYf9IbZYkYfx~Ft+>C2@DO5ZGfuk@4B&q}{3JzaXH)KwN)mR{y5 zD<~UTR#(FbMOA%OW7U+ZxmAm*+N!RvT3&T?)yk^7tL~|~ziMMu zXVueH&sXiOda>%As*kHaullAcv^u;xp*k17f~u-(s_UySte#vwt$Jp4YxTnFtE*R6 z-&4J_`tj;L)z4PHUj1hE;p#7|PgOf=Ts7e}nKcbH6KW>bOs=`SrnP2i&5D}4Yqr#E zuX(iQ)tYx|KB+lYbG+tMO=xX&t*5r4wyL(V_Pp9jwbN=Zu5GEETf3;Xt@h^Hdus2m zeYp1N+Wob!*1l2uPVIZOAJ-nLJzU#Y>!{1B%dN|=E37N28(Y^{cVXS7bqnimsJppt zRo&{kHFfLjHr934JzV#A-BWeX*6po(z3$_>&+3lWeN%V3&NVu5bn@uz(FLPNj4m5J zY4nuQmyVu2dfw=(N8d2|_R-r$Zy){i=+{TTGy2fz&qf~|eSGwp(XRT0`pkMyeQy28 z`nviF_0#HS*0#-&y~3{hs<4>krhwS^r-Bq58x1C+qv_ z9b;n0B#cQNlRc(zOx2j?F_Xtk8*}NHxnmZNX&ZCfm^;U881wL$-DCESd3ns6V?G}9 z$(UnfPK|MmjUAglHgjzDSkKszV=KnijBOa(Ja*C8#bcL_y9HtcP9z2RWP#|>XL9Bnw(aHb*C>+$A$M|jJ;4c=z&1n=eER_{FT)!y5^ zYrI>$+r3YEpY}fQ{m}b~_o(+2jwOj~jBZS5Om6fvRy0;M);BgZ&TO39xUlj1#^sG` z8y{_ay7BqOy^RMNKX3e|@pxlzV`x)&Q+iW&Q*KjXQ%O^E)3l};O_w&cHZ5+txoK6? zZB2JJt!diO^ib38ru|I^nhrL7+;q6?wPP`cvArT6Q$S8ZXPf%xP*3 zDb2vyS=P<`JCMz*WgnpoN<>%>eoNn!(y-vC*vJkC9cde&lb}v>Ae=UO1L5Zbr%kHP z&k{xGFBPtB;J#G~!)t8lK<+*u{abACzq7&bx559x27l59-(!RCx4{qE;2+!IU)$hk zY;ed42P~f?8{Ezh$7q}Ie_?~q0M7c=Hcvh({&8Jt6Mm@;PQMBRwVzcs_}|&!>w%M> zN0gG@>Th7kuT(azaId{?(X7^4SK;gjDw+-WE;WCchell2dW~tHON&~4k|IoA{lCwf z@ayKLmf5XWnT|bR1#3oaxdKN*ESbw=Ae$#r@(zz}0fl8xVWxp%^c+kpM8R^;? z0&DAE={v;E==Q?Nzn*Sd6f2tkXIKDhW8=A2zL=c0>-7iIfN(F;{|F3tK7j`m>!=Um z*JR$@Yvx{O9-_g5RCyO>$;ztuY?I)C5wTT#C^cTDFc){)*eJ6p6E8OZ!k#e*AFpuQ z4*BaE*abG>FB9RVjSy|jd6AAbQ{nR+c;-c%b`|wKh0>+?iJ}{RlOl6W4XhfN27kwq$OBOIxX88@$#A z*XKk8x1Z@Md~o}benVt?xK+@XHfCD|E^Wi4?XI+8`-2ECZOo1cT-wNeC2-nN`7brD zvOJ~Dq4f75Z5M}&@Y0sDQsB}C@&bXo{fQcev<;U1;wBN^Bf>u+aM>@kZ&mW2Bf?9Y zTNz&3+{*I*NZ8QIc4cQP`>hBs+tm*W4{j%hvSkf!CzZm+Rq`WkVr6@NLWGy;K4*h# z-?uCu8U7;?Ue@nd0?!lWDgAfI@z5=7Q1eCjN`Vg(`1t~t^?r%K3q*Knb1TE&A;Qc4 z)gf@sHTAX227gK5GQaN&T+;bM;4G!^%K*j2H9@a9!Um8a+b{`+X`_t{NtB(od`--;|wdW zVmz>_e{TFT#3fDjIma*S>e1=)3dk!sKA(g0&hW!k`g(mD1&rf>>Q;W6Wfs#w>8Ghqw>2oi zpvV8q-j~2fRh{kMnS>-jP?oUDXC`3}NJ9t#mzE){0xDZuT-r=F35F$*s3_445G^It z5{XK|mI(rqh^?)t;6_kH4d{o&R$Fa}fJz(fhZQwZX#UT0mYFj*b3akruU~)v@BV%> z_nzmT38sI-iWFHX-Gm2T`1BX^4t`^1bIadDbQT<1RL zHO^?jdO@#cc`;j}gQd@G{TTB<0j@)PuoCb1T!lix+$TBLBm21ym3kg1=D3ih3EIs$ zp4O?@a29xD!rhi`6(S_B8MgO6o4d&7_S@X+Y;LbD{ebO#XIuJ@*xm#p6BewYK zY~lU3_o=qzS^=ALJB7uekM zZSF-j_YF38vCVz6&Ar&>F0{E9*xazag~>;e&Ar6tUTAX%8K)kym(EM`EGY5dKGMp` z&hsqI&z%p;3QQwb&ir|>c6dq_FZL{0yl5WWCB?#3ypV0&E?QSRcr`HSXx~3-TAuD=7#%VcnURA9NKL%)h?GVz6va@sb;} zm*xw{{6+Ii<|Fj2h-cAak6u@e$Ku5cZY-IK>8 zM{^dX<>luxNjw!uGZl?NI5Jh6h$2~}lnDp7tVN5na=^gc0{SO_5*Npua$j72!bB0J z@$JO9GmyWm%dea>an_aNrW2YxDQzKl(KVm-j=K7tUVk2RgW)&jV@uua@L(Z0D|@Lp zV<;42NgKDwUug9_?N=Z*EzF<=Afg+K@E5_dM>8Svpn?jYL5rXUH8-@oc>cno1;Joi zic~Dh8O~FNlytV)MVP$SwM#`I_Ce-z(fqWWMI=v^pEhCg9x~(EmgxVZhD=1e?VmYj z!Zugr)*%&?>c}gd#GC9#wZ++lHOEHu`foPTh->-rlP<(3G`HC<2^#Z*4r=wZQPoTn^( zL5)g`zU4{93=BBrQ@V?Tc2wF%Vic{sX!5&xzL7dI~e$8nF*zm`d z{~b2`MTPIS;cqDXB^&;c!r!#vy7ha~hWAjdvSu4TSmC;SH2+5{T-)$9u5I7ihOcpL zLAqDjynOr|<$BexJgZ+3?K@Uv0y&H>bEZ*zhM5zT1W?v9w;Y z;o4sIrVZEj@sl>3HWFUVHvCcvTe|n6^E*f3ddx!OK85S@(Ky=U;?iRi8egmMDJp*& z|AoTm+VF=JUSPwYQus0({<6YX+wk8he1i>tPvJXk_(uxgZNoX{%aiquWevDJx#xMkH7&*aR!uVIpN~4c&i^D}Og{}j^IE1Dz1Nm8oqv7*E&}m6)eMa1(JG-YvqAn) zg|`K_@-?Bh7dl-Hcfo^=MDc2aYB-_4A9mTp)2&ofn7;y*zF!51$6M+?O_t`LlMV8u zYN{55#VUDaLg>JuM-jmWIV!RZa%4sttdqRX-3GbC*l@=y68EA_7YiHYlVW{1*MwfZ zEOEBnuNrGL4_#crHTc}~k!!=h7;3f5!5LPG{>0|bu+MDSomMmUMNat~>%n-|^g`?< zc^qqIH{E{Q`V5a%$#rU21DC?RQITAg?}kg8AI-5UOI}T{xS*povnttotqg0jKfu1B z*v}Vh_`73`U1;xCti3~6u3?n>FiJmMhbR4nt+6kh0Q$K0{lE^Sm4LObwOot+{GHxr ztVK*AEm&_jle83P(#DE&sz5*2WoLE9xqw)+%W&jHmd7&I&bm|d9?;|udEmmj!2d4o ztjnw=(9i#^pSh*3ZscL_vfI{kt@ou??+UER2fvu-(D{2}?LF4n9|s;m1}q?9VRuHti|ufd!es8vk9aADffq z{s(4Sq-pba7=Zc#yoITb; zen6iYzF(9a+c<D+0RHKRYque@pjWL`{j_!0=fGG_zsCI^W;5KK7|ppm<~P1Q8*AL^oHKryoEXP#-+vcZ^~Cmz)rd_Cp$gNHHI!sehfvW z=Q0*s3-cGMxrs=Nwk)SE{r5292^juO{_DOe{hRakbYF(JZa*`+c-7Y+ZkE?D12@ZSjDf4E4uYy8 z12_3^&YLsS4H*7S{Hyn&Q4JU7W1jACjB4c%pM2$aFT!wHZlS@eZ}R9tV6euqkGxCe zL#JVLI?j_>t(baP$rYVUNAp_q#Ho*b+MbXifN_}DFgO^e5|`ksa}7TNAsAd3vMO19j*{w?DVq^+G(f9xk`CW6`?|Z_V9Eo7Kc3HX|PIP+gPbP$tOGi ziAPFb@1gl$cyC_z^!c4BUU=?(%rT=gFzbcax%V-5t2tMs!z+l9eav^!{>{QZVixvV zxd`XSWR+aFbRXJ!nWeX_j|J9hxtmsC{~@;T2V(w9W@l^WR@{^PR^`0X1K1WTx?&ri z50pl2O0=Sz8t>cOr`(FEu=;xM-fCUgd=waZbQ`z&f7p!K>lK4=zrOTE5sv=nmBwy5 zP<7`ycN_JwHbN+Ep}y7h_#k(*W?GptRkl z{L&XTkv8(`J>;GA^+&#arO})65cf9Zb6eFN8{ZXqZ71@|J3>OYWjh;klT&-raKDVM^`0z zv*IkyL`Qno;p7Sn_cD~*ILH{&O)mE~PbhV7$^+e*rO$23iFP$}-@Gk2W9jVjXM+7h z_S;UQfA>i@3+F|+(btoGyuI#jO*!uF2VHUgS+m!z-{JAKd^3Naq_;6-K=i4 zkKta0--&pkJ zR-oTB&DE|p$#Pe0gB+Au9h?4)G|)MDt=w`S%(dbU@|>2&GVgEx3-@euV;;^-jn= z>)&<@{Jd}T#?1(`4R|!_st4sf2|w05){pIw#my)))Q^p%}D8gMJ{BVSXSB z!Vm7c{xU8d2kRv3<7>$4pn~h0r{EV09gt|nHl1YMKw7O*9&d<$WgN9`+tQ5bu#^@gDcE_sG8tuihiyVegS&zGqnOUpBZPzj-o# z?Om}46J4=Q16?r(V+sZ|zXw0tkk|e2_ll4M{}JXv&qrh)SU>Zi4`>6-g>JyNr)5%t z7xmHGG7s)tyc>XhD9gdm9ndS=pjYk$Ph+C37U~V^iB^>T1o+RbTD5Ty_NL5*&bb`- z_n=SShd#+eSsjI+fry8?b*~lGG#<|<@%#dG!U5=nRR}|T0OFxu>fnm0*jm~i>Ak!u z7jhOA2RjbK#d}+rCUxQEu67j_2w#ry{ahU@%3M)RloOWqNtF2@q;b^h&@>6O#ND$R z>9%jW1MjEy_twNA?7RF1AU^{Y%}k&4#k*oFUO?IhMB0ijq)WOgKvzv^2hddyy4qJn z#ak_7k?wfVL%N1^_O{%BxG%abYSWP0p5HXy)v01H-VcE;-VC~=EXE5ukD~6s2RiqH z#upIxV5Big@VZ?E`B;wlr|ukA)9$vIO>ws!*u;F0x1^K#xeMhG%mc#dcg({pA`cyq z2hthN+nvZmZD~j3;UM01sEF!pwPZ052{I2U$V&zCa24_}6?w>YonO(4_fzj#vvDlG zF{0kN&QrYZ)bu{`aMX%#dQX&X$EL|u<7%iAhJvOE2y+1C$GlwuzUST6Zd2iHFNiW_ zdG<%13h$}dc*yElaR4|#CDn>=Wba-^K7 zd?Fv@!C%3Hn$k|l=PP)JvP!U(RWEPLE6C>vRaOtUx>SsXewAg_S>^M5kiyrZU2Qd|sz~{YI*QSY(g+VBr za+K51t>bF8A^#6E|G;$qAHL@&8)tjGH9@`^`Cn&ssvz&qcRTa$Bk*nj;vHh+Im>jo zyM3s>fF_+LW#x$ATO8`kOCdP|Us%>Z1mAX)b_3rU@Gh<*sxNh))M2digW<0ss$E3_ z_!h_d;!eQ#TGr7lRbTeHItw}441WCud@FNxQG7j5@Ua#A83Y=SS{Evv(5-3cBTA-( zF6dA}9ZcR0+A%J~A47J?^ER?&@K4LuMDS;-jqfbuU%5Jj_@nCJjh2r?&@)|>e5_J> zhI!Nal=X?aj(KLiVxFZuoTua=UVI}c1Cv0vkb|w6;6Yr))M4Xmf--O9m%P0TIw<&! zF!Jm8jR4Io&oIM=b!?gl9>+nq^BXZx zJ##$f1lk?%qup_NLS_xW{rpal-u=Kkp`IRKn*?&D-)VZo+6%*Edtr!@zX{+A>E*uJ z{cekfen7j#6@~V9w9xliuDGV-g72N0*p3n3Gq_3TWY2h^+essJ2EQdQu&;@470Y2S z;uwJVNyiP)cMqb?zYThXWfh%jwXl6OS<%rSaZCXn73y0T3w>3FHXF-+EOZKKV4H_vNl?G@_Je5BJ4aTK7WBro7U3HKcq^Ay)K2>p*F^nqf)uVW%# zF-@6OE71mN*OXMXV&gdMfgTebTf_FC*$(`=Z9ul6m`~jfWc!c2dJ%2F1ELKWi@tQU z_;&JJ#r9u4_{Fy6gJ{ET6K%lQ3byN7@t*aDeEJc-?d9Uz9xK{_d^ZGs$S<}9VRIw|@CI)U>-R*^v>APZ{&+tbaZE+nXtYP-&>ooxI2Rn9%5NrQ>Uw2In1H%=6f!02io1#NE&zRquVp*p z-i9<*3P0|q=g{AFqYv>ACkQgQ~nW2SD#C_agC8wEimm!WE zr1=WyB`A^+No^M7OFdtjVbMR#_%9}FEx*60D;FDS2&{DYv=tO@qzL9V#Q)E|+zkWg_*>`6920?(>u^cM-CcdYd5oJ6ZW&B(e z`zunm*gmI@8_TkUEN@2LWt)Wkwpg|)see(1vhUipX$bPm{_9wGXW+75w;65m!Qg?g zA0xlA+}q)sA^YR}=9zi#gm{@Zem_|5C!j-rith+*45q(RibwrXcI1;R_t=U%gXK=W zrgRqC(JXhmMY$tQQMVBGc9eTP@_hjLe=aIi?k|I{dzFsY<<5Q@<(cJ9S!=brAfHmk zb=fn&g976q-za~`B)^l)Gs~W`ycm3mq~Ct2U1uJ#pU!Lwx4+gi{=Srj%C=pE*jGDz9fWkWj z$jb_p#r4pAxkB$5a)I{ke8@HBq5$b7qr52RvCyxRz{lx=kMR|oRoP{^lx}8Ppn*D1 zep6zb_&t$*rzp|JWWOpun5OZaKwGvDY3ya$p{+F_4t$3Da-=yKJmdF!fcSQ{Ynp;@ zHNVZwH_M1=mcjlOg}Si{c|3u9MWg-7HX*<3Y`b0$9%orGO>D0YD0QLzx^L5d_}i=e zkdM0U8m-!{U)Gkm18KDrZHabGliIW;Vk-2Q!$inA+s14^Nj)js6E`4#cY>E}7i4oPuY;<^z3oGYc>uS*ywGe|rRjci`);{|nLZUZ?J8`h71z{q&pEN2FMMiKn;BX+=7gqIF-9@}O3b(l zx+2WRVsdJx*3&9~oaskcVaM=`a}$Yq!(nSiq6GBZ63%s?sM+T{ z3{<#%-os8?x-vEyhkoYWY0k;HhIg8CqQigPIVXQONBW)SoD?Yjecd@HjVgV;e(tNz zIoUzQf@_Do1^<=02)a>oxH3C9=_I(f%BaZe8q!C8^}SUJ&I=}|ILk`gGT6tor|Y}KyC+~-8D==d7q*v+ro}wJi*pi~uFqxd!u<9lIv;v&z7P2! zO|+5Hj>$MIxX)m0_w4egjrk2x>ij=<%4Zi?Eu7EJbqI}Ed%*Zf7w=x|J(GYl;Itd* zz<+2?{MqIEMH-(VJk|uHFpMAPR-Hij<5)Yu^#P<)uQRAS+dAq4LCaG?T2ABqG0w;T z7-@4pKIheQjRoh{ldeX*mo&-s2cHW}K65_(z2ZDL>8AgC3^(b@in2cHe}OsYUi!tS zB;hFLObIo?ZTe;0w!z zbJZD6%-K+9e%+jgwFhdh|7TnLeS8@>Z_esj*ob)>#}NkWF0kgJTdgi%Uxu|u_`x|& zjV-Nnau8n9B-g}vaUK`Lg zfIWaR$NGdNNtipazqfxD^!Pfo4Jx<9`)7^oj5?%vv;qE(ffl{CNAMeGsy!Y<0uQFlVqKF}}e zlVxu~)=xt&c*d8M`Cgzsbp9C5x=Z1ikn)^C@>z!CxnWu-f)A6&kH5q-c>4TB*-ICD z;P7M&PrE2BbwtMS5hI4sF?@uF&Jp;5C6O=c+<)f!1v$OZuGu9mQ4#il;2Yt+f ztNX1E{#QEScRAp?O{?d#uT}B$8yktv#~koF2mGJ|jt@n|`2Pr;`K?k#GhMY=F()me z|BoE-FC1_;;*FHA4i0!P2fROU(%GmQiMx>=uS*>KvyUJeC8Cpn)eo~Kj-MfxKydFN zE{D+f;0x~UGJe+8Gv-{C#XXc3i=BLeZ}kSw;;y`DEa*usxCm}6onIoCO&~el*HznydU1XS-EjtJMQ>qe&R- z+uCu~D_&eTVy-thEa5i$PB$7j+7Q9(q=9z}qL`%KPWG2=;4`hmDff2x7AKd3LvhZPt7 zoBY&zhB*5_`nt~WZ^mElfUh%fvs~&7+*}XSXyB@QB$C#9R*)WZf7i}R-w-$boBL*) z{=J5O)qN82&oyw9KUE61*Ov_nx98@QS7Ap`dapYktWb>f*XQ+^T* z+${J025y!M&h8Z#<4HE+*Lw;OSLPe>cAeqh8AV<>1Z z=(Q|uW08ADu+Q~<%yk$2dCV986n#UzU&6hXHHvHNJ?OX1K;IjEqgqeAchB$959a!c zkI`ov8)X%)#Xbk`pbzQ8Z+BO&6L(F$+3judp&#k%;NL?(AHdHau#dn~Dc+V_u;#rx z`iDGgeQZ>Z!a}_BV=X=U_Jz|sV66q>IgYc#83)gC{u%D~BFty*J{5k^pXJ^XvhNE` zcM#_S97N@Ojs5?lZdc(U#OFgkpi7rrf&Sk+SQn9e$WxJxc(_I*xjd^m2Q~+USyBx< zf)8=iKln3>>+}5)!me-#>ql7nM<0CDW`yNA?(bkv3~hhG+4X4dOZ$$~z6hL~BH70%>(VYD>|?uV2RJ77)aYJ20<_Uiz_mPf zn_*(PwVP$-TPf|8zGK>M*{-H6r>)&Gb6^C!WhV!_CBicwrrpvX$!>}DA(3eC<(#Vx zbGNYd^^5cF;TjTiAC>3Nv(hOC+^2;$QoWakwzZLOzM#EL+MFWW+g=j(wp+ocn<>MB zx6(ESS=d$A!@I|Cbv4_lITeKds~BJ~G^2C1lfLJ^C2* z-Vb?29Cz!q{scF4(~&>pPW$M+N}dxfS5wG_4I49ToGjNQ%9WC>I_OV?0o{;C!*-pG z^7P|Jnk?)GlYIr#j zppD-twE5Rze6y0@C)mDIS|Eqq!-#sL-*;r4c^v%8#k15UJyYrsmT7+vGReD;S&Ri7 zgUuD?T}#aCvPNnBKv^+uiY?fmNZW=zF4#fGh2mz|0MdiJ@6zEPh5LEh{+rtp+0-)6;Ok{HsQwW)Mz)c)y#kNHYb2f`;oot&wjV%UY>LCU$6X^ zs|M->xOx2nzew?)1kU(hQvT=AGcG8fi2h?;k#Y8U8IL|=N$;Q9&%yt<9PmpW@JSB% zcOCF72fWY$UkY5vi85&U$plrHaf%;Y}{*G<@HM!b0hCXCG!?9%wKwo zv>`$Zgf@49L+{Z-?GUzqjA7Ob#X)1=xfmMdRx!$cXrqI1Xwzo!U^{I_)%W0wi00Jb zTWvbcU67xREtZ$&=WE-meiQVnjH;#qmG)45bf94yr8U#o1w6DNxn>-5pbV(N=-cFo z5yJXgn4hOfq6_7>UzB3oJ#O+)uDodLkmD%Q{fL3bOGx~iHaFA%1XaHok7?U9ZDpnn z)3lYD^>nQfPZuLyb3TgE)w4b@{F~{XHgGfDXjSh?r42Mi+?f93lud&+XVca< zUE%if#o}{u5jXj)Z9;ZFYg-d>lh1WVJSN{x8MtY4)3yu7W7-VOGvm-63|`Zft%d$Q zLDaH*2A*W#%M3i(z^e?rpMgJZ;3hqX4BVv0Jd@6hM;qzv`MON$V>{n`4tS9RzDwbD zIoz#qyBxl5#52&yuX)CtiJvz7o3_?CCETRnv_&TvcyA;A2?lP)KgYmL|2~D==`S+; zoALa++id+RUz%mAnrNq^&31~~a7x!7+V)T+mNMl9$8X3h;!1tsNnUlfbTv-D<~0ls z#`$%_k3d+)nTDTv>GV68Af9#l`tDU&s?A@$qJOvz*WvX2auwd@&BEp!5icE1zvQ>e zo_D^Rt3F;=Yme$~4^OxHgoXLk>F-dHlMnpa%g@PX8&DtZ?Y0DMPSLC@njbXThRz&w zm=~9p`qgc=MM^g^gI@mOU(SmQ?RTU1x?vv~9;#e@tuEcr*JNKmDZZf(?VgEo-oJg^ zb90|`^nE>@IV9JuqkYd9_WRi%^|@Ug{pVR1yRbJ(@|n5o(SN--`OJ*J-f1h~2aSj>a<0!aHDlvL z`|`41kMYboC?+wVs6XZtWy0R&IxjS*$h0faW~%qM>27)V&<+vkPHQS+Bl5~kOUx%YNy zPvJhRH^I;AU$lxje}c!@GgbHV-&B2g$U^Qvs0%OZ>OXTnkkk!!iAK(F{UiG7RH5u6 z>1&sI;P=jKQ|kBq9Po>PGaeoOZ53d&ga3&R_;d&Sdk(m++`7w#6Q6KO5c?NqKLu#c zd~tA)Izp(;WDIqn5PYcbc=0U@OR{s&<|tVz z?*;k^XBlJc3xc=?BGoyxCto%{H(?n}g} z@L#p9aoCowPTvkYwKdK)yi;34hbP_UrPJ4UFJAK5-q!fN^6+)r8nJFO)zGs}S0hes z4c*53x@`@;_GW`hkg`r*oO4?PA1hw?aD-iU`lUfAE!f!j(mD8PU%joN$I3~FS5PC{ z8m+53ymofECB}iaM8(wvFa}|c1;KZV7$+`nSMy-E*cz|f8odwS@CjW)bA_M7x7erb z?-+NOb#}S8rV(~~yM6tO;)yj#uaa}$1LM6dUvNG-?E0TawZj-wOfAT&!nk2dV65DO zycy4RZY#wHyFKGd!Z<|O*ec=+Oy-#aUJ)Y1JkgN{p`@Y zK!ep%eU-OmEXI5|?|cQ?8kk>yg!w`JNT{CXZCQbF4j+EIF7>vstwnm-PN~Cq2j_OP zeL?IU(Cx=q(9zpFEcpQY&mDa>O5VTYlJ^{I$<2uO%=XQF63aR)Sqndjd!yuitV`Z= zrJv8>$A|gao_1C`X^?Z7nHJ9h!1$I*4;3)|DZKY}6ys2%$QRHq-h*$m0-zaf#*fN7 zcs~yyZ`GSZV_MalynCcu(ogqK(e8O0;n@Cp8u#Dfen0N77Kj*kNqU?1Z8Zj2PIo4XTZM3)L z9qjAp;kr4?D-#9Z|&)Y=fEm=We?tw_m()!%SYL89=#mvmScr%&trVQ569*Lki&Pt7oGkw zgGY5AwWe>vIT-^G-}VRGl>yINeZGilml7zn_G}*+lIQIsy)AV#>;I*7*FNk)$hfv3 zUh-V?+xK6s>48G;9-O<;h5i$*3knZl+;1QD>BM{qMMoclju6lMAA-lo<0YWusRv>z zukQEzKDuuCqA*VT9>xS$MNT)+)S7+`(p=upsvH~Dr*PcgTjy+Hdh0PaBhE^{z-^79 ze&9GQY5f9xN53sS0J;3sZFQ9IdWd(8u~vFA_;D%dIO=v6J`B0}9QuMfM2E+^6pYVV z>AMkL;=M#z*bqcm<{>f4UC6y8%W&R_r`z{#tw!G^06DzA%+-x$rOU$o=Jm~{Jb2%2 zO{Wa(MOkA#3&PI5m2(~@+QKo+%D3{HHShh$Thl2+499$7{>MxU{SL~|&ESQZrg@eJ zWzhPpbyPh3{4U1o!o6rEKinx>a;-hfm&<+) zXCIEo)XIg#=(?$MW!1U0ZTo6BF61nHc@(HI0_8NW793(yoxGr1jcD0NqV&j@aUg@9 z+OOy7hY#rC0OlL>vlcHBN8m;nteamt7qO`SI>;!?0f1yJaMxxdD8H2;-?+(XoTlwkLNN2H~XYB4BV_w zbq3CUg1#CJ+{~Ay`W#GGnJPt)&IaC1M}oU~)buzakM^#(?EX`YaVj&O83t~a`vLXh7kRU1g2snm4hxP!f6*D$!)FIUL~-<@lC^zlTTX~B^4L5J^P!*%-l?!|jPr`r52 zQuGhE;X0hYU#`O2yjl03WB#c#?0IKgJCt(%x;Bu2N`J1>L*&C(v4J!zW61|3#<+C8 zHH6RkyzA3KhhKb|4P-=`KK$a`=g7Zl6oOYI?8P^&J@z4Zyk^Ro+Zr-YdGF?Y$Vts* z4HHk_jL;AKt>GanwtlMBuKs2G_I7mFY)_1;!Jc6C+lEGC|G?<_ns2qM`4RkV zMgMCX+-s~3^*^@S*Oyxz>$hx*sd@0e*qWTa6B@RyvMRU29+6jiT|@1IaW%BFJi08W zIcM0EhF>kqYtCEiYuH8iWz!oTq5J;4hTqUVeMZB>bnh%^xbyGJ8mj)Ztl?SW*Uf48 zCGn>hG#ofJyMBGwZuP$=zF=;{L&OgiHEe- zhLnOSHN-dC|9ZV{Hg| zGS+ez?nJ)B_yb#3HuzA1`M(`72RjG;PDFJq%^u^xZ1_HtB6N9VyK#PvcS(yNYgqb&J20Yg*6@780$lyR;=mBL0Uef z0eh2J)4?+pP_?TB|GtRKzXw1A`6qa1@a8bWZUf#P=P}Gj8V5il?OTaBkKvB4R%JDK zv=6q0eOBzWegpPzOyXG+1=-CHSW)#+1xd~OvDZVA$9k<_(n}jnoM+8syIj+bN4W}z zfd{$xCB@hGSv7IhH5Uzde&asNHH~q_Bd)csPWADK>o~?)8P|AM)UjHBgi+>uEM?_ zyI3B7L42g+Mcgyz<17>C-0{%2mqV||Eh}h_T9(_~e%buyIOxo%eNnYjpd*P7ekZQ> za_DgEcUU_GI$QVwKIG>G4TD$2)e0QCKNH^r`gcR8XTH6xA=4XIn`60akKrtz_pRuP zapcqNC)4ZVEWG#H4M&H z>Eru_J%sNLrteW{<2;iGMfpEkgK`P3C(wJxd;V4STS(t3tn| zz;+mMyx{EeSJZwj(by{ldxt;|37#uECUsLlu2H~RA8Fg<`U1*K57>WyhxraJ$j$FC zmw{`>)tqMz~i(hg0Tz6x`ZeM_p+3spyTp z|NaacHf_s1pNsZ%H}czvIslzncnIIKa>)HP$kVHc2W#+-a4nUKXSaS(O5N9m{w^!X zZT8~qswC_q$TL6QiRw^WlNeL86>DscMRlxw=%LseoaZ?~xsmXEmt=|bOaQ@VqE%R_bZWeSczUP5lZ%a+$q#Cr6>#MKj z_zp4Hr*TKx^;>Vo7>8xmGyk=){X%b51hV+ve?tJs&a-Hf!XqBm7c_PmJ^K$w%Eyf*ZWWnbA+x?8WyYwAMxLMI&?)WE0~|wJkVn znENboJn9|rI1~DlzbqIjvjxvZxqZZSYLK&(mVTkVmOjfJA6z@4ZQ%OO@u2|Z6Jtq` zPdUDF3N*@neB>G*Pit$swkh|Bvu1v3HD}26MRNTU*aB|FmV;-UPN1n5->69ZK zhYxv&ZFuHi;a}RVd!x*_Rwxw4YHc0GF&wS8xt5Ok*X;n#-x-H*T{`I2?E&UH(i*yt z!85iGsH5%sRB_DBo`2G{0_}q&=t`7N74y$=3DPRp{&C%>)V1JW3isqWyL^urqogjO z9x&LYu`KgM2Qw_EaOUQOL6!KfUJ9 zLR%%oTUif$So_AZ)oIGLvoeqVk6U-K?8&z>@T&=R_AQjda;(=4EEc?6BGNk3I%jKD zh!@E=Ufk!v3;!vT7d&%at|_a-7}^QQu3SIJI>!CH2^B zE&>=!;}{&zK$Cu@ys+MX0e!O+cocNnN$@QSWr;eP6#ae7v>|g5eeW3ow_`sYsR!qkf6$b65 zneU$&*RUD;neD^49Mjr{_QV0pHIwI&Lm$tQ``?B3iF@=o)|I0_MP0`}71xR~AJ4%r z^M`yav3gCq^cKte2d_cy{>{#vXMz z3lO@Bdf_wFXX=8_k^UE$ufT73NFT}i=?|`1m2SwAgN}Gvq%Z5f^vk;M!C1ep>q57o zzG^q+9lCgzEc4K~vHuLlSs{z)&!Jv&4>+}#9p)Ztoedq7qVYNSj-$S$1kexNj5f+J z^n(IeU;h-ojdV|kn|;(>Xv66Dxp?P6-SAoRn`z;@$ah?iUkAS>%I{9N_rouEeT47h z5!a9Kt!RgKK@9p`ufv}Y&rhTOL3#7VSs9z7Fed?Wf;FqV67fB3jJM`&j_O^Aj>R14 zwv;m%rzO423&x^r*)RPBd6e~^`wd3dvXA;P^b~oh(`LRH&kEGZB#eJ1#UJRCgtog6 z>(|eq-|K~*9oOC(_231ahHUK_Tl2tp=FO^l@PaFb^zGHRFXZSW z%+Y|Hlr5L-s7LXPZy(-EU1gn8@6pcUT71SU-%DM>I8k?Z@!e+C7UO#VE5Mib;9EA@ z1p(BnVU~A2j6EKJQ3d;$VS~w7h-BL*33s)yWW9c>I;0kg5^Rz!M?!0uHIXxLbkRd9Q7)7 zM78m~(%+E|`2LV;Gp?`TH(s_YWg7#1&^=?({>g^^_CWrnT{fY%81^*reL>$z z+L+}&zTr9~(*7i--9qZuNctmE--`N!x>C0>d`fpvr^vlDqzwiBQsll0=3c_OpBvI= z+|PqH6z;qFb@iE~N43d85B0C?yRrStwsD9ie#4NCxLoQUt?uBfxb%2^7vT4_>=wGi{ zo}tDXuL2&)|Fz2h1f2!tf3buAQV0A;4*1qw*Lf@7Vk$qW?q({2~V&13@x=3LdU? z@@8>w2Bw>Sz68i$UNF1}{1Js0DSC1o;xAVIJ!(P?^UsTWFht64r33zR70($J&;2qQ z3;j(&&jzJXURU@t3SXcUj869zg-=lvYPA19DZH=JWE%fO;inWnL&YBhc_DwiY61xQ zPU7mL@Iwl(QaIJN>KHUxLJP=8@TCzfzqG!-&M;Z?j;6p&UGs{@C3uZUi;6viArUP zw{^;YcN;!TePWodQWe6#xyIk5vs6V&|GJI90FM~BN&jvGH|alQ;3oYG)Thl(kKe#e zdfrz0pK~HjKKEC8oACr2J)m=jftz&BHE@&81qN=?S!&=W-&PyAQZ0g?_ZzrL&(j8O z^7D{^_ZBh8zf%UT+hlyxUwwC&Uy~0r3_L8q1|F7Q0}soufnQ+Iv%$d4xsR_KxJgeO z4E4N7r%6v|12^gE>wph-z^53vSuS}7Zql>Bz|H)wHgL1Nb{lwDc^P=v99#o8_Y66y zaMn{*q=GLWD4g}w#LpPP)?_yPxfoq@xC z61=t=xLGc{4BRZ2Is-TPe_G*ozBMb{&Nsc*j`W*+^C%@^=i3+ue2#&e^{&9c6$v8G zr4D$Nft&fdPBDe_c!FGm{#Up?zsnSE&u_UAkD1>c2Cg1ODvbti*2j|uZkBtqft&TE zzbZVtoTNM86CCjC3_Qu?gMpiT^BcISZ`V5DJ5?nio&AjX4;i>BBJuVE2RvRei}9HL zJ1b@pH|b1QxV;?5DBNC-bB%b+d@V5W0S5i$2JSKNod#~o!!83KX!t*D;HI1pR)x)c znR1e9;3}wy&1>MMoGdW#WFy_x2HxMmcPiY@w?`Ci=i4D89+Pj425$1L*}y$Ux*nBz z=GWxgU;{V#<~49r5Bn8vr@vg`cKWv(@tE}QHgJ>v!v=2B-)!I}{d$8i=F6nNuljfs zH^1Z8DTkeYpTh0*mm2Yy^sh5;ll~nBZqk3)z)kw!G;ovtQwDDCA(pBtp`HG8h1=<$ zp>XoSq(9HVP5Mg>+@yc2ft&R2G;ovt{RZCGki&RI1nE&KO}rgu;AVTQz`)IVT4dm6 zJ@p&7stO|h9R@zkpr_8j&HCGH;AXm(YP^zuGu_SxZl*iNz|C~$82BKAp0B%>pL5I`#nSk}P>2XFnzx*cHc}MR>D&cG+EFbOR>9+HZ{&f0!k3)95C<>Z? zy8PKqj+B0#QclBdk=xUUS!~h#;&VSYVZ;c1IOVyo3GogAk?Qh_yBB%s0J--c$+Dsg zKfoAJ7RF>VG1os6a}&xi&*l&?&Vd<#^$hKn^>5}}<4-Wok+=-=>+#HSP|RmS_^86^ z%5Q(n{f%DMuNm`cDnFNFBI}Tx*b4)9@of2Q?mC;>;|llhm+rI6Kv;w7nu8eYi3})tFj8% z>9^3D3b?+F!eh7?*;Tad- z%Y4f5y8!kfAYYl^g;?_dfth&>JaR?(X9>FEk~W$CyF+#aUGQV_s}W~fWV?IRe-hRG zV3K96VLp?r?rQ|E-LCpY$kz(w-$&eQRoc(A@MFFX=E{jPDYk=u+3=^!6lE~Whq*A1 z0RI@g<2;yAkW20d&oxhaPKRA)(2QHh`461aL7DktD0t_VaT`t$*JdSW8Pnm8ZKQ}A+@hSPK%aLQNPV&RE8ox|_j=~S+r?HcgAM8i>3g#+N zepZ4PdY)x(%E~HNC1vLwq`OM+tVeAW@I7x#s@Waou6$~q7xSNc)%yB)_wfA_V$Xzb zwaZuauHCcp_v?M=R|}g?vH>R6R8>4zkuO_?~e*R@lCV@7m&VHI%=-2+#Mv3&niW zb)O-x2^nfr<^NTx_o^mbVnx66VYjF`ffzHPohSpU@lKr`saK4)iT=X9{W4W zC*}09+r8^4qm)&Kr<{_n`yi+L|1Ra!4|ft|Ba)nA?-C)WYf(-s;7`jB<bb@Rz9eCe7QSd}K66{O^@tC0 zKa1;d&MtpU$USuS;^6uCA^0`RzF2~K2Kx;@}b~p5;d>^hayEg@TVtyd?CFK1lJ*+uT1m&G$@jYvQ zfU?=QQkJc|o79(6fIT`M>mGhIv8H;q)$;iBE>ZSYsqgN+QSEEE_epXoWcT}4%ifN$ zLI=A1`_@}$d=1r@FDKSVpe%GbpbU?=@hiC@8{a^jcY8xpbJgF=8j?I#<;n}acaQa3 zA0jHh@b6YKZAGntF59jR0Q1AAvB|T_Ytizs;Ev$QC z;bJG&B>U^u=OFAB=u4ieKx`~zG{SLd{~<%;%gHJ_&|S*pK&E2pE)rW zcq8fX_~kh$ZkvMIAw1@g&xUR3j}X zJ%Mlk9_wW5sJ&Qs^&Qk#sVAh|Q&0F#wC>fm4*AOO4(nqQ z>IHQ|GS*C6XCSYcI6E5OHMW`1maHZ1Y+rD_0OOM171@SLuo5~3I!>-3&TrW`)H~{y zYRGXiqhHxVDgF+Td2Z9=bT6Yed;zIg~szkAC%i0`rK zpMJ65?%hnk8oVK$_uAS73;rAdyprfFUS+n7~~1)4Dtl@eF;ydRjWLZ zroAd%4|zepfF_sL@v9`AM*gSqz2+zL=|XUmK{6(H16WTv@i*AchueelOBqBhPb#^a7o4r?PPD80gWneZpe6LMsXkY?Ck5KJ zKd4vy?@7IqhWfn^{&XFsUTHkmy6ZCFoTEM#cj^_=Ouh1DG@E)QQu~8?1?#AkUJ13k zIq#6|53$Fyn%gVd-Th==O}0N0YPYymn;ZQ-&0pvChiq>@fiP@ey^|AFxdHvPdr{XZ zU$XsywFxUD=@nTolfVz%{@Cp9rrIA|&miBM?GL{9@f<$3KRj6bjy=>$kXADGsFr#q zq4wJ-o5ylpmHmLByg*m?T6aHd<{;qwK2;}Ml@DMYqx;O|4IZ@HlF(+zeA}u`wi27i zT2W10=V##^>loJrF&=+1>mK@#9`D`$WY#0umm~(W!aB5dMS7XOIFTOn?!p{-(T;Vy z)~s+_YpUH`tCCPlS`$D^Ht6=?ImvRhX}{tdy2p!s*UIo++Kuu|f>1WcY>9*6W{g`*s ztn*=~-}I-SnFpOOKEt;2&%IRUH4ilJzVh8HxUWUAox+>+^4W}=Y3Oh|Pui{hne~GH83!+NMaz#4OPn&I<>XxO82IOpm+8Mf z-2Cw}aVP(r@}#Cch54tgR@-aMc;bQc$IHZNOXiQ4z$cF%e~D-C^!bajmoE0e;mH`D zc2QdDh>YPQMhu~2_y`Z3Bk+^KBL0)F{~P8~dlhvY^WYq7?e-{~w@7oW<#-ykS@`9L z)0|_?u>fA{@guI?UV^x`<41h8aAAx@-S;SbuoA#i3Wp6^_}Ay$>G*~y+@}gp$9J*9 zPb%C8H?Pa_6Z9yd^%BH&HGYB~g^v-aWzAQ3ox;trjYxCHC4VTL;nyv2x`GlO8uwhQ zaP%$2rSF>+uG7=_ZxpWcukjZY?!%pz#^1y<(_JRe5Pn+WG{p1L{yT&3^uI&GL7a2H ziPzciDGFygymUN#jtbUXxl9%^^Yd`9hxSevqn;r0I#1|=^cn7?<13u6J9|4?vYs8&b zv$~H{_?xP#4pz!|rot^Xm^WA9*$SVlCfb}te#E5*rNmrq4o_v}7G(iUwL%Wg*%m`r zSw&f+(nfINbI?6O$Y`<(gnIEPuJQj`VQ!USp)N=r*`1C7eC zLrC8afkZo`QXM`zHMLC)NQV^RU3#iLoXQQ}Wn653r*b}g^oZ0*B*-{Nj1&{v=jE5A zs;n-Zzc6297c;HxFtZ#9Mz$ls%z6Zv*#|5b%gNVdE!~UY;Dg@B)tpo>X1$}-F%@4- zC@n!S|$0T|Ra1204VyE_mgsC(bD`ajhTh{)-&^ zYrSFj?|1O8^@-j8ItTw+&)EG39Q+?rxZVE=2mc=^oO3<~t7qP*zj@jD(_i8A&u^x_ zu)&15>^Sv0FXAckQT!Je_)r6X-N1(#IQ1eg#$)1rm7cQW{S{6=#L1xIU+ZP&%fzP} z@mys1*ZVix{pUIOuQPCSo`T+w)?O~XRC~bA=fMhRzRYr&;ov{d@Nbq&i37gcz|C^m zVc=%DOi=pW&gUWr9Q#9wi~dc1ZdLeb8@|)Q|1O2w%W=2D$JpZ8uW);Lop6Z%w1fWw z^}QqgW;yD$9QOFP8vafB)N4GLUlXrW{z<=yH!IvOC-JH&XqS_|3b)IN*TMfB!@nsf zdcRi2W8%vU|E8R5FmO{&h8b%`%zQ0yz^fE)FW;>W{!cpK9#xs`@^+mA9&o@L9q^M1 zx6AD*h1=y&@84>dlV0s3*9(ur?f%yp{!KaD>EQp6;os!{35DC`Q13HrmqU+g*V*MT zUEy{)oS<;K92PkEH`nA0G4$>MP`F(_XDHk*Z$%FAEOYRG((rG} zXY_fJPJ8_Q6;AqxNiX96GKJga)2nd1e3mHOE}v@^ZkNyd6>gW$ItTx+8~#l>JmG*h z8@MT-y^J*&Lyi3IGH{a*Pb=Imw{;4)^YgF~&qYT3gH>md`5kWH`q2eksV)KO{0^WFyiCo6aVPrtN68@Wtk1vb`ag})&6z6WQWcF6xA-Nv*FqN%nA@wTF}ShT}x^>;=~F+{FtQ<}bpzdy5vAG<##VCF3HX< zRCImQn+Fk)mFn{vjLxf`ysBLF3)OtlPRH|m5BHT`IxD@!8`FtXA$9o=RJdZddTUvJ zTe|v%Dt7G@b((R0-SF(VF;3Nt4#um~KV^$p)2}^#M}@a}vx-zF@09ka?)LDs_mQVw z^F}C=Gl7x*RQ$}#r`CAb>!RkLzF&ht`q>PBmkMuUe75_gt=XP; z`a3+B|CV)wyaoU5;pw*Xo}SmK^j}f}$InwTe)jycnGq>{J@PW0V|Q#{PUMn0J8vl-()Yd$tpM z<~2t}*S?Ou))0X>Ki4mw{j(q&*!w%7c3VGJ@yK_hZ-?= z7kkNl1Rl&fhI5FsEY}S_%=Lw>8~fXJtHmB%M;JGs#r}S3e(~Am2gF=C#!=jL^G3P1 z-!nDuV$Nwl(0dl+?+;vH?Rg*<`{rZceSHp^J|~!an7?Q9dpxRL3jJTpS?_~)mbworXNtsXqMM^b}S4UzE69PkOi8NZHKfB$DV_|H=Q zPvXu?>y{EcM@pAAHBpK5LA~?x7v(R_F3Ha-qES$o&hl^OE&K%zh9ansWWsI~LI3($ zc?mkN&n_-0$uAbWHM9Zgnb#QcFWaot5Be%l4{W2TX1qYE3|xJ#1oF0lt7fM_;#E;G z9@QL@KELw$x&PX4d#{kl3Hl8+CEQNyiZ&>PE4eLoGNZEVW~XoaTwA)5d2PQflvBoO z*YD>VUVq!Q{OWXc_%Hi5UV;FTNWC)>7{Ra8x3RNg^i)ldy4$0r+xGbqK36M`es!me zlTUX3JAE7D6hqgF*g}8y^ii#I7cUAe?D?{@UNTb0jPZ!;+`o-+MmxhRNRj8=9>bg~ z7tX5%v<|;Y{1S+1w~KqxVxCnSychAPwz!9QOj|sac!##Qmw4y4xQ}?Rwz!{oe}RLh z;C!B!&;P@gq=M(t_aDfq@W0*nwIS{+Zd^UvEa$?$LvgL(Z!;~)KD zVaL|%9zPxP#D{+!Q~1R-Ki<6Umz(={DV>)1-sOX@pZURivsajD^Z9=?{S()I`#Gz0 zcXjUGb{qaMC8O_m8#d1GF?Pq<{{NY^D*p%l-hSZWd;8{m{5{Vdv!43JZ->Md-FxrC zdGVvJoci>J=#NSk#MSpJ9`tWbf3Kv{v~@q6G(6+gOOOBJ=3%|gyEAIjpjBHwh~4tj z$6olssm0T0z5J)42S2@MZqHs9-*b8CU+%f#-R?&Q_S*1yyUyL0-gV8IowWu3U+2Ge z|3wdv?Aa-L#;qfFd^hQ#qkW&u`{0W^qUXN#Ume!`Wy$w{5EFmfqxYSE$M$zly!g;3 zzg+uP`;l*4xVEZs>VWK@zk2-0z&=O*TKLhoK9BkRnz+0-Z*muZ=cOC+W+e{o)pNNg z{;79*e*f0&A1t`J{pz|We?RG1+_9?yCGS2oV*Fdzo@qSW`L1azU-Q&las*3U!mod; z`twcY?_bUTq&QcfrI&Sm@JH{xv3kkI&d)q~?ZBTsKd9FYr;lCMr>Y?R@$Mb}Fksc6 z>r-Bze)6rSo_j0$Pj|Hpzw1mw;5aeCCt z=`ka)WGejnzw-YdtbhON@^_cto$>tVyN;9=4czzo+rRM*ob;!cZ@loPZ$CNunda82 zn1_Ec`@DDG8uP7jsjgo>a>MKo*A04eM9=#MJ#yzYKkoI1@4VIYpPLdsobc*`CtrR2 zsSDmJOPKuLp#jrIdS=cX`o^y^7w3Sw500t+ZN(EW{NbigX4HOr zP2%2DO}!8O`hjl0z3va+d-;Rmf4etrOxejd7F`xy5dEE>UO#q<@2_3=UUY58l9J!O zSJiUi!b9Hv;nM$a)_(Xu{rAoE-~aFO|7@45OCGp;ao4}Udt%JZrH|L79bNn8v-=Mh z?-}vrr7xvD{*#|KSS5)M?pc#ZpGkFXCl3FVZ%{f|NmWVe6%}9wgN=9-;@`5y z;ZD3!x$D$j&-V@J&bqoU!F&1-D1(7t;XhWmM;mw4`)ZAAGo`W#?9n)l2fTDRJVx3> znqDH=I$r~B+BDU0i1j}3NH)Zelz;6{k8i{wAB;!aEH%zOl8H}1I9?jhQ22Ec4&qlR zoHk5e+P|K^t8F0~U#|RbmEME?Y3r0m5n=4a1kzcP#;2vHUYs>!*5y}B%o?3BX80&< zZ(@T-q^6}4&mcZ>R9c4eK4R3!jNzlwQ&VktT53AtNyh}taQ`DyN2d`VW5YoJ;~62+ zHR8`0k&blJF||KDo-vp_2|O*;!c@(yrPt?*EC}-}vp}pLBEZZ?1en=~05cb=e6;P0>y)eiBj zbBL$PA)bIkJUblX+366^Zijfj{RLcfHvA%fkZ^g`_kijiqTR-Z zJW%0w8~hpIkuJtzUc=ys!|&^cAAzupvyB~GCFC&&W>i|Z1uu@T)2ptJ`h|ysZn(Z| z3?LJJ?0I6iD^++to0r{h7reCRo&NP6l{9dhmpwe)ZSoFmhDv|6ddcxD7AbknOY1R~ zYozqw>@2)lT#sU2HYY!K%Pt-{qDT*rf7uuSJ~dx?4B#cB484LFJwE9Wc&C!q~XnpWy`8DhsSf zZ8r9W(qra6oDDe+W8&KF`FrcA6I@elVAvOF6dJWSCo~}ieuHb(IgZcsBlUThde1Mt z*H>K}&W^*rO+5dOtbc-vtZ6(4E^J%SgeJP zln(_Ez#E-#tWL zq(9(cXJ)l<wI7?NY&&mBBLUHu0y&G|0p(f6o;W?rDteM_|W-rb_l{nABKqfwqM8=`^dX1)nL0GW+~43uHPWi`%r41jhYWlxpUIPA-y`4a#?-Jmbq zpb`A<$@1f!=XhnEIX`%&u9iQ_-a_m>_1(VK(j?qxm%6&0hJ4Ahb#ZEzXQ|eJy9?}Cg`Rf;vAa1KHkr( zQI?o96Rh*7V<~5skE{83c4o~d*N(^Dd=o(L#2U~f_5=JFXHJqwEU#*eZEE@(QHJ5T ztal#Z-1p>NQ8%rY_d(NpkSlqPDbIG}`J{4BAC?jI2+sn18+`aj^{)}H`2PJf*Z#^j zy8X)|=T?~KDD5XP>Wb9oC?$ z#w8Xr%IQhxa0U-gra=tqM40@g#bVAAmKkbPJ@P;x_|xkT`8+RIKqB$r?5Md#OZZNo zpQDe&Ar|gY_Po`!CrkHHIWI|@Z^*Yi$vrWLpY23_={_6%oAaL5Di6eE-IPGU0oQ#h z`Zwe63pX#~W^;M4ft&NE#yH>;9Pk+q_;n6=xq+MVc-X+%Uf0)216SQ8`AXGq=F9Z2 z=bjTc{iizkpJ3po4WhunwLOdpmm0V+ZN@Us88Z2Qzv17Mhn)uALuVHE{RWPGzJk{W z25zS7QT3epHRT5%GjS0&>CtoTiT4i1jt`gN-;|U44cwHIIs-T3dELNGe!gws=9bK8 zzXa(t<)OdQJEYUZOAOqk6Ya`iJSLs%9B^~(p&7rqX3)&n86zGOAEwO7q|@j^p;KFY z%fgcE9NbHm%6ox+!rFrD;U)RYu%3Wx4Xoig#l`>XH3pZ3%;JKND!Y=Y_;<8nD4~v1 z0oeBiE86sdoopDTwsduZjKjQ!!4b)ZajxM-6>AX&z$jInqxZ zr9?d}CB4RKY8cwq-a$H)3JCN0h)O@8Ua~m&J69XT4CRsXYhE^|m7klnV1ACaKzKYs z8$<@4Q&Uro|BUo>xH3kjNh8F$&qI9avJeGc@#w|3uRZ4IKT`wVt>YYb_TfM2hW&$a zrgSdmBu01e&svEyuUFt_x$%Q4;~aYE$OQJet!V5Wh`vKP{Lz0V&TVHO1!EAE?vCtR zp^tl^499+jAMs8A&U0Fm;n$3p{r6A0;cWKV-Q;X;w?wO>$pC z-xj%FZFLOyk$YrTnLBQXAN>vARBI38D7(E~jmH}MJ3s6e+9uGz{sQ`&+$$Y4?@@Q* zc1`f^$+ns^tP=Ge`Q!Vu%hlPu9jzAbVeSGQI=)7%C-5m74A&fd+>!fB%QJW_(1I~#<%~rIF@M+kmPOVvp6dvhGI=zx!H|R`SW_8W9T>PcDC#d(pv58Dq((Ia| zuqiSO%T|}`X_nVu@R#-_lrh#{)cTMQ3uU?)JS#(=Z!7wI9@vyJ(`Xam-o+x%DfHt{ zv06}myX3yEvhTQlxZF3=UT!17L+&k4S>aj=rYm?pOy1j}EVdu^|Kc-H)97g#N{Nz$Isi28dUWI)SC<`mTJcCvm$0q^Shrd8AZu&X8; z_8s^U`vH594%&(dt~hVYSgS|V3hrka&*$zH3 zs7Mh51_Y&YxI;yVAu3g0b3zgfa!E{rL_s+qRa&rxN-I_0dbp@SeJib?P_+b0EmgFL z*3xR*pjfe}#Y#1?D&Oxnv*w(2hO-s@_x(TL_dVUubI#uL+iTXWnOSq$b6LaZynS0R z*5LBHV5F^g%1;Gvsdp%Ea-5_i%iC6?3zU=NkWs{m@yS6r_XSz|x`1B}!nrTV-nRu~ zFgXb4KG<+9$1~~xtB>&e59K#mW{n+guEmbFBF^g_&vMv*bUd^8EIc`el@~|_JEf4 z1M3aS%XVktH>BM`JHvRmc4rlE*Y0TEjI&>VEf@Xmf^bZ_U~JOW{eMC@3Fw5&N0#OH zO&bxc?Sgu4uqo4$meMXjjy$F%`t_OpL1&%6nAk&&jlg&=+NIbH(N^e=si$LT^ODa) zY`y5(!&r~hJCl!I*ft++o1|s#iaNO~;uDqp&pKM|kyAVvH|RX-t3fY+Ai9C&7#ZW! z73FRP;!2+XC-F%j-sQcly;#N%>1g)uWt|=(Bhqm$#@Q+3Ya%1t7Pbd$GgcJh{0`J% zuAW(Sjjc0T#|%DB>M_;MoC!ahgSPvcP-i$l1!eJ)6&TxmAN)I`o{8Zd+a=b+tn1zb zuFD|xkM)SNt;_ljtO9F)IlySVwj`Y03J^utxQ<#PqrM~a6jBEYY5krHOz^avc~=6bx2$d9_x{OQ5< zrr!*ALe)D~ucS};IsBZx^Uvc)y=-d3zOF4JoRgVY19D>s*Jd@;lgMK`oH#%woX!IU~82PV@pUF-Qnk8kee1p<)rj5nxr4ZvTni{m>xz! zwGCrA%em@PxOij=V=Mf)vTo>97;PcbucFb`Dix2)>ueZvL*j83{QMDG5-!bJH-ytfW zazOvh3F&E=GsA{m9uhX=cOP_t;f*lQ>FvyX_-A0ZIi^z@9WIGMU2mR=WBHrg<@gv2RRU9bm!be=_37$zQ->G8;!Wy9DV z5=N$Y%!eNxhK`5Ho9gtu**e>X(Iq{M6I@z-UfvA5IaA)GY#o?yY^>#A-Olf9V@qGw zLa?6a59=9vxH(w5|B@X{iQ=232z4vwO%It9w(AkBodP$nivDEZ4(NlOD(wpSxb}+c zCET-KEAg?y?fkZ#i`DBU{so#yo7CEiEAd_7cwziE&&eJ6_+XKfMaPG6+0uHj^bgQo z%EWdkhV~EZQ%>NSCR~&867F%d$9BC!r{p?{Bk)~Ko(c5f0<6=p>0xEO678;&<1zS8 zB>i`U|5GqmoWIukKhgM)V2uVb*9S;oOlUXg+}wS{xI4n#$@G^JAG4ot*JUsbTs*li zmuob3w;`>4AN|+CzIH5xYc?zv$NC71F--d%)r@|J#ZqfQqDhRhSh@t(Mrc{1E$Omy ztmpv7nw~_wU0Z6(&(!qtQ+bQk?W~YCC{y{_13zKqhxO{JTI3V@IDdsMXF=Bnp-+rH ztm*g0QJ!7jxH2wbAD_8SAK6&m@+SCg_S?X@Hhg}Icfq-YdvR|Ex;Go5ts|i~(4o9$ zQ*ZoY%^aN3H$Ol6(OoVJYlXZTX{TH^15dA>xs^tDls^k@!(zU;Tt5BsL1nepkt4Ll!% zWyJsP;5r!nol$Ux{jT2qIo}yvi%z=E^J6`3=ZQTGN;QEp+biS+JO*sD)XB+}>n$R*`;N;`%wK{pu3!xt>^aCZs zS4p^6gwR(BeY4Ov2z|ZarJVT0m5ccBnj6CBdm%W+1C9Jw%R-7`%O-eO@P|D73Bf-W z-0AIa1<#QJ}e2xuwyN6#Oc%iLelWT~s5qznK-zs>Ehd(Iz)v{osQsT8; zaAyzG<@+B5ABc`LuUdNx{wnxGf;&DR2;N?l#o@<6U#Slb9^OrGxBlJnFBE*#@istL z?!N|HScoL{_Vp0_vJgBLf=>;>XNKUn0B5|`%K{e{-#Z1*&$IHyMcOrjFB4pD!DAu( ze<}12385>eI|Sb&c!BVLD}+xL%0K0F_I(_EXW*IAbD+@oJkc^v2!Gm-&O}f9(d55f z=(h{~tPuL!fgi8>4`&H|s)tn2$m1Y}4=o#6GVZeCvgxo`HoT;ytae62Syf$KO5@hKgLP_!<{j{3t4P|DXP8wWOhc%Csz^rymdsR_0sl1{=^Wkv_6*KCv zLUMXJjIpItXTV8cUO&Be*`%rE*QS$afJt3jGZ|uHSL6*?`Z&2}dfB9!x@qY?KZk@| z>Z__MgK1UMDr#>`^IK@&q{&U%vZ+e{+0 zm3|e~RTWdpDks-hV6iBUSAvOF$T)mL*|5Q-gCTP&;~Yj|TxL3qdUFU^F}13^&e+8} zQBeR}T?1OQ|!^h%#qm0mW zEOkxhjH01#CL=)#;ZmbB*R9n}27L%%3ZW~Jl`~AnT25(>wBlypGyNNCP(&xOlp2jn zz4&@6%AZATv3D4gzSS=!7|YiOUT?hEJ6lVJ_+G`2D4Bat7WMWKaUZm%1EOb zah-88%_}EPO*tmBj2cC?L1JNac|(R&0*-QQibBeB#WYp2=s+$X#_DLTRD5QpQa>y= zE623*DOD1$WO((cYBQo(ZH*;iGsg}dQO1?m$(V}6*59>tRoIz{+PjKG4M`t9p48sz zaxNkd@fG$`(b6wt~ou|KL-1yWOIOYyg$R!q`Ad^-+_fQi zApLC8Yd&rbwx4e9+!j9_3KSn5-~I|e-AH2p+?r~ie?sVe{;L!poiDEn?(=C5;j<@% zPbc*2dHH-WK5Z^vo&v%Be7rh@Pb`FwKL16>>)sGPi4Z=k1o!26HH1%d2%kM6e2SzX z`RUVNa6f&92~K&mKDhH`d_HcCx6fyl;-k~26#ZphzTR#O!Sm2>%|u@vg1hrmd^r~h zy)S1%@zHWNh0t#g!CzH;bh>@4aLr$z+oH>FrHl{Io`S~Rxh+gLjBmoI0YRMwQ|JjK62aG$Iaihhy8 z`zm~C2);_;TF!?QuH(B=;hKJ%;C{Rg2=41)*f}-F$oL7^)tr~Xq)oxzNMKx1q$z{^2?ofLq5749H!_s-k@-uUva_x zbek`@pKc2jA6Mb90EF+^JU zd>1Hsc{JRXDg1oJf0e?|RroH2YkBr6T<6yTh3k4IUzEvD|4xGY>0c-~(?RRum=He2 zA$(?s(8ojQmkREOyDo&!`VcX2~Vxk!F|cZJZu9TILtDhr=af#AOU#Ub>iA@tRP`{}$mgwN6tK20I? zTSMq~3GRn`AcRj#2%iEOWcAa>o$KVM&p@H~!<`Vq=W4-yJ_|zV7lqI#1oy*zB7{#< z2%on@==X=v=g7Q(A8t><{d6l7+>dXq;v+$s)~7+?@@Vk5!ZrPTg=_ka3U^}#WVBu3 z7aPv@?`st|me;C^}8F1TM_niU`EGMMl_4&mbtSN8b~lgRtwjuPCbzglp= zyw48d6A$6DN^pK3m8$gIB{=zySNMKKe}%&Hq|;A6-%xl|aPrZ5J3--vihj1jb^qL* zw?#f$pA(AyD#d4=!ZrV9!TogJBeHYhPDmH{RPjx9Ioo)%$;Y3w{tmT#%H3496s67L})E5(T7C6|gFL^i|K9LRo-&Mz zCwsZ@^*1cvIQfMvU|FI6J`RxkL6KiR|C4W>{O&#qZ}_as3W;;M;ty9ZdrSU1f9`%M z-ni!^5gz)9e~t0kr)Bf(ryc2HvM{Ke4t4qd>Gso(J*8vwL$E*z$xq!;ANw6_|2sm-2h*loi;>n&LO zi#@sTH60cGXp5}>hpJ$WJ?#b9bPo<5f_66V zeXI{>TC{@y#;(B;q39nkrp|NupT~X z%aQi!xYj?^~;3&$4q)aQ$-VOX75{36HkI{azQkvEPz;`2osuGA!iDqtMY!;7dD(w9U|uOEZ^3 z9}xG{o`t-%G3Y`Jb|JZ+I+J`%Po~+Uxa)jleozjsJJ)&FVr&PrSxfzF?S{4P*aLb1 zd2-pn_#Tx1-SD4{I;t6E0DSV^ z5bQOSgEj^~!r(d|n3hQ!m`LxrNGr;~{9zhL;bvVj4Eq7lUM;S`p82lWf4n>|wPyqR z9Gd>Lg~GgZ>-ycDdm!Ai-dCje9_c+vG3+sBy%L!}x`k<ynDv}$R zGGoeuskdC7%KLUf(Q?>g3673#+D#jtZG)nvDCbsp^Mu#QCLfxP2#V}}qde>vIuY+u zwk4b4cL>sj`Rwv23M|DZwT~#?CMbd(U8I5C4}peX@pX1z?Y@Wz?1LsCpQ~S88nqrs z>Fp}ycXA&P%Hv#9f7&L5W2k0IDIvO7&b4z*dT?d3ujdc1fcc5@^@rDA!M+tWZ}l$8YM+-PpI~>R#pv-H}{dH_nC4 z*9ht()=8`zv0k$@(jInkjtKga7x`=jAJ!)`Q6~B#&gj?WZHAoO!_BhCy`Iefr@Gp@ zBpH_4mz{u(VeAWE&v^YD^yF>)psc6r6|1Y%0ZgmrG0eNrhHL?i(>1n}v3A?oH}6<81BmvcBB&^;AAhL>zQJ{a)nBLYuV(^<~a{E8A=EZ}-7Ty9N8f z%kcg~#DnsaelXh8BjRp<-l?*`&hCFpppC%Zc~dTJdFr_KDTy!rFr7%lw%wK=+8w67 zU|UbKU%_yktzwtH+HZh8aT0<$h?EQbFuB0k}gpb-Q@aO&Ni>r^KHiV%m=7H znr<7>l2uu}X8DCd>r1e;Kt8O4Bh>lxsPlGjpu4jkcF(rXwC}C{+h^`Qq|OK9VLJhJ z7VVZ~ccVVhhV{wVn>py^1oRzeU?W|L*}8`H(Cff#-A3H*n~b7N8yx*FO^^Oh5yR+o zYp?`;slNBaJ~wUewt1arRx{6Rc+ATv-aEMyu!kKHo##Hx&4}mIxHmr&-9%Yqs5i60 z!`9$4W_iIbMUofW zS3ljFq3eFS!MZ@wkBzhC6^D+SwD;ly`ws@U>1^d;o&>;?@*=JEdsAkN{cPrsZR36f z`D`6#!-LMRPe2Eqd`>T;*c(cmve_ztSEX%kE`J+vNA5*mI%{7Ji#`k?+2Q z`A)KSrQBZ8xyU#7or`{(X^Y+WZUSXG4jqrlcQ4!IjA0YR~j6=VV{C1rEfmYOWA4xmjIXAfe9Sq6hyVCSM?%*@(T(*bNtl)gt z_ZtQ~60gC|z!ufMvww&&`MeHj6DSkwtQgWl_vM_vunr5PPwBAq@2Nxgvb(-Kzt7%A z8ZI;6WvOo*d`GQEy^QYwt6R1WVO_^>DO=aEZeV?sh5lm!zsb;+)8>n%Wtp^X8}?}z z{Sf`B6c6f}ZHHp0E8<8Ke$!!{i`v}{d z$$++$?I-1O?I-)}3A7t7ADAu&kS>VtA>YlqPw41lK~Ti>Gxo)x=j3Jd9rw9i(GKB9 zd7IJ4nmZ3}{OC5}pltJ8fdumGXm+C{eiT%Qja06=uh`CbstpsG5NiMGGXi! zI2~pi7sD6@dC+D7+c@sErmT@8gTBn`d9S&C;fZTwtpCx*+5Sqt^cmU4K^LBM=ltVdBk+U#>>gY}#1&rt`de;nVS{=RPB z4MAVeo|jq)<%o6*+4o}}n)VAiM*l4Tv?Gdg%ab`^Tny>G`$^)Is)Iz zu0Oa1Y1)jokMWA*yE!ou{d=S<-2vRp(@1X6cNO|`e|*i3BiTNGp3%oR`g2YAPF_CF z>6-0dx_pIRiO#Uk#cycqkNOng-SUf-zgtuK5JA81tH=X>L(xtJ!#@>$CtEMF|E|JE zpVaDko|F}STUecIMn2hh8N$cA<%n<6FXHX|(PoBA@2-#|f%s*i&&hO&qWwxh?kvbl zcN5y#6?p%1^Ib*RQg%R^c`ik}QP8tf*RFsc;~!WYV+>6wD~X}N@SPdYW}n#RX{vom zwNca|eji5hO-~+)Ibq)u&zSECev3qqUZfo~UcN)X<5{F7Wu-h;PU%CT{4QT;<#aZ` z_+7RI`A=P0el+^`N6B}w@I@bWJ@bX~u0TAPCk%^eNWBP9rrmqyGy9wFT?F4`E8C4; z!?b7L%cVQdb)kIykk(d4=Cd6eiKB07b&u_qd<&sJO5L-4deT}v0(>Q8vi#HaE{eV? z^TOskzfDs0SPXsE6-k}oyOeBk(=VkSv9Fj4s|o$mxb%%4Y7><5T|{()^%(n+%aQI` zNVlYX?;Kq3!e_bYV%}MujiTSW7W7+C-r{JxIF?0PeoHyMH{}QY*S~`7Lnw`5(yu{Y{Q1mo7Qr?;sYb<;%X|6J&>t=F>GvL6eYyoj{*u3xL$d1s%9 z^(4QSUH$qm;U7N%Iu7~rtBco+$2b7PWFIg%A#)q6>p4Bfr`uT8j}hBXJi(P2wy{wu z8=u#IVEap(jys$j-YCjv3_AZ9(jtD8ZC@vvw72~w(nQd{`sI{(3~g(w zjpKKPlwrJ!bG#jW{wV6p)Hy#^w-e^O@nl19`(+kyHs6iJ*=J4ZTm-n*A18l6`O(g< zl(v5b`m3&=$9FOF-FPU!1j-}hGx1jHSSp^)#+DGnweq+=+6tr}!(VB>P1(*{KPG&X z)7R10^krt-O?(CX=(seYJch-k8RgOVK|E;ZiEaG?+}YOOhPxiGrY?3Zj&4e}^%%2; zJyO$0q)vp*1F+A=c?Rkx^pEpUee2bjV+8fP)sZrClxSo#)xPqF_^*<84fqA%(4gL46xhuKN{SWFw9 z@AS#6$C6`N$+VDuPga*;JS>HBTQr4!!KH5Nb@jxFWq|g5w)1GaH zOs^nrm?K}@^*-48Y!fVr)}O}ZKub5GK4AVd;heL4$U&^>rv5EajC|`S92DVuYD~9xA+q`NOzL}5~U0|~c`DpBp^F7mt^JOuF$$7FiNRusiX1&imjiIeX zpRNbnOV0Tj*(4sEU%M4y&Vt;JLr=(q<7!>oMb}h7{&r@J6k{5~qZwsy0P3}S@!JW% zkk^b=;+uQJGLeDbsFg=TW{d-!GBkMM580@LTl zf0CWQa3JEs{BHps48`{c>N3i7%ImC4`CZAn;Ka2#7$0Wb*biXbB4|5F$MGb4CKtzI zve(*i+74z6j&#i!%W-jh9lYGQmrs{K8)^96`q}(qXd_9-bYE%ah1eHhot#Sd=-)7& zh<*$Ez8@m*4`v7ZvS4%WLd5lAq?wHukHwq+RrlRGLs1T$(WdecI;N(f)vk2~YGJ;~N{w z5SAHZ5G?WD!3|de>tf2S9m8Nhn{hr3cj|0M+yj(1{LGnbxCdGI{eXY}xehA@l524) z{%vN(Ot{Q~|4rLsc70*yjLu|R>?=kp*_f$P24jEFnH28!E|Vma4Ka%!$=e}U8+?%Z zS4RM}ZQ`!>^3Y#!=XN%oE(Pu|=ZE)i;72}V1a$Ouf-exfQ0^E5&B*8bLch_YUnlrp z4}SsfO!E9i=rO-%F2=`Pa8u4=!Ci{*jQ31@zAE$+gx;MeHadj<(h!{Igk|Di4V?1e z`_)_<;pW9UA`|_6LhtqzyYt7M6MU(tN}gpCyb;1@ztFE1`h20MO{q-bb^uN}n}nYJ zd0h}fKPm*jECi2*;MaxVH-zAGL-0kwDgQc5`ts^-Z^60{`X_{bm(VxE&Fjq&dbD{N z)9pBPWEk$oqpW|7%a|(yJX1Qe1DgpS5rSV4f=>a?aNXXeN*io2UvOvh%HjVlc*0gh z!B)xN$3yr(8-o8n1pl+}uRPugvP|ST66ujCz9)s?gMc$$9}Axak}sDEK3^0+PxQ1R zgimb{da!|{r?F49-*gR^7?fM{cnZ7wv(mHlYDtAg#K8> zJ5zf022MHW)0iZ#G4Ri;B!vE&5IoF=7{2!m{~cW{U)%oSSvBAV#_CmFRYR}-y?ghj zl@u7kDXX81rM6W(Hd9-NNq>25UCoSIYXb|GOpGn8bOLMhDZ>lvlZJWft7!?wSQ^UY zS4h%dS>Iw^D9J-v8%ie^%Tv}EktI(ju>6c|CTrmd5+zUE3?sFcaX{%z7AeCvNqaZx zo@wjlv+M~m*y%Vz)XRgGNk+qq{l+w1F;4^6`CtXlWpV=l- z$}W(n#v+I@g#`0e=^SY-NeFBldY4^4V{*k52lB+&G=PV>rUBNQVCl>yU1{e>v$ zp)aft#y+WWbWE?hww%_hC>13#HiYm@n@X8D)6bz+qv-pF@~JbbVC%`4@v^prf znjXNRL55qOa)qVNXh(06-ji5NR6({GJT^ByG;NoP6o-bM$!3(Xy?1E*)9rm_P9sB; zE`!OebmLTF8qic^hnNX;M$A(6s5O}sSzQV70BaG%e|ie9=92Fa23mV3iA?%HAU(Rj}g`l1kgU8JSNZdJIB*VX8UxNy_r6@t$X!B+{+^p9AU=Kl$WcU5?^;-k~2 zMR4v>)L-Qv3(h@?8b3z%CNaJRihqBFpP_Kfg_w)B- z#;5$r_Y(Q&^vP5BS&ClUX3~5HDth;=MsE`oezxLMtMDEQpRI7MCkqs=^<-HHzD?n- z&SWsTGJwGN_EO>I3-0H8C&B%E@2U9ce4n6jtyfbOuJxfo;b$s&;vu-U<)rDCh0ymG zWo3MIIuBF0PUpD7)6zKvceaqo|6C=1lhFI=xm9pKJzrA%b$U*f?{M;uDE{jduJv}W z!gc=UaN{8^^3nP*M&UZYVhY#!RjqKH{tY2`JOp19f^SuLZ!5C-e^udq6s~OyX}sq# zmdMZd{tDOm?rZ~*Uh~m5fX-9lZc}`;oF9ka&UTN_fBvy4Ikmpst8mT#fWnKEJh{iE z_-Oj5!nOR)W)0=he6(#EO}{mS&jE#N`SWC4hWs_|Y|8lfgb@115PU%hzC+=!-8%;-}laicfOP z7%^L?aNTb?5Q4WqKBYec?4$XQDEtD24^+6$-(?DSW9sy_RdDuCzNYx>65OvRUlrW1 zCz}<2oiE)_uuPdgy%c|K14ZN2A@qwCuH%~s!JkmL)`uMm*ZQza;aVT|gy8!_@Q*|A z_8n5`p!KSg!nIzlSGbPvF!@MedTM-|;LOLUO6O)puhZGtxF`K!Mc@9!l$@HrzruBT zj#0Qy&r*f!^o)hzQ$z5^5PW_Ju5E(oaPJMF->7h1UbcncJH&PZ(_iOfv%)o>{UP`< zQVEieuFoSOcvRs!+){<>e6Liv)~m$|@2T<~o6OBcdHN`PTL`{a;X1w(WCF;K*Hne~ zR{ZBHT&KhS5d0VkjQocvJ_QQb@+?yLP(}Zc!nL075S-;=xS~Hsl%C;g`iR1HxhPV& zE*Aq8uJvC2J@aKA zg5hfV!Vvrkh3oX+u5gK>38h)#I{o)5T&Mqm5Ij#BY05cT$zQ1OuPZz%xZiFL6Wnh% zCn!F;-Ha(*=i^j`OVXOqH!57G!*+%1ba+YOIvtur@IVZyG99!$$0%IO6H&M{K}OCZ zg^y9`78Bf0w`#%tbgNZ-E>V2uD}1cN*C|}r5Bn8<0OqqUL!`V){Odjiap%w7uTmJ_yX#xx-?`o0`Ezc59=CB0b#Io! zHAP{3^!?MF?a|P=Si+CXxH8K;e}4LL3?)u_zEo!_UZ zFk-I5w`G>A8px=T#o97U?wN7+$FP=r&Mn8T(e}9xp~3m!FVk zPYyD6z1`1Y_fa=t-wJJ}p_Yy>~ zhmOy?@w^A??zx8A?NKF;Jr_j{mmiD$VSL9uS6o-ly{LAN9Axa#%yW#dvwP}XTGQ_w zr1MOyv8R04CxU$m)@Dxw^2O~@m|>pn`hDy{IArgE+gHvwv_Nj&_u-z*Z?OXqAiZe| zAodw~Zuh!axk1-A058<%d2z^&IBbYRM^MN%M1XVemD^{YCr77~v(bhA z#(UiJ$Gsa!pT+o@_4BOT{V7evN$=>Q@~#s1O!TN@ zGvYUg;LCuMKl$;Bn*Shp4EId@e-(oN6*&2<692Ul#cbR&@i{gGKP?15Cj`GR1RoND zj|;)8LhxHdaGuxA_`0<+t0mqKgwXR`?o8>hBLx4w@aLLxUSsSnaOZWqwKBzmw*ejH znScg`SE;=Podm}oX>&;zH0TRFlRR95Pd?~>n9K363Zb7S^zK|T_D6ZeL+F1Lf+9(hU#ZIn7uXDnzNpt-!eWn2V7a*tIp&s_Ohj zxEa>k`b)W$pk^&=ri5~fT$2(yfJfGf2gAp%)mE#o6{?nPE3|5QMNMUL#j<))iL*}e z0&C z=F;nQgzMSU5m{gDfuFV0Lod2c_x9P#uhVHwjMJA*qaAZ~AIJ3d82Uid%Gt4gJvQyy zY0^8tB#j9@=NdUa(JxcDOm7+g zs}-)(dA-7Qer;E{9_!zwaLs3r!Zn{l^iz0IeoY@$xX#~Vg-47}`^WwiFY?j(vRL6= zEQ$F~C|rm8kixqv`j-T!Ug`AQFSwt-ZVk7ezb%Tt&ffy`gLwJ;qk{YVhY9ZUA0;@` zLGy16;lDJ5|FRJN_lEFqQvA=dQ8E9ohVX9=;lC$@e|z+^c=_p&C%B&u5yAa*C{p;@ zmZkZ3{d4liI9T!;rTA;yjVWh=-u3C}$>}!nWss z5!$8jugNoS&GJnCdae`2nF zjFRV<^&d6|>B9fAbC7PW-wtV~7=KQO`SBkLjB(Os8_uLH1NzgKi@&><;3c06H4&bl zWnj2;okX|u=k8&1kgejMe)Q%1IV@}ra+zfC6h|m`-#^`wMCp{$NbD6k*f#Lzr(f6{ zq&uhh4Ns5!@HxDI{nv**2idQ0pZ*bZ9sV3-RCRo#CYE*%vTH4DCe;S5fYQzY;+!1k z`P}&^wB<#6rIp&o9_)N_F3-)GxjPbQJ@{en&CY*CV22X!#VDbz@w&j+MdUo$>zHq| zcIqr0!tCLA++gNd#73QGuh-cFrrlM{o9%3t`6(A(+%DZQ;n9A-mPNn&(`UTnxe8(a zev5Y~>t-%%RR_%dVBTl&DXDo$%n6q8TpZqcmJsbJbIzu~x2KHx(O2spaRhe0_S9Ls zny8KyLMl#e*4`QtC)$>FcHO>gd@`L)#rW_n9i$_4=Rb35NP{nYCF`<^|IDc|@pRk$ zzhRGx?GZ1w-R;d&`rpNHa*o5%O_0Xt+7SA>5PVJu{_PNac?iBH1m6^b|2_nNEd+lz z1U~}t&Xhj<*35)+OeYi0F`Z2K_z=7z1ivW+|8@w@u^#4QCGNbM&3_R5B!qs0&<~T2 z%?_b|HiUks(C49&=H>L|jS%`zL-11&UZ(U3vxCKb_L=B$&QV4@Y)LF zF^GRAc?v`DYeMivA^2k<_-i3J+P94Iv_+pXlbjtxaN0x5L|+nuqo0?NK5VWH1KZMx z4Vxol54TL_ox+T(=*a;^&%ysp6H#FnZ!kVzXnNFTwRMxHRh9J~(1-IY#zG11hBK$2 zh^G&Xhs-*FT+`xP7v|eT?CjWT12p zPqPao(K8gONiGPg=DO5Nu~x*JOhj4URSngLT0=@1oywGm87GOt=N)B&#S$Q%|C!yw zTBL@m`V2;Im^z0)7xtgoEzGVazu7q^ujjVh_@qB)G0HZBW)4Evo5c#(b6XP>eu6yn z7L#Z4*K;4$g5xaCw7IRRg7^3E1&Ys!^32;(g{x2eAfa%6(70=xJWw7t{zYhq!nK^c z1gD&O4&qh8DW}HwC_Z{_>urT={s$C)J?GV;_-ot^9#MWhcjLxX{d8^*I$o4t&ynQ` zPWd(7NpSMfb72Jv*Ydl$Kk~=7bMkWie)88i-Msv{4>won&wUiDa3jX2{aY5o=U%~m zKI=mG=(#^VclNfT@2bL$px?xc>7(^(s^EUSY6bV@nXmXn3`hHyP`H-Itqo(i1&ZFy z+4=Igeyl$S#5GgAD31*98F#Mv$JiurJ;v_JK5;!4=E@H7?&6oXh&&T_eP}|ChPa+f zDpd4(4y(Vyd&o0yQF$hxugWuTqZHm#;jX?Sy`D3gpy>7ZY)s*L&Zt`9PG&;23fFT+ zjSAp7!c3cpaEd25zuhO6g{Tzy5ni_q}q>MP>i6#oCWxf_iArd{}~NV{0K6N{#y zC@)g@-P|wdAdpnac06C`SyqXA!2~fM5PH(;i)AGjKcDe|8j5Nv}68^?7Id`+*D9i3XFCM=9`0}Z^AvtpsiS+Kcs!%eh;gPzUCoNTy4^NF&4A9D1Hhu-#r{dbk}xyD8RkF1J#}FXC{1D z2+q176ManxerpJRX9)fPaLVuGu7#V|FYwD0?n@y!$9!05%}5o8IZDP|R?KzEcFe(< zqUADNJ^G<3&FF~nmK>Y1-Z=PDRW+q-YB@%`s_N=$>_CbkRd%sCNMoHT8gJFF4lXHJ zpJ{enrq48I7hKi|C#khOpytK=<;6ZS=c?V+T^@)_b!U(<3fJvNsltzuXWkkWuD`A0 z3fFz!1q#>nixjT={)-i^<$OrtTF(6n*Wc&|6t4NSmm z>Dc!_y{4h6*T}J#odZMNFl7DjxguagQB^Zx7)Q-N`lAvLahm>yd*(f?4^}O0pZf-7 z--WDPALjG=V6(k&85S=e?g@-M{XW>?`ez@CJPYyDm-GL5eHixdeVNE-Z6+`SZCD@1 z^*z2$X6o|U(w(UfEBeyaCk zdordE)4TBe^YQ8n^$y<)|$}omA0DjniGH2IuAN8T< z@@_L{$t}+bE*+GQ{u0)4RAL`5)`9GN9bxmlJpfA_uNx&<2W~vVOQcD zd#C507dFm8F=1m3zX?05U8;ZU_)`vsNxh;xSy`5bGDVe4`!mS&$*i9xza?0P?(fiU z&5H3sYXS5x8$WmUYFUu8kLO!2FAG{9xHf2wB2DI>lZwX*oF`eXY&4)BUV@^Zw`zQ} z^**d~iseQ>isS^PT%VK=o$K7D&A#1mC$5dQZoUd<10ro1hXi=TM#K69G5CdD(Dm*- zM4k^Av+K|nBmI`lFGRUL&X!pdHvBW(#8u4i_|E9iV8b8GdM1<$yn`Q;PRL`fH#@{O zgFU1Bc~h3DGeKix3q~kf%YtBE47$0sSG;5^(vW9A?!Z0K2j~AueT8zdcnD-d9lN*- z?hNlE#1(^q>w{dBFWjRYqOCkbZzbZ)v~}@9Iqd;E$bA{#tJ+!p8Paa>n&BtoEJ@TU zLnB-6-i&j{yW|F?9Z+^7EVICPE_eM=uiVXZFXv=u@2mgbyt`vKOEGZ;&L{1Mbog;} zQ>R*UmgQpTKWrd$>S5{#$j18+(p0cs>(qnta!nucdBEe{Y&}9Z*PE>X=I9XVwO1fr zakf)yqQcaX?`=Ib`cdMDpcL491s$UwMe!W`vS?u&$l3`%p8dHQXNM<-MqB3~J-Z<; z@8hiA3%(L;xUX$+JxW~ZunSGyZ1R?Mrq(Ccm-pEGGw&;l>^Y`$kq=yNcPifV+Yjdp z?%WJL*^IQ|xr0S`cb>z6Z4`|3&W?i7rSq*Gu^sSriDAcj<6KL`6?(9qcczzKtN451 z|3q7oK$&YUWLdSgLGs?_n!G%N#|>`3xp_t+%fPpgPCN&6CC(ZR8Y`f0_?|`{cOKaJ zJ)X6@7iFaL>|@?D_lI)qJul1N#{}=~zU#ibp(9HuQ&-4Io>`6ET2R(5jYgX8UV-zd zqd~B6;{KaoOz`aX?Cgd3rf)qPXO1#lhRLv>0^Z}(gLg5^=9{{;#19-?-*i(&3(kpJ zav#p@ytiBY?j?|!I!b!3liY&vSidgEoog}Y;?8qM%W;1dchbIv`{tUUwE^azD+k&$ zb}4HcoQpd6E78^!6>XNRyfA3Zs_xc8`XeEOX}9*H4yZv`kdfiHK{{li+%1Q0@6K+s z@W6H5T5#r7YZLCIb274wMW%FPIxfag+LFYb(M_+7V%rEiDQp{Uc`)sN{1~?X9o80% zw(Y;xH`XDhE`c1!U<-WxoDTPN4m#|ch4 zx#>I;*EvWJhPQQSyrhWX1s$JFAdO@HxcSB1SgZR$=eBEx43C$rLb^6x7u$%jtk#v# zed-p^O@E;Ch&3xATO4g-9PP?{&?fa>`ae#Fu9N}k+k~*WM)E0~x4XMdyR|Djv|aN6 z_&+Fo9{^vT#k;b@h&3)Rno!3*h;Zgdf+YxR!>SRs%>EU8&YX2#%bQ5Qr-M@$vi@oU z#lU=p_8j`WwXEA+y&gR_D7v>@a4G7alK7nHov3q4 znCGvyZRz(2-YqXn(RM~Z<9)2ZrQSu33pUiFuIr4mj3cw^TiBmuU$jeOy=jk(yhjB^ zHjeczD9`V$M% zw)s}a^Y?9mtki3!jVlL_!++CFjV;T8Gp~jqO`G8ks(1Hi+OV(LW>x&kvN=)HPrMUr znXhaUl*G^<>@usdFf?wyZCap*?285QtR)}9 zrqIf4d}H8OjvxC-4EK@o?bd8Sn~TD*{uKBt!uQog*cam3@SvS(XU&*x1m%AfaN5aY z9WWQ)N$wj6?RLpRwz=p}Hf9HF;)vIrqfkzc3tA(1H|Lh@HL*UyCU+Kj0(EmU`IQMj z^v&iLzE0IeCTuDX7Fa)8tw4E)61(=M|*O8<3}SV^ItHCX82Eo4kF?+1?=C*f&FY+fZ<=jhE)-(w6)% zUIn!YmL_hxpoM;7=r0pDa!fkZFKJ!cvP?$Nk0Cbx{ev5Rhv)ZE9%B5qY0o~5-4~$y zJq@67X~_Oz=I`TYO`n?Ia6DJu<(X;capwGTwucCld6@VY&Y4DAe4}x|8_^>^E6ZLE7 zpxwUePY;$ZKOcEv`U+Y5RARtvTn@g}pWbq38nnkVz&Q|>0 zS^%ykBJSJ+p7b4?73@ zyb$_m2tG0dFAc%33&9&h@Nb6T-wVN4gy7s?z&W>knE=@+Md9fX`d32my&?GfA$VJq zhfL{zd{x;|O%;2_}?1Q7Wt_p^Brq!0w1P~u)G*p$%96NXfDU&bV zF}O)U&E3hNl055kY7HiF(hr$TUw*9*qvY!F8Pm!pPHw2@5^z{@!6Q#oO`VQvf*n^p zeC+t~W6b>EbR3F`sXcobsFDG)Qf9M?8@!xxrsOQ3Stx#O)%2>m@&-EvnL1BYALj}W z!zYvt8(ccroXcsX&Ww=_kw$NluhNbqO&u

CgI-`>o+&7^qV?W%?S}0v_3{*J2O_Nun!XrsE2$~e$ zMd8lo2j$fCS07`Eh-?0sdoUOAuJ+OVuU2>$g>O~3rr)FRZi;@t!gYJsqHvvGInroR z9^LK~2+sUs{psq%o*wRkF7j|!504R?`K#;UVh?xxOFi82zglq0d4>aVpDMVoSG9_d zsD|+sSA4XdCls#re22nyd#BGy)%5wolyd5Jv!}w(RPq-oTrHUi#wfhIqOTO(FE0&> zUdyvc;ksUWD1^_eie4UV=)#oo()@cWT$j^Tx?aiE=T(OSB<;Mlv|xja9v+55Zo^>OFi6`7k56Z zqjynWrTF)7Anw~09#QySg=;zUL}@607e!yKaLs2?2)95S;PV{kJc^2K4{tsZO@-fyjY$Ph50@s66HBk1k-+ zO-<6VPf9GBMC`*}sr1@QWx(d0;YfERxu=wM8gcoYz>~d3dEq*owEF4^2YG&3|GnXt zJp16MFBiUU1Nh#B@9t5-3i(o9B_e+>h4In(bNA5-)1>jkj6c=Rk30FaNMrF0%@ofr zTnE$5_SL^!_z}r)rURQaKmVAonZi$;WI1A9Htq7m$B+tEw!2f6)V`RoHKj#`1HR~* z(jDieM2MQlDB^OISyO7((_tMcV6*-Mn#|{=NT>~F4G5mghZJC~X|$E+;RJSGGS9iW zP7hx~QVSa9L9jnJ-5ng6?r!h7Bc6N5vFY^9K7Zfs(MLUZvFDC??pn_s_uNgMyU>$2 z>bZ+Ocg%AKUrCQ&q33Szxuc%D*mFlb_d0hpcHWzT5L3@!s$7-tX|xCEf-WPlBh*$n&-uqh59rxW{c#FOF3D3RGb1(M%H+k<9-uoTi`)1F*-*Ox=l-7Op5eK_$#_U?rEO; z4$pm;=l-_mp5(c&_1x8-`zFsl-*eCM+~4xtSTmBAev3Re<`&c5-|V?>_uLCS_br~g z#&dtub1(GVw|VaGd+s@&`#R4(#dH6_b5Hf$*L&``=br1i>pb_Zo_mSsp69t;xpDXM z`suwRcE7KAoH2dM^qQH|BgQUUFmdv=SRN3mnb8obnG~rjpMGssFmcADNmX@`hMJm4 z{j~C_Q?XzH6WZ1=SUP28pUDxJ;G0rgURRDS!ButjkxAu~r_QLW3haSI5^&|@`U=>@ z1B>Ymk;(Ouo2qc)bX7&f*jjNANP0KY84;$I*FmOhC-s>Y!9LbV{fye$ zn!1Ln%D{N;lQHngeJaD`nv4^arqz}=OrAKkDpE7?x~d8+jKHFR@~M+6BM54S*)r<@ z($-bg*H=|Wj775~rF${CW_kn*DpL52x*MvJuFA>RR@J9oT4$u;#@ZB#IninI^lOuT zY`!=FCe_qUOTMznWfvDXf?DkGEuUU9ZF2e4$i(vc$*IV|3gHc~I>nKrq;9@3?V>Qj*7&zvcbj2%6`G-8Y&1{O$Wmj7zjPfw4rqR6$3$Y^Ao`WXJRwQ>Uh01=#*x$CyeSv{v-7$>tQ( zoI;A=^P!BTVb3;{7Cq8_bwqSq0B{om%aZ!fXb) za%Mt@4_oToyHv{9{GM4?gH$#lr(#tfSlD{P%9GM@Wg~`<8GcDHblfGymz54LyMjxI zPzuY24=qlXK?huXC}gwjVray$aqv@i@$hey6_<=2TZ$Db!$y@2y<~jZu;FI;Pzo47 zytHimsKF(}hn0;UJ7OGO7+-@+24B*r^c%&)H9+6vh9#kr(U)gHhL6=Wmkseq0Hjec zj6TH-4k4wYL@S%v+Z#OUE;hK(NPp(eeDmkuu(@4vV>!>bh3 z$1H+M`av!*;|!zJE4QjDxfF_vr$+R-1Q8uuI&$14!%Lu*nLUMcX!Jre)w^C%mO3 zF(M`#n?t$E*?gw5D3infjLc~-LXQWunn`0J_KZKvhk?pLfQRz(4JV zWaS$x3Zr2Nr`RTjEeo~KRWZVw@-HFM)`@waR)&nE>90OB(Ooz!z{WsqNH};O7LI#$ zIN_jVeP%d(9}-UT)nSBFX0u6Up0NxgnFnjRDh@CPSe%XCX08X)`I^FpUO>t4 z@#E1l`|^_5n*XV;!fN4kXPNGgt9LYzouoW;F>h*pYemhZ@(Nkvt5EiRkyZ*QXSkf+rdqHo$S&2FJ;ZJ6%UTGi8qQQ{Ln~=GIsbCWg|+) zU1HWFr(l0UZZgnh&EmyW<0_`ir{NPyO9p%VNuKIFf;&4^wtTX~?f}UWz7*=JGWA{} z$=9wsWEdHT?Fbn+L#v%Jaq8p>`VP_B&stucwuZW5nu(w-G!-JEb)_x5W-cFEK$7WZ zeS{LJFi7)Rwx^L=mKnZ^s_M+jZE>fcYMP>}$MLt)CrE<2YD$6V(lH#&qmld1jac-0* zR_n=a0`A!_PWVDk|7H{2yZ@aqPlaOa?37B*wMt34Kp+^rMj8lvMAp8|O%F3Zad z(qC}y3D9`1;IMsQ_L}@g^2hOa`0oVo?$Ps%5nhhJqldi(bGiI*cw1Q`GQqw!wy~*$ zCktNf;b#fn=;8eZU*O@F3ck$4CknpW!)FM-(Zg>Se4B^=Q1D$IzE<$P9{#xCEgtUn z4rrUrOozV+eLnJomrJ*Q3f|qrkCGzS-^05K?)KI=J{Jf+!K1%I@M;gQ5uAGhwLGvb zW3B}ro)CPQhyPsg)gJE7bKL0RuL}J(4}VAST^|0a;Cns%1Sw1{9^PH>Tv>DE(r2*X z`5u0?;N3lZhT#1@e6ir8Jbabl6FmHB!K*#|UBTU2Lnr64vKL^1M}MZ^%RGFL;Hy1+ zir^bP{4T+_dH5E=cX{|91>fu8?+f1I;Ya3L{mGSj!o}-M!JSQghYu9IyGK7k@ctg& zDEKH3Unckj4}V1PY7cJ~ywSs*(bEMU-cj1UWgb3C@YNn(E%-(czg6&U9==ZST^|0l z;Cns%Rl!?4yhZR_saIS&ceWjZAm78kCU|!bFB9C=$Bxfj!AE)Y_Xs}0!ygg6+QXj} zywSto7JPw+pDcSQmU;LH!B>0u^@4Bo@Py#oJp4C;@AB{u1mEl7M@WO;;^AEccYC&6 zx}7U{zSL(9A1Qcu5C1R0`+N8d!AE)cBEctkctY@M4}V1PMi1X9_yQ0AyWq<_{A0ma zd-%z=Lm6!J@Lqy%^YD>^@AB|6!S{Oj4T86L_;&<%cFr_g13119>H^^eQ@b>KybI$&EdyLr?tCB-$n5L9^OyzQ64^2@ChF7 z_KZ|}c!kh6diV{3FYxet1YhRin+0F(;d=$&=;3Zp$2JciARh|5JiJ8ky&gVM@D>lR z6FgViH*Y9xjR}0?g(PMp-xfXc%e8HD__zwkN?ct9KzR|;<7JQqB z|3UCw9)3XZy&nD*>EE|_xI1GjSNaPszI}y0-^0fW-rd6|3Etns8w7WIOdbDQ1)t#2 z-z9jphr92hMh|~f=ofhSF9l!b;lCGrwTHha_(l&uLi**~Jp44lcX@bk!S{OjMS{0@ z_@#p9iUPazsS-Tj!*3A0yN53kyuXJp7kre5|5We^9{vl#t37;&;BIfOlk=~FFYxI9 zDfluEZ!i7q)gIne@QohcU+`@n{&m53d3dSddp*2b@D>km6g*e@UoKv^37+raO9k)l z;SUJj-@~62{7dXztD0Kgi>6X~)m2UH1*--kNVi04mDJv}QAxx; zNcTO7hV5lr5V0hSg_7C9aHRVG+`ViI#GikY;+uqf3Qw2(?#1Ey?*|X$8RoxO^4alq z@;i5LJTOh74v>3(7yID$#4-NtdOQF5LN@|;hVR-bfrDKV?%mQpI^4zI-7gdWg^ob( zb_Uz zNSmR&lONWK!~P`fZsHm1rty5LdBz%PJX^b~=pW(P+T(6C&(%kdX!DV_g&F1m+MR|yM~30} z(w1uMlY{Fujed_Yr?qjM+tuNSV0|om(94XYvBL~mw$7bfk_~&%&|zcOk#aP*$?oCH z!F;&~a%5qz##dX+pK5g(cWgqwTWQR%ZX3y8DQj3yQEF9^-A8A^HXsR<3As~ zF^931Y4$q!^BfPCoJt_pTUQAUz?HMuj9_NNZARs`V)n1TE=^o3dfK4DDY3f4kz=JGDeWE zj0^4VMNjAA8WStoH^tA7q!u=t$)qb4$A7T$e4X z+_J3p0X^!I_X_f(AE8n$r9bDV;Hdb{E{o^iU7nYu7%) zbpX<>KKsOlG1wY*b-^dIerasnE`=T7`z{LJD~J75?k#RXyx}MKK^FgQTg=C`fBNr@ zue`N&;h>lP`jhj1^KrXp3-5U3k>Bh*?&XSmpQ$}B_xhVJxhJ^i>FOard2V@+zpjk` zwfo$I=bkg~>2G#l8@qhM1*6{oKlHzU_Tx{q4(s&MW7G2&@2Q^ux7WLTc+Anyj-Ff6 zcvtboZ(r2!fv-OIQMa7Cs-hnZ55D=2Kkgp>)EVQ~SKZL>TlvSWxFY}BAs1C1_x#l- zG~RylrY%2j`|MK>eERcm&M%not7(7!@1M@NV?a~yug&}UrS(_8a?z?EuATYd%S$h) z{BY$z%3iB!yP@OSGk@^W;=X^pYW&5&`~E*4{>qAN-#dTm{D*cwKDO|b$4)A0I==Ub z_x_~K^Kbp(&MxzR@%JuMet+6O{`i;M9yqIT`fppOJ-+av-OC<5J!pBP&*#Ly_Ogqv z9z15vnWqfCt^AZZ549h8+D~7coBLmX{L_Zpe=zUfHNoV6cYZV$uI#-qcHy^P>vR3^ zhq{gV)zWAGbjR0PPinuqXz(+CTUPPJIq&?}m8;LVVEIwK-uunMySHtabNtByeKv8ko&&42FyUzb<(dAsRvo7eodvFj)QIP$}w;Qm>sCW2pGwV?Cdba};m$q$u?)0x*uq*d_|E~OCUy9H4|`sDF5ragaJq+#uu7cPij{Z4J)E6-bh z{k!>pUbgO>O)J~}XTzXwu>8>4X z&mFuVcl#MXK4S937u#OCJn!M1Gp>BGU&EX`M_zSP=VvZl@Q+7Vk#w!d&epX|4Cs;Zp+e%bVz^~-rr ze{Io;#|*5?J?i-*9!@;}GC`jv0rKlkg!7reADXZ5fD)b;u9 zXS(~s0UJtB+COaexsTnvyWOihALzB5oCBCSuYy85U4zVrRx{;p)=V@IF;>Dv=3ci(%&xYi|ScRy~#h%Pgi%sqa{ zyf%Z+960{OFPmQ7MZaFWW@Mz_6XPD+J+SebomtIQt>69a10NhX_V44qx9RQ1JKyg9 z@k=NC^u0%VopqRW1rPqSyt)6r(|;Fx;n-fAYkT7ysv!+oILquGu|kaMAZm z*WbOp_p8q>7(QTb%{A*E`tDEPdtm63x7_`&@w+ybeCvs=-+5#6U;mMH{tHLt-ty?1 zx1Zjl{rx}ub^C|!ICj8mZI93UWXEO0-|n>S$I&|r=FB|nns!4EzH|Kb^ZvHx*NrpR zK6Kr$Uo08^!sK4x+5JW1ACdfD^RFvjS^n;tCoY>o; zt@HHpGe75j!=#?&TMKuMUG?dt2kXCf^bL<~zH{H!htC~-#&vJZ&HD7MujZ`WyKmr@ z-@f@+eb){@yP&Fk^ux=CY`y8>C%$^)@+Ft|>Ttw?bAC8=UeSPGO`9{T>+TW52H!II ziAVoDV8>a(X+Pfk{#9rE<`-W0*Do4y)5;Cy4}7@z^yB8;HR|#QU49;Jd~Uw-$Qd8^ zEWF~~4`vh&zUknb|B7F><;+*Fp8D3;FCO-O;f6ox=f{6Pd-M0_pLF)sAMSpB%Jx_D z4=!r==)#>p+4Sr!S3KME;!)>*JomAOH~smn-LF5{?Wqffjeqj)=le`7y``n^FaNmp zle=0*oSIjD+HankIlRL;?|i59>eEVpeQwU=yAC%#v=zwu|My#p)}A?Z(rrER3(uJG z!tZZicVD|J?)u}m{&~x`rh}jH?&FKkyZO$+InT}d`&k`7IOd(xcOJWZOztC(SHAb{ z*n&H*`|0b$oW75Lg@vmhsob<%S)BgO#%KIO@^FEgkha-3O{eSJb=J~0e z&R*8$fi2^YzI1GUk6r6>dVJ%Vo%anrBmTj_-|iXQ|Mqqre!8aHiS01VB zKQ(&vv5U|CpPsi|eV{0}+s{_t{Pdz9jd}g#F{e-eS_v}-uR=j z&plMo_u?P@@R^k#ym&)i_H&0LH^+LI-oMN~aN3mVv9CpTV>gP_ z|Mj}}oO*S8-%sZA{r-Rd-~T-7eeZpq=Xssid7b5+?fpL1O&%Y5-(^c1xA1@7`_F7u zWqKR$kP}TiBw6h{>-M9NaNyydyHn4p&Jg+S)~#C{G5pCJoz*9|ALn+hNWbvK_0$t~ z=j5)1PG`}a*~ic3s2~2e+VWKo_@8QdZqw~?jr9h&tvGyk`ujT3$C{tXN(q{twm)_5 zpmh6Fk?F6K4BL%xAJpFWYMuQ_bHa}d&sgB=Zh5?ypz~;AmyMrVtyxr&es!4ro{sA6 z8yhq9w%@(eJC^UcZoIs1Kus-JwaJ4c#_Sw4e9FMT+w_~3Ho5AE!S6J?SMBb&#^Kd* zm+3(VpI6#`BDlC&{En+*7fhX6-~aWhh6xtkCYpPm$=OjVZ|LI79<9{t{0ggZJN+j; z9BNFtzfto%?*38#gE!+wu6*+GSK%9<)w7qoI@C5EkkV1B{4O#FuncV_Gc zi`u_%-#k?yV>H@ab)mS_{arBC?bdn=vx9|OMsfYnPB88)nX5w~YW$F@fpqtuKK1Pv zY4L{XCb?5(>!fja`rYZoh8O27+8W9Az$N8!cG8iVNB*c9J!w*E)zp;_ubha9uUt=f z->3JR7bgO17{rfwey%Q0`j=yica3=#E9t}I!?|R?mM|if;0iwF5jU7M{dM)Lg*BS> z-K7^9K63tSm*LGKPwr^*&Z^puBWLdXW0wAWRppDzXGBInJMZrmde5le{T1gI8Qs{s z>4x641$Da({rPjl8D6u~`#zsDtNoobcW)+Jg{&U7cul~V{vKQJ#5OdVyeh!C$-e9Q z$6A=yu9-EmQ^>X-bN&B(U!_IUqO&m#^FGw<=`*(f{JDqT{^av&q50!eubu`wHHmDs zD(ghg^jp`eJvv}^ao0TEZPDNRZagtKZe*wK4Q<*i?Q!Ek-t5PR^O{5qZPIyB_?_R= z5BF`iZ1S|+t!n~Ch7VoP-cQg~J1G7&`_=fv!F^2e*A*T!3@AE%A?MGR&8v7;{%}9F;P0mEn>3G_lyZOX;FZP*3_WkjLX5K#c;P~LlpNvkt&N?y6yT_?Ly;u6Q(Iu6NyfKEpTIxBX26cts9k7oEyG zBqThzkJfPw!J+(*3VDC4}y;FLa>TzXFv-*jhn*Z=lZ(_*f zzjNMvNt<-@rE^!OaARwe4i_%}ZK1liHsbc(AsD9UodWByVTi`?YL_smJOaQSGvfINRXuoWmRF&6&@O zB4(fRp4Y}~%kvcj9**SxM{WS8hUc}>@Fqfwd`RlU~VZnz{15~fmJ z@g8FJ^L9*9eoe> z{^i{Jwf*ljt(k5)wyo>Y@vYmatMof~e&3wWX2RHzS7%!P^5DYM`Dw)txmIfj$LL-= z-649H&}G#>=MrW;RDTrw4Gtb^^YZY=xs~Quiac7aD4^}cW*g__%-7#({HnUqrLlLu z7mQAa4KbPh&8vtl|ID@acm4cl*9@EDQH9%IoJ}94BaFQJBWSG>K7BCu%6YKPeaXEj z+qL7eO-yt@bx)hJYQD*oMc)K0H!sa+tRJ|vWeET4^rQR1cNRj&`wtwS`_1}06AR3` zY5>>juu`a0&F0394iA|yX7q%Q@sB3#4_j4l^yo)(M~|61`nT});mhhzJh(o*+rU-Z z3kO!7er4{5`lnv(>za|*wbtFn>X?6?UhHSNw*S1vogNIT`sJza%4x2#056LJji&L z{^%A#lMZ-$J@WNv|17xcia%bTpY_Y}-tGRd?vg*zbN0UOV%NkUlm z?Vc&K9f~IWnJFB&_R97{%zCqGeK%I}4zcgseb>8vDIItGcx_ahvD=mgcu(^h^zlov`#s;lFz0E(cl37`;YW8z2&h2H@Yw4S_S4Zddag=JKh~s>`LoMeBrlUq0vkoV)bi@}VzY zPtLj!Ke&I(gy##txwLt*P;>CU29+QGu=>~ey1pOGuBX?Vd35(rhYb9uJ;3sPuwcZ> zW~Zh^n%}f8ZaeBq;*l$3r<=F?QHq%72X+jxoaGD}*!H&sUd}v1cE*osqLHYwPaRdH zO24OfmBme)8hI~nH1XQ>iCZQ=qjhE@W1-zY?*qk_LRy; zX-V?0R<(X;?PL2b=Xc(Oicr0=92ty#)$Ud4d+}(_jS+Pal5MGrjLE4vG+efP(+#hH4|feW%zojt=Vty!yUGP8->$m$OM|sei`&1= z?wy-feZug^4)%KrM%lNrdt75<_p=tJ&uSECOh2njBNOyC)=2s_DI|O8q0G$)^YV?0 zGEv&zCt?BD7xEt6YPG!b2=%ldT{14Nn6e_K&(^1~uYBaqo`y$*>fHU|xcyGcr-!Z; zzA(%wek*)$a$-(M@_wP<^@6=ypZL9NwJ@jmkYph`bf<` zK>Aea>u+xH+qa#YZ}d*l4_oim^MO^K_r4msA1l{Oe!l9y^Oxv`1;gEop1XTBZ>>|1 zKV|BWepT=OF~8{}&z|E87T!Jbd!Ik(9FJ-s+Z)yPqozh>%Ww?6(y>w^i>9X)=fOQ+u-PpnSa-qSEJU{ zfsI~|s~ocZx%006?hDm%_Qg8~G@5DRe9ug zEO~hkqi-kKtv~l|Tw+c8Lr-*nSG{Ov-f-yX9nTtfnfvjXkNeKo2hPGd%-pFS)y$sN z=yboGyN;LD(;Xf$->p)7K6a>K|Fe5UO@BS3Qypd)H#5?rCztmxu6oV?1^GWwRXXo$ zOmAxbcKO{_W9uDwceUM!@Rh~CFMRdpe8koZy;qy=NGSgK$Pb@}+P8kZBgFfss8+qd zm=23CuASytqu*nfgJ-MFC@P-OYVf$py1GJRhYaslktSJ}t9QCK-f-!qKbQM%HQfBZ zX7;TqR!5FJbn$qf_2<&_*J^DV9`d=)s-1qibLzZt>3wX|-fWK>Eps1FSo_0^w)J(V zyp46e8MtQ5x#FS&--caV7}@eCVeO%_^)>l}T+E;Rl;GOA+rjktLjo4>TGXTAFI)Ev zYTQn5_VG0)_umYRYIdhn1NWA@8qPmHytFu#l>c%!kNhu~77tF2HK?@4G_=|5Z%*G? zyTPRK({BgHU5)x~*3(1np7igD#^db`=BwDg|0j!nwcr0*9)5L<6%bWAQ3tjTUDD<7 zEYlUX`9@vxwy)i|QmB39vY&;cgr&b!derl#O~1Vt(ia}ObkL<&&k3KC z7xb*x?`-1f`^!APOKCK3oNlk%ni&I*wI9&?+1-w3m)rKcvhc-vo5^0qzkO3EjG5o& z$6k}Nw!7`zGT`W;%#Y)C-rjGP-eAg>T@CH@Y_f;ePxwc5zHgn*Z%)IJ$Q3(dQ;*y? zs{`})EZ%x+@ru`J2Ue_l_uL?s#onx9a3<0{Uq~m ztMu)2zMpG=dDX9pOVmaqe&PoktCT!{&5cSh-+Utb<@)C%`m7$`aZ1mK8CPAc-@LmM z($oLbs;k>uW^dcD@|SV5+C^TOJUDHD$4=WR#$LXvk?wvM6YuQl6;aJEXncU5Tcf+Z z-%M=WFTF|8aEFI0b#FHxHfMe<%|LJ6oj?0c>hE=E(uysD|L#A2j(GU4^|3AAS^RAj zKEWyT)RrUlzgPLB4e(05xX5|nfF}3)3{d}R+R$m{uR#ZOVo&3-nF>yIKke#Iwcpw6 zAN5V0+G$;-cHhkmI^X`r##$x)2n>k!#rpAo$d(x8zjZ3X@3n96BA5c|uzOz3u?gli zzEqj}KtH>0%k6(;6#O&w#7RHXb^FrN0$w(?-o0nA`j4kN?R%&mgjK3KwZH53gN?Tz z(`&WX!7sku;vZ65KC&Aa{Pda8gPXpQu1`;S)=gWxak5X~3-{|emJz~?a?K3`ihRHO zT`;7Q5Bj+36KX^H{fK;IkC*Dtwjd@=4JF78Q_O~reJYV@x z!qJM~A4VI#!YC@8DWQhh8AHcxPTe)Xeu_<(vn#($=x(!q!PB>|)!ffb&Od+j{G8opgLFeey^1XAG|F7`=<+Ys zb@mR7{;1mDaB?hoGvYYu+XPtXpE21|4Sxyh(gG=zI&`X2-oJo6HR}PCv2T!l##|lj__} z=bDYy*?yl?FjD`aYxI-p-LsyU_DIef8sOC5p_c!|J57hG%4Pf0oz@q}Pi!%=c*e5s z-&Fp_q?12SCyu8vothF2)g^Z&H_DZ=graz(YL&8o>)dVMJ&moB_|x2$TYtIK;$+_w z=cZT%53X%76TdR@39S9!u`m9-5vBM@6{Wf*~ z(lv-qKs+@vFAB0MjhG|C~0JFgj@Z z-AMa3GZt29cF4!PqkTuSrx#pj7S-~dwkT}kS%AO#zs$9+_qg5su%^0= zTj>6gb4{K<|ARE}lxn}KRO9Rp&h9Whw!xcLZ`-}Evpg`h{)vbWhJAmGdbPv9h3eLz zX)m7CKk%{U;9(&rTW&qS=FR-)YrJ!g8+m_vw22fOlwSGA;hA+0Uyl0R;L4lWpYI{W z+mrfmk7+PEu$T9j2e!}N5Pk7x(^}fn22_~U3w$?hVEYpnI{)= zhCBVIFH&7tX78>4tKRljkMDlIaaQ$VMM2A^eeeDeNwYyU>}T(Wf|v2R%P&`50S&;F z)4$8k(_yKfC$AhBmOJ+26!qM@Rpw`Jt95URO8D}**Re;x zZe729N803Xh991K{KUiSwmlQ;sNT;!>{~OxcifK1d(n5_AM>9SFlgNMtW&u{^9QTm zCbh49?%lI>9U5Gkk-o>QVfe=j4J%Roh12hPPh8~I;oOoM2YZ$3k9T|=sIBcjBT>tK zs&owf>g#8m8FaSJ%;!b}+r`KAwyX3-_x1A)0dqE9nVzz$R_NtbJ=#BU=vGn zY)X{@8_!?qzPr(gYLj9u-jq}@L1#(P#K+ZYr#9zP_=4+w-^g8veX2;%2L}i$8WK@Y!`kH*DpKl|OfzH*ubK$UN^E@sr~x z{NyEc8+FU|)vjNXe;im;_#nGV;`=7~-;o!9d)oeaC)RE;YPses^(ku^>8Xs}IYFgU zWSli<%Hdku)AX+`z1x4xs1eIvKGB({Uo(BAbFq(I6KhQ+rz_6qZo+yN4KR>%98c&K4f)>Z^aEUU2L$ zdKoRkdz|tfvOTu%gGH)E=1X+FZ(n~~;9em^qWwo1Mn2YccZa zbBmf>A61ywMti+A+t}(PFaKPhlCm!$>P&@xtaY89Mc{ zyp0n31ZMtrx|K( z`IuAAP}2db&6C5Yv^YEJL%Z`CCOuaQdv=`Zf2k;>Z{{%zs6$4uBD~< zQxgBkxo^{ZkIr`+pE69pXOP>KnX6_C(;bL>xHZ|B zlkvK<@ts!PM~txgmhUgXdM_rbEE%2(HLS>yBq-hLYV+W>D&q&)&zQ?+)pG z4B8>C59VVzeZD;AVYFUlv6sdmvU!ZE7taPaxZa-aJmB$}0S5z=OMWQ;`Bd0W6!qVK z=ubL2dV0a_L)!WFtm2Y23nw97rE06V~tkSepNQUl385--7Bd+y6_| zb#D!LQzL80)158Sr|D=8ymx54`O@xZIg!)Wv}-qJt+(Ztgsy=X>mHrspq`bMcw+sj-q0blmJfvkWz0v)Keb7xjD0tpZcWBk2*7PO=-ZZrNSpP>`w+my0qFqIAAK1QK zku&yF^@8L!MO!X+u_m^3{O0kTt)}lbY>1F7BiGYt(D}SJB@N=Bj_>mAyUSH7o&l-V z1{Mm9Rvs<%Ix=}d@b>)mGcRA>aVq#zccJ%+eW5>mh_&ny6gDsP*9DozzZcFDn*C%s z*fw<8w4t}p)YfY@u>IsypY2NZRK3qGXu0#Rv*Vi%Db*A2xIN|3OSY4^6@Tgr9s4@B zc`$jyl2p~Y2{umeKiugz{gAM9VS%IVqT7E*oR~FdP(Ax!Uw0btlIWE2$>iS8tIwM3 z-y@Yj%wJr>6JK>DFV@=EUpv?qKI)kG9<1~Q{!83d-TKLw_8clYHuT(@V+A{NN4+fE zq`BCt{_QrwK8ME4A2}s_^Yu|fT7CEEv)z{S&yTBH?q3`}uV06kV=EVFe1GlZ)&(TZ zfd8X{#kk7G`^0r4o`2#}A||{>^%700Wp!|iz34Ovf|Sui_FVX6{G{VXliq)O-C|Xz zHZMp0WzyuM=Yn}_+E%mlo4UEp@Hu}B%XS&Q>$!1O+l@=^{5|g8Kgt&Rme7&Tfm;ph&t1^z8h^sV%6zG2!w zBWk>EGw|-4nIrf89as2k-`Ury^x0&%@5z$Axj{c(Tr#KIj`KY}BwDxcdG}q^@~D+g z_Y8Mk&$u>p>V`^Y7yIz^W4vNkeW+%okxtP4XJFiwu z>!wxQ$GNN;HtKQ2;DQscleeyYxNELO*2c~?YJMCquy7MB?`;qEKgHuUWAUE+(aB)W zW4)!}qvLape{6AJ=KASLU?*5vlGK8$=n$h0z|s;155%u<*l&*4(>g4Dyyy9m!4s0_ z91d<=IsM$A^nW^D=+wF8pMHHJ>Ro!9+s3tL{^3Ut15?#+C+bd{+4i}8%KHs2-LEH~ zSTW#%>;0kzGuHg@_<8TCHP@N6zFyd4#~;FoWve&- zcEf$p#YcXJ^1XJS@$h{*%tZguyhSe6Dj#kv(H*1z$XgIKGhx*((+7V?zLUkf za^&-_dw!}kwNp3q9-hGi<>`8|S7oACWsvUKj+#};t#j7@zWR}gOadg~>(k{w!mTCO*?HW#_5~TaDPgjI0vg7SH^SWNV>b0cK z__JfT-D>yCw8rfx`OiMFtc_vKPb)gz-a0e#oP9=6>%R*s{rZ>BkZ-%R{CuQir_8in z)1E)cduljxXO!CO?4YVCJ-qgWnqFuc;Zpef6rDFaWm>HpwR-)?q_LkbdA3MQ`mric z7k}TM3=4I0yt^m<*BHwUI|(q#|xX*{`Q2+uu5mQxPH6y+?k$! zTP_DQkGK+MGOg9bnZj?w8gGbiZ{qX)h1Lstzx<);BGVPl+iErqjBRhM-Lf2n#>!&;qJ=^MTNv%zos zX?VEj`pMuDyzpGptM@WTL^RJ^TRku+^P$&#s-Z|6%heoTLELm-y zvVXSv<;I)ihOgRF_g%)`d5eE|Qzh5CzRSQD)0a*$@yt5XarZHO$Jl#`-?njh^QwE3 z%Ml)31mU;YKU6-Tr}y;yy3W6kZnk`{>)N21E|t3MGtal&ZQ3EZ%z8-hI#U+2O8h3Z_rDJ@N3!XqBl;tMK^M9kcXC%=g{fW?I7=$sgQ$4O!zB zT5s2pdM!JTZnN^`xK*Rxw@{z*$W(RNq3`e5DQ3>baVOM?N0&`le`&Nwg?9KfaL(NC zj&5L#2oZ`EBc)HeMT5G_z}M-8u$~ zJdEcK`_0?s`}x+FezcmM{r6ultX`$fJ=^r?f=caw*nRq&cV;`{q8fJ$Sg>VH^3ac6 zb7py2IS_3?o_K- zOgL|6`1t(DScjgguADBs-F@HsO_@J03SYM1lw7W4G4WHLk+d%VA0M;R^zin_ru)w5 zY}a-{e-Bx1`PWRdXSwDpuE^3ub*5e%FAOrTRR7^x&EuL|p8h<}!lqYI#@!dkdt~l5 z{eEkWbep7qrXDkU-fcso@V?ma%dBFf+WPfdFE7r%86Rj=>+cAQ^H*XECT{psLs;Qw0%{--PO=fCAj zR4Q|Orh@QiEAaol0{?Rr_^&F{Yb~Ri_^`SH|1}l(udTrU#|r${Rp7tA0{`3c}y4!2ebS z{SEe8M@E9&PQN@g5H35e9Yd*0bFZufBuW@u$&ngp--SnXRoIo~$dKC(BMNM(TgX zvUC0#Sxz=uS=y9SpvshU`I;nvRmw$+XBf3BpIU8HEi6Z;uN4Tn@U>LPD(zGs7i%Xw zEy_ZkmkS_rD>jlAnw`Cic4=B-h7wkeTi#5zw)P?`08Z~5H;I%mZTW34CB7V2mKJTa zlDyO=*GWMKnOtqO61iW&)slJ_Eispf)S@a>eC_5c8$HjbGL|ZlE8{wA5vjn1wx)da z3S4NB%5$}pDQMBYj@Mo)Pi4}iO`glw#cO9HHAfZ6(`rjC@!GYQYFb6|>}{mlULns> zi>2T0iEwr`xTCzhMt$e$pg{7s1E@8!*v6qat2Gy`iFONaNf$e(r>E3RD ze?%l4DlVPN-OQc`vvqVVS8%KitMrHS!DGjV#rfme@^Esy862uTs4I9391q99!%^{~ zM{s;xa8xWF94{W^YAz^8=ui@&^Z#aqo;|vmIXXduDy56RaJ5)WfvKfs*Ur>tUj?R? zHd{N>-md&>T7jwM?WUdSsHL+Z^z7EHgPCPtd_6>)!GoETwOv~~8(Sx9TiaInU~OxL zkGAkH?;)0b#%Uit;f=WNS=I-C4@CQ8!7SBdfAcXY*gHTdOObPS&_ z-c}Mc;x2nw4-!4$`{@k#V4Daz{tLs+*!Ki882>kh^Rogtev{!z_@#GnDdMLfyo4*- z!KSJNa2$7OA%2nJiHvW;a33in1ddxVJcr?2PA7(Is!IYmAI}y*`3AVL09>SW5r#56 zp5b2bj4qnt7o`jp+Aw@J!v)-c3C@AxIRA(WKI!|;3={*K`n#oZaD{3i5SWF zeK?=tyq)o5c%rpL%wqiUTn^ibnZoe-41dD#REFbsa?uV+HWI+`y$p92SEb;Gff@e{ z!?PKl!0@{a_pp-yj=y90b%w_?z5%qq7_W!D1aQ1D!?PKl$N2UPPj`?2UaopEJkhZ% z?#pmL_Fm-t@eFrnJ0y9%Ucm6zGJFHWw>nGm(^-Al%Wxlj0fBR4_-Tfxbd>OO(nYw* z@R&{#z~jXyUGWzi7?EA1=9IsTO8xL`NfqInvG)d^9fml6eq9;_a7?x%o_r5JfWDG>d|Z5; z?0mbqclEUMg%PS}c@)OCL$sidF5X&D8wV|17@2EB?OnVjb*K(7+V{2-m6W69V}lt4 zEplyLY_-Tmw7gtI%geQG@1zZNvezaTP%Ux+mE_{&3^OlG$he9rD~t7!V=&26jt5vd z9!xNo;{hh|aITBR3nuMTP8pcUDj(Rsd|+D_drv8SL?VLaB*HwBB#{!Gv=hteXbVNJ zd^9EHk&3j{rVxOVLQ>I|M2Yt{MQtC$U61Y_t=da`#jUf6I!s4K(07^flN!w7#WyGJ?R1lO>8ltb|( zhNGO}gr7?A5d=>s_(+2DaT>}QMeuCG_a*pc1w2Oqf1!ZqE8u#d2RhV;##@Krej-Eq z;NPo8zCXb=j4!um0>kC@%X z55WT^k>Y2hg8Uc-`5GdJmLI+!2jk^^O^kr=GekU?#QTEC@h5npf<7>~5uH4}br>#B zuLHrUd_2Gh9r8y@x8i3I!{v77XBo=ly$M%+&b>7Z% zKA#_9(+nki-Y&ZnIih?!3Gg8}%HPkPd0un*e7+`LfuBfll+WjVk_nFTZ?osE1V=uf zKgu9DC|8zlHpS;K+Ap^H%u;M}AwdD>?&q<>}?~Vx|N~{vh^jNpO_U z=WCn^j{HgN*`46X&tUU$J_JX8DtitkIP&>CQ9Qwsf0jKb5*+z_zA2gD$p65ew-Oxr zd|oMo;K=9gem238&*!+7nGziN@$A`>;3%KZ z-#HVU^4$rJd_E7z-(MIn<%i1nd_IxK&-v>aFHy$l^SQ|cNBMl8(pG|_K73v{gW!~( zO>pG%`Q_^bNB&#({Dk1h=kwJ01V{citi3j1S8jhk-)%~8^YR+D4(wb#ScM}8!G zenN2M^L5sIf>XW$lE88M^YvO&f>XXF!SU9at^4Bo06Lyu%UFEw1Q+?WC7ut#QT}1Z z$8`X7Tpzv;9ZzuN=P`aF!SR-_XD1UJ`PJC-R)XU#Ul-3HIPx9Xb2h>8mang0Cphv) zu;(WP$6MZ>=Mxk96kg` zKCa`S3ne)6`M!{Nf+PPL<0ldv`Fwv#GQlZ-E5VV^_o-wM9Qi8toK0}#^ZhQ@2~PP> z2#$QdZziAM$ZyS_4cLAgZhyZ2#+2ZcZ%J^J&-d{-6CC-2nS6JGBcJaF@*z0ohZ0=m z;|I8Sf+K$hlb=X%k zf+PPgZhy88&Fv3fqBA8p<@0rF)&gcKRSBa@RZ!@Dv(ONRGk_(d7skKs8od=SH5%kZHL=LY0@ zmdtfp$4(jp+d&0um}8c%q5N)KaHPL=9Bc*^tb_dH`~~ZP*jT}OT(tBc`r@rM+yQDG z86D^!$^B8Bt+lOS9T+`kOmGy4h>DI2w(i+~aNF28|G)^Y*8lWs1_E%%iDi&FHGAmG z>IwH_-9!E;G=w|E)Fp^?lM%|UEPOS1#CTY77FhRAXu)t+U8F$pxlk4__dprc;k-S{ z{BOhKHXD@5hJA1+xg-|9#kU-hu3UePc7_`aFONUNRbm+NipK)T!@B^k&3-XaQh;P5 z>5BHlJmTTG{RRSt@w4eFxRYEqE9mk=61e^N)eq=+ZzBaO`8EpNxGDL%ERNcJnxX4&*JxB^|?A=SeNDY!{%07 z{O*3s?E(AhfLIk~tvIKf_LGg})Q8}jMo;9zEE=j;TZ z===<4bnn|kM^&04m2jY(eK6h_t~A`M5rEICkdiM`4wsxQk7vr`dGa3vb+^G@$$dat z_8y*LJe_6+&&F_8e5!%Q6VjR#2xr$fh5N2`HJ*YF{NtJPy2e)gtoe_D-L`$1a#B2R z{=Kd$%@oe4&(W=uCh?@}N018zcW*A>IdFD8`n}T?tkgP!V_o3qRVj_@L=Aadl8kuR z_L-w=Du%6FSPb`d#rr#Orv35C>H>e2u#fATYN+vSDwBipV7gua|31;9i6D$UCkVLY zAg0x#s>U;*y2kSj@VKrYQ2(Ohy%;W6w_cev2%n1`-WjSh?Nx#!ml0G=DSOD0@P$`oYO|K1LD zsqFsWv_~Dv4AebY1w#;=(w;rKM~=^};%|ttW>O5xKd|qi4aY5r+Hf}oe1HOuFJWzR zCMe*u6!0Vke6s@nivoU10sm707x$itjhDFhtYk}p*q|wIJz(1lpc^tSj=L+^!!362Wlw|rLu*|$)#iyQqg07fW+wvf1Ax5)!QwUn z$$!lF$Wk&$@Q?Eii-OGuVR8H&(g^H;4%e0prCagSf!*U;7wrc*GaT2bDDKX1ltW+d zF$Bl=HFwa?i4OVr9^!5xyFr|7`xlWEhRgLyWw=})zSmW*58W#u?RS*~WHUL)r{$OK z72x9nq~OTX3&qV z1N}qnLl-nt7nJR1pJM%NA?-f&$sx^2=FmUKaL|8DQ$rv10bCzKA2JWZ-`A~gl?#35 z9O!EzM|^vA94Lw}rOI0oSNIp9yn4DUc!I&R3pXI&jggRUq~Xe889 zsbG9i?RbNFQ`JlBK{}wn4e2mWE1L#stZ*Ot*;IdwTLb#%5*5;|pt7|v6?mhn31~Om|NdEsl z-?IgE{zqe&Y!mU^2Lm1DykHqs~|CK_HKY`Zf> zq66cEZk|IuyaxD=@sEV5SpLL!QJ3zLmVyOD*@?1nJQFp3j4%9&cu8UR*axO#AIxWTh|{r8mWWC?<-aC49kWQ+^V`=@=)4;B?G#o8Z)*daN%cPp<*P<>}>pPo z|MRhug{&j|wPPi|Z-MV$`?q5yzTaB3A^Bj%umouXcLwk;Q&afb@JeGP9-hy|@CbSQ z{Hg{Iytm;5cGWP2{@bzAPI-cuTpllvPHC)k5e*LRza1;3v-s7lyknjGH)EyOY^?lN z)S~o5u0Oo~{9~hR`B16ibqPl&2j_n|R*LZ}jbAO^s)d@+I$$51_PudU0{h%*GM|5P zyvB1D%zGaPwk>7jP2T1@Tv>)Q(&DT1=b-T&H{h@84AF%ARY^!()Eh~hzE7sKy-y{ObUc? z+R2HqE&yvNcR}t(Lv=w@m9V!f$jSv-W+)%7u5b+~z3#IZs_}dZd~-;r4#*Ytf)4(OT5?Skt)Da0m0!=x~{UL)6+j~6|_zL;hKbi{a@jHo=e ztC8S^m?_Awud6QTGQ{xBd9r?zHv;s4@eYo!Fbt0CsICbkVQmJ+uBfY^&*W}39Gj~z zcnMX(o{+A*QDyB3?~pnu3&$2Jh_i{HdL9mO!rIN7zVLNxZihTykPUHD+hh9R_hIVr zaipdg*I10L_%j?l;-CWC@n;x=I!Nm?CTy*zbX?y!1d*uh^%oynio_zde- z{5k6%c&@F^Jc#-^S?gKE0im5 z$bmeE1A*#k%eN&W&gx&7B(ED_SWg54b%7ezCH<`63i*R^AZ`k2H-)*IfCwD7L!JQ- z>Ody?`&kJE8mLDP08apaEX!CXXqm%&MK0E>sSwu&kZBGwnhKgsbEr2w9!ahy)6ZHc zNU1H=|CAc)0zcFRcv-}zsgaURAA&qCKOgHftc7A2tq71GC!y@~ zw#^mFSyxl(y@YY$oEp~!BHydg5i-pH$GH{s&(ih1noFK^H>3v?V0 zS5YS1$KgH1!*zd0bO*hXpw3}kfp=%dEw)8jm4$+wLY&hibq8$N1o|wwUy8j@X3Cdh zQRZ{Nv3!8enNZKcw!*SPNP{1=W#S%;?$FM|d?mJL{v-`oAdV{q#rtr+7{lQFWfp{~ z2X!^IhxRZzx{btg)gI)3gEjwZ}b|fKjl;ryaag1@w8)~fZy{p zW4zE7S>Y818Q4$Sm)c5-TL;>sj!;I5hgBY{g7*<}3P4BX1X-2pX9padTgLVf-xJtJ z;_^{8*ufFoK)u#dn672s>Gj3*)H4(un~CKS!%7%zNhoL!cFloy=p+k^Z6t=rIt+I5 zM4etS`yn6ORX@;A&su7?xE=z$-*Uh<{2AJJD>Kjw^Tnc_)OX}^QKp_dygxx7yw8Dr zLYXIlC%(gfHWb^n4fZ;VxjgLKh+IR7>t?I*ghM*(ZCE6|+rYMtCjrCwFb(*wX|l_3 z>;~wYYyvqOo9QgxU|cFsC@d?_!XEYwp}e{3OsKO38y3J-53V3zWgrwBfcM}rdmWb{ zm7!k*{TBhRP#&_NokG1nfn9Q-Y*{#$=9@Vwi>u*XjqloqJk6L6nA1P$pz)l;?2GS2 zK`eJt9YVR-SHXP8clLeV25HdFi+Mj2+I{qgI^pQ%BE^YifX0~veB{vnTgnV*8*72B z!2W0}46}skDO&x`T z`yHh+gXMTrM|eMCS?MITFE>CgmSf~``N*jRW#^%;u&*JcEdjUzQ0~g6Ln^O*K+hD& z%jUqV5C8C8%YrF-T!)6D4x4LM-gf_6Nr%r6*XEi%wy7as^g2sAP`N|F{s%y(Opt?h zT-2>zsGSb0O{Lg zTzMPj!zSY%+j79hsa+)7V>yM+PMrrJ1N#$Lp6=`FiRnOo7L@s!R_cNrD0|1@oty&c zKs*P^4yFlhpQ#Om6!u;;*nt}|eZwcWY z6TpwRHMzjSHaQpG9Xt&htV{hQ4!(ajK;M+VTT*IE^7FtS+g5qloZpKbHbCF9gl_`* z{d@7gy#A10;Q#x6LFxWU9Lq>+p{g`9=ud2bH8L}CT};X+f%FSfC&M@g^3@#H?r=PS z?*z1ufcJ34{w?n#@HH}g#~%D#yb}9qevn7Jj}ol;(ANselw*m$)1ge43oo_Hs4rh@L|bB-u`k5!iRtHAutn+E zySyz?H|%rn0lWMKGMJua?K)Gc|0t`}u9BYEZ_+^h&%wSbv@L4ZM?-8Nj!-<4TjYb=Z-Q1*mz9!dbuP>sz?eg< zi_mw(b|nznZZ(W6Vcog5Ukf3V%g%v(PDq3?3dRlbVLO58;%$)_Ki1!Q8qY(>X^MS} zCU$;Jh0MWXen3Btl}T*(Q@~ERPJKMT*bD1P3SeKRWR~>Bv5eG(ek<*Z`@#H~IHm$! z1-SQ<+Mm4`*C!}TY8`|2evnTB*mo1Oe?i}aZJ~b)`zt(EI96eG5!#zF`8Hhh zI;KS&YhoV%pz%am*j{28_S4a1;=4Ty>K4Y2-1_joN1M3Ryww1o@m=pSL%p;iyzk@T z+C|s&`572%p`6r3lFhN+mDfv}I|93mT~>R2gR2l9taUDKnuP5*wv!F5P(HThDWF>r z;12*t-Eg0?j&A+mH?|jGUO;C7*A41})yDSf0yD@zVYy_K{-P`H84hn z_5tdc)NW@%y6!`~yd6h*5Vxbn63H(3KE}Qe=7Cxzv`0G}hdf9tEMA!fsip8A;bwUGm742iOOsbpO?IY;~hnLn1Xra!;GUzu)y^WSZ&@ZituJC*# z*gFH{L4B}lwjA0~c&G6+K^pf30fzlU?DOWs_zP`HW#T&!_mv1>8$aMDtk8J=0o*Le zb9}GK`v%lLz;_H` zdyI4DSblk1033X$cz&63Tr9J6+>do<1IR*Kn8Ew%1J(_&FAp2EMv|){?H|}%oL~P3 z<_Y2;>{6(o#!!zi9;|aIB)r91DUWFQvhOu%4gmKW;r@1L0~Vv493lhDg5Hl%FG+h2 z2@>CD*e+;37klx!AZ*9#z_=FQZ@53EOj=>DN(zKChIGcl70X{1i6>#blvYfis!TtN z?p2ZW#W@>)D7!dU0&`qq+WnvmXF>jR+qtDkX~+7;%ib)o74C__Gy=EeeRvYMm`-e8 zk%R53t5A0VZ(C%hTdsu7+xg_8JDkyfqxRDEb6<}S6 z{aoxQVI~VOUhG$c|9|apy;7UQf=QhbeIWOor(zh)8Gn^iidP=^f14+luk`%2@haIx zF86EgVkQsBp1FOww8 zHUhcLIUh(oB+R|+9!CD5aT}%ejYXsJcO9>0g+*W2zKx0 z(Z{2!XV-q+y}El25+?XZjt{oRpOFoceh-x)B&h9VNw1*#-?$yoLYsdij5x_VpXmpgTe{2|} z*E%kS-^H*y_9MaF`+IfmKcHW)u6>0FTOq#6}Qw2ln3T&fLsTjdcyf2UU1RT$b;4X#TjDRcR{2AuU zMK=~c5jSP3zGnDrhVwm&oS)2a=;MjbL%Ik%L|nf_jx)oLi8!3W!}xv-zsztOR`Dzu z{(#{=4CnFcf_^GkoJnMQa`|Q=4)Pg4iOEqj+>bT1Tt4m%#q{#u@Z$0@n6~e)N_N&~ zQp;Yno&6xmk#fH*8|A}jTIRw)A8l>pLY9MBrCp8_7IfKO4t6BTgm&uB|8o*k_X$1~M&FFkJ; zVpw^>vy8Rzu|uE@uMarN;lG)cz~neFd;}}fhZ#PY;ijzpfjwQKivYY9)VnOmPjtNA zX#m$2?+;9lg-p(71^!;fw~_HL0gmzVz1%$BzZt)ij9(S%Ii}ZLhBpEn<#0Q4Ic*r< zOUCcaa6cJ7kjdfU`85!5ZFYbKO;MjnnVbX#{u0KIm+?0%6!5_cc!UBzT>)PPIM$bVrWCL5KLL*Qg*#r(4={d$jDLpVNizHv!`I62mki&^ zaM%|qIu%5T`oz_eo)Z~fhv9_`H-mN%U30*h2nk@HHVSwr1>8dc9|<_>)2I#;4DAlO zC(rM3{@t2efMY&xWjvmb z&lsK~!#@MA&7Qi@?r6jDJ)sT9-ecTm84D&RvDaQrTqxEWsjDj0k4jfp572-$^< ziyj}tdA{P49VG}B;_(x31_&FJ!SNMiedF*)FX)&HehY|!C1WT~Bme9eu22@k(a z*L6^TTVFWqq)7ND@&{83}RGzOMbte2Gu1keD*x z2Q2$d!IA*v+jwJw#{|aUkX+lZm!P`hcl_X7lqfd3_l47h$=NAozA0FGa*LMZQN$xr zaAfQ&4wOrjf$4$J=pf(d(WnGW3Ahh%Lv#6x!*LlG@i_Quee{?x|43gL=fgO=L=bw$ zz)#Tmm+>w)_S)e@MkH$Sw>{_o1~MOhX?rSZNZ0E`-?y$%B*e0RAyQWg9!rbLGMLd@WDg><{Wy?WOa0s3^ zLXT# z3ComJiU=s9NTr7O%gSr%6k$nuEQMI9E}cdEyYOar{v%#r%Q4c=&VI{zFl|=o+#95q=kzb*)6ijN$lQSc*F^ z9KYMj!y?p|;QaSi5%M57{^l8XBiM~RUO$G*<7MiK-^r%&CNnUC9JD zCwlVVHb6ej$85%z>wk{na{cLd#G4ZNPZZ?5P>=(Y#iEnzW6E&3K8+YI*T<5`X-4#M zQ;_4XAZG-TL(3sQ8w>TcAoBTl%H{Y%B8T!*3ErH@f&EsZlczU};qvsJBXX#omkDl8 zu#|#|pUw($Iw{B*LFC|C3wJ>ZazYj4EF^Mp zlMQ#v6yzi;$k|ThwB|zKdXeC?d|oGb8^V82@U{dugLx=)aywfvTyAG)hNGS7_wjuQ z-cAxJe&T!_I^^3(x8kRU;qrJB7%q=DnaH8#il5mbm$O|#&N+p6FDmeJNW9d}F9=S{ zn-R=gp~Li=OSj^u1;K3z?o4o+EbOSFW3DUm~Q4aCgEFB6wGV$1z-G`T!l&uoPVg>7PL_fk{+lrJ_U$^6V@~Ac5uEl1sXGC!KwX23GPVb#}IrV!4nCNU+my+ z8N=oJWDvd+C&M+1;Oz-+P)&M3JJ5VLWw>0vCE?TbIum>lk>8i#RQ?Ep)AH;`a9W-< z1gGU~A;aZ*t|fe`XDY#Ic}rKovlQf?BYZEC-W-Bk68yaau2)?m$@Mp7IOa=hB1cW| z!2}N?I8ARP!L0~Ck>T=q*AhOB_b|b!{M!Vl`V7k@mJvSH6TZVFI@HI9$azBWp#;w-_%MR&)s!CO`Zr=Y%BS&K z61*#s<3RA?1otBN2!e+)Tpn*6;nVzGMsTXnUV>BkmkBG*FkH@eAp8M@??rGwf(H?t^7+07?2iQy{#3@taRJ3O499T+?Pv1+4stn(3UU?_ zIkcb2_eaR(EK`uf&kB-{Q}})gxttUQIjKY++RwbmaLgB1VxQ{_m-okRGhCiu?};2* zt_lfG`+*j0ABSANCBxTgk7iVW@JPvUiExIA5*7%oqjJCQ@{B7ZNzX+B5V4x8!=oi$C>b{o@#>A{@VzGk0A0R736COKZfwr z2~OqQCb&1@=My}T;0A1eoIG6?49E9o2;r+4E-%k+3Ub^TE-yb*7363XW1jdDBanMx$NJ^5MOay!^CKH{|93uU-mex!o@1R{s( zzn$Q;-OEsre^^2OZ6b%ZdwB|So+!v^Q(v-=JY6;nm)p&a;c~la2u{m?s)GEj3i30E z9NI3uCODO!uOPorLB0|GG6p!g{*4Gu+XrSg@l0nF$)C+o2sjm#lZn!;_^D?1h$G*O zJ@dW|;_(c_ODMbNe4b|BwjfUDjgw@2C-$67@JZ|*FBt?!efU@+i{O*lJzjFyJ=e#d zJwGA1n%(2Y0Q5u0`QxNV!HD2f7={p!|n;QU<1&nNsc_R*CHod1;ZEeTH7q1*|M`oCvj(lFuQwWaf zn$4aw2#$OMR_?D89Qk|M^J{`5U&HuDEZtlmUhjB*B98ovjL-L>aomQLC)%ze--qGy zc9oag6cVo}pYhXWxF5@pi!wZs;jamf>FvOt|BLem@kDcSW;vWzE<^smIK|uy(u7H3 z+ZEtWa%y(%)PUWv3o}az*bwdzQ4arzqL!Ms3cDqR%MFrO-mm(fKT z{2s43SAjBF_97&@uMLm=6x2%|Uc=+BB+28STz~#-3pd)*AL=79_OJa6nW-#z?NxhNYYQzYF;r;*DdY*Hhv*s+nn%tY-U-s{J&ffdKpZ%<7J?mL(@4eQup5^~f z%l#JPvEHXRyXnHR`hq^A~clR{B5Ap5J@$u6b zUklwkZk;||pHE|M?gHHlhy%xXRtHDgSb;vqq{hEYAukh&3U194#G;>2$#oF3!(1H0T(TA7B1V3) z7JjX@8N@Dw{CwnW%ODO}{unXm^2d+)dl(z7>>LwQRASZR-YOfno^j!A{7?8%@-xfD zbVFewUU!u{&mgX47ID4Em$A}F!($tFo^jV8>njrxH_Wc#auBihG@la@*Q)_KoM&`M ze#*z5WzgroEb`ooxWQTEH#H#HcPH|y>uG#xG~%)W%OcJoV@hTbYmD(J zv*p;MEV5IvpPKYAJ{)Cd>@%xRjhpK7dHQVkCg_@UnKNf+axH-@b&s_btlo(^8pMF> zJB527AJ4G{{LJsOoFQi~W6oi}2|q{s2I5nT3>n7yJbQLuFU}bYEtSmuLGJal-8;^o zw}){$ce(hsJ~m(<*5lZR7--)EZBSla^4l#1JgRyk!hQ#@<9aE{D}&P(UO{wOcrle@AK z2br-IQ|BbzUxtpp47quoG3d}>cT>l@_5*R`b8>cIf;C$huhHv zmrxF1vQNv$l{M-d&wqrNbd|8T3j8$wpz_TiUNhs@ed*I>`FPdf(@nd>wfx$ee@+at zdd$m!cUjaG9}g0?TogZ4Bv}~I$%`TmPo?mMt5j`Ugyo-y-bLtAZtsH6-cewKK_puEt6$g>^GJ#!aY|h@~y`Zas{7+%e z@(tT!EqAtmY2=4G&{)`+feF_BNnYtY=WC;F8=MS@@Bv)zxL z3saAw>$R_<{234P5Y{|U+vU2zR!@As6w>FK2L;(uSof)Ltynh3RZUXq9@=GDDslS+ zaYNntM65Z&Hs9N2mABnO`^ECWP+w;|;)L>9kwY0UZYg8UGKTEySli%vJDp1p&#Dw+5udE6bZMW$ znsSfNb88%Ro`Osbkdyq$JLlw3J^40}a`fRDpmBfwv*V(!oV;)G{+;u^jA^7pKC~+< zqqVJ2clJC%9;we{iq~~H_Vbdm$z@Y~8Tj+@gY{hAp&Nfu@yf~|{4XjOGCHya=>p+v={xhOCxv>@hg??3&2UgMCez@{@)_><+xso&-)|z z2O{|72tGT4qfIQC?xG0(8Q{#<{&Hjl+d{ufZWH{B;4E)$oWn`_uPVBYd6~KD&j_7X`n^KTz`b z?u_vHme4;S^eX>9MCgAa^g7o-^>bQqook>n55c30`Q0DL!`MLVsVO=EJ4x&f&zr=eQSNpg%K4?Wz6d4am+zEf8)IK1DhNN)OA>1YA zg$%Kmi<%h(iSYRlH8mjslN{c$rfyxci(5m1B<4*s^-n$vYL_doLSPLaYXeu;)webA z@AhUFE+ZeO0+&>|WMH+_xT3jnrQ?qDeMS&Xr@o`ErR}zsww4YP#s~Q7Hi@PSj*Y9F z%n~8PpLmfw5O>7Il#(nlw|T&eZ8D5_B-837ysrvEKD^7qNV4BuE*3_=n~G2`pSjcV z&6CvC--diPqoAP0mNtYKZdX0Gchs+Q5tgX4=C&rqAu!b&4J+hRWHSAE*DbovhGb$a zmbWE}ax(glGRoT(DVp0FUC{s7weUJd#Ib&hr`%QVDpF{Cp z#f`Yy0MAnfzleZr*BIRDUt@}p&uAsazShu>G58vTbF51@8$09!3Sz(8(A$_g>QfVz z%TYr=((rlF;I>?b;(d!-ST0q9hvhO>aHebRwl=~?eF#E6t%i>+-}MH!dayAu4RM1$K{AhsL_ReB=k_Yy;&GWewiuQ9l_lf?$N^tA@R%cQ%NsC191)y+Y`%^f+}gu2gIl{A zA`dO{xx$O!{;LEJ@{H8HKLOgBg?Q?da!LQD9Ns=amf7swz zgI{CtPJ>%}&PDLO2G_ndvU}9vlMMeOf`{e!wBTVm9y5GwIqJ(0_45(Kf2_PD5&sQ? zFBY8dR|^cD5j>PfV@rhcXsihGzt-@{nRKr+_28K z#Rj+UEjJ1t^1s#4TRAriPQ6`k@})5wh~HrF_uwY|%IaV5Sn(IN5++EU;Hk&C`H$U4nGY==NG=`r_wm*k^6ji22POJ#gf zjFiRBbi{n~@3@x=F0Vm(78+Y356A&|*o|#EdA`^Cr{iAov~4j?6HQ;tm5|#sech*l z@_3rNTKKy_@+~f5`3riV?rB4MoF~G;T)E$3JPv93%@O9EbbBx6f0EqdclrPDex8@- zuNDr{lD_r}(+sGKu>6RXN`JR}%#9mR;K`#f{pQB%x^}Fmq~37TXI9UeGpAdaW>lxRy>nl<-R8lZcH*S*tuPqFyy+f}C-+_Wwb7-Q8PgAMw(2_@qi<%u>fy-Cmb zGsy+n-+^D<@4&zA^VokL`!8buMeKhc``^d@%h-Pzz5?+18$YCXbmouJJ@E5bIiw<~ zeYPC_E3mg5{N?Jw)6syZqx-I>yAghm2ZS#3#@U&f!L^r{-SfEz$0g+}UxI%~X7H!- z=jVc!W&Jm>Da`|H`W3Dfuk!PpYne9QoouGiZ5>0*p)ee2q*)Z+-~ z&-)WpxOzbSz7Ago<=q$P)z*WK^75^ZK{op5DSfj3gTuxRP1dH6k0$uyq3!5wOp>h) z@H?tE>rqpVJ5Vmq<6ghss`p*V!LOvB-bBCnhA-$1`n7sH7uQ&>o*#WpJipW%CHP4> z459yN30?msWYhbpTl%qux_!aWB=B$KI@zUleP9pml)i|x?W8jKc)|CuVAm`Q`r*to z>kre{1C95-D(HAKeBxA>^w)i^XkFjJ+TLpST=Sm3cr`wYJxgp?eeB?2NSAct&(*m!kbZ8%LRa8sFJdhcuh4k1_JO z-S~=ap6-3c>Z{;~1AjcGT`F%Z_t&7GjtN``ob|Yh`rXEKd5rQ}+5!29c^@pf?#kL< z=d})zmp;47BMV<);?uQKp!twGxKEA54yke9O;>^C7lz4$SmzMr3+NjvMskLOx<=?mTt ze{y29*X+Qgo4&|er*;2^!Mrb^_r*JH@RK-3xv~8jruY32KH=&UOn>kTQUCuZ_Q&AQ z_5ytVp05~ed74+dKKj|VF}j$M%lPBfgjui=!^GI@AO&AzsDJ0NamZqd(;)$#mQOdbO!wG zRd*@W8MeuqcimGjdQ9E+mM7gWV9$I$4dutrtveUbMLeF1oBRQYx?89xuL&p@|i&$&^~FKYM1H3$;=$yTSvDp*+aWR zxz0qLW4XSiU3Sa!h|dk^M{LR05v@Dcmy|X~oAJCo-RrL1@P6ccmeOYa4f~_e$qux| z)DLx@akiqqro*Af;n4Glu5`uRA7o)GKY-4N(N9rz(~I|of`4l9J$>*)-GO%9^YQkb z2F5ur>g!1U8S=+_g7;x%nw}Q(A8Io4TznOEn7U`X@J*-tzcB5BeD%m!iZod}o!(WGfyOU`n z&sB`=q7EM%Sg_YVv~jts68L9|{Ibt2Dqy(zh(psz>T>R;RkJFQ3B+OEK^x+$O98T3Ds@;xW* z4)i%QIT!Ehs3Y4^E}EW}4d3;0bNS6Ts%ty=FwI`r(RT1)d#BHo6tFDn80FsS=;`x2 zvTMK=&ohT_!~}LmnioLhZE!?aYYdtIHNf3!RkPSQ5L|FB}c@NwROG<;hl z@4CRA$34Cc_4O@_IW{U2efPbe^o3mmvIUtkujzdkB29l^?+IdT%L`Zv81>`J@IvsS zjK2K#K}Usj*w*{!fX#dAr{u}@k@eTNXW3WYS|8b$c~5cP`~J=A=pfQOhPw5FuUq)0 zweKLPlX!>n??b-s^`YD|ll?Q*>xp&U%b$Y%HK2W|N1McFMIU&+Chv?1?2_*~;d>UkRIvu}~%nZmP_+|Qf`|<431zpP5+mH7I9c7S_U1)Zl>1l>#+&7#(a{af8 ze9v9s8vAbPyQiCuQ_T@v&s&AyGlJhE=Q_@F2hNpNF1g+3@K641gt;mGS8z=HxI+tl zr{BbRDL&s8dW|3P?Lw&&)058Soh6w&i z;WG*!GThY1aTGqLVrZ)b3(u0i{;|Ll*(5HI)Y2#^i3&+ zkBQ)yM(}Fj)W5EGF-hd1Pjo5%jY6N5sxeCF>6=oDzEkLRy^AWL-xHz#j?n8Ey7K=) zg#O1ue@NuX3jYBpZ{}+uIvBV$`CT$j@ZEwR68r|>rR4ui1YaS1T4gNtsPNeqp?@TT ze^dDA*yuyB4{m=Ip?^u}pOGe|Qs@W5o|xah!T$bx1RoE)RKBhhdW~1T1$?=sBlI^# z@J~kY)e(FfaLRd12Go7KoFv~6{AIz{cyW^NMEE=@^cl&V@_8{rPhaU$dKeD7DTTvV zS_VO!w=|YcUDw<(b@ue>)9FP`@6WpS7L1WJ*9C62!Bw{eUwhrE`jyS%AsXKAJZj;l zixt@58te9@c$B>2@1=up`wHIeJc3K!Ei}P3f4?|E=DC<<@&bBU@UykKejV1}bg2du z!cp9%o!fLnTV3<|HE?OJE}eC{db-scnFFWUHLF|is;*zRE-7A&RWGl?lAyd=GHK_1 z>Q{IKecK(YxTtD-Xs#+=h8KEsX+|u={_fNTU-+QPfgzpP1DT5a+Dmiv zUfjWbZ&6hP&v{o!m<3Si${#x zh|93IJ0BFm)rXnBB9>m???XPbBYYMM9`eZ;`Vo>B?p8$bH4&Weo7^ameZr2aI$lvPzj~RN4r{z5(HePu*| zKVjd_67nVZM$T zJ~m&2#*QqdFh-{@-Hec`CbUq)j6ZY zryD&?iqOwCxTUu~tJQ{&^;xz0yfwmSi@|FQpH9I;J!}&^)WdGW$Le9f!L6LS4j%O| z)1>=EBwbw}FHHBC;cwF&B+gQy{znT{C8t=?uE+|sWxxYb)Wg71ysb{#XThZhaK z#m^XgywRIo_sq5rqogsV9*WwB2tF->>m1yWkIuCvZrhVv4WCPloLPfkW$=e1xLx1O z>fupCZ*l8`YRhG|d@oZ@t2gyQC2sXrYv`@sG7&s$aGS4AgIl}GMew}_zs%_8kio5< zj~LwQS$!y(FRO>e;#(N%;Z}oNJv15I>cOt}W%131-pbi&a4Y8{2DiTAeGz=9bO2C( zOMguS?=-m8L(bsW7(E{`xTSy5;MRW57~JYj*TtfoRzE{!qEv{Fjo_0acufSi>ucF` zZ;a3{kKi2!w|2WZg6}rCwf`p~_)&vfJ2_@>YbPfRZsnfK47&KuqC!V6W=31m~i6e)lY3`Z|@(q8p!{~St=>!0Y6*! zn2|L9u(b~Ld;PD}1KIN%pIBPXb$3!eO1DVm<>Q{|3=)D-vZw75uaI-yJrbm=IBD%h z-IM2gy`Q#MD*e5ZzV;hwnkv7Z^P8bm{sN;g}WK8J@GgW{dek(pI98}nwkz4JLT zou)xgJ6SYd^u9fFlZuzkqer}l5+nqytcdbkJjD+uY z-}#t}QIV{~8nv~_`~C5sV9pQXR!&wwvdoaAyI1H|fzDqOzom0MzY*DFYffki_j`XV ze8+WD#)k6pt)rPHe5usu4Bx0V^!wDb&>>lqaeiU+P4uxWE1h51@Gj>UHppJ5kJm`? z8mSTr{RaFK2|Bj7TyH^wiM^ap?fQn zePf)wKK*}&kDp%GJ?Sv1zKHG*;pa!6L!Tb~*L+^o4^icy43swo{Zr5IIo(J7qCt0M zML)$PmHY$so-YgJo&JbwO9^6oXPn=m`p$~qq4V(@-j#!2q4QbPG965@R4LXq3#m+EqWjLf={L9aUIJPzQ!5&$g*6uexzSK+xI<@&CrKCZ};>|?aw2ik_bEjd48pVyq&tM`59ybJOP(ifZcG-~(oM>cgn}C;{PXnh1u0ro)o?W zmg`3a@KQd+fPu?E6i>`nDqi$-Trc(cIyZtZkKk(}_~#<{mI(e}1m79K|15%kJA!{d zg8v|bzZk(^2JU=Vr93cK+ievns#5wqKZ3LGu@wEK5qx0;|9Awii{Pt(Q~q6pz1-SY z@}DF0|3&C`2lU^H(8HrgK31JCqx$izTHV%h`|4HA>+Y)ao?ZN&ZCTTbP@!Q6*g_~w z>&%vSTI%nQMIX9;j&sHl(7L$Ml@I6id~$wqdW~*Wf?MA)6U7sOEZaLeT2?jJwSTsL z4T+t@p=MAVH0jfXOX}8#tDn7T-gW$XS6Bn7`dFAH{hRW6?H?XCf2qg~u!Q%NOSS~= z+_FlhseB|7?mLI{MR4`GA|JM`y5VEfZ6Urqf_E6)*5AzrXMdA!eFnGPRW=@@rN{fd+bEC4 zu@+Vyw|cX28f{j@lKN8&KP=&S4u}$SYC*I;Wpy7ymYQa zh)*%}R-V}gxAu@WxaD7KaLWg=BJ%QB`Lhwc*WjkB%=xgB5#_h#`;auOA%2ha^@aGu z2Dkk88r<^NISAxq?WE7pTm8IfaI2pa5nMal$=}jz96#b#pA)5XK9nbGa4Wy{S+aPI zG$Q0}R;zQ**9O8>3c&EWfc@uE|hYfCh@T_l)9fPwzEn^IyiN+_y`T}WOdCF;V zjl)LV*6UWo$NJ74F}NM$dnSVGbDr&O%E+nDbK(;W{vSPF*(3I0gM8`xjb@Q$MJ%m= z>~&07>j~8f)%5GjkBtQ#57JfkhS}il(po zv|!VC(QL1a{8J6aL%mP;*Bi`|UJ@oO7xg}+Wm^^Io!6#Gqj!rE%09fG=kn+&qMRh@ zFBay^4u4Xu^L`mD*HY=Pkw)%^L4v_49oFmV&i+ovVy4fTHV2{1-ql#ls6~aWrQKl~ zZ7?!86yMlvcDcv2O2*mIxIySQaB-zHwhsIGdO7b{?qN))ap`2Oj^i*+4d*{^$GFY* zin6WumS=mi=x<0pFz#f+ena#{uwMr0?1R2K8;kOyiMUNkx$l!_e+TD5 zb6iK`pCQ)I+ULMmdGw;sM0spRTo%SBVr&BKOC%lpbnx!ejsC=?Joj-xe7{K!eH}{6 z_z=qL*ogk}ppVkUzR-Rcjsv{8VZZ5XDx1u{rt#=MXI!_rW0SRmKAhCDzvcw`osf1X zep{2}_3P`Q@zn0r{Yf(J2My>qVr&Pr-Bpxj=L=<9cRXI^;u}$37q0Ed%DqA&vW(_ag9c-5s0`OzMmEOn9P`3 zI&SvnhQqFJYR73m=CKQM>XX>-*a?~$Wm|Lim2EwMu_^M(&G32|ml?P=gRwWnHCcK&^pA0+o^e&l z+R9P$uHHV7a(EdNuC3|qeH;7Z91rkHV|-A@S1>LJJ@~OD&|oajA9GxXb?DgW^xeH@ z&elHv+vx|lzW{k2_hpqrj1tWsVmov*&H>MT|E5o$eRn_mA!57XTH3D>x9tws-{|}H zeulm=wcX9l*`+(MX5GOL6zUT6yL2=3%YMwNvuD4;F}fVqPJIlR(+_k*9Ug$JE^ipq z^E&dfq+w6{ATRZ;{fW6s(0m5^I(+_GT(2GX#QAH>DwEoYNQ-6EnB2RxJd3f~8SL9H z)s^p0|0x-)Xm@o`D*vEM9=6W zbXK3|q3^h1CD%DlI>)np0Z*218g{k4qI@gcT}%Ik)38Cd6{rJhYu`lr+i{-4dX&lW zdwxGjKKI{KgOXD&-zY!wEN(-5c{1-P?_tH|=xvg9fOdP{$+NXzf1zwEb^mx#*?BsS z;VGZS64#+)$LIU6VT|}Z*csN*&D@z?+CD5h`s~1DZ5i;=_EhNi{?}J=FUq?Q{phrJ zTSge;t>HDvBigUw(2dkhjCE++!WcBZT(DlEso#{3IG;1QmtBl1caApF@x*t^soeXt zzuvbAPA~6EYWZB`y;)2X(BrRxp7}wnlgTfX&i02kP>lKVG&K@mwbRXPW0t zd2+|k)_fgp1!DbAzPQZR!-7uEL!DJUsC~P8abF7SxIXxkvo(~>**xOy&{n7$Vzd{w zm3kj-gJW~FGp^Y>17%IR1+eX9D621H&vVvcwuk-eaY3#jD61KuXT9N`yxNnbr}pRI zQJY=54Cfh~FTpvk4Z8_@*H%@sZor=c?;_iuJ6oIJ9QCQE4EqH7^zo5=I?PkwvxPe7 z-VyMO&2g*&a_Wy|o|9+p^WgD(S?;HJOZ@yi9FI?OKOL8py|f*AM1I`!i1k->N*=vv zBe$cB)rMTzp&skGFXv=3pXbG8U1%@=1nniu8e@bg=Mh~w)Ftxn!?X44u-pD+T)6jd z@oc01*skj{`Z4HhI57YIQi$VKCwO<&_ym=kNmbx;qdp$pf=ONo2KDT{bEI*z}-S-XkyoQfOmjl-OY(Kwu zbUU7t8_z{q!q%0C^QZA)Kepjx_kuF64LaoD=;R*ImM1T@Pso0?VNRhf%uEJ9$jI_e zL0A-ov1~BsYu^k!oA``CxjgweY zeWp?`5#5r5}^y1vvhw9AAv%ML5pK9EP8ni=!#;a37^WE6TRMhVQtYjo3rp9k2Qrcn1*U@PLas>A&SNZi-uW=`FCYop@K-aWUSv zU*LO)zmE5wp6!>VPu+P2@13|Wg=fo-x!E4J0l5XfEz6p3!OE2X_S$ZI{Bn5S^vQej zk03M8oi0#!^q9IQM*X5~+*diFV6(Iz@ww)y&C?`yi)+b!=S4P~|0D<@``vR-RCJ3!~(oqc;s+i>4%_$Joa zou%TAF|MTAptW!6CueMZ^XT*&(0gqL?J3_Mm=Ctinm+PBIfZ8o%5mvjymO^}T=HQB z8GKAz%5@rYGcIP4{XCv*Wtux-4?Di;Z3n!bJTM0K0~=!gGh#cFXgjcx9k842JB{sJ z0oxguKJ_oBVLP}7^6YbEc2S{hpEKpkSkyZ{B(_yiu&o5;TnRcYclI^#KFW~07`BD) zE*}5CydURY@4gIG@4AjT+miWs-ne>lF5|q>?!2u-pZl2Bu?59x9b}sc{-9fGoll?%~8#gX%u4C@!3!RSmiZwaCYgv?}v^|e+>B!LpiZ6 zV2n@3q-Cr+=8HN=;ak}0)Agx%`%XLi!Fv$ig?n*-t~}{s9t(XA-iDM1>v&m;{;FR0 z8PM}NIs|sAcBwKp4aqL09{9|n&YwaW^e1_9!(Z$vKgY+0reARtp7G4zzQ(ex?3dv? z4c{mD++e!&F=8J=Zg|<&Z{ypz7vF5i&*b~cldTIc^KH>V>K18`9&!ZzCK@Nx*Hb)W ztMz@wf2-x+hbHG>?-MV_cQ1HTcD5tiaC|Q?);`xNb*K4FJ|^LeM~>ob?}Xtyum zx7`?g+j;(du8s1~+s%`+OL;%jc!m0rZ@8U{(mg+h{JUHmlsJDTJSSjB{vCk%&Kf?9 zN6vQ?zLVIvw|p+p4sv)V)Ig8aAN_ph4jFgyw~P+8tSHAW`fbCWv<;>n3;lb4>H40$ zzPuh-?hl~c`A&rIvmW;Sv96Zkor-#DckdV8&Zrm0oNs{5>N^f;T-}6SQa=A3?0NGU z=-$up?X0>%OiMhI*j}Yi{Rq!h#+p>!Ch!xa9-g8u!S^}0|NFAt}h*xy^;Dk%2UY)GDqv7flg2^N|uW4?>Lb<7H7o_T2Z(qHxrDMgaUz|skA5-{M z@TtI?=iFYzk9^Jq^d|(@`Lf-jr-9g$e!n;*JU}Mc_#s4mp*UKQ zFSknspTe(3Y??0hPWsLOXS_z@Cj>w0Z%b|!{0TfTxh=;zw>H5iR{3+CN5`{LzI47E zWuV*NlK(FichmD3oTsq|6`1G|ZW|$wsG#UlX9V97!T&UZABf=S-z}N$(FlGlf}f4x zBVpI2@^x7RpBceF9>ISzf_FslYy@Xq$x?F0;!6H?g#LvHehwbMrTAYM!KX&>c@dm1 z)TQ`0MDW!Sd~*cM=92lk00aD`^80}Z&iIt2=syy{Z;0Tx zM(`C8d`krXuMzxDBlzJ6{=*3VqX_=<2tEXls8aeF6TzoP@N@)U62WhY;432d=OXwQ zBRKkmOXlla5&SPB_%jjwl?YyeM@1=pzCVIr7Qw3{_?!sNHBw8Z`>6=t8o}?5;P*!G zFGlb`jNqJ4TT0HJ2>#a*{OJgOEP}rl!OP*3R!W}H5u9hHNQ0xmIi`{BI*T*NQDg|34%6&m;Kxc(E+SXIuoI1^j{pg(lk(Jun|c6W1rJ zTbt^D@FSzvA%nRY^oES@PSg`D>x@Ffdy6M`bb=Ti?-OY7Q zUVH$zC)a**N!=1kfrKdp!VxziB=hYpO-$O65QbdUkS|$2bK0D`c{eV)c_}9vOiLDg zY+2p1mfPE!*InOs+iJs?7nU|RwybHv3a^E0VrT0M>2f}S6K73x^E#;8u`IrGW&OGq zPlFHk+bO9LgZGx=MppBd-88*!S?$v6Z(3B>+T3<~$BH7zMFCmu%gA*oxDr)`xETt1 zg3L~rN>NCxsTqcVNfS^zg)dxiTJNucLO!6^P}{|&L9MvzsLF3|bL^4Zx~7)fo7+1Y z?s68fVCgMOYH#)x+i1l}&{EBc?E6ZXHKAQq-`cvmu}BlHENKcKTj&~ww=9Il4qto= zu3xek2IWL;S+hbEAgHTR`rNfBnq}mfgg~l}Qc_gVMJM%oW0BqqIomTJPI%b;%8dW=h&{S16cl~ zacY))xZ^xi3CiqKXu4xfA`NA6%jW~4H?Lc_8g+%;c4%nOzO#9n?VmspZkj8Ku#xpT z2s45|t9?#C(QQ1`Q%$hTdC7+njc9J4W zk>;~cox0N2*0`W*(|Fs~$ceS8c~v8VfQvw60;6>;I!wzyfGK4GG@5cX)^S7&aqWUy z(*lT~q!2;<6Vypa2VcBP;B&}r^pU?v3k%rNaSzz-z44}FG@)x#NsUu)8>9NkWNMKJ7y}ZTxlHE-f+i)*jYJ@P{J!(FlIh;Atagj{ zRR*{1ZOY&`7YYcAnP-}2&S4{^0 zl;OYG;8xD#248OIZQOKQ?nB<^iI^|juG)C&wmqye^tTxPDT9C7;I#(-jKP}>u4BNw z++lEQSKAD3^SjsJwjAwTRZIV(p})?^Gew3(sfURMw{g>d)8I=C{eLoe#^7}ZUvKb? z!8aSc-rzcSmhvgLOAMde41XK1{dR-z4*1JyqH)=kzvA5iJ)M2H z?H63>74Hq`=XvtvP(ZKvQNgLt6++A1ivgcSa_xA)NAYBcCkXjW6kPQwY?4WWtNe=3 zHheBq5c`D&Z!!3i2(IhzQJ&v2^eYVgwFW<7a9bZW5C{2Ke609;5MOEdEHSvHuQhn9 zp)?IHlgQt_bP+ic<|Q#yAA&~Lx05JR?cS(ZtKg72Cp}KY@B#oE||pY zHp;o$(9af}dRt>~8~5G5zujZ#*BbiGf`@jc@r^^fdf4!>cD38!ml*!t2Dj}k=9suG zw1>k6UuXDe9QshsXM{eK)5fQ_a=t9|A)gZwK11JMkh9&$GuGf82A^bb`d;Z~WhxuJDc$nWN!^g_A+2A(a-3GtZ=>Ji{!*qKE57Rwt_}Fw`G`LN7 z&@i7^$bX37A^()%v@6U18iQN=Tx{?SCSSD%*FI8SzSZE<4Sm+&_Pb!4!B-jj-3I@h z!5o!~8xIp+9N(|F+>@HQb+sd?pDV>TR*XHyS>iD94TTS$E|BG6uic;A;dA z)4eBxZ!vuA`|2YGx8>VwaGUNE2Dk4U#|&=Ev9ihw&3tV#@?$cd+lX5}%LNb1>sG%#CY{b;8Jxcd9f4si8XP6xR9 z4XaKx-6y18sa%SyKlJi|kNPEN0$lx=R|L5F6R!zzdH>V4QPUkHblHIZ8lm43;Od9n z8Q|*YoeS_9Io}=N^nd2I*YEP>qJGl*16)oq$nmb%197W=^j{ZbD#py~TmSd24&rT+ zS(om)e74eZR3rAT7b^8Y_G7RomX>qf?Y+Vuy*$eA`8mXNw0s42V|v6ZJX!v~BS=>- zNHOWD8zUpn_j*6;JbAJX+D+3RYC#-_`Tq@IrR3it@*fHA*ZeEYv652y%PsU2Cndww zAInJZSN(k)7)h$}v)l5K{;b)8I2LyKeMYcp0o`}x{;2^T-p_9|#VqMda=*oR9MWC@ zEG#?HJ#-!alf=F=^E|wt=V95A?qx}TJr#$I&Bw*~h5BQ6TB-C`kQm!_dV@dhmp)zF z-c3xa*;mb)opRedUtc7_L@wRZ?jVi)3{G@zEa(1lzM@-W1oOL~6Bj4N&tLTO0cC&U>*|%PPc`xNjKdM2sb zWFeL^yqYlYy&>R*$5ItyjJUKp_w&HuWcqmM=)s2GIndMe?T|HLj3AjiJAB%WPxXNg zv9d0hJ1ANEB4Y7;sUewj0JOc(o6<4{3*z*2&zP3(p}wDk&L*IY<|pY>F6I}`$Ir%G zZ>*WH3HERhw($wrXcot1&@FYbo%+N+I~eo8&z{{k9A$Bk`7$&Q$$9Tj{aoa)ftGRI znU8v;@!)OgIo&wV4NN}HI6^C4hP<~Wb3V`eFgLyzy82zxmm`+Rzv0>klT-Kc+6U98 zGKe{o<*~8RFON)4-3eL0G&(tT7p{E``_E#p@yie&W^EdJ(7HS>J8&)1D4ahqcx~FA zX9qjm%+qhib?85Tz6IBj546dhjfnNMd0KYqe3aquAW`g^_69bUU`{c0*^9bZmSl&GyC>NLU+7b1nPkp*=(VgVnKSO5@;&43so0Z29@(zg z`j_C`$G#}cA!mD9jxv4C%?&Q=DubOs=iSK=)M;aPm6!v3FJvAc%q>UPTGcY#vkdLg z4A|E{;vSvzO(H>8V}%gJX?N-yl;n% ze1)<@H}g=B*#u>K3#Wl#^}x>lKyI zg@0bpeLVHj^C+hTbIh9%w^8fHy@(Gmk2Xfzf$nYDox&V%jiHg8WAjzjwX2;mwYbjA zg~*qGW>S~u!De!G>7IW^ehT?2*gv0b8R(z(Z|!{|;t{c(tvB{gTfjRPVk!7|N-XCL zVhq;fe#%RGWBIadZ440FU}4U@w|CXUDW_*Ik1x}tYoyUN4sJq$)W`d5D?(TmbUtJt5Y~h&6-+$W%ab_v!+g;emPI3PEYZ4I(~1dRjU10VQ&8x zDgPAY;oNUMuNCR}tw>ybF(;xy;zqwb;>iGanx9+#QNf!8@Aa3HTLjnm=Vt_O6UYT&!PVEKQ}90!{KOy+>=m39m3(&b;}08O(se5pYha(dD8ehD z?Bnak2=jjQB8BKT_&{2UZvDS5_5aI}jh=|2>~KODgq zMev3Qepdwld<5ruET!_bJA(H_@V|`U`0gvo|3?uVFa9OzhoVEHl$_%u__PR~j^H1Q z;L9U;V+3!D;P@UaDgW<9@ZAyo(Fh)k5%4tVFVMyZwtWOYx8*x&+`2k$iWp}LVm2Zc zzgd^$f!5~wHq0%_pL4pRp0r^8P5#7B%*vng;SfM~V(QjycjYPEln-U452O55OwPfx zDSzq~$H6p7$R_h%WRgcqdxx9A$2nW=ZTZ7ie;CaD)A=U(nO-{OsAzf@rnaFjr`C-3<$`t6M&&ZdP@2^O9?CLJXfe zirLmqHk?W%C2Hms>7k#^qcbf{E<`dd37z?)=izkKe5Tx#BR|m!SYguB{7+yxq~=xB z6-}Dc-DJ9rGxJem?i?$V;XsFs6`W&b7M~YC@~E41NxLypO^es`y?}f! zQex~ga;)+Ulk+Cot2~OY7o2=X%Q1KQe5UUY#~XCxbCa9$|A0SD9+kcFSNxFRVSb+w zT=}qbh?}+_%17~|{<719)mxw7%4de0ACtZEQT({zp*(|-Pj1R*u0KueoF0~=;_Oi6 z7V?>BaJ2!_p^wmQ%3t-bbAVJ%#cKol8~pA0m_JIdc*dk__0wu_EfccZW$+IQZ|?RQ z9N(w;&CVH0<^b-^xEq z@R0vl!9)Ib&W+`Njp0AR$e%Iz#Rh-E;1do0w81Yi_{#>jzA*S0aU1hx^`9|#%J9h= z{4#@gM(|t&-y6YuBlwXB{*2(E{`&+E^POpBW?ScugnYIM zeVFcU!^f7p&JiL1%Z)zm91(4kc-hVck>OW&mtA*iis7?g27N<09~C^5vsdsizh?}N z@rC?0RKC+lZ^scw89bGzMhr27Tl>ih&U*bJL(f%JI&nM4 z!q#h@0};xp>vDy1&X!NyP(MoyZslBIa4XMxgQHU{zjX@Ea<@Gv4;y-$-%*48t(51g zJQvhWgI{9sYYaZy;G(v?4~TwJ=r>sz`14Vq{RgAuUd6S)WKw`@|AeNc^x8kMIH1>l zj^zQa{UZAVT>DXa16=!Q4hOiLz84>s=GOYDjBYV?U32Tyb*q0heOH!C`D#9;+1FF| zE=eq%NBqH(D!ltU`1P)KB6ulc1D{nrn097M;R`Y?`y_|$HE&Btah#4pxy6s~t>{UJDp;>Ul=C)+h^dNBsVG&f@m7<%n& z#Q1SJ)`i$U()z8GmgfbGgCS1zlk?8=<7qx#{0NSTb|KqtJu*G+FAwrBW5T4hc@M|3 zeBLFVHS*4JMdtfnud8>EmS200v8kCBf12+m$Zqq!34SgdGjuYc97@T;alkO&nopE# zKL1=t;mr+yl3xps`sY~Zsg;#`PPY%(^W4;=n=+k2*_;*|$lZ)Fr5cWzjdil-zLNCx zfoFns-OAm1BxAte>mq}7WRwm%0`9^iAa;4dpGj%)&a#$kY@t3lKPQV{>3j|R8a~u@ zc1F@2riF$CHa9%)CuQ#+Qtj4Cdy?yuaD9*q@f(fbMflN{t}UbQiq8-An!7LQ;ohwm zbEWI5*!Bj}O+g>T8H+t5$0sR|9Mf+5K%cuW-SYy*nz42Y>cmA|<8B?ecGt}uLmb;R zk7K?}1HMq2CiB$m>y}$HWIW_?>7aaAj?cLHTS7ddzg7-^sZRNe^w% zuj}CNWt~pmY4HNGD>W)PicLcq^-`DM(Sof?Re7F|Qjzt*H$Nhbfdpz$4pYgb#YvasKhQBl; z_25^@s~x<^=Q(E^BfGZW@AXcfiS75Nd&qMKQpNrW)OTup2^$)j)UfQxD{7-y=Z`cj)A8@8kBiss8P zE9c4NskTkt);>Q5KQ6s?tYQrO6NbZfF3QuSFDUrU6|RpiTpwEM`h|t-??=8iKxX(l z&BIzp{nO%lI?{e&4Wa(m>BAw{hm^WbTa@ePA}y@B)jPnit#lsh?#7DpwL5o~Z%xoX zWS+{7E=L)bq2Bqn!>ut%8|d2cl{9R|^I?1N1*|oO$7SbywD~Gi(RKLB=eH7#E2VgsE zQU8>#p!bWqz6zZBEMQe#LFtLGaqxxs4J|cMH||_02uOIUX@&6bNYCCebJ09(x2cLDv zeqDwRckJ7T_3n6-qq)-^dmk07$Cmf0YrQZOsZ!VJYZBu0cd{6ti9CN3d-6JfJ#|65;96Gi=AC8N`wIGd9`_#%p55x(W8b0P z?K_LUFXFxEY8R+3b@TNLuTEXko(xWIx_()0YQZO#e)3uZgOlr8np>MvwFq13&*#^- zx3rt{C97NSYFoXkrM?xcuEr}Rmrq#Le04J4oh;I@X{kvZXj#|X-rn4F`PIqI3=DU5 zDlymZKv+>jVXmyWt6^OW?^+-Z7r1d*b92+x2}HhRTJ?JDeo@{RuzytlSI%PBZ>zuy zL#eHzBBEgjgb}OBOeMuB5~gW>2Ndj@GV5YWP$%0xyJF5p@vQmCq?j&L~y={ zl;YC>oat(MojB*V4!=_LpNruCIf6eJ!5@y`UkC2=AgXA^Ik)}zm6GT0fRkRwCbp0m z+cErzpAbINq>qpdYbidJpeu#5FRB!NX$1d`2!4G8=R>3v|Jx#X%xB{FBlLd|!T(zX z|LX|e7r|eR;P1o3yi~rXMDX8;;2(|PvGonwBlMdh_#Z^@Z$$7vjo|wuILEF^>49Tc zrSPM`X}8*E+eu^QR%rYuB8aGszD&OW7ok_-u?62af8e7h(k^q9Pj)2Z4~%&BY&%(w85=@ zmK%J8zt#OW8Qkh;v%#%?bZjKlkNO;k`gvIRg!*~J@VEMT+Td0{eEx7_y6iB~?YP0M zeo|;hxsiU9KXm`}wc|$oB7f-qZ#1|av!hQPH`4Q6Og9@hRBe^lT7_QqpgLV6xavXi z^@hLosn{IwQJJ;`d=&4D@W~n6`Zn-+#f|w=9z550r7FMX?QoE;;_7QbK30BxwI+`5 z`}}5oEmCw{tO6(-#YCfyE$Uu^IP3_j7| zIfGwf@NR>1yh*oSgWECaXAI7FeBF*4{Bi}cM_-iNs0WKrsVt4pj^G^;d~*c1@kb~7 zq};#8AEi837~J}D*mkl{_-nn;TaKA@rznWMjZ13nR((8}uG%JV8!De>YR}56N^nhA z@v(xFkG1F72EWqCv&7(5o?8uW<;e)H@?0al)VE&cQC!EMLV4~9_}nObvVtog#npF( zeC)W~!vUY=!Y3E-QQXE!wR|28_%sWj-hhwdPYWK(^P=FYpOwPrc)&+-edvaK28od= zpZkQ*5W!VHil+n*`AiD<^a!6R0UyQF5kBh;Zhc_37<`)W=5CwdD*qw5_K@Hzzv2%E z^nWAtxqx1At~11q`L%X_Jm8}?{c^xZaT^!b%CGTXRel{yR^K6&U-53%z2!3M(Umn5LcZTU& z{%a!i_ZYm|$g{=ZGYp=VmuB*}@2d+9KGe`_T-Z==%Y{DFoArINdQ%@Krfc6#+4?^|E|Ln?nV~1 zxy|!R%Tc%FOE1XdTTi3DI(?$Fmxp*#vSB(>%=vfsO9hwL9Z!t^6G6IqfjsQS=R0}6 z*ZXO+kY>1y8TQWECpn*_bE)9 z4fD=xN95)F7A2H@ct6kO6QGDvwDFsLN8?BrY#XLZ`b@ zV;bmFG)irJOFzPn=JjY>+=5tB8`|4{sqGEFv#Be2<3#XG&9Z4G&bbzSd&ySh#v+E6AyNgMx4Y$0u|u1^xeYXctP{X8#ab!+6l z-Lj{S_*(K#>$>(?+2=4>h3OZ}a^|dG*Y#g`U58SCUDs)M+?|p~A zTwa#{Prt+4J}~C1)I0p@#tuHx-S&2Meb!agnD4^vozHE_nvS(Jg}@i0pWD)tpXcyu zMWxJbNxF2t!yAYp$2kwDD=H>$hrcjx-1by?vX6WEi)Y3p-56JcpR@X>`aS0YD0ade zbMAoRoFkBvxif!^q3W^lC;eaWCH==8jM+wC?-7_MK!0xUm){G2{$9ijE9*?3nl~WX zSGhTT%F}T^0e!Vcc4d>fKgho6=@6r}>jm7;xNFbBcYi>Za}7o!&AC6woB_?>qwhOZHe)NA;73V|v zpFCURWn)}AmEH6DC*OEc;ui{#m zM&{Mhd~!b}u4O}CdhffO6PqZzXZcfeha_v^chI?sb2_FZ!^S;Y=3*~WSND}CTbrt~ zOCQ7ho$-k8m&lx*jga9Ga9(eKPcVIwtIkdLd=0TX(XU^dRM5{meJV95xoQLEh@_$0 ze@0Bv1T^%Ce_#OTk7So_tUx?c#7RV~&XpNpcxrT_q2Ia?@$l}2-!fyuVO_wPoD+lC zsCnDM9DwP)FP*Jr98ul_AGliHw;A)Pb_BAj{odpJvSt2>nfq1jm;F8Gm%Z@9>{9Y$ zzW)_6XnvrRVNcon^#>v9_9!@N?iV~A&14%y1^(=wrd_ZOk( z)2OGfW1bUZHJ(HpaiU^?v-=F@7LA18{!!H7V`B?G-Hg@9di-p8GG_*Od=5M^JIl7R z{6}!!3Vis_B5v=#^Lt14VD8IvDBqdz`Tz2HN%w*BQ7`>9&MU`dmmUX?6z(5!Xy*O2 z2aNN%c8Bdr3bFjyerTQ5J?A6oG25l|z@(eHeF4YEP`_E<`YOhF`3EF58zDzoWm20J zJNgsMgUE`lr7MzIeTaqIi+uFqKFZH|Je0p3vd?&Y#`ot|41Z|>Y^8l*vb7h#gXP2T zpNn}o^IV)*e^2{ksrysNA7Vwl1YWh36SGUvUsuI>21k&uAA9uWubXm z|0?Gx`7&pG+;LUO>|@x!e)k85ogIdGEa0zmZ#ZA546-Ie4vtPeo`S5&OOK<>AA^jH zRZ2NoM`t9%@8>;~oq43Z8_P$$MElr$X?7`NWL6@+@c+QRZpHZ7<1u&S6&$~c`onzW zWixXbSVz>4zf^soovMw7^XnFvc$Nz%qu#=vp2JV=lJ%e!>7K!}2{Bpcd>VD=Q|reK zs~h@(b-l2irYj11d<^$dR@yG-?CnH++*6ph$7fw#Qt?}5(AV8)PmbXpwu4_moAT_y zT4(0LZN%{ev)!3&+)TgN3MU!r^qr)HNPMOw7& zid8Q_(&UW)YZD(}v=Fvf~NOzlkc20yG2SCp`8+>-)Suq)7xURk>i0}Cv z>|J9Hr^-%VwF_~Ewcb-dR=2Eklz$WKSDv4fJsSQ0@+SuUub8kt3n?B2G>+C6A=f#0c~LqF!r(X{S58oFKBeb zzXQJe@eN2I1kdONW#&D1R>BlhFjo&L`1s^c-Uu6c8enT z(gg)4}q}v;z{~rB2IGWeBx2#&z+6*smILPPcZQ&3;=ZJvY(G2H&c=`JXf8ytVQypUv(gRDkV^v*4O9$sS2n`+T1t}qoYL{Ap3k$1bbx~5duezbl2`e!s3mGe2t}b(V!5}=Q3%L0T`Eg46unhK9 z#r@BgW8%K;^}vk=A0o%x;bX;Zq(4uNxy#6Lh~s_7Z6Ursg6p^=>DgB6HWcUFh+E$u z9q%M=+m*DTxBVD8{!jX0o~8SLz|dQtohKsrF@xK5r$~Dc%CpemRVH2QlRm=W>XRP& zE~)Q1`P*^~eb1GZ`k0e`q=MM1FL~$#)hBX>=^hh2q_@7_rmMzHT4r(~pRw}14f$A~ zZY$?(p{M+#jQk4?ev!djBm5sW^y=5h+YT9={h9eqd|g8MD+LebA0>FGXX}e?efn;U z@Lv+)-)i_$`31?@>c<@skF}yK;V;A}%P*uayUV7j7e-%2UJM z1P}G8KFgs#(HE8HW9{J)gIjypZ*Xf5M-6V}94fDdp`42iZu!?5-11jn-7sJ3s~hHP zui<0!byV<>&ohFDe6EpKUdCOUVDzlMv|+huoHF9pPOJ~CwUgb#pY+xqtZ%Hvt?%l^ zMxNt_&qRaUIDe8wch$!Ev-l8kK%qQVZ#K@~C5Hb(Lw~8kt?#NWU+cSS%lBc!$L8x1 zgWG%!q7xi8%4yq~p@N6yTP1i{zW>pEMRjhg*M^T_rpHb{_+!(O=84(X$iscF*bUVK zRrd2gVwn<`<{L+TYZ86xx$a48w<$Pb5x&>^r{iAoL|=K)rs>;fGYK?(-KPbc#*1ca z6ZxkajE8!k?yonPCDpi#7UQwrr#Rn_1DP&y8_gl=d#yf9c1X;&E1de-&e7 zJ&(Sjua=jiziO=XEBikC49A}aBVH2L`txHYqq{aeR*rr`KgPrUGv5crSXk_XV*i{U z8)84&Yv}K1pKBIlUH*R3jOePwco*q7#+AmH6R&$dBf9Pdf6@%t;%PX>mBRXK9NXH| zz_fk*pe)9o{CJm%P4qfrvyH%58OL?lKkob5phvfMA_{C<$#I<{#p61=ur3nEH#T7$ zNBe3Sg8`|+MW=;#2} z;_Jm4bxN!H-HkL^uI$U?{tMWb>Tl+l24lL-#~2C6MCuR+isK^3MlZZOjlM+GD?fIG zu^Wz!j5qn>*vKEE-<4yauay`V!E?xsi*VdY`LG|G@$?|K8yC4B_p9xVG~*&az}Uh+ z$+*ZT(U1Fy_b1)Y%D70==)$;3}ra%>@o^2%VGBvYQ$WSs4hehlb2o;bE^ptHToFsX%%hSHXIOTXQn5Qs%~0 z{5>3}NXxiN7PN;jW`t*<8&~Oto;QEc=pN%Kw)|8VM_(z7r`(Tw=3+dBV{FCaDZWk6 z{(X+8q%odSC*vtQN{**o)U~~6JY}RCPg#gD9@gzcsZ!%9BY)}RDZ4P9Lpv-pw#@OA zHPD-mr+fyV^tYJtltY&l^k~OZ*j95q<&9uGWdp`j7EbcxDTt|(A5W>g{O!k6v|Loz zbI(oIj)1;%k+GCr7$4%eRLYH|%yeTZh->1;30XJM2EOfBO88vJiBAIFjoi2j$B%p) zGool*C5y42+>GSZbFOarwx8oG6R#}Rm(}%8z>9e*jIWHD?0K`@^>s3pA73e8d@g+K zocBJyLj7S4JQ-g>K4g5Q_vG2`O>PWJo=q5E*@f{bj<3ueldL_6dX>#TXGWr~Ux>Os zs^~eBgFk|{>HWuG#;k-sYd3!=yY$=OSv&@#&%Z)Gxdy1Vm&Y(p#W9$@!1O((@z-N8 ziEixIvtuyYr!^b6?MqYo#Swg21kXh9l@a{T2!3w_|NRL5jR^ik1V0+VUyb0gHNW`n zNPVgv`{dnuD)3VJye@)&I)ZPE;24ZA$^T2hDbJ14_oDLrX@vfJ5&Rz_cx+6i9QiJl zUv$3vj|I21lp7fdFZoRV^BQ5n!o)@Dyz2#6!poX^}`+#`)m_lapCO;$*9Ru+q=Lbz7z8w%L z6vHoZL)jU0vrF)hkBzTm)8!g>+{k~FKXm^uM))6( z@E?R13U1_M`y_8PxV6uW!L5DT_&2uCw!_d{9Pe29bS<7Uxb52<#Ev{{l+%u(Tw`z> zAEim~P|qs_5B0p>@UeQ%8r;^42MliO#Ulo{a@sgFR?e|z?7;G$WN^#BRq!xh8s8<% z*Ji`V=1a#oLOy$iKIEfg85|3+V;rNT13k2#TMcgQXN|$F{iv@4`B;0{Z0IfC8Nv4( z+>Rw3F?h;ZlK<1Ok5CVNLLchkWy8nnv&xJ?j5quz8GM4lb!>(CwdHQdR&2S$XU%P- zxB2Qcc*^h}YQ_$1d#mw0!u*aE`Y^x$(Z>j;Xs58~Myh9CQ>>%J(s{%m43a`YACKGE zmkibS>tnuDaA~$2E&p1BboByx*lh|8ls==&w39~12o5+u;Q{C){-eeC!8iCDNxJ9uvg9gc+x5>L zLOk*L=-=D^{zAVq`x)NcaM1bQUxs@RBcuz!oANXgNpPs5qHe%iQW%}**z_6Fr_t;rlvH<2pbJgoXZwVsQezkb2=lKG%gl zgJK>5Uf@x$_v&!IB&T9k@Wr zyLayY(lZm;)KZo6svx=-UGkEdB89REKe z|9gG6$C!7?P1Dtjv3L8dywASZcYEy<>yrdoXQ&H(P1gP}VtA+Rw>`uUK5UBufrHaz zU3-09bNyZUm;3zO^Q+8?ikNMVH5T2viqmJzoLT)Y-|g41kY!7|eH#4%=O$$xSjVh# zTyf4W( zZ~fNA75RC8^&iB%WV}P?K9gX6GUk+j8~GW6{Q>MN=U<+CJn6}O4|&CyIu(vZcz0Ud4T1GH6!AF!~Nv zb&bdT&&>0F?k(z6H?QX^(zEIn> zP*pBZq-%za3>-y&sEfMjlahtc6zS9FrLTHV@}QjGN}eqIsGK~P!WIS_d2pYTXTHia z!pW0h+}!)la2~q%&&pu_eh#|m9h}T;nCi>W&r=uQvJ*ay?BMiOz0m0n*y2Ixi?-Jb zol-v9UoZ6v`|G7%#r~kPBHL?(T+|o&C-k3yPBX7a`sW~h=$~a@l>W;qbHRVC_utOe zG>nA(VtzK}doSGpJ4&-YV4b-%>jTy=OtU`x9`-}Ae=zCcT5a>H(mgvWoIMRI(ks@^ zq|a8~Mj_`PDNp!kIi6TY(eeDO@Wi@~xsAfp&owXRxiRT^7(5zWSrqi$cjD~Kn}E{? zDi?g!<6+{rGGR@AY}%oPGM% ziT&bQG92}`(#J7K!5*Cbj7ED>p1z7Yq>gfE5140HwrCSvzR@O7mpjl7{r~K}4VabH zbua$TnGpz*1Ys0J8V*PznHb98pkTb0!unie9h zH1%H20H#1~LmNyXwRKdQ(!|_aVvRS=zZnr56HQB^iHs5F{(gI}bMtyMOO`*Z%%md+oKe(k>L_FWUsI5AdJ5bPTf(uP=YpDH&U~d%}AeZ%4!P4886j zY+%e90sQQyuO4_j30X>Mw1em0I(;|T6M*Py`|rV419dgC$n!I3Q=w1i+6d|w4qWcr z)%5bz0M3nDnSxHv<&!fj`Ht;KA261;t8u4$0p9hOmOvLq>H)sXLJx=GRvo$Y@@QZK z@ZW=O-O&Zycb(JKbZwB=!x3FA=w2r2M`?8QE3ol#C&JnQ-6#5$!jFCrT+X)P;(~qZ zXE%M#wO8qtI2RG$qRo8h_o2hYxIT`3`(gOW?>WI4e)8qFjMtFxuSEFq?z>3Wz0|`3 zPfZJAR!8w=?pH@TXQB6+9-SIco!EiWvI=jHC2_D9x<~YH(&$tt&w|A`z{$fJmuFT^ zf!+-Fb!Q}<(N>Q^I=<;1?DVkt2OK|?izgrhD_fD*W1{SZ`jlyu6Hhav^GBdbquzUW zN#}aFPvINN)QGV!O}##Nn9l&VzmE9oK6G!V!MACyZxz0(_cj0K%u4Q|r(PlY7?-Zl zxBD^s@3PBMuchD@27V7c2cBC&I|cG28{Zqzr%_jQH*`c%IBNE-L_UGnok$m+^Vo}b z?9;MW`SABa2eJ-f(Ed0JJ*Z==XL&EBj+EWeVTl|^6fwx zx{q_mMV+|U__ov6DcGQ>nET$S6Y};NzVE~Pxx-<90(xC&A6(hz-gniBL|v=skIq~@ zbv43)c+Q86(8f{IQtuZ-mvIa9ytFUT`<)1TJ>teQ6j|PMJkU4b`tUKd)e-5w`BACQ zPnr?^82ZIEOb_nK*ES&w`#Vp7wpdts24pe(?}6|8xDWqh2>*R>YdQDjII3XzrtYC{ zUwpaO@=o2teWLpvmh-L9VPrX{os9pNay}KZMXfvMTF%R07p7P_*Szp!$N2Ki`oKKh zi#p75UJqIEv#9f0)?uq7SJu-gzk5+mlTzOIftKYxjQ0vD^HEuJ^CZ~d!TAsr4{VDhId!Y8*S@5bud)6m;Rd2_ahP~Lo-%l_b-I4{+YNmvd&p2XS6zHa!oHB$;5 zLD-97`0qsB_-Ewl1!!l=(61HaOP$AJIPI1c!^v+d^qg5<{ua-ycj>aQ-d#GR-t}Yr zrDe55^rYG4pOQK}ymd7U}?$J)P=}T$q@H zmtc?Pq1|}5d!4tB!uI0qriXL$5VqxP4`013LK{l+rNXjkS^E0&&8R%u6?KO=hzCq8%*TOd~C zY~4uc=F_g%u@w4H)cs!5&wUv*ehkL**1c_}zKf&7lMxQxAHcS~Y(Cre2?tqzPb06A zpW^&!_BFH>*843#ws`dH;CR?hH_KbXP1r4Q#+ z{~^ZKVPBG6n>t#8x=wpr$48+*L^|WQBU)TnP}ip*-|I^Kc=F-rptFo~pxqeyE*VSy z7VaZ3PsKPr`@5;5^9$ywi3*O}drL-K!!U9jdpXkbB+~Z%IER^G9WG zcB2n3+p>?rJr3hA#|P!3|3`yWEGs@O*cNlFd)dLCyfJuR^sj@nNK2bEXE){Rr;ZD? zjHTR)RH^Zm{0C)*<(&uP7cTxokL#`^4+sCPeqy7o&K=jtf?wqp}gucf75 z%CeqwOyg zYEG%2h!@)lEnlqn7&AU}>?-gEuJwK{c=n^N9YJ~5a$U#y9OuKRcS+8NQSXwR52M~W z`H<8*HwU(JbksYBFN?Zo=W-mA`T6HKnSWm5=AT!=?~U+_;}YLT70Q2D_ZZf~y65}7 zKFmR>pT7s?Uu}HN20x~gtCMUWv3IOkdA%OxH3PYY>!;D?Q6Bc}s~9ste$dN1@a!pSF44hGPW#ga7mz`c#ykd1&wbSd=mcUmn;`^BcA)EJIJ9 zxbF+vciX<7^|BXze@WkD*f{fX&D#F|%pm%ImOGVW`TPGt`_b##51nJ`J#G%=+Yf}t zwZZIHqlr_>uUvJ@QegkCm&$Y-qD5UT4ar;DH?*z2qB~i=biu02E0Zf%&3lIy!!fo* z*Y@v!jyTnp5}5qyRW1+Ib0V(pg@Uu;BEDMOs!xBd;A$hGRai2^NIzQi&Q#yDUhp%r zD4{sn7F(OYoiC!HYxZ2bB>(g;@i-;@k0CQE>6mcPrJyw9~7LfVz#-w zzoOLTKXLz$;=d%y;~nN*X{0L)2E=1&G_nv7SE*Z#D17x4oTCdN=XyQ{|49sfHU_@{ z`BRMl#2EaF7(7lVU{(x0*JO+N3p<5H@f9(6eGLBT7<_vS&NbO$;h|1MG5oJ%@UO+- zar;HS7eoJp82sfJd`zNvINuk8PmjT`jlpk@!JA|7-;BYtF*w%-i>31uF*xSQMd=4( z@bReM#rV&P!I#J2>tgUs4E|fdsax}uG@#NvMZ03?bBl*gi3a@&R}x`)tEDGW2km`z zH|Lz(Vbip+!+prDF7>S~Z7`*_Hb>C00Z;?B#WZx?-jQb`a8sLyr#3nc`n4SDZOHwh z?L*lJu6)>0cC2gYu5Es5wVWk2F{;+s zavM3*R2pt#uZ>%eyR?FPTp;P=PiI^H3FOMlGJ7wn4x9WT;bT*qs~?LL&Op||*v7~JlYn&`c9|JR{? z=0*P2<`~=gV)$sZlZxB@Bi1Gx<|?^syP>!I4;kFjTN`W19G57{h^`02Y4L0f-fwUl zPJ3Ro4bLta!iN0qImSBXX0ZB%p1NBW?>BrVoAB$9l>9Aj_uW`r&l4v76vJns3~h;D zZt!IWpK9>c27kZ7TLllpe}|#B;dwBI9_u{r3gh)u4E~bAZM-6xhlJtLbAZYJ119{{ zLQkDKoBlO1e3}I(pDPTXod%y~@O^@Z{MFW37|tVxj}7PX7~I-G`=Ign1w(J!AGM7Z zhUc`jJrLj_d^EXWx`|A z|0RQK+s@A>%Dj}}`LN-0rQl(Bt~2yDJPQqO+rwoBw|aG-H2AL?f7ON;!!yI+cNlux zKHKwtZM$^b&{rBh{RW?D@RtM+<9nq{Wf>lukFy02%g=R!hkU9HADeD>7~JO9Ju&>Z z$MDY@J~o_(V(?=I|DZ{SCk<}v%QFVI<^NO+e%jzRJg*BLrkg5chv_!{LLa!WzElYw z(l0jjHk}&D*)RD-Hd2gWGz#%iy-2?l-utr-uw~>nYZh+{JL(dOBX@Q`EJ- z#)N00;9+@43Ld6gN^tU@Z1~g|-12WVxTSyC;I{l9H@GeTPa52o|L?}&F9;sS>m|X% zc%3$UY(9>n;1X9@{-+5Z@~JlT1?Au1AMz~Se~-Zn%B{g|d}oWIKf`mS;ZrTR)-M?@ zMm2&noGcoO>$%inITgr${M`F^1sdCw*1eQK{@H|IA@{3|GQ`D{%Z_w^RdU^w*GE6 zxUCnv3~uYieuLY3ame5^On6j2$nqmaz`cD&=$T&@*H24;lSGCMxfKWEoKow$id2_K zab1Vex}dnOha|-V#dZBe%aY=&g-+u_JS7-!nny~nuTt`$xJ2_!&w%f0YOR|-aqJuD&j@+1`NpzKT*Mpl7BY*AbB_fNq_r2zIC;L^?bo%h ztdqsUul8*_^h3Fa{MgqOOTTGSAfJ)%n0~|X)9*F?76YUIGx4+6E=j*B7R0lrpWZ(% zn3jJf|Ehd%+XTMT@ARHF7~kvl!a3$2+k`Oh91ms;t}y-7U;oyJC(Jv(Q~y<7#Nij^ znPK{IT3FP7X(ZLwGRWK&`p@NpwM}j3yjQBK>Z+MZcb&T(gzYj`V*pYv6lw?IA*Z8P zHiG(sB?ojr)7GlgfZN9e`?ZbGi>JPr(;F_0(^L3{({qAd<%+r2MV-r_TTzC6_(&J0 zJASgXtYY$LuTKlzkCh0*PU_Ww=fMH!b)A7uATjC{^^J-S^I3H#sGF_NRu7PRMv5md z#2zH*6@PkobkQd^myAt~gc~|58R!s^S9(G;fDYnt8hYh9?2>38{Vrh8E6HK+!+w_$ zz@TH2!=_Nb1{m~Ba@Yr=0oau}oaP=O^`inhm^c?O4Ly_`HXS-~#NaQ_1d9+B$T1K1 zU6MKqThB;`_s#6P1o}7#!}HL;p{{EwehIvT4jYF>J5$(aa0lM=`J{_8byU0#V!AY{ zB3=*v)Oq24Ak}5*EA??#8_PVC4g>NrlMa>m^Ud%bZ0TGCz1)g<@K5!M`e0{upmbsd z?a7ii#yOD8O4n#RQuy1-TG&n`GX z|9BqjCeZRZA75{qw;yMy5-%3tq}XTG_-=u&xyE-gpYh#Cio`bsd)5QcTjtq$Q-ZLk zp_`=PN<(L!&vkc}9$;Bxde{B74|5Va!W#?n$nV#opDFCW**GLVUN@2Zvb?U6*E>?( z=&bC=N@BlGHUS+k=*MQcw+;J~vfP6OUD+)6V9EZZUX-VY_Bvh2A^Vf+?wo(X`*E=^ zf6(WrPE|eXM|ODXniO=%9>RX9bJdO`h7uQN&x zwDFpMmxYd^3j@-Oaby^{hc87vw!NZ1iv4>j?(35Mdv0GB_V^76!e3dJMh5A=dzA-qCde79M)ONSw9nxEZzpiilkI-GB-^Fx=JU*PaAy+XSA9fSg zj)$(@a11bd2nR2JErxUcS`6n{qZqy_2LD71ULS*hDhA&ggWny4?~1|yCG8OJ`A$X!8b2xWtQ*M^hILovU5fbUT-(hpgu7Dn6Ef<1`lJ zT)Kw#4!262W7*Nwvc5^yyKk#&-Oz*s&ziW7OpOJ4M9qfvbzQmh>D*d47WG{qirGhP z@8BtH`pFH8mM@rJ+W@@+G8L@@QG*cO2nIPkf(~hu#*Y{0nj91B)hG{~Yg&Ax;GA2J zRASukG5CcBXZhhpdXBsG%E|+A5$8GN!5I8V41O#IKV@(;v_8d8zZhDR!!!uq3 ziTnMAk4?`94Q|u(u)%G59yhp6&nFFT)AJ>R+w?@|l}k4pFFlVgOy_Ba-o`8L+_`E) zZ{wRbxQ(x#Q%8R-{T(s%I}LuRN$1lBx9PLGEFWJh^XrMhpE9`RV{M~Sj-uB~hTh8R z{3Ml{vTBEO`8Zk9b)sWJ9`+&+dtC_!c}lkD zUY+armH2`@XXd{25Bj}r3;0I;*LzB^8GLE3>m~ft4aP_PPVY+$W=VU_G5)M8Vcf}Q zhIB5sSf+SZe-)-%nh1s5eWUoV_G_39%)>DMh!yo;2&wCBufXYsN3AXOLuE0rJPBJh zGt9rUTQh6s?Ahlli`j1)l#~lh3S)$KF)g+yBgh}H$HUsIL3_JBjX7XiRAFu?Sgd8XR9>?o&gn82D_e29*FbC@y84c9oJ#8Y8 zCW*Nd_jBfL-~82qJ+Swv_8KTBLOZnm_pyhP@)>781^b=Jlm2C}5A_u2xi_49x8|9> z)bu02SM+fwH%eTbIZ*;X`8|JWgy$jb)zbNJ8nzP3#(I8_l?~+wnbHY<$NjMz5GTeF z1jl4 zfc!I2G>hTN!p05fpX6IIF*UFSdzW(Q4!a? zIacl&@`Kzn%24hZbMf3WWCOWp$O3ZD)6Mg8^SshL-)U%l#t< zrcTEGb;Nrz!q0TjG|9!kEb8q4_U;L4pY-|CvV*4}cYF@=fRm^zwDTe9jH8QOn&s{# z*o#^R`Qh13M-G(qVLzhyK^ZA+hER6e3!6_R{Ww?ZS8MSNfLL+Zc0+Pe+2h* z$qv??UhLUJ{+!@`%gdW@KQlQQ?U>sa{kQ>gkOs&==0~L$&Ku+&vgjb|*-n(%)UxOz z*l{>mk8_ivj$h%F+1bMAld`=PIAtKNzCqT?_b4l_9&-=4?n^zp>A0(NXbxO3O9AUtiZ6Gr&bs#$|I*>s*&7uxbKKND0Dvx}&xFK-!qEc)>l?D?mR=e8T8fvD$K#;{%_;SX(+@Xmb0w^TGvcHlJg zWc!-rijJl>s2e9Mr_Y!^vpt!dc}?=Bx~}BR8I`khZF9prB(Euf-@i<<8s9|@?Pxt7 zj&%IEv;;BGOZ!5)i^+C8ZmIN3(hrppO~Gp`3mPTla|Bnnjy0-*j}{txLp$U6=$gHT zphNJ5LcCh;n{hA3=W{}TztG*o48%ouF?u#$#qc9B_#-iRoDApNG4%fugP)DTM|EbX5FZ@@-&FccBW3hCe5Q9$!eo>UKkJCJx z$TUP#H%8br)Y!D9ZbNHNEyZbWw+|mE+R_&U+Z)}E3T{s-0vBww@M1Yg#`2#zL78_h zT7JWl<%?>~7AT0{l(ulIO`$ArebaidiR62?%Sg!G<{7~mKmQ=P zpL}bbe|}$pt2`s5*LoGwPZduntFW>(Ew3T{l|mol9fr>sdFJhqJTp9Y{>cFD-(ik_#7_NN9P`Ia4RdavPsK7W#~0+$%sabc+uZW z{iFMD7CekskD<5x?=ZMcx2*=ZGM?`m{4(S3Xldse9?K_ba4iG;>`K9@FKcCTy1yvQ zuawY-@%p6Uk2yl_vNA;*9*jlZ#c;^$rYc3$1A^CU?rAouYypw{!N*rw7S9q(vaijz@R z<%cQ-oXNvp%nS0AVv&0_TfSHS^hM~d#0&D2YNTY5em^aT_=oU&&L8;w%z!Q}{@cEU zBpQCbFBWV@@cpgw{qz9W@AQ7N;b}>AKcdC>tlueq5gx*{RBUU*HQ|u-RE~h5l3Tp}S>mPT}mWY;#v#Q#tdzWt?Upl5(L@ zeY3APeX}q2q>fT%@(RvMr#u8Q#0ttneg-)VWh$?hUU2X=$Yx-d^xzjuW?cQn5vhT% zU6~rd*{Fy6AfJR>1h#dC>Y|<9^mQlOc;xFPom-%Tw)^u@XKHxfhUvZwA=`p%q!)Ix zGLS)7U9>E0D`g?Ofy}W2LEcHbN?F)ZD}g-ZQOI7A=T63U4ECP(;CtG&zN$QR^eV_E z8zJA+_jlr*@+TkKZ|j9$k3jy@yAC$bpr=z(2Huw^c2EYyvz`yrR#QXCj;}0*tOVaM zez0$QLUp;$z#UDCZiWnU-Gzvk`n3=`b_w`L`r=) z`$XQaK&F&Me9DjxDxal|;@-OwJAMZFO>)#_XBZaJPDQxAUJvbvQMb(7O+$aw`6mbm zb!?KbXY2fYd9bDgey9vc@4pY;5Tu=;z8};3r??l|9vkLt(*6wj%`))Q(&4TQFwV3= zHh?nm8p_G*rDgDc_`wH|jtm>*brqDY&5g#oGthHs0y~x`ktUOI))4cUwDcEanDR;A zDCvZb;=xzP?Vj*G*aduc`0fdViIQ8>(2eW;NNT{x_hQHcy-g>^^TTgIckGVTy^L$7 zl;vY+x%+wdBFM_UttQIr8<6g_ySW!-=;U}G2B!O7*tW|c?WbPqZEb!VX;FJGYw&oaIQ9%UpS-Ejxzyn+Wfu%_W`Dh?Spy7V*j?QgbGa zjyjQEHJM>}PWf}fw~UN-{ETY?WvK&wkn=@}%n8Pi@kFAPC*W4QY3aeis$-BdGhPXl z_3t3uOv`x)>!j_l!G_`Von@I5)N#~&?}JX?zKPzRY43u>j-SKs6>ZT+C<|4iCY@ov zaP0v4cZc^ZfE+w=+1<5K$%~T_PSVf4$J3mWc&$fVV9RkG{p`JgwgN9ZxDWbp>L262 zuN(I7khe}R4m4YkZ}caNXLsKOeKN@5r@k*A7gUP!EM%Ec8P-rl?mnp;c6Je`#!23; zuX~SnAObJgZ(fH6yoPCUD(TO?XZf;urRx^GuoI@?(|ZTf?q{+#L4GN;X}tFigB>%R ziADRNS@?Yn@@)EX66+|mH1=XG=#Szu(33SDx!v8r~rREtsoNG#G5Dz%{NG}5$|8!TTbzt`9O#)2+hy#z41C>XDg%UsP6mY`SD;4|p(f%{C>dj5{IyZ;oP!RNXWs6RXU;(_zEg0{K}X6nZ!BNDh;!Vm z7t0Z^kbj>;z3j^J|E}O6eSZx7X~DzrOhq_&5%+D3cUu{i)&EodxzOKb!Y53JR>4Dh z)vF8XGbTJ%miC~*Z8(n^oNbt1FBsg`lhX#5X^{J5v9xzg2OD3NIfdcJILuvP_7A+ThmT!v?pq&pyFJe_x29A7x}DR;FTQ zFgCwd8+z++kHKwz-C=N>U-t+ehI5~xzr-hr`|mTjmBl_0!^i5Y*?fG-@X>iLJvd`< z8-87uVZPY#kCJwn_@ySCqYZ9lvEvPHWwA2^57R+ye3Jh}!#`vA*z|u!aLV2=|Hxm{ zyKi6LQ&$g}S5KF}H|x`z?eYADZ|0N`CUHlQ3))`3O7RcZcO_olb?!2*YRPoXSBfm? z&j?|pdH(^yrFzI)q`7UZbLdbR&6RjZo^SX2N_@+3aolAu_22d}d{0_ldQZvo41(sm zLc;%6GO8u`MtPafqmQ0r{8=Z$xRcLfY0Pi2Oz|B0MYlAG1(a&rN@elPPUc~lf5eLU zKaDSNO$j^rbf@svLmKl9A%?QFoe-DkKuc7yWgKkngYJqzJULZ;)-jPW{P z)W0GPZPGKm1Gw`Hr+%c1>IA-wd83!*UEt(6JP(g)bO!TErjz$$>^jOv`r!}fwp$Tz z%4#@&E`gjXgFESp$yoFZrQ7ix(>CGcT7FNZ%CsmCdk!)P#{ETvk^2W#rsK~9$j23W z6E*Y~axLUj;Xbi`rrTX5I}%QQ0C|PTA}Fs&zcF|?!TEJG-p#K$Z$F7RYF?*HqAJFX zyr*LBPI*aT-26T~&eg91&Fi?k=>p3;3dRi!7F?U0wydSCuB$x>NAl|FGd~OssH>+} zR(_C<>6KK7y1EiSq*d(2I`v;^?mSHz2^Q9Zv4EsNDh6j;T8#eVF?dr9&N)jlKK~;I z=UkX`Lk+i%<^Mc}{%>ONe~Q6R#^CwJGiN}T;{IAUuUoO8W>HP;s+yIs@#^NBLs36j z#iXrJeWXC+!Oc+5XDTW>5t#WE35T247MkegjC5$wWV-5J_&E5fC{iMd7P|kTWA$o- z+kX3#f`@a2M#00e-yMdJ9eZbE=noruJNMB!W;myK#n9V12xSkvNN?w2Ru96KOVxKG zy^Sy0C3l7KZ5BL?Z$@zPDTr?j{UJkdua2qcjc+g)PukkV+P;f|FVqLb?)qQ|J=vwXJm}OTGE9>H)fd*o8D@yj!v@Z zMIQEw8>^q|_ixH|%OCU9>L+=l}G zeStd}gzt3lJ{$1s3&KAm_&yc5s{?mBaCZdmLxF$W1OK9th3WTX@IDoUzc1kTWZ>=( z+@}M6r-S#|;QiQa3=$I6vTf<@IDo|(?R??0{8ZSUp8KuqJS?4cyIv`_{m{E^xO7?)8DYEpTrQ z-0guI>vRR-{bJzm2;3OU7SMktaBm9SzZtl<2kva({@uWhIZ}atXrv3=y@C6#zB>;Qp<^-5t1l0ykt>1>xTtxbF+xw*~H9fqP%z zejsrFLE!#E;QqtFeQ)6YRNxMpkEpJ7ZF^TsPxJcZ`j+nXbv+HuQGH!wvMK4zp19{V zEgPE}lg&6(rKu~aC()1yN0TJ$Z|`YJHsD0H9!JahdR@+Pjjl{gQO+ zw2n!R)V%|j4Xqox^PeGpFu0PVbk2Z_TLw-xwm118`vmce!%1?lZ&~ZUz|fI?M~&+{ zDqZAoM#|c*4LFMiWJ&C-S>IV4N6IoS3dk#?H7#A;*hbjU)6|oMDVe%ftXa3Twl=M; zYfU1S8``=zbab?L^&lVQJQ$`?QzW!WAHu-NBwULle3Z!NV9tr)*SGX^=iIGz^{~CE z#Os^7yX)3Ag*?`;T~nD{kHGmrCfneXR3`Qj?BrWMCbYrm(XB04Xt%U5?;!UBk~0g zC*ma6v~+YQneDQNwe$3#Bqk#5T~T`nZ5m)k&^lVl_rQ-iejidg@ck**uCmoyY!}vCaABD@4w_$mB?}zz6%H3mzf;Z&%;D zyIXI&D%sWE+FD;SngeM%*0r^N3TdD* zL;>8;=COSH<>IWcR0wshuj^i?MME)7o`UaKBy->9BAXPQ73PbO=ij+{lk9Ha(ACg{ zVC7#pPjlfL`YKm#3SQ+}Q16p#hS@f|a`dS#G&5-Mq>8pmYv?jvOxjwdN<&x`fiEdhS(~6b1)Gk}GU}>~s*+M1!Sna|^3sx*#6jd)> zbc+KQ)T~@q=%V;Fk3ipNdEO=5b6VlhAF;FXSsjhMEMe}Z{MU*}^uVzs!4#Qf7^dH6kyahwaJ#49S z#=q2i3t$tT3&N6`MK{$-R2f9bb#puG=)UQO>!E^_i=x@!$hXTsx@?(a!v~zJwy<{5 zYJV)31B%71;DrsYe=#(67Ps_L+-td!@l8$<8*(OB{(v#Qs$~b@qG0*?O`z4QR>i-0 zvkzINa9A2sXed|ra_F&UF^7bm>#=FRp!skQiE{XIXxJ@9k{Mlx@dZ9xxmu`V_9WfRst<*U;iUcdUbFW&(q6$NE-jBj{49C?&s*N^np~zAQX^dWxCZ0%#<7p4`rDAT zuGxZ9kIJqUY08!Wr+oWwB#V{5;!g`cP53DOoZ!k|@t+8;`J(t6g0BwvjFHGS2Y6EO zjR8JW@NEH}5`0&HR|~#Bz}E_XB)~r<`0)V$ZNZ-j@Lhtx5a9a-KNH}6f{#GD^V0Nr zMsQu5RQ%rr*R^oPhl$yd*#Vz%f-es64+*YooXQ7wo!zBtnTjtJd}F}p6M}CG@D{;$ z1$dX>`vd$g!H)#^{emA4@P`C{CcwWb_zMC4yx?a7{58Q<|6b#J@d%#|x>lfX^d>Zw&CK1m70mFABaZz(;VA3fKMsuMqr5 zfG-jJcz`zx{!D;x5&VS!-zE5&0N*3{2w6DOboi3s;{*J0!KVfIw*^-{W99RG!50Vg zuL`dE$4WnpjUTS&fc{d!HwL(#S+^~~KO*$I0(`mP`vd&rf*%R+F2Ron_-6!vCcwWS z_zMC4CBb!dK;!FUi~aS|FDs7qKX*+F@JWKt4)EE6FAngfg0Bv6U5jlFaLDW3wK2f& z5`0^LL;mZoT><`};QIsoxZpW2N414Dk00zAeD#2)--8mkGWlku z@Qnek?ZvhL|9hd|72y9Y`2GO@iQq>9e7Ka?;{iTF@Mi-2YQbL!@D+le32?RPFha%! zn*P5j^y33OEBLek|5L%=hAtOR+~Q&f&(xZZ)tI_}zmv71D2aBQO_&r*Y1LH+2KxLt z#6L(j<DEu4EQe30fg2VRLM@_f7B zQ^A=$hXA#lw$NSgO^|;gjnc~*laUuLW8J{Sw z@z?uD@q*8s@7oK?;qIDlK|JesdjEBUS<**zpku)zw3KgzX~$1Grtm+Cbll=ydH=0j zx(J2by-)nlNI;p4)cFk4kHghs{->n;wK{J3KaIB{)Gg~+S9#95Wmi?rK5yMJJ-3*C zrkuyR59F`hJ`i^<*4Su(=f+IIK91U`bRG6h)?}bZ*7&Zx-H*qh=f4F%u)y-W*j*h< zo3-A?G3*!|ylPZ*b9bV2DecF0!ydvbrKJ_Sr$)1%g`I&!Sv2P)^ws)H%MOwU>7nU* zH*5f7pFQ>rltnvsH($je>&_&;r%eFrzdc`CQc;KfAZq(}ZdA6e7yJI_fqs6Jno|qA zw^@W2`QYrAoPzz5`3NWWCyXh<-V4TqJl&oPv9U|rtPN$+&D_JVIZ?XqMewULJoaIq z#T0x?8z@ug$Lpn?{dkXkJ+mgm-_7rfI-fA~jj&~L68=61dJPBnemn;3pMmk4?qShI z&*Pc*?r7}N&4~-veG~pFJ@-=VLAXzV2I*A6Fw>6m*-a1U^9g%%UcD?Dc-7>U4aZd2 zkY+yh;-~SB5J$B~{pw}RuVc=J4EK7>$GgeMGuS4nsESILKJo$N74n05r8XWgx9I#4 zY~8+$JW3}nUOFi%U-!p|JNL}MjtKH@+(For$mJX3I2n9(PmTNj=dhIvI~^(5*+Bev z&=&RCO@Db{E_m1NPkmbV*l>Rh_a$*(&4sX&!96!PI}Q7560nt1Qo%59M*gFD+y3B4 z*uR+;b*{(#DeOmi3^qk*KN#i9rJXxV4LXvv8C*8O+asB5$^*+s@qIXdP{AMO>&(y>cnNBKt7p&KtR9gBM@;(h6j5qKu4DAf%HCH8Yo@|(2FB7mPNEz=ggjyz(dLe}Qw{Ij z_8r$3{4&YVk)LSGWq?M9xr*5vrd-#`xc3SDhj3SUv0)L-iNRAb_zl3xU-{B@1Ftps z5m#B=GY*ZSyKpb&@9zkGMmjpQ?e6-M82Z1A!M_oMI~hGYvD|i?nB}?3V8;zsMQO0r z*iO(7hpddf)w18b}RhlM^2&l7@&>HJ;8 zpW|1(UN^W6=am>B@M1V^`AHevh7)^5bMzKR|B}PU_(%6Y!r*q;JznrI{BL89>CSKd zW!W!urNm2v6GgrVZ5X-$Nnr@;hZ3DPT3lIBmt1(slmaKo}Q<8lf%#Td(H{T zGn~`u_qJ@2x%#j7lwdRX(pcYu0aqEd@(%r?TdI^~b)FgLyD`3*_vw6c$UJgH z)Y)g|W1PR$gCG6nT#@7aspYBJTXBBye2mLCM~QX!;0zPq$ChM1zi|8wpMJu8Uxqm$ z=a4)PWNLHw?A@baqY&Zc{0HOhKdZyHWtj7!thsq>J!oyX?L6@B!GnHwM+rA?yb0gx zcc*0D_!wxk>@~bY<8+qo|4L)@e#D2@`|&F_R=z3*=Nb0J=obO!SiB#1UP)~X@);rK z(R55oMLE&wD%^j*GCzim9TCfiQ8d+iH^lCjj#-|?u%N{2-1lB*OrcFVk992d$brqURm-u)dNa=02irRwJ8{fZhdVxT<0d_K?dxU? zun^;``H&^kCiE$H4qGYYrDX^CO%mU~4E*e-zsmXJWbu%JLJyz@Hl@d$f(<0?=l8&` zXT@KB51T#}D%VvR{Ld&Ch8&l2Qk;)i@iJtm^I_wsM8BbdcbyeECT&;e z()yhmJh-&bH}hVbogSaQ7Q#dKx)=6vLQoauwK~0CkcUuy@}Ir$J*^RxyJ^N864&>t{9=Sune**?XB4k$ zxxP<>71#Hk>-TYeuYPaK5dG9(={+Ub48AniM}*+*_Ps6Yf#J!=5RU76laf(yx9{x` zkE-Qj2%Ay7U5@qz|Du}+V@t?Ie)t++0pqxq}-$Sy?>Tl^ZYXG`*B^6XJ>G2 z@C^Dkt`Bm3(Vw4CcJSxu_x9qf1h7EA=xyeuE;w_|!_SrM7>EAvtB)se?q}u%Z2O(q zow(%1b?BqvUO9!f@!wc|FV4o8lYOK5-t6~zUwrRF|AzaEC0yG(;cfnVJ1giftMnH!+8$VI%LkMETu&arOmyd@oV@;)k#nS5jJzbvXas-m7r#Xd;@$ zeqJ%#r|Ws9{_KUncWaW~#-IN_1v~eTCCbr{PdFHXFT=v~E*^q>0qgDuzvjjk59QMF zD#$Q&ef3PKKZ9ZbX~{H%{lbbpNWY(BZ1Q^P1r=XQL=TZ4*XVH`z>m3RKYr}iFYH5n zh!5L1Y1M6sVH{^vd@nI!-9E&n)r^rA4)lhvZWka8v3`1jYq49f4hvh7F73bAkUE;ic?S{v zz#P5&j>Lqe9P8X)I&5hsG4Ad=hetO*oS1mw{f}LDH^)H?2XyIoaO~BKe9XK&X?7ap zA)X%)^r;TjEsq(lTe}lxHat82W!5Pxa30E*WLaJj0yKR`;-%q=icU`+Nb20 z?K$KLZ8Y)>g71L;DcIBW=Zsu-(B&7x(N}in8iX5VBU*>Gf|{>9Ub4f}O~AT3&qW?b z-Y%Z$QcwE`Xs-mVmKVlD$AE?9rL1fI92=(lojJ_s1=i1hjCGKM zW#dz?@w|=aKz|H0%#+DdCUGwC7>48C(a}Rs;rxe3kxxVHWR{N0jj;>U_a9vPzKVME zb)?hd_?G4FB+o=aJ^CcdD0%Ni8JmJD^k!{s`YafU`g{&?8{p z|IxT%2c84ZEY8b0iFVA#^8#N6Mn$v!Xx#M&SY~Q*M#qCV>)Mx>i6}1@fOa_2#J3G- zBP;qxx_WWKl^M|X-jz9ebV2EkEY5*peL98mG8ANw%8Tm+J;<}fR#*?DbTQg__ct#HM^)H~aFew_hZsY|~%~YI| z(!e@{`HQAM)92W)czg=#{uhvrTTu7*G^4z_GMTusx7nB3V|Z7G@;YUmFUxgOmjBM- zcg#jRzH%YLbtl4CRyy&<`3T!q=wWP)5+fU;M8y=m+ZBz!ab7feB=)ZCsJmlJ1$yj} z|A6naIJ4#?@}Uko5)4zXD+fLuH9a?ij{OH@%O|Ll!?N=;xqk}x!Mmb=U|l)8spP=f z1<{T{oHIjSXE)6|fOk8nZfgstr)&J2LCK@&gnGVDH&URF^2w2G5BA_;KyU|zmLJc6N7UOR4iVU+cNyy zL_jtQZeH(2J`mq2_(Zu^0x!mAUJSlM_#7JM`A+pWf5xyIT)Mff-=xc3@p`HTwj1Nz z+ZG(>YfjnV^Fn8PWeHw!vwa@3ew7~G!W%K5Qg zPZ)ZekNpO>`S`lvVSLMFZXL!~*Bcm48{g}MKE#_1Zu8xqD?<5-Ub;UeOowBJkImmx z2DkZZ&+)M7e4WVa$=~7~2DjyEtHCE~AaQ?6@GyN&8G0MvmtyEQN_)=m*zj*PxJ{pX z3~tNGF@v+u&t3n?&kuP@;-&GC>{e&2j?s20pq!1ea=%<6B-_ebw>E z5#ixV{6^sScE694&8h#kuF_w|ftTJ>@;rl}xh6^Y->z)#rgMycoNO*7g_+|+dug~8 zqg$Fvh1|Vb{C`qjjs(g)WLopmvQI2bd%nl4%3YA96kLJREe$j@uT#<7TiPV9s;W9~ z9iv^Q15UZnsBG@5IXM95-qFO=fXbC9m*Y7hNu2qZo`Q26F|SUKft-u?OHu=A-Y296 zl8`U)oQ-3U6CoYE{tM1Ct;0Mp103E#ju&@M$k*K5n>3u`^G^8!?~p0DJLOt*Q&z}3 z&eJ%!8!~}Y6H>4BL+*t6^N*)qmU=CN=Sg^`oZwN&RWvNz_d;2L4G+Q#Ih~%Pq5AWX zy@9{V9Q6zmmD^Bnhw;96MC#}x!=lc~6EHu9{pQK|&Bes64)f(`bm}P5YZlXEs$K8H z-Vy6R`ILYU_e^{a;f|agXryIHbPd1V_h#R|FNGw@oS-a{ateld686pD+Zuk`h%;3* z?g{8E75IyMe6w$-BAoi|l;GRC-(CQD2G7-%bo=RGRUOKMy5WD7^B-~n<#7^a!1})l zVP|-G)(O9(?3M1!%Y#*$5Vrigak+QdpA1&f-;I?+$LD*Q>E9;~YW?EC}%J>`8qE}4HDtjdgp{0iy#Eb=46Gggr&aR0cD?lCT3 zUHs}1r>#cU%j(>vKad(o{b=xTx&q(xJ{{+@zBG6^F5Z1FB0Q)=K0IDdNSP4B+W$kO zFZk)cj$Hae_ND22XPCYPX=u{-g?N9m--ka4Z|Kj|i}U{M3H+)5Y++f*JU@824sq4= zOg=wY)p$w%`^U`pEF+9x67^{op8p%}l&7!_Z213m-HVpILJXekd~?h4e#%XQfQ9Sv z^Ox7cv|of9g%9%RWB~%{b4xeRJzbAePdAc!{f1WFIJ3vi*>Vm&+JBu*}{(BDSELw`3KKGxs=?D|qV9`dEm+s)8t-sAM8PRpErvB-4J zS0-~@($o6IXB3ZuD^4bJuHRP*&zS{Wqe#Cm$V;ImsfHsZ&oc;`>x6{=?aE}V`BB3* z=dWTcvr^R*a`)NNIlf()jQXFF_K)dsJ~A2TA-L;+zvccl-4t;8v#{;1LYcSHRh~I( z&P-}5pO3C`zmY4ZoX07QSw==l%!#?>W++0v+ieJx6-(%Od@==RmLVKsdMK=hn?#H2*p zvrHcmmYx5Ib$gDl5~k*I(T1l!{wW?fw|-K9+&sh-6xry- z;~i?(VC}lQ*{#bucQIq!1uv}eZ2w}Yoo$N`p?8brFp#VPg3Wmx>QOi!1rNisEr!pb7(Rz%_#BDh zqxsGB$>lj{pE7(bF0iu~%=qd&S<8C~_^=z&`Y~EQP`p{(;{$xQxRU{{eD%HZIWBam zfL@%@+ZfCJQrn4BS%Ahb9CF2t?R2bLjeOz7{NkggtL8)8dfP<#j^ElVgyY6`=lVVM zo5(X9A0@@34(mCdHT(*5Y{)c8DIj;X>$zXtj6aur^?Qx~^}y&=IJVp_{+HvOy##jO z5dSEC#AeW8u6;uIR%1)<6H}h%^9YL>MXwN!8(VhBc&aVn5`Is&3?B<9RR+>8AFwT8 zyBMY)$D3i^k&(__|C$bSh5oZu$DuPiw0!IJzS%RYFtEgR?)%`LF%5Leg(ZbH?_D^9 z^pIQcqpt4}=&I@-HSRIXUm_$dQbxECB0Y^%!us&65M|UB8>s; zd&^=CiM&v#Z=NtB!n&NdZFO5|Y7TA9O-_Di!qbV8TeDb)Ifn5kdG5jZle*`S8_(JV z9Z-I|1-95GVUHhms*hnD?C9XP_1CQF#pnV*>DD7lqVlD^o1>$%z;|xx#p~9=?}hO5 zMXmupp1eCcT|0Zy=|ras6L9)7HRmvdxssUNBpx3BCL;i zJ!h_QKJeb_4`ia~p?!GA^~tC4?Vbf(3z~?vE3VyKaFFSe8JX7?huo(I=L%Fsupbsh z6PCV)^!dbx`X=;4=NNkIBVS8Ib9y(Yjz(BRnmi)9`6TpgVL!O47VBCme9Lf^Vg2YN z!fey!Bgl(qL0d06xzCDDE^Rq5O>cz#GNkbiruhWeF1QqVo`oLwT<9({4Yq)A?KDWxif)G4%pE$t$rYT#mK)*m}Wz8mN4;um(QoVwBIF z*jtf=o;G#EpFm!mf_}F8@fgyA`vBT++Wso?ZT|bH zhtE9<-c}*k+EcK%w+}e?I%xUCSql7i-GwL*)c5`u@W#2t6^t|H9i8-_anSTe8(Kad zY5Et~525Mq^OHLNe%(Ed^>Ti*@r}WU=zsA&5MP&iY0HrRK8d|Ez0l21LN}l5%317d zQQoPugH@}_qFGNP-1PTprw=~v;Qfh9P&X&K`jvcruuADqVLkeC$A`M}`L*uo=YzAd z3EFv#IxmebT{;Ieb1sbjVJr3jZ@ryEww0M%=gfW(`THI01KRo6th>`AGGnenyfQzT zG@Iqo+3v%dwEC4kGg$Q<;H;~6M$z4+sC%qqOkcZ?<4V{EVY?I7`Ha;0FQ6Q79|+5E znUr6I$6eajG`vGIUiM|b$hoc`V~0Jak4v$+<$K&KQEc;M?w?}>JGaz6oG**n|MR$| zBI2)Nb5V|^?E36@84z$xrSky!+}-BK;LBt1PsZTQF?eST&bd~x@O(Z7r>*~D^k0g> z`(p5K#o*tG!T$v~(^Jz?!|-##r%C!AmVq13)=?UeD84UHOWDsXeCF zpKj{HiJxv#U;J<>Du#=u`B2^Ul`CsIHb80J9pH#X+qMnsYu(A3oRz!7NzLb~s9vZ| z9;nHmzbd?_i-%h2VQdQY$@7ZwI9W^1ILn)=v6|-vlu<-|0bZ09*mc!q9(K5|iymP4 z<;A%+$IE(k$OGs87FU@7`J16@Zf;H7=J$T#L!5P8uVeBM@_#7?e_im<-!ky!MSP5Z zbpNXb5BWF8;9CtJyWV8iXA9@L>5_|A#`tUT zdjzMyc0Dm0gZCNSu4g@EaGi(J<9@-z_`YuFt-m9r9bkAabs_hEs=Lm1Ay?<|s?pHf z^0`&;uzc#?nJ_%}8$Pyt9x}KspM3_m<@1FYe_s+j^jFs(!*E*Nc$@FK{>b#PWp14RXdGml5-fsq~&z7|L9Mg|&Oqh1$(;#Z|q%syY4SijVL1|a1^p*rw? zbpU(jm+D-f^L(5^ck?5d>p^+ACWASg)#c`#`dP@Az+z{F^;ey*s@*2)(bIMl>^4+H zn9ucs2lP%3rtn=Fb2Zvufb61z^GovJyY#Tkn9T92*-7|C8B0BA>p@FB^FGX}C&RA) z6v*1@#(96!m|yl{epv?oNXt2#AM$*K-BGEtarN?r(ZHklZb6iqQ@6k5=E)PIF>@gU zI$-1vT+5vTc@5^?V@e}UudI#6uKQ!~?@lC^ zLcTPs5#M9QuKaS?)ZF|+q7!EW)NFn!;lkdCv_jc%Yu5AOALpv`Aw%MM4EG|PryTE| zT|1-H)8f6-Ql9pIK%?g;aIQQlGqN*-I6MfyA(wJzMKBMzUOs8-$j*M^+eUWM9%pt~ z#;v1gn)nxvVXhQB9K%rP!;51N+dtglVTXHph6fHA z+~=VOP75CT`-Zs8TT-ndu@XUq5O>i8J;jUNy^>>pK^wa~YreKX4+dA{B6b!-%lZPfpQyp*sq zOqwhyd7eSgTnl8t@K$4+CHO{pna`unVgrsMv~gpbj5Kw(Sf)k3r{BfA+9;sb57uGk zVVHl!!n6kz^$XZchq=PIvY)BzZae3(&DB?5U3I==o5f}_lX786L5?yC>wSNn+uz4E zj1*+;cuiUTk5{1|f4TJD37G`t+DF#7#pgwbk=h&bw(<#IfJ?8`>J8^>y9rZfI(A&mF7UH*_^Lxo3Vr zS-GK~*Sfa7tEH!Ty?&Gjy6akdmNm7lg|=Q#S6xeMQ`hw^O|6ZT!Q=SCrU=6M?w0np zs4?n@I-|z*9hLa&tc+SZu{|uhVZnlHlhc;L)=gJ?5{~56(`SBo=8Vd#r&m^fkdEn< zNjfX>vx!mUnd$f+F$dw?!Rn;yIsk)MY;NMat)X+4OF?hf?>3SFF4kw_>dq3xbv=H> z$4ddydi4pxwU5_3zbQ5+^5Ge(d)n^!4A0rj(e@`J_z3Y=alqgomRh33!x5L_b{65W z&*K)>ZN9|!*lK2Y`A$H$FCUwr-74CGl_61pC91482zij zN#8?aTuMI@=~9fI`9%7Rqt4S`8AJaOp}!}fr%fuxOD~OAz0mIp=x-BzUx5F%;D-Wy zx8M&4_@4o%zfTIT{yrx3Ojll-4o?aGl!tTp^TMY?aOLw;q3;jqhoPZmy1gX0rtLW3 z`Yf;9?fpXkdO**!z>Co@iorh`gV)C3ZqDuoy>8CVA#g)I*Ik1KxVF2gv$m(l!TDy^ zpw&)wdTG<`7VB!c4feqTFh^LoVI%of=cxp7yLK4>w^g@sW=ky{d2ho|z+&0FRm&@D zTY8$-*MdB1nb{bAk|)5+kO6lI=LzU4^w0++Pf-vq+fDH^<3@;bVKK1dZrr)}TFm;9 zPa=MrcNzY9Fp>nz<%s(xm+JW-#Sk>YR$D%*bQStZWc92Wb86=;yJ5vj2EkD;Szfc~ zhDFXjf5{EYKYA12EL*Ys2HtafA}Nz7HwAyOJQKI;RN5|H1ALsJPs=ms@)mCtoa;j4 z4ZXIDA)nS5K3c!YXM*9Q?PbVkV+@}=1Sg+~hEGPGLq1yt5975>aPoPdJoBdQEBPc1 zzFnTl$KpE$57TFt;31#;WB6nZADcefPKSK<$MAX3@UiK0Nbr!);TS$g3?G|54;w!3 zmuKGk2q9ghR4!B5yR(6!^fu2Q-;qpdFJgId1iPl{$0Vt@bnAL@L2j& zF??Pyd~A45$MAV2hR+$p=R@-BZU_gjFnv@nBTQ!hb+=i#m;N*XwqsBbJ;FezN6aCGP!t;AW zG+x4{pdOKaqr3>~QKjG+xhwzik{`Any&E+9g)VF88U9a+yU*Yf6^Ha2oZ)E}{-+I2 z{#s8Wd9U$O{z-#d{%>P#q+oAWS35LG0%Uq?dqZ98zpsW#5^2CF+VvwiqZI#e>6(;x z`Ta@y%zNA#N|K3-D_Q36bkd&@-kBS7#jT+%lXMsI+%1H!6rQ16>|DRU8sC#=_3v5?|Q3uDIr0{rxQ?Y|ZSE9SqZo3_g!bC-Uv?ge-#=6|-_ zQzRuG^q=)WzgPc%4H!wnHKb|=7MG6eyvx(_S=dJGSNLq(ZoXHWq_$5YuHWgs+hBaJ z*MzV@$_xEY>6px6-tk?ZOb+f+Lb-?E(_K)ng)S-n?~?NS9^g#UF#RYAD(3$Y5&5hQ zn1}vz0^Qiu(RHr+F_l+eGc)O~bKf&ILgK)vrTB;ckthvkHyzEbA^Ec+BDV+TRp_{! z!Je0a%cFq-tS#Y#oz#8d9eWsZXEtQYyj{ZN7615!zC?5l&V9gMm6Faa(9uX@EopB< z$&T!=@r(rSdAg+HNbRr#SdVgi`mnD@ZORcFxI8tW`Zhen;q0crb?a6Bd=GESFLHZ) z{B!pkgNOMYbX-m_T+}&94-OtagZn!rZ)INnN61>?Ey`5!3Q$be`d-jecBI!c@{q(` z`*D58`?MIG{eLlfwlT%b-OX_^jU$%ngp>KfMN82-OKB=I?-G^E6(fbr7u3CMo)&oG#y$_pqz51T-!`_2h+mC&=5&8h?3G)83({Fs-?}SP&$~}|LKriwrc_Rcn zx#u$F{N!FzuY-XQ4NxzW@Ac>W!9Gi5A#^FC9sB+}^geN>Q7`t>X3#g1j{TPpuh-3p zMtgmVg1cbJM1*+cbv|B3zg*?@FLpv;cu@)W4Uc+sLIhn>=ySX{ANn2X1me4D9{N(x z-=&f8JG<#GbA3N~vHyQ)K?%+ziw<%hY#MvFF$So3`x(B24PZY1BcEZfmd`jJ{XW{x+>_gfv_xOOvTQv zIZQs-n_ZEBJ}bu}I`-(hkmo6ltC&5~$EE*W(P5Nt=(a@I*XqX_(5dPC+{pZ%T76#+ z-mvdm@f_lyv?-j=RF5=L-0!{he9|MLs$KZeF0k@Yy4?4}@gC_I`+gYSBW+{fUx4>W z@7VX)uU(Hkh<%Se+V#j64VThs_?Q+i58pjO_ww&SeZVTr?gBbyTkly4g2Yud%m;%q8c z_fX%MhS{;HfjxVp9io4=GYdQJ{D$?N;X~XG_jmeq*o!zaEfR@*{2v(?4KVI0gq7cs zpFXD(u#F8JvVP>T54&$m85i!SKfCE+({4luADQIay$28;`i*_cEBB%;O2B>rR)Jyj z!KVfD=)*YQ>;dE*X-Z4(T$$Jm`(${wH1EbaWDnfyX`YKfQ(8z9q5Pt)pgr%(El3~D z!|W9i+Gsyd=|@}XXsV&-27bMWEB*K#v@`vvAHA2s#{HCN$Nyp*1UJ)k&vUHrV-ISY zG7VmF<=lrqJ1I4Q#G1u>TG9>qdBUgBG1t~WudedhpAXj9a;D)!-YiAOdo#nS?-7@q zCyhw`WZrAgX-Ays{@+Mr#v?s48pyz(-YeMmpo|U-@(jwAXm?#6pidgZw9~x}54;@h z7>hdbN@4c~yV3|3e)y{hrU4Zy1baF7)f$MKIdic=cZgW6KoUjH2V4RLoeEeUvN17~`UB z(00d(sj2)PoGBQGKKmwP(W~s(72nMd=&2{1M!BOO`eQxpJ3E*g^DdkRdo&oM{RFgU zH~I5OIJP{)`h&9iD%vO7DS8?5Cf2{+D|}xv3H7euhk4At8}nhVM;PYGxuEnDc@dNx9n!Oi+7pV z2VH-867k6(?r*&A+s8h%j~SH1q_mMZ$E2b^I&-y-{g2&*b9Uh;ZSMR&`r!=9n9}kb ziayj+rJcG0^91ab!gzYzUzA0M^XGq#J;*jl?XM(%KFEG>;26pz&k4PpeI@#YXG_Z} zm^Q8+_5ldE6q1iFE~#7D};%DKG0C&`f%IN zEA4vJ6|EyE4;9&8^<@Nd!*!^~xplQ*n)CF|0BeoZT?R&p3$)!`=pa-8!#3*!Myx+W zo9J8c!?+Cf40SA8UAM6gqP*mO*tv=(J^dKkj=gu4>_EBUc{4737^g4eoanJ5qr-hn zBe)r6_Un7#X5L`uYHgtJKw(;pp|Fka6|I&+N7xM0#*UW=^^krQ_Uz|mH(T`_Q zZ@S`9Szg`ACc!@u9Y-LxDLbK)?V;=pxf8!xO8oW zoP=|{&10g@lAjLNJh0c(H*g%E)-ifMAKv{gj`clF;aERU^P}OQLHXcV^{yg(m_B{O zXd}&^A(h71q4%29!2M`5#?iq}s)0aetKZ;*3(jV;r z(%bv*cw;=TZq3WfkZ1RzE${E~Wxl7)Y^ z++}|>STpI9@99h-U$vb&)s$IzC)(LZ(MDz@4DfqQJ^XXuW6Yd+w;RJb`Pbxkqul`3 zy8wRT9?HMiK0_$(#@dsAK6oF~2mRf_4Eo&v4|UA-?HIpj&_7;{_dMgP5B(z3^jjD! zre(}9>HflSZf!=tTqK-VAwSaKT|)WXXuoG#<5t#!ea`rXZ4bjd7Bu5d<^u**5v!Y z`6kU^d(pKOm?xh2Gth*c&>;*5BSJW5ZZj&|%dCNldnVNSYf67&vP88Av{A$OpsoBbapl)I8ln!T z8@*^_2abDc>$x_^V+CM`~;+rKpWbd)~so1XmNo_PFu44WAm0RS(t?Wd(!Q0T2!-WlP#dwnb6*elkp7giqhqx0zM&%}4t^Vd39^x}3 zqN>OB9`GZMH6eHH7y4fje81omB^|C5{Fu+^C?oXO3BFJk_8SFHDIdX?2~K@77kyFZHvM0i@~!o_#emMeKGj|j=}q5@E^qB+}BksUT?(U zqfowz(Z}ugni4}lBL=@N2EQo=za<9mh{0)Zuvqx-j=}$D4F1P4_*Y}_ugBp36obDQ zgD22V6$^iP44#a^uZqDJ#o)KZ;A>;>4Kes6cWAML>!B52C&jG*4%@};o!1mo;cHj*QzjSgG3Z>bG_Qoc^ z9hLj`YkS&j*EdG(t&O#$;ZV93=kJiFrLD(dPD_w4okiab9gS2xtlzMvwW%#f<81sk zwkr?l+~v4|r8+m%(*xrYpIqn~8I(GP$%odt8D{5f=-J5kI48n6-4@jDmbGo(pYCpn z*z}g}uDa>|6TCLwx!C*2x}f0`xWG2g&zlM^Obe4<9Zu;Ue*3#(qh~_tOMzn&=DL_OTyr0?K=CHL;%4}>|+tl4te|uZq`ljG)BiUzL zo!h~i*WN5@Y`M^~^86($aBOZP6(RZPa$t?$Oj_S2DP*lCt8coMH5XV!%I`?6{^s=&Z9lGcCjwZWlmHMdp=<@>>HiPJ{R+pb0)Xg+6$=`=_Rn5vJ z*x~9*q9Jf@rfD^U!*hs{kO&gBVhdoGYhr@h6;bmwxuJmpfWuG`frTH~JW64E7UME5ndtFYl1TaTA4 zzkY>JX;jy4dAD-Wf+f|3uc8Gvt*Tvx7&LV)XELWVhFRhJbv<1zCXmcuQD*37S|l?qlEjZ1C-t*Z_p+k#*|$E^r1-z1M+O~K9OA2ax4a!-28r`_OKD~jC? zgWnXRQIwN=+SD6o@I7*WReh|*8-x9-12aFs{Pd#T_m zkK!4_2WtYcYYO-bl_&gep;JDJw*~a0JXwUjtj;OD;?_<&zrEG%6?&%E;s*o%jS}Ec zz+dsB34D$Rd>#@$F9v)Re=UJeZ@}kE!skrDNAaN;uhWI;8X>rr*Kd2WXq4cZZ;DS$ z;4?ko!}%n-nE@Zg7bft@1blXRHnClJl}GWW1U{P#K2><|@>szC9(mR-xbjzgr{QDk z=bnJi^}=Uwz(?_?0(yP7)gHaZtGG@{vb=5;-n^9KdxMTR7f{vlJBp6DzFYM3JBp6D z&4*0}pW#W||2BhD|3RJV%aPCR3gY^Lp|^baT|_qx^fUdf`#&Q%=Ory3UE+zz{}YD3 z%-~iYYe#-SJ{bDnFnrPmpJnic22UG&tHEa*oZm}ylyi>1b^k{aaMhO#=}ToQj`&=| zXQ;vF8GN4L%+L7-Uo1HD)8aLTkIl~pgWqBJY%sXZpPdH3)6nlRxRoFK0G(sH78v>$ z41SlvPa6D_1|Ki;zG1#K8T@WTzscZM{%r=g^<B;?0JSmGd!!+w|@X_`faucLn?v-(&b#{)Y^1`5y`RXt^IV z^p+3wXPjfX*nBu8xaRX{Jg0jt;IH^;!^iR;DoYLIzu2>I|04v~@=`fdhTih2G`N)$ zdO*&poLuLjn;Gy|e4gQB`7blLm2+jlN9AlY^p?*igWusrasOKdS2^F4XWIh)inkj+ zmjBLx&mc+fu7Ho?djk583;o`JUhxBhv%GA)2LnEfgwLUXkK%_D_#6xPXnwvB@KOB5 z1U{v*?iYSPjuM>m+xEFqaLs=$nkvDy9x6W1@Uh>6%M$ox68N+w@W~q7%DL6x6I2*n zw;B8W_hgYObNlqV;6D9@n;K1UMx98KVJ+VH71@|1tbdzfB3&YYfrFH69;CEz;^ zZpZC=67U0phxyYfc$hyY4If*7dK37ZN#Ii^>*`^-FEjWOlW)y}hjO+F9?H4N@R?}% z>@s+b!H*gIK7)_?u=g?6BMff8bE^zqYv|`0JY(>M2Cp;t zGK1UlYBsnnuQtK?y}8`*$qLTzO^a_eeC+q;4ujixpE9_O_prh3cieG<+wwhaa9h5m zS9+nD&$j-I5Ik%jMhPCa50!?GZ6BHpUT^ZJ)8IDVZo$KN4+|c~d))A`@t#iL)0@Dj zvOJ#;ww^;-(7Euv-jIOrO27{o+}5{422cB_+<&j&VLqG@Jj{n-vhRs<+I*O4@S6?) z#e#?YYXlGZHyA#af7al(-sTM6VB$R>co=V|;9`xw&!{a)$67X-NOyIUOKx=&L3Eak8JEi(cAi{jrI;JRNi z7vL|5e{X=F7C8?Dxb90l7~n_6-yPt(zwtwe2$!QP=e3+mUy$|2^3kS-GvkOAx<$^_oE--fO#{JVuW6cas#5tA^9-D&Tr=Nf$_Xi}60BGe^_=T*Z7aid>KEFIGzaekBs`nVw5(F2`E=sZ#1DAos8 z{a@%F!S00Dwd#TX5#f zNZ|_Yb@%vS_dNV7v`3v?p0#(_EP>b*gzXp~U7vt+yjF;QQ3B5I2F9!LwZl)xwxJN8 zwgh}r0{%M*_~Qw<->-+4GB&5^Hzmegw9&^=-9{EiKsR$h}@}YZ`A{c!(UIW5BWK5CY=n$(6WF`#D6v z%ZRfdP`6TUh|BbkLmo4@OiMUK%Z2o|TyjFsF|8d3>=B$}T8noIPCoLP?hqZj5tq+O zhred%r8#y;ufgT>%Oe+U2lChJ?D4RZWB+bl(wK>R!s$}TKRV_WZ^J$-Y0Q+Ca13i* z2v5XA@(laE3k|Phrf|%m;ccC!92&n~(}Gp

dxSg7b|z?m`&lWr9Z=3V{V^lg1n) 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

~!|$raPY6A2iPUa_ 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

*DoownfK(McNXJ- z{w6V&W4JP9%lFMSk2BoIA-meyPaeho0F8Se=b1SpEmLq;|0$Fgt$WxOUJf~sj`eOm z5>NHh&hPm4&c`3?-d9mKu0fwKA97X=eq_>v==)a{f9lQ(bz+|=&xGKr<9WZ}R|tMY>`NFR80w~x&kST9n!|!$hj-#nhz^48 z@24&X@!1ndo!NK07VpFlp6TGI%|D{`f)@&({etseSJJEQ7(1afl$ZE+31~v(*(UgY z43=p$KE953(kIV#aQfW2ZwP)w@B{v{`^}|m|AhM@%nj|6c(?bEo^8GrL=q^2@wFhW zp^^O|moERaAfZmT8V%RK04P?_JTHjBG5*O(|7HyS(-?dLM9Jmv*)e#WZu`O*`m1B` zx)}V%7@YTe=92S&#NdArga2s^{x>oBcYwRS3zGleK|Ip1+~ktyM=|)jG58rMhq?Hi z9fMB=PI(TU<>k=&VWHqJ3a>zY_Z6La+4|=5%t(^Di;@4`T4QV(>zAP#HgEAN1kxl6bg4@L|DINI#m7 z0nZgbONBlmAFLMv$v_gx1|-m$hMv) zckUXF(ZlYbb+ixSbUP15?dvySGt=#zU2Uy6dQhzGx3+Y4$$M)H`kc+KN*`;Lnd^0;xOSZt%x8x&-w>%y9v@xMue7gvPbs^XHG`G#l|C6vdHJK!=fh1Fi&i_{=5sjITWmU1x99f{V#Id)?ussG>k$xpKv_CKJsCFiR(P ziT2&W;y*B`-N*FZ%-q`{O^2(&XG%RD;$<;-mEhcKX!$IU!5a;(eP2S`1rPU{Xg`2B z=J(R3SK3|Tn2SrBod!>&(M&&#^wSKEbtY#*J|zaX;YtY(T?veDqx3j@v*6rAWASYP zy^hbf2lR?RCU_X$0|uXN{I`DCGwey)?>4``3knD<8$niab5}T<%}pZ$joe0vQ4U50+Hq2Ft8Tkb|; z@MmLi9e1-{nr--x3cbeLh4SsN;2IB#9}zs{^IE`1>!70nAI0AZ=#{??;6i^3C4+_j z&J>*KyU>JdiQpP8O~<6*%3tw1!^g&dqrn#${#^zyH~0evztZ4)1P|reD|jf+0mH}2 z^Q^(GJfjA;@)Uo-3laKTB6#Sp-lxv^wEmU~J@F+bT!RMZ9IcumgIhVb2_DL`UGPwz z#|$4U&tZdqTs_6}sKKqj#|01leMj)n-`O&M!th>W_%|4QvBA3xKHK1f2Djz+fZ!^R z=Kq6&t2~N7YxvlH!V3W(ZDS4vd=wvz;d3P5qiw)z0UyPW#qfD2;FFFE*_f~4QoKlT z#gC+SYyCP@#Yvl9RVM$v$_I4 ziVwu_*%`iQ%GnmsE8Zb^DF3j*uQ2i- z5BO_(y%X?PyhvU&{uQ4nFB<=fC*+0l%r*YbG`Ov|XA8av^jbI5S()HG1H z7+j``U8svCQYe3oiHF%S_0fXCk z+iP%}UIz_shf8TnZHL4#ZRQG?%P_~?1l zT8>m7<(SZGc~rbu8YlYuYlcsk!9Q#8%?58W_+tjQ^rJEOaf4ev4N^%_9?Pf8;Ff-` z!9Qcr6cSqGuQV$_~62Srd373dU$eC4tc# zmGF6+KjU5B`DC1Osx*l|YZB5~NJ_oI=}7t`)1m40a@N_z3-D)6sjURe2hv)@z8rb} zqVCyOAkTdKS)=}+Z9%-N{0c9|3*FCCK%NyMzb(W3r1I;tMzB(Gr;i84z3p@Ho4V5{ z+a!Hgw|sv4G~BeP7sZ@gzqq`tJmJjgpIcvkvHGt0Jc)Dn zCPeA|IXL?S6hr9BZUqJ3w;@sXQ6HS|El(G3)$>EBPYbL>?bNM}k`tx_%b4Q8o(Sy2 zjL^z@O?P&KN;BT0()s-Zw~k; zg715R@5w;kk-#1W@+AU$X<#1>_!kG?p9}1xf&FM;j{^CN1AA$Z{&j);djk62fPZs9 z-yG71-vjq`f&IB4{6_=(P+%_&?1{i$9N32gdlZB}8OSpdgl8xSPb#nv2lhRIy)N)C z74T05@{I=Hj|TS9fd6xWeJG%RF0f~62KRPb6lIma+XFlLGg;r;1N*MP{yTwvIIw>% zu-_ZlhXQ*luzw-2qms;$uRpM_4eaPwWzi1=_Adwa^?`kRV1FpEKOERQ0()m*e^BGYTLODmV81o6-yhh&7}&c5`~L{+pAYQ67uf%2VBZ1TEc3}UFz`ilC z|5jk%64>tu>~{zD`vUt{0()Oz|MkG$8`!r6_AdqYuLkx90{ia=_CE;h4+i$%4eWOY z_PYXmPhj5^*zXDKgMocRVE=kx-yGP3>Lps!(w6A#O+YmW7s&QIs~onzraR$v)e`7+ z_4Gxs5A-Bj`n%^Qpl#N^uDwq_KpC(bcSleQEJ59*#M%wrZfj4}*4aljGNEh3wb8vj zaGPl9!acohcOw$iIeTSTYLKYAZx;3`J3p!qkEubFfq`w z4&T7D6M^Z+HPCC?`wY<6(!H)dZKpycZlX?zj-R?q`x}11Rl>N68MjlnW_UO)H<-4>Sdg5=V|Qs1b@umf zK;}o`=xNiueJem_RUf$ScI3UDzI83#op&O;_H-w319(Ei*4@L*y|!~*f@-yEsGtl; zxVAFSuXP2&pl$5~P-*TbGB%(DT^Q+Bzjq;LY-m~64lz+M+uNMe4Qo);61Y&CHqj9V zf#==RrXnVK*7|JOANAm}ZXW{XcjeVHfQ(~GjL4MsQ_Hu~%lF=vfsO=Jpw|s_L}Q_J ztq{19l0g4kH=vAk4|JjCNS8cebbCj8w?so)j6UdncOow*($S`y4uPP;awU61cgq@N zZd7ehHq}(nILY}D@rPPU?&L_|E^aATnG&Gi(j_lVoko0xq=b^0H*}}NmB;~6mps~l zd&VJcPok>_+VE5ZwVJk2BCV~0-gfP>+Uoksnw7Pc)lHQZD^{+k{d9G%Z?&uBb7jSH zD7Dtz*i?OeMXkKnu3EJk%Fk6Ro2qK-sX@wD-WgBrSADOYSEa8j6tA6kgV!nt00q|y zs6VfYt|f<6P0Q+6Uf;B;y0XDB%+^Xy>s@Dbw4>U2t3-#oVu4qd9jl&A|8na5V&`cC zqk#U^u3QnVsIOkuv|{C|sBY!*+R7W#cwPNUry^WeS=)3&#d7Rvt)ExhR9Ri$07CbU zFVQMsUY$EF$`~#1G+!iusL-;P`-)o7>bm&nwA$``DXyK&136V@z!{ z`z`$zWV>PQX+?N2r6c19t>{!_=$YtNCmc>3qWcs~Py+i9{_Ngk)iItXxZ0aJaV{p;9%Ftga5JPzm3ijc zt6YZ9+>52AMqZZVS*)OWu8G017mJgs?wY9?=?sYKr^)r=)47ib`riFL=mT;?N>@)y zTa#oOUs-vau9{pAUbmX0sg=x0<>S-qR*y4ss_b05vv`Tn@Q!+m>)bNec0OqM%#e5D zOd~br^1?NFix&x=2b}8{PfAiNf5o2@d}cuZn&8S`=_iV?nm&r-&;@5213niE-Vxw) z1Ro6WD+S*Y;MIa}5Ab@ycLn&(g6|J-oXO+N!2tiF;D-Wyhu}v7e6Qfg1N^T9FG9T2 zX#Bh+_~ZcpPr-3ccozMef^*HCM)`~z@9i}Kj`NS5X$;m~;dSHUL-_>Tmi z8Q}Rv-hFw1mk3@H;4=kp4Dh9bcLewif)56Gm*86he1qWI1N?r$cLn$#2);kSzajX+ z0RJ<=4+Z!$f*%R+?+Jc9z<(roQ9*Y6kMj*wr1y$wx?Cu@?%h#*mf+<9pIX6d0{pXr zHwJjO;2i;ex8Q>T{#$}?3Gjyn-yYz9BKWQV|CZqU1N?cx4+i+Ff*%U-p9p>=z>8R^ z!yFIrj|i@3oM?QO3O-rdZN)1DFAs3f9r|klu5Cu*z<*8f z?E#K?XJ>W=_$I;k2RPz9qnMPqZ`J1AM%c^IZX6BKZCQpCS0c0G}`Tp#Z;D@FM}f zTJYlm-Yx|-y1=oIx;ymkuraYiuCwNVO|Ayd=0sck7I|3YMQadvk;D0RmFQ9AI z-qkXPGtG1Q+Pmi9Ac~f*U!mez0-<5mCdI*pjXz0wtC6QZB>B`Dt8+GVt|!5Iv@_H> zqCXOCr_?#y;+>88m1;PR&la9iT+;aIy5|fBdB(XPQh|kYV0HU47$-^ju8+id{%w~G zq#1r@5p_RV2$$hW|3jU%$D(^_k%(pg)yc+tXyGpDb!Hq$7(CY>xv%mICXau2n79W@?dFtk+O<8U}dadJ9s zB?!mRv|o_^z2fr<&itetoS2615rTOBF+5((6jdL|0zZ>@_xif1M(fXOdeLUj6shZaER!p_6*)sjU zWHj}=5zgzJhCj#qmw6Ytu7Q6=2%k?YoI_vJQr-st?%i_nea-MMzc9jC&C%nOy9HU0rtzA2w$&bD^ve)A0U{M`u8wh^40 z`UcNx_2Jug8}6&&*`}{R=P}RgIBrYesb`w%x%!A>cW(pZvK8sD333*I2lM2`5$}w` znZx9Xza;GBA#%BA!MJgl5gj*C$54V2wZh z5GS90KPg7-r+R8ShjeTstSPn@ylePEJmeRC|3%%|6*H{6ws&Im6leBc2L_KX!JlSqNnc;`P$yrS=Z7xpw4xZCEUtT8QvqFybr3qj zx|6V8*-*n}HY`EA1J$tp?lmpmo5dzcFUI%#x#q+^S|&F*OZq3*nv-A8&{CczbuYQj zwe|E`+B5X*L*+#oe5QQ5OmMY#NQS#o@FB6+3H=JeM+2OnbFEQ%d2*M+0=LQ{jLoA! z4?!^)Ukf51dlqhj#jb(rno=+Dvr&tc3$Z>^u!m)gB)^3}@=^Etgl=C>`u`>L+Q(M< zKL<{Kci~B+{vO0T`Ok1@=A6#&3SJuEhhfhp=YI+Pl7OCL(_Hk$!0B&IKtByQAw7WVMwz8<3D~s-R4;nRQUC`Q zX6s~G_TcUh`g6YUY(wa5WRpA98~2&&9ORbv!gxldQMk|lyV@dWh1e)WE21)3yTK-yo6qOX#5xT*M@1qLJ`V>#u~I%(n=q%OpK$;1TD zv|PFL6HVy@SQ~Dvt9G_5*Xhr4Qe*lkOs89v{%X~|#xj9kOsQ!6WHE=jO-|g=r?o7- z^iDh%Z(~_x`f)CxwW^<%&TXrzKe@Vk1vKFhr%r{(Ne_#o&k{ZjdetXbq5TIXsFn3M zN)#wX#flrrFKxIF9s}#N(Q!<9fNPCT9SoU9ac;D}4*6(Z5b{yK$VaxGIzC#Dlg|Zd zX)Rz#KODnnr{QDMYgY`P$71;GF??)#?Tz8HKZef}hL4S(1BQ>CRz7HOnJ#z8 zvw}0;Ed6r^xAZRv&iI@y@9qIR4Ry@s_*eHkS#Z*S%;21mqv6_iW;BMiQNcr@89K+RYGY0UVNox(;B=Q_XJ_hivLicPdhy}q+Go0p~rGLZlv+U4) z=pEL}oKc-5Z_9*V?W{X;#b3E}I)+6s#vh|HjK4Zyx%_XGsnbz>w?^G7#`-mv|A#K{ z6eB`N|LIoUYx=bUqyM&Tg*7UdbpIhO#*mgqpMCPK<==h8&&A{Y+Z+YtsqXZ77jS*I zq@NV`7UO$J8@I;3U6d5>3mAm%X&;k!fHkWB5)WL*V}C1*KdzsIc?VF`$OUE-l2>8FL&eq-${$%&nvj=Gtb=9e2jN> zzH@SszYEyk!|c{{d43K4cz5M-bY=J*_W^%W?`qb&FMo$?wV~A0OrAIocOrim@3^<@ao+2>VI1$FJ>RW0C*L}`plWVBU)yF_g?{`X=G%!FoPLnkpWK_b zH9x`o;pP6_w@xxW(()7k2cgA1@9-0M?iNSuk)Ikq|3Ta#3fiRz^XDcc7w08X&u<== zTs#b(_vR-TQ!dK719rqq$DIfaN3Xy9 z?#YIiA-Be(q=gIDSAnmQutR3tr|QEFo>}4E3cBITk|+Kro>rHEcTU?o%>CWi{_fWY zaVP6Dkm(JSH>M(!428wk6FUi1wl!q0C(1>HxM)XcIGTuY=o3sro$pC8a&f zB_GQn%Psk%-+;0i?VcXpgZjpoPqu5gd%BEmh|e?Lzhfs(F3`9*aCNHwA^2nCocX0i z?r26ghxLhT1CzLSn(qwnXo2V_!G0UU{xZTcjCzaTNBA9W{J#8>XQtPp?JK}N)Tk@? zjbV-W&D}FjJt;3Mb){H`yma$|@&WK8Z7QGs`1Y9b8&T)(*vWl6Kc1?``qkDoko$Sa zs$r?R2I-1?_-$Y#xaVADWt@*hnfR?r`h3RrQu7DX13Go-x@{Qo_Bnh%4|(}(c-nid z`=3ib%KD1!>I)|S?yU4>VF%JZDd`r$z0JSx-gUsWnUv`#sOR29`OvgIUQh`CeSS-w z5tS*fSo65CSd;^Up7a>E$sE{d;aED9$1;u2!ez)C5|)?I|6+WyzE`=DlK1`w@sq&& z_X{TDKJAj-uOc2_K^y1u+__ohm*EGWk`d7JUTyODFFd2XRK2TbVQ2f1!t*seUq$>B z;{6rG74vt5_@w)H@A|WJKZoswrpF1?PjA7^+m}Zt-gfl9o@qWK+KVyC&}8JB3-DZw zC(;&q?m|}vUqYKV>kQWpBMm%;eE?3c?`3JLN6(BFj7~_N7(SEb*Ow)vSzhvrT2PS+_jF7-GwylUx=mBxH$nM88AIQHw@=r|r7PuS+tG~rh-rBh(h`9f!hV;nXfu(fz8}Rf z%qnD>Qf7~#PIPHH4Q|LMQ5Y>qAx&AIX}%`jTo5f_yUxBN>!5GHbMniHGol5jO0xqq zeb_60jx=NXye#p80jQG)@rn5H@!X8Koeo+4#l>TZlq;V{Q*UR-BjbC-#pM&}^5Nq$ z+WqE5(Fy9Ua_q%0x;R8#9QOToqYq;HdDJ!beO9T9;f86){-35l%WgW~miah%%G86T zd-I}9zSVj#SA4P$7G03|!0dA_U33csjm|pnj6~5zm#@O>%II$VyA%3CcjDbY-+e&W-wbR9ly*5G~32v~ptt+Kp+SuFRG|{S9C%MexbVbmb-e5yavH zk~y0f?#hIb;Yt+~@l6o}dq>Q2mW9YvYgMT9i|8wDAER+4Zw)Xci^#3~se=P?8aSVP2 z;+x?bks?N2K$`P_=Zc@{F*rIlIq8?h;M~}gi~pJ!d_xS*yI*th`TZC?PRDY84EBUV(339^i@*D`T7y} zS;WwH#^4)b@Gr#RzZ-);5`+IQ;0)JBHYhM7?ic3>0Y4i9ST*Gm-oK9FL)}y^W;oSU zHneh`HqK_^v26a7NK!bf-t$iT*h|#?`CjkGRq#%0P_zN5RhdyKY-{goA87a2OdHr= zB|lbsG1T8Q`l-U+xzS7GJLlb&tt%@hP_^K&G`}Gv1kB~}{zyU`GTVg%F{7omE1UYe zdvVO(fV;{bN6#2Ovl)HB3@*o$N@ab zjw1AKz%jI)^IEd}9doK9^;B_T_dFbj>e89v^@nV^b@efqfoB0G85rFXL*a37K6YGe z3x!h=9dniV4fFLBIiFTI)r%LRXY^|6hsz%sg;i&T#x>6pZEw15epFe1V_n0_rdwOO zupga=9d@^(ODU+6!R9cx<%euRh~q;&cgY?+agGHeEAkPy?65jL-0&lrP-~Z2s;Ae7 z!KDo&1jlpoZuAxC23t(yjA!amWt(^2B%vmFHgXu^0X6g-TF62ZfGm|}3ukEG2EgUj-@`=t~z-P?}t5W_j@G9 zU-r{zG`uR$(SUxMCyR~+^onB;&+!t?M8Q=a#b*Tci#&N+*GlOX zpDpx^hmQy?AIX5v)$&bs5S5SOjRAdy(BCAu(knh-{KdZVwAmQ&sg^IPfREz40{ZKP z{;_~w@dJW0yot20QS@TK=SKN98t_s4a6o^P&>sot6)!=5h9>kkVeo05#Qm}#NJDyy zvmZ#K`G@0An&pCPJS*N1&})6#7|<);D>(g~?peFvfq+lHd>ah-D8AS5nPK=mCpdL# zFERLwhW=86A2s+CgX_7Wj0e^mGJO!06?!7ZgTc-0wtmOI581!p|W6k0wo z-|UR?`8{uq+5$d`cLnr&guXYRSA1hYk2QE_QUSf<_X{4%spp!hoLHN1=COc};!gzr z{7ijM~T6+dS9*nYwk84A*0+b^0axaJ4tGh1-Y4~i!Z zAIrbP@L~O+esmc=7T;p{T%pYIRGrmO9;}Br6Uwv8@UikdCb;t9{2I-kfREx&7(Q0- z@u0yk@GRW#VT0Sf7RLlvf7OYe%NELC#7Kc*x|I4?_gif6xdzvBVo5*G;H5$z`dcP= z=x>eTZ{uxwz~>T)H$7KY`6zyq;bY^i!{GCcoEr^ZX7FtWUtsVD1P{YCEV#;}PWBo; zHe3f{_#8C!3zZ3;FBn|=bo_kS;N^z?n86ntT+e+Ag^@EE@X>Eo0UyPe$M9(g_-LFq z27DB6j^Wc0@R~DJd~%-@Ui)1 zqrs~U|N9NT%;4Ju5B=RPc-=?&-=-za#P&xZ_dR#iId6WLzu`#UCC^rGZd^U(Mwd(WJpy7KdiH-TVEPBl` z7+=+$K3ffDNxST#nfajZ6e3xecKkLf;n#U2r4QZH9;O{>d&U2Rj8j>yvEB;fkKNZ? z{trn6|G&Y<(0?pM_T!?$^rpyDojW{#?)-%bXHI`lq>l9badN7X+_8ioYIPz9NhBtxy(lf*Ezm@rUpxCCeDrbKr>g*|Vn4`Poe z+@+wGoy5MFD(I=J`=xMe-P`a{KN_)pA}YZj;&%k$-&~xkXILFRIeFqOyhHE*@x29k zThH}ruzYGjc}tdvS-{ zhryXTOKMmT(Quwn-yI-76?l?fzikx!Q+O&Skb88+;CII0TVn9vi@}Fu@JD0ty)pO! z;Acmfct%!p<{$8zD_qp_aFwf5(&CMuwBd@)2wGa{J524NYEkw*r@1c)&8hN|t<{CD zm$??yI`C>zUbUtAhPtNyj+VI*U#dFSwfD<8Z&qi<2Z2I6Hdb0a)QxRB4d+Uv`|a#A z+^-*#NOSIxQo-4Gm+2RW==?JK?iQ~xd~7_o8QeD4g9e`@?|cl)yZS3r9??$0)nCP# z4`?{1I>*1d--Gf_+;;Ph7~F>UxZvuqSfh93Mg3KLBKXpTV>ymRXhJ?q1P}RGT^1W} zjfTICpCN;nc(2^=V+OanK4_Pmp`2FNM|Da>>&ahW3=^Cx^DDgY1ac=B2K>d1U0&ozV+zeXU*pCuMZysM1!vgKkd?->#&O)( zWlF9NsqkAL6o4dn{mC&d2_@kbvjzuM>Gg>jNpK%TnBQX_VTpS8BS z*YH;YqyO{pXU!Jz-USU z=vvP$0fW#z?YX=90{N{~O#*rTj`?$15;7&3{Nbn^JI zhwiWBo=W5gw-=WCD!CsJ^U!WjEced7f%`(ZXOQ~>F?Oiuo=Wbg)qSz(e z2>Sgg?CnHa=~*P(peMHe$LBwIA@?_O-y!?@+=Hv`lHv{pYmB=$;0|YMoXvg4`4~&Q zEaQ*E=)3E<0}KtZW9)@}y>N2!t!dcXseT?lH&wqhkX^@i z>R!i_e+j=aZhD?)Qn)aJC-%ti-N$nP;3xMFkC^?%ZRh)O(Z9nTzw;~z?l0!PQQbex zJ@zTab3yd@x#Ob~1D}l^y=?;X+0WkNd_H909#K6*B!Mv>^XwbQ#}Az!ok(FkiSq<> zjJ=J1K7_F`;}Eh8;cqKt(y+B4-FINW?L!zFM-ska@M&f~jN!$xZ#FMKHstu)j>$n2 zalR&O$B4hz2K5TMtSw!)x7-1}`TqV5xF$mDn^vdw&FzeRoh@DO-FT5pfM>3;q}Qp)jByM(=w&j>f{u^vt!F;w+K0FppNlgj>9=GI-VlTT zS`6M6gZIVYpNqkNF9!cw48AW0|GOCcPz?T`G5Ako@DCuv<%&=0N#(+4#o$-P;FU4> zCu8t6F?e?jjyfghnEJjLdQ*sJ47!aK6{{O+R@T=x+}Lzo^^Mq&!Ob`!hVeG`Vsv9i zPVlA4Z5Pp`u#d*>`8b_@AZdEpmc>mcX17gxXO!P-!%AtzhFjO5#G-}9h>P~fXc7<{un+i-!$~s@;~C?ba<7|Yl4UTj|v|0!91}uDyNRu zCkw886rUnE`PjJ<-3Oz5J|h0j4EQKsYWPeNT0V5HLHVe^I(He$(`NWsc{Uo{&be$8 zJmkM!@R0u=!$)PIocj%K=Q2hOZs#%%8{AE5lL^dGgJb-VHpdKpK^n!_N!sI3e!G8# z`CMg92z{7dGY#(NeZ41ob}H%ZI(fOFw|I@gZF$i#ANgq6qz`REAIje$co_eKhCkv!KWKMX>cn~ zo!~0Z3~|GO1dYn0xb80rO@Am1c^V06w)`*SrOPUB+5LG%50+&a** z2G4;$|Lo8=cb4)1_Ao~7zTarhn*RQ=CoKQ>nhP6{_|otd>We(%=EAm1*EA_z+MjnW zY;WMNdW+=AGP7Z0+J)q&>ppHSY`-w<$nq^S7o+f8yf99Z3dr-26mHEYKkr;vLL&O| zfUkyMpK)_x*NOW%r*I!P7j{RO(85RkRkmzH!no(Rgf#lU=v-Jz{MY?m?BB58!L+8) zx<76%Oz#)}gFxWG%5H7%EgRCy@TWYRc>coq^AgUS{yKcG>3Aib^hxxICgN=3zsy?u z=2|!8bMsBF;JixCK_G73nl+r^EJDl;;M}Wwa88}l>3Z-ceAD+7<`PJ!G)p;OBO6E!TS_ROZoGM`XajGg1S*nJ<1 zUkW_W(AQ=089OK9`HaQsEZ12}9%s!w*5tbX@*0qhNpoPIh{2g(bJ6zz=Q_Q{3+pzT z&*ATEGuKn@&?x!}p1Jt!0!}{rg--eWWeokZLVqBjeyHGpHjyPO29uCSrM zWnFtyFXl>nL@kFIHPSO`^FZZA>Wl=tm%EmO0W2Ad0}7Lj^&pG ze6$271y??b*BCxF|7g8V{&q~-Ec7a;j(ghz{)+d;@J|JNbo{wF;G_8cF?_Zg+{*cw z;M8TdW9L1Bmk0P>!8vE5X-7!QameS17(OF{laC!cYxxfO9E{=ftl^`1hR}0@hkRZT zJPg+%!6}a&BP&mip(cWc`b#tk_v^=2cFdbJIO%ndm*yYxvGk3G-p2p1!EM{Ed5?T- zYf)F+eLzb9k5K;z-R<2^brYIx;Y7}(>+db&q>SR$G2KcaR_U){IoW5)|RM;3UO zuE!LgEj-Z|%`&I!K5nd+ps+Ce{UiNblz#IsabrE*J2@ou3_t5Ub+7rK`IlaW@*fia z%kj+`b+1?@UYI6H1>~uF_%#30f97j-um0;;Z(iWOSki4-fQwk^bhsJciK#zIeuKC_ z)mXD%+^ai%ZWi}y*Qffg_PDX;5t(baR|(}Ax~DytS6c+!FHa8L+0KRW7dO^SN(09= z8*2h9yE{0|?DWT)^Gbhyy^B#(Xp>HuB&Xz!4#S^ckV}NnKL&*>s#TV3yoJ37~N4m7oN-_c7u4p1CuX=?53q6H7Xy18n_ z+$M3v^|-W>u`+V?HbrOO$c{KQ9oQGKeQT{_iQDjL8$sL_tb35Fei<0M@ANXm=Gv*MNZ69`r}~DIV9isS$VK zgFLK>>)V{J`?$W1x@TYA8kJwMxW3IH3I8r3WcYLSZP+)V7n*N{JbicQsrm-X#l5=I z=N|=fD;~meeS?%F^iAqeo}qi%ZFy31UC-Pu4p?^ir}3xhAJ;d~^U`ithVl&kM`h9u zJ&APZ;FSBp=FKZhICJ{*(1%oL$dGh$jGc$3P8s)M>78}dTU#>^d!S@5lkP#%xnZy= zsf3=}HBrG2H}SqMw-@YbW|xws&CynOuZr_)>`xd6N|7ra_)W5+lBJ(vS=JA^Td%Qo zgwmVnQOG@|dzppN!m^OdoP^1Re=!&MK47c6`+M74JJ)u$w?(*BA^m<``yGkOo?CnS zdT#CPZ;vp^WNeic_FH9z`BbrXZD&_!%RpyOccQYRrF$Ltwq!7cR&Bs!ReyUMzV>Hc zE8F|~z0;Lz6DvXCEK#e%E7xYg%J#kih>fFu+Y>cCU2ULB1I}LG&T9=4%MgM@W&QG~ z&)I3Et*)>0w$85hb?u2ybq;j2^|jpI9bxLvV;QI-E2I@Rq|tlQ%VWNNKl^yT|B$=% z?_*+Zp~y2vj~5-@8UrGTo;2k z#o#vsxAW^Au+t3UFBgCI@LZ+rI*aHZvb)#U-qPRG%`>6<{h83!D^_1$U0=~qUDec3 zv2=O0pFB1ww99f)M@v^PYl3P3^~3NS~p!2-i*2K-jvTtd_q4TQ5nbvBwo?{=+ z=OzC|-6}p&93W3CYYl_|I+5H3bZR+wN<;*X};{bqi` zeni}u;D~fAYQ!n$+vtzR`((l6#stIiJ$y*=rQx_S!Rfk>8xyE|Ti?@Dm7ni4abto~ ziO^9InBmVgCSd(clCa;lOWbwfn>C^T%kYtDlC(s4FBZZY!Rddl`OZe*^eS$?^GcCJ z*f?6gE4)tLwcIG(CnP|p8q@R|Uh0-l)oHO9-_>8mvq3ndqJFY^fQ4`e)We8@P`^Fp{Mj(2SGZd2%czCHu{ z!}J^y`pI-^h9A76bg4OudprEoc=LCjA89y=5xrOW?!1m2KKGj6XgnI^oZJ z!Jan68RbquN9^oe8u299Ezdro zzq|{QdFsL6ntELK{V`uXgY+4mD)|Mx^sYwcFQv=dl6@cVgx zzD(v0O3lYf_^0?q_-9T^yB9>}C+(hQdKJ;2-Wc z*PP46?#tL2NIxdX;B~@hKAxP5QM*3*IoDi_=l}lA#Vm!tVVN^P12rpTCcxr>+d?j|cQe zV(5P&^o5e;lt1r%$R*Dt;N)K%&{NmN&S7czc+NcORToD2^IlBiy01*}#e$dNNuzj` z;7P%I{paXL*mKFr`!dO2*Gam>-EYLu-yeg2DF)vegHyRZmpo4Zckv+QbWr5~b`1T$ z3Vo4O_QOK|dJO$IRLr^jJs&vz)q796gb(+P5!ZV|?ic(j;9UP!|2hP(is9c7gWD<^ z8*^Q4-2`1)dBg2$T-bJ%x9ZJ0OKp`}osO!mU30F|=+(;RT|E31dg)0|UDvjoRvjZb z!YZS2E52!K!PW7MRxB@TgZ6Bb5@o(nr&a}}?ri1@ZTcmb{w&pe-FFGKTaFhm1WL2; z*Tgw$cNt@6o37$}4<$6bkIoZuyRIS1-m#3y-1PN#8lk-Z&PELFh)%a5IE!UVKQ7vX z=#E&UH;ZCJS5No4EN1D8_pA>tPO^eT)>(k(q>a00sRC>I5}w5UHVYo+ z=Zyxp`I+r64e2lQukQDd;94H%$hQ{-*Yc(KQN!n>h7UJ~(U3nU64cBPJmk;zktXDy zG<;@w68Fn?kcRv(_pk0(_d^qBA6rdtjK2dh{;Do2`EWf_%>%|?8?HSDpRL4rju`w3 zgC7w*j0e@r4C6s3&nb_MXWfTQ9P?&rQ!M=+;+LdR+<9a0j~TpKaF&;u1|JYSlvC%9 zLpe7Z{#MTY2DkO?sKIUiJZf;wYZR-r&pHGw_C2=cHsljc$>HTw| zJV~Js<Vt+66JKgyPyzrV!zH|C|{yXk*8J2ve!IomC z*4VQ>w{v0$rdJ}LYmP{wF>7XierN2O=V;(BdC`!EHEcuZg;ay-Pp9jid6hil+-v_! z8B1`~8oTCOBn463GyDvay4P}A11y*SN5*+Cdi^8)tL_!3#0%3Tsen9-rO-Buo&Iz7 zOWmvgp8-byZCwOw)JS5OU-OUjug1SVZ^jqCYq?Uwed2zO0`gRM`s@d;@0Rpcac?oc zhqQ5PzP%Fudjkfcd)jTiq2x!z|D@zYmVNpa#^0I1!n{KsGa2D9odNUEe`+%I_H^~D zBI~KveCIA)xL{#|=JeNm>#p{)@HgpRb@PZZ?Odb|ION8iRe z2iFtbnitj<;dBUpTZb1#Cvcu4&Pce(tzDdyHC?;rcH)+*N8j$R#=7O-xV1N|5n&z5 z)9YF%cx{_Hl)pZS^DU=t%U_Q>v(8T7T+COoPU6>&&q<%}K-wMV%m&1xTWi+!BBVpf zFxCPU_dG6`RR}#?rFj!;UEjf4mwr=P{r&{p|1Q>;u^zg21b(R;N@sbEfY!-h7_IMu z%!eT}#+O5%E{L}B?A6e%`l0TgWSk+~%3Hsuux>r_)=5s+x$r3;`u+Ei9c6uJGt%Ju zcqcEcAF+GA?G>y={S(&n9-7a!)(g{Xtq;vlo_HE(eC}A3i3gs?`mb>B_c;0WGrEu7 z^k;pNhss0ux)#iJsCV!3dIEk;EZ?njW1K&<4|#`q1!MT3@ABQ~3UIxWaieF5a=r3Y zIsks%(yuFW{U2+qE>HM-9{hUmG^7>R)ENE>#Jj$8?SB*2nDddJh%GyL^2=Q3xd_RJ9_-d2cySFvG&h2+VNl#dhb}PhW-b` zM0^@_9{BCwkTyQ&($wyIz z4?Ti1vleH=Dy@&xXzK{_CjGx2{0C5;_P*=R?j6GSbbcBsjmlE_$;DHny!ClkV4eLs zZYH)Bov70B=s!b854bL0c=yj>qJS4AhD{3_$bpQpUzt3FOx9-3Ld z6=u?7=XB@`;JjnXMmlxFJ5Y99m4prg^o6-h~TKv*A++U5BTk`_W?3 z^&S&1pZ^*0!t_P?eV$=qxLLRGeg0+9zAz2F{rufL>sQmY7xB;xJ&Iw-9~DMt4|fj9%WlGg8GJ%58_5@X@TI;B-0aq~Q*@W&BNpo)q1^&2X7~Q<(7i=F6btcPAsx>K>MGj)dX7 z#D{Z}2`3nHYQX6dAwJV(@t+Xp;cFs<)wjRb6hyb&hx|6o{8o%}kC2~QP+vwUi_OKE z{8xAd@(pDF0c66t-Rbsw3h3FM`207;<%j0{XhE_d6UXoT%sBRLM$V2FXn8ygzo-lH zEd1JW4b#Qb41@0zkn;)27v$TFGpvE1*zw!R$5UtnDxi1r6w;UJnODfN<=X_NC)1TQ zhrzc3^1bQfSIW2dV{~G)Ubh& zV2j5`XJ2o=9hm079sDWzm!Qw+^C9!+h%IB#fnz;52s--j>SlbWZk+l4Yi`rM46sKoNE46I<=4By#8c%GIO;)$v`-=5qFn6dce>ZU zId#kO-_7(Re}r&&JxWifd@McWV!d+OhT~Cdbj)NizQeE6G9g_YztdtyB4NmVXEbr{ zcE)^&^B;YToFuhbm(g7>`*0pqZ-s$!h zrm6g4-k0=4k!^M&n#t3-q31^T)q}lVovob%i3Xg;nx^sS390|FUxh0*w?<6{=0K%>sBtWt-SG*t1Fh*u2{A*>Rr!}w?%DpT6_C9 z^mXEedVO9dSb7FJ5Ek#qJ8xz8ZtS7K0y;!Q*uHxR#d7-zhOT_v_`NUksc&W5*<)`Ft5g zwZN(SHww9EG#x(`!)LAVK_WP#e5jj8KB_CBe10c}&%?q;&-hk8e;z~sw?aQT@b~2y z`X34XjDWrf;b%OQ2Ds|lEeY^TgwfIkeJ{%XAI^N)poD4-t^{DA=f2f=p*_)CKC4eiBdBer*i@ z8)ERaG5CfU{5NB8w>{o1D!GmLPPeql^f-8QEKiC6Nz?}wN`0Tvmgy0xwri$4q)2uj zCYu*1oo7L)Splz<}uL*9^t?>dFTHX~TdyhCo$DtwwI9r{)!1ja}6|Gw04yZ#IXdx%zXt zm3VVG&ZzBDp*IIbj$?9jQ8}encYv?!vAWJD6^An+vhhy+-VCv(SeSsK7@VE{ArV<+ zQ~0PP`%GRky=;H{S6j?SvdcKju*&q@({IWs4VcVKHq1GC=TNpDvRp0H+k(?rnz}l1 zyRaawJ>6@)pHxBa>Gkh9E?R;nGj*QDnZF*%jc_97&w;^#dB~&sSq49z8OK9SbgN3v zbb!q499T8wwC=Linl=|8kI{v;iqYP$bj)}wrIifPv|?qI9{a2-(ot3Is=DPBH#Sr^ zHl#D~7_DblyfU9F7Klh%UMg1H$gj?5|APHK>IS13bw=x8>QGs{RK6?yGO?G*Q|T42 z5}dkHljWTc@!sixU10E(ypta5lWDV4-qhcAvG0H z{IR~{%!oXdzv9}?kiXTjd_m}y51Kh=4#`vbDE^w@p`2*yoKZfax)Z5Rvhq<}b&o?n zs_UzK65^lg`YIpARd+Y!lN5P~+jOi86>kY}2NiI3xgvwT?m9l@!iJKfOh zc$Iu+7+mk9A|H#ZE;RXEV(2GIMG^8T7ChurA~^Y6X87nhHsmuUhEKxqvAVK4z76@z zjNvoe@Uiiu<6-idX5=h0d@NpW_}KW-@pH&08N;W_@UihzBY4PXc?_RA!^g&tj?c;G zVGJI^fngtK}w8il0Fnnydx?=eB#_$<1d~CP|WB6>0;gd3aY`SkYe6-KN zXxd`@j?7{OmP+7MuLD z-|(^c6NZnCpOF|o2V(dfG<fxbo*BI!$B1Uvb@A5w=Ggg`VY6_4mm~_g1hTw)hq!Pm+XU zh5~ssT-yS96xY4DVR-i&{;L1nwV*&kFh5mRz zulPFw{X-f-XZRQ8uXvH*jE4%P#dEUYn!bN1-=+k76rW-EEH!+fo8t`mR~meIz+cm) zF5s_tv*B}v;nNlH`G$P!4frUYGJI^mNcWg%c-7wr0zQiGHGH!2iNS3=95Q&7k$+V1 z(BH#?YkH}_#|}zSNx{Q-zDe-V-{ydi#>1fDW9zHUF?_bf@Y!zo z*mT@waGPFxWBBin;s31RW7F#egWJ7nqXGYyBt8!Z{1rcD_}F@Ka*=l!#^)5l!*nbY zoatig$r^*(da}XbHotWl+~&892DkZbv*4keTLcf~95#HcJbMg&mC4U98r;frTyXVQ z=b_#aT>VwN@J!E?@niihF}U@2w!v+GY>D9N?-r3YDY*Kpc!S|%^UqBIA8jw113rp( z1oYZobOrQ^_XhOZUJL~Eifqe~ZCw{@fXZj~LwM!)Fb?-0*)<@Gw3{1rOu% zsNrMd^SIz)`&Br>dlt4|MS?TDNh8k`gU>VgOoQ8Yv)tgeeW@|{wT914G5AJ<>l_cA zZ5BL?pDlui@w46VvGKDrhR?1TJ|i*o2V&@76rAz-|B?4T@L5*p-T28Lks?}zsAySv zf~b^I8ZaPORv!o`RD=}bhOJ$mkVHd;5RzbHapgf-YggNanXPW~eGSfjhK#*GX0e5q z)@W^Cwz`cn-_EVRYgFEit@fS&T1f@-`+m>4t|!-Xa^D)5?Yph#lRWo*fA8yD=Q`K< zbDzK0vF)y7DSTc?;d8?9vF*>XX9Xq3dKf2otcPiWQy#1TYJ+D2OaH6$vdlm84Su80 zGyhmTCwM$=)+M;gdAsnsU2v6C@w+1WQlY;)qF20IaK`IhM$Y>TKFQ#{5r55F4@UeI z-(&dvis7?A;=}bfbO$3oiuXmh%Kv1=@p+QIMdhaS?j|?|4SSC;nl%=OrumN`JY8yVT&TH#|&4=9vCp{P9)7={`e($`MXTQNoPupR1ef}3~&hWfi?s@5#dzJqqLVwKQ6L7yv zo;BT+ev{Bolq>N%q2)#AWt9GtLZ|U2ZpYJF3?It>8F_9q`1OW=x4}vOhw^-{!EJo^ z8=Ul9cSYA{a6A5~^BpR`o|SXV&{qZ){`a`Sry4vf1%!NfTP@Ezuc7$UWxoh=>U!U10Op1R-D$%>7oH70! z@=^a9|E0hfr&#_&+`JE``8hld`Pb(f+$4p+>jQxzBMM{q>_aDCM4$3esUDiRy_59fx5)3v2Adc0v~ZZ%wm7)-1?zB?q1C zvi??WDI9zV!$RHP!M`TmJe=9ahR;wS~50(L4l8x+!JL>oAzBT08>fgiOHM?)V0X)fr zb_y6q$6B|8`>&P%G2C0*cE{Xas}f%54-GHZuDX)nLs z@6Y|08b_6h&)maLc`55;*j?Zr<6eX_d92&SE5oBr?W;z+fs>%gaDVvV;J%Yv9`*a- z>6bJow>;+eu3K9Mj34*h(uM)gavQif>|xB0a{CznKIkkn$~}UOgZ|6|>P}^RRQ6|H z4h-#Z?9U8)=@{OH*q=$iIoPy+1?ii^eb*HCy&U%D<^2B13wKlhq|FQt&M7I&9+<*- zfQ}d{glb2d5ZIqfyA97HUc~#b{}p>iAEDl~{Y|c-Ati;V}MBdi)pbXm}f7o9*VRt8NEHJI9U)nf7 zx#c@PJkspDvt&mz{4Pd5dA{t7-P^wKD{NZ%{7*im@bi3Q{z%QZ-j}&wSNB;ejXsBb zIb?rAZ5z-AKhsUqhIS56zjRN;zRLl`g?nmIg+NCa`ZC4+v}e7=85Fc>ui=LMw!v=+ z@*MNYHl&BfeJ|qvIO6#LFrERRXC1u$#^4wGun&`IP1+jB6UT}BG?mZA;KO~g-1l01 z=73KRf960)kFx0@{4&3{vm5?$W3mS(JGbd<#EWTZ(<<-}d!lpajF9f4k8$ssxH}3m@oWUxC_#P-=O^5Qe8TWh ze!WgUQR=Go9rON=kr(v2q}+X2@7=iUfj)dcHSF!Qa{{{xHvGRm9&GN=kLsLuDo|e@ z>0@1t`n%vCa+gN_D-h?9W<&Kb?M0yOIr1W|)C22m#<3T)%$GeVH&;1#pt{@*{0V3> zxW63t4|;mo6~Hy(tm#;Z!^7lRt4)u)`>qux(B;XJU1hxRWEEz;JzFGJFxG6 z741amb1!U_sLhcdqRxD;*YD6?a(-8a?7fv!Tuo_CzMYj!P(0 zq29w7bz%R$hFuQZ4VtFh_y3r&lfd(6P>&-nVgEnNFYOR9Pg3SfQAU{OHlXZIggt`) z4f<`+&lG&CgZ+xq-4DP{7Ug~bwla|a=Tx3WJxtpD+)31pZwz{QC<|%62miF`qPCWD zCkKW8yxmW+E*;|r`c4c!@(SoeT|zm6Z3gNk{}XSwric2?4urUqZ~yT@4#^aBXWLf2 z#-;(~I0)XP%^{!W(QZQg4#42l!1wV@`V`)cB>$aiezo)`w|uQA?+)eL5}$8jm(1r| z#usC{`}BLS-+Ja>^q~vi`Jp^Jp-?v$=h@Ik33)br-&ubJ{RSIazxQ(Xp+ANGnbvoo z>FO$x#x|cZT^rD@(|RyBYAByE?>+~;h4w(mmpSOXVYb^r`w75Ks z$kWh8=~Ndw#xg_^?v#$>F?4o5BOu{d`B*IJ{_WPw=Oqx;OIm#Ij)Y0m^KT2?TcyVh zs^Ez4+x>X++s*J4`KcaaZ>sMYPg6@;{?L3C^TAk4qT{$+l1od^H2W_auQE59k?55eAe#+5wnibg>eEV-_>?uHMJao#Klt$kb#DWv$kGbR`hF6``VU$=I1XY+6tg;?l_VWYbV(coS@ z9FZO(AP?d2Y6P{;i|sZ-EPr+vZ)z6$=YI@g5Fhix0zwZg~=m^2^;4jc`|YCbOpm5&-ssMM0WgM0Oq$Ixy4iiOuL zag4~!LiGGoQ5>&tMSOVhy}$hDKl8p;Pq6=ge5!pYLM+!m&vV(r)VkIlL&cV3?A8X$ zVR^;xGjVjRU-(%he^dDR1KiP; zON$^c%Js{FuMxh}1m7umUhpo#zbiNgI_YY|#s4PRcnR_h|9U+OA0>XaDKJoZ{;%Mw z7nO%pZ--5oQpi0n1X=Wp@x?^^{1kj<3O*+V|6mIK;S@ZVg14vOx2515m`#fBms0Sr zq~Np#LE8~}&WX0eVJFtx5}~|w^TNf?2_}X6y%hdOQ}EYP@H0?8lK9gmOcMTH;FP~f z8agWfRlsQr<=#mCRVjRO!ly0b)0sklhtTUsBtf4AUz4uaxpOGMY|D*isuC&g=i3cfrAuS>z3Q}9m!r~F69 zgp8^3d=5C%UDtGIzWwh)|6)Y{u;98jQ2BgE@X=B~EB*t)D0r=>I4Me<%h225{PtQK#RZCj{5E zMT$QqxYjd@Ka;}$$0<02Owz-+6x`dE;Uv2;Eu#(HU})y%=GG3^)Ye+xxE6N)I_rzy z4z+N-6&i4A!-m2aHo}+yGNBjh(&;P8Re8`x|KK)_V-6H2Rr-#~b>D z<(lEG>4G_#;ubW_Q3O*mQA4@Dv4sX^g1GfJt#7#5HmiMGy1rp^m$fqE4bIT2jJLJ1 zXjxsoSihhJkhL&-5nHRdX32^rs}?Q~%)Gk1QIPQLZMF=zMIyFE;vlFO1`*>lb@Ha> zOT336GdA7|2s;Y(A^DoS)VnofQfx4VYPV5YtzL>uo6zJ-q+`=h331j4czNK#pKcj@ z8j_esaiX^g263RVRyD^Gf-y?*Q7vRK^q@=%ELl;v>V{w(#YQh6akvE&J3}ub>5ELx zScaY8ptJ4+JQh4ezp(kkcyP9TJXyWIs$jC0D3F0t};iV|4U`a?LBW8HRDMOHw zQJK@cfzbN38)1_w!NAUtj!~*nA+-5=U?}f4ZDuvnR9`?$s`3m{7#3~6jdd4m3tW(R z9WBkMRj^=4tF%y*u3ofqsBb>ef51VdlC%b<#ZW zwn{8sAq1r7B#gR=a>F&x7M~`#^4IU_3`0-;idRMS(u^yt*Cl__E6)BJ9oKSOTOUmU z_O?4n|4w<N%D3B3##$lFxKQuk9-G(K5x?`-DIFSbV?W7Xg2t;nOF$rkB1t zD!8VX;_P?ODZS>E7b1GaUlg43D@Okrw4do>{#Al2f0ea5qE~#L;4%MNgL8~X9s3=0 z%3sUfnux#RIm5^1Pqp0<^HJL!8ZYJ39feyH#3-B-sPu~WM)X4N)V2oWTd5$fPYXS9 zE9X&zPcigU%fo|)tFNXBuJO87Ud)K-7022T?_&Mm9r02AYV#ouwZh~vwC4V~&OJUQ1N@lpI}ME^VTLTyc`oQl6H z^l`Y_CDU+wg-^M3)s&Co8Nroa$er4PP7I#c*` z89rAi6I^w?EaroC%ib|wR-WyK&wRt@KEXBrXnUwvaLu=h9~7MW;aq?^wT+;BUXmBD zMtl@MVfb9COmHoip>Xp5fWfiW$~)pVzfBWd!_|B>LvWQ}akZI1J~qGA8vYARxH*H{ zeAQ;~sfPY`gI5|HYlysKxE8mz5$t#5L7|W1r8X1dcpWtSZM>ckocYA=HCCGm%qJE< zZ1~vxueK3ld5#HvEYAtU$I4SaI_QD&e9-7;tl*T#;<|T)db9Fmgr4|3!$-$w<8pDM z;cv@DPVl(>)+9Lj*!EtF;bU>N$uO+Er|{`a;nO8J`4pA+6h8SBKHCi+Ti&e=2W=Bk zeFueJ)AtS0X`kSlzKTB?(T{?>bcZ8)#h(#8&i~`y5&RLi`G2axZFyJQ4y3pFWU--N z99a6_rGhgZ-)rz%!I|GIZf!x>{FXEP7a2ZX2Cp>u-3GVy#(f4~V(51n+{&|Ga7~wg z6h8+A*K|?b+HkPtPHi~EdY(8YFeGm4;ROb_@?hzOcQJjJ!LJq>c~RR4q`$`CJ%--u z;XZ>~J?}NRr9WtJE9W7D+xkK0IhY@o8F|zO0`r5#)doUbu66z+=JTqA8}m6XcwDY^ zz9i=3&I-cCe98qUA6u?;_Srad-pBBNHpKFbNItABqIu7sYx&+s9 zs`%{@{e?oGkLVS@E27T`y|pz_8G`h`PY6BbwDsz%2DjzCd~EPc`c;O{ID>!K;8P85 z`BV$8@l`n&q|h%HT=jOD#H%*qqxhN>J}nWS%Y~2bfmV4G?@ZxyU&Kf2)n37skKzv+ zKDNHy6Y;4LdG5daVcc8eGR<2pu*!>9rns+TfP{ zxWP%U`CJF~DL>a-snc>vob+10rb#@ATmCv;t@K?&SDQlLW^nT7IvYCmM?NzGJjd`;Yv^rzqub!TRU2*hM!2rC)A48Ww|tIA^vVZ|#JnRtNtBN*7nJ`wk$+qu zFX-W41kXgc>Tz0x4+_1u!Bn4Ti+tIL{#}CGaz}Zl3BD$xUm$o(gs&95Ey6z{cs|0L z1-~o8bzb4#2;U*}y%GL^;CmzdVZrxD_;&<96ybj__~8iuXTfc`J{L3^|F~R#RP`@c z>Ywy$|1Igu zMsGi|)m8p05~pqo_Eaw{nK;)~Wd|mY&c591_h05OB3%ymyyoTVJ`zOEH zhpB?e6>ifu>}lQxK3BO}MSx zuG}yF3if`V-17J?hoKeffx1WBr*9K|-hsG3fb>PYt0`}PS@~|-W7(RRE?bLatwg%# zp`U&??TX3nwwJSzx4$f;y{5IwPJK`>4C7f``(clT;XEVz*%NhB{>h^7(s+FL&3Hum zMShidB7G4468atOHrf1^fo}59XNKurzR>4+jYqNGOLjkiw4#ogpQz_qNH^wH=8ea| zW9{_pK>e#-FE50hfO^J<_5w;!o@O%bOJ3TB{Kh@PkG+$+3-%_mCC9J8K4R!7JR|LT zn1A|_=QKT;mXzrP!o&M+lxL)aE3!G{rn+;r3}s5BEQ0ssjN9}i@*(P`?n-oxN=LyS zQ~8uXBF~bk-ZZ7>$2{Y(_nCMh-m6O-Sw#5A?%l z(ztP1*q;!42yYBl)1J~xkejwLu7WHr@XtIM!a3;kb?*d+Ix55~kA2;cWBkc2Pk6pN zYl7V(ti7I<9UQDx`6EXs4aMJvp=pY5A4ClD&^`)m z?HqV?l$&+iTK68*P2)c?#tkfT7foLaIc`1Q4P>F$%ORJh|4%-;=%FNg2aIy~1?{r#?TF8v(8V1nZz@}FhvZl1USb*6{IwG{ zzN`%cma7cPG41Ct4$uj06Ahrj@yKS_D)?X64#zZ7nbDEF66OxZ7J+ngtX4l z<_&bf_j%-p+@-w#(YJFo5UQcTI*exw2E`p?VE4fKIW9&-1d?`_)j z{3AH%JS^|%1K>+ zTj@%7Hvnq@&q}xT;Rfi$K~Gy}4(Y~zN2r@Vk@wM+tWQ5x6yKdIkyo6%<(6~9w}3KN zitY=#Mjcd08^0aX``L8%1wmHO&u^HmGW}*jCiTD2#5Fh94J3pY^SiEL zlSh|s%9p#k7ofAr<)xc?%Um7x=*r!>z0gA={7xQQx~UKNi}JvF zDm-s}m~EtR|CcZAG4D{F$b-@51={^g{VW$9^CC zO!X+U?}NM!SUt)t>Y(}CE^-I*kR90kOvX*m^BH#Juu6H1zeha*`B4W4TQm)b3+)Hx zrSAQq)aiVteISMlzP?Up`-NdaH;-r@Vj0PUC+TQQrXDhX5n-|}rX8Js#nq<6jd*7L z9DjG*ROTaZw`=-O**-7HUcql^2fm@tA+O&F8&wUElkG@`#eDD?d`G_pobUNAEAQA= zKzT(z4|;=)zU`Bx{P0^gnzjeehrPlfn_jfjlXH{5UkN^Jv&Hs%^qc#Nv_C0tEaSJ9 z4wvyaAY<9G;WASGP);7-wfID_Eg_~ezrVC$MtS+&(r<34lce4$b92}>A+N;ET=*bz4|zhlt0JKXh&tF^c*9iPDkoEhD1Lj zbvkC$=vJ>@o@rda4!eq6N5^`(BiPa0ert0(LAhJe+}Y9C(AJzWZ(BQt-miZDb<3_> zlId7?bL+a+n_b6-b=U%l2PZF@TN~SNYwP4bHUCbYxr3|V3455lmxZmjWoj{~wXvhw zHMHL5R@SVp&9pSHZ-Yb|8#~(MwhlpLR(CdRXe)5&WT-?uA9qbn&6SyH%h$Cwv~SGd zAv1U8?Dx&Cnl*RktXc2j!^~M3KF-4bn<$TI@gKqVg^u~6FM{$`;`Di($j&{v#L=(w zE+FTKHPGtOu7XBs^B_zrSyjd?-P2((PjvIq|(UZnXU}sFF!E&OQ6OH--6??(r1*zYzLz zQQf>i?tYL$Pg@h@zd-0UpTChpPg@hD*F7k;!haI*B>ATbeZTP6@-iodzDDR5NLE3E z%sUL+CGuaJf^SH{J5z9$AI9sjWR*1%FV6iY#p}Nby{<{u{Q2jCSMkFJr}!bk=S6tG z;MoX&P4K0HFAeP6IF!#Md8Vh}b5n5GsSfEV{GSp2t5fLLrQlmraPHMglJiR`_?J^~ zo=2R-=THj%_bK?lrr;&Wmr49HDfpZe{OT0^#uR*G3jSNbnGeTuQVecyxH#_NN|KX% zxJZ9c=yO8lIv>gY*@R# zIcys*Fl1{f4xL!NZ^sk|;+s#{2=3ccktejElDrg}Md4-FoT~XyQDXxb*Ee@{!q5fU zWgWCW(XqL$ZDV_9b5lL^)iHBc^}H+Qsm!hmO{>Oov3l9c6`r)QeO>3e#)kFbUG4R&YFDma65edw%*N;~^{tyX z40~I}7k-2NuvZMZBN*D~Y%ds1u$)1#4iUVi{w5f?EB24A_z}@;36_x>TY1`b3_*y}_!2 zd6407h+&M^ceZctkS+W}30O$jz`i&EHm?0R43oH(i#}A3+u2BLf4{b)xuG5QLxPu( z?;38wOK-YjWli0Zf@zR~j)QrP_H_;GS8U#}7EN?d3oC$2u356m7dP|{e$=}(2;&hxb?sL41Te} z_Zxhw!L@xh0en#P7ThyJ|LzEX!SK1XK#e+HJd+RC|EQ}F{JaRadyQ?ly4N@kw@Qep zhiS?jS6%B$JzQe&PN64$nZff0=fIh|y@JPj*e7@_kKGHbZCmm>Zuq}fnd3TE+J)r* zZiCa75gqko@kxSH{+WTq|8^PN^4GnwG5@<$_}^#vR2lvU4Q|7==b={``hG)iaouA} z`DYpWR}HMy)8<2!(WofOQm~GJ+3$Yb-#6Gk43KV|4CXCL^{J#FYMe$>!g{k&js zTds94ZCtK(FKrwzyO(xO5XJviNIO2Jw|iYbVCd_Fp8C&iuo8O%y*(f@^vy zu6tuiFUz{Tk4{5xal2>sSA{n(x<{4rTx#%sBd4veMoY(v^q5yGxJd@j7EtG=8hoL_ zmm7SM!F6vb`PUfyZbQG=;JpT4V(>i%zuMrscar?CG5917Si%us8gBjX0)t!nCWBl4 zdfqhoEHiw%4ZY>_l)*n_=wC3nr5`IpB;;??Ym(sHdv&ehGgWYo(^!0(;bZgj0)yLd zTMYgo!~b@JTY9_q(Bi#@e!1bZ$KW^Hd04^J8VgNBdp-5Zv^X9c1duS>z33~u$T zd(Ft_Iuq{QhW=uM_ZZyP1NR!-)&u(tKGpE)Gq|-0VE3BYe5mLAQqC!ckDlin<4eZ| zBI45wz3v?&ZslCS#kX)VeXqf--t1l>%m1*Ux9R?j!B>Q!{BM=?x8v_@wczo0cB$Z$ zv)1rwO2In~{$4}B-QbrQ{3*d>d7c(Lmgfb-$I3HW#tULOs|{|;OV;34Z_5pC%S(^J zZF$kLjS}dm6!FsW3jNLy=XY6(o6AVt73a7=UDp3%tXcTzIK9@TN~=(y|N2yc|P7d6D1K1*bVq!29^+nvGu;0v^t}=O4}zb@-jj_@4V?{cCJpY-+QVL^Wa%MGn~-@F0>C>#}b$9ByTavKCWp0R&D zS69PR5AiemK;$XKLdgo}@>Ug)a1;CgAmAkVmx}y$-iRDx|C}#O(qEfY-fDx6`ePcY zf34qE0Au*J&x1#I{9OLJg6+ca6li&`dgT5@-pBFmA5W^{zAvBEpI&b=7~iWqXM)}p zU)7(Y6f;gczB~TDKyhoh6ne2&wO#N#CVLuUrB{2W)}Kh__csY&5KeNpiDM3mv< z@G<7QuJxvkBi<`=MOF2@jCUj7D{{!MAPMqh{YB3e-d8viZRosHoZpBu{l4<8k{w*{ z46pu7TAp=^Jk#BabLT3seg~1>!SnulFXy_x3wMKU&;48{j`crS8~0LfO!j9D;qxME zYtqh1d(y9AD>?@i>z`oLes?dTFuV0A?@x}xIy|hu?!y`#UKexCIrPHy)(g#=Zt9~6`sjr|kp4wyZ(^( zJdbNMkBIJic!u!=H{rXe6nFI2xPfxSGlRVwOvB!5ux1eH^vB3o4q-8jeyo*VbOG1s zpN~8f(wA$)@>qYj9r*LWc@AAA=sP}@y+`xo{U5&^O%BQ$)@-6YV67VbObmXWJEvII z=Rgs^Eu3A=i zLzqTcSW~lP^=fxbb8B-uW_xJl-UY0F@siawtCrQ)VS>+XXzpy;*yPwc^y|Ieu4Pz0 zE{xxQgtb_Ai=wAN9vOF~!%x!r zJAuD6Bn&NYlh*bGTn0Rb(T|A`=YA7NoOejHJq7Ph!T%ry=SLuk|JPFR$5QaWNx^@R zg8y?0{z?kYzFCr-<5O^sS#u48<{P$=>E;6G`5^PcW8u0yh0jNYkM{YLPkRb|Ug)*Y zsq|k=q31b4lvDcxO3(bA6yLv0!H=Zif1iTm%1waAtBGl=&` z_+O{+`QItHKO=yReZK}~-RxWIlPhzc*^vAOt3eW96wVzPUiIrqC0rAMX%Eun;aXqcvVC% zkA-n}rB{5p+;GfThATYMWN;aV@QAK0CcPbA*k$M|7p0LJ}Ku!q2VQiXFB2+hFkwzoq{hgxC}>ldUitTVtqCldXCGf>lB=GYg&i$ z-R**N?A79V!6_&Dhy|zLS@MzLJ^xO}P|3&QJ;H};MluC1u5eCV%;!F#kNNZ(K2r=I z{r<*$cBSyyWB6#^COiEu$9(ps@Y!$paQsr;QNgJ7*K#d>QKdQC6Zt#qA&YkDbuyWu}0kow>42DkM_PYSN>I_hnv;nOSh)SJb1 z?HkMW6hp7=y_nCQ6h3RQTOPGN8S{A}MV>>3PsYSc*XS|5 zE;qQ=?d-QOO*DhMqY4BXq~Y#q+m(^!pX_nI`@eS3cTCCq7zu@}lho;*6JmgRLG&KaIq2 zE#czjA^kjgK8-oIqPe#Ajq&VT`^I1R1RUa$!9P{V`5o)B@^DP@rM@fI8@aL$B$kzD zz4TI9a2e^MaSnvxP`7lNe_3XTN5MER=9wb_LFZ`I=yZO6?ioo91m(Ines~A!C1L8{||vY|yTr z0-7ZM%TEl}(T2lYh4W+3ZSyjQc|?YN9k4XMPYw*${lf_OzVBz?i#V&Sy#wj8_W#}e z7kvjjt$hRPkm>Ur^r-RExF}D`O4}2(pil^H@_G;ESbvIiwOvJ+1sU|Og=BaF<6JHp?f0coiQfRjkCOWeE*Y^SJQ4yzs!MS z{`r<$5YG&-e?~qbuJ%qi53aI3TQ;#MpKW-3ux=sd*{!U9g?#@k=KC$ivak^IqZa!- z$`Ngq{1D+mR@Z@u|03L`Ur;#z;};ap7k&{+Ll~T^_(iylzo2l`w)@XLPM1vYzz)yr z+t**2!2oA?!lpYsg?n1W2oD@N_3ea4zFOANvAMaOp77u&c>hbz$!c2*b(Q0stUfQ5 zgkjr~c&$8Z-{e;XNB!-c;@1hjCc=M1@EZlMm3+2Aa2>nL$@@pQYeuAbpa;y&wgzOu=WT;AnRw^8Z*0z99v_GXv@Q@b!#*6yp^`qqtpC$FD7^ELolH?}r5d&@<5 zhg(0%H}poPCo!uin0gm}sPeG`yTHDoadYR!n{Em~*v4IW7eeAZ-w^vDpR`M`uCbXL z*fF`gp?L%642SRR_H%fgjl-tuWh<@;;(4+a*Dqi0g~KYMs6lY~W?~k*peKbiO^2SDq#bNH?_c>O(9}|oAu(yu zs($s7Rll~ZX36rEHHArLuV74Yn)&d;yI5@?^K4*2YuRE_IUQH$*stlr7ru8KyS8(A z`n@A=$KLgONBmu(X!>7%m*_a=uj8P6zK=g}9P_vMg8?qk0$=}Ycph@7J@)0suF1X66IQmdU^t$a}Ttu(5%HNOVH^@%`6&KmM6V+8`$nhq;R*YV1drqOg26LNjH}LRYW~r1 zr{TLnr~DP?cZ^Qy!xP3tBYMT>2_DO{+~Ac;jO+G@zlN)Gov}Q3NA$|7TX3aU{9Y5T zEvI`8K1GRf)w7!@zpa19V(^2G_{HJY|1LGSt(WQqSG{R{w?=T4Q}HIlXR6^(yG?Y; zCp=-0BjTgD&iyI9&U@{P=oQyFzBs*(8+k5K=D3!ZhX>`qNZySWT;rwq*ogibp;x;a zO0RfE=qV59Pt>VBG~$;jh-;mpx9Qtr@Jd5}yTLWD@pZSs?cDTe@mqp$IUk~~R&Izh zD``Kc&ER(4q1WJ~*YDQ;2$#pAeS~&yG=uQyG~BUd2B-Bc@#+Bi-@79EJ@UNE;FkVH zgOjz=kCSl7e~#h5#^AiYQQnP{tIDbRni%2wUC%`LVd1N3q3UH`0~lEObG z;kRjeONc7J3XnE;dDr=YLi=%yKYNYpU*o?NSW@_Fq|4Y6*c5)%zXCP5p{Q8}EPU6Q4WrTR;oyR4N4+wVlo3H-PZb=S z8;Se85NTXhXR%-9rz+CAJf>4V@%y;UYnrJ4p+&dXF1Y~~_@HMF8u)=v&T$MnX@3I0$#Gtw-`~JL`KW)rwx`hNg`E9Rp# zF`o(vnS5Ag)MX zngbrm8l3dXYpKDNC!rRDlU~Q0+6->{u&PgnE6qPoS!L+Sr{HFG+_nKGV9}=TY!BBK zz4O*JI$^idc^eyU=Gu;q;j8|JBmWWC0c!j;-kN{)nPW)AvI@vm+oBohla5Ub-fBMA zv`TABYdX=db;7OyF@KR~{9PTX|FpKW`tK@)6mC?0h11&7qa_n{3nAlwDsAaw;%}Y? zB-c3n8sJI#SKEYD;*a5T8wlx1$|C)c(+S0my_I1k?_i_06Otx)kXzLhhTNb)$SJELd%o!s&_VxM6G)>Q@C*RW2A_BLqKfoH@$hc!tEzUMitB?@@3!SNi{5Yd)` zo~47cUoU{33T=4!K`{#L`IB41IgngiNO`%&i}I2$^6WmYWAy8oz>k<;$Aq;~TxW!_ zx{4;8r-{14uQTLYtxDM6$YKo_Y4I(r;2I~j3Bt8x4rdbOu~w1tkcadudbYzZ$m3@Z z`B$FgbI17XLn!OrU&30(Ph-8Gz6)`3JNlqg(mAs}jJ7WH9LqfPlRq(tY2HAG@y6YG z@X=@Lb#j?|seEGgXU`%nV%Z*q%?qBD$T0e`?k#@Lb1omn`-wL?oVn_DbIp~m!+IEa zT*rgY+v>Co#Y}k)(J#``9s}J-!-O8a8y9(q#g5+>%6Oxj;b$+ebTeq;{7Q7_8fjYL zN>{sb`LdcD>aSZ^TZ^gM)zP!`{}ylD(6FwxcH{bWjkm$VyPq>I!rrEiA>;Y~qEE>7 zFxT~{yH9Q|7JQ#P>--iUllqWXcshP9mjWXSh$YVelyMB>sO5oP2iSN~e6D#eEX}zop>(Mkdj} z16d&n=e$S~J}m{WPQf`po77id>G9!v`qR$OVP7|V#0#7B692cDPl%{FuP6*EOW%03irXzp$_tZ@?xYhFv!5J^R zj)diqj`6ZMpXtbdQn>ZM%LR|+tQ9<#lMNxdSWaChp?tI-pNse?-V%kYd1ZY>uXtNT zuW8U3(JOwt;FMFxB`EiU2Dj@Z_NCy51dsKs>mg!2KV|q>J@*@2`!$s3SPFlg2aWl^ zYWP_GIzP(z+VwFS7ROwe-}s%U%lKb>lY!fElr=c%7s>NdgHMrrURn%J`s?Mn&ES?k zZ}5!V^Ri#=DUWUI^+mY0PxRYF`q4tei`G|he69SXpC*1<9qs6-dobE;*1vgSK73(r{fa;JC!iSKf{i)xTnlY__}_Ibr-`@{cF9M zHuiLvbWJuzk&7OELko75Mn3j5dv0~cyOGc19+SMth-LYMU(VxlpC}%>@xS9F_MdS) z=gZ%6J2(!-F_yJon0)*>*<;7Om~!vw;isqfg5qePmg2F zhEC^ZF zk10Kev6Y39mnDM-oYkqpv_@v(zCG9`V-*WF$T5>V^=DN%13>SbnJ@fh;!U%Kdub( zZ*YZw_gVgoz$u;PNzL1_*Bwd_zj&LUHJEV`-?)6n?^iW%+Ptp4IkTjz4Z||)Ix{jn zv#hmc-P*!q=DN_687gv(u08lvkK%7#@E4xc*ISGlnRCbQ$7C1yCr!b2l62G!A*cyt9e*b4(SmYhQ*GOA(WqJfqanxQoZ zL&GsL=re4fB@6-4m>`Z_6xn#5p~t;!2_rB=Lo595ceZ0V8Cz(Q7BFZNh<#>h&UpQ6 zJ>R;pAEx77m@gBj+$I5?S#HU%p?Tz>-zAK{NAoP18dd2rf^qoS#FQQlc zpx~6#j=`yJIYz+psQD@*{D|8zrmVq9ulZ`J!7aU(Bl5B3tJ~1qHj?IB(i7MEdYqxx zI)qS_!70yg%JVPF7{^o4lXY6}Dwa0J(JxIB?JHAvWTm>*e8F}TakTM^9PKM7xk#MU zwdy1FpEky!V>|mJAyj^aXW@oA$tob%yJWC-mpn86obglt8vmuhlH#v>DCUWOy{LbE zuE9-G_*K%7()`QtPi2f_v?Pd@BMndWuh+COj(f%b>5g%HC(aNefQGB`@Y|L|nv?k7 zse~#1$uB9Z9TKLR4jkiP9ijTy^m_-er0{iplddxYnRl`LXz{e3${5GI`Bl{!??yhx zamWnTXT20z#N}+{$NZ6ccgBwzuto#@d~b8BtfhJ0RQzvs<+o&UcFIlVB_ICIBsczt zO>R>Q=o<6x+(tZqI>NUD-wvGqdO?@r+K{RFkI<&j#W)A$OE|lP>t+VORr0-)TS^`} zS;H}vQrPw4x}LI!UM(xbI+=3V7CPf0+V6S2W7I>hmz7S3xZWlZZAL-QehdRT#Q2HZ zan#!%dKbnZf~_NbAN}|U(#G2kIv+CVxi3G&x}a;pgL0kRvhbl-RxiT(oSKJTYg~*l zmpt@($JGx(wjGogV;JBW&Wqug#`9$t>|T48J6FTi@U~%$CF8OOCQovkcAg2|7z0t7 z^MF_2S!o}g0vhNu|L*L3rTNVH+4-LypPm0(=Va$^ACsMb=cw%bJ4&GbFa-KN|i?IKOw{TiNa_ze3QVCt7^ zdDN~N$H|zcuVM`AS=zUPj(#%14g3VQqi8ox)9_P+gI~<~akKNL(~g$nUBG_=+i6Uv zV6Q9KrJ4eLE-H5)uCH*LrcH2lcAb^34dYrNS!=~=YlmC2wreelZFX1YbC}ur{v3?k z-GeZD$7By6Z_ml$+KVlBShsXUU$J%yaQxRhcgxt(7*jh3wzqE2-m?=|#yxi? zx6$QSjY5+z_&v{$!R1d5&drn-+q}{>Q`v%O{8YH5vS#MPBTOoxGB=?18Hg&%Z)gl{ik8VeEXo@^j?J ze9(VJe$|t>ZY{0&Q3mqeQHpbj+lOJP(B70 z;`}3rcv5$$boP~$XXjsa5aprV)txswJO9ydx=jmlKVhufL0XMVFUBszdbf~AGkDf_ zeWkAY4#ZpacQN!zy)A@{lU?a8*TH@l)6DVTm3}u@>OS}9kO#f3YhS{ZG?lRDRf_lD z#&d2|e%0^d+KX$qJO_JdL+kl8pYiOe*WTp@5IMj8ko8Pn)(*0sxdk$89fk6PI^io* z0!<#WGX7kj_+G@7`3Ik<3i@Mx!*?an)gL2GnAf*LzQ@3)6nc9Ow%sz2OKr8i_O9%J z<}0rM%M1=avUQBxv<+#v8hlwlgz|a8?%6D7usJvx`Yu7)z8vq5BYu&R zA^#S141dar!ABTQ|LcR$|M|Or1w8vuZpgC_JZW2y`Q&L_9pwBzuc(I{;)5&7$k2Fq z8lH6amyUz~4E2dWmknoo!N0eW*N6O!{-r4`cax*q+OYt-n0Z*Wxp-`&b8(M+W>kZq4!PQZK^= zC|}`SAI8Y@Q?m2((EaVmS3Q@y9X|ve&aOMsg!9X^4tJej4lr(y z_%*s0?4H5;3w3V>?sXSX?gi$ncN{=MLXy5zv* zHK-%~d)kq_VE6gVlW1oY(%F}hFi(MSR`p$-^>VWO{VDP{;eoTeW0~Tiejl>^7`xUAF-T+iYm)^4I@j>t<2E zc*n5=&Y9@*(~{sEBOuu9UjSls=VTuDqTDN ziQkQe9bKMO`tYQ9QKqu~^Pk_QQv1Ux*0SU8eZ)RK$n~Uo?-B!=wyzxCm zlhbfG(+ihY#u`^1eHI7IS-%(?HZ2$vB+Us9izzt|1HpP2=DBh9Q-kpoJbDcF^>k4; z?)}>A;yK4*yn=Z{uM18*%7zr5)_y|LYp5Pa$hY5ywBL-`(t_UV>0w=KQ*&4S+S}?^ zz|KMOEAPo*OIFmay1{$$3(1+^q8wFFtQS+YD)tIx&G>_ozvH={y@GSjs6y^}*(dj$ zGqU)8!IfT$u{#*iEB>V540od3^Kw}3m5;u9N^atCpN{Bt?Dv_7Uh!js$MMaGV8kyJ z8eXadS9v)0N>?qo%A@!K!^g&}F5+``VB^+Ad=zgnd@d4NUb-Sa9F(KGJ>sLd&cVfc z);Tzh*OI`da0ZvgOL05bX61P@lIK0bhu;A@<)iph5&eunRS`fkCMUh$_5 zy=`qhW9ThDPC6!(6XUQ2S8Z@Rce&i)mj1B8&CtC&nu0HvNjZj#{&&H(8Qk)@F9qL| zg6}tYrobI@v(kQMxE%0Nr)R{(_}zxymg{n9=aAmwHww=5xh$FS^n<3H_51z2eUZ9;ffPGlR!C9j6)G=FjB@uQc+nH@MbSe0{sY zryKfigTL3{dkk*FJuJA!cZ2wON^sSW;ztc1tqbYp1%ppB;T})ne9zQy3A*Y-`D!K>w-mu`cT{xNyJ*Wj4gDY*RxC;eZ@ zbDzO2{b7S&CilFILpv+dFPaWvbk$YaM3{H8vj&o7r0{o1 z!?$%E9^J&V`0L#F!lm#l(eZu=a@>%ZmQP}I|04cphR4Eh?0*a1C{`fC%>{A7$;+7b zT;Orqk#wFk`aUQA^b-5$bDVcbJ5j<{dyVe|#(F>2AG1kP_|qsD+?OKearo#iw>7RS zm}|_umA%Hxub5qx@$MAXz?g=5)=L%k`9N;0De-edTr$>;x%dIRX7$>Q9PRHRZ+E5K zpDKMES0D5UepJUJAWbBR!%gF-bmJl}QIZWC=Q~}0wX0UHxuL#h$*MXW)^PR8`Xy`X zmaJI4Y~>2q)>zxn*|NO3_2$l&n!-?=Yir-wb(?HH37*5^b=T(i;4g1zy?JxP&CT-o zpJsnas2Ws@#mY~b%V6D=v|ofpENQ<8>oVfC^aiI_-Y4xN3H+sjN+RRl4ttbWgCED1 z)oIoC>j08$dfW^=&Xe@J8UN&?{`LCl6#5>a*ScQmzm!7%Wuc#nE1lAR8}~`_JO!Nc zRFN1?>0icu(mt4XLItE>;Hih`vA)gYOCua>);wMp;U5Q{B+n;P@Xw~;VLu8gUp0f7 zT0nJN+7?2^Xe86(&OUH-({JJMn?^v2VfChB@}bwXjalTGL&rm}`Bd~eY4~|anxuLr zcu#mkIfo=mAdrv~-gxt!>5PYjGy}dqQsEGqf`(#Ko|5ReaICPO3C%qN?|XR+a9^`qrC=CeG7Pp#o&^`qrI=CdY+&y9wU)sLnZ z`<~1LIzF2bdg69WGHY1*XhEa$JPhhGvqsX2|WT($mCnB(fivI@wxUzDDe1|jD}kQBrE z0GA3L_XB!?Cpq%4ZU!DkzL1z;-8T|aGww}{%7D{{cHJJ z3M?u7tVFa;{Od*i>vIimlEUwo@N+`Q@YzaJ{~G>BfibAK54%^w&*7bQ0((EiKaPK5 zTCRxEscoFM>ce(`R(X1l^7FyCBO!Q9%epvDJCbIl-*%_?(@X51&q+aPzE$RI=dvFg z>o2Vjn`L6d{r4!q=uw(cY9$rt47|me1M_B|`k4dA^dk#-vJ?uxXJZ}E;GLD&Q{lX= zRN9a@A8S~{I{dI6o_i~3PvSV&(Z1Ie_9(oD_4#T`6!DycHJsBO*Qa7VD$>I5wRjNr zQP)nunbBrF=~`ny^rknlABuIG(_eot*D7bR-(n&5TP(tUi?IF{GW)$2Ib$~zX*7_- zwDugV&E%R(m7(dZV9S(iU7>gM#oZ2-n=&Jf=k#M8bszkypT#)i`T@v&1b%{@iLi#; z#}Vr~m989iChh>;p%mV|uMf`2gZD(pl*RgahvD>msl(cPtSQAhUgfh`Y-fB0d~Wq| z3Uc1z_Z9?OubI(q&dxir$7DSACV&s^q|$#M*0nbxPEWw@#T4*49bI=#aMhHPeD8;R zJ0Zt*Jl_hwy_aVP?t~2xoYlP>mCU)@u)e&+m7JAFJ|R8yw{IJ09{}COE`K0X?ywg2 zg54;Q96IXJcNzFYDLX6U+<{8?z3NbA9@pNI<{pHn_j&Mo9$_^h&){2r0Bd;%xX$=5 zjgB8Mdg;f03QgC(^Mh`<2D=|}p}o@m5$tFAI`nn{{FJ(FICuSB$hX062-YA^M;Mzh z*If4)*7cT@a2@f`yFB(J==1sI$LDT8Kfem~M8$(hb4|Na*w_7I$mZp)pq?(;UBb8` zj*pd=oK*>(F^)_xtO?#ny2n42y@ztZ7%g;|KLA<1uK13AzYl*{pYC}~J~Ve8^Wm@m z%U~hDY`-YK>g&L$2aP-PG}><63@cae=BO^1j<4bT^+v4Meh&I(`t@G!1}Il0%+qT+ zZUdcz&X|TwOQs{!umSn8vLfh}H2z&eT26sHQ!mV~;(n*AAUo^~4RBAyQDO+c6gs;B z&s<~w4qQ)e+5b>K>JZw;@wS=EO1+&NtTA83eK@Rh2BgmU+P6w}JPMmRU;krV2S+`m z`qVswJnQ#O^kU6?<}6dLroa{q!fn8RR_q|-n+H3{6<8M@@*eh+3}DUp?vnB$e^cL$ zvK09nX}v`ma$$K*&!gCL(E9=N`~f^)WuC8c16W^vWEo__zK!|yu4GdNdk#vlUt;I$ zgZrMx+I8k9=9S-nWAKX(>H3e*9nubUSRtS8?lW~s(`2MG%Io()$9jhA*R{Tz>?Yi@ z0sOgET`{gvx8dB5aA1>pdJcKt+T&R>Fj(CKTIO}?-*vrv{N$!Fo6v@?W1JvEq5dqt z7&1VA4+t&wYh`=_?^&k*knf>??sY&u9@q&!NQVK{+oRA=4)xKa&>P;vM)d`|E5lf7 z55EmbdoxaMIppmN=^iicF?bF6D16gOy&dqM`u$|*Pe(ts`%dId@*)39)OU>Av&iSq zmUACNsQ1yg>V5=t*iVGI1N%2{PrB!^)*toaboHzB{iA$2F6^sPfAqt5j5E@CUpcNv zp*Quf{FG0IWdVB;^!um#c9dS}xOe7@sF;2cZoQ6~hJkks{iGT2X~T#tR|DOc;ywNP zQQS-&nPo2NKx^;qJ3I(FMsa&-FiEFnj&Fy%GHobEugbtFb`TbBI3KprxsF_2mw3f@ z%H#Tsa^W54ib?;p^tE0Lu>VaO3l4Mp(l9l&yiFS04Y+h9hS6(Fc<2TD5aWg(3wQHV z@M}`=kEGx?rQlmqa2C`gdHx^;|C1E_n<@BTrQlDc;QcB1k5llUrr>Gk#g9kUNs8}< zDLD4HCDPAM!9S3KFHgaLBL&}-g8xCfMgxsw2#uD}V&W-h`xx*-W(Fn62m#$fLLv7v4`u66A z^*pg%j%ydxQ*gOC7hkjH_ouFdw#nagHg|N^-?YBr<_`Zz>Uyxz1?D1hTSI$CbN%{t z9i4s|H#RmERD8X*6eEpS3ZibH+(quq0S412jw$fUUbP-`6!+jT zdA>WMSG-4X#@Cj!Ck)Pxn7XIsM)_-epAlT;QT&C7e!4ur7||0scJLhww!6z2DIF~p0 zg$CDk@s!8ndxT!~#&u$Jdj(f{6hCPA+w^@R;^r{EN?RoGvUG6gcZMy6cJm#gjBKoUCblek>Jc>UV(W{(xpMg!UXM~>mv2%C2{~(s9ygUd%dK=$q2DkBT5DHLx}TVOu>5C4e6*ga z5?uKxJ};uzGO!?`S6t^PR8Eb<;)q`H<$_aATmP&v_!Ogu7K2}G@GgVf`s$#;ryBZ0 zf~%aG51$lV^`Q7M!zW|-oG`e?iLa+h|C#Z+#L!n8{8EE27d)1yR`6J!oZ-VhyE@%R z67$i0Br%^|!iRJF)07FWdj;qB-{N+k$9oL@38B|;m+QMT!;OZk_-MhE{yL!_8__Fn z_j72Qh+Z;6Pd&d^cXsbpMCSqj+@`uF5&j@SkD$FOK+k%DbfzAH{18A1goX z@_0x2-)H#SeJ3{D?NPX&6+d@H;VOQw;cvs;7x7sqeD+6t6z@ynGg|y{?Zf+x{Iv$> zr%%U|)<2+_5Xfn01ug+HFK7m*|>4T25gRXGg~)yHqX3f#r5y& z=xk`b#R&QDxXr*XqUo@xGD@XoqetXX(Ton$Q$?yIB`v{Z1$pH-~-*Z9`} zWB9Z2Z(W-Z{x=KaUgNLVRf1JTbZ5UK0B^O%;G>48W$^*=Z!z9$xQesy80(Jjx+MN_ zHjVxBS(=peR&ZGfKQ9@M*@*r1Sbro-3cv5{!0M8Sc^rOQBQ~lxU|YK^GkB{t2Gv#7 z^D^Fze4YF_k%bavy;xa{NiZguL*%>-<~um|3!ox{xyF-Qz8TJFJcnadN|+l3hZW`-17J?@(4E8_7~21kQ=pmYcE9&>EF zbCB!)Gu^BP%s+G9@J`4^xsa4QvLajVgG2K_y8a>99}Dwb)L9;D3woiieq3Qs?nv%Z z>TC1Exl7%^X6R6DVBLDQdxU3OV9xWvRin!{!RB5a*HKI@IHj8^Lal6pRaCp2l#&HYl8*7HGFJHZ++00>h`hYLp0kA4eg3iuS&NKyv{p5 z_{c8A0rRMs_Y5*VS2hXrcKIWW18s)pX?rc?&7R4-&f4@CWbDH{U16aE-yzwt^%3l@c}&?L08DUcu2_?Wa3vpcce zdJJlqVA359o_`T3nS_H@ks_LQT+cs7(ukKTxo0{`bKD~f1ZSVw;#tAjXSVoa!O6!o zX=wP-JBDlLRJIGwd}X^4cL~nEtHtjVJkD=>3~uKtjv5>vfr8Vy1oE+X6`twha2Zd! zINa?9w`2PE8C>fy`rn^|A2PTdi$5$l^<$fDW4P%m0MXGkxtC zV!1G7ye)2R&e-(jCQiCIpG-1*Y(B{dPI)XJYjeh?ON*hmxZ02*AMGzuj{6M#g#^Uu z*gENT9FMP_GW2%L`k29`yW%<7F>V_#wck(vb}W0E)N{mbe$X*);&#jzjX3Y(bV0k? zyEt9!*tgZE9s9QNf~|7z7_QaZX^c($0!Jc3djTS+jz#Q~c!k)7ez)H9N*%Dfn8m+! z-J`=(hA-jRXJj}67j%?17V&BnE_u+AhjlaXK%O!ANd0pxfjnp9-#Ybg^CI7C_ zru98(ypwpp)mXqX5Gyb7=`S=nUph#18F`7A}Uh_Xt<7sc}1#{W3| z(#8U+|o!1C+s(K4g8e5Cmjck?|=16Uq<^^p)d2DqP~pwi8wCs6Y$}h z(4S&WDEBaMT`1Qa_ex*LuO$XguFJ*HUIlTk7iM^Vd;$Hb$?p6g>&Gp6A;c&-(A;kf)C&N?)7d z_hQ}X1$FMB$>ZFC3f%XL-0ZV%!&=-t)@$dmC*U6RBfo;{|H61gnk;$vMLZsXOg;Hg zuqTe^JjM%n?j|wk`>_*tQx|;xzldue`HP=Egu&mF#=RB0uUXd^5m`V0!6gKL9RbI|Zpv~>i0dv66^QxeX zTu)1R*pKeN;QovJ`dFO%aB@pH?}2`Y>~RNL$Xv~}&OAFb174Jo&2(Q58sD}quCFV8 zo_*X<#l$5#%o*A~uKmux9erGWU$xzh+k(sBj(s2vPwVb#;7Rl!5c+Aj(k%}cw-nbT z`q~tnbu7c}6#sY2bzKU5o6!3N!o60t+fwL1FZAW2>R0hh$F_TtoXn6(_*YW!Z>HdX z37qjdF5&jz**lY2r*=7J+oZmv;(k*(I$i9K(R#S=h1GZ5!j71B$U^UJee%(h$ z)=r=FzC1tQ9kad9;HROf$rqofzZrG^ytUOJNqy^Ptnag&y)9fHJ#D|meLBroao-^m zwBq|X_FFntaPrZ-NQn81j%`KTce^pb9+#;ck1(C-NN@XM`vW|TzTe}~tIC0?2yS`X=STHAh&3_DH}|EJove=-VJ!;@sx$5eY_ zBlVxwwpaf)FEUUKU$0rgs`%2lzZ3aSw{3q$+*uLc8m{)ZGPPJ{nSJu!_gshh%wC#t@ z=Sh1whqhg>8^>XQ?i}|MqU{H7tfIPeXshWn+o^Vbk8MV@@m|V|&i;)11lew68~#~o zpL=@Q8?0?V^dZrHF2y`g$?k2KV`MmN^XJhXNxB^7!7`Xb zBVX_D#9(3W>?qocJQt1UQk`FdIWU~ng?9FVpP;?G8ExkZ_`^9$13$ofv{?`Q4A(sR z1v$J!pTf7Tb9jG0p1Gg1kWT*v+MduA#sW;HARz8k=22Mxv+bjcotrr^HA?F;3w>42eu_pluxOap`w`VU{faCy;idtsx2 zZHq~B%1;^S=zG)Vwy05N8(@X8JAR|>w>1O#=~z&0Jv}YJZeE1X5S)B$TdPWN^0EBq z89o+YkiuuV;A}hD@jz`8GhEwdcu?rsrjpO4M|KI$HkHNq3Qj&YA00F}zX$4`lpE4p zd7d`7jn{wnw#p2|)4GwiRgTHGwnhA(YFlM}6t2n;!_0sDe#W2nk@{!-L7wqAr24mI z0Az)lN#)22rum&Tbe|A{(`~DKNdpM%3coSTycx%x#I;ftpKe=4`v`j_K;~(t;Yiym zYecBup)kh9^79+Gp`oo{_~b3yDpm7Nc}>zT^I6JzS+b~;&UE%nI<_hNcp&T!OvL)3 zfs36#$B%6YcjN~}TQ`Hg(P$W3B5%#S(tqHRID3D6(b(wtvdOEYjW z`J6Xh_lI+R(8(>|_G6z|-?7_)ryGqn2-+Pvw832YfUIj(Qx_G@3(exBoK zp=`%F5;2EMICNp`;FqUB3EZQHx4DanXMaUiNge3fm6uc${|40h{@f7@1Dfn-v z;J=%K`?d@Vt!>Kqg@xEs*;$y*XM4l$)wF{`DHHo~Lq?V<{QvB|4}6x@c{hINkBVR| zV$`Tq?qF0(DGeAPboS)|fv^u{>58Y0^95)i1!=1TXj7tr!xV`b2{)GtJ!y{(>X|p*9!r0 z_IK*iazosX2b~G{W`o-~kR&hoyhZAUR=XA*rYMVSA@!@MV>UI8D><2pL6oMUhSTqhatG{=}-Gqd_s*F#=53!o_{k6#Zd z!aBz$tPfy)W8eI!d^R4HjXoE;#C`wc8buoPKPf47-zWL)?+JXngMR2pu^W>!&)PWw zG8Nz4Xy?k?%c4$m-dG=9;>K{*{jI?KA%pLBI@Uw?74w;*sfE5#^6d4OFrH`EbKJS? zJfoNAgBR`0U_OGh^rx||F^F%FX~;kwYGUr2+!_9x9QCxBUWY^PbP)Q+G2$I@^9+37 z#Fcut`fZTwJMJ6nSzd=5>)Cyr_qezwI2%FPZ=ug4&K~@yaSr?AJeL>W2ys73XPmMz ze7IHwtSp0PDU=VNXZ*KNWxz|H@l56ZyP~Z;)7+QeH;vAD=~Sz4uIEi3M;;oa2)d~Rq$RF5^L_4vS0&w1(n zIL~|S$D?|D*PietH$N?zx}!VV_uw7)7F#mWl@s&17|&7GQ<;9P7dyIBpiAvbqpt9~ z_}vKKcsb^##VhA9UesrIu6P61<@zUVzKAmL?D_f8lsPy%{Duf+2l@Xe!q-n4oc+r4 z4`eQCDvfU7niu7H&6U0X&d>Tg02@y)UW_uvS;~}ya;32DMq5x1Ow816oEq(m*Ic}U z&sg8E#SKz3VPwUOZhV{q!-Wpw`>gNuKm1( zwLaj_sy(gL*l71J77x$<#+gy|283mO9YDVALHWZL+P(qg&7`Pk&6+d)+2AEuM=ahv zf4E}IrN2`VH4JZ>6zySKe#_-M-wS+x55R^M<@zC>{r(59dF1zCgRL@#eMImd>WsFs zee(J5!S>qk!)DkOA1odoM0;Zz8ZZnUGw^ruRqeW-sEaISaWyGD2xy3(%r3H8_g8fpi49LM*1zCUHo_~l`y zkvjT=@?LQQZTDKd6AfI1ye(QhryO(xcX_%=+($4rs(+xkVfYEO)BPw9?x)Z`Z3y** z;Rd7Sv%d*`YSZm})VCWyI6V6&i1+!sqHiB^&%ECM1$g$`qk>1D4R)9^h2me9!tOcrxtal5*EZv4?u+WW2kvF7H77(Ym#R z_WH0U?f06L!d_gC*WjxscC%atAP36-oPP*-I=h5-HS8UMzD6cmK4%DdjB#sUV^K5* zHiKpzK{?W2*&qPU5{ewXXqs zB*+ifPt8YpR-ioROLbnv67rRGg?vC>xXyu$)W`$MuiH2$P=5{tRmo=-W?VtU}m&uA@+<0|>`<&UKK(7&~>&6Jfry ze{AXz_SY5Y!!E>_S~P}rhw~EOr!$Rd%o7Gd%j;q7dxuZVVmyt1e}ZEo^55tCYkzm5 zn)|NsU4De^cn~^5+HW~|Q7+dVI#G|luMT}CXLS1bkZpK9GPjKe$FzS%e!nedkZo0s7ydDJ19j67ZK2@P7r) zcn?XudN%io1p3oKS14YdJ5mToKUomJG6A2TfGdhn9$ zfHK>dWa|>_$r0q@AxyK)go!r&tjVl%d!0mVmp-peRzRVxxuv}YmPCEpxRVHqaCSw~ z%I=7;`>Cp7Lw8FTmK)pKn%Y{ronD+CB98V$r*$*bHDmun$F()P*0;sO4!3K1>`&-O zZ`btnJ9M~4cg&NITGJbY@N}e~;BVb;N^q_*mKmJwj*j%_`CIq9TyTCzwQDzQk96k+ z_)5Xa2k-1zceCI%xY~Go1*beVy>}XVi)RE6`EN0}U2DBh@UUDSHuPr6CT~BJmH&XD zxAK=urcfTtL$Yq0!7s|9QS`9EIaaFMW$=j#;#ywfJn-97lg7k4VR@}&E z7~+__WnG!UEuYxnw!G9P68TvCW|o?=`sP z|D3@spE1%Ygynvg!7nrX7aQERUp@Pkd~AK#Z0PN`r27nR$C14Tzud(8n89tj4jTLl zLx1Yuq`H2t_VbmFwTU@}Z&WhDXq9@&>_L%4QvBKXE#@t8>5g&dU2PDr;-s~18a(9r zZo}(0s+pE4?lpe<-IOF6zg|;&5*Ngnq4aQpyr`IJ0v!tIt$@C|E42p4$WYesw9D*eRuj{Es$%)N5< zsea=cFJl(tPw@x8)T2rBb#@HaPTY4MtRLZuIl_-B%2S^k$2B-Sn->+Y*@<-@gc+&0 z^Nuee1@{R3v%ESUSVOef5cn2N!8&9#W_F~{us&^Rvfrm*>m&aO+x+J=C2XF7FRlbz8d$WU+K`?*^j>__??1l zxZj6gx=nfFFMos!`3wp=MXpcdT8RETz)AnI(CJ#&F~RZ3ImOR`pY-K|XXh1M0A%BI zO8}!@H2uqJQ^y9_y&Lt=y@fi8glE~8)51aXUtlebkJc{=xVYtAeKd`efrNYk_B+Nb zkz?U#{EK*=pt*P{elnRlB0i=qLat?r%F&PiSnobPn@-SE`s2LHMG zD!K+J$-&ZbzT^8Lu~a@B^$DT27mgvUYT;OtG#B8SSs@p~Nppdd4X<+nl~d!?@b5I1 ze;ffqnaJZe3xNe_lg9Ev$-hsMnQj7c{_crCejqrz}j|ZbozVtfr9K$eT*uU>zo%Ani&x{6B3sO|5NC! zoouEyMQ_(#@KB=2StyOBuj=l8{|u6{jWdss<9RNX=gWCaaXGL8zr@0vNx7$^f5Py5 zw_?40x8d1GkZ0J&Q^4rnsg3iyP$(0_t>aGt7t$uR@k@npQNSY%Pk*7>)+ym0mMim! zuU;qH#&zsZdfySYt~xe1cl}ozmkfE&+Bh@yzuLIV)&FYa|LJYKyQ!!9q}%xHsyQ=H z^_{#|Uy@MbDOc(#d~X_yy)EB(1l~UUZ`FOXuR`~bXKJc`BJ>ic(nc0Rhl(Q$qvvGYcqpO~4NnwuV%JJ(fpGLq;w&rIE3jQzNGLzjiRQtw26A9O<~ zC-t*RGWR_D9 zJwwn(dI&n5o5$_{D#nt&1xV-SV?`HlD)zc44?(Yl;SPh2JiJbp*NMyVE1dq#t5Ub` zz`4X2r<}g4rsqNEL>9`gyPi(Xz58!)e(3mU{eIXI-U$6se0!+hcviH2KK!YsOda04 z%kDlOy2QvQn@6u;4aDbb`KWT(JRx=a-O$Csdsx}Y%Ch+`gt^3*1LLCX)DiOe=<5gT z)YyML!Ow|#>1%>4nH64lj_WevbLu2#u+C%GeVo29)@4#|eMah?XS4}N;je~TtiU#kdua12X*#{uj=$8usH&*E(y8*SYK9W$P-%;(fW z!ek8f<$Rp6owFIG_MYFm<1bwsdz^Z|C{MQGJ!7LA7|%^tqpMw+fl{U&87#yQ9LpB=3~6E>xz)~1^N3DFJdr=z(G$46UJrRa

3yK@Dy3^LN4ujaos4f;H4e6 z#7k;9v;ihvHW-1+rq8JEo_<-?mCc`a4;S_Jw5%hWZaiGqu@1+-O5}|_8@gJQhaV~Z zZ?s|Ensptwts@}@zsss-uH=7oSvM!zZV<+t@I73Db?+{x{(f7yunN7e`u7L)T7f$o zerw}P&$PN&aP?P9xJtp*F0`&m@;eRrs6Ig&1DLu(@6}jOhf8|j<{Q#zSCXfpkb7Q| zeVfW*7&{BD!7fR_>k{x^O2E-q7v%rN1pI#_;9pC?A4|ZwW;q`Jp?d>BA)IT-h46_9 z_>=^^IsyM=0)Arxj-!r42Y;2IrW1`_k7eTDGVTMm0XYsJ4E|b&H&JGC-!vYbDqC-zny}sJfD$gJ%Xz|ies+t9Qjzi zJnHSz5tmQ&&aZlZ#Pz!zAM7yn7dlG+vrBN5=N5UkTX2;}@y86Gy!sIE=@mZD1bh^K zE`iTbz~}SA=SaXu@uLZR)J7ch!PbWw8Rs><_Y4241lRN`Zta-c^wtM_{!sX=4EQLn z^9#yj`LqXoena@EjWm@<@m`@1`Scsyrq|j}xBZOjV`@J9fyDc0Aiv_f4Sy^Dpuw#k z)>DEj|8EF?wSlMUQv5l?$MPRGIOllk)Rr8-g<4$ad5o7qbv{@oQ%}Zgan&;=pNYyG z*X2Ube75?e_Zr;lhpHZ^rgxw4y3fSR{$KG&4WCIS-ZB|@7;kKFdlqPg!K)3u&4=X% zw|rU+KH2cmzM=^6GJiB5HLT(~UtTU@6<1c709QUbekr~3*&EO+pSSx+)x}fvMt!Mr zC?_d$w%&B;#y7S{(|^A7;O-1wA*496$z~Z6OJxy%lVRn7Q@vBZAEBtSZxUL5N#DL7 z3*sd&I`Xh?8a!k0FV!>q=w!psMhNl@!(%PZx$L~xd$aP3H=2Q)Lh0|6LAOr`nSQdQ ztaO@wzArKUnFNjNlMjtg8jQD^e!Z>~tSX>eA+LDT16;%DwbAgjq?-!AB4*=PTK0Wm z-nnNoxmd4+a@BYhrl0LMbb8iiT9~ssaXbj~FX`L;%VRyqF9#6@-l(Z#-Rg#xuIz`s ztgVSzaXh1{s>=M%uC9*b>Z%#1tcTYrZGjS{oLIW%pF2wra38A7R#1%Kz8@LAM{T+{ zK5^Ps)q{($o{#5c>Ua8UnbWz_m+)rHezv3*P*wonT#?#4o97Q*(o zw(iz=^@ep#Jy>+i;(&V$+R?nBy(K2t20gaVHIg=Vl3|TfB4unX&Wm0^uQ6nAS$At& zSI0UYZ5!X(*wxm!s@>6bxA-{0p?gCUglO})SF+o%j&yMk*mt#XwH3BKV+|rJp7B~Q z*t*8GEs?U0TY5Vi-4ZGScOd7m_>q0q+SnZz7^K(7a)7XTxfk3#EtIoV#mS z)z)ErO5`K$HpEcg>u!OPV|PzfyXfkMrPt4|&E7O%9VWW&`r1z|UDU8-*^+v_Cs9M~ zitMwxPc4g<K4ll=Q!gPG}nd%JU1vi1>8!h->3}@uGM$@8csjjSvNjBM2qU`T;)coqfPjF z<57m-0N>H2%Y0c{CDY-V??P6;OJ(Len8kJ7r(V?Ki`o$^;)bpogO$C2V)La+Q4&j_yNqWG^1zB1r*zu>I_{x!jS1AMRGTLS#g z1>Y9n-xmDg06#4F-T>FNlcxgwO`$&&;AhIj^5p=(NbunR|ES<&grDZmJi%30O!4J{ zb4{O4@y`fe6X2f}d~ty58p+B4zf0(Q1Kh_JMOy-#?VfI1fM4$6=-~igDEQt0zftg~ z0vz)m=MDw`(kCF6gzI{{h@&Nyy;JQYp^e+lt6VU&g;EMxX%X?*j zvwhRG2Ka{s*YeSL7YY9Fedqs=e&LUiMv89xGI*mDf8ZATOZJ!VwbmuQ>pvy$ihV+S zs_*(+Y$WDhvss~OxEX{0@O|@S!zaD#Yxq7Xe~piESvLb7=1IzexL+xR4~t+)@A_AR zmT8(9gx58_dxH2i{d)bBgs%$1KPXdx=>e|c^!m#ZJ|K&}J$ee^NHm<%pM#q)@7*&Q zK(&8R`Y=5GK@uJ5A&FndC$jqh{x$#09hKidUnu^SQvW)IPA_5n?p@z(x_hU0{n^#0 zZo7Kr`5L>{lN7$MoeBNEKh4@7q^=#__50G$!|~^-741yJW*kB~dwImUFAlcbcE-`X z=f4bHobbFfq^&QGp!0AkqRl6UcluUXPe9)FHDQfm$A>a?lgB_;=mQ8V zXVz2a%dRP8pmPM9Vj~sU#}`MFo@X3c414+%#Pm*wgp*2fglKgtVv*oagJ$ zDkqN;@NKH(-n~hX`|(G1#E=KFRN(wP@}W#BEBSEEn`@!R# z!dn~SUwP zWlNs4Lr$J7rwX^O6ZH?G3}DOZ*-FT%>05xbZNeERxpFAmN#2Y{&qtwLl*j3UiOo*d zA(f4`yxv|0w`P=$zxIQ<_+Lc)hyP>audAJ$AOC!myGj4llT3eBXVj(WN~Vr&bOB`9Zsd0DGdMSAv(VlZ&>lfu(R9(q ztk%H{%9?Tht4rgbWcwr5*Fotsa(VCTHrvQMwGW=BY0t-WwpDR1=0Z~zM?Q@FMW0h- z%9`yO??Yv*%RE1mve6D_3Ob9wSd@A8`_Ny^pfB8BoSIua(f5Zb^k+lRe~b~<^@*QZ z@CfbU>RFwn{|>{PpQ5zGOHBnO~AN zmh$G%`Uk*Y0|HeZAK>r&^3#RmP(aUjY~pDQ9CRw@KjXd-ALa|`cME+j1Hly| zJ;a9v-{xVbcU6cF^^^+XCBjGdP%jrgv_IzLmnynT@J}keyi2qT{^3xm?@Q)7qiy zom@BPJBzNWdqP?K#6t}!f&5}Pm%q8f*}0*|FMCR8rB4xc1rOt`5j>1nze$9AdJ_2bCh&RG;8uRC2WVc=BVC)+c)4~%cRYw!@kshj z%739Jb-&{US3dfvOzc0`U@*FbsRvuj-BE6MI^{PU7%4D1vl|O=q@>u(bwj5U)dMi)6;9np zoy~{NAl|b@rk;S0;&%r0=Lvl#pjUj0;FR-HlinQ$uQ2#C2DkY+EO?kd#|01bM{Q+= z`BN$L1L8K`T?W6*$g|hrR~Y<=!L6K?GH(dwoFaHA=QP1XIrXe*;+DU)AE{###k$w< zvF-G}1bGG$DxqSPlL+oi{1=LUv0tcg2ZlRB`3d89-((s)+tld7JAIR>eivtbm58dNP{=;qcLSq+pzqGQ-QNa?fO2$mf`!5 zxB1}D@WQ!NH*CN;Q$3K4-;KyCjdf67!?j~zW&WHGPshFP5%}>uA<_?uEZkd8|Gz+X zrsGBA59ML{{TjGi!*=JRG3}M*sh_5?mz}bbmg}0^pM*{;ct4Ic=E?V7!q%}qhk>{VKB7S%AX+ov09&olL{P!E? zSqjS)UT(=BNoN{#j9b5_#3(Pf-s`^cJn6pita9t)DsOJ>oU*VSxW4*2(u{fB?r&ht zd^^@x!LtwlTL=Dk3BHk?zcVB8Adm1Y^Q?;l>({!b%yg4(&pjoNP@c5p#ZQoav>W#w zNzdHDc_y<|-a(vg!gJ1eRvE*wyfQdX1$I19mos$>idldDj7K3j9xRtv@vY9+K`$f2 zu?*8=qmjd~!^v~z?DxPT@FB)}puEA?*>xzyx1pS6;pJieDve7Q{K^}CSAW9q2YR+I z){%T&#+h??7w^OS%T|{8WPI~;=hv0^^=zhP0C}%<_5z&ma+lEHtf8qc-eP`FU>$%B zk1wRYL@a{c3F=vId_Hn{K8QR=f9Pz3Y^r3MeO<9_$e-Ekzw>B$oQrQ3S{|@d`Yg{( zll7Ts(Xt!;vJd;Yrs&pN<4=4dUiPV_OW&h~XXI`4pRwl5HDtTDy%T;q&WDMszuKWu z^b3OT5dXb$T`9P(CD<{y(3&=b68j&q$!J5qjO*cC*l5lR&>r=xbzRp=)8koIuYt+d}el?Whobr|{RkanFf7zmY)y z)dc+E1f2Sjh2s520&Y78tO>g*kyH0>Sh{%rip5wTy>9tvl#ie#-oBy5t<6Ha6{_bYP04~>&So(S zx1tx1XI(8=#BI5?B^vcq7l8c(F7SEvIr#-*tolMj zUvREcyES42=i;|#pIhUmyd910?G24xw=k{F!yA_@PfZ@WaE-X>b$b+o4fs7>?Jd}F z(6Y9v^Y%zSHrBSaX!Fwc7rukn3IW%G?7R79!AY;{C4~AC@TUy!zu$S_1%umqcf{a) zPf*867#-!Ycq#mJlxKp!b-!f>xAYSeaDLOF3*W(O1!uf=4O!QCNw4cb4Buz?VC>Jj zLk2I;qEYm+!7ntpuH}-yeaA1A{wtL8tOQ)wazpyG(1&Xj&4Pz(6g`H&O|RYiZ1G0} z{$nI5^L)^K0T^x-4EQ{k76}ik!OlS?Lu&OX!)O zcFl8fz(?l=y7sGl6mK?sVu_O%yY@>tcgQol_G|GT!>2-MdC@gt*4xPjSA9>)Uuke% z`_=j&ufo}HrCJ{pf6Bzmxs$p>2Io49x}yfS^q2%XM|rMLVqC`?+_sBy!BtLO-=8SB z%Bi^B(>=xTUu^i>{-@sHw%>TSYirXnUd)(2xMHVLNNv9=ULay1a-o!Pv zzOkNU%4z<}wG+mp?NKbf zHL<6pp!Ww623|ka!^`8zu8GZTXtdT$-w@!d-_PxER zG#Z&SCK`#c4xnpVZY{vjSEP!z+AyTAh{kMX*f3ngb*+gTzZ11K_9FTTi^w;A zs=9`<|0Q@00OwgTDO^Wzjc|Pf*P^q*uP<7^=>s_DnQ|TlFP!r{X#o1&xIO?GBjo!C z@}#09HTN>4uLU;A?k_p*vztnz`gt$IUMsE@XQbxxz7h8?!Dj5n%Bbdtkl_a?_wBH$ zxxcp&VTwLmfpe0%Hu)lO(v85jZ0#ADx*aIf8t}*2+j9p>qiUW#jd^4}`mMeutQl^; zCR6tW^s=|->1O-&Sjx8;^%&=EZ~Y$9^bqooc2;?oIBocH{qIUVdl0s6^_=aWqOLs% zo2B5rd*IdibJI~Y7w^||F{jDuK$m_pQ&$XqO!9gavhpl%wGX@>Ysnjm&-+$I#Q*4? zd8yQo{tD%*^6o&`yP(_qoD1XSjB&pC7u`Br=Gld7(lwiKrVs4B&tkmLDW3XEpw;k| z*ZMsP?ks8KBjbpWu1i}ltKpgUtn2?B*Fij+gmO-o$;zdSM1o5 zelqGoaqp_$1*IRF(2$DOBhTx(FM!V~khWpO`%)U|7P{i1DYMz-3`?DN<@MGbd$N6x>%-6oIvs5EKic{8O{QwonpFy@OW5v~vaXs47f8W}(x-i$phOpm66`&(=}m`*)c{aY^YW&(4^uc{H~q znmRH$s^&O?dNdVzz5ZX3*GAOnPuqDV+7!pk2+uhN zZ0A__#-uru+KbljKP##~3^{4X`@^97C(!*6|A$LX$2fZ0&W{44y>I`G=d_(M{6*k1 zucv4|CfW6kXXMI;dnfKfzJCR>-5tfVk-n{ekNcsLQYTw8;;zM5TKVR@Iijd#SNvdmZi4ZO&cdn1~Qt44)?C@P;#+U>_- zzZi7vbLk%dzlVPIvDu}-Fh`o3Vm`k)X%6Kg&r;+$(}?tJZAKqaD}6*1-ThUbZ@=TM zNwfbD*Y8KsD+92N%>3C4{{!gzi%|DABClD;Un)6c=Xc&h|Mkj=YOVLIb8J(r>#2V} zu}5*m23|gq9V-rCKL_jW67cpmr%&7Y*FW?5&$63@vGFkKPa0|9J^KE7j*YLET(I+T zjFlObH|?wsN|-lr@3E4de+vNmXt{LvZE2EJIK8m!PZ%Gfr z&UXs^$^qc)OVIYp5PmE7jws*sTUX5C{tmR2AF-c2FZ%LVb-YEHp0mpB@0iH`sz3d+ z=n%aG+{80dOEJ*K6k%nbYKit?Hr6G1KPR5@N4Q8ia`c7QR`d{Tg-fa}XTFgo9F_Ucn zdA@w+vhH7sFYErqW!+<=&(QNrV{_|GO}ZH+x~#n!M!VLv#1S^j{o;~kSI*S$U9oC4 zyf^0gS=)aebQh|m&|+MvyP*CW!9ON=tN8VM6gCe!`a1>JHGRCFJA8}aQ{;Ms;Jd_M zE!TFzkBGlsuD1zZpm^B^0EBI2umHrO|?-aZi ze!2trC!gJdt6uQ81z#=+-9ch;g>*Ik&OH+*N{Fk+B{2s72izA$2A4kb-xSaFq1jM{ z_9c4$qjf<}I6gUixo|lf`CAm7p514tI3E|Xb>(sGriF=I3Z0|CZ!+Wa$((OW0*-g$ zg7otf@aq!rn-cJJ0)DFJ2W&~;^OXdgIw^(n;jsk#uM+SV67U};;6F;hQOOI+g9By? z;uk02v>jC_U2_xgR04iO0{+Vhcvk{`2XN}>ye92b`=wtMTon;i<}U-c`xQT`b=7I3 z@MDCt#fBT`XtZVb9&*6&fFC5Bw_DBq(bv;~=RJ;&d+{Q-A9IgzR< z4NV=;vLM!sBWt=kZueRq28du}vEjDv>22Lzjnk`~ud%(ewUN=cbhS142QwUx?8Zih zccui@tX$9So!AX&_f|UOwzhQ`^aO8^EtW2k>QP-1r&z+Bk#fvLzS4-*p;_>$s~fIc zbe&UEL6WFUq7ZhXhx<15kOaD!o$4`QN9CeX%0AgGq}*8QHmbI?tZ8U(?AGn7Byd9c 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 O*Y%5f1~x8^|NjA<@BNDa literal 0 HcmV?d00001 diff --git a/optee/optee_test/host/openssl/lib/arm/libcrypto.a b/optee/optee_test/host/openssl/lib/arm/libcrypto.a new file mode 100644 index 0000000000000000000000000000000000000000..19547b93b1265afad6939698dd04285c3e3236ec GIT binary patch literal 2800684 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 q=p4%iKHcs4Ng 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�gRjG& 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

@h5rs4zt7#DpR$maacSSekI|sF0ag5s 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

  • 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 WFPq_}MFHKJ@;QQp|L(gM1+vZ1Y( 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 z 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

    4Ymu{tkUp791^B?) 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

    -7z4#m<_IFWaZIO^`g8V5c_fc&0wW_F~+J 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

    7}W`-S$X1#vMxArW&r{sL>^&ZS( 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%0DNaL#p5E#+i=OYtW8hxE<=|z1 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

    h&|__1e|7Rno@hicD{zwCQb1cRZ>}rd7HajF9WY z)!d&{X|Ato26zj-muCnV}Eb?AAD+JKHxU#ao8Jh}IgF6xOoyiUE1H?nJORhiN!r7q#Asyy$7%Fm$< zOD*9qe6sXy?&DQ1udH$K*X^^aB<~S_c!aDAA6FgmJ0o&rU2`9(a$|)Q4Rjbn5rd_q_D|^4m}N4=q_*u`;{K_sd5)d;2}c8=|?BeVWL7EBB46 z92e{Ix!T-=d|NZ#fDT{*p8WJ^ty53e3((x`F3Nwn_}!G@*0cQ%kv>_*PoVBEA60fm z-A}5GUX1q!X+ixzYkv?ae`IyWc7#3~p?_TSXvRyppB^psM?2}8^-Us%4{Go(NKMYz zW!M4C9_`XU^oQ?biLe}#uxpwAqDs004v7a>e?Nu^#o4eidtXf;+ptX1C@94Yq>vZSF zuxdlg-X`k!ez+fe)OLf^7{#iEqd`v&)Q9MYQLmcRZ4p|V8cKtCMO{Q2lBQ~$=Kkw3 z$NFd;I7KtxvCMVXKM`?(?aq*5>@|lr1_*cf3f~)SOTC zJsr~R(BzQY4!J`59r|-{@}bSa`G@GoQI=G@vLrS*d#|n2!b5cLEEB%O?=9(LReKc@ zSnKj+iCYh4`+ENuAs-xiI^++ZCW^e<+#mTe(Hg&d4NL#A=sQvVa+R5*?30?$P6b^v zK##|p+~n^}(Vi+t+3#wCUkG|pTh&jmo#uSu@?Y~VQSzxI}xiMD@AbiOIJ4K<1SjbcS)kRG+&hIIRvnC3D*&0lao+h33wz?qx^C4L8}kc3@GM$iRC4uQA(kO-e|3KMxg8xuwLn2Usgu2 zD`>s_acC=_(pqF@3{AV+BXQ#E)K zL$iLkJnvJ#v(%&S`?gtdbL2bsnJ{y;XA3Bs70~(PMRkEP2%;%qPARA zb%i=+8*#12bqB6wT)l90$JGOu3)ictH{)@!9u;DJZ75EYVv3x4YGn-8d$Fbd@b7k{ zFH+dM^uo6qej88XS(Erkb_tDXev{8Fm{Bn6t^(JjS$UH|!2@SaihA1JC1+h-MVJZc z?^1j82`o zw!en^Jp4aPBg5w$fWgP&=1%afK)Rm<0M^xhJ?ud?^vGo zCRoD|rZ7?X<^Fds19_jMI3QpgqE{cF2rrOvVafgO-mVvmay??<-&(j0&(1J>4m^j) zFyv7dZr$ImpG7{z!pB-T=cNq8@Ml~2QVZw2m0{?f?YCjbxeu>l$ltW^DhvP8!p~Uv zj~32)W*COw-ooQ7ysw4VuK|$t+`6A0=gADi@TXb$T^7F5!Z(1ocA(DVqFyZb+&2uv z`@q6Kx9~45{EUVFVBw7rk6}c4SUBh13`2REg;NjNFqCsX&M@SUS@;VUzR$uxw(zel z{Cf*;YHCs$Uv~??*}~H-{B{eUYvGSr_%q-scukW~j(k2=J>-uq?!U6|OBUXQe|pL= z{gDfy&I)Z6i6*(R&^txyd;!124xP(8Y#3k%(_g53dx)Tp_RlC<@&FQ^F_AIs!9zN zFe&kf<#0k-!W4(lVlb;p);k?j2-OLx7BqWuZk~u!1|rodQbvx1ZX^zO;d;OZ+GpJN zQMc}0*^|u>U=d& zjG+&+1*!tnSWLPyfgl@de~JVd>N9j>sV?=JK2oEE2~u@V>=oERVFoEIH1;mUy-0!d zHVN8{N^u1t#H%2be$uGXStC<~!t6Bayoij~+fo0-&{Y*8RgtOJVs(qK6QrK0RWd1m za&7^%gDkl)>nKsR?+P6stA#mJd|IO7$v^`|C3`A{vM_aUgkr5FU*geCt|+wR$>o1VHAdsc7ErE z#bX|wn1Fd=VlO#P#yv0(lOynNh?tkO<2#3YT=M&l=ptgmiG73CiTHm2w&^GP#+<*5 zSN45?CFUZdb5e>>`o*Okn5QluGnJ|d=2gK;mx(qoY&n-L?+p{V0b6VF{yTe zn1n>)|B`x2p~PhTR}lxJd=&EklCabu4dp3_pNQ~ZAR_!d zM5N<0Wⅇ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 Q?eGCT77>}d1V$u`puEc77 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 +#include +#include +#include +#include +#include +#include +#include +#include + +static TEEC_Result pass_values(unsigned int sub_cmd, void *data, + size_t data_len, size_t *out_len) +{ + struct add_op { + uint32_t a; + uint32_t b; + } *values = NULL; + + values = (struct add_op *)data; + *out_len = sizeof(uint32_t); + + if (sub_cmd == '+') + values->a = values->a + values->b; + else + values->a = values->a - values->b; + + return TEEC_SUCCESS; +} + +static TEEC_Result proc_input_arr(unsigned int sub_cmd, void *data, + size_t data_len, size_t *out_len) +{ + (void)sub_cmd; + + size_t i = 0; + uint8_t sum = 0; + uint8_t *d = data; + + for (; i < data_len; ++i) + sum += d[i]; + + d[0] = sum; + *out_len = sizeof(sum); + + return TEEC_SUCCESS; +} + +static TEEC_Result get_test_arr(unsigned int sub_cmd, void *data, + size_t data_len, size_t *out_len) +{ + (void)sub_cmd; + char test_arr[] = "Array from plugin"; + size_t test_size = sizeof(test_arr); + + if (data_len < test_size) + return TEEC_ERROR_GENERIC; + + memcpy(data, test_arr, test_size); + *out_len = test_size; + + return TEEC_SUCCESS; +} + +static TEEC_Result test_plugin_invoke(unsigned int cmd, unsigned int sub_cmd, + void *data, size_t data_len, + size_t *out_len) +{ + switch (cmd) { + case TEST_PLUGIN_CMD_PING: + return TEEC_SUCCESS; + case TEST_PLUGIN_CMD_PASS_VALUES: + return pass_values(sub_cmd, data, data_len, out_len); + case TEST_PLUGIN_CMD_WRITE_ARR: + return proc_input_arr(sub_cmd, data, data_len, out_len); + case TEST_PLUGIN_CMD_GET_ARR: + return get_test_arr(sub_cmd, data, data_len, out_len); + default: + break; + } + + return TEEC_ERROR_NOT_SUPPORTED; +} + +struct plugin_method plugin_method = { + .name = "test", + .uuid = TEST_PLUGIN_UUID, + .invoke = test_plugin_invoke, +}; diff --git a/optee/optee_test/host/xtest/CMakeLists.txt b/optee/optee_test/host/xtest/CMakeLists.txt new file mode 100644 index 0000000..776787b --- /dev/null +++ b/optee/optee_test/host/xtest/CMakeLists.txt @@ -0,0 +1,147 @@ +project (xtest C) + +include(${OPTEE_TEST_SDK}/host_include/conf.cmake) + +################################################################################ +# Packages +################################################################################ +find_package(Threads REQUIRED) +if(NOT THREADS_FOUND) + message(FATAL_ERROR "Threads not found") +endif() + +find_package(OpenSSL) +if(OPENSSL_FOUND) + add_compile_options(-DOPENSSL_FOUND=1) + set (OPENSSL_PRIVATE_LINK OpenSSL::Crypto) +endif() + +find_package(Python REQUIRED) + +include(GNUInstallDirs) + +macro(EMBED_8100FILE prefix infile) + add_custom_command( + OUTPUT regression_8100_${prefix}.h + COMMAND ${Python_EXECUTABLE} ${OPTEE_TEST_ROOT_DIR}/scripts/file_to_c.py --inf ${infile} + --out ${CMAKE_CURRENT_BINARY_DIR}/regression_8100_${prefix}.h + --name regression_8100_${prefix} + DEPENDS ${OPTEE_TEST_ROOT_DIR}/scripts/file_to_c.py ${infile} + ) + + set_property(SOURCE regression_8100.c APPEND PROPERTY OBJECT_DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/regression_8100_${prefix}.h) +endmacro(EMBED_8100FILE) + +EMBED_8100FILE(ca_crt ${OPTEE_TEST_ROOT_DIR}/cert/ca.crt) +EMBED_8100FILE(mid_crt ${OPTEE_TEST_ROOT_DIR}/cert/mid.crt) +EMBED_8100FILE(my_crt ${OPTEE_TEST_ROOT_DIR}/cert/my.crt) +EMBED_8100FILE(my_csr ${OPTEE_TEST_ROOT_DIR}/cert/my.csr) + +set (SRC + adbg/src/adbg_case.c + adbg/src/adbg_enum.c + adbg/src/adbg_expect.c + adbg/src/adbg_log.c + adbg/src/adbg_run.c + adbg/src/security_utils_hex.c + aes_perf.c + benchmark_1000.c + benchmark_2000.c + regression_1000.c + regression_4000.c + regression_4100.c + regression_5000.c + regression_6000.c + regression_8000.c + regression_8100.c + hash_perf.c + stats.c + xtest_helpers.c + xtest_main.c + xtest_test.c + xtest_uuid_helpers.c +) +if(CFG_SECURE_PARTITION AND CFG_SPMC_TESTS) + list (APPEND SRC ffa_spmc_1000.c) +endif() + +if (WITH_GP_TESTS) + add_compile_options(-DWITH_GP_TESTS=1) + + macro(__GEN_GP_FILE outfile xmldir name basedir) + add_custom_command( + OUTPUT ${outfile} + COMMAND xalan -in ${basedir}/${name}.xml + -xsl gp/${name}.xsl -out ${outfile} + DEPENDS ${basedir}/${name}.xml gp/${name}.xsl + ) + endmacro(__GEN_GP_FILE) + macro(GEN_GP_FILE outfile xmldir name) + __GEN_GP_FILE(${outfile} ${xmldir} ${name} + gp-suite/packages/${xmldir}) + list (APPEND SRC ${outfile}) + endmacro(GEN_GP_FILE) + + GEN_GP_FILE(gp_10000.c ClientAPI/xmlstable TEE) + GEN_GP_FILE(gp_20000.c TrustedCoreFw/xmlstable TEE_Internal_API) + GEN_GP_FILE(gp_30000.c DataStorage/xmlstable TEE_DataStorage_API) + GEN_GP_FILE(gp_40000.c Time_Arithmetical/xmlstable TEE_TimeArithm_API) + GEN_GP_FILE(gp_50000.c Crypto/xmlstable TEE_Crypto_API) + set (GP_INCLUDES PRIVATE gp/include) +endif() + +if (CFG_GP_SOCKETS) + list (APPEND SRC + regression_2000.c + sock_server.c + rand_stream.c + ) +endif() + +if (CFG_SECSTOR_TA_MGMT_PTA) + list (APPEND SRC install_ta.c) +endif() + +if (CFG_SECURE_DATA_PATH) + list (APPEND SRC sdp_basic.c) +endif() + +if (CFG_PKCS11_TA) + add_compile_options(-DCFG_PKCS11_TA) + list (APPEND SRC pkcs11_1000.c) +endif() + +if (CFG_CRYPTO_SE05X) + add_compile_options(-DCFG_CRYPTO_SE05X) +endif() + +################################################################################ +# Built binary +################################################################################ +add_executable (${PROJECT_NAME} ${SRC}) + +target_compile_options (${PROJECT_NAME} PRIVATE -include conf.h) + +target_include_directories(${PROJECT_NAME} + PRIVATE . + PRIVATE ../supp_plugin/include + PRIVATE adbg/include + PRIVATE ${OPTEE_TEST_SDK}/host_include + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${GP_INCLUDES} +) + +target_link_libraries (${PROJECT_NAME} + PRIVATE ${CMAKE_THREAD_LIBS_INIT} + PRIVATE xtest-ta-headers + PRIVATE teec + PRIVATE m + PRIVATE ${OPENSSL_PRIVATE_LINK} + PRIVATE ckteec +) + +################################################################################ +# Install targets +################################################################################ +install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/optee/optee_test/host/xtest/LICENSE b/optee/optee_test/host/xtest/LICENSE new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/optee/optee_test/host/xtest/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/optee/optee_test/host/xtest/Makefile b/optee/optee_test/host/xtest/Makefile new file mode 100644 index 0000000..127bf4a --- /dev/null +++ b/optee/optee_test/host/xtest/Makefile @@ -0,0 +1,243 @@ +# Normally this makefile shouldn't be called directly and we expect the output +# path to be on a certain location to fit together with the other OP-TEE +# gits and helper scripts. + +include ../../scripts/common.mk +out-dir := $(call strip-trailing-slashes-and-dots,$(O)) +ifeq ($(out-dir),) +$(error invalid output directory (O=$(O))) +endif + +include $(TA_DEV_KIT_DIR)/host_include/conf.mk + +# By default we expect optee_client exported folder to be on a certain relative +# path, but if the client specifies the OPTEE_CLIENT_EXPORT then that path will +# be used instead. +OPTEE_CLIENT_EXPORT ?= ../../../optee_client/out/export + +CC ?= $(CROSS_COMPILE)gcc +CPP ?= $(CROSS_COMPILE)cpp +LD ?= $(CROSS_COMPILE)ld +AR ?= $(CROSS_COMPILE)ar +NM ?= $(CROSS_COMPILE)nm +OBJCOPY ?= $(CROSS_COMPILE)objcopy +OBJDUMP ?= $(CROSS_COMPILE)objdump +READELF ?= $(CROSS_COMPILE)readelf + +# Macros to detect the targeted architecture (e.g., arm-linux-gnueabihf or +# aarch64-linux-gnu) and the corresponding bit size (32 or 64). +define cc-arch +$(shell $(1) -v 2>&1 | grep Target | sed 's/Target: \([^-]*\).*/\1/') +endef +define cc-bits +$(if $(filter arm, $(1)),32,$(if $(filter aarch64, $(1)),64,unknown-arch)) +endef + +# OpenSSL is used by: +# - GP tests series 8500 +# - Mbed TLS test 8103 +# - User/group login tests 1027 and 1028 +WITH_OPENSSL ?= y +ifeq ($(WITH_OPENSSL),y) +CFLAGS += -DOPENSSL_FOUND=1 +ifneq ($(OPTEE_OPENSSL_EXPORT),) +LDFLAGS += -lcrypto +CFLAGS += -I$(OPTEE_OPENSSL_EXPORT) +else #OPTEE_OPENSSL_EXPORT +CFLAGS += -I../openssl/include +ifeq ($(call cc-bits, $(call cc-arch, $(CC))),32) +LDFLAGS += ../openssl/lib/arm/libcrypto.a -ldl +else +LDFLAGS += ../openssl/lib/aarch64/libcrypto.a -ldl +endif +endif #OPTEE_OPENSSL_EXPORT +endif #require OpenSSL + +srcs := regression_1000.c + +ifeq ($(CFG_GP_SOCKETS),y) +srcs += regression_2000.c \ + sock_server.c \ + rand_stream.c +endif + +srcs += adbg/src/adbg_case.c \ + adbg/src/adbg_enum.c \ + adbg/src/adbg_expect.c \ + adbg/src/adbg_log.c \ + adbg/src/adbg_run.c \ + adbg/src/security_utils_hex.c \ + aes_perf.c \ + benchmark_1000.c \ + benchmark_2000.c \ + regression_4000.c \ + regression_4100.c \ + regression_5000.c \ + regression_6000.c \ + regression_8000.c \ + regression_8100.c \ + hash_perf.c \ + stats.c \ + xtest_helpers.c \ + xtest_main.c \ + xtest_test.c \ + xtest_uuid_helpers.c + +ifeq ($(CFG_SECURE_PARTITION)-$(CFG_SPMC_TESTS),y-y) +srcs += ffa_spmc_1000.c +endif + +ifeq ($(CFG_SECSTOR_TA_MGMT_PTA),y) +srcs += install_ta.c +endif + +ifeq ($(CFG_SECURE_DATA_PATH),y) +srcs += sdp_basic.c +endif + +ifeq ($(CFG_PKCS11_TA),y) +srcs += pkcs11_1000.c +CFLAGS += -Os +endif + +objs := $(patsubst %.c,$(out-dir)/xtest/%.o, $(srcs)) + +ifeq ($(CFG_PKCS11_TA),y) +CFLAGS += -DCFG_PKCS11_TA +endif + +ifeq ($(CFG_CRYPTO_SE05X),y) +CFLAGS += -DCFG_CRYPTO_SE05X +endif + +CFLAGS += -I./ +CFLAGS += -I./adbg/include +CFLAGS += -I../supp_plugin/include +CFLAGS += -I$(out-dir)/xtest + +CFLAGS += -I$(OPTEE_CLIENT_EXPORT)/include +CFLAGS += -I$(TA_DEV_KIT_DIR)/host_include + +CFLAGS += -I../../ta/include +CFLAGS += -I../../ta/create_fail_test/include +CFLAGS += -I../../ta/crypt/include +CFLAGS += -I../../ta/enc_fs/include +CFLAGS += -I../../ta/os_test/include +CFLAGS += -I../../ta/rpc_test/include +CFLAGS += -I../../ta/sims/include +CFLAGS += -I../../ta/miss/include +CFLAGS += -I../../ta/sims_keepalive/include +CFLAGS += -I../../ta/storage_benchmark/include +CFLAGS += -I../../ta/concurrent/include +CFLAGS += -I../../ta/concurrent_large/include +CFLAGS += -I../../ta/hash_perf/include +CFLAGS += -I../../ta/aes_perf/include +CFLAGS += -I../../ta/socket/include +CFLAGS += -I../../ta/sdp_basic/include +CFLAGS += -I../../ta/tpm_log_test/include +CFLAGS += -I../../ta/large/include +CFLAGS += -I../../ta/supp_plugin/include +CFLAGS += -I../../ta/bti_test/include +CFLAGS += -I../../ta/subkey1/include +CFLAGS += -I../../ta/subkey2/include + +TA_DIR ?= /lib/optee_armtz +CFLAGS += -DTA_DIR=\"$(TA_DIR)\" + +# Include configuration file generated by OP-TEE OS (CFG_* macros) +CFLAGS += -include conf.h + +CFLAGS += -Wall -Wcast-align -Werror \ + -Werror-implicit-function-declaration -Wextra -Wfloat-equal \ + -Wformat-nonliteral -Wformat-security -Wformat=2 -Winit-self \ + -Wmissing-declarations -Wmissing-format-attribute \ + -Wmissing-include-dirs \ + -Wmissing-prototypes -Wnested-externs -Wpointer-arith \ + -Wshadow -Wstrict-prototypes -Wswitch-default \ + -Wwrite-strings -Wno-unused-parameter \ + -Wno-declaration-after-statement \ + -Wno-missing-field-initializers -Wno-format-zero-length + +CFLAGS += -g3 + +LDFLAGS += -L$(OPTEE_CLIENT_EXPORT)/lib -lteec +ifeq ($(CFG_PKCS11_TA),y) +LDFLAGS += -lckteec +endif +LDFLAGS += -lpthread -lm + +.PHONY: all +all: xtest + +xtest: $(objs) + @echo " LD $(out-dir)/xtest/$@" + $(q)$(CC) -o $(out-dir)/xtest/$@ $+ $(LDFLAGS) + +$(out-dir)/xtest/%.o: $(CURDIR)/%.c + $(q)mkdir -p $(out-dir)/xtest/adbg/src + @echo ' CC $<' + $(q)$(CC) $(CFLAGS) -c $< -o $@ + +RMDIR := rmdir --ignore-fail-on-non-empty +define rm-build-dirs + $(q)for d in $1; do $(RMDIR) $(out-dir)/xtest/$$d 2> /dev/null; true; done + $(q)$(RMDIR) $(out-dir)/xtest 2> /dev/null; true + $(q)$(RMDIR) $(out-dir) 2> /dev/null; true +endef + +ifeq ($(CFG_GCM_NIST_VECTORS),y) +GCM_NIST_VECTORS_DECRYPT = gcmDecrypt128 gcmDecrypt192 gcmDecrypt256 +GCM_NIST_VECTORS_ENCRYPT = gcmEncryptExtIV128 gcmEncryptExtIV192 \ + gcmEncryptExtIV256 + +cleanfiles += $(out-dir)/gcmtestvectors.zip +$(out-dir)/gcmtestvectors.zip: + @echo ' DL $@' + $(q)curl https://csrc.nist.gov/csrc/media/projects/cryptographic-algorithm-validation-program/documents/mac/gcmtestvectors.zip -o $@ + +define create-nist-gcm-vectors +cleanfiles += $(out-dir)/xtest/$(1).h $(out-dir)/$(1).rsp + +$(out-dir)/$(1).rsp: $(out-dir)/gcmtestvectors.zip + @echo ' UNZIP $$@' + $(q)unzip -o $$< $$(notdir $$@) -d $$(dir $$@) + $(q)touch $$@ + + +$(out-dir)/xtest/$(1).h: $(out-dir)/$(1).rsp + @echo ' GEN $$@' + $(q)$(PYTHON3) ../../scripts/rsp_to_gcm_test.py --inf $$< --outf $$@ --mode=$(2) \ + $(if $(filter y,$(CFG_GCM_NIST_VECTORS_LIMITED)),--limited) + +$(CURDIR)/regression_4000.c: $(out-dir)/xtest/$(1).h +endef + +$(foreach v, $(GCM_NIST_VECTORS_DECRYPT), $(eval $(call \ + create-nist-gcm-vectors,$v,decrypt))) +$(foreach v, $(GCM_NIST_VECTORS_ENCRYPT), $(eval $(call \ + create-nist-gcm-vectors,$v,encrypt))) +endif + +define embed-file +cleanfiles += $(out-dir)/xtest/$(1).h + +$(out-dir)/xtest/$(1).h: $(2) + $(q)mkdir -p $(out-dir)/xtest/ + @echo ' GEN $$@' + $(q)$(PYTHON3) ../../scripts/file_to_c.py --inf $$< --out $$@ --name $(1) + +$(CURDIR)/regression_8100.c: $(out-dir)/xtest/$(1).h +endef + +$(eval $(call embed-file,regression_8100_ca_crt,../../cert/ca.crt)) +$(eval $(call embed-file,regression_8100_mid_crt,../../cert/mid.crt)) +$(eval $(call embed-file,regression_8100_my_crt,../../cert/my.crt)) +$(eval $(call embed-file,regression_8100_my_csr,../../cert/my.csr)) + +.PHONY: clean +clean: + @echo ' CLEAN $(out-dir)' + $(q)rm -f $(out-dir)/xtest/xtest + $(q)$(foreach obj,$(objs), rm -f $(obj)) + $(q)rm -f $(cleanfiles) + $(call rm-build-dirs,adbg/src adbg) diff --git a/optee/optee_test/host/xtest/adbg/include/adbg.h b/optee/optee_test/host/xtest/adbg/include/adbg.h new file mode 100644 index 0000000..49a10cc --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/include/adbg.h @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef ADBG_H +#define ADBG_H +#include +#include +#include +#include +#include + +#define ADBG_STRING_LENGTH_MAX (1024) + +/* + * Case definitions + */ + +/** + * Defines a test case + * + * Used in the follwing way for readability: + */ +#if 0 /* #if 0 to avoid nested comments */ +ADBG_CASE_DEFINE(TEST_1001, TEST_Test_1001, + /* Title */ + "My test case title", + ); +#endif + +typedef struct ADBG_Case ADBG_Case_t; + +typedef struct adbg_case_def { + const char *TestID_p; + const char *Title_p; + void (*Run_fp)(ADBG_Case_t *ADBG_Case_pp); + TAILQ_ENTRY(adbg_case_def) link; +} ADBG_Case_Definition_t; + +TAILQ_HEAD(adbg_case_def_head, adbg_case_def); + +typedef struct adbg_suite_def { + const char *SuiteID_p; + struct adbg_case_def_head cases; +} ADBG_Suite_Definition_t; + +#define ADBG_CASE_DEFINE(Suite, TestID, Run, Title) \ + __attribute__((constructor)) static void \ + __adbg_test_case_ ## TestID(void) \ + { \ + static ADBG_Case_Definition_t case_def = { \ + .TestID_p = #Suite "_" #TestID, \ + .Title_p = Title, \ + .Run_fp = Run, \ + }; \ + struct adbg_case_def_head *ch = &(ADBG_Suite_ ## Suite).cases; \ + struct adbg_case_def *cd = NULL; \ + \ + TAILQ_FOREACH(cd, ch, link) \ + if (strcmp(case_def.TestID_p, cd->TestID_p) < 0) \ + break; \ + if (cd) \ + TAILQ_INSERT_BEFORE(cd, &case_def, link); \ + else \ + TAILQ_INSERT_TAIL(ch, &case_def, link); \ + } + +/* + * Suite definitions + */ + +/** + * Declares a suite defined in a C-file. + */ +#define ADBG_SUITE_DECLARE(Name) \ + extern ADBG_Suite_Definition_t ADBG_Suite_ ## Name + +#define ADBG_SUITE_DEFINE(Name) \ + ADBG_Suite_Definition_t ADBG_Suite_ ## Name = { \ + .SuiteID_p = #Name, \ + .cases = TAILQ_HEAD_INITIALIZER(ADBG_Suite_ ## Name.cases), \ + } + +/* + * Enum table definitions + */ + +#define ADBG_ENUM_TABLE_DECLARE(Name) \ + extern const ADBG_EnumTable_t ADBG_EnumTable_ ## Name[] + +#define ADBG_ENUM_TABLE_DEFINE_BEGIN(Name) \ + const ADBG_EnumTable_t ADBG_EnumTable_ ## Name[] = { +#define ADBG_ENUM_TABLE_ENTRY(Value) { Value, #Value } + +#define ADBG_ENUM_TABLE_DEFINE_END(Name) , { 0, NULL } } + +typedef struct { + int Value; + const char *const Name_p; +} ADBG_EnumEntry_t; + +typedef ADBG_EnumEntry_t ADBG_EnumTable_t; + +ADBG_ENUM_TABLE_DECLARE(Boolean); + +/* + * Expect functions/macros + */ + +#define ADBG_EXPECT(Case_p, Expected, Got) \ + ADBG_EXPECT_ENUM(Case_p, Expected, Got, NULL) + +#define ADBG_EXPECT_NOT(Case_p, Expected, Got) \ + ADBG_EXPECT_NOT_ENUM(Case_p, Expected, Got, NULL) + +#define ADBG_EXPECT_ENUM(Case_p, Expected, Got, EnumTable_p) \ + Do_ADBG_Expect(Case_p, __FILE__, __LINE__, Expected, Got, #Got, \ + EnumTable_p) + +#define ADBG_EXPECT_NOT_ENUM(Case_p, NotExpected, Got, EnumTable_p) \ + Do_ADBG_ExpectNot(Case_p, __FILE__, __LINE__, \ + NotExpected, Got, #Got, EnumTable_p) + +#define ADBG_EXPECT_BOOLEAN(Case_p, Expected, Got) \ + ADBG_EXPECT_ENUM(Case_p, Expected, Got, ADBG_EnumTable_Boolean) + +#define ADBG_EXPECT_TRUE(Case_p, Got) \ + ADBG_EXPECT_ENUM(Case_p, true, Got, ADBG_EnumTable_Boolean) + +#define ADBG_EXPECT_EQUAL(Case_p, Buf1_p, Buf2_p, Length) \ + ADBG_EXPECT(Case_p, 0, memcmp(Buf1_p, Buf2_p, Length)) + +#define ADBG_EXPECT_BUFFER(Case_p, ExpBuf_p, ExpBufLen, GotBuf_p, GotBufLen) \ + Do_ADBG_ExpectBuffer(Case_p, __FILE__, __LINE__, \ + ExpBuf_p, ExpBufLen, #GotBuf_p, GotBuf_p, \ + #GotBufLen, GotBufLen) + +#define ADBG_EXPECT_POINTER(Case_p, Expected, Got) \ + Do_ADBG_ExpectPointer(Case_p, __FILE__, __LINE__, Expected, Got, #Got) + +#define ADBG_EXPECT_NOT_NULL(Case_p, Got) \ + Do_ADBG_ExpectPointerNotNULL(Case_p, __FILE__, __LINE__, Got, #Got) + +#define ADBG_EXPECT_COMPARE_SIGNED(Case_p, Val1, Compar, Val2) \ + Do_ADBG_ExpectCompareSigned(Case_p, __FILE__, __LINE__, \ + Val1, Val2, (Val1)Compar( \ + Val2), #Val1, #Compar, #Val2) + +#define ADBG_EXPECT_COMPARE_UNSIGNED(Case_p, Val1, Compar, Val2) \ + Do_ADBG_ExpectCompareUnsigned(Case_p, __FILE__, __LINE__, \ + Val1, Val2, (Val1)Compar( \ + Val2), #Val1, #Compar, #Val2) + +#define ADBG_EXPECT_COMPARE_POINTER(Case_p, Val1, Compar, Val2) \ + Do_ADBG_ExpectComparePointer(Case_p, __FILE__, __LINE__, \ + Val1, Val2, (Val1)Compar( \ + Val2), #Val1, #Compar, #Val2) + +bool Do_ADBG_Expect(ADBG_Case_t *const Case_p, const char *const FileName_p, + const int LineNumber, const int Expected, const int Got, + const char *const GotVarName_p, + const ADBG_EnumTable_t *const EnumTable_p); + +bool Do_ADBG_ExpectNot(ADBG_Case_t *const Case_p, const char *const FileName_p, + const int LineNumber, const int NotExpected, + const int Got, const char *const GotVarName_p, + const ADBG_EnumTable_t *const EnumTable_p); + +bool Do_ADBG_ExpectBuffer(ADBG_Case_t *const Case_p, + const char *const FileName_p, const int LineNumber, + const void *const ExpectedBuffer_p, + const size_t ExpectedBufferLength, + const char *const GotBufferName_p, + const void *const GotBuffer_p, + const char *const GotBufferLengthName_p, + const size_t GotBufferLength); + +bool Do_ADBG_ExpectPointer(ADBG_Case_t *const Case_p, + const char *const FileName_p, const int LineNumber, + const void *Expected_p, const void *Got_p, + const char *const GotVarName_p); + +bool Do_ADBG_ExpectPointerNotNULL(ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, const void *Got_p, + const char *const GotVarName_p); + +bool Do_ADBG_ExpectCompareSigned(ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, const long Value1, + const long Value2, const bool Result, + const char *const Value1Str_p, + const char *const ComparStr_p, + const char *const Value2Str_p); + +bool Do_ADBG_ExpectCompareUnsigned(ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const unsigned long Value1, + const unsigned long Value2, + const bool Result, + const char *const Value1Str_p, + const char *const ComparStr_p, + const char *const Value2Str_p); + +bool Do_ADBG_ExpectComparePointer(ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const void *const Value1_p, + const void *const Value2_p, const bool Result, + const char *const Value1Str_p, + const char *const ComparStr_p, + const char *const Value2Str_p); + +const char *Do_ADBG_GetEnumName(const int Value, + const ADBG_EnumTable_t *const EnumTable_p); + +/** + * Writes a string to output. + * String length max is defined by ADBG_STRING_LENGTH_MAX + * + * @param Format_p The formatting string as in printf + */ +void Do_ADBG_Log(const char *const Format_p, ...) +__attribute__((__format__(__printf__, 1, 2))); + +/** + * Writes out the contents of buf_p formatted so that each line will + * have cols number of columns. + * + * @param[in] Buf_p Buffer to print + * @param[in] Size Size of buffer (in bytes) + * @param[in] Cols Number of columns. + */ +void Do_ADBG_HexLog(const void *const Buf_p, const size_t Size, + const size_t Cols); + +/* + * Suite functions + */ + +int Do_ADBG_RunSuite(const ADBG_Suite_Definition_t *Suite_p, int argc, + char *argv[]); +int Do_ADBG_AppendToSuite(ADBG_Suite_Definition_t *Dest_p, + ADBG_Suite_Definition_t *Source_p); + +/* + * SubCase functions + */ +void Do_ADBG_BeginSubCase(ADBG_Case_t *const Case_p, + const char *const FormatTitle_p, + ...) __attribute__((__format__(__printf__, 2, 3))); + +void Do_ADBG_EndSubCase(ADBG_Case_t *const Case_p, + const char *const FormatTitle_p, + ...) __attribute__((__format__(__printf__, 2, 3))); + +#endif /* ADBG_H */ diff --git a/optee/optee_test/host/xtest/adbg/src/adbg_case.c b/optee/optee_test/host/xtest/adbg/src/adbg_case.c new file mode 100644 index 0000000..c02634a --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/src/adbg_case.c @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/************************************************************************* +* 1. Includes +*************************************************************************/ +#include "adbg_int.h" + +/************************************************************************* +* 2. Definition of external constants and variables +*************************************************************************/ + +/************************************************************************* +* 3. File scope types, constants and variables +*************************************************************************/ + +/************************************************************************* +* 4. Declaration of file local functions +*************************************************************************/ + +/* + * Deletes a subcase. Don't call this function before the + * subcase is removed from list. + */ +static void ADBG_SubCase_Delete(ADBG_SubCase_t *SubCase); + +static ADBG_SubCase_t *ADBG_Case_CreateSubCase(ADBG_Case_t *Case_p, + const char *const Title_p); + +static ADBG_SubCase_t *ADBG_Case_GetParentSubCase(ADBG_Case_t *Case_p, + ADBG_SubCase_t *SubCase_p); + +static const char *ADBG_Case_GetTestID(ADBG_Case_t *Case_p); + +/************************************************************************* +* 5. Definition of external functions +*************************************************************************/ +ADBG_Case_t *ADBG_Case_New(const struct adbg_case_def *case_def) +{ + ADBG_Case_t *Case_p = NULL; + + Case_p = calloc(1, sizeof(*Case_p)); + if (Case_p) + Case_p->case_def = case_def; + + return Case_p; +} + +void ADBG_Case_Delete(ADBG_Case_t *Case_p) +{ + ADBG_SubCase_Delete(Case_p->FirstSubCase_p); + free(Case_p); +} + +bool ADBG_Case_SubCaseIsMain( + const ADBG_Case_t *const Case_p, + const ADBG_SubCase_t *const SubCase_p + ) +{ + IDENTIFIER_NOT_USED(Case_p) + return SubCase_p->Parent_p == NULL; +} + + +void ADBG_Case_IterateSubCase( + ADBG_Case_t *Case_p, + ADBG_SubCase_Iterator_t *Iterator_p + ) +{ + Iterator_p->Case_p = Case_p; + Iterator_p->CurrentSubCase_p = NULL; +} + +ADBG_SubCase_t *ADBG_Case_NextSubCase( + ADBG_SubCase_Iterator_t *Iterator_p + ) +{ + ADBG_Case_t *Case_p = Iterator_p->Case_p; + ADBG_SubCase_t *SubCase_p = Iterator_p->CurrentSubCase_p; + + + /* + * Traverse the subcases depth first, that is: + * 1.1.1.1 + * 1.1.1.2 + * 1.1.1 + * 1.1.2.1 + * 1.1.2 + * 1.1 + * 1.2.1 + * 1.2 + * 1 + */ + if (SubCase_p == NULL) { + /* Find the first leaf */ + SubCase_p = Case_p->FirstSubCase_p; + if (SubCase_p == NULL) + goto CleanupReturn; + + while (!TAILQ_EMPTY(&SubCase_p->SubCasesList)) + SubCase_p = TAILQ_FIRST(&SubCase_p->SubCasesList); + goto CleanupReturn; + } + + /* + * Look for the next leaf belonging to the parent + */ + + if (SubCase_p->Parent_p == NULL) { + /* If parent is NULL this is the top + subcase and we're done */ + SubCase_p = NULL; + goto CleanupReturn; + } + + if (TAILQ_NEXT(SubCase_p, Link) == NULL) { + /* If this is the last subcase of the + parent move up to parent */ + SubCase_p = SubCase_p->Parent_p; + goto CleanupReturn; + } + + /* + * Find next leaf + */ + SubCase_p = TAILQ_NEXT(SubCase_p, Link); + while (!TAILQ_EMPTY(&SubCase_p->SubCasesList)) + SubCase_p = TAILQ_FIRST(&SubCase_p->SubCasesList); + +CleanupReturn: + Iterator_p->CurrentSubCase_p = SubCase_p; + return SubCase_p; +} + +void Do_ADBG_BeginSubCase( + ADBG_Case_t *const Case_p, + const char *const FormatTitle_p, ... + ) +{ + ADBG_SubCase_t *SubCase_p = NULL; + + if (Case_p == NULL) { + Do_ADBG_Log("Do_ADBG_BeginSubCase: NULL Case_p!"); + return; + } + + if (FormatTitle_p == NULL) { + Do_ADBG_Log("Do_ADBG_BeginSubCase: NULL FormatTitle_p!"); + return; + } + + va_list ArgList; + char Title[80] = { }; + + va_start(ArgList, FormatTitle_p); + vsnprintf(Title, sizeof(Title), FormatTitle_p, ArgList); + va_end(ArgList); + + SubCase_p = ADBG_Case_CreateSubCase(Case_p, Title); + + if (SubCase_p == NULL) { + Do_ADBG_Log("Do_ADBG_BeginSubCase: HEAP_ALLOC failed"); + return; + } + + + if (ADBG_Case_SubCaseIsMain(Case_p, SubCase_p)) { + /* Main SubCase */ + Do_ADBG_Log(" "); + Do_ADBG_Log("* %s %s", SubCase_p->TestID_p, SubCase_p->Title_p); + } else { + Do_ADBG_Log("o %s %s", SubCase_p->TestID_p, SubCase_p->Title_p); + } +} + +void Do_ADBG_EndSubCase( + ADBG_Case_t *const Case_p, + const char *const FormatTitle_p, ... + ) +{ + va_list ArgList; + char Title[80] = { }; + ADBG_SubCase_t *SubCase_p = NULL; + + if (Case_p == NULL) { + Do_ADBG_Log("Do_ADBG_EndSubCase: NULL Case_p!"); + return; + } + + if (FormatTitle_p == NULL) { + strcpy(Title, "NULL"); + } else { + va_start(ArgList, FormatTitle_p); + vsnprintf(Title, sizeof(Title), FormatTitle_p, ArgList); + va_end(ArgList); + } + + + SubCase_p = Case_p->CurrentSubCase_p; + + if (SubCase_p == NULL) { + Do_ADBG_Log("Do_ADBG_EndSubCase: " + "Have no active SubCase, bailing out for title \"%s\"", + Title); + return; + } + + if (FormatTitle_p != NULL && strcmp(SubCase_p->Title_p, Title) != 0) { + Do_ADBG_Log("Do_ADBG_EndSubCase: " + "Active SubCase \"%s\" doesn't match supplied title \"%s\"", + SubCase_p->Title_p, Title); + return; + } + + if (ADBG_Case_SubCaseIsMain(Case_p, SubCase_p)) { + if (FormatTitle_p == NULL) { + /* To end the main subcase we require + a matching title */ + Do_ADBG_Log("Do_ADBG_EndSubCase: " + "The main SubCase \"%s\" doesn't match supplied title \"%s\"", + SubCase_p->Title_p, Title); + return; + } + /* + * Ending the main subcase + * make a complete copy of the aggregated result. + */ + Case_p->Result = SubCase_p->Result; + } else { + /* + * Ending a subcase, + * Aggregate results to parent. + */ + ADBG_SubCase_t *Parent_p = SubCase_p->Parent_p; + + Parent_p->Result.NumSubTests += SubCase_p->Result.NumTests + + SubCase_p->Result.NumSubTests; + Parent_p->Result.NumFailedSubTests += + SubCase_p->Result.NumFailedTests + + SubCase_p->Result. + NumFailedSubTests; + Parent_p->Result.AbortTestSuite = + SubCase_p->Result.AbortTestSuite; + if (SubCase_p->Result.NumTests > 0 || + SubCase_p->Result.NumSubTests > 0) + Parent_p->Result.NumFailedSubCases++; + } + + /* Print a summary of the subcase result */ + if (SubCase_p->Result.NumFailedTests > 0 || + SubCase_p->Result.NumFailedSubTests > 0) { + Do_ADBG_Log(" %s FAILED", SubCase_p->TestID_p); + } else { + Do_ADBG_Log(" %s OK", SubCase_p->TestID_p); + } + + /* Update current subcase to be the parent of this subcase */ + Case_p->CurrentSubCase_p = + ADBG_Case_GetParentSubCase(Case_p, SubCase_p); +} + +/************************************************************************* +* 6. Definition of internal functions +*************************************************************************/ +static ADBG_SubCase_t *ADBG_Case_CreateSubCase( + ADBG_Case_t *Case_p, + const char *const Title_p + ) +{ + ADBG_SubCase_t *SubCase_p = NULL; + + SubCase_p = calloc(1, sizeof(*SubCase_p)); + if (SubCase_p == NULL) + goto ErrorReturn; + + TAILQ_INIT(&SubCase_p->SubCasesList); + + SubCase_p->Title_p = strdup(Title_p); + if (SubCase_p->Title_p == NULL) + goto ErrorReturn; + + /* Set parent pointer needed "early" below. */ + SubCase_p->Parent_p = Case_p->CurrentSubCase_p; + + if (SubCase_p->Parent_p == NULL) { + /* Main SubCase */ + SubCase_p->TestID_p = strdup(ADBG_Case_GetTestID(Case_p)); + if (SubCase_p->TestID_p == NULL) + goto ErrorReturn; + + Case_p->FirstSubCase_p = SubCase_p; + } else { + ADBG_SubCase_t *Parent_p = SubCase_p->Parent_p; + char PrefixTitle[80] = { }; + + /* Update parent SubCase */ + Parent_p->Result.NumSubCases++; + snprintf(PrefixTitle, sizeof(PrefixTitle), "%s.%d", + Parent_p->TestID_p, Parent_p->Result.NumSubCases); + SubCase_p->TestID_p = strdup(PrefixTitle); + if (SubCase_p->TestID_p == NULL) + goto ErrorReturn; + + TAILQ_INSERT_TAIL(&Parent_p->SubCasesList, SubCase_p, Link); + } + + Case_p->CurrentSubCase_p = SubCase_p; + return SubCase_p; + +ErrorReturn: + ADBG_SubCase_Delete(SubCase_p); + return NULL; +} + +static void ADBG_SubCase_Delete( + ADBG_SubCase_t *SubCase_p + ) +{ + if (SubCase_p != NULL) { + /* + * Note that Util_ListDestroy() checks + * if SubCase_p->SubCasesList_p + * is NULL. + */ + while (true) { + ADBG_SubCase_t *s = + TAILQ_FIRST(&SubCase_p->SubCasesList); + + if (s == NULL) + break; + + TAILQ_REMOVE(&SubCase_p->SubCasesList, s, Link); + ADBG_SubCase_Delete(s); + } + free(SubCase_p->TestID_p); + free(SubCase_p->Title_p); + free(SubCase_p); + } +} + +ADBG_SubCase_t *ADBG_Case_GetParentSubCase( + ADBG_Case_t *Case_p, + ADBG_SubCase_t *SubCase_p + ) +{ + IDENTIFIER_NOT_USED(Case_p) + IDENTIFIER_NOT_USED(SubCase_p) + return SubCase_p->Parent_p; +} + +static const char *ADBG_Case_GetTestID(ADBG_Case_t *Case_p) +{ + IDENTIFIER_NOT_USED(Case_p) + + return Case_p->case_def->TestID_p; +} diff --git a/optee/optee_test/host/xtest/adbg/src/adbg_enum.c b/optee/optee_test/host/xtest/adbg/src/adbg_enum.c new file mode 100644 index 0000000..0d3080b --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/src/adbg_enum.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/************************************************************************* +* 1. Includes +*************************************************************************/ +#include "adbg_int.h" + +/************************************************************************* +* 2. Definition of external constants and variables +*************************************************************************/ + + +ADBG_ENUM_TABLE_DEFINE_BEGIN(Boolean) +ADBG_ENUM_TABLE_ENTRY(false), +ADBG_ENUM_TABLE_ENTRY(true) +ADBG_ENUM_TABLE_DEFINE_END(Boolean); + + +/************************************************************************* +* 3. File scope types, constants and variables +*************************************************************************/ + +/************************************************************************* +* 4. Declaration of file local functions +*************************************************************************/ + +/************************************************************************* +* 5. Definition of external functions +*************************************************************************/ +const char *Do_ADBG_GetEnumName( + const int Value, + const ADBG_EnumTable_t *const EnumTable_p + ) +{ + const ADBG_EnumTable_t *Entry_p = EnumTable_p; + + for (; Entry_p->Name_p != NULL; Entry_p++) { + if (Entry_p->Value == Value) + return Entry_p->Name_p; + } + return ""; +} + + +/************************************************************************* +* 6. Definition of internal functions +*************************************************************************/ diff --git a/optee/optee_test/host/xtest/adbg/src/adbg_expect.c b/optee/optee_test/host/xtest/adbg/src/adbg_expect.c new file mode 100644 index 0000000..4d8fea9 --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/src/adbg_expect.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/************************************************************************* + * 1. Includes + ************************************************************************/ +#include "adbg_int.h" + +/************************************************************************* + * 2. Definition of external constants and variables + ************************************************************************/ + +/************************************************************************* + * 3. File scope types, constants and variables + ************************************************************************/ + +/************************************************************************* + * 4. Declaration of file local functions + ************************************************************************/ + +static bool ADBG_AssertHelper(ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, const bool ExpressionOK); + +static const char *ADBG_GetFileBase(const char *const FileName_p); + +/************************************************************************* + * 5. Definition of external functions + ************************************************************************/ +bool Do_ADBG_Expect( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const int Expected, + const int Got, + const char *const GotVarName_p, + const ADBG_EnumTable_t *const EnumTable_p + ) +{ + if (ADBG_AssertHelper(Case_p, FileName_p, LineNumber, Expected == Got)) + return true; + + if (EnumTable_p != NULL) { + Do_ADBG_Log("%s:%d: %s has an unexpected value: 0x%x = %s, " + "expected 0x%x = %s", + ADBG_GetFileBase(FileName_p), LineNumber, + GotVarName_p, + Got, Do_ADBG_GetEnumName(Got, EnumTable_p), + Expected, + Do_ADBG_GetEnumName(Expected, EnumTable_p)); + } else { + Do_ADBG_Log( + "%s:%d: %s has an unexpected value: 0x%x, expected 0x%x", + ADBG_GetFileBase(FileName_p), LineNumber, + GotVarName_p, Got, Expected); + } + + return false; +} + +bool Do_ADBG_ExpectNot( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const int NotExpected, + const int Got, + const char *const GotVarName_p, + const ADBG_EnumTable_t *const EnumTable_p + ) +{ + if (ADBG_AssertHelper(Case_p, FileName_p, LineNumber, NotExpected != + Got)) + return true; + + if (EnumTable_p != NULL) { + Do_ADBG_Log("%s:%d: %s has an unexpected value: 0x%x = %s, " + "expected 0x%x = %s", + ADBG_GetFileBase(FileName_p), LineNumber, + GotVarName_p, + Got, Do_ADBG_GetEnumName(Got, EnumTable_p), + NotExpected, + Do_ADBG_GetEnumName(NotExpected, EnumTable_p)); + } else { + Do_ADBG_Log( + "%s:%d: %s has an unexpected value: 0x%zu, expected 0x%zu", + ADBG_GetFileBase(FileName_p), LineNumber, + GotVarName_p, (size_t)Got, (size_t)NotExpected); + } + + return false; +} + +bool Do_ADBG_ExpectBuffer( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const void *const ExpectedBuffer_p, + const size_t ExpectedBufferLength, + const char *const GotBufferName_p, + const void *const GotBuffer_p, + const char *const GotBufferLengthName_p, + const size_t GotBufferLength + ) +{ + if (!ADBG_AssertHelper(Case_p, FileName_p, LineNumber, + ExpectedBufferLength == GotBufferLength)) { + Do_ADBG_Log( + "%s:%d: %s has an unexpected value: %zu, expected %zu", + ADBG_GetFileBase( + FileName_p), LineNumber, + GotBufferLengthName_p, GotBufferLength, + ExpectedBufferLength); + return false; + } + + if (!ADBG_AssertHelper(Case_p, FileName_p, LineNumber, + memcmp(ExpectedBuffer_p, GotBuffer_p, + ExpectedBufferLength) == 0)) { + Do_ADBG_Log("%s:%d: %s has an unexpected content:", + ADBG_GetFileBase( + FileName_p), LineNumber, GotBufferName_p); + Do_ADBG_Log("Got"); + Do_ADBG_HexLog(GotBuffer_p, GotBufferLength, 16); + Do_ADBG_Log("Expected"); + Do_ADBG_HexLog(ExpectedBuffer_p, ExpectedBufferLength, 16); + return false; + } + + return true; +} + +bool Do_ADBG_ExpectPointer( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const void *Expected_p, + const void *Got_p, + const char *const GotVarName_p + ) +{ + if (ADBG_AssertHelper(Case_p, FileName_p, LineNumber, Expected_p == + Got_p)) + return true; + + Do_ADBG_Log("%s:%d: %s has an unexpected value: %p, expected %p", + ADBG_GetFileBase(FileName_p), LineNumber, + GotVarName_p, Got_p, Expected_p); + + return false; +} + + + +bool Do_ADBG_ExpectPointerNotNULL( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const void *Got_p, + const char *const GotVarName_p + ) +{ + if (ADBG_AssertHelper(Case_p, FileName_p, LineNumber, Got_p != NULL)) + return true; + + Do_ADBG_Log("%s:%d: %s has an unexpected value: %p, expected not NULL", + ADBG_GetFileBase(FileName_p), LineNumber, + GotVarName_p, Got_p); + + return false; +} + +bool Do_ADBG_ExpectCompareSigned( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const long Value1, + const long Value2, + const bool Result, + const char *const Value1Str_p, + const char *const ComparStr_p, + const char *const Value2Str_p + ) +{ + if (!ADBG_AssertHelper(Case_p, FileName_p, LineNumber, Result)) { + Do_ADBG_Log( + "%s:%d: Expression \"%s %s %s\" (%ld %s %ld) is false", + ADBG_GetFileBase(FileName_p), LineNumber, + Value1Str_p, ComparStr_p, Value2Str_p, + Value1, ComparStr_p, Value2); + } + return Result; +} + +bool Do_ADBG_ExpectCompareUnsigned( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const unsigned long Value1, + const unsigned long Value2, + const bool Result, + const char *const Value1Str_p, + const char *const ComparStr_p, + const char *const Value2Str_p + ) +{ + if (!ADBG_AssertHelper(Case_p, FileName_p, LineNumber, Result)) { + Do_ADBG_Log( + "%s:%d: Expression \"%s %s %s\" (%lu %s %lu) is false", + ADBG_GetFileBase(FileName_p), LineNumber, + Value1Str_p, ComparStr_p, Value2Str_p, + Value1, ComparStr_p, Value2); + } + return Result; +} + + +bool Do_ADBG_ExpectComparePointer( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const void *const Value1_p, + const void *const Value2_p, + const bool Result, + const char *const Value1Str_p, + const char *const ComparStr_p, + const char *const Value2Str_p + ) +{ + if (!ADBG_AssertHelper(Case_p, FileName_p, LineNumber, Result)) { + Do_ADBG_Log( + "%s:%d: Expression \"%s %s %s\" (%p %s %p) is false", + ADBG_GetFileBase(FileName_p), LineNumber, + Value1Str_p, ComparStr_p, Value2Str_p, + Value1_p, ComparStr_p, Value2_p); + } + return Result; +} + +/************************************************************************* + * 6. Definitions of internal functions + ************************************************************************/ +static bool ADBG_AssertHelper( + ADBG_Case_t *const Case_p, + const char *const FileName_p, + const int LineNumber, + const bool ExpressionOK + ) +{ + ADBG_SubCase_t *SubCase_p = Case_p->CurrentSubCase_p; + + IDENTIFIER_NOT_USED(Case_p) + + SubCase_p->Result.NumTests++; + + if (!ExpressionOK) { + SubCase_p->Result.NumFailedTests++; + if (SubCase_p->Result.FirstFailedRow == 0) { + SubCase_p->Result.FirstFailedRow = LineNumber; + SubCase_p->Result.FirstFailedFile_p = ADBG_GetFileBase( + FileName_p); + } + } + + return ExpressionOK; +} + +static const char *ADBG_GetFileBase(const char *const FileName_p) +{ + const char *Ch_p = FileName_p; + const char *Base_p = FileName_p; + + while (*Ch_p != '\0') { + if (*Ch_p == '\\') + Base_p = Ch_p + 1; + + Ch_p++; + } + + return Base_p; +} diff --git a/optee/optee_test/host/xtest/adbg/src/adbg_int.h b/optee/optee_test/host/xtest/adbg/src/adbg_int.h new file mode 100644 index 0000000..9f8265b --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/src/adbg_int.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef __ADBG_INT_H +#define __ADBG_INT_H +#include +#include +#include +#include +#include +#include +#include + +#include "security_utils_hex.h" + +typedef struct ADBG_Result { + int NumTests; + int NumFailedTests; + int NumSubTests; + int NumFailedSubTests; + int NumSubCases; + int NumFailedSubCases; + int FirstFailedRow; + char const *FirstFailedFile_p; + bool AbortTestSuite; +} ADBG_Result_t; + +TAILQ_HEAD(ADBG_SubCaseHead, ADBG_SubCase); +typedef struct ADBG_SubCaseHead ADBG_SubCaseHead_t; + +typedef struct ADBG_SubCase ADBG_SubCase_t; +struct ADBG_SubCase { + char *TestID_p; + char *Title_p; + ADBG_Result_t Result; + ADBG_SubCase_t *Parent_p; /* The SubCase where this SubCase was added */ + ADBG_SubCaseHead_t SubCasesList; /* SubCases created in this SubCase*/ + TAILQ_ENTRY(ADBG_SubCase) Link; +}; + +/* Typedefed in t_adbg.h */ +struct ADBG_Case { + const struct adbg_case_def *case_def; + + ADBG_SubCase_t *CurrentSubCase_p; + ADBG_SubCase_t *FirstSubCase_p; + + ADBG_Result_t Result; + TAILQ_ENTRY(ADBG_Case) Link; +}; + +typedef struct { + ADBG_Case_t *Case_p; + ADBG_SubCase_t *CurrentSubCase_p; +} ADBG_SubCase_Iterator_t; + +bool ADBG_Case_SubCaseIsMain(const ADBG_Case_t *const Case_p, + const ADBG_SubCase_t *const SubCase_p); + +void ADBG_Case_IterateSubCase(ADBG_Case_t *Case_p, + ADBG_SubCase_Iterator_t *Iterator_p); + +ADBG_SubCase_t *ADBG_Case_NextSubCase(ADBG_SubCase_Iterator_t *Iterator_p); + +ADBG_Case_t *ADBG_Case_New(const struct adbg_case_def *case_def); + +void ADBG_Case_Delete(ADBG_Case_t *Case_p); + +bool ADBG_TestIDMatches(const char *const TestID_p, + const char *const Argument_p); + +#define IDENTIFIER_NOT_USED(x) { if (sizeof(&x)) {} } + +#endif /* __ADBG_INT_H */ diff --git a/optee/optee_test/host/xtest/adbg/src/adbg_log.c b/optee/optee_test/host/xtest/adbg/src/adbg_log.c new file mode 100644 index 0000000..993f905 --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/src/adbg_log.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include "adbg_int.h" + +#include + +#include +/************************************************************************* + * 2. Definition of external constants and variables + ************************************************************************/ + +/************************************************************************* + * 3. File scope types, constants and variables + ************************************************************************/ + +/************************************************************************* + * 4. Declaration of file local functions + ************************************************************************/ + +/************************************************************************* + * 5. Definition of external functions + ************************************************************************/ + +/******************************************************************************/ +/*! @fn void Do_ADBG_Log( void* This_p, char* Format, ...) + * @brief + * @param [in] This_p + * @param [in] Format + * @param [in] ... + * @return void + */ +/******************************************************************************/ +void Do_ADBG_Log(const char *const Format, ...) +{ + va_list ap; + + va_start(ap, Format); + vprintf(Format, ap); + printf("\n"); + va_end(ap); + fflush(stdout); +} + +void Do_ADBG_HexLog( + const void *const Buf_p, + const size_t Size, + const size_t Cols + ) +{ + const uint8_t *Data_p = Buf_p; + size_t n = 0; + + for (n = 0; n < Size; n += Cols) { + char HexBuffer[ADBG_STRING_LENGTH_MAX]; + char AsciiBuffer[ADBG_STRING_LENGTH_MAX / 3]; + size_t m, NumCols; + + (void)SecUtil_BufferToHex(Data_p + n, MIN(Cols, Size - n), NULL, + HexBuffer, sizeof(HexBuffer)); + NumCols = MIN(MIN(Cols, Size - n), sizeof(AsciiBuffer) - 1); + for (m = 0; m < NumCols; m++) { + int ch = Data_p[n + m]; + + if (isprint(ch)) + AsciiBuffer[m] = (char)ch; + else + AsciiBuffer[m] = '.'; + } + AsciiBuffer[m] = '\0'; + + Do_ADBG_Log(" %-*s %s", (int)Cols * 3, HexBuffer, AsciiBuffer); + } +} + +/************************************************************************* + * 6. Definitions of internal functions + ************************************************************************/ diff --git a/optee/optee_test/host/xtest/adbg/src/adbg_run.c b/optee/optee_test/host/xtest/adbg/src/adbg_run.c new file mode 100644 index 0000000..da274e9 --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/src/adbg_run.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/************************************************************************* + * 1. Includes + ************************************************************************/ +#include "adbg_int.h" + +/************************************************************************* + * 2. Definition of external constants and variables + ************************************************************************/ +#ifndef TAILQ_CONCAT +#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) +#endif + +/************************************************************************* + * 3. File scope types, constants and variables + ************************************************************************/ + +TAILQ_HEAD(ADBG_CaseHead, ADBG_Case); +typedef struct ADBG_CaseHead ADBG_CaseHead_t; + +typedef struct ADBG_Runner { + ADBG_Result_t Result; + const ADBG_Suite_Definition_t *Suite_p; + + ADBG_CaseHead_t CasesList; +} ADBG_Runner_t; + +/************************************************************************* + * 4. Declaration of file local functions + ************************************************************************/ + +static int ADBG_RunSuite(ADBG_Runner_t *Runner_p, int argc, char *argv[]); + + +/************************************************************************* + * 5. Definition of external functions + ************************************************************************/ +int Do_ADBG_RunSuite( + const ADBG_Suite_Definition_t *Suite_p, + int argc, + char *argv[] + ) +{ + ADBG_Runner_t *Runner_p = NULL; + + Runner_p = calloc(1, sizeof(*Runner_p)); + if (Runner_p == NULL) { + Do_ADBG_Log("calloc failed for Suite %s!", + Suite_p->SuiteID_p); + return -1; + } + TAILQ_INIT(&Runner_p->CasesList); + Runner_p->Suite_p = Suite_p; + + int ret = ADBG_RunSuite(Runner_p, argc, argv); + free(Runner_p); + return ret; +} + +int Do_ADBG_AppendToSuite( + ADBG_Suite_Definition_t *Dest_p, + ADBG_Suite_Definition_t *Source_p + ) +{ + char *p = NULL; + size_t size = 0; + + /* Append name of 'Source_p' to name of 'Dest_p' */ + size = strlen(Source_p->SuiteID_p); + if (Dest_p->SuiteID_p) { + size += strlen(Dest_p->SuiteID_p); + size += 1; /* '+' */ + } + size += 1; /* '\0' */ + p = malloc(size); + if (!p) { + fprintf(stderr, "malloc failed\n"); + return -1; + } + if (Dest_p->SuiteID_p) + snprintf(p, size, "%s+%s", Dest_p->SuiteID_p, + Source_p->SuiteID_p); + else + snprintf(p, size, "%s", Source_p->SuiteID_p); + free((void *)Dest_p->SuiteID_p); + Dest_p->SuiteID_p = p; + + TAILQ_CONCAT(&Dest_p->cases, &Source_p->cases, link); + return 0; +} + +/************************************************************************* + * 6. Definitions of internal functions + ************************************************************************/ +static int ADBG_RunSuite( + ADBG_Runner_t *Runner_p, + int argc, + char *argv[] + ) +{ + ADBG_Case_t *Case_p = NULL; + size_t NumSkippedTestCases = 0; + int failed_test = 0; + struct adbg_case_def *case_def = NULL; + + Do_ADBG_Log("######################################################"); + Do_ADBG_Log("#"); + Do_ADBG_Log("# %s", Runner_p->Suite_p->SuiteID_p); + Do_ADBG_Log("#"); + Do_ADBG_Log("######################################################"); + + TAILQ_FOREACH(case_def, &Runner_p->Suite_p->cases, link) { + /* Default match if by default all tests are to be run */ + bool HaveMatch = !argc || !strcmp(argv[0], "-x"); + int i = 0; + + for (i = 0; i < argc; i++) { + if (!strcmp(argv[i], "-x")) { + i++; + if (i >= argc) { + Do_ADBG_Log("Error: -x "); + return 1; + } + if (strstr(case_def->TestID_p, argv[i])) + HaveMatch = false; + } else { + if (strstr(case_def->TestID_p, argv[i])) + HaveMatch = true; + } + } + if (!HaveMatch) { + NumSkippedTestCases++; + continue; + } + + Case_p = ADBG_Case_New(case_def); + if (Case_p == NULL) { + Do_ADBG_Log("HEAP_ALLOC failed for Case %s!", + case_def->TestID_p); + Runner_p->Result.AbortTestSuite = 1; + break; + } + + TAILQ_INSERT_TAIL(&Runner_p->CasesList, Case_p, Link); + + /* Start the parent test case */ + Do_ADBG_BeginSubCase(Case_p, "%s", case_def->Title_p); + + case_def->Run_fp(Case_p); + + /* End abondoned subcases */ + while (Case_p->CurrentSubCase_p != Case_p->FirstSubCase_p) + Do_ADBG_EndSubCase(Case_p, NULL); + + /* End the parent test case */ + Do_ADBG_EndSubCase(Case_p, "%s", case_def->Title_p); + + /* Sum up the errors */ + Runner_p->Result.NumTests += Case_p->Result.NumTests + + Case_p->Result.NumSubTests; + Runner_p->Result.NumFailedTests += + Case_p->Result.NumFailedTests + + Case_p->Result. + NumFailedSubTests; + Runner_p->Result.NumSubCases++; + if (Case_p->Result.NumFailedTests + + Case_p->Result.NumFailedSubTests > 0) + Runner_p->Result.NumFailedSubCases++; + + Runner_p->Result.AbortTestSuite = Case_p->Result.AbortTestSuite; + + if (Runner_p->Result.AbortTestSuite) { + Do_ADBG_Log("Test suite aborted by %s!", + case_def->TestID_p); + break; + } + } + + Do_ADBG_Log("+-----------------------------------------------------"); + if (argc > 0) { + bool test_exclusion = false; + int i = 0; + + for (i = 0; i < argc; i++) { + if (!strcmp(argv[i], "-x")) { + test_exclusion = true; + continue; + } + Do_ADBG_Log( + "Result of testsuite %s filtered by \"%s%s\":", + Runner_p->Suite_p->SuiteID_p, + test_exclusion ? "-x " : "", argv[i]); + test_exclusion = false; + } + } else { + Do_ADBG_Log("Result of testsuite %s:", + Runner_p->Suite_p->SuiteID_p); + } + + TAILQ_FOREACH(Case_p, &Runner_p->CasesList, Link) { + ADBG_SubCase_Iterator_t Iterator; + ADBG_SubCase_t *SubCase_p; + + ADBG_Case_IterateSubCase(Case_p, &Iterator); + while ((SubCase_p = ADBG_Case_NextSubCase(&Iterator)) != NULL) { + if (SubCase_p->Result.NumFailedTests + + SubCase_p->Result.NumFailedSubTests > 0) { + if (SubCase_p->Result.FirstFailedFile_p != + NULL) { + Do_ADBG_Log( + "%s FAILED first error at %s:%d", + SubCase_p->TestID_p, + SubCase_p-> + Result.FirstFailedFile_p, + SubCase_p-> + Result.FirstFailedRow); + } else { + Do_ADBG_Log("%s FAILED", + SubCase_p->TestID_p); + } + } else if (ADBG_Case_SubCaseIsMain(Case_p, SubCase_p)) { + /* A level one test case is displayed + if successfull too */ + Do_ADBG_Log("%s OK", SubCase_p->TestID_p); + } + } + } + + + Do_ADBG_Log("+-----------------------------------------------------"); + if (Runner_p->Result.AbortTestSuite) + Do_ADBG_Log("Test suite was ABORTED"); + + Do_ADBG_Log("%d subtest%s of which %d failed", + Runner_p->Result.NumTests, + Runner_p->Result.NumTests != 1 ? "s" : "", + Runner_p->Result.NumFailedTests); + Do_ADBG_Log("%d test case%s of which %d failed", + Runner_p->Result.NumSubCases, + Runner_p->Result.NumSubCases != 1 ? "s" : "", + Runner_p->Result.NumFailedSubCases); + Do_ADBG_Log("%zu test case%s skipped", + NumSkippedTestCases, + NumSkippedTestCases != 1 ? "s were" : " was"); + + failed_test = Runner_p->Result.NumFailedSubCases; + + while (true) { + Case_p = TAILQ_FIRST(&Runner_p->CasesList); + if (Case_p == NULL) + break; + TAILQ_REMOVE(&Runner_p->CasesList, Case_p, Link); + ADBG_Case_Delete(Case_p); + } + return failed_test; +} diff --git a/optee/optee_test/host/xtest/adbg/src/security_utils_hex.c b/optee/optee_test/host/xtest/adbg/src/security_utils_hex.c new file mode 100644 index 0000000..3526561 --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/src/security_utils_hex.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +/************************************************************************* +* 1. Includes +*************************************************************************/ +#include +#include +#include +#include + +#include "security_utils_hex.h" + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + + +/************************************************************************* +* 2. Definition of external constants and variables +*************************************************************************/ + +/************************************************************************* +* 3. File scope types, constants and variables +*************************************************************************/ +static const char SecUtil_HexChars[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; +/************************************************************************* +* 4. Declaration of file local functions +*************************************************************************/ + +/************************************************************************* +* 5. Definition of external functions +*************************************************************************/ +#if 0 +void SecBase_HexPrintBuffer( + const char *Prefix_p, + const char *Postfix_p, + const char *BufferName_p, + const void *Buffer_p, + size_t BufferLength + ) +{ + char LineBuf[67]; + size_t LinePos = 0; + const uint8 *Data_p = Buffer_p; + size_t n; + char EmptyString[] = ""; + + if (Prefix_p == NULL) + Prefix_p = EmptyString; + if (Postfix_p == NULL) + Postfix_p = EmptyString; + + if (BufferName_p != NULL) { + DELAY_MS(5); + printf("%s%s: Size: %d%s", Prefix_p, BufferName_p, BufferLength, + Postfix_p); + } + + /* Initialize the line buffer for a new line */ + SEC_MEM_SET(LineBuf, ' ', sizeof(LineBuf)); + LineBuf[sizeof(LineBuf) - 1] = '\0'; + LinePos = 0; + for (n = 0; n < BufferLength; n++) { + char Separator; + char PrintableChar; + + if (((n + 1) % 4) == 0) + Separator = ' '; + else + Separator = ':'; + + if (isprint(Data_p[n])) + PrintableChar = (char)Data_p[n]; + else + PrintableChar = '.'; + + LineBuf[LinePos * 3 + 0] = SecBase_HexChars[Data_p[n] >> 4]; + LineBuf[LinePos * 3 + 1] = SecBase_HexChars[Data_p[n] & 0x0F]; + LineBuf[LinePos * 3 + 2] = Separator; + LineBuf[50 + LinePos] = PrintableChar; + + LinePos++; + if (LinePos == 16) { + DELAY_MS(5); + printf("%s%s%s", Prefix_p, LineBuf, Postfix_p); + /* Initialize the line buffer for a new line */ + SEC_MEM_SET(LineBuf, ' ', sizeof(LineBuf)); + LineBuf[sizeof(LineBuf) - 1] = '\0'; + LinePos = 0; + } + } + if (LinePos != 0) { + DELAY_MS(5); + printf("%s%s%s", Prefix_p, LineBuf, Postfix_p); + } + (void)fflush(stdout); +} +#endif + +#if 0 +void SecUtil_CHexPrintBuffer( + const char *Prefix_p, + const char *Postfix, + const void *Buffer_p, + size_t BufferLength + ) +{ + char LineBuf[84]; + const uint8 *Data_p = Buffer_p; + size_t n; + char EmptyString[] = ""; + static const SecUtil_HexFormat_t HexFormat = { "0x", ", ", ", " }; + + if (Prefix_p == NULL) + Prefix_p = EmptyString; + if (Postfix == NULL) + Postfix = EmptyString; + + for (n = 0; n < BufferLength; n += 16) { + (void)SecUtil_BufferToHex(Data_p + n, MIN(16, BufferLength - n), + &HexFormat, + LineBuf, sizeof(LineBuf)); + DELAY_MS(5); + printf("%s%s%s", Prefix_p, LineBuf, Postfix); + } +} +#endif + +size_t SecUtil_BufferToHex( + const void *const Buffer_p, + size_t BufferLength, + const SecUtil_HexFormat_t *const HexFormat_p, + char *const Destination_p, + const size_t DestinationLength + ) +{ + const uint8_t *Data_p = Buffer_p; + size_t UsedDestLength = 0; + size_t n = 0; + const char *ByteSeparator_p = NULL; + const char *GroupSeparator_p = NULL; + const char *BytePrefix_p = NULL; + size_t BytePrefixLength = 0; + + if (DestinationLength > 1) + Destination_p[0] = '\0'; + + UsedDestLength = 1; + + if (HexFormat_p != NULL) { + BytePrefix_p = HexFormat_p->BytePrefix_p; + ByteSeparator_p = HexFormat_p->ByteSeparator_p; + GroupSeparator_p = HexFormat_p->GroupSeparator_p; + } + + if (BytePrefix_p == NULL) + BytePrefix_p = ""; + + BytePrefixLength = strlen(BytePrefix_p); + + if (ByteSeparator_p == NULL) + ByteSeparator_p = ":"; + + if (GroupSeparator_p == NULL) + GroupSeparator_p = " "; + + /* + * This for loop is unnecessarily complicated due to + * the absense of both snprintf and strlcat + */ + for (n = 0; n < BufferLength; n++) { + const char *Separator_p = NULL; + size_t SeparatorLength = 0; + + /* Establish separator for this byte and the next */ + if (n == BufferLength - 1) + Separator_p = ""; + else if ((n + 1) % 4 == 0) + Separator_p = GroupSeparator_p; + else + Separator_p = ByteSeparator_p; + + SeparatorLength = strlen(Separator_p); + + /* Insert the Byte prefix */ + if (UsedDestLength < DestinationLength) { + size_t CopyLength = 0; + + CopyLength = MIN(BytePrefixLength, + DestinationLength - UsedDestLength); + memcpy(Destination_p + UsedDestLength - 1, BytePrefix_p, + CopyLength); + Destination_p[UsedDestLength - 1 + CopyLength] = '\0'; + } + UsedDestLength += BytePrefixLength; + + /* Insert the first nibble of the ASCII hexadecimal byte */ + if (UsedDestLength < DestinationLength) { + Destination_p[UsedDestLength - + 1] = SecUtil_HexChars[Data_p[n] >> 4]; + Destination_p[UsedDestLength] = '\0'; + } + UsedDestLength++; + + /* Insert the second nibble of the ASCII hexadecimal byte */ + if (UsedDestLength < DestinationLength) { + Destination_p[UsedDestLength - + 1] = SecUtil_HexChars[Data_p[n] & 0x0F]; + Destination_p[UsedDestLength] = '\0'; + } + UsedDestLength++; + + /* Insert the separator */ + if (UsedDestLength < DestinationLength) { + size_t CopyLength = 0; + + CopyLength = MIN(SeparatorLength, + DestinationLength - UsedDestLength); + memcpy(Destination_p + UsedDestLength - 1, Separator_p, + CopyLength); + Destination_p[UsedDestLength - 1 + CopyLength] = '\0'; + } + UsedDestLength += SeparatorLength; + } + return UsedDestLength; +} + +/************************************************************************* +* 6. Definition of internal functions +*************************************************************************/ diff --git a/optee/optee_test/host/xtest/adbg/src/security_utils_hex.h b/optee/optee_test/host/xtest/adbg/src/security_utils_hex.h new file mode 100644 index 0000000..6fa5302 --- /dev/null +++ b/optee/optee_test/host/xtest/adbg/src/security_utils_hex.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef INCLUSION_GUARD_UTILS_HEX_H +#define INCLUSION_GUARD_UTILS_HEX_H +/************************************************************************* +* 1. Includes +*************************************************************************/ + +/************************************************************************* +* 2. Types, constants and external variables +*************************************************************************/ + +#if 0 /* Should format into a buffer instead */ +/** + ************************************************************************** + * Prints data hexadecimally to stdout + * + * Each line of binary data is printed as 66 characters on the format + * shown below: + * XX:XX:XX:XX XX:XX:XX:XX XX:XX:XX:XX XX:XX:XX:XX xxxxxxxxxxxxxxxx + * + * @param [in] Prefix_p String printed first each line, may be NULL + * to indicate the empty string + * @param [in] Postfix_p String printed last each line, may be NULL + * to indicate the empty string + * @param [in] BufferName_p Name of the buffer, if != NULL the name of the + * buffer is printed together with the length of + * the buffer before the data is printed + * @param [in] Buffer_p Pointer to a buffer holding the data + * @param [in] BufferLength Length of the buffer above + * + * @sigbased No + * @waitmode Wait mode + **************************************************************************/ +void SecUtil_HexPrintBuffer(const char *Prefix_p, const char *Postfix_p, + const char *BufferName_p, const void *Buffer_p, + size_t BufferLength); +#endif + +#if 0 +/** + ************************************************************************** + * Prints data hexadecimally in a format suitable for initialization of + * an array in c. + * + * 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, + * 0xXX,0xXX, + * + * @param [in] Prefix_p String printed first each line, may be NULL + * to indicate the empty string + * @param [in] Postfix_p String printed last each line, may be NULL + * to indicate the empty string + * @param [in] Buffer_p Pointer to a buffer holding the data + * @param [in] BufferLength Length of the buffer above + * + * @sigbased No + * @waitmode Wait mode + **************************************************************************/ +void SecUtil_CHexPrintBuffer(const char *Prefix_p, const char *Postfix_p, + const void *Buffer_p, size_t BufferLength); +#endif + +/************************************************************************** +* Specifies how hexadecial data should be formated +* +* @param BytePrefix_p ASCII string prefix for each hexadecimal +* byte printed (for example "0x"). If NULL +* nothing is inserted in front of a byte. +* @param ByteSeparator_p ASCII string to insert between each printed +* hexadecimal byte. If NULL a ":" is inserted +* between each hexadecial byte. +* @param GroupSeparator_p ASCII string to insert instead of +* ByteSeparator_p between each group +* of printed hexadecimal bytes. If NULL " " +* is used as group separator. +**************************************************************************/ +typedef struct { + const char *BytePrefix_p; + const char *ByteSeparator_p; + const char *GroupSeparator_p; +} SecUtil_HexFormat_t; + +/************************************************************************* +* 3. Functions +*************************************************************************/ + +/**************************************************************************** + * Formats data hexadecimally into an NULL terminated ASCII string in + * the format below. + * + * 0xXX:0xXX:0xXX:0xXX 0xXX:0xXX:0xXX:0xXX + * 0xXX:0xXX:0xXX:0xXX 0xXX:0xXX:0xXX:0xXX + * + * The colons and spaces in the result can be cusomized with ByteSeparator_p + * and GroupSeparator_p respectivly. + * + * @param [in] Buffer_p Pointer to a buffer holding the data + * @param [in] BufferLength Length of the buffer above + * @param [in] HexFormat_p How the data should be formatted + * @param [in, out] Destination_p Output ASCII buffer + * @param [in] DestinationLength Length of output buffer + * + * @returns The size of a needed DestinationLength, if greater than supplied + * DestinationLength the result in Destination_p is truncated but + * still NULL terminated. + * @sigbased No + * @waitmode Wait mode + **************************************************************************/ + +size_t SecUtil_BufferToHex(const void *const Buffer_p, size_t BufferLength, + const SecUtil_HexFormat_t *const HexFormat_p, + char *const Destination_p, + const size_t DestinationLength); + +#endif /*INCLUSION_GUARD_UTILS_HEX_H*/ diff --git a/optee/optee_test/host/xtest/aes_perf.c b/optee/optee_test/host/xtest/aes_perf.c new file mode 100644 index 0000000..70f2187 --- /dev/null +++ b/optee/optee_test/host/xtest/aes_perf.c @@ -0,0 +1,674 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crypto_common.h" +#include "xtest_helpers.h" + +#ifdef CFG_SECURE_DATA_PATH +#include "sdp_basic.h" + +static int input_sdp_fd; +static int output_sdp_fd; + +static const char *heap_name = DEFAULT_HEAP_NAME; +#endif /* CFG_SECURE_DATA_PATH */ + +/* + * Type of buffer used for the performance tests + * + * BUFFER_UNSPECIFIED test did not specify target buffer to use + * BUFFER_SHM_ALLOCATED buffer allocated in TEE SHM. + * BUFFER_SECURE_REGISTER secure buffer, registered to TEE at TA invoc. + * BUFFER_SECURE_PREREGISTERED secure buffer, registered once to TEE. + */ +enum buffer_types { + BUFFER_UNSPECIFIED = 0, + BUFFER_SHM_ALLOCATED, + BUFFER_SECURE_REGISTER, /* requires SDP */ + BUFFER_SECURE_PREREGISTERED, /* requires SDP */ +}; + +static enum buffer_types input_buffer = BUFFER_UNSPECIFIED; +static enum buffer_types output_buffer = BUFFER_UNSPECIFIED; + +static const char *buf_type_str(int buf_type) + { + static const char sec_prereg[] = "Secure memory, registered once to TEE"; + static const char sec_reg[] = "Secure memory, registered at each TEE invoke"; + static const char ns_alloc[] = "Non secure memory"; + static const char inval[] = "UNEXPECTED"; + + switch (buf_type) { + case BUFFER_SECURE_PREREGISTERED: + return sec_prereg; + case BUFFER_SECURE_REGISTER: + return sec_reg; + case BUFFER_SHM_ALLOCATED: + return ns_alloc; + default: + return inval; + } +} + +/* Are we running a SDP test: default to NO (is_sdp_test == 0) */ +static int is_sdp_test; + +/* + * TEE client stuff + */ + +static TEEC_Context ctx; +static TEEC_Session sess; +/* + * in_shm and out_shm are both IN/OUT to support dynamically choosing + * in_place == 1 or in_place == 0. + */ +static TEEC_SharedMemory in_shm = { + .flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT +}; +static TEEC_SharedMemory out_shm = { + .flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT +}; + +static void errx(const char *msg, TEEC_Result res, uint32_t *orig) +{ + fprintf(stderr, "%s: 0x%08x", msg, res); + if (orig) + fprintf(stderr, " (orig=%d)", (int)*orig); + fprintf(stderr, "\n"); + exit (1); +} + +static void check_res(TEEC_Result res, const char *errmsg, uint32_t *orig) +{ + if (res != TEEC_SUCCESS) + errx(errmsg, res, orig); +} + +static void open_ta(void) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_UUID uuid = TA_AES_PERF_UUID; + uint32_t err_origin = 0; + + res = TEEC_InitializeContext(NULL, &ctx); + check_res(res, "TEEC_InitializeContext", NULL); + + res = TEEC_OpenSession(&ctx, &sess, &uuid, TEEC_LOGIN_PUBLIC, NULL, + NULL, &err_origin); + check_res(res, "TEEC_OpenSession", &err_origin); +} + +/* + * Statistics + * + * We want to compute min, max, mean and standard deviation of processing time + */ + +struct statistics { + int n; + double m; + double M2; + double min; + double max; + int initialized; +}; + +/* Take new sample into account (Knuth/Welford algorithm) */ +static void update_stats(struct statistics *s, uint64_t t) +{ + double x = (double)t; + double delta = x - s->m; + + s->n++; + s->m += delta/s->n; + s->M2 += delta*(x - s->m); + if (!s->initialized) { + s->min = s->max = x; + s->initialized = 1; + } else { + if (s->min > x) + s->min = x; + if (s->max < x) + s->max = x; + } +} + +static double stddev(struct statistics *s) +{ + if (s->n < 2) + return NAN; + return sqrt(s->M2/s->n); +} + +static const char *mode_str(uint32_t mode) +{ + switch (mode) { + case TA_AES_ECB: + return "ECB"; + case TA_AES_CBC: + return "CBC"; + case TA_AES_CTR: + return "CTR"; + case TA_AES_XTS: + return "XTS"; + case TA_AES_GCM: + return "GCM"; + default: + return "???"; + } +} + +#define _TO_STR(x) #x +#define TO_STR(x) _TO_STR(x) + +static void usage(const char *progname, int keysize, int mode, size_t size, + size_t unit, int warmup, unsigned int l, unsigned int n) +{ + fprintf(stderr, "Usage: %s [-h]\n", progname); + fprintf(stderr, "Usage: %s [-d] [-i] [-k SIZE]", progname); + fprintf(stderr, " [-l LOOP] [-m MODE] [-n LOOP] [-r|--no-inited] [-s SIZE]"); + fprintf(stderr, " [-v [-v]] [-w SEC]"); +#ifdef CFG_SECURE_DATA_PATH + fprintf(stderr, " [--sdp [-Id|-Ir|-IR] [-Od|-Or|-OR]]"); +#endif + fprintf(stderr, "\n"); + fprintf(stderr, "AES performance testing tool for OP-TEE\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -d Test AES decryption instead of encryption\n"); + fprintf(stderr, " -h|--help Print this help and exit\n"); + fprintf(stderr, " -i|--in-place Use same buffer for input and output (decrypt in place)\n"); + fprintf(stderr, " -k SIZE Key size in bits: 128, 192 or 256 [%u]\n", keysize); + fprintf(stderr, " -l LOOP Inner loop iterations [%u]\n", l); + fprintf(stderr, " -m MODE AES mode: ECB, CBC, CTR, XTS, GCM [%s]\n", mode_str(mode)); + fprintf(stderr, " -n LOOP Outer test loop iterations [%u]\n", n); + fprintf(stderr, " --not-inited Do not initialize input buffer content.\n"); + fprintf(stderr, " -r|--random Get input data from /dev/urandom (default: all zeros)\n"); + fprintf(stderr, " -s SIZE Test buffer size in bytes [%zu]\n", size); + fprintf(stderr, " -u UNIT Divide buffer in UNIT-byte increments (+ remainder)\n"); + fprintf(stderr, " (0 to ignore) [%zu]\n", unit); + fprintf(stderr, " -v Be verbose (use twice for greater effect)\n"); + fprintf(stderr, " -w|--warmup SEC Warm-up time in seconds: execute a busy loop before\n"); + fprintf(stderr, " the test to mitigate the effects of cpufreq etc. [%u]\n", warmup); +#ifdef CFG_SECURE_DATA_PATH + fprintf(stderr, "Secure data path specific options:\n"); + fprintf(stderr, " --sdp Run the AES test in the scope fo a Secure Data Path test TA\n"); + fprintf(stderr, " --heap-name NAME Set heap name where to allocate secure buffers [%s]\n", heap_name); + fprintf(stderr, " -I... AES input test buffer management:\n"); + fprintf(stderr, " -Id allocate a non secure buffer (default)\n"); + fprintf(stderr, " -Ir allocate a secure buffer, registered at each TA invocation\n"); + fprintf(stderr, " -IR allocate a secure buffer, registered once in TEE\n"); + fprintf(stderr, " -O... AES output test buffer management:\n"); + fprintf(stderr, " -Od allocate a non secure buffer (default if \"--sdp\" is not set)\n"); + fprintf(stderr, " -Or allocate a secure buffer, registered at each TA invocation\n"); + fprintf(stderr, " -OR allocate a secure buffer, registered once in TEE (default if \"--sdp\")\n"); +#endif +} + +#ifdef CFG_SECURE_DATA_PATH +static void register_shm(TEEC_SharedMemory *shm, int fd) +{ + TEEC_Result res = TEEC_RegisterSharedMemoryFileDescriptor(&ctx, shm, fd); + + check_res(res, "TEEC_RegisterSharedMemoryFileDescriptor", NULL); +} +#endif + +static void allocate_shm(TEEC_SharedMemory *shm, size_t sz) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + + shm->buffer = NULL; + shm->size = sz; + res = TEEC_AllocateSharedMemory(&ctx, shm); + check_res(res, "TEEC_AllocateSharedMemory", NULL); +} + +/* initial test buffer allocation (eventual registering to TEEC) */ +static void alloc_buffers(size_t sz, int in_place, int verbosity) +{ + (void)verbosity; + + if (input_buffer == BUFFER_SHM_ALLOCATED) + allocate_shm(&in_shm, sz); +#ifdef CFG_SECURE_DATA_PATH + else { + input_sdp_fd = allocate_buffer(sz, heap_name, verbosity); + if (input_buffer == BUFFER_SECURE_PREREGISTERED) { + register_shm(&in_shm, input_sdp_fd); + close(input_sdp_fd); + } + } +#endif + + if (in_place) + return; + + if (output_buffer == BUFFER_SHM_ALLOCATED) + allocate_shm(&out_shm, sz); +#ifdef CFG_SECURE_DATA_PATH + else { + output_sdp_fd = allocate_buffer(sz, heap_name, verbosity); + if (output_buffer == BUFFER_SECURE_PREREGISTERED) { + register_shm(&out_shm, output_sdp_fd); + close(output_sdp_fd); + } + } +#endif +} + +static void free_shm(int in_place) +{ + (void)in_place; + + if (input_buffer == BUFFER_SHM_ALLOCATED && + output_buffer == BUFFER_SHM_ALLOCATED) { + TEEC_ReleaseSharedMemory(&in_shm); + TEEC_ReleaseSharedMemory(&out_shm); + return; + } + +#ifdef CFG_SECURE_DATA_PATH + if (input_buffer == BUFFER_SECURE_PREREGISTERED) + close(input_sdp_fd); + if (input_buffer != BUFFER_SECURE_REGISTER) + TEEC_ReleaseSharedMemory(&in_shm); + + if (in_place) + return; + + if (output_buffer == BUFFER_SECURE_PREREGISTERED) + close(output_sdp_fd); + if (output_buffer != BUFFER_SECURE_REGISTER) + TEEC_ReleaseSharedMemory(&out_shm); +#endif /* CFG_SECURE_DATA_PATH */ +} + +static ssize_t read_random(void *in, size_t rsize) +{ + static int rnd; + ssize_t s = 0; + + if (!rnd) { + rnd = open("/dev/urandom", O_RDONLY); + if (rnd < 0) { + perror("open"); + return 1; + } + } + s = read(rnd, in, rsize); + if (s < 0) { + perror("read"); + return 1; + } + if ((size_t)s != rsize) { + printf("read: requested %zu bytes, got %zd\n", rsize, s); + } + + return 0; +} + +static void get_current_time(struct timespec *ts) +{ + if (clock_gettime(CLOCK_MONOTONIC, ts) < 0) { + perror("clock_gettime"); + exit(1); + } +} + +static uint64_t timespec_to_ns(struct timespec *ts) +{ + return ((uint64_t)ts->tv_sec * 1000000000) + ts->tv_nsec; +} + +static uint64_t timespec_diff_ns(struct timespec *start, struct timespec *end) +{ + return timespec_to_ns(end) - timespec_to_ns(start); +} + +static void prepare_key(int decrypt, int keysize, int mode) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t cmd = TA_AES_PERF_CMD_PREPARE_KEY; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + op.params[0].value.a = decrypt; + op.params[0].value.b = keysize; + op.params[1].value.a = mode; + res = TEEC_InvokeCommand(&sess, cmd, &op, + &ret_origin); + check_res(res, "TEEC_InvokeCommand", &ret_origin); +} + +static void do_warmup(int warmup) +{ + struct timespec t0 = { }; + struct timespec t = { }; + int i = 0; + + get_current_time(&t0); + do { + for (i = 0; i < 100000; i++) + ; + get_current_time(&t); + } while (timespec_diff_ns(&t0, &t) < (uint64_t)warmup * 1000000000); +} + +static const char *yesno(int v) +{ + return (v ? "yes" : "no"); +} + +static double mb_per_sec(size_t size, double usec) +{ + return (1000000000/usec)*((double)size/(1024*1024)); +} + +static void feed_input(void *in, size_t size, int random) +{ + if (random) + read_random(in, size); + else + memset(in, 0, size); +} + +static void run_feed_input(void *in, size_t size, int random) +{ + if (!is_sdp_test) { + feed_input(in, size, random); + return; + } + +#ifdef CFG_SECURE_DATA_PATH + if (input_buffer == BUFFER_SHM_ALLOCATED) { + feed_input(in, size, random); + } else { + char *data = mmap(NULL, size, PROT_WRITE, MAP_SHARED, + input_sdp_fd, 0); + + if (data == MAP_FAILED) { + perror("failed to map input buffer"); + exit(-1); + } + feed_input(data, size, random); + munmap(data, size); + } +#endif +} + + +void aes_perf_run_test(int mode, int keysize, int decrypt, size_t size, size_t unit, + unsigned int n, unsigned int l, int input_data_init, + int in_place, int warmup, int verbosity) +{ + struct statistics stats = { }; + struct timespec ts = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + int n0 = n; + double sd = 0; + uint32_t cmd = is_sdp_test ? TA_AES_PERF_CMD_PROCESS_SDP : + TA_AES_PERF_CMD_PROCESS; + + if (input_buffer == BUFFER_UNSPECIFIED) + input_buffer = BUFFER_SHM_ALLOCATED; + + if (output_buffer == BUFFER_UNSPECIFIED) { + if (is_sdp_test) + output_buffer = BUFFER_SECURE_PREREGISTERED; + else + output_buffer = BUFFER_SHM_ALLOCATED; + } + + if (clock_getres(CLOCK_MONOTONIC, &ts) < 0) { + perror("clock_getres"); + return; + } + vverbose("Clock resolution is %jd ns\n", + (intmax_t)ts.tv_sec * 1000000000 + ts.tv_nsec); + + vverbose("input test buffer: %s\n", buf_type_str(input_buffer)); + vverbose("output test buffer: %s\n", buf_type_str(output_buffer)); + + open_ta(); + prepare_key(decrypt, keysize, mode); + + alloc_buffers(size, in_place, verbosity); + if (input_data_init == CRYPTO_USE_ZEROS) + run_feed_input(in_shm.buffer, size, 0); + + /* Using INOUT to handle the case in_place == 1 */ + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT, + TEEC_MEMREF_PARTIAL_INOUT, + TEEC_VALUE_INPUT, TEEC_NONE); + op.params[0].memref.parent = &in_shm; + op.params[0].memref.size = size; + op.params[1].memref.parent = in_place ? &in_shm : &out_shm; + op.params[1].memref.size = size; + op.params[2].value.a = l; + op.params[2].value.b = unit; + + verbose("Starting test: %s, %scrypt, keysize=%u bits, size=%zu bytes, ", + mode_str(mode), (decrypt ? "de" : "en"), keysize, size); + verbose("random=%s, ", yesno(input_data_init == CRYPTO_USE_RANDOM)); + verbose("in place=%s, ", yesno(in_place)); + verbose("inner loops=%u, loops=%u, warm-up=%u s, ", l, n, warmup); + verbose("unit=%zu\n", unit); + + if (warmup) + do_warmup(warmup); + + while (n-- > 0) { + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + struct timespec t0 = { }; + struct timespec t1 = { }; + + if (input_data_init == CRYPTO_USE_RANDOM) + run_feed_input(in_shm.buffer, size, 1); + + get_current_time(&t0); + +#ifdef CFG_SECURE_DATA_PATH + if (input_buffer == BUFFER_SECURE_REGISTER) + register_shm(&in_shm, input_sdp_fd); + if (output_buffer == BUFFER_SECURE_REGISTER) + register_shm(&out_shm, output_sdp_fd); +#endif + + res = TEEC_InvokeCommand(&sess, cmd, + &op, &ret_origin); + check_res(res, "TEEC_InvokeCommand", &ret_origin); + +#ifdef CFG_SECURE_DATA_PATH + if (input_buffer == BUFFER_SECURE_REGISTER) + TEEC_ReleaseSharedMemory(&in_shm); + if (output_buffer == BUFFER_SECURE_REGISTER) + TEEC_ReleaseSharedMemory(&out_shm); +#endif + + get_current_time(&t1); + + update_stats(&stats, timespec_diff_ns(&t0, &t1)); + if (n % (n0 / 10) == 0) + vverbose("#"); + } + vverbose("\n"); + sd = stddev(&stats); + printf("min=%gus max=%gus mean=%gus stddev=%gus (cv %g%%) (%gMiB/s)\n", + stats.min / 1000, stats.max / 1000, stats.m / 1000, + sd / 1000, 100 * sd / stats.m, mb_per_sec(size, stats.m)); + verbose("2-sigma interval: %g..%gus (%g..%gMiB/s)\n", + (stats.m - 2 * sd) / 1000, (stats.m + 2 * sd) / 1000, + mb_per_sec(size, stats.m + 2 * sd), + mb_per_sec(size, stats.m - 2 * sd)); + free_shm(in_place); +} + +#define NEXT_ARG(i) \ + do { \ + if (++i == argc) { \ + fprintf(stderr, "%s: %s: missing argument\n", \ + argv[0], argv[i - 1]); \ + return 1; \ + } \ + } while (0); + +#define USAGE() usage(argv[0], keysize, mode, size, unit, warmup, l, n) + +int aes_perf_runner_cmd_parser(int argc, char *argv[]) +{ + int i = 0; + /* + * Command line parameters + */ + size_t size = 1024; /* Buffer size (-s) */ + size_t unit = CRYPTO_DEF_UNIT_SIZE; /* Divide buffer (-u) */ + unsigned int n = CRYPTO_DEF_COUNT; /*Number of measurements (-n)*/ + unsigned int l = CRYPTO_DEF_LOOPS; /* Inner loops (-l) */ + int verbosity = CRYPTO_DEF_VERBOSITY; /* Verbosity (-v) */ + int decrypt = 0; /* Encrypt by default, -d to decrypt */ + int keysize = AES_128; /* AES key size (-k) */ + int mode = TA_AES_ECB; /* AES mode (-m) */ + /* Get input data from /dev/urandom (-r) */ + int input_data_init = CRYPTO_USE_ZEROS; + /* Use same buffer for in and out (-i) */ + int in_place = AES_PERF_INPLACE; + int warmup = CRYPTO_DEF_WARMUP; /* Start with a 2-second busy loop (-w) */ + + /* Parse command line */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + USAGE(); + return 0; + } + } + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d")) { + decrypt = 1; + } else if (!strcmp(argv[i], "--in-place") || + !strcmp(argv[i], "-i")) { + in_place = 1; + } else if (!strcmp(argv[i], "-k")) { + NEXT_ARG(i); + keysize = atoi(argv[i]); + if (keysize != AES_128 && keysize != AES_192 && + keysize != AES_256) { + fprintf(stderr, "%s: invalid key size\n", + argv[0]); + USAGE(); + return 1; + } + } else if (!strcmp(argv[i], "-l")) { + NEXT_ARG(i); + l = atoi(argv[i]); + } else if (!strcmp(argv[i], "-m")) { + NEXT_ARG(i); + if (!strcasecmp(argv[i], "ECB")) + mode = TA_AES_ECB; + else if (!strcasecmp(argv[i], "CBC")) + mode = TA_AES_CBC; + else if (!strcasecmp(argv[i], "CTR")) + mode = TA_AES_CTR; + else if (!strcasecmp(argv[i], "XTS")) + mode = TA_AES_XTS; + else if (!strcasecmp(argv[i], "GCM")) + mode = TA_AES_GCM; + else { + fprintf(stderr, "%s, invalid mode\n", + argv[0]); + USAGE(); + return 1; + } + } else if (!strcmp(argv[i], "-n")) { + NEXT_ARG(i); + n = atoi(argv[i]); + } else if (!strcmp(argv[i], "--random") || + !strcmp(argv[i], "-r")) { + if (input_data_init == CRYPTO_NOT_INITED) { + perror("--random is not compatible with --not-inited\n"); + USAGE(); + return 1; + } + input_data_init = CRYPTO_USE_RANDOM; + } else if (!strcmp(argv[i], "--not-inited")) { + if (input_data_init == CRYPTO_USE_RANDOM) { + perror("--random is not compatible with --not-inited\n"); + USAGE(); + return 1; + } + input_data_init = CRYPTO_NOT_INITED; + } else if (!strcmp(argv[i], "-s")) { + NEXT_ARG(i); + size = atoi(argv[i]); +#ifdef CFG_SECURE_DATA_PATH + } else if (!strcmp(argv[i], "--sdp")) { + is_sdp_test = 1; + } else if (!strcmp(argv[i], "-IR")) { + input_buffer = BUFFER_SECURE_PREREGISTERED; + } else if (!strcmp(argv[i], "-OR")) { + output_buffer = BUFFER_SECURE_PREREGISTERED; + } else if (!strcmp(argv[i], "-Ir")) { + input_buffer = BUFFER_SECURE_REGISTER; + } else if (!strcmp(argv[i], "-Or")) { + output_buffer = BUFFER_SECURE_REGISTER; + } else if (!strcmp(argv[i], "-Id")) { + input_buffer = BUFFER_SHM_ALLOCATED; + } else if (!strcmp(argv[i], "-Od")) { + output_buffer = BUFFER_SHM_ALLOCATED; + } else if (!strcmp(argv[i], "--heap-name")) { + NEXT_ARG(i); + heap_name = argv[i]; +#endif // CFG_SECURE_DATA_PATH + } else if (!strcmp(argv[i], "-u")) { + NEXT_ARG(i); + unit = atoi(argv[i]); + } else if (!strcmp(argv[i], "-v")) { + verbosity++; + } else if (!strcmp(argv[i], "--warmup") || + !strcmp(argv[i], "-w")) { + NEXT_ARG(i); + warmup = atoi(argv[i]); + } else { + fprintf(stderr, "%s: invalid argument: %s\n", + argv[0], argv[i]); + USAGE(); + return 1; + } + } + + if (size & (16 - 1)) { + fprintf(stderr, "invalid buffer size argument, must be a multiple of 16\n\n"); + USAGE(); + return 1; + } + + + aes_perf_run_test(mode, keysize, decrypt, size, unit, n, l, + input_data_init, in_place, warmup, verbosity); + + return 0; +} diff --git a/optee/optee_test/host/xtest/benchmark_1000.c b/optee/optee_test/host/xtest/benchmark_1000.c new file mode 100644 index 0000000..78e8822 --- /dev/null +++ b/optee/optee_test/host/xtest/benchmark_1000.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include + +#include "xtest_test.h" +#include "xtest_helpers.h" + +#include +#include + +#define DO_VERIFY 0 +#define DEFAULT_DATA_SIZE (2 * 1024 * 1024) /* 2MB */ +#define DEFAULT_CHUNK_SIZE (1 * 1024) /* 1KB */ +#define DEFAULT_COUNT (10) + +size_t data_size_table[] = { + 256, + 512, + 1024, + 2 * 1024, + 4 * 1024, + 16 * 1024, + 512 * 1024, + 1024 * 1024, + 0 +}; + +static void xtest_tee_benchmark_1001(ADBG_Case_t *Case_p); +static void xtest_tee_benchmark_1002(ADBG_Case_t *Case_p); +static void xtest_tee_benchmark_1003(ADBG_Case_t *Case_p); + +static TEEC_Result run_test_with_args(enum storage_benchmark_cmd cmd, + uint32_t arg0, uint32_t arg1, uint32_t arg2, + uint32_t arg3, uint32_t *out0, uint32_t *out1) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session sess = { }; + uint32_t orig = 0; + + res = xtest_teec_open_session(&sess, &storage_benchmark_ta_uuid, NULL, &orig); + if (res != TEEC_SUCCESS) + return res; + + op.params[0].value.a = arg0; + op.params[0].value.b = arg1; + op.params[1].value.a = arg2; + op.params[1].value.b = arg3; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(&sess, cmd, &op, &orig); + + if (out0) + *out0 = op.params[2].value.a; + if (out1) + *out1 = op.params[2].value.b; + + TEEC_CloseSession(&sess); + + return res; +} + +struct test_record { + size_t data_size; + float spent_time; + float speed_in_kb; +}; + +static TEEC_Result run_chunk_access_test(enum storage_benchmark_cmd cmd, + uint32_t data_size, uint32_t chunk_size, struct test_record *rec) +{ + TEE_Result res = TEEC_ERROR_GENERIC; + uint32_t spent_time = 0; + + res = run_test_with_args(cmd, data_size, chunk_size, DO_VERIFY, 0, + &spent_time, NULL); + + rec->data_size = data_size; + rec->spent_time = (float)spent_time / 1000.0; + rec->speed_in_kb = ((float)data_size / 1024.0) / rec->spent_time; + + return res; +} + +static void show_test_result(struct test_record records[], size_t size) +{ + size_t i = 0; + + printf("-----------------+---------------+----------------\n"); + printf(" Data Size (B) \t | Time (s)\t | Speed (kB/s)\t \n"); + printf("-----------------+---------------+----------------\n"); + + for (i = 0; i < size; i++) { + printf(" %8zd \t | %8.3f \t | %8.3f\n", + records[i].data_size, records[i].spent_time, + records[i].speed_in_kb); + } + + printf("-----------------+---------------+----------------\n"); + +} + +static void chunk_test(ADBG_Case_t *c, enum storage_benchmark_cmd cmd) +{ + uint32_t chunk_size = DEFAULT_CHUNK_SIZE; + struct test_record records[ARRAY_SIZE(data_size_table) - 1]; + size_t i = 0; + + for (i = 0; data_size_table[i]; i++) { + ADBG_EXPECT_TEEC_SUCCESS(c, + run_chunk_access_test(cmd, data_size_table[i], + chunk_size, &records[i])); + } + + show_test_result(records, ARRAY_SIZE(records)); +} + +static void xtest_tee_benchmark_1001(ADBG_Case_t *c) +{ + chunk_test(c, TA_STORAGE_BENCHMARK_CMD_TEST_WRITE); +} + +static void xtest_tee_benchmark_1002(ADBG_Case_t *c) +{ + chunk_test(c, TA_STORAGE_BENCHMARK_CMD_TEST_READ); +} + +static void xtest_tee_benchmark_1003(ADBG_Case_t *c) +{ + chunk_test(c, TA_STORAGE_BENCHMARK_CMD_TEST_REWRITE); +} + +ADBG_CASE_DEFINE(benchmark, 1001, xtest_tee_benchmark_1001, + "TEE Trusted Storage Performance Test (WRITE)"); +ADBG_CASE_DEFINE(benchmark, 1002, xtest_tee_benchmark_1002, + "TEE Trusted Storage Performance Test (READ)"); +ADBG_CASE_DEFINE(benchmark, 1003, xtest_tee_benchmark_1003, + "TEE Trusted Storage Performance Test (REWRITE)"); diff --git a/optee/optee_test/host/xtest/benchmark_2000.c b/optee/optee_test/host/xtest/benchmark_2000.c new file mode 100644 index 0000000..da9db74 --- /dev/null +++ b/optee/optee_test/host/xtest/benchmark_2000.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015, Linaro Limited + */ + +#include +#include +#include + +#include "xtest_test.h" +#include "xtest_helpers.h" + +#include +#include + +/* SHA bechmarks */ +static void xtest_tee_benchmark_2001(ADBG_Case_t *Case_p); +static void xtest_tee_benchmark_2002(ADBG_Case_t *Case_p); + +/* AES benchmarks */ +static void xtest_tee_benchmark_2011(ADBG_Case_t *Case_p); +static void xtest_tee_benchmark_2012(ADBG_Case_t *Case_p); + +/* ----------------------------------------------------------------------- */ +/* -------------------------- SHA Benchmarks ----------------------------- */ +/* ----------------------------------------------------------------------- */ + +static void xtest_tee_benchmark_2001(ADBG_Case_t *c) +{ + UNUSED(c); + + int algo = TA_SHA_SHA1; /* Algorithm */ + size_t size = 1024; /* Buffer size */ + int offset = 0; /* Buffer offset wrt. alloc'ed address */ + + hash_perf_run_test(algo, size, CRYPTO_DEF_COUNT, + CRYPTO_DEF_LOOPS, CRYPTO_USE_RANDOM, offset, + CRYPTO_DEF_WARMUP, CRYPTO_DEF_VERBOSITY); + +} + +static void xtest_tee_benchmark_2002(ADBG_Case_t *c) +{ + UNUSED(c); + + int algo = TA_SHA_SHA256; /* Algorithm */ + size_t size = 4096; /* Buffer size */ + int offset = 0; /* Buffer offset wrt. alloc'ed address */ + + hash_perf_run_test(algo, size, CRYPTO_DEF_COUNT, + CRYPTO_DEF_LOOPS, CRYPTO_USE_RANDOM, offset, + CRYPTO_DEF_WARMUP, CRYPTO_DEF_VERBOSITY); + +} + +ADBG_CASE_DEFINE(benchmark, 2001, xtest_tee_benchmark_2001, + "TEE SHA Performance test (TA_SHA_SHA1)"); +ADBG_CASE_DEFINE(benchmark, 2002, xtest_tee_benchmark_2002, + "TEE SHA Performance test (TA_SHA_SHA226)"); + + +/* ----------------------------------------------------------------------- */ +/* -------------------------- AES Benchmarks ----------------------------- */ +/* ----------------------------------------------------------------------- */ + +static void xtest_tee_benchmark_2011(ADBG_Case_t *c) +{ + UNUSED(c); + + int mode = TA_AES_ECB; /* AES mode */ + int decrypt = 0; /* Encrypt */ + int keysize = AES_128; + size_t size = 1024; /* Buffer size */ + + aes_perf_run_test(mode, keysize, decrypt, size, CRYPTO_DEF_UNIT_SIZE, + CRYPTO_DEF_COUNT, CRYPTO_DEF_LOOPS, CRYPTO_USE_RANDOM, + AES_PERF_INPLACE, CRYPTO_DEF_WARMUP, CRYPTO_DEF_VERBOSITY); +} + +static void xtest_tee_benchmark_2012(ADBG_Case_t *c) +{ + UNUSED(c); + + int mode = TA_AES_CBC; /* AES mode */ + int decrypt = 0; /* Encrypt */ + int keysize = AES_256; + size_t size = 1024; /* Buffer size */ + + aes_perf_run_test(mode, keysize, decrypt, size, CRYPTO_DEF_UNIT_SIZE, + CRYPTO_DEF_COUNT, CRYPTO_DEF_LOOPS, CRYPTO_USE_RANDOM, + AES_PERF_INPLACE, CRYPTO_DEF_WARMUP, CRYPTO_DEF_VERBOSITY); +} + +ADBG_CASE_DEFINE(benchmark, 2011, xtest_tee_benchmark_2011, + "TEE AES Performance test (TA_AES_ECB)"); +ADBG_CASE_DEFINE(benchmark, 2012, xtest_tee_benchmark_2012, + "TEE AES Performance test (TA_AES_CBC)"); diff --git a/optee/optee_test/host/xtest/crypto_common.h b/optee/optee_test/host/xtest/crypto_common.h new file mode 100644 index 0000000..68debea --- /dev/null +++ b/optee/optee_test/host/xtest/crypto_common.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef XTEST_CRYPTO_COMMON_H +#define XTEST_CRYPTO_COMMON_H + +#include "ta_aes_perf.h" +#include "ta_hash_perf.h" + + +#define AES_PERF_INPLACE 0 + +#define CRYPTO_DEF_LOOPS 1 /* Default amount of inner loops */ + +#define CRYPTO_USE_ZEROS 0 /* Init input data to zero */ +#define CRYPTO_USE_RANDOM 1 /* Get input data from /dev/urandom */ +#define CRYPTO_NOT_INITED 2 /* Input data are not initialized */ + +#define CRYPTO_DEF_WARMUP 2 /* Start with a 2-second busy loop */ +#define CRYPTO_DEF_COUNT 5000 /* Default number of measurements */ +#define CRYPTO_DEF_VERBOSITY 0 +#define CRYPTO_DEF_UNIT_SIZE 0 /* Process whole buffer */ + + +#define _verbose(lvl, ...) \ + do { \ + if (verbosity >= lvl) { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } \ + } while (0) + +#define verbose(...) _verbose(1, __VA_ARGS__) +#define vverbose(...) _verbose(2, __VA_ARGS__) + + +int aes_perf_runner_cmd_parser(int argc, char *argv[]); +void aes_perf_run_test(int mode, int keysize, int decrypt, size_t size, + size_t unit, unsigned int n, unsigned int l, + int random_in, int in_place, int warmup, int verbosity); + +int hash_perf_runner_cmd_parser(int argc, char *argv[]); +void hash_perf_run_test(int algo, size_t size, unsigned int n, + unsigned int l, int random_in, int offset, + int warmup, int verbosity); + +#ifdef CFG_SECURE_DATA_PATH +int sdp_basic_runner_cmd_parser(int argc, char *argv[]); +#endif + +#endif /* XTEST_CRYPTO_PERF_H */ diff --git a/optee/optee_test/host/xtest/ffa_spmc_1000.c b/optee/optee_test/host/xtest/ffa_spmc_1000.c new file mode 100644 index 0000000..1839d03 --- /dev/null +++ b/optee/optee_test/host/xtest/ffa_spmc_1000.c @@ -0,0 +1,535 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include "include/uapi/linux/arm_ffa_user.h" +#include "xtest_helpers.h" +#include "xtest_test.h" + +#define FFA_DRIVER_FS_PATH "/sys/kernel/debug/arm_ffa_user" +#define SPMC_TEST_OK 0xaa +#define INCORRECT_ENDPOINT_ID 0xffff +#define NORMAL_WORLD_ENDPOINT_ID 0 + +#define FFA_USER_REQ_VER_MAJOR 5 +#define FFA_USER_REQ_VER_MINOR 0 +#define FFA_USER_REQ_VER_PATCH 1 + +/* Get the 32 least significant bits of a handle.*/ +#define MEM_SHARE_HANDLE_LOW(x) ((x) & 0xffffffff) +/* Get the 32 most significant bits of a handle.*/ +#define MEM_SHARE_HANDLE_HIGH(x) (((x) >> 32) & 0xffffffff) + +#define MEM_SHARE_HANDLE_LOW_INDEX 1 +#define MEM_SHARE_HANDLE_HIGH_INDEX 2 +#define MEM_SHARE_HANDLE_ENDPOINT_INDEX 3 + +enum sp_tests { + EP_TEST_SP, + EP_TEST_SP_COMMUNICATION, + EP_TEST_SP_INCREASE, + EP_TRY_R_ACCESS, + EP_TRY_W_ACCESS, + EP_RETRIEVE, + EP_RELINQUISH, + EP_SP_MEM_SHARING, + EP_SP_MEM_SHARING_MULTI, + EP_SP_MEM_SHARING_EXC, + EP_SP_MEM_INCORRECT_ACCESS, + EP_SP_NOP +}; + +static int ffa_fd = -1; + +static const char test_endpoint1_uuid[] = + "5c9edbc3-7b3a-4367-9f83-7c191ae86a37"; +static const char test_endpoint2_uuid[] = + "7817164c-c40c-4d1a-867a-9bb2278cf41a"; +static const char test_endpoint3_uuid[] = + "23eb0100-e32a-4497-9052-2f11e584afa6"; + +static struct ffa_ioctl_ep_desc test_endpoint1 = { + .uuid_ptr = (uint64_t)test_endpoint1_uuid, +}; + +static struct ffa_ioctl_ep_desc test_endpoint2 = { + .uuid_ptr = (uint64_t)test_endpoint2_uuid, +}; + +static struct ffa_ioctl_ep_desc test_endpoint3 = { + .uuid_ptr = (uint64_t)test_endpoint3_uuid, +}; + +static bool check_ffa_user_version(void) +{ + FILE *f = NULL; + int ver_major = -1; + int ver_minor = -1; + int ver_patch = -1; + int scan_cnt = 0; + + f = fopen("/sys/module/arm_ffa_user/version", "r"); + if (f) { + scan_cnt = fscanf(f, "%d.%d.%d", + &ver_major, &ver_minor, &ver_patch); + fclose(f); + if (scan_cnt != 3) { + printf("error: failed to parse arm_ffa_user version\n"); + return false; + } + } else { + printf("error: failed to read arm_ffa_user module info - %s\n", + strerror(errno)); + return false; + } + + if (ver_major != FFA_USER_REQ_VER_MAJOR) + goto err; + + if (ver_minor < FFA_USER_REQ_VER_MINOR) + goto err; + + if (ver_minor == FFA_USER_REQ_VER_MINOR) + if (ver_patch < FFA_USER_REQ_VER_PATCH) + goto err; + + return true; + +err: + printf("error: Incompatible arm_ffa_user driver detected."); + printf("Found v%d.%d.%d wanted >= v%d.%d.%d)\n", + ver_major, ver_minor, ver_patch, FFA_USER_REQ_VER_MAJOR, + FFA_USER_REQ_VER_MINOR, FFA_USER_REQ_VER_PATCH); + + return false; +} + +static void close_debugfs(void) +{ + int err = 0; + + if (ffa_fd >= 0) { + err = close(ffa_fd); + if (err < 0) + Do_ADBG_Log("Error: Could not close the FF-A driver"); + } + ffa_fd = -1; +} + +static bool init_sp_xtest(ADBG_Case_t *c) +{ + if (!check_ffa_user_version()) + return false; + + if (ffa_fd < 0) { + ffa_fd = open(FFA_DRIVER_FS_PATH, O_RDWR); + if (ffa_fd < 0) { + Do_ADBG_Log("Error: Could not open the FF-A driver"); + return false; + } + } + + return true; +} + +static int start_sp_test(uint16_t endpoint, enum sp_tests test, + struct ffa_ioctl_msg_args *args) +{ + args->dst_id = endpoint; + args->args[0] = test; + return ioctl(ffa_fd, FFA_IOC_MSG_SEND, args); +} + +static uint16_t get_endpoint_id(uint64_t endp) +{ + struct ffa_ioctl_ep_desc sid = { .uuid_ptr = endp }; + + /* Get ID of destination SP based on UUID */ + if (ioctl(ffa_fd, FFA_IOC_GET_PART_ID, &sid)) + return INCORRECT_ENDPOINT_ID; + + return sid.id; +} + +static void xtest_ffa_spmc_test_1001(ADBG_Case_t *c) +{ + struct ffa_ioctl_msg_args args = { 0 }; + uint16_t endpoint1_id = 0; + uint16_t endpoint2_id = 0; + int rc = 0; + + Do_ADBG_BeginSubCase(c, "SP1 comms check"); + if (!init_sp_xtest(c)) { + Do_ADBG_Log("Failed to initialise test, skipping SP test"); + goto out; + } + + endpoint1_id = get_endpoint_id(test_endpoint1.uuid_ptr); + if (endpoint1_id == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_1 sp to the image to enable tests"); + goto out; + } + + memset(&args, 0, sizeof(args)); + rc = start_sp_test(endpoint1_id, EP_TEST_SP, &args); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0)) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK)) + goto out; + Do_ADBG_EndSubCase(c, "SP1 comms check"); + + Do_ADBG_BeginSubCase(c, "Sp2 comms check"); + endpoint2_id = get_endpoint_id(test_endpoint2.uuid_ptr); + if (endpoint2_id == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_2 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_2 sp to the image to enable tests"); + goto out; + } + + memset(&args, 0, sizeof(args)); + rc = start_sp_test(endpoint2_id, EP_TEST_SP, &args); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0)) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK)) + goto out; + Do_ADBG_EndSubCase(c, "Sp2 comms check"); + + /* Test SP to SP messaging. */ + Do_ADBG_BeginSubCase(c, "SP to SP messaging check"); + memset(&args, 0, sizeof(args)); + args.args[1] = endpoint2_id; + + rc = start_sp_test(endpoint1_id, EP_TEST_SP_COMMUNICATION, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + + memset(&args, 0, sizeof(args)); + args.args[1] = endpoint1_id; + + rc = start_sp_test(endpoint2_id, EP_TEST_SP_COMMUNICATION, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + +out: + Do_ADBG_EndSubCase(c, NULL); + close_debugfs(); +} + +ADBG_CASE_DEFINE(ffa_spmc, 1001, xtest_ffa_spmc_test_1001, + "Test FF-A communication"); + +static void check_alive(ADBG_Case_t *c, uint16_t endpoint) +{ + struct ffa_ioctl_msg_args args = {}; + int rc = 0; + + args.dst_id = endpoint; + rc = start_sp_test(endpoint, EP_SP_NOP, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); +} + +static int share_mem(uint16_t endpoint, uint64_t *handle) +{ + int status = false; + struct ffa_ioctl_shm_desc shm_desc = { .dst_id = endpoint, + .size = 0x1000 }; + + status = ioctl(ffa_fd, FFA_IOC_SHM_INIT, &shm_desc); + + if (!status) + *handle = shm_desc.handle; + + return status; +} + +static int set_up_mem(struct ffa_ioctl_ep_desc *endp, + struct ffa_ioctl_msg_args *args, + uint64_t *handle, ADBG_Case_t *c) +{ + uint16_t endpoint = 0; + int rc = 0; + + endpoint = get_endpoint_id(endp->uuid_ptr); + *handle = 0; + /* Share memory with SP*/ + rc = share_mem(endpoint, handle); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + + if (!ADBG_EXPECT_NOT_NULL(c, handle)) + return TEEC_ERROR_GENERIC; + + /* SP will retrieve the memory region. */ + memset(args, 0, sizeof(*args)); + args->dst_id = endpoint; + args->args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(*handle); + args->args[MEM_SHARE_HANDLE_HIGH_INDEX] = + MEM_SHARE_HANDLE_HIGH(*handle); + args->args[MEM_SHARE_HANDLE_ENDPOINT_INDEX] = NORMAL_WORLD_ENDPOINT_ID; + + rc = start_sp_test(endpoint, EP_RETRIEVE, args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args->args[0], ==, SPMC_TEST_OK); + + return TEEC_SUCCESS; +} + +static void xtest_ffa_spmc_test_1002(ADBG_Case_t *c) +{ + struct ffa_ioctl_msg_args args = { 0 }; + uint64_t handle = 0; + uint16_t endpoint1_id = 0; + int rc = 0; + struct ffa_ioctl_shm_desc shm_desc = { 0 }; + + if (!init_sp_xtest(c)) { + Do_ADBG_Log("Failed to initialise test, skipping SP test"); + goto out; + } + + endpoint1_id = get_endpoint_id(test_endpoint1.uuid_ptr); + if (endpoint1_id == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_1 sp to the image to enable tests"); + goto out; + } + + memset(&args, 0, sizeof(args)); + rc = start_sp_test(endpoint1_id, EP_TEST_SP, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK)) + goto out; + + /* Set up memory and have the SP retrieve it. */ + Do_ADBG_BeginSubCase(c, "Test memory set-up"); + memset(&args, 0, sizeof(args)); + if (set_up_mem(&test_endpoint1, &args, &handle, c)) { + Do_ADBG_EndSubCase(c, "Test memory set-up"); + goto out; + } + Do_ADBG_EndSubCase(c, "Test memory set-up"); + + /* Retrieve it again. */ + Do_ADBG_BeginSubCase(c, "Test retrieve memory second time"); + memset(&args, 0, sizeof(args)); + args.dst_id = endpoint1_id; + args.args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(handle); + args.args[MEM_SHARE_HANDLE_HIGH_INDEX] = MEM_SHARE_HANDLE_HIGH(handle); + args.args[MEM_SHARE_HANDLE_ENDPOINT_INDEX] = NORMAL_WORLD_ENDPOINT_ID; + rc = start_sp_test(endpoint1_id, EP_RETRIEVE, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + Do_ADBG_EndSubCase(c, "Test retrieve memory second time"); + + /*Access it. */ + Do_ADBG_BeginSubCase(c, "Test accessing memory"); + memset(&args, 0, sizeof(args)); + rc = start_sp_test(endpoint1_id, EP_TRY_R_ACCESS, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + Do_ADBG_EndSubCase(c, "Test accessing memory"); + + /*RELINQUISH the memory area.*/ + Do_ADBG_BeginSubCase(c, "Test relinquish memory"); + memset(&args, 0, sizeof(args)); + args.args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(handle); + args.args[MEM_SHARE_HANDLE_HIGH_INDEX] = MEM_SHARE_HANDLE_HIGH(handle); + rc = start_sp_test(endpoint1_id, EP_RELINQUISH, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + check_alive(c, endpoint1_id); + Do_ADBG_EndSubCase(c, "Test relinquish memory"); + + /* Try to reclaim the mem with the SP still having access to it. */ + Do_ADBG_BeginSubCase(c, "Test incorrect reclaim"); + shm_desc.handle = handle; + shm_desc.dst_id = endpoint1_id; + rc = ioctl(ffa_fd, FFA_IOC_SHM_DEINIT, &shm_desc); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, <, 0); + Do_ADBG_EndSubCase(c, "Test incorrect reclaim"); + + /*RELINQUISH the memory area.*/ + Do_ADBG_BeginSubCase(c, "Test relinquish memory second time"); + memset(&args, 0, sizeof(args)); + args.args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(handle); + args.args[MEM_SHARE_HANDLE_HIGH_INDEX] = MEM_SHARE_HANDLE_HIGH(handle); + rc = start_sp_test(endpoint1_id, EP_RELINQUISH, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + check_alive(c, endpoint1_id); + Do_ADBG_EndSubCase(c, "Test relinquish memory second time"); + + /* Try to reclaim again this time it should work. */ + Do_ADBG_BeginSubCase(c, "Test correct reclaim"); + shm_desc.handle = handle; + shm_desc.dst_id = endpoint1_id; + rc = ioctl(ffa_fd, FFA_IOC_SHM_DEINIT, &shm_desc); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, >=, 0); + check_alive(c, endpoint1_id); + Do_ADBG_EndSubCase(c, "Test correct reclaim"); + + /* SP will try to retrieve invalid memory region. */ + Do_ADBG_BeginSubCase(c, "Test retrieve invalid memory region"); + memset(&args, 0, sizeof(args)); + args.args[MEM_SHARE_HANDLE_LOW_INDEX] = MEM_SHARE_HANDLE_LOW(handle); + args.args[MEM_SHARE_HANDLE_HIGH_INDEX] = MEM_SHARE_HANDLE_HIGH(handle); + args.args[MEM_SHARE_HANDLE_ENDPOINT_INDEX] = NORMAL_WORLD_ENDPOINT_ID; + rc = start_sp_test(endpoint1_id, EP_RETRIEVE, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], !=, SPMC_TEST_OK); + check_alive(c, endpoint1_id); + + Do_ADBG_EndSubCase(c, "Test retrieve invalid memory region"); +out: + close_debugfs(); +} + +ADBG_CASE_DEFINE(ffa_spmc, 1002, xtest_ffa_spmc_test_1002, + "Test FF-A memory: share memory from Normal World to SP"); + +static void xtest_ffa_spmc_test_1003(ADBG_Case_t *c) +{ + struct ffa_ioctl_msg_args args = { 0 }; + uint16_t endpoint1 = 0; + uint16_t endpoint2 = 0; + int rc = 0; + + if (!init_sp_xtest(c)) { + Do_ADBG_Log("Failed to initialise test, skipping SP test"); + goto out; + } + + endpoint1 = get_endpoint_id(test_endpoint1.uuid_ptr); + if (endpoint1 == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_1 sp to the image to enable tests"); + goto out; + } + + /* Test SP to SP memory sharing. */ + endpoint2 = get_endpoint_id(test_endpoint2.uuid_ptr); + if (endpoint2 == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_2 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_2 sp to the image to enable tests"); + goto out; + } + + memset(&args, 0, sizeof(args)); + args.args[1] = endpoint2; + rc = start_sp_test(endpoint1, EP_SP_MEM_SHARING, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + +out: + close_debugfs(); +} + +ADBG_CASE_DEFINE(ffa_spmc, 1003, xtest_ffa_spmc_test_1003, + "Test FF-A memory: SP to SP"); + +static void xtest_ffa_spmc_test_1004(ADBG_Case_t *c) +{ + struct ffa_ioctl_msg_args args = { 0 }; + uint16_t endpoint1 = 0; + uint16_t endpoint2 = 0; + int rc = 0; + + if (!init_sp_xtest(c)) { + Do_ADBG_Log("Failed to initialise test, skipping SP test"); + goto out; + } + + endpoint1 = get_endpoint_id(test_endpoint1.uuid_ptr); + if (endpoint1 == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_1 sp to the image to enable tests"); + goto out; + } + + /* Test SP to SP memory sharing. */ + endpoint2 = get_endpoint_id(test_endpoint2.uuid_ptr); + if (endpoint2 == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_2 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_2 sp to the image to enable tests"); + goto out; + } + + Do_ADBG_BeginSubCase(c, "Test sharing with exc access"); + memset(&args, 0, sizeof(args)); + args.args[1] = endpoint2; + rc = start_sp_test(endpoint1, EP_SP_MEM_SHARING_EXC, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + Do_ADBG_EndSubCase(c, "Test sharing with exc access"); + + Do_ADBG_BeginSubCase(c, "Test sharing with incorrect access"); + memset(&args, 0, sizeof(args)); + args.args[1] = endpoint2; + rc = start_sp_test(endpoint1, EP_SP_MEM_INCORRECT_ACCESS, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + Do_ADBG_EndSubCase(c, "Test sharing with incorrect access"); + +out: + close_debugfs(); +} + +ADBG_CASE_DEFINE(ffa_spmc, 1004, xtest_ffa_spmc_test_1004, + "Test FF-A memory: Access and flags"); + +static void xtest_ffa_spmc_test_1005(ADBG_Case_t *c) +{ + struct ffa_ioctl_msg_args args = { 0 }; + uint16_t endpoint1 = 0; + uint16_t endpoint2 = 0; + uint16_t endpoint3 = 0; + int rc = 0; + + if (!init_sp_xtest(c)) { + Do_ADBG_Log("Failed to initialise test, skipping SP test"); + goto out; + } + + endpoint1 = get_endpoint_id(test_endpoint1.uuid_ptr); + if (endpoint1 == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_1 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_1 sp to the image to enable tests"); + goto out; + } + + endpoint2 = get_endpoint_id(test_endpoint2.uuid_ptr); + if (endpoint2 == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_2 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_2 sp to the image to enable tests"); + goto out; + } + + endpoint3 = get_endpoint_id(test_endpoint3.uuid_ptr); + if (endpoint3 == INCORRECT_ENDPOINT_ID) { + Do_ADBG_Log("Could not contact xtest_3 sp, skipping SP test"); + Do_ADBG_Log("Add xtest_3 sp to the image to enable tests"); + goto out; + } + + memset(&args, 0, sizeof(args)); + args.args[1] = endpoint2; + args.args[2] = endpoint3; + rc = start_sp_test(endpoint1, EP_SP_MEM_SHARING_MULTI, &args); + ADBG_EXPECT_COMPARE_SIGNED(c, rc, ==, 0); + ADBG_EXPECT_COMPARE_UNSIGNED(c, args.args[0], ==, SPMC_TEST_OK); + +out: + close_debugfs(); +} + +ADBG_CASE_DEFINE(regression, 1005, xtest_ffa_spmc_test_1005, + "Test FF-A memory: multiple receiver"); diff --git a/optee/optee_test/host/xtest/gp/TEE.xsl b/optee/optee_test/host/xtest/gp/TEE.xsl new file mode 100644 index 0000000..09f2853 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/TEE.xsl @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include "xml_client_api.h" + + + +/**/ +static void gp_test_teec_(ADBG_Case_t *c __maybe_unused) +{ + + + + + + + + + +} + + + + +ADBG_CASE_DEFINE(gp, , gp_test_teec_, ""); + + + + + + ADBG_EXPECT(c, , , + )); + + + , + + ); + + + + + + +& + + + + + + + + + + + + + +XML_(c, + +XML_(c, + +INVOKE_REMEMBER_EXP_PARAM_TYPES( + +INVOKE_STORE_EXP_PARAM_INFO( + +( + +( + +( + +( + +OPERATION_TEEC_PARAM_TYPES( + +XML_InvokeCommand(c, + + +TEEC_( + + + + + diff --git a/optee/optee_test/host/xtest/gp/TEE_Crypto_API.xsl b/optee/optee_test/host/xtest/gp/TEE_Crypto_API.xsl new file mode 100644 index 0000000..9e9f090 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/TEE_Crypto_API.xsl @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include "xml_crypto_api.h" + + + +/**/ +static void xtest_tee_(ADBG_Case_t *c) +{ + declare_local_vars + + + + + + + + + + + + + + + crypto_reset(); +} + + + + +ADBG_CASE_DEFINE(gp, , xtest_tee_, ""); + + + + + + + ADBG_EXPECT_TEEC_RESULT(c, , , + )); + + + , + +); + + + + + + +& + +, sizeof() + +xtest_tee_name +OBJECT_HANDLE_NULL + + + + + + + + + + + + +(c, +(c, +(c, +( +( + +TEEC_( + + + + + diff --git a/optee/optee_test/host/xtest/gp/TEE_DataStorage_API.xsl b/optee/optee_test/host/xtest/gp/TEE_DataStorage_API.xsl new file mode 100644 index 0000000..5fe19e5 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/TEE_DataStorage_API.xsl @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "xml_datastorage_api.h" + + + +/**/ +static void xtest_tee_(ADBG_Case_t *c) +{ + declare_local_vars + + + + + + + + + + + + + +} + + + + +ADBG_CASE_DEFINE(gp, , xtest_tee_, ""); + + + + + + + ADBG_EXPECT(c, , , +)); + + + , + +); + + + + + + + +& + +, sizeof() + +xtest_tee_name + +OBJECT_HANDLE_NULL + +OBJECT_HANDLE_NULL + +ATTRIBUTE_NONE + + + + + + + + + + + + + +XML_(c, + +XML_(c, + +TEEC_( + +TEEC_( + +TEEC_( + +(c + +(c + +TEEC_SetUp_TEE( +TEEC_TearDown_TEE( + +(c, + + + + + diff --git a/optee/optee_test/host/xtest/gp/TEE_Internal_API.xsl b/optee/optee_test/host/xtest/gp/TEE_Internal_API.xsl new file mode 100644 index 0000000..12fb406 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/TEE_Internal_API.xsl @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "xml_internal_api.h" + + + + +/**/ +static void xtest_tee_(ADBG_Case_t *c) +{ + + + + + + + + + +} + + + +ADBG_CASE_DEFINE(gp, , xtest_tee_, ""); + + + + + + + ADBG_EXPECT(c, , , + )); + + ADBG_EXPECT(c, , , + )); + + + , + + ); + + + + + + + +& + +xtest_tee_name + + + + + + + + + + + + + +( + +XML_(c, + +XML_(c, + +TEEC_( + +TEEC_( + +TEEC_( + +TEEC_( + +OPERATION_TEEC_( + +TEEC_SetUp_TEE( +TEEC_TearDown_TEE( + +(c, + + + + + diff --git a/optee/optee_test/host/xtest/gp/TEE_TimeArithm_API.xsl b/optee/optee_test/host/xtest/gp/TEE_TimeArithm_API.xsl new file mode 100644 index 0000000..0721603 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/TEE_TimeArithm_API.xsl @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include "xml_timearithm_api.h" + + + + +/**/ +static void xtest_tee_(ADBG_Case_t *c) +{ + + + + + + + + + + + + + +} + + + + +ADBG_CASE_DEFINE(gp, , xtest_tee_, ""); + + + + + + + ADBG_EXPECT_TEEC_RESULT(c, , , + )); + + + , + + ); + + + + + + + + +& + +xtest_tee_name + +STORED_VALUE_ + +, sizeof() + + + + + + + + + + + + + +( + +XML_(c, + +XML_(c, + +TEEC_( + +TEEC_( + +TEEC_( + +TEEC_( + +(c, SESSION01, CMD_TEE_SetTAPersistentTime_and_GetTAPersistentTime + +OPERATION_TEEC_( + +TEEC_SetUp_TEE( +TEEC_TearDown_TEE( + +(c, + + + + + diff --git a/optee/optee_test/host/xtest/gp/include/xml_client_api.h b/optee/optee_test/host/xtest/gp/include/xml_client_api.h new file mode 100644 index 0000000..351a061 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/include/xml_client_api.h @@ -0,0 +1,378 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef XML_CLIENT_API_H_ +#define XML_CLIENT_API_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "xtest_helpers.h" +#include "xtest_test.h" + +/* ta_testingClientAPI_test.h*/ +#define COMMAND_TTA_Remember_Expected_ParamTypes 0x00000002 +#define COMMAND_TTA_Copy_ParamIn_to_ParamOut 0x00000001 +#define COMMAND_TTA_Check_ParamTypes 0x00000003 +#define COMMAND_TTA_To_Be_Cancelled 0x00000004 +#define COMMAND_TTA_Success 0x00000005 +#define COMMAND_TTA_Panic 0x00000006 + +/* ta_answerSuccessTo_OpenSession_Invoke_test.h */ +#define COMMAND_TTA_Remember_Expected_ParamTypes 0x00000002 +#define COMMAND_TTA_Copy_ParamIn_to_ParamOut 0x00000001 +#define COMMAND_TTA_Check_ParamTypes 0x00000003 + +/* ta_testingClientAPI_test.h */ +#define COMMAND_TTA_Remember_Expected_ParamTypes 0x00000002 +#define COMMAND_TTA_Copy_ParamIn_to_ParamOut 0x00000001 +#define COMMAND_TTA_Check_ParamTypes 0x00000003 +#define COMMAND_TTA_To_Be_Cancelled 0x00000004 +#define COMMAND_TTA_Success 0x00000005 +#define COMMAND_TTA_Panic 0x00000006 + +#define INVALID_CONNECTION_METHODS 0x0A +#define COMMAND_TTA_Check_Expected_ParamTypes COMMAND_TTA_Check_ParamTypes +#define COMMAND_TTA_Check_Update_Params 0xFFFF0002u +#define COMMAND_TTA_Store_Expected_Param_Info 0xFFFF0001u + +#define CLIENT_APP01 NULL + +#define TEEC_UNDEFINED_ERROR 0xDEADDEAD + +#define TEEC_ORIGIN_ANY_NOT_TRUSTED_APP 0x00000005 + +#define OFFSET0 0 +#define OFFSET_02 0x64 + +#define BIG_SIZE 1024 +#define IGNORE 0xFEFEFEFE +#define VALUE01 0x01234567 +#define VALUE02 0xFEDCBA98 +#define SIZE_OVER_MEMORY 0xFFFFFFFE +#define SIZE_VALUE01 4 +#define SIZE_LESSER_THAN_SIZE_02 0x1B58 +#define SIZE_GREATER_THAN_SIZE_02 0x2328 +#define ZERO 0 +#define SIZE_02 0x2000 +#define ALLOC_SIZE_02 0x2800 +#define BYTE_01 1 +#define BYTE_02 2 +#define BYTE_03 3 +#define BYTE_04 4 + +#define VALUE_A_IN_0 0x01234567 +#define VALUE_A_IN_1 0xF9E8D7C6 +#define VALUE_A_IN_2 0xE01C083D +#define VALUE_A_IN_3 0xDCA65016 +#define VALUE_A_OUT_0 0xABCD0248 +#define VALUE_A_OUT_1 0x03579EF4 +#define VALUE_A_OUT_2 0x344C64BC +#define VALUE_A_OUT_3 0x3590BBD9 +#define VALUE_B_IN_0 0x89ABCDEF +#define VALUE_B_IN_1 0x1248DCBA +#define VALUE_B_IN_2 0x5E816B61 +#define VALUE_B_IN_3 0x4C899A96 +#define VALUE_B_OUT_0 0x1A2B3C4D +#define VALUE_B_OUT_1 0x1439F7A2 +#define VALUE_B_OUT_2 0x6EC61CAE +#define VALUE_B_OUT_3 0xB2639F77 + +#define TEEC_MEM_INOUT (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT) + +static TEEC_SharedMemory share_mem[4]; +static TEEC_SharedMemory *SHARE_MEM01 = share_mem; +static TEEC_SharedMemory *SHARE_MEM02 = share_mem + 1; +static TEEC_SharedMemory *SHARE_MEM03 = share_mem + 2; +static TEEC_SharedMemory *SHARE_MEM04 = share_mem + 3; +static TEEC_SharedMemory *SHARE_MEM_NULL_BUFFER; +static TEEC_Session session[2]; +static TEEC_Session *SESSION01 = session; +static TEEC_Session *SESSION02 = session + 1; +static TEEC_Context context[2]; +static TEEC_Context *CONTEXT01 = context; +static TEEC_Context *CONTEXT02 = context + 1; +static TEEC_Operation operation[1]; +static TEEC_Operation *OPERATION01 = operation; + +/* "ItIsNotTotosTEEs" */ +static const char *INVALID_NOT_EXISTING_TEE = "ItIsNotTotosTEEs\0"; + +/** ALL_TEMPORARY_MEMORIES */ +static uint8_t *TEMP_MEM01; +static uint8_t *TEMP_MEM02; +static uint8_t *TEMP_MEM03; +static uint8_t *TEMP_MEM04; +static uint8_t *TEMP_MEM_NULL_BUFFER; + +static TEEC_UUID UUID_TTA_answerErrorTo_OpenSession = { + 0x534D4152, 0x5443, 0x534C, + { 0x54, 0x45, 0x52, 0x52, 0x54, 0x4F, 0x4F, 0x53 } +}; +static TEEC_UUID UUID_TTA_answerSuccessTo_OpenSession_Invoke = { + 0x534D4152, 0x542D, 0x4353, + { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x53, 0x55 } +}; +static TEEC_UUID UUID_Unknown = { + 0x534D4152, 0x542D, 0x4355, + { 0x4E, 0x4B, 0x2D, 0x4E, 0x4F, 0x2D, 0x57, 0x4E } +}; +static TEEC_UUID UUID_TTA_testingClientAPI_Parameters_OpenSession = { + 0x534D4152, 0x5443, 0x534C, + { 0x54, 0x43, 0x4C, 0x49, 0x50, 0x4F, 0x50, 0x53 } +}; +static TEEC_UUID UUID_TTA_testingClientAPI = { + 0x534D4152, 0x542D, 0x4353, + { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x53, 0x54 } +}; +static TEEC_UUID UUID_TTA_answerErrorTo_Invoke = { + 0x534D4152, 0x542D, 0x4353, + { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x45, 0x52 } +}; +/* TTA_testingClientAPI_Parameters_Invoke */ +static TEEC_UUID UUID_TTA_testingClientAPI_Parameters = { + 0x534D4152, 0x5443, 0x534C, + { 0x54, 0x43, 0x4C, 0x49, 0x50, 0x41, 0x52, 0x41 } +}; + +/*Registers the TEEC_SharedMemory to the TEE*/ +static TEEC_Result RegisterSharedMemory(TEEC_Context *ctx, + TEEC_SharedMemory *shm, + uint32_t size, uint32_t flags) +{ + shm->flags = flags; + shm->size = size; + shm->buffer = malloc(size); + return TEEC_RegisterSharedMemory(ctx, shm); +} + +/*Allocates temporary memory area*/ +#define AllocateTempMemory(temp_mem, size) \ + temp_mem = malloc(size) + +/*Releases temporary memory area*/ +#define ReleaseTempMemory(temp_mem) \ + do { \ + if (temp_mem != NULL) { \ + free(temp_mem); \ + temp_mem = NULL; \ + } \ + } while (0) + + +/* Assigns a and b to the value parameter */ +static inline void TEEC_prepare_OperationEachParameter_value(TEEC_Operation *op, + size_t n, + uint32_t a, + uint32_t b) +{ + if (IGNORE != a) + op->params[n].value.a = a; + + if (IGNORE != b) + op->params[n].value.b = b; + +} + +/*Define TEEC_SharedMemory memory content.*/ +#define TEEC_defineMemoryContent_sharedMemory(sh_mem, val, size_val) \ + memcpy(sh_mem->buffer, &val, size_val) + +/*Define temp memory content.*/ +#define TEEC_defineMemoryContent_tmpMemory(buf, val, size_val) \ + memcpy(buf, &(val), size_val) + +#define INVOKE_REMEMBER_EXP_PARAM_TYPES(session, cmd, p0, p1, p2, p3, exp) \ + do { \ + uint32_t ret_orig = 0; \ + \ + memset(OPERATION01, 0x00, sizeof(TEEC_Operation)); \ + OPERATION01->paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, \ + TEEC_NONE, \ + TEEC_NONE, \ + TEEC_NONE); \ + OPERATION01->params[0].value.a = \ + TEEC_PARAM_TYPES((p0), (p1), (p2), (p3)); \ + ADBG_EXPECT(c, exp, \ + TEEC_InvokeCommand(session, cmd, OPERATION01, \ + &ret_orig)); \ + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, \ + ret_orig); \ + } while (0) + +static void store_param_info(TEEC_Operation *op, uint32_t param_num, + uint32_t pt, uint32_t size_in, uint32_t value_in, + uint32_t size_out, uint32_t value_out) +{ + memset(op, 0, sizeof(*op)); + op->params[0].value.a = param_num; + op->params[0].value.b = pt; + switch (pt) { + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + op->paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_NONE); + if (size_in != IGNORE) + op->params[1].value.a = size_in; + if (value_in != IGNORE) + op->params[1].value.b = value_in; + if (size_out != IGNORE) + op->params[2].value.a = size_out; + if (value_out != IGNORE) + op->params[2].value.b = value_out; + break; + default: + op->paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + break; + } +} + +#define INVOKE_STORE_EXP_PARAM_INFO(session, cmd, paramNumber, paramType, \ + sizeIN, valueIN, sizeOUT, valueOUT, \ + expReturnOrigin, expTEEC_Result) \ + do { \ + uint32_t ret_orig = 0; \ + \ + store_param_info(OPERATION01, paramNumber, paramType, sizeIN, \ + valueIN, sizeOUT, valueOUT); \ + ADBG_EXPECT(c, expTEEC_Result, \ + TEEC_InvokeCommand(session, cmd, OPERATION01, \ + &ret_orig)); \ + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, expReturnOrigin, ret_orig); \ + } while (0) + +static void init_mem(uint8_t *buf, size_t buf_size, size_t begin_size, + size_t middle_size, uint8_t begin_value, + uint8_t middle_value, uint8_t end_value) +{ + memset(buf, begin_value, begin_size); + memset(buf + begin_size, middle_value, middle_size); + memset(buf + begin_size + middle_size, end_value, + buf_size - begin_size - middle_size); +} + +#define TEEC_initialize_memory(shm, tmpMem, offset, _size, value_beginning, \ + value_middle, value_end) \ + do { \ + if ((unsigned long)shm != IGNORE) {\ + TEEC_SharedMemory *__shm = (void *)(long)shm; \ + init_mem(__shm->buffer, __shm->size, offset, _size, \ + value_beginning, value_middle, value_end); \ + assert(tempMem == IGNORE); \ + } else if ((unsigned long)tmpMem != IGNORE) {\ + /* \ + * We can't tell the size of tmpMem, so we assume \ + * it's offset + size large. \ + */ \ + init_mem((void *)(long)tmpMem, offset + _size, offset, \ + _size, value_beginning, value_middle, \ + value_end); \ + } else { \ + assert(0); \ + } \ + } while (0) + +static void TEEC_prepare_OperationEachParameter_memref(TEEC_Operation *op, + size_t param_num, + TEEC_SharedMemory *shm, + size_t offs, size_t sz) +{ + op->params[param_num] = (TEEC_Parameter){ + .memref = { + .parent = shm, .size = sz, .offset = offs, + } + }; +} + +static void TEEC_prepare_OperationEachParameter_tmpref(TEEC_Operation *op, + size_t param_num, + void *buf, size_t sz) +{ + op->params[param_num] = (TEEC_Parameter){ + .tmpref = { + .buffer = buf, .size = sz, + } + }; +} + +/*Compares two memories and checks if their length and content is the same */ +#define TEEC_checkMemoryContent_sharedMemory(op, param_num, shrm, exp_buf, \ + exp_blen) \ + do { \ + if ((exp_buf) == IGNORE) { \ + ADBG_EXPECT((c), exp_blen, \ + (op)->params[(param_num)].memref.size); \ + } else { \ + ADBG_EXPECT_COMPARE_POINTER((c), (shrm), ==, \ + (op)->params[(param_num)].\ + memref.parent); \ + ADBG_EXPECT_BUFFER((c), &(exp_buf), (exp_blen), \ + (shrm)->buffer, \ + (op)->params[(param_num)].\ + memref.size); \ + } \ + } while (0) + +/* + * Compares the content of the memory cells in OP with the expected value + * contained. + */ +#define TEEC_checkMemoryContent_tmpMemory(op, param_num, \ + buf, exp_buf, exp_blen) \ + do { \ + if ((exp_buf) == 0) { \ + ADBG_EXPECT((c), exp_blen, \ + (op)->params[(param_num)].tmpref.size); \ + } else { \ + ADBG_EXPECT_COMPARE_POINTER((c), (buf), ==, \ + (op)->params[(param_num)].\ + tmpref.buffer); \ + ADBG_EXPECT_BUFFER((c), &(exp_buf), (exp_blen), \ + (buf), \ + (op)->params[(param_num)].\ + memref.size); \ + } \ + } while (0) + +/* + * Compares the content of the memory cells in OP with the expected value + * contained. + */ +#define TEEC_checkContent_Parameter_value(op, param_num, exp_a, exp_b) \ + do { \ + if (IGNORE != exp_a) \ + ADBG_EXPECT((c), exp_a, \ + (op)->params[(param_num)].value.a); \ + if (IGNORE != exp_b) \ + ADBG_EXPECT((c), exp_b, \ + (op)->params[(param_num)].value.b); \ + } while (0) + +/*Invoke command using TEEC_InvokeCommand and check the returned value.*/ +#define XML_InvokeCommand(c, session, cmd, operation, returnOrigin, expected) \ + do { \ + uint32_t ret_orig = 0; \ + \ + ADBG_EXPECT(c, expected, \ + TEEC_InvokeCommand(session, cmd, operation, \ + &ret_orig)); \ + if (returnOrigin) \ + ADBG_EXPECT(c, (unsigned long)returnOrigin, ret_orig); \ + } while (0) + +#endif /* XML_CLIENT_API_H_ */ diff --git a/optee/optee_test/host/xtest/gp/include/xml_common_api.h b/optee/optee_test/host/xtest/gp/include/xml_common_api.h new file mode 100644 index 0000000..245edde --- /dev/null +++ b/optee/optee_test/host/xtest/gp/include/xml_common_api.h @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef XML_COMMON_API_H_ +#define XML_COMMON_API_H_ + +#include +#include + +#include "xtest_helpers.h" +#include "xtest_test.h" + +#define BIT(n) (1ul << (n)) +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define ALLOCATE_SHARED_MEMORY(context, sharedMemory, sharedMemorySize, \ + memoryType, exit_label) \ + res = AllocateSharedMemory(context, sharedMemory, sharedMemorySize, \ + memoryType); \ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) \ + goto exit_label; \ + memset(sharedMemory->buffer, 0, sharedMemorySize); + +#define ALLOCATE_AND_FILL_SHARED_MEMORY(context, sharedMemory, \ + sharedMemorySize, \ + memoryType, copySize, data, \ + exit_label) \ + res = AllocateSharedMemory(context, sharedMemory, sharedMemorySize, \ + memoryType); \ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) \ + goto exit_label; \ + memset(sharedMemory->buffer, 0, sharedMemorySize); \ + if (data != NULL) { \ + memcpy(sharedMemory->buffer, data, copySize); \ + } +#define ALLOCATE_AND_FILL_SHARED_MEMORY_6(a,b,c,d,e,f) \ + ALLOCATE_AND_FILL_SHARED_MEMORY(a,b,c,d,c,e,f) + +#define SET_SHARED_MEMORY_OPERATION_PARAMETER(parameterNumber, \ + sharedMemoryOffset, \ + sharedMemory, \ + sharedMemorySize) \ + op.params[parameterNumber].memref.offset = sharedMemoryOffset; \ + op.params[parameterNumber].memref.size = sharedMemorySize; \ + op.params[parameterNumber].memref.parent = sharedMemory; + +/*Open session using TEEC_OpenSession and + check the returned value and/or returned origin.*/ +#define XML_OpenSession(c, context, session, destination, connectionMethod, \ + connectionData, operation, returnOrigin, expected) \ + do { \ + uint32_t ret_orig = 0; \ + \ + XML_VERIFY(c, expected, \ + TEEC_OpenSession(context, session, destination, \ + connectionMethod, connectionData, \ + operation, &ret_orig)); \ + if (!(unsigned long)(returnOrigin) || \ + (unsigned long)(returnOrigin) == \ + TEEC_ORIGIN_ANY_NOT_TRUSTED_APP) \ + ADBG_EXPECT_NOT(c, (unsigned long)returnOrigin, \ + ret_orig); \ + else \ + ADBG_EXPECT(c, (unsigned long)returnOrigin, ret_orig); \ + } while (0) + +/* XML_VERIFY macro define. + * + * Use ADBG_EXPECT or ADBG_EXPECT_NOT depending on the expected return value. + * + * ADBG_EXPECT() -> IF(EXP == GOT) RETURN TRUE + * ADBG_EXPECT() -> IF(EXP != GOT) RETURN TRUE + */ +#define XML_VERIFY(c, exp, got) \ + do { \ + if (exp == TEEC_UNDEFINED_ERROR) \ + ADBG_EXPECT_NOT(c, exp, got); \ + else \ + ADBG_EXPECT(c, exp, got); \ + } while (0) + +/*Initialize context using TEEC_InitializeContext and + check the returned value.*/ +#define XML_InitializeContext(c, name, context, expected) \ + XML_VERIFY(c, expected, TEEC_InitializeContext(name, context)) + +#define OPERATION_TEEC_PARAM_TYPES(op, p0, p1, p2, p3) \ + do { \ + op->paramTypes = TEEC_PARAM_TYPES(p0, p1, p2, p3); \ + } while (0) + +/*dummy functions*/ +#define TEEC_SetUp_TEE() /*do nothing for now*/ +#define TEEC_TearDown_TEE(a) /*do nothing for now*/ +#define TEEC_SelectApp(a, b) /*do nothing for now*/ +#define TEEC_createThread(a, b) /*do nothing for now*/ + +struct attr_value { + uint8_t buf[1024]; + size_t buf_size; + uint32_t attr_id; +}; + +#define MAX_NUM_SAVED_ATTR_VALUES 8 +static struct attr_value saved_attr[MAX_NUM_SAVED_ATTR_VALUES] __maybe_unused; + + +static TEEC_Result __maybe_unused +Invoke_Simple_Function(ADBG_Case_t *c __unused, TEEC_Session *sess, + uint32_t cmdId) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + return TEEC_InvokeCommand(sess, cmdId, &op, &org); +} + +static TEEC_Result __maybe_unused +Invoke_Simple_Function_v1(ADBG_Case_t *c __unused, TEEC_Session *sess, + uint32_t cmd, uint32_t a, uint32_t b) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + op.params[0].value.a = a; + op.params[0].value.b = b; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, cmd, &op, &org); +} + +static TEEC_Result __maybe_unused +Invoke_Simple_Function_v2(ADBG_Case_t *c __unused, TEEC_Session *sess, + uint32_t cmd, uint32_t a0, uint32_t b0, + uint32_t a1, uint32_t b1) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + op.params[0].value.a = a0; + op.params[0].value.b = b0; + op.params[1].value.a = a1; + op.params[1].value.b = b1; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, cmd, &op, &org); +} + +static TEEC_Result __maybe_unused +Invoke_Simple_Function_v3(ADBG_Case_t *c __unused, TEEC_Session *sess, + uint32_t cmd, uint32_t a0, uint32_t b0, uint32_t a1, + uint32_t b1, uint32_t a2, uint32_t b2) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + op.params[0].value.a = a0; + op.params[0].value.b = b0; + op.params[1].value.a = a1; + op.params[1].value.b = b1; + op.params[2].value.a = a2; + op.params[2].value.b = b2; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + + return TEEC_InvokeCommand(sess, cmd, &op, &org); +} + +static TEEC_Result __maybe_unused +Invoke_Simple_Function_v4(ADBG_Case_t *c __unused, TEEC_Session *sess, + uint32_t cmd, uint32_t a0, uint32_t b0, uint32_t a1, + uint32_t b1, uint32_t a2, uint32_t b2, uint32_t a3, + uint32_t b3) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + op.params[0].value.a = a0; + op.params[0].value.b = b0; + op.params[1].value.a = a1; + op.params[1].value.b = b1; + op.params[2].value.a = a2; + op.params[2].value.b = b2; + op.params[3].value.a = a3; + op.params[3].value.b = b3; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, TEEC_VALUE_INPUT); + + return TEEC_InvokeCommand(sess, cmd, &op, &org); +} + +static TEEC_Result __maybe_unused AllocateSharedMemory(TEEC_Context *ctx, + TEEC_SharedMemory *shm, + uint32_t size, + uint32_t flags) +{ + shm->flags = flags; + shm->size = size; + return TEEC_AllocateSharedMemory(ctx, shm); +} + +static TEEC_Result GetObjectBufferAttribute_helper(ADBG_Case_t *c, + TEEC_Session *sess, + size_t n, + uint32_t cmd, uint32_t obj, + uint32_t attr_id, + bool buffer_is_null, + uint32_t buffer_size) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEE_SUCCESS; + uint32_t org = 0; + static TEEC_SharedMemory shm = { }; + uint32_t memref_type = TEEC_MEMREF_TEMP_OUTPUT; + + if (!ADBG_EXPECT_COMPARE_SIGNED(c, n, <, MAX_NUM_SAVED_ATTR_VALUES)) + return TEEC_ERROR_BAD_PARAMETERS; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, buffer_size, <=, + sizeof(saved_attr[n].buf))) + return TEEC_ERROR_BAD_PARAMETERS; + + if (!buffer_is_null) { + shm.size = buffer_size; + shm.flags = TEEC_MEM_OUTPUT; + res = TEEC_AllocateSharedMemory(sess->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, &shm, shm.size); + memref_type = TEEC_MEMREF_PARTIAL_OUTPUT; + } + + op.params[0].value.a = obj; + op.params[0].value.b = attr_id; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, memref_type, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + if (!buffer_is_null) { + if (res) { + memset(saved_attr + n, 0, sizeof(saved_attr[n])); + } else { + memcpy(saved_attr[n].buf, shm.buffer, + sizeof(saved_attr[n].buf)); + saved_attr[n].buf_size = op.params[1].memref.size; + saved_attr[n].attr_id = attr_id; + } + TEEC_ReleaseSharedMemory(&shm); + } + + return res; +} + +static TEEC_Result __maybe_unused +Invoke_GetObjectBufferAttribute(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t obj, uint32_t attr_id, + bool buffer_is_null, uint32_t buffer_size) +{ + return GetObjectBufferAttribute_helper(c, sess, 0, cmd, obj, attr_id, + buffer_is_null, buffer_size); +} + +static TEEC_Result __maybe_unused +Invoke_FreeTransientObject(ADBG_Case_t *c, TEEC_Session *sess, uint32_t cmd, + uint32_t obj_handle) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_handle, 0); +} +#endif /* XML_COMMON_API_H_ */ diff --git a/optee/optee_test/host/xtest/gp/include/xml_crypto_api.h b/optee/optee_test/host/xtest/gp/include/xml_crypto_api.h new file mode 100644 index 0000000..8b49dd1 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/include/xml_crypto_api.h @@ -0,0 +1,3589 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef XML_CRYPTO_API_H_ +#define XML_CRYPTO_API_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMD_DS_AllocateTransientObject 0x10000001 +#define CMD_DS_StoreBuffer 0x1F0000CB +#define CMD_DS_InitRefAttribute 0x10000006 +#define CMD_DS_GetObjectBufferAttribute 0x10000008 +#define CMD_DS_FreeTransientObject 0x10000004 +#define CMD_DS_RestrictObjectUsage1 0x10000003 + +#include "xml_common_api.h" +#include "xtest_helpers.h" +#include "xtest_test.h" + +#define declare_local_vars \ + uint32_t iHandleFlags1 __maybe_unused = 0; \ + uint32_t iHandleFlags2 __maybe_unused = 0; \ + uint32_t iAttributeList1 __maybe_unused = 0; \ + uint32_t iObjectUsage1 __maybe_unused = 0; \ + const uint32_t iAttributeListEmpty __maybe_unused = 0; \ + const uint32_t iHandleFlagsNone __maybe_unused = 0; + +#define set_flag(vector, flag) do { (vector) |= (flag); } while (0) +#define clear_flag(vector, flag) do { (vector) &= ~(flag); } while (0) + +#define set_handle_flag(vector, flag) set_flag((vector), (flag)) +#define clear_handle_flag(vector, flag) clear_flag((vector), (flag)) +#define add_attribute(vector, id) set_flag((vector), 1ul << (id)) +#define set_usage_flag(vector, flag) set_flag((vector), (flag)) + +#define BIT_CHANGE(a, b) ((a) ^= BIT((b))) + +#define CRYPTO_INIT(b) \ + b.buffer = NULL; \ + b.size = 0; + +#define CRYPTO_MALLOC(b, size) \ + b.size = size; \ + b.buffer = malloc(size); + +#define CRYPTO_FREE(b) { \ + if (b.buffer != NULL) { \ + b.size = 0; \ + free(b.buffer); \ + b.buffer = NULL; \ + } } + +#define CMD_Crypto_InitObjectWithKeys 0x00010001 +#define CMD_Crypto_FreeAllKeysAndOperations 0x00010002 +#define CMD_Crypto_AllocateOperation 0x00010003 +#define CMD_Crypto_FreeOperation 0x00010004 +#define CMD_Crypto_ResetOperation 0x00010005 +#define CMD_Crypto_SetOperationKey 0x00010006 +#define CMD_Crypto_SetOperationKey2 0x00010007 +#define CMD_Crypto_CopyOperation 0x00010008 +#define CMD_Crypto_GetOperationInfo 0x00010009 +#define CMD_Crypto_DigestUpdate 0x0001000A +#define CMD_Crypto_DigestDoFinal 0x0001000B +#define CMD_Crypto_CipherInit 0x0001000C +#define CMD_Crypto_CipherUpdate 0x0001000D +#define CMD_Crypto_CipherDoFinal 0x0001000E +#define CMD_Crypto_MACInit 0x0001000F +#define CMD_Crypto_MACUpdate 0x00010010 +#define CMD_Crypto_MACComputeFinal 0x00010011 +#define CMD_Crypto_MACCompareFinal 0x00010012 +#define CMD_Crypto_AsymmetricEncrypt 0x00010013 +#define CMD_Crypto_AsymmetricDecrypt 0x00010014 +#define CMD_Crypto_AsymmetricSignDigest 0x00010015 +#define CMD_Crypto_AsymmetricVerifyDigest 0x00010016 +#define CMD_Crypto_AEInit 0x00010017 +#define CMD_Crypto_AEUpdate 0x00010018 +#define CMD_Crypto_AEUpdateAAD 0x00010019 +#define CMD_Crypto_AEEncryptFinal 0x0001001A +#define CMD_Crypto_AEDecryptFinal 0x0001001B +#define CMD_Crypto_DeriveKey 0x0001001D +#define CMD_Crypto_GenerateRandom 0x0001001E +#define CMD_Crypto_GetOperationInfoMultiple 0x0001001F +#define CMD_Crypto_TTAEnsureIntermediateBufferSize 0x00010020 +#define CMD_Crypto_InitObjectWithKeysExt 0x00010021 + +/*Missing TEE Error codes*/ +#define TEE_ERROR_TOO_SHORT_BUFFER TEE_ERROR_SHORT_BUFFER + +/*Other defines*/ +#define TEE_USAGE_NONE 0 + +#define ATTRIBUTE_01 0 +#define ATTRIBUTE_02 1 +#define ATTRIBUTE_03 2 +#define ATTRIBUTE_04 3 +#define ATTRIBUTE_05 4 +#define ATTRIBUTE_06 5 +#define ATTRIBUTE_NONE 0xFFFFFFFF + +#define BUFFER_01 0 +#define BUFFER_02 1 +#define BUFFER_03 2 +#define BUFFER_04 3 +#define BUFFER_05 4 +#define BUFFER_06 5 + +#define BIG_SIZE 1024 +#define DS_BIG_SIZE 16384 + +/*ALL_OBJECT_SIZES*/ +#define KEY_SIZE_TOO_LARGE 4096 +#define SIZE_AES_192 192 +#define SIZE_AES_256 256 +#define SIZE_DES3_128 128 +#define SIZE_DES3_192 192 +#define SIZE_DES_64 64 +#define SIZE_DH_KEYPAIR_1024 1024 +#define SIZE_DIGEST_MD5_16 16 +#define SIZE_DIGEST_SHA1_20 20 +#define SIZE_DIGEST_SHA224_28 28 +#define SIZE_DIGEST_SHA256_32 32 +#define SIZE_DIGEST_SHA384_48 48 +#define SIZE_DIGEST_SHA512_64 64 +#define SIZE_DSA_SHA1_KEYPAIR_768 768 +#define SIZE_DSA_SHA1_PUBLIC_KEY_768 768 +#define SIZE_DSA_SHA224_KEYPAIR_2048 2048 +#define SIZE_DSA_SHA224_PUBLIC_KEY_2048 2048 +#define SIZE_DSA_SHA256_KEYPAIR_2048 2048 +#define SIZE_DSA_SHA256_KEYPAIR_3072 3072 +#define SIZE_DSA_SHA256_PUBLIC_KEY_2048 2048 +#define SIZE_DSA_SHA256_PUBLIC_KEY_3072 3072 +#define SIZE_ECDH_P192 192 +#define SIZE_ECDH_P224 224 +#define SIZE_ECDH_P256 256 +#define SIZE_ECDH_P384 384 +#define SIZE_ECDH_P521 521 +#define SIZE_ECDSA_P192 192 +#define SIZE_ECDSA_P224 224 +#define SIZE_ECDSA_P256 256 +#define SIZE_ECDSA_P384 384 +#define SIZE_ECDSA_P521 521 +#define SIZE_GENERIC_SECRET_2048 2048 +#define SIZE_HMAC_MD5_256 256 +#define SIZE_HMAC_SHA1_256 256 +#define SIZE_HMAC_SHA224_256 256 +#define SIZE_HMAC_SHA256_512 512 +#define SIZE_HMAC_SHA384_512 512 +#define SIZE_HMAC_SHA512_512 512 +#define SIZE_RSA_KEYPAIR_1024 1024 +#define SIZE_RSA_KEYPAIR_2048 2048 +#define SIZE_RSA_PUBLIC_KEY_2048 2048 +#define SIZE_ZERO 0 +#define WRONG_ECC_SIZE 10 +#define WRONG_SIZE 5 + +/*ALL_TEE_TAG_LENGTH_FOR_AES*/ +#define AES_104_bits 104 +#define AES_112_bits 112 +#define AES_120_bits 120 +#define AES_128_bits 128 +#define AES_32_bits 32 +#define AES_48_bits 48 +#define AES_64_bits 64 +#define AES_80_bits 80 +#define AES_96_bits 96 + +/*attribute not defined*/ +#define TEE_ATTR_NONE 0 + +#define AE_TAG_BUFFER_SIZE_32 32 +#define BIG_ATTRIBUTE_BUFFER_SIZE 512 +#define BUFFER_BIG_SIZE BIG_SIZE + +#define OBJECT_HANDLE_NULL 0 +#define OBJECT_HANDLE_01 1 +#define OBJECT_HANDLE_02 2 +#define OBJECT_HANDLE_03 3 +#define OBJECT_HANDLE_INVALID 4 + +#define OPERATION_HANDLE_NULL 0 +#define OPERATION_HANDLE_01 1 +#define OPERATION_HANDLE_02 2 +#define OPERATION_HANDLE_INVALID 4 + +static TEEC_SharedMemory share_mem[6]; +static TEEC_SharedMemory *SHARE_MEM01 = share_mem; +static TEEC_SharedMemory *SHARE_MEM02 = share_mem + 1; +static TEEC_SharedMemory *SHARE_MEM03 = share_mem + 2; +static TEEC_SharedMemory *SHARE_MEM04 = share_mem + 3; +static TEEC_SharedMemory *SHARE_MEM05 = share_mem + 4; +static TEEC_SharedMemory *SHARE_MEM06 = share_mem + 5; +static TEEC_Session session[2]; +static TEEC_Session *SESSION01 = session; +static TEEC_Session *SESSION02 = session + 1; +static TEEC_Context context[2]; +static TEEC_Context *CONTEXT01 = context; +static TEEC_Context *CONTEXT02 = context + 1; + +/*ALL_ATTRIBUTE_VALUES*/ +static const uint8_t TEE_ATTR_AES_256_VALUE01[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, + 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, + 0x09, 0x14, 0xdf, 0xf4 +}; +static const uint8_t TEE_ATTR_DH_PRIME_VALUE01[] = { + 0xe0, 0x01, 0xe8, 0x96, 0x7d, 0xb4, 0x93, 0x53, 0xe1, 0x6f, 0x8e, 0x89, + 0x22, 0x0c, 0xce, 0xfc, + 0x5c, 0x5f, 0x12, 0xe3, 0xdf, 0xf8, 0xf1, 0xd1, 0x49, 0x90, 0x12, 0xe6, + 0xef, 0x53, 0xe3, 0x1f, + 0x02, 0xea, 0xcc, 0x5a, 0xdd, 0xf3, 0x37, 0x89, 0x35, 0xc9, 0x5b, 0x21, + 0xea, 0x3d, 0x6f, 0x1c, + 0xd7, 0xce, 0x63, 0x75, 0x52, 0xec, 0x38, 0x6c, 0x0e, 0x34, 0xf7, 0x36, + 0xad, 0x95, 0x17, 0xef, + 0xfe, 0x5e, 0x4d, 0xa7, 0xa8, 0x6a, 0xf9, 0x0e, 0x2c, 0x22, 0x8f, 0xe4, + 0xb9, 0xe6, 0xd8, 0xf8, + 0xf0, 0x2d, 0x20, 0xaf, 0x78, 0xab, 0xb6, 0x92, 0xac, 0xbc, 0x4b, 0x23, + 0xfa, 0xf2, 0xc5, 0xcc, + 0xd4, 0x9a, 0x0c, 0x9a, 0x8b, 0xcd, 0x91, 0xac, 0x0c, 0x55, 0x92, 0x01, + 0xe6, 0xc2, 0xfd, 0x1f, + 0x47, 0xc2, 0xcb, 0x2a, 0x88, 0xa8, 0x3c, 0x21, 0x0f, 0xc0, 0x54, 0xdb, + 0x29, 0x2d, 0xbc, 0x45 +}; +static const uint8_t TEE_ATTR_DH_BASE_VALUE01[] = { + 0x1c, 0xe0, 0xf6, 0x69, 0x26, 0x46, 0x11, 0x97, 0xef, 0x45, 0xc4, 0x65, + 0x8b, 0x83, 0xb8, 0xab, + 0x04, 0xa9, 0x22, 0x42, 0x68, 0x50, 0x4d, 0x05, 0xb8, 0x19, 0x83, 0x99, + 0xdd, 0x71, 0x37, 0x18, + 0xcc, 0x1f, 0x24, 0x5d, 0x47, 0x6c, 0xcf, 0x61, 0xa2, 0xf9, 0x34, 0x93, + 0xf4, 0x1f, 0x55, 0x52, + 0x48, 0x65, 0x57, 0xe6, 0xd4, 0xca, 0xa8, 0x00, 0xd6, 0xd0, 0xdb, 0x3c, + 0xbf, 0x5a, 0x95, 0x4b, + 0x20, 0x8a, 0x4e, 0xba, 0xf7, 0xe6, 0x49, 0xfb, 0x61, 0x24, 0xd8, 0xa2, + 0x1e, 0xf2, 0xf2, 0x2b, + 0xaa, 0xae, 0x29, 0x21, 0x10, 0x19, 0x10, 0x51, 0x46, 0x47, 0x31, 0xb6, + 0xcc, 0x3c, 0x93, 0xdc, + 0x6e, 0x80, 0xba, 0x16, 0x0b, 0x66, 0x64, 0xa5, 0x6c, 0xfa, 0x96, 0xea, + 0xf1, 0xb2, 0x83, 0x39, + 0x8e, 0xb4, 0x61, 0x64, 0xe5, 0xe9, 0x43, 0x84, 0xee, 0x02, 0x24, 0xe7, + 0x1f, 0x03, 0x7c, 0x23 +}; +static const uint8_t TEE_ATTR_HMAC_SHA256_512_VALUE01[] = { + 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 +}; +static const uint8_t TEE_ATTR_DH_PUBLIC_VALUE_VALUE01[] = { + 0xbb, 0xe9, 0x18, 0xdd, 0x4b, 0x2b, 0x94, 0x1b, 0x10, 0x0e, 0x88, 0x35, + 0x28, 0x68, 0xfc, 0x62, + 0x04, 0x38, 0xa6, 0xdb, 0x32, 0xa6, 0x9e, 0xee, 0x6c, 0x6f, 0x45, 0x1c, + 0xa3, 0xa6, 0xd5, 0x37, + 0x77, 0x75, 0x5b, 0xc1, 0x37, 0x0a, 0xce, 0xfe, 0x2b, 0x8f, 0x13, 0xa9, + 0x14, 0x2c, 0x5b, 0x44, + 0x15, 0x78, 0x86, 0x30, 0xd6, 0x95, 0xb1, 0x92, 0x20, 0x63, 0xa3, 0xcf, + 0x9d, 0xef, 0x65, 0x61, + 0x27, 0x4d, 0x24, 0x01, 0xe7, 0xa1, 0x45, 0xf2, 0xd8, 0xb9, 0x3a, 0x45, + 0x17, 0xf4, 0x19, 0xd0, + 0x5e, 0xf8, 0xcb, 0x35, 0x59, 0x37, 0x9d, 0x04, 0x20, 0xa3, 0xbf, 0x02, + 0xad, 0xfe, 0xa8, 0x60, + 0xb2, 0xc3, 0xee, 0x85, 0x58, 0x90, 0xf3, 0xb5, 0x57, 0x2b, 0xb4, 0xef, + 0xd7, 0x8f, 0x37, 0x68, + 0x78, 0x7c, 0x71, 0x52, 0x9d, 0x5e, 0x0a, 0x61, 0x4f, 0x09, 0x89, 0x92, + 0x39, 0xf7, 0x4b, 0x01 +}; +static const uint8_t TEE_ATTR_DH_PRIVATE_VALUE_VALUE01[] = { + 0x53, 0x8d, 0x3d, 0x64, 0x27, 0x4a, 0x40, 0x05, 0x9b, 0x9c, 0x26, 0xe9, + 0x13, 0xe6, 0x91, 0x53, + 0x23, 0x7b, 0x55, 0x83 +}; +static const uint8_t TEE_ATTR_RSA_MODULUS_VALUE01[] = { + 0xf0, 0x1a, 0x95, 0xcd, 0x5f, 0x9f, 0x1c, 0xbc, 0x5c, 0x2e, 0xc8, 0x00, + 0x3b, 0xfa, 0xe0, 0xd5, + 0x72, 0xea, 0xfc, 0x9e, 0x74, 0xe1, 0x02, 0x66, 0xa8, 0x13, 0x3f, 0x0c, + 0xe6, 0x24, 0xcb, 0x1c, + 0xa5, 0xdf, 0x64, 0xfb, 0x06, 0xd7, 0x13, 0xce, 0xaa, 0x6c, 0xee, 0x16, + 0x7b, 0xf8, 0x92, 0xaf, + 0xc4, 0x5b, 0x46, 0x18, 0xc6, 0x30, 0xb6, 0x04, 0x1c, 0x3a, 0x2e, 0xd7, + 0xca, 0xb8, 0xb5, 0x00, + 0x78, 0x89, 0xa0, 0x69, 0x37, 0x84, 0x59, 0x99, 0x0c, 0x2f, 0x00, 0xe5, + 0x3b, 0xe1, 0x18, 0xe0, + 0xb9, 0x2e, 0x77, 0x1d, 0x32, 0x7e, 0x5f, 0xf4, 0x18, 0xf3, 0x9f, 0x58, + 0xc6, 0x83, 0xe2, 0x7a, + 0xcb, 0x89, 0x18, 0xc2, 0x09, 0x84, 0x7e, 0x9d, 0x96, 0xe0, 0xb9, 0x49, + 0x75, 0xef, 0xcf, 0xff, + 0xf0, 0xb6, 0x18, 0xd3, 0x7a, 0xc1, 0x6f, 0x0c, 0x55, 0x33, 0xbe, 0x9d, + 0x63, 0x06, 0xd6, 0x9f, + 0xc1, 0xa5, 0xe9, 0xbd, 0xb1, 0xb2, 0x5d, 0x5c, 0xf9, 0xab, 0xa9, 0xb5, + 0x6a, 0x4e, 0xa4, 0xfa, + 0x44, 0x32, 0xd6, 0x71, 0x2e, 0x5f, 0xa6, 0x25, 0xf8, 0x40, 0x24, 0xc4, + 0x5b, 0x61, 0x55, 0x1b, + 0xac, 0xa3, 0x0a, 0x11, 0x8e, 0x65, 0x20, 0xda, 0x2c, 0x0d, 0xdf, 0xdb, + 0x47, 0x6b, 0x61, 0x18, + 0x4d, 0xfe, 0xfd, 0x2a, 0x7e, 0x77, 0x40, 0x44, 0x43, 0xc6, 0x33, 0x6c, + 0xe5, 0x1b, 0x8d, 0x80, + 0xf9, 0x97, 0xa2, 0xe4, 0xb9, 0x34, 0x3e, 0x28, 0x94, 0x9f, 0xbd, 0xa8, + 0x2b, 0x0a, 0x4d, 0x1a, + 0xa8, 0x06, 0xe5, 0x99, 0x4e, 0xb9, 0x13, 0x45, 0xc8, 0xf6, 0x0f, 0xd0, + 0x4d, 0xbf, 0xe7, 0x8f, + 0xed, 0xca, 0x8e, 0xf8, 0x8d, 0x87, 0x5f, 0xd4, 0xb4, 0x1a, 0x2c, 0xc9, + 0xa7, 0x67, 0x7e, 0xb2, + 0x1b, 0xc1, 0xce, 0xb6, 0x83, 0x7c, 0xce, 0xb4, 0x3d, 0x85, 0xc7, 0x53, + 0x30, 0x7c, 0xfe, 0x85 +}; +static const uint8_t TEE_ATTR_RSA_PUBLIC_EXPONENT_VALUE01[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t TEE_ATTR_DSA_PRIME_768_VALUE01[] = { + 0xf6, 0xad, 0x20, 0x71, 0xe1, 0x5a, 0x4b, 0x9c, 0x2b, 0x7e, 0x53, 0x26, + 0xda, 0x43, 0x9d, 0xc1, + 0x47, 0x4c, 0x1a, 0xd1, 0x6f, 0x2f, 0x85, 0xe9, 0x2c, 0xea, 0x89, 0xfc, + 0xdc, 0x74, 0x66, 0x11, + 0xcf, 0x30, 0xdd, 0xc8, 0x5e, 0x33, 0xf5, 0x83, 0xc1, 0x9d, 0x10, 0xbc, + 0x1a, 0xc3, 0x93, 0x22, + 0x26, 0x24, 0x6f, 0xa7, 0xb9, 0xe0, 0xdd, 0x25, 0x77, 0xb5, 0xf4, 0x27, + 0x59, 0x4c, 0x39, 0xfa, + 0xeb, 0xfc, 0x59, 0x8a, 0x32, 0xe1, 0x74, 0xcb, 0x8a, 0x68, 0x03, 0x57, + 0xf8, 0x62, 0xf2, 0x0b, + 0x6e, 0x84, 0x32, 0xa5, 0x30, 0x65, 0x2f, 0x1c, 0x21, 0x39, 0xae, 0x1f, + 0xaf, 0x76, 0x8b, 0x83 +}; +static const uint8_t TEE_ATTR_DSA_SUBPRIME_160_VALUE01[] = { + 0x87, 0x44, 0xe4, 0xdd, 0xc6, 0xd0, 0x19, 0xa5, 0xea, 0xc2, 0xb1, 0x5a, + 0x15, 0xd7, 0xe1, 0xc7, + 0xf6, 0x63, 0x35, 0xf7 +}; +static const uint8_t TEE_ATTR_DSA_BASE_768_VALUE01[] = { + 0x9a, 0x09, 0x32, 0xb3, 0x8c, 0xb2, 0x10, 0x5b, 0x93, 0x00, 0xdc, 0xb8, + 0x66, 0xc0, 0x66, 0xd9, + 0xce, 0xc6, 0x43, 0x19, 0x2f, 0xcb, 0x28, 0x34, 0xa1, 0x23, 0x9d, 0xba, + 0x28, 0xbd, 0x09, 0xfe, + 0x01, 0x00, 0x1e, 0x04, 0x51, 0xf9, 0xd6, 0x35, 0x1f, 0x6e, 0x56, 0x4a, + 0xfb, 0xc8, 0xf8, 0xc3, + 0x9b, 0x10, 0x59, 0x86, 0x3e, 0xbd, 0x09, 0x85, 0x09, 0x0b, 0xd5, 0x5c, + 0x82, 0x8e, 0x9f, 0xc1, + 0x57, 0xac, 0x7d, 0xa3, 0xcf, 0xc2, 0x89, 0x2a, 0x0e, 0xd9, 0xb9, 0x32, + 0x39, 0x05, 0x82, 0xf2, + 0x97, 0x1e, 0x4a, 0x0c, 0x48, 0x3e, 0x06, 0x22, 0xd7, 0x31, 0x66, 0xbf, + 0x62, 0xa5, 0x9f, 0x26 +}; +static const uint8_t TEE_ATTR_DSA_PRIVATE_VALUE_160_VALUE01[] = { + 0x70, 0x4a, 0x46, 0xc6, 0x25, 0x2a, 0x95, 0xa3, 0x9b, 0x40, 0xe0, 0x43, + 0x5a, 0x69, 0x1b, 0xad, + 0xae, 0x52, 0xa5, 0xc0 +}; +static const uint8_t TEE_ATTR_DSA_PUBLIC_VALUE_768_VALUE01[] = { + 0x52, 0x9d, 0xed, 0x98, 0xa2, 0x32, 0x09, 0x85, 0xfc, 0x84, 0xb6, 0x5a, + 0x9d, 0xc8, 0xd4, 0xfe, + 0x41, 0xad, 0xa6, 0xe3, 0x59, 0x3d, 0x70, 0x4f, 0x08, 0x98, 0xc1, 0x4e, + 0xc2, 0x46, 0x34, 0xdd, + 0xf5, 0xf1, 0xdb, 0x47, 0xcc, 0x49, 0x15, 0xfc, 0xe1, 0xe2, 0x67, 0x4d, + 0x2e, 0xcd, 0x98, 0xd5, + 0x8b, 0x59, 0x8e, 0x8d, 0xdf, 0xaf, 0xf3, 0x0e, 0x88, 0x26, 0xf5, 0x0a, + 0xab, 0x40, 0x27, 0xb5, + 0xaa, 0xb8, 0x87, 0xc1, 0x9a, 0xd9, 0x6d, 0x7e, 0x57, 0xde, 0x53, 0x90, + 0xad, 0x8e, 0x55, 0x57, + 0xb4, 0x1a, 0x80, 0x19, 0xc9, 0x0d, 0x80, 0x60, 0x71, 0x79, 0xb5, 0x4e, + 0xb0, 0xad, 0x4d, 0x23 +}; +static const uint8_t TEE_ATTR_DSA_PRIME_2048_VALUE01[] = { + 0xaa, 0x81, 0x5c, 0x9d, 0xb1, 0xc4, 0xd3, 0xd2, 0x77, 0x3c, 0x7d, 0x0d, 0x4d, 0x1d, 0xa7, 0x5e, + 0xcf, 0xc4, 0xa3, 0x9e, 0x97, 0xd5, 0xfa, 0x19, 0x1f, 0xfe, 0xc8, 0xb1, 0x49, 0x0a, 0x29, 0x0c, + 0xe3, 0x35, 0xe5, 0xce, 0x87, 0xea, 0x62, 0x0a, 0x8a, 0x17, 0xde, 0x0b, 0xb6, 0x47, 0x14, 0xe2, + 0xec, 0x84, 0x0b, 0xf0, 0x0e, 0x6e, 0xbd, 0xb4, 0xff, 0xb4, 0xe3, 0x24, 0xca, 0x07, 0xc3, 0xc8, + 0x71, 0x73, 0x09, 0xaf, 0x14, 0x10, 0x36, 0x2a, 0x77, 0x2c, 0x9a, 0xdd, 0x83, 0x8b, 0x2b, 0x0c, + 0xae, 0x1e, 0x90, 0xab, 0x44, 0x8a, 0xda, 0xbd, 0xac, 0xd2, 0xe5, 0xdf, 0x59, 0xc4, 0x18, 0x7a, + 0x32, 0xa2, 0x37, 0x19, 0xd6, 0xc5, 0x7e, 0x94, 0x00, 0x88, 0x53, 0x83, 0xbf, 0x8f, 0x06, 0x6f, + 0x23, 0xb9, 0x41, 0x92, 0x0d, 0x54, 0xc3, 0x5b, 0x4f, 0x7c, 0xc5, 0x04, 0x4f, 0x3b, 0x40, 0xf1, + 0x70, 0x46, 0x95, 0x63, 0x07, 0xb7, 0x48, 0xe8, 0x40, 0x73, 0x28, 0x44, 0xd0, 0x0a, 0x9c, 0xe6, + 0xec, 0x57, 0x14, 0x29, 0x3b, 0x62, 0x65, 0x14, 0x7f, 0x15, 0xc6, 0x7f, 0x4b, 0xe3, 0x8b, 0x08, + 0x2b, 0x55, 0xfd, 0xea, 0xdb, 0x61, 0x24, 0x68, 0x9f, 0xb7, 0x6f, 0x9d, 0x25, 0xcc, 0x28, 0xb8, + 0xea, 0xa9, 0x8b, 0x56, 0x2d, 0x5c, 0x10, 0x11, 0xe0, 0xdc, 0xf9, 0xb3, 0x99, 0x23, 0x24, 0x0d, + 0x33, 0x2d, 0x89, 0xdc, 0x96, 0x03, 0xb7, 0xbd, 0xdd, 0x0c, 0x70, 0xb8, 0x3c, 0xaa, 0x29, 0x05, + 0x63, 0x1b, 0x1c, 0x83, 0xca, 0xbb, 0xae, 0x6c, 0x0c, 0x0c, 0x2e, 0xfe, 0x8f, 0x58, 0x13, 0x1e, + 0xd8, 0x35, 0x1b, 0xf9, 0x3e, 0x87, 0x5f, 0x6a, 0x73, 0xa9, 0x3c, 0xba, 0xd4, 0x70, 0x14, 0x1a, + 0x26, 0x87, 0xfb, 0xac, 0xf2, 0xd7, 0x1c, 0x8d, 0xde, 0xe9, 0x71, 0xad, 0x66, 0x07, 0x29, 0xad, +}; +static const uint8_t TEE_ATTR_DSA_SUBPRIME_224_VALUE01[] = { + 0xea, 0x34, 0x7e, 0x90, 0xbe, 0x7c, 0x28, 0x75, 0xd1, 0xfe, 0x1d, 0xb6, 0x22, 0xb4, + 0x76, 0x38, 0x37, 0xc5, 0xe2, 0x7a, 0x60, 0x37, 0x31, 0x03, 0x48, 0xc1, 0xaa, 0x11, +}; +static const uint8_t TEE_ATTR_DSA_BASE_2048_VALUE01[] = { + 0x20, 0x42, 0x09, 0x4c, 0xcb, 0xc8, 0xb8, 0x72, 0x3f, 0xc9, 0x28, 0xc1, 0x2f, 0xda, 0x67, 0x1b, + 0x83, 0x29, 0x5e, 0x99, 0xc7, 0x43, 0x57, 0x6f, 0x44, 0x50, 0x4b, 0xe1, 0x18, 0x63, 0x23, 0x31, + 0x9b, 0x50, 0x02, 0xd2, 0x4f, 0x17, 0x3d, 0xf9, 0x09, 0xea, 0x24, 0x1d, 0x6e, 0xa5, 0x28, 0x99, + 0x04, 0xee, 0x46, 0x36, 0x20, 0x4b, 0x2f, 0xbe, 0x94, 0xb0, 0x68, 0xfe, 0x09, 0x3f, 0x79, 0x62, + 0x57, 0x95, 0x49, 0x55, 0x1d, 0x3a, 0xf2, 0x19, 0xad, 0x8e, 0xd1, 0x99, 0x39, 0xef, 0xf8, 0x6b, + 0xce, 0xc8, 0x34, 0xde, 0x2f, 0x2f, 0x78, 0x59, 0x6e, 0x89, 0xe7, 0xcb, 0x52, 0xc5, 0x24, 0xe1, + 0x77, 0x09, 0x8a, 0x56, 0xc2, 0x32, 0xeb, 0x1f, 0x56, 0x3a, 0xa8, 0x4b, 0xc6, 0xb0, 0x26, 0xde, + 0xee, 0x6f, 0xf5, 0x1c, 0xb4, 0x41, 0xe0, 0x80, 0xf2, 0xda, 0xfa, 0xea, 0x1c, 0xed, 0x86, 0x42, + 0x7d, 0x1c, 0x34, 0x6b, 0xe5, 0x5c, 0x66, 0x80, 0x3d, 0x4b, 0x76, 0xd1, 0x33, 0xcd, 0x44, 0x5b, + 0x4c, 0x34, 0x82, 0xfa, 0x41, 0x50, 0x23, 0x46, 0x3c, 0x9b, 0xf3, 0x0f, 0x2f, 0x78, 0x42, 0x23, + 0xe2, 0x60, 0x57, 0xd3, 0xaa, 0x0d, 0x7f, 0xbb, 0x66, 0x06, 0x30, 0xc5, 0x2e, 0x49, 0xd4, 0xa0, + 0x32, 0x5c, 0x73, 0x89, 0xe0, 0x72, 0xaa, 0x34, 0x9f, 0x13, 0xc9, 0x66, 0xe1, 0x59, 0x75, 0x2f, + 0xbb, 0x71, 0xe9, 0x33, 0x68, 0x90, 0xf9, 0x32, 0x43, 0xfa, 0x6e, 0x72, 0xd2, 0x99, 0x36, 0x5e, + 0xe5, 0xb3, 0xfe, 0x26, 0x6e, 0xbf, 0x11, 0x10, 0x56, 0x8f, 0xee, 0x44, 0x25, 0xc8, 0x47, 0xb5, + 0x02, 0x10, 0xbd, 0x48, 0x4b, 0x97, 0x43, 0x1a, 0x42, 0x85, 0x6a, 0xdc, 0xa3, 0xe7, 0xd1, 0xa9, + 0xc9, 0xc6, 0x75, 0xc7, 0xe2, 0x66, 0x91, 0x83, 0x20, 0xdd, 0x5a, 0x78, 0xa4, 0x8c, 0x48, 0xa9, +}; +static const uint8_t TEE_ATTR_DSA_PRIVATE_VALUE_224_VALUE01[] = { + 0x7b, 0x48, 0x90, 0x21, 0x57, 0x8e, 0x79, 0xe7, 0xbd, 0x3e, 0xe7, 0xab, 0x45, 0x6f, + 0x65, 0x9f, 0x3d, 0xc0, 0x7c, 0x88, 0xf5, 0xc9, 0xa3, 0x9e, 0x4f, 0x8c, 0xee, 0x81, +}; +static const uint8_t TEE_ATTR_DSA_PUBLIC_VALUE_2048_VALUE01[] = { + 0x1a, 0xe1, 0x0c, 0x78, 0x6a, 0xd0, 0x90, 0x2c, 0x5c, 0x68, 0x5d, 0xae, 0x5c, 0x71, 0x21, 0x41, + 0x8a, 0x37, 0x7b, 0x88, 0x8b, 0x5f, 0x2f, 0x2b, 0xc7, 0x66, 0x23, 0x57, 0x0f, 0xd6, 0x2b, 0xcb, + 0x19, 0x0b, 0x47, 0x1a, 0xd5, 0x35, 0x9c, 0x5f, 0x06, 0x2f, 0x88, 0x19, 0x28, 0x9e, 0x95, 0x6d, + 0x8a, 0xa6, 0xf9, 0x0d, 0x1f, 0x8c, 0xf1, 0xee, 0x72, 0xd3, 0xa1, 0xbd, 0xfd, 0x56, 0xc4, 0x78, + 0xdc, 0x29, 0xa1, 0x9c, 0x45, 0x69, 0xb5, 0xa6, 0x0e, 0x3a, 0x8f, 0x34, 0xf6, 0x06, 0x56, 0xea, + 0xc5, 0xb2, 0x5d, 0xde, 0x55, 0x14, 0xa5, 0xc6, 0x7b, 0x67, 0x54, 0x23, 0x20, 0x4f, 0x6c, 0xca, + 0xf0, 0x99, 0x06, 0x17, 0xcc, 0x73, 0x55, 0xb9, 0xd3, 0xed, 0x86, 0x89, 0x78, 0xa2, 0x52, 0x02, + 0x0a, 0x76, 0x9e, 0xd5, 0x9a, 0x6e, 0xda, 0xa6, 0xef, 0xe3, 0x37, 0x7e, 0xef, 0x45, 0xf3, 0xf6, + 0xf3, 0xe6, 0x41, 0x79, 0xcc, 0x7d, 0xb8, 0xb1, 0x43, 0xfb, 0x83, 0x5c, 0x5d, 0x71, 0xbf, 0xcf, + 0xa1, 0xe2, 0xa9, 0x04, 0x9b, 0xcc, 0xf7, 0xfe, 0x9a, 0xb5, 0x75, 0x46, 0x22, 0x0f, 0xe3, 0xf4, + 0xb7, 0x52, 0x1c, 0x86, 0x17, 0x39, 0xd1, 0x38, 0x50, 0x7e, 0x81, 0xa4, 0x6a, 0x69, 0x93, 0x60, + 0x54, 0x41, 0xdc, 0xb9, 0x0d, 0x6e, 0xe4, 0xaf, 0xbc, 0x42, 0xca, 0xbe, 0x90, 0xa2, 0x54, 0x44, + 0x49, 0x68, 0x10, 0x9d, 0x7e, 0xdd, 0x96, 0x94, 0xa0, 0x23, 0x23, 0x9f, 0x1d, 0x56, 0x17, 0x5d, + 0xd1, 0xfa, 0xc1, 0x15, 0x91, 0x5e, 0x24, 0xfa, 0xb5, 0x63, 0xf4, 0xfc, 0x3f, 0x26, 0x9b, 0xed, + 0x2f, 0x30, 0x08, 0x32, 0xd1, 0x12, 0x59, 0x64, 0x85, 0xa7, 0x11, 0x41, 0x7a, 0xa7, 0x3b, 0xb4, + 0xac, 0x72, 0xa6, 0x51, 0xa1, 0xfa, 0x5b, 0xae, 0xd3, 0x63, 0x6c, 0x72, 0x0d, 0x39, 0x70, 0x08, +}; + +static const uint8_t TEE_ATTR_DSA_PRIME_3072_VALUE01[] = { + 0xc7, 0xb8, 0x6d, 0x70, 0x44, 0x21, 0x8e, 0x36, 0x74, 0x53, 0xd2, 0x10, 0xe7, 0x64, 0x33, 0xe4, 0xe2, 0x7a, 0x98, 0x3d, 0xb1, 0xc5, 0x60, 0xbb, + 0x97, 0x55, 0xa8, 0xfb, 0x7d, 0x81, 0x99, 0x12, 0xc5, 0x6c, 0xfe, 0x00, 0x2a, 0xb1, 0xff, 0x3f, 0x72, 0x16, 0x5b, 0x94, 0x3c, 0x0b, 0x28, 0xed, + 0x46, 0x03, 0x9a, 0x07, 0xde, 0x50, 0x7d, 0x7a, 0x29, 0xf7, 0x38, 0x60, 0x3d, 0xec, 0xd1, 0x27, 0x03, 0x80, 0xa4, 0x1f, 0x97, 0x1f, 0x25, 0x92, + 0x66, 0x1a, 0x64, 0xba, 0x2f, 0x35, 0x1d, 0x9a, 0x69, 0xe5, 0x1a, 0x88, 0x8a, 0x05, 0x15, 0x6b, 0x7f, 0xe1, 0x56, 0x3c, 0x4b, 0x77, 0xee, 0x93, + 0xa4, 0x49, 0x49, 0x13, 0x84, 0x38, 0xa2, 0xab, 0x8b, 0xdc, 0xfc, 0x49, 0xb4, 0xe7, 0x8d, 0x1c, 0xde, 0x76, 0x6e, 0x54, 0x98, 0x47, 0x60, 0x05, + 0x7d, 0x76, 0xcd, 0x74, 0x0c, 0x94, 0xa4, 0xdd, 0x25, 0xa4, 0x6a, 0xa7, 0x7b, 0x18, 0xe9, 0xd7, 0x07, 0xd6, 0x73, 0x84, 0x97, 0xd4, 0xea, 0xc3, + 0x64, 0xf4, 0x79, 0x2d, 0x97, 0x66, 0xa1, 0x6a, 0x0e, 0x23, 0x48, 0x07, 0xe9, 0x6b, 0x8c, 0x64, 0xd4, 0x04, 0xbb, 0xdb, 0x87, 0x6e, 0x39, 0xb5, + 0x79, 0x9e, 0xf5, 0x3f, 0xe6, 0xcb, 0x9b, 0xab, 0x62, 0xef, 0x19, 0xfd, 0xcc, 0x2b, 0xdd, 0x90, 0x5b, 0xed, 0xa1, 0x3b, 0x9e, 0xf7, 0xac, 0x35, + 0xf1, 0xf5, 0x57, 0xcb, 0x0d, 0xc4, 0x58, 0xc0, 0x19, 0xe2, 0xbc, 0x19, 0xa9, 0xf5, 0xdf, 0xc1, 0xe4, 0xec, 0xa9, 0xe6, 0xd4, 0x66, 0x56, 0x41, + 0x24, 0x30, 0x4a, 0x31, 0xf0, 0x38, 0x60, 0x5a, 0x3e, 0x34, 0x2d, 0xa0, 0x1b, 0xe1, 0xc2, 0xb5, 0x45, 0x61, 0x0e, 0xdd, 0x2c, 0x13, 0x97, 0xa3, + 0xc8, 0x39, 0x65, 0x88, 0xc6, 0x32, 0x9e, 0xfe, 0xb4, 0xe1, 0x65, 0xaf, 0x5b, 0x36, 0x8a, 0x39, 0xa8, 0x8e, 0x48, 0x88, 0xe3, 0x9f, 0x40, 0xbb, + 0x3d, 0xe4, 0xeb, 0x14, 0x16, 0x67, 0x2f, 0x99, 0x9f, 0xea, 0xd3, 0x7a, 0xef, 0x1c, 0xa9, 0x64, 0x3f, 0xf3, 0x2c, 0xdb, 0xc0, 0xfc, 0xeb, 0xe6, + 0x28, 0xd7, 0xe4, 0x6d, 0x28, 0x1a, 0x98, 0x9d, 0x43, 0xdd, 0x21, 0x43, 0x21, 0x51, 0xaf, 0x68, 0xbe, 0x3f, 0x6d, 0x56, 0xac, 0xfb, 0xdb, 0x6c, + 0x97, 0xd8, 0x7f, 0xcb, 0x5e, 0x62, 0x91, 0xbf, 0x8b, 0x4e, 0xe1, 0x27, 0x5a, 0xe0, 0xeb, 0x43, 0x83, 0xcc, 0x75, 0x39, 0x03, 0xc8, 0xd2, 0x9f, + 0x4a, 0xdb, 0x6a, 0x54, 0x7e, 0x40, 0x5d, 0xec, 0xdf, 0xf2, 0x88, 0xc5, 0xf6, 0xc7, 0xaa, 0x30, 0xdc, 0xb1, 0x2f, 0x84, 0xd3, 0x92, 0x49, 0x3a, + 0x70, 0x93, 0x33, 0x17, 0xc0, 0xf5, 0xe6, 0x55, 0x26, 0x01, 0xfa, 0xe1, 0x8f, 0x17, 0xe6, 0xe5, 0xbb, 0x6b, 0xf3, 0x96, 0xd3, 0x2d, 0x8a, 0xb9, +}; +static const uint8_t TEE_ATTR_DSA_SUBPRIME_256_VALUE01[] = { + 0x87, 0x6f, 0xa0, 0x9e, 0x1d, 0xc6, 0x2b, 0x23, 0x6c, 0xe1, 0xc3, 0x15, 0x5b, 0xa4, 0x8b, 0x0c, + 0xcf, 0xda, 0x29, 0xf3, 0xac, 0x5a, 0x97, 0xf7, 0xff, 0xa1, 0xbd, 0x87, 0xb6, 0x8d, 0x2a, 0x4b, +}; +static const uint8_t TEE_ATTR_DSA_BASE_3072_VALUE01[] = { + 0x11, 0x0a, 0xfe, 0xbb, 0x12, 0xc7, 0xf8, 0x62, 0xb6, 0xde, 0x03, 0xd4, 0x7f, 0xdb, 0xc3, 0x32, 0x6e, 0x0d, 0x4d, 0x31, 0xb1, 0x2a, 0x8c, 0xa9, + 0x5b, 0x2d, 0xee, 0x21, 0x23, 0xbc, 0xc6, 0x67, 0xd4, 0xf7, 0x2c, 0x1e, 0x72, 0x09, 0x76, 0x7d, 0x27, 0x21, 0xf9, 0x5f, 0xbd, 0x9a, 0x4d, 0x03, + 0x23, 0x6d, 0x54, 0x17, 0x4f, 0xbf, 0xaf, 0xf2, 0xc4, 0xff, 0x7d, 0xea, 0xe4, 0x73, 0x8b, 0x20, 0xd9, 0xf3, 0x7b, 0xf0, 0xa1, 0x13, 0x4c, 0x28, + 0x8b, 0x42, 0x0a, 0xf0, 0xb5, 0x79, 0x2e, 0x47, 0xa9, 0x25, 0x13, 0xc0, 0x41, 0x3f, 0x34, 0x6a, 0x4e, 0xdb, 0xab, 0x2c, 0x45, 0xbd, 0xca, 0x13, + 0xf5, 0x34, 0x1c, 0x2b, 0x55, 0xb8, 0xba, 0x54, 0x93, 0x2b, 0x92, 0x17, 0xb5, 0xa8, 0x59, 0xe5, 0x53, 0xf1, 0x4b, 0xb8, 0xc1, 0x20, 0xfb, 0xb9, + 0xd9, 0x99, 0x09, 0xdf, 0xf5, 0xea, 0x68, 0xe1, 0x4b, 0x37, 0x99, 0x64, 0xfd, 0x3f, 0x38, 0x61, 0xe5, 0xba, 0x5c, 0xc9, 0x70, 0xc4, 0xa1, 0x80, + 0xee, 0xf5, 0x44, 0x28, 0x70, 0x39, 0x61, 0x02, 0x1e, 0x7b, 0xd6, 0x8c, 0xb6, 0x37, 0x92, 0x7b, 0x8c, 0xbe, 0xe6, 0x80, 0x5f, 0xa2, 0x72, 0x85, + 0xbf, 0xee, 0x4d, 0x1e, 0xf7, 0x0e, 0x02, 0xc1, 0xa1, 0x8a, 0x7c, 0xd7, 0x8b, 0xef, 0x1d, 0xd9, 0xcd, 0xad, 0x45, 0xdd, 0xe9, 0xcd, 0x69, 0x07, + 0x55, 0x05, 0x0f, 0xc4, 0x66, 0x29, 0x37, 0xee, 0x1d, 0x6f, 0x4d, 0xb1, 0x28, 0x07, 0xcc, 0xc9, 0x5b, 0xc4, 0x35, 0xf1, 0x1b, 0x71, 0xe7, 0x08, + 0x60, 0x48, 0xb1, 0xda, 0xb5, 0x91, 0x3c, 0x60, 0x55, 0x01, 0x2d, 0xe8, 0x2e, 0x43, 0xa4, 0xe5, 0x0c, 0xf9, 0x3f, 0xef, 0xf5, 0xdc, 0xab, 0x81, + 0x4a, 0xbc, 0x22, 0x4c, 0x5e, 0x00, 0x25, 0xbd, 0x86, 0x8c, 0x3f, 0xc5, 0x92, 0x04, 0x1b, 0xba, 0x04, 0x74, 0x7c, 0x10, 0xaf, 0x51, 0x3f, 0xc3, + 0x6e, 0x4d, 0x91, 0xc6, 0x3e, 0xe5, 0x25, 0x34, 0x22, 0xcf, 0x40, 0x63, 0x39, 0x8d, 0x77, 0xc5, 0x2f, 0xcb, 0x01, 0x14, 0x27, 0xcb, 0xfc, 0xfa, + 0x67, 0xb1, 0xb2, 0xc2, 0xd1, 0xaa, 0x4a, 0x3d, 0xa7, 0x26, 0x45, 0xcb, 0x1c, 0x76, 0x70, 0x36, 0x05, 0x4e, 0x2f, 0x31, 0xf8, 0x86, 0x65, 0xa5, + 0x44, 0x61, 0xc8, 0x85, 0xfb, 0x32, 0x19, 0xd5, 0xad, 0x87, 0x48, 0xa0, 0x11, 0x58, 0xf6, 0xc7, 0xc0, 0xdf, 0x5a, 0x8c, 0x90, 0x8b, 0xa8, 0xc3, + 0xe5, 0x36, 0x82, 0x24, 0x28, 0x88, 0x6c, 0x7b, 0x50, 0x0b, 0xbc, 0x15, 0xb4, 0x9d, 0xf7, 0x46, 0xb9, 0xde, 0x5a, 0x78, 0xfe, 0x3b, 0x4f, 0x69, + 0x91, 0xd0, 0x11, 0x0c, 0x3c, 0xbf, 0xf4, 0x58, 0x03, 0x9d, 0xc3, 0x62, 0x61, 0xcf, 0x46, 0xaf, 0x4b, 0xc2, 0x51, 0x53, 0x68, 0xf4, 0xab, 0xb7, +}; +static const uint8_t TEE_ATTR_DSA_PRIVATE_VALUE_256_VALUE01[] = { + 0x34, 0x70, 0x83, 0x20, 0x55, 0xda, 0xde, 0x94, 0xe1, 0x4c, 0xd8, 0x77, 0x71, 0x71, 0xd1, 0x8e, + 0x5d, 0x06, 0xf6, 0x6a, 0xef, 0xf4, 0xc6, 0x14, 0x71, 0xe4, 0xeb, 0xa7, 0x4e, 0xe5, 0x61, 0x64, +}; +static const uint8_t TEE_ATTR_DSA_PUBLIC_VALUE_3072_VALUE01[] = { + 0x45, 0x6a, 0x10, 0x5c, 0x71, 0x35, 0x66, 0x23, 0x48, 0x38, 0xbc, 0x07, 0x0b, 0x8a, 0x75, 0x1a, 0x0b, 0x57, 0x76, 0x7c, 0xb7, 0x5e, 0x99, 0x11, + 0x4a, 0x1a, 0x46, 0x64, 0x1e, 0x11, 0xda, 0x1f, 0xa9, 0xf2, 0x29, 0x14, 0xd8, 0x08, 0xad, 0x71, 0x48, 0x61, 0x2c, 0x1e, 0xa5, 0x5d, 0x25, 0x30, + 0x17, 0x81, 0xe9, 0xae, 0x0c, 0x9a, 0xe3, 0x6a, 0x69, 0xd8, 0x7b, 0xa0, 0x39, 0xec, 0x7c, 0xd8, 0x64, 0xc3, 0xad, 0x09, 0x48, 0x73, 0xe6, 0xe5, + 0x67, 0x09, 0xfd, 0x10, 0xd9, 0x66, 0x85, 0x3d, 0x61, 0x1b, 0x1c, 0xff, 0x15, 0xd3, 0x7f, 0xde, 0xe4, 0x24, 0x50, 0x6c, 0x18, 0x4d, 0x62, 0xc7, + 0x03, 0x33, 0x58, 0xbe, 0x78, 0xc2, 0x25, 0x09, 0x43, 0xb6, 0xf6, 0xd0, 0x43, 0xd6, 0x3b, 0x31, 0x7d, 0xe5, 0x6e, 0x5a, 0xd8, 0xd1, 0xfd, 0x97, + 0xdd, 0x35, 0x5a, 0xbe, 0x96, 0x45, 0x2f, 0x8e, 0x43, 0x54, 0x85, 0xfb, 0x3b, 0x90, 0x7b, 0x51, 0x90, 0x0a, 0xa3, 0xf2, 0x44, 0x18, 0xdf, 0x50, + 0xb4, 0xfc, 0xda, 0xfb, 0xf6, 0x13, 0x75, 0x48, 0xc3, 0x93, 0x73, 0xb8, 0xbc, 0x4b, 0xa3, 0xda, 0xbb, 0x47, 0x46, 0xeb, 0xd1, 0x7b, 0x87, 0xfc, + 0xd6, 0xa2, 0xf1, 0x97, 0xc1, 0x07, 0xb1, 0x8e, 0xc5, 0xb4, 0x65, 0xe6, 0xe4, 0xcb, 0x43, 0x0d, 0x9c, 0x0c, 0xe7, 0x8d, 0xa5, 0x98, 0x84, 0x41, + 0x05, 0x4a, 0x37, 0x07, 0x92, 0xb7, 0x30, 0xda, 0x9a, 0xba, 0x41, 0xa3, 0x16, 0x9a, 0xf2, 0x61, 0x76, 0xf7, 0x4e, 0x6f, 0x7c, 0x0c, 0x9c, 0x9b, + 0x55, 0xb6, 0x2b, 0xbe, 0x7c, 0xe3, 0x8d, 0x46, 0x95, 0xd4, 0x81, 0x57, 0xe6, 0x60, 0xc2, 0xac, 0xb6, 0x3f, 0x48, 0x2f, 0x55, 0x41, 0x81, 0x50, + 0xe5, 0xfe, 0xe4, 0x3a, 0xce, 0x84, 0xc5, 0x40, 0xc3, 0xba, 0x76, 0x62, 0xae, 0x80, 0x83, 0x5c, 0x1a, 0x2d, 0x51, 0x89, 0x0e, 0xa9, 0x6b, 0xa2, + 0x06, 0x42, 0x7c, 0x41, 0xef, 0x8c, 0x38, 0xaa, 0x07, 0xd2, 0xa3, 0x65, 0xe7, 0xe5, 0x83, 0x80, 0xd8, 0xf4, 0x78, 0x2e, 0x22, 0xac, 0x21, 0x01, + 0xaf, 0x73, 0x2e, 0xe2, 0x27, 0x58, 0x33, 0x7b, 0x25, 0x36, 0x37, 0x83, 0x8e, 0x16, 0xf5, 0x0f, 0x56, 0xd3, 0x13, 0xd0, 0x79, 0x81, 0x88, 0x0d, + 0x68, 0x55, 0x57, 0xf7, 0xd7, 0x9a, 0x6d, 0xb8, 0x23, 0xc6, 0x1f, 0x1b, 0xb3, 0xdb, 0xc5, 0xd5, 0x04, 0x21, 0xa4, 0x84, 0x3a, 0x6f, 0x29, 0x69, + 0x0e, 0x78, 0xaa, 0x0f, 0x0c, 0xff, 0x30, 0x42, 0x31, 0x81, 0x8b, 0x81, 0xfc, 0x4a, 0x24, 0x3f, 0xc0, 0x0f, 0x09, 0xa5, 0x4c, 0x46, 0x6d, 0x6a, + 0x8c, 0x73, 0xd3, 0x2a, 0x55, 0xe1, 0xab, 0xd5, 0xec, 0x8b, 0x4e, 0x1a, 0xfa, 0x32, 0xa7, 0x9b, 0x01, 0xdf, 0x85, 0xa8, 0x1f, 0x3f, 0x5c, 0xfe, +}; + +static const uint8_t TEE_ATTR_DES3_192_VALUE01[] = { + 0xCD, 0xFE, 0x57, 0xB6, 0xB6, 0x2F, 0xAE, 0x6B, 0x04, 0x73, 0x40, 0xF1, + 0x02, 0xD6, 0xA4, 0x8C, + 0x89, 0x5D, 0xAD, 0xF2, 0x9D, 0x62, 0xEF, 0x25 +}; +static const uint8_t TEE_ATTR_RSA_PRIVATE_EXPONENT_VALUE01[] = { + 0xa5, 0x0d, 0xe1, 0x84, 0xf9, 0x02, 0xec, 0x42, 0x20, 0x2c, 0x98, 0x98, + 0x70, 0xa3, 0x1a, 0x04, + 0x21, 0xa7, 0xa0, 0x59, 0x5d, 0x87, 0x80, 0x9b, 0x09, 0x57, 0x91, 0xb4, + 0x50, 0x51, 0x62, 0xbf, + 0x22, 0xd7, 0xdb, 0x17, 0x25, 0xb0, 0x9c, 0x91, 0x29, 0x5f, 0x10, 0x9c, + 0xac, 0x44, 0x48, 0xb2, + 0x43, 0x8d, 0x6b, 0x36, 0x84, 0xa7, 0xdf, 0xb8, 0x1b, 0x9f, 0x73, 0xac, + 0x2c, 0x53, 0xa5, 0x39, + 0xd9, 0xa2, 0xe2, 0x7e, 0xf2, 0x07, 0x2d, 0x80, 0xa4, 0x7b, 0x7b, 0x66, + 0x1a, 0x2f, 0xb7, 0x66, + 0x64, 0x66, 0xa8, 0xc3, 0x8d, 0x7e, 0x8a, 0x7f, 0xc6, 0xd7, 0x52, 0xe7, + 0x38, 0x30, 0x59, 0x74, + 0x88, 0x8e, 0x8a, 0x52, 0x79, 0x30, 0x77, 0xc9, 0xe5, 0x7a, 0x3e, 0x65, + 0x5d, 0x89, 0xa9, 0xb7, + 0x0b, 0xc6, 0x62, 0x72, 0x9e, 0xa4, 0x72, 0xae, 0x4b, 0xb3, 0xf2, 0x89, + 0x47, 0x15, 0xe0, 0x5b, + 0x45, 0x4d, 0x99, 0x5b, 0x13, 0x6c, 0x90, 0xbe, 0xe5, 0xb5, 0x98, 0xad, + 0x87, 0x99, 0x1a, 0x57, + 0xd4, 0x1f, 0xf1, 0x52, 0x71, 0x5b, 0x51, 0x40, 0xdc, 0x51, 0x35, 0xf6, + 0x6c, 0xae, 0xa3, 0xf9, + 0x0f, 0x3a, 0xed, 0x28, 0xfc, 0xa5, 0x60, 0x2f, 0x4b, 0x4f, 0x31, 0xac, + 0x48, 0x3e, 0x5b, 0xba, + 0xe4, 0x2b, 0x58, 0x79, 0xe6, 0xb4, 0x6b, 0x5e, 0x56, 0x0a, 0xb2, 0xdb, + 0x68, 0xed, 0x24, 0xd8, + 0x5e, 0x6f, 0x30, 0x59, 0x8d, 0x8c, 0xa3, 0x00, 0x68, 0xf5, 0x42, 0x95, + 0x1a, 0x0b, 0xa8, 0x1c, + 0xfb, 0xdf, 0x29, 0x81, 0x10, 0x32, 0x02, 0xcc, 0x51, 0xa4, 0x17, 0x14, + 0x3e, 0xef, 0x89, 0x41, + 0xde, 0xf8, 0x2d, 0x64, 0x69, 0x30, 0xe8, 0x8a, 0xad, 0x96, 0xf6, 0xf4, + 0x82, 0x83, 0x9a, 0x77, + 0xe7, 0xde, 0x12, 0x31, 0xf7, 0x15, 0xec, 0xce, 0xed, 0x83, 0x68, 0x88, + 0x84, 0xe5, 0x64, 0x81 +}; +static const uint8_t TEE_ATTR_DES_64_VALUE01[] = { + 0xCD, 0xFE, 0x57, 0xB6, 0xB6, 0x2F, 0xAE, 0x6B +}; +static const uint8_t TEE_ATTR_HMAC_SHA1_256_VALUE01[] = { + 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 +}; +static const uint8_t TEE_ATTR_HMAC_MD5_256_VALUE01[] = { + 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 +}; +static const uint8_t TEE_ATTR_HMAC_SHA224_256_VALUE01[] = { + 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 +}; +static const uint8_t TEE_ATTR_HMAC_SHA384_512_VALUE01[] = { + 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 +}; +static const uint8_t TEE_ATTR_HMAC_SHA512_512_VALUE01[] = { + 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 +}; + +#undef TEE_ECC_CURVE_NIST_P192 +static const uint8_t TEE_ECC_CURVE_NIST_P192[] = { 0x00, 0x00, 0x00, 0x01 }; +#undef TEE_ECC_CURVE_NIST_P224 +static const uint8_t TEE_ECC_CURVE_NIST_P224[] = { 0x00, 0x00, 0x00, 0x02 }; +#undef TEE_ECC_CURVE_NIST_P256 +static const uint8_t TEE_ECC_CURVE_NIST_P256[] = { 0x00, 0x00, 0x00, 0x03 }; +#undef TEE_ECC_CURVE_NIST_P384 +static const uint8_t TEE_ECC_CURVE_NIST_P384[] = { 0x00, 0x00, 0x00, 0x04 }; +#undef TEE_ECC_CURVE_NIST_P521 +static const uint8_t TEE_ECC_CURVE_NIST_P521[] = { 0x00, 0x00, 0x00, 0x05 }; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P192_VALUE01[] = { + 0xe1, 0x4f, 0x37, 0xb3, 0xd1, 0x37, 0x4f, 0xf8, 0xb0, 0x3f, 0x41, 0xb9, 0xb3, 0xfd, 0xd2, 0xf0, 0xeb, 0xcc, 0xf2, 0x75, 0xd6, 0x60, 0xd7, 0xf3, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P192_VALUE01[] = { + 0x07, 0x00, 0x8e, 0xa4, 0x0b, 0x08, 0xdb, 0xe7, 0x64, 0x32, 0x09, 0x6e, 0x80, 0xa2, 0x49, 0x4c, 0x94, 0x98, 0x2d, 0x2d, 0x5b, 0xcf, 0x98, 0xe6, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P192_VALUE01[] = { + 0x76, 0xfa, 0xb6, 0x81, 0xd0, 0x0b, 0x41, 0x4e, 0xa6, 0x36, 0xba, 0x21, 0x5d, 0xe2, 0x6d, 0x98, 0xc4, 0x1b, 0xd7, 0xf2, 0xe4, 0xd6, 0x54, 0x77, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P224_VALUE01[] = { + 0x97, 0xc4, 0xb7, 0x96, 0xe1, 0x63, 0x9d, 0xd1, 0x03, 0x5b, 0x70, 0x8f, 0xc0, 0x0d, 0xc7, 0xba, 0x16, 0x82, 0xce, 0xc4, 0x4a, 0x10, 0x02, 0xa1, 0xa8, 0x20, 0x61, 0x9f, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P224_VALUE01[] = { + 0x8a, 0x4d, 0xca, 0x35, 0x13, 0x6c, 0x4b, 0x70, 0xe5, 0x88, 0xe2, 0x35, 0x54, 0x63, 0x7a, 0xe2, 0x51, 0x07, 0x7d, 0x13, 0x65, 0xa6, 0xba, 0x5d, 0xb9, 0x58, 0x5d, 0xe7, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P224_VALUE01[] = { + 0xad, 0x3d, 0xee, 0x06, 0xde, 0x0b, 0xe8, 0x27, 0x9d, 0x4a, 0xf4, 0x35, 0xd7, 0x24, 0x5f, 0x14, 0xf3, 0xb4, 0xf8, 0x2e, 0xb5, 0x78, 0xe5, 0x19, 0xee, 0x00, 0x57, 0xb1, +}; +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P256_VALUE01[] = { + 0xbe, 0x34, 0xba, 0xa8, 0xd0, 0x40, 0xa3, 0xb9, 0x91, 0xf9, 0x07, 0x5b, 0x56, 0xba, 0x29, 0x2f, + 0x75, 0x5b, 0x90, 0xe4, 0xb6, 0xdc, 0x10, 0xda, 0xd3, 0x67, 0x15, 0xc3, 0x3c, 0xfd, 0xac, 0x25, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P256_VALUE01[] = { + 0xfa, 0x27, 0x37, 0xfb, 0x93, 0x48, 0x8d, 0x19, 0xca, 0xef, 0x11, 0xae, 0x7f, 0xaf, 0x6b, 0x7f, + 0x4b, 0xcd, 0x67, 0xb2, 0x86, 0xe3, 0xfc, 0x54, 0xe8, 0xa6, 0x5c, 0x2b, 0x74, 0xae, 0xcc, 0xb0, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P256_VALUE01[] = { + 0xd4, 0xcc, 0xd6, 0xda, 0xe6, 0x98, 0x20, 0x8a, 0xa8, 0xc3, 0xa6, 0xf3, 0x9e, 0x45, 0x51, 0x0d, + 0x03, 0xbe, 0x09, 0xb2, 0xf1, 0x24, 0xbf, 0xc0, 0x67, 0x85, 0x6c, 0x32, 0x4f, 0x9b, 0x4d, 0x09, +}; +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P384_VALUE01[] = { + 0xa4, 0x92, 0xce, 0x8f, 0xa9, 0x00, 0x84, 0xc2, 0x27, 0xe1, 0xa3, 0x2f, 0x79, 0x74, 0xd3, 0x9e, 0x9f, 0xf6, 0x7a, 0x7e, 0x87, 0x05, 0xec, 0x34, + 0x19, 0xb3, 0x5f, 0xb6, 0x07, 0x58, 0x2b, 0xeb, 0xd4, 0x61, 0xe0, 0xb1, 0x52, 0x0a, 0xc7, 0x6e, 0xc2, 0xdd, 0x4e, 0x9b, 0x63, 0xeb, 0xae, 0x71, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P384_VALUE01[] = { + 0xe5, 0x5f, 0xee, 0x6c, 0x49, 0xd8, 0xd5, 0x23, 0xf5, 0xce, 0x7b, 0xf9, 0xc0, 0x42, 0x5c, 0xe4, 0xff, 0x65, 0x07, 0x08, 0xb7, 0xde, 0x5c, 0xfb, + 0x09, 0x59, 0x01, 0x52, 0x39, 0x79, 0xa7, 0xf0, 0x42, 0x60, 0x2d, 0xb3, 0x08, 0x54, 0x73, 0x53, 0x69, 0x81, 0x3b, 0x5c, 0x3f, 0x5e, 0xf8, 0x68, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P384_VALUE01[] = { + 0x28, 0xf5, 0x9c, 0xc5, 0xdc, 0x50, 0x98, 0x92, 0xa9, 0x88, 0xd3, 0x8a, 0x8e, 0x25, 0x19, 0xde, 0x3d, 0x0c, 0x4f, 0xd0, 0xfb, 0xdb, 0x09, 0x93, + 0xe3, 0x8f, 0x18, 0x50, 0x6c, 0x17, 0x60, 0x6c, 0x5e, 0x24, 0x24, 0x92, 0x46, 0xf1, 0xce, 0x94, 0x98, 0x3a, 0x53, 0x61, 0xc5, 0xbe, 0x98, 0x3e, +}; +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P521_VALUE01[] = { + 0x01, 0xbd, 0x56, 0xbd, 0x10, 0x61, 0x18, 0xed, 0xa2, 0x46, 0x15, 0x5b, 0xd4, 0x3b, 0x42, 0xb8, 0xe1, + 0x3f, 0x0a, 0x6e, 0x25, 0xdd, 0x3b, 0xb3, 0x76, 0x02, 0x6f, 0xab, 0x4d, 0xc9, 0x2b, 0x61, 0x57, 0xbc, + 0x6d, 0xfe, 0xc2, 0xd1, 0x5d, 0xd3, 0xd0, 0xcf, 0x2a, 0x39, 0xaa, 0x68, 0x49, 0x40, 0x42, 0xaf, 0x48, + 0xba, 0x96, 0x01, 0x11, 0x8d, 0xa8, 0x2c, 0x6f, 0x21, 0x08, 0xa3, 0xa2, 0x03, 0xad, 0x74, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P521_VALUE01[] = { + 0x01, 0x2f, 0xbc, 0xae, 0xff, 0xa6, 0xa5, 0x1f, 0x3e, 0xe4, 0xd3, 0xd2, 0xb5, 0x1c, 0x5d, 0xec, 0x6d, + 0x7c, 0x72, 0x6c, 0xa3, 0x53, 0xfc, 0x01, 0x4e, 0xa2, 0xbf, 0x7c, 0xfb, 0xb9, 0xb9, 0x10, 0xd3, 0x2c, + 0xbf, 0xa6, 0xa0, 0x0f, 0xe3, 0x9b, 0x6c, 0xdb, 0x89, 0x46, 0xf2, 0x27, 0x75, 0x39, 0x8b, 0x2e, 0x23, + 0x3c, 0x0c, 0xf1, 0x44, 0xd7, 0x8c, 0x8a, 0x77, 0x42, 0xb5, 0xc7, 0xa3, 0xbb, 0x5d, 0x23, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P521_VALUE01[] = { + 0x00, 0x9c, 0xde, 0xf8, 0x23, 0xdd, 0x7b, 0xf9, 0xa7, 0x9e, 0x8c, 0xce, 0xac, 0xd2, 0xe4, 0x52, 0x7c, + 0x23, 0x1d, 0x0a, 0xe5, 0x96, 0x7a, 0xf0, 0x95, 0x8e, 0x93, 0x1d, 0x7d, 0xdc, 0xcf, 0x28, 0x05, 0xa3, + 0xe6, 0x18, 0xdc, 0x30, 0x39, 0xfe, 0xc9, 0xfe, 0xbb, 0xd3, 0x30, 0x52, 0xfe, 0x4c, 0x0f, 0xee, 0x98, + 0xf0, 0x33, 0x10, 0x60, 0x64, 0x98, 0x2d, 0x88, 0xf4, 0xe0, 0x35, 0x49, 0xd4, 0xa6, 0x4d, +}; +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P192_VALUE01[] = { + 0xf1, 0x7d, 0x3f, 0xea, 0x36, 0x7b, 0x74, 0xd3, 0x40, 0x85, 0x1c, 0xa4, 0x27, 0x0d, 0xcb, 0x24, 0xc2, 0x71, 0xf4, 0x45, 0xbe, 0xd9, 0xd5, 0x27, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P192_VALUE01[] = { + 0xb1, 0x50, 0x53, 0x40, 0x1f, 0x57, 0x28, 0x56, 0x37, 0xec, 0x32, 0x4c, 0x1c, 0xd2, 0x13, 0x9e, 0x3a, 0x67, 0xde, 0x37, 0x39, 0x23, 0x4b, 0x37, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P192_VALUE01[] = { + 0xf2, 0x69, 0xc1, 0x58, 0x63, 0x74, 0x82, 0xaa, 0xd6, 0x44, 0xcd, 0x69, 0x2d, 0xd1, 0xd3, 0xef, 0x2c, 0x8a, 0x7c, 0x49, 0xe3, 0x89, 0xf7, 0xf6, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P192_VALUE02[] = { + 0xdf, 0xbe, 0x5d, 0x7c, 0x61, 0xfa, 0xc8, 0x8b, 0x11, 0x81, 0x1b, 0xde, 0x32, 0x8e, 0x8a, 0x0d, 0x12, 0xbf, 0x01, 0xa9, 0xd2, 0x04, 0xb5, 0x23, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P192_VALUE02[] = { + 0x42, 0xea, 0x6d, 0xd9, 0x96, 0x9d, 0xd2, 0xa6, 0x1f, 0xea, 0x1a, 0xac, 0x7f, 0x8e, 0x98, 0xed, 0xcc, 0x89, 0x6c, 0x6e, 0x55, 0x85, 0x7c, 0xc0, +}; +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P224_VALUE01[] = { + 0x83, 0x46, 0xa6, 0x0f, 0xc6, 0xf2, 0x93, 0xca, 0x5a, 0x0d, 0x2a, 0xf6, 0x8b, 0xa7, 0x1d, 0x1d, 0xd3, 0x89, 0xe5, 0xe4, 0x08, 0x37, 0x94, 0x2d, 0xf3, 0xe4, 0x3c, 0xbd, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P224_VALUE01[] = { + 0x8d, 0xe2, 0xe2, 0x6a, 0xdf, 0x72, 0xc5, 0x82, 0xd6, 0x56, 0x8e, 0xf6, 0x38, 0xc4, 0xfd, 0x59, 0xb1, 0x8d, 0xa1, 0x71, 0xbd, 0xf5, 0x01, 0xf1, 0xd9, 0x29, 0xe0, 0x48, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P224_VALUE01[] = { + 0x4a, 0x68, 0xa1, 0xc2, 0xb0, 0xfb, 0x22, 0x93, 0x0d, 0x12, 0x05, 0x55, 0xc1, 0xec, 0xe5, 0x0e, 0xa9, 0x8d, 0xea, 0x84, 0x07, 0xf7, 0x1b, 0xe3, 0x6e, 0xfa, 0xc0, 0xde, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P224_VALUE02[] = { + 0x88, 0x20, 0x92, 0xcc, 0xbb, 0xa7, 0x93, 0x0f, 0x41, 0x9a, 0x8a, 0x4f, 0x9b, 0xb1, 0x69, 0x78, 0xbb, 0xc3, 0x83, 0x87, 0x29, 0x99, 0x25, 0x59, 0xa6, 0xf2, 0xe2, 0xd7, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P224_VALUE02[] = { + 0xaf, 0x33, 0xcd, 0x06, 0x29, 0xbc, 0x7e, 0x99, 0x63, 0x20, 0xa3, 0xf4, 0x03, 0x68, 0xf7, 0x4d, 0xe8, 0x70, 0x4f, 0xa3, 0x7b, 0x8f, 0xab, 0x69, 0xab, 0xaa, 0xe2, 0x80, +}; +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P256_VALUE01[] = { + 0x7d, 0x7d, 0xc5, 0xf7, 0x1e, 0xb2, 0x9d, 0xda, 0xf8, 0x0d, 0x62, 0x14, 0x63, 0x2e, 0xea, 0xe0, + 0x3d, 0x90, 0x58, 0xaf, 0x1f, 0xb6, 0xd2, 0x2e, 0xd8, 0x0b, 0xad, 0xb6, 0x2b, 0xc1, 0xa5, 0x34, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P256_VALUE01[] = { + 0xea, 0xd2, 0x18, 0x59, 0x01, 0x19, 0xe8, 0x87, 0x6b, 0x29, 0x14, 0x6f, 0xf8, 0x9c, 0xa6, 0x17, + 0x70, 0xc4, 0xed, 0xbb, 0xf9, 0x7d, 0x38, 0xce, 0x38, 0x5e, 0xd2, 0x81, 0xd8, 0xa6, 0xb2, 0x30, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P256_VALUE01[] = { + 0x28, 0xaf, 0x61, 0x28, 0x1f, 0xd3, 0x5e, 0x2f, 0xa7, 0x00, 0x25, 0x23, 0xac, 0xc8, 0x5a, 0x42, + 0x9c, 0xb0, 0x6e, 0xe6, 0x64, 0x83, 0x25, 0x38, 0x9f, 0x59, 0xed, 0xfc, 0xe1, 0x40, 0x51, 0x41, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P256_VALUE02[] = { + 0xdb, 0x71, 0xe5, 0x09, 0xe3, 0xfd, 0x9b, 0x06, 0x0d, 0xdb, 0x20, 0xba, 0x5c, 0x51, 0xdc, 0xc5, + 0x94, 0x8d, 0x46, 0xfb, 0xf6, 0x40, 0xdf, 0xe0, 0x44, 0x17, 0x82, 0xca, 0xb8, 0x5f, 0xa4, 0xac, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P256_VALUE02[] = { + 0x70, 0x0c, 0x48, 0xf7, 0x7f, 0x56, 0x58, 0x4c, 0x5c, 0xc6, 0x32, 0xca, 0x65, 0x64, 0x0d, 0xb9, + 0x1b, 0x6b, 0xac, 0xce, 0x3a, 0x4d, 0xf6, 0xb4, 0x2c, 0xe7, 0xcc, 0x83, 0x88, 0x33, 0xd2, 0x87, +}; +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P384_VALUE01[] = { + 0x3c, 0xc3, 0x12, 0x2a, 0x68, 0xf0, 0xd9, 0x50, 0x27, 0xad, 0x38, 0xc0, 0x67, 0x91, 0x6b, 0xa0, 0xeb, 0x8c, 0x38, 0x89, 0x4d, 0x22, 0xe1, 0xb1, + 0x56, 0x18, 0xb6, 0x81, 0x8a, 0x66, 0x17, 0x74, 0xad, 0x46, 0x3b, 0x20, 0x5d, 0xa8, 0x8c, 0xf6, 0x99, 0xab, 0x4d, 0x43, 0xc9, 0xcf, 0x98, 0xa1, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P384_VALUE01[] = { + 0x98, 0x03, 0x80, 0x7f, 0x2f, 0x6d, 0x2f, 0xd9, 0x66, 0xcd, 0xd0, 0x29, 0x0b, 0xd4, 0x10, 0xc0, 0x19, 0x03, 0x52, 0xfb, 0xec, 0x7f, 0xf6, 0x24, + 0x7d, 0xe1, 0x30, 0x2d, 0xf8, 0x6f, 0x25, 0xd3, 0x4f, 0xe4, 0xa9, 0x7b, 0xef, 0x60, 0xcf, 0xf5, 0x48, 0x35, 0x5c, 0x01, 0x5d, 0xbb, 0x3e, 0x5f, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P384_VALUE01[] = { + 0xba, 0x26, 0xca, 0x69, 0xec, 0x2f, 0x5b, 0x5d, 0x9d, 0xad, 0x20, 0xcc, 0x9d, 0xa7, 0x11, 0x38, 0x3a, 0x9d, 0xbe, 0x34, 0xea, 0x3f, 0xa5, 0xa2, + 0xaf, 0x75, 0xb4, 0x65, 0x02, 0x62, 0x9a, 0xd5, 0x4d, 0xd8, 0xb7, 0xd7, 0x3a, 0x8a, 0xbb, 0x06, 0xa3, 0xa3, 0xbe, 0x47, 0xd6, 0x50, 0xcc, 0x99, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P384_VALUE02[] = { + 0xac, 0x68, 0xf1, 0x9f, 0x2e, 0x1c, 0xb8, 0x79, 0xae, 0xd4, 0x3a, 0x99, 0x69, 0xb9, 0x1a, 0x08, + 0x39, 0xc4, 0xc3, 0x8a, 0x49, 0x74, 0x9b, 0x66, 0x1e, 0xfe, 0xdf, 0x24, 0x34, 0x51, 0x91, 0x5e, + 0xd0, 0x90, 0x5a, 0x32, 0xb0, 0x60, 0x99, 0x2b, 0x46, 0x8c, 0x64, 0x76, 0x6f, 0xc8, 0x43, 0x7a, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P384_VALUE02[] = { + 0xa7, 0xc7, 0x6b, 0x97, 0x0c, 0x3b, 0x5f, 0xe8, 0xb0, 0x5d, 0x28, 0x38, 0xae, 0x04, 0xab, 0x47, + 0x69, 0x7b, 0x9e, 0xaf, 0x52, 0xe7, 0x64, 0x59, 0x2e, 0xfd, 0xa2, 0x7f, 0xe7, 0x51, 0x32, 0x72, + 0x73, 0x44, 0x66, 0xb4, 0x00, 0x09, 0x1a, 0xdb, 0xf2, 0xd6, 0x8c, 0x58, 0xe0, 0xc5, 0x00, 0x66, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P521_VALUE01[] = { + 0x00, 0x00, 0x01, 0xb7, 0xc8, 0x5f, 0x26, 0xf5, 0xd4, 0xb2, 0xd7, 0x35, 0x5c, 0xf6, 0xb0, 0x21, 0x17, + 0x65, 0x99, 0x43, 0x76, 0x2b, 0x6d, 0x1d, 0xb5, 0xab, 0x4f, 0x1d, 0xbc, 0x44, 0xce, 0x7b, 0x29, 0x46, + 0xeb, 0x6c, 0x7d, 0xe3, 0x42, 0x96, 0x28, 0x93, 0xfd, 0x38, 0x7d, 0x1b, 0x73, 0xd7, 0xa8, 0x67, 0x2d, + 0x1f, 0x23, 0x69, 0x61, 0x17, 0x0b, 0x7e, 0xb3, 0x57, 0x99, 0x53, 0xee, 0x5c, 0xdc, 0x88, 0xcd, 0x2d, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P521_VALUE02[] = { + 0x00, 0x00, 0x01, 0xba, 0x52, 0xc5, 0x6f, 0xc8, 0x77, 0x6d, 0x9e, 0x8f, 0x5d, 0xb4, 0xf0, 0xcc, + 0x27, 0x63, 0x6d, 0x0b, 0x74, 0x1b, 0xbe, 0x05, 0x40, 0x06, 0x97, 0x94, 0x2e, 0x80, 0xb7, 0x39, + 0x88, 0x4a, 0x83, 0xbd, 0xe9, 0x9e, 0x0f, 0x67, 0x16, 0x93, 0x9e, 0x63, 0x2b, 0xc8, 0x98, 0x6f, + 0xa1, 0x8d, 0xcc, 0xd4, 0x43, 0xa3, 0x48, 0xb6, 0xc3, 0xe5, 0x22, 0x49, 0x79, 0x55, 0xa4, 0xf3, + 0xc3, 0x02, 0xf6, 0x76, +}; +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P521_VALUE01[] = { + 0x00, 0x00, 0x01, 0x7e, 0xec, 0xc0, 0x7a, 0xb4, 0xb3, 0x29, 0x06, 0x8f, 0xba, 0x65, 0xe5, 0x6a, 0x1f, + 0x88, 0x90, 0xaa, 0x93, 0x5e, 0x57, 0x13, 0x4a, 0xe0, 0xff, 0xcc, 0xe8, 0x02, 0x73, 0x51, 0x51, 0xf4, + 0xea, 0xc6, 0x56, 0x4f, 0x6e, 0xe9, 0x97, 0x4c, 0x5e, 0x68, 0x87, 0xa1, 0xfe, 0xfe, 0xe5, 0x74, 0x3a, + 0xe2, 0x24, 0x1b, 0xfe, 0xb9, 0x5d, 0x5c, 0xe3, 0x1d, 0xdc, 0xb6, 0xf9, 0xed, 0xb4, 0xd6, 0xfc, 0x47, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P521_VALUE01[] = { + 0x00, 0x00, 0x00, 0x60, 0x2f, 0x9d, 0x0c, 0xf9, 0xe5, 0x26, 0xb2, 0x9e, 0x22, 0x38, 0x1c, 0x20, 0x3c, + 0x48, 0xa8, 0x86, 0xc2, 0xb0, 0x67, 0x30, 0x33, 0x36, 0x63, 0x14, 0xf1, 0xff, 0xbc, 0xba, 0x24, 0x0b, + 0xa4, 0x2f, 0x4e, 0xf3, 0x8a, 0x76, 0x17, 0x46, 0x35, 0xf9, 0x1e, 0x6b, 0x4e, 0xd3, 0x42, 0x75, 0xeb, + 0x01, 0xc8, 0x46, 0x7d, 0x05, 0xca, 0x80, 0x31, 0x5b, 0xf1, 0xa7, 0xbb, 0xd9, 0x45, 0xf5, 0x50, 0xa5, +}; +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P521_VALUE02[] = { + 0x00, 0x00, 0x00, 0x68, 0x5a, 0x48, 0xe8, 0x6c, 0x79, 0xf0, 0xf0, 0x87, 0x5f, 0x7b, 0xc1, 0x8d, + 0x25, 0xeb, 0x5f, 0xc8, 0xc0, 0xb0, 0x7e, 0x5d, 0xa4, 0xf4, 0x37, 0x0f, 0x3a, 0x94, 0x90, 0x34, + 0x08, 0x54, 0x33, 0x4b, 0x1e, 0x1b, 0x87, 0xfa, 0x39, 0x54, 0x64, 0xc6, 0x06, 0x26, 0x12, 0x4a, + 0x4e, 0x70, 0xd0, 0xf7, 0x85, 0x60, 0x1d, 0x37, 0xc0, 0x98, 0x70, 0xeb, 0xf1, 0x76, 0x66, 0x68, + 0x77, 0xa2, 0x04, 0x6d, +}; + +static const uint8_t TEE_ATTR_DH_PUBLIC_VALUE_VALUE02[] = { + 0xa3, 0xf5, 0x7d, 0xbe, 0x9e, 0x2f, 0x0a, 0xda, 0xa9, 0x4e, 0x4e, 0x6a, 0xf0, 0xe0, 0x71, 0x47, + 0x0e, 0x2e, 0x41, 0x2e, 0xde, 0x73, 0x2a, 0x62, 0x14, 0xc3, 0x7c, 0x26, 0xd4, 0xe9, 0x9a, 0x54, + 0xba, 0x3d, 0xe7, 0x49, 0x85, 0x95, 0x0e, 0xe9, 0x14, 0xb2, 0x90, 0x22, 0x91, 0xdc, 0xff, 0x61, + 0xb2, 0xfc, 0xd1, 0xd0, 0x1b, 0x11, 0x14, 0xb6, 0x02, 0x64, 0x2b, 0x26, 0x5d, 0x88, 0xea, 0x8d, + 0xbb, 0xe2, 0x07, 0x0b, 0x48, 0xfb, 0x01, 0x53, 0x55, 0x1e, 0x59, 0x51, 0x36, 0xf2, 0xf9, 0xd1, + 0x97, 0xfb, 0x66, 0x12, 0x84, 0x5d, 0xed, 0xb8, 0x9b, 0x2d, 0x3e, 0x2b, 0x8c, 0xeb, 0x2a, 0x72, + 0x40, 0x9d, 0x55, 0x4c, 0xed, 0xeb, 0x55, 0x02, 0xff, 0x8c, 0xb0, 0x2e, 0x03, 0x65, 0x3f, 0x41, + 0xb1, 0xac, 0xa3, 0x30, 0x6b, 0xff, 0x6d, 0xf4, 0x6d, 0xe6, 0xe1, 0x0f, 0x86, 0x7c, 0x43, 0x64, +}; + + +/*ALL_CRYPTO_AAD_VALUES*/ +static const uint8_t AAD1_VALUE[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 +}; + +/*ALL_CRYPTO_AAD_LENGTHS*/ +#define AAD1_LENGTH 8 +#define NULL_LENGTH 0 + +/*ALL_TEE_CRYPTO_INITIALISATION_VECTOR_VALUES*/ +static const uint8_t NONCE2_VALUE_AES_GCM[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 +}; +static const uint8_t NONCE1_VALUE_AES_CCM[] = { + 0x00, 0x8D, 0x49, 0x3B, 0x30, 0xAE, 0x8B, 0x3C, 0x96, 0x96, 0x76, 0x6C, + 0xFA +}; + +/*ALL_TEE_CRYPTO_INITIALISATION_VECTOR_LENGTHS*/ +#define NONCE2_LENGTH_AES_GCM 12 +#define NONCE1_LENGTH_AES_CCM 13 + +/*ALL_CRYPTO_DATA_VALUE*/ +static const uint8_t DATA_ALL_ZEROES[4096]; +static const uint8_t DATA_FOR_CRYPTO1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00 +}; +static const uint8_t DATA_FOR_CRYPTO1_PART1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09 +}; +static const uint8_t DATA_FOR_CRYPTO1_PART2[] = { + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F +}; +static const uint8_t DATA_FOR_CRYPTO1_PART3[] = { + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00 +}; +static const uint8_t DATA_FOR_CRYPTO2_LENGTH_NOT_MULTIPLE_OF_128_BITS[] = { + 0x00, 0x01, 0x02, 0x03, +}; +static const uint8_t DATA_FOR_CRYPTO3_LENGTH_NOT_MULTIPLE_OF_64_BITS[] = { + 0x00, 0x01, 0x02, 0x03, +}; + +/*ALL_CRYPTO_DATA_LENGTH*/ +#define LENGTH_DATA_FOR_CRYPTO1 96 +#define LENGTH_DATA_FOR_CRYPTO1_PART1 32 +#define LENGTH_DATA_FOR_CRYPTO1_PART2 32 +#define LENGTH_DATA_FOR_CRYPTO1_PART3 32 +#define LENGTH_DATA_FOR_CRYPTO2 4 +#define LENGTH_DATA_FOR_CRYPTO3 4 +#define RSAES_PKCS1_OAEP_MGF1_SHA1_ENC_INVALID_LENGTH_MOD_2048 215 +#define RSAES_PKCS1_OAEP_MGF1_SHA224_ENC_INVALID_LENGTH_MOD_2048 199 +#define RSAES_PKCS1_OAEP_MGF1_SHA256_ENC_INVALID_LENGTH_MOD_2048 191 +#define RSAES_PKCS1_OAEP_MGF1_SHA384_ENC_INVALID_LENGTH_MOD_2048 159 +#define RSAES_PKCS1_OAEP_MGF1_SHA512_ENC_INVALID_LENGTH_MOD_2048 127 +#define RSAES_PKCS1_V1_5_ENC_INVALID_LENGTH_MOD_2048 246 + +/*ALL_TEE_CRYPTO_INITIALISATION_VECTOR_VALUES*/ +static const uint8_t IV1_VALUE_64bits_DES_DES3[] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef +}; +static const uint8_t IV2_VALUE_128bits_AES[] = { + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78, + 0x90, 0xab, 0xcd, 0xef +}; +static const uint8_t IV_INVALID_LENGTH_VALUE[] = { + 0x01, 0x02, 0x03, 0x04, 0x05 +}; + +/*ALL_TEE_CRYPTO_INITIALISATION_VECTOR_LENGTHS*/ +#define IV_LENGTH_NULL 0 +#define IV_INVALID_LENGTH 5 +#define IV1_LENGTH_64bits_DES_DES3 8 +#define IV2_LENGTH_128bits_AES 16 + +static const uint8_t *TEE_ATTR_VALUE_NONE; + +/*ALL_TEE_BUFFER_CASES*/ +#define INPUT_BUFFER_NORMAL 5 +#define INPUT_BUFFER_TOO_SHORT 4 +#define OUTPUT_BUFFER_NORMAL 1 +#define OUTPUT_BUFFER_TOO_SHORT 2 +#define TAG_BUFFER_TOO_SHORT 3 + +enum signature_validity { + INVALID_SIGNATURE = 0, + VALID_SIGNATURE +}; + +enum mac_validity { + INVALID_MAC = 0, + VALID_MAC +}; + +struct crypto_buffer { + uint8_t *buffer; + uint32_t size; +}; + +/*Saved in Invoke_Crypto_AllocateOperation*/ +struct crypto_op { + uint32_t algo; + uint32_t mode; + uint32_t obj_size; +}; +struct crypto_op saved_alloc; + +/*Saved in Invoke_Crypto_InitObjectWithKeys*/ +struct key_val { + uint32_t obh; + uint32_t obj_type; + uint32_t obj_size; + struct crypto_buffer key; +}; +struct key_val saved_key_vals; + +/*Saved in Invoke_Crypto_SetOperationKey*/ +struct obh_val { + uint32_t oph; + uint32_t obh; +}; +struct obh_val saved_obh1; + +/*Saved in Invoke_Crypto_SetOperationKey2*/ +struct obh_val2 { + uint32_t oph; + uint32_t obh1; + uint32_t obh2; +}; +struct obh_val2 saved_obh; + +/*saved by Invoke_Crypto_AEUpdateAAD*/ +struct crypto_buffer saved_aad_value; + +/*Saved in Invoke_Crypto_AEEncryptFinal*/ +struct crypto_buffer ae_encrypt_tag; + +/*Saved in Invoke_Crypto_AEUpdate_for_encryption*/ +struct crypto_buffer buffer_encrypted_chunks[4]; + +/*Saved in Invoke_Crypto_AEUpdate_for_Decryption*/ +struct crypto_buffer buffer_decrypted_chunks[4]; + +/*filled with data in Invoke_Crypto_AsymmetricEncrypt*/ +struct crypto_buffer buffer_asym_encrypted; + +/*saved by Invoke_Crypto_AEInit*/ +struct crypto_buffer saved_in_nonce; + +/*Saved in Invoke_Crypto_DeriveKey*/ +struct obh_val saved_derive; + +/*Saved in Invoke_Crypto_GenerateRandom*/ +struct crypto_buffer saved_random; + +/*Saved in Invoke_Crypto_DigestDoFinal*/ +struct crypto_buffer saved_digest; + +/*Saved in Invoke_Crypto_MACInit*/ +struct crypto_buffer saved_mac_iv; + +/*Saved in Invoke_Crypto_CipherInit*/ +struct crypto_buffer saved_cipher_iv; + +/*Saved in Invoke_Crypto_CipherUpdate*/ +struct crypto_buffer saved_cipher_update; + +static const void *saved_key_pub_attr[3]; + +static TEE_OperationInfo saved_op_info; +static uint32_t s_saved_op_mult_info[64 / sizeof(uint32_t)]; +static TEE_OperationInfoMultiple *saved_op_mult_info = + (TEE_OperationInfoMultiple *)s_saved_op_mult_info; + + +TEEC_UUID UUID_TTA_testingInternalAPI_crypto = { + 0x534D4152, 0x5443, 0x534C, + { 0x54, 0x43, 0x52, 0x59, 0x50, 0x54, 0x4F, 0x31 } +}; + +static void crypto_reset(void) +{ + saved_obh.oph = 0; + saved_obh.obh1 = 0; + saved_obh.obh2 = 0; + saved_alloc.algo = 0; + saved_alloc.mode = 0; + saved_alloc.obj_size = 0; + saved_key_vals.obh = 0; + saved_key_vals.obj_size = 0; + saved_key_vals.obj_type = 0; + CRYPTO_FREE(saved_key_vals.key); + + CRYPTO_FREE(saved_aad_value); + CRYPTO_FREE(ae_encrypt_tag); + /*4 chunks*/ + CRYPTO_FREE(buffer_encrypted_chunks[0]); + CRYPTO_FREE(buffer_encrypted_chunks[1]); + CRYPTO_FREE(buffer_encrypted_chunks[2]); + CRYPTO_FREE(buffer_encrypted_chunks[3]); + /*4 chunks*/ + CRYPTO_FREE(buffer_decrypted_chunks[0]); + CRYPTO_FREE(buffer_decrypted_chunks[1]); + CRYPTO_FREE(buffer_decrypted_chunks[2]); + CRYPTO_FREE(buffer_decrypted_chunks[3]); + CRYPTO_FREE(buffer_asym_encrypted); + CRYPTO_FREE(saved_in_nonce); + CRYPTO_FREE(saved_random); + CRYPTO_FREE(saved_digest); + CRYPTO_FREE(saved_cipher_iv); + CRYPTO_FREE(saved_cipher_update); + + memset(&saved_op_info, 0, sizeof(saved_op_info)); + memset(s_saved_op_mult_info, 0, sizeof(s_saved_op_mult_info)); +} + +static TEEC_Result calculate_digest(ADBG_Case_t *c, const void *data, + size_t data_length, + struct crypto_buffer *digest); + +static TEEC_Result sign_digest(ADBG_Case_t *c, + const struct crypto_buffer *in_dgst, + struct crypto_buffer *out_dgst); + +static bool verify_digest(ADBG_Case_t *c, const struct crypto_buffer *in_sdgst); + +static TEEC_Result mac_compute_final(ADBG_Case_t *c, TEEC_Session *s, + const void *full_data, + size_t fdata_length, + struct crypto_buffer *mac); + +static TEEC_Result cipher_do_final(ADBG_Case_t *c, TEEC_Session *s, + const void *full_data, + size_t fdata_length, + struct crypto_buffer *cipher); + +static void collapse_crypto_buffers(struct crypto_buffer *in_buffer, + struct crypto_buffer *out_buffer) +{ + int id; + uint8_t *tmp; + + out_buffer->size = 0; + + for (id = 0; id < 4; id++) + out_buffer->size += in_buffer[id].size; + + out_buffer->buffer = malloc(out_buffer->size); + tmp = out_buffer->buffer; + + for (id = 0; id < 4; id++) { + if (in_buffer[id].buffer) { + memcpy(tmp, in_buffer[id].buffer, in_buffer[id].size); + tmp += in_buffer[id].size; + } + } +} + +static TEEC_Result Invoke_Crypto_AllocateOperation(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, uint32_t algo, + uint32_t mode, + size_t obj_size1, + size_t obj_size2, + uint32_t op_handle) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + op.params[0].value.a = algo; + op.params[0].value.b = mode; + if (obj_size1 > obj_size2) + op.params[1].value.a = obj_size1; + else + op.params[1].value.a = obj_size2; + op.params[3].value.a = op_handle; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_VALUE_INPUT); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (!res) { + saved_alloc.algo = algo; + saved_alloc.mode = mode; + saved_alloc.obj_size = op.params[1].value.a; + } + + return res; +} + +static TEEC_Result Invoke_Crypto_GetOperationInfo(ADBG_Case_t *c , + TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = op_handle; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, TEEC_VALUE_OUTPUT); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (!res) + saved_op_info = (TEE_OperationInfo){ + .algorithm = op.params[0].value.a, + .operationClass = op.params[0].value.b, + .mode = op.params[1].value.a, + .digestLength = op.params[1].value.b, + .maxKeySize = op.params[2].value.a, + .keySize = op.params[2].value.b, + .requiredKeyUsage = op.params[3].value.a, + .handleState = op.params[3].value.b, + }; + + return res; +} + +static uint32_t get_be32(const uint8_t *b) +{ + return ((uint32_t)b[0] << 24) | ((uint32_t)b[1] << 16) | + ((uint32_t)b[2] << 8) | b[3]; +} + +static TEEC_Result Invoke_Crypto_GetOperationInfoMultiple(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle, + uint32_t max_num_keys) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + TEEC_SharedMemory shm = { + .size = 64, + .flags = TEEC_MEM_OUTPUT, + }; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, max_num_keys, <=, 2)) + return TEEC_ERROR_BAD_PARAMETERS; + + res = TEEC_AllocateSharedMemory(s->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + op.params[0].value.a = op_handle; + op.params[0].value.b = max_num_keys; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, &shm, shm.size); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, cmd, &op, &org); + + if (!res) { + uint8_t *b = shm.buffer; + TEE_OperationInfoMultiple *d = saved_op_mult_info; + size_t n = 0; + + memset(s_saved_op_mult_info, 0, sizeof(s_saved_op_mult_info)); + d->algorithm = get_be32(b); + d->operationClass = get_be32(b + 4); + d->mode = get_be32(b + 8); + d->digestLength = get_be32(b + 12); + d->maxKeySize = get_be32(b + 16); + d->handleState = get_be32(b + 20); + d->operationState = get_be32(b + 24); + d->numberOfKeys = get_be32(b + 28); + + for (n = 0; n < d->numberOfKeys; n++) { + d->keyInformation[n].keySize = get_be32(b + 32 + n * 8); + d->keyInformation[n].requiredKeyUsage = + get_be32(b + 36 + n * 8); + } + } + TEEC_ReleaseSharedMemory(&shm); + + return res; +} + +#define Check_0_OperationInfoMultiple(c, _algorithm, _operationClass, _mode, \ + _digestLength, _maxKeySize_object1, \ + _maxKeySize_object2, _handleState, \ + _operationState, _numberOfKeys) \ + do { \ + ADBG_EXPECT(c, _algorithm, saved_op_mult_info->algorithm); \ + ADBG_EXPECT(c, _operationClass, \ + saved_op_mult_info->operationClass); \ + ADBG_EXPECT(c, _mode, saved_op_mult_info->mode); \ + ADBG_EXPECT(c, _digestLength, \ + saved_op_mult_info->digestLength); \ + ADBG_EXPECT(c, MAX(_maxKeySize_object1, _maxKeySize_object2), \ + saved_op_mult_info->maxKeySize); \ + ADBG_EXPECT(c, _handleState, saved_op_mult_info->handleState); \ + ADBG_EXPECT(c, _operationState, \ + saved_op_mult_info->operationState); \ + ADBG_EXPECT(c, _numberOfKeys, \ + saved_op_mult_info->numberOfKeys); \ + } while (0) + +#define Check_1_OperationInfoKey(c, _keyIndex, _keySize, _requiredKeyUsage) \ + do { \ + if (ADBG_EXPECT_COMPARE_UNSIGNED(c, _keyIndex, <, saved_op_mult_info->numberOfKeys)) { \ + ADBG_EXPECT(c, _keySize, saved_op_mult_info->keyInformation[_keyIndex].keySize); \ + ADBG_EXPECT(c, _requiredKeyUsage, saved_op_mult_info->keyInformation[_keyIndex].requiredKeyUsage); \ + } \ + } while (0) + +#define Check_OperationInfo(c, _algorithm, _operationClass, _mode, \ + _digestLength, _maxKeySize_object1, \ + _maxKeySize_object2, _keySize, _requiredKeyUsage, \ + _handleFlags) \ + do { \ + ADBG_EXPECT(c, _algorithm, saved_op_info.algorithm); \ + ADBG_EXPECT(c, _operationClass, saved_op_info.operationClass); \ + ADBG_EXPECT(c, _mode, saved_op_info.mode); \ + ADBG_EXPECT(c, _digestLength, saved_op_info.digestLength); \ + ADBG_EXPECT(c, MAX(_maxKeySize_object1, _maxKeySize_object2), \ + saved_op_info.maxKeySize); \ + ADBG_EXPECT(c, _keySize, saved_op_info.keySize); \ + ADBG_EXPECT(c, _requiredKeyUsage, \ + saved_op_info.requiredKeyUsage); \ + ADBG_EXPECT(c, _handleFlags, saved_op_info.handleState); \ + ADBG_EXPECT(c, _algorithm, saved_op_info.algorithm); \ + } while (0) + +static TEEC_Result Invoke_Crypto_ResetOperation(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle) +{ + return Invoke_Simple_Function_v1(c, s, cmd, op_handle, 0); +} + +static TEEC_Result Invoke_Crypto_FreeAllKeysAndOperations(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle) +{ + return Invoke_Simple_Function_v1(c, s, cmd, op_handle, 0); +} + +static TEEC_Result add_be32(uint32_t v, TEEC_SharedMemory *shm, size_t *offs) +{ + uint8_t *d = (uint8_t *)shm->buffer + *offs; + size_t n = sizeof(uint32_t); + + if (*offs + n > shm->size) + return TEEC_ERROR_EXCESS_DATA; + + (*offs) += n; + while (n) { + n--; + d[n] = v; + v >>= 8; + } + + return TEEC_SUCCESS; +} + +static TEEC_Result add_attr(uint32_t id, const void *v, uint32_t sz, + TEEC_SharedMemory *shm1, size_t *offs_1, + TEEC_SharedMemory *shm2, size_t *offs_2) +{ + TEEC_Result res = TEEC_SUCCESS; + uint32_t vid = 0; + uint32_t voffs = 0; + uint32_t vsz = 0; + + if (id == TEE_ATTR_NONE) + goto out; + vid = id; + voffs = *offs_2; + vsz = sz; + + if (*offs_2 + sz > shm2->size) + return TEEC_ERROR_EXCESS_DATA; + memcpy((uint8_t *)shm2->buffer + *offs_2, v, sz); + (*offs_2) += sz; + +out: + res = add_be32(vid, shm1, offs_1); + if (res) + return res; + res = add_be32(voffs, shm1, offs_1); + if (res) + return res; + return add_be32(vsz, shm1, offs_1); +} + +static TEEC_Result +Invoke_Crypto_InitObjectWithKeys(ADBG_Case_t *c, TEEC_Session *s, uint32_t cmd, + uint32_t obj_type, uint32_t obj_size, + uint32_t id1, const void *v1, uint32_t sz1, + uint32_t id2, const void *v2, uint32_t sz2, + uint32_t id3, const void *v3, uint32_t sz3, + uint32_t id4, const void *v4, uint32_t sz4, + uint32_t id5, const void *v5, uint32_t sz5, + uint32_t obj_handle) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_SUCCESS; + uint32_t org = 0; + size_t offs1 = 0; + size_t offs2 = 0; + TEEC_SharedMemory shm1 = { + .size = BIG_SIZE, + .flags = TEEC_MEM_INPUT, + }; + TEEC_SharedMemory shm2 = { + .size = DS_BIG_SIZE, + .flags = TEEC_MEM_INPUT, + }; + + res = TEEC_AllocateSharedMemory(s->ctx, &shm1); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + res = TEEC_AllocateSharedMemory(s->ctx, &shm2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out_free_shm1; + + res = add_attr(id1, v1, sz1, &shm1, &offs1, &shm2, &offs2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out_free_shm2; + res = add_attr(id2, v2, sz2, &shm1, &offs1, &shm2, &offs2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out_free_shm2; + res = add_attr(id3, v3, sz3, &shm1, &offs1, &shm2, &offs2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out_free_shm2; + res = add_attr(id4, v4, sz4, &shm1, &offs1, &shm2, &offs2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out_free_shm2; + res = add_attr(id5, v5, sz5, &shm1, &offs1, &shm2, &offs2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out_free_shm2; + + op.params[0].value.a = obj_type; + op.params[0].value.b = obj_size; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, &shm1, offs1); + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, &shm2, offs2); + op.params[3].value.a = obj_handle; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_VALUE_INPUT); + + res = TEEC_InvokeCommand(s, cmd, &op, &org); + + if (!res) + saved_key_pub_attr[obj_handle] = v1; + +out_free_shm2: + TEEC_ReleaseSharedMemory(&shm2); +out_free_shm1: + TEEC_ReleaseSharedMemory(&shm1); + + return res; +} + +static TEEC_Result +Invoke_Crypto_InitObjectWithKeysExt(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t obj_type, + uint32_t obj_size, + uint32_t id1, const void *v1, uint32_t sz1, + uint32_t id2, const void *v2, uint32_t sz2, + uint32_t id3, const void *v3, uint32_t sz3, + uint32_t id4, const void *v4, uint32_t sz4, + uint32_t id5, const void *v5, uint32_t sz5, + uint32_t obj_handle) +{ + return Invoke_Crypto_InitObjectWithKeys(c, s, cmd, obj_type, obj_size, + id1, v1, sz1, id2, v2, sz2, + id3, v3, sz3, id4, v4, sz4, + id5, v5, sz5, obj_handle); +} + + + +static TEEC_Result Invoke_Crypto_SetOperationKey(ADBG_Case_t *c, + TEEC_Session *s, uint32_t cmd, + uint32_t op_handle, + uint32_t obj_handle) +{ + TEEC_Result res = Invoke_Simple_Function_v1(c, s, cmd, op_handle, + obj_handle); + + if (!res) { + saved_obh.oph = op_handle; + saved_obh.obh1 = obj_handle; + saved_obh.obh2 = TEE_HANDLE_NULL; + } + + return res; +} + +static TEEC_Result Invoke_Crypto_SetOperationKey2(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle, + uint32_t obj_handle1, + uint32_t obj_handle2) +{ + TEEC_Result res = Invoke_Simple_Function_v2(c, s, cmd, op_handle, + obj_handle1, obj_handle2, + 0); + if (!res) { + saved_obh.oph = op_handle; + saved_obh.obh1 = obj_handle1; + saved_obh.obh2 = obj_handle2; + } + + return res; +} + +static TEEC_Result Invoke_Crypto_DeriveKey(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t op_handle, + uint32_t attribute_list, + uint32_t obj_handle) +{ + uint32_t attr1 = ATTRIBUTE_NONE; + uint32_t attr2 = ATTRIBUTE_NONE; + uint32_t n = 0; + + for (n = 0; n <= ATTRIBUTE_06 && attr2 == ATTRIBUTE_NONE; n++) { + if (BIT(n) & attribute_list) { + if (attr1 == ATTRIBUTE_NONE) + attr1 = n; + else + attr2 = n; + } + } + + return Invoke_Simple_Function_v2(c, s, cmd, op_handle, obj_handle, + attr1, attr2); +} + +static TEEC_Result Invoke_Crypto_AEInit(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t op_handle, + const void *nonce_val, + size_t nonce_length, uint32_t tag_len, + uint32_t aad_len, uint32_t payload_len) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + TEEC_SharedMemory shm = { + .size = nonce_length, + .flags = TEEC_MEM_INPUT, + }; + + + res = TEEC_AllocateSharedMemory(s->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + memcpy(shm.buffer, nonce_val, nonce_length); + + op.params[0].value.a = op_handle; + op.params[0].value.b = tag_len; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, &shm, nonce_length); + op.params[2].value.a = aad_len; + op.params[2].value.b = payload_len; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, cmd, &op, &org); + TEEC_ReleaseSharedMemory(&shm); + return res; +} + +static TEEC_Result Invoke_Crypto_AEUpdate_for_encryption(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle, + const void *part_data, + uint32_t partd_length, + uint32_t case_buf, + uint32_t chunk_id) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + size_t initial_size; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, DS_BIG_SIZE, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = op_handle; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + /*if $IN_caseBuffer$ = OUTPUT_BUFFER_TOO_SHORT(2) + then Param[3].memref.size=1 */ + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + } else { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &org); + + /* Store the buffer from "shm2" in + * "buffer_encrypted_chunks[$IN_chunkNumber$]" + * which will be reused for the + * Invoke_Crypto_TEE_AEUpdate_for_decryption function + */ + if (res == TEEC_SUCCESS) { + buffer_encrypted_chunks[chunk_id].size = + op.params[3].memref.size; + buffer_encrypted_chunks[chunk_id].buffer = malloc( + buffer_encrypted_chunks[chunk_id].size); + memcpy(buffer_encrypted_chunks[chunk_id].buffer, + SHARE_MEM02->buffer, + buffer_encrypted_chunks[chunk_id].size); + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_AEUpdate_for_decryption(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle, + const void *part_data, + size_t partd_length, + uint32_t case_buf, + uint32_t chunk_id) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, + buffer_encrypted_chunks[chunk_id].size, + TEEC_MEM_INPUT, + buffer_encrypted_chunks[chunk_id].size, + buffer_encrypted_chunks[chunk_id]. + buffer, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, partd_length, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = op_handle; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, partd_length) + /*if $IN_caseBuffer$ = OUTPUT_BUFFER_TOO_SHORT(2) + then Param[3].memref.size=1*/ + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + } else { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + /* Save the buffer from "SharedMem2" into + * "buffer_decrypted_chunks[$IN_chunkNumber$]" + * in order to collapse all buffers returned for + * AEUpdate_for_decryption, + * which will be used in AEDecryptFinal + */ + if (res == TEEC_SUCCESS) { + if (!ADBG_EXPECT_BUFFER(c, part_data, partd_length, + SHARE_MEM02->buffer, + op.params[3].memref.size)) + res = TEEC_ERROR_GENERIC; + + buffer_decrypted_chunks[chunk_id].size = + op.params[3].memref.size; + buffer_decrypted_chunks[chunk_id].buffer = malloc( + buffer_decrypted_chunks[chunk_id].size); + memcpy(buffer_decrypted_chunks[chunk_id].buffer, + SHARE_MEM02->buffer, + buffer_decrypted_chunks[chunk_id].size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_AEUpdateAAD(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle, + const void *aad_data, + size_t aad_length) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, aad_length, + TEEC_MEM_INPUT, aad_length, + aad_data, mem01_exit) + + op.params[0].value.a = op_handle; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + /* Save the $IN_AAD_Value$ for AAD for later cryptographic computation + */ + if (res == TEEC_SUCCESS) { + saved_aad_value.buffer = malloc(aad_length); + saved_aad_value.size = aad_length; + memcpy(saved_aad_value.buffer, aad_data, aad_length); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_AEEncryptFinal(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle, + const void *part_data, + size_t partd_length, + const void *full_data, + size_t fdata_length, + uint32_t case_buf, + uint32_t chunk_id) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_partd_size, initial_fdata_size; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, partd_length, + TEEC_MEM_OUTPUT, mem02_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM03, partd_length, + TEEC_MEM_OUTPUT, mem03_exit) + + op.params[0].value.a = op_handle; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + switch (case_buf) { + case OUTPUT_BUFFER_TOO_SHORT: + /*if $IN_caseBuffer$ = + OUTPUT_BUFFER_TOO_SHORT(2) then Param[3].memref.size=1*/ + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, SHARE_MEM03, + SHARE_MEM03->size) + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + break; + case TAG_BUFFER_TOO_SHORT: + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, SHARE_MEM03, 1) + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + break; + case OUTPUT_BUFFER_NORMAL: + default: + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, SHARE_MEM03, + SHARE_MEM03->size) + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + break; + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT); + initial_partd_size = op.params[2].memref.size; + initial_fdata_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + /* Store the buffer from "shm2" in + * "buffer_encrypted_chunks[$IN_chunkNumber$]" + * which will be reused for + * the Invoke_Crypto_TEE_AEDecryptFinal function + */ + buffer_encrypted_chunks[chunk_id].size = + op.params[3].memref.size; + buffer_encrypted_chunks[chunk_id].buffer = malloc( + buffer_encrypted_chunks[chunk_id].size); + memcpy(buffer_encrypted_chunks[chunk_id].buffer, + SHARE_MEM02->buffer, + buffer_encrypted_chunks[chunk_id].size); + + /* Store the tag from "SharedMem3" which will be reused for the + * Invoke_Crypto_TEE_AEDecryptFinal function + */ + ae_encrypt_tag.size = op.params[2].memref.size; + ae_encrypt_tag.buffer = malloc(ae_encrypt_tag.size); + memcpy(ae_encrypt_tag.buffer, SHARE_MEM03->buffer, + ae_encrypt_tag.size); + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + if (initial_partd_size == op.params[2].memref.size) + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_fdata_size, <, + op.params[3].memref.size); + else + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_partd_size, <, + op.params[2].memref.size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM03); +mem03_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_AEDecryptFinal(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle, + const void *part_data, + size_t partd_length, + const void *full_data, + size_t fdata_length, + uint32_t case_buf, + enum mac_validity mac_case, + uint32_t chunk_id) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_size; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, + buffer_encrypted_chunks[chunk_id].size, + TEEC_MEM_INPUT, + buffer_encrypted_chunks[chunk_id].size, + buffer_encrypted_chunks[chunk_id]. + buffer, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, partd_length, + TEEC_MEM_OUTPUT, mem02_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM03, ae_encrypt_tag.size, + TEEC_MEM_INPUT, mem03_exit) + /* Fill "SharedMem3" with the tag previously + * saved in Invoke_Crypto_AEEncryptFinal + * (with an error (one bit changed) if $IN_caseMac$ = INVALID_MAC) + */ + if (ae_encrypt_tag.buffer != NULL) { + memcpy(SHARE_MEM03->buffer, ae_encrypt_tag.buffer, + ae_encrypt_tag.size); + + if (mac_case == INVALID_MAC) + BIT_CHANGE(*(uint32_t *)SHARE_MEM03->buffer, 4); + } + + op.params[0].value.a = op_handle; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, SHARE_MEM03, + SHARE_MEM03->size) + /*if $IN_caseBuffer$ = OUTPUT_BUFFER_TOO_SHORT(2) + then Param[3].memref.size=1*/ + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + } else { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + /* Save the buffer from "SharedMem2" to + * "buffer_decrypted_chunks[$IN_chunkNumber$]" + */ + buffer_decrypted_chunks[chunk_id].size = + op.params[3].memref.size; + buffer_decrypted_chunks[chunk_id].buffer = malloc( + buffer_decrypted_chunks[chunk_id].size); + memcpy(buffer_decrypted_chunks[chunk_id].buffer, + SHARE_MEM02->buffer, + buffer_decrypted_chunks[chunk_id].size); + + /* Compare the data in clear $IN_fullDataValue$ and with + * collapsed buffers from table + * "buffer_decrypted_chunks" and check they are equals + */ + struct crypto_buffer collapsed; + CRYPTO_INIT(collapsed); + collapse_crypto_buffers(buffer_decrypted_chunks, &collapsed); + ADBG_EXPECT_BUFFER(c, full_data, fdata_length, collapsed.buffer, + collapsed.size); + CRYPTO_FREE(collapsed); + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM03); +mem03_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_GenerateRandom(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM01, BIG_SIZE, + TEEC_MEM_OUTPUT, mem01_exit) + + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_MEMREF_PARTIAL_OUTPUT); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + /* Check that the buffer shm1 is not empty + * + Check that this random value is + * different of a previous call of this command + */ + if (res == TEEC_SUCCESS) { + if (ADBG_EXPECT_COMPARE_SIGNED(c, 0, !=, + op.params[3].memref.size)) { + if (saved_random.buffer != NULL) { + (void)ADBG_EXPECT_COMPARE_SIGNED(c, 0, !=, + memcmp( + SHARE_MEM01 + -> + buffer, + saved_random + . + buffer, + op. + params[3]. + memref. + size)); + free(saved_random.buffer); + saved_random.size = 0; + } + + saved_random.size = op.params[3].memref.size; + saved_random.buffer = malloc(saved_random.size); + memcpy(saved_random.buffer, SHARE_MEM01->buffer, + saved_random.size); + } + } + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_DigestUpdate(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t op_handle, + const void *part_data, + size_t partd_length) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + + op.params[0].value.a = op_handle; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_DigestDoFinal(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t op_handle, + const void *part_data, + size_t partd_length, + const void *full_data, + size_t fdata_length, + uint32_t case_buf) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_size; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, fdata_length, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = op_handle; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + } else { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE, + TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + /* Compute the hash of $IN_fullDataValue$ + * and compare it to "shm2" + */ + struct crypto_buffer tmp_dgst; + CRYPTO_INIT(tmp_dgst); + ADBG_EXPECT_TEEC_SUCCESS(c, res = calculate_digest(c, full_data, + fdata_length, + &tmp_dgst)); + ADBG_EXPECT_BUFFER(c, tmp_dgst.buffer, tmp_dgst.size, + SHARE_MEM02->buffer, tmp_dgst.size); + + /* Store the Digest value which can be reused for a next call to + * TEE_AsymmetricSignDigest or TEE_AsymmetricVerifyDigest + */ + CRYPTO_FREE(saved_digest); + saved_digest.size = op.params[3].memref.size; + saved_digest.buffer = malloc(saved_digest.size); + memcpy(saved_digest.buffer, SHARE_MEM02->buffer, + saved_digest.size); + CRYPTO_FREE(tmp_dgst); + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result +Invoke_Crypto_AsymmetricSignDigest(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *full_data, + size_t fdata_length, + uint32_t case_buf) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_size; + size_t sz; + + /* Fill SharedMem1 with the previously stored Digest + value after TEE_DigestDoFinal */ + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, + saved_digest.size, + TEEC_MEM_INPUT, saved_digest.size, + saved_digest.buffer, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, 512, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = oph; + + sz = SHARE_MEM01->size; + if (case_buf == INPUT_BUFFER_TOO_SHORT) + sz--; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, sz) + + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) + sz = 1; + else + sz = SHARE_MEM02->size; + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, sz) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + /* Compute a Verify_Signature of the signature + * store under "SharedMem2" + */ + struct crypto_buffer s_dgst; + CRYPTO_INIT(s_dgst); + s_dgst.size = op.params[3].memref.size; + s_dgst.buffer = malloc(s_dgst.size); + memcpy(s_dgst.buffer, SHARE_MEM02->buffer, s_dgst.size); + ADBG_EXPECT(c, true, verify_digest(c, &s_dgst)); + CRYPTO_FREE(s_dgst); + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result +Invoke_Crypto_AsymmetricVerifyDigest(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *full_data, + size_t fdata_length, uint32_t buffer_case, + uint32_t valid_sig) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + uint32_t dec_input = 0; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, fdata_length, + TEEC_MEM_INPUT, + saved_digest.size, saved_digest.buffer, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, 512, + TEEC_MEM_INPUT, mem02_exit) + + struct crypto_buffer signed_dgst; + CRYPTO_INIT(signed_dgst); + res = sign_digest(c, &saved_digest, &signed_dgst); + + /* Fill "SharedMem2" with the valid computed signature based on + * the previously stored Digest value after TEE_DigestDoFinal + */ + if (signed_dgst.buffer != NULL) { + memcpy(SHARE_MEM02->buffer, signed_dgst.buffer, + signed_dgst.size); + + if (valid_sig != VALID_SIGNATURE) { + /*make it invalid*/ + BIT_CHANGE(*(uint32_t *)SHARE_MEM02->buffer, 4); + } + } + + if (buffer_case == INPUT_BUFFER_TOO_SHORT) + dec_input = 1; + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + saved_digest.size - dec_input) + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + signed_dgst.size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE, + TEEC_MEMREF_PARTIAL_INPUT); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + CRYPTO_FREE(signed_dgst); + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_AsymmetricEncrypt(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, + uint32_t oph, + const void *full_data, + size_t fdata_length, + uint32_t case_buf) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_size; + + /* Fill SharedMem1 with full_data */ + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, fdata_length, + TEEC_MEM_INPUT, fdata_length, + full_data, mem01_exit) + + + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, 512, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + /*if $IN_caseBuffer$ = OUTPUT_BUFFER_TOO_SHORT(2) + then Param[3].memref.size=1*/ + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + } else { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + /* Check that "SharedMem2" is not empty + * Store the value from "SharedMem2" to a + * "buffer_asym_encrypted", + * which will be reused in Invoke_Crypto_AsymmetricDecrypt + */ + if (ADBG_EXPECT_COMPARE_SIGNED(c, 0, !=, + op.params[3].memref.size)) { + buffer_asym_encrypted.size = op.params[3].memref.size; + buffer_asym_encrypted.buffer = malloc( + buffer_asym_encrypted.size); + memcpy(buffer_asym_encrypted.buffer, + SHARE_MEM02->buffer, buffer_asym_encrypted.size); + } + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_AsymmetricDecrypt(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, + uint32_t op_handle, + const void *full_data, + size_t fdata_length, + uint32_t case_buf) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_size; + const char *expected_res; + size_t expected_size; + size_t sz; + + /* Fill SharedMem1 with buffer_asym_encrypted */ + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, + buffer_asym_encrypted.size, + TEEC_MEM_INPUT, + buffer_asym_encrypted.size, + buffer_asym_encrypted.buffer, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, 512, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = op_handle; + + sz = buffer_asym_encrypted.size; + if (case_buf == INPUT_BUFFER_TOO_SHORT) + sz--; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, sz); + + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) + sz = 1; + else + sz = SHARE_MEM02->size; + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, sz); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + expected_res = full_data; + expected_size = fdata_length; + if (saved_alloc.algo == TEE_ALG_RSA_NOPAD) { + /* + * According to GP 1.1, no pad encrypting TEE_ALG_RSA_NOPAD + * follows "PKCS #1 (RSA primitive)", as stated in + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf + * Page 10, it is stated that RSA primitives RSAEP and RSADP + * outputs "an integer between 0 and n-1". Hence the + * leading 0s must not be taken into account when checking + * the reference + */ + while (expected_size && expected_res[0] == 0) { + expected_size--; + expected_res++; + } + } + + if (res == TEEC_SUCCESS) { + /* Compare the clear data in + * $IN_fullDataValue$ with "SharedMem2" + * and check they are equal + */ + ADBG_EXPECT_BUFFER(c, expected_res, expected_size, + SHARE_MEM02->buffer, + op.params[3].memref.size); + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_CopyOperation(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t dst_oph, + uint32_t src_oph) +{ + return Invoke_Simple_Function_v1(c, s, cmd, dst_oph, src_oph); +} + +static TEEC_Result Invoke_Crypto_MACInit( + ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *iv, size_t iv_len) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM06, iv_len, + TEEC_MEM_INPUT, iv_len, iv, mem06_exit) + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM06, iv_len) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + /* save the $IN_InitialisationVector$ for + * later computation of encryptedData + */ + if (iv_len != 0) { + CRYPTO_FREE(saved_mac_iv); + saved_mac_iv.size = iv_len; + saved_mac_iv.buffer = malloc(iv_len); + memcpy(saved_mac_iv.buffer, iv, iv_len); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM06); +mem06_exit: + return res; +} + +/*CMD_MACUpdate*/ +static TEEC_Result Invoke_Crypto_MACUpdate( + ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *part_data, size_t partd_length) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +/*CMD_MACCompareFinal*/ +static TEEC_Result Invoke_Crypto_MACCompareFinal( + ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *part_data, size_t partd_length, + const void *full_data, size_t fdata_length, + enum mac_validity mac_case) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + /* Fill SharedMem1 with part_data */ + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, fdata_length, + TEEC_MEM_INPUT, mem02_exit) + + /* Fill SharedMem2 with valid computed MAC of full_data */ + struct crypto_buffer mac; + CRYPTO_INIT(mac); + res = mac_compute_final(c, s, full_data, fdata_length, &mac); + + if (mac.buffer != NULL) { + memcpy(SHARE_MEM02->buffer, mac.buffer, mac.size); + + if (mac_case != VALID_MAC) { + /* change one bit from the valid + MAC to make it invalid. */ + BIT_CHANGE(*(uint32_t *)SHARE_MEM02->buffer, 4); + } + } + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, SHARE_MEM02, mac.size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + CRYPTO_FREE(mac); + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +/*CMD_MACComputeFinal*/ +static TEEC_Result Invoke_Crypto_MACComputeFinal( + ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *part_data, size_t partd_length, + const void *full_data, size_t fdata_length, uint32_t case_buf) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_size; + + /* Fill SharedMem1 with part_data */ + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, fdata_length, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + } else { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + /* Compute the MAC of $IN_fullDataValue$ and + compare it to "SharedMem2" */ + if (res == TEEC_SUCCESS) { + struct crypto_buffer tmp_mac; + CRYPTO_INIT(tmp_mac); + ADBG_EXPECT_TEEC_SUCCESS(c, res = + mac_compute_final(c, s, + full_data, + fdata_length, + &tmp_mac)); + + if (res != TEEC_SUCCESS) + goto exit; + + ADBG_EXPECT_COMPARE_SIGNED(c, 0, ==, + memcmp(SHARE_MEM02->buffer, + tmp_mac.buffer, + op.params[3].memref.size)); + CRYPTO_FREE(tmp_mac); + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + +exit: + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +/*CMD_CipherInit*/ +static TEEC_Result Invoke_Crypto_CipherInit( + ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *iv, size_t iv_len) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, iv_len, + TEEC_MEM_INPUT, iv_len, iv, mem01_exit) + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + /* Save the $IN_InitialisationVector$ for later + * computation of encryptedData + */ + if (iv != NULL) { + CRYPTO_FREE(saved_cipher_iv); + saved_cipher_iv.size = iv_len; + saved_cipher_iv.buffer = malloc(iv_len); + memcpy(saved_cipher_iv.buffer, iv, iv_len); + } else { + saved_cipher_iv.size = 0; + saved_cipher_iv.buffer = NULL; + } + } + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + CRYPTO_FREE(saved_cipher_update); + return res; +} +/*CMD_CipherUpdate*/ +static TEEC_Result Invoke_Crypto_CipherUpdate( + ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *part_data, uint32_t partd_length, + uint32_t case_buf) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_size; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, partd_length, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + /*if $IN_caseBuffer$ = OUTPUT_BUFFER_TOO_SHORT(2) + then Param[3].memref.size=1*/ + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + } else { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + /* Save the buffer returned in "SharedMem2" in order + * to collapse all buffers returned for CipherUpdate, + * which will be used in CipherDoFinal + */ + if (op.params[3].memref.size != 0) { + void *tmp = realloc(saved_cipher_update.buffer, + saved_cipher_update.size + + op.params[3].memref.size); + saved_cipher_update.buffer = tmp; + memcpy( + saved_cipher_update.buffer + + saved_cipher_update.size, SHARE_MEM02->buffer, + op.params[3].memref.size); + saved_cipher_update.size += op.params[3].memref.size; + } + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +/*CMD_CipherDoFinal*/ +static TEEC_Result Invoke_Crypto_CipherDoFinal( + ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph, + const void *part_data, size_t partd_length, + const void *full_data, size_t fulld_length, uint32_t case_buf) +{ + TEEC_Result res; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig; + size_t initial_size; + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM01, partd_length, + TEEC_MEM_INPUT, partd_length, + part_data, mem01_exit) + /* used fulld_length instead of partd_length as + described in the Adaptation layer specification.*/ + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM02, fulld_length, + TEEC_MEM_OUTPUT, mem02_exit) + + op.params[0].value.a = oph; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + /*if $IN_caseBuffer$ = OUTPUT_BUFFER_TOO_SHORT(2) + then Param[3].memref.size=1*/ + if (case_buf == OUTPUT_BUFFER_TOO_SHORT) { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, 1) + } else { + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM02, + SHARE_MEM02->size) + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + initial_size = op.params[3].memref.size; + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + /* Append the buffer returned in "SharedMem2" + * to the previously buffers + * returned for CipherUpdate => "collapsed_buffers" + */ + if (op.params[3].memref.size != 0) { + void *tmp = realloc(saved_cipher_update.buffer, + saved_cipher_update.size + + op.params[3].memref.size); + saved_cipher_update.buffer = tmp; + memcpy( + saved_cipher_update.buffer + + saved_cipher_update.size, SHARE_MEM02->buffer, + op.params[3].memref.size); + saved_cipher_update.size += op.params[3].memref.size; + } + + /* Compute the ciphered data of + * $IN_fullDataValue$ and compare it + * to "collapsed_buffers" + */ + struct crypto_buffer full_ciphered_data; + CRYPTO_INIT(full_ciphered_data); + ADBG_EXPECT_TEEC_SUCCESS(c, res = + cipher_do_final(c, s, + full_data, + fulld_length, + & + full_ciphered_data)); + + if (res == TEEC_SUCCESS) { + ADBG_EXPECT_BUFFER(c, full_ciphered_data.buffer, + full_ciphered_data.size, + saved_cipher_update.buffer, + saved_cipher_update.size); + } else if (res == TEEC_ERROR_SHORT_BUFFER) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, initial_size, <, + op.params[3].memref.size); + } + + CRYPTO_FREE(full_ciphered_data); + CRYPTO_FREE(saved_cipher_update); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Crypto_FreeOperation(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t oph) +{ + return Invoke_Simple_Function_v1(c, s, cmd, oph, 0); +} + + +static const EVP_MD *hash_algo_to_md(uint32_t algo) +{ + switch (algo) { + case TEE_ALG_MD5: + return EVP_md5(); + case TEE_ALG_SHA1: + return EVP_sha1(); + case TEE_ALG_SHA224: + return EVP_sha224(); + case TEE_ALG_SHA256: + return EVP_sha256(); + case TEE_ALG_SHA384: + return EVP_sha384(); + case TEE_ALG_SHA512: + return EVP_sha512(); + default: + return NULL; + } +} + + +static TEEC_Result calculate_digest(ADBG_Case_t *c, const void *data, + size_t data_length, + struct crypto_buffer *digest) +{ + const EVP_MD *md = hash_algo_to_md(saved_alloc.algo); + void *buf = NULL; + unsigned int sz = 0; + + if (!ADBG_EXPECT_NOT_NULL(c, md)) + return TEEC_ERROR_NOT_SUPPORTED; + sz = EVP_MD_size(md); + buf = calloc(1, sz); + if (!buf) + return TEEC_ERROR_OUT_OF_MEMORY; + + if (EVP_Digest(data, data_length, buf, &sz, md, NULL)) { + digest->size = sz; + digest->buffer = buf; + return TEEC_SUCCESS; + } else { + free(buf); + return TEEC_ERROR_GENERIC; + } +} + +struct key_attr { + const void *val; + size_t len; +}; + +#define KEY_ATTR(val_array) { .val = val_array, .len = sizeof(val_array) } + +struct dsa_key_vals { + struct key_attr priv; + struct key_attr pub; + struct key_attr prime; + struct key_attr subprime; + struct key_attr base; +}; + +static const struct dsa_key_vals dsa_key_vals[] = { { + .prime = KEY_ATTR(TEE_ATTR_DSA_PRIME_768_VALUE01), + .subprime = KEY_ATTR(TEE_ATTR_DSA_SUBPRIME_160_VALUE01), + .base = KEY_ATTR(TEE_ATTR_DSA_BASE_768_VALUE01), + .priv = KEY_ATTR(TEE_ATTR_DSA_PRIVATE_VALUE_160_VALUE01), + .pub = KEY_ATTR(TEE_ATTR_DSA_PUBLIC_VALUE_768_VALUE01), + }, { + .prime = KEY_ATTR(TEE_ATTR_DSA_PRIME_2048_VALUE01), + .subprime = KEY_ATTR(TEE_ATTR_DSA_SUBPRIME_224_VALUE01), + .base = KEY_ATTR(TEE_ATTR_DSA_BASE_2048_VALUE01), + .priv = KEY_ATTR(TEE_ATTR_DSA_PRIVATE_VALUE_224_VALUE01), + .pub = KEY_ATTR(TEE_ATTR_DSA_PUBLIC_VALUE_2048_VALUE01), + }, { + .prime = KEY_ATTR(TEE_ATTR_DSA_PRIME_3072_VALUE01), + .subprime = KEY_ATTR(TEE_ATTR_DSA_SUBPRIME_256_VALUE01), + .base = KEY_ATTR(TEE_ATTR_DSA_BASE_3072_VALUE01), + .priv = KEY_ATTR(TEE_ATTR_DSA_PRIVATE_VALUE_256_VALUE01), + .pub = KEY_ATTR(TEE_ATTR_DSA_PUBLIC_VALUE_3072_VALUE01), + }, +}; + + +struct ecdsa_key_vals { + struct key_attr priv; + struct key_attr x; + struct key_attr y; + uint32_t curve; + uint32_t key_size_bytes; +}; +static const struct ecdsa_key_vals ecdsa_key_vals[] = { { + .priv = KEY_ATTR(TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P192_VALUE01), + .x = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P192_VALUE01), + .y = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P192_VALUE01), + .curve = 1, /* TEE_ECC_CURVE_NIST_P192 */ + .key_size_bytes = 24, + }, { + .priv = KEY_ATTR(TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P224_VALUE01), + .x = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P224_VALUE01), + .y = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P224_VALUE01), + .curve = 2 /* TEE_ECC_CURVE_NIST_P224 */, + .key_size_bytes = 28, + }, { + .priv = KEY_ATTR(TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P256_VALUE01), + .x = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P256_VALUE01), + .y = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P256_VALUE01), + .curve = 3 /* TEE_ECC_CURVE_NIST_P256 */, + .key_size_bytes = 32, + }, { + .priv = KEY_ATTR(TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P384_VALUE01), + .x = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P384_VALUE01), + .y = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P384_VALUE01), + .curve = 4 /* TEE_ECC_CURVE_NIST_P384 */, + .key_size_bytes = 48, + }, { + .priv = KEY_ATTR(TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P521_VALUE01), + .x = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P521_VALUE01), + .y = KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P521_VALUE01), + .curve = 5 /* TEE_ECC_CURVE_NIST_P521 */, + .key_size_bytes = 66, + }, +}; + +struct rsa_key_vals { + struct key_attr mod; + struct key_attr pub; + struct key_attr priv; +}; + +static const struct rsa_key_vals rsa_key_vals[] = { { + .mod = KEY_ATTR(TEE_ATTR_RSA_MODULUS_VALUE01), + .pub = KEY_ATTR(TEE_ATTR_RSA_PUBLIC_EXPONENT_VALUE01), + .priv = KEY_ATTR(TEE_ATTR_RSA_PRIVATE_EXPONENT_VALUE01), + }, +}; + +static const void *get_dsa_key_vals(const void *attr) +{ + const size_t nelem = sizeof(dsa_key_vals) / sizeof(dsa_key_vals[0]); + size_t n; + + for (n = 0; n < nelem; n++) { + if (attr == dsa_key_vals[n].priv.val || + attr == dsa_key_vals[n].pub.val || + attr == dsa_key_vals[n].prime.val || + attr == dsa_key_vals[n].subprime.val || + attr == dsa_key_vals[n].base.val) { + return dsa_key_vals + n; + } + } + + return NULL; +} + +static const void *get_ecdsa_key_vals(const void *attr) +{ + const size_t nelem = sizeof(ecdsa_key_vals) / sizeof(ecdsa_key_vals[0]); + size_t n; + + for (n = 0; n < nelem; n++) { + if (attr == ecdsa_key_vals[n].priv.val || + attr == ecdsa_key_vals[n].x.val || + attr == ecdsa_key_vals[n].y.val) + return ecdsa_key_vals + n; + } + + return NULL; +} + +static const void *get_rsa_key_vals(const void *attr) +{ + const size_t nelem = sizeof(rsa_key_vals) / sizeof(rsa_key_vals[0]); + size_t n; + + for (n = 0; n < nelem; n++) { + if (attr == rsa_key_vals[n].priv.val || + attr == rsa_key_vals[n].mod.val || + attr == rsa_key_vals[n].pub.val) + return rsa_key_vals + n; + } + + return NULL; +} + +static BIGNUM *bn_from_key_attr(const struct key_attr *ka) +{ + return BN_bin2bn(ka->val, ka->len, NULL); +} + +static DSA *dsa_from_key_vals(const struct dsa_key_vals *dkv) +{ + BIGNUM *priv_key = bn_from_key_attr(&dkv->priv); + BIGNUM *pub_key = bn_from_key_attr(&dkv->pub); + BIGNUM *q = bn_from_key_attr(&dkv->subprime); + BIGNUM *p = bn_from_key_attr(&dkv->prime); + BIGNUM *g = bn_from_key_attr(&dkv->base); + DSA *dsa = DSA_new(); + + if (!dsa || !priv_key || !pub_key || !p || !q || !g) + goto err_free_all; + + if (!DSA_set0_pqg(dsa, p, q, g)) + goto err_free_all; + + if (!DSA_set0_key(dsa, pub_key, priv_key)) + goto err_free_priv_pub; + + return dsa; + +err_free_all: + BN_free(p); + BN_free(q); + BN_free(g); +err_free_priv_pub: + BN_free(priv_key); + BN_free(pub_key); + DSA_free(dsa); + + return NULL; +} + +static TEEC_Result dsa_sign_digest(ADBG_Case_t *c, + const struct dsa_key_vals *dkv, + const struct crypto_buffer *in_dgst, + struct crypto_buffer *out_dgst) +{ + TEEC_Result res = TEEC_SUCCESS; + DSA *dsa = dsa_from_key_vals(dkv); + const BIGNUM *r = NULL; + const BIGNUM *s = NULL; + DSA_SIG *sig = NULL; + + if (!dsa) { + res = TEEC_ERROR_OUT_OF_MEMORY; + ADBG_EXPECT_TEEC_SUCCESS(c, res); + return res; + } + + sig = DSA_do_sign(in_dgst->buffer, in_dgst->size, dsa); + if (!sig) { + res = TEEC_ERROR_OUT_OF_MEMORY; + ADBG_EXPECT_TEEC_SUCCESS(c, res); + goto out; + } + + out_dgst->size = 2 * dkv->subprime.len; /* q */ + out_dgst->buffer = calloc(1, out_dgst->size); + if (!out_dgst->buffer) { + res = TEEC_ERROR_OUT_OF_MEMORY; + ADBG_EXPECT_TEEC_SUCCESS(c, res); + goto out; + } + + DSA_SIG_get0(sig, &r, &s); + BN_bn2bin(r, out_dgst->buffer + out_dgst->size / 2 - BN_num_bytes(r)); + BN_bn2bin(s, out_dgst->buffer + out_dgst->size - BN_num_bytes(s)); + res = TEEC_SUCCESS; + +out: + DSA_free(dsa); + DSA_SIG_free(sig); + + return res; +} + +static bool dsa_verify_digest(ADBG_Case_t *c, const struct dsa_key_vals *dkv, + const void *digest, size_t digest_len, + const struct crypto_buffer *in_sdgst) +{ + DSA *dsa = dsa_from_key_vals(dkv); + DSA_SIG *sig = NULL; + BIGNUM *r = NULL; + BIGNUM *s = NULL; + bool res = false; + + if (!ADBG_EXPECT_NOT_NULL(c, dsa)) + return false; + + sig = DSA_SIG_new(); + if (!ADBG_EXPECT_NOT_NULL(c, sig)) + goto out; + + r = BN_bin2bn(in_sdgst->buffer, in_sdgst->size / 2, NULL); + if (!ADBG_EXPECT_NOT_NULL(c, r)) + goto out; + s = BN_bin2bn(in_sdgst->buffer + in_sdgst->size / 2, + in_sdgst->size / 2, NULL); + if (!ADBG_EXPECT_NOT_NULL(c, s)) { + BN_free(r); + goto out; + } + DSA_SIG_set0(sig, r, s); + + res = DSA_do_verify(digest, digest_len, sig, dsa); +out: + DSA_free(dsa); + DSA_SIG_free(sig); + + return res; +} + +static int curve_to_nid(uint32_t curve) +{ + switch (curve) { + case 1 /* TEE_ECC_CURVE_NIST_P192 */: + return NID_X9_62_prime192v1; + case 2 /* TEE_ECC_CURVE_NIST_P224 */: + return NID_secp224r1; + case 3 /* TEE_ECC_CURVE_NIST_P256 */: + return NID_X9_62_prime256v1; + case 4 /* TEE_ECC_CURVE_NIST_P384 */: + return NID_secp384r1; + case 5 /* TEE_ECC_CURVE_NIST_P521 */: + return NID_secp521r1; + default: + return -1; + } +} + +static EC_KEY *ecdsa_from_key_vals(const struct ecdsa_key_vals *kv) +{ + EC_KEY *key = EC_KEY_new_by_curve_name(curve_to_nid(kv->curve)); + BIGNUM *priv_key = bn_from_key_attr(&kv->priv); + BIGNUM *x = bn_from_key_attr(&kv->x); + BIGNUM *y = bn_from_key_attr(&kv->y); + + if (!key || !priv_key || !x || !y) + goto err_free_all; + + if (!EC_KEY_set_private_key(key, priv_key)) + goto err_free_all; + + if (!EC_KEY_set_public_key_affine_coordinates(key, x, y)) + goto err_free_xy; + + return key; + +err_free_all: + BN_free(priv_key); +err_free_xy: + BN_free(x); + BN_free(y); + EC_KEY_free(key); + + return NULL; +} + + +static TEEC_Result ecdsa_sign_digest(ADBG_Case_t *c, + const struct ecdsa_key_vals *kv, + const struct crypto_buffer *in_dgst, + struct crypto_buffer *out_dgst) +{ + TEEC_Result res = TEEC_ERROR_OUT_OF_MEMORY; + EC_KEY *key = ecdsa_from_key_vals(kv); + const BIGNUM *r = NULL; + const BIGNUM *s = NULL; + ECDSA_SIG *sig = NULL; + + if (!ADBG_EXPECT_NOT_NULL(c, key)) + return TEEC_ERROR_OUT_OF_MEMORY; + + sig = ECDSA_do_sign(in_dgst->buffer, in_dgst->size, key); + if (!ADBG_EXPECT_NOT_NULL(c, sig)) + goto out; + + out_dgst->size = 2 * kv->key_size_bytes; + out_dgst->buffer = calloc(1, out_dgst->size); + if (!ADBG_EXPECT_NOT_NULL(c, out_dgst->buffer)) + goto out; + + ECDSA_SIG_get0(sig, &r, &s); + BN_bn2bin(r, out_dgst->buffer + out_dgst->size / 2 - BN_num_bytes(r)); + BN_bn2bin(s, out_dgst->buffer + out_dgst->size - BN_num_bytes(s)); + res = TEEC_SUCCESS; +out: + EC_KEY_free(key); + ECDSA_SIG_free(sig); + + return res; +} + +static bool ecdsa_verify_digest(ADBG_Case_t *c, + const struct ecdsa_key_vals *kv, + const void *digest, size_t digest_len, + const struct crypto_buffer *in_sdgst) +{ + EC_KEY *key = ecdsa_from_key_vals(kv); + ECDSA_SIG *sig = NULL; + BIGNUM *r = NULL; + BIGNUM *s = NULL; + bool res = false; + + if (!ADBG_EXPECT_NOT_NULL(c, key)) + return false; + + sig = ECDSA_SIG_new(); + if (!ADBG_EXPECT_NOT_NULL(c, sig)) + goto out; + + r = BN_bin2bn(in_sdgst->buffer, in_sdgst->size / 2, NULL); + if (!ADBG_EXPECT_NOT_NULL(c, r)) + goto out; + s = BN_bin2bn(in_sdgst->buffer + in_sdgst->size / 2, + in_sdgst->size / 2, NULL); + if (!ADBG_EXPECT_NOT_NULL(c, s)) { + BN_free(r); + goto out; + } + ECDSA_SIG_set0(sig, r, s); + + res = ECDSA_do_verify(digest, digest_len, sig, key); +out: + EC_KEY_free(key); + ECDSA_SIG_free(sig); + + return res; +} + +static RSA *rsa_from_key_vals(const struct rsa_key_vals *kv) +{ + BIGNUM *priv = bn_from_key_attr(&kv->priv); + BIGNUM *pub = bn_from_key_attr(&kv->pub); + BIGNUM *mod = bn_from_key_attr(&kv->mod); + RSA *key = RSA_new(); + + if (!key || !priv || !pub || !mod) + goto err_free_all; + + if (!RSA_set0_key(key, mod, pub, priv)) + goto err_free_all; + + return key; + +err_free_all: + BN_free(priv); + BN_free(pub); + BN_free(mod); + RSA_free(key); + + return NULL; +} + +static const EVP_MD *algo_to_md(uint32_t algo) +{ + switch (algo) { + case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: + return EVP_md5(); + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: + return EVP_sha1(); + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: + return EVP_sha224(); + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: + return EVP_sha256(); + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: + return EVP_sha384(); + case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: + case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: + return EVP_sha512(); + default: + return NULL; + } +} + +static bool padding_is_pkcs1_v1_5(uint32_t algo) +{ + 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: + return true; + default: + return false; + } +} + +static int ossl_err_cb(const char *str, size_t len, void *u) +{ + warnx("%*s", (int)len, str); + return 0; +} + +static void print_ossl_errors(const char *func) +{ + warnx("%s failed", func); + ERR_print_errors_cb(ossl_err_cb, NULL); +} + + +static TEEC_Result rsa_sign_digest(ADBG_Case_t *c, + const struct rsa_key_vals *kv, + uint32_t algo, + const struct crypto_buffer *in_dgst, + struct crypto_buffer *out_dgst) +{ + TEEC_Result res = TEEC_SUCCESS; + const EVP_MD *md = algo_to_md(algo); + RSA *key = NULL; + unsigned int sz = 0; + void *buf = NULL; + + if (!ADBG_EXPECT_NOT_NULL(c, md)) + return TEEC_ERROR_GENERIC; + + key = rsa_from_key_vals(kv); + if (!ADBG_EXPECT_NOT_NULL(c, key)) + return TEEC_ERROR_OUT_OF_MEMORY; + + sz = RSA_size(key); + buf = calloc(1, sz); + if (!ADBG_EXPECT_NOT_NULL(c, buf)) { + res = TEEC_ERROR_OUT_OF_MEMORY; + goto out; + } + + if (padding_is_pkcs1_v1_5(algo)) { + if (!RSA_sign(EVP_MD_nid(md), in_dgst->buffer, in_dgst->size, + buf, &sz, key)) { + print_ossl_errors("RSA_sign"); + res = TEEC_ERROR_GENERIC; + } + } else { + /* + * Important to use RSA_PSS_SALTLEN_DIGEST since the + * implementation may expect the size of the hash since the + * salt length isn't supplied as a paramter to + * TEE_AsymmetricVerifyDigest(). + */ + if (!RSA_padding_add_PKCS1_PSS_mgf1(key, buf, in_dgst->buffer, + md, md, + RSA_PSS_SALTLEN_DIGEST)) { + print_ossl_errors("RSA_padding_add_PKCS1_PSS_mgf1"); + res = TEEC_ERROR_GENERIC; + } else if (!RSA_private_encrypt(sz, buf, buf, key, + RSA_NO_PADDING)) { + print_ossl_errors("RSA_padding_add_PKCS1_PSS_mgf1"); + res = TEEC_ERROR_GENERIC; + } + } + + if (!res) { + out_dgst->buffer = buf; + out_dgst->size = sz; + } else { + free(buf); + } + +out: + RSA_free(key); + return res; + +} + +static bool rsa_verify_pss_digest(ADBG_Case_t *c, const EVP_MD *md, RSA *key, + const void *digest, + const struct crypto_buffer *in_sdgst) +{ + bool res = false; + void *buf; + int mlen; + + buf = calloc(1, RSA_size(key)); + if (!ADBG_EXPECT_NOT_NULL(c, buf)) + return false; + + mlen = RSA_public_decrypt(in_sdgst->size, in_sdgst->buffer, + buf, key, RSA_NO_PADDING); + if (mlen < 0) { + print_ossl_errors("RSA_public_decrypt"); + goto out; + } + res = RSA_verify_PKCS1_PSS_mgf1(key, digest, md, md, buf, -2); + if (!res) + print_ossl_errors("RSA_verify_PKCS1_PSS_mgf1"); + +out: + free(buf); + return res; + +} + +static bool rsa_verify_digest(ADBG_Case_t *c, const struct rsa_key_vals *kv, + uint32_t algo, + const void *digest, size_t digest_len, + const struct crypto_buffer *in_sdgst) +{ + const EVP_MD *md = algo_to_md(algo); + RSA *key = NULL; + bool res; + + if (!ADBG_EXPECT_NOT_NULL(c, md)) + return false; + + key = rsa_from_key_vals(kv); + if (!ADBG_EXPECT_NOT_NULL(c, key)) + return false; + + if (padding_is_pkcs1_v1_5(algo)) { + res = RSA_verify(EVP_MD_nid(md), digest, digest_len, + in_sdgst->buffer, in_sdgst->size, key); + if (!res) + print_ossl_errors("RSA_verify"); + } else { + res = rsa_verify_pss_digest(c, md, key, digest, in_sdgst); + } + + RSA_free(key); + return res; +} + +static TEEC_Result sign_digest(ADBG_Case_t *c, + const struct crypto_buffer *in_dgst, + struct crypto_buffer *out_dgst) +{ + const void *kv = NULL; + TEEC_Result res = TEEC_SUCCESS; + + if (!ADBG_EXPECT(c, TEE_HANDLE_NULL, saved_obh.obh2)) + return TEEC_ERROR_GENERIC; + + if (!ADBG_EXPECT_NOT(c, TEE_HANDLE_NULL, saved_obh.obh1)) + return TEEC_ERROR_GENERIC; + + kv = get_dsa_key_vals(saved_key_pub_attr[saved_obh.obh1]); + if (kv) { + res = dsa_sign_digest(c, kv, in_dgst, out_dgst); + goto out; + } + + kv = get_ecdsa_key_vals(saved_key_pub_attr[saved_obh.obh1]); + if (kv) { + res = ecdsa_sign_digest(c, kv, in_dgst, out_dgst); + goto out; + } + + kv = get_rsa_key_vals(saved_key_pub_attr[saved_obh.obh1]); + if (kv) { + res = rsa_sign_digest(c, kv, saved_alloc.algo, + in_dgst, out_dgst); + goto out; + } + + res = TEEC_ERROR_GENERIC; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, res); + return res; +} + +static bool verify_digest(ADBG_Case_t *c, const struct crypto_buffer *in_sdgst) +{ + const void *kv = NULL; + + if (!ADBG_EXPECT(c, TEE_HANDLE_NULL, saved_obh.obh2)) + return false; + + if (!ADBG_EXPECT_NOT(c, TEE_HANDLE_NULL, saved_obh.obh1)) + return false; + + kv = get_dsa_key_vals(saved_key_pub_attr[saved_obh.obh1]); + if (kv) + return dsa_verify_digest(c, kv, saved_digest.buffer, + saved_digest.size, in_sdgst); + kv = get_ecdsa_key_vals(saved_key_pub_attr[saved_obh.obh1]); + if (kv) + return ecdsa_verify_digest(c, kv, saved_digest.buffer, + saved_digest.size, in_sdgst); + kv = get_rsa_key_vals(saved_key_pub_attr[saved_obh.obh1]); + if (kv) + return rsa_verify_digest(c, kv, saved_alloc.algo, + saved_digest.buffer, + saved_digest.size, in_sdgst); + + return ADBG_EXPECT_TRUE(c, false); +} + +static TEEC_Result mac_compute_final( + ADBG_Case_t *c, TEEC_Session *s, + const void *full_data, size_t fdata_length, + struct crypto_buffer *mac) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t op1 = 3; + uint32_t ret_orig; + + res = Invoke_Crypto_AllocateOperation(c, s, CMD_Crypto_AllocateOperation, + saved_alloc.algo, TEE_MODE_MAC, + saved_alloc.obj_size, 0, op1); + + if (res != TEEC_SUCCESS) + goto exit; + + if (saved_obh.obh2 != TEE_HANDLE_NULL) { + res = Invoke_Crypto_SetOperationKey2(c, s, CMD_Crypto_SetOperationKey2, + op1, saved_obh.obh1, + saved_obh.obh2); + + if (res != TEEC_SUCCESS) + goto exit; + + } else if (saved_obh.obh1 != TEE_HANDLE_NULL) { + res = Invoke_Crypto_SetOperationKey(c, s, CMD_Crypto_SetOperationKey, + op1, saved_obh.obh1); + + if (res != TEEC_SUCCESS) + goto exit; + } + + res = Invoke_Crypto_MACInit(c, s, CMD_Crypto_MACInit, op1, + saved_mac_iv.buffer, saved_mac_iv.size); + + if (res != TEEC_SUCCESS) + goto exit; + + /* CMD_MACComputeFinal */ + /* Fill SharedMem1 with full_data */ + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM04, fdata_length, + TEEC_MEM_INPUT, fdata_length, + full_data, mem04_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM05, fdata_length, + TEEC_MEM_OUTPUT, mem05_exit) + + op.params[0].value.a = (uint32_t)op1; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM04, + SHARE_MEM04->size) + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM05, + SHARE_MEM05->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + + res = TEEC_InvokeCommand(s, CMD_Crypto_MACComputeFinal, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + mac->size = op.params[3].memref.size; + mac->buffer = malloc(mac->size); + memcpy(mac->buffer, SHARE_MEM05->buffer, mac->size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM05); +mem05_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM04); +mem04_exit: + Invoke_Crypto_FreeOperation(c, s, CMD_Crypto_FreeOperation, op1); +exit: + return res; +} + +static TEEC_Result cipher_do_final( + ADBG_Case_t *c, TEEC_Session *s, + const void *full_data, size_t fdata_length, + struct crypto_buffer *cipher) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t op1 = 3; + uint32_t ret_orig; + + res = Invoke_Crypto_AllocateOperation(c, s, CMD_Crypto_AllocateOperation, + saved_alloc.algo, + TEE_MODE_ENCRYPT, + saved_alloc.obj_size, 0, op1); + + if (res != TEEC_SUCCESS) + goto crypto_alloc; + + if (saved_obh.obh2 != TEE_HANDLE_NULL) { + res = Invoke_Crypto_SetOperationKey2(c, s, CMD_Crypto_SetOperationKey2, + op1, saved_obh.obh1, + saved_obh.obh2); + + if (res != TEEC_SUCCESS) + goto exit; + + } else if (saved_obh.obh1 != TEE_HANDLE_NULL) { + res = Invoke_Crypto_SetOperationKey(c, s, CMD_Crypto_SetOperationKey, + op1, saved_obh.obh1); + + if (res != TEEC_SUCCESS) + goto exit; + + } + + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM04, fdata_length, + TEEC_MEM_INPUT, + saved_cipher_iv.size, + saved_cipher_iv.buffer, + mem04_exit) + + op.params[0].value.a = (uint32_t)op1; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM04, + saved_cipher_iv.size) + + op.params[1].memref.offset = 0; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, CMD_Crypto_CipherInit, &op, &ret_orig); + + if (res != TEEC_SUCCESS) + goto mem05_exit; + + TEEC_ReleaseSharedMemory(SHARE_MEM04); + + /* CMD_CipherDoFinal */ + /* Fill SharedMem1 with full_data */ + ALLOCATE_AND_FILL_SHARED_MEMORY(s->ctx, SHARE_MEM04, fdata_length, + TEEC_MEM_INPUT, fdata_length, + full_data, mem04_exit) + ALLOCATE_SHARED_MEMORY(s->ctx, SHARE_MEM05, fdata_length, + TEEC_MEM_OUTPUT, mem05_exit) + + op.params[0].value.a = (uint32_t)op1; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM04, + SHARE_MEM04->size) + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, SHARE_MEM05, + SHARE_MEM05->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_MEMREF_PARTIAL_OUTPUT); + + res = TEEC_InvokeCommand(s, CMD_Crypto_CipherDoFinal, &op, &ret_orig); + + if (res == TEEC_SUCCESS) { + cipher->size = op.params[3].memref.size; + cipher->buffer = malloc(cipher->size); + memcpy(cipher->buffer, SHARE_MEM05->buffer, cipher->size); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM05); +mem05_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM04); +mem04_exit: +exit: + Invoke_Crypto_FreeOperation(c, s, CMD_Crypto_FreeOperation, op1); +crypto_alloc: + return res; +} + +static TEEC_Result Invoke_Crypto_EnsureIntermediateBufferSize(ADBG_Case_t *c, + TEEC_Session *s, + uint32_t cmd, + uint32_t oph) +{ + return Invoke_Simple_Function_v1(c, s, cmd, oph, 0); +} + +static TEEC_Result Invoke_AllocateTransientObject(ADBG_Case_t *c, + TEEC_Session *s, uint32_t cmd, + uint32_t obj_type, + uint32_t max_key_size, + uint32_t oph) +{ + return Invoke_Simple_Function_v2(c, s, cmd, oph, 0, obj_type, + max_key_size); +} + +static TEEC_Result Invoke_RestrictObjectUsage1(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, + uint32_t obj_handle, + uint32_t obj_usage) +{ + return Invoke_Simple_Function_v1(c, s, cmd, obj_handle, obj_usage); +} + +static TEEC_Result Invoke_StoreAttributeBuffer(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, uint32_t buffer, + const void *value_bufptr, + size_t value_size) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEE_SUCCESS; + uint32_t org = 0; + static TEEC_SharedMemory shm = { }; + + shm.size = value_size; + shm.flags = TEEC_MEM_INPUT; + res = TEEC_AllocateSharedMemory(sess->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + memcpy(shm.buffer, value_bufptr, shm.size); + + op.params[0].value.a = buffer; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, &shm, shm.size); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + TEEC_ReleaseSharedMemory(&shm); + + return res; +} + +static TEEC_Result Invoke_InitRefAttribute(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t attr, + uint32_t attr_id, uint32_t buffer) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, attr, attr_id, + buffer, 0); +} + +static TEEC_Result +Macro_StoreRefAttribute(ADBG_Case_t *c, TEEC_Session *sess, uint32_t attr, + uint32_t buffer, uint32_t attr_id, + const void *value_bufptr, size_t value_size) +{ + TEEC_Result res = TEE_SUCCESS; + + res = Invoke_StoreAttributeBuffer(c, sess, CMD_DS_StoreBuffer, + buffer, value_bufptr, value_size); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + res = Invoke_InitRefAttribute(c, sess, CMD_DS_InitRefAttribute, + attr, attr_id, buffer); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + return res; +} + +#endif /* XML_CRYPTO_API_H_ */ diff --git a/optee/optee_test/host/xtest/gp/include/xml_datastorage_api.h b/optee/optee_test/host/xtest/gp/include/xml_datastorage_api.h new file mode 100644 index 0000000..2d0169f --- /dev/null +++ b/optee/optee_test/host/xtest/gp/include/xml_datastorage_api.h @@ -0,0 +1,2017 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef XML_DATASTORAGE_API_H_ +#define XML_DATASTORAGE_API_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xml_common_api.h" +#include "xtest_helpers.h" +#include "xtest_test.h" + +#define declare_local_vars \ + uint32_t iObjectUsage1 __maybe_unused = 0; \ + uint32_t iObjectDataFlags1 __maybe_unused = 0; \ + uint32_t iObjectDataFlags2 __maybe_unused = 0; \ + uint32_t iObjectDataFlags3 __maybe_unused = 0; \ + uint32_t iHandleFlags1 __maybe_unused = 0; \ + uint32_t iAttributeList1 __maybe_unused = 0; + +#define iAttributeListEmpty 0u + +#define CLIENT_APP01 NULL + +#define TEEC_UNDEFINED_ERROR 0xDEADDEAD + +#define TEEC_ORIGIN_ANY_NOT_TRUSTED_APP 0x00000005 + +#define CMD_DS_AllocatePersistentObjectEnumerator 0x10000015 +#define CMD_DS_AllocateTransientObject 0x10000001 +#define CMD_DS_Check_ObjectInfo 0x100000C2 +#define CMD_DS_CloseAndDeletePersistentObject 0x1000102B +#define CMD_DS_CloseAndDeletePersistentObject1 0x1000102C +#define CMD_DS_CloseObject 0x10000011 +#define CMD_DS_CopyObjectAttributes 0x10000022 +#define CMD_DS_CopyObjectAttributes1 0x10000009 +#define CMD_DS_CreatePersistentObject 0x10000010 +#define CMD_DS_FreePersistentObjectEnumerator 0x10000016 +#define CMD_DS_FreeTransientObject 0x10000004 +#define CMD_DS_GenerateKey 0x1000100B +#define CMD_DS_GetNextPersistentObject 0x10000019 +#define CMD_DS_GetObjectBufferAttribute 0x10000008 +#define CMD_DS_GetObjectInfo 0x10000023 +#define CMD_DS_GetObjectInfo1 0x10000002 +#define CMD_DS_GetObjectValueAttribute 0x10000012 +#define CMD_DS_InitRefAttribute 0x10000006 +#define CMD_DS_InitValueAttribute 0x1000101F +#define CMD_DS_OpenPersistentObject 0x10000013 +#define CMD_DS_PopulateTransientObject 0x10000007 +#define CMD_DS_PopulateTransientObject_BadAttrBuffer 0x10000027 +#define CMD_DS_ReadObjectData 0x10001028 +#define CMD_DS_RenamePersistentObject 0x10000014 +#define CMD_DS_ResetPersistentObjectEnumerator 0x10000017 +#define CMD_DS_ResetTransientObject 0x10000005 +#define CMD_DS_RestrictObjectUsage 0x10000021 +#define CMD_DS_RestrictObjectUsage1 0x10000003 +#define CMD_DS_Retrieve_ObjectInfo 0x10000020 +#define CMD_DS_SeekObjectData 0x10000024 +#define CMD_DS_StartPersistentObjectEnumerator 0x10000018 +#define CMD_DS_StoreBuffer 0x1F0000CB +#define CMD_DS_TruncateObjectData 0x10000026 +#define CMD_DS_WriteObjectData 0x10000025 + +#define TYPE_NOT_EXISTING 0xA0000095 + +#define OFFSET_0 0 +#define OFFSET_1 1 +#define OFFSET_DOUBLE_MAX_INT32 0xFFFFFFFE +#define OFFSET_HIGH 900 +#define OFFSET_HIGH_PLUS_HIGH (OFFSET_HIGH + OFFSET_HIGH) +#define OFFSET_INITIAL_DATA_SIZE 1024 +#define OFFSET_INITIAL_DATA_SIZE_PLUS_LOW (OFFSET_INITIAL_DATA_SIZE + \ + OFFSET_LOW) +#define OFFSET_LOW 300 +#define OFFSET_LOW_PLUS_HIGH (OFFSET_LOW + OFFSET_HIGH) +#define OFFSET_LOW_PLUS_LOW (OFFSET_LOW + OFFSET_LOW) +#define OFFSET_MAX_INT32 0x7FFFFFFF +#define OFFSET_NEG_1 -1 + +#define BUFFER01_SIZE sizeof(BUFFER01) +#define BUFFER01_SIZE_EXTENDED_01 (BUFFER01_SIZE + OFFSET_LOW) +#define BUFFER01_SIZE_EXTENDED_02 (BUFFER01_SIZE + \ + OFFSET_LOW_PLUS_HIGH - \ + INITIAL_DATA_SIZE) +#define BUFFER_BIG_SIZE BIG_SIZE +#define BUFFER_SIZE_TOO_SMALL 10 +#define INITIAL_DATA_SIZE 1024 +#define LARGER_THAN_INITIAL 1500 +#define SHORTER_THAN_INITIAL 500 +#define SIZE_0 0 +#define SIZE_1 1 + +#define BUFFER_SIZE_TOO_SMALL 10 +#define SIZE_0 0 +#define SIZE_1 1 + +#define INITIAL_DATA_SIZE 1024 +#define LARGER_THAN_INITIAL 1500 +#define SHORTER_THAN_INITIAL 500 + +#define KEY_SIZE_TOO_LARGE 4096 +#define SIZE_AES_192 192 +#define SIZE_AES_256 256 +#define SIZE_DES3_128 128 +#define SIZE_DES3_192 192 +#define SIZE_DES_64 64 +#define SIZE_DH_KEYPAIR_1024 1024 +#define SIZE_DIGEST_MD5_16 16 +#define SIZE_DIGEST_SHA1_20 20 +#define SIZE_DIGEST_SHA224_28 28 +#define SIZE_DIGEST_SHA256_32 32 +#define SIZE_DIGEST_SHA384_48 48 +#define SIZE_DIGEST_SHA512_64 64 +#define SIZE_DSA_SHA1_KEYPAIR_768 768 +#define SIZE_DSA_SHA1_PUBLIC_KEY_768 768 +#define SIZE_DSA_SHA224_KEYPAIR_2048 2048 +#define SIZE_DSA_SHA224_PUBLIC_KEY_2048 2048 +#define SIZE_DSA_SHA256_KEYPAIR_2048 2048 +#define SIZE_DSA_SHA256_KEYPAIR_3072 3072 +#define SIZE_DSA_SHA256_PUBLIC_KEY_2048 2048 +#define SIZE_DSA_SHA256_PUBLIC_KEY_3072 3072 +#define SIZE_ECDH_P192 192 +#define SIZE_ECDH_P224 224 +#define SIZE_ECDH_P256 256 +#define SIZE_ECDH_P384 384 +#define SIZE_ECDH_P521 521 +#define SIZE_ECDSA_P192 192 +#define SIZE_ECDSA_P224 224 +#define SIZE_ECDSA_P256 256 +#define SIZE_ECDSA_P384 384 +#define SIZE_ECDSA_P521 521 +#define SIZE_GENERIC_SECRET_2048 2048 +#define SIZE_HMAC_MD5_256 256 +#define SIZE_HMAC_SHA1_256 256 +#define SIZE_HMAC_SHA224_256 256 +#define SIZE_HMAC_SHA256_512 512 +#define SIZE_HMAC_SHA384_512 512 +#define SIZE_HMAC_SHA512_512 512 +#define SIZE_RSA_KEYPAIR_1024 1024 +#define SIZE_RSA_KEYPAIR_2048 2048 +#define SIZE_RSA_PUBLIC_KEY_2048 2048 +#define SIZE_ZERO 0 +#define WRONG_ECC_SIZE 10 +#define WRONG_SIZE 5 + +#define TEE_ERROR_TOO_SHORT_BUFFER TEE_ERROR_SHORT_BUFFER + +#define TEE_ATTR_NONE (uint32_t)0 + +#define NOMINAL_CASE 0 + +#define BUFFER_ATTRIBUTE 0 +#define VALUE_ATTRIBUTE 1 + +#define TEE_ATTR_TEST_VALUE_A 0x0000FFFF +#define TEE_ATTR_TEST_VALUE_B 0xFFFF0000 + +#define OBJECT_HANDLE_NULL 0 +#define OBJECT_HANDLE_01 1 +#define OBJECT_HANDLE_02 2 +#define OBJECT_HANDLE_03 3 +#define OBJECT_HANDLE_INVALID 4 + +#define OBJECT_INFO_01 1 + +#define INVALID_HANDLE 0xFFFFFF01 +#define OBJECT_ENUM_NULL 0xFFFFFF00 +#define OBJECT_ENUM_01 0 + +#define ATTRIBUTE_01 0 +#define ATTRIBUTE_02 1 +#define ATTRIBUTE_03 2 +#define ATTRIBUTE_04 3 +#define ATTRIBUTE_05 4 +#define ATTRIBUTE_06 5 +#define ATTRIBUTE_NONE 0xFFFFFFFF + +#define BUFFER_01 0 +#define BUFFER_02 1 +#define BUFFER_03 2 +#define BUFFER_04 3 +#define BUFFER_05 4 +#define BUFFER_06 5 + +#define iObjectUsageNone 0 +#define iObjectUsageAllBitsOne 0xFFFFFFFF +#define iHandleFlagsNone 0 +#define iObjectDataFlagsNone 0 + +struct obj_info { + uint8_t obj_id[TEE_OBJECT_ID_MAX_LEN]; + uint32_t obj_id_len; + uint32_t obj_type; + uint32_t obj_size; + uint32_t max_obj_size; + uint32_t obj_usage; + uint32_t data_size; + uint32_t data_pos; + uint32_t handle_flags; +}; + +#define MAX_NUM_SAVED_OBJ_INFO 4 +static struct obj_info saved_obj_info[MAX_NUM_SAVED_OBJ_INFO]; + +static void *saved_obj_data; +static size_t saved_obj_data_size; + +static TEEC_SharedMemory share_mem[1]; +static TEEC_SharedMemory *SHARE_MEM01 = share_mem; +static TEEC_Session session[2]; +static TEEC_Session *SESSION01 = session; +static TEEC_Session *SESSION02 = session + 1; +static TEEC_Context context[2]; +static TEEC_Context *CONTEXT01 = context; +static TEEC_Context *CONTEXT02 = context + 1; + +#define STORAGE_ID_NOT_EXISTING 0x01234567 + +#define OBJECT_ID_01 "testobject01" +#define OBJECT_ID_02 "testobject02" +#define OBJECT_ID_03 "testobject03" +#define OBJECT_ID_SR "testobjectSR" +#define OBJECT_ID_TOO_LONG "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEFx" +#define EMPTY_BUFFER NULL + +#define BIG_ATTRIBUTE_BUFFER_SIZE 512 + +static const uint8_t +TEE_ATTR_RSA_PUBLIC_EXPONENT_VALUE_GEN_OUT_OF_RANGE_INF[] = { + 0x11, /* 17 */ +}; + +static const uint8_t TEE_ATTR_RSA_PUBLIC_EXPONENT_VALUE_GEN_NOT_ODD[] = { + 0x01, 0x00, 0x02, /* 65538 */ +}; + +static const uint8_t TEE_ATTR_RSA_PUBLIC_EXPONENT_VALUE_65537[] = { + 0x01, 0x00, 0x01, /* 65537 */ +}; + +static const uint8_t TEE_ATTR_RSA_PUBLIC_EXPONENT_VALUE_NOT_GEN_DEFAULT[] = { + 0x01, 0x01, 0xd1, /* 66001 */ +}; + +static const uint8_t TEE_ATTR_AES_192_VALUE01[] = { + 0xcd, 0xfe, 0x57, 0xb6, 0xb6, 0x2f, 0xae, 0x6b, + 0x04, 0x73, 0x40, 0xf1, 0x02, 0xd6, 0xa4, 0x8c, + 0x89, 0x5d, 0xad, 0xf2, 0x9d, 0x62, 0xef, 0x25, +}; + +static const uint8_t TEE_ATTR_AES_256_VALUE01[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4, +}; + +static const uint8_t TEE_ATTR_DES3_128_VALUE01[] = { + 0xcd, 0xfe, 0x57, 0xb6, 0xb6, 0x2f, 0xae, 0x6b, + 0x04, 0x73, 0x40, 0xf1, 0x02, 0xd6, 0xa4, 0x8c, +}; + +static const uint8_t TEE_ATTR_DES3_192_VALUE01[] = { + 0xcd, 0xfe, 0x57, 0xb6, 0xb6, 0x2f, 0xae, 0x6b, + 0x04, 0x73, 0x40, 0xf1, 0x02, 0xd6, 0xa4, 0x8c, + 0x89, 0x5d, 0xad, 0xf2, 0x9d, 0x62, 0xef, 0x25, +}; + +static const uint8_t TEE_ATTR_DES_64_VALUE01[] = { + 0xcd, 0xfe, 0x57, 0xb6, 0xb6, 0x2f, 0xae, 0x6b, +}; + +static const uint8_t TEE_ATTR_DH_BASE_2048_VALUE01[] = { + 0x34, 0x49, 0x90, 0x84, 0xea, 0x17, 0x68, 0x38, 0x67, 0x39, 0x4a, 0xda, 0x44, 0xd2, 0x86, 0xac, + 0x8c, 0x9c, 0x75, 0x50, 0x50, 0xdd, 0x7e, 0x8f, 0x1f, 0x42, 0x35, 0xb0, 0x46, 0x6e, 0x40, 0xa0, + 0x2f, 0x55, 0xa0, 0x9e, 0xb8, 0xf6, 0x8b, 0xc8, 0x62, 0x43, 0x7f, 0x5f, 0x45, 0xb6, 0x9f, 0xb1, + 0x2a, 0x92, 0x3e, 0xff, 0x93, 0xd1, 0xa9, 0x6c, 0x0a, 0x55, 0x51, 0x35, 0x91, 0xcc, 0xa8, 0x37, + 0x7c, 0xa2, 0xdd, 0xb5, 0x0d, 0xa0, 0xbd, 0x4a, 0xdd, 0xa1, 0x4d, 0x8b, 0xa2, 0x1e, 0x59, 0x73, + 0x49, 0x58, 0xb7, 0x23, 0xf2, 0x67, 0x3e, 0x50, 0x07, 0xab, 0xce, 0x8e, 0x4e, 0xf6, 0xdf, 0x09, + 0x98, 0x40, 0x04, 0x65, 0x25, 0x98, 0xa2, 0x93, 0x9b, 0x1e, 0x15, 0x1b, 0x8d, 0xbf, 0x0c, 0x87, + 0x80, 0xee, 0xa4, 0x0f, 0xd9, 0xe8, 0x08, 0xb6, 0xae, 0x1e, 0xcf, 0xfa, 0x73, 0x0d, 0x19, 0x3f, + 0x78, 0xc9, 0xeb, 0x7f, 0xd7, 0x28, 0x39, 0x1f, 0xa6, 0xec, 0x65, 0x15, 0xd2, 0x84, 0xc0, 0x8c, + 0x2a, 0xc1, 0x1b, 0x27, 0x3d, 0xc9, 0x70, 0x9d, 0xd7, 0x63, 0xb3, 0xe1, 0x8d, 0xbb, 0x9d, 0x5e, + 0x61, 0x1b, 0xc7, 0x83, 0xc3, 0x37, 0x38, 0x2a, 0xea, 0x6a, 0x66, 0x22, 0xe7, 0x04, 0x5b, 0x87, + 0x8b, 0x3d, 0xc5, 0x8c, 0x45, 0xd6, 0x50, 0x22, 0x80, 0xbe, 0xca, 0x16, 0x63, 0x7c, 0xdc, 0x0b, + 0xad, 0x35, 0x2e, 0xb5, 0x9b, 0xf7, 0x36, 0xfc, 0x6b, 0x17, 0xf0, 0xe2, 0x8c, 0xb6, 0x8f, 0x81, + 0x6d, 0xfa, 0x49, 0x8c, 0x5e, 0x70, 0x6e, 0x5d, 0x5f, 0xdd, 0x49, 0x81, 0xe4, 0x75, 0x2f, 0xe3, + 0x71, 0xb4, 0x2d, 0x10, 0xb5, 0xa2, 0x7e, 0x25, 0x42, 0x2e, 0x7c, 0x70, 0x00, 0x5e, 0xfc, 0x2e, + 0xc0, 0x3f, 0x21, 0x02, 0x6f, 0xe5, 0x00, 0x8b, 0xde, 0xee, 0x9b, 0x1a, 0x5a, 0x8a, 0x19, 0x40, +}; + +static const uint8_t TEE_ATTR_DH_BASE_VALUE01[] = { + 0x1c, 0xe0, 0xf6, 0x69, 0x26, 0x46, 0x11, 0x97, 0xef, 0x45, 0xc4, 0x65, 0x8b, 0x83, 0xb8, 0xab, + 0x04, 0xa9, 0x22, 0x42, 0x68, 0x50, 0x4d, 0x05, 0xb8, 0x19, 0x83, 0x99, 0xdd, 0x71, 0x37, 0x18, + 0xcc, 0x1f, 0x24, 0x5d, 0x47, 0x6c, 0xcf, 0x61, 0xa2, 0xf9, 0x34, 0x93, 0xf4, 0x1f, 0x55, 0x52, + 0x48, 0x65, 0x57, 0xe6, 0xd4, 0xca, 0xa8, 0x00, 0xd6, 0xd0, 0xdb, 0x3c, 0xbf, 0x5a, 0x95, 0x4b, + 0x20, 0x8a, 0x4e, 0xba, 0xf7, 0xe6, 0x49, 0xfb, 0x61, 0x24, 0xd8, 0xa2, 0x1e, 0xf2, 0xf2, 0x2b, + 0xaa, 0xae, 0x29, 0x21, 0x10, 0x19, 0x10, 0x51, 0x46, 0x47, 0x31, 0xb6, 0xcc, 0x3c, 0x93, 0xdc, + 0x6e, 0x80, 0xba, 0x16, 0x0b, 0x66, 0x64, 0xa5, 0x6c, 0xfa, 0x96, 0xea, 0xf1, 0xb2, 0x83, 0x39, + 0x8e, 0xb4, 0x61, 0x64, 0xe5, 0xe9, 0x43, 0x84, 0xee, 0x02, 0x24, 0xe7, 0x1f, 0x03, 0x7c, 0x23, +}; + +static const uint8_t TEE_ATTR_DH_PRIME_2048_VALUE01[] = { + 0xbb, 0xe9, 0x83, 0xd5, 0x01, 0xd1, 0xc8, 0xf3, 0x28, 0xff, 0x36, 0x1a, 0x82, 0xc8, 0x9b, 0x9f, + 0x72, 0xbe, 0x14, 0x20, 0x5e, 0x15, 0x13, 0xa0, 0x24, 0x89, 0x79, 0x0a, 0x67, 0x44, 0xd9, 0x05, + 0x59, 0x90, 0x51, 0x83, 0xf0, 0xed, 0xb5, 0x7d, 0x1a, 0x9a, 0xf4, 0x69, 0x6d, 0x82, 0xc3, 0x5f, + 0xe2, 0x97, 0x94, 0x59, 0xb9, 0xb2, 0x7a, 0x7b, 0xac, 0x6d, 0xba, 0x21, 0xe9, 0xb4, 0xe9, 0x64, + 0xd9, 0x88, 0x5c, 0xe0, 0xbf, 0x62, 0x5b, 0xd4, 0x4c, 0x0e, 0xc9, 0x0d, 0xab, 0x62, 0xe6, 0xf3, + 0x23, 0xf0, 0xa1, 0xd1, 0xda, 0x83, 0x66, 0x06, 0xd3, 0x77, 0x14, 0x00, 0x76, 0x11, 0x21, 0xb6, + 0xa5, 0x6a, 0xc5, 0x4d, 0x38, 0xbc, 0x50, 0x6a, 0x9f, 0x89, 0xd6, 0x91, 0x73, 0xee, 0x2f, 0x77, + 0x45, 0xeb, 0xcf, 0x02, 0x66, 0xd5, 0xd6, 0xc9, 0x94, 0x24, 0x6b, 0x99, 0x88, 0x0d, 0x5f, 0xe6, + 0x19, 0x53, 0x30, 0x3d, 0x01, 0x40, 0x9f, 0x4c, 0x75, 0xae, 0x7b, 0xfd, 0xd8, 0xea, 0x2d, 0x77, + 0x6d, 0x0a, 0x3a, 0x61, 0x61, 0xcb, 0x28, 0x4d, 0xa6, 0xc9, 0x2c, 0xbe, 0x45, 0x9e, 0xc5, 0xee, + 0x42, 0xcf, 0xde, 0x86, 0x68, 0x01, 0x42, 0x34, 0xc3, 0x63, 0xdd, 0xeb, 0x52, 0x44, 0xe2, 0x5e, + 0xef, 0xdd, 0x96, 0x17, 0x66, 0x90, 0xc4, 0xc9, 0xd8, 0x52, 0x45, 0x08, 0xc2, 0xc2, 0x6a, 0x44, + 0x73, 0x16, 0xad, 0x12, 0xbf, 0x90, 0xac, 0x48, 0xd3, 0xd0, 0x65, 0x8a, 0x18, 0xc9, 0x6c, 0x23, + 0x24, 0x61, 0x42, 0x01, 0xc5, 0xe5, 0x8e, 0x1d, 0x85, 0xb7, 0x40, 0x72, 0x53, 0x6d, 0x3c, 0x15, + 0x51, 0x52, 0x09, 0x38, 0x05, 0xc7, 0xf5, 0x8e, 0x9d, 0xa0, 0xf0, 0xb9, 0x41, 0x50, 0x54, 0xc6, + 0x70, 0x46, 0x31, 0x3e, 0xc6, 0x4d, 0x6f, 0x48, 0x85, 0xa4, 0x6b, 0x16, 0x15, 0x86, 0xa6, 0x99, +}; + +static const uint8_t TEE_ATTR_DH_PRIME_VALUE01[] = { + 0xe0, 0x01, 0xe8, 0x96, 0x7d, 0xb4, 0x93, 0x53, 0xe1, 0x6f, 0x8e, 0x89, 0x22, 0x0c, 0xce, 0xfc, + 0x5c, 0x5f, 0x12, 0xe3, 0xdf, 0xf8, 0xf1, 0xd1, 0x49, 0x90, 0x12, 0xe6, 0xef, 0x53, 0xe3, 0x1f, + 0x02, 0xea, 0xcc, 0x5a, 0xdd, 0xf3, 0x37, 0x89, 0x35, 0xc9, 0x5b, 0x21, 0xea, 0x3d, 0x6f, 0x1c, + 0xd7, 0xce, 0x63, 0x75, 0x52, 0xec, 0x38, 0x6c, 0x0e, 0x34, 0xf7, 0x36, 0xad, 0x95, 0x17, 0xef, + 0xfe, 0x5e, 0x4d, 0xa7, 0xa8, 0x6a, 0xf9, 0x0e, 0x2c, 0x22, 0x8f, 0xe4, 0xb9, 0xe6, 0xd8, 0xf8, + 0xf0, 0x2d, 0x20, 0xaf, 0x78, 0xab, 0xb6, 0x92, 0xac, 0xbc, 0x4b, 0x23, 0xfa, 0xf2, 0xc5, 0xcc, + 0xd4, 0x9a, 0x0c, 0x9a, 0x8b, 0xcd, 0x91, 0xac, 0x0c, 0x55, 0x92, 0x01, 0xe6, 0xc2, 0xfd, 0x1f, + 0x47, 0xc2, 0xcb, 0x2a, 0x88, 0xa8, 0x3c, 0x21, 0x0f, 0xc0, 0x54, 0xdb, 0x29, 0x2d, 0xbc, 0x45, +}; + +static const uint8_t TEE_ATTR_DH_PRIVATE_VALUE_256_2048_VALUE01[] = { + 0xd7, 0x2a, 0x8b, 0x81, 0x2b, 0x22, 0x7a, 0x7e, 0x0e, 0xc1, 0xbe, 0x32, 0xfe, 0xdc, 0xda, 0xf4, + 0xda, 0x4e, 0xe2, 0xe3, 0x6e, 0x73, 0x40, 0x28, 0x72, 0xf9, 0x46, 0x20, 0xb6, 0xd4, 0xb1, 0xdc, +}; + +static const uint8_t TEE_ATTR_DH_PRIVATE_VALUE_VALUE01[] = { + 0x53, 0x8d, 0x3d, 0x64, 0x27, 0x4a, 0x40, 0x05, + 0x9b, 0x9c, 0x26, 0xe9, 0x13, 0xe6, 0x91, 0x53, + 0x23, 0x7b, 0x55, 0x83, +}; + +static const uint8_t TEE_ATTR_DH_PUBLIC_VALUE_2048_VALUE01[] = { + 0xb4, 0x0d, 0x9a, 0x68, 0x60, 0xc3, 0x0f, 0x0c, 0x2a, 0xd3, 0x30, 0x4f, 0x4b, 0x54, 0x81, 0x26, + 0xb9, 0xba, 0x58, 0x3c, 0xeb, 0x77, 0x45, 0xe1, 0x10, 0xc6, 0xfa, 0xce, 0xb9, 0xc6, 0x91, 0x55, + 0x21, 0x3b, 0xea, 0x8a, 0x86, 0xcd, 0x5b, 0x9f, 0xc1, 0x9f, 0x64, 0xcc, 0x0d, 0x66, 0xfe, 0x33, + 0x21, 0x28, 0xbc, 0x7f, 0xfe, 0xaf, 0xd3, 0x18, 0x8c, 0x52, 0x73, 0xb4, 0xe7, 0xba, 0x50, 0x5e, + 0x98, 0x1e, 0xac, 0x7d, 0xb5, 0xf1, 0x2a, 0xd9, 0x50, 0x47, 0xfb, 0x6f, 0x1e, 0x34, 0xaa, 0x9d, + 0xff, 0x31, 0x20, 0xb8, 0x55, 0x0f, 0xc5, 0x71, 0xb9, 0x34, 0x9f, 0x23, 0x39, 0xcd, 0x96, 0xde, + 0x9c, 0x11, 0x9d, 0x0e, 0x6b, 0xe1, 0x0f, 0x69, 0x0a, 0x77, 0xc7, 0x5a, 0xed, 0xc5, 0x2a, 0x95, + 0x90, 0xc7, 0x92, 0x94, 0xf8, 0x03, 0x81, 0xaa, 0xfc, 0x34, 0x3c, 0xec, 0x6b, 0x62, 0x4d, 0x03, + 0x7a, 0x6a, 0x7c, 0x92, 0xf7, 0x2c, 0x38, 0x84, 0x33, 0x7e, 0xf3, 0xfd, 0xae, 0x20, 0xb0, 0xc6, + 0x60, 0x76, 0x53, 0x60, 0xf3, 0x77, 0x50, 0x96, 0x0d, 0xbc, 0x40, 0xe4, 0x99, 0xfc, 0xe5, 0x79, + 0xda, 0x3b, 0x65, 0x98, 0xfe, 0x28, 0x68, 0x68, 0xc6, 0x87, 0xbb, 0xc8, 0x12, 0x7c, 0x1d, 0x0b, + 0x42, 0xe9, 0xb4, 0x6c, 0xd9, 0x1b, 0x23, 0xba, 0x34, 0x59, 0x3b, 0x86, 0x60, 0x45, 0xb6, 0x25, + 0x48, 0x53, 0x7c, 0xc7, 0xf8, 0x24, 0xb8, 0xf6, 0x71, 0xb5, 0x42, 0x98, 0xde, 0x8c, 0x6e, 0x61, + 0x7e, 0x1b, 0xf9, 0xab, 0x52, 0x4f, 0x03, 0xd1, 0xde, 0x30, 0xb4, 0x85, 0xa7, 0x3b, 0x97, 0xda, + 0x97, 0x5f, 0xbe, 0x8a, 0xd6, 0x2e, 0x19, 0x91, 0x29, 0xb4, 0x66, 0x6d, 0x03, 0x73, 0x43, 0xbe, + 0x13, 0x47, 0x82, 0x20, 0x80, 0x21, 0xf2, 0x3e, 0xbc, 0x66, 0xa6, 0x07, 0x38, 0x71, 0x77, 0xe4, +}; + +static const uint8_t TEE_ATTR_DH_PUBLIC_VALUE_VALUE01[] = { + 0xbb, 0xe9, 0x18, 0xdd, 0x4b, 0x2b, 0x94, 0x1b, 0x10, 0x0e, 0x88, 0x35, 0x28, 0x68, 0xfc, 0x62, + 0x04, 0x38, 0xa6, 0xdb, 0x32, 0xa6, 0x9e, 0xee, 0x6c, 0x6f, 0x45, 0x1c, 0xa3, 0xa6, 0xd5, 0x37, + 0x77, 0x75, 0x5b, 0xc1, 0x37, 0x0a, 0xce, 0xfe, 0x2b, 0x8f, 0x13, 0xa9, 0x14, 0x2c, 0x5b, 0x44, + 0x15, 0x78, 0x86, 0x30, 0xd6, 0x95, 0xb1, 0x92, 0x20, 0x63, 0xa3, 0xcf, 0x9d, 0xef, 0x65, 0x61, + 0x27, 0x4d, 0x24, 0x01, 0xe7, 0xa1, 0x45, 0xf2, 0xd8, 0xb9, 0x3a, 0x45, 0x17, 0xf4, 0x19, 0xd0, + 0x5e, 0xf8, 0xcb, 0x35, 0x59, 0x37, 0x9d, 0x04, 0x20, 0xa3, 0xbf, 0x02, 0xad, 0xfe, 0xa8, 0x60, + 0xb2, 0xc3, 0xee, 0x85, 0x58, 0x90, 0xf3, 0xb5, 0x57, 0x2b, 0xb4, 0xef, 0xd7, 0x8f, 0x37, 0x68, + 0x78, 0x7c, 0x71, 0x52, 0x9d, 0x5e, 0x0a, 0x61, 0x4f, 0x09, 0x89, 0x92, 0x39, 0xf7, 0x4b, 0x01, +}; + +static const uint8_t TEE_ATTR_DH_PUBLIC_VALUE_VALUE02[] = { + 0xa3, 0xf5, 0x7d, 0xbe, 0x9e, 0x2f, 0x0a, 0xda, 0xa9, 0x4e, 0x4e, 0x6a, 0xf0, 0xe0, 0x71, 0x47, + 0x0e, 0x2e, 0x41, 0x2e, 0xde, 0x73, 0x2a, 0x62, 0x14, 0xc3, 0x7c, 0x26, 0xd4, 0xe9, 0x9a, 0x54, + 0xba, 0x3d, 0xe7, 0x49, 0x85, 0x95, 0x0e, 0xe9, 0x14, 0xb2, 0x90, 0x22, 0x91, 0xdc, 0xff, 0x61, + 0xb2, 0xfc, 0xd1, 0xd0, 0x1b, 0x11, 0x14, 0xb6, 0x02, 0x64, 0x2b, 0x26, 0x5d, 0x88, 0xea, 0x8d, + 0xbb, 0xe2, 0x07, 0x0b, 0x48, 0xfb, 0x01, 0x53, 0x55, 0x1e, 0x59, 0x51, 0x36, 0xf2, 0xf9, 0xd1, + 0x97, 0xfb, 0x66, 0x12, 0x84, 0x5d, 0xed, 0xb8, 0x9b, 0x2d, 0x3e, 0x2b, 0x8c, 0xeb, 0x2a, 0x72, + 0x40, 0x9d, 0x55, 0x4c, 0xed, 0xeb, 0x55, 0x02, 0xff, 0x8c, 0xb0, 0x2e, 0x03, 0x65, 0x3f, 0x41, + 0xb1, 0xac, 0xa3, 0x30, 0x6b, 0xff, 0x6d, 0xf4, 0x6d, 0xe6, 0xe1, 0x0f, 0x86, 0x7c, 0x43, 0x64, +}; + +static const uint8_t TEE_ATTR_DH_SUBPRIME_VALUE01[] = { + 0x84, 0xbb, 0x73, 0xca, 0x02, 0xa8, 0x6e, 0x8b, + 0xef, 0x44, 0x72, 0x06, 0xe0, 0xbe, 0xd2, 0x0e, + 0xeb, 0x47, 0x9f, 0x4d, +}; + +static const uint8_t TEE_ATTR_DSA_BASE_2048_VALUE01[] = { + 0x20, 0x42, 0x09, 0x4c, 0xcb, 0xc8, 0xb8, 0x72, 0x3f, 0xc9, 0x28, 0xc1, 0x2f, 0xda, 0x67, 0x1b, + 0x83, 0x29, 0x5e, 0x99, 0xc7, 0x43, 0x57, 0x6f, 0x44, 0x50, 0x4b, 0xe1, 0x18, 0x63, 0x23, 0x31, + 0x9b, 0x50, 0x02, 0xd2, 0x4f, 0x17, 0x3d, 0xf9, 0x09, 0xea, 0x24, 0x1d, 0x6e, 0xa5, 0x28, 0x99, + 0x04, 0xee, 0x46, 0x36, 0x20, 0x4b, 0x2f, 0xbe, 0x94, 0xb0, 0x68, 0xfe, 0x09, 0x3f, 0x79, 0x62, + 0x57, 0x95, 0x49, 0x55, 0x1d, 0x3a, 0xf2, 0x19, 0xad, 0x8e, 0xd1, 0x99, 0x39, 0xef, 0xf8, 0x6b, + 0xce, 0xc8, 0x34, 0xde, 0x2f, 0x2f, 0x78, 0x59, 0x6e, 0x89, 0xe7, 0xcb, 0x52, 0xc5, 0x24, 0xe1, + 0x77, 0x09, 0x8a, 0x56, 0xc2, 0x32, 0xeb, 0x1f, 0x56, 0x3a, 0xa8, 0x4b, 0xc6, 0xb0, 0x26, 0xde, + 0xee, 0x6f, 0xf5, 0x1c, 0xb4, 0x41, 0xe0, 0x80, 0xf2, 0xda, 0xfa, 0xea, 0x1c, 0xed, 0x86, 0x42, + 0x7d, 0x1c, 0x34, 0x6b, 0xe5, 0x5c, 0x66, 0x80, 0x3d, 0x4b, 0x76, 0xd1, 0x33, 0xcd, 0x44, 0x5b, + 0x4c, 0x34, 0x82, 0xfa, 0x41, 0x50, 0x23, 0x46, 0x3c, 0x9b, 0xf3, 0x0f, 0x2f, 0x78, 0x42, 0x23, + 0xe2, 0x60, 0x57, 0xd3, 0xaa, 0x0d, 0x7f, 0xbb, 0x66, 0x06, 0x30, 0xc5, 0x2e, 0x49, 0xd4, 0xa0, + 0x32, 0x5c, 0x73, 0x89, 0xe0, 0x72, 0xaa, 0x34, 0x9f, 0x13, 0xc9, 0x66, 0xe1, 0x59, 0x75, 0x2f, + 0xbb, 0x71, 0xe9, 0x33, 0x68, 0x90, 0xf9, 0x32, 0x43, 0xfa, 0x6e, 0x72, 0xd2, 0x99, 0x36, 0x5e, + 0xe5, 0xb3, 0xfe, 0x26, 0x6e, 0xbf, 0x11, 0x10, 0x56, 0x8f, 0xee, 0x44, 0x25, 0xc8, 0x47, 0xb5, + 0x02, 0x10, 0xbd, 0x48, 0x4b, 0x97, 0x43, 0x1a, 0x42, 0x85, 0x6a, 0xdc, 0xa3, 0xe7, 0xd1, 0xa9, + 0xc9, 0xc6, 0x75, 0xc7, 0xe2, 0x66, 0x91, 0x83, 0x20, 0xdd, 0x5a, 0x78, 0xa4, 0x8c, 0x48, 0xa9, +}; + +static const uint8_t TEE_ATTR_DSA_BASE_3072_VALUE01[] = { + 0x11, 0x0a, 0xfe, 0xbb, 0x12, 0xc7, 0xf8, 0x62, 0xb6, 0xde, 0x03, 0xd4, 0x7f, 0xdb, 0xc3, 0x32, 0x6e, 0x0d, 0x4d, 0x31, 0xb1, 0x2a, 0x8c, 0xa9, + 0x5b, 0x2d, 0xee, 0x21, 0x23, 0xbc, 0xc6, 0x67, 0xd4, 0xf7, 0x2c, 0x1e, 0x72, 0x09, 0x76, 0x7d, 0x27, 0x21, 0xf9, 0x5f, 0xbd, 0x9a, 0x4d, 0x03, + 0x23, 0x6d, 0x54, 0x17, 0x4f, 0xbf, 0xaf, 0xf2, 0xc4, 0xff, 0x7d, 0xea, 0xe4, 0x73, 0x8b, 0x20, 0xd9, 0xf3, 0x7b, 0xf0, 0xa1, 0x13, 0x4c, 0x28, + 0x8b, 0x42, 0x0a, 0xf0, 0xb5, 0x79, 0x2e, 0x47, 0xa9, 0x25, 0x13, 0xc0, 0x41, 0x3f, 0x34, 0x6a, 0x4e, 0xdb, 0xab, 0x2c, 0x45, 0xbd, 0xca, 0x13, + 0xf5, 0x34, 0x1c, 0x2b, 0x55, 0xb8, 0xba, 0x54, 0x93, 0x2b, 0x92, 0x17, 0xb5, 0xa8, 0x59, 0xe5, 0x53, 0xf1, 0x4b, 0xb8, 0xc1, 0x20, 0xfb, 0xb9, + 0xd9, 0x99, 0x09, 0xdf, 0xf5, 0xea, 0x68, 0xe1, 0x4b, 0x37, 0x99, 0x64, 0xfd, 0x3f, 0x38, 0x61, 0xe5, 0xba, 0x5c, 0xc9, 0x70, 0xc4, 0xa1, 0x80, + 0xee, 0xf5, 0x44, 0x28, 0x70, 0x39, 0x61, 0x02, 0x1e, 0x7b, 0xd6, 0x8c, 0xb6, 0x37, 0x92, 0x7b, 0x8c, 0xbe, 0xe6, 0x80, 0x5f, 0xa2, 0x72, 0x85, + 0xbf, 0xee, 0x4d, 0x1e, 0xf7, 0x0e, 0x02, 0xc1, 0xa1, 0x8a, 0x7c, 0xd7, 0x8b, 0xef, 0x1d, 0xd9, 0xcd, 0xad, 0x45, 0xdd, 0xe9, 0xcd, 0x69, 0x07, + 0x55, 0x05, 0x0f, 0xc4, 0x66, 0x29, 0x37, 0xee, 0x1d, 0x6f, 0x4d, 0xb1, 0x28, 0x07, 0xcc, 0xc9, 0x5b, 0xc4, 0x35, 0xf1, 0x1b, 0x71, 0xe7, 0x08, + 0x60, 0x48, 0xb1, 0xda, 0xb5, 0x91, 0x3c, 0x60, 0x55, 0x01, 0x2d, 0xe8, 0x2e, 0x43, 0xa4, 0xe5, 0x0c, 0xf9, 0x3f, 0xef, 0xf5, 0xdc, 0xab, 0x81, + 0x4a, 0xbc, 0x22, 0x4c, 0x5e, 0x00, 0x25, 0xbd, 0x86, 0x8c, 0x3f, 0xc5, 0x92, 0x04, 0x1b, 0xba, 0x04, 0x74, 0x7c, 0x10, 0xaf, 0x51, 0x3f, 0xc3, + 0x6e, 0x4d, 0x91, 0xc6, 0x3e, 0xe5, 0x25, 0x34, 0x22, 0xcf, 0x40, 0x63, 0x39, 0x8d, 0x77, 0xc5, 0x2f, 0xcb, 0x01, 0x14, 0x27, 0xcb, 0xfc, 0xfa, + 0x67, 0xb1, 0xb2, 0xc2, 0xd1, 0xaa, 0x4a, 0x3d, 0xa7, 0x26, 0x45, 0xcb, 0x1c, 0x76, 0x70, 0x36, 0x05, 0x4e, 0x2f, 0x31, 0xf8, 0x86, 0x65, 0xa5, + 0x44, 0x61, 0xc8, 0x85, 0xfb, 0x32, 0x19, 0xd5, 0xad, 0x87, 0x48, 0xa0, 0x11, 0x58, 0xf6, 0xc7, 0xc0, 0xdf, 0x5a, 0x8c, 0x90, 0x8b, 0xa8, 0xc3, + 0xe5, 0x36, 0x82, 0x24, 0x28, 0x88, 0x6c, 0x7b, 0x50, 0x0b, 0xbc, 0x15, 0xb4, 0x9d, 0xf7, 0x46, 0xb9, 0xde, 0x5a, 0x78, 0xfe, 0x3b, 0x4f, 0x69, + 0x91, 0xd0, 0x11, 0x0c, 0x3c, 0xbf, 0xf4, 0x58, 0x03, 0x9d, 0xc3, 0x62, 0x61, 0xcf, 0x46, 0xaf, 0x4b, 0xc2, 0x51, 0x53, 0x68, 0xf4, 0xab, 0xb7, +}; + +static const uint8_t TEE_ATTR_DSA_BASE_768_VALUE01[] = { + 0x9a, 0x09, 0x32, 0xb3, 0x8c, 0xb2, 0x10, 0x5b, 0x93, 0x00, 0xdc, 0xb8, 0x66, 0xc0, + 0x66, 0xd9, 0xce, 0xc6, 0x43, 0x19, 0x2f, 0xcb, 0x28, 0x34, 0xa1, 0x23, 0x9d, 0xba, 0x28, + 0xbd, 0x09, 0xfe, 0x01, 0x00, 0x1e, 0x04, 0x51, 0xf9, 0xd6, 0x35, 0x1f, 0x6e, 0x56, 0x4a, + 0xfb, 0xc8, 0xf8, 0xc3, 0x9b, 0x10, 0x59, 0x86, 0x3e, 0xbd, 0x09, 0x85, 0x09, 0x0b, 0xd5, + 0x5c, 0x82, 0x8e, 0x9f, 0xc1, 0x57, 0xac, 0x7d, 0xa3, 0xcf, 0xc2, 0x89, 0x2a, 0x0e, 0xd9, + 0xb9, 0x32, 0x39, 0x05, 0x82, 0xf2, 0x97, 0x1e, 0x4a, 0x0c, 0x48, 0x3e, 0x06, 0x22, 0xd7, + 0x31, 0x66, 0xbf, 0x62, 0xa5, 0x9f, 0x26, +}; + +static const uint8_t TEE_ATTR_DSA_PRIME_2048_VALUE01[] = { + 0xaa, 0x81, 0x5c, 0x9d, 0xb1, 0xc4, 0xd3, 0xd2, 0x77, 0x3c, 0x7d, 0x0d, 0x4d, 0x1d, 0xa7, 0x5e, + 0xcf, 0xc4, 0xa3, 0x9e, 0x97, 0xd5, 0xfa, 0x19, 0x1f, 0xfe, 0xc8, 0xb1, 0x49, 0x0a, 0x29, 0x0c, + 0xe3, 0x35, 0xe5, 0xce, 0x87, 0xea, 0x62, 0x0a, 0x8a, 0x17, 0xde, 0x0b, 0xb6, 0x47, 0x14, 0xe2, + 0xec, 0x84, 0x0b, 0xf0, 0x0e, 0x6e, 0xbd, 0xb4, 0xff, 0xb4, 0xe3, 0x24, 0xca, 0x07, 0xc3, 0xc8, + 0x71, 0x73, 0x09, 0xaf, 0x14, 0x10, 0x36, 0x2a, 0x77, 0x2c, 0x9a, 0xdd, 0x83, 0x8b, 0x2b, 0x0c, + 0xae, 0x1e, 0x90, 0xab, 0x44, 0x8a, 0xda, 0xbd, 0xac, 0xd2, 0xe5, 0xdf, 0x59, 0xc4, 0x18, 0x7a, + 0x32, 0xa2, 0x37, 0x19, 0xd6, 0xc5, 0x7e, 0x94, 0x00, 0x88, 0x53, 0x83, 0xbf, 0x8f, 0x06, 0x6f, + 0x23, 0xb9, 0x41, 0x92, 0x0d, 0x54, 0xc3, 0x5b, 0x4f, 0x7c, 0xc5, 0x04, 0x4f, 0x3b, 0x40, 0xf1, + 0x70, 0x46, 0x95, 0x63, 0x07, 0xb7, 0x48, 0xe8, 0x40, 0x73, 0x28, 0x44, 0xd0, 0x0a, 0x9c, 0xe6, + 0xec, 0x57, 0x14, 0x29, 0x3b, 0x62, 0x65, 0x14, 0x7f, 0x15, 0xc6, 0x7f, 0x4b, 0xe3, 0x8b, 0x08, + 0x2b, 0x55, 0xfd, 0xea, 0xdb, 0x61, 0x24, 0x68, 0x9f, 0xb7, 0x6f, 0x9d, 0x25, 0xcc, 0x28, 0xb8, + 0xea, 0xa9, 0x8b, 0x56, 0x2d, 0x5c, 0x10, 0x11, 0xe0, 0xdc, 0xf9, 0xb3, 0x99, 0x23, 0x24, 0x0d, + 0x33, 0x2d, 0x89, 0xdc, 0x96, 0x03, 0xb7, 0xbd, 0xdd, 0x0c, 0x70, 0xb8, 0x3c, 0xaa, 0x29, 0x05, + 0x63, 0x1b, 0x1c, 0x83, 0xca, 0xbb, 0xae, 0x6c, 0x0c, 0x0c, 0x2e, 0xfe, 0x8f, 0x58, 0x13, 0x1e, + 0xd8, 0x35, 0x1b, 0xf9, 0x3e, 0x87, 0x5f, 0x6a, 0x73, 0xa9, 0x3c, 0xba, 0xd4, 0x70, 0x14, 0x1a, + 0x26, 0x87, 0xfb, 0xac, 0xf2, 0xd7, 0x1c, 0x8d, 0xde, 0xe9, 0x71, 0xad, 0x66, 0x07, 0x29, 0xad, +}; + +static const uint8_t TEE_ATTR_DSA_PRIME_3072_VALUE01[] = { + 0xc7, 0xb8, 0x6d, 0x70, 0x44, 0x21, 0x8e, 0x36, 0x74, 0x53, 0xd2, 0x10, 0xe7, 0x64, 0x33, 0xe4, 0xe2, 0x7a, 0x98, 0x3d, 0xb1, 0xc5, 0x60, 0xbb, + 0x97, 0x55, 0xa8, 0xfb, 0x7d, 0x81, 0x99, 0x12, 0xc5, 0x6c, 0xfe, 0x00, 0x2a, 0xb1, 0xff, 0x3f, 0x72, 0x16, 0x5b, 0x94, 0x3c, 0x0b, 0x28, 0xed, + 0x46, 0x03, 0x9a, 0x07, 0xde, 0x50, 0x7d, 0x7a, 0x29, 0xf7, 0x38, 0x60, 0x3d, 0xec, 0xd1, 0x27, 0x03, 0x80, 0xa4, 0x1f, 0x97, 0x1f, 0x25, 0x92, + 0x66, 0x1a, 0x64, 0xba, 0x2f, 0x35, 0x1d, 0x9a, 0x69, 0xe5, 0x1a, 0x88, 0x8a, 0x05, 0x15, 0x6b, 0x7f, 0xe1, 0x56, 0x3c, 0x4b, 0x77, 0xee, 0x93, + 0xa4, 0x49, 0x49, 0x13, 0x84, 0x38, 0xa2, 0xab, 0x8b, 0xdc, 0xfc, 0x49, 0xb4, 0xe7, 0x8d, 0x1c, 0xde, 0x76, 0x6e, 0x54, 0x98, 0x47, 0x60, 0x05, + 0x7d, 0x76, 0xcd, 0x74, 0x0c, 0x94, 0xa4, 0xdd, 0x25, 0xa4, 0x6a, 0xa7, 0x7b, 0x18, 0xe9, 0xd7, 0x07, 0xd6, 0x73, 0x84, 0x97, 0xd4, 0xea, 0xc3, + 0x64, 0xf4, 0x79, 0x2d, 0x97, 0x66, 0xa1, 0x6a, 0x0e, 0x23, 0x48, 0x07, 0xe9, 0x6b, 0x8c, 0x64, 0xd4, 0x04, 0xbb, 0xdb, 0x87, 0x6e, 0x39, 0xb5, + 0x79, 0x9e, 0xf5, 0x3f, 0xe6, 0xcb, 0x9b, 0xab, 0x62, 0xef, 0x19, 0xfd, 0xcc, 0x2b, 0xdd, 0x90, 0x5b, 0xed, 0xa1, 0x3b, 0x9e, 0xf7, 0xac, 0x35, + 0xf1, 0xf5, 0x57, 0xcb, 0x0d, 0xc4, 0x58, 0xc0, 0x19, 0xe2, 0xbc, 0x19, 0xa9, 0xf5, 0xdf, 0xc1, 0xe4, 0xec, 0xa9, 0xe6, 0xd4, 0x66, 0x56, 0x41, + 0x24, 0x30, 0x4a, 0x31, 0xf0, 0x38, 0x60, 0x5a, 0x3e, 0x34, 0x2d, 0xa0, 0x1b, 0xe1, 0xc2, 0xb5, 0x45, 0x61, 0x0e, 0xdd, 0x2c, 0x13, 0x97, 0xa3, + 0xc8, 0x39, 0x65, 0x88, 0xc6, 0x32, 0x9e, 0xfe, 0xb4, 0xe1, 0x65, 0xaf, 0x5b, 0x36, 0x8a, 0x39, 0xa8, 0x8e, 0x48, 0x88, 0xe3, 0x9f, 0x40, 0xbb, + 0x3d, 0xe4, 0xeb, 0x14, 0x16, 0x67, 0x2f, 0x99, 0x9f, 0xea, 0xd3, 0x7a, 0xef, 0x1c, 0xa9, 0x64, 0x3f, 0xf3, 0x2c, 0xdb, 0xc0, 0xfc, 0xeb, 0xe6, + 0x28, 0xd7, 0xe4, 0x6d, 0x28, 0x1a, 0x98, 0x9d, 0x43, 0xdd, 0x21, 0x43, 0x21, 0x51, 0xaf, 0x68, 0xbe, 0x3f, 0x6d, 0x56, 0xac, 0xfb, 0xdb, 0x6c, + 0x97, 0xd8, 0x7f, 0xcb, 0x5e, 0x62, 0x91, 0xbf, 0x8b, 0x4e, 0xe1, 0x27, 0x5a, 0xe0, 0xeb, 0x43, 0x83, 0xcc, 0x75, 0x39, 0x03, 0xc8, 0xd2, 0x9f, + 0x4a, 0xdb, 0x6a, 0x54, 0x7e, 0x40, 0x5d, 0xec, 0xdf, 0xf2, 0x88, 0xc5, 0xf6, 0xc7, 0xaa, 0x30, 0xdc, 0xb1, 0x2f, 0x84, 0xd3, 0x92, 0x49, 0x3a, + 0x70, 0x93, 0x33, 0x17, 0xc0, 0xf5, 0xe6, 0x55, 0x26, 0x01, 0xfa, 0xe1, 0x8f, 0x17, 0xe6, 0xe5, 0xbb, 0x6b, 0xf3, 0x96, 0xd3, 0x2d, 0x8a, 0xb9, +}; + +static const uint8_t TEE_ATTR_DSA_PRIME_768_VALUE01[] = { + 0xf6, 0xad, 0x20, 0x71, 0xe1, 0x5a, 0x4b, 0x9c, 0x2b, 0x7e, 0x53, 0x26, 0xda, 0x43, + 0x9d, 0xc1, 0x47, 0x4c, 0x1a, 0xd1, 0x6f, 0x2f, 0x85, 0xe9, 0x2c, 0xea, 0x89, 0xfc, 0xdc, + 0x74, 0x66, 0x11, 0xcf, 0x30, 0xdd, 0xc8, 0x5e, 0x33, 0xf5, 0x83, 0xc1, 0x9d, 0x10, 0xbc, + 0x1a, 0xc3, 0x93, 0x22, 0x26, 0x24, 0x6f, 0xa7, 0xb9, 0xe0, 0xdd, 0x25, 0x77, 0xb5, 0xf4, + 0x27, 0x59, 0x4c, 0x39, 0xfa, 0xeb, 0xfc, 0x59, 0x8a, 0x32, 0xe1, 0x74, 0xcb, 0x8a, 0x68, + 0x03, 0x57, 0xf8, 0x62, 0xf2, 0x0b, 0x6e, 0x84, 0x32, 0xa5, 0x30, 0x65, 0x2f, 0x1c, 0x21, + 0x39, 0xae, 0x1f, 0xaf, 0x76, 0x8b, 0x83, +}; + +static const uint8_t TEE_ATTR_DSA_PRIVATE_VALUE_160_VALUE01[] = { + 0x70, 0x4a, 0x46, 0xc6, 0x25, 0x2a, 0x95, 0xa3, 0x9b, 0x40, 0xe0, 0x43, 0x5a, 0x69, 0x1b, + 0xad, 0xae, 0x52, 0xa5, 0xc0, +}; + +static const uint8_t TEE_ATTR_DSA_PRIVATE_VALUE_224_VALUE01[] = { + 0x7b, 0x48, 0x90, 0x21, 0x57, 0x8e, 0x79, 0xe7, 0xbd, 0x3e, 0xe7, 0xab, 0x45, 0x6f, + 0x65, 0x9f, 0x3d, 0xc0, 0x7c, 0x88, 0xf5, 0xc9, 0xa3, 0x9e, 0x4f, 0x8c, 0xee, 0x81, +}; + +static const uint8_t TEE_ATTR_DSA_PRIVATE_VALUE_256_VALUE01[] = { + 0x34, 0x70, 0x83, 0x20, 0x55, 0xda, 0xde, 0x94, 0xe1, 0x4c, 0xd8, 0x77, 0x71, 0x71, 0xd1, 0x8e, + 0x5d, 0x06, 0xf6, 0x6a, 0xef, 0xf4, 0xc6, 0x14, 0x71, 0xe4, 0xeb, 0xa7, 0x4e, 0xe5, 0x61, 0x64, +}; + +static const uint8_t TEE_ATTR_DSA_PUBLIC_VALUE_2048_VALUE01[] = { + 0x1a, 0xe1, 0x0c, 0x78, 0x6a, 0xd0, 0x90, 0x2c, 0x5c, 0x68, 0x5d, 0xae, 0x5c, 0x71, 0x21, 0x41, + 0x8a, 0x37, 0x7b, 0x88, 0x8b, 0x5f, 0x2f, 0x2b, 0xc7, 0x66, 0x23, 0x57, 0x0f, 0xd6, 0x2b, 0xcb, + 0x19, 0x0b, 0x47, 0x1a, 0xd5, 0x35, 0x9c, 0x5f, 0x06, 0x2f, 0x88, 0x19, 0x28, 0x9e, 0x95, 0x6d, + 0x8a, 0xa6, 0xf9, 0x0d, 0x1f, 0x8c, 0xf1, 0xee, 0x72, 0xd3, 0xa1, 0xbd, 0xfd, 0x56, 0xc4, 0x78, + 0xdc, 0x29, 0xa1, 0x9c, 0x45, 0x69, 0xb5, 0xa6, 0x0e, 0x3a, 0x8f, 0x34, 0xf6, 0x06, 0x56, 0xea, + 0xc5, 0xb2, 0x5d, 0xde, 0x55, 0x14, 0xa5, 0xc6, 0x7b, 0x67, 0x54, 0x23, 0x20, 0x4f, 0x6c, 0xca, + 0xf0, 0x99, 0x06, 0x17, 0xcc, 0x73, 0x55, 0xb9, 0xd3, 0xed, 0x86, 0x89, 0x78, 0xa2, 0x52, 0x02, + 0x0a, 0x76, 0x9e, 0xd5, 0x9a, 0x6e, 0xda, 0xa6, 0xef, 0xe3, 0x37, 0x7e, 0xef, 0x45, 0xf3, 0xf6, + 0xf3, 0xe6, 0x41, 0x79, 0xcc, 0x7d, 0xb8, 0xb1, 0x43, 0xfb, 0x83, 0x5c, 0x5d, 0x71, 0xbf, 0xcf, + 0xa1, 0xe2, 0xa9, 0x04, 0x9b, 0xcc, 0xf7, 0xfe, 0x9a, 0xb5, 0x75, 0x46, 0x22, 0x0f, 0xe3, 0xf4, + 0xb7, 0x52, 0x1c, 0x86, 0x17, 0x39, 0xd1, 0x38, 0x50, 0x7e, 0x81, 0xa4, 0x6a, 0x69, 0x93, 0x60, + 0x54, 0x41, 0xdc, 0xb9, 0x0d, 0x6e, 0xe4, 0xaf, 0xbc, 0x42, 0xca, 0xbe, 0x90, 0xa2, 0x54, 0x44, + 0x49, 0x68, 0x10, 0x9d, 0x7e, 0xdd, 0x96, 0x94, 0xa0, 0x23, 0x23, 0x9f, 0x1d, 0x56, 0x17, 0x5d, + 0xd1, 0xfa, 0xc1, 0x15, 0x91, 0x5e, 0x24, 0xfa, 0xb5, 0x63, 0xf4, 0xfc, 0x3f, 0x26, 0x9b, 0xed, + 0x2f, 0x30, 0x08, 0x32, 0xd1, 0x12, 0x59, 0x64, 0x85, 0xa7, 0x11, 0x41, 0x7a, 0xa7, 0x3b, 0xb4, + 0xac, 0x72, 0xa6, 0x51, 0xa1, 0xfa, 0x5b, 0xae, 0xd3, 0x63, 0x6c, 0x72, 0x0d, 0x39, 0x70, 0x08, +}; + +static const uint8_t TEE_ATTR_DSA_PUBLIC_VALUE_3072_VALUE01[] = { + 0x45, 0x6a, 0x10, 0x5c, 0x71, 0x35, 0x66, 0x23, 0x48, 0x38, 0xbc, 0x07, 0x0b, 0x8a, 0x75, 0x1a, 0x0b, 0x57, 0x76, 0x7c, 0xb7, 0x5e, 0x99, 0x11, + 0x4a, 0x1a, 0x46, 0x64, 0x1e, 0x11, 0xda, 0x1f, 0xa9, 0xf2, 0x29, 0x14, 0xd8, 0x08, 0xad, 0x71, 0x48, 0x61, 0x2c, 0x1e, 0xa5, 0x5d, 0x25, 0x30, + 0x17, 0x81, 0xe9, 0xae, 0x0c, 0x9a, 0xe3, 0x6a, 0x69, 0xd8, 0x7b, 0xa0, 0x39, 0xec, 0x7c, 0xd8, 0x64, 0xc3, 0xad, 0x09, 0x48, 0x73, 0xe6, 0xe5, + 0x67, 0x09, 0xfd, 0x10, 0xd9, 0x66, 0x85, 0x3d, 0x61, 0x1b, 0x1c, 0xff, 0x15, 0xd3, 0x7f, 0xde, 0xe4, 0x24, 0x50, 0x6c, 0x18, 0x4d, 0x62, 0xc7, + 0x03, 0x33, 0x58, 0xbe, 0x78, 0xc2, 0x25, 0x09, 0x43, 0xb6, 0xf6, 0xd0, 0x43, 0xd6, 0x3b, 0x31, 0x7d, 0xe5, 0x6e, 0x5a, 0xd8, 0xd1, 0xfd, 0x97, + 0xdd, 0x35, 0x5a, 0xbe, 0x96, 0x45, 0x2f, 0x8e, 0x43, 0x54, 0x85, 0xfb, 0x3b, 0x90, 0x7b, 0x51, 0x90, 0x0a, 0xa3, 0xf2, 0x44, 0x18, 0xdf, 0x50, + 0xb4, 0xfc, 0xda, 0xfb, 0xf6, 0x13, 0x75, 0x48, 0xc3, 0x93, 0x73, 0xb8, 0xbc, 0x4b, 0xa3, 0xda, 0xbb, 0x47, 0x46, 0xeb, 0xd1, 0x7b, 0x87, 0xfc, + 0xd6, 0xa2, 0xf1, 0x97, 0xc1, 0x07, 0xb1, 0x8e, 0xc5, 0xb4, 0x65, 0xe6, 0xe4, 0xcb, 0x43, 0x0d, 0x9c, 0x0c, 0xe7, 0x8d, 0xa5, 0x98, 0x84, 0x41, + 0x05, 0x4a, 0x37, 0x07, 0x92, 0xb7, 0x30, 0xda, 0x9a, 0xba, 0x41, 0xa3, 0x16, 0x9a, 0xf2, 0x61, 0x76, 0xf7, 0x4e, 0x6f, 0x7c, 0x0c, 0x9c, 0x9b, + 0x55, 0xb6, 0x2b, 0xbe, 0x7c, 0xe3, 0x8d, 0x46, 0x95, 0xd4, 0x81, 0x57, 0xe6, 0x60, 0xc2, 0xac, 0xb6, 0x3f, 0x48, 0x2f, 0x55, 0x41, 0x81, 0x50, + 0xe5, 0xfe, 0xe4, 0x3a, 0xce, 0x84, 0xc5, 0x40, 0xc3, 0xba, 0x76, 0x62, 0xae, 0x80, 0x83, 0x5c, 0x1a, 0x2d, 0x51, 0x89, 0x0e, 0xa9, 0x6b, 0xa2, + 0x06, 0x42, 0x7c, 0x41, 0xef, 0x8c, 0x38, 0xaa, 0x07, 0xd2, 0xa3, 0x65, 0xe7, 0xe5, 0x83, 0x80, 0xd8, 0xf4, 0x78, 0x2e, 0x22, 0xac, 0x21, 0x01, + 0xaf, 0x73, 0x2e, 0xe2, 0x27, 0x58, 0x33, 0x7b, 0x25, 0x36, 0x37, 0x83, 0x8e, 0x16, 0xf5, 0x0f, 0x56, 0xd3, 0x13, 0xd0, 0x79, 0x81, 0x88, 0x0d, + 0x68, 0x55, 0x57, 0xf7, 0xd7, 0x9a, 0x6d, 0xb8, 0x23, 0xc6, 0x1f, 0x1b, 0xb3, 0xdb, 0xc5, 0xd5, 0x04, 0x21, 0xa4, 0x84, 0x3a, 0x6f, 0x29, 0x69, + 0x0e, 0x78, 0xaa, 0x0f, 0x0c, 0xff, 0x30, 0x42, 0x31, 0x81, 0x8b, 0x81, 0xfc, 0x4a, 0x24, 0x3f, 0xc0, 0x0f, 0x09, 0xa5, 0x4c, 0x46, 0x6d, 0x6a, + 0x8c, 0x73, 0xd3, 0x2a, 0x55, 0xe1, 0xab, 0xd5, 0xec, 0x8b, 0x4e, 0x1a, 0xfa, 0x32, 0xa7, 0x9b, 0x01, 0xdf, 0x85, 0xa8, 0x1f, 0x3f, 0x5c, 0xfe, +}; + +static const uint8_t TEE_ATTR_DSA_PUBLIC_VALUE_768_VALUE01[] = { + 0x52, 0x9d, 0xed, 0x98, 0xa2, 0x32, 0x09, 0x85, 0xfc, 0x84, 0xb6, 0x5a, 0x9d, 0xc8, 0xd4, + 0xfe, 0x41, 0xad, 0xa6, 0xe3, 0x59, 0x3d, 0x70, 0x4f, 0x08, 0x98, 0xc1, 0x4e, 0xc2, 0x46, + 0x34, 0xdd, 0xf5, 0xf1, 0xdb, 0x47, 0xcc, 0x49, 0x15, 0xfc, 0xe1, 0xe2, 0x67, 0x4d, 0x2e, + 0xcd, 0x98, 0xd5, 0x8b, 0x59, 0x8e, 0x8d, 0xdf, 0xaf, 0xf3, 0x0e, 0x88, 0x26, 0xf5, 0x0a, + 0xab, 0x40, 0x27, 0xb5, 0xaa, 0xb8, 0x87, 0xc1, 0x9a, 0xd9, 0x6d, 0x7e, 0x57, 0xde, 0x53, + 0x90, 0xad, 0x8e, 0x55, 0x57, 0xb4, 0x1a, 0x80, 0x19, 0xc9, 0x0d, 0x80, 0x60, 0x71, 0x79, + 0xb5, 0x4e, 0xb0, 0xad, 0x4d, 0x23, +}; + +static const uint8_t TEE_ATTR_DSA_SUBPRIME_160_VALUE01[] = { + 0x87, 0x44, 0xe4, 0xdd, 0xc6, 0xd0, 0x19, 0xa5, 0xea, 0xc2, 0xb1, 0x5a, 0x15, 0xd7, + 0xe1, 0xc7, 0xf6, 0x63, 0x35, 0xf7, +}; + +static const uint8_t TEE_ATTR_DSA_SUBPRIME_224_VALUE01[] = { + 0xea, 0x34, 0x7e, 0x90, 0xbe, 0x7c, 0x28, 0x75, 0xd1, 0xfe, 0x1d, 0xb6, 0x22, 0xb4, + 0x76, 0x38, 0x37, 0xc5, 0xe2, 0x7a, 0x60, 0x37, 0x31, 0x03, 0x48, 0xc1, 0xaa, 0x11, +}; + +static const uint8_t TEE_ATTR_DSA_SUBPRIME_256_VALUE01[] = { + 0x87, 0x6f, 0xa0, 0x9e, 0x1d, 0xc6, 0x2b, 0x23, 0x6c, 0xe1, 0xc3, 0x15, 0x5b, 0xa4, 0x8b, 0x0c, + 0xcf, 0xda, 0x29, 0xf3, 0xac, 0x5a, 0x97, 0xf7, 0xff, 0xa1, 0xbd, 0x87, 0xb6, 0x8d, 0x2a, 0x4b, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P192_VALUE01[] = { + 0xf1, 0x7d, 0x3f, 0xea, 0x36, 0x7b, 0x74, 0xd3, 0x40, 0x85, 0x1c, 0xa4, 0x27, 0x0d, 0xcb, 0x24, 0xc2, 0x71, 0xf4, 0x45, 0xbe, 0xd9, 0xd5, 0x27, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P224_VALUE01[] = { + 0x83, 0x46, 0xa6, 0x0f, 0xc6, 0xf2, 0x93, 0xca, 0x5a, 0x0d, 0x2a, 0xf6, 0x8b, 0xa7, 0x1d, 0x1d, 0xd3, 0x89, 0xe5, 0xe4, 0x08, 0x37, 0x94, 0x2d, 0xf3, 0xe4, 0x3c, 0xbd, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P256_VALUE01[] = { + 0x7d, 0x7d, 0xc5, 0xf7, 0x1e, 0xb2, 0x9d, 0xda, 0xf8, 0x0d, 0x62, 0x14, 0x63, 0x2e, 0xea, 0xe0, + 0x3d, 0x90, 0x58, 0xaf, 0x1f, 0xb6, 0xd2, 0x2e, 0xd8, 0x0b, 0xad, 0xb6, 0x2b, 0xc1, 0xa5, 0x34, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P384_VALUE01[] = { + 0x3c, 0xc3, 0x12, 0x2a, 0x68, 0xf0, 0xd9, 0x50, 0x27, 0xad, 0x38, 0xc0, 0x67, 0x91, 0x6b, 0xa0, 0xeb, 0x8c, 0x38, 0x89, 0x4d, 0x22, 0xe1, 0xb1, + 0x56, 0x18, 0xb6, 0x81, 0x8a, 0x66, 0x17, 0x74, 0xad, 0x46, 0x3b, 0x20, 0x5d, 0xa8, 0x8c, 0xf6, 0x99, 0xab, 0x4d, 0x43, 0xc9, 0xcf, 0x98, 0xa1, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDH_P521_VALUE01[] = { + 0x00, 0x00, 0x01, 0x7e, 0xec, 0xc0, 0x7a, 0xb4, 0xb3, 0x29, 0x06, 0x8f, 0xba, 0x65, 0xe5, 0x6a, 0x1f, + 0x88, 0x90, 0xaa, 0x93, 0x5e, 0x57, 0x13, 0x4a, 0xe0, 0xff, 0xcc, 0xe8, 0x02, 0x73, 0x51, 0x51, 0xf4, + 0xea, 0xc6, 0x56, 0x4f, 0x6e, 0xe9, 0x97, 0x4c, 0x5e, 0x68, 0x87, 0xa1, 0xfe, 0xfe, 0xe5, 0x74, 0x3a, + 0xe2, 0x24, 0x1b, 0xfe, 0xb9, 0x5d, 0x5c, 0xe3, 0x1d, 0xdc, 0xb6, 0xf9, 0xed, 0xb4, 0xd6, 0xfc, 0x47, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P192_VALUE01[] = { + 0xe1, 0x4f, 0x37, 0xb3, 0xd1, 0x37, 0x4f, 0xf8, 0xb0, 0x3f, 0x41, 0xb9, 0xb3, 0xfd, 0xd2, 0xf0, 0xeb, 0xcc, 0xf2, 0x75, 0xd6, 0x60, 0xd7, 0xf3, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P224_VALUE01[] = { + 0x97, 0xc4, 0xb7, 0x96, 0xe1, 0x63, 0x9d, 0xd1, 0x03, 0x5b, 0x70, 0x8f, 0xc0, 0x0d, 0xc7, 0xba, 0x16, 0x82, 0xce, 0xc4, 0x4a, 0x10, 0x02, 0xa1, 0xa8, 0x20, 0x61, 0x9f, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P256_VALUE01[] = { + 0xbe, 0x34, 0xba, 0xa8, 0xd0, 0x40, 0xa3, 0xb9, 0x91, 0xf9, 0x07, 0x5b, 0x56, 0xba, 0x29, 0x2f, + 0x75, 0x5b, 0x90, 0xe4, 0xb6, 0xdc, 0x10, 0xda, 0xd3, 0x67, 0x15, 0xc3, 0x3c, 0xfd, 0xac, 0x25, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P384_VALUE01[] = { + 0xa4, 0x92, 0xce, 0x8f, 0xa9, 0x00, 0x84, 0xc2, 0x27, 0xe1, 0xa3, 0x2f, 0x79, 0x74, 0xd3, 0x9e, 0x9f, 0xf6, 0x7a, 0x7e, 0x87, 0x05, 0xec, 0x34, + 0x19, 0xb3, 0x5f, 0xb6, 0x07, 0x58, 0x2b, 0xeb, 0xd4, 0x61, 0xe0, 0xb1, 0x52, 0x0a, 0xc7, 0x6e, 0xc2, 0xdd, 0x4e, 0x9b, 0x63, 0xeb, 0xae, 0x71, +}; + +static const uint8_t TEE_ATTR_ECC_PRIVATE_VALUE_ECDSA_P521_VALUE01[] = { + 0x01, 0xbd, 0x56, 0xbd, 0x10, 0x61, 0x18, 0xed, 0xa2, 0x46, 0x15, 0x5b, 0xd4, 0x3b, 0x42, 0xb8, 0xe1, + 0x3f, 0x0a, 0x6e, 0x25, 0xdd, 0x3b, 0xb3, 0x76, 0x02, 0x6f, 0xab, 0x4d, 0xc9, 0x2b, 0x61, 0x57, 0xbc, + 0x6d, 0xfe, 0xc2, 0xd1, 0x5d, 0xd3, 0xd0, 0xcf, 0x2a, 0x39, 0xaa, 0x68, 0x49, 0x40, 0x42, 0xaf, 0x48, + 0xba, 0x96, 0x01, 0x11, 0x8d, 0xa8, 0x2c, 0x6f, 0x21, 0x08, 0xa3, 0xa2, 0x03, 0xad, 0x74, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P192_VALUE01[] = { + 0xb1, 0x50, 0x53, 0x40, 0x1f, 0x57, 0x28, 0x56, 0x37, 0xec, 0x32, 0x4c, 0x1c, 0xd2, 0x13, 0x9e, 0x3a, 0x67, 0xde, 0x37, 0x39, 0x23, 0x4b, 0x37, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P192_VALUE02[] = { + 0x42, 0xea, 0x6d, 0xd9, 0x96, 0x9d, 0xd2, 0xa6, 0x1f, 0xea, 0x1a, 0xac, 0x7f, 0x8e, 0x98, 0xed, + 0xcc, 0x89, 0x6c, 0x6e, 0x55, 0x85, 0x7c, 0xc0, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P224_VALUE01[] = { + 0x8d, 0xe2, 0xe2, 0x6a, 0xdf, 0x72, 0xc5, 0x82, 0xd6, 0x56, 0x8e, 0xf6, 0x38, 0xc4, 0xfd, 0x59, 0xb1, 0x8d, 0xa1, 0x71, 0xbd, 0xf5, 0x01, 0xf1, 0xd9, 0x29, 0xe0, 0x48, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P224_VALUE02[] = { + 0xaf, 0x33, 0xcd, 0x06, 0x29, 0xbc, 0x7e, 0x99, 0x63, 0x20, 0xa3, 0xf4, 0x03, 0x68, 0xf7, 0x4d, + 0xe8, 0x70, 0x4f, 0xa3, 0x7b, 0x8f, 0xab, 0x69, 0xab, 0xaa, 0xe2, 0x80, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P256_VALUE01[] = { + 0xea, 0xd2, 0x18, 0x59, 0x01, 0x19, 0xe8, 0x87, 0x6b, 0x29, 0x14, 0x6f, 0xf8, 0x9c, 0xa6, 0x17, + 0x70, 0xc4, 0xed, 0xbb, 0xf9, 0x7d, 0x38, 0xce, 0x38, 0x5e, 0xd2, 0x81, 0xd8, 0xa6, 0xb2, 0x30, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P256_VALUE02[] = { + 0x70, 0x0c, 0x48, 0xf7, 0x7f, 0x56, 0x58, 0x4c, 0x5c, 0xc6, 0x32, 0xca, 0x65, 0x64, 0x0d, 0xb9, + 0x1b, 0x6b, 0xac, 0xce, 0x3a, 0x4d, 0xf6, 0xb4, 0x2c, 0xe7, 0xcc, 0x83, 0x88, 0x33, 0xd2, 0x87, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P384_VALUE01[] = { + 0x98, 0x03, 0x80, 0x7f, 0x2f, 0x6d, 0x2f, 0xd9, 0x66, 0xcd, 0xd0, 0x29, 0x0b, 0xd4, 0x10, 0xc0, 0x19, 0x03, 0x52, 0xfb, 0xec, 0x7f, 0xf6, 0x24, + 0x7d, 0xe1, 0x30, 0x2d, 0xf8, 0x6f, 0x25, 0xd3, 0x4f, 0xe4, 0xa9, 0x7b, 0xef, 0x60, 0xcf, 0xf5, 0x48, 0x35, 0x5c, 0x01, 0x5d, 0xbb, 0x3e, 0x5f, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P384_VALUE02[] = { + 0xa7, 0xc7, 0x6b, 0x97, 0x0c, 0x3b, 0x5f, 0xe8, 0xb0, 0x5d, 0x28, 0x38, 0xae, 0x04, 0xab, 0x47, + 0x69, 0x7b, 0x9e, 0xaf, 0x52, 0xe7, 0x64, 0x59, 0x2e, 0xfd, 0xa2, 0x7f, 0xe7, 0x51, 0x32, 0x72, + 0x73, 0x44, 0x66, 0xb4, 0x00, 0x09, 0x1a, 0xdb, 0xf2, 0xd6, 0x8c, 0x58, 0xe0, 0xc5, 0x00, 0x66, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P521_VALUE01[] = { + 0x00, 0x00, 0x00, 0x60, 0x2f, 0x9d, 0x0c, 0xf9, 0xe5, 0x26, 0xb2, 0x9e, 0x22, 0x38, 0x1c, 0x20, 0x3c, + 0x48, 0xa8, 0x86, 0xc2, 0xb0, 0x67, 0x30, 0x33, 0x36, 0x63, 0x14, 0xf1, 0xff, 0xbc, 0xba, 0x24, 0x0b, + 0xa4, 0x2f, 0x4e, 0xf3, 0x8a, 0x76, 0x17, 0x46, 0x35, 0xf9, 0x1e, 0x6b, 0x4e, 0xd3, 0x42, 0x75, 0xeb, + 0x01, 0xc8, 0x46, 0x7d, 0x05, 0xca, 0x80, 0x31, 0x5b, 0xf1, 0xa7, 0xbb, 0xd9, 0x45, 0xf5, 0x50, 0xa5, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDH_P521_VALUE02[] = { + 0x00, 0x00, 0x00, 0x68, 0x5a, 0x48, 0xe8, 0x6c, 0x79, 0xf0, 0xf0, 0x87, 0x5f, 0x7b, 0xc1, 0x8d, + 0x25, 0xeb, 0x5f, 0xc8, 0xc0, 0xb0, 0x7e, 0x5d, 0xa4, 0xf4, 0x37, 0x0f, 0x3a, 0x94, 0x90, 0x34, + 0x08, 0x54, 0x33, 0x4b, 0x1e, 0x1b, 0x87, 0xfa, 0x39, 0x54, 0x64, 0xc6, 0x06, 0x26, 0x12, 0x4a, + 0x4e, 0x70, 0xd0, 0xf7, 0x85, 0x60, 0x1d, 0x37, 0xc0, 0x98, 0x70, 0xeb, 0xf1, 0x76, 0x66, 0x68, + 0x77, 0xa2, 0x04, 0x6d, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P192_VALUE01[] = { + 0x07, 0x00, 0x8e, 0xa4, 0x0b, 0x08, 0xdb, 0xe7, 0x64, 0x32, 0x09, 0x6e, 0x80, 0xa2, 0x49, 0x4c, 0x94, 0x98, 0x2d, 0x2d, 0x5b, 0xcf, 0x98, 0xe6, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P224_VALUE01[] = { + 0x8a, 0x4d, 0xca, 0x35, 0x13, 0x6c, 0x4b, 0x70, 0xe5, 0x88, 0xe2, 0x35, 0x54, 0x63, 0x7a, 0xe2, 0x51, 0x07, 0x7d, 0x13, 0x65, 0xa6, 0xba, 0x5d, 0xb9, 0x58, 0x5d, 0xe7, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P256_VALUE01[] = { + 0xfa, 0x27, 0x37, 0xfb, 0x93, 0x48, 0x8d, 0x19, 0xca, 0xef, 0x11, 0xae, 0x7f, 0xaf, 0x6b, 0x7f, + 0x4b, 0xcd, 0x67, 0xb2, 0x86, 0xe3, 0xfc, 0x54, 0xe8, 0xa6, 0x5c, 0x2b, 0x74, 0xae, 0xcc, 0xb0, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P384_VALUE01[] = { + 0xe5, 0x5f, 0xee, 0x6c, 0x49, 0xd8, 0xd5, 0x23, 0xf5, 0xce, 0x7b, 0xf9, 0xc0, 0x42, 0x5c, 0xe4, 0xff, 0x65, 0x07, 0x08, 0xb7, 0xde, 0x5c, 0xfb, + 0x09, 0x59, 0x01, 0x52, 0x39, 0x79, 0xa7, 0xf0, 0x42, 0x60, 0x2d, 0xb3, 0x08, 0x54, 0x73, 0x53, 0x69, 0x81, 0x3b, 0x5c, 0x3f, 0x5e, 0xf8, 0x68, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_X_ECDSA_P521_VALUE01[] = { + 0x01, 0x2f, 0xbc, 0xae, 0xff, 0xa6, 0xa5, 0x1f, 0x3e, 0xe4, 0xd3, 0xd2, 0xb5, 0x1c, 0x5d, 0xec, 0x6d, + 0x7c, 0x72, 0x6c, 0xa3, 0x53, 0xfc, 0x01, 0x4e, 0xa2, 0xbf, 0x7c, 0xfb, 0xb9, 0xb9, 0x10, 0xd3, 0x2c, + 0xbf, 0xa6, 0xa0, 0x0f, 0xe3, 0x9b, 0x6c, 0xdb, 0x89, 0x46, 0xf2, 0x27, 0x75, 0x39, 0x8b, 0x2e, 0x23, + 0x3c, 0x0c, 0xf1, 0x44, 0xd7, 0x8c, 0x8a, 0x77, 0x42, 0xb5, 0xc7, 0xa3, 0xbb, 0x5d, 0x23, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P192_VALUE01[] = { + 0xf2, 0x69, 0xc1, 0x58, 0x63, 0x74, 0x82, 0xaa, 0xd6, 0x44, 0xcd, 0x69, 0x2d, 0xd1, 0xd3, 0xef, 0x2c, 0x8a, 0x7c, 0x49, 0xe3, 0x89, 0xf7, 0xf6, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P192_VALUE02[] = { + 0xdf, 0xbe, 0x5d, 0x7c, 0x61, 0xfa, 0xc8, 0x8b, 0x11, 0x81, 0x1b, 0xde, 0x32, 0x8e, 0x8a, 0x0d, + 0x12, 0xbf, 0x01, 0xa9, 0xd2, 0x04, 0xb5, 0x23, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P224_VALUE01[] = { + 0x4a, 0x68, 0xa1, 0xc2, 0xb0, 0xfb, 0x22, 0x93, 0x0d, 0x12, 0x05, 0x55, 0xc1, 0xec, 0xe5, 0x0e, 0xa9, 0x8d, 0xea, 0x84, 0x07, 0xf7, 0x1b, 0xe3, 0x6e, 0xfa, 0xc0, 0xde, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P224_VALUE02[] = { + 0x88, 0x20, 0x92, 0xcc, 0xbb, 0xa7, 0x93, 0x0f, 0x41, 0x9a, 0x8a, 0x4f, 0x9b, 0xb1, 0x69, 0x78, + 0xbb, 0xc3, 0x83, 0x87, 0x29, 0x99, 0x25, 0x59, 0xa6, 0xf2, 0xe2, 0xd7, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P256_VALUE01[] = { + 0x28, 0xaf, 0x61, 0x28, 0x1f, 0xd3, 0x5e, 0x2f, 0xa7, 0x00, 0x25, 0x23, 0xac, 0xc8, 0x5a, 0x42, + 0x9c, 0xb0, 0x6e, 0xe6, 0x64, 0x83, 0x25, 0x38, 0x9f, 0x59, 0xed, 0xfc, 0xe1, 0x40, 0x51, 0x41, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P256_VALUE02[] = { + 0xdb, 0x71, 0xe5, 0x09, 0xe3, 0xfd, 0x9b, 0x06, 0x0d, 0xdb, 0x20, 0xba, 0x5c, 0x51, 0xdc, 0xc5, + 0x94, 0x8d, 0x46, 0xfb, 0xf6, 0x40, 0xdf, 0xe0, 0x44, 0x17, 0x82, 0xca, 0xb8, 0x5f, 0xa4, 0xac, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P384_VALUE01[] = { + 0xba, 0x26, 0xca, 0x69, 0xec, 0x2f, 0x5b, 0x5d, 0x9d, 0xad, 0x20, 0xcc, 0x9d, 0xa7, 0x11, 0x38, 0x3a, 0x9d, 0xbe, 0x34, 0xea, 0x3f, 0xa5, 0xa2, + 0xaf, 0x75, 0xb4, 0x65, 0x02, 0x62, 0x9a, 0xd5, 0x4d, 0xd8, 0xb7, 0xd7, 0x3a, 0x8a, 0xbb, 0x06, 0xa3, 0xa3, 0xbe, 0x47, 0xd6, 0x50, 0xcc, 0x99, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P384_VALUE02[] = { + 0xac, 0x68, 0xf1, 0x9f, 0x2e, 0x1c, 0xb8, 0x79, 0xae, 0xd4, 0x3a, 0x99, 0x69, 0xb9, 0x1a, 0x08, + 0x39, 0xc4, 0xc3, 0x8a, 0x49, 0x74, 0x9b, 0x66, 0x1e, 0xfe, 0xdf, 0x24, 0x34, 0x51, 0x91, 0x5e, + 0xd0, 0x90, 0x5a, 0x32, 0xb0, 0x60, 0x99, 0x2b, 0x46, 0x8c, 0x64, 0x76, 0x6f, 0xc8, 0x43, 0x7a, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P521_VALUE01[] = { + 0x00, 0x00, 0x01, 0xb7, 0xc8, 0x5f, 0x26, 0xf5, 0xd4, 0xb2, 0xd7, 0x35, 0x5c, 0xf6, 0xb0, 0x21, 0x17, + 0x65, 0x99, 0x43, 0x76, 0x2b, 0x6d, 0x1d, 0xb5, 0xab, 0x4f, 0x1d, 0xbc, 0x44, 0xce, 0x7b, 0x29, 0x46, + 0xeb, 0x6c, 0x7d, 0xe3, 0x42, 0x96, 0x28, 0x93, 0xfd, 0x38, 0x7d, 0x1b, 0x73, 0xd7, 0xa8, 0x67, 0x2d, + 0x1f, 0x23, 0x69, 0x61, 0x17, 0x0b, 0x7e, 0xb3, 0x57, 0x99, 0x53, 0xee, 0x5c, 0xdc, 0x88, 0xcd, 0x2d, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDH_P521_VALUE02[] = { + 0x00, 0x00, 0x01, 0xba, 0x52, 0xc5, 0x6f, 0xc8, 0x77, 0x6d, 0x9e, 0x8f, 0x5d, 0xb4, 0xf0, 0xcc, + 0x27, 0x63, 0x6d, 0x0b, 0x74, 0x1b, 0xbe, 0x05, 0x40, 0x06, 0x97, 0x94, 0x2e, 0x80, 0xb7, 0x39, + 0x88, 0x4a, 0x83, 0xbd, 0xe9, 0x9e, 0x0f, 0x67, 0x16, 0x93, 0x9e, 0x63, 0x2b, 0xc8, 0x98, 0x6f, + 0xa1, 0x8d, 0xcc, 0xd4, 0x43, 0xa3, 0x48, 0xb6, 0xc3, 0xe5, 0x22, 0x49, 0x79, 0x55, 0xa4, 0xf3, + 0xc3, 0x02, 0xf6, 0x76, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P192_VALUE01[] = { + 0x76, 0xfa, 0xb6, 0x81, 0xd0, 0x0b, 0x41, 0x4e, 0xa6, 0x36, 0xba, 0x21, 0x5d, 0xe2, 0x6d, 0x98, 0xc4, 0x1b, 0xd7, 0xf2, 0xe4, 0xd6, 0x54, 0x77, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P224_VALUE01[] = { + 0xad, 0x3d, 0xee, 0x06, 0xde, 0x0b, 0xe8, 0x27, 0x9d, 0x4a, 0xf4, 0x35, 0xd7, 0x24, 0x5f, 0x14, 0xf3, 0xb4, 0xf8, 0x2e, 0xb5, 0x78, 0xe5, 0x19, 0xee, 0x00, 0x57, 0xb1, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P256_VALUE01[] = { + 0xd4, 0xcc, 0xd6, 0xda, 0xe6, 0x98, 0x20, 0x8a, 0xa8, 0xc3, 0xa6, 0xf3, 0x9e, 0x45, 0x51, 0x0d, + 0x03, 0xbe, 0x09, 0xb2, 0xf1, 0x24, 0xbf, 0xc0, 0x67, 0x85, 0x6c, 0x32, 0x4f, 0x9b, 0x4d, 0x09, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P384_VALUE01[] = { + 0x28, 0xf5, 0x9c, 0xc5, 0xdc, 0x50, 0x98, 0x92, 0xa9, 0x88, 0xd3, 0x8a, 0x8e, 0x25, 0x19, 0xde, 0x3d, 0x0c, 0x4f, 0xd0, 0xfb, 0xdb, 0x09, 0x93, + 0xe3, 0x8f, 0x18, 0x50, 0x6c, 0x17, 0x60, 0x6c, 0x5e, 0x24, 0x24, 0x92, 0x46, 0xf1, 0xce, 0x94, 0x98, 0x3a, 0x53, 0x61, 0xc5, 0xbe, 0x98, 0x3e, +}; + +static const uint8_t TEE_ATTR_ECC_PUBLIC_VALUE_Y_ECDSA_P521_VALUE01[] = { + 0x00, 0x9c, 0xde, 0xf8, 0x23, 0xdd, 0x7b, 0xf9, 0xa7, 0x9e, 0x8c, 0xce, 0xac, 0xd2, 0xe4, 0x52, 0x7c, + 0x23, 0x1d, 0x0a, 0xe5, 0x96, 0x7a, 0xf0, 0x95, 0x8e, 0x93, 0x1d, 0x7d, 0xdc, 0xcf, 0x28, 0x05, 0xa3, + 0xe6, 0x18, 0xdc, 0x30, 0x39, 0xfe, 0xc9, 0xfe, 0xbb, 0xd3, 0x30, 0x52, 0xfe, 0x4c, 0x0f, 0xee, 0x98, + 0xf0, 0x33, 0x10, 0x60, 0x64, 0x98, 0x2d, 0x88, 0xf4, 0xe0, 0x35, 0x49, 0xd4, 0xa6, 0x4d, +}; + +static const uint8_t TEE_ATTR_GENERIC_SECRET_2048_VALUE01[] = { + 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, + 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, + 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, +}; + +static const uint8_t TEE_ATTR_HMAC_MD5_256_VALUE01[] = { + 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, +}; + +static const uint8_t TEE_ATTR_HMAC_SHA1_256_VALUE01[] = { + 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, +}; + +static const uint8_t TEE_ATTR_HMAC_SHA224_256_VALUE01[] = { + 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, +}; + +static const uint8_t TEE_ATTR_HMAC_SHA256_512_VALUE01[] = { + 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, +}; + +static const uint8_t TEE_ATTR_HMAC_SHA384_512_VALUE01[] = { + 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, +}; + +static const uint8_t TEE_ATTR_HMAC_SHA512_512_VALUE01[] = { + 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, +}; + +static const uint8_t TEE_ATTR_RSA_COEFFICIENT_VALUE01[] = { + 0x94, 0x65, 0xe9, 0xd0, 0x98, 0xf8, 0x9c, 0x30, 0x25, 0xa8, 0xb1, 0x53, 0x78, 0x61, + 0x01, 0x1f, 0xde, 0x48, 0x91, 0x92, 0x90, 0x11, 0x6c, 0x96, 0x27, 0xce, 0xe1, 0x8f, 0x7b, + 0x37, 0x53, 0x25, 0x89, 0xac, 0x2c, 0xa8, 0x09, 0x2b, 0xff, 0x70, 0x42, 0x2a, 0xca, 0xfb, + 0x83, 0x68, 0xca, 0x8f, 0xaf, 0x1b, 0xcd, 0x11, 0x20, 0xfb, 0x64, 0x74, 0x5a, 0x35, 0xdf, + 0x7d, 0x79, 0xed, 0x29, 0xe5, 0xf7, 0xd9, 0xba, 0x5d, 0x02, 0x19, 0xb7, 0x88, 0x74, 0x33, + 0x86, 0xcd, 0x5d, 0xc5, 0xa2, 0x89, 0x36, 0xbe, 0x9e, 0xe5, 0x84, 0xc8, 0x08, 0xca, 0xbc, + 0x85, 0xd1, 0x95, 0x18, 0xba, 0x0f, 0xac, 0x4a, 0xa1, 0x03, 0x84, 0xe3, 0xd3, 0x2d, 0x38, + 0x81, 0xb3, 0x11, 0x27, 0x97, 0x1d, 0x7e, 0x84, 0xe8, 0xa4, 0xc3, 0xb2, 0x75, 0xdf, 0x96, + 0x91, 0xe0, 0x81, 0xa6, 0x57, 0xe9, 0x74, 0x82, 0x88, +}; + +static const uint8_t TEE_ATTR_RSA_EXPONENT1_VALUE01[] = { + 0x88, 0x14, 0x08, 0x30, 0x55, 0x6f, 0x85, 0x25, 0x7b, 0x61, 0xef, 0x47, 0xb5, 0xf6, + 0x69, 0x1a, 0xbc, 0x34, 0xcc, 0x80, 0x80, 0xf5, 0x35, 0x9b, 0x2e, 0x86, 0xb4, 0x3d, 0x3f, + 0x16, 0xb7, 0x18, 0x1f, 0x2f, 0xda, 0xd7, 0x27, 0x7c, 0x5e, 0x8d, 0x15, 0xde, 0x5e, 0x78, + 0xc0, 0xa6, 0x49, 0x94, 0x71, 0x4b, 0x97, 0x2e, 0x8c, 0xf4, 0x10, 0x66, 0x77, 0xbf, 0x78, + 0x31, 0xaf, 0xa7, 0xd0, 0x80, 0x3a, 0x73, 0x13, 0x56, 0xd4, 0x14, 0x04, 0x74, 0x46, 0x4e, + 0x91, 0x1d, 0xdc, 0x45, 0xa7, 0x7c, 0x00, 0x4b, 0x5d, 0x34, 0x70, 0xa0, 0x7f, 0x95, 0xb9, + 0xf2, 0x90, 0x76, 0x6b, 0x4d, 0x64, 0x1c, 0x94, 0x5b, 0x48, 0x2b, 0xdf, 0x37, 0x92, 0x2d, + 0x8d, 0x5e, 0x73, 0xf6, 0x89, 0x40, 0x2d, 0xed, 0x55, 0xd2, 0x40, 0x8f, 0x38, 0x82, 0x41, + 0x82, 0x64, 0xb2, 0xb4, 0xb0, 0xdf, 0xc7, 0x83, 0xc1, +}; + +static const uint8_t TEE_ATTR_RSA_EXPONENT2_VALUE01[] = { + 0x40, 0x26, 0x13, 0xa7, 0x0f, 0x28, 0x79, 0x92, 0xb7, 0x88, 0xca, 0x91, 0x0a, 0xa2, 0xe5, + 0xd1, 0x74, 0xa4, 0xbe, 0x5f, 0x91, 0x8b, 0xa8, 0xff, 0xb9, 0x3d, 0x01, 0xce, 0x5a, 0xc9, + 0xfd, 0xde, 0xb0, 0xc6, 0x1f, 0x52, 0x08, 0xd7, 0x46, 0x9e, 0x3e, 0x1e, 0x82, 0xa5, 0x77, + 0x30, 0x75, 0xb0, 0x16, 0xb1, 0x09, 0xbf, 0x3f, 0x35, 0x9f, 0x3e, 0xcd, 0x74, 0x02, 0x4c, + 0x99, 0x69, 0xa2, 0x02, 0x39, 0x7c, 0x7d, 0xd8, 0xce, 0x92, 0xe9, 0xa9, 0x33, 0x0d, 0xe5, + 0x3e, 0x05, 0x3d, 0xd0, 0x2c, 0xf3, 0x4a, 0xaa, 0xdb, 0xbe, 0xef, 0xd5, 0x9f, 0x2b, 0xec, + 0xbf, 0xea, 0xff, 0x75, 0x2d, 0x6d, 0x23, 0x12, 0x8d, 0x53, 0xe2, 0xca, 0x7f, 0xdb, 0x0d, + 0xbb, 0xc6, 0x5e, 0x16, 0xd5, 0xb1, 0x62, 0x8e, 0x1b, 0xbf, 0xbf, 0x0e, 0x2c, 0xb5, 0xcf, + 0x54, 0x55, 0x22, 0x21, 0xde, 0x7d, 0xba, 0xb1, +}; + +static const uint8_t TEE_ATTR_RSA_MODULUS_3072_VALUE01[] = { + 0xac, 0x6a, 0x77, 0xeb, 0xbf, 0x9c, 0x72, 0x5e, 0xc9, 0x73, 0x11, 0xf5, 0x4c, 0xd3, 0x5a, 0x4d, 0x98, 0xc4, 0x95, 0x82, 0x20, 0x13, 0x83, 0xcc, + 0x8c, 0xaf, 0x06, 0xde, 0x23, 0x3e, 0x8a, 0x64, 0x98, 0xcc, 0xa8, 0x1e, 0x57, 0x05, 0xff, 0x67, 0xc8, 0x78, 0x74, 0xcb, 0xa0, 0x07, 0x0c, 0x94, + 0xdc, 0xf7, 0x37, 0x0a, 0x13, 0xf4, 0x4c, 0x7b, 0xf6, 0xf3, 0x9e, 0x10, 0x39, 0xc0, 0xe7, 0x16, 0xf2, 0x1b, 0xb8, 0x1d, 0x23, 0x81, 0x15, 0xce, + 0x65, 0x19, 0x00, 0xc7, 0x62, 0x70, 0x86, 0xc6, 0xbc, 0x70, 0x47, 0xec, 0x8f, 0xc9, 0xf0, 0x27, 0x13, 0xdc, 0x7c, 0x6c, 0xb3, 0x53, 0x42, 0xcd, + 0xd3, 0xd0, 0x26, 0xb3, 0xe8, 0xe7, 0x35, 0x18, 0xe6, 0x57, 0xf2, 0xe1, 0x68, 0x35, 0x32, 0xa4, 0x8b, 0xfe, 0x3b, 0xbd, 0x55, 0x86, 0x95, 0x86, + 0x0c, 0x71, 0xfc, 0xd4, 0x4a, 0x27, 0x5e, 0x6d, 0x41, 0xd4, 0x02, 0xd5, 0xf0, 0x50, 0x40, 0x0a, 0x34, 0x02, 0xd3, 0xd5, 0xd4, 0xaa, 0xf9, 0x78, + 0x7d, 0xd7, 0x9a, 0x2d, 0x5c, 0x90, 0xa4, 0x3f, 0xd4, 0xcd, 0xf4, 0x3a, 0x48, 0xd0, 0xa5, 0x2b, 0x0b, 0x0d, 0xa5, 0xd3, 0xb1, 0xb5, 0x9c, 0xc2, + 0xab, 0xdd, 0xbc, 0xae, 0x0b, 0x8b, 0x1b, 0x02, 0xa2, 0xe2, 0xed, 0xba, 0xab, 0x93, 0x4e, 0x90, 0x30, 0x97, 0x60, 0xd6, 0x99, 0xec, 0xb9, 0x96, + 0x91, 0xd5, 0x1b, 0xbf, 0x06, 0x74, 0xa1, 0x45, 0xe6, 0xa3, 0x5b, 0x83, 0xa5, 0xad, 0x4a, 0xc3, 0x0d, 0xa4, 0x1b, 0x20, 0x52, 0x7d, 0x48, 0x1d, + 0x80, 0x3b, 0x2f, 0x77, 0xca, 0x0b, 0x1e, 0x18, 0x24, 0x33, 0x06, 0x87, 0xbb, 0x3c, 0x0a, 0x2a, 0x6c, 0x9e, 0xb7, 0x39, 0x5d, 0x26, 0x58, 0x5b, + 0x04, 0x8f, 0xc5, 0xde, 0x51, 0x8f, 0x3e, 0x5c, 0x2b, 0x96, 0x1f, 0xa9, 0x3d, 0x26, 0x5c, 0x45, 0x25, 0x9f, 0x2d, 0xb3, 0xbe, 0xff, 0xe5, 0xd1, + 0xf1, 0x2e, 0x0c, 0xc6, 0x74, 0x3f, 0x9b, 0x24, 0x39, 0x9b, 0x7c, 0x76, 0x4d, 0x88, 0xdb, 0x09, 0x30, 0x44, 0xbb, 0xad, 0x65, 0x82, 0x9b, 0xb6, + 0x1d, 0x21, 0xb1, 0x27, 0xb8, 0x7f, 0x90, 0x54, 0xee, 0xa0, 0x9c, 0x86, 0xb7, 0x56, 0x2d, 0x1c, 0x17, 0x3f, 0xa7, 0x3f, 0x72, 0x80, 0xc4, 0x9c, + 0x62, 0xdd, 0x0a, 0xa5, 0xcb, 0xfc, 0xf9, 0x47, 0xa5, 0xa5, 0x03, 0xb2, 0x96, 0x57, 0x6e, 0xef, 0xc0, 0xe6, 0x14, 0xcb, 0x59, 0x18, 0xb9, 0xf5, + 0xa6, 0xaa, 0x54, 0xb4, 0x8b, 0xf2, 0xe6, 0xbc, 0x87, 0x4c, 0x9d, 0x8c, 0x03, 0x1e, 0xe9, 0x81, 0x2f, 0x63, 0xd2, 0xfe, 0x88, 0x3f, 0x2f, 0x30, + 0x6a, 0xd1, 0xc5, 0x55, 0xd2, 0x1f, 0x29, 0x88, 0x2a, 0xf0, 0xb4, 0x73, 0x04, 0x60, 0xbb, 0x84, 0xab, 0xa7, 0x17, 0x2d, 0xbc, 0xe1, 0xa4, 0x49, +}; + +static const uint8_t TEE_ATTR_RSA_MODULUS_FOR_FUZZING_RSAN[] = { + 0xa8, 0xb3, 0xb2, 0x84, 0xaf, 0x8e, 0xb5, 0x0b, 0x38, 0x70, 0x34, 0xa8, 0x60, 0xf1, 0x46, 0xc4, 0x91, 0x9f, 0x31, 0x87, 0x63, 0xcd, 0x6c, 0x55, + 0x98, 0xc8, 0xae, 0x48, 0x11, 0xa1, 0xe0, 0xab, 0xc4, 0xc7, 0xe0, 0xb0, 0x82, 0xd6, 0x93, 0xa5, 0xe7, 0xfc, 0xed, 0x67, 0x5c, 0xf4, 0x66, 0x85, + 0x12, 0x77, 0x2c, 0x0c, 0xbc, 0x64, 0xa7, 0x42, 0xc6, 0xc6, 0x30, 0xf5, 0x33, 0xc8, 0xcc, 0x72, 0xf6, 0x2a, 0xe8, 0x33, 0xc4, 0x0b, 0xf2, 0x58, + 0x42, 0xe9, 0x84, 0xbb, 0x78, 0xbd, 0xbf, 0x97, 0xc0, 0x10, 0x7d, 0x55, 0xbd, 0xb6, 0x62, 0xf5, 0xc4, 0xe0, 0xfa, 0xb9, 0x84, 0x5c, 0xb5, 0x14, + 0x8e, 0xf7, 0x39, 0x2d, 0xd3, 0xaa, 0xff, 0x93, 0xae, 0x1e, 0x6b, 0x66, 0x7b, 0xb3, 0xd4, 0x24, 0x76, 0x16, 0xd4, 0xf5, 0xba, 0x10, 0xd4, 0xcf, + 0xd2, 0x26, 0xde, 0x88, 0xd3, 0x9f, 0x16, 0xfb, +}; + +static const uint8_t TEE_ATTR_RSA_MODULUS_VALUE01[] = { + 0xf0, 0x1a, 0x95, 0xcd, 0x5f, 0x9f, 0x1c, 0xbc, 0x5c, 0x2e, 0xc8, 0x00, 0x3b, 0xfa, + 0xe0, 0xd5, 0x72, 0xea, 0xfc, 0x9e, 0x74, 0xe1, 0x02, 0x66, 0xa8, 0x13, 0x3f, 0x0c, 0xe6, + 0x24, 0xcb, 0x1c, 0xa5, 0xdf, 0x64, 0xfb, 0x06, 0xd7, 0x13, 0xce, 0xaa, 0x6c, 0xee, 0x16, + 0x7b, 0xf8, 0x92, 0xaf, 0xc4, 0x5b, 0x46, 0x18, 0xc6, 0x30, 0xb6, 0x04, 0x1c, 0x3a, 0x2e, + 0xd7, 0xca, 0xb8, 0xb5, 0x00, 0x78, 0x89, 0xa0, 0x69, 0x37, 0x84, 0x59, 0x99, 0x0c, 0x2f, + 0x00, 0xe5, 0x3b, 0xe1, 0x18, 0xe0, 0xb9, 0x2e, 0x77, 0x1d, 0x32, 0x7e, 0x5f, 0xf4, 0x18, + 0xf3, 0x9f, 0x58, 0xc6, 0x83, 0xe2, 0x7a, 0xcb, 0x89, 0x18, 0xc2, 0x09, 0x84, 0x7e, 0x9d, + 0x96, 0xe0, 0xb9, 0x49, 0x75, 0xef, 0xcf, 0xff, 0xf0, 0xb6, 0x18, 0xd3, 0x7a, 0xc1, 0x6f, + 0x0c, 0x55, 0x33, 0xbe, 0x9d, 0x63, 0x06, 0xd6, 0x9f, 0xc1, 0xa5, 0xe9, 0xbd, 0xb1, 0xb2, + 0x5d, 0x5c, 0xf9, 0xab, 0xa9, 0xb5, 0x6a, 0x4e, 0xa4, 0xfa, 0x44, 0x32, 0xd6, 0x71, 0x2e, + 0x5f, 0xa6, 0x25, 0xf8, 0x40, 0x24, 0xc4, 0x5b, 0x61, 0x55, 0x1b, 0xac, 0xa3, 0x0a, 0x11, + 0x8e, 0x65, 0x20, 0xda, 0x2c, 0x0d, 0xdf, 0xdb, 0x47, 0x6b, 0x61, 0x18, 0x4d, 0xfe, 0xfd, + 0x2a, 0x7e, 0x77, 0x40, 0x44, 0x43, 0xc6, 0x33, 0x6c, 0xe5, 0x1b, 0x8d, 0x80, 0xf9, 0x97, + 0xa2, 0xe4, 0xb9, 0x34, 0x3e, 0x28, 0x94, 0x9f, 0xbd, 0xa8, 0x2b, 0x0a, 0x4d, 0x1a, 0xa8, + 0x06, 0xe5, 0x99, 0x4e, 0xb9, 0x13, 0x45, 0xc8, 0xf6, 0x0f, 0xd0, 0x4d, 0xbf, 0xe7, 0x8f, + 0xed, 0xca, 0x8e, 0xf8, 0x8d, 0x87, 0x5f, 0xd4, 0xb4, 0x1a, 0x2c, 0xc9, 0xa7, 0x67, 0x7e, + 0xb2, 0x1b, 0xc1, 0xce, 0xb6, 0x83, 0x7c, 0xce, 0xb4, 0x3d, 0x85, 0xc7, 0x53, 0x30, 0x7c, + 0xfe, 0x85, +}; + +static const uint8_t TEE_ATTR_RSA_OAEP_LABEL_VALUE01[] = { 1 }; + +static const uint8_t TEE_ATTR_RSA_PRIME1_VALUE01[] = { + 0xfe, 0x56, 0xe9, 0x8b, 0x84, 0xa4, 0x6f, 0x98, 0x45, 0xad, 0x05, 0xbc, 0x67, 0x04, + 0x5f, 0xae, 0x08, 0xdf, 0xe1, 0x8c, 0xcd, 0x49, 0x1d, 0x9d, 0x8e, 0x1e, 0x82, 0x47, 0x0c, + 0x3c, 0x70, 0x40, 0x2d, 0x61, 0xe7, 0xde, 0xd7, 0x6e, 0xb9, 0xeb, 0xf0, 0xa9, 0xff, 0x59, + 0xe1, 0xf8, 0xb7, 0x20, 0x9c, 0xc4, 0x13, 0xd0, 0xd6, 0x41, 0xfb, 0x2b, 0xb0, 0x9b, 0xf2, + 0x93, 0x20, 0x9a, 0x32, 0x67, 0xed, 0xaf, 0x25, 0xdc, 0xa8, 0xc2, 0x8f, 0x28, 0xab, 0xf8, + 0xed, 0xb1, 0x3f, 0x65, 0xd4, 0xe8, 0x48, 0xf2, 0x41, 0x88, 0x21, 0xcb, 0xab, 0x1e, 0xf7, + 0x97, 0x68, 0xe8, 0x32, 0x7d, 0xec, 0x18, 0xf1, 0x83, 0x91, 0x13, 0xf8, 0x8c, 0x89, 0xe1, + 0x0a, 0x6c, 0xff, 0x82, 0xc1, 0x07, 0x00, 0xbd, 0xbc, 0x20, 0xa3, 0x51, 0x6d, 0x86, 0x5a, + 0x19, 0x29, 0x19, 0x02, 0x2f, 0xed, 0x41, 0x08, 0x89, +}; + +static const uint8_t TEE_ATTR_RSA_PRIME2_VALUE01[] = { + 0xf1, 0xab, 0xe1, 0x59, 0x38, 0x71, 0x9e, 0x55, 0x22, 0x40, 0x6d, 0xa1, 0xc6, 0xb9, + 0x6d, 0xba, 0x57, 0x53, 0xec, 0xfd, 0xd2, 0x22, 0x2d, 0xba, 0x74, 0x9e, 0xdc, 0x33, 0x83, + 0xcd, 0x44, 0xd2, 0x7a, 0x63, 0xf3, 0xe0, 0x55, 0x5f, 0x4b, 0x03, 0xe5, 0x58, 0x7b, 0xe8, + 0x99, 0x5e, 0x8c, 0x75, 0x34, 0x3a, 0xa2, 0x96, 0x3c, 0x3b, 0x13, 0xaa, 0xb7, 0x58, 0x1d, + 0xad, 0x2c, 0x88, 0xbb, 0x99, 0x0a, 0x0b, 0xff, 0x9b, 0x68, 0x4d, 0x96, 0x1a, 0xe9, 0x52, + 0xf1, 0xa2, 0xcb, 0xb9, 0xe9, 0xe8, 0x63, 0x3d, 0x40, 0x14, 0x64, 0xb5, 0xd6, 0xe5, 0xf2, + 0x2a, 0x70, 0x4f, 0x1a, 0xab, 0x03, 0x63, 0xaa, 0x0d, 0xc7, 0xb3, 0xf3, 0x06, 0xb0, 0xca, + 0xb1, 0x48, 0x0d, 0x18, 0x63, 0x2e, 0xcc, 0xd9, 0xca, 0x2c, 0x5a, 0x1a, 0x75, 0x50, 0x0e, + 0x11, 0xb0, 0xd5, 0xa7, 0x74, 0x25, 0xe7, 0x0f, 0x1d, +}; + +static const uint8_t TEE_ATTR_RSA_PRIVATE_EXPONENT_3072_VALUE01[] = { + 0x09, 0x83, 0x77, 0x7b, 0xbe, 0x9c, 0x98, 0xdd, 0xdf, 0x0e, 0xa0, 0xde, 0x97, 0xa1, 0x3e, 0x3e, 0xd1, 0x86, 0x3a, 0x7b, 0x8b, 0xeb, 0x62, 0xd7, + 0xa3, 0x92, 0xfc, 0x17, 0xe8, 0x91, 0xa3, 0xe8, 0x25, 0x12, 0x3e, 0x71, 0xba, 0xf0, 0x2c, 0xa4, 0xef, 0xc4, 0xd8, 0xdc, 0xc7, 0x64, 0x15, 0xfb, + 0xc9, 0x9c, 0x13, 0x8f, 0xa3, 0x7c, 0x6c, 0x41, 0x4d, 0x36, 0x5d, 0x2c, 0x59, 0x54, 0x54, 0x8f, 0x6f, 0x88, 0xaf, 0xa3, 0x24, 0x48, 0x10, 0x09, + 0x0f, 0x63, 0x69, 0x11, 0x69, 0x46, 0x67, 0xff, 0x15, 0x52, 0x81, 0xb8, 0x31, 0x1a, 0x50, 0x28, 0xdd, 0x88, 0x75, 0xfb, 0x17, 0xad, 0x9d, 0xe0, + 0x58, 0x47, 0x0a, 0xfc, 0x54, 0xa9, 0xef, 0xf6, 0x22, 0xd0, 0xf8, 0x0a, 0x04, 0xa6, 0xea, 0xe7, 0x8a, 0x15, 0x36, 0xcd, 0x2c, 0xb5, 0xb1, 0x77, + 0xde, 0x39, 0xc0, 0x35, 0xfd, 0x2b, 0xfd, 0x0a, 0xf9, 0x1b, 0x65, 0xca, 0x32, 0x9d, 0x27, 0x9c, 0xfc, 0xcb, 0xca, 0x6d, 0x74, 0x97, 0x3c, 0x5a, + 0xb9, 0x4b, 0x35, 0xc0, 0x40, 0xaa, 0xe6, 0x1c, 0x01, 0x69, 0x2c, 0x95, 0xfa, 0x00, 0xd0, 0x2c, 0x2f, 0xc7, 0x2c, 0xf5, 0xee, 0x48, 0x50, 0x79, + 0x62, 0xbb, 0xfc, 0xd6, 0xc7, 0xe5, 0xc7, 0x78, 0xed, 0x91, 0xfd, 0xd8, 0x0f, 0x52, 0x90, 0x0d, 0x4e, 0x78, 0x66, 0x1a, 0x34, 0x3a, 0x20, 0x67, + 0xb6, 0xf9, 0xc7, 0x96, 0x43, 0xad, 0x28, 0x56, 0xd4, 0xc0, 0xd4, 0x9c, 0x19, 0x5a, 0x03, 0xef, 0x57, 0x72, 0x92, 0x34, 0xac, 0xd9, 0x51, 0x8d, + 0x3b, 0xef, 0xfa, 0x23, 0x04, 0xe7, 0xdc, 0xde, 0x0f, 0xdd, 0x8a, 0xd2, 0xc3, 0xd0, 0x92, 0x87, 0xb1, 0x0c, 0x32, 0x66, 0x27, 0x14, 0x07, 0x7c, + 0x19, 0xf8, 0x8c, 0x04, 0x77, 0x9d, 0x92, 0x6b, 0x78, 0xeb, 0x5a, 0xe2, 0xb3, 0x05, 0x06, 0x34, 0x49, 0x2c, 0x7d, 0x78, 0xfa, 0x66, 0xb7, 0xdd, + 0x73, 0x1d, 0xd4, 0x5c, 0xa9, 0x32, 0x37, 0x07, 0xe5, 0xc4, 0xf4, 0x1c, 0x97, 0x1c, 0x76, 0xe5, 0x3c, 0x04, 0x40, 0x3c, 0x22, 0x54, 0xdd, 0xa6, + 0x35, 0xcb, 0xb3, 0x50, 0x5a, 0x6c, 0xb5, 0x89, 0x33, 0xa6, 0x58, 0x70, 0x0a, 0x85, 0xd5, 0xb7, 0xa2, 0x50, 0x98, 0x68, 0x0c, 0xf3, 0xf4, 0xc0, + 0x20, 0x5b, 0x09, 0x95, 0x7e, 0x0f, 0xae, 0x8c, 0xf8, 0x19, 0x23, 0x0e, 0x61, 0x79, 0x96, 0xfd, 0x80, 0xed, 0x6d, 0x9a, 0xe5, 0x65, 0x64, 0x5b, + 0x29, 0x3f, 0x12, 0xaf, 0xa4, 0xc4, 0x07, 0x6d, 0x2e, 0xa6, 0x5b, 0xb6, 0x9a, 0xf5, 0x05, 0x8c, 0xeb, 0x5c, 0x4b, 0x3c, 0x68, 0x4b, 0xe0, 0x8a, + 0xcb, 0x60, 0x21, 0x47, 0x2b, 0xd9, 0x3a, 0x37, 0x27, 0x5a, 0x1c, 0x20, 0xfc, 0xdf, 0x05, 0xb2, 0x77, 0x56, 0xba, 0x10, 0x15, 0xd3, 0x84, 0xa3, +}; + +static const uint8_t TEE_ATTR_RSA_PRIVATE_EXPONENT_FOR_FUZZING_RSAD[] = { + 0x53, 0x33, 0x9c, 0xfd, 0xb7, 0x9f, 0xc8, 0x46, 0x6a, 0x65, 0x5c, 0x73, 0x16, 0xac, 0xa8, 0x5c, 0x55, 0xfd, 0x8f, 0x6d, 0xd8, 0x98, 0xfd, 0xaf, + 0x11, 0x95, 0x17, 0xef, 0x4f, 0x52, 0xe8, 0xfd, 0x8e, 0x25, 0x8d, 0xf9, 0x3f, 0xee, 0x18, 0x0f, 0xa0, 0xe4, 0xab, 0x29, 0x69, 0x3c, 0xd8, 0x3b, + 0x15, 0x2a, 0x55, 0x3d, 0x4a, 0xc4, 0xd1, 0x81, 0x2b, 0x8b, 0x9f, 0xa5, 0xaf, 0x0e, 0x7f, 0x55, 0xfe, 0x73, 0x04, 0xdf, 0x41, 0x57, 0x09, 0x26, + 0xf3, 0x31, 0x1f, 0x15, 0xc4, 0xd6, 0x5a, 0x73, 0x2c, 0x48, 0x31, 0x16, 0xee, 0x3d, 0x3d, 0x2d, 0x0a, 0xf3, 0x54, 0x9a, 0xd9, 0xbf, 0x7c, 0xbf, + 0xb7, 0x8a, 0xd8, 0x84, 0xf8, 0x4d, 0x5b, 0xeb, 0x04, 0x72, 0x4d, 0xc7, 0x36, 0x9b, 0x31, 0xde, 0xf3, 0x7d, 0x0c, 0xf5, 0x39, 0xe9, 0xcf, 0xcd, + 0xd3, 0xde, 0x65, 0x37, 0x29, 0xea, 0xd5, 0xd1, +}; + +static const uint8_t TEE_ATTR_RSA_PRIVATE_EXPONENT_VALUE01[] = { + 0xa5, 0x0d, 0xe1, 0x84, 0xf9, 0x02, 0xec, 0x42, 0x20, 0x2c, 0x98, 0x98, 0x70, 0xa3, + 0x1a, 0x04, 0x21, 0xa7, 0xa0, 0x59, 0x5d, 0x87, 0x80, 0x9b, 0x09, 0x57, 0x91, 0xb4, 0x50, + 0x51, 0x62, 0xbf, 0x22, 0xd7, 0xdb, 0x17, 0x25, 0xb0, 0x9c, 0x91, 0x29, 0x5f, 0x10, 0x9c, + 0xac, 0x44, 0x48, 0xb2, 0x43, 0x8d, 0x6b, 0x36, 0x84, 0xa7, 0xdf, 0xb8, 0x1b, 0x9f, 0x73, + 0xac, 0x2c, 0x53, 0xa5, 0x39, 0xd9, 0xa2, 0xe2, 0x7e, 0xf2, 0x07, 0x2d, 0x80, 0xa4, 0x7b, + 0x7b, 0x66, 0x1a, 0x2f, 0xb7, 0x66, 0x64, 0x66, 0xa8, 0xc3, 0x8d, 0x7e, 0x8a, 0x7f, 0xc6, + 0xd7, 0x52, 0xe7, 0x38, 0x30, 0x59, 0x74, 0x88, 0x8e, 0x8a, 0x52, 0x79, 0x30, 0x77, 0xc9, + 0xe5, 0x7a, 0x3e, 0x65, 0x5d, 0x89, 0xa9, 0xb7, 0x0b, 0xc6, 0x62, 0x72, 0x9e, 0xa4, 0x72, + 0xae, 0x4b, 0xb3, 0xf2, 0x89, 0x47, 0x15, 0xe0, 0x5b, 0x45, 0x4d, 0x99, 0x5b, 0x13, 0x6c, + 0x90, 0xbe, 0xe5, 0xb5, 0x98, 0xad, 0x87, 0x99, 0x1a, 0x57, 0xd4, 0x1f, 0xf1, 0x52, 0x71, + 0x5b, 0x51, 0x40, 0xdc, 0x51, 0x35, 0xf6, 0x6c, 0xae, 0xa3, 0xf9, 0x0f, 0x3a, 0xed, 0x28, + 0xfc, 0xa5, 0x60, 0x2f, 0x4b, 0x4f, 0x31, 0xac, 0x48, 0x3e, 0x5b, 0xba, 0xe4, 0x2b, 0x58, + 0x79, 0xe6, 0xb4, 0x6b, 0x5e, 0x56, 0x0a, 0xb2, 0xdb, 0x68, 0xed, 0x24, 0xd8, 0x5e, 0x6f, + 0x30, 0x59, 0x8d, 0x8c, 0xa3, 0x00, 0x68, 0xf5, 0x42, 0x95, 0x1a, 0x0b, 0xa8, 0x1c, 0xfb, + 0xdf, 0x29, 0x81, 0x10, 0x32, 0x02, 0xcc, 0x51, 0xa4, 0x17, 0x14, 0x3e, 0xef, 0x89, 0x41, + 0xde, 0xf8, 0x2d, 0x64, 0x69, 0x30, 0xe8, 0x8a, 0xad, 0x96, 0xf6, 0xf4, 0x82, 0x83, 0x9a, + 0x77, 0xe7, 0xde, 0x12, 0x31, 0xf7, 0x15, 0xec, 0xce, 0xed, 0x83, 0x68, 0x88, 0x84, 0xe5, + 0x64, 0x81, +}; + +static const uint8_t TEE_ATTR_RSA_PUBLIC_EXPONENT_3072_VALUE01[] = { + 0x53, 0x5c, 0x97, +}; + +static const uint8_t TEE_ATTR_RSA_PUBLIC_EXPONENT_FOR_FUZZING_RSAE[] = { + 0x01, 0x00, 0x01, +}; + +static const uint8_t TEE_ATTR_RSA_PUBLIC_EXPONENT_VALUE_GEN_OUT_OF_RANGE_SUP[] = { + 0x01, + 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, 0x01, +}; + +static const uint8_t TEE_ATTR_SECRET_VALUE_1024_SHARED_SECRET_DH_VALUE01[] = { + 0x4e, 0x6a, 0xcf, 0xfd, 0x7d, 0x14, 0x27, 0x65, 0xeb, 0xf4, 0xc7, 0x12, 0x41, 0x4f, 0xe4, 0xb6, + 0xab, 0x95, 0x7f, 0x4c, 0xb4, 0x66, 0xb4, 0x66, 0x01, 0x28, 0x9b, 0xb8, 0x20, 0x60, 0x42, 0x82, + 0x72, 0x84, 0x2e, 0xe2, 0x8f, 0x11, 0x3c, 0xd1, 0x1f, 0x39, 0x43, 0x1c, 0xbf, 0xfd, 0x82, 0x32, + 0x54, 0xce, 0x47, 0x2e, 0x21, 0x05, 0xe4, 0x9b, 0x3d, 0x7f, 0x11, 0x3b, 0x82, 0x50, 0x76, 0xe6, + 0x26, 0x45, 0x85, 0x80, 0x7b, 0xc4, 0x64, 0x54, 0x66, 0x5f, 0x27, 0xc5, 0xe4, 0xe1, 0xa4, 0xbd, + 0x03, 0x47, 0x04, 0x86, 0x32, 0x29, 0x81, 0xfd, 0xc8, 0x94, 0xcc, 0xa1, 0xe2, 0x93, 0x09, 0x87, + 0xc9, 0x2c, 0x15, 0xa3, 0x8b, 0xc4, 0x2e, 0xb3, 0x88, 0x10, 0xe8, 0x67, 0xc4, 0x43, 0x2f, 0x07, + 0x25, 0x9e, 0xc0, 0x0c, 0xdb, 0xbb, 0x0f, 0xb9, 0x9e, 0x17, 0x27, 0xc7, 0x06, 0xda, 0x58, 0xdd, +}; + +static const uint8_t TEE_ATTR_SECRET_VALUE_192_SHARED_SECRET_ECDH_VALUE01[] = { + 0x80, 0x3d, 0x8a, 0xb2, 0xe5, 0xb6, 0xe6, 0xfc, 0xa7, 0x15, 0x73, 0x7c, 0x3a, 0x82, 0xf7, 0xce, + 0x3c, 0x78, 0x31, 0x24, 0xf6, 0xd5, 0x1c, 0xd0, +}; + +static const uint8_t TEE_ATTR_SECRET_VALUE_224_SHARED_SECRET_ECDH_VALUE01[] = { + 0x7d, 0x96, 0xf9, 0xa3, 0xbd, 0x3c, 0x05, 0xcf, 0x5c, 0xc3, 0x7f, 0xeb, 0x8b, 0x9d, 0x52, 0x09, + 0xd5, 0xc2, 0x59, 0x74, 0x64, 0xde, 0xc3, 0xe9, 0x98, 0x37, 0x43, 0xe8, +}; + +static const uint8_t TEE_ATTR_SECRET_VALUE_256_SHARED_SECRET_ECDH_VALUE01[] = { + 0x46, 0xfc, 0x62, 0x10, 0x64, 0x20, 0xff, 0x01, 0x2e, 0x54, 0xa4, 0x34, 0xfb, 0xdd, 0x2d, 0x25, + 0xcc, 0xc5, 0x85, 0x20, 0x60, 0x56, 0x1e, 0x68, 0x04, 0x0d, 0xd7, 0x77, 0x89, 0x97, 0xbd, 0x7b, +}; + +static const uint8_t TEE_ATTR_SECRET_VALUE_384_SHARED_SECRET_ECDH_VALUE01[] = { + 0x5f, 0x9d, 0x29, 0xdc, 0x5e, 0x31, 0xa1, 0x63, 0x06, 0x03, 0x56, 0x21, 0x36, 0x69, 0xc8, 0xce, + 0x13, 0x2e, 0x22, 0xf5, 0x7c, 0x9a, 0x04, 0xf4, 0x0b, 0xa7, 0xfc, 0xea, 0xd4, 0x93, 0xb4, 0x57, + 0xe5, 0x62, 0x1e, 0x76, 0x6c, 0x40, 0xa2, 0xe3, 0xd4, 0xd6, 0xa0, 0x4b, 0x25, 0xe5, 0x33, 0xf1, +}; + +static const uint8_t TEE_ATTR_SECRET_VALUE_4096_VALUE01[] = { + 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, + 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, + 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, + 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, + 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, + 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, +}; + +static const uint8_t TEE_ATTR_SECRET_VALUE_521_SHARED_SECRET_ECDH_VALUE01[] = { + 0x00, 0x5f, 0xc7, 0x04, 0x77, 0xc3, 0xe6, 0x3b, 0xc3, 0x95, 0x4b, 0xd0, 0xdf, 0x3e, 0xa0, 0xd1, + 0xf4, 0x1e, 0xe2, 0x17, 0x46, 0xed, 0x95, 0xfc, 0x5e, 0x1f, 0xdf, 0x90, 0x93, 0x0d, 0x5e, 0x13, + 0x66, 0x72, 0xd7, 0x2c, 0xc7, 0x70, 0x74, 0x2d, 0x17, 0x11, 0xc3, 0xc3, 0xa4, 0xc3, 0x34, 0xa0, + 0xad, 0x97, 0x59, 0x43, 0x6a, 0x4d, 0x3c, 0x5b, 0xf6, 0xe7, 0x4b, 0x95, 0x78, 0xfa, 0xc1, 0x48, + 0xc8, 0x31, +}; + +static const uint32_t TEE_ATTR_VALUE_ZERO; + +/* + * Values are 32 bits, while this is 64 so it can never clash with a real + * value. + */ +#define TEE_ATTR_VALUE_NONE 0xffffffffffffffff + +static uint32_t TEE_ATTR_RSA_PUBLIC_EXPONENT_VALUE01[] = { 0x10001 }; + +static const uint8_t BUFFER01[] = { + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, +}; + +static const uint8_t INITIAL_DATA[] = { + 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, + 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, +}; + +static const uint8_t SINGLE_BYTE[] = { 0 }; + +/** ALL_TEEC_UUID + * + * These constants are the UUID of existing + * Trusted Applications + */ +/* "SMARTCSLTDATAST1" */ +static TEEC_UUID UUID_TTA_testingInternalAPI_dataStorage = { + 0x534D4152, 0x5443, 0x534C, + { 0x54, 0x44, 0x41, 0x54, 0x41, 0x53, 0x54, 0x31 } +}; + +static TEEC_Result Invoke_ReadObjectData( + ADBG_Case_t *c, TEEC_Session *sess, uint32_t cmdId, + uint32_t obj_handle, uint32_t buffer, uint32_t buffer_size) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + ALLOCATE_SHARED_MEMORY(sess->ctx, SHARE_MEM01, buffer_size, + TEEC_MEM_OUTPUT, mem01_exit) + + op.params[0].value.a = obj_handle; + op.params[0].value.b = buffer; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_NONE, TEEC_NONE); + + free(saved_obj_data); + saved_obj_data = NULL; + saved_obj_data_size = 0; + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + if (!res) { + size_t sz = op.params[1].memref.size; + + saved_obj_data = malloc(sz); + memcpy(saved_obj_data, SHARE_MEM01->buffer, sz); + saved_obj_data_size = sz; + } + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +#define Check_ReadObjectData_DataRead(c, data, data_size) \ + ADBG_EXPECT_BUFFER(c, data, data_size, saved_obj_data, \ + saved_obj_data_size) + +#define Check_ReadObjectData_AfterWrite(c, data, data_size) \ + ADBG_EXPECT_BUFFER(c, data, data_size, saved_obj_data, \ + saved_obj_data_size) + +static TEEC_Result Invoke_RenamePersistentObject(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmdId, + uint32_t obj_handle, + const char *new_obj_id, + bool use_parameter_buffer) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + size_t obj_id_len = 0; + uint32_t org = 0; + + if (new_obj_id) + obj_id_len = strlen(new_obj_id); + ALLOCATE_AND_FILL_SHARED_MEMORY(sess->ctx, SHARE_MEM01, obj_id_len, + TEEC_MEM_INPUT, obj_id_len, new_obj_id, + mem01_exit); + + op.params[0].value.a = obj_handle; + op.params[1].value.a = use_parameter_buffer; + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_AllocateTransientObject(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t obj_type, + uint32_t obj_size, + uint32_t obj_handle) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, obj_handle, 0, obj_type, + obj_size); +} + +static TEEC_Result Invoke_GetObjectInfo1(ADBG_Case_t *c, + TEEC_Session *sess, uint32_t cmd, + uint32_t obj_handle, uint32_t obj_info) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res; + uint32_t org; + + op.params[0].value.a = obj_handle; + op.params[0].value.b = obj_info; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, TEEC_VALUE_OUTPUT); + + memset(saved_obj_info, 0, sizeof(saved_obj_info[0])); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + if (!res) { + saved_obj_info[0].obj_type = op.params[0].value.b; + saved_obj_info[0].obj_size = op.params[1].value.a; + saved_obj_info[0].max_obj_size = op.params[1].value.b; + saved_obj_info[0].obj_usage = op.params[2].value.a; + saved_obj_info[0].data_size = op.params[2].value.b; + saved_obj_info[0].data_pos = op.params[3].value.a; + saved_obj_info[0].handle_flags = op.params[3].value.b; + } + + return res; +} + +static TEEC_Result Invoke_GetObjectInfo(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t obj_handle, + uint32_t obj_info) +{ + return Invoke_GetObjectInfo1(c, sess, cmd, obj_handle, obj_info); +} + +#define check_saved_obj_info(c, n, IN_ObjectType, IN_KeySize, IN_MaxKeySize, \ + IN_ObjectUsage, IN_DataSize, IN_DataPosition, \ + IN_HandleFlags_Data) \ + do { \ + if (ADBG_EXPECT_COMPARE_UNSIGNED(c, n, <, \ + MAX_NUM_SAVED_OBJ_INFO)) { \ + ADBG_EXPECT(c, IN_ObjectType, \ + saved_obj_info[n].obj_type); \ + ADBG_EXPECT(c, IN_KeySize, \ + saved_obj_info[n].obj_size); \ + ADBG_EXPECT(c, IN_MaxKeySize, \ + saved_obj_info[n].max_obj_size); \ + ADBG_EXPECT(c, IN_ObjectUsage, \ + saved_obj_info[n].obj_usage); \ + ADBG_EXPECT(c, IN_DataSize, \ + saved_obj_info[n].data_size); \ + ADBG_EXPECT(c, IN_DataPosition, \ + saved_obj_info[n].data_pos); \ + ADBG_EXPECT(c, IN_HandleFlags_Data, \ + saved_obj_info[n].handle_flags); \ + } \ + } while (0) + +#define Check_ObjectInfo(c, IN_ObjectType, IN_KeySize, IN_MaxKeySize, \ + IN_ObjectUsage, IN_DataSize, IN_DataPosition, \ + IN_HandleFlags_Handle, IN_HandleFlags_Data) \ + do { \ + check_saved_obj_info(c, 0, IN_ObjectType, IN_KeySize, \ + IN_MaxKeySize, IN_ObjectUsage, \ + IN_DataSize, IN_DataPosition, \ + IN_HandleFlags_Data); \ + ADBG_EXPECT(c, IN_HandleFlags_Handle, 0); \ + } while (0) + +#define set_handle_flag(c, vector, flag) do { (vector) |= (flag); } while (0) +#define set_usage_flag(c, vector, flag) do { (vector) |= (flag); } while (0) +#define clear_usage_flag(c, vector, flag) do { (vector) &= ~(flag); } while (0) +#define set_data_flag(c, vector, flag) do { (vector) |= (flag); } while (0) +#define clear_data_flag(c, vector, flag) do { (vector) &= ~(flag); } while (0) + +static TEEC_Result Invoke_RestrictObjectUsage1(ADBG_Case_t *c, + TEEC_Session *sess, uint32_t cmd, + uint32_t obj_handle, + uint32_t obj_usage) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_handle, obj_usage); +} + +static TEEC_Result Invoke_RestrictObjectUsage(ADBG_Case_t *c, + TEEC_Session *sess, uint32_t cmd, + uint32_t obj_handle, + uint32_t obj_usage) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_handle, obj_usage); +} + +static TEEC_Result Invoke_ResetTransientObject(ADBG_Case_t *c, + TEEC_Session *sess, uint32_t cmd, + uint32_t obj_handle) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_handle, 0); +} + +static TEEC_Result Invoke_CloseAndDeletePersistentObject1(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t obj_handle) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_handle, 0); +} + +static TEEC_Result Invoke_CloseAndDeletePersistentObject(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t obj_handle) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_handle, 0); +} + +static TEEC_Result Invoke_CloseObject(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t obj_handle) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_handle, 0); +} + +static TEEC_Result Invoke_CreatePersistentObject(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t storage_id, + const char *obj_id, + uint32_t flags, + uint32_t attrs_obj_handle, + const void *initial_data, + size_t initial_data_len, + uint32_t obj_handle) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEE_SUCCESS; + uint32_t org = 0; + static TEEC_SharedMemory shm_obj_id = { }; + static TEEC_SharedMemory shm_data = { }; + + shm_obj_id.size = strlen(obj_id); + shm_obj_id.flags = TEEC_MEM_INPUT; + res = TEEC_AllocateSharedMemory(sess->ctx, &shm_obj_id); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + memcpy(shm_obj_id.buffer, obj_id, shm_obj_id.size); + + shm_data.size = initial_data_len; + shm_data.flags = TEEC_MEM_INPUT; + res = TEEC_AllocateSharedMemory(sess->ctx, &shm_data); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out_free_obj_id; + memcpy(shm_data.buffer, initial_data, shm_data.size); + + op.params[0].value.a = obj_handle; + op.params[0].value.b = storage_id; + op.params[1].value.a = flags; + op.params[1].value.b = attrs_obj_handle; + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, &shm_obj_id, + shm_obj_id.size); + SET_SHARED_MEMORY_OPERATION_PARAMETER(3, 0, &shm_data, shm_data.size); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + TEEC_ReleaseSharedMemory(&shm_data); +out_free_obj_id: + TEEC_ReleaseSharedMemory(&shm_obj_id); + + return res; +} + +static TEEC_Result Invoke_OpenPersistentObject(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t storage_id, + const char *obj_id, + uint32_t flags, + uint32_t obj_handle) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEE_SUCCESS; + uint32_t org = 0; + static TEEC_SharedMemory shm = { }; + + shm.size = strlen(obj_id); + shm.flags = TEEC_MEM_INPUT; + res = TEEC_AllocateSharedMemory(sess->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + memcpy(shm.buffer, obj_id, shm.size); + + op.params[0].value.a = obj_handle; + op.params[0].value.b = storage_id; + op.params[1].value.a = flags; + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, &shm, shm.size); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + TEEC_ReleaseSharedMemory(&shm); + + return res; +} + +#define add_attribute(c, vector, attr) do { (vector) |= BIT((attr)); } while (0) + +static uint32_t get_attribute_and_advance(uint32_t attr_list, size_t *n) +{ + while (*n < 32) { + size_t bit_idx = *n; + + (*n)++; + if (attr_list & BIT(bit_idx)) + return bit_idx; + } + + return ATTRIBUTE_NONE; +} + +static TEEC_Result Invoke_PopulateTransientObject(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t obj_handle, + uint32_t attr_list) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + size_t n = 0; + + op.params[0].value.a = obj_handle; + op.params[1].value.a = get_attribute_and_advance(attr_list, &n); + op.params[1].value.b = get_attribute_and_advance(attr_list, &n); + op.params[2].value.a = get_attribute_and_advance(attr_list, &n); + op.params[2].value.b = get_attribute_and_advance(attr_list, &n); + op.params[3].value.a = get_attribute_and_advance(attr_list, &n); + op.params[3].value.b = get_attribute_and_advance(attr_list, &n); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, TEEC_VALUE_INPUT); + + return TEEC_InvokeCommand(sess, cmd, &op, &org); +} + +static TEEC_Result Invoke_CopyObjectAttributes1(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t dest_obj, + uint32_t src_obj) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, dest_obj, src_obj); +} + +static TEEC_Result Invoke_CopyObjectAttributes(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t dest_obj, + uint32_t src_obj) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, dest_obj, src_obj); +} + +static TEEC_Result Invoke_InitValueAttribute(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t attr, + uint32_t attr_id, uint32_t a, + uint32_t a_size, + uint32_t b, + uint32_t b_size) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, attr, attr_id, a, b); +} + +static TEEC_Result Invoke_AllocatePersistentObjectEnumerator(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t obj_enum) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_enum, 0); +} + +static TEEC_Result Invoke_StartPersistentObjectEnumerator(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t obj_enum, + uint32_t storage_id) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_enum, storage_id); +} + +static TEEC_Result Invoke_ResetPersistentObjectEnumerator(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t obj_enum) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_enum, 0); +} + +static TEEC_Result Invoke_GetNextPersistentObject_All(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t obj_enum, + uint32_t obj_info, + uint32_t count) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + static TEEC_SharedMemory shm = { }; + TEEC_Result res = TEEC_SUCCESS; + uint32_t org = 0; + size_t n = 0; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, count, <, MAX_NUM_SAVED_OBJ_INFO)) + return TEEC_ERROR_BAD_PARAMETERS; + + shm.size = TEE_OBJECT_ID_MAX_LEN; + shm.flags = TEEC_MEM_OUTPUT; + res = TEEC_AllocateSharedMemory(sess->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + for (n = 0; n < count; n++) { + memset(&op, 0, sizeof(op)); + op.params[0].value.a = obj_enum; + op.params[0].value.b = obj_info; + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, &shm, shm.size); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_NONE); + res = TEEC_InvokeCommand(sess, CMD_DS_GetNextPersistentObject, + &op, &org); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + break; + + memcpy(&saved_obj_info[n].obj_id, shm.buffer, + sizeof(saved_obj_info[n].obj_id)); + saved_obj_info[n].obj_id_len = op.params[2].memref.size; + + memset(&op, 0, sizeof(op)); + op.params[0].value.a = obj_info; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, + TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT); + res = TEEC_InvokeCommand(sess, CMD_DS_Retrieve_ObjectInfo, + &op, &org); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + break; + saved_obj_info[n].obj_type = op.params[0].value.b; + saved_obj_info[n].obj_size = op.params[1].value.a; + saved_obj_info[n].max_obj_size = op.params[1].value.b; + saved_obj_info[n].obj_usage = op.params[2].value.a; + saved_obj_info[n].data_size = op.params[2].value.b; + saved_obj_info[n].data_pos = op.params[3].value.a; + saved_obj_info[n].handle_flags = op.params[3].value.b; + } + + TEEC_ReleaseSharedMemory(&shm); + return res; +} + +static int find_saved_obj_id(const void *obj_id, size_t obj_id_len) +{ + int n = 0; + + for (n = 0; n < MAX_NUM_SAVED_OBJ_INFO; n++) + if (obj_id_len == saved_obj_info[n].obj_id_len && + !memcmp(saved_obj_info[n].obj_id, obj_id, obj_id_len)) + return n; + + return -1; +} + +#define Check_EnumeratedPersistentObject(c, IN_ObjectID, IN_ObjectType, \ + IN_KeySize, IN_MaxKeySize, \ + IN_ObjectUsage, IN_DataSize, \ + IN_HandleFlags_Handle, \ + IN_HandleFlags_Data) \ + do { \ + int n = find_saved_obj_id(IN_ObjectID, strlen(IN_ObjectID)); \ + \ + if (!ADBG_EXPECT_COMPARE_SIGNED(c, n, >=, 0)) \ + break; \ + ADBG_EXPECT(c, IN_ObjectType, saved_obj_info[n].obj_type); \ + ADBG_EXPECT(c, IN_KeySize, saved_obj_info[n].obj_size); \ + ADBG_EXPECT(c, IN_MaxKeySize, saved_obj_info[n].max_obj_size); \ + ADBG_EXPECT(c, IN_DataSize, saved_obj_info[n].data_size); \ + ADBG_EXPECT(c, IN_HandleFlags_Handle | IN_HandleFlags_Data, \ + saved_obj_info[n].handle_flags); \ + } while (0) + + +static TEEC_Result +Invoke_GetNextPersistentObject_ErrorChecking(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t obj_enum, + uint32_t obj_info, + bool obj_id_is_null, + bool obj_id_len_is_null) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, obj_enum, obj_info, + obj_id_is_null, obj_id_len_is_null); +} + +static TEEC_Result Invoke_FreePersistentObjectEnumerator(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, + uint32_t obj_enum) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_enum, 0); +} + + +static TEEC_Result Invoke_GenerateKey(ADBG_Case_t *c, + TEEC_Session *sess, uint32_t cmd, + uint32_t obj_handle, uint32_t key_size, + uint32_t attr_list) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + size_t n = 0; + + op.params[0].value.a = obj_handle; + op.params[0].value.b = key_size; + + op.params[1].value.a = get_attribute_and_advance(attr_list, &n); + op.params[1].value.b = get_attribute_and_advance(attr_list, &n); + op.params[2].value.a = get_attribute_and_advance(attr_list, &n); + op.params[2].value.b = get_attribute_and_advance(attr_list, &n); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + + return TEEC_InvokeCommand(sess, cmd, &op, &org); +} + +static TEEC_Result GetObjectValueAttribute_helper(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t n, uint32_t cmd, + uint32_t obj, + uint32_t attr_id, + bool extract_a, + bool extract_b) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEE_SUCCESS; + uint32_t org = 0; + + op.params[0].value.a = obj; + op.params[0].value.b = attr_id; + op.params[1].value.a = extract_a; + op.params[1].value.b = extract_b; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_VALUE_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + if (!res) { + memcpy(saved_attr[n].buf, &op.params[2].value, + sizeof(op.params[2].value)); + saved_attr[n].buf_size = sizeof(op.params[2].value); + saved_attr[n].attr_id = attr_id; + } else { + memset(saved_attr + n, 0, sizeof(saved_attr[n])); + } + + return res; +} + +static TEEC_Result get_value_attr(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t n, uint32_t obj, uint32_t attr_id) +{ + return GetObjectValueAttribute_helper(c, sess, n, + CMD_DS_GetObjectValueAttribute, + obj, attr_id, true, true); +} + +static TEEC_Result get_buffer_attr(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t n, uint32_t obj, uint32_t attr_id) +{ + return GetObjectBufferAttribute_helper(c, sess, n, + CMD_DS_GetObjectBufferAttribute, + obj, attr_id, false, + BIG_ATTRIBUTE_BUFFER_SIZE); +} + +static TEEC_Result GetAttributes_helper(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t obj, const uint32_t attr_ids[], + size_t num_attr_ids) +{ + TEEC_Result res = TEE_SUCCESS; + size_t n = 0; + + for (n = 0; n < num_attr_ids; n++) { + if (attr_ids[n] & BIT(29)) + res = get_value_attr(c, sess, n, obj, attr_ids[n]); + else + res = get_buffer_attr(c, sess, n, obj, attr_ids[n]); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + break; + } + + return res; +} + +static TEEC_Result Macro_GetDHAttributes(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t obj) +{ + const uint32_t attrs[] = { + TEE_ATTR_DH_PRIME, TEE_ATTR_DH_BASE, + TEE_ATTR_DH_PUBLIC_VALUE, TEE_ATTR_DH_PRIVATE_VALUE, + TEE_ATTR_DH_X_BITS, + }; + + return GetAttributes_helper(c, sess, obj, attrs, + sizeof(attrs) / sizeof(attrs[0])); +} + +/* TODO check the attributes too */ +#define Check_GeneratedDHAttributes(c) \ + do { ADBG_EXPECT_TRUE(c, true); } while (0) + +static TEEC_Result Invoke_GetObjectValueAttribute(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, uint32_t obj, + uint32_t attr_id, + bool extract_a, + bool extract_b) +{ + return GetObjectValueAttribute_helper(c, sess, 0, cmd, obj, + attr_id, extract_a, extract_b); +} + +static TEEC_Result Macro_GetRSAAttributes(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t obj) +{ + const uint32_t attrs[] = { + TEE_ATTR_RSA_MODULUS, TEE_ATTR_RSA_PUBLIC_EXPONENT, + TEE_ATTR_RSA_PRIVATE_EXPONENT, TEE_ATTR_RSA_PRIME1, + TEE_ATTR_RSA_PRIME2, TEE_ATTR_RSA_EXPONENT1, + TEE_ATTR_RSA_EXPONENT2, TEE_ATTR_RSA_COEFFICIENT, + }; + + return GetAttributes_helper(c, sess, obj, attrs, + sizeof(attrs) / sizeof(attrs[0])); +} + +/* TODO check the attributes too */ +#define Check_GeneratedRSAAttributes(c) \ + do { ADBG_EXPECT_TRUE(c, true); } while (0) + +#define Check_ObjectBufferAttribute(c, attr_buf, attr_buf_len) \ + do { \ + ADBG_EXPECT_BUFFER(c, attr_buf, attr_buf_len, \ + saved_attr[0].buf, \ + saved_attr[0].buf_size); \ + } while (0) + +static bool check_values(uint64_t a, uint64_t b, const uint8_t buf[], + size_t blen) +{ + uint32_t exp_val = 0; + + if (blen != sizeof(uint32_t) * 2) + return false; + + if (a != TEE_ATTR_VALUE_NONE) { + memcpy(&exp_val, buf, sizeof(exp_val)); + if (a != exp_val) + return false; + } + + if (b != TEE_ATTR_VALUE_NONE) { + memcpy(&exp_val, buf + sizeof(uint32_t), sizeof(exp_val)); + if (b != exp_val) + return false; + } + + return true; +} + +#define Check_ObjectValueAttribute(c, a, a_size, b, b_size) \ + ADBG_EXPECT_TRUE(c, check_values(a, b, saved_attr[0].buf, \ + saved_attr[0].buf_size)) + +static TEEC_Result Invoke_StoreBuffer(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t buffer, + const void *data, size_t size) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEE_SUCCESS; + uint32_t org = 0; + static TEEC_SharedMemory shm_data = { }; + unsigned int pt1 = 0; + + op.params[0].value.a = buffer; + if (data) { + shm_data.size = size; + shm_data.flags = TEEC_MEM_INPUT; + res = TEEC_AllocateSharedMemory(sess->ctx, &shm_data); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + memcpy(shm_data.buffer, data, shm_data.size); + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, &shm_data, + shm_data.size); + pt1 = TEEC_MEMREF_PARTIAL_INPUT; + } else { + op.params[1].value.a = size; + pt1 = TEEC_VALUE_INPUT; + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, pt1, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + TEEC_ReleaseSharedMemory(&shm_data); + + return res; +} + +static TEEC_Result Invoke_SeekObjectData(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t obj_handle, + ssize_t offset, int whence) +{ + uint32_t offs; + uint32_t offs_negative; + + if (offset >= 0) { + offs = offset; + offs_negative = 0; + } else { + offs = -offset; + offs_negative = 1; + } + + return Invoke_Simple_Function_v3(c, sess, cmd, obj_handle, 0, + offs, offs_negative, whence, 0); +} + +static TEEC_Result Invoke_WriteObjectData(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t obj_handle, + uint32_t buffer) +{ + return Invoke_Simple_Function_v1(c, sess, cmd, obj_handle, buffer); +} + +static TEEC_Result Invoke_TruncateObjectData(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t obj_handle, + uint32_t size) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, obj_handle, 0, size, 0); +} + +static TEEC_Result Invoke_StoreAttributeBuffer(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, uint32_t buffer, + const void *value_bufptr, + size_t value_size) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEE_SUCCESS; + uint32_t org = 0; + static TEEC_SharedMemory shm = { }; + + shm.size = value_size; + shm.flags = TEEC_MEM_INPUT; + res = TEEC_AllocateSharedMemory(sess->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + memcpy(shm.buffer, value_bufptr, shm.size); + + op.params[0].value.a = buffer; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, &shm, shm.size); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + TEEC_ReleaseSharedMemory(&shm); + + return res; +} + +static TEEC_Result Invoke_InitRefAttribute(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t attr, + uint32_t attr_id, uint32_t buffer) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, attr, attr_id, + buffer, 0); +} + +static TEEC_Result +Macro_StoreRefAttribute(ADBG_Case_t *c, TEEC_Session *sess, uint32_t attr, + uint32_t buffer, uint32_t attr_id, + const void *value_bufptr, size_t value_size) +{ + TEEC_Result res = TEE_SUCCESS; + + res = Invoke_StoreAttributeBuffer(c, sess, CMD_DS_StoreBuffer, + buffer, value_bufptr, value_size); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + res = Invoke_InitRefAttribute(c, sess, CMD_DS_InitRefAttribute, + attr, attr_id, buffer); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + return res; +} + + + +#endif /* XML_DATASTORAGE_API_H_ */ diff --git a/optee/optee_test/host/xtest/gp/include/xml_internal_api.h b/optee/optee_test/host/xtest/gp/include/xml_internal_api.h new file mode 100644 index 0000000..3ac5199 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/include/xml_internal_api.h @@ -0,0 +1,733 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef XML_INTERNAL_API_H_ +#define XML_INTERNAL_API_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xml_common_api.h" +#include "xtest_helpers.h" +#include "xtest_test.h" + +#define Invoke_MaskUnmaskCancellations Invoke_Simple_Function +#define Invoke_ProcessTAInvoke_Payload_Value Invoke_Simple_Function +#define Invoke_ProcessTAInvoke_Payload_Value_In_Out Invoke_Simple_Function +#define Invoke_ProcessTAInvoke_Payload_Memref Invoke_Simple_Function + +#define Invoke_GetPropertyAsBool_withoutEnum Invoke_GetPropertyAsXXX_withoutEnum +#define Invoke_GetPropertyAsU32_withoutEnum Invoke_GetPropertyAsXXX_withoutEnum +#define Invoke_GetPropertyAsUUID_withoutEnum Invoke_GetPropertyAsXXX_withoutEnum +#define Invoke_GetPropertyAsIdentity_withoutEnum \ + Invoke_GetPropertyAsXXX_withoutEnum +#define Invoke_GetPropertyAsBinaryBlock_withoutEnum \ + Invoke_GetPropertyAsXXX_withoutEnum +#define Invoke_GetPropertyAsString_withoutEnum \ + Invoke_GetPropertyAsXXX_withoutEnum + +#define Invoke_GetPropertyAsXXXX_fromEnum Invoke_StartPropertyEnumerator + +#define Invoke_FreePropertyEnumerator Invoke_ResetPropertyEnumerator +#define Invoke_GetNextProperty_enumNotStarted Invoke_ResetPropertyEnumerator + +#define Invoke_ProcessTAInvoke_DeadErrorSuccess \ + Invoke_ProcessInvokeTAOpenSession + +#define CLIENT_APP01 NULL + +#define TEEC_UNDEFINED_ERROR 0xDEADDEAD + +#define TEEC_ORIGIN_ANY_NOT_TRUSTED_APP 0x00000005 +/* same as TEE_ORIGIN_NOT_TRUSTED_APP */ + +#define SIZE_ZERO 0 + +#define TEE_ERROR_TOO_SHORT_BUFFER TEE_ERROR_SHORT_BUFFER + +#define CMD_TEE_GetPropertyAsString_withoutEnum 0x00000010 +#define CMD_TEE_GetPropertyAsBool_withoutEnum 0x00000015 +#define CMD_TEE_GetPropertyAsInt_withoutEnum 0x00000020 +#define CMD_TEE_GetPropertyAsBinaryBlock_withoutEnum 0x00000025 +#define CMD_TEE_GetPropertyAsUUID_withoutEnum 0x00000030 +#define CMD_TEE_GetPropertyAsIdentity_withoutEnum 0x00000035 +#define CMD_TEE_GetPropertyAsXXXX_fromEnum 0x00000045 +#define CMD_TEE_AllocatePropertyEnumerator 0x00000060 +#define CMD_TEE_StartPropertyEnumerator 0x00000065 +#define CMD_TEE_ResetPropertyEnumerator 0x00000070 +#define CMD_TEE_FreePropertyEnumerator 0x00000075 +#define CMD_TEE_GetPropertyName 0x00000080 +#define CMD_TEE_Malloc 0x00000100 +#define CMD_TEE_Realloc 0x00000110 +#define CMD_TEE_MemMove 0x00000120 +#define CMD_TEE_MemCompare 0x00000130 +#define CMD_TEE_MemFill 0x00000140 +#define CMD_TEE_Panic 0x00000104 +#define CMD_TEE_CheckMemoryAccessRight 0x00000103 +#define CMD_TEE_GetCancellationFlag_RequestedCancel 0x00000105 +#define CMD_TEE_MaskUnmaskCancellations 0x00000106 +#define CMD_TEE_Free 0x00000107 +#define CMD_ProcessInvokeTAOpenSession 0x00000200 +#define CMD_ProcessTAInvokeTA_simple 0x00000201 +#define CMD_ProcessTAInvokeTA_PayloadValue 0x00000202 +#define CMD_TEE_GetNextPropertyEnumerator_notStarted 0x00000203 +#define CMD_ProcessTAInvokeTA_PayloadMemref 0x00000204 +#define CMD_ProcessTAInvokeTA_PayloadValue_In_Out 0x00000205 +#define CMD_TEE_OpenTASession 0x00000300 +#define CMD_TEE_InvokeTACommand 0x00000301 +#define CMD_TEE_CloseTASession 0x00000302 + +#define CMD_SUCCESS 1 +#define CMD_SET_PANIC_ON_DESTROY 1 + +static TEEC_SharedMemory share_mem[2]; +static TEEC_SharedMemory *SHARE_MEM01 = share_mem; +static TEEC_SharedMemory *SHARE_MEM02 = share_mem + 1; +static TEEC_Session session[2]; +static TEEC_Session *SESSION01 = session; +static TEEC_Session *SESSION02 = session + 1; +static TEEC_Context context[2]; +static TEEC_Context *CONTEXT01 = context; +static TEEC_Context *CONTEXT02 = context + 1; + +#define TA_SESSION01 0 +#define TA_SESSION02 1 +#define TA_SESSION_NULL 0xffffffff + +static uint32_t BIG_SIZE = 1024; + +static char *NO_DATA; +static uint64_t enumerator1; +static uint64_t *ENUMERATOR1 = &enumerator1; + +#define ANY_OWNER_NOT_SET 0 +#define ANY_OWNER_SET TEE_MEMORY_ACCESS_ANY_OWNER +#define ANY_OWNER_SET_ACCESS_READ (TEE_MEMORY_ACCESS_ANY_OWNER | \ + TEE_MEMORY_ACCESS_READ) +#define ANY_OWNER_SET_ACCESS_WRITE (TEE_MEMORY_ACCESS_ANY_OWNER | \ + TEE_MEMORY_ACCESS_WRITE) +#define ANY_OWNER_SET_ACCESS_READ_WRITE (TEE_MEMORY_ACCESS_ANY_OWNER | \ + TEE_MEMORY_ACCESS_READ | \ + TEE_MEMORY_ACCESS_WRITE) + +#define SMALL_SIZE 0xA + +#define CMD_TEE_GetInstanceData 0x00000101 +#define CMD_TEE_SetInstanceData 0x00000102 +#define CMD_TEE_GetPropertyAsU32_withoutEnum 0x00000020 + +#define NORMAL_SIZE_BUFFER 1 +#define TOO_SHORT_BUFFER 0 +#define CASE_NOT_NULL 1 +#define CASE_NULL 0 +#define CASE_BUFFER1_DIFFERS_FIRST 1 +#define CASE_BUFFER2_DIFFERS_FIRST 2 +#define CASE_EQUAL 0 +#define CASE_ERROR_ICA2 3 +#define CASE_PAYLOAD_VALUE 4 +#define CASE_SUCCESS_ICA2 2 +#define CASE_TARGET_DEAD_ICA2 1 +#define CASE_CANCEL_TIMEOUT 2 +#define CASE_ITEM_NOT_FOUND 3 +#define CASE_SUCCESS 0 +#define CASE_TARGET_BUSY 4 +#define CASE_TARGET_DEAD 1 +#define RESULT_EQUAL 0 +#define RESULT_INTEGER_GREATER_THAN_ZERO 1 +#define RESULT_INTEGER_LOWER_THAN_ZERO 2 + +#define HINT_ZERO 0 +#define SIZE_OVER_MEMORY 0xFFFFFFFE + +#define TEE_ORIGIN_NOT_TRUSTED_APP 5 +/* same as TEEC_ORIGIN_ANY_NOT_TRUSTED_APP */ +#define TEE_PROPSET_IMPLEMENTATION TEE_PROPSET_TEE_IMPLEMENTATION + +static char VALUE_PREDEFINED_STRING[] = "this is a test string"; +static char VALUE_PREDEFINED_U32[] = "48059"; +static char VALUE_PREDEFINED_UUID[] = "534D4152-542D-4353-4C54-2D54412D3031"; +static char VALUE_PREDEFINED_IDENTITY[] = + "F0000000:534D4152-542D-4353-4C54-2D54412D3031"; + +static char *VALUE_NONE; +static char VALUE_PREDEFINED_BINARY_BLOCK[] = + "VGhpcyBpcyBhIHRleHQgYmluYXJ5IGJsb2Nr"; +static char VALUE_PREDEFINED_BOOLEAN[] = "true"; + +static uint8_t CHAR1[] = { 0x10 }; + +static char GPD_CLIENT_identity[] = "gpd.client.identity\0"; +static char GPD_TA_appID[] = "gpd.ta.appID\0"; +static char GPD_TA_dataSize[] = "gpd.ta.dataSize\0"; +static char GPD_TA_instanceKeepAlive[] = "gpd.ta.instanceKeepAlive\0"; +static char GPD_TA_multiSession[] = "gpd.ta.multiSession\0"; +static char GPD_TA_singleInstance[] = "gpd.ta.singleInstance\0"; +static char GPD_TA_stackSize[] = "gpd.ta.stackSize\0"; +static char GPD_TEE_ARITH_maxBigIntSize[] = "gpd.tee.arith.maxBigIntSize\0"; +static char GPD_TEE_SYSTEM_TIME_protectionLevel[] = + "gpd.tee.systemTime.protectionLevel\0"; +static char GPD_TEE_TA_PERSISTENT_TIME_protectionLevel[] = + "gpd.tee.TAPersistentTime.protectionLevel\0"; +static char GPD_TEE_apiversion[] = "gpd.tee.apiversion\0"; +static char GPD_TEE_description[] = "gpd.tee.description\0"; +static char GPD_TEE_deviceID[] = "gpd.tee.deviceID\0"; +static char PROPERTY_NAME_NOT_VALID_ENCODING[] = "gpd.\t\n\r\0"; +static char PROPERTY_NAME_UNKNOWN[] = "unknown\0"; +static char SMC_TA_testuuid[] = "smc.ta.testuuid\0"; +static char SMC_TA_testbinaryblock[] = "smc.ta.testbinaryblock\0"; +static char SMC_TA_testbooltrue[] = "smc.ta.testbooltrue\0"; +static char SMC_TA_testidentity[] = "smc.ta.testidentity\0"; +static char SMC_TA_teststring[] = "smc.ta.teststring\0"; +static char SMC_TA_testu32[] = "smc.ta.testu32\0"; +static char STRING_SAMPLE_SIZE_4_CHAR[] = "TEE\0"; + + +/** ALL_TEEC_UUID + * + * These constants are the UUID of existing + * Trusted Applications + */ +static TEEC_UUID UUID_TTA_testingInternalAPI_TrustedCoreFramework = { + 0x534D4152, 0x542D, 0x4353, + { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x30, 0x31 } +}; +static TEEC_UUID UUID_TTA_testingInternalAPI_TrustedCoreFramework_ICA = { + 0x534D4152, 0x5443, 0x534C, + { 0x54, 0x41, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41 } +}; +static TEEC_UUID UUID_TTA_testingInternalAPI_TrustedCoreFramework_ICA2 = { + 0x534D4152, 0x5443, 0x534C, + { 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32 } +}; +static TEEC_UUID + UUID_TTA_testingInternalAPI_TrustedCoreFramework_MultipleInstanceTA = { + 0x534D4152, 0x5443, 0x534C, + { 0x4D, 0x4C, 0x54, 0x49, 0x4E, 0x53, 0x54, 0x43 } +}; +static TEEC_UUID + UUID_TTA_testingInternalAPI_TrustedCoreFramework_SingleInstanceTA = { + 0x534D4152, 0x5443, 0x534C, + { 0x53, 0x47, 0x4C, 0x49, 0x4E, 0x53, 0x54, 0x43 } +}; +static TEEC_UUID UUID_Unknown = { + 0x534D4152, 0x542D, 0x4355, + { 0x4E, 0x4B, 0x2D, 0x4E, 0x4F, 0x2D, 0x57, 0x4E } +}; + +static TEEC_UUID +UUID_TTA_testingInternalAPI_TrustedCoreFramework_PanicAtCloseSession = { + 0x534D4152, 0x5443, 0x534C, + { 0x43, 0x4C, 0x4F, 0x50, 0x41, 0x4E, 0x49, 0x43 } +}; + +static TEEC_UUID +UUID_TTA_testingInternalAPI_TrustedCoreFramework_PanicAtCreation = { + 0x534D4152, 0x5443, 0x534C, + { 0x54, 0x43, 0x52, 0x50, 0x41, 0x4E, 0x49, 0x43 } +}; + +static uint64_t value_to_u64(TEEC_Value *val) +{ + return ((uint64_t)val->b << 32) | val->a; +} + +static TEEC_Value u64_to_value(uint64_t u) +{ + return (TEEC_Value){ .a = u , .b = u >> 32 }; +} + +static void __maybe_unused *cancellation_thread(void *arg) +{ + TEEC_RequestCancellation((TEEC_Operation *)arg); + return NULL; +} + +#define RequestCancellation(op) \ + (void)ADBG_EXPECT(c, 0, \ + pthread_create(&THREAD02, NULL, cancellation_thread, \ + (void *)op)); \ + (void)ADBG_EXPECT(c, 0, pthread_join(THREAD02, NULL)); + +static TEEC_Result Invoke_MemFill(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmdId, uint32_t memoryFillSize, + uint8_t *charFill) +{ + return Invoke_Simple_Function_v2(c, sess, cmdId, memoryFillSize, 0, + *charFill, 0); +} + +static TEEC_Result Invoke_GetPropertyAsXXX_withoutEnum( + ADBG_Case_t *c, TEEC_Session *sess, uint32_t cmdId, + TEE_PropSetHandle propSet, char *name, uint32_t kindBuffer, + char *expectedValue) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + uint32_t nameLen = 0; + uint32_t expectedValueLen = 0; + + nameLen = strlen(name) + 1; + ALLOCATE_AND_FILL_SHARED_MEMORY(sess->ctx, SHARE_MEM01, BIG_SIZE, + TEEC_MEM_INPUT, nameLen, name, mem01_exit) + + if (kindBuffer == TOO_SHORT_BUFFER) { + ALLOCATE_SHARED_MEMORY(sess->ctx, SHARE_MEM02, 1, + TEEC_MEM_OUTPUT, mem02_exit) + } else { + ALLOCATE_SHARED_MEMORY(sess->ctx, SHARE_MEM02, BIG_SIZE, + TEEC_MEM_OUTPUT, mem02_exit) + } + + op.params[0].value.a = (unsigned long)propSet; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, nameLen) + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, SHARE_MEM02, + SHARE_MEM02->size) + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_VALUE_INPUT, TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + if (res) + goto exit; + + if (expectedValue != VALUE_NONE) { + expectedValueLen = strlen(expectedValue); + if (cmdId != CMD_TEE_GetPropertyAsBool_withoutEnum && + cmdId != CMD_TEE_GetPropertyAsIdentity_withoutEnum && + cmdId != CMD_TEE_GetPropertyAsUUID_withoutEnum && + cmdId != CMD_TEE_GetPropertyAsU32_withoutEnum) + expectedValueLen++; + if (!ADBG_EXPECT_BUFFER(c, expectedValue, expectedValueLen, + op.params[2].memref.parent->buffer, + op.params[2].memref.size)) + res = TEEC_ERROR_GENERIC; + } + +exit: + TEEC_ReleaseSharedMemory(SHARE_MEM02); +mem02_exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_MemCompare( + ADBG_Case_t *c, TEEC_Session *sess, uint32_t cmdId, + uint32_t memorySize, uint32_t Case, uint32_t compareResult) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + uint32_t outValue = 0; + + op.params[0].value.a = memorySize; + op.params[1].value.a = Case; + op.params[2].value.a = outValue; + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + if (res != TEEC_SUCCESS) + goto exit; + + if (compareResult == RESULT_EQUAL) { + (void)ADBG_EXPECT_COMPARE_SIGNED(c, op.params[2].value.a, ==, + 0); + } else if (compareResult == RESULT_INTEGER_GREATER_THAN_ZERO) { + (void)ADBG_EXPECT_COMPARE_SIGNED(c, + (int32_t)op.params[2].value.a, + >, 0); + } else if (compareResult == RESULT_INTEGER_LOWER_THAN_ZERO) { + (void)ADBG_EXPECT_COMPARE_SIGNED(c, + (int32_t)op.params[2].value.a, + <, 0); + } + +exit: + return res; +} + +static TEEC_Result Invoke_SetInstanceData(ADBG_Case_t *c, + TEEC_Session *sess, uint32_t cmdId, + char *data) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + size_t data_size = strlen(data) + 1; + uint32_t org; + + ALLOCATE_AND_FILL_SHARED_MEMORY(sess->ctx, SHARE_MEM01, BIG_SIZE, + TEEC_MEM_INPUT, + data_size, data, mem01_exit) + + SET_SHARED_MEMORY_OPERATION_PARAMETER(0, 0, SHARE_MEM01, data_size) + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_GetInstanceData( + ADBG_Case_t *c, TEEC_Session *sess, uint32_t cmdId, char *expectedData, + uint32_t expectedDataSize) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + ALLOCATE_SHARED_MEMORY(sess->ctx, SHARE_MEM01, BIG_SIZE, + TEEC_MEM_OUTPUT, mem01_exit) + + SET_SHARED_MEMORY_OPERATION_PARAMETER(0, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_MEMREF_PARTIAL_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + if (res != TEEC_SUCCESS) + goto exit; + + if (res != TEE_ERROR_GENERIC) { + if (!ADBG_EXPECT_BUFFER(c, expectedData, expectedDataSize, + SHARE_MEM01->buffer, + op.params[0].memref.size)) + res = TEE_ERROR_GENERIC; + } + +exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_ProcessInvokeTAOpenSession( + ADBG_Case_t *c, TEEC_Session *sess, uint32_t cmdId, + uint32_t TACmd, TEEC_UUID *UUID, uint32_t returnOrigin) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_UUID swapped_uuid = *UUID; + uint32_t org; + + swapped_uuid.timeLow = htonl(swapped_uuid.timeLow); + swapped_uuid.timeMid = htons(swapped_uuid.timeMid); + swapped_uuid.timeHiAndVersion = htons(swapped_uuid.timeHiAndVersion); + + ALLOCATE_AND_FILL_SHARED_MEMORY(sess->ctx, SHARE_MEM01, BIG_SIZE, + TEEC_MEM_INPUT, 16, &swapped_uuid, + mem01_exit) + + op.params[0].value.a = TACmd; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, 16) + op.params[2].value.a = returnOrigin; + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_VALUE_INPUT, TEEC_MEMREF_PARTIAL_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + if (TEE_ORIGIN_NOT_TRUSTED_APP == returnOrigin) { + ADBG_EXPECT_COMPARE_UNSIGNED(c, op.params[2].value.a, !=, + TEE_ORIGIN_TRUSTED_APP); + } else { + ADBG_EXPECT_COMPARE_UNSIGNED(c, op.params[2].value.a, ==, + returnOrigin); + } + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_CheckMemoryAccessRight(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmdId, + uint32_t memoryParamType, + uint32_t memoryAccessFlags) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + uint32_t memory_flag; + + switch (memoryParamType) { + case TEEC_MEMREF_TEMP_INPUT: + case TEEC_MEMREF_PARTIAL_INPUT: + memory_flag = TEEC_MEM_INPUT; + break; + case TEEC_MEMREF_TEMP_OUTPUT: + case TEEC_MEMREF_PARTIAL_OUTPUT: + memory_flag = TEEC_MEM_OUTPUT; + break; + case TEEC_MEMREF_TEMP_INOUT: + case TEEC_MEMREF_PARTIAL_INOUT: + case TEEC_MEMREF_WHOLE: + memory_flag = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + break; + default: + memory_flag = 0; + break; + } + + ALLOCATE_SHARED_MEMORY(sess->ctx, SHARE_MEM01, BIG_SIZE, + memory_flag, mem01_exit) + + op.params[0].value.a = memoryAccessFlags; + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_VALUE_INPUT, memoryParamType, TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_MemMove(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmdId, uint32_t memorySize) +{ + return Invoke_Simple_Function_v1(c, sess, cmdId, memorySize, 0); +} + +static TEEC_Result Invoke_AllocatePropertyEnumerator(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmdId, + uint64_t *enumerator) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + if (res != TEEC_SUCCESS) + goto exit; + + *enumerator = value_to_u64(&op.params[0].value); +exit: + return res; +} + +static TEEC_Result Invoke_StartPropertyEnumerator(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmdId, + uint64_t *enumerator, + TEE_PropSetHandle propSet) +{ + return Invoke_Simple_Function_v2(c, sess, cmdId, *enumerator, + *enumerator >> 32, + (unsigned long)propSet, 0); +} + +static TEEC_Result Invoke_ResetPropertyEnumerator(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmdId, + uint64_t *enumerator) +{ + return Invoke_Simple_Function_v1(c, sess, cmdId, *enumerator, + *enumerator >> 32); +} + +static TEEC_Result Invoke_GetPropertyName(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmdId, uint64_t *enumerator, + char *propertyName, + uint32_t kindBuffer) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + uint32_t strLen = 0; + + if (kindBuffer == TOO_SHORT_BUFFER) { + ALLOCATE_SHARED_MEMORY(sess->ctx, SHARE_MEM01, 1, + TEEC_MEM_OUTPUT, mem01_exit) + } else { + ALLOCATE_SHARED_MEMORY(sess->ctx, SHARE_MEM01, BIG_SIZE, + TEEC_MEM_OUTPUT, mem01_exit) + } + + op.params[0].value = u64_to_value(*enumerator); + SET_SHARED_MEMORY_OPERATION_PARAMETER(1, 0, SHARE_MEM01, + SHARE_MEM01->size) + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_VALUE_INPUT, TEEC_MEMREF_PARTIAL_OUTPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + if (res != TEEC_SUCCESS) + goto exit; + + strLen = strlen(propertyName) + 1; + + (void)ADBG_EXPECT_COMPARE_SIGNED(c, op.params[1].memref.size, ==, + strLen); + + (void)ADBG_EXPECT_COMPARE_SIGNED(c, + 0, ==, + memcmp(SHARE_MEM01->buffer, + propertyName, strLen)); + +exit: + TEEC_ReleaseSharedMemory(SHARE_MEM01); +mem01_exit: + return res; +} + +static TEEC_Result Invoke_Malloc(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmdId, uint32_t memorySize, + uint32_t hint) +{ + return Invoke_Simple_Function_v2(c, sess, cmdId, memorySize, 0, hint, + 0); +} + +static TEEC_Result Invoke_Panic(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmdId) +{ + TEEC_Result res = TEE_ERROR_NOT_SUPPORTED; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmdId, &op, &org); + + if (res != TEEC_SUCCESS) + goto exit; + + ADBG_EXPECT_COMPARE_SIGNED(c, org, ==, TEE_ORIGIN_TEE); + +exit: + return res; +} + +static TEEC_Result Invoke_Realloc(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmdId, uint32_t oldMemorySize, + uint32_t newMemorySize) +{ + return Invoke_Simple_Function_v2(c, sess, cmdId, oldMemorySize, 0, + newMemorySize, 0); +} + +static TEEC_Result Invoke_Free(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmdId, uint32_t Case) +{ + return Invoke_Simple_Function_v1(c, sess, cmdId, Case, 0); +} + +static TEEC_Result Invoke_OpenTASession(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t ta_session, + TEEC_UUID *uuid, uint32_t exp_eo) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t eo = 0; + TEEC_UUID swapped_uuid = *uuid; + TEEC_SharedMemory shm = { + .flags = TEEC_MEM_INPUT, + .buffer = &swapped_uuid, + .size = sizeof(*uuid), + }; + + swapped_uuid.timeLow = htonl(swapped_uuid.timeLow); + swapped_uuid.timeMid = htons(swapped_uuid.timeMid); + swapped_uuid.timeHiAndVersion = htons(swapped_uuid.timeHiAndVersion); + + res = TEEC_RegisterSharedMemory(sess->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_VALUE_OUTPUT, TEEC_NONE); + op.params[0].value.a = ta_session; + + op.params[1].memref.offset = 0; + op.params[1].memref.size = sizeof(*uuid); + op.params[1].memref.parent = &shm; + + res = TEEC_InvokeCommand(sess, cmd_id, &op, &eo); + TEEC_ReleaseSharedMemory(&shm); + + if (!ADBG_EXPECT(c, TEE_ORIGIN_TRUSTED_APP, eo)) + return TEEC_ERROR_GENERIC; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + ADBG_EXPECT(c, exp_eo, op.params[2].value.b); + return op.params[2].value.a; +} + +static TEEC_Result Invoke_InvokeTACommand(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t ta_session, + uint32_t ta_cmd_id, uint32_t exp_eo) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t eo = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + op.params[0].value.a = ta_session; + op.params[0].value.b = ta_cmd_id; + + res = TEEC_InvokeCommand(sess, cmd_id, &op, &eo); + + if (!ADBG_EXPECT(c, TEE_ORIGIN_TRUSTED_APP, eo)) + return TEEC_ERROR_GENERIC; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + ADBG_EXPECT(c, exp_eo, op.params[1].value.b); + return op.params[1].value.a; +} + +static TEEC_Result Invoke_CloseTASession(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t ta_session) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t eo = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + op.params[0].value.a = ta_session; + + res = TEEC_InvokeCommand(sess, cmd_id, &op, &eo); + + ADBG_EXPECT(c, TEE_ORIGIN_TRUSTED_APP, eo); + return res; +} +#endif /* XML_INTERNAL_API_H_ */ diff --git a/optee/optee_test/host/xtest/gp/include/xml_timearithm_api.h b/optee/optee_test/host/xtest/gp/include/xml_timearithm_api.h new file mode 100644 index 0000000..52c2d31 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/include/xml_timearithm_api.h @@ -0,0 +1,1003 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2020, Linaro Limited + */ + +#ifndef XML_TIMEARITHM_API_H_ +#define XML_TIMEARITHM_API_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xml_common_api.h" +#include "xtest_helpers.h" +#include "xtest_test.h" + +#define Invoke_GetSystemTime Invoke_Simple_Function +#define Invoke_GetREETime Invoke_Simple_Function +#define Invoke_SetTAPersistentTime_and_GetTAPersistentTime_Overflow \ + Invoke_Simple_Function +#define Invoke_SetTAPersistentTime_and_GetTAPersistentTime \ + Invoke_Simple_Function +#define Invoke_BigIntConvertToOctetStringOverflow Invoke_Simple_Function +#define Invoke_BigIntConvertFromOctetStringOverflow Invoke_Simple_Function +#define Invoke_GetTAPersistentTime_NotSet_and_SetTAPersistentTime \ + Invoke_Simple_Function +#define Test_Tool_Erase_Persistent_Time Invoke_Simple_Function + +#define CMD_TEE_BigIntAdd 0x00000010 +#define CMD_TEE_BigIntAddMod 0x00000011 +#define CMD_TEE_BigIntCmp 0x00000012 +#define CMD_TEE_BigIntCmpS32 0x00000013 +#define CMD_TEE_BigIntComputeExtendedGcd 0x00000014 +#define CMD_TEE_BigIntDiv 0x00000018 +#define CMD_TEE_BigIntGetBit 0x00000020 +#define CMD_TEE_BigIntGetBitCount 0x00000021 +#define CMD_TEE_BigIntInvMod 0x00000023 +#define CMD_TEE_BigIntIsProbablePrime 0x00000024 +#define CMD_TEE_BigIntMod 0x00000025 +#define CMD_TEE_BigIntMul 0x00000026 +#define CMD_TEE_BigIntMulMod 0x00000027 +#define CMD_TEE_BigIntNeg 0x00000028 +#define CMD_TEE_BigIntRelativePrime 0x00000029 +#define CMD_TEE_BigIntShiftRight 0x00000030 +#define CMD_TEE_BigIntSquare 0x00000031 +#define CMD_TEE_BigIntSquareMod 0x00000032 +#define CMD_TEE_BigIntSub 0x00000033 +#define CMD_TEE_BigIntSubMod 0x00000034 +#define CMD_Arithm_TTA_Store_Value_S32 0x00000038 +#define CMD_Arithm_TTA_New_BigInt 0x00000039 +#define CMD_Arithm_BigIntConvertToOctetString 0x00000040 +#define CMD_Arithm_BigIntComputeFMM 0x00000041 +#define CMD_Arithm_BigIntConvertFromFMM 0x00000042 +#define CMD_Arithm_BigIntConvertToFMM 0x00000043 +#define CMD_Arithm_BigIntInitFMMContext 0x00000044 +#define CMD_Arithm_TTA_New_BigIntFMM 0x00000045 +#define CMD_Arithm_BigIntConvertFromOctetString 0x00000046 +#define CMD_Arithm_BigIntConvertToS32 0x00000047 +#define CMD_Arithm_BigIntConvertFromS32 0x00000048 + +#define CMD_TEE_GetSystemTime 0x00000010 +#define CMD_TEE_Wait 0x00000011 +#define CMD_TEE_SetTAPersistentTime_and_GetTAPersistentTime 0x00000012 +#define CMD_TEE_GetREETime 0x00000013 +#define CMD_TEE_SetTAPersistentTime_and_GetTAPersistentTimeOverflow 0x00000014 +#define CMD_TEE_GetTAPersistentTimeNotSetAndSetTAPersistentTime 0x00000015 + + +static TEEC_Session session01; +static TEEC_Session *SESSION01 = &session01; +static TEEC_Context context01; +static TEEC_Context *CONTEXT01 = &context01; +static TEEC_Context context02; +static TEEC_Context *CONTEXT02 = &context02; +static TEEC_Operation operation01; +static TEEC_Operation *OPERATION01 = &operation01; + +#define CMD_TEE_SetTAPersistentTime_and_GetTAPersistentTime_Overflow \ + CMD_TEE_SetTAPersistentTime_and_GetTAPersistentTimeOverflow + +#define CLIENT_APP01 NULL + +#define TEEC_UNDEFINED_ERROR 0xDEADDEAD + +#define TEEC_ORIGIN_ANY_NOT_TRUSTED_APP 0x00000005 +/* same as TEE_ORIGIN_NOT_TRUSTED_APP */ + +static uint32_t saved_octet_string_sign; +static void *saved_octet_string; +static size_t saved_octet_string_size; + +/*Test data defines*/ +static pthread_t THREAD02; + +#define BIT0_MASK 1 +#define BIT1_MASK 2 +#define BIT2_MASK 4 + +#define NEGATIVE 0 +#define POSITIVE 1 + +#define RESULT_NOT_A_PRIME_SURE 0 +#define RESULT_PRIME_SURE_OR_MAYBE 1 + +#define RESULT_NOT_A_PRIME 0 +#define RESULT_PRIME 1 + +#define RESULT_EQUAL 0 +#define RESULT_INTEGER_GREATER_THAN_ZERO 1 +#define RESULT_INTEGER_LOWER_THAN_ZERO 2 + +#define CASE_WAIT_CANCELLED 1 +#define CASE_WAIT_SUCCESS 2 + + +#define STORED_VALUE_BIG_INT_1 0 +#define STORED_VALUE_BIG_INT_2 1 +#define STORED_VALUE_BIG_INT_3 8 +#define STORED_VALUE_BIG_INT_4 9 +#define STORED_VALUE_FMM_BIG_INT_1 310 +#define STORED_VALUE_FMM_BIG_INT_2 311 +#define STORED_VALUE_FMM_CONTEXT_1 300 +#define STORED_VALUE_FMM_RESULT 312 +#define STORED_VALUE_MODULUS 2 +#define STORED_VALUE_RESULT 3 +#define STORED_VALUE_RESULT_4 6 +#define STORED_VALUE_RESULT_5 7 +#define STORED_VALUE_RESULT_FMM_CONVERTED 10 +#define STORED_VALUE_RESULT_U 4 +#define STORED_VALUE_RESULT_V 5 +#define STORED_VALUE_SHORT_VAL_1 100 +#define STORED_VALUE_NULL 200 + +static uint32_t CONFIDENCE_LEVEL_80 = 80; + +static uint8_t BIG_VALUE1_SIZE_64_BITS[] = { + 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +static uint8_t BIG_VALUE11_SIZE_2048_BITS_PRIME_WITH_VALUE5[] = { + 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +static uint8_t BIG_VALUE20_SIZE_2048_BITS_PRIME_WITH_VALUE18[] = { + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, 0x04, +}; + +static uint8_t BIG_VALUE2_SIZE_64_BITS[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static uint8_t BIG_VALUE3_SIZE_32_BITS[] = { + 0x0F, 0xFF, 0xFF, 0xFF, +}; + +static uint8_t BIG_VALUE4_SIZE_32_BITS[] = { + 0x01, 0x00, 0x00, 0x00, +}; + +static uint8_t BIG_VALUE5_SIZE_2048_BITS[] = { + 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; + +static uint8_t BIG_VALUE6_SIZE_2048_BITS[] = { + 0x01, 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, 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, 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, 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, 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, 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, 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, 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, +}; + +static uint8_t BIG_VALUE7_SIZE_1024_BITS[] = { + 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, +}; + +static uint8_t BIG_VALUE10_SIZE_32_BITS_PRIME_WITH_VALUE3[] = { + 0x0E, 0xFF, 0xFF, 0xFF, +}; + +static uint8_t BIG_VALUE13_SIZE_32_BITS_PRIME[] = { + 0x00, 0x00, 0x0D, 0x69, +}; + +static uint8_t BIG_VALUE14_SIZE_32_BITS_NOT_PRIME[] = { + 0x00, 0x00, 0x0D, 0x68, +}; + +static uint8_t BIG_VALUE15_SIZE_32_BITS[] = { + 0x00, 0x00, 0x00, 0x03, +}; + +static uint8_t BIG_VALUE16_SIZE_64_BITS[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, +}; + +static uint8_t BIG_VALUE17_SIZE_1024_BITS[] = { + 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, + 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, + 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, + 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, 0x03, +}; + +static uint8_t BIG_VALUE18_SIZE_2048_BITS[] = { + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, 0x03, +}; + +static uint8_t BIG_VALUE19_SIZE_32_BITS_PRIME_WITH_VALUE15[] = { + 0x00, 0x00, 0x00, 0x04, +}; + +static uint8_t BIG_VALUE9_SIZE_64_BITS_PRIME_WITH_VALUE1[] = { + 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +static uint8_t BIG_VALUE_ONE_SIZE_64_BITS[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +}; + +static uint8_t BIG_VALUE_TWO_SIZE_1024_BITS[] = { + 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, + 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, + 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, + 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, 0x02, +}; + +static uint8_t BIG_VALUE_ZERO_SIZE_32_BITS[] = { + 0x00, 0x00, 0x00, 0x00, +}; + +static uint8_t BIG_VALUE_ZERO_SIZE_64_BITS[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static uint8_t BIG_VALUE_ZERO_SIZE_2048_BITS[] = { + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, +}; + +static uint8_t BIG_VALUE_TWO_SIZE_2048_BITS[] = { + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, 0x02, +}; + +static uint8_t BIG_VALUE25_SIZE_2048_BITS[] = { + 0x01, 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, 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, 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, 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, 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, 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, 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, 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, 0x01, +}; + +static uint8_t BIG_VALUE_TWO_SIZE_32_BITS[] = { + 0x00, 0x00, 0x00, 0x02, +}; + +static uint8_t BIG_VALUE23_SIZE_32_BITS[] = { + 0x01, 0x00, 0x00, 0x01, +}; + +static uint8_t BIG_VALUE22_SIZE_32_BITS_LIMIT_INT32[] = { + 0x80, 0x00, 0x00, 0x00, +}; + +static uint8_t BIG_VALUE_TWO_SIZE_64_BITS[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, +}; + +static uint8_t BIG_VALUE24_SIZE_64_BITS[] = { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +}; + +static uint8_t BIG_VALUE21_SIZE_64_BITS[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, +}; + +/** ALL_TEEC_UUID + * + * These constants are the UUID of existing + * Trusted Applications + */ +/* "SMARTCLSARITHMET" */ +static TEEC_UUID UUID_TTA_testingInternalAPI_Arithmetique = { + 0x534D4152, 0x5443, 0x4C53, + { 0x41, 0x52, 0x49, 0x54, 0x48, 0x4D, 0x45, 0x54 } +}; +/* "SMARTCSL_TIMEAPI" */ +static TEEC_UUID UUID_TTA_testingInternalAPI_Time = { + 0x534D4152, 0x5443, 0x534C, + { 0x5F, 0x54, 0x49, 0x4D, 0x45, 0x41, 0x50, 0x49 } +}; + +/*Helper functions/macros*/ + +#define BN_DECLARE_AND_INIT(exit_label) \ + BN_CTX *ctx = NULL; \ + BIGNUM *a = NULL, *b = NULL, *s = NULL, *d = NULL, \ + *m = NULL, *l = NULL, \ + *r = NULL; \ + ctx = BN_CTX_new(); \ + if (ctx == NULL) { \ + goto exit_label; \ + } \ + a = BN_new(); \ + b = BN_new(); \ + s = BN_new(); \ + d = BN_new(); \ + m = BN_new(); \ + l = BN_new(); \ + r = BN_new(); + +#define BN_FREE() \ + BN_free(a); \ + BN_free(b); \ + BN_free(s); \ + BN_free(d); \ + BN_free(m); \ + BN_free(l); \ + BN_free(r); \ + if (ctx) { \ + BN_CTX_free(ctx); \ + } + +static void *cancellation_thread(void *arg) +{ + TEEC_RequestCancellation((TEEC_Operation *)arg); + return NULL; +} + +#define RequestCancellation(op) \ + (void)ADBG_EXPECT(c, 0, \ + pthread_create(&THREAD02, NULL, cancellation_thread, \ + (void *)op)); \ + (void)ADBG_EXPECT(c, 0, pthread_join(THREAD02, NULL)); + +static TEEC_Result Invoke_BigIntCmpS32(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t op, + uint32_t short_value, + uint32_t exp_cmp_res) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, exp_cmp_res, 0, + op, short_value); +} + +static TEEC_Result Invoke_BigIntCmp(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t op1, + uint32_t op2, uint32_t exp_cmp_res) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, exp_cmp_res, 0, + op1, op2); +} + +static TEEC_Result Invoke_BigIntComputeExtendedGcd(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd_id, + uint32_t gcd, uint32_t dst_u, + uint32_t dst_v, uint32_t op1, + uint32_t op2) +{ + return Invoke_Simple_Function_v3(c, sess, cmd_id, gcd, 0, dst_u, dst_v, + op1, op2); +} + +static TEEC_Result Invoke_BigIntAddMod(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t dest, + uint32_t op1, uint32_t op2, uint32_t mod) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, dest, mod, op1, op2); +} + +static TEEC_Result Invoke_BigIntAdd(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t dest, + uint32_t op1, uint32_t op2) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, dest, 0, op1, op2); +} + +static TEEC_Result Invoke_BigIntMul(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t dest, + uint32_t op1, uint32_t op2) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, dest, 0, op1, op2); +} + +static TEEC_Result Invoke_BigIntMulMod(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t dst, + uint32_t op1, uint32_t op2, uint32_t mod) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, dst, mod, op1, op2); +} + +static TEEC_Result Invoke_StoreS32(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t dest, + uint32_t sign, const uint8_t *value, + size_t value_size) +{ + uint32_t v = 0; + size_t n = 0; + + if (value_size > 4) + return TEEC_ERROR_BAD_PARAMETERS; + + for (n = 0; n < value_size; n++) { + v <<= 8; + v |= value[n]; + } + return Invoke_Simple_Function_v2(c, sess, cmd_id, dest, sign, v, 0); +} + + +static TEEC_Result Invoke_BigIntConvertFromS32(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd_id, uint32_t dst, + uint32_t short_val) +{ + return Invoke_Simple_Function_v1(c, sess, cmd_id, dst, short_val); +} + +static TEEC_Result Invoke_BigIntConvertToS32(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd_id, uint32_t dst, + uint32_t src) +{ + return Invoke_Simple_Function_v1(c, sess, cmd_id, src, dst); +} + +static TEEC_Result Invoke_BigIntGetBit(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t src, + uint32_t bit_idx, uint32_t exp_result) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + op.params[0].value.a = src; + op.params[0].value.b = bit_idx; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + if (!res && !ADBG_EXPECT_COMPARE_UNSIGNED(c, exp_result, ==, + op.params[1].value.a)) + res = TEEC_ERROR_GENERIC; + + return res; +} + +static TEEC_Result Invoke_BigIntGetBitCount(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t src, + uint32_t exp_bit_count) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + + op.params[0].value.a = src; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd, &op, &org); + + if (!res && !ADBG_EXPECT_COMPARE_UNSIGNED(c, exp_bit_count, ==, + op.params[1].value.a)) + res = TEEC_ERROR_GENERIC; + + return res; +} + +static TEEC_Result Invoke_Wait(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmdId, uint32_t Case) +{ + return Invoke_Simple_Function_v1(c, sess, cmdId, Case, 0); +} + +static TEEC_Result Invoke_BigIntInitFMMContext(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd_id, uint32_t ctx, + uint32_t mod_size, uint32_t mod) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, ctx, mod, mod_size, + 0); +} + +static TEEC_Result Invoke_NewBigIntFMM(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t role, + uint32_t mod_size) +{ + return Invoke_Simple_Function_v1(c, sess, cmd_id, role, mod_size); +} + +static TEEC_Result Invoke_BigIntConvertToFMM(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t dst, + uint32_t src, uint32_t mod, + uint32_t ctx) +{ + return Invoke_Simple_Function_v3(c, sess, cmd_id, ctx, mod, dst, 0, + src, 0); +} + +static TEEC_Result Invoke_BigIntConvertFromFMM(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd_id, uint32_t dst, + uint32_t src, uint32_t mod, + uint32_t ctx) +{ + return Invoke_Simple_Function_v3(c, sess, cmd_id, ctx, mod, dst, 0, + src, 0); +} + +static TEEC_Result Invoke_BigIntComputeFMM(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t dst, + uint32_t op1, uint32_t op2, + uint32_t mod, uint32_t ctx) +{ + return Invoke_Simple_Function_v3(c, sess, cmd_id, ctx, mod, dst, 0, + op1, op2); +} + +static TEEC_Result Invoke_BigIntDiv(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t q, uint32_t r, + uint32_t op1, uint32_t op2) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, q, r, op1, op2); +} + +static TEEC_Result Invoke_BigIntMod(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t dst, uint32_t op, + uint32_t mod) +{ + return Invoke_Simple_Function_v2(c, sess, cmd_id, dst, mod, op, 0); +} + +static TEEC_Result Invoke_BigIntInvMod(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t dst, uint32_t op, + uint32_t mod) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, dst, mod, op, 0); +} + +static TEEC_Result Invoke_BigIntIsProbablePrime(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd, uint32_t op, + uint32_t conf_lvl, + uint32_t exp_result) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, exp_result, 0, op, + conf_lvl); +} + +static TEEC_Result Invoke_BigIntNeg(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t dst, uint32_t op) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, dst, 0, op, 0); +} + +static TEEC_Result Invoke_BigIntRelativePrime(ADBG_Case_t *c, + TEEC_Session *sess, uint32_t cmd, + uint32_t op1, uint32_t op2, + bool exp_result) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, exp_result, 0, op1, op2); +} + +static TEEC_Result Invoke_BigIntShiftRight(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t dst, + uint32_t op, uint32_t bits) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, dst, op, bits, 0); +} + +static TEEC_Result Invoke_BigIntSquareMod(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t dst, + uint32_t op, uint32_t mod) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, dst, mod, op, 0); +} + +static TEEC_Result Invoke_BigIntSquare(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t dst, uint32_t op) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, dst, 0, op, 0); +} + +static TEEC_Result Invoke_BigIntSubMod(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t dst, uint32_t op1, + uint32_t op2, uint32_t mod) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, dst, mod, op1, op2); +} + +static TEEC_Result Invoke_BigIntSub(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd, uint32_t dst, uint32_t op1, + uint32_t op2) +{ + return Invoke_Simple_Function_v2(c, sess, cmd, dst, 0, op1, op2); +} + +static TEEC_Result Invoke_NewBigInt(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t cmd_id, uint32_t role, + uint32_t size) +{ + return Invoke_Simple_Function_v1(c, sess, cmd_id, role, size); +} + +static TEEC_Result Macro_StoreBigInt(ADBG_Case_t *c, TEEC_Session *sess, + uint32_t role, uint32_t size, + uint32_t sign, const uint8_t *value, + size_t value_size) +{ + TEEC_Result res = TEE_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + TEEC_SharedMemory shm_value = { + .size = value_size, + .flags = TEEC_MEM_INPUT, + }; + + res = Invoke_NewBigInt(c, sess, CMD_Arithm_TTA_New_BigInt, role, size); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + res = TEEC_AllocateSharedMemory(sess->ctx, &shm_value); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + memcpy(shm_value.buffer, value, value_size); + + op.params[0].value.a = role; + op.params[0].value.b = size; + op.params[1].value.a = sign; + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, &shm_value, + shm_value.size); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE); + res = TEEC_InvokeCommand(sess, CMD_Arithm_BigIntConvertFromOctetString, + &op, &org); + TEEC_ReleaseSharedMemory(&shm_value); + return res; +} + +static TEEC_Result Invoke_BigIntConvertToOctetString(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd_id, + uint32_t bigint, + size_t size) +{ + TEEC_Result res = TEE_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + TEEC_SharedMemory shm = { + .size = (size + 7) / 8, + .flags = TEEC_MEM_OUTPUT, + }; + + res = TEEC_AllocateSharedMemory(sess->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + op.params[0].value.a = bigint; + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, &shm, shm.size); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd_id, &op, &org); + + if (!res) { + size_t sz = op.params[2].memref.size; + + saved_octet_string = malloc(sz); + memcpy(saved_octet_string, shm.buffer, sz); + saved_octet_string_size = sz; + saved_octet_string_sign = op.params[1].value.a; + + } + TEEC_ReleaseSharedMemory(&shm); + return res; +} + +static TEEC_Result Invoke_BigIntConvertFromOctetString(ADBG_Case_t *c, + TEEC_Session *sess, + uint32_t cmd_id, + uint32_t dst, + size_t size, + uint32_t sign, + const uint8_t *value, + size_t value_size) +{ + TEEC_Result res = TEE_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org; + TEEC_SharedMemory shm = { + .size = (size + 7) / 8, + .flags = TEEC_MEM_INPUT, + }; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, value_size, <=, shm.size)) + return TEEC_ERROR_BAD_PARAMETERS; + + res = TEEC_AllocateSharedMemory(sess->ctx, &shm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + memcpy(shm.buffer, value, value_size); + + op.params[0].value.a = dst; + op.params[1].value.a = sign; + SET_SHARED_MEMORY_OPERATION_PARAMETER(2, 0, &shm, shm.size); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, cmd_id, &op, &org); + + TEEC_ReleaseSharedMemory(&shm); + return res; +} +#endif /* XML_TIMEARITHM_API_H_ */ diff --git a/optee/optee_test/host/xtest/gp/patches/0002-TTAs-add-files-needed-to-compile.patch b/optee/optee_test/host/xtest/gp/patches/0002-TTAs-add-files-needed-to-compile.patch new file mode 100644 index 0000000..9598cab --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0002-TTAs-add-files-needed-to-compile.patch @@ -0,0 +1,1637 @@ +From a6b66e8fce014d26ea3c36d25cf200b58b0b470b Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Mon, 22 Jun 2020 18:00:29 +0200 +Subject: [PATCH 02/11] TTAs: add files needed to compile + +Signed-off-by: Jens Wiklander +--- + TTAs_Internal_API_1_1_1/GP_defs.h | 4 ++ + .../TTA_Arithmetical/code_files/Makefile | 2 + + .../TTA_Arithmetical/code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 41 +++++++++++++ + .../code_files/Makefile | 2 + + .../code_files/sub.mk | 3 + + .../code_files/ta_answerErrorTo_Invoke_test.h | 36 +++++++++++ + .../code_files/user_ta_header_defines.h | 45 ++++++++++++++ + .../code_files/Makefile | 2 + + .../code_files/sub.mk | 3 + + .../ta_answerErrorTo_OpenSession_test.h | 33 ++++++++++ + .../code_files/user_ta_header_defines.h | 44 +++++++++++++ + .../code_files/Makefile | 2 + + .../code_files/sub.mk | 3 + + ..._answerSuccessTo_OpenSession_Invoke_test.h | 36 +++++++++++ + .../code_files/user_ta_header_defines.h | 44 +++++++++++++ + .../code_files/Makefile | 2 + + .../code_files/sub.mk | 3 + + ...check_OpenSession_with_4_parameters_test.h | 33 ++++++++++ + .../code_files/user_ta_header_defines.h | 44 +++++++++++++ + .../TTA_testingClientAPI/code_files/Makefile | 2 + + .../TTA_testingClientAPI/code_files/sub.mk | 3 + + .../code_files/ta_testingClientAPI_test.h | 37 +++++++++++ + .../code_files/user_ta_header_defines.h | 44 +++++++++++++ + .../code_files/Makefile | 2 + + .../TTA_testingClientAPI_Parameters.c | 1 + + .../code_files/sub.mk | 4 ++ + .../code_files/user_ta_header_defines.h | 41 +++++++++++++ + .../code_files/Makefile | 2 + + .../TTA_testingClientAPI_Parameters.c | 1 + + .../code_files/sub.mk | 4 ++ + .../code_files/user_ta_header_defines.h | 42 +++++++++++++ + .../TTA_Crypto/TTA_Crypto/code_files/Makefile | 2 + + .../TTA_Crypto/code_files/TTA_DS_commands.c | 1 + + .../TTA_Crypto/TTA_Crypto/code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 41 +++++++++++++ + .../TTA_DS/TTA_DS/code_files/Makefile | 2 + + .../TTA_DS/TTA_DS/code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 41 +++++++++++++ + .../TTA_TCF/TTA_TCF/code_files/Makefile | 2 + + .../TTA_TCF/TTA_TCF/code_files/sub.mk | 6 ++ + .../TTA_TCF/TTA_TCF/code_files/ta_TCF_test.h | 33 ++++++++++ + .../code_files/user_ta_header_defines.h | 61 +++++++++++++++++++ + .../TTA_TCF/TTA_TCF_ICA/code_files/Makefile | 2 + + .../TTA_TCF/TTA_TCF_ICA/code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 43 +++++++++++++ + .../TTA_TCF/TTA_TCF_ICA2/code_files/Makefile | 2 + + .../TTA_TCF/TTA_TCF_ICA2/code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 44 +++++++++++++ + .../code_files/Makefile | 2 + + .../code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 45 ++++++++++++++ + .../code_files/Makefile | 2 + + .../code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 42 +++++++++++++ + .../code_files/Makefile | 2 + + .../TTA_TCF_PanicAtCreation/code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 41 +++++++++++++ + .../code_files/Makefile | 2 + + .../code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 44 +++++++++++++ + .../TTA_Time/TTA_Time/code_files/Makefile | 2 + + .../TTA_Time/TTA_Time/code_files/sub.mk | 3 + + .../code_files/user_ta_header_defines.h | 42 +++++++++++++ + TTAs_Internal_API_1_1_1/ta_common.mk | 3 + + 65 files changed, 1102 insertions(+) + create mode 100644 TTAs_Internal_API_1_1_1/GP_defs.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/ta_answerErrorTo_Invoke_test.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/ta_answerErrorTo_OpenSession_test.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/ta_answerSuccessTo_OpenSession_Invoke_test.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/ta_check_OpenSession_with_4_parameters_test.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/ta_testingClientAPI_test.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/Makefile + create mode 120000 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/TTA_testingClientAPI_Parameters.c + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/Makefile + create mode 120000 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/TTA_testingClientAPI_Parameters.c + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/Makefile + create mode 120000 TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_DS_commands.c + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/ta_TCF_test.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/Makefile + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/sub.mk + create mode 100644 TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/user_ta_header_defines.h + create mode 100644 TTAs_Internal_API_1_1_1/ta_common.mk + +diff --git a/TTAs_Internal_API_1_1_1/GP_defs.h b/TTAs_Internal_API_1_1_1/GP_defs.h +new file mode 100644 +index 000000000000..3d6ef1d53c78 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/GP_defs.h +@@ -0,0 +1,4 @@ ++#define SLogTrace(...) ++#define SLogError(...) ++#define SLogWarning(...) ++#define S_VAR_NOT_USED(x) do { (void)(x); } while (0) +diff --git a/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/Makefile +new file mode 100644 +index 000000000000..20d98a04cd81 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-4c53-4152-4954484d4554 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/sub.mk +new file mode 100644 +index 000000000000..46f37849c7b8 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_Arithmetical.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..fa248c666f4f +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#define TA_UUID { 0x534D4152, 0x5443, 0x4C53, { 0x41, 0x52, 0x49, 0x54, 0x48, 0x4D, 0x45, 0x54 } } ++ ++#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE ) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_Arithmetical v2.1" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/Makefile +new file mode 100644 +index 000000000000..ba45ad4dfaac +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-542d-4353-4c54-2d54412d4552 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/sub.mk +new file mode 100644 +index 000000000000..fa4fa3f01460 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_answerErrorTo_Invoke.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/ta_answerErrorTo_Invoke_test.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/ta_answerErrorTo_Invoke_test.h +new file mode 100644 +index 000000000000..65a6b262cfbd +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/ta_answerErrorTo_Invoke_test.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. ++ */ ++ ++#define TA_TTA_ANSWERERRORTOINVOKE_UUID { \ ++ 0x534D4152, \ ++ 0x542D, \ ++ 0x4353, \ ++ { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x45, 0x52 } \ ++ } ++#define COMMAND_TTA_Remember_Expected_ParamTypes 0x00000002 ++#define COMMAND_TTA_Copy_ParamIn_to_ParamOut 0x00000001 ++#define COMMAND_TTA_Check_ParamTypes 0x00000003 +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..664f85aeeabf +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_Invoke/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_answerErrorTo_Invoke_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE \ ++ | TA_FLAG_EXEC_DDR \ ++ | TA_FLAG_SINGLE_INSTANCE \ ++ ) ++#define TA_STACK_SIZE (1*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_answerErrorTo_Invoke v0.4" }, ++ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/Makefile +new file mode 100644 +index 000000000000..b85d23b0be11 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5445-5252544f4f53 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/sub.mk +new file mode 100644 +index 000000000000..810273e471cf +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_answerErrorTo_OpenSession.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/ta_answerErrorTo_OpenSession_test.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/ta_answerErrorTo_OpenSession_test.h +new file mode 100644 +index 000000000000..b4715ff1cc10 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/ta_answerErrorTo_OpenSession_test.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. ++ */ ++ ++#define TA_TTA_ANSWERERRORTOOPENSESSION_UUID { \ ++ 0x534D4152, \ ++ 0x5443, \ ++ 0x534C, \ ++ { 0x54, 0x45, 0x52, 0x52, 0x54, 0x4F, 0x4F, 0x53 } \ ++ } +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..19b2e533fbf5 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerErrorTo_OpenSession/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_answerErrorTo_OpenSession_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE \ ++ | TA_FLAG_EXEC_DDR \ ++ | TA_FLAG_SINGLE_INSTANCE \ ++ ) ++#define TA_STACK_SIZE (1*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_answerErrorTo_OpenSession v0.2" }, ++ ++#endif /* USER_TA_HEADER_DEFINES_H*/ +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/Makefile +new file mode 100644 +index 000000000000..5d8b04bad8a6 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-542d-4353-4c54-2d54412d5355 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/sub.mk +new file mode 100644 +index 000000000000..1d1f67ec7642 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_answerSuccessTo_OpenSession_Invoke.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/ta_answerSuccessTo_OpenSession_Invoke_test.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/ta_answerSuccessTo_OpenSession_Invoke_test.h +new file mode 100644 +index 000000000000..ac7bfaf09e57 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/ta_answerSuccessTo_OpenSession_Invoke_test.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. ++ */ ++ ++#define TA_TTA_ANSWERSUCCESSTOOPENSESSION_UUID { \ ++ 0x534D4152, \ ++ 0x542D, \ ++ 0x4353, \ ++ { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x53, 0x55 } \ ++ } ++#define COMMAND_TTA_Remember_Expected_ParamTypes 0x00000002 ++#define COMMAND_TTA_Copy_ParamIn_to_ParamOut 0x00000001 ++#define COMMAND_TTA_Check_ParamTypes 0x00000003 +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..084fc30d393a +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_answerSuccessTo_OpenSession_Invoke/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_answerSuccessTo_OpenSession_Invoke_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE \ ++ | TA_FLAG_EXEC_DDR \ ++ | TA_FLAG_SINGLE_INSTANCE \ ++ ) ++#define TA_STACK_SIZE (1*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_answerSuccessTo_OpenSession_Invoke v0.3" }, ++ ++#endif /* USER_TA_HEADER_DEFINES_H*/ +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/Makefile +new file mode 100644 +index 000000000000..68b1dc533957 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-544f-53345041524d ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/sub.mk +new file mode 100644 +index 000000000000..3e31f1cc13a4 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_check_OpenSession_with_4_parameters.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/ta_check_OpenSession_with_4_parameters_test.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/ta_check_OpenSession_with_4_parameters_test.h +new file mode 100644 +index 000000000000..cf0c1775d38c +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/ta_check_OpenSession_with_4_parameters_test.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. ++ */ ++ ++#define TA_TTA_CHECKOPENSESSIONWITH4PARAMETERS_UUID { \ ++ 0x534D4152, \ ++ 0x5443, \ ++ 0x534C, \ ++ { 0x54, 0x4F, 0x53, 0x34, 0x50, 0x41, 0x52, 0x4D } \ ++ } +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..fbc7c28f60b2 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_check_OpenSession_with_4_parameters/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_check_OpenSession_with_4_parameters_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE \ ++ | TA_FLAG_EXEC_DDR \ ++ | TA_FLAG_SINGLE_INSTANCE \ ++ ) ++#define TA_STACK_SIZE (1*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_check_OpenSession_with_4_parameters v0.2" }, ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/Makefile +new file mode 100644 +index 000000000000..a937f649bcf8 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-542d-4353-4c54-2d54412d5354 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/sub.mk +new file mode 100644 +index 000000000000..e8c0db453040 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_testingClientAPI.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/ta_testingClientAPI_test.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/ta_testingClientAPI_test.h +new file mode 100644 +index 000000000000..2efaa35f39dd +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/ta_testingClientAPI_test.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. ++ */ ++ ++#define TA_TTA_TESTING_CLIENT_API_UUID { \ ++ 0x534D4152, \ ++ 0x542D, \ ++ 0x4353, \ ++ { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x53, 0x54 } \ ++ } ++#define COMMAND_TTA_Remember_Expected_ParamTypes 0x00000002 ++#define COMMAND_TTA_Copy_ParamIn_to_ParamOut 0x00000001 ++#define COMMAND_TTA_Check_ParamTypes 0x00000003 ++#define COMMAND_TTA_To_Be_Cancelled 0x00000004 +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..b42879b34851 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_testingClientAPI_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE \ ++ | TA_FLAG_EXEC_DDR \ ++ | TA_FLAG_SINGLE_INSTANCE \ ++ ) ++#define TA_STACK_SIZE (1*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_testingClientAPI v0.5" }, ++ ++#endif /* USER_TA_HEADER_DEFINES_H*/ +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/Makefile +new file mode 100644 +index 000000000000..7966e463ccf8 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5443-4c4950415241 ++include ../../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/TTA_testingClientAPI_Parameters.c b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/TTA_testingClientAPI_Parameters.c +new file mode 120000 +index 000000000000..7e20440c40e7 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/TTA_testingClientAPI_Parameters.c +@@ -0,0 +1 @@ ++../../common_code_files/TTA_testingClientAPI_Parameters.c +\ No newline at end of file +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/sub.mk +new file mode 100644 +index 000000000000..a53b62c0e3b0 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/sub.mk +@@ -0,0 +1,4 @@ ++global-incdirs-y += ../../../../TEE_include ++srcs-y += TTA_testingClientAPI_Parameters_Invoke.c ++srcs-y += TTA_testingClientAPI_Parameters.c ++cflags-y := -include ../../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..93d585aca7e3 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_Invoke/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#define TA_UUID { 0x534D4152, 0x5443, 0x534C, { 0x54, 0x43, 0x4C, 0x49, 0x50, 0x41, 0x52, 0x41 } } ++ ++#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE ) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_testingClientAPI_Parameters_Invoke v2.1" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/Makefile +new file mode 100644 +index 000000000000..41ccec16b1b6 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5443-4c49504f5053 ++include ../../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/TTA_testingClientAPI_Parameters.c b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/TTA_testingClientAPI_Parameters.c +new file mode 120000 +index 000000000000..7e20440c40e7 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/TTA_testingClientAPI_Parameters.c +@@ -0,0 +1 @@ ++../../common_code_files/TTA_testingClientAPI_Parameters.c +\ No newline at end of file +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/sub.mk +new file mode 100644 +index 000000000000..61a8961185cd +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/sub.mk +@@ -0,0 +1,4 @@ ++global-incdirs-y += ../../../../TEE_include ++srcs-y += TTA_testingClientAPI_Parameters_OpenSession.c ++srcs-y += TTA_testingClientAPI_Parameters.c ++cflags-y := -include ../../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..5212636ce6b2 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_ClientAPI/TTA_testingClientAPI_Parameters/TTA_testingClientAPI_Parameters_OpenSession/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#define TA_UUID { 0x534D4152, 0x5443, 0x534C, { 0x54, 0x43, 0x4C, 0x49, 0x50, 0x4F, 0x50, 0x53 } } ++ ++#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ ++ TA_FLAG_MULTI_SESSION) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_testingClientAPI_Parameters_OpenSession v2.1" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/Makefile +new file mode 100644 +index 000000000000..4be816754ee9 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5443-525950544f31 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_DS_commands.c b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_DS_commands.c +new file mode 120000 +index 000000000000..59c8d082d9da +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_DS_commands.c +@@ -0,0 +1 @@ ++../../../TTA_DS/TTA_DS/code_files/TTA_DS_commands.c +\ No newline at end of file +diff --git a/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/sub.mk +new file mode 100644 +index 000000000000..a81f41cca435 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_Crypto.c TTA_DS_commands.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..48878d6c7505 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#define TA_UUID { 0x534D4152, 0x5443, 0x534C, { 0x54, 0x43, 0x52, 0x59, 0x50, 0x54, 0x4F, 0x31 } } ++ ++#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE ) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_Crypto v4.2" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/Makefile +new file mode 100644 +index 000000000000..10d6ff8634d6 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5444-415441535431 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/sub.mk +new file mode 100644 +index 000000000000..64519a0eaa71 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_DS.c TTA_DS_commands.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..421ee908ca31 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#define TA_UUID { 0x534D4152, 0x5443, 0x534C, { 0x54, 0x44, 0x41, 0x54, 0x41, 0x53, 0x54, 0x31 } } ++ ++#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE ) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_DS v4.0" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/Makefile +new file mode 100644 +index 000000000000..b0a3ee8f90c3 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-542d-4353-4c54-2d54412d3031 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/sub.mk +new file mode 100644 +index 000000000000..c33de9cee75e +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/sub.mk +@@ -0,0 +1,6 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_TCF.c ++cflags-y := -include ../../../../GP_defs.h ++cflags-y += -Wno-int-to-pointer-cast ++cflags-y += -Wno-cast-align ++cflags-y += -Wno-misleading-indentation +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/ta_TCF_test.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/ta_TCF_test.h +new file mode 100644 +index 000000000000..f0da901f0fdd +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/ta_TCF_test.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. ++ */ ++ ++#define TA_UUID { \ ++ 0x534D4152, \ ++ 0x542D, \ ++ 0x4353, \ ++ { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x30, 0x31 } \ ++ } +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..3df06d336dc5 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "ta_TCF_test.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE \ ++ | TA_FLAG_EXEC_DDR \ ++ | TA_FLAG_SINGLE_INSTANCE \ ++ ) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_TCF v1.9" }, \ ++ { "smc.ta.teststring", USER_TA_PROP_TYPE_STRING, \ ++ "this is a test string" }, \ ++ { "smc.ta.testbooltrue", USER_TA_PROP_TYPE_BOOL, \ ++ &(const bool){ true } }, \ ++ { "smc.ta.testboolfalse", USER_TA_PROP_TYPE_BOOL, \ ++ &(const bool){ false } }, \ ++ { "smc.ta.testu32", USER_TA_PROP_TYPE_U32, \ ++ &(const uint32_t){ 48059 } }, \ ++ { "smc.ta.testbinaryblock", USER_TA_PROP_TYPE_BINARY_BLOCK, \ ++ "VGhpcyBpcyBhIHRleHQgYmluYXJ5IGJsb2Nr" }, \ ++ { "smc.ta.testuuid", USER_TA_PROP_TYPE_UUID, \ ++ &(const TEE_UUID) { 0x534D4152, 0x542D, 0x4353, \ ++ { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x30, 0x31 } } }, \ ++ { "smc.ta.testidentity", USER_TA_PROP_TYPE_IDENTITY, \ ++ &(const TEE_Identity) { 0xF0000000, \ ++ { 0x534D4152, 0x542D, 0x4353, \ ++ { 0x4C, 0x54, 0x2D, 0x54, 0x41, 0x2D, 0x30, 0x31 } } } } ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/Makefile +new file mode 100644 +index 000000000000..7fa2badee534 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5441-544346494341 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/sub.mk +new file mode 100644 +index 000000000000..1ee47bdf5a72 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_TCF_ICA.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..51f22238def1 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA/code_files/user_ta_header_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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_TCF_ICA_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \ ++ TA_FLAG_SINGLE_INSTANCE) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_TCF_ICA v0.4" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ ++ +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/Makefile +new file mode 100644 +index 000000000000..388b18a10524 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5454-434649434132 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/sub.mk +new file mode 100644 +index 000000000000..1b787f63932d +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_TCF_ICA2.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..b8539d83c1a3 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_ICA2/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_TCF_ICA2_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \ ++ TA_FLAG_SINGLE_INSTANCE) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_TCF_ICA2 v0.2" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ ++ ++ +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/Makefile +new file mode 100644 +index 000000000000..91ae7c8a3cbe +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-4d4c-54494e535443 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/sub.mk +new file mode 100644 +index 000000000000..e937e20a722a +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_TCF_MultipleInstanceTA.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..ab50b401786f +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_MultipleInstanceTA/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_TCF_MultipleInstanceTA_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE \ ++ | TA_FLAG_EXEC_DDR \ ++ | TA_FLAG_MULTI_SESSION \ ++ ) ++ ++#define TA_STACK_SIZE (1*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_testingInternalAPI_TrustedCoreFramework_MultipleInstanceTA v0.1" }, ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/Makefile +new file mode 100644 +index 000000000000..bbf464cf8393 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-434c-4f50414e4943 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/sub.mk +new file mode 100644 +index 000000000000..4333c6e0d7d2 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_TCF_PanicAtCloseSession.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..86b1d0f1c865 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCloseSession/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#define TA_UUID { 0x534D4152, 0x5443, 0x534C, { 0x43, 0x4C, 0x4F, 0x50, 0x41, 0x4E, 0x49, 0x43 } } ++ ++#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ ++ TA_FLAG_MULTI_SESSION) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_TCF_PanicAtCloseSession v1.1" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/Makefile +new file mode 100644 +index 000000000000..2e2ea217c7f7 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5443-5250414e4943 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/sub.mk +new file mode 100644 +index 000000000000..d44f08240915 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_TCF_PanicAtCreation.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..197efebb119b +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_PanicAtCreation/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#define TA_UUID { 0x534D4152, 0x5443, 0x534C, { 0x54, 0x43, 0x52, 0x50, 0x41, 0x4E, 0x49, 0x43 } } ++ ++#define TA_FLAGS (TA_FLAG_MULTI_SESSION) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_TCF_PanicAtCloseSession v1.1" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/Makefile +new file mode 100644 +index 000000000000..b61365f4249e +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5347-4c494e535443 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/sub.mk +new file mode 100644 +index 000000000000..3ab31a7029cf +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_TCF_SingleInstanceTA.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..136e68d84eec +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF_SingleInstanceTA/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++#include "TTA_TCF_SingleInstanceTA_protocol.h" ++ ++#define TA_FLAGS (TA_FLAG_USER_MODE \ ++ | TA_FLAG_EXEC_DDR \ ++ | TA_FLAG_SINGLE_INSTANCE \ ++ ) ++#define TA_STACK_SIZE (1*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gpd.ta.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_testingInternalAPI_TrustedCoreFramework_SingleInstanceTA v0.4" }, ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/Makefile b/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/Makefile +new file mode 100644 +index 000000000000..07f3d9743a59 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/Makefile +@@ -0,0 +1,2 @@ ++BINARY = 534d4152-5443-534c-5f54-494d45415049 ++include ../../../ta_common.mk +diff --git a/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/sub.mk b/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/sub.mk +new file mode 100644 +index 000000000000..ab3ac849d1c4 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/sub.mk +@@ -0,0 +1,3 @@ ++global-incdirs-y += ../../../TEE_include ++srcs-y += TTA_Time.c ++cflags-y := -include ../../../../GP_defs.h +diff --git a/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/user_ta_header_defines.h b/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/user_ta_header_defines.h +new file mode 100644 +index 000000000000..1f25614bb473 +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/TTA_Time/TTA_Time/code_files/user_ta_header_defines.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 USER_TA_HEADER_DEFINES_H ++#define USER_TA_HEADER_DEFINES_H ++ ++ ++#define TA_UUID { 0x534D4152, 0x5443, 0x534C, { 0x5F, 0x54, 0x49, 0x4D, 0x45, 0x41, 0x50, 0x49 } } ++ ++#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE ) ++#define TA_STACK_SIZE (2*1024) ++#define TA_DATA_SIZE (32*1024) ++ ++#define TA_CURRENT_TA_EXT_PROPERTIES \ ++ { "gp.test.description", USER_TA_PROP_TYPE_STRING, \ ++ "TTA_Time v1.0" }, \ ++ ++#endif /* USER_TA_HEADER_DEFINES_H */ +diff --git a/TTAs_Internal_API_1_1_1/ta_common.mk b/TTAs_Internal_API_1_1_1/ta_common.mk +new file mode 100644 +index 000000000000..b8ce142bcf0a +--- /dev/null ++++ b/TTAs_Internal_API_1_1_1/ta_common.mk +@@ -0,0 +1,3 @@ ++# Note that it is important that that $(BINARY) is set before we include ++# ta_dev_kit.mk. In the optee_test this is done in the individual TA Makefiles. ++include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0003-TTA_TCF-patch.patch b/optee/optee_test/host/xtest/gp/patches/0003-TTA_TCF-patch.patch new file mode 100644 index 0000000..169aa4f --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0003-TTA_TCF-patch.patch @@ -0,0 +1,26 @@ +From 2bdbcc524e8f14c85c46a0e915e195e6d086ba02 Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Mon, 22 Jun 2020 17:50:40 +0200 +Subject: [PATCH 03/11] TTA_TCF: patch + +Signed-off-by: Jens Wiklander +--- + TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.h b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.h +index 688e8cf74597..f46667883162 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.h ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.h +@@ -59,7 +59,7 @@ bool areStringsIdentical(const char *string1, size_t length1, const char *string + bool areStringsIdenticalWithZeroTerminated(const char *string1, size_t length1, const char *zeroTerminatedString); + bool areUUIDsIdentical(TEE_UUID *UUID1, TEE_UUID *UUID2); + bool areIdentitiesIdentical(TEE_Identity *Identity1, TEE_Identity *Identity2); +-bool areBinaryBlocksIdentical(const char *BinaryBlock1, uint32_t nLength1, const char *BinaryBlock2, uint32_t nLength2); ++bool areBinaryBlocksIdentical(const char *BinaryBlock1, size_t nLength1, const char *BinaryBlock2, size_t nLength2); + bool isPropertySet (TEE_PropSetHandle propsetOrEnumerator); + void getUUIDFromBuffer(TEE_UUID *pTargetUUID, char uuidvalue[16]); + enum propType getPropertyType(const char *propString, size_t propStringLength); +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0004-TTA_Arithmetical-patch.patch b/optee/optee_test/host/xtest/gp/patches/0004-TTA_Arithmetical-patch.patch new file mode 100644 index 0000000..9b8a22e --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0004-TTA_Arithmetical-patch.patch @@ -0,0 +1,26 @@ +From 1664c3124576d8b2065206e99016bfa6a5d9ac34 Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Tue, 23 Jun 2020 13:43:40 +0200 +Subject: [PATCH 04/11] TTA_Arithmetical: patch + +Signed-off-by: Jens Wiklander +--- + .../TTA_Arithmetical/code_files/TTA_Arithmetical_protocol.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/TTA_Arithmetical_protocol.h b/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/TTA_Arithmetical_protocol.h +index 063f4b59e218..13cb801eeb20 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/TTA_Arithmetical_protocol.h ++++ b/TTAs_Internal_API_1_1_1/TTA_Arithmetical/TTA_Arithmetical/code_files/TTA_Arithmetical_protocol.h +@@ -61,7 +61,7 @@ typedef struct { + + TTA_Internal_Data* SetUpTTAInternalData(void); + void ResetTTAInternalData(TTA_Internal_Data *pInternalData); +-TEE_BigIntFMM* AllocateAndInitializeFMM(uint32_t nModulusSizeInBytes); ++TEE_BigIntFMM* AllocateAndInitializeFMM(size_t nModulusSizeInBytes); + TEE_BigInt* AllocateAndInitialize(uint32_t nSizeInBytes); + uint32_t CmdGetBigIntSignInUint32(TEE_BigInt *pBigInt); + TEE_Result CmdTEEBigIntCmp( +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0005-GP_defs.h-enable-debug-prints.patch b/optee/optee_test/host/xtest/gp/patches/0005-GP_defs.h-enable-debug-prints.patch new file mode 100644 index 0000000..32e69dc --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0005-GP_defs.h-enable-debug-prints.patch @@ -0,0 +1,28 @@ +From 83990e0e151d164f0d9e69053305fad2429f8cdc Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Mon, 29 Jun 2020 12:48:11 +0200 +Subject: [PATCH 05/11] GP_defs.h: enable debug prints + +Enables debug prints using the *MSG() macros. + +Signed-off-by: Jens Wiklander +--- + TTAs_Internal_API_1_1_1/GP_defs.h | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/TTAs_Internal_API_1_1_1/GP_defs.h b/TTAs_Internal_API_1_1_1/GP_defs.h +index 3d6ef1d53c78..91995187cae2 100644 +--- a/TTAs_Internal_API_1_1_1/GP_defs.h ++++ b/TTAs_Internal_API_1_1_1/GP_defs.h +@@ -1,4 +1,5 @@ +-#define SLogTrace(...) +-#define SLogError(...) +-#define SLogWarning(...) ++#include ++#define SLogTrace DMSG ++#define SLogError EMSG ++#define SLogWarning IMSG + #define S_VAR_NOT_USED(x) do { (void)(x); } while (0) +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch b/optee/optee_test/host/xtest/gp/patches/0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch new file mode 100644 index 0000000..6a9355e --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch @@ -0,0 +1,192 @@ +From 1f8d4686cd7c42ad59c9411e1dd7ceea97f5de9d Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Tue, 7 Jul 2020 17:19:50 +0200 +Subject: [PATCH 06/11] TTA_TCF: fix CmdTEEGetPropertyA*_withoutEnum() + +Property name must not reside in non-secure shared memory when passed as +argument to TEE_GetPropertyAs*(). + +Signed-off-by: Jens Wiklander +--- + .../TTA_TCF/TTA_TCF/code_files/TTA_TCF.c | 56 +++++++++++++------ + 1 file changed, 39 insertions(+), 17 deletions(-) + +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c +index b7c44c67fe32..8d1df25dea69 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c +@@ -311,7 +311,7 @@ TEE_Result CmdTEEGetPropertyAsString_withoutEnum( + { + /** VARIABLES **/ + TEE_PropSetHandle nPropSet; +- char* pPropName; ++ char pPropName[PROPERTY_NAME_MAX_SIZE]; + char* pOutputName; + + TEE_Result cmdResult; +@@ -330,12 +330,15 @@ TEE_Result CmdTEEGetPropertyAsString_withoutEnum( + /* Read the input parameter */ + nPropSet = (TEE_PropSetHandle)pParams[0].value.a; + +- pPropName = pParams[1].memref.buffer; +- if (pPropName == NULL) ++ if (!pParams[1].memref.buffer || ++ pParams[1].memref.size >= sizeof(pPropName)) + { + SLogError("CmdTEEGetPropertyAsString_withoutEnum: property name Input parameter is NULL"); + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } ++ TEE_MemMove(pPropName, pParams[1].memref.buffer, ++ pParams[1].memref.size); ++ pPropName[pParams[1].memref.size] = 0; + + /* Read the output parameters */ + pOutputName = pParams[2].memref.buffer; +@@ -359,7 +362,7 @@ TEE_Result CmdTEEGetPropertyAsBool_withoutEnum( + { + /** VARIABLES **/ + TEE_PropSetHandle nPropSet; +- char* pPropName; ++ char pPropName[PROPERTY_NAME_MAX_SIZE]; + char nTrue[4] = "true"; + char nFalse[5] = "false"; + bool nOutputBool; +@@ -381,12 +384,16 @@ TEE_Result CmdTEEGetPropertyAsBool_withoutEnum( + /* Read the input parameter */ + nPropSet = (TEE_PropSetHandle)pParams[0].value.a; + +- pPropName = pParams[1].memref.buffer; + if (pPropName == NULL) ++ if (!pParams[1].memref.buffer || ++ pParams[1].memref.size >= sizeof(pPropName)) + { + SLogError("CmdTEEGetPropertyAsBool_withoutEnum: property name Input parameter is NULL"); + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } ++ TEE_MemMove(pPropName, pParams[1].memref.buffer, ++ pParams[1].memref.size); ++ pPropName[pParams[1].memref.size] = 0; + + /* if all input/output data are correct */ + cmdResult = TEE_GetPropertyAsBool(nPropSet, pPropName, &nOutputBool); +@@ -412,7 +419,7 @@ TEE_Result CmdTEEGetPropertyAsInt_withoutEnum( + { + /** VARIABLES **/ + TEE_PropSetHandle nPropSet; +- char* pPropName; ++ char pPropName[PROPERTY_NAME_MAX_SIZE]; + char nResultString[5] = "48059"; + char nWrongResultString[11] = "wrong value"; + uint32_t nIntResult; +@@ -435,12 +442,15 @@ TEE_Result CmdTEEGetPropertyAsInt_withoutEnum( + /* Read the input parameter */ + nPropSet = (TEE_PropSetHandle)pParams[0].value.a; + +- pPropName = pParams[1].memref.buffer; +- if (pPropName == NULL) ++ if (!pParams[1].memref.buffer || ++ pParams[1].memref.size >= sizeof(pPropName)) + { + SLogError("CmdTEEGetPropertyAsInt_withoutEnum: property name Input parameter is NULL"); + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } ++ TEE_MemMove(pPropName, pParams[1].memref.buffer, ++ pParams[1].memref.size); ++ pPropName[pParams[1].memref.size] = 0; + + /* if all input/output data are correct */ + cmdResult = TEE_GetPropertyAsU32(nPropSet, pPropName, &nIntResult); +@@ -466,7 +476,7 @@ TEE_Result CmdTEEGetPropertyAsBinaryBlock_withoutEnum( + { + /** VARIABLES **/ + TEE_PropSetHandle nPropSet; +- char* pPropName; ++ char pPropName[PROPERTY_NAME_MAX_SIZE]; + void* pOutputBinaryBlock; + TEE_Result cmdResult; + +@@ -485,12 +495,15 @@ TEE_Result CmdTEEGetPropertyAsBinaryBlock_withoutEnum( + /* Read the input parameter */ + nPropSet = (TEE_PropSetHandle)pParams[0].value.a; + +- pPropName = pParams[1].memref.buffer; +- if ((pPropName == NULL)) ++ if (!pParams[1].memref.buffer || ++ pParams[1].memref.size >= sizeof(pPropName)) + { + SLogError("CmdTEEGetPropertyAsBinaryBlock_withoutEnum: property name Input parameter is NULL"); + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } ++ TEE_MemMove(pPropName, pParams[1].memref.buffer, ++ pParams[1].memref.size); ++ pPropName[pParams[1].memref.size] = 0; + + /* Read the output parameters */ + pOutputBinaryBlock = pParams[2].memref.buffer; +@@ -515,7 +528,7 @@ TEE_Result CmdTEEGetPropertyAsUUID_withoutEnum( + { + /** VARIABLES **/ + TEE_PropSetHandle nPropSet; +- char* pPropName; ++ char pPropName[PROPERTY_NAME_MAX_SIZE]; + char nWrongResultString[10] = "wrong uuid"; + char nResultUUIDString[36] = "534D4152-542D-4353-4C54-2D54412D3031"; + char nClockSeqAndNode[8] = SMC_TA_TESTUUID_CLOCKSEQANDNODE; +@@ -537,12 +550,15 @@ TEE_Result CmdTEEGetPropertyAsUUID_withoutEnum( + /* Read the input parameter */ + nPropSet = (TEE_PropSetHandle)pParams[0].value.a; + +- pPropName = pParams[1].memref.buffer; +- if ((pPropName == NULL)) ++ if (!pParams[1].memref.buffer || ++ pParams[1].memref.size >= sizeof(pPropName)) + { + SLogError("CmdTEEGetPropertyAsUUID_withoutEnum: property name Input parameter is NULL"); + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } ++ TEE_MemMove(pPropName, pParams[1].memref.buffer, ++ pParams[1].memref.size); ++ pPropName[pParams[1].memref.size] = 0; + + /* Read the output parameters */ + if (pParams[2].memref.buffer == NULL) +@@ -579,7 +595,7 @@ TEE_Result CmdTEEGetPropertyAsIdentity_withoutEnum( + { + /** VARIABLES **/ + TEE_PropSetHandle nPropSet; +- char* pPropName; ++ char pPropName[PROPERTY_NAME_MAX_SIZE]; + char nWrongResultString[14] = "wrong identity"; + char nResultIdentityString[45] = "F0000000:534D4152-542D-4353-4C54-2D54412D3031"; + char nClockSeqAndNode[8] = SMC_TA_TESTUUID_CLOCKSEQANDNODE; +@@ -602,12 +618,15 @@ TEE_Result CmdTEEGetPropertyAsIdentity_withoutEnum( + /* Read the input parameter */ + nPropSet = (TEE_PropSetHandle)pParams[0].value.a; + +- pPropName = pParams[1].memref.buffer; +- if ((pPropName == NULL)) ++ if (!pParams[1].memref.buffer || ++ pParams[1].memref.size >= sizeof(pPropName)) + { + SLogError("CmdTEEGetPropertyAsIdentity_withoutEnum: property name Input parameter is NULL"); + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } ++ TEE_MemMove(pPropName, pParams[1].memref.buffer, ++ pParams[1].memref.size); ++ pPropName[pParams[1].memref.size] = 0; + + /* Read the output parameters */ + if (pParams[2].memref.buffer == NULL) +@@ -647,6 +666,9 @@ TEE_Result CmdTEEGetPropertyAsXXX_fromEnum( + TEE_PropSetHandle nPropSet; + char pPropName[PROPERTY_NAME_MAX_SIZE]; + size_t nPropNameSize = 0; ++ TEE_MemMove(pPropName, pParams[1].memref.buffer, ++ pParams[1].memref.size); ++ pPropName[pParams[1].memref.size] = 0; + char pOutputString1[PROPERTY_OUTPUT_STRING_MAX_SIZE], pOutputString2[PROPERTY_OUTPUT_STRING_MAX_SIZE]; + size_t nOutputString1Length = 0; + size_t nOutputString2Length = 0; +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0007-TTAs-revert-to-v1.1-types.patch b/optee/optee_test/host/xtest/gp/patches/0007-TTAs-revert-to-v1.1-types.patch new file mode 100644 index 0000000..4eb3835 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0007-TTAs-revert-to-v1.1-types.patch @@ -0,0 +1,90 @@ +From 309bdb9181502392f1d1a978e4e97706ebf532c8 Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Thu, 24 Sep 2020 11:31:34 +0200 +Subject: [PATCH 07/11] TTAs revert to v1.1 types + +Replacing some occurrences of size_t with uint32_t. + +Signed-off-by: Jens Wiklander +--- + .../TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto.c | 4 ++-- + .../TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto_protocol.h | 2 +- + .../TTA_DS/TTA_DS/code_files/TTA_DS_commands.c | 4 ++-- + .../TTA_TCF/TTA_TCF/code_files/TTA_TCF.c | 6 +++--- + 4 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto.c b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto.c +index 11de643f586d..d17448e878ca 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto.c ++++ b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto.c +@@ -298,7 +298,7 @@ void SetOperationToNull(TEE_CryptoData *pCryptoData, uint32_t lopId) + (pCryptoData->Operation3) = TEE_HANDLE_NULL; + } + +-bool copyOperationInfoMultipleToBuffer(const TEE_OperationInfoMultiple *pOpInfo, uint8_t *buffer, size_t *size) ++bool copyOperationInfoMultipleToBuffer(const TEE_OperationInfoMultiple *pOpInfo, uint8_t *buffer, uint32_t *size) + { + const size_t allocatedSize = *size; + const size_t outputSize = 32 + pOpInfo->numberOfKeys * 8; +@@ -976,7 +976,7 @@ TEE_Result CmdGetOperationInfoMultiple( + if (numberOfKeys > MAX_NUMBER_OF_KEYS) + return TRUSTED_APP_ERROR_VALUE_OUT_OF_RANGE; + +- operationSize = sizeof(TEE_OperationInfoMultiple) + numberOfKeys * sizeof(TEE_OperationInfoKey); // from 1.1 §6.1.3 ++ operationSize = sizeof(TEE_OperationInfoMultiple) + numberOfKeys * sizeof(TEE_OperationInfoKey); // from 1.1 ?6.1.3 + + returnCode = TEE_GetOperationInfoMultiple(operation, pCryptoData->OperationInfoMultiple, &operationSize); + +diff --git a/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto_protocol.h b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto_protocol.h +index 51c827cdb796..13f816d8f0ae 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto_protocol.h ++++ b/TTAs_Internal_API_1_1_1/TTA_Crypto/TTA_Crypto/code_files/TTA_Crypto_protocol.h +@@ -47,7 +47,7 @@ void writeUint32ToBuffer(uint32_t value, uint8_t buffer[]); + bool getOperation(TEE_CryptoData *pCryptoData, uint32_t lopId, TEE_OperationHandle *pOperation); + bool getKey(TEE_CryptoData *pCryptoData, uint32_t lkeyId, TEE_ObjectHandle *pKey); + void SetOperationToNull(TEE_CryptoData *pCryptoData, uint32_t lopId); +-bool copyOperationInfoMultipleToBuffer(const TEE_OperationInfoMultiple *pOpInfo, uint8_t *buffer, size_t *size); ++bool copyOperationInfoMultipleToBuffer(const TEE_OperationInfoMultiple *pOpInfo, uint8_t *buffer, uint32_t *size); + + TEE_Result CmdTTAEnsureIntermediateBufferSize( + void* pSessionContext, +diff --git a/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/TTA_DS_commands.c b/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/TTA_DS_commands.c +index 31efbbb01710..d828e7b4e383 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/TTA_DS_commands.c ++++ b/TTAs_Internal_API_1_1_1/TTA_DS/TTA_DS/code_files/TTA_DS_commands.c +@@ -940,9 +940,9 @@ TEE_Result CmdGetNextPersistentObject( + TEE_Param pParams[4]) + { + uint8_t localBuffer[TEE_OBJECT_ID_MAX_LEN] = { 0 }; +- size_t localBufferLength = NELEM(localBuffer); ++ uint32_t localBufferLength = NELEM(localBuffer); + void *objectID; +- size_t *objectIDLen; ++ uint32_t *objectIDLen; + TEE_ObjectEnumHandle objectEnumerator; + TEE_ObjectInfo *pObjectInfo; + TEE_Result returnCode; +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c +index 8d1df25dea69..14e642cd6193 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c +@@ -665,13 +665,13 @@ TEE_Result CmdTEEGetPropertyAsXXX_fromEnum( + TEE_PropSetHandle nEnum; + TEE_PropSetHandle nPropSet; + char pPropName[PROPERTY_NAME_MAX_SIZE]; +- size_t nPropNameSize = 0; ++ uint32_t nPropNameSize = 0; + TEE_MemMove(pPropName, pParams[1].memref.buffer, + pParams[1].memref.size); + pPropName[pParams[1].memref.size] = 0; + char pOutputString1[PROPERTY_OUTPUT_STRING_MAX_SIZE], pOutputString2[PROPERTY_OUTPUT_STRING_MAX_SIZE]; +- size_t nOutputString1Length = 0; +- size_t nOutputString2Length = 0; ++ uint32_t nOutputString1Length = 0; ++ uint32_t nOutputString2Length = 0; + bool nOutputBool1; + bool nOutputBool2; + uint32_t nOutputInt1; +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0008-TEE.xml.patch b/optee/optee_test/host/xtest/gp/patches/0008-TEE.xml.patch new file mode 100644 index 0000000..f212284 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0008-TEE.xml.patch @@ -0,0 +1,38 @@ +From 1664a1487cdfb235483eb6f874f39839dee80e7e Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Wed, 24 Jun 2020 08:49:24 +0200 +Subject: [PATCH 08/11] TEE.xml + +Disabling the case: +- Request_Cancellation (d3-87-46) +Because the adaption layer we've implemented cannot deal with threads in +a good way + +Signed-off-by: Jens Wiklander +--- + packages/ClientAPI/xmlstable/TEE.xml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/packages/ClientAPI/xmlstable/TEE.xml b/packages/ClientAPI/xmlstable/TEE.xml +index 85cd81818f5f..e59c4df02d3c 100644 +--- a/packages/ClientAPI/xmlstable/TEE.xml ++++ b/packages/ClientAPI/xmlstable/TEE.xml +@@ -825,6 +825,7 @@ + + + ++ + + + +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0009-TEE_Internal_API.xml.patch b/optee/optee_test/host/xtest/gp/patches/0009-TEE_Internal_API.xml.patch new file mode 100644 index 0000000..f8b75a8 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0009-TEE_Internal_API.xml.patch @@ -0,0 +1,96 @@ +From a7caa35eff3487c0bd777f7df6f5337219b8d9dd Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Tue, 7 Jul 2020 11:17:14 +0200 +Subject: [PATCH 09/11] TEE_Internal_API.xml + +Disabling cases: +- Invoke_CheckMemoryAccessRight_BufferRead_AccessWrite_error (a7-35-f1) +- Invoke_CheckMemoryAccessRight_BufferWrite_AccessRead_error (a7-98-4b) +As OP-TEE doesn't check the direction of the passed memrefs + +Disabling the case: +- Invoke_GetCancellationFlag_RequestedCancel (a7-71-11 +Because the adaption layer we've implemented cannot deal with threads in +a good way. + +Disabling the case: +- Invoke_GetPropertyAsBinaryBlock_withoutEnum_success (a7-26-c1) +Because it assumes base64 coded binary properties and is also +in the list of excluded conformance tests. + +Signed-off-by: Jens Wiklander +--- + packages/TrustedCoreFw/xmlstable/TEE_Internal_API.xml | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/packages/TrustedCoreFw/xmlstable/TEE_Internal_API.xml b/packages/TrustedCoreFw/xmlstable/TEE_Internal_API.xml +index f9824238451a..0e96e3bde8e9 100644 +--- a/packages/TrustedCoreFw/xmlstable/TEE_Internal_API.xml ++++ b/packages/TrustedCoreFw/xmlstable/TEE_Internal_API.xml +@@ -523,6 +523,7 @@ + + + ++ + + + +@@ -1045,6 +1047,7 @@ + + + ++ + + + +@@ -2254,6 +2258,7 @@ + + + ++ + + + +@@ -3716,6 +3722,7 @@ + + + ++ + + + +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0010-TEE_DataStorage_API.xml.patch b/optee/optee_test/host/xtest/gp/patches/0010-TEE_DataStorage_API.xml.patch new file mode 100644 index 0000000..726b1e1 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0010-TEE_DataStorage_API.xml.patch @@ -0,0 +1,106 @@ +From cd058f01be06f70c54b9608d4a7b4dae5a5bc2e0 Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Wed, 19 Aug 2020 17:53:31 +0200 +Subject: [PATCH 10/11] TEE_DataStorage_API.xml + +Disabling cases: +- Invoke_SeekWriteRead_Offset_0_SEEK_END_Offset_Low (9d-a6-93) +- Invoke_SeekWriteRead_Offset_High_SEEK_CUR_Offset_Low (9d-60-98) +- Invoke_SeekWriteRead_Offset_Low_SEEK_CUR_Offset_High (9d-6b-51) +- Invoke_SeekWriteRead_Offset_Low_SEEK_END_Offset_Low (9d-21-93) +- Invoke_WriteObjectData_overflow (9d-01-ce) +These tests fails and the expected position counters doesn't seem to +make any sense. + +Signed-off-by: Jens Wiklander +--- + packages/DataStorage/xmlstable/TEE_DataStorage_API.xml | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/packages/DataStorage/xmlstable/TEE_DataStorage_API.xml b/packages/DataStorage/xmlstable/TEE_DataStorage_API.xml +index db43d7b71ebc..69305a880a9f 100644 +--- a/packages/DataStorage/xmlstable/TEE_DataStorage_API.xml ++++ b/packages/DataStorage/xmlstable/TEE_DataStorage_API.xml +@@ -166262,6 +166262,7 @@ + + + ++ + + + +@@ -169043,6 +169045,7 @@ + + + ++ + + + +@@ -170710,6 +170714,7 @@ + + + ++ + + + +@@ -172379,6 +172385,7 @@ + + + ++ + + + +@@ -178054,6 +178062,7 @@ + + + ++ + + + +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0011-TEE_Crypto_API.xml.patch b/optee/optee_test/host/xtest/gp/patches/0011-TEE_Crypto_API.xml.patch new file mode 100644 index 0000000..81b019c --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0011-TEE_Crypto_API.xml.patch @@ -0,0 +1,39 @@ +From af6aa988020a21895688dd2d8221119fbe6d3cf3 Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Wed, 19 Aug 2020 17:53:31 +0200 +Subject: [PATCH 11/11] TEE_Crypto_API.xml + +Disabling case: +- Invoke_Crypto_MACInit_init_vector_not_required_length (50-ea-af) + +CBC MAC doesn't take any IV so TEE_MACInit() is supposed to ignore IV +and IVLen. + +Signed-off-by: Jens Wiklander +--- + packages/Crypto/xmlstable/TEE_Crypto_API.xml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/packages/Crypto/xmlstable/TEE_Crypto_API.xml b/packages/Crypto/xmlstable/TEE_Crypto_API.xml +index 11013c152fb2..b8246376866e 100644 +--- a/packages/Crypto/xmlstable/TEE_Crypto_API.xml ++++ b/packages/Crypto/xmlstable/TEE_Crypto_API.xml +@@ -130401,6 +130401,7 @@ + + + ++ + + + +-- +2.25.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0012-TTA_TCF-remove-TEE_MemMove-from-CmdTEEGetPropertyAsX.patch b/optee/optee_test/host/xtest/gp/patches/0012-TTA_TCF-remove-TEE_MemMove-from-CmdTEEGetPropertyAsX.patch new file mode 100644 index 0000000..798b99a --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0012-TTA_TCF-remove-TEE_MemMove-from-CmdTEEGetPropertyAsX.patch @@ -0,0 +1,34 @@ +From c2431936b80e2064d52a380c715cd3260ce54d54 Mon Sep 17 00:00:00 2001 +From: Jerome Forissier +Date: Fri, 23 Apr 2021 09:25:55 +0200 +Subject: [PATCH] TTA_TCF: remove TEE_MemMove() from + CmdTEEGetPropertyAsXXX_fromEnum() + +Patch 0006-TTA_TCF-fix-CmdTEEGetPropertyA-_withoutEnum.patch introduced +a TEE_MemMove() call in CmdTEEGetPropertyAsXXX_fromEnum(). This call is +wrong, because in this function pParams[1] is always of type +TEE_PARAM_TYPE_VALUE_INPUT (in other words, not a memory reference). + +Fixes: https://github.com/OP-TEE/optee_os/issues/4561 +Signed-off-by: Jerome Forissier +--- + .../TTA_TCF/TTA_TCF/code_files/TTA_TCF.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c +index 14e642c..0c7c743 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c +@@ -666,9 +666,6 @@ TEE_Result CmdTEEGetPropertyAsXXX_fromEnum( + TEE_PropSetHandle nPropSet; + char pPropName[PROPERTY_NAME_MAX_SIZE]; + uint32_t nPropNameSize = 0; +- TEE_MemMove(pPropName, pParams[1].memref.buffer, +- pParams[1].memref.size); +- pPropName[pParams[1].memref.size] = 0; + char pOutputString1[PROPERTY_OUTPUT_STRING_MAX_SIZE], pOutputString2[PROPERTY_OUTPUT_STRING_MAX_SIZE]; + uint32_t nOutputString1Length = 0; + uint32_t nOutputString2Length = 0; +-- +2.27.0 + diff --git a/optee/optee_test/host/xtest/gp/patches/0013-Disable-Invoke_GetTAPersistentTimeNotSet_and_SetTAPe.patch b/optee/optee_test/host/xtest/gp/patches/0013-Disable-Invoke_GetTAPersistentTimeNotSet_and_SetTAPe.patch new file mode 100644 index 0000000..4bda5e2 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0013-Disable-Invoke_GetTAPersistentTimeNotSet_and_SetTAPe.patch @@ -0,0 +1,38 @@ +From a3116f3eb2595600a6b1d40b7b25e2b36770d2f6 Mon Sep 17 00:00:00 2001 +From: Jerome Forissier +Date: Tue, 27 Apr 2021 17:34:40 +0200 +Subject: [PATCH] Disable + Invoke_GetTAPersistentTimeNotSet_and_SetTAPersistentTime_success (ce-7b-17) + +Test case Invoke_GetTAPersistentTimeNotSet_and_SetTAPersistentTime_success +depends on the ability to erase the persistent time previously set by a +TA. OP-TEE doesn't provide any way to do that, so disable this test. + +Signed-off-by: Jerome Forissier +--- + packages/Time_Arithmetical/xmlstable/TEE_TimeArithm_API.xml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/packages/Time_Arithmetical/xmlstable/TEE_TimeArithm_API.xml b/packages/Time_Arithmetical/xmlstable/TEE_TimeArithm_API.xml +index 7d905dc..8c17155 100644 +--- a/packages/Time_Arithmetical/xmlstable/TEE_TimeArithm_API.xml ++++ b/packages/Time_Arithmetical/xmlstable/TEE_TimeArithm_API.xml +@@ -54397,6 +54397,7 @@ + + + ++ + + + seconds. For example, if the Trusted Application sets its persistent time to 2^32 -100 seconds, then after 100 seconds, the TA Persistent Time is 2^32, which is not representable with a uint32_t. In this case, the function TEE_GetTAPersistentTime MUST return TEE_ERROR_OVERFLOW and set time->seconds to 0 (which is 2^32 truncated to 32 bits).]]> +-- +2.27.0 + diff --git a/optee/optee_test/host/xtest/gp/patches/0014-Pass-upper-32-bits-of-TEE_PropSetHandle-in-value.b.patch b/optee/optee_test/host/xtest/gp/patches/0014-Pass-upper-32-bits-of-TEE_PropSetHandle-in-value.b.patch new file mode 100644 index 0000000..3e6bec6 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0014-Pass-upper-32-bits-of-TEE_PropSetHandle-in-value.b.patch @@ -0,0 +1,110 @@ +From 6d47284d5e9704cfa0ef0e4e9b997595288856c9 Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Wed, 4 May 2022 12:39:59 +0200 +Subject: [PATCH] Pass upper 32 bits of TEE_PropSetHandle in value.b + +With MTE enabled 64-bit pointer usually use the upper 32 bits too while +the GP tests assumes that 32 bits are enough. Fix this by passing the +upper 32 bits in value.b + +Signed-off-by: Jens Wiklander +--- + .../TTA_TCF/TTA_TCF/code_files/TTA_TCF.c | 33 +++++++++++++++---- + 1 file changed, 27 insertions(+), 6 deletions(-) + +diff --git a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c +index 0c7c743b34f9..30ba37788662 100644 +--- a/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c ++++ b/TTAs_Internal_API_1_1_1/TTA_TCF/TTA_TCF/code_files/TTA_TCF.c +@@ -154,6 +154,24 @@ void TA_EXPORT TA_CloseSessionEntryPoint( + TEE_Free(pSessionContext); + } + ++static TEE_Param ptr_to_param(void *ptr) ++{ ++ uint64_t u = (unsigned long)ptr; ++ TEE_Param param; ++ ++ param.value.a = u; ++ param.value.b = u >> 32; ++ ++ return param; ++} ++ ++static void *param_to_ptr(TEE_Param *param) ++{ ++ unsigned long u = ((uint64_t)param->value.b << 32) | param->value.a; ++ ++ return (void *)u; ++} ++ + bool isPropertySet (TEE_PropSetHandle propsetOrEnumerator) + { + if((propsetOrEnumerator == TEE_PROPSET_CURRENT_TA)|| +@@ -772,6 +790,7 @@ TEE_Result CmdTEEAllocatePropertyEnumerator( + { + /** VARIABLES **/ + TEE_Result cmdResult; ++ TEE_PropSetHandle h; + + S_VAR_NOT_USED(pSessionContext); + +@@ -782,7 +801,8 @@ TEE_Result CmdTEEAllocatePropertyEnumerator( + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } + +- cmdResult = TEE_AllocatePropertyEnumerator((TEE_PropSetHandle*) &pParams[0].value.a); ++ cmdResult = TEE_AllocatePropertyEnumerator(&h); ++ pParams[0] = ptr_to_param(h); + + return cmdResult; + } +@@ -804,7 +824,8 @@ TEE_Result CmdTEEStartPropertyEnumerator( + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } + +- TEE_StartPropertyEnumerator((TEE_PropSetHandle) pParams[0].value.a, (TEE_PropSetHandle) pParams[1].value.a); ++ TEE_StartPropertyEnumerator(param_to_ptr(pParams), ++ param_to_ptr(pParams + 1)); + + return TEE_SUCCESS; + } +@@ -825,7 +846,7 @@ TEE_Result CmdTEEGetNextPropertyEnumerator_notStarted( + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } + +- return TEE_GetNextProperty((TEE_PropSetHandle) pParams[0].value.a); ++ return TEE_GetNextProperty(param_to_ptr(pParams)); + } + + TEE_Result CmdTEEResetPropertyEnumerator( +@@ -844,7 +865,7 @@ TEE_Result CmdTEEResetPropertyEnumerator( + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } + +- TEE_ResetPropertyEnumerator((TEE_PropSetHandle) pParams[0].value.a); ++ TEE_ResetPropertyEnumerator(param_to_ptr(pParams)); + return TEE_SUCCESS; + } + +@@ -864,7 +885,7 @@ TEE_Result CmdTEEFreePropertyEnumerator( + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } + +- TEE_FreePropertyEnumerator((TEE_PropSetHandle) pParams[0].value.a); ++ TEE_FreePropertyEnumerator(param_to_ptr(pParams)); + + return TEE_SUCCESS; + } +@@ -887,7 +908,7 @@ TEE_Result CmdTEEGetPropertyName( + return TRUSTED_APP_ERROR_BAD_PARAMETERS; + } + +- cmdResult = TEE_GetPropertyName((TEE_PropSetHandle) pParams[0].value.a, pParams[1].memref.buffer, &pParams[1].memref.size); ++ cmdResult = TEE_GetPropertyName(param_to_ptr(pParams), pParams[1].memref.buffer, &pParams[1].memref.size); + + return cmdResult; + } +-- +2.31.1 + diff --git a/optee/optee_test/host/xtest/gp/patches/0015-Enable-compatibility-with-TEE-Internal-Core-API-v1.1.patch b/optee/optee_test/host/xtest/gp/patches/0015-Enable-compatibility-with-TEE-Internal-Core-API-v1.1.patch new file mode 100644 index 0000000..bea7740 --- /dev/null +++ b/optee/optee_test/host/xtest/gp/patches/0015-Enable-compatibility-with-TEE-Internal-Core-API-v1.1.patch @@ -0,0 +1,27 @@ +From 4e495cff6016583a9af14a62a16c2f7988fd9c68 Mon Sep 17 00:00:00 2001 +From: Jens Wiklander +Date: Wed, 30 Nov 2022 09:00:30 +0100 +Subject: [PATCH] Enable compatibility with TEE Internal Core API v1.1 + +The test suite is testing TEE Internal Core API v1.1 so make sure that +the API provided is compatible by setting +CFG_TA_OPTEE_CORE_API_COMPAT_1_1=y. + +Signed-off-by: Jens Wiklander +--- + TTAs_Internal_API_1_1_1/ta_common.mk | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/TTAs_Internal_API_1_1_1/ta_common.mk b/TTAs_Internal_API_1_1_1/ta_common.mk +index b8ce142bcf0a..0f8cc7d01314 100644 +--- a/TTAs_Internal_API_1_1_1/ta_common.mk ++++ b/TTAs_Internal_API_1_1_1/ta_common.mk +@@ -1,3 +1,5 @@ ++# These TAs are made for TEE Internal Core API version 1.1 ++CFG_TA_OPTEE_CORE_API_COMPAT_1_1=y + # Note that it is important that that $(BINARY) is set before we include + # ta_dev_kit.mk. In the optee_test this is done in the individual TA Makefiles. + include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk +-- +2.31.1 + diff --git a/optee/optee_test/host/xtest/gp/prepare_suite.sh b/optee/optee_test/host/xtest/gp/prepare_suite.sh new file mode 100644 index 0000000..142258b --- /dev/null +++ b/optee/optee_test/host/xtest/gp/prepare_suite.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2020, Linaro Limited. + +if [ $# -ne 2 ]; then + echo "usage: prepare_suite.sh " + exit 1 +fi + +set -e + +if [ -e $1/host/xtest/gp-suite ]; then + # Clean up last patching in case it failed in some way + rm -rf $1/host/xtest/gp-suite +fi +mkdir -p $1/host/xtest/gp-suite +7z x -o$1/host/xtest/gp-suite $2 +cd $1/host/xtest/gp-suite +mv TEE_Initial_Configuration-Test_Suite_v2_0_0_2-2017_06_09/* . +rmdir TEE_Initial_Configuration-Test_Suite_v2_0_0_2-2017_06_09 +rm -f TTAs_Internal_API_1_1_1/TEE_include/tee_internal_api.h +chmod -R u+w . +for p in `echo ../gp/patches/*.patch | sort -n` ;do + echo Applying $p + patch -p1 < $p +done diff --git a/optee/optee_test/host/xtest/hash_perf.c b/optee/optee_test/host/xtest/hash_perf.c new file mode 100644 index 0000000..ab96736 --- /dev/null +++ b/optee/optee_test/host/xtest/hash_perf.c @@ -0,0 +1,494 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crypto_common.h" +#include "xtest_helpers.h" + +/* + * TEE client stuff + */ + +static TEEC_Context ctx; +static TEEC_Session sess; +static TEEC_SharedMemory in_shm = { + .flags = TEEC_MEM_INPUT +}; +static TEEC_SharedMemory out_shm = { + .flags = TEEC_MEM_OUTPUT +}; + +static void errx(const char *msg, TEEC_Result res, uint32_t *orig) +{ + fprintf(stderr, "%s: 0x%08x", msg, res); + if (orig) + fprintf(stderr, " (orig=%d)", (int)*orig); + fprintf(stderr, "\n"); + exit (1); +} + +static void check_res(TEEC_Result res, const char *errmsg, uint32_t *orig) +{ + if (res != TEEC_SUCCESS) + errx(errmsg, res, orig); +} + +static void open_ta(void) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_UUID uuid = TA_HASH_PERF_UUID; + uint32_t err_origin = 0; + + res = TEEC_InitializeContext(NULL, &ctx); + check_res(res,"TEEC_InitializeContext", NULL); + + res = TEEC_OpenSession(&ctx, &sess, &uuid, TEEC_LOGIN_PUBLIC, NULL, + NULL, &err_origin); + check_res(res,"TEEC_OpenSession", &err_origin); +} + +/* + * Statistics + * + * We want to compute min, max, mean and standard deviation of processing time + */ + +struct statistics { + int n; + double m; + double M2; + double min; + double max; + int initialized; +}; + +/* Take new sample into account (Knuth/Welford algorithm) */ +static void update_stats(struct statistics *s, uint64_t t) +{ + double x = (double)t; + double delta = x - s->m; + + s->n++; + s->m += delta/s->n; + s->M2 += delta*(x - s->m); + if (!s->initialized) { + s->min = s->max = x; + s->initialized = 1; + } else { + if (s->min > x) + s->min = x; + if (s->max < x) + s->max = x; + } +} + +static double stddev(struct statistics *s) +{ + if (s->n < 2) + return NAN; + return sqrt(s->M2/s->n); +} + +static const char *algo_str(uint32_t algo) +{ + switch (algo) { + case TA_SHA_SHA1: + return "SHA1"; + case TA_SHA_SHA224: + return "SHA224"; + case TA_SHA_SHA256: + return "SHA256"; + case TA_SHA_SHA384: + return "SHA384"; + case TA_SHA_SHA512: + return "SHA512"; + case TA_SM3: + return "SM3"; + case TA_HMAC_SHA1: + return "HMAC_SHA1"; + case TA_HMAC_SHA224: + return "HMAC_SHA224"; + case TA_HMAC_SHA256: + return "HMAC_SHA256"; + case TA_HMAC_SHA384: + return "HMAC_SHA384"; + case TA_HMAC_SHA512: + return "HMAC_SHA512"; + case TA_HMAC_SM3: + return "HMAC_SM3"; + default: + return "???"; + } +} + +static int hash_size(uint32_t algo) +{ + switch (algo) { + case TA_SHA_SHA1: + case TA_HMAC_SHA1: + return 20; + case TA_SHA_SHA224: + case TA_HMAC_SHA224: + return 28; + case TA_SHA_SHA256: + case TA_HMAC_SHA256: + return 32; + case TA_SHA_SHA384: + case TA_HMAC_SHA384: + return 48; + case TA_SHA_SHA512: + case TA_HMAC_SHA512: + return 64; + case TA_SM3: + case TA_HMAC_SM3: + return 32; + default: + return 0; + } +} + +#define _TO_STR(x) #x +#define TO_STR(x) _TO_STR(x) + +static void alloc_shm(size_t sz, uint32_t algo, int offset) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + + in_shm.buffer = NULL; + in_shm.size = sz + offset; + res = TEEC_AllocateSharedMemory(&ctx, &in_shm); + check_res(res, "TEEC_AllocateSharedMemory", NULL); + + out_shm.buffer = NULL; + out_shm.size = hash_size(algo); + res = TEEC_AllocateSharedMemory(&ctx, &out_shm); + check_res(res, "TEEC_AllocateSharedMemory", NULL); +} + +static void free_shm(void) +{ + TEEC_ReleaseSharedMemory(&in_shm); + TEEC_ReleaseSharedMemory(&out_shm); +} + +static ssize_t read_random(void *in, size_t rsize) +{ + static int rnd; + ssize_t s = 0; + + if (!rnd) { + rnd = open("/dev/urandom", O_RDONLY); + if (rnd < 0) { + perror("open"); + return 1; + } + } + s = read(rnd, in, rsize); + if (s < 0) { + perror("read"); + return 1; + } + if ((size_t)s != rsize) { + printf("read: requested %zu bytes, got %zd\n", + rsize, s); + } + return 0; +} + +static long get_current_time(struct timespec *ts) +{ + if (clock_gettime(CLOCK_MONOTONIC, ts) < 0) { + perror("clock_gettime"); + exit(1); + } + return 0; +} + +static uint64_t timespec_diff_ns(struct timespec *start, struct timespec *end) +{ + uint64_t ns = 0; + + if (end->tv_nsec < start->tv_nsec) { + ns += 1000000000 * (end->tv_sec - start->tv_sec - 1); + ns += 1000000000 - start->tv_nsec + end->tv_nsec; + } else { + ns += 1000000000 * (end->tv_sec - start->tv_sec); + ns += end->tv_nsec - start->tv_nsec; + } + return ns; +} + +static uint64_t run_test_once(void *in, size_t size, int random_in, + TEEC_Operation *op) +{ + struct timespec t0 = { }; + struct timespec t1 = { }; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + + if (random_in == CRYPTO_USE_RANDOM) + read_random(in, size); + + get_current_time(&t0); + res = TEEC_InvokeCommand(&sess, TA_HASH_PERF_CMD_PROCESS, op, + &ret_origin); + check_res(res, "TEEC_InvokeCommand", &ret_origin); + get_current_time(&t1); + + return timespec_diff_ns(&t0, &t1); +} + +static void prepare_op(int algo) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_origin = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + op.params[0].value.a = algo; + res = TEEC_InvokeCommand(&sess, TA_HASH_PERF_CMD_PREPARE_OP, &op, + &ret_origin); + check_res(res, "TEEC_InvokeCommand", &ret_origin); +} + +static void do_warmup(int warmup) +{ + struct timespec t0 = { }; + struct timespec t = { }; + int i = 0; + + get_current_time(&t0); + do { + for (i = 0; i < 100000; i++) + ; + get_current_time(&t); + } while (timespec_diff_ns(&t0, &t) < (uint64_t)warmup * 1000000000); +} + +static const char *yesno(int v) +{ + return (v ? "yes" : "no"); +} + +static double mb_per_sec(size_t size, double usec) +{ + return (1000000000/usec)*((double)size/(1024*1024)); +} + +/* Hash test: buffer of size byte. Run test n times. + * Entry point for running SHA benchmark + * Params: + * algo - Algorithm + * size - Buffer size + * n - Number of measurements + * l - Amount of inner loops + * random_in - Get input from /dev/urandom + * offset - Buffer offset wrt. alloc-ed address + * warmup - Start with a-second busy loop + * verbosity - Verbosity level + * */ +extern void hash_perf_run_test(int algo, size_t size, unsigned int n, + unsigned int l, int random_in, int offset, + int warmup, int verbosity) +{ + uint64_t t = 0; + struct statistics stats = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + int n0 = n; + struct timespec ts = { }; + double sd = 0; + + vverbose("hash-perf\n"); + if (clock_getres(CLOCK_MONOTONIC, &ts) < 0) { + perror("clock_getres"); + return; + } + vverbose("Clock resolution is %jd ns\n", + (intmax_t)ts.tv_sec * 1000000000 + ts.tv_nsec); + + open_ta(); + prepare_op(algo); + + alloc_shm(size, algo, offset); + + if (random_in == CRYPTO_USE_ZEROS) + memset((uint8_t *)in_shm.buffer + offset, 0, size); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + op.params[0].memref.parent = &in_shm; + op.params[0].memref.offset = 0; + op.params[0].memref.size = size + offset; + op.params[1].memref.parent = &out_shm; + op.params[1].memref.offset = 0; + op.params[1].memref.size = hash_size(algo); + op.params[2].value.a = l; + op.params[2].value.b = offset; + + verbose("Starting test: %s, size=%zu bytes, ", + algo_str(algo), size); + verbose("random=%s, ", yesno(random_in == CRYPTO_USE_RANDOM)); + verbose("unaligned=%s, ", yesno(offset)); + verbose("inner loops=%u, loops=%u, warm-up=%u s\n", l, n, warmup); + + if (warmup) + do_warmup(warmup); + + while (n-- > 0) { + t = run_test_once((uint8_t *)in_shm.buffer + offset, size, + random_in, &op); + update_stats(&stats, t); + if (n % (n0 / 10) == 0) + vverbose("#"); + } + vverbose("\n"); + sd = stddev(&stats); + printf("min=%gus max=%gus mean=%gus stddev=%gus (cv %g%%) (%gMiB/s)\n", + stats.min / 1000, stats.max / 1000, stats.m / 1000, + sd / 1000, 100 * sd / stats.m, mb_per_sec(size, stats.m)); + verbose("2-sigma interval: %g..%gus (%g..%gMiB/s)\n", + (stats.m - 2 * sd) / 1000, (stats.m + 2 * sd) / 1000, + mb_per_sec(size, stats.m + 2 * sd), + mb_per_sec(size, stats.m - 2 * sd)); + free_shm(); +} + +static void usage(const char *progname, + /* Default params */ + int algo, size_t size, int warmup, int l, int n) +{ + fprintf(stderr, "Usage: %s [-h]\n", progname); + fprintf(stderr, "Usage: %s [-a ALGO] [-l LOOP] [-n LOOP] [-r] [-s SIZE]", progname); + fprintf(stderr, " [-v [-v]] [-w SEC]\n"); + fprintf(stderr, "Hash performance testing tool for OP-TEE\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -a ALGO Algorithm (SHA1, SHA224, SHA256, SHA384, SHA512, SM3," + " HMAC_SHA1, HMAC_SHA224, HMAC_SHA256," + " HMAC_SHA384, HMAC_SHA512, HMAC_SM3) [%s]\n", algo_str(algo)); + fprintf(stderr, " -h|--help Print this help and exit\n"); + fprintf(stderr, " -l LOOP Inner loop iterations (TA calls TEE_DigestDoFinal() times) [%u]\n", l); + fprintf(stderr, " -n LOOP Outer test loop iterations [%u]\n", n); + fprintf(stderr, " -r|--random Get input data from /dev/urandom (default: all-zeros)\n"); + fprintf(stderr, " -s SIZE Test buffer size in bytes [%zu]\n", size); + fprintf(stderr, " -u|--unalign Use unaligned buffer (odd address)\n"); + fprintf(stderr, " -v Be verbose (use twice for greater effect)\n"); + fprintf(stderr, " -w|--warmup SEC Warm-up time in seconds: execute a busy loop before\n"); + fprintf(stderr, " the test to mitigate the effects of cpufreq etc. [%u]\n", warmup); +} + +#define NEXT_ARG(i) \ + do { \ + if (++i == argc) { \ + fprintf(stderr, "%s: %s: missing argument\n", \ + argv[0], argv[i - 1]); \ + return 1; \ + } \ + } while (0); + +extern int hash_perf_runner_cmd_parser(int argc, char *argv[]) +{ + int i = 0; + /* Command line params */ + size_t size = 1024; /* Buffer size (-s) */ + unsigned int n = CRYPTO_DEF_COUNT;/* Number of measurements (-n)*/ + unsigned int l = CRYPTO_DEF_LOOPS; /* Inner loops (-l) */ + int verbosity = CRYPTO_DEF_VERBOSITY; /* Verbosity (-v) */ + int algo = TA_SHA_SHA1; /* Algorithm (-a) */ + /* Get input data from /dev/urandom (-r) */ + int random_in = CRYPTO_USE_ZEROS; + /* Start with a 2-second busy loop (-w) */ + int warmup = CRYPTO_DEF_WARMUP; + int offset = 0; /* Buffer offset wrt. alloc'ed address (-u) */ + + /* Parse command line */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + usage(argv[0], algo, size, warmup, l, n); + return 0; + } + } + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-l")) { + NEXT_ARG(i); + l = atoi(argv[i]); + } else if (!strcmp(argv[i], "-a")) { + NEXT_ARG(i); + if (!strcasecmp(argv[i], "SHA1")) + algo = TA_SHA_SHA1; + else if (!strcasecmp(argv[i], "SHA224")) + algo = TA_SHA_SHA224; + else if (!strcasecmp(argv[i], "SHA256")) + algo = TA_SHA_SHA256; + else if (!strcasecmp(argv[i], "SHA384")) + algo = TA_SHA_SHA384; + else if (!strcasecmp(argv[i], "SHA512")) + algo = TA_SHA_SHA512; + else if (!strcasecmp(argv[i], "SM3")) + algo = TA_SM3; + else if (!strcasecmp(argv[i], "HMAC_SHA1")) + algo = TA_HMAC_SHA1; + else if (!strcasecmp(argv[i], "HMAC_SHA224")) + algo = TA_HMAC_SHA224; + else if (!strcasecmp(argv[i], "HMAC_SHA256")) + algo = TA_HMAC_SHA256; + else if (!strcasecmp(argv[i], "HMAC_SHA384")) + algo = TA_HMAC_SHA384; + else if (!strcasecmp(argv[i], "HMAC_SHA512")) + algo = TA_HMAC_SHA512; + else if (!strcasecmp(argv[i], "HMAC_SM3")) + algo = TA_HMAC_SM3; + else { + fprintf(stderr, "%s, invalid algorithm\n", + argv[0]); + usage(argv[0], algo, size, warmup, l, n); + return 1; + } + } else if (!strcmp(argv[i], "-n")) { + NEXT_ARG(i); + n = atoi(argv[i]); + } else if (!strcmp(argv[i], "--random") || + !strcmp(argv[i], "-r")) { + random_in = CRYPTO_USE_RANDOM; + } else if (!strcmp(argv[i], "-s")) { + NEXT_ARG(i); + size = atoi(argv[i]); + } else if (!strcmp(argv[i], "--unalign") || + !strcmp(argv[i], "-u")) { + offset = 1; + } else if (!strcmp(argv[i], "-v")) { + verbosity++; + } else if (!strcmp(argv[i], "--warmup") || + !strcmp(argv[i], "-w")) { + NEXT_ARG(i); + warmup = atoi(argv[i]); + } else { + fprintf(stderr, "%s: invalid argument: %s\n", + argv[0], argv[i]); + usage(argv[0], algo, size, warmup, l, n); + return 1; + } + } + + hash_perf_run_test(algo, size, n, l, random_in, offset, warmup, verbosity); + + return 0; +} diff --git a/optee/optee_test/host/xtest/include/uapi/linux/arm_ffa_user.h b/optee/optee_test/host/xtest/include/uapi/linux/arm_ffa_user.h new file mode 100644 index 0000000..0acde4f --- /dev/null +++ b/optee/optee_test/host/xtest/include/uapi/linux/arm_ffa_user.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020-2022, Arm Limited + */ + +#ifndef __ARM_FFA_USER_H +#define __ARM_FFA_USER_H + +#include +#include + +#define FFA_IOC_MAGIC 0xf0 +#define FFA_IOC_BASE 0 + +/** + * struct ffa_ioctl_ep_desc - Query endpoint ID + * @uuid_ptr: [in] Pointer to queried UUID. Format must be an RFC 4122 string, + * i.e. "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee". + * @id: [out] 16-bit ID of endpoint. + */ +struct ffa_ioctl_ep_desc { + __u64 uuid_ptr; + __u16 id; +}; +#define FFA_IOC_GET_PART_ID _IOWR(FFA_IOC_MAGIC, FFA_IOC_BASE + 0, \ + struct ffa_ioctl_ep_desc) + +/** + * struct ffa_ioctl_msg_args - Send direct message request + * @args: [in/out] Arguments of FFA_MSG_SEND_DIRECT_REQ (w3-w7). If the + * response is FFA_MSG_SEND_DIRECT_RESP, the received arguments are + * returned in this field. + * @dst_id: [in] 16-bit ID of destination endpoint. + */ +struct ffa_ioctl_msg_args { + __u64 args[5]; + __u16 dst_id; +}; +#define FFA_IOC_MSG_SEND _IOWR(FFA_IOC_MAGIC, FFA_IOC_BASE + 1, \ + struct ffa_ioctl_msg_args) + +/** + * struct ffa_ioctl_shm_desc - Share/reclaim memory region + * @handle: [in/out] Handle assigned by the SPM. Output when used with + * FFA_IOC_SHM_INIT, input when used with FFA_IOC_SHM_DEINIT. + * @size: [in/out] In: the required size of region in bytes. Out: the + * actual region size allocated by the kernel. Unused on reclaim. + * @dst_id: [in] 16-bit ID of destination endpoint. Unused on reclaim. + */ +struct ffa_ioctl_shm_desc { + __u64 handle; + __u64 size; + __u16 dst_id; +}; +#define FFA_IOC_SHM_INIT _IOWR(FFA_IOC_MAGIC, FFA_IOC_BASE + 2, \ + struct ffa_ioctl_shm_desc) + +#define FFA_IOC_SHM_DEINIT _IOW(FFA_IOC_MAGIC, FFA_IOC_BASE + 3, \ + struct ffa_ioctl_shm_desc) + +/** + * struct ffa_ioctl_buf_desc - Read/write shared memory region + * @handle: [in] Handle of the memory region. + * @buf_ptr: [in] Pointer to user space buffer. Data is copied from/to this + * buffer to/from the memory region shared with the given endpoint. + * @buf_len: [in] Length of read/write in bytes. + */ +struct ffa_ioctl_buf_desc { + __u64 handle; + __u64 buf_ptr; + __u64 buf_len; +}; +#define FFA_IOC_SHM_READ _IOW(FFA_IOC_MAGIC, FFA_IOC_BASE + 4, \ + struct ffa_ioctl_buf_desc) + +#define FFA_IOC_SHM_WRITE _IOW(FFA_IOC_MAGIC, FFA_IOC_BASE + 5, \ + struct ffa_ioctl_buf_desc) + +#endif /* __ARM_FFA_USER_H */ diff --git a/optee/optee_test/host/xtest/install_ta.c b/optee/optee_test/host/xtest/install_ta.c new file mode 100644 index 0000000..431981d --- /dev/null +++ b/optee/optee_test/host/xtest/install_ta.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017, Linaro Limited + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "install_ta.h" +#include "xtest_helpers.h" +#include "xtest_test.h" + +static void *read_ta(const char *dname, const char *fname, size_t *size) +{ + char nbuf[PATH_MAX]; + FILE *f = NULL; + void *buf = NULL; + size_t s = 0; + + if (dname) + snprintf(nbuf, sizeof(nbuf), "%s/%s", dname, fname); + else + snprintf(nbuf, sizeof(nbuf), "%s", fname); + + f = fopen(nbuf, "rb"); + if (!f) + err(1, "fopen(\"%s\")", nbuf); + + if (fseek(f, 0, SEEK_END)) + err(1, "fseek"); + + s = ftell(f); + rewind(f); + + buf = malloc(s); + if (!buf) + err(1, "malloc(%zu)", s); + + if (fread(buf, 1, s, f) != s) + err(1, "fread"); + + *size = s; + return buf; +} + +static void install_ta(TEEC_Session *sess, void *buf, size_t blen) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t err_origin = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + op.params[0].tmpref.buffer = buf; + op.params[0].tmpref.size = blen; + + res = TEEC_InvokeCommand(sess, PTA_SECSTOR_TA_MGMT_BOOTSTRAP, &op, + &err_origin); + if (res) + errx(1, "install_ta: TEEC_InvokeCommand: %#" PRIx32 + " err_origin %#" PRIx32, res, err_origin); +} + +static void install_file(TEEC_Session *sess, const char *dirname, + const char *filename) +{ + void *ta = NULL; + size_t ta_size = 0; + + printf("Installing \"%s\"\n", filename); + ta = read_ta(dirname, filename, &ta_size); + install_ta(sess, ta, ta_size); + free(ta); +} + +static void install_dir(TEEC_Session *sess, const char *dirname) +{ + DIR *dirp = NULL; + + printf("Searching directory \"%s\" for TAs\n", dirname); + dirp = opendir(dirname); + if (!dirp) + err(1, "opendir(\"%s\")", dirname); + + while (true) { + struct dirent *dent = readdir(dirp); + + if (!dent) + break; + + if (fnmatch("*.ta", dent->d_name, 0)) + continue; + + install_file(sess, dirname, dent->d_name); + } + + closedir(dirp); +} + +int install_ta_runner_cmd_parser(int argc, char *argv[]) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t err_origin = 0; + TEEC_UUID uuid = PTA_SECSTOR_TA_MGMT_UUID; + TEEC_Context ctx = { }; + TEEC_Session sess = { }; + int i = 0; + + res = TEEC_InitializeContext(NULL, &ctx); + if (res) + errx(1, "TEEC_InitializeContext: %#" PRIx32, res); + + res = TEEC_OpenSession(&ctx, &sess, &uuid, TEEC_LOGIN_PUBLIC, NULL, + NULL, &err_origin); + if (res) + errx(1, "TEEC_OpenSession: res %#" PRIx32 " err_orig %#" PRIx32, + res, err_origin); + + for (i = 1; i < argc; i++) { + struct stat sb = { }; + + if (stat(argv[i], &sb)) { + printf("Skipping \"%s\": %s", argv[i], strerror(errno)); + continue; + } + + if (S_ISDIR(sb.st_mode)) + install_dir(&sess, argv[i]); + else if (S_ISREG(sb.st_mode)) + install_file(&sess, NULL, argv[i]); + else + printf("Skipping unknown file type \"%s\", mode 0%o", + argv[i], sb.st_mode); + } + + TEEC_CloseSession(&sess); + TEEC_FinalizeContext(&ctx); + + printf("Installing TAs done\n"); + + return 0; +} diff --git a/optee/optee_test/host/xtest/install_ta.h b/optee/optee_test/host/xtest/install_ta.h new file mode 100644 index 0000000..62ab89c --- /dev/null +++ b/optee/optee_test/host/xtest/install_ta.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, Linaro Limited + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef INSTALL_TA_H +#define INSTALL_TA_H + +int install_ta_runner_cmd_parser(int argc, char *argv[]); + +#endif /*INSTALL_TA_H*/ diff --git a/optee/optee_test/host/xtest/nist/186-2ecdsatestvectors.h b/optee/optee_test/host/xtest/nist/186-2ecdsatestvectors.h new file mode 100644 index 0000000..290bf40 --- /dev/null +++ b/optee/optee_test/host/xtest/nist/186-2ecdsatestvectors.h @@ -0,0 +1,10518 @@ +/* + * Automatically generated from NIST-186-2ecdsatestvectors-SigGen.txt + */ +/* [P-192] */ +static const uint8_t nist_186_2_ecdsa_testvector_1_ptx[] = { +/* Msg */ + 0x66, 0xe9, 0x8a, 0x16, 0x58, 0x54, 0xcd, 0x07, 0x98, 0x9b, 0x1e, 0xe0, + 0xec, 0x3f, 0x8d, 0xbe, 0x0e, 0xe3, 0xc2, 0xfb, 0x00, 0x51, 0xef, 0x53, + 0xa0, 0xbe, 0x03, 0x45, 0x7c, 0x4f, 0x21, 0xbc, 0xe7, 0xdc, 0x50, 0xef, + 0x4d, 0xf3, 0x74, 0x86, 0xc3, 0x20, 0x7d, 0xfe, 0xe2, 0x6b, 0xde, 0x4e, + 0xd6, 0x23, 0x40, 0xcb, 0xb2, 0xda, 0x78, 0x49, 0x06, 0xb1, 0xb7, 0x83, + 0xb4, 0xd6, 0x01, 0xbd, 0xff, 0x4a, 0xe1, 0xa7, 0xe5, 0xe8, 0x5a, 0x85, + 0xaf, 0xa3, 0x20, 0x8d, 0xc6, 0x0f, 0x09, 0x90, 0xc8, 0x23, 0xbe, 0xdd, + 0xdb, 0x3d, 0xb6, 0x63, 0x42, 0x66, 0x65, 0x15, 0x2e, 0xd7, 0xb0, 0x93, + 0xd6, 0xbd, 0xa5, 0x06, 0xc9, 0x3a, 0x69, 0x4b, 0x83, 0xac, 0x71, 0x55, + 0x3f, 0x31, 0xf5, 0xcc, 0x0d, 0x6b, 0xa2, 0xfa, 0x24, 0x80, 0x90, 0xe8, + 0x79, 0x65, 0x73, 0xc4, 0x91, 0x5d, 0x15, 0x86 +}; +static const uint8_t nist_186_2_ecdsa_testvector_1_private[] = { +/* d */ + 0x00, 0x17, 0x89, 0x99, 0x49, 0xd0, 0x2b, 0x55, 0xf9, 0x55, 0x68, 0x46, + 0x41, 0x1c, 0xc9, 0xde, 0x51, 0x2c, 0x6f, 0x16, 0xec, 0xde, 0xb1, 0xc4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_1_public_x[] = { +/* Qx */ + 0x14, 0xf6, 0x97, 0x38, 0x59, 0x96, 0x89, 0xf5, 0x70, 0x6a, 0xb7, 0x13, + 0x43, 0xbe, 0xcc, 0x88, 0x6e, 0xf1, 0x56, 0x9a, 0x2d, 0x11, 0x37, 0xfe +}; +static const uint8_t nist_186_2_ecdsa_testvector_1_public_y[] = { +/* Qy */ + 0x0c, 0xf5, 0xa4, 0x33, 0x90, 0x9e, 0x33, 0x21, 0x7f, 0xb4, 0xdf, 0x6b, + 0x95, 0x93, 0xf7, 0x1d, 0x43, 0xfb, 0x1c, 0x2a, 0x56, 0x53, 0xb7, 0x63 +}; +/* k = 0098e9c07e8e6adb97b77d85b0c10a265e11737a89a3e37b */ +static const uint8_t nist_186_2_ecdsa_testvector_1_out[] = { +/* R */ + 0xaf, 0x1f, 0x74, 0x9e, 0x3d, 0xf6, 0x22, 0x0f, 0xf0, 0x4e, 0xfd, 0x17, + 0x86, 0x18, 0xa9, 0x77, 0xe0, 0x83, 0x8b, 0x1b, 0x9d, 0xc1, 0x26, 0xe3, +/* S */ + 0x89, 0x90, 0xa0, 0x4c, 0x6c, 0xc0, 0xff, 0x26, 0x26, 0x4e, 0xcf, 0x8f, + 0x78, 0x31, 0x38, 0x1a, 0x9d, 0xbc, 0x6e, 0x53, 0xcc, 0x8c, 0xc8, 0x60 +}; +static const uint8_t nist_186_2_ecdsa_testvector_2_ptx[] = { +/* Msg */ + 0xd3, 0x9a, 0xd5, 0x61, 0x35, 0xbe, 0xc4, 0xc3, 0xc4, 0x36, 0x2d, 0x59, + 0xd3, 0xd9, 0x17, 0x5a, 0xcb, 0x38, 0x66, 0x70, 0xc5, 0xdb, 0x0a, 0x17, + 0x57, 0xce, 0x76, 0x46, 0xad, 0x5d, 0x53, 0x52, 0xdc, 0x1b, 0x76, 0x0f, + 0x74, 0x29, 0x10, 0x38, 0x54, 0xb4, 0x25, 0x11, 0xc3, 0xc0, 0x40, 0x4a, + 0xbc, 0x24, 0x64, 0x27, 0x88, 0xd6, 0x45, 0xde, 0x93, 0x69, 0xb8, 0x41, + 0x78, 0xd4, 0x69, 0x9c, 0x5e, 0x75, 0xcc, 0xe1, 0x87, 0x56, 0x56, 0x02, + 0x26, 0xae, 0xec, 0x9f, 0x71, 0xab, 0x9c, 0xe1, 0xf8, 0x6e, 0x8b, 0xa6, + 0x35, 0x58, 0x2e, 0xde, 0x64, 0x84, 0xbd, 0x34, 0x95, 0x94, 0xe5, 0xf2, + 0xff, 0xb1, 0xbe, 0x1e, 0x97, 0xcd, 0xfc, 0xe9, 0xe1, 0x2b, 0x69, 0x4b, + 0x06, 0x22, 0x93, 0xe7, 0x28, 0x1e, 0xc1, 0x34, 0xf2, 0xe7, 0x2c, 0xde, + 0x73, 0x26, 0x6c, 0x6a, 0x2c, 0x25, 0x31, 0x1a +}; +static const uint8_t nist_186_2_ecdsa_testvector_2_private[] = { +/* d */ + 0x00, 0x64, 0xc3, 0xa5, 0x1f, 0xb6, 0x18, 0x81, 0x70, 0xf3, 0xcd, 0xf1, + 0x2b, 0x47, 0x4a, 0x77, 0xde, 0x4a, 0xe0, 0x05, 0x2b, 0x84, 0xec, 0xe8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_2_public_x[] = { +/* Qx */ + 0x38, 0x6a, 0xfa, 0x71, 0xaf, 0xc0, 0x65, 0x01, 0x9f, 0x3d, 0x20, 0x21, + 0xea, 0xd5, 0x31, 0xed, 0x1d, 0x36, 0x58, 0x87, 0x12, 0x2d, 0x2d, 0x4b +}; +static const uint8_t nist_186_2_ecdsa_testvector_2_public_y[] = { +/* Qy */ + 0xbb, 0xfb, 0x6e, 0x9c, 0xdb, 0x32, 0xc2, 0x25, 0x20, 0x15, 0xac, 0xfb, + 0x4c, 0xfb, 0x04, 0x9b, 0x08, 0xb4, 0xcb, 0x27, 0x9c, 0x64, 0x92, 0x8a +}; +/* k = 00797552b9abf541c886f93556103b817a46c9aa0e2bc86f */ +static const uint8_t nist_186_2_ecdsa_testvector_2_out[] = { +/* R */ + 0x33, 0x7b, 0xe4, 0x2e, 0xeb, 0xdc, 0xed, 0xd9, 0x76, 0x78, 0xee, 0xaa, + 0xe9, 0xd1, 0xb2, 0x31, 0xb7, 0x40, 0xa1, 0x91, 0xa2, 0x93, 0xc2, 0x2a, +/* S */ + 0x9d, 0x67, 0x66, 0xb3, 0x91, 0xe9, 0x5f, 0x64, 0x9e, 0x05, 0x44, 0x24, + 0x53, 0xa8, 0x54, 0x66, 0xda, 0x29, 0xea, 0xa9, 0x7d, 0xdc, 0xfc, 0x62 +}; +static const uint8_t nist_186_2_ecdsa_testvector_3_ptx[] = { +/* Msg */ + 0x47, 0x71, 0x01, 0xda, 0xa2, 0x82, 0xa5, 0xa5, 0x5b, 0x48, 0xc5, 0x31, + 0x32, 0x90, 0xc8, 0xda, 0x65, 0xb0, 0x7c, 0xc4, 0xd4, 0x1a, 0x5a, 0x14, + 0x63, 0x30, 0x0c, 0x60, 0xa0, 0x5a, 0x2c, 0x63, 0xa6, 0x56, 0x4f, 0xf6, + 0x41, 0xd0, 0x42, 0x3c, 0x52, 0x33, 0x93, 0x1c, 0x75, 0xbe, 0x53, 0xf4, + 0xe2, 0xda, 0x1b, 0x8b, 0x91, 0xab, 0x4d, 0x48, 0xa2, 0xe5, 0x9c, 0xa2, + 0xfb, 0xe1, 0xcf, 0xd8, 0x33, 0xf0, 0xc1, 0xe2, 0xaf, 0xef, 0xad, 0xa7, + 0x0a, 0x1b, 0xa8, 0x70, 0xba, 0x27, 0x6f, 0x9d, 0xf1, 0x8c, 0x63, 0x97, + 0xc2, 0x21, 0xd2, 0x05, 0x85, 0xeb, 0x78, 0x43, 0x7c, 0x36, 0x46, 0x0f, + 0xb7, 0xe4, 0x62, 0x86, 0x34, 0x06, 0x6e, 0x50, 0x4b, 0xa9, 0x0d, 0x17, + 0x49, 0xf2, 0xa3, 0x3d, 0x5c, 0x6e, 0x5d, 0xce, 0xaf, 0xa3, 0x72, 0xb3, + 0xd5, 0xeb, 0xa8, 0x29, 0x6b, 0x82, 0x19, 0x72 +}; +static const uint8_t nist_186_2_ecdsa_testvector_3_private[] = { +/* d */ + 0x00, 0xab, 0xd2, 0x05, 0xef, 0x41, 0x26, 0x46, 0x90, 0x7d, 0x2e, 0x48, + 0x86, 0xb8, 0xff, 0xd7, 0xd9, 0x46, 0x78, 0xbd, 0x38, 0x18, 0xed, 0x54 +}; +static const uint8_t nist_186_2_ecdsa_testvector_3_public_x[] = { +/* Qx */ + 0x3b, 0x1c, 0x19, 0xd7, 0x3b, 0x6a, 0x4d, 0x7a, 0x12, 0x00, 0x35, 0x30, + 0xa5, 0x4a, 0xe0, 0xf5, 0xba, 0x18, 0xd7, 0x5c, 0x98, 0xa0, 0xdb, 0x95 +}; +static const uint8_t nist_186_2_ecdsa_testvector_3_public_y[] = { +/* Qy */ + 0xaf, 0xb8, 0xbd, 0x8c, 0x94, 0xc6, 0xe3, 0xd5, 0xdc, 0x05, 0x0e, 0x36, + 0x41, 0xc0, 0xfa, 0xd7, 0x71, 0x55, 0x7c, 0xe9, 0x7f, 0x5f, 0x3d, 0xba +}; +/* k = 00b81567f9e19c4ace373a26337488c1a476b7ee8d8e52bf */ +static const uint8_t nist_186_2_ecdsa_testvector_3_out[] = { +/* R */ + 0xe3, 0x6d, 0x5d, 0xbb, 0x95, 0x60, 0xd9, 0x59, 0x81, 0x4c, 0xbd, 0x30, + 0xaa, 0x6a, 0x40, 0x5d, 0xa9, 0x65, 0x2f, 0xbd, 0x25, 0x0d, 0xa9, 0xab, +/* S */ + 0xf2, 0xdb, 0x3d, 0x62, 0x73, 0x3f, 0x6d, 0x08, 0xb0, 0x8e, 0xf0, 0x68, + 0x2f, 0x57, 0x9a, 0xc5, 0x27, 0x95, 0x01, 0x17, 0xf3, 0x9e, 0x47, 0x4b +}; +static const uint8_t nist_186_2_ecdsa_testvector_4_ptx[] = { +/* Msg */ + 0x85, 0xbc, 0xd4, 0x06, 0xf4, 0xcd, 0xc8, 0xf3, 0x0e, 0x19, 0x55, 0x3b, + 0xa9, 0x2f, 0x9c, 0x08, 0x94, 0xb2, 0x83, 0x3d, 0x7b, 0xb0, 0xb5, 0x65, + 0x0a, 0x30, 0xeb, 0xe8, 0x55, 0x0a, 0x69, 0x85, 0x78, 0xfc, 0xcb, 0xfc, + 0x7a, 0xf9, 0x01, 0x0b, 0x78, 0xc4, 0x99, 0x9c, 0xff, 0xbe, 0x3c, 0x3d, + 0xb9, 0xfd, 0x7c, 0xd0, 0x4c, 0x9d, 0xcd, 0x84, 0x7f, 0x5b, 0xd0, 0x04, + 0x9f, 0x5f, 0xd8, 0xee, 0x21, 0x5a, 0xa7, 0x86, 0x88, 0xd1, 0x78, 0xac, + 0x89, 0xb9, 0x43, 0x0b, 0x6d, 0x43, 0x3c, 0x94, 0xb8, 0xf9, 0x9c, 0x2b, + 0x08, 0x0a, 0xa5, 0x9f, 0x3f, 0xe2, 0xe0, 0xe0, 0xe4, 0xfe, 0xaa, 0x6c, + 0xc7, 0xff, 0xee, 0x0b, 0xe4, 0xfd, 0x34, 0xbc, 0x8a, 0x1d, 0xdb, 0xef, + 0xbd, 0x66, 0xa2, 0xf4, 0xd8, 0xd0, 0x6e, 0xb4, 0x77, 0x9e, 0x47, 0x9f, + 0x93, 0xee, 0xa3, 0xe5, 0xef, 0x8f, 0xe7, 0xe9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_4_private[] = { +/* d */ + 0x00, 0x45, 0x62, 0x4e, 0x64, 0x35, 0x45, 0xc1, 0x13, 0xe4, 0xa1, 0x99, + 0x3c, 0xfa, 0xc6, 0xf2, 0x3c, 0x6e, 0x04, 0x86, 0xc9, 0x8e, 0x14, 0xc9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_4_public_x[] = { +/* Qx */ + 0x21, 0x93, 0x3e, 0x6e, 0x8c, 0xdc, 0xff, 0xf6, 0x2f, 0x36, 0xc4, 0x5e, + 0x83, 0xde, 0xce, 0x12, 0x80, 0xa8, 0x88, 0x66, 0x3a, 0x34, 0x60, 0x8f +}; +static const uint8_t nist_186_2_ecdsa_testvector_4_public_y[] = { +/* Qy */ + 0x56, 0x58, 0x90, 0xe3, 0x7f, 0xdf, 0x56, 0x35, 0x95, 0xd2, 0x45, 0x24, + 0xef, 0x1d, 0xa9, 0xaa, 0xe2, 0x46, 0x89, 0x2e, 0x75, 0xa7, 0x42, 0x34 +}; +/* k = 008df8209daae53a365bdcc8608f597315d43f587859d96a */ +static const uint8_t nist_186_2_ecdsa_testvector_4_out[] = { +/* R */ + 0x17, 0x91, 0xe5, 0x03, 0x64, 0x5e, 0x53, 0xa8, 0x30, 0x4f, 0x2a, 0x44, + 0x71, 0x59, 0x42, 0xc6, 0xaa, 0xb3, 0x15, 0xb0, 0x08, 0x6f, 0x41, 0x47, +/* S */ + 0x36, 0x63, 0x09, 0xb7, 0xf7, 0x9b, 0x2f, 0xd9, 0x8d, 0x6c, 0x2f, 0x3a, + 0x84, 0x24, 0x17, 0x8b, 0x01, 0x23, 0x50, 0x41, 0xf9, 0x86, 0x95, 0x52 +}; +static const uint8_t nist_186_2_ecdsa_testvector_5_ptx[] = { +/* Msg */ + 0xc8, 0x88, 0x8d, 0xdf, 0x35, 0xfb, 0x43, 0xd2, 0x62, 0xa5, 0xf4, 0xee, + 0xbe, 0xc7, 0x31, 0x95, 0xf0, 0xfa, 0x79, 0x57, 0x1b, 0x68, 0xa3, 0xc3, + 0x61, 0x3b, 0x7b, 0x7c, 0xa6, 0x56, 0xb0, 0x90, 0x96, 0x43, 0xee, 0x06, + 0xe9, 0x6d, 0x47, 0xb6, 0xe5, 0x90, 0xd7, 0x5e, 0x25, 0x6d, 0xa8, 0xf1, + 0x9a, 0xc2, 0xd3, 0x32, 0xcf, 0x79, 0xe8, 0x82, 0x71, 0x20, 0x90, 0xf6, + 0x0e, 0x99, 0x71, 0xad, 0x1d, 0x13, 0x52, 0x61, 0x3f, 0x39, 0x80, 0x3b, + 0xc4, 0xa8, 0x70, 0xec, 0x71, 0xa7, 0xa5, 0xf9, 0x80, 0x12, 0xd4, 0x56, + 0xe9, 0x98, 0x47, 0x37, 0xe0, 0x27, 0x7f, 0x23, 0x9f, 0xa3, 0x1d, 0x4a, + 0x65, 0xde, 0x03, 0x18, 0xbf, 0xc5, 0xb6, 0x0a, 0x06, 0xd7, 0x06, 0xc1, + 0x29, 0xdc, 0xf2, 0x55, 0xac, 0xd3, 0xc6, 0xeb, 0xf1, 0x2c, 0x86, 0x8a, + 0xb7, 0x37, 0x8f, 0x2a, 0xe0, 0xdd, 0x7c, 0x0e +}; +static const uint8_t nist_186_2_ecdsa_testvector_5_private[] = { +/* d */ + 0x00, 0xca, 0x3e, 0x5b, 0x5d, 0x69, 0xcf, 0x02, 0x8c, 0x9f, 0xf1, 0x38, + 0xb1, 0xee, 0x5c, 0x28, 0x60, 0x7a, 0x6b, 0xf9, 0x35, 0x2c, 0x64, 0x30 +}; +static const uint8_t nist_186_2_ecdsa_testvector_5_public_x[] = { +/* Qx */ + 0x48, 0x28, 0xad, 0x4a, 0xff, 0x5d, 0x87, 0xdc, 0xca, 0x98, 0xa3, 0x41, + 0x34, 0x4a, 0x46, 0x2e, 0xdf, 0x27, 0x78, 0x50, 0x75, 0x5c, 0x72, 0x77 +}; +static const uint8_t nist_186_2_ecdsa_testvector_5_public_y[] = { +/* Qy */ + 0x8a, 0x1b, 0xfc, 0x6b, 0x7b, 0x04, 0x24, 0xe1, 0x54, 0x54, 0xac, 0x19, + 0x8d, 0x4d, 0x69, 0x79, 0x27, 0xf4, 0xea, 0xaf, 0x9d, 0x14, 0xd8, 0x8e +}; +/* k = 00964e4a3eac4d2641c2a5c4badd301da54962410a459654 */ +static const uint8_t nist_186_2_ecdsa_testvector_5_out[] = { +/* R */ + 0xc4, 0x38, 0xca, 0x66, 0xc5, 0xd3, 0xb1, 0x9e, 0x2b, 0xcd, 0x26, 0xa5, + 0xc5, 0x47, 0x42, 0x43, 0x5f, 0x25, 0xee, 0x0e, 0x93, 0x64, 0xb4, 0x1c, +/* S */ + 0xff, 0x19, 0x44, 0x79, 0x69, 0x5a, 0xfd, 0xcc, 0x88, 0x64, 0x5f, 0x2a, + 0x30, 0x9c, 0xb9, 0x97, 0x17, 0xbe, 0xac, 0x26, 0x79, 0x4c, 0x06, 0x58 +}; +static const uint8_t nist_186_2_ecdsa_testvector_6_ptx[] = { +/* Msg */ + 0x63, 0x7a, 0xc6, 0x1c, 0x9a, 0x10, 0x8a, 0x77, 0xd1, 0xd3, 0x4f, 0x42, + 0x67, 0x6f, 0x9d, 0x31, 0x4b, 0xed, 0xeb, 0x32, 0xc9, 0x34, 0x12, 0x08, + 0xa3, 0xcf, 0x02, 0x35, 0x64, 0xf0, 0xb4, 0x1e, 0xf1, 0xb5, 0x60, 0x6a, + 0x61, 0xab, 0xef, 0xab, 0x0e, 0x91, 0xb3, 0x40, 0xec, 0x5e, 0x56, 0x7a, + 0x1a, 0x85, 0x10, 0xfd, 0xb7, 0x77, 0x1d, 0x69, 0xf7, 0x69, 0x6f, 0x3a, + 0x76, 0x58, 0xa0, 0xed, 0xcc, 0x4b, 0x2a, 0x65, 0x61, 0xd9, 0xda, 0x8c, + 0x83, 0xea, 0x82, 0x3d, 0xb5, 0xc2, 0xef, 0x62, 0x4a, 0x3b, 0x1a, 0x59, + 0x33, 0x51, 0xa2, 0x9d, 0x16, 0xe4, 0x7a, 0xa2, 0xa0, 0xba, 0xdf, 0x00, + 0x1b, 0xc4, 0x8e, 0xd4, 0x43, 0xa2, 0x33, 0x63, 0x55, 0x68, 0x24, 0x01, + 0x6a, 0xa3, 0x4f, 0x32, 0x03, 0x97, 0x72, 0x0e, 0xe5, 0xcb, 0x8a, 0xea, + 0x27, 0xc8, 0x8d, 0x34, 0x89, 0x1d, 0x5b, 0x9f +}; +static const uint8_t nist_186_2_ecdsa_testvector_6_private[] = { +/* d */ + 0x00, 0x55, 0xac, 0xe6, 0x7d, 0xf2, 0xb1, 0x7f, 0x6e, 0x9e, 0x1b, 0x89, + 0x28, 0xac, 0x85, 0x6c, 0xe8, 0xd7, 0x5f, 0x6b, 0xba, 0xaa, 0xed, 0x83 +}; +static const uint8_t nist_186_2_ecdsa_testvector_6_public_x[] = { +/* Qx */ + 0x2f, 0x5d, 0x05, 0xcb, 0xd6, 0x20, 0x14, 0x5b, 0x41, 0xd0, 0xa1, 0xc6, + 0x56, 0xd6, 0x76, 0xea, 0xd2, 0xfc, 0x65, 0x1b, 0x3c, 0xf7, 0x1c, 0xc2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_6_public_y[] = { +/* Qy */ + 0x88, 0xd2, 0x38, 0x6c, 0xfb, 0x81, 0x2d, 0x02, 0xa1, 0xfa, 0x19, 0x57, + 0x8a, 0x7c, 0xd0, 0x4b, 0x35, 0x69, 0x20, 0xa2, 0xb2, 0xe6, 0x98, 0x39 +}; +/* k = 006ed729e5c2ec9bac7ddfbfe04ea9444c2c77f71455f623 */ +static const uint8_t nist_186_2_ecdsa_testvector_6_out[] = { +/* R */ + 0xcd, 0xe9, 0x5d, 0x12, 0xd6, 0x50, 0x10, 0x2c, 0x53, 0x5f, 0xdc, 0x19, + 0x94, 0xfc, 0x46, 0x83, 0x08, 0xb0, 0x5e, 0x2a, 0xf7, 0xaf, 0x9c, 0x14, +/* S */ + 0xc2, 0x60, 0x6a, 0x54, 0xe7, 0x59, 0x22, 0x14, 0xa2, 0x65, 0x27, 0x09, + 0x18, 0x32, 0x2a, 0xe3, 0x3d, 0x48, 0x72, 0x68, 0xb9, 0x10, 0x8c, 0xae +}; +static const uint8_t nist_186_2_ecdsa_testvector_7_ptx[] = { +/* Msg */ + 0xd1, 0x54, 0x75, 0x48, 0x99, 0xfc, 0xbf, 0xe2, 0xa4, 0x8e, 0x2c, 0x70, + 0xbc, 0x40, 0x6c, 0xf2, 0xb1, 0x30, 0x70, 0xa5, 0x9d, 0x9e, 0xce, 0xd4, + 0x6c, 0x58, 0x68, 0xf1, 0x9c, 0x75, 0x49, 0xe4, 0x42, 0x46, 0xcf, 0xa3, + 0x4e, 0x8a, 0x0f, 0x03, 0x0f, 0xe1, 0x75, 0xce, 0xfa, 0x84, 0xab, 0x15, + 0xa7, 0x32, 0xbc, 0xc7, 0x1c, 0x6e, 0x7a, 0x83, 0x4e, 0xe7, 0x1d, 0xab, + 0xe5, 0x38, 0x2c, 0xba, 0x40, 0xd1, 0xa1, 0xd7, 0xb9, 0x35, 0x48, 0xaa, + 0x2a, 0x67, 0x68, 0x6e, 0xb0, 0x9e, 0xa5, 0x47, 0xae, 0x40, 0x25, 0xd6, + 0x15, 0x0e, 0xf2, 0x0b, 0xe3, 0x9c, 0x9f, 0x3b, 0xea, 0x05, 0x2f, 0x73, + 0xd3, 0xdc, 0x32, 0x0b, 0x62, 0x66, 0x31, 0x7e, 0xfc, 0x06, 0x4c, 0x79, + 0x66, 0xf8, 0x22, 0x31, 0xcf, 0x42, 0xf1, 0xfa, 0x11, 0xe8, 0xfe, 0x16, + 0x34, 0x60, 0x38, 0xca, 0x33, 0x45, 0x18, 0xb7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_7_private[] = { +/* d */ + 0x00, 0xd1, 0x85, 0xd5, 0x1f, 0x87, 0x7d, 0x3f, 0xcc, 0x65, 0x7d, 0x18, + 0xf3, 0x0c, 0xd1, 0x45, 0x70, 0x02, 0x2d, 0x07, 0x26, 0xc0, 0xb1, 0x88 +}; +static const uint8_t nist_186_2_ecdsa_testvector_7_public_x[] = { +/* Qx */ + 0x47, 0xe8, 0xec, 0x5e, 0x1e, 0xdb, 0x1d, 0x23, 0xc0, 0x4e, 0xbf, 0xee, + 0xfd, 0x8c, 0xb8, 0xbf, 0x39, 0xcd, 0x48, 0xc3, 0x48, 0xde, 0x3e, 0xa7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_7_public_y[] = { +/* Qy */ + 0xb1, 0x16, 0x7b, 0x3a, 0x4e, 0x2f, 0xbe, 0x16, 0x7b, 0xbd, 0x7b, 0x7b, + 0x06, 0xbf, 0x13, 0x14, 0xd5, 0x8d, 0x9e, 0x39, 0x76, 0xff, 0xa4, 0x7f +}; +/* k = 00124c96b0dd589501ba7d5ddfe9c412cf574be10198899b */ +static const uint8_t nist_186_2_ecdsa_testvector_7_out[] = { +/* R */ + 0x53, 0x9e, 0x28, 0x53, 0x89, 0x39, 0x9c, 0x78, 0x5d, 0xfc, 0x4f, 0x3b, + 0xfc, 0xcb, 0xc8, 0x25, 0x60, 0x2f, 0x44, 0x3a, 0xe0, 0xdc, 0xa3, 0xd1, +/* S */ + 0xed, 0x56, 0xe5, 0x4f, 0xba, 0xa0, 0xb7, 0xc0, 0xbc, 0x46, 0x29, 0x20, + 0x31, 0x40, 0x31, 0xc7, 0xa3, 0xe7, 0xb2, 0xeb, 0x70, 0x1c, 0xb9, 0xdb +}; +static const uint8_t nist_186_2_ecdsa_testvector_8_ptx[] = { +/* Msg */ + 0x26, 0x4b, 0xe3, 0x73, 0x69, 0x84, 0x6f, 0x67, 0x01, 0x9f, 0xb3, 0x1f, + 0x94, 0xfc, 0x9e, 0x9a, 0xb0, 0x3c, 0x5c, 0x24, 0x05, 0xa6, 0x2a, 0xd8, + 0xd1, 0xc9, 0x68, 0x64, 0x9b, 0x63, 0xef, 0x0c, 0x24, 0x82, 0xa6, 0xf2, + 0x9b, 0xe9, 0x50, 0x94, 0x10, 0xb5, 0xa8, 0x96, 0x2b, 0x41, 0xb0, 0xc2, + 0x1e, 0x46, 0x46, 0x4d, 0xd8, 0x47, 0xf8, 0x5b, 0x7b, 0x2c, 0x19, 0xc6, + 0x11, 0x2d, 0x14, 0x1b, 0x7b, 0xf1, 0x01, 0xe6, 0xa9, 0xf7, 0x76, 0x30, + 0x11, 0x36, 0xa0, 0x45, 0x59, 0x00, 0x92, 0xbb, 0x57, 0x2c, 0xdc, 0xaf, + 0x3c, 0x74, 0x60, 0x52, 0x0c, 0x1c, 0x61, 0xa5, 0x52, 0xd5, 0xdd, 0x80, + 0x11, 0xe0, 0x1d, 0xd9, 0xfd, 0x76, 0x8a, 0x43, 0xeb, 0x68, 0xc2, 0xb5, + 0x87, 0x03, 0xeb, 0x8d, 0x45, 0x36, 0x48, 0xd4, 0x9a, 0xf7, 0x09, 0xc4, + 0x6b, 0xe2, 0x68, 0x87, 0xc6, 0x23, 0xf1, 0x42 +}; +static const uint8_t nist_186_2_ecdsa_testvector_8_private[] = { +/* d */ + 0x00, 0x7d, 0x6f, 0xa0, 0xb3, 0xda, 0xca, 0xf0, 0x22, 0x43, 0x67, 0x77, + 0xac, 0x53, 0xc4, 0x43, 0x7c, 0x95, 0x79, 0x47, 0xc9, 0x11, 0xfa, 0xab +}; +static const uint8_t nist_186_2_ecdsa_testvector_8_public_x[] = { +/* Qx */ + 0xa4, 0xdb, 0x13, 0x03, 0xbf, 0x13, 0x69, 0x6e, 0x26, 0x67, 0x82, 0x86, + 0xe2, 0x7c, 0x16, 0x6d, 0xd8, 0x7b, 0xe9, 0x8c, 0xc8, 0xbe, 0x28, 0x44 +}; +static const uint8_t nist_186_2_ecdsa_testvector_8_public_y[] = { +/* Qy */ + 0x09, 0xb4, 0xde, 0x84, 0xbb, 0xfa, 0x77, 0xe0, 0x49, 0xac, 0xe2, 0x72, + 0xa1, 0x2d, 0x0d, 0xd1, 0x41, 0xd3, 0x63, 0xe7, 0x4e, 0xc1, 0x25, 0x11 +}; +/* k = 00620f584b08d3199f6841fefa4b920659b267271c9b4034 */ +static const uint8_t nist_186_2_ecdsa_testvector_8_out[] = { +/* R */ + 0x68, 0x18, 0xd4, 0x4a, 0xea, 0x42, 0x17, 0x01, 0xe3, 0xf4, 0x16, 0x00, + 0xc8, 0x67, 0xfb, 0x3d, 0x37, 0x49, 0xea, 0xdb, 0xf3, 0x38, 0x20, 0xfa, +/* S */ + 0x65, 0x8b, 0x22, 0x8b, 0x2e, 0xdd, 0x85, 0x69, 0xf6, 0x94, 0x0f, 0xee, + 0x1c, 0x30, 0x36, 0x26, 0xe4, 0x81, 0x81, 0x09, 0x45, 0x81, 0x98, 0x7b +}; +static const uint8_t nist_186_2_ecdsa_testvector_9_ptx[] = { +/* Msg */ + 0x66, 0xe6, 0x9d, 0xc2, 0xa4, 0x7b, 0x31, 0x51, 0x5a, 0x71, 0x45, 0x6e, + 0x32, 0x9c, 0xf0, 0x2b, 0x08, 0x33, 0x1b, 0x15, 0x43, 0xd5, 0x7e, 0x5c, + 0x66, 0xc9, 0xcb, 0x34, 0xe2, 0x8a, 0x28, 0x7a, 0x2f, 0x83, 0xe3, 0x9b, + 0x1a, 0x17, 0x61, 0xb2, 0x61, 0xe4, 0x58, 0xf0, 0x7d, 0x49, 0x3e, 0x41, + 0xbf, 0x25, 0x02, 0x2c, 0x9e, 0xe2, 0xf9, 0xfb, 0x50, 0xb3, 0x1b, 0x1d, + 0x97, 0x19, 0x6f, 0xc8, 0xde, 0xac, 0xc4, 0xe3, 0x84, 0x18, 0xa2, 0x22, + 0x78, 0x66, 0x80, 0x73, 0x06, 0x7d, 0x37, 0x99, 0xf0, 0xe8, 0xb7, 0x16, + 0xc1, 0xd9, 0xf9, 0x4f, 0x5e, 0x6e, 0x35, 0xeb, 0xde, 0x34, 0x54, 0x7c, + 0x9b, 0xea, 0xa8, 0x61, 0x89, 0x87, 0xdb, 0xeb, 0xc7, 0x7e, 0x25, 0xbe, + 0x74, 0x40, 0xc2, 0x7a, 0xc4, 0x02, 0xa4, 0x9b, 0x53, 0xc1, 0x65, 0x9e, + 0xb9, 0x84, 0x7f, 0x66, 0x5e, 0xe2, 0xbf, 0xdd +}; +static const uint8_t nist_186_2_ecdsa_testvector_9_private[] = { +/* d */ + 0x00, 0xb5, 0xbf, 0xd0, 0x9a, 0x8d, 0x17, 0x75, 0x13, 0xc4, 0xbd, 0x7d, + 0x1b, 0xd9, 0xac, 0x5c, 0xcb, 0x7c, 0x00, 0xc6, 0x3b, 0x98, 0x41, 0xb4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_9_public_x[] = { +/* Qx */ + 0x27, 0x0d, 0x7b, 0xb9, 0xbf, 0xab, 0x54, 0x52, 0x92, 0x40, 0x42, 0x6a, + 0x08, 0x50, 0x8f, 0x1e, 0xd9, 0x0d, 0xc7, 0x91, 0x4c, 0xdf, 0x11, 0xf3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_9_public_y[] = { +/* Qy */ + 0xc9, 0x1e, 0xd7, 0xf2, 0xec, 0xa3, 0x9f, 0x56, 0x37, 0x57, 0xc5, 0xb5, + 0x18, 0xd9, 0xc2, 0x8d, 0x4d, 0x41, 0xe7, 0xbd, 0xc0, 0xc7, 0xf5, 0x3e +}; +/* k = 00dbc3fbf7b320e9bb6bae128ae19f2c67b297ceb9bc697f */ +static const uint8_t nist_186_2_ecdsa_testvector_9_out[] = { +/* R */ + 0xdb, 0x20, 0xf0, 0x9b, 0x69, 0xac, 0x79, 0xe2, 0x24, 0x25, 0x88, 0x00, + 0xeb, 0xe6, 0xcc, 0x51, 0xa2, 0xe1, 0x25, 0x36, 0xb6, 0x93, 0x96, 0xc8, +/* S */ + 0xd3, 0x1d, 0xf9, 0x54, 0x42, 0x77, 0xf4, 0xa7, 0x96, 0x76, 0xfd, 0xc7, + 0xa5, 0x1f, 0xae, 0xf7, 0x3e, 0xe2, 0xa0, 0xd1, 0x05, 0x7f, 0xf3, 0xa2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_10_ptx[] = { +/* Msg */ + 0xed, 0x3f, 0x4b, 0x0c, 0x4b, 0x79, 0xdd, 0xd5, 0xb0, 0x48, 0xb7, 0xb9, + 0xf3, 0xf6, 0x87, 0xfb, 0x57, 0x8a, 0xca, 0x75, 0x60, 0x49, 0x3f, 0x3a, + 0xe5, 0x7e, 0x9b, 0x7b, 0x65, 0x77, 0x7e, 0xa7, 0x9f, 0xd0, 0xa6, 0xd6, + 0x5c, 0xf4, 0x63, 0x68, 0x90, 0xe0, 0x4a, 0xe9, 0xa1, 0x2a, 0x2e, 0x38, + 0x07, 0x42, 0x4c, 0xe9, 0x15, 0xf9, 0xc6, 0xe7, 0x16, 0x3f, 0x53, 0x5e, + 0x9c, 0x31, 0x34, 0xd8, 0x15, 0x53, 0x6a, 0xa6, 0x9f, 0x19, 0x26, 0x81, + 0x1e, 0xad, 0x81, 0x71, 0x8b, 0xec, 0x6d, 0xee, 0x8f, 0xb1, 0xeb, 0x45, + 0x50, 0x57, 0x7f, 0x3e, 0x8b, 0x79, 0xe1, 0xfc, 0xe3, 0xfc, 0xf6, 0x24, + 0x78, 0x50, 0xfe, 0x42, 0xbc, 0xf2, 0x0f, 0x68, 0x82, 0x36, 0xc2, 0x18, + 0x58, 0x43, 0x2c, 0x63, 0x17, 0x5f, 0x10, 0x53, 0xb8, 0x6d, 0x52, 0x87, + 0x69, 0xb3, 0xaf, 0x1d, 0xe0, 0xe1, 0xac, 0xd5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_10_private[] = { +/* d */ + 0x00, 0x95, 0x8e, 0x4b, 0xbb, 0xdd, 0x87, 0x09, 0xa7, 0x84, 0x41, 0x48, + 0x5d, 0x6f, 0x57, 0xde, 0xe9, 0x6c, 0xc4, 0xd9, 0x8c, 0x38, 0xad, 0x4f +}; +static const uint8_t nist_186_2_ecdsa_testvector_10_public_x[] = { +/* Qx */ + 0x6a, 0x57, 0x23, 0xe7, 0x2f, 0x62, 0x70, 0x16, 0x0f, 0x25, 0x6d, 0xdd, + 0x40, 0x3c, 0x10, 0x85, 0x03, 0x38, 0x8d, 0x43, 0x20, 0xf7, 0x92, 0x6c +}; +static const uint8_t nist_186_2_ecdsa_testvector_10_public_y[] = { +/* Qy */ + 0xf5, 0x2b, 0x0e, 0x0e, 0x4c, 0x88, 0x71, 0x44, 0x3c, 0xfc, 0x0c, 0x23, + 0x1e, 0x85, 0x6f, 0x6a, 0xdc, 0x2a, 0x7c, 0x33, 0x18, 0xa4, 0x35, 0x78 +}; +/* k = 0045f392d1910760550b34e64d578905c20fb1cc51b29eef */ +static const uint8_t nist_186_2_ecdsa_testvector_10_out[] = { +/* R */ + 0x65, 0x05, 0x66, 0x3a, 0x95, 0x2b, 0x74, 0x1c, 0x45, 0x83, 0xe7, 0x55, + 0x49, 0x67, 0x40, 0x83, 0x3d, 0x59, 0x01, 0xfc, 0x09, 0x43, 0x39, 0x63, +/* S */ + 0xde, 0x04, 0x11, 0x97, 0x2e, 0x27, 0xbf, 0xb8, 0x03, 0x62, 0xb4, 0x46, + 0x50, 0xe6, 0x87, 0x86, 0x6c, 0xd2, 0x02, 0xa4, 0x19, 0x9d, 0x60, 0x5c +}; +static const uint8_t nist_186_2_ecdsa_testvector_11_ptx[] = { +/* Msg */ + 0x6a, 0x8b, 0x59, 0x50, 0x76, 0x51, 0x88, 0x80, 0xf0, 0x08, 0x38, 0x2e, + 0xed, 0x3e, 0x51, 0xf2, 0xb3, 0xf0, 0x6c, 0x4f, 0xce, 0x4c, 0x8c, 0x92, + 0x61, 0xbb, 0x08, 0xfd, 0xbb, 0x1f, 0xcc, 0x25, 0x2a, 0x59, 0xc2, 0x99, + 0x14, 0x0f, 0x8a, 0xc4, 0x43, 0xac, 0x71, 0x15, 0x81, 0xa8, 0xa1, 0x5d, + 0x65, 0x09, 0x95, 0x78, 0x6c, 0x2a, 0xd0, 0x2f, 0x4b, 0xbb, 0xcf, 0x5d, + 0x84, 0x09, 0x3c, 0x51, 0x38, 0x7f, 0x64, 0x74, 0x3c, 0x6d, 0xeb, 0x2b, + 0x6f, 0x09, 0xbe, 0xff, 0x4a, 0xb4, 0x4a, 0xfc, 0xb8, 0x7e, 0xec, 0x56, + 0x28, 0xeb, 0xa8, 0x53, 0xe1, 0xf8, 0x1d, 0x64, 0x96, 0x59, 0xb8, 0x95, + 0x3b, 0x05, 0x29, 0x28, 0x17, 0xf4, 0x13, 0x7d, 0x19, 0x27, 0x08, 0x36, + 0x6f, 0xea, 0xb4, 0x98, 0x55, 0x56, 0x58, 0x33, 0x2b, 0x19, 0x7b, 0xc5, + 0xcb, 0x7a, 0xdc, 0x5c, 0x19, 0x97, 0xaa, 0xbb +}; +static const uint8_t nist_186_2_ecdsa_testvector_11_private[] = { +/* d */ + 0x00, 0x49, 0x60, 0x53, 0x3b, 0x78, 0x8b, 0x3f, 0xad, 0x01, 0x7e, 0x61, + 0x0f, 0x5d, 0xda, 0xb7, 0x50, 0xb4, 0xbf, 0x5a, 0x5e, 0x9d, 0x09, 0x64 +}; +static const uint8_t nist_186_2_ecdsa_testvector_11_public_x[] = { +/* Qx */ + 0x1c, 0x0e, 0x4f, 0xc6, 0xd8, 0xf4, 0xe7, 0x60, 0x5f, 0x2b, 0xf5, 0x75, + 0x41, 0x39, 0x5f, 0x51, 0x67, 0xd4, 0x1d, 0x8b, 0xdd, 0x5c, 0x4f, 0x80 +}; +static const uint8_t nist_186_2_ecdsa_testvector_11_public_y[] = { +/* Qy */ + 0x77, 0x5d, 0xa7, 0x32, 0x26, 0x02, 0x0b, 0xad, 0x6e, 0xc4, 0xdf, 0x50, + 0x22, 0xa8, 0xc6, 0x1a, 0xee, 0x06, 0x43, 0x72, 0xba, 0x53, 0x5a, 0xe7 +}; +/* k = 00e93a10b115218fcb2f0413784385e1fc4555b1818f3b3c */ +static const uint8_t nist_186_2_ecdsa_testvector_11_out[] = { +/* R */ + 0xbc, 0x54, 0x0a, 0x8f, 0x5e, 0xa8, 0x1c, 0x61, 0x44, 0x69, 0x8f, 0x54, + 0x52, 0x55, 0x6f, 0x17, 0xda, 0x76, 0xa5, 0x26, 0x36, 0x46, 0x1d, 0x70, +/* S */ + 0x2d, 0xe2, 0x3f, 0x6c, 0xc9, 0xa4, 0x58, 0x99, 0xa9, 0xf6, 0x05, 0xda, + 0xb9, 0xf2, 0x8f, 0xdd, 0xf9, 0xe3, 0x76, 0xea, 0x06, 0xc9, 0x2d, 0xb5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_12_ptx[] = { +/* Msg */ + 0xef, 0xd5, 0xd8, 0x20, 0x00, 0x24, 0x9e, 0xf1, 0x68, 0xa0, 0x4b, 0xc3, + 0x9f, 0x32, 0x35, 0x6b, 0xba, 0xe8, 0x3e, 0x0b, 0xe1, 0x9a, 0xf1, 0xda, + 0x03, 0xcd, 0xce, 0x23, 0xc8, 0xd7, 0xe1, 0x91, 0xc8, 0x44, 0x9a, 0xa9, + 0xfa, 0x79, 0xd8, 0x98, 0x6f, 0x97, 0x47, 0x2f, 0x40, 0xa2, 0xec, 0x2c, + 0xc5, 0xe3, 0xfe, 0xbb, 0x07, 0x8a, 0xf8, 0x3c, 0x78, 0x98, 0xec, 0x47, + 0xe2, 0xfc, 0x1a, 0xed, 0x9e, 0xfc, 0xc1, 0x41, 0x06, 0xd7, 0x35, 0x18, + 0x2c, 0xa9, 0x32, 0x0c, 0xcd, 0x8e, 0x70, 0xc7, 0x80, 0x0a, 0x77, 0x7e, + 0x33, 0xa9, 0xb5, 0xbb, 0xd8, 0xe2, 0xce, 0x60, 0x5c, 0x41, 0x33, 0xe9, + 0xd9, 0xc6, 0xf6, 0xf1, 0x0c, 0x88, 0xdd, 0xf7, 0x09, 0x9d, 0xb5, 0x63, + 0x2d, 0x3e, 0xe8, 0xc4, 0x55, 0x27, 0x52, 0x5c, 0x4d, 0x3d, 0x51, 0xde, + 0x8c, 0x73, 0x1b, 0x76, 0x1e, 0xee, 0x55, 0x0a +}; +static const uint8_t nist_186_2_ecdsa_testvector_12_private[] = { +/* d */ + 0x00, 0xcf, 0x08, 0xdf, 0x71, 0xe8, 0x34, 0x3a, 0xf5, 0x5f, 0xc2, 0x0c, + 0xa9, 0xd6, 0xae, 0x82, 0x2f, 0x9b, 0xbd, 0xf5, 0xab, 0x7d, 0x21, 0x13 +}; +static const uint8_t nist_186_2_ecdsa_testvector_12_public_x[] = { +/* Qx */ + 0x19, 0x4e, 0x8f, 0xdd, 0x4b, 0x6b, 0x84, 0xf1, 0x95, 0x5d, 0x19, 0x19, + 0x38, 0x7f, 0x96, 0xfa, 0xcf, 0x6f, 0xea, 0xdd, 0x81, 0x05, 0xd8, 0xdd +}; +static const uint8_t nist_186_2_ecdsa_testvector_12_public_y[] = { +/* Qy */ + 0x2e, 0xb4, 0x7a, 0x2e, 0xd3, 0xaa, 0xc4, 0x25, 0x0b, 0xe3, 0x7f, 0x9e, + 0x31, 0xd7, 0xff, 0x87, 0xbe, 0x40, 0x43, 0xac, 0x1e, 0xac, 0x40, 0x1f +}; +/* k = 009758de92827113c0d1ece5ad9ab65d9acf18f74b58ecf6 */ +static const uint8_t nist_186_2_ecdsa_testvector_12_out[] = { +/* R */ + 0x0b, 0xbd, 0x33, 0x1b, 0x5c, 0xbc, 0xae, 0xf2, 0xb2, 0x6e, 0x27, 0xbd, + 0xc5, 0x59, 0xd3, 0x1c, 0x62, 0xd5, 0xc9, 0xb6, 0xb8, 0x97, 0x96, 0x03, +/* S */ + 0xc1, 0x67, 0x0a, 0x3b, 0x43, 0x58, 0x05, 0xfa, 0x7a, 0xb2, 0x0e, 0x6d, + 0xd8, 0xff, 0xa1, 0x01, 0x2e, 0x9f, 0xb4, 0x1b, 0x1d, 0x7d, 0x01, 0x76 +}; +static const uint8_t nist_186_2_ecdsa_testvector_13_ptx[] = { +/* Msg */ + 0xf9, 0xe2, 0x39, 0x34, 0xaf, 0xaa, 0x64, 0x63, 0x4c, 0x91, 0xb5, 0xa1, + 0x48, 0xc1, 0xfd, 0x85, 0xa9, 0xb5, 0x18, 0x8c, 0xca, 0xf0, 0xcf, 0x6b, + 0x5b, 0xef, 0xfd, 0xa4, 0xa9, 0x5c, 0xf1, 0x58, 0x1f, 0x84, 0x14, 0x5c, + 0x0d, 0x0b, 0xcb, 0x8f, 0xa9, 0xde, 0x9f, 0x6a, 0x54, 0x6a, 0x9c, 0xd8, + 0x1e, 0x0c, 0xf6, 0x48, 0x8b, 0xc8, 0xf3, 0x01, 0x98, 0x3d, 0x04, 0xb6, + 0xf9, 0xd8, 0x35, 0x5b, 0xa5, 0x49, 0xc8, 0x37, 0x94, 0x33, 0x1d, 0x39, + 0xc7, 0x28, 0xd6, 0x8f, 0x8a, 0xd4, 0x38, 0x75, 0xf6, 0x78, 0xd3, 0x4b, + 0xb9, 0x9b, 0x65, 0xeb, 0x1a, 0xfc, 0xfc, 0x39, 0x37, 0xca, 0x5b, 0xfc, + 0x91, 0x17, 0x9f, 0xec, 0xcb, 0x8b, 0x22, 0x0b, 0xaf, 0x55, 0xa0, 0x39, + 0x72, 0x67, 0x98, 0x03, 0x39, 0xe3, 0xf5, 0xbd, 0xdb, 0xd0, 0xee, 0xd0, + 0xe9, 0x12, 0x2b, 0x54, 0xec, 0x99, 0x29, 0xe2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_13_private[] = { +/* d */ + 0x00, 0x27, 0x49, 0x2b, 0xdd, 0x57, 0x3a, 0x53, 0xba, 0xaf, 0xd1, 0x57, + 0x55, 0x78, 0xfd, 0xce, 0x24, 0x2e, 0x43, 0xf2, 0xe3, 0x53, 0x7a, 0x0b +}; +static const uint8_t nist_186_2_ecdsa_testvector_13_public_x[] = { +/* Qx */ + 0x18, 0xb9, 0x4f, 0xc7, 0x82, 0x5b, 0xad, 0x91, 0xb1, 0xca, 0x5a, 0x69, + 0xcd, 0xf5, 0x76, 0x37, 0x7a, 0xd7, 0x69, 0x65, 0x67, 0x0d, 0x39, 0x67 +}; +static const uint8_t nist_186_2_ecdsa_testvector_13_public_y[] = { +/* Qy */ + 0x0a, 0x73, 0x25, 0x3d, 0x6d, 0xf5, 0x4d, 0x51, 0x05, 0xf0, 0xca, 0x2f, + 0x94, 0x8d, 0x06, 0x86, 0x70, 0x6d, 0xbd, 0x06, 0x47, 0x44, 0xf7, 0xc3 +}; +/* k = 00d8966cd03fdb2509193ddeee3b429cab2605e283c98577 */ +static const uint8_t nist_186_2_ecdsa_testvector_13_out[] = { +/* R */ + 0x1a, 0x81, 0x3b, 0x60, 0x7c, 0x0b, 0x4d, 0x71, 0xe7, 0xac, 0xda, 0xc0, + 0x40, 0xeb, 0x78, 0xb3, 0x79, 0x5e, 0x53, 0xbc, 0x49, 0x8b, 0xae, 0x85, +/* S */ + 0x67, 0xfc, 0x11, 0x24, 0xc3, 0x09, 0x66, 0x47, 0x3d, 0xc6, 0xa1, 0xf1, + 0x4a, 0xe3, 0x2e, 0xc2, 0xdd, 0x86, 0x0b, 0x36, 0x67, 0xc6, 0x1d, 0xec +}; +static const uint8_t nist_186_2_ecdsa_testvector_14_ptx[] = { +/* Msg */ + 0xaa, 0x00, 0x90, 0x57, 0x0f, 0x6f, 0xa8, 0x1e, 0xd0, 0x2f, 0xa1, 0xce, + 0x2c, 0x12, 0x4f, 0xfd, 0x35, 0x74, 0xf2, 0xf8, 0xd4, 0x28, 0x5e, 0x57, + 0x0e, 0xb3, 0x59, 0xd5, 0x85, 0xb8, 0x45, 0x5f, 0x42, 0xb4, 0xff, 0x6b, + 0xb1, 0xec, 0x06, 0x8b, 0xed, 0xa3, 0xe0, 0x42, 0x3e, 0x8f, 0xb9, 0x16, + 0xe1, 0x8e, 0x4e, 0xe6, 0x07, 0x96, 0x09, 0x7e, 0x1f, 0xea, 0x6d, 0x69, + 0x58, 0x94, 0xb5, 0x06, 0x62, 0x0f, 0xb8, 0xdf, 0x75, 0x44, 0x10, 0x35, + 0x95, 0xb8, 0x7b, 0xe0, 0x14, 0x03, 0x81, 0x56, 0x58, 0x84, 0x58, 0x09, + 0xdf, 0x53, 0x04, 0xf6, 0x7f, 0x77, 0xc2, 0x7a, 0xf3, 0x59, 0xa7, 0x68, + 0x93, 0x79, 0x85, 0x5a, 0x63, 0x60, 0x0e, 0x44, 0x4f, 0xd6, 0x3c, 0x4f, + 0xb5, 0x54, 0xf0, 0xe4, 0x24, 0xbc, 0xd9, 0x06, 0x64, 0x48, 0x97, 0xe6, + 0xb6, 0xc0, 0x20, 0xb1, 0x5c, 0xf1, 0x63, 0xad +}; +static const uint8_t nist_186_2_ecdsa_testvector_14_private[] = { +/* d */ + 0x00, 0x06, 0x6e, 0xb1, 0xa5, 0xe6, 0xa4, 0x2b, 0x53, 0xfc, 0xc8, 0x2f, + 0xcf, 0x6a, 0x60, 0x1d, 0x02, 0x31, 0x27, 0xc7, 0xb1, 0xc7, 0x79, 0xdb +}; +static const uint8_t nist_186_2_ecdsa_testvector_14_public_x[] = { +/* Qx */ + 0x38, 0x88, 0xa9, 0x4e, 0xf2, 0x88, 0xeb, 0xe3, 0x2b, 0x4b, 0x9b, 0x53, + 0xbf, 0x2d, 0x3a, 0x85, 0xb4, 0x59, 0x76, 0x58, 0x32, 0x51, 0xf0, 0xec +}; +static const uint8_t nist_186_2_ecdsa_testvector_14_public_y[] = { +/* Qy */ + 0x30, 0x15, 0x6d, 0x8e, 0x0d, 0x21, 0x2a, 0x66, 0xc0, 0x71, 0xfb, 0x2e, + 0x7b, 0x42, 0x2e, 0xf1, 0x78, 0x4a, 0x95, 0xda, 0xcf, 0xfd, 0x9e, 0xdb +}; +/* k = 008c135723cb6a10cbd3e2cde313aee847477e66c4220f47 */ +static const uint8_t nist_186_2_ecdsa_testvector_14_out[] = { +/* R */ + 0x37, 0x03, 0x31, 0x50, 0xaf, 0xed, 0x02, 0x9f, 0xd8, 0x39, 0x07, 0x16, + 0xea, 0xc6, 0x50, 0x02, 0x23, 0xe7, 0x21, 0x54, 0xcc, 0xff, 0x9f, 0xee, +/* S */ + 0xb4, 0xe9, 0x78, 0xe8, 0xd4, 0x99, 0xcc, 0x1b, 0xe5, 0x76, 0xde, 0xa7, + 0x4c, 0x0d, 0xd7, 0x4c, 0xaf, 0xe9, 0xe7, 0x94, 0xa7, 0x56, 0x31, 0x72 +}; +static const uint8_t nist_186_2_ecdsa_testvector_15_ptx[] = { +/* Msg */ + 0xa3, 0xbb, 0xba, 0xd7, 0x66, 0x71, 0xd8, 0xfd, 0xac, 0xbb, 0xee, 0x1f, + 0x5a, 0xb2, 0x41, 0xbd, 0x01, 0x78, 0xff, 0x99, 0x6e, 0x76, 0x77, 0x18, + 0x7c, 0xe8, 0x88, 0xea, 0x2d, 0x9c, 0x5a, 0xed, 0xf9, 0xf6, 0x4d, 0x4f, + 0x66, 0x38, 0x2f, 0xf4, 0xd9, 0x00, 0xb2, 0x17, 0xac, 0x13, 0x1d, 0x33, + 0x80, 0x58, 0x41, 0x24, 0xd5, 0x28, 0xaf, 0x89, 0xd8, 0xc5, 0x28, 0x6e, + 0x7b, 0x27, 0x55, 0x28, 0xcb, 0xff, 0xb8, 0x7f, 0x7f, 0xf6, 0xe3, 0x13, + 0xcc, 0x35, 0xe8, 0xf8, 0x81, 0x2b, 0x10, 0xa4, 0x4f, 0x8a, 0xd0, 0x0b, + 0x68, 0x93, 0xf8, 0x08, 0x4d, 0x94, 0x2e, 0xff, 0xe0, 0xaf, 0x9b, 0xc1, + 0xc1, 0xdc, 0xe4, 0xaf, 0xd7, 0x31, 0x5c, 0x23, 0x2d, 0x62, 0x78, 0x0b, + 0x00, 0x84, 0x83, 0xd7, 0x16, 0x16, 0x92, 0x96, 0x51, 0x41, 0xbb, 0x5b, + 0x83, 0x5f, 0x82, 0xe6, 0x84, 0xbb, 0x94, 0x80 +}; +static const uint8_t nist_186_2_ecdsa_testvector_15_private[] = { +/* d */ + 0x00, 0x6d, 0xfc, 0x40, 0x88, 0x0e, 0x0c, 0x42, 0xd2, 0xce, 0xbc, 0xde, + 0xe2, 0x55, 0x04, 0x0d, 0x18, 0xbb, 0x99, 0x19, 0x09, 0x81, 0xf9, 0xa9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_15_public_x[] = { +/* Qx */ + 0xb1, 0x19, 0x56, 0xa2, 0x9a, 0xf6, 0x98, 0x40, 0x43, 0x97, 0x3e, 0x2d, + 0xe4, 0x6d, 0x53, 0xd8, 0x70, 0xe0, 0x46, 0x87, 0xca, 0xe5, 0x97, 0x28 +}; +static const uint8_t nist_186_2_ecdsa_testvector_15_public_y[] = { +/* Qy */ + 0xc9, 0x15, 0xf8, 0x8a, 0xa0, 0xfa, 0x98, 0x22, 0x76, 0x2c, 0xc4, 0xe6, + 0x0d, 0xf7, 0x59, 0xd1, 0x89, 0xa1, 0x0c, 0x48, 0x6b, 0x90, 0x1d, 0x5e +}; +/* k = 009e03961f041fa811ff88c4948bc0a6d867a7fef5f39453 */ +static const uint8_t nist_186_2_ecdsa_testvector_15_out[] = { +/* R */ + 0xc4, 0x59, 0xf7, 0xbc, 0xea, 0x05, 0x02, 0x10, 0xe3, 0x36, 0x9a, 0xc1, + 0x74, 0xba, 0x89, 0xc8, 0x23, 0xca, 0x1b, 0x0d, 0x4c, 0x09, 0x64, 0xf6, +/* S */ + 0x04, 0x71, 0x5c, 0xba, 0x9b, 0xa3, 0x1c, 0x4e, 0xd9, 0xbf, 0x0b, 0xe0, + 0x7d, 0x19, 0x4e, 0x2a, 0x70, 0x92, 0x94, 0x47, 0x2c, 0xc6, 0x0b, 0xdf +}; +/* [P-224] */ +static const uint8_t nist_186_2_ecdsa_testvector_16_ptx[] = { +/* Msg */ + 0x66, 0xe9, 0x8a, 0x16, 0x58, 0x54, 0xcd, 0x07, 0x98, 0x9b, 0x1e, 0xe0, + 0xec, 0x3f, 0x8d, 0xbe, 0x0e, 0xe3, 0xc2, 0xfb, 0x00, 0x51, 0xef, 0x53, + 0xa0, 0xbe, 0x03, 0x45, 0x7c, 0x4f, 0x21, 0xbc, 0xe7, 0xdc, 0x50, 0xef, + 0x4d, 0xf3, 0x74, 0x86, 0xc3, 0x20, 0x7d, 0xfe, 0xe2, 0x6b, 0xde, 0x4e, + 0xd6, 0x23, 0x40, 0xcb, 0xb2, 0xda, 0x78, 0x49, 0x06, 0xb1, 0xb7, 0x83, + 0xb4, 0xd6, 0x01, 0xbd, 0xff, 0x4a, 0xe1, 0xa7, 0xe5, 0xe8, 0x5a, 0x85, + 0xaf, 0xa3, 0x20, 0x8d, 0xc6, 0x0f, 0x09, 0x90, 0xc8, 0x23, 0xbe, 0xdd, + 0xdb, 0x3d, 0xb6, 0x63, 0x42, 0x66, 0x65, 0x15, 0x2e, 0xd7, 0xb0, 0x93, + 0xd6, 0xbd, 0xa5, 0x06, 0xc9, 0x3a, 0x69, 0x4b, 0x83, 0xac, 0x71, 0x55, + 0x3f, 0x31, 0xf5, 0xcc, 0x0d, 0x6b, 0xa2, 0xfa, 0x24, 0x80, 0x90, 0xe8, + 0x79, 0x65, 0x73, 0xc4, 0x91, 0x5d, 0x15, 0x86 +}; +static const uint8_t nist_186_2_ecdsa_testvector_16_private[] = { +/* d */ + 0x00, 0x69, 0x75, 0xfe, 0xbc, 0x7b, 0x44, 0x2d, 0xab, 0x8f, 0xd2, 0x83, + 0xec, 0x2e, 0x4b, 0xdd, 0x0e, 0x00, 0x09, 0x52, 0x5b, 0x1c, 0xe0, 0x71, + 0xf9, 0xab, 0x59, 0x56 +}; +static const uint8_t nist_186_2_ecdsa_testvector_16_public_x[] = { +/* Qx */ + 0x56, 0xfb, 0x65, 0x38, 0xf1, 0x72, 0x3d, 0x2b, 0xef, 0x3c, 0x76, 0x41, + 0x34, 0x32, 0x0b, 0x44, 0xba, 0x61, 0x5f, 0x66, 0x3d, 0xb8, 0x04, 0xe5, + 0x40, 0x50, 0xb9, 0x5a +}; +static const uint8_t nist_186_2_ecdsa_testvector_16_public_y[] = { +/* Qy */ + 0x95, 0x14, 0xa4, 0x42, 0xeb, 0x66, 0xdb, 0xf2, 0xb4, 0x50, 0x74, 0x6f, + 0x66, 0xd5, 0x41, 0x01, 0x87, 0x7a, 0x50, 0xd4, 0xbc, 0x29, 0x10, 0xc6, + 0x1d, 0x00, 0x5a, 0xdd +}; +/* k = 00591cb4272ddd1546d3d67bd2707d47ca51fd2c81d04635ad71e8aa */ +static const uint8_t nist_186_2_ecdsa_testvector_16_out[] = { +/* R */ + 0x96, 0x60, 0xbf, 0xff, 0xc1, 0x73, 0x43, 0x1d, 0x29, 0xf8, 0x3f, 0xa2, + 0xaf, 0x0b, 0xa5, 0x81, 0x79, 0x1b, 0xe3, 0xf4, 0x36, 0x25, 0x31, 0x6f, + 0x39, 0x5d, 0x27, 0xff, +/* S */ + 0x9e, 0x8c, 0x3b, 0x82, 0xbc, 0xa2, 0xa4, 0x46, 0x7c, 0x96, 0x94, 0xc6, + 0x66, 0xdf, 0xf7, 0xf0, 0xe7, 0x9d, 0x27, 0x9b, 0xd6, 0x4e, 0xb8, 0x3b, + 0xce, 0x2e, 0x30, 0x18 +}; +static const uint8_t nist_186_2_ecdsa_testvector_17_ptx[] = { +/* Msg */ + 0xd3, 0x9a, 0xd5, 0x61, 0x35, 0xbe, 0xc4, 0xc3, 0xc4, 0x36, 0x2d, 0x59, + 0xd3, 0xd9, 0x17, 0x5a, 0xcb, 0x38, 0x66, 0x70, 0xc5, 0xdb, 0x0a, 0x17, + 0x57, 0xce, 0x76, 0x46, 0xad, 0x5d, 0x53, 0x52, 0xdc, 0x1b, 0x76, 0x0f, + 0x74, 0x29, 0x10, 0x38, 0x54, 0xb4, 0x25, 0x11, 0xc3, 0xc0, 0x40, 0x4a, + 0xbc, 0x24, 0x64, 0x27, 0x88, 0xd6, 0x45, 0xde, 0x93, 0x69, 0xb8, 0x41, + 0x78, 0xd4, 0x69, 0x9c, 0x5e, 0x75, 0xcc, 0xe1, 0x87, 0x56, 0x56, 0x02, + 0x26, 0xae, 0xec, 0x9f, 0x71, 0xab, 0x9c, 0xe1, 0xf8, 0x6e, 0x8b, 0xa6, + 0x35, 0x58, 0x2e, 0xde, 0x64, 0x84, 0xbd, 0x34, 0x95, 0x94, 0xe5, 0xf2, + 0xff, 0xb1, 0xbe, 0x1e, 0x97, 0xcd, 0xfc, 0xe9, 0xe1, 0x2b, 0x69, 0x4b, + 0x06, 0x22, 0x93, 0xe7, 0x28, 0x1e, 0xc1, 0x34, 0xf2, 0xe7, 0x2c, 0xde, + 0x73, 0x26, 0x6c, 0x6a, 0x2c, 0x25, 0x31, 0x1a +}; +static const uint8_t nist_186_2_ecdsa_testvector_17_private[] = { +/* d */ + 0x00, 0xfd, 0x12, 0x10, 0xef, 0x46, 0x85, 0xba, 0x8e, 0x31, 0xa3, 0xe0, + 0xd6, 0x6e, 0x03, 0xf9, 0x12, 0x64, 0xa2, 0xa5, 0xb8, 0x89, 0x7a, 0x1d, + 0xc1, 0x81, 0xb3, 0x53 +}; +static const uint8_t nist_186_2_ecdsa_testvector_17_public_x[] = { +/* Qx */ + 0x39, 0x1d, 0xe8, 0x05, 0x90, 0xdf, 0xbc, 0x60, 0xbb, 0x41, 0xcc, 0x9f, + 0x3d, 0x93, 0x70, 0x6d, 0x1d, 0x00, 0x83, 0xf1, 0xef, 0x31, 0xd3, 0xa0, + 0x31, 0xfd, 0xc6, 0x04 +}; +static const uint8_t nist_186_2_ecdsa_testvector_17_public_y[] = { +/* Qy */ + 0x4d, 0xd1, 0x92, 0x8e, 0x55, 0x76, 0x36, 0xf0, 0xa5, 0xdf, 0x08, 0x2a, + 0xa0, 0xb1, 0x85, 0xd0, 0x8f, 0x57, 0xd1, 0xd5, 0xbf, 0x78, 0x57, 0xfc, + 0xee, 0xb8, 0xc4, 0xc1 +}; +/* k = 005ab787e0961baaaba6c9deef88f69fed3e348a93f6564ded6fb51a */ +static const uint8_t nist_186_2_ecdsa_testvector_17_out[] = { +/* R */ + 0xfc, 0x9a, 0x20, 0x58, 0xb2, 0xa7, 0xb6, 0x4c, 0x3c, 0x48, 0xf4, 0x0a, + 0x36, 0x43, 0xb1, 0x8d, 0xbf, 0x41, 0x8f, 0x57, 0x99, 0x29, 0xbf, 0x52, + 0xa5, 0xde, 0xa7, 0x73, +/* S */ + 0x05, 0x65, 0x3b, 0x94, 0x6b, 0x27, 0x0a, 0xaf, 0x01, 0x35, 0x1b, 0x21, + 0xde, 0x75, 0x35, 0x08, 0x61, 0x0b, 0x1a, 0x76, 0xcf, 0x42, 0x36, 0x6f, + 0x1a, 0x6c, 0x1d, 0x62 +}; +static const uint8_t nist_186_2_ecdsa_testvector_18_ptx[] = { +/* Msg */ + 0x47, 0x71, 0x01, 0xda, 0xa2, 0x82, 0xa5, 0xa5, 0x5b, 0x48, 0xc5, 0x31, + 0x32, 0x90, 0xc8, 0xda, 0x65, 0xb0, 0x7c, 0xc4, 0xd4, 0x1a, 0x5a, 0x14, + 0x63, 0x30, 0x0c, 0x60, 0xa0, 0x5a, 0x2c, 0x63, 0xa6, 0x56, 0x4f, 0xf6, + 0x41, 0xd0, 0x42, 0x3c, 0x52, 0x33, 0x93, 0x1c, 0x75, 0xbe, 0x53, 0xf4, + 0xe2, 0xda, 0x1b, 0x8b, 0x91, 0xab, 0x4d, 0x48, 0xa2, 0xe5, 0x9c, 0xa2, + 0xfb, 0xe1, 0xcf, 0xd8, 0x33, 0xf0, 0xc1, 0xe2, 0xaf, 0xef, 0xad, 0xa7, + 0x0a, 0x1b, 0xa8, 0x70, 0xba, 0x27, 0x6f, 0x9d, 0xf1, 0x8c, 0x63, 0x97, + 0xc2, 0x21, 0xd2, 0x05, 0x85, 0xeb, 0x78, 0x43, 0x7c, 0x36, 0x46, 0x0f, + 0xb7, 0xe4, 0x62, 0x86, 0x34, 0x06, 0x6e, 0x50, 0x4b, 0xa9, 0x0d, 0x17, + 0x49, 0xf2, 0xa3, 0x3d, 0x5c, 0x6e, 0x5d, 0xce, 0xaf, 0xa3, 0x72, 0xb3, + 0xd5, 0xeb, 0xa8, 0x29, 0x6b, 0x82, 0x19, 0x72 +}; +static const uint8_t nist_186_2_ecdsa_testvector_18_private[] = { +/* d */ + 0x00, 0xd6, 0x61, 0xae, 0x9d, 0x6a, 0x6e, 0xab, 0x7c, 0xa8, 0x37, 0x83, + 0x31, 0xe4, 0x35, 0x66, 0x45, 0x35, 0x72, 0x08, 0x04, 0xca, 0xb0, 0x9d, + 0xb1, 0xcb, 0xca, 0x6c +}; +static const uint8_t nist_186_2_ecdsa_testvector_18_public_x[] = { +/* Qx */ + 0x99, 0x34, 0x73, 0xa7, 0xd4, 0xb3, 0x33, 0xe3, 0x4c, 0x17, 0xeb, 0xfa, + 0xa8, 0x6e, 0xd9, 0x29, 0xc8, 0x64, 0x5c, 0xcf, 0xd7, 0x97, 0x59, 0xc0, + 0x84, 0xcd, 0xb1, 0x74 +}; +static const uint8_t nist_186_2_ecdsa_testvector_18_public_y[] = { +/* Qy */ + 0xa2, 0x6a, 0xd5, 0x0e, 0x57, 0x34, 0x79, 0x65, 0xb4, 0x2d, 0x5a, 0x15, + 0x9f, 0xf5, 0x3a, 0x28, 0x95, 0x7a, 0x5f, 0x3b, 0x57, 0xa8, 0x44, 0xdc, + 0xd0, 0xee, 0x6d, 0x54 +}; +/* k = 00171f192db736283e30bb89fd6f2aeeb4c70d3eaae2ac58451fbb3b */ +static const uint8_t nist_186_2_ecdsa_testvector_18_out[] = { +/* R */ + 0x25, 0x9f, 0xda, 0x31, 0x43, 0xc5, 0x84, 0x13, 0x1a, 0xb8, 0xe4, 0x9f, + 0xea, 0xf9, 0x3d, 0xad, 0x3b, 0x86, 0x57, 0x5f, 0x27, 0x89, 0x96, 0x24, + 0x06, 0xbf, 0x80, 0x92, +/* S */ + 0xce, 0xa1, 0xcc, 0x15, 0xe2, 0x8c, 0x09, 0x4c, 0x3b, 0xc5, 0x57, 0xb3, + 0xf5, 0xa5, 0x17, 0x2b, 0x62, 0x91, 0x0c, 0xd7, 0xcf, 0xbb, 0x61, 0x93, + 0xae, 0x6d, 0x8d, 0xd2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_19_ptx[] = { +/* Msg */ + 0x85, 0xbc, 0xd4, 0x06, 0xf4, 0xcd, 0xc8, 0xf3, 0x0e, 0x19, 0x55, 0x3b, + 0xa9, 0x2f, 0x9c, 0x08, 0x94, 0xb2, 0x83, 0x3d, 0x7b, 0xb0, 0xb5, 0x65, + 0x0a, 0x30, 0xeb, 0xe8, 0x55, 0x0a, 0x69, 0x85, 0x78, 0xfc, 0xcb, 0xfc, + 0x7a, 0xf9, 0x01, 0x0b, 0x78, 0xc4, 0x99, 0x9c, 0xff, 0xbe, 0x3c, 0x3d, + 0xb9, 0xfd, 0x7c, 0xd0, 0x4c, 0x9d, 0xcd, 0x84, 0x7f, 0x5b, 0xd0, 0x04, + 0x9f, 0x5f, 0xd8, 0xee, 0x21, 0x5a, 0xa7, 0x86, 0x88, 0xd1, 0x78, 0xac, + 0x89, 0xb9, 0x43, 0x0b, 0x6d, 0x43, 0x3c, 0x94, 0xb8, 0xf9, 0x9c, 0x2b, + 0x08, 0x0a, 0xa5, 0x9f, 0x3f, 0xe2, 0xe0, 0xe0, 0xe4, 0xfe, 0xaa, 0x6c, + 0xc7, 0xff, 0xee, 0x0b, 0xe4, 0xfd, 0x34, 0xbc, 0x8a, 0x1d, 0xdb, 0xef, + 0xbd, 0x66, 0xa2, 0xf4, 0xd8, 0xd0, 0x6e, 0xb4, 0x77, 0x9e, 0x47, 0x9f, + 0x93, 0xee, 0xa3, 0xe5, 0xef, 0x8f, 0xe7, 0xe9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_19_private[] = { +/* d */ + 0x00, 0x5a, 0x52, 0x8a, 0x01, 0x67, 0x68, 0x33, 0x93, 0xfa, 0x59, 0x18, + 0xb9, 0x49, 0x89, 0xb9, 0x34, 0x2f, 0x81, 0x73, 0xcc, 0x97, 0x57, 0xdd, + 0xea, 0x49, 0xfe, 0xd7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_19_public_x[] = { +/* Qx */ + 0xb8, 0xc3, 0x39, 0x44, 0xff, 0x61, 0xc5, 0x60, 0x09, 0x04, 0xca, 0x2a, + 0xe0, 0xae, 0xfa, 0xe6, 0xd2, 0x1b, 0xf3, 0xc7, 0x4a, 0xa2, 0x1f, 0xaf, + 0xd8, 0x24, 0xca, 0x69 +}; +static const uint8_t nist_186_2_ecdsa_testvector_19_public_y[] = { +/* Qy */ + 0xed, 0x93, 0xa6, 0xed, 0xb3, 0xf3, 0xc3, 0xc4, 0x99, 0x7e, 0xbf, 0xbc, + 0x97, 0x66, 0x49, 0x65, 0x44, 0x9e, 0x5e, 0xd7, 0xea, 0xae, 0x87, 0x5f, + 0xc3, 0x28, 0xf0, 0xee +}; +/* k = 000c2aa7a8a5fe907b2cb5fc77917dd14fd266315503a3c11476d285 */ +static const uint8_t nist_186_2_ecdsa_testvector_19_out[] = { +/* R */ + 0x6b, 0x4b, 0xc7, 0xa9, 0x07, 0x09, 0x0d, 0xb6, 0x6e, 0x3a, 0x02, 0x25, + 0x8f, 0x04, 0x3c, 0x40, 0x33, 0x04, 0x03, 0xb2, 0x2d, 0xea, 0x13, 0x1b, + 0xad, 0x0d, 0xbb, 0x86, +/* S */ + 0xec, 0xea, 0x70, 0xcd, 0x69, 0x21, 0xe9, 0x34, 0x2d, 0x49, 0xb8, 0x81, + 0x91, 0xc0, 0x20, 0xd2, 0xbf, 0xaf, 0xfa, 0xa6, 0x7d, 0xf5, 0x93, 0x88, + 0xdb, 0x4a, 0x3e, 0xa5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_20_ptx[] = { +/* Msg */ + 0xc5, 0x8c, 0xc5, 0xe0, 0xeb, 0xa5, 0x1a, 0x42, 0xe3, 0xa9, 0x88, 0xc2, + 0x43, 0x24, 0x81, 0xdb, 0x2e, 0x01, 0x53, 0x72, 0x84, 0xef, 0xfc, 0x5c, + 0x56, 0x09, 0x3f, 0x21, 0x9d, 0xb5, 0xf7, 0xff, 0x2b, 0xcc, 0xac, 0x32, + 0xe1, 0xfc, 0x64, 0x73, 0x23, 0x6b, 0xbb, 0xbf, 0x89, 0x9d, 0x36, 0x59, + 0xd7, 0x98, 0xd5, 0x12, 0x30, 0x46, 0xe7, 0xc8, 0x86, 0x1a, 0x22, 0x2d, + 0x55, 0xf6, 0xf3, 0xc9, 0x91, 0x4d, 0x13, 0x43, 0xdd, 0x85, 0x5b, 0xdc, + 0xfd, 0x9f, 0xd9, 0x3c, 0x8e, 0x19, 0x23, 0x71, 0xf4, 0x13, 0xeb, 0x35, + 0x95, 0xb2, 0xd4, 0x6f, 0x45, 0xc2, 0x84, 0xfd, 0x00, 0x9f, 0xfb, 0xb1, + 0xdf, 0x55, 0x23, 0x99, 0x45, 0x06, 0xa8, 0x84, 0x59, 0x8c, 0x09, 0xc1, + 0xba, 0x60, 0xf0, 0x2a, 0x6e, 0xba, 0xbf, 0x62, 0x1b, 0xfa, 0x6b, 0x5a, + 0x79, 0x47, 0x8d, 0x1a, 0x07, 0x76, 0xb6, 0xbe +}; +static const uint8_t nist_186_2_ecdsa_testvector_20_private[] = { +/* d */ + 0x00, 0x75, 0x29, 0x58, 0xa7, 0x9d, 0x6d, 0x45, 0x96, 0xc1, 0x01, 0xaa, + 0xe6, 0x06, 0x13, 0x9b, 0xc9, 0x02, 0xb0, 0x80, 0x8b, 0x94, 0x41, 0xa9, + 0xba, 0x48, 0xd6, 0xba +}; +static const uint8_t nist_186_2_ecdsa_testvector_20_public_x[] = { +/* Qx */ + 0x3b, 0x55, 0xbe, 0x3a, 0x8c, 0xc5, 0xc4, 0x70, 0x85, 0xab, 0x5d, 0x29, + 0xe3, 0xb6, 0xc2, 0x8e, 0x51, 0xe7, 0x4b, 0x79, 0xd1, 0xa8, 0x74, 0xb5, + 0xd7, 0xbb, 0xbb, 0x20 +}; +static const uint8_t nist_186_2_ecdsa_testvector_20_public_y[] = { +/* Qy */ + 0xae, 0xba, 0x7d, 0x2f, 0xf6, 0x7e, 0x2f, 0x68, 0x61, 0xe4, 0xde, 0x55, + 0x21, 0x16, 0xbd, 0xc1, 0xcf, 0xa4, 0xf1, 0x87, 0x14, 0x9d, 0x19, 0xab, + 0xd1, 0xac, 0xd7, 0x58 +}; +/* k = 009c2abc0d279dac6afb9dc33af8dc273e30c7e6e502347d076806bc */ +static const uint8_t nist_186_2_ecdsa_testvector_20_out[] = { +/* R */ + 0x3d, 0xa5, 0x22, 0xea, 0x72, 0xe2, 0x53, 0x2a, 0xa4, 0x39, 0x49, 0x29, + 0x91, 0x01, 0xd3, 0x12, 0x5c, 0xec, 0xc1, 0xbf, 0x45, 0x74, 0x7e, 0xe1, + 0xfd, 0x49, 0xde, 0xd8, +/* S */ + 0xf8, 0x22, 0x63, 0x83, 0x96, 0xa4, 0xc1, 0xd1, 0xd6, 0xa5, 0xec, 0xcf, + 0x89, 0xbd, 0x26, 0xf4, 0x24, 0x8b, 0xde, 0x68, 0x16, 0x31, 0xa2, 0x90, + 0xde, 0x7d, 0xb4, 0x12 +}; +static const uint8_t nist_186_2_ecdsa_testvector_21_ptx[] = { +/* Msg */ + 0xb5, 0x2a, 0xda, 0x0e, 0x56, 0xc5, 0xd6, 0xf5, 0x52, 0xfc, 0xea, 0xcd, + 0xd0, 0xaf, 0x88, 0x0f, 0xf4, 0xc2, 0x12, 0x65, 0x54, 0xc3, 0xf0, 0x69, + 0xac, 0xcd, 0xe1, 0xb0, 0xd2, 0xac, 0x8e, 0x07, 0xec, 0x41, 0x65, 0xfc, + 0xe0, 0x28, 0xa4, 0xa1, 0x0c, 0x99, 0xb4, 0x8c, 0x38, 0x8c, 0xb9, 0x22, + 0xc8, 0x21, 0x67, 0x16, 0x36, 0x3e, 0x17, 0x2c, 0xc0, 0x7a, 0x1a, 0x43, + 0x5e, 0x3a, 0x4d, 0x92, 0xf7, 0x19, 0xed, 0x32, 0xd4, 0x8e, 0xad, 0xdc, + 0x55, 0xc9, 0x06, 0xf5, 0xe3, 0xdd, 0xcf, 0xc7, 0x25, 0x24, 0x0d, 0x12, + 0x77, 0xdf, 0x0c, 0xc3, 0x98, 0x1e, 0xaf, 0x03, 0xa2, 0xe0, 0x04, 0x73, + 0x40, 0x7a, 0x1b, 0xb6, 0x1b, 0x3d, 0x19, 0x31, 0x95, 0x53, 0x88, 0x0e, + 0xba, 0xea, 0xf1, 0x87, 0x73, 0x95, 0xad, 0x61, 0xfd, 0xee, 0xf8, 0xb6, + 0x9a, 0x81, 0x47, 0xf8, 0x87, 0xe5, 0xdc, 0x33 +}; +static const uint8_t nist_186_2_ecdsa_testvector_21_private[] = { +/* d */ + 0x00, 0x37, 0x33, 0xe9, 0x2e, 0x47, 0xfb, 0x22, 0xc7, 0xa6, 0xc4, 0x5b, + 0xa5, 0x11, 0x5f, 0xcc, 0x4d, 0xb1, 0x64, 0xda, 0x56, 0xbc, 0x90, 0x52, + 0x93, 0x0a, 0xcc, 0xc4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_21_public_x[] = { +/* Qx */ + 0xf3, 0x46, 0x5d, 0xa1, 0x23, 0x8f, 0xa9, 0x59, 0xb4, 0xb5, 0x25, 0xb1, + 0x27, 0xb5, 0x3a, 0xbf, 0x0c, 0x9e, 0x29, 0x5d, 0xc8, 0x30, 0x87, 0x46, + 0x35, 0xc4, 0xcc, 0xd0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_21_public_y[] = { +/* Qy */ + 0xb4, 0x2a, 0xf0, 0xbb, 0x8f, 0xeb, 0x22, 0xd4, 0x88, 0x9e, 0xb3, 0xe4, + 0xfe, 0x25, 0x6d, 0x61, 0xbe, 0xb5, 0x0f, 0x02, 0xd7, 0x0e, 0x87, 0x50, + 0x71, 0xfc, 0x87, 0xa7 +}; +/* k = 0028761d9ab7ae71a3b0713e58d7fdf6c1f709f52c6313c21127cf83 */ +static const uint8_t nist_186_2_ecdsa_testvector_21_out[] = { +/* R */ + 0xd0, 0x20, 0x11, 0x39, 0x1f, 0xd3, 0x53, 0xb7, 0x72, 0xb3, 0xa3, 0xa7, + 0x2f, 0xc1, 0xe4, 0x0f, 0x9b, 0xe7, 0xd4, 0xa8, 0x6a, 0x54, 0x28, 0xf1, + 0x63, 0x4d, 0x6a, 0x30, +/* S */ + 0xfc, 0x55, 0x0f, 0x23, 0xca, 0x67, 0xbb, 0x08, 0x74, 0x21, 0x0f, 0xda, + 0x93, 0x44, 0xd4, 0x85, 0x3b, 0xa1, 0x14, 0xf5, 0x43, 0x69, 0x7a, 0x94, + 0x59, 0x4c, 0x96, 0xc2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_22_ptx[] = { +/* Msg */ + 0x24, 0xe3, 0xb4, 0x49, 0xe3, 0xb6, 0x48, 0xa4, 0xc3, 0x7c, 0x04, 0x88, + 0x15, 0xd1, 0x63, 0x8d, 0xda, 0x43, 0x0c, 0xd4, 0x85, 0x07, 0xb1, 0x52, + 0x02, 0xeb, 0x37, 0x6b, 0xf6, 0x8c, 0x17, 0xc3, 0x49, 0xc9, 0x04, 0x51, + 0xe2, 0x77, 0xce, 0xb5, 0xb1, 0x56, 0x86, 0xcb, 0xf3, 0x44, 0xe3, 0x80, + 0xb1, 0xb1, 0xe4, 0xe4, 0x8a, 0x53, 0xb7, 0x81, 0xb3, 0x1b, 0xda, 0xec, + 0x3c, 0x67, 0x80, 0x99, 0x95, 0x79, 0x36, 0xf3, 0x50, 0x28, 0xc6, 0xac, + 0x28, 0xd5, 0x5b, 0x52, 0x43, 0xa1, 0xe7, 0x24, 0xb4, 0xdd, 0xc2, 0x23, + 0x44, 0xc3, 0x94, 0x6c, 0x72, 0x63, 0x74, 0xc4, 0xb8, 0xdf, 0x51, 0x75, + 0x10, 0xdb, 0x91, 0x59, 0xb7, 0x30, 0xf9, 0x34, 0x31, 0xe0, 0xcd, 0x46, + 0x8d, 0x4f, 0x38, 0x21, 0xea, 0xb0, 0xed, 0xb9, 0x3a, 0xbd, 0x0f, 0xba, + 0x46, 0xab, 0x4f, 0x1e, 0xf3, 0x5d, 0x54, 0xfe +}; +static const uint8_t nist_186_2_ecdsa_testvector_22_private[] = { +/* d */ + 0x00, 0x59, 0x8f, 0xca, 0xbe, 0x59, 0x04, 0x52, 0xc6, 0x66, 0x6d, 0x0b, + 0xa3, 0xd1, 0x70, 0x7e, 0x94, 0x43, 0x49, 0xb5, 0x93, 0x06, 0x62, 0xbc, + 0xa6, 0x14, 0x17, 0x8a +}; +static const uint8_t nist_186_2_ecdsa_testvector_22_public_x[] = { +/* Qx */ + 0xe5, 0xf5, 0x82, 0x64, 0xc6, 0x51, 0xf8, 0x98, 0x19, 0x91, 0xcf, 0x8d, + 0xe0, 0xdb, 0xf9, 0x02, 0x35, 0xc3, 0x1c, 0x93, 0xa0, 0xa6, 0x3c, 0xe1, + 0xe4, 0x84, 0x91, 0x5b +}; +static const uint8_t nist_186_2_ecdsa_testvector_22_public_y[] = { +/* Qy */ + 0xf1, 0x62, 0x34, 0xcb, 0x01, 0x66, 0xa7, 0x31, 0x60, 0xb0, 0x5c, 0x31, + 0x4c, 0xc7, 0xa0, 0xc9, 0x47, 0x6e, 0x6f, 0xcf, 0x3b, 0xc1, 0x14, 0x6e, + 0xd1, 0x28, 0x81, 0xde +}; +/* k = 00fa783144e68bf30bf444a7b64b754f9b015c530970f8011d717b14 */ +static const uint8_t nist_186_2_ecdsa_testvector_22_out[] = { +/* R */ + 0x8f, 0x28, 0x56, 0xeb, 0xa0, 0x02, 0x4c, 0xc8, 0xaf, 0xbf, 0x17, 0x05, + 0xd0, 0xca, 0xb8, 0x10, 0x71, 0xb3, 0xb2, 0xb6, 0x2c, 0xac, 0x22, 0xa5, + 0x86, 0x1d, 0xb0, 0xad, +/* S */ + 0x66, 0x93, 0x65, 0x48, 0x9e, 0x79, 0x07, 0x63, 0x11, 0x2a, 0xf6, 0x28, + 0x8e, 0xa7, 0x3c, 0x04, 0x81, 0x02, 0xef, 0x5f, 0x60, 0xf3, 0x80, 0xb8, + 0xfc, 0xea, 0xb9, 0x13 +}; +static const uint8_t nist_186_2_ecdsa_testvector_23_ptx[] = { +/* Msg */ + 0xb2, 0xf1, 0x41, 0xd9, 0x6a, 0xd8, 0xa2, 0xb9, 0x03, 0xa8, 0x9e, 0xbc, + 0x51, 0xf7, 0x47, 0x3e, 0x94, 0x12, 0x86, 0x12, 0xa0, 0x91, 0x60, 0xbd, + 0x3b, 0x2f, 0x77, 0xe2, 0xc7, 0xd9, 0xd4, 0xfe, 0x21, 0x05, 0xe3, 0x56, + 0xc8, 0x45, 0xbf, 0x2d, 0x42, 0x1c, 0xb0, 0x39, 0xbb, 0x10, 0xf3, 0x58, + 0xf0, 0x00, 0xb9, 0x80, 0x4b, 0xb8, 0x71, 0xf4, 0x4f, 0xc3, 0x4a, 0xbe, + 0x37, 0x80, 0xf4, 0x59, 0xda, 0x79, 0xa7, 0xae, 0xd2, 0xef, 0x67, 0x42, + 0xdd, 0xba, 0x86, 0xad, 0x83, 0x50, 0x6a, 0x4e, 0xfa, 0x23, 0x91, 0x3d, + 0x46, 0x30, 0xd1, 0x81, 0xa4, 0xd4, 0xe5, 0x83, 0x29, 0xe2, 0x25, 0xc3, + 0xa7, 0xf4, 0x95, 0xca, 0xd0, 0xfe, 0x21, 0x60, 0x9e, 0x29, 0x27, 0xfe, + 0xf2, 0xde, 0x36, 0x86, 0x7b, 0x20, 0x16, 0x32, 0xd9, 0x20, 0x08, 0xca, + 0x02, 0x0b, 0x4e, 0x1b, 0xe5, 0x27, 0xee, 0xa4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_23_private[] = { +/* d */ + 0x00, 0x89, 0x6f, 0xd1, 0x04, 0x3a, 0x16, 0x83, 0x50, 0x40, 0x4d, 0xeb, + 0xd5, 0xec, 0x46, 0x14, 0xdb, 0x8f, 0x80, 0x30, 0x0c, 0x5b, 0x0e, 0xed, + 0x2f, 0xdf, 0xc8, 0x98 +}; +static const uint8_t nist_186_2_ecdsa_testvector_23_public_x[] = { +/* Qx */ + 0x04, 0x01, 0x59, 0x92, 0x28, 0x61, 0x33, 0xee, 0xf5, 0x4e, 0x6e, 0x91, + 0xec, 0xc5, 0x8c, 0x02, 0x1c, 0x25, 0x80, 0x61, 0x91, 0xbc, 0xf6, 0x68, + 0xf7, 0xf6, 0x51, 0x27 +}; +static const uint8_t nist_186_2_ecdsa_testvector_23_public_y[] = { +/* Qy */ + 0xa3, 0x2a, 0x50, 0xf2, 0x8e, 0x1a, 0x4f, 0x2f, 0x07, 0x64, 0x98, 0xf5, + 0x0b, 0xf2, 0x7c, 0x29, 0x11, 0x03, 0xf9, 0x93, 0xcb, 0x88, 0xce, 0xb4, + 0x5a, 0xc5, 0x50, 0xcb +}; +/* k = 003c00f713e3a2fef78bcd9e534e61fe199faa7238974d118407c820 */ +static const uint8_t nist_186_2_ecdsa_testvector_23_out[] = { +/* R */ + 0x4a, 0x3b, 0x1d, 0x8f, 0x1d, 0x22, 0x4b, 0x34, 0x91, 0xc7, 0xd3, 0xaf, + 0x16, 0x0a, 0xce, 0x4d, 0xa3, 0xb5, 0xda, 0x16, 0xe7, 0x7d, 0x9f, 0x8b, + 0xcd, 0x19, 0x59, 0x2d, +/* S */ + 0x43, 0x53, 0xc4, 0xd8, 0x70, 0x53, 0xd7, 0x8c, 0x82, 0x1d, 0x29, 0xba, + 0x92, 0x6b, 0xb0, 0x04, 0x42, 0x16, 0x98, 0x75, 0xb9, 0xd9, 0x56, 0x18, + 0xf9, 0x35, 0x01, 0x52 +}; +static const uint8_t nist_186_2_ecdsa_testvector_24_ptx[] = { +/* Msg */ + 0xbc, 0x64, 0x29, 0x91, 0x65, 0x35, 0x8e, 0x19, 0xe5, 0xac, 0x85, 0x5c, + 0xdf, 0xab, 0xfb, 0xe6, 0xc7, 0xae, 0x09, 0xb4, 0xac, 0x50, 0x6f, 0xe0, + 0x54, 0x11, 0x3e, 0x80, 0x8e, 0x56, 0xd4, 0xcb, 0xc4, 0xb1, 0x0d, 0x7d, + 0xd0, 0x63, 0xb8, 0x7d, 0x10, 0x1f, 0x48, 0xbd, 0xbd, 0x11, 0xcc, 0x62, + 0x78, 0x1f, 0x22, 0x26, 0x26, 0x6f, 0x67, 0xfa, 0xfe, 0x29, 0xb1, 0xef, + 0xe0, 0x7e, 0x01, 0x56, 0xe9, 0xe9, 0x73, 0x26, 0x44, 0xb4, 0xb8, 0x9f, + 0x43, 0xbf, 0xc6, 0x2d, 0xae, 0x7d, 0xce, 0x8f, 0x5b, 0x3f, 0x6f, 0x38, + 0xfe, 0xb5, 0x29, 0xf6, 0x43, 0xb1, 0x14, 0xd1, 0x1a, 0x2f, 0xd2, 0x36, + 0x52, 0x93, 0xc2, 0x55, 0x6a, 0x31, 0x76, 0xc7, 0xa4, 0x12, 0x68, 0x74, + 0x5a, 0xf5, 0xe8, 0xb4, 0x95, 0x95, 0x59, 0xb4, 0xdc, 0x2a, 0x9d, 0x1c, + 0x4a, 0x32, 0xce, 0xee, 0xe4, 0x71, 0x2f, 0xb1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_24_private[] = { +/* d */ + 0x00, 0x9c, 0x31, 0x01, 0x80, 0x60, 0x9c, 0x72, 0x1a, 0x55, 0x31, 0xcf, + 0x4e, 0x43, 0x8b, 0xf3, 0xc8, 0x5e, 0xf2, 0xb2, 0xff, 0xea, 0xc9, 0xa2, + 0x1c, 0x66, 0x7d, 0x0e +}; +static const uint8_t nist_186_2_ecdsa_testvector_24_public_x[] = { +/* Qx */ + 0xcc, 0x60, 0x2a, 0x85, 0x82, 0x76, 0xf9, 0x44, 0xbc, 0xcc, 0xa2, 0xac, + 0xbb, 0xd8, 0xc9, 0x51, 0x8b, 0x3c, 0xd9, 0xf0, 0x62, 0xe4, 0x80, 0x2e, + 0x34, 0x27, 0x80, 0xd7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_24_public_y[] = { +/* Qy */ + 0x56, 0x50, 0xef, 0xed, 0xdb, 0xce, 0x1c, 0x00, 0xf5, 0x06, 0xa3, 0xf8, + 0x8a, 0x8f, 0x57, 0x66, 0x94, 0x05, 0xe3, 0x44, 0x90, 0x1c, 0xfb, 0x51, + 0xce, 0x54, 0xc1, 0x5f +}; +/* k = 00ef15cd8173fa27a393be6b1e1253aaee433b24e8a4d448a960679e */ +static const uint8_t nist_186_2_ecdsa_testvector_24_out[] = { +/* R */ + 0x73, 0x74, 0xf7, 0xdf, 0x8e, 0x9e, 0x6b, 0x2b, 0xcb, 0x4e, 0x82, 0x25, + 0x8a, 0x0f, 0xa8, 0xb1, 0x36, 0xb9, 0x3a, 0xba, 0x18, 0xa5, 0x3a, 0x79, + 0xe8, 0xc8, 0xe8, 0x97, +/* S */ + 0xa4, 0xa5, 0xda, 0x18, 0xcb, 0xb9, 0x87, 0xe4, 0x8a, 0x80, 0xa7, 0x3b, + 0xd6, 0x9b, 0xe3, 0x78, 0xce, 0x47, 0x6f, 0xbb, 0xda, 0x64, 0x68, 0xc4, + 0xa4, 0x9b, 0x72, 0x19 +}; +static const uint8_t nist_186_2_ecdsa_testvector_25_ptx[] = { +/* Msg */ + 0x11, 0xd4, 0x34, 0x4d, 0xca, 0xa9, 0xf6, 0x7c, 0x16, 0x79, 0xac, 0x2f, + 0xbf, 0x77, 0x05, 0x66, 0x94, 0xc5, 0xf2, 0x5e, 0xb2, 0x9f, 0x0a, 0x62, + 0x02, 0xd7, 0x2c, 0xe4, 0x03, 0x81, 0x66, 0xcc, 0xca, 0xef, 0x15, 0x10, + 0x47, 0xe0, 0x4e, 0x85, 0xc9, 0xf4, 0x7d, 0xf5, 0xc4, 0x63, 0x4c, 0x71, + 0xd3, 0xef, 0xc7, 0xe8, 0xf9, 0x17, 0xbd, 0xf9, 0x2c, 0x8e, 0x69, 0x06, + 0x14, 0xeb, 0x51, 0x8a, 0x10, 0xa2, 0x6f, 0xac, 0x7a, 0x33, 0x8f, 0x14, + 0x2c, 0xa1, 0xf8, 0xfd, 0x42, 0x26, 0x4e, 0x8b, 0x22, 0x25, 0xb7, 0x5f, + 0xba, 0x60, 0x3d, 0x6a, 0x09, 0x6b, 0x74, 0xfe, 0xe1, 0x61, 0x5c, 0x2b, + 0xeb, 0xd5, 0x88, 0x48, 0xeb, 0x0b, 0x80, 0xd0, 0x45, 0x68, 0x65, 0x70, + 0xc1, 0x28, 0xd3, 0x5d, 0x8b, 0x4f, 0x0b, 0xeb, 0x7e, 0xe2, 0x52, 0x5c, + 0xa1, 0x56, 0x94, 0xf5, 0xf2, 0x49, 0x4d, 0x58 +}; +static const uint8_t nist_186_2_ecdsa_testvector_25_private[] = { +/* d */ + 0x00, 0xa1, 0x40, 0xa5, 0x09, 0x60, 0x19, 0xe8, 0xf5, 0x5b, 0xd2, 0xdf, + 0x13, 0x38, 0xb2, 0x93, 0xf7, 0xf6, 0x10, 0x06, 0x8e, 0x75, 0x63, 0x2d, + 0xdf, 0xcb, 0x88, 0x3d +}; +static const uint8_t nist_186_2_ecdsa_testvector_25_public_x[] = { +/* Qx */ + 0x54, 0x4b, 0xf0, 0x8e, 0x35, 0xff, 0xa3, 0xc9, 0x60, 0x55, 0x3c, 0x97, + 0x23, 0xee, 0x70, 0x97, 0xb7, 0xdf, 0xaa, 0xe0, 0x59, 0xad, 0xcc, 0xf2, + 0xda, 0x75, 0x29, 0x9b +}; +static const uint8_t nist_186_2_ecdsa_testvector_25_public_y[] = { +/* Qy */ + 0x99, 0x9d, 0xae, 0x3a, 0x21, 0x78, 0x2c, 0xc2, 0x1b, 0xa3, 0xa5, 0x01, + 0x81, 0xdc, 0x7e, 0x67, 0xb8, 0xd7, 0x96, 0x0f, 0x9d, 0x58, 0xd0, 0x94, + 0xa3, 0xb1, 0x41, 0xef +}; +/* k = 00aef6a43f3f219a611e8e1994cb408ec71f05fb6f9af347a6b29284 */ +static const uint8_t nist_186_2_ecdsa_testvector_25_out[] = { +/* R */ + 0x5b, 0xf0, 0x15, 0x53, 0xdb, 0x59, 0xeb, 0x45, 0x30, 0xe7, 0x21, 0x57, + 0xd3, 0x9f, 0x03, 0xda, 0xb9, 0x16, 0x7f, 0xfd, 0x0d, 0xf3, 0xab, 0xb7, + 0x4d, 0x82, 0x2f, 0xdf, +/* S */ + 0x0c, 0x10, 0x4e, 0x52, 0x01, 0x8d, 0xfb, 0xdd, 0x53, 0x86, 0xdd, 0xb9, + 0x59, 0x9b, 0x41, 0xab, 0xf2, 0x10, 0x77, 0x08, 0xa3, 0xdc, 0x86, 0xb3, + 0x5f, 0x68, 0xdc, 0x1c +}; +static const uint8_t nist_186_2_ecdsa_testvector_26_ptx[] = { +/* Msg */ + 0x00, 0x3b, 0x64, 0x8e, 0x92, 0xb1, 0xc1, 0x7b, 0x00, 0x08, 0x1c, 0x88, + 0xb5, 0x8b, 0xe2, 0x85, 0x16, 0xa3, 0x2e, 0x2c, 0xc1, 0x02, 0x31, 0xfa, + 0x12, 0x22, 0xd7, 0x3d, 0xec, 0xee, 0xa7, 0x6d, 0xb6, 0xbf, 0xec, 0xbf, + 0xa3, 0x89, 0x12, 0xf8, 0x37, 0x57, 0x52, 0x7f, 0x07, 0xf4, 0x92, 0xb7, + 0xc0, 0xeb, 0x86, 0x8b, 0x6a, 0xb2, 0x1c, 0x4b, 0xee, 0x23, 0x17, 0xb6, + 0xd6, 0x2b, 0xf9, 0x58, 0x55, 0xc6, 0x27, 0x16, 0x87, 0x2b, 0x48, 0x07, + 0xf9, 0x43, 0xee, 0x85, 0x6c, 0x60, 0x78, 0x84, 0xd6, 0x2c, 0x37, 0x23, + 0xaa, 0xe0, 0xcf, 0x81, 0x59, 0xb6, 0xe0, 0xd2, 0x19, 0xa0, 0xe6, 0xb2, + 0xe5, 0x3a, 0x5e, 0xb8, 0xc5, 0xfd, 0x2b, 0x4f, 0x4f, 0xb6, 0x37, 0xc1, + 0x6e, 0x37, 0x5d, 0x95, 0x62, 0x4d, 0x87, 0x1b, 0x08, 0xf2, 0x13, 0x45, + 0x5c, 0xc3, 0x7c, 0xb8, 0x3c, 0xb4, 0x36, 0x23 +}; +static const uint8_t nist_186_2_ecdsa_testvector_26_private[] = { +/* d */ + 0x00, 0xa6, 0x1b, 0x96, 0x9a, 0x0b, 0xf6, 0x52, 0x77, 0xfb, 0x7f, 0x87, + 0x96, 0x27, 0x85, 0x54, 0xf1, 0x35, 0x0c, 0xe8, 0x2a, 0xfa, 0x1d, 0x5f, + 0xf4, 0xcf, 0x3a, 0x5f +}; +static const uint8_t nist_186_2_ecdsa_testvector_26_public_x[] = { +/* Qx */ + 0xb4, 0x8b, 0x95, 0x85, 0xbd, 0xfa, 0x5a, 0xd9, 0x02, 0xd3, 0xd9, 0x13, + 0x17, 0xcf, 0x1a, 0xae, 0x9a, 0x17, 0x5d, 0x39, 0x36, 0x4a, 0x18, 0xe5, + 0xdd, 0x9e, 0x13, 0x3d +}; +static const uint8_t nist_186_2_ecdsa_testvector_26_public_y[] = { +/* Qy */ + 0xb0, 0x34, 0x26, 0xdc, 0x86, 0x60, 0x54, 0x3e, 0x13, 0xbe, 0xe6, 0x66, + 0x0b, 0x43, 0xc4, 0x53, 0xfb, 0x1c, 0x7a, 0x13, 0xa8, 0x47, 0xe9, 0x8a, + 0x5d, 0x9b, 0xb0, 0x38 +}; +/* k = 00eddd21ff4e5da2e04a0c66214ad732ecd7521472e921646cde719f */ +static const uint8_t nist_186_2_ecdsa_testvector_26_out[] = { +/* R */ + 0x70, 0x7c, 0xf9, 0x6d, 0xe2, 0x3f, 0x84, 0xdc, 0x98, 0x73, 0x51, 0x59, + 0x9b, 0x63, 0xbc, 0x16, 0xcb, 0x6a, 0xa8, 0x76, 0xfc, 0xeb, 0xde, 0xfb, + 0xdc, 0xc4, 0x0e, 0xee, +/* S */ + 0xdd, 0x71, 0xfb, 0xb5, 0xbc, 0xe1, 0x8e, 0x00, 0x41, 0xc8, 0x67, 0xd5, + 0x77, 0x27, 0x1b, 0x67, 0x83, 0x2c, 0x13, 0x99, 0x01, 0xc7, 0x19, 0x4c, + 0x50, 0xaa, 0x94, 0xed +}; +static const uint8_t nist_186_2_ecdsa_testvector_27_ptx[] = { +/* Msg */ + 0x64, 0x53, 0xfe, 0x08, 0x7d, 0x56, 0x4e, 0x4b, 0x5a, 0x0e, 0x7f, 0xf5, + 0xe7, 0x05, 0xfb, 0x96, 0x02, 0xf4, 0xb0, 0x33, 0x30, 0x9b, 0x67, 0x47, + 0x8e, 0xf1, 0x51, 0x08, 0x0b, 0x7d, 0xe3, 0xeb, 0xd5, 0x04, 0xe4, 0x6a, + 0x11, 0x64, 0xc5, 0x05, 0xcf, 0xc0, 0x30, 0x87, 0x3d, 0xdd, 0xe3, 0x8a, + 0x1a, 0xcc, 0xbf, 0x3d, 0x6e, 0xca, 0x1c, 0x65, 0x79, 0x64, 0x60, 0xa2, + 0xe9, 0xdf, 0xd0, 0xf4, 0x50, 0xd6, 0xa6, 0x7d, 0xd4, 0x25, 0x63, 0x89, + 0x29, 0x06, 0x66, 0xcb, 0xbc, 0x7a, 0xbe, 0xe9, 0x31, 0xeb, 0x3d, 0x3c, + 0x10, 0x0f, 0xcd, 0xd1, 0xbb, 0x0f, 0x07, 0xb3, 0xa4, 0xe9, 0x02, 0x6c, + 0xbc, 0x13, 0x69, 0xc9, 0x2f, 0x61, 0xd1, 0xde, 0x4e, 0x28, 0x49, 0x4a, + 0xcc, 0xa4, 0x32, 0xbc, 0x2e, 0x97, 0x51, 0xb6, 0x7d, 0x33, 0x22, 0x91, + 0x3e, 0x3a, 0x6f, 0xc2, 0xa4, 0x64, 0x22, 0x5b +}; +static const uint8_t nist_186_2_ecdsa_testvector_27_private[] = { +/* d */ + 0x00, 0x82, 0x6f, 0xb0, 0xab, 0x78, 0xdd, 0x5a, 0x83, 0x46, 0x87, 0x27, + 0xa9, 0x3b, 0x46, 0x54, 0xe6, 0x14, 0x23, 0xb5, 0x86, 0xe3, 0xe1, 0x92, + 0x01, 0x02, 0x83, 0xa3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_27_public_x[] = { +/* Qx */ + 0xdc, 0x20, 0xb9, 0x84, 0xeb, 0x64, 0x63, 0x43, 0x67, 0x9e, 0x82, 0x99, + 0x76, 0x34, 0x16, 0xcb, 0x9a, 0xf2, 0x7f, 0xae, 0x39, 0xf2, 0x97, 0xda, + 0x3c, 0xdb, 0x93, 0x4f +}; +static const uint8_t nist_186_2_ecdsa_testvector_27_public_y[] = { +/* Qy */ + 0x0e, 0x63, 0xb6, 0xfd, 0x5e, 0x0a, 0x2f, 0x79, 0xac, 0xc5, 0x00, 0x4c, + 0x21, 0x20, 0xec, 0xaa, 0x57, 0xf5, 0x5b, 0x39, 0x93, 0xc7, 0xc2, 0x7e, + 0xfa, 0xea, 0x58, 0x1a +}; +/* k = 002d50bff84a4a955fe094199cdae4e897ee985b8e15bb2174cf041a */ +static const uint8_t nist_186_2_ecdsa_testvector_27_out[] = { +/* R */ + 0x1b, 0xf7, 0xad, 0xa1, 0x49, 0x36, 0xa7, 0x41, 0x1e, 0x29, 0x72, 0x5d, + 0x86, 0x7e, 0x1f, 0x5c, 0x88, 0xea, 0xd2, 0xe4, 0xee, 0xa3, 0x6e, 0x4a, + 0x8e, 0x2e, 0x7b, 0x89, +/* S */ + 0x9e, 0xe1, 0x5f, 0xfe, 0xdb, 0x03, 0x54, 0x9e, 0xb2, 0xf5, 0xaa, 0xb0, + 0xeb, 0xfe, 0x33, 0x5b, 0xb3, 0x5e, 0xa3, 0x25, 0xd0, 0xaf, 0x71, 0xde, + 0xdd, 0x82, 0xe9, 0x0c +}; +static const uint8_t nist_186_2_ecdsa_testvector_28_ptx[] = { +/* Msg */ + 0x33, 0xd8, 0x76, 0xe7, 0xe5, 0x6b, 0x0a, 0x84, 0x43, 0xf1, 0xdc, 0x28, + 0x4b, 0x41, 0xf3, 0x0d, 0x5a, 0x13, 0xb9, 0x49, 0x43, 0xc2, 0xab, 0xad, + 0x9f, 0x51, 0x55, 0xee, 0x65, 0xad, 0x7e, 0x02, 0xbb, 0x31, 0xa0, 0xcd, + 0x0b, 0x6f, 0x9b, 0xfd, 0x58, 0x2e, 0xa9, 0x33, 0xd3, 0xaf, 0x95, 0x63, + 0xa9, 0x35, 0x28, 0x7d, 0x20, 0xc3, 0xe5, 0x4d, 0xe2, 0x28, 0xf6, 0xa0, + 0x98, 0x39, 0x65, 0xa8, 0xbb, 0x5e, 0x8f, 0xa1, 0xa7, 0x50, 0xd6, 0xb5, + 0xf2, 0x20, 0x97, 0x1d, 0xfb, 0x7c, 0x5c, 0x8a, 0xc6, 0x2e, 0x52, 0xc3, + 0x07, 0xe5, 0xfd, 0x8f, 0x7c, 0x38, 0x2a, 0xd5, 0x80, 0xe8, 0x25, 0x02, + 0xde, 0x65, 0x2d, 0xab, 0xe3, 0x94, 0x25, 0x74, 0xb7, 0xd0, 0x8c, 0x30, + 0xed, 0x2f, 0xaf, 0x49, 0x58, 0x06, 0x1d, 0x62, 0x20, 0xaf, 0x5c, 0x3c, + 0x16, 0x89, 0xda, 0xd6, 0x45, 0x41, 0x26, 0xd9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_28_private[] = { +/* d */ + 0x00, 0x77, 0x4f, 0x99, 0x59, 0xf4, 0x42, 0xd4, 0x8b, 0x56, 0x2d, 0xe2, + 0x4a, 0xe2, 0x52, 0x85, 0x75, 0x6e, 0xc1, 0x5c, 0xe0, 0x72, 0x25, 0xf1, + 0x5c, 0x00, 0x7c, 0x6d +}; +static const uint8_t nist_186_2_ecdsa_testvector_28_public_x[] = { +/* Qx */ + 0x75, 0x16, 0xee, 0xb4, 0xdb, 0x63, 0x1f, 0x0f, 0xd6, 0xfd, 0xe7, 0x01, + 0xaa, 0x18, 0x93, 0xad, 0x11, 0x55, 0x91, 0xe3, 0x7c, 0xdf, 0xcc, 0x52, + 0xb7, 0x14, 0xe7, 0x78 +}; +static const uint8_t nist_186_2_ecdsa_testvector_28_public_y[] = { +/* Qy */ + 0x62, 0xe0, 0x16, 0x48, 0x83, 0xb2, 0x3c, 0xc4, 0xf4, 0xd5, 0xe0, 0x6e, + 0x76, 0x60, 0x70, 0xe8, 0x6f, 0xe3, 0x77, 0xf1, 0x2d, 0xbe, 0xc4, 0x6e, + 0xaf, 0xe5, 0xf4, 0xe2 +}; +/* k = 0060d4854bfc3ddf0ace90c4c4c6476cba853c4ebf3e54bab9bc2352 */ +static const uint8_t nist_186_2_ecdsa_testvector_28_out[] = { +/* R */ + 0xd2, 0x7f, 0xf0, 0x94, 0x80, 0x87, 0x87, 0xc7, 0x64, 0x95, 0xaf, 0x70, + 0x41, 0x94, 0x26, 0x14, 0x9e, 0xc1, 0x10, 0x59, 0xcd, 0xd3, 0x9f, 0x25, + 0x81, 0xb8, 0xd1, 0x35, +/* S */ + 0xf4, 0x50, 0xa1, 0x27, 0x74, 0xd1, 0xa9, 0xc8, 0x43, 0xe7, 0x6e, 0xc1, + 0xa2, 0x4f, 0xe1, 0x50, 0x64, 0xb2, 0x1a, 0xd2, 0xbc, 0xda, 0x9d, 0xfb, + 0x0c, 0xf6, 0xfd, 0x2c +}; +static const uint8_t nist_186_2_ecdsa_testvector_29_ptx[] = { +/* Msg */ + 0x72, 0x10, 0xe8, 0x79, 0xeb, 0xd1, 0x5f, 0x29, 0xdd, 0x3f, 0x8e, 0x6e, + 0xd6, 0x39, 0x29, 0x3e, 0xc7, 0x82, 0x3b, 0x82, 0xc3, 0x6f, 0x10, 0x6e, + 0x04, 0xe3, 0x52, 0x0e, 0x2f, 0x7d, 0x72, 0x22, 0xd8, 0x10, 0x49, 0x2c, + 0x49, 0x54, 0x00, 0xc7, 0x7f, 0xdb, 0x2d, 0x3a, 0x76, 0x46, 0x3e, 0x4d, + 0xa7, 0xb8, 0x1b, 0x5c, 0xce, 0x8b, 0x07, 0xa9, 0xf0, 0x42, 0xc7, 0xf6, + 0x9d, 0xbf, 0x07, 0x54, 0x73, 0xb7, 0xf9, 0x36, 0xe3, 0x62, 0x3f, 0xc9, + 0x38, 0x77, 0x0b, 0x88, 0xd4, 0x57, 0x85, 0x0b, 0xbd, 0x88, 0x6d, 0x1f, + 0x59, 0x66, 0x01, 0x1c, 0x76, 0x15, 0x21, 0x73, 0x8d, 0xba, 0xb1, 0x87, + 0x48, 0xeb, 0x3f, 0xbe, 0x41, 0x64, 0xe5, 0xd7, 0x0d, 0xfb, 0x71, 0x7e, + 0x79, 0xd6, 0xc4, 0x1d, 0x13, 0xdb, 0x78, 0xf6, 0xed, 0x68, 0xc6, 0x6f, + 0x9d, 0x44, 0xa6, 0xac, 0x88, 0xd6, 0x37, 0x63 +}; +static const uint8_t nist_186_2_ecdsa_testvector_29_private[] = { +/* d */ + 0x00, 0x18, 0x0c, 0xe8, 0x83, 0xf0, 0x2d, 0xa5, 0x2f, 0x1c, 0xfe, 0xf7, + 0xf8, 0x6a, 0x74, 0xcc, 0x38, 0x09, 0x92, 0x35, 0x95, 0x07, 0x4b, 0x1c, + 0x3e, 0x4d, 0xbd, 0x67 +}; +static const uint8_t nist_186_2_ecdsa_testvector_29_public_x[] = { +/* Qx */ + 0x3e, 0x44, 0x09, 0xba, 0xa7, 0x81, 0x7f, 0x25, 0xc6, 0x94, 0xa4, 0xe6, + 0x5e, 0x70, 0x45, 0xe1, 0x24, 0xea, 0x0c, 0xef, 0x54, 0x82, 0x69, 0xfd, + 0xc9, 0xd7, 0x33, 0x98 +}; +static const uint8_t nist_186_2_ecdsa_testvector_29_public_y[] = { +/* Qy */ + 0x9d, 0x91, 0x56, 0x8f, 0x03, 0x8a, 0x43, 0xad, 0x6a, 0x0a, 0x91, 0xb4, + 0x24, 0x76, 0x36, 0x9c, 0xcc, 0x67, 0xcd, 0xd8, 0x8b, 0x16, 0xf7, 0x1c, + 0x09, 0xd9, 0xe0, 0x0a +}; +/* k = 00ad38800026a494128dab55dcd2ab1f2ffa6ff2f35b619ccc34a7ae */ +static const uint8_t nist_186_2_ecdsa_testvector_29_out[] = { +/* R */ + 0x67, 0x6d, 0x6f, 0x6a, 0x3f, 0xa6, 0x1b, 0xf0, 0xf3, 0xcf, 0x5f, 0x74, + 0x47, 0x56, 0x3d, 0xf1, 0x01, 0x36, 0x1f, 0x9b, 0x09, 0x18, 0x13, 0x34, + 0x17, 0x9e, 0xf6, 0xce, +/* S */ + 0x06, 0x86, 0x51, 0x78, 0x15, 0xbd, 0xb6, 0xec, 0xe3, 0xbd, 0xa2, 0x57, + 0xa8, 0x21, 0xa6, 0xb7, 0x24, 0x99, 0x31, 0xe5, 0xcc, 0xd5, 0x75, 0x33, + 0x2f, 0x77, 0xd3, 0x58 +}; +static const uint8_t nist_186_2_ecdsa_testvector_30_ptx[] = { +/* Msg */ + 0x22, 0x8e, 0xdf, 0xde, 0xfb, 0x8c, 0x90, 0x11, 0xd4, 0xe6, 0x13, 0x0f, + 0x81, 0x30, 0x7f, 0x29, 0x57, 0x7b, 0x73, 0x12, 0x92, 0x27, 0x9c, 0x4f, + 0xf4, 0xf9, 0x7d, 0xe9, 0xaf, 0x6d, 0x6f, 0x65, 0x85, 0x4e, 0xe6, 0xf5, + 0x2e, 0x83, 0xf7, 0xf0, 0xfa, 0x2c, 0x17, 0x80, 0xb7, 0xee, 0x26, 0x9b, + 0xd5, 0x8a, 0xac, 0x34, 0xc8, 0xb5, 0x62, 0xb2, 0xae, 0x24, 0xf4, 0xa1, + 0x32, 0xe6, 0x05, 0xa7, 0xb0, 0xf6, 0x73, 0xba, 0x9a, 0x11, 0xdd, 0x91, + 0x1a, 0xc5, 0x63, 0x58, 0xf8, 0xcb, 0xad, 0xa8, 0xbf, 0x96, 0x2f, 0xb6, + 0x1b, 0x2c, 0xab, 0xcb, 0x86, 0x35, 0xf7, 0xf4, 0x23, 0x51, 0x00, 0xfa, + 0xea, 0xaf, 0x0f, 0x94, 0x06, 0xdc, 0x4b, 0xdc, 0x7b, 0xd8, 0x80, 0x00, + 0x0c, 0x6f, 0x1e, 0x3a, 0x5c, 0xc6, 0x85, 0x02, 0x53, 0x35, 0x7f, 0x82, + 0xc3, 0x54, 0x0e, 0x4a, 0x4c, 0x59, 0x69, 0x45 +}; +static const uint8_t nist_186_2_ecdsa_testvector_30_private[] = { +/* d */ + 0x00, 0xb3, 0x58, 0x49, 0x19, 0x16, 0x7e, 0x95, 0x90, 0xba, 0xe8, 0xad, + 0x6f, 0x77, 0x00, 0x80, 0xff, 0xc4, 0x82, 0x05, 0x74, 0x43, 0xd2, 0x65, + 0x5c, 0xbf, 0x98, 0xbe +}; +static const uint8_t nist_186_2_ecdsa_testvector_30_public_x[] = { +/* Qx */ + 0x25, 0x2c, 0xfd, 0xa1, 0xf1, 0xf2, 0xba, 0x7a, 0x78, 0xeb, 0x7a, 0xb2, + 0xad, 0xab, 0x3d, 0x12, 0xee, 0x83, 0x0c, 0xd0, 0xe8, 0x27, 0xd6, 0x06, + 0x35, 0xa8, 0x36, 0x14 +}; +static const uint8_t nist_186_2_ecdsa_testvector_30_public_y[] = { +/* Qy */ + 0xca, 0x74, 0x65, 0xc5, 0xfd, 0x9a, 0xd0, 0x7f, 0xdf, 0x54, 0x60, 0xab, + 0xcd, 0x94, 0xda, 0x23, 0xe2, 0xee, 0x52, 0x0c, 0xfb, 0xde, 0xf8, 0xeb, + 0x66, 0xcc, 0x0b, 0xfc +}; +/* k = 00d070665ffa8ae33a3662250aaf9b9a84aa611f2854205555febc4f */ +static const uint8_t nist_186_2_ecdsa_testvector_30_out[] = { +/* R */ + 0xa8, 0x17, 0x6f, 0x87, 0x56, 0xa2, 0xfc, 0xc7, 0x3a, 0xd7, 0x99, 0x49, + 0x8c, 0xc3, 0xfa, 0x7c, 0xd3, 0x47, 0x46, 0x65, 0x0c, 0x7f, 0xfc, 0x15, + 0xb2, 0xd0, 0xa4, 0xe0, +/* S */ + 0xbc, 0xdb, 0x21, 0x90, 0x02, 0x83, 0x62, 0xbe, 0x80, 0x3d, 0x77, 0x6d, + 0xcb, 0x6d, 0xc2, 0xaa, 0xfc, 0xd0, 0xbf, 0x99, 0x97, 0xe7, 0x42, 0x5f, + 0x3e, 0x05, 0xdd, 0xf6 +}; +/* [P-256] */ +static const uint8_t nist_186_2_ecdsa_testvector_31_ptx[] = { +/* Msg */ + 0x5f, 0xf1, 0xfa, 0x17, 0xc2, 0xa6, 0x7c, 0xe5, 0x99, 0xa3, 0x46, 0x88, + 0xf6, 0xfb, 0x2d, 0x4a, 0x8a, 0xf1, 0x75, 0x32, 0xd1, 0x5f, 0xa1, 0x86, + 0x8a, 0x59, 0x8a, 0x8e, 0x6a, 0x0d, 0xaf, 0x9b, 0x11, 0xed, 0xcc, 0x48, + 0x3d, 0x11, 0xae, 0x00, 0x3e, 0xd6, 0x45, 0xc0, 0xaa, 0xcc, 0xfb, 0x1e, + 0x51, 0xcf, 0x44, 0x8b, 0x73, 0x73, 0x76, 0xd5, 0x31, 0xa6, 0xdc, 0xf0, + 0x42, 0x90, 0x05, 0xf5, 0xe7, 0xbe, 0x62, 0x6b, 0x21, 0x80, 0x11, 0xc6, + 0x21, 0x8f, 0xf3, 0x2d, 0x00, 0xf3, 0x04, 0x80, 0xb0, 0x24, 0xec, 0x9a, + 0x33, 0x70, 0xd1, 0xd3, 0x0a, 0x9c, 0x70, 0xc9, 0xf1, 0xce, 0x6c, 0x61, + 0xc9, 0xab, 0xe5, 0x08, 0xd6, 0xbc, 0x4d, 0x3f, 0x2a, 0x16, 0x77, 0x56, + 0x61, 0x3a, 0xf1, 0x77, 0x8f, 0x3a, 0x94, 0xe7, 0x77, 0x1d, 0x59, 0x89, + 0xfe, 0x85, 0x6f, 0xa4, 0xdf, 0x8f, 0x8a, 0xe5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_31_private[] = { +/* d */ + 0x00, 0x2a, 0x10, 0xb1, 0xb5, 0xb9, 0xfa, 0x0b, 0x78, 0xd3, 0x8e, 0xd2, + 0x9c, 0xd9, 0xce, 0xc1, 0x85, 0x20, 0xe0, 0xfe, 0x93, 0x02, 0x3e, 0x35, + 0x50, 0xbb, 0x71, 0x63, 0xab, 0x49, 0x05, 0xc6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_31_public_x[] = { +/* Qx */ + 0xe9, 0xcd, 0x2e, 0x8f, 0x15, 0xbd, 0x90, 0xcb, 0x07, 0x07, 0xe0, 0x5e, + 0xd3, 0xb6, 0x01, 0xaa, 0xce, 0x7e, 0xf5, 0x71, 0x42, 0xa6, 0x46, 0x61, + 0xea, 0x1d, 0xd7, 0x19, 0x9e, 0xbb, 0xa9, 0xac +}; +static const uint8_t nist_186_2_ecdsa_testvector_31_public_y[] = { +/* Qy */ + 0xc9, 0x6b, 0x01, 0x15, 0xbe, 0xd1, 0xc1, 0x34, 0xb6, 0x8f, 0x89, 0x58, + 0x4b, 0x04, 0x0a, 0x19, 0x4b, 0xfa, 0xd9, 0x4a, 0x40, 0x4f, 0xdb, 0x37, + 0xad, 0xad, 0x10, 0x7d, 0x5a, 0x0b, 0x4c, 0x5e +}; +/* k = 00c2815763d7fcb2480b39d154abc03f616f0404e11272d624e825432687092a */ +static const uint8_t nist_186_2_ecdsa_testvector_31_out[] = { +/* R */ + 0x15, 0xbf, 0x46, 0x93, 0x7c, 0x7a, 0x1e, 0x2f, 0xa7, 0xad, 0xc6, 0x5c, + 0x89, 0xfe, 0x03, 0xae, 0x60, 0x2d, 0xd7, 0xdf, 0xa6, 0x72, 0x2c, 0xda, + 0xfa, 0x92, 0xd6, 0x24, 0xb3, 0x2b, 0x15, 0x6e, +/* S */ + 0x59, 0xc5, 0x91, 0x79, 0x2e, 0xe9, 0x4f, 0x0b, 0x20, 0x2e, 0x7a, 0x59, + 0x0e, 0x70, 0xd0, 0x1d, 0xd8, 0xa9, 0x77, 0x48, 0x84, 0xe2, 0xb5, 0xba, + 0x99, 0x45, 0x43, 0x7c, 0xfe, 0xd0, 0x16, 0x86 +}; +static const uint8_t nist_186_2_ecdsa_testvector_32_ptx[] = { +/* Msg */ + 0x05, 0xa0, 0x5b, 0xb2, 0x88, 0x29, 0xcf, 0x6f, 0x43, 0x5c, 0x42, 0x2c, + 0x09, 0x57, 0xb1, 0x03, 0x59, 0x27, 0x42, 0x93, 0x27, 0x80, 0x26, 0x53, + 0xdf, 0xb1, 0xc3, 0x25, 0xa8, 0xd8, 0x13, 0x2f, 0xe6, 0x52, 0x47, 0xe6, + 0x02, 0x76, 0xb1, 0x6b, 0x6d, 0x83, 0xe0, 0x1b, 0xe2, 0xd6, 0x0d, 0x62, + 0xec, 0x61, 0xb6, 0xcf, 0xa9, 0x58, 0x88, 0x6e, 0xcd, 0x2d, 0x82, 0x52, + 0xe9, 0xbf, 0x58, 0x71, 0xee, 0xcf, 0x15, 0xb5, 0xed, 0xb3, 0x05, 0x4f, + 0x20, 0x4e, 0xd2, 0x4f, 0x2e, 0x3f, 0xed, 0x71, 0xab, 0x59, 0x2f, 0x3a, + 0xde, 0x53, 0xc1, 0x44, 0xc8, 0xc1, 0x39, 0xd7, 0x61, 0x43, 0x05, 0xb8, + 0x25, 0xfd, 0x0d, 0x46, 0xcf, 0x47, 0x94, 0xc2, 0x65, 0xa5, 0x5f, 0xef, + 0x74, 0xf9, 0x1a, 0xdb, 0x9d, 0xf7, 0xf7, 0xfc, 0x50, 0xda, 0x98, 0x7e, + 0xd8, 0x55, 0x2f, 0xdc, 0x98, 0xcd, 0xe4, 0xae +}; +static const uint8_t nist_186_2_ecdsa_testvector_32_private[] = { +/* d */ + 0x00, 0xfc, 0x37, 0x66, 0x6c, 0x6b, 0x87, 0xd7, 0xa4, 0x70, 0x1b, 0x14, + 0x90, 0x03, 0xf8, 0x76, 0x7f, 0xa3, 0x20, 0x6d, 0x3e, 0x52, 0x36, 0xca, + 0x31, 0x71, 0x22, 0xb3, 0xce, 0xc5, 0x90, 0x0a +}; +static const uint8_t nist_186_2_ecdsa_testvector_32_public_x[] = { +/* Qx */ + 0x6b, 0xe8, 0x61, 0x3c, 0x70, 0x22, 0xa7, 0x8a, 0x24, 0xd3, 0x8c, 0x44, + 0xbe, 0xfd, 0x48, 0x44, 0x66, 0x48, 0xd4, 0xbd, 0x13, 0x45, 0xe1, 0x47, + 0x0c, 0x7b, 0x5f, 0x8e, 0xdb, 0x56, 0x82, 0x3b +}; +static const uint8_t nist_186_2_ecdsa_testvector_32_public_y[] = { +/* Qy */ + 0x58, 0xd8, 0x49, 0x00, 0xfb, 0x28, 0xf1, 0x5f, 0xde, 0x66, 0xbc, 0x26, + 0x45, 0x08, 0xfe, 0xee, 0x5e, 0x54, 0xc0, 0xfa, 0x97, 0x12, 0xce, 0x00, + 0x59, 0x90, 0x2e, 0xfb, 0x46, 0xc3, 0x49, 0xa3 +}; +/* k = 00cb00d310146dc133ca5dddca6f96a20519de714621579381bccaac247929b5 */ +static const uint8_t nist_186_2_ecdsa_testvector_32_out[] = { +/* R */ + 0x43, 0xf4, 0x0b, 0x64, 0x13, 0x53, 0x1e, 0x99, 0xee, 0x4e, 0xbb, 0x2f, + 0xb4, 0xc5, 0x8b, 0x89, 0xeb, 0x77, 0x96, 0xf8, 0x4c, 0xae, 0xf3, 0x3c, + 0x2b, 0x19, 0x35, 0x77, 0xd1, 0x6e, 0xab, 0x84, +/* S */ + 0x64, 0x2c, 0x95, 0x93, 0x0b, 0xc2, 0xa1, 0x55, 0xee, 0x2f, 0xf8, 0xa9, + 0x42, 0x02, 0xcf, 0xbb, 0x83, 0x49, 0xd3, 0xf6, 0x84, 0x1a, 0x7b, 0xb7, + 0x89, 0x58, 0x7a, 0x8a, 0x1c, 0xfe, 0xdb, 0xea +}; +static const uint8_t nist_186_2_ecdsa_testvector_33_ptx[] = { +/* Msg */ + 0xf8, 0xe8, 0x19, 0xb6, 0xc3, 0x9d, 0xfc, 0x49, 0x92, 0xdb, 0x85, 0x2a, + 0xbf, 0x23, 0x80, 0x01, 0x24, 0x78, 0x34, 0x09, 0xde, 0x14, 0x45, 0x67, + 0x50, 0x5a, 0xd9, 0xba, 0x6b, 0x0c, 0xfa, 0xf3, 0x2d, 0xbe, 0x3c, 0x67, + 0x68, 0x8a, 0x9f, 0x22, 0xc5, 0x06, 0xb6, 0x7e, 0x08, 0x73, 0x09, 0xf5, + 0x96, 0x37, 0xb9, 0x34, 0x34, 0x8e, 0x62, 0x70, 0x11, 0x7c, 0x45, 0xfd, + 0x07, 0x06, 0xa7, 0x1d, 0x1e, 0xa1, 0x74, 0x16, 0x52, 0xeb, 0x28, 0x87, + 0x96, 0x99, 0xef, 0xfb, 0x18, 0xb0, 0x0b, 0xbf, 0xc7, 0xf9, 0x77, 0xf1, + 0x13, 0xae, 0xca, 0xda, 0xf3, 0x7a, 0x5d, 0x7e, 0x2d, 0xa1, 0xb0, 0x70, + 0xd2, 0x7a, 0x0a, 0xeb, 0x07, 0x26, 0x60, 0x1f, 0x0b, 0x7c, 0x78, 0xc9, + 0x76, 0x43, 0x4f, 0x06, 0xbf, 0xa4, 0xb7, 0x69, 0x01, 0xde, 0x44, 0x4b, + 0xff, 0x3c, 0x69, 0x62, 0x65, 0x45, 0xdf, 0x96 +}; +static const uint8_t nist_186_2_ecdsa_testvector_33_private[] = { +/* d */ + 0x00, 0x0d, 0xd9, 0xc3, 0x7b, 0x06, 0xa6, 0x62, 0xbb, 0xb3, 0x27, 0xe7, + 0xe7, 0x53, 0x7a, 0x47, 0x33, 0x00, 0xde, 0x49, 0x7b, 0x3d, 0xcd, 0x89, + 0x0f, 0x3a, 0x25, 0xd9, 0x00, 0x71, 0xa6, 0x08 +}; +static const uint8_t nist_186_2_ecdsa_testvector_33_public_x[] = { +/* Qx */ + 0x07, 0x63, 0xb2, 0x46, 0x36, 0xd1, 0x12, 0x29, 0x4a, 0xd6, 0xd8, 0x5f, + 0xd7, 0x64, 0x0b, 0x4d, 0xef, 0xde, 0xf5, 0xdf, 0x24, 0x5e, 0x53, 0xc4, + 0x27, 0x50, 0xa6, 0x80, 0x83, 0x8e, 0x11, 0x50 +}; +static const uint8_t nist_186_2_ecdsa_testvector_33_public_y[] = { +/* Qy */ + 0xb8, 0x7e, 0x87, 0xa4, 0xb3, 0x53, 0x55, 0xc5, 0x31, 0x70, 0x91, 0x56, + 0x96, 0x1e, 0x64, 0xd8, 0xc1, 0x7f, 0x63, 0xa4, 0x38, 0xaa, 0xd6, 0x52, + 0xfc, 0xc9, 0x86, 0x04, 0xa3, 0x3b, 0xe2, 0xa7 +}; +/* k = 0045af0ce21481f3daedc4d34b611c75cb1f8a0715f30bf2fb45b017258584d5 */ +static const uint8_t nist_186_2_ecdsa_testvector_33_out[] = { +/* R */ + 0x6f, 0x0a, 0x38, 0x66, 0x10, 0x90, 0x07, 0xc5, 0x28, 0xe4, 0xf7, 0x5b, + 0xc4, 0xbe, 0x8f, 0x44, 0x59, 0x06, 0x62, 0x57, 0xd3, 0x54, 0xe7, 0x50, + 0xf6, 0x3d, 0x07, 0x3f, 0x2b, 0x7b, 0x8d, 0x36, +/* S */ + 0xae, 0x80, 0x0d, 0xe3, 0xeb, 0xa8, 0x7a, 0x10, 0x88, 0x90, 0x05, 0x70, + 0xca, 0x0c, 0x26, 0x80, 0xd4, 0xbf, 0x8f, 0x6a, 0x7f, 0x70, 0x65, 0x01, + 0x62, 0x65, 0x03, 0xdb, 0x41, 0x02, 0xcd, 0x0a +}; +static const uint8_t nist_186_2_ecdsa_testvector_34_ptx[] = { +/* Msg */ + 0xad, 0x3f, 0x0a, 0x14, 0xe9, 0xfd, 0xb5, 0x9f, 0xdf, 0x98, 0xb2, 0x87, + 0xc9, 0x2e, 0x2e, 0x93, 0x66, 0x55, 0xfe, 0x95, 0x4d, 0x18, 0x8f, 0x92, + 0x81, 0x3d, 0x20, 0x23, 0x45, 0xca, 0x2e, 0x1b, 0x32, 0xc7, 0x30, 0x6a, + 0x86, 0x44, 0x85, 0x42, 0xbf, 0x9e, 0xab, 0x78, 0x69, 0xff, 0xb1, 0x2c, + 0x34, 0x24, 0xef, 0xac, 0x49, 0x63, 0xf4, 0x96, 0xde, 0xec, 0xc0, 0x3d, + 0x08, 0x4f, 0x34, 0x4e, 0xd1, 0x3e, 0xc6, 0xb4, 0x8b, 0x94, 0x79, 0xb8, + 0x64, 0x97, 0x0d, 0x6d, 0x3a, 0x7a, 0x72, 0x4b, 0xb0, 0x27, 0x83, 0x1a, + 0x81, 0x3b, 0xf1, 0x12, 0x14, 0x51, 0x7d, 0x40, 0x51, 0x83, 0x6b, 0x2b, + 0xb4, 0x2e, 0x33, 0xb8, 0x9f, 0xf6, 0x79, 0x4b, 0xf5, 0x0a, 0x3f, 0x2f, + 0xe4, 0xa9, 0x5a, 0x38, 0x02, 0xe6, 0x22, 0xa6, 0x9c, 0xa8, 0x6e, 0x4d, + 0x4a, 0xf4, 0xc0, 0xf3, 0xc7, 0x6f, 0xbc, 0xfa +}; +static const uint8_t nist_186_2_ecdsa_testvector_34_private[] = { +/* d */ + 0x00, 0x43, 0xfb, 0x05, 0x12, 0x77, 0xa6, 0xcd, 0xe8, 0x08, 0xa3, 0x4e, + 0xa7, 0x5d, 0x38, 0xa8, 0x17, 0x3f, 0x80, 0xec, 0xe4, 0x67, 0x40, 0x82, + 0x8b, 0x07, 0x58, 0xd8, 0x29, 0xd8, 0xca, 0x3c +}; +static const uint8_t nist_186_2_ecdsa_testvector_34_public_x[] = { +/* Qx */ + 0xfa, 0xb5, 0xc3, 0x5a, 0x7a, 0x6e, 0x21, 0x4f, 0x7a, 0x49, 0x98, 0x66, + 0xaa, 0x50, 0xef, 0x16, 0xb8, 0xd9, 0x2e, 0x29, 0xe6, 0x6a, 0x0b, 0x63, + 0x19, 0x72, 0x15, 0x22, 0xdb, 0x10, 0x1e, 0xae +}; +static const uint8_t nist_186_2_ecdsa_testvector_34_public_y[] = { +/* Qy */ + 0x8f, 0x3f, 0x89, 0xad, 0x8d, 0x36, 0x9e, 0x48, 0x73, 0xe5, 0x66, 0xf2, + 0x1b, 0x8a, 0xdf, 0x42, 0x30, 0x4c, 0xb8, 0x10, 0x19, 0xc4, 0x01, 0xc1, + 0xb1, 0xde, 0x40, 0x29, 0xe0, 0x24, 0x5d, 0x75 +}; +/* k = 0036797bf01ddb25973cd9b030b50632d621aac0c653536e751c31c4367de559 */ +static const uint8_t nist_186_2_ecdsa_testvector_34_out[] = { +/* R */ + 0x17, 0xcf, 0xd4, 0xd7, 0xb4, 0x3c, 0x06, 0xa2, 0xa4, 0x39, 0xbc, 0x6d, + 0x04, 0xc2, 0xcf, 0x4f, 0xf8, 0xba, 0x83, 0x24, 0xc4, 0xa1, 0xc8, 0xa3, + 0x29, 0xa6, 0x18, 0x9f, 0x5d, 0xa5, 0xc2, 0x3b, +/* S */ + 0x93, 0x02, 0x90, 0x9d, 0x13, 0x17, 0xbb, 0xec, 0xd9, 0x5d, 0x10, 0xee, + 0xad, 0x9a, 0xb6, 0x94, 0x33, 0x01, 0x2e, 0xdd, 0xf9, 0x17, 0xc1, 0x2f, + 0x6f, 0x91, 0xad, 0xf9, 0xcc, 0x4a, 0x7f, 0x09 +}; +static const uint8_t nist_186_2_ecdsa_testvector_35_ptx[] = { +/* Msg */ + 0xe3, 0x7a, 0x43, 0x2c, 0xd6, 0x19, 0x3a, 0x0b, 0x2e, 0x73, 0x45, 0xdf, + 0x13, 0xe0, 0xeb, 0x62, 0x68, 0x84, 0x53, 0x72, 0xa3, 0xd1, 0xb3, 0xb7, + 0xdc, 0x4d, 0x0c, 0x87, 0x23, 0x96, 0x15, 0x06, 0x17, 0xa3, 0x74, 0x92, + 0xb5, 0x4c, 0x34, 0x5e, 0x6d, 0x0d, 0x74, 0x5c, 0x7b, 0x07, 0x5c, 0x61, + 0x74, 0x47, 0x56, 0x84, 0x1f, 0x4b, 0x7a, 0xc7, 0x87, 0xc2, 0x49, 0xf9, + 0x4e, 0x94, 0x9f, 0xda, 0x44, 0x22, 0xe3, 0x81, 0x38, 0xcf, 0x81, 0xfb, + 0x0f, 0xbf, 0x9a, 0x35, 0x13, 0xdf, 0xfa, 0x1b, 0x8d, 0x25, 0x4a, 0x02, + 0x95, 0x19, 0x86, 0x43, 0x29, 0x94, 0xb2, 0x29, 0x7d, 0xc7, 0xc9, 0x0e, + 0x92, 0x80, 0xf7, 0xc0, 0x0a, 0xa9, 0x07, 0x2a, 0x3b, 0x11, 0x1f, 0x30, + 0x82, 0x70, 0xab, 0xda, 0xd9, 0xa5, 0x97, 0xb5, 0xac, 0x41, 0xc1, 0x76, + 0xe9, 0x49, 0xae, 0xe1, 0x57, 0x38, 0x7c, 0xe9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_35_private[] = { +/* d */ + 0x00, 0xd7, 0x41, 0xac, 0x11, 0x03, 0xee, 0xa6, 0xde, 0x30, 0x31, 0x27, + 0x0f, 0xde, 0x37, 0xcb, 0x68, 0x0c, 0x17, 0x28, 0xf0, 0x5f, 0xc0, 0x85, + 0x57, 0xbb, 0x35, 0xee, 0x61, 0xea, 0x0b, 0xf7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_35_public_x[] = { +/* Qx */ + 0x08, 0xef, 0x74, 0x01, 0x6b, 0x7d, 0x4d, 0xc6, 0x4c, 0x47, 0x98, 0x7b, + 0x11, 0x96, 0x74, 0x37, 0xbf, 0xc6, 0xf7, 0xfa, 0x2d, 0x57, 0x00, 0x63, + 0xc6, 0xb7, 0x2f, 0x1c, 0x8d, 0x51, 0x25, 0xed +}; +static const uint8_t nist_186_2_ecdsa_testvector_35_public_y[] = { +/* Qy */ + 0x1f, 0xc1, 0xcc, 0xb3, 0x17, 0xc3, 0x92, 0x38, 0x25, 0xac, 0x85, 0x26, + 0x35, 0x8f, 0xe4, 0xb0, 0x0d, 0x4c, 0xa1, 0x52, 0x6d, 0x86, 0xd7, 0x30, + 0x9a, 0x00, 0x4a, 0xcf, 0x0c, 0xfa, 0xe6, 0x37 +}; +/* k = 005b5852327259b12ba08f9a0e1c82d87f6cdc833dd69fedf05bd9283b8ebc61 */ +static const uint8_t nist_186_2_ecdsa_testvector_35_out[] = { +/* R */ + 0x99, 0x08, 0xaa, 0xe4, 0x3d, 0xee, 0xd6, 0xb5, 0x65, 0x1d, 0x9a, 0x4d, + 0x00, 0x41, 0xec, 0xc9, 0x76, 0xe8, 0x19, 0xae, 0x64, 0xe3, 0xe9, 0x38, + 0xe0, 0xaf, 0x8b, 0x3d, 0x41, 0xa7, 0x6b, 0x3e, +/* S */ + 0x32, 0xb1, 0x7d, 0x68, 0x01, 0x9e, 0x94, 0xa3, 0x62, 0xd4, 0x17, 0x8a, + 0xa9, 0x54, 0xf5, 0xcf, 0xef, 0xe0, 0xfd, 0x65, 0x9c, 0x34, 0x1c, 0x88, + 0xf4, 0xf0, 0x68, 0xeb, 0xf4, 0x8b, 0x97, 0x73 +}; +static const uint8_t nist_186_2_ecdsa_testvector_36_ptx[] = { +/* Msg */ + 0x26, 0xd3, 0xfa, 0x2a, 0x1d, 0x6c, 0xfa, 0x12, 0xf6, 0x73, 0x6d, 0x5a, + 0x75, 0x2d, 0xdc, 0x7d, 0xff, 0xfd, 0x67, 0x28, 0x59, 0x1f, 0xad, 0x90, + 0xb2, 0x99, 0xec, 0x09, 0xe4, 0x6f, 0x69, 0xd5, 0xf7, 0x17, 0x13, 0x39, + 0xe6, 0x2c, 0x63, 0xd6, 0xa6, 0x67, 0x86, 0x37, 0x65, 0xca, 0xbe, 0xa7, + 0x10, 0x1e, 0x06, 0x45, 0x17, 0xa0, 0xf5, 0x5a, 0x74, 0xf8, 0xe4, 0xe9, + 0xea, 0x6a, 0x53, 0x88, 0x8a, 0x50, 0x89, 0x6f, 0x7c, 0xc8, 0x7b, 0xcf, + 0xfc, 0xaa, 0xef, 0x65, 0xa3, 0xbd, 0xe1, 0x4e, 0xe8, 0x2a, 0x26, 0x1d, + 0xe6, 0x30, 0x4f, 0x2b, 0x60, 0x1a, 0xd0, 0x2e, 0x02, 0x6e, 0x62, 0x0d, + 0xe9, 0x68, 0xa5, 0xf3, 0x66, 0xa6, 0x0a, 0xa3, 0xff, 0x25, 0xf0, 0x0b, + 0xb7, 0x6c, 0x0d, 0x1b, 0x90, 0x07, 0x10, 0xd7, 0x4d, 0x37, 0x84, 0xab, + 0x7c, 0xe8, 0xf8, 0xff, 0xb4, 0xe3, 0x5d, 0x0c +}; +static const uint8_t nist_186_2_ecdsa_testvector_36_private[] = { +/* d */ + 0x00, 0xc2, 0xfe, 0x3b, 0x0d, 0x4f, 0x3d, 0x69, 0x09, 0xa3, 0x99, 0xa4, + 0x32, 0x47, 0xa2, 0x12, 0x92, 0xff, 0x63, 0x3f, 0x8f, 0x0f, 0x05, 0x3e, + 0x39, 0x45, 0x9a, 0xf6, 0xb8, 0x43, 0x7e, 0x6b +}; +static const uint8_t nist_186_2_ecdsa_testvector_36_public_x[] = { +/* Qx */ + 0x1b, 0xaf, 0x23, 0xf8, 0x6d, 0x78, 0xaa, 0x82, 0xda, 0x24, 0x8d, 0x2f, + 0x9a, 0xcf, 0x65, 0xdf, 0xa2, 0xe7, 0x84, 0x8a, 0x8b, 0xde, 0xbb, 0x93, + 0x19, 0x91, 0x68, 0xe6, 0xf0, 0xd4, 0xf5, 0xf9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_36_public_y[] = { +/* Qy */ + 0xca, 0x61, 0x98, 0x5b, 0xfc, 0xd0, 0xac, 0x55, 0xf9, 0x5b, 0x73, 0xf0, + 0x77, 0x74, 0xd8, 0x71, 0x4b, 0x6c, 0x3b, 0x80, 0xdd, 0xd6, 0x12, 0x3b, + 0x3d, 0xac, 0x8a, 0x45, 0xc3, 0x4e, 0x43, 0x5b +}; +/* k = 00c8c9e7cf43fe62a67a3c998c36931a3a5332f3a47972c26a7813f405ffe851 */ +static const uint8_t nist_186_2_ecdsa_testvector_36_out[] = { +/* R */ + 0xdd, 0xf8, 0xfc, 0x4d, 0x06, 0xef, 0x4b, 0x7b, 0x69, 0xe2, 0x6a, 0xc9, + 0xc0, 0x0a, 0xc7, 0xed, 0x9a, 0xe5, 0x50, 0x12, 0xe9, 0xf2, 0xa9, 0x7f, + 0x4e, 0xb9, 0x9c, 0xab, 0xae, 0x39, 0x36, 0x60, +/* S */ + 0x1f, 0x41, 0xca, 0x55, 0x3d, 0xbb, 0x07, 0xd8, 0xe7, 0xd6, 0x8e, 0x36, + 0x50, 0xc5, 0x77, 0x7e, 0x42, 0xb3, 0x47, 0x3e, 0x31, 0x90, 0x86, 0x88, + 0xc0, 0xd7, 0x32, 0x4a, 0xfa, 0x63, 0x7e, 0xd0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_37_ptx[] = { +/* Msg */ + 0x07, 0x2f, 0x0e, 0x1e, 0xd6, 0x22, 0x57, 0x1f, 0x80, 0x60, 0x26, 0x54, + 0x3f, 0x4c, 0x24, 0x4e, 0xaf, 0x25, 0x68, 0x5d, 0x2f, 0xd7, 0xf6, 0x04, + 0x8a, 0x17, 0x85, 0xab, 0xd7, 0xae, 0x86, 0x94, 0x9d, 0x15, 0x61, 0x10, + 0x3b, 0x43, 0x02, 0xf3, 0x87, 0xc3, 0x94, 0x45, 0xb6, 0x09, 0x8c, 0x3a, + 0x7c, 0x06, 0xea, 0x64, 0x73, 0xfa, 0xbb, 0x28, 0xc1, 0x8a, 0xe3, 0x6f, + 0xf6, 0x12, 0x19, 0x9d, 0x33, 0x3c, 0x33, 0xc7, 0x91, 0xd2, 0xa4, 0x21, + 0xc0, 0xd0, 0x43, 0xb5, 0xef, 0xbe, 0x4e, 0x5b, 0xec, 0x3c, 0xae, 0xe5, + 0x8d, 0xdf, 0x7c, 0x9a, 0x4e, 0x3b, 0xc5, 0xe6, 0x3b, 0x41, 0x8a, 0x4f, + 0x11, 0xcc, 0x0b, 0xab, 0xa0, 0x76, 0x46, 0x90, 0x73, 0xb0, 0xba, 0x0d, + 0xb3, 0x12, 0x70, 0x97, 0x49, 0xef, 0x3c, 0x46, 0x43, 0x2d, 0x41, 0x42, + 0x79, 0x53, 0xb3, 0x78, 0x70, 0xe4, 0xe1, 0x91 +}; +static const uint8_t nist_186_2_ecdsa_testvector_37_private[] = { +/* d */ + 0x00, 0x37, 0xd4, 0xac, 0x2a, 0x27, 0x52, 0x0b, 0x13, 0x03, 0x99, 0x03, + 0x91, 0x80, 0x5a, 0xa3, 0xc1, 0x90, 0x65, 0x6e, 0x30, 0xcc, 0x8c, 0x5b, + 0x54, 0xb4, 0x89, 0xac, 0x4d, 0x0b, 0x29, 0x5e +}; +static const uint8_t nist_186_2_ecdsa_testvector_37_public_x[] = { +/* Qx */ + 0x83, 0x4f, 0x19, 0xc9, 0x36, 0x4b, 0x77, 0xec, 0x0a, 0xcd, 0x04, 0x99, + 0x7f, 0x1b, 0x8d, 0xa7, 0xe3, 0x5c, 0x7f, 0x9d, 0x90, 0xd3, 0x05, 0xe4, + 0xbb, 0x15, 0x05, 0xd0, 0xc0, 0x72, 0xc2, 0xd9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_37_public_y[] = { +/* Qy */ + 0x73, 0x43, 0xfc, 0x4f, 0x25, 0x50, 0x7e, 0x00, 0x0a, 0x12, 0xbf, 0x5c, + 0xc5, 0xca, 0x99, 0xe3, 0x10, 0x38, 0x3d, 0x08, 0x24, 0x80, 0x7a, 0x74, + 0xfb, 0x31, 0xd3, 0xbc, 0x89, 0xb9, 0x4d, 0x69 +}; +/* k = 001195d3f0a9f06fd529e351ea3defebd8a68fa6228fcba6e2c23167855d931b */ +static const uint8_t nist_186_2_ecdsa_testvector_37_out[] = { +/* R */ + 0x2a, 0x7b, 0xbe, 0xba, 0x9a, 0x19, 0x25, 0xe6, 0x4c, 0x6e, 0x82, 0x9d, + 0x88, 0xc7, 0xa8, 0x93, 0xc2, 0x96, 0x02, 0x73, 0xac, 0x40, 0xd8, 0x2e, + 0xa9, 0xb6, 0x6c, 0x98, 0x1a, 0x24, 0xb3, 0x46, +/* S */ + 0x50, 0x77, 0x20, 0x70, 0x32, 0xc8, 0xa7, 0xbf, 0xd4, 0xae, 0x87, 0x6f, + 0x22, 0xbb, 0x54, 0xb3, 0xec, 0x4d, 0x7f, 0x39, 0x4c, 0xf0, 0xc1, 0x52, + 0xf6, 0x36, 0xa7, 0x8f, 0xda, 0x8e, 0xb3, 0x5a +}; +static const uint8_t nist_186_2_ecdsa_testvector_38_ptx[] = { +/* Msg */ + 0xc2, 0xc0, 0x47, 0x1e, 0x83, 0x03, 0x27, 0xbf, 0x1b, 0x0d, 0xda, 0x7b, + 0xb0, 0x36, 0xe1, 0x17, 0xff, 0x1c, 0xf8, 0xb9, 0xab, 0xa4, 0x00, 0x06, + 0xd4, 0x3b, 0x3d, 0x87, 0xec, 0x62, 0xc1, 0x51, 0xc6, 0x69, 0x28, 0xe5, + 0xf0, 0x7a, 0x86, 0x55, 0x43, 0xda, 0x9e, 0xa8, 0xb8, 0x6c, 0x55, 0x80, + 0x7e, 0x77, 0x66, 0xfa, 0x49, 0xa8, 0x56, 0xd6, 0xec, 0x5b, 0xab, 0xd8, + 0x2a, 0x16, 0x59, 0x6d, 0xc9, 0x56, 0x7d, 0x92, 0xe9, 0x8f, 0x4d, 0xf2, + 0x94, 0x6e, 0x4f, 0x4e, 0x96, 0x61, 0xca, 0x22, 0x8f, 0x59, 0x7b, 0x86, + 0x46, 0xcf, 0x88, 0x52, 0x40, 0x05, 0xba, 0x85, 0x92, 0x8e, 0xe6, 0xe8, + 0xf3, 0x10, 0xac, 0xee, 0x15, 0x49, 0x64, 0xdf, 0x36, 0x50, 0x56, 0x35, + 0xf2, 0x1d, 0x29, 0x47, 0x5b, 0x4c, 0x9f, 0x24, 0x4b, 0x1e, 0x7f, 0xc2, + 0xf9, 0xc1, 0xd2, 0x58, 0xcb, 0xd1, 0x51, 0x08 +}; +static const uint8_t nist_186_2_ecdsa_testvector_38_private[] = { +/* d */ + 0x00, 0xb3, 0xea, 0x91, 0x54, 0xc8, 0x47, 0x49, 0xf4, 0xd5, 0xee, 0x11, + 0x60, 0xfd, 0xd1, 0xca, 0x69, 0x91, 0x87, 0xf3, 0xb3, 0x39, 0xd4, 0xbd, + 0x8c, 0xac, 0x32, 0x66, 0xe0, 0x71, 0x4d, 0x0b +}; +static const uint8_t nist_186_2_ecdsa_testvector_38_public_x[] = { +/* Qx */ + 0xd2, 0x5e, 0x48, 0xc8, 0x81, 0xcd, 0x1a, 0x8b, 0xf8, 0x01, 0x75, 0x07, + 0xa6, 0x51, 0x1e, 0x1c, 0x49, 0x40, 0x98, 0x02, 0xf1, 0x4d, 0x22, 0x6b, + 0x56, 0x50, 0x7a, 0x28, 0x0f, 0x82, 0x40, 0xb1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_38_public_y[] = { +/* Qy */ + 0xe0, 0xad, 0x27, 0x83, 0x11, 0xc6, 0xe0, 0x8b, 0x65, 0xe7, 0xb1, 0xbb, + 0x86, 0x62, 0x7a, 0x43, 0xfc, 0x45, 0xd0, 0x4a, 0x89, 0xc4, 0x28, 0x04, + 0xb5, 0x5a, 0x37, 0x88, 0x05, 0x65, 0x56, 0xe2 +}; +/* k = 0023ded046abaa7858849550559af1ab74205904ba560a050abfa9358958622e */ +static const uint8_t nist_186_2_ecdsa_testvector_38_out[] = { +/* R */ + 0xfe, 0x7e, 0x11, 0x0c, 0x27, 0xf6, 0x9d, 0x4d, 0x8c, 0x31, 0x91, 0x13, + 0x67, 0x6c, 0x83, 0xd7, 0xb9, 0xb4, 0xd8, 0xde, 0xdd, 0x5d, 0xb6, 0xa7, + 0x58, 0x53, 0xa8, 0xb3, 0x99, 0xaa, 0x27, 0x89, +/* S */ + 0xc5, 0xd7, 0x71, 0x0e, 0xf8, 0x8a, 0x11, 0x20, 0x0d, 0x84, 0xc7, 0x02, + 0xb2, 0x8d, 0x17, 0x48, 0x00, 0xbb, 0xf5, 0xa9, 0xe0, 0x8e, 0xbb, 0xd6, + 0x39, 0xfd, 0x4f, 0xb8, 0xaa, 0x6d, 0xd4, 0xdb +}; +static const uint8_t nist_186_2_ecdsa_testvector_39_ptx[] = { +/* Msg */ + 0x4f, 0x0f, 0x98, 0x13, 0x0c, 0xd6, 0x88, 0xaf, 0x32, 0xb1, 0x4b, 0xac, + 0xad, 0x31, 0x3c, 0xc8, 0xcc, 0xb5, 0x4d, 0xfc, 0x3a, 0x8e, 0x9e, 0xba, + 0x2f, 0x60, 0x4e, 0x74, 0xe7, 0xcb, 0x91, 0x5d, 0x54, 0x4b, 0x02, 0x73, + 0x10, 0x5d, 0x3b, 0xbd, 0x95, 0xe4, 0xa3, 0xd1, 0xb0, 0xca, 0x88, 0x9a, + 0x33, 0xea, 0x6e, 0x58, 0xeb, 0x2e, 0xa6, 0xe8, 0xd1, 0xf4, 0x22, 0x46, + 0x84, 0xb7, 0x87, 0x50, 0xf7, 0xeb, 0x84, 0xcd, 0x67, 0x28, 0x63, 0xad, + 0x91, 0x8b, 0xdd, 0x92, 0x21, 0x5a, 0x33, 0x90, 0x6d, 0xe6, 0x7a, 0x31, + 0x63, 0xb6, 0x36, 0xbd, 0xc0, 0xe1, 0x2b, 0xb8, 0x84, 0xbc, 0x70, 0xab, + 0xa2, 0xb5, 0xc5, 0x28, 0xfb, 0x7f, 0x26, 0x08, 0x8d, 0x70, 0xa1, 0xf7, + 0xe8, 0x27, 0x64, 0x33, 0xe2, 0x71, 0x1a, 0x90, 0x8c, 0x6e, 0x78, 0xc0, + 0x65, 0xef, 0x12, 0xd1, 0xcd, 0x23, 0x74, 0xf7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_39_private[] = { +/* d */ + 0x00, 0x48, 0x0a, 0xb6, 0xfa, 0x57, 0x4a, 0xea, 0xa0, 0x41, 0x13, 0x80, + 0xcb, 0xfd, 0xc3, 0x87, 0x79, 0x24, 0x32, 0xc3, 0xe0, 0xb4, 0xea, 0xea, + 0xf1, 0x61, 0x70, 0x96, 0xf4, 0xf1, 0x1b, 0x89 +}; +static const uint8_t nist_186_2_ecdsa_testvector_39_public_x[] = { +/* Qx */ + 0xaf, 0xb9, 0x82, 0x0f, 0xba, 0xb1, 0xf3, 0x1e, 0x84, 0xb7, 0xbe, 0xd0, + 0xef, 0x93, 0x05, 0x3e, 0xec, 0x01, 0xe7, 0x09, 0x91, 0x00, 0xbb, 0x29, + 0x0d, 0xf1, 0x2a, 0x59, 0x02, 0x8d, 0x0a, 0x37 +}; +static const uint8_t nist_186_2_ecdsa_testvector_39_public_y[] = { +/* Qy */ + 0xf3, 0x96, 0x22, 0x09, 0xd8, 0x68, 0x3a, 0x90, 0x7b, 0x8c, 0x20, 0x13, + 0x89, 0xb4, 0xcd, 0x2a, 0xb4, 0xd0, 0x78, 0x21, 0x66, 0xa8, 0x8d, 0xc4, + 0x20, 0x4a, 0x47, 0x9e, 0x7b, 0x34, 0xd1, 0x01 +}; +/* k = 0006a94c845c7ef871b0c440bbcb997f688b3fee833354b6981702bc3159479c */ +static const uint8_t nist_186_2_ecdsa_testvector_39_out[] = { +/* R */ + 0xa4, 0x17, 0xad, 0xcf, 0x86, 0xb1, 0xde, 0x7c, 0x40, 0xd3, 0x40, 0x97, + 0x79, 0x44, 0x80, 0x55, 0x14, 0xe7, 0x63, 0x7c, 0xba, 0x5e, 0xe8, 0x3e, + 0xbb, 0xdb, 0x24, 0x43, 0x56, 0x23, 0x18, 0xa9, +/* S */ + 0x48, 0xcc, 0x6e, 0xff, 0x80, 0x33, 0x08, 0xb0, 0x2c, 0x9d, 0xdd, 0x73, + 0x99, 0x24, 0x13, 0x8f, 0xd5, 0x72, 0xa8, 0xe9, 0xc2, 0x37, 0x64, 0xa1, + 0x83, 0x1e, 0xe3, 0xd8, 0x19, 0xbf, 0x08, 0x7a +}; +static const uint8_t nist_186_2_ecdsa_testvector_40_ptx[] = { +/* Msg */ + 0x48, 0x49, 0x4b, 0x66, 0x1d, 0x94, 0x4a, 0x04, 0xb2, 0xc3, 0x32, 0x35, + 0xaa, 0x7f, 0x51, 0x1b, 0x6a, 0x2a, 0xd4, 0x43, 0x1c, 0xd0, 0xe8, 0x35, + 0xfa, 0x5a, 0x20, 0x4a, 0xc9, 0x05, 0x17, 0xbe, 0xa3, 0x13, 0x56, 0x06, + 0xfa, 0xc1, 0x78, 0x64, 0xda, 0x78, 0x8c, 0xb8, 0x6e, 0x47, 0xba, 0x99, + 0xc6, 0x91, 0x2a, 0xa4, 0xd7, 0x03, 0x21, 0x14, 0xc4, 0xc9, 0x6d, 0x94, + 0x5c, 0x02, 0x04, 0x51, 0xe3, 0x71, 0xe8, 0x52, 0x15, 0x75, 0x4d, 0x0c, + 0x68, 0x3b, 0xfe, 0x31, 0x92, 0x32, 0xfd, 0xca, 0x4b, 0xbf, 0x69, 0x85, + 0x54, 0x33, 0xa5, 0x50, 0xb8, 0xfa, 0xb7, 0x26, 0x52, 0x14, 0xee, 0x29, + 0x8f, 0xca, 0xc8, 0xf2, 0x75, 0x99, 0x12, 0x25, 0xe4, 0x73, 0x51, 0x48, + 0x1c, 0x27, 0x61, 0xd5, 0x80, 0x1d, 0x5c, 0x8d, 0x9a, 0x46, 0xbe, 0x10, + 0x5e, 0x53, 0xc6, 0xab, 0xb3, 0x25, 0x1f, 0x71 +}; +static const uint8_t nist_186_2_ecdsa_testvector_40_private[] = { +/* d */ + 0x00, 0xe1, 0x1c, 0x4e, 0xb5, 0x7b, 0xdd, 0x6c, 0x26, 0x6b, 0x57, 0x95, + 0xe2, 0xe9, 0x5d, 0x3f, 0x34, 0xf8, 0x02, 0xf8, 0xce, 0x87, 0x28, 0xa6, + 0xd9, 0x81, 0xb8, 0x78, 0x7e, 0xcc, 0x10, 0x2c +}; +static const uint8_t nist_186_2_ecdsa_testvector_40_public_x[] = { +/* Qx */ + 0x99, 0x7a, 0x53, 0x5b, 0x89, 0x2a, 0xdf, 0x06, 0xaf, 0xe8, 0xfd, 0x17, + 0xd9, 0x1b, 0x52, 0xc9, 0x14, 0x9e, 0x1d, 0x83, 0xc3, 0xc7, 0x31, 0x79, + 0x00, 0x87, 0x27, 0xef, 0xcd, 0xba, 0x55, 0x21 +}; +static const uint8_t nist_186_2_ecdsa_testvector_40_public_y[] = { +/* Qy */ + 0xef, 0x14, 0x2f, 0xa4, 0x8a, 0x4b, 0x75, 0x77, 0x1a, 0x9f, 0x15, 0x6d, + 0x22, 0x9c, 0x9d, 0x61, 0xb2, 0x23, 0xa5, 0x73, 0xfa, 0xdb, 0x31, 0x38, + 0xb3, 0xd0, 0xb4, 0xd4, 0x11, 0x41, 0x5a, 0x94 +}; +/* k = 009d3dc147bc10b23b1156aa120e1933f31fa98a4233587941c355ca0b99f0c3 */ +static const uint8_t nist_186_2_ecdsa_testvector_40_out[] = { +/* R */ + 0xd4, 0xed, 0x66, 0xd8, 0xa5, 0xbc, 0x64, 0x0e, 0x01, 0xfd, 0xf9, 0x5a, + 0x7f, 0xf2, 0xd0, 0xfe, 0x13, 0x69, 0x2e, 0xb1, 0x21, 0xbf, 0x68, 0x83, + 0xfd, 0xc2, 0xbe, 0x93, 0x8d, 0x99, 0x10, 0x60, +/* S */ + 0xf4, 0x31, 0x68, 0x41, 0x45, 0x38, 0xb8, 0x81, 0x7a, 0x3e, 0x48, 0x35, + 0x02, 0x43, 0x7f, 0xd1, 0x68, 0x1a, 0x84, 0xf2, 0x05, 0x39, 0xc0, 0x55, + 0x66, 0x8e, 0xaa, 0x5a, 0x93, 0xfa, 0x4d, 0xb0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_41_ptx[] = { +/* Msg */ + 0xe6, 0x58, 0x23, 0x93, 0x3d, 0xfb, 0x7d, 0xf5, 0x03, 0x28, 0xbc, 0x28, + 0xde, 0x79, 0x61, 0xb4, 0x06, 0xd9, 0xf8, 0x07, 0x05, 0x3b, 0xfb, 0xc5, + 0xbb, 0x8c, 0xf3, 0x5f, 0xa4, 0xe5, 0xe0, 0xe7, 0x5e, 0x06, 0xdb, 0x23, + 0x65, 0x00, 0xfa, 0xe0, 0x22, 0x31, 0x74, 0x88, 0x24, 0x75, 0x05, 0xf7, + 0xad, 0x9b, 0x94, 0x8b, 0x70, 0x16, 0x14, 0x7a, 0x99, 0xf5, 0xa8, 0x69, + 0x0e, 0x16, 0x0a, 0x3a, 0xf4, 0x96, 0x2d, 0x25, 0x76, 0x8b, 0x21, 0x0a, + 0xc1, 0xf6, 0x38, 0x05, 0x53, 0xf3, 0x67, 0x44, 0x76, 0x33, 0xee, 0x15, + 0x07, 0xac, 0x3b, 0x43, 0x7c, 0x8f, 0x0c, 0xa3, 0x26, 0x7b, 0xd5, 0xea, + 0xb2, 0xf0, 0x61, 0xc1, 0xf6, 0x06, 0xbb, 0x1c, 0xeb, 0x5f, 0x4f, 0xc7, + 0xf5, 0x5a, 0x4d, 0x41, 0x6b, 0x89, 0x4e, 0xce, 0x53, 0x66, 0x3a, 0xc8, + 0x6d, 0x41, 0x69, 0x36, 0x74, 0x7d, 0x08, 0xa0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_41_private[] = { +/* d */ + 0x00, 0x5e, 0xeb, 0x60, 0x90, 0x1d, 0x07, 0xf4, 0x9f, 0x43, 0x37, 0x44, + 0x71, 0x53, 0x06, 0xce, 0xa0, 0x6c, 0xf7, 0x55, 0x07, 0xb7, 0x4f, 0xb8, + 0x23, 0x22, 0x3d, 0xc3, 0xad, 0x33, 0xd2, 0x0e +}; +static const uint8_t nist_186_2_ecdsa_testvector_41_public_x[] = { +/* Qx */ + 0x00, 0xfe, 0x1a, 0xd1, 0x8e, 0x96, 0x56, 0xd9, 0xd5, 0xfd, 0xc1, 0xcc, + 0xce, 0x2f, 0x26, 0x8d, 0xeb, 0xeb, 0x64, 0xeb, 0xb0, 0xb3, 0x9f, 0xed, + 0x65, 0x7d, 0x20, 0x51, 0x72, 0x7b, 0x0a, 0x57 +}; +static const uint8_t nist_186_2_ecdsa_testvector_41_public_y[] = { +/* Qy */ + 0xef, 0x4d, 0x02, 0xfd, 0xa8, 0x98, 0x26, 0x6c, 0x96, 0xd7, 0xcf, 0x20, + 0x31, 0xd1, 0xe0, 0xd5, 0x6e, 0x15, 0x8e, 0xe0, 0xa0, 0x7f, 0xec, 0xb4, + 0xc8, 0xa1, 0x4a, 0x02, 0x1d, 0x98, 0x45, 0x84 +}; +/* k = 007188abf3ed30221ff28c8adf1c2af5b40bb4021ea5d94672ee7308c5154807 */ +static const uint8_t nist_186_2_ecdsa_testvector_41_out[] = { +/* R */ + 0xd5, 0x60, 0x4a, 0xec, 0xac, 0x4f, 0x8b, 0x69, 0xd5, 0xfe, 0x0e, 0xe8, + 0xee, 0x9d, 0x0d, 0x59, 0x18, 0xd3, 0x78, 0xcc, 0x9c, 0x38, 0x86, 0x2a, + 0x85, 0xca, 0xb1, 0x01, 0x82, 0x83, 0x6f, 0x62, +/* S */ + 0xc7, 0x10, 0x48, 0x58, 0xcd, 0x7b, 0xcc, 0x41, 0x8b, 0x4f, 0x2c, 0x36, + 0x73, 0x94, 0x5d, 0x47, 0xe9, 0x56, 0x7f, 0xa0, 0x5a, 0x90, 0x28, 0xe0, + 0x0d, 0x9a, 0xed, 0x06, 0xea, 0x85, 0x40, 0x68 +}; +static const uint8_t nist_186_2_ecdsa_testvector_42_ptx[] = { +/* Msg */ + 0x4c, 0xe3, 0x7a, 0x16, 0xce, 0xed, 0xe9, 0x5d, 0x71, 0xd6, 0xf9, 0x10, + 0xfa, 0x9f, 0xb3, 0xda, 0xef, 0x05, 0xf8, 0xee, 0x4d, 0x5d, 0xd0, 0x02, + 0x7d, 0xc3, 0xfe, 0x9b, 0x85, 0x73, 0xd8, 0x8c, 0x7c, 0x77, 0x55, 0xb9, + 0x40, 0x83, 0x68, 0x21, 0x6b, 0x1d, 0x8c, 0x1c, 0x82, 0x00, 0xa0, 0xe0, + 0x70, 0xc3, 0xf6, 0x4a, 0x33, 0xb6, 0xa7, 0xdc, 0xd6, 0x0d, 0x29, 0x02, + 0x9f, 0x40, 0x23, 0x99, 0x89, 0xb1, 0x7f, 0xb1, 0xf4, 0x90, 0xc1, 0x92, + 0x9c, 0xfb, 0x98, 0xfe, 0xc8, 0x6a, 0xb3, 0xb6, 0xc4, 0x4b, 0xd6, 0x40, + 0x90, 0xe9, 0x2d, 0xe6, 0xda, 0x92, 0xe0, 0x02, 0x2a, 0xf9, 0xe7, 0x79, + 0x5d, 0xd9, 0x20, 0x86, 0x54, 0xdb, 0x9f, 0xb9, 0xed, 0xba, 0x45, 0x3f, + 0x32, 0xa5, 0x94, 0x63, 0xd1, 0xe5, 0xc1, 0x55, 0xcd, 0xbf, 0x0b, 0x2a, + 0x72, 0x9c, 0x4c, 0x25, 0x8e, 0x67, 0xce, 0x35 +}; +static const uint8_t nist_186_2_ecdsa_testvector_42_private[] = { +/* d */ + 0x00, 0x9d, 0x5f, 0xd2, 0x23, 0x02, 0xb0, 0xb2, 0xd0, 0xd8, 0xe9, 0x0c, + 0x62, 0x3b, 0xa5, 0x36, 0x1c, 0xaa, 0x2c, 0xa0, 0x53, 0x23, 0x97, 0x2c, + 0x62, 0x82, 0x9a, 0xe1, 0x60, 0xb4, 0xfb, 0xfe +}; +static const uint8_t nist_186_2_ecdsa_testvector_42_public_x[] = { +/* Qx */ + 0xad, 0xcf, 0x9c, 0x09, 0x04, 0x41, 0x48, 0xd3, 0xe2, 0x4a, 0xc4, 0x12, + 0xeb, 0x96, 0x85, 0x30, 0x19, 0xcc, 0x39, 0xdf, 0x61, 0xd3, 0xa6, 0xdc, + 0x25, 0xa4, 0xa1, 0x74, 0xd1, 0xe6, 0x55, 0x03 +}; +static const uint8_t nist_186_2_ecdsa_testvector_42_public_y[] = { +/* Qy */ + 0x0c, 0x53, 0xf5, 0x52, 0x19, 0x2b, 0x2e, 0x70, 0x93, 0xef, 0x35, 0x8d, + 0x11, 0x27, 0x58, 0x49, 0x5e, 0x67, 0xb8, 0x7a, 0x4e, 0x26, 0x90, 0x4f, + 0xbf, 0x3b, 0xbb, 0x89, 0x9b, 0xde, 0x7c, 0x26 +}; +/* k = 001b1768e9de3db0bb64886c4e3becf3af3c680bc49e28263bdeddd10ede71d7 */ +static const uint8_t nist_186_2_ecdsa_testvector_42_out[] = { +/* R */ + 0x3e, 0x6d, 0xdd, 0xb2, 0x0c, 0xea, 0x38, 0x8e, 0x69, 0x47, 0xb8, 0xb8, + 0xaf, 0x28, 0x60, 0xf5, 0xbc, 0x38, 0x5d, 0xb8, 0x19, 0xdf, 0x33, 0x7e, + 0x2f, 0x7c, 0x05, 0x64, 0xfc, 0x69, 0xdd, 0xb6, +/* S */ + 0x13, 0xb2, 0xf3, 0xfe, 0x0f, 0x6e, 0x3f, 0x33, 0x01, 0x5e, 0xc2, 0x7c, + 0xa9, 0xbb, 0xaa, 0x4e, 0x0e, 0xf9, 0x37, 0x12, 0x19, 0x2d, 0x37, 0x9d, + 0xdb, 0xbf, 0x09, 0x13, 0xa8, 0xbd, 0x04, 0x59 +}; +static const uint8_t nist_186_2_ecdsa_testvector_43_ptx[] = { +/* Msg */ + 0xb3, 0xa9, 0xa9, 0xb4, 0x63, 0x11, 0x43, 0xaa, 0x6e, 0x67, 0x1f, 0xc1, + 0x68, 0xfc, 0x15, 0xff, 0x90, 0x27, 0xf2, 0x8f, 0xae, 0x98, 0x77, 0xb9, + 0x42, 0xe9, 0xa4, 0x12, 0xda, 0x76, 0x36, 0xf0, 0xc4, 0x6f, 0x6e, 0x21, + 0xe5, 0x2b, 0x14, 0xdd, 0xe9, 0xbf, 0xbc, 0xf8, 0x9d, 0xd0, 0x48, 0x5c, + 0x98, 0xa5, 0xae, 0xb7, 0x21, 0x80, 0xfb, 0x71, 0x4d, 0x2f, 0x98, 0xe1, + 0x68, 0xde, 0xcc, 0xc0, 0x96, 0x2f, 0x83, 0xde, 0xba, 0x8d, 0x4e, 0x13, + 0x97, 0xbd, 0xaa, 0x79, 0x36, 0xb5, 0x85, 0xd8, 0x87, 0xb2, 0xfe, 0x62, + 0x4a, 0x85, 0x6d, 0xa1, 0x30, 0x2d, 0xa3, 0xad, 0x3e, 0xab, 0x73, 0xa2, + 0x73, 0x12, 0x71, 0x51, 0xaa, 0xde, 0xf9, 0x36, 0xc2, 0x86, 0x73, 0xab, + 0xfb, 0x55, 0xd6, 0x5a, 0xa3, 0x75, 0x6b, 0xf8, 0xf3, 0x4d, 0xd4, 0x31, + 0x34, 0x0d, 0x4c, 0xde, 0x25, 0x86, 0x30, 0x7e +}; +static const uint8_t nist_186_2_ecdsa_testvector_43_private[] = { +/* d */ + 0x00, 0x41, 0x2b, 0xc9, 0x4f, 0x1a, 0x48, 0xff, 0xee, 0x13, 0xc3, 0xe9, + 0x6c, 0xdf, 0xc9, 0x4f, 0x3f, 0xe6, 0xef, 0x9d, 0x62, 0xf2, 0x26, 0x3a, + 0x11, 0x82, 0xed, 0xcc, 0x62, 0xfe, 0x9c, 0x84 +}; +static const uint8_t nist_186_2_ecdsa_testvector_43_public_x[] = { +/* Qx */ + 0x5c, 0xa2, 0xc1, 0x76, 0x1d, 0x40, 0x0a, 0x62, 0x61, 0x7e, 0x79, 0xfe, + 0x5f, 0xb2, 0x8c, 0xe6, 0x6d, 0xca, 0x62, 0xd0, 0xac, 0x26, 0x37, 0x93, + 0x5e, 0xd1, 0xca, 0xf4, 0x94, 0x7f, 0x70, 0xed +}; +static const uint8_t nist_186_2_ecdsa_testvector_43_public_y[] = { +/* Qy */ + 0x5d, 0x79, 0xc1, 0xb7, 0x78, 0xd6, 0xd3, 0x1c, 0x84, 0x91, 0xc3, 0x83, + 0x47, 0xf2, 0x67, 0x8f, 0xc4, 0x5c, 0x86, 0x75, 0xc7, 0x4a, 0x5a, 0x42, + 0x89, 0x5b, 0x1e, 0xd5, 0x38, 0x5f, 0xc7, 0xf9 +}; +/* k = 00a0d4137f3e02ee6b17f1ce5204bf138802ec7136bc3a048579a28efec5635f */ +static const uint8_t nist_186_2_ecdsa_testvector_43_out[] = { +/* R */ + 0xb2, 0x62, 0x19, 0xaf, 0x8c, 0xbd, 0xb9, 0x5c, 0x24, 0xba, 0x66, 0x9f, + 0x0c, 0x54, 0x63, 0x7b, 0x27, 0xec, 0x05, 0xc7, 0x12, 0x1a, 0x3c, 0x21, + 0xb9, 0x0e, 0xfd, 0xc0, 0x55, 0xf2, 0x3f, 0xd2, +/* S */ + 0x7f, 0x9a, 0x56, 0xfd, 0x23, 0xf6, 0xe9, 0x30, 0x34, 0x10, 0x7d, 0xbc, + 0xb3, 0xd5, 0xf2, 0x5d, 0xcf, 0x32, 0x5d, 0xbf, 0x59, 0xbb, 0x9f, 0xc8, + 0x6b, 0x7b, 0xb6, 0x2b, 0x54, 0x5f, 0xf2, 0x59 +}; +static const uint8_t nist_186_2_ecdsa_testvector_44_ptx[] = { +/* Msg */ + 0xec, 0x23, 0x56, 0xa8, 0xa3, 0xcc, 0x35, 0xbe, 0x88, 0xeb, 0xaf, 0x0d, + 0xa7, 0xac, 0x4e, 0xc5, 0xfe, 0x66, 0x21, 0x8b, 0x32, 0x7c, 0x0e, 0x79, + 0x81, 0x81, 0x6a, 0x66, 0xf8, 0x9f, 0xc7, 0x68, 0xe6, 0x39, 0x0d, 0x98, + 0x90, 0xcf, 0xcd, 0x15, 0x26, 0x22, 0xd1, 0x4c, 0xf6, 0x99, 0xf8, 0x76, + 0xe0, 0xe4, 0x41, 0x61, 0x0a, 0xdf, 0x25, 0x74, 0xd5, 0xb9, 0x2a, 0xee, + 0x0f, 0x55, 0xb5, 0x6e, 0x6a, 0xf0, 0x1f, 0xb8, 0x2c, 0x05, 0x0c, 0xb6, + 0x29, 0x6d, 0xf8, 0xbd, 0xee, 0xcb, 0x13, 0x12, 0x40, 0x27, 0x4f, 0xad, + 0xc5, 0xd9, 0xb7, 0x3c, 0x00, 0xa9, 0x02, 0x6b, 0x83, 0x34, 0x68, 0x63, + 0x5f, 0x92, 0xb4, 0x90, 0xe0, 0x35, 0x9b, 0xa8, 0x77, 0x14, 0x4c, 0xe9, + 0xf8, 0x09, 0x48, 0xa2, 0x05, 0x78, 0x74, 0xf4, 0xca, 0x32, 0x6c, 0xda, + 0xec, 0x99, 0x1b, 0x67, 0xbb, 0x04, 0x89, 0x4f +}; +static const uint8_t nist_186_2_ecdsa_testvector_44_private[] = { +/* d */ + 0x00, 0x81, 0x27, 0xb4, 0xaa, 0x2a, 0xec, 0x3b, 0x30, 0x27, 0xab, 0x7f, + 0x8b, 0x5d, 0xf1, 0xcb, 0x41, 0x54, 0xdc, 0x5c, 0x6a, 0x03, 0x30, 0xa2, + 0x32, 0xec, 0x07, 0xe5, 0x94, 0xd3, 0x06, 0xcc +}; +static const uint8_t nist_186_2_ecdsa_testvector_44_public_x[] = { +/* Qx */ + 0x79, 0x89, 0x9b, 0x96, 0xa4, 0x40, 0xc9, 0x12, 0xe4, 0x6e, 0x31, 0xc6, + 0x4d, 0xcd, 0xb8, 0xc1, 0x8d, 0x3d, 0x8a, 0x29, 0xb7, 0x75, 0xe4, 0xc0, + 0xff, 0xec, 0xe9, 0x1f, 0xaf, 0xb7, 0xc4, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_44_public_y[] = { +/* Qy */ + 0x4f, 0x14, 0x68, 0x9d, 0xed, 0x44, 0xbe, 0xcc, 0x4d, 0x74, 0x01, 0xbf, + 0x39, 0xcc, 0x36, 0x8f, 0xa1, 0x83, 0xfe, 0xba, 0x2e, 0x41, 0x6c, 0xe1, + 0x61, 0x7d, 0x59, 0xfe, 0x4c, 0x2b, 0xa7, 0x7c +}; +/* k = 00d30706db4e88261037558bf275fb93c7d8778fe20b832e4e3b9b162b1ed12b */ +static const uint8_t nist_186_2_ecdsa_testvector_44_out[] = { +/* R */ + 0x54, 0xe8, 0x2e, 0xa0, 0xaf, 0xf8, 0x3d, 0xfb, 0xeb, 0x8c, 0xea, 0x1f, + 0xdd, 0x7d, 0x69, 0x50, 0xd6, 0xdd, 0x34, 0x46, 0xc1, 0xee, 0x52, 0x45, + 0x53, 0xc6, 0x0d, 0x54, 0x81, 0xcc, 0x52, 0x1e, +/* S */ + 0xf7, 0x51, 0x43, 0x14, 0xdf, 0x4c, 0x0e, 0xb7, 0xfe, 0x0d, 0x95, 0xdf, + 0x0f, 0xc6, 0xfe, 0x5e, 0x38, 0xb8, 0x59, 0x06, 0x13, 0x55, 0x5a, 0x8d, + 0xb2, 0x86, 0x9c, 0x6f, 0x87, 0x41, 0xdc, 0x25 +}; +static const uint8_t nist_186_2_ecdsa_testvector_45_ptx[] = { +/* Msg */ + 0x3b, 0xda, 0x9b, 0xb0, 0xd7, 0xe0, 0x36, 0x13, 0x51, 0xc2, 0xdf, 0x68, + 0xa1, 0x28, 0xee, 0xb9, 0x75, 0x95, 0x2a, 0xbd, 0x79, 0x98, 0x33, 0xac, + 0xd6, 0x46, 0x1d, 0x51, 0xf8, 0xe7, 0x5e, 0x61, 0x95, 0xf0, 0xea, 0x0b, + 0xeb, 0x32, 0x9c, 0xd0, 0x49, 0x50, 0xd8, 0x95, 0xd0, 0x76, 0x6f, 0xf7, + 0x7b, 0x48, 0xc2, 0xde, 0x5d, 0x19, 0x2b, 0x55, 0x2a, 0x5e, 0x98, 0x99, + 0xf9, 0x62, 0x79, 0x6f, 0x48, 0x3b, 0xdd, 0xbb, 0x41, 0xfc, 0xd7, 0x4f, + 0x3c, 0x2c, 0x27, 0x01, 0x84, 0x77, 0x16, 0x00, 0x5e, 0xa4, 0xa2, 0x68, + 0x47, 0xc7, 0xdb, 0x13, 0x7e, 0xb8, 0x8d, 0xb3, 0xc2, 0xc3, 0x1f, 0x1d, + 0x5d, 0xa1, 0xbb, 0xe8, 0x61, 0xa7, 0xb0, 0x37, 0x32, 0x3e, 0x14, 0xd3, + 0x44, 0x93, 0xad, 0x7d, 0x26, 0x90, 0x12, 0x82, 0xc0, 0x0a, 0x0d, 0x8f, + 0xd9, 0x3c, 0x44, 0xc7, 0xdc, 0x74, 0x18, 0x13 +}; +static const uint8_t nist_186_2_ecdsa_testvector_45_private[] = { +/* d */ + 0x00, 0xd0, 0x07, 0xe1, 0xb9, 0xaf, 0xcc, 0x31, 0x2e, 0xec, 0x9c, 0xec, + 0xff, 0xa0, 0x28, 0x07, 0x52, 0xbb, 0xd1, 0x95, 0x31, 0x82, 0xed, 0xef, + 0x12, 0xf3, 0xfc, 0x36, 0x6e, 0x8f, 0x43, 0x56 +}; +static const uint8_t nist_186_2_ecdsa_testvector_45_public_x[] = { +/* Qx */ + 0xd6, 0x60, 0x62, 0x71, 0x13, 0x1e, 0x7e, 0x7e, 0x61, 0x7a, 0x81, 0xaa, + 0x11, 0xf0, 0x9e, 0x7e, 0xd5, 0x63, 0x11, 0x82, 0x88, 0x23, 0x36, 0x7a, + 0x86, 0x9b, 0x45, 0x40, 0x40, 0xb3, 0xf9, 0x05 +}; +static const uint8_t nist_186_2_ecdsa_testvector_45_public_y[] = { +/* Qy */ + 0xcf, 0x48, 0x97, 0x76, 0x61, 0x31, 0xaa, 0x8b, 0x7f, 0x80, 0x45, 0x3a, + 0x15, 0xbf, 0x90, 0xf7, 0x51, 0x78, 0x78, 0x57, 0x9d, 0x5a, 0x4f, 0x97, + 0x3a, 0xea, 0x5b, 0xb1, 0x15, 0x42, 0xe0, 0x7f +}; +/* k = 00c03c3b8b1e40cb328a61d51783356935625884399e26a5828f387c2bde6ebc */ +static const uint8_t nist_186_2_ecdsa_testvector_45_out[] = { +/* R */ + 0xb5, 0xb4, 0x17, 0x61, 0x9b, 0xf9, 0xfa, 0x89, 0xd5, 0x0b, 0x3e, 0x22, + 0x78, 0x2a, 0x2d, 0xe8, 0x0a, 0x86, 0xdb, 0x67, 0xe7, 0x28, 0x11, 0x4e, + 0x6e, 0x0e, 0x91, 0xca, 0xb1, 0xa4, 0x16, 0x12, +/* S */ + 0xe4, 0x3e, 0x81, 0x11, 0x25, 0x8b, 0xea, 0x6f, 0x5c, 0x96, 0xbd, 0x6d, + 0x66, 0x71, 0x57, 0x48, 0xfb, 0xee, 0x75, 0x6d, 0xa4, 0x18, 0xde, 0x90, + 0xf6, 0x40, 0x66, 0xc6, 0xb3, 0xe0, 0x72, 0xf1 +}; +/* [P-384] */ +static const uint8_t nist_186_2_ecdsa_testvector_46_ptx[] = { +/* Msg */ + 0x4c, 0x06, 0x49, 0x1c, 0x03, 0x9e, 0x8a, 0x81, 0x9b, 0xbc, 0xbd, 0x80, + 0x15, 0x2d, 0x0c, 0xed, 0xfe, 0x1a, 0x8c, 0xd6, 0x44, 0x8a, 0xb8, 0x1e, + 0x48, 0x28, 0x1f, 0x68, 0x34, 0x47, 0x59, 0x36, 0x8f, 0x23, 0x3f, 0x52, + 0x0f, 0x69, 0x5c, 0x6e, 0xae, 0xfa, 0x9e, 0x07, 0xff, 0xec, 0x51, 0x8f, + 0xc3, 0xd2, 0x4e, 0xca, 0xb8, 0x3e, 0x70, 0x79, 0xb1, 0x84, 0x48, 0x36, + 0xeb, 0xc0, 0x12, 0x9f, 0x9f, 0x1a, 0xe7, 0xb6, 0xd4, 0x48, 0x34, 0x88, + 0x77, 0x55, 0x6a, 0x0d, 0xad, 0xa1, 0xf7, 0x50, 0x68, 0x2a, 0x76, 0xcf, + 0x39, 0x09, 0x22, 0x25, 0x65, 0x40, 0x91, 0xe6, 0x3a, 0xb2, 0x9f, 0xcb, + 0xa3, 0x73, 0xa8, 0x0f, 0xfb, 0x42, 0xfa, 0x18, 0x1f, 0x54, 0x89, 0x5a, + 0xc7, 0x54, 0xe5, 0x79, 0x16, 0xa7, 0x6a, 0xad, 0x6f, 0xf4, 0xb6, 0x6b, + 0x8b, 0xe4, 0x61, 0x42, 0xc8, 0x26, 0xe8, 0x03 +}; +static const uint8_t nist_186_2_ecdsa_testvector_46_private[] = { +/* d */ + 0x00, 0x82, 0x75, 0x7d, 0x5b, 0x9d, 0xb0, 0x84, 0xbd, 0x2e, 0x09, 0x21, + 0xa6, 0xce, 0x62, 0x10, 0x76, 0xf3, 0xf4, 0x3a, 0x52, 0x35, 0x65, 0xa7, + 0x67, 0x10, 0xc9, 0xa1, 0xdc, 0xc7, 0xc5, 0xf4, 0xb1, 0xa4, 0x23, 0x7f, + 0x24, 0xc5, 0x36, 0x14, 0x15, 0x3e, 0xd9, 0x7b, 0x42, 0x3a, 0x27, 0x77 +}; +static const uint8_t nist_186_2_ecdsa_testvector_46_public_x[] = { +/* Qx */ + 0x32, 0x71, 0x93, 0x8d, 0x4c, 0xd1, 0x44, 0x00, 0x6b, 0x45, 0xc7, 0x3f, + 0x2a, 0x89, 0x30, 0xdf, 0xf8, 0x23, 0x8e, 0x72, 0x20, 0x49, 0x60, 0x00, + 0xbe, 0x36, 0x94, 0xaa, 0x54, 0x18, 0x06, 0x32, 0x71, 0xc2, 0xe1, 0x29, + 0x12, 0xb6, 0xc1, 0xcb, 0xc0, 0x3c, 0x41, 0x75, 0x37, 0x3c, 0x3a, 0x3e +}; +static const uint8_t nist_186_2_ecdsa_testvector_46_public_y[] = { +/* Qy */ + 0xd3, 0x4f, 0x52, 0x57, 0xd2, 0x30, 0xa4, 0x64, 0x95, 0x8d, 0x1f, 0xff, + 0x57, 0x0a, 0x2f, 0x55, 0xfe, 0x64, 0x01, 0xc8, 0x3a, 0x61, 0x3a, 0x53, + 0x38, 0x9a, 0x82, 0x95, 0x7e, 0xaa, 0x63, 0x9e, 0x38, 0x98, 0xcf, 0xe9, + 0x82, 0x3d, 0x57, 0xb3, 0x8b, 0xae, 0xe3, 0x0f, 0x5c, 0x94, 0xf7, 0xe1 +}; +/* k = 003d87d4516517e73854719d4ba3ecc1c6f90e1438b540c628f22d177b7bff158f6dc5b11d20ac390a57516f061c25b4 */ +static const uint8_t nist_186_2_ecdsa_testvector_46_out[] = { +/* R */ + 0xa8, 0x92, 0x97, 0x84, 0xc4, 0x3f, 0xa3, 0xd1, 0x1e, 0x31, 0x69, 0x61, + 0x61, 0x31, 0xa9, 0x61, 0xc8, 0x80, 0xba, 0x74, 0x42, 0xca, 0xdc, 0xab, + 0x6d, 0xf9, 0x87, 0x44, 0xdb, 0x7d, 0x1e, 0xc0, 0x15, 0x0a, 0x5e, 0x34, + 0x5c, 0xc1, 0x49, 0x9d, 0xb7, 0x1e, 0xd7, 0x17, 0x5d, 0xb2, 0x95, 0x4d, +/* S */ + 0x56, 0xdd, 0xef, 0x0b, 0x15, 0xa8, 0x80, 0x4b, 0x08, 0x90, 0x9e, 0x66, + 0x96, 0x58, 0x1b, 0x7d, 0x5a, 0x3a, 0xba, 0x1c, 0x7d, 0x28, 0x0c, 0x74, + 0x86, 0xbc, 0x26, 0x4a, 0x24, 0x63, 0x54, 0x47, 0x0d, 0x80, 0x3e, 0xac, + 0x03, 0x4b, 0xbe, 0x0d, 0xc9, 0xe7, 0x8a, 0x74, 0x2c, 0x83, 0x16, 0x0f +}; +static const uint8_t nist_186_2_ecdsa_testvector_47_ptx[] = { +/* Msg */ + 0x9d, 0xb0, 0xc2, 0x58, 0x24, 0x41, 0xd8, 0xfa, 0xd4, 0xb5, 0x2f, 0x1f, + 0x29, 0xa8, 0xc2, 0x64, 0xa0, 0xb2, 0x99, 0x42, 0x1c, 0x3b, 0x4a, 0x86, + 0x87, 0x91, 0xc0, 0x02, 0xbc, 0x37, 0x3b, 0x83, 0xa5, 0x81, 0x98, 0x03, + 0xa0, 0x5d, 0xd3, 0x1f, 0x28, 0x74, 0xca, 0xcb, 0xb1, 0x72, 0x43, 0x44, + 0xd3, 0xa1, 0x31, 0x46, 0xab, 0xbd, 0x33, 0x80, 0x7f, 0x04, 0x5e, 0x45, + 0xa0, 0x8c, 0x3c, 0x84, 0x95, 0xd9, 0x14, 0xfa, 0x75, 0xaf, 0x6c, 0xa6, + 0x95, 0x25, 0xcd, 0x7d, 0x63, 0xfb, 0xc6, 0x60, 0x92, 0x2d, 0x33, 0x4b, + 0x78, 0xc8, 0xc0, 0xcf, 0xb4, 0xfd, 0xa8, 0xc2, 0x13, 0x74, 0xc3, 0x35, + 0xb5, 0xe3, 0xbf, 0xa6, 0x6b, 0xde, 0xad, 0x77, 0x64, 0xf1, 0xc0, 0x9f, + 0x09, 0xec, 0x52, 0xa0, 0x25, 0x7e, 0x28, 0xb9, 0x49, 0x05, 0xf7, 0x5c, + 0x6f, 0xa5, 0x27, 0xe2, 0xdd, 0x97, 0xd6, 0x7e +}; +static const uint8_t nist_186_2_ecdsa_testvector_47_private[] = { +/* d */ + 0x00, 0x73, 0x04, 0x6c, 0x07, 0xdf, 0x4a, 0x1d, 0xbf, 0xba, 0xb1, 0x9c, + 0x24, 0x8b, 0x8c, 0x2b, 0x5c, 0x27, 0xe5, 0x86, 0x4a, 0xd4, 0x4b, 0xe3, + 0x4d, 0xf4, 0x76, 0x78, 0xde, 0x5b, 0x9c, 0xbd, 0xc7, 0x47, 0x3b, 0xe9, + 0x52, 0x58, 0xfb, 0x43, 0x20, 0xfd, 0x70, 0x03, 0x15, 0x62, 0x84, 0xfc +}; +static const uint8_t nist_186_2_ecdsa_testvector_47_public_x[] = { +/* Qx */ + 0x24, 0x38, 0xdf, 0xad, 0x2b, 0x99, 0x6d, 0x6e, 0xad, 0xf9, 0x78, 0x45, + 0xdc, 0xc2, 0xe6, 0x86, 0xd8, 0xc5, 0x48, 0x43, 0x07, 0x70, 0xb8, 0x1e, + 0xf9, 0xaf, 0x84, 0xd7, 0xae, 0xe5, 0x5c, 0xbd, 0x14, 0xeb, 0x84, 0xfc, + 0xce, 0x7e, 0x3c, 0x5e, 0x90, 0x19, 0xd2, 0x1b, 0x1d, 0xbb, 0x58, 0x97 +}; +static const uint8_t nist_186_2_ecdsa_testvector_47_public_y[] = { +/* Qy */ + 0xb3, 0xa0, 0xee, 0x8e, 0x90, 0x95, 0x70, 0x18, 0x92, 0xf7, 0x37, 0x09, + 0x9a, 0x74, 0xc7, 0xde, 0xe3, 0x50, 0x5e, 0x87, 0xbe, 0x8d, 0xbe, 0xa4, + 0xbf, 0x1e, 0xa5, 0x55, 0xf9, 0x3d, 0x44, 0x8f, 0xde, 0xef, 0x50, 0x9d, + 0x9b, 0x67, 0x95, 0xf8, 0x4d, 0x6d, 0x9a, 0xc0, 0x9c, 0x9b, 0xa8, 0x12 +}; +/* k = 002ec0faebc17e7fa2dcdbc11a94049022b2cdc2afce60428a97206fb3f35194d75e7b1d305a3069e590b13800256bc1 */ +static const uint8_t nist_186_2_ecdsa_testvector_47_out[] = { +/* R */ + 0xf6, 0xb7, 0xbb, 0x08, 0x2f, 0x67, 0x75, 0x75, 0x1e, 0x12, 0x3c, 0x67, + 0x54, 0x8a, 0xaf, 0xc3, 0x44, 0xce, 0x68, 0x9b, 0x63, 0xb7, 0xbd, 0x3b, + 0x6b, 0x34, 0x9b, 0xe1, 0x6e, 0x19, 0xda, 0x9b, 0x9d, 0xac, 0x4e, 0x42, + 0x4a, 0xc6, 0x46, 0xc0, 0xf2, 0x44, 0xd6, 0xbc, 0x51, 0x6d, 0x30, 0xac, +/* S */ + 0x5b, 0x95, 0x57, 0x4d, 0x2f, 0x2c, 0x99, 0xef, 0xe9, 0xbb, 0x1b, 0xbe, + 0xea, 0xda, 0x2d, 0x17, 0x42, 0xd4, 0xff, 0xff, 0xf2, 0x11, 0x02, 0x14, + 0x77, 0x07, 0x62, 0x94, 0x90, 0x76, 0x5e, 0xe4, 0x51, 0x3a, 0x90, 0x9e, + 0xa7, 0xa4, 0x05, 0xce, 0x84, 0x02, 0x2f, 0xbd, 0xde, 0x77, 0x26, 0xc8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_48_ptx[] = { +/* Msg */ + 0xd4, 0xe1, 0x2e, 0x9a, 0x4a, 0x91, 0x28, 0xca, 0xa0, 0x1d, 0x19, 0x7c, + 0x41, 0x55, 0x5e, 0x24, 0x21, 0x6e, 0x2a, 0xbc, 0xa1, 0x54, 0x87, 0xba, + 0xb3, 0x41, 0x97, 0x3f, 0x3e, 0x8f, 0x20, 0x91, 0xc4, 0xcb, 0x47, 0xcb, + 0x42, 0x0a, 0x9c, 0xd3, 0x57, 0x80, 0x57, 0x8d, 0xa9, 0x4e, 0xe1, 0x4e, + 0x85, 0x9c, 0x97, 0x94, 0xc5, 0xe8, 0xca, 0xf4, 0xf7, 0x9d, 0x0a, 0x53, + 0xbb, 0xe8, 0xa4, 0x59, 0x6d, 0xc7, 0x69, 0x23, 0x04, 0x63, 0xb1, 0x38, + 0x3a, 0x9f, 0xa0, 0xbf, 0xee, 0xf1, 0xa8, 0xef, 0xc6, 0x71, 0x4f, 0xc6, + 0x18, 0x2f, 0x33, 0xfe, 0x0b, 0xca, 0x4b, 0x3d, 0xf9, 0x3e, 0x6f, 0x8c, + 0x18, 0xfe, 0x1b, 0x0a, 0x5a, 0x43, 0x70, 0xe1, 0x91, 0xa3, 0x7b, 0x7a, + 0xd7, 0xe5, 0xba, 0xed, 0x2d, 0x14, 0xdc, 0xbc, 0x62, 0xd2, 0xc9, 0xc0, + 0x37, 0xef, 0xe2, 0x63, 0xc0, 0x3a, 0x8a, 0x10 +}; +static const uint8_t nist_186_2_ecdsa_testvector_48_private[] = { +/* d */ + 0x00, 0xf3, 0x64, 0xa5, 0x72, 0x6d, 0x99, 0x6f, 0x6d, 0xd8, 0xd6, 0x37, + 0x22, 0xe8, 0xbf, 0x54, 0xfc, 0xed, 0x1e, 0x5d, 0xc0, 0x67, 0x34, 0xef, + 0xff, 0xc4, 0xdf, 0x46, 0x58, 0xa8, 0x80, 0x14, 0xe1, 0x51, 0xd2, 0x04, + 0x9f, 0x28, 0x4c, 0xbf, 0x32, 0xb4, 0xfd, 0xc0, 0x9d, 0x0e, 0xca, 0xf4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_48_public_x[] = { +/* Qx */ + 0x8b, 0xb6, 0x3e, 0xa0, 0x43, 0x94, 0x81, 0xf6, 0x97, 0x14, 0x2c, 0x89, + 0x86, 0x70, 0xce, 0x27, 0x54, 0xe0, 0x4f, 0x3b, 0xae, 0x95, 0x5b, 0xa5, + 0xf4, 0x5c, 0xe9, 0xbc, 0x2d, 0x24, 0x55, 0x3a, 0xbb, 0xb8, 0xa3, 0x58, + 0x33, 0x9c, 0x25, 0x7f, 0xdc, 0x39, 0x7a, 0xb1, 0x58, 0x76, 0x7b, 0x7a +}; +static const uint8_t nist_186_2_ecdsa_testvector_48_public_y[] = { +/* Qy */ + 0xc8, 0x5c, 0x9c, 0x73, 0xc3, 0x1d, 0x4e, 0x10, 0x5d, 0x4e, 0x8f, 0x1e, + 0x6a, 0x93, 0xcb, 0x39, 0xa4, 0xdb, 0x39, 0xd5, 0x78, 0xae, 0xa5, 0xa3, + 0xac, 0x04, 0x2b, 0xae, 0x28, 0x93, 0x48, 0x5a, 0x27, 0xeb, 0x23, 0x6d, + 0x0f, 0xa1, 0xe3, 0xe6, 0x75, 0xea, 0x29, 0x19, 0x01, 0xea, 0xd2, 0xe2 +}; +/* k = 00040825897316c3c233a99b9b75c1017c97f25770a6384c7b45e5cb8a0db87941b1e193362e9fc6971480c111939ecc */ +static const uint8_t nist_186_2_ecdsa_testvector_48_out[] = { +/* R */ + 0x61, 0xd9, 0x46, 0x4f, 0x89, 0xd0, 0x0c, 0x77, 0xc4, 0x27, 0x19, 0x78, + 0xdc, 0xec, 0x8e, 0x7e, 0xd2, 0xb3, 0x71, 0xa5, 0x59, 0x10, 0x1e, 0xc6, + 0xa2, 0xe3, 0x9a, 0x36, 0xe5, 0xfb, 0xe3, 0xbc, 0x22, 0x0e, 0xad, 0xff, + 0xa1, 0x8f, 0xf3, 0x6f, 0x74, 0xf3, 0xb1, 0x6e, 0x05, 0x52, 0x77, 0xa5, +/* S */ + 0xf9, 0xbc, 0xc9, 0x97, 0x15, 0x83, 0x1b, 0x63, 0x32, 0x1c, 0xa2, 0x4b, + 0xd1, 0x23, 0x33, 0x9c, 0x72, 0xb3, 0x97, 0x92, 0x7e, 0x53, 0x32, 0x8f, + 0x9f, 0xb3, 0x21, 0x19, 0xda, 0x23, 0x2a, 0x98, 0xb3, 0xfc, 0xf8, 0x90, + 0x8c, 0xfa, 0x62, 0x31, 0x0c, 0x52, 0x6b, 0xf1, 0x7f, 0x8d, 0x61, 0xf6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_49_ptx[] = { +/* Msg */ + 0xcb, 0x2b, 0x95, 0x2b, 0x99, 0xaa, 0x98, 0xd9, 0xa8, 0x77, 0x82, 0x6d, + 0x36, 0x29, 0x97, 0xe9, 0xd6, 0x58, 0x25, 0x30, 0x64, 0xb9, 0x18, 0x56, + 0x3e, 0x8a, 0xc8, 0x1a, 0xb1, 0x31, 0x15, 0xb1, 0xb2, 0x20, 0xb6, 0xc6, + 0xcf, 0xfb, 0xce, 0xbe, 0x65, 0xfd, 0xc0, 0x40, 0x12, 0x98, 0x45, 0xf5, + 0x6d, 0x5b, 0xbc, 0x8c, 0xf5, 0x19, 0xc1, 0x02, 0x48, 0x48, 0x00, 0x20, + 0x96, 0xa7, 0x4b, 0x45, 0x54, 0x24, 0xeb, 0x65, 0x35, 0xfc, 0x34, 0x52, + 0x56, 0x24, 0x5d, 0x3a, 0xb8, 0xe8, 0x8e, 0x71, 0xf4, 0xd2, 0x39, 0x71, + 0x2a, 0xcd, 0xae, 0x20, 0x3b, 0x8a, 0xea, 0x51, 0x38, 0x23, 0xb0, 0x8c, + 0x1a, 0xfe, 0xdc, 0x12, 0xb3, 0xf5, 0xf3, 0x1c, 0xe4, 0xb3, 0xfe, 0x64, + 0x11, 0x61, 0x99, 0xe6, 0xd2, 0x83, 0x47, 0xe8, 0xeb, 0x1c, 0x08, 0x38, + 0x7f, 0x19, 0x2e, 0xb5, 0x80, 0xec, 0x6c, 0x10 +}; +static const uint8_t nist_186_2_ecdsa_testvector_49_private[] = { +/* d */ + 0x00, 0x9b, 0xf1, 0x50, 0x1f, 0xd7, 0xb7, 0xdd, 0x4a, 0x4c, 0xfe, 0x01, + 0x87, 0x58, 0x2c, 0xa2, 0x96, 0xed, 0x31, 0xe7, 0xfb, 0x15, 0xe8, 0x5b, + 0xed, 0x0d, 0x2c, 0x95, 0xba, 0xb2, 0x67, 0xd1, 0x62, 0x7f, 0x58, 0x17, + 0xde, 0x28, 0x6e, 0xe5, 0x06, 0x32, 0x71, 0x26, 0x18, 0x18, 0x25, 0x52 +}; +static const uint8_t nist_186_2_ecdsa_testvector_49_public_x[] = { +/* Qx */ + 0xdf, 0x9b, 0x25, 0x6d, 0x12, 0xbf, 0x94, 0xcd, 0x58, 0xea, 0x44, 0xb3, + 0x6c, 0x64, 0xaf, 0xbb, 0xf1, 0x98, 0x0a, 0x98, 0xc4, 0x7b, 0xc0, 0x14, + 0x3f, 0x11, 0xa2, 0xed, 0x9e, 0x98, 0x76, 0x66, 0x67, 0xf7, 0x49, 0xef, + 0xc5, 0xaf, 0x76, 0x7c, 0x99, 0xdd, 0x9e, 0xb5, 0xb1, 0xa9, 0x96, 0x91 +}; +static const uint8_t nist_186_2_ecdsa_testvector_49_public_y[] = { +/* Qy */ + 0x94, 0x53, 0xa0, 0xe0, 0x01, 0x5b, 0x8d, 0x94, 0x3d, 0xf7, 0xa2, 0xba, + 0x26, 0xd8, 0xdf, 0xaf, 0xce, 0x07, 0xb6, 0x74, 0xd9, 0x0c, 0x6b, 0x6f, + 0xee, 0xd0, 0x74, 0xe0, 0xab, 0xfd, 0x7e, 0xef, 0x3d, 0x49, 0x62, 0x56, + 0xc1, 0xc4, 0x12, 0x46, 0x29, 0xc2, 0xeb, 0xb3, 0xe4, 0xcd, 0xe6, 0x11 +}; +/* k = 0018ea0c817eee1dba088205eaacf0c2c48b40b546371c31a74998beee52d6b1937eee33755e3d20a2c1433d56a90844 */ +static const uint8_t nist_186_2_ecdsa_testvector_49_out[] = { +/* R */ + 0x25, 0x0a, 0x4b, 0x5d, 0xee, 0x20, 0x3d, 0x0e, 0x56, 0xad, 0x5b, 0x95, + 0x42, 0x61, 0x21, 0x8d, 0xb5, 0xe2, 0x3a, 0x07, 0xe4, 0x4f, 0x46, 0x07, + 0xe0, 0x8a, 0x34, 0x54, 0xfa, 0x84, 0x8c, 0x45, 0x27, 0x17, 0x2e, 0x95, + 0x11, 0xb4, 0xed, 0x3c, 0x6f, 0x60, 0x58, 0x17, 0x07, 0x5f, 0xbc, 0x7e, +/* S */ + 0x86, 0xd0, 0x4b, 0x60, 0xb7, 0x58, 0x6f, 0x11, 0xca, 0xe4, 0xfd, 0x12, + 0xd4, 0x2f, 0xa7, 0x9b, 0x27, 0x28, 0x90, 0x6b, 0x76, 0xa3, 0x9e, 0xeb, + 0x2e, 0xb5, 0xd3, 0x84, 0x78, 0x4a, 0xc1, 0x53, 0xb7, 0x6f, 0xd2, 0xfb, + 0xd3, 0x2d, 0xbe, 0xcc, 0x48, 0x54, 0x90, 0x93, 0x68, 0xe5, 0x54, 0xe2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_50_ptx[] = { +/* Msg */ + 0xd1, 0xb5, 0x10, 0x9d, 0x0c, 0xa8, 0x8a, 0x78, 0xdf, 0x42, 0xc6, 0xe0, + 0x8e, 0xc4, 0xd5, 0x36, 0x44, 0xbd, 0xd6, 0xad, 0xb4, 0x24, 0xb9, 0x02, + 0x01, 0xa4, 0x48, 0x67, 0xdb, 0x37, 0x67, 0xc0, 0xec, 0xf6, 0x9a, 0x11, + 0x72, 0x30, 0xc9, 0x37, 0x2d, 0xb9, 0x40, 0xd7, 0x7b, 0x84, 0xfa, 0x95, + 0xc2, 0x74, 0x1f, 0x86, 0x0e, 0x70, 0xcb, 0xe7, 0xfb, 0xb6, 0x11, 0x0f, + 0xd6, 0x71, 0x40, 0xa2, 0xff, 0x8d, 0x64, 0x08, 0x91, 0xca, 0x10, 0x1d, + 0x45, 0x0f, 0x5b, 0x2a, 0x94, 0x02, 0x29, 0x15, 0x1c, 0xd5, 0xac, 0xd4, + 0x45, 0x62, 0x2a, 0x27, 0x24, 0x7b, 0x00, 0x87, 0xa0, 0x7b, 0xe7, 0x59, + 0xd3, 0x21, 0x76, 0x68, 0xb3, 0x9f, 0xe8, 0x92, 0xf1, 0xed, 0x20, 0xc2, + 0x21, 0x63, 0xea, 0x1e, 0x1c, 0x87, 0x84, 0x81, 0xa2, 0x24, 0x5d, 0x2b, + 0x44, 0x9c, 0x1c, 0xb7, 0x81, 0x7e, 0xe4, 0x4e +}; +static const uint8_t nist_186_2_ecdsa_testvector_50_private[] = { +/* d */ + 0x00, 0xb7, 0x69, 0x01, 0x62, 0x28, 0x64, 0x4e, 0xcb, 0x3e, 0xda, 0xaf, + 0x65, 0x1c, 0x7b, 0x86, 0xbc, 0x28, 0xda, 0xf4, 0xa8, 0xdc, 0x4a, 0xaa, + 0x2f, 0xcc, 0xa2, 0xdb, 0x5a, 0xba, 0x25, 0x6f, 0xe5, 0xea, 0xc2, 0xf6, + 0x91, 0x1e, 0xbf, 0xf8, 0x08, 0x22, 0xb0, 0xcc, 0x57, 0x5a, 0x9f, 0xb5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_50_public_x[] = { +/* Qx */ + 0xfa, 0xe8, 0x8b, 0xf1, 0x19, 0x0c, 0x5e, 0xf9, 0x3d, 0x49, 0xae, 0xa2, + 0xce, 0xe1, 0xa4, 0x67, 0xc8, 0xb2, 0xe3, 0xdd, 0x45, 0x7e, 0x29, 0x78, + 0x77, 0x31, 0xc1, 0x0a, 0x4f, 0x6c, 0xb7, 0x13, 0xbd, 0xc6, 0x1a, 0x7b, + 0x20, 0x64, 0xb2, 0x54, 0x8f, 0xc6, 0x1e, 0x66, 0x01, 0x64, 0x6b, 0x6d +}; +static const uint8_t nist_186_2_ecdsa_testvector_50_public_y[] = { +/* Qy */ + 0x46, 0x9f, 0x73, 0x00, 0x45, 0x02, 0x27, 0x62, 0x61, 0x67, 0x24, 0x62, + 0x1c, 0x0b, 0x20, 0xfe, 0x4f, 0x4b, 0x8b, 0xf7, 0x30, 0xbd, 0xf4, 0x4d, + 0xad, 0xec, 0x59, 0xd0, 0x14, 0x6b, 0x91, 0x39, 0x3b, 0xe9, 0xbf, 0x49, + 0x79, 0xfd, 0xb3, 0x1f, 0x83, 0x0e, 0x86, 0x7b, 0xab, 0x49, 0xd9, 0xe8 +}; +/* k = 00c7454092e11ce4d4aef9c710a219dc8513aa3aa34de85c3c6d3a50d3ccc993d029bca4013ee6fd7ec9ab5e5806f209 */ +static const uint8_t nist_186_2_ecdsa_testvector_50_out[] = { +/* R */ + 0x07, 0xfb, 0x1b, 0xa7, 0x93, 0xa3, 0x4c, 0x92, 0x32, 0x46, 0x60, 0xb7, + 0x8b, 0xe1, 0xb5, 0x02, 0x75, 0xdc, 0x3e, 0x6c, 0xff, 0x82, 0xd3, 0x3c, + 0x4c, 0x6d, 0xb7, 0xfb, 0xcd, 0x9a, 0x53, 0xb9, 0x27, 0xcc, 0xe0, 0x75, + 0x93, 0xaf, 0x77, 0x9c, 0xff, 0x48, 0xff, 0x7f, 0x2d, 0xed, 0xfe, 0x8e, +/* S */ + 0xc7, 0x1b, 0x22, 0x17, 0x9e, 0xfb, 0x3a, 0xd7, 0xd9, 0x12, 0x79, 0xc0, + 0x8c, 0x7c, 0x31, 0x94, 0x78, 0xc7, 0xaa, 0x05, 0xda, 0x2a, 0x9c, 0x12, + 0x06, 0x8f, 0xb1, 0xb8, 0xd6, 0x8d, 0x0d, 0x47, 0xdb, 0x02, 0x26, 0xb3, + 0xa3, 0x5f, 0xbf, 0x91, 0x4e, 0xe1, 0x7a, 0x49, 0xae, 0x70, 0x86, 0x11 +}; +static const uint8_t nist_186_2_ecdsa_testvector_51_ptx[] = { +/* Msg */ + 0x52, 0x82, 0x49, 0x5b, 0xa2, 0x45, 0x27, 0x95, 0xbd, 0xd8, 0xfd, 0x9c, + 0x47, 0xa2, 0xae, 0x9f, 0x40, 0xee, 0x68, 0xde, 0x7d, 0x8d, 0xc1, 0x69, + 0x59, 0xc3, 0x06, 0x2a, 0xa8, 0x61, 0xcf, 0x25, 0xec, 0x2e, 0xd7, 0xff, + 0xcc, 0x8b, 0x0b, 0xbd, 0xc1, 0x57, 0xe1, 0xcf, 0x13, 0x11, 0xeb, 0x4d, + 0x04, 0x3c, 0xac, 0x80, 0x4a, 0x08, 0xaa, 0xa4, 0xc3, 0x2e, 0xc4, 0xec, + 0x65, 0x1c, 0xc6, 0xc7, 0x74, 0x52, 0x3b, 0x62, 0xf7, 0x0c, 0x83, 0x6e, + 0x6c, 0x21, 0x25, 0x23, 0xbb, 0x2b, 0x66, 0x85, 0x69, 0xe8, 0x1a, 0xe6, + 0x0e, 0xe0, 0xba, 0xac, 0x09, 0x48, 0xb7, 0x54, 0x72, 0x27, 0x0e, 0xb7, + 0x50, 0xb7, 0x1d, 0x8c, 0x0c, 0x0e, 0xb4, 0x2f, 0x26, 0xfd, 0x70, 0xa1, + 0x27, 0x39, 0x44, 0xcf, 0xd7, 0xb8, 0x59, 0x17, 0xaf, 0x5e, 0x18, 0x08, + 0x91, 0xd9, 0x85, 0x69, 0xb7, 0xca, 0xce, 0x7d +}; +static const uint8_t nist_186_2_ecdsa_testvector_51_private[] = { +/* d */ + 0x00, 0x66, 0x14, 0x40, 0x20, 0xde, 0xa9, 0x67, 0x35, 0x0d, 0x34, 0x09, + 0xe0, 0x6a, 0xe3, 0xe9, 0x31, 0x9b, 0xe3, 0x25, 0xa3, 0x23, 0xf9, 0x37, + 0xee, 0xaf, 0xf9, 0x1a, 0xb1, 0x34, 0xe2, 0x19, 0x9c, 0x79, 0x28, 0x9c, + 0xd6, 0x7c, 0x01, 0x0f, 0xe1, 0xbb, 0x0b, 0x7a, 0x57, 0x20, 0x32, 0x37 +}; +static const uint8_t nist_186_2_ecdsa_testvector_51_public_x[] = { +/* Qx */ + 0xc4, 0x8e, 0x79, 0xb3, 0xb9, 0xe9, 0x35, 0xce, 0x9a, 0x84, 0x55, 0x26, + 0xd9, 0x5d, 0x32, 0x25, 0xb2, 0x57, 0x2b, 0x3c, 0x39, 0x81, 0xbe, 0x8b, + 0xd9, 0x1d, 0x30, 0xa1, 0x07, 0xf1, 0x51, 0x35, 0xa6, 0x05, 0xa3, 0x8f, + 0x79, 0x84, 0xb6, 0xde, 0x7f, 0x10, 0x30, 0x91, 0x53, 0xe7, 0x17, 0x50 +}; +static const uint8_t nist_186_2_ecdsa_testvector_51_public_y[] = { +/* Qy */ + 0x80, 0xd9, 0x34, 0x5c, 0x25, 0x23, 0xf4, 0x39, 0x72, 0xa8, 0x16, 0x63, + 0xac, 0xfd, 0xa5, 0x4b, 0x8f, 0xf7, 0x43, 0x0b, 0x3a, 0xce, 0xaf, 0x5f, + 0xdd, 0x86, 0x5f, 0x6e, 0x4b, 0x25, 0xa4, 0x87, 0x61, 0x60, 0xb6, 0x2b, + 0xa8, 0xda, 0x98, 0xa6, 0x13, 0xa2, 0x30, 0xe2, 0x9f, 0x87, 0xd0, 0x3f +}; +/* k = 002a565c981e0d48912970345e72db8e0c848b04f8c51de1480d61da4cce03895007683a55a30be940357c08c967cb30 */ +static const uint8_t nist_186_2_ecdsa_testvector_51_out[] = { +/* R */ + 0xb7, 0xf0, 0xc1, 0x59, 0x47, 0xee, 0xab, 0xb3, 0xf8, 0xd7, 0x76, 0x0a, + 0xee, 0x8a, 0x8d, 0xc3, 0x3d, 0x46, 0x42, 0xce, 0x3c, 0x97, 0x54, 0x8f, + 0xe7, 0x6d, 0x01, 0x4a, 0xc9, 0x95, 0xf1, 0xf1, 0xf5, 0x6e, 0x1b, 0xd9, + 0x9e, 0x1d, 0xe1, 0xc0, 0xed, 0xb2, 0xd2, 0xd0, 0xc6, 0xde, 0x47, 0x04, +/* S */ + 0x63, 0xf8, 0xbf, 0xb9, 0x30, 0xdb, 0x61, 0x37, 0xfb, 0x87, 0x61, 0xa8, + 0x40, 0xcf, 0x9e, 0x48, 0xdb, 0x6e, 0x35, 0x5d, 0xb9, 0xab, 0xc7, 0x67, + 0xd3, 0x15, 0xb3, 0x0d, 0x2b, 0x4c, 0x90, 0xcf, 0x9a, 0x71, 0xaa, 0xad, + 0x21, 0xf2, 0x1c, 0x70, 0x5b, 0x60, 0x18, 0x9e, 0xe2, 0xd9, 0x2e, 0x12 +}; +static const uint8_t nist_186_2_ecdsa_testvector_52_ptx[] = { +/* Msg */ + 0x04, 0xd1, 0xab, 0xca, 0x18, 0x1f, 0x64, 0xf7, 0xc6, 0xb1, 0x1f, 0xb7, + 0xf3, 0x26, 0x0a, 0x50, 0x59, 0x9e, 0xdc, 0x70, 0x80, 0xd8, 0x65, 0x70, + 0xea, 0x98, 0x69, 0xd9, 0x8e, 0x4c, 0xae, 0x28, 0x89, 0xee, 0x54, 0xce, + 0x0f, 0x2c, 0x65, 0x7b, 0xa7, 0xc7, 0xad, 0x9c, 0x98, 0x39, 0xcc, 0x23, + 0x9e, 0x9a, 0x89, 0x86, 0xe2, 0xc4, 0x69, 0x0a, 0x29, 0xb6, 0x81, 0x41, + 0x4c, 0x36, 0x88, 0xd1, 0xe8, 0xbb, 0x30, 0x78, 0x56, 0x89, 0xb6, 0x4d, + 0xde, 0x1e, 0xb8, 0x49, 0x27, 0xcd, 0x48, 0x05, 0xf2, 0xa9, 0x3e, 0xc5, + 0x08, 0xa4, 0xd2, 0xb6, 0x71, 0xf8, 0x6a, 0x74, 0xe7, 0xc6, 0xb0, 0xcf, + 0x8b, 0xfd, 0xe8, 0xcf, 0xd6, 0x7e, 0x81, 0xf6, 0xd1, 0x7e, 0xe9, 0xc4, + 0x89, 0x2b, 0xa6, 0x81, 0xbd, 0x92, 0xa3, 0x36, 0xdb, 0xc0, 0xc7, 0xfd, + 0x2b, 0x27, 0xcc, 0x7a, 0x49, 0x44, 0x4f, 0xaa +}; +static const uint8_t nist_186_2_ecdsa_testvector_52_private[] = { +/* d */ + 0x00, 0x1f, 0xde, 0x5b, 0x8c, 0x4a, 0x03, 0xe1, 0x27, 0xc6, 0xe2, 0x4b, + 0x99, 0x8b, 0xd3, 0x5a, 0xab, 0x25, 0x77, 0xaf, 0x84, 0xb0, 0xcd, 0x6a, + 0x06, 0xc7, 0x4f, 0xf6, 0x5d, 0xe1, 0x64, 0x39, 0x33, 0x6a, 0x15, 0xab, + 0x89, 0x6b, 0xc6, 0x62, 0xde, 0x2b, 0x0b, 0x70, 0x86, 0xc6, 0xa6, 0xe8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_52_public_x[] = { +/* Qx */ + 0xbb, 0xa3, 0x46, 0xc6, 0x53, 0x5b, 0x85, 0x32, 0x1e, 0x6c, 0xbd, 0xff, + 0xfd, 0xa6, 0xa8, 0xfe, 0x8e, 0x6e, 0x56, 0x27, 0x83, 0x0d, 0x80, 0xb6, + 0x46, 0x4e, 0x40, 0xbe, 0x1c, 0x44, 0xc7, 0x2f, 0x9f, 0x19, 0x29, 0x07, + 0x34, 0x59, 0x11, 0x68, 0x64, 0xd6, 0xd3, 0xa6, 0x22, 0x0f, 0xcc, 0x76 +}; +static const uint8_t nist_186_2_ecdsa_testvector_52_public_y[] = { +/* Qy */ + 0x91, 0xd6, 0xba, 0x52, 0x3f, 0x75, 0xca, 0x63, 0x0c, 0xda, 0x60, 0x4c, + 0x39, 0xb5, 0x87, 0x33, 0x7f, 0x7a, 0x9c, 0xc0, 0x6f, 0xa8, 0x20, 0x55, + 0x35, 0x02, 0xf9, 0xc3, 0x19, 0xc6, 0xde, 0xc4, 0x8a, 0xbb, 0xea, 0x21, + 0xcb, 0xc8, 0x97, 0x5f, 0xea, 0x58, 0x6a, 0xa3, 0x8c, 0x66, 0x75, 0x7b +}; +/* k = 00b5c6ab008fad701bb612cbaa1d0036f368292e8780addbb3349c9538a42ef8faa022a6545f44ae5be69613bb6879e9 */ +static const uint8_t nist_186_2_ecdsa_testvector_52_out[] = { +/* R */ + 0x9a, 0xf3, 0x75, 0xad, 0x85, 0xd8, 0x43, 0x4b, 0x70, 0x84, 0x84, 0x39, + 0xe0, 0xa7, 0xc8, 0x5f, 0x36, 0x94, 0xb3, 0xec, 0x03, 0xbb, 0x48, 0x58, + 0x68, 0x4c, 0x86, 0x4f, 0xa1, 0xea, 0x83, 0xaf, 0x8d, 0x80, 0xdb, 0x42, + 0xac, 0xe5, 0x43, 0x01, 0xe6, 0xf3, 0x98, 0xaa, 0xbe, 0x51, 0x6c, 0x7b, +/* S */ + 0x6a, 0x93, 0x34, 0x8b, 0xcd, 0xc6, 0xf9, 0x65, 0x84, 0x54, 0x4c, 0x70, + 0x0c, 0x19, 0xd8, 0x0f, 0xeb, 0xf9, 0x62, 0x40, 0x4f, 0xe3, 0x82, 0x6a, + 0xa5, 0x06, 0xfc, 0x7b, 0x17, 0xa8, 0x66, 0x71, 0x65, 0x0d, 0x85, 0xc4, + 0x70, 0x7a, 0xc5, 0x87, 0xd4, 0xd4, 0x3a, 0x66, 0x0e, 0x1d, 0xa2, 0x11 +}; +static const uint8_t nist_186_2_ecdsa_testvector_53_ptx[] = { +/* Msg */ + 0x3a, 0x7e, 0xe7, 0xc2, 0xda, 0xc3, 0xe5, 0x9b, 0x1b, 0xe3, 0x1e, 0x66, + 0x95, 0x26, 0x87, 0xd9, 0x78, 0x0a, 0x75, 0x7f, 0x72, 0x95, 0xa7, 0xae, + 0xd3, 0xe9, 0x87, 0xba, 0xef, 0x19, 0xad, 0x68, 0xc3, 0x3b, 0xa5, 0xa5, + 0xdc, 0xbf, 0xf2, 0x78, 0x75, 0xff, 0x52, 0x36, 0xe0, 0x16, 0x44, 0xf5, + 0x27, 0xf6, 0xc8, 0x42, 0xf2, 0xb5, 0x66, 0x17, 0xab, 0x28, 0x71, 0x07, + 0xe1, 0xb3, 0x8d, 0xbc, 0xea, 0x5f, 0x6f, 0xa3, 0xcd, 0x2d, 0xe4, 0xe6, + 0x5f, 0xab, 0x15, 0x9b, 0xab, 0xc4, 0x09, 0x3b, 0x97, 0xdc, 0x6b, 0x55, + 0xc5, 0x1d, 0x8e, 0x83, 0xb8, 0x0b, 0xae, 0x9e, 0x38, 0x5f, 0x79, 0x2e, + 0xf7, 0x12, 0xcd, 0x24, 0x74, 0xb8, 0xc4, 0xcc, 0x20, 0x0f, 0xee, 0xfd, + 0xc0, 0xd8, 0xdd, 0x93, 0x12, 0xe5, 0xe7, 0x1e, 0xb3, 0x74, 0x27, 0xdc, + 0x40, 0xbb, 0xc5, 0xe5, 0xbb, 0xc4, 0x77, 0xa6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_53_private[] = { +/* d */ + 0x00, 0x02, 0xd3, 0x72, 0xdb, 0xa2, 0x59, 0x85, 0x6c, 0x17, 0x18, 0x44, + 0xa2, 0xf6, 0x18, 0xaa, 0x03, 0xb8, 0xcb, 0xa5, 0xaf, 0x7a, 0xc2, 0x6f, + 0x6c, 0x90, 0x50, 0xe4, 0x86, 0x5d, 0x78, 0x19, 0x74, 0xdb, 0x81, 0x16, + 0xbe, 0xd2, 0x55, 0x8f, 0x1e, 0x04, 0x83, 0x2a, 0x36, 0x0e, 0xe4, 0x4a +}; +static const uint8_t nist_186_2_ecdsa_testvector_53_public_x[] = { +/* Qx */ + 0x7b, 0x23, 0x89, 0x36, 0x7a, 0xeb, 0x04, 0xdb, 0xde, 0x75, 0xd5, 0x8d, + 0xad, 0xac, 0xa0, 0xe9, 0x6d, 0xd2, 0x65, 0x00, 0x23, 0xf6, 0xa6, 0xe4, + 0x31, 0xf2, 0x72, 0x5f, 0x3d, 0x91, 0x9e, 0x3f, 0xb2, 0x37, 0xce, 0x93, + 0x05, 0xb8, 0xfb, 0x6a, 0x28, 0xa5, 0x7c, 0x0f, 0x2f, 0xda, 0x5b, 0xbe +}; +static const uint8_t nist_186_2_ecdsa_testvector_53_public_y[] = { +/* Qy */ + 0x6d, 0x44, 0xf8, 0xd3, 0x79, 0x52, 0x4c, 0x9f, 0x27, 0x82, 0x1c, 0x80, + 0xf9, 0xa5, 0x75, 0xf8, 0x7b, 0x28, 0xd6, 0x3a, 0x6c, 0x69, 0x10, 0x0f, + 0x94, 0x18, 0xa5, 0x08, 0xa9, 0x55, 0x80, 0x55, 0x56, 0x2b, 0x47, 0xb9, + 0x48, 0x47, 0x06, 0x48, 0x2c, 0xaf, 0xc0, 0xf0, 0x36, 0x4a, 0xd0, 0x97 +}; +/* k = 005485a3b918e08070cec54c4d45fd17993b9269d171e68865cf8a8cf8ebca1d65e5dfdb61ae45ce8fad783663d6bcf6 */ +static const uint8_t nist_186_2_ecdsa_testvector_53_out[] = { +/* R */ + 0x8b, 0x7e, 0xd3, 0x27, 0x70, 0x08, 0xf1, 0x9a, 0x57, 0xc1, 0xf4, 0x72, + 0x89, 0xef, 0x1e, 0x9f, 0x3d, 0xf8, 0xe4, 0x40, 0xb8, 0x2e, 0x34, 0xf2, + 0x77, 0x4f, 0x30, 0x58, 0x4c, 0xe6, 0x54, 0xdc, 0xc9, 0xdc, 0xca, 0x9a, + 0xad, 0x7b, 0x47, 0x53, 0xe8, 0x9f, 0xa9, 0xc6, 0x11, 0x54, 0x20, 0x3f, +/* S */ + 0x9a, 0x53, 0xf6, 0xd0, 0x63, 0xf1, 0xb0, 0xab, 0xd1, 0x26, 0x47, 0x0d, + 0xf6, 0x4f, 0xf0, 0x96, 0xcb, 0xcd, 0x2f, 0x50, 0x16, 0x7c, 0xb9, 0x9b, + 0x8c, 0x33, 0x30, 0xdb, 0xf5, 0xa8, 0x16, 0xc2, 0x4a, 0xe1, 0x56, 0x4f, + 0xc7, 0x83, 0xa9, 0x00, 0x36, 0x1e, 0x8c, 0xdb, 0x85, 0x7c, 0x3d, 0xb3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_54_ptx[] = { +/* Msg */ + 0xbb, 0xb6, 0x4f, 0x9a, 0x67, 0x26, 0xe6, 0x5c, 0xca, 0x3c, 0x25, 0x5b, + 0xda, 0x2a, 0x47, 0x75, 0x48, 0xe8, 0x2f, 0x95, 0xa8, 0xce, 0xa9, 0xe1, + 0xd3, 0x62, 0xf3, 0x34, 0x89, 0x6f, 0x7c, 0xce, 0x5b, 0x57, 0xeb, 0x4a, + 0xc8, 0xa9, 0x63, 0xd1, 0xa7, 0xf6, 0x05, 0x8e, 0xc5, 0xe1, 0xb7, 0x61, + 0xce, 0x76, 0x24, 0xd8, 0x71, 0xbd, 0x04, 0x5b, 0xbf, 0x8e, 0x9e, 0xa6, + 0xd4, 0xa6, 0x8b, 0x7d, 0xba, 0xfb, 0xbc, 0x9a, 0x8a, 0x4d, 0xbf, 0xeb, + 0xd4, 0xfe, 0x3d, 0xfa, 0x41, 0x23, 0xc8, 0xad, 0x77, 0xdb, 0xd3, 0x2f, + 0x3d, 0xe0, 0x02, 0x2e, 0xe0, 0x5b, 0xa5, 0x47, 0xd5, 0xfd, 0x7f, 0xbe, + 0x9f, 0x4b, 0xcb, 0x73, 0xf4, 0x39, 0x81, 0x11, 0x1b, 0xfb, 0xd5, 0x89, + 0x98, 0x18, 0x00, 0xbf, 0x0b, 0xc0, 0x44, 0x82, 0x56, 0x5f, 0x2a, 0xc2, + 0xfe, 0x72, 0x0f, 0xfd, 0xd4, 0x9a, 0xde, 0xfb +}; +static const uint8_t nist_186_2_ecdsa_testvector_54_private[] = { +/* d */ + 0x00, 0xe3, 0x97, 0x4c, 0xd7, 0x75, 0x43, 0xda, 0xdd, 0xa2, 0x44, 0x96, + 0xe5, 0x3e, 0x8b, 0x69, 0xe7, 0x4a, 0xb3, 0xdc, 0x92, 0xa8, 0x7f, 0x3d, + 0x5b, 0x19, 0x92, 0xb7, 0x2b, 0x85, 0xe4, 0xe6, 0x46, 0x14, 0x4d, 0xb0, + 0x96, 0xfd, 0x81, 0xd4, 0xdb, 0x80, 0xbc, 0x8b, 0x16, 0xfe, 0x72, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_54_public_x[] = { +/* Qx */ + 0xe8, 0xc3, 0x5b, 0x6d, 0x8a, 0x41, 0xfa, 0xce, 0x0a, 0xa8, 0x2d, 0xee, + 0xac, 0x83, 0xa1, 0xd3, 0x17, 0x82, 0xe0, 0xdd, 0xbb, 0x6a, 0x1a, 0x1f, + 0x26, 0x68, 0x3a, 0xe6, 0x56, 0xb8, 0xbf, 0xcb, 0xca, 0x61, 0x63, 0xaf, + 0x20, 0x48, 0x74, 0x8f, 0xeb, 0x0c, 0xcc, 0xa2, 0xab, 0x39, 0xe1, 0x78 +}; +static const uint8_t nist_186_2_ecdsa_testvector_54_public_y[] = { +/* Qy */ + 0x4b, 0xe3, 0x15, 0xe0, 0x4b, 0xed, 0x3d, 0x59, 0xf9, 0x6a, 0xe4, 0x86, + 0xb8, 0x48, 0x5f, 0x96, 0x62, 0xc6, 0x74, 0x4c, 0x62, 0x38, 0x16, 0x58, + 0x8c, 0xe2, 0xef, 0xa3, 0x71, 0x2c, 0xb7, 0xb6, 0xca, 0x93, 0x66, 0xb5, + 0xbd, 0x43, 0xe7, 0x30, 0x77, 0x12, 0x85, 0x2d, 0xe3, 0xf7, 0xd2, 0x18 +}; +/* k = 00af94eba17be9aa7b85d4124c3df72da3a6dd0c65293f936bd4c1cba834727e97b86de277b4699347002f5361b7df1b */ +static const uint8_t nist_186_2_ecdsa_testvector_54_out[] = { +/* R */ + 0x8a, 0xe1, 0xd5, 0x45, 0x89, 0xd7, 0xe8, 0x5e, 0x84, 0x4d, 0xfb, 0xba, + 0x76, 0xec, 0x04, 0xf6, 0xfd, 0x1c, 0x70, 0xa4, 0x9d, 0xf1, 0x03, 0x9a, + 0xc7, 0x0a, 0x3b, 0x34, 0x97, 0x6c, 0xe0, 0x5f, 0xa5, 0x05, 0xe1, 0x75, + 0xb7, 0x9f, 0x21, 0xb8, 0x2a, 0x50, 0xea, 0x1a, 0x93, 0x8b, 0x8d, 0x79, +/* S */ + 0xf0, 0x86, 0xf2, 0x65, 0xe3, 0xdb, 0xf0, 0x5c, 0x42, 0x0f, 0x39, 0xde, + 0xe8, 0xc5, 0x3c, 0xa2, 0xf3, 0x05, 0x51, 0x9d, 0xcb, 0xb4, 0xfb, 0xa3, + 0x83, 0x71, 0xf0, 0x3a, 0x6c, 0x90, 0xfe, 0xc4, 0xe0, 0x35, 0x75, 0xf3, + 0x3c, 0x48, 0xb2, 0xd2, 0xf5, 0xf5, 0x9c, 0x4e, 0xef, 0xd7, 0xb0, 0x74 +}; +static const uint8_t nist_186_2_ecdsa_testvector_55_ptx[] = { +/* Msg */ + 0x96, 0x8a, 0xda, 0x50, 0xe8, 0xa6, 0x8e, 0x59, 0xa0, 0x48, 0x86, 0x19, + 0xaf, 0x70, 0x52, 0x2b, 0x55, 0x2c, 0x57, 0xb2, 0x36, 0x5d, 0x80, 0x41, + 0xb1, 0xbd, 0x31, 0xf8, 0x6d, 0x21, 0x7d, 0xf0, 0x34, 0xfc, 0x98, 0xda, + 0x05, 0x25, 0x8f, 0xe2, 0x64, 0xda, 0x36, 0xda, 0xf5, 0x04, 0x62, 0x94, + 0x49, 0xbc, 0x59, 0x8f, 0xf8, 0x0f, 0x87, 0xd6, 0xf0, 0xfe, 0x73, 0x26, + 0x0c, 0xc9, 0xf1, 0x4f, 0xe9, 0x6e, 0x98, 0xdc, 0xf5, 0x6c, 0x76, 0xf6, + 0xc8, 0xcc, 0x03, 0x86, 0xb8, 0x62, 0x54, 0x9a, 0xa7, 0x51, 0x91, 0x0a, + 0x20, 0xcd, 0xa9, 0x5b, 0xa3, 0x25, 0x44, 0xe3, 0x3c, 0x00, 0xfa, 0x2e, + 0x5a, 0xe6, 0xc2, 0xa1, 0xdf, 0x03, 0xad, 0x5d, 0x74, 0x28, 0xd4, 0x67, + 0x1f, 0x13, 0x8e, 0x05, 0x17, 0xf0, 0xe7, 0x6b, 0xd7, 0x20, 0x4e, 0x96, + 0x71, 0x38, 0x8e, 0x79, 0x25, 0x4d, 0x00, 0x57 +}; +static const uint8_t nist_186_2_ecdsa_testvector_55_private[] = { +/* d */ + 0x00, 0xe4, 0x45, 0x4a, 0x8e, 0x6e, 0x76, 0xce, 0x5e, 0x2f, 0x16, 0xde, + 0xdf, 0x3d, 0xe9, 0xa2, 0x6e, 0x62, 0x08, 0x50, 0x7e, 0xad, 0x5b, 0xd4, + 0x79, 0x17, 0xba, 0xbd, 0x37, 0x98, 0xb4, 0x16, 0x51, 0xc4, 0xed, 0xde, + 0xd7, 0xbf, 0xd8, 0xa0, 0x92, 0xd2, 0x29, 0x24, 0xbd, 0xb6, 0x1a, 0x92 +}; +static const uint8_t nist_186_2_ecdsa_testvector_55_public_x[] = { +/* Qx */ + 0xbf, 0x81, 0xdf, 0x29, 0xc4, 0xa9, 0x1c, 0x5d, 0xc7, 0x83, 0xc1, 0x46, + 0xba, 0xe6, 0xff, 0x74, 0xf2, 0x04, 0xaa, 0x8f, 0x75, 0x21, 0xc4, 0x86, + 0xef, 0x6d, 0xbb, 0xa3, 0x97, 0x47, 0xab, 0xaf, 0xf3, 0xf4, 0x47, 0xf0, + 0xef, 0xf1, 0x5c, 0x4f, 0x84, 0x80, 0xcf, 0x89, 0x0e, 0xa0, 0x4c, 0x0a +}; +static const uint8_t nist_186_2_ecdsa_testvector_55_public_y[] = { +/* Qy */ + 0x34, 0xbb, 0xbd, 0xf8, 0xc0, 0xeb, 0xf3, 0x5a, 0x3c, 0x06, 0x76, 0xbd, + 0xc1, 0xe7, 0xb8, 0x40, 0x68, 0x79, 0x49, 0x4d, 0xca, 0x62, 0x88, 0xa7, + 0xeb, 0xd9, 0x80, 0xf7, 0x3d, 0xb7, 0xfc, 0x82, 0x86, 0x2e, 0x22, 0x9b, + 0x3a, 0xcf, 0x38, 0x8c, 0xa3, 0xe7, 0x3b, 0x14, 0xa8, 0x8a, 0xb8, 0xdc +}; +/* k = 00d1bb590604cec37be8b994af4cd515f63362a0093930fb65389e20c5875e5968b0c635441d50ef72e96d655ce929d8 */ +static const uint8_t nist_186_2_ecdsa_testvector_55_out[] = { +/* R */ + 0xbe, 0x29, 0xeb, 0x63, 0xb4, 0x01, 0x3d, 0x31, 0x7c, 0xad, 0x04, 0xf7, + 0x91, 0x93, 0xfa, 0xcf, 0xca, 0xf6, 0x1a, 0x9d, 0xb7, 0x0d, 0x36, 0x55, + 0x0e, 0x75, 0xa7, 0x1c, 0x3d, 0x09, 0x2a, 0x94, 0xa5, 0x66, 0xe6, 0x16, + 0x9f, 0x88, 0xba, 0x32, 0x1a, 0x4a, 0x62, 0x71, 0xdc, 0xc9, 0x23, 0x3b, +/* S */ + 0x9d, 0x66, 0x2d, 0xcc, 0xc6, 0x7d, 0x6d, 0xad, 0x4a, 0x2d, 0x86, 0xa5, + 0x22, 0x38, 0x46, 0x2a, 0xa7, 0x5a, 0x85, 0xd8, 0xdb, 0xa6, 0x76, 0xdb, + 0x2b, 0xd9, 0x40, 0x53, 0x12, 0xf5, 0xe2, 0x47, 0x9e, 0x93, 0x4d, 0x41, + 0x35, 0x48, 0xa7, 0x24, 0x6b, 0xd2, 0xdb, 0xc8, 0x54, 0x5a, 0x2f, 0x41 +}; +static const uint8_t nist_186_2_ecdsa_testvector_56_ptx[] = { +/* Msg */ + 0x3d, 0xac, 0xf9, 0xf9, 0x2d, 0x22, 0x02, 0xdb, 0xd9, 0x74, 0x53, 0x58, + 0x51, 0x7b, 0x2c, 0x41, 0x76, 0xaa, 0x05, 0xc1, 0x17, 0xa1, 0xcf, 0x91, + 0x5a, 0x00, 0x7d, 0x6c, 0x5e, 0x79, 0xc3, 0xc3, 0x1e, 0x2a, 0x1d, 0xb1, + 0x99, 0x29, 0x14, 0x31, 0x30, 0x60, 0xbd, 0x8f, 0x4f, 0x9b, 0x82, 0x1c, + 0x4f, 0xdf, 0x24, 0x26, 0x9b, 0xfe, 0x01, 0x27, 0x12, 0x68, 0x93, 0x3d, + 0xad, 0x44, 0x3a, 0xda, 0x62, 0xbf, 0x3b, 0xbd, 0x48, 0xa4, 0x08, 0x21, + 0xfb, 0x2e, 0xc2, 0x34, 0x42, 0x1a, 0xfc, 0xca, 0xef, 0xff, 0xc2, 0x53, + 0x07, 0xe2, 0xd9, 0x0a, 0x23, 0x05, 0x49, 0x70, 0x16, 0x01, 0x19, 0xf9, + 0xd0, 0x14, 0x5a, 0x05, 0x83, 0xbc, 0x67, 0x11, 0x04, 0x85, 0x6a, 0x2f, + 0x73, 0x1f, 0x22, 0xb3, 0x1e, 0xb3, 0xe4, 0x30, 0xa3, 0x77, 0xe0, 0xa3, + 0x55, 0x81, 0xa6, 0xed, 0xe1, 0xd9, 0xe9, 0x87 +}; +static const uint8_t nist_186_2_ecdsa_testvector_56_private[] = { +/* d */ + 0x00, 0x67, 0x54, 0x3b, 0xb6, 0x91, 0x7b, 0xd7, 0xb3, 0xfb, 0x5b, 0x40, + 0xfc, 0x23, 0xb8, 0x66, 0x8d, 0x24, 0xdb, 0x12, 0x54, 0xeb, 0xf1, 0x0a, + 0xa7, 0x71, 0x4b, 0x26, 0x5c, 0x7d, 0x84, 0x9a, 0xfe, 0xc4, 0x58, 0xce, + 0x06, 0xf2, 0x6c, 0x15, 0x00, 0x5b, 0xc8, 0x04, 0x11, 0xe2, 0xb2, 0x34 +}; +static const uint8_t nist_186_2_ecdsa_testvector_56_public_x[] = { +/* Qx */ + 0xaa, 0x1f, 0x66, 0xc6, 0x03, 0x29, 0xa7, 0x90, 0xd9, 0x67, 0xff, 0xe5, + 0x86, 0xa4, 0x4a, 0xd0, 0x5c, 0xaf, 0x9e, 0x61, 0x26, 0x34, 0x23, 0x94, + 0xfd, 0x6c, 0x02, 0x2a, 0x1e, 0xb1, 0x17, 0xf7, 0xed, 0x53, 0x0e, 0xc1, + 0x4e, 0x71, 0x14, 0xca, 0x91, 0x76, 0x7e, 0x96, 0x41, 0x49, 0xcf, 0x5f +}; +static const uint8_t nist_186_2_ecdsa_testvector_56_public_y[] = { +/* Qy */ + 0x33, 0x2b, 0xff, 0x23, 0x4b, 0xfb, 0x5e, 0x87, 0xe6, 0x19, 0x4b, 0x35, + 0xda, 0xe8, 0x21, 0x4b, 0xa4, 0x1f, 0x9b, 0xa1, 0x32, 0x5f, 0x03, 0x4f, + 0xfe, 0xd7, 0x27, 0xb5, 0x73, 0x53, 0xa7, 0x79, 0x49, 0x72, 0xc5, 0x8e, + 0x5b, 0x27, 0xd6, 0xba, 0x72, 0xfd, 0x22, 0x43, 0x47, 0xec, 0x2c, 0x7f +}; +/* k = 00d1f288633a2e827ced39b5b29b925b4242e8cab7cabf51de74e55f3a600cf1d778dd748ec073f8cb3b056e86cabc8c */ +static const uint8_t nist_186_2_ecdsa_testvector_56_out[] = { +/* R */ + 0x17, 0x1d, 0x44, 0xf5, 0xbb, 0xbb, 0x34, 0xb3, 0x5f, 0x3f, 0xb1, 0xaf, + 0xae, 0x4e, 0x10, 0xd6, 0x1b, 0x2f, 0x5d, 0xe5, 0x63, 0xa1, 0x10, 0x9e, + 0x24, 0x8f, 0xa9, 0x3e, 0x02, 0xca, 0x2d, 0xe8, 0xc1, 0x83, 0x18, 0x48, + 0x28, 0x85, 0x57, 0x63, 0x7b, 0x5a, 0x8f, 0xfc, 0x30, 0xb9, 0xed, 0xaa, +/* S */ + 0x4d, 0x65, 0xe1, 0xb9, 0xc8, 0xb7, 0xff, 0x65, 0x3a, 0x5d, 0x36, 0x0f, + 0x86, 0xb5, 0xf9, 0x16, 0x39, 0x02, 0x10, 0x1f, 0x81, 0x8b, 0x09, 0xf7, + 0x09, 0x0c, 0x40, 0x74, 0xb1, 0x19, 0x73, 0xa0, 0x80, 0x14, 0x3e, 0x4e, + 0x57, 0xaf, 0xb6, 0xfb, 0x41, 0x18, 0x60, 0x29, 0xca, 0xf1, 0xc9, 0x63 +}; +static const uint8_t nist_186_2_ecdsa_testvector_57_ptx[] = { +/* Msg */ + 0xac, 0xe2, 0x5c, 0x0d, 0x4f, 0x7d, 0x46, 0x5f, 0x68, 0x43, 0xfb, 0x69, + 0x0c, 0x4c, 0x46, 0x9a, 0x83, 0x0a, 0xdc, 0xa4, 0x42, 0x74, 0xec, 0xc8, + 0x19, 0x64, 0xf7, 0x54, 0xae, 0x3e, 0xe2, 0x6a, 0x2a, 0xd3, 0x4a, 0x02, + 0x32, 0x85, 0x17, 0x32, 0x19, 0xab, 0x54, 0xae, 0x54, 0x37, 0x3e, 0x8b, + 0x2e, 0x96, 0x9a, 0x48, 0xbd, 0xd7, 0x4c, 0x0e, 0x14, 0x10, 0x26, 0x37, + 0xba, 0xfd, 0xfe, 0x0e, 0x5b, 0xeb, 0x03, 0xd5, 0xbe, 0xd4, 0x51, 0x0d, + 0xf7, 0xcc, 0xc2, 0xf1, 0xde, 0x9b, 0x07, 0x44, 0xbf, 0xac, 0xf8, 0x4c, + 0x53, 0x26, 0x29, 0x1f, 0xef, 0x58, 0xbe, 0x1d, 0xfc, 0x5a, 0x80, 0xbe, + 0xa7, 0xf1, 0x30, 0x8e, 0xd9, 0xb4, 0x1b, 0x75, 0x6a, 0x6d, 0xee, 0x3c, + 0x92, 0xc2, 0xcc, 0x4d, 0xa0, 0x15, 0x9e, 0xba, 0xee, 0xa8, 0xaa, 0x81, + 0x14, 0x05, 0x68, 0x0f, 0x5c, 0x9d, 0x90, 0x02 +}; +static const uint8_t nist_186_2_ecdsa_testvector_57_private[] = { +/* d */ + 0x00, 0x58, 0xfe, 0x57, 0x51, 0x16, 0xc0, 0x54, 0x9b, 0x78, 0x53, 0xf3, + 0x36, 0x69, 0x4d, 0xef, 0xda, 0x21, 0xea, 0x42, 0x3b, 0x13, 0x1e, 0x32, + 0x28, 0xae, 0x21, 0x3e, 0x05, 0x0d, 0x3e, 0xeb, 0x4c, 0x5e, 0xac, 0x9f, + 0x24, 0x96, 0x82, 0x1d, 0x87, 0x18, 0xcd, 0x86, 0xef, 0x94, 0x3e, 0xc4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_57_public_x[] = { +/* Qx */ + 0xfa, 0xa6, 0xc0, 0x91, 0x4b, 0x18, 0x9d, 0x9d, 0xf2, 0xf7, 0xef, 0xe2, + 0x27, 0xf6, 0xb9, 0x5c, 0x31, 0x02, 0x51, 0xc1, 0xa8, 0xd7, 0xb2, 0x61, + 0xa0, 0xbd, 0xb0, 0xce, 0xfa, 0x4f, 0x66, 0x1b, 0xfd, 0xb4, 0xbb, 0x5b, + 0xf5, 0x9d, 0x5f, 0x42, 0x0d, 0x57, 0xf7, 0xf2, 0xc8, 0xb3, 0x2e, 0x73 +}; +static const uint8_t nist_186_2_ecdsa_testvector_57_public_y[] = { +/* Qy */ + 0x96, 0xf8, 0x23, 0x15, 0xc2, 0x5f, 0x68, 0xf2, 0xbf, 0x7e, 0x5c, 0x8e, + 0x74, 0x9f, 0xbc, 0x8c, 0x4d, 0xd8, 0x5f, 0xe1, 0x9a, 0x76, 0xde, 0x7a, + 0xe3, 0x5a, 0xbf, 0x80, 0x61, 0x41, 0xb9, 0x5e, 0x02, 0xe5, 0x8d, 0xef, + 0xab, 0x62, 0xab, 0x0c, 0x3d, 0x47, 0x97, 0x23, 0x48, 0x1f, 0x2e, 0x02 +}; +/* k = 004c3a262bc2374600194d52d1e329f32b6dfa30b04f18c6f7bd3e2da69785847fd01142355306a2d94c14fdea1e2a33 */ +static const uint8_t nist_186_2_ecdsa_testvector_57_out[] = { +/* R */ + 0xe9, 0x60, 0xde, 0x23, 0xe2, 0x9b, 0x6f, 0x9d, 0x70, 0x81, 0x39, 0xbe, + 0x50, 0xfa, 0xf1, 0xf2, 0x38, 0xae, 0x27, 0x1e, 0x87, 0xa0, 0xad, 0x02, + 0x13, 0x51, 0x17, 0xde, 0x08, 0xe6, 0xcb, 0x61, 0x9f, 0x77, 0x01, 0x6d, + 0x77, 0x3c, 0xe5, 0x5b, 0x68, 0xb8, 0xbc, 0x4e, 0x63, 0x42, 0xbb, 0x98, +/* S */ + 0xf3, 0x53, 0xcb, 0x04, 0x5a, 0xb7, 0x2f, 0x01, 0x0b, 0x1b, 0xec, 0x34, + 0x42, 0x82, 0xfc, 0xe0, 0xf0, 0x05, 0xe0, 0xa8, 0x3d, 0xaf, 0x9f, 0xa9, + 0x3d, 0x9a, 0xf3, 0x81, 0x18, 0xea, 0x33, 0x4c, 0x37, 0xf4, 0xdb, 0xc5, + 0x74, 0xe8, 0x13, 0xda, 0x1b, 0x03, 0x9e, 0xea, 0xb8, 0x81, 0x11, 0x7b +}; +static const uint8_t nist_186_2_ecdsa_testvector_58_ptx[] = { +/* Msg */ + 0x72, 0xe1, 0x91, 0x7b, 0xf8, 0x3e, 0xe9, 0x68, 0x9b, 0x5f, 0xa8, 0xfe, + 0x9e, 0x4a, 0x50, 0x0a, 0xac, 0xcb, 0x0d, 0x58, 0x6e, 0xb8, 0xe9, 0x1c, + 0x5d, 0x78, 0x3f, 0x92, 0xd5, 0xc6, 0x72, 0xe2, 0x6b, 0xb3, 0xde, 0x46, + 0x81, 0xea, 0x0f, 0x6e, 0x18, 0x38, 0x31, 0x24, 0xe5, 0x4c, 0xc8, 0x2c, + 0xa6, 0xbb, 0xa2, 0x6e, 0xb6, 0x47, 0x09, 0x57, 0xdf, 0x60, 0x3d, 0x7c, + 0x70, 0xeb, 0x21, 0x80, 0x90, 0x43, 0x34, 0x38, 0xd2, 0x7d, 0xc3, 0x0e, + 0x0a, 0xf1, 0x5d, 0xa3, 0x5e, 0xf5, 0x88, 0xb9, 0xa0, 0xec, 0xb2, 0x4f, + 0xdb, 0x80, 0x6a, 0x0d, 0x2b, 0x2b, 0xd0, 0xe3, 0xd2, 0xfc, 0x4a, 0xee, + 0x89, 0x98, 0x79, 0x9b, 0x14, 0x7f, 0x6c, 0x0e, 0x19, 0x90, 0x13, 0xc5, + 0x32, 0xd0, 0xf6, 0x78, 0x41, 0x67, 0x26, 0x44, 0x04, 0xeb, 0x74, 0x09, + 0xe9, 0xe1, 0xe2, 0x11, 0x23, 0x81, 0x57, 0xf2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_58_private[] = { +/* d */ + 0x00, 0xa9, 0x86, 0xfa, 0x91, 0xca, 0xc9, 0x51, 0x41, 0x0a, 0x7b, 0xec, + 0xc9, 0x25, 0x30, 0xa3, 0xf2, 0x24, 0x30, 0xb4, 0xfd, 0xfa, 0xb2, 0x91, + 0x68, 0x93, 0xc6, 0x44, 0x18, 0x9a, 0x6a, 0x56, 0x35, 0x41, 0x73, 0x04, + 0xaa, 0xc6, 0x02, 0x69, 0x36, 0xef, 0x21, 0x1f, 0x38, 0x37, 0x03, 0xbd +}; +static const uint8_t nist_186_2_ecdsa_testvector_58_public_x[] = { +/* Qx */ + 0x37, 0x8c, 0xe7, 0x3b, 0x4a, 0x19, 0x5e, 0xc7, 0x57, 0x54, 0xb2, 0xf5, + 0x75, 0x28, 0x36, 0x4a, 0x1f, 0x5d, 0x2c, 0x71, 0x9a, 0xab, 0xd1, 0x29, + 0x68, 0x20, 0xa3, 0x53, 0x86, 0xb0, 0x55, 0x64, 0xb3, 0x27, 0x22, 0xaf, + 0xa6, 0xcb, 0x22, 0x2b, 0x02, 0xf7, 0x51, 0xfc, 0x45, 0x04, 0xb2, 0x4f +}; +static const uint8_t nist_186_2_ecdsa_testvector_58_public_y[] = { +/* Qy */ + 0x10, 0xcb, 0xec, 0x24, 0xb5, 0x0e, 0xc9, 0x0f, 0x64, 0xf0, 0x83, 0x20, + 0xea, 0x96, 0xd1, 0x58, 0x10, 0x1f, 0x29, 0x79, 0x9c, 0xc6, 0x69, 0xd0, + 0xcd, 0x6a, 0x7a, 0x4d, 0x38, 0x0e, 0x51, 0xec, 0x98, 0xdc, 0xbf, 0x41, + 0xea, 0xd7, 0x2a, 0xbd, 0xf2, 0xc7, 0x51, 0x31, 0x95, 0x7e, 0xa0, 0x89 +}; +/* k = 00444b31ec4e95af9529be93fe41ed60ced6441b5313d635adac9116142fe7e8e19f28a869486656cd99b8013b6a9642 */ +static const uint8_t nist_186_2_ecdsa_testvector_58_out[] = { +/* R */ + 0x19, 0x1b, 0xd6, 0xd5, 0xcd, 0x8b, 0xca, 0x92, 0xa2, 0x87, 0x44, 0xf7, + 0x6d, 0x29, 0x6a, 0x9a, 0x92, 0x06, 0xad, 0x67, 0x55, 0xe7, 0x5e, 0x90, + 0x2a, 0xac, 0x01, 0x80, 0x40, 0xf6, 0xa6, 0xd3, 0xe3, 0x87, 0x86, 0x37, + 0x41, 0x67, 0x01, 0xb2, 0xef, 0x5b, 0x22, 0x94, 0x3e, 0xe4, 0x7d, 0x92, +/* S */ + 0xdf, 0x07, 0xb2, 0x56, 0x3a, 0x1b, 0xd7, 0x00, 0x7e, 0x62, 0xc8, 0x2d, + 0x6a, 0xd1, 0xeb, 0x10, 0xd0, 0xf6, 0xd9, 0x76, 0x6e, 0x01, 0x43, 0x87, + 0x84, 0x8e, 0x94, 0xe5, 0x92, 0x2f, 0xa5, 0x82, 0xc9, 0x32, 0x91, 0x7a, + 0xcf, 0x30, 0xfd, 0x83, 0xa9, 0xd7, 0xe2, 0xfc, 0xd9, 0xc8, 0x08, 0x9c +}; +static const uint8_t nist_186_2_ecdsa_testvector_59_ptx[] = { +/* Msg */ + 0x6c, 0xf7, 0x75, 0xc9, 0xd5, 0x4b, 0x0a, 0x99, 0xf1, 0x8b, 0xca, 0x17, + 0x7f, 0x0b, 0x0d, 0x49, 0x3a, 0x2a, 0x01, 0xb7, 0x5a, 0xcd, 0x4b, 0x7c, + 0x5d, 0x0d, 0xf1, 0x9c, 0x07, 0x2d, 0x77, 0x98, 0xa8, 0xcf, 0x48, 0x40, + 0x9d, 0x67, 0x58, 0xc9, 0x19, 0xef, 0x08, 0x1f, 0x26, 0xdd, 0x4a, 0x7c, + 0xe6, 0x52, 0x05, 0x3a, 0x1f, 0x94, 0xbb, 0xe6, 0xf6, 0xbe, 0x69, 0x95, + 0xfb, 0xb6, 0xae, 0x7b, 0x66, 0x60, 0x30, 0xb9, 0xa0, 0x11, 0x3c, 0x77, + 0x06, 0x47, 0xac, 0x33, 0xe9, 0x97, 0x0e, 0x58, 0xd9, 0xe6, 0x02, 0x13, + 0x23, 0xdc, 0xe4, 0x62, 0x98, 0x96, 0xab, 0x6e, 0x90, 0x9b, 0x11, 0x1a, + 0x2f, 0x12, 0xf5, 0xdc, 0xe7, 0x32, 0xfd, 0xcc, 0x3e, 0xf9, 0x7f, 0xfa, + 0xd2, 0x21, 0xa2, 0x05, 0x9a, 0x50, 0xc0, 0xe9, 0x6e, 0x8f, 0x0f, 0x19, + 0xca, 0xfd, 0x81, 0xce, 0xcf, 0xc4, 0xe8, 0x9e +}; +static const uint8_t nist_186_2_ecdsa_testvector_59_private[] = { +/* d */ + 0x00, 0x33, 0xac, 0xf6, 0xc1, 0x1e, 0x48, 0xd2, 0x01, 0x0c, 0x5a, 0x82, + 0xc5, 0x7b, 0xb6, 0xdc, 0xfe, 0x43, 0x6b, 0x07, 0xc0, 0x0b, 0x67, 0xb6, + 0x1e, 0xec, 0x4e, 0xb5, 0xc4, 0xc8, 0x3c, 0xcd, 0x16, 0x56, 0x22, 0x91, + 0xc0, 0x4d, 0x3b, 0x5e, 0x0d, 0x22, 0xcf, 0xf6, 0x1c, 0x15, 0x09, 0xb1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_59_public_x[] = { +/* Qx */ + 0x5c, 0xa5, 0xbe, 0xa1, 0x70, 0xdd, 0x19, 0xcc, 0x88, 0xd7, 0x11, 0x3f, + 0xd6, 0x28, 0xc0, 0x84, 0xad, 0x42, 0xf3, 0xc5, 0xd1, 0xe8, 0x29, 0x40, + 0x8c, 0x12, 0x6e, 0xc5, 0xaa, 0xc0, 0x6c, 0x34, 0xc6, 0x89, 0x3f, 0x9d, + 0x44, 0x53, 0x9f, 0xd1, 0x60, 0x1b, 0x49, 0x3d, 0x52, 0x61, 0x87, 0xe9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_59_public_y[] = { +/* Qy */ + 0xa4, 0x98, 0xb6, 0xec, 0xed, 0x71, 0x9c, 0x9a, 0xc2, 0xf8, 0xc7, 0x3e, + 0x97, 0x94, 0xb4, 0x8f, 0x59, 0x47, 0x0f, 0x16, 0xfc, 0x22, 0x47, 0x2e, + 0x4c, 0x7d, 0xe0, 0x76, 0xa7, 0x36, 0xad, 0x2e, 0x43, 0x99, 0xe9, 0xe9, + 0xe1, 0xb7, 0x26, 0x00, 0x22, 0x50, 0xbe, 0xe6, 0xdc, 0xa7, 0xfd, 0xa9 +}; +/* k = 0090c4418f19d7bd59736d4ddfade964e38cd3d159434a73c8e2d1e8c3fde153a742fa3f7b6c74d15601e0601987eaa9 */ +static const uint8_t nist_186_2_ecdsa_testvector_59_out[] = { +/* R */ + 0xff, 0xfc, 0x02, 0x1b, 0x5e, 0x5a, 0x7b, 0x67, 0x5d, 0x3d, 0x34, 0x5e, + 0xca, 0x74, 0xc9, 0x7e, 0x31, 0x51, 0x6d, 0xe0, 0x21, 0x5d, 0xde, 0x3a, + 0x79, 0x9e, 0x7a, 0x2f, 0x83, 0x04, 0xaf, 0xd8, 0x1c, 0xa2, 0x95, 0xa7, + 0xf1, 0xe9, 0x6c, 0xd2, 0xa5, 0x21, 0x87, 0x65, 0xe2, 0xb2, 0xfc, 0x5f, +/* S */ + 0x60, 0x12, 0x80, 0xd4, 0xd4, 0xc2, 0x50, 0x19, 0x9e, 0x11, 0x42, 0xb3, + 0x4b, 0x80, 0x6d, 0x16, 0x51, 0x61, 0x99, 0xf1, 0x43, 0xf0, 0x7a, 0xdf, + 0xb4, 0xb9, 0x6a, 0xc6, 0x44, 0xbe, 0xf3, 0xb2, 0x51, 0x36, 0x09, 0x25, + 0xb8, 0xdb, 0xbe, 0x4b, 0xe2, 0x08, 0x20, 0x1a, 0x7e, 0xe4, 0x1b, 0x48 +}; +static const uint8_t nist_186_2_ecdsa_testvector_60_ptx[] = { +/* Msg */ + 0xc9, 0xf1, 0xbc, 0x04, 0xe1, 0x1c, 0x29, 0x36, 0x26, 0xfe, 0xae, 0x66, + 0x96, 0xf0, 0x50, 0x59, 0x71, 0x84, 0x66, 0xd9, 0xea, 0x6c, 0xf1, 0xb5, + 0x23, 0x98, 0x2b, 0x0a, 0x58, 0x9f, 0x63, 0xc1, 0x5b, 0x60, 0x07, 0x59, + 0x40, 0xe9, 0x03, 0xe6, 0x59, 0x98, 0x49, 0x5a, 0x65, 0x7f, 0xb1, 0x04, + 0x04, 0x0d, 0x04, 0x56, 0x6e, 0xeb, 0x53, 0xeb, 0x65, 0x25, 0x8e, 0xc9, + 0x68, 0x8a, 0x52, 0xe3, 0x2a, 0x55, 0x01, 0xe2, 0x42, 0x0d, 0x18, 0x24, + 0x24, 0xa9, 0xbd, 0x05, 0x50, 0xf8, 0x98, 0x5e, 0xc9, 0x40, 0xe4, 0x4c, + 0xc9, 0x26, 0xc6, 0x33, 0xb3, 0xcd, 0xdd, 0x02, 0x49, 0x42, 0x1a, 0xb8, + 0x1f, 0x18, 0xd2, 0x27, 0x4f, 0x4f, 0x11, 0xf7, 0x6f, 0x7b, 0x32, 0xef, + 0xc0, 0x21, 0xac, 0x70, 0xa8, 0x65, 0x2f, 0x42, 0x63, 0xe2, 0xf0, 0x94, + 0xf5, 0xda, 0x41, 0x3d, 0x63, 0x8f, 0x64, 0x48 +}; +static const uint8_t nist_186_2_ecdsa_testvector_60_private[] = { +/* d */ + 0x00, 0x4b, 0xf7, 0xfd, 0x8d, 0x0e, 0xde, 0x8f, 0xf1, 0xf5, 0x68, 0xed, + 0x3a, 0xb9, 0xce, 0xd8, 0x2c, 0x4e, 0xfe, 0xe7, 0xb2, 0xb6, 0x49, 0x32, + 0x39, 0x2e, 0x6c, 0x70, 0xf1, 0xf3, 0x89, 0x7c, 0x3a, 0xf5, 0x43, 0x53, + 0xb5, 0xf4, 0x1d, 0x19, 0x9e, 0x44, 0x33, 0x9f, 0x73, 0xac, 0x6d, 0xaa +}; +static const uint8_t nist_186_2_ecdsa_testvector_60_public_x[] = { +/* Qx */ + 0x50, 0x67, 0x5a, 0x40, 0x95, 0x31, 0x71, 0xe5, 0xf3, 0x56, 0x51, 0xad, + 0x8d, 0xd7, 0xb7, 0x44, 0x72, 0x32, 0x13, 0x26, 0x99, 0x2e, 0xbc, 0xae, + 0xb2, 0x47, 0xe0, 0x2b, 0x7d, 0x40, 0x29, 0xf2, 0x93, 0x6b, 0x13, 0x00, + 0x96, 0xfc, 0x3d, 0xae, 0x36, 0xc4, 0xc0, 0x73, 0x6d, 0x2b, 0xaf, 0xc8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_60_public_y[] = { +/* Qy */ + 0x3e, 0x28, 0x73, 0x8b, 0x00, 0xb2, 0xcb, 0x5b, 0x6c, 0x69, 0xe4, 0x94, + 0x94, 0xf3, 0x10, 0xe6, 0x69, 0x33, 0xfe, 0x9b, 0xa0, 0x6f, 0xaa, 0x85, + 0x02, 0x87, 0xa0, 0x05, 0x8c, 0xd6, 0x09, 0x35, 0xce, 0x08, 0xda, 0x14, + 0x3c, 0x5d, 0x04, 0x04, 0x4a, 0xea, 0x40, 0x1a, 0xbf, 0x63, 0xd4, 0xfb +}; +/* k = 001bac143611a010a5713f1db6bcc93c18ddb809e07f1c96e7f296b878c2a747f7b5b47b5f4dcec1d65c28abc8918bef */ +static const uint8_t nist_186_2_ecdsa_testvector_60_out[] = { +/* R */ + 0x99, 0x04, 0xcb, 0x5c, 0xb4, 0x92, 0x7b, 0x9c, 0xd6, 0x1b, 0xe9, 0x0a, + 0x49, 0x8d, 0xd5, 0xf3, 0xa5, 0xb1, 0x66, 0x10, 0x32, 0xa1, 0x3e, 0xa2, + 0x0d, 0x0c, 0x9c, 0x9a, 0xb5, 0x7a, 0xe6, 0xf5, 0x0d, 0x62, 0xa1, 0xee, + 0x14, 0x46, 0xa3, 0xd6, 0xe3, 0x5a, 0x46, 0xa9, 0x65, 0x34, 0x52, 0x0a, +/* S */ + 0xaa, 0x1f, 0xd2, 0x69, 0xfb, 0xad, 0xa3, 0xbd, 0xe4, 0x20, 0x10, 0x0e, + 0x54, 0xa4, 0x8e, 0xc4, 0x77, 0xb2, 0xe9, 0x63, 0xe9, 0x6e, 0x43, 0x7f, + 0xc3, 0x1c, 0x52, 0xad, 0xe5, 0xab, 0x32, 0x0a, 0x70, 0x7f, 0x9f, 0xd6, + 0xd6, 0x29, 0x41, 0x0c, 0x45, 0x18, 0x06, 0xdf, 0x7f, 0xcc, 0x2e, 0x46 +}; +/* [P-521] */ +static const uint8_t nist_186_2_ecdsa_testvector_61_ptx[] = { +/* Msg */ + 0xcc, 0x92, 0xca, 0x36, 0xa7, 0x67, 0x60, 0x75, 0x2b, 0x5a, 0x45, 0xca, + 0x5d, 0x72, 0x35, 0x94, 0x71, 0x22, 0xa6, 0x00, 0x2f, 0x1d, 0x4e, 0x7d, + 0x9c, 0x6b, 0xe5, 0x70, 0xd7, 0xbd, 0x2c, 0x29, 0x41, 0xfe, 0x2e, 0x16, + 0xe0, 0x2a, 0xc6, 0x37, 0x06, 0x63, 0x61, 0xd2, 0x2d, 0x42, 0x05, 0x68, + 0x26, 0x6b, 0x93, 0xe7, 0x73, 0x64, 0x49, 0x21, 0xf1, 0xa7, 0x8a, 0x7d, + 0xba, 0xf5, 0xe2, 0xed, 0x49, 0xee, 0x45, 0x20, 0xdf, 0xdf, 0x97, 0xf8, + 0x26, 0xdb, 0x72, 0x3e, 0x14, 0x0d, 0x23, 0x95, 0x13, 0x4c, 0xf5, 0xac, + 0x5f, 0xf0, 0xb3, 0xb8, 0xaf, 0xe4, 0x68, 0x22, 0x17, 0xfd, 0x69, 0x7c, + 0x2d, 0x8a, 0x95, 0xba, 0x6b, 0x2d, 0xdc, 0x9f, 0xd4, 0xe9, 0xfe, 0x75, + 0xda, 0x7b, 0x95, 0x01, 0x80, 0xee, 0x56, 0xb6, 0xbc, 0x6a, 0x94, 0x29, + 0x1f, 0x4d, 0x05, 0xc5, 0xb7, 0x7c, 0xc9, 0xc0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_61_private[] = { +/* d - byte alignment */ + 0x00, 0x3d, 0x72, 0xbc, 0xc7, 0x00, 0x69, 0x5d, 0x40, 0x0c, 0x81, 0x3d, + 0xfd, 0xa1, 0xe3, 0xb3, 0xbf, 0x2c, 0xbc, 0x15, 0xf2, 0x8d, 0x27, 0x2d, + 0xcb, 0x3b, 0xd7, 0xf9, 0x35, 0xfd, 0xab, 0xac, 0x9c, 0x27, 0x7d, 0xc4, + 0x7a, 0x32, 0x45, 0x73, 0x7b, 0x40, 0xde, 0xd8, 0xd0, 0xd2, 0x46, 0x4c, + 0xaa, 0x6a, 0xfa, 0x8b, 0x97, 0x16, 0x93, 0xcb, 0x25, 0x8a, 0x8f, 0x58, + 0xe6, 0x3f, 0xab, 0x2c, 0x48, 0x56 +}; +static const uint8_t nist_186_2_ecdsa_testvector_61_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xf1, 0xdc, 0x7c, 0xcb, 0x09, 0xd6, 0x1e, 0x6a, 0xf3, 0x79, 0xb8, + 0x9a, 0xca, 0x90, 0x5b, 0x49, 0x77, 0x9f, 0xbe, 0x43, 0xa9, 0x4c, 0x8e, + 0xf3, 0x84, 0xcc, 0xbf, 0x66, 0x0f, 0x48, 0x05, 0xc9, 0x65, 0xa3, 0xa2, + 0x4e, 0xd5, 0xa9, 0x62, 0xc2, 0x48, 0x09, 0x41, 0x5c, 0xde, 0xcf, 0xdf, + 0xe5, 0x0f, 0xd1, 0x8f, 0x12, 0x66, 0x07, 0x31, 0x54, 0xb6, 0x2f, 0x35, + 0x5f, 0xe4, 0xc9, 0x8a, 0xf6, 0xe5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_61_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x74, 0x0e, 0xb9, 0x5b, 0x8e, 0x31, 0xa0, 0x43, 0x4c, 0x98, 0x8f, + 0x2e, 0xdd, 0x55, 0x0b, 0x8d, 0xc6, 0xc4, 0x5c, 0x6f, 0x50, 0x43, 0x09, + 0x25, 0x53, 0x70, 0xcc, 0xe5, 0x7e, 0x82, 0x1f, 0xcb, 0x4f, 0x60, 0xba, + 0xd1, 0x7a, 0x8f, 0xb9, 0xa3, 0xf4, 0xdc, 0x67, 0xed, 0x48, 0x60, 0xae, + 0x6d, 0xd3, 0xed, 0x4b, 0x1f, 0x51, 0xb9, 0x84, 0x51, 0xb7, 0xe7, 0x09, + 0x5c, 0xc8, 0x7d, 0x4d, 0x62, 0x79 +}; +/* k = 1fc81abec3fab91a439df81eb49a7179230866c2e0e505d696ca37972e4af043f6ce6edea69c5711d14c43905b3dcc9ed48d225d50d8b136b6f0787215b3500be53 */ +static const uint8_t nist_186_2_ecdsa_testvector_61_out[] = { +/* R - byte alignment */ + 0x00, 0xd3, 0x14, 0xdd, 0xe7, 0x4c, 0xce, 0x60, 0x24, 0x51, 0x89, 0x80, + 0xad, 0x85, 0xcc, 0x7d, 0x5a, 0x29, 0x4e, 0x14, 0x8f, 0xa2, 0x6f, 0x06, + 0x48, 0x48, 0x6a, 0x6d, 0x28, 0x82, 0xca, 0x7a, 0x92, 0xa1, 0xc9, 0x34, + 0xc4, 0xb0, 0x1e, 0xe1, 0xf6, 0xcc, 0x1d, 0xcc, 0x59, 0x20, 0xd4, 0x97, + 0x19, 0xa1, 0x82, 0x3c, 0xfa, 0x32, 0xa6, 0x9c, 0xda, 0x71, 0x0b, 0x0e, + 0x95, 0x62, 0x3b, 0xbb, 0x04, 0x51, +/* S - byte alignment */ + 0x01, 0x4b, 0x0b, 0x93, 0xbd, 0xa1, 0x37, 0xa5, 0x29, 0x39, 0x00, 0xeb, + 0x6c, 0xb6, 0xb1, 0x51, 0xe3, 0x30, 0x1b, 0x8e, 0x29, 0x44, 0xea, 0xee, + 0x5c, 0xe0, 0xf8, 0xdf, 0x87, 0xc9, 0x84, 0x1b, 0x61, 0x37, 0x2a, 0x2d, + 0x70, 0xe7, 0x75, 0xc6, 0x75, 0x8d, 0x29, 0xa7, 0xd2, 0x4f, 0x62, 0xc6, + 0x9d, 0xc8, 0x84, 0xb5, 0x4c, 0xe6, 0x7a, 0x8e, 0xdb, 0x51, 0xa0, 0x72, + 0xe4, 0x79, 0x7a, 0x9b, 0x03, 0x6d +}; +static const uint8_t nist_186_2_ecdsa_testvector_62_ptx[] = { +/* Msg */ + 0x7a, 0x32, 0xe2, 0x33, 0x4f, 0x40, 0x4d, 0x73, 0x4d, 0x4c, 0x54, 0x22, + 0x3c, 0xd0, 0x16, 0x2d, 0x63, 0xc7, 0x38, 0xfb, 0x9c, 0x6b, 0x93, 0x50, + 0xae, 0x43, 0x29, 0x72, 0xd6, 0x5d, 0x5e, 0x8b, 0xa7, 0xd9, 0x65, 0x4f, + 0x15, 0xa7, 0xf8, 0xde, 0xcc, 0x90, 0x4c, 0xec, 0xc6, 0x7b, 0x44, 0x1f, + 0x1c, 0xe9, 0xe5, 0xb8, 0x1c, 0xc3, 0x0a, 0x76, 0x9d, 0x55, 0x58, 0xb7, + 0x8f, 0x9a, 0x75, 0xe1, 0xd6, 0xba, 0x75, 0x00, 0x59, 0xd1, 0x95, 0xb1, + 0x55, 0xf2, 0x2c, 0x3e, 0xf8, 0x6c, 0xde, 0x0a, 0x2b, 0x4b, 0x13, 0x30, + 0xaf, 0x22, 0xa7, 0x67, 0x6b, 0x08, 0xe4, 0x29, 0x04, 0xe1, 0xad, 0x14, + 0xaf, 0xdf, 0xfb, 0x90, 0x43, 0x48, 0x8e, 0xb2, 0x93, 0x79, 0xdc, 0x60, + 0xfa, 0x2b, 0x4e, 0xb6, 0x37, 0xf5, 0xab, 0xa9, 0x7b, 0x12, 0xd4, 0xea, + 0xc1, 0x65, 0xb3, 0x0d, 0x5e, 0xba, 0x6e, 0xeb +}; +static const uint8_t nist_186_2_ecdsa_testvector_62_private[] = { +/* d - byte alignment */ + 0x01, 0x80, 0x52, 0x67, 0x3f, 0xd9, 0x1a, 0x37, 0x44, 0x8f, 0x1f, 0x33, + 0xad, 0x88, 0x52, 0x6e, 0xf7, 0x38, 0xf2, 0x2e, 0x64, 0x76, 0x25, 0x6d, + 0xab, 0x6c, 0x74, 0x48, 0x37, 0x1e, 0x60, 0x85, 0x0d, 0xa9, 0xd7, 0x38, + 0xab, 0x9f, 0x3e, 0x40, 0x20, 0x61, 0xee, 0x95, 0xab, 0xb7, 0x04, 0x36, + 0xd2, 0x82, 0xd3, 0xe8, 0xe6, 0x35, 0x95, 0xd4, 0xdd, 0xfa, 0xcf, 0x94, + 0xd5, 0x3b, 0x3a, 0xf5, 0xd3, 0x48 +}; +static const uint8_t nist_186_2_ecdsa_testvector_62_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x62, 0xa0, 0x05, 0xd8, 0x0e, 0xc3, 0xee, 0x67, 0xc1, 0xc1, 0x84, + 0xeb, 0x2e, 0xfe, 0x8d, 0x10, 0x63, 0xe8, 0x1e, 0xb2, 0xf9, 0x19, 0x35, + 0x7b, 0xb4, 0x42, 0x05, 0x2d, 0x97, 0x7d, 0x14, 0x3d, 0xd7, 0xca, 0x9b, + 0xe4, 0x3f, 0x62, 0x40, 0x28, 0xb7, 0xf8, 0xc8, 0x24, 0x22, 0xe5, 0xfd, + 0xf6, 0x3d, 0x19, 0xf2, 0xce, 0xa7, 0xe2, 0xa4, 0xf6, 0x67, 0x8a, 0x57, + 0x16, 0x5a, 0x1c, 0x45, 0xaa, 0x34 +}; +static const uint8_t nist_186_2_ecdsa_testvector_62_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x72, 0x4c, 0xb8, 0x34, 0xd5, 0x38, 0x3a, 0x18, 0x9c, 0xcf, 0x7f, + 0x37, 0x2f, 0x16, 0x69, 0x4a, 0xf1, 0xdb, 0xaf, 0xad, 0xb3, 0xf5, 0x69, + 0xd3, 0x4d, 0x2e, 0xd5, 0x4d, 0x70, 0xaa, 0xb1, 0x06, 0xbb, 0xbf, 0x04, + 0x1f, 0x53, 0x9d, 0xae, 0x97, 0xc6, 0xef, 0xa3, 0x5d, 0x41, 0xb3, 0x90, + 0xb1, 0xad, 0x75, 0x1e, 0xed, 0x2c, 0x0d, 0x83, 0x87, 0x84, 0x11, 0x1b, + 0xb5, 0x62, 0xde, 0x9b, 0xeb, 0x72 +}; +/* k = 160bcb5a661ffb58dda4110a003e83623e5eecf39de285fd8c79674a40cd89959a04936aa0288ef7e8d6621f882b5c8ab3eca58bb3ba48919087313def041433339 */ +static const uint8_t nist_186_2_ecdsa_testvector_62_out[] = { +/* R - byte alignment */ + 0x00, 0x21, 0xbc, 0xa7, 0x96, 0xda, 0xfa, 0x1c, 0xb5, 0xbf, 0xbd, 0xc3, + 0xfd, 0x70, 0x78, 0x7e, 0xd6, 0x40, 0x5d, 0x41, 0x8a, 0x12, 0xe2, 0x24, + 0xb3, 0x4d, 0x95, 0x16, 0xb8, 0x9e, 0x29, 0xa4, 0x86, 0x60, 0x7b, 0xb7, + 0xd5, 0x1f, 0x68, 0x23, 0xb5, 0x85, 0x57, 0x9f, 0x33, 0xa8, 0x6f, 0x6a, + 0x6b, 0x31, 0x19, 0x7e, 0x7d, 0xd1, 0x67, 0x44, 0xe9, 0x07, 0x16, 0xa7, + 0xdc, 0x94, 0x7a, 0xc9, 0x69, 0x30, +/* S - byte alignment */ + 0x00, 0xc4, 0x26, 0xdd, 0xe5, 0x52, 0xbb, 0x1c, 0x56, 0xbb, 0xa1, 0x73, + 0x93, 0x0b, 0xd5, 0x47, 0x63, 0x9a, 0xc8, 0xbc, 0x75, 0x2f, 0x76, 0x2e, + 0xaa, 0xf8, 0x92, 0x4a, 0x8a, 0xe5, 0xf6, 0x46, 0xca, 0x93, 0xae, 0x46, + 0x48, 0x8e, 0xad, 0x0f, 0x37, 0x58, 0xe7, 0x87, 0xf2, 0x37, 0x95, 0x92, + 0x0a, 0xf0, 0x26, 0x39, 0x50, 0xf8, 0x3c, 0x73, 0xf5, 0x99, 0x4b, 0x7f, + 0x4a, 0xd6, 0x82, 0x32, 0x86, 0x6c +}; +static const uint8_t nist_186_2_ecdsa_testvector_63_ptx[] = { +/* Msg */ + 0xd7, 0xf3, 0x4b, 0x6d, 0xf5, 0x43, 0x9d, 0xf3, 0x35, 0x51, 0x45, 0xc2, + 0xb1, 0x60, 0xca, 0x56, 0xc6, 0xea, 0x11, 0x14, 0x18, 0x93, 0x7e, 0xdb, + 0xd6, 0x5b, 0x5c, 0xdd, 0x40, 0x17, 0x7f, 0xad, 0x66, 0x22, 0x27, 0x98, + 0x32, 0x50, 0x28, 0x39, 0xa8, 0x23, 0x48, 0x48, 0x6d, 0x42, 0xe9, 0xb3, + 0x86, 0x26, 0xe8, 0xf0, 0x63, 0x17, 0xc4, 0x91, 0x1c, 0x57, 0x03, 0x19, + 0xfa, 0x9d, 0xd1, 0x0e, 0x39, 0xc4, 0xeb, 0x4f, 0x0c, 0xc5, 0xbb, 0xa8, + 0xe2, 0xe3, 0xc4, 0xa4, 0xe8, 0x25, 0x41, 0xa2, 0xcf, 0x09, 0x09, 0x2b, + 0xcf, 0x77, 0xb6, 0x83, 0xec, 0xf4, 0x06, 0x7e, 0x78, 0x18, 0x82, 0x95, + 0xd9, 0x42, 0x5d, 0x39, 0x8c, 0x8a, 0x9e, 0x68, 0x6a, 0xf7, 0x82, 0x7d, + 0x2a, 0xf3, 0x1b, 0x4c, 0x28, 0xfb, 0x3e, 0x6e, 0x64, 0x9b, 0x9c, 0xda, + 0xce, 0x9a, 0x2f, 0xb5, 0xc1, 0x72, 0xd8, 0x6c +}; +static const uint8_t nist_186_2_ecdsa_testvector_63_private[] = { +/* d - byte alignment */ + 0x01, 0x0e, 0xae, 0xa9, 0x31, 0x4d, 0xf0, 0x9f, 0x87, 0xf6, 0xd8, 0x96, + 0x07, 0x24, 0x2d, 0xfe, 0xb2, 0x5f, 0x20, 0x63, 0xcd, 0xeb, 0x50, 0x4e, + 0xcd, 0x01, 0xff, 0xa6, 0xe2, 0x2d, 0xab, 0xc0, 0x58, 0x78, 0xba, 0x56, + 0xcd, 0x7b, 0x54, 0x38, 0x40, 0x9d, 0x2e, 0x64, 0x78, 0xe1, 0x03, 0xa3, + 0xe7, 0xef, 0x4f, 0xa8, 0x79, 0x96, 0xc7, 0x95, 0x15, 0x56, 0xc1, 0x38, + 0x09, 0x90, 0x18, 0x16, 0x9c, 0x65 +}; +static const uint8_t nist_186_2_ecdsa_testvector_63_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xd2, 0xec, 0x1e, 0xd0, 0x13, 0xcc, 0x92, 0x75, 0xc0, 0x4a, 0x8d, + 0xdb, 0xea, 0x61, 0x68, 0xd9, 0x2e, 0x52, 0x2a, 0xae, 0x42, 0x00, 0x2c, + 0x3b, 0x0f, 0xf1, 0x00, 0x86, 0xb2, 0x16, 0x71, 0xd6, 0xd5, 0xe0, 0x85, + 0xe9, 0x5d, 0x41, 0x1a, 0xc9, 0x71, 0xfc, 0x57, 0x4a, 0x93, 0xd9, 0x94, + 0x43, 0x1d, 0x62, 0x1e, 0x67, 0xfb, 0x3e, 0xe4, 0x59, 0x9b, 0x7d, 0xd7, + 0xd4, 0x89, 0xd0, 0xc8, 0x4b, 0xa6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_63_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x56, 0x45, 0x3c, 0x78, 0x3a, 0xb4, 0x6f, 0x55, 0x3c, 0x6e, 0xae, + 0x03, 0xc4, 0x6d, 0x4f, 0x44, 0x63, 0xc6, 0x1c, 0x4c, 0xaa, 0xde, 0x1b, + 0x58, 0x3c, 0x3c, 0x82, 0x89, 0x1f, 0x2f, 0xda, 0x17, 0x17, 0x35, 0x1f, + 0x7d, 0x24, 0xff, 0x71, 0x8e, 0xf7, 0xb3, 0xf0, 0x2b, 0x39, 0xf2, 0xbd, + 0x97, 0xf9, 0xd0, 0x3a, 0xd0, 0x8d, 0x05, 0xa2, 0xea, 0xed, 0xb0, 0x59, + 0x0d, 0x94, 0x1f, 0x77, 0x60, 0x01 +}; +/* k = 1ee6d3bc2a6f7806bbb8e6993ff5a5cd2c4e34eac96d499814a387e88a3af15cfa251361fe02d376b8952f01c701246eaa1cdb6c40ef9537db1d9764c23242a0712 */ +static const uint8_t nist_186_2_ecdsa_testvector_63_out[] = { +/* R - byte alignment */ + 0x00, 0xe7, 0x7d, 0x33, 0x8c, 0x32, 0x41, 0x62, 0x09, 0x89, 0xa4, 0xd1, + 0x78, 0xb8, 0x51, 0xbd, 0x6c, 0x8d, 0xd0, 0x66, 0x70, 0x02, 0xc2, 0xfe, + 0xe6, 0x03, 0xdd, 0x2b, 0xbe, 0xe1, 0x9f, 0x57, 0x2d, 0x2d, 0x47, 0x9c, + 0x63, 0xed, 0x41, 0xee, 0xb9, 0x59, 0x88, 0xcb, 0x8f, 0xaa, 0x91, 0x23, + 0x42, 0xf5, 0x46, 0xf0, 0x44, 0x5e, 0xdb, 0x15, 0x8b, 0x0f, 0x2c, 0x6d, + 0x7a, 0xee, 0x4b, 0x37, 0xa7, 0x41, +/* S - byte alignment */ + 0x01, 0x02, 0x39, 0x4e, 0x35, 0x36, 0xa9, 0xd4, 0xc5, 0x9e, 0x8f, 0xfa, + 0x19, 0x45, 0xc0, 0x7b, 0xee, 0xbf, 0x53, 0x5c, 0xd3, 0xea, 0x00, 0x1a, + 0x4c, 0x31, 0x09, 0xd7, 0xdb, 0x6b, 0x11, 0xf3, 0xc8, 0x94, 0x03, 0xc4, + 0x9e, 0x06, 0xd5, 0x0d, 0xb4, 0xaa, 0xa9, 0xe5, 0x2e, 0x32, 0xb9, 0xdd, + 0x4d, 0x3c, 0xf4, 0xfe, 0xdb, 0x5e, 0x72, 0x80, 0x8f, 0xdc, 0x5b, 0x14, + 0xd6, 0xc4, 0xd2, 0x91, 0x9d, 0x96 +}; +static const uint8_t nist_186_2_ecdsa_testvector_64_ptx[] = { +/* Msg */ + 0x05, 0xeb, 0xa7, 0x19, 0xfd, 0x16, 0x2f, 0xa6, 0x27, 0x63, 0x26, 0x67, + 0x34, 0x91, 0xde, 0xb6, 0x23, 0x70, 0x7c, 0x76, 0x5b, 0xa0, 0xa8, 0xf9, + 0xf7, 0x9b, 0x89, 0x21, 0x61, 0xf5, 0xf0, 0xc6, 0x22, 0xe3, 0xd3, 0x58, + 0xf8, 0xfb, 0xfe, 0xc6, 0x29, 0x3a, 0x05, 0x9e, 0x18, 0x4b, 0x7d, 0x75, + 0x16, 0x06, 0x6b, 0x89, 0x7a, 0x38, 0xfd, 0xa5, 0xf4, 0xa2, 0x78, 0x45, + 0x1e, 0x44, 0x72, 0xfb, 0x54, 0xdb, 0x41, 0x11, 0xc6, 0xa8, 0xb3, 0x70, + 0xcb, 0x73, 0x00, 0xc0, 0x79, 0xd0, 0xfc, 0xd1, 0x72, 0xa1, 0x91, 0x3a, + 0x00, 0xdc, 0x6d, 0x40, 0x65, 0x8e, 0xf8, 0xf9, 0x6c, 0x20, 0x89, 0xb1, + 0x44, 0xd9, 0xd9, 0x8c, 0x8e, 0xa5, 0xb8, 0x6d, 0xb5, 0x15, 0xfe, 0x17, + 0x7e, 0xa6, 0xc5, 0x92, 0xe0, 0x46, 0xd5, 0xd1, 0x15, 0x14, 0x60, 0x91, + 0xf1, 0x68, 0xf0, 0x84, 0x73, 0x13, 0x9d, 0xaf +}; +static const uint8_t nist_186_2_ecdsa_testvector_64_private[] = { +/* d - byte alignment */ + 0x00, 0x5b, 0xb2, 0xc9, 0xf4, 0x51, 0xdd, 0x3e, 0x11, 0x13, 0x03, 0x5b, + 0x8f, 0x8a, 0x2f, 0xb7, 0xc2, 0xa5, 0xa2, 0xdf, 0x96, 0x30, 0x1e, 0x7b, + 0x42, 0xe9, 0xed, 0xf3, 0x65, 0xa9, 0x5e, 0x6e, 0xe6, 0x84, 0xa8, 0xfd, + 0xf1, 0x52, 0x67, 0x2a, 0x7f, 0x1a, 0x0b, 0x2a, 0xda, 0x2f, 0xa3, 0x30, + 0xaa, 0x91, 0x32, 0x99, 0x4d, 0x19, 0x69, 0xdb, 0x57, 0x0a, 0x19, 0x5f, + 0x1e, 0xf1, 0xea, 0xfe, 0x8d, 0x64 +}; +static const uint8_t nist_186_2_ecdsa_testvector_64_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xe1, 0xd4, 0x25, 0x54, 0xf0, 0x60, 0x16, 0xc2, 0x20, 0x24, 0xa0, + 0x57, 0xa1, 0xb9, 0xe0, 0x6c, 0x6a, 0x42, 0x2a, 0x85, 0x24, 0x2d, 0x7a, + 0xb6, 0x91, 0xc5, 0xf8, 0x78, 0x52, 0x9b, 0x69, 0xbc, 0xed, 0x42, 0x99, + 0x6a, 0x0d, 0xad, 0x50, 0x8b, 0x4d, 0x88, 0x7d, 0x33, 0xa3, 0x23, 0xfa, + 0x09, 0x3a, 0x10, 0x90, 0xe3, 0x17, 0x29, 0x7a, 0xf7, 0x38, 0x60, 0xad, + 0x89, 0x56, 0x3c, 0xa9, 0xd0, 0x2b +}; +static const uint8_t nist_186_2_ecdsa_testvector_64_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xbd, 0x54, 0xce, 0x4b, 0x34, 0xbf, 0xd9, 0x1c, 0x23, 0xf2, 0xfe, + 0xfa, 0x19, 0xbb, 0xaf, 0x2b, 0x36, 0x5d, 0x46, 0x43, 0x03, 0x2f, 0x2d, + 0xb0, 0x33, 0x13, 0xae, 0xfd, 0x23, 0x2d, 0xad, 0xef, 0xc3, 0x9a, 0xa9, + 0x67, 0x0f, 0xcc, 0x75, 0xe6, 0xf6, 0x06, 0x1f, 0xab, 0xa6, 0x2f, 0xc3, + 0x8c, 0x67, 0x4a, 0x4a, 0xc8, 0xe8, 0x53, 0x08, 0xd9, 0x6d, 0x2b, 0x97, + 0x6e, 0xe1, 0x72, 0x58, 0x78, 0xa9 +}; +/* k = 1a4b9f5a4c1b3662863c98ee560364fb046033b6b667ee42334113c661641e826fdcfabfea43ed8142e0a2b63e3d52fb0e5c1d8f5ea89cb756876cda91e58deb803 */ +static const uint8_t nist_186_2_ecdsa_testvector_64_out[] = { +/* R - byte alignment */ + 0x01, 0xf9, 0x6c, 0xb2, 0x22, 0x15, 0x97, 0xb9, 0x74, 0x36, 0x96, 0xad, + 0x42, 0xde, 0x0e, 0xcf, 0x76, 0x45, 0xc6, 0x3e, 0x49, 0x02, 0x58, 0xc2, + 0xbe, 0xf6, 0xd1, 0x2b, 0xde, 0x51, 0xb7, 0xd1, 0x7e, 0xfb, 0x98, 0xa9, + 0x70, 0x09, 0x03, 0x30, 0x17, 0x0e, 0x80, 0x7f, 0x81, 0x49, 0xf2, 0xb2, + 0x78, 0xff, 0x56, 0x72, 0x36, 0x73, 0xa3, 0x5c, 0x2b, 0xeb, 0xba, 0x13, + 0x0e, 0x19, 0x95, 0x16, 0xa2, 0xf3, +/* S - byte alignment */ + 0x00, 0x54, 0xa2, 0xce, 0x36, 0x1b, 0x35, 0x14, 0x27, 0x0d, 0x41, 0x1b, + 0x46, 0xf1, 0xab, 0xa6, 0xbf, 0xd4, 0xc0, 0x82, 0xc1, 0x97, 0xd9, 0xd1, + 0xa9, 0x2c, 0xb0, 0x4a, 0x77, 0x05, 0x0a, 0x2f, 0xa6, 0xe0, 0x99, 0x13, + 0x37, 0xce, 0x28, 0x5d, 0xe1, 0xa1, 0x46, 0x65, 0x00, 0x91, 0x96, 0x9d, + 0x17, 0xbb, 0xe5, 0x89, 0x38, 0x7a, 0x5d, 0x6e, 0x9a, 0x4d, 0x43, 0x2f, + 0x1c, 0xd0, 0xd8, 0x6a, 0x2a, 0x28 +}; +static const uint8_t nist_186_2_ecdsa_testvector_65_ptx[] = { +/* Msg */ + 0x93, 0x47, 0x74, 0x46, 0x34, 0xed, 0x26, 0x81, 0xcd, 0x80, 0x91, 0x0d, + 0xfd, 0xb3, 0xf1, 0x4a, 0x73, 0x08, 0x08, 0xfd, 0xb1, 0x8b, 0x08, 0xa2, + 0x10, 0xc0, 0xb3, 0x04, 0x05, 0xda, 0xc1, 0x0a, 0xa2, 0x2d, 0x82, 0xd4, + 0x60, 0xe6, 0xc4, 0x06, 0x1b, 0xfa, 0xf7, 0x64, 0x5e, 0x5c, 0x8f, 0xa0, + 0xe1, 0x73, 0xaa, 0x6f, 0x50, 0xcb, 0xf3, 0xe2, 0x4e, 0x0b, 0xc6, 0xf4, + 0xba, 0x27, 0x95, 0x60, 0x31, 0xd6, 0x8a, 0xb5, 0xd4, 0x47, 0x6d, 0xab, + 0x4b, 0x0f, 0xc9, 0xb8, 0x0a, 0x67, 0x4a, 0xdf, 0xd2, 0x94, 0x6a, 0xc9, + 0x7b, 0xa6, 0x4c, 0x16, 0xf2, 0x65, 0xe8, 0xf5, 0x7e, 0x89, 0x69, 0xf2, + 0x47, 0x29, 0xd3, 0x10, 0x18, 0x76, 0xe9, 0x18, 0x64, 0xa9, 0x4e, 0x30, + 0x87, 0x3a, 0xea, 0xaf, 0x4f, 0x53, 0x8f, 0x30, 0xbb, 0x84, 0xdd, 0xe6, + 0x02, 0xb8, 0x63, 0x2f, 0xd7, 0x68, 0x06, 0x6b +}; +static const uint8_t nist_186_2_ecdsa_testvector_65_private[] = { +/* d - byte alignment */ + 0x00, 0x6b, 0x7b, 0xc1, 0x6c, 0xc1, 0x5f, 0xce, 0x1c, 0xc4, 0x63, 0x7e, + 0x7f, 0x1b, 0x9f, 0x98, 0x4c, 0xb7, 0x52, 0x05, 0x45, 0x8d, 0xb7, 0xd1, + 0xb8, 0xb5, 0xab, 0x83, 0xf0, 0x92, 0xa7, 0x08, 0xa5, 0x5b, 0xdd, 0xb5, + 0xb5, 0x02, 0x42, 0x18, 0x26, 0xdf, 0xe3, 0xa3, 0x97, 0x6e, 0x13, 0x44, + 0x91, 0xf5, 0x78, 0x84, 0x23, 0x61, 0x7c, 0xcf, 0x41, 0x8c, 0x33, 0x0d, + 0x5b, 0x53, 0xc4, 0x05, 0x48, 0x57 +}; +static const uint8_t nist_186_2_ecdsa_testvector_65_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x33, 0x01, 0x27, 0xe2, 0xd1, 0x9c, 0xa0, 0xa2, 0xcb, 0xec, 0xad, + 0xe2, 0xe0, 0x86, 0xcc, 0x91, 0x53, 0xdd, 0xaa, 0xe2, 0x4a, 0xa6, 0xef, + 0x11, 0x1a, 0xc0, 0xa9, 0x9d, 0x82, 0x70, 0x8e, 0x2b, 0x2b, 0x64, 0xd3, + 0x8c, 0x9d, 0xcc, 0x83, 0x3b, 0xb0, 0x91, 0xd3, 0x9e, 0x2a, 0xff, 0x69, + 0xca, 0xc6, 0x0b, 0x2a, 0x2b, 0x49, 0x05, 0x20, 0x44, 0xb2, 0xc7, 0xbf, + 0x09, 0x34, 0xe9, 0xf2, 0x21, 0x17 +}; +static const uint8_t nist_186_2_ecdsa_testvector_65_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x7e, 0x82, 0xf5, 0xfa, 0x31, 0xed, 0xa6, 0x9c, 0x1b, 0x78, 0xbf, + 0x9a, 0xd8, 0x08, 0x20, 0xfd, 0x47, 0x0a, 0x77, 0xf7, 0x73, 0xb0, 0xd4, + 0xde, 0x4e, 0x35, 0xc8, 0x50, 0x45, 0x40, 0x43, 0x4f, 0x2d, 0x50, 0x48, + 0xc9, 0x2d, 0xf6, 0x39, 0xf0, 0xf3, 0x50, 0x4c, 0x0b, 0x24, 0xa1, 0xa9, + 0xbe, 0x08, 0xf6, 0x6a, 0xa1, 0xe9, 0x21, 0x8a, 0x95, 0xc9, 0x29, 0x91, + 0x51, 0x58, 0xc4, 0x56, 0x3b, 0xc9 +}; +/* k = 0fc6c339a31bed7d3c4a86424c3c1b2aa5dabc5b570c00d69b01429950636ce7a7b1a22d02a185a6fcc3b87c06a27399b4bfd94fb31d8acd731eb2716d66eefc563 */ +static const uint8_t nist_186_2_ecdsa_testvector_65_out[] = { +/* R - byte alignment */ + 0x01, 0x50, 0x5b, 0x84, 0x34, 0x60, 0x26, 0x6a, 0xff, 0xb1, 0x30, 0x39, + 0x72, 0x79, 0x47, 0x7c, 0xd1, 0x92, 0x03, 0x93, 0xa4, 0xd7, 0x80, 0x08, + 0xb1, 0xf1, 0x1b, 0xff, 0x53, 0xb4, 0x6b, 0x0d, 0xf0, 0x5c, 0x78, 0x3d, + 0xae, 0x9a, 0x49, 0x4a, 0xa1, 0x2e, 0x48, 0xb6, 0xfd, 0x86, 0x71, 0xc2, + 0xd5, 0x8d, 0x86, 0x12, 0xce, 0x01, 0x9d, 0x94, 0xf0, 0x8e, 0xd8, 0xed, + 0x40, 0x31, 0x7d, 0x14, 0xda, 0xc7, +/* S - byte alignment */ + 0x00, 0x35, 0x99, 0x8e, 0xbb, 0x40, 0x50, 0x2b, 0xae, 0xb5, 0xec, 0x86, + 0xbc, 0xde, 0x04, 0x63, 0xd7, 0xcc, 0x95, 0x97, 0xd0, 0xae, 0x17, 0xe6, + 0x48, 0x91, 0x68, 0x00, 0x49, 0xef, 0xe3, 0x9b, 0xa4, 0x6d, 0x87, 0x42, + 0x5a, 0xcf, 0x47, 0xf1, 0x62, 0x23, 0x65, 0x97, 0x5e, 0xa7, 0x96, 0x88, + 0x05, 0xe7, 0xd0, 0x8a, 0xeb, 0x3c, 0x30, 0x77, 0x92, 0xcd, 0xd1, 0x30, + 0xce, 0x3b, 0xf4, 0x2e, 0x13, 0x48 +}; +static const uint8_t nist_186_2_ecdsa_testvector_66_ptx[] = { +/* Msg */ + 0xc3, 0xeb, 0xab, 0xf4, 0xef, 0x29, 0xe3, 0xb0, 0xce, 0x98, 0xbd, 0xf2, + 0xd2, 0x69, 0xef, 0xab, 0xfc, 0x2f, 0x13, 0x1b, 0x59, 0x4f, 0x4d, 0xe6, + 0xcd, 0xb1, 0x2d, 0x6b, 0x0f, 0xbc, 0xd7, 0x51, 0xf5, 0x82, 0x61, 0x62, + 0xf2, 0x37, 0x7c, 0x9d, 0xdd, 0xe8, 0x57, 0x86, 0xf3, 0x69, 0xc0, 0xc1, + 0x20, 0x90, 0x8d, 0xdf, 0x7a, 0xa0, 0x3a, 0x78, 0x0e, 0x08, 0xd3, 0x7a, + 0xe0, 0x4e, 0x14, 0xc0, 0x2d, 0x46, 0xd0, 0xe7, 0xf3, 0x87, 0x8f, 0x5d, + 0xb4, 0x1f, 0x7b, 0xba, 0x76, 0x86, 0x7d, 0x54, 0x0e, 0xd1, 0xa3, 0x0d, + 0x9e, 0x28, 0xc5, 0x70, 0x5d, 0x7a, 0x68, 0xfd, 0x96, 0x6f, 0xe2, 0xc0, + 0xf4, 0x9f, 0xbf, 0x29, 0xfc, 0x01, 0x64, 0x17, 0xdb, 0xa6, 0xf2, 0x36, + 0x62, 0xa7, 0x6d, 0x8b, 0x4f, 0x5c, 0x1e, 0x4d, 0xce, 0xce, 0x35, 0xf7, + 0x3f, 0x6f, 0xb3, 0x9b, 0x3a, 0x09, 0x87, 0x79 +}; +static const uint8_t nist_186_2_ecdsa_testvector_66_private[] = { +/* d - byte alignment */ + 0x01, 0x8e, 0x5c, 0xe7, 0x41, 0x9e, 0x51, 0x18, 0xe7, 0x15, 0xd7, 0x37, + 0xb1, 0xee, 0x69, 0x7b, 0x46, 0xb8, 0x97, 0x04, 0xd9, 0xc2, 0x45, 0xb2, + 0x51, 0xa2, 0x56, 0xd4, 0xda, 0x2a, 0xdb, 0xe4, 0x70, 0xba, 0x31, 0xe1, + 0x0e, 0x5a, 0xca, 0x41, 0x06, 0xa2, 0xb9, 0x90, 0x27, 0x2f, 0xc5, 0x26, + 0xd0, 0xdf, 0xf0, 0x05, 0x45, 0xa3, 0x78, 0xb8, 0x45, 0x86, 0x55, 0x3e, + 0xe2, 0xa6, 0x39, 0xb6, 0xd0, 0xd5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_66_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x2b, 0x13, 0xbc, 0xae, 0xc1, 0x0e, 0x9b, 0x4b, 0xd4, 0x37, 0x6e, + 0xbc, 0x54, 0x13, 0xbe, 0xb7, 0x42, 0x65, 0xa8, 0x39, 0xc8, 0xcd, 0x84, + 0x0e, 0x42, 0x39, 0x3f, 0xf2, 0x8c, 0xca, 0x74, 0xca, 0xb3, 0xdc, 0x24, + 0x35, 0xfd, 0x20, 0x9a, 0xb9, 0xd6, 0x14, 0xa5, 0xaf, 0x71, 0x56, 0x37, + 0x2f, 0x86, 0xfc, 0x78, 0x44, 0x65, 0xd3, 0x8c, 0x12, 0xa4, 0x04, 0x22, + 0x55, 0x91, 0xf3, 0xf2, 0x19, 0x96 +}; +static const uint8_t nist_186_2_ecdsa_testvector_66_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x41, 0xfc, 0x89, 0x51, 0x69, 0xd2, 0x5f, 0x33, 0x73, 0x16, 0x1d, + 0x77, 0x8b, 0x29, 0xca, 0x13, 0x80, 0x0e, 0x41, 0x1c, 0x21, 0x55, 0x2e, + 0xb7, 0x80, 0xfe, 0x32, 0xc8, 0x67, 0x6b, 0x5b, 0xcb, 0xbc, 0x88, 0x2d, + 0x25, 0xc0, 0xaa, 0x59, 0x8b, 0xe4, 0x70, 0x22, 0x42, 0x2d, 0x71, 0xb1, + 0x8f, 0x0c, 0x24, 0xe2, 0xa1, 0x98, 0x61, 0x5e, 0x7e, 0xda, 0xcb, 0x12, + 0xd1, 0x68, 0xf4, 0x39, 0x1a, 0x5d +}; +/* k = 00cb71ea593cb7804c2848be95d3ad3dbf04f9da524b1f0f98c92137b861baa8de20ef6ce6089ab2a6f79c6e76c92f6ededac1d2bb9dbd929cb9d4952f1ff3b4ec7 */ +static const uint8_t nist_186_2_ecdsa_testvector_66_out[] = { +/* R - byte alignment */ + 0x00, 0x7b, 0x89, 0x81, 0x5a, 0xfd, 0x85, 0x08, 0x60, 0xf8, 0xd1, 0x96, + 0x35, 0x4d, 0x73, 0xe5, 0x0c, 0x76, 0x1c, 0xb5, 0xb8, 0x32, 0x31, 0xa2, + 0x94, 0x65, 0x5e, 0x20, 0xc8, 0x1a, 0xe3, 0x82, 0x13, 0xc3, 0x33, 0x7b, + 0x45, 0x0e, 0x05, 0x3d, 0x7b, 0xf0, 0x2a, 0xca, 0x6f, 0x31, 0x35, 0xe6, + 0x95, 0x70, 0x4c, 0xc3, 0x37, 0x18, 0x84, 0x71, 0x29, 0xba, 0xb6, 0xb5, + 0x41, 0xad, 0x11, 0x3c, 0xf7, 0xeb, +/* S - byte alignment */ + 0x01, 0x31, 0xf6, 0x79, 0x2c, 0x60, 0x83, 0x00, 0xd4, 0x20, 0x66, 0xc8, + 0x6c, 0xa8, 0x91, 0x5a, 0xf8, 0x0e, 0x16, 0x75, 0xcd, 0xa7, 0xe0, 0xf3, + 0x06, 0x49, 0xe4, 0xbd, 0x08, 0x33, 0xef, 0x6f, 0x58, 0xb3, 0xc0, 0xa5, + 0xb3, 0x19, 0x53, 0x65, 0xf5, 0x83, 0x59, 0x33, 0xf5, 0xa4, 0x54, 0x92, + 0xca, 0x3a, 0x8f, 0x70, 0x32, 0x89, 0x7e, 0x2d, 0x0f, 0xfc, 0xc8, 0x44, + 0x1d, 0x5c, 0x44, 0x3d, 0xea, 0xd1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_67_ptx[] = { +/* Msg */ + 0xce, 0xb5, 0x5a, 0x4a, 0x0e, 0x78, 0xc5, 0x32, 0x22, 0x1c, 0x82, 0x43, + 0x58, 0x7e, 0x88, 0xe9, 0x7b, 0x14, 0x08, 0xe3, 0x60, 0x2e, 0xa0, 0xa4, + 0xbc, 0x7c, 0xd3, 0xf9, 0x38, 0xd1, 0xb6, 0xed, 0xc8, 0x26, 0xeb, 0xea, + 0x38, 0xe2, 0xd3, 0x20, 0x08, 0x59, 0x00, 0x2a, 0x79, 0x92, 0xe9, 0xef, + 0xe8, 0x4d, 0xe2, 0xc7, 0x5b, 0x44, 0x4b, 0xe0, 0x5a, 0xb2, 0x07, 0xdf, + 0x00, 0x12, 0x30, 0xca, 0x51, 0x29, 0x08, 0x25, 0xce, 0x46, 0x33, 0x5b, + 0x47, 0xc9, 0x24, 0x60, 0xf1, 0xe2, 0xd6, 0x95, 0xb8, 0x9b, 0xbc, 0xec, + 0xd6, 0x19, 0xfa, 0x4c, 0xa5, 0x1e, 0xd5, 0x37, 0xb1, 0xd3, 0x68, 0xaa, + 0x12, 0xc5, 0x99, 0x44, 0xf9, 0x2d, 0x4c, 0xab, 0x88, 0x74, 0xd7, 0x2c, + 0xe7, 0xf6, 0xb5, 0xa1, 0x94, 0x07, 0x7e, 0x98, 0xfa, 0x33, 0x16, 0xb1, + 0x46, 0xca, 0x25, 0x48, 0x76, 0x9d, 0xc8, 0x54 +}; +static const uint8_t nist_186_2_ecdsa_testvector_67_private[] = { +/* d - byte alignment */ + 0x00, 0x52, 0x06, 0x28, 0x11, 0x2a, 0x15, 0xad, 0x5f, 0xe4, 0xd9, 0x00, + 0xce, 0x73, 0xb0, 0x6a, 0xea, 0x1d, 0x91, 0x45, 0xca, 0x9c, 0x6c, 0x0b, + 0x77, 0xc0, 0x19, 0xc1, 0xc3, 0x23, 0x58, 0x05, 0xab, 0xd3, 0x27, 0x50, + 0x7b, 0x10, 0x67, 0x82, 0xf7, 0xcb, 0x90, 0xdc, 0xa0, 0xb6, 0xdf, 0xe1, + 0xa9, 0x9e, 0xc7, 0xeb, 0x77, 0xfe, 0x6b, 0x54, 0x8b, 0xa9, 0x8d, 0x5b, + 0x91, 0x14, 0x11, 0x54, 0x0f, 0x02 +}; +static const uint8_t nist_186_2_ecdsa_testvector_67_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xc6, 0xca, 0x7d, 0x88, 0xf5, 0xcd, 0x5a, 0xd1, 0xd1, 0xfc, 0xdc, + 0x4d, 0x5c, 0x10, 0x87, 0x7a, 0x9f, 0x5b, 0xd5, 0x18, 0xb4, 0x53, 0x23, + 0x4b, 0x40, 0x2b, 0xcf, 0x9e, 0x16, 0x25, 0x67, 0xa7, 0xc6, 0xb0, 0x47, + 0x7b, 0x72, 0xc2, 0x7e, 0xbb, 0x79, 0xa4, 0x25, 0x6e, 0xb3, 0xdf, 0x6b, + 0x89, 0xe7, 0xc6, 0xc5, 0x00, 0x19, 0x4b, 0x91, 0x7e, 0xc0, 0xcf, 0xdb, + 0x8d, 0xb5, 0x23, 0x24, 0x97, 0xfe +}; +static const uint8_t nist_186_2_ecdsa_testvector_67_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xe7, 0x06, 0xe7, 0xc6, 0xb9, 0xee, 0x85, 0xa9, 0xf7, 0xf8, 0xe5, + 0x15, 0xa3, 0xa4, 0x04, 0xe0, 0x11, 0xf8, 0xcc, 0x1e, 0x92, 0x0c, 0x59, + 0xb0, 0xf6, 0x57, 0xd7, 0x95, 0x21, 0x2f, 0x01, 0x97, 0x5b, 0x1e, 0xc8, + 0x06, 0x5a, 0xb1, 0xc3, 0xcf, 0x6f, 0xd9, 0x2d, 0x12, 0xeb, 0x2f, 0x54, + 0x6f, 0xa1, 0xb0, 0xb2, 0x95, 0xb1, 0xd9, 0x70, 0xf5, 0x52, 0xfc, 0x3f, + 0x8d, 0xa0, 0xd2, 0x15, 0x18, 0xd3 +}; +/* k = 0787b4a2f40954128fd6463a4a67d79dc042c3ac99c2836e2342449c81eff65ad6175c077a5b748e6235101b6ab7cd15cd7af27fc73018c3b447409ff535f6396a1 */ +static const uint8_t nist_186_2_ecdsa_testvector_67_out[] = { +/* R - byte alignment */ + 0x01, 0x45, 0x56, 0xd7, 0x5f, 0xf5, 0x41, 0xb9, 0x15, 0xc5, 0x85, 0xd8, + 0x0f, 0xed, 0xc1, 0x78, 0x16, 0x72, 0xce, 0x63, 0xdf, 0x34, 0x77, 0x7a, + 0x4a, 0x37, 0x39, 0xc1, 0xe6, 0x6d, 0x41, 0x2f, 0xd7, 0xa2, 0x8b, 0x5b, + 0x02, 0x9f, 0x68, 0x67, 0xd9, 0x4f, 0xf0, 0xd1, 0x3e, 0xa5, 0xa1, 0x71, + 0x27, 0xd9, 0x38, 0x95, 0xd8, 0x73, 0x81, 0x46, 0x61, 0x10, 0x50, 0x9f, + 0x36, 0x9d, 0x15, 0xf5, 0x99, 0xea, +/* S - byte alignment */ + 0x00, 0xd9, 0xce, 0xd8, 0x28, 0xd8, 0xda, 0xb1, 0x25, 0x28, 0x98, 0x93, + 0x27, 0x6b, 0xed, 0xa8, 0xda, 0xa4, 0x66, 0x0d, 0x2f, 0xf8, 0xa3, 0xf1, + 0x57, 0xb1, 0xb6, 0x16, 0xd1, 0x8e, 0x4a, 0x79, 0x83, 0xc7, 0xb8, 0xf8, + 0x79, 0xe4, 0x23, 0xbf, 0xac, 0x39, 0x90, 0x90, 0x5f, 0x84, 0xf1, 0xc9, + 0x07, 0x9e, 0x23, 0x99, 0xdf, 0x5f, 0x4f, 0x1d, 0xa9, 0x47, 0xb2, 0x2a, + 0xf8, 0xe0, 0xed, 0x0a, 0x68, 0xf1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_68_ptx[] = { +/* Msg */ + 0x74, 0x53, 0x54, 0x64, 0x27, 0x79, 0x68, 0xda, 0xf4, 0xc7, 0x97, 0x3f, + 0x30, 0x14, 0xee, 0xbd, 0x6d, 0x76, 0xbc, 0xb7, 0x93, 0x06, 0x46, 0xad, + 0x33, 0xe3, 0xbc, 0x60, 0x17, 0x7a, 0x6c, 0x37, 0x1e, 0x04, 0x36, 0xe2, + 0x47, 0x4f, 0x40, 0x3d, 0x0b, 0xc2, 0xeb, 0x77, 0xf0, 0x9c, 0x05, 0x73, + 0x5b, 0x7c, 0x40, 0x6e, 0xa5, 0x26, 0xe2, 0xe3, 0x72, 0x84, 0xbf, 0xab, + 0x3e, 0xeb, 0x64, 0x69, 0x39, 0xa0, 0x96, 0x25, 0x55, 0x9b, 0xfb, 0x37, + 0x9d, 0x8a, 0x16, 0x67, 0xc8, 0x19, 0x79, 0x52, 0x0e, 0x71, 0x35, 0x10, + 0x3a, 0xfe, 0x96, 0x13, 0x01, 0x76, 0x0d, 0x52, 0x92, 0x17, 0x6e, 0xa7, + 0x6e, 0x30, 0x5b, 0x76, 0x7a, 0xe2, 0x00, 0x90, 0x52, 0x28, 0x02, 0x57, + 0xe1, 0x15, 0xb1, 0x22, 0x2f, 0x5d, 0x85, 0xe3, 0x79, 0x17, 0xc8, 0x07, + 0x87, 0xc1, 0x90, 0x9d, 0x3a, 0x85, 0xf0, 0xbb +}; +static const uint8_t nist_186_2_ecdsa_testvector_68_private[] = { +/* d - byte alignment */ + 0x00, 0xef, 0xe1, 0xf5, 0x92, 0x83, 0xcf, 0xef, 0x65, 0xc8, 0x4b, 0x0d, + 0xe9, 0x46, 0x93, 0xd2, 0x99, 0xd9, 0x81, 0x34, 0x08, 0x8f, 0xf1, 0xc1, + 0x9b, 0x3d, 0xfd, 0xac, 0x78, 0x95, 0x01, 0x32, 0x75, 0xfb, 0x4e, 0xa4, + 0xc3, 0x45, 0xe7, 0x8e, 0xf5, 0x39, 0x4d, 0x8e, 0x2f, 0xb1, 0x0f, 0xa6, + 0xf7, 0xe7, 0xd1, 0x86, 0xa7, 0xaa, 0xfe, 0x38, 0x20, 0x6d, 0xd7, 0xf3, + 0xe3, 0x36, 0x05, 0x17, 0x36, 0x0f +}; +static const uint8_t nist_186_2_ecdsa_testvector_68_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xc0, 0x39, 0xc9, 0x86, 0xf5, 0xd7, 0x1b, 0xae, 0x5a, 0x15, 0x79, + 0x86, 0xfd, 0x80, 0xed, 0xd5, 0x0c, 0xa1, 0x5a, 0x0a, 0xc0, 0x00, 0xd4, + 0x15, 0x30, 0xb8, 0xb0, 0xf3, 0xd9, 0xd8, 0x81, 0x9f, 0x64, 0xee, 0xde, + 0xa9, 0x1c, 0xd8, 0xf0, 0x0d, 0xb1, 0x93, 0x1e, 0x53, 0xe0, 0x6c, 0xb5, + 0x34, 0x4b, 0x82, 0xc6, 0x92, 0xf8, 0x73, 0x11, 0xcf, 0xb1, 0xc4, 0x7d, + 0xc7, 0x31, 0x8c, 0x06, 0x13, 0x8f +}; +static const uint8_t nist_186_2_ecdsa_testvector_68_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x3b, 0x17, 0xf8, 0x33, 0xfe, 0x30, 0xce, 0xce, 0x8c, 0xa5, 0x45, + 0x48, 0xb5, 0x31, 0xf9, 0x4f, 0xba, 0x92, 0x09, 0x15, 0x69, 0xa3, 0x2f, + 0x68, 0x11, 0xe2, 0x31, 0x5d, 0x8b, 0x0f, 0xc6, 0x4a, 0x62, 0xf4, 0x32, + 0xac, 0x0f, 0xd5, 0x42, 0x77, 0xf8, 0x19, 0x63, 0xf2, 0xb2, 0x9c, 0x13, + 0x11, 0x07, 0x75, 0xda, 0x93, 0xea, 0xa0, 0x3a, 0x31, 0xcd, 0xd3, 0x1d, + 0xd0, 0x39, 0x20, 0x47, 0xd4, 0x3a +}; +/* k = 17eaddf16a30e150adace9e1f3284f5ef34c0deb8f819c388e9a27fa091d2e3a1098cedf0a0cc7d3b245ca722b1acd347997961d9a2dc60fe96bda520aad4d2a8eb */ +static const uint8_t nist_186_2_ecdsa_testvector_68_out[] = { +/* R - byte alignment */ + 0x01, 0xaf, 0xb0, 0x93, 0x6e, 0x04, 0x23, 0x5b, 0xcd, 0xf2, 0x77, 0x42, + 0x06, 0x70, 0x35, 0xa4, 0xff, 0x67, 0x3a, 0x0d, 0xe8, 0xff, 0xbb, 0x12, + 0x59, 0xcd, 0x61, 0xab, 0x07, 0xee, 0xf0, 0x85, 0xb9, 0x9d, 0x76, 0xe1, + 0x1b, 0x3c, 0xca, 0x16, 0x97, 0xbf, 0x93, 0xd7, 0x3b, 0x3a, 0x72, 0xe8, + 0xa0, 0x0c, 0x61, 0xae, 0x66, 0xea, 0xe9, 0x6c, 0x95, 0x1a, 0xd0, 0xb7, + 0xfe, 0x8e, 0xf6, 0x70, 0xb2, 0xe0, +/* S - byte alignment */ + 0x01, 0x01, 0xce, 0x08, 0xad, 0x3c, 0xec, 0xec, 0x9e, 0x5c, 0x42, 0x6b, + 0xf0, 0x0b, 0xc9, 0x9e, 0x2e, 0x47, 0x14, 0x91, 0xb3, 0x41, 0xe9, 0xac, + 0x6d, 0xe2, 0x0c, 0xa8, 0xf0, 0xd3, 0x32, 0xc0, 0x9c, 0x36, 0xb5, 0x6a, + 0xb0, 0x59, 0x18, 0xf5, 0xdd, 0x0d, 0x16, 0x8a, 0xca, 0xb6, 0xc3, 0x19, + 0xcf, 0x14, 0x61, 0xfb, 0x61, 0xf8, 0xcc, 0x33, 0xfb, 0x96, 0x1e, 0x0a, + 0xa6, 0x68, 0x84, 0xce, 0xce, 0x30 +}; +static const uint8_t nist_186_2_ecdsa_testvector_69_ptx[] = { +/* Msg */ + 0x07, 0xe3, 0xc8, 0x9d, 0xc3, 0xd1, 0xd8, 0x20, 0x5b, 0xe4, 0x4b, 0xfd, + 0x63, 0x32, 0x77, 0x82, 0xff, 0x1b, 0xc2, 0xc8, 0xf7, 0x17, 0x5c, 0x92, + 0x0e, 0xb2, 0x2e, 0x77, 0x90, 0xd4, 0x0d, 0x44, 0x2b, 0x46, 0x34, 0x9c, + 0xff, 0x72, 0xf1, 0xe1, 0xf8, 0x6a, 0x9e, 0x58, 0x5c, 0x2c, 0xd3, 0x87, + 0xa0, 0x25, 0xda, 0xe2, 0x80, 0xf3, 0x63, 0xa7, 0x4f, 0x6f, 0x79, 0x07, + 0x8b, 0xeb, 0xb5, 0x86, 0xb4, 0xb8, 0xb2, 0xa4, 0x5e, 0xec, 0xc0, 0xbd, + 0x86, 0x61, 0xdd, 0x2e, 0x22, 0x01, 0xe1, 0xb9, 0xfb, 0x41, 0xf8, 0x2b, + 0xbf, 0xec, 0x55, 0x3b, 0x52, 0x22, 0x25, 0xb6, 0x66, 0xa0, 0xc2, 0xd9, + 0x4b, 0x42, 0x2a, 0xfe, 0x08, 0xc5, 0xaf, 0x7c, 0xaa, 0xd2, 0xf0, 0xc8, + 0xdc, 0x38, 0x07, 0xe0, 0xb8, 0x7a, 0x04, 0xe9, 0xdd, 0x89, 0x9b, 0x16, + 0xc2, 0xd2, 0x19, 0xcd, 0x4a, 0x7b, 0x9c, 0x05 +}; +static const uint8_t nist_186_2_ecdsa_testvector_69_private[] = { +/* d - byte alignment */ + 0x01, 0xdf, 0xf5, 0x6f, 0x8c, 0x4d, 0xa7, 0x8f, 0x84, 0x5c, 0x1d, 0xd7, + 0x60, 0xc7, 0x87, 0x3f, 0x2d, 0x6f, 0x86, 0x61, 0x3a, 0x59, 0x01, 0x66, + 0x6f, 0x57, 0x99, 0x8a, 0x59, 0xd0, 0xfa, 0x64, 0x5c, 0xc9, 0xa1, 0xab, + 0x38, 0x8f, 0x6f, 0x99, 0xfa, 0xef, 0x83, 0xdb, 0x24, 0xc0, 0x19, 0xac, + 0x83, 0xaa, 0xc6, 0xee, 0x44, 0x60, 0xe4, 0xfb, 0x83, 0x71, 0x8d, 0xf0, + 0x92, 0x26, 0x03, 0x3d, 0x7a, 0xd6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_69_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x1b, 0xda, 0x77, 0x68, 0x21, 0x8b, 0x82, 0xec, 0xb8, 0xb1, 0xbf, + 0x1f, 0x08, 0x2a, 0xc5, 0x7d, 0x14, 0x6a, 0x36, 0x71, 0x54, 0x0d, 0x20, + 0x0e, 0xe4, 0xa2, 0x9b, 0x5b, 0x01, 0xfd, 0x6f, 0xb7, 0xf4, 0x64, 0x48, + 0xaa, 0x46, 0xf6, 0x40, 0xa6, 0xcc, 0x36, 0x31, 0x9e, 0x62, 0x37, 0xa0, + 0xfe, 0x26, 0xbf, 0x8a, 0x0c, 0x5b, 0xd6, 0xd1, 0x4d, 0xa1, 0x0c, 0xee, + 0x4b, 0x4d, 0x24, 0x66, 0x12, 0xf8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_69_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x2b, 0xbd, 0x5c, 0x3d, 0x13, 0x92, 0xe4, 0x61, 0x6d, 0x8d, 0xf0, + 0x85, 0x6e, 0x18, 0xfe, 0xb9, 0x5c, 0xe5, 0xbd, 0x37, 0x3b, 0x3a, 0x04, + 0x1f, 0x48, 0x52, 0x00, 0x62, 0x8c, 0x20, 0xe4, 0x2a, 0xbc, 0xa5, 0x9f, + 0xd0, 0xdd, 0x93, 0x6c, 0x64, 0x3d, 0xc2, 0xdc, 0xd8, 0xb5, 0xd9, 0x33, + 0x14, 0x75, 0x6e, 0xec, 0x63, 0xdd, 0x01, 0x37, 0xbf, 0x61, 0xbf, 0x2f, + 0xca, 0xd1, 0xa0, 0x6b, 0x45, 0x80 +}; +/* k = 04a8d24aa509b9aa0515920528b86ec50bee63a3e852d162f0723e83f744c6de3adf95c7aebeff779938259db3089d4df3a14315b811e07a2f451c7183588b8cfb5 */ +static const uint8_t nist_186_2_ecdsa_testvector_69_out[] = { +/* R - byte alignment */ + 0x01, 0xce, 0x49, 0xa1, 0x10, 0xb5, 0x7e, 0xf3, 0x61, 0x04, 0x95, 0x31, + 0x84, 0xba, 0x30, 0x3d, 0xc4, 0xf6, 0xf1, 0xbe, 0xa3, 0x86, 0x73, 0x57, + 0xb5, 0x7b, 0x07, 0x3d, 0x2c, 0xfc, 0x6c, 0xeb, 0xb6, 0xb3, 0xf5, 0xd0, + 0x7b, 0x3b, 0xcc, 0x21, 0xc4, 0x39, 0x81, 0x08, 0xb4, 0xf0, 0xe2, 0xf4, + 0xab, 0x77, 0xaf, 0xe6, 0x01, 0xbd, 0xdf, 0x33, 0x11, 0x55, 0x8f, 0x99, + 0x12, 0x33, 0x29, 0xf2, 0x73, 0xa9, +/* S - byte alignment */ + 0x00, 0xdb, 0xe7, 0xba, 0xb4, 0x9e, 0xe2, 0x6f, 0x51, 0xc2, 0xe8, 0x60, + 0x90, 0x7e, 0xc2, 0x19, 0x47, 0x65, 0x00, 0x5b, 0xad, 0x98, 0xb0, 0x9b, + 0x68, 0x9f, 0xc5, 0x8e, 0x22, 0x7f, 0xf6, 0x1e, 0x8e, 0xb2, 0x9b, 0x79, + 0xa5, 0xc5, 0x4f, 0x54, 0x47, 0xe9, 0x33, 0xa7, 0x18, 0x02, 0x56, 0x45, + 0xd9, 0x15, 0x61, 0x06, 0xdc, 0x7b, 0x3d, 0x43, 0x33, 0xf3, 0xa6, 0xe0, + 0x67, 0x0e, 0x73, 0xc7, 0x7a, 0x15 +}; +static const uint8_t nist_186_2_ecdsa_testvector_70_ptx[] = { +/* Msg */ + 0xd4, 0xa6, 0x50, 0x9f, 0xbe, 0x6f, 0x9b, 0x0d, 0xcd, 0x7a, 0x1b, 0xed, + 0x45, 0x02, 0xea, 0x86, 0xa4, 0xa6, 0x00, 0x82, 0x3d, 0x77, 0xf6, 0x9f, + 0x23, 0x50, 0x10, 0xa7, 0x48, 0x66, 0x7b, 0xa2, 0xe6, 0x1f, 0xd3, 0x4a, + 0x1e, 0x28, 0xe9, 0xbf, 0xe0, 0xc2, 0xc2, 0x7c, 0x0a, 0x5c, 0xe3, 0x8a, + 0xd4, 0x67, 0xcb, 0xf3, 0x6b, 0x66, 0xc2, 0x7a, 0xdc, 0x44, 0xd1, 0x89, + 0x34, 0xeb, 0x12, 0x6b, 0xe5, 0x12, 0x2a, 0xbb, 0x6c, 0x56, 0x13, 0x1d, + 0x31, 0x8d, 0x1f, 0x2c, 0xaf, 0x57, 0x39, 0xb3, 0xd4, 0xf5, 0x6e, 0x1f, + 0xab, 0x5f, 0xad, 0x34, 0x38, 0x90, 0xcb, 0x00, 0xa4, 0x25, 0xca, 0x0d, + 0x9a, 0x26, 0x5b, 0xdb, 0xf0, 0x24, 0xa1, 0x8d, 0x8a, 0x84, 0x38, 0xe3, + 0x7b, 0x1a, 0x76, 0x68, 0x6e, 0xfa, 0xf1, 0xed, 0x45, 0x8a, 0x41, 0x35, + 0xff, 0xdc, 0x07, 0xf2, 0xdf, 0x3b, 0x2e, 0xf0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_70_private[] = { +/* d - byte alignment */ + 0x01, 0x5f, 0x5a, 0x6d, 0x61, 0xc0, 0x66, 0xe7, 0x4c, 0xfd, 0x41, 0xf7, + 0xa9, 0x45, 0xc7, 0x1e, 0xc0, 0x8d, 0x5c, 0x99, 0xdc, 0xe3, 0x58, 0x54, + 0x6e, 0x5a, 0x17, 0xfa, 0xca, 0xe5, 0xd6, 0x57, 0xff, 0x27, 0xd0, 0x20, + 0x45, 0x66, 0xb2, 0x9d, 0x78, 0x27, 0x5d, 0x67, 0x38, 0x43, 0x38, 0xb7, + 0x7d, 0xb6, 0x1d, 0x60, 0x2a, 0x99, 0x72, 0x09, 0x61, 0xc3, 0xe7, 0xb0, + 0x86, 0x81, 0xff, 0x31, 0xba, 0xe6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_70_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xf4, 0x20, 0x22, 0x85, 0x12, 0xec, 0x74, 0xa1, 0x45, 0xd4, 0x72, + 0xc4, 0x13, 0x94, 0x8c, 0x4a, 0x6d, 0xbf, 0xfb, 0x42, 0x01, 0x4d, 0x35, + 0x9a, 0x31, 0x5e, 0x8c, 0x85, 0xa1, 0x82, 0xd0, 0x11, 0xd8, 0x08, 0x03, + 0xd9, 0x07, 0xe0, 0x71, 0x47, 0xa7, 0x8a, 0x2e, 0x86, 0x2d, 0xc8, 0x19, + 0x27, 0xc9, 0x95, 0x36, 0x52, 0xfe, 0xf7, 0x52, 0x3a, 0xb0, 0xfb, 0x9e, + 0x18, 0xc4, 0x66, 0xb2, 0x3c, 0x96 +}; +static const uint8_t nist_186_2_ecdsa_testvector_70_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x26, 0x9f, 0x90, 0x9e, 0xc3, 0x35, 0x51, 0xb4, 0xea, 0x92, 0x58, + 0x9e, 0x72, 0x94, 0xb2, 0x72, 0xe3, 0xdb, 0x1c, 0x32, 0x72, 0xef, 0xa9, + 0x79, 0x3b, 0xa9, 0x53, 0x1d, 0xf9, 0xd3, 0x02, 0xbc, 0x3a, 0x43, 0x78, + 0xb0, 0x2e, 0x3d, 0x1b, 0x41, 0x20, 0x71, 0x68, 0x62, 0x0a, 0x0a, 0x84, + 0x32, 0x7c, 0x9f, 0x24, 0x7b, 0xeb, 0x6f, 0xec, 0xab, 0xca, 0x38, 0x41, + 0x08, 0xd1, 0xd1, 0xaf, 0xce, 0xa7 +}; +/* k = 1cdf0e8fa606b24c12bfd2f1e6f954f5963e6ce308040d8f664d61777ed640e56e8e2dfc2480cf7bbad6cbe160b6b41abbec0070baabbd5d4ca2ec7d1af59711b54 */ +static const uint8_t nist_186_2_ecdsa_testvector_70_out[] = { +/* R - byte alignment */ + 0x01, 0x30, 0xed, 0xf4, 0x96, 0x4a, 0x6b, 0xd5, 0x33, 0x6a, 0xb5, 0x2c, + 0xe4, 0x0f, 0x32, 0x2c, 0x13, 0x1a, 0x3c, 0x45, 0x63, 0xc9, 0x9e, 0x5e, + 0x72, 0xc4, 0xaf, 0xf8, 0xd8, 0x66, 0xf7, 0x95, 0x51, 0x8a, 0xa1, 0xed, + 0xbc, 0x6c, 0xb7, 0x8d, 0xd8, 0x61, 0xdf, 0xa3, 0x73, 0x0a, 0xc0, 0xc7, + 0xe6, 0xf1, 0x94, 0x68, 0xd7, 0xa6, 0xc6, 0x43, 0xf8, 0xa2, 0xdd, 0x62, + 0x00, 0x9a, 0xec, 0x3c, 0xb4, 0xd3, +/* S - byte alignment */ + 0x01, 0x15, 0x99, 0xbf, 0xf4, 0x26, 0xcf, 0x80, 0xee, 0xd7, 0x9f, 0x36, + 0xa9, 0x9d, 0x0d, 0x68, 0xf0, 0x8e, 0xc7, 0x91, 0xa2, 0xba, 0xb8, 0x5d, + 0x95, 0xd8, 0xbf, 0xc4, 0x8e, 0x16, 0x1a, 0xc8, 0x06, 0xf0, 0x0c, 0xb2, + 0x91, 0x47, 0x0d, 0x4a, 0xdf, 0xd1, 0xbf, 0x9a, 0xd4, 0x04, 0xf3, 0x83, + 0x74, 0xae, 0x34, 0xce, 0x06, 0x4f, 0xb4, 0x4b, 0xed, 0x4d, 0xeb, 0x48, + 0x15, 0xf8, 0x16, 0x61, 0xc3, 0x1a +}; +static const uint8_t nist_186_2_ecdsa_testvector_71_ptx[] = { +/* Msg */ + 0x65, 0xbe, 0x26, 0x41, 0xeb, 0x2d, 0x11, 0x16, 0xe5, 0x10, 0x3a, 0x69, + 0xca, 0x0d, 0x7f, 0x2a, 0x11, 0xd1, 0xa7, 0x9a, 0x52, 0xa6, 0xa2, 0x72, + 0xa8, 0x48, 0x12, 0x61, 0x59, 0xf4, 0x0b, 0xbc, 0xb9, 0xc3, 0x17, 0x72, + 0x4b, 0x36, 0x7e, 0x3e, 0x2a, 0x12, 0xc4, 0x20, 0xa7, 0x6e, 0x72, 0x0d, + 0x34, 0x0a, 0x1a, 0xe6, 0x81, 0xe2, 0x95, 0xa7, 0xe4, 0x03, 0x8f, 0xe1, + 0xfe, 0x9e, 0x46, 0x6a, 0x9c, 0x5b, 0x8e, 0x52, 0xdb, 0xef, 0x19, 0x1a, + 0x90, 0xf1, 0xf5, 0x21, 0xe6, 0xe9, 0x56, 0x5f, 0x49, 0xab, 0x96, 0x55, + 0x83, 0xe3, 0x7a, 0x44, 0x25, 0xf0, 0xb7, 0x9e, 0x29, 0xf6, 0xb4, 0xba, + 0xd5, 0x2e, 0x92, 0xcb, 0xe3, 0x81, 0x6a, 0x13, 0xde, 0x56, 0xd5, 0x54, + 0xcf, 0xa8, 0xb2, 0x88, 0x19, 0x5b, 0x23, 0xd1, 0xa2, 0xd0, 0xd9, 0xb3, + 0x33, 0xb7, 0x92, 0x81, 0x22, 0x24, 0xdf, 0x15 +}; +static const uint8_t nist_186_2_ecdsa_testvector_71_private[] = { +/* d - byte alignment */ + 0x01, 0x8b, 0xfb, 0xd7, 0xbc, 0x20, 0xc4, 0xc4, 0xf0, 0x95, 0x66, 0xda, + 0xbb, 0xa0, 0x18, 0x15, 0x53, 0x6a, 0xfc, 0xb9, 0x6b, 0x55, 0x83, 0x58, + 0xda, 0xaf, 0xf6, 0x11, 0x24, 0x6b, 0x14, 0xd4, 0xc2, 0xe0, 0x17, 0x91, + 0x1d, 0xc4, 0xb0, 0x5c, 0x60, 0xdb, 0xbe, 0x1c, 0x9b, 0x46, 0xb8, 0x18, + 0xac, 0xfd, 0x1d, 0x18, 0x3e, 0x83, 0x65, 0x07, 0x72, 0x99, 0x88, 0x7f, + 0x83, 0x2d, 0x8d, 0x83, 0x71, 0xb2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_71_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xa5, 0xe5, 0xb9, 0x8e, 0xc1, 0x76, 0xf7, 0x51, 0x55, 0xac, 0x94, + 0x18, 0xf7, 0x80, 0x97, 0x96, 0x6d, 0xf7, 0xc0, 0x97, 0x68, 0x02, 0x77, + 0x0f, 0xbc, 0x47, 0xc9, 0xa1, 0x60, 0xb4, 0x57, 0x57, 0xdf, 0xc1, 0xea, + 0x1e, 0xda, 0xc1, 0x64, 0xd8, 0xf3, 0x64, 0x06, 0xc7, 0x33, 0x1c, 0xe0, + 0x99, 0x2a, 0x41, 0x28, 0x82, 0x6b, 0x9d, 0x2a, 0x4c, 0xa6, 0x26, 0x7c, + 0x16, 0x92, 0x43, 0x1c, 0xac, 0x43 +}; +static const uint8_t nist_186_2_ecdsa_testvector_71_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x0d, 0x10, 0x0c, 0x8e, 0xe8, 0x93, 0x60, 0x9e, 0xdc, 0x97, 0x52, + 0xb3, 0xdf, 0x71, 0x47, 0x7d, 0x70, 0xc4, 0x72, 0x77, 0xeb, 0xbb, 0xd5, + 0x60, 0x08, 0x26, 0x29, 0x15, 0x14, 0x92, 0x8c, 0x33, 0xeb, 0x9b, 0x48, + 0x94, 0x52, 0x33, 0x7d, 0x1e, 0x8e, 0xd1, 0xab, 0xc2, 0xb5, 0xf0, 0x6d, + 0x5d, 0x40, 0xf9, 0x13, 0x20, 0xad, 0xcc, 0xa8, 0x92, 0x1f, 0xf5, 0x32, + 0xc0, 0xca, 0xb6, 0x0e, 0x4e, 0xbe +}; +/* k = 11b49c065e990979ea28bcbf13a82f5464de7f8dcf7e06eedf550482926611b0f80eea2bf528b6a7c86dbbff281fa0105bd474f56af86560bfc394fc1b824997ef8 */ +static const uint8_t nist_186_2_ecdsa_testvector_71_out[] = { +/* R - byte alignment */ + 0x01, 0x37, 0xab, 0x30, 0x74, 0x37, 0xbd, 0xd4, 0x7e, 0x5c, 0xc0, 0x4d, + 0x51, 0x4c, 0xa1, 0x33, 0xa6, 0xb9, 0x8c, 0x96, 0xa2, 0x7c, 0x4b, 0xee, + 0x65, 0x81, 0xb7, 0x59, 0x7b, 0x8c, 0xd8, 0xda, 0xc6, 0x9f, 0x06, 0xdb, + 0x84, 0xd9, 0xab, 0x58, 0x35, 0xf4, 0x6e, 0x88, 0x71, 0xa0, 0xc1, 0x25, + 0xa7, 0xf7, 0xb1, 0x59, 0x4c, 0x53, 0x2c, 0x37, 0x81, 0xde, 0xbb, 0xf5, + 0x1e, 0xa2, 0xce, 0x27, 0x32, 0x23, +/* S - byte alignment */ + 0x00, 0xb6, 0x21, 0x3c, 0xec, 0xcd, 0x39, 0x1d, 0x96, 0xe4, 0xf5, 0x46, + 0x86, 0x47, 0x79, 0x8f, 0x7f, 0x4d, 0xbd, 0x65, 0xe8, 0xf5, 0x40, 0xae, + 0x74, 0x6f, 0x72, 0xec, 0xf5, 0x2b, 0x50, 0xd0, 0x62, 0x9c, 0xd5, 0x5f, + 0x1d, 0x59, 0x01, 0x17, 0x5e, 0x0d, 0xdd, 0xf4, 0x66, 0xad, 0x1f, 0x6d, + 0x64, 0xf2, 0xe1, 0x29, 0xd3, 0xbf, 0xd1, 0x09, 0x18, 0x00, 0xcf, 0xf2, + 0x58, 0xa1, 0xb4, 0xfb, 0xc7, 0xbc +}; +static const uint8_t nist_186_2_ecdsa_testvector_72_ptx[] = { +/* Msg */ + 0x30, 0xbb, 0xd8, 0xf6, 0x29, 0x1a, 0x1f, 0x38, 0x61, 0xb9, 0xad, 0x88, + 0xc0, 0xef, 0x50, 0x10, 0x18, 0x57, 0x07, 0x60, 0x08, 0x23, 0x09, 0x63, + 0x21, 0xb3, 0x09, 0x92, 0x48, 0x67, 0xb9, 0x67, 0x5b, 0xb1, 0x8d, 0x15, + 0x18, 0x6e, 0xc1, 0x76, 0x3a, 0x76, 0x9d, 0x45, 0xe4, 0x71, 0xf8, 0x8d, + 0x43, 0xed, 0xfb, 0x61, 0x70, 0xae, 0x27, 0xce, 0x93, 0x45, 0x99, 0x0e, + 0x4e, 0xe5, 0x8d, 0xfe, 0x59, 0x71, 0x22, 0xd3, 0x69, 0xd9, 0x5d, 0x08, + 0x57, 0xa7, 0x6f, 0x9a, 0x7e, 0xd5, 0x3b, 0x78, 0x65, 0xe2, 0x13, 0x35, + 0x9e, 0x25, 0xc2, 0x01, 0xed, 0x60, 0xd0, 0xd7, 0xad, 0x98, 0x01, 0xf8, + 0x70, 0x24, 0x1f, 0x97, 0xe6, 0x05, 0xf9, 0xd6, 0x00, 0x75, 0xac, 0xf1, + 0x54, 0xc2, 0x21, 0xb9, 0xc4, 0x5d, 0xd7, 0x45, 0x5a, 0x2e, 0xe3, 0xe4, + 0x77, 0x2b, 0x35, 0x55, 0x2d, 0x29, 0x1c, 0x3b +}; +static const uint8_t nist_186_2_ecdsa_testvector_72_private[] = { +/* d - byte alignment */ + 0x01, 0x1e, 0xf5, 0x50, 0x1b, 0xe4, 0x84, 0x0f, 0x9a, 0xdc, 0x12, 0x63, + 0xfd, 0x22, 0x58, 0x1d, 0x58, 0xf9, 0x83, 0x22, 0xaf, 0x32, 0xff, 0x3b, + 0x32, 0x3f, 0xce, 0x67, 0x91, 0xe2, 0xc6, 0x18, 0x27, 0xd8, 0x71, 0x43, + 0xec, 0x98, 0x0c, 0xda, 0x54, 0x94, 0xe1, 0xc8, 0xbe, 0xf8, 0x15, 0x00, + 0x6b, 0x22, 0xca, 0x9c, 0xd9, 0x1c, 0x14, 0x77, 0xae, 0x8f, 0xfe, 0x86, + 0x63, 0x2c, 0xd7, 0x0a, 0xc6, 0x8a +}; +static const uint8_t nist_186_2_ecdsa_testvector_72_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x62, 0xb9, 0x10, 0x63, 0x5a, 0x71, 0xce, 0x46, 0x44, 0xa7, 0x06, + 0x2f, 0x4e, 0xb4, 0x27, 0xc8, 0x4b, 0x49, 0xe0, 0x89, 0x1f, 0x0d, 0xd0, + 0xef, 0x56, 0x40, 0x4f, 0x10, 0x2d, 0xc4, 0xe7, 0xff, 0x6f, 0xe9, 0x53, + 0x6f, 0x84, 0x06, 0xcd, 0xe4, 0x17, 0x1b, 0x0a, 0xed, 0x3c, 0xa8, 0x20, + 0xdf, 0x75, 0xfd, 0x45, 0x85, 0x68, 0xec, 0xf7, 0x71, 0x86, 0x06, 0x71, + 0x4a, 0xb3, 0x1d, 0xd8, 0x89, 0x87 +}; +static const uint8_t nist_186_2_ecdsa_testvector_72_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x78, 0xa7, 0x5f, 0x70, 0xb4, 0x7e, 0xa4, 0x2d, 0x43, 0x90, 0xf6, + 0x16, 0x67, 0x6c, 0x10, 0x08, 0x53, 0x0c, 0x1d, 0xb4, 0xf8, 0x49, 0x9c, + 0x21, 0xaf, 0x25, 0xa7, 0x59, 0x9b, 0x10, 0x02, 0x0f, 0x22, 0xe7, 0xbd, + 0x94, 0x05, 0x71, 0xeb, 0x82, 0xeb, 0x98, 0xbd, 0x41, 0x2a, 0xee, 0x49, + 0x07, 0xc0, 0xf1, 0x12, 0xe3, 0x81, 0x7b, 0x40, 0xd5, 0x37, 0x3f, 0x0f, + 0xc4, 0x15, 0x2e, 0xb9, 0xda, 0xd5 +}; +/* k = 043e176a6fd627fbd7e058d8a3dacacd1f232120e312f9fcc825b720ab15e459108622be15cd6026c4b05bea6ed2cbe6817ea6be2427034d5db80703c759ce0190d */ +static const uint8_t nist_186_2_ecdsa_testvector_72_out[] = { +/* R - byte alignment */ + 0x01, 0x23, 0x9e, 0x1d, 0x43, 0xa3, 0xda, 0x16, 0x57, 0x8c, 0x77, 0xdd, + 0xcf, 0xc0, 0x92, 0xed, 0x53, 0x97, 0x4a, 0x97, 0xd7, 0x9b, 0x5e, 0xbf, + 0x58, 0xcc, 0xf8, 0x36, 0x26, 0xbb, 0xeb, 0x4a, 0x8d, 0xc4, 0xe6, 0xcf, + 0xd7, 0xe9, 0x1c, 0xac, 0x19, 0x72, 0x23, 0x24, 0x80, 0x44, 0x7a, 0x82, + 0x3b, 0x7b, 0xdc, 0x6f, 0x5e, 0x5b, 0x0f, 0xf3, 0xf8, 0x03, 0x79, 0x5c, + 0xbc, 0x10, 0x91, 0x12, 0x8e, 0x1b, +/* S - byte alignment */ + 0x00, 0x1f, 0x04, 0x20, 0x25, 0x23, 0xb6, 0xc2, 0x0b, 0xa2, 0x85, 0x39, + 0x12, 0x58, 0x43, 0x91, 0x27, 0x8a, 0xf6, 0x0e, 0x89, 0x22, 0x6c, 0x01, + 0xb7, 0x10, 0x90, 0xee, 0x95, 0x2e, 0x76, 0xfe, 0x38, 0x83, 0x5c, 0x89, + 0x80, 0xd2, 0x40, 0x87, 0xc9, 0xbd, 0x29, 0x3b, 0x9d, 0xee, 0x79, 0xae, + 0xee, 0x6f, 0x80, 0xf0, 0xff, 0xc3, 0x69, 0x23, 0x0e, 0xcf, 0x9d, 0x26, + 0x55, 0x27, 0xbb, 0xd7, 0xb8, 0x46 +}; +static const uint8_t nist_186_2_ecdsa_testvector_73_ptx[] = { +/* Msg */ + 0x64, 0xf1, 0x6a, 0x92, 0x91, 0x99, 0x24, 0x8d, 0x64, 0x1a, 0xf9, 0x4a, + 0xbd, 0x9f, 0xf5, 0xf1, 0x33, 0x38, 0x7c, 0xaa, 0x63, 0xda, 0x3b, 0xba, + 0x88, 0xa8, 0x5e, 0xef, 0x4d, 0x70, 0x03, 0x3f, 0xdf, 0x79, 0xef, 0xac, + 0x45, 0x7c, 0x80, 0x6b, 0xf4, 0xf0, 0xe3, 0x44, 0x9e, 0x8a, 0x87, 0x3c, + 0x4c, 0x05, 0xd2, 0x72, 0xac, 0x1f, 0x12, 0x47, 0xac, 0xe4, 0xb6, 0xc1, + 0x47, 0x2e, 0xbe, 0x32, 0x9f, 0x6d, 0x70, 0x14, 0x4d, 0xa4, 0x4d, 0x38, + 0xf5, 0xb4, 0x43, 0x20, 0x1d, 0xdd, 0x24, 0xa9, 0x3f, 0x82, 0x57, 0xec, + 0x1c, 0x2c, 0xce, 0x67, 0x54, 0xd2, 0x37, 0x58, 0x34, 0x58, 0x77, 0x6a, + 0xcf, 0x55, 0x54, 0x93, 0x50, 0x19, 0x71, 0x3d, 0x8e, 0xef, 0x80, 0xa4, + 0xe1, 0x9f, 0xb3, 0x7f, 0x35, 0x37, 0x73, 0xe2, 0x5c, 0x0b, 0x55, 0x63, + 0xa9, 0xfb, 0x4a, 0x7c, 0xba, 0xf4, 0x16, 0x30 +}; +static const uint8_t nist_186_2_ecdsa_testvector_73_private[] = { +/* d - byte alignment */ + 0x01, 0x97, 0xd5, 0xa8, 0x11, 0x8e, 0xc8, 0x70, 0xe7, 0x37, 0x3d, 0x48, + 0x44, 0x36, 0xd4, 0x9f, 0xa4, 0xc3, 0xf9, 0xff, 0xe8, 0xf6, 0x4a, 0x4c, + 0xd8, 0x08, 0x74, 0x82, 0x94, 0x8d, 0x96, 0x1d, 0xd3, 0x0e, 0x85, 0x00, + 0xe1, 0xfe, 0x66, 0x3b, 0x49, 0x3a, 0xa5, 0x3b, 0x80, 0xa2, 0x1f, 0x57, + 0xc1, 0x44, 0xb9, 0x7f, 0x9d, 0xfa, 0xc7, 0x24, 0xc2, 0xb9, 0xd7, 0xed, + 0xbc, 0x82, 0x41, 0x73, 0x63, 0x1f +}; +static const uint8_t nist_186_2_ecdsa_testvector_73_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xc9, 0x29, 0x07, 0x41, 0xf8, 0xd8, 0x3e, 0x60, 0x50, 0x5f, 0x90, + 0xd1, 0x11, 0x6b, 0xb5, 0x97, 0x1b, 0x82, 0x27, 0x37, 0x3c, 0x2a, 0xde, + 0x7a, 0xc9, 0xf6, 0x46, 0xe4, 0xb7, 0x4f, 0xe5, 0xde, 0xfa, 0xd0, 0xb7, + 0xa6, 0x15, 0xcd, 0xac, 0x9d, 0x04, 0x15, 0x34, 0x01, 0xfb, 0x54, 0x26, + 0xac, 0xe5, 0x6e, 0x28, 0xac, 0x8f, 0x9d, 0x81, 0xf1, 0x5d, 0xa8, 0x60, + 0xc0, 0x82, 0x21, 0xa6, 0xd5, 0xde +}; +static const uint8_t nist_186_2_ecdsa_testvector_73_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x02, 0x8d, 0xb7, 0xea, 0x9a, 0x29, 0xc7, 0x31, 0x42, 0x48, 0xb9, + 0x3f, 0x21, 0x4b, 0x7c, 0x65, 0xff, 0x05, 0x54, 0xc0, 0xe8, 0xe5, 0x08, + 0x16, 0xd0, 0x03, 0x2c, 0x9a, 0xfe, 0x7d, 0xe6, 0x1f, 0x1f, 0x7e, 0x3c, + 0xa7, 0xb3, 0x4f, 0xe4, 0x4a, 0xa9, 0x9a, 0x92, 0xf0, 0xcc, 0xbc, 0xa8, + 0xce, 0xd9, 0xb7, 0xca, 0xba, 0x4d, 0xb2, 0xb2, 0x91, 0xcf, 0xaf, 0x39, + 0x79, 0x66, 0x7c, 0xf6, 0x14, 0x74 +}; +/* k = 0c097b10e7533825ba682ef6a445ded274a1d0524eb790db11deb61f7f481d78b960e90d5fdb4a9771fcf99a3746cfada273a6548525d66d7774b92146adfda5214 */ +static const uint8_t nist_186_2_ecdsa_testvector_73_out[] = { +/* R - byte alignment */ + 0x01, 0x48, 0x83, 0x2a, 0x67, 0x00, 0x27, 0xa7, 0x09, 0x82, 0x2e, 0x3b, + 0x9f, 0x25, 0x1d, 0x57, 0xc1, 0xde, 0xce, 0xd7, 0x46, 0x4e, 0xf4, 0xbd, + 0x8d, 0x16, 0x8f, 0x80, 0xb3, 0x60, 0x58, 0x54, 0x53, 0xc8, 0x56, 0x88, + 0xaa, 0x09, 0x6d, 0x40, 0x90, 0xcf, 0x3d, 0x70, 0x89, 0xe1, 0x84, 0xdb, + 0x0c, 0xff, 0x97, 0x39, 0x32, 0x66, 0x50, 0x8d, 0x1e, 0xc8, 0xbe, 0xa4, + 0xc4, 0x87, 0x97, 0x8a, 0x8c, 0x46, +/* S - byte alignment */ + 0x01, 0xba, 0x38, 0x83, 0xed, 0x44, 0x1a, 0x49, 0xd3, 0x9c, 0x66, 0xda, + 0xf7, 0x1a, 0x29, 0x05, 0x40, 0xcf, 0x50, 0x86, 0xc0, 0xa4, 0xbe, 0x76, + 0xf3, 0xfb, 0xe3, 0xd1, 0xf0, 0xc9, 0xfa, 0xbc, 0xab, 0xc3, 0x4f, 0xb8, + 0x18, 0x01, 0x54, 0xbf, 0x79, 0xd6, 0x81, 0xda, 0x2d, 0x0a, 0xd3, 0x15, + 0xdf, 0x51, 0x9d, 0x13, 0x05, 0xbf, 0x63, 0xbb, 0x1a, 0xce, 0x7d, 0xb9, + 0xec, 0xdf, 0x36, 0x9c, 0x03, 0xda +}; +static const uint8_t nist_186_2_ecdsa_testvector_74_ptx[] = { +/* Msg */ + 0xac, 0xc3, 0x7a, 0x55, 0xf3, 0xf7, 0x01, 0x92, 0x02, 0xbc, 0x1a, 0x4c, + 0x05, 0x5f, 0x70, 0xd1, 0x24, 0x37, 0x8c, 0xd4, 0x57, 0x2a, 0x4a, 0x10, + 0x7c, 0x72, 0x8e, 0x2e, 0xa7, 0xa1, 0x33, 0xe9, 0xb9, 0xe3, 0x44, 0x70, + 0x34, 0x84, 0x6f, 0x0b, 0x4d, 0xb2, 0xb6, 0x02, 0x43, 0x83, 0x68, 0xbb, + 0xf0, 0x3a, 0x50, 0x22, 0x9e, 0xc6, 0x2c, 0x4d, 0x1b, 0x8b, 0x61, 0x61, + 0x10, 0x65, 0xec, 0xaf, 0x8e, 0xea, 0x9c, 0x23, 0xea, 0xf0, 0x7e, 0xdf, + 0xcb, 0x50, 0x99, 0x23, 0x81, 0xe9, 0xdc, 0x70, 0x98, 0xe7, 0x55, 0xed, + 0xad, 0x45, 0xa4, 0x09, 0x81, 0x90, 0xae, 0x62, 0x4c, 0xee, 0x96, 0xe6, + 0x54, 0x60, 0xe9, 0x37, 0xbd, 0x44, 0x18, 0x54, 0xa3, 0x1e, 0x2c, 0x77, + 0x66, 0x97, 0xb5, 0x39, 0x45, 0xc6, 0x03, 0xfc, 0x2f, 0xaf, 0x99, 0x8a, + 0xd5, 0x09, 0xdf, 0xfa, 0x04, 0x45, 0x17, 0xd4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_74_private[] = { +/* d - byte alignment */ + 0x00, 0x17, 0xdd, 0xec, 0xce, 0x87, 0x0a, 0xaa, 0x4a, 0x82, 0xbc, 0x3a, + 0x0a, 0xe8, 0x14, 0x6b, 0xdb, 0x33, 0x02, 0x54, 0x4e, 0x5f, 0x13, 0x66, + 0x85, 0x16, 0xf8, 0xb4, 0x03, 0x85, 0x6f, 0xb7, 0x47, 0x2f, 0x9c, 0xb4, + 0x3c, 0x4c, 0x8a, 0x64, 0x74, 0x23, 0x32, 0x0f, 0xb9, 0xa1, 0xcd, 0xcf, + 0x13, 0xb7, 0xc7, 0xc5, 0x84, 0x39, 0xa9, 0xdd, 0x67, 0x42, 0x95, 0x64, + 0x63, 0x78, 0x4a, 0xd3, 0xdc, 0xf0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_74_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xb3, 0x64, 0xfb, 0x81, 0x93, 0xdf, 0x3e, 0xaf, 0xb3, 0x92, 0x8b, + 0x0f, 0xb4, 0xcb, 0x85, 0xcb, 0x3b, 0xc7, 0x0b, 0x41, 0x28, 0x53, 0xae, + 0x1c, 0x8d, 0x72, 0x59, 0x46, 0xc5, 0xb1, 0x3f, 0x0a, 0x4f, 0x43, 0x95, + 0x42, 0x16, 0x28, 0xdd, 0xdf, 0x16, 0x2f, 0xc6, 0xfd, 0x63, 0x76, 0x16, + 0x1b, 0xf2, 0x7b, 0x15, 0x71, 0xcd, 0x18, 0x61, 0xe5, 0x24, 0xa8, 0x66, + 0xc2, 0x3b, 0x07, 0x5a, 0x03, 0x93 +}; +static const uint8_t nist_186_2_ecdsa_testvector_74_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x4c, 0x44, 0x4f, 0xc0, 0x06, 0x9f, 0xa9, 0x0f, 0x43, 0x64, 0x35, + 0x00, 0xf3, 0x9b, 0xfd, 0xf0, 0x0c, 0x17, 0x4c, 0xda, 0xa1, 0x0b, 0xac, + 0x56, 0x5c, 0xa2, 0xde, 0x67, 0x98, 0xc1, 0x06, 0xbf, 0x43, 0x41, 0x15, + 0x81, 0xbf, 0x24, 0xcd, 0xb8, 0xa1, 0x5b, 0xfd, 0x85, 0x32, 0xa1, 0xa8, + 0xfd, 0x3b, 0x46, 0x5c, 0x20, 0x1a, 0xee, 0xe9, 0x0f, 0x12, 0xf5, 0x8d, + 0xfe, 0x70, 0x53, 0x98, 0x40, 0x55 +}; +/* k = 0bf348f48bccfa65a24118d70f6ae96bd604287cb83cd644a94d652dca636bfef2a5d48768373dd97b64f916f0328166fc8b3636e1a7776a2b9e5dcf4c90536f45e */ +static const uint8_t nist_186_2_ecdsa_testvector_74_out[] = { +/* R - byte alignment */ + 0x01, 0x86, 0xa8, 0x2f, 0x8f, 0xcb, 0xf5, 0xcc, 0x8a, 0xbd, 0x4e, 0x61, + 0x77, 0x71, 0xc3, 0x74, 0x12, 0xc4, 0x13, 0xbd, 0x51, 0xb9, 0xf2, 0xb9, + 0x7b, 0x76, 0xe5, 0x6c, 0x99, 0xa4, 0x1f, 0x1c, 0xa2, 0x76, 0xc3, 0xfc, + 0xd8, 0xbb, 0xea, 0xe0, 0xd7, 0xcc, 0xf1, 0x82, 0x86, 0x81, 0x02, 0xce, + 0xcb, 0x8a, 0xd1, 0x09, 0xd7, 0x7e, 0xc7, 0x77, 0xf5, 0x0c, 0xc4, 0xa1, + 0x21, 0x52, 0xa3, 0xe3, 0x0b, 0xfd, +/* S - byte alignment */ + 0x01, 0xa2, 0x97, 0xd1, 0xf7, 0x48, 0xd8, 0xbd, 0x8e, 0x84, 0xb9, 0x40, + 0x2b, 0xa4, 0xc4, 0x87, 0xa1, 0xd8, 0x37, 0x42, 0x83, 0x45, 0xef, 0x7f, + 0x82, 0x76, 0x39, 0x47, 0x65, 0xc5, 0x06, 0xee, 0x6e, 0x2c, 0x52, 0x17, + 0x21, 0x45, 0x4e, 0x2e, 0x71, 0x80, 0x1d, 0x73, 0xd2, 0x3e, 0x5a, 0x56, + 0x6d, 0xfb, 0x79, 0x34, 0x90, 0xdb, 0x32, 0x13, 0xad, 0x50, 0x95, 0x91, + 0x07, 0x47, 0x04, 0xfb, 0x27, 0xe4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_75_ptx[] = { +/* Msg */ + 0x4b, 0xc8, 0x83, 0xa6, 0x72, 0xe4, 0xbf, 0x88, 0x55, 0xe3, 0x06, 0x25, + 0x61, 0x52, 0x43, 0x13, 0xe9, 0x05, 0x89, 0x66, 0xbe, 0x5b, 0x4a, 0x1a, + 0x00, 0xc2, 0xcb, 0xb1, 0x33, 0x7e, 0xd4, 0x1c, 0x95, 0xa7, 0xac, 0xdf, + 0xaf, 0x71, 0x45, 0x71, 0x2b, 0xb1, 0xb3, 0xe1, 0xe5, 0x9c, 0xe2, 0xbf, + 0x45, 0xd1, 0x89, 0x3a, 0xcb, 0x9a, 0x5a, 0x86, 0xeb, 0x6e, 0x7c, 0x81, + 0x1c, 0xbb, 0x3a, 0x95, 0x2c, 0xe3, 0xfd, 0xe0, 0xd6, 0x84, 0x77, 0x92, + 0x96, 0xfd, 0x22, 0x97, 0xbc, 0x2e, 0xe9, 0x77, 0xc0, 0x7f, 0x24, 0x7a, + 0xd5, 0x23, 0xca, 0x0f, 0xc0, 0x9e, 0xe2, 0x6e, 0xeb, 0x84, 0x3b, 0x7d, + 0xb5, 0x84, 0x5d, 0xf0, 0x0d, 0xa6, 0xbf, 0xb5, 0x3f, 0xd1, 0x3b, 0x8f, + 0x0d, 0x90, 0xbe, 0x01, 0x02, 0x15, 0x44, 0x6d, 0x03, 0x7f, 0x04, 0x7d, + 0x27, 0x58, 0xe7, 0xc2, 0xc9, 0x62, 0x3f, 0x9b +}; +static const uint8_t nist_186_2_ecdsa_testvector_75_private[] = { +/* d - byte alignment */ + 0x01, 0xfe, 0x1b, 0x13, 0x76, 0xf8, 0x0b, 0x0c, 0x0f, 0xf2, 0x7c, 0x1c, + 0xe2, 0x4d, 0xed, 0x67, 0x6b, 0x0e, 0xb0, 0xd5, 0x78, 0x22, 0x8f, 0xd5, + 0x1c, 0x65, 0x00, 0x64, 0x1e, 0x2e, 0x0e, 0x54, 0x1d, 0xe3, 0x32, 0xcb, + 0xb8, 0x1b, 0xe6, 0xa5, 0xd6, 0xf1, 0x9a, 0x7c, 0xd6, 0x5a, 0x4b, 0x59, + 0xa6, 0x23, 0x83, 0x58, 0x15, 0xf7, 0x4c, 0x42, 0x2d, 0x23, 0x7f, 0xd7, + 0xf0, 0x39, 0x59, 0x8e, 0x6b, 0xb9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_75_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xab, 0x5a, 0x78, 0x7d, 0xe5, 0xf1, 0xc1, 0xc5, 0xb4, 0x22, 0x8c, + 0x0b, 0x4a, 0x30, 0x40, 0xe4, 0x8a, 0xd3, 0x40, 0xdb, 0xb7, 0xda, 0xa4, + 0x5a, 0xd1, 0xab, 0x0a, 0x04, 0x8e, 0xbe, 0xc2, 0x4f, 0xb4, 0xf3, 0xfe, + 0xee, 0xb2, 0x23, 0xb3, 0x6a, 0xdf, 0xe4, 0xe7, 0xd1, 0xc5, 0xaa, 0x42, + 0x86, 0x41, 0x74, 0xea, 0x02, 0xea, 0x81, 0x51, 0x59, 0xea, 0xa1, 0x56, + 0x8d, 0xae, 0x67, 0xe8, 0x28, 0xb3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_75_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x2e, 0x1e, 0x35, 0xbf, 0x55, 0xfd, 0x6e, 0xd0, 0x7a, 0x6d, 0x62, + 0xcd, 0x30, 0xeb, 0xfc, 0x3f, 0x6d, 0x60, 0xd4, 0x23, 0x11, 0xba, 0x17, + 0x6b, 0x99, 0xc3, 0x68, 0x71, 0xc0, 0x33, 0xa2, 0xd9, 0xe5, 0xac, 0x36, + 0x0c, 0x67, 0xf1, 0xe7, 0xaa, 0xa2, 0x1a, 0x8a, 0x63, 0xf6, 0x52, 0xda, + 0xac, 0x01, 0x3f, 0x18, 0x9e, 0xf6, 0x16, 0x6a, 0x64, 0x27, 0x60, 0x15, + 0x83, 0xec, 0x9e, 0x19, 0x18, 0x57 +}; +/* k = 0dafe91e7502aab9143d6bb7d127cfefa374030c10fa0f69b9bc7a071f38ff1b28518dc16852080e04c7da89792587228e7eaf03a00953cec725999216a7dc8ac88 */ +static const uint8_t nist_186_2_ecdsa_testvector_75_out[] = { +/* R - byte alignment */ + 0x01, 0x43, 0x7a, 0x67, 0x47, 0x42, 0x82, 0xfa, 0xd0, 0x15, 0x4b, 0xfc, + 0xa2, 0x99, 0x53, 0x80, 0xee, 0x44, 0xef, 0x12, 0x49, 0x2c, 0x8c, 0x78, + 0x37, 0x4b, 0x16, 0x9d, 0x2a, 0x7d, 0x45, 0xe1, 0x6b, 0x5b, 0x71, 0xf1, + 0x84, 0x3a, 0x28, 0x73, 0x00, 0xbe, 0x7b, 0x6c, 0xdd, 0xa3, 0xb2, 0xfa, + 0x8b, 0xa7, 0xd8, 0x9d, 0x84, 0x77, 0xb7, 0x3a, 0x0a, 0xa8, 0x0b, 0x0c, + 0xb0, 0xcf, 0x5b, 0x33, 0xb6, 0x93, +/* S - byte alignment */ + 0x01, 0x83, 0x3b, 0xf3, 0xe4, 0x58, 0xed, 0x65, 0xfe, 0xf4, 0x0e, 0x59, + 0xfa, 0xb6, 0xfa, 0x16, 0x30, 0x2d, 0xaf, 0xf0, 0x58, 0x8b, 0xe4, 0x2a, + 0x6b, 0xe8, 0xa3, 0xa0, 0x43, 0x01, 0xe4, 0xb4, 0xd9, 0x00, 0x6b, 0x2a, + 0xc5, 0x68, 0xc9, 0x9c, 0x7f, 0x52, 0xb3, 0x57, 0x0c, 0x61, 0x1a, 0xb9, + 0xd8, 0xb6, 0xf8, 0x3c, 0xa8, 0x32, 0xf5, 0x15, 0x8a, 0xa9, 0x51, 0xd3, + 0x96, 0xa7, 0xc7, 0x97, 0xed, 0xe3 +}; +/* [K-163] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_76_ptx[] = { +/* Msg */ + 0xa2, 0xc1, 0xa0, 0x3f, 0xdd, 0x00, 0x52, 0x1b, 0xb0, 0x8f, 0xc8, 0x8d, + 0x20, 0x34, 0x43, 0x21, 0x97, 0x7a, 0xaf, 0x63, 0x7e, 0xf9, 0xd5, 0x47, + 0x0d, 0xd7, 0xd2, 0xc8, 0x62, 0x8f, 0xc8, 0xd0, 0xd1, 0xf1, 0xd3, 0x58, + 0x7c, 0x6b, 0x3f, 0xd0, 0x23, 0x86, 0xf8, 0xc1, 0x3d, 0xb3, 0x41, 0xb1, + 0x47, 0x48, 0xa9, 0x47, 0x5c, 0xc6, 0x3b, 0xaf, 0x06, 0x5d, 0xf6, 0x40, + 0x54, 0xb2, 0x7d, 0x5c, 0x2c, 0xdf, 0x0f, 0x98, 0xe3, 0xbb, 0xb8, 0x1d, + 0x0b, 0x5d, 0xc9, 0x4f, 0x8c, 0xdb, 0x87, 0xac, 0xf7, 0x57, 0x20, 0xf6, + 0x16, 0x3d, 0xe3, 0x94, 0xc8, 0xc6, 0xaf, 0x36, 0x0b, 0xc1, 0xac, 0xb8, + 0x5b, 0x92, 0x3a, 0x49, 0x3b, 0x7b, 0x27, 0xcc, 0x11, 0x1a, 0x25, 0x7e, + 0x36, 0x33, 0x7b, 0xd9, 0x4e, 0xb0, 0xfa, 0xb9, 0xd5, 0xe6, 0x33, 0xbe, + 0xfb, 0x1a, 0xe7, 0xf1, 0xb2, 0x44, 0xbf, 0xaa +}; +static const uint8_t nist_186_2_ecdsa_testvector_76_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0x1f, 0x26, 0x26, 0xd9, 0x0d, 0x26, 0xcb, 0x4c, + 0x03, 0x79, 0x04, 0x3b, 0x26, 0xe6, 0x41, 0x07, 0xfc +}; +static const uint8_t nist_186_2_ecdsa_testvector_76_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x38, 0x9f, 0xa5, 0xad, 0x7f, 0x83, 0x04, 0x32, 0x5a, 0x8c, 0x06, + 0x0e, 0xf7, 0xdc, 0xb8, 0x30, 0x42, 0xc0, 0x45, 0xbc +}; +static const uint8_t nist_186_2_ecdsa_testvector_76_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xee, 0xfa, 0x09, 0x4a, 0x50, 0x54, 0xda, 0x19, 0x69, 0x43, 0xcc, + 0x80, 0x50, 0x9d, 0xcb, 0x9f, 0x59, 0xe5, 0xbc, 0x2e +}; +/* k = 0000000c3a4ff97286126dab1e5089395fcc47ebb */ +static const uint8_t nist_186_2_ecdsa_testvector_76_out[] = { +/* R - byte alignment */ + 0x00, 0xdb, 0xe6, 0xc3, 0xa1, 0xdc, 0x85, 0x1e, 0x7f, 0x23, 0x38, 0xb5, + 0xc2, 0x6c, 0x62, 0xb4, 0xb3, 0x7b, 0xf8, 0x03, 0x5c, +/* S - byte alignment */ + 0x01, 0xc7, 0x64, 0x58, 0x13, 0x5b, 0x1f, 0xf9, 0xfb, 0xd2, 0x30, 0x09, + 0xb8, 0x41, 0x4a, 0x47, 0x99, 0x61, 0x26, 0xb5, 0x6a +}; +static const uint8_t nist_186_2_ecdsa_testvector_77_ptx[] = { +/* Msg */ + 0x67, 0x04, 0x80, 0x80, 0xda, 0xae, 0xb7, 0x7d, 0x3a, 0xc3, 0x1b, 0xab, + 0xdf, 0x8b, 0xe2, 0x3d, 0xbe, 0x75, 0xce, 0xb4, 0xdf, 0xb9, 0x4a, 0xa8, + 0x11, 0x3d, 0xb5, 0xc5, 0xdc, 0xb6, 0xfe, 0x14, 0xb7, 0x0f, 0x71, 0x7b, + 0x7b, 0x0e, 0xd0, 0x88, 0x18, 0x35, 0xa6, 0x6a, 0x86, 0xe6, 0xd8, 0x40, + 0xff, 0xcb, 0x7d, 0x97, 0x6c, 0x75, 0xef, 0x2d, 0x1d, 0x43, 0x22, 0xfb, + 0xbc, 0x86, 0x35, 0x73, 0x84, 0xe2, 0x47, 0x07, 0xae, 0xf8, 0x8c, 0xea, + 0x2c, 0x41, 0xa0, 0x1a, 0x9a, 0x3d, 0x1b, 0x9e, 0x72, 0xce, 0x65, 0x0c, + 0x7f, 0xde, 0xcc, 0x4f, 0x94, 0x48, 0xd3, 0xa7, 0x7d, 0xf6, 0xcd, 0xf1, + 0x36, 0x47, 0xab, 0x29, 0x5b, 0xb3, 0x13, 0x2d, 0xe0, 0xb1, 0xb2, 0xc4, + 0x02, 0xd8, 0xd2, 0xde, 0x7d, 0x45, 0x2f, 0x1e, 0x00, 0x3e, 0x06, 0x95, + 0xde, 0x14, 0x70, 0xd1, 0x06, 0x4e, 0xee, 0x16 +}; +static const uint8_t nist_186_2_ecdsa_testvector_77_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x6a, 0x38, 0x03, 0x30, 0x1d, 0xae, 0xe9, 0xaf, + 0x09, 0xbb, 0x5b, 0x6c, 0x99, 0x1a, 0x4f, 0x49, 0xa4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_77_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0xb5, 0x00, 0xf5, 0x55, 0xe8, 0x57, 0xda, 0x8c, 0x29, 0x97, 0x80, + 0x13, 0x0c, 0x5c, 0x3f, 0x48, 0xf0, 0x2e, 0xe3, 0x22 +}; +static const uint8_t nist_186_2_ecdsa_testvector_77_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0xc1, 0xc0, 0xae, 0x25, 0xb4, 0x7f, 0x06, 0xcc, 0x46, 0xfb, 0x86, + 0xb1, 0x2d, 0x2d, 0x8c, 0x0b, 0xa6, 0xa4, 0xbf, 0x07 +}; +/* k = 0000002f39fbf77f3e0dc046116de692b6cf91b16 */ +static const uint8_t nist_186_2_ecdsa_testvector_77_out[] = { +/* R - byte alignment */ + 0x03, 0xd3, 0xee, 0xda, 0x42, 0xf6, 0x5d, 0x72, 0x7f, 0x4a, 0x56, 0x4f, + 0x14, 0x15, 0x65, 0x43, 0x56, 0xc6, 0xc5, 0x7a, 0x6c, +/* S - byte alignment */ + 0x03, 0x5e, 0x4d, 0x43, 0xc5, 0xf0, 0x8b, 0xad, 0xdf, 0x13, 0x84, 0x49, + 0xdb, 0x1a, 0xd0, 0xb7, 0x87, 0x25, 0x52, 0xb7, 0xcd +}; +static const uint8_t nist_186_2_ecdsa_testvector_78_ptx[] = { +/* Msg */ + 0x77, 0xe0, 0x07, 0xdc, 0x2a, 0xcd, 0x72, 0x48, 0x25, 0x61, 0x65, 0xa4, + 0xb3, 0x0e, 0x98, 0x98, 0x6f, 0x51, 0xa8, 0x1e, 0xfd, 0x92, 0x6b, 0x85, + 0xf7, 0x4c, 0x81, 0xbc, 0x2a, 0x6d, 0x2b, 0xcd, 0x03, 0x00, 0x60, 0xa8, + 0x44, 0x09, 0x1e, 0x22, 0xfb, 0xb0, 0xff, 0x3d, 0xb5, 0xa2, 0x0c, 0xaa, + 0xef, 0xb5, 0xd5, 0x8c, 0xcd, 0xcb, 0xc2, 0x7f, 0x0f, 0xf8, 0xa4, 0xd9, + 0x40, 0xe7, 0x8f, 0x30, 0x30, 0x79, 0xec, 0x1c, 0xa5, 0xb0, 0xca, 0x3d, + 0x4e, 0xcc, 0x75, 0x80, 0xf8, 0xb3, 0x4a, 0x9f, 0x04, 0x96, 0xc9, 0xe7, + 0x19, 0xd2, 0xec, 0x3e, 0x16, 0x14, 0xb7, 0x64, 0x4b, 0xc1, 0x11, 0x79, + 0xe8, 0x95, 0xd2, 0xc0, 0xb5, 0x8a, 0x1d, 0xa2, 0x04, 0xfb, 0xf0, 0xf6, + 0xe5, 0x09, 0xf9, 0x7f, 0x98, 0x3e, 0xac, 0xb6, 0x48, 0x70, 0x92, 0xca, + 0xf6, 0xe8, 0xe4, 0xe6, 0xb3, 0xc4, 0x58, 0xb2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_78_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x02, 0xe2, 0x86, 0x76, 0x51, 0x4b, 0xd9, 0x3f, 0xea, + 0x11, 0xb6, 0x2d, 0xb0, 0xf6, 0xe3, 0x24, 0xb1, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_78_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0xf9, 0xc9, 0x0b, 0x71, 0xf6, 0xa1, 0xde, 0x20, 0xa2, 0x71, 0x6f, + 0x38, 0xef, 0x1b, 0x5f, 0x98, 0xc7, 0x57, 0xbd, 0x42 +}; +static const uint8_t nist_186_2_ecdsa_testvector_78_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0xff, 0x0a, 0x5d, 0x26, 0x6d, 0x44, 0x7e, 0xf6, 0x2d, 0x43, 0xfb, + 0xca, 0x6c, 0x34, 0xc0, 0x8c, 0x1c, 0xe3, 0x5a, 0x40 +}; +/* k = 00000001233ae699883e74e7f4dfb5279ff22280a */ +static const uint8_t nist_186_2_ecdsa_testvector_78_out[] = { +/* R - byte alignment */ + 0x03, 0x9d, 0xe3, 0xcd, 0x2c, 0xf0, 0x41, 0x45, 0xe5, 0x22, 0xb8, 0xfb, + 0xa3, 0xf2, 0x3e, 0x92, 0x18, 0x22, 0x6e, 0x08, 0x60, +/* S - byte alignment */ + 0x02, 0xaf, 0x62, 0xbf, 0xb3, 0xcf, 0xa2, 0x02, 0xe2, 0x34, 0x26, 0x06, + 0xee, 0x5b, 0xb0, 0x93, 0x4c, 0x3b, 0x03, 0x75, 0xb6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_79_ptx[] = { +/* Msg */ + 0xfb, 0xac, 0xfc, 0xce, 0x46, 0x88, 0x74, 0x84, 0x06, 0xdd, 0xf5, 0xc3, + 0x49, 0x50, 0x21, 0xee, 0xf8, 0xfb, 0x39, 0x98, 0x65, 0xb6, 0x49, 0xeb, + 0x23, 0x95, 0xa0, 0x4a, 0x1a, 0xb2, 0x83, 0x35, 0xda, 0x2c, 0x23, 0x6d, + 0x30, 0x6f, 0xcc, 0x59, 0xf7, 0xb6, 0x5e, 0xa9, 0x31, 0xcf, 0x01, 0x39, + 0x57, 0x1e, 0x15, 0x38, 0xed, 0xe5, 0x68, 0x89, 0x58, 0xc3, 0xac, 0x69, + 0xf4, 0x7a, 0x28, 0x53, 0x62, 0xf5, 0xad, 0x20, 0x1f, 0x89, 0xcc, 0x73, + 0x5b, 0x7b, 0x46, 0x54, 0x08, 0xc2, 0xc4, 0x1b, 0x31, 0x0f, 0xc8, 0x90, + 0x8d, 0x0b, 0xe4, 0x50, 0x54, 0xdf, 0x2a, 0x73, 0x51, 0xfa, 0xe3, 0x6b, + 0x39, 0x0e, 0x84, 0x2f, 0x3b, 0x5c, 0xdd, 0x9a, 0xd8, 0x32, 0x94, 0x0d, + 0xf5, 0xb2, 0xd2, 0x5c, 0x2e, 0xd4, 0x3c, 0xe8, 0x6e, 0xaf, 0x25, 0x08, + 0xbc, 0xf4, 0x01, 0xae, 0x58, 0xbb, 0x1d, 0x47 +}; +static const uint8_t nist_186_2_ecdsa_testvector_79_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0x61, 0xdd, 0x08, 0x8e, 0x3a, 0x6d, 0x3c, 0x91, + 0x06, 0x86, 0xc8, 0xdc, 0xe5, 0x7e, 0x5d, 0x4d, 0x8e +}; +static const uint8_t nist_186_2_ecdsa_testvector_79_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x64, 0xf9, 0x05, 0xc1, 0xda, 0x9d, 0x7e, 0x9c, 0x32, 0xd8, 0x18, + 0x90, 0xae, 0x6f, 0x30, 0xdc, 0xc7, 0x83, 0x9d, 0x32 +}; +static const uint8_t nist_186_2_ecdsa_testvector_79_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x6f, 0x1f, 0xae, 0xdb, 0x6d, 0x90, 0x32, 0x01, 0x6d, 0x3b, 0x68, + 0x1e, 0x7c, 0xf6, 0x9c, 0x29, 0xd2, 0x9e, 0xb2, 0x7b +}; +/* k = 00000022f723e9f5da56d3d0837d5dca2f937395f */ +static const uint8_t nist_186_2_ecdsa_testvector_79_out[] = { +/* R - byte alignment */ + 0x03, 0x74, 0xcd, 0xc8, 0x57, 0x10, 0x83, 0xfe, 0xcf, 0xbd, 0x4e, 0x25, + 0xe1, 0xcd, 0x69, 0xec, 0xc6, 0x6b, 0x71, 0x5f, 0x2d, +/* S - byte alignment */ + 0x03, 0x13, 0xb1, 0x09, 0x49, 0x22, 0x29, 0x29, 0xb2, 0xf2, 0x0b, 0x15, + 0xd4, 0x46, 0xc2, 0x7d, 0x6d, 0xca, 0xe3, 0xf0, 0x86 +}; +static const uint8_t nist_186_2_ecdsa_testvector_80_ptx[] = { +/* Msg */ + 0x22, 0x0f, 0x5c, 0xeb, 0xca, 0xbe, 0x9f, 0x75, 0x74, 0x20, 0x8f, 0x9c, + 0x59, 0xa0, 0xc0, 0x35, 0x4a, 0xdc, 0x29, 0xec, 0x94, 0xf8, 0x28, 0x35, + 0x26, 0x37, 0xc6, 0x85, 0xf6, 0xcc, 0x3d, 0xc1, 0xa0, 0xed, 0xb7, 0xf7, + 0x50, 0x2a, 0x59, 0x4c, 0xe3, 0xfd, 0x80, 0x35, 0x49, 0xa2, 0x4a, 0xea, + 0x2e, 0x28, 0x59, 0x18, 0xd9, 0xc9, 0xd3, 0xd6, 0x54, 0x77, 0xad, 0xdb, + 0xcd, 0xb7, 0x2a, 0xee, 0x3c, 0xb2, 0x9e, 0x9d, 0x46, 0x89, 0x78, 0x32, + 0x61, 0xea, 0x7f, 0xe3, 0x3a, 0xe1, 0x5c, 0x49, 0x54, 0xf0, 0x59, 0x14, + 0xf1, 0x61, 0x68, 0xfc, 0x35, 0xdb, 0x67, 0xfb, 0x89, 0x34, 0xa2, 0xb9, + 0x3e, 0x86, 0x9a, 0x48, 0x72, 0x85, 0x05, 0x11, 0x38, 0x0f, 0x15, 0x0e, + 0xf3, 0x05, 0xfd, 0x3a, 0x03, 0x5a, 0xb2, 0x46, 0xa4, 0x69, 0xee, 0x8e, + 0x12, 0x8c, 0x7b, 0x4b, 0xf2, 0xea, 0xae, 0x0a +}; +static const uint8_t nist_186_2_ecdsa_testvector_80_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0xea, 0x9b, 0xc0, 0x41, 0x22, 0x9b, 0x8b, 0x6d, + 0x2d, 0x69, 0x20, 0x3a, 0x88, 0x36, 0x5f, 0xfd, 0x5e +}; +static const uint8_t nist_186_2_ecdsa_testvector_80_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0x17, 0x11, 0xcd, 0xff, 0x26, 0x44, 0x2d, 0xd6, 0x77, 0x07, 0xf4, + 0x45, 0xaf, 0x77, 0xd7, 0x0e, 0x01, 0x1b, 0xcd, 0x51 +}; +static const uint8_t nist_186_2_ecdsa_testvector_80_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x9c, 0x58, 0x5b, 0x72, 0xbc, 0x26, 0xef, 0xee, 0x95, 0x29, 0xf3, + 0x98, 0xf0, 0x66, 0xe6, 0x74, 0x1c, 0xa3, 0xec, 0x35 +}; +/* k = 00000016a031feed289363088b92e9d87f98b184f */ +static const uint8_t nist_186_2_ecdsa_testvector_80_out[] = { +/* R - byte alignment */ + 0x00, 0xb7, 0x2f, 0xf8, 0xa8, 0xb4, 0x05, 0xd4, 0xfc, 0x33, 0xa5, 0x0f, + 0x21, 0x07, 0x83, 0xe2, 0x5b, 0x02, 0x6f, 0x29, 0x8b, +/* S - byte alignment */ + 0x00, 0x1d, 0xb7, 0x46, 0x29, 0x9f, 0xd3, 0x0d, 0x20, 0x3b, 0x2b, 0xe4, + 0x4b, 0xb2, 0x3c, 0xcf, 0x61, 0x05, 0x5c, 0x9a, 0x09 +}; +static const uint8_t nist_186_2_ecdsa_testvector_81_ptx[] = { +/* Msg */ + 0xb2, 0x7e, 0x3e, 0xfe, 0x6f, 0xfc, 0xe7, 0xe1, 0x76, 0x1c, 0x27, 0x84, + 0x9e, 0xab, 0xa3, 0xcc, 0xce, 0x43, 0xa5, 0xae, 0xb5, 0x28, 0x6c, 0x38, + 0xbb, 0x70, 0xc7, 0xd1, 0x37, 0x67, 0xe2, 0xc1, 0xe2, 0x31, 0x5f, 0xf4, + 0x8c, 0xb1, 0xa8, 0xfa, 0x0d, 0xaa, 0x84, 0x53, 0x7f, 0x24, 0xe9, 0xea, + 0xaa, 0x12, 0x12, 0xdf, 0xc0, 0x31, 0xd0, 0x89, 0x4b, 0x33, 0x25, 0xbc, + 0x63, 0x1d, 0x0f, 0x47, 0x24, 0xee, 0xa2, 0xc1, 0x5f, 0x81, 0x59, 0x86, + 0x90, 0xb4, 0xae, 0xfc, 0x10, 0xca, 0xe8, 0x1b, 0x8c, 0x0e, 0x35, 0x2c, + 0xb6, 0xb9, 0xf8, 0xd0, 0x3a, 0x16, 0x64, 0x45, 0xf4, 0xe4, 0x4a, 0xe5, + 0x60, 0xfc, 0x2f, 0xef, 0x52, 0x34, 0xa2, 0x8a, 0xe7, 0x82, 0xcd, 0x07, + 0xbb, 0x65, 0x49, 0x67, 0x5c, 0x80, 0x37, 0x1d, 0xff, 0x88, 0x8c, 0x15, + 0x72, 0x61, 0xac, 0xf4, 0x52, 0x84, 0x3b, 0xa2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_81_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0x0d, 0x5c, 0x1d, 0xc7, 0x23, 0x12, 0xfb, 0x6e, + 0x0a, 0x99, 0xb1, 0x2c, 0xd1, 0x49, 0xbc, 0x87, 0xa0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_81_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0x64, 0x4d, 0x39, 0x7d, 0x5d, 0xa9, 0xca, 0x51, 0x2e, 0x53, 0x1a, + 0xd7, 0xea, 0xbd, 0xd4, 0x6e, 0x94, 0xee, 0x64, 0x34 +}; +static const uint8_t nist_186_2_ecdsa_testvector_81_public_y[] = { +/* Qy - byte alignment */ + 0x03, 0x07, 0x6e, 0xce, 0x39, 0xb0, 0xa6, 0x20, 0x12, 0x79, 0xda, 0x46, + 0x6a, 0x6e, 0x94, 0xb1, 0x06, 0xec, 0xaf, 0x0b, 0xb4 +}; +/* k = 000000217f4ff46866a7d6245ba213da3c4ea7abd */ +static const uint8_t nist_186_2_ecdsa_testvector_81_out[] = { +/* R - byte alignment */ + 0x01, 0x3c, 0xb5, 0x49, 0x9d, 0xef, 0x63, 0x9a, 0xc6, 0xd2, 0x8b, 0xe0, + 0x65, 0x99, 0x20, 0x63, 0x42, 0xf5, 0x53, 0xb8, 0x96, +/* S - byte alignment */ + 0x02, 0x0b, 0xd7, 0x31, 0xcf, 0x1e, 0xfd, 0xe7, 0x53, 0x59, 0xf9, 0x25, + 0xd9, 0xb9, 0xff, 0xb1, 0x18, 0x60, 0xfb, 0xed, 0xb8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_82_ptx[] = { +/* Msg */ + 0x87, 0xf3, 0xb9, 0xf9, 0x71, 0x94, 0xfb, 0x07, 0x0e, 0xa8, 0x3c, 0x0c, + 0xe6, 0xa8, 0xe2, 0x67, 0x2e, 0x05, 0x6a, 0x30, 0xed, 0xbc, 0xad, 0x6e, + 0x5d, 0x2b, 0x62, 0x8a, 0x94, 0x22, 0xe5, 0x04, 0x63, 0x3e, 0x37, 0x65, + 0x7f, 0x72, 0x45, 0x75, 0xde, 0xe7, 0x6d, 0xad, 0x64, 0x06, 0x3e, 0xef, + 0xbf, 0xd3, 0x7f, 0x75, 0x90, 0x7c, 0x73, 0x08, 0xcb, 0x31, 0x5c, 0x72, + 0x60, 0x37, 0x3e, 0x35, 0x1b, 0x38, 0xe5, 0x7d, 0xc8, 0xde, 0x29, 0x54, + 0x9c, 0xa0, 0x71, 0x15, 0xd0, 0xdb, 0x76, 0x23, 0x8f, 0x24, 0x4a, 0xda, + 0x12, 0xdd, 0x98, 0xc6, 0x0a, 0x06, 0x2d, 0x13, 0x3e, 0x56, 0xb7, 0x45, + 0x75, 0x8a, 0xcd, 0x2a, 0x96, 0xfe, 0x30, 0x0c, 0x0e, 0x7a, 0x51, 0x2a, + 0x72, 0x4e, 0x13, 0x6a, 0x65, 0xa1, 0xd1, 0x48, 0xbd, 0x06, 0xa3, 0x12, + 0xe1, 0x50, 0xdd, 0x57, 0x75, 0xa8, 0xd9, 0x9d +}; +static const uint8_t nist_186_2_ecdsa_testvector_82_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0x61, 0xe9, 0x60, 0x4c, 0x1c, 0xf3, 0xa7, 0x2a, + 0x25, 0x59, 0xf5, 0x2f, 0x2e, 0x5a, 0x33, 0xa0, 0x0d +}; +static const uint8_t nist_186_2_ecdsa_testvector_82_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0xaa, 0x80, 0x97, 0x24, 0x50, 0xe0, 0x1b, 0x6a, 0x92, 0x9a, 0x50, + 0x61, 0xc1, 0xe2, 0xfa, 0x89, 0x46, 0x02, 0xf8, 0x06 +}; +static const uint8_t nist_186_2_ecdsa_testvector_82_public_y[] = { +/* Qy - byte alignment */ + 0x07, 0x14, 0x40, 0x7f, 0x01, 0x02, 0xa1, 0xe3, 0xc2, 0xb9, 0x76, 0xb5, + 0xc1, 0x4d, 0x27, 0xc3, 0x6c, 0xc7, 0xc9, 0x79, 0xcf +}; +/* k = 0000003a825776cddc985306cd5aa113f7c564063 */ +static const uint8_t nist_186_2_ecdsa_testvector_82_out[] = { +/* R - byte alignment */ + 0x01, 0xcf, 0x66, 0xa6, 0x8f, 0x88, 0x23, 0xae, 0xe8, 0xdf, 0x5a, 0x84, + 0x2d, 0x76, 0x9c, 0x59, 0xab, 0x81, 0x52, 0xdd, 0xf2, +/* S - byte alignment */ + 0x01, 0x9a, 0xdf, 0x89, 0x20, 0x11, 0x10, 0x5e, 0xcf, 0x4a, 0x9f, 0xf3, + 0x7a, 0xb6, 0x1b, 0x11, 0x12, 0x90, 0x3b, 0x0e, 0xa9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_83_ptx[] = { +/* Msg */ + 0x4c, 0xf2, 0xee, 0x62, 0x40, 0xa7, 0x5c, 0xb1, 0xc7, 0xf9, 0xf3, 0x81, + 0xd1, 0xa4, 0xd0, 0x8e, 0x01, 0x57, 0x39, 0x15, 0x68, 0x65, 0x7f, 0x2f, + 0x94, 0xbd, 0x29, 0x5d, 0xc9, 0x1c, 0x4e, 0x64, 0x8e, 0x81, 0x43, 0x5b, + 0x6b, 0xe2, 0x77, 0x02, 0xf2, 0x1d, 0x9a, 0x55, 0xfc, 0x31, 0x05, 0x61, + 0x35, 0xae, 0x56, 0x57, 0xdb, 0x6a, 0x5a, 0xdf, 0xc2, 0x76, 0x31, 0xae, + 0x9c, 0x50, 0xac, 0x5b, 0x77, 0x5a, 0xfa, 0x6e, 0x87, 0x8b, 0x84, 0xbb, + 0x26, 0x65, 0x15, 0xee, 0x19, 0x27, 0x3e, 0x66, 0x15, 0x43, 0xf9, 0x47, + 0x81, 0x12, 0x8c, 0xca, 0x7e, 0xc7, 0xb0, 0xd8, 0x25, 0xa2, 0xf3, 0xd8, + 0x0f, 0x66, 0x5b, 0xc5, 0x1b, 0x0c, 0x4c, 0x83, 0x6b, 0xb9, 0xab, 0x73, + 0xb0, 0xee, 0x44, 0x45, 0xa8, 0xfe, 0x69, 0x0d, 0xe5, 0xc6, 0xdc, 0x99, + 0xcf, 0x98, 0xf0, 0x02, 0xec, 0x78, 0xea, 0x82 +}; +static const uint8_t nist_186_2_ecdsa_testvector_83_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0x12, 0xd8, 0xd8, 0x62, 0xd6, 0x3a, 0xa8, 0xcc, + 0x9a, 0xae, 0x8f, 0xc6, 0x08, 0x93, 0x10, 0x26, 0x1a +}; +static const uint8_t nist_186_2_ecdsa_testvector_83_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xfb, 0x53, 0x45, 0x0e, 0x99, 0x8e, 0x10, 0xf3, 0xd7, 0xe2, 0x50, + 0xaf, 0x25, 0x09, 0x1b, 0x34, 0x16, 0xf9, 0x55, 0x7c +}; +static const uint8_t nist_186_2_ecdsa_testvector_83_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x20, 0x13, 0xa4, 0x3e, 0x83, 0xde, 0x70, 0xea, 0xe3, 0x4e, 0xc0, + 0xf1, 0xc9, 0xe0, 0x64, 0xf8, 0xb8, 0xa4, 0xcf, 0x96 +}; +/* k = 0000000f87c1a90f06df81b91e3f5ea2b901dc1ce */ +static const uint8_t nist_186_2_ecdsa_testvector_83_out[] = { +/* R - byte alignment */ + 0x03, 0x86, 0x52, 0x6c, 0x35, 0x5a, 0x58, 0x65, 0xdd, 0x24, 0x4e, 0x0d, + 0x1d, 0xc7, 0x60, 0x8c, 0x68, 0xa0, 0x5d, 0x09, 0x24, +/* S - byte alignment */ + 0x01, 0x2a, 0x0c, 0x46, 0x92, 0x44, 0x23, 0x4a, 0xcf, 0x9e, 0xf7, 0x6a, + 0xab, 0x62, 0x5e, 0xe4, 0xf0, 0x87, 0xd5, 0x87, 0x1d +}; +static const uint8_t nist_186_2_ecdsa_testvector_84_ptx[] = { +/* Msg */ + 0x72, 0xdd, 0xa4, 0x28, 0x45, 0x65, 0x4c, 0xb2, 0x5d, 0x35, 0xcf, 0x8c, + 0xe3, 0xa7, 0xb3, 0x77, 0xa5, 0x1b, 0x66, 0x72, 0xb1, 0x3b, 0x77, 0x25, + 0x23, 0x84, 0x06, 0x80, 0x3b, 0x02, 0x7a, 0xa0, 0xb3, 0x5a, 0x72, 0xf2, + 0x4f, 0x0e, 0xfd, 0x9a, 0xb5, 0xfd, 0x0d, 0x16, 0x7f, 0x29, 0x29, 0x1e, + 0x8f, 0xbd, 0x63, 0xcf, 0xa2, 0x4f, 0x8a, 0x09, 0x28, 0x62, 0xa0, 0x16, + 0x54, 0x2f, 0x8e, 0x8c, 0x6f, 0xa5, 0x17, 0x74, 0x71, 0xae, 0x0b, 0xab, + 0xd2, 0xb4, 0xbd, 0x89, 0x9e, 0x64, 0xb6, 0xc1, 0xc8, 0xb1, 0xab, 0x88, + 0xc0, 0x1c, 0xad, 0xfa, 0x47, 0x33, 0xa0, 0xb9, 0x83, 0x58, 0xee, 0xd7, + 0x4e, 0xc4, 0x7d, 0xf6, 0xd4, 0xcc, 0xde, 0xad, 0x5d, 0x62, 0xc7, 0x2e, + 0x67, 0xde, 0xc3, 0x26, 0xf8, 0xff, 0x28, 0xe5, 0x32, 0x2c, 0x49, 0xbf, + 0x28, 0x00, 0xee, 0xb2, 0xf0, 0x06, 0x01, 0x49 +}; +static const uint8_t nist_186_2_ecdsa_testvector_84_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0x10, 0x0c, 0x44, 0x9f, 0x8f, 0x2a, 0xfb, 0x6c, + 0xc3, 0x7c, 0xb5, 0x9a, 0xbb, 0x74, 0x42, 0x35, 0xaa +}; +static const uint8_t nist_186_2_ecdsa_testvector_84_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xcc, 0x30, 0x8b, 0xd9, 0x87, 0xb7, 0x3d, 0xe3, 0xda, 0xde, 0x37, + 0x50, 0xb6, 0x02, 0xb2, 0xaf, 0x38, 0x97, 0x5d, 0x2f +}; +static const uint8_t nist_186_2_ecdsa_testvector_84_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x43, 0x40, 0x7a, 0x50, 0xec, 0xcf, 0x27, 0x33, 0x85, 0x84, 0x04, + 0xdb, 0x64, 0x6b, 0x47, 0x81, 0x6a, 0xeb, 0xbf, 0x5d +}; +/* k = 0000001f196493e41d9aa701ae69b9efa6ef754d0 */ +static const uint8_t nist_186_2_ecdsa_testvector_84_out[] = { +/* R - byte alignment */ + 0x02, 0xe9, 0x13, 0xb4, 0x69, 0x87, 0x46, 0x0d, 0x86, 0x35, 0xc8, 0x63, + 0x71, 0xae, 0xb0, 0x89, 0x8d, 0x51, 0xfc, 0x57, 0x9f, +/* S - byte alignment */ + 0x01, 0x76, 0x8e, 0xde, 0x6f, 0xa5, 0xbc, 0x7a, 0x16, 0x55, 0x41, 0x89, + 0xd5, 0xdd, 0x8c, 0x6d, 0x64, 0xbb, 0x35, 0x36, 0x5b +}; +static const uint8_t nist_186_2_ecdsa_testvector_85_ptx[] = { +/* Msg */ + 0xbe, 0xc9, 0x65, 0x87, 0xaf, 0x3c, 0x78, 0x4d, 0xa0, 0xe5, 0x47, 0xbc, + 0xfb, 0x15, 0x34, 0xc0, 0xd2, 0x25, 0x81, 0x9f, 0x23, 0xad, 0xb8, 0xce, + 0x5b, 0xf7, 0x4a, 0x09, 0x18, 0xb4, 0x76, 0xa2, 0x33, 0xed, 0x6c, 0x1a, + 0xfe, 0x3c, 0xb3, 0xee, 0xca, 0x3b, 0xc8, 0xb3, 0xad, 0x3d, 0x08, 0x65, + 0x82, 0x3c, 0xcf, 0xfd, 0x30, 0x13, 0xe2, 0x41, 0x30, 0xed, 0x0a, 0xe0, + 0x49, 0xfe, 0x02, 0xbe, 0x9e, 0x71, 0x93, 0x8d, 0xeb, 0xa1, 0xfe, 0x9d, + 0x0c, 0x8b, 0x9a, 0xf5, 0xbf, 0x84, 0xbe, 0xa2, 0xaa, 0x27, 0xe1, 0x4f, + 0xa0, 0x92, 0x00, 0x16, 0x20, 0xd2, 0x41, 0x96, 0x1e, 0x9b, 0xd5, 0x46, + 0x06, 0x3c, 0x22, 0x08, 0xff, 0xd3, 0x22, 0x02, 0x6d, 0xbd, 0x06, 0xa9, + 0xb9, 0x51, 0x20, 0x1e, 0x54, 0xce, 0xff, 0xbe, 0xf9, 0x91, 0xdc, 0xf5, + 0x33, 0x8c, 0x35, 0x52, 0x20, 0xf3, 0xb7, 0xe1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_85_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0xc8, 0x7d, 0x11, 0xdf, 0x7c, 0x27, 0xdd, 0x15, + 0x99, 0x03, 0x5c, 0x33, 0xa5, 0x48, 0x7f, 0xaf, 0x21 +}; +static const uint8_t nist_186_2_ecdsa_testvector_85_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xa7, 0xd1, 0xab, 0xee, 0x8f, 0x7f, 0x94, 0x12, 0x83, 0x8f, 0xcb, + 0x46, 0x86, 0xf2, 0x46, 0xd8, 0x2b, 0x71, 0xf9, 0x7a +}; +static const uint8_t nist_186_2_ecdsa_testvector_85_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xfe, 0xf6, 0x98, 0x42, 0xfb, 0xde, 0x66, 0x1e, 0xee, 0x35, 0xfb, + 0xde, 0x66, 0xf2, 0x69, 0x31, 0xc5, 0x61, 0x54, 0x06 +}; +/* k = 0000002e991f95b13753b6c9ffb941d4553681bce */ +static const uint8_t nist_186_2_ecdsa_testvector_85_out[] = { +/* R - byte alignment */ + 0x03, 0x8e, 0x87, 0x1a, 0x80, 0xd0, 0x4d, 0x37, 0x53, 0xaf, 0xee, 0x22, + 0xd4, 0x0e, 0xda, 0xee, 0xa8, 0x55, 0x51, 0xdf, 0x74, +/* S - byte alignment */ + 0x03, 0xe2, 0xa9, 0xd7, 0x5c, 0xc3, 0xd7, 0x98, 0x92, 0x89, 0x88, 0xe3, + 0x98, 0x52, 0x59, 0xef, 0x4b, 0x69, 0x6c, 0x91, 0x83 +}; +static const uint8_t nist_186_2_ecdsa_testvector_86_ptx[] = { +/* Msg */ + 0xee, 0xe8, 0x3f, 0x9a, 0xd3, 0xf8, 0x0c, 0x73, 0xc6, 0xe3, 0x3e, 0x4c, + 0x34, 0xf5, 0x38, 0x08, 0x41, 0x4d, 0xf4, 0xca, 0x54, 0x48, 0xa6, 0x0a, + 0xd5, 0x3d, 0x9c, 0xe9, 0x35, 0x6b, 0x69, 0xc1, 0x2f, 0x2f, 0x42, 0x01, + 0x4e, 0x7b, 0xa8, 0x38, 0xb0, 0x83, 0x48, 0x6f, 0x09, 0xb9, 0x1f, 0xbc, + 0xea, 0xfc, 0xe1, 0x14, 0x44, 0x0c, 0x9c, 0x61, 0x28, 0x42, 0x98, 0xd4, + 0xd0, 0x7e, 0x83, 0x7d, 0xe3, 0x60, 0xca, 0x19, 0xf5, 0xbb, 0x4a, 0x2b, + 0x4d, 0x46, 0x28, 0x4e, 0xec, 0x95, 0xfd, 0xc9, 0xcb, 0x48, 0x37, 0x64, + 0x63, 0x83, 0xbc, 0x7a, 0x72, 0x9e, 0xd0, 0x50, 0xfd, 0x1d, 0x38, 0xa5, + 0x91, 0xe2, 0x9f, 0x8a, 0xcf, 0xa1, 0x3a, 0x74, 0x28, 0x95, 0xa8, 0x90, + 0xe4, 0x71, 0x1c, 0x56, 0x69, 0x9a, 0xbd, 0x61, 0xba, 0x93, 0x4d, 0x7e, + 0x3e, 0xb8, 0x09, 0x03, 0xc3, 0x30, 0xd1, 0x62 +}; +static const uint8_t nist_186_2_ecdsa_testvector_86_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x02, 0x17, 0x95, 0xe5, 0x62, 0xec, 0x44, 0xfa, 0xbf, + 0x86, 0xa7, 0x75, 0xa5, 0x8c, 0xb6, 0x15, 0x8a, 0x4c +}; +static const uint8_t nist_186_2_ecdsa_testvector_86_public_x[] = { +/* Qx - byte alignment */ + 0x07, 0x45, 0x73, 0x40, 0xc9, 0xec, 0xa2, 0x80, 0xbf, 0x33, 0xd2, 0x97, + 0xa4, 0x65, 0xd4, 0x00, 0xe3, 0x14, 0x18, 0xba, 0xf7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_86_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0xf3, 0x35, 0xb0, 0x7b, 0x49, 0x02, 0x1b, 0xe5, 0x6f, 0x0e, 0x7b, + 0x32, 0x0f, 0x0b, 0x2f, 0xe5, 0x7a, 0x92, 0x36, 0xf2 +}; +/* k = 00000016d19275205c1d866392ff232ddc4e0e41d */ +static const uint8_t nist_186_2_ecdsa_testvector_86_out[] = { +/* R - byte alignment */ + 0x00, 0xe8, 0xf2, 0x08, 0xd7, 0x40, 0x8d, 0x23, 0x1b, 0xc0, 0xa0, 0xf8, + 0x85, 0xfc, 0x50, 0xc9, 0xd0, 0x98, 0xf3, 0xe6, 0x9d, +/* S - byte alignment */ + 0x03, 0xd7, 0x20, 0xaa, 0xff, 0x03, 0x43, 0xd0, 0xd7, 0xff, 0x93, 0xc1, + 0xff, 0xf9, 0x0e, 0x83, 0xfc, 0x18, 0xc0, 0x7c, 0xcb +}; +static const uint8_t nist_186_2_ecdsa_testvector_87_ptx[] = { +/* Msg */ + 0x3d, 0x0c, 0x9a, 0x35, 0x03, 0x6a, 0xae, 0xaa, 0xd2, 0xb2, 0xf7, 0xac, + 0x72, 0x1e, 0x15, 0x6c, 0x24, 0x76, 0xfe, 0x17, 0x2a, 0x87, 0xa1, 0xf3, + 0x8a, 0xd0, 0xca, 0xaa, 0x10, 0x7e, 0x46, 0xe6, 0x92, 0x9b, 0x47, 0x1d, + 0x77, 0x82, 0x0a, 0xaf, 0x7a, 0x96, 0xb6, 0x2e, 0xac, 0x33, 0x88, 0xfc, + 0xb8, 0xe5, 0x2d, 0x1c, 0x6b, 0xd8, 0x6f, 0x42, 0x74, 0x90, 0x14, 0x2c, + 0x68, 0xda, 0x03, 0x35, 0x09, 0x03, 0xa9, 0x28, 0xc7, 0x47, 0x9b, 0x52, + 0x87, 0x8c, 0x7d, 0xdb, 0xa4, 0x51, 0x22, 0x56, 0x33, 0xe1, 0xf4, 0x96, + 0x8c, 0xcc, 0x97, 0xc3, 0x06, 0x97, 0xc9, 0xae, 0x01, 0xb3, 0x8d, 0x62, + 0x2a, 0xac, 0x88, 0xfc, 0xfa, 0xa3, 0xab, 0xbc, 0x80, 0xfe, 0x12, 0x5b, + 0x61, 0x5e, 0x2c, 0x9f, 0x1d, 0xd1, 0x1d, 0x2e, 0x93, 0x4a, 0x60, 0xa0, + 0xc8, 0x4e, 0xb1, 0xd7, 0xe4, 0xef, 0x2a, 0x93 +}; +static const uint8_t nist_186_2_ecdsa_testvector_87_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0x10, 0xb1, 0x81, 0xa9, 0x71, 0xc6, 0x5b, 0x40, + 0x46, 0xb8, 0x9a, 0x12, 0x76, 0xe1, 0x48, 0x09, 0x47 +}; +static const uint8_t nist_186_2_ecdsa_testvector_87_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0xce, 0x4a, 0xd1, 0x99, 0x09, 0x31, 0xf9, 0x41, 0xf3, 0x38, 0xa9, + 0xd9, 0x6a, 0xf9, 0x57, 0x1a, 0x1d, 0xb9, 0x44, 0xc7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_87_public_y[] = { +/* Qy - byte alignment */ + 0x03, 0xc5, 0x15, 0x88, 0x97, 0xa7, 0xd9, 0x6c, 0x06, 0x56, 0x50, 0xed, + 0x31, 0x41, 0x6f, 0x30, 0x0f, 0xf4, 0x5d, 0xf8, 0x08 +}; +/* k = 00000010a625837343a44a7d8701636b82a8a950c */ +static const uint8_t nist_186_2_ecdsa_testvector_87_out[] = { +/* R - byte alignment */ + 0x02, 0xcd, 0xb0, 0x81, 0x1a, 0xc0, 0x4a, 0x55, 0xe2, 0x0d, 0x60, 0x67, + 0x7f, 0xda, 0x53, 0x98, 0x2e, 0xa2, 0x40, 0x71, 0x89, +/* S - byte alignment */ + 0x03, 0x67, 0xe4, 0x48, 0x88, 0xd8, 0x29, 0x50, 0xa2, 0x08, 0x14, 0x99, + 0x39, 0xc6, 0xae, 0x73, 0x26, 0x7c, 0x9d, 0x16, 0xc5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_88_ptx[] = { +/* Msg */ + 0x14, 0xd1, 0xfb, 0x46, 0x3a, 0x53, 0xde, 0xad, 0x1c, 0xaa, 0x23, 0x3c, + 0x94, 0x18, 0x9a, 0xd8, 0x00, 0x50, 0xb6, 0x74, 0x99, 0x7e, 0x86, 0x35, + 0x00, 0x88, 0xe7, 0xd4, 0x1a, 0x93, 0xf9, 0x45, 0x1e, 0xca, 0xcf, 0x96, + 0xec, 0x5a, 0x6b, 0x19, 0xa1, 0xc1, 0xe9, 0xc5, 0x68, 0x49, 0xfa, 0xda, + 0x93, 0xcf, 0x94, 0xc4, 0xea, 0xc9, 0xe8, 0x42, 0x42, 0x88, 0x95, 0xc7, + 0x52, 0xba, 0x1b, 0x21, 0xc3, 0x32, 0x92, 0x58, 0x86, 0xec, 0x9c, 0xd9, + 0x6a, 0x4b, 0x98, 0xd3, 0xee, 0xa6, 0x18, 0xe2, 0x53, 0x03, 0x95, 0xeb, + 0xf6, 0x22, 0x62, 0x47, 0xdd, 0xbe, 0xdf, 0x23, 0x90, 0x0f, 0xef, 0x26, + 0x2a, 0x93, 0xac, 0x55, 0xaf, 0x0e, 0x59, 0x34, 0xa0, 0xd0, 0x97, 0x2e, + 0xcd, 0x36, 0xdc, 0x37, 0x6b, 0x73, 0x22, 0xb0, 0x66, 0x90, 0xdc, 0x8b, + 0xf9, 0xb2, 0x2e, 0xaf, 0x7b, 0x9c, 0x5d, 0x9e +}; +static const uint8_t nist_186_2_ecdsa_testvector_88_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x5b, 0xbc, 0xe8, 0xf1, 0xf0, 0xd1, 0xad, 0xb7, + 0xbd, 0xf2, 0xf5, 0xdd, 0xa8, 0x2f, 0xa4, 0xc6, 0xba +}; +static const uint8_t nist_186_2_ecdsa_testvector_88_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xfa, 0xb0, 0x00, 0x0b, 0xb5, 0xd8, 0x16, 0x3e, 0xdf, 0x17, 0xb9, + 0x6c, 0xd5, 0xb7, 0x77, 0x26, 0x1d, 0xf0, 0xfe, 0x12 +}; +static const uint8_t nist_186_2_ecdsa_testvector_88_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0x2a, 0xc5, 0xec, 0x94, 0xf8, 0x87, 0x3a, 0x7b, 0x60, 0xff, 0x2e, + 0x71, 0xfc, 0x17, 0x22, 0x3e, 0xfb, 0xb4, 0x6e, 0x38 +}; +/* k = 000000067b782d169e842d0077bde068705aee8e7 */ +static const uint8_t nist_186_2_ecdsa_testvector_88_out[] = { +/* R - byte alignment */ + 0x03, 0x1f, 0x6c, 0x99, 0x6e, 0xc0, 0xd1, 0x61, 0x05, 0xff, 0x1a, 0xc7, + 0x5e, 0xda, 0x35, 0xf1, 0x5e, 0x14, 0x29, 0x25, 0xda, +/* S - byte alignment */ + 0x01, 0xe2, 0x3e, 0xef, 0x66, 0xc3, 0x12, 0x6a, 0x36, 0xee, 0x19, 0xa9, + 0x04, 0x80, 0x95, 0xf9, 0x61, 0x38, 0x57, 0x08, 0x23 +}; +static const uint8_t nist_186_2_ecdsa_testvector_89_ptx[] = { +/* Msg */ + 0x1e, 0xf7, 0x9e, 0x82, 0xfd, 0x0c, 0x8d, 0x6e, 0x52, 0xfd, 0x25, 0xa5, + 0xec, 0xb3, 0xbb, 0xfd, 0xd9, 0x51, 0xf6, 0x4e, 0x1e, 0x16, 0x26, 0x79, + 0xab, 0x86, 0xd7, 0xa9, 0x8d, 0xc4, 0xa7, 0xd9, 0x66, 0x43, 0x54, 0x97, + 0x1a, 0x9d, 0x19, 0x07, 0xcc, 0xc3, 0x3b, 0x2a, 0x09, 0x57, 0xdf, 0x60, + 0x42, 0x56, 0x1e, 0x2c, 0x80, 0xfa, 0x5b, 0x38, 0x53, 0xdf, 0xd4, 0x99, + 0x0b, 0x64, 0x78, 0x53, 0x2b, 0x54, 0xf9, 0x20, 0x1b, 0xc6, 0x21, 0x6d, + 0x1d, 0x41, 0x69, 0xa6, 0x82, 0x24, 0xc8, 0xb3, 0x1e, 0x45, 0xc9, 0xc3, + 0xf9, 0xd9, 0xe0, 0x48, 0x47, 0x94, 0xfe, 0x42, 0x9b, 0x11, 0x63, 0xc1, + 0x57, 0x73, 0xb4, 0xa5, 0x67, 0x4d, 0x4d, 0xa9, 0x2f, 0xbf, 0xd8, 0xa0, + 0xc1, 0xe2, 0x1e, 0xfe, 0x54, 0x66, 0x1e, 0x99, 0xf2, 0x7a, 0x5c, 0xb1, + 0x70, 0xec, 0x7c, 0x2e, 0xa3, 0x92, 0x0f, 0x2a +}; +static const uint8_t nist_186_2_ecdsa_testvector_89_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x02, 0x34, 0xe1, 0xb3, 0x04, 0x6e, 0xd2, 0x9e, 0xcc, + 0xa9, 0x2e, 0x31, 0xd8, 0x6a, 0x0d, 0xc2, 0x2b, 0xc6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_89_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0x0b, 0x3e, 0x2f, 0xae, 0x4d, 0xdc, 0x9b, 0xde, 0x52, 0x58, 0x68, + 0x95, 0x24, 0x54, 0xd5, 0x93, 0x42, 0x32, 0x70, 0x79 +}; +static const uint8_t nist_186_2_ecdsa_testvector_89_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x9c, 0xa8, 0x67, 0xd2, 0xd7, 0x9c, 0xd3, 0xa2, 0x32, 0x12, 0x84, + 0x4d, 0x76, 0xb5, 0x0d, 0xbf, 0x9b, 0x47, 0x48, 0xcd +}; +/* k = 0000000261db3bb5df417062578d6699ac24bf28a */ +static const uint8_t nist_186_2_ecdsa_testvector_89_out[] = { +/* R - byte alignment */ + 0x00, 0x49, 0x67, 0xf9, 0xca, 0xe7, 0x4a, 0xcf, 0x37, 0x26, 0xa2, 0x41, + 0xe5, 0x3c, 0xf7, 0x68, 0x1f, 0x7d, 0xc7, 0x2e, 0x2f, +/* S - byte alignment */ + 0x03, 0x52, 0x45, 0x77, 0x7c, 0x0e, 0x01, 0xf3, 0x0c, 0x61, 0x31, 0x20, + 0x73, 0x77, 0xbb, 0xae, 0x3c, 0xf8, 0x81, 0x0f, 0xea +}; +static const uint8_t nist_186_2_ecdsa_testvector_90_ptx[] = { +/* Msg */ + 0xd5, 0xdd, 0x3b, 0x6c, 0xe9, 0x77, 0x2d, 0x9a, 0x97, 0xfe, 0x21, 0x64, + 0x84, 0x97, 0x78, 0x3b, 0xac, 0x5b, 0xb5, 0x25, 0x4a, 0xad, 0x82, 0xb6, + 0xf7, 0xcb, 0xf4, 0x3b, 0x15, 0xa4, 0x0f, 0x38, 0x6e, 0xea, 0x8d, 0x15, + 0x19, 0x67, 0xdb, 0x14, 0x9e, 0x94, 0x65, 0x86, 0x59, 0x68, 0x13, 0x3f, + 0x24, 0x6e, 0x13, 0x47, 0x30, 0x1a, 0xda, 0xd2, 0x34, 0x5d, 0x65, 0x72, + 0xca, 0x77, 0xc5, 0x8c, 0x15, 0x0d, 0xda, 0x09, 0xa8, 0x7b, 0x5f, 0x4d, + 0xa3, 0x6b, 0x26, 0x6d, 0x1f, 0xa7, 0xa5, 0x9c, 0xcd, 0x2b, 0xb2, 0xe7, + 0xd9, 0x7f, 0x8b, 0x23, 0x15, 0x43, 0x19, 0x23, 0x53, 0x0b, 0x76, 0x2e, + 0x12, 0x6e, 0xac, 0xaf, 0x5e, 0x5a, 0xc0, 0x2f, 0xf1, 0xaa, 0xef, 0x81, + 0x9e, 0xfb, 0x37, 0x3c, 0xf0, 0xbb, 0x19, 0x6f, 0x0e, 0x82, 0x9e, 0x8f, + 0xe1, 0xa6, 0x98, 0xb4, 0x79, 0x0a, 0x2a, 0x05 +}; +static const uint8_t nist_186_2_ecdsa_testvector_90_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0xf0, 0x76, 0x90, 0x78, 0x0b, 0xd7, 0x56, 0x01, + 0x56, 0x5b, 0x3c, 0x4c, 0xc9, 0x67, 0x15, 0x9f, 0x0e +}; +static const uint8_t nist_186_2_ecdsa_testvector_90_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x85, 0xdb, 0x6d, 0x13, 0x12, 0xda, 0xb2, 0xfd, 0x00, 0xc8, 0x01, + 0x62, 0xbe, 0xd1, 0x79, 0x10, 0x7a, 0x4b, 0x7c, 0xf3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_90_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0x80, 0x07, 0xc8, 0x61, 0x93, 0xb2, 0x22, 0x98, 0x77, 0xf2, 0x9b, + 0xce, 0x5b, 0xea, 0xc1, 0xe5, 0x47, 0xee, 0xf2, 0xd2 +}; +/* k = 000000113523759c8e2b89b3fb82f490a2f9a413f */ +static const uint8_t nist_186_2_ecdsa_testvector_90_out[] = { +/* R - byte alignment */ + 0x00, 0xe8, 0xe4, 0x2b, 0x4a, 0x02, 0xba, 0x46, 0xb5, 0x85, 0x24, 0xce, + 0x93, 0x3f, 0xad, 0x94, 0x47, 0xd8, 0x7f, 0x01, 0x77, +/* S - byte alignment */ + 0x03, 0x4e, 0x41, 0xac, 0x5e, 0x05, 0xc0, 0x76, 0x30, 0x34, 0x91, 0x2f, + 0xd8, 0x6e, 0xb4, 0x6e, 0x2d, 0xbe, 0xbc, 0x2f, 0x4f +}; +/* [K-233] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_91_ptx[] = { +/* Msg */ + 0xf7, 0x64, 0xf4, 0x2d, 0x70, 0xcf, 0x6e, 0xce, 0xa6, 0x26, 0xc3, 0x06, + 0x9a, 0xb0, 0x27, 0x07, 0x4b, 0xca, 0x9e, 0x9c, 0xe1, 0x41, 0xc7, 0xb3, + 0x2b, 0x00, 0xf8, 0x18, 0x4b, 0xeb, 0x90, 0x83, 0xb0, 0x0a, 0x89, 0xd5, + 0x45, 0xea, 0x4d, 0x9f, 0xe8, 0x40, 0xcb, 0xe4, 0x1e, 0xd0, 0xc9, 0x20, + 0x05, 0x8d, 0x7c, 0x88, 0x8a, 0x02, 0x56, 0x94, 0xdb, 0xf0, 0x1f, 0xbb, + 0x20, 0x39, 0x47, 0x7d, 0x66, 0xfc, 0x7b, 0xa7, 0xdb, 0x02, 0x76, 0xd3, + 0x41, 0x59, 0x1a, 0x2e, 0x9d, 0x3e, 0xbf, 0x7e, 0x2f, 0x41, 0xcb, 0x63, + 0xa7, 0xa3, 0x82, 0xdc, 0x96, 0x03, 0x20, 0x0e, 0x23, 0x39, 0x25, 0x41, + 0xff, 0x83, 0xf1, 0x2c, 0x9b, 0xdf, 0x90, 0x72, 0x98, 0xb7, 0xd7, 0x6c, + 0x7f, 0xc3, 0xb0, 0x29, 0xb2, 0x2c, 0xb2, 0xb3, 0xa2, 0xed, 0xf5, 0x94, + 0x43, 0x7f, 0x24, 0x99, 0xbd, 0xb5, 0xd3, 0xd6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_91_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x4f, 0xaa, 0xe1, 0x14, 0x0e, 0x1f, 0x42, 0x79, + 0xe1, 0x89, 0x21, 0xc9, 0x41, 0x03, 0x79, 0xfc, 0xe7, 0x16, 0x92, 0xe5, + 0x67, 0x83, 0x41, 0x90, 0x9c, 0xac +}; +static const uint8_t nist_186_2_ecdsa_testvector_91_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xc6, 0x36, 0x4b, 0x59, 0x33, 0xbe, 0xcd, 0x86, 0x78, 0xda, 0xa7, + 0x9d, 0xc8, 0xd7, 0x92, 0x73, 0x2e, 0x2f, 0xa7, 0xfa, 0x74, 0xf3, 0xb7, + 0x21, 0x78, 0x71, 0xfb, 0xe5, 0xc7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_91_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x79, 0x76, 0x4b, 0xdd, 0x86, 0x02, 0xe4, 0x5c, 0x4e, 0x26, 0x68, + 0x9d, 0x0c, 0x39, 0x8c, 0x48, 0x94, 0x66, 0x7c, 0xd6, 0x7f, 0x18, 0x63, + 0x4d, 0x8d, 0xcc, 0x93, 0x20, 0xe8 +}; +/* k = 00000000e6acf6a5eefdab8b6ad75e200b0a055bffd9293f73ca13d6d41 */ +static const uint8_t nist_186_2_ecdsa_testvector_91_out[] = { +/* R - byte alignment */ + 0x00, 0x7b, 0x9d, 0x20, 0x1e, 0x5c, 0xf2, 0xb3, 0x80, 0x66, 0xba, 0xca, + 0x3b, 0xbb, 0xa5, 0x5c, 0xb1, 0x64, 0x2d, 0xb5, 0x8e, 0xdf, 0xca, 0xbe, + 0xef, 0xdb, 0x36, 0x60, 0x5f, 0x0d, +/* S - byte alignment */ + 0x00, 0x0d, 0x96, 0x6c, 0xf5, 0xed, 0x16, 0x09, 0x11, 0x36, 0x03, 0x1f, + 0xf0, 0xcb, 0x5b, 0x83, 0x04, 0xf5, 0x1a, 0x46, 0xaa, 0xcd, 0x0c, 0xa7, + 0x0e, 0xdf, 0xb8, 0xdd, 0x9e, 0x94 +}; +static const uint8_t nist_186_2_ecdsa_testvector_92_ptx[] = { +/* Msg */ + 0x4f, 0x01, 0x17, 0x01, 0xb0, 0x91, 0x94, 0x4a, 0xd9, 0x43, 0x33, 0x90, + 0xdf, 0xef, 0x3b, 0x8f, 0xdb, 0x52, 0x47, 0x08, 0xd8, 0x62, 0x47, 0xb9, + 0xef, 0xdf, 0xc9, 0x8c, 0xb0, 0x2b, 0x77, 0x0f, 0xc4, 0x5b, 0xe0, 0x24, + 0xd1, 0x8e, 0x7b, 0xfa, 0x9e, 0x7d, 0xe8, 0x3b, 0x78, 0x54, 0x7a, 0x87, + 0xd4, 0xc1, 0xf3, 0x22, 0x35, 0x4a, 0x8e, 0xe9, 0x50, 0xe3, 0x43, 0x8b, + 0x6e, 0xc0, 0x46, 0xf5, 0x13, 0x68, 0xd1, 0x0e, 0xdd, 0x0b, 0x23, 0xa5, + 0xae, 0x15, 0xc9, 0xa7, 0x0e, 0x03, 0x1c, 0x96, 0xca, 0x75, 0x0b, 0x36, + 0xe1, 0x85, 0x1a, 0x8a, 0xa1, 0x58, 0xab, 0xfe, 0x0e, 0xf2, 0x7c, 0xe6, + 0x83, 0x4f, 0x72, 0x27, 0x9c, 0xaf, 0x95, 0x34, 0x52, 0x31, 0x5b, 0x3d, + 0x68, 0xa3, 0x29, 0xa3, 0x07, 0x99, 0x17, 0xae, 0xa5, 0xbc, 0xf4, 0x82, + 0x2b, 0x65, 0x8a, 0x4f, 0x56, 0x6b, 0x22, 0xc9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_92_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x1a, 0x65, 0x57, 0x96, 0xb6, 0x89, 0x6b, 0x4a, + 0xd8, 0xf1, 0xf9, 0xfb, 0x7c, 0x8d, 0xeb, 0x2f, 0xc5, 0xa1, 0x2e, 0x35, + 0x0c, 0xd2, 0x62, 0xda, 0xa0, 0xd7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_92_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x4b, 0xc5, 0x01, 0x44, 0x1d, 0xdf, 0x32, 0x30, 0x88, 0x78, 0x65, + 0xc9, 0x74, 0x95, 0x41, 0xc7, 0x31, 0x67, 0x53, 0x08, 0x15, 0x58, 0xe5, + 0xdf, 0x20, 0xca, 0xdd, 0x5d, 0x96 +}; +static const uint8_t nist_186_2_ecdsa_testvector_92_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x7f, 0x90, 0x8f, 0x1b, 0x85, 0xcf, 0x0a, 0xf2, 0xfd, 0xb6, 0x50, + 0xba, 0x58, 0xbb, 0x1d, 0x1a, 0x50, 0xa5, 0x38, 0xf4, 0x22, 0x64, 0x45, + 0xaa, 0xab, 0x67, 0x74, 0x16, 0x7b +}; +/* k = 00000001575c1e51145323e428693bdda6c974e997622cf9193aafde2b6 */ +static const uint8_t nist_186_2_ecdsa_testvector_92_out[] = { +/* R - byte alignment */ + 0x00, 0x0b, 0xfd, 0xa7, 0x98, 0x6f, 0xdf, 0xe8, 0x51, 0xec, 0x65, 0x0e, + 0x57, 0x57, 0xa7, 0x0c, 0x1b, 0xbf, 0xe9, 0xa4, 0x17, 0xdc, 0xa4, 0x4e, + 0xa1, 0xa9, 0x30, 0xb1, 0x5d, 0x63, +/* S - byte alignment */ + 0x00, 0x1b, 0xb9, 0x20, 0x16, 0xc9, 0xad, 0xb8, 0x6a, 0x94, 0x02, 0x0a, + 0x79, 0xfa, 0xf0, 0x41, 0xa5, 0xe5, 0xbe, 0xb1, 0x7d, 0x95, 0x05, 0x8b, + 0xe6, 0x46, 0x31, 0xd4, 0x77, 0x4f +}; +static const uint8_t nist_186_2_ecdsa_testvector_93_ptx[] = { +/* Msg */ + 0x93, 0x8b, 0x1f, 0x1d, 0x62, 0x88, 0x29, 0x39, 0x9e, 0x62, 0x2d, 0xb6, + 0xd1, 0x0d, 0xa1, 0x3f, 0xc8, 0xb1, 0x59, 0x68, 0x97, 0xa3, 0xaa, 0x42, + 0xdd, 0x93, 0xd0, 0x2e, 0x49, 0x07, 0x8d, 0xee, 0x5d, 0x08, 0x13, 0x02, + 0x72, 0x1a, 0x24, 0x31, 0xfd, 0x72, 0x78, 0x66, 0x10, 0x64, 0x5f, 0xbd, + 0x24, 0x1b, 0xa7, 0xde, 0x15, 0x8c, 0xc0, 0x8a, 0x6e, 0xac, 0x1e, 0x73, + 0xe7, 0xe1, 0xdf, 0x51, 0x2c, 0xb7, 0xae, 0x32, 0xe0, 0xd5, 0xe7, 0x11, + 0xe2, 0x2f, 0xfb, 0xab, 0xcf, 0x7d, 0x17, 0x8e, 0xc8, 0xeb, 0x00, 0x73, + 0x75, 0x12, 0x42, 0xcd, 0x49, 0x27, 0x89, 0xa2, 0x08, 0x72, 0x4f, 0x9a, + 0x87, 0x02, 0xb7, 0x56, 0xb4, 0xa0, 0xb9, 0x02, 0xd5, 0x01, 0x80, 0x2e, + 0x15, 0x40, 0x10, 0xd9, 0x3c, 0x8b, 0x2c, 0xcf, 0xbe, 0x1c, 0x77, 0x36, + 0xf7, 0x6a, 0xd9, 0x63, 0xb5, 0xa1, 0x24, 0xf2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_93_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x9b, 0x4f, 0xa1, 0x7e, 0x60, 0xdf, 0x6d, + 0x11, 0xd4, 0x36, 0xed, 0xae, 0x33, 0x4d, 0xd5, 0xc3, 0xf3, 0x04, 0xb9, + 0xa9, 0xf4, 0x1a, 0x4d, 0xfe, 0x01 +}; +static const uint8_t nist_186_2_ecdsa_testvector_93_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xc7, 0x5a, 0x98, 0xf2, 0xd8, 0x55, 0x17, 0x5b, 0x60, 0xc4, 0xc8, + 0xc6, 0xc3, 0xf7, 0x06, 0x2a, 0x6d, 0x2b, 0x42, 0x56, 0x52, 0xdf, 0x1b, + 0xb2, 0xd6, 0x42, 0x8e, 0x6b, 0x47 +}; +static const uint8_t nist_186_2_ecdsa_testvector_93_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xbe, 0xe7, 0xf3, 0x0a, 0x60, 0xed, 0x09, 0xba, 0xf3, 0xe2, 0x6d, + 0x30, 0x04, 0x54, 0x62, 0x4f, 0x88, 0x63, 0x41, 0x2a, 0x51, 0x1d, 0x2a, + 0x29, 0x2f, 0xd3, 0x2b, 0xed, 0x6b +}; +/* k = 0000000296f1a8b7941f2cfb3fc9a02eadb92e3ca70f3ee32b5f0715a2a */ +static const uint8_t nist_186_2_ecdsa_testvector_93_out[] = { +/* R - byte alignment */ + 0x00, 0x49, 0xb5, 0x8c, 0x83, 0x38, 0xf8, 0x71, 0x08, 0x94, 0x63, 0x4a, + 0xd4, 0xcd, 0xae, 0x92, 0xa2, 0x59, 0x16, 0x47, 0xe3, 0xa6, 0xd6, 0xb4, + 0xa2, 0xb0, 0x4f, 0x29, 0x24, 0xee, +/* S - byte alignment */ + 0x00, 0x5d, 0x2f, 0xb9, 0x19, 0x7e, 0x25, 0xad, 0xc6, 0x01, 0x93, 0xce, + 0x94, 0x01, 0x06, 0x5c, 0xd1, 0xb1, 0x1a, 0x41, 0x29, 0x47, 0x04, 0x96, + 0x31, 0x92, 0xf5, 0x23, 0xff, 0xf5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_94_ptx[] = { +/* Msg */ + 0x44, 0x32, 0x87, 0x17, 0xed, 0x47, 0x56, 0xc5, 0xd2, 0x14, 0xbf, 0x59, + 0xee, 0x71, 0xcd, 0xfb, 0xde, 0x60, 0x0e, 0x58, 0xaa, 0x8f, 0xff, 0x46, + 0xe3, 0x25, 0xc4, 0xa6, 0xee, 0xbb, 0x1c, 0x8f, 0x9f, 0xa7, 0x95, 0xa9, + 0x0a, 0x81, 0xfc, 0xd6, 0x95, 0xe0, 0x18, 0x18, 0x52, 0x65, 0x98, 0xaf, + 0x8c, 0xfb, 0x49, 0x81, 0xa0, 0x5c, 0x8c, 0xbf, 0x0e, 0xd8, 0x08, 0xc6, + 0xd0, 0x52, 0x9c, 0x43, 0xeb, 0x8b, 0x97, 0x9b, 0x43, 0xa3, 0x2c, 0x8a, + 0xb3, 0xdc, 0x20, 0x0a, 0x5d, 0xa2, 0xc6, 0x76, 0x3f, 0xc8, 0x2d, 0xef, + 0x08, 0x15, 0x98, 0xff, 0x29, 0xff, 0x2e, 0x7c, 0x2e, 0xb6, 0xf3, 0xaf, + 0x4f, 0x64, 0xf7, 0xb6, 0x42, 0xb3, 0xce, 0x27, 0x54, 0x91, 0x3f, 0xf6, + 0xb8, 0x30, 0x40, 0x99, 0x1f, 0x50, 0x23, 0x69, 0x89, 0xc0, 0x0a, 0x4c, + 0x5a, 0x22, 0xa0, 0x91, 0xb0, 0xf0, 0x0b, 0x1b +}; +static const uint8_t nist_186_2_ecdsa_testvector_94_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x53, 0xf2, 0x25, 0x5c, 0xfe, 0xd5, 0x6f, 0x12, + 0x79, 0xc9, 0xec, 0xc2, 0x3c, 0xce, 0xe7, 0x25, 0x65, 0x0d, 0x72, 0x76, + 0x99, 0x34, 0x49, 0x3e, 0x9a, 0x00 +}; +static const uint8_t nist_186_2_ecdsa_testvector_94_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x7d, 0xc7, 0x4b, 0x9d, 0x26, 0xa4, 0xce, 0x66, 0x66, 0x24, 0x1e, + 0xfd, 0xaf, 0x16, 0x9c, 0xec, 0x9b, 0x82, 0x4a, 0xf6, 0xe7, 0x06, 0xd6, + 0x56, 0x93, 0x04, 0x94, 0x5a, 0x02 +}; +static const uint8_t nist_186_2_ecdsa_testvector_94_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x09, 0x97, 0x4b, 0x20, 0xb3, 0xb4, 0x33, 0x23, 0x7f, 0xc2, 0xd8, + 0x01, 0x84, 0x84, 0xc2, 0x18, 0xa7, 0xbe, 0x9b, 0x94, 0xa3, 0x21, 0x60, + 0xd4, 0xc2, 0xa1, 0x5f, 0xdb, 0x4c +}; +/* k = 00000001c438cc6db3c3c47925f1ea6c1807a84a1f54acac4609bf1af5b */ +static const uint8_t nist_186_2_ecdsa_testvector_94_out[] = { +/* R - byte alignment */ + 0x00, 0x66, 0x6c, 0xf8, 0xed, 0x39, 0x59, 0x68, 0xf5, 0xfd, 0x1b, 0xe2, + 0x56, 0xc3, 0xc9, 0xf5, 0xe2, 0x23, 0x18, 0x40, 0x03, 0xc4, 0x77, 0xa5, + 0x20, 0xa6, 0xe3, 0x37, 0x26, 0x94, +/* S - byte alignment */ + 0x00, 0x4d, 0xca, 0xcd, 0xee, 0x85, 0x9f, 0xce, 0x43, 0x06, 0xe7, 0xa6, + 0x8b, 0x89, 0x2c, 0xb6, 0x0c, 0x36, 0x12, 0x28, 0xfd, 0x5d, 0x3d, 0x91, + 0x6e, 0xc0, 0xad, 0xb4, 0x8a, 0xa7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_95_ptx[] = { +/* Msg */ + 0xca, 0x70, 0x40, 0xfd, 0xec, 0x98, 0x5b, 0x31, 0xff, 0x8e, 0x28, 0xf7, + 0x64, 0x82, 0x2b, 0x95, 0xd4, 0x93, 0x13, 0xce, 0x99, 0x36, 0x8f, 0x63, + 0xfe, 0xdc, 0x63, 0xd9, 0x04, 0xcf, 0xbb, 0x7d, 0x56, 0x5d, 0xbf, 0xa6, + 0x7f, 0x39, 0x67, 0x3a, 0x5b, 0x1e, 0x91, 0x73, 0xcb, 0xb5, 0x51, 0xe3, + 0xad, 0xb9, 0x88, 0xb6, 0x0c, 0x59, 0xb8, 0x38, 0x93, 0xde, 0x16, 0x97, + 0x48, 0x8d, 0xe1, 0xe9, 0x77, 0xcf, 0xf3, 0x70, 0xeb, 0x8f, 0x96, 0x1d, + 0x64, 0xe4, 0x98, 0x54, 0x46, 0xf0, 0xa2, 0xef, 0x8f, 0x08, 0xc5, 0x85, + 0x0b, 0x14, 0x56, 0xec, 0xcb, 0x39, 0xfc, 0xfc, 0xd3, 0xb6, 0x07, 0x96, + 0x13, 0x0c, 0x03, 0xe5, 0x99, 0x62, 0x8d, 0xe4, 0x04, 0x27, 0x66, 0x21, + 0x3c, 0xf9, 0xc6, 0xc0, 0x60, 0xc6, 0xf3, 0xc2, 0x00, 0x31, 0x11, 0x88, + 0x8d, 0x37, 0x3c, 0x92, 0x0d, 0x12, 0xd4, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_95_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x36, 0xb1, 0x7d, 0x3a, 0x44, 0x85, 0xc8, 0x60, + 0x32, 0xa4, 0xca, 0x73, 0xdc, 0xd5, 0x04, 0x00, 0x2d, 0x89, 0x07, 0xa2, + 0x64, 0x98, 0xc4, 0xa3, 0xf3, 0xda +}; +static const uint8_t nist_186_2_ecdsa_testvector_95_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x14, 0x98, 0xc5, 0xda, 0x88, 0x68, 0x34, 0x7c, 0xc9, 0xc3, 0x50, + 0x7d, 0x5b, 0x4e, 0x53, 0x53, 0x22, 0x0e, 0x2b, 0xf0, 0xd0, 0xfd, 0x0e, + 0xfb, 0xde, 0x84, 0xc9, 0x9b, 0x65 +}; +static const uint8_t nist_186_2_ecdsa_testvector_95_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x95, 0x7f, 0x22, 0xe2, 0x8b, 0x3d, 0x17, 0xfb, 0xa8, 0x6c, 0xaa, + 0x03, 0xb5, 0xcb, 0xd3, 0x7d, 0xad, 0xb7, 0x51, 0x95, 0x98, 0xdf, 0xc6, + 0x8b, 0x38, 0xed, 0x12, 0xc4, 0x43 +}; +/* k = 000000057915cb92004afcb45505796ad55ece04dbc4228dfcbf784f1b6 */ +static const uint8_t nist_186_2_ecdsa_testvector_95_out[] = { +/* R - byte alignment */ + 0x00, 0x18, 0x2c, 0x2d, 0xfe, 0x78, 0x26, 0xc7, 0x68, 0x58, 0xb8, 0x41, + 0xbd, 0xb9, 0xbb, 0x47, 0x31, 0x1b, 0xee, 0xe3, 0x62, 0xc0, 0xdf, 0x3a, + 0xdd, 0x26, 0x8e, 0x3e, 0xd9, 0xbb, +/* S - byte alignment */ + 0x00, 0x19, 0x27, 0x58, 0x30, 0xe0, 0x7b, 0x4d, 0x7c, 0x76, 0xec, 0xf2, + 0xf7, 0x42, 0x4b, 0x06, 0x8b, 0xb9, 0x8e, 0x0c, 0x59, 0x7f, 0x76, 0x4f, + 0xa7, 0xec, 0x52, 0x5e, 0x76, 0x7f +}; +static const uint8_t nist_186_2_ecdsa_testvector_96_ptx[] = { +/* Msg */ + 0xe7, 0xde, 0x41, 0x36, 0x2e, 0x2d, 0x2a, 0x37, 0x30, 0x52, 0x74, 0x67, + 0xb5, 0xcb, 0x3a, 0xc7, 0xc5, 0x47, 0xfa, 0x26, 0x06, 0xae, 0x91, 0x45, + 0x45, 0x61, 0x66, 0x38, 0x52, 0xc3, 0xe5, 0x0f, 0x11, 0xf8, 0x2f, 0xb6, + 0xce, 0xed, 0x0f, 0x1a, 0xd1, 0x98, 0x31, 0x8d, 0x32, 0x81, 0x8e, 0x6c, + 0xef, 0x81, 0x2b, 0xff, 0x3c, 0xc9, 0x03, 0xa0, 0x1a, 0x27, 0x41, 0x20, + 0x2b, 0x85, 0xb3, 0x66, 0xc5, 0xb3, 0x7c, 0x59, 0x45, 0x66, 0x09, 0x01, + 0xa6, 0x80, 0x46, 0xe8, 0x52, 0x91, 0x11, 0xc7, 0x37, 0x9e, 0xef, 0x5e, + 0x1e, 0x22, 0xfd, 0xa4, 0x38, 0x53, 0x2a, 0x20, 0xfa, 0xa6, 0xa4, 0x97, + 0x2b, 0x95, 0x90, 0xe7, 0x3c, 0xa0, 0xfe, 0x33, 0xd7, 0x92, 0x1c, 0x40, + 0xba, 0x05, 0xa9, 0x1f, 0xc6, 0x28, 0xad, 0x0d, 0x53, 0xc0, 0x68, 0x97, + 0xc7, 0x6d, 0x88, 0x02, 0x67, 0x2f, 0x9f, 0xe9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_96_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x40, 0xc9, 0xf8, 0x81, 0x6a, 0xca, 0x2e, 0xfc, + 0xbe, 0x6d, 0xfe, 0x1a, 0xf9, 0xcc, 0x22, 0x57, 0xbc, 0x7d, 0x50, 0xde, + 0x18, 0x6e, 0xea, 0x81, 0xa7, 0x8b +}; +static const uint8_t nist_186_2_ecdsa_testvector_96_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xf4, 0x32, 0xdd, 0x0f, 0xf3, 0x5b, 0x71, 0x46, 0x19, 0x00, 0x7b, + 0x3f, 0x4e, 0xd8, 0x6c, 0x6a, 0x2a, 0x13, 0x4c, 0xf4, 0xc3, 0xbb, 0x77, + 0xfd, 0xde, 0x9f, 0xff, 0x4d, 0x18 +}; +static const uint8_t nist_186_2_ecdsa_testvector_96_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x61, 0x08, 0xe7, 0xd7, 0x5c, 0x57, 0xc2, 0xdd, 0x65, 0x6d, 0x17, + 0x9e, 0x23, 0x60, 0x81, 0x27, 0xd7, 0x0b, 0x1c, 0x58, 0xf2, 0x58, 0x2a, + 0x82, 0x85, 0x7c, 0xbf, 0xb9, 0xd8 +}; +/* k = 0000000325b8f2d8947423b268761b0544c668df4475bcd722aa1857101 */ +static const uint8_t nist_186_2_ecdsa_testvector_96_out[] = { +/* R - byte alignment */ + 0x00, 0x0e, 0x46, 0xa7, 0x3e, 0x81, 0xea, 0xdb, 0x86, 0xe0, 0x77, 0xcd, + 0x66, 0x27, 0x15, 0xcd, 0xe1, 0x8e, 0x8f, 0xee, 0x6e, 0xf9, 0xf5, 0x8e, + 0x0a, 0x5b, 0x90, 0x88, 0x91, 0x52, +/* S - byte alignment */ + 0x00, 0x2d, 0x7c, 0xa8, 0x42, 0x74, 0xd7, 0x61, 0x89, 0x6d, 0x7a, 0x1f, + 0x4b, 0xb9, 0xd7, 0x13, 0x61, 0xcd, 0x00, 0xc5, 0xcb, 0x80, 0x6a, 0xe1, + 0xb0, 0x83, 0x9b, 0xbf, 0x3c, 0x1e +}; +static const uint8_t nist_186_2_ecdsa_testvector_97_ptx[] = { +/* Msg */ + 0x4b, 0x39, 0x8c, 0x6d, 0xa9, 0x09, 0x9c, 0xf8, 0x1a, 0xc5, 0x7c, 0x61, + 0x08, 0xbf, 0x82, 0xb4, 0x20, 0x81, 0x61, 0xe6, 0x56, 0xbe, 0x51, 0x67, + 0x29, 0x88, 0x6a, 0xf6, 0x28, 0xc2, 0x51, 0xb9, 0xb5, 0xd9, 0x17, 0x8d, + 0x09, 0xaf, 0x5e, 0x9b, 0x78, 0xd8, 0xbe, 0x2c, 0xf6, 0x09, 0x67, 0xbe, + 0xdb, 0xcd, 0x07, 0x56, 0xe3, 0x7a, 0xee, 0x19, 0x79, 0x64, 0x70, 0x16, + 0x35, 0x50, 0x8a, 0x67, 0xa3, 0x2c, 0xc9, 0x78, 0x46, 0xfd, 0x68, 0xa6, + 0xdc, 0x18, 0xb8, 0x0c, 0xe4, 0x95, 0xc5, 0x99, 0x5e, 0x01, 0x37, 0x66, + 0xd2, 0x53, 0x76, 0x47, 0x93, 0x21, 0x12, 0xa1, 0x45, 0x14, 0x61, 0x7b, + 0x9d, 0x9a, 0x6a, 0xd7, 0x68, 0xda, 0x01, 0x42, 0xcf, 0xed, 0x34, 0xaa, + 0xd9, 0x4b, 0xe6, 0x70, 0x31, 0x83, 0xba, 0xbe, 0x2a, 0x30, 0x33, 0x1b, + 0x00, 0x28, 0x19, 0x3c, 0x61, 0xf6, 0x1e, 0x1d +}; +static const uint8_t nist_186_2_ecdsa_testvector_97_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x71, 0xb6, 0x27, 0x13, 0x2c, 0xc5, 0x27, 0x96, + 0x7d, 0xba, 0xf7, 0x92, 0x29, 0x03, 0x83, 0x56, 0x33, 0x2d, 0xf1, 0x4a, + 0xc6, 0xd3, 0x9b, 0x0c, 0xd3, 0xdf +}; +static const uint8_t nist_186_2_ecdsa_testvector_97_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x54, 0xc5, 0x6c, 0x17, 0x94, 0x87, 0x93, 0x75, 0xd4, 0x2f, 0xed, + 0x34, 0x65, 0xb4, 0x68, 0x28, 0xc0, 0xf6, 0x93, 0x32, 0x3b, 0xcd, 0x39, + 0x3f, 0x59, 0x9f, 0x27, 0xc5, 0xa6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_97_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x0a, 0x7a, 0xcf, 0x85, 0xe9, 0xbd, 0xff, 0xdd, 0xcf, 0xe7, 0x96, + 0xb1, 0xdb, 0xa2, 0x7c, 0xd4, 0x8c, 0x3d, 0x8a, 0xf5, 0xba, 0xea, 0xff, + 0x31, 0x7d, 0x9e, 0x58, 0x76, 0x97 +}; +/* k = 000000014c667d9fecec4fcb0c8e80c2dca83cb3919f094b1eb061180d7 */ +static const uint8_t nist_186_2_ecdsa_testvector_97_out[] = { +/* R - byte alignment */ + 0x00, 0x48, 0x1e, 0xb3, 0x29, 0xf1, 0x48, 0xb4, 0x86, 0x4c, 0xf6, 0x2b, + 0x0f, 0xc7, 0x70, 0xd5, 0x81, 0xd2, 0x4a, 0x15, 0xad, 0xb3, 0x64, 0x15, + 0x2a, 0xc5, 0xb7, 0x13, 0x32, 0x35, +/* S - byte alignment */ + 0x00, 0x23, 0x8d, 0x6a, 0x8a, 0x5e, 0x5b, 0x7d, 0x1c, 0x2c, 0x77, 0x0a, + 0x6c, 0x1e, 0x40, 0x53, 0x00, 0xb5, 0xa8, 0x9b, 0x4c, 0xad, 0x39, 0x08, + 0x6d, 0x97, 0xbb, 0x57, 0x6e, 0x19 +}; +static const uint8_t nist_186_2_ecdsa_testvector_98_ptx[] = { +/* Msg */ + 0x9f, 0xc5, 0xd8, 0x40, 0x92, 0xa9, 0x2a, 0x8b, 0x31, 0x93, 0x5c, 0x61, + 0xa5, 0x92, 0x93, 0x66, 0xd5, 0x81, 0x88, 0x7e, 0xe6, 0x80, 0x2e, 0xe0, + 0x02, 0xa5, 0x96, 0x6d, 0x59, 0xee, 0x0f, 0x3f, 0x66, 0x7a, 0x91, 0x84, + 0x74, 0xf9, 0x5c, 0x8d, 0x60, 0x62, 0xdc, 0x22, 0xa0, 0xe4, 0xd0, 0x19, + 0x84, 0x1e, 0xab, 0x27, 0xbc, 0x92, 0x3a, 0xf5, 0x1b, 0x57, 0x88, 0x76, + 0x9b, 0x0f, 0xff, 0x79, 0xa0, 0x19, 0xcf, 0x7a, 0x81, 0x08, 0x94, 0xbe, + 0x44, 0x53, 0x33, 0x9f, 0xa9, 0x4d, 0x04, 0x24, 0x6b, 0x58, 0x37, 0xd4, + 0xc2, 0x56, 0x70, 0xcc, 0x2c, 0x61, 0xb5, 0x10, 0x6d, 0xbc, 0x8a, 0x1f, + 0xd4, 0x09, 0x5a, 0xca, 0xc1, 0xbc, 0x19, 0x45, 0x64, 0xcf, 0x28, 0x7f, + 0xc7, 0xb8, 0x79, 0xaf, 0x0f, 0x98, 0xf3, 0x2f, 0xff, 0xb5, 0x18, 0x8e, + 0xbd, 0x2a, 0xe5, 0xe1, 0xd9, 0xdd, 0xf9, 0x59 +}; +static const uint8_t nist_186_2_ecdsa_testvector_98_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x13, 0x31, 0x93, 0x42, 0x62, 0x16, 0x94, 0xf3, + 0xaa, 0x5f, 0x90, 0xd2, 0x8c, 0xd5, 0x4c, 0x4d, 0x82, 0x5b, 0xf9, 0x01, + 0x7f, 0x35, 0x91, 0xc4, 0x30, 0x26 +}; +static const uint8_t nist_186_2_ecdsa_testvector_98_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xd3, 0x35, 0x12, 0x91, 0xe1, 0xbe, 0xfd, 0x05, 0x1b, 0x6e, 0x84, + 0xdd, 0x72, 0xf1, 0xe5, 0x87, 0xf7, 0xe0, 0x5c, 0xc8, 0x9a, 0xb0, 0x19, + 0x57, 0xea, 0xc9, 0x97, 0xb2, 0xb4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_98_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x9c, 0x49, 0x2f, 0x3e, 0x35, 0x24, 0xd9, 0x28, 0x8e, 0xe6, 0x1c, + 0x8e, 0x64, 0xa3, 0xf3, 0x21, 0x48, 0x90, 0x19, 0xa2, 0x71, 0x15, 0xda, + 0x34, 0xab, 0x6b, 0xde, 0x30, 0x99 +}; +/* k = 0000000095a7927a0389b06597f60703194fb6c3ff7493aa3e7b5aeb1da */ +static const uint8_t nist_186_2_ecdsa_testvector_98_out[] = { +/* R - byte alignment */ + 0x00, 0x4c, 0xbd, 0xfc, 0x77, 0xdc, 0x32, 0x19, 0xad, 0x89, 0x32, 0xe3, + 0x54, 0xc0, 0xdc, 0xf1, 0xc6, 0x52, 0xef, 0x31, 0x70, 0x70, 0xa3, 0x19, + 0x6f, 0x8c, 0x65, 0x42, 0x54, 0x8c, +/* S - byte alignment */ + 0x00, 0x04, 0x7c, 0x14, 0xc9, 0xc4, 0xd0, 0x05, 0xbb, 0xae, 0x11, 0x00, + 0x41, 0xfd, 0xfe, 0x82, 0x25, 0x61, 0x51, 0x39, 0x84, 0x24, 0xe9, 0x41, + 0x84, 0xda, 0xf6, 0x13, 0x2c, 0x82 +}; +static const uint8_t nist_186_2_ecdsa_testvector_99_ptx[] = { +/* Msg */ + 0x24, 0x05, 0x89, 0x34, 0x7a, 0x03, 0xca, 0x00, 0xac, 0xed, 0xd2, 0xdc, + 0x7f, 0x7e, 0x3b, 0x88, 0x04, 0x98, 0x34, 0x0a, 0x78, 0x93, 0x82, 0xa2, + 0x68, 0xd5, 0xc5, 0x00, 0x18, 0xa2, 0xfd, 0xb5, 0x26, 0x36, 0x4c, 0xe8, + 0x6b, 0x11, 0xfe, 0x4a, 0x22, 0x93, 0xc6, 0x4c, 0x4c, 0xc8, 0x4a, 0x8f, + 0x53, 0x85, 0xe2, 0x9b, 0xed, 0xb4, 0x9d, 0xd5, 0x43, 0xec, 0x86, 0xab, + 0x53, 0x45, 0x25, 0x12, 0x92, 0x6a, 0x48, 0x32, 0xd6, 0xef, 0x03, 0x5f, + 0x74, 0xe5, 0xf5, 0x4c, 0xa5, 0xac, 0xcd, 0x7b, 0x2f, 0x09, 0x0d, 0xf8, + 0x41, 0x78, 0x0e, 0x47, 0x9e, 0xc4, 0x44, 0x9b, 0xfd, 0xd4, 0xc4, 0x49, + 0xb0, 0xc8, 0x03, 0x7b, 0x85, 0x45, 0xe1, 0x29, 0xea, 0x0c, 0xe6, 0x45, + 0x54, 0xd2, 0xcb, 0x36, 0xe1, 0x4c, 0x3c, 0x88, 0x3c, 0x89, 0xdc, 0xe2, + 0xc1, 0x84, 0x8a, 0x38, 0xe1, 0xfa, 0xe3, 0x41 +}; +static const uint8_t nist_186_2_ecdsa_testvector_99_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x55, 0x12, 0xcb, 0x10, 0x56, 0x46, 0x8e, 0xa7, + 0x82, 0x22, 0xc2, 0xca, 0xd6, 0x7c, 0xb0, 0x59, 0xc0, 0xbe, 0x34, 0x26, + 0x82, 0x20, 0x24, 0x3f, 0xa5, 0xee +}; +static const uint8_t nist_186_2_ecdsa_testvector_99_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x2b, 0x21, 0xb8, 0xce, 0x38, 0x27, 0x60, 0x02, 0x03, 0x9d, 0xfa, + 0x33, 0xd3, 0xfe, 0xea, 0xa6, 0xc5, 0x3b, 0x74, 0xa8, 0x0f, 0x0f, 0xcf, + 0x8d, 0xc9, 0xfd, 0x79, 0xe3, 0x89 +}; +static const uint8_t nist_186_2_ecdsa_testvector_99_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x89, 0x47, 0xf6, 0xa0, 0x01, 0x61, 0xb8, 0xa6, 0x4a, 0xb2, 0x88, + 0x2f, 0x8d, 0x00, 0xd4, 0xa5, 0xe4, 0xf4, 0x1f, 0x22, 0x2e, 0xc7, 0x72, + 0x8c, 0x6a, 0x01, 0x66, 0x56, 0x26 +}; +/* k = 000000072670f9c6948a6e0f8f3b3b84fba3511ae360a7af745a885671d */ +static const uint8_t nist_186_2_ecdsa_testvector_99_out[] = { +/* R - byte alignment */ + 0x00, 0x5c, 0x77, 0xee, 0xe6, 0x2d, 0xad, 0x21, 0x8f, 0x7e, 0x94, 0xc9, + 0x43, 0x86, 0xcc, 0xaf, 0x16, 0xfc, 0x3e, 0x33, 0x4e, 0xac, 0x7c, 0x2c, + 0x7d, 0x7f, 0x9d, 0x60, 0x36, 0xf3, +/* S - byte alignment */ + 0x00, 0x55, 0x8f, 0x88, 0xe2, 0xf3, 0x48, 0xe4, 0xa4, 0xd5, 0xb1, 0x4c, + 0x05, 0xf5, 0x32, 0xb1, 0x28, 0x3e, 0x7a, 0x05, 0xe5, 0x9e, 0xf2, 0xc8, + 0xd2, 0xa3, 0xd4, 0xe4, 0xa6, 0xc8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_100_ptx[] = { +/* Msg */ + 0x07, 0xde, 0xe1, 0x2f, 0x72, 0x94, 0x1e, 0xa3, 0xdc, 0x45, 0x7c, 0x70, + 0xf7, 0xae, 0x59, 0xd7, 0x13, 0xaa, 0xaf, 0x2f, 0x37, 0xf9, 0xd3, 0xcf, + 0x70, 0x41, 0x63, 0x2e, 0x69, 0x52, 0x79, 0x49, 0x3c, 0xae, 0x25, 0x45, + 0x88, 0x49, 0x1b, 0x56, 0xc4, 0x8d, 0xa8, 0xdf, 0xd2, 0xa1, 0xeb, 0xdb, + 0xd7, 0xeb, 0x41, 0x7b, 0x4b, 0xd4, 0x01, 0x10, 0x4c, 0xcb, 0x6a, 0x2c, + 0x38, 0x8c, 0xd9, 0x04, 0x7a, 0xa2, 0x3f, 0x19, 0xa4, 0x2a, 0xd3, 0x18, + 0xbf, 0xdb, 0x04, 0xfe, 0xde, 0x43, 0xb2, 0x7f, 0xfa, 0x53, 0x9d, 0xa9, + 0xf9, 0x1e, 0x1e, 0xc5, 0x10, 0xde, 0x15, 0x7e, 0x4b, 0x38, 0x22, 0x45, + 0x6a, 0xc1, 0x18, 0xf3, 0xef, 0xc0, 0xae, 0xb0, 0x75, 0x36, 0x78, 0x14, + 0x43, 0x1b, 0x16, 0x8d, 0x21, 0xeb, 0xac, 0x01, 0x6b, 0x61, 0x92, 0xb4, + 0x63, 0x82, 0x4c, 0x6b, 0xcb, 0xde, 0xbc, 0xd2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_100_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x47, 0xbc, 0x59, 0xbd, 0x9d, 0x2f, 0xb5, 0xb2, + 0x95, 0x6d, 0x9d, 0x54, 0xc8, 0x98, 0xac, 0x70, 0x05, 0x55, 0x9a, 0x16, + 0xb0, 0x60, 0xde, 0x4a, 0xd2, 0xe6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_100_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xe9, 0xa7, 0xf6, 0xab, 0xe2, 0x72, 0xee, 0xbf, 0xbc, 0x85, 0x12, + 0xe7, 0x2d, 0x17, 0xfe, 0x92, 0x2b, 0x58, 0xc6, 0x51, 0x8a, 0xe7, 0xf8, + 0x9f, 0x76, 0x28, 0x06, 0x10, 0x61 +}; +static const uint8_t nist_186_2_ecdsa_testvector_100_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x22, 0x60, 0xab, 0xa4, 0x24, 0x41, 0x71, 0x0b, 0x54, 0xc1, 0x77, + 0xd2, 0x47, 0xc6, 0x1d, 0xd9, 0x5c, 0xaf, 0x2c, 0xde, 0x1d, 0x12, 0x90, + 0x5e, 0x3c, 0xf3, 0x8a, 0x32, 0xc9 +}; +/* k = 0000000524234bf1ea81de91d3a69a9c9f5eef0e429d7b2304f45bf60d6 */ +static const uint8_t nist_186_2_ecdsa_testvector_100_out[] = { +/* R - byte alignment */ + 0x00, 0x7f, 0xb3, 0xa7, 0x8f, 0x41, 0x6f, 0x16, 0x25, 0x35, 0x0c, 0x1b, + 0x96, 0xfd, 0x53, 0x8a, 0x74, 0x5f, 0x9b, 0x3e, 0xc7, 0xb5, 0x0f, 0xb5, + 0xf0, 0x18, 0x27, 0xd4, 0x62, 0x93, +/* S - byte alignment */ + 0x00, 0x4a, 0x61, 0xe8, 0xb4, 0xbd, 0x50, 0xf2, 0x62, 0x3a, 0xb8, 0xa8, + 0xd6, 0x7c, 0xc3, 0x15, 0xb5, 0x1c, 0x70, 0xde, 0x29, 0xa7, 0x14, 0x01, + 0x18, 0x2e, 0xb7, 0x15, 0xac, 0x99 +}; +static const uint8_t nist_186_2_ecdsa_testvector_101_ptx[] = { +/* Msg */ + 0x4d, 0x2f, 0xb9, 0xb7, 0x5a, 0x4f, 0xc7, 0x83, 0x52, 0x92, 0xbf, 0xa1, + 0x2e, 0x9d, 0xfd, 0x07, 0xda, 0x3d, 0x6d, 0x04, 0x3a, 0x59, 0xab, 0xd4, + 0x6b, 0x25, 0x69, 0x72, 0x4b, 0x99, 0x12, 0xad, 0x3b, 0x22, 0xac, 0x7e, + 0x23, 0x97, 0x03, 0x99, 0xb7, 0x6e, 0x04, 0x42, 0xf9, 0x30, 0x67, 0x62, + 0xff, 0x2a, 0x91, 0xda, 0xf7, 0x66, 0xb8, 0x17, 0x68, 0xd9, 0x48, 0xe6, + 0xbb, 0xde, 0x85, 0x8a, 0xf9, 0xe3, 0x72, 0x0d, 0xd6, 0x62, 0xf2, 0xd3, + 0xef, 0x14, 0x2e, 0x75, 0x50, 0x61, 0x36, 0xcc, 0x39, 0x1a, 0xeb, 0x4b, + 0x22, 0x6a, 0x1c, 0x92, 0xfc, 0x0a, 0xef, 0x41, 0xba, 0xb5, 0x83, 0x0a, + 0x10, 0xdc, 0xd3, 0x0b, 0x7a, 0x9a, 0xde, 0x5a, 0x81, 0xea, 0x05, 0xe1, + 0x3a, 0x18, 0xb4, 0x6c, 0x0f, 0x75, 0x44, 0x00, 0xc1, 0x4f, 0x20, 0x6f, + 0xae, 0x20, 0x27, 0x29, 0x50, 0x06, 0x52, 0x55 +}; +static const uint8_t nist_186_2_ecdsa_testvector_101_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x4a, 0x54, 0xeb, 0xe2, 0x0a, 0x0d, 0x5f, 0x31, + 0x03, 0x76, 0x63, 0x66, 0x3a, 0xa5, 0xbb, 0x62, 0x82, 0x49, 0x92, 0xd9, + 0x49, 0xea, 0xce, 0xc5, 0xfd, 0xcb +}; +static const uint8_t nist_186_2_ecdsa_testvector_101_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x28, 0x97, 0xe3, 0x6d, 0x2a, 0x25, 0xe2, 0x3f, 0x01, 0x1a, 0x20, + 0xb7, 0xfd, 0xf5, 0xb4, 0x94, 0x9d, 0x70, 0xd6, 0xb2, 0x87, 0xaf, 0x45, + 0xad, 0x53, 0x4b, 0x90, 0x38, 0xfa +}; +static const uint8_t nist_186_2_ecdsa_testvector_101_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x0d, 0x38, 0x8f, 0x45, 0x7f, 0x2b, 0x2d, 0xf0, 0xf8, 0x61, 0x3e, + 0x9b, 0x57, 0x1f, 0xf0, 0x51, 0xc3, 0x12, 0xf1, 0x1a, 0xe0, 0x9a, 0x20, + 0x03, 0x8d, 0x08, 0x98, 0x46, 0xbc +}; +/* k = 00000000750665d8bd56f486fd2627689719630e89671455caeaad89c34 */ +static const uint8_t nist_186_2_ecdsa_testvector_101_out[] = { +/* R - byte alignment */ + 0x00, 0x27, 0xa0, 0xda, 0xd7, 0x5d, 0x50, 0x4a, 0x7a, 0xdb, 0xbd, 0xd2, + 0x47, 0xd8, 0x0e, 0xb0, 0x51, 0xc7, 0xb8, 0x84, 0xf4, 0xec, 0xd5, 0x53, + 0x7a, 0xba, 0x2f, 0x59, 0xef, 0x57, +/* S - byte alignment */ + 0x00, 0x77, 0x20, 0x86, 0x7f, 0x79, 0x76, 0x9d, 0x27, 0xc8, 0x2e, 0x2f, + 0x1f, 0x3e, 0x19, 0x0f, 0xbd, 0xf9, 0xcd, 0xe2, 0x86, 0x35, 0xa8, 0x56, + 0x4b, 0x25, 0x63, 0x16, 0x79, 0x6b +}; +static const uint8_t nist_186_2_ecdsa_testvector_102_ptx[] = { +/* Msg */ + 0x96, 0x16, 0xdf, 0x5b, 0x4f, 0x67, 0xb5, 0xb9, 0xd2, 0x47, 0x18, 0xc6, + 0x4b, 0x44, 0x2e, 0xa0, 0xa9, 0x9c, 0x0a, 0x9c, 0x47, 0x53, 0x75, 0xf0, + 0xcc, 0x82, 0xee, 0xaf, 0x50, 0xf2, 0xef, 0xfb, 0xc0, 0xe9, 0x72, 0x76, + 0x83, 0x44, 0xb4, 0xf9, 0x5d, 0xc6, 0x39, 0x89, 0x94, 0xb0, 0x10, 0x86, + 0x52, 0x92, 0x58, 0x26, 0x4b, 0x60, 0x03, 0x22, 0x9f, 0xc8, 0xda, 0xaf, + 0x02, 0xc3, 0xc1, 0xb0, 0x1a, 0x6b, 0x3d, 0x2a, 0x28, 0x0c, 0x33, 0xf8, + 0xeb, 0x7d, 0xf3, 0xc0, 0xc2, 0xb1, 0x74, 0x25, 0x10, 0x89, 0xe1, 0x3e, + 0xe4, 0xec, 0x55, 0x47, 0xda, 0x1a, 0xe4, 0x97, 0x3c, 0x3d, 0xda, 0xd2, + 0x6d, 0x42, 0x47, 0x60, 0x88, 0xe6, 0xbb, 0x1e, 0x44, 0x14, 0x4e, 0x53, + 0x1b, 0x6e, 0xe3, 0xe5, 0xab, 0x2a, 0xae, 0xcd, 0x5c, 0x1f, 0xf4, 0xc8, + 0x43, 0x1f, 0x12, 0x4f, 0x46, 0x88, 0xc1, 0xca +}; +static const uint8_t nist_186_2_ecdsa_testvector_102_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x2a, 0xa6, 0xc4, 0x61, 0xf8, 0xb0, 0xf5, 0x0f, + 0xf7, 0x21, 0xcc, 0x0f, 0x77, 0x3e, 0xcc, 0x19, 0x9f, 0x51, 0xcb, 0xb0, + 0x72, 0xc8, 0xb8, 0xba, 0x39, 0x2e +}; +static const uint8_t nist_186_2_ecdsa_testvector_102_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xaa, 0x8e, 0x0d, 0x74, 0x8d, 0x2d, 0x3d, 0xe4, 0xe8, 0x64, 0x14, + 0x9f, 0x32, 0xe2, 0xd7, 0xaf, 0x95, 0x1a, 0xe9, 0x63, 0x7c, 0x46, 0xdb, + 0xfa, 0xd8, 0x78, 0x24, 0x66, 0xae +}; +static const uint8_t nist_186_2_ecdsa_testvector_102_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x4a, 0xd6, 0xf2, 0x18, 0x6a, 0xec, 0x78, 0xcc, 0x79, 0x84, 0x79, + 0x5d, 0x5b, 0x9f, 0x5e, 0x1e, 0xe7, 0x0d, 0xe4, 0x3a, 0x53, 0x67, 0x0e, + 0x6d, 0x28, 0xa5, 0x36, 0x25, 0x55 +}; +/* k = 00000007a73a1ed4c2700b4cbb0beea6c4f5f7721fe00b0d2cdefd62e5c */ +static const uint8_t nist_186_2_ecdsa_testvector_102_out[] = { +/* R - byte alignment */ + 0x00, 0x3c, 0x50, 0xaf, 0x64, 0xac, 0x35, 0x69, 0x68, 0xd1, 0xc8, 0xde, + 0x2b, 0x4e, 0x13, 0xe7, 0x76, 0xb5, 0xd4, 0xa6, 0x83, 0x41, 0x06, 0xe6, + 0xa8, 0x10, 0x77, 0x2f, 0xe2, 0x75, +/* S - byte alignment */ + 0x00, 0x1b, 0x68, 0x89, 0x7e, 0x67, 0x25, 0x87, 0xa6, 0x8c, 0x43, 0xae, + 0xa6, 0x04, 0x4a, 0x09, 0x72, 0x77, 0x3c, 0x4e, 0xd5, 0xfe, 0xe3, 0xfd, + 0xd5, 0xfb, 0x49, 0xc3, 0x33, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_103_ptx[] = { +/* Msg */ + 0xda, 0xd1, 0x2a, 0xcf, 0x81, 0x77, 0x9f, 0x7e, 0x90, 0x3b, 0xc6, 0xec, + 0xd7, 0xf7, 0x24, 0x60, 0x0e, 0xd1, 0x53, 0xdb, 0xc9, 0x62, 0x9b, 0x55, + 0xa8, 0x18, 0xc2, 0x4a, 0xce, 0xd8, 0x24, 0x75, 0x95, 0xe8, 0x06, 0xdc, + 0x80, 0x0d, 0x27, 0x0c, 0x72, 0xf0, 0x98, 0xa6, 0x1d, 0xc6, 0xce, 0x1a, + 0xbc, 0x30, 0xf6, 0xb3, 0x05, 0x60, 0x88, 0xd4, 0x59, 0x7e, 0x1f, 0x81, + 0x3f, 0x4a, 0x88, 0x20, 0x10, 0x02, 0x18, 0x81, 0xf4, 0x86, 0x43, 0x1d, + 0x0c, 0xba, 0x6b, 0x9b, 0xf1, 0x2c, 0xf6, 0x99, 0x5e, 0xf7, 0xa3, 0xa8, + 0x29, 0xe7, 0x1e, 0x98, 0x78, 0xdd, 0xd2, 0xf7, 0x31, 0x75, 0xfe, 0xd4, + 0xb2, 0xe7, 0x0b, 0xc8, 0xc3, 0x2b, 0x1d, 0x38, 0xc8, 0x61, 0xe8, 0xd4, + 0x3c, 0x6f, 0xc5, 0x63, 0x5a, 0xec, 0x04, 0xc3, 0x1d, 0x3d, 0x84, 0x2b, + 0x6b, 0xfd, 0x82, 0xb4, 0x8d, 0xa3, 0xaf, 0x18 +}; +static const uint8_t nist_186_2_ecdsa_testvector_103_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x67, 0x4f, 0xd6, 0x30, 0x51, 0x76, 0x9b, 0x32, + 0x1d, 0x74, 0x56, 0x4c, 0x0b, 0xc9, 0xde, 0x95, 0x84, 0x38, 0xe1, 0x3f, + 0xdd, 0xb4, 0xf8, 0xa9, 0x51, 0x71 +}; +static const uint8_t nist_186_2_ecdsa_testvector_103_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x01, 0x9e, 0xfa, 0x37, 0x20, 0x62, 0xa1, 0x5e, 0x62, 0xd4, 0x84, + 0x85, 0x31, 0xf6, 0xf2, 0xe3, 0xcc, 0x37, 0x4c, 0xea, 0x5b, 0x01, 0x03, + 0x44, 0xb4, 0x05, 0xa0, 0xbe, 0x37 +}; +static const uint8_t nist_186_2_ecdsa_testvector_103_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x02, 0x8a, 0x9b, 0xd5, 0xef, 0xad, 0xbb, 0xe9, 0xc2, 0x32, 0x35, + 0x6f, 0x93, 0x10, 0xeb, 0xd5, 0x0d, 0x54, 0xcb, 0x34, 0x9e, 0xf7, 0x0c, + 0x72, 0x37, 0xdf, 0xc3, 0x55, 0xd4 +}; +/* k = 00000001f92d4ce1bc35799bd39adf7613ca26088c659f80426a21014db */ +static const uint8_t nist_186_2_ecdsa_testvector_103_out[] = { +/* R - byte alignment */ + 0x00, 0x1d, 0x26, 0xcc, 0xdb, 0xa5, 0xca, 0x39, 0x7e, 0x73, 0xcf, 0x7c, + 0x8e, 0x35, 0x7e, 0x9a, 0xd8, 0x7c, 0x4f, 0xda, 0x86, 0x6d, 0x87, 0x23, + 0x63, 0x23, 0xb8, 0x9c, 0xeb, 0x82, +/* S - byte alignment */ + 0x00, 0x69, 0xf0, 0xa5, 0xf2, 0x86, 0x53, 0xbf, 0x40, 0x08, 0x43, 0x8e, + 0xbf, 0x19, 0x50, 0xd9, 0x39, 0xe4, 0xdb, 0x9c, 0x53, 0x08, 0xde, 0xdd, + 0x29, 0x1e, 0x8d, 0x61, 0xa3, 0x2a +}; +static const uint8_t nist_186_2_ecdsa_testvector_104_ptx[] = { +/* Msg */ + 0x56, 0xc8, 0x64, 0xa8, 0xc4, 0x25, 0x91, 0x96, 0xe0, 0x66, 0x57, 0xe8, + 0x3b, 0x9f, 0x0a, 0xf3, 0xe7, 0x6f, 0x5d, 0xf3, 0x44, 0x85, 0xd2, 0xaa, + 0x17, 0x63, 0x75, 0x4a, 0xdc, 0x62, 0xca, 0x95, 0x5e, 0xf7, 0x04, 0x43, + 0x84, 0x34, 0x77, 0xa4, 0x6e, 0x92, 0x50, 0x86, 0xc0, 0xed, 0x84, 0x59, + 0x3e, 0xd0, 0x06, 0x91, 0x9a, 0xf3, 0x3d, 0x4c, 0x89, 0x02, 0xb5, 0x35, + 0x1c, 0xa0, 0x15, 0xa8, 0x4e, 0xac, 0x51, 0x17, 0xda, 0xc3, 0x20, 0xac, + 0x4f, 0x06, 0xb1, 0x2f, 0x65, 0x1d, 0x99, 0x2b, 0x92, 0x7c, 0x11, 0x4c, + 0xd9, 0xe4, 0x5e, 0x0c, 0xe3, 0x2d, 0x90, 0x8e, 0x50, 0x44, 0x6f, 0xca, + 0x4f, 0x70, 0xb3, 0xeb, 0x6c, 0xd9, 0x73, 0xf5, 0xaa, 0x4a, 0xe0, 0xab, + 0xd2, 0x36, 0x33, 0xb0, 0x0a, 0xf9, 0xe4, 0xec, 0xa9, 0x61, 0x1d, 0x31, + 0x4a, 0x6d, 0x6e, 0x1f, 0x20, 0x54, 0xc2, 0x45 +}; +static const uint8_t nist_186_2_ecdsa_testvector_104_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x10, 0x5e, 0xc1, 0x55, 0xc1, 0x53, 0xc2, 0xae, + 0x7b, 0xb9, 0xf6, 0xdb, 0xa5, 0xd3, 0x01, 0x6a, 0x3d, 0x44, 0xae, 0x80, + 0x03, 0x55, 0x40, 0xce, 0xa9, 0xf4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_104_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x7c, 0x13, 0x91, 0x21, 0xbe, 0x81, 0xda, 0x9a, 0xb4, 0xf9, 0x28, + 0xb7, 0xd5, 0xd9, 0x06, 0x46, 0x8b, 0x76, 0x84, 0xa1, 0x1e, 0x14, 0x14, + 0xf3, 0x45, 0x90, 0x01, 0x15, 0x4b +}; +static const uint8_t nist_186_2_ecdsa_testvector_104_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x9d, 0x05, 0x50, 0x8f, 0x18, 0x00, 0x93, 0x1b, 0x03, 0xdd, 0x29, + 0x0a, 0x9c, 0x74, 0xc4, 0x7e, 0xd4, 0x3a, 0x0b, 0x47, 0x9d, 0x55, 0x84, + 0xd9, 0xbf, 0xfc, 0x2b, 0xca, 0x32 +}; +/* k = 0000000195eeed8137349bb0ae8c941ca8a6fe0dbdf4cacac9a28507c95 */ +static const uint8_t nist_186_2_ecdsa_testvector_104_out[] = { +/* R - byte alignment */ + 0x00, 0x49, 0x17, 0x29, 0xe9, 0x92, 0x91, 0x68, 0x4d, 0xc8, 0x75, 0xf1, + 0x80, 0x1d, 0xda, 0x25, 0xa9, 0x97, 0xe9, 0x89, 0x44, 0x54, 0x15, 0xd0, + 0xf7, 0x4f, 0xc8, 0xab, 0xe7, 0x7b, +/* S - byte alignment */ + 0x00, 0x7b, 0x28, 0x90, 0x2f, 0x9f, 0x6c, 0x9d, 0x35, 0xde, 0x0f, 0x1b, + 0x3a, 0xd1, 0xff, 0x1a, 0x60, 0xee, 0xc2, 0x3a, 0x0e, 0x8d, 0x5c, 0x8b, + 0xa4, 0x7b, 0xf2, 0x4e, 0x5e, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_105_ptx[] = { +/* Msg */ + 0x75, 0x8f, 0x26, 0xa0, 0xa2, 0xbd, 0xb5, 0xe5, 0x3e, 0xea, 0x6c, 0x43, + 0xdb, 0x2c, 0x9a, 0x1d, 0x61, 0x9c, 0x84, 0xf3, 0x61, 0x59, 0x5a, 0x86, + 0xa5, 0xd0, 0x6a, 0x3d, 0x0c, 0x3a, 0x94, 0xc8, 0x95, 0x65, 0xfe, 0x03, + 0xb9, 0xb8, 0x09, 0x1d, 0xfe, 0x72, 0x83, 0xf9, 0xc9, 0x32, 0x1e, 0xd4, + 0x73, 0xbc, 0x20, 0x29, 0xa0, 0xfa, 0x5d, 0xd1, 0xcc, 0x41, 0x62, 0x6f, + 0x27, 0xd6, 0xf4, 0x0b, 0xa3, 0xb1, 0xb9, 0xfd, 0x4b, 0x80, 0x34, 0x0d, + 0xd6, 0xef, 0xf7, 0xd8, 0x7c, 0x27, 0x13, 0x76, 0x08, 0x94, 0xd4, 0x59, + 0x2f, 0xec, 0xab, 0x78, 0x20, 0x6d, 0x6c, 0xad, 0x5c, 0x66, 0xb9, 0x5c, + 0xc8, 0xf8, 0xbe, 0x56, 0x00, 0x1e, 0x20, 0xfd, 0xef, 0xeb, 0x2f, 0xa8, + 0x9d, 0x13, 0x63, 0x49, 0x47, 0xad, 0x06, 0x4d, 0xb5, 0x37, 0x2e, 0xc3, + 0xc8, 0xdb, 0xee, 0xc1, 0x53, 0xf0, 0xcd, 0x03 +}; +static const uint8_t nist_186_2_ecdsa_testvector_105_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x10, 0x64, 0x52, 0xe5, 0xca, 0x45, 0x76, 0xad, + 0x01, 0x52, 0x29, 0xdf, 0x08, 0xc3, 0xf2, 0xff, 0xdb, 0x58, 0x90, 0x4b, + 0xa8, 0x92, 0x3c, 0xf3, 0x50, 0xd4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_105_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x2b, 0x7c, 0xd9, 0x24, 0xc4, 0x41, 0x00, 0x39, 0x5f, 0x23, 0x90, + 0x68, 0x99, 0x24, 0x76, 0x3d, 0x59, 0x74, 0x99, 0xe0, 0xcb, 0x4e, 0x15, + 0xc7, 0x8e, 0x80, 0x7f, 0xca, 0x02 +}; +static const uint8_t nist_186_2_ecdsa_testvector_105_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x32, 0xd2, 0xd4, 0xae, 0x07, 0xdd, 0x7e, 0x6c, 0xc9, 0xe6, 0xf6, + 0x59, 0x18, 0xd6, 0x49, 0xfe, 0xe9, 0x8b, 0x08, 0xe2, 0xd8, 0x97, 0x9b, + 0xe8, 0x87, 0x58, 0x5c, 0x0f, 0xe1 +}; +/* k = 00000000f1f9a014d98bc3729a23f74820c2395cfba1ff7cf767af47573 */ +static const uint8_t nist_186_2_ecdsa_testvector_105_out[] = { +/* R - byte alignment */ + 0x00, 0x51, 0x82, 0x91, 0x4d, 0x54, 0x5b, 0xc8, 0xb5, 0x21, 0xba, 0x6c, + 0x92, 0xa4, 0x92, 0x4c, 0x18, 0x05, 0x35, 0xf0, 0x9a, 0x9c, 0xd0, 0xdd, + 0x22, 0xd5, 0xa5, 0xe4, 0x28, 0x89, +/* S - byte alignment */ + 0x00, 0x76, 0x42, 0xf4, 0xf1, 0x3b, 0xca, 0xe9, 0xa2, 0x7a, 0x47, 0xa8, + 0x63, 0xc8, 0x45, 0xd3, 0x39, 0x53, 0x17, 0x55, 0xc9, 0x5b, 0x27, 0x83, + 0xf9, 0x81, 0xa2, 0x12, 0xaa, 0x1b +}; +/* [K-283] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_106_ptx[] = { +/* Msg */ + 0xf0, 0x6b, 0x64, 0x2f, 0xdb, 0x21, 0x1d, 0xad, 0xa7, 0x2e, 0xea, 0xae, + 0xa5, 0x6c, 0xc7, 0x93, 0xc7, 0xd7, 0x50, 0xd3, 0xb2, 0x4f, 0x79, 0xe5, + 0x15, 0x9a, 0x7f, 0x61, 0x39, 0xa9, 0x1f, 0x62, 0xda, 0x1c, 0x05, 0x2e, + 0x36, 0x08, 0x87, 0x19, 0x63, 0xf7, 0x93, 0xa6, 0xe5, 0x30, 0xe6, 0xf0, + 0x80, 0x39, 0x7f, 0x48, 0x4b, 0x9b, 0x54, 0x20, 0x06, 0xe5, 0x43, 0x28, + 0xad, 0xf3, 0x4b, 0xb6, 0x4d, 0x70, 0xfc, 0x6b, 0x17, 0x9a, 0x2c, 0x14, + 0xb3, 0x45, 0xec, 0xce, 0xd7, 0x23, 0xbb, 0x6e, 0x17, 0x42, 0xf9, 0x1f, + 0xff, 0xd6, 0x9e, 0x4d, 0x5f, 0x39, 0x2b, 0xc2, 0xe6, 0x30, 0xe1, 0x0f, + 0xf2, 0x70, 0x31, 0x2e, 0xa7, 0x61, 0x75, 0x65, 0x3f, 0x21, 0xdd, 0x6d, + 0xa0, 0xcc, 0xac, 0xd4, 0x34, 0xfb, 0xa4, 0xa0, 0xf5, 0x8a, 0xbe, 0x35, + 0xc7, 0x9f, 0x1f, 0x79, 0x0b, 0xe7, 0x48, 0x35 +}; +static const uint8_t nist_186_2_ecdsa_testvector_106_private[] = { +/* d - byte alignment */ + 0x00, 0x5b, 0xa8, 0x71, 0x21, 0x9b, 0xd8, 0x03, 0x5f, 0xfe, 0x4f, 0xca, + 0xfd, 0x38, 0x1f, 0x38, 0x02, 0x73, 0x46, 0x97, 0x00, 0xdb, 0x81, 0xb4, + 0xb3, 0xab, 0x35, 0xe9, 0xe8, 0x82, 0x8b, 0x22, 0x7b, 0x97, 0x58, 0x7f +}; +static const uint8_t nist_186_2_ecdsa_testvector_106_public_x[] = { +/* Qx - byte alignment */ + 0x02, 0xac, 0x04, 0xf2, 0xa3, 0xfc, 0x49, 0x91, 0x2b, 0x16, 0x67, 0x75, + 0xe6, 0xb2, 0x37, 0x15, 0x11, 0x64, 0xe9, 0x38, 0x11, 0x25, 0x76, 0x5c, + 0x51, 0x2c, 0x4c, 0x23, 0x12, 0x21, 0xaa, 0x22, 0x13, 0x1a, 0xb7, 0xec +}; +static const uint8_t nist_186_2_ecdsa_testvector_106_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x5c, 0x18, 0x36, 0x2b, 0xb4, 0x6d, 0x48, 0x68, 0x3d, 0x14, 0xfe, + 0xb3, 0xd0, 0x07, 0x88, 0xec, 0x13, 0xe2, 0xf4, 0xcb, 0xc2, 0x1e, 0x09, + 0x4a, 0x76, 0xc1, 0x18, 0x3f, 0x0d, 0xb0, 0x0e, 0x52, 0x92, 0xb9, 0x38 +}; +/* k = 0f291f9fd39310ecbd8e6067e82f4d18c3b35a081d9ce2fb9d9f5847f80afd5074f76eb */ +static const uint8_t nist_186_2_ecdsa_testvector_106_out[] = { +/* R - byte alignment */ + 0x00, 0xc1, 0xf8, 0xd8, 0x6e, 0xf4, 0x95, 0x78, 0x28, 0xab, 0x0a, 0xf8, + 0x9a, 0x18, 0x2c, 0x54, 0x95, 0xd6, 0x4f, 0xb4, 0xb9, 0x16, 0x46, 0xb7, + 0x82, 0x4c, 0x41, 0x9b, 0x7c, 0x92, 0xe6, 0x87, 0xd7, 0x6b, 0x88, 0xf3, +/* S - byte alignment */ + 0x00, 0x66, 0x79, 0x13, 0xe0, 0xcb, 0x09, 0xfe, 0x65, 0x65, 0xac, 0x5a, + 0x27, 0xe6, 0x85, 0xc1, 0x76, 0x99, 0xcd, 0xaf, 0x44, 0x3d, 0xe3, 0xfb, + 0xb6, 0x53, 0x77, 0x4f, 0xe2, 0x63, 0xb2, 0xed, 0xba, 0x0d, 0xac, 0xa3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_107_ptx[] = { +/* Msg */ + 0xd8, 0xf7, 0xf3, 0xe9, 0x79, 0xdf, 0x1c, 0x0a, 0x81, 0xcc, 0x8c, 0x58, + 0xfd, 0x62, 0xe2, 0x44, 0xad, 0x38, 0xf1, 0xa7, 0x13, 0x95, 0x71, 0xa9, + 0xca, 0x77, 0xf3, 0xe3, 0x19, 0xda, 0x1b, 0xc0, 0xc8, 0x36, 0x09, 0x29, + 0x32, 0x4a, 0x18, 0x61, 0x9c, 0x18, 0xcb, 0x2d, 0xc5, 0x31, 0x04, 0x39, + 0xbe, 0x32, 0x77, 0xb7, 0xfc, 0x8f, 0x5f, 0x49, 0xac, 0x8f, 0x6f, 0x21, + 0x46, 0x98, 0x0c, 0x66, 0x65, 0xad, 0xb9, 0xda, 0xd6, 0x35, 0xd3, 0xbb, + 0xef, 0xfe, 0x7e, 0xe7, 0x22, 0x81, 0xdf, 0x43, 0xd2, 0x68, 0x8c, 0x5c, + 0x64, 0x4d, 0x40, 0x4f, 0x9a, 0xc5, 0xd4, 0xe7, 0x1c, 0x9d, 0x6a, 0x06, + 0x58, 0x63, 0xec, 0x46, 0x8c, 0x28, 0xb5, 0xdf, 0x21, 0x85, 0x8d, 0xcc, + 0x3b, 0xdc, 0xdb, 0x29, 0x8e, 0xe0, 0x16, 0xe0, 0x73, 0x58, 0x7d, 0x84, + 0x3b, 0x20, 0x08, 0x7d, 0xc3, 0x70, 0x9e, 0x66 +}; +static const uint8_t nist_186_2_ecdsa_testvector_107_private[] = { +/* d - byte alignment */ + 0x01, 0xf4, 0x12, 0x2e, 0x6b, 0xbf, 0xd5, 0x4c, 0x74, 0xc2, 0x09, 0x09, + 0xb5, 0x17, 0xad, 0xca, 0x2a, 0xa6, 0x15, 0xa3, 0xa9, 0x70, 0xaf, 0x49, + 0xf1, 0xb6, 0xd4, 0x82, 0xe5, 0x29, 0x55, 0x67, 0x8d, 0x90, 0x08, 0xca +}; +static const uint8_t nist_186_2_ecdsa_testvector_107_public_x[] = { +/* Qx - byte alignment */ + 0x07, 0xc9, 0x29, 0x09, 0x8f, 0x03, 0x9b, 0xd5, 0xb1, 0xcd, 0x28, 0x85, + 0x45, 0xd2, 0xed, 0xa3, 0x52, 0x5a, 0x4f, 0xc3, 0x1b, 0x1c, 0x50, 0x50, + 0x78, 0xb2, 0x1b, 0xd9, 0x33, 0x70, 0x6a, 0xa8, 0xa3, 0x09, 0x6c, 0x00 +}; +static const uint8_t nist_186_2_ecdsa_testvector_107_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xb9, 0x09, 0x6a, 0x35, 0x68, 0x91, 0xfe, 0xe0, 0xf7, 0xa3, 0x46, + 0xf4, 0xa5, 0xc4, 0xfd, 0xa4, 0xb5, 0xac, 0xe8, 0x2b, 0xc3, 0xb6, 0x68, + 0xe3, 0x1f, 0x50, 0x5d, 0x82, 0x11, 0x7a, 0xfb, 0x1e, 0x9b, 0x2d, 0xa6 +}; +/* k = 139c2fb0c80eb68c87b60947fdbcfc542f522b17684153bc6fc68abd76f97d1543dedd0 */ +static const uint8_t nist_186_2_ecdsa_testvector_107_out[] = { +/* R - byte alignment */ + 0x01, 0x69, 0xac, 0x4c, 0x71, 0x42, 0xfd, 0x56, 0x29, 0xe9, 0x80, 0x0d, + 0x4c, 0x80, 0xf2, 0x02, 0xba, 0x9b, 0xae, 0xb7, 0xf1, 0xbe, 0x25, 0xed, + 0xb2, 0x49, 0xe1, 0x54, 0x2d, 0xd3, 0x0a, 0xf1, 0xce, 0x5e, 0x1d, 0x0a, +/* S - byte alignment */ + 0x00, 0x6e, 0x84, 0x72, 0xe5, 0x5f, 0x81, 0x7f, 0xcf, 0xf2, 0x88, 0x6f, + 0x1b, 0x3d, 0x67, 0x54, 0xa6, 0x09, 0xe7, 0x25, 0xfc, 0x2c, 0xea, 0x17, + 0x92, 0x07, 0xf4, 0x9d, 0xf0, 0x47, 0xac, 0x07, 0x38, 0x4f, 0x08, 0x1c +}; +static const uint8_t nist_186_2_ecdsa_testvector_108_ptx[] = { +/* Msg */ + 0xc8, 0x27, 0xf3, 0x8a, 0xc2, 0x4f, 0x78, 0x3c, 0x28, 0xf2, 0x5a, 0x7e, + 0xec, 0x43, 0xc7, 0x51, 0x5d, 0x6d, 0x14, 0x4e, 0x04, 0xe2, 0xb8, 0x95, + 0xcc, 0xef, 0x9c, 0x07, 0x67, 0x95, 0x92, 0xb5, 0xec, 0x94, 0x22, 0x97, + 0xc5, 0xc8, 0x8d, 0x82, 0xc8, 0xb8, 0x0c, 0x54, 0xa4, 0x6d, 0x59, 0x72, + 0x7f, 0x80, 0x70, 0x74, 0xdd, 0x77, 0x97, 0x1e, 0xc4, 0x52, 0x9c, 0x92, + 0x1e, 0x60, 0x5e, 0xc5, 0x5e, 0x57, 0x8e, 0x30, 0x66, 0xa4, 0xb7, 0xc8, + 0xa8, 0x00, 0x7c, 0x2f, 0x8c, 0x44, 0x22, 0x2c, 0x12, 0x7e, 0x4e, 0x59, + 0xb9, 0x44, 0x0f, 0x1b, 0x9f, 0x48, 0x1e, 0xd7, 0xe9, 0x2d, 0x65, 0x63, + 0x65, 0x99, 0xbf, 0xbb, 0x6e, 0x8c, 0xff, 0xf6, 0x11, 0xf0, 0x33, 0x78, + 0x6e, 0x71, 0x2a, 0x68, 0x60, 0x8e, 0x33, 0x65, 0x60, 0xf0, 0x28, 0x74, + 0xa6, 0xfb, 0xab, 0x3d, 0x92, 0xa4, 0xb0, 0x78 +}; +static const uint8_t nist_186_2_ecdsa_testvector_108_private[] = { +/* d - byte alignment */ + 0x01, 0x10, 0xac, 0xab, 0x54, 0xde, 0x0a, 0xee, 0x30, 0xf9, 0xcf, 0x6b, + 0x02, 0xc7, 0xa4, 0x96, 0xe2, 0x19, 0xbc, 0x0a, 0x13, 0xf7, 0x45, 0xa5, + 0xf5, 0xb9, 0xed, 0xbd, 0x9f, 0xa4, 0x81, 0xb9, 0x48, 0x5c, 0xea, 0x58 +}; +static const uint8_t nist_186_2_ecdsa_testvector_108_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0xb1, 0x89, 0x0a, 0xcf, 0x9b, 0x84, 0xbb, 0xc2, 0x3f, 0xce, 0x4f, + 0xcf, 0x05, 0x49, 0x93, 0xe3, 0xa2, 0x09, 0x05, 0x8e, 0x3f, 0x68, 0x70, + 0xc9, 0xb9, 0xb7, 0x55, 0x2d, 0xbe, 0x4d, 0x01, 0xe6, 0xa5, 0x7a, 0x5b +}; +static const uint8_t nist_186_2_ecdsa_testvector_108_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0xda, 0x10, 0xfb, 0x30, 0x80, 0xa0, 0x27, 0xfb, 0x1d, 0x8c, 0x06, + 0x66, 0x11, 0xad, 0x52, 0x9f, 0x2f, 0x22, 0x58, 0xfb, 0xed, 0x2b, 0xde, + 0x4c, 0x44, 0x1a, 0x41, 0x59, 0xf4, 0x3f, 0x35, 0x49, 0x3c, 0xd7, 0xbc +}; +/* k = 18b3ca7f07bd7598ff56b8039eb37b38771ccf2bf01943188001636ef35303a603ffa6f */ +static const uint8_t nist_186_2_ecdsa_testvector_108_out[] = { +/* R - byte alignment */ + 0x00, 0xba, 0x25, 0x30, 0xcc, 0x00, 0xb0, 0xc5, 0x5f, 0xdd, 0x5c, 0x37, + 0xcc, 0x37, 0xb6, 0x8e, 0x9b, 0x9f, 0x88, 0xaa, 0x26, 0x4b, 0x57, 0x6e, + 0x9f, 0x60, 0xad, 0xf0, 0xef, 0x41, 0x92, 0x11, 0x5f, 0xd2, 0x07, 0x05, +/* S - byte alignment */ + 0x01, 0x1b, 0x07, 0x37, 0x0a, 0xe7, 0x1d, 0x82, 0x1f, 0xd5, 0x70, 0xbc, + 0x3d, 0x25, 0xf0, 0x85, 0x98, 0x48, 0x13, 0x03, 0x07, 0x0a, 0xa9, 0x4b, + 0x99, 0xc9, 0x56, 0x2e, 0xf2, 0xc9, 0x7e, 0x06, 0x04, 0x85, 0xa6, 0xd4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_109_ptx[] = { +/* Msg */ + 0x75, 0xea, 0xda, 0x8d, 0x9f, 0xda, 0x06, 0x5d, 0x74, 0xca, 0x2d, 0x45, + 0xe7, 0x2f, 0x01, 0xfd, 0x5f, 0x27, 0x3a, 0x31, 0x68, 0x5c, 0xe6, 0x84, + 0xa8, 0x2c, 0x00, 0xd5, 0x16, 0x08, 0x45, 0xc1, 0x66, 0x1a, 0x43, 0x69, + 0xc7, 0x2b, 0xb3, 0x75, 0xd1, 0xc3, 0x08, 0x59, 0xb9, 0x92, 0x48, 0xd6, + 0xc8, 0x0e, 0x1b, 0xc4, 0x0b, 0x5e, 0x22, 0x10, 0x4b, 0x77, 0x89, 0x01, + 0x3f, 0x85, 0xe0, 0xbf, 0x01, 0x8c, 0x26, 0x15, 0xbf, 0x4f, 0x27, 0x76, + 0xb3, 0x71, 0x09, 0x3e, 0x55, 0xda, 0x21, 0x3b, 0xcf, 0x5c, 0x0b, 0x6c, + 0xb1, 0x96, 0xf9, 0x08, 0xe6, 0x19, 0x4b, 0xc2, 0xe7, 0xca, 0x60, 0x4c, + 0x2e, 0x88, 0xac, 0x1a, 0xee, 0x0e, 0x0b, 0x68, 0x01, 0x1a, 0x55, 0x7e, + 0x21, 0xcf, 0x33, 0x33, 0x5c, 0x57, 0x31, 0xb0, 0xc2, 0xce, 0x14, 0x76, + 0x61, 0x5b, 0x6d, 0xa3, 0x73, 0xa0, 0x6e, 0x70 +}; +static const uint8_t nist_186_2_ecdsa_testvector_109_private[] = { +/* d - byte alignment */ + 0x01, 0x4c, 0xb8, 0x48, 0x03, 0x78, 0x9e, 0x2b, 0xb7, 0x1e, 0xf8, 0x4e, + 0xb2, 0xbd, 0x35, 0xa3, 0xed, 0x51, 0x61, 0xf9, 0xc8, 0x95, 0xf5, 0x30, + 0x37, 0xef, 0xf8, 0x35, 0x2d, 0xe6, 0x10, 0x71, 0xc1, 0xc1, 0x0a, 0x22 +}; +static const uint8_t nist_186_2_ecdsa_testvector_109_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0xdb, 0x6c, 0x52, 0x07, 0x76, 0xe5, 0x85, 0x7b, 0x1c, 0xf7, 0xf0, + 0xc2, 0xff, 0x5a, 0xf8, 0x9f, 0x32, 0x9b, 0xe2, 0x73, 0xa8, 0xd7, 0xb6, + 0x28, 0xc0, 0x08, 0xa6, 0x62, 0x7d, 0xdf, 0x08, 0x45, 0xa7, 0x98, 0x30 +}; +static const uint8_t nist_186_2_ecdsa_testvector_109_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0xdc, 0x68, 0xac, 0x24, 0x69, 0xaf, 0x1b, 0xfa, 0x7c, 0xc7, 0xde, + 0x61, 0x46, 0x6a, 0xd9, 0xf1, 0x64, 0xa0, 0x2d, 0x65, 0x42, 0x8f, 0xef, + 0x7e, 0x57, 0x6a, 0xa5, 0x51, 0x79, 0x09, 0xb0, 0x00, 0xf3, 0x40, 0xaa +}; +/* k = 1dc37802ec3d06d3fa6e665214a5e7ca7dc6e51584af57edfdf6c2171e89c29fbd5bc0b */ +static const uint8_t nist_186_2_ecdsa_testvector_109_out[] = { +/* R - byte alignment */ + 0x01, 0xfa, 0x2d, 0xd3, 0xcd, 0x44, 0x95, 0xe9, 0x21, 0x8e, 0x1f, 0x6e, + 0x19, 0xe3, 0x38, 0x66, 0x68, 0xc5, 0x69, 0x77, 0x3b, 0x51, 0xd5, 0xf0, + 0xe2, 0x15, 0x8a, 0xf9, 0x4d, 0x98, 0xa7, 0x90, 0x7b, 0x52, 0xf8, 0x18, +/* S - byte alignment */ + 0x00, 0xe8, 0x56, 0x1e, 0x4c, 0xb6, 0x76, 0xce, 0x73, 0xe3, 0xbd, 0xed, + 0x25, 0x72, 0xcc, 0xb3, 0x68, 0xca, 0xb7, 0xb7, 0x56, 0x2a, 0x18, 0x4f, + 0xcd, 0x58, 0x28, 0x41, 0x57, 0x48, 0x00, 0x24, 0xfd, 0x14, 0x46, 0x94 +}; +static const uint8_t nist_186_2_ecdsa_testvector_110_ptx[] = { +/* Msg */ + 0x3f, 0x30, 0x1e, 0x82, 0x81, 0xf0, 0x90, 0x55, 0xc5, 0x29, 0x15, 0x7b, + 0x76, 0xed, 0x84, 0x3b, 0x50, 0x58, 0x9b, 0x2e, 0x14, 0x74, 0x4d, 0x45, + 0x80, 0x5a, 0x5d, 0x0d, 0x7e, 0x9a, 0x2c, 0x32, 0x9c, 0xdd, 0xd0, 0x43, + 0xbc, 0xc9, 0x65, 0xb4, 0x0c, 0x25, 0xa8, 0x29, 0x39, 0x3e, 0xc2, 0xf2, + 0xe0, 0x89, 0x61, 0xd1, 0x46, 0x89, 0x0d, 0x04, 0x48, 0xf3, 0xba, 0x7f, + 0x95, 0x11, 0x99, 0x7a, 0x1a, 0x64, 0x34, 0x2b, 0xbe, 0x8d, 0xba, 0xd5, + 0x50, 0x6e, 0x97, 0x01, 0xbd, 0x8c, 0x48, 0x0b, 0x87, 0xb7, 0x6e, 0xe1, + 0x72, 0xee, 0x21, 0x08, 0x81, 0x7d, 0x86, 0xe0, 0x20, 0x68, 0xa4, 0x28, + 0xa3, 0x0c, 0x73, 0xc4, 0xef, 0x04, 0x36, 0xbe, 0x77, 0x4a, 0x0b, 0x8c, + 0x6b, 0x9e, 0xc1, 0x91, 0x2b, 0x2c, 0xe9, 0xe6, 0x02, 0x69, 0x30, 0x59, + 0x11, 0x3e, 0xec, 0xb6, 0x89, 0x68, 0xf4, 0x46 +}; +static const uint8_t nist_186_2_ecdsa_testvector_110_private[] = { +/* d - byte alignment */ + 0x00, 0xc8, 0xd5, 0x48, 0x6a, 0x78, 0x1e, 0x1e, 0x3d, 0xa0, 0x0f, 0x48, + 0x8e, 0x6c, 0xc7, 0x64, 0x42, 0xfb, 0x96, 0xb3, 0x86, 0xdf, 0xd4, 0xf9, + 0x8f, 0x64, 0x61, 0x10, 0xd7, 0xde, 0x44, 0x14, 0xcb, 0x17, 0x86, 0xf7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_110_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0x79, 0x06, 0xd4, 0xf2, 0xfb, 0xaf, 0x1e, 0x35, 0x35, 0x7e, 0xcc, + 0xc6, 0xfd, 0xe7, 0xe1, 0xce, 0x23, 0x8c, 0xfd, 0x86, 0xa1, 0xe0, 0x1b, + 0xb3, 0x12, 0x50, 0x80, 0xb5, 0x43, 0x44, 0xe0, 0x0f, 0x30, 0xdb, 0x42 +}; +static const uint8_t nist_186_2_ecdsa_testvector_110_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xd3, 0x3f, 0xfa, 0x8b, 0x33, 0xb3, 0xcb, 0x3c, 0xc4, 0x0e, 0x31, + 0x71, 0x48, 0x61, 0x66, 0x72, 0xfe, 0xa4, 0x44, 0xdc, 0x58, 0x67, 0x2b, + 0x2e, 0xff, 0x9a, 0xea, 0x53, 0xb1, 0x51, 0x64, 0x58, 0x03, 0x81, 0x12 +}; +/* k = 01121d761d048f9792b699e0130cde517e5170c9f898457e72604791053bba2a7efee9a */ +static const uint8_t nist_186_2_ecdsa_testvector_110_out[] = { +/* R - byte alignment */ + 0x00, 0x91, 0xb7, 0x67, 0x07, 0x5b, 0x3a, 0xbf, 0xe2, 0x20, 0xb0, 0xf6, + 0xbd, 0x05, 0x71, 0x41, 0xb8, 0x5c, 0x21, 0x5b, 0x37, 0x49, 0x00, 0xe7, + 0xff, 0x67, 0x52, 0x8c, 0xa8, 0x02, 0x14, 0x26, 0xe5, 0xec, 0x4a, 0x5d, +/* S - byte alignment */ + 0x00, 0xda, 0x1f, 0x7d, 0x29, 0xe0, 0x24, 0x49, 0x52, 0x41, 0xe1, 0x71, + 0x96, 0x5d, 0xb5, 0x50, 0xdc, 0x40, 0x80, 0xe8, 0x8b, 0x7b, 0xfc, 0xf2, + 0xee, 0x90, 0x24, 0x3d, 0xe0, 0x9e, 0x79, 0xd4, 0x90, 0x98, 0x13, 0x70 +}; +static const uint8_t nist_186_2_ecdsa_testvector_111_ptx[] = { +/* Msg */ + 0x79, 0x51, 0xcb, 0xcb, 0x32, 0xb5, 0x33, 0x19, 0xf8, 0x93, 0x49, 0x04, + 0xec, 0xda, 0x51, 0x94, 0x87, 0x6b, 0xba, 0x4b, 0xd2, 0x7b, 0xf2, 0xa9, + 0xda, 0x38, 0x7f, 0xf6, 0x5e, 0xaf, 0x4c, 0x3b, 0xcc, 0xed, 0x40, 0x92, + 0x6c, 0x64, 0x15, 0x9f, 0xda, 0x91, 0x68, 0x5f, 0xb9, 0xdc, 0x0c, 0x20, + 0xa6, 0xc0, 0xa4, 0xd1, 0x6b, 0x2b, 0x71, 0x7c, 0x75, 0x28, 0x68, 0x11, + 0x89, 0xbb, 0x88, 0x65, 0xb2, 0x0c, 0x6a, 0x7a, 0x7e, 0xc8, 0x1a, 0x01, + 0x69, 0xc5, 0x25, 0x1d, 0x9a, 0xe5, 0xf3, 0x6a, 0xcd, 0x3c, 0x57, 0x3e, + 0x91, 0x75, 0x65, 0x2f, 0xb3, 0x71, 0x84, 0xd5, 0xfa, 0x32, 0xc4, 0xd1, + 0x14, 0xf8, 0x71, 0x0d, 0xd1, 0xa9, 0xe8, 0x46, 0x8f, 0x76, 0xa9, 0xc8, + 0xf6, 0xbc, 0xae, 0x79, 0xe5, 0x28, 0xfb, 0x19, 0xab, 0x1f, 0x77, 0xc8, + 0x7b, 0x5d, 0xfa, 0xc9, 0x1a, 0xdc, 0xa7, 0x85 +}; +static const uint8_t nist_186_2_ecdsa_testvector_111_private[] = { +/* d - byte alignment */ + 0x00, 0xff, 0x58, 0x02, 0xe7, 0x58, 0x94, 0x55, 0xfe, 0x8e, 0x87, 0x75, + 0x6a, 0x7c, 0xb7, 0x21, 0x4e, 0x73, 0x70, 0x1b, 0xd6, 0x35, 0x70, 0x97, + 0x13, 0xb5, 0xbe, 0x4b, 0xcb, 0xe5, 0x10, 0x91, 0xcb, 0xab, 0x25, 0x80 +}; +static const uint8_t nist_186_2_ecdsa_testvector_111_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0x42, 0xf1, 0x1a, 0xc3, 0xbd, 0x7e, 0xff, 0x65, 0x01, 0x77, 0x66, + 0x33, 0xa1, 0x0c, 0x14, 0x23, 0x3c, 0xc6, 0x56, 0xf8, 0x89, 0x15, 0xcd, + 0x90, 0x48, 0xa4, 0xfc, 0x41, 0x19, 0xb1, 0x82, 0xa0, 0xe7, 0x84, 0x47 +}; +static const uint8_t nist_186_2_ecdsa_testvector_111_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0x5f, 0x7e, 0xa4, 0x34, 0xdb, 0xab, 0x0c, 0x2c, 0x4c, 0xd7, 0x75, + 0xcf, 0x3d, 0x8c, 0xb7, 0x18, 0x9e, 0x47, 0xf1, 0x0e, 0x40, 0xde, 0xaa, + 0x47, 0xf0, 0x56, 0x80, 0x9c, 0xb1, 0x62, 0xd2, 0x8e, 0xb3, 0x2b, 0xb2 +}; +/* k = 13dbae9d89dd59876b87934fd6025084d6bdbe946f1bee4a173665063f9af9d61b5e92f */ +static const uint8_t nist_186_2_ecdsa_testvector_111_out[] = { +/* R - byte alignment */ + 0x01, 0xeb, 0x31, 0x93, 0x04, 0xff, 0xd6, 0xdc, 0xce, 0x3b, 0x57, 0x32, + 0xe3, 0x42, 0x19, 0x6b, 0x48, 0x27, 0xde, 0xc3, 0x16, 0x85, 0x81, 0xc8, + 0x65, 0x78, 0x82, 0xbb, 0xc5, 0xe2, 0x7e, 0x73, 0xa2, 0x73, 0x6b, 0x90, +/* S - byte alignment */ + 0x00, 0x29, 0xcf, 0xcc, 0x7e, 0xff, 0x79, 0x15, 0xe1, 0xd4, 0xc8, 0xb7, + 0x0f, 0xda, 0x11, 0x86, 0xc7, 0xfe, 0xab, 0x22, 0xd7, 0x58, 0xbc, 0x10, + 0x28, 0x51, 0xfa, 0x9b, 0xa5, 0x6c, 0x31, 0xf6, 0x21, 0xc1, 0xbb, 0xa4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_112_ptx[] = { +/* Msg */ + 0x9c, 0x84, 0x64, 0x69, 0x1a, 0xb7, 0xfe, 0x42, 0xe0, 0xb5, 0x54, 0x8c, + 0x56, 0x95, 0x33, 0xb8, 0xbe, 0xdf, 0x11, 0x2e, 0x69, 0xf0, 0xe6, 0xda, + 0x2b, 0x9f, 0x3d, 0xe7, 0x0c, 0x20, 0x8a, 0xca, 0x40, 0x29, 0xbe, 0x83, + 0x5a, 0x54, 0x19, 0x1f, 0xbc, 0xc5, 0x3f, 0x82, 0x52, 0x0c, 0x8f, 0x63, + 0x80, 0x4c, 0xb0, 0x98, 0x58, 0x9d, 0x6c, 0x94, 0x11, 0xb0, 0xc2, 0x2e, + 0xb4, 0xb2, 0x36, 0xa4, 0x19, 0x72, 0x6c, 0xdf, 0x12, 0xc5, 0xf5, 0xf8, + 0xe6, 0x2a, 0x69, 0xfc, 0x01, 0xaa, 0xb6, 0xec, 0xe9, 0x02, 0xb7, 0x08, + 0x74, 0x04, 0x09, 0x4d, 0x39, 0x3b, 0x1a, 0x3d, 0x44, 0xce, 0x82, 0xde, + 0x0e, 0xa6, 0x97, 0x05, 0xac, 0xd3, 0x3b, 0xd4, 0x46, 0x2c, 0xf9, 0x82, + 0xcb, 0x36, 0x51, 0x5a, 0xe3, 0x48, 0x4f, 0x07, 0x25, 0xec, 0x63, 0x0e, + 0x8b, 0x87, 0x6c, 0x9c, 0x22, 0x3d, 0x16, 0x82 +}; +static const uint8_t nist_186_2_ecdsa_testvector_112_private[] = { +/* d - byte alignment */ + 0x00, 0x3f, 0xf4, 0x93, 0x07, 0x06, 0x3d, 0xe1, 0x26, 0x27, 0x1b, 0xa6, + 0x65, 0x00, 0x9c, 0x1a, 0xb2, 0x7b, 0xe4, 0x12, 0xbe, 0xe1, 0xc6, 0x15, + 0xc9, 0x6b, 0x26, 0x6a, 0xb7, 0x13, 0x24, 0xf0, 0x11, 0x61, 0x9f, 0x3a +}; +static const uint8_t nist_186_2_ecdsa_testvector_112_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x08, 0x8d, 0x92, 0x98, 0x98, 0xc3, 0xae, 0xcd, 0x20, 0x94, 0xb6, + 0xd5, 0x2b, 0x6b, 0xa1, 0x0c, 0x5f, 0xd6, 0x3a, 0x73, 0xea, 0xd1, 0x50, + 0x77, 0x0a, 0x9d, 0xaa, 0x98, 0xb1, 0x26, 0xfc, 0x0e, 0x21, 0xd1, 0x79 +}; +static const uint8_t nist_186_2_ecdsa_testvector_112_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x0c, 0x27, 0x16, 0x3f, 0xc8, 0x4d, 0xc5, 0xb4, 0xe5, 0xa4, 0x78, + 0xeb, 0x4e, 0xf8, 0xbf, 0xbb, 0xdb, 0xfa, 0x52, 0xd1, 0xbe, 0xf0, 0xb8, + 0xa2, 0x4f, 0xe4, 0x8d, 0x9c, 0xf2, 0x36, 0x0a, 0x18, 0x85, 0xe0, 0x91 +}; +/* k = 1d304d9fc85e8e31cf7ab232dd851341db971c67c83b1f5e3312f53b4d2df053db2b9d7 */ +static const uint8_t nist_186_2_ecdsa_testvector_112_out[] = { +/* R - byte alignment */ + 0x01, 0xd9, 0xcc, 0x14, 0xaf, 0x94, 0x23, 0x07, 0x80, 0x24, 0x66, 0x12, + 0x38, 0xb5, 0xe4, 0x9b, 0x20, 0xfe, 0x8e, 0x98, 0x9e, 0x6b, 0xe6, 0x95, + 0xd8, 0x0a, 0xab, 0xb7, 0xf4, 0x9b, 0xe0, 0xf3, 0x24, 0x9d, 0x7d, 0x84, +/* S - byte alignment */ + 0x01, 0xff, 0x18, 0x9c, 0x0c, 0x55, 0x77, 0xb6, 0xcf, 0x7f, 0xde, 0x2c, + 0xf6, 0xf7, 0x11, 0x59, 0x0c, 0xbc, 0x58, 0x3d, 0x61, 0xef, 0x19, 0x4e, + 0xa2, 0x89, 0x97, 0x0c, 0x4c, 0x18, 0x34, 0x6d, 0x80, 0xf7, 0xcd, 0x12 +}; +static const uint8_t nist_186_2_ecdsa_testvector_113_ptx[] = { +/* Msg */ + 0x37, 0xf2, 0x2d, 0x64, 0x75, 0xd3, 0xf9, 0xf4, 0x2c, 0xbe, 0x47, 0x1b, + 0xc3, 0x0d, 0x5d, 0x16, 0x5b, 0xf0, 0xf5, 0xcb, 0x0d, 0xaa, 0x9a, 0xa1, + 0x72, 0xfd, 0x55, 0x95, 0x69, 0xe2, 0x89, 0x8b, 0x14, 0x7e, 0x1c, 0xe1, + 0x24, 0x52, 0xd7, 0x4a, 0x57, 0xb2, 0x10, 0xda, 0x3e, 0x78, 0x86, 0x5d, + 0x44, 0xf9, 0x8c, 0xed, 0xec, 0x38, 0x6a, 0xc4, 0x5a, 0x5a, 0x00, 0x4e, + 0x15, 0x5a, 0xac, 0x82, 0x0b, 0xfe, 0x6e, 0x73, 0xd6, 0x0a, 0x4a, 0x22, + 0x3d, 0xb3, 0xee, 0x97, 0xfe, 0x56, 0x95, 0x30, 0xcb, 0x6a, 0x2b, 0x38, + 0x92, 0xb4, 0xb2, 0xbb, 0x01, 0xb9, 0xe4, 0x99, 0x4a, 0x79, 0x1a, 0xda, + 0x23, 0x5a, 0x6c, 0x41, 0x11, 0x63, 0x1a, 0x24, 0xe7, 0xaa, 0x2b, 0x7b, + 0x89, 0x10, 0x53, 0x36, 0xf6, 0x2b, 0x1a, 0xd4, 0x86, 0x84, 0x3b, 0x31, + 0x70, 0x03, 0x4a, 0x9f, 0x8e, 0xa7, 0x9a, 0x39 +}; +static const uint8_t nist_186_2_ecdsa_testvector_113_private[] = { +/* d - byte alignment */ + 0x01, 0xe5, 0x69, 0x3c, 0xfc, 0xe0, 0xf4, 0x1b, 0x4f, 0xaf, 0xbd, 0x6b, + 0x44, 0xd4, 0x93, 0x65, 0x12, 0x15, 0xe2, 0x5a, 0xfe, 0x3f, 0x40, 0x3d, + 0x3f, 0x45, 0xc7, 0x3a, 0x87, 0x9d, 0xf7, 0xf3, 0x42, 0x5b, 0xde, 0x81 +}; +static const uint8_t nist_186_2_ecdsa_testvector_113_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xad, 0xf6, 0x7f, 0x4b, 0x2f, 0xba, 0xcf, 0x3f, 0xa8, 0x65, 0x67, + 0xcd, 0x54, 0xdc, 0x86, 0x85, 0x62, 0x39, 0x1a, 0x06, 0xd6, 0x11, 0xf1, + 0xbc, 0xc0, 0x5c, 0x0e, 0x4a, 0xad, 0x28, 0x5c, 0x99, 0x13, 0x5a, 0xa9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_113_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0x2f, 0x13, 0x75, 0xee, 0xec, 0x12, 0xf4, 0x4d, 0x0d, 0x18, 0x67, + 0x04, 0x73, 0xf2, 0x4f, 0xee, 0xb3, 0x82, 0x0b, 0xf5, 0x0a, 0x57, 0x45, + 0x41, 0xbe, 0xc0, 0x97, 0x11, 0x67, 0x6e, 0xf7, 0xc0, 0xa9, 0x1b, 0x2b +}; +/* k = 16706bb67cc99d89560a49ba21a1644ae83e22f5bc1be388343dfca768536b5220204a0 */ +static const uint8_t nist_186_2_ecdsa_testvector_113_out[] = { +/* R - byte alignment */ + 0x00, 0xc9, 0xad, 0xd0, 0x5e, 0xec, 0x55, 0xf4, 0x28, 0xba, 0x4d, 0xd3, + 0xbc, 0xba, 0xbe, 0x90, 0xb6, 0xa7, 0xc1, 0xb7, 0x1c, 0x28, 0xce, 0x25, + 0x59, 0x84, 0xf0, 0xf0, 0x89, 0xf4, 0x0a, 0x6d, 0x15, 0xf7, 0x37, 0x74, +/* S - byte alignment */ + 0x00, 0x50, 0x46, 0x50, 0x03, 0x3a, 0x44, 0x8b, 0xcc, 0xfb, 0xb1, 0x77, + 0x83, 0x88, 0xac, 0x6a, 0x28, 0xe4, 0x85, 0x85, 0x77, 0x74, 0x00, 0xd6, + 0xf3, 0xdf, 0xbf, 0x74, 0x2c, 0x5d, 0x7b, 0x70, 0x1a, 0xa5, 0x5e, 0xa0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_114_ptx[] = { +/* Msg */ + 0xc9, 0x49, 0xc2, 0x96, 0xd1, 0xae, 0x5a, 0xbe, 0xcb, 0xa3, 0x13, 0x0d, + 0xae, 0xd2, 0x3b, 0xad, 0xc3, 0xf0, 0x0b, 0x05, 0xac, 0xa9, 0xcc, 0x45, + 0xa4, 0xd6, 0x3d, 0x3e, 0x08, 0xf6, 0x39, 0x78, 0x17, 0xdc, 0x95, 0x7e, + 0xf6, 0xa5, 0x48, 0x7d, 0xf6, 0xed, 0xce, 0x0d, 0x1a, 0x43, 0xce, 0x4f, + 0xd4, 0xd9, 0xfa, 0x38, 0x10, 0x80, 0x36, 0x2c, 0x73, 0xd4, 0xfd, 0xcf, + 0xe5, 0xb4, 0x01, 0x18, 0x4d, 0xf6, 0x12, 0xa7, 0x9b, 0x58, 0x41, 0x58, + 0x0c, 0xb9, 0x45, 0x18, 0xa9, 0x89, 0x1e, 0xf7, 0x12, 0x7e, 0xf8, 0x7f, + 0x79, 0x88, 0x51, 0x44, 0xf1, 0x08, 0x5e, 0xbd, 0xe9, 0x3d, 0xab, 0x52, + 0xf3, 0xfe, 0x03, 0xb6, 0xcb, 0xaf, 0x8f, 0x77, 0x94, 0x6e, 0x41, 0xd4, + 0x64, 0x8d, 0x74, 0xce, 0x03, 0x45, 0xcc, 0x82, 0xf0, 0xa8, 0x64, 0xb5, + 0xa5, 0xd8, 0x28, 0xb1, 0x1c, 0x77, 0x7f, 0x50 +}; +static const uint8_t nist_186_2_ecdsa_testvector_114_private[] = { +/* d - byte alignment */ + 0x00, 0x2f, 0xdd, 0xd8, 0xf3, 0xe8, 0x14, 0x0b, 0x9a, 0x06, 0x6b, 0x80, + 0x40, 0x2d, 0xb5, 0xb3, 0x45, 0xbf, 0x89, 0x8d, 0x80, 0xae, 0xd2, 0xd0, + 0xe3, 0xa0, 0x7c, 0x27, 0xd8, 0x7d, 0xaf, 0x27, 0x76, 0x93, 0x25, 0xc4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_114_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xfe, 0x5f, 0x36, 0xa1, 0xac, 0x57, 0x70, 0x03, 0xc8, 0x8e, 0xa4, + 0xa0, 0x95, 0x70, 0x4f, 0x39, 0xef, 0xbb, 0x44, 0xdf, 0xe2, 0x1f, 0x33, + 0xc2, 0xeb, 0x84, 0xfe, 0x77, 0x80, 0x91, 0x94, 0x06, 0x24, 0xff, 0xa4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_114_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0x75, 0x4c, 0x7b, 0xde, 0x4c, 0x7c, 0xc0, 0x5f, 0x6b, 0x30, 0x8b, + 0xa8, 0x72, 0x50, 0x18, 0x00, 0xea, 0xc3, 0x8d, 0x52, 0x2d, 0xf0, 0xc6, + 0x04, 0x70, 0xce, 0xa1, 0xab, 0x10, 0xb2, 0x95, 0xe2, 0x84, 0x1c, 0x6c +}; +/* k = 1f0682ed3f910946c617e385c78b410104ed341d4fc3068958980ad1955a2516d553380 */ +static const uint8_t nist_186_2_ecdsa_testvector_114_out[] = { +/* R - byte alignment */ + 0x00, 0x59, 0x93, 0x2e, 0x17, 0x60, 0x54, 0x7c, 0x91, 0xa5, 0x0f, 0x4d, + 0x9b, 0xf6, 0x33, 0xe7, 0x2f, 0x5f, 0x96, 0x3b, 0x79, 0x3f, 0x16, 0xe6, + 0xbe, 0xa3, 0x59, 0xa7, 0xd4, 0xf8, 0x1e, 0xee, 0x16, 0xb1, 0xf8, 0xcd, +/* S - byte alignment */ + 0x00, 0xda, 0x9e, 0x43, 0x7b, 0x65, 0x01, 0x93, 0x73, 0x1a, 0xbb, 0xb9, + 0x2f, 0xdd, 0x57, 0x50, 0x78, 0xdf, 0x41, 0x1b, 0xc4, 0xbb, 0x12, 0xfc, + 0xf3, 0x3f, 0xa4, 0xe0, 0xed, 0xad, 0x9a, 0xff, 0x3a, 0x90, 0xac, 0xa5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_115_ptx[] = { +/* Msg */ + 0x89, 0xa5, 0x35, 0x8b, 0x6c, 0x4f, 0x82, 0x01, 0x30, 0xd2, 0xcf, 0xde, + 0x90, 0x0d, 0x49, 0x26, 0xcf, 0x47, 0xf4, 0x63, 0xa0, 0x7b, 0xa8, 0x9b, + 0x44, 0xf2, 0x59, 0x7f, 0xf2, 0x17, 0x9b, 0xe5, 0x7b, 0x88, 0x64, 0x78, + 0x2e, 0x69, 0x14, 0xae, 0xf9, 0xfd, 0xb4, 0xfb, 0xd2, 0x77, 0x7b, 0x45, + 0x55, 0x0d, 0x97, 0x97, 0xaf, 0x4f, 0x2a, 0x19, 0xba, 0xb7, 0x92, 0x40, + 0x69, 0x81, 0xed, 0x42, 0x67, 0xbc, 0xdc, 0xcd, 0xfb, 0xa2, 0x88, 0xf8, + 0x2f, 0x25, 0xe3, 0x7a, 0x31, 0xca, 0x31, 0x19, 0xf9, 0xba, 0xc6, 0x66, + 0x2c, 0x17, 0x11, 0xa8, 0x41, 0x8c, 0xd9, 0x16, 0xe2, 0x28, 0xc7, 0x49, + 0x95, 0x6c, 0x25, 0xf0, 0x9b, 0xa2, 0xe5, 0xc6, 0x18, 0x71, 0xe5, 0xc1, + 0x75, 0xaf, 0x71, 0x8c, 0x03, 0x76, 0x0a, 0x38, 0xe1, 0x7a, 0x65, 0x2f, + 0x1f, 0x99, 0xb7, 0x69, 0x23, 0xb4, 0x30, 0xe2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_115_private[] = { +/* d - byte alignment */ + 0x01, 0xda, 0x9c, 0x38, 0x43, 0x43, 0xe2, 0xde, 0x38, 0xa1, 0x5f, 0x27, + 0x68, 0x64, 0x6f, 0x63, 0x26, 0x4e, 0xa5, 0x7b, 0xe6, 0x61, 0x59, 0x15, + 0x53, 0x20, 0x08, 0x7b, 0x18, 0x41, 0x80, 0x44, 0x0d, 0x76, 0x75, 0xd0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_115_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0xd0, 0x5a, 0x98, 0xcc, 0x74, 0x68, 0xbc, 0xcb, 0x23, 0x37, 0x32, + 0xa9, 0xa3, 0x8f, 0x60, 0x42, 0x25, 0x61, 0x9c, 0xd6, 0x16, 0x74, 0x70, + 0xcf, 0xd7, 0xc5, 0x57, 0x05, 0xa8, 0x29, 0xf0, 0x55, 0xc2, 0x34, 0x54 +}; +static const uint8_t nist_186_2_ecdsa_testvector_115_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x30, 0x34, 0xb8, 0xc1, 0x2c, 0xbc, 0x1d, 0x6d, 0x01, 0xfe, 0x64, + 0x6f, 0xbf, 0xde, 0x6e, 0x4f, 0xfb, 0x9b, 0xa1, 0x65, 0xce, 0x1b, 0x7e, + 0xcb, 0xad, 0x60, 0x81, 0x2d, 0x22, 0x07, 0x4e, 0x65, 0xc9, 0x5e, 0xcb +}; +/* k = 1f2c34ee3c4a2c2d9504b4c560c572f0c9e713dabcc215e784314fecfb2c3b771fe6362 */ +static const uint8_t nist_186_2_ecdsa_testvector_115_out[] = { +/* R - byte alignment */ + 0x01, 0x3b, 0x10, 0xfb, 0xc3, 0x3d, 0xc4, 0xd0, 0xcf, 0x16, 0x72, 0xae, + 0x57, 0x7b, 0x70, 0xf8, 0x22, 0x3e, 0x9c, 0x64, 0x8b, 0x9a, 0x79, 0x18, + 0x80, 0xb3, 0xd5, 0x74, 0x5a, 0x80, 0x5f, 0xa4, 0x2c, 0x99, 0xe7, 0xc5, +/* S - byte alignment */ + 0x01, 0xa4, 0x24, 0xc8, 0x6e, 0x66, 0x15, 0xa7, 0x1b, 0x61, 0x7d, 0xee, + 0x72, 0xa8, 0xe4, 0x97, 0x02, 0x18, 0x2b, 0x36, 0x06, 0x98, 0xba, 0x5f, + 0x06, 0xdd, 0xda, 0x19, 0x3f, 0xa6, 0xf3, 0x6b, 0xfd, 0xcb, 0xfe, 0xae +}; +static const uint8_t nist_186_2_ecdsa_testvector_116_ptx[] = { +/* Msg */ + 0x5e, 0x78, 0x56, 0xa7, 0xa6, 0xcb, 0x24, 0x2f, 0x7f, 0x27, 0x91, 0x9f, + 0x46, 0xcd, 0xf0, 0xd2, 0xf8, 0x14, 0x47, 0x88, 0xe7, 0x53, 0xa3, 0x67, + 0xb2, 0x01, 0xaf, 0x3f, 0x73, 0x1b, 0x85, 0x92, 0x3a, 0xc6, 0xc4, 0x54, + 0xbb, 0x36, 0xe3, 0xef, 0x43, 0xce, 0xc5, 0x8a, 0xf1, 0x89, 0x8d, 0x8b, + 0x22, 0x98, 0xb3, 0x5a, 0x2d, 0x4d, 0x58, 0x68, 0x51, 0x37, 0xd6, 0x71, + 0xeb, 0x8f, 0x9c, 0xfe, 0xec, 0xd2, 0x39, 0x2d, 0x8b, 0xb0, 0xb6, 0xb4, + 0x37, 0x25, 0x29, 0x24, 0xd0, 0xe6, 0x87, 0x6b, 0x16, 0xfe, 0xba, 0x9d, + 0x62, 0xb9, 0xf3, 0xf4, 0x94, 0xc1, 0x42, 0x15, 0x4c, 0x87, 0x64, 0x94, + 0x5d, 0xe4, 0xdc, 0xbb, 0x7e, 0x01, 0x45, 0x87, 0x43, 0x74, 0xe6, 0xf4, + 0x4c, 0xab, 0x87, 0x7a, 0xbd, 0x8e, 0x83, 0xd8, 0xed, 0x60, 0x1f, 0x10, + 0x63, 0xe6, 0x1a, 0xb3, 0xfe, 0xcc, 0x85, 0x5e +}; +static const uint8_t nist_186_2_ecdsa_testvector_116_private[] = { +/* d - byte alignment */ + 0x01, 0x58, 0x0d, 0x8a, 0xca, 0x42, 0x6c, 0x30, 0x55, 0x45, 0x63, 0x08, + 0xd3, 0x99, 0xcb, 0x94, 0xa7, 0xf0, 0xc9, 0xbd, 0x3f, 0x04, 0x49, 0xc9, + 0x79, 0xf1, 0xeb, 0xfb, 0x9d, 0xf9, 0x50, 0xa9, 0xda, 0x54, 0xca, 0x71 +}; +static const uint8_t nist_186_2_ecdsa_testvector_116_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xe8, 0xbe, 0x02, 0xe0, 0x6f, 0x92, 0x07, 0x85, 0xaf, 0x95, 0x3b, + 0xe0, 0x9a, 0x12, 0x2d, 0x42, 0x1a, 0xf5, 0x49, 0x5d, 0x5a, 0x56, 0x17, + 0xed, 0xfa, 0x99, 0x67, 0xe6, 0x8f, 0x2f, 0xca, 0xe1, 0xf6, 0xe3, 0xdb +}; +static const uint8_t nist_186_2_ecdsa_testvector_116_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x85, 0x28, 0xbc, 0xa3, 0x28, 0x78, 0xd7, 0x41, 0xb6, 0xfe, 0xfb, + 0xb0, 0x2a, 0xe9, 0x7f, 0x11, 0x4a, 0xdb, 0x81, 0x6f, 0xf4, 0xb9, 0xc9, + 0xb2, 0xd0, 0x4a, 0x6b, 0x65, 0xb1, 0x3b, 0x9b, 0xbb, 0xdd, 0x55, 0x4d +}; +/* k = 1e90d37fe1d50b7d1ceadf965452ef3b724ff79fec1c907102ca873fbf33fd788341c30 */ +static const uint8_t nist_186_2_ecdsa_testvector_116_out[] = { +/* R - byte alignment */ + 0x00, 0xf5, 0x77, 0x63, 0xe5, 0x26, 0x31, 0xde, 0xb2, 0x4a, 0x53, 0x4f, + 0xba, 0xde, 0x5d, 0x71, 0xec, 0x38, 0x1c, 0xe1, 0xf3, 0x9d, 0xcf, 0xd3, + 0xea, 0xbe, 0x52, 0x32, 0xe1, 0x0b, 0xbc, 0x4c, 0x91, 0x98, 0x51, 0x4c, +/* S - byte alignment */ + 0x01, 0x1a, 0xb8, 0x2d, 0x77, 0x0a, 0x91, 0xa3, 0x23, 0x3b, 0x72, 0x7c, + 0x31, 0x3f, 0x68, 0xbf, 0x7c, 0x6d, 0x82, 0xe3, 0xf5, 0xe5, 0xfa, 0x22, + 0xf1, 0x81, 0xf5, 0xfb, 0x38, 0x29, 0x82, 0x41, 0x9b, 0xbd, 0x95, 0x4c +}; +static const uint8_t nist_186_2_ecdsa_testvector_117_ptx[] = { +/* Msg */ + 0x72, 0xf3, 0xf9, 0xfb, 0xa5, 0xc0, 0x98, 0x4a, 0x73, 0x6d, 0x8f, 0xa6, + 0xd8, 0x10, 0x6f, 0xef, 0x89, 0x9e, 0x26, 0xe5, 0x91, 0x01, 0xc8, 0xe1, + 0x3c, 0x6a, 0x8f, 0xc3, 0x34, 0xe9, 0x20, 0x2b, 0xea, 0x3b, 0x0f, 0xec, + 0x37, 0xe3, 0xa6, 0xbd, 0x44, 0x7c, 0xe2, 0x32, 0xa7, 0x4d, 0xbf, 0xeb, + 0xce, 0x1e, 0xb5, 0x0c, 0xa1, 0x4a, 0x83, 0xec, 0x63, 0x16, 0x2b, 0x12, + 0xd9, 0x41, 0x3e, 0x5d, 0xaf, 0xdc, 0x59, 0x82, 0x17, 0x5c, 0xf0, 0xbc, + 0xb3, 0xee, 0x4a, 0xbe, 0xb5, 0x0a, 0xcd, 0xed, 0x45, 0x4b, 0x7c, 0xcc, + 0x23, 0x7e, 0xbe, 0xb7, 0x8d, 0xf9, 0x61, 0xd5, 0x63, 0x2e, 0xde, 0x48, + 0x89, 0x7f, 0xdf, 0xa6, 0x8d, 0x54, 0xfe, 0xad, 0x89, 0x6b, 0xd0, 0x32, + 0x4b, 0x70, 0x22, 0x5b, 0xb4, 0xce, 0x82, 0x0e, 0x5e, 0xc4, 0x02, 0xa9, + 0x81, 0xbb, 0x38, 0xf4, 0x18, 0xd7, 0x89, 0x54 +}; +static const uint8_t nist_186_2_ecdsa_testvector_117_private[] = { +/* d - byte alignment */ + 0x00, 0x7a, 0x71, 0xfd, 0x04, 0xdf, 0xfa, 0x5c, 0x22, 0xe2, 0xde, 0x6b, + 0xea, 0x0b, 0xc1, 0xa9, 0x8f, 0xd6, 0xac, 0x39, 0xcf, 0x26, 0x12, 0xa4, + 0xaf, 0x1c, 0x4b, 0x3f, 0x2f, 0x82, 0xf9, 0xd8, 0x80, 0xd8, 0x1c, 0x29 +}; +static const uint8_t nist_186_2_ecdsa_testvector_117_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0x01, 0xc0, 0xc4, 0xe9, 0xe9, 0xbe, 0x16, 0x86, 0x12, 0x00, 0xb8, + 0x1f, 0x48, 0xe4, 0xbf, 0x3b, 0x7e, 0x4c, 0x7a, 0xb2, 0xf4, 0x8b, 0xbe, + 0xe3, 0xbf, 0x26, 0x92, 0x26, 0xf6, 0x9d, 0x57, 0xa3, 0xe3, 0x00, 0xe9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_117_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0x91, 0x7b, 0x38, 0xac, 0x03, 0x74, 0x89, 0x36, 0x7b, 0x57, 0x20, + 0x9a, 0x45, 0x59, 0xe1, 0xfe, 0xe9, 0x09, 0x72, 0x5a, 0xb8, 0x54, 0x34, + 0x27, 0x4e, 0xff, 0x49, 0xaf, 0x0e, 0x6d, 0xf2, 0x0c, 0x60, 0x5b, 0xff +}; +/* k = 03837ed333cef5e0ff44c70808e7a0e3d4c90eced420249c6aba43a064612add2256b93 */ +static const uint8_t nist_186_2_ecdsa_testvector_117_out[] = { +/* R - byte alignment */ + 0x01, 0x29, 0x82, 0xe4, 0x95, 0x21, 0x0f, 0x20, 0xe8, 0xfa, 0x92, 0x01, + 0xa1, 0x53, 0x5e, 0xeb, 0xec, 0xdd, 0xf3, 0x7e, 0x2f, 0x5c, 0x8b, 0xd8, + 0xc3, 0x20, 0x4f, 0xfe, 0x3a, 0x93, 0x4a, 0x30, 0x09, 0x32, 0xf2, 0xd7, +/* S - byte alignment */ + 0x00, 0x40, 0x08, 0xa9, 0x69, 0x3d, 0x40, 0x27, 0x78, 0x12, 0xe8, 0xf1, + 0x12, 0x1a, 0x3e, 0xc1, 0x92, 0xba, 0x88, 0x04, 0x8d, 0xce, 0x82, 0x11, + 0x83, 0xbd, 0xda, 0x79, 0x5f, 0x2b, 0x79, 0xe6, 0xcd, 0x1c, 0x05, 0x3f +}; +static const uint8_t nist_186_2_ecdsa_testvector_118_ptx[] = { +/* Msg */ + 0xd5, 0xec, 0xb0, 0xbe, 0x35, 0xdf, 0xe0, 0x4d, 0x67, 0xec, 0x11, 0xf5, + 0x02, 0x9e, 0xb1, 0x37, 0x15, 0x1c, 0x58, 0x1c, 0x15, 0x4f, 0x5c, 0x76, + 0x1a, 0x47, 0xa0, 0x68, 0x4b, 0xdb, 0xac, 0x28, 0x97, 0x90, 0x03, 0x04, + 0xa7, 0xbd, 0xb0, 0xa3, 0x10, 0xec, 0x23, 0x8e, 0xcc, 0x82, 0x3b, 0xee, + 0xeb, 0xa3, 0xa4, 0x98, 0x86, 0x50, 0x63, 0x46, 0xf5, 0xd2, 0xaf, 0x27, + 0x41, 0x5c, 0x03, 0x9b, 0xdc, 0xec, 0x71, 0x37, 0x90, 0x72, 0x39, 0x10, + 0xb6, 0x34, 0x9a, 0x36, 0xa8, 0x71, 0xe8, 0x7e, 0x79, 0x44, 0xdf, 0x85, + 0xe3, 0xcc, 0x37, 0xf1, 0x80, 0x8a, 0x78, 0xfa, 0x3d, 0x0a, 0x10, 0x2a, + 0x0d, 0xc6, 0xa3, 0x60, 0xda, 0x47, 0xa2, 0x1b, 0xc1, 0x8d, 0x1f, 0xf5, + 0x7e, 0xb1, 0xe0, 0x6e, 0x25, 0xc9, 0xb2, 0xeb, 0x14, 0x0c, 0xff, 0xff, + 0x25, 0x37, 0xa3, 0xe8, 0x28, 0x2f, 0xfc, 0x5d +}; +static const uint8_t nist_186_2_ecdsa_testvector_118_private[] = { +/* d - byte alignment */ + 0x01, 0xab, 0x85, 0x82, 0x15, 0x5c, 0xfa, 0x50, 0x64, 0x33, 0xac, 0xf6, + 0xc1, 0x25, 0x3f, 0xf2, 0x04, 0x34, 0x5c, 0x32, 0xe3, 0xe1, 0x41, 0x88, + 0x28, 0xe4, 0x68, 0xa6, 0x36, 0xbf, 0x65, 0xf4, 0x60, 0x01, 0xa2, 0x63 +}; +static const uint8_t nist_186_2_ecdsa_testvector_118_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0x35, 0x03, 0x5d, 0x24, 0x2f, 0x45, 0xe0, 0xf2, 0x57, 0x85, 0x53, + 0xe5, 0xc3, 0x10, 0x73, 0x57, 0x30, 0x7a, 0xa2, 0xde, 0x71, 0x3d, 0xf6, + 0xbe, 0xce, 0x98, 0x20, 0x90, 0xc1, 0xca, 0x76, 0x00, 0x96, 0xac, 0xa8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_118_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xe6, 0x82, 0x34, 0x13, 0xd9, 0x75, 0xe2, 0xf1, 0x23, 0x9f, 0x42, + 0xcb, 0x30, 0xbf, 0x4f, 0xbb, 0x8b, 0x88, 0x19, 0xde, 0xe6, 0x3f, 0x99, + 0x56, 0xa9, 0x53, 0xea, 0x10, 0xea, 0x6b, 0xd3, 0xc7, 0x4d, 0x91, 0x11 +}; +/* k = 11f07fdfe8534ff7b1d370bf3ee284e69e074ebd7c379cf5dbd271f6197adbb31a643f2 */ +static const uint8_t nist_186_2_ecdsa_testvector_118_out[] = { +/* R - byte alignment */ + 0x00, 0xd4, 0x83, 0xde, 0x90, 0x09, 0xee, 0xa6, 0x55, 0xc0, 0xf6, 0x6b, + 0x38, 0x8f, 0xc3, 0x55, 0xfe, 0x6d, 0xa7, 0x5e, 0x38, 0x64, 0xa2, 0x4c, + 0x78, 0x77, 0xf8, 0x7c, 0x33, 0x47, 0x3e, 0x5c, 0x5f, 0x72, 0x7b, 0xce, +/* S - byte alignment */ + 0x00, 0x5e, 0xdb, 0x94, 0xfd, 0xc3, 0xac, 0x1d, 0x55, 0x3c, 0x0f, 0xb4, + 0xde, 0x54, 0x1a, 0x0f, 0x84, 0x97, 0x15, 0xe2, 0x82, 0xbb, 0xf5, 0xd1, + 0xde, 0xc0, 0xec, 0x0e, 0x8f, 0xb2, 0x13, 0x0c, 0x95, 0x4a, 0x94, 0x38 +}; +static const uint8_t nist_186_2_ecdsa_testvector_119_ptx[] = { +/* Msg */ + 0xe3, 0xc8, 0x76, 0x07, 0x77, 0xf1, 0x96, 0x1e, 0x0b, 0xe4, 0xed, 0xc6, + 0x50, 0xa1, 0x52, 0x09, 0x75, 0xac, 0x02, 0xbc, 0x48, 0xa9, 0xe9, 0xb4, + 0x9f, 0x29, 0x1d, 0x37, 0xf6, 0xc4, 0xac, 0xb1, 0x59, 0x68, 0x97, 0xa8, + 0x85, 0xf0, 0x1e, 0xf2, 0x4a, 0xf8, 0x3e, 0x26, 0x33, 0xf0, 0x79, 0x50, + 0x69, 0x70, 0xd5, 0xe9, 0xd5, 0xcb, 0x27, 0x06, 0x85, 0xe7, 0x91, 0xcf, + 0x51, 0x4c, 0x4a, 0x33, 0xbe, 0x7a, 0x9d, 0xda, 0x22, 0x80, 0x35, 0x5b, + 0x09, 0xca, 0x97, 0xb0, 0xd8, 0x3b, 0xf0, 0xe7, 0xb0, 0x7c, 0x11, 0x19, + 0x95, 0x93, 0xb8, 0xa0, 0xd0, 0xb7, 0x11, 0x85, 0x91, 0x62, 0x7c, 0x38, + 0xd9, 0xa9, 0x91, 0x84, 0x97, 0xc9, 0x61, 0xc1, 0x12, 0x02, 0xff, 0x4c, + 0x86, 0xa8, 0x40, 0x34, 0x12, 0x77, 0xbe, 0x36, 0xd1, 0x27, 0x23, 0xec, + 0x48, 0x40, 0xa4, 0x41, 0x00, 0x30, 0xcb, 0x28 +}; +static const uint8_t nist_186_2_ecdsa_testvector_119_private[] = { +/* d - byte alignment */ + 0x00, 0x11, 0x06, 0x8d, 0x2c, 0x25, 0x04, 0x2c, 0x60, 0x84, 0x59, 0x61, + 0x57, 0x90, 0x91, 0x2e, 0x58, 0x7b, 0x67, 0xcf, 0x65, 0xa9, 0xb3, 0x0a, + 0x61, 0x96, 0x15, 0xf9, 0x16, 0x5e, 0xd8, 0x9f, 0x30, 0xdb, 0xb1, 0x2c +}; +static const uint8_t nist_186_2_ecdsa_testvector_119_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x02, 0xc0, 0x2e, 0x0b, 0x3c, 0xaa, 0xd8, 0x5b, 0x1c, 0xbf, 0x31, + 0xf9, 0x2d, 0x00, 0x41, 0x0a, 0xc3, 0xcd, 0x31, 0xb0, 0x08, 0x0c, 0x56, + 0x4b, 0x5a, 0x31, 0xb1, 0x5e, 0x7a, 0xa8, 0x3e, 0xef, 0x2d, 0xab, 0x21 +}; +static const uint8_t nist_186_2_ecdsa_testvector_119_public_y[] = { +/* Qy - byte alignment */ + 0x07, 0x6b, 0xe5, 0xed, 0xa9, 0x3a, 0x20, 0x78, 0xb0, 0xbb, 0x72, 0x2b, + 0xd9, 0x0e, 0x38, 0xe6, 0x18, 0xe8, 0x3d, 0x6b, 0x95, 0x01, 0x4f, 0x96, + 0x7f, 0xad, 0xb3, 0xbe, 0xd2, 0x87, 0x52, 0x9b, 0x0c, 0x1a, 0xa8, 0x28 +}; +/* k = 07e2c03faa50b97a323ed2622ac95da642d1e2c69e2635c2506c736f9cd9cb4aee27383 */ +static const uint8_t nist_186_2_ecdsa_testvector_119_out[] = { +/* R - byte alignment */ + 0x01, 0x39, 0x39, 0x0c, 0xf1, 0x1a, 0x28, 0x51, 0x48, 0x67, 0x2a, 0x70, + 0x6b, 0x69, 0x65, 0x03, 0x48, 0x8e, 0x11, 0xa2, 0xed, 0xc0, 0xff, 0x17, + 0x7a, 0x70, 0x00, 0x15, 0xfd, 0x5f, 0x87, 0x5c, 0xdd, 0xcc, 0xab, 0x7f, +/* S - byte alignment */ + 0x01, 0x0c, 0x8d, 0x96, 0x3c, 0x0d, 0xff, 0x78, 0x84, 0x96, 0x8b, 0xa6, + 0xb9, 0x6b, 0xbc, 0x42, 0xb1, 0xc7, 0x70, 0x6c, 0x30, 0xad, 0x35, 0xb7, + 0xec, 0x19, 0xde, 0xe5, 0xad, 0x8b, 0xb2, 0x40, 0xa8, 0x1b, 0x02, 0x50 +}; +static const uint8_t nist_186_2_ecdsa_testvector_120_ptx[] = { +/* Msg */ + 0x58, 0xc9, 0x19, 0xf5, 0xe8, 0xa7, 0x14, 0x7d, 0x23, 0xc1, 0xa6, 0x66, + 0xca, 0xe2, 0x3c, 0xf8, 0x59, 0xaa, 0xc8, 0xef, 0xe8, 0xe0, 0xc0, 0x74, + 0x4f, 0x09, 0x69, 0x4c, 0x8d, 0x3a, 0x55, 0x50, 0x6b, 0x2a, 0x2a, 0x1d, + 0x5c, 0x8b, 0xa6, 0x0c, 0xa8, 0x9b, 0xe0, 0x65, 0xc9, 0xf6, 0xd1, 0xcf, + 0x15, 0xae, 0x12, 0x0b, 0x9e, 0x9d, 0xe7, 0xe2, 0x57, 0xfa, 0x7d, 0x5c, + 0x78, 0x2b, 0x70, 0x33, 0x23, 0xda, 0x90, 0x87, 0x47, 0x4b, 0xe5, 0xd3, + 0xc5, 0xed, 0xf1, 0x20, 0xd1, 0x2f, 0x34, 0x79, 0x9b, 0x94, 0xf6, 0x9e, + 0x2f, 0x0a, 0x40, 0xfd, 0x9a, 0x78, 0x2c, 0xdd, 0x4f, 0x96, 0x5e, 0xdd, + 0xc9, 0x01, 0xd3, 0x9d, 0x71, 0x8f, 0xda, 0xbb, 0xc1, 0xdf, 0x5f, 0x01, + 0xaa, 0x35, 0x6f, 0xdc, 0x33, 0x85, 0xf9, 0x10, 0x64, 0xce, 0xd2, 0xab, + 0x62, 0xaa, 0xfc, 0x37, 0xdb, 0x22, 0x28, 0x34 +}; +static const uint8_t nist_186_2_ecdsa_testvector_120_private[] = { +/* d - byte alignment */ + 0x00, 0xef, 0xeb, 0xf8, 0x3d, 0xff, 0xf3, 0x4f, 0x1b, 0x3f, 0x4b, 0x33, + 0xd0, 0xa5, 0x5d, 0x53, 0xdd, 0xa7, 0xcc, 0xed, 0xbf, 0xfb, 0xe2, 0x59, + 0x4e, 0x4d, 0xb2, 0xd7, 0xcb, 0xc6, 0x81, 0xe2, 0x6f, 0xd3, 0x0c, 0xe0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_120_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0x01, 0xa1, 0xba, 0x3c, 0x25, 0xfa, 0xb1, 0xf6, 0xd3, 0xa0, 0x2a, + 0xfc, 0xe1, 0xad, 0xf3, 0x9c, 0x69, 0xa5, 0x1d, 0xe8, 0xce, 0x92, 0x58, + 0xe9, 0xec, 0x91, 0x12, 0xb8, 0x88, 0x55, 0x4b, 0x90, 0xc3, 0x39, 0xcb +}; +static const uint8_t nist_186_2_ecdsa_testvector_120_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0xca, 0xdd, 0x42, 0x98, 0x5e, 0xe5, 0x9e, 0x7b, 0xb3, 0x61, 0xbe, + 0x74, 0xc7, 0x20, 0x87, 0xa8, 0x88, 0x76, 0x2b, 0x43, 0xae, 0xcb, 0xbe, + 0xc7, 0x70, 0x5b, 0x5e, 0x9e, 0x5c, 0x01, 0x16, 0x34, 0x2f, 0xd3, 0x44 +}; +/* k = 11c175da1bcf4459d0da24dc404885157216c49dda35ceb2b055d5794ab7f1b6ac4002a */ +static const uint8_t nist_186_2_ecdsa_testvector_120_out[] = { +/* R - byte alignment */ + 0x00, 0xdc, 0x41, 0xd0, 0xa1, 0x32, 0x61, 0xe5, 0x14, 0xdf, 0x2a, 0x5c, + 0x73, 0x92, 0xfb, 0xed, 0xed, 0xf1, 0x12, 0x5b, 0x05, 0xaa, 0xd3, 0x49, + 0x68, 0xc9, 0xdd, 0x73, 0x2c, 0x26, 0x16, 0xc7, 0x73, 0xb2, 0xa0, 0x3a, +/* S - byte alignment */ + 0x00, 0x14, 0xa2, 0x53, 0x79, 0x4a, 0x90, 0xe6, 0x6a, 0xea, 0x23, 0xf5, + 0x31, 0x3a, 0x29, 0x55, 0x3b, 0xb7, 0xbf, 0x46, 0xfd, 0x46, 0x89, 0x17, + 0x78, 0xc7, 0x98, 0xd5, 0x8c, 0xe4, 0xa0, 0x24, 0x80, 0x52, 0x07, 0x9e +}; +/* [K-409] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_121_ptx[] = { +/* Msg */ + 0xb6, 0xab, 0x51, 0x3b, 0x9d, 0x08, 0x45, 0x80, 0xae, 0x77, 0x51, 0x95, + 0x01, 0x02, 0x64, 0x7d, 0x23, 0x51, 0x97, 0xbf, 0x0b, 0xcf, 0xbe, 0xaf, + 0x4f, 0x08, 0x3d, 0xee, 0x98, 0x55, 0x1e, 0x34, 0x54, 0xbc, 0x60, 0x4d, + 0xaa, 0x12, 0x91, 0x62, 0xb3, 0x62, 0x9f, 0x7a, 0xe7, 0x93, 0xeb, 0x40, + 0xd5, 0x44, 0x9f, 0x07, 0x18, 0xfb, 0x42, 0x0b, 0x86, 0x7f, 0x89, 0xfa, + 0xaa, 0x82, 0x70, 0xb3, 0x75, 0x83, 0x8a, 0x4d, 0x30, 0xf3, 0x95, 0x5b, + 0xb5, 0x97, 0x52, 0x6e, 0xdf, 0x2d, 0x94, 0xdc, 0x3f, 0x52, 0x96, 0xc0, + 0x10, 0xa3, 0x91, 0x42, 0x6d, 0x23, 0x8e, 0x19, 0xc2, 0xdd, 0x79, 0x4e, + 0x81, 0xca, 0x78, 0x42, 0x16, 0xf4, 0x7b, 0xf2, 0x1c, 0xdc, 0x13, 0x7a, + 0xd1, 0x19, 0x87, 0xd8, 0xc7, 0x43, 0x25, 0xf3, 0xdd, 0x0f, 0xd6, 0xdc, + 0x6e, 0xbb, 0xf5, 0x53, 0xc8, 0xad, 0x61, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_121_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x31, 0xb7, 0x2b, 0x38, 0x79, 0x86, 0x2d, 0xbf, 0xb6, 0xd0, + 0xb5, 0x74, 0x26, 0x7a, 0x56, 0x0e, 0xd5, 0xde, 0x2b, 0x88, 0x20, 0x63, + 0xe9, 0x67, 0xc1, 0x8a, 0x62, 0xbb, 0x4e, 0xe3, 0x42, 0xab, 0x54, 0x15, + 0x06, 0x32, 0xa9, 0xa8, 0x46, 0x28, 0x36, 0x02, 0x4c, 0xe6, 0x5d, 0x4c, + 0x79, 0x97, 0x2a, 0x3b +}; +static const uint8_t nist_186_2_ecdsa_testvector_121_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x2e, 0x80, 0x26, 0x16, 0x36, 0xdd, 0x38, 0x58, 0xf3, 0x12, 0x81, + 0xbd, 0x40, 0xd5, 0x19, 0x14, 0x64, 0x8b, 0x1b, 0x95, 0xb6, 0xab, 0x62, + 0x17, 0x84, 0xec, 0x11, 0xb2, 0x76, 0x77, 0x85, 0x90, 0xdd, 0x88, 0xf2, + 0x56, 0x64, 0x3d, 0xf3, 0xf2, 0x04, 0xba, 0x82, 0xdb, 0xc3, 0x8c, 0x19, + 0x7a, 0x92, 0xb6, 0x0a +}; +static const uint8_t nist_186_2_ecdsa_testvector_121_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xca, 0x47, 0x73, 0x03, 0xa5, 0x91, 0x65, 0x82, 0x81, 0xfb, 0x9f, + 0x48, 0x66, 0x3b, 0x53, 0x05, 0x65, 0xfa, 0x8e, 0xa0, 0x58, 0x7f, 0xd0, + 0x36, 0x1d, 0x6c, 0x83, 0x01, 0x30, 0xa9, 0xae, 0x14, 0x98, 0x55, 0x93, + 0x0a, 0x35, 0x86, 0x27, 0xc2, 0xcd, 0x8b, 0x66, 0x82, 0xe1, 0x6a, 0x72, + 0x70, 0x1d, 0x46, 0xa7 +}; +/* k = 00038421e9318c4cc05519a6eb81d87a1d16331f8e7cdac4f0c47c390a381e4bb193c43ea7eb5e47d4756d41e1eef586acf6741 */ +static const uint8_t nist_186_2_ecdsa_testvector_121_out[] = { +/* R - byte alignment */ + 0x00, 0x7a, 0xca, 0xa9, 0xa1, 0x3d, 0x6a, 0x0c, 0x7d, 0xf8, 0xe6, 0x0d, + 0x5d, 0x32, 0x44, 0x65, 0x85, 0x4d, 0x6f, 0x78, 0xa3, 0xe8, 0x1e, 0x94, + 0xee, 0x74, 0x4c, 0x7a, 0xe4, 0x5c, 0xce, 0x94, 0x68, 0xc8, 0x5b, 0x16, + 0xe2, 0xea, 0xfb, 0x18, 0x49, 0x01, 0xd9, 0x8b, 0xef, 0x18, 0xd5, 0x2e, + 0x8d, 0x93, 0x33, 0xf1, +/* S - byte alignment */ + 0x00, 0x3b, 0x24, 0x7f, 0x58, 0x1f, 0x59, 0x04, 0x70, 0xa9, 0x06, 0x64, + 0x28, 0x75, 0xb7, 0x49, 0x9b, 0x3a, 0xf1, 0x4a, 0x96, 0x14, 0xf4, 0xe6, + 0xaa, 0x00, 0xcd, 0x5e, 0xa3, 0xf5, 0xda, 0xc4, 0xf7, 0xf5, 0xf1, 0x33, + 0x32, 0x27, 0xb6, 0xcb, 0x0d, 0xea, 0x73, 0x62, 0xc7, 0x95, 0x69, 0x53, + 0x21, 0xf8, 0x00, 0x21 +}; +static const uint8_t nist_186_2_ecdsa_testvector_122_ptx[] = { +/* Msg */ + 0x12, 0x5c, 0x4b, 0x0a, 0x58, 0x3f, 0xc2, 0x86, 0x85, 0x18, 0x5b, 0x8a, + 0x46, 0xaa, 0x5f, 0x92, 0x39, 0xf4, 0x60, 0x30, 0xb7, 0xb3, 0xb8, 0xae, + 0xf1, 0x28, 0x32, 0xf4, 0x3e, 0x1b, 0x06, 0xad, 0xb3, 0x20, 0x0b, 0xa6, + 0xf5, 0x19, 0x28, 0x76, 0x4b, 0xfc, 0x0b, 0x64, 0xf7, 0xd7, 0x1e, 0x85, + 0xc7, 0x11, 0xb7, 0x25, 0xe7, 0xf2, 0x90, 0x68, 0xf9, 0x65, 0x76, 0x31, + 0x67, 0xfd, 0x45, 0x43, 0xf8, 0x37, 0x13, 0xa7, 0xa2, 0xff, 0xac, 0x4d, + 0xa0, 0x75, 0x3f, 0xf6, 0xc4, 0xf0, 0x56, 0x50, 0x0d, 0x43, 0x0b, 0x63, + 0x7c, 0x40, 0x79, 0x2d, 0x24, 0x7b, 0x72, 0x89, 0x81, 0x51, 0x70, 0x56, + 0x0a, 0x28, 0xcd, 0xd4, 0x09, 0xf7, 0x36, 0x51, 0xab, 0x0a, 0x5d, 0x06, + 0x53, 0xff, 0xee, 0x3c, 0x34, 0x15, 0xc5, 0xb3, 0x1f, 0xa6, 0x5e, 0x43, + 0x99, 0xf1, 0x8c, 0xc4, 0x31, 0x1d, 0x6e, 0x2c +}; +static const uint8_t nist_186_2_ecdsa_testvector_122_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x7a, 0x7c, 0x91, 0x60, 0x9a, 0x8b, 0x4f, 0xe2, 0xf9, 0x78, + 0x67, 0x88, 0x8f, 0x20, 0xbd, 0x02, 0x8d, 0xff, 0xf0, 0xf9, 0xd2, 0x78, + 0xb6, 0x85, 0x62, 0x33, 0xed, 0xa9, 0x2a, 0xb6, 0x52, 0x1a, 0x47, 0x90, + 0xb7, 0xd3, 0x17, 0xa1, 0x25, 0xec, 0xef, 0xe1, 0xcd, 0xce, 0x03, 0xe2, + 0x2e, 0xc4, 0xdc, 0x55 +}; +static const uint8_t nist_186_2_ecdsa_testvector_122_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x1c, 0xc6, 0xe1, 0xc8, 0x78, 0x91, 0xc7, 0x27, 0x20, 0x4a, 0xcb, + 0xcc, 0x85, 0x3e, 0xbe, 0x42, 0x29, 0x93, 0x38, 0xb8, 0x14, 0x44, 0x6b, + 0x9a, 0xe4, 0x0f, 0x73, 0x1f, 0x9e, 0x8f, 0x9e, 0x5c, 0xd9, 0x9a, 0x5e, + 0x47, 0x07, 0x87, 0x5e, 0xa8, 0x0e, 0x06, 0x7e, 0x08, 0x8e, 0x22, 0xe9, + 0xcc, 0x12, 0x5a, 0xc0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_122_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xab, 0x77, 0x02, 0xd8, 0x7a, 0x34, 0x09, 0x3c, 0x0a, 0xb9, 0xfb, + 0xac, 0xbe, 0x7d, 0x93, 0x31, 0xc4, 0xfd, 0xc5, 0x22, 0x0f, 0x8f, 0x02, + 0xc0, 0x69, 0xd4, 0xe4, 0xdb, 0x5a, 0x2f, 0xcd, 0x4f, 0x42, 0xea, 0x7f, + 0xab, 0xad, 0x70, 0x4c, 0x8c, 0x10, 0xb1, 0x2b, 0xd8, 0x13, 0x91, 0xa4, + 0x0a, 0xff, 0x90, 0xba +}; +/* k = 000700d3107da55e6b926e2b749bb4a7efc19775e838d19bdb647f0afb8d69ea58f42efb421850e7c0d3aec09790a44f29ed6ca */ +static const uint8_t nist_186_2_ecdsa_testvector_122_out[] = { +/* R - byte alignment */ + 0x00, 0x2b, 0xb5, 0xbf, 0x94, 0xce, 0x12, 0x29, 0xa0, 0xdc, 0xfc, 0x5c, + 0x49, 0xf8, 0xb1, 0x14, 0xe2, 0x4f, 0xb5, 0x65, 0xca, 0x2c, 0x72, 0x11, + 0xf0, 0x44, 0xe2, 0x9d, 0xf2, 0xae, 0x55, 0xec, 0xad, 0x9d, 0x4e, 0x7d, + 0x47, 0x49, 0xa8, 0xb9, 0x6f, 0x1f, 0x47, 0xa8, 0x77, 0x94, 0x6d, 0x85, + 0x93, 0x94, 0xda, 0xd4, +/* S - byte alignment */ + 0x00, 0x61, 0x68, 0xfd, 0x2d, 0x43, 0xa3, 0xcf, 0x8c, 0x8a, 0x1d, 0xf8, + 0xdd, 0x03, 0x81, 0x20, 0xdf, 0x95, 0xbd, 0x8c, 0x5b, 0xd0, 0xef, 0x85, + 0x4a, 0x11, 0x8b, 0x88, 0x14, 0x01, 0x76, 0x52, 0x9a, 0x9b, 0xfc, 0x71, + 0x31, 0x42, 0x72, 0x68, 0xa7, 0x25, 0xda, 0xec, 0x4b, 0x6a, 0x86, 0xe6, + 0xc2, 0x23, 0x50, 0x84 +}; +static const uint8_t nist_186_2_ecdsa_testvector_123_ptx[] = { +/* Msg */ + 0xaf, 0x81, 0x7d, 0xe5, 0x87, 0x42, 0xa0, 0x88, 0xb6, 0xab, 0xc4, 0x3d, + 0x72, 0x29, 0x73, 0xf9, 0x27, 0x89, 0x12, 0x17, 0x19, 0x0e, 0xae, 0x05, + 0x4c, 0xc1, 0xf8, 0x3e, 0xa1, 0x09, 0x8d, 0x78, 0x41, 0x7b, 0x7b, 0x1e, + 0x3e, 0xf3, 0x01, 0x00, 0x78, 0xe4, 0x97, 0x4a, 0xbe, 0xec, 0x2e, 0xb2, + 0x36, 0xac, 0xb9, 0xf6, 0xff, 0xd6, 0xec, 0x86, 0x14, 0x87, 0x44, 0x7d, + 0x74, 0xd8, 0x47, 0xd6, 0x80, 0xb0, 0x0d, 0xdd, 0xa4, 0xdc, 0xff, 0xe3, + 0x39, 0x61, 0xdf, 0x36, 0xaa, 0x10, 0x09, 0x51, 0xd6, 0x5c, 0xf8, 0x4f, + 0xb6, 0x69, 0x0b, 0xa6, 0x40, 0x65, 0x89, 0x11, 0x8b, 0x1b, 0xe4, 0xce, + 0x33, 0xc5, 0x3a, 0x0a, 0xff, 0x22, 0x21, 0x9a, 0xc1, 0xc9, 0xa4, 0xeb, + 0x7e, 0xbd, 0x89, 0x3c, 0xcf, 0x41, 0xd6, 0x0a, 0x87, 0xee, 0x93, 0xcc, + 0x96, 0x02, 0xd0, 0xe1, 0x2e, 0xfb, 0xea, 0xc7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_123_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x38, 0x42, 0x1e, 0x93, 0x18, 0xc4, 0xcc, 0x05, 0x51, 0x9a, + 0x6e, 0xb8, 0x1d, 0x87, 0xa1, 0xd1, 0x63, 0x31, 0xf8, 0xe7, 0xcd, 0xac, + 0x4f, 0x0c, 0x47, 0xc3, 0x90, 0xa3, 0x81, 0xe4, 0xbb, 0x19, 0x3c, 0x43, + 0xea, 0x7e, 0xb5, 0xe4, 0x7d, 0x47, 0x56, 0xd4, 0x1e, 0x1e, 0xef, 0x58, + 0x6a, 0xcf, 0x67, 0x41 +}; +static const uint8_t nist_186_2_ecdsa_testvector_123_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xfa, 0xca, 0xa9, 0xa1, 0x3d, 0x6a, 0x0c, 0x7d, 0xf8, 0xe6, 0x0d, + 0x5d, 0x32, 0x44, 0x65, 0x85, 0x4d, 0x6f, 0x78, 0xa3, 0xe8, 0x1e, 0x94, + 0xee, 0x74, 0x47, 0x99, 0x6f, 0x75, 0x4d, 0x52, 0xc9, 0x88, 0x87, 0x63, + 0xe3, 0x63, 0x17, 0x93, 0xf4, 0xb9, 0x38, 0x9d, 0xd1, 0x2e, 0x60, 0x59, + 0x2d, 0xee, 0x53, 0x5e +}; +static const uint8_t nist_186_2_ecdsa_testvector_123_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x50, 0x25, 0x9a, 0x8e, 0xfd, 0xf3, 0x9f, 0x94, 0x79, 0x72, 0x24, + 0x88, 0xb3, 0x6f, 0x8f, 0x37, 0xd6, 0x25, 0xc4, 0xfa, 0x98, 0xfc, 0xd7, + 0x1e, 0x37, 0x06, 0x7d, 0x2a, 0xda, 0x08, 0x6d, 0xd4, 0x7e, 0x35, 0xf9, + 0xb3, 0x0d, 0xb2, 0xbe, 0xd8, 0x70, 0x3d, 0xdf, 0x42, 0x5c, 0x67, 0x02, + 0xc5, 0xe0, 0xc3, 0xab +}; +/* k = 00062b38c52225795d13c0c60c0124cb90748338c1a3960166d0d5282e203207c2da1dacd1d4af81614a6ad94ad3a64c29cb344 */ +static const uint8_t nist_186_2_ecdsa_testvector_123_out[] = { +/* R - byte alignment */ + 0x00, 0x42, 0xd6, 0x10, 0x96, 0x59, 0xda, 0xbb, 0xa1, 0x15, 0x30, 0x53, + 0xa5, 0x45, 0x98, 0x7c, 0x13, 0x0e, 0x54, 0x3c, 0x0e, 0x60, 0xa7, 0x06, + 0xa8, 0x8a, 0xdf, 0x93, 0x81, 0x1a, 0xee, 0xe4, 0x88, 0x19, 0xf7, 0x6a, + 0x66, 0xc1, 0x05, 0xf9, 0x99, 0xd9, 0x2c, 0x9f, 0x5c, 0x66, 0xb8, 0xcd, + 0xc1, 0xde, 0x9e, 0x01, +/* S - byte alignment */ + 0x00, 0x15, 0x17, 0x07, 0xd2, 0x54, 0x34, 0x04, 0xf2, 0x6f, 0x8b, 0x6a, + 0xf3, 0x8f, 0x82, 0x63, 0xea, 0x2a, 0x7a, 0x0a, 0x42, 0xb0, 0x53, 0x35, + 0x85, 0xb4, 0x41, 0x99, 0x1e, 0x81, 0xf8, 0x04, 0xf4, 0x32, 0x5e, 0x3a, + 0xb4, 0x08, 0x4c, 0x91, 0x69, 0xda, 0x5a, 0xe3, 0x0c, 0x11, 0x2d, 0x13, + 0x39, 0x8f, 0x15, 0xb1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_124_ptx[] = { +/* Msg */ + 0xa2, 0x8c, 0x69, 0xb4, 0x21, 0x1f, 0xc1, 0xb6, 0x35, 0xd1, 0x27, 0x56, + 0x23, 0xdf, 0xb1, 0xe0, 0x54, 0x23, 0x9f, 0x1f, 0xb3, 0xe9, 0xe3, 0xd3, + 0x57, 0xff, 0xe1, 0x60, 0x62, 0x0b, 0x73, 0xc4, 0x29, 0x21, 0x30, 0xcb, + 0x95, 0x95, 0xee, 0x86, 0xc9, 0x0e, 0x85, 0xf9, 0x04, 0xdc, 0xd6, 0x14, + 0xc9, 0x8c, 0x0c, 0xe5, 0x3e, 0xb9, 0x22, 0x0b, 0xd3, 0x25, 0xa6, 0x6e, + 0x23, 0x08, 0xbc, 0x2d, 0x1f, 0xa7, 0x65, 0xd8, 0x69, 0x29, 0x01, 0xe0, + 0xfe, 0xa6, 0x13, 0x4b, 0x18, 0x82, 0x45, 0xac, 0x53, 0xf9, 0xac, 0x53, + 0x0e, 0xfa, 0x4c, 0xc1, 0x14, 0x39, 0xdf, 0x5f, 0x7c, 0x80, 0xd2, 0x6f, + 0xcd, 0x45, 0x91, 0x42, 0x66, 0x82, 0x04, 0xab, 0x1d, 0xc1, 0x59, 0xb5, + 0x27, 0x76, 0x05, 0x91, 0x38, 0x92, 0x05, 0xd2, 0xea, 0x55, 0x6a, 0xdd, + 0x63, 0x64, 0x14, 0x9a, 0x32, 0x1b, 0xbe, 0x70 +}; +static const uint8_t nist_186_2_ecdsa_testvector_124_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x76, 0x2e, 0x08, 0xaa, 0x0b, 0xad, 0xdf, 0x4a, 0x50, 0xb1, + 0x69, 0xca, 0x78, 0xc5, 0xa1, 0x9b, 0xe0, 0x3e, 0x7f, 0x11, 0x6f, 0xad, + 0x0e, 0x41, 0x69, 0x72, 0x32, 0x49, 0x20, 0x60, 0xa5, 0x2e, 0x30, 0x64, + 0xf2, 0xc8, 0xd0, 0x54, 0x86, 0x13, 0x85, 0xb0, 0x44, 0xba, 0xa1, 0xec, + 0xaa, 0x0b, 0x90, 0x1c +}; +static const uint8_t nist_186_2_ecdsa_testvector_124_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xb3, 0xec, 0x10, 0x86, 0x8f, 0xc3, 0x6d, 0x33, 0x25, 0x4f, 0xd3, + 0xf1, 0x25, 0xf0, 0xe6, 0xac, 0x7c, 0x73, 0x47, 0x49, 0x45, 0x98, 0x7a, + 0xc2, 0x7e, 0x13, 0x13, 0xba, 0x00, 0x45, 0xe8, 0xd2, 0x43, 0x77, 0x16, + 0x0f, 0x43, 0xa6, 0xea, 0xcf, 0x02, 0xcb, 0x70, 0x02, 0x9c, 0xee, 0xd1, + 0x88, 0x43, 0x1d, 0x4c +}; +static const uint8_t nist_186_2_ecdsa_testvector_124_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x21, 0x5e, 0xe1, 0xa5, 0xf5, 0xd0, 0x2b, 0xf0, 0xda, 0xfe, 0x15, + 0x5e, 0x9c, 0x95, 0x64, 0x11, 0xc6, 0xff, 0xcc, 0x6c, 0x4a, 0x2c, 0x4b, + 0x0b, 0xdc, 0xeb, 0x11, 0x26, 0xb4, 0xa1, 0x21, 0xe6, 0xf7, 0x70, 0x28, + 0xa3, 0x69, 0x96, 0x51, 0x06, 0xe3, 0x04, 0xa5, 0x38, 0xae, 0xa8, 0x83, + 0x97, 0xb7, 0xd0, 0xf7 +}; +/* k = 0007a496e31791af248ee59fdcb77eb5547ac6d4ca36383d0870d3a35c81b3d620426458586241519543b33e394be5cfa2b9139 */ +static const uint8_t nist_186_2_ecdsa_testvector_124_out[] = { +/* R - byte alignment */ + 0x00, 0x69, 0xb8, 0xc4, 0xbe, 0x27, 0xf0, 0x5e, 0xc3, 0x48, 0x36, 0xbc, + 0xd8, 0xac, 0xc6, 0x65, 0xe4, 0x57, 0xf1, 0x55, 0x2c, 0x1d, 0x4b, 0x36, + 0x09, 0x43, 0xc3, 0x50, 0x39, 0xb6, 0xf2, 0xf3, 0xa7, 0xba, 0xe9, 0x7b, + 0x91, 0x02, 0xca, 0x7a, 0xf2, 0x87, 0x5c, 0x73, 0x6d, 0x1e, 0xf2, 0x90, + 0xed, 0x8d, 0x75, 0x88, +/* S - byte alignment */ + 0x00, 0x52, 0xcb, 0x8b, 0xd5, 0xdd, 0x83, 0xe5, 0xd5, 0xa7, 0x40, 0xb5, + 0x62, 0x02, 0xb4, 0xf2, 0xf3, 0x9f, 0xf6, 0xe9, 0x8f, 0xfa, 0x38, 0x19, + 0x3e, 0x6b, 0x6c, 0xc4, 0x5b, 0x76, 0x8e, 0x90, 0xa8, 0xe3, 0xeb, 0x66, + 0x52, 0x07, 0x85, 0xf9, 0x69, 0xb6, 0xed, 0xf0, 0x87, 0x4d, 0xd8, 0xc5, + 0xdf, 0x5d, 0x1a, 0x9c +}; +static const uint8_t nist_186_2_ecdsa_testvector_125_ptx[] = { +/* Msg */ + 0x1a, 0x11, 0x2a, 0x50, 0x38, 0x63, 0x6f, 0x16, 0x6e, 0x6e, 0x84, 0x74, + 0xc0, 0x77, 0xab, 0x72, 0xa4, 0x6c, 0x2c, 0x0e, 0xb5, 0xc9, 0xa5, 0x3a, + 0xab, 0xb8, 0xa2, 0x25, 0x8b, 0x7c, 0x6d, 0xbb, 0x1b, 0x0f, 0x28, 0x6f, + 0x99, 0x0a, 0x18, 0x38, 0xac, 0xc6, 0x44, 0xd9, 0x9b, 0xc1, 0x3f, 0x66, + 0xbd, 0x43, 0x42, 0x04, 0x31, 0x41, 0x7d, 0xf0, 0xce, 0x81, 0xaf, 0xc3, + 0x5d, 0xff, 0xf5, 0xf4, 0x06, 0x90, 0xdf, 0x9e, 0x09, 0xc5, 0xc9, 0x83, + 0xaf, 0x12, 0x69, 0x52, 0x7f, 0x2f, 0xa4, 0x25, 0xb4, 0xbf, 0xa6, 0x4e, + 0xef, 0x30, 0x31, 0x53, 0x2a, 0xe2, 0x35, 0x37, 0xed, 0x8b, 0xa2, 0xfb, + 0xc4, 0xda, 0x7a, 0x65, 0xf0, 0x5a, 0x2a, 0x00, 0x5d, 0x9a, 0x1a, 0x64, + 0xd4, 0x8b, 0x83, 0xb7, 0x72, 0x29, 0x81, 0x74, 0x59, 0x5d, 0x69, 0x6b, + 0xa5, 0x22, 0x5c, 0x0a, 0xa2, 0xe8, 0x1c, 0xda +}; +static const uint8_t nist_186_2_ecdsa_testvector_125_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x61, 0xeb, 0x2b, 0xae, 0x31, 0x10, 0x95, 0xea, 0x51, 0x9f, + 0x89, 0xea, 0xd3, 0x8d, 0xa3, 0x78, 0xe3, 0x2e, 0xfa, 0x65, 0xab, 0x4f, + 0xf8, 0xc2, 0xe9, 0xbf, 0xaa, 0x6f, 0xeb, 0x8f, 0x44, 0x38, 0x74, 0x2a, + 0xd3, 0x31, 0x1a, 0x4b, 0x8d, 0x4f, 0x07, 0x38, 0x93, 0xeb, 0xb2, 0x11, + 0x41, 0x0f, 0xc8, 0xa1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_125_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xfa, 0xa2, 0x6a, 0xf7, 0xa4, 0x77, 0xc2, 0x41, 0x38, 0x7d, 0xfb, + 0xec, 0x89, 0xf6, 0xd2, 0x46, 0xdd, 0x46, 0x45, 0xa2, 0xd6, 0x89, 0x27, + 0x67, 0xe3, 0xf3, 0xa4, 0x6e, 0x26, 0x2a, 0xb4, 0x9a, 0x89, 0xc6, 0x9a, + 0x9a, 0xb8, 0x88, 0x78, 0x24, 0x1f, 0xf7, 0xe2, 0x67, 0xb1, 0x18, 0xab, + 0x11, 0x65, 0xcd, 0x16 +}; +static const uint8_t nist_186_2_ecdsa_testvector_125_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xdb, 0xde, 0x2e, 0x35, 0xc7, 0xec, 0xbb, 0x73, 0xca, 0x32, 0x76, + 0x1b, 0x87, 0x2e, 0x09, 0xe1, 0x92, 0xdc, 0xd3, 0x0f, 0xcd, 0xd6, 0x36, + 0x6a, 0x7c, 0xb7, 0x60, 0x0b, 0x1d, 0xcc, 0x0d, 0xe3, 0x33, 0xfe, 0xec, + 0xf5, 0x90, 0xf1, 0x0b, 0xa4, 0xe3, 0x7e, 0xf0, 0x55, 0xba, 0xde, 0x25, + 0xff, 0xc9, 0x98, 0xc6 +}; +/* k = 00036dc870af1992f9dac60892e35b7d3feb89a05a1fff46652816de8d8f8ebe1c51ad06009eaf1483269856bf1cb1a85a14c11 */ +static const uint8_t nist_186_2_ecdsa_testvector_125_out[] = { +/* R - byte alignment */ + 0x00, 0x28, 0xa9, 0xc2, 0xbd, 0x4b, 0xa0, 0x2f, 0x64, 0x5b, 0xc5, 0x0a, + 0xdb, 0xfe, 0x28, 0x9c, 0x22, 0xfb, 0x90, 0xd7, 0x1b, 0x6e, 0x92, 0x6f, + 0x67, 0xfb, 0x6b, 0x17, 0x7b, 0xea, 0x53, 0x8f, 0xef, 0x57, 0x83, 0xf5, + 0x5f, 0xa6, 0x46, 0xb0, 0xc4, 0x45, 0xff, 0x54, 0x10, 0xc8, 0x39, 0xfd, + 0xd5, 0xf1, 0x7f, 0xef, +/* S - byte alignment */ + 0x00, 0x75, 0x40, 0x75, 0xcc, 0x6f, 0xfe, 0x8d, 0xcb, 0xe0, 0x72, 0x6f, + 0x22, 0x22, 0x0a, 0xf5, 0x69, 0xc0, 0x69, 0x1a, 0xf0, 0x11, 0x5a, 0xeb, + 0x1d, 0x09, 0x05, 0x4f, 0xfa, 0x77, 0xd2, 0x74, 0xff, 0x02, 0xe3, 0x1c, + 0xc3, 0xa2, 0xc8, 0x42, 0x8a, 0xfc, 0x9c, 0x24, 0x67, 0xbf, 0xb0, 0x64, + 0x3e, 0x56, 0xcd, 0x47 +}; +static const uint8_t nist_186_2_ecdsa_testvector_126_ptx[] = { +/* Msg */ + 0x1f, 0xaf, 0x00, 0x7c, 0x6e, 0x57, 0x8e, 0x86, 0x79, 0xfc, 0x92, 0xe5, + 0x5b, 0x9a, 0x25, 0x1f, 0x0f, 0x95, 0x30, 0x4c, 0xe1, 0x58, 0x7f, 0xd5, + 0x22, 0x3c, 0x17, 0x7c, 0x20, 0xac, 0xca, 0x9c, 0x56, 0x88, 0x08, 0xb2, + 0xdf, 0xc6, 0xf8, 0x1d, 0x31, 0x5f, 0xc7, 0x22, 0x07, 0x69, 0x41, 0x33, + 0x9f, 0x80, 0x9e, 0x71, 0x26, 0x6b, 0x9e, 0x6f, 0x71, 0xfd, 0xd8, 0x39, + 0xed, 0x38, 0x4e, 0x95, 0xd9, 0xb9, 0x46, 0x88, 0xb2, 0x50, 0x55, 0x1c, + 0xef, 0xee, 0xbd, 0x61, 0xef, 0xc4, 0xf9, 0xb2, 0x30, 0xa9, 0x95, 0x39, + 0xc1, 0xbc, 0x43, 0xb6, 0xfa, 0x4b, 0x2c, 0x7b, 0x6a, 0xf4, 0x84, 0xbb, + 0x11, 0x0a, 0x61, 0x05, 0xcf, 0x3b, 0xcd, 0x0c, 0x1d, 0x6f, 0x19, 0xa9, + 0xfb, 0xf2, 0x75, 0x23, 0x29, 0xd6, 0xbe, 0xad, 0x9a, 0x93, 0x97, 0x30, + 0x26, 0xf1, 0xbb, 0x4b, 0x7f, 0x28, 0x92, 0x99 +}; +static const uint8_t nist_186_2_ecdsa_testvector_126_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x48, 0x67, 0xad, 0xe1, 0x7b, 0x1c, 0x21, 0x96, 0xfb, 0x37, + 0x7e, 0xa1, 0x7a, 0xaa, 0x1c, 0xb1, 0x75, 0x2d, 0x5e, 0xfe, 0x9f, 0xff, + 0xaf, 0xf7, 0x7b, 0x76, 0xf6, 0x3d, 0xa7, 0xf6, 0xb4, 0x09, 0x3d, 0xc9, + 0x83, 0xca, 0xe2, 0xa4, 0x44, 0x79, 0xdd, 0xfe, 0xc3, 0x99, 0x92, 0xee, + 0x3b, 0x37, 0xf2, 0xc7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_126_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xb3, 0xce, 0x1f, 0xbf, 0x76, 0x41, 0x0f, 0x49, 0x23, 0xea, 0x96, + 0x8e, 0xa4, 0xf2, 0x6e, 0x2f, 0x5a, 0xb0, 0x34, 0xb8, 0xa1, 0xb7, 0xe3, + 0x7f, 0xf2, 0xa6, 0xb9, 0x57, 0x24, 0x5e, 0x68, 0x21, 0xf3, 0x05, 0x38, + 0x7f, 0xdf, 0xbd, 0xb0, 0x73, 0xf7, 0x2d, 0x2c, 0x18, 0xc2, 0x28, 0x5b, + 0x12, 0xd8, 0xb1, 0x86 +}; +static const uint8_t nist_186_2_ecdsa_testvector_126_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x5d, 0x15, 0xf2, 0x47, 0x12, 0x82, 0xac, 0x16, 0x3d, 0x9d, 0x66, + 0xd7, 0x19, 0xd0, 0x0a, 0x33, 0xcd, 0x99, 0x5d, 0x59, 0xb5, 0xd7, 0xd5, + 0xb2, 0xa9, 0x21, 0x34, 0x4f, 0xb6, 0x59, 0x1c, 0x60, 0x65, 0x34, 0x89, + 0x40, 0x84, 0x84, 0xd8, 0xa4, 0x3f, 0xd2, 0x71, 0xa1, 0x2b, 0xc7, 0x45, + 0x1a, 0xb4, 0x38, 0xdc +}; +/* k = 00071d3e240a04eac60d80f26557009d8f66ecdf9be60ad72ce159bdbbc597cfe6e9125beec626d6769cef109fa0d732978646e */ +static const uint8_t nist_186_2_ecdsa_testvector_126_out[] = { +/* R - byte alignment */ + 0x00, 0x45, 0x7b, 0x85, 0x03, 0x6a, 0x52, 0x26, 0x69, 0xf6, 0xd5, 0xf8, + 0x22, 0xb8, 0x85, 0x77, 0xf6, 0x3f, 0x58, 0xcb, 0x87, 0x98, 0x01, 0x59, + 0xa7, 0xb8, 0xfb, 0xde, 0xad, 0x41, 0xde, 0x4f, 0x24, 0x03, 0xe1, 0x7a, + 0xab, 0x49, 0xdd, 0xca, 0x29, 0x1c, 0x8d, 0x39, 0xe4, 0x51, 0x73, 0x68, + 0xb4, 0xaf, 0xef, 0x71, +/* S - byte alignment */ + 0x00, 0x10, 0x8f, 0xc9, 0x58, 0x3b, 0x97, 0x90, 0x8f, 0xfb, 0x8e, 0xf4, + 0x7c, 0x6e, 0xea, 0xa9, 0xeb, 0x10, 0xf3, 0xed, 0xa1, 0xad, 0x66, 0xf8, + 0x24, 0x7a, 0xa8, 0xf6, 0x72, 0x7b, 0xb1, 0xdb, 0x15, 0x42, 0x4c, 0xbf, + 0x2f, 0x7e, 0x8a, 0xbf, 0x29, 0xf9, 0xb3, 0x34, 0x15, 0xb3, 0xc6, 0xff, + 0x99, 0x73, 0x83, 0x61 +}; +static const uint8_t nist_186_2_ecdsa_testvector_127_ptx[] = { +/* Msg */ + 0xc4, 0x31, 0x0a, 0x0d, 0x8c, 0xec, 0xe8, 0x90, 0xee, 0x3f, 0xbe, 0xdb, + 0xe9, 0x02, 0x9a, 0x13, 0x16, 0x37, 0x09, 0xe6, 0x81, 0x8c, 0x88, 0x2a, + 0xb7, 0x28, 0x3b, 0xc0, 0x20, 0xa3, 0xe2, 0xbf, 0x8f, 0x56, 0x08, 0xce, + 0x18, 0xd6, 0x7d, 0xd2, 0x22, 0xbb, 0x07, 0xca, 0xbc, 0xa6, 0x55, 0xf6, + 0x35, 0x82, 0x34, 0x3f, 0xe6, 0x09, 0x06, 0xd3, 0x53, 0x8a, 0x6f, 0x10, + 0x73, 0xea, 0x51, 0xa3, 0x4b, 0xea, 0xfb, 0xf1, 0xc2, 0xa7, 0x9d, 0xb6, + 0xb0, 0x67, 0xff, 0xeb, 0x38, 0x92, 0x73, 0xee, 0x58, 0xff, 0x09, 0xdd, + 0xbe, 0x71, 0x01, 0x42, 0xdd, 0x62, 0x86, 0xf6, 0x41, 0xff, 0x99, 0x3f, + 0x1f, 0x73, 0x4b, 0x3c, 0x31, 0x68, 0x2f, 0x83, 0xc0, 0xcb, 0x0f, 0x08, + 0x03, 0xd0, 0xde, 0x41, 0xa7, 0x37, 0xee, 0x87, 0xaf, 0xcd, 0x63, 0xc0, + 0x7e, 0x35, 0xe8, 0x3b, 0x32, 0xe8, 0xa0, 0xdb +}; +static const uint8_t nist_186_2_ecdsa_testvector_127_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x54, 0xe2, 0xa7, 0xc7, 0x44, 0x93, 0x63, 0xd7, 0x2f, 0x66, + 0x10, 0xf2, 0x93, 0x1e, 0x82, 0xa7, 0x24, 0xab, 0xea, 0x79, 0x30, 0xbd, + 0x36, 0xed, 0xcc, 0xa5, 0x7b, 0xdc, 0x84, 0xd4, 0x2e, 0x07, 0x0b, 0xf0, + 0xb7, 0x94, 0xde, 0x47, 0xd1, 0xb1, 0xe0, 0xc0, 0x97, 0x35, 0x0e, 0xf6, + 0x64, 0x97, 0x29, 0xa0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_127_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x25, 0xb1, 0x0b, 0x27, 0x9a, 0x04, 0x10, 0xbd, 0x42, 0x45, 0x11, + 0x2e, 0x51, 0xc2, 0x98, 0xbc, 0xa1, 0x43, 0x65, 0xf0, 0xd7, 0x26, 0xfe, + 0x85, 0xfb, 0x57, 0x7a, 0x17, 0xd3, 0xbe, 0xc8, 0xdc, 0x5d, 0x06, 0x92, + 0xdc, 0x83, 0xf4, 0x99, 0x03, 0x57, 0xf2, 0x99, 0x61, 0xa9, 0x61, 0xf0, + 0xd0, 0x16, 0x0a, 0xac +}; +static const uint8_t nist_186_2_ecdsa_testvector_127_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xa4, 0xbb, 0x6f, 0xe1, 0x8d, 0x9e, 0xd9, 0x78, 0xf8, 0xd6, 0x8a, + 0x0e, 0xda, 0xe6, 0x59, 0xe4, 0xa9, 0x3f, 0x23, 0xfa, 0x2a, 0x5a, 0xd3, + 0xcf, 0x70, 0x32, 0x77, 0xa5, 0x53, 0x34, 0xfa, 0x0b, 0x5a, 0x22, 0x1d, + 0x30, 0x51, 0xdf, 0x5a, 0xbd, 0x4f, 0x36, 0x50, 0x98, 0xbb, 0x88, 0x32, + 0x71, 0x62, 0x06, 0x25 +}; +/* k = 00016e79c6ee8d97dedd9c2b0fd56ad8a06d9a3690735656a47e664cfbb745ab61b620d8c33ef6467b316b2488566208397f4be */ +static const uint8_t nist_186_2_ecdsa_testvector_127_out[] = { +/* R - byte alignment */ + 0x00, 0x70, 0x9a, 0x59, 0x35, 0x1f, 0x81, 0x73, 0xf9, 0xdc, 0x85, 0x07, + 0x6c, 0x1d, 0xfa, 0x25, 0x79, 0x2f, 0xc9, 0xa2, 0xf8, 0xcc, 0xe5, 0x4b, + 0x72, 0xd0, 0x14, 0x66, 0x60, 0x67, 0x4c, 0x1f, 0x20, 0x5a, 0xec, 0x5f, + 0xef, 0x6d, 0x93, 0x52, 0xcb, 0xd8, 0xc4, 0xde, 0xc2, 0x44, 0x93, 0x0e, + 0xdd, 0x7c, 0x70, 0x9a, +/* S - byte alignment */ + 0x00, 0x26, 0x23, 0xbf, 0xa0, 0x1c, 0x32, 0xcc, 0x0a, 0x84, 0x43, 0x8d, + 0x60, 0xdd, 0xe1, 0xfe, 0x82, 0xe9, 0xb5, 0x61, 0x0f, 0x45, 0x19, 0xae, + 0x48, 0xe8, 0xa8, 0x82, 0xb2, 0x2b, 0xe6, 0x7e, 0xce, 0x8b, 0xa2, 0x98, + 0xec, 0x19, 0xce, 0x4b, 0xa7, 0xe6, 0x20, 0xa1, 0xa6, 0xc0, 0xb6, 0xde, + 0x12, 0x99, 0x6d, 0x77 +}; +static const uint8_t nist_186_2_ecdsa_testvector_128_ptx[] = { +/* Msg */ + 0xa8, 0xc9, 0xa5, 0x8a, 0xe4, 0x68, 0x16, 0x90, 0x05, 0xab, 0x9b, 0x57, + 0xed, 0x7e, 0xc1, 0x49, 0x2d, 0xbf, 0x3d, 0x54, 0xc8, 0xf2, 0xd3, 0x41, + 0x3a, 0x37, 0x76, 0x41, 0xb8, 0x7a, 0xb1, 0xc9, 0xba, 0xea, 0x45, 0xa0, + 0xb7, 0xac, 0x14, 0x37, 0x2f, 0xd0, 0x3d, 0x38, 0xef, 0x84, 0x89, 0x61, + 0x91, 0x87, 0x06, 0x93, 0x42, 0xe1, 0xf1, 0x26, 0xc8, 0xd2, 0xd9, 0x80, + 0xc3, 0x08, 0x02, 0xe6, 0x32, 0x14, 0x08, 0x91, 0x3a, 0x1f, 0xc4, 0x05, + 0x23, 0xd9, 0x73, 0x9e, 0xa4, 0xb3, 0x15, 0x6c, 0x60, 0x4e, 0x14, 0x41, + 0xb0, 0x33, 0x26, 0x07, 0xa3, 0xc4, 0x74, 0x57, 0x43, 0x73, 0xfc, 0x48, + 0x1a, 0x31, 0x34, 0x85, 0xf5, 0x29, 0xf0, 0xa3, 0xe8, 0xaf, 0x85, 0xb1, + 0x92, 0x73, 0x2f, 0x10, 0xa2, 0xfb, 0xb0, 0x85, 0x9a, 0x50, 0x3a, 0x8c, + 0xd4, 0xf7, 0x8f, 0xef, 0xc2, 0x22, 0x67, 0x98 +}; +static const uint8_t nist_186_2_ecdsa_testvector_128_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x58, 0xd1, 0x3f, 0x58, 0x45, 0xfd, 0xba, 0xa2, 0x3d, 0xb9, + 0xde, 0x5f, 0xb7, 0xdd, 0x25, 0x80, 0x1e, 0x49, 0x28, 0x8b, 0xee, 0x32, + 0xf6, 0x03, 0x5e, 0x69, 0xa2, 0x1d, 0xa8, 0xd3, 0x36, 0xe1, 0xc7, 0x6b, + 0x59, 0xe4, 0x26, 0x9f, 0x3a, 0xf8, 0x4d, 0x8d, 0x47, 0xaf, 0xfb, 0x48, + 0x25, 0xe4, 0x6e, 0xf2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_128_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x42, 0xa7, 0xe9, 0x7e, 0xa9, 0xec, 0x59, 0xfa, 0x59, 0x6b, 0x50, + 0x1c, 0xef, 0xc0, 0x31, 0x89, 0x91, 0x29, 0x32, 0xef, 0xd3, 0xa5, 0xf5, + 0xf3, 0xcf, 0x5d, 0x3f, 0x68, 0x11, 0x66, 0x57, 0x35, 0x22, 0xbf, 0xcf, + 0xf4, 0x0f, 0x08, 0x0b, 0x01, 0x3d, 0x57, 0x01, 0x0d, 0x33, 0x13, 0x63, + 0x5c, 0x06, 0x40, 0x90 +}; +static const uint8_t nist_186_2_ecdsa_testvector_128_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x45, 0xf0, 0x57, 0x14, 0x21, 0xd4, 0x88, 0x85, 0x3f, 0x5c, 0x61, + 0x46, 0x33, 0x03, 0xdd, 0x99, 0x6a, 0x7d, 0xca, 0xe2, 0x80, 0xa0, 0x13, + 0x8f, 0xdd, 0xbd, 0x8c, 0x05, 0xee, 0x51, 0xf2, 0xd4, 0x89, 0xf6, 0xbb, + 0xb9, 0x56, 0x16, 0x48, 0x02, 0xe2, 0xb6, 0xc6, 0xa8, 0x07, 0xf8, 0xdf, + 0x49, 0x01, 0x0e, 0x66 +}; +/* k = 00010d75461d11156b46f7dac65750135ced6271516de97b660ac9b535bf3ef20739089443c2257673591a970dabc12ba8e4064 */ +static const uint8_t nist_186_2_ecdsa_testvector_128_out[] = { +/* R - byte alignment */ + 0x00, 0x7d, 0xfc, 0x37, 0x83, 0x3f, 0x96, 0x63, 0xd4, 0xa4, 0xab, 0x2c, + 0xfa, 0x40, 0x20, 0x02, 0x10, 0x6d, 0x83, 0xb8, 0x9a, 0x3d, 0xa7, 0xc9, + 0x74, 0xff, 0x35, 0xf6, 0xd0, 0xa5, 0xa0, 0x30, 0x44, 0xf7, 0x83, 0x67, + 0xb9, 0xb4, 0x01, 0xd5, 0x22, 0x2b, 0x4d, 0xb2, 0xcd, 0xe1, 0x39, 0x7a, + 0xbb, 0xd7, 0x35, 0xb6, +/* S - byte alignment */ + 0x00, 0x37, 0x61, 0x43, 0xde, 0x67, 0xfe, 0xcd, 0xb6, 0xda, 0x1c, 0x82, + 0x65, 0xfb, 0x79, 0xea, 0x92, 0x79, 0x76, 0x78, 0xf2, 0x60, 0x13, 0xa0, + 0x25, 0x75, 0xde, 0xac, 0x47, 0x6c, 0xcd, 0x5d, 0x35, 0x92, 0xc4, 0xda, + 0xfa, 0x99, 0xc9, 0x2b, 0x84, 0x4c, 0xf7, 0x21, 0x63, 0xe8, 0xe8, 0x98, + 0x01, 0xbe, 0x32, 0x31 +}; +static const uint8_t nist_186_2_ecdsa_testvector_129_ptx[] = { +/* Msg */ + 0xf2, 0x32, 0x3a, 0x75, 0xbe, 0x27, 0x91, 0x18, 0x23, 0x50, 0x52, 0x5f, + 0xec, 0x58, 0x4f, 0x69, 0x0f, 0x6e, 0xcb, 0xf9, 0x90, 0x99, 0x82, 0x6e, + 0xa3, 0x4b, 0xea, 0xf5, 0x11, 0x3a, 0xb9, 0xfd, 0xdc, 0x6b, 0xa7, 0xeb, + 0x26, 0x8f, 0x75, 0x0f, 0x4f, 0x93, 0x2e, 0xd7, 0x5e, 0x73, 0xad, 0x43, + 0xa2, 0x4f, 0x5f, 0x99, 0x99, 0xc0, 0x4a, 0x5a, 0x10, 0x6c, 0x4e, 0x74, + 0x8c, 0xd8, 0xab, 0xb9, 0xe9, 0x7e, 0xc4, 0x90, 0x41, 0x20, 0x23, 0xeb, + 0x0f, 0x5b, 0xbc, 0x79, 0x94, 0x7f, 0x76, 0x1c, 0x7a, 0x9e, 0xe7, 0x9d, + 0xb8, 0xe3, 0x5f, 0x9f, 0xb5, 0x25, 0x29, 0xd1, 0xb0, 0xbc, 0x0d, 0x68, + 0x5f, 0x94, 0x19, 0xcd, 0xd6, 0x80, 0xa2, 0x92, 0xab, 0xd0, 0x85, 0xab, + 0x58, 0x25, 0xb2, 0xdb, 0xe0, 0x84, 0xec, 0x6c, 0xb6, 0xaa, 0xca, 0x23, + 0xda, 0x9f, 0x02, 0x73, 0x45, 0x8e, 0xe6, 0xf1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_129_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x6d, 0xff, 0xc3, 0xf5, 0x92, 0x2c, 0x17, 0xfa, 0x81, 0x38, + 0xf0, 0x9c, 0xce, 0x93, 0x47, 0x4d, 0xfd, 0x06, 0x78, 0x6c, 0x27, 0xe2, + 0x23, 0x38, 0x40, 0xb8, 0xcf, 0xd2, 0xbf, 0xf3, 0x83, 0xe1, 0xd7, 0x16, + 0x2b, 0xc5, 0x94, 0xd6, 0xf9, 0x58, 0x8c, 0xf8, 0xf9, 0x65, 0x3d, 0x28, + 0xa6, 0x99, 0xaa, 0x6d +}; +static const uint8_t nist_186_2_ecdsa_testvector_129_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x15, 0xb5, 0x99, 0x8b, 0x3a, 0xd4, 0xd8, 0x98, 0x77, 0xa0, 0x52, + 0x9d, 0x63, 0x15, 0x59, 0x47, 0xfa, 0x36, 0x8f, 0xaf, 0x70, 0x90, 0x5d, + 0xd2, 0xd3, 0x3b, 0x18, 0x3c, 0xb9, 0xeb, 0xef, 0x11, 0x49, 0x2d, 0x81, + 0x25, 0x8c, 0xa5, 0xca, 0x3f, 0xdd, 0x7a, 0x4d, 0xa3, 0x75, 0xa9, 0x85, + 0xe4, 0x75, 0xe3, 0x42 +}; +static const uint8_t nist_186_2_ecdsa_testvector_129_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x5d, 0x00, 0x7b, 0x8f, 0xb5, 0x2d, 0x28, 0x26, 0xd0, 0x0d, 0xa4, + 0x7e, 0x72, 0xd5, 0xa9, 0xaf, 0xc3, 0x69, 0xed, 0x7e, 0x30, 0x88, 0x5f, + 0x65, 0xa0, 0x80, 0x87, 0xcf, 0x3c, 0x70, 0x57, 0xac, 0xed, 0xa4, 0x87, + 0x00, 0x38, 0x34, 0x43, 0x5b, 0xbd, 0xc9, 0xcb, 0xd1, 0xe1, 0x41, 0x82, + 0x13, 0x05, 0x01, 0xc8 +}; +/* k = 000478825379adb579470f028566011597ea6d63429a9d13e019b628e83c5b11732f2c9a430f7e8892566868e12a058ad1ce2ec */ +static const uint8_t nist_186_2_ecdsa_testvector_129_out[] = { +/* R - byte alignment */ + 0x00, 0x18, 0x35, 0x4d, 0xaf, 0xae, 0x65, 0xb5, 0xed, 0x8a, 0xdb, 0xc1, + 0x2b, 0x90, 0xa0, 0x96, 0xd5, 0x0d, 0x94, 0xf0, 0x39, 0xba, 0xd9, 0x56, + 0x46, 0xd7, 0x7c, 0xed, 0x3c, 0x5b, 0x62, 0x06, 0xa9, 0x7b, 0x2f, 0x6b, + 0x0a, 0x65, 0xa7, 0x98, 0xab, 0x14, 0x85, 0x92, 0xd0, 0x23, 0x5d, 0x79, + 0xe7, 0xe5, 0xc0, 0x2d, +/* S - byte alignment */ + 0x00, 0x2c, 0x8b, 0xaf, 0x9f, 0xd4, 0x7b, 0x26, 0xb4, 0x4c, 0x7c, 0xcb, + 0x96, 0x7c, 0x36, 0xa5, 0xbd, 0xc5, 0x49, 0x21, 0x5e, 0x72, 0x90, 0x5f, + 0x3a, 0x77, 0xb9, 0xd5, 0x70, 0x05, 0x83, 0x2a, 0xcc, 0x65, 0xe5, 0x4b, + 0x7e, 0x1d, 0x22, 0x84, 0x83, 0x8c, 0xf4, 0x1f, 0x7f, 0x78, 0x8f, 0x87, + 0x8d, 0x85, 0xc2, 0xf9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_130_ptx[] = { +/* Msg */ + 0x79, 0x63, 0x32, 0x4b, 0xdf, 0x37, 0xe2, 0xfb, 0xd0, 0xa1, 0x31, 0xad, + 0x26, 0xa0, 0x70, 0x79, 0x63, 0x3e, 0xd2, 0xd8, 0xf5, 0xc4, 0xd2, 0x6e, + 0xb9, 0x2a, 0xcf, 0x26, 0xbd, 0xd1, 0xf9, 0x84, 0x4a, 0x75, 0x71, 0x37, + 0x22, 0x5d, 0xac, 0xee, 0x06, 0xd4, 0x19, 0x6d, 0x7b, 0xdd, 0x03, 0xe0, + 0xce, 0x23, 0xb8, 0x6f, 0x56, 0x2f, 0xeb, 0x12, 0xf9, 0xdd, 0x57, 0xa7, + 0xf1, 0x11, 0xa5, 0x42, 0xd0, 0xa6, 0x90, 0xc4, 0xc2, 0xa7, 0x47, 0xaf, + 0x13, 0xc2, 0x12, 0x38, 0xf1, 0xf9, 0x39, 0x9e, 0x72, 0x9b, 0x22, 0xbb, + 0xd9, 0x73, 0xb9, 0xd9, 0x15, 0x3f, 0x14, 0xc6, 0x8a, 0x64, 0x58, 0x2b, + 0x14, 0xdf, 0xd6, 0x19, 0x49, 0x7f, 0x7a, 0xe5, 0xff, 0x51, 0x66, 0x36, + 0x0f, 0x5c, 0xda, 0x5c, 0x58, 0x8f, 0x57, 0xe3, 0x06, 0xf8, 0x04, 0x68, + 0x14, 0x37, 0x50, 0xac, 0x0f, 0x31, 0xd9, 0xe7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_130_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x66, 0x9a, 0x1d, 0xa4, 0xa2, 0x16, 0x9b, 0x6d, 0xdd, 0x27, + 0xb0, 0x98, 0x97, 0x38, 0x7b, 0x4c, 0x64, 0x24, 0xfc, 0x4a, 0x4b, 0xab, + 0x74, 0xbc, 0xf7, 0x68, 0x97, 0xe7, 0x75, 0xc0, 0x11, 0x03, 0xf6, 0x27, + 0xe3, 0x57, 0x8f, 0x5d, 0xd6, 0x14, 0xf8, 0x8b, 0x80, 0x94, 0xcb, 0x47, + 0x5e, 0x17, 0xf1, 0x0c +}; +static const uint8_t nist_186_2_ecdsa_testvector_130_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x13, 0xc1, 0x7a, 0xa3, 0xbf, 0x85, 0x86, 0x59, 0x2c, 0xed, 0x7e, + 0x80, 0x2b, 0xa8, 0x71, 0x08, 0x8f, 0xfd, 0xd1, 0x7c, 0xa1, 0xe3, 0xc1, + 0x28, 0xac, 0x11, 0x83, 0x83, 0x16, 0x66, 0x6f, 0x4f, 0x06, 0xd4, 0x64, + 0x67, 0x76, 0x39, 0xc8, 0xc8, 0x08, 0xf6, 0x2d, 0xbd, 0xcf, 0x07, 0xdd, + 0x4f, 0xa1, 0x24, 0xf0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_130_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x9b, 0x86, 0x7e, 0x2e, 0x29, 0x60, 0x8a, 0xad, 0x63, 0x5b, 0xb2, + 0x57, 0xb2, 0xa2, 0x4f, 0x71, 0x39, 0x5c, 0x8e, 0x6a, 0x22, 0xbb, 0xef, + 0x60, 0x8a, 0xf9, 0x38, 0x19, 0x75, 0x44, 0x99, 0xf9, 0x1d, 0xe4, 0xc3, + 0x37, 0xed, 0x21, 0xed, 0x81, 0xd1, 0x65, 0xe9, 0xcf, 0xa9, 0x71, 0x57, + 0xa3, 0xa0, 0xc8, 0xde +}; +/* k = 000033608dd88995c994f72266cfff53c4901a04560f9c5b33f9478ed32461ea3a28d67634a8fbaf497d315e1a2b178300fde2e */ +static const uint8_t nist_186_2_ecdsa_testvector_130_out[] = { +/* R - byte alignment */ + 0x00, 0x72, 0xea, 0xaf, 0xde, 0xfd, 0x9a, 0xfd, 0x85, 0x76, 0xf0, 0xda, + 0x99, 0x93, 0x3a, 0x9c, 0xf4, 0x51, 0x36, 0xb7, 0x3c, 0xb7, 0xd7, 0xa1, + 0x15, 0xa5, 0x83, 0xd3, 0x7e, 0xe6, 0x44, 0x20, 0xeb, 0x4d, 0x51, 0x92, + 0xb4, 0x33, 0x2a, 0x84, 0x6f, 0xa1, 0xc3, 0x81, 0xaa, 0x37, 0xec, 0xda, + 0x89, 0x66, 0x20, 0xfc, +/* S - byte alignment */ + 0x00, 0x34, 0x96, 0x3b, 0x47, 0xf5, 0x28, 0x9b, 0xd9, 0x81, 0xe2, 0x3b, + 0xff, 0x06, 0xa2, 0x15, 0xa7, 0xfe, 0x97, 0x55, 0xa1, 0xf8, 0xcf, 0xa7, + 0xb2, 0x90, 0x2b, 0xb8, 0x30, 0xa0, 0xb1, 0x0e, 0xa1, 0x51, 0xa0, 0x0a, + 0x6e, 0x98, 0x4b, 0xcb, 0xef, 0x13, 0x7d, 0x06, 0xdf, 0xf0, 0x11, 0xd4, + 0xfd, 0xd8, 0x72, 0x3d +}; +static const uint8_t nist_186_2_ecdsa_testvector_131_ptx[] = { +/* Msg */ + 0x59, 0xa4, 0x50, 0xd6, 0x16, 0x92, 0x56, 0x92, 0xb8, 0x66, 0xec, 0xdb, + 0xfd, 0x74, 0x63, 0xcc, 0x64, 0xd4, 0xc7, 0x54, 0xed, 0x13, 0xc0, 0x8c, + 0x20, 0x28, 0xb6, 0x48, 0x50, 0xaa, 0x38, 0xed, 0x21, 0x40, 0x9f, 0x82, + 0x48, 0x58, 0xee, 0x09, 0x92, 0x1c, 0xfd, 0x0f, 0x28, 0xa1, 0xd7, 0x82, + 0x11, 0x62, 0x60, 0xc3, 0xf8, 0xee, 0x3b, 0xfc, 0x30, 0xdd, 0xea, 0xb4, + 0xf5, 0x08, 0x37, 0xa0, 0xf5, 0xfa, 0xd3, 0xbc, 0x0f, 0xa1, 0x3e, 0x9b, + 0x5a, 0x49, 0xe6, 0xfb, 0x69, 0xcc, 0x93, 0x9d, 0xcd, 0x02, 0x02, 0x54, + 0xdc, 0x7f, 0xd0, 0x5b, 0xb1, 0x7e, 0x9b, 0xeb, 0x74, 0x18, 0x63, 0x0d, + 0xdc, 0xba, 0x36, 0xae, 0xf1, 0xd5, 0x0c, 0xf1, 0x17, 0xd7, 0xf0, 0xc9, + 0x48, 0x5b, 0x60, 0xc6, 0xa1, 0x9c, 0xf7, 0x2f, 0x20, 0x30, 0x49, 0x52, + 0xac, 0xf3, 0x0f, 0x18, 0x55, 0x41, 0x84, 0xdc +}; +static const uint8_t nist_186_2_ecdsa_testvector_131_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x11, 0x82, 0x52, 0x18, 0x93, 0xfe, 0x9b, 0xbd, 0xab, 0x3d, + 0x51, 0x7b, 0x99, 0x2c, 0xe4, 0xc8, 0xb5, 0xb9, 0x13, 0x44, 0x9a, 0x1e, + 0x8a, 0x64, 0x6d, 0x46, 0x82, 0x6e, 0x3d, 0x39, 0x2c, 0x9e, 0xd8, 0x37, + 0x9f, 0x1f, 0xab, 0x71, 0x24, 0x31, 0x27, 0xf0, 0xf3, 0x7f, 0x9b, 0xcc, + 0xdc, 0x48, 0xb3, 0xab +}; +static const uint8_t nist_186_2_ecdsa_testvector_131_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x22, 0xda, 0x40, 0x19, 0x4e, 0x34, 0xf7, 0xa1, 0xe5, 0x15, 0xaf, + 0x92, 0x19, 0x73, 0xe3, 0x36, 0x60, 0xb2, 0xcf, 0x4f, 0xc1, 0xbc, 0xee, + 0xbf, 0x3f, 0xf9, 0x42, 0x4c, 0xf7, 0x52, 0x84, 0x63, 0x75, 0x7f, 0xcd, + 0x25, 0x8e, 0xd2, 0x58, 0x42, 0xa1, 0xdf, 0xc3, 0x96, 0x2d, 0xd3, 0xcc, + 0x7b, 0x09, 0x86, 0xee +}; +static const uint8_t nist_186_2_ecdsa_testvector_131_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x99, 0x30, 0x3a, 0x1c, 0x50, 0x7e, 0x07, 0x97, 0xd5, 0xac, 0x19, + 0xd2, 0xb6, 0xfc, 0x42, 0xec, 0xfd, 0xed, 0x12, 0x70, 0xa1, 0x63, 0xa9, + 0x5e, 0x51, 0x53, 0xe8, 0xbd, 0xa4, 0x84, 0xc3, 0x26, 0x30, 0x03, 0xcd, + 0xcb, 0x4b, 0x4c, 0xeb, 0xfb, 0xca, 0x2d, 0x0b, 0x4b, 0x07, 0x66, 0x45, + 0x16, 0xd9, 0x19, 0x43 +}; +/* k = 000591d2484fd67a396b07bdd351d61b66eb791e22991530de6fce16be730a95af789789bf86dcffe8d3e49af64fcd7aa026d0e */ +static const uint8_t nist_186_2_ecdsa_testvector_131_out[] = { +/* R - byte alignment */ + 0x00, 0x6c, 0x33, 0x31, 0xc5, 0x87, 0x19, 0x7e, 0x5d, 0x4b, 0x74, 0x02, + 0x99, 0x39, 0xd9, 0xc0, 0x8b, 0xd0, 0x65, 0xed, 0x5b, 0x03, 0x16, 0x1e, + 0xfa, 0xc2, 0x49, 0x5d, 0x2e, 0x86, 0x41, 0x55, 0xf2, 0x02, 0x0c, 0x52, + 0xb1, 0xbf, 0xdf, 0xa1, 0x13, 0x20, 0x74, 0x86, 0x4b, 0x29, 0x5f, 0xe4, + 0x5b, 0xe3, 0x07, 0x07, +/* S - byte alignment */ + 0x00, 0x38, 0x08, 0x1e, 0x2c, 0x12, 0x60, 0x31, 0x1d, 0xd1, 0xb7, 0x53, + 0x3d, 0xf3, 0x14, 0x55, 0xe0, 0xf9, 0x7f, 0x98, 0x89, 0x22, 0x5e, 0x73, + 0x6c, 0x81, 0xd7, 0x61, 0xb9, 0x74, 0xdd, 0x6c, 0xd0, 0x62, 0xd9, 0x58, + 0x6c, 0x6c, 0x4f, 0x93, 0xf9, 0x0b, 0x15, 0xfb, 0xa9, 0xb8, 0x86, 0x42, + 0x89, 0x32, 0x70, 0xac +}; +static const uint8_t nist_186_2_ecdsa_testvector_132_ptx[] = { +/* Msg */ + 0x31, 0x04, 0x25, 0x69, 0x53, 0x62, 0x01, 0x2e, 0x38, 0x55, 0x7b, 0x02, + 0x37, 0x2e, 0xb4, 0x54, 0x8f, 0x7c, 0x06, 0xe0, 0x9d, 0x78, 0xe0, 0x31, + 0x53, 0xa0, 0xd1, 0x64, 0xe5, 0xa1, 0xe2, 0x30, 0xc5, 0x7a, 0x29, 0x23, + 0xd2, 0xdf, 0x9b, 0x2e, 0xcd, 0xdb, 0x22, 0x64, 0x0c, 0xba, 0xf0, 0xff, + 0x72, 0x26, 0x12, 0xa4, 0x9e, 0x90, 0x48, 0xe8, 0x63, 0xd2, 0x14, 0x12, + 0x78, 0x12, 0x11, 0x22, 0x71, 0xe9, 0x86, 0x13, 0xee, 0xc4, 0x3b, 0x5e, + 0x13, 0x8b, 0x8b, 0xbf, 0x38, 0x81, 0xbb, 0x3b, 0xe1, 0x6c, 0x8a, 0x62, + 0xf0, 0xf5, 0x09, 0xd2, 0x19, 0x51, 0xad, 0xfc, 0x97, 0x21, 0xa3, 0x2b, + 0x1d, 0x97, 0x63, 0xc2, 0x10, 0xdb, 0x88, 0xc4, 0xf3, 0xad, 0xdf, 0x9a, + 0x23, 0x4b, 0xbe, 0x11, 0xc4, 0x95, 0x97, 0xa3, 0xfb, 0x6f, 0xcc, 0xf7, + 0x5d, 0x67, 0xc5, 0xab, 0xa8, 0x98, 0x41, 0x50 +}; +static const uint8_t nist_186_2_ecdsa_testvector_132_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x39, 0xe1, 0x29, 0x56, 0xad, 0xcc, 0x35, 0x0f, 0xea, 0x48, + 0x18, 0xe4, 0x65, 0xef, 0xde, 0x85, 0x1d, 0xfa, 0x14, 0x0d, 0xa9, 0x82, + 0x2f, 0xde, 0x7a, 0x26, 0xe2, 0xd7, 0xf7, 0x4d, 0x65, 0x1e, 0x59, 0x77, + 0x1e, 0x3f, 0xa0, 0x89, 0xb7, 0x6c, 0xaf, 0x73, 0x22, 0x38, 0xd5, 0xc9, + 0x82, 0x6d, 0xbe, 0x66 +}; +static const uint8_t nist_186_2_ecdsa_testvector_132_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xb2, 0x5d, 0x8a, 0xf0, 0x8e, 0x3e, 0x91, 0xac, 0x51, 0x98, 0x5a, + 0x2b, 0x0f, 0xd4, 0x37, 0xbf, 0x32, 0xf9, 0x1b, 0x2c, 0x87, 0x6f, 0x68, + 0xbd, 0x7a, 0x19, 0x94, 0x17, 0xeb, 0xc0, 0x75, 0x59, 0x3f, 0x09, 0xba, + 0x5c, 0xcf, 0x90, 0xf1, 0x41, 0x26, 0x60, 0x34, 0x75, 0x5a, 0x03, 0x2b, + 0xeb, 0x78, 0x4c, 0x28 +}; +static const uint8_t nist_186_2_ecdsa_testvector_132_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xe2, 0x2e, 0x1d, 0xc5, 0xe4, 0xfb, 0x11, 0x19, 0xc3, 0x30, 0x3e, + 0x6f, 0x33, 0x77, 0xc2, 0x26, 0x10, 0x01, 0xcd, 0xbb, 0xa9, 0x5f, 0xd4, + 0xa4, 0x96, 0x90, 0xb6, 0x26, 0xaf, 0x4a, 0xdb, 0x0f, 0x92, 0xd5, 0xb3, + 0x71, 0x82, 0x1d, 0x9b, 0xfe, 0x6d, 0xcd, 0xcf, 0x83, 0xff, 0x89, 0x40, + 0x27, 0xaf, 0xbc, 0x19 +}; +/* k = 000572dba48019e2779fadeae40f8efcc690aa39811814f5218781382e2e4460da443d2a81eff5d0aabbb37693408e0a45e1964 */ +static const uint8_t nist_186_2_ecdsa_testvector_132_out[] = { +/* R - byte alignment */ + 0x00, 0x04, 0xac, 0x35, 0x7f, 0xe0, 0x9a, 0x9c, 0x05, 0x36, 0x23, 0x52, + 0xd0, 0xa8, 0xe7, 0xde, 0xfd, 0xf2, 0x03, 0x4e, 0x98, 0x09, 0x07, 0x3a, + 0x24, 0x87, 0x10, 0x8e, 0x66, 0x64, 0x0a, 0x7b, 0x97, 0x23, 0x80, 0x53, + 0x59, 0x63, 0x64, 0x3d, 0x5e, 0xfb, 0xa4, 0xe8, 0x27, 0x1c, 0x74, 0xd7, + 0xaf, 0x18, 0x01, 0xbd, +/* S - byte alignment */ + 0x00, 0x22, 0x14, 0x1c, 0x29, 0x0b, 0xcb, 0xab, 0x70, 0x9b, 0xaa, 0xb7, + 0x0c, 0xa5, 0x86, 0xda, 0x85, 0x05, 0x2c, 0x1e, 0x0d, 0x94, 0xe9, 0xf6, + 0xf8, 0x4e, 0x8f, 0x55, 0x15, 0x51, 0x81, 0xff, 0x7f, 0xf9, 0x9c, 0x25, + 0x26, 0x6f, 0x6a, 0x35, 0xf2, 0xa7, 0x98, 0xe2, 0x72, 0xe6, 0xf5, 0x5b, + 0x05, 0x5e, 0x17, 0xf1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_133_ptx[] = { +/* Msg */ + 0x74, 0xb1, 0xfb, 0x86, 0x5f, 0x5d, 0xf6, 0xe1, 0xac, 0x90, 0x45, 0x78, + 0x9f, 0xd7, 0x56, 0xcf, 0x35, 0x82, 0x4a, 0x5a, 0xa3, 0x4b, 0x01, 0x43, + 0xfe, 0x38, 0x77, 0x67, 0x3c, 0xc2, 0x54, 0xa2, 0x5b, 0x36, 0xbe, 0x4c, + 0xe0, 0x5c, 0x72, 0x03, 0x83, 0x57, 0x13, 0xab, 0x29, 0xcc, 0xc1, 0xb4, + 0x12, 0x46, 0xee, 0x9b, 0x54, 0xd9, 0x6d, 0xb4, 0x88, 0x06, 0xcc, 0x26, + 0xc3, 0xdf, 0xe4, 0x37, 0xc8, 0x6b, 0xae, 0xca, 0x7b, 0x4c, 0x59, 0x25, + 0x99, 0x9f, 0x99, 0xf8, 0xa7, 0x24, 0x41, 0x9b, 0x28, 0x9f, 0x14, 0x98, + 0x13, 0x7e, 0xd8, 0x69, 0x84, 0xbb, 0xad, 0x83, 0xb2, 0x04, 0x9d, 0x93, + 0x21, 0x1a, 0x74, 0x07, 0x19, 0x77, 0xd2, 0xd0, 0x56, 0x33, 0x7e, 0x66, + 0x01, 0x28, 0xfd, 0x0d, 0xdf, 0x55, 0x64, 0x58, 0xc9, 0x80, 0x6a, 0xeb, + 0x5c, 0x1f, 0xc1, 0x84, 0xf1, 0x79, 0xa7, 0x3d +}; +static const uint8_t nist_186_2_ecdsa_testvector_133_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x1e, 0x24, 0xd2, 0xd3, 0x63, 0x56, 0xa6, 0x4c, 0x9f, 0xe3, + 0xb1, 0xb9, 0x55, 0xe9, 0x9c, 0x30, 0xf6, 0xa2, 0x23, 0xc3, 0x0b, 0xcf, + 0x33, 0xf3, 0x6e, 0xeb, 0x4a, 0xa8, 0x46, 0x63, 0xf4, 0x36, 0xac, 0x02, + 0x48, 0x9b, 0xe1, 0x9c, 0xe3, 0x91, 0x3c, 0xcf, 0x19, 0xca, 0xe0, 0xc6, + 0xee, 0x45, 0xe6, 0x57 +}; +static const uint8_t nist_186_2_ecdsa_testvector_133_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xe4, 0x00, 0x75, 0xcc, 0x1a, 0x8d, 0xb1, 0xdc, 0x3a, 0xe8, 0x4f, + 0xb1, 0x1d, 0xf4, 0x9f, 0x0e, 0xb6, 0x4c, 0x57, 0xea, 0xcf, 0x77, 0x65, + 0x5c, 0x6d, 0x4c, 0x88, 0x1d, 0x52, 0x84, 0x12, 0x7f, 0x68, 0xf9, 0x91, + 0x5c, 0xbd, 0x84, 0x79, 0x7d, 0x59, 0x95, 0x93, 0x2c, 0x40, 0x3b, 0x99, + 0x69, 0xe3, 0x0e, 0xaa +}; +static const uint8_t nist_186_2_ecdsa_testvector_133_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x71, 0x77, 0x1c, 0x3e, 0xc1, 0x82, 0x76, 0x0c, 0x14, 0xc1, 0x10, + 0xb2, 0x22, 0x4e, 0xe0, 0x29, 0x1c, 0xc2, 0x51, 0x8f, 0xa1, 0xfd, 0xcd, + 0x43, 0x1e, 0x41, 0x66, 0x66, 0xe8, 0x5d, 0xac, 0x29, 0x92, 0x70, 0xe1, + 0x0d, 0xe2, 0xd2, 0x02, 0x6a, 0x4f, 0xa7, 0x27, 0xa2, 0x4a, 0x3d, 0x61, + 0x47, 0x5e, 0x64, 0x8c +}; +/* k = 0000b9ce98a3e275f6b96ebeb01e29766e32057d51ff5ed2b76f0465d63988e557fde97ed3bd79ec76bf1d3f4bc466696228b99 */ +static const uint8_t nist_186_2_ecdsa_testvector_133_out[] = { +/* R - byte alignment */ + 0x00, 0x41, 0x47, 0x63, 0x15, 0x8b, 0xf4, 0xa2, 0x43, 0x07, 0xe0, 0x54, + 0x92, 0x9d, 0x63, 0x74, 0xa0, 0x4c, 0x9a, 0x35, 0x0d, 0x54, 0x45, 0xd1, + 0x20, 0xbc, 0xca, 0x19, 0xa8, 0x23, 0x04, 0x67, 0x87, 0x0f, 0xe6, 0xc7, + 0xce, 0xc6, 0x9d, 0x3d, 0xeb, 0xc1, 0x5d, 0xe8, 0xb8, 0x1d, 0xd3, 0x13, + 0x3b, 0xaf, 0xde, 0xbc, +/* S - byte alignment */ + 0x00, 0x22, 0xc4, 0xc3, 0xd8, 0xa4, 0x59, 0x33, 0xce, 0x59, 0xb7, 0x80, + 0x2a, 0x35, 0xc6, 0xd2, 0xc7, 0x16, 0x01, 0x6a, 0x74, 0x66, 0x08, 0xe0, + 0x23, 0x24, 0x4e, 0x42, 0xeb, 0x34, 0xde, 0x87, 0x68, 0xe9, 0xbe, 0x16, + 0xeb, 0xc4, 0xe5, 0x6f, 0x9a, 0x50, 0xc1, 0xa6, 0x6a, 0x5e, 0x32, 0xd9, + 0x0d, 0x4b, 0x66, 0x95 +}; +static const uint8_t nist_186_2_ecdsa_testvector_134_ptx[] = { +/* Msg */ + 0xbd, 0xda, 0xd3, 0xed, 0xbf, 0x5a, 0x09, 0x67, 0x37, 0x7e, 0x38, 0x49, + 0x84, 0xfb, 0xd2, 0x8d, 0xca, 0x38, 0x2e, 0x79, 0x42, 0x56, 0x7f, 0xc7, + 0xd5, 0x6e, 0x07, 0x02, 0xea, 0x19, 0x88, 0x33, 0x7c, 0x36, 0xfc, 0xbd, + 0x6f, 0xe7, 0x85, 0x86, 0x24, 0xdd, 0xa7, 0x57, 0x4b, 0xd6, 0xb5, 0x86, + 0xf8, 0x63, 0x89, 0xd2, 0xf9, 0xef, 0x78, 0x8e, 0x68, 0xfd, 0x86, 0x02, + 0x7c, 0xb1, 0xd5, 0x0e, 0xa4, 0x92, 0x64, 0x10, 0xd7, 0x8e, 0xf6, 0x08, + 0x25, 0x3f, 0x4f, 0xfa, 0x93, 0x6c, 0xa6, 0x94, 0x25, 0xd3, 0x58, 0x11, + 0x3c, 0x25, 0xda, 0x5d, 0x22, 0x53, 0xf1, 0x7a, 0xe4, 0x08, 0x25, 0x22, + 0x60, 0x76, 0x73, 0xae, 0x9e, 0x56, 0x42, 0x36, 0x64, 0x2a, 0x98, 0xfa, + 0x04, 0xc6, 0x8e, 0x00, 0x79, 0x0e, 0x01, 0xff, 0xb2, 0x01, 0x8b, 0x7c, + 0x2e, 0xf7, 0xb1, 0x33, 0xc9, 0x26, 0x5e, 0xb8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_134_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x74, 0x29, 0xb9, 0xed, 0x32, 0x37, 0x19, 0x5e, 0x77, 0x45, + 0x66, 0xb7, 0xb6, 0xe3, 0xbb, 0x51, 0xdf, 0xcc, 0xe9, 0x5f, 0xbd, 0x2d, + 0x6f, 0x67, 0x74, 0xa3, 0xcd, 0xc2, 0x55, 0x86, 0xae, 0x0a, 0xae, 0x09, + 0xbd, 0x7e, 0xf7, 0x32, 0xc9, 0x69, 0x16, 0x15, 0xa0, 0xb3, 0x11, 0x86, + 0x31, 0x33, 0xfd, 0xaf +}; +static const uint8_t nist_186_2_ecdsa_testvector_134_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x67, 0xdc, 0xe3, 0x69, 0x17, 0x67, 0xdc, 0x30, 0xc2, 0xaf, 0x5c, + 0x39, 0x6b, 0x9d, 0xc0, 0xc8, 0x40, 0x91, 0x41, 0xc5, 0x79, 0x3c, 0xea, + 0x87, 0xab, 0x8c, 0x18, 0xfd, 0xc6, 0x43, 0xf3, 0x7f, 0xac, 0x2a, 0x8c, + 0xc2, 0x11, 0xe8, 0x2f, 0x9e, 0x11, 0x4d, 0x0b, 0x05, 0xce, 0xd8, 0x27, + 0x25, 0x09, 0xf1, 0xe4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_134_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xda, 0x55, 0xee, 0xc9, 0x01, 0xca, 0x02, 0xad, 0x05, 0xa5, 0x59, + 0x46, 0x53, 0xa3, 0x51, 0x1d, 0x7d, 0x45, 0xa5, 0x77, 0xb7, 0xf4, 0x9e, + 0x3d, 0x53, 0x70, 0x41, 0xe7, 0x96, 0xed, 0xe1, 0xb0, 0x13, 0xd0, 0xeb, + 0x9e, 0x5f, 0xd2, 0x49, 0x28, 0x0d, 0x59, 0xdd, 0xac, 0x85, 0xe8, 0xa0, + 0xf1, 0xf7, 0x08, 0xb0 +}; +/* k = 0005c0c854e66eb2df3381f4de0f8b05e187735b4e2b329ff96dd0710edfc950eaaeb09b8b7242da5a1639300a981f6cb5e62ec */ +static const uint8_t nist_186_2_ecdsa_testvector_134_out[] = { +/* R - byte alignment */ + 0x00, 0x0e, 0xbe, 0x27, 0x77, 0xcc, 0x4d, 0x7b, 0x02, 0x6a, 0xd5, 0x6d, + 0x2d, 0xc0, 0x89, 0xb5, 0xd6, 0xf7, 0xb2, 0x29, 0xa2, 0xf4, 0x4f, 0x8b, + 0xb5, 0x36, 0xa3, 0x21, 0x92, 0x02, 0xf8, 0xef, 0x9c, 0xe8, 0x00, 0x04, + 0x06, 0xe0, 0x32, 0x86, 0x2b, 0x1c, 0xc5, 0x68, 0x5c, 0x5d, 0xf8, 0x6e, + 0xba, 0x97, 0xd2, 0x30, +/* S - byte alignment */ + 0x00, 0x58, 0xdd, 0x30, 0x1a, 0xc3, 0x66, 0xc2, 0x44, 0xd0, 0x5c, 0x06, + 0x49, 0x18, 0x09, 0x53, 0x29, 0x00, 0x2a, 0x18, 0xa0, 0x82, 0x51, 0xf1, + 0xbd, 0x04, 0x9a, 0x2c, 0x42, 0x21, 0xd7, 0xbe, 0xe7, 0x5e, 0x26, 0x66, + 0x92, 0x37, 0xf8, 0x53, 0xd1, 0xdc, 0xab, 0x6d, 0x1d, 0x5c, 0x59, 0x7b, + 0x23, 0x71, 0x2d, 0xc0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_135_ptx[] = { +/* Msg */ + 0x81, 0x73, 0xcc, 0x65, 0x1e, 0x14, 0xc1, 0x3d, 0xae, 0x61, 0x23, 0x7e, + 0xfa, 0x8f, 0xa3, 0x22, 0xe7, 0x81, 0xe8, 0x42, 0xf7, 0x3c, 0x33, 0x2c, + 0x12, 0x9b, 0x43, 0xb7, 0x87, 0x43, 0x76, 0xd3, 0x4e, 0xda, 0x32, 0x64, + 0x90, 0x74, 0x83, 0x51, 0x68, 0x4e, 0x05, 0xd7, 0xec, 0xbf, 0x05, 0x24, + 0x67, 0x6b, 0xe3, 0x21, 0xe9, 0xba, 0xba, 0x8f, 0x02, 0x89, 0x43, 0x55, + 0xca, 0x1f, 0xf7, 0x18, 0x24, 0x62, 0x74, 0x0d, 0x44, 0x4a, 0x22, 0x0b, + 0x6f, 0x97, 0x16, 0xe5, 0x02, 0xbf, 0x37, 0xf6, 0xb6, 0x2b, 0x9f, 0xfd, + 0x22, 0xa2, 0x44, 0x2c, 0x82, 0x06, 0xd7, 0x7b, 0xb6, 0x3e, 0xec, 0x42, + 0x8e, 0x73, 0x5c, 0x07, 0x44, 0x7f, 0xe7, 0x94, 0x4a, 0xa2, 0x1e, 0x4d, + 0x46, 0x77, 0x81, 0xc1, 0x5c, 0x27, 0xe4, 0x7f, 0xab, 0xdd, 0x17, 0x2b, + 0x1a, 0x7a, 0xc5, 0xd1, 0x54, 0x89, 0x9d, 0x78 +}; +static const uint8_t nist_186_2_ecdsa_testvector_135_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x2e, 0x1a, 0x6f, 0x65, 0x8a, 0x05, 0x8b, 0x79, 0xa8, 0xc0, + 0x62, 0x8a, 0x93, 0xab, 0x3b, 0x35, 0xb6, 0x04, 0xce, 0xa4, 0xa9, 0x5b, + 0x89, 0xe2, 0x3e, 0xf5, 0xa8, 0xf8, 0xd5, 0x7c, 0x1b, 0xda, 0xe7, 0x3f, + 0x76, 0x60, 0x72, 0xca, 0x53, 0x16, 0xd0, 0x96, 0x70, 0x41, 0x7f, 0xae, + 0x85, 0x46, 0xa5, 0x24 +}; +static const uint8_t nist_186_2_ecdsa_testvector_135_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x75, 0x7b, 0xa5, 0x97, 0x3d, 0xf2, 0x80, 0x09, 0x27, 0xf7, 0x3f, + 0xa4, 0x13, 0x25, 0x47, 0xe6, 0x98, 0x99, 0xb7, 0xc3, 0xf7, 0x0b, 0x82, + 0xf6, 0xe7, 0x23, 0x01, 0x6a, 0xf3, 0xa2, 0x26, 0xa5, 0x26, 0xc6, 0xc1, + 0x15, 0x39, 0x5e, 0x67, 0x1a, 0x59, 0x8a, 0x1b, 0xc2, 0x31, 0x78, 0x00, + 0x28, 0x81, 0xb6, 0xaa +}; +static const uint8_t nist_186_2_ecdsa_testvector_135_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x81, 0x25, 0xaf, 0x3b, 0x70, 0x2c, 0x4a, 0x2c, 0x36, 0xeb, 0x95, + 0x5c, 0x70, 0x36, 0x04, 0x29, 0xdc, 0x0b, 0xd0, 0x82, 0xc4, 0x09, 0x7c, + 0x56, 0xe1, 0xae, 0x13, 0xd8, 0x3c, 0xeb, 0x53, 0xe0, 0x08, 0x03, 0xda, + 0x18, 0x60, 0xea, 0xac, 0xd8, 0x57, 0x6c, 0x09, 0x2a, 0xcb, 0x91, 0x47, + 0xb5, 0xc0, 0x4f, 0xe5 +}; +/* k = 0007b7c4449d744e373a38aab13ff033d14ab96dd2e56ed9a650e4e03f9a29f1ad5f788c754f3e5e90662e6277f7548051ff84e */ +static const uint8_t nist_186_2_ecdsa_testvector_135_out[] = { +/* R - byte alignment */ + 0x00, 0x75, 0x00, 0x24, 0x69, 0x8e, 0xfa, 0xc4, 0xe1, 0xce, 0x6b, 0x6b, + 0xc3, 0x00, 0x4e, 0x4b, 0x73, 0xf8, 0x7b, 0x7e, 0x5e, 0x22, 0x6a, 0x0e, + 0x8a, 0x10, 0x02, 0xba, 0x23, 0x09, 0xa4, 0xca, 0xca, 0xb0, 0x54, 0x58, + 0xdc, 0xf2, 0x40, 0x7c, 0x30, 0xff, 0x34, 0xe5, 0xf8, 0x8f, 0xbc, 0xd7, + 0xd5, 0xfa, 0xfa, 0x1b, +/* S - byte alignment */ + 0x00, 0x28, 0xae, 0xb1, 0xc4, 0x04, 0xa5, 0xc2, 0x9b, 0x3c, 0x4a, 0xa5, + 0x61, 0x56, 0xab, 0x8f, 0x92, 0x0a, 0xfe, 0x25, 0xfe, 0xd6, 0x69, 0x68, + 0x5d, 0xdb, 0xbc, 0x2c, 0xfc, 0x69, 0xab, 0x62, 0x5d, 0xd5, 0xed, 0xf2, + 0x63, 0xab, 0xe5, 0x2b, 0x75, 0xad, 0x2c, 0x8a, 0x3d, 0x3e, 0x1d, 0xe3, + 0xf0, 0x4f, 0xe3, 0xee +}; +/* [K-571] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_136_ptx[] = { +/* Msg */ + 0xc8, 0xca, 0x3f, 0xa3, 0xa0, 0xe0, 0x69, 0x22, 0x6c, 0xdd, 0x8f, 0x9a, + 0x87, 0x43, 0x7c, 0xb9, 0xb6, 0x51, 0xc1, 0xde, 0xae, 0x79, 0x57, 0x2a, + 0xd6, 0x14, 0x87, 0xda, 0x4f, 0x55, 0x07, 0xd4, 0x32, 0x7b, 0x66, 0x7f, + 0x18, 0x4b, 0xa9, 0xd8, 0xe0, 0xbe, 0x37, 0xc3, 0xac, 0xf7, 0xf2, 0x9e, + 0x2d, 0x77, 0xa7, 0x1c, 0x21, 0x94, 0xa8, 0x51, 0x19, 0x27, 0xb7, 0x09, + 0x80, 0x86, 0x26, 0x5e, 0xd9, 0xb2, 0x3d, 0x8a, 0x48, 0xd1, 0xdc, 0xf9, + 0x54, 0xde, 0x61, 0xa3, 0xeb, 0x9f, 0xcc, 0x98, 0xa6, 0xd7, 0x22, 0xdc, + 0x4f, 0xbe, 0x0f, 0x76, 0xa1, 0xae, 0xce, 0xc4, 0x4e, 0x1f, 0x4e, 0x11, + 0x47, 0xd5, 0x8d, 0x69, 0x37, 0x58, 0x48, 0xac, 0x50, 0xa5, 0xd7, 0xe2, + 0x4b, 0x23, 0x53, 0xce, 0xaa, 0xd8, 0xf9, 0xc6, 0x41, 0xdd, 0xd3, 0xc2, + 0xf4, 0x0f, 0x95, 0xb2, 0xc2, 0x08, 0xc5, 0x15 +}; +static const uint8_t nist_186_2_ecdsa_testvector_136_private[] = { +/* d - byte alignment */ + 0x01, 0xa6, 0xfc, 0xa9, 0xb7, 0x19, 0x13, 0xac, 0xe1, 0x5d, 0xe7, 0x92, + 0xbe, 0x91, 0x29, 0xdd, 0x4a, 0x25, 0xdb, 0x43, 0xfb, 0xf2, 0xee, 0x5f, + 0x01, 0x97, 0xe2, 0x48, 0xa5, 0xeb, 0x31, 0x2b, 0xaf, 0x72, 0xa7, 0x84, + 0x59, 0xc4, 0xb3, 0x55, 0xcb, 0x6f, 0x1f, 0x24, 0x4f, 0x05, 0x1a, 0x17, + 0x26, 0xe2, 0xce, 0xe4, 0xcb, 0xcb, 0x16, 0x7e, 0x09, 0x69, 0x4a, 0x04, + 0x74, 0x5b, 0xaa, 0xec, 0x61, 0x0f, 0x3a, 0xcb, 0x08, 0x7d, 0xaf, 0xa9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_136_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0xb8, 0x1a, 0xc9, 0x91, 0xf6, 0x19, 0xb2, 0x14, 0xc6, 0xce, 0x1e, + 0x4f, 0xb4, 0x80, 0x9d, 0x18, 0xdb, 0xc1, 0x2f, 0x8b, 0x30, 0xf8, 0x6e, + 0x34, 0x92, 0xc4, 0x54, 0xbc, 0x5c, 0x22, 0x06, 0x77, 0x92, 0x68, 0x2c, + 0xcd, 0xd8, 0xd5, 0x3f, 0x8f, 0xd8, 0x61, 0x32, 0x53, 0x5d, 0x73, 0x1e, + 0x64, 0xcc, 0x2a, 0x85, 0x51, 0x3a, 0x86, 0x12, 0xf7, 0x52, 0x11, 0xa6, + 0x0a, 0x1c, 0x47, 0x5b, 0xa1, 0x24, 0x5e, 0xd9, 0x43, 0xe4, 0xfe, 0xc5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_136_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x88, 0xb0, 0xb2, 0x58, 0xc4, 0x1f, 0xf1, 0x74, 0xad, 0xb6, 0x5c, + 0x8c, 0xfd, 0x63, 0x0c, 0x88, 0xc5, 0x77, 0x17, 0x30, 0x37, 0x05, 0xd3, + 0x4f, 0xd0, 0x71, 0x01, 0x40, 0xb2, 0x5c, 0x4a, 0xd2, 0x04, 0x0e, 0x40, + 0x66, 0xa5, 0xbd, 0x21, 0x64, 0xf2, 0xfb, 0x98, 0xb0, 0x96, 0x2d, 0x6a, + 0x88, 0x71, 0x90, 0x2d, 0x8d, 0x6e, 0xef, 0x02, 0x46, 0x0d, 0xa5, 0x7d, + 0xcd, 0x92, 0xb3, 0x0e, 0x24, 0xe8, 0xd7, 0x59, 0xb1, 0x1a, 0xd6, 0x39 +}; +/* k = 17cd7b62dde55ca12e74b81a852b4f8f400fca8df8a3c03027a247dba330b08ea751d3fa704c1a6521d8494a8fc8c670fdc35208d61722bb1d4d7efe7a42c32b0afb713369fbfa0 */ +static const uint8_t nist_186_2_ecdsa_testvector_136_out[] = { +/* R - byte alignment */ + 0x00, 0x31, 0x2a, 0xa5, 0x93, 0xaf, 0xe9, 0x87, 0x55, 0x4e, 0xff, 0x95, + 0x66, 0x47, 0xf6, 0xc8, 0xc4, 0xa2, 0x33, 0xa9, 0xc7, 0x72, 0xd3, 0x82, + 0x4b, 0x2b, 0xfb, 0x12, 0xfe, 0x9f, 0x5e, 0xfd, 0x47, 0x63, 0xc2, 0x84, + 0x75, 0xcd, 0x76, 0x4f, 0x67, 0xe0, 0x94, 0x7d, 0x43, 0x94, 0x5d, 0x78, + 0x38, 0x4f, 0xfb, 0xf7, 0xd9, 0xf9, 0xc4, 0x7b, 0x96, 0x77, 0xb5, 0x9d, + 0xc2, 0xdf, 0xd6, 0x58, 0x77, 0xab, 0xff, 0x95, 0xe1, 0x16, 0xf1, 0x90, +/* S - byte alignment */ + 0x00, 0x66, 0xba, 0x80, 0xd6, 0x13, 0xe9, 0x80, 0x7e, 0xc1, 0x7b, 0x46, + 0xe9, 0x62, 0x53, 0x57, 0xeb, 0x5a, 0x32, 0xb3, 0xaf, 0x21, 0x96, 0x2d, + 0x4e, 0xd1, 0x2a, 0x52, 0x3a, 0xf8, 0xc8, 0x4b, 0x6c, 0x5e, 0x35, 0x7b, + 0xee, 0x20, 0x6c, 0xe7, 0x34, 0xf5, 0xe1, 0x96, 0x6a, 0xe5, 0xc0, 0x47, + 0xe9, 0x8d, 0x56, 0xd4, 0x35, 0xc0, 0xe6, 0xa3, 0xe9, 0xb7, 0x61, 0xce, + 0xf9, 0xdc, 0x57, 0x7e, 0x14, 0x5e, 0x72, 0x47, 0xe2, 0x39, 0x09, 0x1d +}; +static const uint8_t nist_186_2_ecdsa_testvector_137_ptx[] = { +/* Msg */ + 0x6d, 0x0b, 0x8b, 0xb0, 0x43, 0xb2, 0x5c, 0x2a, 0x4e, 0x69, 0xf8, 0x59, + 0xfb, 0xf4, 0xdf, 0x4c, 0x6e, 0xf9, 0xf0, 0xf3, 0x25, 0x12, 0x30, 0xd6, + 0xd8, 0x21, 0xc7, 0x06, 0xa4, 0xe4, 0x4b, 0x54, 0x69, 0xc9, 0x41, 0xc2, + 0x71, 0x03, 0xe1, 0x37, 0x52, 0xdd, 0x1a, 0x77, 0x15, 0x4e, 0xd6, 0x51, + 0x97, 0xce, 0x7f, 0x1b, 0x30, 0x69, 0xc2, 0x5b, 0x93, 0x12, 0x93, 0xc7, + 0xf5, 0x39, 0x71, 0x70, 0x72, 0xa0, 0xeb, 0x3a, 0xac, 0x6a, 0x63, 0x8f, + 0xb5, 0x75, 0x12, 0x54, 0x2f, 0xe9, 0x4c, 0x1c, 0xb1, 0x11, 0x05, 0x9c, + 0x6d, 0x6a, 0x95, 0x60, 0x10, 0xfa, 0xb8, 0xbc, 0xea, 0xe3, 0xd9, 0x04, + 0x4f, 0x38, 0x90, 0xff, 0x3d, 0x0f, 0x69, 0x9a, 0x3e, 0xd8, 0xe7, 0xda, + 0x90, 0xed, 0xc8, 0x14, 0x84, 0x6a, 0x8b, 0x60, 0x24, 0x3e, 0x30, 0x4b, + 0x18, 0x82, 0x3f, 0xcc, 0xcb, 0x0a, 0x0b, 0x7a +}; +static const uint8_t nist_186_2_ecdsa_testvector_137_private[] = { +/* d - byte alignment */ + 0x00, 0x31, 0xdc, 0xf1, 0xb8, 0xaf, 0x2a, 0xb6, 0x2b, 0x76, 0xe1, 0x6a, + 0x99, 0x52, 0x06, 0xd2, 0x4c, 0x14, 0xae, 0x95, 0xa1, 0x36, 0x59, 0x69, + 0x97, 0xb8, 0x97, 0x23, 0xcd, 0xc1, 0xbd, 0xf0, 0xbe, 0x2d, 0x1d, 0x62, + 0xff, 0x6f, 0x2b, 0xeb, 0x88, 0xa5, 0x59, 0x2f, 0xcd, 0x4d, 0x88, 0xca, + 0x67, 0x6a, 0x8c, 0xa2, 0xb5, 0x2c, 0xb5, 0x25, 0xa2, 0x8e, 0x91, 0xec, + 0xf6, 0x49, 0x22, 0xac, 0xde, 0xf3, 0x88, 0x49, 0x49, 0x2d, 0x62, 0x3f +}; +static const uint8_t nist_186_2_ecdsa_testvector_137_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0xcd, 0xa2, 0xb2, 0xb3, 0x0b, 0xac, 0xf5, 0xd1, 0x7f, 0x34, 0x25, + 0xba, 0x7e, 0x56, 0x24, 0x15, 0x19, 0xe4, 0xe7, 0x61, 0x5c, 0x22, 0xed, + 0xad, 0xc4, 0xfd, 0x0c, 0x3e, 0x73, 0x1b, 0x33, 0x5e, 0xa7, 0x4d, 0x2f, + 0xc0, 0xb5, 0x11, 0x01, 0xdc, 0xd2, 0x39, 0xbc, 0xab, 0xd8, 0xab, 0xf6, + 0xa1, 0x6d, 0x2b, 0x96, 0xa8, 0x5c, 0x0e, 0x39, 0xbd, 0x9a, 0x67, 0x59, + 0x1b, 0xc1, 0x4c, 0x05, 0xd3, 0x17, 0x6d, 0xbc, 0xe6, 0x65, 0xa8, 0xcb +}; +static const uint8_t nist_186_2_ecdsa_testvector_137_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0xb1, 0xe2, 0x71, 0xff, 0x46, 0x4f, 0x0e, 0x2b, 0x30, 0xee, 0xe4, + 0x14, 0x47, 0xed, 0xb0, 0x65, 0xff, 0xf9, 0x37, 0x5a, 0x0c, 0x49, 0x69, + 0x01, 0xc3, 0x8e, 0xf2, 0x54, 0xaa, 0x1a, 0x7d, 0x90, 0x24, 0x74, 0x1f, + 0x99, 0x84, 0x1a, 0xf2, 0xaa, 0xb8, 0xe3, 0x08, 0x66, 0x23, 0x46, 0x4f, + 0x23, 0x15, 0x09, 0x4c, 0x02, 0x56, 0x4f, 0x8b, 0xfe, 0x8c, 0xec, 0x30, + 0xe4, 0xd6, 0xa8, 0x19, 0x51, 0xfd, 0x3b, 0x4b, 0x45, 0x81, 0x39, 0x12 +}; +/* k = 0f660a7340497ba7a7fe947d51573bc9e0cadb7890cb8f8969651467d4172efa0d201d9f19fc047177a04261794cd85e17829eb569e414b7829f07f8546b38c454a9ab124daf638 */ +static const uint8_t nist_186_2_ecdsa_testvector_137_out[] = { +/* R - byte alignment */ + 0x01, 0xf4, 0x8f, 0xb9, 0xc3, 0x18, 0x15, 0x34, 0x19, 0x85, 0x9f, 0xc2, + 0xe3, 0x3d, 0x42, 0x6f, 0x3d, 0x04, 0x83, 0xb6, 0x0e, 0x6f, 0x2d, 0x27, + 0xb7, 0xa8, 0xef, 0xb5, 0xce, 0x70, 0xde, 0x48, 0x61, 0xe4, 0xf9, 0xbc, + 0x01, 0xcc, 0xfb, 0x95, 0x7a, 0x17, 0x94, 0x13, 0x9e, 0x06, 0x91, 0x25, + 0xcf, 0x25, 0xa4, 0xd4, 0x5e, 0x2b, 0xfa, 0xd1, 0x5f, 0x79, 0x77, 0x4a, + 0xb9, 0x73, 0x33, 0x57, 0x79, 0xb0, 0x95, 0xea, 0xef, 0x7f, 0x06, 0xac, +/* S - byte alignment */ + 0x01, 0x83, 0x81, 0x4e, 0x2e, 0x7d, 0xdd, 0x53, 0xaa, 0x0d, 0xd3, 0xec, + 0x36, 0x89, 0x0b, 0xe7, 0x0c, 0x30, 0xd6, 0x24, 0x19, 0x21, 0x7b, 0x60, + 0x74, 0x61, 0xa6, 0xfe, 0xf8, 0x28, 0x84, 0xfe, 0x91, 0xaf, 0x44, 0xee, + 0xc6, 0xad, 0xd4, 0xc0, 0x58, 0x6d, 0x27, 0x2d, 0x9c, 0x57, 0x39, 0x8c, + 0x3f, 0x94, 0x42, 0xa3, 0x22, 0x21, 0xed, 0x0f, 0x71, 0xd4, 0xe5, 0x84, + 0x46, 0x03, 0x94, 0xcf, 0x34, 0xe0, 0x18, 0x2f, 0x0b, 0x92, 0x24, 0xbd +}; +static const uint8_t nist_186_2_ecdsa_testvector_138_ptx[] = { +/* Msg */ + 0x6d, 0x6b, 0x2c, 0xeb, 0x19, 0xfa, 0x08, 0xfa, 0x47, 0xa8, 0x9c, 0xae, + 0x1b, 0x97, 0xc8, 0x76, 0x1c, 0xc6, 0xea, 0x49, 0x38, 0xf8, 0x02, 0x37, + 0x09, 0xf1, 0x14, 0x45, 0x56, 0xe8, 0xce, 0x77, 0xdd, 0x3a, 0x6b, 0x2e, + 0x4f, 0x5c, 0xd7, 0xb4, 0x9d, 0x13, 0x14, 0x16, 0x72, 0xe7, 0xdc, 0x32, + 0x00, 0xd5, 0x88, 0x10, 0x00, 0x44, 0x30, 0x76, 0xf4, 0x3a, 0x14, 0xb6, + 0xb0, 0xd0, 0x3a, 0xcb, 0x18, 0xe3, 0x59, 0xa4, 0x2b, 0x0d, 0xf6, 0xc0, + 0x41, 0xd3, 0xcd, 0xfb, 0x90, 0x20, 0x72, 0xa8, 0xf5, 0xf3, 0x38, 0xdf, + 0xf2, 0x54, 0x52, 0x18, 0xf3, 0x8c, 0x38, 0xf9, 0xd5, 0x95, 0x4d, 0x6d, + 0xa8, 0xd0, 0xbe, 0xf6, 0xb4, 0xf6, 0xad, 0x44, 0xbb, 0x51, 0x8f, 0x06, + 0x7e, 0x2c, 0xd2, 0x00, 0x82, 0x88, 0xc3, 0x5e, 0x14, 0x10, 0xb0, 0x48, + 0x8b, 0x4f, 0x49, 0xb6, 0xcd, 0x21, 0x4c, 0x86 +}; +static const uint8_t nist_186_2_ecdsa_testvector_138_private[] = { +/* d - byte alignment */ + 0x01, 0x45, 0x45, 0x6a, 0x77, 0x55, 0x32, 0x1b, 0x3c, 0xbc, 0x7b, 0xf9, + 0x9e, 0x06, 0x12, 0xa8, 0xfc, 0x0a, 0x2b, 0x2d, 0x12, 0xee, 0x48, 0xb1, + 0xe6, 0xb5, 0x34, 0x79, 0xb1, 0x4b, 0x0a, 0xf5, 0x61, 0xe9, 0xa9, 0xce, + 0x95, 0x38, 0x6b, 0xd1, 0x33, 0x2c, 0x25, 0xaf, 0x0f, 0x35, 0x19, 0x2b, + 0x13, 0x9a, 0x46, 0x7c, 0x3e, 0xbc, 0x6d, 0xf2, 0x23, 0x44, 0xc9, 0xc4, + 0xdd, 0xaf, 0xe5, 0x4d, 0x9a, 0x87, 0x5e, 0xc1, 0xad, 0x34, 0xb1, 0xa4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_138_public_x[] = { +/* Qx - byte alignment */ + 0x07, 0x4a, 0x4e, 0x54, 0x6d, 0x69, 0x27, 0xb6, 0xab, 0xc9, 0xd2, 0x82, + 0x6e, 0x23, 0xbb, 0x4c, 0x2d, 0x2a, 0x3a, 0x67, 0x96, 0xe8, 0x61, 0xae, + 0x8f, 0x4e, 0xab, 0x8a, 0x4f, 0x90, 0x16, 0xbd, 0xa3, 0x69, 0x71, 0xe1, + 0x04, 0xba, 0x38, 0xcf, 0x1a, 0xba, 0x3a, 0x4f, 0x42, 0xe4, 0x76, 0x9d, + 0xad, 0x09, 0xbd, 0xa9, 0x5a, 0x75, 0x00, 0x1a, 0xe6, 0x15, 0xc5, 0x0d, + 0x52, 0x79, 0x3b, 0xec, 0x9f, 0xdf, 0x77, 0x63, 0x21, 0xac, 0xd5, 0x8c +}; +static const uint8_t nist_186_2_ecdsa_testvector_138_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xd6, 0xf8, 0x52, 0x91, 0xc9, 0xa1, 0x41, 0x08, 0xbd, 0xbd, 0x1e, + 0x57, 0xf5, 0x45, 0xac, 0xd3, 0x96, 0x02, 0x88, 0x71, 0x1d, 0x06, 0x14, + 0xd7, 0x4d, 0x6c, 0xdf, 0x85, 0x06, 0x67, 0x0b, 0xcb, 0x20, 0xa6, 0x80, + 0xbf, 0x6b, 0xc5, 0x34, 0xab, 0x2f, 0x82, 0xfa, 0x9d, 0x8a, 0x5a, 0xe2, + 0xd6, 0x01, 0xc8, 0xb3, 0xf4, 0x7c, 0xdd, 0x5a, 0xbf, 0x01, 0x23, 0xaf, + 0x80, 0xf7, 0xce, 0x4d, 0xcb, 0x98, 0xb0, 0xd8, 0x10, 0xd8, 0x52, 0x19 +}; +/* k = 1bb40f8257538fc900ce705b7ba3beab9b736871de75092547320051960fac4c531fcc7d67d849aa07ea35eb7773cd344329aa8a50c949cb2ef9e12a5cd46b4d10e02f8d4f31bb9 */ +static const uint8_t nist_186_2_ecdsa_testvector_138_out[] = { +/* R - byte alignment */ + 0x00, 0x63, 0xca, 0x4a, 0xbb, 0x7e, 0x43, 0x9f, 0x90, 0xd1, 0x4d, 0x76, + 0x76, 0x86, 0x91, 0x01, 0xb5, 0xcc, 0x88, 0xc0, 0xa5, 0xdd, 0x1c, 0xb9, + 0x6c, 0x36, 0xef, 0x1a, 0xee, 0x9b, 0xce, 0x43, 0x13, 0x68, 0x92, 0x62, + 0x20, 0xda, 0x46, 0x19, 0x5f, 0xf4, 0x64, 0x29, 0x45, 0x43, 0xfe, 0xd4, + 0xce, 0x21, 0xb9, 0xfa, 0x5a, 0x50, 0x6f, 0x6e, 0x13, 0x18, 0x3c, 0x4a, + 0x50, 0x52, 0xca, 0xf1, 0x0d, 0x8b, 0xd4, 0x81, 0xe5, 0x1c, 0x87, 0x1d, +/* S - byte alignment */ + 0x01, 0xda, 0x94, 0x69, 0x30, 0xd6, 0xcf, 0x5b, 0x27, 0xe3, 0x64, 0xc1, + 0x9b, 0x7a, 0x16, 0xd4, 0x70, 0x59, 0xde, 0x3a, 0x43, 0x91, 0xb9, 0x9c, + 0x80, 0xd8, 0x2b, 0x35, 0x4d, 0x77, 0xde, 0x00, 0xe2, 0x70, 0xe6, 0xda, + 0x67, 0x87, 0x96, 0x84, 0xfa, 0x5f, 0x51, 0x85, 0xe6, 0x39, 0x11, 0xde, + 0x52, 0x1c, 0x80, 0xbf, 0xc3, 0xf4, 0x2a, 0xfd, 0x37, 0x2a, 0xd7, 0x22, + 0x2f, 0xfd, 0xa1, 0xbd, 0xc2, 0x90, 0x35, 0x4f, 0x55, 0x84, 0xa2, 0x93 +}; +static const uint8_t nist_186_2_ecdsa_testvector_139_ptx[] = { +/* Msg */ + 0x89, 0x38, 0x19, 0x18, 0xe8, 0x03, 0x41, 0x47, 0xa8, 0x1a, 0x32, 0x14, + 0xa3, 0x43, 0xa8, 0x17, 0x9f, 0x7a, 0xc3, 0xc9, 0xc5, 0x94, 0x13, 0x45, + 0x55, 0x22, 0xf1, 0x4b, 0x97, 0x98, 0x16, 0x8a, 0x15, 0xaf, 0x66, 0x1f, + 0x07, 0x07, 0x0d, 0x59, 0x0f, 0x11, 0xcd, 0xbf, 0x26, 0x2c, 0x96, 0x54, + 0xd6, 0x0e, 0x58, 0x19, 0xab, 0x66, 0x15, 0xd4, 0xe4, 0xbf, 0x3a, 0x10, + 0x6d, 0xa8, 0x2f, 0x65, 0x12, 0x12, 0x2d, 0xf9, 0xed, 0xf9, 0x50, 0x47, + 0x20, 0x47, 0xed, 0x1f, 0xca, 0xf5, 0x25, 0xee, 0x33, 0x73, 0xba, 0x40, + 0x4a, 0x4a, 0x22, 0x83, 0x52, 0x00, 0xda, 0x0e, 0xd8, 0x3b, 0xfd, 0x62, + 0xe8, 0x2a, 0x15, 0xaf, 0x80, 0x21, 0x31, 0x9a, 0x45, 0x83, 0x38, 0x3d, + 0x75, 0xe5, 0x7c, 0x6f, 0x1d, 0x70, 0x92, 0x46, 0x8c, 0x87, 0x62, 0xdb, + 0x07, 0xaa, 0x7a, 0x4d, 0xbe, 0x9b, 0xa8, 0x09 +}; +static const uint8_t nist_186_2_ecdsa_testvector_139_private[] = { +/* d - byte alignment */ + 0x01, 0xf8, 0x79, 0x9a, 0xda, 0x52, 0x27, 0x82, 0xb4, 0x25, 0x39, 0x72, + 0x1c, 0x9a, 0x41, 0x87, 0x03, 0xd1, 0x75, 0xf4, 0xfa, 0x72, 0xe9, 0x8f, + 0x73, 0x87, 0x74, 0xd6, 0x8e, 0x02, 0x6f, 0xf6, 0x0d, 0x57, 0xa0, 0x39, + 0x70, 0xb2, 0xf6, 0x07, 0xc9, 0xce, 0x6d, 0x32, 0x6d, 0x6f, 0xad, 0x7e, + 0x1c, 0x86, 0x5f, 0x15, 0x1e, 0x89, 0xf7, 0xa3, 0x33, 0x3e, 0xa6, 0xfc, + 0xfc, 0x9c, 0x51, 0xd1, 0xeb, 0xe6, 0xf6, 0xaa, 0xfd, 0x9f, 0xf9, 0xfc +}; +static const uint8_t nist_186_2_ecdsa_testvector_139_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0x40, 0x1a, 0x65, 0x61, 0x79, 0xf5, 0x45, 0x2b, 0x1a, 0x1f, 0xdd, + 0x17, 0xe7, 0x35, 0xc6, 0xc4, 0x09, 0xa6, 0xd9, 0xbb, 0xa2, 0x99, 0xce, + 0xe1, 0x66, 0xc4, 0xf4, 0xa7, 0x7f, 0xfc, 0xbb, 0x1c, 0x83, 0x3c, 0x18, + 0x54, 0xb7, 0xc0, 0x99, 0x07, 0x3e, 0x2d, 0x16, 0xce, 0x24, 0xac, 0xfd, + 0x02, 0x68, 0xaf, 0x65, 0xc3, 0x56, 0x6e, 0xf3, 0xdd, 0xe7, 0x96, 0x61, + 0xee, 0xd1, 0x8b, 0x58, 0x64, 0xaa, 0x94, 0xd0, 0x27, 0x7c, 0x1f, 0x12 +}; +static const uint8_t nist_186_2_ecdsa_testvector_139_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0x6a, 0xf9, 0x9d, 0x03, 0xe7, 0x22, 0x2d, 0x03, 0x3c, 0x30, 0x91, + 0x42, 0x30, 0x01, 0x88, 0xdd, 0xf4, 0xfa, 0x52, 0xfb, 0xdc, 0x46, 0xe7, + 0xbe, 0xe8, 0xe3, 0x74, 0x49, 0x00, 0x86, 0xa8, 0xeb, 0x4f, 0xc9, 0x1f, + 0xdb, 0xab, 0x67, 0xe5, 0xaa, 0x55, 0xd9, 0xfd, 0x80, 0x91, 0xe1, 0x40, + 0x12, 0x93, 0xeb, 0x96, 0x3b, 0x2c, 0x14, 0x5b, 0x52, 0xc7, 0xfa, 0xa3, + 0x8d, 0x80, 0x12, 0xe8, 0x85, 0xbe, 0xaf, 0x15, 0x5e, 0xca, 0x7a, 0x4b +}; +/* k = 1bd9d3ecf3ac1c7b8c1631d9647222372d6830e81b880f1dc86a23a24849d7eb3602d970b7cffb138023702ca02164cc62f526daec5158619ea8b79f2384b60ab4ddf034d2c5f28 */ +static const uint8_t nist_186_2_ecdsa_testvector_139_out[] = { +/* R - byte alignment */ + 0x01, 0x4c, 0x44, 0xb4, 0x90, 0xdb, 0x92, 0x39, 0x26, 0xbd, 0x9b, 0x39, + 0x6f, 0x7e, 0xfb, 0xab, 0xd1, 0x11, 0xa6, 0x2a, 0x98, 0x13, 0xeb, 0x4b, + 0x86, 0x95, 0xb0, 0x87, 0x95, 0x80, 0x22, 0x26, 0x3b, 0x10, 0xdd, 0xd9, + 0x96, 0x4b, 0x0e, 0xc2, 0x20, 0x1c, 0x0f, 0xb5, 0x47, 0x77, 0x45, 0x86, + 0x55, 0x3f, 0x9e, 0x09, 0xe2, 0x33, 0x97, 0x5e, 0x85, 0xcb, 0x74, 0x98, + 0xa9, 0xeb, 0x69, 0x01, 0x76, 0x8f, 0xea, 0x70, 0xfa, 0x53, 0x0d, 0x42, +/* S - byte alignment */ + 0x01, 0x79, 0x72, 0xbf, 0x17, 0xf9, 0xa7, 0x52, 0x9b, 0xdb, 0x84, 0xe2, + 0xbb, 0xd7, 0x6c, 0x95, 0x72, 0x17, 0x6f, 0x3c, 0x02, 0x17, 0xaf, 0x1f, + 0x98, 0x19, 0xd2, 0x16, 0xd8, 0x71, 0xff, 0x91, 0xb4, 0xdc, 0xc0, 0x90, + 0xc3, 0x93, 0xee, 0xc2, 0x76, 0x62, 0xf4, 0xb2, 0x72, 0xa5, 0xe0, 0x70, + 0x60, 0xb6, 0xd6, 0xf4, 0xf4, 0xe5, 0x72, 0x96, 0x2b, 0xc4, 0xec, 0x3f, + 0x70, 0xd5, 0x2b, 0x73, 0x1c, 0xb6, 0x54, 0xeb, 0x3b, 0x3f, 0xa7, 0x08 +}; +static const uint8_t nist_186_2_ecdsa_testvector_140_ptx[] = { +/* Msg */ + 0x43, 0x78, 0x26, 0x28, 0x31, 0x57, 0xd8, 0x6b, 0x9f, 0xab, 0x3c, 0x58, + 0xcb, 0x8f, 0x9a, 0x6a, 0x53, 0xf8, 0x99, 0xf7, 0x49, 0x83, 0xfa, 0x11, + 0x85, 0x71, 0x86, 0xab, 0x3f, 0xef, 0x45, 0xfc, 0xdd, 0x9b, 0xf1, 0x29, + 0x09, 0x45, 0xaa, 0x1e, 0x07, 0xf2, 0xeb, 0xbc, 0x45, 0x27, 0xbd, 0x3a, + 0x34, 0x64, 0x2b, 0xc5, 0x57, 0xee, 0xf5, 0x6a, 0x9a, 0xd1, 0x89, 0x36, + 0xe4, 0x26, 0x2e, 0x9c, 0xef, 0x92, 0x83, 0x16, 0x58, 0x0f, 0x28, 0x0f, + 0xf2, 0xef, 0xbb, 0x01, 0x60, 0x1e, 0x06, 0xdb, 0xe3, 0xa7, 0x76, 0xa5, + 0x70, 0x79, 0xcf, 0x66, 0x06, 0x6c, 0x1f, 0x46, 0x3e, 0x7f, 0xf1, 0xf0, + 0x24, 0x63, 0xc2, 0x3a, 0x45, 0x3e, 0xb9, 0x08, 0x09, 0xa9, 0x92, 0x6d, + 0x43, 0xfa, 0xdc, 0x14, 0x07, 0xc9, 0x64, 0xdf, 0xbc, 0xad, 0xf1, 0xcd, + 0x71, 0x47, 0x31, 0x21, 0x75, 0x82, 0xf4, 0xc1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_140_private[] = { +/* d - byte alignment */ + 0x01, 0x7f, 0x4f, 0xd6, 0x76, 0x9e, 0x2b, 0x06, 0xe2, 0x8a, 0xd0, 0x7b, + 0x58, 0x6c, 0x88, 0x8a, 0x3f, 0xb6, 0x2d, 0x90, 0x4a, 0x79, 0x5d, 0x82, + 0x97, 0x5d, 0xaf, 0x90, 0x02, 0xad, 0xda, 0x1a, 0x48, 0x12, 0xad, 0xbc, + 0xa3, 0x27, 0x21, 0x52, 0x26, 0x88, 0x5d, 0x70, 0x24, 0x1d, 0xd4, 0xf5, + 0xfd, 0xf6, 0xdb, 0xf5, 0xdd, 0xbc, 0x97, 0xfb, 0x43, 0x81, 0x53, 0x11, + 0xd3, 0x9c, 0x82, 0xa0, 0xc3, 0xc7, 0xaf, 0xad, 0x7d, 0xf7, 0x5a, 0x83 +}; +static const uint8_t nist_186_2_ecdsa_testvector_140_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0x52, 0xd9, 0x55, 0x8a, 0x4e, 0x7c, 0x0a, 0x74, 0xfc, 0xe5, 0x1a, + 0x62, 0x27, 0x00, 0x13, 0x61, 0x67, 0xe7, 0x0f, 0x07, 0xf2, 0xcb, 0x4c, + 0x11, 0x3d, 0xd2, 0xdd, 0x42, 0x60, 0xf0, 0xc6, 0x63, 0x36, 0xb4, 0x0d, + 0xb3, 0xc5, 0xf9, 0x00, 0xae, 0x15, 0xf9, 0x0f, 0x58, 0x0d, 0x0a, 0x2f, + 0x4e, 0xe8, 0x87, 0xc1, 0x6c, 0x12, 0xc2, 0xa7, 0x00, 0x61, 0x80, 0x1a, + 0x96, 0xdd, 0x6f, 0xcb, 0x89, 0xb5, 0xca, 0x13, 0x08, 0xc0, 0xba, 0x91 +}; +static const uint8_t nist_186_2_ecdsa_testvector_140_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x08, 0xfa, 0x08, 0xed, 0xe3, 0x83, 0x3a, 0x0a, 0xce, 0xba, 0xb0, + 0x03, 0xb9, 0xc2, 0x2c, 0x43, 0x7e, 0x7a, 0x2b, 0x2a, 0x25, 0x20, 0xb1, + 0x50, 0x33, 0xbf, 0x4f, 0x9e, 0x94, 0x3f, 0x2f, 0x77, 0x6b, 0x3e, 0xdc, + 0x55, 0xa6, 0xcc, 0x41, 0x2c, 0xf6, 0x08, 0x9f, 0x0c, 0x48, 0x65, 0x64, + 0xc3, 0x71, 0x8c, 0x4a, 0x15, 0x41, 0x48, 0x6b, 0x79, 0x24, 0xe8, 0x60, + 0x5d, 0x72, 0xc5, 0x91, 0x80, 0x7c, 0x1c, 0x83, 0xbd, 0x09, 0xf9, 0x34 +}; +/* k = 07d322958bb1c35a57a5c12b9791419a127a7731d550acb027bebe102140e1ecb72cb7f986e930320733dbbe7d8680f221c3fea64416db7484da8270ff7b1e32be7d30e27169954 */ +static const uint8_t nist_186_2_ecdsa_testvector_140_out[] = { +/* R - byte alignment */ + 0x01, 0xd8, 0x56, 0x2a, 0xb3, 0x89, 0x78, 0xd1, 0xdd, 0x6a, 0x64, 0xd8, + 0x23, 0xf9, 0x4c, 0x1a, 0xd5, 0xbe, 0x5d, 0xd4, 0x1e, 0x78, 0x5d, 0xd9, + 0x1f, 0x2e, 0xb5, 0xc5, 0x20, 0x42, 0x0e, 0x4e, 0xdc, 0x4d, 0xec, 0xfc, + 0x2e, 0xb6, 0x9e, 0x4a, 0x43, 0xe3, 0x22, 0x41, 0xb9, 0xbb, 0x5a, 0x41, + 0x77, 0x22, 0xac, 0xeb, 0xad, 0x1c, 0x5f, 0x43, 0x98, 0x30, 0x0f, 0xde, + 0xc3, 0x47, 0x35, 0xeb, 0x22, 0x97, 0x43, 0xd4, 0x14, 0x75, 0xfd, 0xcc, +/* S - byte alignment */ + 0x00, 0xd7, 0xa8, 0xfe, 0x30, 0x04, 0x07, 0x2c, 0x40, 0xbe, 0xd0, 0x3c, + 0xc2, 0xbf, 0x7f, 0x32, 0x9d, 0xef, 0x7e, 0xb2, 0x90, 0x44, 0x37, 0x2b, + 0xd8, 0x3c, 0x6b, 0xeb, 0xa0, 0xbb, 0x6c, 0xab, 0x90, 0xec, 0xb8, 0x6c, + 0x94, 0x32, 0xa0, 0xbc, 0xb8, 0x25, 0xce, 0xce, 0x47, 0x19, 0x00, 0xc0, + 0xe6, 0x0a, 0xad, 0x50, 0x4d, 0xac, 0xc7, 0xd4, 0x6f, 0x63, 0x27, 0x68, + 0x2d, 0xc4, 0xc8, 0x51, 0x24, 0x83, 0xcf, 0x47, 0x6f, 0xc8, 0x3d, 0xb5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_141_ptx[] = { +/* Msg */ + 0xbe, 0xd6, 0xe6, 0x9f, 0xe6, 0x2e, 0xae, 0x11, 0x73, 0x1e, 0x55, 0xf7, + 0x70, 0x5a, 0x50, 0x43, 0x1a, 0xf7, 0xea, 0x62, 0x36, 0x74, 0x39, 0x63, + 0xa8, 0xfa, 0x50, 0x5c, 0x42, 0xe3, 0xb6, 0x09, 0xda, 0x7a, 0x17, 0xb7, + 0x9f, 0x01, 0x3a, 0x60, 0xad, 0xf9, 0x33, 0x18, 0xde, 0x9d, 0xda, 0xa7, + 0xe3, 0xb0, 0x7b, 0x78, 0x94, 0x78, 0xcf, 0xb2, 0x85, 0x0b, 0x2b, 0xa4, + 0xda, 0xc9, 0xf8, 0x66, 0x5c, 0x2a, 0x63, 0xbd, 0xcc, 0xba, 0x55, 0x40, + 0x77, 0x61, 0xa6, 0xb9, 0x0a, 0xe8, 0x8e, 0xce, 0xa8, 0xb9, 0x5c, 0xe1, + 0x3a, 0xe6, 0x6a, 0x34, 0x06, 0x6d, 0x50, 0x51, 0x84, 0xbb, 0x58, 0xa9, + 0x6c, 0x6e, 0x32, 0x7b, 0x14, 0x5f, 0xe9, 0xf7, 0xf9, 0xe0, 0x16, 0xa4, + 0x9b, 0x42, 0x54, 0xff, 0x8f, 0x9b, 0xf3, 0x65, 0xcf, 0xc5, 0xf1, 0x32, + 0x54, 0xaa, 0x25, 0x2b, 0xe7, 0xbf, 0xbe, 0x19 +}; +static const uint8_t nist_186_2_ecdsa_testvector_141_private[] = { +/* d - byte alignment */ + 0x00, 0x6d, 0xdd, 0xac, 0x33, 0x80, 0xd7, 0x99, 0x85, 0x0f, 0xb7, 0xe2, + 0xd2, 0xc8, 0x71, 0x35, 0x47, 0xf7, 0x6b, 0x30, 0x92, 0x4b, 0xa7, 0xa3, + 0xc2, 0xa0, 0x51, 0x10, 0x52, 0xe0, 0x63, 0x51, 0xe0, 0xc2, 0x10, 0x51, + 0x79, 0xd5, 0xb4, 0x30, 0xad, 0x3e, 0xa9, 0xbe, 0x3d, 0xa5, 0x1a, 0x8d, + 0x4f, 0x3c, 0xa9, 0x13, 0xb4, 0xa8, 0x4b, 0xfe, 0x0a, 0x4a, 0x38, 0xfc, + 0xfe, 0xe6, 0xd5, 0x11, 0x71, 0x44, 0x3b, 0x31, 0x52, 0x71, 0xc5, 0x85 +}; +static const uint8_t nist_186_2_ecdsa_testvector_141_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0xb5, 0x73, 0x91, 0x18, 0xa1, 0x9a, 0xa7, 0x2e, 0xfa, 0x96, 0x97, + 0x16, 0x82, 0x7f, 0xff, 0xf7, 0x4d, 0xa1, 0x7f, 0xae, 0x33, 0xdc, 0xa2, + 0xe7, 0xfe, 0xbc, 0x36, 0x96, 0x6f, 0x27, 0xb5, 0x4e, 0xac, 0x18, 0xd0, + 0x01, 0x8c, 0x98, 0xcf, 0xe5, 0xaa, 0x84, 0xd4, 0x54, 0x11, 0xae, 0x69, + 0xc8, 0x15, 0xeb, 0x92, 0x99, 0xf0, 0x11, 0x5d, 0xc4, 0x44, 0x3f, 0xdc, + 0x6d, 0x01, 0x8a, 0x38, 0x92, 0x0c, 0x63, 0x99, 0x43, 0x2c, 0xb5, 0x04 +}; +static const uint8_t nist_186_2_ecdsa_testvector_141_public_y[] = { +/* Qy - byte alignment */ + 0x07, 0x6a, 0xa0, 0x85, 0x67, 0x97, 0xe3, 0x7b, 0x6f, 0x16, 0xf7, 0x0e, + 0xb5, 0xcd, 0xd8, 0xb8, 0xef, 0x20, 0x13, 0xae, 0xcf, 0xa4, 0x4c, 0x43, + 0xd4, 0x7f, 0xca, 0x5e, 0x41, 0x72, 0xd0, 0xa0, 0x35, 0x47, 0xe4, 0xf5, + 0xdf, 0x2a, 0xe3, 0x61, 0x12, 0xe4, 0x0b, 0x69, 0x98, 0x40, 0xc9, 0xff, + 0x1a, 0xa5, 0x9e, 0x76, 0xe3, 0xfe, 0xc8, 0x72, 0x1a, 0x01, 0xb5, 0xe5, + 0xa4, 0x04, 0xda, 0xaa, 0x39, 0x58, 0x12, 0x62, 0xa2, 0x60, 0xe4, 0xb8 +}; +/* k = 030222f1352ac2444d325de02d037d8dbe9a7c40e5db167f0d76d2f805c04a1c6a4535ca435fe38628b65aeb0043dbd14d35363bd138dc8543da3646b419672f9d193e4c9383fcb */ +static const uint8_t nist_186_2_ecdsa_testvector_141_out[] = { +/* R - byte alignment */ + 0x01, 0x2b, 0xbd, 0xae, 0xbe, 0x06, 0xe3, 0xf5, 0x26, 0xcc, 0x72, 0x22, + 0xa8, 0x0f, 0xea, 0xc9, 0x37, 0xa1, 0x2d, 0xa5, 0xf4, 0xd7, 0x78, 0x04, + 0x39, 0x58, 0x57, 0x80, 0xee, 0x52, 0x6c, 0x83, 0x8b, 0x38, 0xd2, 0x6d, + 0x12, 0x65, 0x6b, 0x61, 0xf2, 0xcb, 0x5b, 0x9c, 0xf0, 0xf9, 0x6e, 0xbc, + 0x64, 0x21, 0x0f, 0x29, 0xac, 0xc4, 0x01, 0x24, 0xa8, 0x93, 0x74, 0xb4, + 0x27, 0xb7, 0x18, 0xfb, 0x5d, 0x0f, 0x47, 0xdb, 0x02, 0xd6, 0x7d, 0x89, +/* S - byte alignment */ + 0x01, 0xb6, 0xd0, 0x8c, 0xc5, 0x3e, 0xbc, 0xa5, 0xd9, 0x09, 0x61, 0xa6, + 0xd8, 0x7c, 0x61, 0x78, 0xc3, 0x62, 0xc4, 0xb1, 0xef, 0x2f, 0xee, 0xc3, + 0x8d, 0x87, 0xac, 0x4d, 0x37, 0x92, 0x42, 0x3b, 0x83, 0x4b, 0x70, 0xce, + 0xc9, 0x19, 0x47, 0xdb, 0x65, 0x05, 0xb0, 0x31, 0x9a, 0xba, 0xb7, 0xb5, + 0xdb, 0x0d, 0x4d, 0x8b, 0x6e, 0xbe, 0x29, 0x0b, 0xe0, 0xb9, 0xf5, 0x6a, + 0x19, 0x53, 0xd4, 0xb6, 0x1e, 0xce, 0x9e, 0xde, 0x96, 0x91, 0x45, 0xdf +}; +static const uint8_t nist_186_2_ecdsa_testvector_142_ptx[] = { +/* Msg */ + 0x9c, 0x1f, 0xdd, 0xc0, 0xf4, 0x33, 0x97, 0xf5, 0x68, 0xd7, 0xe2, 0xab, + 0xca, 0x6e, 0x2c, 0xe1, 0x25, 0xa2, 0x04, 0x3f, 0x95, 0xed, 0x8a, 0xb5, + 0x5c, 0x5e, 0x24, 0x60, 0x33, 0x9a, 0x73, 0xad, 0xde, 0x21, 0x86, 0xc0, + 0x03, 0xd2, 0x4d, 0x17, 0x3c, 0xb2, 0x50, 0x6a, 0x6b, 0xe9, 0xa0, 0xd6, + 0x4e, 0x0d, 0x0e, 0x3b, 0x53, 0xa3, 0x9c, 0xe3, 0xad, 0xe3, 0x31, 0x64, + 0xa7, 0xbc, 0x91, 0xc7, 0x38, 0x18, 0x8b, 0xe9, 0xd8, 0x61, 0x75, 0x22, + 0x93, 0x44, 0xd5, 0x25, 0x5c, 0xb5, 0x61, 0x27, 0xa3, 0x33, 0x2a, 0x44, + 0x2a, 0x4d, 0x14, 0x1e, 0x14, 0x65, 0x89, 0xc7, 0x3f, 0xb4, 0x6e, 0xe1, + 0xd3, 0x8e, 0x56, 0x03, 0x1b, 0xe7, 0xf6, 0x5f, 0x94, 0x17, 0xda, 0xa2, + 0x44, 0xda, 0x56, 0x1c, 0x4d, 0x9b, 0xbe, 0x21, 0xc2, 0xf2, 0xd9, 0xaf, + 0xb9, 0x6b, 0x94, 0x50, 0xa2, 0x89, 0xf4, 0x42 +}; +static const uint8_t nist_186_2_ecdsa_testvector_142_private[] = { +/* d - byte alignment */ + 0x01, 0x09, 0xb0, 0x9c, 0x1b, 0xb1, 0x8f, 0x36, 0x3e, 0x67, 0x35, 0xa6, + 0xd0, 0xae, 0xd4, 0xa2, 0x2e, 0x83, 0xe3, 0x3d, 0xc1, 0xf7, 0xbd, 0x74, + 0xe0, 0x28, 0xd2, 0x07, 0xe2, 0xc8, 0x88, 0x37, 0x1b, 0x42, 0xd1, 0x8c, + 0x37, 0x6b, 0xd5, 0x0f, 0x16, 0xdb, 0x9b, 0xef, 0x49, 0x11, 0x3f, 0xc3, + 0xc0, 0x09, 0x21, 0x4c, 0xcc, 0x78, 0xb5, 0x8a, 0x73, 0x1b, 0xc0, 0x1d, + 0xbe, 0x37, 0x4a, 0xfb, 0x58, 0x8f, 0x09, 0xbe, 0x08, 0xba, 0x14, 0xcc +}; +static const uint8_t nist_186_2_ecdsa_testvector_142_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0x6e, 0xd6, 0x64, 0x95, 0xaa, 0x19, 0x9e, 0x00, 0x88, 0xfd, 0x9a, + 0xe6, 0xba, 0x4a, 0xbe, 0x61, 0x71, 0xcf, 0xfe, 0x75, 0x67, 0xfb, 0x37, + 0x3c, 0x59, 0x86, 0xec, 0x0f, 0xbb, 0xe6, 0xad, 0x4e, 0x8d, 0xbb, 0x90, + 0x16, 0x69, 0x02, 0x81, 0xa9, 0x72, 0x89, 0xbd, 0x58, 0x96, 0x4d, 0x62, + 0xf7, 0xf7, 0x84, 0x30, 0x93, 0x53, 0xbe, 0xfa, 0x0f, 0x82, 0x47, 0xbf, + 0xd1, 0xd5, 0x42, 0x7d, 0x06, 0xfb, 0x25, 0x64, 0xb8, 0x9d, 0x11, 0x0b +}; +static const uint8_t nist_186_2_ecdsa_testvector_142_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x08, 0xc7, 0x0b, 0x99, 0x35, 0xb3, 0x6e, 0xb4, 0x07, 0x60, 0x16, + 0x8e, 0x67, 0xae, 0x5a, 0x25, 0x06, 0x76, 0x32, 0xcd, 0xce, 0xc5, 0x87, + 0x75, 0x8a, 0x62, 0x66, 0x43, 0xbd, 0x9b, 0xca, 0x16, 0x67, 0x06, 0x95, + 0xe0, 0xbc, 0x79, 0x2a, 0x9b, 0x1e, 0x32, 0xc5, 0x01, 0xbb, 0xf6, 0xc7, + 0x19, 0x0f, 0x98, 0xc3, 0x3e, 0xdd, 0x68, 0x45, 0xd6, 0xfb, 0x55, 0x2f, + 0x31, 0x4c, 0x13, 0x60, 0x59, 0x97, 0x0a, 0xf7, 0xe6, 0xc6, 0xe6, 0x01 +}; +/* k = 0d8acc4a715cdf8aeaed8d4fafd06459f4d4d88a0a7f66f59319ad2402ba250f8fc7da47ff2215fd6f59783344f900e1615d9c3e287623a5534afaa1f9cd1dd96bbbca443477be4 */ +static const uint8_t nist_186_2_ecdsa_testvector_142_out[] = { +/* R - byte alignment */ + 0x00, 0x33, 0xfa, 0xd5, 0xd3, 0x5e, 0x11, 0x35, 0x3a, 0xf1, 0x88, 0x11, + 0xa1, 0xe7, 0x8d, 0xd8, 0xd0, 0xe6, 0xd4, 0xbd, 0xd9, 0xf3, 0xe5, 0xc2, + 0x99, 0xfa, 0x48, 0x0e, 0x0b, 0x8f, 0x41, 0xfb, 0x5a, 0x38, 0xa7, 0x0d, + 0x0e, 0x7a, 0x07, 0x38, 0xaa, 0xde, 0xe8, 0xed, 0xdc, 0x06, 0x98, 0xfd, + 0x8b, 0x7d, 0x33, 0x31, 0x14, 0x08, 0xf5, 0xfe, 0xc2, 0x2a, 0x45, 0x69, + 0x53, 0x08, 0xa2, 0xb6, 0x04, 0x62, 0xe4, 0x94, 0xb3, 0x56, 0xe0, 0x65, +/* S - byte alignment */ + 0x01, 0xdb, 0x16, 0xa2, 0xf2, 0x25, 0xfb, 0xc4, 0xd4, 0x01, 0xe9, 0x81, + 0x76, 0x6e, 0x69, 0x1e, 0x69, 0x47, 0x76, 0xcb, 0xf2, 0x21, 0xc3, 0x2f, + 0x4c, 0x1f, 0xf2, 0xee, 0xc6, 0xf4, 0xd9, 0xd5, 0x50, 0xb5, 0x7f, 0xe1, + 0xe7, 0x08, 0xcf, 0x4c, 0x48, 0x0f, 0xe4, 0xa2, 0xf4, 0x51, 0xe0, 0xa0, + 0xc3, 0x90, 0x52, 0xfb, 0xc5, 0x89, 0x51, 0xa5, 0x76, 0x0c, 0x55, 0x78, + 0xaa, 0x22, 0x01, 0x4e, 0xba, 0x22, 0x47, 0xd9, 0x52, 0x92, 0x04, 0xc8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_143_ptx[] = { +/* Msg */ + 0xd0, 0x0d, 0x1c, 0x0f, 0x85, 0x28, 0x5b, 0xda, 0xc9, 0xa7, 0x40, 0x4d, + 0x4e, 0xc4, 0x25, 0x29, 0x5a, 0xfa, 0xab, 0x59, 0xc1, 0x25, 0x51, 0x32, + 0x11, 0xe5, 0x46, 0xf9, 0x0c, 0x43, 0x7c, 0xa5, 0x5b, 0x97, 0xfe, 0xe7, + 0x80, 0xa9, 0x83, 0x68, 0x0d, 0x16, 0x43, 0x52, 0x13, 0xf5, 0x09, 0x11, + 0xde, 0xbb, 0x8a, 0x5b, 0xdf, 0x5c, 0xf5, 0x6d, 0xea, 0xb3, 0xcb, 0x98, + 0xa2, 0x24, 0xf1, 0xfd, 0x31, 0x80, 0x04, 0x95, 0x3c, 0x28, 0xec, 0x74, + 0x15, 0x76, 0xb4, 0x4e, 0x33, 0x58, 0x98, 0x3a, 0xe0, 0x3e, 0x60, 0xb6, + 0x32, 0x37, 0xed, 0xeb, 0x3c, 0x56, 0x12, 0x33, 0x85, 0x5b, 0xa5, 0xd9, + 0xba, 0x8f, 0xd5, 0x20, 0x9f, 0xf0, 0xbd, 0x86, 0x4b, 0x8e, 0x3a, 0x49, + 0x95, 0x35, 0xfa, 0x2b, 0xca, 0x4c, 0xd6, 0x72, 0xa1, 0xfd, 0x62, 0x34, + 0x70, 0x97, 0xc2, 0xd1, 0x9f, 0x30, 0xbf, 0xc1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_143_private[] = { +/* d - byte alignment */ + 0x00, 0xfd, 0xbf, 0x5b, 0x8e, 0xc9, 0x97, 0xdc, 0x35, 0x30, 0xe5, 0xdb, + 0x8b, 0x43, 0x18, 0xb0, 0x8b, 0x5b, 0xe2, 0xc7, 0x63, 0x82, 0x2b, 0x0a, + 0xe3, 0x1e, 0x45, 0x6f, 0x76, 0xad, 0xa1, 0xde, 0x4e, 0x1b, 0xc5, 0x2f, + 0xbc, 0x9a, 0x2c, 0x8b, 0xa3, 0x54, 0x46, 0x7b, 0x09, 0xca, 0xd6, 0xec, + 0x28, 0x18, 0x08, 0x10, 0x52, 0xd7, 0xa9, 0x4e, 0x48, 0x1f, 0xb8, 0xd1, + 0x03, 0xc6, 0x55, 0x8c, 0xaa, 0x5d, 0x9d, 0x07, 0x62, 0xf0, 0xe5, 0xd6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_143_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x57, 0x13, 0x80, 0x19, 0xcd, 0x1f, 0xc5, 0x0c, 0xb6, 0x99, 0x6b, + 0xdb, 0x4d, 0xe7, 0x33, 0x2a, 0x95, 0xb4, 0x34, 0x46, 0x83, 0x87, 0xcb, + 0x1a, 0xcc, 0x82, 0xec, 0x7b, 0x8f, 0x25, 0xd9, 0xee, 0xa7, 0xf0, 0x48, + 0x4f, 0x26, 0x32, 0x0e, 0x9c, 0x32, 0x16, 0xf0, 0x89, 0xce, 0x5b, 0xfc, + 0xbf, 0x0a, 0xb5, 0xd2, 0x77, 0xe3, 0xc4, 0xd2, 0xd5, 0xbf, 0x04, 0xa7, + 0x69, 0x5b, 0xab, 0x50, 0x4e, 0x28, 0xc2, 0xe8, 0x2d, 0x21, 0x93, 0x37 +}; +static const uint8_t nist_186_2_ecdsa_testvector_143_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x60, 0xec, 0x1b, 0x48, 0x8a, 0x47, 0x8a, 0x19, 0xf3, 0x33, 0x8b, + 0xfb, 0x91, 0x38, 0xe7, 0xb8, 0x7f, 0x67, 0xfb, 0x7e, 0xf8, 0xb1, 0xa0, + 0xeb, 0x26, 0x78, 0x46, 0x2a, 0xf5, 0x90, 0xc5, 0xa2, 0xc9, 0x00, 0xa1, + 0xbb, 0x3c, 0xaf, 0xfb, 0x30, 0xff, 0x80, 0x3e, 0x04, 0xff, 0x26, 0x7c, + 0x97, 0x1f, 0x05, 0xd4, 0x81, 0xd4, 0x20, 0x0c, 0x6e, 0xe8, 0x9d, 0x8c, + 0x20, 0x5c, 0xa8, 0xa6, 0xe1, 0x3b, 0x47, 0x28, 0xbc, 0x23, 0xc5, 0xe8 +}; +/* k = 00795bb246effbdd1cf8e9ef2313851f9d0ebfcf1b8d78b7026960559e675f0435dff97e7d6cfa33951a12f63c4b6aebe4fe8f32e32af170f27547a92d670405b9764aae85029d8 */ +static const uint8_t nist_186_2_ecdsa_testvector_143_out[] = { +/* R - byte alignment */ + 0x01, 0xbc, 0xc7, 0x85, 0x3b, 0xa5, 0x34, 0x83, 0x5b, 0xbb, 0x2e, 0x41, + 0xb3, 0xa8, 0x92, 0x70, 0xba, 0xac, 0xd7, 0x3f, 0x9c, 0xf1, 0x0d, 0x58, + 0x41, 0x57, 0xee, 0xcf, 0xa7, 0x3a, 0xe6, 0x76, 0x82, 0x94, 0x99, 0x16, + 0x6e, 0x34, 0x69, 0x19, 0x8e, 0xc3, 0x86, 0xfd, 0x55, 0x73, 0x85, 0xfd, + 0x9b, 0x93, 0xf8, 0x0a, 0xdb, 0xde, 0x19, 0x3c, 0x4f, 0x20, 0x73, 0x5c, + 0x7b, 0x4d, 0xe7, 0xe2, 0xac, 0x44, 0x84, 0x14, 0x81, 0xf9, 0xad, 0x2e, +/* S - byte alignment */ + 0x00, 0x6f, 0xae, 0xc4, 0xdf, 0xd4, 0x07, 0x81, 0xb8, 0xba, 0x3b, 0x66, + 0x94, 0x3b, 0x72, 0xe4, 0x6e, 0x50, 0x20, 0x57, 0xd0, 0x5e, 0xda, 0xbc, + 0x3f, 0xfe, 0xa9, 0x35, 0x1e, 0xfc, 0xe6, 0xde, 0xd2, 0x65, 0x0f, 0x96, + 0xeb, 0xf0, 0xd5, 0x86, 0x7f, 0x3a, 0xcd, 0x38, 0xc3, 0x43, 0xb2, 0x80, + 0x4b, 0x36, 0xbc, 0xbb, 0x8c, 0x1c, 0x69, 0x63, 0x16, 0x4d, 0x38, 0xec, + 0x9a, 0x61, 0x88, 0x71, 0x09, 0x24, 0x63, 0xbd, 0x4b, 0x84, 0x42, 0x63 +}; +static const uint8_t nist_186_2_ecdsa_testvector_144_ptx[] = { +/* Msg */ + 0xda, 0xde, 0xab, 0xe7, 0xb8, 0x6a, 0xd4, 0x42, 0x63, 0x74, 0xd4, 0x26, + 0x4b, 0x3b, 0x40, 0xe2, 0x55, 0xa2, 0xbc, 0x9d, 0xdc, 0x28, 0x1b, 0xea, + 0xf6, 0x1a, 0xc8, 0x9d, 0xf8, 0x08, 0x64, 0xdc, 0x3c, 0x75, 0xb0, 0x79, + 0x21, 0xd2, 0xae, 0x7f, 0x54, 0xae, 0x03, 0x0a, 0x4e, 0x27, 0xa0, 0x5c, + 0x1e, 0xa4, 0xa1, 0x2e, 0x69, 0xc6, 0x75, 0x44, 0xaf, 0x9b, 0x40, 0x44, + 0xcf, 0x15, 0x7d, 0xc8, 0xce, 0xbb, 0xe8, 0xb2, 0xd4, 0x9f, 0x9b, 0xc0, + 0x77, 0x90, 0x77, 0x60, 0x3c, 0x90, 0xc5, 0xc5, 0x5b, 0x89, 0x1d, 0x3a, + 0xc3, 0x3b, 0x87, 0xb6, 0x5e, 0x79, 0xe1, 0xb1, 0x96, 0x95, 0x81, 0x37, + 0x18, 0x19, 0x1b, 0x3b, 0xd8, 0xb7, 0xe4, 0x2d, 0x55, 0x83, 0xf7, 0xcf, + 0x1e, 0x60, 0xf8, 0x44, 0x95, 0xb8, 0xf8, 0x69, 0xf3, 0x71, 0x99, 0x69, + 0x8c, 0x1c, 0x73, 0x8c, 0x55, 0x6f, 0xb6, 0x50 +}; +static const uint8_t nist_186_2_ecdsa_testvector_144_private[] = { +/* d - byte alignment */ + 0x00, 0x4a, 0xfe, 0x51, 0x29, 0x80, 0x6d, 0x0a, 0xb6, 0xb8, 0x8d, 0x86, + 0x0b, 0x71, 0xd9, 0x8a, 0x00, 0xf1, 0x0d, 0x5a, 0x79, 0x5b, 0x35, 0xd0, + 0x98, 0x7b, 0x7c, 0x97, 0xf8, 0xbb, 0x9c, 0x2f, 0x2e, 0x8c, 0x53, 0x8c, + 0x72, 0x44, 0x36, 0xab, 0xf6, 0x66, 0x47, 0xfa, 0x90, 0xbc, 0x01, 0xff, + 0xe3, 0xa8, 0x7f, 0xbd, 0xa1, 0xe6, 0x8f, 0x71, 0x71, 0xf7, 0x6e, 0xe6, + 0x64, 0x01, 0x4f, 0x33, 0x0c, 0x4d, 0x4a, 0x28, 0xf9, 0x37, 0x20, 0xba +}; +static const uint8_t nist_186_2_ecdsa_testvector_144_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x9b, 0x36, 0xab, 0x8f, 0xcb, 0x8c, 0x9d, 0x6e, 0xe8, 0xa6, 0x39, + 0x2c, 0xa1, 0x90, 0x09, 0xd4, 0xfe, 0xb9, 0x02, 0xdb, 0xbd, 0xf9, 0x4b, + 0xb9, 0xd0, 0x69, 0x15, 0x2e, 0xb5, 0xb6, 0x7f, 0x41, 0xa4, 0x97, 0x23, + 0xe3, 0xc4, 0xdf, 0xd8, 0xce, 0x77, 0xb5, 0xd0, 0x91, 0x9b, 0xea, 0x8b, + 0x26, 0x81, 0xf7, 0x48, 0xe8, 0x04, 0xbd, 0xd1, 0x11, 0x1b, 0x7c, 0xae, + 0xc3, 0x02, 0x73, 0xde, 0x28, 0xba, 0x47, 0x62, 0xe9, 0x7f, 0x56, 0x0d +}; +static const uint8_t nist_186_2_ecdsa_testvector_144_public_y[] = { +/* Qy - byte alignment */ + 0x07, 0x87, 0x8e, 0x31, 0x10, 0xe4, 0x96, 0x3a, 0xab, 0x77, 0xde, 0x8d, + 0xb2, 0x04, 0xde, 0xfe, 0x4e, 0xaa, 0x6b, 0xe6, 0x16, 0x95, 0x0e, 0x67, + 0x80, 0xc2, 0x3d, 0x1b, 0x88, 0x88, 0xc1, 0xac, 0x22, 0x82, 0xd3, 0x80, + 0x45, 0xcc, 0x4d, 0xdd, 0x0e, 0xa8, 0x41, 0xdf, 0x48, 0x44, 0xf8, 0x75, + 0x16, 0xd0, 0x4b, 0x1d, 0x2e, 0x99, 0x4f, 0x12, 0xf6, 0xe9, 0xe0, 0xc0, + 0xa6, 0xbb, 0x64, 0x0a, 0xf7, 0x4e, 0xb4, 0xa6, 0xb4, 0x05, 0x45, 0x86 +}; +/* k = 03d86bdadcb891157e3fe27b57adf717388fcad072c32ba8a8e90c3c2f9410b61ec376f9512eb1a190a34c4ac7fbfbcce77e4cdf4bf31aa2577b1a8a7c3d0505e926a21c4a10253 */ +static const uint8_t nist_186_2_ecdsa_testvector_144_out[] = { +/* R - byte alignment */ + 0x00, 0xa9, 0x4e, 0xaa, 0x42, 0xdb, 0x67, 0xd1, 0x3a, 0xa3, 0x76, 0xcf, + 0x0c, 0xed, 0x26, 0x01, 0x9c, 0x04, 0x90, 0xa6, 0x2c, 0x09, 0x28, 0xbf, + 0x8f, 0xfe, 0x56, 0xc7, 0x25, 0x1b, 0xab, 0xd3, 0x77, 0x6f, 0x04, 0x35, + 0xa5, 0xf9, 0x94, 0x4b, 0xca, 0xea, 0x78, 0x48, 0xd5, 0x51, 0xd6, 0x20, + 0x19, 0x81, 0xa1, 0x82, 0x53, 0x40, 0x7e, 0x18, 0x76, 0x18, 0x1e, 0xa3, + 0x40, 0x06, 0xc7, 0xe0, 0x0e, 0x1a, 0x0b, 0x64, 0xf2, 0x0a, 0x8b, 0x96, +/* S - byte alignment */ + 0x00, 0x96, 0xe9, 0x8e, 0xcb, 0x15, 0x68, 0xcc, 0x09, 0x1e, 0x22, 0x7e, + 0x46, 0xb6, 0xc0, 0x13, 0xf7, 0xf2, 0x0a, 0x22, 0xae, 0x10, 0x78, 0x20, + 0xad, 0x9b, 0xc4, 0xf4, 0x81, 0x0e, 0x90, 0x06, 0x2a, 0xb6, 0xb3, 0xb0, + 0x26, 0x0e, 0x39, 0xf8, 0xb8, 0x07, 0xeb, 0xd3, 0xd0, 0xb2, 0x86, 0xe7, + 0x18, 0x7e, 0xd9, 0x84, 0x73, 0x20, 0x59, 0xe3, 0xf9, 0xc2, 0xb8, 0x49, + 0x06, 0xd7, 0x46, 0x11, 0x97, 0x5d, 0x6e, 0xbc, 0x41, 0x25, 0xf6, 0x86 +}; +static const uint8_t nist_186_2_ecdsa_testvector_145_ptx[] = { +/* Msg */ + 0x7c, 0x86, 0xb7, 0xa4, 0x12, 0x18, 0x47, 0x65, 0xb7, 0xad, 0x39, 0xba, + 0x77, 0x73, 0x16, 0xda, 0x3b, 0xfd, 0x34, 0x8b, 0x40, 0xe6, 0xd2, 0xe7, + 0xc8, 0xb7, 0x64, 0x60, 0x10, 0x0a, 0x2c, 0x02, 0x81, 0xf0, 0x0a, 0xf8, + 0x2a, 0x91, 0x95, 0x52, 0x6e, 0x12, 0x6a, 0x05, 0xfa, 0xbc, 0xc5, 0x33, + 0xfb, 0x5a, 0x4e, 0xad, 0x8d, 0xe2, 0x35, 0xb7, 0x76, 0x58, 0x80, 0x0b, + 0x14, 0xf0, 0xa4, 0x20, 0x94, 0x73, 0x53, 0xab, 0x65, 0xe3, 0x96, 0x67, + 0xec, 0x62, 0x1b, 0x11, 0x7a, 0x50, 0xd0, 0xb7, 0x7b, 0xb4, 0xb1, 0x33, + 0xf0, 0xdd, 0xdd, 0xf3, 0x1f, 0x49, 0xf0, 0xfb, 0x88, 0xc5, 0x8d, 0x2c, + 0x1c, 0xd6, 0x3a, 0xc6, 0xaa, 0x58, 0x71, 0x2c, 0x9a, 0x65, 0xf3, 0xe7, + 0xdd, 0x78, 0x60, 0xee, 0x24, 0xd2, 0x05, 0x24, 0x50, 0x1d, 0xf5, 0x23, + 0x2a, 0x50, 0x5b, 0x38, 0x55, 0xd2, 0x0e, 0xae +}; +static const uint8_t nist_186_2_ecdsa_testvector_145_private[] = { +/* d - byte alignment */ + 0x00, 0x6a, 0x46, 0xb7, 0x27, 0xb6, 0x4f, 0x68, 0x81, 0x0c, 0x10, 0x3b, + 0x8e, 0x9d, 0x33, 0xa0, 0x16, 0x8e, 0xad, 0xd2, 0xca, 0x6d, 0xc8, 0xb8, + 0x08, 0x0f, 0xa0, 0x5a, 0x05, 0x23, 0x33, 0xc0, 0xb5, 0x67, 0xd2, 0x26, + 0xc7, 0x20, 0xd4, 0xea, 0x5a, 0x90, 0x40, 0xf2, 0x46, 0x7f, 0xd9, 0x3a, + 0xdf, 0x0b, 0x43, 0xd5, 0xdc, 0x0a, 0x77, 0x0a, 0x66, 0xf8, 0x6c, 0x29, + 0x7d, 0x35, 0xdf, 0x29, 0xc4, 0x42, 0x60, 0xfe, 0x1b, 0x17, 0xe4, 0x49 +}; +static const uint8_t nist_186_2_ecdsa_testvector_145_public_x[] = { +/* Qx - byte alignment */ + 0x02, 0xad, 0x7e, 0xe2, 0xda, 0x9e, 0x6d, 0x28, 0xd5, 0xc2, 0x60, 0x5e, + 0x9d, 0x95, 0xf6, 0x74, 0x97, 0x17, 0x90, 0x92, 0x35, 0x0d, 0x4b, 0xe4, + 0x44, 0x1b, 0x08, 0x93, 0x26, 0x3e, 0xa7, 0x08, 0x91, 0x79, 0xbe, 0x06, + 0x08, 0xe6, 0x44, 0x93, 0xde, 0xb7, 0xc6, 0x50, 0x84, 0x2e, 0xa3, 0x81, + 0x3e, 0x70, 0xa9, 0x10, 0xad, 0x3d, 0x2b, 0x78, 0x56, 0xa5, 0xb5, 0x89, + 0x25, 0x0a, 0x99, 0x75, 0x9c, 0x6f, 0xa8, 0xe5, 0xd4, 0xff, 0x3a, 0xc1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_145_public_y[] = { +/* Qy - byte alignment */ + 0x03, 0x16, 0xa6, 0x04, 0x01, 0x9d, 0xf5, 0x55, 0x27, 0x89, 0x6c, 0x79, + 0xb7, 0xdf, 0xc0, 0xe2, 0x38, 0x78, 0xe1, 0x8b, 0x6f, 0xf1, 0x80, 0x3f, + 0xe8, 0x5d, 0xc4, 0x3f, 0x42, 0xc7, 0xfc, 0xe8, 0x02, 0x8d, 0xa8, 0x8a, + 0xc5, 0x5b, 0x61, 0x38, 0x07, 0xb3, 0x13, 0x95, 0x5f, 0x29, 0xe7, 0x2b, + 0x16, 0xed, 0xba, 0x7c, 0xc3, 0xdb, 0xfc, 0x3c, 0x24, 0xf1, 0x55, 0x98, + 0xc9, 0x16, 0x10, 0x1f, 0x1e, 0x32, 0x01, 0x0b, 0xd6, 0x16, 0xc9, 0xc0 +}; +/* k = 0403d95f88d2713cc6ed6b6fb96562d4406a8dc54290d943ab01cfb9a548f5e47246a33ee995d2a9878bba141dcf0aa22382f6bd41173862bf698315750081d15b4d6024fd05792 */ +static const uint8_t nist_186_2_ecdsa_testvector_145_out[] = { +/* R - byte alignment */ + 0x01, 0xc5, 0x63, 0x2f, 0xa6, 0x52, 0x90, 0xf1, 0x55, 0x6e, 0x4e, 0x9b, + 0x20, 0x02, 0xb8, 0x02, 0x87, 0x82, 0xcc, 0x9e, 0x3e, 0x92, 0x18, 0xff, + 0x59, 0xb2, 0x52, 0xce, 0x6f, 0xe7, 0xe9, 0x11, 0x4c, 0x79, 0x9a, 0x6e, + 0x72, 0xca, 0xcc, 0x1b, 0x54, 0xe7, 0xe7, 0xe2, 0x94, 0xee, 0x32, 0x39, + 0x6a, 0x2b, 0x49, 0xe2, 0x87, 0x89, 0xe7, 0xbb, 0x5a, 0xe8, 0x49, 0x2f, + 0x49, 0x5f, 0x7f, 0x2c, 0x8c, 0x01, 0xcd, 0x51, 0xe3, 0x23, 0x08, 0xe4, +/* S - byte alignment */ + 0x00, 0x32, 0xbc, 0x1c, 0x37, 0x3a, 0x54, 0x14, 0x96, 0x86, 0x42, 0x27, + 0x7b, 0xf9, 0x66, 0x1f, 0x7f, 0x2e, 0x1f, 0x2e, 0x26, 0xc9, 0xa1, 0x57, + 0x2b, 0x2a, 0x00, 0xbb, 0x8a, 0x9e, 0x93, 0x68, 0x81, 0x49, 0x7d, 0x8c, + 0xb4, 0x50, 0x0a, 0xf3, 0xfe, 0xda, 0xe9, 0x53, 0xdc, 0x44, 0x5c, 0x84, + 0xe0, 0x62, 0x74, 0xa3, 0xe4, 0x2d, 0x78, 0x46, 0xfd, 0xb7, 0x62, 0xb1, + 0x85, 0xa1, 0x5e, 0xc9, 0x69, 0xa5, 0xb2, 0xf1, 0xe9, 0xfe, 0x68, 0x83 +}; +static const uint8_t nist_186_2_ecdsa_testvector_146_ptx[] = { +/* Msg */ + 0x2b, 0xab, 0xf4, 0x2f, 0xe8, 0x6c, 0x04, 0x3e, 0x40, 0x1f, 0xff, 0x55, + 0x21, 0x46, 0x6a, 0xb5, 0x5d, 0xbe, 0xbf, 0xc0, 0x5b, 0xa1, 0xc0, 0x02, + 0x0d, 0x6a, 0x0a, 0x6f, 0x21, 0x5a, 0xed, 0xeb, 0x7c, 0x1b, 0x7b, 0x10, + 0xe4, 0xa4, 0xdf, 0x2b, 0xfc, 0x5c, 0xf1, 0x87, 0x76, 0x82, 0x07, 0xef, + 0x84, 0xcc, 0x0d, 0x6e, 0x8f, 0x4e, 0xd8, 0x59, 0x2c, 0x9e, 0xb7, 0x8f, + 0x4c, 0x36, 0x4b, 0x00, 0xb2, 0x19, 0x99, 0x6c, 0xab, 0xba, 0x5e, 0x6d, + 0xf9, 0x19, 0xa2, 0xb8, 0x10, 0x2f, 0x90, 0xa0, 0x85, 0x8c, 0x85, 0xdc, + 0xc3, 0x3f, 0x67, 0x89, 0x00, 0xf6, 0x38, 0x73, 0x6f, 0x66, 0xeb, 0x90, + 0xb7, 0xed, 0x76, 0xcd, 0xa5, 0x76, 0x28, 0x0d, 0x1d, 0x9e, 0x3d, 0x6f, + 0x57, 0x15, 0xb0, 0xd0, 0x48, 0x46, 0x50, 0x92, 0x5d, 0x3a, 0x16, 0x9b, + 0x6f, 0xb9, 0xb6, 0xa0, 0xf4, 0xb3, 0x74, 0xa3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_146_private[] = { +/* d - byte alignment */ + 0x00, 0x31, 0x43, 0x90, 0xd2, 0x1e, 0xf2, 0x41, 0x32, 0x8c, 0xc0, 0xe1, + 0xf6, 0x27, 0xe2, 0xde, 0x01, 0xcd, 0x3c, 0x64, 0x45, 0x7e, 0xc0, 0xe0, + 0x11, 0x3b, 0xbf, 0xdd, 0x05, 0x5f, 0x84, 0x75, 0x55, 0xbc, 0xe1, 0xde, + 0x8a, 0x5b, 0x15, 0xa1, 0x15, 0x78, 0x57, 0xb6, 0x1d, 0x85, 0x97, 0xc1, + 0xe9, 0x78, 0xfe, 0xdc, 0xa4, 0x5a, 0x99, 0xf2, 0x81, 0x33, 0x24, 0x42, + 0xf4, 0x4a, 0x1e, 0x68, 0xfc, 0x3a, 0x05, 0x09, 0xc4, 0x95, 0x79, 0x4b +}; +static const uint8_t nist_186_2_ecdsa_testvector_146_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0x78, 0xbd, 0x75, 0xdf, 0xa0, 0xbc, 0x87, 0x4f, 0x88, 0xc6, 0x79, + 0x9b, 0x59, 0x86, 0xe1, 0x80, 0xa4, 0x81, 0xd3, 0xc3, 0x84, 0xa8, 0x10, + 0xef, 0x43, 0xbc, 0x7e, 0x8c, 0x0e, 0x07, 0x89, 0x94, 0x30, 0x89, 0x4a, + 0xe6, 0x87, 0x72, 0x2d, 0x7f, 0x06, 0x7c, 0x83, 0x31, 0xc2, 0xd9, 0x7d, + 0x31, 0xd5, 0x58, 0x97, 0xd3, 0xa3, 0xa9, 0xf6, 0x6d, 0xf1, 0xa3, 0xbe, + 0x25, 0xa8, 0x0e, 0x49, 0x0e, 0xe0, 0x79, 0x24, 0xf2, 0x3b, 0x56, 0x23 +}; +static const uint8_t nist_186_2_ecdsa_testvector_146_public_y[] = { +/* Qy - byte alignment */ + 0x07, 0x61, 0xac, 0x3b, 0xee, 0xc4, 0xe0, 0xb2, 0x38, 0xc2, 0x66, 0xb0, + 0x57, 0x23, 0xe1, 0x98, 0x3e, 0x24, 0x67, 0x70, 0x9e, 0x9f, 0xed, 0x61, + 0xc1, 0x31, 0xfc, 0x1e, 0xab, 0xcd, 0x8f, 0x43, 0x1f, 0x62, 0x77, 0x5c, + 0x5c, 0xc2, 0xd4, 0x5c, 0xac, 0x83, 0xd0, 0x00, 0x3c, 0x9a, 0xd6, 0xc3, + 0x95, 0x3a, 0x18, 0x9d, 0x13, 0xd9, 0xf6, 0x42, 0xf6, 0x56, 0x52, 0x06, + 0x30, 0x89, 0xf1, 0xf2, 0xec, 0x57, 0x43, 0x85, 0xce, 0x33, 0x3b, 0x0e +}; +/* k = 1c562493602d5a35eb6e7ebbf821c8aa021f0125f845f32f33fc8fac1955cbd8f6ecd370fe8e0a405248d00de47c0d596d90c796dbecd13c2edc9fadc28b98f07e9e2f288a745b2 */ +static const uint8_t nist_186_2_ecdsa_testvector_146_out[] = { +/* R - byte alignment */ + 0x00, 0x48, 0xf2, 0x80, 0x47, 0x8d, 0xe4, 0xec, 0x2d, 0xfd, 0x9a, 0x15, + 0x10, 0x02, 0x2b, 0xfe, 0x97, 0xe9, 0xe1, 0xe8, 0x3e, 0x0a, 0xef, 0x24, + 0xa4, 0xfe, 0x08, 0x70, 0x06, 0xca, 0x27, 0xec, 0x28, 0xf2, 0x72, 0x23, + 0x7a, 0xe3, 0x75, 0x05, 0x72, 0x27, 0xbc, 0xb5, 0x41, 0x72, 0x24, 0xa3, + 0xff, 0xc2, 0x9a, 0x26, 0xfe, 0xb5, 0x07, 0xea, 0xc4, 0x19, 0xdc, 0x8d, + 0x69, 0x32, 0x7a, 0x97, 0xae, 0xc2, 0xfd, 0xea, 0x80, 0x7e, 0xbc, 0x08, +/* S - byte alignment */ + 0x00, 0x5a, 0xd5, 0xbb, 0xfa, 0xf9, 0xc5, 0x33, 0x2b, 0xd9, 0xa4, 0x45, + 0xd5, 0x8c, 0xa0, 0xcc, 0xeb, 0x55, 0x91, 0xc2, 0x84, 0x41, 0xca, 0xe9, + 0xe6, 0xab, 0xd6, 0x68, 0x1b, 0xcb, 0x48, 0x45, 0xc3, 0xb2, 0xc9, 0xd6, + 0x3c, 0xc1, 0x58, 0xcd, 0x24, 0x85, 0xc1, 0xd8, 0x78, 0xf0, 0x4f, 0xbd, + 0x64, 0x9a, 0xd9, 0x6f, 0x06, 0x3c, 0x6a, 0x9e, 0xe8, 0xa4, 0xa9, 0xed, + 0x56, 0x21, 0x12, 0xd4, 0x81, 0x3d, 0xe8, 0x36, 0xf5, 0xe6, 0xdc, 0x24 +}; +static const uint8_t nist_186_2_ecdsa_testvector_147_ptx[] = { +/* Msg */ + 0xc4, 0xe1, 0xd8, 0x3d, 0xa0, 0x6f, 0x0e, 0x3b, 0x05, 0x64, 0x00, 0x32, + 0xf8, 0x46, 0x6b, 0xfd, 0xb6, 0xeb, 0x1f, 0x39, 0x3d, 0xea, 0xa7, 0x54, + 0x0e, 0x4f, 0x2c, 0xe6, 0x32, 0x93, 0x97, 0x45, 0x7b, 0xcb, 0xf6, 0x54, + 0x0c, 0x1f, 0x21, 0x9b, 0x1b, 0x7e, 0x9d, 0x9d, 0xf6, 0x90, 0xc0, 0x65, + 0x44, 0xec, 0x16, 0x63, 0x8e, 0x8c, 0x04, 0x76, 0xfe, 0x7d, 0xab, 0x4a, + 0x66, 0xdb, 0x0f, 0xe4, 0x83, 0xfd, 0x79, 0x7b, 0x84, 0xed, 0x1a, 0x8a, + 0xc6, 0x1b, 0xf0, 0x23, 0xe2, 0x52, 0xee, 0x86, 0xe9, 0xea, 0x57, 0xf2, + 0xee, 0x40, 0x6b, 0xbb, 0xc5, 0x63, 0x45, 0x9d, 0x0b, 0x10, 0x04, 0x50, + 0x66, 0xe1, 0x29, 0x5c, 0x0e, 0xc1, 0x40, 0x2f, 0x8d, 0xa3, 0xc3, 0x6d, + 0xc3, 0x74, 0x3b, 0x87, 0x2c, 0x4d, 0xa8, 0x8f, 0x66, 0xee, 0x23, 0x4b, + 0xed, 0x68, 0xc2, 0x88, 0x2a, 0x19, 0xbc, 0xb0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_147_private[] = { +/* d - byte alignment */ + 0x00, 0x5f, 0x3f, 0x6c, 0x0a, 0x13, 0xa2, 0x11, 0x23, 0x85, 0x4a, 0x6f, + 0xfa, 0x49, 0xf1, 0x5a, 0x3f, 0x06, 0x35, 0x2a, 0xfe, 0x9b, 0x85, 0xf4, + 0xae, 0xc4, 0x0d, 0x8b, 0x22, 0x4c, 0x78, 0x54, 0xc5, 0x06, 0x3e, 0xa1, + 0xe1, 0xe6, 0x72, 0x52, 0xc1, 0x63, 0x43, 0x86, 0x8d, 0xdf, 0x2a, 0xb3, + 0xd1, 0xc9, 0xc1, 0x03, 0x78, 0x8e, 0x72, 0xe7, 0xab, 0x73, 0x63, 0x81, + 0x60, 0x3b, 0xb9, 0xf7, 0xf9, 0x1e, 0x2b, 0xcb, 0x26, 0xc3, 0xe2, 0x03 +}; +static const uint8_t nist_186_2_ecdsa_testvector_147_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0xf9, 0xa3, 0x87, 0x0b, 0x2a, 0x26, 0x2e, 0xdd, 0x5c, 0x03, 0x5e, + 0x4e, 0xb2, 0x58, 0x1f, 0x70, 0x58, 0x9d, 0xdd, 0x0d, 0x20, 0x97, 0xe7, + 0xfa, 0x62, 0xd7, 0x27, 0xd0, 0xd2, 0x66, 0x97, 0x45, 0x7a, 0xf6, 0x8e, + 0x27, 0x3e, 0x92, 0x71, 0xe2, 0x80, 0xdc, 0x09, 0x2c, 0x08, 0x11, 0x6b, + 0xc8, 0x3a, 0x88, 0x09, 0x94, 0x1a, 0xdc, 0x89, 0xe7, 0x8b, 0x6e, 0xa1, + 0x40, 0x1d, 0xd7, 0x06, 0xe5, 0x95, 0xfd, 0xa0, 0xdd, 0xec, 0xa6, 0xcf +}; +static const uint8_t nist_186_2_ecdsa_testvector_147_public_y[] = { +/* Qy - byte alignment */ + 0x03, 0xab, 0xbb, 0x91, 0xd7, 0x38, 0x20, 0xed, 0x69, 0x0f, 0x90, 0x94, + 0x05, 0x9f, 0x90, 0xcf, 0x66, 0x9c, 0x69, 0x91, 0x05, 0x0c, 0xd4, 0x9b, + 0x09, 0x12, 0x1e, 0x87, 0x6e, 0x33, 0x10, 0x57, 0x2b, 0xdf, 0xd6, 0x77, + 0xab, 0x7f, 0x96, 0x2c, 0x69, 0x2a, 0xb2, 0xda, 0x1f, 0xc2, 0x1f, 0xfc, + 0xa4, 0x68, 0xe9, 0x15, 0xbd, 0x44, 0x85, 0x37, 0xe0, 0xee, 0xe1, 0x24, + 0x11, 0x90, 0x18, 0x77, 0x08, 0xab, 0x71, 0xf6, 0x59, 0xcd, 0xe6, 0x17 +}; +/* k = 0e3f1ea1fd26217e314d8bb1bb06930fc4f98039a4067aa5bfa9825d706e9ce89354d2a215298e003b227eb7defa5c3cefc8f5696135e7373c6d278f17eaee4d0b9bd9eddcc75ea */ +static const uint8_t nist_186_2_ecdsa_testvector_147_out[] = { +/* R - byte alignment */ + 0x00, 0xd1, 0x61, 0x48, 0x13, 0x0f, 0xde, 0xfb, 0x6c, 0x2b, 0x6c, 0xb3, + 0x05, 0xea, 0x8c, 0x58, 0x6f, 0x7c, 0x5e, 0x9c, 0x06, 0xcb, 0xed, 0xe1, + 0x34, 0x50, 0xde, 0x7b, 0xe7, 0xbd, 0xf2, 0xaa, 0x18, 0x22, 0xcf, 0x10, + 0x91, 0x86, 0xde, 0x3b, 0xf1, 0x14, 0xc2, 0x74, 0xca, 0x3a, 0x05, 0x66, + 0x2b, 0x56, 0xb9, 0x78, 0x30, 0x46, 0x45, 0x7e, 0xae, 0x64, 0x5c, 0x14, + 0xdc, 0x72, 0x2e, 0x36, 0xd7, 0x7e, 0x62, 0x89, 0x64, 0xd5, 0x2f, 0xbc, +/* S - byte alignment */ + 0x01, 0x9d, 0xed, 0x7e, 0xd1, 0xa6, 0x12, 0xa2, 0xe6, 0x53, 0x60, 0xd6, + 0x15, 0x19, 0xf9, 0x8b, 0xfe, 0x98, 0x15, 0xdb, 0x1b, 0x2a, 0xc8, 0xfc, + 0x7d, 0xa8, 0xca, 0x76, 0xfc, 0xa8, 0x86, 0x93, 0x3b, 0xfb, 0x95, 0xd9, + 0x20, 0xeb, 0x7a, 0xf4, 0xfd, 0xe7, 0x31, 0xee, 0xbf, 0x19, 0x20, 0x0d, + 0xbd, 0x1e, 0x9e, 0xa5, 0x1f, 0x1f, 0x9e, 0x41, 0xf5, 0xd6, 0xd0, 0xc9, + 0x09, 0xfe, 0x3b, 0x45, 0x10, 0x4e, 0xc3, 0xad, 0xc8, 0x99, 0xd4, 0x60 +}; +static const uint8_t nist_186_2_ecdsa_testvector_148_ptx[] = { +/* Msg */ + 0x3f, 0xdd, 0xfe, 0x5f, 0xe1, 0x9b, 0x1a, 0x4a, 0x9f, 0x23, 0x7f, 0x61, + 0xcb, 0x8e, 0xb7, 0x92, 0xe9, 0x5d, 0x09, 0x9a, 0x14, 0x55, 0xfb, 0x78, + 0x9d, 0x8d, 0x16, 0x22, 0xf6, 0xc5, 0xe9, 0x76, 0xce, 0xf9, 0x51, 0x73, + 0x7e, 0x36, 0xf7, 0xa9, 0xa4, 0xad, 0x19, 0xee, 0x0d, 0x06, 0x8e, 0x53, + 0xd9, 0xf6, 0x04, 0x57, 0xd9, 0x14, 0x8d, 0x5a, 0x3c, 0xe8, 0x5a, 0x54, + 0x6b, 0x45, 0xc5, 0xc6, 0x31, 0xd9, 0x95, 0xf1, 0x1f, 0x03, 0x7e, 0x47, + 0x2f, 0xe4, 0xe8, 0x1f, 0xa7, 0xb9, 0xf2, 0xac, 0x40, 0x68, 0xb5, 0x30, + 0x88, 0x58, 0xcd, 0x6d, 0x85, 0x86, 0x16, 0x5c, 0x9b, 0xd6, 0xb3, 0x22, + 0xaf, 0xa7, 0x55, 0x40, 0x8d, 0xa9, 0xb9, 0x0a, 0x87, 0xf3, 0x73, 0x5a, + 0x5f, 0x50, 0xeb, 0x85, 0x68, 0xda, 0xa5, 0x8e, 0xe7, 0xcb, 0xc5, 0x9a, + 0xbf, 0x8f, 0xd2, 0xa4, 0x4e, 0x1e, 0xba, 0x72 +}; +static const uint8_t nist_186_2_ecdsa_testvector_148_private[] = { +/* d - byte alignment */ + 0x01, 0x06, 0x22, 0x53, 0x72, 0xae, 0x1a, 0x8c, 0x90, 0xb4, 0x61, 0xef, + 0x65, 0x7b, 0xc7, 0xf5, 0x6f, 0x14, 0x7e, 0x06, 0x4d, 0x2b, 0x9e, 0xcc, + 0x3e, 0x25, 0xf0, 0x1a, 0xcb, 0xd3, 0xd7, 0xd9, 0x79, 0xef, 0xf4, 0x8d, + 0x70, 0x36, 0x34, 0x28, 0x4a, 0x2d, 0x6f, 0xdd, 0xb2, 0x16, 0x19, 0x18, + 0xe9, 0xa1, 0x8a, 0x9a, 0x2d, 0x5d, 0x4e, 0x7b, 0xbe, 0xd2, 0xf7, 0x5b, + 0x7a, 0x4c, 0xad, 0x37, 0x2a, 0x11, 0xbf, 0x7e, 0x11, 0x8d, 0xab, 0x4a +}; +static const uint8_t nist_186_2_ecdsa_testvector_148_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0xab, 0x89, 0x4b, 0x73, 0xae, 0x5f, 0xcf, 0x82, 0x2e, 0x79, 0x2c, + 0x06, 0x78, 0xfc, 0xaf, 0xa8, 0x10, 0x84, 0x71, 0x19, 0xa1, 0xbf, 0x44, + 0x75, 0x6d, 0xd1, 0x5e, 0x44, 0xab, 0xd9, 0x94, 0x57, 0x7f, 0xdc, 0x33, + 0x66, 0xc9, 0xf8, 0x1e, 0xaf, 0xa8, 0xaa, 0x1b, 0x50, 0x97, 0x7e, 0x86, + 0xe1, 0xcf, 0xc9, 0xdc, 0x0a, 0xe9, 0xde, 0x38, 0xa9, 0x2c, 0x66, 0x90, + 0x05, 0x93, 0x7d, 0xa7, 0xd5, 0xbc, 0x8a, 0xdf, 0x1a, 0xbc, 0x3e, 0x97 +}; +static const uint8_t nist_186_2_ecdsa_testvector_148_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0xba, 0xf7, 0x96, 0x45, 0x66, 0xb3, 0x8b, 0xaa, 0xa3, 0x33, 0x4d, + 0xe1, 0x21, 0x14, 0x99, 0x43, 0xf2, 0x12, 0xd2, 0xd6, 0xa8, 0xb8, 0x91, + 0xe0, 0x68, 0x24, 0xb4, 0x59, 0x9a, 0x03, 0x3a, 0xdd, 0x0c, 0x47, 0xa7, + 0xf3, 0xa3, 0xe2, 0x33, 0x7b, 0x88, 0xf6, 0x24, 0x6c, 0xd2, 0xbe, 0x4f, + 0x78, 0xdd, 0xd4, 0x1a, 0xdf, 0xb5, 0xb5, 0xae, 0x1f, 0x11, 0x16, 0x96, + 0x6b, 0xad, 0xa7, 0xb3, 0x05, 0x98, 0xef, 0x5e, 0x9e, 0x5f, 0x0e, 0xe7 +}; +/* k = 0e16e40c853dc6c904ae4ed9c43a362c3a3edec8475b624b93e38002934f609aaec6a673bd38b6f4f579abe36435a608ec286ba1b3f56fdf9691a23bc70a276d4247f5310e04d7a */ +static const uint8_t nist_186_2_ecdsa_testvector_148_out[] = { +/* R - byte alignment */ + 0x00, 0x73, 0xe1, 0x3e, 0x82, 0xa6, 0x62, 0xfd, 0x94, 0xb0, 0x2b, 0xea, + 0xd7, 0x1d, 0x9b, 0x8c, 0x68, 0x22, 0x3b, 0xc5, 0x7d, 0x1b, 0x89, 0x28, + 0x2a, 0xa2, 0x0a, 0x7a, 0xad, 0x71, 0xae, 0xc9, 0xae, 0xf3, 0x12, 0xa7, + 0x67, 0x27, 0x55, 0x9c, 0xa6, 0xd1, 0xe9, 0xc5, 0xcd, 0xdb, 0x63, 0xe1, + 0x0e, 0x18, 0x88, 0x42, 0xa7, 0x9b, 0x78, 0xe2, 0x71, 0x8b, 0x31, 0x21, + 0x93, 0x1d, 0x7e, 0x12, 0x02, 0xb0, 0x42, 0x7b, 0x94, 0x64, 0x30, 0x29, +/* S - byte alignment */ + 0x01, 0x04, 0x80, 0x75, 0xf9, 0x68, 0x12, 0x13, 0x5c, 0xdf, 0x64, 0x4f, + 0x3c, 0x7b, 0x3c, 0x02, 0xe5, 0x71, 0x97, 0x56, 0x1c, 0xf1, 0x7b, 0x6b, + 0xa1, 0xd4, 0xd7, 0x7f, 0x48, 0xcf, 0x53, 0x01, 0x67, 0xa4, 0x6e, 0xa7, + 0x82, 0x9b, 0xec, 0x00, 0x9b, 0x20, 0xde, 0x15, 0xe5, 0x75, 0x3b, 0x35, + 0x51, 0xda, 0x65, 0xc2, 0xc5, 0x5d, 0xb0, 0xb4, 0x90, 0x06, 0xd0, 0x85, + 0x95, 0x53, 0xd0, 0xfe, 0xe0, 0x31, 0xc2, 0xc5, 0x82, 0xf4, 0x78, 0xc9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_149_ptx[] = { +/* Msg */ + 0x11, 0x94, 0x75, 0xc3, 0x75, 0x3a, 0x4e, 0x1a, 0x09, 0xf6, 0xf4, 0xd9, + 0xff, 0xbe, 0xd7, 0xbc, 0xf0, 0x5e, 0xe6, 0x0a, 0xd9, 0x6a, 0xaf, 0x25, + 0x63, 0x77, 0xc7, 0x60, 0x67, 0x8a, 0x6c, 0x12, 0xb1, 0xd1, 0x69, 0xe9, + 0x04, 0x91, 0x3a, 0x80, 0x5f, 0x60, 0x71, 0x33, 0x7f, 0x94, 0x58, 0x32, + 0xa5, 0xfb, 0xd8, 0xd4, 0x99, 0xcd, 0x99, 0x2e, 0xef, 0xde, 0x6b, 0xe5, + 0x89, 0x18, 0xe5, 0x40, 0x5d, 0x29, 0x4b, 0x81, 0x78, 0x79, 0xb5, 0x76, + 0x43, 0x5f, 0x6e, 0x4b, 0x06, 0x94, 0x9b, 0xa2, 0xaa, 0xe8, 0x1d, 0xe5, + 0xc3, 0x33, 0xb8, 0xdb, 0xce, 0x8f, 0x74, 0x7a, 0xb6, 0xc4, 0x43, 0xfd, + 0x9e, 0x04, 0xe5, 0x36, 0xda, 0xd9, 0x09, 0x24, 0x3e, 0x5b, 0xb5, 0xc8, + 0x9c, 0xa6, 0xe7, 0x35, 0x88, 0x8b, 0x7d, 0xe7, 0x5e, 0x86, 0x52, 0x55, + 0x87, 0xf0, 0xaa, 0xc9, 0xf7, 0x76, 0xd0, 0x70 +}; +static const uint8_t nist_186_2_ecdsa_testvector_149_private[] = { +/* d - byte alignment */ + 0x00, 0xea, 0x88, 0xfc, 0x4d, 0x45, 0xc3, 0x68, 0x56, 0xc0, 0x4d, 0x6f, + 0x90, 0x00, 0x3d, 0xdc, 0xfa, 0x10, 0xc0, 0xe4, 0x9a, 0x4e, 0xb4, 0x36, + 0xe1, 0xe9, 0x92, 0x41, 0x37, 0x80, 0x91, 0x70, 0x87, 0xf2, 0xb0, 0x52, + 0xde, 0x62, 0x39, 0x09, 0xfa, 0xeb, 0x99, 0x5b, 0x67, 0x4a, 0x8a, 0xb2, + 0x14, 0x20, 0x8c, 0xaa, 0x3c, 0xd5, 0x0c, 0xf4, 0x53, 0x08, 0x95, 0xcf, + 0x5a, 0xa9, 0xaf, 0x27, 0xc9, 0xbe, 0x7d, 0xc4, 0x47, 0x37, 0x7d, 0x4d +}; +static const uint8_t nist_186_2_ecdsa_testvector_149_public_x[] = { +/* Qx - byte alignment */ + 0x02, 0x8c, 0x5a, 0x67, 0x38, 0x2e, 0x01, 0xdc, 0x19, 0xf9, 0x49, 0xd9, + 0xc8, 0xfb, 0x0b, 0x0e, 0xab, 0x5b, 0x08, 0x3b, 0x89, 0xf3, 0x63, 0x61, + 0x58, 0x0c, 0x94, 0x61, 0xdd, 0xbe, 0x34, 0x15, 0x55, 0x9c, 0x6b, 0xdc, + 0x6e, 0xd7, 0x61, 0xb4, 0x53, 0x73, 0x54, 0x57, 0xe2, 0x0c, 0xb8, 0x46, + 0x8a, 0xa8, 0xaf, 0x81, 0x66, 0x0e, 0x4d, 0x5f, 0xb0, 0x0f, 0x7e, 0x50, + 0x8e, 0x14, 0x18, 0xfa, 0xbd, 0xba, 0x20, 0xe9, 0x31, 0x35, 0x25, 0x9b +}; +static const uint8_t nist_186_2_ecdsa_testvector_149_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x43, 0xdf, 0x4d, 0x7b, 0xc9, 0x7d, 0xff, 0x16, 0xf5, 0xeb, 0xb7, + 0xe9, 0x25, 0x1d, 0x3a, 0x33, 0xe2, 0x1f, 0xe3, 0x5c, 0xee, 0x80, 0xa9, + 0x17, 0xfe, 0x46, 0xd9, 0xce, 0x6f, 0xef, 0xee, 0xd6, 0x8b, 0xe9, 0x60, + 0x1b, 0x8f, 0xd4, 0x75, 0x0f, 0x63, 0x0d, 0x9e, 0xf5, 0x02, 0x8c, 0xb6, + 0xc6, 0x19, 0x00, 0x9d, 0x05, 0xcd, 0xa1, 0xf9, 0xc4, 0x68, 0x6b, 0x89, + 0x8d, 0x7e, 0x40, 0x23, 0x87, 0xf3, 0x97, 0xce, 0xd8, 0xc8, 0xec, 0x90 +}; +/* k = 17466571d853ff59d6471ac324805af5d5d72d2360a3f7a3e9529cb3489ed0c66c71b0dac9f0fa2d1de1f67c2eb01553e0c14b77e35f2db48ae361025241afd4ecc818dc50133a4 */ +static const uint8_t nist_186_2_ecdsa_testvector_149_out[] = { +/* R - byte alignment */ + 0x00, 0xd4, 0x0d, 0xb5, 0x62, 0xa9, 0xac, 0xe3, 0x40, 0xbb, 0xfb, 0x70, + 0xb0, 0x7a, 0xd9, 0x90, 0x29, 0x4b, 0xfb, 0xaf, 0x5b, 0xe6, 0xb8, 0x83, + 0x9c, 0x9d, 0xf5, 0x34, 0x75, 0x46, 0x35, 0x03, 0xae, 0x55, 0x99, 0xda, + 0xf2, 0xa6, 0x56, 0xcf, 0xcc, 0xbf, 0xa9, 0x08, 0xc8, 0x8c, 0xe3, 0x7c, + 0x2b, 0x46, 0xb3, 0xac, 0x71, 0xcc, 0x58, 0x45, 0x60, 0xa7, 0x50, 0x7d, + 0xb8, 0x00, 0x9e, 0x63, 0xb0, 0x88, 0x8c, 0x8e, 0x53, 0x19, 0xfe, 0xde, +/* S - byte alignment */ + 0x00, 0xc7, 0xf0, 0x6c, 0xb8, 0xb8, 0xf8, 0x3c, 0x86, 0x2c, 0xd3, 0x50, + 0x62, 0xe9, 0x09, 0xe3, 0xee, 0x61, 0x5a, 0x8c, 0x3f, 0x83, 0x15, 0x67, + 0x80, 0x45, 0xa0, 0x1e, 0xdc, 0x4d, 0x89, 0x88, 0xe1, 0x01, 0xc1, 0xea, + 0xe8, 0x80, 0x1e, 0x3d, 0xa4, 0x7f, 0x92, 0xa2, 0xd3, 0xcc, 0x67, 0xba, + 0x84, 0x2e, 0x5a, 0xf1, 0x3e, 0x0b, 0xaf, 0x96, 0xe0, 0x4e, 0x60, 0xfc, + 0xb2, 0xa4, 0x85, 0x2e, 0x11, 0x54, 0xb6, 0x27, 0xfe, 0xbb, 0x72, 0x7a +}; +static const uint8_t nist_186_2_ecdsa_testvector_150_ptx[] = { +/* Msg */ + 0x31, 0x94, 0x16, 0xc2, 0x93, 0x4e, 0x83, 0xe5, 0x2e, 0xb3, 0xf1, 0x01, + 0xe8, 0xa3, 0x11, 0x14, 0x94, 0x2f, 0xfd, 0xe1, 0xba, 0x50, 0x1c, 0x43, + 0x9b, 0xd8, 0x45, 0xc2, 0x70, 0xa8, 0x27, 0x64, 0xf3, 0x24, 0xe8, 0xc5, + 0x20, 0xe4, 0x0c, 0x6a, 0x3d, 0xac, 0x99, 0x53, 0x18, 0x9f, 0x78, 0xcf, + 0x90, 0xaf, 0x1f, 0x95, 0x56, 0x58, 0x6d, 0x0f, 0xf5, 0x8e, 0xd5, 0xf9, + 0x10, 0xf4, 0xbf, 0x2b, 0xeb, 0x4e, 0x2b, 0xb3, 0x2e, 0x39, 0x98, 0x27, + 0xe5, 0x1a, 0x24, 0x3a, 0xca, 0x54, 0xf4, 0x8c, 0xc7, 0xbe, 0xd6, 0xc7, + 0xb7, 0x54, 0x25, 0xe7, 0x6d, 0x2c, 0xee, 0xd9, 0xf7, 0xac, 0x50, 0x48, + 0x23, 0xfb, 0x29, 0xb4, 0x43, 0xb5, 0xef, 0xc4, 0x2e, 0xe3, 0xdb, 0xdd, + 0x87, 0x2a, 0x4d, 0xf3, 0x42, 0x42, 0x6c, 0x9f, 0x63, 0xaa, 0x0c, 0x72, + 0x09, 0x9a, 0xd6, 0x8a, 0xac, 0x3a, 0xa2, 0x62 +}; +static const uint8_t nist_186_2_ecdsa_testvector_150_private[] = { +/* d - byte alignment */ + 0x00, 0xd7, 0x64, 0x1d, 0x00, 0xae, 0x2a, 0xa1, 0xb8, 0x4e, 0x28, 0x5e, + 0x8a, 0xec, 0x02, 0xf3, 0xd0, 0xdb, 0x16, 0x83, 0xec, 0xa0, 0x2e, 0xee, + 0x2a, 0x1e, 0x14, 0x52, 0x3e, 0x32, 0x6f, 0x1f, 0x5b, 0x7c, 0xbd, 0x14, + 0xa0, 0x9f, 0x90, 0x5b, 0xe2, 0xad, 0x6b, 0xde, 0x53, 0x99, 0x18, 0x51, + 0x66, 0xb0, 0xe0, 0x13, 0x50, 0xcb, 0x28, 0x88, 0x5b, 0x0f, 0x6b, 0x09, + 0x5a, 0x81, 0x9d, 0xe5, 0x6c, 0xe3, 0x15, 0xbf, 0x05, 0x0c, 0x02, 0x9b +}; +static const uint8_t nist_186_2_ecdsa_testvector_150_public_x[] = { +/* Qx - byte alignment */ + 0x07, 0x3d, 0x87, 0x9a, 0x43, 0x3d, 0x98, 0x9f, 0x74, 0xb2, 0x13, 0xd7, + 0x67, 0x69, 0x64, 0x48, 0x50, 0x57, 0x92, 0x3d, 0xd1, 0x73, 0x50, 0x16, + 0xa3, 0x61, 0x36, 0xca, 0x62, 0xad, 0xf8, 0xa6, 0xa4, 0xec, 0x40, 0x25, + 0x5e, 0xdf, 0x9b, 0x07, 0xcb, 0x40, 0x75, 0xc2, 0xef, 0x0e, 0xc5, 0x8e, + 0xeb, 0x9e, 0x02, 0xba, 0xfc, 0x75, 0x9d, 0x67, 0xbe, 0xeb, 0xe8, 0xdb, + 0x14, 0xe2, 0x23, 0x58, 0x50, 0xbe, 0x1d, 0x2b, 0x59, 0x48, 0x5b, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_150_public_y[] = { +/* Qy - byte alignment */ + 0x07, 0x0e, 0x91, 0x0d, 0xbf, 0x6e, 0x83, 0xcc, 0xd6, 0x46, 0xea, 0x00, + 0x44, 0x85, 0x75, 0x03, 0xab, 0x42, 0x74, 0x9a, 0xfb, 0x92, 0x70, 0x17, + 0x98, 0xda, 0x87, 0x1e, 0xbe, 0x35, 0x0e, 0x69, 0x1b, 0x14, 0xc6, 0xbd, + 0xcb, 0x23, 0x28, 0xdf, 0x0d, 0x41, 0x18, 0x3e, 0x83, 0xec, 0xc3, 0x5a, + 0xbc, 0x47, 0x55, 0xbc, 0xfb, 0x28, 0xdd, 0x8f, 0x3b, 0xbf, 0x60, 0x40, + 0xd1, 0x9e, 0x6d, 0x89, 0x95, 0x3c, 0x47, 0xa3, 0x94, 0x30, 0xa2, 0xf5 +}; +/* k = 122174974c29e11768cf326bbd0f82c042b4f380f2920d2a331e08f5f8755067a7269a2d8ac0798509ed42ac00f3a1c7fbdaaa8d673f9524eb269d2eff04d86ac0cb0f6d809748a */ +static const uint8_t nist_186_2_ecdsa_testvector_150_out[] = { +/* R - byte alignment */ + 0x01, 0x80, 0x33, 0x77, 0xea, 0x63, 0xf9, 0xf5, 0x57, 0x45, 0x11, 0x28, + 0xb1, 0xa8, 0x85, 0xf4, 0xaf, 0xab, 0xc2, 0x86, 0x8a, 0xef, 0xe6, 0xa9, + 0xfe, 0x2e, 0x84, 0xee, 0x15, 0x29, 0x40, 0x5c, 0x60, 0xd3, 0x13, 0x2a, + 0x22, 0x1b, 0x6d, 0x7c, 0xe1, 0xb6, 0xd2, 0x8c, 0x55, 0xd5, 0x5c, 0xac, + 0x2d, 0x00, 0x0e, 0x96, 0x9d, 0xa0, 0xab, 0x90, 0xa1, 0x8a, 0x0a, 0xf2, + 0x8c, 0xd3, 0x59, 0x0b, 0xca, 0xc8, 0x5d, 0x71, 0xf8, 0x1b, 0x5e, 0x48, +/* S - byte alignment */ + 0x01, 0x64, 0xc4, 0x20, 0xcc, 0x98, 0x41, 0x41, 0xa4, 0xbd, 0x14, 0x42, + 0xd1, 0x8a, 0xb8, 0xdc, 0x6f, 0x57, 0xa8, 0xe8, 0xf7, 0x7c, 0xd2, 0xfa, + 0x89, 0x94, 0x56, 0xff, 0xd1, 0x72, 0x89, 0xd1, 0x05, 0x46, 0x01, 0xfc, + 0x10, 0x54, 0x70, 0xbc, 0x9a, 0xce, 0xc8, 0x60, 0xcd, 0xa2, 0x07, 0x4c, + 0xe7, 0xb7, 0xbb, 0xdf, 0xf5, 0x9a, 0xf1, 0x33, 0x1d, 0xf1, 0x91, 0xae, + 0xf4, 0x29, 0x8c, 0xf1, 0x3f, 0xf7, 0x65, 0x06, 0x7b, 0xd1, 0x63, 0x74 +}; +/* [B-163] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_151_ptx[] = { +/* Msg */ + 0xc2, 0xd1, 0xaf, 0xa4, 0x0b, 0x33, 0x18, 0x01, 0x6d, 0xe5, 0xb6, 0x42, + 0x91, 0xfe, 0x1b, 0x45, 0x32, 0x5e, 0x73, 0x15, 0x7f, 0x87, 0x0a, 0x5d, + 0xc0, 0xaf, 0x0e, 0x23, 0x3d, 0x13, 0x95, 0xb2, 0x5b, 0x8d, 0xe1, 0xd8, + 0x09, 0x69, 0xe3, 0x52, 0x5a, 0x75, 0xff, 0x85, 0x73, 0x57, 0x0f, 0x6f, + 0xa8, 0x23, 0xaa, 0xdc, 0xe2, 0x2d, 0xa6, 0xdd, 0x44, 0x1c, 0xdb, 0x76, + 0x0e, 0x40, 0x2a, 0x97, 0xc1, 0x26, 0xbf, 0x4d, 0x84, 0x69, 0x92, 0x3a, + 0xc6, 0xca, 0x34, 0x43, 0x25, 0x83, 0xc8, 0x88, 0x8e, 0xd9, 0x4f, 0x99, + 0xa6, 0xf1, 0x2a, 0xe7, 0x69, 0xe4, 0xd9, 0x78, 0x11, 0x15, 0x09, 0xdf, + 0x3a, 0xc3, 0xce, 0x6c, 0x43, 0xda, 0x2d, 0xa0, 0xf7, 0x0f, 0xdd, 0xe3, + 0x6d, 0x2b, 0x4e, 0x79, 0x2c, 0xa7, 0xeb, 0xb3, 0x93, 0x7a, 0x9d, 0x62, + 0x79, 0x2f, 0x90, 0x91, 0x10, 0x3a, 0x39, 0x74 +}; +static const uint8_t nist_186_2_ecdsa_testvector_151_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0x87, 0xc0, 0xc5, 0x88, 0xfb, 0xdc, 0xf9, 0x4a, + 0x53, 0xb4, 0x51, 0x6d, 0x62, 0xd8, 0x98, 0xd0, 0x20 +}; +static const uint8_t nist_186_2_ecdsa_testvector_151_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xe1, 0x6c, 0x18, 0xb8, 0x00, 0xd4, 0xd5, 0x5c, 0xea, 0x0e, 0x77, + 0x22, 0x46, 0x73, 0x11, 0xd8, 0x98, 0xe4, 0x65, 0x4e +}; +static const uint8_t nist_186_2_ecdsa_testvector_151_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x9e, 0xc2, 0xe9, 0x5a, 0x75, 0xa5, 0x9f, 0x01, 0x41, 0x4c, 0xed, + 0x5c, 0xeb, 0x72, 0xb8, 0xf3, 0x47, 0xa9, 0x62, 0x09 +}; +/* k = 0000002e9c9c0846b936a6c112c0131cfe9e997b7 */ +static const uint8_t nist_186_2_ecdsa_testvector_151_out[] = { +/* R - byte alignment */ + 0x02, 0x66, 0x06, 0xf4, 0xab, 0xd3, 0xb5, 0x8b, 0x9f, 0x68, 0xd6, 0x4a, + 0x55, 0xbf, 0x68, 0xa2, 0x2c, 0xf7, 0x3d, 0x02, 0x6d, +/* S - byte alignment */ + 0x00, 0x20, 0xda, 0x66, 0x4d, 0x91, 0x19, 0x81, 0x36, 0x07, 0xaf, 0xbb, + 0x17, 0xf4, 0xc3, 0xcb, 0x55, 0x5e, 0x1b, 0xc0, 0xd0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_152_ptx[] = { +/* Msg */ + 0xf0, 0x1c, 0x31, 0x54, 0x3a, 0x4a, 0xc1, 0x99, 0xca, 0xbd, 0x42, 0xc7, + 0x67, 0xac, 0x61, 0xec, 0xba, 0xb0, 0xa0, 0x89, 0x0d, 0x78, 0x44, 0xe9, + 0x52, 0xbf, 0x6e, 0xb0, 0x67, 0x7b, 0x88, 0xb7, 0x98, 0x57, 0xe2, 0x17, + 0x66, 0x64, 0x9d, 0x84, 0x86, 0x0b, 0xc9, 0xdd, 0x2d, 0x47, 0xca, 0x00, + 0x8b, 0x11, 0x00, 0xe3, 0x95, 0x1b, 0xa7, 0xe1, 0x08, 0xc0, 0xfb, 0x51, + 0xab, 0x3b, 0xa0, 0x5d, 0xd4, 0x18, 0x42, 0x12, 0x2d, 0xe9, 0x79, 0xb3, + 0xb8, 0x3a, 0xef, 0x53, 0x11, 0xc7, 0xc4, 0xa2, 0xf4, 0xec, 0x31, 0x08, + 0xfe, 0x5c, 0x6c, 0xf0, 0xb8, 0x16, 0xcc, 0x67, 0xd1, 0x95, 0x2e, 0xe5, + 0xab, 0x47, 0x97, 0x6a, 0x1a, 0x41, 0x1b, 0xcd, 0x68, 0x31, 0xfd, 0x51, + 0x9c, 0x94, 0x17, 0x7a, 0xfb, 0x29, 0x7c, 0x1f, 0xd0, 0xa5, 0x5d, 0xbf, + 0x69, 0xa8, 0x29, 0x19, 0x62, 0xf0, 0xf8, 0xf6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_152_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x02, 0xc9, 0x5e, 0xdf, 0x46, 0xf6, 0xe6, 0x10, 0x38, + 0x48, 0xed, 0x80, 0xfa, 0x5b, 0x8c, 0x69, 0xa6, 0x29 +}; +static const uint8_t nist_186_2_ecdsa_testvector_152_public_x[] = { +/* Qx - byte alignment */ + 0x02, 0xbb, 0xcf, 0x0a, 0xa9, 0x0a, 0xea, 0xd1, 0x76, 0x8b, 0x54, 0xb4, + 0xb4, 0xf6, 0x64, 0x50, 0xd1, 0x8f, 0xd3, 0xc3, 0x96 +}; +static const uint8_t nist_186_2_ecdsa_testvector_152_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xe1, 0x6e, 0x24, 0xf6, 0x01, 0xd7, 0xdd, 0x5d, 0x53, 0x22, 0x0f, + 0x86, 0x38, 0x3c, 0x5d, 0x93, 0x4b, 0x57, 0x6b, 0xfb +}; +/* k = 000000333fd7cc66b6f57a447d0bab348fb697710 */ +static const uint8_t nist_186_2_ecdsa_testvector_152_out[] = { +/* R - byte alignment */ + 0x02, 0xe8, 0x4a, 0x2c, 0xef, 0x9d, 0x8e, 0x24, 0x69, 0xe1, 0x05, 0x93, + 0x6d, 0x9f, 0x52, 0x23, 0x9f, 0xdf, 0x7c, 0x68, 0x0c, +/* S - byte alignment */ + 0x01, 0xb7, 0x8c, 0xa4, 0xe6, 0xe8, 0xe6, 0x34, 0x08, 0x1f, 0x9d, 0x1a, + 0x1f, 0x50, 0xaa, 0xdc, 0xe2, 0x64, 0x6a, 0x0c, 0x58 +}; +static const uint8_t nist_186_2_ecdsa_testvector_153_ptx[] = { +/* Msg */ + 0xd0, 0xfa, 0xbb, 0x6f, 0x60, 0x95, 0x4c, 0xd1, 0x36, 0x59, 0x6d, 0x6a, + 0xbb, 0x1c, 0x6a, 0xe2, 0x42, 0xf8, 0xc3, 0x4b, 0xe9, 0xa1, 0x30, 0x0e, + 0xc0, 0xf5, 0xe3, 0x25, 0x2e, 0xd5, 0x0d, 0x8b, 0x90, 0x34, 0xa3, 0xf1, + 0x22, 0x6d, 0x62, 0xb3, 0x23, 0xda, 0x11, 0x0a, 0x34, 0xa2, 0x06, 0x83, + 0x02, 0xd2, 0xeb, 0xb0, 0x24, 0xb0, 0xc2, 0x1d, 0x47, 0x4c, 0x27, 0x85, + 0x88, 0x57, 0xd5, 0x46, 0x21, 0x38, 0x6c, 0x13, 0x48, 0x5d, 0x72, 0xe9, + 0x54, 0xcf, 0x97, 0x44, 0x22, 0x0a, 0x3d, 0x92, 0xb7, 0x0b, 0x37, 0xe8, + 0x26, 0xaa, 0xd1, 0xf4, 0xb4, 0x2a, 0x11, 0x33, 0x3b, 0x0f, 0x3d, 0x63, + 0xcc, 0x2f, 0x9d, 0x3c, 0x98, 0x0c, 0x82, 0x5b, 0x11, 0x61, 0x88, 0x7f, + 0x4c, 0xfb, 0x17, 0xf7, 0xaa, 0xca, 0x30, 0x5b, 0xb7, 0x38, 0x66, 0x7b, + 0x52, 0xb9, 0x2a, 0x95, 0x0f, 0xa4, 0x4c, 0xcb +}; +static const uint8_t nist_186_2_ecdsa_testvector_153_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0xf4, 0xc3, 0x94, 0xa9, 0xa5, 0xfa, 0x49, 0xf7, + 0x8b, 0x90, 0x21, 0xe2, 0xb4, 0x7a, 0xfd, 0xb3, 0x8b +}; +static const uint8_t nist_186_2_ecdsa_testvector_153_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0x78, 0x31, 0x04, 0xa8, 0x2a, 0x81, 0xf2, 0xe9, 0x77, 0xa7, 0xde, + 0x8d, 0x8c, 0xdd, 0xed, 0x90, 0x23, 0x81, 0x41, 0xe6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_153_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0x4d, 0x41, 0xba, 0x6a, 0xc3, 0xc4, 0xec, 0x5e, 0x49, 0x1c, 0x96, + 0x4a, 0x9d, 0xe5, 0xeb, 0x04, 0x2a, 0xb8, 0x6c, 0xca +}; +/* k = 00000009afe938c8eb8a501a12d6c6cb7759f72e5 */ +static const uint8_t nist_186_2_ecdsa_testvector_153_out[] = { +/* R - byte alignment */ + 0x01, 0xda, 0x8a, 0xa8, 0xd7, 0x1f, 0x1e, 0x4f, 0x41, 0x70, 0x76, 0xd3, + 0x5e, 0xa0, 0x9d, 0x28, 0x1f, 0x78, 0xbb, 0xd3, 0x15, +/* S - byte alignment */ + 0x01, 0x4c, 0x68, 0x88, 0xc2, 0x4e, 0xb3, 0x17, 0x58, 0x32, 0x76, 0xb8, + 0x21, 0x71, 0x34, 0x0c, 0x83, 0x72, 0x3c, 0xb0, 0x1e +}; +static const uint8_t nist_186_2_ecdsa_testvector_154_ptx[] = { +/* Msg */ + 0xa4, 0xa3, 0x72, 0xcf, 0xcb, 0x4e, 0x50, 0xd6, 0x14, 0x99, 0x41, 0xcf, + 0x02, 0x89, 0x83, 0x14, 0x53, 0x73, 0x67, 0xc1, 0x86, 0x6f, 0xf7, 0xc5, + 0x9b, 0x0a, 0xdb, 0x39, 0x1a, 0x3b, 0x7e, 0xf1, 0x56, 0x99, 0x6c, 0x51, + 0xf3, 0xca, 0xff, 0x62, 0xa6, 0x3f, 0x3a, 0x25, 0x3c, 0x1e, 0xf5, 0x28, + 0xde, 0x80, 0x3a, 0x56, 0x93, 0xdd, 0xf0, 0x13, 0x06, 0xc4, 0xb6, 0x89, + 0x8a, 0xd0, 0x12, 0x3c, 0x5b, 0xd7, 0xcb, 0xe5, 0x26, 0x64, 0x93, 0x7d, + 0xcc, 0x68, 0xe9, 0x98, 0x64, 0x2c, 0x3e, 0xf4, 0x7f, 0x8a, 0x57, 0x52, + 0xaf, 0x5d, 0xf2, 0x84, 0x4a, 0x36, 0xac, 0xc8, 0x6b, 0x51, 0x22, 0x54, + 0x3a, 0xc7, 0x57, 0x32, 0x6d, 0x04, 0x56, 0x4e, 0x0f, 0x7c, 0x18, 0xce, + 0x80, 0x9a, 0xa7, 0xa1, 0xbe, 0xf9, 0x84, 0x5b, 0xe2, 0xd7, 0x46, 0x40, + 0xee, 0xc7, 0x85, 0x9e, 0xc5, 0xa5, 0xf6, 0x61 +}; +static const uint8_t nist_186_2_ecdsa_testvector_154_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0x29, 0x78, 0x79, 0x14, 0xb2, 0xc6, + 0x85, 0x06, 0xdd, 0xc2, 0xef, 0xe5, 0x63, 0x01, 0x69 +}; +static const uint8_t nist_186_2_ecdsa_testvector_154_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x81, 0x7c, 0xb0, 0x47, 0x6e, 0x95, 0x5d, 0xad, 0x76, 0x8f, 0x77, + 0xba, 0x52, 0x23, 0x3d, 0xb1, 0xa5, 0x8c, 0x03, 0x5d +}; +static const uint8_t nist_186_2_ecdsa_testvector_154_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x18, 0xa8, 0x5d, 0x44, 0x19, 0x31, 0x11, 0x0d, 0xdd, 0x2e, 0xdc, + 0x5b, 0x13, 0x4e, 0xa1, 0x06, 0x34, 0xe1, 0x79, 0x5a +}; +/* k = 0000002fb9b0762de99093bb55e342fea56ee5330 */ +static const uint8_t nist_186_2_ecdsa_testvector_154_out[] = { +/* R - byte alignment */ + 0x00, 0x86, 0xeb, 0x7a, 0x66, 0x59, 0x76, 0xa5, 0xd5, 0x8a, 0xa3, 0x6c, + 0xbb, 0x50, 0xfd, 0x2a, 0xa4, 0x6a, 0x11, 0x8b, 0x2d, +/* S - byte alignment */ + 0x00, 0xf9, 0x9a, 0x5d, 0xac, 0x0b, 0x35, 0xc5, 0x9f, 0x87, 0x03, 0x5f, + 0x20, 0xbb, 0xba, 0x30, 0xba, 0xaa, 0x99, 0xb8, 0x79 +}; +static const uint8_t nist_186_2_ecdsa_testvector_155_ptx[] = { +/* Msg */ + 0xd1, 0xb4, 0x16, 0x83, 0x6f, 0x44, 0x6b, 0xb1, 0x9e, 0xcd, 0xd0, 0xc5, + 0xdc, 0xe3, 0x55, 0x1d, 0x5e, 0xfd, 0x6a, 0xfb, 0xb0, 0x83, 0xa1, 0x36, + 0x9d, 0x28, 0xb5, 0x2f, 0x4e, 0x7a, 0xcc, 0x07, 0xb6, 0xb7, 0xf9, 0x0f, + 0x2d, 0xe3, 0x05, 0x80, 0x5a, 0x17, 0x6f, 0x6d, 0x57, 0x1c, 0xb1, 0xf5, + 0x10, 0x39, 0xc5, 0xbd, 0xec, 0x48, 0xe8, 0x9e, 0xb0, 0x0f, 0x9e, 0x9a, + 0xa0, 0xce, 0xf6, 0x15, 0xe7, 0x15, 0x0f, 0x41, 0x38, 0xd8, 0xdb, 0xdb, + 0xb6, 0xc5, 0x23, 0x15, 0x11, 0xd5, 0xcb, 0xd3, 0xf2, 0x22, 0x58, 0x19, + 0x9a, 0xf8, 0xaf, 0xc4, 0xc6, 0x2e, 0x1f, 0x79, 0xd5, 0xb7, 0xa2, 0xdc, + 0x2c, 0x74, 0x60, 0x02, 0xda, 0x4c, 0x75, 0x28, 0x78, 0x7f, 0xf4, 0xa5, + 0x53, 0x37, 0x2c, 0x1d, 0xce, 0x61, 0x2a, 0xf8, 0x01, 0xba, 0x7f, 0x12, + 0xa6, 0x2d, 0x43, 0xb4, 0x36, 0x5c, 0x59, 0xc4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_155_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x90, 0x0c, 0x60, 0x8d, 0x8a, 0x2f, 0x46, 0xf1, + 0x0e, 0x02, 0x39, 0x0e, 0x74, 0xec, 0x61, 0x14, 0xaf +}; +static const uint8_t nist_186_2_ecdsa_testvector_155_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xaa, 0x21, 0x7c, 0x61, 0x15, 0xe2, 0x60, 0x0d, 0x97, 0xde, 0xc6, + 0x64, 0x55, 0x87, 0x64, 0x8b, 0xf6, 0x6b, 0x69, 0xf2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_155_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0xc2, 0xf3, 0x05, 0x37, 0xeb, 0xbb, 0x44, 0x2d, 0xf6, 0x9e, 0xdf, + 0x9f, 0xcd, 0xe8, 0xa2, 0x73, 0xc3, 0xe0, 0x26, 0xcc +}; +/* k = 000000129013ba5076d03a52ed0bbeafadd591a72 */ +static const uint8_t nist_186_2_ecdsa_testvector_155_out[] = { +/* R - byte alignment */ + 0x00, 0x60, 0x2f, 0x25, 0x0e, 0x61, 0x71, 0xac, 0x1a, 0xb8, 0x5f, 0x13, + 0xad, 0x6b, 0x0c, 0x75, 0x19, 0xe7, 0xaa, 0xc3, 0xe0, +/* S - byte alignment */ + 0x01, 0x45, 0x8f, 0xb5, 0xf2, 0x88, 0xa6, 0x52, 0x4d, 0xec, 0x62, 0x06, + 0x76, 0xd7, 0xd3, 0xc0, 0x1c, 0x22, 0xfe, 0xa6, 0xcb +}; +static const uint8_t nist_186_2_ecdsa_testvector_156_ptx[] = { +/* Msg */ + 0x18, 0xab, 0xee, 0x60, 0xc8, 0x09, 0xc6, 0x41, 0x2d, 0x00, 0xb7, 0x33, + 0x4b, 0x0f, 0x8d, 0xe0, 0xee, 0x63, 0x17, 0xf1, 0xee, 0x06, 0x86, 0xdf, + 0xb2, 0x53, 0x17, 0x06, 0xf3, 0xad, 0xf2, 0xfc, 0xc2, 0x70, 0x51, 0x20, + 0xcd, 0x28, 0xe4, 0x76, 0xde, 0x01, 0x75, 0xb2, 0xa4, 0x7f, 0xc8, 0x92, + 0xb6, 0x6f, 0xc5, 0x71, 0xd5, 0x1e, 0xd8, 0x1a, 0x71, 0xc8, 0x99, 0xda, + 0x6f, 0x53, 0xa8, 0xd9, 0x2a, 0x3d, 0xdb, 0xa9, 0xb8, 0xd4, 0x9c, 0x20, + 0x6e, 0xa5, 0x8c, 0x63, 0xa6, 0x36, 0x6d, 0x44, 0xbf, 0xf8, 0x3e, 0xce, + 0x66, 0x77, 0xa7, 0x1d, 0x14, 0xd4, 0x98, 0x74, 0xd8, 0x75, 0x2e, 0x89, + 0x57, 0xfb, 0xd6, 0x23, 0x11, 0x74, 0xb4, 0xe7, 0xe6, 0xd2, 0x46, 0x6f, + 0xd8, 0x9d, 0x44, 0x9d, 0x12, 0xe4, 0xcb, 0x2f, 0x2a, 0x79, 0xbb, 0x93, + 0xa3, 0x5e, 0x5e, 0xfc, 0xb6, 0x7a, 0x4a, 0xb5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_156_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0x7b, 0x61, 0x94, 0xa9, 0xe4, 0xbe, 0xc4, 0xd1, + 0x58, 0x6a, 0x2a, 0x24, 0x5f, 0xae, 0xab, 0x25, 0xac +}; +static const uint8_t nist_186_2_ecdsa_testvector_156_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x05, 0x8a, 0x0a, 0xb4, 0x61, 0xe8, 0x06, 0x53, 0x34, 0xc5, 0x4c, + 0x80, 0x72, 0x31, 0x90, 0x93, 0x8c, 0xac, 0x81, 0x57 +}; +static const uint8_t nist_186_2_ecdsa_testvector_156_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x7b, 0x51, 0x1e, 0xad, 0xd2, 0x50, 0x39, 0x5d, 0x96, 0x8a, 0x0a, + 0x95, 0x94, 0xb2, 0x80, 0x9d, 0x88, 0x6a, 0x36, 0xc4 +}; +/* k = 0000001b020387027d94b94f2a8959e1e8634f544 */ +static const uint8_t nist_186_2_ecdsa_testvector_156_out[] = { +/* R - byte alignment */ + 0x02, 0xae, 0x2d, 0x90, 0xd5, 0x73, 0xa8, 0x2e, 0x2c, 0x70, 0x4f, 0x1a, + 0x1d, 0x6c, 0x1b, 0xb3, 0x36, 0xb3, 0x08, 0xd0, 0x0e, +/* S - byte alignment */ + 0x01, 0x7e, 0xfb, 0x4e, 0x03, 0xe3, 0x0a, 0xee, 0x08, 0x91, 0x6a, 0xaa, + 0xe8, 0x03, 0xf9, 0x3b, 0x9f, 0xa8, 0x9e, 0x88, 0x97 +}; +static const uint8_t nist_186_2_ecdsa_testvector_157_ptx[] = { +/* Msg */ + 0xa9, 0xd6, 0x26, 0xa2, 0x1a, 0x5a, 0x4c, 0x54, 0xd8, 0xe4, 0xa9, 0x91, + 0x62, 0xc2, 0xdd, 0xcb, 0x74, 0x90, 0xa6, 0x17, 0xdb, 0xb9, 0x53, 0xd6, + 0x87, 0x3a, 0x7c, 0x94, 0xe2, 0xa9, 0xf1, 0x30, 0x60, 0x76, 0xf0, 0x3d, + 0x57, 0x72, 0x9b, 0xa9, 0x12, 0x8d, 0xa8, 0x9c, 0x21, 0xe4, 0x5b, 0xa3, + 0xf2, 0xfb, 0xb1, 0x0e, 0xa6, 0x46, 0xdf, 0x97, 0x1d, 0xef, 0xfa, 0x44, + 0x53, 0xd3, 0xf8, 0x8e, 0xf0, 0xce, 0xd7, 0xc2, 0x1a, 0x38, 0x1c, 0xa8, + 0x8e, 0xaf, 0x7f, 0x63, 0xef, 0x17, 0xe5, 0x98, 0x5d, 0xe0, 0x8e, 0xd2, + 0x4a, 0x87, 0x90, 0x25, 0x89, 0x60, 0x84, 0x12, 0xa8, 0x92, 0x7f, 0xab, + 0x80, 0x63, 0x44, 0xf7, 0x0a, 0xb6, 0xb7, 0x98, 0x75, 0xd1, 0x95, 0xab, + 0x75, 0x64, 0x63, 0xf0, 0xdd, 0xc7, 0xa4, 0x2b, 0x70, 0x84, 0x4f, 0xca, + 0xf4, 0x15, 0x80, 0xc7, 0x89, 0xef, 0x6e, 0xd0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_157_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0xe8, 0xd0, 0x55, 0xc3, 0x29, 0xc4, 0xa6, 0x00, + 0x5f, 0xd2, 0x8c, 0xb0, 0x9e, 0xe0, 0x28, 0xcf, 0x84 +}; +static const uint8_t nist_186_2_ecdsa_testvector_157_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xbb, 0x20, 0x5e, 0x46, 0xcf, 0x73, 0xd7, 0x6a, 0x06, 0x5f, 0xfd, + 0xdb, 0xdc, 0x2c, 0x55, 0x7c, 0xd8, 0xba, 0x63, 0xf4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_157_public_y[] = { +/* Qy - byte alignment */ + 0x03, 0x33, 0x92, 0x53, 0xcd, 0xc8, 0x2c, 0xcf, 0x24, 0x58, 0x05, 0x33, + 0x89, 0x59, 0x59, 0xbc, 0xeb, 0x46, 0x7a, 0xda, 0xd0 +}; +/* k = 0000000d70f69010361a39558ae58c460cc9fdf0a */ +static const uint8_t nist_186_2_ecdsa_testvector_157_out[] = { +/* R - byte alignment */ + 0x02, 0xa7, 0x75, 0xfa, 0xfe, 0xb8, 0x16, 0xbe, 0x66, 0x0f, 0xcd, 0x7f, + 0x1a, 0x94, 0xa9, 0x45, 0x50, 0x52, 0x55, 0xa8, 0xd9, +/* S - byte alignment */ + 0x02, 0x68, 0xbd, 0x5e, 0xdb, 0xb6, 0x43, 0x27, 0x46, 0xa2, 0xfd, 0xe7, + 0xa5, 0xfb, 0xcc, 0x37, 0xdf, 0x6f, 0x04, 0xbf, 0xd4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_158_ptx[] = { +/* Msg */ + 0x32, 0x83, 0xa8, 0x5c, 0x84, 0x30, 0xf2, 0xca, 0x98, 0x1b, 0x00, 0x74, + 0x5e, 0xbe, 0x73, 0x47, 0x9c, 0x1c, 0x50, 0x07, 0x9b, 0xa8, 0x54, 0x4b, + 0x21, 0x62, 0x88, 0xc9, 0x9e, 0x43, 0x15, 0xd3, 0xaa, 0xdb, 0x58, 0x22, + 0xaf, 0x39, 0x39, 0xd3, 0xe3, 0x0b, 0xb9, 0xaf, 0x7a, 0x06, 0xcb, 0xaf, + 0x19, 0x88, 0x65, 0xbf, 0x8d, 0x7c, 0xd6, 0xc3, 0xbd, 0x7f, 0x5a, 0xd8, + 0xdd, 0x40, 0xec, 0xdc, 0xe5, 0x2d, 0x5b, 0x30, 0x42, 0x4c, 0xa0, 0xbc, + 0xcb, 0x66, 0x6f, 0x34, 0xf6, 0x6b, 0x0c, 0x9a, 0x4c, 0x12, 0x60, 0x05, + 0x1a, 0xc0, 0x4c, 0xa0, 0x6a, 0xab, 0x3d, 0xf5, 0x31, 0x3f, 0x01, 0x6c, + 0xca, 0xc1, 0xd9, 0x0e, 0xa3, 0x32, 0xcf, 0x8f, 0x37, 0x76, 0x49, 0x8c, + 0x3c, 0xb5, 0xdf, 0x11, 0x1d, 0x02, 0x6a, 0x5e, 0xaa, 0x3a, 0x5d, 0xeb, + 0x0f, 0x2f, 0x59, 0xa9, 0x02, 0x06, 0xfb, 0x8b +}; +static const uint8_t nist_186_2_ecdsa_testvector_158_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0x03, 0xd9, 0xc3, 0x95, 0x81, 0x45, 0xf2, 0x4c, + 0x41, 0x60, 0x07, 0x69, 0x0d, 0x7d, 0xf1, 0x43, 0x88 +}; +static const uint8_t nist_186_2_ecdsa_testvector_158_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0xa3, 0xbe, 0x2c, 0x25, 0x99, 0x7e, 0x75, 0x6d, 0xe9, 0xe2, 0x28, + 0x6e, 0x7a, 0xc0, 0x33, 0xac, 0xb1, 0xbd, 0x90, 0x78 +}; +static const uint8_t nist_186_2_ecdsa_testvector_158_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0xed, 0xfa, 0x21, 0x57, 0x65, 0x58, 0xbb, 0x32, 0xe6, 0xbb, 0x7c, + 0x4e, 0x4a, 0xed, 0xdf, 0x57, 0xf2, 0x17, 0xd4, 0x89 +}; +/* k = 0000002b007ad6ec8aebb6388cfe7a060672e50fb */ +static const uint8_t nist_186_2_ecdsa_testvector_158_out[] = { +/* R - byte alignment */ + 0x03, 0xa6, 0x91, 0xe5, 0xbe, 0x8c, 0xbe, 0x8b, 0x5e, 0xd3, 0xeb, 0x8e, + 0x2e, 0xbb, 0x6e, 0xee, 0xf1, 0xa5, 0x64, 0xae, 0xd2, +/* S - byte alignment */ + 0x02, 0xd8, 0x64, 0xaa, 0x86, 0x20, 0x16, 0x34, 0x08, 0xe5, 0xff, 0x81, + 0x52, 0x5e, 0x16, 0xf2, 0x77, 0xec, 0x4e, 0x4c, 0x40 +}; +static const uint8_t nist_186_2_ecdsa_testvector_159_ptx[] = { +/* Msg */ + 0xc2, 0xdc, 0x36, 0xa2, 0xa3, 0xc2, 0x2f, 0xfd, 0xfe, 0xa9, 0xce, 0x61, + 0x54, 0x62, 0xb7, 0xaf, 0x93, 0x6f, 0x70, 0x25, 0x8d, 0xad, 0x73, 0x26, + 0xa9, 0x36, 0x81, 0x3e, 0xd9, 0x85, 0x3a, 0x61, 0xcc, 0xdb, 0xeb, 0x73, + 0x64, 0xe2, 0xa7, 0x0e, 0x6a, 0x90, 0x99, 0x7f, 0x81, 0x4f, 0x98, 0x11, + 0x58, 0x5b, 0xfc, 0x8f, 0x24, 0x6b, 0xb0, 0x04, 0x4e, 0x93, 0x89, 0xc5, + 0x68, 0x69, 0xd6, 0xb1, 0x66, 0x67, 0x39, 0xb8, 0x0b, 0x90, 0xb5, 0x9a, + 0xa1, 0x56, 0x07, 0xf1, 0xed, 0xbc, 0x3a, 0x72, 0x62, 0xb8, 0x76, 0x70, + 0x95, 0xdb, 0x19, 0xa1, 0xf1, 0x33, 0x08, 0x25, 0xac, 0x71, 0x48, 0xc4, + 0xf9, 0x47, 0xc8, 0x78, 0x80, 0x14, 0x81, 0x2b, 0x0b, 0xc3, 0xc1, 0xc1, + 0x82, 0xf0, 0xc4, 0x59, 0x19, 0x4d, 0x85, 0xd0, 0xc8, 0x45, 0xd3, 0x87, + 0xfc, 0xdf, 0xa7, 0x67, 0x8c, 0xe4, 0xb5, 0x22 +}; +static const uint8_t nist_186_2_ecdsa_testvector_159_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0x2f, 0xee, 0x2b, 0xb5, 0xf7, 0xb2, 0xcf, 0x24, + 0x2a, 0x14, 0x9c, 0xdc, 0x2a, 0xf3, 0x28, 0x8c, 0x98 +}; +static const uint8_t nist_186_2_ecdsa_testvector_159_public_x[] = { +/* Qx - byte alignment */ + 0x02, 0x74, 0xb4, 0x32, 0x30, 0xb8, 0xb7, 0x4c, 0x55, 0x4b, 0xf4, 0xf4, + 0x0a, 0x94, 0x30, 0xb5, 0xc9, 0xdf, 0x16, 0x24, 0xe8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_159_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0x35, 0xc4, 0xf1, 0xfa, 0xe7, 0x72, 0xcc, 0xca, 0x08, 0xa4, 0xe7, + 0xb7, 0x00, 0xc1, 0xbe, 0x54, 0x80, 0xfa, 0x84, 0x38 +}; +/* k = 0000000d91ac5eb54506ebfe2a8ab846e2b30c3a2 */ +static const uint8_t nist_186_2_ecdsa_testvector_159_out[] = { +/* R - byte alignment */ + 0x01, 0x74, 0xf2, 0xba, 0xf3, 0xf7, 0xb3, 0x1a, 0xdc, 0x85, 0xdb, 0x39, + 0x6c, 0xf2, 0xcc, 0x8b, 0x34, 0x50, 0xb8, 0x0c, 0x40, +/* S - byte alignment */ + 0x03, 0xec, 0x94, 0xcb, 0x19, 0xf4, 0xf2, 0xb0, 0x29, 0x5a, 0x14, 0x27, + 0x3d, 0xea, 0xe9, 0xd6, 0xa1, 0x5a, 0xcc, 0xa8, 0x0f +}; +static const uint8_t nist_186_2_ecdsa_testvector_160_ptx[] = { +/* Msg */ + 0xf4, 0x84, 0x1c, 0xb2, 0x46, 0x37, 0x4d, 0x7b, 0x0a, 0xc6, 0x4a, 0xc1, + 0xc4, 0x3a, 0x4d, 0xe4, 0x1d, 0x23, 0xef, 0x23, 0x2c, 0xd1, 0x92, 0x6d, + 0xf5, 0xc7, 0x00, 0x73, 0x2f, 0x6d, 0x50, 0x02, 0x4b, 0x05, 0x0a, 0x90, + 0xb1, 0xe0, 0x8b, 0x15, 0x4d, 0xd2, 0xaa, 0x1c, 0x4a, 0xe3, 0x9b, 0x19, + 0x1d, 0x47, 0x14, 0xfd, 0xc6, 0x91, 0xaf, 0x08, 0x52, 0x23, 0x90, 0xde, + 0xa5, 0xe9, 0x47, 0xde, 0x76, 0x47, 0xf7, 0xaf, 0x9b, 0x4f, 0xb8, 0x1b, + 0x87, 0x38, 0x3b, 0x21, 0x11, 0x0b, 0xad, 0x45, 0x77, 0xa0, 0xdd, 0x2b, + 0xa2, 0xc9, 0xa0, 0x64, 0xab, 0xcd, 0x75, 0x88, 0x9f, 0x18, 0x65, 0x85, + 0x7f, 0x30, 0x2d, 0x36, 0x8b, 0xeb, 0x9f, 0x38, 0xc0, 0xe0, 0x46, 0xf9, + 0xa0, 0x1b, 0x49, 0x11, 0x31, 0x15, 0x91, 0xd6, 0x48, 0xe3, 0x2e, 0x2a, + 0x07, 0xad, 0xf7, 0x98, 0xa5, 0x62, 0x71, 0xa0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_160_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0xf8, 0x99, 0x5d, 0xc1, 0xeb, 0x5b, 0x51, 0x69, + 0xb2, 0x3b, 0x3f, 0x79, 0x1b, 0xe9, 0x10, 0x30, 0xe2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_160_public_x[] = { +/* Qx - byte alignment */ + 0x02, 0xfd, 0xe9, 0xa6, 0x3f, 0x79, 0xc8, 0xc8, 0x5b, 0x95, 0x9e, 0x89, + 0x66, 0xd2, 0xa5, 0x25, 0x21, 0xa6, 0x39, 0xc2, 0xd0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_160_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xc1, 0x84, 0x87, 0xed, 0xe8, 0x81, 0x54, 0x98, 0xc0, 0xfa, 0x1a, + 0x75, 0x6a, 0x95, 0x0f, 0xef, 0x03, 0x3d, 0x52, 0x3b +}; +/* k = 00000013d1e8e7e08d3e5f315a32d2061bedf8065 */ +static const uint8_t nist_186_2_ecdsa_testvector_160_out[] = { +/* R - byte alignment */ + 0x02, 0x71, 0x5e, 0x19, 0x54, 0x44, 0x80, 0x01, 0x06, 0xb9, 0x56, 0xcb, + 0xcb, 0x8f, 0x25, 0x8a, 0xd8, 0x35, 0x21, 0x4b, 0x22, +/* S - byte alignment */ + 0x01, 0x64, 0xa1, 0xd8, 0x2d, 0x2a, 0xc3, 0xcd, 0x5b, 0x76, 0x1e, 0x58, + 0x8d, 0xd4, 0xc5, 0xc6, 0x83, 0x8b, 0xad, 0xfd, 0x43 +}; +static const uint8_t nist_186_2_ecdsa_testvector_161_ptx[] = { +/* Msg */ + 0x56, 0x52, 0x6f, 0x99, 0x8e, 0x82, 0x99, 0x2f, 0xd1, 0xf0, 0xf3, 0x79, + 0x26, 0x93, 0x65, 0x50, 0x56, 0x1f, 0xa3, 0x2a, 0x51, 0xda, 0xaf, 0x8d, + 0xce, 0xac, 0xa0, 0xca, 0x32, 0x76, 0xa1, 0xe7, 0xb3, 0xa5, 0x3c, 0xdd, + 0xbd, 0x07, 0xd9, 0x04, 0x94, 0xdd, 0x81, 0xcb, 0x3c, 0x31, 0xe8, 0xac, + 0x96, 0x6a, 0xab, 0x5f, 0xcb, 0x1d, 0xd6, 0x4e, 0xed, 0x26, 0xa9, 0x4a, + 0xdc, 0xf8, 0x9c, 0x7c, 0x67, 0x31, 0xa0, 0x9e, 0xb4, 0x72, 0xa8, 0x6b, + 0xe2, 0x6d, 0x68, 0x53, 0xec, 0x3f, 0x5c, 0x74, 0xd1, 0x01, 0x0d, 0xc6, + 0xf2, 0x99, 0x90, 0x95, 0xbb, 0xd6, 0x4f, 0x35, 0x85, 0xbd, 0x0c, 0xf1, + 0xbb, 0x1d, 0x22, 0x44, 0x3c, 0x6a, 0x0e, 0x4c, 0x01, 0xc7, 0x2f, 0x7b, + 0x00, 0x65, 0xca, 0x90, 0x50, 0x0c, 0x51, 0xc5, 0x8d, 0xf7, 0xe5, 0x4a, + 0x7e, 0xe5, 0x19, 0xf3, 0xf5, 0x6d, 0xf9, 0x2e +}; +static const uint8_t nist_186_2_ecdsa_testvector_161_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x09, 0xed, 0x47, 0x3f, 0xc4, 0xd9, 0x06, 0x96, + 0x46, 0xe8, 0xda, 0xe1, 0x43, 0x4f, 0x2a, 0x05, 0x66 +}; +static const uint8_t nist_186_2_ecdsa_testvector_161_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0xd0, 0xfa, 0x3a, 0xc7, 0x35, 0xcf, 0x1c, 0xc1, 0x56, 0xf0, 0x47, + 0x70, 0xff, 0x3f, 0x71, 0x48, 0x9e, 0xcb, 0x44, 0x4f +}; +static const uint8_t nist_186_2_ecdsa_testvector_161_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x54, 0x3c, 0xb6, 0x4c, 0xfa, 0xe5, 0xed, 0x2c, 0xd8, 0x1e, 0x54, + 0x70, 0xe5, 0x89, 0x88, 0x1e, 0x32, 0xaf, 0x76, 0x16 +}; +/* k = 000000383482f2cd0b0635e07dc0179f8d4a478ca */ +static const uint8_t nist_186_2_ecdsa_testvector_161_out[] = { +/* R - byte alignment */ + 0x01, 0xa0, 0x0a, 0xa7, 0xce, 0xc4, 0xf1, 0xbf, 0x5d, 0xc0, 0x86, 0x5c, + 0xf2, 0xf6, 0x6b, 0x2a, 0x23, 0x6f, 0x92, 0xf0, 0xf6, +/* S - byte alignment */ + 0x03, 0x65, 0x7c, 0xdd, 0x4f, 0x17, 0xfe, 0x59, 0x2f, 0xa0, 0x17, 0x3c, + 0x57, 0xc8, 0x55, 0x4e, 0xf6, 0xb1, 0xf6, 0x3b, 0x90 +}; +static const uint8_t nist_186_2_ecdsa_testvector_162_ptx[] = { +/* Msg */ + 0x0c, 0x12, 0x8f, 0x1c, 0x5f, 0x04, 0x38, 0xe8, 0xe2, 0x05, 0xda, 0x4e, + 0x08, 0xc7, 0x33, 0xa6, 0x19, 0x88, 0x5a, 0x38, 0x8f, 0xe4, 0x47, 0xab, + 0xc1, 0xed, 0x96, 0xc1, 0xbe, 0x7d, 0x88, 0x41, 0x7c, 0xcb, 0x4b, 0x34, + 0x32, 0x3d, 0x7b, 0x53, 0x02, 0x7d, 0xe8, 0xc1, 0xdb, 0xcf, 0x9a, 0xf6, + 0x9e, 0xa2, 0x12, 0xfb, 0x7f, 0x64, 0xd3, 0xdd, 0xaf, 0x9b, 0x21, 0x5c, + 0x38, 0x32, 0x09, 0xe3, 0x28, 0x10, 0xa1, 0xbd, 0xf1, 0xf0, 0x91, 0x85, + 0x10, 0x6c, 0xd2, 0xde, 0xed, 0x5a, 0xb6, 0x65, 0x02, 0x5c, 0x29, 0xe4, + 0x40, 0xb3, 0x36, 0xc9, 0xae, 0x54, 0xcd, 0xd6, 0x54, 0x3e, 0xc3, 0x19, + 0x57, 0x0a, 0x1a, 0x1f, 0x65, 0xc4, 0x83, 0x65, 0x53, 0xf9, 0x21, 0x0f, + 0x05, 0x11, 0x90, 0xdc, 0x8f, 0xdf, 0x26, 0x5a, 0x99, 0x77, 0x78, 0x56, + 0x08, 0x40, 0x20, 0x97, 0xdb, 0x4a, 0xbe, 0xcc +}; +static const uint8_t nist_186_2_ecdsa_testvector_162_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0x7a, 0xeb, 0x88, 0x81, 0xcc, 0x1a, 0x37, 0x86, + 0x8f, 0xee, 0xbf, 0x0a, 0xfb, 0x16, 0x63, 0x47, 0xe3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_162_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0x3c, 0x87, 0x66, 0x95, 0x7f, 0xa8, 0x79, 0x0a, 0xde, 0x8a, 0xbb, + 0xe0, 0xe7, 0x43, 0xfe, 0x97, 0x07, 0x5e, 0xe0, 0xd4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_162_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x54, 0x17, 0x7a, 0x8f, 0xb1, 0x82, 0xd8, 0xb1, 0xdf, 0x53, 0x12, + 0xc4, 0x90, 0x21, 0xdc, 0x8d, 0x23, 0x1c, 0xb7, 0x87 +}; +/* k = 00000023c13933cd6db18498861ce7341b3769879 */ +static const uint8_t nist_186_2_ecdsa_testvector_162_out[] = { +/* R - byte alignment */ + 0x00, 0x50, 0xb4, 0x70, 0x1f, 0xbf, 0xfa, 0x98, 0xad, 0x36, 0x3c, 0x2b, + 0x2a, 0xaf, 0xa3, 0xdb, 0xeb, 0x71, 0x82, 0xde, 0x3f, +/* S - byte alignment */ + 0x03, 0x10, 0x65, 0xd4, 0xb4, 0x20, 0xe1, 0xac, 0xe0, 0x9d, 0x5b, 0xd9, + 0x57, 0x02, 0xbf, 0x8b, 0x76, 0x4e, 0xd3, 0x04, 0x48 +}; +static const uint8_t nist_186_2_ecdsa_testvector_163_ptx[] = { +/* Msg */ + 0xf1, 0x76, 0xec, 0x2d, 0x74, 0xb0, 0x34, 0xa9, 0x38, 0xf2, 0x02, 0xcd, + 0x68, 0xd0, 0x62, 0xfc, 0x28, 0xe8, 0x4d, 0xe3, 0xc1, 0x75, 0xe2, 0xae, + 0xfe, 0x21, 0xf3, 0x7c, 0xd6, 0x1b, 0xc3, 0x10, 0x4a, 0x6a, 0x0e, 0xc9, + 0x91, 0x81, 0x4a, 0xd4, 0x73, 0x13, 0x2d, 0xa0, 0xf3, 0x28, 0x6f, 0x92, + 0x30, 0x71, 0xd1, 0xfb, 0x8d, 0xd8, 0x5e, 0x47, 0x10, 0x5c, 0xf1, 0x77, + 0x08, 0x1c, 0xf7, 0xd1, 0xf3, 0xb1, 0x76, 0xd5, 0x9e, 0xc1, 0x4f, 0x74, + 0x8e, 0xd1, 0xc0, 0x7d, 0x9f, 0x5b, 0x2c, 0x58, 0xeb, 0x21, 0x1f, 0xf6, + 0xed, 0xc0, 0x8d, 0x08, 0xe7, 0x88, 0x5a, 0x6f, 0x80, 0x8b, 0x1f, 0xf4, + 0xb2, 0xf4, 0x2c, 0x3a, 0xe3, 0x9b, 0xc9, 0xf0, 0x52, 0xd6, 0xc2, 0x4b, + 0xb5, 0x91, 0x22, 0xb4, 0x21, 0xa1, 0x3e, 0xbe, 0x29, 0x55, 0xf5, 0x5a, + 0x4a, 0x4e, 0x37, 0x4e, 0x87, 0x91, 0xc4, 0xe3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_163_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x01, 0x29, 0x01, 0x3b, 0xa5, 0x07, 0x6d, 0x03, 0xa5, + 0x2e, 0xd0, 0xbb, 0xea, 0xfa, 0xdd, 0x59, 0x1a, 0x72 +}; +static const uint8_t nist_186_2_ecdsa_testvector_163_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x60, 0x2f, 0x25, 0x0e, 0x61, 0x71, 0xac, 0x1a, 0xb8, 0x5f, 0x13, + 0xad, 0x6b, 0x0c, 0x75, 0x19, 0xe7, 0xaa, 0xc3, 0xe0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_163_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x82, 0xbb, 0x2d, 0xda, 0xaf, 0x24, 0xca, 0xe0, 0xe6, 0xb0, 0x6b, + 0x8c, 0x6a, 0xdf, 0xd5, 0xcc, 0xb4, 0x52, 0xa9, 0x93 +}; +/* k = 00000022ff25c072ee5833817bc0c9a30d3a08374 */ +static const uint8_t nist_186_2_ecdsa_testvector_163_out[] = { +/* R - byte alignment */ + 0x03, 0x1e, 0x58, 0x80, 0xe9, 0xd7, 0x3d, 0xbb, 0xa8, 0x0e, 0xc7, 0x68, + 0x7c, 0x56, 0x2c, 0xf1, 0x0f, 0x7a, 0x21, 0xf3, 0x57, +/* S - byte alignment */ + 0x00, 0xb9, 0x96, 0x5d, 0x7d, 0xb0, 0xf4, 0x92, 0x9e, 0x5e, 0xe7, 0xf3, + 0xbd, 0x8d, 0xa8, 0xc3, 0xfe, 0xb9, 0x4e, 0x77, 0x3c +}; +static const uint8_t nist_186_2_ecdsa_testvector_164_ptx[] = { +/* Msg */ + 0x8a, 0x9e, 0x55, 0x09, 0x57, 0x5c, 0xea, 0x1b, 0xea, 0x88, 0xff, 0x55, + 0x18, 0xac, 0xc6, 0xaa, 0x54, 0x84, 0xd8, 0xe6, 0x8c, 0x57, 0x31, 0xa0, + 0x4e, 0x87, 0x7c, 0x69, 0x2f, 0x68, 0x92, 0x4a, 0x6d, 0x4e, 0x3d, 0x6e, + 0xd3, 0xea, 0x41, 0x1b, 0xdd, 0xd6, 0x9d, 0xe7, 0x1d, 0x6e, 0x0e, 0x28, + 0xdd, 0xe2, 0xd5, 0xac, 0x06, 0x89, 0xba, 0xaa, 0x41, 0x78, 0x51, 0xf9, + 0x5b, 0x54, 0x7c, 0x80, 0xee, 0x64, 0x31, 0xee, 0x3e, 0xea, 0x7d, 0xab, + 0x61, 0xb4, 0xc9, 0x0e, 0xa3, 0xee, 0x5d, 0xd0, 0x28, 0x3a, 0x22, 0xc0, + 0xd3, 0x03, 0xac, 0xb9, 0x67, 0x0d, 0x77, 0xd1, 0xec, 0x51, 0x71, 0xd4, + 0x55, 0x09, 0xb9, 0xf1, 0x5f, 0x07, 0xa7, 0xb2, 0xbc, 0x4a, 0x0c, 0x32, + 0x71, 0xd3, 0xbb, 0x8a, 0x7d, 0xb5, 0x48, 0x8c, 0xbb, 0x6c, 0x0f, 0xb4, + 0x09, 0x6f, 0x78, 0x5b, 0xaa, 0x09, 0x7a, 0x2e +}; +static const uint8_t nist_186_2_ecdsa_testvector_164_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x03, 0x64, 0xad, 0xbc, 0x7d, 0x7d, 0x8c, 0x34, 0x7e, + 0x80, 0x41, 0xa0, 0x90, 0xd7, 0xbe, 0x32, 0x0d, 0x43 +}; +static const uint8_t nist_186_2_ecdsa_testvector_164_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0x4e, 0x52, 0xdf, 0x28, 0xfa, 0xd7, 0x75, 0xcc, 0x62, 0xd5, 0x75, + 0x39, 0x38, 0x4b, 0x8a, 0x0c, 0xf2, 0x25, 0x2c, 0x0b +}; +static const uint8_t nist_186_2_ecdsa_testvector_164_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0xb7, 0xd2, 0x72, 0xad, 0x99, 0xb4, 0x1b, 0x88, 0x50, 0x68, 0x26, + 0x92, 0xd3, 0xe1, 0xbc, 0x35, 0x0e, 0x47, 0xb8, 0xc5 +}; +/* k = 00000008bd7183a6955813153d452d4fe92571e5f */ +static const uint8_t nist_186_2_ecdsa_testvector_164_out[] = { +/* R - byte alignment */ + 0x03, 0xd6, 0xf4, 0x9e, 0xc3, 0x50, 0xaf, 0x2d, 0x0d, 0x5d, 0x4e, 0xbf, + 0x37, 0x60, 0xb3, 0xd8, 0x5d, 0xcd, 0x39, 0xef, 0xc0, +/* S - byte alignment */ + 0x01, 0xe6, 0x84, 0x91, 0xf6, 0x42, 0xab, 0x6f, 0xf6, 0xfc, 0x60, 0xf0, + 0x8d, 0xcc, 0xb0, 0x71, 0x51, 0x5d, 0x09, 0x78, 0x21 +}; +static const uint8_t nist_186_2_ecdsa_testvector_165_ptx[] = { +/* Msg */ + 0xa0, 0x78, 0x53, 0xcc, 0xb3, 0xb7, 0x70, 0x25, 0xd9, 0xf3, 0xfa, 0x14, + 0xa8, 0xf5, 0xdf, 0xdd, 0x20, 0x54, 0xaf, 0xe3, 0xe9, 0xa4, 0xff, 0x79, + 0xdc, 0xeb, 0x0b, 0xf6, 0xc5, 0x54, 0x9f, 0x07, 0x67, 0x28, 0x37, 0x4a, + 0xc1, 0xf9, 0x65, 0x18, 0x90, 0x21, 0x73, 0xa2, 0x15, 0x6b, 0x49, 0x3f, + 0x18, 0x0f, 0x92, 0x04, 0x2d, 0xe4, 0x1b, 0x96, 0x36, 0xd1, 0x7b, 0x3c, + 0x29, 0x84, 0xf9, 0x38, 0x14, 0x67, 0xaa, 0x58, 0x5e, 0xd0, 0xda, 0xc8, + 0x4f, 0x79, 0xad, 0x2a, 0xd2, 0x2f, 0x06, 0xe8, 0x7a, 0xce, 0xa8, 0xc9, + 0xc4, 0x6c, 0x9c, 0xc3, 0x9c, 0xd5, 0xd2, 0x11, 0x22, 0x38, 0x0b, 0x85, + 0xad, 0x1f, 0xf5, 0x1e, 0x10, 0xa4, 0x98, 0xdd, 0x1d, 0xe2, 0xf2, 0xd5, + 0x68, 0xab, 0xde, 0x82, 0x4e, 0x79, 0x3b, 0x5b, 0x35, 0xa6, 0x49, 0xaa, + 0x14, 0xdf, 0x56, 0x9c, 0x37, 0xd6, 0x9b, 0x94 +}; +static const uint8_t nist_186_2_ecdsa_testvector_165_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x00, 0x70, 0xd5, 0x9b, 0xc0, 0x59, 0xdf, 0x30, 0xc6, + 0x0e, 0xc0, 0x38, 0x55, 0x38, 0x05, 0x24, 0xdc, 0xb5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_165_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0x21, 0x11, 0x9b, 0xcf, 0xbb, 0xcd, 0xff, 0xf8, 0x8a, 0x82, 0x6c, + 0xc8, 0xbb, 0x54, 0xbb, 0xa6, 0xb4, 0xa3, 0x9b, 0x6e +}; +static const uint8_t nist_186_2_ecdsa_testvector_165_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x3e, 0xbc, 0x3a, 0xd3, 0x8b, 0x32, 0x3a, 0x36, 0x8a, 0xe0, 0xbb, + 0xb2, 0x9f, 0xbc, 0xc4, 0x84, 0xbf, 0x76, 0x71, 0xeb +}; +/* k = 0000001ecd85d31dfba4ce8e363a548e259f207c1 */ +static const uint8_t nist_186_2_ecdsa_testvector_165_out[] = { +/* R - byte alignment */ + 0x03, 0xd8, 0x53, 0x45, 0x25, 0xb3, 0xce, 0xf4, 0x0c, 0xc4, 0xa5, 0x51, + 0xfe, 0x77, 0x81, 0x50, 0x83, 0xb0, 0x8b, 0x6f, 0x1f, +/* S - byte alignment */ + 0x02, 0x15, 0x62, 0x2f, 0xc7, 0xa0, 0x59, 0x7f, 0x3e, 0xda, 0x19, 0xd3, + 0xc6, 0xe6, 0x7b, 0x76, 0xfb, 0x36, 0x22, 0xba, 0x00 +}; +/* [B-233] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_166_ptx[] = { +/* Msg */ + 0xc2, 0xd1, 0xaf, 0xa4, 0x0b, 0x33, 0x18, 0x01, 0x6d, 0xe5, 0xb6, 0x42, + 0x91, 0xfe, 0x1b, 0x45, 0x32, 0x5e, 0x73, 0x15, 0x7f, 0x87, 0x0a, 0x5d, + 0xc0, 0xaf, 0x0e, 0x23, 0x3d, 0x13, 0x95, 0xb2, 0x5b, 0x8d, 0xe1, 0xd8, + 0x09, 0x69, 0xe3, 0x52, 0x5a, 0x75, 0xff, 0x85, 0x73, 0x57, 0x0f, 0x6f, + 0xa8, 0x23, 0xaa, 0xdc, 0xe2, 0x2d, 0xa6, 0xdd, 0x44, 0x1c, 0xdb, 0x76, + 0x0e, 0x40, 0x2a, 0x97, 0xc1, 0x26, 0xbf, 0x4d, 0x84, 0x69, 0x92, 0x3a, + 0xc6, 0xca, 0x34, 0x43, 0x25, 0x83, 0xc8, 0x88, 0x8e, 0xd9, 0x4f, 0x99, + 0xa6, 0xf1, 0x2a, 0xe7, 0x69, 0xe4, 0xd9, 0x78, 0x11, 0x15, 0x09, 0xdf, + 0x3a, 0xc3, 0xce, 0x6c, 0x43, 0xda, 0x2d, 0xa0, 0xf7, 0x0f, 0xdd, 0xe3, + 0x6d, 0x2b, 0x4e, 0x79, 0x2c, 0xa7, 0xeb, 0xb3, 0x93, 0x7a, 0x9d, 0x62, + 0x79, 0x2f, 0x90, 0x91, 0x10, 0x3a, 0x39, 0x74 +}; +static const uint8_t nist_186_2_ecdsa_testvector_166_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xd4, 0x67, 0xbb, 0x20, 0x60, 0xec, 0xb1, 0x05, 0x29, + 0x68, 0x49, 0x47, 0xe1, 0xe9, 0x5a, 0x74, 0x03, 0x48, 0xab, 0x21, 0xc3, + 0x8a, 0xfa, 0xf6, 0xe4, 0x64, 0xa2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_166_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xb8, 0x93, 0x2e, 0xe9, 0x9a, 0xdf, 0x72, 0xb6, 0x20, 0xe1, 0xa6, + 0x77, 0x9c, 0x9d, 0xc5, 0xf9, 0xad, 0x38, 0xbd, 0x3f, 0x64, 0x75, 0xca, + 0xe8, 0x4e, 0x20, 0x9c, 0x70, 0x4e +}; +static const uint8_t nist_186_2_ecdsa_testvector_166_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x04, 0x05, 0x1c, 0xed, 0x12, 0x59, 0xd5, 0x08, 0x5f, 0x2e, 0x1c, + 0x8f, 0x5c, 0xa5, 0x39, 0x4e, 0x09, 0x4c, 0x33, 0xe7, 0x57, 0xa6, 0x3c, + 0xe4, 0x3d, 0x1c, 0x06, 0xd3, 0xec +}; +/* k = 000005f77b867f215519eafb9807e239068db9cb19253ed669163cb7cec */ +static const uint8_t nist_186_2_ecdsa_testvector_166_out[] = { +/* R - byte alignment */ + 0x00, 0x5f, 0x25, 0xaf, 0x72, 0xc9, 0x8e, 0x8e, 0x9b, 0x4a, 0x2c, 0x73, + 0x0f, 0xec, 0x92, 0x2c, 0x29, 0x4f, 0x4d, 0xaa, 0x78, 0x19, 0xa4, 0xef, + 0xe3, 0x5a, 0x80, 0x56, 0xea, 0x84, +/* S - byte alignment */ + 0x00, 0x0d, 0xbd, 0xb0, 0x01, 0x3d, 0x94, 0x8a, 0xe6, 0x84, 0xb5, 0x86, + 0x96, 0xa2, 0x60, 0xa2, 0x25, 0xba, 0x09, 0x1c, 0xbd, 0xa3, 0x70, 0x49, + 0x86, 0x94, 0x41, 0x13, 0x70, 0x0d +}; +static const uint8_t nist_186_2_ecdsa_testvector_167_ptx[] = { +/* Msg */ + 0xf3, 0x19, 0xf9, 0x53, 0x85, 0xa1, 0xe9, 0x2a, 0x49, 0xb9, 0xae, 0xf3, + 0xe2, 0x4e, 0x11, 0xa6, 0x7c, 0xa9, 0xc7, 0x6e, 0xa4, 0xf1, 0xeb, 0x4f, + 0x5d, 0xf1, 0xab, 0x0c, 0x70, 0x1c, 0x41, 0x48, 0x03, 0xce, 0x25, 0xeb, + 0x6d, 0xd5, 0x80, 0xc7, 0x49, 0x30, 0xe4, 0x7c, 0xc9, 0x16, 0x3b, 0x98, + 0x4e, 0x3b, 0xfe, 0x03, 0x35, 0x4e, 0xa8, 0x9b, 0xf3, 0xc6, 0x69, 0x1b, + 0x64, 0xde, 0x1e, 0x41, 0x60, 0xde, 0x81, 0x30, 0x90, 0x9d, 0x9d, 0x13, + 0x7f, 0x44, 0x86, 0x03, 0xf4, 0x54, 0x46, 0x2b, 0x80, 0xeb, 0x1a, 0x29, + 0x53, 0x43, 0xdf, 0xb8, 0x53, 0x7b, 0xc7, 0x8c, 0x70, 0x9a, 0x50, 0x7e, + 0x31, 0xd1, 0x77, 0xe9, 0x93, 0x00, 0x28, 0x54, 0x14, 0x7c, 0xfa, 0x51, + 0x0b, 0x10, 0x19, 0xa4, 0x3a, 0x41, 0x83, 0xa8, 0xa6, 0xd6, 0x78, 0xef, + 0xa7, 0x98, 0x2b, 0x29, 0x3b, 0x57, 0xbe, 0x47 +}; +static const uint8_t nist_186_2_ecdsa_testvector_167_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xdb, 0xd1, 0xb2, 0x54, 0x78, 0xb8, 0x2c, 0x19, 0x44, + 0xc4, 0x1f, 0x89, 0x05, 0xfe, 0x27, 0x1c, 0x2c, 0x01, 0xd6, 0xe6, 0xe9, + 0xfa, 0xfd, 0x42, 0xd8, 0xbc, 0xdf +}; +static const uint8_t nist_186_2_ecdsa_testvector_167_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x08, 0x90, 0x15, 0xf7, 0x85, 0xed, 0x88, 0x0a, 0x20, 0x0c, 0x2c, + 0x8e, 0x09, 0xa8, 0xd7, 0x0f, 0x5e, 0x79, 0x17, 0x4c, 0x60, 0x9b, 0x25, + 0x2a, 0xb4, 0xf5, 0x4d, 0xcc, 0x43 +}; +static const uint8_t nist_186_2_ecdsa_testvector_167_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x5e, 0x5e, 0x52, 0x97, 0xd2, 0x96, 0x36, 0xd6, 0xae, 0xb2, 0xca, + 0x63, 0x54, 0xf5, 0x18, 0x39, 0x36, 0x52, 0xb7, 0xeb, 0x2c, 0x7a, 0xa5, + 0x5f, 0x9e, 0x08, 0xfb, 0xe7, 0x10 +}; +/* k = 000008a3e301af481418118308ee6a5e93fa25b8cd87e778611ce96e726 */ +static const uint8_t nist_186_2_ecdsa_testvector_167_out[] = { +/* R - byte alignment */ + 0x00, 0xf5, 0x9a, 0x4f, 0xf3, 0xb7, 0xb4, 0x2b, 0x64, 0x93, 0x1d, 0xcd, + 0xe2, 0x47, 0x88, 0x3c, 0x05, 0x79, 0x15, 0xcc, 0x67, 0x84, 0xc7, 0xf9, + 0xc8, 0x34, 0x9e, 0xf7, 0x53, 0x53, +/* S - byte alignment */ + 0x00, 0x3f, 0x3c, 0x4a, 0x48, 0xe4, 0x06, 0x80, 0x74, 0x4c, 0x89, 0x10, + 0x43, 0xc6, 0xff, 0x8f, 0xd0, 0x4a, 0x6f, 0x4b, 0xd3, 0x54, 0x80, 0xb1, + 0x4e, 0xdc, 0x6c, 0xe7, 0x7b, 0x61 +}; +static const uint8_t nist_186_2_ecdsa_testvector_168_ptx[] = { +/* Msg */ + 0x7e, 0xc7, 0x30, 0x55, 0x38, 0x4b, 0xd2, 0x28, 0xd2, 0x80, 0x60, 0x35, + 0xc8, 0x8b, 0xbe, 0xdf, 0xc0, 0x02, 0x7a, 0x8c, 0x58, 0xa0, 0xaf, 0xfb, + 0x21, 0x3e, 0x29, 0xd8, 0xeb, 0xfe, 0xc9, 0x8d, 0x44, 0xca, 0x2b, 0x5c, + 0x3b, 0xfd, 0x87, 0xaa, 0x6a, 0x5f, 0xd5, 0x9e, 0x33, 0x57, 0x35, 0xeb, + 0x49, 0x5c, 0x8d, 0xea, 0x72, 0xad, 0x74, 0xec, 0x8c, 0x42, 0x4f, 0xce, + 0xce, 0x02, 0xb9, 0xce, 0x51, 0x36, 0x29, 0x9c, 0xcf, 0x3e, 0xce, 0xb5, + 0xaa, 0x82, 0xbe, 0xec, 0x30, 0xac, 0x50, 0x49, 0x1d, 0x15, 0xc6, 0x17, + 0x61, 0x7c, 0x30, 0x39, 0x24, 0xfe, 0x8d, 0xbd, 0x08, 0x42, 0x32, 0xb4, + 0xae, 0xf5, 0x70, 0x40, 0x7b, 0x76, 0x71, 0xee, 0x9c, 0xd2, 0x63, 0x46, + 0x47, 0xf2, 0xd8, 0xa1, 0x44, 0x13, 0x6d, 0x3b, 0xad, 0x77, 0xaa, 0x89, + 0xf2, 0x5a, 0x2a, 0xcd, 0x1f, 0x28, 0xfc, 0xe7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_168_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x66, 0x38, 0x78, 0xeb, 0xb3, 0x4c, 0x38, 0xdf, 0x8d, + 0xca, 0xf9, 0x68, 0xaa, 0xbe, 0x48, 0xca, 0xe2, 0xbf, 0xa4, 0xd1, 0xe3, + 0xb6, 0x7e, 0xce, 0xeb, 0x5f, 0xaa +}; +static const uint8_t nist_186_2_ecdsa_testvector_168_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x9c, 0x72, 0x22, 0xce, 0x23, 0x4b, 0xf3, 0xca, 0x69, 0x8f, 0xe0, + 0x6c, 0x61, 0x5f, 0x69, 0x2b, 0xfa, 0x89, 0xd2, 0xc3, 0x2b, 0xb7, 0xb0, + 0x46, 0x2e, 0xfa, 0x2b, 0xa9, 0x8c +}; +static const uint8_t nist_186_2_ecdsa_testvector_168_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x63, 0xab, 0x9a, 0xd6, 0x0b, 0xb7, 0x76, 0x24, 0xae, 0xfc, 0x10, + 0x0e, 0x30, 0xc4, 0xc3, 0x81, 0x58, 0x6e, 0x12, 0x21, 0xcf, 0xa5, 0x2a, + 0x9d, 0x99, 0x71, 0x46, 0x47, 0x34 +}; +/* k = 000003c78b556033fddac988ffd24bb952d59be10c7e6a104acd76bedc5 */ +static const uint8_t nist_186_2_ecdsa_testvector_168_out[] = { +/* R - byte alignment */ + 0x00, 0xde, 0xd3, 0xe1, 0xa3, 0xdf, 0x2c, 0xc4, 0xb1, 0x3b, 0xbe, 0xec, + 0xb0, 0x12, 0x72, 0x86, 0x81, 0xe9, 0x80, 0x78, 0x61, 0x72, 0x9f, 0xba, + 0xd0, 0x64, 0xed, 0xa4, 0x16, 0x2b, +/* S - byte alignment */ + 0x00, 0x1f, 0x35, 0x1e, 0xa6, 0xfd, 0x7b, 0xaa, 0xb5, 0x7a, 0x8c, 0xc6, + 0x7c, 0xd2, 0xac, 0x90, 0x8a, 0xc4, 0x4f, 0x86, 0x0c, 0xfb, 0xbf, 0x3a, + 0x34, 0x2b, 0x8a, 0x80, 0xa6, 0xfb +}; +static const uint8_t nist_186_2_ecdsa_testvector_169_ptx[] = { +/* Msg */ + 0x85, 0xad, 0x5f, 0xba, 0x82, 0x13, 0x55, 0xa0, 0xb9, 0xf5, 0x5a, 0xc9, + 0xd2, 0x2a, 0x7f, 0x55, 0x82, 0x60, 0x43, 0x15, 0x60, 0xa9, 0x06, 0x38, + 0xf4, 0x36, 0xc0, 0x27, 0x11, 0x61, 0xf2, 0xad, 0x65, 0xf1, 0xdd, 0x5b, + 0x4f, 0x9a, 0xf3, 0x2b, 0xf0, 0xc4, 0x8b, 0x63, 0x85, 0x8e, 0xd8, 0xbc, + 0xf4, 0x11, 0x1c, 0xc4, 0xa4, 0xe9, 0x19, 0x81, 0x92, 0xf2, 0xc8, 0x57, + 0xa2, 0x4f, 0x4e, 0x2b, 0x33, 0xb1, 0x2c, 0xc9, 0xf5, 0xd5, 0xb6, 0x83, + 0xff, 0x4f, 0xc6, 0x1b, 0x1c, 0x87, 0xb1, 0xe4, 0x66, 0x01, 0x7a, 0x23, + 0x17, 0xe1, 0x46, 0xbb, 0x9b, 0xae, 0x10, 0x0a, 0xea, 0x56, 0x9e, 0x0e, + 0x14, 0x72, 0xb4, 0xcc, 0x1d, 0xcc, 0x87, 0xf2, 0x0c, 0x1e, 0x74, 0xbb, + 0x3f, 0x1d, 0xf2, 0x13, 0x01, 0xb6, 0xc6, 0xfc, 0x5f, 0x98, 0x76, 0x30, + 0x37, 0xf2, 0xff, 0x07, 0x91, 0x7e, 0xca, 0x9c +}; +static const uint8_t nist_186_2_ecdsa_testvector_169_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xed, 0xd6, 0xa7, 0xa4, 0x6a, 0x1f, 0xdb, 0x56, 0xf4, + 0xd4, 0xd3, 0xa5, 0x92, 0x3a, 0x96, 0x13, 0xf5, 0x19, 0x79, 0x0a, 0x6a, + 0x9e, 0x45, 0x6c, 0x1d, 0x1a, 0xca +}; +static const uint8_t nist_186_2_ecdsa_testvector_169_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xad, 0x3e, 0x9c, 0xef, 0xf5, 0x2b, 0xa5, 0x51, 0xfe, 0x95, 0x18, + 0x69, 0xc0, 0xf2, 0xb3, 0xcf, 0x83, 0xde, 0xb1, 0x8e, 0x7a, 0xaa, 0xbd, + 0x1e, 0x28, 0xc5, 0x5d, 0xa0, 0x00 +}; +static const uint8_t nist_186_2_ecdsa_testvector_169_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xb8, 0x28, 0x65, 0x60, 0x56, 0xbd, 0x75, 0xdd, 0xa5, 0xa3, 0xa7, + 0xba, 0x49, 0x0a, 0x70, 0x39, 0x50, 0xc3, 0x51, 0xcb, 0x29, 0x4e, 0xd7, + 0x37, 0x7e, 0x73, 0xc1, 0x70, 0x9f +}; +/* k = 0000062d295aa4294802636682b2a5b59b30fe637e7d462f34752dc93de */ +static const uint8_t nist_186_2_ecdsa_testvector_169_out[] = { +/* R - byte alignment */ + 0x00, 0x72, 0x10, 0xe8, 0xe4, 0x8e, 0xff, 0xca, 0xfd, 0xa6, 0x87, 0x04, + 0xdd, 0xc2, 0x1c, 0x23, 0x58, 0x9a, 0x8d, 0x8e, 0xfd, 0x32, 0xad, 0x67, + 0x8f, 0x4f, 0x7b, 0x05, 0xbd, 0xc6, +/* S - byte alignment */ + 0x00, 0xc8, 0x8a, 0x70, 0xc6, 0x61, 0x5e, 0xb3, 0x5a, 0x90, 0xe3, 0xe0, + 0x22, 0xcf, 0x96, 0x6c, 0x5b, 0x09, 0x4f, 0x5f, 0x74, 0x8b, 0x9b, 0xbb, + 0x55, 0x67, 0x75, 0x10, 0x1e, 0x0e +}; +static const uint8_t nist_186_2_ecdsa_testvector_170_ptx[] = { +/* Msg */ + 0x0d, 0xcd, 0xe4, 0x4a, 0x0c, 0x16, 0x75, 0x8f, 0x8b, 0xee, 0x34, 0xc5, + 0xda, 0x6f, 0x9e, 0xfa, 0x1a, 0x4d, 0x6c, 0x9b, 0x5b, 0x66, 0xd0, 0x9f, + 0x01, 0x9b, 0xfb, 0x02, 0x6c, 0xdf, 0xe2, 0x75, 0xd8, 0x8d, 0x42, 0x54, + 0x81, 0xff, 0xe1, 0xd8, 0x0b, 0x5c, 0x18, 0x8e, 0x22, 0xb1, 0x8e, 0x07, + 0x5e, 0x44, 0x46, 0xd1, 0x69, 0x25, 0xdc, 0xa7, 0x63, 0x05, 0x0b, 0xe5, + 0x85, 0x4b, 0x73, 0x3f, 0x05, 0x65, 0x99, 0xb1, 0x3a, 0x5c, 0x30, 0xb9, + 0x01, 0xac, 0x97, 0xc5, 0x5f, 0x52, 0xa2, 0xe7, 0x68, 0x26, 0x9d, 0xd0, + 0x5f, 0x6b, 0x8e, 0xfc, 0x1e, 0xa5, 0xbb, 0x2a, 0xb8, 0xaa, 0x6c, 0x0f, + 0x5e, 0xfc, 0xf2, 0x4b, 0x7f, 0x56, 0xe8, 0x9c, 0x33, 0x85, 0xb9, 0x52, + 0xda, 0x79, 0x63, 0x03, 0x00, 0x9c, 0x7a, 0x7f, 0x85, 0x63, 0x6f, 0x06, + 0xfa, 0x22, 0x12, 0xb9, 0x4d, 0x24, 0x56, 0x4f +}; +static const uint8_t nist_186_2_ecdsa_testvector_170_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xac, 0x9c, 0xfc, 0x36, 0xde, 0x28, 0x04, 0xc8, 0x07, + 0x16, 0xbe, 0xf7, 0xcb, 0x64, 0xe8, 0x6f, 0xd2, 0xbd, 0x10, 0xe2, 0xe2, + 0xa3, 0xff, 0x75, 0xeb, 0x3d, 0x3b +}; +static const uint8_t nist_186_2_ecdsa_testvector_170_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xa9, 0xc5, 0xd9, 0x6b, 0x46, 0xf6, 0xa3, 0x58, 0xd2, 0x57, 0xb1, + 0x73, 0x18, 0x61, 0x0a, 0xc3, 0xbc, 0x03, 0xd6, 0x54, 0xe3, 0x50, 0x86, + 0x9e, 0xae, 0xb5, 0x22, 0xc6, 0x2d +}; +static const uint8_t nist_186_2_ecdsa_testvector_170_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xef, 0xe9, 0x12, 0x9c, 0x74, 0xf9, 0xf0, 0x6c, 0xc4, 0x85, 0xff, + 0x93, 0x1a, 0x94, 0x30, 0x2f, 0x47, 0xa3, 0xbd, 0x19, 0x03, 0x5f, 0xf9, + 0x84, 0xe1, 0x56, 0x47, 0x11, 0xcb +}; +/* k = 000009e397d554cac46643884ae3fb87110f2e58d9106ed66b23dd901d5 */ +static const uint8_t nist_186_2_ecdsa_testvector_170_out[] = { +/* R - byte alignment */ + 0x00, 0x11, 0x9f, 0xb2, 0xff, 0xfc, 0x19, 0xf6, 0x78, 0x2b, 0xd3, 0x44, + 0x59, 0x61, 0x87, 0xbe, 0x6b, 0xaf, 0x1d, 0x7f, 0x98, 0x22, 0x80, 0xe7, + 0x1b, 0x86, 0x62, 0x31, 0x30, 0x16, +/* S - byte alignment */ + 0x00, 0xce, 0xac, 0x24, 0x8e, 0x4b, 0x31, 0xc3, 0x64, 0x08, 0xe1, 0xc8, + 0xbf, 0x3f, 0x63, 0x4d, 0xb5, 0xa5, 0xf5, 0xaf, 0x3d, 0x98, 0x94, 0x5b, + 0xa2, 0x53, 0x7d, 0x08, 0x8e, 0xcc +}; +static const uint8_t nist_186_2_ecdsa_testvector_171_ptx[] = { +/* Msg */ + 0x37, 0x92, 0x8d, 0x29, 0x9f, 0x8b, 0x4d, 0x25, 0x32, 0x80, 0xa3, 0xc7, + 0xa3, 0x69, 0x74, 0xeb, 0xad, 0x24, 0xfb, 0x75, 0xf9, 0xc4, 0xc8, 0x40, + 0x42, 0x2d, 0x08, 0x57, 0xb7, 0xde, 0x06, 0x68, 0xa1, 0x0d, 0xf2, 0x75, + 0x45, 0xf9, 0xe2, 0xcd, 0x0c, 0x7c, 0x16, 0x3b, 0xe1, 0xdf, 0x80, 0x7d, + 0xdb, 0xf3, 0x83, 0xf7, 0x1c, 0x5d, 0xfc, 0xa9, 0xf9, 0x32, 0x7f, 0x5f, + 0x5b, 0xc4, 0xe3, 0x27, 0x64, 0xbb, 0x00, 0x08, 0x56, 0x67, 0xb7, 0xf1, + 0xb1, 0x54, 0x33, 0xf0, 0x9c, 0x1f, 0x6f, 0xa4, 0x86, 0x89, 0xf8, 0xf5, + 0x0d, 0xca, 0xf5, 0x02, 0x1f, 0x28, 0x64, 0x5b, 0x5f, 0xc7, 0xa6, 0x71, + 0xca, 0xc3, 0x3e, 0x4b, 0x9a, 0x7c, 0xd6, 0x7a, 0x6a, 0x31, 0x82, 0x4e, + 0x9c, 0xd1, 0x49, 0x4a, 0xf8, 0x0d, 0xe2, 0xd6, 0x95, 0xb2, 0xbb, 0x34, + 0xfd, 0x36, 0x40, 0xb5, 0x8c, 0x90, 0x59, 0x2d +}; +static const uint8_t nist_186_2_ecdsa_testvector_171_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x45, 0xae, 0x3c, 0x55, 0x41, 0xfd, 0x4a, 0xba, 0xb4, + 0xa3, 0x2b, 0xc5, 0xb3, 0x59, 0x20, 0x51, 0x3c, 0x74, 0xce, 0x8b, 0xf9, + 0xd5, 0xd9, 0x6e, 0x30, 0x5a, 0xd8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_171_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xb4, 0xb2, 0xc4, 0xdd, 0x07, 0x8a, 0xc1, 0x7b, 0x2f, 0x84, 0x08, + 0x9a, 0x9a, 0xd4, 0x78, 0x80, 0x9f, 0x3a, 0x14, 0x53, 0x06, 0x81, 0xb0, + 0xcc, 0xdc, 0xea, 0xa9, 0x4b, 0x56 +}; +static const uint8_t nist_186_2_ecdsa_testvector_171_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xa5, 0x0c, 0x5f, 0xde, 0xd7, 0xdb, 0xc9, 0x82, 0xfe, 0x90, 0x40, + 0x33, 0xa6, 0xef, 0xa0, 0xf7, 0xb8, 0xb8, 0x13, 0x3c, 0xa9, 0x1d, 0xc7, + 0x8b, 0xc8, 0x19, 0xb8, 0xe6, 0x3f +}; +/* k = 0000002bc8d93e325751d5dbbe2383c74faafa4087c33bbc421a61f046a */ +static const uint8_t nist_186_2_ecdsa_testvector_171_out[] = { +/* R - byte alignment */ + 0x00, 0x68, 0xdf, 0x21, 0x6e, 0xe2, 0xb1, 0xe6, 0x92, 0xe3, 0xcf, 0xac, + 0x3f, 0x66, 0x52, 0xa7, 0xdf, 0xcc, 0xf0, 0x13, 0x2d, 0x52, 0x41, 0xe5, + 0xf0, 0x8d, 0x2c, 0xe3, 0xf5, 0x62, +/* S - byte alignment */ + 0x00, 0x44, 0xfa, 0xd1, 0xed, 0x97, 0x12, 0x9a, 0xa6, 0x93, 0xcd, 0xfe, + 0x1a, 0xc9, 0x60, 0xb7, 0xed, 0x15, 0xec, 0x3b, 0x4f, 0xd0, 0xcf, 0xb4, + 0x5b, 0x96, 0xab, 0x8a, 0x0a, 0xeb +}; +static const uint8_t nist_186_2_ecdsa_testvector_172_ptx[] = { +/* Msg */ + 0xa7, 0x72, 0xdd, 0xe5, 0xe6, 0xc9, 0xdf, 0x0e, 0x19, 0x60, 0xc9, 0x87, + 0x4f, 0x1a, 0xc0, 0x6a, 0x89, 0x07, 0x69, 0x5f, 0x1c, 0x37, 0x64, 0x12, + 0x56, 0xcc, 0x16, 0xe5, 0x64, 0x53, 0xac, 0xe2, 0x73, 0x55, 0x5c, 0xf3, + 0x16, 0x28, 0xee, 0x55, 0xe8, 0x0b, 0x7c, 0x4a, 0x72, 0x73, 0x76, 0x0e, + 0x4f, 0x9f, 0xe8, 0x0d, 0x8d, 0x72, 0x00, 0x53, 0x57, 0x82, 0xcb, 0x44, + 0xd1, 0x6d, 0x3f, 0x8d, 0x44, 0x6c, 0x7e, 0x5a, 0x7b, 0x2a, 0x59, 0xca, + 0x6d, 0xd6, 0x13, 0x9f, 0x1c, 0x76, 0x68, 0x3b, 0xbc, 0x7f, 0xce, 0xc8, + 0x18, 0xa3, 0xfb, 0xb6, 0x32, 0xeb, 0xa7, 0x6a, 0x29, 0x05, 0x93, 0x34, + 0x60, 0xdf, 0xca, 0x82, 0xdd, 0x75, 0x27, 0x54, 0xef, 0xe7, 0x17, 0xf0, + 0x14, 0xce, 0xa0, 0xd7, 0x19, 0xd0, 0xa3, 0xf7, 0x83, 0x72, 0x5e, 0x22, + 0x2e, 0x2e, 0x34, 0xbf, 0x34, 0xc6, 0xb1, 0xc0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_172_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x11, 0x43, 0xbe, 0x2c, 0x59, 0x9d, 0x6b, 0xb5, 0x81, + 0xe9, 0x88, 0xa5, 0xa2, 0x7b, 0xeb, 0x8f, 0x2f, 0xe8, 0x95, 0x8c, 0x5d, + 0x33, 0x80, 0xe9, 0x15, 0x33, 0x0e +}; +static const uint8_t nist_186_2_ecdsa_testvector_172_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xfa, 0xe6, 0x45, 0x98, 0x83, 0x06, 0xe8, 0x2c, 0x47, 0xdf, 0x92, + 0xf4, 0xba, 0x5d, 0x3a, 0xd8, 0x05, 0xe6, 0x94, 0x93, 0x69, 0xd3, 0x02, + 0x96, 0xac, 0x0a, 0x16, 0x20, 0x52 +}; +static const uint8_t nist_186_2_ecdsa_testvector_172_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x47, 0x9b, 0x9a, 0xd3, 0x7a, 0xd3, 0xba, 0xea, 0x5d, 0xaa, 0x6e, + 0x5e, 0x1d, 0xdf, 0x8e, 0x22, 0x8c, 0x03, 0x14, 0xe6, 0x97, 0x2e, 0xd5, + 0x28, 0xeb, 0xca, 0xc5, 0x1d, 0xdb +}; +/* k = 000000bbcddc5a72df1abd6186f85ccec9426d11995f5fe0de315afff86 */ +static const uint8_t nist_186_2_ecdsa_testvector_172_out[] = { +/* R - byte alignment */ + 0x00, 0x12, 0x68, 0xce, 0xe2, 0xf2, 0x5e, 0x98, 0xb5, 0x2b, 0xe0, 0xeb, + 0xda, 0xb3, 0x0e, 0x09, 0xdb, 0x73, 0x54, 0xd8, 0x86, 0xdb, 0x55, 0xb9, + 0x84, 0x28, 0x27, 0x9b, 0xd1, 0xc1, +/* S - byte alignment */ + 0x00, 0x79, 0x77, 0x6e, 0xcf, 0xdc, 0x94, 0x51, 0xe2, 0x5b, 0x93, 0x67, + 0x6b, 0x04, 0xfd, 0xf4, 0x1d, 0xdf, 0x7d, 0xb5, 0xb4, 0x5d, 0xea, 0x3c, + 0x26, 0x9a, 0x23, 0xf9, 0xb4, 0x47 +}; +static const uint8_t nist_186_2_ecdsa_testvector_173_ptx[] = { +/* Msg */ + 0x97, 0xfe, 0x91, 0x73, 0x2b, 0x56, 0x8c, 0xb9, 0xf6, 0x65, 0x57, 0xb0, + 0x4a, 0xfd, 0x0d, 0x58, 0x37, 0xc7, 0x41, 0x44, 0x14, 0x87, 0x37, 0xfc, + 0x5c, 0xa1, 0x54, 0xa1, 0xbc, 0xdd, 0xd4, 0xcf, 0x69, 0x67, 0xbb, 0xc7, + 0xb7, 0x1a, 0x0e, 0xce, 0xe8, 0xfd, 0x42, 0xd0, 0x41, 0x0e, 0xf5, 0x49, + 0x64, 0x3f, 0xdc, 0x66, 0xd9, 0xbf, 0xfd, 0x67, 0xee, 0x7a, 0x1e, 0x47, + 0xc1, 0xe3, 0x7d, 0x9f, 0x9b, 0xf1, 0xc1, 0xc8, 0x7f, 0x67, 0x31, 0x3f, + 0x03, 0x59, 0x24, 0x4e, 0x5f, 0xec, 0xb8, 0xe9, 0xc4, 0x5d, 0xc7, 0xd7, + 0xef, 0x45, 0x17, 0x12, 0xfd, 0x1b, 0xd1, 0x6f, 0x81, 0xfa, 0x35, 0x81, + 0xd4, 0xa4, 0x8b, 0xbb, 0xac, 0xc8, 0x5d, 0xd6, 0xf0, 0x80, 0xe3, 0x72, + 0xcb, 0x1e, 0xbf, 0x00, 0x00, 0x28, 0xeb, 0xdf, 0x7d, 0xa1, 0xef, 0xc5, + 0x32, 0x8a, 0x57, 0x61, 0x23, 0xa9, 0x64, 0x3f +}; +static const uint8_t nist_186_2_ecdsa_testvector_173_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x1f, 0x73, 0x5a, 0x6c, 0x43, 0x4a, 0xe8, 0x0a, 0xed, + 0x64, 0x42, 0x43, 0x8b, 0x46, 0xe4, 0x24, 0x16, 0x19, 0xc7, 0x81, 0x27, + 0x81, 0x1c, 0x4a, 0x01, 0xe4, 0x78 +}; +static const uint8_t nist_186_2_ecdsa_testvector_173_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xa9, 0xe2, 0x95, 0x86, 0xe5, 0x67, 0xff, 0x7e, 0xd1, 0xfd, 0x86, + 0x63, 0xf0, 0xa3, 0x2b, 0x01, 0x1d, 0x94, 0xf2, 0xbe, 0x69, 0xe5, 0xbb, + 0xb3, 0x88, 0x7b, 0xec, 0x8f, 0x66 +}; +static const uint8_t nist_186_2_ecdsa_testvector_173_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xa4, 0xea, 0x53, 0xc8, 0x6c, 0x27, 0x04, 0xc0, 0x13, 0x95, 0xf5, + 0x8f, 0x88, 0x38, 0x8a, 0x7b, 0xa0, 0x39, 0xe1, 0x94, 0x03, 0xad, 0x80, + 0x33, 0xea, 0x09, 0xdd, 0x2e, 0x4a +}; +/* k = 00000642e71d725e137731d250648fd8f5d1aa2bd7da608f08065700242 */ +static const uint8_t nist_186_2_ecdsa_testvector_173_out[] = { +/* R - byte alignment */ + 0x00, 0x7f, 0x00, 0x0c, 0xea, 0x21, 0x71, 0x7b, 0x7e, 0xcf, 0x27, 0x9d, + 0xae, 0xff, 0x07, 0xbc, 0x81, 0x61, 0xfd, 0xaa, 0x79, 0x6b, 0xfa, 0x87, + 0xad, 0x00, 0xeb, 0x08, 0xb6, 0xf1, +/* S - byte alignment */ + 0x00, 0xd2, 0x05, 0x9c, 0xd4, 0xfc, 0x81, 0x4b, 0x4d, 0x0d, 0xa7, 0x1d, + 0xa5, 0x31, 0xa4, 0x7c, 0x72, 0xfa, 0x14, 0x31, 0x6a, 0x67, 0x08, 0xf0, + 0x3b, 0x8b, 0x6b, 0xcc, 0x3e, 0xbb +}; +static const uint8_t nist_186_2_ecdsa_testvector_174_ptx[] = { +/* Msg */ + 0x1e, 0xa6, 0x72, 0x92, 0x99, 0x7e, 0x53, 0xf2, 0xae, 0xe2, 0x7c, 0xc2, + 0xa3, 0x14, 0xef, 0x86, 0x3d, 0xd7, 0x3d, 0x20, 0x25, 0x39, 0x03, 0x44, + 0x90, 0xb0, 0xb5, 0x2d, 0x1f, 0x68, 0x9a, 0x8e, 0x04, 0xdc, 0x18, 0xcc, + 0x67, 0xa4, 0x32, 0x6a, 0x08, 0x8d, 0x4f, 0xc5, 0x25, 0xef, 0x3d, 0x01, + 0x9e, 0x3b, 0x75, 0x43, 0x57, 0xd4, 0xa1, 0x20, 0xde, 0x20, 0x5b, 0x56, + 0x4e, 0xde, 0x38, 0xba, 0x73, 0xba, 0x05, 0x72, 0x2e, 0x1e, 0x50, 0x64, + 0x1b, 0x4c, 0x2b, 0xee, 0x72, 0xaa, 0x2c, 0xd8, 0x2b, 0x5c, 0xb8, 0x87, + 0x66, 0x18, 0x81, 0x73, 0x09, 0x36, 0x4e, 0xdb, 0xab, 0x07, 0xfb, 0xb7, + 0xb1, 0x68, 0xc0, 0xee, 0xb6, 0x97, 0xb6, 0xc9, 0x31, 0x45, 0x96, 0xa7, + 0x51, 0xec, 0xc4, 0xf3, 0x2c, 0x62, 0x8d, 0x54, 0x19, 0xaf, 0xad, 0x23, + 0x5a, 0x1c, 0x15, 0x22, 0xff, 0x8c, 0xeb, 0x6b +}; +static const uint8_t nist_186_2_ecdsa_testvector_174_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xc0, 0x9c, 0x66, 0xf8, 0x94, 0x32, 0xee, 0xe8, 0xf6, + 0x36, 0xb2, 0x32, 0x4a, 0x56, 0x40, 0x68, 0x5f, 0x71, 0xf1, 0x3e, 0x20, + 0x02, 0x0d, 0x46, 0x0b, 0x86, 0x6c +}; +static const uint8_t nist_186_2_ecdsa_testvector_174_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x40, 0x52, 0x34, 0xb9, 0x95, 0x5b, 0xd0, 0xb6, 0xf3, 0x94, 0xc4, + 0x59, 0xec, 0x58, 0xcc, 0xc2, 0xf6, 0x8f, 0x0f, 0x2d, 0x7b, 0x5f, 0xc0, + 0xef, 0x2b, 0x0b, 0x5e, 0xb3, 0xea +}; +static const uint8_t nist_186_2_ecdsa_testvector_174_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x5c, 0xd0, 0x85, 0x77, 0x35, 0x7c, 0x97, 0xa8, 0xb1, 0x86, 0x13, + 0xa2, 0xa2, 0xb7, 0x9d, 0x64, 0x54, 0xe6, 0x54, 0xd0, 0x48, 0xf3, 0x46, + 0xdc, 0x28, 0xef, 0x50, 0x5e, 0x8e +}; +/* k = 000008ce062ed814f46fba5276d2439cd455f6d22aaf77f31dbc4f8a417 */ +static const uint8_t nist_186_2_ecdsa_testvector_174_out[] = { +/* R - byte alignment */ + 0x00, 0xe5, 0xff, 0xd3, 0xda, 0x8d, 0xd8, 0x07, 0x66, 0x9e, 0xac, 0x82, + 0xc5, 0xb8, 0xe9, 0xfc, 0x37, 0x05, 0x5e, 0x18, 0xf3, 0x36, 0x6a, 0x78, + 0xc4, 0x52, 0xa7, 0xf4, 0x5c, 0x68, +/* S - byte alignment */ + 0x00, 0x24, 0xbf, 0xcd, 0x45, 0x8c, 0x67, 0xb6, 0xf2, 0x96, 0x7e, 0x89, + 0xe3, 0x80, 0x37, 0xdf, 0xe4, 0xc1, 0x86, 0xfd, 0xb7, 0xec, 0x75, 0x10, + 0x6f, 0x07, 0x44, 0x5a, 0x2c, 0xcc +}; +static const uint8_t nist_186_2_ecdsa_testvector_175_ptx[] = { +/* Msg */ + 0xfc, 0xb2, 0x9e, 0x64, 0x68, 0x88, 0x12, 0x63, 0x93, 0xcd, 0x32, 0x75, + 0x47, 0x32, 0xba, 0xf4, 0xc4, 0x0a, 0x86, 0xdd, 0x64, 0x59, 0x54, 0x85, + 0x7b, 0x2d, 0xca, 0x87, 0x81, 0x31, 0xbb, 0x01, 0x73, 0x7f, 0xa6, 0x00, + 0x76, 0xb6, 0x7f, 0x38, 0xbe, 0x4c, 0xb2, 0xf9, 0xae, 0x26, 0x66, 0x5e, + 0x40, 0x66, 0xfe, 0xc8, 0xa8, 0x85, 0xe6, 0x8a, 0x34, 0xa1, 0x8c, 0xe6, + 0x77, 0x18, 0xac, 0x39, 0xa6, 0x55, 0xd1, 0x72, 0x42, 0xea, 0x19, 0xc8, + 0xf7, 0xdf, 0x38, 0xad, 0xc5, 0x4a, 0xbf, 0xfd, 0x5d, 0x20, 0x9f, 0x7c, + 0xce, 0x4b, 0xe8, 0x7f, 0x60, 0xfd, 0xd7, 0xe9, 0xc0, 0x43, 0x10, 0x59, + 0x5e, 0xdd, 0x28, 0xa2, 0x14, 0x4d, 0x66, 0x7c, 0x08, 0x2e, 0xcb, 0x79, + 0xd3, 0xc7, 0x4f, 0x3a, 0xe3, 0xe0, 0x6e, 0xe2, 0x1d, 0xd4, 0xe3, 0xcb, + 0xc7, 0xe8, 0xb4, 0x78, 0xa6, 0xdb, 0x6e, 0xcb +}; +static const uint8_t nist_186_2_ecdsa_testvector_175_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xdc, 0xa4, 0x78, 0xf7, 0xf5, 0xa5, 0xbe, 0x46, 0xb4, + 0x07, 0x0c, 0x9f, 0x22, 0x97, 0xe8, 0x0c, 0x3d, 0x7c, 0xd1, 0x06, 0x31, + 0xc0, 0x25, 0x9e, 0xc4, 0xaa, 0x83 +}; +static const uint8_t nist_186_2_ecdsa_testvector_175_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x19, 0xd3, 0x90, 0xa8, 0x6e, 0x98, 0xd1, 0x3b, 0x47, 0xd4, 0x6b, + 0xea, 0x13, 0xd0, 0x98, 0xd0, 0x4f, 0xd1, 0x81, 0xf1, 0x48, 0x5f, 0xc3, + 0x7c, 0xc1, 0x8c, 0x92, 0xd3, 0xca +}; +static const uint8_t nist_186_2_ecdsa_testvector_175_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x11, 0xa6, 0x6a, 0xff, 0x04, 0x27, 0x38, 0x16, 0x3d, 0x0a, 0x7e, + 0x89, 0x55, 0x5b, 0x5c, 0xf4, 0x19, 0x30, 0x34, 0xc4, 0x17, 0xe6, 0x48, + 0x6f, 0xc0, 0xff, 0x41, 0xf8, 0x43 +}; +/* k = 000000720c7f812ae1b94da84b4c6f206a253692e7a9da1a4e0ba7115b6 */ +static const uint8_t nist_186_2_ecdsa_testvector_175_out[] = { +/* R - byte alignment */ + 0x00, 0xa3, 0x33, 0x48, 0xc7, 0xbf, 0x63, 0xd7, 0x24, 0x22, 0x7e, 0x09, + 0x65, 0x15, 0x2f, 0x31, 0xca, 0x4c, 0xc1, 0x06, 0x5b, 0x1d, 0x76, 0x22, + 0x60, 0x94, 0x23, 0xd0, 0xda, 0xa4, +/* S - byte alignment */ + 0x00, 0x3e, 0xbd, 0x07, 0x20, 0x45, 0x41, 0x66, 0xed, 0x6f, 0x04, 0xbf, + 0x32, 0x15, 0x3a, 0xf1, 0xa8, 0xd7, 0x60, 0xad, 0x1c, 0x98, 0x97, 0xa6, + 0xd1, 0x93, 0x54, 0xd1, 0xc6, 0x0f +}; +static const uint8_t nist_186_2_ecdsa_testvector_176_ptx[] = { +/* Msg */ + 0x19, 0x35, 0xf9, 0x50, 0x92, 0x66, 0xce, 0xda, 0x1e, 0x89, 0x53, 0xc4, + 0x35, 0x03, 0xe8, 0x3d, 0x5d, 0x13, 0x5e, 0x28, 0xfb, 0x5b, 0x63, 0xc2, + 0x69, 0x9c, 0x41, 0x86, 0x48, 0xc1, 0xc9, 0x4e, 0x18, 0x1f, 0x89, 0xba, + 0x06, 0xfb, 0x46, 0xd5, 0x04, 0x4c, 0xa6, 0xf6, 0x1f, 0xc3, 0x2c, 0xe5, + 0x0d, 0x09, 0x69, 0x3f, 0x06, 0x48, 0x71, 0x1c, 0xd6, 0xec, 0x8d, 0xee, + 0x2f, 0xab, 0x2f, 0xad, 0x43, 0xc2, 0x2b, 0x31, 0x92, 0x82, 0x23, 0xdf, + 0x01, 0x0c, 0x43, 0x87, 0x2d, 0x59, 0x2f, 0x8d, 0xfe, 0x7d, 0x3a, 0x47, + 0x7f, 0x2c, 0xd9, 0xa7, 0xed, 0x7d, 0x57, 0x1a, 0x0e, 0xee, 0xca, 0xaf, + 0xc3, 0xa8, 0x45, 0x7c, 0xe1, 0x05, 0x4f, 0x3e, 0x3d, 0x50, 0x94, 0x3f, + 0x06, 0xcc, 0xdb, 0x7d, 0x58, 0xf7, 0x38, 0x08, 0x0d, 0x0f, 0x83, 0xac, + 0xd7, 0xd6, 0x08, 0xd0, 0x8c, 0x93, 0x80, 0x9e +}; +static const uint8_t nist_186_2_ecdsa_testvector_176_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xf7, 0x7c, 0x1d, 0x84, 0x93, 0x2b, 0xd0, 0xe8, 0x87, + 0x84, 0xac, 0x00, 0xf6, 0x07, 0xe0, 0x35, 0xb2, 0xb8, 0x51, 0x6e, 0xbc, + 0xe8, 0xd2, 0x83, 0xfd, 0xf9, 0x1b +}; +static const uint8_t nist_186_2_ecdsa_testvector_176_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x5e, 0x55, 0x9e, 0x4a, 0x07, 0xb1, 0x46, 0xb4, 0x94, 0x02, 0x4d, + 0xd9, 0x9f, 0x95, 0x95, 0xd1, 0x48, 0xd8, 0x3f, 0xd4, 0x66, 0x65, 0x65, + 0x6c, 0xc2, 0x14, 0x8b, 0x32, 0x8b +}; +static const uint8_t nist_186_2_ecdsa_testvector_176_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x75, 0xea, 0x9f, 0x8e, 0xed, 0xd0, 0x1a, 0xea, 0xab, 0xfe, 0x81, + 0x00, 0x95, 0x28, 0x88, 0xf0, 0x50, 0xb6, 0x99, 0x6a, 0x9a, 0xab, 0x65, + 0x1b, 0x50, 0x11, 0x4f, 0xee, 0xa7 +}; +/* k = 000006f702f3b453551bd67d4414e5604f4a48382890ead5efea1a4d747 */ +static const uint8_t nist_186_2_ecdsa_testvector_176_out[] = { +/* R - byte alignment */ + 0x00, 0x43, 0xc0, 0x93, 0x0b, 0x46, 0x2d, 0x98, 0x76, 0xf8, 0xb6, 0x09, + 0x86, 0x6a, 0xa3, 0x1d, 0x86, 0x0d, 0x89, 0xff, 0x38, 0xce, 0xd0, 0x97, + 0x76, 0x11, 0x4b, 0xde, 0x23, 0x20, +/* S - byte alignment */ + 0x00, 0x76, 0x64, 0x90, 0xc3, 0xd0, 0xed, 0x29, 0x92, 0xf4, 0x52, 0xd4, + 0xc8, 0x6f, 0x3c, 0x35, 0x80, 0xf3, 0x8b, 0xa4, 0xd5, 0xd1, 0xf5, 0x18, + 0xa4, 0xe1, 0x52, 0xd0, 0x12, 0xf1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_177_ptx[] = { +/* Msg */ + 0x52, 0xe1, 0xf6, 0x5d, 0x62, 0x18, 0x54, 0x76, 0xba, 0x62, 0xbf, 0x9b, + 0x5e, 0x83, 0x7a, 0x50, 0xcd, 0xca, 0x27, 0x00, 0xd8, 0x97, 0x3a, 0x9f, + 0xb3, 0x1a, 0xad, 0x8e, 0x4d, 0x5d, 0xf6, 0xbf, 0xdd, 0x85, 0x36, 0x19, + 0xbd, 0x55, 0xb3, 0x1e, 0x7c, 0xf3, 0x88, 0xcb, 0x2f, 0xef, 0x9b, 0xbf, + 0x07, 0x81, 0xd0, 0xa0, 0x29, 0x12, 0x7c, 0xbb, 0xb9, 0xfe, 0x1d, 0xea, + 0x38, 0x99, 0x48, 0xbb, 0x11, 0x70, 0xe2, 0xce, 0x6e, 0xd1, 0x93, 0x7f, + 0x50, 0x8d, 0x78, 0xc5, 0xdf, 0xfc, 0x18, 0x5a, 0xff, 0x42, 0x9a, 0x1d, + 0x23, 0xd1, 0x35, 0xb4, 0x66, 0x2f, 0xe7, 0x75, 0xd8, 0xfa, 0x6a, 0x87, + 0x15, 0x29, 0x64, 0x44, 0x1d, 0x94, 0xde, 0xe2, 0x5f, 0xb7, 0xf7, 0x53, + 0x17, 0xb2, 0xd9, 0x69, 0xda, 0x95, 0xed, 0x3e, 0x6f, 0xdb, 0x4b, 0xd3, + 0xe1, 0x34, 0x75, 0xf7, 0xd2, 0x88, 0x44, 0x6b +}; +static const uint8_t nist_186_2_ecdsa_testvector_177_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xb7, 0x16, 0x9e, 0xfc, 0xe7, 0x77, 0x48, 0x43, 0x04, + 0x4a, 0xc9, 0x8a, 0x9f, 0xc8, 0x94, 0x10, 0xf0, 0xa6, 0x98, 0x96, 0x83, + 0x6a, 0x8c, 0x4e, 0xd0, 0xa9, 0x4c +}; +static const uint8_t nist_186_2_ecdsa_testvector_177_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xba, 0x0d, 0xac, 0xef, 0x4d, 0x48, 0x32, 0x53, 0x42, 0xe9, 0x94, + 0xa3, 0xfb, 0x7a, 0xc5, 0x49, 0x79, 0xda, 0x27, 0x35, 0x27, 0x2c, 0x38, + 0x64, 0xa4, 0x42, 0x63, 0x6f, 0xd2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_177_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x3d, 0x8c, 0x12, 0x74, 0xce, 0xf3, 0x6b, 0xb3, 0xe1, 0x72, 0x77, + 0x3a, 0xb5, 0x2d, 0xbb, 0x33, 0xbc, 0xfc, 0xb9, 0xd4, 0xf5, 0x0c, 0x89, + 0xf5, 0x9f, 0xa2, 0x96, 0x6d, 0x1a +}; +/* k = 0000029215f5e7f6dd5fe45200b03952e76b3af952d7622e7d05eef86c8 */ +static const uint8_t nist_186_2_ecdsa_testvector_177_out[] = { +/* R - byte alignment */ + 0x00, 0xd5, 0xc7, 0x02, 0xb0, 0x43, 0xea, 0xf7, 0xb5, 0xa8, 0x31, 0x86, + 0x8e, 0xcb, 0xde, 0x23, 0x4e, 0xc1, 0x0f, 0x78, 0x72, 0x2e, 0xcc, 0x46, + 0x62, 0x42, 0xa9, 0xda, 0x42, 0x29, +/* S - byte alignment */ + 0x00, 0x36, 0x5b, 0x0f, 0x55, 0xb7, 0x90, 0xf9, 0xe9, 0xd3, 0x4d, 0x3c, + 0x78, 0xa3, 0x1c, 0x27, 0x96, 0x16, 0xf2, 0xf5, 0x75, 0xcf, 0x68, 0x84, + 0x4e, 0x7d, 0xd8, 0xe7, 0xc7, 0xb7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_178_ptx[] = { +/* Msg */ + 0x83, 0x69, 0xf3, 0xd5, 0x21, 0x18, 0x8d, 0x4e, 0x1b, 0x38, 0x47, 0x18, + 0x1e, 0x51, 0xd5, 0x1e, 0x32, 0xda, 0x25, 0xaf, 0x40, 0xac, 0xfa, 0x8d, + 0xd2, 0xb7, 0xd7, 0x40, 0x1b, 0xf4, 0x1e, 0xb0, 0x37, 0x9a, 0x79, 0xf3, + 0xb4, 0x95, 0x79, 0x64, 0x50, 0x34, 0x7d, 0xf5, 0x04, 0x22, 0xd6, 0xc6, + 0x42, 0x97, 0x28, 0xf6, 0x7c, 0xcf, 0x13, 0xb9, 0xe5, 0xbc, 0x13, 0xaa, + 0x7b, 0xf8, 0xa5, 0x63, 0x45, 0xfd, 0xac, 0x4b, 0xd9, 0x98, 0x12, 0xb0, + 0x22, 0x9b, 0xb2, 0x16, 0x60, 0xd3, 0x76, 0xce, 0x70, 0x39, 0xbc, 0xca, + 0x4e, 0x6c, 0xff, 0xaf, 0xd8, 0x5f, 0xb3, 0x2c, 0xd5, 0x4f, 0x70, 0x8b, + 0x35, 0xf9, 0x53, 0x85, 0x9a, 0x09, 0xa2, 0x5b, 0x18, 0xd5, 0xae, 0x22, + 0x39, 0x4b, 0xfe, 0x5e, 0x45, 0x28, 0xa9, 0xd3, 0xc0, 0x6c, 0x04, 0x98, + 0x33, 0x0a, 0x7d, 0x6d, 0x30, 0xe3, 0xc7, 0x4e +}; +static const uint8_t nist_186_2_ecdsa_testvector_178_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xb5, 0x3d, 0x07, 0xd9, 0xde, 0xd1, 0x2e, 0xf7, 0x22, + 0x3e, 0x5a, 0xd3, 0x0f, 0xea, 0x81, 0xa5, 0x42, 0x50, 0x27, 0x7c, 0xa7, + 0xb1, 0x4e, 0x39, 0xd7, 0xf7, 0x0f +}; +static const uint8_t nist_186_2_ecdsa_testvector_178_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xae, 0x55, 0x28, 0x58, 0xd6, 0x30, 0x0b, 0x9b, 0xf2, 0x07, 0x11, + 0xca, 0xde, 0x4d, 0xb4, 0x7c, 0x70, 0xdb, 0x9a, 0x1c, 0x65, 0x88, 0xdb, + 0xc6, 0xe7, 0x2d, 0x8d, 0xe1, 0x85 +}; +static const uint8_t nist_186_2_ecdsa_testvector_178_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xcf, 0xdb, 0x85, 0xf3, 0xea, 0xf4, 0xa9, 0x51, 0xd8, 0x37, 0xf5, + 0x51, 0xac, 0x09, 0xdb, 0x28, 0xc4, 0x68, 0x7b, 0x00, 0x4d, 0x1f, 0x16, + 0x95, 0x20, 0xbf, 0xcf, 0xc5, 0xa4 +}; +/* k = 00000980235bd756979641956e695fc5152b88d3f279e95b0e3ffb786cb */ +static const uint8_t nist_186_2_ecdsa_testvector_178_out[] = { +/* R - byte alignment */ + 0x00, 0xa0, 0xaf, 0x0e, 0xab, 0x40, 0x12, 0xf8, 0x13, 0x40, 0x8b, 0x3b, + 0x13, 0x6e, 0xe4, 0xd2, 0x39, 0x7f, 0x28, 0x6b, 0x5c, 0xf0, 0x7a, 0xbf, + 0x6d, 0xf7, 0xd6, 0x6e, 0x5f, 0xd7, +/* S - byte alignment */ + 0x00, 0xae, 0xdf, 0x9e, 0xd2, 0xf6, 0x6b, 0xe4, 0x79, 0x60, 0x29, 0xdb, + 0x91, 0xc9, 0x67, 0xbf, 0xcd, 0xb8, 0x1e, 0x2d, 0x3a, 0x59, 0x94, 0xd2, + 0x82, 0x91, 0x84, 0x6f, 0xbb, 0xa1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_179_ptx[] = { +/* Msg */ + 0x06, 0xd5, 0x53, 0x4b, 0x77, 0x69, 0x25, 0x6e, 0x8c, 0xf6, 0x5c, 0x6c, + 0xe5, 0x2a, 0x3e, 0x86, 0x96, 0x5a, 0x1f, 0xd1, 0x2c, 0x75, 0x82, 0xd2, + 0xeb, 0x36, 0x82, 0x4a, 0x5a, 0x9d, 0x70, 0x53, 0x02, 0x9f, 0xbe, 0xac, + 0x72, 0x1d, 0x1b, 0x52, 0x86, 0x13, 0xe0, 0x50, 0xe9, 0x12, 0xab, 0xd7, + 0xd9, 0xf0, 0x49, 0x91, 0x2a, 0xbe, 0xda, 0x33, 0x8e, 0xfa, 0x2f, 0x52, + 0x13, 0x06, 0x77, 0x77, 0xed, 0xd9, 0x1b, 0x75, 0x76, 0xf5, 0xe6, 0xfa, + 0x73, 0x98, 0x69, 0x65, 0x99, 0x37, 0x9e, 0xd7, 0x50, 0x28, 0xcb, 0x8d, + 0xb6, 0x9f, 0xa9, 0x6d, 0xe7, 0xdb, 0xc6, 0xde, 0x7c, 0xa1, 0x28, 0xdd, + 0x51, 0xea, 0x33, 0x4e, 0x8c, 0xd9, 0xcd, 0x8f, 0xda, 0xef, 0xbf, 0x53, + 0xfc, 0x82, 0x5e, 0xae, 0x83, 0x6b, 0x6c, 0x6c, 0xd7, 0x00, 0x39, 0xa7, + 0x7e, 0x42, 0x0d, 0x99, 0x9b, 0x57, 0xca, 0xae +}; +static const uint8_t nist_186_2_ecdsa_testvector_179_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0xe1, 0xa5, 0x11, 0xbf, 0x74, 0xa9, 0xf8, 0x2d, 0x2e, + 0xe3, 0x1a, 0x75, 0x0d, 0x64, 0x2d, 0x62, 0x0d, 0x9d, 0x0d, 0x1e, 0x13, + 0xb2, 0xfd, 0xcf, 0xf9, 0xa7, 0xa8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_179_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x90, 0x94, 0x29, 0x95, 0x53, 0x21, 0xe4, 0x27, 0xd9, 0x3a, 0x52, + 0xa1, 0x16, 0x38, 0xc0, 0x45, 0x4c, 0x85, 0x5e, 0xba, 0xa5, 0xc0, 0xb3, + 0x3e, 0x0e, 0x04, 0x11, 0x32, 0x17 +}; +static const uint8_t nist_186_2_ecdsa_testvector_179_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x2a, 0xbb, 0x5f, 0x53, 0xa0, 0x78, 0x46, 0xbb, 0x88, 0x8a, 0xec, + 0x61, 0x1b, 0xce, 0x88, 0x35, 0xeb, 0x4b, 0x36, 0xfd, 0xe6, 0x9a, 0x7e, + 0x9d, 0xd9, 0xe6, 0xfa, 0x89, 0xed +}; +/* k = 000001c22bc25286ee5b895d61d834780e4fa197cf90f3003cb60e79514 */ +static const uint8_t nist_186_2_ecdsa_testvector_179_out[] = { +/* R - byte alignment */ + 0x00, 0x0b, 0x8e, 0x42, 0xc1, 0x39, 0xa9, 0xf1, 0xd8, 0x6b, 0x67, 0x24, + 0xac, 0x62, 0xbc, 0x4d, 0xac, 0xc7, 0x9a, 0x85, 0xd9, 0xc0, 0x84, 0xca, + 0xbb, 0x99, 0xc5, 0xf7, 0xa2, 0x59, +/* S - byte alignment */ + 0x00, 0xfa, 0x52, 0x3a, 0x97, 0xe8, 0x53, 0x5e, 0xa1, 0x08, 0x45, 0x4b, + 0xca, 0x9f, 0xe4, 0x8b, 0xc1, 0xc6, 0xb6, 0x55, 0x9e, 0x3c, 0x97, 0x58, + 0x76, 0x59, 0x4b, 0xdb, 0x62, 0xdc +}; +static const uint8_t nist_186_2_ecdsa_testvector_180_ptx[] = { +/* Msg */ + 0xa7, 0xa2, 0x2d, 0x03, 0x51, 0x6d, 0xb5, 0xf6, 0x16, 0x7f, 0x9a, 0x32, + 0xdf, 0xec, 0x35, 0xff, 0xe0, 0xee, 0x66, 0x0a, 0x25, 0x2a, 0xcd, 0xc3, + 0x6e, 0x34, 0x3d, 0x04, 0x3d, 0x56, 0x6d, 0xf3, 0x2d, 0x8d, 0xf1, 0x29, + 0x85, 0xd5, 0x69, 0x14, 0x0d, 0xa6, 0xf9, 0x99, 0x21, 0xbf, 0xf9, 0xfe, + 0x03, 0x22, 0xed, 0x08, 0x76, 0x60, 0xb7, 0x60, 0x88, 0x16, 0x0b, 0x3b, + 0xaf, 0xb8, 0x24, 0x3a, 0x17, 0x8d, 0xb5, 0x8f, 0x3b, 0xfb, 0x23, 0x62, + 0xb3, 0x05, 0xf1, 0x73, 0x4c, 0x12, 0x7c, 0x00, 0x5e, 0xf0, 0xe8, 0xe9, + 0x5a, 0x18, 0x5a, 0x12, 0xa3, 0x34, 0x67, 0x09, 0x9f, 0xde, 0xcd, 0xe9, + 0x0d, 0xab, 0x61, 0x7e, 0x99, 0x68, 0x49, 0xa9, 0xad, 0xa3, 0x6b, 0x06, + 0x8b, 0x6e, 0x25, 0xcd, 0x99, 0x5f, 0x3f, 0xf6, 0xfb, 0xdb, 0x1e, 0xa1, + 0x67, 0x94, 0x3a, 0xb4, 0x35, 0x51, 0xd2, 0xc6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_180_private[] = { +/* d - byte alignment */ + 0x00, 0x00, 0x00, 0x30, 0x74, 0x6b, 0x53, 0xd2, 0x07, 0x22, 0x80, 0x69, + 0xd5, 0x8b, 0x60, 0xfb, 0xf9, 0xf3, 0x84, 0x99, 0x88, 0x81, 0xa2, 0x7c, + 0x04, 0x7e, 0x22, 0xb9, 0x78, 0x89 +}; +static const uint8_t nist_186_2_ecdsa_testvector_180_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xbb, 0x1b, 0xc2, 0xe3, 0x7b, 0x85, 0x2c, 0x23, 0x74, 0x02, 0xfa, + 0xb4, 0xba, 0x65, 0x84, 0xc6, 0x85, 0x36, 0x32, 0xa2, 0xc0, 0x60, 0xf5, + 0x03, 0x99, 0x2b, 0x03, 0x37, 0xa7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_180_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x3a, 0x0e, 0xa8, 0xb4, 0x3f, 0x49, 0xd9, 0x42, 0x26, 0x9b, 0xbd, + 0x31, 0xd6, 0x0d, 0x8f, 0xd7, 0xc1, 0xf2, 0x88, 0x89, 0x18, 0x35, 0x69, + 0xac, 0xd8, 0x8e, 0xe4, 0x6c, 0xc3 +}; +/* k = 00000ad833129fbb7605452a7b9bc5dcece7ed67b81d5fdd93569e76c17 */ +static const uint8_t nist_186_2_ecdsa_testvector_180_out[] = { +/* R - byte alignment */ + 0x00, 0x2f, 0x13, 0xc7, 0xd7, 0xd7, 0x51, 0xb2, 0x40, 0xdc, 0x80, 0x56, + 0xca, 0xce, 0x86, 0x83, 0x47, 0xd4, 0xef, 0xc7, 0x27, 0x01, 0x80, 0xf1, + 0x0d, 0x5e, 0x24, 0xbd, 0xc8, 0x29, +/* S - byte alignment */ + 0x00, 0xd3, 0x45, 0x23, 0xbe, 0xe6, 0x0f, 0xe2, 0xc9, 0x12, 0xef, 0x53, + 0x51, 0x95, 0x91, 0x34, 0x5f, 0xc9, 0xa9, 0xb7, 0x1b, 0x7a, 0x08, 0x0a, + 0x19, 0xc8, 0x3a, 0xb4, 0xbb, 0xe5 +}; +/* [B-283] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_181_ptx[] = { +/* Msg */ + 0x9b, 0xfc, 0x4d, 0xac, 0x8c, 0x22, 0x32, 0x38, 0x72, 0x16, 0xa5, 0x32, + 0xce, 0x62, 0xd9, 0x8c, 0x1a, 0xaf, 0xa3, 0x5c, 0x65, 0xdc, 0x38, 0x8e, + 0x3d, 0x4d, 0x37, 0xd6, 0xd1, 0x86, 0xea, 0xe9, 0x57, 0xf8, 0xc9, 0xed, + 0xac, 0x1a, 0x3f, 0x2e, 0x3a, 0xbc, 0xb1, 0x12, 0x1f, 0x99, 0xbd, 0x4f, + 0x8c, 0x2b, 0xbf, 0x5b, 0x6a, 0xc3, 0x9a, 0x25, 0x44, 0xd8, 0xb5, 0x02, + 0x61, 0x9f, 0x43, 0xea, 0x30, 0xdd, 0xc8, 0xe4, 0xea, 0xfa, 0xd8, 0xbf, + 0x72, 0x56, 0x22, 0x03, 0x80, 0xe0, 0xae, 0x27, 0xfe, 0xe4, 0x63, 0x04, + 0xb2, 0x24, 0xcc, 0x8a, 0x1e, 0x2b, 0x1c, 0xb2, 0xa4, 0xde, 0x6f, 0xb3, + 0xee, 0x54, 0x52, 0x79, 0x8d, 0xe7, 0x86, 0x53, 0xe0, 0x8b, 0x01, 0xec, + 0x38, 0x5f, 0x36, 0x7c, 0x39, 0x82, 0x96, 0x3f, 0x84, 0x28, 0x57, 0x27, + 0x93, 0xed, 0x74, 0xce, 0xe3, 0x69, 0xf5, 0xae +}; +static const uint8_t nist_186_2_ecdsa_testvector_181_private[] = { +/* d - byte alignment */ + 0x00, 0x31, 0xca, 0x77, 0xb8, 0x9d, 0xf0, 0xc2, 0xf9, 0x0a, 0xe6, 0xd3, + 0x8c, 0x93, 0x5a, 0x75, 0xeb, 0xd7, 0x4d, 0x64, 0xf8, 0x26, 0xcf, 0xe6, + 0xd2, 0x3d, 0x13, 0x5e, 0x28, 0xbb, 0x66, 0xa0, 0xba, 0xea, 0xfb, 0xa9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_181_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0x23, 0x0e, 0x12, 0x93, 0x9f, 0x6d, 0x02, 0x0d, 0xbf, 0xe0, 0x77, + 0x26, 0x7a, 0x40, 0xe8, 0xe3, 0xc4, 0x21, 0x9c, 0x5d, 0x3b, 0x1f, 0x04, + 0x25, 0x89, 0x97, 0x66, 0xa5, 0x97, 0x0c, 0x90, 0x95, 0x06, 0x83, 0x85 +}; +static const uint8_t nist_186_2_ecdsa_testvector_181_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xc5, 0x57, 0xb8, 0x84, 0xef, 0x70, 0x03, 0xfd, 0x84, 0x69, 0x2b, + 0x6b, 0x69, 0xcd, 0xa8, 0x5f, 0xf9, 0xb5, 0x86, 0xd5, 0xfd, 0x6a, 0xe2, + 0x3a, 0xc9, 0x42, 0x1b, 0xb3, 0xb1, 0xb5, 0x70, 0x26, 0x5c, 0xa7, 0x7a +}; +/* k = 0c20977aed96ec8ec3abce9ed21ffd7f6469ef0696150418844edd960b9d7d90391ee7f */ +static const uint8_t nist_186_2_ecdsa_testvector_181_out[] = { +/* R - byte alignment */ + 0x03, 0x07, 0x40, 0x7b, 0x6a, 0x2d, 0xcc, 0x40, 0x01, 0x2a, 0xdc, 0x4e, + 0x7b, 0x72, 0xb4, 0xc1, 0x20, 0x02, 0xbf, 0x5c, 0x94, 0xb4, 0x40, 0x2c, + 0x78, 0x53, 0x65, 0x81, 0x06, 0x48, 0xb8, 0xb3, 0x5a, 0x7d, 0xab, 0x10, +/* S - byte alignment */ + 0x01, 0xc4, 0x49, 0x49, 0x1c, 0xc8, 0xd5, 0x61, 0x06, 0x34, 0xb7, 0xb3, + 0x6c, 0xf2, 0x8e, 0xc3, 0x0f, 0x08, 0xa3, 0xdb, 0xa2, 0x28, 0x02, 0x0a, + 0x08, 0xb6, 0x46, 0x52, 0xda, 0xb5, 0xb1, 0xb8, 0x86, 0xbb, 0x5f, 0xcd +}; +static const uint8_t nist_186_2_ecdsa_testvector_182_ptx[] = { +/* Msg */ + 0xc0, 0x7b, 0xe7, 0xf9, 0x32, 0xe6, 0xa0, 0x20, 0x07, 0xcf, 0xef, 0x54, + 0x4d, 0x99, 0xff, 0x1e, 0x38, 0x39, 0x3c, 0x51, 0x22, 0x31, 0x70, 0x9b, + 0xd0, 0xc2, 0x2c, 0x5b, 0xf7, 0x5d, 0x6a, 0xb2, 0xfe, 0x5c, 0x70, 0xdd, + 0x06, 0xef, 0xf8, 0xc2, 0x28, 0x59, 0x8d, 0xc8, 0xfd, 0x5c, 0x38, 0xec, + 0x64, 0xf1, 0x5c, 0x12, 0x7f, 0x3d, 0xdf, 0x98, 0xff, 0xc1, 0x8a, 0x31, + 0xa2, 0xd1, 0xb3, 0xf1, 0xf9, 0x47, 0x19, 0xa4, 0x6f, 0x78, 0x0f, 0x64, + 0x87, 0x67, 0xdd, 0x6b, 0x65, 0x39, 0x63, 0x25, 0x90, 0xe9, 0xff, 0x89, + 0xf6, 0x3d, 0xb1, 0xaa, 0x31, 0xf9, 0x7d, 0x89, 0x08, 0x52, 0x11, 0x2e, + 0x39, 0xa5, 0xa8, 0xf7, 0x76, 0x69, 0x2e, 0x2f, 0xad, 0x63, 0xa5, 0xe2, + 0x8c, 0x18, 0xc7, 0xf0, 0x45, 0x88, 0xed, 0x61, 0x8e, 0x19, 0x2f, 0xf8, + 0xec, 0xd2, 0xcd, 0x0b, 0x32, 0xc9, 0xce, 0x92 +}; +static const uint8_t nist_186_2_ecdsa_testvector_182_private[] = { +/* d - byte alignment */ + 0x03, 0xa3, 0xa1, 0xc1, 0x6d, 0x76, 0xa6, 0xd7, 0x60, 0xcc, 0x20, 0x67, + 0x05, 0x82, 0xd0, 0xc9, 0xf8, 0xd1, 0x9c, 0x99, 0x19, 0x59, 0x54, 0x8d, + 0x46, 0x58, 0x91, 0xb7, 0xed, 0xcb, 0xd3, 0x3c, 0xb1, 0xf2, 0xf3, 0x4d +}; +static const uint8_t nist_186_2_ecdsa_testvector_182_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0x3c, 0xf4, 0x26, 0x11, 0x9b, 0xdb, 0xa4, 0xb6, 0x83, 0x38, 0x8d, + 0xd3, 0xc4, 0x90, 0x77, 0x71, 0x9e, 0xe3, 0x98, 0x9d, 0x29, 0x0d, 0x07, + 0xb4, 0x9c, 0xf5, 0xf4, 0xf8, 0x24, 0x1e, 0xc4, 0xb3, 0xfa, 0x8a, 0x76 +}; +static const uint8_t nist_186_2_ecdsa_testvector_182_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x79, 0xe8, 0x77, 0xcb, 0x44, 0x8c, 0x84, 0x61, 0xca, 0x7f, 0x82, + 0x52, 0x97, 0xec, 0x06, 0xc1, 0xac, 0x21, 0x60, 0x80, 0x88, 0x42, 0x08, + 0xfe, 0x18, 0x51, 0x6d, 0xd0, 0xeb, 0x56, 0xec, 0x7a, 0xab, 0x9e, 0x2a +}; +/* k = 0f4568a9683e9da78745a492b8d3aea0a0f734abd1594687013f09aef361f34b806bdfb */ +static const uint8_t nist_186_2_ecdsa_testvector_182_out[] = { +/* R - byte alignment */ + 0x02, 0xc0, 0x19, 0x76, 0xc9, 0x64, 0xe8, 0x46, 0xab, 0x4d, 0x05, 0xd4, + 0x97, 0x85, 0x19, 0x84, 0x30, 0x1a, 0xb6, 0x80, 0xf1, 0xf3, 0xc1, 0x59, + 0xda, 0x27, 0xed, 0x4f, 0x10, 0xc7, 0xe8, 0x53, 0x37, 0x27, 0x79, 0x56, +/* S - byte alignment */ + 0x02, 0xa2, 0xd8, 0x8d, 0xdf, 0x6b, 0x89, 0x57, 0xfb, 0x2c, 0x04, 0xda, + 0x26, 0xe3, 0x38, 0x3e, 0xc8, 0x30, 0x58, 0x63, 0x6f, 0x8a, 0xcb, 0x8d, + 0xdf, 0xc0, 0xb6, 0x39, 0x90, 0xf0, 0x33, 0x0e, 0x98, 0xce, 0xbc, 0xd7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_183_ptx[] = { +/* Msg */ + 0x7a, 0xfd, 0xac, 0xad, 0x6e, 0x0d, 0xfe, 0x6d, 0x4c, 0x59, 0xa8, 0x09, + 0xe6, 0x7d, 0x9f, 0x34, 0x76, 0xde, 0x8b, 0x85, 0x83, 0xf6, 0xcb, 0x70, + 0x04, 0xec, 0xb9, 0x75, 0xc8, 0x68, 0x2f, 0x97, 0x15, 0xa5, 0x4a, 0x10, + 0x90, 0xc8, 0x6d, 0x43, 0x5c, 0x70, 0x89, 0xf2, 0x86, 0x8e, 0x9c, 0xb1, + 0xa1, 0x77, 0x78, 0x9b, 0xad, 0x37, 0xc6, 0x43, 0x3e, 0x28, 0x4a, 0xee, + 0xda, 0xc4, 0x69, 0xff, 0xa2, 0xb8, 0xe8, 0xb2, 0x34, 0x39, 0xf6, 0x0d, + 0xd1, 0x9b, 0x6d, 0x14, 0xbb, 0x20, 0x55, 0x3d, 0xe1, 0x0e, 0xaa, 0x23, + 0xbe, 0x04, 0x5e, 0x7e, 0x7f, 0x8d, 0xa2, 0x53, 0x64, 0xf6, 0x62, 0x68, + 0x68, 0x5d, 0x0e, 0xfb, 0x24, 0x0b, 0xa0, 0xb3, 0xf1, 0x04, 0xdb, 0xd7, + 0x4d, 0xdb, 0xd0, 0xbe, 0x80, 0xcb, 0xa7, 0x87, 0x7f, 0x04, 0x9c, 0x0a, + 0x10, 0x43, 0x48, 0x0d, 0x2f, 0xa5, 0x22, 0xbc +}; +static const uint8_t nist_186_2_ecdsa_testvector_183_private[] = { +/* d - byte alignment */ + 0x01, 0x18, 0x7c, 0xa0, 0x9d, 0xba, 0x19, 0x51, 0x0a, 0x5e, 0x55, 0x5a, + 0xf2, 0x62, 0x6e, 0xd1, 0xfb, 0x00, 0x50, 0x72, 0xbe, 0x13, 0x0d, 0x77, + 0x45, 0xd7, 0xd4, 0xc0, 0x43, 0x13, 0x62, 0xd0, 0x49, 0x81, 0xa5, 0x5b +}; +static const uint8_t nist_186_2_ecdsa_testvector_183_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x5c, 0xd1, 0x3a, 0xe1, 0xe8, 0xfd, 0x9c, 0x9b, 0x02, 0x50, 0xf2, + 0xfa, 0xe1, 0x5b, 0xa4, 0x9b, 0xb5, 0x9b, 0x03, 0x77, 0xff, 0x48, 0x05, + 0x36, 0x1f, 0x83, 0x9a, 0x95, 0x8e, 0x41, 0x42, 0x36, 0x8b, 0xc6, 0xa6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_183_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xc3, 0x1a, 0x44, 0x1a, 0x21, 0x36, 0x8a, 0x40, 0xe3, 0x6b, 0x17, + 0x09, 0x0e, 0x9b, 0x5e, 0x11, 0xf1, 0x9a, 0x72, 0xd6, 0x40, 0xa2, 0x1f, + 0x02, 0x9d, 0x61, 0x13, 0x4c, 0xca, 0xed, 0xa9, 0x50, 0x99, 0xdb, 0xec +}; +/* k = 2e23b033f329a2b605c8cdee982b78099be3157b06b32bbd4fe10bb475c2fca92c55a54 */ +static const uint8_t nist_186_2_ecdsa_testvector_183_out[] = { +/* R - byte alignment */ + 0x02, 0x1d, 0xb5, 0xc4, 0x50, 0x3c, 0x3b, 0x7d, 0x8b, 0x51, 0x63, 0x1f, + 0x39, 0x26, 0xeb, 0x8e, 0x9d, 0xf2, 0x49, 0x5a, 0xa2, 0xef, 0x17, 0x3c, + 0x29, 0x4b, 0xf9, 0xe4, 0xc5, 0x60, 0xe0, 0xb2, 0xc4, 0x64, 0x03, 0x15, +/* S - byte alignment */ + 0x00, 0x56, 0x14, 0x22, 0xc5, 0x55, 0x9c, 0x17, 0x00, 0xac, 0xf6, 0xc8, + 0xb2, 0x13, 0xfa, 0x04, 0xf0, 0x1c, 0x1f, 0x3f, 0xaa, 0x2d, 0x84, 0x79, + 0x0e, 0xd7, 0x40, 0xa4, 0xdf, 0xc1, 0x0f, 0xce, 0xf6, 0x0c, 0x9d, 0x9b +}; +static const uint8_t nist_186_2_ecdsa_testvector_184_ptx[] = { +/* Msg */ + 0xf3, 0x6d, 0x12, 0x96, 0x9c, 0x07, 0xbf, 0x5b, 0x2b, 0xfe, 0x30, 0x48, + 0xe5, 0x90, 0x7a, 0xb0, 0x1e, 0xd3, 0x27, 0x82, 0x5a, 0x4b, 0x7f, 0x7b, + 0xb1, 0xbc, 0x06, 0x9a, 0x78, 0x3d, 0x45, 0xd5, 0x1d, 0x8e, 0xcd, 0x0a, + 0x53, 0xab, 0x7a, 0x38, 0x6f, 0xa1, 0xf5, 0xef, 0x12, 0xa1, 0x7c, 0x05, + 0x09, 0x53, 0xe6, 0x8b, 0x71, 0x6c, 0xe1, 0xff, 0x1f, 0x83, 0x7f, 0xc3, + 0x3f, 0x21, 0xf1, 0xce, 0x3a, 0x17, 0x92, 0xa2, 0xde, 0x14, 0x27, 0x7e, + 0xb9, 0x76, 0x64, 0xd4, 0xc5, 0x61, 0xb3, 0xfd, 0x4b, 0x0e, 0x32, 0x2c, + 0x01, 0x66, 0xfa, 0xa1, 0x75, 0xd0, 0xa7, 0x1f, 0xaf, 0x47, 0x15, 0x9f, + 0x12, 0xaf, 0x67, 0x46, 0x84, 0x69, 0x4e, 0x95, 0xcf, 0x25, 0x88, 0xe0, + 0x46, 0xf7, 0xa6, 0x01, 0xab, 0xae, 0x13, 0x4d, 0x50, 0x61, 0x52, 0xc7, + 0x7d, 0x4a, 0x87, 0x94, 0x12, 0xd7, 0x39, 0xaf +}; +static const uint8_t nist_186_2_ecdsa_testvector_184_private[] = { +/* d - byte alignment */ + 0x02, 0xdf, 0x90, 0x2b, 0xc8, 0xa6, 0x55, 0x0a, 0x1c, 0x3c, 0xf3, 0x80, + 0x3a, 0x38, 0x91, 0xe8, 0x94, 0xc3, 0xbe, 0xb5, 0x6d, 0xc0, 0x06, 0xb9, + 0x49, 0xb8, 0x26, 0x03, 0xd7, 0x64, 0xe1, 0x81, 0x91, 0xd0, 0xf4, 0x90 +}; +static const uint8_t nist_186_2_ecdsa_testvector_184_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0x37, 0xf9, 0x64, 0x6c, 0x9c, 0x0d, 0xdb, 0x8d, 0x88, 0x1f, 0xef, + 0x33, 0x1c, 0x5c, 0xbf, 0xaf, 0xe8, 0x25, 0x77, 0x11, 0xbd, 0x3e, 0xa0, + 0xf6, 0xdc, 0xb0, 0xaf, 0xbe, 0x12, 0x2b, 0xc0, 0xf0, 0xeb, 0x5c, 0x9e +}; +static const uint8_t nist_186_2_ecdsa_testvector_184_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x6b, 0xcd, 0x06, 0xcd, 0x95, 0xa5, 0xa6, 0xdf, 0x5a, 0x4d, 0xbd, + 0x6a, 0x5a, 0xdb, 0x9e, 0x3a, 0xb0, 0x8a, 0x4b, 0x30, 0xae, 0x54, 0x98, + 0x4a, 0x5a, 0x36, 0x65, 0xca, 0x98, 0xd0, 0xee, 0x86, 0xa7, 0x0c, 0xf5 +}; +/* k = 01e4cfdf4a0d809bf6e464fe6c1561672571b40ed9aa78d4546d4719ccbc32ec81da657 */ +static const uint8_t nist_186_2_ecdsa_testvector_184_out[] = { +/* R - byte alignment */ + 0x00, 0xf9, 0x55, 0x29, 0xf3, 0xf4, 0x78, 0x6d, 0xdb, 0xbd, 0x90, 0xb6, + 0x35, 0x8d, 0xf8, 0x88, 0x42, 0x83, 0xd3, 0xe8, 0xc3, 0x6c, 0xda, 0xe5, + 0xb3, 0x83, 0x14, 0xb9, 0xb3, 0x10, 0x50, 0xba, 0xbf, 0xd8, 0x17, 0xd6, +/* S - byte alignment */ + 0x03, 0xe7, 0x6e, 0x4a, 0xd3, 0x9c, 0xff, 0xa3, 0x8b, 0x3f, 0x2b, 0xb5, + 0x43, 0x53, 0xd1, 0xda, 0x6c, 0x53, 0x8c, 0xd1, 0x47, 0xc4, 0x5e, 0xea, + 0x83, 0xfe, 0xe3, 0x32, 0x5b, 0xdb, 0xa6, 0xa2, 0x92, 0x39, 0x95, 0x32 +}; +static const uint8_t nist_186_2_ecdsa_testvector_185_ptx[] = { +/* Msg */ + 0x4d, 0xfc, 0x7c, 0x45, 0x3b, 0xd2, 0x55, 0xe6, 0x17, 0x48, 0x14, 0x85, + 0xe3, 0x28, 0xeb, 0xde, 0x7d, 0xa7, 0xc9, 0x73, 0x73, 0xea, 0xd1, 0x2c, + 0x18, 0xc8, 0x0a, 0x41, 0xd8, 0xd2, 0x58, 0x59, 0xc8, 0x90, 0xab, 0xf4, + 0x81, 0x0e, 0x76, 0x06, 0x2f, 0x97, 0x63, 0xe4, 0xe5, 0xc1, 0x45, 0x64, + 0x34, 0xaa, 0x4d, 0x40, 0xfb, 0x80, 0x82, 0xbc, 0x80, 0x47, 0x6b, 0x89, + 0xc0, 0xd6, 0x0e, 0xe8, 0x04, 0x23, 0x1f, 0x13, 0xb5, 0xc1, 0x71, 0xd8, + 0x71, 0xa7, 0xb0, 0x87, 0x5e, 0x33, 0x52, 0x0e, 0xbf, 0x6f, 0xcb, 0x63, + 0xc5, 0x92, 0x00, 0x22, 0xa7, 0xca, 0xff, 0x78, 0xf5, 0x38, 0xed, 0x3f, + 0x29, 0x3c, 0x3f, 0x6a, 0x7f, 0xf4, 0x2e, 0xa4, 0x06, 0xff, 0x64, 0x34, + 0xf7, 0x87, 0xfc, 0x24, 0x46, 0x7e, 0xa9, 0xa2, 0x78, 0x27, 0x35, 0xa6, + 0xb4, 0xd9, 0x2e, 0xd5, 0x1c, 0x00, 0xdc, 0xa6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_185_private[] = { +/* d - byte alignment */ + 0x02, 0x99, 0xcb, 0xae, 0xc3, 0x25, 0x75, 0xd3, 0x64, 0x9f, 0xaf, 0xb0, + 0xa5, 0xa3, 0xe5, 0x19, 0xa1, 0x64, 0x1f, 0xc3, 0xa5, 0x07, 0x95, 0xb1, + 0x2e, 0x95, 0xb9, 0xf2, 0xda, 0xa7, 0xb2, 0x72, 0x76, 0xf5, 0x0e, 0xc7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_185_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0x86, 0xfc, 0xf9, 0x70, 0x31, 0x83, 0xc1, 0xe8, 0xb0, 0x4b, 0x4d, + 0xcf, 0xfb, 0x90, 0xd2, 0x97, 0x4c, 0x78, 0xcc, 0x5e, 0x95, 0xb6, 0x55, + 0xdb, 0x23, 0x6b, 0x23, 0x4f, 0x8a, 0x7e, 0x25, 0xbc, 0xa9, 0x81, 0xfa +}; +static const uint8_t nist_186_2_ecdsa_testvector_185_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0xfe, 0x9b, 0x68, 0x60, 0xff, 0x39, 0xed, 0x30, 0x1d, 0x94, 0xf8, + 0x38, 0xbf, 0x1f, 0x2a, 0xb9, 0xda, 0x1f, 0x21, 0x5c, 0x3a, 0x78, 0x23, + 0xa0, 0xe9, 0x6d, 0x94, 0xca, 0x54, 0x79, 0xa6, 0x61, 0xf4, 0x85, 0x34 +}; +/* k = 2b71bc909d8ca418ebf17c6ca61fb51d839b44989991023ff35d556c98c788c5922e877 */ +static const uint8_t nist_186_2_ecdsa_testvector_185_out[] = { +/* R - byte alignment */ + 0x03, 0x63, 0x16, 0x8d, 0x66, 0x5a, 0x86, 0xea, 0xef, 0x81, 0x16, 0x1c, + 0x49, 0xa2, 0xf9, 0x60, 0x73, 0x7f, 0x60, 0x9c, 0x18, 0xad, 0x30, 0x59, + 0xf5, 0xf6, 0xc8, 0xbd, 0x7f, 0xaf, 0xf1, 0x91, 0x89, 0xb5, 0x71, 0x18, +/* S - byte alignment */ + 0x00, 0xbe, 0xfa, 0x58, 0x07, 0xde, 0x6b, 0x72, 0x2d, 0x0c, 0xa5, 0x15, + 0xa4, 0x97, 0xf3, 0xca, 0x83, 0xe7, 0x5e, 0x1b, 0x09, 0xcf, 0x4b, 0x0a, + 0xbd, 0x14, 0xb8, 0x99, 0xfc, 0x49, 0x6e, 0x63, 0xd2, 0x1a, 0xc0, 0x06 +}; +static const uint8_t nist_186_2_ecdsa_testvector_186_ptx[] = { +/* Msg */ + 0x8e, 0x96, 0x36, 0x9a, 0x51, 0x77, 0x58, 0x2f, 0xea, 0xe5, 0x9c, 0xf4, + 0x27, 0xca, 0x58, 0xb8, 0x2b, 0x0c, 0xeb, 0x32, 0x63, 0xb3, 0x4f, 0x43, + 0xbb, 0x4a, 0xee, 0x7c, 0x11, 0x87, 0xb7, 0xe0, 0xe9, 0x2e, 0x70, 0xeb, + 0x63, 0x32, 0x4e, 0xd3, 0x6b, 0x1d, 0xc3, 0x0d, 0x30, 0xb3, 0x97, 0x13, + 0xd7, 0xd2, 0x3a, 0x65, 0x70, 0x9d, 0x59, 0xcd, 0x29, 0xda, 0xaf, 0xe8, + 0xc1, 0x97, 0x1e, 0xe2, 0x40, 0x14, 0xfe, 0x81, 0xe6, 0xdd, 0xb5, 0x65, + 0x61, 0x37, 0x87, 0x8e, 0x43, 0xbd, 0xb0, 0x1e, 0xb2, 0x4b, 0xb0, 0x60, + 0x61, 0x1b, 0xe7, 0x0a, 0xc0, 0x2e, 0x61, 0xbf, 0x70, 0xee, 0xf3, 0xd8, + 0xfa, 0x11, 0x87, 0x64, 0xc0, 0xc0, 0xb4, 0x6d, 0x34, 0xf9, 0x92, 0x7e, + 0x47, 0x32, 0xcc, 0x61, 0x25, 0x3f, 0xf6, 0x2d, 0x1f, 0x75, 0x21, 0x81, + 0xe8, 0x10, 0xad, 0x0a, 0x05, 0xd2, 0x5f, 0x4b +}; +static const uint8_t nist_186_2_ecdsa_testvector_186_private[] = { +/* d - byte alignment */ + 0x03, 0x2e, 0x5f, 0x90, 0xe7, 0xb2, 0xd3, 0x67, 0x62, 0x69, 0x70, 0x0e, + 0x54, 0x91, 0x1d, 0x2f, 0x93, 0x69, 0xb1, 0xbd, 0x4f, 0xe7, 0x6a, 0x80, + 0x97, 0xf0, 0xfa, 0x88, 0x01, 0xe4, 0xdb, 0xe0, 0xcc, 0xd6, 0x3c, 0x48 +}; +static const uint8_t nist_186_2_ecdsa_testvector_186_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xf5, 0x64, 0xb6, 0x7c, 0x00, 0x09, 0xb3, 0x85, 0xd0, 0x33, 0xc4, + 0x71, 0x8e, 0xd0, 0xbc, 0x33, 0x58, 0x9e, 0xa3, 0x2a, 0x25, 0xe5, 0xff, + 0xca, 0x8d, 0x06, 0x0a, 0xf5, 0x8e, 0x3f, 0x2a, 0x9f, 0xd6, 0x74, 0x87 +}; +static const uint8_t nist_186_2_ecdsa_testvector_186_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x4f, 0x74, 0xeb, 0xdd, 0x5f, 0x03, 0x87, 0xf3, 0xb4, 0x27, 0x3f, + 0x2d, 0xb6, 0x1d, 0xb0, 0xff, 0x8d, 0xd6, 0xee, 0xbd, 0xaa, 0xd8, 0xb3, + 0xb2, 0xdf, 0xa5, 0x34, 0x0e, 0x59, 0xea, 0x34, 0xb2, 0xfe, 0x63, 0xb6 +}; +/* k = 33c1685b8aa35959f6e76228bf71f3d1ddcd04ea6c39f153fd34b21407ea001d74d1c79 */ +static const uint8_t nist_186_2_ecdsa_testvector_186_out[] = { +/* R - byte alignment */ + 0x00, 0x95, 0x45, 0x89, 0x47, 0x0e, 0x0e, 0x87, 0xd5, 0x3a, 0xc0, 0x2b, + 0xfc, 0x08, 0x42, 0x07, 0x30, 0x2b, 0x62, 0x14, 0xa9, 0xdb, 0x45, 0xfb, + 0xdf, 0x66, 0xb1, 0x9e, 0x61, 0x85, 0x10, 0xe1, 0xdd, 0x92, 0x80, 0xe4, +/* S - byte alignment */ + 0x01, 0xc6, 0xd7, 0x91, 0xa8, 0x5b, 0x7c, 0x75, 0xcc, 0xc3, 0x29, 0xf4, + 0x18, 0x5b, 0xb5, 0x94, 0x78, 0x66, 0xcc, 0x65, 0xe0, 0xd7, 0x27, 0x84, + 0x5f, 0x9a, 0xf0, 0x61, 0xfe, 0x1f, 0x88, 0x08, 0x72, 0x1c, 0x1b, 0x9c +}; +static const uint8_t nist_186_2_ecdsa_testvector_187_ptx[] = { +/* Msg */ + 0x48, 0x8a, 0xfd, 0x29, 0x87, 0x79, 0x70, 0x54, 0xbc, 0xfa, 0xcc, 0xe1, + 0x73, 0xfb, 0x9c, 0x40, 0x2f, 0x81, 0x1c, 0xcb, 0xaf, 0xe1, 0x9d, 0x9d, + 0x6f, 0x33, 0x2b, 0xa8, 0x72, 0x04, 0x6e, 0x02, 0x3f, 0x4b, 0xce, 0x80, + 0x2a, 0x9e, 0xda, 0x86, 0xd4, 0xa6, 0xeb, 0x1d, 0xf5, 0xd1, 0x04, 0x46, + 0x59, 0x46, 0xfd, 0x8f, 0x29, 0x1e, 0xe1, 0xe3, 0x6c, 0xd1, 0x94, 0xa6, + 0xcd, 0xee, 0xb9, 0x02, 0x9f, 0x10, 0xd2, 0x7b, 0x1e, 0x0d, 0xa9, 0xca, + 0xf8, 0x70, 0xf0, 0xe8, 0x0c, 0x2a, 0x24, 0x69, 0x71, 0x84, 0xb7, 0x0b, + 0xba, 0x58, 0x6d, 0x8f, 0x78, 0x81, 0x07, 0xc7, 0x01, 0x90, 0x1f, 0xf1, + 0x70, 0xc0, 0x53, 0x43, 0xed, 0x2d, 0xa5, 0xc7, 0x2f, 0x40, 0x22, 0x69, + 0x3e, 0x6e, 0xc2, 0x4f, 0x7e, 0x22, 0x90, 0x68, 0xe9, 0xf7, 0x0a, 0x48, + 0x9c, 0x2b, 0xcb, 0x33, 0x95, 0x51, 0x67, 0x77 +}; +static const uint8_t nist_186_2_ecdsa_testvector_187_private[] = { +/* d - byte alignment */ + 0x02, 0x15, 0x2c, 0x3e, 0x39, 0x02, 0x8f, 0x07, 0xe7, 0xe3, 0xbe, 0x6c, + 0x13, 0x2c, 0xd7, 0x3b, 0x65, 0xe8, 0xf3, 0x94, 0xfc, 0x57, 0x02, 0x0e, + 0xcb, 0x3d, 0xa4, 0xc9, 0xa9, 0x07, 0x31, 0x49, 0xcb, 0x80, 0xcb, 0x90 +}; +static const uint8_t nist_186_2_ecdsa_testvector_187_public_x[] = { +/* Qx - byte alignment */ + 0x02, 0x12, 0x4d, 0x9f, 0x3a, 0x3a, 0x3c, 0x23, 0xf1, 0xc5, 0x89, 0xe4, + 0x57, 0x9e, 0x7c, 0xd0, 0xf8, 0xe1, 0x86, 0x99, 0x78, 0x2e, 0xf9, 0x5b, + 0xef, 0xd4, 0x33, 0x31, 0x95, 0x73, 0x57, 0x84, 0xc4, 0xbe, 0x3c, 0x05 +}; +static const uint8_t nist_186_2_ecdsa_testvector_187_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x36, 0xe2, 0xb0, 0x9b, 0xf2, 0x6e, 0xee, 0xa0, 0xcb, 0xeb, 0x8b, + 0x93, 0xdb, 0xb3, 0x60, 0xae, 0x07, 0x36, 0x9a, 0xd9, 0x9d, 0x21, 0x10, + 0xf9, 0x2d, 0x36, 0xe5, 0x04, 0xd5, 0x0c, 0x79, 0x91, 0xb0, 0x1e, 0x77 +}; +/* k = 34ca338d6fd6ef9815416b00cec2277972856cc3ff1eaa5e022ecba782084963aea90c7 */ +static const uint8_t nist_186_2_ecdsa_testvector_187_out[] = { +/* R - byte alignment */ + 0x01, 0x60, 0xfb, 0x38, 0xf0, 0x9d, 0x0b, 0x90, 0x82, 0xf9, 0xcb, 0xdf, + 0xab, 0xfc, 0x80, 0xb5, 0x80, 0xcb, 0x93, 0xee, 0xe2, 0x53, 0x20, 0x1b, + 0x1e, 0x3e, 0xcd, 0xa1, 0xb8, 0x8f, 0x23, 0xe9, 0x7a, 0x5a, 0x8e, 0xb9, +/* S - byte alignment */ + 0x03, 0x20, 0xc8, 0x1b, 0xd2, 0x4f, 0xd6, 0x10, 0xa1, 0x25, 0xa8, 0xa8, + 0x4e, 0xab, 0x73, 0x72, 0xcc, 0xe1, 0x7a, 0xad, 0x0f, 0xc6, 0xb7, 0xef, + 0x49, 0x6b, 0xb3, 0xd0, 0xfd, 0x2b, 0xc6, 0xfa, 0xd1, 0x22, 0x9b, 0x12 +}; +static const uint8_t nist_186_2_ecdsa_testvector_188_ptx[] = { +/* Msg */ + 0x5f, 0x53, 0x8e, 0x87, 0xd3, 0xb6, 0x65, 0x44, 0x14, 0xcc, 0xd6, 0x13, + 0x7a, 0x5f, 0x17, 0xa6, 0x03, 0x3e, 0x47, 0xed, 0xec, 0x86, 0xa3, 0x7f, + 0x83, 0x20, 0xfc, 0x3b, 0x37, 0x8b, 0x69, 0x2f, 0xf1, 0xdc, 0x39, 0xb9, + 0xa7, 0x03, 0x2b, 0xeb, 0x2e, 0x4f, 0xe2, 0x34, 0x4f, 0x35, 0x93, 0x3d, + 0x1e, 0x4d, 0x01, 0x12, 0x87, 0x9d, 0xab, 0x82, 0x2a, 0x1a, 0x43, 0xc8, + 0x69, 0x6c, 0x63, 0x6b, 0xbe, 0xf2, 0x7c, 0x62, 0x52, 0x06, 0x0f, 0x7c, + 0xcc, 0x82, 0x1f, 0xff, 0x67, 0x82, 0xe6, 0x8f, 0x48, 0x6c, 0xc7, 0x52, + 0x0e, 0x2e, 0x84, 0x52, 0xaa, 0xc7, 0xb1, 0x23, 0x71, 0x09, 0x68, 0xc5, + 0x6f, 0x9d, 0x3f, 0xcb, 0xff, 0x47, 0x77, 0xbd, 0x99, 0x6b, 0x76, 0xbc, + 0xea, 0xd1, 0x77, 0x64, 0x2a, 0xa5, 0x81, 0xf7, 0xaa, 0xc2, 0x95, 0xb7, + 0xac, 0x30, 0x2c, 0x93, 0x78, 0xea, 0xe1, 0x06 +}; +static const uint8_t nist_186_2_ecdsa_testvector_188_private[] = { +/* d - byte alignment */ + 0x02, 0x1f, 0x71, 0x54, 0xf5, 0x23, 0xa0, 0xf3, 0x28, 0x92, 0x8f, 0x9b, + 0x86, 0x63, 0xc0, 0x2a, 0x58, 0x8c, 0x4d, 0x9d, 0xa2, 0x8a, 0xe6, 0x55, + 0xa3, 0x67, 0x91, 0x7e, 0x18, 0x78, 0xf2, 0xff, 0x39, 0x99, 0x7b, 0x38 +}; +static const uint8_t nist_186_2_ecdsa_testvector_188_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0xa1, 0xbf, 0xc7, 0x0e, 0x68, 0xb4, 0xda, 0xf6, 0xe2, 0xde, 0x91, + 0xf7, 0x51, 0xf6, 0x05, 0xbf, 0x16, 0xf3, 0x99, 0xd1, 0xc7, 0x00, 0xd4, + 0x2c, 0x3d, 0xe8, 0x94, 0x4b, 0x00, 0x8d, 0x8b, 0x19, 0x71, 0x23, 0x82 +}; +static const uint8_t nist_186_2_ecdsa_testvector_188_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0x03, 0xc3, 0x98, 0xda, 0x7c, 0xc1, 0xd2, 0x54, 0x2d, 0xcf, 0xc7, + 0x30, 0x0a, 0x05, 0x9c, 0x2d, 0xad, 0xf8, 0x0e, 0xe9, 0x3b, 0x01, 0xb3, + 0xf3, 0xa7, 0xcc, 0x8f, 0x67, 0xd8, 0x43, 0x5d, 0x54, 0xc9, 0xc2, 0x19 +}; +/* k = 3ccf0daf98653825495b36ef481a3d810fc81cd6dad82e7667780d6c7b08b462fe5c510 */ +static const uint8_t nist_186_2_ecdsa_testvector_188_out[] = { +/* R - byte alignment */ + 0x00, 0xe1, 0xe8, 0x3a, 0x74, 0x62, 0xb5, 0xf4, 0xc0, 0xa2, 0xcd, 0x62, + 0x47, 0x65, 0xfb, 0x50, 0xa4, 0x64, 0x05, 0x66, 0x85, 0x81, 0x4a, 0x70, + 0xc6, 0x5d, 0x85, 0x5c, 0x8e, 0x3e, 0x96, 0x7f, 0x72, 0x58, 0x8f, 0xd0, +/* S - byte alignment */ + 0x03, 0x6b, 0x92, 0x69, 0x15, 0x11, 0xf9, 0xc0, 0x16, 0xdb, 0xd6, 0xda, + 0xbf, 0xdf, 0x12, 0x61, 0x98, 0xee, 0x61, 0x11, 0x2e, 0x8a, 0x95, 0x0b, + 0xca, 0xab, 0xca, 0x9f, 0xbd, 0x05, 0x6e, 0xd8, 0x1c, 0x96, 0xc1, 0x0b +}; +static const uint8_t nist_186_2_ecdsa_testvector_189_ptx[] = { +/* Msg */ + 0x36, 0xf7, 0x1a, 0xad, 0x73, 0x51, 0x13, 0xeb, 0x75, 0x53, 0x35, 0x4e, + 0x32, 0xac, 0xc4, 0x18, 0xb5, 0xc3, 0xd6, 0x14, 0x68, 0xf1, 0xb7, 0x71, + 0x92, 0xef, 0x8b, 0xd0, 0x1f, 0x8a, 0x35, 0x9c, 0xa0, 0x9e, 0x78, 0x9a, + 0x92, 0x41, 0x5c, 0xc1, 0xe3, 0x3f, 0xd4, 0x4b, 0xb2, 0xc7, 0x9d, 0x0c, + 0x57, 0x63, 0x69, 0x03, 0xa3, 0x2d, 0x3d, 0x2f, 0x68, 0x41, 0x18, 0xa3, + 0x3c, 0x6e, 0xd5, 0xdd, 0x7b, 0x31, 0x52, 0x54, 0x8b, 0xe3, 0xd2, 0x50, + 0x64, 0x31, 0xa0, 0xfe, 0x4f, 0xcd, 0xf6, 0xc4, 0xed, 0x63, 0x1c, 0xd2, + 0x7c, 0xcf, 0xd4, 0xfa, 0x56, 0x8d, 0xf6, 0xc1, 0xba, 0x70, 0x58, 0xb6, + 0xcf, 0x97, 0xf0, 0x02, 0xe6, 0x9e, 0x3d, 0x41, 0x00, 0x11, 0xe2, 0x90, + 0x90, 0x26, 0x95, 0xe7, 0x82, 0xab, 0x37, 0xaa, 0x7b, 0x3d, 0x44, 0x7a, + 0x63, 0xbb, 0x6e, 0x51, 0x21, 0xfa, 0x85, 0xce +}; +static const uint8_t nist_186_2_ecdsa_testvector_189_private[] = { +/* d - byte alignment */ + 0x03, 0xcb, 0xbe, 0xbf, 0xcd, 0x2d, 0xc6, 0x13, 0xbf, 0x16, 0xfc, 0xe4, + 0x7b, 0xb4, 0xa0, 0xf7, 0xf7, 0xc3, 0x2b, 0x7a, 0xdf, 0x74, 0xfd, 0x85, + 0x8f, 0xa1, 0x96, 0xa1, 0xc8, 0x7c, 0xf1, 0x52, 0xd0, 0xa0, 0x03, 0x19 +}; +static const uint8_t nist_186_2_ecdsa_testvector_189_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0x5f, 0x75, 0x5e, 0x65, 0x7c, 0x50, 0xda, 0xd7, 0xdf, 0x12, 0x71, + 0x7d, 0x7b, 0x0b, 0x17, 0x99, 0x3a, 0x90, 0x2a, 0x4f, 0xb4, 0xa2, 0xd5, + 0x4f, 0x8b, 0xaa, 0x4f, 0xc0, 0x56, 0x06, 0x1f, 0x0d, 0x4a, 0xba, 0x07 +}; +static const uint8_t nist_186_2_ecdsa_testvector_189_public_y[] = { +/* Qy - byte alignment */ + 0x06, 0x52, 0xcf, 0x38, 0x73, 0x94, 0x95, 0x0f, 0xe9, 0xe0, 0xba, 0xcb, + 0x73, 0xf5, 0x98, 0xea, 0x42, 0xe4, 0xf6, 0xe3, 0x86, 0x46, 0x71, 0x3a, + 0x2f, 0x84, 0x66, 0xaf, 0x03, 0x33, 0xc4, 0x77, 0xc6, 0x67, 0xd1, 0x2f +}; +/* k = 0991a66ea073a99b9bde01e928ca6caba36af91ef9a6f1307e898eb15e90c8f15a08725 */ +static const uint8_t nist_186_2_ecdsa_testvector_189_out[] = { +/* R - byte alignment */ + 0x01, 0x2a, 0x18, 0x33, 0x2c, 0xf4, 0xc8, 0x1e, 0x44, 0x09, 0xa4, 0x99, + 0x30, 0x9f, 0xc0, 0xf7, 0xc2, 0x5d, 0x06, 0x97, 0x8c, 0x43, 0x8b, 0x4a, + 0x5a, 0x5d, 0xd5, 0x09, 0x7e, 0x34, 0x53, 0xc6, 0x99, 0x81, 0xcb, 0x69, +/* S - byte alignment */ + 0x03, 0xbb, 0x17, 0xd7, 0xb8, 0x85, 0xbd, 0x26, 0x5c, 0xf9, 0x0d, 0x93, + 0xc3, 0x61, 0x1f, 0xbf, 0x44, 0x7d, 0x17, 0xb6, 0x4a, 0x45, 0x39, 0x54, + 0x94, 0xb4, 0x7e, 0x12, 0x94, 0x42, 0x0d, 0xa1, 0xe3, 0x94, 0x3e, 0xf2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_190_ptx[] = { +/* Msg */ + 0x82, 0xe2, 0xdb, 0x12, 0xb8, 0xd5, 0x81, 0xe5, 0x32, 0xce, 0xa2, 0x9e, + 0xf0, 0x1c, 0x60, 0xaa, 0x38, 0x3d, 0x54, 0x0f, 0x8b, 0xfe, 0x22, 0xad, + 0xd7, 0xe4, 0x50, 0xc4, 0xee, 0xcb, 0x58, 0xb7, 0x37, 0xcd, 0xfb, 0x10, + 0xa3, 0x65, 0xd9, 0xc3, 0xe3, 0xd4, 0x3f, 0xb7, 0xd9, 0xc4, 0x40, 0x82, + 0x4c, 0x2c, 0x07, 0x75, 0xdf, 0x73, 0x6b, 0xd8, 0x44, 0xd8, 0xc4, 0x76, + 0xad, 0x11, 0xfd, 0x5d, 0x83, 0x32, 0xeb, 0xdf, 0x5b, 0xd1, 0xdd, 0xdc, + 0x26, 0x68, 0x75, 0x44, 0xa7, 0xfa, 0xb6, 0xd7, 0x2b, 0xfa, 0x5d, 0x2f, + 0x74, 0x68, 0x75, 0x01, 0xf6, 0x3d, 0x26, 0xa0, 0x46, 0x09, 0xce, 0xc2, + 0xcf, 0xdb, 0x53, 0x87, 0xc7, 0x61, 0xb7, 0xb7, 0x61, 0x50, 0xec, 0x4b, + 0x44, 0x06, 0xea, 0x30, 0x3d, 0x6f, 0x00, 0x47, 0x30, 0x25, 0x67, 0xb0, + 0x55, 0xdb, 0x1d, 0x48, 0xa0, 0xfb, 0xf0, 0x70 +}; +static const uint8_t nist_186_2_ecdsa_testvector_190_private[] = { +/* d - byte alignment */ + 0x03, 0xfb, 0x84, 0xca, 0xa7, 0xcb, 0xeb, 0x11, 0xd4, 0x91, 0x45, 0x95, + 0x51, 0x0c, 0x5d, 0x02, 0xdd, 0x16, 0xd2, 0xd6, 0x58, 0x06, 0x47, 0x3e, + 0x1d, 0x52, 0xd8, 0x2a, 0x20, 0xa0, 0x44, 0x42, 0x80, 0xd9, 0x1b, 0x6d +}; +static const uint8_t nist_186_2_ecdsa_testvector_190_public_x[] = { +/* Qx - byte alignment */ + 0x07, 0x52, 0x01, 0x15, 0x70, 0x50, 0xa7, 0x73, 0x71, 0x01, 0x73, 0x7e, + 0xe9, 0x47, 0xd1, 0x65, 0x9d, 0x76, 0x69, 0x2b, 0x4d, 0x39, 0x1b, 0x99, + 0x6d, 0x6e, 0x99, 0x55, 0x1a, 0x74, 0x2e, 0x31, 0x17, 0xb8, 0x53, 0x9f +}; +static const uint8_t nist_186_2_ecdsa_testvector_190_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x00, 0x99, 0xc1, 0xcf, 0x05, 0x77, 0xe0, 0x81, 0x13, 0x09, 0x57, + 0x93, 0x09, 0x72, 0x19, 0x19, 0xe8, 0xd8, 0x9b, 0xae, 0xc5, 0xab, 0x83, + 0xa1, 0x8e, 0x6b, 0x60, 0x9f, 0x70, 0x71, 0x2b, 0xf4, 0x9c, 0x13, 0x5b +}; +/* k = 3cc06e9dd24971a106849f45d780284e8fca99d19abd79aba02d07ded33006c601d6374 */ +static const uint8_t nist_186_2_ecdsa_testvector_190_out[] = { +/* R - byte alignment */ + 0x03, 0xd9, 0x75, 0x57, 0x6d, 0x05, 0x48, 0x2e, 0x95, 0xca, 0x1e, 0xc8, + 0x02, 0x30, 0xf9, 0x96, 0xa5, 0x7a, 0x43, 0x0a, 0x78, 0x5a, 0x7b, 0xf1, + 0x48, 0xa6, 0x46, 0x77, 0x0c, 0x70, 0xd9, 0x05, 0x58, 0xb7, 0xdc, 0x65, +/* S - byte alignment */ + 0x02, 0xc5, 0x70, 0x0a, 0x18, 0x2f, 0xe3, 0x58, 0x54, 0xde, 0xbe, 0x4c, + 0x13, 0xcd, 0x23, 0x19, 0x55, 0x5f, 0x4e, 0x18, 0x52, 0x4f, 0x8a, 0x50, + 0x6b, 0xee, 0x3b, 0x75, 0x95, 0xe4, 0xb8, 0xf8, 0x01, 0xaa, 0x37, 0x99 +}; +static const uint8_t nist_186_2_ecdsa_testvector_191_ptx[] = { +/* Msg */ + 0xd3, 0x38, 0x3b, 0x11, 0x9c, 0xbf, 0x3b, 0x8b, 0x04, 0x4d, 0x87, 0x08, + 0xa7, 0x58, 0xc9, 0x5f, 0x8e, 0x19, 0x63, 0x36, 0x5e, 0xf0, 0x4a, 0x7d, + 0xcf, 0x04, 0x17, 0x3c, 0x60, 0x2a, 0x5b, 0x8f, 0x4a, 0x08, 0x33, 0xee, + 0xb2, 0x7a, 0x1d, 0xb2, 0x22, 0x34, 0x0a, 0xd5, 0x3a, 0xa9, 0xb5, 0xfa, + 0xa3, 0x2c, 0x32, 0xad, 0x45, 0x55, 0xca, 0xeb, 0xba, 0xa7, 0x06, 0xe5, + 0x02, 0x6f, 0x0a, 0x01, 0x78, 0xef, 0x24, 0x22, 0x04, 0xbc, 0xa5, 0x29, + 0x93, 0x65, 0xf0, 0xbc, 0xc4, 0x55, 0xd0, 0x46, 0xe4, 0xfb, 0x0f, 0x3e, + 0x1d, 0x28, 0x44, 0xad, 0xea, 0xb8, 0xec, 0xea, 0xce, 0x74, 0xbc, 0xa8, + 0x46, 0x37, 0x36, 0x33, 0xfc, 0x50, 0x7b, 0xf7, 0x3d, 0x28, 0x60, 0x42, + 0xad, 0x25, 0xc3, 0x4b, 0x3a, 0xcd, 0x20, 0x72, 0x4e, 0x2f, 0x5f, 0xc9, + 0x49, 0x7e, 0xf0, 0xd4, 0x2e, 0x00, 0x1a, 0x8d +}; +static const uint8_t nist_186_2_ecdsa_testvector_191_private[] = { +/* d - byte alignment */ + 0x02, 0xe3, 0x01, 0x5f, 0xc3, 0x01, 0x78, 0x20, 0x19, 0x46, 0x19, 0xb9, + 0x2a, 0xb7, 0x51, 0xa8, 0x25, 0x5c, 0xd2, 0xfd, 0xab, 0x80, 0x6b, 0xb5, + 0x7b, 0x12, 0x18, 0xa8, 0xce, 0xca, 0xfe, 0x26, 0xe9, 0xf6, 0xa5, 0x12 +}; +static const uint8_t nist_186_2_ecdsa_testvector_191_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x61, 0x5a, 0xb2, 0x40, 0xb7, 0xd2, 0x04, 0xa8, 0x25, 0x0d, 0x37, + 0xfc, 0x3d, 0x29, 0x89, 0xde, 0x1b, 0x49, 0xde, 0x75, 0xa9, 0x62, 0x79, + 0xa6, 0x40, 0xe6, 0x12, 0x85, 0xe5, 0x00, 0x4d, 0xb5, 0x07, 0xd1, 0xa3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_191_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0x6b, 0x8b, 0xe9, 0x30, 0xdf, 0x02, 0x42, 0x48, 0x56, 0xe0, 0x53, + 0xbf, 0x93, 0x6d, 0xbc, 0xf2, 0xe9, 0xee, 0xf6, 0x1d, 0x24, 0x19, 0xc4, + 0x53, 0x29, 0x3c, 0x37, 0xc9, 0x75, 0x41, 0xe9, 0xb6, 0x31, 0x60, 0x66 +}; +/* k = 194b411a9fbd218da63883fa439585a9c86a0e4f4a2526b6eab8de30e959e0a5872f3d3 */ +static const uint8_t nist_186_2_ecdsa_testvector_191_out[] = { +/* R - byte alignment */ + 0x02, 0xba, 0x5a, 0xb6, 0x22, 0x4c, 0x46, 0x5b, 0xa1, 0x44, 0x09, 0xd9, + 0x18, 0xdf, 0x41, 0xb0, 0xc8, 0x90, 0x9a, 0xba, 0x61, 0x1b, 0xb8, 0xf2, + 0xf5, 0x25, 0xdc, 0xa1, 0x6c, 0xa0, 0x37, 0x9c, 0x74, 0x27, 0xcb, 0x2c, +/* S - byte alignment */ + 0x00, 0x71, 0x1f, 0x14, 0x2d, 0x5e, 0x68, 0xde, 0x71, 0x6e, 0x2a, 0xb6, + 0x6f, 0x50, 0xf9, 0xbe, 0xe8, 0xa8, 0x66, 0x76, 0xe0, 0x3a, 0x74, 0x88, + 0xb6, 0x38, 0xf8, 0x66, 0x57, 0x46, 0xf2, 0xb5, 0x2d, 0x4e, 0x64, 0x2d +}; +static const uint8_t nist_186_2_ecdsa_testvector_192_ptx[] = { +/* Msg */ + 0x6b, 0x58, 0x16, 0xfe, 0xd0, 0xe5, 0x75, 0x09, 0x71, 0xff, 0x79, 0x4d, + 0xf9, 0xac, 0xdb, 0x2b, 0x91, 0x88, 0x97, 0x3f, 0xbd, 0x18, 0xf3, 0x4a, + 0x80, 0x5c, 0xbd, 0x6f, 0xc7, 0xa3, 0xd4, 0xa3, 0x05, 0xa3, 0xea, 0x5f, + 0x1a, 0xc9, 0x87, 0x97, 0x79, 0xce, 0x51, 0xf0, 0x8a, 0x8b, 0x8c, 0x2e, + 0x4d, 0x0e, 0xdd, 0xeb, 0x41, 0xed, 0x53, 0x8f, 0x84, 0xda, 0xa7, 0x7c, + 0x3b, 0x78, 0xc3, 0x89, 0x34, 0x6e, 0x82, 0xb2, 0xca, 0xb9, 0xb7, 0x0e, + 0x09, 0x46, 0x70, 0x01, 0x13, 0xc0, 0x7c, 0xb2, 0xc2, 0xa7, 0x2a, 0xbf, + 0x8f, 0xa2, 0x54, 0x30, 0xb3, 0x16, 0x9c, 0xaa, 0x8c, 0xf7, 0xf6, 0xe5, + 0x41, 0xde, 0x67, 0x60, 0xa9, 0x5c, 0x0c, 0x54, 0x69, 0x8f, 0x5d, 0xe6, + 0x5d, 0xf2, 0xb3, 0xa0, 0x3a, 0x79, 0x08, 0x22, 0x71, 0xde, 0xfe, 0x15, + 0x56, 0x35, 0x23, 0x61, 0x81, 0xc7, 0x74, 0xa0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_192_private[] = { +/* d - byte alignment */ + 0x03, 0x9f, 0x1b, 0x78, 0x58, 0x8a, 0x7a, 0xee, 0x6f, 0x2b, 0x05, 0x23, + 0xa4, 0x88, 0x58, 0x8b, 0xea, 0xc1, 0x21, 0xaf, 0x07, 0x22, 0x95, 0xd0, + 0x9c, 0x1b, 0x00, 0xcb, 0xce, 0xd9, 0xf6, 0xf3, 0x5d, 0xed, 0xe5, 0xd1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_192_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0x46, 0x51, 0x62, 0x5b, 0xcd, 0xfe, 0xdc, 0x22, 0x12, 0xa5, 0x33, + 0xc8, 0x07, 0xec, 0x31, 0x64, 0xbe, 0x42, 0x13, 0x3b, 0x4f, 0xbf, 0x8b, + 0xa2, 0xd8, 0x0c, 0xf1, 0xef, 0x17, 0x11, 0xec, 0x3a, 0x5f, 0xb8, 0x43 +}; +static const uint8_t nist_186_2_ecdsa_testvector_192_public_y[] = { +/* Qy - byte alignment */ + 0x07, 0x0a, 0xae, 0x79, 0xc0, 0x17, 0xd3, 0x45, 0x25, 0x6d, 0x43, 0x50, + 0xb8, 0x44, 0xaa, 0x20, 0x42, 0x9b, 0x2c, 0x49, 0x8d, 0x64, 0x9d, 0x35, + 0x97, 0x47, 0xd8, 0x84, 0x56, 0x03, 0x4c, 0x5b, 0xb4, 0x39, 0xe3, 0x28 +}; +/* k = 07480702d0232848fb242113f468c39d83ccf4bce0451b29f379297dfbc78b7cc782477 */ +static const uint8_t nist_186_2_ecdsa_testvector_192_out[] = { +/* R - byte alignment */ + 0x00, 0xf8, 0xe9, 0xbd, 0x16, 0xf8, 0xd2, 0x21, 0x06, 0x58, 0x69, 0x14, + 0xc7, 0x87, 0x39, 0x2c, 0x35, 0xfe, 0xd3, 0xf5, 0xaf, 0xdc, 0x12, 0x06, + 0xfd, 0x4b, 0x07, 0x3d, 0x9c, 0xbb, 0x87, 0x88, 0x3a, 0x99, 0xbb, 0xe0, +/* S - byte alignment */ + 0x00, 0x52, 0x05, 0x5f, 0x74, 0x2b, 0x05, 0xc5, 0x56, 0x79, 0xcf, 0xcc, + 0x1b, 0x7a, 0xe0, 0x17, 0xce, 0x08, 0xc7, 0x95, 0x6e, 0x5d, 0x76, 0xc1, + 0xad, 0xa0, 0x2a, 0x69, 0x80, 0xa5, 0x53, 0xee, 0x96, 0xc2, 0x59, 0xf2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_193_ptx[] = { +/* Msg */ + 0x6b, 0xea, 0xfa, 0x91, 0x27, 0x47, 0x75, 0xaf, 0x63, 0x12, 0xd1, 0xa2, + 0xb3, 0xe4, 0x55, 0x66, 0xb7, 0x2a, 0xc9, 0x73, 0x92, 0xcc, 0x88, 0x88, + 0x9e, 0x0d, 0xd7, 0xa7, 0x5f, 0xb3, 0x75, 0x60, 0xb5, 0x67, 0x74, 0x53, + 0x55, 0x5e, 0x46, 0xf1, 0x79, 0x39, 0x1b, 0x82, 0xd7, 0x2a, 0x6b, 0x6c, + 0xd0, 0x59, 0xce, 0xb2, 0xeb, 0x86, 0x14, 0xbb, 0x81, 0xef, 0x92, 0x55, + 0xba, 0x74, 0xba, 0xf9, 0xb8, 0xf9, 0xef, 0x51, 0x11, 0x0c, 0x97, 0xf7, + 0x83, 0xc7, 0x71, 0x80, 0xe3, 0xf8, 0x28, 0xb9, 0x57, 0x80, 0x29, 0x30, + 0xc5, 0xf9, 0xb2, 0xf6, 0x8b, 0x9c, 0x2c, 0xa4, 0x71, 0x61, 0xbb, 0x9c, + 0xdb, 0x67, 0x13, 0x91, 0x44, 0x97, 0x8d, 0x4a, 0xe7, 0x85, 0x7a, 0xa2, + 0xbf, 0x96, 0xb7, 0xd4, 0xb2, 0x68, 0x82, 0xf5, 0x0a, 0x6e, 0x8b, 0xc2, + 0x24, 0xdb, 0x4e, 0x9c, 0x6c, 0xc2, 0xa1, 0xd1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_193_private[] = { +/* d - byte alignment */ + 0x00, 0x8d, 0x2e, 0x32, 0x5a, 0xd4, 0xaf, 0x49, 0xfe, 0x2e, 0x60, 0xd7, + 0xff, 0xab, 0xee, 0xc2, 0x42, 0xf4, 0x76, 0xd2, 0xac, 0xe5, 0x27, 0x3f, + 0x00, 0x45, 0xe3, 0xb5, 0x15, 0xd1, 0x65, 0x20, 0x9a, 0x09, 0xfd, 0x60 +}; +static const uint8_t nist_186_2_ecdsa_testvector_193_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0x63, 0x74, 0x38, 0x13, 0x86, 0x12, 0xce, 0xad, 0x95, 0x84, 0x6c, + 0x71, 0x6e, 0x3f, 0xdf, 0x8b, 0xd1, 0xa9, 0x0d, 0x99, 0xda, 0x93, 0xcd, + 0xc6, 0x08, 0xbd, 0x42, 0x83, 0x31, 0x7a, 0xfe, 0x05, 0x36, 0x69, 0xe1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_193_public_y[] = { +/* Qy - byte alignment */ + 0x03, 0xf7, 0x81, 0x99, 0x62, 0x2b, 0x25, 0x16, 0x58, 0xa2, 0xe7, 0x3f, + 0x5d, 0x0b, 0x74, 0xa2, 0xb4, 0xae, 0x88, 0x11, 0x19, 0xb9, 0x74, 0xfa, + 0xf0, 0xb6, 0x5f, 0xed, 0x8b, 0x21, 0x75, 0x95, 0xaa, 0x94, 0x10, 0x3e +}; +/* k = 0a06efb818ad3ba2f917b8003c0c1c18a4196c94a8e2b42612ed53ed71859c6a1353bf0 */ +static const uint8_t nist_186_2_ecdsa_testvector_193_out[] = { +/* R - byte alignment */ + 0x01, 0x45, 0x4c, 0x36, 0x2f, 0x36, 0xee, 0x53, 0x2f, 0x11, 0x0c, 0x39, + 0x53, 0xdc, 0x6a, 0xa1, 0x31, 0xbd, 0xa4, 0x71, 0xb4, 0x98, 0x06, 0x0e, + 0xf8, 0x6e, 0xf3, 0x53, 0x3b, 0x3d, 0xcd, 0x92, 0x34, 0x98, 0xda, 0x4b, +/* S - byte alignment */ + 0x03, 0xff, 0x22, 0x58, 0x3b, 0x80, 0x5c, 0xc8, 0xfe, 0xa3, 0x03, 0x48, + 0x8b, 0x13, 0x22, 0x13, 0x49, 0x69, 0xd8, 0x6e, 0xe4, 0xe2, 0x43, 0xcf, + 0x5b, 0x49, 0xa7, 0x7c, 0x4d, 0x85, 0x71, 0xfe, 0xa7, 0xff, 0x27, 0xce +}; +static const uint8_t nist_186_2_ecdsa_testvector_194_ptx[] = { +/* Msg */ + 0x3a, 0x5e, 0x0b, 0xeb, 0x07, 0x2c, 0x40, 0xa7, 0xfa, 0x1c, 0x52, 0x0e, + 0x36, 0x57, 0x14, 0xaf, 0xdd, 0x08, 0x56, 0x2d, 0xd2, 0x10, 0xc3, 0x96, + 0xc4, 0xfa, 0x0a, 0xf1, 0x68, 0x31, 0x3c, 0x16, 0x05, 0x70, 0x75, 0xc3, + 0x36, 0x7b, 0xbf, 0xeb, 0xec, 0x0d, 0x33, 0x51, 0xb2, 0x11, 0x62, 0x56, + 0x35, 0x14, 0xf3, 0x0f, 0x03, 0xfb, 0x8d, 0x9b, 0x93, 0xf1, 0xf7, 0xb4, + 0x86, 0xa4, 0x7d, 0x83, 0x2c, 0xb1, 0x96, 0xb9, 0x4a, 0x5c, 0xc5, 0xdb, + 0x1a, 0x85, 0xbd, 0xdd, 0x94, 0xd8, 0xc8, 0xf3, 0xec, 0x43, 0x69, 0xa4, + 0x5c, 0xad, 0x40, 0x20, 0x23, 0xe5, 0x2f, 0xd3, 0xce, 0xd8, 0xbb, 0x3a, + 0xb6, 0x08, 0xb5, 0xf6, 0xca, 0x39, 0x19, 0x1f, 0x8e, 0x6d, 0x36, 0xda, + 0x64, 0x13, 0x0f, 0x2e, 0x0b, 0x7c, 0x02, 0x13, 0x65, 0x8e, 0xa7, 0xcc, + 0x7d, 0xbc, 0xfb, 0x77, 0xc8, 0x36, 0xbe, 0xe3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_194_private[] = { +/* d - byte alignment */ + 0x03, 0x22, 0x30, 0x44, 0xf9, 0x7b, 0xc3, 0x01, 0xa6, 0x70, 0x7e, 0xa3, + 0xd8, 0x0f, 0x5a, 0x58, 0x5e, 0x1e, 0x48, 0xbe, 0x45, 0x23, 0x86, 0x20, + 0x60, 0xa1, 0xf4, 0x59, 0xcd, 0xaa, 0x62, 0x6b, 0x7c, 0x07, 0x09, 0xc1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_194_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xba, 0xa5, 0xb0, 0x12, 0xef, 0x1b, 0x1c, 0xb4, 0xd8, 0xb4, 0x11, + 0x3b, 0x30, 0x54, 0xf7, 0xe5, 0xc9, 0x21, 0x9e, 0x88, 0x26, 0x92, 0xdb, + 0xde, 0xaa, 0xf1, 0x0f, 0x2b, 0x5a, 0x76, 0x36, 0xd0, 0x1c, 0x98, 0xe4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_194_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x15, 0xea, 0x87, 0xe5, 0xc5, 0xbb, 0xc9, 0x60, 0x18, 0xdf, 0x31, + 0xe8, 0xb5, 0x57, 0x9f, 0x9f, 0x95, 0x24, 0xd0, 0x36, 0x83, 0x74, 0x58, + 0xdf, 0xc4, 0x62, 0x86, 0x8e, 0x6f, 0x44, 0xff, 0x0a, 0x80, 0x9e, 0xf9 +}; +/* k = 19d0f59f71634f979df2f75b17e5737a2013cd01e9f0f0ede74789485b2f585ecb6ff38 */ +static const uint8_t nist_186_2_ecdsa_testvector_194_out[] = { +/* R - byte alignment */ + 0x03, 0xf2, 0xd8, 0x41, 0x61, 0x4e, 0x11, 0x76, 0xbf, 0xd7, 0x35, 0xb2, + 0x59, 0x5a, 0x3a, 0xf1, 0xbf, 0x3a, 0x46, 0xf1, 0xd6, 0xbf, 0xa3, 0xd2, + 0xbe, 0xf3, 0x3c, 0x01, 0x75, 0xde, 0x29, 0x6b, 0xec, 0x07, 0x30, 0x77, +/* S - byte alignment */ + 0x01, 0xeb, 0xff, 0x29, 0x92, 0x88, 0xb7, 0x73, 0x2a, 0x91, 0xea, 0xe3, + 0x30, 0x20, 0x81, 0xd6, 0x01, 0x0d, 0x80, 0x0b, 0xb0, 0x60, 0x2a, 0x8f, + 0x32, 0x7d, 0xc8, 0x06, 0x3f, 0xae, 0x6d, 0xf4, 0x8d, 0xaa, 0x63, 0xa2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_195_ptx[] = { +/* Msg */ + 0x9a, 0x7d, 0xd0, 0x9a, 0xe3, 0x42, 0xe2, 0x75, 0x57, 0x11, 0x35, 0x85, + 0x4f, 0xf0, 0x7e, 0x37, 0xd1, 0xe1, 0x8a, 0xb5, 0xb2, 0x71, 0x82, 0x15, + 0xfd, 0x8e, 0x6d, 0xcf, 0x99, 0x99, 0xf6, 0x75, 0x25, 0xbc, 0x6f, 0x9e, + 0x27, 0x7e, 0x17, 0x24, 0x66, 0x94, 0x98, 0x8f, 0x94, 0xfa, 0xd4, 0xd0, + 0x30, 0x43, 0xe1, 0x33, 0xab, 0x2e, 0x52, 0x8f, 0xca, 0x79, 0xb9, 0xbf, + 0x4b, 0xfa, 0x6a, 0x56, 0xcb, 0xeb, 0x81, 0x8f, 0xe7, 0x86, 0x26, 0x83, + 0xa2, 0xd2, 0x0f, 0x9f, 0x06, 0xbc, 0x47, 0x54, 0x0f, 0x69, 0x2e, 0x10, + 0xc4, 0xcb, 0xc2, 0x6e, 0xa7, 0x72, 0x1c, 0xaa, 0x4f, 0xa5, 0x3d, 0x57, + 0x54, 0xb2, 0x0b, 0x54, 0x6b, 0x82, 0x97, 0xfc, 0xd2, 0x70, 0xa1, 0x9d, + 0xef, 0x5b, 0x5e, 0x2b, 0x34, 0xfa, 0x79, 0x36, 0x45, 0x70, 0x57, 0x1a, + 0x5d, 0x21, 0x9f, 0x76, 0xee, 0xc3, 0xfa, 0xdf +}; +static const uint8_t nist_186_2_ecdsa_testvector_195_private[] = { +/* d - byte alignment */ + 0x00, 0x83, 0xff, 0xa9, 0x7b, 0x2b, 0xd8, 0x59, 0xce, 0x0c, 0xd7, 0xb9, + 0xb3, 0x68, 0x0e, 0xc2, 0xb3, 0x0e, 0xd6, 0x3b, 0xed, 0x24, 0x44, 0x04, + 0xe1, 0x9c, 0x81, 0xa8, 0x88, 0x3b, 0x7a, 0xd8, 0x68, 0xec, 0xbf, 0xb9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_195_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x36, 0x7a, 0x18, 0xb2, 0xbf, 0x2f, 0xb1, 0x24, 0x41, 0x76, 0x39, + 0xf7, 0x71, 0xaa, 0x84, 0xc4, 0xc4, 0xdf, 0x68, 0xed, 0x50, 0x9e, 0x54, + 0x36, 0xf7, 0xce, 0x48, 0x6a, 0x79, 0x1b, 0xf2, 0x16, 0x30, 0xf1, 0x25 +}; +static const uint8_t nist_186_2_ecdsa_testvector_195_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x48, 0x26, 0x14, 0xac, 0x11, 0x65, 0x3d, 0x51, 0x36, 0xa8, 0xfa, + 0x73, 0xe2, 0x98, 0x78, 0x25, 0x75, 0x1d, 0x71, 0x9f, 0x19, 0x61, 0x54, + 0x4c, 0x2e, 0x8a, 0x83, 0x87, 0x2c, 0x65, 0x0c, 0x6e, 0xad, 0x34, 0xcc +}; +/* k = 3e035a2c4706c4690fa5aee52828f2af2d00394927141ea1c1ea4e6fd5d1c7ac4fbe4fb */ +static const uint8_t nist_186_2_ecdsa_testvector_195_out[] = { +/* R - byte alignment */ + 0x01, 0xdf, 0xee, 0xdf, 0x32, 0x25, 0xb0, 0x11, 0xa1, 0x03, 0xf0, 0xa7, + 0xd9, 0x0a, 0x86, 0x01, 0xbc, 0x6c, 0x61, 0x4e, 0xa3, 0xce, 0x29, 0xb6, + 0xa7, 0xfa, 0x85, 0x82, 0x99, 0x39, 0x65, 0x80, 0x54, 0xd7, 0x3b, 0x3c, +/* S - byte alignment */ + 0x02, 0x7e, 0x4a, 0xf9, 0x09, 0x0e, 0xa2, 0x0c, 0x21, 0x84, 0x0c, 0xb1, + 0xbf, 0x82, 0xdc, 0xc5, 0xe8, 0x83, 0x97, 0x03, 0x63, 0x03, 0x31, 0xd6, + 0xef, 0x64, 0x64, 0xdd, 0x88, 0x68, 0x74, 0x5f, 0x68, 0xb3, 0xfb, 0xa4 +}; +/* [B-409] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_196_ptx[] = { +/* Msg */ + 0x84, 0x16, 0xd3, 0xb1, 0x82, 0xc3, 0x17, 0x43, 0xf4, 0x33, 0xb1, 0xfd, + 0x72, 0xf2, 0x08, 0x75, 0xcc, 0xdf, 0x94, 0x1c, 0x40, 0x8d, 0xa8, 0xc0, + 0xf0, 0xea, 0x8f, 0x55, 0x93, 0x1e, 0xdb, 0xf4, 0x6a, 0xb6, 0xfa, 0x24, + 0x75, 0x02, 0x0a, 0x59, 0xe8, 0xbb, 0xee, 0xba, 0xd9, 0xe9, 0xa2, 0x27, + 0x3b, 0x04, 0xcb, 0x7b, 0x0f, 0x5a, 0x93, 0x0e, 0xd9, 0xb0, 0xb3, 0x7f, + 0x51, 0x2c, 0xd1, 0xb0, 0x5c, 0x73, 0x0d, 0x11, 0x3a, 0x0e, 0xd7, 0x22, + 0x01, 0x12, 0x03, 0x33, 0x4a, 0x00, 0x1f, 0x6e, 0x2a, 0xea, 0x04, 0x18, + 0x64, 0xd7, 0xab, 0x14, 0xdc, 0x69, 0x42, 0xa9, 0x4f, 0xbd, 0x7f, 0x85, + 0x42, 0x93, 0x35, 0x01, 0x38, 0xaf, 0x25, 0xa6, 0x28, 0x7f, 0x16, 0xf0, + 0x2e, 0xfd, 0x28, 0x53, 0x81, 0xd7, 0x65, 0x7c, 0xa5, 0xcd, 0x99, 0xd9, + 0xe2, 0x5b, 0x63, 0x5b, 0xf4, 0x99, 0x8d, 0x7b +}; +static const uint8_t nist_186_2_ecdsa_testvector_196_private[] = { +/* d - byte alignment */ + 0x00, 0x83, 0xd2, 0x07, 0x00, 0x93, 0xf0, 0xcf, 0x1e, 0xec, 0xec, 0x5b, + 0xee, 0x3d, 0xeb, 0x44, 0x03, 0xb2, 0xe4, 0x71, 0x49, 0xbe, 0x09, 0x55, + 0x08, 0x8f, 0x95, 0xa7, 0x50, 0xd7, 0x7f, 0xd2, 0xe5, 0x93, 0xd3, 0x7b, + 0xaf, 0xe5, 0x37, 0xea, 0x79, 0xa7, 0xad, 0x33, 0xf8, 0x0b, 0xc3, 0xda, + 0xf3, 0xb4, 0x58, 0xd1 +}; +static const uint8_t nist_186_2_ecdsa_testvector_196_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x2a, 0x05, 0xf6, 0xe3, 0x18, 0x4e, 0x97, 0x24, 0x00, 0xf2, 0x6f, + 0xfa, 0xad, 0x2b, 0xee, 0x81, 0x3f, 0x4f, 0x0e, 0x9a, 0x7e, 0x76, 0xbc, + 0x21, 0x65, 0xa1, 0x07, 0xc9, 0x77, 0x0c, 0x67, 0xfa, 0x14, 0x2f, 0xe5, + 0x06, 0xb9, 0x39, 0xc7, 0x94, 0x06, 0xaa, 0x99, 0xde, 0x29, 0x1b, 0x65, + 0x7f, 0x39, 0xe8, 0xa9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_196_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xe2, 0x6d, 0x28, 0xe6, 0xa0, 0x56, 0xe9, 0x4e, 0xd6, 0xc0, 0x12, + 0x60, 0x69, 0x5f, 0xaf, 0xe4, 0x4d, 0x44, 0xcd, 0xf3, 0x4f, 0xb4, 0x09, + 0x58, 0xdc, 0xa1, 0x80, 0xd1, 0x5f, 0x3e, 0x67, 0xb6, 0xda, 0x1d, 0x4b, + 0x2b, 0x0e, 0xc9, 0xfa, 0xa0, 0xdc, 0x3c, 0x6d, 0x60, 0x8f, 0x27, 0xb2, + 0x5c, 0x2b, 0x08, 0x7a +}; +/* k = 0eb71c20ffcf0445bc220da612064ea36f0b8f1a6e9532f6739d3888f906785ebd04987671df192e77fd070b090fba2e8a67b8d */ +static const uint8_t nist_186_2_ecdsa_testvector_196_out[] = { +/* R - byte alignment */ + 0x00, 0x4f, 0x4d, 0x74, 0x92, 0x7e, 0x6a, 0x86, 0x06, 0x54, 0xf1, 0x3d, + 0xe1, 0xda, 0x11, 0x20, 0x1a, 0x54, 0xcf, 0x2c, 0x52, 0xcd, 0x2a, 0x25, + 0xbf, 0xb7, 0x1a, 0x6a, 0xf3, 0xf1, 0xbd, 0x1c, 0x2b, 0x2c, 0xdb, 0x73, + 0x20, 0x09, 0x8d, 0x5c, 0xc7, 0x2e, 0x39, 0x63, 0xf7, 0x03, 0xc2, 0x9c, + 0xcf, 0xeb, 0x1b, 0x82, +/* S - byte alignment */ + 0x00, 0x20, 0x71, 0x0e, 0x88, 0xc7, 0x79, 0x36, 0x38, 0x9b, 0xd0, 0x77, + 0x42, 0xe4, 0x16, 0xca, 0xb0, 0x94, 0x8a, 0x17, 0x31, 0x4a, 0x49, 0xe1, + 0xa9, 0xec, 0x59, 0xd0, 0x1f, 0xb4, 0xe0, 0x82, 0x9a, 0x27, 0x59, 0x68, + 0xc9, 0x7b, 0x5a, 0x69, 0x25, 0x6b, 0x4e, 0x9d, 0x2b, 0x40, 0x80, 0x8d, + 0x02, 0x44, 0x26, 0xcf +}; +static const uint8_t nist_186_2_ecdsa_testvector_197_ptx[] = { +/* Msg */ + 0x9d, 0xbc, 0x49, 0x51, 0xe3, 0x23, 0xae, 0x97, 0xec, 0xaf, 0x51, 0x1f, + 0x46, 0x0a, 0x42, 0x85, 0xac, 0x54, 0x32, 0x84, 0x7a, 0xc6, 0x88, 0xbc, + 0x64, 0x96, 0xb2, 0xb2, 0x66, 0x1b, 0xb9, 0x19, 0xfe, 0x32, 0x19, 0x50, + 0x9a, 0xe0, 0xcf, 0x2b, 0x4c, 0x39, 0xb3, 0xf6, 0xc5, 0x80, 0x08, 0xb7, + 0x81, 0x8f, 0x52, 0xb4, 0x3f, 0x79, 0x67, 0x35, 0xb4, 0x6f, 0xc9, 0x8b, + 0x80, 0xe0, 0x33, 0x51, 0x61, 0xe4, 0x72, 0xf2, 0xa7, 0xdb, 0x76, 0x6c, + 0xe8, 0x51, 0xa9, 0x53, 0xf4, 0x26, 0x80, 0x18, 0x0b, 0xeb, 0x4f, 0x8b, + 0x4e, 0x8e, 0x61, 0x9f, 0x74, 0x3a, 0x48, 0x6d, 0xbe, 0x79, 0x72, 0x7c, + 0x2d, 0x9c, 0xfd, 0x40, 0xf2, 0x5c, 0xcc, 0xe0, 0x26, 0xc1, 0xdb, 0x3d, + 0xbb, 0x43, 0xcf, 0x2f, 0xb3, 0x30, 0xd2, 0x11, 0x8f, 0x4d, 0x9d, 0x81, + 0x0b, 0xc0, 0xd6, 0x61, 0x08, 0x2d, 0x9d, 0x21 +}; +static const uint8_t nist_186_2_ecdsa_testvector_197_private[] = { +/* d - byte alignment */ + 0x00, 0x0a, 0x9c, 0x92, 0x40, 0xd3, 0xe8, 0x29, 0x09, 0xd8, 0x6a, 0xf8, + 0x98, 0xa9, 0xf1, 0x69, 0x4b, 0x5e, 0x6c, 0x19, 0x38, 0xa3, 0x23, 0x5f, + 0x5c, 0x14, 0x8b, 0xa4, 0xfd, 0x5f, 0x07, 0x50, 0xc9, 0xe7, 0x33, 0x82, + 0x4c, 0xa9, 0xda, 0x34, 0xca, 0x23, 0x25, 0x54, 0xd8, 0x60, 0x1a, 0x11, + 0xcc, 0xec, 0x7c, 0xed +}; +static const uint8_t nist_186_2_ecdsa_testvector_197_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xf5, 0x35, 0xe9, 0xf4, 0xe7, 0x8c, 0x2e, 0x20, 0x7c, 0xa5, 0x92, + 0x88, 0x5d, 0x03, 0x31, 0x37, 0x5d, 0x72, 0xf9, 0x99, 0x7a, 0x22, 0x76, + 0xc4, 0x12, 0xe7, 0x74, 0x8f, 0xa1, 0x7d, 0x5d, 0xe6, 0x86, 0xfe, 0x85, + 0x9e, 0xdd, 0x64, 0x3e, 0x18, 0x0f, 0xd7, 0x87, 0x2b, 0x3c, 0x75, 0x98, + 0x4d, 0x11, 0x4e, 0x2f +}; +static const uint8_t nist_186_2_ecdsa_testvector_197_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xf2, 0x43, 0x3a, 0x78, 0xac, 0xae, 0xad, 0x2a, 0x3c, 0xca, 0x87, + 0xea, 0xbd, 0x0a, 0x03, 0xa2, 0xf1, 0x22, 0x69, 0xbb, 0xea, 0x25, 0xe5, + 0xdd, 0x56, 0x5c, 0xf3, 0x46, 0xd6, 0x56, 0x95, 0x3c, 0xa9, 0x6d, 0x70, + 0x3d, 0x11, 0x34, 0x30, 0xa0, 0xb2, 0xa0, 0xb2, 0xe6, 0xe9, 0x90, 0xd8, + 0x23, 0xe8, 0x9d, 0x5b +}; +/* k = 021133e73d9ea0bdab83640d1652b88804454500893f1653a673b84cc6a6b9877adbd655c076af2980299e98f67738a5258c54f */ +static const uint8_t nist_186_2_ecdsa_testvector_197_out[] = { +/* R - byte alignment */ + 0x00, 0x72, 0x39, 0xa2, 0xc9, 0x1e, 0xc7, 0x01, 0x88, 0x3f, 0xb9, 0x63, + 0xd6, 0x52, 0xd9, 0x82, 0xd5, 0x91, 0x9e, 0xd7, 0x4f, 0x3b, 0xce, 0x8d, + 0xc7, 0x3c, 0x18, 0x19, 0x72, 0x2c, 0x85, 0x65, 0x0e, 0x89, 0x6b, 0x3d, + 0x95, 0xb9, 0xe4, 0x7d, 0xbe, 0xda, 0x72, 0x47, 0x60, 0x29, 0x17, 0x13, + 0xb1, 0x70, 0xe0, 0x95, +/* S - byte alignment */ + 0x00, 0x32, 0x8e, 0x43, 0x23, 0x00, 0x14, 0xef, 0x7c, 0x6e, 0xa0, 0x87, + 0x72, 0xa3, 0xb7, 0x95, 0x89, 0xf4, 0x12, 0xf3, 0xaf, 0x4e, 0x4e, 0x23, + 0x14, 0xe4, 0x0a, 0xb6, 0x7b, 0x81, 0xdc, 0x5a, 0xab, 0x46, 0x7e, 0x31, + 0x5b, 0xa3, 0x0a, 0x0b, 0xa3, 0xd1, 0x82, 0x49, 0xb1, 0xeb, 0x9e, 0x45, + 0xd3, 0x50, 0xae, 0x35 +}; +static const uint8_t nist_186_2_ecdsa_testvector_198_ptx[] = { +/* Msg */ + 0xe7, 0x70, 0x25, 0xc9, 0x85, 0x8e, 0x2a, 0xdc, 0x23, 0x65, 0xcc, 0xbc, + 0x6e, 0x03, 0xb4, 0x01, 0xeb, 0xe9, 0x2c, 0x5b, 0xdb, 0x62, 0x26, 0x82, + 0x63, 0x13, 0x80, 0x70, 0xe9, 0xd2, 0x86, 0xcd, 0xc1, 0xbc, 0xb9, 0xab, + 0x09, 0x81, 0xcf, 0x73, 0xd1, 0x03, 0xfa, 0x1f, 0x80, 0x20, 0x6d, 0xaa, + 0x72, 0xcb, 0x1d, 0xc5, 0xe6, 0x62, 0xc4, 0xcc, 0x18, 0x3b, 0x2c, 0xf8, + 0xaa, 0x81, 0xaa, 0xd6, 0x48, 0x3e, 0xe8, 0xf8, 0x8c, 0xb8, 0xe8, 0xea, + 0x1f, 0x01, 0x46, 0x67, 0x22, 0xca, 0xbe, 0xcd, 0xcc, 0x78, 0xed, 0xcf, + 0x54, 0x7a, 0x5c, 0x6a, 0x11, 0xd9, 0xba, 0x1a, 0xe0, 0x10, 0x69, 0x4d, + 0xc6, 0x1f, 0x3d, 0x18, 0xd6, 0xdb, 0x80, 0x29, 0x55, 0x88, 0x39, 0xfd, + 0x1d, 0xa9, 0xad, 0x53, 0x3f, 0x17, 0x27, 0xe0, 0xec, 0x51, 0xf5, 0x44, + 0x96, 0x13, 0xb3, 0x3d, 0x52, 0x2a, 0xcc, 0x1a +}; +static const uint8_t nist_186_2_ecdsa_testvector_198_private[] = { +/* d - byte alignment */ + 0x00, 0xb9, 0xad, 0x78, 0x4b, 0xfd, 0x87, 0xb3, 0xea, 0xa6, 0x13, 0x1f, + 0xc8, 0x27, 0x3c, 0x88, 0x93, 0xad, 0xe1, 0xca, 0x44, 0x49, 0x76, 0xdd, + 0x25, 0x8b, 0xe5, 0xdd, 0xab, 0xa0, 0xb8, 0xdd, 0xfb, 0x9d, 0xce, 0x58, + 0x95, 0x7a, 0x7e, 0x41, 0xf9, 0xad, 0x60, 0xc9, 0x49, 0x70, 0x22, 0xbb, + 0xe7, 0x24, 0x49, 0x9d +}; +static const uint8_t nist_186_2_ecdsa_testvector_198_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xc6, 0xf4, 0x92, 0x77, 0x11, 0x0d, 0xef, 0xb2, 0x02, 0x7b, 0x3e, + 0xac, 0xc9, 0x32, 0x8b, 0x4c, 0x9b, 0xb7, 0x7e, 0x7b, 0xa2, 0xf8, 0xbf, + 0x68, 0x89, 0x55, 0xe4, 0xa8, 0x59, 0x84, 0xe7, 0x51, 0x36, 0xab, 0x6a, + 0x98, 0x91, 0x76, 0x6d, 0x87, 0xf2, 0xde, 0x5a, 0x23, 0x49, 0x2f, 0xc1, + 0x06, 0x72, 0x74, 0x0d +}; +static const uint8_t nist_186_2_ecdsa_testvector_198_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xf6, 0xf3, 0xe5, 0x87, 0x4b, 0x9a, 0x51, 0x4a, 0xac, 0xfc, 0x66, + 0x1e, 0x7d, 0x98, 0x7c, 0x01, 0xbd, 0xe6, 0xee, 0xf2, 0x81, 0xb9, 0xce, + 0xe6, 0x6f, 0x66, 0xc6, 0x54, 0x3f, 0xe9, 0x26, 0x19, 0xf9, 0x42, 0xa4, + 0x0d, 0x7a, 0xd5, 0xa7, 0xea, 0xd3, 0x98, 0x5b, 0x2b, 0x5f, 0x39, 0x1f, + 0x20, 0x45, 0xfd, 0x69 +}; +/* k = 053a5ae09193c3ba143cb46dc8803eadcf0cff0cb5739efc349c5e8172845ee8f27d5ae18847a8e0996ab649f5986e80cac0320 */ +static const uint8_t nist_186_2_ecdsa_testvector_198_out[] = { +/* R - byte alignment */ + 0x00, 0x67, 0x16, 0xff, 0x3d, 0x60, 0x1d, 0x13, 0x01, 0xf1, 0xe4, 0xff, + 0xc1, 0xcf, 0xef, 0x3e, 0x90, 0xc0, 0x7b, 0x95, 0x8d, 0xb8, 0x61, 0xbd, + 0x43, 0x2c, 0x39, 0xcc, 0xdc, 0x38, 0x41, 0xda, 0x5b, 0x9e, 0x0b, 0x8b, + 0x39, 0xeb, 0xc2, 0xef, 0xf8, 0x03, 0xb9, 0x11, 0x44, 0x03, 0x7a, 0x63, + 0xf1, 0x1c, 0x97, 0xb3, +/* S - byte alignment */ + 0x00, 0x35, 0xe7, 0x30, 0x6a, 0x4c, 0x0f, 0xdb, 0x82, 0x35, 0xbd, 0x21, + 0x28, 0x96, 0x9d, 0xda, 0x0f, 0x64, 0x35, 0x59, 0xda, 0xeb, 0xa7, 0x51, + 0x78, 0xe5, 0x66, 0x6d, 0x5f, 0x21, 0xa5, 0xf8, 0x3d, 0x12, 0xfe, 0xf7, + 0x95, 0xfd, 0xa3, 0x40, 0xa8, 0x15, 0xe1, 0x96, 0x2e, 0x9b, 0xd0, 0x0d, + 0xe8, 0xcb, 0x08, 0x7f +}; +static const uint8_t nist_186_2_ecdsa_testvector_199_ptx[] = { +/* Msg */ + 0x4d, 0xcc, 0x25, 0x48, 0x48, 0x3f, 0xdf, 0x25, 0xd6, 0x69, 0x2e, 0x15, + 0xab, 0x39, 0x13, 0xaa, 0x62, 0xf0, 0x9b, 0x49, 0x1e, 0x32, 0xaa, 0xdb, + 0x72, 0x5d, 0xf7, 0xc4, 0x7e, 0x1b, 0x58, 0x19, 0x5b, 0x33, 0x40, 0x0d, + 0xba, 0xa5, 0x85, 0xad, 0xc7, 0xf5, 0x67, 0xce, 0x54, 0xc7, 0xcf, 0x43, + 0x33, 0xac, 0xd4, 0x53, 0xe3, 0x3c, 0x83, 0x6a, 0x70, 0x65, 0xe0, 0x0e, + 0x94, 0x02, 0x28, 0x15, 0x22, 0xaf, 0x59, 0x15, 0xa4, 0xdc, 0xf4, 0x1d, + 0x43, 0x21, 0x02, 0xa2, 0xe8, 0xd1, 0x55, 0xbc, 0xa1, 0xd2, 0x10, 0x93, + 0x46, 0xac, 0x6a, 0x13, 0x5c, 0xdf, 0xae, 0xe8, 0x39, 0x7a, 0x86, 0xa6, + 0x69, 0xe9, 0x7a, 0x47, 0x51, 0x0f, 0xb4, 0xdb, 0x12, 0x95, 0x06, 0x7b, + 0xb1, 0x81, 0x2e, 0x7f, 0x74, 0x0a, 0x58, 0xf1, 0x8f, 0xaa, 0xe4, 0x41, + 0xff, 0x76, 0x6a, 0x39, 0xb7, 0xab, 0xfb, 0x34 +}; +static const uint8_t nist_186_2_ecdsa_testvector_199_private[] = { +/* d - byte alignment */ + 0x00, 0x9b, 0xb0, 0x0b, 0x37, 0xcd, 0x84, 0xb4, 0x15, 0x5e, 0xc5, 0x94, + 0x91, 0xa0, 0x02, 0xb7, 0xf0, 0xdb, 0x38, 0xb4, 0xa1, 0xaf, 0x39, 0xe8, + 0xae, 0xab, 0x83, 0xe7, 0x10, 0xb2, 0xe4, 0xe4, 0x3e, 0xbb, 0xa3, 0x64, + 0xc6, 0xeb, 0x6a, 0x5e, 0x61, 0xd3, 0x64, 0x26, 0xcd, 0x66, 0x81, 0x5c, + 0x79, 0xfa, 0x21, 0x9d +}; +static const uint8_t nist_186_2_ecdsa_testvector_199_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x85, 0x8a, 0x4a, 0xc6, 0x13, 0x19, 0x53, 0xd6, 0xbf, 0x24, 0x58, + 0xf2, 0x3c, 0x83, 0x2f, 0x23, 0x1d, 0xad, 0x09, 0x4d, 0x08, 0x74, 0xca, + 0x02, 0x2d, 0x99, 0x11, 0xa7, 0x86, 0x12, 0xd5, 0xe6, 0x3e, 0xf9, 0x07, + 0xd8, 0x2f, 0xf8, 0xb4, 0x39, 0x2e, 0x40, 0xe5, 0x53, 0x53, 0x83, 0x85, + 0x5e, 0x28, 0xa5, 0x39 +}; +static const uint8_t nist_186_2_ecdsa_testvector_199_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xf9, 0xa5, 0x52, 0xbd, 0x3c, 0x18, 0x3a, 0xc8, 0x85, 0xe4, 0x11, + 0x8b, 0x21, 0x85, 0x4a, 0x0d, 0x36, 0x9a, 0xd9, 0x1b, 0x3a, 0xce, 0x47, + 0x07, 0xcb, 0x6e, 0x6a, 0x99, 0xe0, 0xe6, 0xb0, 0x54, 0xda, 0x4d, 0x71, + 0xfe, 0x69, 0xe9, 0x9d, 0x07, 0x2a, 0xb8, 0x65, 0x33, 0x4f, 0x6f, 0x63, + 0xdb, 0x9b, 0x4e, 0xa7 +}; +/* k = 029691df256d0b4794600f785f809922326b9c2553488cfb7aa60b311932b32822583b5c60463b2ff901a1a35cca0641c4fc0cc */ +static const uint8_t nist_186_2_ecdsa_testvector_199_out[] = { +/* R - byte alignment */ + 0x00, 0xd9, 0x3c, 0x6f, 0xfd, 0x1f, 0x80, 0x7a, 0x49, 0x08, 0xcb, 0x3b, + 0xef, 0x22, 0xf5, 0x57, 0x66, 0x4a, 0x16, 0x07, 0xce, 0x04, 0x40, 0x74, + 0xc4, 0x1e, 0x56, 0x8d, 0xb4, 0x7e, 0x67, 0x19, 0x6a, 0x6e, 0x50, 0x38, + 0x5b, 0x8a, 0xb5, 0x95, 0x89, 0x82, 0x77, 0x67, 0xb1, 0xaa, 0xa1, 0xb3, + 0x48, 0xb2, 0xf2, 0xbd, +/* S - byte alignment */ + 0x00, 0xa1, 0x8f, 0x0f, 0x28, 0xb5, 0xbf, 0x3c, 0xe8, 0x70, 0xb9, 0x48, + 0xb5, 0x5f, 0xdb, 0xce, 0xa9, 0x91, 0x61, 0x3d, 0x0b, 0x74, 0xa5, 0xc5, + 0x0e, 0xaf, 0xc2, 0x65, 0xff, 0x02, 0x3b, 0x8c, 0x6f, 0x85, 0x64, 0xde, + 0xa5, 0x5c, 0xa7, 0x61, 0x7f, 0x46, 0xab, 0x90, 0x62, 0x55, 0xf4, 0x30, + 0x3b, 0x96, 0x15, 0xda +}; +static const uint8_t nist_186_2_ecdsa_testvector_200_ptx[] = { +/* Msg */ + 0xa3, 0xcb, 0x2e, 0x23, 0xd8, 0x2b, 0x4b, 0x50, 0x01, 0xde, 0xe9, 0x91, + 0x31, 0xb7, 0x5e, 0x71, 0x13, 0xca, 0x3f, 0xc1, 0x89, 0x7e, 0x27, 0x44, + 0x92, 0xe3, 0xb3, 0xac, 0x71, 0x45, 0xd1, 0xc5, 0x0c, 0x01, 0x3b, 0xf1, + 0x92, 0x97, 0x3e, 0xd4, 0x60, 0x01, 0xc0, 0x50, 0x26, 0x43, 0x81, 0xb4, + 0x45, 0x44, 0xa1, 0x30, 0x7c, 0xdc, 0x63, 0x8d, 0xc4, 0x2e, 0x30, 0x1a, + 0x78, 0x38, 0xdf, 0xea, 0xb9, 0xa8, 0x33, 0x3c, 0x11, 0xf1, 0xa5, 0x3b, + 0x56, 0x9f, 0x64, 0xe8, 0xd2, 0xe7, 0x9b, 0x54, 0xa0, 0x83, 0xf2, 0x12, + 0x59, 0xbd, 0x57, 0xec, 0xf1, 0xc9, 0xfe, 0xd5, 0xdb, 0x57, 0xa6, 0x1f, + 0x74, 0x69, 0x1f, 0xee, 0x9e, 0x62, 0x09, 0xed, 0xab, 0x60, 0xde, 0x3f, + 0x7e, 0xcc, 0x33, 0xb9, 0xec, 0x30, 0x3a, 0x4e, 0x68, 0x48, 0x8c, 0xca, + 0xe0, 0x5b, 0x25, 0xc4, 0xe2, 0xcb, 0xb0, 0xcd +}; +static const uint8_t nist_186_2_ecdsa_testvector_200_private[] = { +/* d - byte alignment */ + 0x00, 0x4a, 0xba, 0xab, 0x51, 0xaa, 0xd7, 0x0e, 0x18, 0x6d, 0xe5, 0x77, + 0x34, 0xeb, 0x32, 0xbf, 0xfc, 0x39, 0x28, 0x7c, 0xf3, 0x59, 0x7c, 0xa5, + 0xa1, 0x5f, 0x18, 0x1b, 0xc1, 0x69, 0xc8, 0x87, 0xdd, 0xb1, 0x4e, 0x20, + 0x94, 0xac, 0xcb, 0xba, 0x06, 0xd4, 0xa7, 0xed, 0x6d, 0x86, 0xfd, 0x38, + 0x89, 0x9a, 0x5c, 0x4e +}; +static const uint8_t nist_186_2_ecdsa_testvector_200_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x8b, 0x4a, 0x5f, 0x7c, 0xd1, 0x2b, 0x74, 0xe7, 0xe3, 0xd3, 0x3a, + 0xe4, 0x79, 0x15, 0xf7, 0x25, 0xe5, 0x6a, 0x13, 0xe2, 0x2a, 0x4e, 0x07, + 0xcd, 0x8c, 0x5e, 0x1f, 0x65, 0x0a, 0xcb, 0x69, 0x74, 0x91, 0x8a, 0x81, + 0x44, 0xeb, 0xf7, 0xe7, 0x8d, 0xad, 0xb1, 0x8f, 0x0f, 0x30, 0x5a, 0xac, + 0x68, 0x75, 0x74, 0xef +}; +static const uint8_t nist_186_2_ecdsa_testvector_200_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x9c, 0x5f, 0xc9, 0xce, 0x7d, 0x5a, 0x4a, 0xe3, 0x42, 0x8f, 0xc9, + 0x4c, 0xf2, 0x4e, 0xcb, 0xab, 0xf2, 0x68, 0xcc, 0x47, 0x21, 0xce, 0xcb, + 0x8b, 0xd7, 0x02, 0x84, 0x20, 0x0e, 0x97, 0x55, 0xde, 0x4a, 0xf2, 0x01, + 0x4f, 0xaa, 0xa6, 0x38, 0x54, 0xd6, 0x0f, 0x2a, 0xda, 0x89, 0x5b, 0x90, + 0x55, 0x91, 0x10, 0xd4 +}; +/* k = 0c0109b439973efd6d62bf38c4d7afa79d756e9d97433d7748dbaa635a3ffbd5ff3b9224d926d71f5c9e3eefc57f9a3da352523 */ +static const uint8_t nist_186_2_ecdsa_testvector_200_out[] = { +/* R - byte alignment */ + 0x00, 0xce, 0xe8, 0xe0, 0x19, 0xd4, 0xb2, 0x3d, 0x36, 0xd8, 0x9f, 0xd4, + 0x39, 0x1a, 0x92, 0x2c, 0x66, 0xb0, 0xc2, 0xf0, 0x1e, 0xda, 0x9a, 0x22, + 0xdd, 0x1e, 0x9a, 0x48, 0x0d, 0x3f, 0x4f, 0xdb, 0x50, 0xb1, 0x29, 0x63, + 0xec, 0x7f, 0x55, 0x92, 0x87, 0x94, 0x72, 0x9c, 0x7d, 0x6c, 0x0a, 0x0c, + 0x1e, 0x1f, 0x8b, 0xdf, +/* S - byte alignment */ + 0x00, 0x45, 0x94, 0x13, 0x1a, 0x93, 0x19, 0x66, 0x08, 0xca, 0x3a, 0x24, + 0xd3, 0x9a, 0xaf, 0xdd, 0x5d, 0xb2, 0xee, 0xb0, 0x3c, 0x2e, 0x8d, 0x6b, + 0xdf, 0xc8, 0x22, 0xb5, 0x6f, 0x64, 0x82, 0xbe, 0xac, 0xa1, 0xdf, 0x3c, + 0x47, 0x2f, 0xec, 0x59, 0xab, 0x88, 0x28, 0x2e, 0x02, 0x07, 0xb3, 0x7e, + 0x35, 0x17, 0x8f, 0x3e +}; +static const uint8_t nist_186_2_ecdsa_testvector_201_ptx[] = { +/* Msg */ + 0x73, 0x1c, 0x69, 0x97, 0xfc, 0x71, 0xd6, 0x4c, 0x29, 0x43, 0x91, 0xc7, + 0xf1, 0x80, 0x60, 0x08, 0x65, 0xc1, 0x07, 0x13, 0x87, 0xd0, 0xbb, 0x96, + 0x5e, 0x68, 0xd9, 0xcc, 0x4a, 0x3b, 0xd8, 0xa1, 0x96, 0x39, 0x7d, 0x17, + 0x4c, 0x10, 0x4d, 0xe8, 0x4d, 0xef, 0x48, 0x6d, 0xa0, 0x90, 0xd4, 0xbe, + 0x0b, 0x75, 0xf8, 0x1b, 0xe0, 0x72, 0xca, 0x8b, 0x1a, 0x6b, 0x2b, 0xc2, + 0xa8, 0x5f, 0xb1, 0x48, 0x09, 0xa5, 0xe5, 0xd8, 0x19, 0x76, 0xaf, 0x07, + 0x2b, 0xac, 0x0e, 0x26, 0x57, 0xc9, 0x0c, 0x68, 0x16, 0x3b, 0xf2, 0x48, + 0x0c, 0xdf, 0xb8, 0x25, 0x24, 0xc3, 0xbf, 0x2f, 0xe2, 0x30, 0xc3, 0x87, + 0xf5, 0xe8, 0x0b, 0xa2, 0x0c, 0xac, 0xe2, 0xef, 0xeb, 0x01, 0x4b, 0xb9, + 0xbe, 0x34, 0xf1, 0x4e, 0xad, 0x9c, 0x5d, 0x61, 0xb0, 0x1f, 0x6b, 0xad, + 0xa5, 0xf7, 0xff, 0xdb, 0xa0, 0xb6, 0xf4, 0xa6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_201_private[] = { +/* d - byte alignment */ + 0x00, 0x12, 0xee, 0xe9, 0x8d, 0x39, 0xf1, 0x54, 0x1f, 0x70, 0xb2, 0xc5, + 0x45, 0xbe, 0xc7, 0x4b, 0x66, 0x84, 0x47, 0xb9, 0x42, 0x45, 0x9a, 0x1e, + 0xd8, 0xdf, 0xcd, 0x93, 0xc0, 0xf1, 0x5f, 0x94, 0x4d, 0xb7, 0x66, 0x66, + 0x36, 0x40, 0x81, 0xfc, 0x0d, 0xd3, 0xaf, 0xb3, 0xbe, 0xf7, 0xf5, 0xb5, + 0x90, 0x92, 0xcf, 0x8f +}; +static const uint8_t nist_186_2_ecdsa_testvector_201_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xdc, 0x4b, 0xca, 0x5f, 0xf4, 0x2c, 0xe3, 0xf0, 0xf4, 0x14, 0x1e, + 0x91, 0x2c, 0xbb, 0xcf, 0x56, 0x20, 0x87, 0x1f, 0xa3, 0x5d, 0xe2, 0x7d, + 0xc7, 0xf3, 0xf0, 0xfd, 0x80, 0x75, 0x24, 0xba, 0x64, 0x98, 0x1f, 0x16, + 0x4c, 0xa5, 0x45, 0x3d, 0xc5, 0xb2, 0xa3, 0x63, 0x8e, 0x1f, 0xea, 0x84, + 0x18, 0x72, 0x8a, 0x3f +}; +static const uint8_t nist_186_2_ecdsa_testvector_201_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x1e, 0xc0, 0xf5, 0x90, 0x1e, 0xe9, 0x03, 0xe6, 0x04, 0xe9, 0xe6, + 0xc8, 0x3c, 0x5e, 0xf8, 0x4b, 0x0a, 0x16, 0x54, 0xe9, 0xdd, 0xbd, 0xd5, + 0x62, 0xd2, 0xb2, 0x23, 0x1b, 0x8f, 0x5b, 0x5f, 0xdd, 0x6d, 0x8e, 0xaf, + 0x04, 0x3b, 0xf3, 0x27, 0x4e, 0xf5, 0x12, 0xab, 0x7a, 0xd7, 0x88, 0x64, + 0xef, 0x89, 0xa0, 0x6d +}; +/* k = 0d98a9c6d99e49fc3657a674f483cf87d3848b199d8decf7478035807f25bcbf02af09055f8156176ab814ee87e29d5ae978bed */ +static const uint8_t nist_186_2_ecdsa_testvector_201_out[] = { +/* R - byte alignment */ + 0x00, 0x16, 0xd5, 0xc0, 0xc9, 0xca, 0xed, 0x1e, 0xf8, 0x71, 0x09, 0x6f, + 0xea, 0x97, 0x10, 0x29, 0x8b, 0x21, 0x01, 0x4b, 0x00, 0xba, 0x27, 0xaa, + 0x22, 0x81, 0x77, 0x84, 0x8d, 0xdf, 0x63, 0x9a, 0xef, 0xbe, 0x8f, 0xae, + 0x05, 0xd4, 0x04, 0xb4, 0xca, 0x57, 0x06, 0x15, 0xa7, 0x1d, 0xa4, 0xf4, + 0xae, 0x0a, 0xaa, 0x43, +/* S - byte alignment */ + 0x00, 0xca, 0xe8, 0xea, 0xbd, 0x63, 0x3f, 0xef, 0x32, 0x15, 0x39, 0x3b, + 0x5b, 0x84, 0x98, 0xc6, 0xfb, 0xf4, 0x82, 0xd6, 0x6b, 0xf8, 0x5e, 0x91, + 0x13, 0x83, 0xc6, 0x4c, 0x97, 0x6e, 0x22, 0xb5, 0x53, 0x68, 0x8d, 0xdd, + 0x9c, 0xdc, 0xdb, 0xca, 0x26, 0x78, 0x5d, 0xc0, 0x1f, 0x39, 0x50, 0x21, + 0xd1, 0x97, 0x17, 0xad +}; +static const uint8_t nist_186_2_ecdsa_testvector_202_ptx[] = { +/* Msg */ + 0x7a, 0x4d, 0xde, 0x7d, 0x59, 0x8a, 0xd7, 0xc3, 0x35, 0x34, 0x66, 0xb2, + 0xd7, 0x39, 0xcf, 0x4a, 0xd6, 0x29, 0x75, 0x33, 0xc6, 0x99, 0xab, 0x46, + 0xad, 0xc5, 0xc8, 0x4f, 0xb6, 0x79, 0x79, 0x11, 0x2a, 0x31, 0x5c, 0x8b, + 0x9b, 0x7f, 0xca, 0x7a, 0x63, 0xad, 0xf4, 0x1f, 0x4d, 0xa3, 0x31, 0x42, + 0x91, 0x0c, 0x96, 0x77, 0x06, 0xb5, 0xc8, 0xa0, 0x93, 0x35, 0x0e, 0xb3, + 0xe6, 0xd3, 0xaa, 0xbe, 0x69, 0xa4, 0x6a, 0x28, 0x72, 0xf4, 0x7a, 0x39, + 0xbb, 0xe7, 0x7c, 0xdc, 0x11, 0x60, 0xda, 0xa4, 0x50, 0x22, 0x5b, 0x0e, + 0x8e, 0x36, 0xf5, 0x06, 0x97, 0x8c, 0xe3, 0xac, 0x9a, 0xe5, 0xf7, 0x57, + 0x21, 0xef, 0x30, 0xda, 0x46, 0xb2, 0x8f, 0x07, 0x24, 0x2c, 0x27, 0x72, + 0x8d, 0x38, 0x74, 0x78, 0xfb, 0xb5, 0xed, 0x7f, 0xc8, 0xe3, 0xdc, 0x7e, + 0xa1, 0x10, 0x6e, 0xc1, 0x38, 0x75, 0x06, 0xe6 +}; +static const uint8_t nist_186_2_ecdsa_testvector_202_private[] = { +/* d - byte alignment */ + 0x00, 0x3d, 0xda, 0x4a, 0xcf, 0x12, 0x75, 0xa9, 0xc8, 0xd7, 0xda, 0x0c, + 0x7b, 0xcc, 0x1f, 0x06, 0xb8, 0xc3, 0xeb, 0x44, 0x47, 0x2d, 0x81, 0xf5, + 0x01, 0x5e, 0x7b, 0x39, 0x74, 0xbc, 0x72, 0x71, 0x7f, 0x4c, 0x81, 0x13, + 0xf7, 0x2f, 0xcf, 0xb6, 0xba, 0xd5, 0xe1, 0x0a, 0x4f, 0x57, 0xe0, 0x6a, + 0x4a, 0x7d, 0x61, 0x62 +}; +static const uint8_t nist_186_2_ecdsa_testvector_202_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xd8, 0x64, 0x9a, 0xc8, 0xd0, 0x85, 0x6c, 0x86, 0x21, 0xe7, 0xb7, + 0x01, 0xaa, 0x2d, 0x86, 0x9f, 0x18, 0xf0, 0x12, 0x39, 0x16, 0x89, 0xa7, + 0xfb, 0xb3, 0x82, 0x8d, 0xc8, 0xef, 0xac, 0xcc, 0xa7, 0x04, 0x87, 0x8b, + 0xc2, 0x97, 0xe1, 0x06, 0x33, 0xb4, 0x2b, 0x1c, 0x22, 0x15, 0xc8, 0xf4, + 0x16, 0xf7, 0xd8, 0x49 +}; +static const uint8_t nist_186_2_ecdsa_testvector_202_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x4d, 0x30, 0x26, 0xd0, 0xe8, 0x77, 0x1c, 0xf3, 0x27, 0xc3, 0x81, + 0xbf, 0xfe, 0x50, 0xc2, 0x8f, 0xdd, 0x00, 0x88, 0x24, 0xd8, 0x89, 0xc0, + 0x37, 0x2b, 0x27, 0x02, 0xd4, 0xb2, 0x1d, 0x46, 0x51, 0x1d, 0x00, 0xba, + 0x42, 0x4f, 0xe5, 0x61, 0x39, 0x40, 0xc9, 0x8b, 0xde, 0x1c, 0x0c, 0x37, + 0x31, 0x52, 0x24, 0x1e +}; +/* k = 035f0a268fa93e03e6c2ad7a28c61ab3e19e83a41d5d9f28865cce8eb3a5bc8ed4bd6c5e744444959d762f6b30ed63405667ee7 */ +static const uint8_t nist_186_2_ecdsa_testvector_202_out[] = { +/* R - byte alignment */ + 0x00, 0x98, 0x98, 0xd7, 0x3a, 0xee, 0x50, 0xeb, 0x24, 0x16, 0xc7, 0x03, + 0x75, 0x62, 0xe2, 0xa3, 0xa7, 0x14, 0xbe, 0x98, 0xff, 0x63, 0xf0, 0xec, + 0x7e, 0x6e, 0x32, 0x8b, 0x3f, 0x40, 0x2c, 0xb9, 0x97, 0xc5, 0x78, 0x3d, + 0x5d, 0x27, 0x1a, 0x58, 0x4f, 0x96, 0x7e, 0xba, 0xf6, 0x1d, 0x6d, 0xfc, + 0x78, 0x56, 0xcb, 0xd4, +/* S - byte alignment */ + 0x00, 0xb5, 0x3e, 0xf2, 0x5a, 0x9a, 0x7b, 0xe8, 0x6f, 0xc8, 0xb8, 0xe9, + 0x12, 0x76, 0xfa, 0x46, 0x10, 0xdc, 0x63, 0xae, 0x4b, 0xee, 0x7d, 0x22, + 0xfa, 0x5a, 0x85, 0xda, 0x54, 0x49, 0x85, 0x45, 0x15, 0xcb, 0xae, 0xe1, + 0x60, 0x1d, 0xab, 0xef, 0x7c, 0x37, 0x52, 0x35, 0x7b, 0xe0, 0x62, 0x29, + 0x33, 0xcc, 0x89, 0x2f +}; +static const uint8_t nist_186_2_ecdsa_testvector_203_ptx[] = { +/* Msg */ + 0xb5, 0x11, 0xd8, 0xdf, 0xe9, 0xe0, 0x6a, 0x6d, 0xac, 0x8a, 0xce, 0x58, + 0xe7, 0x27, 0x50, 0x0b, 0x66, 0x20, 0x41, 0xdf, 0x2e, 0x37, 0xef, 0x3f, + 0x11, 0xc7, 0xd5, 0x0b, 0x7f, 0x4d, 0x0e, 0x39, 0x9f, 0x28, 0x10, 0xc2, + 0x9e, 0x9d, 0x96, 0xbc, 0x48, 0x1e, 0xde, 0xc3, 0xd5, 0xcc, 0x15, 0x9e, + 0x05, 0x3a, 0x10, 0x20, 0x6f, 0x74, 0x3c, 0x4b, 0x15, 0x40, 0xd8, 0xbc, + 0x3d, 0xa3, 0x61, 0x43, 0x7c, 0xa7, 0x4e, 0xd1, 0x14, 0x5c, 0xfe, 0x97, + 0x80, 0x1d, 0xef, 0x6c, 0x4c, 0x14, 0x30, 0x6f, 0x2a, 0x01, 0x19, 0xee, + 0x43, 0x36, 0x39, 0x87, 0xcb, 0xe6, 0x90, 0x8d, 0xd8, 0xa0, 0xfe, 0xae, + 0x74, 0x17, 0xfc, 0xd2, 0xf0, 0x24, 0x8a, 0x45, 0x7c, 0x0e, 0x68, 0x19, + 0xf5, 0x08, 0x89, 0xc6, 0xfe, 0xfb, 0xc5, 0x14, 0x52, 0x86, 0xce, 0x3b, + 0x59, 0x44, 0x65, 0x48, 0xf9, 0x4d, 0xce, 0xc2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_203_private[] = { +/* d - byte alignment */ + 0x00, 0x17, 0x14, 0xa3, 0x15, 0xa0, 0xf3, 0xd7, 0x1e, 0xe5, 0x53, 0xb8, + 0x20, 0x4b, 0xc6, 0x57, 0xa7, 0x24, 0x65, 0xe4, 0x37, 0x4e, 0xb6, 0xae, + 0x77, 0xcc, 0x2f, 0x04, 0x9b, 0x68, 0x58, 0x3b, 0x87, 0x09, 0x60, 0x7e, + 0x32, 0x1c, 0xa7, 0x61, 0x44, 0x9c, 0x66, 0x33, 0x03, 0x4c, 0x28, 0xa7, + 0x2c, 0x38, 0xda, 0x20 +}; +static const uint8_t nist_186_2_ecdsa_testvector_203_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x7f, 0xc8, 0xfa, 0xfd, 0x2c, 0xe5, 0x85, 0xcd, 0xea, 0xd3, 0x17, + 0x7b, 0x8c, 0xfc, 0xfa, 0x09, 0x61, 0xc6, 0xf1, 0x21, 0x99, 0x11, 0xa0, + 0x70, 0xaa, 0x45, 0x10, 0xe9, 0xdc, 0x11, 0x09, 0x6e, 0xed, 0xb2, 0x3b, + 0xfd, 0xcd, 0xd8, 0xe7, 0xbd, 0x27, 0x49, 0x90, 0x6b, 0x4f, 0x15, 0x59, + 0x3a, 0x3b, 0xf7, 0x61 +}; +static const uint8_t nist_186_2_ecdsa_testvector_203_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0xaf, 0x05, 0x22, 0x54, 0x63, 0x1f, 0xf7, 0x99, 0x97, 0x39, 0x85, + 0x9d, 0x93, 0x22, 0x9d, 0xce, 0x24, 0x22, 0x43, 0xda, 0xde, 0xae, 0x42, + 0xc1, 0xef, 0xb7, 0xba, 0xc4, 0x8b, 0x7f, 0x09, 0xc2, 0x7d, 0xb7, 0xc8, + 0x7d, 0xd5, 0x20, 0xa7, 0xa2, 0xb9, 0x90, 0x65, 0x60, 0x32, 0x8a, 0x67, + 0xdb, 0x6c, 0x8d, 0xf2 +}; +/* k = 0c5f8589aff6152ef23d020157f712083d7901b711de486da9fa0ec3243a1780ea6941e1a2e9ca5082e9127f16e930e6a82eb5e */ +static const uint8_t nist_186_2_ecdsa_testvector_203_out[] = { +/* R - byte alignment */ + 0x00, 0xaf, 0xc9, 0x92, 0xe4, 0x79, 0xf2, 0x59, 0x51, 0x90, 0x3c, 0x52, + 0x21, 0xf0, 0x9f, 0x11, 0xb3, 0x38, 0xf2, 0x7c, 0x65, 0x70, 0x11, 0x8f, + 0xfb, 0x2a, 0xdc, 0xec, 0xb9, 0x9e, 0x9c, 0x91, 0x55, 0x6c, 0xe4, 0xbd, + 0x4d, 0xb0, 0x11, 0xcd, 0x8a, 0xf8, 0x1b, 0x4e, 0x67, 0x09, 0x0e, 0x12, + 0xdc, 0xb1, 0x92, 0x4b, +/* S - byte alignment */ + 0x00, 0x48, 0x46, 0xc5, 0x03, 0xdd, 0xe7, 0x2b, 0x6d, 0x72, 0xaf, 0xbf, + 0x60, 0x65, 0x9c, 0xcb, 0x2f, 0x4c, 0x7d, 0x94, 0x87, 0x82, 0x19, 0x56, + 0x0e, 0xde, 0x27, 0xc2, 0x76, 0x4b, 0xa4, 0x36, 0xce, 0x52, 0x1f, 0xd0, + 0x64, 0xc7, 0xa0, 0x6f, 0x3a, 0xf4, 0x2b, 0xef, 0xb7, 0x77, 0x55, 0xbe, + 0x52, 0x6a, 0xc1, 0xc8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_204_ptx[] = { +/* Msg */ + 0xd6, 0x7a, 0xa8, 0xfd, 0xd8, 0x68, 0x44, 0x3c, 0x1c, 0xd5, 0x90, 0xd9, + 0x01, 0x32, 0x8e, 0xdf, 0x34, 0x0e, 0xe3, 0x6a, 0x2e, 0x87, 0x80, 0xbc, + 0xfe, 0x04, 0x81, 0x8e, 0x49, 0x26, 0x55, 0xa4, 0x8f, 0xfb, 0x20, 0xa4, + 0xaf, 0x75, 0x5d, 0x28, 0xae, 0x1b, 0xc8, 0x12, 0xb4, 0xff, 0x7b, 0x20, + 0x57, 0xf0, 0x57, 0xc0, 0x1c, 0xf0, 0xa5, 0x25, 0x3b, 0xe9, 0xfd, 0x9a, + 0xa3, 0x9b, 0x67, 0x16, 0x3e, 0xd9, 0xc1, 0x11, 0x76, 0xf5, 0x61, 0x97, + 0xf8, 0x79, 0xfb, 0x9b, 0xb8, 0x17, 0xc4, 0x8d, 0x35, 0xe3, 0xd7, 0x2f, + 0xfe, 0xc0, 0xd8, 0xa4, 0x75, 0x18, 0xd8, 0xc9, 0xd3, 0xd1, 0x79, 0xc9, + 0x6c, 0x7c, 0x53, 0xec, 0x35, 0xcf, 0x96, 0xb0, 0x83, 0x55, 0xf0, 0x1b, + 0x15, 0x64, 0xb1, 0x4f, 0x55, 0x50, 0x2d, 0x5f, 0xdb, 0xde, 0x61, 0x61, + 0x33, 0xfb, 0xda, 0xc5, 0xe0, 0xae, 0xd3, 0xe5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_204_private[] = { +/* d - byte alignment */ + 0x00, 0xe1, 0x6f, 0x43, 0x1c, 0x80, 0x4c, 0x22, 0x20, 0x5d, 0xaa, 0xcd, + 0x72, 0x2b, 0x0b, 0xae, 0xb6, 0xb0, 0x3e, 0xe0, 0x2e, 0x3a, 0x0e, 0x49, + 0xe8, 0x8e, 0xda, 0x3f, 0x8f, 0xe9, 0x5f, 0xc3, 0x1f, 0xb5, 0x16, 0xfa, + 0x51, 0xab, 0x02, 0x14, 0xda, 0xb0, 0xcf, 0x74, 0xd4, 0x26, 0x22, 0x4e, + 0x52, 0x4d, 0xc3, 0x0d +}; +static const uint8_t nist_186_2_ecdsa_testvector_204_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x47, 0x08, 0xc0, 0x64, 0x1f, 0x07, 0xc8, 0x8d, 0x4f, 0xf2, 0xc2, + 0xfe, 0x4d, 0x7a, 0x11, 0x7d, 0xf8, 0xfb, 0x96, 0x9e, 0x86, 0x04, 0x17, + 0x3f, 0x72, 0x1d, 0x69, 0x1c, 0xa5, 0x08, 0x8c, 0x38, 0x9b, 0xd4, 0x17, + 0x5b, 0x71, 0xf2, 0x0d, 0x89, 0x93, 0x76, 0xf0, 0x8d, 0xef, 0xcd, 0x01, + 0xe1, 0xed, 0x47, 0x41 +}; +static const uint8_t nist_186_2_ecdsa_testvector_204_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x14, 0xd1, 0x16, 0x1d, 0x1a, 0xda, 0x4a, 0x30, 0x15, 0xa0, 0xfc, + 0x9a, 0x61, 0x63, 0xe3, 0xd3, 0x48, 0x09, 0x91, 0x5e, 0x47, 0x7a, 0x63, + 0x77, 0x8f, 0xdf, 0x09, 0xe8, 0x20, 0x2f, 0xc9, 0xba, 0x6d, 0x41, 0xd0, + 0x9f, 0x9f, 0x8f, 0xa1, 0x37, 0x7e, 0xf3, 0xaa, 0x06, 0xa6, 0xe4, 0x5d, + 0xcb, 0x36, 0xdf, 0x5c +}; +/* k = 05f3f6c0a13a21123854a6ffa49f15a3f048181aa05de4b8a951e35745d19b53ccf73d47d9e7b4f580ac0a28a52d2be059aaf21 */ +static const uint8_t nist_186_2_ecdsa_testvector_204_out[] = { +/* R - byte alignment */ + 0x00, 0x9c, 0x9b, 0xd4, 0x83, 0x71, 0x61, 0x59, 0xee, 0xda, 0x02, 0x20, + 0x66, 0x5f, 0xfa, 0x68, 0x20, 0xa3, 0xd6, 0x9e, 0x88, 0x20, 0x7e, 0xcc, + 0x6b, 0xc9, 0x20, 0xf6, 0x05, 0xdf, 0x6c, 0x15, 0xd1, 0x47, 0x37, 0xf7, + 0xca, 0xaf, 0x96, 0xea, 0x62, 0xac, 0xb5, 0x30, 0xb2, 0x08, 0xb3, 0xc6, + 0xfc, 0x25, 0xe3, 0x3e, +/* S - byte alignment */ + 0x00, 0xb6, 0x1d, 0x36, 0xb3, 0xce, 0x87, 0x60, 0xc2, 0x06, 0x2a, 0x0a, + 0x54, 0x1d, 0x87, 0xa9, 0x19, 0xaa, 0x33, 0x93, 0x5c, 0xa9, 0x96, 0x55, + 0x0b, 0x00, 0x7f, 0x74, 0xe2, 0x44, 0x6a, 0xf8, 0x59, 0xc9, 0xfa, 0xd1, + 0x66, 0xaf, 0x23, 0x1e, 0xba, 0x62, 0x62, 0x2d, 0xcc, 0x96, 0x5a, 0x1c, + 0xa2, 0x06, 0x30, 0x04 +}; +static const uint8_t nist_186_2_ecdsa_testvector_205_ptx[] = { +/* Msg */ + 0x88, 0x60, 0xd5, 0x6c, 0xf5, 0xe0, 0x3c, 0xc1, 0x95, 0x5f, 0xd9, 0xd6, + 0xd3, 0x72, 0x83, 0x75, 0x5f, 0xd1, 0x9b, 0xca, 0xc8, 0xa2, 0x42, 0xc4, + 0x4c, 0xfb, 0xc9, 0xbe, 0xef, 0xa2, 0x69, 0x5f, 0xca, 0x17, 0x35, 0xbe, + 0xa6, 0xd4, 0x4c, 0xca, 0xc9, 0xd3, 0x53, 0xea, 0x10, 0x51, 0x23, 0xe0, + 0x3e, 0xd2, 0xbe, 0xf3, 0x94, 0x65, 0x88, 0x4d, 0xa2, 0x29, 0xb4, 0xa2, + 0x5c, 0x10, 0xfc, 0x12, 0x70, 0xe3, 0x95, 0x51, 0xd7, 0x86, 0x62, 0x05, + 0xaa, 0x7e, 0x68, 0x6f, 0x38, 0xb0, 0x82, 0x4e, 0x55, 0x6b, 0x55, 0x00, + 0xf5, 0xa9, 0x87, 0xeb, 0xf9, 0x92, 0x2c, 0x1b, 0x48, 0x42, 0x81, 0x2c, + 0x22, 0xcc, 0xdd, 0x6b, 0xb1, 0x7f, 0xe4, 0x38, 0xe1, 0x68, 0xfe, 0xaf, + 0x72, 0x17, 0x08, 0x87, 0x4c, 0xa6, 0x49, 0x39, 0x12, 0xf8, 0xa7, 0x65, + 0xf9, 0x3f, 0x1a, 0x72, 0xdb, 0xc1, 0x62, 0x76 +}; +static const uint8_t nist_186_2_ecdsa_testvector_205_private[] = { +/* d - byte alignment */ + 0x00, 0x98, 0x8d, 0x40, 0xb2, 0x1e, 0xa9, 0x9e, 0x93, 0xf4, 0xf5, 0x08, + 0xb5, 0x3e, 0x18, 0x96, 0xcb, 0xfc, 0xd1, 0x0f, 0x4e, 0xcd, 0xbe, 0x30, + 0x27, 0x8b, 0x95, 0xbb, 0x14, 0xc0, 0x75, 0x10, 0xd0, 0x12, 0x5f, 0xa3, + 0xf5, 0x31, 0xf6, 0xcb, 0xcc, 0x3c, 0x39, 0x23, 0x77, 0xbc, 0xd6, 0x04, + 0xc5, 0x82, 0xfe, 0xa9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_205_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0xc5, 0x64, 0x64, 0xa2, 0xff, 0x1f, 0xa2, 0x7a, 0x5c, 0x61, 0x5a, + 0x30, 0x1e, 0xfa, 0xe2, 0xd0, 0x52, 0xa5, 0x2b, 0xd9, 0x9b, 0x32, 0x52, + 0x94, 0x00, 0xcb, 0xe0, 0xed, 0x44, 0x06, 0xdd, 0x15, 0x73, 0x6e, 0xb4, + 0x13, 0xb6, 0x38, 0x1c, 0x56, 0xca, 0x68, 0x9d, 0xd0, 0xe4, 0x0d, 0x0e, + 0x1b, 0x2e, 0x25, 0x19 +}; +static const uint8_t nist_186_2_ecdsa_testvector_205_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xcd, 0xcd, 0x0c, 0x8e, 0x3a, 0x9a, 0xde, 0x00, 0x9d, 0xca, 0x37, + 0xa3, 0x99, 0xd8, 0xe4, 0x12, 0xed, 0x1a, 0x55, 0xdc, 0x0c, 0x9c, 0x92, + 0x64, 0x67, 0xe3, 0x5c, 0x9b, 0x89, 0x5d, 0x4d, 0x59, 0x08, 0x3c, 0x8f, + 0xeb, 0xb2, 0xe8, 0xa3, 0x81, 0x81, 0x24, 0x65, 0xff, 0x70, 0x64, 0x99, + 0x6a, 0xed, 0xb6, 0x68 +}; +/* k = 09611532af142d75dfbda90b6a375351660ad39c30b7320f73b56ac7488ce62a2357538fc2a7cb73147ca2a8163b754d6d2e94e */ +static const uint8_t nist_186_2_ecdsa_testvector_205_out[] = { +/* R - byte alignment */ + 0x00, 0x25, 0xd8, 0x0a, 0xb8, 0x45, 0x97, 0x76, 0xfd, 0xf1, 0x88, 0xc1, + 0x03, 0xe9, 0xcc, 0x7a, 0x4c, 0xa2, 0xce, 0xaa, 0x2f, 0xee, 0xa1, 0x8e, + 0xa7, 0xf2, 0xb4, 0xba, 0x06, 0x30, 0xec, 0x0f, 0xf3, 0x03, 0xd4, 0x0a, + 0xbb, 0xe2, 0x5e, 0xc2, 0x08, 0xa9, 0xcc, 0xe3, 0xd3, 0xd9, 0x2d, 0x81, + 0xa5, 0xa4, 0xfd, 0xcc, +/* S - byte alignment */ + 0x00, 0x1a, 0x08, 0x28, 0x4e, 0xd5, 0xd9, 0xbf, 0xed, 0x00, 0x3b, 0xb5, + 0xf0, 0x64, 0x57, 0x00, 0x38, 0xc4, 0xa8, 0x31, 0x65, 0xbd, 0x78, 0xc1, + 0x63, 0xf1, 0xeb, 0x41, 0x7a, 0x93, 0x37, 0x4e, 0x19, 0xdc, 0x87, 0xc4, + 0x7b, 0x79, 0xf0, 0x46, 0x27, 0xe9, 0x39, 0x0f, 0xa0, 0xcf, 0x93, 0xe6, + 0x9e, 0xd8, 0x4d, 0xc5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_206_ptx[] = { +/* Msg */ + 0x59, 0x24, 0xcd, 0xe8, 0xbf, 0x72, 0xa6, 0x55, 0xd2, 0x6b, 0x5c, 0x88, + 0x7c, 0xe7, 0xbf, 0x21, 0xad, 0xa3, 0xe0, 0xfc, 0xa0, 0x7e, 0x76, 0x06, + 0x5f, 0xe8, 0x80, 0x4f, 0x89, 0x97, 0x2c, 0x61, 0x53, 0x7b, 0xf8, 0xd1, + 0xcd, 0xf5, 0x17, 0x13, 0x67, 0x44, 0x16, 0x92, 0xb3, 0x40, 0xbf, 0x00, + 0x6c, 0x4a, 0x3e, 0xeb, 0xb8, 0x83, 0x82, 0x92, 0xaa, 0x3c, 0xe6, 0xf6, + 0x0b, 0xae, 0x11, 0x34, 0x5a, 0xeb, 0x1a, 0x11, 0x11, 0x15, 0xf0, 0xd7, + 0x2a, 0xce, 0xfa, 0x60, 0xe2, 0xef, 0xfa, 0x70, 0xbd, 0x7d, 0x37, 0x48, + 0xca, 0xd9, 0xdb, 0x77, 0x28, 0x36, 0x9a, 0xf4, 0xc9, 0x50, 0x94, 0x6a, + 0x76, 0x5c, 0x7d, 0xd3, 0x13, 0x3a, 0xfb, 0x48, 0x25, 0xf2, 0x4f, 0x17, + 0x91, 0x5e, 0x38, 0x17, 0xa6, 0x24, 0x14, 0x38, 0x5e, 0xe8, 0x49, 0x5e, + 0xe1, 0xbf, 0xe3, 0x70, 0x4b, 0xe6, 0x7f, 0xab +}; +static const uint8_t nist_186_2_ecdsa_testvector_206_private[] = { +/* d - byte alignment */ + 0x00, 0x76, 0xa9, 0x20, 0x86, 0x24, 0x0f, 0x51, 0xa0, 0x00, 0xb7, 0x87, + 0x35, 0x06, 0xf6, 0x4e, 0xb1, 0x44, 0xaa, 0xc0, 0xd0, 0xa8, 0xda, 0x2b, + 0x28, 0x9f, 0x94, 0x0a, 0xbd, 0x35, 0x39, 0xef, 0x58, 0x67, 0xb0, 0x8d, + 0x4a, 0x79, 0xc0, 0xb5, 0xbf, 0x18, 0x36, 0x6d, 0x7c, 0xfe, 0xfa, 0xc7, + 0xb0, 0x91, 0x9c, 0x0e +}; +static const uint8_t nist_186_2_ecdsa_testvector_206_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x1e, 0x48, 0x59, 0x66, 0x9e, 0x29, 0xaa, 0xdb, 0x00, 0x20, 0xf3, + 0x76, 0xc1, 0x21, 0x4d, 0x1b, 0x34, 0x44, 0x4b, 0x92, 0x9c, 0xee, 0xe2, + 0x6a, 0xdb, 0xf6, 0xf2, 0xc5, 0x4f, 0x65, 0xf6, 0xa7, 0x4a, 0x52, 0xbe, + 0x67, 0xb2, 0x12, 0x53, 0x63, 0xcd, 0xe3, 0xaa, 0xbe, 0x9d, 0xa3, 0xa3, + 0xe0, 0x18, 0x1a, 0x77 +}; +static const uint8_t nist_186_2_ecdsa_testvector_206_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x83, 0xab, 0x0d, 0xa1, 0xf5, 0x29, 0xa5, 0x8c, 0x3e, 0x68, 0x75, + 0x06, 0x18, 0xcb, 0x40, 0x99, 0x63, 0x31, 0xac, 0xdc, 0x2a, 0x70, 0x90, + 0xc3, 0x2f, 0x1f, 0x2b, 0xb5, 0x94, 0x14, 0xd1, 0x1a, 0x30, 0x0d, 0x13, + 0x6e, 0x08, 0x79, 0xc3, 0x66, 0x8a, 0xeb, 0xbe, 0x66, 0x27, 0x26, 0x7c, + 0x49, 0xcc, 0x19, 0x06 +}; +/* k = 0e52a50b6bbdd7f109b01341502dd471e60de74c0c3b37bdefa78d9f4e5b875d3744c109fa205e25109d081dfc2fbd363939551 */ +static const uint8_t nist_186_2_ecdsa_testvector_206_out[] = { +/* R - byte alignment */ + 0x00, 0xfd, 0xc5, 0x3f, 0xe5, 0xe4, 0x97, 0x62, 0x5c, 0x8d, 0x69, 0xb7, + 0x66, 0x61, 0xda, 0x56, 0x6a, 0x97, 0xde, 0x20, 0x09, 0xd2, 0xcc, 0xde, + 0xd1, 0x1e, 0x02, 0x4e, 0xad, 0x4c, 0xbc, 0xb3, 0xf7, 0x38, 0x3a, 0x1e, + 0x3d, 0xab, 0x04, 0x64, 0xc4, 0x9f, 0xdd, 0x7b, 0xe2, 0x3c, 0xcd, 0xbf, + 0xc1, 0x6d, 0xc7, 0x9b, +/* S - byte alignment */ + 0x00, 0x6f, 0x64, 0x9e, 0x3a, 0x89, 0xbd, 0x86, 0x03, 0x10, 0xf9, 0x7b, + 0x3f, 0x0f, 0xc4, 0xf9, 0x66, 0x38, 0x55, 0x56, 0xe1, 0xff, 0x62, 0x0b, + 0x4c, 0x5b, 0x0d, 0x6e, 0x84, 0xaa, 0xac, 0x50, 0x3c, 0x42, 0x81, 0x03, + 0xd2, 0xf1, 0x43, 0xac, 0x9f, 0xb1, 0x4b, 0xc4, 0xff, 0xbe, 0xde, 0xe5, + 0xa5, 0x38, 0xc5, 0xd8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_207_ptx[] = { +/* Msg */ + 0x30, 0x3b, 0x55, 0x09, 0xd2, 0xf9, 0x6f, 0xfb, 0x7b, 0xbe, 0x1e, 0x35, + 0x3f, 0x61, 0xac, 0x65, 0x61, 0x25, 0x20, 0x08, 0xbb, 0x8e, 0xbf, 0xdd, + 0x60, 0x73, 0xd4, 0x99, 0x81, 0x53, 0xad, 0xdc, 0x8d, 0xed, 0xe6, 0x64, + 0x9c, 0x0a, 0xea, 0x81, 0x0e, 0x9e, 0xb6, 0xc8, 0x6f, 0x0f, 0xe0, 0x0c, + 0x9e, 0xd5, 0xd8, 0x8a, 0x2f, 0x43, 0x6f, 0x64, 0x0d, 0xa4, 0x95, 0x51, + 0x64, 0x8a, 0x67, 0x92, 0xbe, 0x63, 0x69, 0x28, 0x6c, 0x4d, 0x0f, 0x44, + 0x27, 0x2c, 0x83, 0xff, 0xf7, 0xf9, 0xa2, 0x4b, 0x54, 0x5d, 0x47, 0x29, + 0x8b, 0x7e, 0xcd, 0x1d, 0x64, 0x19, 0xcf, 0xdf, 0x02, 0xd1, 0x32, 0x54, + 0x0a, 0xc6, 0x66, 0xbc, 0x08, 0x6a, 0xe8, 0x2d, 0x0e, 0x90, 0x0c, 0x40, + 0x9e, 0xc6, 0xf9, 0x0a, 0xc9, 0xe5, 0xf5, 0x4e, 0x99, 0xe6, 0xe3, 0xf0, + 0xad, 0xf7, 0x09, 0xad, 0x23, 0xce, 0x17, 0x0a +}; +static const uint8_t nist_186_2_ecdsa_testvector_207_private[] = { +/* d - byte alignment */ + 0x00, 0x53, 0x1e, 0xd2, 0xc1, 0x33, 0x5a, 0x2b, 0x8c, 0x8c, 0x40, 0x99, + 0x25, 0x00, 0xc5, 0xfe, 0x5d, 0xd3, 0xde, 0x77, 0x95, 0x3b, 0x20, 0xc6, + 0x7d, 0xc5, 0xc3, 0xe1, 0x42, 0x97, 0xd9, 0x64, 0xdd, 0xef, 0xb7, 0x4e, + 0x82, 0x67, 0x9c, 0xbd, 0x32, 0x60, 0xed, 0x52, 0xdb, 0xd8, 0xca, 0x1c, + 0xf4, 0x6a, 0x77, 0xe7 +}; +static const uint8_t nist_186_2_ecdsa_testvector_207_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x55, 0xc7, 0x44, 0x98, 0x28, 0x54, 0xc1, 0x22, 0x02, 0xe5, 0x51, + 0x72, 0x36, 0x25, 0xd5, 0x22, 0x88, 0x30, 0x4f, 0x62, 0x8d, 0x33, 0xd6, + 0xa8, 0x4b, 0xcf, 0x5d, 0xb3, 0x17, 0xd1, 0x5b, 0x4c, 0xed, 0x7f, 0xf9, + 0x36, 0x02, 0x5e, 0x7e, 0x86, 0x34, 0xab, 0x99, 0x52, 0x6a, 0x50, 0x01, + 0x01, 0xc7, 0xf4, 0x53 +}; +static const uint8_t nist_186_2_ecdsa_testvector_207_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x67, 0x6a, 0xb6, 0x66, 0xa9, 0xe9, 0xcd, 0xd7, 0xda, 0x45, 0x20, + 0xfe, 0x82, 0x10, 0x80, 0x75, 0x9e, 0x9b, 0xe2, 0x3f, 0xd5, 0xdd, 0x74, + 0x9d, 0x66, 0x89, 0xab, 0xae, 0x50, 0x1e, 0xd2, 0x55, 0xda, 0xfe, 0x02, + 0x13, 0x60, 0xe5, 0xab, 0xbd, 0xde, 0x07, 0xdf, 0x05, 0xf5, 0x46, 0x57, + 0xa6, 0x87, 0x12, 0x53 +}; +/* k = 09213abf4a10b44c52c89d0dee38089cd52fc54959d1a4006a3f8771b57ebd30f4f58c9ab3f54d4dbfd6fcc304dea203137c34b */ +static const uint8_t nist_186_2_ecdsa_testvector_207_out[] = { +/* R - byte alignment */ + 0x00, 0x8e, 0x0c, 0x19, 0xef, 0x52, 0x51, 0x9e, 0xb2, 0x27, 0x4e, 0xa0, + 0x53, 0xa6, 0xb3, 0x4e, 0xa8, 0x82, 0xc1, 0xb7, 0xd3, 0xe1, 0x9c, 0x9f, + 0x05, 0x97, 0x48, 0x82, 0x31, 0x0b, 0x05, 0x9c, 0x02, 0xa4, 0x85, 0xbd, + 0xe6, 0x31, 0xaf, 0x08, 0xd2, 0x0f, 0x3e, 0x12, 0x04, 0x32, 0x51, 0xb5, + 0x02, 0x7c, 0xa3, 0xa7, +/* S - byte alignment */ + 0x00, 0x15, 0xeb, 0xc7, 0x7e, 0xb4, 0x55, 0x66, 0x61, 0x08, 0x11, 0xb6, + 0xa4, 0xac, 0xcc, 0x5c, 0x85, 0x08, 0xff, 0x8b, 0xab, 0x68, 0x7c, 0xb9, + 0xa7, 0xd6, 0x0d, 0x61, 0x85, 0x6c, 0x73, 0x80, 0x27, 0x39, 0x33, 0x06, + 0xc3, 0x40, 0x07, 0x8e, 0x7d, 0x77, 0xeb, 0x1c, 0x43, 0xb9, 0x41, 0xe1, + 0x97, 0xcd, 0xed, 0x48 +}; +static const uint8_t nist_186_2_ecdsa_testvector_208_ptx[] = { +/* Msg */ + 0x8c, 0xf2, 0x2f, 0x5a, 0xa2, 0x23, 0x84, 0xe7, 0x98, 0xa9, 0xf9, 0xb3, + 0xfc, 0x6c, 0x29, 0xf6, 0xf2, 0x8b, 0x05, 0xf5, 0x7b, 0x96, 0x2f, 0xd7, + 0xf7, 0xfe, 0xa4, 0xb4, 0xe9, 0xc9, 0x9e, 0xf0, 0xfb, 0x8a, 0xb9, 0xc7, + 0x42, 0x91, 0x54, 0x28, 0xc2, 0x5f, 0x3a, 0xc7, 0x35, 0x5d, 0x82, 0x6e, + 0x08, 0xcd, 0xb3, 0x93, 0xa7, 0x00, 0x2c, 0x30, 0xfa, 0xc9, 0xc3, 0xcf, + 0x2f, 0x33, 0xad, 0xe4, 0xbb, 0x6f, 0x9e, 0x60, 0x9b, 0x10, 0x30, 0x83, + 0xe0, 0x7b, 0x89, 0xf2, 0x6a, 0x98, 0x38, 0x09, 0xf4, 0xce, 0x61, 0x72, + 0x51, 0x2f, 0x1a, 0xf7, 0xf4, 0xef, 0x14, 0x94, 0xb6, 0x1b, 0x7e, 0xd1, + 0xd4, 0x87, 0x26, 0x4f, 0x37, 0x09, 0xe2, 0xa0, 0xf9, 0xe4, 0x2e, 0x5b, + 0x24, 0x87, 0x16, 0x70, 0xbd, 0x78, 0x57, 0xba, 0x01, 0x8b, 0xc1, 0xd3, + 0xee, 0x57, 0xdf, 0x2c, 0x05, 0xea, 0xda, 0x5d +}; +static const uint8_t nist_186_2_ecdsa_testvector_208_private[] = { +/* d - byte alignment */ + 0x00, 0x57, 0x2e, 0x4c, 0x0f, 0x38, 0x1b, 0x61, 0xa0, 0xd4, 0x7d, 0xfd, + 0xa6, 0x77, 0xe9, 0x91, 0x5d, 0x98, 0x46, 0x3d, 0xfd, 0x3d, 0x5b, 0x87, + 0xf2, 0xa4, 0xa4, 0x10, 0x54, 0xdf, 0xab, 0x92, 0x7b, 0xbc, 0x9b, 0x5e, + 0x45, 0xf0, 0xe4, 0x37, 0xd0, 0x15, 0xc3, 0x79, 0xcb, 0x3d, 0x18, 0xc3, + 0x75, 0x1f, 0x2b, 0x8f +}; +static const uint8_t nist_186_2_ecdsa_testvector_208_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xfd, 0xec, 0xb7, 0xbf, 0xe2, 0xd0, 0xa0, 0x5a, 0xf1, 0xa9, 0xbc, + 0xfb, 0xa7, 0x75, 0xf1, 0x99, 0xa9, 0x6c, 0x95, 0x7f, 0x9d, 0xc7, 0x76, + 0x25, 0x1f, 0x7a, 0x76, 0x1f, 0x11, 0xc6, 0x90, 0x3f, 0xa2, 0xc0, 0xb0, + 0x11, 0x82, 0xee, 0xa0, 0xdb, 0xdb, 0xe1, 0x4f, 0x05, 0x42, 0x87, 0x6c, + 0xb8, 0xf9, 0x72, 0xff +}; +static const uint8_t nist_186_2_ecdsa_testvector_208_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x23, 0x38, 0x98, 0x88, 0xf2, 0x1b, 0x65, 0x88, 0x5c, 0x86, 0xa1, + 0x2a, 0x87, 0x05, 0x82, 0x9c, 0xa1, 0x96, 0x77, 0xcd, 0x34, 0x42, 0xf5, + 0x8c, 0x0e, 0x7b, 0xa1, 0xde, 0x37, 0x9b, 0x0c, 0x6e, 0xe8, 0xd4, 0x64, + 0x9f, 0x79, 0x99, 0xa4, 0x3f, 0x9c, 0x21, 0x0f, 0x12, 0xf2, 0x83, 0xe8, + 0xd5, 0x63, 0x30, 0x64 +}; +/* k = 0e96980c24a092c58f466f7bbbc194b03e0200a0a714f778caab9fe956feaa4d2e3a1bfd8f2bbe376588d3d3cb90071fec4502a */ +static const uint8_t nist_186_2_ecdsa_testvector_208_out[] = { +/* R - byte alignment */ + 0x00, 0xb8, 0x3b, 0xdd, 0xf5, 0x8e, 0x3e, 0x82, 0x77, 0x0f, 0x38, 0x12, + 0x71, 0x53, 0x2d, 0x11, 0xc4, 0xb4, 0xc0, 0x15, 0x38, 0x09, 0x1c, 0x29, + 0xd3, 0x6a, 0x34, 0x24, 0x0b, 0xfa, 0x63, 0xe1, 0x1f, 0x03, 0x2b, 0xad, + 0x90, 0xa4, 0x3a, 0xed, 0x00, 0x71, 0x0c, 0xf7, 0x97, 0xb5, 0xe8, 0x54, + 0xa6, 0x55, 0x23, 0xe3, +/* S - byte alignment */ + 0x00, 0xe1, 0x24, 0x36, 0x09, 0x1b, 0xc3, 0x50, 0x51, 0x48, 0xab, 0x15, + 0x73, 0xc9, 0x73, 0xbe, 0x1e, 0xa1, 0x5e, 0x8e, 0x55, 0x96, 0x7d, 0xf3, + 0xad, 0x54, 0xf7, 0xca, 0x03, 0xe2, 0x69, 0x96, 0x17, 0x90, 0xbf, 0x26, + 0xcc, 0x87, 0xbd, 0xaa, 0x09, 0xc9, 0x47, 0x65, 0xaa, 0x1e, 0xeb, 0xfb, + 0x2c, 0x10, 0xe0, 0x2f +}; +static const uint8_t nist_186_2_ecdsa_testvector_209_ptx[] = { +/* Msg */ + 0xb9, 0x52, 0x06, 0xdd, 0x32, 0x95, 0x79, 0x17, 0x0b, 0xb8, 0x45, 0x51, + 0xc7, 0x82, 0x2b, 0x15, 0x5d, 0x60, 0xf2, 0xdd, 0xe9, 0x4d, 0xb9, 0x1d, + 0xa2, 0xf4, 0x8d, 0x84, 0x0c, 0x19, 0x37, 0x7f, 0x6f, 0x35, 0x57, 0x00, + 0x87, 0x60, 0xb7, 0x7d, 0x7d, 0x74, 0xd9, 0x3b, 0x16, 0x70, 0xd2, 0xcc, + 0x2b, 0x1a, 0x5b, 0xd7, 0x59, 0xe9, 0x26, 0x17, 0xf9, 0x21, 0x6e, 0xa6, + 0x52, 0x40, 0xd2, 0x7c, 0x0e, 0x99, 0x63, 0x32, 0xeb, 0x3f, 0xfc, 0x0c, + 0xb3, 0x24, 0xd2, 0x37, 0x6e, 0x82, 0x4b, 0x4f, 0xd6, 0x7a, 0x14, 0x25, + 0x0b, 0xfc, 0x6e, 0xbe, 0x88, 0xe6, 0xc8, 0x9f, 0x56, 0x70, 0x93, 0x47, + 0x7f, 0xc7, 0x52, 0xfe, 0xc6, 0xf8, 0xf0, 0xcd, 0x95, 0x10, 0x57, 0xce, + 0x37, 0x81, 0x3e, 0xa6, 0x47, 0xc8, 0x42, 0x4f, 0x69, 0x4d, 0x39, 0x1b, + 0x38, 0x8b, 0xc3, 0xf5, 0x7f, 0x70, 0x21, 0xea +}; +static const uint8_t nist_186_2_ecdsa_testvector_209_private[] = { +/* d - byte alignment */ + 0x00, 0x02, 0x74, 0x8f, 0xaa, 0x0b, 0x51, 0x0d, 0x0f, 0x79, 0x14, 0xfb, + 0x57, 0x0d, 0xf3, 0xd7, 0x17, 0x43, 0x58, 0x14, 0xc4, 0x9e, 0xe1, 0x21, + 0x06, 0xbd, 0xa7, 0x93, 0xdd, 0x1c, 0xfa, 0xb5, 0x9b, 0x78, 0xe0, 0x94, + 0xf1, 0x47, 0x54, 0x39, 0x4a, 0x05, 0xc1, 0x72, 0xaf, 0xcf, 0xa7, 0x37, + 0xd3, 0xdc, 0xa8, 0x44 +}; +static const uint8_t nist_186_2_ecdsa_testvector_209_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xf8, 0xbf, 0xfd, 0xe3, 0xab, 0x80, 0x2c, 0x82, 0xd6, 0xaa, 0xe2, + 0x90, 0x17, 0x7b, 0xf5, 0xcd, 0x8a, 0x6d, 0x2a, 0x66, 0x9b, 0x0d, 0x4a, + 0x42, 0x43, 0x29, 0x13, 0xa4, 0xa6, 0x28, 0x95, 0x29, 0x30, 0xf6, 0x05, + 0x0c, 0x56, 0xb5, 0xfc, 0xaf, 0x08, 0xb9, 0x22, 0xab, 0x31, 0xdb, 0x48, + 0x55, 0xb4, 0xa4, 0x71 +}; +static const uint8_t nist_186_2_ecdsa_testvector_209_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xaf, 0xca, 0xe3, 0xc8, 0x34, 0x82, 0xba, 0xbc, 0x04, 0xe3, 0xc5, + 0x80, 0x9d, 0x32, 0xb6, 0x2f, 0x45, 0x19, 0xe8, 0x6e, 0xa4, 0x45, 0x7d, + 0x40, 0xbf, 0xaa, 0xa2, 0xd1, 0xe4, 0x9a, 0x8a, 0x99, 0x57, 0x2e, 0x9c, + 0x1f, 0xaf, 0xeb, 0x76, 0x15, 0xd2, 0x5e, 0x7e, 0xa5, 0xc8, 0x13, 0x4d, + 0x2a, 0x47, 0x9e, 0x7c +}; +/* k = 060cd7168ba4135379d0766c577acbbceb2e713f9ce2b1babe49ce98cf68320ae0906ef2288560c4f0d7973bcbf7f9d3bd085bb */ +static const uint8_t nist_186_2_ecdsa_testvector_209_out[] = { +/* R - byte alignment */ + 0x00, 0xfa, 0xf8, 0x3a, 0x27, 0x99, 0x14, 0x1b, 0xe5, 0x83, 0x2b, 0x39, + 0x33, 0xcd, 0xfc, 0xe9, 0x36, 0x9b, 0xbb, 0x6a, 0x98, 0xfc, 0x8d, 0x82, + 0x57, 0x1b, 0xe6, 0xb9, 0x73, 0x48, 0x83, 0x26, 0xce, 0x10, 0x37, 0xae, + 0x72, 0x29, 0x14, 0x77, 0xa1, 0xff, 0x0e, 0xcc, 0xdb, 0xda, 0x12, 0x75, + 0x02, 0xaa, 0x57, 0x99, +/* S - byte alignment */ + 0x00, 0x7c, 0x2b, 0xfe, 0xa0, 0xd2, 0x7c, 0xc2, 0x5e, 0x95, 0xbe, 0xe0, + 0x33, 0x33, 0xed, 0xca, 0x21, 0xa9, 0xc5, 0x63, 0xda, 0xcb, 0x6a, 0xfd, + 0xe7, 0x12, 0x7a, 0x62, 0x08, 0x03, 0x65, 0xd5, 0x5a, 0xc3, 0x2a, 0xdf, + 0xba, 0xd9, 0xa4, 0x4b, 0x8f, 0xcf, 0xcc, 0xae, 0x18, 0x1e, 0xf5, 0x1e, + 0x70, 0xfa, 0x06, 0x30 +}; +static const uint8_t nist_186_2_ecdsa_testvector_210_ptx[] = { +/* Msg */ + 0x6e, 0xe8, 0xbc, 0xaa, 0x0f, 0x01, 0xbc, 0x07, 0x24, 0x83, 0x33, 0xe9, + 0xdf, 0x67, 0x86, 0x38, 0x5e, 0xe4, 0x5c, 0x0a, 0x2e, 0xe6, 0x47, 0xba, + 0x0e, 0xbc, 0xa6, 0x3a, 0xf5, 0x10, 0xca, 0xaa, 0x56, 0x1d, 0x57, 0x29, + 0xa2, 0x1c, 0xed, 0xeb, 0x0f, 0xff, 0x08, 0x8b, 0x98, 0x62, 0x25, 0xa3, + 0x44, 0xbf, 0x27, 0x9b, 0xac, 0xe1, 0xf8, 0xbe, 0xb7, 0x9b, 0x73, 0x93, + 0xa9, 0xb9, 0x82, 0x6a, 0x5c, 0x37, 0x83, 0x35, 0xcc, 0xb1, 0xf1, 0x99, + 0xda, 0x1b, 0x40, 0x45, 0x49, 0xb2, 0x08, 0x83, 0x0d, 0x32, 0x66, 0x0c, + 0xc5, 0x4a, 0xa0, 0x21, 0x86, 0x4d, 0x07, 0xd7, 0xda, 0x2a, 0x22, 0xb3, + 0x08, 0x9e, 0x08, 0x76, 0x96, 0xa8, 0x0e, 0x3a, 0x0d, 0x3e, 0xa2, 0xbe, + 0xfc, 0x3e, 0x77, 0xff, 0x3f, 0xa7, 0xe3, 0x08, 0x81, 0x09, 0x85, 0x0a, + 0x00, 0x3a, 0x2a, 0xaf, 0x90, 0x4b, 0xf1, 0xac +}; +static const uint8_t nist_186_2_ecdsa_testvector_210_private[] = { +/* d - byte alignment */ + 0x00, 0x46, 0x79, 0xf6, 0x42, 0xe2, 0x68, 0xf4, 0x01, 0x78, 0x35, 0xa1, + 0xfb, 0xba, 0x9b, 0xfd, 0x9b, 0x7b, 0x4a, 0x40, 0xe0, 0xc7, 0x5d, 0xcc, + 0x57, 0x46, 0x16, 0xe7, 0x5a, 0x82, 0x7a, 0xf3, 0xd7, 0x07, 0x04, 0x49, + 0x12, 0xd1, 0x8e, 0xb6, 0x21, 0xd2, 0x44, 0x1a, 0x38, 0xd1, 0xa9, 0xc8, + 0x52, 0x3a, 0x30, 0x57 +}; +static const uint8_t nist_186_2_ecdsa_testvector_210_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x0c, 0x98, 0x9d, 0xdd, 0x76, 0xe0, 0x8e, 0xf5, 0x3a, 0xb8, 0x58, + 0x38, 0x49, 0xa2, 0xe3, 0x97, 0x3c, 0xfc, 0xeb, 0x31, 0x15, 0x58, 0xe1, + 0x7c, 0x21, 0x70, 0x58, 0x95, 0x46, 0x5a, 0xee, 0x0b, 0x5c, 0xf5, 0x53, + 0x51, 0x70, 0x1e, 0xc1, 0x24, 0x21, 0x01, 0x89, 0x66, 0xeb, 0xf9, 0x56, + 0xa7, 0x68, 0xc9, 0x3b +}; +static const uint8_t nist_186_2_ecdsa_testvector_210_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x33, 0xc0, 0x1e, 0xcb, 0xfd, 0xe5, 0x03, 0xb7, 0xd3, 0xc4, 0xaa, + 0xca, 0xfd, 0x05, 0xd9, 0xff, 0xad, 0xd2, 0x30, 0x00, 0x6b, 0xb0, 0xea, + 0xda, 0x2c, 0x33, 0x13, 0x6c, 0x54, 0x92, 0xca, 0x5f, 0x22, 0x50, 0xf1, + 0x59, 0x74, 0x3d, 0xe6, 0xe4, 0xa7, 0x9d, 0x82, 0x1a, 0xe4, 0x35, 0xfb, + 0x6f, 0x0c, 0xaf, 0x45 +}; +/* k = 087740649e3f08744d614e862ec6c928f33682cd013f9ab67e3992452f5522dfaf8001641f7c798125106dd8b947b5e7c070fa1 */ +static const uint8_t nist_186_2_ecdsa_testvector_210_out[] = { +/* R - byte alignment */ + 0x00, 0xc7, 0x0c, 0x32, 0x7c, 0x2d, 0x2c, 0x78, 0x9d, 0xaa, 0x7d, 0x25, + 0xd9, 0xc4, 0x36, 0xd4, 0x54, 0x42, 0xff, 0xe1, 0x45, 0x32, 0x4f, 0x5f, + 0x36, 0x74, 0x99, 0x4b, 0x4c, 0xd1, 0x0a, 0x15, 0x48, 0x3a, 0x64, 0xc2, + 0xe9, 0xea, 0xe3, 0xee, 0x20, 0x39, 0x92, 0x36, 0xde, 0x5f, 0x21, 0x2b, + 0x8c, 0x25, 0x06, 0x14, +/* S - byte alignment */ + 0x00, 0xb4, 0xad, 0xb3, 0x9b, 0x33, 0xb9, 0x98, 0xb9, 0x4a, 0xc5, 0x0c, + 0x22, 0x57, 0xbd, 0xe9, 0x45, 0xff, 0x77, 0x6f, 0xe9, 0x3b, 0x45, 0x8e, + 0x68, 0xc7, 0x70, 0xc1, 0x7c, 0x9b, 0x19, 0x67, 0x26, 0x50, 0x68, 0x4c, + 0x3a, 0x55, 0x36, 0xf2, 0x7f, 0x9a, 0x3d, 0xae, 0x20, 0x24, 0x48, 0x74, + 0xb6, 0x0a, 0x63, 0x47 +}; +/* [B-571] - GP NOT SUPPORTED */ +static const uint8_t nist_186_2_ecdsa_testvector_211_ptx[] = { +/* Msg */ + 0x70, 0x2b, 0x22, 0xb5, 0xc2, 0xba, 0x25, 0xdf, 0xf7, 0x4b, 0x28, 0xf5, + 0x91, 0x24, 0xe7, 0x19, 0x40, 0x08, 0xab, 0xc0, 0xb3, 0xb8, 0xbf, 0x58, + 0xae, 0xb9, 0x24, 0x2f, 0x5d, 0x58, 0x85, 0x90, 0xe8, 0xec, 0x6d, 0x2f, + 0x47, 0x5b, 0xb8, 0xc6, 0x58, 0xdf, 0x48, 0x01, 0x2e, 0x0a, 0xf9, 0x98, + 0xac, 0x08, 0xd6, 0xba, 0x53, 0x25, 0x8d, 0xb2, 0x59, 0x8e, 0x20, 0xc5, + 0xfb, 0x5c, 0xde, 0x59, 0x14, 0xce, 0x92, 0x5d, 0xed, 0xd6, 0xfa, 0xe4, + 0x57, 0xd8, 0x7a, 0x13, 0xf7, 0xae, 0x12, 0x3e, 0xe2, 0xef, 0x8e, 0x4e, + 0x6a, 0x71, 0xfc, 0x66, 0x37, 0x0c, 0x63, 0xc6, 0x99, 0xa1, 0xb2, 0xef, + 0x1c, 0x5b, 0xf7, 0x07, 0x5d, 0x35, 0xd1, 0x80, 0x1d, 0xbd, 0x28, 0xf5, + 0x94, 0x17, 0x1b, 0x54, 0x07, 0x44, 0x3a, 0x42, 0x9d, 0xa5, 0xf6, 0xbb, + 0x6f, 0xba, 0x55, 0xf9, 0xde, 0x30, 0xeb, 0x98 +}; +static const uint8_t nist_186_2_ecdsa_testvector_211_private[] = { +/* d - byte alignment */ + 0x01, 0x60, 0x1d, 0x26, 0x08, 0xcc, 0xba, 0xc5, 0x9e, 0x9f, 0x16, 0xeb, + 0x12, 0x3f, 0x98, 0x8c, 0xeb, 0x1e, 0xee, 0x23, 0x9c, 0xa0, 0x38, 0x80, + 0xd1, 0xdc, 0x25, 0x44, 0x6d, 0x84, 0xae, 0x67, 0xff, 0xc4, 0xe0, 0xa7, + 0xea, 0xf2, 0x6c, 0x33, 0xbf, 0x3d, 0x6d, 0x2b, 0x27, 0x91, 0x3e, 0x5e, + 0x33, 0x7f, 0x58, 0xe4, 0x8b, 0x5e, 0xf2, 0xab, 0xa6, 0xbb, 0x5b, 0xeb, + 0x42, 0x1d, 0x25, 0x58, 0x9e, 0xce, 0x18, 0xa6, 0x41, 0x2c, 0x0d, 0x50 +}; +static const uint8_t nist_186_2_ecdsa_testvector_211_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0xac, 0xc7, 0x28, 0x79, 0x8f, 0xfb, 0x2d, 0xea, 0x9f, 0x3b, 0x34, + 0x5c, 0x7e, 0x4d, 0x86, 0xb9, 0xd0, 0x53, 0x00, 0xd2, 0xc5, 0x9d, 0x2d, + 0x15, 0xef, 0x99, 0xad, 0x0b, 0xc9, 0x87, 0x32, 0x89, 0x74, 0xc4, 0xe1, + 0x78, 0x00, 0x74, 0x2d, 0x98, 0xc7, 0x8b, 0x2b, 0x70, 0x10, 0x93, 0xba, + 0xed, 0xe6, 0x86, 0x33, 0x93, 0x4b, 0xaa, 0xa8, 0x7e, 0xb2, 0xb0, 0xa0, + 0xe0, 0x10, 0x8b, 0x0f, 0x48, 0x3e, 0xd1, 0x87, 0xa0, 0xc7, 0x25, 0xd3 +}; +static const uint8_t nist_186_2_ecdsa_testvector_211_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x62, 0xe9, 0x27, 0xac, 0x17, 0xbf, 0xd2, 0x42, 0xdc, 0xac, 0x4a, + 0xfa, 0xb0, 0xd2, 0x0c, 0x65, 0xba, 0xde, 0xf4, 0x64, 0x68, 0xf2, 0x02, + 0x11, 0xad, 0xf5, 0x4e, 0xc4, 0xd2, 0x14, 0x5a, 0x85, 0x1d, 0x11, 0x21, + 0xd4, 0xcb, 0xf0, 0x13, 0x10, 0x9e, 0x06, 0xc5, 0xaf, 0x21, 0x5c, 0xdb, + 0x3d, 0x38, 0xa8, 0x5f, 0xf9, 0x2f, 0x6d, 0x54, 0x6b, 0x4a, 0xa8, 0x17, + 0xa4, 0xe5, 0x80, 0x34, 0x9a, 0xea, 0xc0, 0xca, 0x74, 0x41, 0x25, 0x88 +}; +/* k = 1510cc95330968b97382d63c46071c75ab92e9175862e5272222735a12e906625bb59b1843908d0e94052e2d90f82291fbbb5f853a40d8a4354f37015e5dc8118266747c19bfa95 */ +static const uint8_t nist_186_2_ecdsa_testvector_211_out[] = { +/* R - byte alignment */ + 0x03, 0xf4, 0x00, 0xdd, 0x5c, 0xc3, 0x87, 0xf1, 0xd8, 0xc5, 0x68, 0xd5, + 0xbc, 0x6d, 0x3e, 0xb0, 0x7e, 0x79, 0x28, 0x23, 0x06, 0x1d, 0x38, 0x44, + 0xe8, 0x04, 0x44, 0x0c, 0x3d, 0x78, 0x89, 0xa7, 0x78, 0x02, 0x19, 0x41, + 0x00, 0x0d, 0x6a, 0x47, 0x55, 0xe4, 0x89, 0xdd, 0xcb, 0xb0, 0x34, 0x5b, + 0x79, 0x8c, 0x4a, 0xbe, 0xbb, 0x7b, 0xb5, 0xfe, 0x57, 0x8e, 0x4a, 0x44, + 0x09, 0x3d, 0x2b, 0x17, 0x00, 0x37, 0xd2, 0xe7, 0x8c, 0x7a, 0x18, 0x65, +/* S - byte alignment */ + 0x00, 0x98, 0x66, 0xd2, 0x4d, 0x6f, 0x00, 0xc9, 0x4f, 0x67, 0xde, 0x16, + 0xec, 0xfa, 0xa5, 0xaa, 0x8b, 0x87, 0xdb, 0x45, 0x88, 0xff, 0x32, 0x03, + 0xf8, 0xdb, 0xc5, 0xee, 0x79, 0x01, 0x8a, 0x54, 0x12, 0x55, 0x76, 0x0c, + 0xdb, 0xac, 0xdd, 0xe6, 0xda, 0xf6, 0xad, 0xa8, 0xf2, 0x2a, 0x5d, 0x13, + 0x62, 0xc0, 0x81, 0x4d, 0xf4, 0x6d, 0x76, 0x64, 0x8b, 0x7a, 0x0f, 0xf1, + 0x37, 0x2a, 0xcd, 0x89, 0x9f, 0x38, 0x5e, 0xd5, 0x12, 0xd6, 0x3a, 0x25 +}; +static const uint8_t nist_186_2_ecdsa_testvector_212_ptx[] = { +/* Msg */ + 0x2b, 0x8a, 0x1e, 0x3e, 0x77, 0x71, 0x41, 0x82, 0xdd, 0xe3, 0x3c, 0xe1, + 0x11, 0x97, 0x77, 0x72, 0xdd, 0xfb, 0x34, 0xbc, 0xb8, 0x7a, 0xc4, 0x1e, + 0x99, 0xff, 0xfb, 0x6f, 0x0d, 0xb5, 0xe1, 0xe1, 0x88, 0x12, 0xaa, 0x2b, + 0xf8, 0x13, 0xe9, 0xe7, 0xa0, 0xc9, 0x00, 0x38, 0x24, 0x14, 0xdb, 0xb1, + 0xe0, 0xaf, 0xde, 0x72, 0x7e, 0x6c, 0x1b, 0x94, 0xc8, 0xc1, 0xc9, 0xc8, + 0xba, 0x84, 0xf1, 0x3a, 0xdc, 0xf3, 0x6b, 0xbc, 0xcf, 0xf7, 0x09, 0x20, + 0x25, 0xaa, 0x12, 0xe5, 0x76, 0x16, 0xf2, 0x17, 0xaf, 0x40, 0x2f, 0x70, + 0xae, 0x65, 0x9f, 0xc3, 0x0c, 0x83, 0xd9, 0x9b, 0x3a, 0x1b, 0xe9, 0x1f, + 0xd0, 0x35, 0x48, 0x38, 0x21, 0xa6, 0x0b, 0xf6, 0x13, 0x8e, 0x5a, 0x30, + 0x2e, 0x24, 0x24, 0x6b, 0xf2, 0xb6, 0x11, 0xfd, 0x6e, 0xeb, 0xb8, 0x73, + 0x0e, 0x4c, 0x13, 0x2f, 0xb5, 0x02, 0x2f, 0x56 +}; +static const uint8_t nist_186_2_ecdsa_testvector_212_private[] = { +/* d - byte alignment */ + 0x01, 0x85, 0x07, 0x58, 0xe4, 0xf1, 0xc0, 0x73, 0x09, 0x27, 0x2f, 0xf2, + 0xbf, 0x8d, 0xca, 0x7d, 0xf0, 0x07, 0xb4, 0xd9, 0x4e, 0x18, 0xbc, 0x41, + 0xeb, 0xb8, 0xb4, 0x34, 0xda, 0x48, 0x2f, 0x8b, 0xf0, 0xed, 0x67, 0xf3, + 0x66, 0xe8, 0xef, 0x6f, 0xcc, 0xd6, 0xc1, 0xd6, 0x54, 0xf6, 0xc4, 0x01, + 0xed, 0x02, 0x8e, 0xe3, 0x1b, 0x7c, 0x4c, 0x92, 0xeb, 0x07, 0x5b, 0x02, + 0xdd, 0xe7, 0xdd, 0xef, 0xe9, 0xa7, 0xad, 0x89, 0xb8, 0xd9, 0x4e, 0xfc +}; +static const uint8_t nist_186_2_ecdsa_testvector_212_public_x[] = { +/* Qx - byte alignment */ + 0x05, 0x28, 0x7b, 0x78, 0x75, 0x97, 0xd6, 0x61, 0x3d, 0xda, 0x0c, 0x27, + 0xad, 0xb6, 0x41, 0x0b, 0x2b, 0xf3, 0xb9, 0x93, 0xbb, 0x7a, 0xfa, 0x71, + 0xa8, 0xe0, 0x11, 0x3d, 0x48, 0xdb, 0x32, 0x94, 0x1a, 0x6f, 0xeb, 0x01, + 0xca, 0xb6, 0x04, 0x5d, 0xcb, 0x68, 0x84, 0xe9, 0x86, 0x9e, 0xea, 0xd3, + 0x58, 0xb2, 0xc5, 0x1f, 0x17, 0x36, 0xa9, 0xf8, 0x8f, 0xe3, 0x3a, 0x8b, + 0x4c, 0xbc, 0xb8, 0x76, 0xa4, 0x56, 0x34, 0xdf, 0x41, 0xf7, 0x5e, 0x29 +}; +static const uint8_t nist_186_2_ecdsa_testvector_212_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x63, 0x6e, 0x68, 0xf1, 0x97, 0x0d, 0x90, 0x58, 0xab, 0xd3, 0x4d, + 0xd2, 0x90, 0xe1, 0x64, 0xb5, 0x96, 0xc1, 0xd1, 0xdd, 0xee, 0x8d, 0xb6, + 0x04, 0x02, 0x74, 0xd9, 0xa5, 0x6a, 0x47, 0xbb, 0xf9, 0xd8, 0x2e, 0xd7, + 0x34, 0x4b, 0x01, 0x7e, 0xf5, 0x9a, 0xe6, 0x33, 0x6f, 0xd0, 0x2d, 0x16, + 0xcb, 0x32, 0x5a, 0xb2, 0x90, 0xc4, 0xbf, 0x0c, 0xa5, 0x61, 0xfd, 0xad, + 0xc7, 0xcc, 0xcc, 0x81, 0x55, 0x5a, 0x25, 0x1d, 0xd7, 0x39, 0xe1, 0xf7 +}; +/* k = 0612df3727988c24712035d9070fae6eb3cf2ff2f2cac00265140a660afd738829906f479b5f55e9591e412f874f03adb8f09ff8faf91c5f86294296bbc2bf7c9fad3660bb47606 */ +static const uint8_t nist_186_2_ecdsa_testvector_212_out[] = { +/* R - byte alignment */ + 0x01, 0x3b, 0x24, 0xdc, 0x81, 0xfb, 0x93, 0xfc, 0xdf, 0x70, 0xfa, 0xac, + 0x12, 0x90, 0x72, 0xce, 0x5f, 0x95, 0x0a, 0xd3, 0xfb, 0x55, 0x3a, 0x4d, + 0x32, 0x26, 0x07, 0xa6, 0x9a, 0x29, 0xb6, 0xbe, 0x3d, 0x9f, 0xf7, 0x27, + 0x65, 0xd6, 0xee, 0x2d, 0x93, 0x43, 0xe0, 0x0a, 0x25, 0x2e, 0x67, 0x2e, + 0x00, 0xb1, 0x99, 0x09, 0x52, 0x38, 0x34, 0x8c, 0x06, 0x6c, 0x95, 0xb4, + 0x24, 0x32, 0x84, 0x60, 0xcc, 0xb1, 0x0d, 0xd7, 0x7b, 0x13, 0x71, 0x43, +/* S - byte alignment */ + 0x00, 0xd6, 0x07, 0x5c, 0xbd, 0xf3, 0xa5, 0x3c, 0x93, 0x27, 0x76, 0x59, + 0xcf, 0x1f, 0xdd, 0xfc, 0xfe, 0x7c, 0xf0, 0x97, 0x33, 0x19, 0xad, 0xe7, + 0x0f, 0xce, 0x19, 0xf6, 0x6c, 0xf8, 0xb2, 0xd7, 0xd7, 0xae, 0x5e, 0xeb, + 0x44, 0x71, 0x1d, 0x51, 0x9a, 0x16, 0xfb, 0x05, 0xa7, 0x11, 0x8d, 0x74, + 0xf2, 0xc1, 0x17, 0x41, 0xa7, 0x29, 0x4b, 0x98, 0x51, 0x98, 0x9d, 0x5f, + 0xad, 0xb8, 0x4c, 0xd6, 0x32, 0x49, 0xaf, 0x87, 0x70, 0x6d, 0x42, 0xe8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_213_ptx[] = { +/* Msg */ + 0x07, 0xe2, 0xce, 0x83, 0x25, 0x6d, 0xba, 0x59, 0x1a, 0x6f, 0x55, 0xe2, + 0xb1, 0x51, 0xf6, 0x6a, 0x19, 0x5a, 0x56, 0x15, 0xf3, 0x76, 0x45, 0xc6, + 0xaa, 0x36, 0x9b, 0x40, 0x03, 0x17, 0x72, 0x8b, 0xf5, 0x07, 0x92, 0x9a, + 0xba, 0x25, 0x2d, 0x2a, 0x26, 0xc9, 0xcd, 0xed, 0x38, 0xc4, 0x8a, 0xe8, + 0xef, 0xe9, 0x80, 0x19, 0x5e, 0xcc, 0x80, 0x5e, 0x03, 0xc9, 0x06, 0x92, + 0x55, 0x48, 0x6b, 0xf9, 0x9c, 0x40, 0x5c, 0xde, 0x05, 0xfa, 0x8b, 0x7a, + 0xf6, 0x18, 0xa4, 0x18, 0x9f, 0xd5, 0x83, 0x77, 0xd2, 0x8e, 0xa4, 0x70, + 0x14, 0x82, 0xdb, 0xd8, 0xf4, 0xd6, 0x45, 0xa8, 0x9b, 0xdc, 0x7e, 0x5b, + 0xa5, 0x94, 0x14, 0x98, 0x2f, 0x73, 0x3c, 0x11, 0x31, 0x64, 0xc4, 0xab, + 0x0f, 0x0d, 0x49, 0xdf, 0x6a, 0x53, 0xaa, 0x60, 0x3c, 0x20, 0xbc, 0xfe, + 0x24, 0x63, 0x40, 0xca, 0xfe, 0x59, 0x12, 0x7b +}; +static const uint8_t nist_186_2_ecdsa_testvector_213_private[] = { +/* d - byte alignment */ + 0x03, 0xf8, 0xe4, 0x73, 0x72, 0x8c, 0xd7, 0xaa, 0x7c, 0xe1, 0x52, 0xce, + 0xf8, 0x99, 0x3b, 0xd6, 0x3b, 0xdd, 0xb3, 0x10, 0x75, 0xb2, 0x89, 0x0c, + 0xd0, 0xc2, 0x2f, 0x36, 0xe8, 0xec, 0x39, 0xb7, 0xde, 0xae, 0xab, 0x89, + 0x03, 0x28, 0x7f, 0x27, 0xbe, 0x9f, 0x6c, 0x69, 0x57, 0x47, 0xf9, 0x45, + 0xf3, 0x43, 0x8b, 0xea, 0x91, 0x1d, 0xb8, 0xa0, 0x79, 0xdd, 0x27, 0x81, + 0x44, 0x42, 0xb1, 0x64, 0x62, 0x4f, 0xdb, 0xe7, 0x0b, 0xea, 0xb9, 0xf9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_213_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x0e, 0x15, 0x36, 0x08, 0xa7, 0x3e, 0x25, 0xc0, 0xa7, 0x88, 0xbe, + 0x27, 0xc7, 0x1b, 0xfb, 0x2d, 0x4c, 0x11, 0x35, 0xa4, 0xd6, 0xa9, 0x52, + 0xc5, 0x39, 0x59, 0x32, 0xeb, 0x56, 0xfa, 0xfe, 0xbf, 0xc3, 0xda, 0xa1, + 0xb8, 0xce, 0x6b, 0x38, 0x82, 0x5e, 0xf0, 0xe4, 0xfa, 0x08, 0xad, 0xa8, + 0xcb, 0xf6, 0x5e, 0xae, 0x17, 0x5d, 0x59, 0xfc, 0x13, 0x71, 0x0f, 0x76, + 0xc9, 0x19, 0x13, 0x7f, 0xbe, 0x23, 0x3e, 0x46, 0xd3, 0x4c, 0x72, 0x56 +}; +static const uint8_t nist_186_2_ecdsa_testvector_213_public_y[] = { +/* Qy - byte alignment */ + 0x05, 0xbc, 0x33, 0x01, 0xb3, 0xb8, 0xee, 0xb3, 0xba, 0xb2, 0xc9, 0xc4, + 0xed, 0x9e, 0x35, 0x39, 0x7d, 0x5a, 0x91, 0x2b, 0xdc, 0xf2, 0x62, 0xe2, + 0x1c, 0xc3, 0xef, 0xab, 0x70, 0x69, 0xef, 0x61, 0xc4, 0x09, 0x21, 0xa1, + 0xf2, 0x3c, 0x25, 0xc5, 0xcd, 0xaa, 0x86, 0x93, 0x5a, 0x15, 0x98, 0x3c, + 0xf4, 0xa1, 0xe3, 0xdd, 0xdd, 0x7a, 0xeb, 0x52, 0x0c, 0x22, 0xeb, 0xb4, + 0x89, 0x24, 0x37, 0x9e, 0x18, 0x49, 0x18, 0x21, 0x33, 0x56, 0x4a, 0xc1 +}; +/* k = 3e3aac20908ac81c6906f5c8d011ed9a2117997d16d6b0093f602278e13335718b22aa88e9f1d0b8373d513b3dd7138a914d26a5b4f7fb4a75881a83ef05ac61efa580caef69702 */ +static const uint8_t nist_186_2_ecdsa_testvector_213_out[] = { +/* R - byte alignment */ + 0x02, 0x97, 0x8c, 0xcb, 0x53, 0x14, 0x5a, 0xfd, 0x54, 0x96, 0x23, 0x0f, + 0x0f, 0x30, 0xf7, 0x11, 0x2b, 0x42, 0x5a, 0x0a, 0xf6, 0xf9, 0x1b, 0xeb, + 0x64, 0xdd, 0xf0, 0xcc, 0x7d, 0xc2, 0xeb, 0xe0, 0x49, 0xe9, 0x7e, 0x73, + 0xf5, 0xdd, 0xb7, 0xbe, 0xf6, 0xb4, 0x86, 0x91, 0xea, 0x7d, 0x78, 0x89, + 0x23, 0x6e, 0xf5, 0x2c, 0x08, 0x41, 0x13, 0xe4, 0x06, 0x3f, 0x51, 0x99, + 0x4b, 0x73, 0x75, 0xe3, 0x42, 0x82, 0x0f, 0x62, 0x45, 0x09, 0xb1, 0xe1, +/* S - byte alignment */ + 0x03, 0xf2, 0x52, 0xc5, 0x6c, 0x6d, 0x4e, 0x56, 0x52, 0x36, 0x8c, 0x22, + 0x43, 0x72, 0xd9, 0x83, 0xb9, 0xe4, 0x27, 0x4f, 0x57, 0x21, 0xc8, 0x85, + 0xc7, 0x1a, 0x08, 0x9d, 0x31, 0x41, 0xf7, 0x06, 0x33, 0xfa, 0xb7, 0xa0, + 0xe9, 0x80, 0x89, 0xea, 0x1a, 0x66, 0xaf, 0xa9, 0xb1, 0xc6, 0x57, 0xe8, + 0x1a, 0xb7, 0xc5, 0x7c, 0x18, 0x96, 0xc6, 0xf4, 0xf8, 0xba, 0x74, 0x14, + 0xf1, 0xcf, 0x2d, 0xaf, 0x53, 0xee, 0xaa, 0x43, 0xac, 0x1c, 0x71, 0x28 +}; +static const uint8_t nist_186_2_ecdsa_testvector_214_ptx[] = { +/* Msg */ + 0xf6, 0xe7, 0x64, 0x6e, 0x7a, 0xc8, 0xba, 0xc1, 0xc9, 0x4a, 0x2b, 0xcb, + 0xd6, 0xe1, 0x69, 0x45, 0x08, 0xab, 0x2c, 0xdb, 0xeb, 0x53, 0x82, 0x30, + 0x26, 0x35, 0x66, 0x23, 0xad, 0xc3, 0x95, 0x51, 0x37, 0x27, 0x9d, 0xda, + 0xf3, 0x2a, 0x37, 0x69, 0x76, 0x54, 0xd6, 0x6e, 0xf8, 0x54, 0x80, 0xae, + 0xc1, 0xa3, 0xdd, 0xfe, 0xde, 0x65, 0x8e, 0x4b, 0x18, 0x90, 0xbf, 0xde, + 0x27, 0x4f, 0x00, 0xde, 0x22, 0xa9, 0x50, 0x17, 0x3a, 0x5e, 0x7b, 0xf9, + 0xa8, 0x11, 0xa7, 0xe4, 0xe4, 0xac, 0x29, 0xa3, 0x18, 0x01, 0x9d, 0x36, + 0xd4, 0xad, 0x35, 0xd4, 0x03, 0x42, 0x51, 0x30, 0x1e, 0xa5, 0x50, 0xfc, + 0x9f, 0xb4, 0xa6, 0xab, 0xb9, 0x2c, 0x2f, 0x7c, 0x46, 0xca, 0xc4, 0xb4, + 0x01, 0xb1, 0x0b, 0x2a, 0xf5, 0x0c, 0x93, 0x09, 0x35, 0xf4, 0x20, 0xd2, + 0xce, 0x94, 0x43, 0xa0, 0xfa, 0x8b, 0x2e, 0xb0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_214_private[] = { +/* d - byte alignment */ + 0x03, 0xc3, 0x26, 0x9d, 0x22, 0x23, 0xb2, 0xbf, 0xc9, 0x2e, 0x28, 0xdc, + 0x58, 0x63, 0x77, 0xd5, 0x50, 0x11, 0xee, 0xd1, 0x37, 0x08, 0xcf, 0x47, + 0x62, 0xc2, 0xec, 0x5b, 0x97, 0x7f, 0x40, 0x49, 0xe6, 0xab, 0x90, 0x90, + 0xde, 0x5f, 0x3d, 0xc7, 0x6b, 0xb8, 0x6f, 0x2e, 0xce, 0x59, 0xd1, 0x4f, + 0xd9, 0xb9, 0xc3, 0x15, 0x52, 0x94, 0x3e, 0x7b, 0xda, 0x92, 0x20, 0xb7, + 0x73, 0xff, 0x2c, 0x0d, 0x61, 0x0e, 0xe7, 0xd2, 0xc7, 0x16, 0x57, 0xbd +}; +static const uint8_t nist_186_2_ecdsa_testvector_214_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0x15, 0xad, 0x90, 0xc4, 0x4e, 0xe2, 0xa4, 0x24, 0x5e, 0x7a, 0x11, + 0xb2, 0xbc, 0xa9, 0x6c, 0x86, 0x65, 0x7a, 0x60, 0x1f, 0xdc, 0x64, 0xb3, + 0x96, 0x36, 0x12, 0x0c, 0xfd, 0x40, 0xfa, 0x35, 0xeb, 0xd8, 0xc5, 0xfe, + 0x0c, 0xf8, 0xd2, 0x8e, 0x33, 0xb7, 0x3d, 0xb5, 0x2a, 0xf5, 0xd2, 0x77, + 0x51, 0x5d, 0xee, 0x9f, 0x62, 0xd7, 0x55, 0x90, 0x77, 0x4a, 0xc2, 0x46, + 0xc0, 0x1a, 0xe2, 0x3a, 0x96, 0x95, 0xf9, 0x31, 0x6d, 0xec, 0xd6, 0xb4 +}; +static const uint8_t nist_186_2_ecdsa_testvector_214_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0xb0, 0xd1, 0xb9, 0xf0, 0x48, 0x09, 0x23, 0x63, 0x78, 0xf8, 0xfe, + 0xe9, 0x26, 0xb9, 0x2c, 0x2e, 0xf9, 0x87, 0x1e, 0xb9, 0x1b, 0xf6, 0xfa, + 0xab, 0x54, 0x34, 0x8f, 0xda, 0x84, 0x86, 0xf8, 0x8b, 0xa6, 0x90, 0x2b, + 0x97, 0x26, 0x8a, 0xf8, 0x93, 0x9d, 0x59, 0x0b, 0xec, 0xfa, 0x97, 0x7a, + 0x90, 0xcf, 0x2a, 0xf0, 0x89, 0x3b, 0x3a, 0x0e, 0xe0, 0x4a, 0x6c, 0x37, + 0x1a, 0x79, 0x57, 0x7e, 0x99, 0xf5, 0xc7, 0x20, 0x99, 0xe2, 0xaa, 0x6d +}; +/* k = 1a2670992bc17d4be856b4aef9fe5ea6e5764f1215317657c77fec4feb0d94de2b2cf5cfd56218122fd3b5c24cfc23d3a9e1d289de99c61f1a64ea2a93597e78da2a8621c0cb84f */ +static const uint8_t nist_186_2_ecdsa_testvector_214_out[] = { +/* R - byte alignment */ + 0x01, 0xa5, 0x36, 0x61, 0xe2, 0x8f, 0x57, 0xae, 0x75, 0xb3, 0x9c, 0xe0, + 0x44, 0x3a, 0x13, 0xcf, 0xb8, 0x1b, 0xd6, 0xbf, 0x64, 0x96, 0x2d, 0x29, + 0x99, 0x81, 0x54, 0xf3, 0xeb, 0x7d, 0xa9, 0x1e, 0x4e, 0x34, 0x82, 0xdd, + 0x67, 0xc6, 0x4a, 0xb2, 0x27, 0x1e, 0x4e, 0xbd, 0x26, 0x8f, 0xb1, 0x0d, + 0x36, 0xee, 0xe6, 0x74, 0xb3, 0xd0, 0xd7, 0xb1, 0xe0, 0xdd, 0x83, 0x4c, + 0x02, 0x8f, 0x31, 0x4c, 0x68, 0xec, 0xdd, 0x59, 0xf0, 0x99, 0x76, 0xb0, +/* S - byte alignment */ + 0x02, 0x56, 0x57, 0x15, 0xde, 0x56, 0x8b, 0x2e, 0x43, 0x28, 0xbb, 0xbc, + 0x5a, 0xab, 0xd2, 0xc4, 0xdf, 0xde, 0xae, 0x5d, 0xf7, 0xcf, 0x85, 0x91, + 0x06, 0x66, 0x47, 0x5b, 0xe4, 0x5b, 0x3b, 0xf8, 0xe5, 0x1c, 0x95, 0x32, + 0x17, 0x75, 0x27, 0xcb, 0x0e, 0x4c, 0x41, 0x7d, 0x9e, 0x58, 0x91, 0x50, + 0x29, 0x21, 0x07, 0x54, 0x8d, 0x8f, 0x53, 0x0b, 0xd8, 0xed, 0x27, 0x58, + 0xbd, 0x23, 0xf3, 0x63, 0x2d, 0xef, 0x1d, 0x08, 0xcc, 0x7b, 0xd8, 0xaf +}; +static const uint8_t nist_186_2_ecdsa_testvector_215_ptx[] = { +/* Msg */ + 0x4b, 0x59, 0x6e, 0x1f, 0x2a, 0xe2, 0xa0, 0x65, 0x06, 0x81, 0x68, 0x5f, + 0x69, 0xaa, 0x3d, 0x35, 0x29, 0xe6, 0x4f, 0xe8, 0x90, 0x6e, 0xc8, 0x8b, + 0xb9, 0xf8, 0x52, 0xb1, 0x3d, 0xd1, 0xda, 0x22, 0x10, 0x2c, 0x94, 0xd2, + 0xa5, 0xba, 0x40, 0x13, 0x59, 0x7a, 0xab, 0x09, 0x0e, 0xd3, 0x78, 0x5e, + 0x16, 0xe0, 0x20, 0x38, 0x54, 0x0b, 0x38, 0x68, 0x9d, 0xdd, 0xf3, 0xe5, + 0x64, 0x14, 0xe7, 0x78, 0x97, 0xf6, 0x14, 0xb8, 0xc4, 0xe6, 0x22, 0x39, + 0x80, 0x35, 0xea, 0x01, 0x09, 0x3a, 0x38, 0x3b, 0x2a, 0xa5, 0xcf, 0x30, + 0x5f, 0x10, 0xae, 0x72, 0x3a, 0xd7, 0x92, 0x5a, 0x05, 0x2a, 0xbc, 0xb5, + 0xa9, 0x60, 0xf4, 0xbb, 0xcf, 0x8e, 0xce, 0x41, 0x44, 0x59, 0x2c, 0x2f, + 0xa2, 0x08, 0x04, 0x33, 0x2d, 0xde, 0x64, 0xb7, 0xfb, 0xa6, 0xb3, 0x11, + 0x58, 0x8f, 0x39, 0xfa, 0x68, 0x3a, 0xe2, 0x42 +}; +static const uint8_t nist_186_2_ecdsa_testvector_215_private[] = { +/* d - byte alignment */ + 0x00, 0xc5, 0xfe, 0x0b, 0x12, 0xd4, 0x5a, 0x0e, 0xc0, 0xdb, 0x7f, 0x60, + 0xfd, 0x0b, 0xb9, 0x6f, 0xe8, 0x92, 0x05, 0x05, 0xa8, 0xb6, 0xbe, 0xaa, + 0x85, 0x3c, 0x0c, 0x85, 0xc8, 0xe0, 0x4d, 0x6c, 0x61, 0xdf, 0x5b, 0xac, + 0x49, 0x05, 0x66, 0x29, 0xf8, 0x21, 0x18, 0x40, 0xf9, 0x78, 0xc9, 0x9c, + 0x4f, 0x67, 0x3c, 0xbe, 0x5b, 0xf9, 0x8b, 0xcb, 0x0d, 0x1c, 0xfe, 0x85, + 0xc0, 0x4f, 0x66, 0xed, 0x18, 0xd3, 0x46, 0xb8, 0x20, 0x1c, 0xa2, 0x36 +}; +static const uint8_t nist_186_2_ecdsa_testvector_215_public_x[] = { +/* Qx - byte alignment */ + 0x07, 0xc6, 0x29, 0x37, 0xd0, 0xc4, 0x4b, 0xf8, 0x6c, 0x3a, 0xb5, 0x82, + 0x25, 0x2a, 0x5e, 0x64, 0x57, 0xc4, 0x36, 0x7c, 0x6a, 0x0e, 0x41, 0xe2, + 0xf9, 0x2e, 0xdb, 0x1c, 0x7a, 0x56, 0x05, 0xba, 0x4a, 0x42, 0xc6, 0xd5, + 0xfe, 0x19, 0xa1, 0x63, 0xf9, 0xcf, 0x5c, 0x83, 0x12, 0xf8, 0xac, 0x47, + 0x29, 0xef, 0x01, 0x53, 0xb5, 0x5c, 0xc9, 0x81, 0xd1, 0x13, 0xd6, 0xdc, + 0x8b, 0x39, 0x61, 0x0f, 0x4f, 0x57, 0x7e, 0x73, 0x70, 0xb2, 0xfb, 0xb9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_215_public_y[] = { +/* Qy - byte alignment */ + 0x01, 0x48, 0x76, 0x4e, 0x23, 0xec, 0x53, 0x5b, 0x17, 0x1d, 0x3f, 0x9e, + 0x70, 0x29, 0x54, 0x7f, 0x3c, 0xac, 0xe7, 0xfb, 0x06, 0xa8, 0x54, 0xa7, + 0x54, 0xbe, 0x63, 0x5b, 0x69, 0xb8, 0xc1, 0x51, 0xa5, 0x1f, 0x5c, 0x5b, + 0xf0, 0x11, 0x29, 0x92, 0x31, 0xd5, 0xad, 0x2f, 0x99, 0xf0, 0xdb, 0x96, + 0xaa, 0x6e, 0x0d, 0xad, 0x4f, 0xef, 0x45, 0x00, 0x1a, 0x57, 0x63, 0x95, + 0x19, 0x85, 0xa3, 0xb0, 0x91, 0xc5, 0xdb, 0xef, 0xe6, 0x8a, 0x2a, 0x09 +}; +/* k = 0d04bc12c2eefad9bca46c727801d39231e72a8d8c0cf3ea9416530da56f3339165406a08a45901e3b210ac8597cf588b0a48c61ef300ef2c96ee02d13a30ffeb4fc5f386d1a0ea */ +static const uint8_t nist_186_2_ecdsa_testvector_215_out[] = { +/* R - byte alignment */ + 0x02, 0x63, 0x16, 0x99, 0x79, 0x89, 0xb9, 0xf7, 0x48, 0x34, 0x83, 0xc5, + 0x2d, 0x3f, 0x68, 0x04, 0xe9, 0x2d, 0xb3, 0xb8, 0x21, 0x2d, 0x5b, 0x1f, + 0xd0, 0x47, 0x4f, 0xd4, 0xfe, 0x51, 0xe3, 0xfe, 0xe6, 0xb7, 0x91, 0xbe, + 0xfe, 0x7d, 0x5e, 0x07, 0x4b, 0xe9, 0xf0, 0xc5, 0x61, 0xcf, 0xa7, 0x3b, + 0x7b, 0x2b, 0x6a, 0x8e, 0x46, 0x89, 0x18, 0xfe, 0x69, 0x41, 0x53, 0x25, + 0x48, 0xb5, 0x99, 0x1d, 0xc0, 0x90, 0x31, 0xfb, 0x2f, 0xe1, 0xa0, 0x27, +/* S - byte alignment */ + 0x03, 0x27, 0x4c, 0xe2, 0xca, 0x05, 0xd0, 0xfe, 0x8b, 0x0a, 0x95, 0x8c, + 0x66, 0x60, 0x46, 0xcb, 0x0b, 0x94, 0x4e, 0x31, 0xa2, 0x8a, 0xef, 0xbb, + 0x6b, 0x3f, 0xfa, 0x76, 0x6f, 0x68, 0xc5, 0xee, 0xf6, 0xeb, 0x34, 0xe9, + 0x52, 0xc2, 0xf3, 0x12, 0x6d, 0x73, 0x59, 0x8e, 0x22, 0x26, 0x47, 0xfb, + 0x70, 0x96, 0xbd, 0x98, 0x27, 0xec, 0x6c, 0x01, 0xf9, 0x7e, 0xd2, 0x3e, + 0x3b, 0xac, 0xf7, 0xc7, 0xb3, 0x7c, 0xa6, 0xe8, 0x5f, 0xb1, 0x84, 0x42 +}; +static const uint8_t nist_186_2_ecdsa_testvector_216_ptx[] = { +/* Msg */ + 0xff, 0x93, 0x70, 0xf9, 0x30, 0x84, 0x51, 0x7d, 0x70, 0xa1, 0xa1, 0xd6, + 0xcf, 0x8a, 0x16, 0x30, 0xd7, 0x71, 0xa0, 0x09, 0x1c, 0x69, 0xa0, 0x96, + 0x15, 0xe1, 0x55, 0x63, 0x2a, 0x6b, 0x96, 0x3b, 0x0e, 0xc3, 0xc7, 0x47, + 0x4f, 0x0c, 0x06, 0x79, 0x2c, 0x5c, 0xa5, 0x2c, 0xa6, 0x7b, 0xdd, 0x04, + 0xda, 0xe8, 0xc0, 0x1c, 0x8d, 0x1d, 0x70, 0x60, 0x09, 0x14, 0x8f, 0x37, + 0x28, 0x0a, 0xf6, 0x66, 0xae, 0x83, 0xaa, 0x31, 0xdb, 0x8e, 0x0b, 0xc2, + 0x41, 0x4a, 0x4f, 0xcf, 0xd4, 0xa9, 0x2f, 0x78, 0x40, 0x74, 0xe0, 0x6e, + 0x7f, 0x90, 0x45, 0x5a, 0xaa, 0x7f, 0x63, 0x7d, 0x0f, 0x29, 0x15, 0x93, + 0x85, 0xdd, 0x01, 0xfe, 0xfc, 0x93, 0xca, 0x20, 0x58, 0x74, 0x88, 0x09, + 0x80, 0x9c, 0x75, 0x52, 0xb1, 0x1e, 0xe8, 0x48, 0x19, 0x48, 0x88, 0x4e, + 0xa1, 0x29, 0xb9, 0x7c, 0x0a, 0x51, 0x5b, 0x8c +}; +static const uint8_t nist_186_2_ecdsa_testvector_216_private[] = { +/* d - byte alignment */ + 0x03, 0xe5, 0xa9, 0xc2, 0x5a, 0xe4, 0xb7, 0x42, 0x3a, 0xeb, 0xac, 0x13, + 0x28, 0x3e, 0xb1, 0x0e, 0xce, 0x49, 0x53, 0x37, 0x1c, 0xcd, 0x3f, 0xca, + 0xf2, 0x1f, 0x0c, 0x1f, 0x39, 0xfa, 0x75, 0x3c, 0xa2, 0x0a, 0x6a, 0x2f, + 0x47, 0x9b, 0x82, 0x10, 0x64, 0xec, 0x52, 0xd4, 0x57, 0x45, 0x9c, 0xfd, + 0xb6, 0xab, 0x6e, 0x7c, 0x7f, 0xcd, 0x86, 0x6c, 0x8b, 0x0b, 0x6c, 0x9d, + 0x84, 0x8c, 0x4d, 0xbf, 0x22, 0x1c, 0x06, 0xa1, 0x6b, 0xb9, 0x91, 0x85 +}; +static const uint8_t nist_186_2_ecdsa_testvector_216_public_x[] = { +/* Qx - byte alignment */ + 0x03, 0x42, 0xd3, 0x9b, 0x3f, 0x2c, 0xc9, 0x33, 0x6d, 0xcb, 0xf7, 0xa0, + 0x9c, 0x06, 0xaf, 0x6f, 0x60, 0xa0, 0x8f, 0xb7, 0x63, 0x17, 0xb3, 0x71, + 0x15, 0x5b, 0xf9, 0x96, 0x5b, 0x6b, 0x96, 0x9c, 0x99, 0xc7, 0xf5, 0x73, + 0x65, 0xe6, 0x03, 0x10, 0xa8, 0xaf, 0xc5, 0x8b, 0xec, 0x92, 0x43, 0xfc, + 0xf4, 0x81, 0x42, 0xa3, 0x19, 0xaa, 0xb1, 0x54, 0x25, 0xac, 0x09, 0x5f, + 0x53, 0x8a, 0xdf, 0xd1, 0x20, 0x4c, 0x7b, 0xe6, 0x07, 0xb9, 0x97, 0x7d +}; +static const uint8_t nist_186_2_ecdsa_testvector_216_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x07, 0xfb, 0x19, 0xc9, 0xd3, 0xd0, 0xad, 0x25, 0x69, 0xa4, 0x63, + 0x45, 0x53, 0x08, 0x46, 0xc3, 0xf6, 0x6a, 0x34, 0xd6, 0x24, 0x1e, 0x0b, + 0x9d, 0xe4, 0xb8, 0x4b, 0xc5, 0x08, 0x2a, 0x09, 0xb7, 0xfc, 0x98, 0x58, + 0x6b, 0x16, 0x8a, 0x9f, 0xed, 0xdf, 0x67, 0x58, 0x3f, 0x0f, 0xd9, 0xfb, + 0x75, 0x9e, 0x95, 0x2c, 0xa4, 0x2c, 0xb6, 0x29, 0x44, 0x40, 0x47, 0x03, + 0x9f, 0xd8, 0xc1, 0xc6, 0x01, 0xac, 0x80, 0x8d, 0x8b, 0xba, 0x06, 0xb4 +}; +/* k = 3d3c85e9b396d0b691dd3449647d786a06024e46ccfed1555b03ade3d57b339cdab9b0905d7395c603ea609b6175ce3083b2c38a93324acd08e7acc2a9b9d971fc4a80abe458574 */ +static const uint8_t nist_186_2_ecdsa_testvector_216_out[] = { +/* R - byte alignment */ + 0x00, 0x7b, 0x4c, 0x54, 0x4e, 0x06, 0x35, 0x56, 0x71, 0xd6, 0x8b, 0xbc, + 0xf7, 0xc7, 0x0d, 0x39, 0xc8, 0xb4, 0xd1, 0xee, 0xc2, 0xbe, 0x71, 0xd7, + 0x61, 0x41, 0x7f, 0xda, 0x2d, 0xa7, 0x4f, 0x72, 0x60, 0x7b, 0xbc, 0xb0, + 0x95, 0xe3, 0x80, 0x94, 0x48, 0xfa, 0xd6, 0x85, 0x62, 0x39, 0x59, 0xea, + 0xe5, 0xb6, 0xb5, 0x66, 0x3d, 0xde, 0xf4, 0xcc, 0xda, 0x9b, 0x6c, 0xc9, + 0x59, 0x84, 0x17, 0xfc, 0x9f, 0x6c, 0x93, 0xf9, 0xc2, 0xf3, 0xd4, 0xb8, +/* S - byte alignment */ + 0x00, 0x7c, 0x15, 0x21, 0xdf, 0x33, 0xc2, 0x28, 0x2b, 0xf8, 0xb0, 0x5e, + 0xf3, 0x86, 0x42, 0x40, 0xdd, 0x09, 0x87, 0x04, 0x78, 0x47, 0xdc, 0x33, + 0x14, 0x99, 0x05, 0x0e, 0x1d, 0x86, 0xa9, 0x8f, 0x12, 0xe5, 0x8d, 0x55, + 0x26, 0xd2, 0x29, 0x02, 0x23, 0x15, 0xc4, 0xd8, 0xfc, 0xcd, 0xe6, 0xf0, + 0x83, 0x19, 0xeb, 0xd0, 0x25, 0x55, 0x49, 0xd2, 0x15, 0x22, 0x95, 0x93, + 0x4e, 0xb1, 0xad, 0xb9, 0x8a, 0x34, 0x69, 0x60, 0x22, 0x6b, 0x8d, 0x39 +}; +static const uint8_t nist_186_2_ecdsa_testvector_217_ptx[] = { +/* Msg */ + 0xf3, 0xa7, 0xf1, 0x92, 0x28, 0x29, 0x4d, 0x19, 0xfe, 0xa1, 0x2e, 0xd7, + 0xe1, 0xe3, 0xee, 0x4d, 0x9b, 0x9b, 0x52, 0xbc, 0xbd, 0x28, 0x0f, 0x96, + 0x41, 0xae, 0x8c, 0x32, 0x6d, 0x66, 0xea, 0xc3, 0xfb, 0x39, 0x42, 0x8b, + 0x76, 0x8e, 0x2d, 0x4c, 0xe7, 0x60, 0x8a, 0x00, 0xb1, 0x93, 0x7b, 0xc9, + 0xba, 0x88, 0xb1, 0x2b, 0xcb, 0xef, 0xea, 0x79, 0x3a, 0xdc, 0xb7, 0x8d, + 0xc6, 0x1d, 0x83, 0xbc, 0xc2, 0xcc, 0xd1, 0x0a, 0x76, 0x20, 0xc5, 0x99, + 0xc2, 0x88, 0xe6, 0x68, 0x04, 0xfb, 0x22, 0x3a, 0x3c, 0x89, 0x13, 0xd3, + 0x6e, 0x37, 0x80, 0x6a, 0x48, 0x09, 0x27, 0x5c, 0x05, 0x60, 0xb9, 0x1e, + 0x91, 0x86, 0x27, 0x75, 0xee, 0x88, 0x1c, 0xe9, 0xd6, 0x44, 0xca, 0x77, + 0xa2, 0xc2, 0xea, 0x86, 0x6a, 0xc8, 0xfe, 0x1c, 0x6e, 0xa8, 0xda, 0x52, + 0xb4, 0x5d, 0x62, 0x05, 0xf3, 0xd6, 0x95, 0xcf +}; +static const uint8_t nist_186_2_ecdsa_testvector_217_private[] = { +/* d - byte alignment */ + 0x02, 0x7c, 0xb0, 0x16, 0xc5, 0xe7, 0x48, 0xe1, 0xd1, 0xe9, 0xf3, 0x9e, + 0xc9, 0x13, 0x7e, 0x5a, 0xee, 0xc4, 0xce, 0xb1, 0x7e, 0x26, 0x1e, 0x61, + 0x4e, 0x29, 0xde, 0x53, 0x3d, 0xe5, 0x82, 0x30, 0xd3, 0xd8, 0x17, 0xb6, + 0x5a, 0xec, 0x05, 0x11, 0xad, 0x1a, 0x9d, 0x5d, 0x23, 0x58, 0x71, 0x59, + 0xf5, 0xf8, 0x38, 0xed, 0xeb, 0x26, 0x56, 0xc2, 0x01, 0x6c, 0xcf, 0x21, + 0x1f, 0xb3, 0x3d, 0xd1, 0x06, 0x0a, 0xbc, 0x01, 0xa4, 0xa3, 0x66, 0xaf +}; +static const uint8_t nist_186_2_ecdsa_testvector_217_public_x[] = { +/* Qx - byte alignment */ + 0x06, 0xdd, 0xbf, 0x57, 0xed, 0xe6, 0xbd, 0x2c, 0x24, 0x49, 0xdc, 0x49, + 0xc2, 0xc9, 0x34, 0xfb, 0xd7, 0x59, 0x1f, 0x7b, 0xcb, 0xd6, 0x83, 0x26, + 0x51, 0x9e, 0xef, 0xbe, 0x5e, 0xfe, 0x92, 0xd0, 0x54, 0x2f, 0x29, 0xc1, + 0xad, 0xe9, 0xfd, 0x25, 0x1d, 0x36, 0x7d, 0xfd, 0x18, 0x17, 0x7c, 0x4f, + 0xff, 0x10, 0xe3, 0x6c, 0xcb, 0xd4, 0xb4, 0x66, 0x63, 0x9e, 0x8f, 0x1b, + 0x25, 0xad, 0xbd, 0xbe, 0x0f, 0x8d, 0xe8, 0x8a, 0x07, 0xf8, 0x25, 0xfc +}; +static const uint8_t nist_186_2_ecdsa_testvector_217_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x1e, 0x23, 0xa5, 0x43, 0x40, 0xe3, 0xed, 0x9b, 0x94, 0xdb, 0xbf, + 0x40, 0xb5, 0x88, 0xfa, 0x83, 0x12, 0xe5, 0x76, 0x9f, 0xb4, 0x72, 0xe8, + 0xca, 0x8c, 0x4d, 0xe1, 0x14, 0x9b, 0xab, 0xff, 0xc4, 0x2a, 0xee, 0xc3, + 0x3a, 0xee, 0xb9, 0xc4, 0x66, 0xd2, 0xa6, 0x99, 0x34, 0x07, 0x48, 0xc0, + 0xbf, 0xc4, 0xd3, 0x6c, 0xe1, 0x61, 0x5c, 0x09, 0x59, 0x2b, 0xa9, 0xe4, + 0xbc, 0xee, 0x7e, 0x5b, 0xaf, 0xfc, 0xf4, 0xfd, 0x60, 0x04, 0xb8, 0xe5 +}; +/* k = 176e893cdb9bb48d19e67a2cf0fccdfeb8adfecbcc375b86efbb8b37245b7108332e149409643f916693f38f2f966e55c77cf19edee58584344bb159ab7aa93b6f59113d83e3b9b */ +static const uint8_t nist_186_2_ecdsa_testvector_217_out[] = { +/* R - byte alignment */ + 0x01, 0x16, 0x03, 0x17, 0x82, 0x59, 0xb2, 0x8c, 0x0f, 0x94, 0xe1, 0xe9, + 0xbd, 0xf2, 0xef, 0xe3, 0x23, 0x5f, 0xfb, 0x39, 0x4e, 0xc1, 0x43, 0xd7, + 0x0a, 0xc0, 0xf0, 0xdc, 0xfa, 0x86, 0x37, 0xb0, 0x3c, 0x6e, 0xa9, 0x83, + 0x30, 0xd3, 0x6b, 0x6b, 0x32, 0x0f, 0x2d, 0xfe, 0x77, 0x6d, 0x57, 0xdf, + 0x71, 0x9a, 0xfd, 0xd7, 0x3c, 0x8b, 0x1b, 0x5a, 0x85, 0xdf, 0x65, 0xca, + 0x09, 0xaf, 0xa5, 0xcf, 0xcf, 0xc3, 0x25, 0x77, 0x07, 0xe3, 0xa7, 0x1f, +/* S - byte alignment */ + 0x03, 0xaa, 0x5f, 0xa8, 0x27, 0x2e, 0xd3, 0x4c, 0x09, 0xfc, 0x43, 0x21, + 0xfe, 0x22, 0x3c, 0x2a, 0xc1, 0xaf, 0x03, 0xc1, 0x4a, 0x80, 0x37, 0xa1, + 0x4d, 0x2c, 0x38, 0xf5, 0x81, 0x71, 0x89, 0xb7, 0xd1, 0xb1, 0xa7, 0xc9, + 0x67, 0x05, 0xd4, 0xf9, 0x11, 0xbf, 0xe0, 0x3e, 0x00, 0xcf, 0xb0, 0xb3, + 0x64, 0x94, 0x4b, 0x5b, 0x70, 0x27, 0x8d, 0xa5, 0x78, 0xf9, 0x6f, 0x57, + 0xc0, 0x82, 0xb5, 0xa5, 0xd6, 0x40, 0xbf, 0x83, 0x87, 0xc3, 0xdb, 0x01 +}; +static const uint8_t nist_186_2_ecdsa_testvector_218_ptx[] = { +/* Msg */ + 0x99, 0x75, 0x3b, 0xca, 0xab, 0xcd, 0xc6, 0xa8, 0xce, 0x6c, 0x15, 0x7d, + 0x49, 0x4b, 0xc8, 0xb7, 0xe4, 0xe3, 0x03, 0x3c, 0xfa, 0xf2, 0x1e, 0x50, + 0xd0, 0x7d, 0x9d, 0xb8, 0x25, 0x11, 0x62, 0x1f, 0x0a, 0x4f, 0x21, 0xba, + 0xf4, 0xa8, 0x15, 0x28, 0x10, 0x64, 0xf1, 0x9c, 0xd6, 0xe9, 0x1a, 0x3d, + 0xe1, 0x3a, 0x13, 0xcd, 0xfe, 0xbe, 0x38, 0x89, 0x83, 0x43, 0xb0, 0x51, + 0xe2, 0x42, 0x9d, 0x09, 0x7d, 0x64, 0x95, 0x3f, 0xbc, 0x46, 0x56, 0x0e, + 0x5d, 0x79, 0xb5, 0x42, 0x0c, 0xce, 0xd8, 0xbc, 0x34, 0xd0, 0xa5, 0x19, + 0x14, 0x91, 0x7a, 0x8e, 0x15, 0xaa, 0x1f, 0x16, 0x5b, 0x7d, 0xf9, 0xd0, + 0x9a, 0xbd, 0x80, 0xa2, 0x2b, 0x31, 0xf3, 0x23, 0x5f, 0xb4, 0x4a, 0xb8, + 0x13, 0x81, 0x6c, 0xfd, 0x84, 0xad, 0xa2, 0x66, 0x65, 0xf5, 0x4b, 0x26, + 0x2f, 0xba, 0xd2, 0x4f, 0xb9, 0x4a, 0xde, 0x3b +}; +static const uint8_t nist_186_2_ecdsa_testvector_218_private[] = { +/* d - byte alignment */ + 0x03, 0x4e, 0x5a, 0xd3, 0xa2, 0xd9, 0x7b, 0xd4, 0xef, 0x31, 0xa5, 0xbf, + 0x0a, 0x91, 0x45, 0xc8, 0xaf, 0x88, 0x79, 0xca, 0xa8, 0x05, 0x62, 0xc1, + 0xb0, 0x49, 0xe5, 0x81, 0x4b, 0x20, 0xb4, 0x71, 0x5d, 0xc6, 0xbe, 0x9a, + 0x9c, 0xa6, 0x11, 0x2e, 0x58, 0x2d, 0x5c, 0x6e, 0xa3, 0xf3, 0x21, 0x81, + 0xd3, 0x23, 0xbd, 0xca, 0x35, 0xd9, 0xd0, 0x95, 0x26, 0x07, 0x46, 0xa6, + 0x03, 0xbb, 0xd6, 0xef, 0xeb, 0x4a, 0xf8, 0xcf, 0x8f, 0x55, 0x00, 0xa8 +}; +static const uint8_t nist_186_2_ecdsa_testvector_218_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0xd4, 0x9d, 0x90, 0x4b, 0x28, 0xff, 0x3a, 0x76, 0x54, 0x98, 0x3c, + 0x1c, 0x14, 0x5c, 0x25, 0xd5, 0x1e, 0xbc, 0xfb, 0xa7, 0x67, 0x28, 0xd6, + 0xdf, 0xc9, 0xb0, 0x8a, 0xe2, 0x41, 0xa7, 0x68, 0xb5, 0x6c, 0x2d, 0x7d, + 0x04, 0x95, 0x34, 0x74, 0x69, 0xa5, 0xe3, 0xea, 0xc8, 0xf7, 0x69, 0x5c, + 0xf8, 0x72, 0xec, 0x4d, 0x9f, 0x08, 0xe5, 0xe1, 0x40, 0xd4, 0x5d, 0x47, + 0x52, 0x13, 0xe2, 0xeb, 0xfc, 0x43, 0x8f, 0x43, 0x53, 0x7d, 0x71, 0xed +}; +static const uint8_t nist_186_2_ecdsa_testvector_218_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x2e, 0x3d, 0x6e, 0xc8, 0xf7, 0xdc, 0x2c, 0xc1, 0x5d, 0xea, 0xaa, + 0xae, 0x66, 0x59, 0x3f, 0x01, 0xb8, 0x0f, 0xa2, 0xcf, 0x40, 0xb5, 0x2a, + 0xf6, 0x8c, 0x47, 0x16, 0x3a, 0x86, 0xd8, 0x4f, 0xaa, 0xa8, 0x34, 0x51, + 0xc8, 0xc1, 0x69, 0x37, 0x80, 0xee, 0x6a, 0xbf, 0x3f, 0x9b, 0x91, 0xc1, + 0x20, 0xd2, 0xd9, 0xc2, 0xeb, 0x9b, 0x7f, 0xf2, 0x13, 0x86, 0x16, 0x25, + 0x52, 0x91, 0x64, 0x9e, 0xe3, 0xcb, 0x40, 0xd1, 0xf2, 0x76, 0x28, 0x17 +}; +/* k = 1fcb55dab8822e70a4ffeff66138660f48612175d26df8445f1da492f4b525d311031c6b41948e08a1f22e4cc81fbfd0298ce565bb65c2d1cb002d674f65f4aa235da0cd5baa7a6 */ +static const uint8_t nist_186_2_ecdsa_testvector_218_out[] = { +/* R - byte alignment */ + 0x01, 0x70, 0xa3, 0x81, 0x06, 0x57, 0xa1, 0x73, 0x55, 0x42, 0xfd, 0xd8, + 0xe1, 0xdf, 0xe0, 0x21, 0x93, 0x9e, 0xa2, 0xf3, 0x44, 0xd2, 0x9f, 0x92, + 0x42, 0x82, 0x9c, 0x17, 0xe6, 0xf2, 0xfd, 0x59, 0x5f, 0xa4, 0xf7, 0xed, + 0x58, 0xe2, 0x8e, 0xe8, 0xe5, 0xc3, 0x09, 0xe3, 0x43, 0x7b, 0xee, 0x82, + 0x77, 0xcf, 0x47, 0xdb, 0x60, 0x93, 0xf6, 0x93, 0xa7, 0xf1, 0xac, 0x89, + 0x65, 0x1c, 0x04, 0x31, 0x31, 0xfc, 0x58, 0x4a, 0x80, 0x57, 0x4f, 0x0d, +/* S - byte alignment */ + 0x00, 0x57, 0xec, 0xdd, 0x33, 0xd0, 0x4a, 0x47, 0x1e, 0x8e, 0xd4, 0x48, + 0xbb, 0xe0, 0xf8, 0x18, 0xf2, 0x11, 0x4c, 0x0b, 0x51, 0xcd, 0x22, 0x47, + 0x3c, 0x19, 0x4d, 0xf0, 0x5b, 0x87, 0x00, 0xcf, 0x36, 0x99, 0x68, 0x42, + 0xef, 0x0b, 0xbb, 0x41, 0x3c, 0x2f, 0xd3, 0x32, 0xe8, 0x2e, 0x24, 0x9b, + 0xc2, 0xf9, 0x41, 0xe9, 0x18, 0x15, 0x25, 0x75, 0xa6, 0xf6, 0xd6, 0x6f, + 0xdf, 0xd8, 0x6f, 0x42, 0xfe, 0xd9, 0x2f, 0x45, 0x7c, 0x06, 0xad, 0xda +}; +static const uint8_t nist_186_2_ecdsa_testvector_219_ptx[] = { +/* Msg */ + 0xb8, 0x3c, 0xf7, 0xe1, 0x01, 0x77, 0x4a, 0x1e, 0xe7, 0x30, 0x16, 0x13, + 0x41, 0xba, 0xf4, 0x42, 0x9a, 0x3f, 0xf9, 0xbd, 0xcb, 0x02, 0xe8, 0x8b, + 0xd0, 0xe6, 0xa5, 0x4e, 0xd4, 0x34, 0xed, 0x23, 0x8e, 0x99, 0x45, 0xca, + 0xd0, 0x6e, 0x30, 0x07, 0x5d, 0x3c, 0xa5, 0x47, 0xfc, 0x80, 0xc0, 0x87, + 0xca, 0xab, 0xb8, 0x72, 0xd4, 0x6d, 0x11, 0xc9, 0xe5, 0x33, 0x13, 0x08, + 0x9d, 0xef, 0x7a, 0x47, 0xc3, 0x17, 0x6f, 0x5e, 0xdc, 0xf0, 0xb7, 0x4c, + 0xfd, 0x0c, 0x2b, 0xda, 0xdd, 0x11, 0x68, 0x7b, 0x2e, 0xbd, 0xc7, 0x77, + 0x2e, 0x27, 0x90, 0x48, 0x79, 0x48, 0x6a, 0x44, 0x21, 0xb9, 0x16, 0x7d, + 0x00, 0xbe, 0x5d, 0xe6, 0x4d, 0x84, 0x47, 0xb7, 0x6e, 0xa7, 0x8e, 0x12, + 0x0d, 0xf7, 0x52, 0xe6, 0x6e, 0x7c, 0x0e, 0x14, 0x00, 0xb8, 0xcb, 0xd0, + 0x32, 0x2b, 0x94, 0x4a, 0x87, 0x1d, 0x29, 0x8e +}; +static const uint8_t nist_186_2_ecdsa_testvector_219_private[] = { +/* d - byte alignment */ + 0x02, 0x64, 0xee, 0xc5, 0x75, 0xfe, 0xac, 0x9b, 0x93, 0xd1, 0x46, 0xbf, + 0xf0, 0x9d, 0x0a, 0x66, 0x78, 0x56, 0xca, 0x00, 0x62, 0x2b, 0x0c, 0x5a, + 0xfb, 0x94, 0x7e, 0x3d, 0x21, 0x19, 0x6d, 0xa5, 0x4e, 0xc0, 0xaa, 0xad, + 0x3e, 0xbd, 0xee, 0x0f, 0x76, 0x08, 0xf6, 0x4e, 0x48, 0x7b, 0x18, 0xcd, + 0x7d, 0x45, 0xb0, 0x0a, 0x8f, 0xd9, 0x3c, 0xad, 0x39, 0x6d, 0xc1, 0xb2, + 0xd1, 0xa3, 0x9a, 0xe1, 0x52, 0xb5, 0x10, 0x8e, 0x9c, 0xd2, 0x02, 0x6e +}; +static const uint8_t nist_186_2_ecdsa_testvector_219_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0x34, 0xdc, 0x73, 0xbc, 0x7a, 0x96, 0xe7, 0x9c, 0x7d, 0x11, 0x8e, + 0x2d, 0xf4, 0x19, 0xdb, 0x00, 0x30, 0xce, 0x90, 0xb3, 0xd2, 0xd7, 0x6d, + 0x6e, 0x7a, 0x0d, 0xcf, 0x97, 0x19, 0x99, 0x13, 0x8e, 0xc8, 0x3b, 0x53, + 0xc0, 0xbf, 0x54, 0x6d, 0x95, 0xa3, 0xa0, 0x54, 0x9b, 0xc9, 0xf6, 0x20, + 0x48, 0xbf, 0xe4, 0x54, 0xf9, 0x6a, 0x1e, 0xfc, 0x7d, 0xd9, 0x72, 0x0f, + 0xf8, 0x8b, 0x2c, 0x0f, 0x55, 0xbd, 0x9f, 0x8b, 0xbc, 0x0d, 0xeb, 0x79 +}; +static const uint8_t nist_186_2_ecdsa_testvector_219_public_y[] = { +/* Qy - byte alignment */ + 0x02, 0x72, 0x68, 0xbf, 0x70, 0x31, 0x65, 0x4d, 0x96, 0xc4, 0x05, 0xb9, + 0x4a, 0xcb, 0x9d, 0x2c, 0x9b, 0xa8, 0x33, 0xba, 0x71, 0x5c, 0x11, 0x23, + 0xa4, 0x0d, 0x89, 0x50, 0xc9, 0x58, 0x6c, 0x1d, 0xcc, 0xce, 0xd0, 0xf7, + 0x66, 0x19, 0x90, 0x9c, 0xd5, 0x4f, 0x3b, 0x36, 0x26, 0x80, 0xfc, 0x41, + 0x2f, 0x87, 0xe9, 0x59, 0xa0, 0xd0, 0xfb, 0x70, 0x74, 0x1a, 0x99, 0x44, + 0x2a, 0x85, 0xaa, 0xff, 0x09, 0x0c, 0x24, 0x23, 0x86, 0x76, 0x64, 0x8a +}; +/* k = 0e24f9bdd9e99e974723782982cec708b7e479ff01f414fdfa32d5cd56b73a82802030cce77a7a3def73844901e6a1b6d7d7d7d4131925d20f8c2f1d57ed6c38a0c44343ef4354c */ +static const uint8_t nist_186_2_ecdsa_testvector_219_out[] = { +/* R - byte alignment */ + 0x02, 0x0e, 0x3a, 0xb1, 0xba, 0x07, 0xbc, 0xee, 0xa8, 0xe0, 0x7b, 0x67, + 0x5e, 0x4b, 0x99, 0x03, 0x6d, 0xd5, 0x99, 0x45, 0x2d, 0x46, 0x55, 0x4b, + 0x20, 0x2d, 0xee, 0xf6, 0xb3, 0xc7, 0x3c, 0x95, 0x3f, 0xdf, 0x41, 0x1f, + 0xcc, 0x62, 0xb9, 0x52, 0x4d, 0xee, 0xba, 0xf1, 0x7b, 0x70, 0x0a, 0x62, + 0xa3, 0x51, 0xbb, 0xd8, 0xe2, 0xe7, 0xe1, 0x9e, 0x47, 0x23, 0x37, 0xc2, + 0x8a, 0x25, 0xd8, 0x09, 0xe3, 0x94, 0xd5, 0x01, 0xd5, 0x0f, 0xe8, 0x29, +/* S - byte alignment */ + 0x02, 0x4c, 0x08, 0x46, 0x4f, 0x28, 0x31, 0x5a, 0x0a, 0x07, 0xcb, 0x5a, + 0x2d, 0x66, 0x98, 0x0b, 0xb5, 0x3d, 0x7d, 0x72, 0xc5, 0xf4, 0x32, 0x7e, + 0x84, 0x19, 0xbf, 0xa2, 0x99, 0xf3, 0xf9, 0x3c, 0x4e, 0x42, 0xee, 0x4f, + 0x9e, 0xc6, 0x01, 0x17, 0x28, 0x95, 0xc4, 0x59, 0xea, 0x08, 0x2b, 0xa1, + 0xdd, 0xc1, 0x3d, 0x8b, 0x37, 0x66, 0xad, 0xd7, 0xc7, 0x4b, 0xdf, 0x69, + 0xdb, 0x53, 0x72, 0x47, 0x20, 0x0e, 0x95, 0x94, 0x0c, 0x80, 0xab, 0xdc +}; +static const uint8_t nist_186_2_ecdsa_testvector_220_ptx[] = { +/* Msg */ + 0xb5, 0x7d, 0xfa, 0x37, 0xcf, 0xc8, 0x8d, 0x60, 0xf2, 0xcd, 0x75, 0x06, + 0x22, 0x11, 0x70, 0x01, 0xb1, 0x2c, 0x06, 0xc7, 0x05, 0x7d, 0x6d, 0xca, + 0x9c, 0x1c, 0xa9, 0x07, 0x4c, 0x10, 0xf7, 0xdb, 0xd0, 0xc2, 0x6c, 0x19, + 0x80, 0xb2, 0xda, 0x5b, 0x60, 0x69, 0xf3, 0x95, 0x5c, 0xaf, 0xb1, 0xf0, + 0xd2, 0xfd, 0xf5, 0xd5, 0x51, 0x35, 0x6e, 0x47, 0xa1, 0x91, 0xbc, 0x77, + 0x03, 0xd9, 0xd5, 0x92, 0xb9, 0xda, 0xa8, 0xde, 0xc9, 0x13, 0x01, 0x05, + 0xff, 0xb1, 0xad, 0xb1, 0x31, 0xbe, 0xde, 0x58, 0xc6, 0x95, 0xd1, 0x5a, + 0x79, 0x99, 0xad, 0x49, 0x5b, 0x26, 0xaf, 0x87, 0x17, 0xc8, 0x84, 0x17, + 0x7a, 0xab, 0xf6, 0xad, 0x33, 0x53, 0xcb, 0x07, 0xd7, 0x8d, 0xea, 0x80, + 0x28, 0xa6, 0xc0, 0xe3, 0x96, 0xda, 0xe2, 0x7d, 0x06, 0x0f, 0xf4, 0x76, + 0xd3, 0xc4, 0xc9, 0x61, 0x12, 0x44, 0xcb, 0x11 +}; +static const uint8_t nist_186_2_ecdsa_testvector_220_private[] = { +/* d - byte alignment */ + 0x01, 0x23, 0x56, 0x16, 0x00, 0x10, 0x42, 0x2b, 0x88, 0x83, 0xb1, 0x8e, + 0x1a, 0xda, 0xb3, 0xf9, 0xd3, 0xc8, 0xb4, 0x6c, 0x90, 0x70, 0x94, 0xcc, + 0xc2, 0xc5, 0x8b, 0xa1, 0x40, 0x87, 0x6d, 0x81, 0x7d, 0x5c, 0x37, 0x49, + 0xf6, 0xbb, 0x9d, 0x5f, 0x64, 0xfc, 0xe6, 0x53, 0x2d, 0x43, 0xef, 0x6f, + 0xd2, 0xbe, 0x41, 0xf0, 0x1a, 0x33, 0xd9, 0xcd, 0x81, 0x3e, 0x18, 0x82, + 0x8a, 0x84, 0xea, 0x99, 0x64, 0x40, 0x28, 0x85, 0x27, 0xa8, 0x1a, 0x09 +}; +static const uint8_t nist_186_2_ecdsa_testvector_220_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0x42, 0x4d, 0x5e, 0x39, 0x42, 0x31, 0xc8, 0x6d, 0xfd, 0x0d, 0xdc, + 0x96, 0xe8, 0x49, 0xfc, 0xc5, 0xcb, 0x89, 0x9c, 0x32, 0x41, 0x78, 0xa1, + 0xf0, 0x6f, 0x13, 0x50, 0x30, 0x4a, 0x31, 0x08, 0xf7, 0xd0, 0xc7, 0xa5, + 0xe6, 0xd3, 0x22, 0x19, 0xaf, 0xac, 0x6e, 0x5d, 0x1f, 0x69, 0x7d, 0x82, + 0x75, 0x79, 0x2a, 0x51, 0x2f, 0x33, 0x70, 0xdd, 0x0c, 0xb8, 0x7f, 0x09, + 0xc9, 0xfb, 0x04, 0xb6, 0x14, 0xd9, 0xcd, 0xe0, 0xcf, 0xe8, 0x90, 0x70 +}; +static const uint8_t nist_186_2_ecdsa_testvector_220_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x84, 0xfd, 0x10, 0x4b, 0x23, 0x89, 0xfb, 0x82, 0x77, 0x47, 0x94, + 0xce, 0xd5, 0xe9, 0xcc, 0x39, 0x85, 0x1c, 0x11, 0xef, 0xde, 0xb7, 0xe4, + 0x49, 0xb7, 0x35, 0xd1, 0x82, 0x15, 0xc6, 0xdd, 0xcb, 0xb7, 0xc5, 0xbb, + 0xc0, 0x8b, 0x5e, 0xfe, 0x0b, 0x3d, 0x22, 0x14, 0x4f, 0x26, 0x56, 0xd5, + 0xb0, 0x17, 0x1d, 0x3b, 0x57, 0x3d, 0x85, 0xa8, 0x0a, 0x92, 0x4d, 0xb3, + 0x86, 0x87, 0xfe, 0x59, 0x35, 0x4b, 0x9a, 0x96, 0x06, 0xa6, 0x42, 0x83 +}; +/* k = 151f25d130f9e4bad9523c90ae32f53bebf95515a5ee5e8344c0766c2c9550fe139355bdaa5874d5cb1364c0591a8f0a6affd32234bb93252909b5ab475b87334101a4e257c8a16 */ +static const uint8_t nist_186_2_ecdsa_testvector_220_out[] = { +/* R - byte alignment */ + 0x02, 0x39, 0x7d, 0x48, 0x45, 0x1c, 0x8c, 0x15, 0xd9, 0x32, 0x6d, 0x5a, + 0x06, 0x15, 0xb4, 0xe3, 0x2d, 0x79, 0xa6, 0xdd, 0xe9, 0x24, 0x28, 0x0e, + 0x1f, 0x4d, 0x10, 0x28, 0x0a, 0xd8, 0xd5, 0x38, 0x23, 0x2f, 0x22, 0x53, + 0xa0, 0xcc, 0x9d, 0xc4, 0xdd, 0x3a, 0x7e, 0xdf, 0xa1, 0x2e, 0x4e, 0x00, + 0x65, 0x26, 0x61, 0xd3, 0x61, 0xc9, 0x26, 0x6a, 0xb3, 0x52, 0xe2, 0x99, + 0xd4, 0xae, 0x0f, 0x2f, 0x88, 0xb2, 0x17, 0x94, 0x25, 0x7f, 0x8e, 0xf7, +/* S - byte alignment */ + 0x01, 0xe9, 0xae, 0x69, 0xac, 0x91, 0x4a, 0xa6, 0xa3, 0x37, 0x3f, 0x38, + 0xf2, 0xf1, 0x96, 0x63, 0xb7, 0x79, 0x76, 0x65, 0x3a, 0x6a, 0x09, 0xba, + 0x88, 0x46, 0x17, 0x65, 0xa3, 0x8a, 0x51, 0x99, 0x25, 0x1b, 0xb5, 0x63, + 0xda, 0x93, 0xb9, 0x55, 0x7c, 0x19, 0x92, 0x84, 0xa6, 0x3f, 0x63, 0x47, + 0xe9, 0x38, 0x07, 0xe7, 0xb3, 0xb3, 0xb7, 0x18, 0x72, 0x00, 0x07, 0x49, + 0xf3, 0x9e, 0x53, 0x45, 0xe9, 0x93, 0xcb, 0x77, 0x8b, 0x56, 0x01, 0x09 +}; +static const uint8_t nist_186_2_ecdsa_testvector_221_ptx[] = { +/* Msg */ + 0x98, 0xdc, 0xbb, 0x87, 0x95, 0x09, 0x0a, 0x5d, 0x0d, 0xf4, 0x89, 0x5b, + 0xe0, 0x50, 0x35, 0x5e, 0x0d, 0x72, 0x19, 0x0f, 0x21, 0xfb, 0x66, 0xac, + 0xf6, 0xb8, 0xc6, 0x0c, 0x99, 0xc6, 0xee, 0xdd, 0x8c, 0xfa, 0x72, 0x31, + 0x2e, 0x7f, 0xde, 0x39, 0x77, 0xc1, 0x02, 0x4f, 0xe8, 0x8a, 0x8d, 0x3a, + 0xc2, 0x6b, 0xde, 0xae, 0x77, 0x5e, 0x16, 0x13, 0x5e, 0xa9, 0x72, 0x87, + 0xaa, 0x06, 0xd8, 0x26, 0x9d, 0x00, 0xaf, 0x89, 0xf9, 0xa0, 0xf4, 0x8c, + 0xb8, 0x49, 0x8a, 0x55, 0xfc, 0xe1, 0xd2, 0x92, 0x49, 0x31, 0x7c, 0x01, + 0xf2, 0x8f, 0x9d, 0x36, 0xd1, 0xba, 0x01, 0x99, 0x3b, 0x05, 0xc2, 0xae, + 0x33, 0xb8, 0x19, 0x99, 0xde, 0xb3, 0x75, 0xe1, 0x38, 0x54, 0xca, 0x74, + 0x04, 0x9b, 0x2c, 0xeb, 0x09, 0x8c, 0x9c, 0x10, 0x7b, 0xd5, 0x22, 0x9d, + 0xb8, 0xb1, 0x1c, 0x47, 0x35, 0x0c, 0xd5, 0xfb +}; +static const uint8_t nist_186_2_ecdsa_testvector_221_private[] = { +/* d - byte alignment */ + 0x02, 0xe2, 0x3e, 0xdb, 0xb2, 0x01, 0xcf, 0xc1, 0x32, 0xcb, 0x7b, 0x77, + 0xa1, 0x6c, 0xa6, 0x9d, 0x60, 0xcb, 0x62, 0x23, 0x26, 0x6a, 0x20, 0xd3, + 0xfe, 0x76, 0xb5, 0x21, 0x06, 0x08, 0xf4, 0x15, 0x81, 0x7d, 0xae, 0x6d, + 0x0b, 0xb2, 0x30, 0x2e, 0x51, 0x9b, 0xde, 0xda, 0x4b, 0xd7, 0x9e, 0x3d, + 0x7d, 0x36, 0xd3, 0x9d, 0x63, 0x65, 0xe1, 0x06, 0xd4, 0xe4, 0x54, 0x40, + 0x2d, 0xef, 0xbf, 0xa8, 0xe5, 0xce, 0x54, 0xff, 0xec, 0x45, 0xcd, 0x4b +}; +static const uint8_t nist_186_2_ecdsa_testvector_221_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x52, 0x6d, 0x32, 0xef, 0x32, 0xd7, 0xad, 0xa5, 0xc1, 0xf0, 0x0f, + 0x1a, 0x3c, 0x27, 0xaa, 0x76, 0x7f, 0x6e, 0x33, 0x4e, 0x7d, 0x9d, 0x5b, + 0x20, 0x5b, 0x59, 0x5f, 0xc9, 0x29, 0x9c, 0xd2, 0xaf, 0x61, 0xdc, 0x8f, + 0xc6, 0x7b, 0xef, 0x93, 0x75, 0xf7, 0xc9, 0x1a, 0xfd, 0xd6, 0x0d, 0x8c, + 0xca, 0xaf, 0x63, 0x25, 0x41, 0xb0, 0xeb, 0xd6, 0xbe, 0x28, 0x5a, 0xfa, + 0x85, 0xaa, 0x5d, 0xd8, 0x9c, 0x2d, 0xab, 0xac, 0xba, 0x2a, 0x24, 0x56 +}; +static const uint8_t nist_186_2_ecdsa_testvector_221_public_y[] = { +/* Qy - byte alignment */ + 0x03, 0xe4, 0x48, 0x32, 0x2e, 0x90, 0x00, 0x97, 0x1b, 0x6f, 0x1f, 0xcf, + 0x5d, 0xbd, 0x37, 0xd9, 0xa0, 0x07, 0xcb, 0xca, 0x6e, 0xed, 0xc1, 0x6e, + 0xf8, 0xd8, 0x34, 0x40, 0xf7, 0x42, 0x1b, 0xa1, 0xf7, 0xac, 0xe1, 0x3a, + 0x17, 0x3c, 0x36, 0x34, 0xd7, 0x13, 0x06, 0x1b, 0x54, 0x97, 0xff, 0x9a, + 0xf9, 0xb7, 0x2f, 0x1a, 0x88, 0xf6, 0xba, 0xad, 0xa7, 0x1b, 0xa4, 0x26, + 0x79, 0x2e, 0x3b, 0xd8, 0xe9, 0x7a, 0x82, 0x60, 0x61, 0x11, 0xe1, 0xd0 +}; +/* k = 21aa9009e6abca6b88fd0cbf68ae4a40bf7014b427c2e31cded299652e924f214e006853f72b957796c35b12425e9d3b0f12d01a02303e6f2ead725d056340bcd4c58214d770b73 */ +static const uint8_t nist_186_2_ecdsa_testvector_221_out[] = { +/* R - byte alignment */ + 0x00, 0xc5, 0xc9, 0xc8, 0xa5, 0xe2, 0x72, 0xd3, 0x25, 0x4e, 0x3c, 0xeb, + 0x1a, 0x9c, 0x5c, 0x6a, 0xf4, 0xcf, 0x2f, 0xa8, 0x5b, 0xed, 0x53, 0xaa, + 0x78, 0xc4, 0x8f, 0xc2, 0x86, 0x20, 0x0b, 0x31, 0xe6, 0xc8, 0x45, 0x88, + 0xb4, 0x38, 0x2e, 0xfd, 0x98, 0x57, 0x90, 0x2c, 0x1b, 0x68, 0xd8, 0xe3, + 0x33, 0xa2, 0x3b, 0x3c, 0x62, 0x18, 0x81, 0x65, 0x3c, 0x69, 0xb5, 0x5e, + 0x63, 0x93, 0xe4, 0x05, 0x7b, 0x70, 0x3d, 0xcd, 0xd4, 0x3f, 0x0c, 0x39, +/* S - byte alignment */ + 0x00, 0xaf, 0x3e, 0xb2, 0x1d, 0xd6, 0x7b, 0x0f, 0x9d, 0x4a, 0x5d, 0x43, + 0x07, 0x4e, 0xf8, 0x1e, 0x95, 0x51, 0x57, 0x63, 0x34, 0xfe, 0xf6, 0xde, + 0xf4, 0x32, 0xdd, 0x97, 0x3e, 0x67, 0x30, 0x9e, 0x42, 0xd9, 0x50, 0x0b, + 0xed, 0x14, 0xc7, 0x8a, 0x40, 0x2a, 0x41, 0x22, 0xaa, 0xfb, 0xc9, 0xba, + 0xc6, 0x94, 0x30, 0x8b, 0x00, 0xb6, 0x0e, 0xcf, 0x5a, 0x1e, 0xa2, 0xdd, + 0xdf, 0x77, 0xb5, 0xb8, 0xa5, 0xc1, 0x06, 0x2b, 0x82, 0xe6, 0xa3, 0x2f +}; +static const uint8_t nist_186_2_ecdsa_testvector_222_ptx[] = { +/* Msg */ + 0x41, 0x38, 0xb2, 0x52, 0xb9, 0x65, 0xac, 0x22, 0x4e, 0xcd, 0x35, 0x83, + 0x7d, 0x92, 0x3a, 0xbb, 0x3d, 0x56, 0x22, 0xa7, 0xcc, 0xf2, 0xb1, 0x0a, + 0xad, 0x6b, 0x2d, 0x25, 0xf2, 0x22, 0xc0, 0x88, 0xb7, 0x4a, 0x1e, 0x27, + 0xef, 0x9f, 0x67, 0xb0, 0x63, 0x55, 0x4f, 0x1c, 0xf7, 0x4f, 0x7c, 0x85, + 0x2f, 0x92, 0x30, 0x37, 0xf3, 0xf9, 0x27, 0x09, 0x8f, 0x2a, 0xc3, 0xee, + 0xfe, 0xc8, 0x66, 0xc7, 0x68, 0xeb, 0x1f, 0x7b, 0xe9, 0xcd, 0x8a, 0x4a, + 0x94, 0xc6, 0xf1, 0x5e, 0xb8, 0x7a, 0xb7, 0xa3, 0x61, 0x51, 0xf7, 0xd9, + 0x22, 0x27, 0x68, 0xe8, 0x12, 0x45, 0x84, 0x73, 0x15, 0x90, 0xe9, 0xaf, + 0x5d, 0x01, 0xff, 0x76, 0x30, 0x55, 0xdb, 0x97, 0xeb, 0x06, 0x63, 0x71, + 0x47, 0x79, 0xb3, 0xc0, 0xdb, 0x79, 0xc0, 0xb6, 0xe2, 0xe4, 0x3b, 0x4e, + 0x3f, 0xa4, 0xb9, 0xdd, 0xbe, 0xe1, 0x10, 0xe9 +}; +static const uint8_t nist_186_2_ecdsa_testvector_222_private[] = { +/* d - byte alignment */ + 0x01, 0x13, 0x5a, 0xfa, 0xea, 0x83, 0x71, 0x7f, 0x9c, 0xd4, 0xe8, 0xc0, + 0xb2, 0x3b, 0xd9, 0x12, 0x84, 0xc4, 0x06, 0xf2, 0x23, 0x3e, 0x05, 0x00, + 0xca, 0x18, 0xec, 0xe6, 0x24, 0x18, 0x47, 0x55, 0xfc, 0xe5, 0x69, 0xb5, + 0xf3, 0x62, 0x11, 0x5b, 0xd9, 0x2f, 0xf5, 0xc5, 0xa9, 0x27, 0x74, 0x42, + 0x14, 0x96, 0x6a, 0xfe, 0x28, 0x1a, 0x7c, 0xcb, 0x3e, 0x56, 0x6e, 0x87, + 0xc3, 0x53, 0x1f, 0x85, 0xac, 0x7f, 0xda, 0xcc, 0x75, 0xcd, 0x13, 0x59 +}; +static const uint8_t nist_186_2_ecdsa_testvector_222_public_x[] = { +/* Qx - byte alignment */ + 0x02, 0x1a, 0x07, 0xd9, 0x09, 0x01, 0x29, 0x30, 0xc0, 0x49, 0x76, 0xa1, + 0xae, 0x44, 0x1b, 0x1f, 0x99, 0x9f, 0x9f, 0x9d, 0x64, 0xd7, 0xcd, 0x0e, + 0xd8, 0xdc, 0x1a, 0xd3, 0x3f, 0x78, 0x51, 0x8d, 0x7c, 0xa7, 0x77, 0x3b, + 0x65, 0x23, 0x4a, 0xd8, 0xfe, 0x45, 0x44, 0xf6, 0xbe, 0xdd, 0x07, 0x12, + 0x30, 0xbb, 0x00, 0x70, 0x1d, 0xfa, 0x9b, 0xea, 0xca, 0x6e, 0x47, 0x40, + 0x80, 0x06, 0x0c, 0xb7, 0xfc, 0xb4, 0x87, 0xd3, 0x55, 0x15, 0x66, 0xe5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_222_public_y[] = { +/* Qy - byte alignment */ + 0x07, 0xe4, 0xa9, 0x1b, 0x8d, 0xc9, 0x5b, 0x8b, 0x7a, 0x17, 0x7d, 0x6b, + 0x18, 0x34, 0xa0, 0xa2, 0x34, 0x6a, 0x62, 0xd3, 0xe2, 0x66, 0xb7, 0x3a, + 0x29, 0x73, 0x25, 0xeb, 0xcf, 0xcc, 0x9a, 0x33, 0xe0, 0x7c, 0x4d, 0x3e, + 0x27, 0x79, 0xd3, 0x64, 0x7e, 0x8d, 0x51, 0xac, 0x4e, 0x55, 0x44, 0x7d, + 0xff, 0x5a, 0xc2, 0x39, 0x87, 0x86, 0x33, 0x8a, 0xc1, 0x55, 0x94, 0x42, + 0xac, 0xcc, 0x8f, 0x52, 0x75, 0x9e, 0x4f, 0xe9, 0x9e, 0x37, 0x94, 0x8b +}; +/* k = 041b977a3a59f4faf5d2dfd47d3a1a58c39c615e0c366b3f81c775bd360a05721fdaea34078de53f22cc082bd48f341bc658c458424c3fbbc8f4c472818a37f79838db8ca8e687c */ +static const uint8_t nist_186_2_ecdsa_testvector_222_out[] = { +/* R - byte alignment */ + 0x01, 0x2c, 0x92, 0x87, 0x46, 0xf5, 0x16, 0x9d, 0x2d, 0x3d, 0x4b, 0xc0, + 0xad, 0x5c, 0x00, 0x15, 0xd1, 0x3e, 0xd3, 0x9e, 0xf0, 0xe1, 0xd5, 0xa4, + 0x5d, 0x64, 0x60, 0xc7, 0xa0, 0x2f, 0xdb, 0xd0, 0x28, 0x97, 0x61, 0x62, + 0x24, 0xfa, 0x94, 0x94, 0xd2, 0x2f, 0xfd, 0xde, 0x6b, 0x7a, 0xf6, 0x6a, + 0xfe, 0xc2, 0x16, 0x65, 0x53, 0x89, 0x27, 0x54, 0x8c, 0x3f, 0x5a, 0x42, + 0xc9, 0x13, 0x52, 0x5e, 0x7e, 0x95, 0x68, 0xbd, 0x10, 0xf2, 0x8a, 0x52, +/* S - byte alignment */ + 0x01, 0x9b, 0x1b, 0x02, 0xb2, 0x32, 0x02, 0x62, 0x1f, 0x1a, 0x9a, 0x5b, + 0x10, 0x50, 0x50, 0x07, 0x6f, 0x9f, 0x97, 0x7b, 0x2b, 0xc9, 0x23, 0x94, + 0xe9, 0x55, 0xa2, 0x98, 0x5b, 0x33, 0x6a, 0x96, 0xbc, 0x4f, 0xbf, 0xd7, + 0xf0, 0xc4, 0xc7, 0x68, 0x64, 0xbf, 0x4e, 0x8c, 0x5a, 0x44, 0x7f, 0x30, + 0x58, 0x69, 0x8e, 0xef, 0x6a, 0x27, 0xfd, 0xa1, 0x64, 0x23, 0xcb, 0xbe, + 0x9f, 0x53, 0xe1, 0x35, 0x97, 0x67, 0x2c, 0x30, 0xf3, 0x97, 0xb5, 0x9b +}; +static const uint8_t nist_186_2_ecdsa_testvector_223_ptx[] = { +/* Msg */ + 0xdd, 0x4f, 0x69, 0xfb, 0x13, 0x11, 0x36, 0x99, 0x6b, 0xb2, 0x99, 0xe0, + 0x82, 0xec, 0xb1, 0x88, 0xfe, 0x59, 0xff, 0x19, 0x17, 0xe6, 0x0f, 0x01, + 0x57, 0x86, 0x5b, 0xe4, 0x9d, 0x23, 0x6c, 0x33, 0x68, 0xda, 0x42, 0x00, + 0x52, 0x67, 0xf6, 0x11, 0xdb, 0xde, 0x9e, 0x33, 0x68, 0x9d, 0x71, 0xd0, + 0x8c, 0x7e, 0x2c, 0xc4, 0x85, 0x51, 0xb4, 0x6d, 0x0a, 0x89, 0xfc, 0x01, + 0x44, 0x35, 0x29, 0x25, 0x1a, 0x32, 0xf4, 0xbb, 0xb1, 0x9f, 0x50, 0xfb, + 0x33, 0x92, 0x4d, 0xc5, 0xd0, 0x09, 0x3d, 0x35, 0x03, 0x24, 0x15, 0x79, + 0x17, 0x91, 0x16, 0xdf, 0xe9, 0x47, 0xac, 0x32, 0xef, 0x77, 0x96, 0x47, + 0x79, 0xbf, 0x47, 0xd3, 0x37, 0xa2, 0x8c, 0x7f, 0xfc, 0x35, 0x70, 0x3f, + 0xc1, 0x1a, 0x5d, 0xdf, 0xed, 0xb2, 0x83, 0xdf, 0xd4, 0x8f, 0x7d, 0x80, + 0x7d, 0x28, 0x32, 0x1f, 0xa8, 0xd1, 0xfa, 0xc2 +}; +static const uint8_t nist_186_2_ecdsa_testvector_223_private[] = { +/* d - byte alignment */ + 0x01, 0x15, 0xe7, 0x47, 0xfb, 0xc4, 0x5a, 0xd1, 0x10, 0x2b, 0x61, 0x1b, + 0x57, 0x5e, 0xf3, 0x9c, 0x6c, 0x47, 0xd3, 0xb7, 0x70, 0x79, 0x60, 0x75, + 0xfa, 0xc4, 0x4b, 0xa5, 0x7f, 0x94, 0x80, 0xed, 0xc6, 0xb6, 0xe0, 0x9d, + 0xbe, 0xe1, 0x08, 0x57, 0x66, 0xb9, 0x7c, 0x8e, 0x08, 0x63, 0xff, 0xd7, + 0x5e, 0x18, 0x1f, 0x13, 0x8d, 0x80, 0x0f, 0x58, 0x50, 0x77, 0xf9, 0xd7, + 0x38, 0x23, 0xaa, 0x0d, 0x25, 0xd4, 0xed, 0xb6, 0x46, 0xda, 0x54, 0xeb +}; +static const uint8_t nist_186_2_ecdsa_testvector_223_public_x[] = { +/* Qx - byte alignment */ + 0x04, 0x94, 0xf3, 0x8a, 0xd1, 0x02, 0x0f, 0x0c, 0x66, 0xe1, 0xb7, 0xbe, + 0x27, 0x6e, 0x67, 0x84, 0x56, 0xa8, 0x6f, 0x5a, 0x14, 0x43, 0x60, 0x8c, + 0x34, 0x32, 0xa1, 0xe4, 0xef, 0xe1, 0xed, 0x9c, 0xc3, 0x27, 0x16, 0xbd, + 0x65, 0xee, 0x78, 0x66, 0xa6, 0x38, 0x66, 0x7f, 0x70, 0x70, 0x30, 0x64, + 0x28, 0x84, 0x9d, 0x5c, 0x66, 0xb5, 0x43, 0xa4, 0xe7, 0x59, 0x21, 0xc3, + 0x63, 0x76, 0xef, 0x91, 0xbe, 0xdf, 0xee, 0x36, 0xf8, 0xfe, 0x5b, 0xb5 +}; +static const uint8_t nist_186_2_ecdsa_testvector_223_public_y[] = { +/* Qy - byte alignment */ + 0x03, 0xd1, 0xc4, 0xe1, 0xcc, 0xa6, 0x10, 0xb1, 0x8f, 0x1f, 0x8a, 0x8c, + 0x80, 0x27, 0x09, 0x77, 0x29, 0x14, 0x71, 0xaf, 0x9d, 0xff, 0xe5, 0xa3, + 0x92, 0xf6, 0x92, 0x97, 0x94, 0x08, 0xc7, 0x3e, 0xb5, 0x38, 0x11, 0x4f, + 0x3e, 0x3e, 0xfe, 0x16, 0xeb, 0xac, 0x44, 0x08, 0x4c, 0xb4, 0x03, 0xe7, + 0x0e, 0xf1, 0xc7, 0x9f, 0xb7, 0xa0, 0x45, 0xc0, 0x9f, 0x82, 0x01, 0x19, + 0xf6, 0x2f, 0x7c, 0x6e, 0xf7, 0xd1, 0x9b, 0x29, 0xe5, 0xe2, 0xce, 0xd5 +}; +/* k = 28228918e93708cfe1c8c283f368696f93e618a85d544aa87e9e1181dcc2017a747058ed6db1deda0a51e4754d53a7823c894981fc691e8f5d9d27d88acaba16b2b973733f24f13 */ +static const uint8_t nist_186_2_ecdsa_testvector_223_out[] = { +/* R - byte alignment */ + 0x00, 0x3e, 0xd5, 0xa1, 0x7a, 0x6b, 0x70, 0xa1, 0x01, 0xe9, 0xb9, 0x10, + 0xbf, 0x1a, 0xc4, 0x2b, 0xc2, 0xce, 0x81, 0x75, 0xb5, 0x8a, 0x9b, 0x3f, + 0xb7, 0x96, 0xe8, 0x09, 0xf8, 0x33, 0x14, 0x1d, 0x75, 0x07, 0x0d, 0xee, + 0x73, 0xc7, 0x06, 0x1e, 0xa7, 0xee, 0x1a, 0x72, 0x7a, 0xbd, 0x76, 0x25, + 0x96, 0x23, 0x36, 0x1a, 0xf4, 0xe0, 0xe7, 0xdb, 0x7c, 0x7f, 0x44, 0x09, + 0x6b, 0x3a, 0x88, 0xe4, 0x21, 0x04, 0x0b, 0x48, 0xb9, 0xe7, 0x11, 0xc7, +/* S - byte alignment */ + 0x02, 0x70, 0x89, 0x2e, 0x50, 0x23, 0x71, 0x55, 0x46, 0x57, 0x27, 0xee, + 0xf7, 0xb1, 0x5e, 0x97, 0x01, 0xa0, 0xf8, 0x6a, 0x1b, 0x79, 0xe9, 0x3e, + 0x47, 0x4a, 0xf1, 0xb9, 0x57, 0xb9, 0xbf, 0xf5, 0x0f, 0x81, 0x8b, 0x6e, + 0x71, 0x8e, 0x07, 0xc0, 0x1a, 0x69, 0x07, 0xc8, 0x99, 0x4c, 0x26, 0x9a, + 0xc6, 0x23, 0x26, 0xd2, 0xa6, 0x40, 0x7b, 0xb3, 0x07, 0x9e, 0x19, 0x54, + 0xd9, 0x7d, 0x2a, 0x79, 0xbb, 0x6e, 0x10, 0x6d, 0x3f, 0x2a, 0xdf, 0x9a +}; +static const uint8_t nist_186_2_ecdsa_testvector_224_ptx[] = { +/* Msg */ + 0xe1, 0xd2, 0x4f, 0x97, 0x74, 0xec, 0xca, 0x0d, 0x9e, 0x0d, 0xc9, 0x2c, + 0x2d, 0xdf, 0x1f, 0x0c, 0x29, 0x53, 0xc5, 0x4f, 0xff, 0x38, 0x22, 0x54, + 0xde, 0x0d, 0x89, 0xad, 0x62, 0x13, 0x04, 0xd4, 0x70, 0xa7, 0x50, 0x19, + 0x61, 0xcf, 0x28, 0xdf, 0x62, 0x13, 0xc7, 0x08, 0x1a, 0x8e, 0xa8, 0xae, + 0x8e, 0x44, 0x90, 0x14, 0x42, 0xb6, 0xce, 0xdc, 0xa1, 0xb4, 0xc1, 0x7a, + 0x9f, 0x73, 0x9c, 0xe8, 0x9d, 0xdf, 0x66, 0x9b, 0x8d, 0x32, 0x45, 0xb7, + 0x56, 0xc6, 0xfb, 0x7f, 0x7a, 0x27, 0xb1, 0x0f, 0xf6, 0x6d, 0xf4, 0x4d, + 0x6a, 0xc9, 0xfd, 0x1d, 0x79, 0x5d, 0x35, 0xd4, 0x73, 0x51, 0xf8, 0xf0, + 0x31, 0x23, 0x99, 0x06, 0x41, 0x3e, 0xa7, 0xfb, 0x44, 0xcf, 0x6f, 0x77, + 0x93, 0xd4, 0xc2, 0x97, 0x29, 0x75, 0xf9, 0xe2, 0xbd, 0x98, 0x35, 0x7f, + 0x2e, 0xb0, 0xec, 0xa5, 0x24, 0xd5, 0xa1, 0x52 +}; +static const uint8_t nist_186_2_ecdsa_testvector_224_private[] = { +/* d - byte alignment */ + 0x03, 0x1a, 0xa2, 0x47, 0xb6, 0x9d, 0x1b, 0x0f, 0xa8, 0xef, 0x8c, 0x2e, + 0x47, 0xa7, 0xb6, 0xc6, 0xf2, 0x59, 0x26, 0xdc, 0xa4, 0x2e, 0xab, 0x73, + 0x07, 0x85, 0x04, 0x6c, 0x12, 0x42, 0x57, 0x74, 0xa3, 0x60, 0x02, 0x73, + 0xfe, 0x41, 0x08, 0x35, 0xbc, 0x0c, 0xdd, 0x20, 0xd1, 0x0c, 0x21, 0xc4, + 0x0a, 0x07, 0xd8, 0x56, 0x7f, 0xb4, 0x98, 0x70, 0x93, 0x15, 0x47, 0xb2, + 0x2e, 0x60, 0xa6, 0xea, 0xdb, 0x2e, 0x26, 0x24, 0x7b, 0x10, 0x82, 0x57 +}; +static const uint8_t nist_186_2_ecdsa_testvector_224_public_x[] = { +/* Qx - byte alignment */ + 0x00, 0x98, 0x10, 0xb1, 0xdf, 0x87, 0x95, 0xcf, 0x27, 0x93, 0x86, 0xfb, + 0x65, 0xce, 0xe6, 0x9b, 0x89, 0xe0, 0xb6, 0xb3, 0x53, 0x97, 0x42, 0x04, + 0xbf, 0xa1, 0xc7, 0xb0, 0xd8, 0xd4, 0x22, 0x8c, 0x7e, 0x9a, 0xbc, 0x46, + 0xdc, 0xbb, 0x8c, 0xff, 0xc6, 0x24, 0x41, 0x5f, 0x57, 0xbf, 0xad, 0x60, + 0xe1, 0x7c, 0x8b, 0x36, 0xb1, 0x13, 0xb1, 0xb9, 0xbb, 0x03, 0x21, 0xe0, + 0xd0, 0x77, 0xdf, 0x7a, 0x1c, 0xdf, 0x82, 0xe1, 0x09, 0xbd, 0xae, 0x7f +}; +static const uint8_t nist_186_2_ecdsa_testvector_224_public_y[] = { +/* Qy - byte alignment */ + 0x04, 0x16, 0xbe, 0x11, 0x79, 0x44, 0x68, 0xa2, 0x7a, 0xb6, 0xf4, 0x4a, + 0x54, 0xfb, 0x27, 0x38, 0x15, 0x08, 0x4d, 0xb4, 0xf0, 0xb7, 0x93, 0xb5, + 0x73, 0x1e, 0xad, 0x8e, 0x9d, 0xff, 0xe2, 0xec, 0x6d, 0x19, 0x9d, 0xe1, + 0x06, 0xeb, 0xca, 0xba, 0xed, 0x14, 0x7e, 0xd1, 0x79, 0x3b, 0xde, 0xb0, + 0xc0, 0xbf, 0x1f, 0x40, 0x81, 0xe5, 0xe8, 0xc7, 0x2b, 0xd3, 0x29, 0x15, + 0xd0, 0xb0, 0xb4, 0xb1, 0x8e, 0x16, 0xaa, 0xb4, 0x51, 0x32, 0xaf, 0x6f +}; +/* k = 16804100a6aa43fac2c18325b07acf9782fa957ead28e30bfb991f5c1526f1b8c6a82c9e5ffc4fdf7981fa12f961bdac94f9f6a441760cd9cc391ac43956ce32719a96a11f4e792 */ +static const uint8_t nist_186_2_ecdsa_testvector_224_out[] = { +/* R - byte alignment */ + 0x00, 0xd3, 0x01, 0xbe, 0x45, 0x90, 0xf7, 0x54, 0xbb, 0x46, 0x82, 0x3e, + 0x7b, 0x9f, 0x67, 0x71, 0x18, 0x6f, 0x77, 0xb6, 0xf4, 0xa4, 0x7f, 0x6b, + 0x4b, 0xd7, 0x74, 0xc4, 0xea, 0xcd, 0x2d, 0x9b, 0x3d, 0x3c, 0x5f, 0x9e, + 0xa3, 0xc9, 0x41, 0x66, 0x6f, 0x94, 0x62, 0xc7, 0x52, 0x49, 0xbc, 0x50, + 0xb4, 0x24, 0x93, 0x70, 0xf6, 0xbb, 0xc0, 0x9f, 0x98, 0x35, 0xdb, 0xbc, + 0xe1, 0x0f, 0x1a, 0x00, 0x10, 0x80, 0xc3, 0x31, 0x1d, 0x3d, 0x08, 0xd9, +/* S - byte alignment */ + 0x01, 0x67, 0x07, 0x61, 0x30, 0x2b, 0x30, 0xc3, 0xba, 0x1d, 0xe4, 0x5b, + 0x44, 0x2a, 0xbb, 0xe6, 0x36, 0xeb, 0x8c, 0x47, 0xf6, 0x6f, 0x77, 0x83, + 0x36, 0x32, 0x80, 0x11, 0x3d, 0xa8, 0xdc, 0x47, 0x09, 0x74, 0x15, 0x8f, + 0xcd, 0x0d, 0x27, 0xb7, 0x09, 0xce, 0xa7, 0xae, 0x31, 0xa1, 0x27, 0x63, + 0xf4, 0x5d, 0xde, 0x13, 0x47, 0xb6, 0x63, 0xc8, 0x80, 0x55, 0xa0, 0xaf, + 0xf0, 0xbd, 0xc9, 0xc3, 0xfd, 0x73, 0x0c, 0x3b, 0xbb, 0xe9, 0x84, 0xcb +}; +static const uint8_t nist_186_2_ecdsa_testvector_225_ptx[] = { +/* Msg */ + 0xa9, 0xe2, 0xa7, 0xba, 0x51, 0x4d, 0x81, 0x18, 0xab, 0x1d, 0xb6, 0xcc, + 0xd7, 0x06, 0xf9, 0x4d, 0xbb, 0x61, 0x0e, 0xda, 0xee, 0x7f, 0xd4, 0x6b, + 0xd4, 0x3d, 0x82, 0xe7, 0x0b, 0xd8, 0x31, 0x97, 0x06, 0x03, 0x9b, 0xdb, + 0xf8, 0x37, 0x22, 0x1b, 0xf4, 0x4b, 0x14, 0x01, 0x52, 0x44, 0x2d, 0xe5, + 0x54, 0x6e, 0x5d, 0x89, 0x0a, 0xac, 0xcc, 0x07, 0x72, 0x0c, 0x1c, 0x07, + 0xe4, 0x9e, 0xee, 0x35, 0xad, 0x87, 0xa7, 0xf3, 0xfb, 0x51, 0x74, 0x4a, + 0xf9, 0x85, 0x8b, 0x27, 0x3a, 0x7c, 0xb4, 0xc4, 0x5b, 0x72, 0x08, 0x64, + 0xe4, 0xdc, 0xf9, 0x43, 0x70, 0xfb, 0x93, 0xcd, 0x0e, 0xb2, 0x02, 0x0e, + 0xe6, 0x95, 0x53, 0x6a, 0x20, 0x42, 0x7f, 0x8e, 0x01, 0xf4, 0xa5, 0xa6, + 0x57, 0x55, 0x97, 0xd0, 0x18, 0x94, 0x98, 0xd1, 0x46, 0xb8, 0x64, 0x08, + 0x15, 0x34, 0x71, 0xa0, 0x50, 0xbb, 0x75, 0x09 +}; +static const uint8_t nist_186_2_ecdsa_testvector_225_private[] = { +/* d - byte alignment */ + 0x01, 0x62, 0x40, 0xcb, 0xf2, 0x1f, 0x7c, 0x2e, 0x8f, 0x74, 0xd1, 0xda, + 0x2e, 0xc4, 0xb0, 0xa5, 0xec, 0xe0, 0x6d, 0x00, 0x23, 0x85, 0x2c, 0xf3, + 0xae, 0x09, 0x49, 0xc6, 0xac, 0xb4, 0x4b, 0xc4, 0x88, 0x1d, 0x1a, 0x13, + 0x66, 0x12, 0xfd, 0xf2, 0x7a, 0x26, 0xfe, 0x59, 0x4e, 0xee, 0xa7, 0x00, + 0xe6, 0x31, 0x16, 0x4f, 0x21, 0x34, 0x30, 0xff, 0xab, 0x45, 0x61, 0x17, + 0x91, 0xa6, 0x41, 0xd5, 0x69, 0x88, 0x18, 0x27, 0x2c, 0x8b, 0xb4, 0xff +}; +static const uint8_t nist_186_2_ecdsa_testvector_225_public_x[] = { +/* Qx - byte alignment */ + 0x01, 0x16, 0xce, 0xd6, 0xa8, 0x20, 0x56, 0xa3, 0x69, 0x27, 0x56, 0x81, + 0x72, 0x10, 0x88, 0xef, 0x79, 0x4c, 0xff, 0xe7, 0x1b, 0x61, 0xd4, 0x0d, + 0x54, 0x4e, 0xf7, 0x41, 0x5a, 0xfb, 0x8e, 0x97, 0xd2, 0xc9, 0x1e, 0xf0, + 0x13, 0xc2, 0x07, 0xeb, 0x43, 0x45, 0xdb, 0xec, 0x26, 0x0c, 0xff, 0x31, + 0x5f, 0x2e, 0x93, 0xfb, 0xe4, 0x92, 0x67, 0x18, 0x13, 0x9a, 0x6d, 0xf6, + 0x5b, 0xa7, 0x07, 0xe4, 0xca, 0xa9, 0x23, 0x6a, 0xce, 0x08, 0x23, 0xa0 +}; +static const uint8_t nist_186_2_ecdsa_testvector_225_public_y[] = { +/* Qy - byte alignment */ + 0x00, 0x02, 0x29, 0xa0, 0xe0, 0x2c, 0xcf, 0x8c, 0x4d, 0x52, 0xce, 0xba, + 0xff, 0x42, 0xa0, 0x0e, 0x13, 0x43, 0xb8, 0xdb, 0xfd, 0x79, 0x5d, 0xa4, + 0x2e, 0x21, 0x3a, 0xf4, 0xdd, 0x24, 0x90, 0x49, 0x73, 0x36, 0x01, 0xad, + 0xfb, 0x0b, 0x3e, 0x98, 0x23, 0xf0, 0xf0, 0x3f, 0xcc, 0xb2, 0x21, 0xd1, + 0x8d, 0x31, 0x48, 0x94, 0xb8, 0xba, 0xf3, 0x80, 0x14, 0xa1, 0x2d, 0x0c, + 0x8c, 0xd0, 0xaf, 0xf7, 0x57, 0x2c, 0x1c, 0x0b, 0x63, 0xbd, 0x6d, 0x55 +}; +/* k = 0d4e667480b9abef5c841ff725972b8f8543bdb689b28a0ab7c21105dee935dce3fde34bcefa7da3e44e9915ce1788b2ff421abbd36bd336c3f9e66c57b499e97ce93d5bc657472 */ +static const uint8_t nist_186_2_ecdsa_testvector_225_out[] = { +/* R - byte alignment */ + 0x01, 0x70, 0x20, 0xca, 0x84, 0xab, 0x6e, 0x1d, 0xf5, 0xd8, 0x44, 0xb5, + 0x5d, 0xac, 0xe5, 0x40, 0x88, 0xa2, 0x69, 0x5d, 0xa7, 0x60, 0x40, 0x87, + 0x85, 0x55, 0xc9, 0xb2, 0xd1, 0x2d, 0x8c, 0x2c, 0x3d, 0x32, 0x0d, 0x7d, + 0x8d, 0xd6, 0x22, 0x10, 0xde, 0x5d, 0x3a, 0xb7, 0x0b, 0x58, 0xbd, 0x86, + 0xa9, 0x56, 0x59, 0x9c, 0x69, 0x92, 0xde, 0x0d, 0x16, 0xe6, 0xe9, 0x7c, + 0x62, 0x76, 0xe4, 0xa1, 0xce, 0x77, 0x35, 0x9d, 0x35, 0x03, 0xb3, 0xba, +/* S - byte alignment */ + 0x02, 0xf7, 0x8c, 0x46, 0xc3, 0xe5, 0x84, 0xd6, 0x16, 0x9a, 0x85, 0x61, + 0xf4, 0x88, 0xa3, 0xc0, 0xfd, 0x9f, 0xe8, 0x6d, 0xdd, 0x77, 0x49, 0x62, + 0x6c, 0xb1, 0xea, 0x30, 0xfa, 0xe0, 0x9b, 0x3c, 0x18, 0x03, 0xf1, 0x4a, + 0x80, 0xa7, 0xde, 0x23, 0xe9, 0xe3, 0xaa, 0x44, 0x7b, 0x5b, 0x20, 0x3a, + 0x53, 0x01, 0xcf, 0x70, 0x37, 0x5e, 0xcf, 0x9d, 0xe3, 0x83, 0x8f, 0xd3, + 0x8c, 0x75, 0xed, 0xd6, 0x64, 0x32, 0x53, 0xe6, 0x0d, 0x8a, 0xd7, 0xc1 +}; diff --git a/optee/optee_test/host/xtest/nist/186-3dsatestvectors.h b/optee/optee_test/host/xtest/nist/186-3dsatestvectors.h new file mode 100644 index 0000000..6609217 --- /dev/null +++ b/optee/optee_test/host/xtest/nist/186-3dsatestvectors.h @@ -0,0 +1,18471 @@ +/* + * DSA Test data automatically generated from + * from http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3dsatestvectors.zip + * SigGen.txt + */ + +/* [mod = L=1024, N=160, SHA-1] */ +static const uint8_t ac_dsa_vect1_prime[] = { +/* P */ + 0xa8, 0xf9, 0xcd, 0x20, 0x1e, 0x5e, 0x35, 0xd8, 0x92, 0xf8, 0x5f, 0x80, + 0xe4, 0xdb, 0x25, 0x99, 0xa5, 0x67, 0x6a, 0x3b, 0x1d, 0x4f, 0x19, 0x03, + 0x30, 0xed, 0x32, 0x56, 0xb2, 0x6d, 0x0e, 0x80, 0xa0, 0xe4, 0x9a, 0x8f, + 0xff, 0xaa, 0xad, 0x2a, 0x24, 0xf4, 0x72, 0xd2, 0x57, 0x32, 0x41, 0xd4, + 0xd6, 0xd6, 0xc7, 0x48, 0x0c, 0x80, 0xb4, 0xc6, 0x7b, 0xb4, 0x47, 0x9c, + 0x15, 0xad, 0xa7, 0xea, 0x84, 0x24, 0xd2, 0x50, 0x2f, 0xa0, 0x14, 0x72, + 0xe7, 0x60, 0x24, 0x17, 0x13, 0xda, 0xb0, 0x25, 0xae, 0x1b, 0x02, 0xe1, + 0x70, 0x3a, 0x14, 0x35, 0xf6, 0x2d, 0xdf, 0x4e, 0xe4, 0xc1, 0xb6, 0x64, + 0x06, 0x6e, 0xb2, 0x2f, 0x2e, 0x3b, 0xf2, 0x8b, 0xb7, 0x0a, 0x2a, 0x76, + 0xe4, 0xfd, 0x5e, 0xbe, 0x2d, 0x12, 0x29, 0x68, 0x1b, 0x5b, 0x06, 0x43, + 0x9a, 0xc9, 0xc7, 0xe9, 0xd8, 0xbd, 0xe2, 0x83 +}; +static const uint8_t ac_dsa_vect1_sub_prime[] = { +/* Q */ + 0xf8, 0x5f, 0x0f, 0x83, 0xac, 0x4d, 0xf7, 0xea, 0x0c, 0xdf, 0x8f, 0x46, + 0x9b, 0xfe, 0xea, 0xea, 0x14, 0x15, 0x64, 0x95 +}; +static const uint8_t ac_dsa_vect1_base[] = { +/* G */ + 0x2b, 0x31, 0x52, 0xff, 0x6c, 0x62, 0xf1, 0x46, 0x22, 0xb8, 0xf4, 0x8e, + 0x59, 0xf8, 0xaf, 0x46, 0x88, 0x3b, 0x38, 0xe7, 0x9b, 0x8c, 0x74, 0xde, + 0xea, 0xe9, 0xdf, 0x13, 0x1f, 0x8b, 0x85, 0x6e, 0x3a, 0xd6, 0xc8, 0x45, + 0x5d, 0xab, 0x87, 0xcc, 0x0d, 0xa8, 0xac, 0x97, 0x34, 0x17, 0xce, 0x4f, + 0x78, 0x78, 0x55, 0x7d, 0x6c, 0xdf, 0x40, 0xb3, 0x5b, 0x4a, 0x0c, 0xa3, + 0xeb, 0x31, 0x0c, 0x6a, 0x95, 0xd6, 0x8c, 0xe2, 0x84, 0xad, 0x4e, 0x25, + 0xea, 0x28, 0x59, 0x16, 0x11, 0xee, 0x08, 0xb8, 0x44, 0x4b, 0xd6, 0x4b, + 0x25, 0xf3, 0xf7, 0xc5, 0x72, 0x41, 0x0d, 0xdf, 0xb3, 0x9c, 0xc7, 0x28, + 0xb9, 0xc9, 0x36, 0xf8, 0x5f, 0x41, 0x91, 0x29, 0x86, 0x99, 0x29, 0xcd, + 0xb9, 0x09, 0xa6, 0xa3, 0xa9, 0x9b, 0xbe, 0x08, 0x92, 0x16, 0x36, 0x81, + 0x71, 0xbd, 0x0b, 0xa8, 0x1d, 0xe4, 0xfe, 0x33 +}; +static const uint8_t ac_dsa_vect1_ptx[] = { +/* Msg */ + 0x3b, 0x46, 0x73, 0x6d, 0x55, 0x9b, 0xd4, 0xe0, 0xc2, 0xc1, 0xb2, 0x55, + 0x3a, 0x33, 0xad, 0x3c, 0x6c, 0xf2, 0x3c, 0xac, 0x99, 0x8d, 0x3d, 0x0c, + 0x0e, 0x8f, 0xa4, 0xb1, 0x9b, 0xca, 0x06, 0xf2, 0xf3, 0x86, 0xdb, 0x2d, + 0xcf, 0xf9, 0xdc, 0xa4, 0xf4, 0x0a, 0xd8, 0xf5, 0x61, 0xff, 0xc3, 0x08, + 0xb4, 0x6c, 0x5f, 0x31, 0xa7, 0x73, 0x5b, 0x5f, 0xa7, 0xe0, 0xf9, 0xe6, + 0xcb, 0x51, 0x2e, 0x63, 0xd7, 0xee, 0xa0, 0x55, 0x38, 0xd6, 0x6a, 0x75, + 0xcd, 0x0d, 0x42, 0x34, 0xb5, 0xcc, 0xf6, 0xc1, 0x71, 0x5c, 0xca, 0xaf, + 0x9c, 0xdc, 0x0a, 0x22, 0x28, 0x13, 0x5f, 0x71, 0x6e, 0xe9, 0xbd, 0xee, + 0x7f, 0xc1, 0x3e, 0xc2, 0x7a, 0x03, 0xa6, 0xd1, 0x1c, 0x5c, 0x5b, 0x36, + 0x85, 0xf5, 0x19, 0x00, 0xb1, 0x33, 0x71, 0x53, 0xbc, 0x6c, 0x4e, 0x8f, + 0x52, 0x92, 0x0c, 0x33, 0xfa, 0x37, 0xf4, 0xe7 +}; +static const uint8_t ac_dsa_vect1_priv_val[] = { +/* X */ + 0xc5, 0x3e, 0xae, 0x6d, 0x45, 0x32, 0x31, 0x64, 0xc7, 0xd0, 0x7a, 0xf5, + 0x71, 0x57, 0x03, 0x74, 0x4a, 0x63, 0xfc, 0x3a +}; +static const uint8_t ac_dsa_vect1_pub_val[] = { +/* Y */ + 0x31, 0x3f, 0xd9, 0xeb, 0xca, 0x91, 0x57, 0x4e, 0x1c, 0x2e, 0xeb, 0xe1, + 0x51, 0x7c, 0x57, 0xe0, 0xc2, 0x1b, 0x02, 0x09, 0x87, 0x21, 0x40, 0xc5, + 0x32, 0x87, 0x61, 0xbb, 0xb2, 0x45, 0x0b, 0x33, 0xf1, 0xb1, 0x8b, 0x40, + 0x9c, 0xe9, 0xab, 0x7c, 0x4c, 0xd8, 0xfd, 0xa3, 0x39, 0x1e, 0x8e, 0x34, + 0x86, 0x83, 0x57, 0xc1, 0x99, 0xe1, 0x6a, 0x6b, 0x2e, 0xba, 0x06, 0xd6, + 0x74, 0x9d, 0xef, 0x79, 0x1d, 0x79, 0xe9, 0x5d, 0x3a, 0x4d, 0x09, 0xb2, + 0x4c, 0x39, 0x2a, 0xd8, 0x9d, 0xbf, 0x10, 0x09, 0x95, 0xae, 0x19, 0xc0, + 0x10, 0x62, 0x05, 0x6b, 0xb1, 0x4b, 0xce, 0x00, 0x5e, 0x87, 0x31, 0xef, + 0xde, 0x17, 0x5f, 0x95, 0xb9, 0x75, 0x08, 0x9b, 0xdc, 0xda, 0xea, 0x56, + 0x2b, 0x32, 0x78, 0x6d, 0x96, 0xf5, 0xa3, 0x1a, 0xed, 0xf7, 0x53, 0x64, + 0x00, 0x8a, 0xd4, 0xff, 0xfe, 0xbb, 0x97, 0x0b +}; +/* K = 98cbcc4969d845e2461b5f66383dd503712bbcfa */ +static const uint8_t ac_dsa_vect1_out[] = { +/* R */ + 0x50, 0xed, 0x0e, 0x81, 0x0e, 0x3f, 0x1c, 0x7c, 0xb6, 0xac, 0x62, 0x33, + 0x20, 0x58, 0x44, 0x8b, 0xd8, 0xb2, 0x84, 0xc0, +/* S */ + 0xc6, 0xad, 0xed, 0x17, 0x21, 0x6b, 0x46, 0xb7, 0xe4, 0xb6, 0xf2, 0xa9, + 0x7c, 0x1a, 0xd7, 0xcc, 0x3d, 0xa8, 0x3f, 0xde +}; +#define ac_dsa_vect2_prime ac_dsa_vect1_prime +#define ac_dsa_vect2_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect2_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect2_ptx[] = { +/* Msg */ + 0xd2, 0xbc, 0xb5, 0x3b, 0x04, 0x4b, 0x3e, 0x2e, 0x4b, 0x61, 0xba, 0x2f, + 0x91, 0xc0, 0x99, 0x5f, 0xb8, 0x3a, 0x6a, 0x97, 0x52, 0x5e, 0x66, 0x44, + 0x1a, 0x3b, 0x48, 0x9d, 0x95, 0x94, 0x23, 0x8b, 0xc7, 0x40, 0xbd, 0xee, + 0xa0, 0xf7, 0x18, 0xa7, 0x69, 0xc9, 0x77, 0xe2, 0xde, 0x00, 0x38, 0x77, + 0xb5, 0xd7, 0xdc, 0x25, 0xb1, 0x82, 0xae, 0x53, 0x3d, 0xb3, 0x3e, 0x78, + 0xf2, 0xc3, 0xff, 0x06, 0x45, 0xf2, 0x13, 0x7a, 0xbc, 0x13, 0x7d, 0x4e, + 0x7d, 0x93, 0xcc, 0xf2, 0x4f, 0x60, 0xb1, 0x8a, 0x82, 0x0b, 0xc0, 0x7c, + 0x7b, 0x4b, 0x5f, 0xe0, 0x8b, 0x4f, 0x9e, 0x7d, 0x21, 0xb2, 0x56, 0xc1, + 0x8f, 0x3b, 0x9d, 0x49, 0xac, 0xc4, 0xf9, 0x3e, 0x2c, 0xe6, 0xf3, 0x75, + 0x4c, 0x78, 0x07, 0x75, 0x7d, 0x2e, 0x11, 0x76, 0x04, 0x26, 0x12, 0xcb, + 0x32, 0xfc, 0x3f, 0x4f, 0x70, 0x70, 0x0e, 0x25 +}; +static const uint8_t ac_dsa_vect2_priv_val[] = { +/* X */ + 0xe6, 0x51, 0x31, 0xd7, 0x34, 0x70, 0xf6, 0xad, 0x2e, 0x58, 0x78, 0xbd, + 0xc9, 0xbe, 0xf5, 0x36, 0xfa, 0xf7, 0x88, 0x31 +}; +static const uint8_t ac_dsa_vect2_pub_val[] = { +/* Y */ + 0x29, 0xbd, 0xd7, 0x59, 0xaa, 0xa6, 0x2d, 0x4b, 0xf1, 0x6b, 0x48, 0x61, + 0xc8, 0x1c, 0xf4, 0x2e, 0xac, 0x2e, 0x16, 0x37, 0xb9, 0xec, 0xba, 0x51, + 0x2b, 0xdb, 0xc1, 0x3a, 0xc1, 0x2a, 0x80, 0xae, 0x8d, 0xe2, 0x52, 0x6b, + 0x89, 0x9a, 0xe5, 0xe4, 0xa2, 0x31, 0xae, 0xf8, 0x84, 0x19, 0x7c, 0x94, + 0x4c, 0x73, 0x26, 0x93, 0xa6, 0x34, 0xd7, 0x65, 0x9a, 0xbc, 0x69, 0x75, + 0xa7, 0x73, 0xf8, 0xd3, 0xcd, 0x5a, 0x36, 0x1f, 0xe2, 0x49, 0x23, 0x86, + 0xa3, 0xc0, 0x9a, 0xae, 0xf1, 0x2e, 0x4a, 0x7e, 0x73, 0xad, 0x7d, 0xfc, + 0x36, 0x37, 0xf7, 0xb0, 0x93, 0xf2, 0xc4, 0x0d, 0x62, 0x23, 0xa1, 0x95, + 0xc1, 0x36, 0xad, 0xf2, 0xea, 0x3f, 0xbf, 0x87, 0x04, 0xa6, 0x75, 0xaa, + 0x78, 0x17, 0xaa, 0x7e, 0xc7, 0xf9, 0xad, 0xfb, 0x28, 0x54, 0xd4, 0xe0, + 0x5c, 0x3c, 0xe7, 0xf7, 0x65, 0x60, 0x31, 0x3b +}; +/* K = 87256a64e98cf5be1034ecfa766f9d25d1ac7ceb */ +static const uint8_t ac_dsa_vect2_out[] = { +/* R */ + 0xa2, 0x6c, 0x00, 0xb5, 0x75, 0x0a, 0x2d, 0x27, 0xfe, 0x74, 0x35, 0xb9, + 0x34, 0x76, 0xb3, 0x54, 0x38, 0xb4, 0xd8, 0xab, +/* S */ + 0x61, 0xc9, 0xbf, 0xcb, 0x29, 0x38, 0x75, 0x5a, 0xfa, 0x7d, 0xad, 0x1d, + 0x1e, 0x07, 0xc6, 0x28, 0x86, 0x17, 0xbf, 0x70 +}; +#define ac_dsa_vect3_prime ac_dsa_vect1_prime +#define ac_dsa_vect3_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect3_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect3_ptx[] = { +/* Msg */ + 0xd5, 0x43, 0x1e, 0x6b, 0x16, 0xfd, 0xae, 0x31, 0x48, 0x17, 0x42, 0xbd, + 0x39, 0x47, 0x58, 0xbe, 0xb8, 0xe2, 0x4f, 0x31, 0x94, 0x7e, 0x19, 0xb7, + 0xea, 0x7b, 0x45, 0x85, 0x21, 0x88, 0x22, 0x70, 0xc1, 0xf4, 0x31, 0x92, + 0xaa, 0x05, 0x0f, 0x44, 0x85, 0x14, 0x5a, 0xf8, 0xf3, 0xf9, 0xc5, 0x14, + 0x2d, 0x68, 0xb8, 0x50, 0x18, 0xd2, 0xec, 0x9c, 0xb7, 0xa3, 0x7b, 0xa1, + 0x2e, 0xd2, 0x3e, 0x73, 0xb9, 0x5f, 0xd6, 0x80, 0xfb, 0xa3, 0xc6, 0x12, + 0x65, 0xe9, 0xf5, 0xa0, 0xa0, 0x27, 0xd7, 0x0f, 0xad, 0x0c, 0x8a, 0xa0, + 0x8a, 0x3c, 0xbf, 0xbe, 0x99, 0x01, 0x8d, 0x00, 0x45, 0x38, 0x61, 0x73, + 0xe5, 0xfa, 0xe2, 0x25, 0xfa, 0xeb, 0xe0, 0xce, 0xf5, 0xdd, 0x45, 0x91, + 0x0f, 0x40, 0x0a, 0x86, 0xc2, 0xbe, 0x4e, 0x15, 0x25, 0x2a, 0x16, 0xde, + 0x41, 0x20, 0xa2, 0x67, 0xbe, 0x2b, 0x59, 0x4d +}; +static const uint8_t ac_dsa_vect3_priv_val[] = { +/* X */ + 0x20, 0xbc, 0xab, 0xc6, 0xd9, 0x34, 0x7a, 0x6e, 0x79, 0xb8, 0xe4, 0x98, + 0xc6, 0x0c, 0x44, 0xa1, 0x9c, 0x73, 0x25, 0x8c +}; +static const uint8_t ac_dsa_vect3_pub_val[] = { +/* Y */ + 0x23, 0xb4, 0xf4, 0x04, 0xaa, 0x3c, 0x57, 0x5e, 0x55, 0x0b, 0xb3, 0x20, + 0xfd, 0xb1, 0xa0, 0x85, 0xcd, 0x39, 0x6a, 0x10, 0xe5, 0xeb, 0xc6, 0x77, + 0x1d, 0xa6, 0x2f, 0x03, 0x7c, 0xab, 0x19, 0xea, 0xcd, 0x67, 0xd8, 0x22, + 0x2b, 0x63, 0x44, 0x03, 0x8c, 0x4f, 0x7a, 0xf4, 0x5f, 0x5e, 0x62, 0xb5, + 0x54, 0x80, 0xcb, 0xe2, 0x11, 0x11, 0x54, 0xca, 0x96, 0x97, 0xca, 0x76, + 0xd8, 0x7b, 0x56, 0x94, 0x41, 0x38, 0x08, 0x4e, 0x74, 0xc6, 0xf9, 0x0a, + 0x05, 0xcf, 0x43, 0x66, 0x0d, 0xff, 0x8b, 0x8b, 0x3f, 0xab, 0xfc, 0xab, + 0x3f, 0x0e, 0x44, 0x16, 0x77, 0x5f, 0xdf, 0x40, 0x05, 0x58, 0x64, 0xbe, + 0x10, 0x2b, 0x45, 0x87, 0x39, 0x2e, 0x77, 0x75, 0x2e, 0xd2, 0xae, 0xb1, + 0x82, 0xee, 0x4f, 0x70, 0xbe, 0x4a, 0x29, 0x1d, 0xbe, 0x77, 0xb8, 0x4a, + 0x44, 0xee, 0x34, 0x00, 0x79, 0x57, 0xb1, 0xe0 +}; +/* K = 7d9bcfc9225432de9860f605a38d389e291ca750 */ +static const uint8_t ac_dsa_vect3_out[] = { +/* R */ + 0x3f, 0x0a, 0x4a, 0xd3, 0x2f, 0x08, 0x16, 0x82, 0x1b, 0x8a, 0xff, 0xb5, + 0x18, 0xe9, 0xb5, 0x99, 0xf3, 0x5d, 0x57, 0xc2, +/* S */ + 0xea, 0x06, 0x63, 0x8f, 0x2b, 0x2f, 0xc9, 0xd1, 0xdf, 0xe9, 0x9c, 0x2a, + 0x49, 0x28, 0x06, 0xb4, 0x97, 0xe2, 0xb0, 0xea +}; +#define ac_dsa_vect4_prime ac_dsa_vect1_prime +#define ac_dsa_vect4_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect4_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect4_ptx[] = { +/* Msg */ + 0x85, 0x66, 0x2b, 0x69, 0x75, 0x50, 0xe4, 0x91, 0x5c, 0x29, 0xe3, 0x38, + 0xb6, 0x24, 0xb9, 0x12, 0x84, 0x5d, 0x6d, 0x1a, 0x92, 0x0d, 0x9e, 0x4c, + 0x16, 0x04, 0xdd, 0x47, 0xd6, 0x92, 0xbc, 0x7c, 0x0f, 0xfb, 0x95, 0xae, + 0x61, 0x4e, 0x85, 0x2b, 0xeb, 0xaf, 0x15, 0x73, 0x75, 0x8a, 0xd0, 0x1c, + 0x71, 0x3c, 0xac, 0x0b, 0x47, 0x6e, 0x2f, 0x12, 0x17, 0x45, 0xa3, 0xcf, + 0xee, 0xff, 0xb2, 0x44, 0x1f, 0xf6, 0xab, 0xfb, 0x9b, 0xbe, 0xb9, 0x8a, + 0xa6, 0x34, 0xca, 0x6f, 0xf5, 0x41, 0x94, 0x7d, 0xcc, 0x99, 0x27, 0x65, + 0x9d, 0x44, 0xf9, 0x5c, 0x5f, 0xf9, 0x17, 0x0f, 0xdc, 0x3c, 0x86, 0x47, + 0x3c, 0xb6, 0x01, 0xba, 0x31, 0xb4, 0x87, 0xfe, 0x59, 0x36, 0xba, 0xc5, + 0xd9, 0xc6, 0x32, 0xcb, 0xcc, 0x3d, 0xb0, 0x62, 0x46, 0xba, 0x01, 0xc5, + 0x5a, 0x03, 0x8d, 0x79, 0x7f, 0xe3, 0xf6, 0xc3 +}; +static const uint8_t ac_dsa_vect4_priv_val[] = { +/* X */ + 0x52, 0xd1, 0xfb, 0xe6, 0x87, 0xaa, 0x07, 0x02, 0xa5, 0x1a, 0x5b, 0xf9, + 0x56, 0x6b, 0xd5, 0x1b, 0xd5, 0x69, 0x42, 0x4c +}; +static const uint8_t ac_dsa_vect4_pub_val[] = { +/* Y */ + 0x6b, 0xc3, 0x6c, 0xb3, 0xfa, 0x61, 0xce, 0xcc, 0x15, 0x7b, 0xe0, 0x86, + 0x39, 0xa7, 0xca, 0x9e, 0x3d, 0xe0, 0x73, 0xb8, 0xa0, 0xff, 0x23, 0x57, + 0x4c, 0xe5, 0xab, 0x0a, 0x86, 0x7d, 0xfd, 0x60, 0x66, 0x9a, 0x56, 0xe6, + 0x0d, 0x1c, 0x98, 0x9b, 0x3a, 0xf8, 0xc8, 0xa4, 0x3f, 0x56, 0x95, 0xd5, + 0x03, 0xe3, 0x09, 0x89, 0x63, 0x99, 0x0e, 0x12, 0xb6, 0x35, 0x66, 0x78, + 0x41, 0x71, 0x05, 0x8e, 0xac, 0xe8, 0x5c, 0x72, 0x8c, 0xd4, 0xc0, 0x82, + 0x24, 0xc7, 0xa6, 0xef, 0xea, 0x75, 0xdc, 0xa2, 0x0d, 0xf4, 0x61, 0x01, + 0x3c, 0x75, 0xf4, 0x0a, 0xcb, 0xc2, 0x37, 0x99, 0xeb, 0xee, 0x7f, 0x33, + 0x61, 0x33, 0x6d, 0xad, 0xc4, 0xa5, 0x6f, 0x30, 0x57, 0x08, 0x66, 0x7b, + 0xfe, 0x60, 0x2b, 0x8e, 0xa7, 0x5a, 0x49, 0x1a, 0x5c, 0xf0, 0xc0, 0x6e, + 0xbd, 0x6f, 0xdc, 0x71, 0x61, 0xe1, 0x04, 0x97 +}; +/* K = 960c211891c090d05454646ebac1bfe1f381e82b */ +static const uint8_t ac_dsa_vect4_out[] = { +/* R */ + 0x3b, 0xc2, 0x9d, 0xee, 0x96, 0x95, 0x70, 0x50, 0xba, 0x43, 0x8d, 0x1b, + 0x3e, 0x17, 0xb0, 0x2c, 0x17, 0x25, 0xd2, 0x29, +/* S */ + 0x0a, 0xf8, 0x79, 0xcf, 0x84, 0x6c, 0x43, 0x4e, 0x08, 0xfb, 0x6c, 0x63, + 0x78, 0x2f, 0x4d, 0x03, 0xe0, 0xd8, 0x88, 0x65 +}; +#define ac_dsa_vect5_prime ac_dsa_vect1_prime +#define ac_dsa_vect5_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect5_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect5_ptx[] = { +/* Msg */ + 0x87, 0xb6, 0xe7, 0x5b, 0x9f, 0x8e, 0x99, 0xc4, 0xdd, 0x62, 0xad, 0xb6, + 0x93, 0xdd, 0x58, 0x90, 0xed, 0xff, 0x1b, 0xd0, 0x02, 0x8f, 0x4e, 0xf8, + 0x49, 0xdf, 0x0f, 0x1d, 0x2c, 0xe6, 0xb1, 0x81, 0xfc, 0x3a, 0x55, 0xae, + 0xa6, 0xd0, 0xa1, 0xf0, 0xae, 0xca, 0xb8, 0xed, 0x9e, 0x24, 0x8a, 0x00, + 0xe9, 0x6b, 0xe7, 0x94, 0xa7, 0xcf, 0xba, 0x12, 0x46, 0xef, 0xb7, 0x10, + 0xef, 0x4b, 0x37, 0x47, 0x1c, 0xef, 0x0a, 0x1b, 0xcf, 0x55, 0xce, 0xbc, + 0x8d, 0x5a, 0xd0, 0x71, 0x61, 0x2b, 0xd2, 0x37, 0xef, 0xed, 0xd5, 0x10, + 0x23, 0x62, 0xdb, 0x07, 0xa1, 0xe2, 0xc7, 0xa6, 0xf1, 0x5e, 0x09, 0xfe, + 0x64, 0xba, 0x42, 0xb6, 0x0a, 0x26, 0x28, 0xd8, 0x69, 0xae, 0x05, 0xef, + 0x61, 0x1f, 0xe3, 0x8d, 0x9c, 0xe1, 0x5e, 0xee, 0xc9, 0xbb, 0x3d, 0xec, + 0xc8, 0xdc, 0x17, 0x80, 0x9f, 0x3b, 0x6e, 0x95 +}; +static const uint8_t ac_dsa_vect5_priv_val[] = { +/* X */ + 0xc8, 0x6a, 0x54, 0xec, 0x5c, 0x4e, 0xc6, 0x3d, 0x73, 0x32, 0xcf, 0x43, + 0xdd, 0xb0, 0x82, 0xa3, 0x4e, 0xd6, 0xd5, 0xf5 +}; +static const uint8_t ac_dsa_vect5_pub_val[] = { +/* Y */ + 0x01, 0x4a, 0xc7, 0x46, 0xd3, 0x60, 0x5e, 0xfc, 0xb8, 0xa2, 0xc7, 0xda, + 0xe1, 0xf5, 0x46, 0x82, 0xa2, 0x62, 0xe2, 0x76, 0x62, 0xb2, 0x52, 0xc0, + 0x94, 0x78, 0xce, 0x87, 0xd0, 0xaa, 0xa5, 0x22, 0xd7, 0xc2, 0x00, 0x04, + 0x34, 0x06, 0x01, 0x6c, 0x0c, 0x42, 0x89, 0x6d, 0x21, 0x75, 0x0b, 0x15, + 0xdb, 0xd5, 0x7f, 0x97, 0x07, 0xec, 0x37, 0xdc, 0xea, 0x56, 0x51, 0x78, + 0x1b, 0x67, 0xad, 0x8d, 0x01, 0xf5, 0x09, 0x9f, 0xe7, 0x58, 0x4b, 0x35, + 0x3b, 0x64, 0x1b, 0xb1, 0x59, 0xcc, 0x71, 0x7d, 0x8c, 0xeb, 0x18, 0xb6, + 0x67, 0x05, 0xe6, 0x56, 0xf3, 0x36, 0xf1, 0x21, 0x4b, 0x34, 0xf0, 0x35, + 0x7e, 0x57, 0x7a, 0xb8, 0x36, 0x41, 0x96, 0x9e, 0x31, 0x1b, 0xf4, 0x0b, + 0xdc, 0xb3, 0xff, 0xd5, 0xe0, 0xbb, 0x59, 0x41, 0x9f, 0x22, 0x95, 0x08, + 0xd2, 0xf4, 0x32, 0xcc, 0x28, 0x59, 0xff, 0x75 +}; +/* K = 6c445cee68042553fbe63be61be4ddb99d8134af */ +static const uint8_t ac_dsa_vect5_out[] = { +/* R */ + 0x63, 0x7e, 0x07, 0xa5, 0x77, 0x0f, 0x3d, 0xc6, 0x5e, 0x45, 0x06, 0xc6, + 0x8c, 0x77, 0x0e, 0x5e, 0xf6, 0xb8, 0xce, 0xd3, +/* S */ + 0x7d, 0xfc, 0x6f, 0x83, 0xe2, 0x4f, 0x09, 0x74, 0x5e, 0x01, 0xd3, 0xf7, + 0xae, 0x0e, 0xd1, 0x47, 0x4e, 0x81, 0x1d, 0x47 +}; +#define ac_dsa_vect6_prime ac_dsa_vect1_prime +#define ac_dsa_vect6_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect6_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect6_ptx[] = { +/* Msg */ + 0x22, 0x59, 0xee, 0xad, 0x2d, 0x6b, 0xbc, 0x76, 0xd4, 0x92, 0x13, 0xea, + 0x0d, 0xc8, 0xb7, 0x35, 0x0a, 0x97, 0x69, 0x9f, 0x22, 0x34, 0x10, 0x44, + 0xc3, 0x94, 0x07, 0x82, 0x36, 0x4a, 0xc9, 0xea, 0x68, 0x31, 0x79, 0xa4, + 0x38, 0xa5, 0xea, 0x45, 0x99, 0x8d, 0xf9, 0x7c, 0x29, 0x72, 0xda, 0xe0, + 0x38, 0x51, 0xf5, 0xbe, 0x23, 0xfa, 0x9f, 0x04, 0x18, 0x2e, 0x79, 0xdd, + 0xb2, 0xb5, 0x6d, 0xc8, 0x65, 0x23, 0x93, 0xec, 0xb2, 0x7f, 0x3f, 0x3b, + 0x7c, 0x8a, 0x8d, 0x76, 0x1a, 0x86, 0xb3, 0xb8, 0xf4, 0xd4, 0x1a, 0x07, + 0xb4, 0xbe, 0x7d, 0x02, 0xfd, 0xde, 0xfc, 0x42, 0xb9, 0x28, 0x12, 0x4a, + 0x5a, 0x45, 0xb9, 0xf4, 0x60, 0x90, 0x42, 0x20, 0x9b, 0x3a, 0x7f, 0x58, + 0x5b, 0xd5, 0x14, 0xcc, 0x39, 0xc0, 0x0e, 0xff, 0xcc, 0x42, 0xc7, 0xfe, + 0x70, 0xfa, 0x83, 0xed, 0xf8, 0xa3, 0x2b, 0xf4 +}; +static const uint8_t ac_dsa_vect6_priv_val[] = { +/* X */ + 0xae, 0xe6, 0xf2, 0x13, 0xb9, 0x90, 0x3c, 0x80, 0x69, 0x38, 0x7e, 0x64, + 0x72, 0x9a, 0x08, 0x99, 0x9e, 0x5b, 0xaf, 0x65 +}; +static const uint8_t ac_dsa_vect6_pub_val[] = { +/* Y */ + 0x0f, 0xe7, 0x40, 0x45, 0xd7, 0xb0, 0xd4, 0x72, 0x41, 0x12, 0x02, 0x83, + 0x1d, 0x49, 0x32, 0x39, 0x6f, 0x24, 0x2a, 0x97, 0x65, 0xe9, 0x2b, 0xe3, + 0x87, 0xfd, 0x81, 0xbb, 0xe3, 0x8d, 0x84, 0x50, 0x54, 0x52, 0x8b, 0x34, + 0x8c, 0x03, 0x98, 0x41, 0x79, 0xb8, 0xe5, 0x05, 0x67, 0x4c, 0xb7, 0x9d, + 0x88, 0xcc, 0x0d, 0x8d, 0x3e, 0x8d, 0x73, 0x92, 0xf9, 0xaa, 0x77, 0x3b, + 0x29, 0xc2, 0x9e, 0x54, 0xa9, 0xe3, 0x26, 0x40, 0x60, 0x75, 0xd7, 0x55, + 0xc2, 0x91, 0xfc, 0xed, 0xbc, 0xc5, 0x77, 0x93, 0x4c, 0x82, 0x4a, 0xf9, + 0x88, 0x25, 0x0f, 0x64, 0xed, 0x56, 0x85, 0xfc, 0xe7, 0x26, 0xcf, 0xf6, + 0x5e, 0x92, 0xd7, 0x08, 0xae, 0x11, 0xcb, 0xfa, 0xa9, 0x58, 0xab, 0x8d, + 0x8b, 0x15, 0x34, 0x0a, 0x29, 0xa1, 0x37, 0xb5, 0xb4, 0x35, 0x7f, 0x7e, + 0xd1, 0xc7, 0xa5, 0x19, 0x0c, 0xbf, 0x98, 0xa4 +}; +/* K = e1704bae025942e2e63c6d76bab88da79640073a */ +static const uint8_t ac_dsa_vect6_out[] = { +/* R */ + 0x83, 0x36, 0x6b, 0xa3, 0xfe, 0xd9, 0x3d, 0xfb, 0x38, 0xd5, 0x41, 0x20, + 0x3e, 0xcb, 0xf8, 0x1c, 0x36, 0x39, 0x98, 0xe2, +/* S */ + 0x1f, 0xe2, 0x99, 0xc3, 0x6a, 0x13, 0x32, 0xf2, 0x3b, 0xf2, 0xe1, 0x0a, + 0x6c, 0x6a, 0x4e, 0x0d, 0x3c, 0xdd, 0x2b, 0xf4 +}; +#define ac_dsa_vect7_prime ac_dsa_vect1_prime +#define ac_dsa_vect7_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect7_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect7_ptx[] = { +/* Msg */ + 0x21, 0x9e, 0x8d, 0xf5, 0xbf, 0x88, 0x15, 0x90, 0x43, 0x0e, 0xce, 0x60, + 0x82, 0x50, 0xf7, 0x67, 0x0d, 0xc5, 0x65, 0x37, 0x24, 0x93, 0x02, 0x42, + 0x9e, 0x28, 0xec, 0xfe, 0xb9, 0xce, 0xaa, 0xa5, 0x49, 0x10, 0xa6, 0x94, + 0x90, 0xf7, 0x65, 0xf3, 0xdf, 0x82, 0xe8, 0xb0, 0x1c, 0xd7, 0xd7, 0x6e, + 0x56, 0x1d, 0x0f, 0x6c, 0xe2, 0x26, 0xef, 0x3c, 0xf7, 0x52, 0xca, 0xda, + 0x6f, 0xeb, 0xdc, 0x5b, 0xf0, 0x0d, 0x67, 0x94, 0x7f, 0x92, 0xd4, 0x20, + 0x51, 0x6b, 0x9e, 0x37, 0xc9, 0x6c, 0x8f, 0x1f, 0x2d, 0xa0, 0xb0, 0x75, + 0x09, 0x7c, 0x3b, 0xda, 0x75, 0x8a, 0x8d, 0x91, 0xbd, 0x2e, 0xbe, 0x9c, + 0x75, 0xcf, 0x14, 0x7f, 0x25, 0x4c, 0x25, 0x69, 0x63, 0xb3, 0x3b, 0x67, + 0xd0, 0x2b, 0x6a, 0xa0, 0x9e, 0x7d, 0x74, 0x65, 0xd0, 0x38, 0xe5, 0x01, + 0x95, 0xec, 0xe4, 0x18, 0x9b, 0x41, 0xe7, 0x68 +}; +static const uint8_t ac_dsa_vect7_priv_val[] = { +/* X */ + 0x69, 0x9f, 0x1c, 0x07, 0xaa, 0x45, 0x8c, 0x67, 0x86, 0xe7, 0x70, 0xb4, + 0x01, 0x97, 0x23, 0x5f, 0xe4, 0x9c, 0xf2, 0x1a +}; +static const uint8_t ac_dsa_vect7_pub_val[] = { +/* Y */ + 0x3a, 0x41, 0xb0, 0x67, 0x8f, 0xf3, 0xc4, 0xdd, 0xe2, 0x0f, 0xa3, 0x97, + 0x72, 0xba, 0xc3, 0x1a, 0x2f, 0x18, 0xba, 0xe4, 0xbe, 0xde, 0xc9, 0xe1, + 0x2e, 0xe8, 0xe0, 0x2e, 0x30, 0xe5, 0x56, 0xb1, 0xa1, 0x36, 0x01, 0x3b, + 0xef, 0x96, 0xb0, 0xd3, 0x0b, 0x56, 0x82, 0x33, 0xdc, 0xec, 0xc7, 0x1e, + 0x48, 0x5e, 0xd7, 0x5c, 0x92, 0x2a, 0xfb, 0x4d, 0x06, 0x54, 0xe7, 0x09, + 0xbe, 0xe8, 0x49, 0x93, 0x79, 0x21, 0x30, 0x22, 0x0e, 0x30, 0x05, 0xfd, + 0xb0, 0x6e, 0xbd, 0xfc, 0x0e, 0x2d, 0xf1, 0x63, 0xb5, 0xec, 0x42, 0x4e, + 0x83, 0x64, 0x65, 0xac, 0xd6, 0xd9, 0x2e, 0x24, 0x3c, 0x86, 0xf2, 0xb9, + 0x4b, 0x26, 0xb8, 0xd7, 0x3b, 0xd9, 0xcf, 0x72, 0x2c, 0x75, 0x7e, 0x0b, + 0x80, 0xb0, 0xaf, 0x16, 0xf1, 0x85, 0xde, 0x70, 0xe8, 0xca, 0x85, 0x0b, + 0x14, 0x02, 0xd1, 0x26, 0xea, 0x60, 0xf3, 0x09 +}; +/* K = 5bbb795bfa5fa72191fed3434a08741410367491 */ +static const uint8_t ac_dsa_vect7_out[] = { +/* R */ + 0x57, 0x97, 0x61, 0x03, 0x9a, 0xe0, 0xdd, 0xb8, 0x11, 0x06, 0xbf, 0x49, + 0x68, 0xe3, 0x20, 0x08, 0x3b, 0xbc, 0xb9, 0x47, +/* S */ + 0x50, 0x3e, 0xa1, 0x5d, 0xba, 0xc9, 0xde, 0xde, 0xba, 0x91, 0x7f, 0xa8, + 0xe9, 0xf3, 0x86, 0xb9, 0x3a, 0xa3, 0x03, 0x53 +}; +#define ac_dsa_vect8_prime ac_dsa_vect1_prime +#define ac_dsa_vect8_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect8_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect8_ptx[] = { +/* Msg */ + 0x2d, 0xa7, 0x9d, 0x06, 0x78, 0x85, 0xeb, 0x3c, 0xcf, 0x5e, 0x29, 0x3a, + 0xe3, 0xb1, 0xd8, 0x22, 0x53, 0x22, 0x20, 0x3a, 0xbb, 0x5a, 0xdf, 0xde, + 0x3b, 0x0f, 0x53, 0xbb, 0xe2, 0x4c, 0x4f, 0xe0, 0x01, 0x54, 0x1e, 0x11, + 0x83, 0xd8, 0x70, 0xa9, 0x97, 0xf1, 0xf9, 0x46, 0x01, 0x00, 0xb5, 0xd7, + 0x11, 0x92, 0x31, 0x80, 0x15, 0x43, 0x45, 0x28, 0x7a, 0x02, 0x14, 0xcf, + 0x1c, 0xac, 0x37, 0xb7, 0xa4, 0x7d, 0xfb, 0xb2, 0xa0, 0xe8, 0xce, 0x49, + 0x16, 0xf9, 0x4e, 0xbd, 0x6f, 0xa5, 0x4e, 0x31, 0x5b, 0x7a, 0x8e, 0xb5, + 0xb6, 0x3c, 0xd9, 0x54, 0xc5, 0xba, 0x05, 0xc1, 0xbf, 0x7e, 0x33, 0xa4, + 0xe8, 0xa1, 0x51, 0xf3, 0x2d, 0x28, 0x77, 0xb0, 0x17, 0x29, 0xc1, 0xad, + 0x0e, 0x7c, 0x01, 0xbb, 0x8a, 0xe7, 0x23, 0xc9, 0x95, 0x18, 0x38, 0x03, + 0xe4, 0x56, 0x36, 0x52, 0x0e, 0xa3, 0x8c, 0xa1 +}; +static const uint8_t ac_dsa_vect8_priv_val[] = { +/* X */ + 0xd6, 0xe0, 0x8c, 0x20, 0xc8, 0x29, 0x49, 0xdd, 0xba, 0x93, 0xea, 0x81, + 0xeb, 0x2f, 0xea, 0x8c, 0x59, 0x58, 0x94, 0xdc +}; +static const uint8_t ac_dsa_vect8_pub_val[] = { +/* Y */ + 0x56, 0xf7, 0x27, 0x22, 0x10, 0xf3, 0x16, 0xc5, 0x1a, 0xf8, 0xbf, 0xc4, + 0x5a, 0x42, 0x1f, 0xd4, 0xe9, 0xb1, 0x04, 0x38, 0x53, 0x27, 0x1b, 0x7e, + 0x79, 0xf4, 0x09, 0x36, 0xf0, 0xad, 0xcf, 0x26, 0x2a, 0x86, 0x09, 0x7a, + 0xa8, 0x6e, 0x19, 0xe6, 0xcb, 0x53, 0x07, 0x68, 0x5d, 0x86, 0x3d, 0xba, + 0x76, 0x13, 0x42, 0xdb, 0x6c, 0x97, 0x3b, 0x38, 0x49, 0xb1, 0xe0, 0x60, + 0xac, 0xa9, 0x26, 0xf4, 0x1f, 0xe0, 0x73, 0x23, 0x60, 0x10, 0x62, 0x51, + 0x5a, 0xe8, 0x5f, 0x31, 0x72, 0xb8, 0xf3, 0x48, 0x99, 0xc6, 0x21, 0xd5, + 0x9f, 0xa2, 0x1f, 0x73, 0xd5, 0xae, 0x97, 0xa3, 0xde, 0xb5, 0xe8, 0x40, + 0xb2, 0x5a, 0x18, 0xfd, 0x58, 0x08, 0x62, 0xfd, 0x7b, 0x1c, 0xf4, 0x16, + 0xc7, 0xae, 0x9f, 0xc5, 0x84, 0x2a, 0x01, 0x97, 0xfd, 0xb0, 0xc5, 0x17, + 0x3f, 0xf4, 0xa4, 0xf1, 0x02, 0xa8, 0xcf, 0x89 +}; +/* K = 6d72c30d4430959800740f2770651095d0c181c2 */ +static const uint8_t ac_dsa_vect8_out[] = { +/* R */ + 0x5d, 0xd9, 0x0d, 0x69, 0xad, 0xd6, 0x7a, 0x5f, 0xae, 0x13, 0x8e, 0xec, + 0x1a, 0xaf, 0xf0, 0x22, 0x9a, 0xa4, 0xaf, 0xc4, +/* S */ + 0x47, 0xf3, 0x9c, 0x4d, 0xb2, 0x38, 0x7f, 0x10, 0x76, 0x2f, 0x45, 0xb8, + 0x0d, 0xfd, 0x02, 0x79, 0x06, 0xd7, 0xef, 0x04 +}; +#define ac_dsa_vect9_prime ac_dsa_vect1_prime +#define ac_dsa_vect9_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect9_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect9_ptx[] = { +/* Msg */ + 0xba, 0x30, 0xd8, 0x5b, 0xe3, 0x57, 0xe7, 0xfb, 0x29, 0xf8, 0xa0, 0x7e, + 0x1f, 0x12, 0x7b, 0xaa, 0xa2, 0x4b, 0x2e, 0xe0, 0x27, 0xf6, 0x4c, 0xb5, + 0xef, 0xee, 0xc6, 0xaa, 0xea, 0xbc, 0xc7, 0x34, 0x5c, 0x5d, 0x55, 0x6e, + 0xbf, 0x4b, 0xdc, 0x7a, 0x61, 0xc7, 0x7c, 0x7b, 0x7e, 0xa4, 0x3c, 0x73, + 0xba, 0xbc, 0x18, 0xf7, 0xb4, 0x80, 0x77, 0x22, 0xda, 0x23, 0x9e, 0x45, + 0xdd, 0xf2, 0x49, 0x84, 0x9c, 0xbb, 0xfe, 0x35, 0x07, 0x11, 0x2e, 0xbf, + 0x87, 0xd7, 0xef, 0x56, 0x0c, 0x2e, 0x7d, 0x39, 0x1e, 0xd8, 0x42, 0x4f, + 0x87, 0x10, 0xce, 0xa4, 0x16, 0x85, 0x14, 0x3e, 0x30, 0x06, 0xf8, 0x1b, + 0x68, 0xfb, 0xb4, 0xd5, 0xf9, 0x64, 0x4c, 0x7c, 0xd1, 0x0f, 0x70, 0x92, + 0xef, 0x24, 0x39, 0xb8, 0xd1, 0x8c, 0x0d, 0xf6, 0x55, 0xe0, 0x02, 0x89, + 0x37, 0x2a, 0x41, 0x66, 0x38, 0x5d, 0x64, 0x0c +}; +static const uint8_t ac_dsa_vect9_priv_val[] = { +/* X */ + 0x50, 0x01, 0x84, 0x82, 0x86, 0x4c, 0x18, 0x64, 0xe9, 0xdb, 0x1f, 0x04, + 0xbd, 0xe8, 0xdb, 0xfd, 0x38, 0x75, 0xc7, 0x6d +}; +static const uint8_t ac_dsa_vect9_pub_val[] = { +/* Y */ + 0x09, 0x42, 0xa5, 0xb7, 0xa7, 0x2a, 0xb1, 0x16, 0xea, 0xd2, 0x93, 0x08, + 0xcf, 0x65, 0x8d, 0xfe, 0x3d, 0x55, 0xd5, 0xd6, 0x1a, 0xfe, 0xd9, 0xe3, + 0x83, 0x6e, 0x64, 0x23, 0x7f, 0x9d, 0x68, 0x84, 0xfd, 0xd8, 0x27, 0xd2, + 0xd5, 0x89, 0x0c, 0x9a, 0x41, 0xae, 0x88, 0xe7, 0xa6, 0x9f, 0xc9, 0xf3, + 0x45, 0xad, 0xe9, 0xc4, 0x80, 0xc6, 0xf0, 0x8c, 0xff, 0x06, 0x7c, 0x18, + 0x32, 0x14, 0xc2, 0x27, 0x23, 0x6c, 0xed, 0xb6, 0xdd, 0x12, 0x83, 0xca, + 0x2a, 0x60, 0x25, 0x74, 0xe8, 0x32, 0x75, 0x10, 0x22, 0x1d, 0x4c, 0x27, + 0xb1, 0x62, 0x14, 0x3b, 0x70, 0x02, 0xd8, 0xc7, 0x26, 0x91, 0x68, 0x26, + 0x26, 0x59, 0x37, 0xb8, 0x7b, 0xe9, 0xd5, 0xec, 0x6d, 0x7b, 0xd2, 0x8f, + 0xb0, 0x15, 0xf8, 0x4e, 0x0a, 0xb7, 0x30, 0xda, 0x7a, 0x4e, 0xaf, 0x4e, + 0xf3, 0x17, 0x4b, 0xf0, 0xa2, 0x2a, 0x63, 0x92 +}; +/* K = df3a9348f37b5d2d4c9176db266ae388f1fa7e0f */ +static const uint8_t ac_dsa_vect9_out[] = { +/* R */ + 0x44, 0x84, 0x34, 0xb2, 0x14, 0xee, 0xe3, 0x8b, 0xde, 0x08, 0x0f, 0x8e, + 0xc4, 0x33, 0xe8, 0xd1, 0x9b, 0x3d, 0xdf, 0x0d, +/* S */ + 0x0c, 0x02, 0xe8, 0x81, 0xb7, 0x77, 0x92, 0x3f, 0xe0, 0xea, 0x67, 0x4f, + 0x26, 0x21, 0x29, 0x8e, 0x00, 0x19, 0x9d, 0x5f +}; +#define ac_dsa_vect10_prime ac_dsa_vect1_prime +#define ac_dsa_vect10_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect10_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect10_ptx[] = { +/* Msg */ + 0x83, 0x49, 0x9e, 0xfb, 0x06, 0xbb, 0x7f, 0xf0, 0x2f, 0xfb, 0x46, 0xc2, + 0x78, 0xa5, 0xe9, 0x26, 0x30, 0xac, 0x5b, 0xc3, 0xf9, 0xe5, 0x3d, 0xd2, + 0xe7, 0x8f, 0xf1, 0x5e, 0x36, 0x8c, 0x7e, 0x31, 0xaa, 0xd7, 0x7c, 0xf7, + 0x71, 0xf3, 0x5f, 0xa0, 0x2d, 0x0b, 0x5f, 0x13, 0x52, 0x08, 0xa4, 0xaf, + 0xdd, 0x86, 0x7b, 0xb2, 0xec, 0x26, 0xea, 0x2e, 0x7d, 0xd6, 0x4c, 0xde, + 0xf2, 0x37, 0x50, 0x8a, 0x38, 0xb2, 0x7f, 0x39, 0xd8, 0xb2, 0x2d, 0x45, + 0xca, 0xc5, 0xa6, 0x8a, 0x90, 0xb6, 0xea, 0x76, 0x05, 0x86, 0x45, 0xf6, + 0x35, 0x6a, 0x93, 0x44, 0xd3, 0x6f, 0x00, 0xec, 0x66, 0x52, 0xea, 0xa4, + 0xe9, 0xba, 0xe7, 0xb6, 0x94, 0xf9, 0xf1, 0xfc, 0x8c, 0x6c, 0x5e, 0x86, + 0xfa, 0xdc, 0x7b, 0x27, 0xa2, 0x19, 0xb5, 0xc1, 0xb2, 0xae, 0x80, 0xa7, + 0x25, 0xe5, 0xf6, 0x11, 0x65, 0xfe, 0x2e, 0xdc +}; +static const uint8_t ac_dsa_vect10_priv_val[] = { +/* X */ + 0xae, 0x56, 0xf6, 0x6b, 0x0a, 0x94, 0x05, 0xb9, 0xcc, 0xa5, 0x4c, 0x60, + 0xec, 0x4a, 0x3b, 0xb5, 0xf8, 0xbe, 0x7c, 0x3f +}; +static const uint8_t ac_dsa_vect10_pub_val[] = { +/* Y */ + 0xa0, 0x15, 0x42, 0xc3, 0xda, 0x41, 0x0d, 0xd5, 0x79, 0x30, 0xca, 0x72, + 0x4f, 0x0f, 0x50, 0x7c, 0x4d, 0xf4, 0x3d, 0x55, 0x3c, 0x7f, 0x69, 0x45, + 0x99, 0x39, 0x68, 0x59, 0x41, 0xce, 0xb9, 0x5c, 0x7d, 0xcc, 0x3f, 0x17, + 0x5a, 0x40, 0x3b, 0x35, 0x96, 0x21, 0xc0, 0xd4, 0x32, 0x8e, 0x98, 0xf1, + 0x5f, 0x33, 0x0a, 0x63, 0x86, 0x5b, 0xaf, 0x3e, 0x7e, 0xb1, 0x60, 0x4a, + 0x07, 0x15, 0xe1, 0x6e, 0xed, 0x64, 0xfd, 0x14, 0xb3, 0x5d, 0x3a, 0x53, + 0x42, 0x59, 0xa6, 0xa7, 0xdd, 0xf8, 0x88, 0xc4, 0xdb, 0xb5, 0xf5, 0x1b, + 0xbc, 0x6e, 0xd3, 0x39, 0xe5, 0xbb, 0x2a, 0x23, 0x9d, 0x5c, 0xfe, 0x21, + 0x00, 0xac, 0x8e, 0x2f, 0x9c, 0x16, 0xe5, 0x36, 0xf2, 0x51, 0x19, 0xab, + 0x43, 0x58, 0x43, 0xaf, 0x27, 0xdc, 0x33, 0x41, 0x4a, 0x9e, 0x46, 0x02, + 0xf9, 0x6d, 0x7c, 0x94, 0xd6, 0x02, 0x1c, 0xec +}; +/* K = 8857ff301ad0169d164fa269977a116e070bac17 */ +static const uint8_t ac_dsa_vect10_out[] = { +/* R */ + 0x8c, 0x2f, 0xab, 0x48, 0x9c, 0x34, 0x67, 0x21, 0x40, 0x41, 0x5d, 0x41, + 0xa6, 0x5c, 0xef, 0x1e, 0x70, 0x19, 0x2e, 0x23, +/* S */ + 0x3d, 0xf8, 0x6a, 0x9e, 0x2e, 0xfe, 0x94, 0x4a, 0x1c, 0x7e, 0xa9, 0xc3, + 0x0c, 0xac, 0x33, 0x1d, 0x00, 0x59, 0x9a, 0x0e +}; +#define ac_dsa_vect11_prime ac_dsa_vect1_prime +#define ac_dsa_vect11_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect11_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect11_ptx[] = { +/* Msg */ + 0xf2, 0x3e, 0xe7, 0x9e, 0xb4, 0xfc, 0xe5, 0xcb, 0xf3, 0xb0, 0x8d, 0x65, + 0xa1, 0x80, 0x3d, 0x2e, 0x3e, 0x19, 0x1d, 0x35, 0x80, 0xa4, 0x4d, 0x17, + 0x7d, 0x8f, 0xf0, 0x69, 0xf9, 0x07, 0x84, 0xd0, 0x12, 0xca, 0x57, 0x46, + 0xe6, 0xdd, 0x66, 0x38, 0xdf, 0xe8, 0x41, 0x3f, 0x1d, 0xb3, 0xd8, 0xfe, + 0x28, 0x2c, 0x21, 0x60, 0xf5, 0xdd, 0x96, 0x60, 0x7d, 0xd6, 0x3d, 0x61, + 0x0f, 0x79, 0x1d, 0xfc, 0x10, 0xab, 0xad, 0x18, 0x72, 0x15, 0x87, 0x10, + 0x1c, 0xec, 0x8a, 0x2a, 0x12, 0x91, 0x3c, 0xfb, 0xad, 0xa3, 0xa5, 0xb7, + 0x59, 0x39, 0x58, 0xb9, 0xbf, 0xa6, 0xe9, 0xaf, 0x3a, 0xf5, 0xd7, 0x1f, + 0xf1, 0x7e, 0xc7, 0x2a, 0xaa, 0xee, 0xca, 0xaf, 0xfc, 0x5d, 0x17, 0x4e, + 0x62, 0x9a, 0x09, 0x02, 0x97, 0xe9, 0x4c, 0xdf, 0xe9, 0x88, 0xd9, 0xbf, + 0x6c, 0x80, 0x82, 0x7c, 0x23, 0xdf, 0x51, 0x37 +}; +static const uint8_t ac_dsa_vect11_priv_val[] = { +/* X */ + 0xa6, 0x20, 0x79, 0xb4, 0xf4, 0x57, 0x72, 0xbf, 0x17, 0xb8, 0x5d, 0x75, + 0x60, 0xe3, 0xbe, 0x4e, 0x52, 0x14, 0x39, 0xeb +}; +static const uint8_t ac_dsa_vect11_pub_val[] = { +/* Y */ + 0x22, 0x9a, 0x26, 0xdc, 0xaf, 0xf2, 0x9e, 0xd1, 0xa7, 0x26, 0x4e, 0xd0, + 0xf7, 0x7d, 0x67, 0x62, 0x39, 0xb9, 0xba, 0x1e, 0xf4, 0x77, 0x8e, 0x7d, + 0xd6, 0x40, 0xe8, 0xaa, 0x6f, 0xab, 0xdc, 0x1f, 0x1b, 0xd3, 0xf5, 0x82, + 0xe2, 0x11, 0xbd, 0x01, 0xc2, 0x6b, 0x3d, 0x9d, 0x3b, 0xff, 0xe7, 0x19, + 0x9f, 0x9e, 0xd4, 0x5d, 0x76, 0x4c, 0xd9, 0xd0, 0xe8, 0x44, 0xb3, 0x85, + 0xcb, 0x34, 0xe6, 0xde, 0x22, 0x37, 0x0e, 0xbc, 0x6b, 0xa4, 0x1d, 0xb4, + 0x09, 0xd6, 0x3f, 0x50, 0xc1, 0xac, 0x09, 0xbe, 0xd0, 0x0c, 0xdc, 0x2b, + 0x7c, 0x55, 0x22, 0x3c, 0x59, 0x6b, 0x7e, 0x13, 0x3b, 0xa2, 0x5b, 0xa9, + 0xe7, 0x8f, 0x33, 0x50, 0x2f, 0x8d, 0xd5, 0x2f, 0x32, 0xa6, 0x67, 0xa7, + 0x68, 0x3e, 0x50, 0x40, 0x47, 0x81, 0x79, 0x63, 0x23, 0x8d, 0x96, 0x29, + 0xa9, 0x18, 0xa0, 0xce, 0xeb, 0xaa, 0xd5, 0x18 +}; +/* K = c01acd36910f2f2bff608386b81c35a0a7c0b378 */ +static const uint8_t ac_dsa_vect11_out[] = { +/* R */ + 0x8d, 0x38, 0x8e, 0xc7, 0xf2, 0x86, 0x3d, 0xd5, 0xb7, 0xc9, 0x9a, 0xc9, + 0x35, 0x05, 0xd1, 0x58, 0x0b, 0xf2, 0xe0, 0xc7, +/* S */ + 0x76, 0xae, 0x93, 0x17, 0x69, 0x6d, 0x37, 0xf2, 0xd8, 0xbd, 0x61, 0xc4, + 0x77, 0x33, 0xe9, 0x45, 0x5b, 0x61, 0xd3, 0x47 +}; +#define ac_dsa_vect12_prime ac_dsa_vect1_prime +#define ac_dsa_vect12_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect12_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect12_ptx[] = { +/* Msg */ + 0x68, 0x36, 0x25, 0x5e, 0x6e, 0x65, 0x9d, 0xe4, 0xff, 0xb5, 0x35, 0x89, + 0x2d, 0x46, 0x6a, 0x3b, 0xea, 0x09, 0x69, 0x3e, 0x58, 0x7e, 0xb5, 0xbd, + 0x50, 0xf4, 0x4f, 0x8a, 0x22, 0xf1, 0x16, 0x97, 0x05, 0x7d, 0x68, 0x66, + 0x0b, 0xc6, 0x56, 0x24, 0x00, 0xd5, 0x87, 0xba, 0xac, 0x1c, 0x19, 0xd3, + 0x30, 0xff, 0x79, 0x4a, 0x70, 0xdf, 0x53, 0x00, 0xa5, 0x21, 0x1c, 0x72, + 0x54, 0x1a, 0x56, 0xd0, 0xff, 0x2a, 0xf0, 0x2a, 0x27, 0x8e, 0xd2, 0xdb, + 0x1d, 0xf9, 0x4c, 0xcb, 0x20, 0x26, 0xd3, 0x13, 0x8b, 0x2d, 0x92, 0x42, + 0x45, 0x02, 0x1e, 0xe8, 0x35, 0xd3, 0xc1, 0x7b, 0x0b, 0x3b, 0x76, 0x77, + 0xde, 0xf8, 0x56, 0x11, 0x22, 0x7f, 0x6c, 0xe2, 0x91, 0x3e, 0x7c, 0xb4, + 0x46, 0xa4, 0x79, 0xb9, 0x5a, 0xcf, 0xd0, 0x10, 0x5c, 0x25, 0xe4, 0x65, + 0x6f, 0xbc, 0x56, 0xc2, 0xa1, 0x0a, 0x22, 0xb3 +}; +static const uint8_t ac_dsa_vect12_priv_val[] = { +/* X */ + 0x78, 0x61, 0xe8, 0x2e, 0x66, 0xb6, 0xca, 0xea, 0x54, 0xb1, 0x59, 0xc5, + 0x9c, 0x88, 0x7e, 0xc2, 0x7b, 0x2e, 0x91, 0x5f +}; +static const uint8_t ac_dsa_vect12_pub_val[] = { +/* Y */ + 0xa7, 0xbb, 0xc3, 0x54, 0x23, 0x51, 0x0e, 0xdf, 0xeb, 0xf7, 0x9c, 0x4e, + 0x2e, 0x56, 0x98, 0x6f, 0x28, 0x06, 0xd1, 0x11, 0x16, 0xbc, 0xae, 0x90, + 0xa7, 0x16, 0xf0, 0x5d, 0xcb, 0xfc, 0x46, 0xdc, 0xbf, 0xeb, 0xe2, 0xec, + 0x94, 0x6c, 0x40, 0xf9, 0xcc, 0x8c, 0x1a, 0x74, 0x39, 0xcd, 0xd0, 0x4e, + 0x27, 0x01, 0x22, 0xec, 0x1c, 0x3b, 0xac, 0xa8, 0x38, 0x11, 0xa9, 0xf1, + 0xbd, 0xae, 0xd9, 0xb1, 0x17, 0x21, 0x50, 0xaf, 0x1c, 0x8c, 0xe1, 0xc5, + 0xd5, 0x02, 0xdf, 0xe5, 0xf4, 0xe8, 0x46, 0x7e, 0x50, 0x60, 0x50, 0x87, + 0xa8, 0xf8, 0xc5, 0xf4, 0x5c, 0xa6, 0x72, 0xfd, 0x04, 0x9e, 0xec, 0x0a, + 0x06, 0xf5, 0xe0, 0x1f, 0x78, 0x2d, 0x51, 0xf3, 0xba, 0x56, 0x40, 0x4b, + 0xf1, 0x38, 0x80, 0x65, 0x55, 0x2f, 0xc8, 0x7a, 0xd2, 0x1a, 0xc0, 0xfa, + 0x40, 0x27, 0xa1, 0x45, 0xd0, 0xb0, 0xd9, 0xe6 +}; +/* K = 4e22cfa2e8ca2b33a9fd91ff4837fc205864e8b1 */ +static const uint8_t ac_dsa_vect12_out[] = { +/* R */ + 0xc0, 0xab, 0x43, 0xd3, 0x09, 0xa5, 0xe9, 0x4b, 0x6e, 0xf4, 0xdb, 0x99, + 0x43, 0x30, 0x6e, 0x6d, 0x96, 0x6f, 0xc9, 0xb5, +/* S */ + 0x07, 0xec, 0x5a, 0xa1, 0x92, 0x8f, 0x19, 0xfc, 0x3a, 0x42, 0x0f, 0x29, + 0xb9, 0x35, 0xba, 0xc4, 0x61, 0x24, 0xc0, 0xe2 +}; +#define ac_dsa_vect13_prime ac_dsa_vect1_prime +#define ac_dsa_vect13_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect13_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect13_ptx[] = { +/* Msg */ + 0x4b, 0x08, 0x45, 0xc9, 0x9d, 0xb3, 0x48, 0x29, 0x4f, 0x1d, 0x83, 0x16, + 0x6b, 0x27, 0xf4, 0x48, 0xec, 0x29, 0xab, 0x79, 0x65, 0x46, 0x44, 0x77, + 0xf4, 0x54, 0x44, 0xf4, 0x46, 0x72, 0xa4, 0x09, 0xdd, 0xca, 0xfa, 0xf3, + 0x5e, 0x91, 0xfa, 0xf4, 0x01, 0xec, 0xa7, 0x49, 0x8e, 0x32, 0x68, 0xca, + 0xa2, 0xd9, 0x6b, 0xf1, 0xaa, 0x84, 0x0c, 0x0e, 0x1e, 0xd4, 0x3a, 0x5a, + 0xb6, 0x08, 0x88, 0xfc, 0xf0, 0x2b, 0x2f, 0x8a, 0x2c, 0x89, 0xda, 0xa5, + 0x98, 0xad, 0xf0, 0xb7, 0xd2, 0xda, 0xce, 0x92, 0x10, 0xef, 0xd4, 0x1a, + 0xb4, 0x96, 0xa1, 0xe7, 0x3a, 0x18, 0x2d, 0xa4, 0x30, 0xc1, 0xd0, 0x43, + 0xe2, 0x49, 0xa1, 0x28, 0x9c, 0x91, 0x80, 0x9c, 0x8c, 0x72, 0x98, 0xcf, + 0xdb, 0xb0, 0xae, 0x43, 0x8b, 0x00, 0x93, 0x6c, 0x28, 0x3a, 0x0e, 0xc2, + 0xd7, 0x9c, 0xdc, 0x81, 0xc9, 0xce, 0x3c, 0x2d +}; +static const uint8_t ac_dsa_vect13_priv_val[] = { +/* X */ + 0x6f, 0x2d, 0x3b, 0x09, 0xfa, 0xe6, 0x91, 0x0d, 0xd9, 0x75, 0x87, 0x0d, + 0xb3, 0xa2, 0xc1, 0x9d, 0x97, 0x16, 0x94, 0x91 +}; +static const uint8_t ac_dsa_vect13_pub_val[] = { +/* Y */ + 0x54, 0x1a, 0x9c, 0x45, 0xe1, 0x65, 0xd3, 0xd9, 0x1e, 0x71, 0xbb, 0x13, + 0x70, 0xd7, 0xc0, 0x32, 0xc3, 0x60, 0x32, 0x2a, 0xa1, 0x5e, 0x99, 0xd8, + 0xc1, 0xc1, 0x6e, 0xa3, 0x5c, 0x8c, 0x19, 0x32, 0x24, 0xa0, 0x64, 0x67, + 0xab, 0x77, 0xa6, 0x54, 0x78, 0xc4, 0x67, 0xb3, 0xf2, 0x0c, 0xb0, 0xc5, + 0xfd, 0xb8, 0xc8, 0x4c, 0xef, 0xa6, 0x95, 0x66, 0xa5, 0x94, 0xa2, 0xaa, + 0x54, 0xc3, 0xa9, 0x48, 0xeb, 0xc1, 0xea, 0x7e, 0x6c, 0x3d, 0x28, 0xd3, + 0x80, 0xcb, 0xd0, 0x17, 0x40, 0x63, 0x4c, 0x96, 0xb7, 0x6d, 0x6a, 0x03, + 0xcc, 0x6e, 0xba, 0x0a, 0xfa, 0x72, 0x26, 0xf2, 0x3f, 0xc1, 0x0a, 0x18, + 0xb0, 0xb6, 0xf9, 0x72, 0x70, 0xdf, 0xa0, 0x38, 0x16, 0x09, 0x60, 0xb5, + 0xb8, 0x39, 0xba, 0x66, 0xaf, 0x50, 0xfd, 0xa0, 0x72, 0x45, 0x81, 0x0e, + 0x80, 0xd3, 0x8b, 0x66, 0x93, 0xe8, 0xa9, 0xce +}; +/* K = 8588557c12ec6fe176b0be7bbd8b482ad78f1fef */ +static const uint8_t ac_dsa_vect13_out[] = { +/* R */ + 0x44, 0x28, 0x60, 0x19, 0xc1, 0xd5, 0x31, 0x03, 0x98, 0x06, 0x16, 0x94, + 0x0c, 0x02, 0x8b, 0xad, 0x32, 0x17, 0xf7, 0x8d, +/* S */ + 0x4b, 0x37, 0x2b, 0xf5, 0x27, 0xc5, 0x15, 0xf5, 0x80, 0x25, 0x69, 0x9a, + 0x45, 0xf2, 0x02, 0x1e, 0xf1, 0x8e, 0x11, 0xb9 +}; +#define ac_dsa_vect14_prime ac_dsa_vect1_prime +#define ac_dsa_vect14_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect14_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect14_ptx[] = { +/* Msg */ + 0x45, 0x97, 0xc1, 0xca, 0x0b, 0x07, 0x64, 0xbe, 0x31, 0xfa, 0x73, 0xcc, + 0xc5, 0x89, 0x11, 0x6c, 0xc8, 0xd0, 0xa3, 0x16, 0x05, 0xf2, 0x55, 0x0e, + 0xb3, 0x7f, 0xa5, 0x69, 0xb2, 0x49, 0x6c, 0x4f, 0x34, 0x32, 0x1d, 0x61, + 0xbb, 0x8e, 0x49, 0xf8, 0x58, 0xc8, 0x67, 0x1b, 0x74, 0x37, 0xfc, 0x15, + 0xf2, 0x69, 0xdd, 0x2d, 0x41, 0x46, 0x47, 0x0b, 0x81, 0x7d, 0xfe, 0x30, + 0x69, 0x22, 0x5d, 0xdd, 0x3c, 0xd4, 0xa6, 0xc9, 0x77, 0xfb, 0x6c, 0xfc, + 0x0d, 0x43, 0x26, 0x4a, 0x7b, 0xf6, 0x65, 0x92, 0x83, 0xe1, 0x40, 0xe4, + 0xc8, 0x9a, 0xb2, 0xe8, 0xa4, 0xd0, 0xed, 0xe6, 0x27, 0x49, 0x61, 0xd6, + 0x55, 0xbd, 0x79, 0xc7, 0xe4, 0x78, 0x80, 0xa7, 0x41, 0xfb, 0x01, 0x80, + 0xc3, 0x25, 0xb5, 0xb7, 0xd2, 0xf7, 0xb8, 0xa5, 0x7a, 0xed, 0x52, 0xd0, + 0x20, 0x6a, 0x83, 0xbb, 0x69, 0xa9, 0xd7, 0xa4 +}; +static const uint8_t ac_dsa_vect14_priv_val[] = { +/* X */ + 0x49, 0xf6, 0xc1, 0xac, 0x8e, 0x63, 0x9b, 0xcc, 0x99, 0xb2, 0xd9, 0xd1, + 0xf1, 0xe3, 0x25, 0x71, 0x3f, 0x29, 0xb9, 0x7c +}; +static const uint8_t ac_dsa_vect14_pub_val[] = { +/* Y */ + 0x53, 0x15, 0xad, 0xf9, 0x0e, 0x19, 0x69, 0x46, 0xbe, 0x6b, 0x04, 0xc5, + 0x41, 0x4d, 0xa1, 0xfa, 0xfd, 0x98, 0xb0, 0xd1, 0x7c, 0x3a, 0x39, 0x00, + 0x0a, 0x00, 0x09, 0x1b, 0x7b, 0x56, 0x57, 0x4b, 0x1e, 0xcd, 0x02, 0x6e, + 0xab, 0xb2, 0x5b, 0xe9, 0xec, 0xd0, 0xad, 0x69, 0x1d, 0xf2, 0xb7, 0xbf, + 0x7e, 0xec, 0xd6, 0xad, 0x95, 0xbb, 0x4d, 0x7d, 0x17, 0xac, 0x74, 0x70, + 0x60, 0xee, 0x7e, 0x3e, 0xb5, 0xc6, 0xfb, 0x75, 0x57, 0xcf, 0x7e, 0x80, + 0x03, 0xa6, 0x20, 0xe4, 0x3e, 0x58, 0x7d, 0x06, 0x12, 0x85, 0x44, 0x72, + 0xc3, 0xad, 0x85, 0x18, 0x39, 0xf7, 0x44, 0x15, 0x94, 0x11, 0xa3, 0x38, + 0x76, 0xae, 0xc3, 0x65, 0xeb, 0x04, 0x91, 0xde, 0xc8, 0x0b, 0xa1, 0x4c, + 0xba, 0x2d, 0x11, 0xde, 0xc4, 0x2a, 0xf4, 0xa4, 0xbf, 0x9c, 0x99, 0x31, + 0x2a, 0x2a, 0xe7, 0xe5, 0x46, 0x2a, 0x2a, 0xdf +}; +/* K = 8ef1c5976ac8caf74df65d9ecdbe78a6490bc220 */ +static const uint8_t ac_dsa_vect14_out[] = { +/* R */ + 0x90, 0xd5, 0x47, 0x71, 0x2b, 0xc0, 0xce, 0xbb, 0xd3, 0xeb, 0xd1, 0x8a, + 0x63, 0xd9, 0xb9, 0x2a, 0x03, 0x95, 0x30, 0x50, +/* S */ + 0x34, 0xea, 0x61, 0x76, 0xb4, 0xc6, 0x30, 0x43, 0x29, 0x5f, 0x12, 0x9a, + 0x48, 0x95, 0xe1, 0x4e, 0xe5, 0x81, 0x65, 0x63 +}; +#define ac_dsa_vect15_prime ac_dsa_vect1_prime +#define ac_dsa_vect15_sub_prime ac_dsa_vect1_sub_prime +#define ac_dsa_vect15_base ac_dsa_vect1_base +static const uint8_t ac_dsa_vect15_ptx[] = { +/* Msg */ + 0x18, 0xc6, 0x2a, 0x40, 0xb5, 0x23, 0x47, 0xa4, 0x73, 0xf5, 0x7a, 0xa6, + 0x68, 0xee, 0xbb, 0x44, 0x84, 0xbe, 0xb5, 0xf1, 0x0f, 0xdc, 0x51, 0x77, + 0x9e, 0x67, 0x70, 0x10, 0x6c, 0x0d, 0x12, 0x2e, 0xb6, 0x35, 0x6a, 0xe5, + 0x3a, 0x33, 0x79, 0xe2, 0x70, 0xed, 0xca, 0x39, 0x01, 0x5d, 0xa3, 0x00, + 0x57, 0x70, 0xc7, 0xb2, 0xa5, 0xaf, 0xd1, 0x12, 0x17, 0x99, 0x31, 0x53, + 0xff, 0x43, 0xa0, 0xb2, 0x6d, 0xb0, 0x1a, 0xa2, 0xa4, 0x93, 0xde, 0x06, + 0x14, 0x92, 0xa0, 0xaa, 0x3f, 0x22, 0x9b, 0x5a, 0xbd, 0x1a, 0xff, 0x29, + 0x39, 0x5e, 0x31, 0xb0, 0x63, 0x50, 0x4e, 0xb3, 0x56, 0x20, 0x21, 0x9b, + 0xa2, 0x99, 0x97, 0xf9, 0x2a, 0x52, 0xe1, 0xb2, 0xe6, 0xff, 0x20, 0x74, + 0x80, 0xfd, 0x13, 0xd5, 0x8f, 0xf0, 0x29, 0x0e, 0xec, 0x5a, 0xab, 0xf2, + 0x3b, 0x84, 0x94, 0x3e, 0xea, 0x20, 0xa4, 0x3c +}; +static const uint8_t ac_dsa_vect15_priv_val[] = { +/* X */ + 0x39, 0x6c, 0xbe, 0x3e, 0x71, 0xd7, 0x4f, 0x6d, 0xb7, 0x95, 0xc3, 0x8d, + 0x49, 0xc3, 0x2d, 0x78, 0xea, 0xb0, 0x33, 0x97 +}; +static const uint8_t ac_dsa_vect15_pub_val[] = { +/* Y */ + 0x3b, 0x73, 0x82, 0x46, 0xf9, 0xe3, 0x8c, 0xeb, 0xf4, 0x54, 0x2c, 0xed, + 0x3f, 0xc0, 0xc0, 0x09, 0x6a, 0xeb, 0x9e, 0x9a, 0x3a, 0xd9, 0x28, 0xf4, + 0xdd, 0x47, 0x45, 0xd8, 0x75, 0xfe, 0x6e, 0x20, 0xfb, 0x65, 0x55, 0x6d, + 0x06, 0x69, 0x64, 0x32, 0xec, 0xff, 0xd5, 0x5b, 0x33, 0x49, 0x40, 0xc6, + 0xe2, 0x3c, 0x90, 0x3f, 0x0a, 0xa4, 0xa1, 0x33, 0x5f, 0x73, 0x94, 0xc5, + 0x50, 0x70, 0x58, 0x6b, 0xaa, 0xc8, 0x6c, 0x38, 0xcc, 0x19, 0x8e, 0xba, + 0xf1, 0x54, 0x01, 0x25, 0x95, 0x28, 0xc5, 0x51, 0x92, 0xe9, 0x29, 0x8d, + 0x2a, 0x0c, 0x89, 0x14, 0xda, 0xf2, 0xad, 0x00, 0x25, 0x9f, 0xe7, 0x25, + 0x55, 0xc3, 0xc0, 0x44, 0x2e, 0x38, 0xc1, 0xe6, 0xe5, 0x02, 0x09, 0x28, + 0xc6, 0xe6, 0x57, 0x1a, 0x0a, 0x98, 0xf6, 0xf4, 0x85, 0xe4, 0x37, 0x91, + 0xae, 0x8a, 0xaa, 0xb1, 0x80, 0x46, 0x1f, 0xa4 +}; +/* K = 04bfe51616f5c244d2e01648362f5bbe5fa73501 */ +static const uint8_t ac_dsa_vect15_out[] = { +/* R */ + 0x29, 0xb7, 0xc0, 0xf9, 0x0d, 0x62, 0x4f, 0x8d, 0x58, 0x7e, 0xfd, 0x3f, + 0x49, 0xf9, 0x7d, 0xa7, 0x0f, 0x6e, 0x63, 0xe7, +/* S */ + 0x22, 0x2a, 0x3d, 0x9f, 0xfc, 0xa0, 0xdc, 0xf5, 0x79, 0x37, 0xe8, 0x9c, + 0x92, 0x53, 0x8e, 0x32, 0xe7, 0xa8, 0x68, 0x0f +}; +/* [mod = L=1024, N=160, SHA-224] */ +static const uint8_t ac_dsa_vect16_prime[] = { +/* P */ + 0x8b, 0x9b, 0x32, 0xf5, 0xba, 0x38, 0xfa, 0xad, 0x5e, 0x0d, 0x50, 0x6e, + 0xb5, 0x55, 0x54, 0x0d, 0x0d, 0x79, 0x63, 0x19, 0x55, 0x58, 0xca, 0x30, + 0x8b, 0x74, 0x66, 0x22, 0x8d, 0x92, 0xa1, 0x7b, 0x3b, 0x14, 0xb8, 0xe0, + 0xab, 0x77, 0xa9, 0xf3, 0xb2, 0x95, 0x9a, 0x09, 0x84, 0x8a, 0xa6, 0x9f, + 0x8d, 0xf9, 0x2c, 0xd9, 0xe9, 0xed, 0xef, 0x0a, 0xdf, 0x79, 0x2c, 0xe7, + 0x7b, 0xfc, 0xec, 0xca, 0xdd, 0x93, 0x52, 0x70, 0x0c, 0xa5, 0xfa, 0xec, + 0xf1, 0x81, 0xfa, 0x0c, 0x32, 0x6d, 0xb1, 0xd6, 0xe5, 0xd3, 0x52, 0x45, + 0x80, 0x11, 0xe5, 0x1b, 0xd3, 0x24, 0x8f, 0x4e, 0x3b, 0xd7, 0xc8, 0x20, + 0xd7, 0xe0, 0xa8, 0x19, 0x32, 0xac, 0xa1, 0xeb, 0xa3, 0x90, 0x17, 0x5e, + 0x53, 0xea, 0xda, 0x19, 0x72, 0x23, 0x67, 0x4e, 0x39, 0x00, 0x26, 0x3e, + 0x90, 0xf7, 0x2d, 0x94, 0xe7, 0x44, 0x7b, 0xff +}; +static const uint8_t ac_dsa_vect16_sub_prime[] = { +/* Q */ + 0xbc, 0x55, 0x0e, 0x96, 0x56, 0x47, 0xfb, 0x3a, 0x20, 0xf2, 0x45, 0xec, + 0x84, 0x75, 0x62, 0x4a, 0xbb, 0xb2, 0x6e, 0xdd +}; +static const uint8_t ac_dsa_vect16_base[] = { +/* G */ + 0x11, 0x33, 0x3a, 0x93, 0x1f, 0xba, 0x50, 0x34, 0x87, 0x77, 0x73, 0x76, + 0x85, 0x9f, 0xdc, 0x12, 0xf7, 0xc6, 0x87, 0xb0, 0x94, 0x8a, 0xe8, 0x89, + 0xd2, 0x87, 0xf1, 0xb7, 0xa7, 0x12, 0xad, 0x22, 0x0a, 0xe4, 0xf1, 0xce, + 0x37, 0x9d, 0x0d, 0xbb, 0x5c, 0x9a, 0xbf, 0x41, 0x96, 0x21, 0xf0, 0x05, + 0xfc, 0x12, 0x3c, 0x32, 0x7e, 0x50, 0x55, 0xd1, 0x85, 0x06, 0x34, 0xc3, + 0x6d, 0x39, 0x7e, 0x68, 0x9e, 0x11, 0x1d, 0x59, 0x8c, 0x1c, 0x36, 0x36, + 0xb9, 0x40, 0xc8, 0x4f, 0x42, 0xf4, 0x36, 0x84, 0x6e, 0x8e, 0x7f, 0xca, + 0xd9, 0x01, 0x2c, 0xed, 0xa3, 0x98, 0x72, 0x0f, 0x32, 0xff, 0xfd, 0x1a, + 0x45, 0xab, 0x61, 0x36, 0xce, 0x41, 0x70, 0x69, 0x20, 0x7a, 0xc1, 0x40, + 0x67, 0x5b, 0x8f, 0x86, 0xdd, 0x06, 0x39, 0x15, 0xae, 0x6f, 0x62, 0xb0, + 0xce, 0xc7, 0x29, 0xfb, 0xd5, 0x09, 0xac, 0x17 +}; +static const uint8_t ac_dsa_vect16_ptx[] = { +/* Msg */ + 0xfb, 0x21, 0x28, 0x05, 0x25, 0x09, 0x48, 0x8c, 0xad, 0x07, 0x45, 0xed, + 0x3e, 0x63, 0x12, 0x85, 0x0d, 0xd9, 0x6d, 0xda, 0xf7, 0x91, 0xf1, 0xe6, + 0x24, 0xe2, 0x2a, 0x6b, 0x9b, 0xea, 0xa6, 0x53, 0x19, 0xc3, 0x25, 0xc7, + 0x8e, 0xf5, 0x9c, 0xac, 0xba, 0x0c, 0xcf, 0xa7, 0x22, 0x25, 0x9f, 0x24, + 0xf9, 0x2c, 0x17, 0xb7, 0x7a, 0x8f, 0x6d, 0x8e, 0x97, 0xc9, 0x3d, 0x88, + 0x0d, 0x2d, 0x8d, 0xbb, 0xbe, 0xdc, 0xf6, 0xac, 0xef, 0xa0, 0x6b, 0x0e, + 0x47, 0x6c, 0xa2, 0x01, 0x3d, 0x03, 0x94, 0xbd, 0x90, 0xd5, 0x6c, 0x10, + 0x62, 0x6e, 0xf4, 0x3c, 0xea, 0x79, 0xd1, 0xef, 0x0b, 0xc7, 0xac, 0x45, + 0x2b, 0xf9, 0xb9, 0xac, 0xae, 0xf7, 0x03, 0x25, 0xe0, 0x55, 0xac, 0x00, + 0x6d, 0x34, 0x02, 0x4b, 0x32, 0x20, 0x4a, 0xbe, 0xa4, 0xbe, 0x5f, 0xaa, + 0xe0, 0xa6, 0xd4, 0x6d, 0x36, 0x5e, 0xd0, 0xd9 +}; +static const uint8_t ac_dsa_vect16_priv_val[] = { +/* X */ + 0x6e, 0x2e, 0x31, 0xbb, 0xfc, 0x67, 0x09, 0x44, 0xd7, 0xa7, 0x12, 0x0e, + 0x39, 0xa9, 0x81, 0x52, 0x06, 0x14, 0xd8, 0xa8 +}; +static const uint8_t ac_dsa_vect16_pub_val[] = { +/* Y */ + 0x7e, 0x33, 0x9f, 0x37, 0x57, 0x45, 0x03, 0x90, 0x16, 0x0e, 0x02, 0x29, + 0x15, 0x59, 0xf3, 0x0b, 0xed, 0x0b, 0x2d, 0x75, 0x8c, 0x5c, 0xcc, 0x2d, + 0x8d, 0x45, 0x62, 0x32, 0xbb, 0x43, 0x5a, 0xe4, 0x9d, 0xe7, 0xe7, 0x95, + 0x7e, 0x3a, 0xad, 0x9b, 0xfd, 0xcf, 0x6f, 0xd5, 0xd9, 0xb6, 0xee, 0x3b, + 0x52, 0x1b, 0xc2, 0x22, 0x9a, 0x84, 0x21, 0xdc, 0x2a, 0xa5, 0x9b, 0x99, + 0x52, 0x34, 0x5a, 0x8f, 0xc1, 0xde, 0x49, 0xb3, 0x48, 0x00, 0x3a, 0x9b, + 0x18, 0xda, 0x64, 0x2d, 0x7f, 0x6f, 0x56, 0xe3, 0xbc, 0x66, 0x51, 0x31, + 0xae, 0x97, 0x62, 0x08, 0x8a, 0x93, 0x78, 0x6f, 0x7b, 0x4b, 0x72, 0xa4, + 0xbc, 0xc3, 0x08, 0xc6, 0x7e, 0x25, 0x32, 0xa3, 0xa5, 0xbf, 0x09, 0x65, + 0x20, 0x55, 0xcc, 0x26, 0xbf, 0x3b, 0x18, 0x83, 0x35, 0x98, 0xcf, 0xfd, + 0x70, 0x11, 0xf2, 0x28, 0x5f, 0x79, 0x45, 0x57 +}; +/* K = 8cb35d255505a4c41421e562d10827266aa68663 */ +static const uint8_t ac_dsa_vect16_out[] = { +/* R */ + 0xaf, 0xee, 0x71, 0x9e, 0x7f, 0x84, 0x8b, 0x54, 0x34, 0x9c, 0xcc, 0x3b, + 0x4f, 0xb2, 0x60, 0x65, 0x83, 0x3a, 0x4d, 0x8e, +/* S */ + 0x73, 0x4e, 0xfe, 0x99, 0x22, 0x56, 0xf3, 0x13, 0x25, 0xe7, 0x49, 0xbc, + 0x32, 0xa2, 0x4a, 0x1f, 0x95, 0x7b, 0x3a, 0x1b +}; +#define ac_dsa_vect17_prime ac_dsa_vect16_prime +#define ac_dsa_vect17_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect17_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect17_ptx[] = { +/* Msg */ + 0x02, 0x97, 0x1e, 0x0c, 0xdd, 0x48, 0xae, 0x23, 0x31, 0xdb, 0x9c, 0x62, + 0x85, 0xe9, 0x88, 0x0e, 0x96, 0x10, 0x4f, 0xa7, 0xa9, 0xf3, 0x78, 0xdf, + 0xea, 0x71, 0x8e, 0x63, 0xef, 0xe9, 0x83, 0x52, 0xfe, 0x4d, 0x35, 0xa2, + 0xbc, 0x94, 0xb3, 0xa8, 0x88, 0xcf, 0xb8, 0x8b, 0x8b, 0x7d, 0x9f, 0x6c, + 0x8c, 0x54, 0xe4, 0x86, 0x13, 0xf3, 0x2c, 0x99, 0x46, 0xff, 0xe6, 0xe9, + 0xa4, 0xb7, 0x10, 0x8e, 0xce, 0xcd, 0xda, 0x41, 0xbc, 0x15, 0x1b, 0x3d, + 0x87, 0x24, 0xb6, 0x1f, 0x5b, 0x83, 0xa4, 0xe2, 0x74, 0x76, 0x91, 0x43, + 0x87, 0xb0, 0x48, 0x8e, 0x41, 0xbe, 0x54, 0xf6, 0x3a, 0xa7, 0x73, 0x17, + 0x5e, 0xb3, 0x73, 0xa3, 0x64, 0x1e, 0x6e, 0x79, 0x50, 0xee, 0xe8, 0xfa, + 0xf0, 0x48, 0xa8, 0x41, 0xf1, 0x07, 0xd3, 0x0c, 0xf9, 0xbe, 0x26, 0x84, + 0x93, 0x23, 0x15, 0x45, 0xd8, 0x98, 0x46, 0x94 +}; +static const uint8_t ac_dsa_vect17_priv_val[] = { +/* X */ + 0x0b, 0x44, 0x8f, 0x49, 0xa0, 0x85, 0xa5, 0x2a, 0x03, 0xd7, 0xf6, 0x68, + 0xa1, 0xd6, 0xfb, 0x87, 0xf2, 0xe2, 0x21, 0xac +}; +static const uint8_t ac_dsa_vect17_pub_val[] = { +/* Y */ + 0x63, 0x3b, 0xb7, 0x57, 0xb3, 0xc0, 0xe3, 0xb7, 0x86, 0x7b, 0xf8, 0x45, + 0x30, 0x1e, 0xa4, 0xe3, 0x9f, 0x75, 0xc9, 0x75, 0x9c, 0x22, 0x3f, 0x46, + 0xce, 0x26, 0x6d, 0x40, 0x6b, 0x9d, 0xf5, 0xdb, 0x50, 0x1f, 0xb8, 0x26, + 0xb6, 0xe6, 0x1c, 0xba, 0x61, 0x04, 0xc6, 0x04, 0x45, 0x8c, 0x90, 0x79, + 0x9f, 0x2a, 0x36, 0xab, 0x51, 0x16, 0x6d, 0x0e, 0x83, 0xb7, 0x70, 0x84, + 0x06, 0x24, 0xfe, 0xdc, 0x35, 0xeb, 0xfb, 0x98, 0x53, 0x41, 0x9e, 0x7e, + 0x09, 0xb3, 0x2b, 0x4b, 0xd6, 0x52, 0xda, 0x4f, 0x1c, 0xe9, 0x73, 0xac, + 0x26, 0x20, 0xc9, 0x66, 0xb6, 0x1e, 0x35, 0xa3, 0xf2, 0x16, 0x43, 0x9a, + 0x8d, 0xe1, 0xa1, 0x04, 0xf1, 0x72, 0xe1, 0xb6, 0xe2, 0x87, 0x81, 0x12, + 0xa6, 0x6c, 0x34, 0xd1, 0x6a, 0x9a, 0xef, 0x3a, 0xc2, 0x4a, 0x34, 0xaf, + 0x5e, 0xdb, 0xf3, 0x98, 0x18, 0xa3, 0xe2, 0xef +}; +/* K = 4481a4be9db6821e3b0a08c9c82603631971a682 */ +static const uint8_t ac_dsa_vect17_out[] = { +/* R */ + 0x92, 0xc6, 0x5e, 0x07, 0x46, 0x2d, 0x66, 0x8b, 0x06, 0xdd, 0x45, 0xb6, + 0x08, 0x78, 0x49, 0x65, 0x89, 0x78, 0x38, 0xbc, +/* S */ + 0x2e, 0x40, 0xad, 0xf4, 0x1c, 0xaf, 0xb8, 0x04, 0x8c, 0x79, 0x3c, 0x70, + 0x92, 0xa7, 0xe8, 0x23, 0x51, 0x5b, 0x6c, 0xfa +}; +#define ac_dsa_vect18_prime ac_dsa_vect16_prime +#define ac_dsa_vect18_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect18_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect18_ptx[] = { +/* Msg */ + 0x06, 0x2e, 0x82, 0xfb, 0x43, 0x23, 0x6e, 0xe1, 0x7e, 0xbf, 0xaa, 0x3d, + 0x36, 0x3b, 0x9b, 0x87, 0x3d, 0x0f, 0xe4, 0x14, 0x44, 0xc7, 0x4c, 0xef, + 0x7f, 0x7e, 0x3b, 0xd8, 0x1f, 0x72, 0x3f, 0xd9, 0x0f, 0xd1, 0x48, 0xa2, + 0x8e, 0x99, 0x75, 0x85, 0x41, 0x36, 0x95, 0x11, 0x37, 0x57, 0x75, 0x8a, + 0xa4, 0xdd, 0x27, 0x5f, 0x70, 0xb3, 0x75, 0xf8, 0x90, 0x3c, 0x7b, 0xe4, + 0x6e, 0x3a, 0x3a, 0xd3, 0x19, 0x0c, 0xd0, 0x49, 0x71, 0xab, 0xd2, 0xf1, + 0xdb, 0x19, 0x2e, 0xf0, 0xd2, 0xb9, 0x8b, 0xbb, 0x80, 0x18, 0x1a, 0x72, + 0x1a, 0x58, 0x09, 0x92, 0x8b, 0x5b, 0xca, 0x5c, 0x11, 0x8a, 0x29, 0x11, + 0x13, 0x2a, 0xd2, 0x33, 0xcd, 0x27, 0xc7, 0xe4, 0x1a, 0xdf, 0xcc, 0xfe, + 0xb4, 0xe9, 0x52, 0x87, 0x4b, 0xfa, 0x81, 0x96, 0x61, 0x18, 0x29, 0x75, + 0xe4, 0x4d, 0x37, 0xc6, 0x17, 0x34, 0x75, 0x9c +}; +static const uint8_t ac_dsa_vect18_priv_val[] = { +/* X */ + 0xa4, 0xa2, 0x5a, 0x8b, 0xb1, 0xc2, 0xba, 0x69, 0xf9, 0x61, 0x19, 0x39, + 0xb5, 0x91, 0x03, 0x2b, 0x96, 0x33, 0x3f, 0xa3 +}; +static const uint8_t ac_dsa_vect18_pub_val[] = { +/* Y */ + 0x3b, 0x0a, 0x09, 0x1d, 0xfc, 0xa0, 0x5d, 0xce, 0x61, 0xe9, 0xf0, 0x5b, + 0x15, 0xb0, 0x74, 0x87, 0xd2, 0xe3, 0xea, 0x4f, 0x56, 0x8d, 0xc9, 0xac, + 0x75, 0x2d, 0x42, 0xc0, 0xaa, 0x77, 0x1a, 0xe0, 0xcc, 0xc3, 0x72, 0xce, + 0x97, 0x74, 0xfb, 0x9f, 0xd1, 0x6a, 0x30, 0xcb, 0x37, 0x59, 0xbb, 0x19, + 0x89, 0x48, 0x8c, 0xe8, 0x5d, 0xb7, 0xcd, 0xfa, 0x50, 0x64, 0x76, 0xac, + 0xec, 0x64, 0x4c, 0x21, 0x16, 0x8f, 0x2d, 0xb1, 0xf3, 0x6e, 0xfe, 0x02, + 0x30, 0xc6, 0xfb, 0x8f, 0x1f, 0x2a, 0xe4, 0xea, 0xf1, 0x79, 0x9d, 0x5e, + 0x29, 0xe2, 0x12, 0x46, 0x7b, 0x11, 0xbf, 0xbc, 0x1e, 0xeb, 0xed, 0x14, + 0x2d, 0x7a, 0x01, 0x72, 0x62, 0xcd, 0x87, 0x35, 0xe3, 0xe2, 0x9d, 0x8e, + 0x0c, 0x4a, 0x6e, 0x76, 0x6c, 0x07, 0xd7, 0xaa, 0x9f, 0x8d, 0x17, 0x6f, + 0x53, 0x60, 0x87, 0xbf, 0xec, 0xf4, 0xc4, 0x14 +}; +/* K = a7135820910f041b27321534a17bb1f33ac51aca */ +static const uint8_t ac_dsa_vect18_out[] = { +/* R */ + 0xba, 0x55, 0x41, 0x24, 0x87, 0x4d, 0x06, 0xa6, 0xce, 0xf6, 0x27, 0x40, + 0xe1, 0x58, 0x21, 0xcc, 0xdd, 0xbf, 0xe6, 0xf3, +/* S */ + 0x59, 0x62, 0xbe, 0x75, 0x7d, 0x75, 0xb0, 0xf1, 0x7d, 0x15, 0x48, 0x2e, + 0xbb, 0x59, 0x5c, 0xa4, 0xe9, 0xfb, 0xfe, 0x22 +}; +#define ac_dsa_vect19_prime ac_dsa_vect16_prime +#define ac_dsa_vect19_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect19_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect19_ptx[] = { +/* Msg */ + 0x4f, 0xca, 0x07, 0x48, 0x44, 0xea, 0xe2, 0x47, 0xd1, 0x9c, 0x06, 0xe9, + 0x20, 0x32, 0xae, 0x8e, 0x77, 0x30, 0x43, 0xe2, 0xe1, 0xf4, 0x5d, 0x40, + 0x0e, 0x9d, 0xce, 0xbb, 0xde, 0x5d, 0x65, 0xe7, 0xc1, 0x42, 0x3b, 0x03, + 0x90, 0x16, 0x19, 0x91, 0xc0, 0x26, 0xf3, 0x8a, 0x0e, 0x2b, 0xfe, 0xef, + 0x40, 0xda, 0xe1, 0x87, 0x41, 0x73, 0x7b, 0x1d, 0x53, 0x5a, 0xb4, 0x6b, + 0x56, 0x6a, 0x1b, 0x67, 0x2f, 0xc2, 0x2d, 0xec, 0x86, 0x74, 0x7a, 0x7c, + 0x76, 0x38, 0xfa, 0x65, 0x04, 0x7f, 0x1e, 0xde, 0x36, 0xad, 0x43, 0xf6, + 0xae, 0xdf, 0x51, 0xb5, 0xbf, 0x29, 0x79, 0xad, 0xf4, 0xd9, 0xa9, 0x4e, + 0xd8, 0x02, 0xa2, 0x9d, 0xe5, 0x60, 0x3b, 0x70, 0x47, 0x70, 0xb3, 0x2c, + 0x8b, 0x94, 0x6a, 0x32, 0xe1, 0xb6, 0x05, 0x4c, 0xd7, 0x0c, 0x3a, 0xdd, + 0x02, 0x5c, 0xc9, 0x37, 0x1d, 0x1e, 0x40, 0x4d +}; +static const uint8_t ac_dsa_vect19_priv_val[] = { +/* X */ + 0x1f, 0x15, 0xca, 0xfc, 0xa2, 0x82, 0x08, 0x3e, 0x82, 0xd7, 0xe5, 0x42, + 0x58, 0x64, 0x7b, 0x29, 0x14, 0x41, 0x89, 0x86 +}; +static const uint8_t ac_dsa_vect19_pub_val[] = { +/* Y */ + 0x40, 0xb6, 0x38, 0xc9, 0x4b, 0x1e, 0x71, 0x9a, 0x33, 0x7d, 0x83, 0x35, + 0x86, 0x99, 0xc7, 0x0c, 0xd8, 0x67, 0xff, 0x88, 0x8c, 0x65, 0x5a, 0x5f, + 0x5a, 0x1d, 0xe8, 0x73, 0x2d, 0x05, 0x8b, 0xf0, 0x27, 0xd4, 0x74, 0x7e, + 0xfe, 0x3b, 0x8d, 0xed, 0xca, 0x32, 0x76, 0xde, 0x5a, 0x58, 0xf1, 0x36, + 0xed, 0x35, 0xcf, 0xf0, 0x30, 0x30, 0xf6, 0x72, 0xda, 0x65, 0xc7, 0x1f, + 0x18, 0xe5, 0x82, 0x78, 0xdd, 0xfc, 0x7b, 0x9b, 0x50, 0xa2, 0x48, 0xef, + 0xf9, 0x23, 0x68, 0x74, 0xee, 0x3c, 0xb0, 0xd0, 0xa3, 0x5b, 0x7b, 0x2e, + 0xe1, 0x85, 0xb1, 0x39, 0xea, 0x84, 0xee, 0xd7, 0xbf, 0xfc, 0x50, 0x94, + 0xab, 0x87, 0x43, 0xa7, 0x53, 0x74, 0xbc, 0x36, 0xc7, 0xd6, 0x9d, 0x5f, + 0x3e, 0x6f, 0xe5, 0xf3, 0xef, 0x1f, 0x93, 0x58, 0xf0, 0x0a, 0x3c, 0x58, + 0x92, 0xff, 0xf4, 0x1e, 0xd6, 0xaf, 0xee, 0x3b +}; +/* K = 128ab9677c7ade5e1c02a8427650ff054db6390e */ +static const uint8_t ac_dsa_vect19_out[] = { +/* R */ + 0x65, 0x1a, 0x38, 0x9d, 0x8c, 0xa5, 0x0d, 0x6e, 0x32, 0x73, 0xca, 0xbb, + 0xe7, 0x1c, 0xd8, 0x4c, 0xcc, 0xd0, 0x23, 0x61, +/* S */ + 0x34, 0x01, 0xfe, 0x47, 0xb3, 0x81, 0x2d, 0xaa, 0x8c, 0x02, 0x0c, 0x9b, + 0xd4, 0x26, 0x09, 0xcb, 0xeb, 0xdf, 0xa7, 0x28 +}; +#define ac_dsa_vect20_prime ac_dsa_vect16_prime +#define ac_dsa_vect20_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect20_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect20_ptx[] = { +/* Msg */ + 0x4d, 0x96, 0x30, 0xfe, 0x05, 0x89, 0x98, 0xca, 0x5b, 0x80, 0xae, 0x62, + 0xf3, 0xf7, 0x3d, 0xc8, 0x5b, 0xee, 0x29, 0x15, 0x09, 0x84, 0x3a, 0xc0, + 0x02, 0x40, 0xd1, 0x3d, 0x55, 0x25, 0x1a, 0xe5, 0x3b, 0x37, 0x79, 0x47, + 0x83, 0xb9, 0x7d, 0x53, 0xe0, 0x42, 0xca, 0xb2, 0x6f, 0x8c, 0x84, 0xde, + 0x0a, 0x70, 0xf5, 0xb4, 0x30, 0x51, 0xfb, 0xef, 0xb3, 0xe4, 0x3f, 0x08, + 0xf5, 0xd2, 0xe8, 0xaa, 0xd9, 0xe2, 0xde, 0x27, 0x17, 0x41, 0x2d, 0xbb, + 0x90, 0x2a, 0xcc, 0x88, 0x49, 0xad, 0xc0, 0x4d, 0x06, 0xfe, 0xd8, 0xc1, + 0x42, 0x1c, 0x4c, 0xfe, 0x8b, 0x81, 0xee, 0x7f, 0x5a, 0xc5, 0xd4, 0xf0, + 0xc0, 0xb6, 0x8e, 0x80, 0xb6, 0xf8, 0x8f, 0xd3, 0xc7, 0xd5, 0xb3, 0x20, + 0x22, 0x57, 0x2b, 0x0a, 0x68, 0x1b, 0xd2, 0xd4, 0xdf, 0x2d, 0x04, 0x7b, + 0x0b, 0x23, 0xb6, 0x88, 0x71, 0x45, 0xaf, 0xe1 +}; +static const uint8_t ac_dsa_vect20_priv_val[] = { +/* X */ + 0x14, 0x85, 0xf7, 0x19, 0xb8, 0xbe, 0x77, 0xc7, 0x88, 0x29, 0xba, 0xa0, + 0xd2, 0xc3, 0x22, 0xdf, 0x60, 0x17, 0x44, 0x76 +}; +static const uint8_t ac_dsa_vect20_pub_val[] = { +/* Y */ + 0x72, 0x7b, 0x65, 0x28, 0x35, 0x7d, 0x67, 0x05, 0xc2, 0x0d, 0x31, 0x35, + 0x8f, 0x64, 0x19, 0x34, 0xfd, 0xec, 0x63, 0xcc, 0x66, 0xdf, 0x98, 0x83, + 0x7d, 0x2f, 0x37, 0x81, 0x64, 0xe1, 0x5f, 0xa0, 0x84, 0x22, 0x07, 0xac, + 0xf3, 0x22, 0x0c, 0x80, 0x23, 0xa9, 0xf4, 0xf8, 0xd2, 0x05, 0x71, 0x65, + 0xb3, 0xc8, 0x49, 0xea, 0xeb, 0x53, 0x76, 0xe3, 0xfa, 0xd1, 0x17, 0x85, + 0xf1, 0xd0, 0x26, 0x17, 0x79, 0xaa, 0xed, 0xd5, 0x3b, 0x1e, 0x52, 0x79, + 0x80, 0x07, 0xeb, 0x4c, 0x8e, 0x83, 0xb1, 0xff, 0x32, 0x1b, 0x62, 0x0d, + 0x88, 0x33, 0x91, 0xa1, 0x4f, 0xa4, 0x7f, 0xec, 0x49, 0x01, 0xd9, 0x6e, + 0xc2, 0x32, 0xea, 0xbb, 0x4a, 0x0b, 0xb4, 0x45, 0x33, 0x68, 0xfe, 0xf5, + 0x17, 0x6c, 0x67, 0x13, 0x56, 0x49, 0x97, 0x9d, 0x32, 0x14, 0xd3, 0xfb, + 0x67, 0xa1, 0x31, 0x9a, 0xc5, 0x4f, 0xeb, 0x01 +}; +/* K = 8f4cc1254c787ec8cbf54405105f7ef83ffdeee0 */ +static const uint8_t ac_dsa_vect20_out[] = { +/* R */ + 0x9c, 0xa3, 0xe4, 0x33, 0x50, 0x4c, 0x55, 0x7b, 0xa1, 0xaa, 0xc6, 0x64, + 0x69, 0x78, 0x11, 0x75, 0xcd, 0xfb, 0x4a, 0xd5, +/* S */ + 0x72, 0x14, 0x5d, 0xfa, 0x52, 0x79, 0xdd, 0x82, 0xae, 0x99, 0x60, 0x4d, + 0x16, 0xa2, 0xb8, 0xdf, 0x71, 0xb9, 0x53, 0x20 +}; +#define ac_dsa_vect21_prime ac_dsa_vect16_prime +#define ac_dsa_vect21_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect21_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect21_ptx[] = { +/* Msg */ + 0x62, 0xb9, 0xd6, 0x01, 0xe3, 0x0b, 0x42, 0xa2, 0x79, 0xc7, 0xe0, 0x4d, + 0xf3, 0xca, 0x8d, 0x81, 0x40, 0xa5, 0x5c, 0xd5, 0x87, 0x6c, 0x7e, 0x91, + 0x81, 0xc7, 0x35, 0x75, 0xe4, 0xc4, 0xf9, 0x21, 0xa9, 0x4e, 0x4e, 0x2d, + 0x0b, 0xdd, 0x7b, 0xa9, 0x86, 0x00, 0xd6, 0x52, 0xe5, 0xdf, 0x5b, 0xe9, + 0x46, 0x4e, 0x7a, 0x90, 0x11, 0xab, 0x48, 0x69, 0x60, 0xf6, 0x9d, 0x57, + 0xec, 0xe1, 0xd2, 0xc4, 0xaf, 0x93, 0x24, 0x45, 0x7c, 0x1e, 0x3d, 0x83, + 0xfb, 0xa4, 0x26, 0x5b, 0xeb, 0x47, 0x40, 0x7e, 0x47, 0x61, 0xdb, 0xc9, + 0x49, 0xd5, 0xbd, 0x67, 0xfe, 0xe4, 0xa4, 0x76, 0xa4, 0xd5, 0xa9, 0x3d, + 0x77, 0xac, 0xda, 0x96, 0xa2, 0x21, 0xa0, 0xa3, 0x1e, 0x0f, 0x02, 0x4b, + 0x3f, 0x0b, 0x82, 0x34, 0xc0, 0x15, 0x23, 0x8f, 0x32, 0x58, 0xda, 0xa0, + 0x85, 0xae, 0x9f, 0x4e, 0x1a, 0xa7, 0xb1, 0xcc +}; +static const uint8_t ac_dsa_vect21_priv_val[] = { +/* X */ + 0x43, 0xc7, 0x6a, 0x9a, 0x00, 0x04, 0x5c, 0xdf, 0xb2, 0xe7, 0x92, 0x7b, + 0x5c, 0x87, 0x30, 0xe0, 0x06, 0x42, 0x3c, 0x05 +}; +static const uint8_t ac_dsa_vect21_pub_val[] = { +/* Y */ + 0x5f, 0x6d, 0xfb, 0x06, 0x4c, 0xad, 0xdf, 0x64, 0x4a, 0xf3, 0x99, 0xe3, + 0x3a, 0x67, 0x25, 0x65, 0x76, 0x67, 0x61, 0xd5, 0x5a, 0xc0, 0xb8, 0x4b, + 0xea, 0xd4, 0x2c, 0x39, 0x80, 0xe7, 0xe3, 0x96, 0x04, 0x37, 0x44, 0x36, + 0x17, 0x78, 0xf0, 0x4d, 0xcb, 0x69, 0x8e, 0x45, 0x63, 0x85, 0x34, 0x20, + 0xfe, 0xca, 0xcd, 0x59, 0x4a, 0xf8, 0x28, 0xf5, 0x7d, 0xf5, 0x41, 0xd9, + 0xe4, 0xde, 0x89, 0x9d, 0x61, 0xf0, 0x4f, 0x63, 0x79, 0xc1, 0xc9, 0x62, + 0x46, 0xd1, 0x52, 0x36, 0x93, 0x95, 0x24, 0x2a, 0x1c, 0x2e, 0x70, 0xee, + 0xf8, 0xf3, 0x54, 0x17, 0xa0, 0xff, 0xdb, 0x03, 0x92, 0x82, 0x51, 0x6c, + 0xe2, 0x1b, 0x85, 0x68, 0x79, 0x04, 0xc5, 0x11, 0x08, 0x7f, 0x11, 0x3e, + 0x51, 0x42, 0xf0, 0x27, 0xf1, 0x17, 0x97, 0x12, 0xed, 0xcb, 0xce, 0x27, + 0x93, 0x9a, 0xb1, 0x5e, 0xc4, 0x9c, 0x08, 0x5f +}; +/* K = 5e4b5e4595e31397422c7a4487ae51051289be61 */ +static const uint8_t ac_dsa_vect21_out[] = { +/* R */ + 0x33, 0x19, 0x20, 0xa7, 0xb7, 0x9e, 0x3c, 0xfa, 0x76, 0x38, 0xe4, 0x09, + 0xd9, 0x70, 0x2a, 0xaf, 0xd0, 0x8f, 0xbe, 0xc6, +/* S */ + 0x07, 0x1d, 0x06, 0xe6, 0xcd, 0x30, 0x15, 0x15, 0xf3, 0x7b, 0x60, 0x69, + 0x0a, 0xfa, 0x21, 0x9f, 0xe5, 0x08, 0x3d, 0x96 +}; +#define ac_dsa_vect22_prime ac_dsa_vect16_prime +#define ac_dsa_vect22_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect22_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect22_ptx[] = { +/* Msg */ + 0x00, 0x06, 0xe0, 0x9c, 0x20, 0x37, 0x64, 0x42, 0xe6, 0x89, 0xbf, 0x2d, + 0x34, 0x26, 0x8f, 0xd6, 0x91, 0x09, 0xc1, 0x30, 0x1e, 0xa6, 0x6c, 0xbe, + 0x90, 0x39, 0x4c, 0xc0, 0xf4, 0x1f, 0x94, 0x82, 0x2c, 0x28, 0x84, 0x58, + 0x19, 0xb9, 0xa9, 0x87, 0x64, 0xd2, 0xf7, 0x26, 0x2e, 0x98, 0x89, 0x14, + 0x87, 0xff, 0x55, 0xb0, 0x5b, 0xd6, 0x9e, 0x18, 0xb7, 0xca, 0xd4, 0x1b, + 0xd9, 0x8e, 0x13, 0x75, 0x66, 0xb6, 0x04, 0x1c, 0x73, 0x9d, 0xb1, 0x1f, + 0x78, 0xe5, 0x67, 0xca, 0xc0, 0x2f, 0x33, 0xf1, 0x40, 0xd1, 0x9a, 0x48, + 0x05, 0x00, 0x25, 0x45, 0x37, 0x5d, 0xae, 0xbf, 0xd7, 0xdc, 0xbe, 0xa3, + 0x32, 0x42, 0xe7, 0x3c, 0x8e, 0x26, 0x91, 0x49, 0xd7, 0xeb, 0x9d, 0xb9, + 0xf9, 0x00, 0x6e, 0x17, 0xac, 0xb7, 0x36, 0xb5, 0xe9, 0x77, 0x64, 0x5a, + 0xb6, 0x51, 0xb8, 0x12, 0x25, 0xc5, 0xe5, 0x43 +}; +static const uint8_t ac_dsa_vect22_priv_val[] = { +/* X */ + 0x16, 0xf8, 0x9d, 0x97, 0xdd, 0x3b, 0x31, 0xc1, 0x91, 0x49, 0x51, 0x73, + 0xae, 0x0e, 0x14, 0x5c, 0x6c, 0xe1, 0x85, 0xd6 +}; +static const uint8_t ac_dsa_vect22_pub_val[] = { +/* Y */ + 0x1b, 0x1f, 0x72, 0x56, 0x64, 0xd7, 0x5b, 0xdc, 0xb2, 0xa5, 0xa4, 0xc6, + 0x53, 0x06, 0x1c, 0x46, 0x07, 0x99, 0xdd, 0x48, 0xbf, 0x1e, 0x6b, 0x03, + 0xe1, 0x3c, 0x71, 0xd8, 0x3e, 0x3f, 0xdb, 0x50, 0x6f, 0xa9, 0x4e, 0x6c, + 0xaf, 0xb5, 0xdb, 0xde, 0xad, 0x88, 0xa3, 0x3d, 0x23, 0xd4, 0xe9, 0x28, + 0x7b, 0x47, 0x07, 0xe1, 0xfb, 0xa8, 0x71, 0xb9, 0x7c, 0x9a, 0x48, 0xf9, + 0x30, 0xcd, 0xcc, 0xba, 0x0d, 0xc0, 0x6a, 0x4f, 0x0a, 0x8b, 0xfb, 0xb4, + 0xe1, 0x4d, 0x0b, 0x4d, 0x5a, 0x08, 0x71, 0xfa, 0x13, 0x41, 0xca, 0xec, + 0x7b, 0xc0, 0x81, 0x38, 0x71, 0x31, 0x21, 0xd4, 0x19, 0x76, 0x9f, 0x31, + 0x20, 0x35, 0x08, 0xdf, 0x71, 0x94, 0x72, 0x65, 0x64, 0x4f, 0xdc, 0x61, + 0x37, 0xd8, 0xe4, 0x66, 0xc8, 0xcb, 0x0c, 0xe9, 0x85, 0x34, 0x0c, 0xb2, + 0xe2, 0x79, 0xb4, 0xce, 0x93, 0x15, 0xa7, 0x72 +}; +/* K = 475b5aa12ff77d49e4c8171f80d3d1f15147ed12 */ +static const uint8_t ac_dsa_vect22_out[] = { +/* R */ + 0xb6, 0xaa, 0x83, 0x3b, 0x82, 0x51, 0x84, 0x72, 0x9a, 0xf3, 0x08, 0xf8, + 0x1b, 0xf5, 0xe5, 0x8e, 0x2d, 0x7e, 0x92, 0x84, +/* S */ + 0x54, 0x53, 0xb4, 0xb2, 0xe3, 0xfc, 0x80, 0x2b, 0x2f, 0x97, 0x7d, 0x0c, + 0xf6, 0xeb, 0x7f, 0x5c, 0x16, 0x67, 0x3f, 0xa3 +}; +#define ac_dsa_vect23_prime ac_dsa_vect16_prime +#define ac_dsa_vect23_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect23_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect23_ptx[] = { +/* Msg */ + 0xe0, 0x4a, 0x71, 0xf2, 0xb5, 0xc1, 0x76, 0xa0, 0xdb, 0x17, 0xa9, 0x83, + 0xa1, 0x7d, 0xec, 0x58, 0x8c, 0x00, 0xf4, 0x2c, 0x9a, 0xa3, 0x02, 0x6b, + 0x5e, 0xb4, 0x40, 0xf0, 0x7a, 0x21, 0x40, 0xc2, 0xed, 0x84, 0x02, 0x4e, + 0x05, 0x31, 0xea, 0x77, 0x88, 0xdf, 0xea, 0xa9, 0x18, 0x83, 0xfb, 0x6a, + 0x98, 0x41, 0xc1, 0x7d, 0xcf, 0xd3, 0x12, 0x96, 0x8a, 0xdb, 0x00, 0xe5, + 0x56, 0xbc, 0x7e, 0xb3, 0x02, 0x1f, 0x57, 0xb7, 0xa1, 0x68, 0x94, 0xfa, + 0x4f, 0xe1, 0x2e, 0xc9, 0x3d, 0xfd, 0x49, 0x4a, 0x0a, 0x1c, 0x69, 0x3d, + 0x6a, 0xde, 0x15, 0x4e, 0xf6, 0x48, 0xc0, 0x55, 0x52, 0xda, 0x41, 0x22, + 0x4d, 0x49, 0x22, 0xd1, 0x86, 0x1d, 0x9f, 0x76, 0x71, 0xb8, 0xce, 0x6c, + 0xe4, 0x48, 0xe8, 0x95, 0xea, 0x0e, 0xed, 0x25, 0x80, 0x2e, 0x33, 0x50, + 0xec, 0x08, 0xae, 0x79, 0xf2, 0xd6, 0x1e, 0x0f +}; +static const uint8_t ac_dsa_vect23_priv_val[] = { +/* X */ + 0x3e, 0xda, 0x44, 0xe3, 0xc3, 0x83, 0x80, 0xdf, 0x7a, 0x4f, 0x47, 0xd8, + 0xe1, 0x02, 0x45, 0x96, 0x23, 0x8b, 0xce, 0xf1 +}; +static const uint8_t ac_dsa_vect23_pub_val[] = { +/* Y */ + 0x68, 0x7e, 0x16, 0x30, 0x9b, 0x06, 0x81, 0x7b, 0x93, 0x23, 0x6d, 0xd9, + 0x90, 0xfa, 0xef, 0x9e, 0x23, 0x2e, 0xb8, 0x1c, 0xb9, 0xc7, 0xd6, 0xda, + 0xe4, 0xfd, 0xd4, 0xf8, 0xe7, 0xca, 0x93, 0x3e, 0x18, 0x5b, 0x1d, 0xa6, + 0x22, 0xd7, 0xc7, 0xfa, 0x35, 0xe0, 0xa3, 0x90, 0x6f, 0x91, 0x5d, 0xed, + 0x14, 0xba, 0x96, 0xd6, 0x03, 0x5b, 0x46, 0xbd, 0x6c, 0xa5, 0xfe, 0x17, + 0x2a, 0xf9, 0x4e, 0x08, 0x1f, 0xb0, 0xb9, 0xa9, 0x58, 0x3a, 0x45, 0x8b, + 0xd2, 0x06, 0xc1, 0xe8, 0x7f, 0x97, 0xa5, 0x7d, 0x00, 0xd6, 0xea, 0xde, + 0x19, 0xec, 0x56, 0xac, 0x2e, 0x9b, 0xbd, 0x8c, 0x15, 0xdf, 0x35, 0x6e, + 0xe7, 0xb1, 0x2c, 0x91, 0x31, 0x1a, 0x38, 0xfc, 0x33, 0x15, 0xcf, 0xde, + 0x9f, 0xf4, 0x62, 0xca, 0x6a, 0xdf, 0xf2, 0x80, 0x8b, 0x3f, 0x8e, 0x80, + 0x5e, 0xe9, 0x15, 0xae, 0x88, 0x5c, 0xa9, 0x57 +}; +/* K = aeaa655b6febfec50b05562c3f358865533e4736 */ +static const uint8_t ac_dsa_vect23_out[] = { +/* R */ + 0x14, 0x89, 0x2b, 0x1e, 0xc7, 0xfc, 0x71, 0x6c, 0x75, 0xa1, 0x7f, 0x7a, + 0xd2, 0xe4, 0x1e, 0xc6, 0xfa, 0xa7, 0x88, 0x36, +/* S */ + 0x72, 0xcc, 0x56, 0xa9, 0x89, 0x0e, 0x8b, 0xdf, 0x1a, 0x53, 0xd3, 0xac, + 0xc6, 0xf8, 0x91, 0x37, 0x26, 0x4f, 0x9f, 0xf8 +}; +#define ac_dsa_vect24_prime ac_dsa_vect16_prime +#define ac_dsa_vect24_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect24_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect24_ptx[] = { +/* Msg */ + 0x5e, 0x8e, 0xb9, 0x6b, 0x5c, 0x6a, 0xd7, 0x5d, 0x3d, 0xab, 0x1e, 0x28, + 0xbb, 0x2c, 0xe7, 0x51, 0xec, 0xc3, 0x16, 0x11, 0xa0, 0x19, 0xe8, 0xd4, + 0xb5, 0x61, 0xc7, 0xe4, 0x53, 0x3c, 0xc7, 0xab, 0x73, 0xbd, 0x9d, 0xe9, + 0x31, 0xe8, 0xc5, 0x4c, 0x51, 0xc5, 0x71, 0x1e, 0x6c, 0x27, 0x6a, 0x8e, + 0xd9, 0x2f, 0x4b, 0xb4, 0x57, 0xdd, 0xf2, 0x82, 0x33, 0xda, 0x2c, 0xa3, + 0xe3, 0x01, 0x3c, 0x56, 0xe3, 0xcd, 0x2b, 0xc6, 0x1d, 0x4d, 0x4e, 0x0e, + 0x22, 0xcf, 0x63, 0x61, 0x30, 0x4e, 0x56, 0xd6, 0x8b, 0x31, 0x5c, 0xa5, + 0xd3, 0xfc, 0xc4, 0x72, 0xa7, 0xee, 0xf8, 0xcc, 0xa5, 0x75, 0x20, 0x4d, + 0xd0, 0x84, 0xa2, 0x1a, 0x99, 0xba, 0x67, 0xfd, 0xdb, 0xf9, 0x0d, 0xf7, + 0xc6, 0xc6, 0x58, 0x76, 0x17, 0x34, 0xbc, 0xe1, 0x3c, 0x3d, 0x22, 0xd8, + 0x0b, 0x6f, 0xb9, 0xbe, 0xce, 0x55, 0x14, 0x92 +}; +static const uint8_t ac_dsa_vect24_priv_val[] = { +/* X */ + 0x0b, 0x55, 0xf9, 0x9a, 0xd9, 0x58, 0xa7, 0x66, 0xea, 0xf5, 0xac, 0x20, + 0xa1, 0x27, 0xa4, 0xdf, 0x1b, 0x94, 0x6b, 0xae +}; +static const uint8_t ac_dsa_vect24_pub_val[] = { +/* Y */ + 0x50, 0xb0, 0xf7, 0x60, 0x59, 0x11, 0xbc, 0xe6, 0xed, 0x5e, 0xcf, 0xf1, + 0xe3, 0xc1, 0x81, 0x6f, 0xbb, 0xf0, 0x3a, 0x14, 0x79, 0xa0, 0x82, 0x06, + 0x03, 0xff, 0xa7, 0x15, 0xae, 0xf9, 0xff, 0xbc, 0xcb, 0xd0, 0x67, 0x57, + 0x9c, 0xbb, 0xc8, 0xc8, 0x7c, 0x39, 0x2e, 0x85, 0xbb, 0xe9, 0x29, 0xa0, + 0xb5, 0xe1, 0x05, 0x9f, 0xaa, 0xe6, 0xf9, 0x12, 0x1d, 0xf4, 0x9c, 0x66, + 0xa0, 0x49, 0xa9, 0x8a, 0x90, 0xd8, 0x4c, 0x70, 0xa2, 0x13, 0x12, 0xbf, + 0x83, 0x7f, 0x47, 0x23, 0x99, 0x3d, 0x0e, 0xc0, 0xac, 0x4c, 0x2a, 0x7f, + 0xfb, 0x9d, 0x40, 0x09, 0x57, 0xb3, 0x9f, 0xb8, 0x3e, 0x95, 0x1e, 0xf4, + 0x13, 0x62, 0x45, 0x2c, 0xf4, 0x58, 0xd7, 0x84, 0xc4, 0x3f, 0xe8, 0x22, + 0xea, 0x7a, 0x7a, 0xbb, 0xea, 0x0a, 0x69, 0x98, 0x32, 0x1a, 0x93, 0x81, + 0x9d, 0x2d, 0x28, 0x2c, 0x78, 0x84, 0xf5, 0xc2 +}; +/* K = 9e9b9afb43a7157761f6c2011138d2f65ac1cba9 */ +static const uint8_t ac_dsa_vect24_out[] = { +/* R */ + 0x73, 0x99, 0xb1, 0x20, 0xd4, 0xbf, 0xbd, 0x6d, 0xc4, 0x06, 0x4d, 0x2f, + 0x3f, 0x8f, 0x0c, 0xa5, 0xc3, 0x62, 0xb2, 0xd8, +/* S */ + 0x23, 0x02, 0xd8, 0x1d, 0x7e, 0xbb, 0x24, 0x17, 0xee, 0xf4, 0x5d, 0x88, + 0x94, 0x1b, 0x07, 0x0e, 0xca, 0xb1, 0x1c, 0xab +}; +#define ac_dsa_vect25_prime ac_dsa_vect16_prime +#define ac_dsa_vect25_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect25_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect25_ptx[] = { +/* Msg */ + 0xda, 0x91, 0xc6, 0x92, 0xcd, 0xb0, 0xa5, 0x95, 0x62, 0xe2, 0xb6, 0x64, + 0xdc, 0xfe, 0x75, 0x54, 0xac, 0x58, 0x9d, 0x57, 0xf8, 0x22, 0x46, 0xc4, + 0xa8, 0xa3, 0xf9, 0x57, 0x3b, 0xf4, 0x7b, 0x25, 0x7e, 0xb8, 0xf9, 0x34, + 0x47, 0xc1, 0xeb, 0xab, 0x13, 0xdc, 0xe5, 0x3d, 0x6f, 0x44, 0x16, 0xfb, + 0x2c, 0x6c, 0x36, 0x30, 0x3e, 0xd9, 0x78, 0x85, 0xcf, 0x7a, 0x6c, 0xae, + 0xf0, 0x55, 0xf7, 0xe3, 0x14, 0x5e, 0xf3, 0x83, 0x8c, 0x31, 0x87, 0x7f, + 0xad, 0x7a, 0x88, 0x83, 0xff, 0xc8, 0x4e, 0xbd, 0x97, 0x3f, 0x8c, 0x06, + 0xd1, 0x7c, 0xdd, 0x33, 0x9b, 0xb3, 0x37, 0x1f, 0x9d, 0x3d, 0x4f, 0x2d, + 0x9f, 0x0b, 0x80, 0xae, 0x2b, 0xcc, 0x87, 0x8b, 0x4a, 0xf7, 0x8f, 0x84, + 0x5e, 0xac, 0x4f, 0x2a, 0xac, 0xee, 0x6a, 0x94, 0x51, 0xda, 0xf8, 0x14, + 0xa4, 0x4e, 0x92, 0x7b, 0xb5, 0x42, 0x88, 0x20 +}; +static const uint8_t ac_dsa_vect25_priv_val[] = { +/* X */ + 0xac, 0x70, 0x12, 0x52, 0xc7, 0x73, 0xba, 0x36, 0x71, 0x1b, 0x97, 0x31, + 0xaf, 0xdc, 0x07, 0x7c, 0x5d, 0x3f, 0x92, 0x71 +}; +static const uint8_t ac_dsa_vect25_pub_val[] = { +/* Y */ + 0x67, 0x8b, 0x39, 0x58, 0xed, 0x24, 0xfc, 0x84, 0x94, 0x20, 0x54, 0xf4, + 0x9d, 0x9e, 0x6f, 0x27, 0xbb, 0xac, 0x7d, 0xe3, 0xa4, 0xa5, 0x2a, 0xf9, + 0xff, 0xcb, 0x9c, 0xe6, 0xc1, 0xfb, 0x8b, 0xdd, 0x99, 0xdb, 0x0e, 0x80, + 0xc8, 0x68, 0xac, 0x54, 0x7c, 0x4c, 0xfc, 0x78, 0x2d, 0xe7, 0xeb, 0xcf, + 0x69, 0x43, 0xb2, 0xe4, 0x64, 0x33, 0xc6, 0x70, 0x17, 0x8d, 0xe0, 0x10, + 0x4b, 0xd6, 0xfc, 0x25, 0xdc, 0x30, 0x54, 0xdb, 0x9c, 0x48, 0xc1, 0x27, + 0x06, 0xe1, 0xde, 0xa3, 0x5e, 0x16, 0x3b, 0xe3, 0x6a, 0x4a, 0xb7, 0x21, + 0x95, 0x0c, 0x02, 0x8b, 0x05, 0x46, 0xf1, 0x71, 0x9f, 0xf2, 0xed, 0xd8, + 0x1b, 0x2b, 0x79, 0x74, 0xfb, 0x9b, 0x12, 0x12, 0x24, 0xcc, 0xfa, 0xab, + 0xc4, 0x7e, 0x9e, 0x62, 0x9a, 0x97, 0xbc, 0x6b, 0xa4, 0x26, 0x91, 0xca, + 0x3f, 0x64, 0x9c, 0xca, 0xc4, 0x7d, 0x0f, 0x1e +}; +/* K = 6cabf2c0e2890b2b393da3ea6aac2782216efa73 */ +static const uint8_t ac_dsa_vect25_out[] = { +/* R */ + 0x6f, 0x15, 0x79, 0xed, 0xcf, 0x43, 0x75, 0x84, 0xd3, 0xe9, 0x39, 0xfa, + 0x5b, 0x00, 0x2e, 0xee, 0x83, 0xe3, 0xb6, 0x14, +/* S */ + 0x71, 0x20, 0x8a, 0x87, 0xa4, 0xcf, 0x2b, 0x3a, 0x9b, 0x65, 0x47, 0x77, + 0x73, 0xb0, 0x09, 0x6d, 0x45, 0x2d, 0xae, 0x60 +}; +#define ac_dsa_vect26_prime ac_dsa_vect16_prime +#define ac_dsa_vect26_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect26_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect26_ptx[] = { +/* Msg */ + 0x0f, 0x2e, 0xdc, 0x87, 0xf4, 0xd2, 0x94, 0x2c, 0x46, 0x93, 0xb0, 0x64, + 0xa5, 0x11, 0xb9, 0x3f, 0x79, 0x0c, 0x60, 0xdc, 0x14, 0x9a, 0x1b, 0x0b, + 0x70, 0x41, 0xaf, 0x51, 0x83, 0xbc, 0x0f, 0x42, 0x23, 0x41, 0x34, 0xb2, + 0x84, 0x27, 0x0e, 0x4c, 0x7e, 0x53, 0x61, 0x4f, 0x7e, 0xcf, 0xe7, 0x11, + 0xde, 0x0e, 0xfb, 0x28, 0x33, 0x6d, 0x0b, 0xb3, 0x59, 0xc8, 0x6e, 0x8b, + 0xe8, 0x83, 0x9f, 0x58, 0x32, 0x11, 0xe9, 0x17, 0x48, 0x32, 0xb3, 0xd4, + 0x1e, 0xe6, 0xd2, 0x18, 0x64, 0xac, 0x61, 0x86, 0xfd, 0x1d, 0xb9, 0x20, + 0xdd, 0xa6, 0x5b, 0x25, 0x96, 0x6c, 0x59, 0x51, 0xab, 0x8a, 0x20, 0x50, + 0xdd, 0xa8, 0x7d, 0x1d, 0x72, 0xe3, 0x03, 0x28, 0x52, 0xad, 0x43, 0xda, + 0x9f, 0xb4, 0x30, 0xe8, 0x50, 0x02, 0x2b, 0x4b, 0xb6, 0xcc, 0x9c, 0xb9, + 0x0e, 0x42, 0x8f, 0x3a, 0x5c, 0xa3, 0x2a, 0x62 +}; +static const uint8_t ac_dsa_vect26_priv_val[] = { +/* X */ + 0x58, 0x8f, 0x40, 0xe3, 0xeb, 0x81, 0x3c, 0xd2, 0x2a, 0x41, 0xc9, 0xcd, + 0xea, 0xdb, 0x68, 0x95, 0xa3, 0x48, 0xdb, 0x3c +}; +static const uint8_t ac_dsa_vect26_pub_val[] = { +/* Y */ + 0x3a, 0x97, 0x8e, 0x90, 0x22, 0xa8, 0xf7, 0xa0, 0xca, 0xa9, 0x1f, 0x27, + 0x5b, 0xf9, 0xcf, 0x76, 0x48, 0xe1, 0xb9, 0xa3, 0x1a, 0x07, 0x02, 0xd8, + 0xac, 0xdb, 0xf5, 0x9a, 0xff, 0xb5, 0x46, 0x7f, 0xb0, 0x7a, 0x8f, 0x7e, + 0x5b, 0x4c, 0x86, 0x77, 0x5a, 0xc4, 0xef, 0xb6, 0x09, 0xb9, 0x46, 0xf0, + 0x5a, 0x3f, 0x13, 0x03, 0x4d, 0xb9, 0x4a, 0xcc, 0x64, 0x05, 0x7f, 0x90, + 0x6d, 0x18, 0x54, 0x91, 0x0d, 0xe5, 0x38, 0xf8, 0x43, 0x67, 0x18, 0x1c, + 0x61, 0x8e, 0x96, 0xc3, 0xf9, 0x22, 0x54, 0x7d, 0x40, 0x8e, 0xe6, 0x40, + 0x8b, 0x7a, 0x70, 0xac, 0xed, 0xc7, 0x5d, 0xe8, 0xae, 0x44, 0x5c, 0x5d, + 0x4d, 0xd5, 0xde, 0xf4, 0xa3, 0x52, 0xd2, 0x52, 0x82, 0x34, 0x07, 0x0c, + 0xc7, 0x20, 0x70, 0x0c, 0x14, 0xce, 0x12, 0xd2, 0xf3, 0x69, 0x90, 0xd3, + 0x6b, 0x29, 0xd7, 0xb0, 0x05, 0x96, 0xe3, 0x4b +}; +/* K = 8ac2fe7bcd690a7239d294b22725b818d262a446 */ +static const uint8_t ac_dsa_vect26_out[] = { +/* R */ + 0xb6, 0xea, 0x9c, 0xdb, 0x21, 0x1c, 0x45, 0x60, 0xb3, 0xd5, 0x92, 0xe9, + 0x3a, 0xf6, 0xd5, 0xf1, 0x33, 0xb6, 0x4b, 0x9b, +/* S */ + 0x62, 0x42, 0xe4, 0x5a, 0x47, 0x2f, 0xa8, 0x14, 0x7c, 0xb5, 0x25, 0x3d, + 0xbd, 0xde, 0xba, 0xe3, 0x1e, 0xf3, 0x1e, 0x4e +}; +#define ac_dsa_vect27_prime ac_dsa_vect16_prime +#define ac_dsa_vect27_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect27_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect27_ptx[] = { +/* Msg */ + 0xd1, 0x2f, 0xc1, 0x98, 0x3e, 0x00, 0x95, 0xe9, 0xe2, 0xb6, 0xb8, 0x74, + 0x3f, 0xb3, 0x43, 0x86, 0xcc, 0x48, 0x21, 0x54, 0x0e, 0x3e, 0xfe, 0x1a, + 0x29, 0xf8, 0x4c, 0xf7, 0xe6, 0x3e, 0x2a, 0x06, 0x68, 0xd5, 0x51, 0xf9, + 0x12, 0xad, 0x22, 0x21, 0xb5, 0xa3, 0xd6, 0xb9, 0xeb, 0xd1, 0x21, 0x36, + 0xde, 0xf5, 0xe6, 0x69, 0x0e, 0x1d, 0x32, 0xaa, 0xe9, 0x19, 0xf9, 0xf1, + 0xcf, 0x5d, 0x24, 0xd6, 0x2a, 0x46, 0xa9, 0xa9, 0xa6, 0x04, 0xba, 0xe1, + 0x1b, 0x9c, 0x08, 0x66, 0x35, 0x03, 0x67, 0x20, 0x4a, 0x92, 0x0b, 0x58, + 0x9a, 0x31, 0x7d, 0xdf, 0xbb, 0x87, 0x7f, 0x9f, 0xad, 0x6b, 0x0d, 0x36, + 0x29, 0xaf, 0x96, 0x35, 0xda, 0x46, 0x93, 0x31, 0x51, 0xc0, 0xd9, 0xa2, + 0x0a, 0xaa, 0xbd, 0xdd, 0x3d, 0xf5, 0xd0, 0x49, 0x65, 0x9b, 0x28, 0x60, + 0xdd, 0xb8, 0xb2, 0x09, 0x63, 0x26, 0x1e, 0xa0 +}; +static const uint8_t ac_dsa_vect27_priv_val[] = { +/* X */ + 0x67, 0xcd, 0x81, 0xc7, 0xd6, 0xac, 0x2d, 0x8b, 0xd4, 0x4e, 0xf2, 0x62, + 0x97, 0xac, 0x02, 0xec, 0xba, 0x41, 0xf7, 0x3f +}; +static const uint8_t ac_dsa_vect27_pub_val[] = { +/* Y */ + 0x10, 0xb7, 0xb1, 0x4a, 0xd2, 0x9f, 0xb3, 0x4d, 0x7a, 0x39, 0xf3, 0xe9, + 0x53, 0x05, 0x1f, 0x45, 0x6a, 0x0c, 0xd1, 0x23, 0x3e, 0xf5, 0x4d, 0x90, + 0xa4, 0xad, 0xc8, 0x2d, 0xfb, 0xd9, 0xfa, 0x7a, 0x85, 0x62, 0x8f, 0x11, + 0x03, 0x96, 0x32, 0xb4, 0x7b, 0xa9, 0xda, 0xec, 0xa6, 0xe4, 0x63, 0xec, + 0x46, 0x44, 0xf5, 0xe2, 0xa2, 0xa4, 0xbf, 0x95, 0xd3, 0x92, 0xe8, 0xc9, + 0xc9, 0xf2, 0x87, 0xa2, 0x0b, 0xa4, 0x5a, 0x19, 0x88, 0x15, 0xca, 0x0e, + 0x9b, 0xa8, 0x54, 0xd7, 0xf3, 0xc7, 0x9d, 0x90, 0x37, 0xfa, 0x14, 0x17, + 0x72, 0x4f, 0xb7, 0xf0, 0x27, 0x99, 0xb1, 0xc2, 0xb2, 0xbc, 0xc7, 0x9d, + 0x64, 0x36, 0x7b, 0x90, 0xc0, 0x6d, 0x17, 0x89, 0xdc, 0xc6, 0xde, 0x57, + 0xca, 0x19, 0xfc, 0xef, 0xaf, 0xc0, 0x4f, 0xcc, 0xe2, 0x9c, 0x8f, 0x49, + 0x5e, 0xd5, 0x64, 0xf5, 0xd9, 0xa1, 0x12, 0xca +}; +/* K = 1341e376e8919e01991e5e48b8e0c7255929b3d2 */ +static const uint8_t ac_dsa_vect27_out[] = { +/* R */ + 0x36, 0x06, 0x17, 0x96, 0x5f, 0x65, 0xa6, 0x8a, 0xbc, 0xb8, 0x3d, 0xbf, + 0x2d, 0x88, 0x6a, 0x1a, 0x10, 0xca, 0x05, 0xde, +/* S */ + 0x71, 0xab, 0xb6, 0xac, 0xbf, 0x7e, 0x65, 0x3d, 0x2e, 0xbc, 0x3c, 0xb7, + 0x14, 0x9b, 0x51, 0xcc, 0x0c, 0x92, 0xfb, 0xa8 +}; +#define ac_dsa_vect28_prime ac_dsa_vect16_prime +#define ac_dsa_vect28_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect28_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect28_ptx[] = { +/* Msg */ + 0x87, 0xa6, 0xdf, 0xb8, 0x48, 0x7f, 0x16, 0xf6, 0xfe, 0xf1, 0xd6, 0x8b, + 0xc3, 0x14, 0x69, 0xac, 0x21, 0x0e, 0xa5, 0x53, 0x87, 0x96, 0x5b, 0xb4, + 0x45, 0x8c, 0xa0, 0xd0, 0x0d, 0x6c, 0x46, 0x85, 0x8b, 0xe2, 0x8a, 0x01, + 0x9c, 0xe9, 0x14, 0xc3, 0x9c, 0x24, 0x79, 0xf3, 0x21, 0xf0, 0x25, 0x2c, + 0xa4, 0xa8, 0xbd, 0x68, 0x1a, 0x5b, 0x35, 0x8a, 0x09, 0x3f, 0xc8, 0x34, + 0x1c, 0x31, 0xbc, 0x47, 0xc6, 0x18, 0x40, 0x3f, 0x93, 0x32, 0x2b, 0x44, + 0x30, 0x84, 0xce, 0x58, 0x18, 0x49, 0x0b, 0x74, 0xe8, 0x3c, 0x38, 0x66, + 0xb8, 0x16, 0x4b, 0xbc, 0xf7, 0x9b, 0xf8, 0x25, 0x39, 0xf4, 0x28, 0xc9, + 0x35, 0x1c, 0x40, 0xb1, 0x0d, 0x77, 0x3c, 0xbe, 0x1c, 0xba, 0xa8, 0xc9, + 0x80, 0x0a, 0x6d, 0xcf, 0x38, 0xd8, 0x55, 0x15, 0xe2, 0xdf, 0xf5, 0xd4, + 0xf8, 0xa9, 0x65, 0xec, 0xae, 0xf3, 0x7e, 0x38 +}; +static const uint8_t ac_dsa_vect28_priv_val[] = { +/* X */ + 0x22, 0xbb, 0xb8, 0x46, 0x8f, 0x3e, 0x90, 0x76, 0x8d, 0x34, 0x7c, 0xb3, + 0x49, 0x2f, 0x64, 0xdb, 0x2a, 0x23, 0xf7, 0x21 +}; +static const uint8_t ac_dsa_vect28_pub_val[] = { +/* Y */ + 0x75, 0xef, 0x5d, 0x5f, 0x67, 0x02, 0x24, 0x26, 0xf5, 0x31, 0xe9, 0xb8, + 0xca, 0x91, 0x15, 0x92, 0x1d, 0x5a, 0x5c, 0x44, 0x6b, 0xcd, 0xf1, 0xaf, + 0x70, 0x1b, 0x60, 0x5b, 0xae, 0x68, 0x7d, 0xff, 0x8d, 0x1e, 0x7b, 0x3c, + 0x4f, 0x8b, 0x28, 0x95, 0x37, 0xeb, 0x09, 0xa7, 0x46, 0x1d, 0x66, 0x88, + 0xa3, 0x71, 0x19, 0x74, 0x37, 0x1a, 0x5b, 0x73, 0xa2, 0x08, 0x2e, 0x99, + 0x14, 0x10, 0x11, 0x86, 0x66, 0xcc, 0xd9, 0x4f, 0x44, 0x49, 0x77, 0xd0, + 0xc8, 0x9b, 0xa3, 0x61, 0x62, 0xde, 0x02, 0x3a, 0xa5, 0x19, 0x03, 0x7a, + 0x6b, 0xa6, 0x30, 0x54, 0x17, 0xda, 0xd3, 0xf2, 0xdc, 0x38, 0x75, 0x6a, + 0x40, 0x04, 0x64, 0x91, 0xe8, 0xee, 0x80, 0xc4, 0xf1, 0x47, 0x82, 0x5b, + 0x8c, 0x02, 0x1b, 0x5d, 0x09, 0xa2, 0x42, 0x2d, 0x39, 0xd7, 0xc4, 0xab, + 0xc3, 0x95, 0xf6, 0xc2, 0xd7, 0x90, 0x3c, 0x66 +}; +/* K = 9c609e56c19f74ddc46eb2e2cfe26b1519ff0d1b */ +static const uint8_t ac_dsa_vect28_out[] = { +/* R */ + 0x54, 0x09, 0xcd, 0x62, 0xf5, 0x53, 0x93, 0x06, 0xae, 0x8c, 0x93, 0x60, + 0x82, 0xee, 0xf9, 0x32, 0xc6, 0x50, 0x5c, 0x39, +/* S */ + 0x07, 0xc0, 0xcc, 0xb3, 0x0e, 0xc9, 0x0b, 0x14, 0x81, 0x40, 0x9c, 0xbf, + 0xa2, 0xf5, 0xde, 0x6c, 0xfa, 0xf1, 0xef, 0xc5 +}; +#define ac_dsa_vect29_prime ac_dsa_vect16_prime +#define ac_dsa_vect29_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect29_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect29_ptx[] = { +/* Msg */ + 0xa3, 0x32, 0xb3, 0x8e, 0x64, 0x2b, 0xca, 0xd8, 0xbd, 0x27, 0x1f, 0x77, + 0x6f, 0xff, 0x24, 0xa7, 0x31, 0x72, 0x4a, 0x43, 0x40, 0x0c, 0x16, 0x14, + 0xf5, 0xe2, 0x12, 0x96, 0xdb, 0x04, 0xf7, 0x25, 0xee, 0xba, 0xd2, 0x8d, + 0x62, 0xe2, 0x0c, 0xa3, 0xf7, 0xf1, 0x83, 0x28, 0xa7, 0x6b, 0x80, 0x92, + 0xd9, 0x7b, 0x63, 0x2b, 0xb7, 0x87, 0x18, 0xf0, 0xf2, 0xf9, 0xec, 0xc7, + 0xc1, 0x2c, 0xc3, 0x6b, 0x50, 0x59, 0x59, 0x91, 0x7b, 0x5c, 0x54, 0x31, + 0x2a, 0xd4, 0x71, 0x7b, 0xe8, 0x4f, 0xa8, 0x40, 0xb9, 0xf0, 0x6d, 0xe0, + 0x05, 0xc7, 0x92, 0xaf, 0x3e, 0x9e, 0xa7, 0x2b, 0x7a, 0xe2, 0xe3, 0x42, + 0x3d, 0x07, 0xc7, 0x81, 0xc9, 0xc2, 0x55, 0x3f, 0x89, 0x95, 0x54, 0xa0, + 0xd8, 0xde, 0xc9, 0xa2, 0x85, 0xc1, 0xee, 0x25, 0x16, 0x0f, 0xa2, 0x78, + 0x48, 0x94, 0x74, 0xa0, 0xe4, 0x37, 0x95, 0x16 +}; +static const uint8_t ac_dsa_vect29_priv_val[] = { +/* X */ + 0xbb, 0xb1, 0x85, 0x4e, 0x9b, 0x09, 0x42, 0xcb, 0x5d, 0x1e, 0xb7, 0x1e, + 0x8c, 0xc6, 0xfc, 0x7e, 0x0f, 0x4c, 0xfc, 0xb5 +}; +static const uint8_t ac_dsa_vect29_pub_val[] = { +/* Y */ + 0x41, 0xcc, 0x1d, 0x6d, 0x9e, 0x0c, 0xf5, 0xf1, 0x58, 0xda, 0xb5, 0x99, + 0x11, 0x4f, 0x3e, 0xe4, 0x73, 0x8f, 0x19, 0x7c, 0xf2, 0xc9, 0x56, 0xb6, + 0xbb, 0x0d, 0xdd, 0x6d, 0xfd, 0xcf, 0x5e, 0x4d, 0xb3, 0x99, 0xaa, 0xcc, + 0x16, 0xc5, 0x38, 0x94, 0x8c, 0x4b, 0x50, 0xde, 0x85, 0xba, 0xd6, 0xd9, + 0x16, 0xdb, 0xc4, 0x15, 0xba, 0xd2, 0xf6, 0x73, 0x70, 0x23, 0xfc, 0x70, + 0x63, 0xc1, 0x33, 0xbd, 0x0c, 0x42, 0x31, 0xd6, 0xb3, 0x3c, 0xe8, 0x13, + 0xc0, 0xd6, 0x02, 0x4d, 0x13, 0x15, 0x26, 0x95, 0x71, 0xb2, 0x55, 0x4b, + 0xbb, 0x2e, 0xdf, 0x2a, 0x99, 0x10, 0x8a, 0x43, 0x59, 0xe8, 0xe2, 0x3b, + 0xf8, 0xa1, 0x43, 0xbf, 0xc5, 0x38, 0xab, 0x9f, 0x88, 0x42, 0xcd, 0x4e, + 0x92, 0x59, 0x68, 0xf4, 0x9a, 0xc5, 0x6a, 0x02, 0xe3, 0xf0, 0x67, 0xe2, + 0x60, 0x01, 0xe5, 0x20, 0x7b, 0xcb, 0x56, 0xd4 +}; +/* K = 336e458fc213c0b2775537ae61decc034ccb1d32 */ +static const uint8_t ac_dsa_vect29_out[] = { +/* R */ + 0xa1, 0x6a, 0x73, 0x08, 0xa6, 0x82, 0x4d, 0x92, 0x9b, 0x6a, 0x9a, 0x3b, + 0xdb, 0x28, 0x0d, 0x15, 0x1a, 0x6e, 0xed, 0x81, +/* S */ + 0x7a, 0x42, 0xad, 0xda, 0xb7, 0xdd, 0xb9, 0x80, 0x00, 0x28, 0x60, 0x44, + 0xd9, 0x99, 0x3d, 0x5c, 0xf8, 0x18, 0xf2, 0xb1 +}; +#define ac_dsa_vect30_prime ac_dsa_vect16_prime +#define ac_dsa_vect30_sub_prime ac_dsa_vect16_sub_prime +#define ac_dsa_vect30_base ac_dsa_vect16_base +static const uint8_t ac_dsa_vect30_ptx[] = { +/* Msg */ + 0x79, 0xb1, 0x44, 0xd5, 0x0e, 0x00, 0x47, 0x59, 0x6c, 0xf0, 0x6b, 0xfc, + 0xb3, 0xe9, 0xce, 0x39, 0x59, 0xec, 0x4b, 0x8c, 0xc9, 0xba, 0x01, 0x43, + 0x4f, 0xc3, 0xf6, 0x8f, 0x47, 0xc8, 0x68, 0xce, 0xa0, 0x48, 0xb9, 0x90, + 0xe6, 0x2c, 0xd7, 0xa5, 0x0e, 0xee, 0x28, 0x8b, 0x35, 0xae, 0x62, 0xaa, + 0x79, 0x79, 0x24, 0xc9, 0xdc, 0xab, 0x76, 0x40, 0x9b, 0x86, 0x9b, 0x33, + 0xde, 0x28, 0x88, 0x5e, 0x62, 0xf1, 0x7d, 0xb7, 0xa7, 0x75, 0x89, 0x73, + 0x48, 0x29, 0x68, 0xb9, 0xf9, 0x60, 0xeb, 0x2d, 0xba, 0x84, 0xae, 0x85, + 0x10, 0x1a, 0xa6, 0xc6, 0x14, 0x1b, 0x3f, 0x08, 0x39, 0xa4, 0x18, 0x5a, + 0x4c, 0x49, 0x6e, 0xae, 0x87, 0x6e, 0xcd, 0xc4, 0x56, 0x27, 0x33, 0x0d, + 0x36, 0xf0, 0x1a, 0x67, 0xcb, 0xb7, 0xfa, 0xef, 0x83, 0x43, 0x57, 0x33, + 0x0a, 0xac, 0x36, 0xc7, 0xc6, 0xf4, 0x7a, 0xc9 +}; +static const uint8_t ac_dsa_vect30_priv_val[] = { +/* X */ + 0x75, 0x4b, 0x24, 0xea, 0x5c, 0x8c, 0xb8, 0xe8, 0x8e, 0x37, 0x00, 0x74, + 0xe7, 0x9c, 0xb6, 0x26, 0x05, 0x53, 0x00, 0x18 +}; +static const uint8_t ac_dsa_vect30_pub_val[] = { +/* Y */ + 0x74, 0xdb, 0x74, 0x60, 0xc5, 0x19, 0x19, 0xa9, 0xe8, 0x7b, 0x43, 0x0d, + 0x10, 0x5d, 0x86, 0x36, 0x2e, 0xe4, 0xac, 0xd9, 0x68, 0x2b, 0xf6, 0xc9, + 0xfe, 0x87, 0xd9, 0x95, 0x6c, 0x2f, 0x5f, 0xf1, 0x7d, 0x95, 0x93, 0x0c, + 0xcc, 0x12, 0xf7, 0xe9, 0x2d, 0x8b, 0xcb, 0x6a, 0xf5, 0xf7, 0xef, 0x18, + 0x48, 0xda, 0x8d, 0x15, 0xc9, 0x15, 0x20, 0x82, 0x47, 0x7d, 0xe9, 0x95, + 0x94, 0x78, 0x1b, 0x99, 0x8d, 0xaa, 0xfb, 0xf8, 0xae, 0x4a, 0xf2, 0x37, + 0x72, 0x12, 0x5c, 0x19, 0xe1, 0x66, 0x42, 0x1f, 0x80, 0x6b, 0xd0, 0xfb, + 0xea, 0xc3, 0x65, 0x07, 0x6e, 0xcd, 0x9e, 0x15, 0x43, 0x2a, 0xd4, 0xac, + 0x25, 0x23, 0x41, 0x8f, 0x6e, 0x41, 0x0c, 0xbf, 0xcb, 0xc5, 0xa7, 0x1a, + 0x0e, 0xdf, 0x22, 0xe6, 0x94, 0xa6, 0x7d, 0x14, 0xb9, 0xcf, 0xc9, 0x72, + 0x2b, 0xc4, 0xbd, 0x8c, 0x43, 0xe2, 0x2a, 0x91 +}; +/* K = 1b50341e94f4498b92cce4d17ab9d4016fb2e074 */ +static const uint8_t ac_dsa_vect30_out[] = { +/* R */ + 0x02, 0x1a, 0x3d, 0xe9, 0x8c, 0x3d, 0xa6, 0x98, 0xb4, 0x77, 0xb4, 0xc3, + 0xd5, 0x0b, 0x21, 0x69, 0xe6, 0x5f, 0x5e, 0x91, +/* S */ + 0xaf, 0xd7, 0x64, 0x31, 0x8d, 0xd0, 0xfe, 0xe0, 0x4f, 0xd6, 0xb0, 0x7f, + 0x55, 0x03, 0x20, 0x78, 0x9c, 0xd9, 0xbf, 0xa5 +}; +/* [mod = L=1024, N=160, SHA-256] */ +static const uint8_t ac_dsa_vect31_prime[] = { +/* P */ + 0xcb, 0xa1, 0x3e, 0x53, 0x36, 0x37, 0xc3, 0x7c, 0x0e, 0x80, 0xd9, 0xfc, + 0xd0, 0x52, 0xc1, 0xe4, 0x1a, 0x88, 0xac, 0x32, 0x5c, 0x4e, 0xbe, 0x13, + 0xb7, 0x17, 0x00, 0x88, 0xd5, 0x4e, 0xef, 0x48, 0x81, 0xf3, 0xd3, 0x5e, + 0xae, 0x47, 0xc2, 0x10, 0x38, 0x5a, 0x84, 0x85, 0xd2, 0x42, 0x3a, 0x64, + 0xda, 0x3f, 0xfd, 0xa6, 0x3a, 0x26, 0xf9, 0x2c, 0xf5, 0xa3, 0x04, 0xf3, + 0x92, 0x60, 0x38, 0x4a, 0x9b, 0x77, 0x59, 0xd8, 0xac, 0x1a, 0xdc, 0x81, + 0xd3, 0xf8, 0xbf, 0xc5, 0xe6, 0xcb, 0x10, 0xef, 0xb4, 0xe0, 0xf7, 0x58, + 0x67, 0xf4, 0xe8, 0x48, 0xd1, 0xa3, 0x38, 0x58, 0x6d, 0xd0, 0x64, 0x8f, + 0xee, 0xb1, 0x63, 0x64, 0x7f, 0xfe, 0x71, 0x76, 0x17, 0x43, 0x70, 0x54, + 0x0e, 0xe8, 0xa8, 0xf5, 0x88, 0xda, 0x8c, 0xc1, 0x43, 0xd9, 0x39, 0xf7, + 0x0b, 0x11, 0x4a, 0x7f, 0x98, 0x1b, 0x84, 0x83 +}; +static const uint8_t ac_dsa_vect31_sub_prime[] = { +/* Q */ + 0x95, 0x03, 0x1b, 0x8a, 0xa7, 0x1f, 0x29, 0xd5, 0x25, 0xb7, 0x73, 0xef, + 0x8b, 0x7c, 0x67, 0x01, 0xad, 0x8a, 0x5d, 0x99 +}; +static const uint8_t ac_dsa_vect31_base[] = { +/* G */ + 0x45, 0xbc, 0xaa, 0x44, 0x3d, 0x4c, 0xd1, 0x60, 0x2d, 0x27, 0xaa, 0xf8, + 0x41, 0x26, 0xed, 0xc7, 0x3b, 0xd7, 0x73, 0xde, 0x6e, 0xce, 0x15, 0xe9, + 0x7e, 0x7f, 0xef, 0x46, 0xf1, 0x30, 0x72, 0xb7, 0xad, 0xca, 0xf7, 0xb0, + 0x05, 0x3c, 0xf4, 0x70, 0x69, 0x44, 0xdf, 0x8c, 0x45, 0x68, 0xf2, 0x6c, + 0x99, 0x7e, 0xe7, 0x75, 0x30, 0x00, 0xfb, 0xe4, 0x77, 0xa3, 0x77, 0x66, + 0xa4, 0xe9, 0x70, 0xff, 0x40, 0x00, 0x8e, 0xb9, 0x00, 0xb9, 0xde, 0x4b, + 0x5f, 0x9a, 0xe0, 0x6e, 0x06, 0xdb, 0x61, 0x06, 0xe7, 0x87, 0x11, 0xf3, + 0xa6, 0x7f, 0xec, 0xa7, 0x4d, 0xd5, 0xbd, 0xdc, 0xdf, 0x67, 0x5a, 0xe4, + 0x01, 0x4e, 0xe9, 0x48, 0x9a, 0x42, 0x91, 0x7f, 0xbe, 0xe3, 0xbb, 0x9f, + 0x2a, 0x24, 0xdf, 0x67, 0x51, 0x2c, 0x1c, 0x35, 0xc9, 0x7b, 0xfb, 0xf2, + 0x30, 0x8e, 0xaa, 0xcd, 0x28, 0x36, 0x8c, 0x5c +}; +static const uint8_t ac_dsa_vect31_ptx[] = { +/* Msg */ + 0x81, 0x21, 0x72, 0xf0, 0x9c, 0xba, 0xe6, 0x25, 0x17, 0x80, 0x48, 0x85, + 0x75, 0x41, 0x25, 0xfc, 0x60, 0x66, 0xe9, 0xa9, 0x02, 0xf9, 0xdb, 0x20, + 0x41, 0xee, 0xdd, 0xd7, 0xe8, 0xda, 0x67, 0xe4, 0xa2, 0xe6, 0x5d, 0x00, + 0x29, 0xc4, 0x5e, 0xca, 0xce, 0xa6, 0x00, 0x2f, 0x95, 0x40, 0xeb, 0x10, + 0x04, 0xc8, 0x83, 0xa8, 0xf9, 0x00, 0xfd, 0x84, 0xa9, 0x8b, 0x5c, 0x44, + 0x9a, 0xc4, 0x9c, 0x56, 0xf3, 0xa9, 0x1d, 0x8b, 0xed, 0x3f, 0x08, 0xf4, + 0x27, 0x93, 0x5f, 0xbe, 0x43, 0x7c, 0xe4, 0x6f, 0x75, 0xcd, 0x66, 0x6a, + 0x07, 0x07, 0x26, 0x5c, 0x61, 0xa0, 0x96, 0x69, 0x8d, 0xc2, 0xf3, 0x6b, + 0x28, 0xc6, 0x5e, 0xc7, 0xb6, 0xe4, 0x75, 0xc8, 0xb6, 0x7d, 0xdf, 0xb4, + 0x44, 0xb2, 0xee, 0x6a, 0x98, 0x4e, 0x9d, 0x6d, 0x15, 0x23, 0x3e, 0x25, + 0xe4, 0x4b, 0xd8, 0xd7, 0x92, 0x4d, 0x12, 0x9d +}; +static const uint8_t ac_dsa_vect31_priv_val[] = { +/* X */ + 0x2e, 0xac, 0x4f, 0x41, 0x96, 0xfe, 0xdb, 0x3e, 0x65, 0x1b, 0x3b, 0x00, + 0x04, 0x01, 0x84, 0xcf, 0xd6, 0xda, 0x2a, 0xb4 +}; +static const uint8_t ac_dsa_vect31_pub_val[] = { +/* Y */ + 0x4c, 0xd6, 0x17, 0x86, 0x37, 0xd0, 0xf0, 0xde, 0x14, 0x88, 0x51, 0x5c, + 0x3b, 0x12, 0xe2, 0x03, 0xa3, 0xc0, 0xca, 0x65, 0x2f, 0x2f, 0xe3, 0x0d, + 0x08, 0x8d, 0xc7, 0x27, 0x8a, 0x87, 0xaf, 0xfa, 0x63, 0x4a, 0x72, 0x7a, + 0x72, 0x19, 0x32, 0xd6, 0x71, 0x99, 0x4a, 0x95, 0x8a, 0x0f, 0x89, 0x22, + 0x3c, 0x28, 0x6c, 0x3a, 0x9b, 0x10, 0xa9, 0x65, 0x60, 0x54, 0x2e, 0x26, + 0x26, 0xb7, 0x2e, 0x0c, 0xd2, 0x8e, 0x51, 0x33, 0xfb, 0x57, 0xdc, 0x23, + 0x8b, 0x7f, 0xab, 0x2d, 0xe2, 0xa4, 0x98, 0x63, 0xec, 0xf9, 0x98, 0x75, + 0x18, 0x61, 0xae, 0x66, 0x8b, 0xf7, 0xca, 0xd1, 0x36, 0xe6, 0x93, 0x3f, + 0x57, 0xdf, 0xdb, 0xa5, 0x44, 0xe3, 0x14, 0x7c, 0xe0, 0xe7, 0x37, 0x0f, + 0xa6, 0xe8, 0xff, 0x1d, 0xe6, 0x90, 0xc5, 0x1b, 0x4a, 0xee, 0xdf, 0x04, + 0x85, 0x18, 0x38, 0x89, 0x20, 0x55, 0x91, 0xe8 +}; +/* K = 85976c5610a74959531040a5512b347eac587e48 */ +static const uint8_t ac_dsa_vect31_out[] = { +/* R */ + 0x76, 0x68, 0x3a, 0x08, 0x5d, 0x67, 0x42, 0xea, 0xdf, 0x95, 0xa6, 0x1a, + 0xf7, 0x5f, 0x88, 0x12, 0x76, 0xcf, 0xd2, 0x6a, +/* S */ + 0x3b, 0x9d, 0xa7, 0xf9, 0x92, 0x6e, 0xaa, 0xad, 0x0b, 0xeb, 0xd4, 0x84, + 0x5c, 0x67, 0xfc, 0xdb, 0x64, 0xd1, 0x24, 0x53 +}; +#define ac_dsa_vect32_prime ac_dsa_vect31_prime +#define ac_dsa_vect32_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect32_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect32_ptx[] = { +/* Msg */ + 0xc1, 0xb1, 0xf1, 0x47, 0x2f, 0x08, 0xdf, 0x38, 0xa5, 0x2a, 0x55, 0xba, + 0x55, 0x82, 0x7b, 0xa3, 0xb7, 0xcd, 0xd6, 0xbe, 0xde, 0xd9, 0x04, 0xfc, + 0xd5, 0x26, 0x10, 0xc8, 0x99, 0xed, 0xa3, 0xc6, 0x16, 0x82, 0x65, 0x68, + 0x73, 0xbb, 0xfa, 0xab, 0x0d, 0x90, 0x74, 0x95, 0xda, 0xcf, 0x45, 0x8e, + 0xa3, 0x45, 0x0a, 0xfd, 0x93, 0xbe, 0x96, 0x7a, 0x37, 0x43, 0x4d, 0x41, + 0x2b, 0x63, 0x25, 0x66, 0x9a, 0xd8, 0x4b, 0x4e, 0xaa, 0x27, 0x8a, 0x24, + 0x87, 0x0e, 0xcc, 0x2d, 0xf0, 0xda, 0x13, 0xad, 0x52, 0x6a, 0x9e, 0x66, + 0x69, 0x95, 0x8d, 0x4e, 0x52, 0xdb, 0xfb, 0xa2, 0x80, 0x3a, 0xe9, 0xae, + 0x13, 0x5d, 0x0c, 0x0a, 0xcc, 0xa8, 0x6a, 0x04, 0xc4, 0x2b, 0xa9, 0xca, + 0xfb, 0x09, 0xb7, 0xaf, 0x96, 0x34, 0x71, 0x88, 0x88, 0x0b, 0x08, 0x61, + 0x69, 0xeb, 0xdf, 0x9f, 0x1f, 0x5f, 0x31, 0x73 +}; +static const uint8_t ac_dsa_vect32_priv_val[] = { +/* X */ + 0x1a, 0x22, 0x05, 0x85, 0xa9, 0x89, 0xef, 0x2c, 0x12, 0xbb, 0xfa, 0x9f, + 0xc0, 0xd2, 0x58, 0x71, 0x35, 0x56, 0xfe, 0x38 +}; +static const uint8_t ac_dsa_vect32_pub_val[] = { +/* Y */ + 0x99, 0x18, 0x74, 0x98, 0x53, 0x4f, 0x31, 0x3d, 0xc7, 0xcd, 0x7f, 0x3a, + 0x48, 0xd6, 0x2b, 0x23, 0x35, 0xbc, 0xdc, 0x36, 0xf0, 0xdc, 0x98, 0xdb, + 0xf8, 0x45, 0xdc, 0x60, 0x85, 0xc2, 0x67, 0x47, 0x4c, 0x36, 0xfd, 0xfc, + 0xa3, 0x88, 0x54, 0x21, 0x98, 0x30, 0xe6, 0x14, 0xbb, 0xca, 0xb2, 0xbb, + 0x9d, 0xec, 0xb8, 0x1e, 0x86, 0x12, 0x4b, 0xd7, 0x8f, 0x86, 0xd4, 0x71, + 0xbd, 0x84, 0xbe, 0x06, 0xac, 0x1f, 0x0f, 0x41, 0xfe, 0x5b, 0x4b, 0x37, + 0x40, 0xb2, 0x10, 0x7e, 0x0c, 0x9c, 0x48, 0xf8, 0x1e, 0x31, 0xe9, 0xbf, + 0x55, 0x0d, 0x96, 0x56, 0x4d, 0xd3, 0x80, 0xca, 0x47, 0xa1, 0x1d, 0x72, + 0xf0, 0xd0, 0xa3, 0x27, 0x5f, 0x07, 0x5f, 0x95, 0xbb, 0xd5, 0x98, 0x69, + 0xc1, 0x4d, 0xc9, 0x12, 0xa1, 0xcb, 0xcf, 0x01, 0xdb, 0x9f, 0xb7, 0xf7, + 0x10, 0x15, 0xcc, 0x14, 0x99, 0x86, 0x82, 0x5e +}; +/* K = 8fef50b7121a04a24755b6f3e1cdc93848a9081c */ +static const uint8_t ac_dsa_vect32_out[] = { +/* R */ + 0x54, 0xed, 0x4e, 0xfa, 0xec, 0xdf, 0xc7, 0x8d, 0x02, 0x64, 0x71, 0xb6, + 0x5c, 0xfe, 0xfc, 0x65, 0x29, 0x94, 0x5b, 0xbf, +/* S */ + 0x6d, 0x6d, 0xac, 0x29, 0x6e, 0xbd, 0xe3, 0xf8, 0x73, 0xb7, 0x51, 0xc6, + 0xb1, 0x48, 0x43, 0xf0, 0xb7, 0xbe, 0xfd, 0xff +}; +#define ac_dsa_vect33_prime ac_dsa_vect31_prime +#define ac_dsa_vect33_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect33_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect33_ptx[] = { +/* Msg */ + 0xb8, 0x0a, 0x47, 0x07, 0x1d, 0x13, 0x76, 0xfe, 0x61, 0x7e, 0x59, 0xfd, + 0xc0, 0x05, 0xa8, 0x90, 0x36, 0x9a, 0x4c, 0xa5, 0xe6, 0x78, 0xff, 0x46, + 0xeb, 0x9b, 0x20, 0x5d, 0x6e, 0xc0, 0x9c, 0xbd, 0x49, 0x37, 0x3b, 0xb3, + 0x41, 0xfe, 0x78, 0x13, 0xee, 0x44, 0x2a, 0x6e, 0xce, 0x17, 0xe7, 0x20, + 0xbf, 0x71, 0xa7, 0x45, 0x57, 0xac, 0x9a, 0x37, 0x5c, 0x05, 0x9e, 0x55, + 0x35, 0xe7, 0x73, 0xa4, 0x5e, 0x79, 0xe1, 0xbf, 0xf3, 0x46, 0x5a, 0x38, + 0x86, 0xc8, 0x6e, 0x2a, 0x2b, 0xc8, 0x82, 0xf0, 0xbe, 0xce, 0xef, 0xff, + 0xb2, 0xae, 0x1a, 0x52, 0x2f, 0x13, 0xc8, 0x2d, 0xef, 0x4c, 0xfd, 0x0c, + 0xfc, 0xa6, 0xfc, 0xee, 0xb4, 0xce, 0xce, 0x71, 0x86, 0x9e, 0x90, 0xcd, + 0x10, 0xd0, 0xaf, 0xf2, 0x7a, 0x84, 0xb5, 0x60, 0x1d, 0xaa, 0xe0, 0x61, + 0xcb, 0xeb, 0x3a, 0xa6, 0x2b, 0x37, 0xfd, 0x3a +}; +static const uint8_t ac_dsa_vect33_priv_val[] = { +/* X */ + 0x42, 0x47, 0xe7, 0xe4, 0xdc, 0x42, 0x70, 0xfc, 0x76, 0x80, 0xbc, 0x05, + 0x74, 0x68, 0x07, 0xc1, 0x83, 0xe0, 0xdd, 0x98 +}; +static const uint8_t ac_dsa_vect33_pub_val[] = { +/* Y */ + 0x91, 0xf5, 0x02, 0x70, 0xa7, 0x54, 0x05, 0x5e, 0x5d, 0xa6, 0x11, 0xc7, + 0x20, 0xa4, 0x26, 0x2f, 0x3c, 0xb8, 0xbd, 0x41, 0x61, 0xf7, 0x7d, 0x07, + 0x40, 0x16, 0x04, 0xd3, 0xd1, 0x16, 0x5e, 0x45, 0x51, 0x8f, 0x7e, 0x19, + 0x01, 0xad, 0xef, 0x66, 0x28, 0xf2, 0x3d, 0xc4, 0x82, 0x71, 0xd3, 0x5f, + 0xf4, 0x92, 0xaf, 0x8d, 0x62, 0xaa, 0x53, 0x8c, 0x0e, 0x77, 0xe0, 0x42, + 0xf2, 0x3a, 0x52, 0x2f, 0x22, 0x14, 0xe6, 0x21, 0x14, 0xbf, 0xee, 0xa4, + 0x6a, 0xe8, 0x88, 0x8b, 0xda, 0xda, 0xcd, 0xaa, 0x0a, 0x9a, 0x5b, 0x50, + 0x3d, 0x79, 0xc2, 0x3e, 0x4c, 0x20, 0xc9, 0x8b, 0xd4, 0xeb, 0xb3, 0x6f, + 0x95, 0xbf, 0x44, 0x51, 0xcc, 0xb0, 0xb5, 0xbb, 0x44, 0xdf, 0xd0, 0x11, + 0x34, 0x1c, 0xfa, 0x29, 0xa9, 0xe1, 0x56, 0xa3, 0xcd, 0x82, 0x8e, 0x12, + 0x6e, 0x68, 0xcb, 0x91, 0x1e, 0x8f, 0x9d, 0xc0 +}; +/* K = 3aeb3383a3c0f53217c0d7077c3cd66d2ef74a2e */ +static const uint8_t ac_dsa_vect33_out[] = { +/* R */ + 0x1f, 0xc2, 0xd1, 0xcb, 0x80, 0xbf, 0x6e, 0x0e, 0x78, 0xb2, 0x5f, 0xac, + 0x29, 0x3b, 0x75, 0x2c, 0xbf, 0xf2, 0xb5, 0xac, +/* S */ + 0x75, 0xbc, 0xc7, 0x72, 0xf7, 0x73, 0xd5, 0xfd, 0x98, 0xdd, 0xe1, 0xf9, + 0x07, 0xe7, 0xec, 0x2c, 0xba, 0x20, 0x1d, 0xfb +}; +#define ac_dsa_vect34_prime ac_dsa_vect31_prime +#define ac_dsa_vect34_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect34_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect34_ptx[] = { +/* Msg */ + 0xa9, 0x60, 0x30, 0x54, 0x46, 0x58, 0x87, 0xdf, 0x15, 0xdb, 0x07, 0xc0, + 0x70, 0x9a, 0x8c, 0x87, 0x8d, 0x2f, 0x1a, 0xbd, 0xcf, 0xc6, 0x19, 0x5e, + 0xab, 0xf3, 0xe9, 0xb3, 0xad, 0x07, 0xe8, 0x55, 0x8b, 0x99, 0xcc, 0x4a, + 0x7a, 0xa0, 0x76, 0xda, 0xf6, 0x7e, 0x9b, 0x7d, 0x84, 0x80, 0xf1, 0x1e, + 0x8a, 0xfb, 0x18, 0xe2, 0xac, 0x56, 0xa9, 0x54, 0x7b, 0x48, 0x45, 0x3f, + 0xed, 0xca, 0x32, 0xda, 0x9e, 0xb0, 0xc2, 0x92, 0x71, 0xeb, 0x60, 0xf0, + 0xa1, 0xd9, 0x5c, 0x18, 0xf4, 0x2d, 0x99, 0x23, 0x94, 0xb3, 0x26, 0x4f, + 0xf3, 0xe2, 0x1e, 0x60, 0x6e, 0x0b, 0xea, 0xc0, 0x8a, 0x7b, 0xa7, 0x1b, + 0x8e, 0x57, 0x95, 0xa8, 0xda, 0x98, 0x51, 0x18, 0xe4, 0x32, 0xcf, 0x5b, + 0x30, 0xb6, 0xcd, 0x3a, 0x60, 0x3d, 0x8b, 0x0d, 0x58, 0x0f, 0x06, 0xc6, + 0x26, 0xee, 0x93, 0x7c, 0x6c, 0xd0, 0x5f, 0x40 +}; +static const uint8_t ac_dsa_vect34_priv_val[] = { +/* X */ + 0x4d, 0x2a, 0x54, 0x62, 0xeb, 0xcc, 0xc5, 0xd1, 0x9b, 0xc6, 0xc1, 0xca, + 0xbb, 0x60, 0x9c, 0x08, 0xad, 0x08, 0x8e, 0x08 +}; +static const uint8_t ac_dsa_vect34_pub_val[] = { +/* Y */ + 0xa2, 0xc4, 0x56, 0x9a, 0x30, 0x14, 0x73, 0xae, 0x4f, 0x16, 0x4d, 0x68, + 0xb9, 0xa3, 0xc6, 0xeb, 0x70, 0x5a, 0xe8, 0x1f, 0x75, 0xd6, 0xe5, 0xcc, + 0x30, 0x70, 0xa5, 0x59, 0xcc, 0xcb, 0x8b, 0x1a, 0x2d, 0x8c, 0x21, 0x09, + 0x0e, 0xd7, 0x0e, 0x61, 0x67, 0x0c, 0x7e, 0x9d, 0xbf, 0x5f, 0x75, 0x5a, + 0x37, 0xd5, 0x8d, 0x3a, 0xbb, 0x34, 0xc2, 0xdf, 0xd4, 0x0d, 0xb9, 0xf2, + 0x6f, 0x68, 0x68, 0xd0, 0xdd, 0x91, 0xbe, 0x98, 0xf3, 0x95, 0xac, 0x0e, + 0xbd, 0xc3, 0x7e, 0x1b, 0x54, 0x23, 0x80, 0x2b, 0xea, 0x7a, 0x6c, 0xb1, + 0x96, 0xd7, 0xe0, 0xf9, 0x3d, 0xb9, 0x2f, 0x66, 0x3b, 0x6c, 0x9c, 0x72, + 0x6e, 0x80, 0xfe, 0xb2, 0xe9, 0x22, 0x71, 0x54, 0xce, 0x1c, 0x15, 0xf8, + 0xe8, 0xdf, 0x93, 0xec, 0x0d, 0x37, 0xfa, 0x47, 0xe5, 0xfa, 0x11, 0x2b, + 0xb0, 0xa4, 0x8f, 0x4a, 0x23, 0x9d, 0x60, 0x52 +}; +/* K = 36a3cd0101358a4d30c5b7117bc239fb4f6ce2e7 */ +static const uint8_t ac_dsa_vect34_out[] = { +/* R */ + 0x48, 0x53, 0x95, 0x23, 0x81, 0x5b, 0xd8, 0xd7, 0x3c, 0xe7, 0x02, 0x36, + 0x7c, 0x77, 0x12, 0xb9, 0xb1, 0x38, 0x67, 0xf2, +/* S */ + 0x20, 0xff, 0x4c, 0xfe, 0xf8, 0xa6, 0x68, 0x82, 0x9f, 0xea, 0xe7, 0x3b, + 0x52, 0x0e, 0x8a, 0xa4, 0xd0, 0x2c, 0x81, 0x68 +}; +#define ac_dsa_vect35_prime ac_dsa_vect31_prime +#define ac_dsa_vect35_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect35_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect35_ptx[] = { +/* Msg */ + 0x19, 0xeb, 0x08, 0x8c, 0x32, 0x29, 0xa4, 0x4f, 0x95, 0x86, 0xf0, 0x04, + 0x21, 0xcf, 0xe7, 0x42, 0x3a, 0x48, 0x6d, 0x5f, 0x7e, 0x28, 0xad, 0x2c, + 0x91, 0x19, 0xdd, 0x2e, 0x13, 0x95, 0xdf, 0x1a, 0xcc, 0x06, 0xcb, 0x28, + 0xe9, 0x06, 0x9c, 0xee, 0x62, 0xf0, 0x9f, 0x48, 0xe4, 0xca, 0x29, 0x26, + 0x9d, 0xd8, 0x9d, 0xf9, 0xfe, 0xc1, 0xff, 0xdf, 0x64, 0xb1, 0xfe, 0x27, + 0x17, 0xfe, 0x52, 0xb1, 0x42, 0x1f, 0xcf, 0x6c, 0x70, 0x5c, 0x0c, 0xf3, + 0x99, 0x30, 0xf9, 0x0e, 0xcb, 0x33, 0x9b, 0x51, 0xef, 0x95, 0xb2, 0xef, + 0x38, 0xa6, 0xd9, 0x6a, 0x57, 0x5f, 0x7b, 0x36, 0xf5, 0xed, 0xf4, 0xf2, + 0xcb, 0xd6, 0xd2, 0x61, 0xe1, 0xfd, 0xd7, 0x7d, 0x44, 0x59, 0x28, 0x8c, + 0x02, 0xe6, 0x8c, 0x82, 0xa3, 0x91, 0x0f, 0xf8, 0xca, 0x17, 0x47, 0xc8, + 0x6b, 0xb1, 0x87, 0xd5, 0x20, 0x5f, 0x51, 0xa8 +}; +static const uint8_t ac_dsa_vect35_priv_val[] = { +/* X */ + 0x08, 0x42, 0xdd, 0xd5, 0xa0, 0x41, 0x61, 0xe4, 0x57, 0x97, 0x97, 0xb5, + 0xd8, 0xed, 0xa0, 0x00, 0x2d, 0xd8, 0x47, 0xad +}; +static const uint8_t ac_dsa_vect35_pub_val[] = { +/* Y */ + 0x49, 0xe6, 0x06, 0xaa, 0xd5, 0xd2, 0xe5, 0x4e, 0x1b, 0xae, 0x25, 0x17, + 0x91, 0x5c, 0x66, 0x0b, 0xa3, 0x0e, 0xc4, 0xfd, 0x28, 0xd7, 0x18, 0x61, + 0x3a, 0x7c, 0x84, 0x46, 0x4b, 0x0f, 0x44, 0xbc, 0x6d, 0x54, 0x6e, 0x5a, + 0x9b, 0xc1, 0xdc, 0x60, 0x42, 0x3b, 0x45, 0xdd, 0x01, 0xec, 0x29, 0x55, + 0x64, 0xec, 0x08, 0xf2, 0x9d, 0x68, 0x87, 0xe6, 0x9f, 0x68, 0x9d, 0x6b, + 0x34, 0x88, 0xf9, 0xda, 0x5d, 0x5a, 0x60, 0xf3, 0x9c, 0xdd, 0x5a, 0x15, + 0x8d, 0x51, 0xa3, 0xd0, 0x73, 0xb2, 0x22, 0x5f, 0xea, 0x55, 0x9e, 0x58, + 0xbb, 0x22, 0x2e, 0x29, 0xa8, 0x7b, 0x5f, 0x0f, 0x5a, 0xb3, 0x1d, 0xd7, + 0xc0, 0xce, 0xaa, 0xd8, 0x87, 0x07, 0x0d, 0xac, 0x95, 0x5d, 0x28, 0x97, + 0x36, 0x07, 0xa9, 0x9e, 0x46, 0xdd, 0xd7, 0x73, 0x7b, 0xea, 0xb6, 0x51, + 0x99, 0xf2, 0x50, 0xd7, 0xf0, 0x3b, 0x65, 0x83 +}; +/* K = 712eed73c8d2567809b4d9ec2f59e77d39290b2b */ +static const uint8_t ac_dsa_vect35_out[] = { +/* R */ + 0x6b, 0xf4, 0xf5, 0xd3, 0x25, 0x12, 0x01, 0x05, 0x9e, 0xe8, 0x5e, 0xdb, + 0x99, 0xa6, 0x7a, 0x70, 0x6f, 0x37, 0x19, 0x7d, +/* S */ + 0x31, 0x25, 0xc5, 0xaf, 0x39, 0x77, 0x59, 0x99, 0x6b, 0x87, 0x6c, 0xb5, + 0x85, 0x7b, 0xe2, 0x63, 0x2a, 0xaa, 0xf3, 0xb6 +}; +#define ac_dsa_vect36_prime ac_dsa_vect31_prime +#define ac_dsa_vect36_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect36_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect36_ptx[] = { +/* Msg */ + 0xad, 0xdb, 0x5a, 0x04, 0x5c, 0x9f, 0x4f, 0x4f, 0xb9, 0xeb, 0x5e, 0x5d, + 0xb4, 0x4d, 0x65, 0x15, 0x98, 0x0c, 0x9e, 0x08, 0x80, 0x15, 0xb6, 0x85, + 0x93, 0xd8, 0xbc, 0xbf, 0xfc, 0x6f, 0xf5, 0x7f, 0x18, 0x86, 0x5a, 0xb8, + 0x24, 0xd3, 0xd1, 0x58, 0x64, 0x25, 0xcb, 0x50, 0x81, 0x19, 0x7e, 0x9e, + 0x01, 0xcb, 0x72, 0x97, 0xb0, 0x6b, 0x64, 0x10, 0x3c, 0xea, 0x43, 0x7e, + 0xee, 0xec, 0x9c, 0x50, 0x79, 0x86, 0x79, 0xfb, 0x86, 0x9e, 0xc3, 0x06, + 0xa7, 0x25, 0x75, 0x05, 0x7f, 0xd3, 0x68, 0xae, 0xb0, 0xf6, 0x74, 0xa2, + 0x9c, 0x3a, 0xc2, 0x48, 0xb6, 0xa0, 0x8f, 0x91, 0x33, 0x1d, 0x84, 0x56, + 0xd0, 0x62, 0x02, 0x53, 0x47, 0xc1, 0x2a, 0x0a, 0x61, 0xc6, 0x1f, 0x76, + 0xe5, 0x20, 0x6f, 0xe6, 0xca, 0x43, 0x77, 0x35, 0xaf, 0x43, 0x0d, 0xea, + 0x7c, 0xc8, 0xf3, 0x9f, 0x1a, 0x5b, 0x75, 0x05 +}; +static const uint8_t ac_dsa_vect36_priv_val[] = { +/* X */ + 0x1f, 0x1c, 0xfc, 0x68, 0x20, 0x48, 0x37, 0x59, 0x15, 0xfb, 0x48, 0x3b, + 0x77, 0x03, 0x7c, 0x81, 0xc0, 0x5e, 0xd7, 0x28 +}; +static const uint8_t ac_dsa_vect36_pub_val[] = { +/* Y */ + 0x22, 0x1c, 0xed, 0x57, 0xa9, 0x13, 0x25, 0xb1, 0x0f, 0x8d, 0xcd, 0x12, + 0x20, 0xb1, 0xaf, 0x68, 0xf8, 0xda, 0xf3, 0x97, 0xf4, 0x19, 0xa4, 0x3b, + 0xbd, 0x8f, 0xbe, 0x64, 0x43, 0x11, 0x75, 0x5b, 0x11, 0x1a, 0xae, 0x52, + 0x57, 0xc6, 0x42, 0xfa, 0xfd, 0x83, 0xb0, 0x47, 0xa1, 0xf5, 0x6f, 0x2a, + 0x82, 0x9f, 0xcd, 0xf4, 0xdf, 0x3e, 0x5d, 0xcc, 0xb2, 0x36, 0x45, 0xb2, + 0x8c, 0x0a, 0x34, 0xc6, 0xe8, 0xa6, 0x50, 0xef, 0xcd, 0xfa, 0xdd, 0x48, + 0xfe, 0xa4, 0x67, 0xcc, 0x94, 0x3c, 0xa4, 0xe7, 0x37, 0x88, 0x29, 0x30, + 0x07, 0x13, 0x83, 0x8b, 0x6c, 0x71, 0x09, 0x62, 0xba, 0x72, 0xe7, 0x90, + 0xc1, 0x0a, 0xb8, 0x79, 0xa0, 0x1f, 0xe1, 0x45, 0x7e, 0xa3, 0xdd, 0x4b, + 0x7c, 0x3c, 0x3a, 0x54, 0x2e, 0x35, 0x22, 0xa7, 0x5d, 0x0d, 0xb2, 0x61, + 0xe5, 0x76, 0xcd, 0x3f, 0x22, 0xc9, 0x98, 0xe4 +}; +/* K = 703154f6c6e12f163ecad0494897dfcf5657fbe2 */ +static const uint8_t ac_dsa_vect36_out[] = { +/* R */ + 0x7c, 0xc6, 0x62, 0xe3, 0x52, 0xe0, 0xee, 0xde, 0x85, 0x14, 0x01, 0x07, + 0xa7, 0x77, 0x3a, 0xd8, 0x66, 0x3e, 0x70, 0xbd, +/* S */ + 0x15, 0xc1, 0x7b, 0x9d, 0x24, 0x58, 0x72, 0x84, 0x4e, 0xaa, 0xc3, 0xd4, + 0x6b, 0xb0, 0x8c, 0x3e, 0x08, 0x59, 0x74, 0x23 +}; +#define ac_dsa_vect37_prime ac_dsa_vect31_prime +#define ac_dsa_vect37_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect37_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect37_ptx[] = { +/* Msg */ + 0x02, 0x70, 0x9d, 0x2b, 0xe0, 0xd9, 0xdc, 0x1d, 0xc0, 0xeb, 0xc5, 0x5f, + 0x63, 0x0d, 0x91, 0xfa, 0x23, 0x60, 0x9f, 0x61, 0xb5, 0x13, 0xc2, 0x27, + 0x57, 0x66, 0x03, 0x4d, 0x8f, 0x40, 0xe8, 0x19, 0xaa, 0xf9, 0x32, 0x6c, + 0x8d, 0xb3, 0x7c, 0x35, 0xc5, 0xa1, 0x7e, 0x96, 0xbc, 0x95, 0x6d, 0xf6, + 0xd1, 0x1b, 0x55, 0x8d, 0x16, 0xd9, 0x18, 0x71, 0xaf, 0xc0, 0x10, 0xb3, + 0x11, 0x9c, 0x57, 0x98, 0xc2, 0xe2, 0x94, 0x11, 0xff, 0x4f, 0x0d, 0x71, + 0x96, 0xe7, 0xe4, 0x76, 0xbf, 0x0a, 0xd0, 0x3b, 0xf7, 0x2e, 0x89, 0x7f, + 0xed, 0x87, 0x3c, 0x10, 0x61, 0x3d, 0xd2, 0x55, 0xd1, 0x52, 0x43, 0x87, + 0x0b, 0x81, 0xcd, 0x87, 0xd0, 0xab, 0xc1, 0x6e, 0x14, 0x0d, 0x03, 0x2f, + 0xe5, 0xbd, 0x1c, 0x8e, 0xeb, 0x2f, 0x66, 0xe0, 0x4d, 0x13, 0xd4, 0x92, + 0x69, 0xfc, 0x7d, 0xa6, 0xb6, 0x5a, 0x7c, 0x1c +}; +static const uint8_t ac_dsa_vect37_priv_val[] = { +/* X */ + 0x1d, 0x9c, 0xf9, 0x8d, 0xc0, 0xc1, 0xd7, 0xbf, 0x8d, 0xec, 0x98, 0x96, + 0x2a, 0xc6, 0xef, 0x6e, 0x94, 0x06, 0xce, 0x76 +}; +static const uint8_t ac_dsa_vect37_pub_val[] = { +/* Y */ + 0x9e, 0x93, 0xbc, 0x03, 0xe6, 0xe8, 0x15, 0x30, 0x87, 0x34, 0xe3, 0xb8, + 0xf1, 0xd1, 0x06, 0x96, 0x1b, 0xeb, 0xdf, 0xf1, 0x0a, 0x52, 0x53, 0x03, + 0x25, 0x7a, 0x05, 0x3d, 0xea, 0x4d, 0xa6, 0xdc, 0xf5, 0x04, 0xc7, 0x83, + 0x9b, 0x54, 0xd5, 0x75, 0x22, 0xf2, 0xac, 0xb3, 0xaa, 0xc9, 0x59, 0xff, + 0x4a, 0xe8, 0x61, 0x00, 0x22, 0xca, 0x5a, 0x1e, 0x68, 0x82, 0x32, 0x33, + 0x6c, 0xa1, 0xee, 0x8f, 0xd7, 0x02, 0x8b, 0xf7, 0xb6, 0xe9, 0xee, 0xdf, + 0x8a, 0x4b, 0x0d, 0x09, 0x89, 0x69, 0xf5, 0xe5, 0xfd, 0x3d, 0x93, 0x00, + 0xc3, 0x40, 0xe7, 0xf1, 0x9f, 0xd4, 0x71, 0xa4, 0x51, 0xaf, 0xb9, 0x2e, + 0xd4, 0x82, 0x9f, 0xa4, 0xd9, 0x02, 0x49, 0x14, 0x4a, 0xa3, 0x63, 0xdc, + 0x18, 0x80, 0x7b, 0x3e, 0x29, 0xd2, 0x7e, 0x6e, 0xc3, 0xda, 0x73, 0x6c, + 0x33, 0xb1, 0x85, 0x51, 0x1b, 0xb3, 0xaa, 0xa0 +}; +/* K = 68ae16534c5f6225fc7ef980f0063de483a76903 */ +static const uint8_t ac_dsa_vect37_out[] = { +/* R */ + 0x72, 0xb0, 0xbc, 0xc6, 0xde, 0xfa, 0x66, 0xfa, 0x8b, 0xab, 0x02, 0x96, + 0x76, 0xa1, 0xc7, 0x70, 0x3f, 0x96, 0x08, 0xf2, +/* S */ + 0x69, 0xd9, 0x11, 0xe0, 0x5a, 0xcd, 0x7b, 0xe5, 0x2f, 0x28, 0x34, 0xc0, + 0xaa, 0x00, 0x51, 0x28, 0xe7, 0xfa, 0x85, 0xb8 +}; +#define ac_dsa_vect38_prime ac_dsa_vect31_prime +#define ac_dsa_vect38_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect38_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect38_ptx[] = { +/* Msg */ + 0xcc, 0x06, 0x1e, 0xdb, 0x31, 0xc3, 0x4d, 0x39, 0x81, 0x51, 0x7f, 0x4d, + 0x89, 0xaf, 0xbe, 0x98, 0x0f, 0x74, 0x18, 0x52, 0x60, 0xcf, 0x48, 0xb3, + 0x04, 0x3b, 0xc1, 0x3a, 0x14, 0x49, 0x44, 0xad, 0x43, 0xe0, 0xe5, 0x76, + 0xd2, 0xa5, 0x8b, 0xf5, 0x89, 0xcc, 0x02, 0x1d, 0xc1, 0xc1, 0xd3, 0x32, + 0xc4, 0xd7, 0x68, 0x96, 0xea, 0x77, 0xdd, 0xa1, 0x97, 0xf6, 0x83, 0xe5, + 0x1e, 0xed, 0x71, 0xb4, 0xd6, 0xdf, 0x46, 0x66, 0x6a, 0x1b, 0x14, 0x2e, + 0x67, 0x9b, 0x02, 0x83, 0xcf, 0x33, 0x9e, 0x5b, 0xca, 0x90, 0xe2, 0xff, + 0x9c, 0x34, 0xdd, 0x5f, 0xd7, 0xcc, 0x49, 0x17, 0xd6, 0x67, 0x04, 0xfe, + 0xe4, 0x36, 0x4f, 0x76, 0x93, 0x10, 0x1d, 0xc7, 0x66, 0x70, 0x71, 0x04, + 0xef, 0xb2, 0xb9, 0x33, 0xc4, 0x84, 0x8b, 0x93, 0xe1, 0x3f, 0x94, 0x85, + 0x5f, 0x75, 0xe4, 0xfd, 0x75, 0x6c, 0xb6, 0xe3 +}; +static const uint8_t ac_dsa_vect38_priv_val[] = { +/* X */ + 0x78, 0xff, 0xb4, 0x0f, 0xd8, 0x94, 0x16, 0x38, 0x88, 0x04, 0xe5, 0x64, + 0x44, 0xc9, 0xa6, 0x42, 0xcb, 0x5e, 0x98, 0xe8 +}; +static const uint8_t ac_dsa_vect38_pub_val[] = { +/* Y */ + 0x5d, 0x7d, 0x2e, 0x34, 0x21, 0x54, 0x98, 0x3e, 0xbc, 0x20, 0x15, 0xbc, + 0x67, 0x50, 0xf9, 0x87, 0x6f, 0x56, 0x89, 0xca, 0x0a, 0xda, 0x85, 0x29, + 0x90, 0x8e, 0xd4, 0xfd, 0xbc, 0x59, 0x6b, 0x97, 0x2c, 0x5c, 0xc6, 0xd5, + 0x3e, 0x80, 0xa8, 0xad, 0x8a, 0x8c, 0xed, 0xf3, 0xce, 0x64, 0xb6, 0x2a, + 0x75, 0xdb, 0x44, 0x1c, 0x96, 0x20, 0x7f, 0xc7, 0x47, 0x7e, 0x3f, 0x7b, + 0x9f, 0x10, 0xdf, 0x28, 0xe0, 0xcc, 0x2f, 0xb7, 0x73, 0x83, 0xe7, 0xca, + 0x4c, 0x51, 0x50, 0xf7, 0x12, 0xdd, 0x82, 0x3c, 0x23, 0x09, 0xf0, 0x16, + 0x1b, 0xe0, 0xbd, 0x5e, 0xed, 0xd6, 0x0c, 0xf6, 0xba, 0x23, 0x08, 0x61, + 0xa0, 0x8b, 0x9d, 0x9a, 0x74, 0x68, 0x43, 0x8b, 0x4d, 0x6e, 0xc6, 0x73, + 0xd2, 0x8a, 0x54, 0xd8, 0x3c, 0x70, 0x10, 0xd5, 0x06, 0x31, 0xe5, 0x5f, + 0x0a, 0x02, 0x83, 0x2a, 0xbc, 0x5a, 0x0a, 0x46 +}; +/* K = 07c6857486160ef4003470411573399fc4e5f7af */ +static const uint8_t ac_dsa_vect38_out[] = { +/* R */ + 0x21, 0xf5, 0x12, 0x42, 0x56, 0x70, 0x94, 0x34, 0x77, 0x53, 0x4e, 0x90, + 0x75, 0xce, 0xb5, 0xb7, 0xd6, 0x3f, 0x20, 0xdf, +/* S */ + 0x73, 0xc6, 0xf6, 0xf8, 0xde, 0x3a, 0xae, 0xa5, 0x20, 0xa0, 0x83, 0xb2, + 0x26, 0x42, 0x99, 0xe8, 0x1c, 0xfc, 0x91, 0xc5 +}; +#define ac_dsa_vect39_prime ac_dsa_vect31_prime +#define ac_dsa_vect39_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect39_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect39_ptx[] = { +/* Msg */ + 0x79, 0xd5, 0x29, 0xe4, 0x0c, 0x2b, 0xa4, 0xe5, 0xb9, 0xc7, 0xd7, 0x7d, + 0x72, 0x07, 0x6f, 0x1f, 0xd9, 0x49, 0x09, 0x28, 0xff, 0x44, 0x19, 0xc8, + 0x24, 0xe6, 0x4d, 0xb8, 0xfb, 0x9a, 0x05, 0x1e, 0x01, 0xe8, 0xe1, 0x73, + 0xc6, 0xf2, 0x14, 0xe0, 0xe9, 0xe6, 0x45, 0xed, 0x25, 0x0b, 0x6d, 0xaa, + 0xa6, 0xf8, 0xc1, 0xa5, 0xcc, 0x90, 0x0d, 0x52, 0xcf, 0x3e, 0x1e, 0xfb, + 0xfe, 0xa2, 0x57, 0x48, 0xe8, 0x9a, 0x1a, 0x54, 0x8c, 0x73, 0xe2, 0xd1, + 0x10, 0xb2, 0x5f, 0x53, 0x08, 0xbc, 0xf7, 0x57, 0xb2, 0x13, 0x52, 0x16, + 0xc9, 0x1d, 0xca, 0x27, 0x83, 0x33, 0x2c, 0x0d, 0x79, 0x03, 0xeb, 0x21, + 0xc2, 0x26, 0xdb, 0xd3, 0x3a, 0x69, 0xee, 0xf5, 0x75, 0xaa, 0x8a, 0x41, + 0xcb, 0xbd, 0xcd, 0x1b, 0x3d, 0x94, 0x92, 0x8a, 0xa8, 0xf8, 0xba, 0x58, + 0xc5, 0xce, 0x0d, 0x31, 0x77, 0x86, 0xe8, 0x7b +}; +static const uint8_t ac_dsa_vect39_priv_val[] = { +/* X */ + 0x78, 0x4b, 0x9d, 0xb2, 0xd1, 0x9e, 0xf0, 0xca, 0x8e, 0x69, 0x68, 0x84, + 0xc7, 0x71, 0x1d, 0xc2, 0xf8, 0xce, 0x15, 0x0a +}; +static const uint8_t ac_dsa_vect39_pub_val[] = { +/* Y */ + 0x28, 0x2d, 0xec, 0xc0, 0xe3, 0x79, 0x94, 0xc2, 0x85, 0x6e, 0x61, 0xf3, + 0x6b, 0x83, 0x1b, 0x61, 0xbd, 0xc0, 0x2b, 0x7c, 0xa6, 0x75, 0xdb, 0xc3, + 0xc2, 0x03, 0x28, 0x00, 0xb7, 0xef, 0xd3, 0xb7, 0x11, 0xac, 0xf1, 0x4c, + 0x88, 0x69, 0x96, 0x88, 0x31, 0xe1, 0x45, 0x36, 0x1b, 0xf2, 0x18, 0x2b, + 0x06, 0x0e, 0x48, 0x38, 0xf0, 0x7d, 0xc6, 0x1f, 0x76, 0x58, 0x4c, 0xf1, + 0x02, 0xa9, 0x13, 0xbb, 0x28, 0xa5, 0x2c, 0x73, 0x17, 0xaf, 0x5f, 0x9d, + 0x23, 0x22, 0x92, 0x7c, 0x96, 0x66, 0xe5, 0xe8, 0x7c, 0x2f, 0x2b, 0xfd, + 0x2f, 0x18, 0x1d, 0xd3, 0x26, 0x12, 0xd7, 0xb2, 0xb2, 0xa6, 0x45, 0xbf, + 0x1a, 0x47, 0xc0, 0xeb, 0xfd, 0x79, 0xa9, 0x40, 0xf6, 0x27, 0xa6, 0x68, + 0xa8, 0xf2, 0xeb, 0x72, 0x9f, 0xd0, 0x51, 0xaa, 0x2c, 0x65, 0x9a, 0xbc, + 0x91, 0x8e, 0x55, 0x71, 0x99, 0x4e, 0x65, 0x93 +}; +/* K = 1bfcf3290fa84652a476655506b145743213e1b4 */ +static const uint8_t ac_dsa_vect39_out[] = { +/* R */ + 0x92, 0x9a, 0x48, 0x51, 0xbe, 0x0a, 0xe4, 0xba, 0x91, 0xda, 0x0e, 0x6c, + 0x73, 0x76, 0xd7, 0x1d, 0xf7, 0x59, 0x2d, 0xbb, +/* S */ + 0x7e, 0x6b, 0x65, 0x04, 0xb7, 0x48, 0xef, 0x00, 0x24, 0xd9, 0xd2, 0xa2, + 0xe6, 0xf3, 0xbc, 0xd7, 0xcf, 0x13, 0x5a, 0xc7 +}; +#define ac_dsa_vect40_prime ac_dsa_vect31_prime +#define ac_dsa_vect40_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect40_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect40_ptx[] = { +/* Msg */ + 0xf5, 0x51, 0x64, 0x10, 0x70, 0x63, 0x23, 0x54, 0x9b, 0x20, 0xc5, 0x2d, + 0xaf, 0xa2, 0xf2, 0xf9, 0x07, 0x99, 0x78, 0x6c, 0x0d, 0xdb, 0x85, 0x04, + 0x88, 0x92, 0xcc, 0xc1, 0x87, 0x20, 0xdc, 0xe5, 0xc1, 0x29, 0xa1, 0x0e, + 0xb4, 0x38, 0x87, 0x88, 0xa3, 0xd9, 0x7a, 0x03, 0xb0, 0x00, 0x17, 0x99, + 0xcb, 0x65, 0xa7, 0x9c, 0x88, 0x08, 0x36, 0xbc, 0x9f, 0x32, 0x04, 0xea, + 0x75, 0xa5, 0x77, 0x20, 0x4d, 0xc1, 0xe2, 0x89, 0x4c, 0x57, 0x2a, 0x25, + 0x8f, 0x9e, 0x51, 0x7c, 0xa3, 0x7c, 0x5b, 0x79, 0x1e, 0x48, 0xb2, 0x7c, + 0x8d, 0xc1, 0xc8, 0x21, 0xb3, 0x4e, 0xbb, 0x1f, 0x29, 0x85, 0x8c, 0x4a, + 0x72, 0xa0, 0xd5, 0x17, 0x2c, 0x56, 0x5e, 0x9d, 0xbe, 0x1b, 0xdd, 0xdf, + 0x6e, 0x02, 0x48, 0x91, 0xcd, 0x62, 0x91, 0xfa, 0xa8, 0x1e, 0xd5, 0x65, + 0x74, 0x6c, 0x61, 0xc2, 0xed, 0xa2, 0x01, 0x1f +}; +static const uint8_t ac_dsa_vect40_priv_val[] = { +/* X */ + 0x67, 0x3a, 0x38, 0x46, 0x87, 0xef, 0x29, 0xeb, 0xfa, 0x66, 0xe3, 0x31, + 0x86, 0x6b, 0xd2, 0x06, 0xca, 0x2f, 0x76, 0x64 +}; +static const uint8_t ac_dsa_vect40_pub_val[] = { +/* Y */ + 0x74, 0xcc, 0xc6, 0xeb, 0x83, 0xad, 0xbc, 0xba, 0xd0, 0xfc, 0x37, 0x14, + 0x4d, 0x9b, 0xfb, 0x85, 0xfd, 0xcc, 0x85, 0xab, 0x92, 0xc9, 0xf8, 0x87, + 0x7c, 0x9c, 0xda, 0x66, 0x25, 0x1d, 0x1a, 0xff, 0x2f, 0xb2, 0x24, 0x88, + 0x8d, 0xdd, 0xb7, 0xd7, 0x72, 0xa8, 0xb7, 0x38, 0xc5, 0x3e, 0x03, 0xec, + 0xad, 0x99, 0x03, 0x79, 0x6f, 0xa3, 0xc9, 0xc6, 0x02, 0x4d, 0x06, 0x36, + 0x7e, 0x08, 0x70, 0xad, 0x79, 0x76, 0x94, 0xf5, 0x98, 0x70, 0x8d, 0x08, + 0x91, 0x2c, 0x0f, 0xe0, 0x98, 0x81, 0x76, 0x3a, 0x0a, 0x72, 0x2d, 0xda, + 0x95, 0xd9, 0x4e, 0xee, 0x88, 0x24, 0x92, 0x7c, 0xbf, 0xa6, 0x76, 0x1a, + 0x79, 0xa0, 0x38, 0xaa, 0x6d, 0x33, 0x1d, 0xa3, 0x4d, 0x9b, 0xd5, 0xc5, + 0x83, 0x3c, 0x94, 0xc5, 0x26, 0xa8, 0x6a, 0xf1, 0xcd, 0xfb, 0x2d, 0x40, + 0x79, 0xd2, 0xdb, 0x6d, 0x0b, 0x9a, 0x12, 0x38 +}; +/* K = 52ee4510675f0da529684fa60f6848ce63c4689f */ +static const uint8_t ac_dsa_vect40_out[] = { +/* R */ + 0x27, 0xb3, 0xf2, 0x35, 0xe4, 0xaf, 0xc1, 0x8c, 0x66, 0x13, 0xb4, 0xfa, + 0x7f, 0x27, 0xd7, 0xa8, 0x26, 0x2b, 0xa4, 0xc0, +/* S */ + 0x8b, 0x22, 0x63, 0x4e, 0x4d, 0x45, 0xb7, 0x1a, 0x84, 0xea, 0xba, 0xa1, + 0xe5, 0xa4, 0xbf, 0x1e, 0x37, 0x33, 0x7a, 0x59 +}; +#define ac_dsa_vect41_prime ac_dsa_vect31_prime +#define ac_dsa_vect41_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect41_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect41_ptx[] = { +/* Msg */ + 0x55, 0xbd, 0x15, 0x26, 0xe0, 0x8f, 0x64, 0x43, 0xb2, 0x55, 0xac, 0xd3, + 0x2c, 0x28, 0x68, 0x07, 0x54, 0x2d, 0x34, 0xc0, 0xf3, 0xd7, 0x98, 0x92, + 0x71, 0x3f, 0x9d, 0x6d, 0x6d, 0x6b, 0x3b, 0xe7, 0x07, 0xe4, 0xaf, 0x6e, + 0x71, 0xf7, 0xda, 0xb4, 0xa2, 0xc5, 0xf6, 0xbd, 0x25, 0xf5, 0xae, 0x1f, + 0x51, 0x4b, 0x26, 0x44, 0xa4, 0xcd, 0xaf, 0xce, 0xce, 0x1e, 0x58, 0xf7, + 0x57, 0x6f, 0x82, 0xe2, 0xab, 0x0a, 0xf2, 0x32, 0x6c, 0x71, 0x27, 0x9e, + 0x9b, 0xce, 0xf1, 0xe1, 0xc5, 0x4a, 0x76, 0xfa, 0x77, 0xec, 0x2b, 0x2d, + 0x05, 0x67, 0x17, 0x64, 0x57, 0x64, 0xe7, 0x99, 0x1b, 0x52, 0x0b, 0x0e, + 0x5a, 0x1b, 0x04, 0x91, 0x09, 0x51, 0x9b, 0x22, 0xaa, 0x52, 0x04, 0xe3, + 0xed, 0x53, 0xb1, 0xe0, 0x95, 0x7d, 0xab, 0x5e, 0xc3, 0x24, 0x79, 0xd0, + 0x6a, 0xc3, 0xe1, 0x1a, 0x5d, 0x1c, 0xbd, 0x03 +}; +static const uint8_t ac_dsa_vect41_priv_val[] = { +/* X */ + 0x49, 0x50, 0x09, 0xf3, 0xa9, 0x25, 0x48, 0xbe, 0x4c, 0x9a, 0x56, 0x2f, + 0xf7, 0x03, 0x18, 0x7b, 0x0e, 0xc2, 0xcc, 0x86 +}; +static const uint8_t ac_dsa_vect41_pub_val[] = { +/* Y */ + 0x5d, 0x6e, 0xdf, 0x6d, 0xb6, 0xe6, 0xc2, 0x7e, 0x80, 0xa7, 0xf0, 0x25, + 0x97, 0x23, 0x79, 0x19, 0x17, 0x0b, 0x49, 0x36, 0x48, 0x9d, 0x6f, 0x15, + 0xf5, 0x98, 0xb8, 0x20, 0xcd, 0x91, 0x7e, 0x17, 0x25, 0x09, 0xb7, 0xe2, + 0x87, 0xb8, 0x8b, 0x0c, 0xc1, 0x4e, 0x1a, 0x01, 0x86, 0x79, 0x38, 0x86, + 0x80, 0x9a, 0xb4, 0x17, 0x02, 0x09, 0x98, 0x70, 0x95, 0x09, 0x22, 0x34, + 0xb4, 0xfd, 0xc4, 0x4b, 0x3d, 0x1f, 0xc1, 0x6e, 0xeb, 0x2e, 0xfa, 0xf8, + 0x52, 0xed, 0x39, 0x16, 0x69, 0x8c, 0xf9, 0xec, 0xa4, 0x61, 0x2b, 0x49, + 0x61, 0xbb, 0x6e, 0x20, 0xc3, 0x2e, 0x18, 0x84, 0x69, 0x88, 0x3f, 0x97, + 0xf4, 0x9e, 0x29, 0xa8, 0x19, 0x7c, 0x30, 0xd0, 0x72, 0x3b, 0xab, 0xb0, + 0x6d, 0xea, 0x70, 0x4f, 0x77, 0x04, 0xb2, 0x78, 0x8e, 0x57, 0xd7, 0x6d, + 0x6d, 0x9a, 0x3c, 0xfa, 0x68, 0xf6, 0xc7, 0x83 +}; +/* K = 423308bb414ef959025bf1a4b27db278f904241d */ +static const uint8_t ac_dsa_vect41_out[] = { +/* R */ + 0x62, 0x1a, 0x29, 0x09, 0x30, 0xac, 0x43, 0x67, 0x37, 0xa7, 0x2f, 0xb4, + 0xc6, 0x2b, 0xf5, 0xc4, 0xb6, 0x74, 0x81, 0xaf, +/* S */ + 0x62, 0xdb, 0x20, 0xf8, 0x2a, 0x57, 0x54, 0xf1, 0x09, 0xf7, 0xa2, 0xce, + 0x58, 0x1d, 0x4c, 0x8d, 0x71, 0xc6, 0x8d, 0x29 +}; +#define ac_dsa_vect42_prime ac_dsa_vect31_prime +#define ac_dsa_vect42_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect42_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect42_ptx[] = { +/* Msg */ + 0x62, 0x78, 0x9a, 0x89, 0xf0, 0xd7, 0x08, 0xe2, 0x1a, 0x12, 0x1f, 0xc3, + 0x40, 0x09, 0xaf, 0x88, 0x41, 0x33, 0x68, 0x1b, 0x9d, 0x4a, 0x66, 0xcc, + 0x36, 0xc0, 0x36, 0x5c, 0x34, 0xbe, 0x72, 0xa4, 0x98, 0x2e, 0xb0, 0x96, + 0x1c, 0xe2, 0x57, 0xf3, 0x5e, 0x6e, 0x71, 0x83, 0xf0, 0x20, 0x4a, 0x96, + 0xa5, 0x45, 0x19, 0x30, 0x01, 0x02, 0x3d, 0x33, 0x09, 0xa8, 0x99, 0x7e, + 0x7c, 0x4b, 0x76, 0x2a, 0xb4, 0xf4, 0xc4, 0x0e, 0x03, 0xe1, 0x3f, 0x4e, + 0xdb, 0x32, 0x8b, 0x23, 0xcf, 0x00, 0xc0, 0x91, 0x19, 0xde, 0xb4, 0x0a, + 0xdd, 0xf6, 0x56, 0x7b, 0x3b, 0x74, 0xac, 0xef, 0x5c, 0xef, 0xf0, 0x45, + 0x30, 0x4d, 0x61, 0x84, 0x21, 0xe8, 0x73, 0xc4, 0x1a, 0x72, 0xd3, 0x1e, + 0x45, 0x1d, 0x21, 0x3b, 0x06, 0x08, 0x29, 0xb2, 0x86, 0xf6, 0x40, 0x13, + 0xd4, 0xd9, 0x34, 0x2a, 0xe7, 0xab, 0x80, 0x64 +}; +static const uint8_t ac_dsa_vect42_priv_val[] = { +/* X */ + 0x2b, 0x8d, 0xd3, 0x96, 0x59, 0x92, 0xfc, 0xff, 0xd1, 0x58, 0xa0, 0x81, + 0x6a, 0x59, 0x87, 0xf8, 0x09, 0x08, 0xb8, 0x4c +}; +static const uint8_t ac_dsa_vect42_pub_val[] = { +/* Y */ + 0xad, 0x59, 0x05, 0x90, 0xa8, 0x2e, 0x89, 0x29, 0xca, 0x86, 0xf4, 0x05, + 0x51, 0x6c, 0x32, 0x91, 0x3b, 0xf5, 0x28, 0x2f, 0x70, 0x30, 0x9c, 0x6d, + 0x4a, 0x88, 0xcc, 0xf1, 0x65, 0xce, 0x15, 0xfc, 0xf1, 0x1e, 0x14, 0x0c, + 0x36, 0x6b, 0xb2, 0x73, 0x83, 0x9a, 0x71, 0x1c, 0xb6, 0xae, 0x52, 0xbb, + 0x71, 0x78, 0x59, 0x57, 0x0f, 0xdb, 0xf9, 0xfc, 0x26, 0x72, 0x67, 0x28, + 0x59, 0x6e, 0x6f, 0xc7, 0x19, 0x23, 0xde, 0xad, 0xb3, 0x5a, 0x9d, 0x57, + 0xcd, 0xb2, 0x13, 0xc0, 0xf2, 0x9c, 0x13, 0x75, 0xf8, 0xb1, 0xd3, 0xc6, + 0xb5, 0x26, 0x90, 0xc4, 0x28, 0xf7, 0x48, 0x1c, 0x14, 0xaa, 0xd8, 0x2f, + 0xba, 0x7f, 0x24, 0xee, 0xa8, 0xcd, 0x8d, 0xa7, 0xf0, 0xef, 0x7a, 0xe7, + 0x81, 0xc1, 0xa9, 0x26, 0x67, 0x1a, 0x61, 0xd4, 0xe5, 0xff, 0xc8, 0xdd, + 0xf1, 0xbc, 0x10, 0xd6, 0x88, 0xa9, 0x04, 0xc6 +}; +/* K = 58ccff88958d5fc48d671ba22ed71f5f82370ac6 */ +static const uint8_t ac_dsa_vect42_out[] = { +/* R */ + 0x89, 0xdc, 0xbc, 0xa7, 0xc8, 0xcd, 0x6b, 0x90, 0xaa, 0x90, 0x6a, 0x4c, + 0x54, 0x71, 0x53, 0x76, 0x2f, 0xcf, 0xff, 0xd6, +/* S */ + 0x23, 0xe8, 0x92, 0x6b, 0x18, 0xcf, 0xd4, 0xb6, 0x7c, 0x53, 0xfa, 0xc4, + 0xa2, 0xd5, 0x32, 0x1e, 0x5c, 0x3d, 0x88, 0x0c +}; +#define ac_dsa_vect43_prime ac_dsa_vect31_prime +#define ac_dsa_vect43_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect43_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect43_ptx[] = { +/* Msg */ + 0x4e, 0xaf, 0xcc, 0x68, 0x74, 0xae, 0x2a, 0x6d, 0x52, 0x57, 0x38, 0x96, + 0x7a, 0xfb, 0x30, 0x54, 0x35, 0x7a, 0x39, 0x67, 0x0d, 0x1e, 0x55, 0x55, + 0xd7, 0xdc, 0x55, 0xbe, 0x24, 0xdd, 0x5a, 0x32, 0xa0, 0xc7, 0xca, 0x3f, + 0x1b, 0x5c, 0x6d, 0x94, 0x8c, 0x9c, 0xe3, 0x91, 0x01, 0x3a, 0xbe, 0xb4, + 0x7f, 0x7e, 0x24, 0xcd, 0x2c, 0x54, 0xe1, 0xfc, 0x7c, 0x0e, 0x92, 0xc4, + 0xab, 0x77, 0xf5, 0x97, 0x3a, 0x70, 0x54, 0xbd, 0x1c, 0x6c, 0x84, 0x5b, + 0x80, 0x2b, 0x79, 0x37, 0xd6, 0x52, 0x05, 0x08, 0xae, 0x01, 0x8a, 0xe1, + 0x4b, 0x27, 0xff, 0x4b, 0x1e, 0x34, 0x0a, 0x4b, 0x9f, 0x6f, 0x6b, 0x48, + 0x14, 0xd0, 0x7e, 0x90, 0xcb, 0x8f, 0x19, 0xb1, 0x5e, 0x91, 0x5d, 0x6a, + 0xd1, 0x83, 0x4c, 0x0f, 0x7a, 0x3c, 0x3e, 0x1e, 0x45, 0x20, 0x67, 0x72, + 0xa0, 0xee, 0xc2, 0xd3, 0xf9, 0x16, 0x08, 0x97 +}; +static const uint8_t ac_dsa_vect43_priv_val[] = { +/* X */ + 0x6b, 0x3a, 0xce, 0xe4, 0x22, 0x76, 0xbb, 0xa1, 0x55, 0x15, 0x6f, 0x23, + 0xdf, 0xb7, 0xcd, 0xf6, 0x4e, 0x4b, 0x1a, 0xe8 +}; +static const uint8_t ac_dsa_vect43_pub_val[] = { +/* Y */ + 0xb9, 0x3d, 0x79, 0x47, 0x2f, 0x04, 0x98, 0x93, 0x77, 0x9a, 0x3a, 0x0e, + 0x83, 0xb3, 0x85, 0x3f, 0x78, 0xb3, 0xcf, 0x69, 0xb7, 0x59, 0x61, 0xa6, + 0x0e, 0x95, 0x0f, 0x0c, 0x00, 0xf4, 0x98, 0xf3, 0xea, 0xa2, 0x38, 0x43, + 0x25, 0xf7, 0x4d, 0xdd, 0x38, 0x29, 0x2f, 0xbd, 0xbd, 0xb1, 0x99, 0x21, + 0x2e, 0x90, 0xb1, 0x4e, 0xc9, 0xe5, 0x54, 0x72, 0x7d, 0xf8, 0x1e, 0x06, + 0xeb, 0x77, 0x83, 0xad, 0xda, 0x38, 0x69, 0x1c, 0x63, 0xa7, 0xcb, 0x00, + 0xcd, 0x76, 0xd8, 0xe1, 0x8e, 0x3d, 0x29, 0xc7, 0x93, 0xe9, 0xf1, 0xfe, + 0x83, 0x37, 0xf1, 0x59, 0x8b, 0x89, 0x65, 0x1f, 0x63, 0x4c, 0xb7, 0x03, + 0xf2, 0x18, 0xe1, 0x90, 0x63, 0x19, 0xf8, 0x2a, 0xc6, 0xd5, 0x8e, 0x67, + 0x86, 0xda, 0x7a, 0xec, 0xfb, 0xca, 0x59, 0x39, 0xf0, 0x3a, 0x13, 0xe7, + 0xb4, 0xd5, 0xa8, 0xac, 0x81, 0x2d, 0x78, 0x29 +}; +/* K = 1c48f62bd097d7686879d33ee5771558e453bb3d */ +static const uint8_t ac_dsa_vect43_out[] = { +/* R */ + 0x63, 0x3e, 0x98, 0x12, 0xa0, 0x65, 0x7c, 0xec, 0x33, 0x26, 0xaa, 0x54, + 0x15, 0x34, 0x0c, 0x46, 0x36, 0x2f, 0xcd, 0x4b, +/* S */ + 0x6b, 0x20, 0x1f, 0x0c, 0x3f, 0xd4, 0x42, 0x47, 0xf6, 0xc2, 0x8c, 0x01, + 0xd1, 0x21, 0x7e, 0xb9, 0x91, 0x46, 0xc0, 0x40 +}; +#define ac_dsa_vect44_prime ac_dsa_vect31_prime +#define ac_dsa_vect44_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect44_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect44_ptx[] = { +/* Msg */ + 0x86, 0xd9, 0x89, 0x2b, 0x48, 0xf5, 0x95, 0x41, 0x01, 0x48, 0x27, 0x42, + 0xc0, 0xda, 0xfb, 0x68, 0xdc, 0x97, 0x12, 0x24, 0x83, 0xb9, 0xe4, 0x59, + 0xf9, 0x74, 0x95, 0xcc, 0x97, 0x0e, 0x05, 0x6d, 0x21, 0x62, 0xc7, 0xc7, + 0x1d, 0xb1, 0x67, 0x22, 0x9f, 0xb7, 0xf4, 0x52, 0x09, 0xe0, 0xc0, 0x1e, + 0xb0, 0x6f, 0xf9, 0x24, 0xb8, 0x23, 0xed, 0xa5, 0x1a, 0x7e, 0x99, 0x0f, + 0x3c, 0x98, 0x6e, 0xb9, 0xaf, 0x2a, 0x7a, 0x07, 0x3f, 0x75, 0x4c, 0xb8, + 0x4d, 0xb4, 0x53, 0xa9, 0xe8, 0xc0, 0xae, 0x7f, 0xa5, 0xc0, 0x5a, 0x26, + 0x55, 0xd2, 0x61, 0xad, 0x7e, 0xc5, 0x61, 0x28, 0x76, 0xfa, 0x7d, 0xf0, + 0x95, 0x22, 0xe0, 0xb6, 0x9a, 0xe9, 0x24, 0x77, 0xf6, 0x3d, 0xef, 0x19, + 0x92, 0xc9, 0x6c, 0xe9, 0x5e, 0xe7, 0xbd, 0x63, 0x0e, 0xc1, 0x61, 0x46, + 0x21, 0xda, 0x6a, 0x51, 0x2a, 0xb5, 0x3d, 0xd7 +}; +static const uint8_t ac_dsa_vect44_priv_val[] = { +/* X */ + 0x83, 0x6d, 0x90, 0xfd, 0x90, 0xd2, 0x1b, 0x84, 0xbb, 0x01, 0x2d, 0xa7, + 0xb2, 0x16, 0x8e, 0xa8, 0xf0, 0x52, 0x02, 0xcf +}; +static const uint8_t ac_dsa_vect44_pub_val[] = { +/* Y */ + 0xae, 0x26, 0x4e, 0xa9, 0x6b, 0xf0, 0x93, 0xef, 0x2d, 0xe2, 0x73, 0x81, + 0x73, 0x82, 0x19, 0xe3, 0xbf, 0xdb, 0x08, 0x61, 0x69, 0x67, 0xcd, 0x13, + 0xe9, 0x41, 0x5f, 0x47, 0x5c, 0x4a, 0x79, 0x4c, 0x19, 0xf1, 0x2a, 0x60, + 0x7b, 0x89, 0x8d, 0xb1, 0xe3, 0xe6, 0xbc, 0x54, 0x02, 0x32, 0x75, 0x85, + 0xd3, 0x28, 0x41, 0xae, 0x15, 0xe3, 0x46, 0x28, 0x80, 0x85, 0x0e, 0x9e, + 0x41, 0x36, 0xa4, 0x75, 0x1b, 0x64, 0xa7, 0x29, 0xea, 0x27, 0xb7, 0x2c, + 0xe3, 0x61, 0x28, 0xa4, 0x4f, 0xa5, 0x37, 0x52, 0xa0, 0x8d, 0x73, 0x58, + 0x4f, 0xaa, 0x44, 0xfb, 0x14, 0x12, 0x0f, 0x47, 0xa0, 0x4c, 0x47, 0xe9, + 0x89, 0xea, 0xda, 0xbc, 0x7e, 0x5c, 0xdb, 0x15, 0xd2, 0x7c, 0x2b, 0x0e, + 0xa4, 0x25, 0x7c, 0xec, 0x22, 0x9a, 0x2c, 0x7b, 0xf7, 0xc9, 0x3c, 0x57, + 0x1e, 0x8d, 0x22, 0xae, 0xaa, 0x2e, 0x38, 0xbe +}; +/* K = 7956ea15111ff392d6a9359067bfd8c21f0bfc0b */ +static const uint8_t ac_dsa_vect44_out[] = { +/* R */ + 0x77, 0xb4, 0x80, 0x88, 0x5c, 0x70, 0xc1, 0xfe, 0xe2, 0x05, 0x62, 0x37, + 0xd1, 0xb7, 0x9c, 0xfd, 0x9f, 0xb5, 0x4a, 0x1f, +/* S */ + 0x22, 0x83, 0xf4, 0xc0, 0x64, 0x0f, 0xf6, 0xda, 0xac, 0xbd, 0xfb, 0xbe, + 0xf7, 0x22, 0x4a, 0xfa, 0x59, 0xca, 0x39, 0x59 +}; +#define ac_dsa_vect45_prime ac_dsa_vect31_prime +#define ac_dsa_vect45_sub_prime ac_dsa_vect31_sub_prime +#define ac_dsa_vect45_base ac_dsa_vect31_base +static const uint8_t ac_dsa_vect45_ptx[] = { +/* Msg */ + 0x8b, 0x60, 0xb9, 0xb6, 0xba, 0x37, 0x54, 0x48, 0xde, 0x4f, 0x00, 0xde, + 0x51, 0xd1, 0x87, 0x06, 0xef, 0x8c, 0x4f, 0x97, 0xba, 0x34, 0xc9, 0xcc, + 0xe2, 0xb0, 0xab, 0xb0, 0x69, 0x84, 0x36, 0x00, 0x9d, 0x1d, 0x2b, 0xaf, + 0xcb, 0xef, 0x73, 0xa8, 0xb5, 0xdf, 0xf6, 0xa3, 0xcd, 0x5d, 0xb5, 0x25, + 0x8a, 0xc8, 0x4e, 0xf7, 0x24, 0xb2, 0x8d, 0x8a, 0x62, 0xd7, 0x15, 0xda, + 0x6e, 0x11, 0x19, 0x39, 0x73, 0x53, 0x66, 0xa7, 0xc6, 0x64, 0x70, 0x36, + 0x45, 0x57, 0xf5, 0x46, 0x37, 0x7d, 0x5c, 0x0e, 0x7e, 0xa9, 0x06, 0x47, + 0x31, 0xcb, 0x71, 0x49, 0xe1, 0x05, 0x1d, 0x66, 0xa7, 0xbe, 0xd1, 0x4a, + 0xa2, 0x05, 0xbd, 0xc5, 0xd4, 0xb9, 0xca, 0x02, 0x9a, 0x1e, 0x68, 0xa6, + 0xfa, 0x2c, 0x1d, 0xb2, 0x2d, 0x27, 0xfb, 0x79, 0xd8, 0x38, 0x77, 0xcf, + 0xaa, 0x67, 0x42, 0x11, 0x92, 0x29, 0xa4, 0x93 +}; +static const uint8_t ac_dsa_vect45_priv_val[] = { +/* X */ + 0x5a, 0x4a, 0xe9, 0xf8, 0xfc, 0x82, 0xc9, 0x19, 0x8d, 0x94, 0x00, 0xc5, + 0x1f, 0x28, 0x24, 0x93, 0xb1, 0x94, 0xa0, 0x7b +}; +static const uint8_t ac_dsa_vect45_pub_val[] = { +/* Y */ + 0x87, 0x03, 0x2f, 0x26, 0x3d, 0xe2, 0xbf, 0x2f, 0x26, 0x8a, 0x09, 0x3f, + 0x33, 0xc3, 0x66, 0xd6, 0xbc, 0xda, 0x77, 0x2c, 0xa9, 0x59, 0xfa, 0x17, + 0xcf, 0xe9, 0x48, 0xf1, 0xdc, 0xa3, 0xe7, 0x5e, 0xc9, 0x42, 0x76, 0xde, + 0x91, 0xd9, 0xbc, 0x60, 0xfc, 0x6a, 0xb9, 0x22, 0x48, 0x61, 0xc5, 0x5d, + 0xc9, 0xcc, 0xc5, 0xf7, 0x15, 0xc2, 0x51, 0xdd, 0x50, 0x8b, 0xd4, 0x38, + 0x68, 0x1c, 0xab, 0x20, 0x50, 0x59, 0x05, 0x0f, 0x8e, 0x11, 0xe8, 0xa5, + 0x46, 0x8d, 0xa4, 0x2d, 0x20, 0xae, 0xfa, 0xc5, 0x3d, 0x7a, 0x9f, 0xb7, + 0x1f, 0x64, 0x24, 0xd7, 0xbd, 0xc6, 0x5d, 0xb8, 0x73, 0xee, 0x4f, 0x9d, + 0xcd, 0x91, 0x80, 0x91, 0xaa, 0x72, 0x4b, 0x26, 0x1b, 0x60, 0x56, 0xf3, + 0x20, 0xca, 0x77, 0x24, 0x51, 0x8e, 0x14, 0xcb, 0x8d, 0xba, 0x0b, 0x71, + 0x3f, 0x54, 0xa0, 0xfe, 0x44, 0xff, 0x15, 0x97 +}; +/* K = 662351e9b8c3a607afdf3ee599b46681e27b83c0 */ +static const uint8_t ac_dsa_vect45_out[] = { +/* R */ + 0x5d, 0x15, 0x9f, 0x89, 0x4d, 0x25, 0x0d, 0xb9, 0x0d, 0x7f, 0xcc, 0xd4, + 0x93, 0x29, 0xe4, 0x4d, 0x11, 0x12, 0xdb, 0x47, +/* S */ + 0x37, 0x23, 0x1b, 0xc1, 0x51, 0x95, 0xec, 0xb6, 0xba, 0xdb, 0x7c, 0x3f, + 0xe8, 0x03, 0x80, 0xff, 0x91, 0x2b, 0xae, 0xda +}; +/* [mod = L=1024, N=160, SHA-384] */ +static const uint8_t ac_dsa_vect46_prime[] = { +/* P */ + 0xf2, 0x4a, 0x4a, 0xfc, 0x72, 0xc7, 0xe3, 0x73, 0xa3, 0xc3, 0x09, 0x62, + 0x33, 0x2f, 0xe5, 0x40, 0x5c, 0x45, 0x93, 0x09, 0x63, 0x90, 0x94, 0x18, + 0xc3, 0x07, 0x92, 0xaa, 0xf1, 0x35, 0xdd, 0xea, 0x56, 0x1e, 0x94, 0xf2, + 0x47, 0x26, 0x71, 0x6b, 0x75, 0xa1, 0x88, 0x28, 0x98, 0x2e, 0x4c, 0xe4, + 0x4c, 0x1f, 0xdd, 0xcb, 0x74, 0x64, 0x87, 0xb6, 0xb7, 0x7a, 0x9a, 0x5a, + 0x17, 0xf8, 0x68, 0xab, 0x50, 0xcd, 0x62, 0x1b, 0x5b, 0xc9, 0xda, 0x47, + 0x08, 0x80, 0xb2, 0x87, 0xd7, 0x39, 0x81, 0x90, 0xa4, 0x2a, 0x5e, 0xe2, + 0x2e, 0xd8, 0xd1, 0xff, 0x14, 0x7e, 0x20, 0x19, 0x81, 0x0c, 0x82, 0x98, + 0xed, 0x68, 0xe1, 0xca, 0x69, 0xd4, 0x1d, 0x55, 0x5f, 0x24, 0x9e, 0x64, + 0x9f, 0xb1, 0x72, 0x5d, 0xdb, 0x07, 0x5c, 0x17, 0xb3, 0x7b, 0xef, 0xf4, + 0x67, 0xfd, 0xd1, 0x60, 0x92, 0x43, 0x37, 0x3f +}; +static const uint8_t ac_dsa_vect46_sub_prime[] = { +/* Q */ + 0xda, 0x06, 0x5a, 0x07, 0x8d, 0xdb, 0x56, 0xee, 0x5d, 0x2a, 0xd0, 0x6c, + 0xaf, 0xab, 0x20, 0x82, 0x0d, 0x2c, 0x47, 0x55 +}; +static const uint8_t ac_dsa_vect46_base[] = { +/* G */ + 0x47, 0xb5, 0x59, 0x1b, 0x79, 0x04, 0x3e, 0x4e, 0x03, 0xca, 0x78, 0xa0, + 0xe2, 0x77, 0xc9, 0xa2, 0x1e, 0x2a, 0x6b, 0x54, 0x3b, 0xf4, 0xf0, 0x44, + 0x10, 0x4c, 0xd9, 0xac, 0x93, 0xef, 0xf8, 0xe1, 0x01, 0xbb, 0x60, 0x31, + 0xef, 0xc8, 0xc5, 0x96, 0xd5, 0xd2, 0xf9, 0x2e, 0x3a, 0x3d, 0x0f, 0x1f, + 0x74, 0x70, 0x2d, 0xd5, 0x4f, 0x77, 0xd3, 0xcd, 0x46, 0xc0, 0x4d, 0xee, + 0x7a, 0x5d, 0xe9, 0xf0, 0x0a, 0xd3, 0x17, 0x69, 0x1f, 0xdd, 0xce, 0xfe, + 0x4a, 0x22, 0x0a, 0x26, 0x51, 0xac, 0xae, 0x7f, 0xce, 0xdd, 0xa9, 0x2b, + 0xfc, 0xca, 0x85, 0x5d, 0xb6, 0x70, 0x5e, 0x8d, 0x86, 0x4f, 0x81, 0x92, + 0xbf, 0x6b, 0xf8, 0x60, 0xc0, 0x0f, 0x08, 0xad, 0x64, 0x93, 0xec, 0xc1, + 0x87, 0x2e, 0x00, 0x28, 0xd5, 0xc8, 0x6d, 0x44, 0x50, 0x5d, 0xb5, 0x74, + 0x22, 0x51, 0x5c, 0x38, 0x25, 0xa6, 0xf7, 0x8a +}; +static const uint8_t ac_dsa_vect46_ptx[] = { +/* Msg */ + 0xb0, 0xdb, 0xbf, 0x4a, 0x42, 0x1b, 0xa5, 0xc5, 0xb0, 0xe5, 0x2f, 0x09, + 0x62, 0x98, 0x01, 0xc1, 0x13, 0x25, 0x8c, 0x25, 0x2f, 0x29, 0x89, 0x8c, + 0x33, 0x54, 0x70, 0x6e, 0x39, 0xec, 0x58, 0x24, 0xbe, 0x52, 0x3d, 0x0e, + 0x2f, 0x8c, 0xfe, 0x02, 0x2c, 0xd6, 0x11, 0x65, 0x30, 0x12, 0x74, 0xd5, + 0xd6, 0x21, 0xa5, 0x97, 0x55, 0xf5, 0x04, 0x04, 0xd8, 0xb8, 0x02, 0x37, + 0x1c, 0xe6, 0x16, 0xde, 0xfa, 0x96, 0x2e, 0x36, 0x36, 0xae, 0x93, 0x4e, + 0xc3, 0x4e, 0x4b, 0xcf, 0x77, 0xa1, 0x6c, 0x7e, 0xff, 0x8c, 0xf4, 0xcc, + 0x08, 0xa0, 0xf4, 0x84, 0x9d, 0x6a, 0xd4, 0x30, 0x7e, 0x9f, 0x8d, 0xf8, + 0x3f, 0x24, 0xad, 0x16, 0xab, 0x46, 0xd1, 0xa6, 0x1d, 0x2d, 0x7d, 0x4e, + 0x21, 0x68, 0x1e, 0xb2, 0xae, 0x28, 0x1a, 0x1a, 0x5f, 0x9b, 0xca, 0x85, + 0x73, 0xa3, 0xf5, 0x28, 0x1d, 0x30, 0x8a, 0x5a +}; +static const uint8_t ac_dsa_vect46_priv_val[] = { +/* X */ + 0x64, 0x98, 0x20, 0x16, 0x8e, 0xb5, 0x94, 0xf5, 0x9c, 0xd9, 0xb2, 0x8b, + 0x9a, 0xef, 0xe8, 0xcc, 0x10, 0x6a, 0x6c, 0x4f +}; +static const uint8_t ac_dsa_vect46_pub_val[] = { +/* Y */ + 0x43, 0xa2, 0x7b, 0x74, 0x0f, 0x42, 0x2c, 0xb2, 0xdc, 0x3e, 0xaa, 0x23, + 0x23, 0x15, 0x88, 0x3a, 0x2f, 0x6a, 0x22, 0x92, 0x7f, 0x99, 0x7d, 0x02, + 0x4f, 0x5a, 0x63, 0x8b, 0x50, 0x7b, 0x17, 0xd3, 0xb1, 0xcb, 0xd3, 0xec, + 0x69, 0x1c, 0xc6, 0x74, 0x47, 0x09, 0x60, 0xa0, 0x14, 0x6e, 0xfd, 0xec, + 0xb9, 0x5b, 0xb5, 0xfe, 0x24, 0x97, 0x49, 0xe3, 0xc8, 0x06, 0xcd, 0x5c, + 0xc3, 0xe7, 0xf7, 0xba, 0xb8, 0x45, 0xda, 0xdb, 0xe1, 0xf5, 0x0b, 0x33, + 0x66, 0xfb, 0x82, 0x7a, 0x94, 0x2c, 0xe6, 0x24, 0x6d, 0xda, 0x7b, 0xd2, + 0xc1, 0x3e, 0x1b, 0x4a, 0x92, 0x6c, 0x0c, 0x82, 0xc8, 0x84, 0x63, 0x95, + 0x52, 0xd9, 0xd4, 0x60, 0x36, 0xf9, 0xa4, 0xbc, 0x2a, 0x9e, 0x51, 0xc2, + 0xd7, 0x6e, 0x30, 0x74, 0xd1, 0xf5, 0x3a, 0x63, 0x22, 0x4c, 0x42, 0x79, + 0xe0, 0xfa, 0x46, 0x04, 0x74, 0xd4, 0xff, 0xde +}; +/* K = 33c7ba88ff69707971b25ac344ae4a566e195f99 */ +static const uint8_t ac_dsa_vect46_out[] = { +/* R */ + 0x77, 0xc4, 0xd9, 0x9f, 0x62, 0xb3, 0xad, 0x7d, 0xd1, 0xfe, 0x64, 0x98, + 0xdb, 0x45, 0xa5, 0xda, 0x73, 0xce, 0x7b, 0xde, +/* S */ + 0x23, 0x87, 0x1a, 0x00, 0x2a, 0xe5, 0x03, 0xfd, 0xab, 0xaa, 0x6a, 0x84, + 0xdc, 0xc8, 0xf3, 0x87, 0x69, 0x73, 0x7f, 0x01 +}; +#define ac_dsa_vect47_prime ac_dsa_vect46_prime +#define ac_dsa_vect47_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect47_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect47_ptx[] = { +/* Msg */ + 0xec, 0x84, 0xbe, 0xd0, 0x9e, 0xcb, 0x4a, 0x6f, 0xee, 0xec, 0x3a, 0x70, + 0x71, 0xb6, 0x5a, 0x4c, 0x12, 0x67, 0xa0, 0x3c, 0xac, 0x8b, 0x5a, 0x05, + 0x00, 0xc2, 0x37, 0xb2, 0x0d, 0xc0, 0x58, 0x51, 0x4d, 0xa7, 0x98, 0x33, + 0x5a, 0x21, 0xb2, 0x3d, 0x7e, 0x8c, 0xbb, 0x15, 0xef, 0xcf, 0x92, 0xe6, + 0x06, 0x0a, 0x13, 0xfb, 0x77, 0xf4, 0x99, 0x81, 0x47, 0xde, 0xc1, 0xd0, + 0xfa, 0x0e, 0xdd, 0x41, 0x8b, 0x0a, 0xae, 0x8e, 0xb0, 0x05, 0x6f, 0xc7, + 0xd4, 0x00, 0x8b, 0x19, 0x8b, 0xd4, 0x0b, 0x96, 0x9d, 0xc1, 0x0d, 0x79, + 0xe1, 0x5b, 0x23, 0x00, 0x82, 0x03, 0x23, 0xbd, 0x5e, 0x1b, 0x7d, 0x89, + 0x4c, 0xe8, 0xe7, 0xbc, 0x8f, 0x7c, 0xec, 0xa1, 0x29, 0xb5, 0xe5, 0x11, + 0xee, 0x1c, 0x8c, 0xae, 0xc2, 0x55, 0x14, 0xf5, 0x37, 0x35, 0x3a, 0x91, + 0x2a, 0x97, 0x1b, 0x80, 0x70, 0xe3, 0xf1, 0x41 +}; +static const uint8_t ac_dsa_vect47_priv_val[] = { +/* X */ + 0x95, 0x2b, 0x61, 0xea, 0x90, 0xdf, 0x3f, 0x78, 0x8e, 0xab, 0x61, 0xd9, + 0x5b, 0xe1, 0x6c, 0xa2, 0x80, 0x01, 0x80, 0x0c +}; +static const uint8_t ac_dsa_vect47_pub_val[] = { +/* Y */ + 0xd7, 0xa0, 0x95, 0x0d, 0x0e, 0x63, 0x62, 0xb0, 0xc9, 0x42, 0xad, 0x8a, + 0xf6, 0x71, 0x61, 0xdf, 0x07, 0xde, 0xbc, 0xa5, 0x9a, 0x4c, 0xfa, 0x72, + 0x8f, 0x93, 0xd4, 0x9b, 0x6e, 0x29, 0x6a, 0x23, 0x96, 0x9a, 0x65, 0xa9, + 0x2b, 0x2e, 0x05, 0x39, 0x8a, 0x11, 0x4d, 0x73, 0xd5, 0xa5, 0x2b, 0x73, + 0xb7, 0x1e, 0xbb, 0x28, 0x57, 0x1c, 0xf6, 0xb6, 0x00, 0x2f, 0x85, 0x3a, + 0x8f, 0x59, 0x4b, 0x5c, 0x93, 0xb9, 0xa8, 0x42, 0x33, 0xf3, 0xc5, 0x52, + 0x82, 0x36, 0x19, 0xe0, 0xaa, 0x84, 0x7d, 0x60, 0x20, 0x3d, 0xb1, 0x5d, + 0x2a, 0x91, 0x6a, 0xd0, 0x22, 0x28, 0x32, 0x5e, 0x15, 0x78, 0x39, 0x88, + 0xf4, 0x15, 0x9e, 0x05, 0xc8, 0xca, 0x08, 0x83, 0x60, 0xe6, 0xea, 0x7a, + 0xce, 0x51, 0xb0, 0x55, 0x10, 0x21, 0x53, 0xc0, 0x0a, 0xdf, 0x33, 0x5f, + 0xf6, 0xaf, 0xfd, 0x17, 0x54, 0xf2, 0xa8, 0xaa +}; +/* K = 7982f6b8956c2bc0a2c2d02ecdb9e47d23a7ba81 */ +static const uint8_t ac_dsa_vect47_out[] = { +/* R */ + 0xb2, 0x57, 0x0e, 0x0e, 0x19, 0x93, 0x54, 0x38, 0xd3, 0x26, 0x86, 0xc4, + 0x78, 0x47, 0x3a, 0x0e, 0x45, 0xda, 0xd0, 0x23, +/* S */ + 0x39, 0xa0, 0x2e, 0x98, 0x03, 0x62, 0x4f, 0x7e, 0x90, 0xfe, 0xab, 0x87, + 0x14, 0xcd, 0xdc, 0x41, 0xe0, 0x1f, 0x8f, 0xce +}; +#define ac_dsa_vect48_prime ac_dsa_vect46_prime +#define ac_dsa_vect48_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect48_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect48_ptx[] = { +/* Msg */ + 0x80, 0xf7, 0x57, 0xfc, 0x06, 0x40, 0x9b, 0x70, 0xd7, 0x33, 0xef, 0xdb, + 0x68, 0xb5, 0x20, 0xf3, 0xf9, 0x07, 0x8a, 0xb9, 0x36, 0xc4, 0x47, 0x9f, + 0xb9, 0x8d, 0x0b, 0xeb, 0x16, 0x31, 0xd8, 0x30, 0x33, 0x24, 0x47, 0x08, + 0x24, 0x86, 0x22, 0x24, 0xb4, 0x39, 0xbc, 0x85, 0xde, 0xcf, 0xcc, 0xb8, + 0xde, 0x8f, 0xbf, 0x36, 0xa2, 0xbc, 0x4c, 0xe3, 0xa0, 0x92, 0x68, 0x82, + 0x49, 0xab, 0x4e, 0xb9, 0xfe, 0xbf, 0xad, 0x26, 0x82, 0x45, 0xfb, 0xd7, + 0xe7, 0x2e, 0x0f, 0x24, 0x05, 0x00, 0xaf, 0x71, 0x29, 0x2e, 0xa2, 0x3c, + 0x8a, 0xd4, 0xb7, 0x1e, 0x03, 0x21, 0x06, 0xf5, 0x87, 0xf4, 0x61, 0x16, + 0x63, 0x13, 0x76, 0x90, 0xcb, 0x25, 0x24, 0x19, 0x12, 0x76, 0x3c, 0x5e, + 0x18, 0x79, 0xb3, 0xab, 0x67, 0xe2, 0x18, 0x7f, 0x92, 0xd8, 0x21, 0xfc, + 0x81, 0xf5, 0x52, 0xe2, 0xc3, 0x55, 0xbd, 0x73 +}; +static const uint8_t ac_dsa_vect48_priv_val[] = { +/* X */ + 0x2a, 0x5f, 0x63, 0x7f, 0x4b, 0x88, 0x6a, 0x3d, 0x37, 0xc4, 0x36, 0x9c, + 0xab, 0x04, 0xd7, 0x8c, 0x79, 0xf1, 0xa3, 0xa8 +}; +static const uint8_t ac_dsa_vect48_pub_val[] = { +/* Y */ + 0x1f, 0x03, 0x01, 0x3e, 0x66, 0xfd, 0x1e, 0x63, 0x3f, 0xf7, 0x43, 0x89, + 0x4c, 0x37, 0xf6, 0x96, 0x48, 0x39, 0xa5, 0x2c, 0xfb, 0xb6, 0xe8, 0x49, + 0xcf, 0xb4, 0xea, 0xc9, 0xa3, 0xc9, 0xcd, 0xb5, 0x5c, 0x28, 0xe1, 0x47, + 0x88, 0x86, 0x5c, 0x21, 0x2b, 0xe6, 0x20, 0x47, 0xcb, 0x39, 0xc6, 0x36, + 0x57, 0x80, 0xbb, 0x2e, 0x62, 0x79, 0x57, 0xd3, 0x4e, 0x99, 0x23, 0x2f, + 0x69, 0x17, 0x0a, 0x8e, 0xfb, 0x89, 0x4d, 0x80, 0x29, 0xd1, 0xb8, 0xbe, + 0xa8, 0xb9, 0x11, 0xce, 0xbc, 0xd4, 0x3b, 0x86, 0xbd, 0x53, 0x66, 0x93, + 0xf1, 0x8b, 0xfe, 0x50, 0xc8, 0x4b, 0x99, 0x91, 0x11, 0x81, 0xac, 0xe1, + 0x4c, 0x3f, 0xab, 0x9f, 0xb6, 0xac, 0xd9, 0x87, 0x86, 0xf9, 0xd2, 0xad, + 0x12, 0x9c, 0x5e, 0xfe, 0xb8, 0xcd, 0x09, 0x41, 0xa3, 0xd8, 0x90, 0x98, + 0xd5, 0x72, 0x1d, 0x43, 0x53, 0x43, 0xcb, 0x76 +}; +/* K = b7c75c380bce0fffd59dfc3993e1d0724da877b6 */ +static const uint8_t ac_dsa_vect48_out[] = { +/* R */ + 0xc7, 0xdb, 0x4a, 0x9f, 0x54, 0xd8, 0x82, 0xec, 0x5f, 0x56, 0x17, 0x05, + 0x39, 0x6c, 0x94, 0x83, 0x4d, 0xd5, 0x3c, 0x5a, +/* S */ + 0x67, 0x52, 0xcb, 0x6b, 0xe9, 0xb8, 0x72, 0x65, 0xd7, 0x6d, 0x69, 0xb3, + 0x82, 0x29, 0x96, 0x78, 0xf9, 0x6a, 0x5f, 0xaf +}; +#define ac_dsa_vect49_prime ac_dsa_vect46_prime +#define ac_dsa_vect49_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect49_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect49_ptx[] = { +/* Msg */ + 0x36, 0xa2, 0x56, 0x59, 0xa7, 0xf1, 0xde, 0x66, 0xb4, 0x72, 0x1b, 0x48, + 0x85, 0x5c, 0xde, 0xbe, 0x98, 0xfe, 0x61, 0x13, 0x24, 0x1b, 0x7b, 0xed, + 0xdc, 0x26, 0x91, 0x49, 0x3e, 0xd0, 0xad, 0xd0, 0xb6, 0xa9, 0xfb, 0xbf, + 0x9f, 0xb8, 0x70, 0xa1, 0xbc, 0x68, 0xa9, 0x01, 0xb9, 0x32, 0xf4, 0x7d, + 0xed, 0x53, 0x2f, 0x93, 0x49, 0x3b, 0x1c, 0x08, 0x14, 0x08, 0x16, 0x58, + 0x07, 0xb3, 0x8e, 0xfc, 0xe7, 0xac, 0xc7, 0xdb, 0xc2, 0x16, 0xbe, 0xf7, + 0x4e, 0xd5, 0x9e, 0x20, 0x97, 0x33, 0x26, 0x55, 0x3c, 0xc8, 0x37, 0x79, + 0xf7, 0x42, 0xe3, 0xf4, 0x69, 0xa7, 0x27, 0x8e, 0xeb, 0x15, 0x37, 0xdd, + 0x71, 0xcd, 0x8f, 0x15, 0x11, 0x4d, 0x84, 0x69, 0x3c, 0x2e, 0x6b, 0xbf, + 0x62, 0x81, 0x4a, 0x08, 0xe8, 0x2b, 0xa7, 0x15, 0x39, 0xf4, 0xcb, 0x4b, + 0xf0, 0x8c, 0x86, 0x9d, 0x7d, 0xb9, 0xde, 0xa9 +}; +static const uint8_t ac_dsa_vect49_priv_val[] = { +/* X */ + 0xbb, 0x31, 0x89, 0x87, 0xa0, 0x43, 0x15, 0x8b, 0x97, 0xfd, 0xbb, 0xc2, + 0x70, 0x74, 0x71, 0xa3, 0x83, 0x16, 0xce, 0x58 +}; +static const uint8_t ac_dsa_vect49_pub_val[] = { +/* Y */ + 0xc9, 0x00, 0x39, 0x95, 0xb0, 0x14, 0xaf, 0xad, 0x66, 0xde, 0x25, 0xfc, + 0x0a, 0x22, 0x10, 0xb1, 0xf1, 0xb2, 0x2d, 0x27, 0x5d, 0xa5, 0x1a, 0x27, + 0xfa, 0xac, 0xda, 0x04, 0x2f, 0xd7, 0x64, 0x56, 0x86, 0xec, 0x8b, 0x1b, + 0x62, 0xd5, 0x8d, 0x8a, 0xf2, 0xe1, 0x06, 0x3a, 0xb8, 0xe1, 0x46, 0xd1, + 0x1e, 0x3a, 0x07, 0x71, 0x0b, 0xc4, 0x52, 0x12, 0x28, 0xf3, 0x5f, 0x51, + 0x73, 0x44, 0x3b, 0xbf, 0xd0, 0x89, 0xf6, 0x42, 0xcd, 0x16, 0x64, 0x1c, + 0x57, 0x19, 0x9c, 0x9a, 0xb6, 0xe0, 0xd9, 0xb0, 0xc0, 0x19, 0x31, 0xc2, + 0xd1, 0x62, 0xf5, 0xe2, 0x0d, 0xbe, 0x73, 0x65, 0xc9, 0x3a, 0xdc, 0x62, + 0xfd, 0x5a, 0x46, 0x1b, 0xea, 0x59, 0x56, 0xd7, 0xc1, 0x1a, 0xc6, 0x76, + 0x47, 0xbe, 0xdc, 0xea, 0xd5, 0xbb, 0x31, 0x12, 0x24, 0xa4, 0x96, 0xaa, + 0x15, 0x59, 0x92, 0xae, 0xe7, 0x4e, 0x45, 0xad +}; +/* K = 2ff654b680e722ce65a560e785e8ce0b4773c86d */ +static const uint8_t ac_dsa_vect49_out[] = { +/* R */ + 0x17, 0xcc, 0x53, 0xb5, 0xb9, 0x55, 0x8c, 0xc4, 0x1d, 0xf9, 0x46, 0x05, + 0x5b, 0x8d, 0x7e, 0x19, 0x71, 0xbe, 0x86, 0xd7, +/* S */ + 0x00, 0x3c, 0x21, 0x50, 0x39, 0x71, 0xc0, 0x3b, 0x5e, 0xf4, 0xed, 0xc8, + 0x04, 0xd2, 0xf7, 0xd3, 0x3f, 0x9e, 0xa9, 0xcc +}; +#define ac_dsa_vect50_prime ac_dsa_vect46_prime +#define ac_dsa_vect50_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect50_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect50_ptx[] = { +/* Msg */ + 0x65, 0xa3, 0xc9, 0x24, 0x53, 0xf9, 0x61, 0xde, 0x7f, 0x57, 0x6d, 0x5a, + 0x1e, 0x31, 0x06, 0xc3, 0x8b, 0x7f, 0x20, 0x81, 0x39, 0x94, 0xb5, 0xdd, + 0x20, 0x15, 0x46, 0xdc, 0x45, 0x50, 0x65, 0xdd, 0xe5, 0x9e, 0xdc, 0xd8, + 0x4d, 0x0f, 0xa1, 0x7a, 0x85, 0xc0, 0xf9, 0xf9, 0x91, 0x71, 0xd6, 0x7a, + 0x34, 0x47, 0x5c, 0xef, 0x4f, 0x31, 0x19, 0x51, 0xf2, 0xee, 0xf7, 0xf6, + 0xb6, 0x4a, 0x5b, 0xbc, 0x6d, 0xa6, 0xd1, 0xb6, 0x22, 0x48, 0x0c, 0xde, + 0x56, 0xa0, 0x7a, 0x77, 0xaa, 0x60, 0x40, 0xeb, 0xc1, 0xfc, 0xb2, 0x65, + 0xb3, 0xb6, 0x24, 0x88, 0x1f, 0xd2, 0x72, 0x03, 0xdc, 0xfe, 0x8a, 0x12, + 0x49, 0x21, 0x98, 0x47, 0x4a, 0x99, 0x0c, 0xb9, 0xf3, 0x4a, 0x19, 0x43, + 0x35, 0x6f, 0xde, 0x5b, 0xce, 0x3f, 0xd8, 0x35, 0x16, 0xda, 0x8b, 0xf7, + 0x80, 0xf8, 0xcb, 0x18, 0x51, 0xb3, 0xb9, 0x54 +}; +static const uint8_t ac_dsa_vect50_priv_val[] = { +/* X */ + 0x59, 0xd9, 0x2a, 0xba, 0x23, 0xf5, 0x0a, 0xd0, 0x8b, 0x1d, 0x7c, 0x2a, + 0xd5, 0x60, 0xde, 0xd3, 0x6b, 0x94, 0xeb, 0xc8 +}; +static const uint8_t ac_dsa_vect50_pub_val[] = { +/* Y */ + 0x0f, 0xc5, 0x14, 0xca, 0x16, 0x0f, 0x34, 0xf2, 0xf6, 0xed, 0xe1, 0xba, + 0x59, 0x14, 0xd5, 0x84, 0x4c, 0x9d, 0xe5, 0x14, 0x20, 0x8c, 0x72, 0x56, + 0x9a, 0x0b, 0x36, 0xec, 0x92, 0xc8, 0xb2, 0xc8, 0xfd, 0xfb, 0x7d, 0x68, + 0x12, 0x74, 0x86, 0xe5, 0x8a, 0x04, 0xa3, 0x2d, 0x0d, 0x15, 0x0e, 0x51, + 0xbb, 0x05, 0xe6, 0x66, 0x24, 0xcb, 0x62, 0x2e, 0xda, 0xe1, 0x9a, 0x6b, + 0x4b, 0x1d, 0x83, 0x17, 0x68, 0x9b, 0xaa, 0xfa, 0x30, 0x16, 0x8e, 0xf3, + 0x75, 0x9e, 0xe8, 0x2e, 0x61, 0x4e, 0x47, 0x61, 0x90, 0x01, 0x82, 0xdf, + 0x90, 0xe9, 0xcd, 0x2d, 0x93, 0x11, 0x53, 0x77, 0x1b, 0x8b, 0xe3, 0x0d, + 0x89, 0xc2, 0xfb, 0xb9, 0x5b, 0xe7, 0xe0, 0x5a, 0x4b, 0x29, 0xda, 0x96, + 0x8f, 0xfe, 0xbb, 0xda, 0x5c, 0x0c, 0x98, 0x39, 0x35, 0x4b, 0xb5, 0x9d, + 0xc6, 0x97, 0xa2, 0x69, 0x06, 0x3f, 0x2f, 0x50 +}; +/* K = 3d0ea569b4dc69342955f5b240af66d228791e50 */ +static const uint8_t ac_dsa_vect50_out[] = { +/* R */ + 0x77, 0xff, 0xaf, 0x42, 0x90, 0xc4, 0x1e, 0xb0, 0x89, 0xc1, 0xd7, 0xbe, + 0x5c, 0x8d, 0x38, 0x33, 0x02, 0x77, 0x02, 0xef, +/* S */ + 0xcb, 0x75, 0x3a, 0x2d, 0x4c, 0xe0, 0xe5, 0x98, 0x51, 0xf8, 0x14, 0x77, + 0x9f, 0x34, 0x3b, 0xeb, 0x61, 0x5f, 0x27, 0x70 +}; +#define ac_dsa_vect51_prime ac_dsa_vect46_prime +#define ac_dsa_vect51_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect51_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect51_ptx[] = { +/* Msg */ + 0x15, 0x26, 0xb6, 0x4c, 0xe4, 0x1c, 0xc8, 0xe2, 0xce, 0xf2, 0x6f, 0x37, + 0x06, 0xbe, 0x53, 0x0a, 0x36, 0xac, 0x9c, 0xd1, 0x6f, 0xf6, 0x9f, 0x05, + 0x77, 0x3e, 0x94, 0x47, 0xed, 0x94, 0x52, 0x06, 0x4b, 0x77, 0x51, 0xf3, + 0xa6, 0x49, 0x19, 0xbf, 0xa3, 0xa7, 0xe1, 0x02, 0x0d, 0xfc, 0x17, 0x5a, + 0x10, 0xac, 0xfd, 0xf0, 0x96, 0xfd, 0x41, 0xc0, 0x33, 0x72, 0xe4, 0xd2, + 0xab, 0xd7, 0xba, 0x88, 0x7e, 0x00, 0x76, 0x71, 0x6c, 0xe9, 0x55, 0x2f, + 0x2c, 0x7c, 0x8e, 0xdd, 0xb1, 0xb3, 0xfc, 0xa1, 0xbd, 0xcd, 0x23, 0x30, + 0x0c, 0xe2, 0xb1, 0x67, 0x7d, 0x4a, 0x2d, 0xeb, 0xea, 0xa7, 0x05, 0x34, + 0x66, 0xe5, 0x9b, 0x09, 0x87, 0x71, 0xbf, 0xb9, 0x21, 0x8e, 0x0f, 0xb4, + 0xab, 0x6b, 0x74, 0x18, 0xab, 0xeb, 0xcc, 0x34, 0xd6, 0x81, 0xe1, 0x4c, + 0x4a, 0x89, 0x75, 0x00, 0x0d, 0x83, 0xbb, 0x44 +}; +static const uint8_t ac_dsa_vect51_priv_val[] = { +/* X */ + 0x71, 0x62, 0x90, 0xd0, 0xff, 0x2a, 0xd2, 0x32, 0x9b, 0xe2, 0xcc, 0xcf, + 0x82, 0x5f, 0x20, 0x75, 0xbe, 0x65, 0x97, 0x43 +}; +static const uint8_t ac_dsa_vect51_pub_val[] = { +/* Y */ + 0xd3, 0x0e, 0xed, 0x73, 0x9f, 0x46, 0x47, 0x93, 0x64, 0xd4, 0xc2, 0xbe, + 0xc1, 0x8c, 0xf4, 0xc7, 0x5c, 0x32, 0x4f, 0x8d, 0xb8, 0x18, 0x4d, 0x9c, + 0x3c, 0x17, 0x55, 0x56, 0xa0, 0x0a, 0xcf, 0xb0, 0xa6, 0x81, 0x38, 0x87, + 0xb6, 0x87, 0x06, 0xe7, 0x0c, 0x16, 0x7f, 0x40, 0x63, 0xbc, 0x00, 0x46, + 0x39, 0x6b, 0xa1, 0xbb, 0x32, 0x26, 0xc2, 0x92, 0x21, 0xbd, 0x64, 0xec, + 0x4c, 0xeb, 0xc9, 0x90, 0xa7, 0xb4, 0x04, 0xe2, 0x6e, 0x2c, 0xf0, 0x42, + 0x30, 0x4a, 0x7c, 0x57, 0xab, 0x7d, 0xe4, 0x18, 0xba, 0x67, 0x1e, 0x17, + 0xf7, 0xf5, 0x02, 0xb9, 0xe1, 0xbb, 0x59, 0x84, 0x46, 0x9b, 0x30, 0x4e, + 0xbc, 0x0c, 0x3c, 0x3a, 0x5a, 0x69, 0xcf, 0xf7, 0xab, 0xff, 0x41, 0x10, + 0x13, 0x03, 0x16, 0x65, 0x1e, 0x0f, 0x93, 0xeb, 0xd2, 0x83, 0x4d, 0xd0, + 0x44, 0xea, 0xe1, 0xfd, 0x6f, 0x04, 0x51, 0x02 +}; +/* K = 919d698fe37c027e3e40cdf6e77f81e96d8bfffb */ +static const uint8_t ac_dsa_vect51_out[] = { +/* R */ + 0x31, 0xab, 0xe8, 0xe7, 0x45, 0x8c, 0xe3, 0x63, 0xa5, 0xf3, 0x98, 0x51, + 0x11, 0xb2, 0x39, 0xbc, 0x8d, 0xf8, 0xdc, 0xb9, +/* S */ + 0x1d, 0x96, 0x7b, 0xe0, 0x11, 0x61, 0x28, 0x69, 0x9d, 0x16, 0x7f, 0xc1, + 0x6e, 0x5e, 0x92, 0x0a, 0x41, 0x31, 0x16, 0x69 +}; +#define ac_dsa_vect52_prime ac_dsa_vect46_prime +#define ac_dsa_vect52_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect52_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect52_ptx[] = { +/* Msg */ + 0xd7, 0x85, 0x2e, 0xe9, 0x0b, 0x3f, 0x11, 0x20, 0xbb, 0x11, 0x24, 0x98, + 0x08, 0xc7, 0xe7, 0xbe, 0x14, 0xfe, 0x57, 0x7b, 0xff, 0x18, 0x86, 0xbe, + 0x3c, 0x42, 0x58, 0x9a, 0x6e, 0xeb, 0x06, 0xa1, 0x83, 0x41, 0x10, 0x86, + 0x2b, 0x65, 0xd2, 0x6c, 0xc5, 0xa2, 0xe5, 0xd9, 0x03, 0xed, 0x24, 0x32, + 0x8d, 0x68, 0x4c, 0x96, 0xe3, 0xba, 0xbb, 0x37, 0xae, 0x31, 0xf9, 0x6d, + 0x32, 0xf5, 0x76, 0x57, 0xa3, 0xbd, 0x77, 0x98, 0xaa, 0xfa, 0xe8, 0x6f, + 0x44, 0xad, 0x89, 0x81, 0xe7, 0xcd, 0x47, 0xd7, 0xf3, 0x1b, 0xb4, 0x56, + 0x4a, 0x75, 0x7c, 0x92, 0x5c, 0x64, 0xda, 0x98, 0x20, 0x96, 0x3c, 0x1c, + 0x51, 0x48, 0xf5, 0x89, 0xd6, 0x39, 0x30, 0x04, 0xa6, 0xa5, 0x8a, 0xa2, + 0xc8, 0xa5, 0x78, 0xf4, 0xdb, 0x75, 0x95, 0xf8, 0x86, 0x17, 0x0e, 0x79, + 0xe9, 0xd5, 0x7b, 0xf7, 0xff, 0x8f, 0xd0, 0xa7 +}; +static const uint8_t ac_dsa_vect52_priv_val[] = { +/* X */ + 0x05, 0x31, 0xcb, 0x42, 0xf4, 0x5b, 0xb8, 0x13, 0xf4, 0x01, 0xbd, 0x23, + 0x90, 0x44, 0xdf, 0x2d, 0x3d, 0x19, 0x68, 0xb2 +}; +static const uint8_t ac_dsa_vect52_pub_val[] = { +/* Y */ + 0x0d, 0xd3, 0x79, 0x85, 0x16, 0x3f, 0x93, 0x61, 0x8f, 0xde, 0xa8, 0xe3, + 0x97, 0x54, 0x19, 0xfc, 0xf7, 0x44, 0x6f, 0xf9, 0x80, 0x85, 0x1e, 0x18, + 0x93, 0x2d, 0x74, 0x94, 0xf8, 0x09, 0xc0, 0xae, 0x9c, 0x03, 0xcc, 0x39, + 0x77, 0x9f, 0xf0, 0x42, 0x2c, 0xb2, 0x24, 0x8a, 0xe1, 0x98, 0x6f, 0x9a, + 0xad, 0x2a, 0x43, 0xd6, 0xfa, 0x68, 0x78, 0xd2, 0x44, 0xb4, 0x29, 0xaa, + 0xc5, 0xea, 0x80, 0x15, 0x79, 0x80, 0x57, 0x7e, 0x5b, 0xa0, 0xd1, 0x1b, + 0x1f, 0xa3, 0x40, 0xa2, 0x83, 0xfa, 0x0a, 0x2d, 0x65, 0x1e, 0x02, 0x43, + 0x31, 0xe6, 0xbb, 0xe7, 0xd0, 0x1a, 0xc0, 0x34, 0xdb, 0x37, 0xb0, 0x08, + 0xb9, 0x1f, 0x9f, 0x88, 0xd1, 0x35, 0xfa, 0xd2, 0x3a, 0xf8, 0xc2, 0x27, + 0x65, 0xd8, 0x33, 0xa9, 0xc9, 0xef, 0xf7, 0xac, 0xcf, 0x66, 0x8e, 0x17, + 0xf9, 0xa8, 0xbd, 0xf5, 0x93, 0x17, 0xc2, 0x02 +}; +/* K = 739dbd1f84b6be2efdb921a0dfb76dbc6136915c */ +static const uint8_t ac_dsa_vect52_out[] = { +/* R */ + 0x44, 0xc2, 0xd6, 0x50, 0x98, 0x74, 0xac, 0xe7, 0x1a, 0xcd, 0x1d, 0xcc, + 0x32, 0x33, 0x5b, 0x39, 0x4c, 0x4e, 0x41, 0xe0, +/* S */ + 0x37, 0xe7, 0x8f, 0x13, 0xae, 0xc0, 0x52, 0xeb, 0x7b, 0x07, 0xa8, 0xb9, + 0xf6, 0xd5, 0x4d, 0xbc, 0x77, 0x82, 0x90, 0x06 +}; +#define ac_dsa_vect53_prime ac_dsa_vect46_prime +#define ac_dsa_vect53_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect53_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect53_ptx[] = { +/* Msg */ + 0x9a, 0xb9, 0x14, 0x48, 0xa0, 0xdc, 0x96, 0x94, 0xbe, 0x17, 0x3c, 0xe6, + 0xd9, 0xb5, 0x22, 0xce, 0x0e, 0x2f, 0x75, 0xfc, 0xb5, 0x77, 0x20, 0xfc, + 0x5e, 0xb8, 0xf9, 0x2d, 0x8f, 0xb0, 0xe1, 0x95, 0x03, 0x00, 0x63, 0x96, + 0x89, 0x25, 0xa5, 0x68, 0x63, 0x6f, 0x4a, 0xea, 0x1e, 0xdf, 0x6c, 0x5f, + 0xcb, 0x86, 0xdc, 0xed, 0xd2, 0x04, 0x53, 0x9d, 0x8c, 0x29, 0x17, 0x57, + 0xfb, 0x8a, 0x51, 0x62, 0x0a, 0xbd, 0xa5, 0x9a, 0xa8, 0xf8, 0x50, 0x2e, + 0x69, 0x04, 0xbc, 0xe0, 0x66, 0x7d, 0x92, 0xc8, 0xcb, 0x3f, 0xcf, 0x1a, + 0x61, 0xb1, 0xfb, 0x0b, 0xb4, 0xe9, 0x38, 0x3b, 0x37, 0xeb, 0x46, 0x9b, + 0xd5, 0xc2, 0xf5, 0xa7, 0x76, 0x80, 0xda, 0x62, 0xf9, 0x07, 0xc2, 0xe2, + 0x63, 0xcb, 0x48, 0x40, 0x2b, 0x4b, 0x12, 0x98, 0x5e, 0xaa, 0xb9, 0x04, + 0x51, 0x88, 0x5e, 0x81, 0x9b, 0x3e, 0x8c, 0x3a +}; +static const uint8_t ac_dsa_vect53_priv_val[] = { +/* X */ + 0x6d, 0x76, 0x4c, 0xf6, 0x2a, 0x26, 0x8b, 0x00, 0x70, 0xbf, 0x80, 0x30, + 0x86, 0x22, 0xbb, 0x31, 0x94, 0x1d, 0x47, 0x63 +}; +static const uint8_t ac_dsa_vect53_pub_val[] = { +/* Y */ + 0x49, 0xd7, 0xf0, 0x8f, 0xde, 0x0a, 0x83, 0xcf, 0xb8, 0x11, 0x6c, 0x9b, + 0x7c, 0xdc, 0xab, 0x29, 0x75, 0x1f, 0xca, 0x5f, 0xfe, 0x31, 0x07, 0x60, + 0xfe, 0xa7, 0x13, 0xc3, 0x0e, 0x95, 0xe7, 0x75, 0x5e, 0x65, 0xce, 0x60, + 0x92, 0x88, 0x93, 0xc6, 0x50, 0x20, 0xee, 0x9b, 0x61, 0xf6, 0xc9, 0xc8, + 0x9c, 0x07, 0xe0, 0xfc, 0x50, 0x3b, 0x7b, 0x03, 0x13, 0x68, 0xf0, 0x69, + 0x57, 0x8a, 0x9e, 0x6b, 0x45, 0x1f, 0xef, 0x36, 0x9e, 0xf9, 0x0c, 0x26, + 0xdd, 0x66, 0x0e, 0xe1, 0xa6, 0xb8, 0xb7, 0x14, 0xd1, 0xcc, 0x28, 0x24, + 0x5e, 0x9f, 0x13, 0xf1, 0x87, 0x12, 0x2d, 0xe2, 0x6a, 0xc2, 0xfb, 0xf5, + 0xbc, 0xcb, 0x7c, 0xaf, 0xf5, 0x9f, 0x1d, 0xe9, 0x10, 0x55, 0x11, 0x04, + 0xd3, 0xa0, 0xe8, 0xfa, 0x9f, 0xe6, 0xb7, 0xea, 0xcc, 0x9a, 0x5f, 0xd5, + 0x56, 0xb7, 0xbf, 0x71, 0x39, 0xd6, 0xed, 0xf9 +}; +/* K = c66ea7177cd6edf6b9079fbcf6737d3890469b19 */ +static const uint8_t ac_dsa_vect53_out[] = { +/* R */ + 0x95, 0xda, 0x25, 0xd0, 0x6f, 0xf9, 0xc0, 0x2b, 0xc8, 0x93, 0xfb, 0x03, + 0x25, 0x08, 0x30, 0x4c, 0x17, 0xeb, 0xcf, 0x08, +/* S */ + 0x61, 0x7a, 0xdb, 0x8d, 0xe1, 0x0d, 0xa1, 0xa8, 0x74, 0x13, 0xd6, 0x44, + 0x66, 0xb4, 0x82, 0x40, 0x9d, 0x27, 0xbc, 0xe7 +}; +#define ac_dsa_vect54_prime ac_dsa_vect46_prime +#define ac_dsa_vect54_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect54_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect54_ptx[] = { +/* Msg */ + 0xc9, 0xc0, 0xe6, 0x9f, 0x84, 0x0c, 0xb6, 0xde, 0xb9, 0x84, 0xc2, 0x57, + 0x5d, 0x7f, 0x68, 0x16, 0xfa, 0x35, 0xaf, 0x03, 0xb4, 0x42, 0x9c, 0x70, + 0x3a, 0x5a, 0xec, 0x90, 0xe7, 0xcb, 0x26, 0xe5, 0x24, 0x13, 0x58, 0x7f, + 0x3b, 0xc5, 0xa0, 0x77, 0x2b, 0xe7, 0xb5, 0xe5, 0x89, 0xc9, 0xa7, 0x60, + 0x71, 0xc1, 0x73, 0x98, 0x33, 0xf4, 0x61, 0x1f, 0xa9, 0x51, 0xd3, 0x75, + 0x82, 0x0b, 0x48, 0xd7, 0x40, 0x62, 0x6c, 0x66, 0x55, 0x34, 0xd6, 0x04, + 0x87, 0xbf, 0x3e, 0x0a, 0x84, 0xeb, 0x63, 0x89, 0xe0, 0x99, 0xfe, 0x62, + 0x1f, 0x26, 0x94, 0x91, 0xc3, 0xb8, 0x94, 0x2e, 0x03, 0xbb, 0xad, 0x2a, + 0x52, 0x20, 0xca, 0xf5, 0x1e, 0x7b, 0x4a, 0x26, 0x50, 0xe4, 0xb3, 0x00, + 0x02, 0x4a, 0x0a, 0x96, 0xf0, 0x86, 0x1b, 0x32, 0x06, 0xff, 0xfc, 0xa8, + 0x3d, 0x08, 0x50, 0xf2, 0xa3, 0xe2, 0xa0, 0x6c +}; +static const uint8_t ac_dsa_vect54_priv_val[] = { +/* X */ + 0x38, 0xa6, 0x2d, 0x23, 0x4e, 0x1a, 0xea, 0x0e, 0x84, 0x76, 0x21, 0xe7, + 0x9d, 0xd1, 0x7e, 0xe9, 0xd0, 0x8b, 0xd9, 0xc6 +}; +static const uint8_t ac_dsa_vect54_pub_val[] = { +/* Y */ + 0x26, 0xf7, 0x32, 0x19, 0xd0, 0xe7, 0xdd, 0x3a, 0x80, 0xe7, 0xfb, 0xc0, + 0x79, 0xd9, 0xba, 0xad, 0x45, 0x12, 0x89, 0x1a, 0xad, 0xfd, 0x24, 0x16, + 0xb1, 0x85, 0x9f, 0x41, 0xad, 0xac, 0x31, 0x17, 0x1e, 0xc6, 0x24, 0xd8, + 0xa4, 0xd6, 0xa1, 0x0d, 0x5d, 0xe1, 0xb9, 0x39, 0x59, 0xbc, 0x49, 0x95, + 0x3f, 0x23, 0x49, 0x2f, 0x18, 0xab, 0x76, 0x5f, 0x96, 0x3a, 0x98, 0x58, + 0x48, 0x07, 0xd6, 0x66, 0x29, 0xe5, 0xa1, 0xe0, 0x57, 0xd7, 0x7d, 0x42, + 0xe3, 0x36, 0x34, 0x58, 0x64, 0x1a, 0x04, 0x69, 0x16, 0x6a, 0x0d, 0x85, + 0x3b, 0x27, 0x79, 0x8b, 0xd8, 0x48, 0xaa, 0x0d, 0x3c, 0xcd, 0xbb, 0x40, + 0xfa, 0x21, 0xb9, 0xfe, 0x62, 0x82, 0x4c, 0xb2, 0xc7, 0xcc, 0x62, 0x42, + 0x59, 0x78, 0xe6, 0x72, 0xaf, 0xf0, 0xbb, 0xd8, 0xc8, 0xcd, 0x08, 0xe4, + 0x63, 0x85, 0xb0, 0xd6, 0x21, 0x9d, 0xc5, 0x6e +}; +/* K = 5f5755dce464174adfe00affb55a71222d83da85 */ +static const uint8_t ac_dsa_vect54_out[] = { +/* R */ + 0xb6, 0xb2, 0x5a, 0x9d, 0xa1, 0x10, 0xb5, 0xd5, 0x76, 0x75, 0x88, 0x9e, + 0xae, 0x75, 0xab, 0x58, 0xa4, 0xd8, 0xe2, 0x81, +/* S */ + 0x5a, 0x60, 0xc2, 0xb0, 0xad, 0xbe, 0xa4, 0xc5, 0xbe, 0x06, 0x5b, 0xbd, + 0x0f, 0xd0, 0xe3, 0xce, 0x4b, 0xf2, 0x92, 0x00 +}; +#define ac_dsa_vect55_prime ac_dsa_vect46_prime +#define ac_dsa_vect55_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect55_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect55_ptx[] = { +/* Msg */ + 0x40, 0x02, 0xde, 0x82, 0x5b, 0xb8, 0x7a, 0xc3, 0x46, 0xbd, 0x84, 0x87, + 0xcf, 0x6b, 0xe0, 0x53, 0xcb, 0x30, 0xee, 0x67, 0xc6, 0x64, 0x34, 0x21, + 0x71, 0x07, 0xa8, 0xb0, 0xb5, 0x2e, 0x57, 0x26, 0x90, 0x06, 0x15, 0xed, + 0xd2, 0xfd, 0x0a, 0xcd, 0xf8, 0x8a, 0x7e, 0x65, 0xe7, 0xdd, 0x3b, 0xa6, + 0xab, 0xbb, 0xb3, 0x71, 0xa1, 0xc8, 0x40, 0x25, 0x0d, 0x9c, 0xe8, 0x09, + 0xe7, 0xb1, 0x11, 0x1f, 0x16, 0xda, 0xf5, 0x19, 0x42, 0x11, 0x71, 0x5f, + 0xf5, 0xfe, 0x63, 0x1e, 0x37, 0x84, 0x08, 0x74, 0x98, 0x48, 0xa0, 0xc8, + 0x1a, 0x28, 0x9b, 0x43, 0x38, 0xbc, 0xcd, 0x8d, 0x10, 0x53, 0xf8, 0x63, + 0x19, 0x7a, 0xd0, 0x29, 0x20, 0xfc, 0xbc, 0xa5, 0x14, 0xe2, 0xdf, 0xd9, + 0x4a, 0x8b, 0x00, 0xf9, 0x0c, 0xf0, 0x34, 0xad, 0xfd, 0x77, 0x6f, 0x4d, + 0xca, 0xef, 0x2c, 0x8d, 0xce, 0x3b, 0x05, 0x39 +}; +static const uint8_t ac_dsa_vect55_priv_val[] = { +/* X */ + 0xc8, 0xf0, 0xd6, 0x97, 0xbb, 0xcb, 0xcc, 0x0e, 0x31, 0x86, 0x4f, 0x83, + 0x19, 0x98, 0x41, 0x25, 0xf5, 0x2f, 0xf5, 0xaa +}; +static const uint8_t ac_dsa_vect55_pub_val[] = { +/* Y */ + 0x14, 0x9b, 0xcb, 0xb4, 0xf5, 0x98, 0x3d, 0xb5, 0x6f, 0xbe, 0x99, 0x8f, + 0xcd, 0x02, 0xd7, 0x36, 0xe6, 0xd2, 0xf1, 0x8f, 0xcf, 0x96, 0x46, 0x8c, + 0xd7, 0xe9, 0x9b, 0xc6, 0x47, 0x43, 0x6f, 0xbd, 0x74, 0xfd, 0x7a, 0x2c, + 0xc2, 0xf0, 0xd8, 0x86, 0x69, 0x52, 0xb9, 0x7b, 0x44, 0xff, 0x64, 0x4b, + 0x56, 0x65, 0xcd, 0x10, 0x65, 0xb0, 0x7a, 0x2c, 0x33, 0xd9, 0x15, 0x1d, + 0xeb, 0x33, 0x5e, 0x35, 0x22, 0xc1, 0xb7, 0x7d, 0xa1, 0x44, 0x3a, 0x13, + 0x73, 0xc9, 0x3b, 0xfa, 0x04, 0x0d, 0xa5, 0xa1, 0x35, 0x3b, 0x88, 0xa7, + 0x8e, 0x3a, 0x5a, 0x08, 0x4e, 0x6c, 0x44, 0x2d, 0xb0, 0x3f, 0x7f, 0xbb, + 0x4b, 0xdb, 0xd3, 0x0b, 0x1a, 0xf3, 0x96, 0x3f, 0x8c, 0x5d, 0x3e, 0x83, + 0x45, 0x32, 0x94, 0xe3, 0xa0, 0x7d, 0xda, 0xcf, 0xd4, 0x3d, 0xc8, 0xf9, + 0xe8, 0x30, 0x32, 0xfe, 0xf7, 0x84, 0x20, 0xc4 +}; +/* K = b4281920a775fbeefb89615b236217fd1046f2cf */ +static const uint8_t ac_dsa_vect55_out[] = { +/* R */ + 0xd3, 0xcd, 0xe1, 0x70, 0xd8, 0x21, 0x54, 0xec, 0x1b, 0xbd, 0x90, 0x77, + 0xc4, 0x86, 0x97, 0x11, 0x20, 0x60, 0x03, 0x76, +/* S */ + 0xb0, 0x08, 0xfc, 0xd0, 0x1b, 0x5e, 0x49, 0xa8, 0x5a, 0x92, 0x1b, 0xee, + 0x1d, 0xdd, 0x70, 0x62, 0x12, 0x79, 0x90, 0x86 +}; +#define ac_dsa_vect56_prime ac_dsa_vect46_prime +#define ac_dsa_vect56_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect56_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect56_ptx[] = { +/* Msg */ + 0xf7, 0x01, 0x8f, 0xf0, 0xaf, 0x67, 0x76, 0xed, 0x42, 0x34, 0xc1, 0xfb, + 0x9c, 0xca, 0x1f, 0x8c, 0xff, 0x31, 0x29, 0x5c, 0xb9, 0xf7, 0x6d, 0x8b, + 0x73, 0x89, 0x84, 0x30, 0x09, 0x7c, 0x49, 0xa4, 0x00, 0x28, 0x44, 0x17, + 0x71, 0xea, 0x1d, 0xe0, 0x8f, 0xfd, 0x5c, 0xec, 0x7e, 0xaa, 0x59, 0xe3, + 0x2b, 0x3a, 0x17, 0x03, 0x29, 0x13, 0x92, 0x27, 0xba, 0x86, 0xe0, 0xc5, + 0xef, 0xca, 0xee, 0x38, 0x2b, 0xff, 0xf9, 0x62, 0x24, 0x9d, 0xa8, 0x53, + 0xde, 0xe4, 0x18, 0x41, 0x3f, 0x20, 0x1a, 0x28, 0xfe, 0x45, 0xb8, 0x29, + 0x3c, 0x26, 0x20, 0x89, 0xd2, 0xce, 0xeb, 0x9a, 0xf6, 0x75, 0x29, 0xab, + 0x01, 0x1f, 0x04, 0xf5, 0xee, 0xaf, 0x82, 0xba, 0x32, 0xdc, 0xe9, 0xa9, + 0x82, 0x17, 0x62, 0xc3, 0x35, 0x1b, 0x00, 0x20, 0x65, 0x91, 0xa3, 0xf8, + 0x7c, 0x52, 0x60, 0xa4, 0x26, 0x36, 0x59, 0xf0 +}; +static const uint8_t ac_dsa_vect56_priv_val[] = { +/* X */ + 0x9d, 0xbd, 0x26, 0x2d, 0xa7, 0xa5, 0x29, 0xf8, 0x0a, 0xa6, 0x67, 0xb2, + 0x7a, 0x29, 0xd6, 0xa5, 0x26, 0x71, 0xfb, 0x89 +}; +static const uint8_t ac_dsa_vect56_pub_val[] = { +/* Y */ + 0x6c, 0x20, 0x6e, 0x71, 0xfe, 0xd8, 0xb3, 0x63, 0xfc, 0xf5, 0x71, 0x78, + 0x6c, 0xe1, 0xb4, 0xe5, 0x2a, 0x40, 0x4d, 0xe7, 0xed, 0xa7, 0x03, 0x1e, + 0x5d, 0x93, 0xa4, 0x7e, 0xa6, 0x68, 0xde, 0x43, 0xdc, 0x70, 0x73, 0xe3, + 0x1d, 0x3b, 0x6b, 0x12, 0x5a, 0xe3, 0xe8, 0xee, 0x45, 0xae, 0xd2, 0x73, + 0xbc, 0x87, 0x8c, 0x73, 0x42, 0x3b, 0x22, 0x5a, 0x15, 0x26, 0xbb, 0xb1, + 0x49, 0xa0, 0xce, 0x5e, 0x9a, 0x2d, 0x29, 0x62, 0xbd, 0x6d, 0x33, 0x23, + 0x75, 0x86, 0x0f, 0x84, 0xce, 0x0e, 0x78, 0x7a, 0x0a, 0xf9, 0x3f, 0x44, + 0xe6, 0x4e, 0xda, 0xa2, 0xdc, 0xe6, 0xca, 0x22, 0xbc, 0xc6, 0xd4, 0x8b, + 0x84, 0xb0, 0xaf, 0xfb, 0xa3, 0x42, 0x75, 0x3b, 0x18, 0x42, 0x94, 0x10, + 0x67, 0xd5, 0xb8, 0x41, 0x4c, 0x35, 0x61, 0x38, 0xe6, 0x25, 0xbb, 0x50, + 0x65, 0x66, 0xa2, 0x7b, 0x33, 0x50, 0x94, 0xb0 +}; +/* K = 0f0e02596ce6674684e7ec448d2938de12842fe2 */ +static const uint8_t ac_dsa_vect56_out[] = { +/* R */ + 0x07, 0x9b, 0x08, 0xbc, 0x01, 0x6c, 0x54, 0x3d, 0x09, 0xd6, 0xb2, 0x76, + 0xc0, 0x23, 0x34, 0x7a, 0x3a, 0xac, 0xe9, 0xae, +/* S */ + 0x16, 0x4c, 0x3c, 0x38, 0x0f, 0x20, 0x9f, 0xea, 0xf8, 0xff, 0xcf, 0x53, + 0x69, 0x1e, 0xe3, 0x03, 0x1c, 0x3b, 0x3f, 0xff +}; +#define ac_dsa_vect57_prime ac_dsa_vect46_prime +#define ac_dsa_vect57_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect57_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect57_ptx[] = { +/* Msg */ + 0x4a, 0x18, 0xbd, 0xcc, 0xcd, 0x46, 0xbb, 0x89, 0x56, 0x7c, 0xeb, 0x9c, + 0x1e, 0x2e, 0x50, 0x0a, 0x3b, 0xae, 0xd2, 0x4f, 0xf2, 0xc5, 0xfc, 0x7f, + 0x83, 0xcb, 0x3c, 0xf6, 0xa6, 0xf3, 0x88, 0x59, 0xa1, 0xa9, 0x27, 0xfa, + 0xb5, 0xe2, 0xfd, 0x7e, 0xa1, 0xe1, 0xa4, 0x15, 0x47, 0x39, 0x30, 0x1c, + 0xb1, 0x95, 0x77, 0x09, 0x10, 0x3a, 0xf8, 0x86, 0xc9, 0x29, 0xcf, 0x88, + 0xd2, 0x5c, 0xed, 0x5c, 0xd6, 0xf8, 0xcf, 0x3f, 0xfe, 0xe7, 0xb0, 0x88, + 0xed, 0xc2, 0xf6, 0xab, 0xd1, 0x11, 0x43, 0x98, 0xa3, 0xab, 0x00, 0xfc, + 0x21, 0xbe, 0xc0, 0x2e, 0x8e, 0x53, 0x9b, 0xa1, 0x2d, 0xf7, 0x0a, 0x58, + 0x7f, 0xbf, 0xba, 0x63, 0x19, 0x5c, 0x64, 0x49, 0xb2, 0xb8, 0x49, 0x54, + 0x7c, 0x42, 0x27, 0x78, 0x34, 0xe1, 0xec, 0x08, 0x6b, 0x5e, 0x53, 0xd9, + 0x49, 0x84, 0x67, 0x69, 0xe8, 0x97, 0x15, 0xbf +}; +static const uint8_t ac_dsa_vect57_priv_val[] = { +/* X */ + 0x5b, 0x3e, 0x9c, 0xc0, 0xe0, 0xbe, 0x3d, 0x71, 0x4d, 0x1b, 0xb2, 0xd9, + 0x5e, 0x51, 0x46, 0xd2, 0x7a, 0x58, 0xf2, 0xee +}; +static const uint8_t ac_dsa_vect57_pub_val[] = { +/* Y */ + 0x8e, 0x66, 0x8d, 0xd1, 0x52, 0x7b, 0x5d, 0x1e, 0x56, 0xaa, 0xe4, 0xa6, + 0xca, 0x22, 0x5e, 0x67, 0x73, 0x68, 0x41, 0x23, 0x24, 0xa7, 0x9d, 0x98, + 0xbf, 0xda, 0xd9, 0xa8, 0x4d, 0x9f, 0x87, 0xc1, 0x35, 0x75, 0x18, 0xc9, + 0xa5, 0x05, 0x6e, 0xa6, 0xa0, 0x88, 0x2e, 0x94, 0xd4, 0xff, 0xad, 0xd9, + 0x7d, 0x89, 0xbc, 0xf2, 0xf3, 0x2f, 0xf4, 0x42, 0xb2, 0x5d, 0xd2, 0xaf, + 0x2a, 0x78, 0xdd, 0xad, 0xe4, 0x6b, 0x75, 0xaa, 0x8a, 0x5b, 0x1a, 0x14, + 0x71, 0x76, 0x4a, 0xb6, 0x99, 0xd7, 0x00, 0xcb, 0x2a, 0x28, 0xb9, 0x59, + 0xa3, 0x84, 0x8e, 0xdb, 0xbd, 0x6c, 0x95, 0x14, 0xee, 0x84, 0x9f, 0x83, + 0x3c, 0x43, 0x00, 0x85, 0x31, 0x36, 0x5a, 0x01, 0x54, 0x1f, 0x9c, 0x0b, + 0x65, 0xd5, 0xe7, 0xd3, 0xc2, 0x1d, 0xc8, 0xbe, 0xf1, 0x36, 0x9a, 0x41, + 0xc0, 0x40, 0x5f, 0x37, 0x23, 0xf6, 0x79, 0x10 +}; +/* K = 3d9b8166860e18a9306026ba669a3620c2954ad4 */ +static const uint8_t ac_dsa_vect57_out[] = { +/* R */ + 0xb2, 0x2c, 0x00, 0xfe, 0x0b, 0xc2, 0xfa, 0xe7, 0xa4, 0xab, 0x74, 0xed, + 0xcd, 0x49, 0x6c, 0x64, 0xa9, 0x99, 0xc7, 0xd3, +/* S */ + 0x85, 0xba, 0x8d, 0xbb, 0xc9, 0x3a, 0xb9, 0x4a, 0x76, 0x13, 0x3d, 0x47, + 0x9e, 0x3f, 0x79, 0x57, 0x69, 0x44, 0xe6, 0xca +}; +#define ac_dsa_vect58_prime ac_dsa_vect46_prime +#define ac_dsa_vect58_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect58_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect58_ptx[] = { +/* Msg */ + 0x75, 0x47, 0x47, 0x11, 0x82, 0x17, 0x66, 0xb0, 0x65, 0xe2, 0x44, 0x86, + 0x01, 0xe8, 0x2b, 0x88, 0x15, 0x3a, 0x41, 0xbf, 0xb5, 0xc6, 0xb6, 0xa9, + 0xdd, 0xcf, 0x73, 0x17, 0x0e, 0xe3, 0x74, 0xa6, 0x62, 0x5d, 0xe1, 0x9c, + 0x56, 0x0b, 0xcb, 0xd2, 0x02, 0x0b, 0xfe, 0xab, 0x5c, 0xbf, 0xad, 0x8f, + 0xc6, 0x0c, 0xcf, 0xc9, 0x5a, 0x1b, 0x94, 0xfb, 0xef, 0xdf, 0x81, 0x5d, + 0x9b, 0xfc, 0x43, 0xfa, 0x59, 0x31, 0x5e, 0x70, 0x93, 0xd5, 0x68, 0x52, + 0x74, 0xb8, 0xaf, 0xc3, 0x13, 0x9b, 0x92, 0x5e, 0xbf, 0x69, 0x7f, 0xe2, + 0x69, 0x9b, 0x0f, 0xeb, 0x1e, 0x42, 0xbc, 0xa6, 0x5e, 0x5d, 0x4e, 0xb0, + 0xb4, 0x51, 0x4a, 0xf9, 0x2d, 0xfa, 0xb8, 0x5e, 0x7f, 0x26, 0x66, 0xc8, + 0x7e, 0x97, 0x89, 0x39, 0x5f, 0x35, 0x4c, 0xe3, 0x39, 0x38, 0xe9, 0x62, + 0x30, 0x61, 0x11, 0x34, 0x65, 0xa4, 0xe2, 0xb9 +}; +static const uint8_t ac_dsa_vect58_priv_val[] = { +/* X */ + 0x9b, 0x4a, 0x25, 0x36, 0xa1, 0x08, 0x89, 0x22, 0x40, 0xfc, 0x40, 0xc8, + 0xc6, 0x9a, 0x4b, 0x9b, 0x90, 0x3a, 0xc7, 0x60 +}; +static const uint8_t ac_dsa_vect58_pub_val[] = { +/* Y */ + 0x74, 0xa9, 0x3c, 0x73, 0xd7, 0x55, 0x00, 0xca, 0x43, 0x05, 0xca, 0x31, + 0x84, 0x47, 0x5b, 0x53, 0xd9, 0x6c, 0x6f, 0xdd, 0x41, 0x7e, 0xf2, 0x3d, + 0x9d, 0xc6, 0x1b, 0x80, 0xbb, 0xc1, 0x10, 0x82, 0x28, 0xd2, 0x54, 0x3c, + 0x1c, 0x3a, 0x9f, 0x2e, 0x77, 0x83, 0xca, 0x69, 0xb0, 0x19, 0xc0, 0xcd, + 0x9a, 0x6d, 0x2b, 0x62, 0xb0, 0xed, 0x93, 0xd4, 0x22, 0x9d, 0xa8, 0x7b, + 0xfc, 0x21, 0xf9, 0xe4, 0xbd, 0x0d, 0xea, 0x2c, 0x4e, 0x6d, 0x4d, 0x2f, + 0x88, 0x20, 0x1a, 0xb0, 0x50, 0x4b, 0x31, 0xf4, 0xef, 0x15, 0x58, 0xad, + 0xf4, 0x93, 0xe4, 0x70, 0xad, 0xfc, 0x57, 0x2c, 0xa6, 0x8d, 0xeb, 0xc4, + 0x61, 0x23, 0x58, 0x9a, 0xe9, 0x13, 0xb9, 0x67, 0x98, 0x3d, 0xbc, 0xac, + 0x6b, 0xf3, 0xbd, 0x86, 0x11, 0x13, 0x7e, 0x39, 0xd5, 0x87, 0x00, 0x57, + 0xae, 0x18, 0xcb, 0x84, 0xa7, 0x6a, 0xae, 0x30 +}; +/* K = a993b059a49855e359014151700d02e8292ae708 */ +static const uint8_t ac_dsa_vect58_out[] = { +/* R */ + 0x1e, 0xd1, 0x31, 0xc9, 0x6a, 0x2c, 0x31, 0x0e, 0x1f, 0x79, 0x76, 0xd3, + 0x08, 0x2a, 0x69, 0xa5, 0xaf, 0x45, 0xbd, 0xd0, +/* S */ + 0x70, 0x66, 0x3e, 0x9a, 0xd7, 0x11, 0x3a, 0xe5, 0x7d, 0x4a, 0xf6, 0x90, + 0x77, 0x12, 0xe0, 0xaa, 0xf8, 0x8b, 0xc0, 0x7a +}; +#define ac_dsa_vect59_prime ac_dsa_vect46_prime +#define ac_dsa_vect59_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect59_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect59_ptx[] = { +/* Msg */ + 0x34, 0x0d, 0xf7, 0x08, 0xd4, 0x57, 0xdf, 0x94, 0x13, 0xef, 0x2b, 0xda, + 0x22, 0x5c, 0x5f, 0x55, 0x8b, 0x90, 0x96, 0x6c, 0xdd, 0x53, 0x1a, 0x0b, + 0x5a, 0xa7, 0x45, 0xd5, 0xc3, 0xea, 0x79, 0x0d, 0xeb, 0xea, 0x22, 0x48, + 0x61, 0xef, 0x12, 0xfb, 0x16, 0x38, 0xbf, 0xf0, 0x12, 0x1f, 0xf2, 0x6d, + 0xbd, 0xcf, 0xfc, 0x29, 0x9b, 0xf9, 0xf3, 0xa9, 0xc1, 0xfe, 0x60, 0x27, + 0x40, 0x0f, 0xf1, 0x4c, 0x34, 0xfb, 0x06, 0xf6, 0x7d, 0xb9, 0xc3, 0x0a, + 0x1d, 0xcb, 0xfd, 0x99, 0x69, 0x03, 0x52, 0x3d, 0x85, 0x04, 0x63, 0x82, + 0xff, 0x28, 0x04, 0x18, 0xd9, 0x74, 0xa3, 0xec, 0xe6, 0xb5, 0xfa, 0xfe, + 0x30, 0x5e, 0x2e, 0x79, 0xb1, 0xd0, 0x7a, 0x7c, 0x1e, 0xeb, 0x7a, 0x12, + 0x77, 0xa8, 0x22, 0x82, 0xbe, 0x62, 0x83, 0x1d, 0xf7, 0xfe, 0xe3, 0x88, + 0x41, 0x46, 0x26, 0x02, 0x98, 0x6a, 0x8e, 0x9b +}; +static const uint8_t ac_dsa_vect59_priv_val[] = { +/* X */ + 0x06, 0x7e, 0x6e, 0x55, 0xbe, 0x47, 0x44, 0x72, 0x3b, 0x6f, 0x05, 0x6b, + 0x76, 0x62, 0x9e, 0x93, 0xc2, 0x97, 0xa5, 0x85 +}; +static const uint8_t ac_dsa_vect59_pub_val[] = { +/* Y */ + 0x61, 0x50, 0xa6, 0x8d, 0x64, 0xad, 0xda, 0x3d, 0x3f, 0xb5, 0xa9, 0x73, + 0xc6, 0x2b, 0x99, 0x2a, 0xd3, 0xfe, 0x53, 0x8a, 0xf7, 0x16, 0x1b, 0xae, + 0x41, 0xea, 0x2f, 0x17, 0x99, 0x30, 0x4f, 0xe5, 0xb8, 0xc8, 0x64, 0xe0, + 0x61, 0xd1, 0x33, 0xd9, 0x4c, 0x16, 0xa4, 0xc6, 0xb0, 0xed, 0x8d, 0xff, + 0xdf, 0x2c, 0xef, 0xa7, 0x39, 0x40, 0x15, 0xe7, 0x5c, 0x57, 0xb1, 0x81, + 0x41, 0x9d, 0xcf, 0xef, 0xe3, 0x40, 0x9d, 0x3b, 0x53, 0xd8, 0x69, 0x11, + 0xc7, 0x49, 0xf9, 0xf2, 0x8f, 0x7c, 0x1d, 0xe9, 0x9f, 0x7e, 0x4b, 0x2e, + 0xa2, 0x2a, 0x48, 0x81, 0x7a, 0xce, 0x4f, 0xd9, 0x97, 0x4f, 0xa5, 0x3b, + 0x8d, 0x4f, 0x05, 0xf5, 0x73, 0x14, 0x88, 0x81, 0x38, 0x03, 0xd7, 0xf3, + 0xaa, 0xf1, 0xcf, 0xa1, 0x38, 0xbc, 0x73, 0xc4, 0xd2, 0x7c, 0xa1, 0x62, + 0x1e, 0x92, 0x26, 0x66, 0x18, 0x83, 0xe9, 0xdd +}; +/* K = 77857e6de8f37eeb6925a87c027a3cd88b9d3584 */ +static const uint8_t ac_dsa_vect59_out[] = { +/* R */ + 0x4f, 0x18, 0x2a, 0xd4, 0x2c, 0xb5, 0x67, 0x1d, 0x31, 0x62, 0xbb, 0x9d, + 0x04, 0xa0, 0x6c, 0xd2, 0x0e, 0xdb, 0xc5, 0x58, +/* S */ + 0xa6, 0xc5, 0x41, 0x79, 0x47, 0x44, 0x77, 0x18, 0xed, 0x1c, 0xb8, 0x9a, + 0x6e, 0xfc, 0xe2, 0xd3, 0x11, 0x6e, 0x50, 0xd1 +}; +#define ac_dsa_vect60_prime ac_dsa_vect46_prime +#define ac_dsa_vect60_sub_prime ac_dsa_vect46_sub_prime +#define ac_dsa_vect60_base ac_dsa_vect46_base +static const uint8_t ac_dsa_vect60_ptx[] = { +/* Msg */ + 0x9f, 0x23, 0xc8, 0x25, 0x63, 0xab, 0x7c, 0x0b, 0xa8, 0x6b, 0xbb, 0x98, + 0x93, 0x35, 0x00, 0x0a, 0x49, 0x3b, 0x29, 0x1e, 0x5d, 0xc1, 0x7c, 0xe7, + 0x29, 0x49, 0x49, 0x58, 0x90, 0x36, 0x23, 0xed, 0x99, 0xdf, 0x34, 0x42, + 0x30, 0xff, 0xb6, 0x26, 0xb1, 0xdb, 0xef, 0xcc, 0xe0, 0x59, 0xae, 0x16, + 0xc2, 0xee, 0x7e, 0xe6, 0xfd, 0x2a, 0x78, 0x07, 0x33, 0x6c, 0xb7, 0x1b, + 0x88, 0x53, 0xe2, 0xed, 0x3b, 0x74, 0xb2, 0xfa, 0xac, 0x82, 0xa8, 0x31, + 0xd5, 0x3e, 0x03, 0xd7, 0xbb, 0xb9, 0x6d, 0x38, 0xdf, 0x98, 0xfd, 0x19, + 0xbd, 0x4c, 0x1a, 0x62, 0x48, 0xcd, 0x50, 0x7c, 0x89, 0xf7, 0x99, 0x5f, + 0x59, 0x57, 0x9a, 0xfe, 0x53, 0x19, 0x73, 0x1b, 0x44, 0x3d, 0x68, 0x71, + 0xe5, 0x58, 0xf5, 0xb7, 0x7f, 0x2f, 0x9a, 0x4d, 0xd9, 0x9e, 0xfb, 0x30, + 0x5e, 0x27, 0x91, 0x65, 0x94, 0x52, 0x4e, 0x02 +}; +static const uint8_t ac_dsa_vect60_priv_val[] = { +/* X */ + 0xb4, 0x57, 0xe1, 0x75, 0x6e, 0xe9, 0x05, 0x6f, 0xda, 0x72, 0x07, 0x61, + 0x6c, 0xf7, 0xc0, 0x4a, 0x33, 0xaf, 0xa6, 0x6a +}; +static const uint8_t ac_dsa_vect60_pub_val[] = { +/* Y */ + 0x96, 0xd7, 0x45, 0x11, 0x81, 0xfb, 0x25, 0x3f, 0xbc, 0x3f, 0x44, 0x14, + 0x09, 0xbe, 0x5e, 0x5e, 0x01, 0x44, 0x97, 0x26, 0x10, 0xe3, 0x7f, 0xa8, + 0x2b, 0xc2, 0xaf, 0x24, 0x66, 0x37, 0xa4, 0xc9, 0x18, 0x02, 0x30, 0x97, + 0x87, 0x52, 0x55, 0xa2, 0x17, 0xea, 0x89, 0x5d, 0xad, 0xdf, 0x46, 0xbf, + 0xbb, 0x17, 0x47, 0x49, 0xb0, 0x4c, 0x59, 0xfe, 0xfa, 0x62, 0x89, 0x68, + 0x4f, 0x2f, 0x9a, 0xea, 0xdf, 0x5c, 0xe7, 0xca, 0x47, 0xf0, 0x03, 0x2e, + 0x38, 0x4b, 0x7d, 0x50, 0x59, 0x79, 0x01, 0x18, 0x15, 0x01, 0xcb, 0x59, + 0x15, 0xfb, 0x46, 0x86, 0xa6, 0xad, 0x7b, 0xcd, 0x5b, 0x46, 0x86, 0x24, + 0x11, 0xa4, 0xdf, 0x22, 0xb1, 0xed, 0x2a, 0x56, 0x90, 0x5e, 0x07, 0xc0, + 0xa9, 0x36, 0xc9, 0x94, 0x42, 0x13, 0x19, 0x4e, 0xbe, 0xfd, 0x4e, 0xc6, + 0x85, 0x97, 0xcc, 0xa0, 0x36, 0x33, 0x8b, 0x3c +}; +/* K = b29f28659dffea28449435b5a044487e29d82d6a */ +static const uint8_t ac_dsa_vect60_out[] = { +/* R */ + 0xb6, 0x59, 0x9f, 0xbd, 0xdb, 0x48, 0x56, 0x27, 0x6d, 0xf4, 0x48, 0xcf, + 0x09, 0xd6, 0x2f, 0xd7, 0x65, 0x7d, 0xe6, 0xc3, +/* S */ + 0x4b, 0x49, 0x58, 0x90, 0x99, 0xbe, 0x55, 0x78, 0x32, 0x2d, 0x82, 0x9b, + 0x87, 0xb4, 0x3a, 0xc0, 0x7f, 0x62, 0xe3, 0x5d +}; +/* [mod = L=1024, N=160, SHA-512] */ +static const uint8_t ac_dsa_vect61_prime[] = { +/* P */ + 0x88, 0xd9, 0x68, 0xe9, 0x60, 0x2e, 0xcb, 0xda, 0x6d, 0x86, 0xf7, 0xc9, + 0x70, 0xa3, 0xff, 0xbe, 0xb1, 0xda, 0x96, 0x2f, 0x28, 0xc0, 0xaf, 0xb9, + 0x27, 0x0e, 0xf0, 0x5b, 0xc3, 0x30, 0xca, 0x98, 0xc3, 0xad, 0xf8, 0x3c, + 0x07, 0x2f, 0xeb, 0x05, 0xfb, 0x2e, 0x29, 0x3b, 0x50, 0x65, 0xbb, 0xb0, + 0xcb, 0xcc, 0x93, 0x0c, 0x24, 0xd8, 0xd0, 0x78, 0x69, 0xde, 0xae, 0xcd, + 0x92, 0xa2, 0x60, 0x4c, 0x0f, 0x5d, 0xd3, 0x5c, 0x5b, 0x43, 0x1f, 0xda, + 0x6a, 0x22, 0x2c, 0x52, 0xc3, 0x56, 0x2b, 0xf7, 0x57, 0x1c, 0x71, 0x02, + 0x09, 0xbe, 0x8b, 0x3b, 0x85, 0x88, 0x18, 0x78, 0x87, 0x25, 0xfe, 0x81, + 0x12, 0xb7, 0xd6, 0xbc, 0x82, 0xe0, 0xff, 0x1c, 0xbb, 0xf5, 0xd6, 0xfe, + 0x94, 0x69, 0x0a, 0xf2, 0xb5, 0x10, 0xe4, 0x1a, 0xd8, 0x20, 0x7d, 0xc2, + 0xc0, 0x2f, 0xb9, 0xfa, 0x5c, 0xef, 0xaa, 0xb5 +}; +static const uint8_t ac_dsa_vect61_sub_prime[] = { +/* Q */ + 0xa6, 0x65, 0x68, 0x9b, 0x9e, 0x5b, 0x9c, 0xe8, 0x2f, 0xd1, 0x67, 0x60, + 0x06, 0xcf, 0x4c, 0xf6, 0x7e, 0xcc, 0x56, 0xb7 +}; +static const uint8_t ac_dsa_vect61_base[] = { +/* G */ + 0x26, 0x7e, 0x28, 0x28, 0x57, 0x41, 0x77, 0x52, 0x11, 0x3f, 0xba, 0x3f, + 0xca, 0x71, 0x55, 0xb5, 0xce, 0x89, 0xe7, 0xc8, 0xa3, 0x3c, 0x1a, 0x29, + 0x12, 0x2e, 0x2b, 0x72, 0x09, 0x65, 0xfc, 0x04, 0x24, 0x52, 0x67, 0xff, + 0x87, 0xfc, 0x67, 0xa5, 0x73, 0x0f, 0xe5, 0xb3, 0x08, 0x01, 0x3a, 0xa3, + 0x26, 0x69, 0x90, 0xfb, 0xb3, 0x98, 0x18, 0x5a, 0x87, 0xe0, 0x55, 0xb4, + 0x43, 0xa8, 0x68, 0xce, 0x0c, 0xe1, 0x3a, 0xe6, 0xae, 0xe3, 0x30, 0xb9, + 0xd2, 0x5d, 0x3b, 0xbb, 0x36, 0x26, 0x65, 0xc5, 0x88, 0x1d, 0xaf, 0x0c, + 0x5a, 0xa7, 0x5e, 0x9d, 0x4a, 0x82, 0xe8, 0xf0, 0x4c, 0x91, 0xa9, 0xad, + 0x29, 0x48, 0x22, 0xe3, 0x39, 0x78, 0xab, 0x0c, 0x13, 0xfa, 0xdc, 0x45, + 0x83, 0x1f, 0x9d, 0x37, 0xda, 0x4e, 0xfa, 0x0f, 0xc2, 0xc5, 0xeb, 0x01, + 0x37, 0x1f, 0xa8, 0x5b, 0x7d, 0xdb, 0x1f, 0x82 +}; +static const uint8_t ac_dsa_vect61_ptx[] = { +/* Msg */ + 0x3a, 0x84, 0xa5, 0x31, 0x4e, 0x90, 0xfd, 0x33, 0xbb, 0x7c, 0xd6, 0xca, + 0x68, 0x72, 0x0c, 0x69, 0x05, 0x8d, 0xa1, 0xda, 0x1b, 0x35, 0x90, 0x46, + 0xae, 0x89, 0x22, 0xca, 0xc8, 0xaf, 0xc5, 0xe0, 0x25, 0x77, 0x16, 0x35, + 0xfb, 0x47, 0x35, 0x49, 0x15, 0x21, 0xa7, 0x28, 0x44, 0x1b, 0x5c, 0xb0, + 0x87, 0xd6, 0x07, 0x76, 0xee, 0x0e, 0xcc, 0x21, 0x74, 0xa4, 0x19, 0x85, + 0xa8, 0x2c, 0xf4, 0x6d, 0x8f, 0x8d, 0x8b, 0x27, 0x4a, 0x0c, 0xc4, 0x39, + 0xb0, 0x09, 0x71, 0x07, 0x7c, 0x74, 0x5f, 0x8c, 0xf7, 0x01, 0xcf, 0x56, + 0xbf, 0x99, 0x14, 0xcc, 0x57, 0x20, 0x9b, 0x55, 0x5d, 0xc8, 0x7c, 0xa8, + 0xc1, 0x3d, 0xa0, 0x63, 0x27, 0x0c, 0x60, 0xfc, 0x2c, 0x98, 0x8e, 0x69, + 0x2b, 0x75, 0xa7, 0xf2, 0xa6, 0x69, 0x90, 0x3b, 0x93, 0xd2, 0xe1, 0x4e, + 0x8e, 0xfb, 0x6f, 0xb9, 0xf8, 0x69, 0x4a, 0x78 +}; +static const uint8_t ac_dsa_vect61_priv_val[] = { +/* X */ + 0x07, 0xce, 0x88, 0x62, 0xe6, 0x4b, 0x7f, 0x6c, 0x74, 0x82, 0x04, 0x6d, + 0xbf, 0xc9, 0x39, 0x07, 0x12, 0x3e, 0x52, 0x14 +}; +static const uint8_t ac_dsa_vect61_pub_val[] = { +/* Y */ + 0x60, 0xf5, 0x34, 0x1e, 0x48, 0xca, 0x7a, 0x3b, 0xc5, 0xde, 0xce, 0xe6, + 0x12, 0x11, 0xdd, 0x27, 0x27, 0xcd, 0x8e, 0x2f, 0xc7, 0x63, 0x5f, 0x3a, + 0xab, 0xea, 0x26, 0x23, 0x66, 0xe4, 0x58, 0xf5, 0xc5, 0x1c, 0x31, 0x1a, + 0xfd, 0xa9, 0x16, 0xcb, 0x0d, 0xcd, 0xc5, 0xd5, 0xa5, 0x72, 0x9f, 0x57, + 0x3a, 0x53, 0x2b, 0x59, 0x47, 0x43, 0x19, 0x9b, 0xcf, 0xa7, 0x45, 0x49, + 0x03, 0xe7, 0x4b, 0x33, 0xdd, 0xfe, 0x65, 0x89, 0x63, 0x06, 0xce, 0xc2, + 0x0e, 0xbd, 0x84, 0x27, 0x68, 0x2f, 0xa5, 0x01, 0xee, 0x06, 0xbc, 0x4c, + 0x5d, 0x14, 0x25, 0xcb, 0xe3, 0x18, 0x28, 0xba, 0x00, 0x8b, 0x19, 0xc9, + 0xda, 0x68, 0x13, 0x6c, 0xf7, 0x18, 0x40, 0xb2, 0x05, 0x91, 0x9e, 0x78, + 0x3a, 0x62, 0x8a, 0x5a, 0x57, 0xcf, 0x91, 0xcf, 0x56, 0x9b, 0x28, 0x54, + 0xff, 0xef, 0x7a, 0x09, 0x6e, 0xda, 0x96, 0xc9 +}; +/* K = 2f170907ac69726b14f22056dcb37b4df85f7424 */ +static const uint8_t ac_dsa_vect61_out[] = { +/* R */ + 0xa5, 0x3f, 0x1f, 0x8f, 0x20, 0xb8, 0xd3, 0xd4, 0x72, 0x0f, 0x14, 0xa8, + 0xba, 0xb5, 0x22, 0x6b, 0x07, 0x9d, 0x99, 0x53, +/* S */ + 0x11, 0xf5, 0x3f, 0x6a, 0x4e, 0x56, 0xb5, 0x1f, 0x60, 0xe2, 0x0d, 0x49, + 0x57, 0xae, 0x89, 0xe1, 0x62, 0xae, 0xa6, 0x16 +}; +#define ac_dsa_vect62_prime ac_dsa_vect61_prime +#define ac_dsa_vect62_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect62_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect62_ptx[] = { +/* Msg */ + 0x6f, 0x39, 0x97, 0x3f, 0xd2, 0x25, 0x16, 0x7a, 0x76, 0x73, 0xcd, 0x71, + 0xab, 0x35, 0x34, 0xd2, 0x68, 0x66, 0x87, 0xc3, 0x32, 0xf9, 0x3f, 0xd6, + 0x6d, 0xb5, 0xf1, 0xca, 0x99, 0x67, 0x8e, 0xfd, 0x28, 0x25, 0xa8, 0x4c, + 0xd7, 0xa7, 0x10, 0x7a, 0xdf, 0x96, 0x50, 0x1d, 0xd1, 0xd0, 0x5e, 0x7b, + 0xbc, 0x8d, 0x11, 0x3e, 0x08, 0x7b, 0xba, 0x77, 0xb2, 0x34, 0x6b, 0x43, + 0x64, 0x13, 0x21, 0x25, 0x24, 0x5e, 0x9a, 0xac, 0xe3, 0xa1, 0x46, 0xb5, + 0x76, 0xf6, 0x54, 0xc8, 0x6e, 0x07, 0xfc, 0x19, 0x14, 0xca, 0xfa, 0x20, + 0x9d, 0xd6, 0xd0, 0x48, 0x45, 0x57, 0x5d, 0xbb, 0x27, 0x9c, 0xd1, 0xb2, + 0x32, 0x96, 0xd0, 0x1e, 0xf5, 0x05, 0xb5, 0xe1, 0xce, 0x7f, 0x21, 0x94, + 0xf1, 0x89, 0x88, 0xf3, 0x55, 0xc9, 0xb3, 0x4f, 0x92, 0x0a, 0xb3, 0x51, + 0x52, 0xe0, 0x3b, 0xcf, 0x79, 0x2a, 0xc5, 0x29 +}; +static const uint8_t ac_dsa_vect62_priv_val[] = { +/* X */ + 0x8d, 0x75, 0x29, 0x4b, 0x56, 0x26, 0x2e, 0x42, 0xa8, 0x2d, 0xb4, 0x1a, + 0x40, 0x39, 0x61, 0x53, 0x96, 0x57, 0x4d, 0xbf +}; +static const uint8_t ac_dsa_vect62_pub_val[] = { +/* Y */ + 0x11, 0x0e, 0x39, 0x8e, 0x36, 0xc9, 0xd2, 0x72, 0x6e, 0x77, 0xde, 0xb4, + 0x65, 0xdd, 0x23, 0x30, 0x3f, 0x9e, 0x38, 0x77, 0x78, 0xb5, 0x49, 0x70, + 0x0a, 0x52, 0xb9, 0xa5, 0x46, 0x85, 0x12, 0xee, 0x37, 0x7c, 0xe3, 0xd7, + 0xdc, 0xbf, 0xc6, 0xb6, 0x4e, 0xe3, 0x53, 0xea, 0xc6, 0xa4, 0x38, 0x98, + 0xb2, 0x64, 0x84, 0x05, 0x8b, 0xa1, 0xb2, 0x4b, 0x22, 0x9c, 0xd6, 0x9c, + 0x99, 0x4d, 0x97, 0x6d, 0x43, 0x34, 0x4c, 0x18, 0x1e, 0xa6, 0xc4, 0x7d, + 0xf0, 0x06, 0x2c, 0x09, 0xa1, 0x6b, 0x23, 0xab, 0x60, 0x75, 0xc0, 0x4a, + 0x08, 0x99, 0xba, 0xc3, 0xe4, 0xf0, 0x34, 0xa9, 0x83, 0xbf, 0x90, 0x43, + 0x8f, 0x6a, 0xc2, 0x68, 0x55, 0xd8, 0xa5, 0xfd, 0xed, 0x90, 0x17, 0x2e, + 0x7e, 0x8c, 0x19, 0x6a, 0x2c, 0xe7, 0xe1, 0xfc, 0x0d, 0xac, 0x94, 0x27, + 0x8a, 0xff, 0x16, 0x53, 0xc3, 0xae, 0x09, 0xf5 +}; +/* K = 66a1322607ab98aaa57c12a5cc3f59dce8d7d0cc */ +static const uint8_t ac_dsa_vect62_out[] = { +/* R */ + 0x1b, 0x9e, 0xd3, 0x9b, 0xcc, 0x4b, 0x46, 0xed, 0x00, 0x07, 0x67, 0x9c, + 0xe9, 0xc3, 0xf6, 0xdc, 0x7c, 0x41, 0x57, 0xb9, +/* S */ + 0x25, 0x8d, 0x41, 0x36, 0xad, 0x95, 0xb7, 0x04, 0xa7, 0x95, 0x9d, 0x04, + 0x09, 0x6d, 0xcd, 0x78, 0x1e, 0xb5, 0x4b, 0xde +}; +#define ac_dsa_vect63_prime ac_dsa_vect61_prime +#define ac_dsa_vect63_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect63_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect63_ptx[] = { +/* Msg */ + 0x7f, 0x59, 0x74, 0x4c, 0x79, 0x0c, 0x0f, 0x98, 0x5a, 0x9a, 0xe1, 0x01, + 0xd9, 0xfa, 0x00, 0xda, 0x3b, 0x95, 0xd2, 0x47, 0x3d, 0x79, 0x28, 0x05, + 0xec, 0x1d, 0x6d, 0x1e, 0x95, 0x22, 0x2a, 0x6f, 0x30, 0xee, 0x6a, 0xb8, + 0xfc, 0x5a, 0x63, 0x20, 0x57, 0x15, 0x3f, 0x23, 0x7a, 0xd3, 0xaa, 0x2f, + 0xae, 0x8f, 0x1e, 0x51, 0xea, 0xe7, 0x59, 0x06, 0xd0, 0x7e, 0x57, 0x6d, + 0xd0, 0x02, 0x1a, 0xc1, 0x71, 0x1b, 0x1c, 0x88, 0x53, 0xe6, 0x2d, 0x27, + 0xfe, 0x6b, 0x09, 0x87, 0x66, 0xb8, 0xce, 0x3e, 0x76, 0xd3, 0x47, 0xc8, + 0xe4, 0x9b, 0xe0, 0xab, 0x05, 0xd0, 0xd1, 0x2f, 0xd7, 0x77, 0xa8, 0x5c, + 0xff, 0xc7, 0xad, 0x12, 0x07, 0xa9, 0xaa, 0x75, 0x64, 0x3d, 0x7b, 0x41, + 0x5b, 0xa4, 0xb1, 0xb9, 0x7d, 0xc0, 0xee, 0x19, 0xd0, 0x5a, 0x60, 0x7b, + 0xa0, 0x63, 0xa0, 0x34, 0x1f, 0x17, 0x61, 0x04 +}; +static const uint8_t ac_dsa_vect63_priv_val[] = { +/* X */ + 0x25, 0xb7, 0xfe, 0xdc, 0xba, 0x71, 0xed, 0xa8, 0x5f, 0xe1, 0x89, 0xbf, + 0x0d, 0x0c, 0x43, 0x21, 0x4a, 0xb6, 0x38, 0x8a +}; +static const uint8_t ac_dsa_vect63_pub_val[] = { +/* Y */ + 0x3e, 0xad, 0x9c, 0xf2, 0x11, 0xf3, 0x85, 0x9d, 0x5b, 0xaa, 0x51, 0x55, + 0xfb, 0x62, 0x33, 0x1b, 0xca, 0x3f, 0xff, 0x9e, 0xcb, 0xe1, 0x82, 0xeb, + 0xf8, 0xb0, 0x4d, 0xb0, 0xeb, 0xb1, 0x9e, 0xda, 0x54, 0x8c, 0x86, 0xdb, + 0x4c, 0xbb, 0x5e, 0xca, 0x98, 0xce, 0x44, 0x9c, 0xfd, 0x51, 0xf1, 0xc4, + 0x60, 0xd7, 0x84, 0x83, 0x26, 0xee, 0xe2, 0x2f, 0xca, 0xc7, 0x24, 0x7f, + 0xb8, 0x89, 0xee, 0x41, 0x5c, 0x49, 0x33, 0xa9, 0x09, 0xc7, 0x8c, 0xe9, + 0xbc, 0x50, 0xee, 0x19, 0x01, 0x16, 0xda, 0x9a, 0xe2, 0x54, 0x7a, 0xe6, + 0x24, 0x2a, 0x34, 0x0d, 0xdb, 0xb9, 0xa1, 0x5a, 0xc8, 0x18, 0xc4, 0x67, + 0x7f, 0x29, 0x19, 0xc6, 0x45, 0x09, 0xd0, 0x3c, 0x49, 0xd1, 0x30, 0x7b, + 0xb2, 0xcd, 0x78, 0xe0, 0x1c, 0xe5, 0xb2, 0x5a, 0x9f, 0x47, 0xd8, 0x28, + 0xfc, 0x75, 0x84, 0xeb, 0xce, 0x36, 0x6c, 0x2f +}; +/* K = 8fd754defb1274bb7ddea0fc13fdc76722442d86 */ +static const uint8_t ac_dsa_vect63_out[] = { +/* R */ + 0x38, 0xf5, 0x2d, 0xf7, 0x8b, 0x0e, 0x45, 0x4d, 0x35, 0x83, 0x20, 0x8a, + 0x0f, 0xce, 0x03, 0xb9, 0x04, 0xee, 0xc8, 0x16, +/* S */ + 0x5c, 0xdc, 0x57, 0xa9, 0x43, 0xab, 0x1f, 0x26, 0x9c, 0xa1, 0x1c, 0x63, + 0xbc, 0xb1, 0x05, 0x9e, 0xe7, 0x6f, 0x9c, 0x2e +}; +#define ac_dsa_vect64_prime ac_dsa_vect61_prime +#define ac_dsa_vect64_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect64_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect64_ptx[] = { +/* Msg */ + 0x16, 0x25, 0x0c, 0x74, 0xcc, 0xb4, 0x04, 0x43, 0x62, 0x5a, 0x37, 0xc4, + 0xb7, 0xe2, 0xb3, 0x61, 0x52, 0x55, 0x76, 0x82, 0x41, 0xf2, 0x54, 0xa5, + 0x06, 0xfa, 0x81, 0x9e, 0xfb, 0xb8, 0x69, 0x8a, 0xde, 0x38, 0xfc, 0x75, + 0x94, 0x6b, 0x3a, 0xf0, 0x90, 0x55, 0x57, 0x8f, 0x28, 0xa1, 0x81, 0x82, + 0x7d, 0xda, 0x31, 0x1b, 0xd4, 0x03, 0x8f, 0xd4, 0x7f, 0x6d, 0x86, 0xcc, + 0xeb, 0x1b, 0xbb, 0xef, 0x2d, 0xf2, 0x0b, 0xf5, 0x95, 0xa0, 0xad, 0x77, + 0xaf, 0xd3, 0x9c, 0x84, 0x87, 0x74, 0x34, 0xad, 0xe3, 0x81, 0x2f, 0x05, + 0xec, 0x54, 0x1e, 0x04, 0x03, 0xab, 0xad, 0xc7, 0x78, 0xd1, 0x16, 0xfd, + 0x07, 0x7c, 0x95, 0xc6, 0xec, 0x0f, 0x47, 0x24, 0x1f, 0x4d, 0xb8, 0x13, + 0xf3, 0x19, 0x86, 0xb7, 0x50, 0x4c, 0x1c, 0xd9, 0xdd, 0xb4, 0x96, 0xac, + 0x6e, 0xd2, 0x2b, 0x45, 0xe7, 0xdf, 0x72, 0xcc +}; +static const uint8_t ac_dsa_vect64_priv_val[] = { +/* X */ + 0x3f, 0xee, 0x04, 0xcc, 0x08, 0x62, 0x4f, 0x3a, 0x7f, 0x34, 0xc5, 0x38, + 0xd8, 0x76, 0x92, 0x20, 0x9d, 0xd7, 0x47, 0x97 +}; +static const uint8_t ac_dsa_vect64_pub_val[] = { +/* Y */ + 0x6e, 0x8c, 0x85, 0x15, 0x0c, 0x5c, 0x9c, 0xa6, 0xdc, 0xb0, 0x48, 0x06, + 0x67, 0x1d, 0xb1, 0xb6, 0x72, 0xfc, 0x10, 0x87, 0xc9, 0x95, 0x31, 0x1d, + 0x70, 0x87, 0xad, 0x12, 0xab, 0x18, 0xf2, 0xc1, 0x4b, 0x61, 0x2c, 0xea, + 0x13, 0xbf, 0x79, 0x51, 0x8d, 0x2b, 0x57, 0x0b, 0x8b, 0x69, 0x6b, 0x3e, + 0x4e, 0xfc, 0xd0, 0xfd, 0xa5, 0x22, 0xa2, 0x53, 0xbb, 0xcb, 0x7d, 0xbb, + 0x71, 0x1d, 0x98, 0x4c, 0x59, 0x8f, 0xa2, 0x01, 0xc2, 0x1a, 0x8a, 0x9e, + 0x27, 0x74, 0xbc, 0x15, 0x02, 0x09, 0x20, 0xcd, 0x8c, 0x27, 0xc2, 0x87, + 0x5c, 0x77, 0x9b, 0x08, 0xef, 0x95, 0x09, 0x3c, 0xaa, 0xc2, 0xc9, 0xce, + 0xa3, 0x7e, 0xc4, 0x98, 0xc2, 0x3d, 0xd2, 0x4b, 0x68, 0x4a, 0xbc, 0xb4, + 0x67, 0xec, 0x95, 0x2a, 0x20, 0x2c, 0xbd, 0x2d, 0xf7, 0x96, 0x0c, 0x1e, + 0xf9, 0x29, 0xcc, 0x2b, 0x61, 0x1c, 0xa6, 0xc8 +}; +/* K = 934552738360670c98b9c5384b639c46cdecfa83 */ +static const uint8_t ac_dsa_vect64_out[] = { +/* R */ + 0x00, 0x01, 0x8f, 0x0f, 0xdc, 0x16, 0xd9, 0x14, 0x97, 0x1c, 0x8f, 0x31, + 0x0f, 0x1a, 0xf7, 0x79, 0x6c, 0x6f, 0x66, 0x2a, +/* S */ + 0x62, 0xb7, 0xae, 0xcc, 0x75, 0xcb, 0xc6, 0xdb, 0x00, 0xdd, 0x0c, 0x24, + 0x33, 0x9f, 0x7b, 0xdb, 0x5a, 0xe9, 0x66, 0xa5 +}; +#define ac_dsa_vect65_prime ac_dsa_vect61_prime +#define ac_dsa_vect65_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect65_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect65_ptx[] = { +/* Msg */ + 0xa2, 0xce, 0x90, 0xb5, 0x1a, 0x48, 0x0c, 0x06, 0x68, 0xb5, 0x59, 0x36, + 0xbb, 0xee, 0xbe, 0x36, 0x79, 0xf8, 0xd4, 0x06, 0xa0, 0xb6, 0x94, 0xb9, + 0x03, 0x45, 0x74, 0x9e, 0x3b, 0x9c, 0x67, 0x77, 0x6c, 0xae, 0x9a, 0x62, + 0xc2, 0x5c, 0xc0, 0x11, 0xcd, 0xb3, 0x18, 0x02, 0x63, 0xdd, 0xd7, 0x3a, + 0xa2, 0x09, 0x0e, 0xc7, 0xa7, 0x49, 0x09, 0x2f, 0x6c, 0x78, 0x16, 0xc2, + 0x67, 0x44, 0xc5, 0x39, 0x3a, 0xcb, 0x08, 0xc6, 0xb7, 0xb3, 0x59, 0xbb, + 0x3a, 0x3c, 0x75, 0x43, 0x68, 0x4f, 0x80, 0x50, 0xec, 0xc6, 0x42, 0x22, + 0x34, 0xff, 0x24, 0x97, 0x8a, 0xe0, 0x6b, 0x91, 0xd6, 0xa2, 0x4c, 0x08, + 0x6d, 0x71, 0xeb, 0x17, 0x61, 0xca, 0xf1, 0x41, 0x76, 0xd8, 0xba, 0xcd, + 0xca, 0xd5, 0x3b, 0x78, 0x95, 0xbd, 0xb0, 0xe0, 0x53, 0xc6, 0x16, 0xb1, + 0x47, 0xff, 0x73, 0xd2, 0xd8, 0x6b, 0xa3, 0xbc +}; +static const uint8_t ac_dsa_vect65_priv_val[] = { +/* X */ + 0x2d, 0x66, 0x7b, 0xeb, 0xf4, 0x45, 0xcd, 0x3e, 0xe4, 0x5d, 0x58, 0x15, + 0xe0, 0x7c, 0xa5, 0x73, 0x5b, 0x85, 0x8a, 0xda +}; +static const uint8_t ac_dsa_vect65_pub_val[] = { +/* Y */ + 0x0e, 0x6b, 0x41, 0x9d, 0xa8, 0xb4, 0xdb, 0x80, 0x2d, 0x93, 0x88, 0x73, + 0xe3, 0xb1, 0x05, 0xab, 0x3e, 0xff, 0x43, 0x2d, 0x8a, 0x13, 0x76, 0x60, + 0x20, 0x59, 0xcf, 0x2e, 0x51, 0x0f, 0x69, 0x6a, 0x2a, 0x4e, 0x42, 0x02, + 0x56, 0x70, 0xdb, 0x00, 0x11, 0xe9, 0xbe, 0x31, 0xe8, 0xb1, 0x40, 0x36, + 0x15, 0xb9, 0xa3, 0x39, 0xce, 0x65, 0x4a, 0x89, 0xa2, 0xd4, 0x62, 0xee, + 0x20, 0xc0, 0x80, 0xc4, 0x47, 0x96, 0x48, 0xc5, 0xc0, 0x0e, 0x17, 0x2e, + 0xcd, 0x53, 0x7c, 0x93, 0x4e, 0x75, 0x34, 0xaf, 0x70, 0x02, 0xbd, 0x6f, + 0xda, 0xfa, 0xb5, 0x65, 0x06, 0x68, 0x0c, 0x01, 0x9c, 0xed, 0x38, 0x77, + 0x9d, 0x95, 0x40, 0x91, 0x64, 0x5f, 0xed, 0xf5, 0xd0, 0x05, 0x7a, 0x23, + 0xff, 0x63, 0x49, 0x19, 0xfc, 0x56, 0xa9, 0x67, 0x71, 0xce, 0x21, 0xfa, + 0x99, 0xec, 0xd9, 0xaa, 0x7f, 0x79, 0x85, 0xf1 +}; +/* K = 4aeb4911d38f1f634ddf5fe6c970d943ea51b266 */ +static const uint8_t ac_dsa_vect65_out[] = { +/* R */ + 0x5b, 0x13, 0xf1, 0x33, 0x7a, 0xc7, 0x2e, 0x41, 0x98, 0x67, 0xc9, 0x2f, + 0x93, 0x87, 0xf9, 0xdf, 0x62, 0x88, 0x3a, 0xa5, +/* S */ + 0x90, 0xab, 0x5b, 0x68, 0xfd, 0x82, 0x53, 0xb6, 0xbb, 0x64, 0xc6, 0x17, + 0x59, 0x16, 0x4a, 0x97, 0x83, 0x4c, 0x39, 0xe1 +}; +#define ac_dsa_vect66_prime ac_dsa_vect61_prime +#define ac_dsa_vect66_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect66_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect66_ptx[] = { +/* Msg */ + 0x3b, 0x6e, 0xea, 0xed, 0xc5, 0xfb, 0x38, 0xce, 0x86, 0x91, 0x68, 0x6c, + 0x89, 0x99, 0x3c, 0xaf, 0x17, 0xc9, 0xe2, 0x4f, 0xa5, 0x65, 0xa9, 0xe8, + 0xd4, 0x84, 0x36, 0xb8, 0x7d, 0xb6, 0x2f, 0xab, 0x83, 0x9c, 0x42, 0xd8, + 0x1f, 0xb1, 0xf8, 0xb8, 0x96, 0x8c, 0x82, 0x6e, 0x78, 0xd3, 0x33, 0xb1, + 0xd9, 0x9d, 0x5c, 0x36, 0xe0, 0x8a, 0x9a, 0x0e, 0xc7, 0x55, 0x4c, 0x2b, + 0xde, 0x07, 0xfd, 0x8e, 0xc4, 0x22, 0xaf, 0x12, 0x82, 0x46, 0xba, 0x3b, + 0xea, 0xe1, 0x8e, 0xf2, 0xbe, 0x75, 0x5d, 0xb2, 0x2a, 0x86, 0x92, 0x02, + 0x95, 0x1c, 0xd9, 0x57, 0x96, 0xfc, 0x2f, 0xf7, 0xba, 0x2a, 0x69, 0x67, + 0xd1, 0x9e, 0x5c, 0xa2, 0x30, 0x46, 0x55, 0xbf, 0xdf, 0x87, 0x9b, 0x77, + 0x47, 0xf8, 0x0a, 0x59, 0xb1, 0xda, 0xc0, 0x46, 0x1c, 0xf6, 0xe4, 0x90, + 0x37, 0x8e, 0x56, 0xab, 0x37, 0x85, 0x84, 0xf2 +}; +static const uint8_t ac_dsa_vect66_priv_val[] = { +/* X */ + 0x71, 0xdb, 0xba, 0xc5, 0x97, 0x68, 0xe1, 0xe3, 0x09, 0x3f, 0x0c, 0x60, + 0x40, 0x47, 0x31, 0xa2, 0xea, 0xd4, 0x82, 0xc3 +}; +static const uint8_t ac_dsa_vect66_pub_val[] = { +/* Y */ + 0x4a, 0x7f, 0xf6, 0x67, 0xf7, 0xab, 0x28, 0x91, 0xa8, 0xa6, 0x9a, 0xb5, + 0xd1, 0x5d, 0x93, 0xd1, 0xfd, 0x83, 0x39, 0x06, 0xc9, 0xb6, 0x29, 0xfc, + 0xb9, 0xb4, 0x9e, 0x84, 0xd8, 0xec, 0xb3, 0x5b, 0x39, 0x7d, 0x93, 0x83, + 0x9d, 0x79, 0x85, 0x59, 0x03, 0x26, 0xcf, 0xfb, 0x55, 0xa7, 0x0e, 0x4a, + 0x51, 0xa2, 0x82, 0x9e, 0x38, 0x72, 0x90, 0xf6, 0xfa, 0xfb, 0x7d, 0x22, + 0x61, 0x51, 0xc2, 0x82, 0x47, 0x02, 0x24, 0xfd, 0x71, 0x7f, 0x3d, 0x52, + 0x65, 0x89, 0xc6, 0xee, 0xd9, 0x61, 0x1c, 0x5b, 0xdf, 0x4b, 0xde, 0x63, + 0xfc, 0xc9, 0x20, 0x4c, 0x80, 0x07, 0xb0, 0xb1, 0x43, 0xc4, 0x9d, 0x19, + 0x81, 0x83, 0x56, 0x58, 0xbc, 0xf8, 0x00, 0xa2, 0x15, 0x7c, 0x5c, 0x14, + 0x3d, 0x76, 0x36, 0x9f, 0xd6, 0xe7, 0x8d, 0x0a, 0x3f, 0x80, 0x0b, 0x8a, + 0x3a, 0x8f, 0x0e, 0x11, 0xc9, 0x05, 0x9d, 0xcd +}; +/* K = 8f78910d1e8a9daad9523626ee7ab1d0a5b4d977 */ +static const uint8_t ac_dsa_vect66_out[] = { +/* R */ + 0x61, 0x38, 0x0c, 0xa8, 0x67, 0x98, 0xfc, 0x5f, 0xb6, 0x1c, 0x35, 0x67, + 0x5a, 0xf0, 0x8d, 0x5c, 0xc1, 0x3c, 0x25, 0xaa, +/* S */ + 0x54, 0xdd, 0xf6, 0x8f, 0x47, 0x68, 0x84, 0xaf, 0x3e, 0x0e, 0x65, 0x36, + 0xf3, 0xa8, 0x09, 0x25, 0xee, 0x63, 0xa4, 0x02 +}; +#define ac_dsa_vect67_prime ac_dsa_vect61_prime +#define ac_dsa_vect67_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect67_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect67_ptx[] = { +/* Msg */ + 0x01, 0x19, 0x7a, 0xe9, 0x60, 0xde, 0x90, 0xa9, 0x3d, 0x97, 0x36, 0x89, + 0x6f, 0xe1, 0x36, 0xbc, 0x56, 0x1f, 0x05, 0x50, 0xc6, 0xb1, 0xcc, 0x36, + 0x31, 0xb3, 0x1d, 0xf6, 0x83, 0x01, 0x7c, 0x2a, 0xb8, 0xc6, 0xf4, 0x1d, + 0x27, 0x45, 0xf1, 0xa7, 0x97, 0xe0, 0xe8, 0x9d, 0xc3, 0xd5, 0x87, 0x88, + 0x66, 0xc3, 0x69, 0x4a, 0x08, 0x03, 0x66, 0x75, 0x7e, 0x6f, 0xd8, 0x92, + 0xd2, 0x66, 0x68, 0xfd, 0x2d, 0x86, 0x0e, 0xa2, 0xa2, 0xb6, 0x7f, 0xda, + 0xca, 0x96, 0xe3, 0x22, 0x97, 0x75, 0x87, 0x87, 0xec, 0xc0, 0xa7, 0xe1, + 0xd3, 0x04, 0xcc, 0x71, 0x98, 0x03, 0x27, 0x2e, 0x72, 0xe3, 0x39, 0xb3, + 0xf3, 0x4c, 0x34, 0x7e, 0x47, 0xb9, 0x1a, 0x1e, 0xd6, 0x9c, 0xa8, 0x06, + 0x2c, 0xd3, 0x50, 0xdc, 0xcc, 0x9c, 0x22, 0x64, 0x73, 0x2b, 0x9f, 0xdd, + 0x84, 0x62, 0xd9, 0xf6, 0xfc, 0x76, 0x85, 0x0c +}; +static const uint8_t ac_dsa_vect67_priv_val[] = { +/* X */ + 0x45, 0x96, 0x3a, 0x07, 0x71, 0x45, 0x6d, 0x6a, 0xe8, 0x97, 0xed, 0xf7, + 0x57, 0x90, 0x91, 0xf5, 0xf8, 0xc7, 0x67, 0x47 +}; +static const uint8_t ac_dsa_vect67_pub_val[] = { +/* Y */ + 0x37, 0x30, 0x81, 0x77, 0x0a, 0x9f, 0x4d, 0xae, 0x8d, 0xf5, 0xdf, 0xa7, + 0x05, 0x03, 0xe1, 0x49, 0xd7, 0x59, 0xca, 0x37, 0x40, 0x85, 0x49, 0xaa, + 0x34, 0xd1, 0xb4, 0x9b, 0x31, 0x76, 0xa3, 0x9d, 0x7c, 0x46, 0x61, 0xe4, + 0x21, 0xa1, 0xf5, 0xd6, 0x1e, 0x3f, 0x77, 0xb3, 0xc4, 0xb3, 0x9b, 0xb2, + 0xe6, 0x3c, 0xd2, 0x49, 0x19, 0xa2, 0x91, 0x0a, 0x8b, 0x15, 0x5e, 0x17, + 0x58, 0xf5, 0xa3, 0x75, 0xda, 0x60, 0xf1, 0x9d, 0x2b, 0xf4, 0x02, 0x0e, + 0x82, 0x8f, 0x42, 0x37, 0xeb, 0x3e, 0x2a, 0x36, 0x12, 0x4a, 0x6a, 0x39, + 0x14, 0x46, 0x9d, 0x68, 0x33, 0x69, 0x5b, 0x83, 0xb9, 0x37, 0x7f, 0xb2, + 0x85, 0xb2, 0x7b, 0xd2, 0x68, 0x99, 0x33, 0xc1, 0x89, 0xc7, 0xfd, 0xe4, + 0x2e, 0x1e, 0x0e, 0x20, 0x30, 0x83, 0x31, 0xfd, 0x56, 0xed, 0x0d, 0xb2, + 0xef, 0xbc, 0x77, 0xea, 0x3a, 0xc7, 0x12, 0x1f +}; +/* K = 1f68d020331b81fc1aea51907e94f7d62ace9135 */ +static const uint8_t ac_dsa_vect67_out[] = { +/* R */ + 0x41, 0xed, 0x17, 0x0c, 0x8b, 0xf6, 0xf2, 0x0f, 0xd1, 0xce, 0x18, 0xfa, + 0xac, 0x97, 0x56, 0x5f, 0xdb, 0x4f, 0xe6, 0xf4, +/* S */ + 0x7c, 0x8c, 0x6f, 0xea, 0xce, 0x68, 0xc9, 0x7c, 0xa4, 0x37, 0x80, 0x74, + 0x1f, 0xae, 0x58, 0xf2, 0xf6, 0x1b, 0xf7, 0x65 +}; +#define ac_dsa_vect68_prime ac_dsa_vect61_prime +#define ac_dsa_vect68_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect68_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect68_ptx[] = { +/* Msg */ + 0x0d, 0x5a, 0xb2, 0x7b, 0x2b, 0x7e, 0x18, 0xcf, 0xce, 0x4c, 0xcd, 0xa1, + 0x3a, 0xa1, 0xa5, 0xa8, 0xc1, 0x8b, 0xaa, 0xf3, 0x9b, 0x14, 0xe6, 0x42, + 0xb8, 0xf8, 0x1b, 0x30, 0xcd, 0x54, 0x18, 0xa1, 0xdd, 0x05, 0xdf, 0x22, + 0x59, 0x9f, 0xbb, 0xb3, 0xba, 0xe4, 0xfe, 0xe1, 0xe4, 0xb2, 0xc1, 0x50, + 0xa2, 0x3e, 0x21, 0x6c, 0x13, 0x3f, 0xe2, 0xd8, 0x23, 0x54, 0x85, 0xe3, + 0x4f, 0x80, 0x68, 0x5c, 0x66, 0xbc, 0x0c, 0x19, 0x0a, 0xf6, 0x7a, 0x0a, + 0x49, 0x93, 0x0b, 0x47, 0x6b, 0x28, 0x03, 0xe1, 0x22, 0x74, 0xcd, 0x43, + 0x09, 0x09, 0x21, 0xbf, 0x66, 0x8f, 0xdf, 0xef, 0x15, 0x50, 0x72, 0xa3, + 0xcd, 0xf1, 0x79, 0x01, 0x42, 0x7a, 0xfa, 0x51, 0x31, 0x8a, 0xfd, 0xda, + 0x93, 0x7e, 0x28, 0x3e, 0x2c, 0x60, 0xd8, 0x5e, 0x3b, 0xfe, 0x07, 0xf3, + 0xda, 0x5f, 0x99, 0x2c, 0x1f, 0xca, 0x4b, 0x98 +}; +static const uint8_t ac_dsa_vect68_priv_val[] = { +/* X */ + 0x95, 0xbc, 0x58, 0x8b, 0xb8, 0x48, 0x75, 0x1b, 0xa5, 0x7d, 0x7a, 0x9a, + 0xb3, 0x40, 0xcb, 0x00, 0xe7, 0x9e, 0x06, 0xd8 +}; +static const uint8_t ac_dsa_vect68_pub_val[] = { +/* Y */ + 0x1c, 0xa3, 0x6e, 0x35, 0x05, 0xee, 0x70, 0xa5, 0x6a, 0xfd, 0x5d, 0xc4, + 0x0a, 0x48, 0xe9, 0x79, 0x79, 0xe9, 0x84, 0xdd, 0x2d, 0x89, 0x6a, 0xbc, + 0x7a, 0x49, 0x1d, 0x34, 0x61, 0xc6, 0x93, 0x16, 0x68, 0xa0, 0xce, 0xf1, + 0x1e, 0x45, 0xbb, 0x66, 0xc6, 0x11, 0x13, 0x79, 0x99, 0x90, 0x7a, 0xd7, + 0xe1, 0xf7, 0xcf, 0xea, 0x7f, 0x7e, 0xd4, 0x9a, 0xae, 0x93, 0x5b, 0xfc, + 0x41, 0x44, 0x32, 0x93, 0xe7, 0x1d, 0xd2, 0xfe, 0xc2, 0x9f, 0x37, 0xa9, + 0x54, 0x46, 0x72, 0xab, 0x92, 0x50, 0xca, 0xa2, 0x81, 0x88, 0xf3, 0x90, + 0xb5, 0xd4, 0xaf, 0x13, 0xbb, 0x05, 0xe9, 0x69, 0x2c, 0x1c, 0x6a, 0x4d, + 0x6a, 0xaf, 0xeb, 0xdd, 0xaf, 0x7e, 0xef, 0x18, 0x34, 0xff, 0xfe, 0x0f, + 0x53, 0x91, 0xbc, 0xe2, 0x43, 0x78, 0x9a, 0x2d, 0x55, 0xd2, 0x9e, 0x2b, + 0x90, 0xce, 0x12, 0x04, 0x29, 0xf2, 0xa0, 0x75 +}; +/* K = 07a4f8000f0ecddb72302cf4d7975c7efc41c143 */ +static const uint8_t ac_dsa_vect68_out[] = { +/* R */ + 0x66, 0x01, 0x5e, 0x5f, 0xb3, 0xab, 0xe9, 0xd7, 0x85, 0x23, 0x77, 0x0f, + 0x7b, 0xa0, 0x99, 0x00, 0x31, 0x06, 0x5a, 0xd7, +/* S */ + 0x4b, 0x8b, 0x15, 0x3d, 0x5b, 0x01, 0xdd, 0xfa, 0x91, 0xf2, 0xde, 0xc6, + 0xf0, 0xfa, 0xff, 0x02, 0xe6, 0xe8, 0x72, 0x18 +}; +#define ac_dsa_vect69_prime ac_dsa_vect61_prime +#define ac_dsa_vect69_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect69_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect69_ptx[] = { +/* Msg */ + 0x90, 0x6a, 0x93, 0x3b, 0xc8, 0x23, 0xa3, 0x07, 0xe2, 0xab, 0x29, 0xa4, + 0xa8, 0xf7, 0xf1, 0x51, 0x0d, 0x5d, 0x30, 0x35, 0x04, 0xfd, 0xe3, 0x81, + 0x69, 0xde, 0xd1, 0x68, 0x91, 0x3e, 0x3b, 0xf8, 0x1d, 0x53, 0xa4, 0x38, + 0x9a, 0x3e, 0x73, 0xa3, 0xef, 0xeb, 0xd5, 0xe4, 0x2c, 0xf4, 0x02, 0xbf, + 0x9f, 0xdc, 0x5d, 0xa5, 0xef, 0x46, 0x87, 0x81, 0x65, 0xad, 0xa6, 0xd2, + 0xe0, 0x72, 0x99, 0x03, 0x5a, 0x39, 0x87, 0xed, 0x6c, 0x2c, 0x6c, 0x8b, + 0xec, 0xc4, 0x4e, 0xa1, 0x31, 0xa9, 0x49, 0x3e, 0x72, 0xae, 0xe2, 0x82, + 0x42, 0xcf, 0x7c, 0xfa, 0xc3, 0x8e, 0xe8, 0x70, 0xe5, 0x4e, 0xb9, 0x5a, + 0x6e, 0xfa, 0x9f, 0xad, 0x74, 0x35, 0x4b, 0x28, 0x1c, 0xb6, 0x3e, 0xa7, + 0x16, 0x52, 0xeb, 0xa1, 0xad, 0x73, 0xf8, 0x41, 0xdb, 0xa7, 0x77, 0x8f, + 0x3a, 0x03, 0xd3, 0xe0, 0x01, 0x90, 0xed, 0x68 +}; +static const uint8_t ac_dsa_vect69_priv_val[] = { +/* X */ + 0x82, 0x95, 0xed, 0x7e, 0x12, 0x5a, 0x65, 0xea, 0x17, 0x62, 0xaa, 0xaa, + 0xda, 0x34, 0x60, 0x2a, 0x7b, 0xc7, 0x68, 0x45 +}; +static const uint8_t ac_dsa_vect69_pub_val[] = { +/* Y */ + 0x4f, 0x3a, 0xde, 0x3e, 0xa4, 0xf7, 0x06, 0x61, 0x07, 0x32, 0x1e, 0x8b, + 0xfb, 0x12, 0xee, 0xaf, 0x9b, 0x3c, 0x7b, 0xdc, 0xc6, 0x14, 0x79, 0x08, + 0x75, 0x42, 0x31, 0x15, 0x6b, 0x46, 0xe0, 0x63, 0x9c, 0x9d, 0xb9, 0xd5, + 0x44, 0x7a, 0xbd, 0x2d, 0x0a, 0x92, 0x23, 0xc8, 0x5d, 0x63, 0xd8, 0xb1, + 0xdf, 0xa6, 0x97, 0x42, 0xeb, 0xf7, 0xe0, 0x41, 0x9e, 0x60, 0x8c, 0x4b, + 0x18, 0xc3, 0xad, 0x9f, 0x55, 0xf5, 0xd2, 0x84, 0x8e, 0xdb, 0xec, 0x4e, + 0x71, 0x80, 0xe3, 0x4b, 0xfb, 0xb1, 0xf6, 0xb6, 0xeb, 0xbb, 0x68, 0x64, + 0x97, 0x14, 0xb5, 0xfb, 0xfa, 0x6c, 0xfa, 0xb4, 0xa0, 0x1f, 0x65, 0x50, + 0x08, 0xa9, 0x5a, 0x7e, 0xed, 0xcd, 0xc2, 0xf7, 0x17, 0x10, 0x94, 0x56, + 0x3a, 0x3c, 0x18, 0x31, 0xe8, 0x1f, 0x5c, 0xa0, 0x75, 0xc6, 0xe8, 0x53, + 0xbe, 0xea, 0xe8, 0x7a, 0x67, 0xff, 0x90, 0x22 +}; +/* K = 8148e40362a255d240a3e6af746a8880162d78ad */ +static const uint8_t ac_dsa_vect69_out[] = { +/* R */ + 0x99, 0xc9, 0x1e, 0x07, 0x94, 0x72, 0x3b, 0xcd, 0xe3, 0x45, 0x94, 0xdd, + 0x22, 0x68, 0x41, 0x8d, 0xfb, 0x35, 0x34, 0x43, +/* S */ + 0x42, 0xe9, 0xc4, 0x9d, 0x60, 0xad, 0x8f, 0x9b, 0x41, 0xf2, 0x90, 0xae, + 0x6b, 0x77, 0x2f, 0x44, 0xbe, 0x62, 0xce, 0xa9 +}; +#define ac_dsa_vect70_prime ac_dsa_vect61_prime +#define ac_dsa_vect70_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect70_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect70_ptx[] = { +/* Msg */ + 0x1d, 0x6b, 0xa4, 0x3a, 0x0f, 0xf6, 0x77, 0xcf, 0x8c, 0xf6, 0x8d, 0x6a, + 0x1d, 0x33, 0x04, 0xd9, 0x94, 0x90, 0xa7, 0xca, 0xe5, 0x6f, 0xe3, 0x53, + 0x18, 0xf3, 0x8e, 0xd0, 0xf5, 0x87, 0x9f, 0xe2, 0x54, 0x70, 0x3f, 0xa7, + 0x74, 0x58, 0xc4, 0x5e, 0x8a, 0x69, 0x84, 0x69, 0xb8, 0x99, 0xa2, 0x15, + 0xc2, 0x5e, 0x86, 0x9f, 0xd2, 0x87, 0x41, 0x10, 0x1d, 0x27, 0xdc, 0x11, + 0x1f, 0xfa, 0xd6, 0x98, 0x0f, 0x8e, 0xbd, 0x74, 0x8f, 0x69, 0x77, 0xd5, + 0xd6, 0x04, 0x38, 0xe6, 0xed, 0xec, 0x37, 0xa4, 0x9d, 0x30, 0x11, 0xf8, + 0xf0, 0xf0, 0x85, 0x25, 0x15, 0x6a, 0xe6, 0x0b, 0xc9, 0x1a, 0xbe, 0x66, + 0x16, 0x38, 0xf4, 0xb9, 0xc6, 0xc3, 0x65, 0xc3, 0xaf, 0x17, 0x13, 0xbf, + 0x7f, 0x72, 0x25, 0xd4, 0xaf, 0xad, 0x7a, 0x1b, 0x53, 0x1a, 0x33, 0x11, + 0x33, 0xd8, 0xb8, 0xfd, 0x23, 0x85, 0x98, 0xa4 +}; +static const uint8_t ac_dsa_vect70_priv_val[] = { +/* X */ + 0x8d, 0x3c, 0x30, 0x2d, 0xa7, 0xb7, 0x7e, 0xce, 0x9c, 0xe6, 0xe2, 0x80, + 0xe6, 0x03, 0xbd, 0x26, 0x0d, 0x2d, 0xc1, 0x44 +}; +static const uint8_t ac_dsa_vect70_pub_val[] = { +/* Y */ + 0x08, 0xad, 0x77, 0xf2, 0x33, 0x33, 0x4c, 0x04, 0xca, 0x22, 0x82, 0xf6, + 0xda, 0xc0, 0xb0, 0xd8, 0xa0, 0x0d, 0x59, 0x6e, 0x02, 0xe8, 0x36, 0xa7, + 0x67, 0xa1, 0x46, 0xef, 0x80, 0x62, 0x4b, 0x33, 0xfd, 0xba, 0x8b, 0x35, + 0x20, 0x4b, 0x20, 0xbe, 0xe8, 0xff, 0x2b, 0xe9, 0xa8, 0x2b, 0xd8, 0x01, + 0x31, 0xc0, 0xaa, 0x89, 0x8b, 0x17, 0xee, 0xab, 0x5a, 0xf2, 0x4c, 0x20, + 0x55, 0x1d, 0x5d, 0x63, 0x6a, 0x11, 0x54, 0x8f, 0xdd, 0x2e, 0x6c, 0x61, + 0x6b, 0x09, 0xdf, 0x86, 0xb0, 0x57, 0xe5, 0x70, 0x21, 0x46, 0xec, 0xc4, + 0xfa, 0x2d, 0x44, 0xd8, 0x5b, 0xb1, 0x42, 0x7e, 0x7e, 0x35, 0x76, 0xf6, + 0x98, 0xb4, 0xf2, 0x16, 0x45, 0xa1, 0xe0, 0x04, 0x79, 0xd0, 0x89, 0x82, + 0xb0, 0x57, 0x3d, 0xd1, 0x98, 0x1b, 0xbd, 0x40, 0x5c, 0x2a, 0x45, 0xd7, + 0xde, 0x92, 0x42, 0xaf, 0xae, 0x8f, 0x95, 0xc9 +}; +/* K = 79989e8eb43520091706039415794d2306329861 */ +static const uint8_t ac_dsa_vect70_out[] = { +/* R */ + 0xa2, 0xb4, 0x2c, 0xca, 0x55, 0xbc, 0x1b, 0xa3, 0x3f, 0x82, 0x52, 0xd1, + 0xa8, 0x9c, 0x8d, 0x89, 0xb0, 0x0b, 0x39, 0x50, +/* S */ + 0x2e, 0xc5, 0x16, 0x6e, 0x35, 0xe6, 0x3f, 0x0f, 0xa1, 0x16, 0xb3, 0xdb, + 0x1b, 0xd1, 0x86, 0x81, 0xa4, 0x39, 0x9c, 0x04 +}; +#define ac_dsa_vect71_prime ac_dsa_vect61_prime +#define ac_dsa_vect71_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect71_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect71_ptx[] = { +/* Msg */ + 0x3b, 0xd0, 0xc5, 0xb7, 0x59, 0xcb, 0x71, 0x0c, 0x52, 0xb8, 0x1f, 0xba, + 0x48, 0xb6, 0x77, 0x1c, 0xab, 0x17, 0xbf, 0x1b, 0x67, 0xea, 0xfd, 0x08, + 0xf4, 0xee, 0x17, 0x77, 0xdd, 0x47, 0x30, 0x64, 0xdd, 0x0b, 0xec, 0x98, + 0xd3, 0x58, 0x2e, 0xe1, 0xe9, 0x91, 0xab, 0x9a, 0x91, 0xa6, 0xfe, 0x55, + 0x8a, 0x41, 0xdb, 0x9a, 0xe6, 0xb2, 0x1a, 0x05, 0x79, 0x32, 0x81, 0x14, + 0x40, 0xd6, 0x4c, 0x78, 0x6b, 0x22, 0xd1, 0x50, 0xe3, 0xd3, 0x8c, 0x71, + 0x90, 0x0a, 0xd5, 0xb6, 0x1e, 0x05, 0x30, 0x74, 0x4e, 0x76, 0x5b, 0x5c, + 0x2e, 0xf3, 0x0b, 0xcb, 0x96, 0xe7, 0x26, 0xe3, 0x07, 0x9e, 0x44, 0x00, + 0x86, 0xef, 0x30, 0x0b, 0xae, 0x90, 0x00, 0xdf, 0x34, 0x03, 0xc3, 0x3a, + 0x79, 0x84, 0x9f, 0x8f, 0x83, 0xd6, 0xc0, 0x3f, 0x77, 0xea, 0xe9, 0x80, + 0x52, 0x57, 0x8d, 0x82, 0xd6, 0x28, 0xe6, 0x5c +}; +static const uint8_t ac_dsa_vect71_priv_val[] = { +/* X */ + 0x4d, 0x3e, 0x42, 0xef, 0x42, 0xa6, 0x06, 0x30, 0xed, 0xcc, 0x84, 0x2f, + 0x25, 0xa1, 0xb3, 0x3c, 0x88, 0x51, 0xc7, 0x42 +}; +static const uint8_t ac_dsa_vect71_pub_val[] = { +/* Y */ + 0x3a, 0x1e, 0xd9, 0x76, 0xb7, 0x93, 0x4b, 0xee, 0x3e, 0x80, 0xd6, 0x9f, + 0xbc, 0xdd, 0x35, 0xf8, 0x20, 0x51, 0xcc, 0xc2, 0x14, 0xbd, 0xe6, 0xfa, + 0x75, 0x6b, 0xe6, 0x70, 0x17, 0xff, 0x60, 0xac, 0x68, 0x47, 0xcf, 0x8d, + 0x1f, 0x82, 0x3f, 0x89, 0x0d, 0x26, 0xaf, 0x8c, 0xd3, 0x51, 0x71, 0x6a, + 0xd2, 0xd4, 0xee, 0xfd, 0x7f, 0x06, 0xc1, 0x95, 0x1e, 0xa4, 0xa7, 0xdb, + 0x5c, 0xaf, 0x25, 0x0f, 0x40, 0x7b, 0x78, 0xf2, 0x1f, 0xff, 0x42, 0x5d, + 0x0c, 0xba, 0x1b, 0x5f, 0xb3, 0x5a, 0x5b, 0x5d, 0xcf, 0x06, 0x2a, 0x1c, + 0xdf, 0x25, 0x07, 0xaf, 0x74, 0x78, 0x93, 0x26, 0x71, 0x0e, 0x33, 0x4f, + 0xaf, 0x3c, 0x50, 0x1b, 0xd8, 0xc8, 0x34, 0x72, 0x25, 0xf9, 0x4f, 0x89, + 0x73, 0xad, 0xb7, 0xa8, 0xb5, 0xde, 0xf9, 0x89, 0x61, 0x09, 0xd1, 0xef, + 0xe5, 0x50, 0x32, 0x5d, 0xd8, 0x9f, 0x31, 0xd6 +}; +/* K = 6c59f3cec7e34db174dcbd6bfe224d52226c56cd */ +static const uint8_t ac_dsa_vect71_out[] = { +/* R */ + 0x77, 0xd6, 0x2e, 0xc2, 0xa9, 0x5b, 0xeb, 0xa6, 0xc6, 0x72, 0xd8, 0x42, + 0x2e, 0xe6, 0x63, 0xd1, 0xd1, 0x80, 0x49, 0xd0, +/* S */ + 0x2a, 0x33, 0x9c, 0xc8, 0xf5, 0x67, 0xc1, 0x21, 0x49, 0xa8, 0x91, 0x73, + 0x75, 0xec, 0x6c, 0xa4, 0xb4, 0x72, 0x54, 0xa1 +}; +#define ac_dsa_vect72_prime ac_dsa_vect61_prime +#define ac_dsa_vect72_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect72_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect72_ptx[] = { +/* Msg */ + 0x8d, 0xc5, 0x82, 0xa2, 0xb5, 0xaf, 0x65, 0xe6, 0x6e, 0xbd, 0xf5, 0xb5, + 0x33, 0xd8, 0xe2, 0x2b, 0x38, 0xb5, 0xc1, 0x97, 0x7e, 0x57, 0x8d, 0x32, + 0x13, 0xa1, 0x10, 0xe9, 0xd4, 0x83, 0x7a, 0x74, 0xd4, 0xb7, 0xbf, 0x7d, + 0x71, 0x87, 0x56, 0x90, 0xb5, 0xb7, 0x1c, 0x8e, 0x8a, 0xfa, 0xb8, 0x94, + 0x34, 0xc4, 0x6a, 0x86, 0x41, 0xcc, 0xed, 0x1a, 0x13, 0x0e, 0x21, 0xcd, + 0x0c, 0x80, 0x5e, 0xe4, 0x5c, 0x13, 0x4c, 0x7c, 0x0d, 0xf7, 0x5d, 0x5c, + 0xd3, 0x0c, 0x41, 0x81, 0x8f, 0x7a, 0xe4, 0x75, 0xdd, 0x60, 0x22, 0x87, + 0x7c, 0x74, 0x3d, 0x09, 0xd5, 0x4f, 0x0c, 0x94, 0x58, 0x1a, 0xe7, 0xbd, + 0x4b, 0x42, 0x3f, 0x02, 0xe1, 0x93, 0x97, 0xbe, 0x7b, 0xd4, 0xa9, 0x04, + 0xb8, 0x8c, 0xbd, 0x2f, 0x81, 0x4b, 0x1d, 0xff, 0x1e, 0x79, 0x6d, 0x9f, + 0x2d, 0x1c, 0x84, 0x70, 0xb7, 0x96, 0xc6, 0x9a +}; +static const uint8_t ac_dsa_vect72_priv_val[] = { +/* X */ + 0x6a, 0x6a, 0x98, 0x74, 0xf0, 0xf8, 0x9f, 0x04, 0xcb, 0xea, 0xeb, 0xde, + 0x38, 0x33, 0xae, 0x17, 0x9a, 0xde, 0x3f, 0x5a +}; +static const uint8_t ac_dsa_vect72_pub_val[] = { +/* Y */ + 0x5d, 0x6d, 0xc1, 0x74, 0x9f, 0x28, 0xcb, 0x8f, 0x7c, 0x01, 0x4d, 0x5c, + 0x55, 0x16, 0xcf, 0x5b, 0xc2, 0x22, 0xc6, 0xd9, 0x33, 0x7a, 0xc0, 0x08, + 0x9b, 0x19, 0xb9, 0x0b, 0x32, 0x19, 0x56, 0xcf, 0x61, 0x92, 0xf3, 0x25, + 0x5d, 0x0e, 0xec, 0x45, 0x84, 0x08, 0x10, 0xc2, 0x1f, 0xe9, 0x1c, 0xf5, + 0x30, 0x89, 0x48, 0x85, 0x2a, 0x57, 0xcd, 0x01, 0x89, 0xf1, 0x5b, 0xd9, + 0x6a, 0xf8, 0x38, 0x0d, 0x19, 0xcb, 0x82, 0x1b, 0x1c, 0x56, 0xaf, 0xdc, + 0x38, 0xa9, 0x4b, 0x2c, 0x32, 0xfe, 0xb1, 0x82, 0x13, 0x93, 0x96, 0x93, + 0xb6, 0x9f, 0x2b, 0xcb, 0xae, 0x7e, 0x70, 0xab, 0x09, 0xea, 0xd3, 0xb6, + 0xa8, 0xb7, 0xda, 0xd3, 0xc4, 0xf5, 0x21, 0xad, 0x04, 0x55, 0xdd, 0x4e, + 0x87, 0x2b, 0x36, 0x27, 0xd4, 0xfe, 0xd2, 0x0d, 0x5e, 0xfc, 0x78, 0xf6, + 0xae, 0x46, 0x7f, 0xb9, 0x26, 0x7a, 0xb1, 0xd4 +}; +/* K = 27b2661922214411aec66e58cb36142ab3e5a256 */ +static const uint8_t ac_dsa_vect72_out[] = { +/* R */ + 0x05, 0x36, 0x3b, 0xcc, 0xa1, 0x93, 0xd7, 0x26, 0xcd, 0x20, 0xe0, 0x34, + 0x89, 0xe1, 0xb1, 0x3b, 0x7d, 0xf3, 0xbc, 0x98, +/* S */ + 0x31, 0xbd, 0xac, 0xcb, 0x29, 0xe4, 0xa6, 0x00, 0x23, 0x92, 0x9f, 0x18, + 0x21, 0x99, 0xc0, 0x70, 0xb7, 0x1a, 0xc5, 0x75 +}; +#define ac_dsa_vect73_prime ac_dsa_vect61_prime +#define ac_dsa_vect73_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect73_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect73_ptx[] = { +/* Msg */ + 0x47, 0x7a, 0xf8, 0xc0, 0x25, 0x18, 0x1b, 0x55, 0x77, 0x32, 0xb9, 0x56, + 0x86, 0x34, 0xb1, 0x32, 0x4e, 0x66, 0x69, 0xb4, 0xc2, 0x8a, 0x0b, 0xcd, + 0x4c, 0x65, 0x3d, 0x4c, 0x81, 0xed, 0x68, 0xb2, 0xa2, 0x04, 0x3a, 0x80, + 0x0a, 0x31, 0x4b, 0xa9, 0x5e, 0x50, 0xde, 0xea, 0xcc, 0x5e, 0xe9, 0xc2, + 0xba, 0x6f, 0x6f, 0x62, 0xfd, 0xba, 0x0e, 0x86, 0xac, 0xa2, 0x27, 0xd7, + 0x27, 0x37, 0x75, 0x52, 0xa3, 0xab, 0xdb, 0xab, 0x60, 0x1c, 0x26, 0x01, + 0x84, 0x6e, 0xc2, 0x7a, 0x19, 0x2a, 0x3f, 0x33, 0xe7, 0xff, 0xdb, 0xe4, + 0xa4, 0xaa, 0x7b, 0xeb, 0x2b, 0x3f, 0xf6, 0xc9, 0x1b, 0xd5, 0xcd, 0x5c, + 0x89, 0x0b, 0xcb, 0x6f, 0x4c, 0x90, 0x8f, 0xf5, 0xb9, 0xb5, 0x55, 0xe2, + 0xa0, 0xa7, 0xdf, 0x8c, 0x3e, 0xf6, 0x77, 0x01, 0x36, 0xbb, 0xf0, 0x09, + 0x75, 0x5b, 0xf6, 0xc3, 0xe6, 0x30, 0x73, 0x10 +}; +static const uint8_t ac_dsa_vect73_priv_val[] = { +/* X */ + 0x17, 0x94, 0x9e, 0x83, 0x8d, 0x7c, 0x93, 0xe1, 0xd8, 0x37, 0xbe, 0x65, + 0xb3, 0xc4, 0x48, 0x24, 0x33, 0xa1, 0xb2, 0x08 +}; +static const uint8_t ac_dsa_vect73_pub_val[] = { +/* Y */ + 0x2c, 0xce, 0xdd, 0xc9, 0xe2, 0xce, 0xbb, 0xc1, 0xe9, 0x9b, 0x83, 0xb0, + 0x30, 0x53, 0xbb, 0x14, 0xa9, 0xcf, 0xaf, 0x07, 0x2b, 0x45, 0xe4, 0x74, + 0x6d, 0x18, 0xcb, 0x39, 0x01, 0xf6, 0xa2, 0xc3, 0xcf, 0x72, 0xda, 0x66, + 0xb0, 0xb9, 0xb3, 0xe1, 0x05, 0xbd, 0x4c, 0xd0, 0xe5, 0x42, 0x7d, 0x7e, + 0x9b, 0x65, 0x7e, 0xd7, 0x18, 0x84, 0xcd, 0x49, 0xf5, 0x1f, 0xe8, 0xfa, + 0x18, 0xa3, 0x66, 0x01, 0x8a, 0x3e, 0xaf, 0xac, 0x33, 0x81, 0xe0, 0x7a, + 0x5b, 0x19, 0xf6, 0xd3, 0x86, 0x2e, 0xd2, 0x91, 0x60, 0x94, 0x90, 0x6e, + 0x75, 0x28, 0x6e, 0xaf, 0x1d, 0x13, 0xc4, 0x85, 0x74, 0x4b, 0x27, 0x04, + 0x04, 0xff, 0x9a, 0xdc, 0x8e, 0x17, 0x78, 0x33, 0x04, 0x3b, 0xdc, 0x34, + 0xc3, 0x07, 0xe6, 0xfc, 0x9c, 0x55, 0xc5, 0x3d, 0x8f, 0xf8, 0x4a, 0x6e, + 0x25, 0x10, 0x38, 0xdb, 0xeb, 0x5e, 0xf7, 0x74 +}; +/* K = 620f07d7e7ced030e669685ab8c39174d88c79eb */ +static const uint8_t ac_dsa_vect73_out[] = { +/* R */ + 0x35, 0x91, 0xc5, 0x21, 0xb2, 0xa5, 0x6c, 0xf4, 0x60, 0x51, 0xc0, 0xcb, + 0x3d, 0x44, 0x4b, 0x9a, 0x22, 0xff, 0xf6, 0x3f, +/* S */ + 0x7a, 0xc7, 0x8e, 0xe2, 0x52, 0x44, 0x0c, 0xf9, 0xe8, 0x51, 0x04, 0x94, + 0xd1, 0xfa, 0xd8, 0xb5, 0x18, 0xf1, 0xe1, 0x28 +}; +#define ac_dsa_vect74_prime ac_dsa_vect61_prime +#define ac_dsa_vect74_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect74_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect74_ptx[] = { +/* Msg */ + 0xbb, 0x65, 0x93, 0xff, 0x21, 0x9c, 0x9f, 0x20, 0xaa, 0x47, 0xe1, 0xe1, + 0x57, 0xe8, 0x8e, 0xd5, 0x9a, 0xe2, 0x9c, 0x89, 0x40, 0xa5, 0x27, 0xc8, + 0x2e, 0x0e, 0x0f, 0x2e, 0x85, 0x5f, 0xa9, 0x8e, 0x94, 0xe0, 0x7b, 0xe1, + 0xf6, 0xbc, 0xe3, 0x83, 0x2b, 0x7e, 0xa1, 0xe6, 0x0a, 0x5c, 0x9e, 0xf5, + 0x83, 0xf2, 0xec, 0x7b, 0x17, 0x92, 0x27, 0xe4, 0xaf, 0xdc, 0xf8, 0x29, + 0xd6, 0x73, 0xe1, 0x37, 0x7f, 0x83, 0x2a, 0xe3, 0x8e, 0x7c, 0xad, 0xed, + 0xe4, 0x15, 0x96, 0x4f, 0x12, 0xba, 0xf7, 0x75, 0xd3, 0x8c, 0xe3, 0x8e, + 0x94, 0x55, 0x63, 0xe7, 0x28, 0x61, 0x51, 0x91, 0x97, 0xc2, 0xd0, 0x8f, + 0x28, 0xd8, 0xb6, 0x46, 0x65, 0x62, 0xe0, 0x59, 0xec, 0x41, 0x74, 0x1d, + 0xe3, 0x49, 0xed, 0x5d, 0xe2, 0xc7, 0xd6, 0xcc, 0x75, 0x18, 0xa8, 0x77, + 0x20, 0xa2, 0x48, 0xb3, 0x01, 0x73, 0x3a, 0x47 +}; +static const uint8_t ac_dsa_vect74_priv_val[] = { +/* X */ + 0x30, 0x1c, 0x11, 0xa3, 0x4e, 0xdc, 0xe1, 0xf7, 0xab, 0x04, 0x07, 0x54, + 0xe0, 0xb2, 0xd4, 0xfd, 0x88, 0x57, 0x21, 0x87 +}; +static const uint8_t ac_dsa_vect74_pub_val[] = { +/* Y */ + 0x15, 0xd9, 0xe2, 0x0c, 0x3f, 0x39, 0xcc, 0x9e, 0x3b, 0x8f, 0xb6, 0x5f, + 0xeb, 0x64, 0xfb, 0x15, 0x68, 0xf6, 0xef, 0xde, 0xf6, 0x45, 0x7d, 0x23, + 0x1c, 0x49, 0x1e, 0xd5, 0x17, 0x31, 0xd5, 0x8f, 0x06, 0xe4, 0x5e, 0xa5, + 0xd6, 0x65, 0xd0, 0x49, 0x69, 0x82, 0x3d, 0xa4, 0xe6, 0x75, 0x0a, 0x2c, + 0x3d, 0x16, 0xc5, 0xff, 0x60, 0x80, 0xec, 0xd0, 0x9a, 0xa3, 0x9c, 0x00, + 0x6e, 0xed, 0xce, 0xb4, 0xdb, 0xc1, 0x6e, 0xbd, 0x64, 0xbc, 0x5b, 0x1e, + 0x44, 0xb8, 0x31, 0xa6, 0xbb, 0x25, 0xaf, 0xbc, 0xb3, 0x00, 0x0f, 0xa6, + 0xb6, 0xc2, 0x00, 0x08, 0x60, 0x01, 0x40, 0x11, 0x18, 0x9c, 0x22, 0x54, + 0x2c, 0x14, 0x5e, 0x40, 0x7e, 0x7b, 0x59, 0xf6, 0xd3, 0xfb, 0x1e, 0x13, + 0x62, 0x95, 0xec, 0x85, 0x0b, 0x14, 0xff, 0x2f, 0x49, 0x94, 0xea, 0x37, + 0x48, 0x1e, 0x80, 0x19, 0x99, 0x10, 0xbe, 0x8e +}; +/* K = 117e12f88d6e44fc7f4d51d5384fc31b2e3419a2 */ +static const uint8_t ac_dsa_vect74_out[] = { +/* R */ + 0x61, 0xe7, 0x27, 0x71, 0x6c, 0xc9, 0x69, 0x14, 0x50, 0x97, 0x40, 0xa7, + 0xcb, 0xa6, 0xe7, 0x4a, 0x9d, 0xec, 0x64, 0x06, +/* S */ + 0x2e, 0x77, 0xc1, 0x4f, 0x01, 0xf2, 0x21, 0x80, 0xbc, 0xda, 0x57, 0x25, + 0xcf, 0x0e, 0xaa, 0xc9, 0xad, 0x13, 0xa7, 0xd1 +}; +#define ac_dsa_vect75_prime ac_dsa_vect61_prime +#define ac_dsa_vect75_sub_prime ac_dsa_vect61_sub_prime +#define ac_dsa_vect75_base ac_dsa_vect61_base +static const uint8_t ac_dsa_vect75_ptx[] = { +/* Msg */ + 0x56, 0x5f, 0x19, 0x24, 0x44, 0x68, 0x51, 0x5e, 0x84, 0x63, 0xd0, 0x7b, + 0x42, 0x5b, 0x4d, 0x5f, 0x81, 0xff, 0x2e, 0xfa, 0xb5, 0x15, 0x6b, 0xa1, + 0x9a, 0x63, 0x73, 0x42, 0x19, 0xc2, 0x26, 0xcc, 0xca, 0x59, 0x03, 0xbf, + 0x9c, 0x35, 0xdb, 0xca, 0x09, 0x61, 0xdb, 0x7c, 0x2e, 0x3f, 0x69, 0x44, + 0xd0, 0x57, 0xed, 0xfa, 0x6c, 0x23, 0x94, 0xc3, 0x9a, 0x00, 0xf1, 0xc4, + 0x25, 0x96, 0xe7, 0xee, 0x72, 0xed, 0x64, 0x4c, 0x6a, 0x18, 0x21, 0x15, + 0xbd, 0xc4, 0x4b, 0x90, 0x10, 0xc8, 0x6e, 0x7b, 0x0e, 0xc2, 0xe3, 0xbd, + 0xf7, 0x01, 0x6c, 0x5e, 0x04, 0xf4, 0x55, 0xb4, 0xcb, 0x69, 0x3e, 0x32, + 0x49, 0x0b, 0x8f, 0x49, 0x4b, 0xb4, 0x10, 0x3b, 0x3b, 0x5e, 0xa6, 0x80, + 0x82, 0x22, 0x45, 0x28, 0x41, 0xb7, 0x33, 0xfa, 0xf7, 0x35, 0xf1, 0x0a, + 0x95, 0xfb, 0x28, 0x3d, 0xd8, 0x6c, 0xe5, 0x93 +}; +static const uint8_t ac_dsa_vect75_priv_val[] = { +/* X */ + 0x07, 0xdf, 0xca, 0x41, 0x44, 0x6b, 0x2f, 0x4e, 0x1a, 0xf2, 0xa6, 0x7b, + 0xc8, 0x46, 0x8d, 0xb9, 0xa9, 0xc2, 0xdf, 0xe0 +}; +static const uint8_t ac_dsa_vect75_pub_val[] = { +/* Y */ + 0x66, 0x42, 0x45, 0xaa, 0xeb, 0xcf, 0x5c, 0x05, 0x5c, 0x32, 0x10, 0x9b, + 0x21, 0x59, 0xa1, 0x74, 0x73, 0x04, 0x30, 0x87, 0x91, 0x5f, 0x14, 0xe9, + 0x59, 0xdd, 0xdc, 0x0c, 0x9b, 0x20, 0xc7, 0x26, 0xf0, 0x12, 0x4f, 0x1e, + 0xcb, 0xaf, 0x20, 0x2f, 0xe2, 0x67, 0x6a, 0xfd, 0xab, 0xd3, 0x46, 0xa7, + 0xb5, 0xbe, 0xf7, 0x69, 0xa2, 0x5c, 0x6f, 0x73, 0x36, 0x12, 0xd7, 0x37, + 0x8d, 0xf1, 0xb2, 0xd4, 0xc5, 0x18, 0xa2, 0xda, 0x5b, 0x3a, 0x4c, 0xd0, + 0x25, 0x2b, 0xb8, 0x18, 0x08, 0x38, 0xa4, 0x63, 0x89, 0xa8, 0x46, 0x93, + 0xbe, 0x8c, 0xc2, 0x4f, 0xbd, 0xc6, 0x39, 0xb6, 0x2c, 0xb2, 0x1d, 0x8a, + 0xbe, 0x12, 0x72, 0xb5, 0xaa, 0x06, 0x22, 0x2f, 0xe2, 0x13, 0x3f, 0xc5, + 0x55, 0x6d, 0x24, 0xe7, 0x54, 0x96, 0xa5, 0x3e, 0x19, 0x34, 0xd3, 0xb5, + 0x84, 0x8e, 0x51, 0x0b, 0x69, 0xda, 0x04, 0xa4 +}; +/* K = 4522d27cd17a6ee739873d69f107d872ed7e2db5 */ +static const uint8_t ac_dsa_vect75_out[] = { +/* R */ + 0x5c, 0xa0, 0x7b, 0xc7, 0xcd, 0x9f, 0x7a, 0x60, 0xcf, 0x79, 0x39, 0x1d, + 0x87, 0x3b, 0x6f, 0xdd, 0xf5, 0xa4, 0x8c, 0xca, +/* S */ + 0x97, 0x99, 0xc7, 0x4a, 0x80, 0x6f, 0xc1, 0x96, 0xe0, 0x22, 0x3f, 0xb1, + 0xa6, 0x13, 0xfd, 0x17, 0x8c, 0xaf, 0xbd, 0x99 +}; +/* [mod = L=2048, N=224, SHA-1] */ +static const uint8_t ac_dsa_vect76_prime[] = { +/* P */ + 0xf2, 0xd3, 0x9e, 0xd3, 0x06, 0x2b, 0x13, 0xc9, 0x16, 0x27, 0x36, 0x00, + 0xa0, 0xf2, 0xa0, 0x29, 0xe8, 0x6d, 0x7a, 0x4b, 0x92, 0x17, 0xb4, 0xf1, + 0x81, 0x5b, 0xf2, 0xb2, 0x4d, 0x97, 0x10, 0xa5, 0x7a, 0xb3, 0x3f, 0x99, + 0x72, 0x94, 0xb0, 0x14, 0x58, 0x5b, 0x8d, 0x01, 0x98, 0xdf, 0xdc, 0xcb, + 0xcd, 0x75, 0x31, 0x4d, 0xa5, 0xff, 0x85, 0xaa, 0x34, 0x4b, 0x45, 0xad, + 0xae, 0xaa, 0x97, 0x9b, 0x51, 0xa3, 0x12, 0xa7, 0xbf, 0xa9, 0x44, 0x72, + 0xfb, 0x63, 0x3f, 0x1a, 0x6f, 0x15, 0x6b, 0xb4, 0x45, 0x88, 0x67, 0xdf, + 0xd3, 0x84, 0x03, 0xf0, 0x6b, 0x85, 0x1f, 0x00, 0xfe, 0x2d, 0x34, 0x84, + 0x07, 0x7b, 0xde, 0xd7, 0x1a, 0xb7, 0x51, 0x3d, 0x04, 0xa1, 0x40, 0x22, + 0x05, 0x75, 0xfb, 0x69, 0x33, 0x95, 0x48, 0x0e, 0x4c, 0x84, 0x02, 0xb7, + 0xa4, 0x6c, 0xec, 0x2d, 0x37, 0xa7, 0x78, 0xc3, 0x05, 0xac, 0xcd, 0x1f, + 0x13, 0xe9, 0xf6, 0x2e, 0x86, 0x53, 0x15, 0xf4, 0xb2, 0x2c, 0xc4, 0x67, + 0xc8, 0x98, 0x6e, 0xc8, 0xe4, 0x96, 0x1d, 0xdf, 0x81, 0x05, 0x66, 0xb0, + 0xc4, 0xee, 0x36, 0x9a, 0xc6, 0xaa, 0x15, 0xe4, 0x3f, 0x47, 0x44, 0x00, + 0x58, 0x26, 0xf5, 0xbd, 0xe8, 0x07, 0x1a, 0x19, 0xe3, 0x0b, 0x69, 0x09, + 0xaa, 0xc4, 0xb3, 0xd1, 0x74, 0x23, 0x72, 0x70, 0xda, 0xd0, 0x27, 0x99, + 0xd0, 0x9b, 0x8a, 0x2c, 0xc5, 0xf2, 0x2e, 0x66, 0x89, 0x4b, 0x54, 0x22, + 0x22, 0x8b, 0x2c, 0x23, 0x4f, 0x11, 0xf5, 0xa7, 0x71, 0xc5, 0xb8, 0x9c, + 0xf4, 0x65, 0xa2, 0xac, 0xec, 0xbb, 0xee, 0xaa, 0x17, 0x25, 0xfe, 0x8f, + 0x9b, 0x59, 0x42, 0x2b, 0xe8, 0x99, 0x10, 0x52, 0xcb, 0x55, 0x6d, 0xdf, + 0x2c, 0x8c, 0xe8, 0xfa, 0x92, 0x06, 0xdb, 0xf3, 0x9f, 0xea, 0xdc, 0x19, + 0x4e, 0x00, 0xf8, 0xe5 +}; +static const uint8_t ac_dsa_vect76_sub_prime[] = { +/* Q */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x18, 0xf4, 0x98, + 0x35, 0xe4, 0xef, 0x73, 0x3c, 0x4d, 0x15, 0x80, 0x0f, 0xcf, 0x05, 0x9e, + 0x88, 0x4d, 0x31, 0xb1 +}; +static const uint8_t ac_dsa_vect76_base[] = { +/* G */ + 0xe3, 0xa9, 0x3c, 0x09, 0xda, 0x6f, 0x56, 0x0e, 0x4d, 0x48, 0x3a, 0x38, + 0x2a, 0x4c, 0x54, 0x6f, 0x23, 0x35, 0xc3, 0x6a, 0x4c, 0x35, 0xac, 0x14, + 0x63, 0xc0, 0x8a, 0x3e, 0x6d, 0xd4, 0x15, 0xdf, 0x56, 0xfd, 0xc5, 0x37, + 0xf2, 0x5f, 0xd5, 0x37, 0x2b, 0xe6, 0x3e, 0x4f, 0x53, 0x00, 0x78, 0x0b, + 0x78, 0x2f, 0x1a, 0xcd, 0x01, 0xc8, 0xb4, 0xeb, 0x33, 0x41, 0x46, 0x15, + 0xfd, 0x0e, 0xa8, 0x25, 0x73, 0xac, 0xba, 0x7e, 0xf8, 0x3f, 0x5a, 0x94, + 0x38, 0x54, 0x15, 0x1a, 0xfc, 0x2d, 0x7d, 0xfe, 0x12, 0x1f, 0xb8, 0xcd, + 0x03, 0x33, 0x5b, 0x06, 0x5b, 0x54, 0x9c, 0x5d, 0xcc, 0x60, 0x6b, 0xe9, + 0x05, 0x24, 0x83, 0xbc, 0x28, 0x4e, 0x12, 0xac, 0x3c, 0x8d, 0xba, 0x09, + 0xb4, 0x26, 0xe0, 0x84, 0x02, 0x03, 0x0e, 0x70, 0xbc, 0x1c, 0xc2, 0xbf, + 0x89, 0x57, 0xc4, 0xba, 0x06, 0x30, 0xf3, 0xf3, 0x2a, 0xd6, 0x89, 0x38, + 0x9a, 0xc4, 0x74, 0x43, 0x17, 0x60, 0x63, 0xf2, 0x47, 0xd9, 0xe2, 0x29, + 0x6b, 0x3e, 0xa5, 0xb5, 0xbc, 0x23, 0x35, 0x82, 0x8e, 0xa1, 0xa0, 0x80, + 0xed, 0x35, 0x91, 0x8d, 0xee, 0x21, 0x2f, 0xd0, 0x31, 0x27, 0x9d, 0x1b, + 0x89, 0x4f, 0x01, 0xaf, 0xec, 0x52, 0x38, 0x33, 0x66, 0x9e, 0xac, 0x03, + 0x1a, 0x42, 0x0e, 0x54, 0x0b, 0xa1, 0x32, 0x0a, 0x59, 0xc4, 0x24, 0xa3, + 0xe5, 0x84, 0x9a, 0x46, 0x0a, 0x56, 0xbc, 0xb0, 0x01, 0x64, 0x78, 0x85, + 0xb1, 0x43, 0x3c, 0x4f, 0x99, 0x29, 0x71, 0x74, 0x6b, 0xfe, 0x29, 0x77, + 0xce, 0x72, 0x59, 0xc5, 0x50, 0xb5, 0x51, 0xa6, 0xc3, 0x57, 0x61, 0xe4, + 0xa4, 0x1a, 0xf7, 0x64, 0xe8, 0xd9, 0x21, 0x32, 0xfc, 0xc0, 0xa5, 0x9d, + 0x16, 0x84, 0xea, 0xb9, 0x0d, 0x86, 0x3f, 0x29, 0xf4, 0x1c, 0xf7, 0x57, + 0x8f, 0xaa, 0x90, 0x8c +}; +static const uint8_t ac_dsa_vect76_ptx[] = { +/* Msg */ + 0xed, 0xc6, 0xfd, 0x9b, 0x6c, 0x6e, 0x8a, 0x59, 0xf2, 0x83, 0x01, 0x6f, + 0x7f, 0x29, 0xee, 0x16, 0xde, 0xea, 0xa6, 0x09, 0xb5, 0x73, 0x79, 0x27, + 0x16, 0x2a, 0xef, 0x34, 0xfe, 0xd9, 0x85, 0xd0, 0xbc, 0xb5, 0x50, 0x27, + 0x56, 0x37, 0xba, 0x67, 0x83, 0x1a, 0x2d, 0x4e, 0xfc, 0xcb, 0x35, 0x29, + 0x6d, 0xfe, 0x73, 0x0f, 0x4a, 0x0b, 0x4f, 0x47, 0x28, 0xd1, 0xd7, 0xd1, + 0xbb, 0x8f, 0x4a, 0x36, 0x23, 0x8a, 0x5c, 0x94, 0x31, 0x1f, 0xa1, 0x13, + 0x4a, 0x93, 0xa6, 0xb4, 0xde, 0x39, 0xc0, 0x85, 0xe9, 0xf6, 0x0a, 0xe4, + 0xe2, 0x37, 0xc0, 0x41, 0x6d, 0x58, 0x04, 0x2b, 0xb3, 0x6b, 0xaa, 0x38, + 0xcb, 0xa8, 0xc8, 0x96, 0x29, 0x5b, 0x74, 0x5d, 0x53, 0x76, 0xfd, 0x8c, + 0xe4, 0x2e, 0xb6, 0xee, 0x5a, 0x1b, 0x38, 0xf8, 0x77, 0x16, 0xb2, 0x65, + 0xb7, 0x6e, 0x58, 0xcf, 0xb2, 0x4a, 0x91, 0x70 +}; +static const uint8_t ac_dsa_vect76_priv_val[] = { +/* X */ + 0x61, 0x32, 0xe5, 0x51, 0xcd, 0xac, 0x88, 0x40, 0x91, 0x83, 0xbd, 0x37, + 0xee, 0x14, 0x52, 0xcd, 0x24, 0x7d, 0x48, 0x34, 0xb0, 0x88, 0x14, 0xb2, + 0x75, 0xbe, 0x3f, 0xf5 +}; +static const uint8_t ac_dsa_vect76_pub_val[] = { +/* Y */ + 0x28, 0x9f, 0xf1, 0x8c, 0x32, 0xa5, 0x6b, 0xb0, 0xb8, 0x83, 0x93, 0x70, + 0x64, 0x76, 0x83, 0xa3, 0x8a, 0x5a, 0x7e, 0x29, 0x14, 0x10, 0xb9, 0x32, + 0x07, 0x21, 0x2a, 0xdc, 0x80, 0x88, 0xd3, 0x0f, 0x93, 0xe9, 0xe4, 0xab, + 0xc5, 0x23, 0xf3, 0xd4, 0x69, 0x36, 0xe7, 0xd5, 0xc9, 0x0d, 0x88, 0x74, + 0x2b, 0x36, 0xaf, 0xd3, 0x75, 0x63, 0x40, 0x8f, 0x15, 0xc8, 0xc1, 0xa4, + 0xf7, 0xac, 0x24, 0xbf, 0x05, 0xf0, 0x10, 0x08, 0xff, 0xee, 0x70, 0xc8, + 0x82, 0x5d, 0x57, 0xc3, 0xa9, 0x30, 0x8b, 0xad, 0x8a, 0x09, 0x5a, 0xf2, + 0xb5, 0x3b, 0x2d, 0xda, 0x3c, 0xbe, 0xd8, 0x46, 0xd9, 0x5e, 0x30, 0x1e, + 0xb9, 0xb8, 0x47, 0x66, 0x41, 0x5d, 0x11, 0xf6, 0xc3, 0x32, 0x09, 0xa0, + 0xd2, 0x85, 0x71, 0x09, 0x6a, 0xb0, 0x4a, 0x79, 0xaa, 0x0d, 0xc4, 0x65, + 0x99, 0x75, 0x29, 0x68, 0x6b, 0x68, 0xe8, 0x87, 0xcd, 0x8a, 0x20, 0x5c, + 0x2d, 0xc8, 0x19, 0x5a, 0xef, 0x04, 0x22, 0xeb, 0xa9, 0x97, 0x9f, 0x54, + 0x9a, 0xc8, 0x55, 0x48, 0xe4, 0x19, 0x41, 0x36, 0x43, 0xb7, 0x24, 0x43, + 0x61, 0x15, 0x3a, 0xda, 0x14, 0x80, 0xd2, 0x38, 0xcd, 0x00, 0xdc, 0x16, + 0x52, 0x79, 0x38, 0x95, 0x55, 0x48, 0xdd, 0x5d, 0x02, 0x7d, 0xed, 0x10, + 0x29, 0xee, 0xeb, 0x8e, 0xd6, 0xc6, 0x1b, 0x4c, 0xd5, 0x93, 0x41, 0xd8, + 0xb1, 0x54, 0x66, 0xe9, 0xda, 0x89, 0x0a, 0x98, 0x99, 0x96, 0xf4, 0xd7, + 0x69, 0x1e, 0x60, 0x72, 0xde, 0x13, 0x6a, 0xf2, 0x8b, 0x58, 0x74, 0xbf, + 0x08, 0xbd, 0x1f, 0x8a, 0x60, 0xcf, 0xb1, 0xc0, 0x08, 0x88, 0x13, 0x29, + 0x09, 0xf5, 0x15, 0xe0, 0x4b, 0xce, 0x81, 0xb0, 0x29, 0x51, 0xaa, 0x41, + 0xba, 0xac, 0x68, 0xff, 0xdb, 0x8c, 0x5d, 0xc7, 0x7a, 0x1d, 0x32, 0xd8, + 0xf2, 0xc1, 0x0d, 0xd7 +}; +/* K = 7197392d32d0af6a7183cc3398556f8f687d86a8ff742be6ad38562f */ +static const uint8_t ac_dsa_vect76_out[] = { +/* R */ + 0x45, 0xdf, 0x2f, 0x42, 0x3e, 0x94, 0xbf, 0x15, 0x5d, 0xd4, 0xe1, 0xd9, + 0xe6, 0x3f, 0x31, 0x5e, 0xa6, 0x06, 0xdd, 0x38, 0x52, 0x7d, 0x4c, 0xf6, + 0x32, 0x87, 0x38, 0xc8, +/* S */ + 0x59, 0xb3, 0xe8, 0xef, 0xa5, 0xbc, 0x0c, 0xcb, 0xf4, 0xa3, 0xcb, 0xb6, + 0x51, 0x5c, 0x4b, 0x9b, 0xf7, 0x84, 0xcf, 0xac, 0xdc, 0xc1, 0x01, 0xdc, + 0x9f, 0x81, 0xd3, 0x1f +}; +#define ac_dsa_vect77_prime ac_dsa_vect76_prime +#define ac_dsa_vect77_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect77_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect77_ptx[] = { +/* Msg */ + 0x3b, 0xd2, 0xab, 0x08, 0x21, 0x78, 0x78, 0xe6, 0x77, 0x4e, 0xc7, 0x79, + 0x7d, 0xeb, 0x75, 0xd5, 0xc9, 0x4c, 0x40, 0xe2, 0x4d, 0xdf, 0x1f, 0xac, + 0x8d, 0xde, 0x3a, 0x29, 0xc8, 0x6b, 0x26, 0xf5, 0x71, 0x57, 0xd3, 0x29, + 0xaa, 0xc3, 0x1a, 0x66, 0x22, 0xe1, 0xd6, 0xda, 0xc9, 0x7e, 0x22, 0x69, + 0x5d, 0x7d, 0x1f, 0x8e, 0x20, 0xaa, 0x26, 0xb0, 0x67, 0x95, 0xc2, 0xf8, + 0x78, 0xba, 0x5d, 0x2b, 0x9c, 0xc4, 0xb1, 0x6d, 0x5f, 0xa6, 0x0a, 0x5f, + 0xa5, 0xc2, 0x4c, 0x09, 0x03, 0x1d, 0xe2, 0xf9, 0x70, 0xa9, 0xb5, 0x7e, + 0xa2, 0x4a, 0xf1, 0x71, 0x92, 0xec, 0xe2, 0x1a, 0x4d, 0x12, 0x0f, 0xdb, + 0x52, 0xe6, 0x2b, 0x82, 0x38, 0xf7, 0x78, 0xff, 0x85, 0x52, 0xfa, 0x45, + 0x3c, 0x0a, 0x88, 0x91, 0x24, 0x3f, 0xc8, 0x75, 0x71, 0x88, 0xe9, 0xc4, + 0xe0, 0xe7, 0x49, 0xf7, 0xe9, 0xcd, 0xf1, 0xc1 +}; +static const uint8_t ac_dsa_vect77_priv_val[] = { +/* X */ + 0x32, 0xd5, 0x3a, 0xd2, 0x62, 0x0c, 0x15, 0x6e, 0x46, 0x17, 0xa8, 0x68, + 0x0c, 0x54, 0x38, 0x39, 0xc9, 0xbe, 0x93, 0x10, 0x3e, 0x80, 0xcc, 0x0f, + 0xef, 0xa4, 0x4c, 0xe5 +}; +static const uint8_t ac_dsa_vect77_pub_val[] = { +/* Y */ + 0xb9, 0xb0, 0xe1, 0xcd, 0x37, 0xba, 0xfb, 0xed, 0xee, 0xd1, 0x73, 0xfd, + 0x70, 0x99, 0x83, 0xf5, 0x3c, 0x2c, 0x42, 0x7f, 0x9f, 0x61, 0xc8, 0x95, + 0xfa, 0xc9, 0xeb, 0x54, 0x9b, 0xd6, 0x20, 0x1d, 0x05, 0xef, 0xd5, 0x51, + 0xae, 0xcb, 0x98, 0xb2, 0xdf, 0x80, 0x14, 0x2d, 0xea, 0x7a, 0x35, 0x49, + 0x1d, 0x47, 0x4a, 0x3a, 0xdc, 0x83, 0xf0, 0xda, 0x8d, 0xc4, 0xea, 0xcd, + 0x7f, 0x6d, 0x72, 0x01, 0xc6, 0xfc, 0x0a, 0xb7, 0x98, 0xab, 0xe8, 0x9d, + 0xcd, 0x7d, 0x03, 0x10, 0xd5, 0xf0, 0x0f, 0xa1, 0x0d, 0x21, 0x1f, 0x18, + 0xea, 0x85, 0x35, 0x79, 0xe2, 0xfe, 0x31, 0xee, 0x55, 0x37, 0x1d, 0x1c, + 0x9f, 0xc4, 0xcf, 0xb0, 0x50, 0x78, 0x65, 0x86, 0x65, 0x9b, 0xdc, 0x0f, + 0x1a, 0xac, 0x4c, 0x10, 0x9b, 0x9e, 0x4f, 0x94, 0x16, 0xd2, 0x2c, 0x42, + 0xb3, 0x9a, 0x47, 0x13, 0x11, 0xe2, 0x8a, 0x8e, 0xd6, 0x2f, 0x1f, 0x41, + 0xbc, 0xfe, 0x06, 0xe0, 0x74, 0xbb, 0x2f, 0x1a, 0xcd, 0x29, 0x59, 0x79, + 0x53, 0xc3, 0xb6, 0x9d, 0x3a, 0x78, 0x83, 0x1f, 0xb2, 0xf8, 0x36, 0x65, + 0xd0, 0x4a, 0x13, 0x95, 0x77, 0x5e, 0xa3, 0xa2, 0xa6, 0xea, 0x14, 0x2e, + 0xc0, 0x05, 0x07, 0xba, 0xdd, 0x4d, 0xe0, 0xd9, 0xc1, 0x02, 0xea, 0xc7, + 0xbb, 0x89, 0x4f, 0x74, 0x53, 0xe6, 0xa8, 0xe0, 0xdd, 0x3f, 0x14, 0x97, + 0x83, 0x77, 0xd1, 0xdd, 0xb1, 0xfd, 0xf1, 0xc5, 0x58, 0x35, 0xb9, 0x92, + 0x4f, 0x42, 0xad, 0x45, 0xc8, 0x47, 0xc7, 0x9b, 0x3f, 0x83, 0xfb, 0xf9, + 0x24, 0xf8, 0x0b, 0x78, 0xf5, 0x03, 0x29, 0x73, 0x10, 0x16, 0x76, 0x3e, + 0x01, 0xba, 0x8e, 0xf6, 0x9e, 0x81, 0x52, 0x3e, 0x18, 0x15, 0x84, 0xf4, + 0x5c, 0x21, 0xe3, 0xc8, 0xed, 0xfe, 0xd4, 0xe2, 0xec, 0x56, 0xfb, 0x7b, + 0x02, 0xaa, 0x4e, 0xe9 +}; +/* K = 2e8e4625de74e31bea9e480a5de92890095b6ce36897a2337ff97d53 */ +static const uint8_t ac_dsa_vect77_out[] = { +/* R */ + 0x6d, 0x19, 0xfe, 0x3c, 0x41, 0x5d, 0x6b, 0x07, 0xd6, 0xa1, 0x03, 0x9a, + 0x1f, 0xe3, 0x4b, 0x10, 0x6d, 0xaa, 0x2e, 0xea, 0x4c, 0xbc, 0xa9, 0x71, + 0xcb, 0x66, 0x9e, 0xac, +/* S */ + 0x14, 0xd7, 0xde, 0xcc, 0x2c, 0xc0, 0x5a, 0x17, 0x00, 0xfa, 0x25, 0x6e, + 0x4d, 0x29, 0x94, 0xbc, 0x4b, 0xd9, 0x57, 0xbe, 0xd0, 0xba, 0xf9, 0xa1, + 0x8b, 0xda, 0x70, 0x90 +}; +#define ac_dsa_vect78_prime ac_dsa_vect76_prime +#define ac_dsa_vect78_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect78_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect78_ptx[] = { +/* Msg */ + 0xc6, 0x7f, 0xa7, 0x7c, 0xd7, 0x35, 0x1d, 0x10, 0x0c, 0x76, 0x24, 0xe2, + 0x54, 0x18, 0x48, 0x1f, 0x8f, 0xa4, 0x99, 0xd7, 0x5f, 0x59, 0x49, 0xa5, + 0xca, 0xe6, 0x0f, 0x96, 0xa0, 0xf7, 0xbf, 0xcd, 0xda, 0x7d, 0xba, 0x37, + 0x3f, 0x9f, 0x75, 0x12, 0xa5, 0xf1, 0x46, 0x0a, 0x95, 0x21, 0x30, 0x77, + 0xce, 0xbd, 0x91, 0x2e, 0x26, 0x62, 0xc4, 0x3a, 0xc6, 0xbb, 0xe3, 0x8c, + 0x44, 0x79, 0xb0, 0x41, 0x51, 0xa5, 0xe2, 0xd2, 0x88, 0x09, 0x02, 0xd0, + 0x31, 0xaa, 0x0d, 0xff, 0x3f, 0x41, 0x12, 0x6d, 0xd0, 0x9f, 0xba, 0x5c, + 0x05, 0x07, 0x63, 0x4e, 0xd1, 0x6c, 0x39, 0x38, 0xfb, 0xd3, 0xa9, 0x64, + 0x73, 0xa8, 0xb1, 0xeb, 0xdc, 0x37, 0xd3, 0x2c, 0x76, 0x7f, 0xd5, 0x93, + 0x2e, 0xfa, 0x23, 0x55, 0x55, 0xf3, 0x82, 0x5a, 0x15, 0x95, 0x36, 0x92, + 0x38, 0x67, 0x54, 0x53, 0x60, 0x4d, 0x27, 0x8e +}; +static const uint8_t ac_dsa_vect78_priv_val[] = { +/* X */ + 0x06, 0x2b, 0xd0, 0x14, 0x87, 0xe4, 0x13, 0x07, 0x41, 0x26, 0xd9, 0xd4, + 0x72, 0x58, 0xb5, 0xc7, 0xc7, 0x77, 0x90, 0xa9, 0xdb, 0x0a, 0xf9, 0x52, + 0xce, 0x79, 0x9e, 0xb0 +}; +static const uint8_t ac_dsa_vect78_pub_val[] = { +/* Y */ + 0x31, 0x93, 0x9c, 0xcd, 0xd3, 0x93, 0xf7, 0x47, 0x54, 0x1a, 0x5c, 0x69, + 0xf8, 0xe5, 0x09, 0x76, 0x1d, 0xd6, 0x7e, 0xdd, 0xb4, 0x2e, 0x0b, 0xdf, + 0xc4, 0x12, 0xd4, 0xcc, 0x30, 0xd3, 0x68, 0xd8, 0x78, 0xd2, 0x6d, 0x85, + 0x6c, 0x52, 0x90, 0xec, 0x74, 0x6b, 0x59, 0xc5, 0xe5, 0xaf, 0x65, 0xef, + 0x3f, 0xd6, 0x2c, 0x9a, 0x2d, 0xcc, 0xfc, 0x15, 0x58, 0xdf, 0xbf, 0xb6, + 0x2c, 0xfe, 0xcd, 0x78, 0x38, 0xe6, 0xd5, 0x94, 0x95, 0xb2, 0x0d, 0xb5, + 0xad, 0x9d, 0x78, 0xe8, 0x2f, 0x04, 0x6f, 0x9f, 0x15, 0x98, 0x11, 0x3a, + 0xae, 0x0a, 0x79, 0x60, 0x1d, 0x6b, 0x94, 0xa3, 0x2e, 0x05, 0xf6, 0xec, + 0xfd, 0xf2, 0xb9, 0xc4, 0xcf, 0xa7, 0x20, 0xde, 0xbf, 0xc2, 0x12, 0x22, + 0x1b, 0x14, 0xb0, 0xdd, 0x6f, 0x70, 0x78, 0x20, 0x5a, 0x4f, 0x21, 0x8c, + 0xd4, 0xb8, 0xf1, 0x0b, 0xea, 0x8f, 0xa4, 0x81, 0xec, 0xa5, 0x25, 0x4f, + 0x36, 0x5d, 0x01, 0xf3, 0xc8, 0x65, 0x20, 0xbf, 0x25, 0x43, 0x23, 0xd5, + 0x63, 0x4b, 0x96, 0x92, 0x0a, 0x13, 0xb8, 0xf2, 0x9d, 0x73, 0x4e, 0x07, + 0xfd, 0xe8, 0x06, 0x4e, 0xb0, 0xc9, 0xf8, 0xeb, 0xb6, 0xae, 0x0b, 0x40, + 0xb4, 0xaa, 0x7d, 0x26, 0xbb, 0x8d, 0x80, 0x86, 0x82, 0x31, 0xd4, 0x55, + 0x8a, 0x27, 0x80, 0x45, 0xcb, 0x5f, 0x29, 0x51, 0xcb, 0xfe, 0x0d, 0xc9, + 0x7b, 0xbd, 0xce, 0xe7, 0xaf, 0x8c, 0x9b, 0x1e, 0x3b, 0x63, 0xcb, 0x49, + 0xdc, 0x29, 0xf3, 0x00, 0x77, 0x5c, 0xdb, 0xe4, 0xd2, 0xd2, 0x78, 0x94, + 0xe2, 0x7e, 0x0e, 0x7c, 0x9e, 0xad, 0xa1, 0x3a, 0x35, 0x9f, 0x0b, 0x92, + 0xb4, 0x49, 0xe9, 0xd0, 0x69, 0xb9, 0x5b, 0xdc, 0x2a, 0xa7, 0xc8, 0x5e, + 0x56, 0x81, 0x1c, 0x07, 0x20, 0x7a, 0x15, 0x0e, 0x59, 0x87, 0x35, 0x99, + 0x6a, 0x6e, 0x53, 0x49 +}; +/* K = 7439c7aa4446ed540ba50b9c817792b08fc0278fa0af2daded03756b */ +static const uint8_t ac_dsa_vect78_out[] = { +/* R */ + 0x79, 0x24, 0xb7, 0x6e, 0xe7, 0x6a, 0xd7, 0xff, 0x2a, 0xb3, 0x27, 0xda, + 0xbb, 0xbd, 0x31, 0x33, 0x67, 0x50, 0xfc, 0x76, 0x63, 0xdf, 0x4b, 0x5b, + 0x94, 0xee, 0xb6, 0x2d, +/* S */ + 0x59, 0x14, 0xcf, 0x96, 0x54, 0x90, 0xb0, 0xbf, 0x81, 0x92, 0xfc, 0x6e, + 0x16, 0x97, 0x54, 0xbd, 0xfd, 0x31, 0xc4, 0x8d, 0x71, 0x63, 0x61, 0xdd, + 0x15, 0xf4, 0x5b, 0xf7 +}; +#define ac_dsa_vect79_prime ac_dsa_vect76_prime +#define ac_dsa_vect79_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect79_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect79_ptx[] = { +/* Msg */ + 0xfd, 0xe7, 0x43, 0x4c, 0x41, 0x66, 0x60, 0x22, 0xd6, 0xd7, 0xda, 0xbc, + 0x7a, 0x67, 0x31, 0x5b, 0x1f, 0xf4, 0x9a, 0x2a, 0x85, 0xa6, 0x16, 0x8f, + 0x2b, 0x60, 0x63, 0xe3, 0x03, 0x6a, 0x4f, 0x35, 0xe6, 0x6d, 0x28, 0x72, + 0xaf, 0x3d, 0x97, 0xe5, 0xbe, 0xba, 0x23, 0x96, 0x98, 0xd8, 0x8e, 0x13, + 0xbd, 0x03, 0x6e, 0xf0, 0x8c, 0xf0, 0xe8, 0x3a, 0x41, 0x66, 0x4c, 0x3d, + 0x0d, 0x21, 0x86, 0x3c, 0x24, 0x12, 0x9a, 0x6a, 0x9b, 0x27, 0xb8, 0xe9, + 0x6c, 0x80, 0x29, 0xec, 0x67, 0x3e, 0x07, 0xaf, 0x72, 0x46, 0xab, 0x77, + 0xa5, 0x6c, 0x21, 0xca, 0x20, 0x8d, 0xf4, 0xb1, 0x81, 0x8d, 0xed, 0xa9, + 0x06, 0xb5, 0x53, 0xb2, 0xb2, 0x3a, 0x37, 0xb5, 0xa0, 0x5e, 0x29, 0x82, + 0x5e, 0xbe, 0xb4, 0x7f, 0x53, 0x98, 0x6c, 0x2b, 0xf2, 0x6d, 0x73, 0x1a, + 0x5b, 0x73, 0x1f, 0xff, 0xc3, 0x53, 0x25, 0x8c +}; +static const uint8_t ac_dsa_vect79_priv_val[] = { +/* X */ + 0x6e, 0x6b, 0xae, 0x97, 0xe3, 0xb3, 0x7a, 0x40, 0x2e, 0xca, 0x05, 0x0d, + 0x66, 0x6b, 0x64, 0x83, 0xcf, 0x7d, 0x70, 0x04, 0x19, 0xc5, 0xab, 0x1e, + 0xed, 0x1b, 0xed, 0x05 +}; +static const uint8_t ac_dsa_vect79_pub_val[] = { +/* Y */ + 0x59, 0xa1, 0x4e, 0x36, 0xc9, 0xed, 0xed, 0xdc, 0xe8, 0x00, 0x0f, 0x04, + 0xc6, 0xf7, 0x40, 0x1a, 0xd9, 0x87, 0xf1, 0xc7, 0xa5, 0xa0, 0x70, 0xb8, + 0x0e, 0x0a, 0xae, 0xd7, 0x75, 0x1d, 0x1d, 0x50, 0xd9, 0x9a, 0x58, 0x0c, + 0xf2, 0x05, 0xdb, 0xcc, 0x37, 0x97, 0xa0, 0xa0, 0x40, 0x6b, 0x04, 0x77, + 0x6d, 0x80, 0xf2, 0xf2, 0xdf, 0x41, 0x8c, 0xee, 0x24, 0x9b, 0x98, 0x67, + 0x2d, 0xe7, 0xe6, 0x1c, 0xda, 0x85, 0xcf, 0xbe, 0x90, 0x36, 0x90, 0xe5, + 0x46, 0x42, 0xdc, 0x2a, 0x12, 0xa9, 0x0e, 0xcf, 0x88, 0xc5, 0x92, 0x56, + 0xa4, 0xd7, 0x7c, 0x4c, 0x0c, 0xb5, 0x4e, 0x13, 0xfa, 0x36, 0x47, 0xb1, + 0x14, 0x31, 0xe1, 0x73, 0x4f, 0x3c, 0xee, 0xea, 0x04, 0xfb, 0xf3, 0x45, + 0x96, 0x65, 0xe9, 0x99, 0xfc, 0x0f, 0x7a, 0x75, 0x46, 0x83, 0xe4, 0x8c, + 0xef, 0xeb, 0x4a, 0x95, 0xfe, 0x47, 0x39, 0x11, 0xff, 0xe0, 0xde, 0x0f, + 0x73, 0x89, 0x60, 0x75, 0x3d, 0xac, 0x33, 0x66, 0x6c, 0x53, 0xed, 0x28, + 0x93, 0xbc, 0x63, 0xdd, 0x41, 0x62, 0xd7, 0xa6, 0x32, 0x87, 0x39, 0xa2, + 0x52, 0xcd, 0xae, 0xa7, 0xa9, 0x48, 0xc9, 0x7d, 0x02, 0x41, 0x53, 0xb5, + 0x5d, 0x14, 0xfd, 0x53, 0x04, 0xe3, 0x57, 0x50, 0x48, 0x41, 0x88, 0x08, + 0xa9, 0x52, 0x67, 0x5f, 0xaf, 0xb9, 0x5f, 0xad, 0x84, 0xb1, 0x15, 0x6b, + 0x24, 0xe9, 0x8e, 0x04, 0x8a, 0xa7, 0x77, 0xa7, 0x45, 0x32, 0x4e, 0xc1, + 0x3b, 0xa3, 0x78, 0xe8, 0x3b, 0x23, 0x84, 0xbc, 0x2e, 0x96, 0xc6, 0x09, + 0x5a, 0xa7, 0x86, 0xbd, 0x28, 0xfc, 0x3b, 0xe6, 0xbf, 0xa4, 0xdb, 0x0c, + 0x3c, 0x44, 0xfe, 0xd4, 0xc3, 0x51, 0xbd, 0x88, 0xa1, 0x9e, 0x17, 0x9a, + 0x6a, 0x7b, 0xc1, 0x2f, 0xc0, 0x14, 0xf1, 0x7d, 0xe4, 0x6f, 0xd1, 0x2e, + 0xf1, 0x28, 0x7f, 0x72 +}; +/* K = 08544a6237ac967e5d11f2eccc6618399818b891df7a04d08cbc5e74 */ +static const uint8_t ac_dsa_vect79_out[] = { +/* R */ + 0x49, 0xea, 0x82, 0x71, 0x3a, 0xaa, 0xd7, 0x99, 0xe2, 0x63, 0x80, 0x9e, + 0x16, 0x1b, 0x06, 0x55, 0xf1, 0xe7, 0x43, 0x23, 0xa0, 0x60, 0x41, 0x83, + 0x6f, 0x67, 0x69, 0x80, +/* S */ + 0x76, 0xb3, 0xf6, 0xc1, 0x64, 0x7f, 0x8d, 0x17, 0x71, 0x8f, 0xfb, 0x92, + 0xd6, 0xe1, 0x42, 0x46, 0x06, 0xba, 0x97, 0x24, 0xe5, 0x29, 0x0d, 0xaa, + 0x4e, 0xe9, 0x5e, 0xfb +}; +#define ac_dsa_vect80_prime ac_dsa_vect76_prime +#define ac_dsa_vect80_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect80_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect80_ptx[] = { +/* Msg */ + 0x66, 0x76, 0xa3, 0xa1, 0x31, 0xce, 0xf7, 0xe5, 0x64, 0x7e, 0xa7, 0x59, + 0x0d, 0xa3, 0xc7, 0x04, 0xa0, 0xf5, 0xdc, 0x3f, 0x37, 0xf2, 0x69, 0x13, + 0xa7, 0x0d, 0x43, 0x06, 0x09, 0xcc, 0x24, 0x97, 0xc4, 0x5e, 0x68, 0xb7, + 0xbd, 0x6f, 0x58, 0x93, 0xdb, 0xa2, 0x62, 0x87, 0xff, 0x0d, 0x24, 0x0b, + 0xab, 0x8a, 0x07, 0x61, 0x93, 0x6a, 0xa7, 0x09, 0xa2, 0x16, 0x2e, 0xbf, + 0x1c, 0x20, 0xa6, 0x13, 0x6a, 0x74, 0x83, 0x52, 0xdc, 0x39, 0xba, 0x44, + 0x03, 0xcb, 0xe4, 0xb0, 0xa5, 0xa5, 0x4a, 0x72, 0x92, 0x86, 0xdd, 0x19, + 0x3e, 0xac, 0x1a, 0x2e, 0x6b, 0xdc, 0x15, 0x0f, 0xb0, 0x63, 0x69, 0xbe, + 0x44, 0x43, 0xa6, 0x0e, 0x75, 0xe5, 0x33, 0x00, 0x83, 0xff, 0x00, 0x9e, + 0xab, 0xb0, 0x52, 0x32, 0xc5, 0x23, 0x68, 0xa2, 0x6f, 0xd2, 0x37, 0xc7, + 0xc3, 0x18, 0x5c, 0x1c, 0x7e, 0x7d, 0x59, 0x55 +}; +static const uint8_t ac_dsa_vect80_priv_val[] = { +/* X */ + 0x18, 0xfa, 0xf5, 0x83, 0x21, 0x5b, 0xc4, 0xfa, 0x71, 0x79, 0x1f, 0x6f, + 0x34, 0xe6, 0x82, 0xab, 0x35, 0x29, 0xaa, 0x9a, 0x1a, 0x71, 0xc1, 0xfc, + 0x7b, 0xd4, 0x56, 0xa8 +}; +static const uint8_t ac_dsa_vect80_pub_val[] = { +/* Y */ + 0xdd, 0xcd, 0xf4, 0xc6, 0x16, 0xfd, 0x6e, 0x40, 0x16, 0x09, 0x9f, 0xb3, + 0x4e, 0xbc, 0x4e, 0xc5, 0x07, 0x29, 0x07, 0x62, 0xc5, 0xee, 0x68, 0x76, + 0xf1, 0x0c, 0x6a, 0x2d, 0xed, 0xec, 0x97, 0xba, 0x86, 0xa6, 0x06, 0x3a, + 0xa8, 0xff, 0x06, 0x9f, 0x3f, 0x3d, 0xb4, 0x0c, 0x94, 0x64, 0xaf, 0xb1, + 0xba, 0x7e, 0xd6, 0x91, 0x77, 0x3a, 0xfd, 0x60, 0x83, 0x58, 0x6b, 0x14, + 0xe3, 0x56, 0x94, 0xa9, 0xdd, 0xc3, 0x76, 0xdd, 0xc3, 0x9d, 0xac, 0x57, + 0x13, 0x2a, 0x05, 0xbf, 0x88, 0xa0, 0xa6, 0x08, 0x5c, 0x72, 0xa8, 0x0a, + 0x21, 0xc1, 0x3e, 0x59, 0x0c, 0x68, 0xc4, 0xe9, 0x8e, 0xed, 0xb6, 0x7f, + 0x1e, 0x16, 0xc8, 0xcc, 0x7e, 0x9e, 0x25, 0xff, 0x37, 0xc8, 0x7e, 0xe3, + 0xbe, 0x9a, 0xdf, 0x1a, 0xd0, 0xb8, 0x38, 0x65, 0x1b, 0x0f, 0xdd, 0xf8, + 0xd0, 0x26, 0x96, 0x9d, 0x4a, 0x16, 0xbb, 0xb8, 0x28, 0xfc, 0xaf, 0x00, + 0xef, 0xa3, 0x06, 0xfc, 0xed, 0xd5, 0xae, 0x19, 0xca, 0x1a, 0x1a, 0xbf, + 0x44, 0xa2, 0xbd, 0xf6, 0xf9, 0x94, 0x12, 0x3c, 0xe9, 0x41, 0xfd, 0x35, + 0x23, 0xbc, 0x13, 0x35, 0xf5, 0x1f, 0xa8, 0xdc, 0x5d, 0x52, 0x53, 0x58, + 0xbd, 0xdf, 0x0c, 0x55, 0xfe, 0x2c, 0xe0, 0x7c, 0xe9, 0x74, 0x40, 0x8d, + 0x90, 0x90, 0x48, 0x88, 0x37, 0x97, 0x6f, 0x16, 0x84, 0x5e, 0xb7, 0xa8, + 0x2d, 0x04, 0xc4, 0x3a, 0x70, 0x4b, 0xe2, 0xde, 0xe1, 0xbe, 0x2c, 0x86, + 0x83, 0xb2, 0xd9, 0xe5, 0xc4, 0x4f, 0x18, 0x33, 0xf5, 0xc4, 0x6c, 0x65, + 0xb6, 0xe6, 0x2c, 0x2a, 0x72, 0x04, 0x21, 0xbb, 0x35, 0x84, 0x3f, 0xea, + 0xd7, 0xb9, 0xe0, 0xb3, 0xfc, 0x04, 0xc6, 0x46, 0xbe, 0x39, 0xe8, 0x90, + 0xe3, 0x70, 0xb9, 0x82, 0xbd, 0xe9, 0x1f, 0x2f, 0xc1, 0x84, 0x42, 0xb6, + 0x50, 0xae, 0x60, 0x2f +}; +/* K = 11b25b09408bb5dd784ad70264e585c978dc02cc1df8bb95a28aedfe */ +static const uint8_t ac_dsa_vect80_out[] = { +/* R */ + 0x16, 0x58, 0xa7, 0xef, 0x2f, 0x44, 0x4b, 0x01, 0x4a, 0x18, 0x85, 0xb1, + 0xed, 0xa8, 0xda, 0xd3, 0x60, 0x5b, 0x96, 0xc3, 0x94, 0x8e, 0x54, 0x4e, + 0x4c, 0x88, 0x25, 0xeb, +/* S */ + 0x60, 0x21, 0x50, 0xf6, 0x7b, 0x19, 0xa5, 0xe3, 0xe3, 0x9f, 0xc5, 0x3a, + 0xbe, 0xa0, 0x2d, 0xd8, 0xf3, 0xb3, 0x0d, 0x25, 0xc0, 0xb4, 0xea, 0x0b, + 0xcd, 0xdc, 0xbd, 0xb0 +}; +#define ac_dsa_vect81_prime ac_dsa_vect76_prime +#define ac_dsa_vect81_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect81_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect81_ptx[] = { +/* Msg */ + 0x07, 0x1f, 0x06, 0xa1, 0x15, 0x88, 0x58, 0x4d, 0xa5, 0x57, 0x60, 0x13, + 0x02, 0x9b, 0x5a, 0x14, 0x71, 0x25, 0x81, 0xa4, 0x84, 0x08, 0xbb, 0xfd, + 0xbe, 0x34, 0xe1, 0x75, 0x68, 0xc0, 0xa0, 0xe4, 0xd1, 0x2c, 0x1e, 0x9c, + 0x3f, 0xb2, 0x27, 0x10, 0x14, 0x40, 0xdd, 0x8d, 0xcd, 0xc4, 0x15, 0xe3, + 0xb4, 0x9f, 0x68, 0xa2, 0x6a, 0x0e, 0xc7, 0x61, 0x2a, 0x10, 0xbb, 0xc6, + 0x4d, 0xdb, 0x8f, 0x7e, 0xc9, 0xe9, 0x75, 0x0d, 0x1e, 0xfc, 0x9c, 0x05, + 0x74, 0x70, 0x08, 0x75, 0xfc, 0xf5, 0x2d, 0x00, 0xd3, 0x7b, 0x9d, 0xd7, + 0x44, 0xca, 0x84, 0x1e, 0xcf, 0x75, 0x66, 0x97, 0x7c, 0x1b, 0x57, 0x99, + 0xdc, 0x41, 0x05, 0xd0, 0xb7, 0xa9, 0x25, 0x51, 0xc5, 0xb3, 0x3a, 0x50, + 0x13, 0x3f, 0xa3, 0x00, 0xa5, 0x90, 0x8b, 0x18, 0xf4, 0xc0, 0x19, 0x36, + 0x34, 0x7c, 0x60, 0x49, 0x44, 0x7a, 0xbf, 0x29 +}; +static const uint8_t ac_dsa_vect81_priv_val[] = { +/* X */ + 0x58, 0x88, 0x2f, 0x1a, 0x41, 0xe0, 0x8b, 0xf6, 0xc8, 0xda, 0xd0, 0x91, + 0xa2, 0x99, 0xaf, 0x0f, 0xbb, 0xd1, 0x45, 0x15, 0xc1, 0x55, 0x09, 0x06, + 0xff, 0x77, 0xf6, 0xae +}; +static const uint8_t ac_dsa_vect81_pub_val[] = { +/* Y */ + 0xb1, 0xf4, 0xdf, 0xc9, 0xc8, 0x34, 0x55, 0xf2, 0x79, 0xa3, 0xe7, 0x52, + 0x27, 0x34, 0xd6, 0xb1, 0x20, 0xab, 0x8e, 0xd3, 0x6c, 0xcb, 0xa7, 0x85, + 0x4e, 0x26, 0x50, 0x4c, 0x70, 0x79, 0x83, 0xd2, 0xa9, 0xc0, 0x75, 0x04, + 0x57, 0x23, 0xf4, 0x41, 0xab, 0xfc, 0x7b, 0x36, 0xfb, 0xb5, 0xd4, 0xbf, + 0x04, 0x47, 0x67, 0x8f, 0x5b, 0x70, 0x9c, 0xa5, 0x12, 0x9b, 0x74, 0x88, + 0x8a, 0x07, 0x23, 0xe9, 0x05, 0x76, 0x98, 0x36, 0xb9, 0xda, 0xc1, 0x30, + 0x3f, 0x1b, 0x9a, 0xce, 0x26, 0x55, 0x43, 0x42, 0xb6, 0xe6, 0xd0, 0x32, + 0xac, 0x4b, 0x47, 0x7e, 0x01, 0x1a, 0x4d, 0xdd, 0x3e, 0x29, 0x78, 0xfc, + 0x0c, 0x44, 0x9c, 0x64, 0xa6, 0x6e, 0xfe, 0x7d, 0x4e, 0x22, 0xe5, 0xa5, + 0xfa, 0x2b, 0x01, 0xbb, 0x17, 0xfc, 0xdb, 0xec, 0x71, 0x85, 0xdd, 0x41, + 0x15, 0xa1, 0x9d, 0x97, 0x2f, 0xb0, 0x1a, 0x06, 0xb3, 0x3b, 0xb1, 0x8b, + 0x93, 0x49, 0xff, 0x95, 0xfb, 0x10, 0xdb, 0xbf, 0x2d, 0xcf, 0x89, 0x9b, + 0x18, 0x17, 0xd3, 0x0a, 0xd4, 0x8a, 0x99, 0xa6, 0x14, 0xd5, 0x77, 0x70, + 0xba, 0x76, 0x4a, 0x11, 0xa8, 0x4a, 0x8d, 0xb3, 0xaf, 0x30, 0x41, 0xec, + 0x36, 0x26, 0x14, 0xf8, 0x07, 0x19, 0x6e, 0xa3, 0xb9, 0x0d, 0x05, 0xb0, + 0x14, 0x05, 0x4f, 0xf4, 0xe1, 0x85, 0x24, 0xc7, 0x95, 0xe6, 0x72, 0x2c, + 0x0f, 0xa1, 0xf6, 0xd1, 0x20, 0x5d, 0x53, 0x2d, 0x94, 0x34, 0x76, 0x33, + 0xeb, 0x13, 0x2e, 0x6c, 0xbb, 0x59, 0x6d, 0x8b, 0x34, 0x1e, 0x65, 0xf2, + 0xb2, 0xf9, 0x55, 0x87, 0x2e, 0xbd, 0x4d, 0x30, 0x06, 0xc4, 0x5a, 0xc3, + 0x3d, 0xa1, 0x11, 0x67, 0xfa, 0x46, 0x86, 0x9c, 0x7e, 0xe7, 0x0e, 0x9c, + 0xf1, 0x47, 0xb2, 0x33, 0x68, 0xb3, 0xaa, 0xcd, 0x9c, 0x18, 0x80, 0xb0, + 0x9a, 0xc8, 0x6a, 0x8d +}; +/* K = 5ff04e754fe3246f35b3400b87a450192a7bfd9b3c03f3ece93449f4 */ +static const uint8_t ac_dsa_vect81_out[] = { +/* R */ + 0x07, 0xbd, 0x3f, 0x67, 0x18, 0xe3, 0x98, 0x39, 0x30, 0x4e, 0xf5, 0x4a, + 0xc4, 0x8b, 0xda, 0x8d, 0x9a, 0xc8, 0xee, 0x05, 0x1a, 0x49, 0xbb, 0x91, + 0x31, 0xdc, 0xc9, 0x18, +/* S */ + 0x64, 0x96, 0xb2, 0x46, 0x9b, 0xfb, 0x58, 0x45, 0x48, 0x50, 0x04, 0x70, + 0x2b, 0x0c, 0x79, 0x94, 0x1b, 0xc3, 0xc3, 0x00, 0x70, 0x07, 0xba, 0x16, + 0x9d, 0x83, 0x07, 0xce +}; +#define ac_dsa_vect82_prime ac_dsa_vect76_prime +#define ac_dsa_vect82_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect82_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect82_ptx[] = { +/* Msg */ + 0x71, 0x27, 0x9b, 0x84, 0x8c, 0x00, 0x20, 0x8f, 0xb4, 0xe4, 0xd8, 0x79, + 0x79, 0xcf, 0x97, 0x3b, 0x32, 0x1b, 0x20, 0xd0, 0x98, 0xde, 0xa9, 0x12, + 0xa3, 0xb4, 0xb5, 0x78, 0x9c, 0xdd, 0x3b, 0x7c, 0xcd, 0x8f, 0x39, 0x93, + 0xa9, 0xc9, 0x2c, 0x34, 0xb7, 0x0e, 0x9b, 0x0b, 0xd5, 0x75, 0x20, 0xdb, + 0x56, 0xf2, 0xde, 0xd3, 0xa6, 0x12, 0xa6, 0x16, 0x9d, 0x2a, 0x1c, 0xc6, + 0x35, 0x09, 0x05, 0xed, 0x02, 0x02, 0xa2, 0x5c, 0x11, 0x3b, 0x7b, 0xf8, + 0xfa, 0xec, 0x4e, 0xdd, 0x2e, 0xa3, 0xb8, 0xf4, 0x47, 0xca, 0x75, 0xd1, + 0x5a, 0x71, 0x2b, 0x4b, 0x43, 0x94, 0xc2, 0x2d, 0xe0, 0xc2, 0x55, 0x4b, + 0x9a, 0xa0, 0x7e, 0xc8, 0x46, 0x67, 0x27, 0xe7, 0xef, 0x6f, 0x1f, 0x04, + 0xac, 0x45, 0x68, 0xd7, 0x72, 0x6d, 0x9d, 0x77, 0xf5, 0x0a, 0x2f, 0xd5, + 0x51, 0xac, 0x29, 0xe4, 0x2f, 0x8d, 0xda, 0x23 +}; +static const uint8_t ac_dsa_vect82_priv_val[] = { +/* X */ + 0x29, 0x2b, 0x16, 0x66, 0xd0, 0xb1, 0xfb, 0x36, 0x1d, 0xa2, 0x68, 0xde, + 0x72, 0x5b, 0x11, 0x31, 0x00, 0x00, 0x70, 0x59, 0x64, 0x70, 0x5e, 0xe9, + 0x75, 0xd4, 0xeb, 0xae +}; +static const uint8_t ac_dsa_vect82_pub_val[] = { +/* Y */ + 0x7c, 0x8d, 0x63, 0xb9, 0xd5, 0x5f, 0x59, 0x29, 0x0b, 0x02, 0xa0, 0xfc, + 0xea, 0x6d, 0x98, 0xc6, 0xc5, 0x45, 0xe2, 0xc0, 0xd4, 0xb1, 0x09, 0xa0, + 0x69, 0x69, 0x4d, 0x80, 0xcb, 0x03, 0x4d, 0xbd, 0xbd, 0x9e, 0xdb, 0x6b, + 0x4d, 0x9b, 0x15, 0x28, 0x49, 0xca, 0xbd, 0x65, 0x5f, 0xc7, 0x70, 0x71, + 0x64, 0x4b, 0xbf, 0x4a, 0x0c, 0x7e, 0xa4, 0xed, 0xfe, 0x86, 0x4a, 0x43, + 0xc4, 0x4f, 0xde, 0xd1, 0x63, 0xdd, 0x89, 0x9c, 0x21, 0xcc, 0x2f, 0x9c, + 0x33, 0xcb, 0xf5, 0x6e, 0x8c, 0xaf, 0x84, 0x39, 0x4b, 0x24, 0xf8, 0xc1, + 0x4e, 0x84, 0xf2, 0x2c, 0x3b, 0x0f, 0x74, 0x71, 0x29, 0xd9, 0xae, 0xf4, + 0x1b, 0x6f, 0x1b, 0x1f, 0xa8, 0xff, 0x5a, 0x8f, 0x68, 0x0b, 0x49, 0x65, + 0x95, 0xdb, 0xc7, 0xb7, 0xb6, 0x3a, 0x77, 0x90, 0xe3, 0x62, 0x87, 0x47, + 0x01, 0x1b, 0x32, 0x77, 0xb0, 0x6e, 0x80, 0xde, 0x0b, 0x67, 0x94, 0x2f, + 0x60, 0x2e, 0xad, 0xa6, 0x0b, 0x51, 0x8f, 0x28, 0x2c, 0xde, 0x69, 0xcd, + 0x71, 0x7a, 0x5f, 0x6a, 0x19, 0xc8, 0xe1, 0x69, 0x44, 0x9e, 0x0d, 0x32, + 0xa9, 0xd8, 0xce, 0x8f, 0x09, 0xa5, 0xad, 0xa2, 0x3c, 0x12, 0xa0, 0x2d, + 0xcc, 0xfc, 0xdc, 0x02, 0x90, 0xa8, 0xbd, 0x46, 0xe8, 0xb7, 0xeb, 0x39, + 0x74, 0x94, 0xf3, 0x2a, 0x0e, 0xcb, 0x49, 0xfa, 0x5a, 0x8e, 0xdd, 0x41, + 0x84, 0x5e, 0xb4, 0x17, 0xfb, 0xb8, 0xcd, 0xb8, 0x9a, 0x9f, 0x18, 0xb9, + 0xad, 0x1b, 0x41, 0xdd, 0x41, 0x22, 0xab, 0x34, 0x9b, 0xb3, 0xc4, 0x49, + 0x51, 0xe4, 0xf9, 0x60, 0x43, 0x60, 0xfc, 0xb1, 0xb7, 0x95, 0x31, 0x15, + 0x45, 0xa6, 0x1c, 0xfd, 0x67, 0xc2, 0x87, 0xa7, 0xc9, 0xd4, 0xd3, 0x53, + 0x02, 0x14, 0x98, 0x8e, 0x76, 0x16, 0x97, 0x9e, 0x2c, 0xe9, 0x07, 0xd5, + 0xc7, 0xf3, 0xe9, 0xad +}; +/* K = 6b1b752bb180d8787c71505be758c0ce41fef428ac10591502c9a04b */ +static const uint8_t ac_dsa_vect82_out[] = { +/* R */ + 0x4c, 0xf5, 0xc2, 0x6c, 0x4c, 0x2c, 0xd4, 0x8c, 0x05, 0x50, 0x8e, 0x52, + 0xd7, 0x43, 0xef, 0x48, 0x68, 0x5f, 0x63, 0x24, 0x14, 0x1a, 0xde, 0xf2, + 0x3d, 0x79, 0xa3, 0x96, +/* S */ + 0x59, 0xf6, 0x47, 0x55, 0xa0, 0x4c, 0x90, 0xa1, 0x4b, 0x18, 0x7a, 0xe1, + 0x42, 0xec, 0x48, 0x3c, 0x46, 0x00, 0xb6, 0xfb, 0xbe, 0x19, 0xf0, 0x4a, + 0x49, 0xe9, 0xff, 0x88 +}; +#define ac_dsa_vect83_prime ac_dsa_vect76_prime +#define ac_dsa_vect83_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect83_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect83_ptx[] = { +/* Msg */ + 0x3e, 0xa0, 0x3e, 0x9b, 0x00, 0x5e, 0xc1, 0x95, 0x4f, 0xee, 0x0c, 0x73, + 0x32, 0x6d, 0x8a, 0xca, 0x1a, 0x4f, 0x63, 0x64, 0x8e, 0xb4, 0xcc, 0x59, + 0x26, 0x55, 0x28, 0xee, 0x8e, 0x96, 0x9e, 0xce, 0xfe, 0xcf, 0x27, 0x97, + 0xa0, 0x14, 0x4c, 0x83, 0x36, 0x50, 0x0e, 0x26, 0xa1, 0xc7, 0xcb, 0x1a, + 0x64, 0x2b, 0x1e, 0xc6, 0x52, 0x01, 0x41, 0x6e, 0x5d, 0xeb, 0x35, 0x52, + 0x01, 0xde, 0x2b, 0xda, 0x69, 0x5d, 0x1b, 0xeb, 0xa8, 0xde, 0xe6, 0x27, + 0x72, 0xf4, 0xd5, 0x91, 0x4a, 0x24, 0x5b, 0xe9, 0xff, 0xec, 0xf3, 0x94, + 0x08, 0xae, 0x7b, 0xf1, 0xbf, 0xf7, 0xc2, 0x45, 0x10, 0x29, 0xc4, 0xba, + 0x0c, 0x52, 0x25, 0x16, 0xe8, 0x99, 0x55, 0xad, 0x3b, 0xd6, 0x99, 0xcc, + 0xe9, 0x4c, 0x74, 0x40, 0x81, 0xa9, 0xf2, 0xd6, 0x0f, 0x5c, 0x51, 0x27, + 0xec, 0x72, 0x2f, 0xa5, 0x73, 0x16, 0xce, 0xde +}; +static const uint8_t ac_dsa_vect83_priv_val[] = { +/* X */ + 0x08, 0x7e, 0x43, 0x2b, 0x1c, 0x29, 0xc0, 0x05, 0x08, 0xd7, 0x68, 0xfd, + 0xa7, 0xc4, 0xb2, 0x79, 0xfc, 0x08, 0x8c, 0x48, 0x43, 0x9f, 0x09, 0x98, + 0x0b, 0xfa, 0x15, 0x9c +}; +static const uint8_t ac_dsa_vect83_pub_val[] = { +/* Y */ + 0x12, 0x39, 0xc3, 0x47, 0xbe, 0x4c, 0xe6, 0xf1, 0xda, 0xa7, 0x21, 0xfb, + 0xbb, 0x14, 0x1e, 0xe6, 0xe2, 0xf7, 0xc7, 0x30, 0x98, 0xef, 0xfe, 0x8e, + 0x71, 0xbe, 0xb9, 0xf1, 0xab, 0x72, 0xd1, 0xb5, 0xbd, 0x3e, 0x78, 0xdf, + 0x77, 0x0f, 0x7f, 0xbd, 0x4b, 0x3a, 0x95, 0x05, 0x70, 0x2d, 0xac, 0xf1, + 0x02, 0xee, 0xb8, 0xa1, 0x6f, 0x11, 0xb4, 0xf8, 0x09, 0xca, 0x00, 0x2a, + 0xe3, 0x77, 0x4a, 0xc0, 0x40, 0x7e, 0x25, 0x72, 0xae, 0x3e, 0xe1, 0x71, + 0x64, 0x58, 0xe5, 0xf4, 0x5c, 0x49, 0x3f, 0x4b, 0x92, 0x11, 0x44, 0xe8, + 0x58, 0xd8, 0x7d, 0x63, 0x77, 0x3d, 0x02, 0x37, 0x45, 0x51, 0x2b, 0x0c, + 0xc0, 0x2b, 0x31, 0xeb, 0xfe, 0x5c, 0x24, 0xad, 0x37, 0xef, 0xe5, 0x39, + 0xcd, 0x39, 0x3c, 0xfc, 0x2b, 0x95, 0x1f, 0xe1, 0xb6, 0xff, 0xad, 0x2a, + 0x28, 0x24, 0xc0, 0xf5, 0x4b, 0xd7, 0x76, 0xaa, 0x0a, 0xfc, 0xf9, 0xc1, + 0xef, 0x42, 0x7a, 0xfc, 0x6c, 0xf4, 0xc4, 0xb1, 0x7f, 0x66, 0x35, 0x5d, + 0x68, 0x57, 0x41, 0x32, 0xe1, 0xd8, 0x8a, 0xde, 0x37, 0x22, 0x51, 0x3e, + 0x39, 0x5f, 0xc6, 0x2d, 0x65, 0xe9, 0x48, 0x51, 0x57, 0xc8, 0x20, 0x64, + 0xc9, 0x08, 0x03, 0xa1, 0xa9, 0x1f, 0x9e, 0x6b, 0x10, 0xaf, 0x2f, 0x80, + 0x69, 0x9d, 0x91, 0x7d, 0xaa, 0x6b, 0x81, 0x41, 0x5e, 0x50, 0x81, 0x93, + 0x15, 0x2b, 0x4c, 0xcd, 0xed, 0x59, 0x3d, 0xde, 0x35, 0xf6, 0x45, 0xe5, + 0x4b, 0x7c, 0xba, 0x44, 0x57, 0x75, 0xeb, 0x16, 0xc5, 0xe1, 0x90, 0x73, + 0xf0, 0xa9, 0xeb, 0x53, 0x69, 0xbf, 0x25, 0x13, 0xb9, 0x21, 0x58, 0x16, + 0x5b, 0x94, 0xde, 0xa5, 0x11, 0xe9, 0x38, 0xfb, 0x6a, 0x87, 0x98, 0xe0, + 0x40, 0xa0, 0x5d, 0xa9, 0x4f, 0xdb, 0x5a, 0x4d, 0x44, 0xbe, 0xe9, 0x43, + 0xb9, 0x5b, 0x39, 0xd9 +}; +/* K = 0a8a45ce2412cb84e4e0174d7ecd2eb5b37ad0a53b474fa9bcf56d9a */ +static const uint8_t ac_dsa_vect83_out[] = { +/* R */ + 0x5c, 0xa2, 0xe9, 0x71, 0xf2, 0x1b, 0x70, 0x12, 0x7a, 0x70, 0xc6, 0x55, + 0xeb, 0x87, 0xe2, 0x0b, 0x25, 0x17, 0x97, 0x62, 0x28, 0xa2, 0xc4, 0xe6, + 0x48, 0xd5, 0x49, 0xb2, +/* S */ + 0x44, 0x03, 0x6b, 0x34, 0x66, 0x71, 0x36, 0xa5, 0x14, 0x0d, 0xd1, 0x94, + 0x8d, 0xdc, 0x2f, 0xb2, 0xbf, 0x67, 0x9e, 0xfe, 0xe2, 0x1f, 0x29, 0xb7, + 0xad, 0x87, 0xaf, 0x7c +}; +#define ac_dsa_vect84_prime ac_dsa_vect76_prime +#define ac_dsa_vect84_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect84_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect84_ptx[] = { +/* Msg */ + 0xa3, 0xf7, 0x03, 0x39, 0x58, 0xc5, 0xb7, 0x79, 0x07, 0x2b, 0x05, 0x48, + 0xba, 0xed, 0xf4, 0xf8, 0x8d, 0x14, 0xf1, 0x1a, 0x6d, 0xd6, 0xee, 0xc0, + 0x18, 0x1b, 0x39, 0x99, 0x43, 0xd7, 0x24, 0x6a, 0x45, 0xd5, 0x0c, 0x4f, + 0x7b, 0x52, 0x95, 0xda, 0xe4, 0xcd, 0x3b, 0xa7, 0xc4, 0xc1, 0x81, 0xfa, + 0x20, 0x15, 0x81, 0xad, 0x5c, 0x4b, 0x38, 0x79, 0x3b, 0xcf, 0x45, 0x4f, + 0x17, 0x68, 0x68, 0xe9, 0xcb, 0xe0, 0x99, 0x7a, 0xa4, 0x19, 0x87, 0xb1, + 0xaa, 0x3d, 0x5d, 0xdc, 0x04, 0x6b, 0xe7, 0xb0, 0x22, 0xfb, 0x51, 0x30, + 0x59, 0x4c, 0x8a, 0x9d, 0xf0, 0x3c, 0xfa, 0xa7, 0xac, 0xef, 0x81, 0x7e, + 0x3b, 0xa5, 0xe1, 0x92, 0xc6, 0x9a, 0x12, 0x02, 0x99, 0x49, 0x2b, 0xaa, + 0x52, 0xa9, 0xbe, 0x83, 0xb8, 0xe8, 0x71, 0xab, 0xe3, 0x18, 0xb4, 0xa1, + 0xf5, 0x88, 0xf9, 0xed, 0xcd, 0xda, 0xfc, 0x17 +}; +static const uint8_t ac_dsa_vect84_priv_val[] = { +/* X */ + 0x58, 0x31, 0xab, 0xf9, 0x84, 0x3e, 0xee, 0x92, 0x89, 0x44, 0xe3, 0xdb, + 0xb7, 0x59, 0xdc, 0x72, 0x24, 0x91, 0x0e, 0x1a, 0xda, 0xb8, 0x27, 0xa0, + 0x4f, 0x59, 0x6e, 0x3c +}; +static const uint8_t ac_dsa_vect84_pub_val[] = { +/* Y */ + 0x62, 0xde, 0x24, 0x65, 0xed, 0xbc, 0x1e, 0xf8, 0x45, 0x8b, 0xea, 0xa2, + 0x05, 0xf4, 0x5f, 0x9d, 0xc0, 0xfc, 0x3d, 0xb7, 0x7b, 0xae, 0x0f, 0x2b, + 0x13, 0xbe, 0xf6, 0xd8, 0x03, 0xdb, 0x68, 0x9b, 0x8f, 0x5c, 0x74, 0x7e, + 0x3a, 0x04, 0x1c, 0x08, 0xd3, 0x26, 0xcd, 0x7e, 0x18, 0x91, 0x67, 0x5b, + 0x02, 0x2a, 0x9d, 0xa3, 0xbb, 0xae, 0xf8, 0x00, 0x77, 0x84, 0xc5, 0x6c, + 0x86, 0xc4, 0x17, 0x6c, 0x0a, 0xc8, 0x76, 0x35, 0x1d, 0x10, 0x62, 0xd9, + 0xc2, 0x70, 0xd5, 0x48, 0xc8, 0xf4, 0xec, 0x39, 0xa4, 0x55, 0x6c, 0x66, + 0xe7, 0x6e, 0x50, 0x7f, 0xc5, 0xf2, 0x54, 0x0a, 0xbf, 0xa7, 0x7c, 0x17, + 0x8a, 0x9b, 0xae, 0x15, 0x34, 0x35, 0xa7, 0xca, 0xaa, 0x00, 0x8f, 0x36, + 0xb9, 0xca, 0xb2, 0x13, 0xec, 0xf5, 0xe1, 0x9a, 0x0f, 0x7b, 0x1e, 0x62, + 0xfb, 0x9a, 0x9c, 0x82, 0x23, 0xbb, 0x68, 0x9e, 0x85, 0x47, 0xb5, 0xec, + 0x91, 0x5b, 0x04, 0xa8, 0x5b, 0x2f, 0x53, 0xcc, 0xc7, 0x92, 0xdc, 0x0a, + 0x7a, 0x41, 0xd1, 0x72, 0xe6, 0xf5, 0x9f, 0x5b, 0x5e, 0x7c, 0x44, 0x03, + 0x50, 0xac, 0x6a, 0x72, 0xca, 0x9c, 0x06, 0x56, 0x2d, 0x4c, 0xf8, 0xc6, + 0x0e, 0x70, 0x87, 0x0a, 0x97, 0x83, 0x12, 0xe1, 0x9b, 0xf5, 0x4c, 0x24, + 0x81, 0xc5, 0x82, 0x29, 0x6b, 0x64, 0x55, 0x4b, 0xd8, 0x71, 0xac, 0xcc, + 0x8b, 0x25, 0x1a, 0x76, 0x17, 0xca, 0x5e, 0x5d, 0x2a, 0xad, 0xc1, 0x9d, + 0x48, 0x4d, 0x76, 0xbc, 0x38, 0x26, 0x84, 0x1f, 0x88, 0xfa, 0xd1, 0x49, + 0x1d, 0x80, 0x67, 0x92, 0x43, 0xe1, 0x52, 0x71, 0x97, 0xd0, 0x2a, 0x40, + 0x63, 0x48, 0xb2, 0x47, 0xae, 0x78, 0x61, 0x08, 0xe5, 0x40, 0x09, 0x75, + 0xa3, 0x8f, 0x39, 0x61, 0x75, 0x8a, 0xdc, 0x07, 0xce, 0x74, 0x0d, 0x8d, + 0x44, 0x2f, 0x15, 0x2f +}; +/* K = 36b3d1d36d1a8c41442b6fffd46bcd7977a306b53dcf7fa590538194 */ +static const uint8_t ac_dsa_vect84_out[] = { +/* R */ + 0x18, 0x23, 0xf0, 0xa8, 0x07, 0xfb, 0x9e, 0x71, 0xad, 0x69, 0xb8, 0xe9, + 0xfc, 0x67, 0x4c, 0xf7, 0x6f, 0x67, 0xc4, 0x2c, 0xad, 0xbe, 0xa6, 0xd3, + 0x4c, 0xf1, 0xf1, 0xcc, +/* S */ + 0x66, 0x7f, 0xc5, 0x7a, 0x44, 0xb2, 0x89, 0xfc, 0x34, 0xa1, 0x98, 0x55, + 0x61, 0x17, 0xaf, 0xd6, 0x96, 0xdc, 0xbd, 0x96, 0xbf, 0x1b, 0xaa, 0xcb, + 0x40, 0xd3, 0xf8, 0xb2 +}; +#define ac_dsa_vect85_prime ac_dsa_vect76_prime +#define ac_dsa_vect85_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect85_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect85_ptx[] = { +/* Msg */ + 0x68, 0x0d, 0x87, 0x8c, 0xa6, 0xee, 0xb8, 0x7e, 0x4a, 0xe1, 0x58, 0xdd, + 0xdc, 0x37, 0x32, 0x78, 0x40, 0x13, 0xeb, 0xb1, 0xda, 0x89, 0x40, 0x1a, + 0xcd, 0xd6, 0x10, 0x90, 0x89, 0xe5, 0x60, 0x1d, 0x69, 0x5f, 0x9e, 0x4e, + 0x6e, 0xbf, 0x16, 0x02, 0x6a, 0xa7, 0x46, 0xde, 0xe8, 0x0a, 0x01, 0x23, + 0x50, 0x33, 0xf2, 0x42, 0x07, 0x9a, 0xf1, 0xb7, 0xfa, 0x69, 0x65, 0xc8, + 0x7e, 0xae, 0x8b, 0x32, 0x91, 0xa0, 0x09, 0xe4, 0xf1, 0x9d, 0x5b, 0x8f, + 0x13, 0x94, 0xd8, 0x66, 0xe7, 0xc9, 0xb7, 0x20, 0x73, 0xa9, 0x56, 0x52, + 0xc0, 0xee, 0xd9, 0x8e, 0x94, 0x84, 0xa1, 0x5c, 0x92, 0x44, 0x76, 0x4d, + 0x8c, 0xba, 0xab, 0xd4, 0x9d, 0x24, 0xc2, 0x07, 0xc7, 0x05, 0x70, 0x3c, + 0xc3, 0x5e, 0xbf, 0xc7, 0x68, 0x3f, 0x4a, 0x0e, 0x6a, 0xbf, 0x23, 0xfa, + 0x07, 0x67, 0x83, 0x50, 0xa6, 0xa0, 0x0c, 0xde +}; +static const uint8_t ac_dsa_vect85_priv_val[] = { +/* X */ + 0x73, 0x8a, 0x8b, 0xfc, 0x47, 0x8e, 0x46, 0x2c, 0x4b, 0xef, 0x8d, 0x56, + 0x33, 0xe0, 0x79, 0x34, 0x75, 0x20, 0x65, 0x51, 0xbb, 0xdd, 0xd0, 0x85, + 0x07, 0xf0, 0x05, 0xf5 +}; +static const uint8_t ac_dsa_vect85_pub_val[] = { +/* Y */ + 0x51, 0x1a, 0x36, 0x08, 0xc4, 0xbd, 0xa7, 0xc8, 0x2d, 0x7d, 0x68, 0xa5, + 0xd3, 0x0b, 0xd4, 0xc7, 0x1e, 0x45, 0x7b, 0x0f, 0x32, 0x30, 0x27, 0xd6, + 0x01, 0xd6, 0x32, 0x4a, 0x94, 0x89, 0x3a, 0xb3, 0xd6, 0x28, 0x78, 0xb1, + 0x2d, 0x98, 0xc4, 0x4d, 0xcf, 0x30, 0xad, 0xab, 0x43, 0x52, 0xb7, 0x0f, + 0x4d, 0xaa, 0x77, 0x2d, 0xf6, 0xae, 0xd3, 0xc0, 0x75, 0x87, 0xe9, 0x6c, + 0x68, 0xf8, 0xa8, 0x47, 0xa3, 0x35, 0x05, 0x14, 0x81, 0xd5, 0x39, 0x03, + 0xd1, 0xd1, 0xae, 0x0c, 0xf9, 0x9a, 0x54, 0x38, 0x7b, 0x00, 0x16, 0x9a, + 0x1c, 0x97, 0x04, 0xbb, 0x62, 0xf1, 0xd9, 0x80, 0x47, 0xdb, 0xa8, 0xa0, + 0xfd, 0xda, 0x73, 0x4c, 0xd4, 0x16, 0x11, 0x58, 0x4d, 0x50, 0x55, 0x4a, + 0xd7, 0x78, 0x90, 0x72, 0x0c, 0x8a, 0xc2, 0x99, 0x32, 0x09, 0x7c, 0xf2, + 0xbb, 0x1a, 0x8d, 0x0d, 0xaf, 0x86, 0x63, 0x24, 0x1e, 0x23, 0x64, 0x0c, + 0xc3, 0x96, 0xf9, 0xe6, 0x87, 0x73, 0x48, 0xf0, 0x14, 0x07, 0x3f, 0x4f, + 0xdc, 0x5b, 0xeb, 0xd1, 0x15, 0xa0, 0xd7, 0x4c, 0x2c, 0xe8, 0x57, 0xe1, + 0x00, 0xae, 0x3d, 0xc0, 0x70, 0x7b, 0x95, 0xef, 0xfa, 0x4a, 0x2c, 0xd8, + 0x62, 0x9f, 0xdd, 0x9b, 0xce, 0x72, 0x09, 0x1c, 0x0e, 0x26, 0x12, 0xd2, + 0xb3, 0x03, 0x20, 0x42, 0x0f, 0x42, 0xec, 0xb0, 0x98, 0x6a, 0xc3, 0x28, + 0x92, 0x51, 0xb4, 0xae, 0x54, 0xe5, 0x1e, 0xd8, 0x3d, 0x01, 0x95, 0xde, + 0xda, 0x9d, 0x4e, 0x5b, 0x39, 0x8b, 0x03, 0x72, 0x13, 0xd2, 0xf8, 0xf0, + 0xff, 0xdb, 0xf7, 0x27, 0x21, 0x40, 0x85, 0x53, 0x4a, 0x32, 0x4d, 0x4f, + 0xef, 0xc1, 0x65, 0x36, 0x42, 0x03, 0x5e, 0xbd, 0xbe, 0x81, 0x67, 0xb1, + 0x50, 0xbd, 0x92, 0xb7, 0xcd, 0xf2, 0x76, 0xfc, 0xf5, 0xe0, 0xbf, 0xfc, + 0xe9, 0x56, 0xa4, 0x7e +}; +/* K = 58d8b64bc8c2da02a294e9db46bfefb273e74870651e19d6cd017c55 */ +static const uint8_t ac_dsa_vect85_out[] = { +/* R */ + 0x7c, 0xeb, 0x71, 0x48, 0x0b, 0x5a, 0x71, 0x33, 0x40, 0x1b, 0x52, 0x27, + 0xfa, 0x22, 0x53, 0x33, 0x2e, 0x04, 0xf7, 0x8e, 0xa5, 0xd0, 0xfe, 0x23, + 0x7c, 0x85, 0x25, 0xd1, +/* S */ + 0x48, 0x48, 0x00, 0xe8, 0x1f, 0x7b, 0x56, 0x92, 0xb7, 0x9e, 0xb2, 0x1a, + 0xc2, 0xff, 0xf8, 0x3c, 0x49, 0xc9, 0xf0, 0xd4, 0x09, 0xc7, 0x56, 0xc7, + 0x3f, 0xbd, 0xd2, 0xf0 +}; +#define ac_dsa_vect86_prime ac_dsa_vect76_prime +#define ac_dsa_vect86_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect86_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect86_ptx[] = { +/* Msg */ + 0x69, 0x7f, 0x9e, 0xfc, 0x86, 0x53, 0xfe, 0xdb, 0x89, 0x8c, 0x77, 0xf9, + 0x0f, 0x12, 0x4b, 0xea, 0x5c, 0x3b, 0x89, 0x3c, 0x49, 0xd7, 0xf1, 0xb1, + 0x16, 0x47, 0x9e, 0x83, 0xd3, 0x5c, 0xb6, 0xc3, 0x94, 0x07, 0x97, 0x50, + 0x1e, 0x7f, 0x52, 0x88, 0x7d, 0x18, 0xae, 0x9f, 0x40, 0x55, 0xe1, 0xbd, + 0xd1, 0x24, 0xb5, 0x72, 0xf7, 0xa6, 0xfa, 0xd1, 0x01, 0xf5, 0x8b, 0x52, + 0xb3, 0x0c, 0xa3, 0x0d, 0x97, 0x43, 0xa9, 0x01, 0x6a, 0xf8, 0x91, 0x89, + 0x6d, 0x25, 0x35, 0x6e, 0x44, 0xf9, 0x82, 0xd4, 0x06, 0xea, 0x26, 0xa9, + 0xb2, 0x5f, 0xc4, 0xf9, 0x03, 0x09, 0x2d, 0x7e, 0x8e, 0x87, 0x13, 0x77, + 0x4a, 0x8b, 0xe7, 0xaa, 0xac, 0x93, 0xa6, 0x94, 0x2c, 0x1f, 0x2c, 0x48, + 0xe9, 0xde, 0xa6, 0x49, 0x84, 0xae, 0x54, 0xf7, 0xef, 0x99, 0x96, 0x1b, + 0xfd, 0x9b, 0x8d, 0x93, 0x22, 0x6a, 0xf7, 0x76 +}; +static const uint8_t ac_dsa_vect86_priv_val[] = { +/* X */ + 0x55, 0x0c, 0x87, 0x55, 0x23, 0x78, 0x57, 0xa0, 0xc8, 0xfc, 0x8a, 0x63, + 0x52, 0x5d, 0x40, 0x25, 0x71, 0x3b, 0x89, 0xbd, 0xb1, 0x27, 0xd1, 0xc3, + 0x30, 0xc3, 0x32, 0x4a +}; +static const uint8_t ac_dsa_vect86_pub_val[] = { +/* Y */ + 0x64, 0xb5, 0x88, 0x49, 0x9c, 0x9d, 0xb3, 0xe5, 0x86, 0x41, 0x92, 0x46, + 0x4d, 0x32, 0xfa, 0x35, 0x47, 0xf6, 0x48, 0xfe, 0x67, 0x6c, 0x15, 0x0a, + 0x8f, 0x9e, 0x15, 0x3c, 0x5a, 0xf5, 0x79, 0x25, 0xc7, 0x6d, 0xda, 0x4b, + 0x41, 0x9d, 0x60, 0xb2, 0x2f, 0xa5, 0xcd, 0xea, 0x0f, 0xb6, 0xf0, 0xb8, + 0x47, 0x9c, 0x98, 0x8a, 0x32, 0x4d, 0x27, 0x5b, 0xd4, 0x2e, 0xf1, 0x0d, + 0x89, 0x98, 0xc3, 0x60, 0x39, 0xeb, 0x40, 0x21, 0xfc, 0x0d, 0x27, 0x88, + 0xb5, 0x9a, 0x75, 0xcf, 0x25, 0xed, 0x6e, 0xe4, 0xd4, 0x48, 0x82, 0xb0, + 0xc5, 0xc5, 0xcb, 0x8d, 0xcc, 0x10, 0x02, 0xc0, 0xba, 0xa4, 0x79, 0x81, + 0x07, 0xe0, 0xb5, 0x7c, 0xd2, 0x6d, 0xeb, 0xbc, 0xd0, 0xba, 0x41, 0xd1, + 0xb1, 0xb8, 0x60, 0xb8, 0xeb, 0x90, 0xf6, 0xf3, 0x05, 0x00, 0xb2, 0xe4, + 0xbe, 0x7a, 0x00, 0xb6, 0x7d, 0x93, 0xc8, 0x7d, 0x3f, 0xf7, 0xa6, 0xce, + 0x53, 0xb9, 0x77, 0xa9, 0x30, 0x99, 0x98, 0x07, 0xfc, 0xbe, 0xf5, 0x7d, + 0x8d, 0xc6, 0x7a, 0x8f, 0x36, 0x61, 0x24, 0x99, 0x13, 0x89, 0x32, 0x8c, + 0xe7, 0xe7, 0x0f, 0x9e, 0x5c, 0x22, 0xff, 0xde, 0xdb, 0x28, 0x49, 0x82, + 0x82, 0xb4, 0xa9, 0xa9, 0xc6, 0x85, 0x34, 0xa2, 0x38, 0x32, 0x2e, 0x0d, + 0xb6, 0x08, 0x8e, 0xd0, 0xaf, 0xa8, 0xbc, 0x77, 0xce, 0x99, 0x8c, 0x81, + 0x44, 0x71, 0xab, 0x56, 0x76, 0x7b, 0x35, 0xd0, 0x7b, 0x94, 0x29, 0x0e, + 0xa1, 0x06, 0xff, 0x0c, 0x99, 0x8b, 0x51, 0xf0, 0x22, 0x22, 0x73, 0x8e, + 0xf9, 0x30, 0x1f, 0x29, 0x0c, 0x6b, 0x48, 0x5d, 0xbc, 0x4f, 0x12, 0xb4, + 0x72, 0xa1, 0x19, 0x2f, 0xd9, 0x3f, 0x2d, 0x23, 0x52, 0x7a, 0x02, 0xd9, + 0x5a, 0xf0, 0xb4, 0x22, 0xbe, 0x76, 0x40, 0xa9, 0x70, 0x2e, 0xca, 0xac, + 0x26, 0xc9, 0xe0, 0x04 +}; +/* K = 0b4329f9e5ac4a117689883db2ca8e968d30a3aced61e27ba27c6242 */ +static const uint8_t ac_dsa_vect86_out[] = { +/* R */ + 0x62, 0x05, 0x4d, 0x11, 0x52, 0x9b, 0x99, 0x3a, 0x6f, 0x19, 0xa0, 0xd5, + 0x48, 0x1b, 0x99, 0xb4, 0xb4, 0x46, 0x1a, 0x49, 0x86, 0x6c, 0x29, 0x53, + 0x4a, 0x36, 0x1a, 0x8b, +/* S */ + 0x7a, 0x7f, 0xd0, 0x98, 0x2e, 0x4e, 0x21, 0x18, 0xd1, 0xa0, 0x69, 0x78, + 0x7a, 0x80, 0xb9, 0x02, 0x49, 0x34, 0x65, 0xf6, 0x62, 0x0a, 0x35, 0x5c, + 0x86, 0xa9, 0x48, 0x67 +}; +#define ac_dsa_vect87_prime ac_dsa_vect76_prime +#define ac_dsa_vect87_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect87_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect87_ptx[] = { +/* Msg */ + 0xd0, 0x80, 0xa7, 0xdf, 0xf1, 0xef, 0x20, 0xe3, 0x38, 0x32, 0xb9, 0x9c, + 0xf8, 0x3c, 0x6c, 0x91, 0x9c, 0x07, 0x62, 0x0b, 0xf6, 0x08, 0xe0, 0x80, + 0xaa, 0x30, 0x18, 0x31, 0xca, 0x61, 0x78, 0xe4, 0x4e, 0xf7, 0xa4, 0xc1, + 0x15, 0xe9, 0x3a, 0xb6, 0xd8, 0x77, 0xe9, 0x66, 0x52, 0x17, 0x16, 0x10, + 0xa5, 0x1d, 0x92, 0x7d, 0x20, 0x34, 0xf4, 0x2f, 0x28, 0x0f, 0xe8, 0x7d, + 0x7c, 0x17, 0x47, 0xc4, 0x80, 0xeb, 0xcc, 0xbf, 0x56, 0x5a, 0x15, 0x0f, + 0x32, 0x40, 0xf6, 0xd4, 0xce, 0x5d, 0x6e, 0xb0, 0xb2, 0xe9, 0x64, 0x41, + 0x67, 0x91, 0x37, 0x6e, 0xd2, 0x2b, 0x35, 0x59, 0xcf, 0x93, 0xa0, 0x19, + 0x67, 0x6e, 0x9e, 0x0b, 0xe3, 0xc8, 0xd3, 0x4f, 0x0e, 0x0d, 0x11, 0x52, + 0xec, 0x6c, 0x32, 0x6d, 0x3d, 0xbf, 0x1d, 0x33, 0x03, 0xbe, 0xad, 0xd1, + 0x88, 0xc3, 0xaa, 0x0d, 0x77, 0xe8, 0xa1, 0x17 +}; +static const uint8_t ac_dsa_vect87_priv_val[] = { +/* X */ + 0x21, 0x71, 0xd5, 0xe7, 0xcd, 0xda, 0x9a, 0x69, 0x1d, 0xd2, 0x7f, 0x05, + 0x24, 0xf2, 0x4c, 0xa4, 0x1d, 0x5d, 0x80, 0x1e, 0xb2, 0xab, 0x0d, 0xcd, + 0xbe, 0x60, 0x14, 0xad +}; +static const uint8_t ac_dsa_vect87_pub_val[] = { +/* Y */ + 0x41, 0x76, 0x7c, 0xe2, 0x6c, 0x78, 0x0e, 0x3f, 0x20, 0x19, 0xf5, 0xa4, + 0x9a, 0x70, 0x15, 0x70, 0x14, 0x8e, 0x9f, 0xf3, 0x38, 0x22, 0x03, 0x83, + 0x3d, 0x1b, 0x18, 0xe9, 0xd8, 0xd6, 0xa0, 0x0c, 0x0b, 0x22, 0x58, 0xf2, + 0xe5, 0x67, 0xdb, 0x31, 0xad, 0x4e, 0x8c, 0xfb, 0x26, 0x21, 0x79, 0x4b, + 0xac, 0x87, 0xd9, 0xb3, 0xb5, 0x3b, 0x79, 0x19, 0x9a, 0x77, 0x50, 0x58, + 0xfe, 0xbc, 0x19, 0x0d, 0x00, 0xad, 0xed, 0xae, 0x0f, 0xd3, 0x02, 0x12, + 0x91, 0xbc, 0x2d, 0x1f, 0xf0, 0x50, 0x8b, 0xf0, 0x19, 0xec, 0xa0, 0xc5, + 0x73, 0xfd, 0x86, 0x37, 0x22, 0xf3, 0x67, 0xd5, 0xd0, 0x2b, 0xd9, 0xfa, + 0x0d, 0x07, 0xf7, 0x54, 0x06, 0xac, 0x20, 0x4f, 0xd3, 0xa5, 0xca, 0x16, + 0x32, 0x5c, 0x66, 0x1f, 0xe8, 0x54, 0xfd, 0x00, 0xfb, 0x26, 0x65, 0x47, + 0x52, 0xfe, 0xbb, 0xe4, 0x39, 0x09, 0x6d, 0xd2, 0x28, 0x4d, 0x5a, 0xb1, + 0x3d, 0xe9, 0xeb, 0x00, 0x48, 0x47, 0xd1, 0xd8, 0x59, 0x9f, 0xee, 0x68, + 0x7c, 0xb2, 0xec, 0xd0, 0xe5, 0xb7, 0x61, 0xd9, 0x1a, 0x7e, 0x9c, 0x58, + 0xe6, 0x92, 0x1f, 0x10, 0x30, 0x24, 0x21, 0x5e, 0x74, 0xf3, 0xde, 0x3c, + 0xc1, 0x2f, 0x5e, 0xd7, 0x70, 0x3d, 0xef, 0x04, 0x1d, 0xd3, 0x26, 0x7f, + 0x1c, 0xde, 0x0d, 0x4f, 0xda, 0x8d, 0xd5, 0xcc, 0xc9, 0xc0, 0x7b, 0x65, + 0xde, 0x59, 0x48, 0x2c, 0x47, 0x84, 0xb4, 0xf6, 0xfa, 0x85, 0x66, 0x71, + 0x86, 0xe2, 0xdf, 0x6c, 0x5d, 0xc8, 0xb4, 0x95, 0xbe, 0x8e, 0xc6, 0x13, + 0x79, 0xf2, 0x09, 0x23, 0x57, 0x6f, 0x17, 0x68, 0x0c, 0x4d, 0xab, 0x99, + 0x31, 0x2d, 0x0b, 0x64, 0x41, 0x30, 0x6a, 0xe7, 0x17, 0xc9, 0x5d, 0x3f, + 0x35, 0x2b, 0xa4, 0xc0, 0x96, 0xf0, 0x1d, 0x14, 0xa7, 0xdc, 0x05, 0xb2, + 0x8b, 0xa9, 0xa3, 0xca +}; +/* K = 0f6626008e50c19def9bd694c00522cc861eb7069d55892e08ddff58 */ +static const uint8_t ac_dsa_vect87_out[] = { +/* R */ + 0x44, 0xe7, 0x0d, 0x2e, 0xad, 0x3c, 0x51, 0xdd, 0x0c, 0x54, 0x61, 0xdd, + 0x41, 0x86, 0x82, 0x5e, 0x23, 0xb4, 0xe7, 0x51, 0xd8, 0xab, 0x17, 0xd0, + 0xb7, 0xed, 0xfa, 0xac, +/* S */ + 0x48, 0xff, 0xad, 0xe2, 0x75, 0x31, 0xdb, 0x47, 0x8f, 0x22, 0xfa, 0x0e, + 0xc9, 0x2b, 0xcf, 0xd2, 0xff, 0xeb, 0x6d, 0xb6, 0x77, 0x15, 0xdc, 0xdc, + 0x79, 0xbc, 0xb0, 0x28 +}; +#define ac_dsa_vect88_prime ac_dsa_vect76_prime +#define ac_dsa_vect88_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect88_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect88_ptx[] = { +/* Msg */ + 0xf6, 0xa9, 0xaf, 0xe2, 0x41, 0xdd, 0x98, 0x4e, 0x3b, 0xc2, 0x65, 0x78, + 0x7d, 0xcc, 0x49, 0x49, 0x1b, 0x3b, 0xca, 0x67, 0xfe, 0xef, 0x32, 0xfc, + 0x1e, 0x07, 0xfd, 0xaf, 0x0a, 0xf6, 0xc5, 0xd0, 0x6d, 0xcc, 0xb4, 0x7c, + 0xdb, 0x69, 0x07, 0x51, 0x1c, 0xb3, 0x0c, 0x10, 0x9f, 0x62, 0xe6, 0x67, + 0x18, 0xc5, 0xc4, 0xbb, 0x43, 0xd4, 0xb0, 0x0b, 0x51, 0x23, 0x5d, 0xf4, + 0x32, 0x23, 0xd6, 0x0c, 0xe1, 0xf9, 0xbe, 0x34, 0x93, 0xa4, 0xdc, 0xb0, + 0x2e, 0x25, 0xed, 0x3d, 0xda, 0xe1, 0x0d, 0x13, 0x1b, 0x48, 0x1a, 0x61, + 0xae, 0xf3, 0x34, 0xb6, 0x90, 0xc7, 0xa1, 0xec, 0x74, 0x86, 0x59, 0x54, + 0xb3, 0x9c, 0xcf, 0xa7, 0xa5, 0x1a, 0x9a, 0x1e, 0x62, 0xe6, 0x54, 0xbb, + 0x89, 0x27, 0x0c, 0x77, 0x4f, 0x08, 0x2a, 0xdf, 0x09, 0xb5, 0x79, 0xc8, + 0x35, 0x8d, 0xac, 0xb9, 0xdb, 0x7c, 0xa1, 0xc2 +}; +static const uint8_t ac_dsa_vect88_priv_val[] = { +/* X */ + 0x77, 0x20, 0x7c, 0xf0, 0x96, 0x3f, 0x1e, 0x96, 0x1c, 0x35, 0x39, 0xd7, + 0xd0, 0xf6, 0x78, 0xfc, 0xe5, 0x17, 0xf6, 0x7b, 0x72, 0x8b, 0xf1, 0x5e, + 0x0c, 0xab, 0x3a, 0xe6 +}; +static const uint8_t ac_dsa_vect88_pub_val[] = { +/* Y */ + 0xb4, 0x13, 0x8f, 0xa4, 0xe1, 0xdc, 0x67, 0x72, 0xb4, 0x7e, 0x5a, 0x3e, + 0xd1, 0x30, 0xa1, 0x3b, 0x82, 0x23, 0x94, 0xc3, 0xce, 0x8a, 0x01, 0x93, + 0xd1, 0xdd, 0xe4, 0xc9, 0x0e, 0x7d, 0xa1, 0x17, 0x8e, 0x11, 0x26, 0xdd, + 0x29, 0x62, 0x52, 0xfa, 0x7d, 0x2f, 0x13, 0x9a, 0x14, 0x8a, 0xc4, 0x4d, + 0xc0, 0x6a, 0x05, 0x8b, 0x84, 0xec, 0xb0, 0x3a, 0xd8, 0x27, 0xe6, 0x68, + 0x92, 0xe8, 0x55, 0x29, 0xc3, 0x62, 0xce, 0xac, 0x2e, 0x71, 0x04, 0xb7, + 0x97, 0xb2, 0xe9, 0x82, 0x60, 0x54, 0xde, 0x35, 0x05, 0x96, 0xab, 0x58, + 0x17, 0x65, 0xe9, 0xa5, 0xc9, 0xff, 0x51, 0x43, 0x33, 0x2c, 0x2f, 0x3b, + 0xfd, 0x24, 0x9a, 0x87, 0xfe, 0x1e, 0x30, 0xef, 0xd6, 0xfc, 0x05, 0x7e, + 0x23, 0x4a, 0x1c, 0xd4, 0xc1, 0x9e, 0x07, 0x2b, 0xd7, 0x1b, 0x32, 0xd5, + 0x5e, 0xf1, 0x22, 0xea, 0x93, 0x09, 0x11, 0x08, 0x1e, 0x26, 0xd9, 0x98, + 0x49, 0x03, 0x76, 0xe3, 0xb7, 0x21, 0xcc, 0x32, 0xfe, 0xd9, 0x2b, 0x82, + 0xd5, 0x45, 0xa7, 0xe6, 0xba, 0x6e, 0x4e, 0xb4, 0x34, 0x06, 0x3c, 0x87, + 0xdb, 0x84, 0x8d, 0xf4, 0xef, 0x02, 0xed, 0xa3, 0xfd, 0xf4, 0xf9, 0xd2, + 0x90, 0x5b, 0x78, 0xf7, 0xb1, 0x6b, 0x5e, 0xa0, 0xb5, 0x99, 0x8f, 0x1f, + 0xbb, 0x0a, 0xaf, 0x62, 0xa1, 0x73, 0x55, 0x91, 0x60, 0x0f, 0x98, 0x01, + 0x97, 0x7b, 0x1b, 0x94, 0x7f, 0x61, 0xa9, 0x1f, 0xf2, 0xaf, 0xb8, 0x72, + 0x7c, 0x55, 0x26, 0x89, 0x72, 0xc8, 0x72, 0x16, 0xaa, 0xe9, 0x00, 0x61, + 0x7a, 0x56, 0xf5, 0x35, 0xed, 0x18, 0xc4, 0xc5, 0xdd, 0xf8, 0xd7, 0xa5, + 0x44, 0x63, 0x25, 0x6d, 0x09, 0x14, 0x4d, 0x88, 0x9c, 0x14, 0x9e, 0x5b, + 0x09, 0xbd, 0xd9, 0xd8, 0x50, 0x93, 0x14, 0xb1, 0x03, 0xb8, 0x46, 0xf3, + 0xe6, 0xfa, 0x1b, 0xb2 +}; +/* K = 57585204d88d73c21f66a150991531973978dfeaedd8024e268f18d5 */ +static const uint8_t ac_dsa_vect88_out[] = { +/* R */ + 0x55, 0x5a, 0x45, 0x48, 0x80, 0x08, 0x4f, 0x6c, 0xb2, 0x52, 0x2d, 0xaf, + 0x33, 0x99, 0xfb, 0x4a, 0x50, 0x1a, 0x94, 0x3a, 0x9b, 0x6a, 0xac, 0xd5, + 0x8e, 0x2c, 0x7d, 0x37, +/* S */ + 0x73, 0x0f, 0xed, 0xb3, 0xa5, 0x91, 0x18, 0x44, 0x14, 0x60, 0x98, 0xac, + 0x56, 0x03, 0xe2, 0xba, 0xaa, 0xe7, 0x69, 0x62, 0xb3, 0x3a, 0x32, 0x7b, + 0x50, 0x42, 0x0a, 0x50 +}; +#define ac_dsa_vect89_prime ac_dsa_vect76_prime +#define ac_dsa_vect89_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect89_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect89_ptx[] = { +/* Msg */ + 0x2d, 0x1c, 0x57, 0x3b, 0xf3, 0x24, 0x02, 0x8d, 0xc2, 0xfe, 0x00, 0x92, + 0x8f, 0x55, 0xf7, 0xfa, 0xc7, 0x90, 0x37, 0xd4, 0xd9, 0x9e, 0xb1, 0x85, + 0xf3, 0xb9, 0x97, 0xe0, 0x42, 0xcd, 0xf8, 0x08, 0xb5, 0x38, 0x2d, 0x50, + 0xa6, 0xaa, 0x80, 0x85, 0xc5, 0xd1, 0x95, 0x8e, 0x67, 0x28, 0x3d, 0xf6, + 0x69, 0x86, 0xb9, 0x34, 0x71, 0xc1, 0x2e, 0x30, 0x45, 0xba, 0x14, 0x6e, + 0xd5, 0x96, 0x5c, 0x8a, 0xc5, 0xb4, 0x46, 0x68, 0xf6, 0x19, 0x84, 0xd2, + 0x17, 0x36, 0xcf, 0x1c, 0x27, 0x67, 0x54, 0xb8, 0x48, 0xe9, 0xfa, 0x63, + 0x6b, 0x63, 0x15, 0xb2, 0x27, 0x2c, 0x19, 0xe6, 0x56, 0x26, 0xbf, 0x8b, + 0x12, 0x14, 0xd7, 0x09, 0x89, 0xa6, 0x23, 0xb5, 0xff, 0xf7, 0x80, 0x3d, + 0x28, 0xa6, 0x63, 0xbb, 0xbb, 0xeb, 0xb8, 0x4c, 0x83, 0x9b, 0x42, 0x72, + 0x0f, 0xd0, 0xe6, 0x22, 0x46, 0xb3, 0xb0, 0x34 +}; +static const uint8_t ac_dsa_vect89_priv_val[] = { +/* X */ + 0x78, 0x93, 0x75, 0x05, 0x5f, 0x94, 0xb9, 0xad, 0xe4, 0x0b, 0x0a, 0xf8, + 0xf7, 0x06, 0x40, 0x33, 0x6f, 0x5d, 0xe2, 0x13, 0x57, 0x1c, 0xa1, 0xc6, + 0x45, 0xca, 0x46, 0x8f +}; +static const uint8_t ac_dsa_vect89_pub_val[] = { +/* Y */ + 0x5c, 0xcd, 0xca, 0x35, 0x55, 0x1c, 0xf3, 0x55, 0xec, 0x85, 0xdb, 0x8d, + 0x68, 0x01, 0x0d, 0xed, 0x63, 0x58, 0x32, 0x55, 0xb1, 0xd5, 0xfd, 0x2a, + 0x52, 0x2e, 0x29, 0x51, 0x3a, 0xd3, 0xce, 0x61, 0x57, 0xbe, 0x30, 0xea, + 0x1c, 0x30, 0x5d, 0x87, 0xde, 0x6c, 0x27, 0xfb, 0xe3, 0xa3, 0xfa, 0x50, + 0x07, 0x12, 0x82, 0x75, 0xd6, 0xe6, 0x18, 0x3a, 0x65, 0xce, 0xc5, 0xb6, + 0x94, 0xbc, 0x6c, 0x02, 0x73, 0x35, 0x06, 0x6e, 0x01, 0x27, 0x3f, 0xd6, + 0x98, 0x1c, 0xc5, 0xf6, 0x0c, 0x3e, 0x33, 0x75, 0x13, 0x86, 0xce, 0x79, + 0x2c, 0xcb, 0x6e, 0x6a, 0x6d, 0xb5, 0xd7, 0xf0, 0x73, 0x80, 0x03, 0x29, + 0xf9, 0xcc, 0x46, 0xd1, 0x9f, 0x42, 0x29, 0x23, 0xb9, 0x74, 0x8d, 0xcc, + 0xa4, 0x97, 0x1e, 0x43, 0xa9, 0xd1, 0xf5, 0x9d, 0x1c, 0x74, 0x97, 0x88, + 0xa8, 0x52, 0x7a, 0xd5, 0x24, 0xdf, 0x74, 0x15, 0x0b, 0x39, 0xea, 0xfa, + 0x7f, 0x4d, 0x56, 0x08, 0xd1, 0xc9, 0x72, 0x55, 0x65, 0x44, 0x56, 0xea, + 0xdd, 0x4d, 0x38, 0x2a, 0xc5, 0x4f, 0xdd, 0x12, 0x53, 0x8b, 0x2f, 0x2e, + 0xf7, 0x5a, 0x50, 0x98, 0x01, 0x71, 0xa0, 0x4d, 0x40, 0x54, 0xb4, 0xcd, + 0x79, 0xc7, 0x1e, 0x1c, 0x4d, 0xeb, 0x3b, 0xc6, 0xaf, 0x4c, 0x87, 0x4f, + 0x5c, 0xf0, 0x27, 0x38, 0x96, 0xd4, 0xfd, 0xc5, 0x84, 0x7f, 0xef, 0xdc, + 0xc9, 0x7f, 0x54, 0x02, 0xc7, 0xe7, 0x64, 0x84, 0xd3, 0xd2, 0xd7, 0x0a, + 0xc1, 0x6b, 0xda, 0x41, 0x99, 0x6c, 0xad, 0xcd, 0x83, 0xad, 0x92, 0xcb, + 0x37, 0xc0, 0xc1, 0xe9, 0xd6, 0x4f, 0xa1, 0xab, 0xd9, 0xa2, 0xcf, 0x00, + 0x5c, 0x2c, 0x29, 0xa1, 0x73, 0x7c, 0xdd, 0x6d, 0x63, 0xaa, 0x2f, 0xda, + 0xa5, 0x60, 0x79, 0x9b, 0x9f, 0x07, 0xd4, 0x48, 0x76, 0x06, 0x78, 0x47, + 0x76, 0x29, 0xf2, 0x2f +}; +/* K = 325b1562d5c9c61f95e6944fb12a4bb08d227c4dc0c8e9a79e391b08 */ +static const uint8_t ac_dsa_vect89_out[] = { +/* R */ + 0x7b, 0xf3, 0xc0, 0xc5, 0x47, 0xe2, 0x18, 0x46, 0x21, 0x2b, 0xf4, 0xcf, + 0x3e, 0x38, 0x36, 0x2d, 0xd4, 0xd3, 0x59, 0xb7, 0xaf, 0x64, 0x20, 0xf9, + 0x0d, 0xa5, 0x79, 0x07, +/* S */ + 0x5e, 0xbd, 0x5d, 0x2d, 0x88, 0xca, 0xe4, 0x0b, 0x37, 0xa9, 0xa5, 0xa8, + 0x4e, 0x62, 0x18, 0xd2, 0x45, 0x3a, 0xfa, 0x14, 0x6c, 0x79, 0xa5, 0xd5, + 0xf5, 0xdf, 0x44, 0xf4 +}; +#define ac_dsa_vect90_prime ac_dsa_vect76_prime +#define ac_dsa_vect90_sub_prime ac_dsa_vect76_sub_prime +#define ac_dsa_vect90_base ac_dsa_vect76_base +static const uint8_t ac_dsa_vect90_ptx[] = { +/* Msg */ + 0xba, 0xb4, 0xdb, 0x55, 0xbf, 0x6d, 0x3a, 0xbe, 0xfd, 0x1b, 0xb4, 0xe0, + 0xf7, 0xbc, 0xec, 0x65, 0xee, 0x6c, 0x6d, 0x8e, 0xb0, 0x4b, 0x7c, 0x48, + 0x0d, 0xf4, 0xe9, 0xe3, 0x91, 0x50, 0xf1, 0x0c, 0x38, 0xf1, 0xab, 0xb6, + 0x3d, 0xfe, 0x1b, 0xb9, 0x75, 0x5c, 0x41, 0xb3, 0x89, 0x55, 0xba, 0x38, + 0xba, 0x93, 0x8b, 0x6c, 0xee, 0xdf, 0xec, 0x02, 0x00, 0x1f, 0xa8, 0x70, + 0x07, 0x0c, 0x59, 0xdf, 0x1f, 0xd2, 0xd7, 0x2a, 0x81, 0x41, 0x04, 0xc5, + 0x14, 0x33, 0x76, 0xa3, 0x13, 0x6b, 0x81, 0x18, 0xf7, 0xb4, 0x7b, 0xd1, + 0xff, 0xab, 0x53, 0x35, 0x9e, 0x53, 0xf9, 0x5c, 0x66, 0xee, 0x12, 0x70, + 0x5e, 0x31, 0xa4, 0x62, 0xa8, 0xca, 0xae, 0x48, 0x15, 0x56, 0xce, 0xff, + 0x60, 0x7c, 0xcc, 0x8b, 0xf1, 0x45, 0x07, 0x72, 0xcd, 0x68, 0x08, 0x1d, + 0x3f, 0x15, 0xa7, 0x10, 0xe6, 0x56, 0xae, 0x56 +}; +static const uint8_t ac_dsa_vect90_priv_val[] = { +/* X */ + 0x6f, 0x4a, 0x94, 0xc9, 0x25, 0x4a, 0x55, 0x77, 0x87, 0xde, 0x9a, 0xfa, + 0x08, 0x21, 0x54, 0x14, 0xdb, 0x5a, 0x0d, 0xbc, 0x67, 0xc6, 0x6c, 0xde, + 0x1c, 0x1e, 0x6f, 0x04 +}; +static const uint8_t ac_dsa_vect90_pub_val[] = { +/* Y */ + 0x53, 0xc0, 0xb0, 0xb0, 0x26, 0x9f, 0xcf, 0x29, 0x48, 0x66, 0x7e, 0x28, + 0xb1, 0x1c, 0xcd, 0xa9, 0xcb, 0xb9, 0x27, 0x54, 0x63, 0xf2, 0x1e, 0xe3, + 0x0d, 0xa3, 0x3c, 0x45, 0x75, 0xbe, 0x5e, 0x11, 0x1a, 0x18, 0x2a, 0x6f, + 0x38, 0xb8, 0x90, 0xf2, 0x0b, 0x8f, 0x2d, 0x22, 0x4f, 0x59, 0x81, 0x89, + 0x53, 0x10, 0xdb, 0x7c, 0x47, 0x03, 0xc1, 0xce, 0xc2, 0xb2, 0x57, 0xf4, + 0x52, 0xd9, 0x64, 0xbe, 0x50, 0xc0, 0x14, 0xb7, 0x52, 0x36, 0x0e, 0xe2, + 0x4f, 0x2f, 0xe1, 0xbc, 0xc0, 0x23, 0x47, 0x7a, 0x2d, 0x70, 0x85, 0xf5, + 0x82, 0x14, 0xdf, 0x86, 0x6b, 0x13, 0xa8, 0xd8, 0xaf, 0x91, 0x31, 0x46, + 0xdc, 0x0b, 0xee, 0x07, 0x8a, 0xea, 0x1c, 0xe6, 0x45, 0x99, 0x9b, 0x57, + 0x94, 0x98, 0xea, 0xe9, 0x27, 0x7e, 0xd7, 0xe8, 0xb2, 0xc7, 0x5f, 0x49, + 0x4e, 0xfa, 0xa7, 0x3a, 0x97, 0x3f, 0x32, 0x23, 0x2f, 0x08, 0xce, 0x7f, + 0x0a, 0xfc, 0xba, 0x31, 0x66, 0x23, 0xb9, 0x41, 0x58, 0xde, 0x39, 0xbd, + 0x4c, 0x0d, 0x51, 0x32, 0x34, 0xee, 0x1a, 0x48, 0x1d, 0x5b, 0x72, 0xf4, + 0xee, 0xa3, 0x77, 0x49, 0xb4, 0x0f, 0xff, 0x12, 0xab, 0x62, 0x0f, 0x11, + 0xaa, 0xa0, 0x1e, 0x35, 0x58, 0xe7, 0xa4, 0xc5, 0x50, 0x70, 0x7b, 0x71, + 0xc1, 0x6c, 0xb8, 0xcd, 0xa9, 0x8f, 0x46, 0xbf, 0x71, 0x76, 0x9a, 0x47, + 0x6c, 0x33, 0x85, 0xa8, 0xca, 0xf7, 0xc8, 0x86, 0xae, 0x47, 0xd2, 0x28, + 0xb1, 0x77, 0x1a, 0x8b, 0xd4, 0xb7, 0xf1, 0x9e, 0x6f, 0x53, 0x04, 0x7f, + 0x62, 0xf0, 0x29, 0xc3, 0x39, 0xfe, 0x75, 0x75, 0xbe, 0x93, 0x08, 0x0a, + 0xc7, 0x48, 0x28, 0x91, 0x49, 0xa5, 0x7a, 0x0d, 0xdc, 0xed, 0x54, 0xd7, + 0x2f, 0x6d, 0x4d, 0x34, 0x4f, 0xb8, 0x74, 0xcc, 0xc8, 0x5e, 0xa7, 0xf3, + 0xdd, 0x21, 0x64, 0xdf +}; +/* K = 14fe2a5a75756885240ff29abd19d346b2e7e5dfa76d2430f0d069d6 */ +static const uint8_t ac_dsa_vect90_out[] = { +/* R */ + 0x11, 0x8d, 0x22, 0x27, 0xbe, 0x4b, 0xd9, 0x1e, 0x98, 0xa2, 0xef, 0xde, + 0x15, 0x60, 0x9b, 0x2b, 0x91, 0x24, 0xb2, 0xe8, 0x3c, 0x27, 0x4b, 0x63, + 0x23, 0x00, 0x43, 0x2b, +/* S */ + 0x3a, 0x44, 0x74, 0x61, 0x94, 0x4b, 0x2a, 0x59, 0x27, 0x8a, 0x8e, 0x11, + 0x18, 0xb4, 0x06, 0xbd, 0x3f, 0xf4, 0x16, 0x77, 0x5d, 0x65, 0x53, 0x0e, + 0x54, 0xf9, 0xe6, 0x23 +}; +/* [mod = L=2048, N=224, SHA-224] */ +static const uint8_t ac_dsa_vect91_prime[] = { +/* P */ + 0xaa, 0x81, 0x5c, 0x9d, 0xb1, 0xc4, 0xd3, 0xd2, 0x77, 0x3c, 0x7d, 0x0d, + 0x4d, 0x1d, 0xa7, 0x5e, 0xcf, 0xc4, 0xa3, 0x9e, 0x97, 0xd5, 0xfa, 0x19, + 0x1f, 0xfe, 0xc8, 0xb1, 0x49, 0x0a, 0x29, 0x0c, 0xe3, 0x35, 0xe5, 0xce, + 0x87, 0xea, 0x62, 0x0a, 0x8a, 0x17, 0xde, 0x0b, 0xb6, 0x47, 0x14, 0xe2, + 0xec, 0x84, 0x0b, 0xf0, 0x0e, 0x6e, 0xbd, 0xb4, 0xff, 0xb4, 0xe3, 0x24, + 0xca, 0x07, 0xc3, 0xc8, 0x71, 0x73, 0x09, 0xaf, 0x14, 0x10, 0x36, 0x2a, + 0x77, 0x2c, 0x9a, 0xdd, 0x83, 0x8b, 0x2b, 0x0c, 0xae, 0x1e, 0x90, 0xab, + 0x44, 0x8a, 0xda, 0xbd, 0xac, 0xd2, 0xe5, 0xdf, 0x59, 0xc4, 0x18, 0x7a, + 0x32, 0xa2, 0x37, 0x19, 0xd6, 0xc5, 0x7e, 0x94, 0x00, 0x88, 0x53, 0x83, + 0xbf, 0x8f, 0x06, 0x6f, 0x23, 0xb9, 0x41, 0x92, 0x0d, 0x54, 0xc3, 0x5b, + 0x4f, 0x7c, 0xc5, 0x04, 0x4f, 0x3b, 0x40, 0xf1, 0x70, 0x46, 0x95, 0x63, + 0x07, 0xb7, 0x48, 0xe8, 0x40, 0x73, 0x28, 0x44, 0xd0, 0x0a, 0x9c, 0xe6, + 0xec, 0x57, 0x14, 0x29, 0x3b, 0x62, 0x65, 0x14, 0x7f, 0x15, 0xc6, 0x7f, + 0x4b, 0xe3, 0x8b, 0x08, 0x2b, 0x55, 0xfd, 0xea, 0xdb, 0x61, 0x24, 0x68, + 0x9f, 0xb7, 0x6f, 0x9d, 0x25, 0xcc, 0x28, 0xb8, 0xea, 0xa9, 0x8b, 0x56, + 0x2d, 0x5c, 0x10, 0x11, 0xe0, 0xdc, 0xf9, 0xb3, 0x99, 0x23, 0x24, 0x0d, + 0x33, 0x2d, 0x89, 0xdc, 0x96, 0x03, 0xb7, 0xbd, 0xdd, 0x0c, 0x70, 0xb8, + 0x3c, 0xaa, 0x29, 0x05, 0x63, 0x1b, 0x1c, 0x83, 0xca, 0xbb, 0xae, 0x6c, + 0x0c, 0x0c, 0x2e, 0xfe, 0x8f, 0x58, 0x13, 0x1e, 0xd8, 0x35, 0x1b, 0xf9, + 0x3e, 0x87, 0x5f, 0x6a, 0x73, 0xa9, 0x3c, 0xba, 0xd4, 0x70, 0x14, 0x1a, + 0x26, 0x87, 0xfb, 0xac, 0xf2, 0xd7, 0x1c, 0x8d, 0xde, 0xe9, 0x71, 0xad, + 0x66, 0x07, 0x29, 0xad +}; +static const uint8_t ac_dsa_vect91_sub_prime[] = { +/* Q */ + 0xea, 0x34, 0x7e, 0x90, 0xbe, 0x7c, 0x28, 0x75, 0xd1, 0xfe, 0x1d, 0xb6, + 0x22, 0xb4, 0x76, 0x38, 0x37, 0xc5, 0xe2, 0x7a, 0x60, 0x37, 0x31, 0x03, + 0x48, 0xc1, 0xaa, 0x11 +}; +static const uint8_t ac_dsa_vect91_base[] = { +/* G */ + 0x20, 0x42, 0x09, 0x4c, 0xcb, 0xc8, 0xb8, 0x72, 0x3f, 0xc9, 0x28, 0xc1, + 0x2f, 0xda, 0x67, 0x1b, 0x83, 0x29, 0x5e, 0x99, 0xc7, 0x43, 0x57, 0x6f, + 0x44, 0x50, 0x4b, 0xe1, 0x18, 0x63, 0x23, 0x31, 0x9b, 0x50, 0x02, 0xd2, + 0x4f, 0x17, 0x3d, 0xf9, 0x09, 0xea, 0x24, 0x1d, 0x6e, 0xa5, 0x28, 0x99, + 0x04, 0xee, 0x46, 0x36, 0x20, 0x4b, 0x2f, 0xbe, 0x94, 0xb0, 0x68, 0xfe, + 0x09, 0x3f, 0x79, 0x62, 0x57, 0x95, 0x49, 0x55, 0x1d, 0x3a, 0xf2, 0x19, + 0xad, 0x8e, 0xd1, 0x99, 0x39, 0xef, 0xf8, 0x6b, 0xce, 0xc8, 0x34, 0xde, + 0x2f, 0x2f, 0x78, 0x59, 0x6e, 0x89, 0xe7, 0xcb, 0x52, 0xc5, 0x24, 0xe1, + 0x77, 0x09, 0x8a, 0x56, 0xc2, 0x32, 0xeb, 0x1f, 0x56, 0x3a, 0xa8, 0x4b, + 0xc6, 0xb0, 0x26, 0xde, 0xee, 0x6f, 0xf5, 0x1c, 0xb4, 0x41, 0xe0, 0x80, + 0xf2, 0xda, 0xfa, 0xea, 0x1c, 0xed, 0x86, 0x42, 0x7d, 0x1c, 0x34, 0x6b, + 0xe5, 0x5c, 0x66, 0x80, 0x3d, 0x4b, 0x76, 0xd1, 0x33, 0xcd, 0x44, 0x5b, + 0x4c, 0x34, 0x82, 0xfa, 0x41, 0x50, 0x23, 0x46, 0x3c, 0x9b, 0xf3, 0x0f, + 0x2f, 0x78, 0x42, 0x23, 0xe2, 0x60, 0x57, 0xd3, 0xaa, 0x0d, 0x7f, 0xbb, + 0x66, 0x06, 0x30, 0xc5, 0x2e, 0x49, 0xd4, 0xa0, 0x32, 0x5c, 0x73, 0x89, + 0xe0, 0x72, 0xaa, 0x34, 0x9f, 0x13, 0xc9, 0x66, 0xe1, 0x59, 0x75, 0x2f, + 0xbb, 0x71, 0xe9, 0x33, 0x68, 0x90, 0xf9, 0x32, 0x43, 0xfa, 0x6e, 0x72, + 0xd2, 0x99, 0x36, 0x5e, 0xe5, 0xb3, 0xfe, 0x26, 0x6e, 0xbf, 0x11, 0x10, + 0x56, 0x8f, 0xee, 0x44, 0x25, 0xc8, 0x47, 0xb5, 0x02, 0x10, 0xbd, 0x48, + 0x4b, 0x97, 0x43, 0x1a, 0x42, 0x85, 0x6a, 0xdc, 0xa3, 0xe7, 0xd1, 0xa9, + 0xc9, 0xc6, 0x75, 0xc7, 0xe2, 0x66, 0x91, 0x83, 0x20, 0xdd, 0x5a, 0x78, + 0xa4, 0x8c, 0x48, 0xa9 +}; +static const uint8_t ac_dsa_vect91_ptx[] = { +/* Msg */ + 0xe9, 0x20, 0xfc, 0x16, 0x10, 0x71, 0x8f, 0x2b, 0x02, 0x13, 0xd3, 0x01, + 0xc0, 0x09, 0x2a, 0x51, 0xf3, 0xc6, 0xb0, 0x10, 0x7b, 0xbb, 0xd8, 0x24, + 0x3a, 0x96, 0x89, 0xc0, 0x44, 0xe2, 0xd1, 0x42, 0xf2, 0x02, 0xd9, 0xd1, + 0x95, 0xa5, 0xfa, 0xef, 0x4b, 0xe5, 0xac, 0xad, 0xc9, 0xff, 0x6f, 0x7d, + 0x22, 0x61, 0xe5, 0x8b, 0x51, 0x71, 0x39, 0xbc, 0xb9, 0x48, 0x9b, 0x11, + 0x04, 0x23, 0xc2, 0xe5, 0x9e, 0xb1, 0x81, 0x29, 0x4f, 0xfd, 0xae, 0x8a, + 0xad, 0x0e, 0x62, 0x4f, 0xab, 0x97, 0x4c, 0x97, 0xf9, 0xf5, 0xe7, 0xdc, + 0x19, 0xd6, 0x78, 0xa9, 0xcb, 0x34, 0x29, 0xcf, 0x05, 0xec, 0x50, 0x90, + 0x72, 0x85, 0x6f, 0x5a, 0xdf, 0xec, 0x6e, 0x29, 0xba, 0xfe, 0x8e, 0x5b, + 0xa9, 0x55, 0x93, 0xe6, 0x12, 0x84, 0x3e, 0x34, 0x31, 0x11, 0xd8, 0x8a, + 0x1e, 0xaf, 0xf7, 0xdc, 0x0a, 0x2e, 0x27, 0x7f +}; +static const uint8_t ac_dsa_vect91_priv_val[] = { +/* X */ + 0x7b, 0x48, 0x90, 0x21, 0x57, 0x8e, 0x79, 0xe7, 0xbd, 0x3e, 0xe7, 0xab, + 0x45, 0x6f, 0x65, 0x9f, 0x3d, 0xc0, 0x7c, 0x88, 0xf5, 0xc9, 0xa3, 0x9e, + 0x4f, 0x8c, 0xee, 0x81 +}; +static const uint8_t ac_dsa_vect91_pub_val[] = { +/* Y */ + 0x1a, 0xe1, 0x0c, 0x78, 0x6a, 0xd0, 0x90, 0x2c, 0x5c, 0x68, 0x5d, 0xae, + 0x5c, 0x71, 0x21, 0x41, 0x8a, 0x37, 0x7b, 0x88, 0x8b, 0x5f, 0x2f, 0x2b, + 0xc7, 0x66, 0x23, 0x57, 0x0f, 0xd6, 0x2b, 0xcb, 0x19, 0x0b, 0x47, 0x1a, + 0xd5, 0x35, 0x9c, 0x5f, 0x06, 0x2f, 0x88, 0x19, 0x28, 0x9e, 0x95, 0x6d, + 0x8a, 0xa6, 0xf9, 0x0d, 0x1f, 0x8c, 0xf1, 0xee, 0x72, 0xd3, 0xa1, 0xbd, + 0xfd, 0x56, 0xc4, 0x78, 0xdc, 0x29, 0xa1, 0x9c, 0x45, 0x69, 0xb5, 0xa6, + 0x0e, 0x3a, 0x8f, 0x34, 0xf6, 0x06, 0x56, 0xea, 0xc5, 0xb2, 0x5d, 0xde, + 0x55, 0x14, 0xa5, 0xc6, 0x7b, 0x67, 0x54, 0x23, 0x20, 0x4f, 0x6c, 0xca, + 0xf0, 0x99, 0x06, 0x17, 0xcc, 0x73, 0x55, 0xb9, 0xd3, 0xed, 0x86, 0x89, + 0x78, 0xa2, 0x52, 0x02, 0x0a, 0x76, 0x9e, 0xd5, 0x9a, 0x6e, 0xda, 0xa6, + 0xef, 0xe3, 0x37, 0x7e, 0xef, 0x45, 0xf3, 0xf6, 0xf3, 0xe6, 0x41, 0x79, + 0xcc, 0x7d, 0xb8, 0xb1, 0x43, 0xfb, 0x83, 0x5c, 0x5d, 0x71, 0xbf, 0xcf, + 0xa1, 0xe2, 0xa9, 0x04, 0x9b, 0xcc, 0xf7, 0xfe, 0x9a, 0xb5, 0x75, 0x46, + 0x22, 0x0f, 0xe3, 0xf4, 0xb7, 0x52, 0x1c, 0x86, 0x17, 0x39, 0xd1, 0x38, + 0x50, 0x7e, 0x81, 0xa4, 0x6a, 0x69, 0x93, 0x60, 0x54, 0x41, 0xdc, 0xb9, + 0x0d, 0x6e, 0xe4, 0xaf, 0xbc, 0x42, 0xca, 0xbe, 0x90, 0xa2, 0x54, 0x44, + 0x49, 0x68, 0x10, 0x9d, 0x7e, 0xdd, 0x96, 0x94, 0xa0, 0x23, 0x23, 0x9f, + 0x1d, 0x56, 0x17, 0x5d, 0xd1, 0xfa, 0xc1, 0x15, 0x91, 0x5e, 0x24, 0xfa, + 0xb5, 0x63, 0xf4, 0xfc, 0x3f, 0x26, 0x9b, 0xed, 0x2f, 0x30, 0x08, 0x32, + 0xd1, 0x12, 0x59, 0x64, 0x85, 0xa7, 0x11, 0x41, 0x7a, 0xa7, 0x3b, 0xb4, + 0xac, 0x72, 0xa6, 0x51, 0xa1, 0xfa, 0x5b, 0xae, 0xd3, 0x63, 0x6c, 0x72, + 0x0d, 0x39, 0x70, 0x08 +}; +/* K = 37fadd419fcbd2b073a06ae96b9eceb63e29aee9ac5fa2bdb31ab85d */ +static const uint8_t ac_dsa_vect91_out[] = { +/* R */ + 0x65, 0x10, 0x2e, 0x8f, 0x64, 0xec, 0xb1, 0x1f, 0x06, 0x01, 0x7b, 0x1a, + 0x0c, 0x0d, 0xef, 0x3c, 0x29, 0x89, 0x7c, 0x27, 0x7c, 0x4a, 0x94, 0x8b, + 0x1f, 0x4d, 0xa6, 0xb9, +/* S */ + 0x21, 0xad, 0x0a, 0xbb, 0x27, 0xbd, 0x3c, 0x21, 0x16, 0x6c, 0xb9, 0x6a, + 0xef, 0x70, 0xc0, 0xdb, 0xd5, 0xf3, 0x07, 0x9c, 0xab, 0x0d, 0xd5, 0x43, + 0xd4, 0x12, 0x5b, 0xd1 +}; +#define ac_dsa_vect92_prime ac_dsa_vect91_prime +#define ac_dsa_vect92_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect92_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect92_ptx[] = { +/* Msg */ + 0xda, 0x5e, 0x7b, 0x05, 0x1c, 0x18, 0x59, 0xd2, 0x2f, 0x2a, 0x31, 0x63, + 0x33, 0x5d, 0x27, 0x79, 0x51, 0x97, 0x3c, 0x17, 0x2e, 0x06, 0x69, 0x7c, + 0x04, 0x90, 0xff, 0x15, 0xb5, 0x92, 0xc1, 0xeb, 0xd0, 0xfa, 0x5e, 0xfa, + 0x24, 0x63, 0x11, 0x98, 0x04, 0xa3, 0xfe, 0xa2, 0x24, 0xb9, 0x6b, 0x46, + 0x3e, 0x30, 0x08, 0x3e, 0x00, 0x29, 0x49, 0xa2, 0x4e, 0x92, 0x20, 0x31, + 0x76, 0x4b, 0xb3, 0xda, 0xff, 0x81, 0x01, 0xfa, 0x08, 0x8a, 0xf5, 0x45, + 0x7a, 0xf3, 0x66, 0x54, 0xc6, 0x68, 0xf2, 0x34, 0xa0, 0x0c, 0xd8, 0x28, + 0xcc, 0x74, 0x0a, 0x89, 0x8c, 0x0c, 0xd3, 0xdf, 0x09, 0x31, 0x5d, 0xa9, + 0xb3, 0x46, 0xb3, 0x25, 0xb2, 0xfb, 0xec, 0x47, 0x52, 0x10, 0xb7, 0x54, + 0x82, 0xaf, 0xfa, 0x61, 0xa3, 0xef, 0xf5, 0x0c, 0x83, 0xc3, 0xa0, 0x39, + 0xfa, 0xe5, 0xcf, 0xa8, 0xd9, 0x71, 0xfd, 0xdd +}; +static const uint8_t ac_dsa_vect92_priv_val[] = { +/* X */ + 0x9d, 0x8b, 0xba, 0x12, 0x44, 0x17, 0xc1, 0x26, 0xc1, 0xc0, 0x11, 0x11, + 0x59, 0x06, 0xa7, 0xbd, 0xb7, 0xa4, 0x93, 0x66, 0x1d, 0x8a, 0x94, 0x5e, + 0x32, 0xcb, 0x28, 0x3c +}; +static const uint8_t ac_dsa_vect92_pub_val[] = { +/* Y */ + 0x5e, 0x27, 0x69, 0x87, 0xb8, 0x47, 0xb8, 0x52, 0xcc, 0x37, 0x2e, 0x98, + 0x6e, 0x8a, 0xba, 0x06, 0x33, 0xdd, 0x46, 0xc4, 0x61, 0xba, 0xb5, 0x8a, + 0xca, 0xe0, 0x56, 0xd4, 0xd1, 0xa9, 0xdf, 0x03, 0xa1, 0x9d, 0xf1, 0x14, + 0xf6, 0x48, 0xb2, 0x8e, 0x03, 0x85, 0x06, 0xfd, 0x09, 0xad, 0x0d, 0x95, + 0x44, 0x9d, 0x9d, 0x80, 0x58, 0xaa, 0x1b, 0x24, 0x1b, 0x2a, 0xcd, 0x3b, + 0xad, 0xbf, 0x98, 0x82, 0x69, 0x73, 0x31, 0xde, 0x45, 0xb4, 0x52, 0x34, + 0x5c, 0x05, 0x1c, 0x2c, 0xd8, 0x30, 0xf7, 0xcd, 0xd7, 0x48, 0x6b, 0x11, + 0x66, 0xb9, 0x38, 0x91, 0xa7, 0x2a, 0x8b, 0x7d, 0xc6, 0x22, 0x8b, 0xad, + 0x70, 0x87, 0x20, 0xef, 0x33, 0x23, 0x58, 0x01, 0xc4, 0xd4, 0xc3, 0xc4, + 0xf2, 0x80, 0x36, 0xdf, 0x60, 0x29, 0xa1, 0x95, 0xd0, 0x01, 0x91, 0x24, + 0xd1, 0x6f, 0xe8, 0xf7, 0x6c, 0x52, 0x5b, 0x7e, 0x8f, 0x04, 0xbf, 0x4b, + 0x8d, 0x8b, 0xa6, 0xef, 0x60, 0x8e, 0x62, 0x32, 0x24, 0xfa, 0x8d, 0x98, + 0x84, 0x20, 0xf4, 0x05, 0x26, 0xc2, 0x5a, 0xe3, 0xe4, 0xc7, 0x9d, 0x5a, + 0xe7, 0xfe, 0xe6, 0x97, 0x93, 0xe0, 0x2b, 0xad, 0x96, 0x51, 0xea, 0x0f, + 0xef, 0xd3, 0xea, 0xdc, 0x5f, 0xf1, 0xca, 0x2d, 0x14, 0x29, 0x30, 0x35, + 0x5b, 0x1f, 0x3a, 0xea, 0x10, 0x22, 0x21, 0xfa, 0x17, 0xb7, 0x35, 0xa1, + 0x8a, 0xf3, 0xb8, 0x33, 0x27, 0xc8, 0xf3, 0x3e, 0xfb, 0x9a, 0x49, 0xb7, + 0x02, 0x11, 0x01, 0x4e, 0xba, 0x43, 0xfa, 0x65, 0xee, 0xaf, 0x25, 0xeb, + 0xf4, 0x52, 0xbc, 0x4b, 0x7d, 0xc1, 0xf4, 0x07, 0xd0, 0xcf, 0x1b, 0x83, + 0x46, 0x19, 0xb5, 0xf7, 0x3c, 0x6c, 0xab, 0x70, 0x51, 0xc9, 0x20, 0x70, + 0xaa, 0x06, 0xf7, 0xf9, 0x40, 0x6c, 0x50, 0x7d, 0x1a, 0x15, 0xd1, 0x2c, + 0x11, 0xbc, 0x83, 0x9a +}; +/* K = 1abaec5b4efaa83403fa970ff6027fdb596359df930a02baa12ed854 */ +static const uint8_t ac_dsa_vect92_out[] = { +/* R */ + 0x31, 0x36, 0x15, 0x83, 0x6f, 0x0d, 0x33, 0x8d, 0x81, 0xb6, 0x70, 0xf1, + 0x16, 0xa5, 0x41, 0x4d, 0x2c, 0xe9, 0x0e, 0xa5, 0xca, 0x53, 0x08, 0xba, + 0x4f, 0x0c, 0x8a, 0x7d, +/* S */ + 0xdc, 0x1d, 0x4c, 0x3c, 0x06, 0x20, 0x3f, 0xd5, 0x98, 0xa4, 0x76, 0xc8, + 0x91, 0xdf, 0xe5, 0x93, 0x41, 0x62, 0xd0, 0xd3, 0x5f, 0x37, 0xf1, 0xc0, + 0x9d, 0xd6, 0x39, 0x5d +}; +#define ac_dsa_vect93_prime ac_dsa_vect91_prime +#define ac_dsa_vect93_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect93_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect93_ptx[] = { +/* Msg */ + 0xf4, 0x98, 0x95, 0xb3, 0x29, 0x0d, 0x9a, 0xae, 0xb4, 0xaf, 0x61, 0x1c, + 0x5e, 0x30, 0xaf, 0xc0, 0x04, 0x7d, 0xd4, 0x2c, 0x07, 0x21, 0x62, 0x11, + 0xd5, 0x49, 0x77, 0xd1, 0x49, 0x7f, 0xa4, 0xee, 0x6a, 0xbe, 0x11, 0x00, + 0x0d, 0x6a, 0xc0, 0x4d, 0x24, 0xb4, 0xc5, 0x0f, 0x31, 0xe0, 0x6e, 0xe8, + 0xa7, 0x47, 0x74, 0xd3, 0xd3, 0x04, 0x13, 0x7c, 0xc6, 0xb1, 0x14, 0xd1, + 0x45, 0x25, 0x0e, 0xe7, 0xe9, 0x4a, 0x12, 0xa1, 0xab, 0x59, 0x2a, 0xe3, + 0x07, 0xef, 0x5d, 0x93, 0x0c, 0xf3, 0x91, 0x70, 0xe9, 0x75, 0x6a, 0xdc, + 0x5e, 0x7b, 0xa6, 0x2a, 0x54, 0xab, 0xb6, 0xf0, 0x47, 0xb4, 0x50, 0x0b, + 0x61, 0x21, 0xe1, 0xf4, 0xa9, 0x5d, 0x3c, 0x6a, 0x96, 0xf7, 0xf8, 0x33, + 0x3c, 0xbb, 0x1e, 0xbe, 0xed, 0x8b, 0x4d, 0xb1, 0xa7, 0xfe, 0x75, 0xf4, + 0x07, 0x1c, 0xeb, 0xfb, 0xbd, 0xfd, 0xab, 0x90 +}; +static const uint8_t ac_dsa_vect93_priv_val[] = { +/* X */ + 0xb9, 0x17, 0x4a, 0x6c, 0xb4, 0xd3, 0xb2, 0xe7, 0xe4, 0xd1, 0x68, 0x07, + 0x8e, 0x92, 0x0e, 0xcb, 0x65, 0x13, 0x43, 0x22, 0x35, 0x75, 0xdd, 0x37, + 0xc0, 0x67, 0x73, 0x71 +}; +static const uint8_t ac_dsa_vect93_pub_val[] = { +/* Y */ + 0x6d, 0x62, 0x25, 0x25, 0xec, 0xf5, 0x4d, 0xbe, 0xca, 0xa8, 0x11, 0x93, + 0x9e, 0xe0, 0x7e, 0xf2, 0x97, 0x5d, 0x9d, 0xa9, 0xf7, 0xa3, 0xc5, 0x8b, + 0xbb, 0x89, 0x3c, 0xe3, 0x88, 0x06, 0x77, 0x40, 0x4f, 0x2c, 0x6e, 0x59, + 0x63, 0xb8, 0xc0, 0xb4, 0x49, 0x26, 0x01, 0xf1, 0x5b, 0xc6, 0xfd, 0xfd, + 0x74, 0x7a, 0x00, 0xab, 0x83, 0x34, 0xe9, 0x05, 0x32, 0x01, 0xe1, 0xc9, + 0xfb, 0xa5, 0x5f, 0xbf, 0xde, 0x36, 0xec, 0x54, 0x23, 0x75, 0x01, 0xb8, + 0x74, 0x16, 0x99, 0x27, 0x71, 0xcb, 0x5a, 0xb8, 0x78, 0x1d, 0x0a, 0x96, + 0x7b, 0x7f, 0x14, 0xf3, 0xd5, 0xde, 0x6b, 0x16, 0x65, 0xf6, 0x62, 0x88, + 0x58, 0x78, 0xe5, 0x0a, 0xd3, 0x78, 0x27, 0xb9, 0x5c, 0x8f, 0x0e, 0x21, + 0xd6, 0xbb, 0xeb, 0xc9, 0xdf, 0xd4, 0x7b, 0x29, 0x57, 0xd2, 0xfc, 0xdd, + 0x1a, 0x2b, 0x25, 0xa6, 0x16, 0xe6, 0x98, 0x12, 0x9b, 0x45, 0x99, 0x8b, + 0x6b, 0x6a, 0xa2, 0xa9, 0x9c, 0x1e, 0xbf, 0x42, 0x75, 0x49, 0x3e, 0x28, + 0xee, 0xf1, 0xae, 0x34, 0xe9, 0xca, 0x63, 0xcd, 0x88, 0x86, 0xda, 0x58, + 0x57, 0x29, 0x07, 0xaa, 0x9b, 0x71, 0x4e, 0x89, 0xbd, 0x36, 0x44, 0xa7, + 0xea, 0x02, 0x9f, 0xa3, 0xa4, 0xae, 0x9c, 0x26, 0xe6, 0x65, 0xc8, 0x52, + 0x96, 0x20, 0x4f, 0xdf, 0x86, 0xb7, 0xb1, 0xdd, 0x78, 0x66, 0xbc, 0x8e, + 0x93, 0x85, 0xe9, 0x51, 0x8a, 0x27, 0x02, 0x48, 0x29, 0x25, 0x94, 0xc5, + 0x4a, 0x4a, 0x03, 0xdc, 0x14, 0x92, 0x66, 0x4d, 0xda, 0xe5, 0x32, 0x77, + 0xc6, 0xfb, 0xb9, 0xdd, 0x0c, 0xdd, 0x99, 0xbf, 0x11, 0xea, 0xf6, 0xae, + 0x31, 0x92, 0x3e, 0x4f, 0x97, 0x9a, 0x7f, 0x58, 0x17, 0x99, 0xdc, 0x43, + 0x2b, 0x19, 0x40, 0xf6, 0x13, 0xa7, 0xa7, 0xea, 0x68, 0x55, 0x23, 0x7f, + 0x77, 0x6e, 0x91, 0xd4 +}; +/* K = 1c52eec9523245bd82707f2ebdb05fee6d34749f23023ba72a5a60ef */ +static const uint8_t ac_dsa_vect93_out[] = { +/* R */ + 0x79, 0xd5, 0x44, 0xcd, 0xec, 0xfd, 0x1e, 0xc1, 0xb7, 0xd1, 0xba, 0x63, + 0x22, 0xa5, 0xe0, 0xeb, 0x85, 0x8a, 0xeb, 0x4b, 0x76, 0xd5, 0xb3, 0x20, + 0x2c, 0xea, 0x23, 0x3a, +/* S */ + 0x0e, 0xa5, 0x3d, 0xea, 0x4c, 0xcb, 0x25, 0x97, 0x8a, 0x0a, 0xf5, 0x52, + 0x95, 0x98, 0x91, 0x1b, 0x47, 0xc2, 0x5e, 0x0b, 0xa3, 0xb2, 0xa0, 0x50, + 0x5f, 0xd1, 0xd7, 0xfc +}; +#define ac_dsa_vect94_prime ac_dsa_vect91_prime +#define ac_dsa_vect94_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect94_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect94_ptx[] = { +/* Msg */ + 0x31, 0xd7, 0x39, 0x56, 0x69, 0x14, 0x54, 0x9e, 0xb2, 0x57, 0x26, 0xbf, + 0x6d, 0x4b, 0x6c, 0x67, 0x4f, 0x47, 0x9b, 0xa7, 0xa4, 0x06, 0xac, 0xd1, + 0x08, 0xa1, 0x06, 0xf3, 0x6c, 0x7f, 0x52, 0x14, 0x97, 0x6d, 0xcf, 0x3a, + 0xdf, 0x2c, 0x83, 0xfd, 0x26, 0xb3, 0x7d, 0x52, 0xc0, 0xb5, 0xff, 0x51, + 0xe6, 0xb3, 0x81, 0x1a, 0x8d, 0xcb, 0x02, 0x6a, 0x1f, 0xbb, 0x52, 0xf9, + 0x50, 0x27, 0xea, 0x60, 0x34, 0xd9, 0x11, 0x49, 0xb3, 0x0a, 0xb4, 0x92, + 0x8e, 0xde, 0x26, 0xdd, 0xd6, 0x92, 0xdd, 0xb8, 0xdd, 0xd9, 0x29, 0xfb, + 0xff, 0x83, 0xfc, 0x67, 0x37, 0x88, 0xfa, 0xa0, 0xba, 0x5d, 0x96, 0x7f, + 0xd1, 0x33, 0x92, 0x99, 0xe5, 0x5b, 0xe5, 0x1c, 0xea, 0x80, 0x60, 0x9d, + 0x2b, 0x3c, 0x34, 0x33, 0xcf, 0x71, 0x3a, 0x96, 0x86, 0xe2, 0x29, 0x33, + 0x6c, 0xfa, 0x7e, 0x72, 0x0f, 0xd5, 0x30, 0x3d +}; +static const uint8_t ac_dsa_vect94_priv_val[] = { +/* X */ + 0x4c, 0xb5, 0x6c, 0x8a, 0xcb, 0x9c, 0x10, 0x70, 0x87, 0x83, 0x7e, 0xf5, + 0xe0, 0x21, 0xf7, 0x7c, 0xb0, 0x15, 0x02, 0x3c, 0x8a, 0xc1, 0xec, 0x73, + 0x57, 0x5e, 0x52, 0x89 +}; +static const uint8_t ac_dsa_vect94_pub_val[] = { +/* Y */ + 0x38, 0x6c, 0xbb, 0x8f, 0x7e, 0x72, 0x87, 0x51, 0xd4, 0xf6, 0xa7, 0x5f, + 0x89, 0x05, 0x02, 0x98, 0x9b, 0x51, 0x22, 0x8d, 0x30, 0x39, 0xdd, 0x1a, + 0xf7, 0xf2, 0xdd, 0x01, 0x86, 0xbf, 0x97, 0xa9, 0xff, 0x76, 0x3b, 0x40, + 0x32, 0x3b, 0x30, 0xab, 0x0d, 0xc8, 0x1b, 0xf0, 0x9e, 0xf4, 0x8d, 0xb7, + 0x2c, 0x0c, 0xfb, 0xe7, 0x72, 0xb3, 0xd3, 0x14, 0x92, 0x7e, 0xd1, 0x9b, + 0xad, 0xee, 0x7b, 0x88, 0xb4, 0x9e, 0xe2, 0x94, 0x92, 0x37, 0x14, 0xad, + 0xae, 0x30, 0xc9, 0x55, 0xd3, 0x7b, 0x99, 0xc1, 0xda, 0xdc, 0x4a, 0x29, + 0xf0, 0xf8, 0xc2, 0xb9, 0xd1, 0x03, 0x8d, 0x17, 0x05, 0x9c, 0x58, 0x6a, + 0x21, 0x2a, 0x97, 0x48, 0x72, 0x0f, 0xde, 0xc9, 0x5b, 0x42, 0x89, 0x71, + 0xdf, 0x19, 0x23, 0xf0, 0x8a, 0x01, 0xd3, 0x58, 0x93, 0xd1, 0x2e, 0xd1, + 0x7e, 0x0b, 0x14, 0x2e, 0xd8, 0xe9, 0xef, 0x77, 0xd4, 0x40, 0xa0, 0x1d, + 0x77, 0x90, 0x5b, 0x92, 0xc5, 0x1d, 0xac, 0xe1, 0xb3, 0x45, 0xcd, 0x19, + 0xf9, 0x16, 0x23, 0xa6, 0x96, 0x42, 0x88, 0xdd, 0xee, 0x6e, 0x99, 0x08, + 0x19, 0x7f, 0x91, 0xda, 0x9a, 0x26, 0xf8, 0x06, 0xbb, 0x14, 0xe2, 0x37, + 0x17, 0x42, 0xf8, 0x49, 0xcd, 0xc6, 0xce, 0x7a, 0x04, 0x5a, 0x70, 0x4a, + 0x79, 0x2e, 0x57, 0x60, 0xd6, 0x64, 0x4e, 0xad, 0xb7, 0xcf, 0xfa, 0xba, + 0x80, 0x6b, 0x05, 0x45, 0xfa, 0xe3, 0xb9, 0xfa, 0xda, 0xe4, 0xe3, 0x6b, + 0xdf, 0x3b, 0x69, 0xc6, 0xdb, 0xbf, 0x0d, 0x8b, 0x05, 0x3d, 0xa3, 0x8b, + 0x90, 0x4e, 0x9c, 0x4b, 0x94, 0x93, 0x25, 0xb2, 0xa0, 0x05, 0xb2, 0x49, + 0x27, 0x6a, 0xc3, 0x69, 0x27, 0xb3, 0x17, 0x93, 0xf8, 0x01, 0x15, 0xb5, + 0xe2, 0xf2, 0x10, 0x7f, 0x98, 0x77, 0x10, 0x38, 0x07, 0x08, 0xe2, 0xc3, + 0x22, 0x89, 0x4f, 0xa8 +}; +/* K = d223b9e9c662ba6651cdbad84f2616fa223fa8742f783c87c2fb9e8e */ +static const uint8_t ac_dsa_vect94_out[] = { +/* R */ + 0xc8, 0xb8, 0xa9, 0x2e, 0x8c, 0x10, 0x15, 0x05, 0xa1, 0x99, 0x1b, 0xcb, + 0x02, 0xfb, 0x6e, 0x38, 0x2a, 0x3e, 0xcb, 0xae, 0xc8, 0xf4, 0x37, 0x45, + 0x01, 0xb6, 0x57, 0xbe, +/* S */ + 0x20, 0xd1, 0x61, 0xce, 0xfd, 0x58, 0x49, 0x79, 0x22, 0x43, 0x79, 0xf2, + 0x8d, 0x82, 0x7a, 0xa2, 0x19, 0xc5, 0x72, 0xf9, 0x60, 0x01, 0x47, 0xf4, + 0x04, 0x8b, 0xa7, 0xcf +}; +#define ac_dsa_vect95_prime ac_dsa_vect91_prime +#define ac_dsa_vect95_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect95_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect95_ptx[] = { +/* Msg */ + 0xd0, 0xa8, 0xa1, 0xca, 0x0f, 0xf2, 0xb4, 0x4b, 0x37, 0xff, 0x86, 0x00, + 0x07, 0x33, 0x4b, 0x23, 0xbe, 0x49, 0x34, 0xff, 0x89, 0x05, 0x1d, 0x78, + 0x7c, 0xe6, 0x9d, 0x3d, 0x7f, 0xa7, 0x34, 0xb9, 0x77, 0x9e, 0x2f, 0x0b, + 0x38, 0xc2, 0x35, 0x39, 0x1a, 0x89, 0x7f, 0xb8, 0x51, 0x4b, 0x85, 0x7b, + 0x99, 0x1d, 0x10, 0xe3, 0x4a, 0x00, 0xdc, 0x25, 0xb0, 0xc4, 0x38, 0x2d, + 0xfb, 0x6d, 0x53, 0xaa, 0x87, 0xec, 0x17, 0x84, 0xf1, 0xca, 0xe2, 0x59, + 0x92, 0x59, 0x40, 0x6d, 0x47, 0x56, 0x53, 0x98, 0x67, 0x67, 0x9d, 0x30, + 0x88, 0x91, 0x3a, 0x13, 0x88, 0x71, 0xe2, 0xa4, 0x34, 0x74, 0x72, 0x22, + 0xfc, 0xfa, 0xb0, 0x79, 0xd9, 0xe6, 0x55, 0xba, 0x25, 0x44, 0x63, 0xcb, + 0x0c, 0x57, 0x86, 0xb9, 0x85, 0x8d, 0xc4, 0x29, 0xff, 0xda, 0xdf, 0x4c, + 0x3b, 0x6a, 0x25, 0x3f, 0x90, 0xee, 0xba, 0x24 +}; +static const uint8_t ac_dsa_vect95_priv_val[] = { +/* X */ + 0x22, 0x86, 0x42, 0x4f, 0x36, 0x8e, 0x5e, 0x64, 0xba, 0xc0, 0xc9, 0x77, + 0xff, 0x0d, 0x92, 0xa5, 0x60, 0xb7, 0x8e, 0x4f, 0x21, 0xb4, 0x9f, 0x3a, + 0xee, 0x7c, 0xde, 0xc6 +}; +static const uint8_t ac_dsa_vect95_pub_val[] = { +/* Y */ + 0x72, 0x47, 0xd4, 0xe1, 0x25, 0x3f, 0x0b, 0x52, 0xa1, 0x38, 0x8b, 0x79, + 0x48, 0x15, 0xdb, 0x61, 0xc1, 0xa3, 0x54, 0xcb, 0x0f, 0x73, 0xfd, 0x19, + 0xfe, 0xde, 0x61, 0x5c, 0x1c, 0x30, 0x25, 0x84, 0x0f, 0xff, 0x20, 0x4b, + 0x0c, 0x6e, 0x61, 0x0e, 0xbe, 0xf1, 0x11, 0x3d, 0xf5, 0x6f, 0x67, 0x40, + 0x6b, 0xad, 0xeb, 0x99, 0x44, 0x58, 0x91, 0xdc, 0xaf, 0xe1, 0x8d, 0x28, + 0xf5, 0x97, 0x12, 0x60, 0x64, 0xdd, 0xf7, 0xaa, 0xf2, 0x03, 0xb2, 0xfb, + 0x0d, 0x35, 0xd2, 0xf4, 0x58, 0xbb, 0x74, 0x34, 0x1a, 0xd9, 0x37, 0x21, + 0x1e, 0xdc, 0x39, 0x4e, 0xc1, 0xa3, 0xf7, 0x90, 0x9a, 0x3f, 0x97, 0x2d, + 0xb2, 0x7a, 0xa1, 0x35, 0xd3, 0x1b, 0xbd, 0x7e, 0x36, 0xc2, 0xbb, 0xc3, + 0x60, 0x58, 0x5e, 0x7b, 0xb6, 0xe8, 0x32, 0x76, 0x40, 0x6b, 0x95, 0x25, + 0xf6, 0x88, 0xee, 0x59, 0x95, 0xe7, 0xaa, 0x8e, 0xf7, 0xa7, 0x2c, 0x27, + 0xe9, 0x90, 0xd6, 0x40, 0x16, 0xb9, 0x9a, 0x0a, 0xe4, 0xd0, 0x4b, 0x2f, + 0x1b, 0x7d, 0x23, 0x8a, 0xf8, 0x8a, 0xc4, 0xc2, 0xe4, 0xe0, 0xf3, 0x29, + 0x4c, 0xfe, 0xe9, 0xbe, 0x24, 0x57, 0xe4, 0x89, 0x55, 0x94, 0x8c, 0xf4, + 0xbb, 0x3a, 0x44, 0x5a, 0x1d, 0x77, 0x8c, 0xed, 0xfa, 0x4b, 0x86, 0xf5, + 0x9f, 0x15, 0x61, 0x18, 0x03, 0x4b, 0x2b, 0x83, 0x4a, 0x9a, 0xa1, 0x21, + 0xe9, 0xd4, 0x82, 0xd6, 0x92, 0x22, 0x92, 0x82, 0x3b, 0xe2, 0x99, 0x1b, + 0x3b, 0x5b, 0x42, 0xc2, 0x39, 0x25, 0xda, 0x29, 0x4d, 0x5e, 0xa3, 0x74, + 0x06, 0xea, 0xf7, 0x8b, 0x7d, 0xc7, 0x25, 0x19, 0xd8, 0xf2, 0x61, 0x48, + 0x2d, 0x6a, 0xff, 0xf0, 0xe5, 0x67, 0xbf, 0x6e, 0x67, 0x3d, 0xd8, 0x99, + 0x60, 0xce, 0x73, 0x4f, 0x09, 0x2d, 0x98, 0x95, 0x63, 0x52, 0x42, 0x9a, + 0x91, 0x84, 0x56, 0x94 +}; +/* K = c2795f65f0f077e32c022a703f7eb8e5dc068fa67cb087ef366b243a */ +static const uint8_t ac_dsa_vect95_out[] = { +/* R */ + 0x9d, 0xab, 0xff, 0x22, 0xa4, 0x30, 0x12, 0xdb, 0xf4, 0x7d, 0x56, 0xb9, + 0xae, 0x5a, 0x09, 0xf4, 0xd7, 0x39, 0xdd, 0x69, 0xfe, 0x90, 0x77, 0x25, + 0xaf, 0xcd, 0x84, 0xf4, +/* S */ + 0xb6, 0x0c, 0x44, 0x72, 0x8e, 0x4b, 0x13, 0x90, 0xf3, 0x02, 0x38, 0xfb, + 0xa1, 0xdc, 0x10, 0x03, 0xfd, 0xd3, 0x95, 0x07, 0xff, 0x5d, 0x6b, 0xa7, + 0xe6, 0x09, 0xf2, 0xae +}; +#define ac_dsa_vect96_prime ac_dsa_vect91_prime +#define ac_dsa_vect96_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect96_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect96_ptx[] = { +/* Msg */ + 0xe4, 0xff, 0xe7, 0x2c, 0x77, 0xc3, 0xa4, 0x3a, 0xf8, 0xa6, 0x1f, 0x58, + 0xf9, 0x24, 0x0e, 0x1a, 0x07, 0xb5, 0xc2, 0x89, 0x4d, 0x5b, 0xdb, 0x65, + 0x4b, 0x2b, 0x99, 0x4d, 0xc0, 0xc9, 0x87, 0xba, 0xd9, 0xb7, 0x04, 0x07, + 0x5d, 0x3d, 0x0a, 0x96, 0x9c, 0xec, 0xfc, 0x98, 0xb1, 0xdc, 0x20, 0xe7, + 0x6c, 0xd8, 0xe0, 0x12, 0x28, 0x58, 0x19, 0x46, 0x22, 0x26, 0xa8, 0x4d, + 0xcd, 0xd6, 0x78, 0x95, 0xf6, 0xea, 0x27, 0x82, 0x66, 0xf1, 0x57, 0x5e, + 0xa7, 0x85, 0xa2, 0xc3, 0x59, 0xf8, 0xf4, 0x59, 0x3b, 0xef, 0x31, 0xa5, + 0x80, 0x91, 0xb6, 0x4a, 0xfb, 0x84, 0xcd, 0xfd, 0x23, 0xe4, 0xaa, 0xff, + 0x29, 0xd9, 0x62, 0x6f, 0x0c, 0x82, 0x3d, 0x93, 0x42, 0x83, 0xa4, 0xfa, + 0xaf, 0xc9, 0xc6, 0xcc, 0x18, 0x62, 0x23, 0x28, 0xca, 0xd9, 0x6f, 0x77, + 0xd7, 0x9b, 0x9b, 0xa3, 0x5a, 0x43, 0xd8, 0x25 +}; +static const uint8_t ac_dsa_vect96_priv_val[] = { +/* X */ + 0x86, 0xb0, 0xe5, 0x64, 0xef, 0x08, 0xe0, 0x89, 0xc4, 0xc8, 0x56, 0x75, + 0xb6, 0xe5, 0x28, 0x1d, 0xaa, 0x4e, 0x82, 0xbc, 0x2f, 0xc0, 0xe2, 0x76, + 0x68, 0x05, 0x2e, 0x4e +}; +static const uint8_t ac_dsa_vect96_pub_val[] = { +/* Y */ + 0x71, 0x46, 0x00, 0x9d, 0x12, 0xb0, 0x3b, 0x2f, 0x32, 0x30, 0x5f, 0x49, + 0x5f, 0xaf, 0xcc, 0x4d, 0x45, 0x2e, 0xfb, 0x85, 0xcc, 0x80, 0xd6, 0x71, + 0xff, 0x42, 0x49, 0x49, 0x2c, 0x66, 0x99, 0xfb, 0x26, 0xa8, 0x9c, 0xa4, + 0xb2, 0x24, 0xd5, 0x6f, 0x6b, 0x8e, 0x74, 0x5d, 0xf9, 0xfb, 0xc7, 0x35, + 0x2c, 0xa5, 0x83, 0x22, 0x2f, 0x4d, 0xea, 0xb1, 0x18, 0xf9, 0xfe, 0xc0, + 0xb3, 0x4e, 0x33, 0x40, 0x60, 0xbd, 0xc2, 0x8d, 0xb8, 0x72, 0xe0, 0x09, + 0x06, 0x49, 0x14, 0x94, 0x99, 0xe7, 0xa1, 0xc1, 0x97, 0x87, 0x8d, 0x3c, + 0x72, 0x62, 0x43, 0x93, 0x03, 0xb9, 0x02, 0x01, 0xd0, 0xb7, 0xf5, 0xbe, + 0x94, 0xd0, 0xa7, 0xc4, 0xeb, 0x15, 0x18, 0x29, 0x35, 0x29, 0x6c, 0x3e, + 0x3f, 0xa2, 0xd7, 0x7d, 0x74, 0xd7, 0x8f, 0x41, 0xca, 0xda, 0xa4, 0x0e, + 0xaf, 0xd4, 0x0d, 0x01, 0x78, 0x88, 0xca, 0xa0, 0x2a, 0x47, 0x48, 0x68, + 0xe4, 0x0f, 0x49, 0x6b, 0x7b, 0xc1, 0xce, 0x36, 0x7f, 0x50, 0x34, 0x35, + 0xe0, 0xd9, 0xa6, 0x37, 0x5a, 0xab, 0x03, 0xc2, 0x31, 0xd9, 0xcd, 0xaa, + 0x15, 0xde, 0x23, 0xc4, 0x8a, 0xc0, 0x87, 0x8e, 0xf6, 0x49, 0xeb, 0x14, + 0x4c, 0xe6, 0xbe, 0x4d, 0x2d, 0xe1, 0x1d, 0xa2, 0x02, 0xfa, 0xe8, 0x20, + 0x90, 0x67, 0x3c, 0x83, 0xb3, 0x28, 0x40, 0xa3, 0x2d, 0xf6, 0x17, 0x6e, + 0x1d, 0x55, 0x02, 0x7d, 0x7a, 0x1c, 0x1c, 0x56, 0xe6, 0x42, 0xf5, 0x1a, + 0xae, 0xcc, 0xb3, 0xc9, 0x90, 0x89, 0x80, 0x61, 0xbf, 0xa1, 0x6b, 0x3d, + 0xc1, 0x46, 0x10, 0x73, 0xc3, 0x33, 0x33, 0x7f, 0xd7, 0x6a, 0x31, 0x03, + 0xf3, 0xfd, 0xe8, 0x21, 0xbc, 0x99, 0x4e, 0xbe, 0xdd, 0x6f, 0xfd, 0x79, + 0x74, 0xd0, 0xca, 0x1b, 0x54, 0x96, 0x1d, 0x7d, 0xf5, 0xb9, 0xee, 0xbb, + 0xfa, 0x26, 0xc3, 0xd6 +}; +/* K = 5aba2fdf6b24bf24151943a4f32d2794e44d1f62e8c968ceb5b073c7 */ +static const uint8_t ac_dsa_vect96_out[] = { +/* R */ + 0x4a, 0x2a, 0xbc, 0x68, 0x9d, 0x2a, 0x63, 0xe8, 0xb2, 0x32, 0x14, 0xa3, + 0x21, 0x2a, 0x5d, 0x20, 0xa7, 0x38, 0x68, 0x82, 0xd5, 0xe1, 0x1c, 0x5d, + 0x5d, 0xaa, 0x66, 0xbc, +/* S */ + 0x08, 0xe0, 0xc6, 0x54, 0x70, 0x87, 0xb5, 0x8b, 0xc9, 0x4f, 0xae, 0x24, + 0x7e, 0x96, 0x2d, 0xa1, 0xa2, 0x89, 0x78, 0x88, 0xd1, 0xbc, 0x9c, 0x8c, + 0xbf, 0x3a, 0xd6, 0xaf +}; +#define ac_dsa_vect97_prime ac_dsa_vect91_prime +#define ac_dsa_vect97_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect97_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect97_ptx[] = { +/* Msg */ + 0xf8, 0xfe, 0xc1, 0x92, 0x88, 0xf3, 0xa8, 0xbd, 0x1d, 0x0d, 0x57, 0x3b, + 0xbb, 0xc1, 0x80, 0x10, 0x60, 0x65, 0x69, 0x74, 0x81, 0xbe, 0xd9, 0x12, + 0xf8, 0x75, 0x27, 0x50, 0xd3, 0x31, 0xe3, 0xa0, 0x97, 0x77, 0x5a, 0x12, + 0x27, 0x6b, 0xc4, 0x29, 0x3a, 0x78, 0xa8, 0x07, 0x48, 0xb2, 0xb2, 0xc3, + 0x7d, 0x20, 0xb8, 0x00, 0x33, 0x5c, 0x1d, 0x1b, 0x43, 0x0a, 0x71, 0xbb, + 0xdf, 0xd8, 0xf7, 0xaf, 0xee, 0xec, 0x82, 0xce, 0xff, 0x2f, 0xd3, 0x3f, + 0x26, 0x24, 0xe4, 0x9d, 0x37, 0x45, 0x7f, 0x26, 0x2c, 0xf5, 0xde, 0xde, + 0xf9, 0x02, 0x5c, 0xe9, 0x6e, 0x0b, 0x7d, 0x49, 0x9f, 0xcc, 0x7a, 0x7f, + 0xf0, 0x6c, 0x02, 0x59, 0x0e, 0xa8, 0x21, 0xdd, 0x8e, 0xd0, 0x60, 0xca, + 0xbc, 0xf4, 0xfe, 0xec, 0x95, 0x92, 0xac, 0xed, 0xdf, 0xd3, 0x2b, 0x4c, + 0x09, 0xe4, 0xd4, 0x49, 0x38, 0x43, 0x5b, 0x82 +}; +static const uint8_t ac_dsa_vect97_priv_val[] = { +/* X */ + 0xe5, 0xad, 0xa2, 0x9e, 0x91, 0xcc, 0xae, 0x11, 0xfd, 0x06, 0x01, 0x12, + 0x54, 0x0e, 0xac, 0x31, 0xd9, 0x65, 0x1b, 0x34, 0xb2, 0x75, 0x4e, 0xe5, + 0x16, 0x20, 0x62, 0x4c +}; +static const uint8_t ac_dsa_vect97_pub_val[] = { +/* Y */ + 0x7e, 0x50, 0x01, 0x1d, 0x42, 0x29, 0x86, 0xea, 0xe0, 0x1a, 0xe6, 0x89, + 0x43, 0xdc, 0xa0, 0xc8, 0x7a, 0xf4, 0x4f, 0x7b, 0x87, 0x9b, 0xd1, 0x25, + 0x6d, 0x4c, 0xaf, 0xfa, 0x0e, 0xb1, 0x92, 0x50, 0x29, 0xc0, 0x63, 0x3a, + 0x7a, 0xc6, 0x74, 0x87, 0xa7, 0xb6, 0xf9, 0x8a, 0xd7, 0x7e, 0xe7, 0xe1, + 0x44, 0x2d, 0x12, 0x9d, 0x06, 0xdb, 0x47, 0x5a, 0x4f, 0x78, 0x04, 0xfd, + 0x8c, 0x6a, 0x03, 0x81, 0x51, 0x91, 0x1f, 0x81, 0x39, 0x7e, 0x96, 0x35, + 0x94, 0xb9, 0xc9, 0x1e, 0x3b, 0xfe, 0x94, 0x32, 0x8f, 0x05, 0x6e, 0x9b, + 0xdb, 0xb9, 0xb1, 0x1f, 0x54, 0x93, 0x9d, 0x7e, 0x23, 0x7a, 0xaf, 0xb0, + 0xc9, 0x50, 0xe0, 0x58, 0x1c, 0xab, 0xfe, 0x94, 0xbc, 0x26, 0xf0, 0xe0, + 0xd5, 0x56, 0x09, 0x97, 0xbf, 0xb0, 0xf6, 0x35, 0x7b, 0xbf, 0x2c, 0xad, + 0xb0, 0x10, 0x8e, 0xc0, 0x09, 0x56, 0x46, 0xe4, 0xca, 0xa2, 0x2f, 0x71, + 0xe1, 0xf1, 0x7a, 0x9f, 0x34, 0xe8, 0xa8, 0xc4, 0xb7, 0x1c, 0xf0, 0xb1, + 0x26, 0x5e, 0x00, 0x15, 0x54, 0xfa, 0x91, 0xf1, 0x8a, 0x17, 0x56, 0x2b, + 0xc0, 0x94, 0x8c, 0x43, 0x1f, 0x25, 0x94, 0x59, 0x62, 0xba, 0x7f, 0xaf, + 0x7d, 0xcb, 0x64, 0xff, 0x0b, 0x8b, 0xdd, 0xe7, 0x01, 0xe1, 0xdf, 0x62, + 0x0a, 0x11, 0xaa, 0xd0, 0x71, 0x96, 0xd6, 0x7a, 0x95, 0x6e, 0xbe, 0x49, + 0x8a, 0xe6, 0xf8, 0x23, 0x24, 0xf7, 0x5c, 0xaf, 0xbe, 0x80, 0xed, 0xaa, + 0xbe, 0xf0, 0x03, 0x7b, 0x79, 0xc3, 0xed, 0x65, 0x8d, 0x9b, 0xa1, 0xb5, + 0x42, 0x2c, 0x4a, 0xc0, 0x53, 0xba, 0x69, 0xbb, 0xaf, 0x7f, 0xa9, 0xdb, + 0x99, 0x0e, 0x8b, 0x5e, 0x7f, 0x9a, 0xf5, 0x7a, 0x79, 0xf3, 0xe3, 0x1c, + 0x07, 0x61, 0x1f, 0x50, 0x2b, 0x30, 0x15, 0x96, 0x2b, 0x02, 0xb6, 0xb4, + 0x25, 0x70, 0x6e, 0x0a +}; +/* K = cf0544a08823ea2ad5f13716b43b154aa4bf80d6bbcafe6040ad91c3 */ +static const uint8_t ac_dsa_vect97_out[] = { +/* R */ + 0x2f, 0x38, 0xc5, 0xcf, 0x86, 0xaa, 0x0e, 0x53, 0xd1, 0xfe, 0xa0, 0xe6, + 0x5d, 0xd0, 0x38, 0x13, 0x64, 0x04, 0x04, 0xb8, 0xd9, 0xa8, 0xcd, 0x6d, + 0x26, 0x4d, 0x92, 0x85, +/* S */ + 0x47, 0x60, 0x38, 0x80, 0xf3, 0xd6, 0x7b, 0xa1, 0xa6, 0xea, 0xbc, 0x20, + 0x13, 0x7d, 0xc4, 0x88, 0x2e, 0x41, 0x73, 0x04, 0xcb, 0x95, 0xd6, 0x22, + 0x17, 0x7d, 0xf5, 0x11 +}; +#define ac_dsa_vect98_prime ac_dsa_vect91_prime +#define ac_dsa_vect98_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect98_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect98_ptx[] = { +/* Msg */ + 0x75, 0x59, 0x46, 0x5a, 0xf5, 0xca, 0x04, 0xc1, 0xe7, 0x4d, 0xeb, 0x9f, + 0x8e, 0x46, 0xb0, 0xef, 0x17, 0xde, 0x4d, 0x7a, 0x2a, 0xe0, 0xfa, 0xf4, + 0xe9, 0x03, 0xa2, 0x99, 0x8b, 0xca, 0xa0, 0x9b, 0x7f, 0x17, 0x30, 0x39, + 0x33, 0x20, 0xeb, 0xc5, 0x7d, 0x05, 0x2d, 0x2e, 0x98, 0xf5, 0x48, 0x6e, + 0x8e, 0x92, 0xbd, 0x1e, 0xe6, 0xbb, 0x0f, 0xfd, 0x02, 0xd6, 0x9e, 0x5d, + 0x45, 0x91, 0xe2, 0xfa, 0x12, 0xe4, 0xeb, 0xff, 0x8b, 0x6b, 0x9d, 0x32, + 0x70, 0xfc, 0x75, 0x27, 0x4f, 0x8f, 0x82, 0xe1, 0xc6, 0x0e, 0xdb, 0x2a, + 0x21, 0xf8, 0xd5, 0x53, 0x1a, 0x23, 0x80, 0xcb, 0xeb, 0xb2, 0x4f, 0x64, + 0x57, 0x17, 0x6e, 0x54, 0x76, 0x9a, 0x13, 0x66, 0x01, 0xa9, 0xb8, 0x1d, + 0xa6, 0x8f, 0xf1, 0x96, 0xff, 0x8c, 0xc7, 0x8c, 0xf0, 0x59, 0xc0, 0x4a, + 0xe2, 0x24, 0x59, 0xce, 0xc7, 0xda, 0x89, 0xb6 +}; +static const uint8_t ac_dsa_vect98_priv_val[] = { +/* X */ + 0x6b, 0xa8, 0x14, 0xfb, 0x6c, 0x1d, 0x9f, 0xe5, 0xd2, 0x82, 0x00, 0x8d, + 0xcc, 0x9a, 0xf2, 0x76, 0x1d, 0x1b, 0x03, 0xeb, 0x1f, 0xd0, 0x2e, 0x24, + 0x99, 0xc1, 0xb5, 0x09 +}; +static const uint8_t ac_dsa_vect98_pub_val[] = { +/* Y */ + 0x5b, 0xcd, 0x42, 0xe5, 0x86, 0xca, 0x18, 0x0f, 0x74, 0x33, 0x95, 0xfc, + 0x39, 0xe2, 0xbd, 0x39, 0x38, 0x20, 0xf5, 0xb4, 0xc4, 0x9c, 0x7c, 0xb7, + 0x69, 0x21, 0xec, 0x38, 0xbb, 0x53, 0xe8, 0x64, 0xfb, 0xe8, 0x09, 0xa0, + 0x33, 0x77, 0x5f, 0x16, 0xc7, 0xf5, 0xc6, 0x48, 0x72, 0xfe, 0xdd, 0xe6, + 0xab, 0xc5, 0x60, 0x48, 0x8e, 0x57, 0x29, 0x55, 0xed, 0xd3, 0xf9, 0x56, + 0x90, 0x92, 0x07, 0x1e, 0x56, 0xdf, 0x21, 0x15, 0x64, 0xf3, 0x31, 0x85, + 0xdb, 0xff, 0x18, 0x0e, 0x7a, 0xb2, 0x29, 0x77, 0x00, 0xc6, 0x4d, 0xb6, + 0xe2, 0x20, 0x70, 0x1c, 0xb8, 0xa2, 0x1e, 0xad, 0x2e, 0xa8, 0x09, 0xf0, + 0x6a, 0x16, 0x55, 0x43, 0x19, 0xb2, 0x73, 0x9d, 0xe2, 0xac, 0xa8, 0x05, + 0x7a, 0x62, 0xd4, 0xca, 0xa7, 0x95, 0x7a, 0x2b, 0x9f, 0x03, 0x9b, 0x3c, + 0x7d, 0x4f, 0xb0, 0x76, 0x1a, 0x73, 0x30, 0x2a, 0x6f, 0xbb, 0x58, 0x31, + 0x00, 0xb2, 0x39, 0xd7, 0x27, 0x15, 0x8b, 0x4c, 0xdc, 0x97, 0x65, 0xfe, + 0x04, 0x85, 0xaf, 0xb6, 0xa1, 0xb0, 0xac, 0x0d, 0xb5, 0x04, 0xa9, 0x47, + 0xf3, 0xd8, 0x7f, 0xaa, 0x55, 0x42, 0xc6, 0xee, 0xf7, 0xa6, 0x81, 0xc5, + 0xfc, 0xd2, 0x8f, 0x46, 0x36, 0x36, 0x0f, 0x55, 0x93, 0xbf, 0xf7, 0xe4, + 0x33, 0xb6, 0xa3, 0x38, 0xd7, 0x7e, 0x3d, 0x63, 0xf6, 0xce, 0xff, 0x69, + 0x53, 0x6e, 0x2a, 0x3f, 0xf7, 0x7a, 0xce, 0x74, 0x5b, 0x65, 0xa5, 0x16, + 0x0d, 0x7f, 0xbf, 0x91, 0x05, 0xa9, 0x0f, 0x46, 0xce, 0x1c, 0x54, 0xfa, + 0x35, 0x3c, 0x8a, 0xee, 0xbe, 0x16, 0xfb, 0x23, 0x8c, 0x8e, 0xd9, 0x98, + 0x61, 0x7b, 0x63, 0x28, 0x75, 0x11, 0x20, 0x8d, 0x9d, 0xb3, 0xf6, 0x6d, + 0x50, 0x33, 0x74, 0xbb, 0xda, 0x48, 0xa5, 0x52, 0xd0, 0x4b, 0x2c, 0x30, + 0x4a, 0x15, 0xba, 0xc0 +}; +/* K = 70af9c79fad2b3a0677fccadd95e6f72eb8a51464e443d1e5c007f98 */ +static const uint8_t ac_dsa_vect98_out[] = { +/* R */ + 0xc5, 0xd3, 0x3f, 0x5a, 0x4f, 0xe2, 0x28, 0x0a, 0x9b, 0x96, 0xd7, 0xa9, + 0xb5, 0x53, 0x0d, 0xc1, 0x7c, 0xd1, 0x05, 0x4b, 0xf1, 0xe8, 0xcf, 0x6f, + 0x4a, 0xa3, 0xe2, 0xac, +/* S */ + 0xc9, 0xbf, 0x1c, 0x06, 0x2b, 0xd1, 0xe8, 0x6f, 0x3b, 0xd3, 0xc1, 0xff, + 0x58, 0x2c, 0x33, 0x27, 0x05, 0x37, 0xfa, 0x77, 0x69, 0xb9, 0x59, 0x2a, + 0xef, 0x12, 0xe1, 0x04 +}; +#define ac_dsa_vect99_prime ac_dsa_vect91_prime +#define ac_dsa_vect99_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect99_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect99_ptx[] = { +/* Msg */ + 0x16, 0x74, 0x82, 0x38, 0x96, 0xc5, 0xa7, 0x64, 0xc6, 0x1f, 0xd1, 0x9b, + 0x12, 0x5a, 0x7d, 0x6c, 0xd5, 0x8c, 0x88, 0x3d, 0x86, 0x79, 0x43, 0x91, + 0x47, 0x73, 0x49, 0xf0, 0x36, 0x16, 0xd7, 0x5b, 0x69, 0x25, 0xe9, 0xdc, + 0xc5, 0x53, 0xde, 0xa3, 0x70, 0x47, 0xf0, 0xcd, 0x15, 0x31, 0x68, 0xeb, + 0x26, 0xe5, 0xad, 0x4b, 0x8f, 0xe7, 0xcc, 0x65, 0xe4, 0xfa, 0x27, 0x55, + 0x14, 0xc8, 0x42, 0xaf, 0x63, 0x50, 0x7f, 0x90, 0x1f, 0xd1, 0x10, 0xb9, + 0x82, 0x49, 0x13, 0x3d, 0x3d, 0x12, 0x66, 0xd2, 0xf9, 0x67, 0xc8, 0x5b, + 0x7f, 0x88, 0xdd, 0x76, 0xc7, 0xf7, 0x6b, 0x78, 0x6b, 0x55, 0x72, 0xdc, + 0xae, 0x68, 0xcc, 0x64, 0x6e, 0x45, 0x8b, 0x82, 0x78, 0xdb, 0x34, 0x6b, + 0x2e, 0x97, 0x0c, 0x78, 0x70, 0xcf, 0xfd, 0x84, 0x57, 0xfb, 0xec, 0x06, + 0xbb, 0xb5, 0x14, 0x15, 0x75, 0xf4, 0x0f, 0xde +}; +static const uint8_t ac_dsa_vect99_priv_val[] = { +/* X */ + 0xb5, 0xa6, 0x07, 0x13, 0x6e, 0x5d, 0xfa, 0x76, 0x64, 0x5f, 0x4f, 0xee, + 0x9d, 0xb1, 0x7b, 0xbc, 0xd2, 0x60, 0xb1, 0xf6, 0x02, 0x3f, 0x28, 0x47, + 0x49, 0x21, 0x71, 0x4b +}; +static const uint8_t ac_dsa_vect99_pub_val[] = { +/* Y */ + 0x5c, 0x34, 0x13, 0x5c, 0x90, 0xf9, 0x7e, 0xbc, 0x9b, 0xf1, 0xed, 0x98, + 0x6e, 0xba, 0x56, 0x3e, 0x32, 0xce, 0x8c, 0x25, 0xae, 0x71, 0x41, 0xdf, + 0xef, 0xca, 0x86, 0x00, 0xad, 0x2f, 0x3c, 0xbe, 0x8e, 0x45, 0xb4, 0xa0, + 0x10, 0xae, 0x49, 0x97, 0x82, 0x0a, 0x38, 0xb4, 0x88, 0x81, 0x87, 0xbf, + 0x20, 0x7b, 0xde, 0x43, 0x8a, 0x1e, 0xc7, 0xbe, 0xff, 0xf8, 0x1a, 0x64, + 0x26, 0x5a, 0x4c, 0xe9, 0x90, 0x0b, 0x37, 0xa3, 0x8e, 0x4f, 0xc2, 0x36, + 0x13, 0x88, 0x7b, 0x63, 0x8a, 0x11, 0x3e, 0xf4, 0x16, 0x65, 0xad, 0x2b, + 0x1f, 0x15, 0x76, 0x4c, 0xb5, 0x36, 0x07, 0xd0, 0xee, 0xc3, 0x03, 0xac, + 0x48, 0xc0, 0x55, 0xf5, 0xaa, 0xda, 0xbc, 0xfb, 0xe2, 0xc5, 0xfa, 0xa8, + 0x5e, 0x02, 0x9c, 0x43, 0xe1, 0x60, 0x7a, 0x3a, 0x29, 0xf6, 0x58, 0x02, + 0x95, 0x9b, 0x68, 0x6b, 0x46, 0x8e, 0x81, 0x07, 0xc4, 0x66, 0xa7, 0x31, + 0x7b, 0x50, 0x63, 0xe0, 0x38, 0x02, 0x19, 0x75, 0xb2, 0xf0, 0x17, 0xf1, + 0xf3, 0xba, 0xd0, 0x7c, 0xd0, 0xeb, 0xb4, 0x87, 0x96, 0x41, 0x51, 0xe4, + 0xf8, 0x2b, 0xb5, 0x27, 0x7c, 0x35, 0xa2, 0x18, 0xec, 0x57, 0x0c, 0xb5, + 0x68, 0xad, 0x04, 0x04, 0xa3, 0x71, 0x3a, 0xb7, 0xfc, 0xc1, 0x29, 0x7b, + 0x1e, 0xa9, 0x74, 0x3f, 0x85, 0xac, 0x5d, 0x5a, 0x7e, 0xc8, 0x18, 0xe5, + 0xf9, 0x0a, 0x4a, 0x58, 0xf2, 0xc2, 0x19, 0x2b, 0xba, 0x6d, 0xff, 0xec, + 0xbc, 0xd3, 0x9f, 0x24, 0x5c, 0xc9, 0x32, 0x95, 0x31, 0x90, 0xee, 0x35, + 0x3a, 0x0c, 0xa9, 0x9d, 0xc6, 0x1e, 0xac, 0x4b, 0x4f, 0x83, 0x46, 0x18, + 0x14, 0x0c, 0x9a, 0x32, 0xec, 0xa3, 0x1d, 0x71, 0x8c, 0x95, 0xee, 0x03, + 0xb2, 0x99, 0x2c, 0x63, 0xa6, 0x83, 0xb0, 0x62, 0x88, 0x83, 0xa5, 0xc2, + 0x22, 0xfd, 0xde, 0xf0 +}; +/* K = 02e860266b3b7919a3d74f37f4fa9054f62f37959ee1ce66baea3b15 */ +static const uint8_t ac_dsa_vect99_out[] = { +/* R */ + 0xb1, 0xa9, 0x46, 0xfa, 0x42, 0xa3, 0x6d, 0x83, 0x6d, 0xaa, 0xb5, 0x6f, + 0xe0, 0x15, 0xc9, 0xf2, 0x9c, 0x45, 0x44, 0xa4, 0xa4, 0x7d, 0x48, 0x2e, + 0xa2, 0xd9, 0xcc, 0x5b, +/* S */ + 0xe2, 0x90, 0x5e, 0xe7, 0x0a, 0x5d, 0xc0, 0x99, 0xb7, 0xe0, 0xba, 0xec, + 0x55, 0x66, 0xb2, 0x29, 0xe9, 0xca, 0x8e, 0x7e, 0x00, 0x84, 0x09, 0x66, + 0xcf, 0x56, 0xc4, 0xd5 +}; +#define ac_dsa_vect100_prime ac_dsa_vect91_prime +#define ac_dsa_vect100_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect100_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect100_ptx[] = { +/* Msg */ + 0x28, 0x1f, 0xd1, 0x4a, 0xe2, 0xe7, 0x02, 0xdb, 0xd2, 0x5f, 0x77, 0xd8, + 0xba, 0x8a, 0xf0, 0x9f, 0xdd, 0x77, 0xb1, 0x83, 0x96, 0x48, 0xab, 0x9c, + 0x88, 0x0b, 0xd1, 0x19, 0xd4, 0x47, 0x53, 0x78, 0xfc, 0xd0, 0xd1, 0x24, + 0x15, 0xab, 0xb9, 0xf2, 0x6b, 0xfb, 0x8e, 0x26, 0xf1, 0x08, 0xb1, 0x29, + 0x88, 0x59, 0x23, 0x5e, 0xd1, 0x2e, 0x7f, 0x9e, 0x91, 0x56, 0x28, 0xe3, + 0xca, 0x36, 0xc5, 0x98, 0x6d, 0x18, 0x81, 0x1a, 0x59, 0x05, 0xae, 0xf7, + 0x87, 0x8c, 0x63, 0x00, 0xa9, 0x5e, 0xa8, 0x71, 0x82, 0x01, 0x6e, 0xc5, + 0x95, 0xd3, 0x2e, 0x4d, 0xfc, 0x27, 0x4a, 0xdb, 0x47, 0xc3, 0xed, 0x0f, + 0x6c, 0x38, 0xec, 0x89, 0x3b, 0x33, 0x1f, 0x70, 0x92, 0xf1, 0x9b, 0x72, + 0x4b, 0x9f, 0xe4, 0x3f, 0x0e, 0xf8, 0xde, 0xc1, 0x4f, 0xb7, 0xbf, 0x8b, + 0x90, 0x41, 0xb5, 0x39, 0x0b, 0xeb, 0x44, 0x08 +}; +static const uint8_t ac_dsa_vect100_priv_val[] = { +/* X */ + 0x27, 0x2b, 0x54, 0xa7, 0x7c, 0x97, 0xfd, 0xfa, 0xaa, 0xdf, 0x12, 0xee, + 0x05, 0xe1, 0x27, 0x9f, 0x65, 0xe8, 0x74, 0x8e, 0xf8, 0x73, 0xc4, 0x07, + 0x37, 0x2a, 0xaf, 0x80 +}; +static const uint8_t ac_dsa_vect100_pub_val[] = { +/* Y */ + 0x48, 0xed, 0x8f, 0xa8, 0x9d, 0x07, 0xde, 0xb5, 0xf8, 0xee, 0x6d, 0x38, + 0x74, 0x8a, 0x4e, 0x66, 0x00, 0x20, 0x20, 0xf7, 0x9f, 0xf2, 0x2d, 0x66, + 0xfa, 0x53, 0xad, 0x91, 0x3d, 0x59, 0x68, 0x60, 0xd4, 0xdb, 0xcb, 0x7c, + 0x3a, 0x66, 0x33, 0xcd, 0x42, 0x24, 0xa8, 0x0e, 0x5e, 0x95, 0x90, 0x8f, + 0x87, 0xb1, 0x8a, 0xcc, 0x2e, 0x36, 0x4c, 0x14, 0xb5, 0x1d, 0xe6, 0xbd, + 0xda, 0x7a, 0xd8, 0x96, 0x1d, 0xfd, 0xa4, 0x54, 0xef, 0x47, 0x98, 0xd0, + 0xf7, 0xa3, 0x0e, 0xf1, 0x0e, 0xae, 0x87, 0xde, 0x40, 0x86, 0x77, 0x64, + 0xb8, 0x4b, 0xc5, 0x5d, 0x7c, 0x02, 0x83, 0xf9, 0xc7, 0xcd, 0x2b, 0xe0, + 0x8e, 0x18, 0x52, 0x48, 0x75, 0x12, 0xff, 0x43, 0xa8, 0xd1, 0xe6, 0x8a, + 0x95, 0x11, 0x97, 0xc7, 0x71, 0xf9, 0xe6, 0xc2, 0xff, 0xdf, 0x2c, 0x00, + 0xed, 0x21, 0x63, 0xf8, 0x6d, 0xff, 0x52, 0x41, 0xf9, 0xe2, 0xff, 0x1c, + 0xdb, 0x05, 0xa0, 0xb3, 0xe6, 0x47, 0xe6, 0xfd, 0x23, 0xcc, 0xad, 0xa8, + 0x3b, 0x9c, 0x59, 0x61, 0xe6, 0xe2, 0xfe, 0xf3, 0x29, 0x74, 0x93, 0xdd, + 0xb0, 0xe9, 0x90, 0x29, 0x5d, 0x38, 0x40, 0x5a, 0x24, 0x44, 0x8e, 0x24, + 0x96, 0x27, 0xc0, 0xa7, 0x99, 0x8c, 0xc4, 0x07, 0x2d, 0xd2, 0x91, 0x39, + 0xc5, 0x33, 0x6d, 0x98, 0x56, 0x01, 0x66, 0x42, 0x99, 0x2c, 0xd2, 0x45, + 0xc7, 0x58, 0xa3, 0x03, 0x1e, 0xc2, 0x80, 0x7b, 0x17, 0x1a, 0xba, 0xee, + 0xf1, 0x4c, 0x82, 0xa3, 0xda, 0xb2, 0x01, 0x75, 0x23, 0x51, 0xde, 0x2b, + 0xff, 0xa5, 0x08, 0x5c, 0x13, 0x76, 0x56, 0xe4, 0x69, 0x58, 0x1f, 0x63, + 0xf8, 0x63, 0x79, 0xd6, 0x28, 0x68, 0xac, 0x3e, 0x3a, 0xa2, 0x4d, 0xf9, + 0x82, 0x6a, 0x83, 0x33, 0x14, 0xbd, 0x41, 0xe0, 0xd9, 0xa0, 0xae, 0x56, + 0x80, 0xe6, 0xa4, 0xd2 +}; +/* K = bc06f559baf16de28e915dd27485338abf2bd0e62cdda5b3f1ad05f5 */ +static const uint8_t ac_dsa_vect100_out[] = { +/* R */ + 0x5a, 0x77, 0x63, 0x96, 0x63, 0x66, 0x4e, 0x3f, 0x0b, 0x19, 0xfd, 0x58, + 0x3b, 0xab, 0x6e, 0x68, 0x06, 0x88, 0xcd, 0x89, 0xd5, 0xe0, 0x12, 0xdd, + 0xcb, 0x1e, 0x06, 0xbc, +/* S */ + 0xd4, 0x1c, 0x78, 0x4b, 0x58, 0x3c, 0xbc, 0x52, 0x5b, 0xce, 0x87, 0xc6, + 0xca, 0xa4, 0x40, 0x62, 0xea, 0xc8, 0x47, 0xbc, 0xa8, 0xb0, 0x05, 0xc1, + 0x2a, 0xb5, 0xe5, 0x54 +}; +#define ac_dsa_vect101_prime ac_dsa_vect91_prime +#define ac_dsa_vect101_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect101_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect101_ptx[] = { +/* Msg */ + 0x50, 0x3f, 0x20, 0x42, 0x35, 0x8f, 0x7e, 0x41, 0x42, 0x96, 0xab, 0x2d, + 0x41, 0xf3, 0xa1, 0xf3, 0xf1, 0x11, 0x82, 0xec, 0xa6, 0xc8, 0x2b, 0x2a, + 0xe6, 0xee, 0x83, 0x3d, 0xd7, 0x37, 0xbc, 0xb3, 0x46, 0x91, 0x79, 0x3e, + 0x30, 0x11, 0x00, 0x36, 0xae, 0x54, 0xd4, 0x03, 0xa5, 0xea, 0x45, 0xcb, + 0xf3, 0xe5, 0x51, 0x5b, 0xbf, 0x80, 0xb1, 0xaf, 0x13, 0x98, 0x53, 0xf5, + 0x06, 0x79, 0x2d, 0xf7, 0xff, 0x52, 0x35, 0x99, 0x5e, 0x08, 0x0f, 0x82, + 0xb5, 0x62, 0x32, 0x6a, 0xda, 0xf3, 0x21, 0x15, 0x9a, 0xde, 0xef, 0x20, + 0x38, 0x80, 0x24, 0x50, 0x9f, 0x22, 0x5e, 0x8c, 0x52, 0x35, 0x36, 0x8a, + 0x7b, 0x04, 0x5d, 0x69, 0xe4, 0x72, 0xe6, 0xb2, 0xad, 0x7d, 0x47, 0x0a, + 0x11, 0xf6, 0xaa, 0x8d, 0x4c, 0xa6, 0xc6, 0xcd, 0xb0, 0xf3, 0xed, 0x4e, + 0x06, 0xfb, 0x9a, 0x95, 0xe2, 0xcf, 0x20, 0x0c +}; +static const uint8_t ac_dsa_vect101_priv_val[] = { +/* X */ + 0xc3, 0xff, 0x27, 0xec, 0xdb, 0x6a, 0x7d, 0xe6, 0x42, 0xfb, 0x2d, 0x2f, + 0x9d, 0x93, 0xcc, 0xb5, 0x1d, 0xd0, 0x9b, 0x54, 0x3a, 0x77, 0xfb, 0x2e, + 0x7a, 0x22, 0xa2, 0x9f +}; +static const uint8_t ac_dsa_vect101_pub_val[] = { +/* Y */ + 0x7e, 0x51, 0x4a, 0x04, 0xbb, 0x57, 0x5a, 0xb9, 0x3e, 0x71, 0xb3, 0x55, + 0x5c, 0xdb, 0xac, 0x63, 0x4d, 0x47, 0x5c, 0x58, 0xc1, 0xd9, 0xb4, 0x80, + 0x2e, 0x15, 0x3a, 0x85, 0x8d, 0x02, 0x78, 0x04, 0xea, 0x74, 0x8c, 0x29, + 0x07, 0xeb, 0x99, 0x87, 0xf7, 0x8e, 0x41, 0xc6, 0x75, 0x7e, 0xd5, 0xcb, + 0xf1, 0x02, 0x54, 0x4a, 0x71, 0x46, 0x99, 0xa0, 0x2a, 0x9e, 0xf1, 0x47, + 0x68, 0xf9, 0x6d, 0xbb, 0xdf, 0x48, 0xf3, 0xb2, 0xb3, 0x79, 0x2e, 0xfb, + 0x97, 0x3a, 0x7f, 0x91, 0xf2, 0x60, 0xe0, 0xde, 0xa2, 0x80, 0x34, 0xc9, + 0x15, 0xd9, 0xd5, 0xa8, 0x7a, 0x8f, 0x98, 0x6a, 0x15, 0xf5, 0xd6, 0xf9, + 0x8d, 0x7d, 0x6d, 0x35, 0xbe, 0xe7, 0xe0, 0x59, 0xae, 0xdb, 0x59, 0xfe, + 0x59, 0x5b, 0xa7, 0xda, 0x17, 0xce, 0x0d, 0xb8, 0x95, 0xf3, 0x41, 0x1b, + 0x83, 0x2a, 0x1e, 0x22, 0x1a, 0x83, 0x1f, 0x70, 0x65, 0x87, 0x84, 0x1d, + 0x93, 0x23, 0xe0, 0xc7, 0xf4, 0x43, 0x57, 0x03, 0x12, 0x70, 0x84, 0xb2, + 0x0e, 0xda, 0x9c, 0x6a, 0x24, 0x97, 0x28, 0x01, 0x90, 0xa2, 0xb5, 0x27, + 0x3b, 0x23, 0x1b, 0x44, 0x48, 0x2c, 0x92, 0x53, 0x50, 0x1c, 0x66, 0xef, + 0x11, 0x22, 0x25, 0x3b, 0xe4, 0xea, 0x34, 0x77, 0xff, 0x61, 0x86, 0xaf, + 0x87, 0x18, 0x69, 0xaf, 0x1b, 0xa1, 0x0f, 0x6a, 0x15, 0xd1, 0xc4, 0x32, + 0x94, 0x03, 0x17, 0xd1, 0x19, 0xdd, 0x76, 0x1c, 0xa0, 0x34, 0x2a, 0xb6, + 0x06, 0xd5, 0x32, 0xc4, 0x71, 0x78, 0x3a, 0x4d, 0xcd, 0x6f, 0xac, 0x9b, + 0x8a, 0x67, 0xa6, 0xba, 0xe1, 0x87, 0xc7, 0xdc, 0x64, 0xc7, 0x61, 0x1d, + 0xed, 0x72, 0x73, 0xdc, 0x34, 0x8c, 0xd7, 0x61, 0x3a, 0x52, 0xd0, 0x26, + 0x70, 0xe8, 0x77, 0xe1, 0x8d, 0x0b, 0x60, 0xc8, 0xbb, 0xdd, 0x1a, 0xdb, + 0x04, 0xef, 0xf2, 0x13 +}; +/* K = ac8009b8bc2503f5a68d667696c7fbf66ebba6f88ed3db3504c0c9b6 */ +static const uint8_t ac_dsa_vect101_out[] = { +/* R */ + 0x84, 0x86, 0xab, 0x31, 0xc8, 0x27, 0x8f, 0xad, 0x06, 0x91, 0xfd, 0xd6, + 0xca, 0xc2, 0xf5, 0xfd, 0x79, 0x0b, 0x2f, 0x3f, 0xed, 0x52, 0xb0, 0x99, + 0x86, 0x76, 0x60, 0x42, +/* S */ + 0xb6, 0x96, 0x7b, 0x9e, 0xac, 0xde, 0x5f, 0x48, 0x83, 0x71, 0x0e, 0xba, + 0x38, 0x7b, 0x3c, 0x6f, 0xed, 0xfc, 0x91, 0x94, 0x4e, 0xa5, 0x1f, 0x6f, + 0xfa, 0xb7, 0x25, 0x31 +}; +#define ac_dsa_vect102_prime ac_dsa_vect91_prime +#define ac_dsa_vect102_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect102_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect102_ptx[] = { +/* Msg */ + 0x65, 0x0c, 0x3c, 0x40, 0x9a, 0x88, 0x5f, 0xa6, 0xd1, 0xac, 0x1f, 0xf4, + 0x1e, 0x15, 0xf9, 0x00, 0x1f, 0x6c, 0xd6, 0xa1, 0x52, 0xc3, 0x76, 0xfd, + 0x22, 0xe2, 0x85, 0x1c, 0x9c, 0xba, 0xa5, 0x35, 0x0d, 0x8a, 0x92, 0xb7, + 0x40, 0x10, 0x30, 0x80, 0x93, 0x95, 0xcf, 0x0b, 0x1a, 0x0c, 0xb0, 0x3a, + 0x24, 0xdc, 0x3b, 0x43, 0x47, 0x05, 0x0e, 0x85, 0x53, 0xda, 0x0e, 0x61, + 0xd8, 0x1d, 0xee, 0x44, 0x02, 0xb1, 0xce, 0xc9, 0x7d, 0x89, 0x8d, 0xc6, + 0x88, 0x66, 0x01, 0x02, 0x4f, 0x6b, 0xfb, 0xc4, 0x8d, 0x2f, 0x2c, 0x40, + 0xbf, 0x96, 0xde, 0x9b, 0xc0, 0xe0, 0x78, 0xe4, 0x40, 0xc7, 0x71, 0xf7, + 0x4e, 0x71, 0x15, 0xad, 0x22, 0xba, 0x99, 0x4a, 0xe2, 0xf8, 0x57, 0xc7, + 0xfb, 0x86, 0x5e, 0xa7, 0x50, 0xb1, 0x8c, 0x79, 0xe7, 0xb0, 0x48, 0x56, + 0x3b, 0xec, 0xef, 0x88, 0x98, 0xce, 0xd3, 0xdd +}; +static const uint8_t ac_dsa_vect102_priv_val[] = { +/* X */ + 0xd3, 0x9e, 0x52, 0xc3, 0x9e, 0xa4, 0x6d, 0x6c, 0xe2, 0x74, 0x67, 0x0d, + 0x3e, 0x8a, 0x22, 0x87, 0x5c, 0xb9, 0x87, 0x3d, 0xaf, 0x4c, 0x2e, 0xd8, + 0x3b, 0xd3, 0xbe, 0x37 +}; +static const uint8_t ac_dsa_vect102_pub_val[] = { +/* Y */ + 0x55, 0x18, 0x6d, 0xe3, 0x9e, 0x6a, 0x01, 0x31, 0xad, 0xb7, 0xd8, 0x41, + 0x70, 0xa8, 0xd3, 0x6a, 0xc4, 0xbf, 0x31, 0x36, 0x16, 0xe7, 0x50, 0x22, + 0x0d, 0xe3, 0x56, 0xfb, 0xb1, 0x89, 0x9d, 0xba, 0xaa, 0x65, 0x0d, 0x8d, + 0xe9, 0xa7, 0xaf, 0xab, 0xf3, 0xc4, 0xdd, 0x6a, 0x3c, 0x8b, 0xac, 0x24, + 0x19, 0x22, 0xac, 0xbc, 0xc4, 0xbb, 0x7f, 0xa4, 0xce, 0x5f, 0xcd, 0xb5, + 0xf2, 0x31, 0xcb, 0x17, 0xa8, 0xc0, 0x97, 0x8c, 0x8e, 0x69, 0xfb, 0x82, + 0xd4, 0x46, 0x83, 0xeb, 0xb9, 0xfb, 0x17, 0x89, 0x8e, 0x0b, 0xa4, 0x93, + 0x91, 0x96, 0xed, 0x99, 0x80, 0xeb, 0xec, 0xab, 0xba, 0xad, 0x7b, 0x5b, + 0x34, 0xcd, 0x9e, 0xc0, 0xea, 0x6d, 0xf9, 0x62, 0x43, 0x82, 0x3b, 0x1d, + 0x17, 0x0e, 0xfc, 0xcb, 0x4d, 0x59, 0xbc, 0xba, 0x24, 0xce, 0x5f, 0xaa, + 0xd3, 0x2d, 0x59, 0x1a, 0xd6, 0xec, 0xe0, 0x44, 0x0d, 0x2b, 0x62, 0xa2, + 0x12, 0x05, 0x9e, 0x00, 0x0f, 0xb5, 0x00, 0x5a, 0xbf, 0xec, 0x12, 0x7c, + 0x1e, 0x9f, 0xa7, 0xd3, 0x46, 0x9c, 0x72, 0xb8, 0x9a, 0x96, 0x97, 0x6e, + 0xb4, 0x70, 0x2f, 0x09, 0xf9, 0xc0, 0xa0, 0x97, 0x1b, 0x30, 0xdf, 0xc3, + 0x39, 0x07, 0x2b, 0x5e, 0x3a, 0x6c, 0xe4, 0x0b, 0xfe, 0xa2, 0xd5, 0x2f, + 0x2c, 0x93, 0x0a, 0x11, 0xdd, 0x65, 0x5d, 0xd3, 0x6a, 0xc9, 0xfa, 0xd8, + 0x6f, 0xc3, 0x98, 0x6b, 0x48, 0x71, 0xe7, 0xc9, 0x04, 0x59, 0xa2, 0xea, + 0xa3, 0xb3, 0xd2, 0x2d, 0xd0, 0x4c, 0xb8, 0x24, 0x17, 0x3c, 0xcc, 0x08, + 0x7d, 0x42, 0x9b, 0xb2, 0xa1, 0x88, 0xe0, 0x5d, 0x8a, 0xf0, 0xac, 0x29, + 0x11, 0xc9, 0x07, 0xfd, 0x95, 0x7b, 0x2b, 0xb3, 0x30, 0xa6, 0xf3, 0x98, + 0x7a, 0x59, 0x59, 0x30, 0xb3, 0x12, 0x05, 0x3c, 0x4b, 0xdf, 0x85, 0x6d, + 0xe7, 0x29, 0x38, 0x58 +}; +/* K = 78683cfccca3e13d49999e7bacccb43fa33e11547014baf66b987b83 */ +static const uint8_t ac_dsa_vect102_out[] = { +/* R */ + 0xa0, 0xc4, 0x9d, 0x3c, 0x47, 0x24, 0x0d, 0x30, 0xd2, 0x6f, 0x0c, 0x20, + 0xe4, 0x50, 0x8b, 0x36, 0x0a, 0x84, 0x12, 0x85, 0xde, 0x3f, 0xc1, 0x98, + 0x6f, 0x1e, 0xf9, 0xf6, +/* S */ + 0x97, 0xca, 0xa2, 0xb7, 0x6d, 0x15, 0xb1, 0xf9, 0xf1, 0x77, 0xe2, 0x09, + 0x00, 0x4a, 0x2b, 0x1f, 0xdd, 0x23, 0xa3, 0x94, 0x50, 0x34, 0x58, 0x4c, + 0x2c, 0x15, 0xbf, 0xa2 +}; +#define ac_dsa_vect103_prime ac_dsa_vect91_prime +#define ac_dsa_vect103_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect103_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect103_ptx[] = { +/* Msg */ + 0x64, 0x12, 0x91, 0x53, 0xeb, 0x9c, 0xcc, 0x74, 0xcc, 0x3a, 0xae, 0x1d, + 0x59, 0x99, 0xc6, 0xe9, 0x0d, 0x98, 0x6b, 0xe6, 0xfa, 0x40, 0xc6, 0xc4, + 0xbc, 0x00, 0xb1, 0xc3, 0xf8, 0x07, 0x2d, 0x10, 0xa9, 0xd8, 0xe6, 0xc3, + 0x14, 0xd8, 0x2a, 0x76, 0x41, 0xf8, 0xa3, 0xae, 0x29, 0xd3, 0xe7, 0xdd, + 0x19, 0x42, 0xdb, 0xf0, 0xdc, 0x52, 0xb4, 0xb4, 0xb3, 0x5b, 0xb6, 0x7a, + 0x99, 0x49, 0x42, 0xaf, 0xf0, 0x29, 0xca, 0x6f, 0xa1, 0x87, 0x09, 0x91, + 0x5f, 0xf7, 0x20, 0xab, 0x8f, 0x65, 0xf2, 0x31, 0x15, 0x5c, 0xb1, 0xd0, + 0xdb, 0xcb, 0xa0, 0x4f, 0xc5, 0x19, 0x3a, 0xfc, 0x71, 0xa5, 0xed, 0xdb, + 0x4a, 0x03, 0x86, 0x7e, 0x5c, 0x4b, 0xb9, 0x2d, 0x37, 0xb7, 0xef, 0x77, + 0x1d, 0xa9, 0x54, 0xec, 0x67, 0x54, 0xd5, 0xfb, 0xe2, 0xe3, 0x72, 0xb9, + 0x2d, 0xf6, 0xa3, 0xea, 0x8c, 0x3a, 0x4a, 0xff +}; +static const uint8_t ac_dsa_vect103_priv_val[] = { +/* X */ + 0xa7, 0xd5, 0x66, 0x4e, 0x78, 0x1c, 0x28, 0xf4, 0x85, 0x9f, 0x5c, 0x12, + 0x6c, 0xbe, 0x8d, 0x87, 0xf9, 0xb2, 0xaa, 0x00, 0x27, 0x14, 0x9f, 0x8b, + 0x0a, 0x92, 0x1d, 0x46 +}; +static const uint8_t ac_dsa_vect103_pub_val[] = { +/* Y */ + 0x23, 0xf5, 0x38, 0xd4, 0xec, 0x34, 0x5f, 0xaa, 0x90, 0x6e, 0xff, 0x12, + 0xf6, 0xc5, 0x94, 0x2a, 0xc1, 0x66, 0x91, 0x4b, 0xaf, 0x8e, 0x73, 0x7d, + 0xaf, 0xc7, 0x1e, 0x47, 0x28, 0x55, 0x12, 0xeb, 0xc5, 0x7e, 0xbf, 0x3e, + 0xc6, 0x66, 0x34, 0x2a, 0xbc, 0x05, 0x9b, 0x0e, 0xbd, 0xdb, 0x02, 0x1c, + 0xea, 0xff, 0x6e, 0xf7, 0x58, 0x28, 0xc7, 0xbe, 0x37, 0x66, 0x25, 0x7f, + 0x72, 0x47, 0xa6, 0x7e, 0x14, 0x08, 0x23, 0x9f, 0xa4, 0xdd, 0x1c, 0xaa, + 0xc2, 0xb7, 0x22, 0x9e, 0x8c, 0x1b, 0xcf, 0xd5, 0x7a, 0xee, 0xa4, 0xc0, + 0x4e, 0x15, 0x86, 0x76, 0x4e, 0x28, 0x66, 0x9c, 0x36, 0x12, 0xd8, 0xa0, + 0x06, 0x58, 0x2c, 0xf8, 0xf8, 0x29, 0x10, 0x48, 0x26, 0x91, 0xc1, 0x0e, + 0x41, 0x13, 0x21, 0x6f, 0xc2, 0x4f, 0xeb, 0x29, 0x9f, 0x84, 0xba, 0x58, + 0x70, 0x0a, 0x3b, 0xb6, 0xfd, 0xef, 0xa1, 0x7a, 0x7f, 0xac, 0x9a, 0xa9, + 0xbb, 0x41, 0x0f, 0xe4, 0x11, 0xfb, 0x29, 0x4d, 0x62, 0x94, 0x39, 0x6f, + 0x7f, 0x62, 0x7d, 0xca, 0x04, 0x52, 0xef, 0x59, 0x5d, 0xc2, 0x41, 0x70, + 0xc1, 0x47, 0xd3, 0x86, 0x3f, 0xc1, 0x6e, 0x23, 0x64, 0x50, 0x19, 0xac, + 0xa6, 0x3f, 0xcc, 0x11, 0x52, 0xb0, 0xf7, 0x66, 0xf5, 0xf6, 0x51, 0xc9, + 0xbb, 0x69, 0x9e, 0x2f, 0x50, 0x47, 0xfa, 0x1e, 0x96, 0x03, 0x97, 0x2d, + 0x2c, 0x75, 0x51, 0xb1, 0x8f, 0x3b, 0x16, 0xc1, 0x06, 0xdd, 0xd6, 0xcc, + 0x2e, 0x24, 0xd2, 0xd0, 0x5e, 0x79, 0x68, 0x7e, 0xfe, 0x65, 0x51, 0x02, + 0xe6, 0xbc, 0x15, 0xbc, 0x3a, 0x57, 0xf6, 0x0c, 0x1a, 0x6a, 0xd2, 0x0b, + 0xf1, 0xcb, 0xe6, 0x20, 0x52, 0xad, 0x09, 0x47, 0x43, 0x7b, 0x92, 0xb2, + 0xc9, 0x32, 0xaf, 0x5d, 0x72, 0x77, 0x5d, 0x43, 0x18, 0x3b, 0xbc, 0x6f, + 0x35, 0x9a, 0x4d, 0xf6 +}; +/* K = 85adc235c0060b510825ed2b436bdf003f4d63e299e973b5ddc81fc8 */ +static const uint8_t ac_dsa_vect103_out[] = { +/* R */ + 0x3d, 0x72, 0x89, 0x62, 0xae, 0xc3, 0x58, 0x22, 0xff, 0xf9, 0x9e, 0x1b, + 0x52, 0x17, 0xd8, 0xa6, 0x26, 0x4a, 0x7c, 0x60, 0x8d, 0x80, 0x66, 0xf4, + 0xfc, 0xc9, 0x00, 0x8a, +/* S */ + 0xca, 0x5c, 0x8e, 0x17, 0x8a, 0x14, 0xba, 0x00, 0x6e, 0x93, 0xcf, 0x4a, + 0xd1, 0x19, 0xf0, 0x45, 0xbb, 0xf8, 0x2b, 0x82, 0x87, 0x67, 0xd3, 0xe5, + 0x83, 0xd0, 0xbd, 0x15 +}; +#define ac_dsa_vect104_prime ac_dsa_vect91_prime +#define ac_dsa_vect104_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect104_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect104_ptx[] = { +/* Msg */ + 0x9f, 0xd2, 0x79, 0x1c, 0x41, 0xa2, 0xff, 0xa6, 0xdf, 0x26, 0x10, 0x98, + 0x04, 0xea, 0xf0, 0x70, 0x12, 0x2e, 0x20, 0xbb, 0xb6, 0x2e, 0xcd, 0x98, + 0x11, 0x55, 0x11, 0x36, 0xaa, 0x95, 0x6d, 0xc1, 0xc3, 0x21, 0x32, 0x78, + 0x93, 0xa0, 0xdd, 0xe6, 0xdd, 0x1d, 0x5b, 0x3a, 0x0d, 0x2a, 0x5a, 0xa9, + 0x7e, 0xd7, 0x54, 0xe5, 0xbc, 0x06, 0x67, 0x53, 0x33, 0x8d, 0xdd, 0xfc, + 0x68, 0xeb, 0xa2, 0x17, 0xd2, 0x48, 0x35, 0x05, 0xb0, 0xd7, 0xc0, 0xa4, + 0x37, 0x73, 0x2f, 0x80, 0x46, 0xcf, 0x3b, 0xf5, 0x93, 0x0a, 0x11, 0xef, + 0xd3, 0xf6, 0x59, 0x9c, 0x0f, 0x8d, 0x46, 0x5f, 0xca, 0x76, 0x76, 0xce, + 0x1f, 0x39, 0x10, 0x2c, 0xc0, 0xcd, 0xf1, 0x32, 0x81, 0xb2, 0xc7, 0xb9, + 0xcf, 0x7a, 0x7a, 0xfc, 0xde, 0x68, 0x10, 0x05, 0xe5, 0xa2, 0xe4, 0xe3, + 0x8c, 0xf8, 0x2e, 0x42, 0x13, 0x57, 0xa4, 0x1f +}; +static const uint8_t ac_dsa_vect104_priv_val[] = { +/* X */ + 0xdd, 0xff, 0xa0, 0xc5, 0xaa, 0xfa, 0x1a, 0xcf, 0x98, 0x29, 0x0c, 0xe6, + 0xaa, 0x7a, 0x48, 0xdb, 0x2d, 0xdf, 0xec, 0x48, 0xd6, 0xea, 0x88, 0x17, + 0x45, 0xf2, 0x37, 0x3a +}; +static const uint8_t ac_dsa_vect104_pub_val[] = { +/* Y */ + 0x14, 0x7a, 0xa8, 0xd9, 0xe4, 0xcc, 0xac, 0x90, 0x6d, 0x6a, 0x5a, 0x0b, + 0x65, 0xbf, 0xeb, 0x59, 0xd4, 0xd6, 0x60, 0x37, 0xad, 0x40, 0xd2, 0x88, + 0xd7, 0x53, 0x4f, 0xc9, 0xae, 0x33, 0xc5, 0xaa, 0x70, 0x1c, 0xa1, 0x8e, + 0x60, 0xf0, 0xb6, 0x89, 0x08, 0x28, 0x05, 0x62, 0x11, 0x0a, 0xf7, 0xd1, + 0xd1, 0xbf, 0xb5, 0x38, 0xc5, 0x9d, 0x91, 0x00, 0x98, 0x03, 0x84, 0xae, + 0x93, 0xb7, 0x7b, 0xe0, 0x33, 0x2a, 0x03, 0xcc, 0x56, 0x7d, 0x4d, 0x63, + 0x4f, 0x76, 0x48, 0xa1, 0xb9, 0xfd, 0x25, 0xda, 0xf2, 0x50, 0xb2, 0x86, + 0x96, 0x83, 0xe9, 0x42, 0x6d, 0x75, 0x56, 0x1a, 0x5e, 0x17, 0x87, 0xc2, + 0xba, 0xb7, 0x11, 0x32, 0x75, 0x7d, 0xff, 0xc4, 0xb7, 0x66, 0x51, 0x43, + 0xe7, 0xd8, 0x7d, 0x50, 0xf1, 0x2d, 0x01, 0x07, 0x5b, 0xef, 0x5f, 0x4b, + 0x0f, 0x14, 0xcb, 0x3f, 0x10, 0x9d, 0x15, 0x99, 0xe5, 0xbf, 0x94, 0xde, + 0x01, 0x11, 0xa0, 0x1a, 0xf5, 0x7e, 0x8c, 0x13, 0xf5, 0x83, 0xbe, 0x4d, + 0xc9, 0x00, 0x89, 0x61, 0x9c, 0x72, 0xd2, 0x2a, 0x49, 0x5c, 0x45, 0x25, + 0x6e, 0xc7, 0x87, 0xa5, 0x83, 0x2d, 0x2e, 0x4c, 0x4a, 0x42, 0xf0, 0x00, + 0x18, 0x37, 0xa9, 0x75, 0xac, 0x8f, 0xbb, 0x8c, 0x56, 0x5f, 0x77, 0xb2, + 0x53, 0x30, 0x3b, 0x1a, 0x87, 0x33, 0x06, 0xfa, 0x5c, 0xf6, 0xa5, 0xda, + 0xb6, 0x2d, 0x7b, 0x1b, 0xa3, 0xd7, 0x0d, 0xc1, 0x1b, 0x4e, 0x4f, 0x87, + 0x5e, 0x3e, 0xda, 0xe5, 0x0e, 0xe8, 0xe5, 0x17, 0x8d, 0xd0, 0x9a, 0x33, + 0x4c, 0xf9, 0x26, 0x0c, 0x3e, 0x0a, 0x10, 0x91, 0x1d, 0x38, 0x1d, 0x7f, + 0x56, 0x01, 0xc0, 0xb3, 0xf2, 0x69, 0x46, 0x68, 0x20, 0x18, 0x62, 0x99, + 0x22, 0x94, 0x6d, 0xd7, 0x3f, 0x81, 0x24, 0x08, 0x16, 0xae, 0x96, 0x06, + 0x91, 0x1c, 0xbf, 0xd6 +}; +/* K = 3ee8b1f03687b9726de846f54618ac45f8e2d6e8957ce6996bf50c2d */ +static const uint8_t ac_dsa_vect104_out[] = { +/* R */ + 0xa7, 0xcc, 0x74, 0x86, 0xf4, 0x7f, 0xe6, 0x2f, 0xe3, 0x25, 0x4e, 0xd6, + 0x55, 0xe1, 0xc9, 0x94, 0x90, 0x2d, 0x79, 0x7f, 0x0d, 0x7c, 0xa9, 0x3f, + 0xb9, 0x7d, 0xf9, 0xc1, +/* S */ + 0x91, 0x4b, 0xf7, 0xd1, 0x5c, 0xe2, 0xc9, 0xec, 0xc5, 0xae, 0x15, 0x0d, + 0x63, 0x08, 0xfc, 0x55, 0x7d, 0x94, 0xe1, 0xef, 0x18, 0xc0, 0x86, 0x0a, + 0xa6, 0x8a, 0xd4, 0x8e +}; +#define ac_dsa_vect105_prime ac_dsa_vect91_prime +#define ac_dsa_vect105_sub_prime ac_dsa_vect91_sub_prime +#define ac_dsa_vect105_base ac_dsa_vect91_base +static const uint8_t ac_dsa_vect105_ptx[] = { +/* Msg */ + 0x6b, 0x78, 0xb4, 0xde, 0x5f, 0x75, 0x26, 0xdb, 0xed, 0x08, 0xee, 0x0f, + 0xf4, 0xe4, 0x33, 0x35, 0xb6, 0x0c, 0xd3, 0xbc, 0x37, 0x1b, 0x70, 0xcd, + 0x4f, 0xd9, 0xce, 0x45, 0xbf, 0x06, 0x50, 0x83, 0x91, 0x08, 0x5d, 0x14, + 0x2c, 0xc3, 0x89, 0x1b, 0x17, 0x91, 0x67, 0xc7, 0x6a, 0x13, 0x50, 0xca, + 0x8e, 0xf8, 0xce, 0x75, 0x4a, 0xb1, 0xd6, 0x24, 0x57, 0x2e, 0x43, 0x71, + 0x95, 0x66, 0x0f, 0x00, 0x4c, 0xb7, 0xbe, 0xd2, 0xff, 0x3b, 0x0f, 0x7c, + 0x7e, 0x53, 0xf8, 0x53, 0x30, 0x5a, 0x38, 0x21, 0xdf, 0xba, 0xec, 0x33, + 0xe2, 0x20, 0xdf, 0x3c, 0x3e, 0xf7, 0xa7, 0x9f, 0x34, 0xe8, 0x2c, 0xc8, + 0xff, 0xf8, 0x41, 0x5f, 0x10, 0x8c, 0x00, 0x0f, 0x21, 0xc3, 0xbb, 0x21, + 0xa4, 0xc3, 0x32, 0x67, 0xa2, 0x13, 0xcb, 0x4a, 0x55, 0x8e, 0x3b, 0x37, + 0x0d, 0x17, 0xc6, 0x39, 0x24, 0x7b, 0xff, 0xeb +}; +static const uint8_t ac_dsa_vect105_priv_val[] = { +/* X */ + 0x9d, 0xa0, 0x93, 0xf7, 0x3c, 0x71, 0x4e, 0x0b, 0x99, 0x94, 0x07, 0x8b, + 0x6c, 0xc7, 0x48, 0xa6, 0x75, 0xcf, 0x4f, 0x3b, 0xbc, 0x50, 0x2a, 0x23, + 0x89, 0x50, 0x97, 0xb3 +}; +static const uint8_t ac_dsa_vect105_pub_val[] = { +/* Y */ + 0x91, 0x47, 0x67, 0x0f, 0x64, 0xae, 0xdf, 0xa2, 0x46, 0x93, 0x8b, 0xa7, + 0x7f, 0xb9, 0xc1, 0xac, 0x27, 0x1c, 0xa1, 0x09, 0x1d, 0x86, 0x3f, 0x32, + 0xf0, 0x0d, 0x5c, 0xcd, 0xeb, 0xe7, 0x02, 0x2d, 0x26, 0x8b, 0xa9, 0x05, + 0x1d, 0x80, 0xfe, 0x55, 0xdf, 0xc5, 0xf6, 0x4b, 0x07, 0x16, 0xc4, 0xbb, + 0x8d, 0xa4, 0xb1, 0x1e, 0x9e, 0x28, 0x34, 0x48, 0xed, 0x8b, 0xe4, 0x27, + 0x8e, 0x93, 0xb5, 0x2d, 0x67, 0x56, 0x49, 0xab, 0xb4, 0x59, 0x56, 0x52, + 0x2f, 0x92, 0x63, 0x4c, 0x92, 0xa0, 0x9a, 0xc5, 0xa5, 0xd6, 0x03, 0xaa, + 0xe2, 0xa6, 0xd0, 0x4a, 0x43, 0x52, 0x39, 0x53, 0x8d, 0xe3, 0x03, 0xfc, + 0x05, 0xb9, 0xed, 0x5f, 0xcb, 0x84, 0x3f, 0x05, 0x36, 0xa8, 0xab, 0x94, + 0x2d, 0x9c, 0x3b, 0xdc, 0x90, 0xfe, 0xed, 0x97, 0x44, 0x9c, 0xe3, 0x09, + 0xbe, 0x8a, 0xb1, 0x19, 0x67, 0x6a, 0x96, 0xc2, 0xa6, 0x0a, 0x06, 0x69, + 0x2e, 0x8c, 0xd5, 0x9e, 0x55, 0xe6, 0xff, 0x8d, 0x91, 0xfa, 0x46, 0x29, + 0x66, 0x55, 0x55, 0x26, 0xc9, 0x87, 0xfc, 0x44, 0xba, 0x42, 0x0b, 0xbf, + 0xf7, 0x68, 0xf7, 0xa7, 0xfd, 0x36, 0x36, 0x38, 0xd5, 0xce, 0x4d, 0x9e, + 0xa1, 0xed, 0xd7, 0xfd, 0x39, 0x9d, 0x6c, 0x65, 0x62, 0x7b, 0xbc, 0x33, + 0x7f, 0x13, 0x1c, 0x73, 0x45, 0xb3, 0xd7, 0x9b, 0x4d, 0xb7, 0x41, 0x25, + 0x62, 0x54, 0x7c, 0xa2, 0xa7, 0xc8, 0xea, 0x55, 0xeb, 0xdd, 0xdd, 0x05, + 0xa4, 0xb4, 0x20, 0x0c, 0x72, 0xab, 0x2b, 0x83, 0x31, 0x11, 0x52, 0xb7, + 0x1c, 0x99, 0x30, 0x6c, 0x1d, 0x3b, 0x3d, 0x44, 0x66, 0x57, 0xbe, 0x65, + 0xe5, 0x8d, 0x7c, 0xf8, 0xa0, 0x62, 0xb2, 0x25, 0xce, 0x93, 0x78, 0x02, + 0x59, 0x05, 0x46, 0x85, 0x3f, 0x19, 0x2a, 0x6a, 0x8c, 0x8b, 0x3f, 0xf7, + 0xa6, 0x2f, 0xcf, 0x80 +}; +/* K = bdd792b1ece3d0ce428cc1294b9d7497208de86929a2aad2ef481557 */ +static const uint8_t ac_dsa_vect105_out[] = { +/* R */ + 0x2f, 0x85, 0xee, 0x5c, 0x32, 0xd5, 0x46, 0xc6, 0x8f, 0x0a, 0xa2, 0x69, + 0x8b, 0xea, 0xe5, 0x3e, 0x28, 0x48, 0xc3, 0x75, 0x51, 0x7a, 0x57, 0x0e, + 0x0f, 0x1b, 0x55, 0x46, +/* S */ + 0x54, 0x76, 0x67, 0xe8, 0xb1, 0x3f, 0x21, 0x63, 0x5a, 0x0b, 0x10, 0x6d, + 0x32, 0x4d, 0x06, 0xc8, 0x5b, 0x74, 0xa6, 0x4c, 0xe9, 0x22, 0x5c, 0xc5, + 0xe0, 0x84, 0x35, 0x81 +}; +/* [mod = L=2048, N=224, SHA-256] */ +static const uint8_t ac_dsa_vect106_prime[] = { +/* P */ + 0xa4, 0xc7, 0xea, 0xab, 0x42, 0xc4, 0xc7, 0x3b, 0x75, 0x77, 0x70, 0x91, + 0x64, 0x89, 0xf1, 0x7c, 0xd5, 0x07, 0x25, 0xcd, 0x0a, 0x4b, 0xc4, 0xe1, + 0xcf, 0x67, 0xf7, 0x63, 0xb8, 0xc1, 0xde, 0x2d, 0x6d, 0xab, 0x98, 0x56, + 0xba, 0xaf, 0xb0, 0x08, 0xf3, 0x65, 0xb1, 0x8a, 0x42, 0xe1, 0x4d, 0xc5, + 0x1f, 0x35, 0x0b, 0x88, 0xec, 0xa0, 0x20, 0x9c, 0x5a, 0xa4, 0xfd, 0x71, + 0xa7, 0xa9, 0x6c, 0x76, 0x5f, 0x59, 0x01, 0xc2, 0x1e, 0x72, 0x05, 0x70, + 0xd7, 0x83, 0x7b, 0xec, 0x7c, 0x76, 0xd2, 0xe4, 0x93, 0x44, 0x73, 0x1c, + 0xa3, 0x94, 0x05, 0xd0, 0xa8, 0x79, 0xb9, 0xe0, 0xdc, 0xd1, 0xa8, 0x12, + 0x5f, 0xd1, 0x30, 0xec, 0x1e, 0x78, 0x3e, 0x65, 0x4b, 0x94, 0xe3, 0x00, + 0x2e, 0x6b, 0x62, 0x9e, 0x90, 0x4a, 0xb3, 0x87, 0x78, 0x67, 0x72, 0x0c, + 0xbd, 0x54, 0xb4, 0x27, 0x0a, 0x9e, 0x15, 0xcd, 0x02, 0x8c, 0x7c, 0xc7, + 0x96, 0xf0, 0x6c, 0x27, 0x2a, 0x66, 0x09, 0x51, 0x92, 0x8f, 0xdb, 0xeb, + 0x2d, 0xca, 0x06, 0x1b, 0x41, 0xe9, 0x32, 0x25, 0x73, 0x05, 0x74, 0x2f, + 0xf1, 0x6e, 0x2f, 0x42, 0x91, 0x91, 0xd5, 0xe5, 0xf1, 0xa6, 0xdd, 0xf6, + 0xe7, 0x8c, 0x5d, 0x77, 0x22, 0xcf, 0xf8, 0x0a, 0x9c, 0x0b, 0xd5, 0xc8, + 0xd7, 0xae, 0xba, 0x8c, 0x04, 0x43, 0x89, 0x92, 0xb0, 0x75, 0xe3, 0x07, + 0xc1, 0x53, 0x4c, 0x49, 0xad, 0x38, 0x0f, 0x47, 0x7f, 0x5f, 0x79, 0x87, + 0xdc, 0x17, 0x2c, 0x16, 0x1d, 0xca, 0x38, 0xdc, 0xaf, 0x3f, 0xb3, 0x84, + 0x6c, 0x72, 0xc9, 0x11, 0x9a, 0x52, 0x99, 0xad, 0xc7, 0x48, 0x95, 0x1b, + 0x3d, 0xce, 0x0d, 0x00, 0xd4, 0xa9, 0x01, 0x38, 0x00, 0xb2, 0x00, 0x82, + 0x03, 0xb7, 0x24, 0x65, 0xbc, 0x6a, 0x84, 0xae, 0x05, 0x9a, 0x30, 0xc4, + 0x52, 0x2d, 0xea, 0x57 +}; +static const uint8_t ac_dsa_vect106_sub_prime[] = { +/* Q */ + 0xce, 0x89, 0xfe, 0x33, 0x2b, 0x8e, 0x4e, 0xb3, 0xd1, 0xe8, 0xdd, 0xce, + 0xa5, 0xd1, 0x63, 0xa5, 0xbc, 0x13, 0xb6, 0x3f, 0x16, 0x99, 0x37, 0x55, + 0x42, 0x7a, 0xef, 0x43 +}; +static const uint8_t ac_dsa_vect106_base[] = { +/* G */ + 0x8c, 0x46, 0x5e, 0xdf, 0x5a, 0x18, 0x07, 0x30, 0x29, 0x1e, 0x08, 0x0d, + 0xfc, 0x53, 0x85, 0x39, 0x7a, 0x50, 0x06, 0x45, 0x0d, 0xba, 0x2e, 0xfe, + 0x01, 0x29, 0x26, 0x4f, 0xbd, 0x89, 0x7b, 0xb5, 0x57, 0x9c, 0xa0, 0xea, + 0xb1, 0x9a, 0xa2, 0x78, 0x22, 0x04, 0x24, 0x72, 0x4b, 0x4f, 0x2a, 0x6f, + 0x6e, 0xe6, 0x32, 0x84, 0x32, 0xab, 0xf6, 0x61, 0x38, 0x06, 0x46, 0x09, + 0x72, 0x33, 0x50, 0x53, 0x39, 0xc5, 0x51, 0x9d, 0x35, 0x7d, 0x71, 0x12, + 0xb6, 0xee, 0xc9, 0x38, 0xb8, 0x5d, 0x5a, 0xa7, 0x5c, 0xc2, 0xe3, 0x80, + 0x92, 0xf0, 0xa5, 0x30, 0xac, 0xb5, 0x4e, 0x50, 0xfe, 0x82, 0xc4, 0xd5, + 0x62, 0xfb, 0x0f, 0x30, 0x36, 0xb8, 0x0b, 0x30, 0x33, 0x40, 0x23, 0xeb, + 0xbe, 0x66, 0x37, 0xa0, 0x01, 0x0b, 0x00, 0xc7, 0xdb, 0x86, 0x37, 0x11, + 0x68, 0x56, 0x36, 0x71, 0xe1, 0xe0, 0xf0, 0x28, 0xae, 0xdb, 0xd4, 0x5d, + 0x2d, 0x57, 0x26, 0x21, 0xa6, 0x09, 0x98, 0x2a, 0x07, 0x3e, 0x51, 0xaa, + 0xe2, 0x77, 0x07, 0xaf, 0xbe, 0xef, 0x29, 0xe2, 0xec, 0xee, 0x84, 0xd7, + 0xa6, 0xd5, 0xda, 0x38, 0x2b, 0xe3, 0xa3, 0x5f, 0x42, 0xb6, 0xc6, 0x68, + 0x49, 0x20, 0x2a, 0xb1, 0x9d, 0x02, 0x5b, 0x86, 0x9d, 0x08, 0x77, 0x64, + 0x76, 0xd1, 0xab, 0x98, 0x14, 0x75, 0xad, 0x2a, 0xd2, 0xf3, 0xe6, 0xfd, + 0x07, 0xe3, 0x06, 0x96, 0xd9, 0x0a, 0x62, 0x68, 0x16, 0xdf, 0x60, 0xd6, + 0xca, 0x7a, 0xfd, 0x7b, 0x48, 0x2f, 0x94, 0x2f, 0x83, 0xb4, 0x5c, 0xc8, + 0x29, 0x33, 0x73, 0x1f, 0x87, 0xfa, 0xee, 0x32, 0x09, 0x00, 0xf2, 0xaa, + 0x3e, 0x70, 0xb1, 0x86, 0x7e, 0x14, 0x30, 0xe4, 0x0b, 0xe6, 0x7c, 0x07, + 0xf9, 0x29, 0x02, 0x99, 0xef, 0x06, 0x7b, 0x8b, 0x24, 0xa7, 0x51, 0x5b, + 0x3f, 0x99, 0x2c, 0x07 +}; +static const uint8_t ac_dsa_vect106_ptx[] = { +/* Msg */ + 0xce, 0xc8, 0xd2, 0x84, 0x3d, 0xee, 0x7c, 0xb5, 0xf9, 0x11, 0x9b, 0x75, + 0x56, 0x25, 0x85, 0xe0, 0x5c, 0x5c, 0xe2, 0xf4, 0xe6, 0x45, 0x7e, 0x9b, + 0xcc, 0x3c, 0x1c, 0x78, 0x1c, 0xcd, 0x2c, 0x04, 0x42, 0xb6, 0x28, 0x2a, + 0xea, 0x61, 0x0f, 0x71, 0x61, 0xdc, 0xed, 0xe1, 0x76, 0xe7, 0x74, 0x86, + 0x1f, 0x7d, 0x26, 0x91, 0xbe, 0x6c, 0x89, 0x4a, 0xc3, 0xeb, 0xf8, 0x0c, + 0x0f, 0xab, 0x21, 0xe5, 0x2a, 0x3e, 0x63, 0xae, 0x0b, 0x35, 0x02, 0x57, + 0x62, 0xcc, 0xd6, 0xc9, 0xe1, 0xfe, 0xcc, 0x7f, 0x9f, 0xe0, 0x0a, 0xa5, + 0x5c, 0x0c, 0x3a, 0xe3, 0x3a, 0xe8, 0x8f, 0x66, 0x18, 0x7f, 0x95, 0x98, + 0xeb, 0xa9, 0xf8, 0x63, 0x17, 0x1f, 0x3f, 0x56, 0x48, 0x46, 0x25, 0xbf, + 0x39, 0xd8, 0x83, 0x42, 0x73, 0x49, 0xb8, 0x67, 0x1d, 0x9b, 0xb7, 0xd3, + 0x96, 0x18, 0x06, 0x94, 0xe5, 0xb5, 0x46, 0xae +}; +static const uint8_t ac_dsa_vect106_priv_val[] = { +/* X */ + 0x55, 0x15, 0x95, 0xec, 0xcb, 0xb0, 0x03, 0xb0, 0xbf, 0x8d, 0xdd, 0xa1, + 0x84, 0xa5, 0x9d, 0xa5, 0x1e, 0x45, 0x9a, 0x0d, 0x28, 0x20, 0x5e, 0x55, + 0x92, 0xca, 0x4c, 0xb1 +}; +static const uint8_t ac_dsa_vect106_pub_val[] = { +/* Y */ + 0x74, 0x8a, 0x40, 0x23, 0x72, 0x11, 0xa2, 0xd9, 0x85, 0x25, 0x96, 0xe7, + 0xa8, 0x91, 0xf4, 0x3d, 0x4e, 0xb0, 0xee, 0x48, 0x82, 0x6c, 0x9c, 0xfb, + 0x33, 0x6b, 0xbb, 0x68, 0xdb, 0xe5, 0xa5, 0xe1, 0x6b, 0x2e, 0x12, 0x71, + 0xd4, 0xd1, 0x3d, 0xe0, 0x36, 0x44, 0xbb, 0x85, 0xef, 0x6b, 0xe5, 0x23, + 0xa4, 0xd4, 0xd8, 0x84, 0x15, 0xbc, 0xd5, 0x96, 0xba, 0x8e, 0x0a, 0x3c, + 0x4f, 0x64, 0x39, 0xe9, 0x81, 0xed, 0x01, 0x3d, 0x7d, 0x9c, 0x70, 0x33, + 0x6f, 0xeb, 0xf7, 0xd4, 0x20, 0xcf, 0xed, 0x02, 0xc2, 0x67, 0x45, 0x7b, + 0xb3, 0xf3, 0xe7, 0xc8, 0x21, 0x45, 0xd2, 0xaf, 0x54, 0x83, 0x0b, 0x94, + 0x2e, 0xc7, 0x4a, 0x5d, 0x50, 0x3e, 0x42, 0x26, 0xcd, 0x25, 0xdd, 0x75, + 0xde, 0xcd, 0x3f, 0x50, 0xf0, 0xa8, 0x58, 0x15, 0x5d, 0x7b, 0xe7, 0x99, + 0x41, 0x08, 0x36, 0xdd, 0xc5, 0x59, 0xce, 0x99, 0xe1, 0xae, 0x51, 0x38, + 0x08, 0xfd, 0xae, 0xac, 0x34, 0x84, 0x3d, 0xd7, 0x25, 0x8f, 0x16, 0xf6, + 0x7f, 0x19, 0x20, 0x5f, 0x6f, 0x13, 0x92, 0x51, 0xa4, 0x18, 0x6d, 0xa8, + 0x49, 0x6d, 0x5e, 0x90, 0xd3, 0xfe, 0xcf, 0x8e, 0xd1, 0x0b, 0xe6, 0xc2, + 0x5f, 0xf5, 0xeb, 0x33, 0xd9, 0x60, 0xc9, 0xa8, 0xf4, 0xc5, 0x81, 0xc8, + 0xc7, 0x24, 0xca, 0x43, 0xb7, 0x61, 0xe9, 0xfd, 0xb5, 0xaf, 0x66, 0xbf, + 0xfb, 0x9d, 0x2e, 0xbb, 0x11, 0xa6, 0xb5, 0x04, 0xa1, 0xfb, 0xe4, 0xf8, + 0x34, 0xec, 0xb6, 0xac, 0x25, 0x4c, 0xab, 0x51, 0x3e, 0x94, 0x3b, 0x9a, + 0x95, 0x3a, 0x70, 0x84, 0xb3, 0x30, 0x5c, 0x66, 0x1b, 0xfa, 0xd4, 0x34, + 0xf6, 0xa8, 0x35, 0x50, 0x3c, 0x9a, 0xde, 0x7f, 0x4a, 0x57, 0xf5, 0xc9, + 0x65, 0xec, 0x30, 0x1e, 0xcd, 0xe9, 0x38, 0xee, 0x31, 0xb4, 0xde, 0xb0, + 0x38, 0xaf, 0x97, 0xb3 +}; +/* K = 6f326546aa174b3d319ef7331ec8dfd363dd78ae583a920165ff7e54 */ +static const uint8_t ac_dsa_vect106_out[] = { +/* R */ + 0x9c, 0x5f, 0xa4, 0x68, 0x79, 0xdd, 0xaf, 0x5c, 0x14, 0xf0, 0x7d, 0xfb, + 0x53, 0x20, 0x71, 0x5f, 0x67, 0xa6, 0xfe, 0xc1, 0x79, 0xe3, 0xad, 0x53, + 0x34, 0x2f, 0xb6, 0xd1, +/* S */ + 0xc3, 0xe1, 0x7e, 0x7b, 0x3c, 0x4d, 0x0a, 0xc8, 0xd4, 0x9f, 0x4d, 0xd0, + 0xf0, 0x4c, 0x16, 0xa0, 0x94, 0xf4, 0x2d, 0xa0, 0xaf, 0xcc, 0x6c, 0x90, + 0xf5, 0xf1, 0xbb, 0xc8 +}; +#define ac_dsa_vect107_prime ac_dsa_vect106_prime +#define ac_dsa_vect107_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect107_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect107_ptx[] = { +/* Msg */ + 0xf3, 0xbb, 0x27, 0xbf, 0x9d, 0x41, 0x2f, 0x13, 0x22, 0x9a, 0x56, 0xd2, + 0xd1, 0x53, 0x3e, 0xae, 0x63, 0xf4, 0x00, 0x04, 0xc1, 0x43, 0xc6, 0xb9, + 0x2f, 0x6e, 0x60, 0x6d, 0x26, 0x3d, 0xd2, 0xda, 0x75, 0x81, 0xe5, 0xeb, + 0x20, 0xb6, 0xcd, 0x02, 0x1e, 0x3a, 0xb6, 0x3b, 0x49, 0x8a, 0xba, 0xfc, + 0xe0, 0x1b, 0x4a, 0xd7, 0xac, 0x86, 0x28, 0xf7, 0xa1, 0x84, 0x9c, 0x4e, + 0x45, 0x4f, 0x11, 0x68, 0xae, 0x97, 0xad, 0xfa, 0xb1, 0xfa, 0xdb, 0xd3, + 0x13, 0xfc, 0xa7, 0x38, 0x17, 0x26, 0xf5, 0x04, 0x57, 0x52, 0xda, 0xba, + 0xad, 0x6e, 0xa3, 0x25, 0x0d, 0x30, 0x3a, 0x54, 0x96, 0xbb, 0xa2, 0xfa, + 0x48, 0x95, 0xae, 0x49, 0xf0, 0x6a, 0x9a, 0xa6, 0x45, 0x1a, 0xe7, 0x0c, + 0xf3, 0x3b, 0x5f, 0x06, 0xfa, 0x17, 0xca, 0xc0, 0x14, 0x4f, 0x28, 0xbd, + 0x19, 0xfb, 0x2a, 0xc0, 0x41, 0xa5, 0x78, 0xed +}; +static const uint8_t ac_dsa_vect107_priv_val[] = { +/* X */ + 0x02, 0x7d, 0x01, 0x71, 0x59, 0x8e, 0x7e, 0xcf, 0x23, 0xf2, 0x92, 0x2d, + 0x02, 0x57, 0xe6, 0x04, 0x29, 0x1c, 0xef, 0xa7, 0x7b, 0x5c, 0xfa, 0xf1, + 0xb3, 0xe3, 0x1a, 0xc4 +}; +static const uint8_t ac_dsa_vect107_pub_val[] = { +/* Y */ + 0x00, 0xc7, 0xaa, 0xbe, 0x30, 0xfa, 0x4c, 0x3d, 0x1b, 0xa8, 0x5e, 0x7a, + 0xe0, 0xaa, 0xe7, 0x93, 0x60, 0xe5, 0xea, 0xb3, 0x04, 0x1b, 0xca, 0xaa, + 0x5d, 0x32, 0x1c, 0x92, 0xf3, 0x47, 0x1e, 0x41, 0x94, 0xc1, 0x04, 0x84, + 0xcf, 0xf1, 0x52, 0xba, 0xde, 0x6b, 0x7d, 0x61, 0x9c, 0xf2, 0x86, 0x77, + 0x34, 0x75, 0x29, 0x8f, 0x88, 0x3e, 0xfd, 0xf6, 0x4c, 0x08, 0xb6, 0x92, + 0x58, 0x3d, 0xe3, 0x1b, 0xe0, 0xa4, 0xe2, 0xb8, 0xe8, 0xd5, 0x08, 0xec, + 0x14, 0x5c, 0x65, 0xa3, 0x69, 0xce, 0x61, 0x95, 0x44, 0x6c, 0x52, 0xd0, + 0x23, 0x72, 0xeb, 0xa5, 0x62, 0xf9, 0xa9, 0xd7, 0xcb, 0x24, 0xd2, 0xec, + 0x3b, 0x0a, 0x1a, 0xb8, 0x33, 0xe4, 0xd7, 0x62, 0x3b, 0x04, 0x55, 0xa4, + 0x1e, 0xec, 0x75, 0x9d, 0x07, 0xa3, 0xc8, 0xa2, 0x0d, 0x88, 0xa9, 0x26, + 0x40, 0x8c, 0x20, 0xf1, 0x67, 0x56, 0x01, 0xbe, 0x53, 0xcf, 0xfd, 0x65, + 0x61, 0x7b, 0x66, 0xfd, 0x4e, 0xb3, 0x53, 0xa1, 0xf2, 0xdb, 0x31, 0xf6, + 0x63, 0x43, 0xb0, 0x7f, 0xaf, 0x60, 0xde, 0x0b, 0x6a, 0x68, 0x08, 0x09, + 0xc6, 0x16, 0x6a, 0xdb, 0xf5, 0xe5, 0x04, 0xc5, 0xc6, 0x1b, 0xab, 0xb8, + 0x4b, 0xe7, 0x2c, 0x02, 0xd3, 0xeb, 0xee, 0xe0, 0x66, 0xd9, 0xea, 0xb0, + 0xd0, 0xec, 0xdf, 0xe0, 0x1b, 0x8c, 0xcd, 0x67, 0x28, 0xee, 0x91, 0x23, + 0xb9, 0xd2, 0x11, 0x54, 0xb2, 0xbc, 0x9a, 0x13, 0x43, 0x63, 0x56, 0x64, + 0x02, 0x29, 0x1a, 0xc8, 0xa4, 0x84, 0xee, 0x32, 0xeb, 0x88, 0x40, 0x46, + 0xd4, 0x0f, 0xde, 0x7c, 0xab, 0xbf, 0x51, 0xd1, 0xd1, 0x20, 0x6d, 0xf1, + 0xc5, 0xec, 0xf2, 0x90, 0xab, 0x7e, 0xa7, 0x2a, 0xbb, 0x5b, 0xd3, 0xbe, + 0x8d, 0x91, 0xc0, 0x2b, 0xb6, 0x3f, 0x80, 0x97, 0x18, 0xba, 0x1d, 0x38, + 0x0a, 0xf8, 0x83, 0x31 +}; +/* K = 7494772f199ab7a7e9a248f6c2df918c9da62dc2d4176b7db9419b37 */ +static const uint8_t ac_dsa_vect107_out[] = { +/* R */ + 0x79, 0xa6, 0xae, 0xd7, 0x3c, 0xe1, 0x77, 0xed, 0x35, 0x81, 0xf5, 0xd1, + 0x81, 0xa7, 0x7f, 0x00, 0x0d, 0x63, 0x58, 0x51, 0x4e, 0xa9, 0x5c, 0xb0, + 0x38, 0x8a, 0x6a, 0xdd, +/* S */ + 0x2b, 0x85, 0x97, 0xa6, 0x94, 0x56, 0x4e, 0x26, 0x7b, 0x6f, 0x25, 0x0a, + 0x4c, 0x76, 0x36, 0x1f, 0x8c, 0xdf, 0x49, 0x86, 0x3a, 0x79, 0x02, 0xaf, + 0xa4, 0x8f, 0xd6, 0xd8 +}; +#define ac_dsa_vect108_prime ac_dsa_vect106_prime +#define ac_dsa_vect108_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect108_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect108_ptx[] = { +/* Msg */ + 0xe7, 0x14, 0xc0, 0x16, 0x31, 0x70, 0x4e, 0x94, 0x47, 0x39, 0x0f, 0x5c, + 0x31, 0x5c, 0x96, 0x15, 0xa7, 0xa5, 0x28, 0x63, 0xb1, 0x43, 0x70, 0x65, + 0x83, 0xf6, 0x61, 0x59, 0x5c, 0x50, 0x5a, 0xec, 0x47, 0x7e, 0xeb, 0x5a, + 0xd6, 0xd6, 0x40, 0xca, 0x81, 0x2c, 0xe1, 0x17, 0x50, 0xb6, 0x7b, 0xc8, + 0xbe, 0xde, 0x2e, 0x4f, 0x96, 0x18, 0xdb, 0xe7, 0x37, 0x6c, 0xab, 0x62, + 0x31, 0xb2, 0x12, 0x48, 0xec, 0x91, 0x4a, 0xe1, 0x82, 0xdf, 0x87, 0x53, + 0x36, 0x2d, 0x21, 0x18, 0xa6, 0x5e, 0x66, 0xf6, 0x40, 0x18, 0x81, 0x08, + 0x04, 0xad, 0x97, 0xfc, 0xc1, 0xa8, 0x7b, 0x8c, 0x9f, 0x34, 0x9d, 0x10, + 0x01, 0xe4, 0xb0, 0x9b, 0x04, 0x69, 0x91, 0xe6, 0xab, 0xe6, 0x33, 0x8f, + 0xbe, 0xf7, 0xbe, 0x48, 0xf1, 0xc8, 0x0c, 0x35, 0x0d, 0x29, 0x62, 0xeb, + 0x6b, 0x8f, 0xce, 0x25, 0xb6, 0x9f, 0x8d, 0xc9 +}; +static const uint8_t ac_dsa_vect108_priv_val[] = { +/* X */ + 0x69, 0x11, 0xc2, 0x1a, 0x3d, 0xa8, 0x8d, 0x54, 0xff, 0x9a, 0xb5, 0x8a, + 0xe2, 0x07, 0x5a, 0x2a, 0xff, 0xa3, 0xf3, 0xeb, 0x65, 0x69, 0x78, 0xea, + 0x26, 0xbf, 0xa7, 0x02 +}; +static const uint8_t ac_dsa_vect108_pub_val[] = { +/* Y */ + 0x04, 0xd3, 0x01, 0xf0, 0x01, 0x82, 0x1b, 0x03, 0xc9, 0x13, 0x94, 0xc5, + 0x20, 0x83, 0x9a, 0xb6, 0xaa, 0xa9, 0x53, 0x25, 0xc1, 0x08, 0xa0, 0x2d, + 0xad, 0x9d, 0xb4, 0x8b, 0x3c, 0x80, 0x33, 0xd6, 0x44, 0x3b, 0xcb, 0xf0, + 0x50, 0x45, 0x23, 0x0c, 0xa8, 0x8a, 0xaf, 0x98, 0xa8, 0xc4, 0xcb, 0x6b, + 0x09, 0x5b, 0x35, 0x2d, 0x91, 0xb4, 0xc4, 0x16, 0xf6, 0x32, 0xfa, 0xb4, + 0x9d, 0x45, 0xac, 0x90, 0x69, 0x9a, 0x5a, 0x41, 0x96, 0x30, 0xa8, 0x1d, + 0x47, 0x3b, 0xc8, 0x91, 0x22, 0xeb, 0x5b, 0xac, 0xb9, 0x1c, 0x40, 0xca, + 0xa4, 0xe4, 0xbc, 0xc4, 0x76, 0xf3, 0xca, 0x77, 0xbf, 0x6a, 0x21, 0x03, + 0x7a, 0x06, 0xbe, 0x24, 0xf1, 0x1c, 0x64, 0x5b, 0x0c, 0x21, 0xb8, 0x57, + 0xfd, 0xc5, 0xc0, 0x4f, 0xbb, 0xf0, 0xa2, 0x6e, 0xfc, 0x56, 0x9c, 0xdb, + 0xb0, 0xea, 0x98, 0x9b, 0xa0, 0xe0, 0x37, 0xc2, 0x3f, 0x22, 0xb0, 0xc5, + 0xf1, 0x64, 0x3d, 0x77, 0xd9, 0x8f, 0x2d, 0xe2, 0x48, 0xcc, 0xc3, 0x66, + 0x72, 0xd3, 0x97, 0xd3, 0x0c, 0x1c, 0x5e, 0x13, 0x19, 0xfc, 0x7e, 0x58, + 0x42, 0xae, 0x1a, 0x9f, 0xcd, 0x9e, 0x96, 0xfe, 0x89, 0x0a, 0x74, 0xdd, + 0xee, 0x91, 0xa3, 0x9c, 0xe7, 0x32, 0xe4, 0xc0, 0xea, 0xf7, 0x09, 0x4b, + 0x53, 0xb7, 0xb4, 0x09, 0x30, 0x38, 0x60, 0xb0, 0xb4, 0x94, 0x4c, 0xc8, + 0x1b, 0x4a, 0x42, 0xd4, 0x05, 0x38, 0xcf, 0xe5, 0x12, 0xb9, 0x68, 0x0e, + 0x0a, 0x28, 0x1b, 0x1f, 0xbb, 0xf6, 0x39, 0x13, 0x9e, 0x80, 0x66, 0xad, + 0x63, 0x8c, 0xf8, 0x46, 0xc9, 0xea, 0x51, 0xfb, 0x4c, 0x4e, 0xf8, 0x49, + 0x21, 0xf1, 0x6a, 0x6c, 0xa3, 0xf2, 0xbd, 0x15, 0x81, 0x57, 0xc5, 0x51, + 0x73, 0x9c, 0x9d, 0x02, 0x3e, 0x27, 0x0b, 0x3d, 0xe7, 0xc2, 0xf1, 0xd7, + 0x68, 0x3c, 0xf8, 0x09 +}; +/* K = bfb79665f7d6df843d2c39357173e415724c83e1a10932efb9e22676 */ +static const uint8_t ac_dsa_vect108_out[] = { +/* R */ + 0x79, 0x0b, 0x4d, 0xca, 0xe3, 0x1f, 0xe4, 0x5c, 0xd3, 0xa7, 0xbb, 0x6f, + 0xa1, 0x0d, 0xcf, 0x9e, 0xde, 0x1f, 0x06, 0x71, 0x23, 0xf9, 0x3b, 0xaa, + 0xd7, 0xed, 0xb4, 0x89, +/* S */ + 0x71, 0xe3, 0xe4, 0x6d, 0xfe, 0x04, 0x04, 0x96, 0xce, 0x4c, 0x5e, 0x49, + 0x0f, 0x69, 0x44, 0xa2, 0x3c, 0xd5, 0xe6, 0x6c, 0xe9, 0xb4, 0xd9, 0xac, + 0xbe, 0x41, 0x30, 0xce +}; +#define ac_dsa_vect109_prime ac_dsa_vect106_prime +#define ac_dsa_vect109_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect109_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect109_ptx[] = { +/* Msg */ + 0x3f, 0x6e, 0x48, 0x2f, 0xd4, 0x84, 0xed, 0x3d, 0x07, 0xf1, 0xd0, 0x76, + 0x1f, 0x2d, 0x60, 0xfc, 0x96, 0xd4, 0x6e, 0xb0, 0xec, 0xd1, 0x0a, 0x59, + 0xdd, 0x4f, 0x39, 0x2e, 0x3d, 0x3b, 0x2c, 0xbe, 0x18, 0x40, 0x10, 0xe1, + 0x32, 0x68, 0x55, 0x78, 0xb1, 0xf6, 0x30, 0x32, 0x39, 0x79, 0x8a, 0x53, + 0x03, 0xa8, 0x11, 0x69, 0xd4, 0xf5, 0x2f, 0xba, 0x0d, 0x20, 0xa4, 0x28, + 0x34, 0xde, 0x29, 0x3e, 0x3a, 0x7b, 0x32, 0x84, 0x8b, 0x65, 0xdd, 0x30, + 0x8e, 0xef, 0x53, 0x50, 0xd6, 0x33, 0x29, 0x74, 0x65, 0x42, 0x5b, 0x7b, + 0x15, 0x95, 0xff, 0xc8, 0xea, 0x7b, 0x12, 0x58, 0x96, 0xf8, 0x9e, 0x28, + 0x44, 0x56, 0x16, 0x35, 0xf5, 0x2e, 0xc6, 0x2f, 0xab, 0x2e, 0xcf, 0xea, + 0x28, 0x8d, 0x23, 0xf0, 0xa7, 0x71, 0xcd, 0x63, 0x11, 0x80, 0x61, 0x03, + 0x13, 0x51, 0x72, 0xcf, 0x9f, 0xef, 0x14, 0x55 +}; +static const uint8_t ac_dsa_vect109_priv_val[] = { +/* X */ + 0x20, 0x32, 0x80, 0x83, 0xaa, 0x86, 0x51, 0x11, 0x40, 0x32, 0x4f, 0xd0, + 0x35, 0x70, 0x67, 0xa1, 0xd6, 0xab, 0xfc, 0x31, 0x6e, 0x77, 0xfe, 0x3d, + 0x26, 0x0f, 0x0e, 0xf2 +}; +static const uint8_t ac_dsa_vect109_pub_val[] = { +/* Y */ + 0x9f, 0xc1, 0xb2, 0x92, 0xeb, 0xe1, 0x55, 0x31, 0x57, 0x9f, 0x35, 0xdd, + 0xa8, 0xd7, 0x06, 0xbe, 0xe0, 0xda, 0x85, 0x7c, 0xd6, 0x96, 0xa1, 0x0a, + 0xf7, 0x70, 0xdc, 0x35, 0x62, 0x32, 0x73, 0x6c, 0xf8, 0x93, 0xf7, 0x41, + 0x1a, 0x9d, 0x27, 0x18, 0xb3, 0x9f, 0x38, 0x81, 0x18, 0xd1, 0x77, 0xcd, + 0x8d, 0x0f, 0xd7, 0xca, 0x3b, 0x3c, 0x22, 0x0f, 0x3a, 0xa7, 0x43, 0xd8, + 0xb1, 0x67, 0x21, 0x9d, 0x3c, 0x2c, 0x78, 0x3e, 0x1f, 0x09, 0xd8, 0xb8, + 0xdf, 0x8e, 0xc7, 0xe1, 0x75, 0x78, 0xc5, 0x32, 0x94, 0x88, 0xc8, 0x7a, + 0x89, 0x67, 0x8d, 0x28, 0x18, 0xa9, 0x93, 0x66, 0xb7, 0x85, 0xd5, 0x3f, + 0x6c, 0xa6, 0x99, 0x5e, 0x19, 0x3b, 0xa5, 0xca, 0x26, 0xc0, 0x0b, 0x84, + 0x9f, 0x90, 0x27, 0xca, 0x5d, 0xf5, 0xbb, 0x7e, 0xc8, 0x7f, 0xe7, 0x87, + 0x35, 0xae, 0x88, 0x0f, 0x1a, 0x97, 0xda, 0xbc, 0x3c, 0xa7, 0x98, 0x5d, + 0x8c, 0xbc, 0x81, 0xbe, 0x82, 0x4c, 0x1f, 0xfb, 0x95, 0x3f, 0x10, 0x96, + 0xbf, 0x92, 0x62, 0x26, 0xfb, 0x5e, 0x9d, 0x4a, 0xd4, 0x3e, 0x93, 0x63, + 0xda, 0x5e, 0x6b, 0x73, 0x8c, 0x9a, 0x2f, 0x95, 0x1a, 0xb3, 0x29, 0x4e, + 0x2b, 0x28, 0x22, 0xcf, 0x52, 0x82, 0xbb, 0x41, 0x34, 0x15, 0x8a, 0xa9, + 0x0a, 0xb9, 0xc8, 0xf0, 0xf6, 0x4d, 0x05, 0xa0, 0xd6, 0x25, 0xa7, 0x5b, + 0xc2, 0xd6, 0xa4, 0xae, 0x3d, 0xd1, 0x1f, 0xc0, 0x5e, 0xde, 0x7b, 0x66, + 0x47, 0xae, 0x7c, 0x07, 0x50, 0xdd, 0xb2, 0x73, 0xfe, 0x5f, 0x88, 0x28, + 0x31, 0x8a, 0x91, 0xdb, 0x31, 0x72, 0xad, 0x59, 0x16, 0x6a, 0xac, 0xf2, + 0xda, 0x4f, 0x37, 0x04, 0xd1, 0x69, 0xeb, 0xc8, 0x60, 0xd9, 0xe1, 0xc6, + 0x46, 0x4a, 0xbc, 0x2b, 0x65, 0x30, 0x13, 0x77, 0x4d, 0x29, 0x37, 0x5b, + 0x77, 0xba, 0xc1, 0xec +}; +/* K = 8f4398bb9fe1b393c1d90a62e178899261fa0501c98bd9a8178b364c */ +static const uint8_t ac_dsa_vect109_out[] = { +/* R */ + 0x3b, 0x5d, 0x80, 0x34, 0xc4, 0xb8, 0xad, 0x97, 0x01, 0xbf, 0x29, 0xb1, + 0x00, 0x06, 0xdb, 0x69, 0xd0, 0x17, 0xfd, 0xe8, 0x63, 0x80, 0x79, 0xdd, + 0x7b, 0xbf, 0xac, 0xe7, +/* S */ + 0xcd, 0xe0, 0x1d, 0xf5, 0x4a, 0x66, 0xce, 0xf3, 0xc0, 0x53, 0x86, 0x48, + 0x52, 0x5b, 0x25, 0x0c, 0xb1, 0xf0, 0x87, 0x07, 0xf5, 0xff, 0x11, 0x4b, + 0xde, 0xbf, 0xf8, 0xf7 +}; +#define ac_dsa_vect110_prime ac_dsa_vect106_prime +#define ac_dsa_vect110_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect110_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect110_ptx[] = { +/* Msg */ + 0x31, 0xa2, 0x78, 0xf8, 0x81, 0xfd, 0xd3, 0x75, 0x56, 0x5c, 0x0f, 0x28, + 0xff, 0x75, 0x75, 0xf2, 0x16, 0x11, 0x04, 0x86, 0xd6, 0xfe, 0x08, 0xda, + 0xe8, 0xfd, 0x07, 0x29, 0x50, 0x97, 0x8b, 0xdf, 0xf6, 0x01, 0xde, 0xd1, + 0xef, 0x22, 0x6b, 0x5d, 0x90, 0x4c, 0x47, 0xf7, 0x14, 0x2a, 0x8f, 0x46, + 0x65, 0xe0, 0x3e, 0xfe, 0x58, 0x70, 0xda, 0x2d, 0xd1, 0xab, 0x80, 0xe4, + 0x49, 0xf5, 0xc7, 0x57, 0xb3, 0xb6, 0x99, 0x6a, 0x9d, 0xc0, 0xb5, 0xb2, + 0x75, 0x0b, 0x97, 0xbb, 0xad, 0x2f, 0x55, 0x3f, 0xba, 0xff, 0x2a, 0xed, + 0xec, 0xfc, 0x9f, 0xf6, 0xa9, 0x70, 0xd1, 0x56, 0xe4, 0xfe, 0x38, 0x52, + 0x97, 0x9d, 0xc9, 0x13, 0xbd, 0xb2, 0x96, 0xa3, 0x21, 0xf7, 0x66, 0x36, + 0x72, 0x39, 0xde, 0x45, 0xe4, 0x7c, 0xbe, 0xf4, 0xd7, 0x9b, 0xfa, 0x3d, + 0x57, 0x68, 0x87, 0xc6, 0x5f, 0x7f, 0x8a, 0x60 +}; +static const uint8_t ac_dsa_vect110_priv_val[] = { +/* X */ + 0xb7, 0x5e, 0xe8, 0x0c, 0x89, 0x6b, 0x42, 0x14, 0x8e, 0xeb, 0x7d, 0x18, + 0x5d, 0x45, 0xf5, 0x87, 0x2a, 0x37, 0x58, 0xe9, 0x83, 0xb4, 0xfd, 0xd8, + 0xc2, 0xe7, 0x1c, 0xa0 +}; +static const uint8_t ac_dsa_vect110_pub_val[] = { +/* Y */ + 0x7e, 0xc0, 0xa5, 0x41, 0x88, 0x28, 0x15, 0x9e, 0x3e, 0xc8, 0x29, 0xf7, + 0x93, 0xb9, 0x6e, 0xa3, 0x46, 0x03, 0x28, 0xde, 0xa2, 0x1b, 0xa1, 0x57, + 0xd7, 0x1a, 0xc3, 0x06, 0xf9, 0xbc, 0xde, 0x61, 0x7d, 0xb6, 0x73, 0x68, + 0xd5, 0x92, 0xbf, 0x46, 0xd4, 0x69, 0x18, 0xb1, 0x30, 0xfc, 0x7e, 0x3d, + 0x11, 0x89, 0xee, 0xb7, 0x99, 0x6d, 0x5f, 0x66, 0x0a, 0xce, 0x30, 0xbe, + 0x50, 0x9a, 0x26, 0xb2, 0x18, 0xd8, 0x65, 0xd9, 0xe5, 0x6b, 0xa7, 0xf6, + 0x19, 0x42, 0xe5, 0x67, 0xd8, 0xcd, 0xab, 0x96, 0xa7, 0x8c, 0xa3, 0x03, + 0xc6, 0xb0, 0x1d, 0x98, 0x9b, 0x1e, 0x78, 0xae, 0x95, 0x64, 0x23, 0xe3, + 0x5b, 0x5a, 0x46, 0x6c, 0x16, 0x07, 0x4e, 0x0b, 0xc9, 0xe8, 0x37, 0x23, + 0x40, 0xd2, 0xc1, 0x25, 0x16, 0xc2, 0x2d, 0x5e, 0x1f, 0xf6, 0x5a, 0xbd, + 0x5d, 0x44, 0x82, 0x15, 0xb6, 0xba, 0xf5, 0x65, 0xde, 0x18, 0x20, 0x1c, + 0x1f, 0xd5, 0xba, 0x3d, 0xe8, 0x7e, 0x5d, 0x5b, 0x43, 0x7d, 0x2f, 0x48, + 0xde, 0xee, 0x72, 0xa1, 0x2e, 0x65, 0x5f, 0x8c, 0x7f, 0xa3, 0x13, 0xd2, + 0x4b, 0xd0, 0xc8, 0xc2, 0x0e, 0x59, 0xc9, 0x0e, 0xdf, 0xbf, 0x5d, 0xfc, + 0x05, 0x7c, 0x6b, 0x67, 0x98, 0x50, 0xae, 0x41, 0x82, 0x61, 0x78, 0xf2, + 0xf3, 0x04, 0xca, 0x3b, 0x92, 0xa9, 0xba, 0xc3, 0x1a, 0xb3, 0xcf, 0x74, + 0xdf, 0xb8, 0xee, 0x5b, 0x64, 0x3b, 0x4a, 0x34, 0x1e, 0xbb, 0xdb, 0x5d, + 0xbd, 0x24, 0xd0, 0xb7, 0x82, 0xc5, 0xb4, 0x50, 0x59, 0x6a, 0xbf, 0xc3, + 0xdf, 0x9e, 0xe0, 0x5f, 0x45, 0xd0, 0xea, 0x2e, 0x8f, 0xf4, 0x35, 0x7c, + 0xd3, 0x60, 0x5f, 0x35, 0x06, 0xce, 0x58, 0xa5, 0x39, 0x4f, 0x1f, 0x24, + 0x44, 0xc2, 0x63, 0x59, 0x29, 0x9a, 0xf1, 0x53, 0x53, 0x2b, 0xc9, 0x0d, + 0xaa, 0xf9, 0x54, 0xae +}; +/* K = ba98b478a9e12a1d03b6aca65c0acb265764357cca67d04d782fded9 */ +static const uint8_t ac_dsa_vect110_out[] = { +/* R */ + 0x2b, 0x47, 0xe2, 0x57, 0xbf, 0x72, 0xad, 0xf3, 0x4d, 0x61, 0x8d, 0x3a, + 0x6c, 0x46, 0x14, 0x28, 0x81, 0xbd, 0xd0, 0x68, 0x9a, 0x46, 0xf1, 0xcb, + 0x31, 0x99, 0xee, 0x6c, +/* S */ + 0xcc, 0x1f, 0xf2, 0xfa, 0x37, 0x55, 0xa0, 0xe8, 0x1e, 0xdf, 0xc7, 0x53, + 0xbc, 0xf1, 0x4e, 0x63, 0x74, 0x13, 0xea, 0xee, 0x0f, 0x22, 0xd7, 0x88, + 0x6b, 0x05, 0x8d, 0xcc +}; +#define ac_dsa_vect111_prime ac_dsa_vect106_prime +#define ac_dsa_vect111_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect111_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect111_ptx[] = { +/* Msg */ + 0xa6, 0xd7, 0x60, 0x47, 0xbd, 0x18, 0xde, 0xef, 0xe7, 0x0d, 0xc0, 0xa4, + 0xbd, 0x08, 0x2a, 0x10, 0xfa, 0x52, 0x1d, 0xff, 0xda, 0x78, 0x2a, 0x93, + 0x64, 0xb9, 0xe2, 0xb1, 0x1e, 0x14, 0x7e, 0x1a, 0x36, 0xa1, 0x1c, 0x43, + 0x00, 0x67, 0x21, 0x44, 0xd9, 0xb9, 0x74, 0x13, 0x2b, 0x49, 0x75, 0xf2, + 0x7e, 0xa6, 0xe8, 0xe4, 0x6b, 0x55, 0xae, 0xdd, 0x67, 0x23, 0xe5, 0x3e, + 0x7b, 0xc9, 0xb4, 0x0d, 0xce, 0x24, 0x49, 0x28, 0x5a, 0x69, 0x08, 0x85, + 0xc3, 0x22, 0x3b, 0x63, 0x6c, 0xb5, 0xc4, 0x87, 0x3c, 0x5d, 0xda, 0xeb, + 0xb0, 0xb6, 0xdc, 0x5b, 0x69, 0x43, 0x8d, 0x88, 0x1a, 0x52, 0x59, 0x05, + 0xa5, 0x1b, 0xdb, 0x97, 0xb0, 0x51, 0xdb, 0xfe, 0xc6, 0xdd, 0x4a, 0x7b, + 0x58, 0x02, 0x97, 0xb0, 0x8f, 0x2b, 0xa6, 0x0f, 0x2e, 0xad, 0x3a, 0x07, + 0x53, 0x1c, 0xf2, 0x99, 0x97, 0x74, 0x13, 0xaf +}; +static const uint8_t ac_dsa_vect111_priv_val[] = { +/* X */ + 0x1c, 0x0e, 0x4c, 0x78, 0xa4, 0xad, 0x4f, 0x50, 0x46, 0xf9, 0x29, 0xe7, + 0xcd, 0x3d, 0xb3, 0xf4, 0x8b, 0x86, 0xe5, 0xea, 0xb4, 0xa5, 0xe2, 0xbe, + 0x61, 0xa0, 0x8d, 0xfe +}; +static const uint8_t ac_dsa_vect111_pub_val[] = { +/* Y */ + 0x8b, 0x26, 0x62, 0x77, 0x5b, 0xb7, 0xf1, 0x92, 0x52, 0x20, 0x45, 0x94, + 0xa8, 0x4b, 0x46, 0x9f, 0x3d, 0xc8, 0xd6, 0x6e, 0xb7, 0x99, 0x3b, 0xed, + 0x12, 0x2d, 0x8a, 0x06, 0x5f, 0x59, 0xea, 0x81, 0xd4, 0xc4, 0x84, 0xce, + 0xe5, 0xbd, 0x76, 0x6a, 0x5c, 0x13, 0x7d, 0xd5, 0x7e, 0x43, 0xe9, 0x41, + 0x33, 0x98, 0x52, 0x15, 0x05, 0x09, 0xac, 0xbd, 0xe6, 0xf7, 0x95, 0x7a, + 0x1b, 0x04, 0xec, 0xe7, 0x18, 0x56, 0x5c, 0xe8, 0xb6, 0x37, 0xea, 0x03, + 0x1b, 0xfa, 0x34, 0x10, 0xa5, 0x80, 0x74, 0x4b, 0x3d, 0x49, 0x59, 0xa5, + 0xe7, 0x5e, 0x31, 0x5d, 0xd3, 0x3c, 0x02, 0xb5, 0x2c, 0x7c, 0x56, 0x21, + 0x8b, 0x7c, 0xdf, 0xdc, 0x24, 0xf5, 0x1d, 0xdb, 0x4e, 0x78, 0x49, 0xfa, + 0xf2, 0x89, 0xcf, 0x80, 0x6c, 0x4d, 0x3c, 0x6b, 0x87, 0x7c, 0x63, 0xdb, + 0xfa, 0xb5, 0x69, 0x92, 0x0a, 0x2b, 0x21, 0x9c, 0x39, 0x21, 0x5c, 0x5e, + 0x3e, 0x63, 0x8a, 0x3e, 0xbe, 0xeb, 0xfb, 0x52, 0xc8, 0xb3, 0x8e, 0x82, + 0x85, 0xa8, 0x5d, 0x62, 0x5f, 0xc1, 0xb4, 0x2f, 0xbf, 0x0e, 0x51, 0x8c, + 0x58, 0xeb, 0x8f, 0x45, 0xfa, 0x54, 0x67, 0x6e, 0xd8, 0xb0, 0x09, 0x41, + 0x5d, 0x26, 0x96, 0xee, 0x9b, 0x51, 0x53, 0xdd, 0xdc, 0x5e, 0xeb, 0xef, + 0x49, 0xcc, 0x76, 0x59, 0x81, 0x0a, 0x98, 0xd4, 0xb5, 0xe8, 0xb9, 0x69, + 0x5f, 0xb2, 0xd9, 0xe4, 0xbf, 0x19, 0x20, 0x93, 0x74, 0x7c, 0x87, 0x8a, + 0x95, 0x65, 0xb4, 0x7c, 0xba, 0x05, 0x3c, 0x48, 0xba, 0x7c, 0x0b, 0x9b, + 0x1c, 0xe7, 0x7f, 0x8a, 0x3e, 0x10, 0x43, 0xe8, 0x7f, 0xcc, 0x61, 0x32, + 0xcb, 0xe8, 0xfa, 0xd7, 0xc7, 0x38, 0xe9, 0xbf, 0x79, 0xbc, 0xcb, 0x41, + 0x4e, 0xf2, 0x49, 0x07, 0x67, 0x5b, 0xa7, 0xcb, 0x05, 0x9a, 0x83, 0x89, + 0xee, 0xe7, 0xeb, 0xbe +}; +/* K = 5135933094326e3953250a29d5f5c4c9a1033ccb844ab35a14c19d31 */ +static const uint8_t ac_dsa_vect111_out[] = { +/* R */ + 0xb8, 0x67, 0x4d, 0x1b, 0xa6, 0xf1, 0x33, 0x98, 0xf5, 0xe8, 0x94, 0x4b, + 0x82, 0x15, 0x0d, 0x9e, 0x9b, 0xc9, 0xb2, 0x10, 0xa8, 0x14, 0x95, 0xb3, + 0x35, 0x94, 0x7e, 0x64, +/* S */ + 0x75, 0xfc, 0xfe, 0x96, 0x92, 0x61, 0x86, 0xef, 0xa1, 0x2c, 0x00, 0x7c, + 0x09, 0x85, 0x20, 0x51, 0x47, 0xcf, 0x65, 0xab, 0xd1, 0x08, 0x36, 0x3d, + 0x8b, 0x89, 0x11, 0x90 +}; +#define ac_dsa_vect112_prime ac_dsa_vect106_prime +#define ac_dsa_vect112_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect112_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect112_ptx[] = { +/* Msg */ + 0xf0, 0xd5, 0xb3, 0x33, 0x27, 0x69, 0x55, 0x36, 0xe3, 0x51, 0xb3, 0x7c, + 0xd3, 0xfe, 0xea, 0x69, 0x3f, 0x10, 0x37, 0x7a, 0x5f, 0x8b, 0xdd, 0x91, + 0x34, 0x02, 0xc2, 0xed, 0x67, 0xa0, 0xfc, 0x1e, 0x7b, 0xca, 0xab, 0x00, + 0x2f, 0xa7, 0x79, 0x93, 0x59, 0x50, 0xc7, 0x6e, 0x42, 0xa4, 0x91, 0xa6, + 0x8f, 0xa6, 0xfe, 0x44, 0x5c, 0xd3, 0x55, 0x75, 0xcf, 0xce, 0x5f, 0x37, + 0x6c, 0x29, 0xc4, 0xe8, 0xc0, 0xfe, 0xd5, 0xa5, 0x48, 0x7e, 0xf4, 0x18, + 0xb9, 0x6f, 0xa5, 0x75, 0x2a, 0x03, 0x3a, 0xd0, 0x79, 0x59, 0x65, 0x3d, + 0x1b, 0x8a, 0xf6, 0x70, 0x2d, 0xcc, 0xe4, 0x0e, 0xfe, 0xf2, 0x1b, 0x2d, + 0x64, 0xcf, 0x06, 0xbd, 0x8b, 0x03, 0xda, 0xdb, 0x2f, 0xda, 0xaa, 0x73, + 0xfb, 0x2d, 0x3d, 0x75, 0xb0, 0x98, 0x5e, 0x9a, 0xef, 0xa1, 0xf9, 0x44, + 0x42, 0xa5, 0x49, 0x1a, 0xe4, 0x6d, 0x7c, 0x51 +}; +static const uint8_t ac_dsa_vect112_priv_val[] = { +/* X */ + 0x26, 0x90, 0x55, 0xde, 0x62, 0xd0, 0x74, 0x23, 0x24, 0x80, 0x36, 0x24, + 0x52, 0x2e, 0x67, 0x82, 0x34, 0xc3, 0x60, 0x0a, 0xe7, 0xbc, 0x39, 0x96, + 0xc8, 0xd1, 0x7b, 0xc9 +}; +static const uint8_t ac_dsa_vect112_pub_val[] = { +/* Y */ + 0xa4, 0x48, 0xb0, 0xd4, 0x48, 0x24, 0x9a, 0x0e, 0x54, 0xa9, 0x45, 0x86, + 0x88, 0x29, 0x85, 0xa0, 0x8e, 0x19, 0x97, 0x22, 0x81, 0xd1, 0x0d, 0x9e, + 0x7f, 0xb5, 0x7f, 0x95, 0xdf, 0xee, 0xbf, 0x97, 0x1f, 0x6d, 0x9d, 0xfe, + 0x88, 0xdb, 0xd0, 0xa4, 0x95, 0x0f, 0x52, 0x82, 0x00, 0xbe, 0x7b, 0x60, + 0x58, 0x65, 0xee, 0xfd, 0x8e, 0xc2, 0x74, 0xac, 0x53, 0xe4, 0xed, 0x5b, + 0x28, 0x8c, 0x6a, 0x00, 0x72, 0x1e, 0x02, 0x88, 0x81, 0xb9, 0x72, 0x5f, + 0xb0, 0xa9, 0xce, 0x41, 0x53, 0xdc, 0xc1, 0xfe, 0x7b, 0x5c, 0xe7, 0x25, + 0x9f, 0x16, 0xea, 0x8b, 0x32, 0x45, 0x6c, 0xb0, 0x3b, 0xae, 0x81, 0xbe, + 0x77, 0xf3, 0xf6, 0xe8, 0xb3, 0x9f, 0x52, 0x58, 0x7b, 0xc9, 0xdd, 0x47, + 0xa2, 0x64, 0x27, 0x8d, 0x5d, 0x8e, 0xcb, 0xe1, 0xba, 0x57, 0x42, 0x69, + 0x69, 0x6a, 0x7b, 0xb1, 0xe1, 0x67, 0xa3, 0xae, 0x71, 0x10, 0xec, 0x05, + 0x7f, 0x42, 0x91, 0xa1, 0xba, 0xe8, 0x25, 0x7d, 0x69, 0xc1, 0x0a, 0xe0, + 0x95, 0xf3, 0x27, 0x16, 0x21, 0xc6, 0xd6, 0xb5, 0x60, 0x79, 0x25, 0xc3, + 0x49, 0x81, 0x89, 0xd7, 0x51, 0xb7, 0xc9, 0xbf, 0x30, 0xe6, 0x56, 0x83, + 0xcb, 0x39, 0xfb, 0x51, 0xbd, 0x59, 0x2f, 0x1f, 0x98, 0x27, 0x9f, 0x2e, + 0x7b, 0x2b, 0x53, 0xad, 0x54, 0x68, 0x16, 0xa8, 0x50, 0x8c, 0x93, 0xf0, + 0x34, 0x96, 0xde, 0x7c, 0x47, 0x16, 0x5f, 0x5c, 0xf2, 0x97, 0x68, 0x7a, + 0xd7, 0xd6, 0x0f, 0x01, 0x0a, 0xb9, 0xfa, 0xad, 0x01, 0x53, 0x43, 0x2e, + 0xc1, 0xcc, 0xdf, 0x26, 0xd4, 0xf4, 0x41, 0xdf, 0x62, 0x53, 0x94, 0xe2, + 0x10, 0x42, 0x08, 0xbb, 0x67, 0x5e, 0x7f, 0x97, 0x2b, 0x6c, 0x66, 0xed, + 0x70, 0x28, 0xa1, 0xe3, 0xf4, 0x5a, 0x67, 0x1a, 0xb2, 0x71, 0x6c, 0x60, + 0xfe, 0xab, 0xcc, 0x22 +}; +/* K = 0d9d0b3e1f24cbb18320f9ce896cfca2a5a6bb28ceec83e1ff3218d3 */ +static const uint8_t ac_dsa_vect112_out[] = { +/* R */ + 0x01, 0xa4, 0xf4, 0xbc, 0x63, 0x3e, 0xbf, 0x84, 0x2a, 0x28, 0xd0, 0x45, + 0x18, 0x4d, 0x25, 0x05, 0x29, 0x92, 0x0d, 0xf2, 0x80, 0x54, 0x5c, 0xba, + 0x00, 0x50, 0x1c, 0xad, +/* S */ + 0x09, 0xfc, 0xeb, 0x2d, 0xf2, 0x00, 0xb7, 0xc0, 0xa5, 0x6a, 0xe7, 0x96, + 0x9f, 0x54, 0x73, 0xb7, 0xa1, 0xf6, 0xb7, 0x03, 0xf7, 0x43, 0xf9, 0x54, + 0xa4, 0xfb, 0xdb, 0xe3 +}; +#define ac_dsa_vect113_prime ac_dsa_vect106_prime +#define ac_dsa_vect113_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect113_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect113_ptx[] = { +/* Msg */ + 0xf5, 0x8e, 0x03, 0x9d, 0x66, 0x6e, 0xf0, 0x64, 0xcc, 0xcc, 0x7e, 0xd0, + 0x15, 0x01, 0x7c, 0x68, 0x39, 0x3d, 0x14, 0x55, 0x30, 0x0d, 0x0c, 0x4f, + 0xd4, 0xf0, 0xd3, 0x02, 0xc4, 0x3a, 0x00, 0x22, 0x36, 0x3a, 0x7c, 0xb0, + 0x1b, 0xf0, 0x67, 0x3d, 0x32, 0x52, 0x93, 0xbd, 0x50, 0xb2, 0x7f, 0x81, + 0x87, 0xd8, 0x8e, 0xe2, 0xb5, 0x53, 0xb1, 0x59, 0xa9, 0x7d, 0x15, 0xac, + 0x54, 0x34, 0x21, 0x44, 0x6c, 0x2a, 0xec, 0x39, 0x56, 0x63, 0x15, 0x21, + 0x1b, 0x9b, 0x41, 0x08, 0xca, 0xcf, 0x90, 0x85, 0xda, 0xcd, 0xb4, 0xde, + 0x94, 0xbc, 0xe8, 0x40, 0x97, 0xc0, 0x89, 0x2b, 0x1c, 0xc6, 0x5f, 0x2e, + 0x10, 0xd7, 0x4e, 0x52, 0x93, 0xa0, 0x4a, 0x83, 0x7b, 0x61, 0x6d, 0x41, + 0x81, 0xf3, 0xfe, 0x4c, 0xaa, 0x4c, 0xc2, 0xe7, 0x44, 0x91, 0x6e, 0x77, + 0x0f, 0xf0, 0xab, 0x13, 0x68, 0xc8, 0x6c, 0xfc +}; +static const uint8_t ac_dsa_vect113_priv_val[] = { +/* X */ + 0x37, 0x52, 0xb2, 0x00, 0x33, 0x84, 0x3d, 0x1e, 0xa4, 0xf4, 0x80, 0x18, + 0xbe, 0xde, 0x79, 0xf3, 0x9c, 0x15, 0xde, 0x33, 0xdf, 0x64, 0x14, 0x02, + 0x59, 0xae, 0xbb, 0x82 +}; +static const uint8_t ac_dsa_vect113_pub_val[] = { +/* Y */ + 0x40, 0x52, 0x53, 0x4a, 0x77, 0x26, 0xcb, 0xe1, 0x7e, 0x34, 0x55, 0x56, + 0x48, 0xe5, 0xf2, 0x97, 0xb9, 0x63, 0xf2, 0x2d, 0x3a, 0xca, 0x24, 0x97, + 0x85, 0xad, 0x93, 0x2f, 0x6e, 0xa1, 0xfb, 0x5d, 0xf3, 0x1d, 0x37, 0x9b, + 0x68, 0x52, 0x2f, 0x8e, 0xeb, 0xed, 0xfc, 0x9b, 0x5c, 0x52, 0x77, 0xe9, + 0x15, 0x74, 0xfa, 0x79, 0xec, 0xf0, 0x37, 0x80, 0xcc, 0x44, 0x35, 0x1f, + 0x3e, 0x3b, 0xfa, 0x1a, 0x05, 0x87, 0xc8, 0x8d, 0x0e, 0x04, 0xe0, 0xa0, + 0x2c, 0xd1, 0xee, 0x9a, 0xe2, 0x10, 0xb3, 0xc9, 0xaa, 0xcc, 0x65, 0xc7, + 0x1c, 0xf1, 0xb8, 0x64, 0x63, 0x36, 0x7e, 0x2b, 0xe2, 0x5c, 0xca, 0xdd, + 0x9d, 0x5a, 0x4d, 0x1f, 0xcb, 0xd5, 0x87, 0x72, 0xf7, 0xa1, 0x17, 0xf3, + 0x67, 0x3c, 0x76, 0xee, 0x2a, 0x8d, 0x93, 0x44, 0x6f, 0xfd, 0x7c, 0xda, + 0x7f, 0x84, 0x30, 0x49, 0x05, 0x02, 0xc1, 0x6b, 0x1a, 0x50, 0x22, 0xe1, + 0x2a, 0x3a, 0x95, 0xa7, 0xa9, 0xf2, 0x0e, 0x98, 0xd3, 0xb2, 0x85, 0xab, + 0xe3, 0x0e, 0x8d, 0xe4, 0x2a, 0x11, 0xc5, 0x17, 0xc1, 0x4e, 0xf3, 0xb6, + 0xe5, 0xb6, 0xc4, 0x71, 0x14, 0xa9, 0x61, 0xd8, 0x58, 0xc6, 0x87, 0x55, + 0x61, 0xc7, 0xd5, 0xd2, 0x1b, 0x7c, 0x93, 0xf3, 0x73, 0xcb, 0x33, 0x08, + 0x00, 0x72, 0x8e, 0xa1, 0x88, 0xb2, 0x57, 0x8a, 0x6d, 0xf3, 0x47, 0x72, + 0xa7, 0xac, 0xdd, 0xb8, 0x29, 0xc0, 0x9b, 0x3a, 0xcf, 0x9b, 0xc5, 0xb0, + 0x61, 0x40, 0xb9, 0xb0, 0x35, 0x26, 0x7a, 0x40, 0xe8, 0x6c, 0x1a, 0xf5, + 0x57, 0x7b, 0x3d, 0x02, 0xa8, 0x9b, 0x20, 0xa4, 0x65, 0x73, 0xc8, 0x75, + 0x00, 0xa2, 0xeb, 0xed, 0x4b, 0x00, 0xb1, 0xfb, 0x13, 0xa8, 0x6f, 0x14, + 0x3e, 0x35, 0x67, 0x02, 0xd7, 0x91, 0x37, 0x9a, 0x90, 0xdf, 0xcc, 0x26, + 0xb8, 0x07, 0x19, 0xad +}; +/* K = 1220ac99b9124f1dc2212ade5691fd330d6d868f3e90694236d44b70 */ +static const uint8_t ac_dsa_vect113_out[] = { +/* R */ + 0x31, 0xfd, 0xe5, 0xf2, 0x2e, 0xbb, 0x42, 0x6f, 0x25, 0x6b, 0x17, 0x50, + 0x57, 0xa7, 0x61, 0x25, 0xc4, 0x01, 0x36, 0x97, 0x4a, 0xd5, 0x8e, 0x68, + 0x1e, 0xc2, 0xc4, 0xa9, +/* S */ + 0x77, 0xb0, 0x61, 0x4d, 0xd9, 0x9a, 0xcb, 0xbf, 0x4c, 0x43, 0xaa, 0x92, + 0x6b, 0x3f, 0x0b, 0xe1, 0xcd, 0x52, 0xd5, 0x27, 0x75, 0xf2, 0x2a, 0x40, + 0x8c, 0x4e, 0x03, 0x04 +}; +#define ac_dsa_vect114_prime ac_dsa_vect106_prime +#define ac_dsa_vect114_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect114_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect114_ptx[] = { +/* Msg */ + 0x14, 0x77, 0xaa, 0x0b, 0x9f, 0x1b, 0x19, 0x9b, 0x6a, 0xa0, 0x93, 0x1d, + 0x4d, 0x3f, 0x76, 0x6d, 0x80, 0xa3, 0xaf, 0x10, 0xc9, 0xff, 0x73, 0x15, + 0x39, 0x1f, 0x15, 0xed, 0xc4, 0xe9, 0x26, 0x32, 0xf9, 0xd4, 0xd2, 0x1a, + 0x80, 0x33, 0x21, 0x5d, 0x5e, 0x99, 0xcf, 0xf1, 0x70, 0xd9, 0x88, 0x8f, + 0x02, 0x0b, 0x0d, 0xb0, 0xe5, 0xb9, 0x7e, 0x12, 0x3a, 0x28, 0x89, 0x89, + 0x8c, 0x5b, 0x0e, 0xf7, 0xc8, 0x32, 0xd0, 0x28, 0xaf, 0xd5, 0xe3, 0x85, + 0x00, 0x45, 0x31, 0xff, 0x99, 0x89, 0x79, 0x7c, 0x3b, 0xd9, 0x54, 0xb1, + 0xac, 0x72, 0x90, 0x66, 0x57, 0x76, 0x67, 0x56, 0x78, 0x84, 0xcd, 0x4b, + 0xc5, 0xd0, 0x55, 0xa3, 0xf6, 0x45, 0x58, 0x3d, 0x29, 0xcf, 0x47, 0x58, + 0x50, 0x7c, 0x88, 0x3c, 0x5b, 0xbf, 0xa7, 0x44, 0x44, 0xb9, 0xc5, 0xb9, + 0xb4, 0x95, 0x07, 0x2c, 0x32, 0x61, 0xb6, 0xec +}; +static const uint8_t ac_dsa_vect114_priv_val[] = { +/* X */ + 0x83, 0x77, 0x07, 0x84, 0x91, 0x62, 0x27, 0xab, 0x2a, 0x73, 0xed, 0xaa, + 0xc5, 0xa9, 0x5f, 0x75, 0x38, 0xfd, 0x94, 0xf8, 0x96, 0x50, 0x84, 0x1d, + 0x79, 0xa3, 0x7d, 0x7a +}; +static const uint8_t ac_dsa_vect114_pub_val[] = { +/* Y */ + 0x46, 0x75, 0xf1, 0x9b, 0x00, 0x95, 0xfa, 0xf8, 0xec, 0x96, 0x88, 0x8e, + 0x48, 0x3f, 0x3a, 0x0a, 0xa6, 0x75, 0xf5, 0xb4, 0x25, 0x91, 0x07, 0x65, + 0x06, 0x9a, 0xb5, 0x7c, 0x97, 0xa1, 0x2b, 0x7c, 0x50, 0x64, 0x37, 0xc8, + 0x75, 0x7f, 0xef, 0x54, 0xec, 0xc6, 0xd3, 0x10, 0x92, 0x1d, 0x71, 0x59, + 0xff, 0x39, 0xf2, 0xf1, 0xcd, 0x95, 0x35, 0xb6, 0x4f, 0x27, 0xf1, 0x36, + 0x91, 0x37, 0x15, 0x77, 0x5a, 0x23, 0x8f, 0xbe, 0x01, 0x23, 0x7e, 0x18, + 0x1a, 0xde, 0xbe, 0x55, 0x1f, 0xfe, 0x5d, 0x21, 0xe3, 0xc3, 0x57, 0x74, + 0xe7, 0xad, 0xe8, 0xc7, 0x9d, 0xf7, 0x41, 0xc5, 0x2d, 0xab, 0xd8, 0xbe, + 0x47, 0x82, 0xee, 0x5a, 0x3b, 0x60, 0x7a, 0x39, 0xd1, 0xb4, 0x55, 0xdc, + 0x84, 0x83, 0x01, 0x84, 0x73, 0x12, 0x98, 0x05, 0x66, 0xf5, 0x5e, 0xba, + 0x08, 0x06, 0x21, 0xe3, 0xc1, 0x23, 0x14, 0x2a, 0x1a, 0x20, 0x74, 0xe2, + 0xe3, 0x9f, 0x6c, 0x06, 0x30, 0xb3, 0x68, 0x31, 0xf0, 0x74, 0x86, 0x9d, + 0x46, 0xa6, 0x84, 0x29, 0xf6, 0x25, 0x73, 0xcd, 0x2c, 0x67, 0x17, 0x26, + 0x13, 0x1f, 0xbf, 0xd5, 0x66, 0xa6, 0xd0, 0x71, 0x93, 0xdb, 0x4f, 0x36, + 0x78, 0x02, 0xd7, 0xde, 0x8f, 0x4e, 0x83, 0x0a, 0xa8, 0x78, 0xee, 0x2c, + 0xdf, 0xb8, 0x6d, 0x85, 0x37, 0x74, 0x6b, 0x71, 0xc7, 0x0f, 0xbc, 0xb6, + 0xa1, 0xfa, 0xd6, 0x62, 0x13, 0xd6, 0xfb, 0xea, 0x68, 0x24, 0x1e, 0xb9, + 0xf6, 0x17, 0x47, 0x8a, 0xdc, 0xc9, 0xfa, 0xaa, 0xb2, 0x6c, 0xf8, 0x1b, + 0x91, 0x20, 0x89, 0xda, 0x0c, 0x4b, 0x18, 0x7b, 0x49, 0x6a, 0x17, 0xd8, + 0x86, 0xce, 0xf5, 0x71, 0xe3, 0x93, 0xd6, 0xf1, 0xf8, 0x57, 0xeb, 0xf5, + 0x17, 0xc8, 0x01, 0xf9, 0x23, 0x1e, 0x95, 0xdb, 0x66, 0x1e, 0x8c, 0xb2, + 0x09, 0x54, 0x56, 0xa3 +}; +/* K = 6406035023c5e150e8758baeb00a9b858ebd0e4090334c69e2fd2377 */ +static const uint8_t ac_dsa_vect114_out[] = { +/* R */ + 0xa2, 0x38, 0x0b, 0x5e, 0xce, 0x76, 0x67, 0x26, 0x69, 0xe2, 0x61, 0x87, + 0xa1, 0x7d, 0xa4, 0x5a, 0xd8, 0x9d, 0xe1, 0x72, 0x6c, 0x82, 0x6e, 0x57, + 0x37, 0x8a, 0xf7, 0x07, +/* S */ + 0x9c, 0xc2, 0x6c, 0x34, 0x56, 0xc0, 0xa4, 0x09, 0xf4, 0xcc, 0x98, 0xc8, + 0x3e, 0xa5, 0x17, 0x6e, 0xb2, 0x93, 0xec, 0x71, 0x57, 0xe5, 0x13, 0x70, + 0x72, 0x64, 0x29, 0xce +}; +#define ac_dsa_vect115_prime ac_dsa_vect106_prime +#define ac_dsa_vect115_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect115_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect115_ptx[] = { +/* Msg */ + 0xfc, 0x82, 0x37, 0x25, 0x66, 0xef, 0x2c, 0x62, 0x6b, 0x21, 0x45, 0x54, + 0x9a, 0x5d, 0xb9, 0x73, 0x11, 0x8d, 0xff, 0x4c, 0x6d, 0x1d, 0x7c, 0x4a, + 0x2e, 0x16, 0xec, 0xc3, 0x1b, 0x43, 0xc1, 0x4a, 0xd3, 0x68, 0x31, 0x73, + 0x53, 0x5b, 0x0b, 0x82, 0x33, 0x1f, 0x15, 0xa1, 0x83, 0xe6, 0xa5, 0x02, + 0x00, 0xfd, 0x1e, 0x88, 0xff, 0x90, 0x3e, 0xcf, 0xc5, 0x0b, 0xdd, 0x4f, + 0x58, 0x75, 0xe2, 0x64, 0xa4, 0x49, 0x9e, 0xad, 0xbd, 0xaf, 0x80, 0x7f, + 0x97, 0x4f, 0x8d, 0x81, 0x04, 0x47, 0x7a, 0x0e, 0x4d, 0x30, 0x46, 0x3d, + 0xfc, 0x61, 0xcd, 0xac, 0x5b, 0xf4, 0x4e, 0xab, 0x96, 0xc7, 0x70, 0xa7, + 0xdb, 0x91, 0x2e, 0xee, 0x2d, 0xb2, 0x48, 0xcd, 0xd2, 0xb9, 0xb3, 0x62, + 0x11, 0xf9, 0x38, 0x70, 0xbe, 0xae, 0x6b, 0xdf, 0x8e, 0x0a, 0xed, 0x00, + 0x97, 0x51, 0x9e, 0xcd, 0xe3, 0x47, 0x0c, 0xdd +}; +static const uint8_t ac_dsa_vect115_priv_val[] = { +/* X */ + 0x8d, 0x28, 0x55, 0xe4, 0xea, 0x3e, 0x50, 0x85, 0xa5, 0xc1, 0x45, 0xe3, + 0x24, 0xe5, 0xd5, 0xa5, 0xf8, 0xf2, 0x37, 0x56, 0x28, 0x46, 0x69, 0x27, + 0x97, 0x28, 0xec, 0x9c +}; +static const uint8_t ac_dsa_vect115_pub_val[] = { +/* Y */ + 0x38, 0x84, 0xab, 0x23, 0xab, 0x93, 0xd9, 0xd1, 0xb7, 0x16, 0x71, 0x2c, + 0x8d, 0xaa, 0x08, 0x0b, 0x26, 0xaf, 0x01, 0x65, 0x7f, 0x0d, 0xab, 0x71, + 0x5e, 0xbe, 0x6b, 0xd7, 0x66, 0xde, 0xca, 0x76, 0x12, 0xbe, 0xa6, 0xa4, + 0xcf, 0x1f, 0xf7, 0xd0, 0x8a, 0xbb, 0x2d, 0x44, 0x42, 0xac, 0x0e, 0xaa, + 0xb0, 0x1e, 0x68, 0x57, 0x0b, 0xdc, 0xc2, 0x22, 0xf8, 0x4b, 0xc3, 0xdd, + 0x6d, 0x8c, 0x54, 0x90, 0x13, 0x2d, 0x1c, 0x36, 0xe2, 0x39, 0x13, 0xf0, + 0x0d, 0x11, 0xc8, 0x03, 0xb7, 0x03, 0xa6, 0x9a, 0x51, 0xa1, 0xb4, 0x75, + 0xf5, 0x6d, 0xb0, 0x0f, 0xca, 0x47, 0xd2, 0x34, 0xaa, 0xc3, 0x07, 0xb9, + 0xe7, 0x98, 0xe9, 0xfd, 0x89, 0x1d, 0xff, 0x9c, 0x12, 0x57, 0xbe, 0xe5, + 0x56, 0x31, 0x4b, 0x02, 0x1f, 0xbf, 0x93, 0xf7, 0x5e, 0xd8, 0xc4, 0x34, + 0x33, 0xaf, 0xa7, 0x15, 0xb8, 0x2d, 0x5e, 0xc6, 0xaf, 0x8e, 0xf9, 0x47, + 0x1e, 0x9b, 0x02, 0xf9, 0x55, 0x4e, 0xd7, 0x95, 0x7c, 0x1f, 0x46, 0xd8, + 0xdb, 0x35, 0xa5, 0x92, 0x1f, 0x4a, 0x83, 0x72, 0x7f, 0x75, 0x4e, 0x82, + 0xb6, 0xff, 0xa6, 0xd1, 0xb8, 0x25, 0x95, 0x22, 0x08, 0x76, 0xd2, 0x2e, + 0x18, 0xfb, 0xaf, 0xa5, 0x33, 0x3b, 0x26, 0xc2, 0xcf, 0xd4, 0x7d, 0x89, + 0x4a, 0xaa, 0x71, 0x64, 0xa2, 0x63, 0x02, 0x94, 0xd0, 0xa3, 0x85, 0xfc, + 0x8a, 0x8c, 0xf5, 0x7d, 0x10, 0xed, 0x0f, 0xc5, 0x3f, 0x21, 0xf1, 0xfd, + 0x6b, 0x4c, 0x27, 0xe9, 0xc6, 0x9e, 0x65, 0xa2, 0x88, 0x44, 0x46, 0x19, + 0xa3, 0xc2, 0x48, 0xbc, 0xc4, 0x4e, 0xc2, 0x56, 0x05, 0x02, 0x83, 0x25, + 0x24, 0x32, 0x74, 0xd7, 0x21, 0x00, 0xed, 0xf5, 0x60, 0xcd, 0x38, 0x2b, + 0xab, 0xee, 0x1c, 0xa5, 0x32, 0xb7, 0xf0, 0x6a, 0x43, 0x88, 0xf1, 0x81, + 0xdb, 0xbb, 0x5d, 0xb5 +}; +/* K = 5cc12f090fd965c719efa2ee907a43b3643ca8f9ef7c537adcb09189 */ +static const uint8_t ac_dsa_vect115_out[] = { +/* R */ + 0x54, 0x61, 0xb2, 0x07, 0x04, 0x45, 0x3b, 0x6c, 0x51, 0x83, 0x7f, 0x7b, + 0x9e, 0xf5, 0x83, 0x61, 0x31, 0xb5, 0x01, 0xf2, 0x53, 0x91, 0x45, 0xca, + 0x34, 0x81, 0xe6, 0xaf, +/* S */ + 0xb6, 0x5f, 0x69, 0xd2, 0x91, 0xff, 0xae, 0x2d, 0x16, 0xe3, 0x10, 0x8d, + 0x69, 0xae, 0xb0, 0x1b, 0x4f, 0x92, 0x02, 0xaf, 0xa0, 0x13, 0x82, 0xe5, + 0x3d, 0xea, 0x4d, 0x54 +}; +#define ac_dsa_vect116_prime ac_dsa_vect106_prime +#define ac_dsa_vect116_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect116_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect116_ptx[] = { +/* Msg */ + 0xe6, 0x6a, 0xad, 0x54, 0x04, 0x8b, 0xec, 0xec, 0xa5, 0x68, 0x26, 0x44, + 0xd5, 0x27, 0x4c, 0x18, 0x06, 0x83, 0x63, 0xe9, 0x68, 0xe3, 0x7e, 0x6c, + 0x11, 0xc1, 0xf8, 0xa0, 0xd7, 0xe3, 0x20, 0x57, 0x85, 0x14, 0xe1, 0x87, + 0x4e, 0x9d, 0x4e, 0xaf, 0x1b, 0xd0, 0x2d, 0xa6, 0xb7, 0x22, 0xed, 0x22, + 0xac, 0xfc, 0xa4, 0x8c, 0x3a, 0xcb, 0x67, 0x0a, 0x6f, 0x9e, 0xe6, 0x2e, + 0x3a, 0xa7, 0x1d, 0xeb, 0x18, 0x09, 0x75, 0x08, 0xf4, 0x31, 0xb0, 0x52, + 0x14, 0xc1, 0x99, 0xc1, 0x66, 0xfa, 0x42, 0xcd, 0x6a, 0x07, 0x97, 0xbc, + 0x7b, 0x4d, 0x1a, 0x2f, 0x33, 0x0c, 0xb6, 0x2c, 0x2c, 0x95, 0x18, 0x2f, + 0xef, 0x0d, 0x06, 0x86, 0x25, 0x42, 0x84, 0x5e, 0x43, 0x0d, 0x77, 0x8c, + 0x82, 0x07, 0x63, 0x87, 0xad, 0xad, 0x43, 0x55, 0xc2, 0x58, 0xe6, 0xc5, + 0x43, 0xcd, 0x65, 0x6f, 0xe3, 0xcd, 0x23, 0x32 +}; +static const uint8_t ac_dsa_vect116_priv_val[] = { +/* X */ + 0x2c, 0x98, 0x4e, 0x84, 0x64, 0xcf, 0x57, 0x16, 0x05, 0x35, 0x20, 0xb6, + 0xa7, 0x2c, 0x69, 0x79, 0x8b, 0x9e, 0xec, 0x1e, 0x11, 0x5b, 0x0a, 0x1e, + 0x30, 0xe2, 0xe4, 0x4e +}; +static const uint8_t ac_dsa_vect116_pub_val[] = { +/* Y */ + 0x06, 0x24, 0x5b, 0xc5, 0x09, 0xb4, 0x95, 0x54, 0x40, 0xb0, 0xe4, 0x01, + 0x71, 0x0d, 0xdb, 0x2c, 0x4e, 0xa2, 0xe5, 0x59, 0x59, 0x83, 0x61, 0xa3, + 0x66, 0x6c, 0x4a, 0xb1, 0x2e, 0x76, 0x6b, 0x43, 0x9f, 0x21, 0xb9, 0x53, + 0x96, 0x2f, 0x6e, 0xf5, 0xa1, 0x1d, 0xbe, 0xe5, 0x67, 0x7a, 0xb7, 0xf8, + 0x90, 0x6d, 0x8b, 0x32, 0x51, 0x80, 0xef, 0x4e, 0x45, 0xd0, 0x5c, 0x12, + 0x94, 0xfc, 0xe5, 0xdc, 0xaf, 0x63, 0x60, 0xf7, 0x1b, 0x10, 0xb7, 0x05, + 0x56, 0xf3, 0x06, 0x99, 0x3d, 0x29, 0x5b, 0x69, 0x5f, 0xfe, 0x57, 0x29, + 0xc5, 0xc5, 0xbb, 0xb6, 0xcb, 0x48, 0x34, 0xad, 0x03, 0x7b, 0xd8, 0x36, + 0x4a, 0x12, 0xc9, 0x92, 0xc2, 0x59, 0x8e, 0x8e, 0xe6, 0xbe, 0xb1, 0x60, + 0x6e, 0xbc, 0x0a, 0xc0, 0xff, 0x00, 0xc0, 0xea, 0x2e, 0xb8, 0xae, 0xd7, + 0x5d, 0xca, 0x01, 0xa8, 0x90, 0x08, 0x5a, 0x40, 0x0e, 0xbf, 0x99, 0x3e, + 0x58, 0x79, 0x38, 0x2f, 0xf9, 0x1a, 0xbf, 0x1b, 0xe2, 0xce, 0xed, 0xd1, + 0xfc, 0x4a, 0x87, 0x43, 0x42, 0xb7, 0x7b, 0x6c, 0x55, 0xff, 0xe7, 0xf6, + 0x76, 0xa1, 0xc9, 0x5e, 0xe4, 0xec, 0xc3, 0x23, 0x58, 0xa0, 0x80, 0xc9, + 0x23, 0x61, 0xcf, 0xcd, 0x2e, 0x34, 0x26, 0xf7, 0x8c, 0x21, 0x7a, 0xe2, + 0x95, 0x56, 0x70, 0x9e, 0xd0, 0x29, 0xb2, 0x87, 0xe7, 0x1f, 0xea, 0xe0, + 0x60, 0x8c, 0xf3, 0x93, 0x88, 0x57, 0x04, 0x0d, 0x7f, 0x06, 0xb0, 0xf9, + 0x1b, 0x3b, 0x4d, 0xa8, 0x92, 0x9d, 0xf4, 0xb5, 0x69, 0x8e, 0x73, 0x4a, + 0x37, 0x31, 0x68, 0x79, 0xc3, 0x08, 0xa8, 0x1c, 0x09, 0x6b, 0x72, 0x3b, + 0xf2, 0x08, 0x99, 0x10, 0xd5, 0xab, 0x30, 0xb8, 0xef, 0xf3, 0x88, 0x58, + 0xaf, 0xf6, 0xec, 0xf7, 0x64, 0xe2, 0x68, 0xed, 0x69, 0x8b, 0x70, 0xe8, + 0xfb, 0x7f, 0x3c, 0x66 +}; +/* K = b20370d79e097e7c65e956d76aea1e288b668dacb8e7944aba5fbadd */ +static const uint8_t ac_dsa_vect116_out[] = { +/* R */ + 0x86, 0xd5, 0xba, 0xc3, 0xae, 0xee, 0x9b, 0x50, 0x1f, 0x91, 0xf2, 0xfa, + 0x71, 0xb1, 0x06, 0x67, 0x60, 0xdf, 0x2e, 0x0e, 0xe1, 0x47, 0x38, 0x3f, + 0x14, 0x5b, 0xb0, 0xd3, +/* S */ + 0x8d, 0x6a, 0x20, 0x78, 0x02, 0xd6, 0xfd, 0x6e, 0x53, 0x4e, 0x1b, 0x8a, + 0x1e, 0xdb, 0x99, 0x7b, 0x7c, 0xc9, 0xa2, 0x5a, 0x97, 0xa9, 0xe4, 0xb6, + 0xee, 0xbd, 0x0e, 0x23 +}; +#define ac_dsa_vect117_prime ac_dsa_vect106_prime +#define ac_dsa_vect117_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect117_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect117_ptx[] = { +/* Msg */ + 0xc8, 0x57, 0x47, 0xcd, 0xd2, 0xac, 0x9d, 0xa0, 0x99, 0x9b, 0x7e, 0x5d, + 0x7f, 0x64, 0xd1, 0x1d, 0xce, 0x76, 0x73, 0xdf, 0x5b, 0xc6, 0x05, 0x05, + 0x13, 0x16, 0xb4, 0xb9, 0x4b, 0xc7, 0xfc, 0x77, 0x6f, 0xb1, 0xd3, 0xda, + 0x5a, 0x43, 0x95, 0xa6, 0x74, 0xaa, 0x8a, 0x07, 0x98, 0xa3, 0x41, 0xb3, + 0x1b, 0x11, 0xe6, 0x3c, 0xdf, 0xac, 0x5f, 0x85, 0x43, 0x46, 0xf6, 0xa4, + 0xb7, 0x4b, 0x49, 0xf2, 0xd0, 0x89, 0xcb, 0xb8, 0x6f, 0xae, 0x54, 0xeb, + 0xfd, 0x95, 0xeb, 0x9f, 0x05, 0xa1, 0xb5, 0xe8, 0x43, 0x06, 0xe9, 0x30, + 0x46, 0x1a, 0xd7, 0xf8, 0x27, 0xcf, 0xb9, 0x10, 0x01, 0x4a, 0x3a, 0xf4, + 0xda, 0xe0, 0xd4, 0x6e, 0xce, 0x91, 0x2b, 0xc2, 0x68, 0x70, 0xa4, 0x33, + 0xf7, 0x0f, 0x0a, 0x38, 0xbf, 0x23, 0xb1, 0x5d, 0x98, 0xcc, 0x65, 0x88, + 0x48, 0xf4, 0xba, 0xd9, 0xc8, 0x4e, 0x89, 0xf0 +}; +static const uint8_t ac_dsa_vect117_priv_val[] = { +/* X */ + 0x40, 0x76, 0xf4, 0xab, 0xf4, 0xd3, 0xc9, 0xa5, 0x5b, 0x3f, 0x06, 0x35, + 0x35, 0xf6, 0xa6, 0x9c, 0x22, 0x11, 0x99, 0x58, 0x1e, 0x72, 0xc5, 0xa8, + 0xc3, 0x1f, 0x1a, 0x71 +}; +static const uint8_t ac_dsa_vect117_pub_val[] = { +/* Y */ + 0x29, 0x72, 0x78, 0x7d, 0xcb, 0xd6, 0x7e, 0x5b, 0xdd, 0xaa, 0xf1, 0xbd, + 0x3f, 0x05, 0xeb, 0xd6, 0x69, 0x49, 0x60, 0x1d, 0xda, 0x44, 0x23, 0x7e, + 0xc9, 0x36, 0x15, 0x91, 0xce, 0x9b, 0x80, 0x9f, 0x87, 0x22, 0xfb, 0x39, + 0x9e, 0x6b, 0x9b, 0x81, 0x09, 0xa7, 0x9e, 0xa7, 0xb8, 0x3f, 0xe9, 0x83, + 0x59, 0xa0, 0x7a, 0x27, 0xe2, 0x32, 0xcd, 0xea, 0x8f, 0x65, 0x33, 0xe3, + 0x4e, 0x37, 0xdb, 0x3a, 0xe5, 0x33, 0x09, 0xf6, 0x2f, 0x10, 0x8b, 0x2e, + 0xe7, 0xb4, 0x89, 0xa9, 0x33, 0xe4, 0xef, 0x58, 0xdd, 0x4d, 0xb8, 0xc0, + 0x10, 0x8a, 0x36, 0x70, 0xc6, 0x75, 0xb9, 0x8b, 0x75, 0x79, 0x8a, 0xc0, + 0x88, 0x4c, 0xf5, 0xa4, 0x61, 0xaf, 0x28, 0x1f, 0x6d, 0xd8, 0xe7, 0xea, + 0x3d, 0x41, 0x39, 0x6f, 0x04, 0x96, 0x01, 0xa9, 0xaf, 0x2e, 0x39, 0x08, + 0x8a, 0xe0, 0xa1, 0xec, 0x0d, 0x2d, 0x10, 0xfa, 0xe1, 0xdc, 0x1d, 0xe9, + 0x62, 0xd8, 0x4d, 0x8c, 0xf0, 0x42, 0x15, 0xfc, 0x6d, 0x62, 0x62, 0xac, + 0x43, 0x25, 0x41, 0xaf, 0x2c, 0x48, 0xc0, 0x9c, 0xd4, 0xe1, 0x5b, 0xd9, + 0x46, 0x0e, 0x9a, 0x7b, 0xae, 0x17, 0xe0, 0x03, 0x5a, 0xf0, 0xb1, 0x3d, + 0x8d, 0xe7, 0x07, 0x87, 0x0c, 0x54, 0xbc, 0x85, 0x11, 0x12, 0xf4, 0xae, + 0x1d, 0x69, 0x07, 0x47, 0x12, 0xc2, 0x12, 0xbc, 0x7e, 0x13, 0xf1, 0x99, + 0xff, 0xc8, 0xf3, 0x77, 0x23, 0xcd, 0x6d, 0xcf, 0x53, 0x9f, 0x8d, 0xf8, + 0xcf, 0x0c, 0xf1, 0xed, 0x4c, 0x10, 0xee, 0xaf, 0x0f, 0x44, 0x48, 0x04, + 0xf1, 0xeb, 0x9d, 0x9c, 0x32, 0x9d, 0x6f, 0x19, 0x97, 0x3e, 0xec, 0x27, + 0x32, 0x22, 0xfa, 0x04, 0xb5, 0xf1, 0xf0, 0xe1, 0x79, 0x71, 0xce, 0x39, + 0x98, 0x69, 0x58, 0x20, 0x27, 0xb1, 0xc4, 0x54, 0xdc, 0x1a, 0xdd, 0xd4, + 0x84, 0x90, 0x2c, 0xb0 +}; +/* K = 7149f49e3d07c45c97db09632740560e5b0e843240255da43ae97ec1 */ +static const uint8_t ac_dsa_vect117_out[] = { +/* R */ + 0x28, 0xe3, 0xdd, 0x71, 0x09, 0x8f, 0xf0, 0x4d, 0x1c, 0xa8, 0x85, 0xc2, + 0x77, 0x4f, 0x78, 0xec, 0xb3, 0xec, 0xea, 0x70, 0x8f, 0xab, 0x2e, 0x16, + 0xbd, 0x5c, 0xec, 0xe1, +/* S */ + 0xac, 0x8b, 0x6e, 0xe4, 0x98, 0xee, 0x38, 0x3e, 0x28, 0x40, 0x4b, 0xa4, + 0xb5, 0x3e, 0x64, 0xac, 0xa0, 0xfc, 0xd2, 0x67, 0x90, 0x71, 0x32, 0x64, + 0xfe, 0x3c, 0xf6, 0xa1 +}; +#define ac_dsa_vect118_prime ac_dsa_vect106_prime +#define ac_dsa_vect118_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect118_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect118_ptx[] = { +/* Msg */ + 0xa7, 0xa5, 0x9d, 0xa6, 0x2a, 0x93, 0x91, 0xcf, 0xe6, 0x28, 0x69, 0x75, + 0x48, 0xb0, 0x5f, 0x8a, 0xf3, 0x9e, 0xa9, 0x82, 0x1d, 0x76, 0xc3, 0x14, + 0x47, 0x8e, 0x21, 0x0f, 0xbc, 0xd2, 0x7f, 0xbf, 0x6b, 0x0b, 0xf4, 0x60, + 0xa6, 0x5d, 0xbc, 0xba, 0xdc, 0xdd, 0xfc, 0x01, 0x78, 0xec, 0xe1, 0x35, + 0x26, 0x4a, 0x7d, 0x7c, 0x5b, 0x70, 0x53, 0x20, 0x8b, 0xfb, 0xde, 0x54, + 0xe3, 0x33, 0x8d, 0x90, 0x19, 0x27, 0xe9, 0x5e, 0x1d, 0xc8, 0xee, 0xb7, + 0x3d, 0x29, 0x9e, 0x6f, 0xa6, 0x58, 0x45, 0x55, 0xcf, 0xea, 0xfd, 0x19, + 0x25, 0xe9, 0x5e, 0x0b, 0x35, 0x58, 0xdd, 0xec, 0x64, 0x11, 0x75, 0xfc, + 0x72, 0x93, 0xc0, 0x31, 0x02, 0x66, 0xac, 0xe1, 0x8b, 0xbb, 0x16, 0xf9, + 0x08, 0x4f, 0xd4, 0xac, 0x22, 0xad, 0x2d, 0xc8, 0x52, 0x8c, 0x3f, 0x3f, + 0x33, 0x26, 0x84, 0x03, 0x9e, 0x74, 0xb3, 0x90 +}; +static const uint8_t ac_dsa_vect118_priv_val[] = { +/* X */ + 0x22, 0xfd, 0xd4, 0x4a, 0xfd, 0x37, 0x2e, 0x15, 0x84, 0x24, 0x13, 0xc0, + 0x82, 0x9c, 0x9a, 0x89, 0x4c, 0xe6, 0x1a, 0x3f, 0x0b, 0x13, 0x5c, 0x15, + 0x46, 0xf5, 0x7f, 0xb0 +}; +static const uint8_t ac_dsa_vect118_pub_val[] = { +/* Y */ + 0x0a, 0xa0, 0x40, 0xbb, 0xb2, 0x3c, 0x33, 0x7d, 0x58, 0x87, 0x4d, 0x95, + 0xef, 0xe9, 0x27, 0x70, 0x80, 0x86, 0x2e, 0xa0, 0x88, 0x8d, 0x92, 0x09, + 0xec, 0xc2, 0xf5, 0xd7, 0xe0, 0xd5, 0x6b, 0x3e, 0x84, 0x44, 0xca, 0x93, + 0x38, 0x00, 0x45, 0x0f, 0x10, 0xb8, 0x12, 0x4f, 0xf8, 0x81, 0x2f, 0x87, + 0xe1, 0xbe, 0xcf, 0x1a, 0x31, 0x7a, 0xce, 0x0c, 0x3a, 0x13, 0x76, 0xd6, + 0x24, 0x93, 0x8c, 0xab, 0x61, 0x7b, 0xb5, 0x46, 0xd0, 0xaa, 0xd4, 0xf1, + 0xd0, 0xaa, 0x23, 0xc6, 0x67, 0x0c, 0xfa, 0xe0, 0xda, 0x28, 0x66, 0x03, + 0x93, 0xa9, 0x09, 0x11, 0xb3, 0xdb, 0xe3, 0x84, 0x7e, 0xab, 0x4e, 0xbb, + 0x7d, 0xd0, 0x50, 0x4a, 0xeb, 0x02, 0x69, 0x12, 0x66, 0x55, 0xd1, 0x35, + 0xd2, 0xe9, 0x14, 0x9c, 0xd8, 0xac, 0x52, 0x21, 0x15, 0x16, 0x40, 0x91, + 0x4d, 0x48, 0x05, 0x69, 0xb3, 0x83, 0xe9, 0x83, 0x64, 0xcc, 0x41, 0xce, + 0xc5, 0x6e, 0xa1, 0x57, 0xce, 0x8d, 0x7e, 0x73, 0xa9, 0x49, 0xb3, 0x48, + 0xe5, 0xff, 0xd3, 0xce, 0xef, 0xea, 0x7f, 0x76, 0x25, 0xf5, 0x99, 0xaa, + 0x9a, 0xfe, 0x2d, 0xb4, 0xcf, 0x3b, 0x0d, 0x59, 0xf2, 0x70, 0x0f, 0x6c, + 0xec, 0xc5, 0x4f, 0x8b, 0xf7, 0x85, 0x38, 0x92, 0xf0, 0x73, 0x37, 0xdb, + 0xe7, 0x6b, 0xe7, 0x81, 0x99, 0x4e, 0xf4, 0xe1, 0x4d, 0xf2, 0xf0, 0xcf, + 0x7c, 0xb3, 0x42, 0xee, 0x1c, 0x8b, 0x18, 0x8a, 0x7d, 0xcc, 0x31, 0x7a, + 0x09, 0x7c, 0x9f, 0x9e, 0x33, 0xff, 0x89, 0x46, 0x2c, 0x26, 0x46, 0x5b, + 0xb5, 0x3e, 0xec, 0x05, 0xd1, 0x08, 0x5f, 0xc6, 0x15, 0x6c, 0xad, 0x0f, + 0x7c, 0x9b, 0x80, 0xd2, 0xa6, 0x89, 0x53, 0x50, 0x1a, 0x97, 0xac, 0xb7, + 0x46, 0xac, 0x3a, 0x2b, 0x9b, 0xdc, 0xf1, 0x8d, 0xfc, 0xea, 0xa1, 0x96, + 0x71, 0x6e, 0xc7, 0x73 +}; +/* K = b93120b594e8994f533c1811d61495f2ebf32fde9e7ecec856033f20 */ +static const uint8_t ac_dsa_vect118_out[] = { +/* R */ + 0x84, 0x93, 0x4f, 0x3f, 0x56, 0xd6, 0x48, 0x15, 0xfc, 0x66, 0xb0, 0xdb, + 0xf3, 0xb1, 0xfa, 0x56, 0xd1, 0x38, 0x7b, 0xe7, 0x61, 0x1a, 0x1e, 0x57, + 0x1c, 0x40, 0x51, 0x00, +/* S */ + 0x43, 0x1f, 0x11, 0x34, 0x69, 0x50, 0xe7, 0x7c, 0x9e, 0x9e, 0xd0, 0x12, + 0x7c, 0x50, 0xbf, 0x62, 0x0f, 0x6f, 0x69, 0xa6, 0x99, 0xcd, 0x01, 0x7c, + 0x7d, 0x87, 0x36, 0x8a +}; +#define ac_dsa_vect119_prime ac_dsa_vect106_prime +#define ac_dsa_vect119_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect119_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect119_ptx[] = { +/* Msg */ + 0xd4, 0xc5, 0xb4, 0x39, 0xa1, 0xcc, 0xf5, 0xd9, 0x8c, 0xf0, 0xb9, 0x31, + 0xf2, 0x53, 0xf7, 0x33, 0x03, 0x79, 0x21, 0xd4, 0xef, 0xb0, 0x2c, 0xf8, + 0x7b, 0x25, 0x09, 0xe7, 0x32, 0xa5, 0x6c, 0xcb, 0x49, 0xe0, 0xc8, 0x3b, + 0x14, 0x09, 0xcc, 0x00, 0x9f, 0x1d, 0x2d, 0x1c, 0xb4, 0xc0, 0xc7, 0xab, + 0x00, 0xc4, 0x02, 0xee, 0x01, 0x8e, 0xc5, 0x09, 0x80, 0x31, 0xac, 0x9e, + 0x71, 0x97, 0xd4, 0x39, 0x5d, 0x49, 0x17, 0x21, 0x70, 0x8a, 0x41, 0xff, + 0x5c, 0xda, 0x5a, 0x03, 0xbe, 0x6a, 0x11, 0x69, 0xbf, 0x45, 0x94, 0x70, + 0xb1, 0xaa, 0xf5, 0x3c, 0x8a, 0x96, 0x68, 0xac, 0xae, 0x13, 0x85, 0xb9, + 0x21, 0xf5, 0xa2, 0x6c, 0x73, 0x36, 0x54, 0x44, 0x51, 0x5c, 0x3c, 0x12, + 0x6c, 0x69, 0x40, 0xb4, 0xbf, 0x57, 0x59, 0x1a, 0x0b, 0xfd, 0x6c, 0x2c, + 0x74, 0xc7, 0x24, 0x42, 0x6c, 0xb2, 0xad, 0x3f +}; +static const uint8_t ac_dsa_vect119_priv_val[] = { +/* X */ + 0xc9, 0xed, 0x82, 0x46, 0x21, 0x58, 0xcc, 0x9c, 0x99, 0x23, 0x1f, 0xd4, + 0x8a, 0x81, 0xe4, 0xf8, 0x31, 0x8a, 0x88, 0x73, 0x5c, 0x35, 0xb9, 0xf2, + 0xc0, 0x8a, 0xd2, 0x80 +}; +static const uint8_t ac_dsa_vect119_pub_val[] = { +/* Y */ + 0x37, 0xc5, 0xf0, 0x29, 0x81, 0x63, 0x22, 0xda, 0x51, 0x61, 0xc4, 0xe2, + 0x0d, 0xc4, 0xf5, 0xab, 0xde, 0x9f, 0x04, 0xf5, 0xf9, 0xdf, 0xf5, 0xd5, + 0x81, 0xb2, 0x53, 0x10, 0x91, 0x91, 0xb3, 0x84, 0x24, 0xdd, 0xe7, 0x5f, + 0xeb, 0xac, 0x32, 0xd6, 0xce, 0x31, 0xb1, 0x16, 0x06, 0x34, 0x94, 0xa7, + 0x0c, 0x5c, 0x1d, 0x9d, 0x8b, 0x73, 0x51, 0x25, 0x2e, 0xd3, 0x77, 0xea, + 0x38, 0xfb, 0xe8, 0x5b, 0x9f, 0x61, 0x4e, 0xca, 0x13, 0x46, 0xbf, 0xf6, + 0x53, 0x45, 0xd5, 0x7e, 0x64, 0x6b, 0xfb, 0x03, 0x2e, 0x9b, 0xef, 0xa9, + 0xe6, 0xe5, 0xa8, 0x9c, 0x16, 0xd7, 0x15, 0x42, 0x0e, 0x24, 0x12, 0x9b, + 0x6f, 0x70, 0xe4, 0xf6, 0x81, 0xbc, 0x1d, 0x38, 0xad, 0x17, 0x37, 0xdb, + 0x79, 0x65, 0x5d, 0x24, 0x4b, 0x4d, 0x67, 0xad, 0x3d, 0x2b, 0xd8, 0x0f, + 0xd9, 0xd8, 0x0c, 0x2e, 0x15, 0x24, 0x02, 0x14, 0x85, 0x9f, 0xdc, 0x0b, + 0x6c, 0x43, 0xdd, 0x1e, 0x80, 0x5d, 0xcd, 0xd2, 0xa5, 0xb9, 0x78, 0x13, + 0x97, 0xbd, 0x4a, 0x4e, 0x8b, 0xc4, 0xd6, 0xf9, 0xa1, 0x66, 0x40, 0x36, + 0xe9, 0x0c, 0xac, 0x55, 0x0e, 0x83, 0xd6, 0x64, 0x13, 0x67, 0x61, 0x37, + 0x07, 0xd0, 0xde, 0x4f, 0x2d, 0xee, 0x55, 0xe9, 0xa5, 0xbe, 0x6d, 0x3d, + 0xe8, 0x93, 0xd6, 0x15, 0x61, 0xf4, 0xba, 0x90, 0xd3, 0x87, 0xb7, 0xab, + 0x48, 0x80, 0x10, 0x86, 0x01, 0x6c, 0x84, 0x2f, 0x3e, 0x0c, 0xe6, 0x0e, + 0x6b, 0x46, 0xaa, 0x98, 0x01, 0x91, 0xcb, 0xa1, 0x47, 0x40, 0x7a, 0xa4, + 0xcc, 0xbe, 0x19, 0xb0, 0x0b, 0x0a, 0xc7, 0x16, 0x48, 0xd5, 0x29, 0x6d, + 0x13, 0xe4, 0x8c, 0x75, 0xd5, 0x28, 0x48, 0xbb, 0xd3, 0x9f, 0x1d, 0xed, + 0x98, 0x8c, 0x36, 0x16, 0xfa, 0xaf, 0x64, 0xf9, 0x1a, 0x30, 0x74, 0x25, + 0x06, 0x31, 0x68, 0x93 +}; +/* K = 9f1fc151bcf8fe18bde1ac505737dc6868c34be605bf2ead6ae3294b */ +static const uint8_t ac_dsa_vect119_out[] = { +/* R */ + 0x1b, 0x51, 0xb8, 0xd2, 0xd3, 0xee, 0xb3, 0xd6, 0x21, 0x8d, 0xa3, 0x49, + 0x47, 0x14, 0xd0, 0xe8, 0x8c, 0xd7, 0x36, 0x6f, 0x38, 0x7e, 0x6e, 0xde, + 0x00, 0xf6, 0x53, 0xe0, +/* S */ + 0x84, 0x42, 0x03, 0xa8, 0x1f, 0xb3, 0x8f, 0x57, 0x50, 0x5b, 0xf8, 0x3b, + 0xc8, 0xc1, 0xda, 0x00, 0x2a, 0x39, 0xe8, 0x1a, 0xbb, 0xdd, 0x2f, 0x99, + 0xab, 0x6a, 0x4d, 0x65 +}; +#define ac_dsa_vect120_prime ac_dsa_vect106_prime +#define ac_dsa_vect120_sub_prime ac_dsa_vect106_sub_prime +#define ac_dsa_vect120_base ac_dsa_vect106_base +static const uint8_t ac_dsa_vect120_ptx[] = { +/* Msg */ + 0x40, 0xd4, 0xd9, 0x73, 0x6b, 0x54, 0x99, 0x3c, 0x1b, 0xce, 0xe7, 0x07, + 0x1c, 0x68, 0x23, 0x90, 0xd3, 0x4d, 0x47, 0xc3, 0x5f, 0x17, 0x79, 0x39, + 0xca, 0x5b, 0x70, 0xf4, 0x57, 0xb3, 0x45, 0x8f, 0xd5, 0xec, 0xa4, 0xcb, + 0x03, 0xf0, 0xef, 0xe1, 0xae, 0xc1, 0x0b, 0xf7, 0x94, 0xb8, 0x41, 0x21, + 0x60, 0x56, 0xa1, 0x55, 0xda, 0xb5, 0x8a, 0x3d, 0xbf, 0xc1, 0x9d, 0xdf, + 0x05, 0xd4, 0x58, 0x61, 0xba, 0xe6, 0xee, 0xa2, 0xbd, 0x7f, 0xfb, 0x87, + 0xa6, 0xfd, 0x0f, 0xd2, 0x39, 0x4e, 0x84, 0x7d, 0xc3, 0x6c, 0x94, 0xc8, + 0x15, 0x61, 0xde, 0xe1, 0x20, 0x77, 0x9b, 0xbe, 0xcb, 0xc3, 0x22, 0x06, + 0x32, 0x7f, 0xeb, 0xaa, 0x17, 0xc9, 0x65, 0x05, 0xec, 0xb9, 0x7d, 0x56, + 0x0c, 0x93, 0x4c, 0x38, 0x6f, 0x6f, 0x76, 0x6a, 0x2f, 0x51, 0x54, 0xf5, + 0x45, 0xf2, 0x21, 0x81, 0xc1, 0x9f, 0xc6, 0x98 +}; +static const uint8_t ac_dsa_vect120_priv_val[] = { +/* X */ + 0x5a, 0x05, 0x0b, 0xfa, 0xe6, 0x3d, 0x34, 0x7d, 0x64, 0x37, 0x9a, 0xd0, + 0x14, 0x41, 0xb0, 0xef, 0x9a, 0xb0, 0x6e, 0xc5, 0x84, 0x2c, 0x95, 0x2f, + 0x7a, 0x1c, 0x29, 0xce +}; +static const uint8_t ac_dsa_vect120_pub_val[] = { +/* Y */ + 0x24, 0xaa, 0x1c, 0x7c, 0x6a, 0x04, 0x1f, 0x6d, 0x2c, 0x53, 0x30, 0x06, + 0xce, 0xbc, 0xc2, 0xad, 0x04, 0x8b, 0x3d, 0xc0, 0x8f, 0xa8, 0x62, 0x82, + 0xf5, 0x87, 0x9a, 0x23, 0x72, 0x31, 0xd2, 0x30, 0xcd, 0x85, 0x4a, 0xa1, + 0x01, 0x58, 0xce, 0xbb, 0x45, 0xf3, 0x87, 0x92, 0x3f, 0xad, 0xa8, 0xc5, + 0xf4, 0xb9, 0x1a, 0x7b, 0xc2, 0xdc, 0x3e, 0x2c, 0x39, 0x46, 0x37, 0x97, + 0xe6, 0xeb, 0x19, 0x58, 0xab, 0xc9, 0xb9, 0xe7, 0x48, 0xbb, 0xfe, 0x80, + 0xe3, 0x60, 0x23, 0x3e, 0x96, 0x95, 0x22, 0x79, 0x95, 0x9a, 0x6b, 0x80, + 0x61, 0x91, 0x00, 0xf6, 0xf1, 0x87, 0x6f, 0xad, 0xeb, 0x79, 0x04, 0x91, + 0x46, 0x2f, 0x59, 0x17, 0xda, 0x36, 0xce, 0xa3, 0x79, 0x3c, 0x44, 0xdb, + 0x90, 0x90, 0x8c, 0xb9, 0xda, 0x18, 0xf6, 0x96, 0xce, 0xd9, 0x0f, 0x2a, + 0xcb, 0x82, 0x63, 0x55, 0x10, 0x4c, 0x4c, 0x8f, 0x06, 0xc7, 0x37, 0xd4, + 0x8a, 0xcf, 0x98, 0x5d, 0x6b, 0x8c, 0x2a, 0xbf, 0x31, 0x80, 0x72, 0x82, + 0xb6, 0xe6, 0x51, 0xd2, 0x96, 0x7a, 0x16, 0x90, 0x7b, 0xe3, 0xd8, 0xe4, + 0xb7, 0xf3, 0x2e, 0xd3, 0x4e, 0xba, 0x8c, 0x26, 0x2d, 0x6c, 0x0e, 0xcb, + 0x13, 0x19, 0x46, 0xd2, 0x54, 0x63, 0x62, 0xc2, 0x17, 0xae, 0x19, 0x5d, + 0x05, 0x65, 0x6a, 0x4f, 0xcf, 0xac, 0x73, 0x71, 0x7a, 0xe8, 0x5a, 0x57, + 0x1d, 0x81, 0x1c, 0xbc, 0x99, 0xe0, 0xb3, 0x12, 0x4b, 0xba, 0x76, 0x7f, + 0xea, 0xd6, 0x05, 0x26, 0x6d, 0x99, 0x02, 0x1c, 0xdd, 0x8c, 0xb4, 0xc0, + 0x81, 0xbe, 0xf1, 0x02, 0x43, 0x10, 0x07, 0xee, 0x12, 0x52, 0x3b, 0x48, + 0xbb, 0x83, 0x86, 0x98, 0xa5, 0x97, 0x1e, 0x51, 0x72, 0x52, 0xd6, 0xd9, + 0x3e, 0x1c, 0x7f, 0xe9, 0xfb, 0xe0, 0x7b, 0xf4, 0x34, 0x16, 0x4b, 0xaa, + 0xa1, 0x02, 0x6d, 0xa4 +}; +/* K = 5de3d5e6b78c888ba4185c1547272fe562b44e507c871a0524765aea */ +static const uint8_t ac_dsa_vect120_out[] = { +/* R */ + 0x32, 0x5a, 0xa7, 0xb1, 0x73, 0xca, 0xc9, 0x6d, 0x58, 0x65, 0xaa, 0x50, + 0xea, 0x54, 0xe5, 0xdf, 0x45, 0xa1, 0x0e, 0x72, 0xfd, 0x5d, 0xd1, 0xfb, + 0x26, 0x5a, 0xae, 0x09, +/* S */ + 0x0a, 0x72, 0x03, 0xf6, 0xb8, 0xfb, 0xf6, 0x68, 0xb8, 0xf6, 0x43, 0x5e, + 0x92, 0x9f, 0xd5, 0x2f, 0x52, 0xe2, 0x3a, 0xd4, 0xb8, 0xa1, 0x56, 0xae, + 0x5f, 0x3c, 0x9c, 0x47 +}; +/* [mod = L=2048, N=224, SHA-384] */ +static const uint8_t ac_dsa_vect121_prime[] = { +/* P */ + 0xa6, 0xbb, 0x53, 0x33, 0xce, 0x34, 0x3c, 0x31, 0xc9, 0xb2, 0xc8, 0x78, + 0xab, 0x91, 0xee, 0xf2, 0xfd, 0xea, 0x35, 0xc6, 0xdb, 0x0e, 0x71, 0x67, + 0x62, 0xbf, 0xc0, 0xd4, 0x36, 0xd8, 0x75, 0x06, 0xe8, 0x65, 0xa4, 0xd2, + 0xc8, 0xcf, 0xbb, 0xd6, 0x26, 0xce, 0x8b, 0xfe, 0x64, 0x56, 0x3c, 0xa5, + 0x68, 0x6c, 0xd8, 0xcf, 0x08, 0x14, 0x90, 0xf0, 0x24, 0x45, 0xb2, 0x89, + 0x08, 0x79, 0x82, 0x49, 0x5f, 0xb6, 0x99, 0x76, 0xb1, 0x02, 0x42, 0xd6, + 0xd5, 0x0f, 0xc2, 0x3b, 0x4d, 0xbd, 0xb0, 0xbe, 0xf7, 0x83, 0x05, 0xd9, + 0xa4, 0xd0, 0x5d, 0x9e, 0xae, 0x65, 0xd8, 0x7a, 0x89, 0x3e, 0xaf, 0x39, + 0x7e, 0x04, 0xe3, 0x9b, 0xaa, 0x85, 0xa2, 0x6c, 0x8f, 0xfb, 0xde, 0xf1, + 0x23, 0x32, 0x87, 0xb5, 0xf5, 0xb6, 0xef, 0x6a, 0x90, 0xf2, 0x7a, 0x69, + 0x48, 0x1a, 0x93, 0x2e, 0xe4, 0x7b, 0x18, 0xd5, 0xd2, 0x7e, 0xb1, 0x07, + 0xff, 0xb0, 0x50, 0x25, 0xe6, 0x46, 0xe8, 0x87, 0x6b, 0x5c, 0xb5, 0x67, + 0xfe, 0xc1, 0xdd, 0x35, 0x83, 0x5d, 0x42, 0x08, 0x21, 0x98, 0x53, 0x1f, + 0xaf, 0xbe, 0x5a, 0xe2, 0x80, 0xc5, 0x75, 0xa1, 0xfb, 0x0e, 0x62, 0xe9, + 0xb3, 0xca, 0x37, 0xe1, 0x97, 0xad, 0x96, 0xd9, 0xdd, 0xe1, 0xf3, 0x3f, + 0x2c, 0xec, 0x7d, 0x27, 0xde, 0xae, 0x26, 0x1c, 0x83, 0xee, 0x8e, 0x20, + 0x02, 0xaf, 0x7e, 0xb6, 0xe8, 0x2f, 0x6a, 0x14, 0x79, 0x6a, 0xf0, 0x37, + 0x57, 0x7a, 0x10, 0x32, 0xbb, 0xc7, 0x09, 0x12, 0x9c, 0xaa, 0xbd, 0x8a, + 0xdd, 0xf8, 0x70, 0xae, 0x2d, 0x05, 0x95, 0xc8, 0xfd, 0xb3, 0x71, 0x55, + 0x74, 0x8f, 0x0d, 0xea, 0x34, 0xb4, 0x4d, 0x4f, 0x82, 0xed, 0x58, 0xc2, + 0xf5, 0xb1, 0xb8, 0x48, 0x16, 0x62, 0xac, 0x53, 0x47, 0x3c, 0x69, 0x34, + 0x10, 0x08, 0x2f, 0xbd +}; +static const uint8_t ac_dsa_vect121_sub_prime[] = { +/* Q */ + 0x8c, 0x3e, 0xe5, 0xbd, 0x9a, 0x2a, 0xaf, 0x06, 0x8b, 0xd5, 0x84, 0x5b, + 0xd5, 0x5e, 0xcf, 0x27, 0x41, 0x70, 0x55, 0x30, 0x75, 0x77, 0xbb, 0xc3, + 0x77, 0x0e, 0xc6, 0x8b +}; +static const uint8_t ac_dsa_vect121_base[] = { +/* G */ + 0x43, 0xb5, 0xa6, 0xb6, 0xd0, 0xbb, 0x96, 0x2e, 0xc9, 0x76, 0x6a, 0x37, + 0x7c, 0x32, 0xcc, 0x41, 0x24, 0xf1, 0x31, 0x11, 0x88, 0xc2, 0xec, 0xf9, + 0x5c, 0x0c, 0xd4, 0xa4, 0xfa, 0x09, 0x72, 0x25, 0xb7, 0x61, 0x8c, 0xb1, + 0x27, 0x6c, 0x47, 0x45, 0x78, 0xd3, 0xbf, 0x56, 0x4c, 0x14, 0x51, 0x99, + 0xc0, 0x92, 0xa1, 0xb1, 0x4b, 0xaa, 0x92, 0x9c, 0x2f, 0x3f, 0x0f, 0x36, + 0xe0, 0xc2, 0xda, 0xe9, 0x1e, 0xba, 0x08, 0xbe, 0x30, 0x99, 0x2a, 0x88, + 0x9f, 0x29, 0x52, 0xe0, 0x44, 0x2c, 0x37, 0xaf, 0x48, 0x4a, 0x4e, 0xcd, + 0xc3, 0x24, 0x3c, 0xcf, 0xcb, 0x9e, 0x34, 0x13, 0xcf, 0x5c, 0xdd, 0x66, + 0x30, 0xb0, 0x9f, 0xe1, 0x7e, 0xfb, 0xfd, 0xe1, 0x4d, 0x87, 0x25, 0x49, + 0x30, 0x19, 0xb7, 0xb7, 0x3d, 0x1f, 0x78, 0x2b, 0x48, 0xef, 0x30, 0xbe, + 0xc3, 0x6e, 0x00, 0xe0, 0x2b, 0xa3, 0x36, 0xd2, 0x25, 0x4f, 0xc2, 0x02, + 0xa6, 0x96, 0x12, 0xcd, 0x94, 0x46, 0xf9, 0x1d, 0x76, 0xb7, 0x39, 0xff, + 0xa6, 0xd8, 0xb8, 0x60, 0x52, 0xf8, 0xdc, 0x5f, 0x11, 0x45, 0x80, 0x1c, + 0x56, 0x24, 0x1a, 0xf5, 0xba, 0x90, 0x37, 0x24, 0x1b, 0xd8, 0x9e, 0x63, + 0x38, 0xb5, 0x8e, 0x01, 0x31, 0x06, 0x71, 0xc2, 0x68, 0xeb, 0x5e, 0x33, + 0xac, 0xb5, 0x7d, 0x1f, 0x99, 0xf1, 0x64, 0x40, 0xa6, 0x75, 0x82, 0x7d, + 0x40, 0x17, 0x75, 0x4d, 0x60, 0x1a, 0x17, 0xad, 0xa2, 0xfb, 0xed, 0xf9, + 0x04, 0x55, 0x4a, 0x90, 0xb0, 0x15, 0x30, 0xda, 0x8c, 0x93, 0xcd, 0x14, + 0xce, 0x29, 0x3c, 0xb2, 0xbd, 0x3e, 0x79, 0x37, 0xe9, 0x34, 0xb7, 0x9e, + 0x31, 0x0f, 0xe4, 0xd8, 0x0c, 0x13, 0xf9, 0x2f, 0x63, 0x38, 0x13, 0x55, + 0xbd, 0x80, 0xa1, 0xab, 0xee, 0x1a, 0x73, 0xfd, 0xfb, 0x6d, 0xa2, 0x4e, + 0xf2, 0x80, 0x02, 0xa3 +}; +static const uint8_t ac_dsa_vect121_ptx[] = { +/* Msg */ + 0xdf, 0x5d, 0x56, 0x4d, 0xb8, 0x35, 0x92, 0xc1, 0x12, 0x8b, 0xe5, 0xd2, + 0x9b, 0x70, 0x36, 0x88, 0x0d, 0x55, 0xe8, 0x34, 0xa2, 0x91, 0xa7, 0x45, + 0xed, 0x8d, 0xcd, 0x43, 0x8c, 0x4d, 0xa6, 0xb1, 0xb9, 0xf3, 0x94, 0x12, + 0xb2, 0xc5, 0x11, 0x07, 0x30, 0xdb, 0x83, 0xc1, 0xcc, 0xdf, 0xe9, 0x05, + 0x9d, 0xd9, 0x6e, 0xc7, 0xea, 0x2b, 0xbc, 0xb3, 0x4e, 0x3e, 0xba, 0x72, + 0xef, 0x0a, 0x1d, 0x47, 0x21, 0xc7, 0xc0, 0x22, 0x1e, 0x29, 0x27, 0x9f, + 0x01, 0x4d, 0x63, 0xfa, 0xcc, 0x5b, 0xc8, 0xf1, 0x8c, 0x53, 0x9b, 0x92, + 0xff, 0x2a, 0xf8, 0x9e, 0x56, 0x82, 0x25, 0xd6, 0xb4, 0xcf, 0x59, 0x9c, + 0xb3, 0xdf, 0xf5, 0xe3, 0xc6, 0xdd, 0xfa, 0xc0, 0xa2, 0x7f, 0x10, 0xf6, + 0x36, 0xec, 0x22, 0x0a, 0xbb, 0x72, 0x63, 0x0b, 0xae, 0x9a, 0x39, 0xc1, + 0x8f, 0xd3, 0x66, 0x3e, 0x46, 0x51, 0xcc, 0xac +}; +static const uint8_t ac_dsa_vect121_priv_val[] = { +/* X */ + 0x4e, 0xfa, 0x51, 0x36, 0xeb, 0x6a, 0xa7, 0x4e, 0x92, 0xbb, 0xfc, 0x91, + 0x3b, 0x0b, 0xfe, 0xbb, 0x61, 0x3d, 0xb7, 0xa4, 0x72, 0x21, 0xfb, 0x7b, + 0x64, 0xf4, 0x2e, 0x6f +}; +static const uint8_t ac_dsa_vect121_pub_val[] = { +/* Y */ + 0x64, 0x79, 0x79, 0xb7, 0x96, 0x0c, 0xe7, 0xb9, 0x71, 0xff, 0x0e, 0x5f, + 0x64, 0x35, 0xf4, 0x2a, 0x41, 0xb1, 0x8c, 0x9d, 0xe0, 0x9a, 0x30, 0x11, + 0x14, 0xa0, 0x13, 0xa7, 0xcd, 0x01, 0x18, 0x3f, 0x17, 0x6f, 0x88, 0x83, + 0x83, 0x79, 0xdc, 0xb4, 0xef, 0xb6, 0x7d, 0xae, 0xa7, 0x9d, 0xef, 0x3f, + 0x04, 0x2c, 0xbc, 0xf9, 0xcc, 0x50, 0x3b, 0x4c, 0x21, 0x51, 0xa2, 0x36, + 0x4f, 0x7c, 0x94, 0x37, 0xb1, 0x96, 0x43, 0xe6, 0x7e, 0x24, 0xa3, 0x6b, + 0xac, 0x4a, 0x4c, 0xfa, 0x29, 0x3d, 0xee, 0xdf, 0x8e, 0xc6, 0xb1, 0x54, + 0xa3, 0x2a, 0xa7, 0x29, 0x85, 0xf7, 0xd8, 0xde, 0x23, 0x53, 0x34, 0xb5, + 0x46, 0xc2, 0x9d, 0xef, 0x45, 0x8c, 0x55, 0xd0, 0xc5, 0xc0, 0xac, 0x5d, + 0x74, 0xe2, 0x02, 0x4e, 0xc7, 0xd4, 0xab, 0xc2, 0xfd, 0xa5, 0x16, 0xa2, + 0xa0, 0xb1, 0xa4, 0xd8, 0x86, 0xad, 0x92, 0xc2, 0x04, 0x70, 0x78, 0x28, + 0xa4, 0xfc, 0x77, 0x94, 0xf6, 0x0e, 0xe8, 0xa4, 0xbe, 0x11, 0x01, 0xc9, + 0xe5, 0x51, 0x8f, 0x7e, 0x19, 0xee, 0xbd, 0x47, 0x5f, 0x2d, 0xe6, 0xf6, + 0xba, 0x89, 0xc2, 0x8b, 0xd1, 0x29, 0xf1, 0x39, 0x93, 0xbe, 0xfe, 0x58, + 0x18, 0x44, 0x03, 0x19, 0xa7, 0x95, 0x49, 0x83, 0x31, 0x96, 0x34, 0x2a, + 0x31, 0xdb, 0xaf, 0x7d, 0x79, 0x49, 0x7d, 0xec, 0x65, 0xee, 0x7d, 0xbe, + 0xf7, 0x0e, 0x58, 0xf9, 0x9d, 0x05, 0x95, 0xf6, 0xa7, 0x11, 0x40, 0x9a, + 0xde, 0x31, 0x51, 0xd4, 0x55, 0x63, 0xd5, 0x3c, 0x1c, 0xd0, 0xa8, 0xab, + 0x1a, 0x18, 0xbe, 0xff, 0x65, 0x02, 0xcb, 0xb0, 0xc0, 0x69, 0xb1, 0x14, + 0xea, 0x7b, 0xe7, 0x78, 0x98, 0xd0, 0xf4, 0xe5, 0x49, 0x99, 0x1b, 0xa0, + 0xb3, 0x68, 0x97, 0x1b, 0x10, 0x72, 0xec, 0xe4, 0xaf, 0xc3, 0x80, 0xe9, + 0xae, 0x32, 0x9a, 0x50 +}; +/* K = 7e0f1ce21d185ae65c0a00395567ea9cf217462b58b9c89c4e5ff9cf */ +static const uint8_t ac_dsa_vect121_out[] = { +/* R */ + 0x5a, 0xb4, 0x3e, 0xde, 0x66, 0xa1, 0x56, 0x88, 0x14, 0x6d, 0x1f, 0x4c, + 0xd7, 0x16, 0x47, 0x02, 0xc0, 0xc4, 0x45, 0x7b, 0xd4, 0xfd, 0xde, 0xba, + 0xc0, 0x48, 0x29, 0x53, +/* S */ + 0x6c, 0x58, 0xe8, 0xab, 0x27, 0xd2, 0x85, 0x12, 0xc4, 0x60, 0x63, 0xc9, + 0x6b, 0xf5, 0xbc, 0xeb, 0x8f, 0xba, 0xd2, 0x32, 0xd8, 0xf5, 0xb3, 0x9c, + 0x47, 0x55, 0xd0, 0xb1 +}; +#define ac_dsa_vect122_prime ac_dsa_vect121_prime +#define ac_dsa_vect122_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect122_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect122_ptx[] = { +/* Msg */ + 0xeb, 0xeb, 0x9e, 0x2b, 0x69, 0x2e, 0xc6, 0xc9, 0xaf, 0xad, 0x2a, 0x0c, + 0x2b, 0x90, 0x89, 0x39, 0x94, 0x3f, 0xdf, 0x4b, 0xb7, 0x43, 0x8e, 0x3b, + 0xd9, 0x28, 0x8e, 0x76, 0x81, 0x98, 0x40, 0x87, 0xff, 0xdc, 0xf8, 0x65, + 0x02, 0x07, 0x9c, 0x29, 0x12, 0x36, 0xd7, 0xf1, 0xad, 0xb5, 0x04, 0xe6, + 0x7e, 0x0f, 0x88, 0xbe, 0xe6, 0x1b, 0x61, 0x71, 0x70, 0x14, 0xcf, 0x06, + 0xb5, 0xfa, 0xd5, 0xcb, 0x36, 0xf1, 0xb2, 0x23, 0xb6, 0x39, 0x12, 0xcd, + 0xcd, 0x2b, 0x94, 0x16, 0x52, 0x4d, 0x37, 0xf5, 0xd7, 0xb0, 0x5c, 0x37, + 0xd1, 0x78, 0x96, 0x69, 0xe1, 0x41, 0xaf, 0xf6, 0x67, 0x0d, 0xb2, 0xe0, + 0xde, 0x31, 0x67, 0x3b, 0x20, 0x55, 0xf6, 0x79, 0x9a, 0xc8, 0x87, 0x93, + 0x7e, 0x56, 0x64, 0xa6, 0x59, 0xea, 0x02, 0x54, 0xa8, 0xd4, 0xba, 0x6f, + 0x20, 0x4d, 0xf2, 0xa3, 0x8c, 0x2a, 0x77, 0xe4 +}; +static const uint8_t ac_dsa_vect122_priv_val[] = { +/* X */ + 0x1c, 0x84, 0xc5, 0xc0, 0x65, 0xff, 0x16, 0x5a, 0x0e, 0x1d, 0x27, 0x6c, + 0x2e, 0xa9, 0xfd, 0xbf, 0x84, 0x23, 0xc1, 0x2a, 0xa1, 0xc7, 0x38, 0x44, + 0xd6, 0xc6, 0x49, 0x42 +}; +static const uint8_t ac_dsa_vect122_pub_val[] = { +/* Y */ + 0x31, 0xd3, 0x1a, 0x5b, 0xb8, 0x28, 0x74, 0xbd, 0xc7, 0x6c, 0xab, 0xae, + 0x3e, 0xc8, 0x56, 0x90, 0xaa, 0x51, 0x03, 0xca, 0xcb, 0xe5, 0x23, 0x4e, + 0x0d, 0x5e, 0xf6, 0x45, 0xee, 0xf3, 0x80, 0xd3, 0xae, 0x2f, 0x62, 0x39, + 0x14, 0x4b, 0x82, 0xb1, 0x01, 0xa7, 0xef, 0x47, 0x44, 0xaa, 0xdb, 0x8f, + 0xc9, 0x8e, 0x82, 0xb4, 0x13, 0x72, 0xe9, 0x9d, 0x6c, 0x90, 0x5c, 0xa9, + 0x74, 0xb8, 0x1c, 0x9f, 0xa5, 0x21, 0xf9, 0x20, 0xa1, 0xdf, 0xfa, 0xb4, + 0xe2, 0xee, 0x15, 0xf6, 0x1e, 0x03, 0xb7, 0x42, 0xf4, 0x24, 0x70, 0xdc, + 0x2f, 0xa9, 0xab, 0x25, 0x7f, 0x11, 0x36, 0xf9, 0xfe, 0x4b, 0x5a, 0xa2, + 0xec, 0xe5, 0x20, 0x72, 0x30, 0xc4, 0x90, 0x6d, 0x67, 0xa1, 0x56, 0xa3, + 0xff, 0xef, 0x47, 0x0c, 0xbf, 0x3a, 0x65, 0xe3, 0x18, 0x9b, 0x38, 0x9d, + 0xdc, 0x66, 0xc6, 0x04, 0x0a, 0x79, 0x95, 0xc6, 0x8a, 0xe1, 0xdf, 0x20, + 0x85, 0x94, 0x1b, 0x5b, 0x1d, 0xf7, 0xd9, 0x57, 0xfb, 0xcf, 0x36, 0x68, + 0x24, 0xe0, 0x29, 0x1d, 0xf8, 0x8e, 0xae, 0x55, 0xd8, 0xd3, 0x04, 0x0d, + 0x8d, 0x09, 0xf4, 0xf6, 0xff, 0xee, 0x34, 0xcc, 0xbd, 0x19, 0x61, 0x85, + 0x2a, 0x5a, 0x62, 0xb2, 0x6c, 0x8d, 0xaa, 0xaa, 0x56, 0xa8, 0xff, 0x7f, + 0xa8, 0x63, 0xb6, 0x3c, 0x6d, 0x60, 0x4f, 0xd3, 0x37, 0x82, 0x62, 0xe8, + 0x15, 0xf5, 0x51, 0x71, 0xdc, 0xa3, 0x5d, 0x04, 0x76, 0x1f, 0xe3, 0xd9, + 0xed, 0xdc, 0x6d, 0x32, 0x65, 0x7a, 0x96, 0xd6, 0x43, 0xd4, 0x60, 0x8e, + 0xf2, 0x14, 0x3b, 0x19, 0xf1, 0xc9, 0xd8, 0xc0, 0x0e, 0xd2, 0x65, 0x47, + 0x1b, 0x24, 0x5b, 0x60, 0xf3, 0x1f, 0x8c, 0x7e, 0xd4, 0x8d, 0xd6, 0xb1, + 0x8b, 0x5b, 0xec, 0x1a, 0x6e, 0xde, 0x14, 0x5d, 0xea, 0x40, 0x28, 0x32, + 0x30, 0x72, 0x4e, 0xc8 +}; +/* K = 6f399d636570476f7a2013efdc74a1bb75f5b35ce835079c4e19cc4d */ +static const uint8_t ac_dsa_vect122_out[] = { +/* R */ + 0x82, 0xc3, 0x74, 0x7a, 0x06, 0x58, 0xdf, 0x00, 0x6a, 0x7a, 0x20, 0x5a, + 0x6a, 0xe2, 0xae, 0xdd, 0x5d, 0x29, 0x48, 0x48, 0x85, 0x59, 0xfc, 0x3c, + 0xfd, 0x64, 0x3a, 0x64, +/* S */ + 0x86, 0x36, 0x79, 0x6d, 0xf6, 0x22, 0xd1, 0x3f, 0x07, 0x0f, 0xbe, 0xd4, + 0x18, 0x4c, 0x81, 0x38, 0x35, 0x8c, 0x21, 0xdb, 0x30, 0xc6, 0x06, 0xb8, + 0xf9, 0xbe, 0x52, 0x1a +}; +#define ac_dsa_vect123_prime ac_dsa_vect121_prime +#define ac_dsa_vect123_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect123_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect123_ptx[] = { +/* Msg */ + 0xdb, 0xd2, 0x51, 0x6b, 0x03, 0xfd, 0xc5, 0x8b, 0x32, 0xc0, 0x23, 0x30, + 0x80, 0xff, 0xee, 0xa4, 0x1c, 0x0d, 0x9c, 0x15, 0x6b, 0x30, 0x33, 0x2e, + 0xc4, 0x2b, 0xe5, 0xe1, 0x05, 0x84, 0xbe, 0x3e, 0x3d, 0xb8, 0x5f, 0xfd, + 0x5b, 0x5b, 0xae, 0x16, 0xfc, 0x87, 0x6a, 0x0c, 0x92, 0x17, 0x62, 0x7d, + 0x84, 0x01, 0x12, 0x23, 0xfa, 0xb5, 0x7d, 0x17, 0x6d, 0xef, 0x61, 0xe4, + 0x0d, 0x91, 0x2e, 0x7e, 0xeb, 0x2b, 0xf8, 0x68, 0x73, 0x4a, 0xe8, 0xf2, + 0x76, 0xa9, 0x6a, 0xb1, 0x3d, 0xe5, 0x58, 0xec, 0x42, 0x61, 0x41, 0x67, + 0xc5, 0xaa, 0x4c, 0x60, 0x35, 0x7f, 0x71, 0xfa, 0xc5, 0x89, 0x80, 0xe5, + 0x79, 0x44, 0x0f, 0x69, 0x96, 0x8d, 0x22, 0x80, 0xbc, 0x97, 0x0d, 0x00, + 0x66, 0xb5, 0xbd, 0x6a, 0x6f, 0x50, 0x02, 0x48, 0x15, 0x10, 0x25, 0x6b, + 0x3e, 0xb2, 0x1b, 0xbb, 0x92, 0xef, 0x2c, 0xdd +}; +static const uint8_t ac_dsa_vect123_priv_val[] = { +/* X */ + 0x38, 0x35, 0x85, 0x09, 0x8e, 0xdd, 0x86, 0x7a, 0x85, 0x22, 0xdf, 0xad, + 0x08, 0x99, 0x70, 0x95, 0xaa, 0x23, 0x53, 0x9b, 0x9c, 0x81, 0x6a, 0x5e, + 0x28, 0x35, 0x9b, 0x51 +}; +static const uint8_t ac_dsa_vect123_pub_val[] = { +/* Y */ + 0x6e, 0x6e, 0xe0, 0x31, 0x9a, 0xf8, 0xfa, 0xfd, 0x7a, 0xe0, 0x20, 0x13, + 0xf4, 0x22, 0x7e, 0x26, 0x62, 0x44, 0xae, 0x5d, 0x87, 0xfe, 0x15, 0x6c, + 0xef, 0xd4, 0x51, 0x8b, 0xcd, 0x71, 0xaa, 0x73, 0xf9, 0x36, 0x4b, 0xff, + 0x35, 0xd4, 0xd2, 0x3d, 0x45, 0xb0, 0xf4, 0x7d, 0xfe, 0x93, 0xa6, 0x07, + 0xd9, 0xf8, 0xb3, 0x99, 0xb4, 0x24, 0xba, 0x75, 0x07, 0x2f, 0xdc, 0xed, + 0x6c, 0x3e, 0xd2, 0x11, 0x06, 0x06, 0xfa, 0x48, 0xed, 0x63, 0x3f, 0xae, + 0xf2, 0x06, 0x4f, 0xb3, 0x36, 0x06, 0x9e, 0xec, 0x7e, 0xbd, 0x8a, 0xe4, + 0x75, 0x97, 0x83, 0x89, 0xe6, 0xe4, 0x33, 0xd5, 0xa4, 0x35, 0xd6, 0x52, + 0x9a, 0x66, 0xc4, 0x89, 0xce, 0x15, 0x39, 0x40, 0xd2, 0xb1, 0xb8, 0xc8, + 0x86, 0xc8, 0x11, 0x0d, 0x8b, 0x0a, 0xeb, 0x64, 0x1a, 0x40, 0xe2, 0x85, + 0xd6, 0x75, 0x1c, 0xe7, 0x10, 0x27, 0xc3, 0x0e, 0xc6, 0x2f, 0x4b, 0x1f, + 0xc1, 0x4f, 0x4d, 0xa2, 0x0b, 0x1d, 0x50, 0x57, 0x42, 0xca, 0xda, 0x20, + 0x1c, 0xea, 0x81, 0x93, 0x0c, 0x38, 0x1f, 0x8a, 0x6f, 0x13, 0xdd, 0x0a, + 0x42, 0xaa, 0xc1, 0xe0, 0xbd, 0x7f, 0xcd, 0x19, 0xc6, 0xbd, 0xd1, 0x70, + 0xfa, 0xc6, 0xa4, 0x23, 0x76, 0x7b, 0x83, 0x1c, 0x1e, 0x28, 0x9e, 0x0a, + 0x29, 0xef, 0x85, 0xd8, 0x17, 0xad, 0x23, 0x8d, 0x91, 0xac, 0x3a, 0xce, + 0x2f, 0x40, 0xa1, 0x63, 0xb0, 0xa9, 0xbb, 0xdd, 0xc6, 0xf0, 0x5d, 0x0b, + 0xdc, 0xd8, 0xcc, 0x27, 0x4a, 0x74, 0xd0, 0x74, 0x3c, 0x9f, 0xb5, 0x65, + 0x56, 0xec, 0x1c, 0xb8, 0xe9, 0xcb, 0xa9, 0x82, 0xc1, 0x5a, 0x9a, 0x66, + 0xfa, 0x6b, 0x69, 0x99, 0xb8, 0x48, 0x5d, 0xb1, 0xa8, 0x6e, 0xe1, 0x8b, + 0xe1, 0x6e, 0x06, 0x8e, 0x12, 0xa8, 0xa1, 0x65, 0xe3, 0x59, 0x9d, 0xf9, + 0x66, 0x69, 0xa1, 0xb7 +}; +/* K = 0183d11f1597ec9db32db21c1e910fa2be2f276f35d0583ce8b8f6ab */ +static const uint8_t ac_dsa_vect123_out[] = { +/* R */ + 0x04, 0x04, 0x05, 0x13, 0x6a, 0x12, 0x20, 0xad, 0xbb, 0x64, 0xab, 0x75, + 0x1d, 0xb3, 0x30, 0x7f, 0xaf, 0xad, 0x54, 0x47, 0xab, 0x2d, 0x9b, 0xcc, + 0x52, 0xf7, 0x9b, 0xe3, +/* S */ + 0x1d, 0x35, 0xf3, 0x26, 0x9c, 0x77, 0xc5, 0x77, 0x24, 0x3f, 0x1d, 0xb8, + 0xdf, 0xdb, 0xc4, 0xcc, 0x45, 0x31, 0x57, 0x42, 0x76, 0xf0, 0xda, 0x1f, + 0x7a, 0x44, 0xac, 0xd4 +}; +#define ac_dsa_vect124_prime ac_dsa_vect121_prime +#define ac_dsa_vect124_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect124_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect124_ptx[] = { +/* Msg */ + 0x34, 0xc4, 0x54, 0x35, 0xd0, 0xcc, 0x29, 0x26, 0x92, 0x72, 0xa9, 0x3d, + 0x43, 0x32, 0x06, 0x98, 0xe4, 0x54, 0xa7, 0xc2, 0x87, 0xdb, 0x9d, 0x06, + 0x20, 0x92, 0xac, 0xac, 0xd7, 0xca, 0x08, 0x64, 0x55, 0xe5, 0x83, 0xba, + 0xee, 0x12, 0x76, 0xca, 0xba, 0x06, 0x8f, 0xde, 0xeb, 0x52, 0x18, 0x33, + 0x96, 0xd5, 0x44, 0x4c, 0x5a, 0x14, 0xad, 0x52, 0xa5, 0xc2, 0xbc, 0x08, + 0x2c, 0xd8, 0x74, 0x52, 0xaa, 0x8f, 0x9b, 0x23, 0x05, 0x6b, 0x5f, 0x8a, + 0xf2, 0x63, 0x8d, 0x96, 0x5e, 0xf4, 0xfe, 0x6e, 0x4e, 0x68, 0xe8, 0x8b, + 0x0f, 0x50, 0xe0, 0x12, 0x48, 0xfe, 0x6a, 0x6a, 0x1d, 0x9d, 0x6d, 0x93, + 0xb0, 0x3c, 0xd5, 0x5d, 0x16, 0xfd, 0x83, 0xcd, 0x4e, 0x06, 0x76, 0x3d, + 0x92, 0x6f, 0x7c, 0x50, 0xf2, 0x0f, 0x0e, 0xd6, 0x73, 0x06, 0x13, 0xf0, + 0xf4, 0xdb, 0x57, 0x1e, 0x22, 0xd2, 0x88, 0xe4 +}; +static const uint8_t ac_dsa_vect124_priv_val[] = { +/* X */ + 0x0f, 0x11, 0x5f, 0xc7, 0x07, 0x32, 0x62, 0xe2, 0xf9, 0x3a, 0x9d, 0x46, + 0xb4, 0x07, 0xb0, 0xf1, 0xbc, 0x29, 0x29, 0x2a, 0xa0, 0x9c, 0xd1, 0xa9, + 0x8a, 0x34, 0xa2, 0x19 +}; +static const uint8_t ac_dsa_vect124_pub_val[] = { +/* Y */ + 0x5e, 0xbd, 0x81, 0x52, 0x93, 0x5f, 0xf2, 0xa3, 0xf9, 0xa6, 0x1b, 0x27, + 0x5e, 0x98, 0x08, 0xa0, 0x41, 0xaa, 0xd5, 0x65, 0x0f, 0x59, 0x3f, 0x61, + 0x2a, 0xf3, 0x3b, 0xc4, 0x62, 0xb8, 0xc9, 0x94, 0x16, 0x93, 0x72, 0xe8, + 0xf8, 0x0f, 0x51, 0xb1, 0x5f, 0x5c, 0xe9, 0x66, 0xea, 0x3e, 0x76, 0xa9, + 0x12, 0xc6, 0x53, 0x97, 0x83, 0x37, 0xe9, 0x62, 0x21, 0x9e, 0x32, 0x3b, + 0x6e, 0x92, 0x2d, 0xea, 0x4b, 0xcc, 0x23, 0xc6, 0x46, 0xa2, 0x2e, 0xec, + 0xde, 0x02, 0x43, 0x31, 0x26, 0xfb, 0xac, 0xe0, 0xe3, 0xa0, 0x1f, 0xa6, + 0xd0, 0xb9, 0xfd, 0xea, 0x92, 0x45, 0xd6, 0x78, 0x99, 0xa7, 0xb7, 0x45, + 0xb8, 0x84, 0x7c, 0x80, 0x87, 0xfa, 0x7f, 0x6c, 0x0f, 0x3e, 0xda, 0xfa, + 0xb4, 0xc3, 0xb4, 0x72, 0x20, 0x82, 0x1f, 0xe4, 0x6f, 0x1b, 0xcb, 0x00, + 0xa3, 0x23, 0xdf, 0xf3, 0xde, 0xe4, 0x7e, 0xe1, 0xde, 0x2e, 0xce, 0x44, + 0xe1, 0xfd, 0xf3, 0xe6, 0x4a, 0xa2, 0x0c, 0x9e, 0x6b, 0x58, 0xe5, 0x34, + 0x48, 0x2e, 0x73, 0x13, 0xda, 0xce, 0x1c, 0x61, 0x7d, 0x8e, 0xa9, 0xa6, + 0x5d, 0xd5, 0x1f, 0xd3, 0x30, 0x24, 0xf7, 0x35, 0xc3, 0x84, 0x4c, 0x5c, + 0x6b, 0x4a, 0x3f, 0x44, 0x7e, 0x71, 0x4a, 0xb0, 0xc1, 0x7d, 0xc8, 0x8e, + 0x33, 0xf0, 0x8b, 0x14, 0x2b, 0x72, 0xe8, 0x11, 0xe6, 0xda, 0x00, 0x29, + 0x9c, 0x82, 0x89, 0x8a, 0xaf, 0x2b, 0xed, 0x5a, 0xe5, 0x17, 0x0c, 0x1d, + 0xd0, 0x05, 0x67, 0x8d, 0x2b, 0x57, 0x6b, 0x9c, 0xe3, 0xe6, 0xbc, 0x6b, + 0x2a, 0xeb, 0x04, 0xc9, 0xf0, 0x4e, 0x44, 0x4e, 0x2a, 0x98, 0x08, 0x40, + 0x5f, 0xf5, 0x92, 0x65, 0x48, 0xb5, 0x93, 0x04, 0xdd, 0xdc, 0xa8, 0x97, + 0x26, 0x31, 0xf7, 0xfb, 0x13, 0x68, 0x08, 0xe2, 0x13, 0xec, 0xd9, 0x3a, + 0xf9, 0x8e, 0x2e, 0x54 +}; +/* K = 835a744aa418a297b7e11febe7f3bba590752e58fa1ae12ffa3bfacc */ +static const uint8_t ac_dsa_vect124_out[] = { +/* R */ + 0x66, 0x48, 0x1f, 0x24, 0x1f, 0x6b, 0x44, 0x31, 0x48, 0xf0, 0xb1, 0xf2, + 0x45, 0x9b, 0xe5, 0xca, 0x16, 0x41, 0x3d, 0x94, 0x7d, 0x09, 0x81, 0x62, + 0x87, 0x17, 0xc1, 0x08, +/* S */ + 0x2c, 0xda, 0xa7, 0x35, 0x00, 0xd0, 0xad, 0x29, 0x12, 0x52, 0xd0, 0x7c, + 0xef, 0xf9, 0xcf, 0xea, 0xb8, 0x7a, 0x73, 0x97, 0x52, 0x29, 0x1e, 0xb5, + 0xdc, 0xef, 0xea, 0x87 +}; +#define ac_dsa_vect125_prime ac_dsa_vect121_prime +#define ac_dsa_vect125_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect125_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect125_ptx[] = { +/* Msg */ + 0xd7, 0xac, 0x5c, 0xc8, 0xa4, 0xc3, 0xf3, 0x8c, 0xfe, 0x5c, 0x0e, 0x10, + 0x68, 0xea, 0x28, 0xf0, 0xf9, 0x5d, 0x32, 0x50, 0xd1, 0xae, 0xae, 0x5f, + 0x66, 0xbd, 0xc4, 0xd2, 0x2e, 0x23, 0xe2, 0x46, 0xff, 0x30, 0x42, 0x9c, + 0xbc, 0xba, 0xd3, 0xb0, 0x2a, 0x62, 0xa0, 0xa1, 0x79, 0xd4, 0xd1, 0x07, + 0x13, 0x0f, 0xa3, 0xa7, 0x80, 0xc0, 0x09, 0x2c, 0x32, 0x9c, 0x2b, 0x02, + 0x6e, 0x12, 0xe6, 0x73, 0x5a, 0x75, 0xc4, 0x95, 0xb0, 0x97, 0xaa, 0x69, + 0xeb, 0xe9, 0x8a, 0x96, 0xff, 0x89, 0x12, 0x34, 0xff, 0x37, 0x95, 0x11, + 0x14, 0x9e, 0x07, 0xc6, 0xe2, 0x41, 0x1e, 0x58, 0x97, 0x6e, 0xe9, 0x3f, + 0xba, 0x7d, 0x3d, 0x57, 0x0c, 0x91, 0x1f, 0x6f, 0x20, 0x83, 0x75, 0x78, + 0x3f, 0xf5, 0xd9, 0x47, 0xa3, 0xaf, 0x0c, 0x83, 0x9d, 0x21, 0x0a, 0x8e, + 0x4a, 0x8c, 0x8f, 0xa4, 0x1e, 0xfb, 0xc5, 0x7e +}; +static const uint8_t ac_dsa_vect125_priv_val[] = { +/* X */ + 0x53, 0x39, 0xec, 0x1f, 0x86, 0xa0, 0xdf, 0xd8, 0x13, 0x24, 0xfc, 0xa6, + 0xa0, 0xd3, 0xe1, 0x02, 0xb1, 0x2f, 0xba, 0x8f, 0xe8, 0xc1, 0xbc, 0xa4, + 0x5d, 0x8d, 0xdf, 0x10 +}; +static const uint8_t ac_dsa_vect125_pub_val[] = { +/* Y */ + 0x7b, 0x5f, 0xb0, 0x22, 0xb5, 0x5f, 0xb6, 0x1f, 0x8e, 0xf8, 0xcd, 0xbf, + 0xee, 0x46, 0xc0, 0xfc, 0x61, 0xe5, 0x9f, 0xc6, 0x2d, 0xee, 0x5c, 0x14, + 0xd0, 0xc3, 0x13, 0x4b, 0x4f, 0x26, 0x59, 0x11, 0x2e, 0x3f, 0x4e, 0x70, + 0x17, 0xf9, 0x57, 0x4a, 0x27, 0x24, 0x18, 0x8b, 0xa6, 0xa1, 0xce, 0x77, + 0x7a, 0x89, 0x15, 0xbc, 0x11, 0x71, 0xd7, 0x38, 0x75, 0x4b, 0x5a, 0xc1, + 0xdf, 0x92, 0x31, 0x03, 0xad, 0x7b, 0x19, 0x85, 0x11, 0xed, 0x36, 0x27, + 0x26, 0x68, 0xae, 0x0c, 0x2e, 0x31, 0x42, 0xba, 0x01, 0x1c, 0xb4, 0x5f, + 0x89, 0x3d, 0xdb, 0xf7, 0xb3, 0x86, 0x25, 0x81, 0x8c, 0xba, 0x9a, 0x9b, + 0x78, 0xae, 0xf8, 0xd0, 0x60, 0x07, 0xed, 0x50, 0x5e, 0x6d, 0xd6, 0xe2, + 0x0c, 0x92, 0xd2, 0x50, 0x02, 0x34, 0xf1, 0x04, 0xc1, 0x28, 0x3f, 0x7c, + 0x00, 0xcf, 0x2a, 0x3a, 0x32, 0x45, 0x8d, 0x97, 0xf7, 0xbd, 0x17, 0x09, + 0x0f, 0x76, 0x23, 0x5c, 0x6c, 0x4f, 0x8a, 0xe1, 0x94, 0xd5, 0x2d, 0x67, + 0xc7, 0x4a, 0x85, 0x49, 0x73, 0xfd, 0x12, 0x47, 0x51, 0xf7, 0xf5, 0x80, + 0x4b, 0x67, 0x87, 0x9b, 0x02, 0x3b, 0xb6, 0xee, 0xac, 0x76, 0xe9, 0x6f, + 0xe6, 0x76, 0xda, 0xeb, 0xbc, 0xb1, 0xbc, 0x94, 0xd5, 0xd8, 0x51, 0xd7, + 0xbc, 0x56, 0xbf, 0xb3, 0xd2, 0xa0, 0xa6, 0xd9, 0x92, 0x31, 0x37, 0x86, + 0xd9, 0xfb, 0x38, 0xad, 0x29, 0xb7, 0x62, 0x34, 0x94, 0x51, 0xd1, 0x49, + 0xd0, 0xe5, 0xfd, 0xe6, 0xad, 0x49, 0x71, 0x83, 0xe3, 0x52, 0x82, 0x8e, + 0x25, 0x1b, 0xcc, 0x7c, 0x3a, 0x91, 0x8b, 0xe4, 0xd0, 0x3b, 0x17, 0xaf, + 0x60, 0xf3, 0xf3, 0xef, 0x6d, 0x9f, 0xb2, 0x45, 0x5d, 0xf7, 0xe8, 0xb6, + 0xb1, 0x69, 0x47, 0x5e, 0x5f, 0x89, 0xdb, 0x99, 0x08, 0x54, 0x1b, 0x56, + 0x7d, 0x0f, 0x29, 0x9b +}; +/* K = 7c62eb8fd725a453fdb2d1e75bbe22f0c5d27a5835135c788061ddfb */ +static const uint8_t ac_dsa_vect125_out[] = { +/* R */ + 0x5b, 0x6b, 0xe6, 0xba, 0xd7, 0x25, 0xaf, 0xa4, 0x42, 0xf2, 0x9a, 0xb7, + 0xd3, 0x43, 0xd2, 0xf8, 0xb4, 0xb4, 0x94, 0x1c, 0xbd, 0x23, 0xd6, 0x91, + 0x64, 0xb3, 0xc5, 0xfd, +/* S */ + 0x3a, 0x1b, 0x94, 0x63, 0x4e, 0x31, 0x3f, 0xc4, 0xdf, 0x82, 0x92, 0xe0, + 0x38, 0xc6, 0xe8, 0x76, 0x33, 0x6c, 0xef, 0x88, 0xd6, 0x91, 0xb8, 0x94, + 0xc0, 0xec, 0xcd, 0x3f +}; +#define ac_dsa_vect126_prime ac_dsa_vect121_prime +#define ac_dsa_vect126_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect126_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect126_ptx[] = { +/* Msg */ + 0x7a, 0x96, 0x87, 0x3f, 0x07, 0x77, 0xe8, 0xad, 0xa9, 0x86, 0x75, 0x32, + 0xae, 0x5f, 0x51, 0x93, 0x8b, 0xae, 0x2d, 0x56, 0xfb, 0x47, 0x1e, 0x0f, + 0xef, 0xa6, 0x93, 0xb7, 0x1a, 0x2a, 0xea, 0x25, 0x71, 0xc0, 0x10, 0x8b, + 0xa5, 0x9e, 0x63, 0x44, 0x01, 0xbb, 0xaf, 0x20, 0xa8, 0x48, 0xad, 0x8c, + 0x30, 0x58, 0x48, 0x42, 0x0c, 0xee, 0x65, 0x4a, 0x30, 0x40, 0x00, 0x7f, + 0x05, 0x5d, 0x4e, 0x97, 0x58, 0x07, 0x89, 0x4b, 0x56, 0x18, 0xb9, 0x39, + 0x23, 0x63, 0xbc, 0x7f, 0x8c, 0x88, 0xd5, 0x26, 0xbc, 0x49, 0x1a, 0xdb, + 0xd8, 0x92, 0xa9, 0x37, 0x51, 0xa2, 0x1d, 0x13, 0x7c, 0xee, 0xde, 0x8a, + 0x04, 0x42, 0x3a, 0x4d, 0x0c, 0xa1, 0x55, 0x7b, 0xcf, 0x33, 0x4e, 0x4f, + 0x85, 0x5b, 0x04, 0x47, 0x45, 0x44, 0x21, 0x29, 0x29, 0xa8, 0x1d, 0xc7, + 0x1f, 0xb3, 0xfc, 0x41, 0xf7, 0x0d, 0x6b, 0x18 +}; +static const uint8_t ac_dsa_vect126_priv_val[] = { +/* X */ + 0x49, 0x4b, 0x68, 0x62, 0x47, 0x28, 0xaa, 0xae, 0x98, 0x98, 0xc3, 0xca, + 0x22, 0xc1, 0xbc, 0xe8, 0x10, 0xa0, 0x52, 0xe2, 0x5c, 0x88, 0x1a, 0x18, + 0x5a, 0xf4, 0x3c, 0xd1 +}; +static const uint8_t ac_dsa_vect126_pub_val[] = { +/* Y */ + 0x05, 0x31, 0x51, 0x81, 0x77, 0x08, 0x7d, 0xff, 0x8d, 0x04, 0xa0, 0x66, + 0x6c, 0x13, 0x01, 0xa9, 0xb3, 0x84, 0x27, 0xc2, 0xea, 0x1b, 0x16, 0x2e, + 0x6f, 0xca, 0x52, 0x01, 0x81, 0xef, 0x22, 0xa2, 0xd2, 0x05, 0xce, 0xff, + 0xff, 0xb1, 0x54, 0x9c, 0x97, 0x07, 0x80, 0x55, 0x60, 0xc6, 0xc4, 0xb3, + 0x19, 0x43, 0xd5, 0x25, 0x56, 0xbf, 0x30, 0x1c, 0x5e, 0x0e, 0x75, 0x92, + 0x4f, 0xbe, 0x6b, 0x5c, 0x36, 0x2f, 0xc9, 0x80, 0x17, 0x53, 0xe6, 0x30, + 0x43, 0x3a, 0x9a, 0x34, 0x8f, 0x53, 0xe6, 0x2c, 0x07, 0x46, 0xb2, 0x6e, + 0x34, 0x8d, 0xfb, 0x85, 0x85, 0x3d, 0x1e, 0xf6, 0xec, 0xa0, 0x2c, 0xf3, + 0xf3, 0x43, 0xe7, 0x7c, 0x17, 0x69, 0xff, 0xc1, 0xc1, 0x09, 0xb8, 0x8e, + 0xce, 0xa1, 0x6a, 0xb6, 0xcf, 0x47, 0x6e, 0x54, 0x31, 0x25, 0x00, 0x98, + 0x36, 0x22, 0xdf, 0x41, 0xe6, 0x95, 0xec, 0x27, 0xa4, 0x1c, 0xa7, 0xa6, + 0x31, 0x21, 0xba, 0x97, 0xbe, 0xe7, 0xb0, 0xe9, 0xd5, 0x47, 0xbf, 0x42, + 0x0f, 0x64, 0x7d, 0x0f, 0x86, 0x71, 0xbf, 0x41, 0x07, 0xa7, 0x12, 0xa7, + 0xdb, 0xc1, 0xaf, 0x3a, 0xa8, 0xd1, 0x5b, 0x98, 0x54, 0x8d, 0x39, 0x09, + 0xf7, 0x2b, 0x9a, 0x27, 0xf8, 0x1c, 0x46, 0xe3, 0xde, 0xfa, 0x95, 0xea, + 0xff, 0x75, 0x90, 0xc6, 0x26, 0xb9, 0xba, 0x10, 0x97, 0x4a, 0xe8, 0xb9, + 0xf5, 0x85, 0x35, 0xd0, 0x9c, 0xa3, 0x0f, 0x9f, 0x52, 0x35, 0x39, 0xcf, + 0x58, 0x4f, 0x9b, 0xc6, 0xc7, 0x41, 0x85, 0xc2, 0xff, 0x12, 0x50, 0x4f, + 0x55, 0x98, 0xff, 0xde, 0x6f, 0x86, 0x02, 0x1a, 0xe5, 0x14, 0x56, 0x2f, + 0xed, 0x38, 0x81, 0x19, 0x7f, 0xca, 0x22, 0xdb, 0x55, 0x90, 0xfc, 0xf9, + 0x52, 0x2e, 0xf7, 0x60, 0xed, 0x0e, 0x36, 0x31, 0xa6, 0xbd, 0x79, 0xf2, + 0x90, 0x00, 0xb4, 0x2b +}; +/* K = 065a3ebed489d78ad676afb5373c7028f843816fa97c30169149897f */ +static const uint8_t ac_dsa_vect126_out[] = { +/* R */ + 0x76, 0xbd, 0x6f, 0xf4, 0xcd, 0xc4, 0xfe, 0x37, 0xf6, 0x70, 0x5e, 0x77, + 0xef, 0xdc, 0xac, 0x6f, 0xbb, 0x9d, 0x54, 0xfc, 0x0b, 0x22, 0x06, 0x43, + 0xc6, 0x62, 0xac, 0xbf, +/* S */ + 0x8a, 0x12, 0x4a, 0x36, 0x40, 0xad, 0x73, 0x28, 0x0f, 0x30, 0x5a, 0xfc, + 0x2b, 0xc3, 0xe5, 0x7f, 0x7a, 0x2e, 0x07, 0x40, 0x81, 0xbe, 0x7b, 0xc9, + 0x0b, 0x5b, 0x1f, 0xaa +}; +#define ac_dsa_vect127_prime ac_dsa_vect121_prime +#define ac_dsa_vect127_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect127_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect127_ptx[] = { +/* Msg */ + 0xd6, 0x96, 0x94, 0xbf, 0x9a, 0x93, 0xac, 0x0c, 0xc3, 0x91, 0x59, 0x73, + 0xd4, 0x0e, 0x35, 0x12, 0x47, 0xc3, 0xbc, 0xac, 0xa9, 0x80, 0x69, 0xcd, + 0x9c, 0x1e, 0x7a, 0x3c, 0x58, 0x50, 0x63, 0x6a, 0x59, 0x2e, 0xa7, 0x5f, + 0xae, 0x7b, 0xfd, 0x38, 0xb1, 0x29, 0x0e, 0x3f, 0x4d, 0x0a, 0xae, 0x8e, + 0xe6, 0x89, 0xce, 0x41, 0x37, 0xea, 0x86, 0x8a, 0xae, 0xbb, 0x17, 0xda, + 0xfb, 0x25, 0x5c, 0x4a, 0x20, 0xe0, 0xfa, 0xc1, 0xf4, 0x66, 0x66, 0x12, + 0xf9, 0x0c, 0x46, 0x32, 0x0a, 0x62, 0x00, 0x2e, 0xde, 0x31, 0x67, 0xa3, + 0x4d, 0xff, 0x74, 0xa3, 0x06, 0xa0, 0x84, 0x24, 0x27, 0xcb, 0x9d, 0x2c, + 0x61, 0x59, 0x9b, 0x05, 0xc6, 0x7b, 0x67, 0x31, 0x44, 0xf6, 0xc0, 0x82, + 0x32, 0xd7, 0x71, 0xf2, 0xe0, 0xaf, 0x38, 0x25, 0x3f, 0x36, 0xe1, 0x22, + 0x87, 0x0e, 0x04, 0xeb, 0xc5, 0x4a, 0x51, 0x2f +}; +static const uint8_t ac_dsa_vect127_priv_val[] = { +/* X */ + 0x04, 0x4b, 0x1b, 0xcb, 0x76, 0xdb, 0x64, 0xab, 0x75, 0x00, 0x74, 0x1f, + 0x43, 0x98, 0x9d, 0x3d, 0x87, 0x89, 0x91, 0x78, 0x89, 0x47, 0xb6, 0x79, + 0xbf, 0x22, 0xc0, 0x88 +}; +static const uint8_t ac_dsa_vect127_pub_val[] = { +/* Y */ + 0x9c, 0x58, 0x8b, 0x76, 0x26, 0x9b, 0x2f, 0x08, 0x7f, 0x7e, 0x7a, 0xf4, + 0xec, 0x4c, 0x0e, 0xf2, 0x63, 0xe9, 0x63, 0x6f, 0x45, 0xe7, 0x3e, 0x60, + 0x45, 0x02, 0xd6, 0x2f, 0xae, 0x90, 0xa2, 0x51, 0x01, 0xbc, 0x2b, 0xad, + 0x2a, 0x00, 0x21, 0x27, 0xd4, 0xb6, 0x0f, 0x5c, 0x4a, 0x13, 0x88, 0x88, + 0x0c, 0xad, 0xe9, 0x46, 0x3a, 0xb5, 0xf7, 0x99, 0x7d, 0x54, 0xa0, 0x2c, + 0x24, 0xe7, 0xd5, 0x1a, 0x4b, 0x8a, 0x7d, 0x91, 0xcd, 0xf6, 0xaf, 0xca, + 0x2b, 0x43, 0x37, 0x68, 0x09, 0x45, 0x33, 0xa0, 0xde, 0x08, 0xde, 0xc1, + 0xf1, 0x9e, 0xcc, 0xb4, 0x6d, 0xf1, 0x80, 0x0f, 0x53, 0xd3, 0xdf, 0xee, + 0xfb, 0xfb, 0x76, 0x9a, 0x80, 0xe1, 0x68, 0x6e, 0x8d, 0x53, 0xc6, 0x0e, + 0x8c, 0x15, 0x11, 0xa6, 0xdd, 0x4f, 0x42, 0xa1, 0x55, 0xbd, 0x85, 0xf7, + 0x57, 0x40, 0xbc, 0xbb, 0x7b, 0x11, 0x27, 0x59, 0x18, 0x22, 0x92, 0x6d, + 0x16, 0x82, 0x98, 0x23, 0x75, 0xea, 0x5e, 0xc2, 0x9f, 0xd1, 0xef, 0x4f, + 0x28, 0x3b, 0x94, 0xe0, 0x24, 0x23, 0xa8, 0x30, 0xb3, 0x5e, 0x97, 0x3c, + 0xaf, 0x12, 0x37, 0x7e, 0xe1, 0x8d, 0x2c, 0x6e, 0xe7, 0x77, 0x11, 0x84, + 0xd7, 0xa9, 0x4e, 0x7a, 0x0c, 0x4a, 0x01, 0x04, 0x4a, 0xfc, 0x4e, 0xfb, + 0x2f, 0xfe, 0xcb, 0x69, 0x5e, 0x23, 0x3a, 0xeb, 0x80, 0xc5, 0x16, 0xc7, + 0x7d, 0x1c, 0x73, 0x0d, 0x30, 0xd1, 0xaa, 0x4f, 0x39, 0xda, 0x51, 0xbc, + 0xc4, 0x8f, 0x44, 0xd0, 0x7a, 0xbf, 0xbe, 0x75, 0xf2, 0x28, 0xab, 0xec, + 0x2e, 0x72, 0x73, 0x59, 0x3c, 0x98, 0xf3, 0x23, 0xa9, 0xb0, 0x03, 0x56, + 0x2a, 0x16, 0x87, 0x52, 0xe8, 0x37, 0xa1, 0x23, 0x2f, 0x46, 0x2a, 0x23, + 0xd3, 0xb1, 0x85, 0xea, 0x8a, 0x05, 0x36, 0x15, 0x70, 0x45, 0x5a, 0xad, + 0xd1, 0x03, 0x70, 0x63 +}; +/* K = 4707e611f7d2dbb66f5ff083bab786a525884b49390213300b088fde */ +static const uint8_t ac_dsa_vect127_out[] = { +/* R */ + 0x10, 0x8a, 0x08, 0x2d, 0x2b, 0xf6, 0x35, 0x8a, 0x73, 0x74, 0x65, 0x62, + 0x43, 0x20, 0xc4, 0xfa, 0x9d, 0x37, 0x19, 0x74, 0x4c, 0x2d, 0xb6, 0x9d, + 0x18, 0x96, 0x3d, 0x75, +/* S */ + 0x42, 0x0f, 0x35, 0x37, 0xfa, 0x68, 0x58, 0x65, 0x7d, 0xb7, 0xa2, 0x1e, + 0x72, 0xe1, 0x1e, 0xc0, 0xec, 0x8c, 0xc8, 0x5a, 0x09, 0xa0, 0xd1, 0xa4, + 0x45, 0x94, 0x49, 0x80 +}; +#define ac_dsa_vect128_prime ac_dsa_vect121_prime +#define ac_dsa_vect128_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect128_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect128_ptx[] = { +/* Msg */ + 0x17, 0x45, 0x5b, 0xfb, 0xb1, 0x28, 0xdf, 0x0f, 0x96, 0x54, 0x4b, 0xbf, + 0x83, 0xca, 0x0f, 0xf3, 0x74, 0xbc, 0x08, 0x6b, 0x2d, 0xe1, 0x8f, 0x74, + 0xf5, 0x90, 0x49, 0xf7, 0x3e, 0xff, 0x3c, 0x8e, 0xf3, 0x2a, 0x48, 0x42, + 0x9a, 0x40, 0x38, 0x25, 0x63, 0x04, 0x63, 0x6f, 0x30, 0x32, 0x19, 0x27, + 0x95, 0xba, 0x28, 0x07, 0x40, 0x7e, 0xf5, 0x2b, 0x8d, 0x59, 0xb4, 0x0b, + 0xfd, 0x51, 0x75, 0x83, 0xf9, 0x98, 0x81, 0x02, 0x79, 0xc0, 0x21, 0x17, + 0x71, 0xd9, 0xe5, 0x4f, 0x2b, 0x84, 0xe8, 0x98, 0xf9, 0x89, 0x2e, 0xf7, + 0x7b, 0xeb, 0xa3, 0x3f, 0xf3, 0x1a, 0x28, 0x68, 0x69, 0x3f, 0x1f, 0x09, + 0x78, 0xb8, 0x98, 0x95, 0xe3, 0x50, 0xd5, 0xde, 0xd2, 0x59, 0xfb, 0x13, + 0x97, 0xe9, 0xc6, 0x98, 0x99, 0x86, 0x45, 0x2a, 0x0d, 0x77, 0xdf, 0x99, + 0x04, 0x8f, 0xff, 0x84, 0xb6, 0xeb, 0x15, 0x0e +}; +static const uint8_t ac_dsa_vect128_priv_val[] = { +/* X */ + 0x2b, 0xca, 0x3c, 0x61, 0x3b, 0xe5, 0x3a, 0x6a, 0xab, 0x12, 0x1d, 0xe9, + 0x1d, 0xb4, 0xfa, 0x06, 0xb4, 0x68, 0xfc, 0x65, 0x50, 0xc8, 0x2e, 0xee, + 0xc4, 0xbc, 0xe9, 0xb1 +}; +static const uint8_t ac_dsa_vect128_pub_val[] = { +/* Y */ + 0x85, 0x0c, 0x0f, 0xca, 0xc0, 0x73, 0xc5, 0x63, 0x18, 0xa9, 0x21, 0x04, + 0x65, 0x4e, 0x6a, 0x8a, 0xe7, 0x67, 0x8f, 0xc4, 0x01, 0x47, 0x28, 0x30, + 0x46, 0x49, 0xbf, 0x10, 0x70, 0x27, 0x77, 0x06, 0xfb, 0xd3, 0x2e, 0xa4, + 0xd4, 0x1f, 0x77, 0xf8, 0x0a, 0x80, 0xc8, 0x8f, 0x27, 0x01, 0xe3, 0x66, + 0x5b, 0xe7, 0x3f, 0x59, 0xf9, 0x14, 0xa9, 0x15, 0xd6, 0x6b, 0x41, 0x1b, + 0xb0, 0x5a, 0xe5, 0xc1, 0x8b, 0x00, 0xbc, 0x21, 0x62, 0x51, 0x39, 0x97, + 0x32, 0xfd, 0xc2, 0xa6, 0x8b, 0xe6, 0xa2, 0x1b, 0x3b, 0x08, 0x87, 0x97, + 0x41, 0x6a, 0xe0, 0x5c, 0xe8, 0x76, 0xb6, 0x80, 0x2e, 0x4f, 0x94, 0x1a, + 0x21, 0xb1, 0xc6, 0x61, 0xe3, 0xf0, 0x6d, 0x50, 0x1e, 0xf2, 0xa1, 0x76, + 0x59, 0xf0, 0x88, 0xd2, 0x19, 0x5d, 0xd1, 0x61, 0xf0, 0x64, 0x04, 0x48, + 0x7a, 0x27, 0xb7, 0x9d, 0xf1, 0xec, 0x57, 0x4a, 0xc3, 0xab, 0xc3, 0x0e, + 0xce, 0x2a, 0x14, 0x28, 0xc5, 0xe0, 0xc1, 0xd4, 0xc4, 0x98, 0x03, 0x39, + 0x8d, 0x07, 0x14, 0xca, 0xcd, 0x98, 0x53, 0x85, 0x4b, 0x08, 0x74, 0x6f, + 0xa4, 0x53, 0x56, 0x15, 0x45, 0xe6, 0xf0, 0xd9, 0x6c, 0xd2, 0xc7, 0xce, + 0x1b, 0x89, 0xbc, 0xac, 0xe1, 0xc6, 0x97, 0xec, 0x4d, 0x61, 0x6b, 0xf1, + 0x4d, 0x18, 0x89, 0xa7, 0x9a, 0x80, 0x6a, 0x36, 0x99, 0xf8, 0x4f, 0x19, + 0xef, 0xe6, 0x90, 0xfa, 0x13, 0xa3, 0xb4, 0x38, 0x3e, 0xbf, 0x77, 0x26, + 0x14, 0x00, 0xfc, 0xbe, 0x30, 0x9c, 0x2e, 0x5e, 0xab, 0x0b, 0x24, 0xb1, + 0x97, 0xcb, 0x85, 0x6a, 0xa2, 0x7d, 0x7d, 0x71, 0xd9, 0x2d, 0x32, 0xaa, + 0xb6, 0x56, 0xfa, 0xec, 0x5f, 0xf7, 0x92, 0xec, 0xe5, 0x38, 0x74, 0xc4, + 0x06, 0x9f, 0x54, 0x0d, 0x94, 0x8f, 0x8b, 0x2e, 0x55, 0x99, 0x08, 0x2e, + 0x21, 0xf0, 0x2d, 0x72 +}; +/* K = 4b528d2b2bdfa4f2fce09dc9806ed5302e41cc52f35962653d7f222c */ +static const uint8_t ac_dsa_vect128_out[] = { +/* R */ + 0x42, 0x3d, 0xe9, 0xe1, 0x12, 0xec, 0x38, 0xe3, 0xa0, 0x34, 0xf5, 0xd9, + 0x67, 0x5c, 0x76, 0xf9, 0xdc, 0x85, 0x36, 0xb3, 0x0d, 0x05, 0x67, 0x8a, + 0x29, 0x63, 0xec, 0x16, +/* S */ + 0x74, 0x05, 0x1e, 0x79, 0x69, 0x9f, 0xa4, 0x4d, 0xe1, 0x8e, 0x36, 0xab, + 0x11, 0x68, 0x73, 0x59, 0x3a, 0x31, 0x0e, 0x4e, 0x09, 0xdc, 0xe1, 0x8b, + 0x83, 0x3f, 0xc2, 0xf5 +}; +#define ac_dsa_vect129_prime ac_dsa_vect121_prime +#define ac_dsa_vect129_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect129_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect129_ptx[] = { +/* Msg */ + 0xde, 0x1f, 0x96, 0x06, 0x26, 0x1f, 0xf8, 0x22, 0x18, 0xc8, 0xc1, 0x45, + 0xaa, 0x4d, 0x58, 0x47, 0x67, 0x3b, 0x45, 0x9e, 0xb5, 0x5f, 0xe7, 0xe6, + 0x45, 0x4c, 0x04, 0x43, 0x26, 0x6b, 0xbf, 0x80, 0x0c, 0x1d, 0x09, 0x05, + 0x1f, 0x5e, 0x31, 0x41, 0xc4, 0x37, 0x0d, 0x1b, 0x99, 0x0c, 0xf5, 0xfe, + 0xa9, 0xd2, 0x68, 0x39, 0x86, 0xc3, 0xbd, 0xd2, 0x82, 0x31, 0x07, 0x82, + 0x9a, 0xce, 0x6e, 0xd7, 0x03, 0x4c, 0xae, 0xb2, 0xf6, 0x57, 0xa0, 0x7b, + 0x25, 0xb7, 0xd6, 0x02, 0x40, 0xa0, 0x20, 0x50, 0x26, 0xc2, 0xe3, 0x01, + 0x81, 0x41, 0xd4, 0x79, 0xc0, 0x77, 0x87, 0xa1, 0x4e, 0x70, 0x26, 0x22, + 0xf8, 0xe6, 0xdf, 0x70, 0x9b, 0x63, 0x6c, 0x6d, 0x3d, 0x0b, 0x5f, 0xd5, + 0x4f, 0x55, 0x16, 0xdb, 0xad, 0x97, 0x03, 0x8e, 0x5c, 0x0e, 0xb3, 0x1f, + 0x54, 0xdb, 0x12, 0x64, 0xd6, 0x00, 0xef, 0xc6 +}; +static const uint8_t ac_dsa_vect129_priv_val[] = { +/* X */ + 0x36, 0x6a, 0x49, 0x17, 0x3a, 0x17, 0x83, 0xb9, 0x95, 0x50, 0xd8, 0x4c, + 0x7f, 0xa0, 0x2b, 0x6c, 0xcc, 0xab, 0x12, 0xee, 0x9a, 0x30, 0x6b, 0xed, + 0x7b, 0xb8, 0x1b, 0xa7 +}; +static const uint8_t ac_dsa_vect129_pub_val[] = { +/* Y */ + 0x4d, 0x6e, 0x89, 0xb0, 0x22, 0xc2, 0x78, 0xf3, 0xbf, 0x89, 0x32, 0xe7, + 0x06, 0xe4, 0x18, 0xec, 0xb2, 0x0c, 0x1b, 0xba, 0xb1, 0x3e, 0xa8, 0xc9, + 0x0b, 0x6b, 0xd8, 0x43, 0x84, 0xf3, 0x8b, 0x31, 0x1e, 0x8f, 0xb2, 0xc4, + 0xc0, 0xa9, 0x4b, 0xa7, 0xd3, 0xaf, 0xca, 0x1b, 0xa9, 0x42, 0x52, 0xa4, + 0xc1, 0xac, 0x11, 0x87, 0x62, 0x2c, 0xd9, 0xc1, 0x6a, 0xa7, 0x3b, 0xb1, + 0xb4, 0xa5, 0xcf, 0x55, 0xb5, 0xaa, 0x34, 0xbd, 0x93, 0x52, 0x6f, 0x18, + 0x7b, 0xee, 0xb1, 0x17, 0x00, 0xe4, 0xaf, 0xb8, 0x8c, 0x81, 0x6e, 0xda, + 0x50, 0xa5, 0x0e, 0x81, 0x86, 0x0c, 0x87, 0xfa, 0x66, 0xa1, 0xb6, 0x3f, + 0x5f, 0xfe, 0xc3, 0xc3, 0xae, 0x39, 0xbd, 0xc0, 0x09, 0xd3, 0x8f, 0xa1, + 0x3d, 0xa8, 0x63, 0xca, 0x5e, 0xc1, 0x34, 0xa7, 0xff, 0xcf, 0x5d, 0xc3, + 0xca, 0x85, 0xcc, 0x34, 0xd6, 0x1c, 0x5d, 0xf8, 0xf9, 0xd9, 0xbd, 0xbe, + 0x6a, 0x54, 0x10, 0x45, 0xb4, 0x5c, 0xb5, 0x12, 0xef, 0x64, 0xd1, 0xad, + 0x3d, 0xb7, 0xb3, 0x7d, 0xba, 0x33, 0xc6, 0xe3, 0xc9, 0x61, 0x80, 0xcf, + 0xb2, 0x6f, 0x48, 0xc6, 0x33, 0x73, 0xa0, 0xf0, 0x00, 0x3a, 0xe6, 0x58, + 0x26, 0x79, 0xda, 0x48, 0x50, 0xad, 0x2a, 0x0b, 0x89, 0x9e, 0x0e, 0x8a, + 0x18, 0x47, 0xdf, 0x07, 0xfe, 0xf3, 0xa4, 0x33, 0x0a, 0x72, 0xf8, 0xa8, + 0x02, 0xc0, 0x6e, 0x8e, 0x95, 0x70, 0x7e, 0x0c, 0x7d, 0xc1, 0x91, 0x5f, + 0x6e, 0x17, 0x31, 0xfe, 0x65, 0x0f, 0x1a, 0xe3, 0x52, 0xe7, 0x82, 0xd2, + 0xdd, 0x77, 0xf5, 0x4e, 0x5d, 0xac, 0x52, 0x53, 0x9a, 0x10, 0xa2, 0x2b, + 0xbc, 0x2e, 0xea, 0x31, 0xef, 0xb9, 0x44, 0x38, 0xa0, 0x30, 0xc4, 0xb2, + 0x45, 0x1b, 0xbf, 0xf6, 0x90, 0x1b, 0x5f, 0xb3, 0x01, 0x6c, 0xd1, 0x62, + 0xaf, 0x6b, 0xf0, 0xfb +}; +/* K = 13894dda6721bf3af8a40603a3d97af240976a8ecb3ead998eee0ff0 */ +static const uint8_t ac_dsa_vect129_out[] = { +/* R */ + 0x5f, 0x38, 0x39, 0xeb, 0x66, 0x3f, 0x02, 0x6f, 0x79, 0x29, 0x12, 0xd1, + 0xcb, 0x0b, 0x44, 0x8f, 0x5e, 0x2e, 0x59, 0x31, 0x39, 0x00, 0x1e, 0x83, + 0x9f, 0x71, 0xc9, 0x42, +/* S */ + 0x6b, 0x07, 0xed, 0xb6, 0xa0, 0x34, 0xd0, 0x84, 0xa6, 0x1b, 0xf3, 0xc0, + 0xa3, 0x6e, 0x7e, 0xe6, 0x91, 0x19, 0x48, 0xad, 0x8f, 0x6e, 0x50, 0xac, + 0x68, 0x44, 0xb1, 0xf3 +}; +#define ac_dsa_vect130_prime ac_dsa_vect121_prime +#define ac_dsa_vect130_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect130_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect130_ptx[] = { +/* Msg */ + 0xc1, 0xed, 0xd8, 0x61, 0x51, 0xaf, 0x66, 0xc6, 0x22, 0x3e, 0x41, 0x3f, + 0x17, 0xe7, 0x34, 0xb2, 0xbc, 0x02, 0x4f, 0xf0, 0x66, 0x57, 0x8c, 0x55, + 0x30, 0x8f, 0x13, 0x88, 0xa9, 0x1a, 0xb8, 0x72, 0x70, 0xcd, 0x25, 0xca, + 0x2e, 0xfb, 0xc2, 0x86, 0x7e, 0xb7, 0x15, 0xeb, 0xed, 0x6d, 0x10, 0x01, + 0x2b, 0x6f, 0x48, 0x08, 0xf2, 0xde, 0x19, 0x86, 0xff, 0x7f, 0x4c, 0x36, + 0x9d, 0xaf, 0x46, 0xc8, 0x0a, 0x61, 0x87, 0x07, 0x88, 0x8a, 0xe3, 0xf8, + 0x6e, 0x38, 0xe7, 0xf2, 0x5d, 0x6c, 0xaa, 0x50, 0x91, 0x04, 0xd4, 0x85, + 0x1c, 0xbe, 0xef, 0xbb, 0x75, 0x69, 0x2a, 0xad, 0x49, 0x9a, 0x33, 0xaa, + 0x35, 0xb1, 0x14, 0x09, 0x30, 0x0e, 0x49, 0x5f, 0xe0, 0x07, 0x52, 0x4b, + 0x4a, 0xf2, 0xc2, 0x0d, 0x33, 0xf1, 0xc8, 0xc0, 0x45, 0x16, 0xb6, 0x97, + 0x3a, 0xc1, 0xe0, 0x7d, 0xf3, 0xf1, 0x60, 0xdd +}; +static const uint8_t ac_dsa_vect130_priv_val[] = { +/* X */ + 0x84, 0x1b, 0xa9, 0x1e, 0x27, 0x3f, 0x1c, 0x57, 0x84, 0x7a, 0xd3, 0x36, + 0xce, 0xa4, 0x7c, 0x64, 0x33, 0x35, 0xe6, 0x8f, 0x61, 0x14, 0x82, 0xa3, + 0x0d, 0x6c, 0x0b, 0xb7 +}; +static const uint8_t ac_dsa_vect130_pub_val[] = { +/* Y */ + 0x90, 0xdb, 0xbe, 0x47, 0x41, 0xa7, 0x6a, 0x5f, 0xf2, 0x22, 0xdd, 0xc8, + 0x33, 0xc0, 0xe2, 0xdd, 0x44, 0x5a, 0xd0, 0x17, 0x26, 0xbb, 0xea, 0x25, + 0xca, 0xc2, 0x47, 0xf9, 0xef, 0x9d, 0xa6, 0x43, 0x93, 0x27, 0x36, 0xdb, + 0x07, 0xcd, 0x9a, 0xef, 0xfe, 0xb4, 0x51, 0x19, 0x35, 0x1e, 0x00, 0x33, + 0x2d, 0x9d, 0xfc, 0x89, 0xf5, 0x90, 0x3a, 0x54, 0x1e, 0x74, 0xe2, 0xe9, + 0x70, 0x9d, 0x0f, 0x85, 0x2a, 0xd6, 0x52, 0x40, 0xd0, 0x61, 0x59, 0xfe, + 0x54, 0x43, 0x6d, 0xd8, 0x20, 0x1f, 0x8c, 0x56, 0x92, 0x6e, 0x8d, 0x23, + 0xc2, 0xec, 0xad, 0xeb, 0x8c, 0xbc, 0x9a, 0xeb, 0xf1, 0x2d, 0x52, 0xbe, + 0x64, 0x89, 0xe0, 0xac, 0xb0, 0xe7, 0x52, 0x6f, 0xba, 0x37, 0x54, 0xb7, + 0xec, 0x16, 0x3d, 0xc7, 0xe2, 0xfa, 0x91, 0x93, 0x31, 0x91, 0x24, 0xf0, + 0xcb, 0xb6, 0x1c, 0x2a, 0xb7, 0xab, 0x1a, 0x28, 0xc1, 0x4e, 0x7d, 0x58, + 0x1d, 0xfb, 0x8d, 0xe2, 0x3f, 0x53, 0x36, 0x4d, 0x20, 0x41, 0x90, 0xa5, + 0x8f, 0xcb, 0x9e, 0xa5, 0xb6, 0xf6, 0x1a, 0x79, 0x79, 0xb8, 0x6b, 0xb7, + 0xa7, 0xa4, 0x26, 0x3a, 0x10, 0x66, 0xf0, 0x51, 0x6e, 0x58, 0x70, 0xde, + 0x42, 0x3a, 0x7e, 0x3b, 0x90, 0x6d, 0x90, 0x31, 0x3d, 0x1f, 0xf9, 0x32, + 0x24, 0x50, 0xf7, 0x2d, 0xdd, 0xa4, 0x73, 0x3a, 0xc7, 0x4f, 0xca, 0x5d, + 0x4a, 0xd2, 0xbe, 0x22, 0xc2, 0x66, 0x7b, 0x92, 0x21, 0x20, 0x69, 0x44, + 0x6b, 0x42, 0xa3, 0x91, 0x23, 0x3d, 0x85, 0x21, 0x6a, 0x88, 0xc2, 0x5b, + 0x76, 0xc9, 0x47, 0xd8, 0xd5, 0x65, 0x91, 0x00, 0x3d, 0xf2, 0x53, 0x2f, + 0xcd, 0x7b, 0x18, 0xf9, 0x23, 0xed, 0x48, 0x2d, 0x46, 0x4f, 0xb7, 0x6f, + 0x2c, 0x85, 0x61, 0x78, 0x40, 0xd3, 0x70, 0xab, 0x99, 0xe3, 0x20, 0xe8, + 0x8c, 0xf9, 0xef, 0x8d +}; +/* K = 5ed84fb90761dc03a5e60f3b396d6cc7f8c16c77f065a6ec0049fa51 */ +static const uint8_t ac_dsa_vect130_out[] = { +/* R */ + 0x83, 0x6d, 0x84, 0xd8, 0x62, 0x71, 0xe1, 0x64, 0x84, 0x66, 0xd1, 0x95, + 0x5c, 0x2b, 0x60, 0xb2, 0xa0, 0x4c, 0xc0, 0x21, 0x40, 0x50, 0x83, 0x62, + 0x63, 0x47, 0xae, 0xf9, +/* S */ + 0x63, 0xc7, 0xee, 0xb5, 0xe0, 0x6e, 0x81, 0xd8, 0x92, 0x33, 0x56, 0xf7, + 0x99, 0x81, 0x0a, 0x26, 0xaf, 0x67, 0xc0, 0xfa, 0xa1, 0x8b, 0x39, 0x22, + 0x58, 0xe4, 0xa9, 0xa0 +}; +#define ac_dsa_vect131_prime ac_dsa_vect121_prime +#define ac_dsa_vect131_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect131_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect131_ptx[] = { +/* Msg */ + 0x2b, 0x5f, 0xb6, 0x13, 0x59, 0x8c, 0x02, 0x91, 0x6b, 0xf6, 0xb4, 0xb0, + 0xfd, 0x7a, 0x6b, 0x54, 0x26, 0xac, 0x5b, 0x56, 0x95, 0x43, 0x92, 0xfb, + 0xa3, 0x2d, 0xe0, 0x0b, 0xdf, 0x4b, 0x70, 0x95, 0x3b, 0xe1, 0x96, 0xad, + 0x51, 0xff, 0x2c, 0x09, 0x7a, 0x81, 0xe6, 0xce, 0x1d, 0x17, 0xcf, 0x83, + 0x7d, 0x24, 0x44, 0x75, 0x2b, 0xe9, 0x2b, 0xd4, 0xa9, 0xd1, 0xa8, 0xb4, + 0x13, 0x27, 0x52, 0x7f, 0xf6, 0xbd, 0xc0, 0xe5, 0xc3, 0xe0, 0xcf, 0x46, + 0xf7, 0xe3, 0x79, 0x66, 0xaa, 0xe1, 0x8a, 0x29, 0xce, 0x19, 0x81, 0xf2, + 0x12, 0xd7, 0x14, 0xdd, 0x6c, 0x0c, 0xbb, 0x41, 0x0d, 0x3a, 0x5f, 0x3d, + 0x00, 0x6b, 0xa9, 0xb5, 0x93, 0xda, 0x15, 0x0c, 0xe4, 0x22, 0xb5, 0xcc, + 0x42, 0x0f, 0x3b, 0x56, 0x1b, 0xfd, 0xf1, 0x1d, 0xcb, 0x99, 0x10, 0x00, + 0x57, 0x09, 0xee, 0xb1, 0x29, 0xe2, 0x06, 0x65 +}; +static const uint8_t ac_dsa_vect131_priv_val[] = { +/* X */ + 0x22, 0x09, 0x47, 0x39, 0x6c, 0x2d, 0xe8, 0x5d, 0x48, 0x0b, 0xae, 0x73, + 0x02, 0x98, 0xdf, 0x67, 0x28, 0x3d, 0x0d, 0x06, 0x94, 0x95, 0x0f, 0x5e, + 0xfa, 0x4e, 0xa5, 0xd6 +}; +static const uint8_t ac_dsa_vect131_pub_val[] = { +/* Y */ + 0x95, 0x94, 0x7f, 0xbc, 0x50, 0xd5, 0xa8, 0x02, 0x99, 0xc9, 0x0d, 0xd2, + 0x7c, 0xf3, 0x91, 0x00, 0x91, 0x42, 0x0d, 0x8a, 0xf8, 0x49, 0x24, 0x0e, + 0xbb, 0x54, 0x1a, 0x21, 0xb4, 0x9e, 0x52, 0x8b, 0x0f, 0x33, 0x17, 0xac, + 0xc1, 0x04, 0x93, 0xd5, 0x0e, 0x6b, 0xce, 0x67, 0x6c, 0x43, 0x3c, 0x31, + 0x14, 0x7f, 0x81, 0x28, 0x67, 0x89, 0xe6, 0xa4, 0x1f, 0x4b, 0x26, 0x03, + 0xba, 0xc0, 0xf6, 0xe5, 0xee, 0x7a, 0xff, 0xdb, 0x44, 0xcc, 0xeb, 0x42, + 0x86, 0x43, 0x58, 0x60, 0x7d, 0x45, 0xf4, 0x65, 0x5a, 0x70, 0x9d, 0x7d, + 0x67, 0xf7, 0x16, 0xd7, 0x36, 0x7b, 0xb5, 0xea, 0xb3, 0x34, 0xf6, 0x1c, + 0xef, 0x37, 0x20, 0xc0, 0x80, 0xca, 0xb1, 0x75, 0x12, 0x32, 0x9e, 0x6d, + 0x99, 0x92, 0x5b, 0x47, 0xe4, 0x96, 0x0c, 0x85, 0x03, 0x1b, 0xfd, 0xdb, + 0x13, 0xf0, 0xc6, 0x1a, 0xf8, 0x0e, 0xa4, 0x6b, 0x7b, 0x87, 0x02, 0xf8, + 0xad, 0x34, 0x8d, 0x57, 0xd4, 0x81, 0xef, 0xe8, 0x21, 0x05, 0x4f, 0xc8, + 0x3b, 0x52, 0x66, 0x78, 0x27, 0x56, 0xa4, 0x2d, 0xd4, 0x31, 0x88, 0x1e, + 0xa6, 0xcf, 0xeb, 0x7f, 0x79, 0x00, 0xd8, 0xf7, 0x47, 0xaa, 0xc9, 0x97, + 0x6b, 0xe8, 0x94, 0x59, 0x52, 0xaf, 0xb8, 0xa2, 0x74, 0xda, 0xd0, 0x34, + 0x28, 0x08, 0x83, 0x10, 0xa2, 0x45, 0x6e, 0xc2, 0x54, 0xd1, 0xcc, 0xfb, + 0x63, 0xee, 0xde, 0xa5, 0xd3, 0x74, 0xed, 0x8c, 0xc6, 0x37, 0xa7, 0xba, + 0xab, 0xf8, 0xf4, 0x22, 0xe1, 0xa1, 0x2d, 0x5f, 0xf3, 0x16, 0xdf, 0xf8, + 0xa0, 0x82, 0x06, 0x89, 0x31, 0x49, 0x0a, 0x47, 0x06, 0x50, 0x3d, 0x19, + 0xf9, 0x35, 0x54, 0xf2, 0x52, 0x43, 0x75, 0x1d, 0xfe, 0x62, 0xcd, 0x87, + 0xcb, 0x85, 0x6f, 0x64, 0x4f, 0xbb, 0x6f, 0xc4, 0x6f, 0xb9, 0xcf, 0x89, + 0xaf, 0x5a, 0xea, 0x1a +}; +/* K = 2697349761cc4ccbdb4550bb9ca73654280ade31f577ef86100ff4cf */ +static const uint8_t ac_dsa_vect131_out[] = { +/* R */ + 0x7b, 0x45, 0x5f, 0xae, 0x10, 0x02, 0xfa, 0x87, 0xf3, 0x6c, 0xf6, 0xf3, + 0x45, 0x71, 0x62, 0x25, 0xd4, 0xaa, 0x14, 0x07, 0x80, 0x2a, 0xf4, 0x08, + 0x2b, 0xfb, 0xb1, 0x4a, +/* S */ + 0x23, 0x5d, 0x8b, 0xe4, 0xce, 0xb0, 0x17, 0x6f, 0x5d, 0x0c, 0x47, 0xc1, + 0x19, 0x9a, 0xfc, 0x7e, 0x30, 0x41, 0xc7, 0xd7, 0x50, 0x8b, 0x9f, 0xed, + 0xdc, 0xaa, 0x0d, 0x74 +}; +#define ac_dsa_vect132_prime ac_dsa_vect121_prime +#define ac_dsa_vect132_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect132_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect132_ptx[] = { +/* Msg */ + 0xbd, 0x7d, 0x69, 0xbc, 0xc2, 0xe4, 0xf8, 0xa4, 0x2e, 0x62, 0x7f, 0xa2, + 0x1c, 0x7f, 0xa9, 0xfd, 0xd3, 0xe5, 0x74, 0xb6, 0xdc, 0x5a, 0xd2, 0x02, + 0x17, 0xe8, 0x0b, 0xcc, 0x99, 0x97, 0xb4, 0xc5, 0xef, 0xb3, 0x1c, 0x7b, + 0x65, 0xdb, 0xe8, 0xa0, 0xa3, 0x94, 0xf0, 0xaf, 0x58, 0x03, 0x87, 0xb9, + 0x91, 0x78, 0x88, 0x15, 0x2d, 0xc4, 0xf6, 0x3c, 0xe5, 0x2d, 0x3e, 0xc4, + 0xb7, 0x23, 0xbf, 0xea, 0x81, 0x14, 0x82, 0x5f, 0x9f, 0x1e, 0x25, 0x9f, + 0x67, 0xb5, 0xd1, 0x3b, 0xca, 0xa6, 0x6c, 0x97, 0xde, 0x72, 0x5f, 0xae, + 0x4a, 0xd2, 0x47, 0xbb, 0x92, 0x24, 0x97, 0xeb, 0xed, 0x0f, 0x09, 0x2b, + 0xba, 0xc1, 0x2f, 0x2c, 0xbd, 0x9b, 0x71, 0xb2, 0x29, 0x08, 0x73, 0x78, + 0xe8, 0xbe, 0x06, 0x26, 0xb8, 0xd5, 0xe8, 0x95, 0x0b, 0x0a, 0x6e, 0x69, + 0xe0, 0x51, 0x29, 0xf0, 0xd3, 0x84, 0x2d, 0x27 +}; +static const uint8_t ac_dsa_vect132_priv_val[] = { +/* X */ + 0x42, 0x77, 0x73, 0x74, 0x11, 0x45, 0x19, 0xbf, 0x32, 0x3b, 0xd0, 0x3b, + 0x6e, 0x0e, 0xc2, 0x38, 0x66, 0x0d, 0xc8, 0x63, 0xb1, 0xa3, 0xb8, 0x5e, + 0x0c, 0xf8, 0xf8, 0xa5 +}; +static const uint8_t ac_dsa_vect132_pub_val[] = { +/* Y */ + 0x6f, 0xa6, 0xde, 0xdc, 0x84, 0xa1, 0x47, 0x9b, 0xe4, 0x39, 0x06, 0xf2, + 0xf6, 0x8d, 0xf0, 0xe9, 0x32, 0x34, 0xca, 0x22, 0x30, 0xc8, 0x32, 0xdb, + 0x07, 0x9d, 0x9c, 0xbd, 0x93, 0x42, 0xb2, 0xdf, 0x13, 0xde, 0x4b, 0xff, + 0x10, 0xbd, 0xd8, 0x31, 0x31, 0x34, 0x53, 0xb3, 0x3b, 0x72, 0x5c, 0xd6, + 0x16, 0xac, 0xf1, 0xfe, 0x2f, 0x79, 0x27, 0xea, 0x32, 0xd4, 0x6f, 0xf1, + 0x0e, 0xf1, 0x15, 0x4e, 0x50, 0x3f, 0x71, 0x16, 0x5a, 0xde, 0xaf, 0xfd, + 0xd5, 0x00, 0xa8, 0x3b, 0xf1, 0x00, 0x1e, 0xd3, 0x6c, 0xa6, 0x5b, 0xb6, + 0x97, 0x4d, 0x03, 0x72, 0xcb, 0x0f, 0x21, 0x18, 0x27, 0x84, 0x66, 0xfe, + 0x12, 0x86, 0xad, 0xff, 0x3c, 0x7e, 0xf7, 0x19, 0xc2, 0xa0, 0x2c, 0xff, + 0x9e, 0xd9, 0x37, 0x4f, 0xbb, 0xe6, 0x05, 0x18, 0x14, 0xd2, 0x68, 0x48, + 0xb7, 0xd9, 0x70, 0xfb, 0xec, 0xfb, 0xbf, 0xfe, 0xdf, 0x40, 0xa0, 0x30, + 0x83, 0xfe, 0x33, 0xd3, 0x06, 0x78, 0x38, 0xac, 0xe2, 0x28, 0x54, 0xa8, + 0xe8, 0x8b, 0xfc, 0xb0, 0x2e, 0xcd, 0x76, 0xc3, 0x78, 0xbb, 0x5c, 0x8b, + 0xab, 0xd2, 0x2d, 0xfb, 0xe0, 0x90, 0x75, 0x3a, 0xbf, 0x9e, 0x97, 0xcb, + 0x6b, 0xa7, 0x08, 0xce, 0x00, 0xff, 0xea, 0x5c, 0x55, 0x0b, 0x09, 0xf2, + 0x49, 0x30, 0x69, 0x8d, 0xf1, 0x15, 0xc0, 0x20, 0xb1, 0x30, 0x1d, 0x57, + 0x1a, 0x47, 0x0e, 0x5a, 0x8a, 0x6c, 0xcf, 0xc7, 0x4a, 0xd1, 0x89, 0x49, + 0xa5, 0x7f, 0x61, 0x4f, 0xcb, 0x0f, 0x7e, 0x8b, 0xf7, 0x53, 0x0a, 0x73, + 0x1b, 0xb6, 0x09, 0x1a, 0x73, 0x01, 0xaf, 0x42, 0x89, 0x9d, 0x9e, 0xe9, + 0xe4, 0x5a, 0xa6, 0x2c, 0xa4, 0x90, 0x3e, 0x66, 0x73, 0x3e, 0x47, 0xd0, + 0x1e, 0x26, 0xb2, 0x99, 0x74, 0x6d, 0xa7, 0x5c, 0x7a, 0x57, 0xdc, 0x00, + 0xbc, 0xeb, 0x4d, 0x6c +}; +/* K = 3ad0d788fbfaf4caef4beec9c1566a8c7a1de26bf75dba82a8243270 */ +static const uint8_t ac_dsa_vect132_out[] = { +/* R */ + 0x16, 0xa2, 0xa4, 0x85, 0x78, 0xa0, 0xb5, 0xb5, 0x75, 0x53, 0xcd, 0x20, + 0x00, 0x5b, 0x7e, 0x84, 0x00, 0xe1, 0x06, 0x1c, 0x4f, 0xef, 0x20, 0xd0, + 0x33, 0xf7, 0x2f, 0x8a, +/* S */ + 0x6c, 0x34, 0xd1, 0x76, 0xe9, 0x5d, 0xd4, 0x92, 0x71, 0xee, 0x48, 0xa3, + 0x80, 0x2e, 0xdf, 0x42, 0x38, 0x40, 0x10, 0x84, 0xbc, 0x39, 0x30, 0x20, + 0x14, 0x05, 0x69, 0x3a +}; +#define ac_dsa_vect133_prime ac_dsa_vect121_prime +#define ac_dsa_vect133_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect133_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect133_ptx[] = { +/* Msg */ + 0x77, 0x66, 0xe1, 0xab, 0x76, 0x38, 0xbc, 0xda, 0x3e, 0x6f, 0xdb, 0xd4, + 0xc8, 0x5b, 0x36, 0x61, 0xac, 0xb2, 0x76, 0x3d, 0x41, 0x13, 0x76, 0xb2, + 0xee, 0xdb, 0x4b, 0x2c, 0x6b, 0xff, 0x5d, 0x8f, 0xa2, 0x0c, 0x0a, 0xe5, + 0xb3, 0xcb, 0xed, 0x20, 0x79, 0x6a, 0x6d, 0x8b, 0x81, 0xa1, 0x09, 0x6d, + 0xc3, 0x6a, 0x39, 0x82, 0x6a, 0x18, 0xff, 0xb8, 0x97, 0xd3, 0x6b, 0xfb, + 0x16, 0x36, 0x3c, 0xca, 0x76, 0x32, 0xec, 0xb7, 0x1d, 0x2f, 0x99, 0x6c, + 0xf7, 0xca, 0xc6, 0x66, 0x69, 0xbf, 0x4c, 0x83, 0x11, 0x4b, 0xd5, 0x3b, + 0xe3, 0xbe, 0x33, 0x05, 0xef, 0xc9, 0x9d, 0x22, 0x76, 0x91, 0x88, 0xf8, + 0x42, 0x89, 0xcb, 0x1d, 0x11, 0x50, 0x1f, 0x04, 0x0b, 0x85, 0xd1, 0x58, + 0x90, 0xd2, 0x9a, 0xf2, 0xc8, 0xea, 0xe6, 0x14, 0xf7, 0x4b, 0xee, 0xee, + 0xb5, 0xfc, 0x91, 0x5a, 0xfa, 0x43, 0x22, 0xc2 +}; +static const uint8_t ac_dsa_vect133_priv_val[] = { +/* X */ + 0x36, 0x4b, 0xdc, 0xe9, 0x3d, 0xf0, 0xea, 0xad, 0x45, 0xee, 0x0e, 0xf5, + 0xc1, 0x88, 0x28, 0xbf, 0xe2, 0xe3, 0x81, 0xdb, 0x60, 0x7e, 0x5b, 0x6a, + 0x77, 0xff, 0xc6, 0xe9 +}; +static const uint8_t ac_dsa_vect133_pub_val[] = { +/* Y */ + 0x4c, 0x2b, 0x55, 0x90, 0x24, 0xf1, 0xb3, 0xff, 0x5c, 0x71, 0x67, 0x27, + 0x0c, 0xd1, 0xf3, 0x3b, 0xbf, 0x0f, 0x40, 0xb9, 0xef, 0xa2, 0x5e, 0x13, + 0x74, 0x41, 0xab, 0x46, 0x98, 0x15, 0x4e, 0x74, 0xda, 0x3c, 0xad, 0x34, + 0x23, 0x6d, 0xa4, 0xbd, 0x1c, 0x57, 0xd7, 0x63, 0x8e, 0x42, 0x77, 0x27, + 0x8b, 0x50, 0x8e, 0x85, 0xe3, 0xa9, 0x8d, 0x30, 0x38, 0x8a, 0xb8, 0x63, + 0x8f, 0x55, 0x3e, 0x2a, 0x70, 0x00, 0x11, 0x92, 0x3e, 0x5d, 0x15, 0x4f, + 0x8c, 0x14, 0x07, 0x45, 0x2d, 0xc4, 0xf8, 0x07, 0x70, 0xc9, 0xc3, 0x1c, + 0x36, 0x8a, 0x21, 0xe4, 0x99, 0xd5, 0xdf, 0xb6, 0xf0, 0x5f, 0xd6, 0x77, + 0x91, 0xe7, 0x61, 0xa4, 0x94, 0x20, 0x07, 0x10, 0xaf, 0x8c, 0x21, 0x88, + 0x89, 0x2c, 0x2d, 0x1c, 0x31, 0x95, 0xbe, 0x4a, 0x0a, 0x1d, 0x67, 0x55, + 0x1a, 0xd4, 0x66, 0xfe, 0xe8, 0x0d, 0x7e, 0xdc, 0x43, 0x53, 0x79, 0xa7, + 0x2c, 0x3b, 0xff, 0xad, 0x27, 0x1d, 0xe3, 0x1a, 0xd2, 0xed, 0x10, 0x7d, + 0x78, 0x4f, 0x40, 0xe2, 0x4c, 0x5a, 0x6e, 0x8d, 0x5a, 0xae, 0x8f, 0x24, + 0x05, 0x96, 0x4f, 0xe3, 0xc2, 0x8c, 0xc3, 0x65, 0x2d, 0xc3, 0xc9, 0x52, + 0x3b, 0x39, 0xd4, 0xb0, 0x83, 0xee, 0x65, 0xe9, 0xa0, 0x7c, 0xe8, 0x97, + 0xa1, 0x7b, 0x02, 0xb3, 0x54, 0x76, 0x6f, 0x1b, 0x19, 0xc2, 0xb1, 0x22, + 0x9a, 0xb4, 0x68, 0xb0, 0x14, 0x8c, 0xa8, 0xfe, 0x89, 0x48, 0x4b, 0x7b, + 0x36, 0x00, 0x24, 0x21, 0x80, 0x86, 0xaf, 0x56, 0x40, 0x37, 0x07, 0xbe, + 0xc6, 0x5c, 0x52, 0x28, 0x1c, 0xb8, 0xaa, 0x53, 0x46, 0xcb, 0x6f, 0x64, + 0x81, 0x43, 0x0e, 0x8e, 0x05, 0x71, 0x46, 0xf3, 0x90, 0x60, 0x7c, 0x57, + 0x2b, 0x5b, 0xd8, 0x42, 0x6b, 0x90, 0xef, 0x3a, 0x82, 0x7c, 0xb0, 0xd5, + 0x8b, 0xd4, 0x38, 0xd1 +}; +/* K = 576f8454ff45df954d123bd1384cbe004413c8f85493ed7d6425bfaa */ +static const uint8_t ac_dsa_vect133_out[] = { +/* R */ + 0x09, 0xc6, 0x18, 0x78, 0xa9, 0x91, 0x71, 0x77, 0x05, 0x8e, 0x9d, 0xff, + 0x27, 0x10, 0x6b, 0xdc, 0xa7, 0xd0, 0x6c, 0x50, 0x0e, 0x09, 0x09, 0x93, + 0x06, 0x66, 0x8c, 0xbf, +/* S */ + 0x7b, 0x8b, 0x6c, 0x4c, 0x56, 0x15, 0x97, 0x6d, 0x7a, 0x73, 0x5a, 0xc3, + 0xe1, 0x84, 0xcd, 0xe9, 0x61, 0x54, 0xff, 0xc8, 0x7b, 0x45, 0x89, 0x24, + 0xd4, 0x60, 0x28, 0x95 +}; +#define ac_dsa_vect134_prime ac_dsa_vect121_prime +#define ac_dsa_vect134_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect134_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect134_ptx[] = { +/* Msg */ + 0x84, 0x09, 0x52, 0x78, 0xf7, 0xf1, 0xd5, 0x78, 0xe7, 0x98, 0x39, 0x9a, + 0xf0, 0xbc, 0x9f, 0x46, 0x95, 0xf9, 0x30, 0x2e, 0xa5, 0x97, 0x24, 0x79, + 0xad, 0xf9, 0x0c, 0x95, 0xfc, 0x25, 0xd5, 0x9e, 0x57, 0x6d, 0x97, 0xb8, + 0x9b, 0x73, 0xde, 0xc6, 0x29, 0xce, 0xf0, 0x5d, 0x61, 0x73, 0xb5, 0x5d, + 0x01, 0x5a, 0x3f, 0xb1, 0xd8, 0x19, 0x1a, 0xe5, 0x40, 0xd5, 0x52, 0x40, + 0x9b, 0x03, 0xa7, 0xa8, 0xdb, 0x51, 0x1b, 0xad, 0x09, 0x51, 0x89, 0x6d, + 0xb9, 0x49, 0xfc, 0xc2, 0x88, 0x70, 0xf9, 0xd1, 0x73, 0x14, 0x73, 0x4c, + 0xa6, 0xa3, 0x47, 0x26, 0x83, 0xd0, 0x2f, 0xdc, 0x8d, 0xef, 0xa7, 0xb9, + 0xd3, 0x76, 0x2a, 0xe9, 0x35, 0x7c, 0xa2, 0xa6, 0xab, 0x62, 0x3b, 0x04, + 0x63, 0x50, 0xfa, 0x21, 0x1d, 0x52, 0x13, 0x78, 0x71, 0x27, 0xd2, 0x71, + 0x1c, 0xbd, 0x91, 0x40, 0x5a, 0xbb, 0xe5, 0x0d +}; +static const uint8_t ac_dsa_vect134_priv_val[] = { +/* X */ + 0x16, 0x1f, 0xff, 0x26, 0xa7, 0xb9, 0xd7, 0xdd, 0xc1, 0x52, 0x37, 0xed, + 0xba, 0xb3, 0xc1, 0xf9, 0x9b, 0x72, 0x94, 0xc7, 0x0f, 0xeb, 0x96, 0xf9, + 0x62, 0xdf, 0x89, 0x73 +}; +static const uint8_t ac_dsa_vect134_pub_val[] = { +/* Y */ + 0x4b, 0x52, 0xc5, 0x6f, 0xc6, 0x49, 0x22, 0xac, 0x04, 0xee, 0x7a, 0x80, + 0xfc, 0x5c, 0x22, 0x40, 0x13, 0xe2, 0xff, 0xda, 0xa1, 0x67, 0x38, 0x12, + 0x57, 0xe0, 0x0c, 0x59, 0x7b, 0x43, 0x36, 0x41, 0xce, 0xad, 0xbc, 0x9b, + 0x16, 0x56, 0x8b, 0xbc, 0x9c, 0x6d, 0x31, 0xd0, 0x2c, 0x8e, 0x36, 0xdb, + 0x2e, 0x39, 0x87, 0x52, 0x0c, 0xe8, 0x59, 0x08, 0x56, 0xbd, 0x4a, 0x84, + 0x1b, 0x72, 0x5e, 0xc9, 0x5a, 0x46, 0x59, 0xa6, 0x1a, 0x00, 0x86, 0xf6, + 0x6a, 0x6b, 0xfd, 0xbf, 0x1e, 0x4b, 0xf9, 0x2b, 0x44, 0x19, 0x28, 0xcf, + 0x31, 0x9f, 0x92, 0x9a, 0x64, 0x28, 0xf5, 0xe3, 0xba, 0x7c, 0x89, 0x12, + 0x3d, 0xbb, 0x0c, 0xac, 0xc1, 0x6b, 0xb0, 0xe2, 0xb8, 0x08, 0x54, 0xb0, + 0xf6, 0x0d, 0xfa, 0xa9, 0x9f, 0x9c, 0x4c, 0xaa, 0x41, 0x2c, 0x44, 0x3a, + 0x07, 0x3b, 0x7a, 0x51, 0x25, 0x91, 0x25, 0xf0, 0x12, 0xd9, 0x8f, 0x0f, + 0x66, 0x99, 0xd7, 0x0a, 0xde, 0x66, 0xdf, 0x9c, 0x5e, 0x18, 0x18, 0x56, + 0x72, 0xe0, 0xe2, 0x83, 0x0e, 0x05, 0x85, 0x41, 0x3d, 0xa2, 0x95, 0x6c, + 0x89, 0xd2, 0x32, 0x0f, 0xaa, 0xc0, 0x3a, 0xaa, 0x83, 0xfe, 0x71, 0x8a, + 0x0d, 0x6c, 0xf7, 0xfe, 0xb3, 0x8a, 0x19, 0x4e, 0x43, 0x62, 0xd7, 0xc8, + 0x9e, 0x4a, 0x13, 0x96, 0x7e, 0x3a, 0x2d, 0x44, 0x93, 0xf4, 0xec, 0x09, + 0xac, 0x2f, 0xc8, 0x9d, 0x56, 0xa5, 0x95, 0x47, 0x2e, 0x60, 0x33, 0x24, + 0x48, 0x54, 0x8d, 0x91, 0xcd, 0x6a, 0xac, 0x84, 0xa2, 0xf9, 0xb4, 0xd7, + 0xa8, 0x04, 0x62, 0xdc, 0x15, 0x47, 0x79, 0xbe, 0x5f, 0x9e, 0x1f, 0x70, + 0x9b, 0x9d, 0x9a, 0x15, 0x62, 0x73, 0x03, 0x3f, 0xe6, 0xe4, 0x84, 0x2e, + 0xc4, 0x75, 0x21, 0x96, 0x4d, 0x2e, 0x2f, 0xe2, 0x62, 0x28, 0x0f, 0xdd, + 0xec, 0x64, 0x03, 0xe8 +}; +/* K = 7cbe0c1c29b955fa1fdafcab79c02177c15ec5789a4dd53a6ad29ce8 */ +static const uint8_t ac_dsa_vect134_out[] = { +/* R */ + 0x0c, 0x4d, 0x45, 0x27, 0x81, 0x5a, 0x94, 0xbc, 0x2d, 0x77, 0x06, 0x3e, + 0xa6, 0x90, 0x49, 0xbe, 0x6a, 0x2b, 0x3b, 0x3a, 0x3a, 0x0b, 0xad, 0xd5, + 0xe6, 0x2a, 0x8f, 0x9a, +/* S */ + 0x57, 0x87, 0xce, 0xd7, 0x08, 0x1f, 0xad, 0x3f, 0xe1, 0x9a, 0xb5, 0xb9, + 0x02, 0x8e, 0x9e, 0x8d, 0xf1, 0x86, 0x39, 0xe4, 0x99, 0x1a, 0xb6, 0xe1, + 0xe2, 0x43, 0x41, 0x6e +}; +#define ac_dsa_vect135_prime ac_dsa_vect121_prime +#define ac_dsa_vect135_sub_prime ac_dsa_vect121_sub_prime +#define ac_dsa_vect135_base ac_dsa_vect121_base +static const uint8_t ac_dsa_vect135_ptx[] = { +/* Msg */ + 0x30, 0xee, 0xdc, 0x9d, 0x63, 0x0b, 0x63, 0x20, 0x82, 0xc1, 0x96, 0xb9, + 0x69, 0xd2, 0x4f, 0x6e, 0xb9, 0xcf, 0x1b, 0x1e, 0x2c, 0x53, 0xd2, 0x44, + 0xe8, 0xd8, 0xb5, 0x0a, 0x40, 0x98, 0x2a, 0xb5, 0x3c, 0x4d, 0x57, 0xff, + 0x99, 0x5f, 0xa8, 0x45, 0x89, 0x08, 0xa7, 0x43, 0x89, 0x03, 0x82, 0xda, + 0x65, 0x13, 0xcf, 0xe9, 0xc1, 0x99, 0x18, 0x24, 0x87, 0x36, 0x15, 0xa8, + 0xa1, 0x63, 0x74, 0xa5, 0xe5, 0xdc, 0x2f, 0xab, 0x3f, 0x5c, 0xd2, 0x56, + 0x52, 0xec, 0x8a, 0xa3, 0x93, 0x9f, 0x48, 0x84, 0xf7, 0x4a, 0xc7, 0x37, + 0x98, 0x9b, 0x6a, 0xc2, 0xe4, 0x3f, 0x45, 0xb8, 0x85, 0x20, 0x6a, 0x31, + 0xe7, 0x97, 0xfd, 0x85, 0x76, 0x35, 0x7e, 0x4b, 0x4b, 0xaa, 0x56, 0x62, + 0x91, 0x81, 0x5d, 0xac, 0x2f, 0x54, 0x6f, 0x4a, 0xbf, 0x8b, 0xa1, 0xde, + 0x11, 0x20, 0xfd, 0x80, 0x42, 0x84, 0xe9, 0x59 +}; +static const uint8_t ac_dsa_vect135_priv_val[] = { +/* X */ + 0x02, 0x09, 0xc0, 0x0e, 0xda, 0xd1, 0x05, 0x94, 0xf7, 0xcd, 0x78, 0x78, + 0x47, 0x21, 0x69, 0xd5, 0x12, 0xa7, 0xe8, 0xdc, 0x3f, 0xc1, 0xcd, 0x69, + 0x28, 0x5e, 0x69, 0xd5 +}; +static const uint8_t ac_dsa_vect135_pub_val[] = { +/* Y */ + 0x89, 0x20, 0xf6, 0xab, 0x95, 0xb1, 0xdc, 0x6b, 0x93, 0xe0, 0x8e, 0xad, + 0x6b, 0x08, 0x14, 0x1c, 0xc2, 0xa8, 0xf1, 0xff, 0xbb, 0x71, 0xd5, 0xec, + 0x59, 0x64, 0xf6, 0xb2, 0xc3, 0xd7, 0x2f, 0xf3, 0xad, 0xad, 0xe5, 0x22, + 0x54, 0x37, 0x0f, 0x13, 0x09, 0x90, 0xb4, 0x34, 0x87, 0x77, 0x5c, 0x2f, + 0xe0, 0x17, 0xa8, 0x20, 0x0d, 0x81, 0x19, 0x81, 0x8a, 0x15, 0xed, 0x7e, + 0x56, 0x36, 0xbf, 0xbf, 0x31, 0x64, 0x04, 0x2f, 0x27, 0xbb, 0x1e, 0xa4, + 0x18, 0x69, 0x8b, 0x67, 0x56, 0xf7, 0x5a, 0x8f, 0xda, 0xeb, 0xf0, 0xf6, + 0xe5, 0x42, 0x3e, 0x46, 0x02, 0x87, 0xf4, 0xfd, 0xd2, 0xa0, 0xef, 0x30, + 0x5e, 0x65, 0x87, 0x41, 0x37, 0x3d, 0x3b, 0xae, 0xcc, 0xe7, 0x90, 0x63, + 0x96, 0x2f, 0x88, 0x33, 0x98, 0xc3, 0x14, 0xe3, 0x62, 0x30, 0xba, 0x8c, + 0x57, 0x0e, 0x66, 0x7c, 0x30, 0xca, 0xc8, 0xfb, 0xaa, 0x4e, 0x70, 0x20, + 0x2a, 0x91, 0x57, 0xd2, 0x27, 0x08, 0xca, 0x60, 0x54, 0x03, 0x06, 0x6d, + 0x0f, 0xc8, 0x48, 0x45, 0xbc, 0xe9, 0xb8, 0xc3, 0xb4, 0x1e, 0xc3, 0x2f, + 0x40, 0xc8, 0x45, 0xa5, 0x32, 0xfd, 0xff, 0x4d, 0xd1, 0x0c, 0xf6, 0x2a, + 0x71, 0x41, 0x21, 0xea, 0x8a, 0x61, 0x88, 0x50, 0x06, 0x45, 0xaf, 0xa9, + 0x31, 0x6f, 0xb3, 0xe1, 0x16, 0x28, 0xb1, 0x63, 0xd3, 0x5d, 0x8c, 0xfc, + 0xc5, 0x52, 0x72, 0xb6, 0x50, 0xe8, 0x07, 0x2c, 0x23, 0x76, 0x45, 0x60, + 0x01, 0x50, 0xbb, 0xb6, 0x6d, 0x39, 0x3c, 0x1c, 0x97, 0x34, 0x5d, 0x58, + 0x20, 0xf1, 0x78, 0xdd, 0x40, 0x5b, 0x5d, 0x46, 0xfc, 0x4a, 0xc8, 0xa5, + 0xf3, 0x92, 0x9e, 0x6b, 0x16, 0x27, 0x94, 0x40, 0x93, 0x17, 0x8a, 0x8d, + 0x65, 0x10, 0x10, 0x59, 0xfb, 0xbb, 0xb7, 0x08, 0x11, 0x74, 0xf2, 0x30, + 0x8b, 0x26, 0x53, 0xce +}; +/* K = 36454e085b6b3dcc7c755b65ff46697b099485abd6ceb00cbf5dceed */ +static const uint8_t ac_dsa_vect135_out[] = { +/* R */ + 0x45, 0x21, 0x2d, 0x1c, 0x8c, 0x12, 0x80, 0x02, 0xfc, 0xb3, 0xce, 0x35, + 0x58, 0x3f, 0xf8, 0xd0, 0x83, 0x63, 0x71, 0x1c, 0x15, 0x98, 0x30, 0x7d, + 0x9e, 0xc6, 0xa1, 0x08, +/* S */ + 0x48, 0x58, 0x10, 0x56, 0x49, 0xdb, 0x59, 0x92, 0x76, 0x4d, 0xd3, 0x2b, + 0x10, 0x2d, 0x9b, 0x9d, 0x2b, 0xc6, 0xaf, 0x64, 0xc6, 0xa8, 0x15, 0x95, + 0x61, 0x1e, 0x3e, 0x20 +}; +/* [mod = L=2048, N=224, SHA-512] */ +static const uint8_t ac_dsa_vect136_prime[] = { +/* P */ + 0xbf, 0xeb, 0xd0, 0x00, 0xb2, 0xd6, 0xcd, 0x4a, 0xb3, 0x8e, 0xfb, 0xa3, + 0x5d, 0xf3, 0x34, 0xdf, 0x72, 0x1d, 0x6c, 0x2f, 0x2b, 0x3d, 0x95, 0x66, + 0x79, 0xcb, 0xad, 0x00, 0x9f, 0x3d, 0xfb, 0xd0, 0x02, 0x95, 0x2c, 0xc8, + 0x99, 0xcc, 0x23, 0x56, 0xec, 0x87, 0x69, 0xbd, 0x3d, 0x1b, 0xa5, 0xa7, + 0x30, 0x23, 0x72, 0x98, 0x88, 0xda, 0x92, 0xca, 0x48, 0xa5, 0xee, 0x94, + 0xc9, 0x7f, 0x4f, 0x04, 0xa2, 0xe3, 0xac, 0xb4, 0xf3, 0x3a, 0x2f, 0x0f, + 0xb3, 0x78, 0x3c, 0x31, 0xf2, 0xc7, 0x0f, 0xa7, 0xc7, 0x0f, 0x38, 0x21, + 0x4a, 0x27, 0xda, 0xde, 0xc8, 0xb1, 0x2e, 0x67, 0x99, 0x6a, 0x9e, 0x85, + 0xee, 0x3b, 0xb1, 0x48, 0x80, 0x31, 0x30, 0x14, 0x73, 0x92, 0xdc, 0x52, + 0x53, 0xc0, 0x4d, 0x70, 0x63, 0x53, 0x5e, 0x6c, 0xd6, 0x46, 0xbf, 0xb1, + 0x86, 0x98, 0x4e, 0x08, 0xb5, 0x8b, 0x74, 0xa7, 0xbe, 0x5b, 0x33, 0x3b, + 0xf3, 0x2b, 0x0a, 0xbf, 0xd5, 0x66, 0x53, 0x60, 0xe9, 0xa9, 0x23, 0xa0, + 0xc5, 0x28, 0xff, 0x1c, 0x62, 0xc7, 0x25, 0x34, 0x58, 0xf5, 0x67, 0x85, + 0x28, 0x71, 0x9d, 0x43, 0x6e, 0x50, 0x14, 0x87, 0x41, 0xf4, 0x5d, 0xc7, + 0xdd, 0x2c, 0x6c, 0xac, 0x71, 0xc5, 0x52, 0x31, 0xf1, 0x2a, 0x83, 0xfe, + 0xfd, 0x2e, 0xd0, 0xa3, 0x3e, 0xde, 0x1b, 0x8a, 0x51, 0xf5, 0x66, 0xfc, + 0xf7, 0x89, 0x06, 0x82, 0xcd, 0xc1, 0x93, 0x1d, 0xc2, 0x07, 0xc9, 0x2b, + 0xf2, 0xef, 0x4e, 0x28, 0xab, 0x31, 0x66, 0x1e, 0xeb, 0x77, 0xf1, 0x60, + 0x1e, 0xea, 0x94, 0x1c, 0x95, 0x91, 0xf0, 0x38, 0xd3, 0xf0, 0x0d, 0x91, + 0x28, 0x57, 0xdb, 0x05, 0xe6, 0x4b, 0x2a, 0xd5, 0x69, 0x32, 0x00, 0x61, + 0xc6, 0xf8, 0x63, 0xff, 0x33, 0x54, 0xd8, 0x42, 0xe7, 0xe7, 0xea, 0x71, + 0x5a, 0xfe, 0xf8, 0xd1 +}; +static const uint8_t ac_dsa_vect136_sub_prime[] = { +/* Q */ + 0xaa, 0x98, 0x6d, 0xf8, 0xa0, 0x64, 0x27, 0x8e, 0x93, 0x63, 0x31, 0x6a, + 0x98, 0x30, 0xbc, 0xfa, 0x49, 0x06, 0x56, 0xfa, 0xa6, 0xd5, 0xda, 0xa8, + 0x17, 0xd8, 0x79, 0x49 +}; +static const uint8_t ac_dsa_vect136_base[] = { +/* G */ + 0x81, 0x95, 0xad, 0x9a, 0x47, 0x8f, 0xd9, 0x85, 0x21, 0x6e, 0xe5, 0x83, + 0x68, 0x36, 0x6d, 0x2e, 0xdd, 0x13, 0xc1, 0x2b, 0x3d, 0x62, 0x23, 0x91, + 0x69, 0xfa, 0x04, 0x2d, 0x91, 0x15, 0x64, 0x08, 0xb4, 0x83, 0x12, 0x2f, + 0x44, 0xed, 0x62, 0x36, 0xb8, 0x30, 0x8a, 0x6c, 0xdb, 0x52, 0xf9, 0xaf, + 0x3d, 0xe8, 0x8e, 0xc8, 0x9e, 0x03, 0x9a, 0xfa, 0xd7, 0xda, 0x3a, 0xa6, + 0x6c, 0x19, 0x76, 0x04, 0x9a, 0x8e, 0x0a, 0x7d, 0x18, 0xd5, 0x67, 0xba, + 0xf9, 0x9f, 0xce, 0xfe, 0x31, 0x5c, 0xad, 0xa0, 0x15, 0x48, 0x38, 0x6b, + 0x10, 0xb2, 0x5e, 0x52, 0xf5, 0x2e, 0xd7, 0x8e, 0xb4, 0xd2, 0x80, 0x82, + 0xe5, 0xe1, 0xff, 0xee, 0x94, 0x80, 0xc4, 0xfe, 0x2c, 0xc4, 0xaa, 0xfd, + 0x1e, 0xfc, 0x9d, 0x4f, 0xd2, 0xcc, 0x6d, 0x15, 0x59, 0x68, 0x93, 0x12, + 0x71, 0xef, 0x15, 0xb3, 0x24, 0x0e, 0x7f, 0xb0, 0x43, 0xa8, 0x0c, 0x8f, + 0x62, 0x8b, 0xef, 0xe0, 0x9d, 0x64, 0x50, 0x77, 0xc1, 0x02, 0x9d, 0x21, + 0xe0, 0xac, 0x8b, 0xf0, 0xba, 0x9c, 0x27, 0x71, 0x4d, 0x1b, 0x58, 0x0e, + 0xde, 0x59, 0x4a, 0xa0, 0x1b, 0x3b, 0x76, 0xf6, 0xe7, 0x45, 0xfc, 0x1e, + 0xc0, 0x7d, 0xb3, 0x7e, 0x2f, 0xd7, 0xe9, 0x8c, 0x6c, 0x8c, 0x69, 0x15, + 0x22, 0x8e, 0x42, 0x2c, 0x30, 0x9d, 0xe9, 0xf5, 0xdb, 0x16, 0x8f, 0x50, + 0x24, 0x9d, 0x1b, 0xe1, 0xed, 0x32, 0x98, 0x09, 0x08, 0x08, 0xe2, 0xeb, + 0xb8, 0x96, 0xbb, 0x79, 0xb8, 0xc4, 0xcb, 0xf9, 0x4d, 0x4c, 0x20, 0x64, + 0xe3, 0x7e, 0x61, 0x2b, 0xa4, 0x44, 0x9d, 0x7a, 0xc2, 0x10, 0xed, 0xde, + 0x21, 0x14, 0x16, 0xd6, 0x4b, 0x05, 0x1d, 0xd8, 0x04, 0x6a, 0xb0, 0x41, + 0x73, 0x26, 0x65, 0x41, 0x1a, 0x7f, 0x15, 0x4d, 0x31, 0xb3, 0xe1, 0x1a, + 0x51, 0xda, 0x7f, 0xc0 +}; +static const uint8_t ac_dsa_vect136_ptx[] = { +/* Msg */ + 0xe9, 0xf5, 0x9c, 0x6a, 0x5c, 0xbe, 0x8f, 0x5b, 0x0c, 0xf7, 0x50, 0x08, + 0xd0, 0x6a, 0x07, 0x6a, 0x67, 0x39, 0xbd, 0xdd, 0xb3, 0x9b, 0x82, 0x14, + 0x3c, 0xd0, 0x39, 0x39, 0xaa, 0x47, 0x38, 0xa2, 0x87, 0xc2, 0xa6, 0xf3, + 0x18, 0x29, 0xbb, 0xe1, 0x5f, 0x02, 0xcc, 0x2e, 0xe7, 0xd7, 0x12, 0x2d, + 0xbd, 0x13, 0x28, 0x25, 0x97, 0x0d, 0xad, 0xdd, 0x8a, 0x4d, 0x85, 0x1d, + 0xa8, 0x6e, 0x7e, 0xdc, 0x89, 0x40, 0xcb, 0x11, 0x88, 0x31, 0x92, 0x18, + 0xb8, 0xe0, 0x24, 0x8a, 0x10, 0x3e, 0xae, 0x34, 0xbc, 0x68, 0xd8, 0x5f, + 0x5a, 0x32, 0x83, 0x0d, 0x7e, 0x5d, 0xc7, 0x71, 0x8f, 0x74, 0xdb, 0x5e, + 0x42, 0x24, 0xc0, 0xde, 0xbe, 0x1e, 0x84, 0x1e, 0x1e, 0xea, 0x1a, 0x88, + 0xfe, 0xe0, 0xf8, 0x5d, 0x9f, 0xb0, 0x87, 0xcb, 0xce, 0xe5, 0x5f, 0x86, + 0x03, 0x7a, 0x64, 0x6e, 0x38, 0x34, 0x6d, 0x2b +}; +static const uint8_t ac_dsa_vect136_priv_val[] = { +/* X */ + 0x6a, 0x5b, 0x4f, 0xfc, 0x44, 0x23, 0x8d, 0x18, 0x52, 0xfb, 0x9b, 0x74, + 0xe4, 0xc1, 0x66, 0x1b, 0xe8, 0x59, 0x84, 0x04, 0x3c, 0xfe, 0xee, 0x02, + 0x3f, 0x57, 0xca, 0xc6 +}; +static const uint8_t ac_dsa_vect136_pub_val[] = { +/* Y */ + 0xaf, 0x67, 0x21, 0xbf, 0x75, 0xde, 0xc6, 0xa1, 0xb7, 0x6a, 0xd3, 0x5c, + 0xa3, 0x75, 0x0d, 0xef, 0x31, 0x11, 0x7c, 0x5b, 0x44, 0x1c, 0x15, 0xa3, + 0x06, 0x83, 0x5a, 0x1d, 0xb7, 0x4c, 0x00, 0x3b, 0x86, 0xae, 0x90, 0x99, + 0xeb, 0xfb, 0x74, 0x5b, 0x0a, 0xa9, 0xcb, 0x00, 0x0c, 0xf4, 0x3f, 0xb0, + 0x21, 0x51, 0x3b, 0x8f, 0x19, 0x7b, 0xc8, 0x65, 0xb2, 0x2b, 0xf9, 0x49, + 0xb4, 0x91, 0x80, 0x9a, 0xd7, 0x52, 0xff, 0xc1, 0xca, 0x8e, 0x54, 0xbe, + 0xa1, 0x6d, 0xc7, 0xf5, 0x39, 0xe4, 0xc5, 0x5f, 0xb7, 0x0a, 0x77, 0x43, + 0xdd, 0x28, 0xf2, 0x62, 0xf6, 0x0e, 0xf0, 0xf2, 0xfc, 0xaa, 0xc2, 0x9e, + 0x80, 0x21, 0xa7, 0x93, 0x8c, 0x18, 0xff, 0xe0, 0x30, 0x75, 0xd0, 0xb7, + 0xe0, 0xa2, 0xb4, 0xdc, 0xab, 0xe4, 0x6e, 0xd1, 0x95, 0x3d, 0x33, 0xe3, + 0x7f, 0x11, 0x3a, 0xf5, 0x19, 0xab, 0x0b, 0xf0, 0xb6, 0x18, 0x6c, 0x12, + 0xb5, 0xf6, 0x48, 0x84, 0x37, 0xf5, 0x19, 0x30, 0x96, 0xe2, 0xfd, 0x6a, + 0x6a, 0x18, 0x35, 0x60, 0x47, 0x94, 0xc6, 0x6b, 0x42, 0xae, 0x52, 0x65, + 0xc1, 0xcf, 0x1c, 0xb5, 0x3a, 0xe8, 0x49, 0x97, 0x97, 0x5e, 0x03, 0x18, + 0xa9, 0x3c, 0xe4, 0x1e, 0x39, 0x02, 0xe4, 0xef, 0x54, 0xde, 0x3c, 0x56, + 0x55, 0x5b, 0xd1, 0x94, 0x91, 0xac, 0xd5, 0x3f, 0x3e, 0x57, 0x46, 0x4e, + 0x1f, 0x46, 0x03, 0x89, 0xdb, 0xc5, 0xfa, 0x80, 0x64, 0x8f, 0xa5, 0xa5, + 0xa0, 0xf2, 0x95, 0x6e, 0x9e, 0xc3, 0xb8, 0xdc, 0x44, 0x1b, 0x53, 0x5c, + 0x64, 0x1c, 0x36, 0x2e, 0xed, 0x77, 0x0d, 0xa8, 0x28, 0x64, 0x9b, 0xfd, + 0x14, 0x64, 0x72, 0xb0, 0xf4, 0x6a, 0x4c, 0x06, 0x4e, 0x45, 0x9f, 0x88, + 0xbf, 0xf9, 0x0d, 0xed, 0xe7, 0xec, 0x56, 0x17, 0x7a, 0x9a, 0x71, 0xd1, + 0x67, 0x94, 0x87, 0x12 +}; +/* K = 9ced89ea5050982222830efef26e7394f5ab7d837d4549962d285fae */ +static const uint8_t ac_dsa_vect136_out[] = { +/* R */ + 0x9d, 0xa9, 0x96, 0x65, 0x00, 0xde, 0x9d, 0x3b, 0x6b, 0x7f, 0x44, 0x1c, + 0xa5, 0x50, 0x23, 0x3f, 0xc4, 0x50, 0x94, 0x4b, 0xc5, 0x07, 0xe0, 0x1c, + 0xd4, 0xac, 0xb0, 0x30, +/* S */ + 0x2d, 0x72, 0xf1, 0xf6, 0x68, 0x1e, 0x86, 0x7f, 0x7d, 0x8b, 0xea, 0xeb, + 0xeb, 0xa4, 0xbc, 0x5b, 0x23, 0x28, 0x76, 0x04, 0xa6, 0x4c, 0xfe, 0xe1, + 0xc1, 0x64, 0x59, 0x5a +}; +#define ac_dsa_vect137_prime ac_dsa_vect136_prime +#define ac_dsa_vect137_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect137_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect137_ptx[] = { +/* Msg */ + 0x97, 0x1d, 0x16, 0xd1, 0x11, 0xc9, 0x6d, 0xe0, 0xf7, 0x09, 0x8b, 0x25, + 0x6a, 0xf2, 0x13, 0xf4, 0x47, 0x5a, 0xef, 0x31, 0x00, 0x7e, 0x12, 0xe2, + 0x97, 0x4c, 0x5f, 0x64, 0xb2, 0xf3, 0x35, 0xe0, 0x18, 0x3c, 0x19, 0x6c, + 0x33, 0xd5, 0x0f, 0x64, 0x45, 0xc5, 0xf6, 0x14, 0x64, 0x95, 0x49, 0x77, + 0x0b, 0x18, 0x74, 0xdd, 0x07, 0x56, 0xa9, 0xa8, 0xe3, 0x99, 0x71, 0xdf, + 0xec, 0xc3, 0xf2, 0x67, 0xeb, 0xcc, 0x1f, 0x53, 0x01, 0x70, 0x3f, 0x88, + 0x74, 0x3b, 0x0f, 0x37, 0x64, 0x82, 0xcf, 0xc0, 0x6d, 0x59, 0x48, 0xbd, + 0x79, 0x26, 0xd9, 0x6e, 0xc4, 0xd7, 0x31, 0xa4, 0x4b, 0x0c, 0x0e, 0xee, + 0x5e, 0x85, 0xda, 0x26, 0x68, 0x72, 0x65, 0xde, 0x5a, 0x66, 0xcb, 0x1a, + 0x73, 0xa7, 0xe4, 0xf3, 0x23, 0x6f, 0x60, 0x64, 0x7b, 0xee, 0x5c, 0x16, + 0x33, 0x40, 0xe1, 0x95, 0x05, 0x57, 0x7c, 0xf6 +}; +static const uint8_t ac_dsa_vect137_priv_val[] = { +/* X */ + 0x90, 0x53, 0xec, 0x8a, 0xb1, 0xf9, 0x70, 0x0c, 0x2a, 0xb5, 0x92, 0x59, + 0xbf, 0x2e, 0x07, 0x89, 0x29, 0x04, 0xf0, 0x3c, 0x84, 0x4c, 0xd5, 0x8a, + 0x7f, 0xf5, 0x9c, 0x79 +}; +static const uint8_t ac_dsa_vect137_pub_val[] = { +/* Y */ + 0x29, 0x05, 0x17, 0x29, 0x7e, 0x42, 0x49, 0xfc, 0x32, 0x12, 0xba, 0xd6, + 0x72, 0x69, 0xe0, 0x32, 0x81, 0x8d, 0x76, 0x0b, 0x0e, 0xe0, 0x52, 0x5d, + 0xc5, 0xa1, 0x7c, 0x97, 0x11, 0x6e, 0xe2, 0x9e, 0xb3, 0xb4, 0x50, 0xb4, + 0x1d, 0x15, 0xce, 0xa4, 0x05, 0xd5, 0xe9, 0x83, 0xa8, 0x55, 0x81, 0x84, + 0x06, 0x7f, 0x42, 0x4a, 0xcc, 0x49, 0x86, 0x76, 0x41, 0x5e, 0x17, 0x50, + 0x6a, 0x35, 0x1c, 0x12, 0x4b, 0x54, 0x04, 0xf1, 0xd1, 0x71, 0x53, 0x27, + 0x26, 0x19, 0xdf, 0x71, 0x3c, 0xe3, 0x4d, 0x03, 0xf1, 0xf9, 0xee, 0x28, + 0x59, 0x2f, 0x22, 0xf8, 0x29, 0xa3, 0x19, 0x93, 0xb1, 0x06, 0xc7, 0x85, + 0xfa, 0x6d, 0xbe, 0x57, 0xd0, 0x04, 0x9c, 0x81, 0x5d, 0xb5, 0xee, 0x2d, + 0xfe, 0x94, 0x8d, 0xde, 0xdd, 0x1a, 0x5e, 0x2c, 0xd2, 0x34, 0x6c, 0xf2, + 0xf6, 0x6f, 0x04, 0xfb, 0xad, 0x61, 0x9c, 0xd9, 0x83, 0xa1, 0xb0, 0x69, + 0xb4, 0x71, 0xef, 0x9a, 0xdb, 0x4d, 0xf6, 0xce, 0xae, 0xa2, 0x3d, 0x09, + 0xf0, 0xa5, 0x48, 0xc3, 0xc7, 0x20, 0x96, 0x34, 0xc8, 0xa0, 0x5e, 0x58, + 0x97, 0x44, 0x59, 0x06, 0xde, 0xa0, 0x8a, 0x52, 0xe4, 0x07, 0x4b, 0xe2, + 0x2d, 0x84, 0x85, 0xf2, 0x0e, 0xaa, 0xea, 0xdb, 0xaa, 0xb3, 0x97, 0x19, + 0x9b, 0x06, 0x7a, 0xa8, 0x60, 0x05, 0x69, 0x91, 0xee, 0x08, 0x84, 0x80, + 0xb4, 0x92, 0x12, 0x67, 0xa6, 0x98, 0xa8, 0xf7, 0xa0, 0x37, 0x77, 0xf5, + 0x6b, 0xac, 0x84, 0xe5, 0x09, 0x03, 0xe8, 0x8d, 0x07, 0x26, 0x1f, 0x24, + 0xd0, 0xa4, 0xf3, 0x17, 0x12, 0x8e, 0x01, 0xfe, 0x8a, 0x92, 0x24, 0xf1, + 0x22, 0x93, 0x94, 0x9c, 0xb6, 0xc3, 0xf0, 0x95, 0xaf, 0xd1, 0x9a, 0xec, + 0xb1, 0x6b, 0x20, 0x9a, 0x99, 0x48, 0x7d, 0xcc, 0x2a, 0x1b, 0x83, 0xc4, + 0x9d, 0x75, 0xe3, 0x51 +}; +/* K = 901632e0b8ffea7efebe2fc9ea0d1a52442817fe1e1b5455bd39a687 */ +static const uint8_t ac_dsa_vect137_out[] = { +/* R */ + 0x1f, 0x44, 0xf6, 0xea, 0xc2, 0x18, 0x23, 0x6a, 0x1d, 0x99, 0xcf, 0x76, + 0x25, 0xab, 0xcf, 0x5c, 0x96, 0x4b, 0x0a, 0x0c, 0x5d, 0x88, 0xb8, 0xd0, + 0x5d, 0x74, 0xa3, 0xc0, +/* S */ + 0x71, 0x01, 0x5c, 0xbe, 0x86, 0x22, 0xd2, 0xa3, 0x4f, 0xbb, 0x5e, 0x7c, + 0xca, 0x8c, 0x59, 0xe8, 0x28, 0xad, 0xee, 0x71, 0xf5, 0x05, 0x24, 0x48, + 0x2d, 0x9e, 0x79, 0x04 +}; +#define ac_dsa_vect138_prime ac_dsa_vect136_prime +#define ac_dsa_vect138_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect138_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect138_ptx[] = { +/* Msg */ + 0x08, 0xea, 0x09, 0xfa, 0x5e, 0xfd, 0xe2, 0x15, 0xbd, 0x8b, 0x3c, 0x4d, + 0x6a, 0x9c, 0x90, 0xee, 0x93, 0x87, 0xff, 0xb7, 0xbd, 0x65, 0xbe, 0xcd, + 0xb8, 0x8b, 0x40, 0x13, 0x2c, 0x63, 0x84, 0x10, 0x6a, 0xa6, 0x19, 0xb7, + 0xc6, 0x6c, 0xa9, 0x20, 0x34, 0xd2, 0x84, 0x60, 0x85, 0x93, 0x86, 0x4c, + 0xe6, 0xb9, 0x28, 0x77, 0x11, 0x2a, 0xa1, 0x39, 0x24, 0x0c, 0xb4, 0x4b, + 0x38, 0x8f, 0xe6, 0x8a, 0x8f, 0xe0, 0x50, 0x1c, 0xa5, 0x84, 0xf6, 0xa2, + 0xde, 0x27, 0xc0, 0xfb, 0x65, 0x8e, 0x72, 0xbb, 0x13, 0xfd, 0xdb, 0x8d, + 0x03, 0x9a, 0x6b, 0xf8, 0x5d, 0x63, 0xa6, 0xc0, 0x73, 0xb2, 0x66, 0x80, + 0x13, 0xce, 0x8f, 0xe5, 0x89, 0xa0, 0x15, 0x0e, 0x46, 0xd5, 0xb1, 0xd9, + 0xb0, 0xcb, 0xb5, 0xa1, 0x4c, 0x10, 0x0a, 0xe4, 0xb2, 0x0d, 0x6c, 0xe8, + 0x1a, 0x98, 0x7a, 0x50, 0xa9, 0x49, 0xf4, 0x34 +}; +static const uint8_t ac_dsa_vect138_priv_val[] = { +/* X */ + 0xa2, 0xcd, 0xf2, 0x51, 0x5c, 0xb0, 0x98, 0x55, 0x9f, 0xa1, 0x3c, 0xb7, + 0x0b, 0x6a, 0x89, 0x7e, 0x89, 0xdf, 0x12, 0x0a, 0x97, 0x10, 0x64, 0xbb, + 0x37, 0x79, 0x88, 0xee +}; +static const uint8_t ac_dsa_vect138_pub_val[] = { +/* Y */ + 0xb3, 0xe2, 0xb7, 0xe0, 0x64, 0x17, 0x21, 0xd6, 0x96, 0x16, 0x67, 0x95, + 0x96, 0xcc, 0x75, 0x09, 0x1f, 0xad, 0xe2, 0xda, 0x05, 0x58, 0xe3, 0x10, + 0xb8, 0xd1, 0x4d, 0xb0, 0xf4, 0x68, 0x6f, 0x1f, 0xed, 0x48, 0xd0, 0xfb, + 0x7f, 0x0b, 0x3b, 0x27, 0xbf, 0x6e, 0x19, 0x81, 0xea, 0xfa, 0x77, 0x37, + 0xa3, 0xe6, 0x51, 0x82, 0x8d, 0x1f, 0xcb, 0xf8, 0x83, 0x87, 0xd0, 0x6f, + 0x78, 0x40, 0x4a, 0x7a, 0xfa, 0xea, 0xaf, 0x8f, 0xae, 0x18, 0x93, 0xbe, + 0xa3, 0xa0, 0x9a, 0x11, 0x88, 0x93, 0x93, 0x7a, 0xe2, 0xa8, 0xfd, 0xef, + 0x33, 0x20, 0x94, 0x2a, 0x15, 0x84, 0x63, 0xde, 0x4f, 0xdd, 0xc1, 0x19, + 0x87, 0xf2, 0x3f, 0xee, 0x96, 0x33, 0xe0, 0x6a, 0xc2, 0x39, 0xc0, 0x66, + 0x10, 0xbc, 0x45, 0x31, 0x9a, 0xba, 0xfe, 0x51, 0x7c, 0xe4, 0xae, 0xae, + 0x62, 0x47, 0xea, 0x78, 0x9d, 0x7d, 0xa6, 0x0d, 0x3e, 0xed, 0xdf, 0xdc, + 0x4b, 0x23, 0x2b, 0x4d, 0x7a, 0x06, 0x9b, 0xcc, 0x0e, 0xac, 0x7b, 0x99, + 0xfc, 0x08, 0x8f, 0xb7, 0xec, 0x19, 0x46, 0x03, 0x4a, 0x98, 0xd7, 0xe6, + 0x9c, 0xab, 0x0c, 0xb2, 0xb0, 0x6b, 0x3d, 0x9d, 0xea, 0xcd, 0x1b, 0x43, + 0x3e, 0xbe, 0x94, 0xf5, 0x47, 0xa3, 0x22, 0x89, 0x5c, 0xca, 0x9b, 0x0e, + 0xd3, 0x19, 0xb1, 0xd4, 0x58, 0xc3, 0xbf, 0xb2, 0x60, 0xbe, 0xb6, 0x41, + 0xa5, 0x34, 0x5d, 0xbe, 0x3d, 0x01, 0xce, 0x80, 0x0e, 0xc2, 0xc6, 0xbd, + 0x43, 0x0c, 0xe3, 0xe3, 0xf5, 0xf7, 0x8f, 0xca, 0xbf, 0x91, 0xa2, 0x96, + 0x58, 0x66, 0x1c, 0x57, 0x3b, 0x9f, 0x6f, 0xd3, 0x81, 0x2e, 0x56, 0x0d, + 0x88, 0x8b, 0x6c, 0xdf, 0x3d, 0x57, 0x67, 0x3c, 0x16, 0x30, 0xe0, 0x0c, + 0xa8, 0x41, 0xee, 0x99, 0x49, 0x58, 0xb2, 0x50, 0xda, 0xfb, 0xc3, 0xe8, + 0x3b, 0xcb, 0x8b, 0xe5 +}; +/* K = 077b3adce42ba0622772eaaa8cabd16107c92f7a134c715a4dda5ebd */ +static const uint8_t ac_dsa_vect138_out[] = { +/* R */ + 0x6c, 0x03, 0x63, 0x7d, 0x25, 0x3a, 0x8d, 0xcd, 0x09, 0x07, 0xd6, 0xde, + 0x93, 0x92, 0x6b, 0xdb, 0x3e, 0x1e, 0xa3, 0x13, 0x5a, 0x70, 0x9d, 0xa2, + 0x30, 0x9a, 0x8d, 0xa6, +/* S */ + 0x23, 0x6e, 0x51, 0x63, 0xf2, 0xc2, 0xeb, 0xe0, 0xec, 0xcd, 0xbd, 0x33, + 0x51, 0xe4, 0x28, 0x55, 0x31, 0xa4, 0xf5, 0x3e, 0x45, 0x28, 0x4e, 0x41, + 0xdb, 0x37, 0xe2, 0x66 +}; +#define ac_dsa_vect139_prime ac_dsa_vect136_prime +#define ac_dsa_vect139_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect139_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect139_ptx[] = { +/* Msg */ + 0x95, 0x7c, 0xef, 0x16, 0x3b, 0x16, 0xd8, 0x07, 0x3d, 0x5d, 0x3f, 0xe1, + 0x58, 0xfa, 0x0c, 0x73, 0x38, 0xbd, 0x10, 0x7c, 0x6a, 0x65, 0x3c, 0xb0, + 0xf1, 0x1e, 0xbe, 0x41, 0x40, 0x26, 0x07, 0xb8, 0x22, 0xab, 0xe3, 0x0e, + 0x36, 0xca, 0x9e, 0xe4, 0xc9, 0xde, 0x00, 0xcf, 0x72, 0xdb, 0x97, 0xf5, + 0x7d, 0x78, 0xf3, 0xdb, 0x49, 0xa8, 0xe1, 0x09, 0x32, 0x85, 0x56, 0x3c, + 0x68, 0xb0, 0xf4, 0xe1, 0x24, 0x83, 0x0b, 0x9f, 0xeb, 0xfa, 0x3e, 0x75, + 0xce, 0x2e, 0xa5, 0x9c, 0xba, 0x2c, 0xc6, 0xd7, 0x1e, 0x90, 0x8b, 0x5e, + 0x6d, 0x8f, 0x46, 0x39, 0x54, 0x92, 0x2b, 0x82, 0xbb, 0x55, 0xa6, 0x9f, + 0xb2, 0xff, 0x14, 0x3f, 0xfc, 0xae, 0x6b, 0x56, 0x56, 0x14, 0x3c, 0x8b, + 0x6c, 0xc2, 0x4f, 0x57, 0xb1, 0x7c, 0xfb, 0x02, 0x0f, 0x6e, 0x15, 0xbd, + 0xc5, 0xf2, 0x54, 0x36, 0xd0, 0x7b, 0x7f, 0x8a +}; +static const uint8_t ac_dsa_vect139_priv_val[] = { +/* X */ + 0x15, 0xea, 0x86, 0xb9, 0x73, 0xef, 0x14, 0x6f, 0x03, 0xcc, 0x70, 0x1b, + 0x17, 0xb5, 0x89, 0xb0, 0xff, 0xdd, 0x31, 0x8b, 0x64, 0x82, 0x7d, 0x49, + 0xee, 0x3c, 0x00, 0x44 +}; +static const uint8_t ac_dsa_vect139_pub_val[] = { +/* Y */ + 0x3f, 0xcb, 0x8e, 0x44, 0xd6, 0x88, 0x0f, 0x9e, 0xeb, 0xae, 0xdf, 0xb7, + 0x59, 0x94, 0x60, 0x5c, 0x9e, 0xc0, 0x01, 0xf0, 0x59, 0x5a, 0xeb, 0x5f, + 0x2b, 0xca, 0xf6, 0xb3, 0x98, 0x7b, 0xc2, 0x8a, 0x7c, 0xa9, 0x05, 0xe1, + 0xfe, 0xd7, 0xe3, 0xc7, 0x15, 0x40, 0x1b, 0x5c, 0x60, 0x8d, 0x12, 0x07, + 0x69, 0x38, 0xa1, 0x80, 0x13, 0x47, 0x3d, 0x8a, 0x43, 0x32, 0x77, 0xfd, + 0x9c, 0xe5, 0xa5, 0xca, 0xe0, 0x38, 0x28, 0x1e, 0x76, 0x8f, 0xf9, 0x09, + 0xae, 0xbe, 0x4d, 0x25, 0x7d, 0xcb, 0x5d, 0x93, 0x48, 0x80, 0x22, 0xd0, + 0x7d, 0x4c, 0x28, 0x62, 0xaf, 0xb2, 0xbf, 0x8a, 0x2b, 0x1e, 0x97, 0x4a, + 0x8e, 0x7b, 0x6e, 0x17, 0x6b, 0x1b, 0x0b, 0x7a, 0xd6, 0xf6, 0x3b, 0xda, + 0x1b, 0x71, 0x42, 0xe4, 0x6f, 0x50, 0x4d, 0xcc, 0xcc, 0xa7, 0xd1, 0xe2, + 0xe7, 0x66, 0x27, 0x58, 0xf7, 0x60, 0xe6, 0x24, 0xe5, 0x95, 0x28, 0xc5, + 0xa0, 0xc9, 0x56, 0x3e, 0xd5, 0x17, 0xc6, 0x91, 0xfb, 0xa2, 0xab, 0xf6, + 0x68, 0x99, 0x24, 0x11, 0x78, 0x22, 0x3b, 0xa2, 0x00, 0x13, 0xed, 0x0a, + 0xb2, 0x1f, 0x91, 0xf3, 0xe6, 0xbe, 0xf7, 0x55, 0xc8, 0x10, 0x0c, 0x51, + 0xee, 0x94, 0x7b, 0x7a, 0x9b, 0xa3, 0x85, 0x70, 0xf8, 0x80, 0xb5, 0xe4, + 0x2f, 0x24, 0xb7, 0x2d, 0x53, 0x21, 0x13, 0x2e, 0x03, 0x1b, 0x98, 0x5a, + 0x0d, 0xb8, 0x25, 0xbf, 0x3b, 0xb0, 0x0a, 0x77, 0x71, 0xa0, 0x30, 0x07, + 0x38, 0x7e, 0x03, 0xce, 0x02, 0x0f, 0xc3, 0x58, 0xe6, 0x5e, 0xd3, 0xde, + 0x8d, 0x84, 0x7f, 0x5b, 0xe6, 0x07, 0x20, 0x91, 0x7c, 0x06, 0x16, 0xa4, + 0x50, 0xaa, 0x34, 0x1a, 0xe0, 0x0a, 0xbe, 0x0a, 0x80, 0x9c, 0x38, 0xe9, + 0x73, 0x14, 0xf3, 0x03, 0xfe, 0x9b, 0x0c, 0x6c, 0xde, 0x44, 0x6d, 0x02, + 0x17, 0xcc, 0x4e, 0xab +}; +/* K = 9af96c995f0b7b8283e2ea288e3c3a6f751a56b38041297e2bc34cd7 */ +static const uint8_t ac_dsa_vect139_out[] = { +/* R */ + 0x15, 0x03, 0x62, 0xda, 0x79, 0x27, 0x01, 0x69, 0x4e, 0x23, 0xf0, 0xb0, + 0xa9, 0xb7, 0x03, 0x54, 0x37, 0xcc, 0x8f, 0x4f, 0xaa, 0x45, 0xc6, 0xdf, + 0x8f, 0x79, 0x82, 0xfb, +/* S */ + 0x6d, 0xf4, 0x32, 0x1c, 0x61, 0x73, 0x87, 0x43, 0xa9, 0xfe, 0x78, 0xec, + 0x76, 0xb4, 0x95, 0x26, 0x92, 0xaa, 0xa3, 0x72, 0xd1, 0xc8, 0x53, 0x0f, + 0xba, 0x0f, 0xcd, 0xec +}; +#define ac_dsa_vect140_prime ac_dsa_vect136_prime +#define ac_dsa_vect140_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect140_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect140_ptx[] = { +/* Msg */ + 0x20, 0x4d, 0x9c, 0xde, 0x24, 0xa2, 0xf0, 0xde, 0x02, 0xaf, 0xf0, 0x20, + 0xf6, 0x36, 0x3f, 0xd6, 0x8f, 0x70, 0x42, 0x0d, 0xc1, 0xa9, 0xb5, 0x13, + 0x82, 0x16, 0x20, 0x13, 0x63, 0xf8, 0x32, 0xda, 0x0a, 0xa8, 0x01, 0x86, + 0x5a, 0x75, 0xa2, 0x43, 0x42, 0x7d, 0x9d, 0x6c, 0x78, 0xdc, 0x5e, 0x60, + 0x41, 0xb2, 0x7d, 0x03, 0x36, 0x60, 0xe1, 0xe4, 0x05, 0xab, 0xe1, 0xbe, + 0x27, 0xc9, 0x09, 0x99, 0x4b, 0xd6, 0xfb, 0x57, 0x18, 0x0c, 0x3d, 0x6b, + 0x49, 0x8c, 0xe8, 0x79, 0x3b, 0xee, 0x8e, 0xcf, 0x51, 0xe0, 0x6b, 0x96, + 0x41, 0x1d, 0x00, 0x99, 0x62, 0x09, 0xf4, 0x4a, 0x38, 0x09, 0x26, 0xc7, + 0xb1, 0x95, 0xe8, 0x4e, 0x78, 0xf0, 0x1f, 0xe0, 0x2e, 0x0b, 0xc7, 0x03, + 0x2c, 0xa4, 0x62, 0xa5, 0x18, 0x26, 0x83, 0x47, 0x52, 0x22, 0xf9, 0xdd, + 0x8f, 0x3a, 0xde, 0x1a, 0xb8, 0xfe, 0xa3, 0x18 +}; +static const uint8_t ac_dsa_vect140_priv_val[] = { +/* X */ + 0x52, 0x4a, 0x63, 0xcc, 0x5a, 0xca, 0xda, 0x85, 0x57, 0x60, 0x9a, 0x5f, + 0x0d, 0x88, 0xfd, 0x3e, 0x9c, 0x6e, 0x63, 0x71, 0x97, 0x04, 0xcd, 0x8b, + 0xab, 0x8f, 0xe3, 0x01 +}; +static const uint8_t ac_dsa_vect140_pub_val[] = { +/* Y */ + 0x99, 0xb8, 0xfc, 0x6e, 0x64, 0xcc, 0xe2, 0x62, 0xed, 0x74, 0x1c, 0x30, + 0xcd, 0x58, 0x69, 0x86, 0xaa, 0x2e, 0x8f, 0x63, 0x71, 0xb8, 0x48, 0xa2, + 0x61, 0x7c, 0x61, 0x98, 0x97, 0xde, 0x23, 0x72, 0x6b, 0xb5, 0x45, 0x36, + 0xec, 0xe4, 0xb4, 0x60, 0xcc, 0x7f, 0x1f, 0x39, 0xe0, 0xc1, 0x84, 0xeb, + 0x19, 0x29, 0x1e, 0x93, 0x0d, 0xc9, 0x14, 0x0e, 0x4b, 0x77, 0x35, 0x54, + 0x1e, 0xee, 0xf8, 0xca, 0x8e, 0xbc, 0x81, 0x79, 0x0f, 0xed, 0x37, 0xa5, + 0xf0, 0x8e, 0x9d, 0xa9, 0xab, 0xc6, 0x6a, 0x3a, 0x2e, 0x90, 0x99, 0x02, + 0xa4, 0x21, 0x21, 0x06, 0x92, 0x7d, 0x08, 0xab, 0xec, 0x01, 0xf2, 0x7c, + 0x60, 0x56, 0xb6, 0xe0, 0x38, 0x11, 0x50, 0xbd, 0x74, 0x2d, 0x40, 0x9f, + 0x68, 0x10, 0xfa, 0x58, 0x18, 0xff, 0xcb, 0x3f, 0x18, 0x2a, 0xdf, 0x89, + 0x4b, 0xa7, 0xf8, 0x06, 0x78, 0xce, 0x88, 0x3c, 0x10, 0x89, 0xa6, 0xae, + 0x71, 0xdb, 0x3a, 0x11, 0x5c, 0x38, 0x6d, 0xd9, 0x15, 0x3f, 0x41, 0x91, + 0xfc, 0x36, 0x54, 0x61, 0xac, 0x86, 0x83, 0x8e, 0xcf, 0x2f, 0x3f, 0x81, + 0xcc, 0xf2, 0x83, 0x29, 0x7a, 0x6f, 0xbc, 0x64, 0x4f, 0x52, 0xaa, 0xe6, + 0x64, 0x90, 0x1a, 0xe3, 0x0c, 0x96, 0xfe, 0x4d, 0xf9, 0x30, 0xcf, 0x1a, + 0x41, 0x75, 0x72, 0x41, 0xcc, 0x4d, 0x9a, 0xdf, 0xcc, 0xdd, 0x9a, 0x6b, + 0xd5, 0x00, 0x4b, 0x05, 0x75, 0x74, 0x43, 0x59, 0x88, 0x56, 0x40, 0x0d, + 0xd7, 0x71, 0xdc, 0x08, 0x90, 0x95, 0xc7, 0xdc, 0xde, 0x82, 0xf7, 0x21, + 0xf9, 0x86, 0xaf, 0x63, 0x66, 0x38, 0xee, 0xa2, 0xc7, 0x17, 0x70, 0x85, + 0x6c, 0x2b, 0xa8, 0x03, 0x15, 0xe8, 0x69, 0x61, 0x42, 0xa1, 0x1e, 0x51, + 0xeb, 0xd7, 0x55, 0x9e, 0x9d, 0xa6, 0xa0, 0x0b, 0xe3, 0xf9, 0xf3, 0x8c, + 0x61, 0x4e, 0xf2, 0x07 +}; +/* K = 028091483753f5643b61e4093a7e0a5135d71c5fa318d6e8bb0efc66 */ +static const uint8_t ac_dsa_vect140_out[] = { +/* R */ + 0x9c, 0x02, 0x33, 0x31, 0x75, 0x1c, 0x79, 0xd5, 0xda, 0x35, 0x5b, 0xb5, + 0x8e, 0x2b, 0xbe, 0x2e, 0x97, 0x3e, 0x3e, 0x4b, 0x4f, 0x52, 0x74, 0x3c, + 0xe1, 0xf1, 0xee, 0xc2, +/* S */ + 0x96, 0xad, 0x0e, 0x8c, 0xa9, 0x06, 0x27, 0xfb, 0x7a, 0xc4, 0x54, 0x0c, + 0x9b, 0x58, 0xa0, 0x16, 0xee, 0x6c, 0x4e, 0x0a, 0x6f, 0x0a, 0xa1, 0xe7, + 0xde, 0xf8, 0x1a, 0x51 +}; +#define ac_dsa_vect141_prime ac_dsa_vect136_prime +#define ac_dsa_vect141_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect141_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect141_ptx[] = { +/* Msg */ + 0x1e, 0x4e, 0x58, 0xaf, 0xb3, 0x4c, 0x5d, 0x6f, 0x64, 0x5a, 0x82, 0x64, + 0x5b, 0xe3, 0x58, 0xa2, 0xe2, 0x28, 0xcc, 0x7b, 0x9c, 0x23, 0xdd, 0x7f, + 0x3a, 0xa7, 0x95, 0x95, 0x81, 0x4d, 0x05, 0x4b, 0x92, 0x3b, 0x9c, 0xbc, + 0x6c, 0x9e, 0x6c, 0x6f, 0x94, 0x84, 0x8c, 0x1a, 0x4d, 0x21, 0x56, 0x79, + 0x02, 0x3a, 0x96, 0x97, 0x6a, 0x44, 0xe9, 0xb5, 0x91, 0x36, 0x24, 0x1f, + 0xdf, 0x26, 0xf8, 0xf7, 0x1f, 0xe5, 0xa9, 0xbf, 0x36, 0x6e, 0x49, 0x12, + 0xb5, 0x93, 0x1e, 0x1c, 0x8f, 0x63, 0xc3, 0x7f, 0xae, 0x2b, 0xf1, 0xd5, + 0x5b, 0xa3, 0x94, 0x3a, 0x65, 0x0b, 0xb4, 0x63, 0xcd, 0xed, 0x9a, 0x7b, + 0x06, 0x2a, 0xe5, 0x5a, 0xa5, 0x7d, 0x9c, 0x5c, 0xee, 0xd3, 0x23, 0xfd, + 0x9a, 0x75, 0x55, 0xe4, 0x8b, 0x83, 0x4d, 0x3a, 0xd4, 0x44, 0x1c, 0x35, + 0xd9, 0xe0, 0x7c, 0x7c, 0x6e, 0x4d, 0x5d, 0x0f +}; +static const uint8_t ac_dsa_vect141_priv_val[] = { +/* X */ + 0x33, 0xb2, 0x5c, 0x6b, 0xbb, 0xf8, 0x16, 0xad, 0xda, 0xd0, 0x5e, 0x48, + 0xb7, 0x2c, 0xa5, 0x60, 0xc5, 0x19, 0x12, 0x14, 0xd9, 0x03, 0xa9, 0x78, + 0xb6, 0x70, 0x8a, 0x30 +}; +static const uint8_t ac_dsa_vect141_pub_val[] = { +/* Y */ + 0xb4, 0xde, 0xa0, 0xd5, 0xb6, 0x71, 0xcc, 0x81, 0x53, 0x82, 0xd0, 0xec, + 0x6d, 0xce, 0x66, 0x1c, 0x30, 0xff, 0x93, 0x71, 0x9d, 0xc7, 0xf5, 0x6e, + 0x7e, 0x61, 0xdf, 0x6e, 0xb6, 0xa3, 0x20, 0x7a, 0x05, 0x61, 0x79, 0x38, + 0xc8, 0x74, 0xbc, 0x3a, 0xb0, 0x93, 0xbc, 0xdb, 0xbc, 0x98, 0x3a, 0x4b, + 0x0b, 0x58, 0x7d, 0x60, 0xfd, 0xeb, 0x7b, 0x87, 0xf7, 0xb0, 0xbe, 0x4a, + 0x65, 0x68, 0x83, 0xf5, 0x44, 0x3c, 0xa7, 0x86, 0x45, 0x41, 0xcc, 0xbf, + 0xe0, 0xd0, 0x83, 0x56, 0x36, 0xef, 0x08, 0xa9, 0x36, 0xb2, 0x32, 0x1a, + 0x51, 0x50, 0x3b, 0xe1, 0xee, 0xc5, 0xf7, 0xbc, 0xcd, 0x0c, 0x73, 0xc9, + 0xcd, 0x52, 0x39, 0x7c, 0xc2, 0x14, 0x31, 0x8b, 0x30, 0xe8, 0xbe, 0x1e, + 0xab, 0x57, 0x20, 0x0a, 0x4d, 0x4d, 0xf7, 0x8a, 0xf9, 0x91, 0xbd, 0xe1, + 0x83, 0xe0, 0x16, 0x4e, 0x69, 0x4d, 0x83, 0x08, 0xb7, 0xd2, 0x0d, 0x06, + 0x7b, 0xfc, 0xab, 0xdc, 0xb5, 0x0f, 0x7a, 0x2c, 0x19, 0x0c, 0x66, 0xce, + 0x3d, 0xd0, 0xe1, 0x89, 0x60, 0x93, 0x9c, 0xb5, 0x7f, 0xc3, 0xa2, 0xe5, + 0xa6, 0x04, 0xf3, 0xd9, 0xbd, 0x6f, 0xa4, 0x40, 0xd5, 0x4e, 0x9c, 0xc0, + 0x38, 0x39, 0x58, 0xa0, 0xd6, 0xaa, 0x2a, 0xb6, 0x70, 0x97, 0x0f, 0x9b, + 0x2c, 0xaf, 0x86, 0x6e, 0xe5, 0x07, 0x06, 0x73, 0x43, 0xf7, 0x51, 0x3e, + 0x0a, 0x98, 0x1f, 0x3a, 0x34, 0x4f, 0x2f, 0x75, 0x3a, 0xf4, 0x4f, 0xda, + 0x26, 0xd6, 0x61, 0x79, 0x60, 0x32, 0xbd, 0xa0, 0xf6, 0xcc, 0x30, 0xa9, + 0xa7, 0x89, 0xdb, 0x8d, 0x3d, 0x54, 0x6f, 0x02, 0xf8, 0x98, 0x11, 0x68, + 0x05, 0x18, 0x0c, 0x6f, 0x0d, 0x2f, 0x53, 0x88, 0xab, 0x51, 0x10, 0xa5, + 0x21, 0x07, 0x7d, 0x88, 0xd2, 0x14, 0xfb, 0xb3, 0x2e, 0xed, 0x26, 0x64, + 0x40, 0x6c, 0xde, 0x9b +}; +/* K = 989d87703853c4133b6d273686bf672492e90ce2a91b3c72a4188a1c */ +static const uint8_t ac_dsa_vect141_out[] = { +/* R */ + 0x04, 0x34, 0xef, 0x1c, 0x12, 0x72, 0x07, 0xd0, 0xc8, 0x84, 0x70, 0x1e, + 0x75, 0xd8, 0x01, 0x72, 0x5c, 0x45, 0x1c, 0xe6, 0x7d, 0x2e, 0x71, 0x53, + 0x46, 0x38, 0xb2, 0x31, +/* S */ + 0x0c, 0x62, 0x5e, 0x4a, 0x33, 0x4d, 0xb0, 0x78, 0x25, 0xa4, 0x6b, 0x55, + 0xda, 0x9c, 0x2e, 0x8a, 0x5f, 0x60, 0x0a, 0x36, 0xb7, 0x16, 0x06, 0x83, + 0x40, 0x97, 0xe7, 0x77 +}; +#define ac_dsa_vect142_prime ac_dsa_vect136_prime +#define ac_dsa_vect142_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect142_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect142_ptx[] = { +/* Msg */ + 0x5a, 0x47, 0x0a, 0x38, 0xb2, 0xeb, 0xbe, 0xad, 0x08, 0xe0, 0x10, 0xef, + 0xef, 0x74, 0x61, 0xf6, 0xf8, 0x59, 0x25, 0x7d, 0x91, 0xa6, 0x1e, 0x2f, + 0x0b, 0xa8, 0x09, 0xe2, 0x8c, 0x0e, 0xa3, 0xd4, 0x10, 0xe4, 0xf4, 0x14, + 0x77, 0xa3, 0x98, 0xd5, 0x93, 0xdf, 0x58, 0x03, 0x9c, 0x43, 0x36, 0x26, + 0x0e, 0xa7, 0xd8, 0xe9, 0x8c, 0x9d, 0x7d, 0xaa, 0xd0, 0xc3, 0x1e, 0xcd, + 0x15, 0x67, 0xc7, 0xdb, 0x73, 0x01, 0x79, 0xe2, 0xa9, 0xa6, 0x20, 0x07, + 0xbd, 0x56, 0xf9, 0xd9, 0xda, 0x48, 0xde, 0xaa, 0x65, 0x7a, 0xc9, 0x22, + 0x93, 0xe5, 0xbf, 0xaf, 0xbd, 0xeb, 0xad, 0x1a, 0xfe, 0x25, 0xc4, 0x1e, + 0x1a, 0xa0, 0x9d, 0xb6, 0x1f, 0xcc, 0x19, 0x19, 0x71, 0xc3, 0x75, 0x49, + 0x15, 0x5b, 0x3e, 0x67, 0x95, 0x69, 0x13, 0xaa, 0xe3, 0xa5, 0xf6, 0x24, + 0x5c, 0xfc, 0xb9, 0xaa, 0xd5, 0xdc, 0x1e, 0x15 +}; +static const uint8_t ac_dsa_vect142_priv_val[] = { +/* X */ + 0x13, 0x41, 0x1c, 0x1a, 0x6f, 0xe0, 0x06, 0x3e, 0x7f, 0x9b, 0x24, 0x67, + 0xcc, 0xeb, 0xf2, 0xbe, 0x5c, 0xf3, 0x0e, 0x74, 0x2f, 0x9a, 0x35, 0xd7, + 0x15, 0x55, 0x8b, 0xa7 +}; +static const uint8_t ac_dsa_vect142_pub_val[] = { +/* Y */ + 0x06, 0xa2, 0x0d, 0x55, 0x71, 0x29, 0x6e, 0xeb, 0x87, 0xe7, 0x9e, 0xb2, + 0x74, 0x03, 0x6d, 0x81, 0x9e, 0x86, 0x23, 0xb1, 0x5d, 0xe4, 0x4c, 0x26, + 0x97, 0xda, 0xde, 0xca, 0xb2, 0x99, 0x6f, 0x51, 0xa7, 0x5a, 0xa0, 0x88, + 0x49, 0x0e, 0x68, 0x3f, 0x34, 0xd5, 0xe0, 0xe7, 0x1d, 0x9f, 0xb8, 0x73, + 0x4b, 0xcf, 0xb7, 0x1e, 0x9d, 0x19, 0xcb, 0xda, 0x3c, 0xac, 0xa5, 0xce, + 0xc4, 0x17, 0xfa, 0x37, 0xa0, 0x61, 0x42, 0xbf, 0xc0, 0x68, 0x2d, 0xe5, + 0x6f, 0x0d, 0xce, 0x6e, 0x82, 0x6e, 0xe9, 0xf3, 0x0d, 0x01, 0x27, 0x98, + 0x59, 0xd3, 0xff, 0xbd, 0x44, 0x33, 0xbf, 0x4a, 0x10, 0x57, 0xba, 0x0a, + 0xd7, 0x50, 0x60, 0xd4, 0x1f, 0x96, 0x8f, 0x6d, 0xa8, 0x22, 0xc3, 0x3c, + 0xbd, 0xa9, 0xf7, 0x72, 0xc2, 0xb7, 0x7b, 0xc1, 0xb2, 0x93, 0x05, 0xcb, + 0x69, 0x71, 0x82, 0xc0, 0xd3, 0x9b, 0x13, 0x28, 0x68, 0x93, 0x2c, 0x64, + 0x01, 0x6b, 0xc9, 0x07, 0x1b, 0x30, 0x92, 0x0e, 0xb3, 0x85, 0xc5, 0xae, + 0x41, 0xc5, 0xd4, 0xf6, 0x31, 0xbf, 0x5f, 0x54, 0xb1, 0xeb, 0x4b, 0x37, + 0x3b, 0xb3, 0xe0, 0xbf, 0x6e, 0x44, 0x8a, 0xd8, 0xc9, 0x88, 0xfe, 0xa1, + 0x6e, 0x64, 0x37, 0x90, 0x30, 0x7b, 0x8b, 0x85, 0xf0, 0x09, 0xfb, 0x67, + 0x31, 0x72, 0x17, 0xd9, 0x14, 0x8c, 0x6c, 0xd7, 0xa4, 0x61, 0x36, 0xee, + 0xce, 0x19, 0x50, 0xa1, 0x19, 0xe5, 0xa4, 0x16, 0xa1, 0x97, 0xe0, 0x0d, + 0x0e, 0x92, 0x9b, 0x04, 0xa5, 0xbb, 0xf6, 0xc9, 0x88, 0xd8, 0x59, 0x5a, + 0x0b, 0x2a, 0x5c, 0xa7, 0x19, 0x26, 0xba, 0x35, 0x1a, 0x5f, 0x76, 0x74, + 0xaf, 0x41, 0x83, 0xb5, 0xa6, 0x89, 0x79, 0xbe, 0xdd, 0x64, 0x91, 0x29, + 0x5b, 0x0f, 0x17, 0x2e, 0x73, 0x73, 0xec, 0xa7, 0xe6, 0x2d, 0x78, 0xd7, + 0x44, 0xfd, 0xcc, 0xec +}; +/* K = 7406254d3cfe3d55267236ff63b0f42b2e3b55d1cee7ed1ca3f06ce0 */ +static const uint8_t ac_dsa_vect142_out[] = { +/* R */ + 0x74, 0xdd, 0xdf, 0xa3, 0x5b, 0x25, 0xd0, 0xc0, 0xb2, 0x85, 0xa5, 0xd2, + 0x17, 0x19, 0xee, 0x39, 0xd6, 0xe3, 0xf4, 0x43, 0x44, 0x5c, 0xeb, 0x90, + 0x55, 0x6b, 0x01, 0x86, +/* S */ + 0x47, 0x48, 0x65, 0xd3, 0xef, 0x07, 0xf5, 0xdf, 0x49, 0xe0, 0xa6, 0xeb, + 0xfb, 0x5a, 0xb5, 0xc2, 0xed, 0xe4, 0x7c, 0x4c, 0x63, 0x14, 0xbe, 0x4c, + 0xcf, 0x45, 0x5e, 0x21 +}; +#define ac_dsa_vect143_prime ac_dsa_vect136_prime +#define ac_dsa_vect143_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect143_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect143_ptx[] = { +/* Msg */ + 0x08, 0x49, 0xd6, 0x7e, 0xad, 0x3e, 0x8c, 0x44, 0xad, 0x3b, 0x2f, 0x94, + 0x9b, 0xe1, 0xcd, 0x9f, 0x9a, 0x4b, 0xf8, 0xb5, 0x78, 0x5b, 0xd0, 0x0c, + 0xa6, 0x60, 0x38, 0xe9, 0xa8, 0xb9, 0x37, 0x27, 0xa6, 0x52, 0xa4, 0x15, + 0xc1, 0xd8, 0xa1, 0xec, 0xfc, 0xad, 0x77, 0x78, 0x2d, 0x87, 0xd9, 0x12, + 0x62, 0x3c, 0x2f, 0xef, 0x45, 0xb2, 0x08, 0x3e, 0xc0, 0xf7, 0x9a, 0x26, + 0x4e, 0xf7, 0xc5, 0xbf, 0xb7, 0x6f, 0xde, 0x5b, 0x22, 0xb9, 0x84, 0x53, + 0x92, 0xe7, 0x59, 0xa1, 0xec, 0x05, 0xfa, 0x63, 0x87, 0xcc, 0xd2, 0x94, + 0x3e, 0xf1, 0x27, 0x7c, 0x2e, 0x06, 0x03, 0x37, 0xf8, 0x2a, 0xa5, 0x62, + 0xce, 0xe5, 0xbd, 0x7c, 0x15, 0x82, 0x58, 0xf2, 0xe7, 0x79, 0xd5, 0x1e, + 0x47, 0xe0, 0x00, 0xa7, 0xb0, 0x70, 0x60, 0x77, 0x49, 0x09, 0x76, 0xa0, + 0x77, 0x63, 0xe2, 0xef, 0xb2, 0x75, 0xb5, 0xbf +}; +static const uint8_t ac_dsa_vect143_priv_val[] = { +/* X */ + 0x56, 0x31, 0xc7, 0xdf, 0xd3, 0xf5, 0xad, 0xc0, 0xb7, 0xb5, 0x42, 0xa8, + 0xd1, 0x21, 0xa0, 0x7b, 0xb8, 0x25, 0x1b, 0x6a, 0x1b, 0xf3, 0xa8, 0xcb, + 0xa7, 0x71, 0xc7, 0x24 +}; +static const uint8_t ac_dsa_vect143_pub_val[] = { +/* Y */ + 0xb1, 0xc6, 0x14, 0x42, 0xd8, 0xae, 0xda, 0xe0, 0xa0, 0x4d, 0xae, 0xf7, + 0xb6, 0xf8, 0xa4, 0x9c, 0x6d, 0x07, 0xbd, 0x95, 0x8e, 0x8e, 0xc5, 0x61, + 0x90, 0x6d, 0xdf, 0x31, 0xf3, 0xb4, 0xff, 0xd4, 0x81, 0xda, 0x54, 0x43, + 0xfe, 0x87, 0x88, 0x05, 0x6c, 0x4e, 0xa7, 0xb5, 0xdf, 0xa2, 0xce, 0xe6, + 0x47, 0x4e, 0x3f, 0xdc, 0x83, 0xfc, 0x04, 0x3a, 0x2b, 0xba, 0x33, 0x3d, + 0x50, 0x3a, 0x2a, 0x93, 0x88, 0x65, 0xec, 0x3f, 0x11, 0x86, 0x40, 0xe8, + 0x45, 0x7c, 0x7d, 0x97, 0x4e, 0x2a, 0x65, 0x65, 0x9c, 0xef, 0x5b, 0x7a, + 0xe4, 0xf4, 0x9a, 0x05, 0x4d, 0x94, 0xae, 0x5e, 0x2e, 0xb6, 0x34, 0x5f, + 0x5b, 0xda, 0xf9, 0x21, 0x48, 0xbe, 0xec, 0xc1, 0x09, 0xc5, 0x50, 0x31, + 0xfc, 0xcd, 0x90, 0xce, 0xf8, 0x82, 0x13, 0xb6, 0x9d, 0xdb, 0x75, 0x4b, + 0x40, 0xca, 0x8d, 0x8f, 0x0a, 0x4b, 0xfc, 0x81, 0xa2, 0x87, 0x63, 0x7a, + 0x38, 0xc2, 0x18, 0x07, 0xf7, 0x27, 0xa6, 0x70, 0x25, 0xff, 0x67, 0xb7, + 0xfc, 0xc5, 0x44, 0x18, 0xad, 0xad, 0x40, 0x8a, 0x5c, 0x7d, 0x1c, 0xe0, + 0x5a, 0x1d, 0xe7, 0xe3, 0x09, 0x88, 0xd5, 0x60, 0xe7, 0x79, 0xfd, 0xea, + 0x1b, 0x78, 0x75, 0x33, 0x14, 0xb0, 0xb8, 0x0f, 0xda, 0xcb, 0x62, 0x46, + 0xfa, 0xa4, 0xb4, 0xc4, 0xee, 0x8a, 0xcc, 0x5a, 0xe2, 0x4b, 0x82, 0x31, + 0x20, 0x40, 0x13, 0x4c, 0xd8, 0xcc, 0x2f, 0xd4, 0xfc, 0xb1, 0x91, 0xfe, + 0x43, 0xf6, 0x4d, 0x14, 0x06, 0x24, 0xa8, 0xc6, 0xc2, 0xac, 0x5f, 0xa4, + 0xbf, 0xdb, 0xa5, 0xd6, 0x25, 0xd7, 0xd2, 0x1e, 0x3c, 0x3f, 0x6a, 0xcd, + 0x8a, 0x15, 0x3a, 0x04, 0xfb, 0x22, 0xf8, 0xd3, 0xb2, 0x44, 0xae, 0x8c, + 0x6a, 0x1d, 0xd0, 0xe6, 0xe3, 0xb2, 0xf7, 0x3c, 0x06, 0x4f, 0xfa, 0xbf, + 0xad, 0x6c, 0xc4, 0x61 +}; +/* K = 9c353ace0ae52501bbb98a2d1c9e28f3a833c2b0eaca49cd12c57ec7 */ +static const uint8_t ac_dsa_vect143_out[] = { +/* R */ + 0x2a, 0xeb, 0x7f, 0xce, 0x1b, 0x77, 0x64, 0xd3, 0x2c, 0xfb, 0x7d, 0x85, + 0x25, 0x4c, 0xee, 0xd9, 0xf3, 0xa6, 0x33, 0x7e, 0xe8, 0xda, 0xb4, 0x2c, + 0x8a, 0xb7, 0xa4, 0x15, +/* S */ + 0x17, 0xcc, 0xe1, 0x3b, 0xcb, 0x91, 0x7c, 0xdb, 0xef, 0xe0, 0xc5, 0x66, + 0x31, 0x8f, 0xc9, 0x74, 0x20, 0x4b, 0x70, 0x0c, 0x5c, 0xdd, 0xc5, 0xb2, + 0xb4, 0x99, 0xa7, 0x8e +}; +#define ac_dsa_vect144_prime ac_dsa_vect136_prime +#define ac_dsa_vect144_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect144_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect144_ptx[] = { +/* Msg */ + 0xe7, 0x46, 0x39, 0xf2, 0xba, 0xd4, 0x2f, 0xd6, 0x39, 0x3f, 0x9b, 0x35, + 0x0d, 0x6e, 0x19, 0xcd, 0x4c, 0x1c, 0xe0, 0xf4, 0x1e, 0x8c, 0x90, 0x26, + 0x84, 0xef, 0x6f, 0x86, 0x79, 0x0f, 0xfc, 0x83, 0x11, 0xac, 0xd9, 0xb5, + 0x7d, 0x65, 0x21, 0xe8, 0x03, 0x39, 0xb3, 0x24, 0x3f, 0x6e, 0xc6, 0xb0, + 0x1a, 0x06, 0xea, 0x89, 0x9f, 0xd7, 0x5d, 0xa9, 0x1e, 0x10, 0x80, 0xfd, + 0xf0, 0x61, 0x29, 0xdd, 0x85, 0x1a, 0x89, 0x5d, 0x74, 0xb1, 0xef, 0xb9, + 0x83, 0x72, 0x89, 0xc1, 0x1d, 0x68, 0xe1, 0x30, 0x8c, 0x47, 0xbb, 0x8c, + 0x59, 0xd5, 0xeb, 0x89, 0x5d, 0xb5, 0x3b, 0xba, 0x29, 0x10, 0x2a, 0x5b, + 0x48, 0xb1, 0xe7, 0x5c, 0x73, 0x38, 0x7f, 0xf2, 0x2e, 0x6c, 0x04, 0x61, + 0x19, 0x6a, 0x7d, 0x48, 0x61, 0x5f, 0xfd, 0xb9, 0xc8, 0xff, 0x4e, 0xc6, + 0x58, 0x7b, 0x4f, 0x68, 0xd2, 0x60, 0xad, 0x86 +}; +static const uint8_t ac_dsa_vect144_priv_val[] = { +/* X */ + 0x73, 0x19, 0xbd, 0xf7, 0x9a, 0x4c, 0x8d, 0xbc, 0x11, 0x5e, 0x37, 0x80, + 0xc8, 0x18, 0xf6, 0xe2, 0xa3, 0x24, 0x3a, 0xb4, 0x72, 0x63, 0xe8, 0x4b, + 0xa2, 0x59, 0xbd, 0x3d +}; +static const uint8_t ac_dsa_vect144_pub_val[] = { +/* Y */ + 0x9e, 0x1b, 0x77, 0x24, 0x3a, 0xba, 0x08, 0x86, 0xf9, 0xba, 0xec, 0xa6, + 0xc1, 0x1b, 0xd2, 0xc5, 0xc5, 0x55, 0x47, 0xcc, 0x50, 0x2e, 0x73, 0x1d, + 0x9c, 0x47, 0x25, 0xda, 0x87, 0x77, 0xab, 0x60, 0x50, 0xe3, 0x39, 0x9e, + 0x25, 0x57, 0x77, 0x04, 0xcf, 0xc6, 0x61, 0x63, 0xf6, 0xdf, 0x8d, 0x74, + 0x91, 0x42, 0xa7, 0xe9, 0x74, 0xe4, 0x9b, 0x73, 0x15, 0xab, 0x7c, 0x8b, + 0x85, 0xad, 0x5d, 0x5c, 0xb2, 0x71, 0xcf, 0x20, 0x7e, 0xb7, 0x2e, 0x1c, + 0x34, 0x76, 0xb0, 0xd8, 0x63, 0x72, 0x1c, 0x96, 0x7b, 0xe1, 0x5e, 0xcb, + 0xfb, 0xf0, 0x6e, 0xad, 0xc2, 0x7d, 0xe3, 0x38, 0xea, 0xa3, 0xca, 0xc1, + 0xdd, 0xe6, 0x42, 0xd5, 0x2a, 0xa5, 0x35, 0x91, 0x98, 0xd8, 0x90, 0x9d, + 0x23, 0xd8, 0x7d, 0x82, 0x70, 0x90, 0xa8, 0xad, 0xa7, 0xb7, 0xa5, 0x55, + 0x36, 0x42, 0xd5, 0x86, 0x60, 0x3e, 0xa2, 0x46, 0x4d, 0xab, 0xd2, 0xef, + 0x5e, 0x18, 0xdb, 0x3a, 0x62, 0x3b, 0xe6, 0x5b, 0xe7, 0xb5, 0xa4, 0x69, + 0x89, 0x0f, 0x9d, 0xde, 0x54, 0xa2, 0x7c, 0xa7, 0x23, 0xb4, 0xe0, 0x5d, + 0x56, 0xb7, 0x18, 0x1b, 0x28, 0xd5, 0xc1, 0xf6, 0x54, 0x15, 0x68, 0x8e, + 0xe4, 0x1d, 0x53, 0x37, 0xa9, 0x95, 0x2d, 0x92, 0xed, 0xe4, 0xd1, 0x92, + 0xb9, 0x09, 0x16, 0x39, 0xca, 0xaa, 0x60, 0x33, 0xe4, 0x74, 0x94, 0x18, + 0xdd, 0xe1, 0x5a, 0xbe, 0x4b, 0xad, 0x62, 0xc3, 0x7f, 0xab, 0x05, 0xe3, + 0xbe, 0xf4, 0xcd, 0x73, 0x98, 0xa4, 0x97, 0x7e, 0x07, 0xe1, 0x21, 0xfe, + 0xf2, 0xaa, 0xc5, 0x6b, 0xe7, 0xe0, 0x54, 0x6e, 0x40, 0xfc, 0xa8, 0x85, + 0x69, 0x6a, 0x38, 0x50, 0xc9, 0xa2, 0x87, 0x09, 0xe6, 0x99, 0xd5, 0x26, + 0x11, 0xc9, 0xb7, 0x92, 0x6e, 0x7a, 0xd1, 0x81, 0x49, 0x04, 0x05, 0x82, + 0xc9, 0x97, 0xdb, 0x71 +}; +/* K = 6defbce0e72f014526c8ab02c6fc320a4bbd85365d99fc5d3423fa4c */ +static const uint8_t ac_dsa_vect144_out[] = { +/* R */ + 0x51, 0x5b, 0x9c, 0xe5, 0x3e, 0xb1, 0x0c, 0x3e, 0x47, 0x89, 0x05, 0x56, + 0xe0, 0xf0, 0xfd, 0x19, 0xad, 0xb2, 0x07, 0xb9, 0xc0, 0x1f, 0x12, 0xef, + 0x5c, 0x6c, 0xaa, 0xad, +/* S */ + 0x09, 0x00, 0xe3, 0xac, 0xc4, 0xc3, 0x78, 0xbd, 0xfe, 0x9c, 0xda, 0x4d, + 0xb8, 0xf8, 0xab, 0x54, 0x43, 0x69, 0x31, 0xc7, 0x3d, 0x8d, 0x31, 0x71, + 0xc6, 0xdc, 0x8b, 0xb8 +}; +#define ac_dsa_vect145_prime ac_dsa_vect136_prime +#define ac_dsa_vect145_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect145_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect145_ptx[] = { +/* Msg */ + 0x4a, 0x14, 0x5d, 0xd5, 0xcc, 0x4a, 0x12, 0xea, 0x43, 0x61, 0x7e, 0xc9, + 0x79, 0x0f, 0x10, 0x38, 0x19, 0x0e, 0xd3, 0xd8, 0xaf, 0x24, 0xbb, 0xec, + 0x14, 0xda, 0x3e, 0xcf, 0x5f, 0x38, 0x7c, 0xa9, 0x76, 0x4a, 0x8b, 0x9c, + 0xbc, 0x5f, 0x62, 0x92, 0xa5, 0x3a, 0x9d, 0xa9, 0x53, 0x3c, 0x75, 0x11, + 0x40, 0xf8, 0xda, 0x5f, 0xb6, 0xf3, 0xd4, 0x8e, 0xba, 0x1e, 0x7b, 0x98, + 0x66, 0x27, 0x34, 0xd9, 0xa8, 0xb1, 0x20, 0xdd, 0x51, 0x54, 0x08, 0xba, + 0x75, 0x6f, 0x75, 0xa5, 0x75, 0x52, 0x12, 0x76, 0x4a, 0xd9, 0x2c, 0x3f, + 0x22, 0x63, 0x83, 0x52, 0x11, 0xad, 0xd5, 0xb4, 0xcc, 0x0e, 0xca, 0x8d, + 0x4f, 0xc7, 0xa8, 0x43, 0xf4, 0x9c, 0x38, 0xce, 0x80, 0x86, 0x8f, 0xaf, + 0x8b, 0x49, 0x8f, 0xb4, 0x14, 0xd3, 0x08, 0x0e, 0xd4, 0x1e, 0x36, 0x74, + 0xe2, 0x85, 0xd3, 0xe4, 0x0d, 0x62, 0xf3, 0x05 +}; +static const uint8_t ac_dsa_vect145_priv_val[] = { +/* X */ + 0x79, 0x44, 0xfa, 0x1a, 0x2a, 0x93, 0x8f, 0xfa, 0xbb, 0x23, 0x4c, 0xa3, + 0x85, 0x91, 0x6e, 0x01, 0xa8, 0x92, 0x20, 0xcd, 0x16, 0xf0, 0x6a, 0x47, + 0x4b, 0x9d, 0x4a, 0xc4 +}; +static const uint8_t ac_dsa_vect145_pub_val[] = { +/* Y */ + 0xb3, 0xf6, 0xd4, 0x4d, 0xa8, 0x6a, 0x51, 0x5d, 0x71, 0x85, 0xb7, 0x0c, + 0x5a, 0xda, 0xa3, 0xf6, 0x05, 0x9c, 0x0b, 0xb7, 0x99, 0x5a, 0x53, 0x91, + 0x07, 0x61, 0xfe, 0xa3, 0x62, 0xd9, 0x84, 0x3f, 0x92, 0xf2, 0x27, 0x1d, + 0xdb, 0x0b, 0xca, 0x0d, 0x45, 0x19, 0xe3, 0x3f, 0xdb, 0x13, 0xaf, 0x49, + 0xd8, 0x55, 0xcd, 0x0b, 0x9a, 0xb0, 0xb9, 0x70, 0x26, 0x72, 0x43, 0xe4, + 0x68, 0xd3, 0xc4, 0x16, 0x77, 0xac, 0x58, 0x8f, 0xdf, 0xcb, 0x1c, 0xb9, + 0xaa, 0x4d, 0x23, 0x3f, 0x7a, 0xe0, 0x17, 0xe6, 0x70, 0x94, 0xf4, 0xf4, + 0xd9, 0x04, 0xe1, 0x57, 0x5e, 0x76, 0xbd, 0xc6, 0xbd, 0x82, 0x99, 0xb4, + 0x2a, 0x2f, 0x39, 0xad, 0xef, 0x63, 0xce, 0x04, 0x78, 0x62, 0xaa, 0xa0, + 0xbb, 0x8b, 0xa3, 0x2e, 0xc2, 0x73, 0x34, 0x93, 0x64, 0x84, 0x06, 0xf5, + 0x4f, 0x5d, 0x8e, 0x2e, 0xb1, 0x9e, 0xea, 0x83, 0x7f, 0x4d, 0x59, 0x63, + 0xad, 0x31, 0x92, 0x91, 0x7f, 0x5f, 0xe3, 0xb6, 0xd0, 0x27, 0xb2, 0x2b, + 0xc1, 0xbf, 0x0d, 0xce, 0x84, 0x01, 0xd6, 0x22, 0xca, 0x72, 0xb1, 0xd7, + 0x3a, 0x89, 0xe8, 0x88, 0xde, 0x1e, 0x62, 0xbe, 0xad, 0x2e, 0x4e, 0x1d, + 0xa6, 0xb5, 0xd0, 0x4b, 0x2a, 0x36, 0x94, 0xc7, 0x6f, 0xe0, 0x7a, 0xd3, + 0xc6, 0x64, 0x26, 0x34, 0x3d, 0x67, 0xbe, 0x12, 0xb2, 0xa7, 0x2c, 0x3f, + 0x76, 0x22, 0x55, 0x73, 0xfc, 0x05, 0x4f, 0x3b, 0x7d, 0x73, 0x59, 0x15, + 0x23, 0x8d, 0x7b, 0xdb, 0xcb, 0x03, 0xba, 0x6d, 0xde, 0x3e, 0xdc, 0x00, + 0xf8, 0xc9, 0x83, 0xb0, 0xb5, 0x01, 0x29, 0xfa, 0xb4, 0x26, 0x00, 0x4a, + 0x27, 0xa0, 0x38, 0x13, 0x9f, 0x2d, 0x32, 0x95, 0xb5, 0xb0, 0x32, 0x70, + 0x1f, 0xac, 0xe3, 0x4a, 0x75, 0x23, 0x55, 0x94, 0x85, 0xfa, 0x63, 0x1c, + 0x21, 0x92, 0x37, 0xf6 +}; +/* K = 8ab9322319a138489eb773f3220d712d05cd14eed9aae402a8aa767b */ +static const uint8_t ac_dsa_vect145_out[] = { +/* R */ + 0x5c, 0xfd, 0x4b, 0x9f, 0x92, 0xca, 0x72, 0x7d, 0x51, 0x3a, 0xc1, 0x41, + 0x43, 0xb1, 0x25, 0x14, 0x86, 0x55, 0xf1, 0x64, 0x2c, 0x53, 0xb7, 0x3c, + 0xc2, 0x51, 0x31, 0xc9, +/* S */ + 0x2a, 0xde, 0xf9, 0x4a, 0xae, 0x37, 0x2d, 0x57, 0x9c, 0x99, 0x62, 0x9c, + 0xa0, 0x78, 0x63, 0x62, 0xcb, 0x02, 0x47, 0xaa, 0x6d, 0x99, 0x95, 0x70, + 0x74, 0xcd, 0x7d, 0x43 +}; +#define ac_dsa_vect146_prime ac_dsa_vect136_prime +#define ac_dsa_vect146_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect146_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect146_ptx[] = { +/* Msg */ + 0x42, 0x8a, 0x20, 0x79, 0x0c, 0xad, 0x1c, 0x7b, 0xa8, 0x21, 0x18, 0xae, + 0x58, 0x41, 0xbd, 0x53, 0x80, 0xee, 0x50, 0xbe, 0x5b, 0x64, 0xb8, 0x04, + 0x09, 0x35, 0xef, 0x3d, 0x6d, 0xa3, 0x7a, 0x26, 0xe6, 0xf0, 0x20, 0x35, + 0xfb, 0x19, 0x37, 0xc7, 0xa6, 0xbc, 0xd8, 0x8c, 0x89, 0x4f, 0xad, 0x7d, + 0x8a, 0xa4, 0x8a, 0xbb, 0x89, 0xe0, 0xc6, 0x42, 0x87, 0xcd, 0xc6, 0x37, + 0x45, 0x4d, 0xb8, 0x9e, 0xaf, 0x0a, 0x7e, 0x69, 0x27, 0x34, 0xc8, 0xa2, + 0x43, 0x85, 0x6d, 0xd7, 0x56, 0x90, 0xbd, 0xce, 0xfe, 0x55, 0x4e, 0x39, + 0xa0, 0xdf, 0x84, 0xe6, 0xe0, 0xc9, 0x6b, 0x2c, 0x57, 0x74, 0xa3, 0xe4, + 0xe2, 0xaf, 0xed, 0x02, 0x8f, 0xb4, 0x3d, 0x79, 0x98, 0xd3, 0xcd, 0xc9, + 0xa6, 0x40, 0x93, 0x22, 0xcf, 0x3b, 0xfa, 0x4d, 0x1e, 0x36, 0xf5, 0xe7, + 0x07, 0x20, 0x3b, 0x59, 0xc4, 0x9a, 0x75, 0x3e +}; +static const uint8_t ac_dsa_vect146_priv_val[] = { +/* X */ + 0x43, 0xde, 0xa1, 0xb4, 0xe5, 0xc2, 0xf2, 0x25, 0x48, 0x07, 0x4d, 0x7d, + 0xdd, 0xbd, 0xcb, 0x94, 0xa2, 0x35, 0xa3, 0xdb, 0xbf, 0xdb, 0x7b, 0x3b, + 0xfc, 0x59, 0x23, 0xd3 +}; +static const uint8_t ac_dsa_vect146_pub_val[] = { +/* Y */ + 0x47, 0xa9, 0x34, 0x0a, 0xc5, 0x13, 0x58, 0x5c, 0x83, 0xbb, 0x20, 0xa2, + 0xfb, 0xa9, 0x46, 0x97, 0x18, 0x11, 0x18, 0x4f, 0xd2, 0x00, 0x65, 0xfb, + 0x95, 0xcb, 0xb2, 0x06, 0x25, 0xb4, 0x7b, 0x21, 0x6f, 0x75, 0xe1, 0xf3, + 0xd8, 0x97, 0x97, 0xf5, 0x40, 0xa0, 0x48, 0x5c, 0xfb, 0xf0, 0x7b, 0x17, + 0x16, 0xa3, 0xec, 0xe7, 0x02, 0x7d, 0x86, 0xf4, 0x94, 0x0a, 0xb9, 0x0b, + 0xbf, 0xdd, 0x8e, 0xbf, 0x15, 0x13, 0x7b, 0xcf, 0x88, 0x05, 0xf9, 0x3c, + 0xea, 0x25, 0x9c, 0x4b, 0xea, 0x5a, 0x2d, 0x3b, 0xb3, 0xdd, 0xdf, 0x83, + 0xaa, 0x29, 0x0d, 0x35, 0x73, 0xe9, 0x1a, 0xa3, 0x00, 0xbb, 0xf1, 0xaf, + 0xb9, 0xb5, 0x25, 0x54, 0x2d, 0x67, 0xa8, 0xd8, 0x60, 0x51, 0xae, 0xd8, + 0xff, 0x8a, 0x2c, 0xfc, 0x22, 0x5a, 0x9e, 0x51, 0xeb, 0x37, 0x4c, 0x31, + 0xfe, 0x10, 0x3a, 0xe8, 0xf4, 0xa0, 0xc8, 0x91, 0x14, 0x21, 0xd2, 0x25, + 0xc0, 0x19, 0xe1, 0xb5, 0xc0, 0x7d, 0xc1, 0x49, 0xba, 0xbc, 0x26, 0xb7, + 0x08, 0xfc, 0x0f, 0xc0, 0xc1, 0x3c, 0x3b, 0x35, 0x39, 0x03, 0x17, 0xc4, + 0x09, 0xfa, 0xae, 0x81, 0xaa, 0xc9, 0xab, 0x5d, 0x01, 0xce, 0x85, 0xad, + 0xd2, 0x49, 0x17, 0xd9, 0x4c, 0xd1, 0xb2, 0x14, 0x1b, 0x63, 0x8d, 0xe3, + 0xa2, 0x53, 0xbf, 0xca, 0x6b, 0x7f, 0x1a, 0x81, 0x04, 0x51, 0x8d, 0x15, + 0x72, 0x21, 0x1b, 0xa5, 0x2d, 0xd1, 0x75, 0x63, 0x2c, 0x8f, 0x3f, 0x67, + 0x48, 0x26, 0x5a, 0x4b, 0xf6, 0xc2, 0xb8, 0x36, 0x3d, 0x98, 0x10, 0xba, + 0x1f, 0x1e, 0x58, 0x47, 0x94, 0xf6, 0x23, 0x19, 0xf0, 0x45, 0x1d, 0xa8, + 0x31, 0xd4, 0x57, 0xb5, 0x26, 0x9b, 0xbe, 0x67, 0x78, 0x4c, 0x47, 0x4f, + 0xff, 0xf6, 0x92, 0xbb, 0xe2, 0xba, 0xac, 0xa3, 0x2d, 0x3f, 0x85, 0xf4, + 0xfe, 0x39, 0xe0, 0x3f +}; +/* K = 5615520867828ae7dbc8e9b116e7661e18f09e5cdae17518ead1484f */ +static const uint8_t ac_dsa_vect146_out[] = { +/* R */ + 0x8a, 0x96, 0xc4, 0x19, 0xe0, 0xf3, 0x91, 0xda, 0xa2, 0x9f, 0xb1, 0x62, + 0xa1, 0xb9, 0x57, 0x0f, 0x48, 0xa0, 0x08, 0x10, 0xaa, 0x48, 0x0c, 0xde, + 0x0f, 0x27, 0xcf, 0xb0, +/* S */ + 0x02, 0x8e, 0xd9, 0x16, 0x55, 0x22, 0xfc, 0x59, 0xae, 0xeb, 0x79, 0xc4, + 0x91, 0xa9, 0x5e, 0xd8, 0x42, 0x7f, 0xd1, 0xb6, 0x95, 0xf3, 0xde, 0xdf, + 0x42, 0x28, 0xa3, 0x28 +}; +#define ac_dsa_vect147_prime ac_dsa_vect136_prime +#define ac_dsa_vect147_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect147_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect147_ptx[] = { +/* Msg */ + 0x2a, 0x07, 0xe2, 0x8f, 0xc1, 0x02, 0xdf, 0xe1, 0x7c, 0x79, 0xb9, 0x36, + 0x8e, 0x0b, 0xa9, 0x24, 0x14, 0xd2, 0xfc, 0xb4, 0x07, 0xd3, 0x4e, 0x90, + 0x3a, 0x0a, 0x53, 0x37, 0x0f, 0x7d, 0x2d, 0x33, 0xaa, 0x13, 0xc0, 0x2e, + 0x52, 0x75, 0x87, 0x71, 0x8c, 0x3b, 0x39, 0x66, 0x61, 0x25, 0xec, 0xa2, + 0xe8, 0xfd, 0x4c, 0x94, 0xb9, 0x86, 0x7f, 0xb6, 0xef, 0x16, 0xd5, 0x55, + 0x54, 0x9d, 0x8d, 0xd0, 0xf6, 0xe1, 0x04, 0x17, 0xeb, 0xec, 0xf4, 0x8f, + 0x99, 0x2a, 0xd8, 0x4b, 0x5d, 0x97, 0x74, 0x54, 0x07, 0x85, 0xdd, 0xcd, + 0x26, 0x4c, 0x55, 0x79, 0x6b, 0xc2, 0x16, 0x28, 0x98, 0xec, 0xef, 0x40, + 0x27, 0xc3, 0x41, 0x87, 0xf8, 0xc0, 0xb1, 0xc2, 0x0d, 0x4d, 0xaa, 0x10, + 0x8b, 0x70, 0xd7, 0x6c, 0x40, 0xdd, 0xbe, 0xbc, 0x1e, 0x0f, 0x50, 0xf4, + 0xdc, 0x90, 0x4d, 0xbf, 0xbe, 0x6b, 0xeb, 0x9d +}; +static const uint8_t ac_dsa_vect147_priv_val[] = { +/* X */ + 0x5f, 0x4f, 0x3c, 0x4f, 0x95, 0xef, 0xb9, 0x1c, 0x6b, 0x49, 0xf4, 0x3a, + 0xfb, 0xde, 0x6d, 0x0f, 0x9b, 0x5a, 0x13, 0x24, 0xb4, 0x92, 0x6f, 0x32, + 0x76, 0xbc, 0x91, 0x3e +}; +static const uint8_t ac_dsa_vect147_pub_val[] = { +/* Y */ + 0x05, 0xf2, 0x7e, 0xc0, 0x35, 0x62, 0x78, 0x60, 0xc3, 0x1a, 0xa5, 0x97, + 0xc9, 0x68, 0x37, 0x08, 0x46, 0x05, 0xf2, 0x70, 0xd1, 0x5a, 0x3f, 0xbb, + 0xdd, 0xa1, 0xc3, 0x85, 0x3d, 0xb2, 0xea, 0x6f, 0x6c, 0x9d, 0xe4, 0xe1, + 0x1a, 0x6f, 0xbd, 0x77, 0x3c, 0x30, 0x0e, 0xba, 0xd0, 0xf9, 0xdb, 0xc3, + 0x36, 0x08, 0xf9, 0xc4, 0xc5, 0xce, 0xde, 0xde, 0x0c, 0x26, 0x79, 0x1c, + 0xbe, 0xa3, 0x5a, 0xf0, 0x32, 0x2a, 0x60, 0x77, 0x39, 0xe9, 0x7c, 0x32, + 0x42, 0xf0, 0xae, 0x7d, 0x36, 0xaf, 0xe2, 0x69, 0xaa, 0xe6, 0x4b, 0x5f, + 0xb2, 0xdb, 0x26, 0x5c, 0xd7, 0x56, 0xce, 0xd4, 0x5d, 0x88, 0x8e, 0xaa, + 0xb0, 0x46, 0x5e, 0x50, 0x9a, 0xb7, 0xf8, 0x3d, 0x62, 0x3f, 0x69, 0xe7, + 0x3c, 0xdc, 0x0c, 0x76, 0x70, 0x67, 0x5c, 0xe0, 0xc2, 0x9f, 0x49, 0xa1, + 0x9d, 0x70, 0x38, 0x62, 0x3b, 0xde, 0x36, 0xe2, 0x9f, 0xb8, 0x54, 0xe6, + 0xfe, 0x6f, 0xfd, 0xb9, 0x16, 0xab, 0xb7, 0xd6, 0x1f, 0xab, 0x4b, 0x62, + 0x0d, 0xc7, 0x39, 0xa5, 0xcb, 0xd9, 0x60, 0x8a, 0x45, 0xe8, 0x6c, 0x2b, + 0xbf, 0xb4, 0x1b, 0x86, 0x99, 0x16, 0x68, 0x22, 0xe8, 0x32, 0xbb, 0x6c, + 0xac, 0x66, 0xe0, 0x04, 0xe9, 0x3d, 0x19, 0x0b, 0x95, 0x14, 0x24, 0xed, + 0xaf, 0x34, 0xbf, 0x6b, 0xd3, 0x43, 0xbf, 0x60, 0x15, 0x4f, 0x73, 0x9c, + 0x43, 0x56, 0x2b, 0x03, 0xae, 0xb4, 0xd2, 0x3d, 0xe1, 0xf7, 0x6c, 0x18, + 0xf7, 0x4b, 0x5f, 0x7a, 0x73, 0xc8, 0x05, 0xb2, 0x2a, 0xf8, 0xcc, 0x6b, + 0xdc, 0x9b, 0x55, 0x77, 0x9c, 0xcf, 0x6d, 0x44, 0x1c, 0xfd, 0x31, 0x54, + 0x61, 0x6c, 0xda, 0x18, 0x80, 0x7a, 0x9f, 0x5e, 0x2d, 0x76, 0x59, 0xe9, + 0xe2, 0x13, 0x29, 0x75, 0x51, 0x57, 0xda, 0xbc, 0x62, 0x2b, 0xd1, 0xae, + 0x2d, 0x50, 0x97, 0xc6 +}; +/* K = 97861b777e2a8cffc4c2d24e2df9eedf0b65ea2c9373c1085ba44efb */ +static const uint8_t ac_dsa_vect147_out[] = { +/* R */ + 0x91, 0xa4, 0x57, 0x69, 0x31, 0xed, 0x62, 0x1a, 0x03, 0x42, 0xf1, 0x4e, + 0xe2, 0xba, 0x8f, 0xa8, 0xe1, 0xbb, 0xdf, 0x89, 0x4c, 0x12, 0x51, 0xaf, + 0xdf, 0x72, 0x14, 0x6f, +/* S */ + 0x56, 0x75, 0x5c, 0xa1, 0x63, 0xf7, 0xdc, 0x89, 0x45, 0x8a, 0x7a, 0x75, + 0xd4, 0xdd, 0x3c, 0xe3, 0xad, 0xec, 0x42, 0xb4, 0xaa, 0x7d, 0x04, 0xb2, + 0x85, 0x8c, 0x47, 0xf6 +}; +#define ac_dsa_vect148_prime ac_dsa_vect136_prime +#define ac_dsa_vect148_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect148_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect148_ptx[] = { +/* Msg */ + 0x7e, 0x96, 0x38, 0x58, 0x16, 0xc9, 0x7b, 0xd9, 0xde, 0x81, 0xde, 0x30, + 0xe6, 0x7d, 0xb7, 0x24, 0x36, 0xfb, 0x42, 0xfa, 0xa9, 0xb6, 0xcc, 0xfe, + 0xab, 0x1f, 0xa5, 0x28, 0xc6, 0x9e, 0x63, 0x51, 0xb2, 0x01, 0x2a, 0x10, + 0x97, 0xfb, 0x86, 0xd8, 0xc5, 0xcc, 0x60, 0x25, 0x6e, 0xf1, 0x1b, 0xe1, + 0x8f, 0x16, 0x13, 0x76, 0x17, 0xf8, 0xcd, 0xd2, 0x9e, 0x3b, 0xab, 0x94, + 0x68, 0xc1, 0x2a, 0xe3, 0x43, 0x36, 0xba, 0x0e, 0x0e, 0xb6, 0xc8, 0x28, + 0x17, 0x7d, 0x1d, 0x55, 0xb0, 0x66, 0x98, 0xdd, 0xf7, 0x53, 0x75, 0x6a, + 0xf8, 0x30, 0xa1, 0x0c, 0xe9, 0xc9, 0x9f, 0x1d, 0x13, 0x68, 0x26, 0x68, + 0xe3, 0xeb, 0x33, 0x6a, 0x80, 0x61, 0x8e, 0x66, 0x62, 0x80, 0x09, 0x64, + 0x17, 0xc1, 0xe2, 0xb0, 0x05, 0xb9, 0x35, 0x1f, 0x5e, 0xa3, 0x06, 0xb8, + 0xc6, 0x3f, 0xd1, 0x84, 0xa5, 0x91, 0x32, 0xb5 +}; +static const uint8_t ac_dsa_vect148_priv_val[] = { +/* X */ + 0x91, 0x4e, 0x5d, 0x6d, 0x95, 0xec, 0x12, 0x44, 0x3f, 0x73, 0xc1, 0x27, + 0xb7, 0x97, 0x22, 0x95, 0x44, 0x97, 0x11, 0x77, 0xf6, 0x45, 0xb8, 0xda, + 0xc5, 0xf6, 0x91, 0x1d +}; +static const uint8_t ac_dsa_vect148_pub_val[] = { +/* Y */ + 0x2b, 0x69, 0xbf, 0x21, 0xbf, 0x68, 0x9a, 0x1f, 0x5e, 0xd7, 0x09, 0x6b, + 0x27, 0xe4, 0x47, 0xc1, 0xd5, 0x2f, 0xc2, 0x47, 0x3e, 0x9e, 0x43, 0x53, + 0xdb, 0xf1, 0x85, 0x63, 0x20, 0x22, 0xfc, 0x60, 0x5c, 0xef, 0xe5, 0x48, + 0x91, 0x02, 0xf7, 0xcb, 0xe9, 0x84, 0xf0, 0x0c, 0x1a, 0xb3, 0x2f, 0x2d, + 0xef, 0x1a, 0x84, 0xf1, 0xbe, 0xdd, 0xdb, 0xc1, 0x5f, 0x87, 0xae, 0xd0, + 0xa2, 0xb1, 0xe9, 0x12, 0xe9, 0xed, 0xd7, 0x4e, 0xdb, 0xe2, 0xc1, 0x5a, + 0x4c, 0x37, 0x53, 0x30, 0x14, 0xb9, 0xd3, 0x2b, 0x05, 0xf5, 0xa4, 0x4d, + 0x32, 0x3d, 0xef, 0x1c, 0xeb, 0xae, 0x0e, 0x21, 0x6b, 0xc3, 0x5a, 0x1c, + 0xa8, 0xa4, 0x26, 0x5c, 0x3d, 0xb5, 0x57, 0x4e, 0xb2, 0x3e, 0x17, 0xf1, + 0x83, 0x8e, 0x22, 0x5e, 0x46, 0x7a, 0x94, 0x26, 0xe8, 0x79, 0x8c, 0x5a, + 0x2e, 0x89, 0x65, 0x36, 0xc4, 0x8c, 0x4e, 0x24, 0xcd, 0x2e, 0xe9, 0xda, + 0x1b, 0x61, 0xae, 0xd2, 0xe2, 0x5b, 0x98, 0xe4, 0xc1, 0xf4, 0xee, 0x55, + 0xe0, 0xb4, 0x70, 0x5f, 0xeb, 0x2b, 0xb1, 0x69, 0x4c, 0xb1, 0x8a, 0x64, + 0x14, 0xbc, 0xdc, 0x1a, 0x74, 0x89, 0xb4, 0xbf, 0x89, 0x67, 0x98, 0x54, + 0x89, 0x31, 0x6b, 0x3e, 0x57, 0xea, 0x28, 0x12, 0x04, 0xce, 0xd3, 0xed, + 0x88, 0xad, 0x1b, 0x20, 0x7b, 0xe7, 0xd2, 0x94, 0x12, 0x7b, 0xca, 0x86, + 0xa9, 0xb8, 0x61, 0xcc, 0xca, 0x19, 0x2c, 0x15, 0xc8, 0x15, 0xe2, 0x32, + 0x8c, 0xbd, 0xaa, 0x58, 0x99, 0xc9, 0xdd, 0x27, 0x1f, 0xcd, 0x6e, 0xea, + 0x0d, 0x2a, 0xb0, 0x09, 0xa8, 0xba, 0x00, 0x1e, 0x67, 0x25, 0x13, 0x9b, + 0xe2, 0x6c, 0x51, 0x51, 0x87, 0x5c, 0xdc, 0xa7, 0xf9, 0x14, 0x34, 0x44, + 0x3b, 0x9e, 0x5e, 0x47, 0xa4, 0x5c, 0xdc, 0x8b, 0x73, 0x99, 0xbc, 0x5e, + 0x8b, 0xed, 0x93, 0x00 +}; +/* K = 7d00160fa1ebb10b0465321748eba9ca6e1b3b5216c0c51dc34b98f7 */ +static const uint8_t ac_dsa_vect148_out[] = { +/* R */ + 0x1b, 0xca, 0xa2, 0xca, 0xf4, 0x83, 0xab, 0xc8, 0x0b, 0x75, 0xf6, 0x70, + 0x25, 0x2f, 0xaa, 0x2a, 0x8e, 0x18, 0xc3, 0x23, 0x01, 0xba, 0x6f, 0xc0, + 0x6f, 0x37, 0xc0, 0x8e, +/* S */ + 0x90, 0x9a, 0x78, 0x52, 0xb8, 0xd5, 0xc8, 0x81, 0x3e, 0x17, 0xc0, 0x40, + 0x77, 0x9a, 0xd0, 0xdc, 0x5e, 0x9e, 0x05, 0x56, 0x61, 0x20, 0x56, 0x83, + 0x5e, 0x68, 0xd2, 0xb8 +}; +#define ac_dsa_vect149_prime ac_dsa_vect136_prime +#define ac_dsa_vect149_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect149_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect149_ptx[] = { +/* Msg */ + 0x24, 0xed, 0x7a, 0x16, 0x78, 0x2b, 0x5c, 0x34, 0xbe, 0xb5, 0x8b, 0xab, + 0x6a, 0x7d, 0x20, 0x28, 0x71, 0x9f, 0x97, 0x38, 0xe5, 0xd1, 0xba, 0x69, + 0x78, 0xef, 0xac, 0x4b, 0x53, 0xb3, 0x7c, 0x88, 0xe7, 0xea, 0x02, 0xe0, + 0xcf, 0x0f, 0xd8, 0x2a, 0x3e, 0x50, 0x04, 0x60, 0x52, 0xa9, 0x04, 0x95, + 0x41, 0xd1, 0x29, 0x93, 0x25, 0x4a, 0x46, 0xfe, 0x40, 0x1f, 0x40, 0x2d, + 0x38, 0x94, 0x3e, 0x94, 0x91, 0x8b, 0xf7, 0xa6, 0xfe, 0xcb, 0x08, 0xed, + 0x13, 0x09, 0xb7, 0xb0, 0xf2, 0x18, 0x59, 0x67, 0xef, 0x28, 0x9a, 0x2e, + 0xfa, 0x6c, 0x2e, 0x37, 0xa7, 0x4d, 0x65, 0x92, 0xa2, 0xeb, 0x74, 0x01, + 0xca, 0x5e, 0x98, 0xbb, 0x86, 0x45, 0xa9, 0x4e, 0x57, 0x49, 0x9d, 0x36, + 0x2e, 0x0f, 0x31, 0x33, 0xef, 0x33, 0x6e, 0x11, 0x95, 0x61, 0xce, 0xe1, + 0xb5, 0x58, 0xc1, 0x55, 0x08, 0x78, 0x18, 0x68 +}; +static const uint8_t ac_dsa_vect149_priv_val[] = { +/* X */ + 0x3a, 0x42, 0xf9, 0x92, 0x7b, 0x4e, 0xb3, 0x9e, 0xe3, 0xa9, 0x10, 0xe4, + 0x41, 0x89, 0x87, 0xd1, 0xaf, 0x1f, 0xfc, 0x1f, 0x3d, 0x5d, 0xf0, 0xc4, + 0x92, 0x0e, 0x05, 0xd0 +}; +static const uint8_t ac_dsa_vect149_pub_val[] = { +/* Y */ + 0x9d, 0xcc, 0xc1, 0x37, 0x19, 0x7b, 0xb2, 0x98, 0x24, 0xb1, 0xc1, 0x0e, + 0x9e, 0x8d, 0xed, 0xd7, 0x14, 0xef, 0xc9, 0x36, 0xcf, 0xf8, 0x3f, 0x42, + 0x63, 0x4d, 0x64, 0x39, 0x1f, 0x9b, 0x7f, 0x4f, 0xc3, 0xa2, 0x31, 0x95, + 0x4a, 0x8c, 0x3b, 0xfe, 0x4a, 0xe0, 0xf8, 0x22, 0x25, 0xfd, 0x52, 0xb5, + 0xdd, 0xe6, 0xdc, 0xd1, 0x4c, 0x0c, 0xe5, 0x08, 0x59, 0x71, 0xc5, 0x15, + 0xda, 0x38, 0x18, 0x34, 0x27, 0xc7, 0xe2, 0xa8, 0xd7, 0x6e, 0x40, 0xef, + 0xb6, 0x71, 0xaf, 0x79, 0x7e, 0x0c, 0x57, 0x6e, 0x38, 0x81, 0xd4, 0x34, + 0xca, 0x80, 0x9d, 0xd5, 0x53, 0xcc, 0xb0, 0xf7, 0xcd, 0x9f, 0x73, 0xc7, + 0xae, 0xa2, 0x26, 0x8f, 0x36, 0xc8, 0x41, 0x70, 0xab, 0x0a, 0xe0, 0x3b, + 0x2b, 0x46, 0xa2, 0x19, 0x54, 0x75, 0x64, 0xfd, 0x21, 0xc5, 0x40, 0xb1, + 0x60, 0x3a, 0xd7, 0x30, 0x6d, 0x22, 0xa9, 0xeb, 0x8e, 0xf3, 0x7c, 0xa0, + 0x8c, 0x2b, 0x28, 0xd1, 0x6c, 0x5b, 0x9c, 0x54, 0xa3, 0x28, 0xeb, 0xb3, + 0xc0, 0xf9, 0x50, 0x50, 0x95, 0xc6, 0x12, 0x27, 0x0d, 0x52, 0x63, 0x7c, + 0xb5, 0x58, 0x4e, 0xd0, 0x8b, 0xad, 0x71, 0x38, 0xd3, 0x38, 0x8c, 0x63, + 0x4b, 0x65, 0x02, 0xfa, 0x64, 0x73, 0xa2, 0xf5, 0x94, 0x04, 0x0b, 0x9a, + 0xcc, 0x14, 0x80, 0xb3, 0x43, 0xd2, 0x28, 0x7f, 0xdc, 0x70, 0xd1, 0x6b, + 0xa1, 0x4b, 0x1c, 0x21, 0x17, 0x61, 0x2d, 0xcc, 0x58, 0x60, 0xdb, 0xef, + 0x83, 0x87, 0xaf, 0x9a, 0xa5, 0xe1, 0x62, 0x1d, 0x37, 0xa3, 0x8f, 0x6c, + 0xbe, 0x59, 0x35, 0x67, 0x3e, 0xa3, 0xcb, 0xcd, 0xe4, 0xf3, 0x2a, 0x24, + 0x9e, 0xb6, 0xa5, 0xee, 0xd4, 0x1c, 0xfd, 0xca, 0xa4, 0xc8, 0x7e, 0x8b, + 0xca, 0xba, 0xa6, 0xbd, 0x1f, 0xe5, 0xa8, 0x79, 0xd1, 0x7e, 0x9a, 0xe3, + 0x58, 0x37, 0xce, 0x0f +}; +/* K = 23dda49474ec6cd13e1b0249ab24f50e9d69e40c6b5c07430780c44f */ +static const uint8_t ac_dsa_vect149_out[] = { +/* R */ + 0x5f, 0x4f, 0x54, 0x49, 0xb8, 0xd0, 0xdd, 0xa3, 0xac, 0x59, 0x0b, 0xa1, + 0x64, 0x0d, 0xf9, 0x77, 0x2f, 0xf0, 0x8c, 0xec, 0x08, 0x52, 0x8b, 0xc2, + 0xd7, 0x0d, 0x7a, 0xc9, +/* S */ + 0x5b, 0xea, 0x04, 0xbf, 0xd3, 0x32, 0x48, 0xf2, 0x6a, 0xee, 0x98, 0xca, + 0x85, 0x96, 0x77, 0x4e, 0x95, 0xce, 0x68, 0x54, 0x65, 0x17, 0x4d, 0x1c, + 0xae, 0xd7, 0xd9, 0x20 +}; +#define ac_dsa_vect150_prime ac_dsa_vect136_prime +#define ac_dsa_vect150_sub_prime ac_dsa_vect136_sub_prime +#define ac_dsa_vect150_base ac_dsa_vect136_base +static const uint8_t ac_dsa_vect150_ptx[] = { +/* Msg */ + 0x49, 0x06, 0xdb, 0xdd, 0x9d, 0xa6, 0xdd, 0xff, 0xa1, 0x52, 0xfa, 0x2e, + 0x25, 0x0e, 0xea, 0xd3, 0xc6, 0xef, 0x70, 0x83, 0x87, 0xa3, 0xad, 0x64, + 0xd3, 0x4a, 0x0e, 0x05, 0x74, 0x59, 0x47, 0x1f, 0x48, 0x75, 0x2f, 0xde, + 0x07, 0x86, 0xdb, 0x28, 0xa4, 0xbb, 0xf5, 0x81, 0x14, 0xd8, 0xdc, 0x91, + 0xb6, 0x9e, 0x56, 0xbe, 0x3c, 0x49, 0xec, 0x1b, 0x98, 0x80, 0xd9, 0x91, + 0x7c, 0x73, 0xab, 0xc8, 0x95, 0x75, 0x4a, 0x60, 0x77, 0x9b, 0x18, 0xbc, + 0x95, 0x15, 0x50, 0xb9, 0x57, 0xa7, 0x7c, 0x8c, 0xef, 0xa1, 0x59, 0x90, + 0x81, 0x26, 0xcc, 0x80, 0x1c, 0x66, 0x5d, 0x1b, 0x01, 0x10, 0x9b, 0xa6, + 0x04, 0xbb, 0x9e, 0x79, 0x7c, 0x7a, 0x37, 0x66, 0x0b, 0xfc, 0x05, 0x93, + 0xba, 0xb0, 0x92, 0x4d, 0xf5, 0x80, 0x6c, 0xa8, 0x03, 0x38, 0x1b, 0x24, + 0xb0, 0x3d, 0xe3, 0xd0, 0x3b, 0x48, 0x4d, 0x49 +}; +static const uint8_t ac_dsa_vect150_priv_val[] = { +/* X */ + 0x0c, 0x53, 0xe5, 0x31, 0x1c, 0x10, 0x4f, 0x11, 0xf6, 0xeb, 0xa6, 0x46, + 0xe4, 0x84, 0x0d, 0x19, 0x60, 0xa9, 0x21, 0x18, 0x20, 0x4a, 0x49, 0xe3, + 0xec, 0x8d, 0xde, 0xc4 +}; +static const uint8_t ac_dsa_vect150_pub_val[] = { +/* Y */ + 0x07, 0x2c, 0xb5, 0x61, 0x25, 0x96, 0xaa, 0x71, 0x61, 0x42, 0xf5, 0xf7, + 0x56, 0xc9, 0x54, 0x20, 0x13, 0xf3, 0xf1, 0x62, 0x8c, 0xfc, 0x54, 0x97, + 0xeb, 0x1b, 0xa0, 0xaa, 0x51, 0xbd, 0x5a, 0xdb, 0x8e, 0xb8, 0xad, 0xfe, + 0x05, 0x9c, 0x0e, 0x08, 0x82, 0xe3, 0xc0, 0x9a, 0x17, 0xd1, 0xf5, 0x1a, + 0xcc, 0xb6, 0x87, 0xb2, 0x43, 0xfd, 0x30, 0x52, 0xbb, 0xcb, 0x81, 0xb0, + 0x63, 0xc1, 0xe7, 0xd5, 0xbe, 0x06, 0x65, 0x87, 0xeb, 0xca, 0x07, 0x80, + 0x06, 0xf6, 0xd6, 0xee, 0x71, 0xa6, 0x9e, 0xf5, 0x9b, 0x63, 0x65, 0xcb, + 0xcf, 0x64, 0xd4, 0xcf, 0x1b, 0x92, 0x99, 0xe7, 0x40, 0x30, 0x09, 0x27, + 0x20, 0x26, 0xfc, 0x16, 0x65, 0xed, 0x40, 0x3a, 0xb8, 0xde, 0xe4, 0x0e, + 0xea, 0x4e, 0xe7, 0xd5, 0x62, 0xaf, 0x00, 0x19, 0x51, 0x92, 0x6d, 0xc8, + 0xbf, 0x0c, 0x78, 0x39, 0x84, 0x66, 0x4f, 0xfe, 0xf6, 0x29, 0xcb, 0x59, + 0xd7, 0x09, 0xb3, 0xd9, 0xaa, 0x06, 0x80, 0x5d, 0x62, 0xaf, 0xd7, 0x94, + 0x54, 0x1a, 0x2b, 0x4c, 0xe0, 0xc5, 0x90, 0x43, 0xac, 0xf7, 0x3e, 0x18, + 0xe7, 0x44, 0x53, 0xe8, 0x6a, 0x08, 0x2f, 0x17, 0x91, 0x4b, 0xa6, 0xb2, + 0xb0, 0xfa, 0x80, 0xda, 0x83, 0x53, 0xc7, 0xed, 0x91, 0x62, 0x60, 0x95, + 0x75, 0xed, 0x41, 0xf8, 0xeb, 0x78, 0xdb, 0xaf, 0xaa, 0x7b, 0x51, 0x8d, + 0xe0, 0xc8, 0x5b, 0x17, 0x20, 0xe7, 0xf4, 0x93, 0xb9, 0x14, 0xd5, 0xa3, + 0xd2, 0xd0, 0x74, 0x82, 0x73, 0xd1, 0x69, 0xd5, 0x5c, 0x45, 0x55, 0x6b, + 0xca, 0xe6, 0x70, 0x57, 0x5c, 0x96, 0xa4, 0x44, 0xfc, 0x1d, 0x78, 0x9f, + 0x5b, 0xac, 0xfc, 0x8b, 0x24, 0x13, 0x2b, 0xfb, 0xd7, 0x5b, 0x30, 0x61, + 0xfb, 0xac, 0xf2, 0x93, 0x5a, 0x21, 0x9b, 0x0f, 0x2a, 0xc5, 0xdc, 0xad, + 0x71, 0x85, 0x16, 0xa9 +}; +/* K = 3523465a8417b3a05ba1032bf6c42511591f2830b55144f9662bf6c9 */ +static const uint8_t ac_dsa_vect150_out[] = { +/* R */ + 0x77, 0x47, 0x59, 0x00, 0xfc, 0x7f, 0x3e, 0x0b, 0x80, 0xf3, 0x88, 0x4a, + 0xf8, 0x60, 0x4e, 0xef, 0x60, 0xff, 0xe4, 0x84, 0xbc, 0x6c, 0xd3, 0xde, + 0x12, 0x3f, 0x79, 0x59, +/* S */ + 0x26, 0xca, 0x92, 0x7d, 0xa0, 0xd1, 0x0b, 0x43, 0xdc, 0x15, 0x21, 0xbf, + 0xeb, 0x58, 0xff, 0x34, 0x7e, 0xe1, 0x43, 0xfc, 0x38, 0xdb, 0x45, 0x1c, + 0x11, 0xa0, 0x35, 0x10 +}; +/* [mod = L=2048, N=256, SHA-1] */ +static const uint8_t ac_dsa_vect151_prime[] = { +/* P */ + 0xc1, 0xa5, 0x9d, 0x21, 0x55, 0x73, 0x94, 0x9e, 0x0b, 0x20, 0xa9, 0x74, + 0xc2, 0xed, 0xf2, 0xe3, 0x13, 0x7f, 0xf2, 0x46, 0x30, 0x62, 0xf7, 0x5f, + 0x1d, 0x13, 0xdf, 0x12, 0xab, 0xa1, 0x07, 0x6b, 0xb2, 0xd0, 0x13, 0x40, + 0x2b, 0x60, 0xaf, 0x6c, 0x18, 0x7f, 0xb0, 0xfa, 0x36, 0x21, 0x67, 0xc9, + 0x76, 0xc2, 0x61, 0x7c, 0x72, 0x6f, 0x90, 0x77, 0xf0, 0x9e, 0x18, 0xc1, + 0x1b, 0x60, 0xf6, 0x50, 0x08, 0x82, 0x5b, 0xd6, 0xc0, 0x2a, 0x1f, 0x57, + 0xd3, 0xeb, 0x0a, 0xd4, 0x1c, 0xd5, 0x47, 0xde, 0x43, 0xd8, 0x7f, 0x25, + 0x25, 0xf9, 0x71, 0xd4, 0x2b, 0x30, 0x65, 0x06, 0xe7, 0xca, 0x03, 0xbe, + 0x63, 0xb3, 0x5f, 0x4a, 0xda, 0x17, 0x2d, 0x0a, 0x06, 0x92, 0x44, 0x40, + 0xa1, 0x42, 0x50, 0xd7, 0x82, 0x2a, 0xc2, 0xd5, 0xae, 0xaf, 0xed, 0x46, + 0x19, 0xe7, 0x9d, 0x41, 0x58, 0xa7, 0xd5, 0xeb, 0x2d, 0x9f, 0x02, 0x3d, + 0xb1, 0x81, 0xa8, 0xf0, 0x94, 0xb2, 0xc6, 0xcb, 0x87, 0xcb, 0x85, 0x35, + 0x41, 0x6a, 0xc1, 0x98, 0x13, 0xf0, 0x71, 0x44, 0x66, 0x0c, 0x55, 0x77, + 0x45, 0xf4, 0x4a, 0x01, 0xc6, 0xb1, 0x02, 0x90, 0x92, 0xc1, 0x29, 0xb0, + 0xd2, 0x71, 0x83, 0xe8, 0x2c, 0x5a, 0x21, 0xa8, 0x01, 0x77, 0xee, 0x74, + 0x76, 0xeb, 0x95, 0xc4, 0x66, 0xfb, 0x47, 0x2b, 0xd3, 0xd2, 0xdc, 0x28, + 0x6c, 0xe2, 0x58, 0x47, 0xe9, 0x3c, 0xbf, 0xa9, 0xad, 0x39, 0xcc, 0x57, + 0x03, 0x5d, 0x0c, 0x7b, 0x64, 0xb9, 0x26, 0xa9, 0xc7, 0xf5, 0xa7, 0xb2, + 0xbc, 0x5a, 0xbc, 0xbf, 0xbd, 0xc0, 0xb0, 0xe3, 0xfe, 0xde, 0x3c, 0x1e, + 0x02, 0xc4, 0x4a, 0xfc, 0x8a, 0xef, 0xc7, 0x95, 0x7d, 0xa0, 0x7a, 0x0e, + 0x5f, 0xd1, 0x23, 0x39, 0xdb, 0x86, 0x67, 0x61, 0x6f, 0x62, 0x28, 0x6d, + 0xf8, 0x0d, 0x58, 0xab +}; +static const uint8_t ac_dsa_vect151_sub_prime[] = { +/* Q */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0xd6, 0x2c, 0x65, 0xe8, 0xb8, 0x7c, 0x89, 0x79, 0x7f, 0x8f, 0x0c, + 0xbf, 0xa5, 0x5e, 0x4a, 0x68, 0x10, 0xe2, 0xc7 +}; +static const uint8_t ac_dsa_vect151_base[] = { +/* G */ + 0xae, 0xa5, 0x87, 0x87, 0x40, 0xf1, 0x42, 0x4d, 0x3c, 0x6e, 0xa9, 0xc6, + 0xb4, 0x79, 0x96, 0x15, 0xd2, 0x74, 0x92, 0x98, 0xa1, 0x7e, 0x26, 0x20, + 0x7f, 0x76, 0xce, 0xf3, 0x40, 0xdd, 0xd3, 0x90, 0xe1, 0xb1, 0xad, 0x6b, + 0x6c, 0x00, 0x10, 0xad, 0x01, 0x5a, 0x10, 0x33, 0x42, 0xdd, 0xd4, 0x52, + 0xca, 0xc0, 0x24, 0xb3, 0x6e, 0x42, 0xd9, 0xb8, 0xed, 0x52, 0xfa, 0xfa, + 0xe7, 0xa1, 0xd3, 0xce, 0x9e, 0x4b, 0x21, 0xf9, 0x10, 0xd1, 0x35, 0x6e, + 0xb1, 0x63, 0xa3, 0xe5, 0xa8, 0x18, 0x4c, 0x78, 0x1b, 0xf1, 0x44, 0x92, + 0xaf, 0xa2, 0xe4, 0xb0, 0xa5, 0x6d, 0x88, 0x84, 0xfd, 0x01, 0xa6, 0x28, + 0xb9, 0x66, 0x27, 0x39, 0xc4, 0x2e, 0x5c, 0x57, 0x95, 0xad, 0xe2, 0xf5, + 0xf2, 0x7e, 0x6d, 0xe1, 0xd9, 0x63, 0x91, 0x7c, 0xe8, 0x80, 0x6f, 0xc4, + 0x0d, 0x02, 0x1c, 0xd8, 0x7a, 0xa3, 0xaa, 0x3a, 0x9e, 0x4f, 0x0c, 0x2c, + 0x4c, 0x45, 0xd2, 0x95, 0x9b, 0x25, 0x78, 0xb2, 0xfb, 0x1a, 0x22, 0x29, + 0xc3, 0x7e, 0x18, 0x10, 0x59, 0xb9, 0xd5, 0xe7, 0xb7, 0x86, 0x2f, 0xa8, + 0x2e, 0x23, 0x77, 0xa4, 0x9e, 0xd0, 0xf9, 0xdc, 0xa8, 0x20, 0xa5, 0x81, + 0x40, 0x79, 0xdd, 0x66, 0x10, 0x71, 0x4e, 0xfa, 0xf8, 0xb0, 0xcc, 0x68, + 0x3d, 0x8e, 0x72, 0xe4, 0xc8, 0x84, 0xe6, 0xf9, 0xd4, 0x94, 0x6b, 0x3e, + 0x8d, 0x4c, 0xbb, 0x92, 0xad, 0xbb, 0xe7, 0xd4, 0xc4, 0x7c, 0xc3, 0x0b, + 0xe7, 0xf8, 0xc3, 0x7c, 0xa8, 0x18, 0x83, 0xa1, 0xaa, 0xc6, 0x86, 0x00, + 0x59, 0xff, 0x46, 0x40, 0xa2, 0x9c, 0xca, 0xe7, 0x3d, 0xe2, 0x0b, 0x12, + 0xe6, 0x3b, 0x00, 0xa8, 0x8b, 0x2e, 0xe9, 0xba, 0x94, 0xb7, 0x5e, 0xb4, + 0x0a, 0x65, 0x6e, 0x15, 0xd9, 0xec, 0x83, 0x73, 0x1c, 0x85, 0xd0, 0xef, + 0xfc, 0xb9, 0xef, 0x9f +}; +static const uint8_t ac_dsa_vect151_ptx[] = { +/* Msg */ + 0xde, 0x36, 0x05, 0xdb, 0xef, 0xde, 0x35, 0x3c, 0xbe, 0x05, 0xe0, 0xd6, + 0x09, 0x86, 0x47, 0xb6, 0xd0, 0x41, 0x46, 0x0d, 0xfd, 0x4c, 0x00, 0x03, + 0x12, 0xbe, 0x1a, 0xfe, 0x75, 0x51, 0xfd, 0x3b, 0x93, 0xfe, 0xd7, 0x6a, + 0x97, 0x63, 0xc3, 0x4e, 0x00, 0x45, 0x64, 0xb8, 0xf7, 0xdc, 0xac, 0xbd, + 0x99, 0xe8, 0x50, 0x30, 0x63, 0x2c, 0x94, 0xe9, 0xb0, 0xa0, 0x32, 0x04, + 0x65, 0x23, 0xb7, 0xaa, 0xcd, 0xf9, 0x34, 0xa2, 0xdb, 0xbd, 0xcf, 0xce, + 0xef, 0xe6, 0x6b, 0x4e, 0x3d, 0x1c, 0xb2, 0x9e, 0x99, 0x4f, 0xf3, 0xa4, + 0x64, 0x8a, 0x8e, 0xdd, 0x9d, 0x58, 0xed, 0x71, 0xf1, 0x23, 0x99, 0xd9, + 0x06, 0x24, 0x78, 0x9c, 0x4e, 0x0e, 0xeb, 0xb0, 0xfb, 0xd5, 0x08, 0x0f, + 0x7d, 0x73, 0x0f, 0x87, 0x5a, 0x1f, 0x29, 0x07, 0x49, 0x33, 0x4c, 0xb4, + 0x05, 0xe9, 0xfd, 0x2a, 0xe1, 0xb4, 0xed, 0x65 +}; +static const uint8_t ac_dsa_vect151_priv_val[] = { +/* X */ + 0x5a, 0x42, 0xe7, 0x72, 0x48, 0x35, 0x8f, 0x06, 0xae, 0x98, 0x0a, 0x2c, + 0x64, 0xf6, 0xa2, 0x2b, 0xea, 0x2b, 0xf7, 0xb4, 0xfc, 0x00, 0x15, 0x74, + 0x50, 0x53, 0xc4, 0x32, 0xb7, 0x13, 0x2a, 0x67 +}; +static const uint8_t ac_dsa_vect151_pub_val[] = { +/* Y */ + 0x88, 0x0e, 0x17, 0xc4, 0xae, 0x81, 0x41, 0x75, 0x06, 0x09, 0xd8, 0x25, + 0x1c, 0x0b, 0xbd, 0x7a, 0xcf, 0x6d, 0x0b, 0x46, 0x0e, 0xd3, 0x68, 0x8e, + 0x9a, 0x5f, 0x99, 0x0e, 0x6c, 0x4b, 0x5b, 0x00, 0x87, 0x5d, 0xa7, 0x50, + 0xe0, 0x22, 0x8a, 0x04, 0x10, 0x2a, 0x35, 0xf5, 0x7e, 0x74, 0xb8, 0xd2, + 0xf9, 0xb6, 0x95, 0x0f, 0x0d, 0x1d, 0xb8, 0xd3, 0x02, 0xc5, 0xc9, 0x0a, + 0x5b, 0x87, 0x86, 0xa8, 0x2c, 0x68, 0xff, 0x5b, 0x17, 0xa5, 0x7a, 0x75, + 0x84, 0x96, 0xc5, 0xf8, 0x05, 0x3e, 0x44, 0x84, 0xa2, 0x53, 0xd9, 0x94, + 0x22, 0x04, 0xd9, 0xa1, 0x10, 0x9f, 0x4b, 0xd2, 0xa3, 0xec, 0x31, 0x1a, + 0x60, 0xcf, 0x69, 0xc6, 0x85, 0xb5, 0x86, 0xd9, 0x86, 0xf5, 0x65, 0xd3, + 0x3d, 0xbf, 0x5a, 0xab, 0x70, 0x91, 0xe3, 0x1a, 0xa4, 0x10, 0x2c, 0x4f, + 0x4b, 0x53, 0xfb, 0xf8, 0x72, 0xd7, 0x00, 0x15, 0x64, 0x65, 0xb6, 0xc0, + 0x75, 0xe7, 0xf7, 0x78, 0x47, 0x1a, 0x23, 0x50, 0x2d, 0xc0, 0xfe, 0xe4, + 0x1b, 0x27, 0x1c, 0x83, 0x7a, 0x1c, 0x26, 0x69, 0x16, 0x99, 0xf3, 0x55, + 0x0d, 0x06, 0x0a, 0x33, 0x10, 0x99, 0xf6, 0x48, 0x37, 0xcd, 0xde, 0xc6, + 0x9c, 0xae, 0xbf, 0x51, 0xbf, 0x4e, 0xc9, 0xf3, 0x6f, 0x2a, 0x22, 0x0f, + 0xe7, 0x73, 0xcb, 0x4d, 0x3c, 0x02, 0xd0, 0x44, 0x6d, 0xdd, 0x46, 0x13, + 0x35, 0x32, 0xef, 0x1c, 0x3c, 0x69, 0xd4, 0x32, 0xe3, 0x03, 0x50, 0x2b, + 0xd0, 0x5a, 0x75, 0x27, 0x9a, 0x78, 0x09, 0xa7, 0x42, 0xac, 0x4a, 0x78, + 0x72, 0xb0, 0x7f, 0x19, 0x08, 0x65, 0x40, 0x49, 0x41, 0x93, 0x50, 0xe3, + 0x7a, 0x95, 0xf2, 0xef, 0x33, 0x36, 0x1d, 0x8d, 0x87, 0x36, 0xd4, 0x08, + 0x3d, 0xc1, 0x4c, 0x0b, 0xb9, 0x72, 0xe1, 0x4d, 0x4c, 0x7b, 0x97, 0xf3, + 0xdd, 0xfc, 0xca, 0xef +}; +/* K = 2cb9c1d617e127a4770d0a946fb947c5100ed0ca59454ea80479f6885ec10534 */ +static const uint8_t ac_dsa_vect151_out[] = { +/* R */ + 0x36, 0x3e, 0x01, 0xc5, 0x64, 0xf3, 0x80, 0xa2, 0x7d, 0x7d, 0x23, 0xb2, + 0x07, 0xaf, 0x3f, 0x96, 0x1d, 0x48, 0xfc, 0x09, 0x95, 0x48, 0x7f, 0x60, + 0x05, 0x27, 0x75, 0xd7, 0x24, 0xab, 0x3d, 0x10, +/* S */ + 0x49, 0x16, 0xd9, 0x1b, 0x29, 0x27, 0x29, 0x4e, 0x42, 0x9d, 0x53, 0x7c, + 0x06, 0xdd, 0x24, 0x63, 0xd1, 0x84, 0x50, 0x18, 0xcc, 0xa2, 0x87, 0x3e, + 0x90, 0xa6, 0xc8, 0x37, 0xb4, 0x45, 0xfd, 0xde +}; +#define ac_dsa_vect152_prime ac_dsa_vect151_prime +#define ac_dsa_vect152_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect152_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect152_ptx[] = { +/* Msg */ + 0x49, 0x70, 0x7b, 0x65, 0x5b, 0x6d, 0x16, 0x8c, 0x70, 0xba, 0xed, 0xe0, + 0x38, 0x66, 0xb0, 0xfb, 0xa6, 0x02, 0x39, 0xad, 0x4c, 0xf8, 0x2f, 0x53, + 0xb4, 0x6e, 0x11, 0xb2, 0x6f, 0xa8, 0xf6, 0x27, 0x6f, 0xf6, 0x68, 0x7d, + 0x09, 0xe8, 0xed, 0x1e, 0x5d, 0x96, 0x3c, 0x11, 0xe4, 0x76, 0x3b, 0x2e, + 0x59, 0xa0, 0x92, 0x7f, 0x01, 0xe8, 0xff, 0xfd, 0x18, 0x94, 0xa6, 0x26, + 0x23, 0x27, 0xc8, 0x4b, 0xbb, 0x42, 0x98, 0xd7, 0xd7, 0xfb, 0xca, 0x66, + 0x06, 0x73, 0x12, 0x8b, 0xb7, 0xde, 0xa4, 0x61, 0x78, 0x14, 0x64, 0x85, + 0x53, 0x9f, 0x9a, 0x8f, 0x88, 0xda, 0xc7, 0x61, 0xd0, 0xd5, 0xd4, 0x5c, + 0xb5, 0x57, 0xcd, 0xac, 0x96, 0x0b, 0xe2, 0x3d, 0xd9, 0x19, 0x9a, 0xcd, + 0x99, 0xcb, 0x64, 0xd1, 0xfe, 0xe2, 0xca, 0x68, 0xe4, 0x23, 0x46, 0x1a, + 0x02, 0xab, 0xb3, 0x4c, 0x1d, 0xc4, 0x50, 0x11 +}; +static const uint8_t ac_dsa_vect152_priv_val[] = { +/* X */ + 0x62, 0x17, 0x7a, 0x5b, 0x2f, 0x0b, 0x44, 0x35, 0x2f, 0x64, 0x3a, 0x9e, + 0x69, 0xc1, 0xad, 0xb4, 0xa0, 0xb2, 0x92, 0xa5, 0xea, 0x52, 0xfa, 0x80, + 0x65, 0xe9, 0x4a, 0xd0, 0x43, 0xd4, 0x62, 0x18 +}; +static const uint8_t ac_dsa_vect152_pub_val[] = { +/* Y */ + 0x38, 0x53, 0x49, 0xec, 0xf9, 0x9c, 0xe7, 0x83, 0xd4, 0xe7, 0xa8, 0x0a, + 0x7d, 0xd2, 0xc5, 0x33, 0xa3, 0x62, 0x3c, 0x38, 0x26, 0x02, 0x43, 0xac, + 0x39, 0x2d, 0x4e, 0xab, 0x6d, 0xed, 0xa5, 0xb7, 0x9b, 0x8f, 0x91, 0x67, + 0x92, 0x2e, 0x8b, 0x60, 0x46, 0x86, 0x23, 0xe4, 0x60, 0x3f, 0xa7, 0x68, + 0x1f, 0x53, 0x5e, 0x20, 0xde, 0x67, 0x35, 0x31, 0x25, 0x5e, 0x10, 0x8f, + 0x54, 0x2a, 0x26, 0xd5, 0xc8, 0x7f, 0x19, 0xe0, 0x63, 0x37, 0x2d, 0x14, + 0x28, 0x69, 0xc5, 0xee, 0xf1, 0x32, 0x52, 0x81, 0xfe, 0xe7, 0xf1, 0xc7, + 0x4d, 0x2a, 0x96, 0x25, 0x5d, 0x42, 0x0f, 0x27, 0x13, 0x86, 0x4d, 0x55, + 0xd3, 0x6f, 0x81, 0x39, 0x19, 0x4f, 0x64, 0x3a, 0x6e, 0x98, 0xb5, 0xbf, + 0x97, 0x32, 0xc8, 0x59, 0x74, 0x45, 0xaf, 0x5a, 0x71, 0xe2, 0x3e, 0x2a, + 0xc5, 0xca, 0xe3, 0x60, 0x43, 0x23, 0xf7, 0xbf, 0x09, 0x44, 0x97, 0x86, + 0x97, 0x4e, 0xd5, 0x3a, 0x57, 0x17, 0xf9, 0xae, 0xc1, 0x4d, 0xd0, 0x1b, + 0xd1, 0xcf, 0x27, 0x6b, 0xf3, 0xc6, 0x3d, 0xec, 0x43, 0xc3, 0xec, 0x8e, + 0xa6, 0x55, 0x7d, 0xe4, 0x69, 0x91, 0x64, 0x12, 0xf0, 0x45, 0x6c, 0x90, + 0xf0, 0x12, 0x91, 0xbb, 0x71, 0x25, 0xe9, 0xf8, 0x55, 0xf4, 0x55, 0xb3, + 0x60, 0xc0, 0x3d, 0x4a, 0x7b, 0x4a, 0x8d, 0x40, 0x90, 0xe4, 0x7a, 0xaf, + 0x11, 0x11, 0xf3, 0x82, 0xdd, 0x26, 0x05, 0x73, 0x4f, 0xb5, 0x4f, 0x4b, + 0x8f, 0xfe, 0x23, 0xc9, 0xde, 0xd2, 0x90, 0x0b, 0x31, 0x21, 0xb4, 0x97, + 0xbd, 0x46, 0xd0, 0x45, 0x8a, 0x09, 0xa5, 0xdf, 0x4a, 0xa9, 0xcf, 0x1b, + 0xe9, 0x06, 0xf5, 0x54, 0x23, 0x13, 0x38, 0x4f, 0x93, 0xd3, 0x77, 0xba, + 0x9e, 0x0a, 0x76, 0x2b, 0x47, 0x93, 0x40, 0x3b, 0x91, 0x4e, 0x52, 0x86, + 0x5a, 0xfa, 0xbb, 0x67 +}; +/* K = 2bae4225836dcbbcad976ed47ecb5f3fc05439358791be244e74d2cf0617fc26 */ +static const uint8_t ac_dsa_vect152_out[] = { +/* R */ + 0x0f, 0xdc, 0x5a, 0x5a, 0x4a, 0x2c, 0x2f, 0x3d, 0xf5, 0x0c, 0x86, 0x83, + 0x83, 0xba, 0x80, 0x03, 0x96, 0xae, 0x25, 0x26, 0x5b, 0xe1, 0xa1, 0x47, + 0x62, 0xd3, 0x11, 0x0c, 0xbe, 0xb3, 0x48, 0x19, +/* S */ + 0x4b, 0x41, 0x84, 0x1c, 0xad, 0x45, 0xfe, 0xde, 0xa5, 0xaa, 0xd0, 0xa1, + 0x6b, 0x05, 0x3e, 0x88, 0x35, 0x3b, 0x6f, 0x01, 0x02, 0xdf, 0x74, 0xc9, + 0xfc, 0xe0, 0x9e, 0x38, 0xf5, 0xe6, 0xc2, 0x77 +}; +#define ac_dsa_vect153_prime ac_dsa_vect151_prime +#define ac_dsa_vect153_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect153_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect153_ptx[] = { +/* Msg */ + 0x76, 0x3c, 0x1f, 0x15, 0xc5, 0xdd, 0x8a, 0x93, 0xaa, 0xc4, 0xe0, 0x48, + 0x65, 0x1c, 0x4e, 0xa8, 0x4a, 0xf1, 0x8a, 0xee, 0x25, 0x5b, 0x56, 0x95, + 0x9e, 0xae, 0xb1, 0x87, 0x66, 0x99, 0xbe, 0x75, 0x27, 0x1a, 0xf0, 0xda, + 0x6c, 0x3c, 0xa9, 0x36, 0xe9, 0x9b, 0xe4, 0xff, 0x44, 0x36, 0x41, 0x0f, + 0x69, 0xae, 0x70, 0x18, 0xb6, 0xc8, 0x43, 0xdc, 0xe9, 0xd8, 0xb7, 0x1a, + 0x91, 0xef, 0xa5, 0x3c, 0x39, 0xbe, 0x55, 0xf2, 0x85, 0xfb, 0x8a, 0xd8, + 0x54, 0x39, 0x52, 0xfd, 0x3c, 0xa8, 0x92, 0x71, 0xec, 0x23, 0xd3, 0x42, + 0xcf, 0xd5, 0x57, 0xbf, 0xb7, 0x2d, 0xb4, 0x3b, 0x43, 0x4d, 0x0e, 0xd5, + 0xb3, 0x07, 0x63, 0x03, 0x77, 0x54, 0xbb, 0x0f, 0x78, 0x2a, 0xb0, 0x82, + 0x35, 0xa6, 0x4a, 0xbb, 0x7f, 0x0a, 0x82, 0x8f, 0x89, 0x2c, 0xde, 0x7e, + 0x05, 0xe3, 0x01, 0xda, 0x7c, 0x21, 0xc0, 0x96 +}; +static const uint8_t ac_dsa_vect153_priv_val[] = { +/* X */ + 0x5d, 0x16, 0x97, 0x61, 0xa3, 0x88, 0x7a, 0x9e, 0xca, 0x0f, 0x7e, 0x59, + 0xd7, 0x7b, 0x75, 0x67, 0x1a, 0xe0, 0x22, 0x10, 0x00, 0x6e, 0x75, 0x4b, + 0xf2, 0xf1, 0x20, 0x91, 0xfc, 0x32, 0x75, 0xb0 +}; +static const uint8_t ac_dsa_vect153_pub_val[] = { +/* Y */ + 0x0b, 0xec, 0xd9, 0x17, 0xee, 0xd0, 0xbe, 0x9c, 0xb5, 0x8f, 0xf9, 0xd2, + 0x59, 0xa8, 0xfa, 0x41, 0x5b, 0x81, 0x6d, 0xa4, 0xa2, 0x5d, 0x3f, 0x56, + 0x9d, 0x7b, 0x9f, 0x31, 0x7b, 0x3f, 0x47, 0xe4, 0x24, 0x4c, 0xde, 0xf3, + 0x57, 0x96, 0xfb, 0x45, 0x5c, 0x05, 0xc1, 0x56, 0x45, 0x2f, 0x1c, 0x86, + 0x60, 0xf5, 0x34, 0x6f, 0xba, 0x16, 0x92, 0x76, 0x22, 0x14, 0x46, 0xf8, + 0x2b, 0xbb, 0x20, 0x27, 0xb0, 0x56, 0xb5, 0x37, 0xcf, 0xd5, 0x9c, 0x57, + 0x29, 0x91, 0x66, 0xa6, 0xf2, 0x08, 0x71, 0xc7, 0x4e, 0x6c, 0x1d, 0x3f, + 0x5a, 0x37, 0xb7, 0x5e, 0x8d, 0xad, 0x6c, 0xad, 0xcf, 0x12, 0xc9, 0x09, + 0x58, 0x6a, 0x32, 0xf1, 0x50, 0xc6, 0x8e, 0x33, 0x23, 0x06, 0xab, 0xef, + 0x8b, 0xe1, 0xab, 0xd5, 0x6c, 0x42, 0xd3, 0xc3, 0x69, 0x36, 0xcf, 0x8f, + 0x2a, 0xca, 0xce, 0xb7, 0x07, 0x99, 0x4a, 0x3d, 0x4c, 0x05, 0x55, 0xa0, + 0x15, 0xde, 0x89, 0x20, 0x37, 0xaa, 0xc6, 0x8e, 0x33, 0x81, 0x3b, 0xf3, + 0x05, 0x0f, 0x0f, 0x3a, 0x8d, 0xf5, 0xe8, 0x14, 0x65, 0x85, 0x2f, 0x6a, + 0x19, 0x5e, 0xa6, 0x88, 0xac, 0x5d, 0x25, 0x8e, 0xee, 0x20, 0x76, 0xa6, + 0xb2, 0x36, 0x36, 0x2e, 0x3d, 0x79, 0x2e, 0x7f, 0x35, 0x8c, 0x6b, 0xa9, + 0x94, 0xda, 0x7a, 0x64, 0xb1, 0x82, 0x63, 0x96, 0x96, 0x55, 0x47, 0x3a, + 0xaa, 0x37, 0xcb, 0x3c, 0xfb, 0x00, 0xa2, 0x7f, 0x8f, 0xb2, 0x4a, 0x4b, + 0x73, 0xb0, 0x25, 0xc9, 0x63, 0x35, 0x43, 0x84, 0x84, 0xe9, 0x58, 0xad, + 0x08, 0x48, 0x27, 0x7d, 0xf9, 0x50, 0x84, 0x7d, 0x46, 0xa9, 0x87, 0x4f, + 0x10, 0x39, 0xfb, 0xea, 0x7e, 0x08, 0xbc, 0x79, 0x67, 0x5e, 0xf1, 0xdf, + 0x6e, 0xf2, 0x12, 0x30, 0xa7, 0x9a, 0x3b, 0x16, 0x13, 0x08, 0xa0, 0xa4, + 0x60, 0x0b, 0x53, 0x47 +}; +/* K = 66011bdefe8cc4a04fbd5d69252bb72da8f9a8d6e00bb7ca75719133ecd86f1d */ +static const uint8_t ac_dsa_vect153_out[] = { +/* R */ + 0x76, 0xe9, 0xb6, 0xef, 0x7e, 0x8d, 0x48, 0xfb, 0xfc, 0x43, 0xbf, 0x46, + 0x52, 0x81, 0x59, 0x22, 0x23, 0xfa, 0x7e, 0x0d, 0x99, 0x78, 0x39, 0x2d, + 0x35, 0x58, 0x68, 0xc8, 0xa2, 0x02, 0x09, 0xbb, +/* S */ + 0x7f, 0x9c, 0x8d, 0xea, 0xb5, 0x1c, 0x60, 0xbb, 0x6f, 0x86, 0x6c, 0x76, + 0x45, 0x01, 0x38, 0xe0, 0xd2, 0x94, 0x6a, 0xca, 0x6c, 0x5f, 0x88, 0xdf, + 0xe3, 0x5a, 0x0c, 0x1b, 0xa4, 0x93, 0xee, 0x47 +}; +#define ac_dsa_vect154_prime ac_dsa_vect151_prime +#define ac_dsa_vect154_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect154_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect154_ptx[] = { +/* Msg */ + 0x67, 0x85, 0x1d, 0xe9, 0x82, 0xfc, 0x70, 0xf9, 0x69, 0xd8, 0x2f, 0x65, + 0xd8, 0x5b, 0x03, 0x32, 0xd6, 0x67, 0x11, 0x4f, 0x27, 0xb5, 0x8b, 0xb9, + 0xe5, 0x65, 0xd2, 0xe4, 0x0a, 0xd0, 0x11, 0x98, 0x3d, 0x93, 0x60, 0x49, + 0xcc, 0x97, 0xa2, 0x16, 0x26, 0x0f, 0xa2, 0xe4, 0x10, 0xad, 0x6d, 0x6c, + 0x98, 0xa5, 0x48, 0x75, 0x9a, 0xa8, 0xe2, 0xd0, 0x22, 0xc1, 0xfb, 0xc1, + 0xb1, 0x6b, 0x10, 0xd8, 0x3f, 0xbb, 0xbd, 0x12, 0x6e, 0xc4, 0x3d, 0x5f, + 0xed, 0xc4, 0x07, 0xc8, 0x31, 0x46, 0x1c, 0x7f, 0x33, 0xed, 0x94, 0x74, + 0x00, 0x31, 0xec, 0xd0, 0xf7, 0x01, 0xc7, 0xb1, 0xdf, 0x88, 0xa2, 0x49, + 0x26, 0x5b, 0x3f, 0x60, 0xc3, 0x8f, 0x42, 0x85, 0xbb, 0xc9, 0xba, 0xe1, + 0x64, 0xbc, 0x38, 0xe1, 0x62, 0xc2, 0x35, 0xc9, 0xa9, 0xdf, 0xc1, 0xb1, + 0x50, 0xea, 0xeb, 0x14, 0x82, 0xeb, 0xed, 0x48 +}; +static const uint8_t ac_dsa_vect154_priv_val[] = { +/* X */ + 0x4f, 0x3e, 0x2c, 0x59, 0x01, 0xb6, 0x56, 0x11, 0x8d, 0x88, 0xa4, 0x7f, + 0xe2, 0xbd, 0x52, 0xf8, 0x5c, 0xbf, 0x82, 0x8d, 0xbf, 0x9b, 0x67, 0x36, + 0x5e, 0x20, 0x13, 0xa9, 0x37, 0xf0, 0xf2, 0xd9 +}; +static const uint8_t ac_dsa_vect154_pub_val[] = { +/* Y */ + 0xab, 0x9a, 0x99, 0xff, 0x87, 0x89, 0x9b, 0xd6, 0x65, 0x7b, 0x3a, 0x9e, + 0x9b, 0x72, 0x06, 0x99, 0x6b, 0xbc, 0x77, 0x99, 0xdd, 0xe5, 0x7d, 0xcf, + 0xff, 0x80, 0x98, 0x87, 0x5d, 0xc4, 0x65, 0x0d, 0x79, 0x1e, 0x90, 0xbc, + 0x4c, 0xee, 0x10, 0x98, 0x9b, 0xf4, 0x9e, 0xb5, 0xe6, 0x23, 0x08, 0x57, + 0xf9, 0x68, 0x41, 0xae, 0x83, 0x62, 0xe4, 0xee, 0x5c, 0xc8, 0x60, 0x2f, + 0x6a, 0x1a, 0x2c, 0x6f, 0x8f, 0x2f, 0x68, 0x0a, 0xd3, 0xa7, 0x2b, 0x0e, + 0x07, 0x51, 0x1e, 0xad, 0x30, 0x1f, 0x57, 0x52, 0x78, 0xa0, 0x74, 0x13, + 0x8a, 0xa4, 0xea, 0xa5, 0x39, 0x19, 0xe3, 0x4f, 0x00, 0x1c, 0xbe, 0x2d, + 0xcb, 0xc3, 0x45, 0xc7, 0x7f, 0x56, 0x87, 0xd0, 0x71, 0x98, 0x1a, 0x4d, + 0xca, 0x29, 0xd0, 0x26, 0xbb, 0x53, 0xec, 0x9c, 0xf0, 0x3a, 0x88, 0xd6, + 0x3c, 0x52, 0x20, 0x6d, 0x35, 0x1f, 0x8f, 0xca, 0x10, 0x23, 0x9e, 0x84, + 0xf4, 0x91, 0x5c, 0xe3, 0x47, 0xf4, 0x8d, 0x65, 0x0a, 0xaa, 0xa6, 0xb0, + 0x2d, 0x31, 0x64, 0x97, 0x3f, 0x82, 0xfc, 0x0e, 0x0f, 0x83, 0xa2, 0xd4, + 0x58, 0xaf, 0x65, 0x73, 0x6d, 0x7e, 0x0d, 0xbb, 0x26, 0x4f, 0xd7, 0x79, + 0xff, 0xd5, 0xa3, 0xf0, 0x66, 0x58, 0x44, 0x94, 0x59, 0x85, 0x26, 0xcd, + 0x67, 0xe1, 0x2d, 0x6c, 0x67, 0x96, 0x5a, 0x70, 0xec, 0x3f, 0x09, 0xe2, + 0xcc, 0x44, 0x7f, 0x17, 0x7e, 0xc8, 0x76, 0x04, 0xb5, 0x31, 0x48, 0x66, + 0x83, 0x02, 0x5e, 0x3b, 0x52, 0x0a, 0x26, 0xe6, 0x9c, 0x95, 0x8c, 0xf8, + 0x43, 0x5f, 0x7c, 0x6c, 0xe5, 0x64, 0xf0, 0xa7, 0x2d, 0x1f, 0xc4, 0x72, + 0x05, 0xa5, 0x0b, 0x39, 0xd5, 0x16, 0xb1, 0x4a, 0x47, 0x6f, 0x6c, 0x2d, + 0xca, 0xce, 0x50, 0x33, 0x9c, 0xae, 0x20, 0xcd, 0x34, 0x21, 0xa7, 0x5f, + 0x6d, 0x37, 0x7b, 0x8b +}; +/* K = 72bd0808076af461353d98cb0191ec76a7c04fbe3a7f793e390cc773434c1d4f */ +static const uint8_t ac_dsa_vect154_out[] = { +/* R */ + 0x76, 0x3e, 0x89, 0xfc, 0x8b, 0x2a, 0x09, 0x0b, 0x75, 0x81, 0x2a, 0xef, + 0xa5, 0x5d, 0xe7, 0xb7, 0xcd, 0x61, 0xec, 0x3f, 0xdf, 0x87, 0x30, 0xce, + 0x16, 0xb0, 0x5a, 0x7b, 0x94, 0x56, 0xfd, 0x2d, +/* S */ + 0x4a, 0x97, 0x08, 0x6b, 0x67, 0x17, 0xa7, 0x3a, 0x6b, 0xe6, 0xd4, 0xa9, + 0x5b, 0x83, 0x43, 0xbd, 0x20, 0xb0, 0xd7, 0xb5, 0x1c, 0x3d, 0xa1, 0xd8, + 0x6c, 0x58, 0x52, 0x35, 0x08, 0x71, 0x37, 0x9b +}; +#define ac_dsa_vect155_prime ac_dsa_vect151_prime +#define ac_dsa_vect155_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect155_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect155_ptx[] = { +/* Msg */ + 0x61, 0x6d, 0xe9, 0xdd, 0x23, 0xeb, 0xed, 0xe4, 0x28, 0xe0, 0x32, 0xdb, + 0x78, 0x38, 0x10, 0x8a, 0x22, 0x4f, 0x7a, 0xca, 0x57, 0xb1, 0xdf, 0x87, + 0xf0, 0x31, 0xfe, 0x1d, 0x86, 0x08, 0x3d, 0x68, 0x8c, 0x5c, 0x3e, 0xf0, + 0x78, 0xe6, 0x4d, 0x8d, 0x5a, 0x9e, 0x61, 0x2d, 0x39, 0x83, 0x46, 0x0c, + 0xa1, 0xf8, 0x16, 0xf7, 0x87, 0xc0, 0x3c, 0xa4, 0x3a, 0x1f, 0xd8, 0xce, + 0x13, 0x86, 0x55, 0xdf, 0x67, 0x70, 0x56, 0x36, 0x4c, 0x0e, 0xab, 0x8e, + 0x04, 0x93, 0xc0, 0x7b, 0xd4, 0xb2, 0xb0, 0x50, 0x22, 0x19, 0x09, 0x32, + 0xde, 0x79, 0x4f, 0x19, 0x5d, 0xbe, 0xf2, 0x97, 0x09, 0x3e, 0x7d, 0xa1, + 0xc4, 0x30, 0x4d, 0xb4, 0x0b, 0x63, 0xca, 0x53, 0xe1, 0xb8, 0xbc, 0xda, + 0xd9, 0x13, 0xd7, 0xa9, 0x02, 0xaf, 0x02, 0x5c, 0x36, 0x7c, 0x48, 0xde, + 0x38, 0x7f, 0x1a, 0x9b, 0xcd, 0x7c, 0xa4, 0x2e +}; +static const uint8_t ac_dsa_vect155_priv_val[] = { +/* X */ + 0x4d, 0x02, 0x40, 0xa3, 0x4d, 0xd4, 0x5a, 0xac, 0xaa, 0xb9, 0xe2, 0x4e, + 0x48, 0x38, 0x22, 0x3c, 0xcb, 0x75, 0x9f, 0x1d, 0x93, 0xfa, 0x87, 0x91, + 0xf2, 0x8f, 0xc7, 0xc2, 0xe8, 0x31, 0x88, 0x20 +}; +static const uint8_t ac_dsa_vect155_pub_val[] = { +/* Y */ + 0x58, 0x4e, 0xae, 0xed, 0x2d, 0xc7, 0x85, 0xd8, 0xe2, 0xb8, 0xc8, 0x5f, + 0xd0, 0xe5, 0xec, 0x25, 0x1f, 0x13, 0x49, 0x58, 0xbd, 0x9e, 0xea, 0xe4, + 0xf7, 0x9f, 0x86, 0x2b, 0x62, 0xcf, 0x60, 0x2a, 0xb1, 0x0d, 0x22, 0xec, + 0xa4, 0x99, 0x04, 0x2f, 0x2c, 0x87, 0x5f, 0x27, 0x08, 0xba, 0x0d, 0x69, + 0x7a, 0xf3, 0x9f, 0x23, 0xf5, 0xe0, 0xb7, 0xde, 0x4f, 0xf7, 0x96, 0x4b, + 0xab, 0x12, 0x79, 0xef, 0xa2, 0xaa, 0x79, 0x7a, 0x2d, 0x21, 0xe7, 0x88, + 0xd2, 0x49, 0xf4, 0x26, 0x93, 0xcd, 0xbf, 0xd7, 0x1f, 0xdc, 0xb1, 0xaa, + 0x93, 0xb7, 0x9b, 0xac, 0x0d, 0xbc, 0xb5, 0x87, 0xbb, 0xff, 0x4e, 0xf1, + 0x5a, 0x37, 0x99, 0xa5, 0xfc, 0xa8, 0xb1, 0x58, 0x98, 0x38, 0xe3, 0x00, + 0x96, 0x06, 0x9c, 0xa7, 0x93, 0x1f, 0x74, 0x08, 0x81, 0x5b, 0x58, 0x5d, + 0x14, 0x0a, 0x74, 0x7d, 0xe4, 0x3b, 0xd9, 0x2c, 0xac, 0x3f, 0x9a, 0x9b, + 0x18, 0x62, 0xfd, 0x70, 0x46, 0x73, 0xe1, 0xe5, 0x87, 0x10, 0xc1, 0x6d, + 0xdb, 0xe7, 0xe5, 0x2d, 0x31, 0xa7, 0xdf, 0x15, 0x97, 0x49, 0x58, 0xb1, + 0x28, 0x81, 0x16, 0xed, 0x98, 0xff, 0x24, 0x7f, 0x50, 0x28, 0xce, 0xc8, + 0x6d, 0x9e, 0xb9, 0x7b, 0x12, 0x6a, 0x48, 0xad, 0xc9, 0x52, 0xe9, 0x0d, + 0xc5, 0x2f, 0x2b, 0xd7, 0x81, 0x03, 0x55, 0xaa, 0x90, 0x75, 0x05, 0x1f, + 0x26, 0x12, 0x9c, 0x2d, 0x2f, 0xb0, 0xba, 0x80, 0x66, 0xe4, 0x14, 0x98, + 0x9d, 0x92, 0xe2, 0x9e, 0x68, 0x99, 0x60, 0xe3, 0x3e, 0xe5, 0x6c, 0xa6, + 0x2d, 0x71, 0x4a, 0x42, 0xcb, 0x74, 0x87, 0xf7, 0x0c, 0x0c, 0x0b, 0xa6, + 0x43, 0xfa, 0x9d, 0xd5, 0xf8, 0x52, 0x59, 0xfd, 0xec, 0xd4, 0x9f, 0xa9, + 0x70, 0xc8, 0x32, 0x26, 0x82, 0xb1, 0x14, 0xf2, 0x64, 0x78, 0x37, 0x63, + 0x7a, 0xbc, 0x0e, 0xd2 +}; +/* K = 325e19d8b7ee8c8d9cb7e70bb5417035a8183bdf73149a45f0e83f3af68decc0 */ +static const uint8_t ac_dsa_vect155_out[] = { +/* R */ + 0x74, 0x8f, 0x46, 0x6b, 0x7f, 0xdc, 0xdf, 0xa7, 0x70, 0x17, 0xc8, 0x65, + 0xa3, 0x3b, 0x1d, 0xad, 0x4d, 0xb9, 0x9d, 0xbd, 0x63, 0xef, 0xa1, 0xc8, + 0x73, 0x45, 0xc4, 0x83, 0x3b, 0x06, 0x32, 0xac, +/* S */ + 0x0b, 0xf9, 0x93, 0x8e, 0x79, 0x72, 0xeb, 0xb0, 0x0f, 0xb0, 0xa3, 0xc0, + 0xc2, 0x47, 0x6d, 0x25, 0x09, 0xdb, 0x23, 0xaf, 0xca, 0xec, 0xb1, 0x7d, + 0xc5, 0x71, 0x90, 0x53, 0x17, 0xeb, 0x8c, 0xa7 +}; +#define ac_dsa_vect156_prime ac_dsa_vect151_prime +#define ac_dsa_vect156_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect156_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect156_ptx[] = { +/* Msg */ + 0x11, 0x5f, 0x0a, 0x8b, 0xe3, 0x4e, 0x84, 0xd0, 0x9b, 0xdc, 0xca, 0x69, + 0xd1, 0x9c, 0xe1, 0x7d, 0xd6, 0x7d, 0xf7, 0x39, 0xaa, 0x4f, 0xc6, 0xe8, + 0x07, 0x70, 0x76, 0x53, 0x5f, 0x39, 0xaf, 0x83, 0x02, 0x88, 0x14, 0x71, + 0xa5, 0xfb, 0x0e, 0x18, 0x39, 0xa3, 0xaa, 0x76, 0xdf, 0xda, 0x4b, 0xde, + 0x2f, 0x9f, 0xa2, 0x5f, 0xa5, 0x82, 0xb7, 0x56, 0xa4, 0x96, 0x6d, 0x75, + 0x32, 0x0a, 0xc1, 0x99, 0x54, 0x72, 0x27, 0x16, 0x66, 0x15, 0x6e, 0xa8, + 0x6c, 0x19, 0xa2, 0x39, 0x89, 0x5e, 0x55, 0x78, 0xa3, 0xc3, 0x9b, 0x0b, + 0xa3, 0x25, 0x88, 0x27, 0xa0, 0x1d, 0xf1, 0xf3, 0x0d, 0xb2, 0x2d, 0xdb, + 0xc2, 0x67, 0xc9, 0xe2, 0x90, 0xd5, 0xd4, 0x57, 0xd0, 0xa9, 0x4d, 0x8a, + 0xa7, 0x3f, 0x8e, 0x79, 0xf3, 0xac, 0xd3, 0x1b, 0xde, 0xee, 0x7a, 0xa3, + 0x2c, 0x79, 0x2c, 0x22, 0xac, 0xb8, 0x07, 0xba +}; +static const uint8_t ac_dsa_vect156_priv_val[] = { +/* X */ + 0x08, 0x00, 0x39, 0x4a, 0x2c, 0xcd, 0xd1, 0xf5, 0x58, 0x00, 0x56, 0x53, + 0x74, 0xd4, 0x6b, 0xe9, 0xbb, 0xc1, 0x19, 0x0b, 0x55, 0xee, 0xe2, 0x65, + 0x02, 0xbf, 0x5f, 0x24, 0x59, 0xac, 0x5c, 0xc0 +}; +static const uint8_t ac_dsa_vect156_pub_val[] = { +/* Y */ + 0x2e, 0x06, 0x07, 0x3f, 0x59, 0x19, 0x6d, 0x3e, 0x29, 0xba, 0x71, 0x8e, + 0x84, 0x48, 0x9b, 0x6f, 0x44, 0x7f, 0xd6, 0xf6, 0x7a, 0x9e, 0xe6, 0x35, + 0x7c, 0x5e, 0x8a, 0x58, 0xfa, 0x3c, 0x4f, 0xb6, 0xac, 0x83, 0x14, 0xeb, + 0xdc, 0x3b, 0x4d, 0x61, 0x27, 0xf2, 0xb4, 0xd2, 0x11, 0x2c, 0x27, 0x79, + 0x9f, 0x0c, 0x1a, 0xc5, 0xf7, 0x94, 0x6b, 0x56, 0x07, 0x21, 0x2d, 0x79, + 0x67, 0x41, 0xcc, 0x3b, 0xe1, 0x27, 0x21, 0x2a, 0x12, 0x5e, 0xdc, 0x3a, + 0x7a, 0x91, 0xa5, 0x25, 0xcd, 0x62, 0x15, 0x21, 0x99, 0xb1, 0x8b, 0x4f, + 0x1d, 0xc3, 0x32, 0x21, 0x5d, 0x65, 0xd6, 0x4a, 0xd0, 0x60, 0x98, 0xff, + 0x21, 0x80, 0xab, 0x47, 0xbb, 0x57, 0x28, 0x72, 0x0c, 0x93, 0x7e, 0x12, + 0x07, 0x64, 0x9e, 0xd1, 0x9c, 0x88, 0x33, 0x31, 0xea, 0x41, 0x5f, 0xaa, + 0x51, 0xc5, 0x56, 0xd1, 0x26, 0x49, 0x66, 0x5f, 0x1e, 0xce, 0x88, 0x0d, + 0x05, 0x5a, 0x2a, 0x79, 0x3a, 0xdc, 0x74, 0xb3, 0x8f, 0x15, 0xf5, 0x0a, + 0xa9, 0xb4, 0x67, 0x86, 0xd9, 0x07, 0x01, 0x7b, 0x1d, 0x62, 0x35, 0xc4, + 0x3b, 0x37, 0xc2, 0x03, 0x6a, 0x16, 0x40, 0xf6, 0xbf, 0xe3, 0xbe, 0xc2, + 0xb9, 0x5b, 0x43, 0x00, 0xa3, 0xbd, 0x78, 0xf4, 0x71, 0xf6, 0xaa, 0x56, + 0xe5, 0xe6, 0x34, 0x75, 0x71, 0x99, 0x6f, 0x77, 0x86, 0x70, 0xad, 0x94, + 0xef, 0xaf, 0x20, 0x99, 0x1c, 0x55, 0x59, 0x24, 0xfd, 0x55, 0xcd, 0x51, + 0x8d, 0xf0, 0xbd, 0x55, 0x8f, 0xaa, 0xc3, 0xf9, 0x82, 0x6a, 0x86, 0x5a, + 0x3c, 0xed, 0x0f, 0x59, 0xcb, 0xea, 0x45, 0xc6, 0x54, 0x12, 0xbd, 0xdf, + 0x8f, 0x2a, 0x8a, 0xab, 0x3d, 0xfc, 0xa1, 0xdf, 0xf5, 0x03, 0x74, 0x16, + 0x3f, 0xa8, 0x99, 0xcc, 0x7f, 0x7f, 0x10, 0x8b, 0x19, 0x4f, 0xc9, 0x55, + 0xca, 0xbe, 0x9c, 0xa4 +}; +/* K = 617d00444047d8e943e429947d28b4718a8b7603475e5453cacb80fa704f90f1 */ +static const uint8_t ac_dsa_vect156_out[] = { +/* R */ + 0x5c, 0x8d, 0x76, 0x44, 0x07, 0x35, 0x05, 0x5c, 0x1b, 0x36, 0x69, 0x8d, + 0xa7, 0x39, 0x03, 0xb3, 0x32, 0xd6, 0x4c, 0xa5, 0x60, 0x30, 0x46, 0x14, + 0x4f, 0xb7, 0x66, 0x8b, 0x1a, 0xca, 0xc3, 0x37, +/* S */ + 0x11, 0xc5, 0x4e, 0xfb, 0xd4, 0x92, 0xa7, 0x14, 0x7a, 0x1c, 0x50, 0xb2, + 0x87, 0x37, 0x7b, 0x52, 0xd2, 0x19, 0x39, 0x07, 0xd5, 0xbb, 0x63, 0x61, + 0x59, 0xc1, 0x53, 0x18, 0xa4, 0x80, 0xca, 0x6a +}; +#define ac_dsa_vect157_prime ac_dsa_vect151_prime +#define ac_dsa_vect157_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect157_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect157_ptx[] = { +/* Msg */ + 0x3c, 0x1f, 0x2b, 0x92, 0xdb, 0x1b, 0x43, 0x15, 0x83, 0x7b, 0xaa, 0x86, + 0x30, 0x43, 0xa9, 0xb4, 0x49, 0x6a, 0x78, 0x14, 0x3c, 0xa7, 0x4f, 0x6e, + 0x67, 0x18, 0x1f, 0xac, 0xf5, 0x0a, 0x6e, 0x08, 0xd2, 0x79, 0x45, 0xd0, + 0x0e, 0x7b, 0x06, 0xf9, 0xc5, 0x7c, 0x0e, 0x2f, 0x15, 0x27, 0xc9, 0x4b, + 0xce, 0xce, 0xa6, 0x99, 0x31, 0x75, 0xd0, 0xf0, 0x9b, 0xab, 0x4f, 0x15, + 0xaf, 0x55, 0xab, 0x7a, 0xa9, 0xb1, 0x6b, 0x48, 0xc9, 0x4a, 0x6a, 0x99, + 0xc2, 0xd7, 0xe4, 0x77, 0xb7, 0x44, 0xcd, 0x27, 0xcd, 0xb9, 0xb0, 0xbb, + 0xf8, 0x10, 0x75, 0x6b, 0xc6, 0x37, 0x6f, 0xa1, 0x5b, 0xfb, 0xea, 0x3c, + 0x93, 0x76, 0xca, 0x69, 0x79, 0x75, 0x2f, 0xdb, 0x3a, 0x65, 0x5a, 0xff, + 0xd6, 0xc0, 0x18, 0x6d, 0x1a, 0x34, 0x35, 0x5d, 0xae, 0xa8, 0xcc, 0x75, + 0xac, 0xf9, 0x6b, 0x88, 0x47, 0xdb, 0xdb, 0x8d +}; +static const uint8_t ac_dsa_vect157_priv_val[] = { +/* X */ + 0x59, 0xed, 0xd0, 0x34, 0x8c, 0xa6, 0xa8, 0x5c, 0x40, 0x88, 0x16, 0x54, + 0x9e, 0x9c, 0x58, 0x33, 0x8e, 0xf9, 0x2f, 0x56, 0xed, 0xd8, 0xfa, 0x75, + 0x32, 0x26, 0xac, 0xc0, 0xe1, 0x81, 0x75, 0x1c +}; +static const uint8_t ac_dsa_vect157_pub_val[] = { +/* Y */ + 0xa4, 0x74, 0x2d, 0x3c, 0x7e, 0x76, 0x81, 0xb0, 0x1c, 0xd6, 0xaa, 0xe1, + 0x74, 0x23, 0xcc, 0x78, 0x04, 0x91, 0xd0, 0x8d, 0xf7, 0x3b, 0x4a, 0x71, + 0xed, 0xf7, 0xbd, 0x2e, 0xe2, 0x9c, 0x69, 0x8c, 0xd6, 0x6d, 0xba, 0x04, + 0x91, 0x68, 0x8f, 0xc7, 0xee, 0xfb, 0x4d, 0x70, 0x91, 0x47, 0xbf, 0xd4, + 0xc8, 0xc4, 0xb7, 0x97, 0xab, 0x91, 0x97, 0x57, 0x3b, 0x5d, 0x36, 0x59, + 0x9c, 0x4a, 0x59, 0x2c, 0x46, 0x69, 0x55, 0xe8, 0x0a, 0xe5, 0xd2, 0x12, + 0x2b, 0xca, 0xa5, 0xd0, 0xe1, 0xd9, 0x4b, 0x4e, 0xd2, 0xa9, 0x9b, 0x1a, + 0xf5, 0xd0, 0x8e, 0xec, 0x86, 0xc3, 0x77, 0x53, 0xa3, 0xc3, 0x65, 0x6c, + 0x0f, 0xef, 0x0d, 0x2c, 0x47, 0x1e, 0x4f, 0xfa, 0x0f, 0xb1, 0x63, 0x17, + 0x4a, 0x4d, 0xf1, 0x70, 0x78, 0x79, 0xfe, 0x08, 0x36, 0x55, 0x29, 0x11, + 0x27, 0xa3, 0xbb, 0xb0, 0x59, 0x7e, 0x23, 0x80, 0x2e, 0x42, 0x4e, 0xfe, + 0x40, 0x16, 0x36, 0x03, 0x64, 0x50, 0x6c, 0x8a, 0xb4, 0x08, 0x1f, 0x0a, + 0x95, 0x69, 0x2c, 0x26, 0x29, 0x53, 0x7f, 0x05, 0x30, 0x61, 0x81, 0xdb, + 0x66, 0x9b, 0xcf, 0xaf, 0x01, 0xc1, 0x53, 0x95, 0x61, 0x42, 0x38, 0xa2, + 0x30, 0x94, 0x29, 0x19, 0x95, 0x55, 0x14, 0x26, 0x39, 0xb3, 0x44, 0x3e, + 0xf8, 0x5a, 0xf7, 0x4b, 0x5e, 0x88, 0xb7, 0xc7, 0x0a, 0x81, 0x67, 0x33, + 0x4f, 0x27, 0x29, 0x4a, 0x8b, 0xa1, 0x26, 0x66, 0x95, 0xa3, 0x69, 0x37, + 0x2b, 0xad, 0xcb, 0xa7, 0x62, 0x3a, 0xa5, 0x8c, 0xbc, 0xf2, 0x5b, 0x4b, + 0xbe, 0x66, 0x3d, 0x4e, 0xce, 0xd1, 0xa1, 0x8e, 0x77, 0x53, 0x39, 0x1d, + 0x6c, 0x53, 0x85, 0x4c, 0x4a, 0x8d, 0x0e, 0xe1, 0xa7, 0x90, 0xa1, 0xa2, + 0x10, 0x71, 0xf1, 0x38, 0x6c, 0x23, 0x5a, 0xc2, 0x61, 0x82, 0xd0, 0x1a, + 0x1e, 0x81, 0xec, 0xf8 +}; +/* K = 0a96189b8740005f215ae5c5a8aa8686dbb4c353d2c55deb3904bccc4f9a9b9b */ +static const uint8_t ac_dsa_vect157_out[] = { +/* R */ + 0x31, 0xc1, 0xc6, 0xae, 0xe7, 0xed, 0x54, 0x1a, 0x28, 0x1f, 0x37, 0x63, + 0x2b, 0x27, 0xba, 0x88, 0x53, 0x6f, 0x36, 0xbc, 0xd9, 0x2f, 0xcc, 0x36, + 0x0d, 0xa0, 0x41, 0xf4, 0x19, 0x7f, 0x7f, 0x95, +/* S */ + 0x45, 0xe1, 0x01, 0x9b, 0x2a, 0x17, 0x02, 0xb5, 0xdf, 0x1e, 0xef, 0x4f, + 0xb7, 0xdf, 0x6a, 0x53, 0xaa, 0xa6, 0x6e, 0xcb, 0x8b, 0xe5, 0xcd, 0x2e, + 0x28, 0xb3, 0x53, 0xc8, 0x70, 0xe0, 0x1f, 0x41 +}; +#define ac_dsa_vect158_prime ac_dsa_vect151_prime +#define ac_dsa_vect158_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect158_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect158_ptx[] = { +/* Msg */ + 0xad, 0x38, 0x9f, 0x53, 0x23, 0x5d, 0xeb, 0x06, 0x8f, 0x70, 0x97, 0x78, + 0x03, 0x30, 0x74, 0x64, 0x93, 0x60, 0x7f, 0xdb, 0x7e, 0x11, 0x70, 0xbd, + 0x1f, 0xe0, 0xda, 0x01, 0x27, 0x14, 0xb8, 0xf1, 0xb1, 0x28, 0xc6, 0x9a, + 0x53, 0xd7, 0xdd, 0x26, 0x46, 0xb0, 0x97, 0x20, 0x88, 0x3e, 0x23, 0x87, + 0xdd, 0x15, 0xd4, 0x65, 0x64, 0xad, 0xff, 0x66, 0x42, 0x37, 0x2c, 0x83, + 0x82, 0x87, 0xba, 0xfa, 0x5f, 0x43, 0x43, 0xa2, 0x7e, 0xc8, 0x06, 0x97, + 0x70, 0xe5, 0xc3, 0x67, 0x54, 0x88, 0x33, 0xfd, 0xdc, 0xc5, 0xf8, 0x61, + 0x7a, 0xaf, 0x41, 0x28, 0x9d, 0x96, 0xdd, 0x40, 0xf1, 0x09, 0x8d, 0xed, + 0x9f, 0xbb, 0x11, 0x0a, 0xeb, 0x14, 0xd6, 0x92, 0x72, 0xdf, 0xb2, 0xdd, + 0x7d, 0x75, 0xe7, 0xa8, 0x8d, 0xc4, 0x14, 0x7f, 0x27, 0xc6, 0x4e, 0xb1, + 0xbf, 0x0a, 0xa0, 0x56, 0x9b, 0xbd, 0xa3, 0x20 +}; +static const uint8_t ac_dsa_vect158_priv_val[] = { +/* X */ + 0x19, 0xff, 0x4e, 0xec, 0x2e, 0x47, 0x30, 0x1d, 0x0b, 0x70, 0xa8, 0x26, + 0xda, 0xd8, 0x22, 0xb6, 0x09, 0xc9, 0x97, 0xbc, 0x1b, 0x3a, 0x9d, 0x7c, + 0xbd, 0x3d, 0x1d, 0x22, 0x52, 0xe8, 0xac, 0xda +}; +static const uint8_t ac_dsa_vect158_pub_val[] = { +/* Y */ + 0xbf, 0x4a, 0xa2, 0xd8, 0x67, 0xb4, 0x33, 0xf9, 0x34, 0xd1, 0xd5, 0x67, + 0x01, 0x0d, 0xbe, 0x06, 0x79, 0x05, 0xf4, 0xe3, 0x5d, 0x7c, 0xe5, 0x68, + 0xb5, 0x5a, 0xba, 0x69, 0x4d, 0x12, 0xdf, 0xba, 0x95, 0xc2, 0x35, 0x07, + 0x84, 0x61, 0xaa, 0xab, 0x81, 0xf1, 0xe4, 0xdf, 0x32, 0x31, 0x9e, 0x57, + 0x59, 0xc5, 0x26, 0x3e, 0xbf, 0xbe, 0xbf, 0x79, 0x60, 0xc5, 0x7a, 0xed, + 0x79, 0xbf, 0x2d, 0xe3, 0x89, 0x48, 0xf8, 0xff, 0x79, 0xef, 0x26, 0xd6, + 0x6a, 0x7f, 0x98, 0x38, 0x41, 0x17, 0xdc, 0xe1, 0xf3, 0x86, 0xae, 0xcc, + 0x43, 0x69, 0xaf, 0xb2, 0xe0, 0xde, 0x77, 0xcc, 0xd2, 0xe7, 0xde, 0xc3, + 0x28, 0x61, 0x42, 0x43, 0xef, 0xfa, 0xc6, 0x07, 0xc8, 0xd5, 0xfc, 0x5c, + 0x7c, 0x0b, 0x11, 0x43, 0x96, 0x35, 0x73, 0xd9, 0xf1, 0x06, 0xfc, 0xec, + 0xf2, 0xe1, 0x5c, 0x67, 0xa3, 0xbf, 0xf6, 0x90, 0x8b, 0x28, 0x6d, 0x0e, + 0x41, 0x31, 0xfb, 0x81, 0x62, 0x2f, 0xff, 0x9e, 0x10, 0xf5, 0x77, 0x1a, + 0xfe, 0xde, 0x22, 0x76, 0xe8, 0x34, 0x4d, 0x9a, 0xe2, 0xf4, 0x93, 0xfb, + 0x48, 0x56, 0xd1, 0xba, 0x57, 0x60, 0xdd, 0xae, 0x38, 0xaf, 0x7d, 0xdc, + 0xa4, 0x09, 0xe7, 0x90, 0x72, 0x68, 0x69, 0x1b, 0xaa, 0x33, 0xdf, 0xcb, + 0xfd, 0x69, 0xe9, 0xaa, 0x9f, 0xaa, 0x79, 0xcf, 0x30, 0x3a, 0xc8, 0xb1, + 0xfa, 0x07, 0xc1, 0xd4, 0x0d, 0x1c, 0xea, 0x01, 0xe8, 0xba, 0x0d, 0x65, + 0x26, 0x5f, 0x4c, 0x6a, 0xab, 0xb1, 0x6e, 0xbe, 0x2f, 0x6e, 0xf5, 0xaa, + 0xac, 0x25, 0xc0, 0xc2, 0x73, 0x0c, 0xbe, 0xed, 0xc1, 0x77, 0x66, 0x7e, + 0xe0, 0x2b, 0xf4, 0x52, 0x34, 0x18, 0xa9, 0x86, 0xd5, 0xb8, 0x7a, 0x9b, + 0x75, 0xec, 0x20, 0x1a, 0xf0, 0xf1, 0x96, 0x1c, 0xd5, 0x1b, 0x85, 0x87, + 0x91, 0x47, 0xe6, 0x07 +}; +/* K = 7ff51bb8946842c7e2f7245e73461e2b0820528548f7ecb53bcadc7a20e826b7 */ +static const uint8_t ac_dsa_vect158_out[] = { +/* R */ + 0x2f, 0x94, 0x84, 0xaa, 0xed, 0xa9, 0xdc, 0xb8, 0x8d, 0x2d, 0x36, 0x44, + 0xdb, 0x2c, 0x58, 0xee, 0xfe, 0x2e, 0x76, 0x95, 0xa6, 0xc8, 0xbe, 0x9a, + 0xbe, 0x97, 0x17, 0x3e, 0xfc, 0x9c, 0x0b, 0xc3, +/* S */ + 0x01, 0x66, 0xa7, 0xbf, 0x4e, 0x8b, 0xda, 0x6b, 0x86, 0x39, 0x69, 0x43, + 0xa7, 0x4a, 0x8e, 0xbf, 0xc6, 0x03, 0xa8, 0x5e, 0xd2, 0x87, 0xbf, 0x3f, + 0x5a, 0x30, 0xdd, 0x0b, 0xbe, 0x49, 0xcd, 0x8b +}; +#define ac_dsa_vect159_prime ac_dsa_vect151_prime +#define ac_dsa_vect159_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect159_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect159_ptx[] = { +/* Msg */ + 0x12, 0xf9, 0x58, 0x2e, 0x3a, 0x1a, 0x76, 0xf2, 0x99, 0xd7, 0x2d, 0x9b, + 0x15, 0x02, 0xb9, 0x90, 0x60, 0x80, 0x26, 0x60, 0x22, 0x6b, 0xc4, 0x7b, + 0x71, 0xe5, 0x4e, 0xc9, 0x38, 0x8e, 0xac, 0x32, 0x59, 0x02, 0xac, 0xbe, + 0x2b, 0xd7, 0x10, 0x9e, 0x19, 0xf3, 0x77, 0xc9, 0xd2, 0xb4, 0xd2, 0x80, + 0xcd, 0xfa, 0xa4, 0x88, 0x88, 0xb9, 0xcf, 0x4e, 0xd0, 0x6c, 0xcf, 0x5a, + 0xd8, 0x66, 0xd6, 0x93, 0x2d, 0x40, 0x25, 0x92, 0xf6, 0xbe, 0x6e, 0x68, + 0x76, 0xdb, 0x5a, 0x62, 0xbe, 0xea, 0xf3, 0x73, 0xb6, 0x02, 0x38, 0xab, + 0x96, 0x82, 0x92, 0x43, 0x75, 0x9b, 0xdb, 0x58, 0x6f, 0x45, 0xec, 0x4a, + 0xe2, 0xcb, 0x22, 0x24, 0x8a, 0xb0, 0xb6, 0xaa, 0x7a, 0x75, 0x83, 0xa6, + 0x1d, 0xd3, 0xb8, 0xf1, 0x19, 0xcd, 0x84, 0x04, 0x79, 0xa4, 0xa9, 0xaf, + 0x8a, 0x43, 0x9d, 0xb9, 0x04, 0xac, 0x14, 0xec +}; +static const uint8_t ac_dsa_vect159_priv_val[] = { +/* X */ + 0x71, 0x42, 0xb1, 0x95, 0xeb, 0x24, 0x17, 0xbc, 0x23, 0x4c, 0xf3, 0x2c, + 0x6f, 0xd7, 0xca, 0xe4, 0x70, 0xcb, 0x48, 0xc7, 0x4d, 0xbd, 0xb4, 0x69, + 0xa2, 0x64, 0xc1, 0x98, 0x8e, 0xb3, 0xe5, 0x2d +}; +static const uint8_t ac_dsa_vect159_pub_val[] = { +/* Y */ + 0x72, 0xd8, 0x10, 0x06, 0x92, 0xe1, 0xa3, 0x0a, 0x32, 0xe3, 0x7c, 0x90, + 0x9e, 0xb6, 0xc7, 0xba, 0xea, 0x72, 0x58, 0xb0, 0xb7, 0x86, 0x68, 0xe7, + 0x59, 0x15, 0x07, 0x00, 0x37, 0x47, 0x9b, 0x88, 0x4f, 0xa9, 0xf1, 0x80, + 0x66, 0xdf, 0x89, 0xb4, 0x90, 0xf9, 0xa2, 0x69, 0x6a, 0x85, 0x05, 0x03, + 0x69, 0x77, 0x60, 0x4d, 0xad, 0x26, 0x8e, 0x90, 0x55, 0x28, 0x35, 0xfd, + 0xca, 0x33, 0x39, 0xb3, 0x23, 0x60, 0xc9, 0x43, 0x58, 0xff, 0xcd, 0x0b, + 0x1e, 0xa1, 0x10, 0x66, 0x12, 0x2e, 0xfd, 0x01, 0x7c, 0xd6, 0xfe, 0x1e, + 0xcd, 0x0d, 0xd6, 0x67, 0x80, 0x81, 0xb8, 0x4c, 0xb6, 0xe1, 0x44, 0x47, + 0x1d, 0xae, 0x76, 0x36, 0xb4, 0xa0, 0x92, 0x9c, 0xa7, 0x1a, 0xa4, 0x7b, + 0x40, 0x86, 0x66, 0x5d, 0x66, 0xd4, 0x03, 0x4c, 0x18, 0x8d, 0x64, 0xd3, + 0x8b, 0x69, 0xf0, 0xca, 0x17, 0x1c, 0x85, 0x92, 0x5c, 0xad, 0x28, 0x40, + 0x27, 0x7d, 0x28, 0x87, 0xa7, 0xf7, 0xb8, 0x1e, 0x6b, 0x12, 0x87, 0x0c, + 0xc3, 0xc6, 0x9e, 0x18, 0xca, 0x9c, 0x22, 0xc3, 0xd3, 0xa3, 0x9e, 0xe2, + 0x86, 0xca, 0x65, 0xd2, 0x3f, 0x3e, 0x81, 0x11, 0xaa, 0x7c, 0x6e, 0xa9, + 0xa0, 0xd1, 0x4c, 0x84, 0xdd, 0xf7, 0x6a, 0xbd, 0x44, 0xdb, 0x3b, 0x98, + 0x33, 0xd6, 0x9c, 0xb9, 0x9b, 0x52, 0x4c, 0x98, 0xfd, 0xb9, 0xd0, 0xff, + 0x20, 0xc9, 0xd2, 0x68, 0xe8, 0xe7, 0x17, 0x5f, 0x13, 0xc1, 0x1c, 0x57, + 0x95, 0xd0, 0xfe, 0x0b, 0x38, 0x99, 0xb7, 0x4c, 0x0d, 0xca, 0x91, 0x47, + 0x6f, 0xeb, 0xcb, 0x50, 0x9f, 0x7f, 0xd5, 0x07, 0x02, 0x39, 0x88, 0x14, + 0x52, 0x42, 0xdf, 0xc8, 0x09, 0xce, 0x95, 0xc6, 0xf1, 0xb3, 0x1f, 0x67, + 0xe0, 0x16, 0x50, 0xdd, 0x45, 0x87, 0x8e, 0xfc, 0x7e, 0xa8, 0x9c, 0xf6, + 0xe3, 0x17, 0x1e, 0x43 +}; +/* K = 1043805a13045a36e1b6498db97d163571c61cc4a719e506173b5e6df33fc81d */ +static const uint8_t ac_dsa_vect159_out[] = { +/* R */ + 0x38, 0xcf, 0x6b, 0x8c, 0xba, 0xe8, 0x2e, 0x62, 0x95, 0xf8, 0x33, 0x16, + 0xa9, 0xc4, 0x9d, 0x2d, 0xc7, 0xc9, 0x2c, 0xb9, 0x0b, 0x19, 0xa2, 0xc2, + 0xd4, 0x56, 0x49, 0x94, 0x93, 0x54, 0xd9, 0x30, +/* S */ + 0x35, 0x6a, 0x58, 0x50, 0xd0, 0x7a, 0xec, 0x6e, 0x9d, 0x4a, 0x4d, 0x7f, + 0x79, 0xd9, 0xb0, 0x35, 0x2b, 0x08, 0x7d, 0x7e, 0xf4, 0x83, 0x94, 0x12, + 0x8c, 0x5a, 0xe4, 0x99, 0x3e, 0x82, 0x59, 0xb8 +}; +#define ac_dsa_vect160_prime ac_dsa_vect151_prime +#define ac_dsa_vect160_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect160_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect160_ptx[] = { +/* Msg */ + 0xb6, 0xac, 0x84, 0xc4, 0x9f, 0x6b, 0xd6, 0x01, 0xd5, 0x86, 0x8b, 0xa0, + 0x6d, 0x49, 0xb8, 0xcb, 0xa8, 0x7a, 0x9d, 0x6e, 0x79, 0x05, 0x24, 0x75, + 0x41, 0xfd, 0x33, 0x2c, 0x2b, 0x03, 0x74, 0xcf, 0x57, 0xd4, 0xa0, 0xdc, + 0x0b, 0x5a, 0x6c, 0x3f, 0x8f, 0x7e, 0x24, 0xbe, 0x3a, 0x1e, 0xed, 0xc4, + 0xa8, 0xc5, 0x75, 0x84, 0x7c, 0x02, 0xe4, 0xed, 0xd4, 0x74, 0x50, 0x40, + 0x68, 0x56, 0x70, 0x05, 0x89, 0x96, 0x25, 0x0f, 0x73, 0xe2, 0x98, 0xa4, + 0x3b, 0x39, 0x1a, 0x4a, 0xd5, 0x67, 0xf0, 0xc9, 0xbc, 0x4b, 0x6a, 0xbf, + 0x6d, 0x1e, 0x5c, 0x56, 0xb2, 0x2f, 0x4e, 0xab, 0x36, 0xaa, 0x1a, 0x81, + 0x2a, 0x1d, 0xae, 0x8d, 0x28, 0x73, 0xcb, 0x2c, 0x2a, 0x52, 0x1d, 0x32, + 0x00, 0x19, 0xc7, 0xca, 0xb1, 0xef, 0xb1, 0x1f, 0xa4, 0x59, 0x5c, 0x53, + 0x4c, 0xe5, 0x27, 0xd4, 0x3b, 0xa6, 0x05, 0xf7 +}; +static const uint8_t ac_dsa_vect160_priv_val[] = { +/* X */ + 0x13, 0x32, 0xc3, 0xc6, 0xe2, 0xd1, 0xb7, 0xb1, 0x6f, 0x50, 0x1b, 0x6d, + 0x48, 0xc7, 0xb8, 0x66, 0x62, 0x8f, 0x0c, 0x82, 0xbf, 0x33, 0x35, 0x45, + 0x35, 0xdf, 0x99, 0xa8, 0x43, 0xdd, 0x68, 0xce +}; +static const uint8_t ac_dsa_vect160_pub_val[] = { +/* Y */ + 0x06, 0xda, 0xb4, 0x8a, 0x07, 0x6e, 0x8c, 0xec, 0x27, 0xd4, 0xc4, 0xfb, + 0x98, 0xe7, 0xc0, 0x0f, 0x36, 0xbe, 0xd7, 0x3f, 0x11, 0xe4, 0x91, 0xd9, + 0x13, 0x86, 0x4c, 0xae, 0x0f, 0xdf, 0x88, 0x34, 0x68, 0xd7, 0x35, 0xde, + 0xee, 0x52, 0x51, 0xdd, 0x38, 0xa1, 0xf8, 0xb1, 0xd2, 0xbc, 0x19, 0xd3, + 0x7f, 0x31, 0x87, 0xa4, 0xef, 0x69, 0xc3, 0x3d, 0xc9, 0x52, 0x88, 0x01, + 0xa2, 0x3a, 0x98, 0xd9, 0x6f, 0xd3, 0xf1, 0x29, 0xb8, 0xca, 0x29, 0x41, + 0x42, 0x1b, 0xa1, 0x82, 0x8e, 0x0c, 0x4f, 0x8d, 0x88, 0xc5, 0x31, 0x93, + 0x93, 0x02, 0x92, 0xa0, 0xdf, 0x11, 0x47, 0xb0, 0x7c, 0x20, 0xaa, 0x72, + 0x6c, 0x71, 0x77, 0xef, 0x66, 0x0d, 0xdd, 0x4e, 0xcd, 0xd7, 0x33, 0x15, + 0xd4, 0xb9, 0x35, 0x60, 0x13, 0xe1, 0x15, 0xf0, 0x67, 0xe8, 0x43, 0xc8, + 0x96, 0xc1, 0xa5, 0x4c, 0x81, 0xff, 0xab, 0x1b, 0xfe, 0x7c, 0x78, 0x5e, + 0xde, 0xc3, 0x2f, 0xba, 0x65, 0x2b, 0xab, 0xfd, 0xaa, 0xa0, 0x39, 0xb0, + 0x56, 0x8c, 0x6b, 0xeb, 0x7d, 0x13, 0xfb, 0x4e, 0x45, 0x88, 0x14, 0x0e, + 0xd6, 0x26, 0xb1, 0x87, 0x49, 0xb0, 0xf7, 0x9f, 0x66, 0x9f, 0x6e, 0x70, + 0x45, 0x73, 0x8c, 0xf5, 0x0a, 0x6d, 0x00, 0x28, 0xba, 0x11, 0xfe, 0x18, + 0x45, 0xa2, 0xdc, 0xbd, 0x9c, 0x1b, 0x02, 0x33, 0x6f, 0xb3, 0x0e, 0xaa, + 0xa3, 0x97, 0x41, 0x8f, 0xe1, 0x7e, 0x14, 0x98, 0x29, 0xca, 0xb1, 0x3d, + 0x2c, 0x2e, 0x6b, 0x90, 0xe5, 0xcc, 0x81, 0x83, 0x4e, 0x32, 0xfc, 0xa8, + 0xa1, 0x73, 0x63, 0x4e, 0x01, 0xf9, 0xa9, 0x73, 0xe0, 0x29, 0x64, 0x4f, + 0x01, 0x65, 0xb3, 0x03, 0x3d, 0xfb, 0x05, 0x4d, 0xd2, 0x1d, 0x65, 0xe0, + 0xc0, 0xe1, 0x37, 0xb4, 0x8c, 0x34, 0xd4, 0x21, 0x34, 0xc4, 0x7b, 0x97, + 0x24, 0x33, 0xcc, 0xde +}; +/* K = 167b97578e52869f49730df464f7e8d786594bb830d72db9af2cc88324ded288 */ +static const uint8_t ac_dsa_vect160_out[] = { +/* R */ + 0x1d, 0x60, 0x0a, 0x74, 0x5a, 0x1d, 0xec, 0x93, 0x38, 0x68, 0xdc, 0x53, + 0x5a, 0x19, 0xee, 0x9f, 0x1a, 0xf8, 0xbf, 0x09, 0xb5, 0xab, 0xee, 0x15, + 0xdc, 0x4f, 0x7c, 0xbc, 0xb9, 0x5a, 0xc8, 0xc5, +/* S */ + 0x23, 0xb8, 0x10, 0x97, 0xd5, 0x83, 0x34, 0x2e, 0xbe, 0x4a, 0xed, 0x36, + 0x4a, 0x7a, 0xf9, 0x88, 0x2f, 0x74, 0xe6, 0x45, 0x18, 0xaa, 0xed, 0xce, + 0x34, 0x6c, 0x91, 0xd6, 0xd7, 0xac, 0x47, 0x0b +}; +#define ac_dsa_vect161_prime ac_dsa_vect151_prime +#define ac_dsa_vect161_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect161_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect161_ptx[] = { +/* Msg */ + 0xa9, 0x2e, 0x2d, 0xdb, 0xfd, 0x18, 0xcd, 0x30, 0x73, 0x73, 0xfc, 0xb3, + 0x9d, 0xff, 0xc3, 0x3e, 0x0b, 0x91, 0xa4, 0x8c, 0x62, 0x07, 0x1f, 0x2f, + 0x7a, 0x8e, 0x50, 0xdb, 0xf2, 0xc2, 0x90, 0x88, 0x93, 0x07, 0x97, 0x5b, + 0x6a, 0xcd, 0x64, 0x2c, 0x8e, 0x3d, 0x34, 0x44, 0xac, 0xac, 0x98, 0xc2, + 0x2e, 0xd0, 0x65, 0x51, 0xfe, 0xc5, 0xdc, 0x7c, 0x9f, 0x22, 0x43, 0xb6, + 0x81, 0xcc, 0x9f, 0xa4, 0xfc, 0xc1, 0x2c, 0x31, 0x82, 0x37, 0xe9, 0xa5, + 0xdf, 0x0a, 0x77, 0xac, 0x22, 0x40, 0x20, 0x39, 0xce, 0xf3, 0x1b, 0x1e, + 0x62, 0x3a, 0xf5, 0x82, 0x12, 0xa2, 0x2e, 0x7e, 0x60, 0x41, 0x9b, 0xb3, + 0x6b, 0x77, 0x7c, 0xf6, 0xce, 0x65, 0xdd, 0x1f, 0x56, 0x96, 0x3e, 0xb2, + 0x8b, 0x77, 0x06, 0xf1, 0x37, 0xc0, 0xf7, 0x36, 0x3a, 0x00, 0x2d, 0x82, + 0x7e, 0x45, 0xba, 0xdc, 0x20, 0x23, 0x3c, 0x16 +}; +static const uint8_t ac_dsa_vect161_priv_val[] = { +/* X */ + 0x11, 0x9a, 0xb8, 0xa6, 0x3a, 0x22, 0xa8, 0x9b, 0xaf, 0x4e, 0xb8, 0xf0, + 0x16, 0xdc, 0xce, 0x94, 0x23, 0xd5, 0xf4, 0x0a, 0x67, 0x7b, 0x25, 0x8f, + 0xab, 0x07, 0x2a, 0x8c, 0xb6, 0x22, 0xeb, 0xe5 +}; +static const uint8_t ac_dsa_vect161_pub_val[] = { +/* Y */ + 0x51, 0x41, 0x22, 0x3f, 0x46, 0x97, 0xde, 0x27, 0x22, 0x69, 0xf3, 0xd9, + 0x94, 0x37, 0xc4, 0x8d, 0xba, 0x5a, 0xb7, 0xf1, 0x37, 0x3f, 0xc6, 0xba, + 0xd8, 0x16, 0x10, 0x18, 0xc5, 0xd6, 0xfc, 0xe2, 0xbc, 0xcc, 0x40, 0xca, + 0x78, 0xe4, 0xd7, 0x3b, 0x6e, 0xeb, 0x09, 0x6f, 0x17, 0x5c, 0x4c, 0xd0, + 0xc8, 0xe9, 0xf3, 0xe9, 0x31, 0x19, 0x51, 0xd5, 0x1e, 0xa2, 0x44, 0xfd, + 0x33, 0xd9, 0xe4, 0x7d, 0xe7, 0x5f, 0x10, 0x00, 0x24, 0x8f, 0xdc, 0x00, + 0x3b, 0xc0, 0x7b, 0x50, 0x1c, 0xe5, 0x8f, 0x6e, 0xc1, 0xae, 0xd1, 0x75, + 0x4c, 0x36, 0x82, 0x6c, 0xd9, 0x19, 0x76, 0xb4, 0x08, 0xeb, 0x7a, 0xa9, + 0xbc, 0x42, 0x44, 0x80, 0x58, 0xff, 0xd3, 0xb4, 0xe5, 0x13, 0xc6, 0x58, + 0x9f, 0x8e, 0x1b, 0xc1, 0x45, 0xa4, 0x7b, 0x24, 0x70, 0xe7, 0x24, 0x1e, + 0x23, 0x25, 0xe5, 0x43, 0x02, 0x25, 0x5c, 0x3d, 0x6d, 0x97, 0xab, 0xc5, + 0xc6, 0x05, 0x62, 0x66, 0xa9, 0x52, 0x3d, 0x46, 0x1f, 0xc7, 0x44, 0x14, + 0x6d, 0xa3, 0x5c, 0x04, 0xa4, 0xfc, 0x0b, 0x09, 0x58, 0x81, 0xcb, 0x94, + 0xfc, 0x4c, 0x03, 0xbb, 0x86, 0x23, 0x95, 0x39, 0x28, 0x49, 0x0d, 0xbe, + 0x7f, 0x84, 0xef, 0x68, 0x66, 0x7f, 0x23, 0xd4, 0xcb, 0x3e, 0xd8, 0x87, + 0x44, 0x9f, 0x77, 0xae, 0xb1, 0x58, 0xa2, 0x6d, 0x1b, 0x39, 0xb4, 0xe6, + 0x29, 0x7f, 0x23, 0xd4, 0x9f, 0x5b, 0x41, 0xf1, 0x70, 0xe7, 0x2f, 0x72, + 0x13, 0xee, 0x40, 0x36, 0x4c, 0x1c, 0x9a, 0x63, 0x98, 0x5f, 0x69, 0xe4, + 0x4e, 0xac, 0xdf, 0xdc, 0xb5, 0x8c, 0x35, 0xda, 0xce, 0x8b, 0x93, 0x5d, + 0x07, 0x89, 0xa8, 0xc0, 0x66, 0x9a, 0x23, 0xd6, 0x73, 0x92, 0x9b, 0x2a, + 0x58, 0x2d, 0x6d, 0x3b, 0x2f, 0x9e, 0x67, 0xbe, 0x89, 0x18, 0x90, 0xda, + 0x12, 0x36, 0xc6, 0xf0 +}; +/* K = 77cefd7a6b0fcd0237ff8f51c458e5e8a79116eba6f11ea1af7f29aa608393e5 */ +static const uint8_t ac_dsa_vect161_out[] = { +/* R */ + 0x34, 0xa6, 0x5e, 0x99, 0xbf, 0x01, 0x69, 0x8b, 0x5a, 0x68, 0xf2, 0x15, + 0xb9, 0xc2, 0x92, 0x11, 0x5d, 0x17, 0xb3, 0xc2, 0x02, 0xea, 0x1f, 0xda, + 0x17, 0xfc, 0xd8, 0xa0, 0xcd, 0x74, 0xb6, 0x36, +/* S */ + 0x7e, 0x67, 0xd4, 0x42, 0xb8, 0xf9, 0xac, 0x29, 0x74, 0xe8, 0x4b, 0xa6, + 0x5a, 0xef, 0xf0, 0xdf, 0x5f, 0x83, 0xc2, 0x71, 0xec, 0xe7, 0x92, 0xa8, + 0xda, 0xb9, 0xc4, 0xae, 0xe8, 0x7b, 0xfe, 0xa8 +}; +#define ac_dsa_vect162_prime ac_dsa_vect151_prime +#define ac_dsa_vect162_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect162_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect162_ptx[] = { +/* Msg */ + 0xb5, 0xaa, 0x1c, 0xfe, 0x23, 0x48, 0xd5, 0x7f, 0x0e, 0x53, 0x33, 0xfc, + 0x70, 0x27, 0x6d, 0x24, 0x18, 0xdd, 0xda, 0x49, 0x12, 0x2f, 0x4a, 0x88, + 0xe8, 0x01, 0x0f, 0x6f, 0x78, 0xdc, 0x82, 0x9b, 0xa5, 0xc7, 0xcc, 0x68, + 0xdb, 0x66, 0x40, 0x80, 0x94, 0x5c, 0x43, 0xee, 0xb7, 0x05, 0xc2, 0xef, + 0x13, 0xde, 0x6e, 0x4b, 0x8f, 0x4d, 0xe1, 0xd0, 0x4f, 0xb3, 0x3d, 0x5b, + 0xcd, 0x78, 0x93, 0xd8, 0xca, 0x8b, 0xfd, 0xe3, 0x8c, 0x9f, 0xec, 0xa6, + 0xc4, 0xec, 0x03, 0xb2, 0xce, 0x7b, 0x35, 0xed, 0x60, 0xa6, 0xa4, 0x3f, + 0x7f, 0xc9, 0xed, 0x08, 0x06, 0x1a, 0x09, 0x9b, 0x3e, 0xee, 0xae, 0x7f, + 0x0f, 0x15, 0x16, 0x14, 0x9d, 0x17, 0x5a, 0x95, 0x3f, 0x52, 0xc8, 0xc5, + 0x18, 0xf3, 0xad, 0x24, 0x7c, 0x9f, 0xba, 0x23, 0xf1, 0xf8, 0x29, 0xd5, + 0xca, 0xe6, 0x26, 0x73, 0xee, 0x20, 0x1a, 0xda +}; +static const uint8_t ac_dsa_vect162_priv_val[] = { +/* X */ + 0x4b, 0x75, 0xdb, 0x03, 0x4e, 0xd0, 0xb8, 0x4d, 0xfc, 0xc6, 0x0b, 0x49, + 0x3a, 0x00, 0x94, 0x0e, 0x80, 0x5f, 0xeb, 0x78, 0x57, 0x5f, 0xd2, 0x56, + 0xb2, 0x4d, 0x14, 0x6b, 0x05, 0xa9, 0x50, 0x0c +}; +static const uint8_t ac_dsa_vect162_pub_val[] = { +/* Y */ + 0x0b, 0x66, 0xef, 0x2c, 0x7a, 0x34, 0x20, 0x5d, 0x70, 0xfc, 0x36, 0x40, + 0x49, 0x57, 0x04, 0x3c, 0xf4, 0x6b, 0x28, 0xac, 0x4f, 0x08, 0x3e, 0xba, + 0xc3, 0x78, 0x7f, 0x55, 0xe8, 0xdd, 0x1f, 0x75, 0xd9, 0x19, 0x3a, 0x84, + 0x27, 0x59, 0x37, 0x6f, 0x05, 0x08, 0xc9, 0x4c, 0xc7, 0x52, 0x8d, 0x66, + 0x11, 0xb5, 0x0a, 0x73, 0x26, 0x1a, 0x4a, 0x5c, 0xff, 0x73, 0x0d, 0x99, + 0x85, 0xbb, 0x34, 0x1d, 0xfd, 0x73, 0x9a, 0x4e, 0x96, 0x3d, 0x1c, 0x40, + 0xf1, 0x14, 0xd7, 0xa7, 0xac, 0xe8, 0x9e, 0x81, 0xdd, 0x70, 0x86, 0x1e, + 0xfe, 0xf2, 0xba, 0x9d, 0x1c, 0x64, 0x25, 0xd5, 0xf8, 0x58, 0x09, 0x05, + 0x9e, 0x8e, 0xf3, 0x1f, 0x45, 0x3c, 0x97, 0x74, 0x3f, 0xcc, 0x94, 0xd3, + 0xb1, 0xbd, 0x62, 0x08, 0x4e, 0x97, 0x57, 0x90, 0xb3, 0x71, 0x93, 0xeb, + 0x40, 0x58, 0x45, 0x4a, 0xb2, 0x83, 0xfe, 0x2b, 0xaf, 0xaa, 0xe8, 0x03, + 0xde, 0x89, 0x28, 0x79, 0x55, 0x4a, 0x34, 0x0b, 0x9a, 0x3e, 0x25, 0x32, + 0x93, 0x1e, 0xb9, 0x5d, 0x3a, 0xc5, 0xeb, 0x3f, 0x29, 0x0a, 0x3f, 0x56, + 0x93, 0x69, 0x51, 0x28, 0x8e, 0x1c, 0x05, 0xbd, 0xa1, 0xfa, 0x74, 0xdc, + 0x78, 0xd6, 0x31, 0xc2, 0xe7, 0xa5, 0x63, 0x67, 0xec, 0x57, 0x81, 0x01, + 0x9d, 0xfe, 0xe7, 0x14, 0x53, 0xea, 0x6b, 0xbd, 0x90, 0x77, 0x8e, 0x92, + 0xfe, 0xa8, 0xc2, 0x6b, 0xd6, 0xa8, 0x23, 0xfb, 0xca, 0x71, 0x57, 0x7b, + 0x63, 0x35, 0xf3, 0xbd, 0xf4, 0x0a, 0x30, 0x83, 0x6e, 0x94, 0x8d, 0xb0, + 0x32, 0xdb, 0x5a, 0x46, 0x03, 0xdd, 0x31, 0xb8, 0x51, 0xec, 0xbb, 0xdf, + 0x76, 0xb4, 0xa6, 0xc9, 0x95, 0x1d, 0x21, 0x92, 0xb9, 0x7f, 0xf0, 0x1d, + 0xaa, 0x5c, 0xb0, 0x30, 0xe1, 0x5a, 0xd1, 0xd4, 0xcf, 0xf3, 0x67, 0xf7, + 0x00, 0xe7, 0x9f, 0xfb +}; +/* K = 654aa8be3b7bfc32f9b560b57a88a8aec1cfda276661283b7f44dd3b0944c20f */ +static const uint8_t ac_dsa_vect162_out[] = { +/* R */ + 0x51, 0x7f, 0x7d, 0xf4, 0x83, 0x1f, 0xbd, 0x01, 0x90, 0x8b, 0x92, 0x18, + 0xb1, 0x7a, 0xe1, 0xc4, 0x0e, 0x00, 0xc5, 0x34, 0x04, 0xb3, 0xbd, 0x72, + 0xb6, 0x4f, 0x67, 0xce, 0xe7, 0x52, 0x15, 0xf2, +/* S */ + 0x19, 0x03, 0x43, 0x4a, 0x72, 0x7c, 0x8e, 0xf0, 0xe8, 0x0a, 0x43, 0xdc, + 0xe2, 0x83, 0x4b, 0x80, 0x78, 0x39, 0xef, 0x43, 0xc2, 0x2a, 0xfb, 0x50, + 0x2b, 0x35, 0xa3, 0x81, 0x78, 0x2b, 0xb6, 0x39 +}; +#define ac_dsa_vect163_prime ac_dsa_vect151_prime +#define ac_dsa_vect163_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect163_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect163_ptx[] = { +/* Msg */ + 0x27, 0xaa, 0x81, 0xd2, 0xbc, 0x49, 0x60, 0x1c, 0x3f, 0x6b, 0xce, 0xb0, + 0x87, 0x0b, 0xb5, 0x5d, 0xd1, 0x0e, 0x7b, 0xa6, 0xd1, 0xf8, 0xac, 0xad, + 0xa7, 0x0b, 0x5f, 0x90, 0x2a, 0x0f, 0x40, 0x62, 0xeb, 0x93, 0xae, 0x72, + 0xcd, 0xfd, 0x3f, 0x94, 0x30, 0x99, 0xcc, 0x2a, 0x10, 0xa3, 0xda, 0x7b, + 0xdc, 0x9f, 0x24, 0xb0, 0x0b, 0xf3, 0x6a, 0x29, 0xd7, 0x51, 0x36, 0xaf, + 0x10, 0xbb, 0x71, 0xec, 0x9c, 0x19, 0x32, 0x05, 0x8e, 0x22, 0xec, 0x9c, + 0x06, 0x00, 0xd1, 0x73, 0xd3, 0x79, 0x70, 0xd5, 0x8a, 0xe1, 0xf6, 0x6c, + 0xef, 0xd2, 0x7e, 0x29, 0x05, 0xaf, 0xdd, 0xe4, 0x22, 0x39, 0x79, 0xb4, + 0x04, 0x1f, 0xd7, 0xd7, 0x16, 0x6e, 0xa3, 0x26, 0xbe, 0xfd, 0x5d, 0xd8, + 0x96, 0xef, 0x47, 0xab, 0xc6, 0xd0, 0x45, 0xc1, 0xca, 0x23, 0xc1, 0x95, + 0x3a, 0x6e, 0x12, 0xcc, 0x3c, 0x54, 0xb4, 0xf6 +}; +static const uint8_t ac_dsa_vect163_priv_val[] = { +/* X */ + 0x7e, 0x6b, 0x77, 0xd4, 0xbc, 0x92, 0x20, 0xc3, 0x35, 0x2e, 0x91, 0xab, + 0xea, 0x67, 0xe3, 0x3a, 0x33, 0x5a, 0xce, 0x34, 0xec, 0x45, 0x16, 0x64, + 0x6e, 0x8a, 0x4f, 0xf0, 0x98, 0x16, 0x6f, 0xf4 +}; +static const uint8_t ac_dsa_vect163_pub_val[] = { +/* Y */ + 0x93, 0x2b, 0x9c, 0x0f, 0x2d, 0x31, 0x0b, 0x6b, 0xfe, 0xe8, 0x00, 0xc0, + 0x74, 0xa0, 0x96, 0x9e, 0xfa, 0x24, 0x62, 0x44, 0xfb, 0x06, 0x2a, 0x74, + 0x5a, 0x9a, 0x3c, 0xfe, 0x6f, 0x53, 0x36, 0xa3, 0x13, 0x19, 0x2e, 0x92, + 0xa2, 0x02, 0x7e, 0x1d, 0x2c, 0x3c, 0xfa, 0x93, 0xaa, 0xc5, 0x3d, 0xfe, + 0x05, 0xcb, 0x8f, 0x83, 0x21, 0xac, 0x88, 0x2a, 0x63, 0xbd, 0x37, 0x5a, + 0xf0, 0xf3, 0xd9, 0xec, 0xc7, 0x3a, 0xee, 0xbe, 0x12, 0x67, 0xf4, 0x73, + 0xa9, 0xf9, 0x0b, 0x94, 0xf5, 0xb6, 0xde, 0x43, 0x57, 0xb7, 0x4e, 0xb3, + 0x0c, 0xd4, 0x1a, 0xea, 0xfc, 0x25, 0x9e, 0x85, 0xca, 0xc7, 0xd3, 0x65, + 0xee, 0x33, 0x38, 0x2a, 0x58, 0x4e, 0xec, 0x63, 0x71, 0x9e, 0xa3, 0x25, + 0xa2, 0x41, 0x4e, 0x11, 0x6f, 0x84, 0xd2, 0xaf, 0x96, 0x54, 0x26, 0x8e, + 0xc4, 0x4d, 0x6e, 0xa2, 0xe9, 0x81, 0x58, 0x1d, 0x45, 0xd8, 0x05, 0xb3, + 0x83, 0xd8, 0x5c, 0x13, 0x0d, 0x2d, 0xcd, 0x1c, 0x71, 0xfa, 0x68, 0xd9, + 0xc7, 0x6d, 0x79, 0xaa, 0x81, 0x96, 0x15, 0x2c, 0x1d, 0x94, 0x40, 0xc3, + 0x3d, 0x99, 0xde, 0x45, 0x1a, 0x35, 0x9e, 0x0d, 0x2c, 0x51, 0xd6, 0xaa, + 0xec, 0xb2, 0x67, 0x95, 0x40, 0x6e, 0x52, 0x8f, 0x5d, 0xe3, 0xe0, 0x09, + 0x47, 0xd3, 0xda, 0xcc, 0x69, 0x5c, 0x08, 0xa9, 0x60, 0x88, 0x9a, 0x2e, + 0x94, 0xec, 0xf0, 0xa4, 0x61, 0xc0, 0x2a, 0xfc, 0x58, 0xb5, 0x1e, 0x00, + 0x36, 0x9c, 0x73, 0xc8, 0x14, 0x0e, 0x8b, 0x92, 0x38, 0x8c, 0xaa, 0xbd, + 0x1f, 0x37, 0xa6, 0x2d, 0x1b, 0x21, 0x0e, 0x0f, 0x31, 0x41, 0x27, 0xf4, + 0x6b, 0x57, 0x6a, 0x4b, 0x8e, 0xde, 0xb3, 0x47, 0x13, 0xaa, 0x41, 0x36, + 0xb8, 0xa1, 0x87, 0x5b, 0xba, 0x8a, 0x59, 0x37, 0x06, 0x65, 0x44, 0xe3, + 0x4c, 0x20, 0x6a, 0xa4 +}; +/* K = 73c28bca3c8067da792f6312153b298a8f714cad70bb2349803b6dad024f6bc1 */ +static const uint8_t ac_dsa_vect163_out[] = { +/* R */ + 0x05, 0x05, 0x7a, 0x98, 0x2a, 0xb4, 0xa2, 0xe3, 0x22, 0x38, 0xef, 0x2e, + 0x3e, 0xdb, 0xa0, 0x7f, 0xd1, 0x93, 0xd9, 0x0c, 0x5f, 0x05, 0x3c, 0x83, + 0xa9, 0xf1, 0x76, 0xe2, 0x1a, 0x9d, 0x52, 0x08, +/* S */ + 0x03, 0xc2, 0xb2, 0x6c, 0xf4, 0x6b, 0x7f, 0x72, 0x69, 0x1a, 0x72, 0xd7, + 0xcb, 0xf3, 0x36, 0x53, 0xdf, 0x34, 0x7f, 0x02, 0xb0, 0x68, 0x3e, 0xbc, + 0x6c, 0xb7, 0xea, 0x7e, 0x72, 0xdc, 0x8a, 0x0a +}; +#define ac_dsa_vect164_prime ac_dsa_vect151_prime +#define ac_dsa_vect164_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect164_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect164_ptx[] = { +/* Msg */ + 0x75, 0x27, 0x53, 0x3f, 0x2d, 0x10, 0xc1, 0x80, 0x78, 0xf5, 0xa8, 0xde, + 0xc3, 0x50, 0xcd, 0xfa, 0xd0, 0x6d, 0x31, 0x57, 0x87, 0x1e, 0x4f, 0xf7, + 0xd7, 0xc2, 0xb7, 0xab, 0x11, 0xdf, 0xf2, 0x32, 0xd3, 0x4f, 0x07, 0x69, + 0x92, 0x78, 0xf0, 0x75, 0x44, 0x2e, 0x1d, 0x4e, 0xe0, 0x0c, 0xd6, 0xe8, + 0x7c, 0x19, 0x31, 0x33, 0x38, 0x41, 0xc3, 0x99, 0x57, 0x6f, 0x4e, 0x58, + 0x7a, 0x25, 0x16, 0x84, 0xe7, 0x31, 0xf7, 0xc8, 0x36, 0x9f, 0x71, 0x26, + 0x56, 0xbc, 0x1e, 0x6c, 0x2d, 0x20, 0x9f, 0x51, 0x11, 0x79, 0xda, 0x09, + 0x36, 0x8d, 0x93, 0x29, 0x0e, 0x05, 0x8e, 0x0c, 0xe9, 0xb6, 0x53, 0x0a, + 0xc6, 0xc5, 0xe4, 0xcf, 0x0a, 0x1b, 0x22, 0xd5, 0x88, 0xd9, 0x8f, 0x32, + 0xb3, 0x4e, 0x85, 0x20, 0x6e, 0x09, 0xaa, 0xc0, 0x4a, 0x0e, 0x1f, 0x2a, + 0xe2, 0xa5, 0xcf, 0xda, 0xc4, 0xe6, 0xe2, 0xb3 +}; +static const uint8_t ac_dsa_vect164_priv_val[] = { +/* X */ + 0x40, 0x79, 0x2e, 0x5a, 0xb4, 0x65, 0x18, 0xc6, 0xff, 0xcf, 0x53, 0x57, + 0xf0, 0xc5, 0xde, 0x5d, 0x9e, 0x2d, 0xe9, 0x9c, 0x92, 0xae, 0xbe, 0xa8, + 0x2a, 0x30, 0x7a, 0xb0, 0xf5, 0xad, 0x25, 0x2b +}; +static const uint8_t ac_dsa_vect164_pub_val[] = { +/* Y */ + 0x72, 0xc4, 0x65, 0x05, 0xe4, 0xb0, 0x71, 0xf4, 0x6e, 0xd6, 0xb6, 0xd5, + 0x30, 0x80, 0x16, 0x64, 0xa4, 0xfd, 0x51, 0x8e, 0x4c, 0x6b, 0xe8, 0x46, + 0x8a, 0x38, 0xc2, 0x2b, 0xf7, 0x4e, 0xd9, 0x66, 0xfd, 0xc7, 0xbf, 0xd7, + 0xc5, 0x72, 0x21, 0x89, 0x98, 0xfc, 0x4c, 0x14, 0x4b, 0x59, 0x46, 0x2a, + 0xf7, 0xe2, 0x94, 0xbd, 0xf5, 0x79, 0x7e, 0xce, 0xa5, 0xcb, 0x2e, 0xdf, + 0x8c, 0x8d, 0x2d, 0xab, 0xba, 0x88, 0xd0, 0xb8, 0x4c, 0xf2, 0x85, 0x24, + 0x36, 0x9c, 0x50, 0x40, 0xb5, 0x8f, 0x09, 0x07, 0x72, 0xda, 0xc0, 0xfe, + 0x45, 0x3c, 0x32, 0x90, 0x7e, 0x9b, 0x6c, 0x74, 0x0f, 0xb2, 0x4e, 0xd4, + 0xda, 0xcb, 0x8f, 0xdd, 0x25, 0xe0, 0x66, 0x1b, 0xc0, 0xd7, 0x9d, 0x41, + 0xf1, 0x03, 0xfb, 0xc8, 0xf9, 0x6b, 0x3e, 0x3a, 0x47, 0x08, 0xa5, 0xa7, + 0xf5, 0xdb, 0xff, 0xc9, 0x8f, 0x34, 0x4b, 0xb7, 0xcc, 0xf0, 0xd5, 0xed, + 0x07, 0xaf, 0x2c, 0x2f, 0x0d, 0x5f, 0x40, 0x7b, 0xcf, 0xef, 0xb5, 0x4d, + 0x9b, 0x94, 0x76, 0x04, 0xe7, 0xa7, 0x83, 0x56, 0x87, 0x4c, 0x01, 0xb8, + 0xc1, 0xfd, 0xd7, 0x49, 0xf6, 0xa3, 0xd6, 0x19, 0xd1, 0x09, 0x0c, 0x83, + 0x72, 0x5e, 0x72, 0x57, 0x06, 0x84, 0x6c, 0x16, 0xbf, 0x9d, 0xfd, 0xf3, + 0x9f, 0x21, 0x80, 0x62, 0x3f, 0x4f, 0x58, 0x54, 0x02, 0xcc, 0x7d, 0x6e, + 0x2c, 0x10, 0xb5, 0x7c, 0x83, 0x00, 0x54, 0x36, 0x86, 0xa3, 0x86, 0x05, + 0x6a, 0x93, 0x1b, 0xe6, 0x33, 0x6b, 0xb6, 0x17, 0x3d, 0x9f, 0xda, 0x8b, + 0x10, 0x2c, 0xf3, 0x29, 0x89, 0xcf, 0x09, 0x78, 0xf9, 0x56, 0xd9, 0xae, + 0x0d, 0x8f, 0x30, 0x75, 0x2f, 0x15, 0x6f, 0x9f, 0x92, 0xd2, 0x95, 0x4e, + 0xf1, 0x31, 0x00, 0xa7, 0x5d, 0x9f, 0x7f, 0xf9, 0x6f, 0xe1, 0x5d, 0xf0, + 0x7e, 0x79, 0x93, 0xe3 +}; +/* K = 0c9fe826a7618108684ba2d74f10ca39168feb85f74d2737fd12d18cf27a2f16 */ +static const uint8_t ac_dsa_vect164_out[] = { +/* R */ + 0x6a, 0xa6, 0xc4, 0xd7, 0xaf, 0xda, 0x30, 0xff, 0x2d, 0x71, 0x78, 0xb5, + 0x2a, 0x3e, 0x43, 0x7e, 0xd5, 0xb0, 0x74, 0x5a, 0x24, 0x7c, 0x9c, 0x9e, + 0x12, 0x0b, 0xd3, 0xe8, 0x33, 0xa1, 0xdf, 0xac, +/* S */ + 0x26, 0xe0, 0x88, 0x79, 0x11, 0xbb, 0x5e, 0xdb, 0x6a, 0x56, 0x6a, 0x2a, + 0x12, 0x76, 0x35, 0x33, 0x91, 0xb1, 0xe4, 0xab, 0x8a, 0xe0, 0xb2, 0x59, + 0xc1, 0xbb, 0xb3, 0xaf, 0x3d, 0x85, 0xb4, 0x39 +}; +#define ac_dsa_vect165_prime ac_dsa_vect151_prime +#define ac_dsa_vect165_sub_prime ac_dsa_vect151_sub_prime +#define ac_dsa_vect165_base ac_dsa_vect151_base +static const uint8_t ac_dsa_vect165_ptx[] = { +/* Msg */ + 0x99, 0x4a, 0x49, 0xe5, 0xe8, 0xa5, 0x69, 0x8f, 0xda, 0xc9, 0xa7, 0xfa, + 0xac, 0x01, 0xfb, 0x09, 0xb2, 0xc6, 0x11, 0x3a, 0x18, 0x66, 0x77, 0x67, + 0x6d, 0x11, 0xe6, 0x04, 0x9d, 0xc9, 0x8c, 0x93, 0xc5, 0x1e, 0xb5, 0x14, + 0x4a, 0xf1, 0x81, 0xe1, 0xef, 0xbf, 0x44, 0x43, 0x9a, 0x13, 0xd2, 0x95, + 0x65, 0x38, 0x54, 0x81, 0x36, 0x71, 0xf0, 0x32, 0xaa, 0x62, 0x25, 0x8c, + 0x14, 0x19, 0x5c, 0x48, 0x64, 0xaf, 0xae, 0x0b, 0x5d, 0x15, 0x4f, 0x97, + 0x56, 0x5c, 0xef, 0x07, 0x5b, 0xbb, 0x6d, 0x97, 0xe3, 0x41, 0x81, 0x41, + 0x03, 0x09, 0xff, 0xe9, 0x8b, 0x45, 0xc1, 0xf8, 0x74, 0x32, 0x63, 0x43, + 0xc3, 0x6c, 0x14, 0xf5, 0x5f, 0xa0, 0x58, 0x48, 0x9d, 0xff, 0x3b, 0x49, + 0xdc, 0x78, 0x88, 0xf4, 0x5a, 0x09, 0x9c, 0x3c, 0x91, 0x9b, 0x25, 0xed, + 0xac, 0x17, 0x06, 0xbb, 0x90, 0xf1, 0x64, 0xca +}; +static const uint8_t ac_dsa_vect165_priv_val[] = { +/* X */ + 0x26, 0x6c, 0xfb, 0xe6, 0x06, 0x01, 0x34, 0xec, 0xe2, 0xc8, 0xb9, 0xe6, + 0xaa, 0x25, 0xbd, 0x6c, 0xc9, 0x35, 0xe4, 0x9c, 0x23, 0xfd, 0xd4, 0xfb, + 0x6a, 0xdb, 0x2e, 0xcd, 0xe6, 0x3a, 0x49, 0x60 +}; +static const uint8_t ac_dsa_vect165_pub_val[] = { +/* Y */ + 0x05, 0xe2, 0x33, 0xac, 0x49, 0xc1, 0xfd, 0xa2, 0xa0, 0xc3, 0xc7, 0x8b, + 0x0b, 0xc7, 0x2f, 0xa3, 0x96, 0x74, 0x05, 0x5d, 0x18, 0x8a, 0x12, 0x4a, + 0x58, 0xab, 0x38, 0x50, 0xd9, 0xa8, 0x88, 0x86, 0x1c, 0x2f, 0xe4, 0xd0, + 0x46, 0xc3, 0xe7, 0xc7, 0x5e, 0xe2, 0x54, 0xde, 0x70, 0xcd, 0xb1, 0xc3, + 0x15, 0x02, 0x01, 0xc2, 0xe0, 0x47, 0x33, 0xeb, 0xcc, 0x25, 0xb8, 0x87, + 0x70, 0xfc, 0x2a, 0xa8, 0x2f, 0x60, 0x52, 0x6b, 0xc6, 0x64, 0x04, 0x7a, + 0x02, 0x6c, 0x22, 0x90, 0xfa, 0xd8, 0xe9, 0xf8, 0x1c, 0xed, 0xdd, 0xde, + 0x7f, 0xe3, 0xba, 0x40, 0x65, 0x35, 0xbf, 0x27, 0x10, 0xd7, 0x9d, 0xa0, + 0x1b, 0xd2, 0xd4, 0x2b, 0xb5, 0xf4, 0x09, 0x9c, 0x3f, 0x8b, 0xc2, 0xac, + 0x86, 0x4b, 0xe7, 0x89, 0x2a, 0xeb, 0x6a, 0x1f, 0x34, 0x02, 0xc8, 0x14, + 0x74, 0xda, 0x23, 0xe0, 0x79, 0x5c, 0xd6, 0xc2, 0x13, 0x67, 0x50, 0x9a, + 0x54, 0x15, 0x91, 0xee, 0x1e, 0x63, 0x64, 0xf7, 0xe7, 0x55, 0xb1, 0x41, + 0x9e, 0x90, 0xaf, 0x86, 0x99, 0x30, 0x15, 0x2f, 0x34, 0xde, 0x51, 0xf0, + 0xf0, 0x6c, 0xa3, 0x07, 0x6e, 0x68, 0xc3, 0xe3, 0xea, 0x7f, 0x4f, 0x1b, + 0xf1, 0xd3, 0xcd, 0xe3, 0xa0, 0xdf, 0xf0, 0xcf, 0xfa, 0x1b, 0x58, 0x42, + 0x75, 0x23, 0x47, 0x08, 0x2d, 0xda, 0x34, 0x75, 0x99, 0x2f, 0x15, 0xa7, + 0x4d, 0x29, 0x85, 0x24, 0xe6, 0x36, 0x22, 0x0b, 0xc9, 0xfa, 0xed, 0x08, + 0xaf, 0x7a, 0xa5, 0xe4, 0x81, 0xba, 0x78, 0xd2, 0xd2, 0xfd, 0x8e, 0x51, + 0x94, 0x2c, 0xfd, 0x08, 0x4e, 0xfe, 0x0e, 0xbd, 0xdd, 0x75, 0x00, 0xef, + 0xc9, 0x5a, 0x6c, 0xad, 0x37, 0xfc, 0x49, 0x23, 0xf9, 0xbf, 0x65, 0x29, + 0x78, 0x05, 0x84, 0x08, 0x76, 0xc6, 0x89, 0xee, 0x07, 0x9b, 0x7f, 0xa6, + 0x16, 0x97, 0x68, 0xfa +}; +/* K = 60f8416735fa49ab567c0bf1b6da434e1df41579699c1a92a3e70e1d90705379 */ +static const uint8_t ac_dsa_vect165_out[] = { +/* R */ + 0x3c, 0xc2, 0x69, 0xbc, 0x7b, 0x89, 0x58, 0x64, 0xa0, 0x32, 0x31, 0x31, + 0x8c, 0xf3, 0x93, 0x79, 0xae, 0x33, 0xc7, 0x18, 0x0a, 0x18, 0xc0, 0x8b, + 0x5a, 0xef, 0x74, 0x14, 0xfd, 0xac, 0x05, 0x8f, +/* S */ + 0x6a, 0x6e, 0xb8, 0x3c, 0x5f, 0xab, 0x10, 0xe3, 0x4f, 0x04, 0x16, 0x62, + 0x8c, 0x82, 0x1a, 0x6d, 0xe0, 0xad, 0x0c, 0x20, 0x24, 0x43, 0xc6, 0xdf, + 0x03, 0x2c, 0xc9, 0xd8, 0xe4, 0x94, 0x8a, 0xc6 +}; +/* [mod = L=2048, N=256, SHA-224] */ +static const uint8_t ac_dsa_vect166_prime[] = { +/* P */ + 0xd0, 0x22, 0x76, 0xeb, 0xf3, 0xc2, 0x2f, 0xfd, 0x66, 0x69, 0x83, 0x18, + 0x3a, 0x47, 0xae, 0x94, 0xc9, 0xbc, 0xcb, 0xcb, 0xf9, 0x5d, 0xdc, 0xb4, + 0x91, 0xd1, 0xf7, 0xce, 0x64, 0x35, 0x49, 0x19, 0x99, 0x92, 0xd3, 0x7c, + 0x79, 0xe7, 0xb0, 0x32, 0xd2, 0x6e, 0xd0, 0x31, 0xb6, 0xba, 0x44, 0x89, + 0xf3, 0x12, 0x58, 0x26, 0xfa, 0xfb, 0x27, 0x26, 0xa9, 0x83, 0x33, 0xeb, + 0xd9, 0xab, 0xdd, 0xe5, 0x92, 0xd8, 0x69, 0x3d, 0x98, 0x59, 0x53, 0x6d, + 0x9c, 0xc3, 0x84, 0x1a, 0x1d, 0x24, 0xe0, 0x44, 0xd3, 0x5a, 0xce, 0xd6, + 0x13, 0x62, 0x56, 0xfc, 0x6d, 0x6b, 0x61, 0x5c, 0xf4, 0xf4, 0x16, 0x3a, + 0xa3, 0x81, 0xeb, 0x2b, 0x4c, 0x48, 0x08, 0x25, 0xa8, 0xec, 0xcc, 0x56, + 0xd8, 0xdd, 0xcf, 0x5f, 0xe6, 0x37, 0xe3, 0x8a, 0xd9, 0xb2, 0x97, 0x4b, + 0xd2, 0xcf, 0x68, 0xbf, 0x27, 0x1e, 0x0d, 0x06, 0x7d, 0x24, 0x65, 0xa8, + 0xb6, 0xb6, 0x60, 0x52, 0x4f, 0x00, 0x82, 0x59, 0x89, 0x45, 0xad, 0xa5, + 0x8e, 0xa6, 0x49, 0xb9, 0x80, 0x4e, 0xb4, 0x75, 0x34, 0x08, 0xc2, 0xc5, + 0x97, 0x68, 0xc4, 0x6a, 0xbb, 0x82, 0xe3, 0x29, 0x5f, 0x3d, 0x9c, 0xa4, + 0x69, 0xf8, 0x4c, 0xc1, 0x87, 0xf5, 0x72, 0xdc, 0x4b, 0x5a, 0x3b, 0x39, + 0x34, 0x6e, 0xc8, 0x39, 0xdf, 0xad, 0x6f, 0x07, 0xd6, 0xd1, 0xf0, 0xe2, + 0x15, 0x20, 0x9b, 0xb0, 0xec, 0xc0, 0x5c, 0x76, 0x7c, 0xf2, 0xe7, 0x94, + 0x3a, 0xc9, 0xcf, 0xb0, 0x2e, 0xee, 0x1e, 0x9e, 0xf5, 0x94, 0x6e, 0x8c, + 0xe8, 0x83, 0x16, 0xb5, 0xe1, 0x5f, 0xdc, 0xf9, 0x5a, 0x13, 0x2e, 0xf2, + 0xe4, 0xbb, 0x08, 0x17, 0x13, 0x65, 0x28, 0xcf, 0xa5, 0xdd, 0x96, 0x53, + 0x2f, 0x9c, 0x3a, 0xbe, 0x5c, 0x42, 0x16, 0x20, 0xed, 0xb6, 0xbc, 0xbd, + 0x52, 0x23, 0x4c, 0xa9 +}; +static const uint8_t ac_dsa_vect166_sub_prime[] = { +/* Q */ + 0x80, 0x00, 0x00, 0x00, 0x12, 0x99, 0x7e, 0x82, 0x85, 0xe4, 0x08, 0x97, + 0x08, 0xf5, 0x28, 0x07, 0x0c, 0x6d, 0x7a, 0xf8, 0xa0, 0xbd, 0x01, 0x40, + 0x9e, 0x7a, 0x07, 0x9c, 0xdb, 0x6f, 0xc5, 0xbb +}; +static const uint8_t ac_dsa_vect166_base[] = { +/* G */ + 0x77, 0x84, 0x53, 0x04, 0x9e, 0xf2, 0x62, 0x14, 0x7f, 0xed, 0x7b, 0x59, + 0xb0, 0xee, 0x67, 0x64, 0x60, 0x7c, 0x51, 0xe7, 0xb5, 0xb5, 0xfc, 0x6f, + 0xea, 0x7a, 0x7a, 0x7b, 0x1d, 0xd6, 0xbb, 0x28, 0x3f, 0x4a, 0x9a, 0xe9, + 0x8e, 0xfd, 0x39, 0x64, 0xb1, 0x55, 0x67, 0x58, 0xcb, 0x15, 0xb2, 0xa5, + 0x3a, 0xf8, 0x61, 0x9e, 0x74, 0xd8, 0x58, 0x98, 0xbe, 0xc7, 0x7d, 0x3b, + 0x3f, 0x38, 0x24, 0x94, 0xae, 0x59, 0x61, 0xa1, 0x3f, 0xfc, 0x74, 0x5d, + 0xa3, 0x86, 0x18, 0x22, 0x91, 0x51, 0x98, 0x00, 0xf9, 0x9d, 0xd7, 0x10, + 0xe0, 0x0a, 0xeb, 0x15, 0xad, 0xee, 0x08, 0x8e, 0x27, 0x98, 0xee, 0x2e, + 0x46, 0xf5, 0x98, 0x52, 0x6c, 0xf0, 0xf4, 0x66, 0x70, 0x55, 0xd1, 0xba, + 0x00, 0x97, 0x50, 0x04, 0x1d, 0xc5, 0xcd, 0xd2, 0x72, 0x5f, 0xf1, 0xd9, + 0x7d, 0xd3, 0x40, 0xc8, 0x51, 0x8a, 0xf7, 0x67, 0x1b, 0x87, 0xd3, 0x9d, + 0x67, 0xae, 0xce, 0xd8, 0x4b, 0x66, 0xf8, 0x4e, 0x07, 0x01, 0xef, 0xc8, + 0x2a, 0x5c, 0x9e, 0xf9, 0x54, 0xee, 0x57, 0x6d, 0x24, 0xc3, 0x85, 0xb1, + 0x4d, 0x63, 0x03, 0x7f, 0x0d, 0x86, 0x6f, 0xd4, 0x24, 0xb4, 0x97, 0x5b, + 0xdd, 0x54, 0x85, 0xed, 0x74, 0x0c, 0xb9, 0x32, 0xe8, 0x43, 0xf9, 0x06, + 0x68, 0x3f, 0x7c, 0x7b, 0x2c, 0x74, 0x77, 0x5d, 0x90, 0x1c, 0x36, 0x1b, + 0x84, 0x7b, 0x51, 0x9c, 0x0d, 0xa6, 0x99, 0x63, 0x8d, 0xa4, 0x0b, 0xd7, + 0x36, 0xb7, 0x83, 0xd2, 0x71, 0x0b, 0x2c, 0x2c, 0xc2, 0x6e, 0xf9, 0x12, + 0x71, 0xbf, 0x4e, 0x2c, 0x19, 0x29, 0xf8, 0x76, 0xe9, 0x02, 0xe2, 0x05, + 0x71, 0x64, 0x22, 0x3b, 0xc7, 0x8d, 0x6a, 0x2b, 0x9f, 0x6c, 0x0c, 0x7a, + 0x7c, 0xb8, 0x59, 0x22, 0xf7, 0xd6, 0xc4, 0x28, 0x7a, 0xe2, 0x38, 0x61, + 0xf8, 0x12, 0x88, 0x48 +}; +static const uint8_t ac_dsa_vect166_ptx[] = { +/* Msg */ + 0x39, 0xf2, 0xd8, 0xd5, 0x03, 0xaa, 0xe8, 0xcd, 0x17, 0x85, 0x44, 0x56, + 0xec, 0xfa, 0xd4, 0x9a, 0x18, 0x90, 0x0d, 0x43, 0x75, 0x41, 0x2b, 0xc6, + 0x89, 0x18, 0x1e, 0xd9, 0xc2, 0xcc, 0xaf, 0xea, 0x98, 0xdc, 0xa6, 0x89, + 0xa7, 0x2d, 0xc7, 0x5e, 0x53, 0x67, 0xd3, 0xd3, 0xab, 0xfc, 0x21, 0x69, + 0x70, 0x0d, 0x58, 0x91, 0xcf, 0xf7, 0x0f, 0x69, 0xd9, 0xac, 0xa0, 0x93, + 0xb0, 0x61, 0xb9, 0xf5, 0x05, 0x7f, 0x94, 0x63, 0x6b, 0xc2, 0x78, 0x31, + 0x15, 0x25, 0x43, 0x44, 0xfb, 0x12, 0xe3, 0x3b, 0x16, 0x72, 0x72, 0xe1, + 0x98, 0x83, 0x8a, 0x87, 0x28, 0xe7, 0x74, 0x4e, 0xa9, 0xa2, 0xe8, 0x24, + 0x8e, 0x34, 0xd5, 0x90, 0x6e, 0x29, 0x83, 0x02, 0x47, 0x26, 0x37, 0xb8, + 0x79, 0xde, 0x91, 0xc1, 0xa6, 0xf9, 0xf3, 0x31, 0xa5, 0xcf, 0x98, 0xa5, + 0xaf, 0x29, 0x13, 0x29, 0x90, 0xd2, 0x74, 0x16 +}; +static const uint8_t ac_dsa_vect166_priv_val[] = { +/* X */ + 0x6b, 0xa8, 0x1e, 0x6c, 0xd4, 0x36, 0x77, 0x98, 0xaa, 0xab, 0x8b, 0x7a, + 0xf1, 0x13, 0x51, 0x83, 0xa3, 0x7c, 0x42, 0xa7, 0x66, 0xdb, 0xd6, 0x8c, + 0xd2, 0xdc, 0xe7, 0x8f, 0x26, 0x70, 0xef, 0x0f +}; +static const uint8_t ac_dsa_vect166_pub_val[] = { +/* Y */ + 0x7b, 0xb3, 0x1e, 0x98, 0xc7, 0xa0, 0x43, 0x7f, 0x97, 0x8a, 0x73, 0xd5, + 0xdc, 0xfb, 0xdf, 0xbb, 0x09, 0xcc, 0x24, 0x99, 0xdf, 0xaf, 0x1e, 0xb5, + 0x25, 0x6b, 0xcc, 0xd6, 0x35, 0x8c, 0xab, 0xb5, 0xf6, 0x7d, 0x04, 0xa4, + 0x28, 0x23, 0x46, 0x3b, 0x7e, 0x95, 0x7f, 0x2b, 0x92, 0x13, 0xf1, 0xfa, + 0x8e, 0x5a, 0x98, 0xd6, 0x14, 0x48, 0x47, 0x01, 0xab, 0xb8, 0xc7, 0xd6, + 0x76, 0x41, 0xfe, 0x6e, 0xd0, 0x6f, 0xa4, 0x52, 0x7b, 0x49, 0x3d, 0xda, + 0xb2, 0xe7, 0x46, 0x40, 0xfd, 0xe3, 0xde, 0x70, 0xda, 0x69, 0x3f, 0x1d, + 0xb2, 0xb8, 0xe2, 0x64, 0x17, 0x04, 0x0a, 0xf0, 0xee, 0xa6, 0xca, 0xb4, + 0x51, 0xa7, 0x95, 0xa5, 0x2e, 0x18, 0x7d, 0x2e, 0xe2, 0x41, 0xb9, 0x3f, + 0x65, 0xc8, 0x6c, 0x6d, 0x66, 0xf4, 0x58, 0x34, 0xcc, 0xe1, 0x65, 0xac, + 0x5e, 0xb6, 0x70, 0xd4, 0xf0, 0x09, 0x5c, 0x23, 0xce, 0x97, 0x57, 0xe3, + 0xbd, 0xc6, 0x36, 0xf9, 0x91, 0xee, 0x00, 0x73, 0xd9, 0x0a, 0x09, 0x20, + 0x2e, 0xdb, 0x35, 0xcc, 0x3e, 0xa1, 0xcf, 0x9a, 0xdc, 0xa1, 0x61, 0x7f, + 0xa0, 0xbf, 0xfd, 0x9c, 0x12, 0x62, 0x29, 0xa6, 0x04, 0xa1, 0xd3, 0xbf, + 0x49, 0x31, 0xdd, 0xf0, 0xb9, 0x94, 0x2d, 0xfc, 0x8a, 0x2f, 0x8c, 0x09, + 0xfc, 0xc9, 0x70, 0x32, 0x56, 0x4a, 0x79, 0xae, 0x1e, 0xbe, 0x1e, 0x2c, + 0xe4, 0x9f, 0xf5, 0x78, 0x39, 0xe7, 0xc4, 0x3f, 0xa6, 0x0b, 0x16, 0x03, + 0xd1, 0x5a, 0x45, 0x08, 0x98, 0xaa, 0x4e, 0x4a, 0x1e, 0xe8, 0x06, 0x57, + 0x94, 0x12, 0x6d, 0x64, 0xf0, 0x13, 0x36, 0x70, 0x96, 0xa8, 0x36, 0x86, + 0xb9, 0xf1, 0x58, 0xc3, 0x3b, 0x10, 0xf5, 0xf3, 0xb3, 0x6c, 0xf1, 0xf6, + 0x35, 0x8b, 0x3f, 0x34, 0xf8, 0x4b, 0x10, 0x1d, 0xc2, 0x6d, 0x3d, 0xb6, + 0x8b, 0xcc, 0x95, 0xc8 +}; +/* K = 45030b79a395b1632700cbaffead97998d02bed8e0656876fc0174e4bdb96f79 */ +static const uint8_t ac_dsa_vect166_out[] = { +/* R */ + 0x05, 0x9b, 0xee, 0x9e, 0x70, 0x8b, 0x7f, 0x20, 0xc3, 0xf7, 0x91, 0xa6, + 0x40, 0xed, 0xee, 0x96, 0x4e, 0x0a, 0xa6, 0x72, 0x89, 0x3c, 0x48, 0x47, + 0x99, 0x71, 0x58, 0x17, 0xb3, 0xa8, 0xf6, 0xd4, +/* S */ + 0x4b, 0xd4, 0x1c, 0x84, 0xa7, 0x24, 0xcc, 0x86, 0xe4, 0xf0, 0x19, 0x4e, + 0xc0, 0xfb, 0xf3, 0x79, 0xe6, 0x54, 0xd0, 0xd7, 0xf6, 0xa1, 0xf0, 0x8b, + 0xd4, 0x68, 0x13, 0x94, 0x22, 0xa5, 0xc3, 0x53 +}; +#define ac_dsa_vect167_prime ac_dsa_vect166_prime +#define ac_dsa_vect167_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect167_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect167_ptx[] = { +/* Msg */ + 0x05, 0x77, 0xee, 0x4a, 0x9b, 0x8d, 0xbe, 0x3c, 0x6f, 0xb9, 0x72, 0x51, + 0x74, 0xe8, 0x99, 0x40, 0xb2, 0x7e, 0x8a, 0x98, 0x92, 0x17, 0xb6, 0x44, + 0x17, 0xe6, 0x6f, 0x39, 0x6a, 0x35, 0xe5, 0x82, 0x4f, 0x21, 0xe5, 0x82, + 0x36, 0xb2, 0x79, 0x10, 0xa3, 0xbe, 0x6b, 0x57, 0xd3, 0x11, 0xaa, 0x77, + 0x8b, 0xef, 0x63, 0xdd, 0x02, 0x5d, 0x94, 0x35, 0x30, 0x1a, 0xef, 0xc9, + 0x22, 0x23, 0xc1, 0xaa, 0xbb, 0x03, 0xd3, 0xd5, 0xd3, 0x85, 0xb1, 0xa3, + 0xd1, 0xf9, 0x37, 0xf0, 0xf1, 0xf7, 0xf8, 0xba, 0xba, 0x91, 0xa0, 0x11, + 0x20, 0x74, 0x80, 0xb5, 0xc2, 0x3a, 0x78, 0xeb, 0xae, 0xa6, 0x9a, 0xe8, + 0xad, 0x43, 0x73, 0xb2, 0xb0, 0x52, 0xd6, 0x0c, 0x54, 0x61, 0x11, 0x14, + 0x79, 0x59, 0x1f, 0x83, 0x30, 0x12, 0x3b, 0xf7, 0x43, 0x70, 0xfb, 0xa6, + 0x6b, 0xc7, 0xe2, 0xb4, 0x00, 0x19, 0x2c, 0x47 +}; +static const uint8_t ac_dsa_vect167_priv_val[] = { +/* X */ + 0x7b, 0xd8, 0x11, 0xcf, 0x60, 0x56, 0xc1, 0xa8, 0x21, 0xa8, 0x5a, 0x31, + 0x69, 0x11, 0x36, 0x39, 0xd7, 0x75, 0x24, 0x7b, 0xc6, 0x57, 0x8c, 0x9e, + 0xeb, 0x28, 0xd4, 0xb0, 0x95, 0x03, 0xac, 0x0b +}; +static const uint8_t ac_dsa_vect167_pub_val[] = { +/* Y */ + 0xc5, 0x4a, 0x57, 0xb0, 0x8f, 0x25, 0x5d, 0xb1, 0xc7, 0x76, 0xbb, 0x21, + 0x26, 0xea, 0x3c, 0x1e, 0x60, 0x22, 0x9f, 0x1e, 0x19, 0x81, 0xe4, 0x3f, + 0x1d, 0x6b, 0x91, 0x10, 0xf9, 0x50, 0xed, 0xd8, 0x24, 0x5e, 0xec, 0xa7, + 0xd5, 0x5b, 0xa0, 0x64, 0x68, 0x04, 0x08, 0x55, 0xb7, 0x36, 0xdb, 0x50, + 0x2f, 0x01, 0xd6, 0xb3, 0xcb, 0x2d, 0x9d, 0x62, 0x1c, 0x4d, 0xb4, 0x4c, + 0xf8, 0xcb, 0x39, 0x0a, 0xb2, 0xae, 0x33, 0x2b, 0xca, 0x21, 0x9e, 0x09, + 0xbb, 0xbb, 0xc2, 0x25, 0x54, 0x1d, 0x4a, 0x0e, 0xc0, 0xb4, 0xf1, 0x1a, + 0x59, 0x1c, 0x07, 0x7f, 0x23, 0x82, 0xf0, 0x4b, 0xd9, 0x3b, 0x36, 0x4c, + 0x94, 0xfb, 0x1c, 0x61, 0x47, 0xff, 0x77, 0x84, 0xe8, 0x25, 0x58, 0xe5, + 0xfb, 0x68, 0x42, 0x74, 0x59, 0xfa, 0x9a, 0x69, 0xd7, 0x8a, 0x9f, 0x60, + 0x51, 0xbd, 0x94, 0x31, 0x88, 0x7a, 0xce, 0x46, 0xfa, 0x49, 0x70, 0xf0, + 0xe2, 0x2d, 0x75, 0xd2, 0xbe, 0xfa, 0x5a, 0x22, 0x8e, 0x48, 0x9e, 0x00, + 0x9a, 0xf9, 0x7c, 0xe9, 0x21, 0x14, 0x08, 0xb4, 0xe5, 0xbf, 0xe3, 0x7d, + 0x3e, 0x07, 0x00, 0xb2, 0x58, 0xb5, 0x41, 0x74, 0xa5, 0x12, 0x5e, 0xb6, + 0xbb, 0xec, 0xa3, 0x88, 0x05, 0xda, 0x53, 0xb1, 0xf5, 0x82, 0x9d, 0xfd, + 0xec, 0x8c, 0x4c, 0x93, 0x76, 0xbf, 0x23, 0x5b, 0x7b, 0x0e, 0xb7, 0x11, + 0x9d, 0x3d, 0x69, 0x76, 0x8b, 0x80, 0xee, 0x02, 0x23, 0x45, 0x89, 0xb8, + 0xd9, 0x5f, 0xaf, 0x80, 0x62, 0xa8, 0xe1, 0xe9, 0xc3, 0xa6, 0x86, 0xb6, + 0x35, 0x0e, 0x30, 0xfa, 0x53, 0x5e, 0xaa, 0xe7, 0x1d, 0x75, 0x3b, 0x7c, + 0x3b, 0x04, 0x8f, 0x8e, 0x97, 0x22, 0x25, 0x4d, 0xed, 0xbc, 0x22, 0x0a, + 0xc9, 0xc9, 0xaf, 0x07, 0x84, 0x53, 0x20, 0x32, 0xab, 0x65, 0xe4, 0x8c, + 0xcf, 0xcf, 0xd6, 0x23 +}; +/* K = 7ce602ece3f821390641dec7ae01b44df0fc822de1c013496bade2e3e44fff0b */ +static const uint8_t ac_dsa_vect167_out[] = { +/* R */ + 0x33, 0xc1, 0x98, 0xea, 0x68, 0xbe, 0xc4, 0xa7, 0xfe, 0xda, 0xf0, 0x30, + 0x9c, 0x31, 0x7d, 0x33, 0x6b, 0x97, 0xd1, 0xeb, 0x1f, 0x1d, 0xc4, 0x4e, + 0xba, 0xf5, 0xc8, 0x5c, 0x5a, 0x3a, 0xfa, 0x98, +/* S */ + 0x5c, 0x9b, 0x23, 0xc1, 0x3b, 0xb6, 0x07, 0xbe, 0x54, 0x73, 0xb3, 0x2a, + 0xe2, 0xb5, 0xe8, 0xf2, 0xa1, 0xe1, 0x8f, 0x59, 0xdf, 0x8c, 0xa7, 0xfd, + 0x93, 0x03, 0xf7, 0x6e, 0xd8, 0xe6, 0x80, 0xe3 +}; +#define ac_dsa_vect168_prime ac_dsa_vect166_prime +#define ac_dsa_vect168_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect168_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect168_ptx[] = { +/* Msg */ + 0xc6, 0x43, 0x69, 0x5d, 0x29, 0xb2, 0x82, 0x10, 0x01, 0x7a, 0xa5, 0xa7, + 0xd1, 0x6e, 0xbe, 0xd8, 0x1b, 0xa0, 0x0a, 0x86, 0x9d, 0x66, 0x81, 0xd1, + 0xc0, 0xfe, 0x90, 0xa5, 0xe8, 0xbe, 0x9d, 0x59, 0x73, 0x29, 0xea, 0x15, + 0xd2, 0x4b, 0xa1, 0x2d, 0x77, 0xe4, 0xc3, 0xf2, 0x16, 0x0b, 0xcb, 0xe8, + 0x08, 0x84, 0x0c, 0x6e, 0x77, 0xb0, 0x52, 0x8b, 0xf9, 0xae, 0x58, 0x87, + 0x38, 0xe2, 0x2f, 0x41, 0x91, 0x0a, 0x80, 0xa7, 0xc6, 0xe3, 0x34, 0x0c, + 0x12, 0x7b, 0x9d, 0xe1, 0x79, 0x45, 0xe7, 0xf9, 0x22, 0x99, 0x53, 0xe2, + 0x85, 0x02, 0x17, 0xb6, 0xd4, 0x86, 0xf7, 0xcc, 0x80, 0x4e, 0x72, 0x0d, + 0xe2, 0x14, 0xce, 0xf0, 0x2d, 0xf4, 0xa8, 0x92, 0xf7, 0xe4, 0x28, 0x98, + 0xf1, 0x5c, 0xaa, 0xd2, 0x6b, 0xb3, 0x0b, 0xfa, 0xf4, 0xb0, 0x55, 0x1a, + 0xee, 0xa1, 0x40, 0x35, 0xcb, 0x75, 0x6b, 0x11 +}; +static const uint8_t ac_dsa_vect168_priv_val[] = { +/* X */ + 0x3f, 0xf2, 0x65, 0x3c, 0xbc, 0x1f, 0x27, 0x25, 0x34, 0x00, 0xa9, 0xb6, + 0xb1, 0xf0, 0x64, 0x24, 0x70, 0x53, 0xc9, 0x81, 0x6c, 0xfd, 0xcb, 0x70, + 0x4b, 0x14, 0xbd, 0xec, 0xe2, 0xa8, 0x55, 0x8b +}; +static const uint8_t ac_dsa_vect168_pub_val[] = { +/* Y */ + 0x17, 0xff, 0x2a, 0x5e, 0xff, 0x39, 0x26, 0xee, 0x15, 0x20, 0xd5, 0xa6, + 0x3a, 0x13, 0xb4, 0xf7, 0x01, 0xdc, 0xee, 0xd2, 0x5a, 0x65, 0x39, 0x66, + 0xf5, 0x25, 0x45, 0x0b, 0x3a, 0x63, 0xb0, 0x32, 0x29, 0xd6, 0x15, 0xec, + 0x54, 0xcf, 0x4f, 0x6d, 0xdb, 0x86, 0x8b, 0x54, 0xdf, 0x36, 0x3f, 0xee, + 0xcc, 0x95, 0xeb, 0x8a, 0x3a, 0xb2, 0x58, 0x7f, 0xc4, 0xde, 0x9c, 0x93, + 0xdc, 0x8f, 0x8d, 0x7f, 0x38, 0xf9, 0x90, 0x82, 0xd2, 0x86, 0x7b, 0x23, + 0xd0, 0x73, 0x58, 0x4c, 0x83, 0x1b, 0xaa, 0x09, 0x61, 0x65, 0x1e, 0x07, + 0x1b, 0x43, 0xf9, 0xd5, 0xda, 0x97, 0xb6, 0x0e, 0x7b, 0x5b, 0x7a, 0x93, + 0x5f, 0x6c, 0x1d, 0xc8, 0x82, 0x79, 0x60, 0x8e, 0x2b, 0xec, 0x5c, 0xac, + 0x61, 0x62, 0x48, 0x80, 0x85, 0xd0, 0x92, 0xa9, 0x7c, 0x6b, 0x6f, 0x24, + 0x53, 0x65, 0x89, 0xb8, 0x01, 0xb6, 0xb4, 0x8d, 0x47, 0x87, 0x96, 0xb5, + 0x2c, 0x05, 0x56, 0x4e, 0x90, 0x4b, 0xc5, 0x8a, 0xc1, 0x50, 0x50, 0x74, + 0xdb, 0x37, 0x34, 0xfc, 0xf3, 0x57, 0x5f, 0x79, 0x95, 0x2b, 0xa0, 0xa2, + 0xa0, 0x69, 0x7e, 0x55, 0xe5, 0x79, 0xd5, 0x08, 0xa4, 0x00, 0xeb, 0xfb, + 0x2d, 0x46, 0x94, 0xb7, 0x20, 0x80, 0x4a, 0x9d, 0x00, 0xf8, 0x84, 0x5e, + 0xf0, 0xa8, 0xe6, 0x90, 0xe6, 0x75, 0xb4, 0xc1, 0xce, 0x07, 0x99, 0x6d, + 0x64, 0xe6, 0x66, 0xb0, 0xd6, 0xa1, 0xd6, 0xfc, 0x6b, 0xbc, 0x3c, 0xd9, + 0xb5, 0xcc, 0x38, 0x64, 0xe5, 0xe8, 0x88, 0xe3, 0xc3, 0x35, 0xe0, 0x5e, + 0x83, 0xc6, 0x7c, 0x00, 0x33, 0xba, 0x5e, 0xfc, 0x3d, 0xcd, 0xec, 0x04, + 0x46, 0xd3, 0xb4, 0x07, 0x93, 0x23, 0x6c, 0xa0, 0x74, 0xc5, 0x4d, 0x2a, + 0x74, 0xda, 0xd2, 0x96, 0xd7, 0xc6, 0x39, 0xde, 0xc9, 0x38, 0xe3, 0xbf, + 0x1c, 0xa0, 0x85, 0xdc +}; +/* K = 356b49268eb799dc4db7781a06be0f8b96d28f6a13b7523c0ecbe70cb3eea1aa */ +static const uint8_t ac_dsa_vect168_out[] = { +/* R */ + 0x4d, 0xdd, 0x2a, 0x1f, 0x41, 0x1b, 0x57, 0x0f, 0xef, 0x6d, 0x91, 0x84, + 0x40, 0x9b, 0x4f, 0xd5, 0x5d, 0x12, 0xc5, 0xe4, 0xbd, 0xdc, 0x2a, 0xc7, + 0x21, 0x12, 0x35, 0x87, 0x33, 0x22, 0x15, 0x5d, +/* S */ + 0x40, 0x43, 0x95, 0x2c, 0x10, 0x8e, 0xf8, 0x4a, 0x25, 0xa1, 0x68, 0xea, + 0x5b, 0x64, 0xa4, 0x38, 0x6f, 0x7a, 0x48, 0x33, 0x66, 0x05, 0x4c, 0x5d, + 0xfb, 0xfc, 0x5f, 0xa9, 0x85, 0x79, 0x43, 0x2a +}; +#define ac_dsa_vect169_prime ac_dsa_vect166_prime +#define ac_dsa_vect169_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect169_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect169_ptx[] = { +/* Msg */ + 0x2f, 0x64, 0xd1, 0x1e, 0x29, 0x02, 0x75, 0x98, 0x7b, 0x7d, 0x74, 0x30, + 0x24, 0x22, 0x89, 0xaf, 0xd5, 0x4f, 0x1b, 0xe0, 0x28, 0xcf, 0x36, 0xf8, + 0xf5, 0x5d, 0xb5, 0x4b, 0xe7, 0x0b, 0x8d, 0xd5, 0xad, 0x74, 0xae, 0x26, + 0xe0, 0x79, 0xd0, 0xed, 0x31, 0xa3, 0x61, 0xc1, 0x16, 0x95, 0x1b, 0xde, + 0x94, 0xd6, 0x86, 0xab, 0xf1, 0x5a, 0xc5, 0xed, 0x14, 0x70, 0xc3, 0xe9, + 0x02, 0x46, 0x1c, 0xea, 0x8e, 0x5d, 0x58, 0xf4, 0x07, 0xd2, 0xe0, 0xc0, + 0x72, 0xee, 0x61, 0x56, 0x7d, 0xa7, 0xb3, 0x53, 0xf6, 0xc4, 0x7e, 0x69, + 0x4c, 0xd6, 0x07, 0xf3, 0xae, 0x89, 0x4a, 0x97, 0x05, 0xe8, 0xea, 0x2b, + 0xf9, 0xce, 0xec, 0x3a, 0xcf, 0xa6, 0xd2, 0x0b, 0x23, 0x8b, 0xf0, 0xa7, + 0xa7, 0xea, 0xc7, 0x6c, 0x44, 0x62, 0xb7, 0xe4, 0xe4, 0xe8, 0x68, 0x17, + 0x4a, 0x88, 0xa6, 0xa6, 0xc9, 0x47, 0x6c, 0xdf +}; +static const uint8_t ac_dsa_vect169_priv_val[] = { +/* X */ + 0x48, 0x00, 0xe9, 0xec, 0xd9, 0xbe, 0xf5, 0xa4, 0xd4, 0x6a, 0xca, 0x60, + 0xac, 0xa9, 0x69, 0x55, 0xd8, 0x56, 0x5e, 0x1b, 0x85, 0xd8, 0x4d, 0xd8, + 0x14, 0x1d, 0x4f, 0x59, 0x7e, 0x17, 0x8b, 0xff +}; +static const uint8_t ac_dsa_vect169_pub_val[] = { +/* Y */ + 0x41, 0xcd, 0xb2, 0xc1, 0xbd, 0xfa, 0x36, 0x52, 0xee, 0x49, 0x69, 0x5d, + 0x5e, 0x5e, 0xee, 0xc0, 0x0f, 0x64, 0xb5, 0x4b, 0x56, 0x76, 0xee, 0x27, + 0xf0, 0x43, 0xb4, 0x3f, 0x24, 0x13, 0x3f, 0x61, 0x42, 0x5b, 0x0c, 0xeb, + 0xaa, 0x1f, 0x88, 0xda, 0x07, 0x2c, 0xc6, 0x88, 0x65, 0xc1, 0x27, 0x90, + 0xc4, 0x32, 0x85, 0xb7, 0xe1, 0x9c, 0x38, 0x44, 0xfc, 0x7d, 0x81, 0xd0, + 0x64, 0x42, 0x3f, 0xf1, 0xe1, 0x92, 0x66, 0xf6, 0x9f, 0x7d, 0xcb, 0x3d, + 0x02, 0x03, 0x73, 0x9f, 0x84, 0xd7, 0x3b, 0xf0, 0x0c, 0x52, 0xd6, 0x0b, + 0x28, 0x75, 0x17, 0x12, 0x16, 0x67, 0x8d, 0x59, 0xfb, 0x55, 0x75, 0x53, + 0xed, 0xc9, 0xeb, 0xa6, 0xb8, 0x41, 0x27, 0x16, 0x9f, 0xe5, 0xdd, 0x2f, + 0x81, 0xfc, 0x90, 0x2c, 0x97, 0x0d, 0x1d, 0x8d, 0x9c, 0x47, 0x79, 0xdf, + 0xa1, 0xb1, 0x43, 0x09, 0xf8, 0x10, 0x06, 0xee, 0x64, 0x17, 0x76, 0xa6, + 0xfa, 0x36, 0x33, 0x9e, 0x96, 0x31, 0x17, 0x44, 0x7a, 0xce, 0xb8, 0x23, + 0xc9, 0xca, 0x33, 0x67, 0x17, 0x2e, 0xdd, 0xaf, 0x6e, 0x36, 0x18, 0x29, + 0xda, 0xe4, 0x3c, 0x40, 0x38, 0xcd, 0xb9, 0x0e, 0xbb, 0x68, 0xb5, 0x3c, + 0x0a, 0x22, 0xd4, 0x10, 0xb6, 0xf1, 0xbf, 0xa7, 0xc4, 0x74, 0x96, 0xea, + 0x3a, 0xed, 0xdc, 0x36, 0xbf, 0x24, 0xf2, 0x19, 0xb8, 0x59, 0x17, 0xa2, + 0x4d, 0x30, 0x84, 0x7c, 0x77, 0xd8, 0x7d, 0x22, 0xa7, 0xf7, 0x48, 0x6c, + 0x66, 0x84, 0x75, 0x5e, 0x04, 0x5d, 0xdf, 0x72, 0xd4, 0x16, 0x50, 0xe9, + 0x7b, 0x64, 0xa6, 0x4b, 0xec, 0xad, 0xfc, 0x47, 0xd5, 0x35, 0x55, 0x12, + 0x7f, 0x8b, 0x7a, 0xb7, 0x8d, 0x48, 0x05, 0x29, 0x57, 0x19, 0x96, 0xee, + 0xde, 0x46, 0x18, 0x88, 0x2d, 0x83, 0x8b, 0xd6, 0x95, 0xef, 0xc8, 0x7e, + 0x74, 0xd6, 0x8c, 0xa5 +}; +/* K = 460410eaeb111a18cf894468e10a88b8de8ef9dfd9a2ea1882a9fb696fd7823d */ +static const uint8_t ac_dsa_vect169_out[] = { +/* R */ + 0x4f, 0xe6, 0xe2, 0xa7, 0x5d, 0x9c, 0x72, 0xe8, 0x1a, 0xc6, 0x0d, 0xd3, + 0x3d, 0x31, 0x18, 0x0d, 0xf8, 0x29, 0xb3, 0x1a, 0x0d, 0xbd, 0x5f, 0xd2, + 0x0b, 0x7e, 0x28, 0xc4, 0xfe, 0xe2, 0x7d, 0x5b, +/* S */ + 0x3c, 0xe4, 0xa0, 0x6b, 0xfa, 0xf7, 0x0c, 0xb6, 0xcc, 0x93, 0xf3, 0x3f, + 0x95, 0xa4, 0x3a, 0xd7, 0x7e, 0xd7, 0xad, 0x7c, 0x77, 0xa1, 0x67, 0x4b, + 0xf8, 0x49, 0xe9, 0xeb, 0xbc, 0x5e, 0xda, 0x29 +}; +#define ac_dsa_vect170_prime ac_dsa_vect166_prime +#define ac_dsa_vect170_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect170_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect170_ptx[] = { +/* Msg */ + 0x17, 0x3c, 0x4a, 0x23, 0x62, 0x1c, 0x32, 0xc3, 0xe4, 0xb1, 0x57, 0xef, + 0x96, 0xb0, 0x2f, 0xc1, 0xbb, 0x46, 0x6a, 0x25, 0x37, 0xd3, 0xf6, 0xe5, + 0x1a, 0x58, 0xe5, 0x10, 0xc4, 0xae, 0xf3, 0xaa, 0xe4, 0xbc, 0xe4, 0xc0, + 0xb4, 0xd5, 0x9b, 0xb1, 0xc0, 0x0e, 0x7a, 0x35, 0xf9, 0x89, 0x45, 0xca, + 0x9d, 0x7f, 0xdf, 0x1f, 0x0b, 0xac, 0x73, 0x2d, 0x42, 0x50, 0x43, 0x06, + 0x2b, 0xc6, 0xd3, 0x20, 0x15, 0x23, 0x3d, 0xfb, 0x29, 0x5a, 0xe0, 0x8a, + 0x32, 0x4a, 0xc7, 0xc1, 0xe0, 0x2a, 0x11, 0x7c, 0xe4, 0x36, 0xd7, 0x7d, + 0x4e, 0x46, 0xd0, 0xb7, 0x94, 0xaf, 0x04, 0xb1, 0xdb, 0x82, 0xa2, 0x70, + 0x9d, 0xa1, 0xc4, 0x44, 0x9c, 0x29, 0xcc, 0xba, 0x93, 0xdb, 0x8e, 0xc4, + 0x8e, 0xb1, 0x79, 0x21, 0xcb, 0x38, 0x9f, 0x6e, 0x0a, 0xe3, 0x29, 0x95, + 0xd7, 0xfe, 0xe1, 0xfa, 0x07, 0x17, 0x7a, 0x7a +}; +static const uint8_t ac_dsa_vect170_priv_val[] = { +/* X */ + 0x3e, 0x69, 0x6f, 0x22, 0x6f, 0x21, 0x91, 0x64, 0x55, 0xf8, 0xcc, 0xc8, + 0x61, 0xb1, 0x84, 0x53, 0x03, 0x86, 0x7b, 0x75, 0x30, 0x3e, 0xd9, 0x2f, + 0x9a, 0xc7, 0x90, 0x88, 0xf5, 0x6e, 0xa7, 0x08 +}; +static const uint8_t ac_dsa_vect170_pub_val[] = { +/* Y */ + 0x67, 0x3e, 0x34, 0x9c, 0xf6, 0xd0, 0x5c, 0xaa, 0x16, 0x75, 0x1d, 0x97, + 0xba, 0x6e, 0x34, 0x4e, 0x40, 0xe1, 0x58, 0xe6, 0xa7, 0xfc, 0x53, 0xea, + 0x2d, 0xb8, 0x78, 0x91, 0x34, 0x1e, 0x64, 0x99, 0x82, 0x5b, 0x5b, 0x9e, + 0xdb, 0xce, 0x91, 0x90, 0xbd, 0x87, 0xc3, 0xea, 0xdf, 0x7c, 0x6d, 0x5b, + 0xf0, 0xa7, 0x93, 0xaf, 0x2c, 0x3a, 0x1c, 0x8d, 0xed, 0x79, 0x0b, 0xc3, + 0x19, 0x44, 0x93, 0x94, 0xc6, 0x43, 0x84, 0x30, 0x58, 0x64, 0x72, 0x3a, + 0x8a, 0x7b, 0xfe, 0xf2, 0x6c, 0x08, 0x20, 0x30, 0xab, 0x36, 0x0b, 0xf9, + 0xab, 0xb1, 0x11, 0x17, 0xe6, 0x1b, 0x00, 0x54, 0x97, 0x26, 0xd7, 0x72, + 0x22, 0x1f, 0x6f, 0x67, 0xc4, 0xa6, 0xa1, 0x10, 0xcd, 0x9a, 0x96, 0x58, + 0x78, 0x1e, 0xa8, 0xf7, 0xef, 0x2f, 0x17, 0x6c, 0x6e, 0x88, 0x16, 0xa8, + 0x65, 0xaf, 0x39, 0x6d, 0xb9, 0x5d, 0x84, 0x15, 0xb5, 0x41, 0xcf, 0x0f, + 0x83, 0xe4, 0x5a, 0x41, 0x73, 0x74, 0xcf, 0x3a, 0xcf, 0x5c, 0x6b, 0x4a, + 0x98, 0x39, 0x05, 0x22, 0xe7, 0x14, 0x0c, 0xc8, 0xaa, 0x3f, 0x9d, 0x2d, + 0xd2, 0x63, 0x41, 0xd4, 0xeb, 0x79, 0xe4, 0xd9, 0x31, 0xa1, 0x78, 0xe3, + 0xd5, 0x7d, 0xc5, 0x2b, 0xfd, 0xf9, 0x01, 0x15, 0xe0, 0x1b, 0x76, 0x09, + 0x4a, 0xd0, 0x29, 0x49, 0x79, 0xd3, 0x5d, 0x92, 0xb5, 0x74, 0xce, 0x7b, + 0x0c, 0x62, 0x7f, 0x08, 0xbe, 0x66, 0xf9, 0x9e, 0xff, 0xad, 0xc3, 0x3a, + 0xed, 0x0f, 0x63, 0x4f, 0x6a, 0x89, 0x50, 0x74, 0x55, 0xd7, 0x34, 0x1e, + 0xe6, 0x41, 0x83, 0xaa, 0x61, 0x0d, 0x8b, 0xb3, 0x23, 0x71, 0x47, 0xbd, + 0x90, 0xdc, 0xd9, 0xc1, 0xa0, 0x3d, 0x89, 0xb2, 0x6e, 0xe3, 0x1d, 0xbe, + 0xf5, 0xae, 0x7e, 0x76, 0x4b, 0xa9, 0xf7, 0x7b, 0x6a, 0x74, 0x34, 0xad, + 0x2a, 0x8f, 0x96, 0x6c +}; +/* K = 2837f7fa85efafb433093231983ccef5d82080e6063f67c68ff93465b59d581e */ +static const uint8_t ac_dsa_vect170_out[] = { +/* R */ + 0x39, 0x3d, 0x68, 0x1c, 0x3e, 0xdb, 0xa2, 0x8f, 0x7c, 0xb0, 0xf3, 0x05, + 0x93, 0xb9, 0x4f, 0xc1, 0x5c, 0xca, 0x65, 0x9a, 0x80, 0xcf, 0xbc, 0xb3, + 0xb2, 0x36, 0x45, 0x37, 0x22, 0xd5, 0xb4, 0x02, +/* S */ + 0x44, 0xf7, 0x42, 0x1b, 0xce, 0x1e, 0x52, 0x73, 0xa3, 0x0e, 0xc0, 0x16, + 0xbb, 0x99, 0x69, 0xb7, 0x57, 0x19, 0x79, 0x87, 0x54, 0x8e, 0x43, 0x4e, + 0x39, 0x5a, 0xb3, 0xde, 0x1b, 0x0e, 0x7b, 0xa2 +}; +#define ac_dsa_vect171_prime ac_dsa_vect166_prime +#define ac_dsa_vect171_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect171_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect171_ptx[] = { +/* Msg */ + 0x7d, 0x6f, 0x2a, 0x97, 0xe1, 0xeb, 0x08, 0x5c, 0xb9, 0xe8, 0x3a, 0xa2, + 0x40, 0x47, 0xaf, 0x9b, 0xa3, 0x0a, 0x05, 0xd7, 0xba, 0xb5, 0x64, 0xa1, + 0x49, 0xb9, 0xcd, 0x23, 0x66, 0x51, 0x8e, 0x8f, 0x19, 0x91, 0x34, 0xfc, + 0x2c, 0xa4, 0x03, 0x94, 0x7f, 0x2a, 0x61, 0x4c, 0x03, 0x63, 0xed, 0x4b, + 0xc1, 0x34, 0x9d, 0xc4, 0x96, 0xa8, 0xec, 0x74, 0xd8, 0x80, 0x57, 0x84, + 0x75, 0xe4, 0x74, 0x27, 0x62, 0x8b, 0xb0, 0x23, 0xf0, 0x27, 0x22, 0x08, + 0x87, 0x6a, 0x3a, 0x73, 0x33, 0x30, 0x7a, 0x59, 0x6c, 0x15, 0x8e, 0xba, + 0x64, 0xce, 0x42, 0xa3, 0xc7, 0x90, 0xe7, 0x16, 0x7b, 0xa4, 0xa3, 0x27, + 0xac, 0x71, 0xaa, 0xba, 0xd2, 0xf3, 0x63, 0x41, 0xed, 0xea, 0x12, 0xce, + 0x5b, 0x2b, 0x73, 0x58, 0x07, 0xb3, 0x4b, 0x71, 0x4a, 0x49, 0xa0, 0xaa, + 0x47, 0x68, 0x93, 0x57, 0x8f, 0x06, 0x45, 0xdb +}; +static const uint8_t ac_dsa_vect171_priv_val[] = { +/* X */ + 0x66, 0x08, 0x98, 0x41, 0x3f, 0x7a, 0x71, 0x80, 0x44, 0x32, 0xec, 0xfa, + 0x11, 0xcc, 0x68, 0xf8, 0x5a, 0x34, 0xfd, 0xf7, 0x50, 0x12, 0xc9, 0x65, + 0x25, 0x9e, 0xa6, 0xca, 0x0b, 0xbc, 0xd9, 0x76 +}; +static const uint8_t ac_dsa_vect171_pub_val[] = { +/* Y */ + 0x77, 0x7c, 0x25, 0x10, 0x67, 0xc8, 0xab, 0x16, 0xcc, 0xe2, 0xc4, 0xa4, + 0xd7, 0x84, 0xc7, 0xe8, 0x06, 0xfd, 0x29, 0x6c, 0xbb, 0xba, 0xb0, 0x13, + 0x2e, 0x2a, 0xb9, 0x16, 0x23, 0xac, 0xec, 0xd8, 0x30, 0xe7, 0xcc, 0x7c, + 0xde, 0x03, 0xe5, 0x44, 0xb5, 0x1f, 0xb1, 0xd8, 0xf0, 0xb2, 0xee, 0xc0, + 0x9f, 0x55, 0x95, 0x39, 0xaa, 0x9d, 0x63, 0xeb, 0xc0, 0xc1, 0xe3, 0x25, + 0x79, 0xf0, 0x95, 0x47, 0x3d, 0x12, 0x71, 0x7c, 0xe8, 0x8f, 0x66, 0x71, + 0xec, 0x7e, 0x3d, 0x25, 0x81, 0xf6, 0x1b, 0xfd, 0xe6, 0x6c, 0xf9, 0xbe, + 0x21, 0x6d, 0x6a, 0x20, 0x80, 0x86, 0xcd, 0x7b, 0xea, 0x77, 0x01, 0x50, + 0xa9, 0xbb, 0x0a, 0x5a, 0x7a, 0x0d, 0xac, 0xe8, 0x2b, 0x46, 0x41, 0x80, + 0x24, 0x12, 0x02, 0xa3, 0x0b, 0x26, 0xad, 0x5f, 0xb9, 0x33, 0xc8, 0x23, + 0x5a, 0xc2, 0x91, 0x8e, 0x29, 0xbc, 0x53, 0xa5, 0xc0, 0x1e, 0xbc, 0x1e, + 0x30, 0xb1, 0xb4, 0x6e, 0x37, 0x12, 0x4a, 0xec, 0x59, 0x6f, 0x8d, 0x1a, + 0x73, 0xba, 0xea, 0xe5, 0x88, 0xce, 0x7d, 0x4a, 0xef, 0x1a, 0xe8, 0x4e, + 0x9a, 0x97, 0x66, 0xc2, 0x43, 0x67, 0x32, 0x1c, 0x04, 0x7c, 0x3c, 0xab, + 0xa6, 0x29, 0xf5, 0xd9, 0x18, 0x5f, 0x0f, 0xfb, 0x3a, 0xf7, 0xe5, 0x0e, + 0xeb, 0xd1, 0xba, 0x0e, 0xb7, 0x7e, 0xb1, 0x21, 0xb9, 0x80, 0x73, 0x79, + 0x4c, 0xbc, 0x66, 0x22, 0xb6, 0x78, 0x26, 0x2e, 0xd3, 0xe2, 0x29, 0xc6, + 0xce, 0xeb, 0x60, 0x72, 0x74, 0xce, 0x34, 0x96, 0xf3, 0x70, 0xb4, 0x82, + 0xbf, 0x8f, 0x68, 0xc2, 0x73, 0x66, 0x81, 0x84, 0x86, 0xb7, 0x2a, 0xdf, + 0xc8, 0x10, 0xb2, 0xf5, 0x79, 0x77, 0x9a, 0xdc, 0x9c, 0x25, 0x00, 0x2e, + 0x27, 0x76, 0x41, 0xdd, 0x9f, 0xfb, 0xc5, 0xdb, 0x52, 0x39, 0xf6, 0x77, + 0xba, 0x1a, 0x9c, 0x1d +}; +/* K = 4abaf5c6f8e28356fd0dc6f096e9354baac1c2049170b2db05c81bacf02092f2 */ +static const uint8_t ac_dsa_vect171_out[] = { +/* R */ + 0x46, 0x3b, 0x1f, 0xd6, 0xef, 0x29, 0x86, 0xf7, 0x5f, 0x96, 0x20, 0x77, + 0x9b, 0xb6, 0xf4, 0x7e, 0x0b, 0xea, 0xfa, 0x93, 0x40, 0xe3, 0xe5, 0xee, + 0x58, 0x9d, 0x92, 0x42, 0x8a, 0xcd, 0x4f, 0x2c, +/* S */ + 0x27, 0xed, 0xd3, 0x39, 0x17, 0xe4, 0x9b, 0xf7, 0x71, 0xf3, 0xfa, 0x13, + 0x55, 0xcd, 0x39, 0x28, 0xd0, 0xbd, 0x40, 0x1a, 0xa7, 0xbf, 0x05, 0x41, + 0xf3, 0xaf, 0x16, 0x43, 0xef, 0xd7, 0xb6, 0x77 +}; +#define ac_dsa_vect172_prime ac_dsa_vect166_prime +#define ac_dsa_vect172_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect172_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect172_ptx[] = { +/* Msg */ + 0x7f, 0x87, 0x85, 0xe1, 0xc4, 0xf8, 0x2b, 0xc0, 0xbb, 0x75, 0xf7, 0x8d, + 0x8c, 0x41, 0x13, 0xe0, 0x88, 0x7e, 0x76, 0x1a, 0x86, 0xb4, 0x8d, 0xfa, + 0x43, 0xa3, 0x68, 0x3b, 0x2b, 0xb8, 0x86, 0xba, 0x53, 0xf5, 0x60, 0x3c, + 0x8d, 0x94, 0xa0, 0x52, 0xaf, 0x36, 0x71, 0xc5, 0xc1, 0xe7, 0xc2, 0x32, + 0x90, 0x8e, 0x10, 0xfa, 0xa6, 0xcd, 0x54, 0xef, 0xc7, 0x9c, 0xcf, 0xd6, + 0x48, 0x11, 0x13, 0x1a, 0xcd, 0x7d, 0x60, 0xa9, 0x30, 0x97, 0x29, 0x45, + 0x5a, 0xa7, 0x04, 0x43, 0xae, 0x8f, 0x32, 0xa3, 0x45, 0x80, 0xf9, 0xa1, + 0xaa, 0x7d, 0x89, 0xe5, 0xfa, 0x8c, 0xd4, 0xe9, 0x58, 0x09, 0xa5, 0x73, + 0xec, 0x6d, 0xfe, 0x9f, 0xe3, 0x5b, 0x11, 0x30, 0x57, 0x19, 0x82, 0xa0, + 0xdd, 0x46, 0xee, 0xeb, 0xb6, 0xa1, 0x6f, 0x85, 0xee, 0x63, 0x14, 0x93, + 0x18, 0x39, 0xe3, 0xa4, 0xc2, 0x9d, 0xc7, 0x00 +}; +static const uint8_t ac_dsa_vect172_priv_val[] = { +/* X */ + 0x4b, 0xe0, 0x92, 0x6f, 0xe2, 0x4d, 0xa1, 0x66, 0x7d, 0x71, 0xd2, 0xab, + 0xc2, 0xbc, 0x0b, 0xf8, 0x71, 0x72, 0xc0, 0x5d, 0x7c, 0x36, 0x3a, 0x32, + 0x4e, 0xc6, 0x1b, 0x46, 0x42, 0x77, 0x7e, 0x57 +}; +static const uint8_t ac_dsa_vect172_pub_val[] = { +/* Y */ + 0x28, 0xc0, 0x6e, 0x5a, 0xb3, 0xc8, 0x60, 0xbe, 0x8c, 0x13, 0xf7, 0x4f, + 0x28, 0xb5, 0x79, 0x2b, 0x39, 0x48, 0x7b, 0x79, 0x54, 0x7f, 0x4a, 0xfa, + 0xf6, 0xf7, 0x7a, 0x5c, 0x3a, 0x43, 0xe8, 0x81, 0x32, 0xed, 0xf9, 0x44, + 0xee, 0x00, 0x15, 0x0a, 0x78, 0xb5, 0x8a, 0x78, 0xcf, 0x92, 0xed, 0x94, + 0x15, 0x78, 0xec, 0x67, 0x9e, 0x10, 0x67, 0x67, 0x01, 0x4e, 0x5b, 0x27, + 0x9c, 0x0e, 0xae, 0x9c, 0x40, 0x8e, 0x6e, 0xd6, 0x06, 0x87, 0xee, 0x14, + 0x64, 0x98, 0x8e, 0xa5, 0x45, 0xf5, 0x5b, 0xe3, 0x67, 0x3e, 0xcd, 0xa1, + 0x0c, 0x63, 0xfb, 0x0b, 0x19, 0x08, 0xe7, 0x96, 0xd6, 0x71, 0x5a, 0xbd, + 0x54, 0x51, 0x84, 0x3d, 0xa6, 0xe6, 0x3b, 0xf8, 0x80, 0x2c, 0xca, 0xda, + 0x32, 0xc7, 0xc5, 0x34, 0x23, 0x74, 0xab, 0x26, 0xee, 0x70, 0x1f, 0x9d, + 0xb3, 0xd3, 0x4f, 0xc9, 0x6d, 0xe9, 0xd2, 0x30, 0x21, 0xb9, 0x8a, 0x93, + 0xdf, 0x68, 0x77, 0xf8, 0x4f, 0xad, 0x67, 0x41, 0x16, 0x40, 0x55, 0x69, + 0x6f, 0x3b, 0x72, 0x05, 0x03, 0x43, 0xea, 0x3e, 0x5c, 0xca, 0x01, 0xa3, + 0xd5, 0x7e, 0x29, 0x72, 0x7e, 0xbc, 0xf8, 0x58, 0x31, 0x18, 0x14, 0x6c, + 0x27, 0xf4, 0x2a, 0xda, 0xf6, 0x23, 0x65, 0xb9, 0x69, 0x7c, 0xf0, 0x3b, + 0xdd, 0xc6, 0x9d, 0x0b, 0xd1, 0x51, 0xf7, 0x15, 0xb2, 0x3b, 0xfa, 0xaa, + 0x27, 0xa3, 0x68, 0x11, 0x4b, 0x3d, 0xfb, 0x54, 0xc0, 0x84, 0xe0, 0x6d, + 0x43, 0x43, 0xff, 0xde, 0x1c, 0xd2, 0x20, 0x58, 0xe9, 0x62, 0x3a, 0x70, + 0xe9, 0x94, 0x2e, 0x09, 0x0e, 0xdc, 0x73, 0xdb, 0x06, 0xdd, 0x31, 0x80, + 0xbb, 0x96, 0x0f, 0x0d, 0x7f, 0xed, 0x00, 0x5b, 0x14, 0x9b, 0x69, 0xd6, + 0xd4, 0x5f, 0x40, 0x36, 0x8f, 0xc2, 0x5a, 0xe0, 0x43, 0x21, 0xed, 0xa4, + 0x6d, 0x52, 0xa5, 0x92 +}; +/* K = 057cca710c8e4998e9fe154cc57847bf35a512e6caf3cd338372b5becc66e8e1 */ +static const uint8_t ac_dsa_vect172_out[] = { +/* R */ + 0x31, 0x65, 0xb1, 0xcf, 0x3c, 0xa9, 0xbb, 0x89, 0x15, 0x4a, 0xd6, 0x84, + 0xe0, 0x89, 0x36, 0x4f, 0x91, 0xb6, 0xe5, 0xd5, 0x94, 0x52, 0x60, 0x72, + 0xf7, 0xb9, 0xdb, 0x3b, 0x23, 0x58, 0xe7, 0x11, +/* S */ + 0x49, 0xe1, 0xc8, 0xc3, 0x47, 0x24, 0xac, 0x55, 0x32, 0xff, 0xf1, 0xc7, + 0xd2, 0x43, 0xb4, 0x86, 0xa2, 0xcd, 0xc0, 0x87, 0x2a, 0xb8, 0x4f, 0xda, + 0x6c, 0xf2, 0xba, 0x96, 0xf9, 0x58, 0xf4, 0x6a +}; +#define ac_dsa_vect173_prime ac_dsa_vect166_prime +#define ac_dsa_vect173_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect173_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect173_ptx[] = { +/* Msg */ + 0x3e, 0x17, 0xea, 0x8b, 0x9f, 0xeb, 0x2f, 0x4e, 0x55, 0xc1, 0x03, 0xe5, + 0x8c, 0x4e, 0xad, 0x96, 0xb5, 0xcb, 0x89, 0x2d, 0x09, 0x82, 0xab, 0x2b, + 0x0c, 0xb1, 0xee, 0xb9, 0xe1, 0xdd, 0xde, 0x99, 0x90, 0x23, 0x3a, 0x22, + 0x58, 0x84, 0x73, 0x42, 0x1a, 0xad, 0xf5, 0x27, 0x67, 0xa8, 0xdf, 0x52, + 0x4b, 0xc6, 0xe6, 0xed, 0x85, 0x7a, 0x9f, 0xd5, 0x94, 0x2e, 0xf9, 0x76, + 0xb1, 0xfd, 0x8b, 0xca, 0xd3, 0x1e, 0x40, 0x3b, 0x1f, 0xeb, 0xb8, 0x65, + 0xd2, 0x87, 0x2a, 0x7b, 0x34, 0xec, 0xdb, 0xab, 0x8b, 0x24, 0x5a, 0xda, + 0x45, 0x24, 0x3a, 0x49, 0xc7, 0xbe, 0x67, 0xaa, 0x09, 0x78, 0x80, 0x29, + 0x77, 0x9d, 0x61, 0x9d, 0xe3, 0x0d, 0xea, 0xd9, 0xf7, 0xd8, 0xc9, 0xc4, + 0x21, 0x53, 0xb8, 0x65, 0xb1, 0xa9, 0xe8, 0x11, 0x80, 0x38, 0x0e, 0x27, + 0xa3, 0x05, 0xa6, 0x39, 0x2f, 0x4b, 0x2a, 0x0b +}; +static const uint8_t ac_dsa_vect173_priv_val[] = { +/* X */ + 0x75, 0xc9, 0xb6, 0xc6, 0x3c, 0x80, 0x75, 0x5f, 0x7a, 0x7b, 0xf3, 0x8e, + 0xab, 0xc5, 0x8e, 0x1b, 0xc2, 0xe0, 0xcc, 0x5c, 0xb4, 0xf2, 0x27, 0x4f, + 0x2d, 0x63, 0x05, 0x81, 0x57, 0x65, 0x66, 0x08 +}; +static const uint8_t ac_dsa_vect173_pub_val[] = { +/* Y */ + 0xb7, 0x1d, 0x0a, 0xb2, 0xd4, 0x05, 0xa5, 0x01, 0x2d, 0x69, 0x4e, 0x0a, + 0x4a, 0x82, 0x76, 0x92, 0x56, 0xcb, 0xdb, 0x49, 0xc1, 0x81, 0x12, 0xef, + 0xee, 0x81, 0x53, 0xc8, 0xe8, 0x16, 0x31, 0x04, 0x86, 0xa1, 0x7b, 0xce, + 0x19, 0x74, 0x8b, 0x11, 0xf3, 0xd5, 0xd1, 0x8c, 0xb4, 0x49, 0x98, 0xeb, + 0x32, 0x9b, 0x95, 0x1c, 0x23, 0xa5, 0x7c, 0xac, 0x47, 0xec, 0x99, 0x73, + 0x83, 0x9b, 0x13, 0x0f, 0x3a, 0x98, 0x0e, 0x62, 0x70, 0x5c, 0x07, 0x02, + 0xe4, 0xd6, 0x84, 0x25, 0x84, 0x5d, 0x54, 0xe1, 0x52, 0xe2, 0xe8, 0x36, + 0x46, 0xb5, 0x6a, 0x67, 0x57, 0xcd, 0xe0, 0x6f, 0x85, 0xba, 0x37, 0x79, + 0xee, 0xa5, 0x85, 0xdf, 0xe8, 0x30, 0x2f, 0x12, 0xae, 0x77, 0xfa, 0x58, + 0xcb, 0xc6, 0xdc, 0xca, 0x70, 0xb4, 0x61, 0x02, 0x4b, 0x7d, 0x17, 0x65, + 0x10, 0xa3, 0x93, 0xec, 0x02, 0x7c, 0x76, 0x9c, 0xfe, 0x49, 0xb6, 0x98, + 0xe5, 0x75, 0xfc, 0xf9, 0x9c, 0x60, 0x29, 0x3a, 0xf2, 0xad, 0xe3, 0xdc, + 0x4d, 0xf2, 0x3f, 0xf3, 0x38, 0x6f, 0x13, 0x77, 0x73, 0x06, 0xc5, 0x2d, + 0xe9, 0x7e, 0xd1, 0xa8, 0x86, 0xb8, 0x24, 0x78, 0x88, 0x63, 0xff, 0x72, + 0x63, 0xbb, 0xbb, 0x5b, 0x5f, 0xa0, 0xd4, 0x68, 0x1c, 0x16, 0x94, 0x22, + 0x72, 0xf5, 0xe4, 0x41, 0xbd, 0xf4, 0x9e, 0xec, 0x75, 0x56, 0xc1, 0xfd, + 0x40, 0x9c, 0x78, 0xe3, 0xaa, 0xff, 0xeb, 0x95, 0xc1, 0x26, 0x7d, 0xee, + 0x12, 0xc2, 0x4c, 0x04, 0x5e, 0xf6, 0x7a, 0xa7, 0x0e, 0x9a, 0x3d, 0x92, + 0x44, 0xf2, 0xcf, 0x1a, 0xc6, 0x8c, 0xd9, 0x18, 0xdf, 0x5f, 0x62, 0xa3, + 0xdd, 0x3d, 0xe7, 0xbc, 0xde, 0xaa, 0x3f, 0x61, 0xde, 0x51, 0xcc, 0x01, + 0xaf, 0x63, 0x6b, 0xd6, 0x65, 0xc0, 0x09, 0x9d, 0x13, 0x93, 0x8e, 0xb4, + 0xfc, 0x28, 0x9b, 0x42 +}; +/* K = 568b8f5049c2c411f05d74e1781be5718ff921026728d285f2a77025208dbd41 */ +static const uint8_t ac_dsa_vect173_out[] = { +/* R */ + 0x11, 0xb7, 0xec, 0xfe, 0xb3, 0x39, 0xd6, 0x01, 0x49, 0x48, 0xde, 0x5a, + 0xd4, 0xc9, 0x6f, 0x4b, 0xa5, 0x17, 0xa2, 0xcd, 0xdc, 0xa6, 0x11, 0xc8, + 0x88, 0x7f, 0xc4, 0x4f, 0x14, 0xac, 0x9a, 0x63, +/* S */ + 0x13, 0x28, 0x7a, 0x22, 0xcf, 0xfd, 0x82, 0x53, 0x02, 0xb0, 0xfd, 0xc0, + 0x95, 0x54, 0x58, 0xd9, 0x18, 0x72, 0x70, 0x92, 0xc7, 0xbf, 0xb3, 0xec, + 0x4c, 0x3d, 0x7a, 0x83, 0x8e, 0xa6, 0xc4, 0x91 +}; +#define ac_dsa_vect174_prime ac_dsa_vect166_prime +#define ac_dsa_vect174_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect174_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect174_ptx[] = { +/* Msg */ + 0xc3, 0xe1, 0x90, 0x3c, 0xec, 0xcb, 0x2a, 0xf5, 0xb0, 0xdc, 0x6b, 0x1f, + 0xba, 0xaf, 0x1b, 0x2e, 0x96, 0x47, 0x7e, 0x00, 0x1c, 0x43, 0xee, 0xe3, + 0x04, 0x6e, 0xed, 0x06, 0x12, 0x8c, 0x4c, 0x81, 0xeb, 0x2b, 0xc9, 0x17, + 0xaa, 0x8a, 0xc3, 0x0d, 0x07, 0xe6, 0x6c, 0x9a, 0x94, 0x69, 0x51, 0x8e, + 0x3c, 0xab, 0xc2, 0x64, 0xd6, 0x93, 0x6e, 0x5d, 0x72, 0x4a, 0x61, 0x3b, + 0xf9, 0xa4, 0x4d, 0x60, 0x79, 0x7b, 0x89, 0x0c, 0xc5, 0xce, 0x0d, 0x04, + 0x62, 0x9e, 0x5f, 0xaa, 0x1d, 0xd5, 0x3e, 0x7a, 0x12, 0x5a, 0x14, 0xa2, + 0x6d, 0xf3, 0xcd, 0xd9, 0x87, 0x8d, 0x9c, 0x67, 0xe7, 0xe1, 0x8a, 0x46, + 0x55, 0xa1, 0x88, 0x88, 0x53, 0x63, 0xdd, 0xab, 0xd7, 0x3a, 0x17, 0x65, + 0x9d, 0x19, 0x1e, 0x51, 0xfa, 0xfb, 0x6d, 0x41, 0x71, 0xff, 0x6c, 0x4b, + 0x65, 0x11, 0x68, 0xce, 0x16, 0x7a, 0xda, 0x01 +}; +static const uint8_t ac_dsa_vect174_priv_val[] = { +/* X */ + 0x5f, 0xeb, 0xa3, 0x70, 0xa5, 0x8c, 0x16, 0xf3, 0x4e, 0x93, 0x1b, 0x65, + 0xc0, 0x42, 0xe6, 0xbf, 0xe7, 0x94, 0x30, 0x9c, 0xf3, 0x01, 0x05, 0xd2, + 0xfd, 0xac, 0x4d, 0x9f, 0xb3, 0xe1, 0x43, 0x03 +}; +static const uint8_t ac_dsa_vect174_pub_val[] = { +/* Y */ + 0x42, 0x9e, 0x6b, 0xa2, 0x0b, 0x02, 0xcd, 0x69, 0xa2, 0x9b, 0x4a, 0x97, + 0xa6, 0xea, 0x56, 0x4e, 0x5b, 0x88, 0x74, 0xad, 0xa1, 0x95, 0xa4, 0x9c, + 0x3a, 0x52, 0x93, 0xc9, 0xbc, 0x8d, 0x19, 0xe0, 0xa3, 0xa3, 0xc4, 0xac, + 0x85, 0x47, 0xbf, 0xdc, 0x7a, 0x20, 0x9b, 0xf3, 0xa6, 0x03, 0x7e, 0x5b, + 0x0b, 0xb7, 0xaa, 0x29, 0x1d, 0x59, 0x40, 0xd2, 0x35, 0xc7, 0x87, 0xa2, + 0xaf, 0x79, 0xa9, 0xcd, 0x7f, 0x83, 0x08, 0x4b, 0xa7, 0xdf, 0x85, 0xc0, + 0x36, 0xad, 0x8e, 0xa2, 0x3c, 0x4f, 0xdb, 0xf9, 0x1d, 0x28, 0x5c, 0x7c, + 0xaa, 0x64, 0x97, 0xaf, 0x38, 0x80, 0x17, 0xbd, 0x58, 0x1f, 0xf3, 0x08, + 0xd9, 0xb5, 0x67, 0x99, 0x02, 0x9e, 0x21, 0x40, 0x0c, 0x0c, 0x99, 0xd1, + 0x03, 0xa2, 0xca, 0xec, 0x19, 0x5e, 0x40, 0xc9, 0x0d, 0x24, 0x4d, 0xac, + 0x89, 0x7b, 0xd4, 0x18, 0xae, 0x01, 0x6d, 0x25, 0xf7, 0x1e, 0x98, 0x9a, + 0xf5, 0x16, 0xd5, 0xe2, 0x49, 0x1e, 0x1e, 0x4b, 0xc2, 0x59, 0x14, 0xec, + 0x3a, 0xd0, 0xa9, 0xf8, 0x59, 0x68, 0xa6, 0x77, 0x7f, 0xbe, 0xbd, 0xc7, + 0x3b, 0x1a, 0xc6, 0x81, 0x44, 0x96, 0xd9, 0x42, 0x1d, 0x2b, 0x7c, 0xdf, + 0x17, 0xd5, 0x3f, 0x00, 0x62, 0x40, 0x10, 0xed, 0x66, 0x18, 0xf1, 0x25, + 0x8d, 0xa1, 0x94, 0xf7, 0x7c, 0x28, 0x28, 0x62, 0x25, 0xd1, 0xb1, 0x6d, + 0xa3, 0xfa, 0xb7, 0x6c, 0x9b, 0x70, 0xdb, 0x1f, 0x7d, 0xbc, 0xba, 0xcf, + 0x4e, 0x60, 0xb6, 0xb9, 0x1a, 0x1f, 0x47, 0x50, 0x07, 0xee, 0x4d, 0x2c, + 0x5e, 0x37, 0xfc, 0x31, 0xe8, 0x9a, 0x0f, 0xa8, 0x08, 0xf8, 0x9e, 0x8a, + 0x4e, 0x54, 0x6b, 0xc9, 0x0e, 0x69, 0x6f, 0x45, 0x47, 0x21, 0xbe, 0x71, + 0xc0, 0x73, 0x1f, 0x99, 0xee, 0x36, 0x8a, 0xfc, 0x69, 0x98, 0x76, 0x1a, + 0xf9, 0xdd, 0x9d, 0x6d +}; +/* K = 7ba86d55b8b5a465f661944832862baf5f565ff0d9195986c809956db2872da9 */ +static const uint8_t ac_dsa_vect174_out[] = { +/* R */ + 0x77, 0x47, 0x0f, 0x0d, 0x39, 0x23, 0xff, 0x40, 0x7e, 0x71, 0xa8, 0x6f, + 0x03, 0x36, 0x81, 0x1b, 0xdd, 0x63, 0xe1, 0x79, 0x89, 0x1f, 0xd3, 0x0e, + 0x34, 0x52, 0xda, 0xc1, 0xe5, 0x17, 0x50, 0x81, +/* S */ + 0x4b, 0x96, 0x9f, 0x77, 0xc7, 0x0b, 0x5e, 0x6f, 0xf9, 0x35, 0x0c, 0xa2, + 0x5e, 0x7d, 0x95, 0x1a, 0xca, 0xae, 0xe9, 0x07, 0xfa, 0x7b, 0x83, 0x0a, + 0x32, 0xdc, 0xe4, 0xf9, 0x1a, 0x89, 0xaf, 0xa4 +}; +#define ac_dsa_vect175_prime ac_dsa_vect166_prime +#define ac_dsa_vect175_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect175_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect175_ptx[] = { +/* Msg */ + 0x4b, 0x7c, 0x08, 0x28, 0xb7, 0x15, 0xec, 0x2d, 0xa1, 0xe0, 0x92, 0x20, + 0x4f, 0x55, 0xdd, 0xd6, 0x5d, 0x13, 0xf1, 0xcd, 0xd6, 0x4c, 0x10, 0x94, + 0x78, 0xd3, 0x84, 0x74, 0x87, 0xbc, 0x48, 0xa8, 0xcb, 0x02, 0x99, 0x22, + 0x2a, 0x74, 0x95, 0xef, 0xff, 0xa6, 0x3e, 0xa1, 0x58, 0x25, 0x3f, 0xae, + 0xdc, 0xb5, 0x31, 0x48, 0x81, 0xab, 0x41, 0xb5, 0xe7, 0x73, 0x33, 0x76, + 0x62, 0xcc, 0x2f, 0x50, 0xdb, 0xcc, 0xc7, 0x36, 0x97, 0x4e, 0x31, 0xb3, + 0xd0, 0x80, 0x46, 0x75, 0x89, 0x95, 0x1d, 0x51, 0x10, 0x32, 0xe4, 0xcb, + 0xa6, 0x64, 0x7f, 0x94, 0xc6, 0x79, 0xaa, 0x26, 0x9f, 0xca, 0x6d, 0xb9, + 0x27, 0x15, 0xa4, 0xda, 0x28, 0xff, 0x98, 0x03, 0xa1, 0xdc, 0x61, 0x67, + 0x5f, 0xa5, 0xac, 0x11, 0x4e, 0x37, 0x6f, 0xa4, 0xda, 0xdb, 0x37, 0xc1, + 0xb0, 0x9e, 0xd5, 0xc3, 0x1b, 0xc5, 0xae, 0xe8 +}; +static const uint8_t ac_dsa_vect175_priv_val[] = { +/* X */ + 0x1b, 0xa8, 0x5c, 0x9c, 0x8f, 0x4f, 0x4a, 0xe9, 0x70, 0x13, 0xbc, 0x9f, + 0x7f, 0xab, 0x37, 0x2e, 0x73, 0x3f, 0x34, 0x45, 0xfd, 0x9a, 0x68, 0xf8, + 0xe0, 0x15, 0xc3, 0x75, 0xdf, 0x3b, 0x55, 0x15 +}; +static const uint8_t ac_dsa_vect175_pub_val[] = { +/* Y */ + 0x09, 0xa1, 0x6e, 0x0a, 0x60, 0x03, 0xf4, 0x5a, 0xaa, 0xa3, 0xc6, 0x31, + 0x1a, 0xa9, 0x86, 0x62, 0x17, 0xd4, 0xa7, 0xc8, 0xcb, 0x50, 0x93, 0x51, + 0x49, 0x76, 0xf6, 0xa3, 0x41, 0x26, 0x0e, 0x5a, 0xba, 0x7c, 0xb0, 0x0a, + 0xb2, 0xad, 0xb7, 0x46, 0x2a, 0x47, 0xa8, 0xcf, 0xee, 0x4f, 0xdc, 0xae, + 0x5a, 0xcc, 0xda, 0x6d, 0x42, 0xa3, 0x14, 0x47, 0x92, 0xa1, 0x46, 0x31, + 0xbb, 0xe8, 0x55, 0x34, 0xc1, 0x11, 0xd2, 0xff, 0xcd, 0xbc, 0x15, 0xb6, + 0xdb, 0x9d, 0xbf, 0xc4, 0xbc, 0x71, 0xd3, 0x00, 0x32, 0x4f, 0xd3, 0x10, + 0xc4, 0x65, 0x44, 0x3c, 0xb2, 0xa6, 0xf2, 0xae, 0x33, 0x70, 0x1f, 0x39, + 0x66, 0x8b, 0x11, 0x8c, 0x38, 0xef, 0x56, 0x2e, 0x85, 0x54, 0xfe, 0xa6, + 0x61, 0xa3, 0xef, 0x80, 0x45, 0x56, 0x99, 0xc2, 0x34, 0x30, 0xd2, 0x8b, + 0xa6, 0xdc, 0xf0, 0x42, 0xfc, 0x92, 0x0a, 0x67, 0x7c, 0x29, 0x71, 0xb2, + 0xdf, 0x8c, 0x67, 0x29, 0xc5, 0xb3, 0xb1, 0xbe, 0x6c, 0x5a, 0x04, 0x7a, + 0xc1, 0xbc, 0xc8, 0xcd, 0x8d, 0xc5, 0x19, 0xad, 0xa2, 0x21, 0xbd, 0x92, + 0xca, 0x68, 0x93, 0xc1, 0xcc, 0x1d, 0xc1, 0x58, 0xf9, 0xd4, 0x72, 0xf8, + 0x9a, 0x8e, 0x02, 0x64, 0x94, 0x40, 0xdd, 0xed, 0x0f, 0x72, 0x34, 0x85, + 0x55, 0x8e, 0xff, 0xe8, 0xcf, 0x9d, 0xf1, 0x21, 0xc9, 0x69, 0xa2, 0xd1, + 0xb7, 0x6a, 0x37, 0xdc, 0xbf, 0xfb, 0x17, 0xed, 0xf3, 0x12, 0x1d, 0x43, + 0x38, 0xd4, 0xab, 0x68, 0xb1, 0x54, 0x22, 0x6c, 0x00, 0x72, 0xd8, 0xbd, + 0x51, 0xf2, 0x3e, 0x56, 0x59, 0xa2, 0xaf, 0xe5, 0x20, 0xdd, 0x5e, 0x91, + 0x00, 0x5a, 0x6f, 0xc1, 0x15, 0x7f, 0x07, 0x97, 0x36, 0x10, 0xc5, 0x57, + 0x78, 0x24, 0xbf, 0x16, 0x66, 0xcc, 0xf8, 0x51, 0xd6, 0x9e, 0xfd, 0xe3, + 0x47, 0xf0, 0xb9, 0x96 +}; +/* K = 11d09ab8f3140f98dd4076d398a9aafb9c98656dd7185567a562cd108932eb77 */ +static const uint8_t ac_dsa_vect175_out[] = { +/* R */ + 0x1b, 0x8b, 0x8d, 0x67, 0xb6, 0x40, 0xaf, 0xda, 0x26, 0xfb, 0xe6, 0x7c, + 0xfd, 0x4b, 0xea, 0x52, 0x13, 0x75, 0x52, 0x6a, 0xd5, 0x8a, 0x22, 0xd4, + 0xd9, 0x7d, 0x7a, 0xf1, 0x34, 0x38, 0x4f, 0x4a, +/* S */ + 0x66, 0xd6, 0xc2, 0x40, 0x99, 0x22, 0x56, 0xee, 0xbe, 0x07, 0x82, 0x65, + 0xc3, 0x02, 0x9a, 0x88, 0xc3, 0x40, 0x95, 0x14, 0x21, 0x34, 0xdf, 0xc3, + 0x1f, 0xf0, 0xa2, 0xd8, 0xbb, 0xd6, 0x09, 0xb5 +}; +#define ac_dsa_vect176_prime ac_dsa_vect166_prime +#define ac_dsa_vect176_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect176_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect176_ptx[] = { +/* Msg */ + 0xba, 0xea, 0x89, 0xdc, 0xc1, 0x02, 0xcd, 0x64, 0x91, 0x35, 0xd6, 0x3a, + 0x5f, 0x52, 0xdf, 0x43, 0x7a, 0xf7, 0x84, 0x0d, 0x69, 0x9a, 0x9d, 0xaf, + 0x13, 0x1e, 0xaa, 0xc3, 0x81, 0x34, 0x8d, 0x45, 0xb4, 0xe6, 0x04, 0x77, + 0xfe, 0xa8, 0x88, 0x03, 0xfc, 0xa3, 0x1b, 0x54, 0x82, 0x9c, 0x58, 0x06, + 0xc7, 0x03, 0xeb, 0x8f, 0xdf, 0x41, 0x23, 0x06, 0xff, 0x7a, 0x79, 0xb5, + 0x5a, 0xab, 0x90, 0x64, 0xbc, 0x37, 0xcb, 0x26, 0xbf, 0xfa, 0xa6, 0x71, + 0xde, 0xbb, 0x74, 0xc2, 0x28, 0xba, 0x2d, 0x2a, 0x06, 0xda, 0x36, 0x2f, + 0x61, 0x3b, 0x78, 0xe5, 0xb1, 0xf0, 0xa0, 0xb5, 0xc5, 0xfe, 0xbf, 0x6b, + 0xc3, 0x26, 0xb0, 0x21, 0xbd, 0x7f, 0xc7, 0x04, 0x71, 0xb2, 0x5e, 0x15, + 0x3e, 0xa5, 0x1d, 0xe1, 0x01, 0x0b, 0x87, 0x11, 0x0e, 0x01, 0x49, 0x7a, + 0x7f, 0x1a, 0xc3, 0x9c, 0xf4, 0xd4, 0x24, 0xc3 +}; +static const uint8_t ac_dsa_vect176_priv_val[] = { +/* X */ + 0x2c, 0x0a, 0x2b, 0x70, 0x0e, 0xa4, 0x3f, 0x5f, 0xd5, 0x89, 0xe6, 0x65, + 0x81, 0x73, 0x39, 0xb6, 0x0f, 0x83, 0x7c, 0xa0, 0xb7, 0xdb, 0xab, 0x50, + 0xd2, 0xca, 0x7e, 0x4c, 0x36, 0x2a, 0x14, 0xe6 +}; +static const uint8_t ac_dsa_vect176_pub_val[] = { +/* Y */ + 0xcb, 0xd4, 0x65, 0xce, 0x9c, 0x3d, 0x0a, 0x13, 0x7e, 0xe3, 0xd5, 0x82, + 0xa5, 0x17, 0x21, 0x83, 0xb8, 0xa6, 0x3c, 0xfe, 0x41, 0x40, 0x70, 0xb2, + 0x47, 0xda, 0x36, 0x74, 0x56, 0x20, 0x3f, 0x98, 0x6e, 0x67, 0x86, 0xff, + 0xb8, 0x3a, 0xd7, 0x64, 0xab, 0xa3, 0x09, 0xc2, 0xef, 0x74, 0x42, 0xce, + 0x38, 0x73, 0x5f, 0x49, 0x2c, 0x0c, 0xe6, 0xd9, 0x2e, 0xaf, 0x9a, 0xe6, + 0xb1, 0xcc, 0x87, 0x3a, 0xb6, 0xff, 0x58, 0x31, 0x7c, 0xd1, 0x66, 0xa5, + 0x10, 0xc3, 0xff, 0xd8, 0xd4, 0xe6, 0x00, 0x88, 0x25, 0xb5, 0x8c, 0xae, + 0x21, 0x7f, 0xa3, 0x5c, 0x94, 0xc9, 0xbb, 0xd1, 0x2a, 0x4d, 0x63, 0x8c, + 0x20, 0x11, 0x63, 0x98, 0xb2, 0x1b, 0x59, 0x29, 0xdc, 0xa1, 0xd4, 0x9a, + 0x7b, 0x74, 0x89, 0x70, 0xe4, 0x5d, 0xe0, 0xd4, 0x32, 0xfc, 0x91, 0x2f, + 0x76, 0x19, 0x91, 0x37, 0xf1, 0xbb, 0x0c, 0x0d, 0x2c, 0x95, 0xbd, 0xcb, + 0xa0, 0xd3, 0x03, 0xec, 0xdb, 0xf4, 0x89, 0x84, 0x9b, 0xe8, 0xe6, 0x30, + 0xff, 0xff, 0x06, 0x03, 0x94, 0x8c, 0x87, 0xa7, 0xe5, 0x81, 0x31, 0x65, + 0x5c, 0x9f, 0x40, 0x77, 0x08, 0xe8, 0xa9, 0xd6, 0x75, 0xe2, 0x8e, 0x9b, + 0x57, 0x72, 0x9f, 0x03, 0x46, 0xc0, 0x28, 0x7f, 0x43, 0xed, 0x67, 0xf9, + 0xc0, 0xc0, 0xce, 0x15, 0x42, 0x98, 0x48, 0x51, 0xcc, 0x3b, 0x52, 0x1a, + 0xfa, 0x5b, 0x9b, 0x8f, 0xa5, 0x36, 0x80, 0xbd, 0xb2, 0xd7, 0x3c, 0x2b, + 0x6b, 0x09, 0x0e, 0xf0, 0x85, 0xa7, 0xe7, 0xc6, 0xf7, 0x6a, 0x2e, 0x50, + 0x10, 0x64, 0xc8, 0x52, 0x59, 0x1d, 0xf6, 0x04, 0x39, 0xa9, 0x6d, 0xd8, + 0xd6, 0x63, 0xb5, 0x64, 0xc9, 0xe5, 0xc2, 0x53, 0xee, 0x8d, 0x8e, 0xe5, + 0x8a, 0xb2, 0x7d, 0x83, 0x32, 0x11, 0x3b, 0xdd, 0x51, 0xd8, 0xb4, 0x1a, + 0xc7, 0x3c, 0x14, 0x3a +}; +/* K = 05c7a20e6e4ddb833c4e30a564436fd66716f349af551e9943bac61572e04107 */ +static const uint8_t ac_dsa_vect176_out[] = { +/* R */ + 0x76, 0x89, 0xb5, 0x24, 0x9f, 0x19, 0x43, 0xe6, 0x85, 0x09, 0x51, 0x06, + 0xd3, 0xf6, 0x83, 0x59, 0xcd, 0xb7, 0x6b, 0xe5, 0xd9, 0xa5, 0x0e, 0xbf, + 0xdf, 0x36, 0xe7, 0x31, 0x57, 0x5f, 0x8b, 0xda, +/* S */ + 0x04, 0x9d, 0xa4, 0x2d, 0xe5, 0x1e, 0x61, 0x7c, 0xdc, 0xde, 0xf1, 0x7c, + 0xdf, 0x60, 0x59, 0x34, 0x5b, 0x8e, 0x18, 0x1b, 0xac, 0x64, 0xc4, 0x71, + 0x23, 0xd4, 0x7b, 0x5e, 0xfe, 0x10, 0x5e, 0xbb +}; +#define ac_dsa_vect177_prime ac_dsa_vect166_prime +#define ac_dsa_vect177_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect177_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect177_ptx[] = { +/* Msg */ + 0xb1, 0x30, 0x37, 0x68, 0xbe, 0x17, 0x4d, 0x83, 0x57, 0x84, 0x07, 0xdd, + 0xe1, 0xab, 0x91, 0xcf, 0x02, 0x11, 0x24, 0xa3, 0x4c, 0x4a, 0x35, 0xea, + 0xfa, 0x45, 0x12, 0x70, 0x7a, 0x36, 0x60, 0xd1, 0xf8, 0x84, 0xfa, 0x6c, + 0x3d, 0x7d, 0xf2, 0x99, 0x59, 0x80, 0x18, 0xdc, 0xa2, 0x2f, 0x27, 0x3f, + 0x60, 0x2b, 0xab, 0x37, 0x15, 0x92, 0xb1, 0x1f, 0x45, 0x74, 0x88, 0x57, + 0x41, 0xab, 0x3f, 0xe2, 0xaf, 0x5b, 0x71, 0x23, 0x7d, 0x00, 0x57, 0xae, + 0x59, 0xf3, 0x7b, 0x61, 0xdf, 0xd1, 0xad, 0x5e, 0xa2, 0x7c, 0xf8, 0xf0, + 0x5f, 0x5b, 0x69, 0xf2, 0x93, 0x6e, 0xc7, 0x9d, 0x10, 0x4f, 0x4a, 0x46, + 0xc9, 0x02, 0xfb, 0x67, 0x90, 0xdf, 0xdc, 0x75, 0xb9, 0x76, 0x8c, 0xc7, + 0xdf, 0xba, 0xe0, 0x11, 0xc7, 0x95, 0xe6, 0x46, 0xf9, 0xa2, 0x34, 0x72, + 0x87, 0x07, 0xfb, 0x11, 0x2c, 0x46, 0x10, 0x07 +}; +static const uint8_t ac_dsa_vect177_priv_val[] = { +/* X */ + 0x24, 0x7f, 0xcc, 0xb4, 0x4c, 0x2c, 0x0c, 0xb1, 0xf1, 0xe5, 0x8d, 0x10, + 0x33, 0xea, 0xbd, 0x20, 0x3d, 0x8d, 0x87, 0x4d, 0x0b, 0xf1, 0x8b, 0xa7, + 0x0f, 0x04, 0xb7, 0x5b, 0xd6, 0x49, 0x5b, 0xad +}; +static const uint8_t ac_dsa_vect177_pub_val[] = { +/* Y */ + 0x56, 0x02, 0xdd, 0x57, 0x9f, 0xbe, 0x37, 0xf1, 0x87, 0xd4, 0x9d, 0x76, + 0xfd, 0x59, 0x36, 0xfc, 0xde, 0xf2, 0x36, 0x9f, 0x7a, 0xf2, 0x9d, 0xa4, + 0x3c, 0x64, 0x56, 0xa6, 0xac, 0x83, 0x17, 0xb3, 0x9e, 0x4c, 0xd6, 0x79, + 0x14, 0x3a, 0x4d, 0x97, 0x75, 0x1b, 0x80, 0xce, 0x1c, 0xb4, 0x51, 0x86, + 0xda, 0x7b, 0xee, 0x99, 0x1e, 0x25, 0xeb, 0x9a, 0x1a, 0xed, 0x14, 0x90, + 0xfd, 0x74, 0xf6, 0xab, 0x50, 0x79, 0x40, 0x82, 0x1a, 0x1a, 0xdf, 0xbc, + 0x30, 0xe1, 0x9a, 0x93, 0x3c, 0xc4, 0xd2, 0x17, 0x69, 0xcc, 0xdf, 0xc5, + 0x7c, 0x96, 0xf0, 0xd2, 0x19, 0x44, 0xf8, 0xa0, 0xf1, 0x31, 0x62, 0x6e, + 0xd0, 0x13, 0xb3, 0xe5, 0xc0, 0x13, 0x13, 0xa1, 0x75, 0x6b, 0x67, 0xb7, + 0xd2, 0xa2, 0x1e, 0xda, 0xc4, 0x86, 0xcb, 0xc3, 0xcd, 0x1d, 0x2b, 0x6f, + 0xcf, 0x20, 0xc8, 0x2d, 0xd7, 0x0b, 0x4f, 0x72, 0x92, 0x9c, 0x14, 0x99, + 0xad, 0x79, 0x6d, 0xe8, 0x94, 0xdb, 0x8a, 0xf1, 0x03, 0xd9, 0xb9, 0x1c, + 0x25, 0x73, 0x70, 0x73, 0xd9, 0xdf, 0x62, 0xe6, 0xb6, 0x24, 0xb9, 0x0f, + 0xb3, 0x52, 0xdb, 0x78, 0x1c, 0x7f, 0x2f, 0xf8, 0xd3, 0xa2, 0x0a, 0x70, + 0x63, 0xfb, 0x51, 0x27, 0x23, 0x95, 0xcc, 0x7d, 0x35, 0xef, 0x79, 0xc2, + 0x7b, 0x76, 0x34, 0xe3, 0x9f, 0x74, 0xeb, 0x15, 0x29, 0x75, 0xfd, 0xf3, + 0xb9, 0x03, 0xc2, 0x39, 0x90, 0xee, 0xde, 0x8a, 0xa5, 0x8d, 0xf9, 0xa2, + 0x99, 0x54, 0x33, 0x3a, 0x3f, 0x52, 0x5d, 0x5b, 0xaa, 0xfd, 0x37, 0x9d, + 0xd5, 0x7f, 0xe3, 0x96, 0xa5, 0x18, 0x76, 0xf2, 0x5d, 0x9e, 0x82, 0x65, + 0xcf, 0x69, 0x71, 0xed, 0xc6, 0x27, 0x8c, 0xe9, 0x96, 0xbd, 0xee, 0x20, + 0x68, 0x83, 0x44, 0x8a, 0xf1, 0x84, 0xfa, 0xe2, 0x3a, 0xf2, 0xa6, 0x95, + 0x72, 0xb2, 0x00, 0x90 +}; +/* K = 0b94ed40c05a4ef445309afb5583cba8d411ff4092452c0a064dbbe6e3ccd1a5 */ +static const uint8_t ac_dsa_vect177_out[] = { +/* R */ + 0x18, 0x00, 0xb6, 0xbd, 0x5c, 0x94, 0xa0, 0x31, 0xd9, 0x77, 0xb9, 0xd0, + 0x17, 0x54, 0x17, 0x90, 0xa9, 0xfe, 0x7e, 0x41, 0x4c, 0x90, 0xfa, 0x4d, + 0x38, 0x03, 0xd5, 0x6e, 0xf1, 0x6a, 0x64, 0x79, +/* S */ + 0x07, 0xec, 0xe1, 0xb6, 0x47, 0x11, 0xc9, 0xb3, 0xec, 0xa4, 0x89, 0xe7, + 0x5f, 0x2e, 0x63, 0x43, 0x8e, 0x09, 0x74, 0x98, 0xe2, 0x89, 0x0d, 0xd0, + 0x27, 0x37, 0x29, 0xa5, 0x5d, 0xf0, 0xd2, 0xdf +}; +#define ac_dsa_vect178_prime ac_dsa_vect166_prime +#define ac_dsa_vect178_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect178_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect178_ptx[] = { +/* Msg */ + 0x25, 0xca, 0x3d, 0xc8, 0xe6, 0xea, 0x4e, 0xbb, 0x93, 0x6f, 0xa0, 0x1b, + 0x1c, 0xcc, 0x08, 0xbb, 0x1d, 0xe9, 0x23, 0xbe, 0x62, 0x92, 0x42, 0x1f, + 0xf9, 0xf7, 0x73, 0xaf, 0x9c, 0xc7, 0x39, 0x35, 0x10, 0xdf, 0x2f, 0xcb, + 0x6e, 0xc1, 0x88, 0xb2, 0x7c, 0x26, 0x88, 0xc7, 0x2f, 0xdc, 0x2f, 0xf6, + 0xc9, 0x0f, 0x0a, 0xb0, 0xed, 0x59, 0xc9, 0xc3, 0xa6, 0x50, 0x3f, 0x53, + 0xe3, 0x27, 0x78, 0xb9, 0x54, 0xea, 0xe5, 0x82, 0xc9, 0x58, 0x03, 0xc5, + 0x11, 0xff, 0x39, 0x18, 0xad, 0xda, 0x02, 0xe6, 0x8e, 0x2c, 0x3e, 0x73, + 0xf8, 0xa6, 0xad, 0x60, 0x7a, 0x89, 0xd8, 0xeb, 0xa0, 0x05, 0x9e, 0xb8, + 0x7f, 0x4d, 0x9b, 0x00, 0x81, 0xf2, 0x96, 0x96, 0x1e, 0xc6, 0xea, 0x78, + 0x85, 0x3a, 0xa5, 0x3d, 0x24, 0xa4, 0x70, 0xa7, 0x4a, 0xcf, 0x16, 0xa2, + 0xf8, 0x67, 0x48, 0xa8, 0xda, 0x34, 0xfb, 0x90 +}; +static const uint8_t ac_dsa_vect178_priv_val[] = { +/* X */ + 0x32, 0xb6, 0xf7, 0xce, 0x3c, 0xe9, 0x97, 0x70, 0xb8, 0x88, 0xc1, 0xef, + 0x23, 0xa8, 0x63, 0x77, 0xf3, 0xe0, 0x0a, 0xdf, 0x5d, 0xab, 0x2e, 0x38, + 0x0e, 0xf8, 0xc4, 0x29, 0x8d, 0x20, 0xa1, 0xee +}; +static const uint8_t ac_dsa_vect178_pub_val[] = { +/* Y */ + 0xbf, 0x2e, 0x14, 0x0f, 0x8b, 0x8d, 0x99, 0xd2, 0xdf, 0x10, 0x52, 0xe9, + 0x81, 0xfa, 0x0a, 0xc5, 0x33, 0xc0, 0xd4, 0xea, 0x9f, 0x26, 0x6f, 0x92, + 0x67, 0xcd, 0xe7, 0xba, 0x03, 0xcf, 0x10, 0x01, 0x5d, 0xa1, 0xcc, 0x13, + 0x61, 0x2d, 0xcf, 0xc9, 0x20, 0x30, 0xb7, 0xc7, 0xd1, 0xc0, 0x57, 0xe2, + 0x8a, 0x6f, 0xb4, 0x57, 0x48, 0xee, 0xb9, 0xc4, 0xbd, 0x2e, 0x6e, 0x79, + 0xb2, 0x17, 0xf4, 0xb6, 0x8e, 0xf0, 0x3f, 0x96, 0x59, 0xc8, 0xe8, 0x4a, + 0x20, 0xee, 0x92, 0x0d, 0x29, 0x71, 0x13, 0x81, 0xce, 0x39, 0xfe, 0x0a, + 0xfc, 0x9a, 0x7f, 0xe2, 0xfb, 0xdf, 0xce, 0x63, 0x24, 0x96, 0x51, 0x23, + 0x0f, 0x3e, 0x72, 0xee, 0xd5, 0x79, 0xf0, 0xd3, 0x65, 0x9c, 0x2b, 0xff, + 0xc7, 0x0f, 0xb5, 0xd8, 0xbe, 0x88, 0x9a, 0x34, 0xbb, 0x67, 0xf1, 0xa9, + 0x04, 0xc3, 0x18, 0x56, 0x83, 0x94, 0xb9, 0x46, 0xfd, 0x40, 0x38, 0x37, + 0x82, 0xcb, 0x5e, 0x48, 0x09, 0xd0, 0xc6, 0x01, 0x9d, 0x20, 0xaf, 0xad, + 0x09, 0xf2, 0x9f, 0xbb, 0xc9, 0x94, 0xd2, 0x8f, 0x4e, 0x41, 0xda, 0xf4, + 0x66, 0x62, 0x98, 0xf3, 0x51, 0x89, 0x8d, 0x8d, 0xef, 0x40, 0x47, 0x12, + 0xc4, 0x09, 0x74, 0x5a, 0x88, 0x96, 0x2e, 0x4a, 0x61, 0x8c, 0x23, 0x49, + 0x76, 0x64, 0x55, 0x59, 0xc9, 0x0c, 0x54, 0xfe, 0x76, 0x4e, 0xea, 0x46, + 0xfa, 0x03, 0x54, 0x3e, 0x4c, 0x4f, 0x25, 0xc8, 0xd2, 0xc3, 0xc1, 0x97, + 0x9f, 0x95, 0x24, 0x58, 0x17, 0x7d, 0xc6, 0x96, 0x3e, 0x3f, 0x34, 0x6a, + 0x7f, 0xdd, 0xbe, 0x0c, 0xdf, 0x23, 0xdd, 0xc7, 0xd2, 0xfa, 0x8a, 0x34, + 0x55, 0xcd, 0x5b, 0x54, 0x6e, 0x47, 0x16, 0x99, 0x12, 0xce, 0x7f, 0x33, + 0x3a, 0xc6, 0xf0, 0x1e, 0x64, 0xae, 0xc5, 0x96, 0x08, 0x0b, 0x5d, 0x3e, + 0x0f, 0x25, 0xad, 0xb9 +}; +/* K = 73418db52c6594dd0956d9e3616a205de8204220648addd4bfd3a9fee412462a */ +static const uint8_t ac_dsa_vect178_out[] = { +/* R */ + 0x7b, 0x1d, 0xfc, 0xf3, 0x9b, 0x62, 0x4d, 0x64, 0xdb, 0x08, 0xa3, 0x97, + 0x4c, 0x8e, 0x14, 0x17, 0x31, 0x05, 0x01, 0x0f, 0x2b, 0xd5, 0x13, 0x5e, + 0x92, 0x6f, 0x28, 0x84, 0xe3, 0x0b, 0x46, 0xfa, +/* S */ + 0x69, 0x7e, 0xea, 0xb6, 0x69, 0x67, 0x74, 0x69, 0xf6, 0x2c, 0xca, 0x46, + 0xd3, 0xe6, 0x8c, 0x84, 0x9f, 0x44, 0x78, 0x81, 0xe2, 0xc9, 0xf7, 0x42, + 0x94, 0xf4, 0xe8, 0xad, 0xa4, 0x42, 0x6c, 0x7d +}; +#define ac_dsa_vect179_prime ac_dsa_vect166_prime +#define ac_dsa_vect179_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect179_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect179_ptx[] = { +/* Msg */ + 0xd5, 0x8a, 0x8f, 0x5a, 0xb4, 0x4f, 0x9d, 0xf9, 0xed, 0x93, 0x6a, 0x13, + 0x18, 0x65, 0x7c, 0x32, 0x4f, 0xb1, 0x39, 0x9c, 0x25, 0x10, 0x54, 0x98, + 0x6d, 0x19, 0x21, 0x4c, 0x15, 0xce, 0x95, 0x1f, 0x87, 0xcc, 0xb3, 0x51, + 0x0a, 0xed, 0x90, 0x85, 0x41, 0x1d, 0x9c, 0x5a, 0x67, 0x40, 0xdf, 0x51, + 0x60, 0xf3, 0xe5, 0x7e, 0xa8, 0xc9, 0x42, 0xd3, 0x35, 0x47, 0x31, 0x7c, + 0x7a, 0x38, 0x7c, 0x60, 0xc7, 0xac, 0x2f, 0x0e, 0x14, 0x17, 0x1f, 0x0b, + 0x77, 0x19, 0xab, 0xa7, 0x6a, 0xc4, 0x18, 0xd1, 0x57, 0xa4, 0xe3, 0xbe, + 0xc6, 0xb7, 0x99, 0xb5, 0xda, 0x10, 0xbd, 0x3e, 0xcd, 0xda, 0xe0, 0x85, + 0x7a, 0x29, 0x67, 0x0c, 0x99, 0xd3, 0x78, 0x10, 0x34, 0x9b, 0x82, 0xb7, + 0xbb, 0x37, 0xc0, 0x93, 0x7b, 0x0d, 0xd2, 0x73, 0x4d, 0xa0, 0x8b, 0x8b, + 0x1c, 0xb7, 0xbe, 0xec, 0xd4, 0x3c, 0xb6, 0x15 +}; +static const uint8_t ac_dsa_vect179_priv_val[] = { +/* X */ + 0x23, 0xa1, 0x29, 0x0f, 0x8a, 0xcb, 0xad, 0xc3, 0x52, 0xa2, 0x82, 0x01, + 0x57, 0x13, 0xd6, 0xcf, 0x5a, 0x88, 0xe8, 0x90, 0x1c, 0xb9, 0x58, 0x8a, + 0x57, 0x15, 0x17, 0x72, 0x61, 0x9f, 0x5a, 0xe6 +}; +static const uint8_t ac_dsa_vect179_pub_val[] = { +/* Y */ + 0xba, 0xa1, 0x36, 0x52, 0x64, 0x2d, 0x95, 0x0d, 0x8b, 0xce, 0xc1, 0x6c, + 0x62, 0x4a, 0x07, 0x99, 0x9f, 0xb5, 0x57, 0xfb, 0x40, 0xa2, 0x66, 0x29, + 0x7c, 0x15, 0x65, 0x97, 0x55, 0xfd, 0x61, 0x5c, 0xc7, 0xe2, 0x12, 0x5d, + 0x4e, 0x8c, 0x8a, 0xf8, 0xc4, 0x33, 0x35, 0x53, 0x90, 0x05, 0xe9, 0xe2, + 0xf2, 0xd4, 0x04, 0x28, 0xe7, 0xc8, 0xcc, 0x05, 0x5f, 0xf3, 0xf6, 0xfe, + 0x3b, 0x3d, 0xf6, 0x04, 0xac, 0x12, 0x8d, 0x99, 0x5c, 0xfb, 0x9c, 0x86, + 0x7e, 0x2a, 0x96, 0x07, 0xaa, 0x3b, 0x77, 0xcf, 0x0f, 0x69, 0x17, 0x38, + 0xb7, 0x84, 0xd4, 0xbe, 0x2f, 0xea, 0x47, 0x39, 0xfd, 0xa1, 0xf0, 0x67, + 0x42, 0x60, 0xf2, 0x1f, 0x66, 0x6a, 0xce, 0xf5, 0xbd, 0x56, 0xa7, 0x80, + 0x0b, 0xbe, 0x95, 0x07, 0x92, 0xba, 0x05, 0xee, 0xe4, 0x2e, 0x80, 0xa2, + 0x57, 0x8d, 0x2c, 0x50, 0xec, 0x28, 0xd4, 0x4a, 0xfb, 0x6b, 0x68, 0x76, + 0x52, 0xbb, 0x94, 0x52, 0x40, 0x8f, 0xca, 0xf2, 0x57, 0xc4, 0xb5, 0xcd, + 0x56, 0x4d, 0xdc, 0x4e, 0x63, 0xce, 0x9c, 0xa1, 0x3d, 0x4c, 0x74, 0x73, + 0xf5, 0x1b, 0x01, 0xac, 0x8e, 0x4c, 0x3f, 0x79, 0x9a, 0xfc, 0x90, 0x8e, + 0xae, 0xac, 0xca, 0xd0, 0x62, 0xb0, 0xf9, 0x7d, 0x95, 0x8a, 0x30, 0x08, + 0xca, 0xe2, 0x20, 0x62, 0xbb, 0x16, 0x6c, 0x73, 0x00, 0xdf, 0x0b, 0x43, + 0x86, 0xba, 0xec, 0xd5, 0x99, 0xfa, 0x8b, 0x08, 0x3f, 0xba, 0x6e, 0x7e, + 0x4e, 0x5b, 0xa1, 0x19, 0x86, 0x02, 0x68, 0x51, 0x7d, 0x79, 0xeb, 0xdc, + 0xbe, 0x02, 0x43, 0x7b, 0xf4, 0xeb, 0x5d, 0x91, 0xa8, 0x43, 0x72, 0x5d, + 0xb0, 0xed, 0xa6, 0x6e, 0xed, 0xd4, 0x6d, 0x66, 0xb7, 0x81, 0xac, 0xed, + 0x0d, 0xcc, 0x23, 0x15, 0x4e, 0x4b, 0x8a, 0x8f, 0x04, 0x53, 0xb2, 0xf4, + 0x66, 0x03, 0x3b, 0xd9 +}; +/* K = 25f8923843d757ee4b7571b42de58925b0c2678ec89df07248b4cf34d83db926 */ +static const uint8_t ac_dsa_vect179_out[] = { +/* R */ + 0x18, 0x76, 0xb2, 0x09, 0x26, 0xd8, 0xed, 0xe7, 0x8d, 0x28, 0x17, 0x4e, + 0xeb, 0x4c, 0xb0, 0xc1, 0xaf, 0x8e, 0xe2, 0x06, 0xfc, 0x8d, 0xb4, 0xa8, + 0xcd, 0xeb, 0xb5, 0xdb, 0xfb, 0x0c, 0x15, 0xcf, +/* S */ + 0x23, 0x1a, 0xf0, 0x7a, 0xeb, 0xa9, 0x9f, 0xfd, 0x00, 0x65, 0x93, 0x94, + 0xab, 0x6e, 0xd1, 0x9a, 0x5e, 0x9f, 0x9e, 0x60, 0xe2, 0x19, 0x7f, 0x65, + 0xfc, 0x88, 0xc8, 0x15, 0xbe, 0xae, 0x7f, 0xe0 +}; +#define ac_dsa_vect180_prime ac_dsa_vect166_prime +#define ac_dsa_vect180_sub_prime ac_dsa_vect166_sub_prime +#define ac_dsa_vect180_base ac_dsa_vect166_base +static const uint8_t ac_dsa_vect180_ptx[] = { +/* Msg */ + 0xaa, 0x13, 0x4e, 0x9d, 0xb7, 0x39, 0x82, 0xe7, 0xa3, 0x7a, 0x10, 0x34, + 0xaa, 0xb8, 0x2b, 0x50, 0xd5, 0xe5, 0x8e, 0x03, 0x4a, 0x56, 0x37, 0x08, + 0x1d, 0xc8, 0x80, 0xa6, 0xe2, 0x65, 0xeb, 0xc7, 0xb3, 0x53, 0xdf, 0x21, + 0x03, 0x04, 0xba, 0x00, 0x77, 0x1c, 0x5b, 0xab, 0x44, 0x5d, 0xc6, 0xc2, + 0x49, 0x99, 0xfe, 0x8e, 0xaf, 0xde, 0xfa, 0xbc, 0xdd, 0x46, 0xf7, 0xa9, + 0x1f, 0x30, 0x72, 0x1a, 0x68, 0x96, 0x33, 0x3c, 0x3f, 0x30, 0x1e, 0x19, + 0x7f, 0x96, 0x19, 0x44, 0xf5, 0x45, 0xe4, 0xfe, 0x07, 0x30, 0xcd, 0x96, + 0x77, 0x90, 0x50, 0x4c, 0x49, 0xb0, 0xab, 0x5b, 0x89, 0x08, 0x09, 0xbe, + 0x5c, 0x7c, 0x1c, 0x3f, 0x8a, 0x2e, 0x52, 0xd9, 0x2a, 0x2c, 0x19, 0x9b, + 0x98, 0x1b, 0x64, 0x8f, 0xdd, 0x52, 0x8e, 0x76, 0x8e, 0x6a, 0xb3, 0x92, + 0x57, 0x9b, 0x54, 0xc7, 0x2c, 0x41, 0x61, 0x7d +}; +static const uint8_t ac_dsa_vect180_priv_val[] = { +/* X */ + 0x02, 0xef, 0x07, 0x8e, 0x61, 0xdf, 0x31, 0x82, 0x37, 0xc9, 0xa2, 0x17, + 0xb5, 0xdd, 0xbd, 0xa1, 0x2a, 0xb9, 0xff, 0xde, 0x68, 0xa2, 0x01, 0x97, + 0x17, 0x82, 0xb6, 0x1b, 0x73, 0x21, 0x4c, 0xae +}; +static const uint8_t ac_dsa_vect180_pub_val[] = { +/* Y */ + 0x69, 0x1d, 0xfe, 0xa1, 0x44, 0xe5, 0x1b, 0x9e, 0x0f, 0xf7, 0x53, 0x65, + 0x57, 0xb5, 0x8a, 0xce, 0x87, 0x16, 0x26, 0x3a, 0x70, 0x55, 0x4e, 0x2f, + 0x46, 0x76, 0xd1, 0x72, 0x33, 0x2a, 0xed, 0xaa, 0x67, 0x73, 0x6d, 0x72, + 0x66, 0x7d, 0x32, 0x81, 0x70, 0xac, 0xa0, 0x70, 0xe1, 0xbb, 0x89, 0x86, + 0x8b, 0xf4, 0xcc, 0x98, 0x96, 0x2d, 0x87, 0xeb, 0x05, 0x99, 0xf1, 0x08, + 0x28, 0xc6, 0xea, 0x24, 0xcf, 0xfe, 0xde, 0x8e, 0xd7, 0xb3, 0x9a, 0xbb, + 0xa6, 0x66, 0xbd, 0x6d, 0x0d, 0x35, 0x02, 0x4a, 0xde, 0x6a, 0xaa, 0x06, + 0xfe, 0x6a, 0xe4, 0x5d, 0xc4, 0xb3, 0xa9, 0x1c, 0x21, 0x9d, 0x47, 0x2d, + 0xb0, 0xef, 0xed, 0x46, 0x9d, 0x69, 0xcb, 0x5f, 0x11, 0xd4, 0x01, 0x58, + 0xea, 0x81, 0x67, 0x2b, 0x1a, 0xe1, 0x16, 0xff, 0x2c, 0x30, 0x16, 0xf2, + 0x45, 0x25, 0x4e, 0x98, 0x4a, 0x59, 0x94, 0x5e, 0x4e, 0x3b, 0x3d, 0x37, + 0xad, 0x12, 0x05, 0x8d, 0x84, 0x08, 0x29, 0x55, 0xc7, 0x68, 0x64, 0x3e, + 0x7d, 0x80, 0xc0, 0x55, 0xc1, 0x70, 0x3a, 0x88, 0x3f, 0x2a, 0xbb, 0x07, + 0x5a, 0x24, 0xc2, 0xe9, 0x30, 0x56, 0x69, 0x73, 0x40, 0x93, 0x1c, 0x25, + 0x89, 0x4d, 0x1d, 0x2f, 0xfa, 0xc4, 0xb1, 0x02, 0x20, 0x12, 0xc1, 0x5c, + 0xb7, 0x07, 0xfb, 0x35, 0x96, 0x83, 0xad, 0x04, 0x08, 0xb6, 0x68, 0x77, + 0x9e, 0x9d, 0x9b, 0xa2, 0x19, 0x89, 0xba, 0xa6, 0xa6, 0xb0, 0xb2, 0x56, + 0xa3, 0x4e, 0xfb, 0x47, 0x51, 0xbc, 0xaf, 0x42, 0x85, 0xb1, 0x56, 0x35, + 0xd4, 0x09, 0xfd, 0xa9, 0x93, 0xc0, 0x43, 0x8a, 0xcd, 0xdc, 0x9d, 0xa0, + 0x06, 0xc3, 0x90, 0x36, 0x03, 0x04, 0xab, 0x12, 0xda, 0x76, 0xb4, 0x44, + 0xd6, 0x4e, 0x11, 0xcc, 0xf0, 0x5d, 0x96, 0x3f, 0xfb, 0x7f, 0x38, 0x9b, + 0xee, 0x83, 0x1d, 0xc7 +}; +/* K = 013e35ddd416e092335f3bb24a5e826e3e06cb90daad599a42cb5ae8da830b24 */ +static const uint8_t ac_dsa_vect180_out[] = { +/* R */ + 0x04, 0x1d, 0x22, 0x93, 0x49, 0xce, 0xc7, 0x5f, 0xb2, 0xbd, 0x8c, 0x35, + 0xc2, 0x49, 0xf9, 0x19, 0x6a, 0x18, 0x96, 0x2c, 0xa7, 0x5e, 0xbd, 0xb4, + 0x2d, 0xca, 0x61, 0xd2, 0x1c, 0xb0, 0xe9, 0x10, +/* S */ + 0x77, 0xbb, 0x79, 0x75, 0xa5, 0x44, 0xc5, 0x1b, 0xf2, 0x49, 0xde, 0xe2, + 0x35, 0x95, 0x23, 0x07, 0x28, 0x63, 0x93, 0x44, 0x97, 0xd1, 0xa4, 0x79, + 0xd6, 0xe4, 0xb2, 0x45, 0xd4, 0x56, 0xeb, 0x2a +}; +/* [mod = L=2048, N=256, SHA-256] */ +static const uint8_t ac_dsa_vect181_prime[] = { +/* P */ + 0xa8, 0xad, 0xb6, 0xc0, 0xb4, 0xcf, 0x95, 0x88, 0x01, 0x2e, 0x5d, 0xef, + 0xf1, 0xa8, 0x71, 0xd3, 0x83, 0xe0, 0xe2, 0xa8, 0x5b, 0x5e, 0x8e, 0x03, + 0xd8, 0x14, 0xfe, 0x13, 0xa0, 0x59, 0x70, 0x5e, 0x66, 0x32, 0x30, 0xa3, + 0x77, 0xbf, 0x73, 0x23, 0xa8, 0xfa, 0x11, 0x71, 0x00, 0x20, 0x0b, 0xfd, + 0x5a, 0xdf, 0x85, 0x73, 0x93, 0xb0, 0xbb, 0xd6, 0x79, 0x06, 0xc0, 0x81, + 0xe5, 0x85, 0x41, 0x0e, 0x38, 0x48, 0x0e, 0xad, 0x51, 0x68, 0x4d, 0xac, + 0x3a, 0x38, 0xf7, 0xb6, 0x4c, 0x9e, 0xb1, 0x09, 0xf1, 0x97, 0x39, 0xa4, + 0x51, 0x7c, 0xd7, 0xd5, 0xd6, 0x29, 0x1e, 0x8a, 0xf2, 0x0a, 0x3f, 0xbf, + 0x17, 0x33, 0x6c, 0x7b, 0xf8, 0x0e, 0xe7, 0x18, 0xee, 0x08, 0x7e, 0x32, + 0x2e, 0xe4, 0x10, 0x47, 0xda, 0xbe, 0xfb, 0xcc, 0x34, 0xd1, 0x0b, 0x66, + 0xb6, 0x44, 0xdd, 0xb3, 0x16, 0x0a, 0x28, 0xc0, 0x63, 0x95, 0x63, 0xd7, + 0x19, 0x93, 0xa2, 0x65, 0x43, 0xea, 0xdb, 0x77, 0x18, 0xf3, 0x17, 0xbf, + 0x5d, 0x95, 0x77, 0xa6, 0x15, 0x65, 0x61, 0xb0, 0x82, 0xa1, 0x00, 0x29, + 0xcd, 0x44, 0x01, 0x2b, 0x18, 0xde, 0x68, 0x44, 0x50, 0x9f, 0xe0, 0x58, + 0xba, 0x87, 0x98, 0x07, 0x92, 0x28, 0x5f, 0x27, 0x50, 0x96, 0x9f, 0xe8, + 0x9c, 0x2c, 0xd6, 0x49, 0x8d, 0xb3, 0x54, 0x56, 0x38, 0xd5, 0x37, 0x9d, + 0x12, 0x5d, 0xcc, 0xf6, 0x4e, 0x06, 0xc1, 0xaf, 0x33, 0xa6, 0x19, 0x08, + 0x41, 0xd2, 0x23, 0xda, 0x15, 0x13, 0x33, 0x3a, 0x7c, 0x9d, 0x78, 0x46, + 0x2a, 0xba, 0xab, 0x31, 0xb9, 0xf9, 0x6d, 0x5f, 0x34, 0x44, 0x5c, 0xeb, + 0x63, 0x09, 0xf2, 0xf6, 0xd2, 0xc8, 0xdd, 0xe0, 0x64, 0x41, 0xe8, 0x79, + 0x80, 0xd3, 0x03, 0xef, 0x9a, 0x1f, 0xf0, 0x07, 0xe8, 0xbe, 0x2f, 0x0b, + 0xe0, 0x6c, 0xc1, 0x5f +}; +static const uint8_t ac_dsa_vect181_sub_prime[] = { +/* Q */ + 0xe7, 0x1f, 0x85, 0x67, 0x44, 0x7f, 0x42, 0xe7, 0x5f, 0x5e, 0xf8, 0x5c, + 0xa2, 0x0f, 0xe5, 0x57, 0xab, 0x03, 0x43, 0xd3, 0x7e, 0xd0, 0x9e, 0xdc, + 0x3f, 0x6e, 0x68, 0x60, 0x4d, 0x6b, 0x9d, 0xfb +}; +static const uint8_t ac_dsa_vect181_base[] = { +/* G */ + 0x5b, 0xa2, 0x4d, 0xe9, 0x60, 0x7b, 0x89, 0x98, 0xe6, 0x6c, 0xe6, 0xc4, + 0xf8, 0x12, 0xa3, 0x14, 0xc6, 0x93, 0x58, 0x42, 0xf7, 0xab, 0x54, 0xcd, + 0x82, 0xb1, 0x9f, 0xa1, 0x04, 0xab, 0xfb, 0x5d, 0x84, 0x57, 0x9a, 0x62, + 0x3b, 0x25, 0x74, 0xb3, 0x7d, 0x22, 0xcc, 0xae, 0x9b, 0x3e, 0x41, 0x5e, + 0x48, 0xf5, 0xc0, 0xf9, 0xbc, 0xbd, 0xff, 0x80, 0x71, 0xd6, 0x3b, 0x9b, + 0xb9, 0x56, 0xe5, 0x47, 0xaf, 0x3a, 0x8d, 0xf9, 0x9e, 0x5d, 0x30, 0x61, + 0x97, 0x96, 0x52, 0xff, 0x96, 0xb7, 0x65, 0xcb, 0x3e, 0xe4, 0x93, 0x64, + 0x35, 0x44, 0xc7, 0x5d, 0xbe, 0x5b, 0xb3, 0x98, 0x34, 0x53, 0x19, 0x52, + 0xa0, 0xfb, 0x4b, 0x03, 0x78, 0xb3, 0xfc, 0xbb, 0x4c, 0x8b, 0x58, 0x00, + 0xa5, 0x33, 0x03, 0x92, 0xa2, 0xa0, 0x4e, 0x70, 0x0b, 0xb6, 0xed, 0x7e, + 0x0b, 0x85, 0x79, 0x5e, 0xa3, 0x8b, 0x1b, 0x96, 0x27, 0x41, 0xb3, 0xf3, + 0x3b, 0x9d, 0xde, 0x2f, 0x4e, 0xc1, 0x35, 0x4f, 0x09, 0xe2, 0xeb, 0x78, + 0xe9, 0x5f, 0x03, 0x7a, 0x58, 0x04, 0xb6, 0x17, 0x16, 0x59, 0xf8, 0x87, + 0x15, 0xce, 0x1a, 0x9b, 0x0c, 0xc9, 0x0c, 0x27, 0xf3, 0x5e, 0xf2, 0xf1, + 0x0f, 0xf0, 0xc7, 0xc7, 0xa2, 0xbb, 0x01, 0x54, 0xd9, 0xb8, 0xeb, 0xe7, + 0x6a, 0x3d, 0x76, 0x4a, 0xa8, 0x79, 0xaf, 0x37, 0x2f, 0x42, 0x40, 0xde, + 0x83, 0x47, 0x93, 0x7e, 0x5a, 0x90, 0xce, 0xc9, 0xf4, 0x1f, 0xf2, 0xf2, + 0x6b, 0x8d, 0xa9, 0xa9, 0x4a, 0x22, 0x5d, 0x1a, 0x91, 0x37, 0x17, 0xd7, + 0x3f, 0x10, 0x39, 0x7d, 0x21, 0x83, 0xf1, 0xba, 0x3b, 0x7b, 0x45, 0xa6, + 0x8f, 0x1f, 0xf1, 0x89, 0x3c, 0xaf, 0x69, 0xa8, 0x27, 0x80, 0x2f, 0x7b, + 0x6a, 0x48, 0xd5, 0x1d, 0xa6, 0xfb, 0xef, 0xb6, 0x4f, 0xd9, 0xa6, 0xc5, + 0xb7, 0x5c, 0x45, 0x61 +}; +static const uint8_t ac_dsa_vect181_ptx[] = { +/* Msg */ + 0x4e, 0x3a, 0x28, 0xbc, 0xf9, 0x0d, 0x1d, 0x2e, 0x75, 0xf0, 0x75, 0xd9, + 0xfb, 0xe5, 0x5b, 0x36, 0xc5, 0x52, 0x9b, 0x17, 0xbc, 0x3a, 0x9c, 0xca, + 0xba, 0x69, 0x35, 0xc9, 0xe2, 0x05, 0x48, 0x25, 0x5b, 0x3d, 0xfa, 0xe0, + 0xf9, 0x1d, 0xb0, 0x30, 0xc1, 0x2f, 0x2c, 0x34, 0x4b, 0x3a, 0x29, 0xc4, + 0x15, 0x1c, 0x5b, 0x20, 0x9f, 0x5e, 0x31, 0x9f, 0xdf, 0x1c, 0x23, 0xb1, + 0x90, 0xf6, 0x4f, 0x1f, 0xe5, 0xb3, 0x30, 0xcb, 0x7c, 0x8f, 0xa9, 0x52, + 0xf9, 0xd9, 0x0f, 0x13, 0xaf, 0xf1, 0xcb, 0x11, 0xd6, 0x31, 0x81, 0xda, + 0x9e, 0xfc, 0x6f, 0x7e, 0x15, 0xbf, 0xed, 0x48, 0x62, 0xd1, 0xa6, 0x2c, + 0x7d, 0xcf, 0x3b, 0xa8, 0xbf, 0x1f, 0xf3, 0x04, 0xb1, 0x02, 0xb1, 0xec, + 0x3f, 0x14, 0x97, 0xdd, 0xdf, 0x09, 0x71, 0x2c, 0xf3, 0x23, 0xf5, 0x61, + 0x0a, 0x9d, 0x10, 0xc3, 0xd9, 0x13, 0x26, 0x59 +}; +static const uint8_t ac_dsa_vect181_priv_val[] = { +/* X */ + 0x44, 0x69, 0x69, 0x02, 0x54, 0x46, 0x24, 0x7f, 0x84, 0xfd, 0xea, 0x74, + 0xd0, 0x2d, 0x7d, 0xd1, 0x36, 0x72, 0xb2, 0xde, 0xb7, 0xc0, 0x85, 0xbe, + 0x11, 0x11, 0x14, 0x41, 0x95, 0x5a, 0x37, 0x7b +}; +static const uint8_t ac_dsa_vect181_pub_val[] = { +/* Y */ + 0x5a, 0x55, 0xdc, 0xed, 0xdd, 0x11, 0x34, 0xee, 0x5f, 0x11, 0xed, 0x85, + 0xde, 0xb4, 0xd6, 0x34, 0xa3, 0x64, 0x3f, 0x5f, 0x36, 0xdc, 0x3a, 0x70, + 0x68, 0x92, 0x56, 0x46, 0x9a, 0x0b, 0x65, 0x1a, 0xd2, 0x28, 0x80, 0xf1, + 0x4a, 0xb8, 0x57, 0x19, 0x43, 0x4f, 0x9c, 0x0e, 0x40, 0x7e, 0x60, 0xea, + 0x42, 0x0e, 0x2a, 0x0c, 0xd2, 0x94, 0x22, 0xc4, 0x89, 0x9c, 0x41, 0x63, + 0x59, 0xdb, 0xb1, 0xe5, 0x92, 0x45, 0x6f, 0x2b, 0x3c, 0xce, 0x23, 0x32, + 0x59, 0xc1, 0x17, 0x54, 0x2f, 0xd0, 0x5f, 0x31, 0xea, 0x25, 0xb0, 0x15, + 0xd9, 0x12, 0x1c, 0x89, 0x0b, 0x90, 0xe0, 0xba, 0xd0, 0x33, 0xbe, 0x13, + 0x68, 0xd2, 0x29, 0x98, 0x5a, 0xac, 0x72, 0x26, 0xd1, 0xc8, 0xc2, 0xea, + 0xb3, 0x25, 0xef, 0x3b, 0x2c, 0xd5, 0x9d, 0x3b, 0x9f, 0x7d, 0xe7, 0xdb, + 0xc9, 0x4a, 0xf1, 0xa9, 0x33, 0x9e, 0xb4, 0x30, 0xca, 0x36, 0xc2, 0x6c, + 0x46, 0xec, 0xfa, 0x6c, 0x54, 0x81, 0x71, 0x14, 0x96, 0xf6, 0x24, 0xe1, + 0x88, 0xad, 0x75, 0x40, 0xef, 0x5d, 0xf2, 0x6f, 0x8e, 0xfa, 0xcb, 0x82, + 0x0b, 0xd1, 0x7a, 0x1f, 0x61, 0x8a, 0xcb, 0x50, 0xc9, 0xbc, 0x19, 0x7d, + 0x4c, 0xb7, 0xcc, 0xac, 0x45, 0xd8, 0x24, 0xa3, 0xbf, 0x79, 0x5c, 0x23, + 0x4b, 0x55, 0x6b, 0x06, 0xae, 0xb9, 0x29, 0x17, 0x34, 0x53, 0x25, 0x20, + 0x84, 0x00, 0x3f, 0x69, 0xfe, 0x98, 0x04, 0x5f, 0xe7, 0x40, 0x02, 0xba, + 0x65, 0x8f, 0x93, 0x47, 0x56, 0x22, 0xf7, 0x67, 0x91, 0xd9, 0xb2, 0x62, + 0x3d, 0x1b, 0x5f, 0xff, 0x2c, 0xc1, 0x68, 0x44, 0x74, 0x6e, 0xfd, 0x2d, + 0x30, 0xa6, 0xa8, 0x13, 0x4b, 0xfc, 0x4c, 0x8c, 0xc8, 0x0a, 0x46, 0x10, + 0x79, 0x01, 0xfb, 0x97, 0x3c, 0x28, 0xfc, 0x55, 0x31, 0x30, 0xf3, 0x28, + 0x6c, 0x14, 0x89, 0xda +}; +/* K = 117a529e3fdfc79843a5a4c07539036b865214e014b4928c2a31f47bf62a4fdb */ +static const uint8_t ac_dsa_vect181_out[] = { +/* R */ + 0x63, 0x30, 0x55, 0xe0, 0x55, 0xf2, 0x37, 0xc3, 0x89, 0x99, 0xd8, 0x1c, + 0x39, 0x78, 0x48, 0xc3, 0x8c, 0xce, 0x80, 0xa5, 0x5b, 0x64, 0x9d, 0x9e, + 0x79, 0x05, 0xc2, 0x98, 0xe2, 0xa5, 0x14, 0x47, +/* S */ + 0x2b, 0xbf, 0x68, 0x31, 0x76, 0x60, 0xec, 0x1e, 0x4b, 0x15, 0x49, 0x15, + 0x02, 0x7b, 0x0b, 0xc0, 0x0e, 0xe1, 0x9c, 0xfc, 0x0b, 0xf7, 0x5d, 0x01, + 0x93, 0x05, 0x04, 0xf2, 0xce, 0x10, 0xa8, 0xb0 +}; +#define ac_dsa_vect182_prime ac_dsa_vect181_prime +#define ac_dsa_vect182_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect182_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect182_ptx[] = { +/* Msg */ + 0xa7, 0x33, 0xb3, 0xf5, 0x88, 0xd5, 0xac, 0x9b, 0x9d, 0x4f, 0xe2, 0xf8, + 0x04, 0xdf, 0x8c, 0x25, 0x64, 0x03, 0xa9, 0xf8, 0xee, 0xf6, 0xf1, 0x91, + 0xfc, 0x48, 0xe1, 0x26, 0x7f, 0xb5, 0xb4, 0xd5, 0x46, 0xba, 0x11, 0xe7, + 0x7b, 0x66, 0x78, 0x44, 0xe4, 0x89, 0xbf, 0x0d, 0x5f, 0x72, 0x99, 0x0a, + 0xeb, 0x06, 0x1d, 0x01, 0xcc, 0xd7, 0x94, 0x9a, 0x23, 0xde, 0xf7, 0x4a, + 0x80, 0x3b, 0x7d, 0x92, 0xd5, 0x1a, 0xbf, 0xad, 0xeb, 0x48, 0x85, 0xff, + 0xd8, 0xff, 0xd5, 0x8a, 0xb8, 0x75, 0x48, 0xa1, 0x5c, 0x08, 0x7a, 0x39, + 0xb8, 0x99, 0x3b, 0x2f, 0xa6, 0x4c, 0x9d, 0x31, 0xa5, 0x94, 0xee, 0xb7, + 0x51, 0x2d, 0xa1, 0x69, 0x55, 0x83, 0x43, 0x36, 0xa2, 0x34, 0x43, 0x5c, + 0x5a, 0x9d, 0x0d, 0xd9, 0xb1, 0x5a, 0x94, 0xe1, 0x16, 0x15, 0x4d, 0xea, + 0x63, 0xfd, 0xc8, 0xdd, 0x7a, 0x51, 0x21, 0x81 +}; +static const uint8_t ac_dsa_vect182_priv_val[] = { +/* X */ + 0x85, 0x3f, 0x75, 0xac, 0x81, 0xb3, 0xa8, 0x42, 0xc9, 0x99, 0x44, 0x85, + 0x62, 0xc5, 0x84, 0xd1, 0xcd, 0x02, 0x77, 0x89, 0x6e, 0xc2, 0xf9, 0x3c, + 0x05, 0xc3, 0x37, 0xee, 0xd4, 0x14, 0x36, 0x7a +}; +static const uint8_t ac_dsa_vect182_pub_val[] = { +/* Y */ + 0x35, 0x6e, 0xd4, 0x75, 0x37, 0xfb, 0xf0, 0x2c, 0xb3, 0x0a, 0x8c, 0xee, + 0x05, 0x37, 0xf3, 0x00, 0xdf, 0xf1, 0xd0, 0xc4, 0x67, 0x39, 0x9c, 0xe7, + 0x0b, 0x87, 0xa8, 0x75, 0x8d, 0x5e, 0xc9, 0xdd, 0x25, 0x62, 0x46, 0xfc, + 0xca, 0xeb, 0x9d, 0xfe, 0x10, 0x9f, 0x2a, 0x98, 0x4f, 0x2d, 0xda, 0xa8, + 0x7a, 0xad, 0x54, 0xce, 0x0d, 0x31, 0xf9, 0x07, 0xe5, 0x04, 0x52, 0x1b, + 0xaf, 0x42, 0x07, 0xd7, 0x07, 0x3b, 0x0a, 0x4a, 0x9f, 0xc6, 0x7d, 0x8d, + 0xdd, 0xa9, 0x9f, 0x87, 0xae, 0xd6, 0xe0, 0x36, 0x7c, 0xec, 0x27, 0xf9, + 0xc6, 0x08, 0xaf, 0x74, 0x3b, 0xf1, 0xee, 0x6e, 0x11, 0xd5, 0x5a, 0x18, + 0x2d, 0x43, 0xb0, 0x24, 0xac, 0xe5, 0x34, 0x02, 0x9b, 0x86, 0x6f, 0x64, + 0x22, 0x82, 0x8b, 0xb8, 0x1a, 0x39, 0xaa, 0xe9, 0x60, 0x1e, 0xe8, 0x1c, + 0x7f, 0x81, 0xdd, 0x35, 0x8e, 0x69, 0xf4, 0xe2, 0xed, 0xfa, 0x46, 0x54, + 0xd8, 0xa6, 0x5b, 0xc6, 0x43, 0x11, 0xdc, 0x86, 0xaa, 0xc4, 0xab, 0xc1, + 0xfc, 0x7a, 0x3f, 0x65, 0x15, 0x96, 0x61, 0xa0, 0xd8, 0xe2, 0x88, 0xeb, + 0x8d, 0x66, 0x5c, 0xb0, 0xad, 0xf5, 0xac, 0x3d, 0x6b, 0xa8, 0xe9, 0x45, + 0x3f, 0xac, 0xf7, 0x54, 0x23, 0x93, 0xae, 0x24, 0xfd, 0x50, 0x45, 0x1d, + 0x38, 0x28, 0x08, 0x65, 0x58, 0xf7, 0xec, 0x52, 0x8e, 0x28, 0x49, 0x35, + 0xa5, 0x3f, 0x67, 0xa1, 0xaa, 0x8e, 0x25, 0xd8, 0xad, 0x5c, 0x4a, 0xd5, + 0x5d, 0x83, 0xae, 0xf8, 0x83, 0xa4, 0xd9, 0xee, 0xb6, 0x29, 0x7e, 0x6a, + 0x53, 0xf6, 0x50, 0x49, 0xba, 0x9e, 0x2c, 0x6b, 0x79, 0x53, 0xa7, 0x60, + 0xbc, 0x1d, 0xc4, 0x6f, 0x78, 0xce, 0xaa, 0xa2, 0xc0, 0x2f, 0x53, 0x75, + 0xdd, 0x82, 0xe7, 0x08, 0x74, 0x4a, 0xa4, 0x0b, 0x15, 0x79, 0x9e, 0xb8, + 0x1d, 0x7e, 0x5b, 0x1a +}; +/* K = d41b335753e1ff3f828f57b797ff5b2db5cd79f6a1abeaa137a2a830e24ed4b5 */ +static const uint8_t ac_dsa_vect182_out[] = { +/* R */ + 0xbc, 0xd4, 0x90, 0x56, 0x8c, 0x0a, 0x89, 0xba, 0x31, 0x1b, 0xef, 0x88, + 0xea, 0x4f, 0x4b, 0x03, 0xd2, 0x73, 0xe7, 0x93, 0x72, 0x27, 0x22, 0x32, + 0x70, 0x95, 0xa3, 0x78, 0xdd, 0x6f, 0x35, 0x22, +/* S */ + 0x74, 0x49, 0x8f, 0xc4, 0x30, 0x91, 0xfc, 0xdd, 0x2d, 0x1e, 0xf0, 0x77, + 0x5f, 0x82, 0x86, 0x94, 0x5a, 0x01, 0xcd, 0x72, 0xb8, 0x05, 0x25, 0x6b, + 0x04, 0x51, 0xf9, 0xcb, 0xd9, 0x43, 0xcf, 0x82 +}; +#define ac_dsa_vect183_prime ac_dsa_vect181_prime +#define ac_dsa_vect183_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect183_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect183_ptx[] = { +/* Msg */ + 0xac, 0x30, 0xfb, 0x15, 0x51, 0x04, 0x95, 0x4b, 0x9d, 0x71, 0x39, 0xde, + 0x93, 0x46, 0xd5, 0x4c, 0xa0, 0x51, 0x78, 0x95, 0x40, 0x53, 0xfd, 0x36, + 0x1c, 0x97, 0x19, 0xce, 0xa5, 0x30, 0xd2, 0xd2, 0xe1, 0x73, 0x7f, 0xc4, + 0x6b, 0x0e, 0xe2, 0x73, 0x57, 0xce, 0xcb, 0xd4, 0x7e, 0x0f, 0xd4, 0x7a, + 0xda, 0x0d, 0x52, 0x36, 0xa9, 0xd7, 0x7d, 0xd6, 0x1a, 0x1b, 0x0d, 0xb5, + 0x2e, 0x62, 0x8b, 0x14, 0x58, 0x8f, 0xdb, 0xa8, 0x77, 0x48, 0x82, 0x86, + 0x6b, 0x04, 0xb4, 0x9c, 0xf5, 0x20, 0x5d, 0xb4, 0x94, 0x45, 0xa8, 0xa2, + 0x02, 0xa5, 0xfc, 0x3f, 0xcc, 0x36, 0xef, 0xe0, 0xbd, 0x0c, 0x1e, 0x51, + 0xeb, 0x08, 0x61, 0x6c, 0x4a, 0x7a, 0xfe, 0x12, 0x00, 0x77, 0xea, 0x08, + 0xca, 0xf1, 0x67, 0xe9, 0x04, 0x46, 0x86, 0x22, 0x98, 0x01, 0x1a, 0xd9, + 0xa1, 0xf1, 0x1c, 0xef, 0xb5, 0xf7, 0x43, 0x35 +}; +static const uint8_t ac_dsa_vect183_priv_val[] = { +/* X */ + 0xd6, 0x92, 0xd2, 0xc6, 0x53, 0xbf, 0xca, 0xb2, 0xe7, 0x49, 0x2e, 0xc5, + 0x6e, 0x51, 0x27, 0x24, 0xc9, 0x12, 0x22, 0x7d, 0x79, 0x3a, 0x59, 0x88, + 0x28, 0x00, 0xd3, 0x7a, 0xd2, 0x60, 0xbf, 0xd9 +}; +static const uint8_t ac_dsa_vect183_pub_val[] = { +/* Y */ + 0x84, 0x74, 0x1b, 0xef, 0x3d, 0x9f, 0x9d, 0xab, 0x0e, 0x3f, 0xae, 0x78, + 0x39, 0xd3, 0x9c, 0x1a, 0x19, 0x66, 0xab, 0x82, 0x79, 0x8d, 0x71, 0xaa, + 0x46, 0xb7, 0xde, 0xf4, 0x65, 0xe3, 0x9e, 0xa5, 0xe7, 0xad, 0xae, 0xed, + 0x2d, 0xfc, 0x92, 0xc9, 0xbe, 0xa7, 0x2d, 0x65, 0x26, 0x8b, 0x8d, 0xf9, + 0x55, 0xf9, 0xb7, 0xe7, 0xb6, 0x92, 0x3d, 0x2b, 0xf0, 0x0e, 0x7e, 0x43, + 0xf8, 0x3a, 0x0e, 0x54, 0xca, 0x94, 0x42, 0x75, 0xdc, 0x39, 0xc0, 0xfb, + 0x0c, 0x8a, 0x00, 0xcc, 0xd0, 0xb2, 0x9b, 0x79, 0x0d, 0x9d, 0x8f, 0x34, + 0x96, 0x05, 0x43, 0x90, 0x41, 0x0b, 0x4a, 0xe5, 0xc6, 0xea, 0xf2, 0xe2, + 0x1b, 0xdb, 0x52, 0x42, 0x11, 0x79, 0x97, 0x0f, 0xa1, 0x3e, 0x09, 0x48, + 0x28, 0x0a, 0x06, 0xa5, 0x76, 0xcd, 0xff, 0xae, 0x6f, 0xdb, 0x23, 0x9e, + 0xbd, 0x48, 0x6b, 0xf4, 0x69, 0x92, 0x70, 0xe2, 0xbc, 0x08, 0x79, 0xbe, + 0x25, 0xa6, 0xa0, 0xc2, 0xf7, 0x28, 0x0e, 0xa3, 0x3e, 0xeb, 0x32, 0xc5, + 0xd2, 0xea, 0x60, 0x93, 0x38, 0x1f, 0xc4, 0xc8, 0x3c, 0x8f, 0x9a, 0x59, + 0x1b, 0x0b, 0x0e, 0x72, 0xfc, 0xc1, 0x49, 0xc6, 0x85, 0xb0, 0x13, 0x81, + 0xa7, 0x4a, 0xf4, 0xcc, 0xb9, 0x02, 0xc0, 0x05, 0x0e, 0x05, 0xba, 0xf7, + 0x32, 0xba, 0xcd, 0x16, 0x06, 0x53, 0x3e, 0x2a, 0xcc, 0x63, 0x08, 0xc7, + 0x77, 0x20, 0x1e, 0xec, 0xdc, 0xdc, 0xbe, 0x93, 0x51, 0x49, 0xc4, 0xe5, + 0x72, 0xa1, 0x5a, 0x20, 0x5d, 0x2b, 0x80, 0xe7, 0x5e, 0xf2, 0x47, 0x31, + 0x60, 0xf8, 0x5e, 0x64, 0x2d, 0x28, 0x37, 0x0c, 0x0f, 0x19, 0x46, 0x41, + 0x25, 0xc6, 0x87, 0xc9, 0x69, 0x66, 0x5b, 0x13, 0xb0, 0x95, 0xaa, 0x87, + 0xba, 0x47, 0x68, 0x02, 0xd7, 0x2c, 0x35, 0x4e, 0xbc, 0xbc, 0xd8, 0x9f, + 0x28, 0xef, 0x00, 0x1c +}; +/* K = 39335e9193222c7ae3caf8e5ad77b751e9847c37b9016d355ac7520407c91e87 */ +static const uint8_t ac_dsa_vect183_out[] = { +/* R */ + 0x28, 0xc6, 0xbf, 0xca, 0xdb, 0x5f, 0x52, 0x32, 0x4e, 0x39, 0x90, 0x3b, + 0xf7, 0xa0, 0x4f, 0xae, 0xfb, 0x89, 0x38, 0x3f, 0x47, 0x3d, 0xaa, 0x43, + 0x2c, 0xab, 0x91, 0x78, 0xf2, 0x47, 0x0d, 0x3c, +/* S */ + 0x4e, 0x88, 0xf6, 0x5f, 0xf7, 0x76, 0x94, 0x0b, 0xaf, 0xbb, 0xfb, 0x35, + 0x64, 0x3b, 0xcd, 0xae, 0xb4, 0x3b, 0x25, 0xb4, 0x5d, 0xe2, 0xde, 0x3c, + 0x01, 0x1f, 0xf1, 0x44, 0x9c, 0x8b, 0x8b, 0x32 +}; +#define ac_dsa_vect184_prime ac_dsa_vect181_prime +#define ac_dsa_vect184_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect184_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect184_ptx[] = { +/* Msg */ + 0x22, 0x25, 0x03, 0x1f, 0xd2, 0x6a, 0x6b, 0xb4, 0xfd, 0x99, 0x90, 0x34, + 0x7b, 0xc2, 0xc8, 0xea, 0x4b, 0xa4, 0x5b, 0xd7, 0x5d, 0xf6, 0x84, 0x76, + 0xf9, 0x83, 0xdf, 0xfb, 0x55, 0x31, 0x89, 0x9f, 0x13, 0x17, 0xd9, 0x5f, + 0x7c, 0xbb, 0x49, 0x3d, 0xe4, 0x5c, 0xd2, 0xf1, 0x19, 0x04, 0xcd, 0x5c, + 0x5d, 0x5a, 0x74, 0x8b, 0x4a, 0xa1, 0x27, 0xca, 0x73, 0x0f, 0x89, 0xa9, + 0x28, 0xdd, 0xcd, 0x25, 0x0a, 0x65, 0x51, 0xc2, 0xf7, 0xcc, 0xe1, 0x09, + 0xe6, 0x4d, 0x3a, 0xb7, 0x4a, 0xfb, 0x2d, 0x4f, 0x4f, 0x7e, 0x34, 0x94, + 0xeb, 0x7d, 0x55, 0x70, 0x60, 0xa1, 0xf2, 0x9e, 0xcb, 0x5b, 0x75, 0xf6, + 0x48, 0x48, 0x37, 0x09, 0x02, 0xbd, 0x6a, 0xe2, 0xfb, 0xf6, 0x80, 0x2b, + 0x2f, 0x9c, 0x37, 0xf3, 0x48, 0x36, 0xad, 0x71, 0xdd, 0x2e, 0x2a, 0xbf, + 0x6a, 0x0a, 0x47, 0xdf, 0x4f, 0xd5, 0x57, 0x3d +}; +static const uint8_t ac_dsa_vect184_priv_val[] = { +/* X */ + 0x87, 0xbd, 0x74, 0xc5, 0xd7, 0x0a, 0x29, 0x29, 0x14, 0xd9, 0x6b, 0x47, + 0xdc, 0x5e, 0x9e, 0x97, 0xa6, 0x79, 0x9c, 0x3b, 0x78, 0x80, 0x14, 0xe7, + 0xf1, 0x06, 0xce, 0x7c, 0xe7, 0xe1, 0x7a, 0x95 +}; +static const uint8_t ac_dsa_vect184_pub_val[] = { +/* Y */ + 0x04, 0x96, 0x4c, 0x09, 0x3f, 0xdb, 0x85, 0x2c, 0x97, 0xb1, 0x65, 0xe1, + 0x79, 0xf7, 0xef, 0x3b, 0x39, 0x35, 0x0c, 0x25, 0x88, 0xe6, 0x0a, 0x01, + 0x77, 0xbc, 0x2e, 0x89, 0x0a, 0xb0, 0x8f, 0xfd, 0x73, 0xd8, 0xa5, 0xa6, + 0x69, 0x2c, 0xfe, 0xbd, 0x0c, 0x91, 0x2d, 0xe2, 0xd5, 0x0b, 0xf0, 0x21, + 0x39, 0xbf, 0x01, 0x7e, 0xc7, 0x15, 0xc2, 0xdd, 0x7b, 0xe1, 0xaa, 0xd9, + 0xd0, 0xb9, 0x6c, 0x47, 0xd6, 0x46, 0x5d, 0x4e, 0xb0, 0xea, 0x02, 0x47, + 0xff, 0x65, 0x59, 0x59, 0xd9, 0x4a, 0x34, 0x09, 0xe9, 0xf9, 0x26, 0x2d, + 0x87, 0x70, 0x75, 0xf6, 0xf0, 0xc7, 0x78, 0x3a, 0x8d, 0xf3, 0xcc, 0x11, + 0x5c, 0x52, 0x87, 0xc6, 0x9b, 0xdb, 0xf0, 0xff, 0xe0, 0xed, 0x37, 0x19, + 0xe4, 0x18, 0xff, 0x99, 0xb5, 0xdc, 0xd5, 0xf0, 0xcf, 0xc1, 0x06, 0x5e, + 0x40, 0x4a, 0x21, 0x6e, 0x09, 0x50, 0x86, 0xa6, 0xe2, 0x19, 0x7a, 0x69, + 0xc4, 0x77, 0x74, 0x37, 0x72, 0x03, 0xd9, 0x9a, 0x23, 0x4e, 0x7b, 0xe6, + 0x1c, 0xc4, 0xa9, 0x5a, 0x80, 0x9f, 0x9b, 0x9d, 0xd0, 0xa5, 0x50, 0xb7, + 0x12, 0xbc, 0xe5, 0xd1, 0xcf, 0xda, 0xfd, 0xa2, 0x32, 0xd7, 0xc8, 0x31, + 0xec, 0x52, 0x88, 0x47, 0x01, 0x15, 0x5a, 0x3d, 0xf2, 0xb0, 0x86, 0xbe, + 0x87, 0x0a, 0xf8, 0xe8, 0x75, 0x55, 0x75, 0x18, 0xb0, 0x35, 0xc8, 0x49, + 0x57, 0xc1, 0x74, 0x2b, 0x8c, 0x02, 0xb0, 0xd4, 0x6b, 0x64, 0xa7, 0x73, + 0x01, 0x28, 0x09, 0xbf, 0xa4, 0xc5, 0x40, 0x7c, 0x3f, 0xbf, 0xed, 0x3b, + 0x96, 0x08, 0x16, 0x60, 0x4c, 0xf4, 0x2b, 0x2d, 0xef, 0xb4, 0xfe, 0xea, + 0xbc, 0x17, 0x2a, 0xfb, 0xfc, 0xbc, 0x82, 0x83, 0x6b, 0x44, 0xb9, 0x27, + 0xe0, 0xcd, 0x4c, 0xa6, 0x3a, 0x1d, 0xae, 0xb3, 0xee, 0xb3, 0x0d, 0x1d, + 0xe6, 0x08, 0x12, 0x7b +}; +/* K = 64f504110193cc4a3f400b6fcfd71d64a1e166c048829d23206da12a7dc1423a */ +static const uint8_t ac_dsa_vect184_out[] = { +/* R */ + 0x55, 0x68, 0xd8, 0x10, 0xba, 0x66, 0x4a, 0x08, 0xb3, 0x01, 0x26, 0x6d, + 0x08, 0xc6, 0x9e, 0xac, 0xcc, 0xec, 0x5a, 0xae, 0x87, 0x0a, 0x6d, 0x57, + 0x9e, 0xda, 0x51, 0xa3, 0x1b, 0x18, 0x46, 0x55, +/* S */ + 0x9e, 0x81, 0x88, 0x68, 0xe0, 0x67, 0x87, 0xfb, 0x95, 0x19, 0xb5, 0x05, + 0x46, 0xee, 0x21, 0xd0, 0x54, 0x6e, 0x16, 0xbb, 0x1b, 0x59, 0x20, 0x31, + 0x1b, 0xa4, 0x47, 0x69, 0xdc, 0x69, 0xc7, 0xa6 +}; +#define ac_dsa_vect185_prime ac_dsa_vect181_prime +#define ac_dsa_vect185_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect185_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect185_ptx[] = { +/* Msg */ + 0x4b, 0x1f, 0x93, 0x35, 0xfd, 0xfe, 0x88, 0xc0, 0x86, 0x6b, 0xb6, 0x48, + 0xc0, 0x58, 0x57, 0xb7, 0x9c, 0x2f, 0xda, 0x92, 0xa9, 0x87, 0xb3, 0x59, + 0x28, 0x2b, 0xbf, 0x08, 0x22, 0xdb, 0x74, 0x7a, 0x39, 0x40, 0xfe, 0xe0, + 0x5a, 0xeb, 0x3c, 0xc0, 0x81, 0x23, 0x1e, 0x29, 0xb9, 0xd4, 0x60, 0xef, + 0x30, 0xa5, 0x5f, 0x0f, 0x88, 0x70, 0x2a, 0x4e, 0xcd, 0xcb, 0x84, 0x2b, + 0xee, 0xb3, 0x6a, 0x97, 0x61, 0x36, 0xc9, 0x24, 0x1f, 0x2e, 0xb5, 0xc2, + 0xd9, 0x3f, 0xe3, 0x8a, 0x15, 0x80, 0xcd, 0x58, 0xfb, 0x93, 0xed, 0x13, + 0x7a, 0x7d, 0x05, 0xea, 0x22, 0xd5, 0xe8, 0x73, 0x45, 0x63, 0x3a, 0x0e, + 0x39, 0x3f, 0xee, 0xa6, 0x16, 0xea, 0xf8, 0x36, 0x84, 0xc3, 0xba, 0xca, + 0x4f, 0xc5, 0xbf, 0x80, 0xa8, 0x7d, 0xbe, 0xc3, 0xa9, 0x78, 0x7d, 0xac, + 0xce, 0xc4, 0x79, 0x66, 0x1a, 0xf0, 0xb9, 0x68 +}; +static const uint8_t ac_dsa_vect185_priv_val[] = { +/* X */ + 0xaf, 0xa0, 0x80, 0x28, 0x78, 0x98, 0xb0, 0x78, 0x7f, 0x5d, 0x06, 0xd5, + 0x82, 0x6c, 0xc2, 0x85, 0xae, 0x5b, 0xee, 0x41, 0x76, 0x80, 0x98, 0x75, + 0x04, 0x19, 0xa5, 0xc8, 0x86, 0x3a, 0xe7, 0x29 +}; +static const uint8_t ac_dsa_vect185_pub_val[] = { +/* Y */ + 0x57, 0x76, 0x7c, 0x34, 0x8a, 0xb0, 0xc6, 0x1e, 0xab, 0x4f, 0x2e, 0x08, + 0x94, 0xbb, 0x62, 0x23, 0x64, 0x5a, 0x33, 0x1c, 0x5b, 0xe2, 0x49, 0x0d, + 0x76, 0x48, 0x39, 0xfa, 0x4d, 0xac, 0x81, 0x4e, 0x05, 0xe7, 0x09, 0x25, + 0xd7, 0x20, 0xd0, 0xe0, 0xab, 0x5f, 0xaa, 0x3d, 0xb6, 0xdc, 0x58, 0xba, + 0x57, 0x3b, 0x4e, 0x0b, 0x7b, 0xc1, 0x3e, 0x4c, 0x04, 0x4b, 0x96, 0x25, + 0x93, 0x85, 0xfc, 0xd1, 0xea, 0xde, 0x0d, 0x7c, 0x51, 0x74, 0x49, 0x8c, + 0x70, 0xba, 0x8f, 0xb8, 0x66, 0x1e, 0xd5, 0x24, 0xfa, 0x81, 0x71, 0x57, + 0x0f, 0xd5, 0x2f, 0xaa, 0xc9, 0x91, 0x5d, 0x94, 0x7b, 0x51, 0xf6, 0xcf, + 0x5b, 0x74, 0xe3, 0xed, 0xfa, 0x06, 0x4a, 0x51, 0x61, 0xc7, 0x62, 0x3e, + 0xc6, 0xe8, 0x0d, 0x29, 0x96, 0x0b, 0x57, 0x3f, 0xb9, 0x8d, 0xe9, 0xe7, + 0x10, 0xc5, 0x6e, 0xe4, 0x5a, 0xab, 0xc4, 0x02, 0x23, 0x57, 0xf6, 0xc3, + 0x71, 0x29, 0x62, 0xad, 0x19, 0xe4, 0x3a, 0x41, 0x48, 0x95, 0x7c, 0xc6, + 0xb9, 0xc8, 0xf6, 0x91, 0x87, 0x7a, 0x59, 0xf4, 0x31, 0x62, 0xd8, 0xf9, + 0x8f, 0x24, 0x72, 0x69, 0x9e, 0xa5, 0x10, 0x10, 0x93, 0x05, 0xf8, 0xf9, + 0x8a, 0xa3, 0xf3, 0xf3, 0x1e, 0x43, 0x02, 0xeb, 0x05, 0xe5, 0xf1, 0xa4, + 0x62, 0xd0, 0xf3, 0xbf, 0xdc, 0xd0, 0xc8, 0x4e, 0x76, 0xbf, 0xdd, 0x14, + 0xb7, 0xc9, 0x0b, 0x98, 0x2b, 0x8c, 0x0e, 0xc7, 0xc7, 0x8c, 0xf3, 0xe6, + 0xc2, 0x16, 0xed, 0x1d, 0x20, 0xb5, 0x2a, 0x13, 0x2f, 0x53, 0xc9, 0x74, + 0x7c, 0x7f, 0xbe, 0x39, 0x09, 0x2d, 0x5c, 0xcf, 0xcc, 0x01, 0xa1, 0x19, + 0xc9, 0x2f, 0xaa, 0x3f, 0x13, 0xd4, 0x64, 0x3e, 0x5d, 0xb2, 0x2c, 0xa1, + 0x68, 0x1d, 0x65, 0x36, 0xbc, 0x7b, 0x70, 0x4b, 0xb0, 0x9b, 0xf6, 0xc6, + 0x21, 0xc2, 0xff, 0x06 +}; +/* K = d23656910f6e8ea72cdb979cfd8c8f6676c47c6161c3aa14f2338392891d1afe */ +static const uint8_t ac_dsa_vect185_out[] = { +/* R */ + 0x7a, 0xc9, 0x5d, 0x3e, 0x09, 0x36, 0xcd, 0xe4, 0x41, 0xe4, 0xa2, 0x90, + 0x71, 0x1c, 0xc0, 0x44, 0xe6, 0xe9, 0x8e, 0x8a, 0x8d, 0xe6, 0x82, 0x98, + 0xbf, 0x7f, 0xb9, 0x0e, 0xef, 0x58, 0x9e, 0xb2, +/* S */ + 0x14, 0x0e, 0x9d, 0xe3, 0x7e, 0xc5, 0xae, 0xb3, 0xfb, 0x79, 0x5b, 0x01, + 0x6f, 0x51, 0xea, 0x3e, 0x92, 0xd6, 0xf1, 0x98, 0xc5, 0xa0, 0xe5, 0xa5, + 0xd2, 0x36, 0x67, 0x1c, 0x91, 0x04, 0x2c, 0x94 +}; +#define ac_dsa_vect186_prime ac_dsa_vect181_prime +#define ac_dsa_vect186_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect186_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect186_ptx[] = { +/* Msg */ + 0x3b, 0x87, 0x10, 0x9b, 0xf2, 0x15, 0x71, 0xfc, 0xfa, 0xe9, 0x2b, 0x85, + 0x96, 0x49, 0xbf, 0x37, 0xdd, 0x23, 0xd5, 0x9f, 0x76, 0xd5, 0x0c, 0xf2, + 0x6f, 0x4b, 0x2e, 0xbf, 0x7c, 0x5f, 0x4a, 0xe0, 0xb3, 0x77, 0xbf, 0x3b, + 0xf2, 0xc7, 0xe0, 0x15, 0xa7, 0x4e, 0xfc, 0x80, 0x84, 0x33, 0x04, 0x7a, + 0x71, 0xbf, 0x1e, 0xd4, 0xba, 0x90, 0x25, 0xf4, 0x56, 0x1d, 0xcb, 0x94, + 0xbe, 0xf2, 0xc2, 0xa2, 0xc9, 0x4b, 0x3f, 0x55, 0xed, 0x61, 0x1c, 0x43, + 0x2f, 0x98, 0xa6, 0x83, 0xab, 0xad, 0xc2, 0xc3, 0x1d, 0x00, 0x2e, 0xac, + 0xa9, 0xb0, 0x70, 0xf2, 0xb2, 0x13, 0x19, 0xd0, 0x72, 0xdf, 0x75, 0xc6, + 0x23, 0x85, 0xd7, 0xd0, 0x28, 0x97, 0xa0, 0x0f, 0x86, 0x3c, 0x28, 0x82, + 0xb2, 0x89, 0x7a, 0x33, 0x13, 0x32, 0xbb, 0x95, 0x68, 0xb2, 0xfd, 0xfa, + 0xcc, 0xf5, 0x0b, 0x3d, 0xe4, 0xb4, 0x2e, 0x8a +}; +static const uint8_t ac_dsa_vect186_priv_val[] = { +/* X */ + 0x66, 0x86, 0x06, 0xf4, 0xa8, 0x2b, 0x50, 0x87, 0x6a, 0xbd, 0x7f, 0x3d, + 0xc0, 0xed, 0x58, 0x0a, 0x10, 0x34, 0x4c, 0x1d, 0xd0, 0x92, 0xc5, 0xbc, + 0x1b, 0x26, 0xc4, 0x27, 0x02, 0x8c, 0xc5, 0xf3 +}; +static const uint8_t ac_dsa_vect186_pub_val[] = { +/* Y */ + 0x7c, 0x16, 0xa9, 0x64, 0x4c, 0x18, 0x25, 0x79, 0x11, 0xb8, 0x26, 0xda, + 0x10, 0xb5, 0xb1, 0x01, 0x15, 0xff, 0x77, 0x67, 0x5b, 0xdc, 0x3c, 0x9f, + 0x77, 0x09, 0x71, 0x62, 0xfc, 0x05, 0x9e, 0x86, 0xb0, 0x4c, 0x1f, 0xae, + 0xed, 0x3c, 0x66, 0x30, 0x6c, 0x7e, 0x5f, 0xe2, 0xd5, 0xc6, 0x3e, 0x8f, + 0xa5, 0xfa, 0x2b, 0x82, 0x56, 0x5a, 0xc6, 0x06, 0x54, 0x45, 0xde, 0x58, + 0x19, 0xa2, 0xe4, 0xa5, 0x69, 0x25, 0xbd, 0xcc, 0xe1, 0x38, 0x65, 0x4d, + 0xfb, 0x49, 0x0a, 0xc6, 0x24, 0xa3, 0x8a, 0xd6, 0x58, 0x49, 0xbe, 0x4b, + 0xa7, 0x4d, 0x14, 0xc8, 0x29, 0xef, 0x10, 0x22, 0x48, 0xa1, 0x81, 0x93, + 0x93, 0x33, 0x35, 0xea, 0xf0, 0xc7, 0x3b, 0x7b, 0xfe, 0x77, 0xd6, 0x69, + 0xf8, 0x57, 0xef, 0x3a, 0xdd, 0xb1, 0xf4, 0xca, 0x42, 0x4d, 0xbf, 0xde, + 0xdb, 0x9e, 0x2d, 0xe1, 0xfc, 0x0c, 0xc2, 0xd9, 0x77, 0x7e, 0xe8, 0x34, + 0xa0, 0xac, 0x7d, 0x0c, 0xac, 0x1b, 0x2a, 0x61, 0x38, 0x90, 0x07, 0x14, + 0x90, 0xef, 0xe5, 0xcb, 0x20, 0x97, 0xac, 0x83, 0x0f, 0xbc, 0x27, 0x88, + 0x1f, 0x9f, 0xa5, 0x1d, 0x3b, 0x02, 0x47, 0xc5, 0xe1, 0xb7, 0xf6, 0xbe, + 0x13, 0xc3, 0x0d, 0xd3, 0x1c, 0x2c, 0x59, 0xb7, 0x68, 0x3c, 0xe6, 0x0a, + 0x0e, 0xbd, 0x66, 0x63, 0xde, 0x97, 0x87, 0x0a, 0xf2, 0xdd, 0x17, 0xd9, + 0x14, 0x31, 0x32, 0x3a, 0x46, 0x86, 0xbf, 0x32, 0xe1, 0xe3, 0x97, 0x32, + 0xda, 0xe1, 0x30, 0x0c, 0x57, 0xbd, 0x60, 0x0b, 0xe7, 0x90, 0x59, 0x3b, + 0x2e, 0xfa, 0x04, 0x5b, 0xbf, 0xca, 0x95, 0x67, 0x68, 0x15, 0x7b, 0x47, + 0x24, 0xca, 0x0a, 0x14, 0x72, 0xfe, 0x6c, 0x8d, 0xcd, 0x82, 0xa3, 0x80, + 0x24, 0x76, 0x63, 0x41, 0xd1, 0xf5, 0x48, 0xad, 0x8f, 0x36, 0xdc, 0x67, + 0x66, 0x76, 0xfb, 0xe3 +}; +/* K = a3d781e5385d66989b38034171da11594b20f15733fd4701a63cf24bb58ec341 */ +static const uint8_t ac_dsa_vect186_out[] = { +/* R */ + 0x1e, 0x21, 0x9e, 0xef, 0xd6, 0x16, 0xca, 0xac, 0x54, 0x9a, 0x85, 0x9d, + 0x45, 0x18, 0x6b, 0x5c, 0x52, 0x86, 0x27, 0x57, 0x39, 0x58, 0xfe, 0x55, + 0xcf, 0x57, 0xfb, 0xbd, 0x16, 0x61, 0xf7, 0xb8, +/* S */ + 0xb0, 0x95, 0x45, 0x84, 0x3d, 0xc0, 0xf6, 0x29, 0x9b, 0x48, 0xf1, 0x43, + 0x11, 0x50, 0x36, 0x05, 0x50, 0x28, 0x68, 0x85, 0x9e, 0x8c, 0x43, 0x86, + 0x7f, 0x80, 0xdf, 0x3c, 0x23, 0x91, 0xc7, 0x62 +}; +#define ac_dsa_vect187_prime ac_dsa_vect181_prime +#define ac_dsa_vect187_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect187_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect187_ptx[] = { +/* Msg */ + 0x04, 0x23, 0x65, 0xb1, 0x25, 0x69, 0x31, 0xa1, 0x11, 0xfa, 0xcc, 0x6c, + 0x40, 0xf6, 0x18, 0xc4, 0x28, 0x80, 0x1b, 0x03, 0xe4, 0xf2, 0x22, 0xa1, + 0xe1, 0xb7, 0x76, 0x3c, 0x3b, 0x02, 0xa6, 0x21, 0x4e, 0x4c, 0x51, 0x7b, + 0xeb, 0x58, 0x7a, 0x4e, 0xa6, 0x9f, 0xdb, 0xd4, 0xea, 0x2d, 0x5d, 0x5f, + 0x45, 0xaf, 0xde, 0xd9, 0x6d, 0xda, 0xc8, 0x7d, 0xc8, 0x99, 0x55, 0x61, + 0x3a, 0xef, 0xf7, 0x64, 0x4f, 0xc6, 0xa5, 0x8b, 0xb8, 0x59, 0xa8, 0x52, + 0x21, 0x31, 0x8f, 0xbc, 0x5e, 0x17, 0x5c, 0x69, 0x85, 0xb1, 0x9a, 0x1d, + 0x16, 0xab, 0x6a, 0xd3, 0xca, 0x8f, 0xa1, 0x90, 0x3a, 0xcc, 0xa4, 0x2b, + 0xc6, 0xd9, 0xef, 0xbe, 0x88, 0xfd, 0x6f, 0x2a, 0x86, 0x50, 0x42, 0x5b, + 0xe9, 0x7b, 0xab, 0x9c, 0xb6, 0x70, 0xb2, 0xe3, 0x9f, 0x36, 0xd5, 0x26, + 0x27, 0x8e, 0x0b, 0xcf, 0xcb, 0xff, 0xc3, 0xc6 +}; +static const uint8_t ac_dsa_vect187_priv_val[] = { +/* X */ + 0x1c, 0x08, 0x57, 0x0d, 0x1e, 0x1a, 0xc0, 0x85, 0x7f, 0x64, 0x9e, 0x4b, + 0xa2, 0x0d, 0xe0, 0xe9, 0xac, 0xa9, 0x73, 0x74, 0xac, 0xba, 0x6b, 0xae, + 0x35, 0x01, 0x04, 0xf1, 0xfc, 0xe2, 0x0b, 0xe0 +}; +static const uint8_t ac_dsa_vect187_pub_val[] = { +/* Y */ + 0x81, 0x54, 0x11, 0xac, 0x6a, 0xa1, 0xb4, 0x95, 0xc4, 0xba, 0xc8, 0x02, + 0x80, 0x6a, 0x1a, 0x35, 0x92, 0x92, 0x4f, 0xd9, 0xc0, 0xa3, 0xcc, 0xa4, + 0x1e, 0x07, 0x6d, 0xb2, 0x93, 0xd8, 0x15, 0xc2, 0xf2, 0xb0, 0xa5, 0x3e, + 0x97, 0xcf, 0x65, 0x7c, 0x89, 0x51, 0xb8, 0x56, 0xcc, 0xa1, 0x16, 0x6a, + 0xd4, 0x33, 0xbe, 0x58, 0x29, 0xb0, 0xb6, 0x36, 0xca, 0x9d, 0xe4, 0x91, + 0x11, 0xce, 0x5c, 0xec, 0xce, 0xde, 0xdf, 0x36, 0xd7, 0x95, 0xed, 0xef, + 0xef, 0xee, 0x1d, 0x55, 0x32, 0x50, 0xfb, 0xcd, 0x5b, 0xd0, 0x5b, 0x4d, + 0x99, 0xde, 0x55, 0xf1, 0x47, 0x77, 0x3a, 0xb3, 0xa0, 0xf7, 0x54, 0xd0, + 0x90, 0xca, 0x7b, 0x6f, 0xf7, 0x5c, 0x16, 0x0e, 0xef, 0xd1, 0x70, 0x9a, + 0x5d, 0xf3, 0xcd, 0x8a, 0x0c, 0xae, 0x3e, 0x34, 0x1f, 0x22, 0x75, 0xfa, + 0xae, 0xe3, 0xe3, 0xe3, 0x17, 0x37, 0xe7, 0xe9, 0xc7, 0xe7, 0x48, 0x45, + 0x65, 0x1f, 0x4f, 0x83, 0x9c, 0x9d, 0x08, 0xda, 0x6b, 0xfd, 0x00, 0xf2, + 0xc2, 0xb9, 0xc6, 0xed, 0x9a, 0xcb, 0x78, 0xd1, 0x11, 0x75, 0xfa, 0x6d, + 0xed, 0x7a, 0xb9, 0x5d, 0xbb, 0x2b, 0xfe, 0xf1, 0x8f, 0xeb, 0x14, 0x9b, + 0xc9, 0x4f, 0x6d, 0xe0, 0x5a, 0x20, 0x52, 0x21, 0xba, 0x04, 0x06, 0xc9, + 0x6f, 0x63, 0x97, 0x2a, 0xef, 0xec, 0x1b, 0xee, 0xf0, 0x30, 0x13, 0x70, + 0x11, 0xe6, 0x79, 0x6a, 0xf2, 0xe4, 0xeb, 0xaa, 0x10, 0x01, 0x50, 0xd5, + 0x8c, 0xaf, 0x40, 0x82, 0x17, 0xac, 0xb1, 0x18, 0x3a, 0x1a, 0x46, 0xe0, + 0x63, 0x68, 0xcf, 0xf6, 0xfd, 0x74, 0x4d, 0xa7, 0x01, 0x9e, 0x7c, 0xa1, + 0x09, 0xac, 0xf1, 0x24, 0x4a, 0x76, 0x3c, 0xc2, 0xb2, 0x18, 0x6f, 0x49, + 0x27, 0x2b, 0xa3, 0xae, 0x04, 0x25, 0xf2, 0xeb, 0xcd, 0x30, 0xe7, 0x7e, + 0x9f, 0x7c, 0x95, 0x7a +}; +/* K = 0bc8f6e0b01bcb55a4d134c967f3a9411737103d400a33a968f9036292d6e3bd */ +static const uint8_t ac_dsa_vect187_out[] = { +/* R */ + 0xe7, 0x14, 0x5c, 0x70, 0xe0, 0x03, 0x8a, 0xe7, 0xe7, 0xd9, 0x01, 0xb4, + 0x88, 0x28, 0xb0, 0xb8, 0xbc, 0x96, 0x0c, 0xc4, 0xfa, 0x29, 0xa5, 0x2e, + 0x11, 0xff, 0xc9, 0xab, 0x08, 0xee, 0xe7, 0x26, +/* S */ + 0xb9, 0xc5, 0x4e, 0xf6, 0xcb, 0x3e, 0x1b, 0x04, 0x98, 0x95, 0x22, 0x99, + 0xd1, 0x46, 0x5e, 0xd2, 0xc5, 0xd4, 0xe6, 0x70, 0xcd, 0xfd, 0x25, 0x06, + 0x46, 0x24, 0x66, 0xc3, 0xb0, 0xfc, 0xc5, 0x38 +}; +#define ac_dsa_vect188_prime ac_dsa_vect181_prime +#define ac_dsa_vect188_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect188_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect188_ptx[] = { +/* Msg */ + 0x98, 0xff, 0xb2, 0x89, 0x9f, 0x17, 0xc8, 0x0a, 0x83, 0xe8, 0x2c, 0xa6, + 0x26, 0x5e, 0x6f, 0x36, 0x17, 0x33, 0xa6, 0xbb, 0xc6, 0x3c, 0xdf, 0x88, + 0x80, 0xdc, 0x75, 0x6b, 0xc7, 0x68, 0xb3, 0x5b, 0x90, 0xdb, 0x73, 0x90, + 0xcf, 0xff, 0x74, 0x5e, 0xc1, 0xb5, 0x6f, 0x16, 0x55, 0xd8, 0xd9, 0xa2, + 0x9a, 0x6e, 0x8a, 0x63, 0xbe, 0x0b, 0x1b, 0x2f, 0x9a, 0xa7, 0x43, 0x62, + 0x09, 0xa1, 0xfa, 0x06, 0x1a, 0x7a, 0xec, 0x28, 0x62, 0x2c, 0x47, 0x2b, + 0x3d, 0x02, 0x85, 0xa7, 0x01, 0x65, 0x5a, 0x49, 0x65, 0x46, 0xe8, 0x91, + 0xa8, 0xab, 0x29, 0xd9, 0xf4, 0x0d, 0x2e, 0x74, 0x8d, 0x0a, 0xa2, 0xba, + 0xbc, 0x06, 0xcf, 0xca, 0x64, 0x1b, 0x30, 0x0b, 0x7a, 0x21, 0x9c, 0xaa, + 0x9e, 0x5b, 0xae, 0x3b, 0xf6, 0x89, 0xf6, 0x05, 0x67, 0xf9, 0x22, 0xe7, + 0x79, 0x6f, 0xe4, 0x7b, 0xb7, 0x2f, 0xfb, 0x64 +}; +static const uint8_t ac_dsa_vect188_priv_val[] = { +/* X */ + 0x79, 0x88, 0x5f, 0xf1, 0x12, 0xbd, 0xb3, 0x26, 0x57, 0x7a, 0xbf, 0x52, + 0xdb, 0x67, 0x78, 0x47, 0x68, 0x74, 0x2b, 0x36, 0xe5, 0x75, 0xf0, 0x6b, + 0x8d, 0x1e, 0x4f, 0x0d, 0x2d, 0x49, 0xa3, 0xa3 +}; +static const uint8_t ac_dsa_vect188_pub_val[] = { +/* Y */ + 0x14, 0x11, 0x1d, 0xca, 0x30, 0xc0, 0x13, 0x87, 0x61, 0xfd, 0x2f, 0x55, + 0x97, 0x2b, 0x98, 0x46, 0x04, 0x1e, 0x5c, 0xa8, 0xb9, 0xbc, 0x6b, 0x2d, + 0xc8, 0x20, 0xf2, 0xa2, 0xf5, 0x10, 0x0a, 0xba, 0xab, 0x33, 0x7c, 0x7e, + 0x0d, 0x1b, 0xc5, 0x9d, 0xe5, 0xae, 0x58, 0x6b, 0xbd, 0xcf, 0x4d, 0x4b, + 0x14, 0xaa, 0x23, 0xbe, 0x40, 0x09, 0x52, 0x93, 0x12, 0x3b, 0xad, 0xbb, + 0x11, 0x91, 0x9b, 0x78, 0xcd, 0x64, 0x12, 0x54, 0x8d, 0x9f, 0x9d, 0x15, + 0xf6, 0x14, 0xb6, 0x92, 0x87, 0x13, 0x34, 0x41, 0x48, 0xfd, 0x7d, 0x30, + 0x98, 0x5f, 0xd2, 0xc5, 0x09, 0xb4, 0x4d, 0x39, 0x6c, 0x56, 0x72, 0xa0, + 0x82, 0xde, 0x41, 0x83, 0xfe, 0xe0, 0x3e, 0x45, 0xa9, 0x0e, 0xef, 0x6a, + 0x08, 0xb0, 0xd9, 0xd4, 0x71, 0x32, 0xc8, 0x2a, 0x2c, 0xcf, 0xef, 0x05, + 0xe2, 0xad, 0x0f, 0x34, 0x0d, 0xcc, 0x06, 0xd9, 0xe2, 0xe9, 0x79, 0xec, + 0xc4, 0x38, 0x44, 0xc6, 0x05, 0x4e, 0x4f, 0xa5, 0xfb, 0x8a, 0x73, 0xa1, + 0xe3, 0x87, 0x3f, 0x21, 0x45, 0xb0, 0xfd, 0x40, 0xf3, 0xec, 0x79, 0x46, + 0xf1, 0xf4, 0x3d, 0xe8, 0xb8, 0x05, 0x7c, 0x1b, 0xe5, 0xbf, 0x04, 0x63, + 0x0a, 0x12, 0x45, 0x3d, 0x62, 0x3c, 0x9b, 0x8d, 0x9f, 0x0e, 0x30, 0xc8, + 0x8c, 0x30, 0x43, 0x42, 0x15, 0xd4, 0x8f, 0x77, 0x34, 0x8e, 0x6b, 0x04, + 0x7f, 0x16, 0x93, 0x4e, 0xa0, 0x97, 0x43, 0xdd, 0x3b, 0x00, 0x9c, 0xeb, + 0xc4, 0x9d, 0xbc, 0x3a, 0x3d, 0x35, 0x67, 0xc3, 0x32, 0x15, 0x55, 0xec, + 0x96, 0xb2, 0x16, 0x0c, 0xaf, 0x78, 0x70, 0x97, 0x0a, 0xc3, 0xcd, 0x82, + 0x94, 0x47, 0x7a, 0x06, 0x43, 0xad, 0x52, 0xc2, 0x3d, 0x9d, 0x98, 0x7d, + 0xbf, 0xff, 0x64, 0xae, 0xd1, 0xa8, 0x83, 0xc3, 0x0a, 0x49, 0xf1, 0x4f, + 0xf0, 0x62, 0x00, 0x95 +}; +/* K = 13ab2945ab2a40067a93ed8c1a4b305182cb070022b79a56740238e55b07e8a2 */ +static const uint8_t ac_dsa_vect188_out[] = { +/* R */ + 0x45, 0x51, 0xb0, 0x96, 0x44, 0x6d, 0xb6, 0x76, 0x1b, 0x70, 0x8f, 0x35, + 0x20, 0x9e, 0xdb, 0x91, 0xcc, 0x51, 0xee, 0x4e, 0xf9, 0x6a, 0x74, 0x95, + 0x40, 0x7a, 0xb4, 0x16, 0x7a, 0x05, 0xc7, 0x91, +/* S */ + 0xcf, 0xe4, 0xc5, 0x8b, 0xdb, 0xf6, 0x1c, 0xaf, 0x09, 0xa4, 0x2a, 0xdb, + 0x1a, 0xa5, 0xd9, 0x8b, 0x4c, 0x45, 0x9c, 0x01, 0x12, 0xc5, 0x78, 0x23, + 0xbc, 0x15, 0xb5, 0xb9, 0x90, 0xd9, 0x2f, 0xf1 +}; +#define ac_dsa_vect189_prime ac_dsa_vect181_prime +#define ac_dsa_vect189_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect189_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect189_ptx[] = { +/* Msg */ + 0x58, 0x98, 0xcc, 0x0b, 0x42, 0x2b, 0xb8, 0x9f, 0x06, 0x6d, 0xab, 0xbd, + 0x30, 0xf5, 0x9e, 0x9a, 0x35, 0xa3, 0x92, 0xbd, 0xd7, 0xad, 0x31, 0x5e, + 0xc8, 0xad, 0x32, 0xb8, 0xf0, 0xf3, 0xd0, 0x28, 0x64, 0xe7, 0x0e, 0xa3, + 0x6e, 0x90, 0x76, 0xc3, 0x95, 0xf0, 0xba, 0x9d, 0xe1, 0xab, 0x60, 0x80, + 0xdf, 0x3c, 0xf4, 0xa1, 0x47, 0x0e, 0x2b, 0x99, 0x90, 0xb8, 0xe7, 0x61, + 0x4b, 0xb8, 0x31, 0x2b, 0x07, 0x5c, 0x0b, 0x2a, 0x13, 0x2d, 0x7e, 0x47, + 0xde, 0xd9, 0xe4, 0xc0, 0xa1, 0x36, 0x84, 0x55, 0xb9, 0xd1, 0xa6, 0x7b, + 0xc4, 0x4a, 0xf2, 0xf3, 0x74, 0x28, 0xf4, 0x8f, 0x7e, 0x08, 0x9a, 0xb4, + 0x1d, 0x04, 0x63, 0x78, 0xb6, 0xd4, 0x8d, 0x9c, 0xb1, 0x35, 0xee, 0xe4, + 0x57, 0x40, 0x72, 0xab, 0xea, 0x93, 0xbd, 0xa7, 0xeb, 0x4f, 0x15, 0xa2, + 0x06, 0xcd, 0xaf, 0x3b, 0xbb, 0xeb, 0xd3, 0x18 +}; +static const uint8_t ac_dsa_vect189_priv_val[] = { +/* X */ + 0x41, 0x66, 0x34, 0xf9, 0xb7, 0x72, 0x21, 0x88, 0xc2, 0xa5, 0x26, 0x6c, + 0xfd, 0x9b, 0xaf, 0x1b, 0xdd, 0x50, 0x8c, 0x0c, 0x06, 0x80, 0x10, 0xfb, + 0x22, 0x8c, 0x09, 0x9f, 0xca, 0x7c, 0xec, 0x11 +}; +static const uint8_t ac_dsa_vect189_pub_val[] = { +/* Y */ + 0x76, 0x6d, 0x7e, 0x4f, 0x8b, 0xc3, 0x25, 0x4d, 0x92, 0xcf, 0x6a, 0x64, + 0xab, 0xd5, 0x04, 0xd0, 0x1c, 0xdc, 0xf6, 0xc2, 0x39, 0x17, 0x8b, 0x0a, + 0xeb, 0x3f, 0x69, 0xc9, 0xbf, 0x20, 0x2b, 0xff, 0x75, 0x66, 0xec, 0xa0, + 0x9f, 0x29, 0xcf, 0x5d, 0x6f, 0xa4, 0x73, 0x6d, 0x57, 0xc0, 0x82, 0x05, + 0x50, 0x0d, 0x64, 0x83, 0x36, 0x40, 0x9d, 0xf0, 0x6e, 0x7f, 0x2c, 0xf9, + 0x91, 0x78, 0xb2, 0x0a, 0x7e, 0xc2, 0xb5, 0x12, 0x4b, 0xcf, 0xfc, 0x61, + 0xad, 0xb6, 0x6f, 0x6f, 0xaf, 0xc5, 0x1e, 0x32, 0x52, 0x1d, 0xea, 0x21, + 0x24, 0xe5, 0x78, 0x1c, 0x38, 0x3b, 0x11, 0x6d, 0x06, 0xa6, 0xa6, 0xe8, + 0x9d, 0xec, 0x46, 0xb5, 0xe4, 0xad, 0x69, 0xf5, 0xa1, 0xe8, 0xdd, 0x7a, + 0xc5, 0xe1, 0x60, 0xda, 0x33, 0x6c, 0x11, 0x86, 0x0b, 0x60, 0x1e, 0x7e, + 0x6d, 0x58, 0x89, 0x5e, 0x67, 0x97, 0xdb, 0x5a, 0xa9, 0x2d, 0xeb, 0x7b, + 0x94, 0x2f, 0x2e, 0xdf, 0x58, 0xd4, 0x3d, 0x3d, 0xac, 0x92, 0x09, 0x55, + 0x7a, 0x6a, 0xa0, 0x7b, 0x22, 0x8e, 0x73, 0xa8, 0x0f, 0xf0, 0xe9, 0x2e, + 0x4e, 0xc4, 0x60, 0x3d, 0x36, 0x2e, 0x1c, 0xca, 0x7e, 0x92, 0x8d, 0x94, + 0x59, 0xc2, 0x14, 0x05, 0xaa, 0x0f, 0x65, 0x48, 0x73, 0x2c, 0x0f, 0xc5, + 0x01, 0xce, 0x50, 0xf0, 0x89, 0x6f, 0x07, 0x63, 0xf6, 0x33, 0xc8, 0xc1, + 0xa8, 0x53, 0x13, 0x21, 0xe1, 0xa0, 0xf4, 0x71, 0x34, 0xa0, 0xd2, 0xd8, + 0x67, 0x6f, 0x45, 0xf1, 0x3e, 0xa5, 0x76, 0xe6, 0x4c, 0x78, 0x70, 0x02, + 0x80, 0x33, 0xa4, 0x26, 0x1b, 0xdf, 0xce, 0xc9, 0x48, 0xeb, 0xb1, 0xaa, + 0x25, 0xb0, 0x21, 0x34, 0xd0, 0x25, 0x9d, 0x73, 0x02, 0x4a, 0x01, 0xda, + 0x0c, 0xad, 0x1c, 0xe6, 0x75, 0x71, 0xe3, 0x69, 0x63, 0xdc, 0x13, 0x04, + 0x96, 0x16, 0x0e, 0xbf +}; +/* K = b057bf5a5ae4204f941ff5a01560cbc29033dc6a2e06ad168403cbc6512646df */ +static const uint8_t ac_dsa_vect189_out[] = { +/* R */ + 0xa2, 0x37, 0xd2, 0xc3, 0xd2, 0x37, 0x06, 0xca, 0xf0, 0x04, 0xa2, 0xe9, + 0x4d, 0xe2, 0x9f, 0x04, 0xc7, 0x48, 0x93, 0x6b, 0x62, 0xab, 0x54, 0x31, + 0xfe, 0x73, 0xc7, 0x24, 0x85, 0x81, 0x42, 0x65, +/* S */ + 0xb4, 0x8b, 0x9e, 0xf9, 0xcb, 0xd8, 0xbd, 0xf7, 0x99, 0xb7, 0x06, 0x05, + 0xf0, 0x05, 0x50, 0xb8, 0x1b, 0x30, 0x9c, 0x15, 0x73, 0x32, 0x15, 0x3b, + 0xe9, 0x70, 0x7a, 0x39, 0x9f, 0xbd, 0xd6, 0x7f +}; +#define ac_dsa_vect190_prime ac_dsa_vect181_prime +#define ac_dsa_vect190_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect190_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect190_ptx[] = { +/* Msg */ + 0x04, 0x18, 0xe0, 0x12, 0x36, 0xca, 0xed, 0x0f, 0x80, 0x24, 0x1c, 0xe8, + 0xc6, 0x30, 0x7d, 0x02, 0x6f, 0x5e, 0x25, 0xf4, 0xa9, 0x22, 0xbb, 0xdb, + 0x4a, 0xaf, 0xb8, 0xd9, 0xdb, 0x95, 0xa1, 0x81, 0x75, 0xf9, 0xdc, 0xea, + 0x9a, 0xcb, 0x4d, 0x37, 0x6f, 0x36, 0xff, 0x7b, 0x7c, 0xb5, 0x98, 0xe0, + 0x73, 0xde, 0x95, 0xad, 0x20, 0x12, 0xeb, 0x9d, 0x11, 0xe1, 0x5c, 0xb3, + 0x94, 0x1c, 0x6d, 0xd0, 0xdd, 0x69, 0x42, 0x2e, 0x78, 0x51, 0x2e, 0xbf, + 0xfb, 0x19, 0xcc, 0x8a, 0x40, 0x3a, 0x9a, 0x7d, 0x1f, 0x17, 0x20, 0xab, + 0x0f, 0x2d, 0x25, 0x62, 0x75, 0x80, 0x36, 0x60, 0x93, 0xe2, 0x1a, 0xc1, + 0x53, 0x7f, 0x93, 0xde, 0x90, 0xa9, 0x45, 0x08, 0xf1, 0xd7, 0xa7, 0xa1, + 0xdb, 0x5a, 0x7b, 0x13, 0xc9, 0xfd, 0x00, 0xb8, 0x2b, 0xe0, 0x44, 0xc3, + 0xa3, 0x5e, 0xc0, 0x45, 0x1c, 0x30, 0x9b, 0x82 +}; +static const uint8_t ac_dsa_vect190_priv_val[] = { +/* X */ + 0x6a, 0xd9, 0x29, 0x11, 0xdd, 0x4f, 0xce, 0x03, 0x3d, 0x7a, 0x50, 0x87, + 0x5e, 0x46, 0x60, 0xbe, 0x08, 0xc4, 0x49, 0x57, 0xb8, 0x74, 0x33, 0x9c, + 0x2a, 0x70, 0xd9, 0x15, 0xcc, 0x03, 0xe2, 0x7f +}; +static const uint8_t ac_dsa_vect190_pub_val[] = { +/* Y */ + 0x4c, 0xf4, 0xce, 0xe4, 0xd5, 0xab, 0xc2, 0xc9, 0x2d, 0xb5, 0x22, 0x92, + 0x8b, 0x6d, 0x7e, 0x43, 0x6e, 0xa0, 0x08, 0x84, 0x00, 0x94, 0x97, 0xed, + 0x58, 0x8e, 0x93, 0x28, 0x1c, 0xf0, 0x5b, 0x37, 0x47, 0xca, 0x00, 0x48, + 0xb9, 0x17, 0x70, 0x82, 0x79, 0xcd, 0x02, 0x77, 0xce, 0x85, 0x60, 0xc2, + 0x27, 0x75, 0xd2, 0xaa, 0x0e, 0x7e, 0xed, 0x1b, 0xba, 0x77, 0xbe, 0x45, + 0x41, 0x7f, 0xa7, 0xaf, 0xd7, 0x76, 0xb8, 0xe5, 0x60, 0x67, 0x9c, 0x49, + 0x3a, 0x52, 0x0a, 0x0e, 0x62, 0x6a, 0xcd, 0xc8, 0x3d, 0xf0, 0x21, 0x35, + 0x16, 0x69, 0xbd, 0xf9, 0xda, 0x19, 0xb1, 0x2b, 0xef, 0x29, 0x26, 0xb5, + 0x25, 0xfa, 0x4c, 0x8e, 0x3d, 0x1f, 0x20, 0x83, 0xea, 0x6b, 0xbb, 0x48, + 0x98, 0x80, 0xf5, 0x94, 0xe6, 0x79, 0x34, 0xd1, 0xf3, 0x55, 0x81, 0xad, + 0x18, 0xe0, 0xdb, 0x46, 0x2a, 0x1a, 0xc9, 0x44, 0x06, 0x6c, 0x65, 0xdd, + 0x74, 0x3f, 0x35, 0x74, 0x1c, 0x6c, 0xf5, 0x88, 0x91, 0x8d, 0x83, 0x36, + 0x70, 0x23, 0x29, 0xc6, 0x21, 0x13, 0xe9, 0x48, 0x6b, 0xfa, 0x49, 0xca, + 0x54, 0x25, 0x91, 0x45, 0x26, 0xa9, 0x65, 0xe3, 0xc1, 0x97, 0x58, 0x24, + 0xf4, 0xb3, 0x9f, 0xa5, 0xfe, 0xf8, 0x9c, 0xf6, 0xf9, 0xea, 0x51, 0x2f, + 0x7f, 0xfc, 0x91, 0x38, 0xe7, 0x2d, 0xbd, 0x0f, 0x71, 0xb0, 0x1a, 0x70, + 0x97, 0x53, 0x12, 0xea, 0xca, 0xb1, 0x11, 0x18, 0x47, 0x11, 0x15, 0xee, + 0x3f, 0xc8, 0x10, 0x52, 0x29, 0x36, 0xc9, 0xdf, 0x35, 0x97, 0x75, 0x09, + 0xb1, 0x96, 0xd8, 0x67, 0xfa, 0x11, 0xf6, 0x07, 0xb7, 0xef, 0x9a, 0xb7, + 0x8c, 0xb7, 0x48, 0x21, 0x3a, 0x67, 0x63, 0x43, 0x9c, 0xe5, 0xe7, 0x64, + 0x1b, 0x05, 0x35, 0x96, 0x70, 0x61, 0x22, 0x03, 0xa4, 0x7d, 0x4d, 0xe9, + 0xc5, 0x38, 0x84, 0x05 +}; +/* K = 5aed2d19239189cd0bc8cfa3c329748c0555d8eafd5e80ff931966680e3ea454 */ +static const uint8_t ac_dsa_vect190_out[] = { +/* R */ + 0x83, 0xee, 0x96, 0x0e, 0x6f, 0x90, 0x26, 0xfe, 0x24, 0x54, 0xd8, 0x59, + 0x46, 0x2a, 0xc3, 0x34, 0xa1, 0x38, 0x96, 0xe7, 0x51, 0x79, 0x85, 0x8e, + 0xf4, 0x0e, 0x2e, 0x9a, 0x06, 0x5c, 0x53, 0x6a, +/* S */ + 0x7c, 0xe8, 0x69, 0x9c, 0x6c, 0xcb, 0x18, 0x4d, 0x42, 0x40, 0xb8, 0x70, + 0x9d, 0xa1, 0x14, 0x51, 0x32, 0x8c, 0xf1, 0xa7, 0xe0, 0xca, 0xfe, 0x6e, + 0x1c, 0x8a, 0xb5, 0x3d, 0x7d, 0xe6, 0x7d, 0x9e +}; +#define ac_dsa_vect191_prime ac_dsa_vect181_prime +#define ac_dsa_vect191_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect191_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect191_ptx[] = { +/* Msg */ + 0x92, 0xc9, 0x49, 0xfe, 0x23, 0x42, 0xf9, 0x1a, 0x38, 0x7b, 0x67, 0xc1, + 0xb1, 0x2b, 0x1d, 0x04, 0xd0, 0x72, 0x12, 0x03, 0xca, 0xed, 0x59, 0x3c, + 0x9c, 0x46, 0x4e, 0x5f, 0xda, 0x09, 0xfd, 0xcc, 0x91, 0xd3, 0x32, 0x1d, + 0x29, 0x85, 0xee, 0xc0, 0x8a, 0xb2, 0x02, 0x6d, 0x1e, 0xc3, 0xfc, 0xfa, + 0x83, 0x8c, 0xb6, 0xaf, 0x45, 0x29, 0x0c, 0x08, 0xdc, 0x30, 0xb9, 0xc1, + 0x4c, 0x44, 0x45, 0xd7, 0x83, 0xb6, 0xf4, 0x84, 0x09, 0xa0, 0x04, 0x90, + 0xf4, 0xe3, 0x08, 0xdb, 0xc8, 0x7f, 0xd1, 0xb2, 0xf8, 0x78, 0x38, 0x52, + 0x12, 0xe1, 0xf4, 0xc3, 0xe1, 0xcf, 0x81, 0xc5, 0x6d, 0x71, 0xe7, 0x3f, + 0xd7, 0xa0, 0x95, 0xb5, 0x6b, 0x4a, 0xbe, 0xc1, 0x5c, 0x57, 0x10, 0x74, + 0x20, 0xfb, 0xdf, 0xa4, 0x44, 0x77, 0x07, 0x8c, 0xcf, 0x45, 0x19, 0xf9, + 0xf6, 0x04, 0x4f, 0x07, 0x44, 0x05, 0x20, 0x35 +}; +static const uint8_t ac_dsa_vect191_priv_val[] = { +/* X */ + 0xb0, 0xd2, 0x3a, 0xab, 0x4d, 0x95, 0x44, 0x6f, 0x8c, 0x6c, 0x5d, 0x49, + 0x6d, 0x47, 0x7d, 0xd9, 0x48, 0x6f, 0x50, 0xb2, 0x82, 0x7f, 0x7c, 0xd1, + 0x97, 0x28, 0xbc, 0x96, 0xf8, 0x28, 0x40, 0xc7 +}; +static const uint8_t ac_dsa_vect191_pub_val[] = { +/* Y */ + 0x25, 0x6d, 0x23, 0x1a, 0xc2, 0xba, 0xe6, 0x50, 0xd2, 0x59, 0x99, 0xb2, + 0x70, 0x6d, 0x4c, 0xb6, 0x3a, 0x89, 0xb1, 0x46, 0x8e, 0x0d, 0xf3, 0x6d, + 0x67, 0x75, 0x35, 0xfa, 0x7a, 0x0e, 0xa8, 0x90, 0x59, 0x0d, 0x32, 0x90, + 0xd4, 0xb5, 0x0b, 0xdb, 0x39, 0x9f, 0x33, 0xdc, 0x41, 0x5e, 0x44, 0x69, + 0xc9, 0x7c, 0x6c, 0x0c, 0xee, 0x82, 0x05, 0xee, 0xc9, 0x62, 0xd7, 0x15, + 0x3c, 0x4c, 0x85, 0xab, 0x88, 0xf7, 0xcf, 0x80, 0x97, 0x9d, 0x4a, 0x1f, + 0xfd, 0x8c, 0x74, 0xe6, 0x81, 0xc1, 0xd2, 0x8d, 0xa0, 0x77, 0x32, 0x11, + 0x6c, 0x32, 0x10, 0xee, 0x4b, 0x69, 0x33, 0x09, 0x33, 0x36, 0x86, 0x24, + 0x6d, 0x66, 0x70, 0x74, 0xc7, 0x17, 0x20, 0x35, 0xfd, 0x60, 0x91, 0xb2, + 0x84, 0x0b, 0x11, 0x39, 0x70, 0xb4, 0x59, 0x83, 0xd4, 0x74, 0xf5, 0x4b, + 0x95, 0xd2, 0x63, 0x94, 0xb7, 0xa4, 0x3e, 0x81, 0xb4, 0x49, 0xa2, 0xee, + 0x94, 0x23, 0xaa, 0x1c, 0x27, 0xf4, 0x59, 0x2b, 0x51, 0x6c, 0x12, 0xd5, + 0x43, 0x3e, 0x2b, 0xa7, 0x24, 0xf5, 0x46, 0x3b, 0x41, 0x69, 0xa2, 0xb0, + 0x94, 0x0e, 0x1b, 0xcc, 0xd6, 0x0c, 0xca, 0xb9, 0xb5, 0xa3, 0x82, 0x48, + 0xac, 0xb6, 0x05, 0x82, 0xab, 0x8b, 0xbc, 0x01, 0xc5, 0xe7, 0x5f, 0x9e, + 0xf7, 0x47, 0x42, 0x73, 0xfb, 0x51, 0xaa, 0x63, 0x16, 0xe6, 0x49, 0xf4, + 0xf2, 0x24, 0x52, 0xdc, 0x70, 0xbf, 0xd4, 0xc3, 0xda, 0x07, 0x2c, 0x03, + 0xea, 0x82, 0xee, 0x00, 0x9d, 0x42, 0x72, 0xa8, 0x49, 0x61, 0xc9, 0x8e, + 0x51, 0x7a, 0xb9, 0x47, 0x74, 0x1d, 0x81, 0x21, 0x16, 0x01, 0x1d, 0xec, + 0x03, 0x73, 0xca, 0x8f, 0xba, 0xc5, 0x57, 0x6c, 0x20, 0x69, 0xb0, 0x67, + 0xf8, 0xb0, 0x05, 0xd6, 0x0a, 0x36, 0xec, 0xa4, 0x4f, 0x56, 0x01, 0x9a, + 0x64, 0x83, 0x5d, 0x76 +}; +/* K = 17a199bd383a84e22029fb90d5abc9a8a7ccd3f0a33720ca80e3161971793526 */ +static const uint8_t ac_dsa_vect191_out[] = { +/* R */ + 0x84, 0xca, 0xce, 0x71, 0xa8, 0x0e, 0xd4, 0x74, 0x94, 0x57, 0x0f, 0xc8, + 0x48, 0x39, 0xf2, 0xe3, 0x50, 0x19, 0x1b, 0x74, 0xf0, 0xee, 0xff, 0xf2, + 0xd7, 0xab, 0x2c, 0x68, 0x9d, 0xb7, 0x7b, 0xae, +/* S */ + 0x9c, 0xac, 0x33, 0x59, 0x4e, 0x19, 0x34, 0xb6, 0x8f, 0x62, 0xac, 0xa0, + 0x5c, 0xa0, 0x40, 0xf3, 0xc8, 0x21, 0x10, 0xc1, 0x0b, 0x73, 0x79, 0x87, + 0x8b, 0x78, 0x94, 0xb0, 0x91, 0x9a, 0x0f, 0x2f +}; +#define ac_dsa_vect192_prime ac_dsa_vect181_prime +#define ac_dsa_vect192_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect192_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect192_ptx[] = { +/* Msg */ + 0xdf, 0x6a, 0x4e, 0xb7, 0xca, 0xd4, 0xff, 0x9b, 0xdd, 0x83, 0x56, 0xd3, + 0x56, 0x8f, 0xcf, 0x02, 0x85, 0xc1, 0xa4, 0xe3, 0xc3, 0x10, 0x9f, 0xaa, + 0x09, 0x1b, 0x58, 0xa9, 0xbd, 0x90, 0x7c, 0x62, 0x9d, 0x54, 0xaa, 0x7a, + 0x23, 0xa7, 0x48, 0x70, 0x54, 0x5a, 0x09, 0x42, 0xa2, 0xd2, 0x39, 0x14, + 0xf2, 0xf1, 0x67, 0xd9, 0x65, 0x73, 0xf0, 0x6f, 0x35, 0xea, 0x05, 0xef, + 0x70, 0x4c, 0xac, 0x80, 0x14, 0xdd, 0x21, 0xb9, 0x61, 0xd3, 0xda, 0xcf, + 0x7b, 0x93, 0x0b, 0xbd, 0x7e, 0x35, 0x55, 0x0f, 0x72, 0x10, 0x94, 0xc8, + 0x63, 0x33, 0xe0, 0x3e, 0xd4, 0xda, 0xb7, 0xbc, 0x1b, 0x64, 0x16, 0xad, + 0xd9, 0x57, 0x8d, 0x27, 0x9e, 0xda, 0xee, 0x37, 0x50, 0x4f, 0xd2, 0x5e, + 0xc0, 0xc5, 0xe8, 0xa3, 0x7a, 0xc9, 0xec, 0x19, 0xbf, 0xb1, 0xe3, 0x77, + 0x8e, 0xd6, 0xd9, 0xc6, 0xb6, 0xe3, 0x5e, 0xc7 +}; +static const uint8_t ac_dsa_vect192_priv_val[] = { +/* X */ + 0x67, 0x9e, 0xf4, 0x8b, 0x64, 0x3b, 0xe3, 0x94, 0x67, 0x7d, 0x17, 0xe8, + 0x37, 0xa0, 0xbe, 0x6d, 0x4d, 0x80, 0x27, 0xa9, 0x00, 0xb6, 0x86, 0xae, + 0xd7, 0xc4, 0xb1, 0x26, 0x34, 0xfe, 0xa7, 0x6a +}; +static const uint8_t ac_dsa_vect192_pub_val[] = { +/* Y */ + 0x2f, 0x4b, 0x0c, 0x01, 0xe4, 0xb1, 0x5e, 0xb5, 0xee, 0x7a, 0xfa, 0x98, + 0x24, 0x09, 0x33, 0x30, 0x73, 0x8b, 0xe2, 0xf3, 0xf0, 0x6c, 0x42, 0xb2, + 0xb7, 0xc6, 0x96, 0x8f, 0xa5, 0x4b, 0x98, 0x7c, 0x18, 0x4e, 0x7f, 0xa8, + 0x9e, 0xff, 0x16, 0xda, 0x02, 0xb9, 0x3f, 0xf6, 0x1b, 0x9c, 0xe4, 0x8e, + 0xeb, 0xe7, 0xea, 0xb0, 0xf7, 0xe2, 0x03, 0xad, 0x11, 0xc7, 0x1e, 0x7b, + 0x29, 0x7d, 0x23, 0xf2, 0xd5, 0xa5, 0x99, 0x82, 0x72, 0xc3, 0x0c, 0x2e, + 0x17, 0x24, 0xb5, 0xe9, 0x63, 0xbf, 0xd6, 0xf8, 0x32, 0x39, 0xf8, 0x74, + 0xd8, 0x8e, 0xa0, 0x89, 0x43, 0x5b, 0x89, 0x6d, 0xd2, 0x10, 0x9b, 0x6a, + 0x14, 0xb2, 0xd8, 0x48, 0xf9, 0xed, 0x7e, 0x92, 0x14, 0x3c, 0x06, 0x49, + 0xf9, 0x7f, 0x4f, 0x2e, 0xb0, 0x5b, 0x8c, 0x5a, 0x07, 0xe9, 0x9e, 0x49, + 0x7d, 0xbc, 0x75, 0x2d, 0x44, 0x3e, 0xba, 0x93, 0xd7, 0xf3, 0xdc, 0xdc, + 0x32, 0x40, 0xa2, 0x71, 0x4e, 0xa0, 0xe3, 0xe7, 0x62, 0x7f, 0x21, 0x6e, + 0x47, 0x01, 0x14, 0x8d, 0xd2, 0x11, 0x92, 0xf2, 0x74, 0xf1, 0xed, 0x5d, + 0xf0, 0x5c, 0x60, 0xb1, 0x57, 0x6d, 0x3a, 0x0b, 0x7f, 0x69, 0xa7, 0x76, + 0xb5, 0x01, 0x04, 0x04, 0xac, 0xd5, 0xaf, 0xaf, 0xd3, 0xd7, 0x0f, 0x57, + 0x76, 0x3f, 0x2b, 0x77, 0x8d, 0x0c, 0x36, 0x1e, 0x5f, 0x7f, 0x0b, 0xbe, + 0x17, 0xaa, 0xfa, 0xa5, 0xcd, 0x39, 0x33, 0x29, 0x17, 0x1d, 0x06, 0xec, + 0x03, 0x20, 0x39, 0xa9, 0xff, 0xb3, 0x7c, 0x3a, 0xb8, 0xcd, 0x85, 0x8e, + 0xa7, 0x88, 0xa7, 0xb9, 0xf5, 0x01, 0x99, 0x6b, 0xaf, 0x95, 0x9c, 0xa8, + 0x5c, 0x7d, 0xaf, 0xe0, 0xcd, 0x3e, 0x30, 0x95, 0x76, 0x40, 0xef, 0xf1, + 0x05, 0x89, 0x4c, 0x43, 0xf8, 0x66, 0xbc, 0xc4, 0x22, 0x69, 0x8d, 0x12, + 0x8d, 0xca, 0x08, 0x87 +}; +/* K = 3cf9da6f182bade870946d3ed3b078208ea8153c45515d64f589bca72b703ebf */ +static const uint8_t ac_dsa_vect192_out[] = { +/* R */ + 0x1d, 0xd2, 0xda, 0xea, 0xf3, 0xe8, 0x9f, 0xd6, 0x44, 0xc6, 0xcc, 0x94, + 0x23, 0x11, 0xea, 0x50, 0x56, 0x41, 0x3d, 0x8a, 0x24, 0x08, 0x77, 0x87, + 0x67, 0x5c, 0xef, 0xfd, 0x3d, 0x6c, 0x15, 0xe4, +/* S */ + 0x3e, 0x12, 0x78, 0x13, 0x96, 0x55, 0x85, 0x60, 0x45, 0x5c, 0x4e, 0x70, + 0xf6, 0x10, 0x52, 0x2a, 0xb2, 0xb1, 0x0f, 0xc2, 0x53, 0x43, 0x29, 0x68, + 0x18, 0xef, 0x7f, 0xfb, 0x03, 0x78, 0xfa, 0x47 +}; +#define ac_dsa_vect193_prime ac_dsa_vect181_prime +#define ac_dsa_vect193_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect193_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect193_ptx[] = { +/* Msg */ + 0x4f, 0x16, 0x68, 0x1e, 0xaa, 0x5d, 0x97, 0x67, 0x3a, 0x7c, 0xca, 0x02, + 0xee, 0x8a, 0x73, 0x74, 0xb7, 0x54, 0x11, 0xe0, 0xb5, 0x70, 0x4a, 0x94, + 0x7f, 0x04, 0xd1, 0xa5, 0xb1, 0x4b, 0xe0, 0xb5, 0x06, 0xf3, 0x1c, 0x2f, + 0xa3, 0x29, 0xe3, 0xca, 0x51, 0x6f, 0xa4, 0xf1, 0x62, 0x6a, 0x9b, 0x5e, + 0x08, 0x0b, 0xda, 0x7f, 0x35, 0x3f, 0x85, 0x03, 0x65, 0xea, 0xc7, 0xc3, + 0xd2, 0x59, 0x6f, 0x50, 0x2a, 0x5d, 0x70, 0xb1, 0x54, 0x22, 0x76, 0xc1, + 0x2d, 0x4e, 0xa4, 0xa2, 0x2b, 0x53, 0x25, 0xb9, 0xeb, 0x3e, 0x94, 0x2e, + 0x55, 0x67, 0x69, 0xb7, 0x96, 0xc4, 0xf5, 0x24, 0x59, 0x5f, 0x1c, 0xc6, + 0xce, 0x17, 0xf9, 0x9f, 0x9d, 0xbf, 0x51, 0x33, 0x14, 0x53, 0x22, 0x8e, + 0xad, 0x32, 0x7b, 0x61, 0x4f, 0x44, 0x38, 0xd3, 0x5d, 0x61, 0x42, 0x84, + 0x29, 0xf7, 0x8c, 0x8c, 0x93, 0x77, 0xaa, 0xaa +}; +static const uint8_t ac_dsa_vect193_priv_val[] = { +/* X */ + 0xe0, 0xe5, 0x76, 0x43, 0x29, 0x13, 0xbc, 0x75, 0xa2, 0xe0, 0xde, 0x3b, + 0x33, 0xbf, 0x30, 0x94, 0x14, 0x82, 0x98, 0x61, 0x2a, 0x9d, 0xc5, 0x6f, + 0xed, 0xd4, 0x7a, 0xa5, 0x69, 0xaf, 0x8a, 0xc8 +}; +static const uint8_t ac_dsa_vect193_pub_val[] = { +/* Y */ + 0x2e, 0x33, 0x60, 0x4e, 0xd9, 0xe6, 0xc0, 0xf1, 0xba, 0x40, 0x3a, 0x8c, + 0x3c, 0x3f, 0xe8, 0xe8, 0xf4, 0x88, 0x59, 0x18, 0x13, 0xaa, 0x3d, 0x2f, + 0xcc, 0xcd, 0xf8, 0x8f, 0xe8, 0x08, 0xf7, 0x0a, 0xdf, 0x17, 0x3f, 0x0f, + 0x14, 0x3a, 0xbd, 0xaa, 0xd4, 0x3b, 0x80, 0x76, 0x9e, 0x30, 0xff, 0xc5, + 0x74, 0x9e, 0x8a, 0xd3, 0x59, 0x99, 0x95, 0x3d, 0xef, 0xf4, 0xf6, 0x1f, + 0x4c, 0xa0, 0x73, 0x13, 0x60, 0x9e, 0x23, 0xac, 0xae, 0x7b, 0x35, 0xf7, + 0x79, 0x34, 0xfd, 0xbb, 0xe1, 0xc3, 0x80, 0xb2, 0x72, 0x7b, 0x1c, 0x38, + 0x99, 0x25, 0x0a, 0xf5, 0xb4, 0x39, 0x9b, 0x65, 0x8b, 0x79, 0x08, 0x67, + 0x6d, 0x64, 0xd1, 0x17, 0x63, 0x78, 0x53, 0x73, 0xb2, 0x16, 0x98, 0x36, + 0x61, 0x1d, 0x72, 0xa9, 0x57, 0x31, 0x99, 0x36, 0xc8, 0x4e, 0xfd, 0x72, + 0xb7, 0x2f, 0x92, 0xbd, 0xd2, 0xdb, 0xe0, 0x00, 0x0d, 0x88, 0x41, 0xab, + 0x6d, 0x8d, 0x0d, 0x66, 0x6e, 0x79, 0x36, 0x1a, 0xbb, 0x23, 0xb6, 0x00, + 0x73, 0x48, 0xdb, 0xbe, 0x7a, 0x94, 0x93, 0x6d, 0xc6, 0xb0, 0x26, 0xf3, + 0xb7, 0x10, 0x00, 0x81, 0xf5, 0x47, 0xb9, 0x94, 0xe0, 0xe0, 0x77, 0x8c, + 0xb7, 0x61, 0xeb, 0xd4, 0x3a, 0x29, 0xd8, 0x76, 0x4c, 0x7f, 0x96, 0x2a, + 0x74, 0x7e, 0xcc, 0x92, 0xe4, 0xa2, 0xa6, 0x28, 0xf5, 0x2d, 0x8a, 0xbf, + 0x43, 0xf6, 0xe3, 0x27, 0x8a, 0x0d, 0x32, 0xea, 0x67, 0xc2, 0xd7, 0x9d, + 0x04, 0xc8, 0x33, 0x87, 0xdd, 0xc7, 0x09, 0x36, 0x5c, 0x0a, 0x0b, 0xac, + 0xc8, 0x3d, 0x75, 0xc9, 0x46, 0xe2, 0x83, 0xe0, 0x73, 0x92, 0x33, 0x58, + 0x14, 0x41, 0xae, 0xdd, 0xb0, 0xd7, 0xd7, 0x65, 0x03, 0xd6, 0x21, 0x40, + 0x5d, 0x27, 0xef, 0x66, 0xfa, 0x8b, 0x53, 0x79, 0xd1, 0x78, 0x61, 0x7d, + 0x4b, 0xb5, 0xad, 0x59 +}; +/* K = 53cb2d046b391193efb14a4dfafa296c2ec92293c7b3c7d19a20e68c4a1141d9 */ +static const uint8_t ac_dsa_vect193_out[] = { +/* R */ + 0xe2, 0xff, 0x3f, 0xc4, 0x41, 0xdb, 0x45, 0x40, 0x19, 0x4a, 0x7f, 0x5d, + 0xa1, 0xea, 0xd8, 0x49, 0xc2, 0xc3, 0xc4, 0x8d, 0xcc, 0xf8, 0xb2, 0xc1, + 0xb3, 0xb3, 0x59, 0xa7, 0xb1, 0x6e, 0x16, 0xab, +/* S */ + 0x52, 0xfb, 0xdc, 0xd5, 0xc6, 0x2a, 0x99, 0x9a, 0xab, 0x46, 0x14, 0x7f, + 0xef, 0x9e, 0x18, 0xcb, 0xfc, 0x7d, 0xaf, 0x68, 0x0a, 0x7d, 0xdb, 0x89, + 0x2e, 0xdf, 0xa4, 0x4d, 0x28, 0x5e, 0x21, 0x58 +}; +#define ac_dsa_vect194_prime ac_dsa_vect181_prime +#define ac_dsa_vect194_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect194_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect194_ptx[] = { +/* Msg */ + 0x09, 0xe4, 0x8a, 0x36, 0x52, 0x3b, 0x52, 0x89, 0xec, 0x41, 0x85, 0x9f, + 0xaa, 0x14, 0x1e, 0x2a, 0x29, 0xb3, 0xe8, 0x8a, 0xb2, 0xd6, 0x35, 0x1e, + 0x20, 0xde, 0x00, 0x1e, 0x64, 0x24, 0xb8, 0x53, 0x37, 0x67, 0x5f, 0x0c, + 0xe2, 0x6b, 0xe2, 0x24, 0xfa, 0x4f, 0x8d, 0xf0, 0xef, 0x97, 0x10, 0xea, + 0x28, 0x56, 0x35, 0xb2, 0x7b, 0x29, 0x7d, 0x68, 0x8e, 0x33, 0x8b, 0x54, + 0x61, 0x82, 0x0b, 0x57, 0xbe, 0x4b, 0xee, 0x21, 0x64, 0x5b, 0x04, 0x95, + 0x7c, 0xa2, 0xf6, 0xcd, 0x7a, 0xf9, 0xa6, 0xa5, 0x2b, 0x3c, 0x97, 0xc5, + 0xb9, 0xdb, 0x1c, 0x2f, 0x7e, 0xa8, 0x17, 0xcd, 0x6d, 0x3c, 0x85, 0x22, + 0xd4, 0xe6, 0xa9, 0xde, 0x86, 0x9a, 0xef, 0x26, 0xec, 0x0d, 0xbd, 0xd2, + 0x69, 0xc7, 0x9b, 0x38, 0x80, 0x69, 0x27, 0xbd, 0x3a, 0x51, 0x00, 0x73, + 0x5e, 0x6f, 0x9f, 0x65, 0x5c, 0xa9, 0x4d, 0xae +}; +static const uint8_t ac_dsa_vect194_priv_val[] = { +/* X */ + 0x78, 0x91, 0xb0, 0x5e, 0x24, 0x82, 0x3f, 0x28, 0x31, 0x26, 0xd7, 0xd1, + 0x75, 0xa4, 0xe8, 0xc8, 0x12, 0x4b, 0x37, 0x76, 0xf4, 0xf2, 0x96, 0xd0, + 0xff, 0xc4, 0xb5, 0xe2, 0x1b, 0xb6, 0x4d, 0x70 +}; +static const uint8_t ac_dsa_vect194_pub_val[] = { +/* Y */ + 0x7e, 0x38, 0xcb, 0x66, 0x8d, 0x64, 0x7e, 0xe1, 0x5f, 0x71, 0xac, 0x5d, + 0x2b, 0x55, 0xc1, 0x1f, 0xd4, 0x73, 0x1e, 0x1a, 0x6c, 0x03, 0x1d, 0xd7, + 0x59, 0x4d, 0x61, 0x4f, 0x2f, 0x1e, 0xd2, 0x56, 0x23, 0xff, 0xfd, 0xc5, + 0x95, 0x6f, 0x52, 0x56, 0xe6, 0x35, 0xc9, 0x14, 0x20, 0x5a, 0x29, 0x37, + 0xa6, 0x07, 0x4c, 0xfe, 0x1f, 0x3e, 0x44, 0x3b, 0xbe, 0xb3, 0x23, 0xa2, + 0x3b, 0x0f, 0x0f, 0xbc, 0xcf, 0x8c, 0x17, 0x70, 0xad, 0x18, 0xba, 0x97, + 0xd0, 0xac, 0xbe, 0xa1, 0xe8, 0x46, 0xe1, 0x2c, 0xf1, 0x2c, 0x37, 0x06, + 0x25, 0xb1, 0x55, 0x5d, 0x71, 0x09, 0x05, 0xee, 0xe9, 0x43, 0x53, 0x9f, + 0x22, 0x41, 0xb8, 0xfb, 0x49, 0x0c, 0x9d, 0x6b, 0x44, 0xf3, 0x61, 0x39, + 0x22, 0x6b, 0x4c, 0x1f, 0x00, 0xe9, 0x5f, 0xfe, 0x59, 0x50, 0x14, 0xf6, + 0x1b, 0xf5, 0x79, 0x83, 0x6a, 0x14, 0x21, 0x2c, 0x07, 0x23, 0x1a, 0x5e, + 0x9e, 0x87, 0xde, 0x4a, 0x9a, 0xaf, 0x0f, 0x46, 0xf3, 0x4c, 0x92, 0x29, + 0xf2, 0xea, 0xbb, 0x71, 0xd4, 0x0d, 0xe2, 0x6a, 0x1c, 0xbe, 0x10, 0xdb, + 0x06, 0x45, 0xce, 0xc3, 0x7d, 0x48, 0x57, 0x5a, 0x11, 0x54, 0xbb, 0x5a, + 0xcc, 0x94, 0x7b, 0xec, 0xb2, 0xa7, 0x4b, 0x07, 0xe2, 0xa0, 0xe4, 0x5b, + 0x90, 0x3b, 0xe3, 0x75, 0x02, 0xf9, 0x1b, 0x07, 0xfb, 0x4e, 0xcd, 0x7f, + 0x21, 0xfb, 0x13, 0x0c, 0x6d, 0x63, 0x9e, 0xf0, 0xfd, 0x84, 0x44, 0xfa, + 0x12, 0xde, 0x85, 0x9a, 0xbe, 0x95, 0x54, 0x88, 0x01, 0xf6, 0xa3, 0xc4, + 0x0e, 0x7a, 0x65, 0xfd, 0x15, 0x18, 0x22, 0x1a, 0x27, 0x4d, 0x7b, 0x65, + 0xed, 0x41, 0x75, 0xf6, 0x6c, 0x04, 0xd9, 0x19, 0xc8, 0x6d, 0x2a, 0xe8, + 0xc3, 0x74, 0xb1, 0x47, 0x09, 0xe9, 0xc8, 0xa3, 0x9e, 0x1d, 0x0c, 0x4e, + 0x99, 0x35, 0x54, 0x0b +}; +/* K = dc24b379ee2d26d5db792839795ad0d4b9622c0e3fd518df541a5f6e9cefba0f */ +static const uint8_t ac_dsa_vect194_out[] = { +/* R */ + 0xe5, 0x50, 0xdc, 0x65, 0xaf, 0x27, 0x5e, 0x47, 0xbe, 0x48, 0x0f, 0xd6, + 0x47, 0x36, 0x6e, 0x2b, 0x05, 0x5c, 0x79, 0xea, 0x33, 0xde, 0xd4, 0xf5, + 0xa9, 0x55, 0x71, 0x21, 0xe0, 0x82, 0xaf, 0x26, +/* S */ + 0xe2, 0x6b, 0x1a, 0x5f, 0x27, 0xcc, 0x6c, 0x87, 0x86, 0x3e, 0x31, 0xef, + 0x7f, 0x1e, 0x61, 0xbe, 0xa4, 0x76, 0xfc, 0x5d, 0x7c, 0x25, 0xfd, 0xf2, + 0x2f, 0xe7, 0x40, 0xf2, 0x3a, 0xa9, 0xa7, 0x52 +}; +#define ac_dsa_vect195_prime ac_dsa_vect181_prime +#define ac_dsa_vect195_sub_prime ac_dsa_vect181_sub_prime +#define ac_dsa_vect195_base ac_dsa_vect181_base +static const uint8_t ac_dsa_vect195_ptx[] = { +/* Msg */ + 0x88, 0x37, 0xbb, 0xce, 0xef, 0x57, 0x75, 0x11, 0xf2, 0xd0, 0xc0, 0x8f, + 0x79, 0x0d, 0x5d, 0x2e, 0x85, 0x62, 0xd9, 0x3d, 0xf3, 0xd8, 0x2d, 0xd4, + 0xc2, 0x82, 0x7c, 0xd9, 0xa9, 0x11, 0x53, 0x08, 0x11, 0x4a, 0x18, 0xc4, + 0x52, 0xdb, 0x27, 0x85, 0x56, 0x10, 0x81, 0xeb, 0x52, 0x36, 0x85, 0xae, + 0x2b, 0x3c, 0x8b, 0x09, 0x0e, 0x0d, 0x44, 0xdd, 0x40, 0xd2, 0xfc, 0x0c, + 0xdf, 0xc8, 0x8d, 0x6f, 0x90, 0x63, 0xa7, 0x70, 0x7d, 0xf6, 0x09, 0xed, + 0xf0, 0xa8, 0xc5, 0x50, 0x34, 0x81, 0x5e, 0xa9, 0xf1, 0xd8, 0xb0, 0xbc, + 0xbc, 0x92, 0xfb, 0xa5, 0x13, 0xba, 0x81, 0xee, 0x64, 0x6b, 0xf9, 0x8a, + 0xd4, 0xeb, 0x22, 0xbe, 0x26, 0xa4, 0x58, 0x2b, 0x1b, 0xe2, 0x89, 0x9c, + 0x91, 0xee, 0xbc, 0xbc, 0x9f, 0xba, 0x58, 0x25, 0xe0, 0x21, 0xe9, 0x9b, + 0xe0, 0xc9, 0xd2, 0x86, 0x42, 0xd1, 0x3f, 0xa4 +}; +static const uint8_t ac_dsa_vect195_priv_val[] = { +/* X */ + 0x11, 0x6d, 0x18, 0x36, 0xa1, 0x31, 0x31, 0x06, 0x44, 0xaa, 0xae, 0xe6, + 0xac, 0x39, 0xb3, 0x64, 0x3c, 0xd5, 0x00, 0x26, 0xa6, 0xb4, 0x86, 0x16, + 0x7c, 0xb4, 0xda, 0xac, 0x24, 0x2a, 0x4e, 0x7a +}; +static const uint8_t ac_dsa_vect195_pub_val[] = { +/* Y */ + 0x77, 0xd7, 0xa4, 0x0a, 0x7b, 0xab, 0x3f, 0x57, 0x78, 0xf8, 0x5d, 0x4f, + 0xc4, 0x8b, 0x3e, 0x28, 0xce, 0x28, 0xb2, 0xdf, 0x9e, 0xb8, 0x7c, 0xc9, + 0xcf, 0x39, 0x4e, 0xf2, 0x8e, 0x80, 0x64, 0xf3, 0x9a, 0x96, 0x90, 0x10, + 0x39, 0x80, 0xa6, 0x6d, 0xa2, 0x19, 0xcb, 0x50, 0x22, 0xc1, 0x01, 0xf2, + 0x20, 0x11, 0xa8, 0x15, 0x7a, 0x75, 0x68, 0xc5, 0xff, 0x2e, 0x97, 0x8b, + 0xa2, 0x20, 0x13, 0x67, 0xd1, 0x7c, 0x22, 0xa8, 0x67, 0x86, 0x5d, 0x00, + 0xc2, 0xa4, 0x37, 0x38, 0x56, 0x27, 0xbd, 0x08, 0x8b, 0xfc, 0xf7, 0x21, + 0x92, 0x51, 0xbf, 0x6a, 0xe1, 0x58, 0x26, 0x9f, 0x4e, 0xf3, 0x5d, 0xa7, + 0x09, 0x5a, 0x53, 0xc2, 0x4f, 0x37, 0xd6, 0x1b, 0xcf, 0xb7, 0xc0, 0x43, + 0xfe, 0xb6, 0xe9, 0x38, 0x32, 0x34, 0x3f, 0x9e, 0x90, 0xee, 0x71, 0x04, + 0xc8, 0x04, 0x86, 0xec, 0xd0, 0x87, 0xbe, 0x1b, 0x67, 0xf1, 0x8c, 0xda, + 0xaa, 0x37, 0x5e, 0x03, 0x9c, 0xb7, 0xad, 0x60, 0x3c, 0xb0, 0xcd, 0x85, + 0x56, 0x23, 0xe9, 0xfb, 0x48, 0xe4, 0xee, 0xde, 0x14, 0xea, 0x3c, 0x76, + 0xa0, 0x36, 0x4a, 0xac, 0x00, 0x66, 0x50, 0xd3, 0xb5, 0xcd, 0x9b, 0x47, + 0x4b, 0x56, 0xf8, 0x58, 0x4b, 0xe5, 0x8a, 0x72, 0x1b, 0xf3, 0x4d, 0xd0, + 0x80, 0x8d, 0x33, 0x4c, 0xd8, 0x63, 0x2e, 0x80, 0x85, 0x36, 0x79, 0x1f, + 0xcb, 0xea, 0x96, 0x1f, 0x71, 0x63, 0xda, 0xd2, 0x83, 0x53, 0xc1, 0x15, + 0xeb, 0x3e, 0x85, 0x67, 0x37, 0xdb, 0xbe, 0xe0, 0x34, 0x36, 0x72, 0x16, + 0x37, 0xa4, 0x77, 0x54, 0xa8, 0xa1, 0xfe, 0x0f, 0xed, 0xf5, 0x47, 0xb3, + 0x58, 0xa7, 0x3d, 0x05, 0xb7, 0x69, 0xa9, 0x5b, 0xde, 0x34, 0x40, 0x00, + 0x7c, 0x07, 0x73, 0xa3, 0xc7, 0xc8, 0xdc, 0x97, 0x14, 0xe1, 0x1c, 0x3a, + 0x10, 0xee, 0x01, 0xd7 +}; +/* K = 4a6febb624c8ebd411cfb30c6db055dec3d0d17456dc0c54bd1b43531d4f2649 */ +static const uint8_t ac_dsa_vect195_out[] = { +/* R */ + 0x7b, 0x6b, 0x3e, 0xae, 0xf6, 0xcd, 0x5f, 0xe6, 0xda, 0xed, 0xe8, 0x6d, + 0x63, 0x94, 0x34, 0x78, 0xc7, 0x71, 0x58, 0x24, 0x83, 0xbe, 0x0b, 0x92, + 0x6e, 0xe3, 0x02, 0x2d, 0x22, 0xef, 0x91, 0x2e, +/* S */ + 0x39, 0xd9, 0x28, 0xb5, 0x9a, 0x69, 0x04, 0x50, 0xd1, 0x33, 0x59, 0xa2, + 0x9e, 0xfe, 0x20, 0xcb, 0x98, 0xbf, 0xd3, 0xfc, 0x97, 0x26, 0xf8, 0x0e, + 0x51, 0x48, 0xf0, 0x59, 0x66, 0x3f, 0xfd, 0x08 +}; +/* [mod = L=2048, N=256, SHA-384] */ +static const uint8_t ac_dsa_vect196_prime[] = { +/* P */ + 0xa6, 0x16, 0x7c, 0x16, 0xff, 0xf7, 0x4e, 0x29, 0x34, 0x2b, 0x85, 0x86, + 0xae, 0xd3, 0xcd, 0x89, 0x6f, 0x7b, 0x16, 0x35, 0xa2, 0x28, 0x6f, 0xf1, + 0x6f, 0xdf, 0xf4, 0x1a, 0x06, 0x31, 0x7c, 0xa6, 0xb0, 0x5c, 0xa2, 0xba, + 0x7c, 0x06, 0x0a, 0xd6, 0xdb, 0x15, 0x61, 0x62, 0x1c, 0xcb, 0x0c, 0x40, + 0xb8, 0x6a, 0x03, 0x61, 0x9b, 0xff, 0xf3, 0x2e, 0x20, 0x4c, 0xbd, 0x90, + 0xb7, 0x9d, 0xcb, 0x5f, 0x86, 0xeb, 0xb4, 0x93, 0xe3, 0xbd, 0x19, 0x88, + 0xd8, 0x09, 0x7f, 0xa2, 0x3f, 0xa4, 0xd7, 0x8f, 0xb3, 0xcd, 0xdc, 0xb0, + 0x0c, 0x46, 0x64, 0x23, 0xd8, 0xfa, 0x71, 0x98, 0x73, 0xc3, 0x76, 0x45, + 0xfe, 0x4e, 0xec, 0xc5, 0x71, 0x71, 0xbb, 0xed, 0xfe, 0x56, 0xfa, 0x94, + 0x74, 0xc9, 0x63, 0x85, 0xb8, 0xba, 0x37, 0x8c, 0x79, 0x97, 0x2d, 0x7a, + 0xaa, 0xe6, 0x9a, 0x2b, 0xa6, 0x4c, 0xde, 0x8e, 0x56, 0x54, 0xf0, 0xf7, + 0xb7, 0x45, 0x50, 0xcd, 0x34, 0x47, 0xe7, 0xa4, 0x72, 0xa3, 0x3b, 0x40, + 0x37, 0xdb, 0x46, 0x8d, 0xde, 0x31, 0xc3, 0x48, 0xaa, 0x25, 0xe8, 0x2b, + 0x7f, 0xc4, 0x1b, 0x83, 0x7f, 0x7f, 0xc2, 0x26, 0xa6, 0x10, 0x39, 0x66, + 0xec, 0xd8, 0xf9, 0xd1, 0x4c, 0x2d, 0x31, 0x49, 0x55, 0x6d, 0x43, 0x82, + 0x9f, 0x13, 0x74, 0x51, 0xb8, 0xd2, 0x0f, 0x85, 0x20, 0xb0, 0xce, 0x8e, + 0x3d, 0x70, 0x5f, 0x74, 0xd0, 0xa5, 0x7e, 0xa8, 0x72, 0xc2, 0xbd, 0xee, + 0x97, 0x14, 0xe0, 0xb6, 0x39, 0x06, 0xcd, 0xdf, 0xdc, 0x28, 0xb6, 0x77, + 0x7d, 0x19, 0x32, 0x50, 0x00, 0xf8, 0xed, 0x52, 0x78, 0xec, 0x5d, 0x91, + 0x2d, 0x10, 0x21, 0x09, 0x31, 0x9c, 0xba, 0x3b, 0x64, 0x69, 0xd4, 0x67, + 0x29, 0x09, 0xb4, 0xf0, 0xdb, 0xee, 0xc0, 0xbb, 0xb6, 0x34, 0xb5, 0x51, + 0xba, 0x0c, 0xf2, 0x13 +}; +static const uint8_t ac_dsa_vect196_sub_prime[] = { +/* Q */ + 0x84, 0x27, 0x52, 0x90, 0x44, 0xd2, 0x14, 0xc0, 0x75, 0x74, 0xf7, 0xb3, + 0x59, 0xc2, 0xe0, 0x1c, 0x23, 0xfd, 0x97, 0x70, 0x1b, 0x32, 0x8a, 0xc8, + 0xc1, 0x38, 0x5b, 0x81, 0xc5, 0x37, 0x38, 0x95 +}; +static const uint8_t ac_dsa_vect196_base[] = { +/* G */ + 0x6f, 0xc2, 0x32, 0x41, 0x5c, 0x31, 0x20, 0x0c, 0xf5, 0x23, 0xaf, 0x34, + 0x83, 0xf8, 0xe2, 0x6a, 0xce, 0x80, 0x8d, 0x2f, 0x1c, 0x6a, 0x8b, 0x86, + 0x3a, 0xb0, 0x42, 0xcc, 0x7f, 0x6b, 0x71, 0x44, 0xb2, 0xd3, 0x94, 0x72, + 0xc3, 0xcb, 0x4c, 0x76, 0x81, 0xd0, 0x73, 0x28, 0x43, 0x50, 0x3d, 0x8f, + 0x85, 0x8c, 0xbe, 0x47, 0x6e, 0x67, 0x40, 0x32, 0x4a, 0xaa, 0x29, 0x59, + 0x50, 0x10, 0x59, 0x78, 0xc3, 0x35, 0x06, 0x9b, 0x91, 0x9f, 0xf9, 0xa6, + 0xff, 0x4b, 0x41, 0x05, 0x81, 0xb8, 0x07, 0x12, 0xfe, 0x5d, 0x3e, 0x04, + 0xdd, 0xb4, 0xdf, 0xd2, 0x6d, 0x5e, 0x7f, 0xbc, 0xa2, 0xb0, 0xc5, 0x2d, + 0x8d, 0x40, 0x43, 0x43, 0xd5, 0x7b, 0x2f, 0x9b, 0x2a, 0x26, 0xda, 0xa7, + 0xec, 0xe3, 0x0c, 0xea, 0xb9, 0xe1, 0x78, 0x9f, 0x97, 0x51, 0xaa, 0xa9, + 0x38, 0x70, 0x49, 0x96, 0x5a, 0xf3, 0x26, 0x50, 0xc6, 0xca, 0x5b, 0x37, + 0x4a, 0x5a, 0xe7, 0x0b, 0x3f, 0x98, 0xe0, 0x53, 0xf5, 0x18, 0x57, 0xd6, + 0xbb, 0xb1, 0x7a, 0x67, 0x0e, 0x6e, 0xaa, 0xf8, 0x98, 0x44, 0xd6, 0x41, + 0xe1, 0xe1, 0x3d, 0x5a, 0x1b, 0x24, 0xd0, 0x53, 0xdc, 0x6b, 0x8f, 0xd1, + 0x01, 0xc6, 0x24, 0x78, 0x69, 0x51, 0x92, 0x7e, 0x42, 0x63, 0x10, 0xab, + 0xa9, 0x49, 0x8a, 0x00, 0x42, 0xb3, 0xdc, 0x7b, 0xbc, 0x59, 0xd7, 0x05, + 0xf8, 0x0d, 0x9b, 0x80, 0x7d, 0xe4, 0x15, 0xf7, 0xe9, 0x4c, 0x5c, 0xf9, + 0xd7, 0x89, 0x99, 0x2d, 0x3b, 0xb8, 0x33, 0x6d, 0x1d, 0x80, 0x8c, 0xb8, + 0x6b, 0x56, 0xdd, 0xe0, 0x9d, 0x93, 0x4b, 0xb5, 0x27, 0x03, 0x39, 0x22, + 0xde, 0x14, 0xbf, 0x30, 0x73, 0x76, 0xab, 0x7d, 0x22, 0xfb, 0xcd, 0x61, + 0x6f, 0x9e, 0xda, 0x47, 0x9a, 0xb2, 0x14, 0xa1, 0x78, 0x50, 0xbd, 0xd0, + 0x80, 0x2a, 0x87, 0x1c +}; +static const uint8_t ac_dsa_vect196_ptx[] = { +/* Msg */ + 0x8c, 0x78, 0xcf, 0xfd, 0xcf, 0x25, 0xd8, 0x23, 0x0b, 0x83, 0x5b, 0x30, + 0x51, 0x26, 0x84, 0xc9, 0xb2, 0x52, 0x11, 0x58, 0x70, 0xb6, 0x03, 0xd1, + 0xb4, 0xba, 0x2e, 0xb5, 0xd3, 0x5b, 0x33, 0xf2, 0x6d, 0x96, 0xb6, 0x84, + 0x12, 0x6e, 0xc3, 0x4f, 0xff, 0x67, 0xdf, 0xe5, 0xc8, 0xc8, 0x56, 0xac, + 0xfe, 0x3a, 0x9f, 0xf4, 0x5a, 0xe1, 0x1d, 0x41, 0x5f, 0x30, 0x44, 0x9b, + 0xcd, 0xc3, 0xbf, 0x9a, 0x9f, 0xb5, 0xa7, 0xe4, 0x8a, 0xfe, 0xab, 0xa6, + 0xd0, 0xb0, 0xfc, 0x9b, 0xce, 0x01, 0x97, 0xeb, 0x2b, 0xf7, 0xa8, 0x40, + 0x24, 0x9d, 0x4e, 0x55, 0x0c, 0x5a, 0x25, 0xdc, 0x1c, 0x71, 0x37, 0x0e, + 0x67, 0x93, 0x3e, 0xda, 0xd2, 0x36, 0x2f, 0xae, 0x6f, 0xad, 0x1e, 0xfb, + 0xa5, 0xc0, 0x8d, 0xc1, 0x93, 0x1c, 0xa2, 0x84, 0x1b, 0x44, 0xb7, 0x8c, + 0x0c, 0x63, 0xa1, 0x66, 0x5f, 0xfa, 0xc8, 0x60 +}; +static const uint8_t ac_dsa_vect196_priv_val[] = { +/* X */ + 0x45, 0x9e, 0xb1, 0x58, 0x8e, 0x9f, 0x7d, 0xd4, 0xf2, 0x86, 0x67, 0x7a, + 0x74, 0x15, 0xcb, 0x25, 0xa1, 0xb4, 0x6e, 0x7a, 0x7c, 0xfa, 0xdc, 0x8a, + 0x45, 0x10, 0x03, 0x83, 0xe2, 0x0d, 0xa6, 0x9d +}; +static const uint8_t ac_dsa_vect196_pub_val[] = { +/* Y */ + 0x5c, 0xa7, 0x15, 0x1b, 0xca, 0x0e, 0x45, 0x7b, 0xbc, 0x46, 0xf5, 0x9f, + 0x71, 0xd8, 0x1a, 0xb1, 0x66, 0x88, 0xdc, 0x0e, 0xb7, 0xe4, 0xd1, 0x7b, + 0x16, 0x6c, 0x33, 0x26, 0xc5, 0xb1, 0x2c, 0x5b, 0xde, 0xbb, 0x36, 0x13, + 0x22, 0x4d, 0x1a, 0x75, 0x40, 0x23, 0xc5, 0x0b, 0x83, 0xcb, 0x5e, 0xcc, + 0x13, 0x90, 0x96, 0xce, 0xf2, 0x89, 0x33, 0xb3, 0xb1, 0x2c, 0xa3, 0x10, + 0x38, 0xe4, 0x08, 0x93, 0x83, 0x59, 0x7c, 0x59, 0xcc, 0x27, 0xb9, 0x02, + 0xbe, 0x5d, 0xa6, 0x2c, 0xae, 0x7d, 0xa5, 0xf4, 0xaf, 0x90, 0xe9, 0x41, + 0x0e, 0xd1, 0x60, 0x40, 0x82, 0xe2, 0xe3, 0x8e, 0x25, 0xeb, 0x0b, 0x78, + 0xdf, 0xac, 0x0a, 0xeb, 0x2a, 0xd3, 0xb1, 0x9d, 0xc2, 0x35, 0x39, 0xd2, + 0xbc, 0xd7, 0x55, 0xdb, 0x1c, 0xc6, 0xc9, 0x80, 0x5a, 0x7d, 0xd1, 0x09, + 0xe1, 0xc9, 0x86, 0x67, 0xa5, 0xb9, 0xd5, 0x2b, 0x21, 0xc2, 0x77, 0x21, + 0x21, 0xb8, 0xd0, 0xd2, 0xb2, 0x46, 0xe5, 0xfd, 0x3d, 0xa8, 0x07, 0x28, + 0xe8, 0x5b, 0xbf, 0x0d, 0x70, 0x67, 0xd1, 0xc6, 0xba, 0xa6, 0x43, 0x94, + 0xa2, 0x9e, 0x7f, 0xcb, 0xf8, 0x08, 0x42, 0xbd, 0x4a, 0xb0, 0x2b, 0x35, + 0xd8, 0x3f, 0x59, 0x80, 0x5a, 0x10, 0x4e, 0x0b, 0xd6, 0x9d, 0x00, 0x79, + 0xa0, 0x65, 0xf5, 0x9e, 0x3e, 0x6f, 0x21, 0x57, 0x3a, 0x00, 0xda, 0x99, + 0x0b, 0x72, 0xea, 0x53, 0x7f, 0xa9, 0x8c, 0xaa, 0xa0, 0xa5, 0x88, 0x00, + 0xa7, 0xe7, 0xa0, 0x62, 0x3e, 0x26, 0x3d, 0x4f, 0xca, 0x65, 0xeb, 0xb8, + 0xed, 0xed, 0x46, 0xef, 0xdf, 0xe7, 0xdb, 0x92, 0xc9, 0xeb, 0xd3, 0x80, + 0x62, 0xd8, 0xf1, 0x25, 0x34, 0xf0, 0x15, 0xb1, 0x86, 0x18, 0x6e, 0xe2, + 0x36, 0x1d, 0x62, 0xc2, 0x4e, 0x4f, 0x22, 0xb3, 0xe9, 0x5d, 0xa0, 0xf9, + 0x06, 0x2c, 0xe0, 0x4d +}; +/* K = 2368037a1c7647c683d7e301ac79b7feebc736effe3ab1644b68308b4b28620d */ +static const uint8_t ac_dsa_vect196_out[] = { +/* R */ + 0x4f, 0xd8, 0xf2, 0x5c, 0x05, 0x90, 0x30, 0x02, 0x73, 0x81, 0xd4, 0x16, + 0x7c, 0x31, 0x74, 0xb6, 0xbe, 0x00, 0x88, 0xc1, 0x5f, 0x0a, 0x57, 0x3d, + 0x7e, 0xbd, 0x05, 0x96, 0x0f, 0x5a, 0x1e, 0xb2, +/* S */ + 0x5f, 0x56, 0x86, 0x9c, 0xee, 0x7b, 0xf6, 0x4f, 0xec, 0x5d, 0x5d, 0x6e, + 0xa1, 0x5b, 0xb1, 0xfa, 0x11, 0x69, 0x00, 0x3a, 0x87, 0xec, 0xcc, 0x16, + 0x21, 0xb9, 0x0a, 0x1b, 0x89, 0x22, 0x26, 0xf2 +}; +#define ac_dsa_vect197_prime ac_dsa_vect196_prime +#define ac_dsa_vect197_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect197_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect197_ptx[] = { +/* Msg */ + 0x02, 0xbb, 0x64, 0xd2, 0xd5, 0x03, 0x2f, 0x54, 0xf1, 0xac, 0x9e, 0x9e, + 0xe1, 0x64, 0xdb, 0x83, 0xaf, 0x0c, 0xb0, 0x36, 0xd8, 0x8d, 0x41, 0xe9, + 0xb2, 0x11, 0x8c, 0xfc, 0x39, 0xd1, 0xb4, 0xb4, 0xdc, 0x2c, 0x49, 0x75, + 0x49, 0xc7, 0x98, 0x2c, 0xca, 0xcf, 0x66, 0x5d, 0x1b, 0x00, 0x11, 0x26, + 0x82, 0x46, 0xc7, 0xc1, 0x7f, 0x56, 0x2e, 0xcb, 0xa2, 0x5e, 0x26, 0x54, + 0x89, 0x87, 0x3e, 0x0d, 0xd9, 0x26, 0x8e, 0x9b, 0x06, 0x88, 0x0b, 0xa7, + 0x4e, 0x74, 0xb5, 0x6f, 0x50, 0xc7, 0x32, 0x4d, 0x29, 0x37, 0x38, 0x53, + 0xe3, 0xa0, 0xf3, 0xff, 0x78, 0x7e, 0xba, 0x4e, 0x5e, 0x7f, 0x94, 0x37, + 0xf8, 0xec, 0x8a, 0x5e, 0x86, 0x83, 0x24, 0xe9, 0xc1, 0x7f, 0xb3, 0xd0, + 0xe1, 0x2d, 0xe2, 0xd3, 0x1d, 0x43, 0x8c, 0x5b, 0xf3, 0x8b, 0x27, 0x16, + 0x7d, 0x43, 0xae, 0x43, 0x11, 0xb1, 0x10, 0x62 +}; +static const uint8_t ac_dsa_vect197_priv_val[] = { +/* X */ + 0x52, 0x1f, 0x08, 0xc1, 0x07, 0x74, 0x07, 0x7a, 0xc1, 0x5b, 0xc8, 0x5f, + 0x2f, 0x6a, 0x03, 0xd8, 0x42, 0x07, 0xb4, 0xed, 0x7b, 0xff, 0xec, 0xc3, + 0x5d, 0x73, 0x0c, 0xdd, 0x11, 0x26, 0x87, 0x7f +}; +static const uint8_t ac_dsa_vect197_pub_val[] = { +/* Y */ + 0x11, 0xf3, 0xa7, 0x16, 0xfb, 0xda, 0x7a, 0xf3, 0x5b, 0xdb, 0x62, 0xd1, + 0x28, 0xaf, 0x6f, 0x21, 0xec, 0x2e, 0xd4, 0x89, 0x6a, 0xa8, 0x1e, 0x87, + 0x69, 0xc6, 0xee, 0xa9, 0xc2, 0x1c, 0x81, 0xae, 0xf2, 0x3a, 0xe0, 0xf5, + 0x25, 0x26, 0x9d, 0xc4, 0x05, 0xac, 0xce, 0xf0, 0x98, 0x37, 0x7f, 0x65, + 0x27, 0x30, 0x96, 0x8a, 0x33, 0xb5, 0x0f, 0x0a, 0x4c, 0x77, 0x84, 0x34, + 0x52, 0x80, 0x65, 0x1c, 0xaa, 0x03, 0x4d, 0xf8, 0x73, 0x42, 0xca, 0x89, + 0x73, 0xad, 0x86, 0xff, 0x7f, 0x0f, 0x87, 0x73, 0xa9, 0x4f, 0x95, 0xdd, + 0x2b, 0xfa, 0x80, 0x2d, 0x26, 0x8d, 0xbf, 0x3a, 0x21, 0x03, 0xb1, 0x27, + 0x6e, 0x06, 0xdb, 0x2d, 0x73, 0x43, 0x99, 0xf2, 0xab, 0x7b, 0xdc, 0xca, + 0x09, 0x76, 0x16, 0xfc, 0x46, 0xed, 0x24, 0x78, 0xe5, 0x2c, 0xef, 0x04, + 0x9d, 0x19, 0x44, 0x45, 0x86, 0xe7, 0xb7, 0x5d, 0x6a, 0x56, 0x74, 0x1d, + 0xa2, 0x27, 0x0f, 0x54, 0xd2, 0xc7, 0x39, 0xec, 0x8d, 0xb9, 0x96, 0xc7, + 0x1f, 0x06, 0xa3, 0x9a, 0xf2, 0x38, 0x3c, 0x61, 0x14, 0x99, 0xbe, 0x0f, + 0xb3, 0x48, 0x09, 0xb1, 0x71, 0x25, 0x4e, 0xf2, 0x73, 0x51, 0x6c, 0x33, + 0xe1, 0x7e, 0x14, 0x04, 0x8e, 0xf2, 0xd2, 0x1d, 0x60, 0x0a, 0xa1, 0x53, + 0xbc, 0xf7, 0x37, 0x7f, 0xba, 0x94, 0x05, 0xc6, 0xb2, 0xe5, 0xf2, 0xaa, + 0xf0, 0xf2, 0xf3, 0x46, 0x7d, 0x74, 0x61, 0xf6, 0x2e, 0x81, 0x4a, 0x2c, + 0x46, 0x1e, 0x8a, 0xc9, 0xdb, 0x0d, 0xf3, 0x70, 0xe1, 0x8e, 0xc6, 0xee, + 0xd8, 0x21, 0x2a, 0xca, 0xec, 0xf1, 0xe7, 0x24, 0x1b, 0xcb, 0xcb, 0xca, + 0x67, 0x10, 0x60, 0xe5, 0x0c, 0x29, 0xf9, 0x66, 0xf1, 0xea, 0x1e, 0x92, + 0xaf, 0x69, 0x03, 0xf8, 0x1c, 0x7a, 0xb9, 0xee, 0x09, 0xf6, 0x05, 0x77, + 0xbf, 0x30, 0xc1, 0x86 +}; +/* K = 08b161571ed031152677136b54e87119133f7de56268aec07cba07667b98bcd8 */ +static const uint8_t ac_dsa_vect197_out[] = { +/* R */ + 0x7a, 0x5d, 0x20, 0x16, 0xaf, 0xe8, 0x78, 0x83, 0x49, 0x1b, 0xd6, 0xcd, + 0x16, 0x6e, 0xdd, 0xdf, 0x13, 0x8c, 0x1c, 0x89, 0x96, 0x1e, 0x4a, 0xf6, + 0x87, 0x6b, 0xe0, 0x8b, 0x0e, 0x06, 0xad, 0x74, +/* S */ + 0x34, 0xef, 0xbd, 0xa1, 0x84, 0x9d, 0xed, 0xd0, 0xd1, 0xaa, 0x77, 0x5d, + 0xab, 0x2a, 0xa2, 0xb1, 0x4c, 0x9b, 0xa0, 0x20, 0x65, 0x92, 0xfb, 0xc3, + 0x4e, 0xb4, 0x7b, 0x84, 0x46, 0x46, 0xad, 0xc2 +}; +#define ac_dsa_vect198_prime ac_dsa_vect196_prime +#define ac_dsa_vect198_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect198_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect198_ptx[] = { +/* Msg */ + 0x4f, 0x1c, 0x00, 0x53, 0x98, 0x4a, 0xb5, 0x5a, 0x49, 0x1f, 0x36, 0x18, + 0xdb, 0x1b, 0xe2, 0x37, 0x91, 0x74, 0xa4, 0x38, 0x59, 0x74, 0x82, 0x5f, + 0xcb, 0xe5, 0x84, 0xe2, 0xb6, 0xd0, 0x70, 0x2a, 0xbb, 0x82, 0x98, 0xdd, + 0x91, 0x84, 0xee, 0xf1, 0x74, 0x0b, 0x90, 0xa5, 0xea, 0xe8, 0x50, 0xe9, + 0x45, 0x2b, 0x4e, 0x4a, 0xb2, 0x19, 0xe1, 0x87, 0x86, 0x0f, 0x0f, 0xb4, + 0xad, 0x2b, 0xe3, 0x90, 0xef, 0x2b, 0xa7, 0xd7, 0x6c, 0xde, 0xdc, 0xaf, + 0x10, 0xae, 0xaf, 0x4f, 0x25, 0xe4, 0x97, 0xb4, 0xda, 0x95, 0x13, 0x75, + 0xb6, 0x87, 0xa8, 0xd6, 0x70, 0x12, 0xd3, 0xf9, 0x9c, 0x7b, 0x5c, 0xa8, + 0x2e, 0x9b, 0xd0, 0x63, 0x0d, 0xff, 0xcd, 0x63, 0x5e, 0xcd, 0x82, 0x09, + 0xcd, 0xdb, 0x87, 0x2d, 0xa5, 0xbf, 0x47, 0x36, 0x30, 0x97, 0x83, 0x34, + 0x5a, 0x35, 0x37, 0x6b, 0x4f, 0xce, 0x4b, 0x91 +}; +static const uint8_t ac_dsa_vect198_priv_val[] = { +/* X */ + 0x6b, 0xa8, 0xf6, 0x63, 0x83, 0x16, 0xdd, 0x80, 0x4a, 0x24, 0xb7, 0x39, + 0x0f, 0x31, 0x02, 0x3c, 0xd8, 0xb2, 0x6e, 0x93, 0x25, 0xbe, 0x90, 0x94, + 0x1b, 0x90, 0xd5, 0xfd, 0x31, 0x55, 0x11, 0x5a +}; +static const uint8_t ac_dsa_vect198_pub_val[] = { +/* Y */ + 0x10, 0xe6, 0xf5, 0x0f, 0xd6, 0xdb, 0xb1, 0xca, 0x16, 0xf2, 0xdf, 0x51, + 0x32, 0xa4, 0xa4, 0xea, 0xbc, 0x51, 0xda, 0x4a, 0x58, 0xfe, 0x61, 0x9b, + 0x22, 0x25, 0xd7, 0xad, 0xab, 0x0c, 0xea, 0x3a, 0xfc, 0x2d, 0xb9, 0x0b, + 0x15, 0x8b, 0x62, 0x31, 0xc8, 0xb0, 0x77, 0x4e, 0x0f, 0x0d, 0x90, 0x74, + 0x51, 0x7f, 0x33, 0x6c, 0xa0, 0x53, 0xae, 0x11, 0x56, 0x71, 0xae, 0xe3, + 0xc1, 0xde, 0x0f, 0x85, 0x72, 0x8c, 0xff, 0x99, 0xde, 0xeb, 0xc0, 0x7f, + 0xfc, 0x9a, 0x63, 0x63, 0x19, 0x89, 0xa9, 0x27, 0x7e, 0x64, 0xc5, 0x4d, + 0x9c, 0x25, 0xa7, 0xe7, 0x39, 0xae, 0x92, 0xf7, 0x06, 0xee, 0x23, 0x7b, + 0x98, 0xb8, 0x70, 0x0a, 0x9d, 0xf0, 0xde, 0x12, 0xd2, 0x12, 0x4e, 0x2c, + 0xfd, 0x81, 0xd9, 0xec, 0x7b, 0x04, 0x69, 0xee, 0x3a, 0x71, 0x8a, 0xb1, + 0x53, 0x05, 0xde, 0x09, 0x9d, 0x9a, 0x2f, 0x8c, 0xec, 0xb7, 0x95, 0x27, + 0xd0, 0x16, 0x44, 0x7c, 0x8f, 0x6f, 0xe4, 0x90, 0x5c, 0x37, 0x18, 0xce, + 0x52, 0x34, 0xd1, 0x3b, 0xf4, 0xed, 0xd7, 0x16, 0x9b, 0x9d, 0x0d, 0xb9, + 0xa6, 0xb0, 0xfc, 0x77, 0xb7, 0xd5, 0x3b, 0xdd, 0x32, 0xb0, 0x7d, 0xc1, + 0x5b, 0xc8, 0x29, 0x62, 0x0d, 0xb0, 0x85, 0x11, 0x45, 0x81, 0x60, 0x8a, + 0xc9, 0xe0, 0x93, 0x77, 0x52, 0x09, 0x59, 0x51, 0xd2, 0x89, 0x85, 0x5d, + 0x0b, 0xcc, 0x9d, 0x42, 0x1b, 0x94, 0x5c, 0xc4, 0xf3, 0x7f, 0x80, 0xb0, + 0xcb, 0x25, 0xf1, 0xff, 0xee, 0x9c, 0x61, 0xe5, 0x67, 0xf4, 0x9d, 0x21, + 0xf8, 0x89, 0xec, 0xbc, 0x3f, 0x4e, 0xd3, 0x37, 0xbc, 0xa6, 0x66, 0xba, + 0x3b, 0xa6, 0x84, 0x87, 0x4c, 0x88, 0x3f, 0xe2, 0x28, 0xac, 0x44, 0x95, + 0x2a, 0x85, 0x13, 0xe1, 0x2d, 0x9f, 0x0c, 0x4e, 0xd4, 0x3c, 0x9b, 0x60, + 0xf3, 0x52, 0x25, 0xb2 +}; +/* K = 2a4a4e014c94d8546c62f0db2fd488f5fac03073a11c3760376114ab3201930d */ +static const uint8_t ac_dsa_vect198_out[] = { +/* R */ + 0x00, 0x6b, 0x75, 0x9f, 0xb7, 0x18, 0xc3, 0x4f, 0x1a, 0x6e, 0x51, 0x8f, + 0x83, 0x40, 0x53, 0xb9, 0xf1, 0x82, 0x5d, 0xd3, 0xeb, 0x8d, 0x71, 0x94, + 0x65, 0xc7, 0xbc, 0xc8, 0x30, 0x32, 0x2f, 0x4b, +/* S */ + 0x47, 0xfa, 0x59, 0x85, 0x2c, 0x9a, 0xe5, 0xe1, 0x81, 0x38, 0x1e, 0x34, + 0x57, 0xa3, 0x3b, 0x25, 0x42, 0x00, 0x11, 0xd6, 0xf9, 0x11, 0xef, 0xa9, + 0x0f, 0x3e, 0xac, 0xed, 0x1d, 0xee, 0x13, 0x29 +}; +#define ac_dsa_vect199_prime ac_dsa_vect196_prime +#define ac_dsa_vect199_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect199_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect199_ptx[] = { +/* Msg */ + 0x42, 0x19, 0x91, 0x86, 0x43, 0x4d, 0x6c, 0x55, 0xbc, 0xef, 0x26, 0x9b, + 0xee, 0x68, 0x5c, 0x4e, 0x15, 0x80, 0xe2, 0x43, 0x02, 0x7e, 0xd1, 0x28, + 0xca, 0x99, 0x49, 0x20, 0x33, 0xa5, 0x29, 0x54, 0xbd, 0x1c, 0xa8, 0xec, + 0xc5, 0x04, 0x38, 0x20, 0x72, 0x5a, 0x3c, 0x0d, 0x71, 0xa1, 0x81, 0xa0, + 0x5a, 0xab, 0xcb, 0x4e, 0xcd, 0xa7, 0x18, 0x0d, 0x86, 0x85, 0x5e, 0x7b, + 0x4d, 0xfa, 0x9a, 0x44, 0xc7, 0xaf, 0x4c, 0x98, 0xfb, 0xf1, 0xf0, 0x62, + 0x40, 0x58, 0x80, 0x4f, 0xd8, 0xea, 0xae, 0x49, 0x90, 0xd4, 0xd7, 0xbb, + 0x75, 0xf0, 0x17, 0x41, 0xce, 0x36, 0xcf, 0xc9, 0xc1, 0x37, 0x25, 0x4c, + 0xab, 0x06, 0x5a, 0x46, 0x17, 0xd0, 0xd0, 0xcd, 0x5f, 0x58, 0xea, 0x56, + 0x86, 0x8a, 0x40, 0xf3, 0xe0, 0xba, 0xf7, 0xdb, 0x5d, 0x25, 0x57, 0xf4, + 0xb9, 0x77, 0x5c, 0x18, 0x20, 0xdc, 0x1d, 0x41 +}; +static const uint8_t ac_dsa_vect199_priv_val[] = { +/* X */ + 0x46, 0xd6, 0x90, 0xca, 0x6b, 0x9c, 0xc0, 0x1e, 0x9a, 0x8c, 0x7b, 0xfd, + 0xed, 0xc5, 0x9a, 0x97, 0xeb, 0xa5, 0x2f, 0x09, 0x7b, 0x8f, 0xdc, 0x19, + 0xbc, 0x1f, 0x8c, 0x0a, 0xb5, 0xd4, 0xbf, 0xdb +}; +static const uint8_t ac_dsa_vect199_pub_val[] = { +/* Y */ + 0x63, 0x64, 0xa3, 0x5a, 0xe9, 0x94, 0xf2, 0x77, 0x03, 0x31, 0x9c, 0x36, + 0xd9, 0x07, 0x93, 0xc8, 0xf2, 0x65, 0x11, 0x84, 0x6b, 0xa0, 0x60, 0x38, + 0x99, 0x5b, 0x65, 0x56, 0xe4, 0x44, 0x3a, 0xa6, 0x1e, 0xb0, 0xf8, 0xef, + 0xcc, 0x3d, 0x47, 0xf7, 0xc5, 0xf8, 0x52, 0x76, 0xea, 0x92, 0x1d, 0xa0, + 0x78, 0x4a, 0x67, 0x99, 0x82, 0x53, 0xc9, 0x92, 0x97, 0x5f, 0x9e, 0x13, + 0x84, 0x7c, 0xca, 0xd0, 0x99, 0xd9, 0xc1, 0xe5, 0xc9, 0x4c, 0xfb, 0x19, + 0x54, 0x88, 0xe1, 0x29, 0x3e, 0x23, 0xb7, 0x4d, 0xb0, 0x06, 0x03, 0xe8, + 0xbd, 0x68, 0x14, 0xc9, 0x46, 0x90, 0xbf, 0x0c, 0xcc, 0xc1, 0xc0, 0xe4, + 0x7f, 0x0c, 0x66, 0x09, 0xa4, 0x8e, 0x14, 0x45, 0x87, 0xec, 0xe1, 0x78, + 0xf7, 0x2c, 0x85, 0x14, 0xa4, 0x35, 0x90, 0xbc, 0x4c, 0x21, 0x9d, 0xa9, + 0x5c, 0xbe, 0x89, 0x66, 0xf4, 0x40, 0x4f, 0xe9, 0xc2, 0x88, 0xf2, 0x3c, + 0xd0, 0xf9, 0x73, 0xe7, 0x7e, 0xc8, 0x4b, 0x4b, 0x0f, 0x16, 0x3b, 0x50, + 0xa3, 0xc5, 0x56, 0xcd, 0x1d, 0x39, 0x51, 0xfa, 0xeb, 0xd9, 0x82, 0xaf, + 0x44, 0x44, 0x7e, 0x60, 0xd7, 0x83, 0x4b, 0x93, 0xb6, 0xd9, 0xc3, 0xff, + 0x09, 0x61, 0xfc, 0xcb, 0x90, 0x83, 0x12, 0xa2, 0x43, 0x76, 0xee, 0xdc, + 0x50, 0x8f, 0x80, 0x66, 0x68, 0xd6, 0x61, 0x7b, 0x77, 0x49, 0x1a, 0x01, + 0xd5, 0xd0, 0x69, 0xd6, 0xcc, 0xd5, 0xf2, 0x1b, 0x5e, 0xb3, 0xc3, 0xa3, + 0xd4, 0xa0, 0x47, 0x95, 0x93, 0x84, 0x5c, 0x72, 0xf7, 0x20, 0x15, 0x7b, + 0x18, 0x8d, 0x2d, 0xfa, 0xe4, 0x40, 0x1c, 0x57, 0xa6, 0x00, 0xb1, 0x42, + 0xb6, 0xbd, 0xe2, 0xa6, 0x9f, 0x1a, 0x0a, 0xfb, 0xa2, 0xf5, 0x07, 0xa6, + 0x3c, 0xd6, 0xdf, 0x05, 0x6b, 0xb5, 0xb3, 0x4f, 0xdf, 0xce, 0xe0, 0x12, + 0xd3, 0x41, 0xb3, 0xf1 +}; +/* K = 638e5fd0885f4c9f7e5f4e6a103b2d2d9d1368c493f9822ef431f54e65a7a3be */ +static const uint8_t ac_dsa_vect199_out[] = { +/* R */ + 0x25, 0x51, 0xd4, 0xf8, 0x55, 0x17, 0x4f, 0x7b, 0x28, 0xa7, 0x82, 0xb8, + 0x96, 0x97, 0xd4, 0x8f, 0xbc, 0x31, 0x4c, 0xfe, 0xb1, 0x7e, 0xc4, 0xc9, + 0x90, 0x2a, 0x8e, 0x55, 0x7c, 0xc6, 0xf6, 0xb9, +/* S */ + 0x27, 0x8b, 0x78, 0x6f, 0x9e, 0x28, 0xee, 0xcc, 0xd0, 0x05, 0x86, 0xb4, + 0x45, 0xe7, 0x5f, 0x48, 0xcf, 0x26, 0x49, 0xf3, 0xf1, 0xb7, 0xbf, 0xf7, + 0x2b, 0x0e, 0x76, 0x7f, 0x34, 0x43, 0xdc, 0x58 +}; +#define ac_dsa_vect200_prime ac_dsa_vect196_prime +#define ac_dsa_vect200_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect200_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect200_ptx[] = { +/* Msg */ + 0x4f, 0xdd, 0x88, 0x87, 0x56, 0xac, 0x68, 0xf4, 0xc2, 0x9c, 0xd5, 0xb1, + 0xde, 0x42, 0x75, 0x67, 0x94, 0x57, 0x0c, 0xa8, 0xf1, 0x8f, 0xf7, 0x95, + 0xf6, 0xf0, 0xfc, 0x85, 0x67, 0x72, 0xb6, 0xa2, 0x18, 0x9b, 0x5e, 0xd4, + 0xa9, 0xb7, 0x54, 0x73, 0x28, 0x07, 0x5b, 0x56, 0xc2, 0x8d, 0xdf, 0x50, + 0xb8, 0x4c, 0x27, 0x20, 0x5c, 0xee, 0x57, 0xb2, 0x9d, 0x0b, 0x38, 0x79, + 0x70, 0xe8, 0x9a, 0x6a, 0x22, 0x36, 0x29, 0x3b, 0xbc, 0x9e, 0x39, 0x90, + 0x13, 0xd1, 0xdd, 0x3b, 0xd5, 0xa1, 0x0a, 0xb0, 0xd2, 0x59, 0xf7, 0xfd, + 0xa7, 0x04, 0xf7, 0x1c, 0xbe, 0x3b, 0x8b, 0x87, 0x52, 0x80, 0x6a, 0x0c, + 0x84, 0x66, 0x8d, 0x85, 0xe4, 0xd7, 0x39, 0xce, 0xc6, 0x28, 0xdf, 0xf6, + 0x33, 0x71, 0xd2, 0x4a, 0x4b, 0x14, 0x13, 0x73, 0x82, 0x75, 0x9b, 0xa4, + 0x00, 0xdf, 0x0e, 0x2c, 0x25, 0x94, 0x7d, 0x18 +}; +static const uint8_t ac_dsa_vect200_priv_val[] = { +/* X */ + 0x49, 0xda, 0x89, 0xd1, 0x67, 0x37, 0x04, 0xd1, 0xf2, 0x4a, 0xc7, 0xdc, + 0x79, 0x9b, 0xf0, 0x06, 0xaa, 0x7d, 0x60, 0x6c, 0x59, 0x0e, 0x5e, 0x37, + 0xe3, 0x80, 0x32, 0xec, 0x51, 0xa7, 0x03, 0x76 +}; +static const uint8_t ac_dsa_vect200_pub_val[] = { +/* Y */ + 0x5b, 0x61, 0x98, 0x45, 0xba, 0x96, 0x9f, 0x1c, 0xa5, 0x96, 0x3f, 0xcf, + 0x04, 0xc0, 0x3a, 0xa4, 0x0e, 0x98, 0x92, 0x22, 0x77, 0x4e, 0x95, 0x7a, + 0x54, 0x19, 0x1a, 0xcf, 0x9d, 0xdc, 0x40, 0x7a, 0x54, 0xa1, 0x61, 0xe2, + 0x2a, 0x5a, 0xc5, 0x0c, 0xa5, 0xd6, 0x1e, 0x66, 0x01, 0xcc, 0x79, 0x95, + 0xbf, 0x0d, 0xb3, 0x8f, 0xf0, 0xfa, 0x1f, 0x77, 0xb2, 0x44, 0xfe, 0x98, + 0x14, 0x8c, 0x81, 0xf2, 0x08, 0xdc, 0xa2, 0x9f, 0xfa, 0x30, 0xf1, 0x13, + 0x1c, 0x76, 0xdb, 0xbe, 0x43, 0x03, 0x42, 0x5e, 0x91, 0x80, 0xb4, 0xa4, + 0x8f, 0x22, 0xc7, 0x57, 0xed, 0x8e, 0x38, 0x8b, 0x61, 0xbd, 0xc6, 0xd5, + 0x55, 0x19, 0x52, 0x3d, 0x00, 0xc3, 0x1a, 0x5f, 0x83, 0x76, 0x64, 0x0d, + 0x46, 0x88, 0xe6, 0x0d, 0xcc, 0x17, 0x2d, 0xee, 0xce, 0x73, 0xde, 0x28, + 0x43, 0x7e, 0x90, 0x0c, 0xb1, 0x9a, 0x53, 0x11, 0xa0, 0xc9, 0xca, 0x9a, + 0xf6, 0xcc, 0x6e, 0xeb, 0x68, 0x44, 0xe9, 0xb8, 0x35, 0x9e, 0x3e, 0xf1, + 0xcb, 0xe0, 0x37, 0x84, 0x10, 0x7d, 0x2d, 0x0a, 0xeb, 0xec, 0x7c, 0x1d, + 0x70, 0xd9, 0x38, 0x5a, 0x4d, 0x2b, 0x80, 0x33, 0x85, 0x1f, 0x5d, 0x5b, + 0x7a, 0xa1, 0x8e, 0xf5, 0x70, 0xaa, 0x03, 0x7f, 0xcb, 0xd3, 0xe3, 0x0f, + 0x2f, 0xc2, 0x01, 0x3f, 0xfb, 0xfa, 0x07, 0x87, 0xbe, 0x6d, 0x59, 0xff, + 0xa1, 0x61, 0x6e, 0xed, 0x5e, 0x12, 0x1e, 0xe4, 0xdb, 0xee, 0x04, 0xa9, + 0xed, 0xe0, 0x04, 0x95, 0x60, 0x75, 0x46, 0x5a, 0x76, 0x88, 0x70, 0x1e, + 0x04, 0xec, 0x9b, 0x21, 0x53, 0xf5, 0x2c, 0xaf, 0xbf, 0xf7, 0xff, 0x92, + 0x26, 0xe6, 0x93, 0x97, 0xc7, 0x08, 0x3c, 0x3a, 0xa5, 0x36, 0xd7, 0x10, + 0x9e, 0xe4, 0x30, 0xa6, 0x54, 0x48, 0xb1, 0x0c, 0x18, 0x18, 0xc7, 0x05, + 0x10, 0xa3, 0x39, 0xc1 +}; +/* K = 14dca45937cfdbca5c799f2ca50de2a44d8051e6d80af242c9f4d614419e6e07 */ +static const uint8_t ac_dsa_vect200_out[] = { +/* R */ + 0x4b, 0x90, 0x99, 0x3d, 0x70, 0x7f, 0x33, 0x71, 0xd0, 0xa0, 0xcc, 0x87, + 0x25, 0x5e, 0x99, 0xa8, 0xfb, 0xa1, 0x8c, 0x3b, 0x58, 0xdd, 0xdd, 0xc1, + 0x06, 0x7c, 0xd3, 0x94, 0x17, 0x23, 0x66, 0xcc, +/* S */ + 0x4b, 0x26, 0x12, 0xd5, 0x06, 0xfb, 0x85, 0xe5, 0xaf, 0xf9, 0xfc, 0xd5, + 0x6c, 0x09, 0xbd, 0x12, 0xbf, 0x60, 0xf7, 0x8a, 0xb7, 0xdf, 0xd0, 0x21, + 0xa7, 0x42, 0xff, 0x85, 0xdc, 0x50, 0x7a, 0xe2 +}; +#define ac_dsa_vect201_prime ac_dsa_vect196_prime +#define ac_dsa_vect201_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect201_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect201_ptx[] = { +/* Msg */ + 0x85, 0x07, 0xdb, 0x5f, 0x1d, 0xf9, 0xd2, 0x2f, 0x44, 0x7c, 0x20, 0xe4, + 0x32, 0x0f, 0x90, 0xd9, 0xb3, 0x07, 0x22, 0x19, 0x71, 0x96, 0xd1, 0xa2, + 0x41, 0x8d, 0x06, 0xdc, 0xa4, 0x1b, 0x33, 0x05, 0xf6, 0xfb, 0xe5, 0x2a, + 0xb5, 0x8c, 0xc0, 0xb6, 0x0e, 0xf1, 0xa1, 0xd2, 0x57, 0xfc, 0x2f, 0xb2, + 0x06, 0x2f, 0xe6, 0xc5, 0xf2, 0xa2, 0x5f, 0x02, 0x93, 0xca, 0x39, 0xd0, + 0xc0, 0x83, 0xcf, 0xd5, 0xe4, 0xbd, 0xad, 0xf2, 0x16, 0x9a, 0xd4, 0xed, + 0x17, 0x8c, 0x88, 0xec, 0xb5, 0x55, 0x4f, 0xfa, 0x2b, 0x53, 0xaa, 0x43, + 0x98, 0x11, 0x5c, 0xde, 0x62, 0x7d, 0x30, 0x14, 0x4a, 0xce, 0x93, 0x25, + 0xb2, 0xd7, 0x9d, 0x7d, 0xce, 0x95, 0x15, 0x09, 0xd7, 0x34, 0xaf, 0xb0, + 0xff, 0x6d, 0x92, 0x65, 0xb9, 0x02, 0x67, 0x2e, 0xb5, 0x88, 0x4e, 0x9d, + 0x8a, 0xcf, 0xf0, 0xea, 0x22, 0xc7, 0x69, 0x38 +}; +static const uint8_t ac_dsa_vect201_priv_val[] = { +/* X */ + 0x82, 0xab, 0x29, 0x08, 0xe3, 0xd2, 0x33, 0x5e, 0x07, 0xc1, 0x00, 0x27, + 0x64, 0xb0, 0x7b, 0x1c, 0xa4, 0x6d, 0x03, 0x9a, 0x95, 0xb5, 0x9b, 0x45, + 0x0b, 0x16, 0xd3, 0x7e, 0xd4, 0x83, 0x88, 0x72 +}; +static const uint8_t ac_dsa_vect201_pub_val[] = { +/* Y */ + 0x43, 0x88, 0x31, 0xcb, 0x0e, 0xb0, 0x9a, 0xab, 0x24, 0x27, 0x54, 0x54, + 0x35, 0x4c, 0xe4, 0x2b, 0x9a, 0x2e, 0xed, 0xb3, 0x1f, 0x42, 0x12, 0x19, + 0xde, 0xf7, 0x46, 0x87, 0xe6, 0xf9, 0xc9, 0x2f, 0x0b, 0x19, 0x82, 0x35, + 0x5c, 0xad, 0xb2, 0x6e, 0x09, 0x5b, 0x7c, 0xa2, 0x5d, 0xe5, 0x30, 0xaa, + 0xba, 0x63, 0xe6, 0x4f, 0xc2, 0x3a, 0xcc, 0x3d, 0x1d, 0x1f, 0x1b, 0x70, + 0xcb, 0x72, 0x61, 0x56, 0xca, 0x0a, 0x79, 0x9b, 0x59, 0x09, 0x4b, 0xcc, + 0x3b, 0x89, 0x98, 0xa4, 0xae, 0x77, 0x44, 0xd2, 0x15, 0xd6, 0x3b, 0x88, + 0x70, 0x82, 0xf4, 0xc8, 0x41, 0x28, 0xe7, 0x4b, 0x9b, 0x99, 0x99, 0xc6, + 0x0c, 0xad, 0x3b, 0xc6, 0xbb, 0x6f, 0x72, 0x72, 0x84, 0xb4, 0x31, 0x1a, + 0x92, 0x9b, 0xbd, 0x96, 0x4c, 0x9a, 0x70, 0x74, 0xe8, 0x60, 0x62, 0x22, + 0x4d, 0xce, 0xdb, 0x58, 0xb9, 0xb5, 0x98, 0x54, 0x6a, 0xc9, 0x5b, 0x3b, + 0x43, 0x4e, 0xa1, 0x14, 0xab, 0x0d, 0x67, 0x85, 0x41, 0xd6, 0xca, 0xec, + 0x0c, 0x56, 0x00, 0x9b, 0xc3, 0x47, 0xa4, 0x25, 0xf1, 0x67, 0xcd, 0x32, + 0xa3, 0x4e, 0xec, 0xb7, 0x19, 0x24, 0x24, 0xd5, 0x7b, 0x0e, 0x54, 0xb4, + 0xa9, 0xe8, 0x2f, 0x42, 0x51, 0x38, 0x70, 0x3c, 0xe8, 0x9b, 0x18, 0x90, + 0x39, 0xe9, 0x2a, 0x77, 0x0b, 0x51, 0x49, 0x7f, 0x8f, 0x10, 0xea, 0xe9, + 0xc3, 0x45, 0x9e, 0xd8, 0x7e, 0x51, 0x01, 0xf5, 0xab, 0x1b, 0x62, 0x71, + 0x48, 0x5f, 0xdb, 0x2d, 0xd3, 0xdb, 0xc4, 0x21, 0x7f, 0xcf, 0x67, 0xc7, + 0xe9, 0x2d, 0x00, 0x96, 0xdc, 0x7d, 0xa9, 0x72, 0x7f, 0x5a, 0x43, 0x4b, + 0x75, 0x45, 0x28, 0x4c, 0xd8, 0xa2, 0x83, 0x07, 0x0b, 0x5a, 0x49, 0xd7, + 0x11, 0xdf, 0xfa, 0x85, 0x90, 0x43, 0x11, 0xe0, 0x34, 0x5a, 0x99, 0x14, + 0x7a, 0x16, 0x8e, 0xa0 +}; +/* K = 1ea475584982b639ada8c84e51ef72738390ed6fa44395f11428dc5fd794a81e */ +static const uint8_t ac_dsa_vect201_out[] = { +/* R */ + 0x1d, 0x27, 0x81, 0xf5, 0xf9, 0xd0, 0x8a, 0xb2, 0xfe, 0xb1, 0x68, 0x39, + 0x42, 0xc2, 0xc2, 0x9a, 0x66, 0x31, 0x88, 0x39, 0xa7, 0xdf, 0xef, 0x9a, + 0xee, 0x9c, 0xd7, 0xa8, 0x9e, 0xfe, 0x2a, 0xb0, +/* S */ + 0x3a, 0xdc, 0x7b, 0xe9, 0x68, 0x50, 0x2e, 0xad, 0x10, 0xfe, 0xec, 0x19, + 0x1e, 0x21, 0x2e, 0xa0, 0xe0, 0x7d, 0x44, 0x90, 0x06, 0xe7, 0xf2, 0x2d, + 0xdf, 0x86, 0x9a, 0x9f, 0xae, 0x71, 0x18, 0x34 +}; +#define ac_dsa_vect202_prime ac_dsa_vect196_prime +#define ac_dsa_vect202_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect202_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect202_ptx[] = { +/* Msg */ + 0xc7, 0x84, 0x49, 0x60, 0x96, 0x65, 0x84, 0xc8, 0xe3, 0xa5, 0x9d, 0xc3, + 0x7d, 0xf3, 0x7b, 0x7e, 0xb3, 0xad, 0x33, 0x31, 0x48, 0xa3, 0x2b, 0x86, + 0xc1, 0xec, 0x18, 0x07, 0x2f, 0x3b, 0x31, 0x6c, 0x59, 0xcd, 0xef, 0x98, + 0xba, 0x4d, 0xc4, 0x6f, 0x53, 0x2a, 0x42, 0x80, 0x20, 0x0c, 0x22, 0x5f, + 0xac, 0x6c, 0xd1, 0xad, 0xf0, 0xa4, 0x53, 0x82, 0xc2, 0xd8, 0x80, 0x54, + 0xe4, 0x47, 0x74, 0x04, 0x54, 0x97, 0x6e, 0x52, 0x72, 0x33, 0x0c, 0x74, + 0x87, 0xeb, 0x42, 0xa0, 0x95, 0xf7, 0x31, 0x41, 0x39, 0x93, 0x8c, 0x74, + 0x19, 0x19, 0x3b, 0x1c, 0x12, 0x80, 0x54, 0xc1, 0xbb, 0xf1, 0x0d, 0x06, + 0x34, 0xe2, 0x2c, 0x6e, 0x02, 0xd8, 0xe1, 0x22, 0x79, 0xca, 0xc0, 0xbf, + 0xa0, 0x1d, 0x30, 0x58, 0xe0, 0xf8, 0xd5, 0x54, 0x7b, 0xa0, 0xf7, 0x15, + 0x29, 0xc2, 0x7e, 0x00, 0x84, 0xd4, 0xbd, 0xe7 +}; +static const uint8_t ac_dsa_vect202_priv_val[] = { +/* X */ + 0x0c, 0x76, 0xbd, 0x64, 0x7c, 0x6f, 0xaf, 0xe7, 0xda, 0x10, 0x29, 0xb9, + 0xbf, 0x36, 0xa9, 0xf0, 0x42, 0x19, 0x56, 0x91, 0xa2, 0x6f, 0x36, 0xbb, + 0xe0, 0xec, 0xa3, 0xd4, 0xb1, 0xe6, 0xcb, 0xb4 +}; +static const uint8_t ac_dsa_vect202_pub_val[] = { +/* Y */ + 0x2d, 0xe9, 0xd2, 0x7f, 0x1a, 0x03, 0x01, 0x99, 0xff, 0xbb, 0xa7, 0x70, + 0xe0, 0x8a, 0xeb, 0x1f, 0xf3, 0x70, 0x8e, 0xdf, 0x8e, 0xbb, 0x3a, 0x8e, + 0x66, 0x4e, 0x3b, 0xd1, 0x51, 0x1d, 0xb1, 0x26, 0xed, 0x87, 0xbc, 0x44, + 0xc2, 0xd2, 0xaf, 0x40, 0xb9, 0xd5, 0x12, 0xc5, 0x0a, 0x4d, 0x6c, 0x10, + 0xb2, 0x3e, 0x3c, 0xa6, 0x18, 0x19, 0xf5, 0x84, 0x1c, 0xbf, 0x5d, 0x0b, + 0xd6, 0xc8, 0x8d, 0x46, 0xf1, 0xac, 0x64, 0x74, 0xec, 0x20, 0xb9, 0x10, + 0x0b, 0x32, 0x8c, 0xc1, 0x55, 0x87, 0x91, 0x66, 0xf4, 0x6b, 0x6d, 0x71, + 0x14, 0x0b, 0x0c, 0xfb, 0x2b, 0x07, 0x25, 0xb6, 0x4a, 0x38, 0xd7, 0x0a, + 0x91, 0xca, 0x8f, 0x0e, 0x3b, 0xae, 0xec, 0x61, 0x25, 0x26, 0x2c, 0x52, + 0xa9, 0x5d, 0x5c, 0xa5, 0xd5, 0xff, 0x6f, 0x44, 0x82, 0xb1, 0x82, 0x50, + 0x06, 0xcd, 0x46, 0x9f, 0x9e, 0x7f, 0x31, 0x76, 0x9a, 0x73, 0xed, 0xdb, + 0x5f, 0x70, 0x17, 0xf1, 0x8b, 0xc7, 0x47, 0xae, 0x4f, 0xce, 0x45, 0x0c, + 0x42, 0x74, 0xf4, 0xab, 0xb9, 0x60, 0x57, 0x7d, 0x13, 0xb6, 0xa7, 0x7d, + 0xd9, 0x9e, 0x67, 0xd1, 0x1e, 0xdb, 0x41, 0x3e, 0x42, 0x8e, 0x50, 0x72, + 0x6f, 0x70, 0x52, 0xe5, 0x35, 0x65, 0xfa, 0x1d, 0x6f, 0xde, 0x91, 0x85, + 0x95, 0x73, 0xc9, 0x28, 0x92, 0x89, 0xff, 0xef, 0x05, 0x98, 0x80, 0x28, + 0x08, 0xec, 0xc5, 0x50, 0x1c, 0xb3, 0x00, 0xe0, 0x64, 0x05, 0xed, 0x0f, + 0xeb, 0xc3, 0xdf, 0x23, 0xf4, 0x0a, 0x1f, 0x65, 0x32, 0x41, 0x0f, 0x7d, + 0x90, 0x49, 0xb9, 0x20, 0x21, 0x6f, 0x7d, 0x5c, 0x7a, 0x72, 0x8c, 0x8d, + 0xd6, 0x3a, 0x8d, 0x00, 0x60, 0xfb, 0x53, 0xb3, 0x54, 0x3d, 0x62, 0xa6, + 0x36, 0x66, 0x17, 0x50, 0xfd, 0x43, 0x77, 0x5e, 0x80, 0xb5, 0x09, 0x00, + 0x43, 0x51, 0x47, 0x5f +}; +/* K = 71e12996d8aaa7cb1e730713fa441098347ca95eb39362c5a78ee6e847469c7c */ +static const uint8_t ac_dsa_vect202_out[] = { +/* R */ + 0x09, 0xe6, 0x54, 0xb1, 0x7a, 0xb7, 0x75, 0x95, 0x96, 0x28, 0xe7, 0xca, + 0xd0, 0xe2, 0x70, 0x53, 0xee, 0x49, 0x5b, 0xcc, 0x29, 0xcc, 0x2a, 0x5e, + 0x3b, 0x02, 0x96, 0x60, 0xa7, 0x7b, 0x13, 0x30, +/* S */ + 0x26, 0x1a, 0xd4, 0x1d, 0x6b, 0xce, 0x6d, 0x04, 0xd8, 0x91, 0xa4, 0x3c, + 0x16, 0xec, 0x2a, 0x81, 0x14, 0xe5, 0x1f, 0x0e, 0x47, 0xb4, 0x8b, 0x1d, + 0xd1, 0xf3, 0xd6, 0x26, 0x15, 0x03, 0x38, 0xfb +}; +#define ac_dsa_vect203_prime ac_dsa_vect196_prime +#define ac_dsa_vect203_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect203_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect203_ptx[] = { +/* Msg */ + 0x6f, 0x3f, 0x74, 0x38, 0x8c, 0xc9, 0x0b, 0x29, 0xc1, 0x09, 0xec, 0xbd, + 0xa0, 0x8c, 0x79, 0x34, 0x9d, 0xff, 0xde, 0xb9, 0x07, 0x22, 0x97, 0x4d, + 0x79, 0xd6, 0x40, 0x62, 0x09, 0x49, 0x44, 0x8f, 0x66, 0xae, 0x67, 0x3e, + 0xaf, 0x4d, 0x4a, 0xf8, 0xc4, 0x3d, 0xa6, 0x73, 0xa4, 0x5e, 0xd1, 0x52, + 0xea, 0x66, 0xfc, 0x97, 0x16, 0x6b, 0xaa, 0x7c, 0xe8, 0xbe, 0xb6, 0x66, + 0xbd, 0x57, 0xca, 0x43, 0xda, 0x68, 0x01, 0xc0, 0xee, 0x5a, 0x5a, 0x9b, + 0x50, 0xc5, 0x04, 0x79, 0x35, 0xd7, 0xa8, 0x55, 0x2c, 0x38, 0x1d, 0x93, + 0xea, 0xf0, 0x3c, 0xbb, 0xbb, 0x88, 0xed, 0x0d, 0x3b, 0x5a, 0x25, 0x21, + 0xb6, 0x76, 0x12, 0xa4, 0x40, 0x51, 0x20, 0xef, 0x02, 0x05, 0xe8, 0x9a, + 0xeb, 0x48, 0xd5, 0x77, 0xbc, 0xda, 0x3a, 0xd2, 0x0e, 0x0a, 0x7c, 0xd0, + 0x7f, 0x8c, 0x9b, 0x21, 0x5c, 0x84, 0x5d, 0xd8 +}; +static const uint8_t ac_dsa_vect203_priv_val[] = { +/* X */ + 0x34, 0xc0, 0xd0, 0xde, 0x98, 0xc8, 0x5b, 0xe2, 0x91, 0xb6, 0x8a, 0x5b, + 0x8c, 0x7f, 0xb3, 0x53, 0x6b, 0x6f, 0x74, 0x47, 0xe8, 0x56, 0x5e, 0xad, + 0x9b, 0x00, 0x24, 0x17, 0xf5, 0x6f, 0x46, 0x16 +}; +static const uint8_t ac_dsa_vect203_pub_val[] = { +/* Y */ + 0x08, 0x0c, 0xa4, 0x12, 0xbd, 0x19, 0x7c, 0x5a, 0xaf, 0xa2, 0xc6, 0xdf, + 0x59, 0x33, 0xa6, 0x21, 0x0f, 0xa5, 0x40, 0x89, 0x82, 0x68, 0x28, 0xd5, + 0x49, 0x6b, 0x45, 0x36, 0x09, 0xa5, 0x6b, 0x7d, 0x55, 0xd2, 0x32, 0xfb, + 0xe6, 0x50, 0xdd, 0x9f, 0x62, 0xc0, 0x5c, 0x05, 0x0c, 0x02, 0x6a, 0x87, + 0x17, 0xa7, 0x8b, 0x5d, 0xb0, 0x16, 0x14, 0xa1, 0x93, 0x01, 0xc6, 0x10, + 0xd2, 0xb9, 0x96, 0x4a, 0x7e, 0x33, 0x57, 0xc7, 0x22, 0xa4, 0xc5, 0x53, + 0x27, 0x3b, 0xf2, 0x7f, 0x87, 0x1b, 0x4b, 0x92, 0x41, 0x67, 0x8c, 0x33, + 0x4e, 0x20, 0x82, 0x7a, 0x5f, 0x51, 0x1f, 0xe9, 0x31, 0x9a, 0x07, 0x5d, + 0x12, 0x75, 0x3a, 0xc0, 0x96, 0x0d, 0xf6, 0x08, 0x70, 0xa0, 0x8a, 0x12, + 0xf0, 0x9b, 0x9d, 0x35, 0x93, 0x78, 0x17, 0x81, 0xa0, 0xcd, 0x75, 0xe9, + 0xd8, 0x1c, 0xc6, 0xb9, 0xb0, 0xd5, 0x06, 0xd1, 0x00, 0xfe, 0x97, 0x21, + 0x65, 0xb6, 0x82, 0x97, 0xe6, 0x07, 0x0d, 0xb2, 0xd8, 0xb6, 0xea, 0x32, + 0x17, 0x6d, 0x15, 0x62, 0x08, 0x4f, 0x6a, 0x06, 0xe0, 0x8e, 0x29, 0x29, + 0x15, 0x5b, 0x25, 0x5d, 0x33, 0x85, 0x3d, 0xe6, 0x54, 0x9e, 0x79, 0xf8, + 0xb5, 0x60, 0x49, 0xa1, 0xd0, 0x2f, 0x29, 0x16, 0x6d, 0x5f, 0x91, 0xcf, + 0xbd, 0xe5, 0xaa, 0xf6, 0xbc, 0xae, 0x56, 0xf5, 0xd2, 0xd9, 0x0a, 0x9b, + 0x4e, 0x8f, 0x6f, 0x45, 0x00, 0x80, 0xca, 0xe8, 0x25, 0x6c, 0x66, 0x19, + 0xe9, 0x15, 0x55, 0x23, 0xc2, 0xb2, 0x05, 0x22, 0x55, 0xa8, 0xf6, 0xd9, + 0xf5, 0x3d, 0x8a, 0x89, 0x7b, 0xe5, 0xb0, 0x47, 0x60, 0x02, 0x41, 0x0b, + 0xf7, 0x98, 0x25, 0x6f, 0x62, 0xbb, 0x1a, 0x81, 0x82, 0x7c, 0x2c, 0x3f, + 0xc4, 0xec, 0xf9, 0xab, 0xfd, 0x77, 0xe7, 0x41, 0x74, 0x78, 0x73, 0x70, + 0x86, 0x4f, 0x05, 0xf9 +}; +/* K = 8086cc691e7e793a5c2a81bd3d5a1ff5ae261d9336b33f103d983a817f7eaf7b */ +static const uint8_t ac_dsa_vect203_out[] = { +/* R */ + 0x43, 0x99, 0x3b, 0x68, 0xe8, 0x47, 0xf6, 0xba, 0x61, 0xd5, 0xad, 0x4d, + 0xc8, 0xf5, 0xad, 0x70, 0xda, 0xbc, 0x31, 0x7a, 0x7b, 0x68, 0x11, 0xc2, + 0x3e, 0x7f, 0x21, 0x5f, 0x95, 0x41, 0x5e, 0xd5, +/* S */ + 0x1e, 0xa7, 0x27, 0xaf, 0xdb, 0x90, 0x7d, 0x1d, 0x5b, 0x23, 0x37, 0xc1, + 0xec, 0xea, 0x46, 0xc7, 0x1e, 0xb0, 0xfc, 0x83, 0x63, 0xaf, 0x23, 0x86, + 0x5a, 0x34, 0x52, 0x02, 0xa7, 0x62, 0xa7, 0xc5 +}; +#define ac_dsa_vect204_prime ac_dsa_vect196_prime +#define ac_dsa_vect204_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect204_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect204_ptx[] = { +/* Msg */ + 0x74, 0xa4, 0x33, 0xc2, 0xd3, 0x13, 0xf6, 0x62, 0x32, 0x32, 0x4d, 0xf8, + 0x75, 0xb8, 0x25, 0x63, 0x80, 0x5d, 0x7e, 0xd6, 0x82, 0xb2, 0x66, 0xea, + 0xf9, 0x62, 0x37, 0x5e, 0x42, 0x2b, 0x3a, 0xbb, 0xfe, 0x3d, 0xce, 0x7f, + 0x3c, 0x19, 0x60, 0xa1, 0xe4, 0x10, 0x0f, 0x33, 0x3e, 0x16, 0x8d, 0x02, + 0x19, 0x68, 0xb4, 0x83, 0x97, 0xe8, 0xcc, 0xe9, 0x00, 0x5e, 0x95, 0x1f, + 0xdc, 0xb0, 0x96, 0xa9, 0xab, 0xea, 0x34, 0x2c, 0xb5, 0xb0, 0x8b, 0xab, + 0x79, 0xef, 0x0c, 0x43, 0x1d, 0xd3, 0xa4, 0x3d, 0xe7, 0xd5, 0xbd, 0x6b, + 0x86, 0xbe, 0xa8, 0x87, 0x2b, 0xa0, 0x38, 0xb4, 0x3a, 0x23, 0x6a, 0x73, + 0x56, 0xb0, 0x3f, 0x89, 0xb0, 0x90, 0x04, 0xba, 0x2d, 0xef, 0x66, 0x3e, + 0x6d, 0x29, 0x97, 0x63, 0xb6, 0xca, 0xfc, 0xb6, 0xb1, 0x50, 0xa5, 0x7f, + 0x82, 0xb8, 0x90, 0xff, 0x6d, 0x56, 0xf8, 0x32 +}; +static const uint8_t ac_dsa_vect204_priv_val[] = { +/* X */ + 0x5c, 0x1a, 0x80, 0xe9, 0x26, 0xde, 0x19, 0x49, 0x95, 0x19, 0x5c, 0x4c, + 0xee, 0x9a, 0x2e, 0x87, 0x4c, 0x7f, 0x6a, 0xf0, 0xfa, 0x8a, 0x4b, 0x2d, + 0xf5, 0x43, 0x2f, 0x9c, 0xfc, 0x86, 0xb6, 0x43 +}; +static const uint8_t ac_dsa_vect204_pub_val[] = { +/* Y */ + 0x44, 0x4f, 0xaf, 0xab, 0x58, 0xdb, 0x4d, 0x6f, 0x52, 0x83, 0xc3, 0x44, + 0x3d, 0x64, 0x78, 0xb5, 0xb7, 0x8d, 0xaa, 0x63, 0x1b, 0xd4, 0xc3, 0xd9, + 0xa2, 0x8e, 0xd1, 0x72, 0x81, 0xda, 0x4c, 0x1c, 0x2e, 0xf4, 0xd5, 0xed, + 0x57, 0x6d, 0x66, 0xbf, 0xe5, 0x31, 0x4e, 0x11, 0xfe, 0x68, 0xab, 0xff, + 0xe4, 0xdf, 0x40, 0x6f, 0x60, 0x33, 0xed, 0xb8, 0x4f, 0x36, 0xa3, 0x8a, + 0x3c, 0xe6, 0x14, 0x60, 0x1b, 0xc2, 0x58, 0x41, 0xf9, 0x41, 0x9a, 0xfb, + 0x28, 0x67, 0xd9, 0x91, 0xe8, 0x7b, 0x44, 0xc4, 0xb7, 0x44, 0xe3, 0x9b, + 0x64, 0x07, 0x9d, 0x9a, 0xad, 0x4b, 0x58, 0x5d, 0x79, 0xc8, 0xe2, 0x1c, + 0x8f, 0x90, 0x99, 0x05, 0x40, 0xfe, 0xc8, 0xae, 0x98, 0x1f, 0x74, 0x83, + 0xdc, 0x55, 0x23, 0xd2, 0x16, 0x08, 0x8a, 0x55, 0xcf, 0x23, 0x80, 0xea, + 0x8e, 0xb5, 0x24, 0x67, 0x81, 0x29, 0x05, 0x59, 0xea, 0x1b, 0x20, 0x8a, + 0xd4, 0xd0, 0xf5, 0x87, 0x1c, 0xb4, 0xd1, 0x3c, 0xdc, 0xa6, 0xef, 0x34, + 0xfd, 0xf2, 0xde, 0x63, 0xe2, 0x09, 0xaa, 0x32, 0x0c, 0xdf, 0x14, 0x18, + 0x5b, 0x8f, 0x5f, 0x60, 0xcc, 0xf9, 0x3f, 0x39, 0x8c, 0x1a, 0x6c, 0xf8, + 0xb3, 0xce, 0x3d, 0x98, 0xda, 0xf0, 0x5e, 0x4c, 0xf9, 0x0c, 0x39, 0x80, + 0x1c, 0xe3, 0x5f, 0x01, 0xec, 0x76, 0xa9, 0xf6, 0x03, 0x5c, 0xe1, 0xb5, + 0xba, 0x10, 0x7a, 0x5f, 0x66, 0xcf, 0x25, 0x3b, 0x71, 0xfb, 0xa3, 0x83, + 0x3e, 0x99, 0x69, 0xc3, 0x14, 0xeb, 0x6d, 0x50, 0x00, 0x05, 0x74, 0x92, + 0x31, 0xf7, 0x99, 0xb0, 0xc7, 0x9a, 0x55, 0x5a, 0x10, 0xcd, 0xd6, 0x9f, + 0x8e, 0xec, 0x4c, 0x11, 0x7d, 0x7c, 0x8b, 0x4e, 0xc6, 0xf6, 0x0a, 0x1e, + 0xe5, 0x57, 0xb7, 0x0c, 0x0d, 0xea, 0x38, 0x0a, 0xf5, 0x3b, 0x92, 0xfd, + 0xde, 0x88, 0x23, 0xca +}; +/* K = 13dcb7c12aeb75a417a93a22ce94618716996c3350909cfbff6d38b603d377f6 */ +static const uint8_t ac_dsa_vect204_out[] = { +/* R */ + 0x3b, 0xda, 0x5b, 0x0c, 0x9e, 0x3d, 0xa2, 0x2f, 0x0b, 0x3e, 0x29, 0x35, + 0x6a, 0x2f, 0x7d, 0xda, 0xce, 0x6e, 0x9b, 0x24, 0xa0, 0x63, 0xeb, 0x3f, + 0x5a, 0x7d, 0x75, 0x5f, 0x2e, 0xea, 0xff, 0xb5, +/* S */ + 0x4c, 0xbb, 0x81, 0x53, 0x20, 0x31, 0x4a, 0x06, 0x53, 0x8d, 0x2a, 0x67, + 0x40, 0xe6, 0xbf, 0x9d, 0x02, 0x2e, 0xac, 0x9a, 0xa2, 0x5c, 0x75, 0x08, + 0xf6, 0x59, 0xf0, 0xf7, 0xc1, 0xf5, 0x9c, 0x45 +}; +#define ac_dsa_vect205_prime ac_dsa_vect196_prime +#define ac_dsa_vect205_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect205_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect205_ptx[] = { +/* Msg */ + 0xf4, 0xea, 0xdf, 0xea, 0x11, 0x7f, 0xd3, 0xd6, 0x70, 0xce, 0xa2, 0x8a, + 0xa9, 0xd2, 0x60, 0x2c, 0x95, 0x1e, 0xd8, 0x43, 0xe2, 0xe8, 0xcb, 0x28, + 0x64, 0x07, 0x4c, 0x8c, 0x9b, 0xcc, 0xb0, 0x60, 0x6c, 0xed, 0x83, 0xae, + 0x29, 0x80, 0x59, 0x8c, 0xc3, 0xe1, 0xb0, 0x47, 0xfc, 0xa8, 0x65, 0x91, + 0x27, 0x40, 0x6d, 0x8f, 0x59, 0xf5, 0xb7, 0xbb, 0xfe, 0x8e, 0xce, 0x6d, + 0x3e, 0x42, 0xf8, 0x7f, 0x4e, 0x42, 0xeb, 0xe9, 0x2a, 0xda, 0xa1, 0xe6, + 0xe9, 0x2c, 0xed, 0x3d, 0xca, 0xcc, 0x2e, 0x0b, 0x2c, 0x98, 0xea, 0xde, + 0x7c, 0x9c, 0x99, 0xda, 0x88, 0x7e, 0x74, 0xdb, 0x5a, 0x59, 0x13, 0x2c, + 0x1d, 0x7d, 0xf7, 0xcd, 0xe8, 0x66, 0xcb, 0x2f, 0x3c, 0xa7, 0x50, 0x85, + 0x2b, 0xa5, 0x3e, 0x26, 0x5e, 0x62, 0xbf, 0x7a, 0x93, 0xfd, 0x69, 0x3e, + 0x4a, 0x13, 0x75, 0x1e, 0x18, 0x6e, 0x9d, 0x6b +}; +static const uint8_t ac_dsa_vect205_priv_val[] = { +/* X */ + 0x6a, 0xbf, 0x7c, 0xc8, 0x87, 0x54, 0x4b, 0xf8, 0xd3, 0x25, 0x6f, 0xb2, + 0x10, 0x84, 0x8e, 0xb4, 0x62, 0x81, 0x52, 0x6b, 0x1e, 0x8c, 0xdf, 0x6c, + 0x92, 0x04, 0xc4, 0xc4, 0x6a, 0x74, 0x74, 0x35 +}; +static const uint8_t ac_dsa_vect205_pub_val[] = { +/* Y */ + 0x10, 0x4f, 0x44, 0xfd, 0x76, 0x69, 0x60, 0x76, 0x44, 0xec, 0x55, 0xe6, + 0xca, 0x40, 0x96, 0xc9, 0xa2, 0x79, 0x47, 0x27, 0x52, 0xa1, 0x75, 0x3d, + 0xbb, 0x9f, 0x2a, 0x69, 0x41, 0xb8, 0x12, 0x22, 0x74, 0xc8, 0x7d, 0x16, + 0xf6, 0x3d, 0x75, 0xdd, 0xa9, 0xeb, 0xcf, 0xd6, 0x58, 0x4b, 0x0c, 0xb3, + 0x74, 0xfd, 0x17, 0x58, 0x13, 0x53, 0xd2, 0xa2, 0x46, 0xec, 0x0b, 0x37, + 0x8d, 0xe6, 0x0e, 0x96, 0x13, 0x13, 0x16, 0x83, 0xc0, 0x56, 0x8b, 0xb5, + 0x4d, 0x74, 0x45, 0x7a, 0xd7, 0x3d, 0xe8, 0x59, 0xa4, 0xf0, 0x24, 0x45, + 0x34, 0x4d, 0x13, 0xee, 0x92, 0x8f, 0x3c, 0xda, 0x51, 0x34, 0x20, 0x2a, + 0x93, 0x88, 0xe6, 0x4c, 0xf0, 0x5f, 0x81, 0x90, 0x04, 0x9d, 0xf4, 0xe7, + 0x77, 0x70, 0x98, 0x38, 0xd0, 0xc9, 0xd3, 0xbc, 0xb3, 0x7e, 0xec, 0xdc, + 0x38, 0xc1, 0xa5, 0xd2, 0xb4, 0x71, 0xc4, 0xb9, 0x10, 0xcf, 0xaa, 0x9a, + 0x9b, 0xa8, 0x1f, 0x69, 0xb4, 0xb4, 0x5c, 0x40, 0x34, 0x40, 0x29, 0x95, + 0x8f, 0xa4, 0x00, 0x00, 0xe5, 0x68, 0x81, 0xbc, 0x6a, 0x14, 0x86, 0x43, + 0x30, 0xd5, 0xb3, 0x51, 0xc1, 0x61, 0x20, 0x86, 0x76, 0xcb, 0x85, 0x2b, + 0xf4, 0x79, 0x70, 0x26, 0x8d, 0x37, 0xd4, 0xbf, 0xe9, 0x7b, 0x3b, 0x26, + 0xef, 0x5b, 0x78, 0x5f, 0x50, 0xeb, 0xc8, 0xc4, 0x79, 0x49, 0xdc, 0x9b, + 0xd0, 0xb2, 0xe6, 0x73, 0xfb, 0x04, 0x0e, 0x26, 0x78, 0x9f, 0x3f, 0x5c, + 0xdb, 0xce, 0x8e, 0x4b, 0x78, 0x38, 0x99, 0x92, 0xbb, 0x83, 0xee, 0xb2, + 0xb0, 0x63, 0xe9, 0xe1, 0xdb, 0x06, 0xa9, 0xed, 0xe9, 0x33, 0xfa, 0xef, + 0x7e, 0x63, 0x5e, 0xff, 0xe5, 0xe1, 0xb1, 0xe2, 0x11, 0x53, 0xdc, 0x69, + 0x34, 0x19, 0x7e, 0xfa, 0x1f, 0xd6, 0x8f, 0x18, 0xa4, 0x0e, 0xd5, 0x69, + 0x74, 0x6c, 0x83, 0x74 +}; +/* K = 0711c4621a8bcd40ff3e8b95728ce67a000e1fa33741246d420b046bdec48657 */ +static const uint8_t ac_dsa_vect205_out[] = { +/* R */ + 0x36, 0xc0, 0x86, 0x07, 0x03, 0x68, 0x26, 0x5f, 0x73, 0x6e, 0x7b, 0xba, + 0xd5, 0x4a, 0xaf, 0x24, 0x82, 0xd2, 0x61, 0x61, 0xf8, 0x05, 0x7a, 0x97, + 0xa4, 0xb8, 0xcd, 0x2b, 0x4d, 0xdd, 0x78, 0x55, +/* S */ + 0x31, 0xd9, 0x9d, 0x73, 0x6e, 0xa6, 0x70, 0x14, 0xfe, 0x59, 0xcb, 0x22, + 0x12, 0xc4, 0x7e, 0xb9, 0x20, 0xf2, 0xaf, 0x44, 0xe3, 0x2b, 0x65, 0xdb, + 0x15, 0xaf, 0x83, 0xcb, 0xe8, 0xe6, 0xaa, 0x70 +}; +#define ac_dsa_vect206_prime ac_dsa_vect196_prime +#define ac_dsa_vect206_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect206_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect206_ptx[] = { +/* Msg */ + 0xcb, 0xc3, 0x7a, 0xfc, 0x75, 0x17, 0x7a, 0x83, 0x86, 0xdc, 0xe2, 0xc4, + 0x0c, 0x33, 0xb8, 0xf5, 0xde, 0xdc, 0x23, 0x11, 0x3b, 0x45, 0x12, 0xcb, + 0x96, 0x79, 0x0f, 0x2d, 0xd7, 0x40, 0x66, 0x10, 0x3e, 0x0c, 0x45, 0xa9, + 0xc6, 0x17, 0x6f, 0xf9, 0x6b, 0x7d, 0x71, 0x91, 0x62, 0x00, 0x3c, 0xee, + 0x10, 0xfa, 0xd6, 0xcc, 0xc1, 0x98, 0x55, 0x0a, 0x38, 0x92, 0x75, 0xd2, + 0x1e, 0x70, 0x8b, 0x69, 0x61, 0x52, 0x32, 0x72, 0xec, 0xd5, 0xef, 0xab, + 0x56, 0x80, 0xed, 0x74, 0x1c, 0x2d, 0xe0, 0x25, 0xb0, 0x2b, 0xbd, 0xc5, + 0x63, 0x15, 0xa4, 0x42, 0xe4, 0x37, 0xc4, 0x3e, 0x3b, 0x37, 0x8e, 0x6d, + 0x62, 0xea, 0x88, 0x78, 0xfd, 0x97, 0x89, 0x85, 0x8a, 0x8c, 0x68, 0xa5, + 0x04, 0xbf, 0xf4, 0x95, 0x16, 0xe7, 0x62, 0xa2, 0x2a, 0xe5, 0x13, 0xa2, + 0xdc, 0xeb, 0xa9, 0x25, 0x3b, 0x36, 0xf5, 0x53 +}; +static const uint8_t ac_dsa_vect206_priv_val[] = { +/* X */ + 0x7c, 0x6e, 0xe8, 0x6f, 0x45, 0xdd, 0xf8, 0xb8, 0x7f, 0x88, 0x84, 0xf5, + 0x9a, 0xad, 0x9e, 0x32, 0x0b, 0x73, 0xb2, 0x46, 0xa8, 0x0b, 0x26, 0xa6, + 0x45, 0x18, 0x8a, 0x40, 0xa9, 0xbc, 0xa6, 0x2d +}; +static const uint8_t ac_dsa_vect206_pub_val[] = { +/* Y */ + 0x35, 0x6c, 0xc7, 0x37, 0x0c, 0x84, 0x0f, 0xa2, 0x6b, 0x0d, 0x10, 0x6c, + 0x47, 0xa6, 0x26, 0xe0, 0x28, 0xa0, 0xc9, 0x67, 0xc0, 0x93, 0x81, 0x0b, + 0x52, 0x06, 0x39, 0xbd, 0xda, 0x0d, 0x33, 0x9b, 0x7f, 0xc2, 0x9a, 0xdc, + 0x0d, 0x90, 0x36, 0xb9, 0x71, 0x03, 0x58, 0xef, 0x9f, 0x8c, 0x6c, 0x05, + 0x25, 0x2b, 0x27, 0x82, 0x81, 0xb2, 0xaf, 0xe7, 0x95, 0x38, 0x86, 0x42, + 0x9e, 0x85, 0xd2, 0x28, 0xfb, 0x54, 0x74, 0xac, 0xfd, 0x65, 0x21, 0x31, + 0x51, 0xe9, 0xda, 0x0a, 0xef, 0x86, 0xa6, 0x6f, 0x9f, 0x9c, 0x59, 0xfa, + 0x88, 0xfd, 0x48, 0xcc, 0x3a, 0xdd, 0xc8, 0x3d, 0x7a, 0xdf, 0x4a, 0xfb, + 0x16, 0x65, 0x04, 0x9e, 0xd0, 0x94, 0x02, 0x02, 0x19, 0xc0, 0x19, 0x58, + 0xb6, 0x97, 0xf2, 0x2e, 0x65, 0x21, 0x52, 0xe5, 0x3b, 0xf4, 0xe8, 0xf6, + 0x8f, 0x47, 0x6a, 0x58, 0x18, 0x1d, 0xdd, 0x3f, 0x64, 0x34, 0x4e, 0x9b, + 0x87, 0xa0, 0x8c, 0x5d, 0x0d, 0xe4, 0x9e, 0x7b, 0x3c, 0x29, 0x95, 0x84, + 0x0c, 0x20, 0x00, 0x84, 0xe9, 0x0a, 0x76, 0xd2, 0xc0, 0x5f, 0x8b, 0x5c, + 0x68, 0xe7, 0x71, 0x92, 0xd0, 0x67, 0x6b, 0x42, 0x19, 0xd4, 0x57, 0x9c, + 0xb2, 0xde, 0x0f, 0x2a, 0x93, 0xa9, 0x16, 0xb4, 0xf9, 0xcf, 0xe0, 0xd8, + 0x11, 0x3d, 0xc4, 0xbb, 0xd9, 0x7e, 0xd1, 0x2d, 0x8c, 0xe0, 0x44, 0x7f, + 0xcf, 0x9d, 0xf1, 0x2e, 0x92, 0x2c, 0x63, 0x83, 0xca, 0x69, 0xc9, 0xde, + 0x9a, 0xd3, 0x20, 0xf9, 0xc5, 0x33, 0x1a, 0xdb, 0x6e, 0xb1, 0xd2, 0x23, + 0x07, 0x91, 0x96, 0xa2, 0x93, 0x9c, 0xc0, 0xa7, 0x25, 0x9c, 0x51, 0x2c, + 0x47, 0x8c, 0x94, 0x3f, 0xe0, 0x57, 0x36, 0x71, 0x0e, 0x27, 0x3e, 0x4b, + 0x58, 0x67, 0x17, 0x4d, 0xe7, 0x2e, 0x70, 0x3b, 0x5e, 0x7b, 0xf7, 0xaf, + 0xdb, 0xc0, 0x64, 0x27 +}; +/* K = 685a19da2ee3dd94fe9726a32e712fac05eeffe11e3dd9f60e6f90af7c13e23a */ +static const uint8_t ac_dsa_vect206_out[] = { +/* R */ + 0x56, 0x45, 0xef, 0x65, 0xe8, 0xe9, 0x23, 0x6d, 0x87, 0x4d, 0x45, 0x9e, + 0x7a, 0x58, 0x09, 0x92, 0x3c, 0x05, 0xd6, 0x4b, 0x22, 0x75, 0x7b, 0xfc, + 0x5b, 0x56, 0x21, 0x07, 0x9e, 0x84, 0x81, 0x9c, +/* S */ + 0x65, 0xf4, 0xc8, 0xfe, 0xba, 0xf3, 0xe9, 0xd4, 0x65, 0x81, 0xb1, 0x76, + 0x85, 0xc4, 0xf2, 0xec, 0x9b, 0x95, 0x64, 0x21, 0xd0, 0x34, 0xa2, 0xc1, + 0xaa, 0xab, 0xee, 0x94, 0xb7, 0x87, 0xa4, 0xf1 +}; +#define ac_dsa_vect207_prime ac_dsa_vect196_prime +#define ac_dsa_vect207_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect207_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect207_ptx[] = { +/* Msg */ + 0x8e, 0xb3, 0x68, 0x5c, 0x3f, 0x40, 0x6c, 0x56, 0x15, 0xe8, 0x8a, 0xcc, + 0xf4, 0xc0, 0xc7, 0xd2, 0x07, 0x1b, 0x6c, 0x7b, 0xde, 0x52, 0x44, 0x99, + 0x4f, 0x73, 0xdc, 0x04, 0xf3, 0xcc, 0x0a, 0xb7, 0xe2, 0xb6, 0x66, 0x4a, + 0x19, 0x94, 0xe6, 0xee, 0xc5, 0x2b, 0x62, 0x79, 0x0a, 0x04, 0x32, 0x8e, + 0x43, 0x6a, 0x2b, 0x4a, 0xf3, 0xcb, 0xe3, 0xba, 0x6e, 0x4c, 0x8f, 0x36, + 0x3a, 0x39, 0xb2, 0x52, 0x9e, 0xf5, 0x54, 0xc0, 0xc6, 0x27, 0xf9, 0xf6, + 0xb2, 0x55, 0x92, 0x8a, 0x39, 0xa4, 0x65, 0xe6, 0x0a, 0xc5, 0x0c, 0xcf, + 0x01, 0xf3, 0x2c, 0x7b, 0xa4, 0x83, 0x64, 0x03, 0x44, 0xb6, 0xa8, 0xf5, + 0x83, 0xc9, 0x08, 0x76, 0xb8, 0x4d, 0x19, 0x55, 0x4b, 0x0a, 0x4b, 0xaa, + 0xbc, 0x2c, 0x24, 0x0e, 0x29, 0x6b, 0x12, 0xc8, 0x19, 0x41, 0x0c, 0xac, + 0xff, 0xe7, 0xa7, 0x46, 0x44, 0x19, 0xbe, 0xe0 +}; +static const uint8_t ac_dsa_vect207_priv_val[] = { +/* X */ + 0x7e, 0x5e, 0x3d, 0x72, 0x55, 0xa6, 0x29, 0xc3, 0x9f, 0x88, 0xb6, 0x04, + 0x6f, 0xe0, 0x03, 0x91, 0x59, 0xe4, 0x4c, 0x2d, 0x23, 0x09, 0xb1, 0x12, + 0xab, 0x05, 0xc6, 0x15, 0x61, 0xd9, 0xe4, 0x4a +}; +static const uint8_t ac_dsa_vect207_pub_val[] = { +/* Y */ + 0x94, 0xba, 0x48, 0x69, 0x77, 0xf5, 0x98, 0x2f, 0x2a, 0xe7, 0x5e, 0x98, + 0x6b, 0x7e, 0x19, 0x44, 0x61, 0xcc, 0x3d, 0x65, 0xcd, 0xbf, 0x26, 0xf9, + 0x36, 0x80, 0x5d, 0x12, 0xd7, 0xf8, 0x50, 0xaa, 0xd7, 0x58, 0x02, 0x06, + 0xd7, 0xdc, 0x54, 0x4c, 0xd1, 0x2c, 0xa1, 0x89, 0x1c, 0x9d, 0xc4, 0x06, + 0xc9, 0x49, 0xe5, 0x2b, 0x9f, 0xeb, 0xfa, 0x88, 0x83, 0x6f, 0x15, 0x66, + 0xd5, 0x21, 0xa1, 0x10, 0xbb, 0x54, 0x5e, 0x07, 0xba, 0x28, 0xca, 0xf0, + 0x7e, 0x1b, 0xbf, 0xa3, 0xb1, 0x76, 0xcc, 0x91, 0x7c, 0xc4, 0xbb, 0x45, + 0xda, 0xe7, 0xf8, 0x73, 0xb7, 0x2d, 0xfa, 0x90, 0x00, 0xe9, 0xab, 0x60, + 0x83, 0xe7, 0x05, 0xc0, 0x16, 0x7d, 0x85, 0x3d, 0xda, 0x11, 0x4c, 0x42, + 0x9f, 0xd8, 0x12, 0xa0, 0x59, 0x61, 0xfc, 0x2e, 0x78, 0xba, 0x9e, 0x68, + 0xcc, 0xdb, 0x9d, 0xc6, 0x7b, 0x11, 0x6f, 0x10, 0x53, 0x20, 0x34, 0xd9, + 0xf0, 0xf7, 0xd3, 0x99, 0x01, 0xdc, 0x64, 0x31, 0x27, 0xc4, 0x30, 0x90, + 0x58, 0xf8, 0xeb, 0xf4, 0x3b, 0x28, 0xa5, 0xce, 0x53, 0x4e, 0x29, 0xd6, + 0x22, 0x7c, 0x4e, 0xc2, 0x7c, 0xcf, 0x77, 0x7b, 0x00, 0x08, 0xdf, 0x5c, + 0xe8, 0xb8, 0xa1, 0x9b, 0x57, 0x71, 0x72, 0x5c, 0xb0, 0xf9, 0xf2, 0xa6, + 0x2b, 0xb4, 0x1f, 0x01, 0x06, 0xc3, 0x90, 0x80, 0x3a, 0x30, 0x7c, 0x60, + 0xac, 0xbe, 0xd6, 0xc2, 0xe1, 0xe0, 0xdb, 0x50, 0x36, 0xe0, 0xe7, 0x9d, + 0xdc, 0xc3, 0xf7, 0x18, 0xb2, 0x9c, 0xa5, 0xaa, 0x02, 0x2f, 0x2f, 0x0b, + 0xbe, 0x81, 0x5f, 0x9c, 0x0e, 0xb5, 0x04, 0xfc, 0x9f, 0xf8, 0xd1, 0x8a, + 0x2d, 0xa9, 0x99, 0x02, 0x3a, 0xf8, 0x10, 0x5c, 0xdd, 0xfc, 0x67, 0x94, + 0xdf, 0xdc, 0xc4, 0x13, 0x33, 0xbc, 0xcd, 0x44, 0x6a, 0xd7, 0xb8, 0x2a, + 0x0a, 0x7b, 0xfe, 0x38 +}; +/* K = 3966daabf7854949475ff47f3932393a73f21e275b3baad861a92a3ab322e376 */ +static const uint8_t ac_dsa_vect207_out[] = { +/* R */ + 0x27, 0xb4, 0xe3, 0xc3, 0xa4, 0x5e, 0xfa, 0x61, 0x31, 0xc3, 0xd0, 0x05, + 0xca, 0x92, 0x4d, 0xff, 0x11, 0xfd, 0xcc, 0xf4, 0x09, 0xc2, 0xa6, 0x99, + 0x3f, 0xcb, 0x50, 0x54, 0x77, 0xb6, 0xe4, 0x00, +/* S */ + 0x68, 0xa0, 0x85, 0xbd, 0x13, 0x0c, 0x4e, 0xc0, 0x8a, 0xa9, 0x67, 0x3c, + 0x49, 0x5b, 0xa5, 0xaf, 0xd4, 0x6c, 0x9d, 0xda, 0xd2, 0x05, 0x2b, 0xa7, + 0xab, 0x39, 0x63, 0x29, 0xd9, 0x00, 0xd8, 0x6c +}; +#define ac_dsa_vect208_prime ac_dsa_vect196_prime +#define ac_dsa_vect208_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect208_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect208_ptx[] = { +/* Msg */ + 0xf2, 0xb0, 0x2a, 0xc6, 0x27, 0xb3, 0xf6, 0x6b, 0xaf, 0x4e, 0xba, 0xa5, + 0x2b, 0x89, 0x9a, 0xdf, 0xd7, 0x07, 0x1a, 0xf5, 0x3e, 0x78, 0x92, 0x31, + 0x82, 0xd8, 0xb4, 0xd5, 0xf3, 0xa9, 0x47, 0x42, 0x51, 0x30, 0x8b, 0x4d, + 0xbd, 0x15, 0xfb, 0x6b, 0x65, 0x7b, 0xe6, 0x50, 0x28, 0xa1, 0x89, 0x35, + 0x39, 0x12, 0xd7, 0xc1, 0x6d, 0x6d, 0x49, 0x89, 0x98, 0x5c, 0x15, 0xce, + 0xdc, 0x43, 0x43, 0xf0, 0xce, 0xb6, 0x80, 0x61, 0x7b, 0xc7, 0x27, 0x85, + 0x11, 0xf9, 0x06, 0x8a, 0xbd, 0x61, 0x37, 0x18, 0xa8, 0x62, 0x51, 0x3e, + 0xe5, 0x14, 0xfd, 0xf8, 0x0c, 0xd2, 0x5b, 0x6f, 0x84, 0xc4, 0x88, 0x51, + 0xe6, 0xa7, 0x85, 0x0f, 0xea, 0xea, 0x57, 0xea, 0x20, 0xde, 0xb1, 0x12, + 0x3c, 0xa4, 0x20, 0x6b, 0xde, 0x8a, 0x93, 0xff, 0x99, 0x9e, 0xf7, 0x89, + 0x58, 0x3e, 0x2c, 0x85, 0x0d, 0x9e, 0x06, 0x35 +}; +static const uint8_t ac_dsa_vect208_priv_val[] = { +/* X */ + 0x7e, 0x52, 0x07, 0x0b, 0x03, 0xab, 0xa0, 0xaf, 0x4c, 0xad, 0x1c, 0xba, + 0x0a, 0x73, 0x36, 0x18, 0xe3, 0xad, 0xb7, 0xde, 0x87, 0x3e, 0xfb, 0xa0, + 0x13, 0x87, 0x8f, 0xa7, 0x63, 0x31, 0xb5, 0xe1 +}; +static const uint8_t ac_dsa_vect208_pub_val[] = { +/* Y */ + 0x4e, 0x16, 0x0d, 0x69, 0x70, 0x68, 0x3f, 0x4d, 0x84, 0xeb, 0x88, 0xc5, + 0x5b, 0xa2, 0xda, 0x58, 0xd7, 0x7f, 0x63, 0x74, 0xfc, 0x51, 0x27, 0x27, + 0x3d, 0x65, 0xe8, 0xef, 0x96, 0xcc, 0xff, 0xf5, 0x1d, 0xf6, 0x9b, 0x0e, + 0x2f, 0xdf, 0x3e, 0x98, 0xf6, 0xd3, 0x5e, 0x6a, 0x3d, 0xd9, 0xf7, 0xed, + 0xd9, 0x0b, 0xba, 0xe4, 0xc6, 0x58, 0x1c, 0xd0, 0x2a, 0xd0, 0x13, 0x36, + 0xc0, 0x08, 0x6d, 0x42, 0x48, 0xeb, 0x13, 0x73, 0x48, 0x07, 0x89, 0xf7, + 0xd8, 0x33, 0x3b, 0x83, 0x1d, 0xb3, 0xba, 0xe0, 0xbd, 0xb4, 0x97, 0x89, + 0xaa, 0xb9, 0x3c, 0xde, 0x1f, 0xaf, 0x1c, 0xe8, 0x8d, 0xcd, 0xc7, 0xa1, + 0xa4, 0xf8, 0x61, 0x43, 0xce, 0x44, 0xf8, 0x51, 0xac, 0xe4, 0x59, 0xa5, + 0x52, 0x8c, 0x96, 0x19, 0x5f, 0x44, 0x38, 0xee, 0x7c, 0x18, 0x56, 0xac, + 0x61, 0xfd, 0x50, 0x35, 0xd8, 0x39, 0xd6, 0x2e, 0x48, 0xa1, 0xab, 0x6b, + 0xd2, 0x3a, 0xd5, 0x2f, 0x1f, 0x6f, 0xfe, 0xd1, 0x98, 0x26, 0xb6, 0xd7, + 0xf6, 0x49, 0x1c, 0xfb, 0x05, 0x00, 0x31, 0x76, 0xf2, 0x90, 0x79, 0x45, + 0x54, 0x43, 0xf0, 0xab, 0x48, 0x21, 0x50, 0xfa, 0xc8, 0xe3, 0x2a, 0x39, + 0x02, 0xa4, 0x09, 0x67, 0x75, 0xf3, 0x42, 0xed, 0xee, 0x2d, 0xaf, 0x4c, + 0x4f, 0x33, 0x8d, 0x45, 0x5b, 0x4e, 0xa3, 0x5d, 0x39, 0x75, 0xf7, 0x2b, + 0xe8, 0x5e, 0x98, 0xe8, 0x71, 0x58, 0x48, 0x6b, 0x4c, 0x3d, 0x6e, 0xc3, + 0x7a, 0x37, 0x03, 0xf6, 0x3a, 0x3e, 0x19, 0x27, 0x2b, 0xa5, 0x25, 0x50, + 0x89, 0xaa, 0xcd, 0x30, 0xfa, 0x39, 0x79, 0xb4, 0x58, 0xdf, 0x61, 0x6f, + 0x57, 0xb7, 0x50, 0x2b, 0x42, 0x91, 0x38, 0x45, 0x62, 0x04, 0x1f, 0x61, + 0x88, 0xdb, 0x50, 0x3f, 0x3d, 0xf7, 0xf5, 0x98, 0x1d, 0xa5, 0x70, 0x5e, + 0xb0, 0xf1, 0xd2, 0x42 +}; +/* K = 57c141f543386db3bd6a97121f93b47e38891796f02565058ec6a5ce65f7a212 */ +static const uint8_t ac_dsa_vect208_out[] = { +/* R */ + 0x64, 0x33, 0xbd, 0x33, 0xdb, 0x0a, 0xc8, 0x26, 0x1c, 0x69, 0x1a, 0xf3, + 0xa2, 0x7f, 0x52, 0xcd, 0xd4, 0xa6, 0x5d, 0x79, 0x99, 0x39, 0xfa, 0xf2, + 0x79, 0xac, 0x41, 0x78, 0x8e, 0x75, 0x28, 0xa6, +/* S */ + 0x04, 0xcf, 0xdc, 0xb9, 0x93, 0x38, 0x2e, 0x8f, 0xd2, 0xdb, 0x8d, 0x90, + 0xdc, 0xa8, 0x0e, 0x94, 0xb1, 0x7b, 0x43, 0x20, 0x09, 0x85, 0x2c, 0xd3, + 0xf8, 0x66, 0x25, 0x15, 0x9e, 0x83, 0x7c, 0x19 +}; +#define ac_dsa_vect209_prime ac_dsa_vect196_prime +#define ac_dsa_vect209_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect209_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect209_ptx[] = { +/* Msg */ + 0x2b, 0x43, 0x65, 0xa4, 0xac, 0x68, 0x54, 0xc9, 0x72, 0xda, 0x73, 0x47, + 0xaf, 0x1c, 0xec, 0xc6, 0xed, 0xcb, 0xae, 0x9d, 0x53, 0x3b, 0x74, 0xfb, + 0xe6, 0xdb, 0x57, 0x12, 0x16, 0x3a, 0x6c, 0xe9, 0x84, 0xf9, 0xd7, 0xa4, + 0xc5, 0x4b, 0x44, 0xdd, 0x75, 0x55, 0xe5, 0xc2, 0xd2, 0xf3, 0xd0, 0x98, + 0xf3, 0x1d, 0x51, 0x7f, 0x8e, 0xbd, 0x33, 0x01, 0x99, 0xa5, 0x4b, 0x15, + 0x29, 0x7e, 0x5a, 0xde, 0xe1, 0xbd, 0xf3, 0x91, 0x58, 0x1f, 0x10, 0x19, + 0xb1, 0xad, 0x72, 0xdc, 0xcc, 0xd5, 0x48, 0x4b, 0x51, 0xd2, 0x75, 0xa3, + 0x68, 0xc6, 0x9a, 0x76, 0x62, 0xe7, 0x9f, 0x9b, 0x29, 0xc9, 0xa3, 0x08, + 0x4c, 0x94, 0xae, 0x76, 0xda, 0x04, 0xf9, 0x58, 0xc7, 0xd3, 0x6c, 0xec, + 0xc5, 0xd4, 0x1d, 0x77, 0xf2, 0x30, 0x2f, 0xf2, 0x8f, 0x2e, 0xd9, 0xc6, + 0x6a, 0x06, 0x62, 0xca, 0xbf, 0x51, 0xc8, 0x42 +}; +static const uint8_t ac_dsa_vect209_priv_val[] = { +/* X */ + 0x35, 0xb7, 0x01, 0xb7, 0xd5, 0x9a, 0xad, 0x55, 0xeb, 0x42, 0x99, 0xe0, + 0xf9, 0xe0, 0x34, 0x8b, 0xae, 0xc8, 0x75, 0xea, 0xf6, 0x2d, 0x21, 0x74, + 0xbc, 0xe9, 0x2d, 0xd2, 0x33, 0x02, 0xa8, 0x1a +}; +static const uint8_t ac_dsa_vect209_pub_val[] = { +/* Y */ + 0x58, 0xe6, 0x35, 0xee, 0xc8, 0x0b, 0xde, 0x1e, 0xb7, 0xbf, 0x2d, 0xa2, + 0x06, 0x00, 0x61, 0x7a, 0xf2, 0x9f, 0x0a, 0x19, 0x17, 0x05, 0x67, 0x6b, + 0xc1, 0x0f, 0x75, 0x53, 0xf7, 0x61, 0x11, 0x26, 0xe4, 0xc4, 0xd4, 0x4b, + 0xcf, 0x14, 0xf7, 0xa9, 0xf4, 0x8d, 0xa6, 0xe1, 0xb1, 0xe5, 0x4d, 0x0a, + 0x71, 0x57, 0x24, 0xaf, 0x5b, 0xca, 0x93, 0x86, 0x70, 0x90, 0xf9, 0xbf, + 0xc9, 0x27, 0x41, 0xdf, 0xe1, 0xdd, 0x4f, 0x06, 0x07, 0x5e, 0xc2, 0xa9, + 0x26, 0x2d, 0xa8, 0x1e, 0x0d, 0xca, 0xbf, 0xca, 0xb9, 0xe6, 0x94, 0xdd, + 0xca, 0x86, 0xd0, 0xe1, 0xcf, 0xaa, 0x32, 0x1e, 0x2b, 0x58, 0x18, 0x18, + 0x2e, 0xb6, 0x20, 0xbd, 0x5d, 0x16, 0xbc, 0x27, 0xa2, 0xda, 0x03, 0x5d, + 0x4b, 0xc1, 0x78, 0x07, 0xcf, 0xe8, 0xae, 0x30, 0x38, 0xc5, 0xbb, 0xb8, + 0xa0, 0x23, 0xfb, 0x23, 0x28, 0x14, 0xb9, 0x1b, 0x99, 0x74, 0x9f, 0x51, + 0x9d, 0xe3, 0x9a, 0xa0, 0xf4, 0x34, 0x31, 0x33, 0x23, 0xb1, 0xb5, 0x82, + 0x02, 0xc5, 0x91, 0x19, 0xb0, 0xbe, 0x21, 0x76, 0x17, 0x04, 0x7c, 0x9e, + 0x2e, 0xa4, 0x53, 0xd6, 0x08, 0x56, 0x2c, 0xb9, 0x6c, 0x4f, 0x08, 0x51, + 0xa7, 0x96, 0x5b, 0x16, 0x4f, 0x9b, 0xbe, 0x15, 0x1f, 0x9c, 0x50, 0x8c, + 0xa2, 0x09, 0xf1, 0xaf, 0x65, 0x9e, 0x36, 0x38, 0x04, 0xc8, 0xd8, 0xfa, + 0x1a, 0xd7, 0x00, 0xe2, 0x08, 0x66, 0xec, 0x9a, 0x1e, 0x50, 0x5b, 0x74, + 0xbb, 0xab, 0x70, 0xcb, 0x47, 0x23, 0x08, 0x43, 0x1a, 0x3e, 0x87, 0x27, + 0x2f, 0xeb, 0xf7, 0xcc, 0xe2, 0xc2, 0x0e, 0xc3, 0x7f, 0x5d, 0x68, 0xb4, + 0xe4, 0x7b, 0xf3, 0x74, 0x10, 0x13, 0x72, 0x39, 0x36, 0xdb, 0x7c, 0x9b, + 0x0f, 0x3d, 0xed, 0x96, 0x4a, 0xcb, 0x7f, 0x8a, 0xc9, 0xc5, 0xa6, 0xb4, + 0xf2, 0x8d, 0xe1, 0x98 +}; +/* K = 1c6ceff82adebf8c81bb4842b90dbe2a12c9d07c3a9d4990d44106a1768bb082 */ +static const uint8_t ac_dsa_vect209_out[] = { +/* R */ + 0x00, 0xa7, 0xc6, 0x64, 0xc5, 0x44, 0xcd, 0x7b, 0x61, 0x74, 0x94, 0x10, + 0xdd, 0xa3, 0x3b, 0xb3, 0xa4, 0x7c, 0x3e, 0xb5, 0xa9, 0xa7, 0xbe, 0x5f, + 0xba, 0x20, 0x1a, 0x39, 0x0c, 0xec, 0xfa, 0xef, +/* S */ + 0x6f, 0xbb, 0xda, 0x96, 0x7b, 0x58, 0x4b, 0xd9, 0xec, 0x6a, 0x0a, 0xe7, + 0x6e, 0x0c, 0x55, 0x2b, 0x3d, 0x42, 0xbf, 0x0e, 0x9c, 0xf2, 0x93, 0x9c, + 0xaf, 0x61, 0x23, 0xf6, 0xe8, 0x60, 0x46, 0xf6 +}; +#define ac_dsa_vect210_prime ac_dsa_vect196_prime +#define ac_dsa_vect210_sub_prime ac_dsa_vect196_sub_prime +#define ac_dsa_vect210_base ac_dsa_vect196_base +static const uint8_t ac_dsa_vect210_ptx[] = { +/* Msg */ + 0xca, 0xb1, 0xd1, 0x76, 0x66, 0xb0, 0xc9, 0x65, 0x8c, 0xc7, 0x8c, 0xfc, + 0xba, 0x17, 0xa0, 0x8e, 0x29, 0x89, 0xd3, 0xc2, 0x02, 0xc8, 0xb5, 0x08, + 0x55, 0x31, 0x40, 0x4d, 0x92, 0x8c, 0x61, 0x8b, 0x6e, 0x23, 0x0b, 0x25, + 0xc4, 0x6a, 0x5b, 0x58, 0x43, 0x7e, 0x43, 0x35, 0xfc, 0x04, 0x00, 0x20, + 0xba, 0x00, 0xc8, 0x63, 0x18, 0x23, 0x25, 0x94, 0x0f, 0x00, 0xaa, 0xd3, + 0x30, 0x14, 0x5e, 0x66, 0x6d, 0x07, 0xe9, 0xe9, 0xd8, 0x76, 0x13, 0x70, + 0x10, 0x93, 0x2a, 0xe5, 0x20, 0xd9, 0x18, 0x8c, 0xa3, 0xd7, 0x99, 0x3c, + 0x90, 0x53, 0x95, 0x21, 0x9c, 0x55, 0x84, 0x6d, 0x19, 0xb8, 0xfc, 0xdb, + 0x1d, 0x0c, 0x15, 0x86, 0xb9, 0xb5, 0x10, 0x97, 0xaf, 0xd6, 0x97, 0x2a, + 0xe1, 0x47, 0x2b, 0x0e, 0x20, 0x45, 0x3f, 0x8f, 0xbd, 0x5d, 0x6a, 0xa9, + 0xe4, 0xa9, 0xa9, 0xb3, 0xdc, 0x37, 0xdd, 0x8f +}; +static const uint8_t ac_dsa_vect210_priv_val[] = { +/* X */ + 0x1c, 0xa2, 0xb2, 0x91, 0x70, 0x7c, 0xe4, 0xf7, 0x0e, 0x36, 0x6e, 0xe9, + 0x7b, 0x5d, 0xa1, 0x58, 0xa1, 0xc9, 0x85, 0xba, 0x4f, 0x25, 0x2c, 0x57, + 0x2f, 0x0f, 0xb3, 0x29, 0xe4, 0x3f, 0x9c, 0xb9 +}; +static const uint8_t ac_dsa_vect210_pub_val[] = { +/* Y */ + 0x50, 0x22, 0xc8, 0xa6, 0xfa, 0x79, 0xb7, 0xaa, 0x11, 0xa3, 0xd7, 0xaf, + 0x5a, 0xce, 0xbb, 0x2e, 0xf8, 0xc5, 0x0b, 0x28, 0xd8, 0xf0, 0xe3, 0xa5, + 0x56, 0x19, 0x65, 0x62, 0xd3, 0x41, 0x31, 0xfb, 0x44, 0xf2, 0x2c, 0x3b, + 0xe3, 0xf9, 0x89, 0x5e, 0x35, 0xee, 0xe7, 0x0a, 0xa5, 0x3b, 0x6c, 0x67, + 0x92, 0x0c, 0x54, 0x0b, 0xa6, 0xc1, 0x08, 0x5b, 0x0e, 0xa8, 0x18, 0xb1, + 0x2a, 0xea, 0x81, 0x1f, 0x2d, 0xfa, 0xeb, 0x6d, 0xae, 0xd9, 0x76, 0xe3, + 0x62, 0x43, 0x07, 0x98, 0xfd, 0xcc, 0xa3, 0x91, 0x2a, 0x08, 0x91, 0xe7, + 0xd1, 0xc8, 0x3b, 0x74, 0x8a, 0xf1, 0xe7, 0x68, 0x9e, 0x03, 0x8b, 0x49, + 0x0e, 0xb7, 0x3f, 0x7f, 0xe6, 0xe0, 0x61, 0x2e, 0x8f, 0x23, 0x85, 0x80, + 0xe7, 0x88, 0x33, 0xb2, 0x07, 0x27, 0xa6, 0x02, 0x76, 0x8a, 0xb2, 0xd5, + 0x9d, 0xda, 0x36, 0xe7, 0x51, 0x46, 0xfa, 0x4d, 0x36, 0x64, 0xf7, 0xb0, + 0xce, 0xf7, 0xbe, 0x87, 0x7a, 0xfd, 0xcd, 0xba, 0x23, 0x00, 0x4e, 0xe3, + 0x13, 0xa6, 0x9f, 0xd6, 0x1c, 0x32, 0x67, 0x59, 0xe7, 0xe7, 0x79, 0xad, + 0x75, 0x0f, 0x7a, 0x5c, 0xad, 0x9f, 0xb2, 0xdd, 0x80, 0xa8, 0xee, 0xa6, + 0xdc, 0xbd, 0xa0, 0x19, 0x5d, 0xcc, 0x17, 0xb3, 0x8a, 0xd6, 0xf0, 0xe2, + 0xab, 0x68, 0xcf, 0xc6, 0x9b, 0x15, 0xc5, 0x72, 0xf8, 0x5f, 0x20, 0xc3, + 0x67, 0x9c, 0x15, 0xa8, 0x30, 0x99, 0xcf, 0x08, 0xa3, 0x79, 0x05, 0x5f, + 0x8f, 0xbd, 0xd8, 0xf5, 0x90, 0xd4, 0x3b, 0xd1, 0x2f, 0x75, 0xba, 0xf0, + 0xec, 0xcd, 0x6c, 0x07, 0x7a, 0xc7, 0x58, 0x9a, 0xab, 0x81, 0x71, 0xe8, + 0x87, 0x5d, 0xb0, 0x12, 0x2e, 0x6c, 0x78, 0x61, 0x7c, 0x13, 0x58, 0x61, + 0x43, 0xa7, 0xeb, 0xe9, 0x04, 0xa7, 0x82, 0x2b, 0xac, 0xf4, 0x8a, 0x75, + 0x27, 0xf7, 0xfa, 0x4e +}; +/* K = 4f1e2aae323c5309b3ee5d3b73e5d4090c75da17765559e118bfd1460c312859 */ +static const uint8_t ac_dsa_vect210_out[] = { +/* R */ + 0x7b, 0x8b, 0x75, 0xac, 0x85, 0x14, 0xc6, 0x8d, 0xe0, 0xca, 0xa9, 0x8e, + 0x9d, 0xe0, 0xb9, 0x60, 0x72, 0x53, 0xd8, 0x08, 0x8d, 0x3f, 0xea, 0xdf, + 0x92, 0xb8, 0x3f, 0xfc, 0x26, 0xe0, 0x88, 0xce, +/* S */ + 0x4b, 0x10, 0xe1, 0x7f, 0xf6, 0x4a, 0x0e, 0xb7, 0x2f, 0x70, 0xa8, 0x63, + 0xd0, 0x0a, 0x9b, 0xf3, 0x31, 0xbb, 0xb5, 0x15, 0xba, 0x3a, 0x9f, 0xef, + 0x72, 0x75, 0x3a, 0xd7, 0xf0, 0xdf, 0x0b, 0xe5 +}; +/* [mod = L=2048, N=256, SHA-512] */ +static const uint8_t ac_dsa_vect211_prime[] = { +/* P */ + 0xf6, 0x3d, 0xa3, 0xbe, 0x9a, 0x96, 0x16, 0x19, 0x6c, 0x65, 0x56, 0xf3, + 0xce, 0x6f, 0xd8, 0xb9, 0x8b, 0xdd, 0xa9, 0x13, 0x74, 0x73, 0xda, 0x46, + 0xfe, 0xd9, 0x70, 0xe2, 0xb8, 0xd1, 0x47, 0x38, 0x7a, 0x81, 0x92, 0x20, + 0x65, 0xd5, 0x28, 0xa7, 0xd6, 0x43, 0x3e, 0xbc, 0x5e, 0x35, 0xb1, 0x5c, + 0x67, 0xea, 0x35, 0xa5, 0xa5, 0xbf, 0xf5, 0xb9, 0xce, 0xf1, 0xcd, 0x1e, + 0x6f, 0xe3, 0x1d, 0xda, 0x52, 0x83, 0x8d, 0xa3, 0xaa, 0x89, 0xb9, 0xb4, + 0xe8, 0xd9, 0xd3, 0xc0, 0x73, 0x2c, 0xcc, 0x4f, 0x23, 0x8c, 0xe1, 0xb4, + 0x16, 0xc4, 0xca, 0x93, 0xf2, 0xc6, 0x80, 0x0e, 0x5f, 0x4e, 0xd4, 0x1c, + 0x4f, 0x76, 0x15, 0xce, 0xc5, 0x53, 0x1b, 0x98, 0x68, 0x0b, 0x20, 0xdc, + 0x63, 0xf7, 0x3e, 0x70, 0xd8, 0x03, 0xaa, 0xcf, 0xae, 0xce, 0x33, 0xd4, + 0x5f, 0xa0, 0xe3, 0x9d, 0x77, 0xc8, 0x50, 0x82, 0x09, 0x52, 0x8b, 0x90, + 0x46, 0xb5, 0x91, 0x70, 0x10, 0x79, 0x12, 0x34, 0x39, 0x7e, 0x41, 0x2d, + 0x22, 0xbc, 0x0b, 0x8d, 0x67, 0xcb, 0xd1, 0xcd, 0x28, 0xa3, 0x2c, 0x24, + 0x60, 0xa0, 0xbd, 0x86, 0xaa, 0xba, 0x0e, 0xea, 0x80, 0xe1, 0x6e, 0x32, + 0x45, 0x64, 0x31, 0x71, 0xe3, 0x42, 0x21, 0x76, 0x0c, 0x20, 0x3a, 0x56, + 0xb8, 0x20, 0x7a, 0x10, 0x09, 0xe6, 0xc1, 0xa2, 0xf6, 0xcd, 0xa8, 0x5f, + 0x85, 0xc4, 0xf9, 0xe4, 0x10, 0xb9, 0x49, 0x92, 0x33, 0xc0, 0xee, 0x07, + 0x2e, 0x46, 0x5a, 0xf4, 0xfb, 0x4f, 0xb9, 0x28, 0x2c, 0x5c, 0x10, 0xe8, + 0x23, 0x4f, 0xd6, 0x30, 0xea, 0x92, 0xf0, 0xaa, 0xe6, 0xb9, 0x7a, 0x52, + 0x0d, 0xb3, 0x44, 0x75, 0x70, 0x7b, 0x79, 0xa4, 0xc1, 0x75, 0x26, 0x5c, + 0x03, 0x56, 0xcc, 0xbc, 0xa8, 0x27, 0xe3, 0x83, 0x7d, 0xf3, 0xd6, 0xd0, + 0x57, 0x6d, 0x90, 0x79 +}; +static const uint8_t ac_dsa_vect211_sub_prime[] = { +/* Q */ + 0x9b, 0x74, 0x63, 0xf8, 0x26, 0x9f, 0x0b, 0x90, 0x9a, 0xbe, 0xd1, 0x09, + 0x91, 0x68, 0x4f, 0x36, 0xa6, 0x4a, 0xc8, 0x64, 0xe0, 0xd6, 0xd7, 0x17, + 0xc0, 0xef, 0x21, 0x57, 0x7a, 0x4c, 0x39, 0x07 +}; +static const uint8_t ac_dsa_vect211_base[] = { +/* G */ + 0x97, 0x2a, 0x75, 0xf6, 0x06, 0xe8, 0xaa, 0x3a, 0x91, 0xff, 0x08, 0xfd, + 0x13, 0x1a, 0x20, 0xf5, 0x96, 0x32, 0x51, 0x30, 0x4e, 0x3d, 0x14, 0x31, + 0xb7, 0x12, 0xfa, 0x08, 0x03, 0xd5, 0x27, 0xfd, 0x71, 0x0f, 0xb7, 0xeb, + 0x27, 0xe5, 0x29, 0x04, 0x97, 0x1c, 0xd4, 0x3c, 0xa9, 0x77, 0x19, 0x9a, + 0x24, 0xdb, 0xee, 0xb4, 0xb7, 0xbc, 0x2b, 0xa0, 0x75, 0xd3, 0xb7, 0x2e, + 0xb6, 0xb2, 0xc5, 0xad, 0x8f, 0x0e, 0x8b, 0x8f, 0x48, 0xc5, 0x0b, 0x55, + 0x4c, 0x7e, 0x07, 0x11, 0xf4, 0xc7, 0x41, 0x63, 0x30, 0x80, 0x66, 0x72, + 0x49, 0x8f, 0x43, 0x02, 0x92, 0x72, 0x4b, 0xf9, 0x8a, 0x8e, 0xa4, 0x8c, + 0x7f, 0x53, 0xd7, 0xb3, 0x1d, 0x8b, 0x75, 0x28, 0xb1, 0xa6, 0xf0, 0x87, + 0xd2, 0xc2, 0x7c, 0x33, 0x52, 0x02, 0x83, 0x5b, 0x1e, 0x31, 0x42, 0x25, + 0xb3, 0x7a, 0xef, 0x8b, 0xfc, 0xec, 0x7d, 0x80, 0x92, 0x0c, 0x4a, 0x46, + 0x0a, 0x3d, 0x68, 0x34, 0x4d, 0xed, 0x75, 0xed, 0x9e, 0xe8, 0x67, 0xfa, + 0x2a, 0x69, 0x45, 0x06, 0x38, 0x94, 0xf5, 0x63, 0xb6, 0x86, 0x33, 0xb8, + 0xb3, 0x9f, 0x83, 0xa1, 0xaa, 0xaf, 0x5a, 0x96, 0xc7, 0xf4, 0x22, 0x68, + 0x7e, 0x7c, 0x84, 0xcf, 0x8f, 0xb8, 0xcc, 0x5f, 0x45, 0x04, 0xdf, 0xf0, + 0x87, 0xbc, 0xb2, 0x6a, 0x95, 0xbb, 0xf8, 0x58, 0x3f, 0x03, 0xb3, 0xa0, + 0xe4, 0x3a, 0x35, 0x6b, 0x2b, 0xd7, 0xe2, 0x5c, 0xdd, 0xdf, 0x7a, 0x01, + 0x53, 0x00, 0xfa, 0xec, 0xc6, 0x79, 0x3c, 0x5e, 0xe9, 0x9b, 0x63, 0x27, + 0xcb, 0x84, 0x56, 0xe3, 0x2d, 0x91, 0x15, 0x33, 0x9d, 0x5a, 0x6b, 0x71, + 0x2b, 0x7f, 0x9d, 0x03, 0x01, 0xac, 0xb0, 0x51, 0x33, 0xe3, 0x11, 0x5e, + 0x45, 0x4d, 0x3a, 0x6d, 0xd2, 0x4a, 0x16, 0x93, 0xc9, 0x4a, 0xab, 0x54, + 0x06, 0x50, 0x4b, 0xf7 +}; +static const uint8_t ac_dsa_vect211_ptx[] = { +/* Msg */ + 0x8a, 0xb0, 0x15, 0x10, 0xcf, 0xa3, 0x3c, 0xfa, 0x5b, 0xcf, 0xf0, 0x03, + 0xbb, 0xa3, 0x99, 0x96, 0xfa, 0x72, 0x76, 0x93, 0xab, 0xf6, 0xac, 0x01, + 0x0b, 0xb9, 0x59, 0xb0, 0xb5, 0x9a, 0x15, 0x30, 0x6c, 0x0c, 0x3a, 0x19, + 0x21, 0xaf, 0x2a, 0x76, 0x71, 0x7a, 0xa5, 0x5b, 0x39, 0xfa, 0x37, 0x23, + 0xf4, 0xc3, 0x22, 0x9c, 0xa9, 0xac, 0xf6, 0xb7, 0x41, 0x61, 0x4b, 0xb5, + 0x51, 0xcd, 0xe8, 0xa7, 0x22, 0x0a, 0xb9, 0x7d, 0x4b, 0x45, 0x3b, 0xec, + 0x1e, 0x05, 0xa0, 0xea, 0xa4, 0x2e, 0x38, 0x2b, 0xbc, 0x7b, 0x9b, 0x84, + 0xf8, 0x23, 0x7d, 0xc8, 0x96, 0x4e, 0xe5, 0xb6, 0x6e, 0x9b, 0x2a, 0x4c, + 0xa6, 0x1c, 0xf6, 0x75, 0x14, 0x0e, 0xfe, 0xf5, 0x4f, 0xb3, 0x27, 0xa6, + 0x65, 0xde, 0xf8, 0xd5, 0x7a, 0xb0, 0x97, 0xe8, 0xc5, 0x3c, 0x64, 0x3f, + 0xcb, 0x58, 0x20, 0x9c, 0x42, 0x15, 0xb6, 0x08 +}; +static const uint8_t ac_dsa_vect211_priv_val[] = { +/* X */ + 0x5f, 0x6e, 0x54, 0x5d, 0xae, 0xf6, 0xcd, 0x1b, 0x8d, 0x98, 0x48, 0xdd, + 0x98, 0x75, 0x88, 0x07, 0x23, 0x6a, 0xc0, 0xb7, 0xff, 0x05, 0x3b, 0x32, + 0xc7, 0x03, 0xea, 0xa3, 0xb1, 0x14, 0x75, 0x57 +}; +static const uint8_t ac_dsa_vect211_pub_val[] = { +/* Y */ + 0x41, 0x19, 0x7c, 0xe2, 0x23, 0x3d, 0x7e, 0x48, 0xc8, 0x03, 0xcd, 0x64, + 0xc7, 0x8f, 0x65, 0x79, 0x23, 0xb9, 0xe3, 0x6b, 0x87, 0x14, 0x01, 0xf8, + 0x66, 0x1c, 0x21, 0xd8, 0xba, 0x38, 0xc6, 0xb9, 0xb3, 0x23, 0x9d, 0xb7, + 0x67, 0xb1, 0x1d, 0x1d, 0x40, 0x1e, 0x5f, 0xae, 0xcb, 0xf7, 0xa4, 0x58, + 0x60, 0xcc, 0x5f, 0x1a, 0x54, 0xd6, 0x02, 0x86, 0xb7, 0xd6, 0xe1, 0xc9, + 0x9f, 0xd5, 0xb8, 0xc8, 0x4e, 0xd8, 0x51, 0xc5, 0x35, 0x7d, 0x41, 0xad, + 0x60, 0x16, 0x3f, 0x22, 0x4d, 0x78, 0xc9, 0x96, 0x14, 0x3f, 0xff, 0x89, + 0xdd, 0x3a, 0x8f, 0xe1, 0x23, 0xda, 0xe1, 0xf6, 0x21, 0x42, 0x7f, 0xd8, + 0xcc, 0xe7, 0x6e, 0xd1, 0x38, 0xd6, 0x8f, 0xa2, 0x48, 0xf3, 0x74, 0xae, + 0x23, 0x32, 0x49, 0x62, 0x5b, 0x93, 0xf3, 0xdd, 0x59, 0x37, 0xd1, 0x5e, + 0x54, 0x1b, 0x7e, 0xff, 0xa4, 0xdf, 0x4f, 0xea, 0x7d, 0x52, 0xfa, 0xce, + 0xd6, 0x15, 0xbf, 0xe0, 0x34, 0x84, 0x18, 0xff, 0x93, 0xe6, 0x9a, 0x20, + 0xa5, 0x2e, 0x55, 0xc7, 0x6c, 0xc3, 0x0f, 0x30, 0x7f, 0x84, 0xe7, 0x1e, + 0x4a, 0xab, 0xc0, 0x82, 0x5e, 0xca, 0x3a, 0x95, 0xb4, 0xbd, 0x58, 0xeb, + 0xfb, 0x00, 0x29, 0xd2, 0x3a, 0x16, 0x9e, 0x9d, 0x80, 0xba, 0x7d, 0x1c, + 0x5f, 0xd3, 0x53, 0x95, 0xe6, 0x60, 0x2e, 0x08, 0x9a, 0xa9, 0x91, 0x8f, + 0x08, 0xba, 0xe3, 0x5a, 0xe1, 0xca, 0xc7, 0xaf, 0x33, 0x69, 0x41, 0x29, + 0xe9, 0x8f, 0x0d, 0xad, 0xad, 0xd9, 0x0e, 0xae, 0xb6, 0xee, 0xd2, 0x50, + 0x24, 0x39, 0x0b, 0x1a, 0x60, 0xaf, 0x79, 0x47, 0x34, 0xc3, 0x97, 0xb0, + 0xf5, 0x09, 0x86, 0x5b, 0x13, 0x4b, 0x28, 0x67, 0xc1, 0x15, 0xd6, 0xf4, + 0x89, 0xb6, 0xdd, 0x7e, 0x3c, 0x82, 0x99, 0x4b, 0x45, 0xdc, 0xe2, 0xa2, + 0x3c, 0x6b, 0xc9, 0x02 +}; +/* K = 5fe61afddbdf04449b24295a52a1a037d3f31441a3cec138b7f0102db86ef132 */ +static const uint8_t ac_dsa_vect211_out[] = { +/* R */ + 0x6a, 0x47, 0xea, 0x57, 0xce, 0xae, 0xcc, 0x11, 0x6d, 0x71, 0x90, 0xff, + 0x6c, 0x6d, 0xd9, 0x83, 0x1a, 0xb7, 0x5b, 0x4b, 0xf6, 0xcb, 0x29, 0x10, + 0x83, 0xe4, 0x26, 0x8b, 0x48, 0x6e, 0xd2, 0x45, +/* S */ + 0x01, 0x73, 0x55, 0xf6, 0x98, 0xa3, 0x2a, 0xbe, 0x9a, 0x4d, 0x4a, 0x7d, + 0xda, 0x7c, 0x85, 0x95, 0x0c, 0xdd, 0xc3, 0x48, 0xab, 0x8a, 0x67, 0x51, + 0xe7, 0x2f, 0xdd, 0xc0, 0x1a, 0xa5, 0xd1, 0xf0 +}; +#define ac_dsa_vect212_prime ac_dsa_vect211_prime +#define ac_dsa_vect212_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect212_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect212_ptx[] = { +/* Msg */ + 0xb2, 0xf5, 0x69, 0x48, 0xa3, 0x36, 0x98, 0x2a, 0x5b, 0xcb, 0x4b, 0xb5, + 0xd7, 0x9e, 0x3f, 0xe5, 0xc3, 0x60, 0x81, 0xbd, 0x28, 0x6e, 0x6e, 0x02, + 0x1a, 0xb2, 0x9b, 0x52, 0x2f, 0x0b, 0xe5, 0xff, 0x5e, 0x81, 0xe6, 0x38, + 0xf2, 0x3d, 0x07, 0x81, 0xc2, 0x68, 0xa8, 0x9b, 0x09, 0x33, 0x25, 0x75, + 0xcb, 0x31, 0xc0, 0x80, 0x4b, 0xbd, 0x34, 0xc8, 0x05, 0x89, 0xfb, 0x11, + 0x57, 0x0f, 0xc6, 0x5b, 0x3f, 0x67, 0x61, 0x26, 0x05, 0xa9, 0x41, 0x1c, + 0xda, 0xb3, 0xac, 0x00, 0xff, 0x3f, 0xce, 0x33, 0xab, 0x22, 0xc4, 0x6d, + 0x26, 0xbf, 0x9c, 0x3f, 0xc5, 0xad, 0x2d, 0x90, 0x18, 0xde, 0xb9, 0xb6, + 0x69, 0xb5, 0x0f, 0xbf, 0xba, 0xf8, 0xbe, 0xd6, 0x23, 0x0c, 0x7b, 0xd6, + 0x21, 0xd5, 0x64, 0xfb, 0x1a, 0xf9, 0x53, 0xf0, 0xe8, 0x2c, 0x5b, 0x55, + 0x20, 0xab, 0x97, 0xba, 0xcc, 0xf5, 0x8d, 0x6e +}; +static const uint8_t ac_dsa_vect212_priv_val[] = { +/* X */ + 0x91, 0xe0, 0x16, 0x26, 0x20, 0x88, 0x63, 0xa9, 0x54, 0xeb, 0x89, 0x87, + 0xf8, 0xe9, 0x87, 0xc8, 0xe6, 0x21, 0x35, 0x36, 0xbb, 0x18, 0xf5, 0xaf, + 0xe3, 0xbd, 0x66, 0xa5, 0x25, 0xbb, 0xad, 0xfc +}; +static const uint8_t ac_dsa_vect212_pub_val[] = { +/* Y */ + 0x72, 0xb8, 0x4e, 0xb6, 0xa6, 0x0c, 0x68, 0x6f, 0x74, 0xf3, 0x76, 0xe2, + 0x6b, 0x2e, 0x47, 0xe4, 0x4a, 0x6d, 0x5d, 0xd9, 0x2c, 0x06, 0xfd, 0xe4, + 0x9f, 0xaa, 0xd0, 0xaf, 0x9b, 0x11, 0xe4, 0x31, 0x47, 0xce, 0x93, 0x08, + 0xef, 0x35, 0x01, 0xa7, 0x52, 0xe7, 0xbf, 0x18, 0xe9, 0xe6, 0xdf, 0x3c, + 0x0a, 0x49, 0xc4, 0x4c, 0xd2, 0x51, 0x5a, 0x05, 0x50, 0x8f, 0x80, 0x60, + 0xa6, 0x1e, 0x6e, 0x6f, 0x1b, 0x2e, 0xcf, 0x14, 0xb3, 0x38, 0xcf, 0x0f, + 0xd8, 0xb7, 0xcc, 0xbe, 0x67, 0x8d, 0x52, 0xdb, 0xdf, 0x20, 0x35, 0x2c, + 0x15, 0x5a, 0x2b, 0xd5, 0x17, 0xd8, 0x27, 0xd6, 0xce, 0xfb, 0xf4, 0x8c, + 0x56, 0x79, 0xc9, 0x98, 0x29, 0x8e, 0x21, 0x86, 0xef, 0x10, 0x98, 0x16, + 0x0d, 0xfb, 0x65, 0x91, 0x45, 0x06, 0xa1, 0x77, 0x94, 0x3a, 0x4a, 0x05, + 0x82, 0x82, 0x38, 0x2d, 0x32, 0x7a, 0xd3, 0x6f, 0x88, 0x30, 0x1b, 0xe6, + 0x93, 0xc0, 0x20, 0x00, 0xc7, 0x24, 0x63, 0xe6, 0x82, 0x42, 0x1a, 0x02, + 0x37, 0x80, 0x4d, 0xbb, 0x27, 0x33, 0x5c, 0x78, 0xe8, 0x49, 0x5f, 0xac, + 0x78, 0x42, 0xd2, 0xaa, 0xfe, 0xbf, 0x90, 0xf3, 0xc3, 0x60, 0x5f, 0x75, + 0x86, 0x15, 0xdf, 0x98, 0x9f, 0xdb, 0xd0, 0x6e, 0x23, 0xe4, 0xad, 0x69, + 0x74, 0xb6, 0x23, 0x84, 0xf0, 0xaa, 0x01, 0x02, 0x7d, 0xb8, 0x9a, 0xc3, + 0xdc, 0xb0, 0x1c, 0xb5, 0x25, 0x8c, 0xdb, 0xd9, 0xc1, 0x93, 0x72, 0xa6, + 0xc4, 0xaa, 0xdf, 0x27, 0x29, 0x80, 0x62, 0xac, 0x9a, 0x16, 0xde, 0x2e, + 0xb0, 0x76, 0xe1, 0x67, 0xad, 0x7c, 0x65, 0xd0, 0x50, 0x5c, 0x8f, 0xce, + 0xcf, 0x35, 0x9b, 0xb5, 0xd0, 0x5c, 0xd2, 0x2e, 0x7d, 0x48, 0x62, 0x9a, + 0xf5, 0x39, 0xfe, 0x7f, 0x60, 0xe2, 0x3e, 0x95, 0x7c, 0x84, 0xc7, 0xa6, + 0x1a, 0xc9, 0x2b, 0xf8 +}; +/* K = 6aff566d97cc48ef6bac507d64973c95da14fd704d3a5332aaaca2bdf21e894e */ +static const uint8_t ac_dsa_vect212_out[] = { +/* R */ + 0x43, 0x70, 0x4e, 0x96, 0xcc, 0x8d, 0x63, 0xe6, 0xf5, 0xb7, 0xe1, 0x18, + 0xcb, 0x7c, 0x03, 0x0d, 0x0b, 0xd5, 0x63, 0xb8, 0xf7, 0xa1, 0xa3, 0x04, + 0xb3, 0x68, 0xa6, 0xc6, 0x6d, 0x7e, 0x7f, 0xa8, +/* S */ + 0x49, 0x0d, 0xa4, 0x3f, 0xd0, 0xf1, 0x9f, 0xec, 0x4e, 0xe0, 0x81, 0xcc, + 0xe2, 0x5d, 0xf6, 0xb2, 0x72, 0x0b, 0x1a, 0x76, 0xb0, 0x23, 0xc1, 0x57, + 0x04, 0xdd, 0x03, 0xef, 0x1c, 0x3e, 0x48, 0xa7 +}; +#define ac_dsa_vect213_prime ac_dsa_vect211_prime +#define ac_dsa_vect213_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect213_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect213_ptx[] = { +/* Msg */ + 0x9a, 0xe8, 0x47, 0x93, 0x27, 0xb8, 0xb8, 0xa5, 0x7f, 0x57, 0x0f, 0x6e, + 0xc7, 0x6a, 0x1a, 0xc6, 0xf0, 0x2b, 0x19, 0x8c, 0x60, 0x48, 0xa1, 0xf0, + 0x96, 0xe6, 0xce, 0x56, 0x30, 0xb6, 0xca, 0xf3, 0x63, 0x17, 0x64, 0x13, + 0xd8, 0x80, 0x33, 0xb1, 0xcd, 0x07, 0xf4, 0xd3, 0x96, 0x0a, 0x12, 0xdb, + 0xae, 0x8a, 0x65, 0x91, 0x74, 0xbb, 0x87, 0xc3, 0x7a, 0xca, 0x6e, 0xc5, + 0x6e, 0xd5, 0xa6, 0x61, 0x9b, 0x8b, 0xa6, 0x76, 0xb6, 0x50, 0xd9, 0x7c, + 0x6a, 0x21, 0xaf, 0x02, 0x39, 0x85, 0xdc, 0x36, 0x1f, 0xa2, 0x34, 0xb2, + 0xb3, 0xc1, 0x7e, 0x77, 0x70, 0x3b, 0xa9, 0x9a, 0xe3, 0x21, 0x12, 0x60, + 0xda, 0x10, 0xa6, 0x0f, 0x24, 0x0e, 0xee, 0xf4, 0x78, 0xf2, 0x64, 0x11, + 0x84, 0xa2, 0x81, 0x71, 0x6a, 0xe5, 0x78, 0x88, 0x11, 0x7d, 0xba, 0x99, + 0x28, 0x53, 0xf4, 0x94, 0xac, 0x3c, 0xaa, 0x45 +}; +static const uint8_t ac_dsa_vect213_priv_val[] = { +/* X */ + 0x8a, 0x56, 0x24, 0x69, 0x4a, 0x25, 0x20, 0x9a, 0x5f, 0xb3, 0x98, 0x3e, + 0xca, 0xc3, 0xfe, 0xdf, 0x50, 0x8e, 0x0b, 0x23, 0xe8, 0x78, 0xf6, 0x0a, + 0x18, 0xec, 0x0e, 0x89, 0x7c, 0x37, 0x9f, 0x7b +}; +static const uint8_t ac_dsa_vect213_pub_val[] = { +/* Y */ + 0xce, 0x34, 0x8b, 0x5c, 0xb3, 0xd3, 0x68, 0x08, 0x42, 0x2a, 0x50, 0x16, + 0xdd, 0x58, 0x73, 0xdf, 0x79, 0xf3, 0xcb, 0xb5, 0xe1, 0xb4, 0x58, 0xe8, + 0xc1, 0x11, 0x02, 0x26, 0x04, 0x75, 0x43, 0xd9, 0x65, 0x76, 0x9a, 0x11, + 0x2a, 0xdb, 0x4f, 0xce, 0xd0, 0xd1, 0x46, 0x23, 0x09, 0x62, 0xa8, 0xd4, + 0x13, 0x22, 0x5c, 0xc7, 0x0d, 0x81, 0x0d, 0x40, 0xe6, 0xa7, 0x2e, 0x6d, + 0xc8, 0x0d, 0xb5, 0x09, 0x40, 0x0c, 0x09, 0xd2, 0x63, 0xd6, 0x62, 0x06, + 0x96, 0x6e, 0xd5, 0x1a, 0xb6, 0x59, 0x30, 0xa2, 0xaa, 0xc9, 0x9f, 0xcc, + 0xe3, 0xa3, 0x98, 0xb6, 0x4d, 0x59, 0x09, 0x76, 0x83, 0xd2, 0xba, 0xa5, + 0x76, 0x82, 0x70, 0x5a, 0xbc, 0x32, 0xeb, 0x8c, 0x32, 0xd6, 0xf1, 0xe7, + 0xd9, 0x4c, 0xa1, 0x7e, 0xd7, 0x06, 0x78, 0x22, 0xcd, 0x20, 0xfb, 0xa3, + 0x79, 0x5e, 0xd1, 0x84, 0x3c, 0x01, 0xb0, 0xd7, 0x55, 0x1c, 0x7c, 0x4c, + 0x75, 0x9d, 0x53, 0xa4, 0x19, 0x14, 0x83, 0xbd, 0xc6, 0xe3, 0x12, 0x1c, + 0x2b, 0xc1, 0x26, 0x07, 0x70, 0x1f, 0x43, 0xe3, 0xba, 0x38, 0x2c, 0x67, + 0x66, 0x81, 0x9d, 0xb0, 0x7e, 0xf9, 0xc5, 0x95, 0x86, 0x93, 0x75, 0x14, + 0x77, 0x2c, 0x2e, 0xcc, 0xde, 0x4c, 0x54, 0xd9, 0x25, 0x75, 0x73, 0x4c, + 0x45, 0xa8, 0xe8, 0x32, 0xc4, 0x41, 0x7b, 0x43, 0xa9, 0x2c, 0x9a, 0xbd, + 0x15, 0x22, 0x59, 0xcc, 0x0a, 0x96, 0x9b, 0xac, 0x64, 0xb2, 0x37, 0xbb, + 0x3a, 0x08, 0x26, 0xae, 0x72, 0x91, 0x9d, 0x7c, 0x2d, 0xd2, 0xef, 0xdf, + 0x03, 0xe8, 0x37, 0x01, 0x98, 0x0c, 0x2a, 0x8f, 0x50, 0xce, 0x6e, 0x44, + 0xd7, 0xcc, 0x88, 0x48, 0x64, 0x5b, 0xf4, 0x0a, 0xef, 0xdf, 0x24, 0xfa, + 0x7a, 0x6d, 0xce, 0x5a, 0x3b, 0x9a, 0xca, 0x6f, 0x01, 0x76, 0x18, 0xa6, + 0x4d, 0x91, 0xce, 0x4b +}; +/* K = 86c3ce567e7995a61bc00e088ff2f2a425433a453252b1a729d8d85ed506bdec */ +static const uint8_t ac_dsa_vect213_out[] = { +/* R */ + 0x00, 0x91, 0xd7, 0x50, 0xad, 0x9a, 0x4f, 0x29, 0x57, 0x3f, 0xd4, 0x57, + 0xa5, 0x89, 0x1b, 0x68, 0xd4, 0xb6, 0xc1, 0x57, 0x03, 0xa2, 0xbc, 0x19, + 0x2c, 0x7c, 0x62, 0x0c, 0x4e, 0x4c, 0x45, 0x29, +/* S */ + 0x92, 0xc4, 0x09, 0xc8, 0x97, 0x79, 0x75, 0xa4, 0x17, 0xd9, 0xf5, 0xe0, + 0xe2, 0xdc, 0x70, 0x68, 0x3a, 0x53, 0xa9, 0x56, 0x62, 0xad, 0x27, 0x0a, + 0xe3, 0x5d, 0x49, 0x65, 0x67, 0xa9, 0xa2, 0xfc +}; +#define ac_dsa_vect214_prime ac_dsa_vect211_prime +#define ac_dsa_vect214_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect214_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect214_ptx[] = { +/* Msg */ + 0xe5, 0xa1, 0xa3, 0x44, 0xc2, 0x5b, 0xa0, 0xcb, 0xbc, 0xff, 0xe6, 0x80, + 0x01, 0x35, 0xf2, 0xed, 0xe8, 0x10, 0x49, 0x18, 0x0f, 0xb2, 0x75, 0x9f, + 0xd9, 0xe1, 0xaf, 0x3b, 0x81, 0x6a, 0xd5, 0x43, 0x6a, 0x24, 0xfa, 0xf2, + 0x9c, 0xf3, 0xad, 0x91, 0xcf, 0x41, 0x33, 0x32, 0xf4, 0x54, 0xf7, 0x4a, + 0x9d, 0x4f, 0x5e, 0xfe, 0x76, 0xcf, 0x02, 0x51, 0x2c, 0x27, 0x3c, 0xd5, + 0x25, 0xf0, 0x4a, 0xfd, 0xb5, 0xc2, 0x4b, 0x05, 0x88, 0xd6, 0x11, 0xd7, + 0x21, 0x53, 0x68, 0x0d, 0x1e, 0x39, 0x95, 0xe0, 0xaa, 0x75, 0x0e, 0x90, + 0x77, 0xb0, 0x75, 0x2b, 0xd4, 0x44, 0x2b, 0xf7, 0xbf, 0xa8, 0xdb, 0xa3, + 0x8e, 0x1c, 0x5e, 0x7d, 0xdd, 0x68, 0x7f, 0x55, 0xaa, 0x54, 0xc1, 0x38, + 0xc7, 0xe6, 0xd5, 0xf0, 0x64, 0xf3, 0xec, 0x55, 0x94, 0x2d, 0xc1, 0x92, + 0xdd, 0x99, 0x6e, 0x55, 0x36, 0x33, 0xaf, 0xd6 +}; +static const uint8_t ac_dsa_vect214_priv_val[] = { +/* X */ + 0x97, 0x6f, 0xb0, 0x67, 0x15, 0x7b, 0x21, 0x4a, 0x80, 0x65, 0x8e, 0x7e, + 0xd2, 0xf5, 0x66, 0x91, 0x1b, 0x35, 0xb1, 0x67, 0x1e, 0x5c, 0x0b, 0xdd, + 0x55, 0xff, 0x58, 0x11, 0xe8, 0x22, 0xbf, 0x82 +}; +static const uint8_t ac_dsa_vect214_pub_val[] = { +/* Y */ + 0x38, 0x59, 0xd4, 0x73, 0x5c, 0x14, 0xba, 0xee, 0xc1, 0x4b, 0x79, 0xcc, + 0x26, 0x93, 0xff, 0xca, 0xc9, 0x00, 0xa2, 0xc2, 0x6e, 0xc6, 0x34, 0xa8, + 0xe9, 0x77, 0xd2, 0x06, 0xad, 0x6e, 0xc7, 0xb1, 0x3f, 0x2d, 0x45, 0x0e, + 0xf0, 0x47, 0x82, 0xec, 0x0a, 0xbb, 0x0d, 0xa4, 0x8f, 0x00, 0x06, 0x28, + 0xce, 0xc1, 0xf6, 0xe9, 0xa7, 0x27, 0xbb, 0x59, 0xd7, 0xc0, 0xf0, 0xd7, + 0x43, 0xf5, 0x13, 0xac, 0x09, 0x25, 0xbe, 0xb6, 0x1b, 0xf3, 0xad, 0x75, + 0x82, 0x4f, 0xff, 0xae, 0x1e, 0xb7, 0x83, 0xeb, 0x1b, 0x68, 0xfc, 0x40, + 0xd2, 0x87, 0x70, 0xe2, 0x80, 0xfd, 0xe2, 0x38, 0x44, 0xa1, 0x44, 0xd4, + 0xb1, 0xa9, 0x54, 0x09, 0xb7, 0x55, 0xc7, 0xff, 0x2e, 0x5c, 0x67, 0x81, + 0x1f, 0x3b, 0x1c, 0x2e, 0xb9, 0x6c, 0xb1, 0x59, 0xa6, 0x42, 0xd8, 0x4d, + 0xd7, 0xb5, 0xdc, 0xcc, 0x2c, 0x0a, 0xef, 0x06, 0xd1, 0xcd, 0x54, 0xea, + 0xc9, 0x4a, 0x11, 0x27, 0x3f, 0x94, 0x98, 0xf1, 0xe7, 0xa7, 0xcd, 0x79, + 0xc1, 0x08, 0xe4, 0x96, 0xdc, 0xf5, 0x73, 0xef, 0x3a, 0x66, 0x10, 0xb7, + 0x73, 0x1a, 0xb1, 0x4c, 0x16, 0x2c, 0xe8, 0x37, 0x7c, 0xb9, 0xb9, 0x07, + 0x88, 0xe3, 0x56, 0xf5, 0x1f, 0x4b, 0x51, 0xa1, 0xec, 0x8b, 0xd8, 0x6b, + 0xd8, 0x8f, 0xd4, 0xc3, 0x8e, 0x62, 0xca, 0xd6, 0x19, 0xab, 0x89, 0x41, + 0xbc, 0xb9, 0x8a, 0x2f, 0x35, 0xee, 0x51, 0x2f, 0x4f, 0x8f, 0xfd, 0xd5, + 0xee, 0x70, 0xca, 0xed, 0x84, 0x67, 0x15, 0x6b, 0x89, 0x3b, 0x35, 0x32, + 0xa0, 0xa2, 0xaa, 0x51, 0x99, 0xce, 0xae, 0xcc, 0x5b, 0x19, 0x4b, 0xc0, + 0x57, 0x96, 0x4c, 0xf4, 0x50, 0x66, 0x8c, 0x44, 0xf2, 0x7e, 0xc8, 0x0d, + 0xe2, 0x1e, 0xa1, 0xa4, 0x15, 0xee, 0x6a, 0x65, 0x69, 0x83, 0x23, 0x94, + 0xf6, 0xb4, 0x05, 0xd1 +}; +/* K = 1ef4f08defdb5c59a3df3358e083ce804c969d046ab67f2f938eb1a8f06a5d0a */ +static const uint8_t ac_dsa_vect214_out[] = { +/* R */ + 0x44, 0x36, 0x44, 0xe1, 0x27, 0xe3, 0x81, 0xb1, 0x7b, 0xb6, 0x6c, 0x53, + 0x50, 0x97, 0x18, 0xa5, 0x8a, 0x30, 0xf9, 0x27, 0x42, 0x58, 0x06, 0xa6, + 0x28, 0x40, 0x11, 0x9e, 0x78, 0xc2, 0x93, 0xb7, +/* S */ + 0x3f, 0x01, 0xe5, 0xd1, 0xe9, 0xfd, 0xb1, 0xcf, 0xda, 0x25, 0xef, 0xf3, + 0xca, 0xcc, 0xf4, 0xed, 0xf5, 0x99, 0xfe, 0xa2, 0x77, 0x20, 0x1c, 0xf2, + 0xb0, 0x1f, 0xfd, 0x7c, 0xb1, 0xa9, 0xa7, 0x27 +}; +#define ac_dsa_vect215_prime ac_dsa_vect211_prime +#define ac_dsa_vect215_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect215_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect215_ptx[] = { +/* Msg */ + 0xb8, 0x8c, 0x21, 0x20, 0x70, 0xbe, 0x39, 0x8a, 0x1f, 0x81, 0xe8, 0x5d, + 0xfd, 0x71, 0xdc, 0x24, 0x24, 0xa3, 0x8a, 0xe3, 0x8a, 0x9d, 0x61, 0x08, + 0x51, 0x86, 0x50, 0x4f, 0x4c, 0x2c, 0xbf, 0xa4, 0x92, 0xb7, 0x6d, 0xbc, + 0xc0, 0x51, 0xce, 0xfd, 0xe0, 0x61, 0x6a, 0x7e, 0x33, 0x10, 0xb4, 0xbf, + 0x17, 0x24, 0x4d, 0xe7, 0xd1, 0x0f, 0x84, 0x7c, 0xe2, 0xa9, 0xf6, 0x65, + 0x94, 0x8e, 0x76, 0x72, 0x4d, 0x8f, 0x1f, 0x4b, 0xb3, 0xa6, 0x19, 0x19, + 0xb2, 0xec, 0x7d, 0xc4, 0x7a, 0xd8, 0xa7, 0x2c, 0xb5, 0x99, 0x8b, 0x79, + 0xfe, 0x3a, 0x15, 0x63, 0x95, 0xe4, 0xae, 0x88, 0xe6, 0x82, 0xb1, 0xdd, + 0x16, 0xc5, 0x2d, 0x64, 0xcb, 0x4b, 0x31, 0xc3, 0x9d, 0x4a, 0x42, 0xa2, + 0x1e, 0x62, 0x42, 0xdc, 0x0c, 0xdb, 0xb0, 0xac, 0xf3, 0xd4, 0x71, 0x82, + 0x63, 0x8c, 0x5f, 0x21, 0x6d, 0xc6, 0xe8, 0xb1 +}; +static const uint8_t ac_dsa_vect215_priv_val[] = { +/* X */ + 0x02, 0x16, 0x3c, 0xda, 0x61, 0x2e, 0x84, 0xeb, 0x5e, 0xa9, 0xe4, 0xe0, + 0x68, 0xb1, 0x4c, 0x10, 0xda, 0xd0, 0x73, 0x40, 0x91, 0x54, 0xd8, 0x6f, + 0xea, 0x6a, 0xae, 0xde, 0x59, 0x53, 0x8d, 0x2e +}; +static const uint8_t ac_dsa_vect215_pub_val[] = { +/* Y */ + 0x54, 0x1c, 0x69, 0x0f, 0x4c, 0xa0, 0xc4, 0x2e, 0x52, 0x67, 0x64, 0x6f, + 0x78, 0xef, 0x42, 0xfd, 0x68, 0xc3, 0x63, 0x37, 0x5b, 0x2e, 0x98, 0x3b, + 0xe4, 0x44, 0xe4, 0x81, 0x9e, 0x63, 0xcd, 0xc1, 0x29, 0x01, 0x8b, 0xd3, + 0xb8, 0xc6, 0xda, 0x8b, 0x70, 0x7c, 0x19, 0x6c, 0x35, 0xc9, 0x3e, 0xab, + 0xee, 0x10, 0xe8, 0x75, 0xc4, 0x1f, 0xd9, 0x25, 0xbb, 0x3c, 0xe8, 0x06, + 0x96, 0x93, 0x5d, 0x16, 0x31, 0x3f, 0xd3, 0xa2, 0x68, 0x58, 0xec, 0xcf, + 0x2d, 0x50, 0x7f, 0xc2, 0xa1, 0x09, 0x50, 0x52, 0x5c, 0x67, 0x0d, 0xad, + 0xc8, 0x83, 0xdc, 0x67, 0x79, 0xac, 0x1c, 0xe8, 0x66, 0xd8, 0x82, 0x03, + 0x95, 0xf3, 0x54, 0x1c, 0x86, 0x30, 0x18, 0x33, 0x7a, 0x6b, 0xe9, 0x44, + 0xdd, 0xc6, 0x44, 0xaa, 0xa6, 0xc0, 0x07, 0x19, 0x7d, 0x7a, 0x5f, 0x9a, + 0xa5, 0x3a, 0x5e, 0x11, 0x80, 0xad, 0x51, 0xc9, 0x8b, 0xe9, 0xd5, 0x61, + 0xa8, 0x5f, 0xe9, 0x73, 0x41, 0x60, 0xca, 0x35, 0xe4, 0xfa, 0xdb, 0x02, + 0x52, 0x7b, 0xa0, 0xfa, 0x58, 0x04, 0x1b, 0x4d, 0x96, 0x38, 0x5f, 0x7f, + 0x8f, 0xf6, 0xae, 0x75, 0x6a, 0xdd, 0x49, 0x68, 0xc0, 0xc2, 0x79, 0x9c, + 0x0d, 0x68, 0x0f, 0x66, 0xc8, 0xce, 0x96, 0xf4, 0x98, 0x22, 0x87, 0x38, + 0xe3, 0xe8, 0x7b, 0x7c, 0x86, 0x63, 0x44, 0xdb, 0x7d, 0x5a, 0x4e, 0xc3, + 0x28, 0x24, 0x31, 0xae, 0xe5, 0x95, 0x1d, 0x9b, 0x4c, 0x83, 0xec, 0x2a, + 0x0c, 0xda, 0x36, 0xcb, 0x2e, 0x2c, 0x43, 0x73, 0x63, 0xce, 0xba, 0x4e, + 0x8e, 0x9f, 0x61, 0x28, 0x43, 0x9d, 0x12, 0xc5, 0x18, 0x68, 0xd0, 0xcb, + 0x1f, 0x61, 0xe5, 0x3a, 0x68, 0xd4, 0xe7, 0x1c, 0x5a, 0x9e, 0x7d, 0xe4, + 0x3c, 0x6d, 0xfc, 0xa2, 0x6f, 0x17, 0x41, 0xac, 0xa9, 0x16, 0xe4, 0x28, + 0x26, 0x53, 0xbf, 0xc1 +}; +/* K = 42cc30e9591b42486ce9998ab7594ddabc5328ca2e931e08c75b76bbe1f8b978 */ +static const uint8_t ac_dsa_vect215_out[] = { +/* R */ + 0x07, 0x8a, 0x71, 0x46, 0xa2, 0xc5, 0x09, 0xb9, 0x7a, 0x6a, 0x8c, 0x96, + 0x3b, 0xaf, 0x1f, 0xbf, 0xbd, 0x1a, 0x2a, 0x5a, 0xa2, 0x14, 0xa1, 0x5e, + 0xa4, 0x57, 0x63, 0xf0, 0xe7, 0x93, 0x0b, 0xeb, +/* S */ + 0x29, 0x79, 0xcb, 0xf5, 0x9a, 0xdb, 0x70, 0xf2, 0x8a, 0xc4, 0xfc, 0xb6, + 0x92, 0x97, 0x49, 0x8f, 0x81, 0x63, 0x76, 0x4c, 0x62, 0xb3, 0x19, 0x63, + 0xda, 0x9c, 0x8f, 0x9c, 0x0c, 0x43, 0xe0, 0x75 +}; +#define ac_dsa_vect216_prime ac_dsa_vect211_prime +#define ac_dsa_vect216_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect216_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect216_ptx[] = { +/* Msg */ + 0x4a, 0xdf, 0x1e, 0xd4, 0xfb, 0xb5, 0xb8, 0x2d, 0x7a, 0x2b, 0x1a, 0x29, + 0x38, 0x43, 0x07, 0x53, 0xa6, 0x20, 0x7d, 0xa1, 0xcc, 0x04, 0x95, 0x74, + 0xf0, 0xa1, 0x93, 0x14, 0x27, 0x2f, 0x9a, 0x80, 0xc6, 0xa5, 0x34, 0x98, + 0xb7, 0x8e, 0x5c, 0x0b, 0x74, 0x01, 0xce, 0x48, 0x5f, 0xd4, 0xba, 0xeb, + 0xc9, 0x66, 0xda, 0x6c, 0x1f, 0xcb, 0x02, 0x58, 0x16, 0xcf, 0xae, 0x32, + 0xb5, 0x8a, 0xa8, 0x7f, 0x5e, 0x88, 0x85, 0x05, 0x47, 0x35, 0xf9, 0x3d, + 0xf1, 0x9e, 0xd3, 0x2c, 0x81, 0x97, 0x86, 0xd4, 0x10, 0x9d, 0xbd, 0xa0, + 0x47, 0xd6, 0x8c, 0x05, 0x89, 0x33, 0x07, 0x15, 0xe1, 0x05, 0x22, 0x64, + 0x3b, 0xbe, 0x27, 0xe3, 0x2c, 0x0d, 0xc9, 0xc5, 0x83, 0x36, 0xbe, 0x30, + 0x5b, 0x4c, 0x0c, 0x98, 0x1b, 0x40, 0xe0, 0xee, 0xda, 0x0d, 0xe4, 0x61, + 0xd8, 0x44, 0x1c, 0x02, 0xc1, 0x8c, 0xea, 0xc5 +}; +static const uint8_t ac_dsa_vect216_priv_val[] = { +/* X */ + 0x5b, 0x44, 0xbf, 0xbb, 0x69, 0x27, 0x7f, 0xbe, 0x49, 0x7e, 0xc7, 0x29, + 0x83, 0x88, 0x86, 0xe7, 0xa7, 0x87, 0xf3, 0x36, 0xc2, 0x46, 0x55, 0x15, + 0x26, 0xb6, 0x60, 0xa7, 0x60, 0x3d, 0x16, 0x7e +}; +static const uint8_t ac_dsa_vect216_pub_val[] = { +/* Y */ + 0x8b, 0x69, 0x27, 0xfe, 0x29, 0x3a, 0xc9, 0x11, 0x1b, 0xa4, 0x06, 0x12, + 0x5d, 0x6e, 0xbf, 0xbc, 0x30, 0xf9, 0x6c, 0xbf, 0xd6, 0x96, 0xfc, 0xac, + 0x7d, 0xde, 0xd4, 0x23, 0x05, 0xc6, 0x10, 0x54, 0x53, 0xac, 0xcb, 0x1b, + 0x0c, 0xa6, 0xf0, 0xf3, 0x16, 0x01, 0xf8, 0xc3, 0x4f, 0x96, 0xbb, 0x8e, + 0xe4, 0xcc, 0xf1, 0x49, 0x92, 0x3a, 0x12, 0x82, 0x1d, 0xfa, 0xa2, 0xa3, + 0x85, 0x9a, 0x39, 0xcf, 0x82, 0x56, 0x76, 0x09, 0xb2, 0x06, 0x0f, 0xf6, + 0x09, 0x23, 0x2e, 0x90, 0x26, 0x1d, 0x66, 0xcf, 0x31, 0xfb, 0x92, 0x64, + 0x67, 0x1f, 0x3f, 0x1b, 0xff, 0x6c, 0x8a, 0x95, 0x8e, 0x5c, 0xd0, 0x15, + 0xdc, 0xc0, 0x2d, 0xfd, 0x2f, 0x02, 0xfb, 0x6a, 0x44, 0x3c, 0x2b, 0xf4, + 0x5a, 0xbf, 0x13, 0x86, 0x20, 0x59, 0xdf, 0x98, 0x06, 0x6e, 0x00, 0x31, + 0x1b, 0xb6, 0x43, 0x8b, 0x7f, 0xe2, 0xd9, 0x1e, 0x28, 0x75, 0x53, 0xd2, + 0x54, 0x11, 0xf0, 0xfb, 0xa4, 0x74, 0x17, 0xc2, 0x90, 0x2f, 0x97, 0x8c, + 0x57, 0x25, 0x7a, 0xe4, 0xea, 0xa3, 0xf9, 0x93, 0x17, 0xd5, 0xad, 0xee, + 0x0f, 0x9a, 0xdf, 0x4d, 0x41, 0xe4, 0x10, 0x72, 0x55, 0x2b, 0x3f, 0x51, + 0xeb, 0x99, 0x36, 0xa7, 0xf6, 0x3c, 0xc2, 0x8b, 0x46, 0x6f, 0xab, 0x64, + 0x29, 0xd0, 0x68, 0x68, 0xd1, 0x8c, 0xa0, 0x9a, 0xba, 0x63, 0x40, 0x93, + 0x76, 0x71, 0x92, 0x04, 0x9b, 0x02, 0xbc, 0xb7, 0x52, 0xeb, 0x67, 0x4c, + 0x98, 0xa8, 0x68, 0x69, 0xd6, 0x72, 0x6f, 0x74, 0x2e, 0x57, 0xef, 0x8c, + 0x3d, 0x45, 0x31, 0x17, 0x1c, 0x64, 0xf0, 0x3e, 0x10, 0xa4, 0xe4, 0x40, + 0x39, 0xa4, 0x4d, 0x40, 0x7e, 0xbf, 0xc6, 0xb5, 0x6a, 0x7c, 0xdf, 0x6b, + 0x17, 0x39, 0x4b, 0x53, 0xb5, 0x60, 0x43, 0x47, 0xc5, 0x1c, 0xf3, 0x75, + 0x55, 0x1b, 0x73, 0x06 +}; +/* K = 5f02472e007874056abe7194e80845b81baeaf4f6f564d3640373757f4252f57 */ +static const uint8_t ac_dsa_vect216_out[] = { +/* R */ + 0x5b, 0x20, 0x11, 0x16, 0xd8, 0xbb, 0xc8, 0x7d, 0xb9, 0x90, 0x01, 0x70, + 0x7b, 0x56, 0x7e, 0x7c, 0x34, 0x51, 0xd8, 0x02, 0xfa, 0x6c, 0x67, 0x9b, + 0xf3, 0xdb, 0x34, 0x56, 0x71, 0x1a, 0x19, 0x13, +/* S */ + 0x5b, 0xe7, 0xe4, 0xc4, 0x93, 0xfd, 0x5d, 0x19, 0xb7, 0x71, 0x37, 0x31, + 0x41, 0x29, 0x4d, 0xaa, 0xd9, 0x76, 0x56, 0xa3, 0xdb, 0xe3, 0xfd, 0x2a, + 0xbb, 0xd3, 0xb6, 0xc6, 0x2c, 0x16, 0x61, 0x26 +}; +#define ac_dsa_vect217_prime ac_dsa_vect211_prime +#define ac_dsa_vect217_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect217_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect217_ptx[] = { +/* Msg */ + 0xbd, 0x49, 0x1c, 0xf6, 0x8b, 0x34, 0xf7, 0xba, 0x9a, 0xfe, 0x0c, 0x6e, + 0xf5, 0xf2, 0xb7, 0x95, 0x6e, 0xf9, 0x64, 0x46, 0x5f, 0x28, 0xb2, 0x79, + 0x7b, 0xc1, 0xd6, 0xe6, 0x70, 0xa6, 0xd8, 0x17, 0x30, 0xee, 0x29, 0x93, + 0xd0, 0xb4, 0xaa, 0x96, 0x90, 0x51, 0x57, 0x02, 0x5d, 0x77, 0x5b, 0xa1, + 0x04, 0xe7, 0xc1, 0x9b, 0x3b, 0x37, 0x2e, 0x85, 0x20, 0x26, 0xb1, 0x28, + 0x6c, 0xbc, 0x6a, 0x48, 0xa1, 0x0c, 0xb9, 0x37, 0x8e, 0x97, 0xad, 0x96, + 0x6f, 0x9c, 0xf0, 0x39, 0x17, 0xee, 0x8d, 0xb7, 0x5b, 0x62, 0x64, 0xe9, + 0xb0, 0xa4, 0x8a, 0x0a, 0xe1, 0x0c, 0x2f, 0x46, 0x44, 0x47, 0x10, 0xd4, + 0x23, 0x41, 0x26, 0xce, 0x45, 0x6b, 0x9f, 0xd1, 0x1a, 0xb7, 0xa3, 0x50, + 0x49, 0x48, 0xd0, 0x46, 0xd5, 0xf4, 0x38, 0xd8, 0x93, 0xd9, 0xb1, 0x05, + 0x2b, 0x8f, 0xac, 0x95, 0x47, 0x41, 0x54, 0x72 +}; +static const uint8_t ac_dsa_vect217_priv_val[] = { +/* X */ + 0x60, 0x9a, 0x37, 0x2d, 0x38, 0x44, 0xca, 0x82, 0x24, 0xdf, 0xe7, 0x80, + 0xb4, 0x25, 0xe1, 0xa7, 0xc0, 0x0d, 0x09, 0x95, 0x7a, 0x86, 0x2d, 0xe6, + 0xf6, 0x40, 0xaf, 0x57, 0xc0, 0x86, 0xdd, 0x6d +}; +static const uint8_t ac_dsa_vect217_pub_val[] = { +/* Y */ + 0xa9, 0x2e, 0x44, 0x65, 0x10, 0x76, 0x4e, 0xe1, 0xcf, 0x81, 0xc6, 0xb5, + 0x9b, 0x51, 0x60, 0xa7, 0x60, 0x8f, 0xf8, 0x95, 0x2d, 0x04, 0x5d, 0xd6, + 0x9f, 0x03, 0x4f, 0xdf, 0xef, 0x93, 0xf6, 0x33, 0x60, 0x7e, 0xc2, 0x09, + 0xb1, 0x06, 0xc6, 0xac, 0x8f, 0x0c, 0xc6, 0xff, 0xa6, 0x4b, 0xb9, 0xa4, + 0x48, 0x45, 0x60, 0xb8, 0x38, 0xd6, 0xf2, 0x4c, 0x99, 0x3a, 0x95, 0x4e, + 0xfc, 0x9d, 0x5e, 0xe1, 0x66, 0x56, 0xaa, 0xba, 0x2a, 0x0d, 0x5a, 0x94, + 0xe7, 0xa3, 0x46, 0xc7, 0xe5, 0x01, 0xaf, 0x83, 0xf1, 0x31, 0xdb, 0x9e, + 0x0c, 0xab, 0x87, 0x89, 0xfa, 0xb1, 0x9b, 0xd5, 0x91, 0xec, 0x22, 0x7f, + 0x39, 0xb3, 0x49, 0xbe, 0x7f, 0x8d, 0x0d, 0xf5, 0x8c, 0xa0, 0x39, 0x6e, + 0xfb, 0x1e, 0x76, 0x54, 0x93, 0x35, 0x90, 0x4b, 0x88, 0xec, 0x21, 0xcd, + 0x32, 0x65, 0xc5, 0x43, 0xc4, 0xe8, 0x0e, 0x9d, 0xde, 0x7c, 0xb5, 0xc9, + 0xea, 0x8c, 0xdd, 0xa2, 0x3d, 0x96, 0xef, 0x1c, 0x38, 0x39, 0xad, 0xe8, + 0xed, 0x4a, 0x5c, 0xd5, 0xfd, 0x98, 0xb7, 0x9b, 0xce, 0xee, 0xd9, 0xc6, + 0x41, 0xc5, 0xa7, 0x75, 0x8d, 0x05, 0x29, 0xac, 0xea, 0xf2, 0x7b, 0x50, + 0x14, 0xf1, 0x3d, 0xfc, 0xaa, 0x26, 0x7a, 0x14, 0xa0, 0x84, 0x1b, 0x36, + 0x89, 0x7b, 0x6e, 0x1e, 0x89, 0x17, 0xb7, 0xf7, 0xcb, 0xf7, 0xcf, 0xf1, + 0xd1, 0x95, 0x3a, 0xc4, 0x3c, 0xc0, 0x4a, 0xb0, 0x6c, 0xf1, 0x11, 0xe0, + 0x06, 0x49, 0x7e, 0xb4, 0x2f, 0x28, 0xcb, 0xc9, 0x05, 0xd6, 0xf1, 0xcd, + 0x5d, 0x83, 0x94, 0x85, 0x79, 0x83, 0xe1, 0xc9, 0xe5, 0x52, 0x01, 0x5a, + 0x45, 0x1d, 0x0c, 0x13, 0xa6, 0x84, 0x8a, 0x8f, 0xc5, 0x6b, 0x79, 0xde, + 0xc1, 0x72, 0x3a, 0x80, 0x67, 0xff, 0x18, 0x93, 0x1c, 0x85, 0x2c, 0xeb, + 0x81, 0xaf, 0xfe, 0xc1 +}; +/* K = 8c70ac971b83f159d2e6ec26bca1463aadbc8e9987593f49a9258f7f0de9cb38 */ +static const uint8_t ac_dsa_vect217_out[] = { +/* R */ + 0x0c, 0xf5, 0x26, 0xd8, 0xa0, 0xf9, 0xc9, 0x12, 0xd1, 0x43, 0xf3, 0xf8, + 0xaf, 0xde, 0xd4, 0x59, 0x8b, 0x2a, 0x5a, 0xaf, 0x20, 0x0e, 0x07, 0x49, + 0xea, 0x27, 0xde, 0xfe, 0xb7, 0xf2, 0x8f, 0x3a, +/* S */ + 0x87, 0x7a, 0x90, 0x66, 0xf6, 0xc5, 0xae, 0x78, 0x25, 0x1d, 0x9d, 0x14, + 0x0b, 0xcf, 0x39, 0xae, 0x91, 0x2d, 0x18, 0xbf, 0x13, 0x1b, 0xdc, 0x7e, + 0x9d, 0x61, 0x01, 0x2d, 0xaa, 0xa4, 0x29, 0x2c +}; +#define ac_dsa_vect218_prime ac_dsa_vect211_prime +#define ac_dsa_vect218_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect218_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect218_ptx[] = { +/* Msg */ + 0xc0, 0x0a, 0x8a, 0x2f, 0xff, 0xd1, 0x0b, 0xc2, 0xea, 0xb6, 0x3b, 0x8e, + 0x37, 0x5d, 0x0c, 0x10, 0xf9, 0xdf, 0xae, 0x28, 0x48, 0xba, 0x42, 0xaf, + 0xe6, 0x08, 0x5a, 0xee, 0xc2, 0x6e, 0x21, 0xaf, 0x3e, 0xaa, 0x49, 0x3c, + 0xe4, 0xb3, 0xd9, 0x5a, 0x31, 0xfa, 0x50, 0x2a, 0x60, 0xab, 0x88, 0xe8, + 0x05, 0xf4, 0xfd, 0xf8, 0x89, 0xed, 0x91, 0xc1, 0x54, 0x21, 0x71, 0x80, + 0x84, 0xcd, 0x0d, 0x64, 0x47, 0x95, 0x74, 0x9b, 0x1a, 0x6b, 0x18, 0x3d, + 0x74, 0x78, 0x2d, 0x52, 0xc7, 0xba, 0xbf, 0x74, 0x00, 0x39, 0x3c, 0xee, + 0x69, 0x8a, 0xf5, 0xdc, 0x01, 0x0c, 0x0f, 0xf7, 0xf5, 0xac, 0xdf, 0x02, + 0x08, 0xf9, 0x3e, 0xe7, 0xe4, 0xef, 0x58, 0xda, 0x12, 0x3d, 0xfd, 0xe7, + 0xf0, 0xa3, 0x4e, 0x20, 0x9b, 0xba, 0xec, 0x61, 0x00, 0x72, 0x93, 0xfd, + 0x11, 0xaf, 0xa6, 0x0b, 0x65, 0x22, 0xc4, 0x5d +}; +static const uint8_t ac_dsa_vect218_priv_val[] = { +/* X */ + 0x68, 0x3e, 0x92, 0x48, 0x93, 0xdb, 0xbd, 0x75, 0x1e, 0x0a, 0x3f, 0x91, + 0x08, 0x67, 0x47, 0x1a, 0x64, 0x10, 0xfe, 0xf5, 0x62, 0xcc, 0xa9, 0xf4, + 0x64, 0x94, 0x3a, 0xbd, 0x88, 0xe0, 0x43, 0x0f +}; +static const uint8_t ac_dsa_vect218_pub_val[] = { +/* Y */ + 0x75, 0x60, 0x10, 0x5b, 0x85, 0x86, 0xc4, 0x53, 0x2b, 0xf1, 0xb5, 0x1e, + 0x0d, 0x2c, 0xf9, 0xa7, 0x13, 0xa5, 0xea, 0x5d, 0x40, 0xe2, 0x62, 0xce, + 0x01, 0xeb, 0xda, 0xf1, 0xee, 0x53, 0xd8, 0x57, 0x12, 0x9e, 0x15, 0x29, + 0xa0, 0xf8, 0xdf, 0xf6, 0x3e, 0x86, 0x20, 0x2c, 0x11, 0x1c, 0x6e, 0xb2, + 0x89, 0x43, 0x9c, 0xb1, 0x5c, 0xd5, 0x9f, 0xc2, 0x18, 0xab, 0xe6, 0x19, + 0xc9, 0x51, 0x62, 0x50, 0xf1, 0x27, 0xfa, 0xfe, 0x9a, 0x53, 0x07, 0x62, + 0x74, 0xf3, 0x06, 0xf0, 0xb7, 0x87, 0x1c, 0xff, 0xbd, 0x15, 0x6b, 0x1a, + 0x88, 0x19, 0x79, 0x5f, 0x0a, 0x99, 0x55, 0x86, 0x47, 0x56, 0x65, 0x02, + 0x74, 0xb8, 0x3e, 0x67, 0xca, 0xa4, 0xe2, 0x15, 0xf8, 0x33, 0xaf, 0xd5, + 0xa7, 0x7d, 0x05, 0x94, 0xb2, 0x1b, 0x4b, 0x54, 0x35, 0x6a, 0x98, 0xa5, + 0x6a, 0x0b, 0xf6, 0x17, 0x7f, 0xaf, 0xfb, 0x9f, 0xdf, 0xd8, 0x88, 0xd6, + 0x53, 0x8a, 0x1c, 0xe7, 0x60, 0x59, 0x85, 0x4b, 0xd1, 0xf0, 0xa2, 0x07, + 0x61, 0x28, 0x1d, 0x7b, 0x75, 0x17, 0x57, 0xc6, 0xec, 0xc9, 0xb1, 0xe8, + 0x13, 0x11, 0x96, 0xd0, 0x66, 0x95, 0x97, 0x21, 0x3a, 0xe7, 0x3e, 0xdb, + 0x99, 0x65, 0xda, 0x9f, 0xf3, 0x72, 0x42, 0x08, 0x51, 0x15, 0x50, 0x11, + 0xf6, 0x91, 0xa0, 0x3a, 0x7f, 0x1e, 0x20, 0x40, 0x29, 0x15, 0x75, 0xb8, + 0x6f, 0x59, 0x59, 0x98, 0xa0, 0x6e, 0xf7, 0x9f, 0x4e, 0xad, 0xba, 0xe2, + 0xbd, 0x9e, 0x2e, 0x47, 0x7d, 0xd7, 0x26, 0x84, 0xd8, 0xef, 0xdc, 0x1e, + 0x83, 0x5f, 0x7f, 0x0f, 0x5c, 0x93, 0x63, 0x5c, 0x18, 0x1b, 0x96, 0xcc, + 0x7c, 0x0e, 0xaa, 0x27, 0xee, 0x62, 0xc9, 0x22, 0x7e, 0xd9, 0x48, 0x5a, + 0x8c, 0x82, 0x2b, 0x32, 0x24, 0xe9, 0xe2, 0xb7, 0xac, 0xc1, 0x09, 0x56, + 0xf3, 0xd4, 0x9a, 0x6f +}; +/* K = 3bf5f524e3a3903c149958d10ae68f0a87a03821445a98b0b9d08a3689738853 */ +static const uint8_t ac_dsa_vect218_out[] = { +/* R */ + 0x98, 0xfe, 0xe1, 0x0c, 0x85, 0xab, 0x46, 0xd3, 0x34, 0x75, 0x87, 0x34, + 0x81, 0x9e, 0x68, 0xb5, 0x04, 0x64, 0x39, 0xcd, 0x0b, 0x66, 0xbe, 0x26, + 0xd4, 0x37, 0x60, 0x61, 0x3a, 0xc7, 0x7b, 0x8c, +/* S */ + 0x66, 0x5f, 0xab, 0x98, 0xdd, 0x43, 0x7e, 0x06, 0xa4, 0xf8, 0x77, 0xee, + 0x21, 0x89, 0x86, 0xe3, 0x7c, 0x2c, 0xb2, 0xd2, 0x37, 0xe5, 0x98, 0xd9, + 0x8f, 0x1b, 0x7d, 0x4e, 0x82, 0x9a, 0x84, 0x6b +}; +#define ac_dsa_vect219_prime ac_dsa_vect211_prime +#define ac_dsa_vect219_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect219_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect219_ptx[] = { +/* Msg */ + 0x27, 0xf0, 0x1b, 0x47, 0xd1, 0x5f, 0x7d, 0x19, 0x6f, 0x26, 0x67, 0xb7, + 0x5e, 0xd1, 0x5b, 0x89, 0xd7, 0x44, 0x3f, 0xb4, 0xfa, 0xb0, 0x68, 0xf4, + 0xad, 0xb6, 0x71, 0x75, 0xca, 0x70, 0x07, 0x1d, 0x52, 0xe2, 0x70, 0xf6, + 0x89, 0x64, 0xf9, 0xfb, 0x0e, 0x0e, 0x14, 0xed, 0x5d, 0x29, 0x54, 0xa3, + 0x3d, 0x93, 0x80, 0x7a, 0xcf, 0x3c, 0x82, 0x50, 0x0e, 0x8b, 0x9f, 0x5f, + 0xc5, 0x51, 0x0c, 0xc3, 0xbd, 0x6a, 0xaa, 0x1d, 0xaa, 0xc8, 0x30, 0x91, + 0x28, 0xef, 0x4c, 0x0b, 0x4c, 0xac, 0x02, 0x64, 0x25, 0xae, 0xfd, 0xd7, + 0xe6, 0x9c, 0x22, 0xc3, 0x2e, 0x5f, 0x8d, 0x2a, 0x6e, 0x8f, 0x2e, 0xa2, + 0x91, 0xac, 0x33, 0xda, 0x6c, 0x71, 0xa1, 0x95, 0x3e, 0x44, 0x3c, 0x0e, + 0xa2, 0x06, 0x56, 0x8a, 0xad, 0xef, 0x2b, 0x96, 0x46, 0x6c, 0xbf, 0x76, + 0xbf, 0x14, 0x9d, 0x89, 0xd8, 0x6f, 0x52, 0x9f +}; +static const uint8_t ac_dsa_vect219_priv_val[] = { +/* X */ + 0x28, 0x5d, 0xcb, 0xa1, 0x40, 0x16, 0x2f, 0xc2, 0x03, 0x65, 0x1c, 0x5f, + 0xf7, 0xf1, 0x15, 0x53, 0x41, 0x43, 0x6c, 0x5c, 0x5c, 0x98, 0xe1, 0xe9, + 0xdf, 0x19, 0x2b, 0x3c, 0x94, 0x8a, 0x16, 0xca +}; +static const uint8_t ac_dsa_vect219_pub_val[] = { +/* Y */ + 0x38, 0xfa, 0x99, 0x4a, 0x1f, 0x61, 0xab, 0x79, 0xee, 0x7a, 0x7e, 0x6f, + 0x68, 0x9c, 0x38, 0xf6, 0xc2, 0x82, 0x6f, 0x06, 0x64, 0x7b, 0x16, 0x63, + 0xcd, 0x81, 0x2a, 0xdb, 0x36, 0xd7, 0xfd, 0x7c, 0xcc, 0x50, 0xe9, 0xa9, + 0x0d, 0x02, 0xbf, 0x7c, 0x3f, 0x12, 0xa2, 0x28, 0xc6, 0x92, 0xc0, 0x56, + 0xfb, 0x3b, 0xd6, 0x08, 0xf5, 0x1a, 0xa4, 0x01, 0x02, 0x2c, 0x83, 0x97, + 0x91, 0xe6, 0xa6, 0x78, 0x18, 0x5c, 0xd3, 0x1d, 0x88, 0xcc, 0x66, 0x1a, + 0xf2, 0x9e, 0x5d, 0x23, 0x81, 0x42, 0x18, 0x1d, 0xd3, 0xf6, 0xe7, 0xc8, + 0xb0, 0x57, 0x85, 0x22, 0x1e, 0x62, 0xfd, 0xb3, 0x6c, 0x71, 0xe0, 0x7f, + 0x51, 0xd7, 0x32, 0xe7, 0xe0, 0xca, 0xb5, 0x20, 0xa7, 0xf2, 0xfc, 0x5b, + 0x18, 0x31, 0xb0, 0xa6, 0xba, 0x28, 0x0e, 0x00, 0x32, 0x1c, 0xb9, 0xa0, + 0x25, 0xdb, 0x65, 0x38, 0xab, 0xd6, 0x72, 0x46, 0x3d, 0xbf, 0xf5, 0xca, + 0x81, 0x99, 0x36, 0x76, 0xbc, 0xba, 0xf0, 0xf6, 0xe9, 0xc7, 0x54, 0xf2, + 0x4d, 0x65, 0x4e, 0xe7, 0x87, 0x9b, 0xc0, 0x3d, 0x7d, 0x4b, 0xc8, 0xe8, + 0xca, 0x58, 0xfb, 0x9b, 0x39, 0x29, 0xa3, 0xc3, 0x83, 0x65, 0xcd, 0x2e, + 0x20, 0x57, 0x29, 0xe9, 0xde, 0xf0, 0xa0, 0x01, 0x08, 0xdf, 0xfe, 0x94, + 0x07, 0x27, 0x1e, 0x17, 0xd3, 0x55, 0xec, 0x4b, 0x29, 0x00, 0x3e, 0x0c, + 0xaf, 0x0c, 0x5b, 0x2a, 0xcb, 0x9b, 0xd8, 0xe5, 0x2d, 0x44, 0x10, 0xba, + 0xa9, 0xb9, 0x7a, 0x49, 0x87, 0x4c, 0x14, 0xbe, 0xeb, 0xf0, 0x3a, 0xbf, + 0x28, 0xa9, 0xec, 0x59, 0xbc, 0x17, 0x38, 0xb8, 0xdd, 0x42, 0x23, 0xd4, + 0x7a, 0xa3, 0x36, 0xac, 0xbc, 0xa7, 0x66, 0x2f, 0xc6, 0x9a, 0x6f, 0xef, + 0xee, 0xcf, 0xfd, 0x47, 0xf6, 0x73, 0x7e, 0xcd, 0xa3, 0x31, 0xd1, 0xba, + 0x5c, 0xdf, 0x02, 0x3d +}; +/* K = 4029e06b437cbcf8e0788a393ba3aad0d182564ab6a53565eec1755c4f4b6e2f */ +static const uint8_t ac_dsa_vect219_out[] = { +/* R */ + 0x8d, 0xad, 0x02, 0xc0, 0x2a, 0xd3, 0x4f, 0xe4, 0xe7, 0x58, 0xff, 0x5c, + 0x81, 0xd5, 0x38, 0x4c, 0x40, 0xd2, 0xc4, 0x9d, 0x0a, 0xc7, 0x77, 0xba, + 0xd1, 0xcd, 0xeb, 0xc5, 0x8e, 0xc0, 0x1c, 0xfd, +/* S */ + 0x0f, 0xe4, 0xe1, 0xf6, 0x87, 0x5c, 0x11, 0x3f, 0x1c, 0x17, 0xa0, 0xf0, + 0xed, 0x22, 0x8d, 0x44, 0x21, 0x3f, 0x8d, 0x7e, 0x2f, 0x15, 0x56, 0x7e, + 0x57, 0xce, 0xb2, 0xe8, 0xb1, 0x09, 0x8f, 0x7d +}; +#define ac_dsa_vect220_prime ac_dsa_vect211_prime +#define ac_dsa_vect220_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect220_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect220_ptx[] = { +/* Msg */ + 0x73, 0xcc, 0x5e, 0x4a, 0x18, 0x8d, 0x28, 0x14, 0x46, 0x69, 0x41, 0x38, + 0x90, 0x14, 0xea, 0x45, 0xa1, 0xa0, 0x65, 0x25, 0xd2, 0x06, 0x9c, 0xf4, + 0x88, 0x3e, 0xbc, 0xb5, 0xf2, 0x2a, 0xb1, 0x28, 0xc0, 0x0f, 0x04, 0x1c, + 0xf6, 0x9f, 0xd9, 0x4b, 0x33, 0xfd, 0xad, 0xe7, 0x85, 0x48, 0xf6, 0x52, + 0x3c, 0x83, 0x8b, 0x87, 0xcc, 0xd8, 0x68, 0xf3, 0xd3, 0xd0, 0xa9, 0xa0, + 0x00, 0xf2, 0x78, 0xba, 0x54, 0x04, 0x8b, 0x9c, 0xad, 0xac, 0x7a, 0x99, + 0xd9, 0x8d, 0xef, 0x51, 0x71, 0x31, 0x91, 0xad, 0x83, 0xe5, 0x23, 0x2e, + 0x3e, 0x86, 0x49, 0x72, 0x45, 0xc8, 0x0b, 0xc7, 0x10, 0xfd, 0xd7, 0xfa, + 0xaa, 0xd8, 0x8c, 0xe9, 0x2c, 0x89, 0x4f, 0x8c, 0xad, 0x3d, 0xe0, 0x07, + 0x5c, 0xab, 0xa3, 0x37, 0xa2, 0x22, 0xcb, 0x7a, 0x3d, 0x7c, 0x2d, 0x93, + 0x7b, 0xcf, 0xe4, 0xb6, 0xe6, 0x9d, 0x38, 0x8d +}; +static const uint8_t ac_dsa_vect220_priv_val[] = { +/* X */ + 0x74, 0x22, 0x42, 0xf1, 0xcd, 0xe8, 0x95, 0x59, 0xda, 0xda, 0xe5, 0xe2, + 0xce, 0xa2, 0x8c, 0xf4, 0x02, 0xc6, 0x0e, 0xa9, 0xaf, 0x2a, 0x52, 0x82, + 0x20, 0x22, 0x81, 0xf5, 0x5a, 0x0d, 0x4d, 0x04 +}; +static const uint8_t ac_dsa_vect220_pub_val[] = { +/* Y */ + 0x52, 0x66, 0x42, 0x7a, 0xd4, 0xc1, 0xcf, 0x3e, 0xa2, 0x29, 0x37, 0x7a, + 0xd3, 0x97, 0xc7, 0xd5, 0x61, 0x35, 0x12, 0xfc, 0x27, 0xf2, 0xce, 0x37, + 0x40, 0x7d, 0x2c, 0xea, 0x8e, 0x19, 0x99, 0xae, 0xbb, 0x8f, 0x37, 0x67, + 0xee, 0x96, 0xcb, 0x92, 0x7e, 0xbd, 0xd4, 0x3b, 0x8d, 0xbc, 0x10, 0xba, + 0x2c, 0x47, 0x84, 0x3d, 0x3f, 0x43, 0x36, 0x8d, 0x9e, 0x44, 0x2b, 0xf5, + 0x1e, 0xbc, 0xf2, 0x0b, 0x48, 0xb5, 0x43, 0xa4, 0xc3, 0x88, 0xbb, 0x3a, + 0xe3, 0xe4, 0x02, 0x7a, 0xcb, 0x65, 0x7d, 0x1b, 0xf7, 0x4a, 0xbe, 0xb8, + 0xb9, 0x98, 0x42, 0x13, 0x08, 0x77, 0x0f, 0x70, 0xb3, 0xf7, 0xb1, 0xd9, + 0x10, 0x21, 0x9a, 0x12, 0x10, 0x26, 0x03, 0x40, 0x12, 0x3b, 0x95, 0xdb, + 0xa1, 0x87, 0xe0, 0x0c, 0xb0, 0x67, 0xf7, 0xe3, 0x77, 0x92, 0x34, 0x12, + 0x02, 0x55, 0x4b, 0xfc, 0x8a, 0x23, 0x5f, 0xc0, 0x1e, 0xcb, 0x09, 0x9e, + 0xc3, 0x61, 0x5a, 0x67, 0xa3, 0x61, 0x0d, 0x4d, 0x8c, 0x2d, 0xad, 0x16, + 0x08, 0x70, 0x24, 0xf5, 0x97, 0x3e, 0xb1, 0x84, 0x00, 0xc2, 0x9c, 0x05, + 0xd6, 0x98, 0x4d, 0x1c, 0x15, 0xc1, 0x59, 0x42, 0x28, 0x27, 0xc0, 0xdb, + 0xb2, 0xbf, 0x45, 0x09, 0xd7, 0x10, 0xc4, 0x97, 0x2e, 0xe9, 0x3b, 0xe7, + 0x28, 0x3a, 0xad, 0xd9, 0x91, 0xae, 0x8e, 0xf0, 0xe9, 0x73, 0x12, 0x11, + 0x8f, 0x19, 0x5d, 0x30, 0x4f, 0xbe, 0x96, 0xd5, 0xae, 0xbf, 0xb2, 0x12, + 0x03, 0xea, 0xe6, 0x11, 0x78, 0x31, 0xf9, 0xbe, 0x90, 0x99, 0xd3, 0xd4, + 0x76, 0xb8, 0x3f, 0x65, 0xab, 0x22, 0x5f, 0x8b, 0xe4, 0x93, 0xa8, 0xad, + 0x21, 0x62, 0x0f, 0x25, 0x9d, 0x8a, 0x44, 0x20, 0x08, 0x10, 0xc8, 0xe5, + 0x62, 0xae, 0xa8, 0xe7, 0xa6, 0xbc, 0x23, 0x8c, 0x12, 0x9b, 0x19, 0xf2, + 0x53, 0x1a, 0x6a, 0xf0 +}; +/* K = 57d9723e0d17ed96a3a77ad47be6eafc06a5aa01b59b89be70a756d37dd0df2b */ +static const uint8_t ac_dsa_vect220_out[] = { +/* R */ + 0x77, 0x23, 0x6b, 0x33, 0xb0, 0x42, 0x85, 0x42, 0x57, 0x75, 0xee, 0x3f, + 0x65, 0x8b, 0x37, 0x61, 0x29, 0x5c, 0xbf, 0xf8, 0xe4, 0xbc, 0x05, 0xab, + 0xdd, 0x22, 0xe3, 0xd7, 0x8b, 0x1b, 0x6d, 0xa2, +/* S */ + 0x43, 0xfd, 0xbd, 0x93, 0x6a, 0xb4, 0x04, 0x59, 0xf6, 0x84, 0x30, 0x56, + 0xca, 0x77, 0xe1, 0x25, 0xb6, 0xec, 0x5a, 0xd9, 0x45, 0x04, 0x1c, 0x1f, + 0x6a, 0x27, 0x70, 0xbe, 0x9d, 0xfc, 0xc6, 0x82 +}; +#define ac_dsa_vect221_prime ac_dsa_vect211_prime +#define ac_dsa_vect221_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect221_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect221_ptx[] = { +/* Msg */ + 0xc0, 0x74, 0x6b, 0xef, 0xd2, 0xaf, 0xc6, 0xca, 0x15, 0xcd, 0xb1, 0x45, + 0xc1, 0x84, 0x62, 0xc5, 0x15, 0xbd, 0x42, 0x79, 0x4c, 0x4c, 0x7e, 0xe5, + 0x13, 0xcd, 0x9a, 0xeb, 0x0f, 0xc6, 0xfc, 0x30, 0x48, 0xb6, 0xc7, 0x23, + 0x16, 0x34, 0x98, 0x4a, 0x1b, 0xe8, 0x24, 0xc7, 0x75, 0xf9, 0xc9, 0xb0, + 0x28, 0x25, 0x5f, 0x5b, 0x3c, 0x3d, 0x8f, 0xa0, 0x8d, 0x47, 0xab, 0xa0, + 0x77, 0x55, 0xb5, 0xf1, 0xb5, 0xb0, 0x08, 0x93, 0x3e, 0xff, 0x35, 0x83, + 0x8f, 0x15, 0xa0, 0x2b, 0xa9, 0x36, 0x6c, 0x10, 0x36, 0xd3, 0xff, 0x19, + 0xe8, 0x81, 0x99, 0xef, 0x86, 0xa8, 0x82, 0x27, 0x27, 0x2c, 0xf4, 0xe4, + 0xe0, 0x0f, 0xfa, 0xd9, 0xc3, 0x6b, 0xeb, 0xac, 0x30, 0x57, 0x8b, 0x00, + 0x21, 0x4f, 0xb2, 0x9b, 0xae, 0x43, 0xcf, 0x55, 0x5e, 0xd4, 0x31, 0xa2, + 0xf2, 0x49, 0x22, 0x43, 0x0b, 0x14, 0x96, 0xfb +}; +static const uint8_t ac_dsa_vect221_priv_val[] = { +/* X */ + 0x47, 0xc0, 0xc6, 0xf4, 0xe6, 0xb5, 0x6c, 0xdf, 0x1e, 0x1d, 0x9b, 0x63, + 0xff, 0x37, 0x39, 0xed, 0xec, 0x9c, 0x3d, 0x5a, 0x7c, 0x99, 0x04, 0x92, + 0xa1, 0xc7, 0x2a, 0xa1, 0x49, 0x4f, 0xcf, 0x9c +}; +static const uint8_t ac_dsa_vect221_pub_val[] = { +/* Y */ + 0x43, 0x1e, 0xee, 0x49, 0x09, 0x0a, 0xd5, 0x8f, 0x4a, 0x87, 0x4c, 0x2e, + 0xb5, 0x89, 0x79, 0x69, 0xfa, 0xfe, 0x32, 0x74, 0xbd, 0x74, 0x86, 0xb6, + 0x5e, 0x35, 0x19, 0xe4, 0x30, 0x9d, 0x63, 0x6a, 0xce, 0x68, 0x64, 0xd5, + 0xca, 0x4d, 0x84, 0x48, 0xa3, 0x57, 0xca, 0xfa, 0xc1, 0x5a, 0xc3, 0xcb, + 0x3b, 0xd7, 0xb2, 0x75, 0x5b, 0x3c, 0xb6, 0xdb, 0x0a, 0xf1, 0xa4, 0xe9, + 0x1b, 0x2d, 0x1f, 0xcb, 0x28, 0x56, 0x1b, 0x17, 0x0f, 0xaf, 0x2e, 0x06, + 0x90, 0x07, 0x1b, 0xc0, 0xf6, 0xe4, 0x2b, 0x2d, 0x82, 0xab, 0xe5, 0x64, + 0x6d, 0xdb, 0x8f, 0x9b, 0x99, 0xee, 0x1d, 0xaf, 0x59, 0x06, 0x03, 0x6f, + 0x39, 0x5d, 0x82, 0x4d, 0x08, 0x0b, 0xfa, 0xea, 0x10, 0x30, 0x48, 0xb3, + 0xf4, 0x4d, 0x06, 0x36, 0xbc, 0x7a, 0x6a, 0x88, 0xe9, 0xb0, 0x04, 0xa3, + 0x63, 0xb9, 0x9d, 0x24, 0xa8, 0x9b, 0x6e, 0x97, 0x37, 0x9b, 0x20, 0xba, + 0xcf, 0x48, 0xc7, 0xae, 0x2e, 0x9b, 0xf7, 0xe2, 0x81, 0xfe, 0x3b, 0x4d, + 0x7e, 0xb9, 0x47, 0xa1, 0x02, 0x39, 0x6d, 0x52, 0x3a, 0x1e, 0x85, 0xce, + 0x17, 0xfd, 0x25, 0xf2, 0x71, 0xf3, 0xc2, 0x21, 0xa5, 0x68, 0x1e, 0x9f, + 0xb7, 0x7d, 0x64, 0xd6, 0x24, 0x10, 0x39, 0xac, 0x8a, 0x85, 0xda, 0x32, + 0x74, 0x1b, 0xac, 0xf0, 0x06, 0x60, 0xe4, 0x21, 0xfe, 0x85, 0x0a, 0x0f, + 0xe7, 0x3a, 0x08, 0xee, 0x3a, 0x9b, 0x06, 0x9c, 0x6d, 0x91, 0x14, 0xc1, + 0x97, 0x52, 0x72, 0x12, 0x74, 0x68, 0xf9, 0x00, 0x85, 0x52, 0xea, 0x4c, + 0xdf, 0x9d, 0x96, 0x56, 0x1e, 0xa6, 0x9a, 0x64, 0x66, 0x95, 0x24, 0x25, + 0x00, 0xf2, 0x31, 0x8b, 0xda, 0x82, 0xda, 0x63, 0x3e, 0xf1, 0xae, 0x04, + 0x97, 0x01, 0x4a, 0x63, 0x7b, 0x15, 0xa5, 0x72, 0xdd, 0xdd, 0xec, 0x07, + 0x0d, 0x19, 0xd8, 0x84 +}; +/* K = 3598a6006fa3f8b8f9b7ff96ba06bf3837a1a1a92892e4a268c75285bfa6d660 */ +static const uint8_t ac_dsa_vect221_out[] = { +/* R */ + 0x79, 0x6d, 0x7d, 0xba, 0x32, 0x2d, 0x92, 0xa0, 0x83, 0xda, 0x7a, 0x58, + 0x8f, 0xb6, 0x23, 0x8d, 0xc8, 0x6b, 0x1f, 0xc5, 0x10, 0x4e, 0xd6, 0x00, + 0xc9, 0xb4, 0xc6, 0x88, 0xed, 0xf8, 0x05, 0xe9, +/* S */ + 0x01, 0x2c, 0x1f, 0xf4, 0xde, 0x8e, 0xe3, 0x86, 0xb9, 0x51, 0x27, 0x5e, + 0x25, 0x05, 0x81, 0xd6, 0x61, 0xd0, 0x30, 0xa4, 0xd8, 0xfe, 0x11, 0x54, + 0x32, 0x28, 0x8a, 0xb0, 0xa4, 0xbd, 0x46, 0xcb +}; +#define ac_dsa_vect222_prime ac_dsa_vect211_prime +#define ac_dsa_vect222_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect222_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect222_ptx[] = { +/* Msg */ + 0xb8, 0xb9, 0x15, 0xcf, 0x4e, 0xa3, 0xb0, 0xc4, 0xcd, 0xcd, 0x8b, 0x2a, + 0x06, 0x47, 0x9e, 0x71, 0xbb, 0x47, 0x97, 0x29, 0x4b, 0x6c, 0x41, 0xca, + 0x87, 0x0d, 0x3c, 0xb2, 0xec, 0x2c, 0xb5, 0xa4, 0x9f, 0x6b, 0xfe, 0x5b, + 0xcd, 0x10, 0xbe, 0x60, 0x9e, 0xd3, 0xe1, 0x88, 0x2a, 0x31, 0x23, 0x95, + 0xfc, 0x99, 0x13, 0x45, 0xab, 0xa5, 0xb5, 0x66, 0xe6, 0x79, 0x60, 0xb4, + 0x29, 0x13, 0xdb, 0x66, 0x90, 0x41, 0xea, 0x30, 0xc2, 0x99, 0x47, 0xed, + 0xde, 0x7b, 0xdc, 0xfc, 0x08, 0x96, 0xb9, 0x76, 0x60, 0x74, 0x0d, 0x6c, + 0x79, 0xf0, 0x08, 0x86, 0x65, 0xf5, 0x1d, 0xad, 0xcf, 0xa0, 0x7f, 0x7b, + 0xe4, 0x48, 0x21, 0xd6, 0x0a, 0x8f, 0xfd, 0xe4, 0xe5, 0xcb, 0x1f, 0x98, + 0x13, 0x9f, 0xf9, 0x1c, 0x9c, 0x6f, 0x31, 0x26, 0x59, 0x63, 0x44, 0xc5, + 0xf7, 0xef, 0xf4, 0x00, 0x49, 0xd3, 0xf9, 0xae +}; +static const uint8_t ac_dsa_vect222_priv_val[] = { +/* X */ + 0x0e, 0xb7, 0x4b, 0x51, 0x86, 0x69, 0x7a, 0xf2, 0x79, 0xce, 0x72, 0xda, + 0x74, 0xf1, 0xeb, 0xf5, 0x99, 0x21, 0xed, 0x42, 0x5d, 0xa0, 0xf3, 0xee, + 0xa1, 0x75, 0x17, 0xea, 0xdd, 0xdb, 0x7c, 0x90 +}; +static const uint8_t ac_dsa_vect222_pub_val[] = { +/* Y */ + 0x1b, 0x37, 0x22, 0x76, 0x42, 0x64, 0xe1, 0x79, 0x94, 0xf3, 0x34, 0x3b, + 0xf2, 0x60, 0xc7, 0x35, 0x75, 0xd1, 0x06, 0xf6, 0x30, 0x7f, 0x2e, 0xaa, + 0x3f, 0x7d, 0xcd, 0x5a, 0xf8, 0x04, 0x46, 0x3d, 0xdb, 0x6b, 0xbe, 0x38, + 0xa3, 0x8f, 0x5a, 0xb5, 0xa8, 0xae, 0x67, 0x01, 0x31, 0x7c, 0xf6, 0xc2, + 0x67, 0x04, 0x9f, 0xc9, 0xb8, 0x40, 0x78, 0x24, 0x1f, 0x82, 0xd3, 0xc6, + 0xb7, 0xe5, 0xbe, 0xba, 0x5c, 0x14, 0x27, 0x03, 0x02, 0x97, 0xf1, 0xdf, + 0x25, 0x81, 0x48, 0xe5, 0xf9, 0xeb, 0x41, 0xeb, 0x20, 0xa8, 0x68, 0x77, + 0xfc, 0xc0, 0x6e, 0x53, 0x73, 0xcd, 0x50, 0x56, 0x26, 0x13, 0xd3, 0x07, + 0x64, 0x95, 0x39, 0xd2, 0x8c, 0xb5, 0x24, 0x18, 0xd4, 0x2f, 0xd5, 0x97, + 0x58, 0xb6, 0x11, 0x85, 0xe7, 0x92, 0x99, 0x2b, 0x5a, 0x58, 0x12, 0x29, + 0xb4, 0x34, 0x03, 0xd7, 0x93, 0xb0, 0x4d, 0x87, 0x8e, 0xb9, 0xb9, 0xd1, + 0x2e, 0xa1, 0x0d, 0x2e, 0x64, 0xd1, 0x53, 0xd3, 0xfa, 0x41, 0x88, 0x1f, + 0xe7, 0x9a, 0x67, 0xac, 0x40, 0x8a, 0x53, 0x48, 0xd7, 0x92, 0x39, 0x56, + 0x7d, 0xca, 0x96, 0xe1, 0xea, 0xd3, 0xc6, 0xac, 0x22, 0xdb, 0xcd, 0xbc, + 0xb5, 0x18, 0x5b, 0xf8, 0xac, 0xe5, 0x76, 0x60, 0xa4, 0x25, 0x21, 0x04, + 0xe5, 0x04, 0x7c, 0xac, 0x87, 0x85, 0x1d, 0x28, 0x15, 0xb1, 0x2a, 0xe8, + 0xae, 0x96, 0xab, 0x2f, 0x33, 0x34, 0x5e, 0xa1, 0xcf, 0x5f, 0x2e, 0x58, + 0xa4, 0xdd, 0xcb, 0xa2, 0x62, 0x65, 0xc0, 0x6d, 0xf6, 0x5a, 0xfc, 0xc6, + 0xe8, 0x52, 0xb3, 0xf9, 0x10, 0xc8, 0x77, 0x8d, 0xe2, 0x8a, 0x9f, 0x09, + 0x81, 0x58, 0xed, 0x0e, 0xca, 0x65, 0x2d, 0xda, 0x2f, 0x9f, 0x4a, 0xc8, + 0xa1, 0x7a, 0x9b, 0x25, 0x24, 0x10, 0xec, 0x59, 0x73, 0xa6, 0x06, 0x3b, + 0x64, 0x25, 0x68, 0xf1 +}; +/* K = 37128d19b2108a8e8fdf2cac984d45851078a194bb9946a4db260f27b4650439 */ +static const uint8_t ac_dsa_vect222_out[] = { +/* R */ + 0x6b, 0x4b, 0x0e, 0x1e, 0x7c, 0xbd, 0xef, 0xed, 0xb1, 0xdf, 0x1f, 0x52, + 0x9e, 0xce, 0x47, 0x89, 0x1f, 0x7b, 0x9e, 0x95, 0x9a, 0x3f, 0x85, 0x56, + 0xba, 0x4b, 0xef, 0x7b, 0xb9, 0x85, 0x65, 0x60, +/* S */ + 0x7e, 0x93, 0x3b, 0x44, 0xed, 0xe6, 0xb2, 0xe9, 0x41, 0xb6, 0x0c, 0x37, + 0xdc, 0xd1, 0x56, 0x82, 0x84, 0xde, 0xf2, 0x29, 0xc0, 0xa2, 0xbb, 0x90, + 0x93, 0xf4, 0x82, 0x90, 0x00, 0xc4, 0x40, 0x9a +}; +#define ac_dsa_vect223_prime ac_dsa_vect211_prime +#define ac_dsa_vect223_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect223_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect223_ptx[] = { +/* Msg */ + 0xdf, 0xfd, 0x45, 0x8a, 0x80, 0x8f, 0x18, 0x89, 0xd7, 0xf3, 0xd6, 0x19, + 0x7f, 0x0e, 0x41, 0x92, 0x0a, 0xd7, 0x31, 0x12, 0x4c, 0xee, 0x30, 0x8c, + 0xb9, 0x0d, 0x23, 0x61, 0xb2, 0x3f, 0xee, 0x96, 0x9c, 0x0e, 0x10, 0x58, + 0x35, 0x54, 0x9e, 0x5d, 0x0a, 0x3f, 0x76, 0x90, 0xd5, 0x86, 0x2d, 0x4c, + 0xd6, 0xcc, 0xb3, 0x3a, 0xd1, 0x80, 0x94, 0xc8, 0x5c, 0x96, 0x50, 0xd7, + 0x5b, 0x24, 0x84, 0x96, 0x39, 0x0a, 0x0b, 0x89, 0xe7, 0xdc, 0x7d, 0xc0, + 0xd3, 0xa6, 0x13, 0x0d, 0xd9, 0x77, 0x89, 0xeb, 0xf1, 0x05, 0xf8, 0xe5, + 0x5d, 0x8f, 0x0a, 0x11, 0x62, 0xfb, 0x3c, 0x6b, 0x52, 0x9e, 0x2a, 0x80, + 0xdd, 0x51, 0xe9, 0x04, 0x5e, 0xf8, 0xec, 0x42, 0xca, 0x4b, 0xc4, 0x6a, + 0xbb, 0x65, 0x39, 0x58, 0x8b, 0x53, 0x1c, 0x97, 0x99, 0x56, 0x0c, 0xf4, + 0xea, 0x80, 0x6c, 0x3d, 0x93, 0xd0, 0x43, 0xe5 +}; +static const uint8_t ac_dsa_vect223_priv_val[] = { +/* X */ + 0x36, 0xff, 0x71, 0xed, 0x60, 0x8f, 0x35, 0x1c, 0x73, 0x60, 0x42, 0xf3, + 0xb6, 0x38, 0xa8, 0x96, 0x66, 0x00, 0x7c, 0xef, 0xe8, 0xab, 0x48, 0x7e, + 0x51, 0x2d, 0x76, 0xfe, 0xdc, 0xe1, 0xff, 0x35 +}; +static const uint8_t ac_dsa_vect223_pub_val[] = { +/* Y */ + 0xea, 0x43, 0x7a, 0xd0, 0xee, 0x92, 0x64, 0xde, 0x87, 0x92, 0xb6, 0x77, + 0x20, 0x7e, 0x54, 0x70, 0x90, 0xb3, 0x2d, 0x6a, 0xb4, 0x60, 0xb4, 0xd5, + 0x89, 0xd8, 0x42, 0xed, 0x0a, 0x0b, 0x4f, 0xb4, 0xc6, 0x35, 0xe4, 0x44, + 0x3b, 0xf6, 0x0e, 0x46, 0xcb, 0xa8, 0xd2, 0x26, 0xf6, 0x59, 0xc7, 0x6d, + 0x2c, 0xa0, 0x1c, 0x69, 0x70, 0x7b, 0xa6, 0xd9, 0x77, 0x25, 0x5c, 0x45, + 0x84, 0xb7, 0x47, 0x40, 0xa7, 0xcd, 0xec, 0x4c, 0x97, 0x3e, 0x3d, 0x16, + 0xab, 0x6a, 0xf6, 0x0c, 0xd3, 0x12, 0x3c, 0xa1, 0x2e, 0xd5, 0x97, 0x1e, + 0x69, 0xea, 0xff, 0xa3, 0xda, 0x07, 0x70, 0xd8, 0xe1, 0x22, 0x88, 0x89, + 0xcd, 0x68, 0x25, 0xe1, 0xb8, 0x58, 0x46, 0xf4, 0xf7, 0xec, 0xdb, 0x33, + 0xf1, 0xe5, 0xc7, 0xac, 0xd6, 0xb2, 0xad, 0xd1, 0x30, 0x8c, 0x5c, 0xec, + 0x43, 0x97, 0x28, 0xd0, 0xcc, 0x62, 0x5e, 0xb8, 0x9d, 0xf3, 0x4f, 0xb9, + 0xc0, 0xdd, 0x45, 0x68, 0xf9, 0x79, 0xde, 0xea, 0xd2, 0x86, 0xc5, 0x01, + 0x45, 0x90, 0x3a, 0x0d, 0xcc, 0xca, 0x72, 0x39, 0x87, 0x4b, 0x46, 0x83, + 0xd3, 0x67, 0xed, 0x31, 0x69, 0x6e, 0xec, 0xad, 0xa9, 0x0d, 0xce, 0xd8, + 0xa9, 0xb1, 0xe0, 0x13, 0x64, 0xb8, 0x79, 0x46, 0x60, 0xc6, 0x0f, 0x40, + 0x59, 0x07, 0x94, 0xc9, 0x5a, 0x61, 0x4c, 0x04, 0x56, 0x3c, 0x92, 0xd4, + 0x44, 0xb5, 0xec, 0xf0, 0x12, 0x86, 0xb1, 0xbf, 0xfe, 0x9e, 0xd9, 0xef, + 0x91, 0x5b, 0x4d, 0xb8, 0x20, 0xea, 0x5c, 0x9a, 0x5b, 0x3d, 0xed, 0xcf, + 0x89, 0xa3, 0xe2, 0xc3, 0x78, 0x71, 0xd2, 0x1b, 0x76, 0x39, 0x90, 0xc7, + 0xbb, 0xf4, 0x44, 0x18, 0xf9, 0x1c, 0xdb, 0xce, 0x43, 0x61, 0xee, 0xb2, + 0x27, 0x51, 0x6c, 0xb3, 0x44, 0x40, 0x9d, 0x2c, 0x65, 0x1f, 0x0d, 0xc2, + 0x9e, 0xc8, 0x26, 0x23 +}; +/* K = 91797ee940a167a57de7619334638f1b3ba63f9065b69f56dc04e4020a1682eb */ +static const uint8_t ac_dsa_vect223_out[] = { +/* R */ + 0x31, 0x52, 0xfc, 0x28, 0x6f, 0xed, 0x44, 0xf2, 0x8b, 0x1a, 0xf2, 0xd5, + 0x37, 0x59, 0x2c, 0x56, 0x91, 0xd6, 0x79, 0x8c, 0xae, 0xd9, 0x05, 0x91, + 0xb5, 0x88, 0x8b, 0x0d, 0x6f, 0xe6, 0xbb, 0x07, +/* S */ + 0x7b, 0xff, 0x61, 0xa8, 0x67, 0x6f, 0x0d, 0xf1, 0x89, 0x65, 0x4f, 0x25, + 0xc5, 0x81, 0x2b, 0x34, 0x1d, 0xd1, 0x7f, 0x4f, 0x44, 0x66, 0x77, 0x89, + 0xcc, 0x88, 0x7c, 0x19, 0x1b, 0xf4, 0x72, 0x02 +}; +#define ac_dsa_vect224_prime ac_dsa_vect211_prime +#define ac_dsa_vect224_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect224_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect224_ptx[] = { +/* Msg */ + 0xa6, 0x51, 0x60, 0x19, 0x72, 0x7d, 0x95, 0x63, 0x9d, 0xb0, 0x38, 0xf9, + 0x03, 0x06, 0xa8, 0xd9, 0x4f, 0xac, 0x52, 0x43, 0xdc, 0x7b, 0x67, 0xc3, + 0x56, 0x8d, 0x63, 0xd8, 0x5d, 0xea, 0xd1, 0xcf, 0xdd, 0xbb, 0x2b, 0x33, + 0x0b, 0x61, 0x95, 0x89, 0xbd, 0x58, 0x2a, 0xf1, 0x5f, 0x08, 0x11, 0x17, + 0x75, 0x04, 0xfd, 0x5b, 0x7a, 0xad, 0x7b, 0x29, 0x86, 0x47, 0xa3, 0xf6, + 0x47, 0x97, 0xe3, 0xda, 0x5f, 0xe5, 0xbf, 0x87, 0xb6, 0x5c, 0x2d, 0xde, + 0xc5, 0x76, 0xa8, 0xf4, 0x06, 0x60, 0x68, 0x6b, 0x80, 0x8b, 0xa4, 0x2e, + 0x54, 0xbf, 0xd0, 0xe9, 0xe4, 0x80, 0x82, 0xd6, 0x90, 0x4f, 0x8e, 0x19, + 0x05, 0x0e, 0x54, 0xea, 0x47, 0x97, 0xa2, 0xf4, 0x01, 0xff, 0x7c, 0x9f, + 0x3d, 0x21, 0x7b, 0x52, 0x6c, 0x03, 0xbe, 0x92, 0x01, 0xc0, 0xdc, 0x1b, + 0x0e, 0x8e, 0x05, 0x4b, 0xbb, 0x32, 0xc3, 0x82 +}; +static const uint8_t ac_dsa_vect224_priv_val[] = { +/* X */ + 0x39, 0x61, 0x02, 0xad, 0x11, 0x6c, 0xa2, 0xe4, 0x19, 0xb9, 0x22, 0x96, + 0x67, 0xa3, 0x17, 0x37, 0x34, 0x4d, 0x0d, 0x78, 0x54, 0xca, 0xc8, 0x93, + 0x0a, 0xf1, 0x8e, 0x12, 0xa9, 0xe2, 0xd6, 0x3e +}; +static const uint8_t ac_dsa_vect224_pub_val[] = { +/* Y */ + 0x97, 0x79, 0xeb, 0x53, 0x38, 0xdc, 0xae, 0x73, 0x77, 0xb1, 0x84, 0x70, + 0x18, 0xce, 0x72, 0xc1, 0xed, 0x4c, 0x55, 0x29, 0x2a, 0x96, 0x3f, 0x81, + 0x60, 0x8e, 0xf3, 0x32, 0x05, 0x0f, 0x0a, 0x48, 0x45, 0x19, 0xaa, 0x96, + 0xb1, 0x8b, 0xcc, 0xe8, 0xe1, 0xb4, 0x9c, 0x11, 0xa2, 0x00, 0xc1, 0xab, + 0x4a, 0x75, 0x72, 0x6b, 0xcc, 0x84, 0x24, 0x85, 0xdf, 0x63, 0x14, 0xe5, + 0xc3, 0x9f, 0xec, 0x62, 0x2d, 0x81, 0x94, 0x34, 0x29, 0x4d, 0xbe, 0x1e, + 0xb6, 0x47, 0x88, 0x5c, 0xe8, 0x41, 0x52, 0x7c, 0x03, 0x48, 0x1b, 0x7f, + 0x22, 0xee, 0x58, 0x6d, 0x8c, 0x2b, 0x1a, 0x84, 0x71, 0xa2, 0x75, 0x7b, + 0xff, 0xbd, 0xd9, 0xc2, 0x6f, 0x12, 0x50, 0x65, 0x68, 0x55, 0x09, 0xff, + 0x0e, 0x4c, 0x8b, 0x82, 0x6d, 0x73, 0xc6, 0xe1, 0x2f, 0x6d, 0x4b, 0x93, + 0x19, 0xcd, 0xfa, 0x72, 0xc0, 0x69, 0xe0, 0x7b, 0x2d, 0x2c, 0x25, 0x4b, + 0x33, 0x0c, 0x06, 0xf4, 0x88, 0xd6, 0x59, 0x8c, 0x74, 0x76, 0xce, 0x0f, + 0x33, 0x30, 0xc9, 0x7e, 0xc3, 0x6b, 0x7c, 0x10, 0x87, 0x13, 0x88, 0x47, + 0x24, 0x51, 0xa3, 0x4a, 0xfb, 0x7b, 0x4d, 0x4e, 0x25, 0x1f, 0x9f, 0x72, + 0xa4, 0xa3, 0x8a, 0x68, 0x51, 0xaa, 0xb8, 0x65, 0x07, 0xb2, 0x83, 0xe8, + 0x90, 0xc3, 0x1b, 0xa9, 0x6d, 0x0a, 0x1e, 0x55, 0x72, 0x63, 0x7b, 0x2d, + 0x84, 0x67, 0x06, 0x0c, 0x07, 0x36, 0xd1, 0x1d, 0x07, 0x44, 0xe3, 0x32, + 0xa1, 0x9f, 0x59, 0xae, 0x29, 0x20, 0x89, 0x4e, 0x9c, 0xff, 0xac, 0xfe, + 0xda, 0x64, 0xae, 0x1f, 0xf4, 0x86, 0x98, 0x82, 0xdf, 0x3b, 0x69, 0x0c, + 0x7c, 0xe8, 0xfe, 0x0e, 0xb8, 0x81, 0x71, 0xe4, 0xf2, 0xab, 0x86, 0x24, + 0xe6, 0xac, 0x77, 0xdc, 0x89, 0x07, 0x61, 0x32, 0x35, 0x16, 0x3e, 0x0a, + 0x2c, 0x7d, 0x9f, 0xd6 +}; +/* K = 79753fbd43773b6757c01663b8f5ef642801aa5ccbf32082c780f71a22c4cb0d */ +static const uint8_t ac_dsa_vect224_out[] = { +/* R */ + 0x72, 0x22, 0xd5, 0xeb, 0x39, 0x24, 0x60, 0xde, 0xfe, 0x8f, 0xe3, 0xdf, + 0x18, 0xfa, 0x53, 0x4f, 0x30, 0x60, 0x23, 0x5f, 0x1e, 0x8d, 0xce, 0x53, + 0x70, 0x76, 0x2e, 0xc6, 0xfc, 0x11, 0xe6, 0x90, +/* S */ + 0x43, 0x51, 0xc4, 0x28, 0x03, 0x1c, 0xd9, 0xaf, 0x56, 0x7b, 0x11, 0x63, + 0x03, 0x7a, 0x4e, 0x37, 0x69, 0x62, 0x62, 0x0c, 0x4e, 0xc2, 0x3c, 0x43, + 0xb7, 0x10, 0x58, 0x79, 0xf9, 0x5b, 0xf6, 0x14 +}; +#define ac_dsa_vect225_prime ac_dsa_vect211_prime +#define ac_dsa_vect225_sub_prime ac_dsa_vect211_sub_prime +#define ac_dsa_vect225_base ac_dsa_vect211_base +static const uint8_t ac_dsa_vect225_ptx[] = { +/* Msg */ + 0x1f, 0xfa, 0x7c, 0xf5, 0x5f, 0x92, 0xf2, 0x34, 0xa2, 0x4b, 0xd3, 0x29, + 0x67, 0x44, 0xd5, 0x43, 0xa4, 0x33, 0xc9, 0x07, 0xc1, 0xf7, 0x7d, 0x8b, + 0x70, 0x6f, 0x4b, 0x62, 0x62, 0xd0, 0x96, 0xe2, 0xdf, 0xe7, 0x13, 0xfa, + 0x9c, 0xa8, 0x0e, 0x68, 0x57, 0x93, 0x96, 0xfc, 0x11, 0xa1, 0x2c, 0x03, + 0x31, 0xcf, 0xb7, 0x74, 0x5d, 0x96, 0xb0, 0x05, 0x20, 0x4e, 0x48, 0x3f, + 0xbf, 0x8f, 0x9f, 0xdc, 0x45, 0x8e, 0x2c, 0xa8, 0x61, 0x34, 0x06, 0x06, + 0x9d, 0xf5, 0xf4, 0x49, 0x18, 0xef, 0xf8, 0xc5, 0xf5, 0x4b, 0x8b, 0x4d, + 0x97, 0x2e, 0x07, 0xa4, 0xb8, 0xe0, 0x6d, 0x84, 0x26, 0xa7, 0x08, 0x74, + 0xce, 0xfe, 0x6e, 0x93, 0x40, 0x4c, 0x1e, 0xb3, 0x81, 0xc2, 0xd0, 0x70, + 0x1c, 0x37, 0xf8, 0x5a, 0xfb, 0x16, 0x01, 0xa0, 0x9f, 0xff, 0x8e, 0xcf, + 0xda, 0xf6, 0xcb, 0x64, 0xad, 0x9b, 0xd8, 0xb7 +}; +static const uint8_t ac_dsa_vect225_priv_val[] = { +/* X */ + 0x24, 0x03, 0x99, 0x63, 0xcc, 0x5a, 0xc2, 0x6a, 0x97, 0x77, 0x28, 0xb8, + 0x52, 0x41, 0x4f, 0x60, 0xa2, 0x87, 0x17, 0x41, 0x86, 0xea, 0x81, 0x2e, + 0x00, 0xa5, 0xc8, 0xa8, 0xa5, 0x35, 0x5d, 0xaf +}; +static const uint8_t ac_dsa_vect225_pub_val[] = { +/* Y */ + 0x18, 0xe2, 0x98, 0xe6, 0x30, 0x13, 0x89, 0xd4, 0x86, 0x44, 0x67, 0x4f, + 0x83, 0x39, 0x48, 0x7a, 0x86, 0x51, 0xb0, 0x76, 0x8d, 0xee, 0x42, 0x59, + 0x05, 0xe8, 0x03, 0xab, 0x35, 0x7c, 0x7f, 0x9f, 0xa0, 0x5d, 0xd5, 0xe2, + 0xee, 0x84, 0xbf, 0xe1, 0x05, 0xa0, 0x92, 0x71, 0x62, 0x74, 0x55, 0x7e, + 0x06, 0x3d, 0x08, 0x6e, 0x78, 0xb7, 0x81, 0xa4, 0x3c, 0x56, 0xa4, 0xe0, + 0xea, 0x11, 0x5c, 0x5c, 0xfe, 0xac, 0x57, 0xa4, 0xc9, 0xb7, 0xe1, 0xef, + 0xfb, 0x89, 0x41, 0x36, 0x89, 0x92, 0x8f, 0x15, 0x46, 0xfe, 0xb3, 0x07, + 0x38, 0x58, 0x6d, 0x36, 0xff, 0xe3, 0x38, 0x08, 0x3e, 0xe2, 0xbf, 0x5c, + 0x5b, 0xd3, 0x44, 0xbc, 0x3d, 0xb2, 0xa7, 0x97, 0x7d, 0xe2, 0xb1, 0xab, + 0x5b, 0xa0, 0x06, 0xd9, 0xee, 0x93, 0xef, 0x86, 0x88, 0xa7, 0xd1, 0x0c, + 0xaf, 0xe2, 0x7a, 0xf3, 0xe6, 0x71, 0x01, 0x3a, 0x81, 0x69, 0x84, 0x19, + 0x6b, 0xfa, 0xcf, 0x00, 0x23, 0x35, 0xfe, 0x74, 0x14, 0x42, 0x3e, 0xd8, + 0xbd, 0xc8, 0x03, 0x27, 0x37, 0x2b, 0x0d, 0x46, 0x08, 0x66, 0x48, 0x0b, + 0xdf, 0x07, 0x3c, 0x9d, 0xef, 0x79, 0x77, 0x13, 0x1b, 0x06, 0xe2, 0x8d, + 0x14, 0xae, 0x1a, 0x81, 0x6d, 0x32, 0x22, 0xeb, 0xaa, 0xdc, 0xc8, 0xd7, + 0xc3, 0x00, 0xaa, 0x82, 0x0e, 0x03, 0x28, 0xaf, 0x66, 0xf7, 0x42, 0x06, + 0x1a, 0xff, 0x5d, 0x4b, 0x71, 0x76, 0xa9, 0x94, 0xad, 0x69, 0xb3, 0x90, + 0xbb, 0xdd, 0x61, 0x9f, 0xce, 0x04, 0x7d, 0xc7, 0xd1, 0x5a, 0x48, 0xea, + 0x71, 0xaf, 0xa7, 0x20, 0x40, 0xbb, 0x14, 0xee, 0xaf, 0x4a, 0x2b, 0x23, + 0xd9, 0x9b, 0x4d, 0x97, 0x7b, 0xeb, 0x6d, 0x80, 0x61, 0x01, 0x02, 0x1e, + 0xb0, 0xc3, 0xa0, 0xe3, 0x1e, 0x54, 0x57, 0x9e, 0x58, 0xc9, 0x53, 0xb5, + 0x5b, 0x6e, 0x32, 0x45 +}; +/* K = 2ae1af11ff810141c37b1c23796e54f027b4eb7c2f0c412b6c83076de3d4aba1 */ +static const uint8_t ac_dsa_vect225_out[] = { +/* R */ + 0x21, 0xd7, 0x0e, 0xd9, 0x55, 0xb0, 0x9e, 0xa3, 0x02, 0xfb, 0x79, 0x29, + 0x78, 0xd1, 0x25, 0x01, 0x07, 0x1a, 0x2e, 0x8e, 0x2c, 0xc8, 0xf6, 0x59, + 0xde, 0xcd, 0x3d, 0xf2, 0x4e, 0x37, 0xc4, 0x66, +/* S */ + 0x2c, 0xda, 0xae, 0xe2, 0xa5, 0xa3, 0xdd, 0x74, 0xa6, 0x77, 0x95, 0xf9, + 0x3a, 0xc1, 0xd8, 0x41, 0x62, 0x23, 0x83, 0x6c, 0x76, 0xf7, 0xfe, 0x31, + 0xc7, 0x2e, 0xc6, 0x17, 0x09, 0x25, 0xfd, 0x73 +}; +/* [mod = L=3072, N=256, SHA-1] */ +static const uint8_t ac_dsa_vect226_prime[] = { +/* P */ + 0xfd, 0x5a, 0x6c, 0x56, 0xdd, 0x29, 0x0f, 0x7d, 0xd8, 0x4a, 0x29, 0xde, + 0x17, 0x12, 0x6e, 0xb4, 0xe4, 0x48, 0x7b, 0x3e, 0xff, 0x0a, 0x44, 0xab, + 0xe5, 0xc5, 0x97, 0x92, 0xd2, 0xe1, 0x20, 0x0b, 0x9c, 0x3d, 0xb4, 0x4d, + 0x52, 0x8b, 0x9f, 0x7d, 0x22, 0x48, 0x03, 0x2e, 0x4b, 0xa0, 0xf7, 0xbf, + 0xc4, 0xfa, 0xfc, 0x70, 0x6b, 0xe5, 0x11, 0xdb, 0x22, 0x76, 0xc0, 0xb7, + 0xec, 0xff, 0xd3, 0x8d, 0xa2, 0xe1, 0xc2, 0xf2, 0x37, 0xa7, 0x53, 0x90, + 0xc1, 0xe4, 0xd3, 0x23, 0x9c, 0xba, 0x8e, 0x20, 0xe5, 0x58, 0x40, 0xec, + 0xb0, 0x5d, 0xf5, 0xf0, 0x1a, 0x1b, 0x69, 0x77, 0xad, 0x19, 0x06, 0xf2, + 0xcb, 0x54, 0x4c, 0xcf, 0xb9, 0x3b, 0x90, 0x1a, 0xd0, 0x96, 0x6b, 0x18, + 0x32, 0xad, 0x2d, 0xab, 0x52, 0x62, 0x44, 0xa3, 0x15, 0x6c, 0x90, 0x5c, + 0x01, 0xac, 0x51, 0xcb, 0x73, 0xb9, 0xdc, 0xd9, 0x86, 0x0d, 0x56, 0x17, + 0x5a, 0x42, 0x5d, 0x84, 0x64, 0x85, 0xd9, 0xb1, 0xf4, 0x4a, 0x8a, 0x0c, + 0x25, 0x78, 0xe6, 0xcf, 0x61, 0x94, 0x7b, 0xc1, 0xa1, 0x39, 0x2f, 0xdd, + 0x32, 0x0b, 0x16, 0xa9, 0xd7, 0x04, 0x55, 0xfe, 0x43, 0x6f, 0x2d, 0x47, + 0xde, 0xd8, 0xe8, 0xe6, 0x05, 0xf7, 0x48, 0x6e, 0xb5, 0x78, 0xea, 0x7f, + 0xc4, 0xff, 0xd1, 0x3c, 0x07, 0xf9, 0x99, 0x6a, 0xf1, 0x59, 0xfd, 0x41, + 0x1e, 0x94, 0x51, 0x40, 0x32, 0x78, 0xdd, 0x11, 0x41, 0xa8, 0xc9, 0x26, + 0xb3, 0x5c, 0x96, 0x38, 0x4b, 0xbd, 0x6b, 0xee, 0x09, 0xc4, 0x6f, 0x44, + 0xc3, 0x6b, 0x1f, 0xfc, 0x71, 0x97, 0xf5, 0xe9, 0x25, 0xdb, 0xe0, 0x54, + 0x4a, 0x68, 0xe6, 0xab, 0x8c, 0x18, 0xe4, 0x26, 0xa4, 0x66, 0xb3, 0x92, + 0xf9, 0xc2, 0x7d, 0xd7, 0x9f, 0xef, 0xa9, 0xca, 0x16, 0x3c, 0xc5, 0xa3, + 0x75, 0x53, 0x9a, 0x85, 0x59, 0xf2, 0x77, 0xf6, 0x57, 0xa5, 0x35, 0xd1, + 0x96, 0x4c, 0x6a, 0x5e, 0x91, 0x68, 0x3e, 0xf5, 0x69, 0x8e, 0xba, 0xa0, + 0x1e, 0xf8, 0x18, 0xdb, 0xf7, 0x2c, 0xb0, 0x4c, 0x3f, 0xf0, 0x92, 0xd1, + 0x88, 0x86, 0x6f, 0x25, 0xcd, 0x40, 0x51, 0x08, 0xf5, 0x66, 0xb0, 0x87, + 0xf7, 0x3d, 0x2d, 0x5b, 0xeb, 0x51, 0xfa, 0xc6, 0xde, 0x84, 0xae, 0x51, + 0x61, 0xa6, 0x6a, 0xf9, 0x60, 0x2c, 0x7e, 0x4b, 0xfc, 0x14, 0x6f, 0x48, + 0x20, 0xbd, 0xfc, 0x09, 0x2f, 0xae, 0xac, 0x69, 0x13, 0x3e, 0x4a, 0x08, + 0xa5, 0xb2, 0x02, 0xa1, 0x24, 0x98, 0xa2, 0x2e, 0x57, 0xba, 0xd5, 0x46, + 0x74, 0xed, 0x4b, 0x51, 0x01, 0x09, 0xd5, 0x2b, 0x5f, 0x74, 0xe7, 0x0e, + 0x1f, 0x6f, 0x82, 0x16, 0x17, 0x18, 0xcd, 0x4c, 0xf0, 0x0c, 0xc9, 0xf1, + 0x95, 0x8a, 0xcc, 0x8b, 0xdd, 0xcd, 0xfb, 0xd1, 0xfb, 0xe4, 0x6c, 0xd1 +}; +static const uint8_t ac_dsa_vect226_sub_prime[] = { +/* Q */ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x4a, 0x26, 0xdd, 0x8f, 0x49, 0xc6, 0x81, 0x1c, 0xe8, 0x1b, 0xb1, + 0x34, 0x2b, 0x06, 0xe9, 0x80, 0xf6, 0x4b, 0x75 +}; +static const uint8_t ac_dsa_vect226_base[] = { +/* G */ + 0x99, 0xab, 0x03, 0x0a, 0x21, 0xa5, 0xc9, 0x81, 0x81, 0x74, 0x87, 0x21, + 0x67, 0x64, 0x1c, 0x81, 0xc1, 0xe0, 0x3c, 0x9b, 0x27, 0x4c, 0xfb, 0xc2, + 0x7b, 0xc4, 0x72, 0x54, 0x29, 0x27, 0x76, 0x6d, 0xe5, 0xfa, 0x05, 0x39, + 0xb3, 0xb7, 0x3f, 0x3f, 0x16, 0xac, 0x86, 0x6a, 0x9a, 0xec, 0x8b, 0x44, + 0x5d, 0xed, 0x97, 0xfb, 0xff, 0x08, 0x83, 0x4e, 0xd9, 0x8c, 0x77, 0xe7, + 0xfc, 0x89, 0xe5, 0xdc, 0x65, 0x7b, 0xef, 0x76, 0x6f, 0xf7, 0xfb, 0xf8, + 0xe7, 0x68, 0x73, 0xe1, 0x7b, 0xee, 0x41, 0x27, 0x62, 0xd5, 0x6f, 0xe1, + 0x14, 0x17, 0x60, 0xab, 0x4d, 0x25, 0xba, 0xfd, 0x4b, 0x6e, 0xf2, 0x5b, + 0x49, 0xa3, 0x50, 0x66, 0x32, 0xd1, 0xf8, 0xe1, 0x07, 0x70, 0x93, 0x07, + 0x60, 0xec, 0x13, 0x25, 0x93, 0x2c, 0x5a, 0x4b, 0xaf, 0x9e, 0x90, 0x15, + 0x42, 0x64, 0xdd, 0xf4, 0x42, 0xec, 0x5c, 0x41, 0xfe, 0xd9, 0x5d, 0x11, + 0x52, 0x51, 0x51, 0xdb, 0xcf, 0xb3, 0x75, 0x81, 0x49, 0xba, 0xd8, 0x1c, + 0x62, 0xb9, 0xcf, 0xf7, 0x81, 0x6b, 0x8f, 0x95, 0x3b, 0x8b, 0x7c, 0x02, + 0x25, 0x90, 0xd1, 0x58, 0x4e, 0x92, 0x1d, 0xc9, 0x55, 0xf5, 0x32, 0x8a, + 0xc7, 0x29, 0x83, 0xed, 0x5c, 0xf0, 0xd0, 0x40, 0x56, 0xfe, 0x0d, 0x53, + 0x1e, 0x62, 0xf8, 0xf6, 0xc9, 0xab, 0x3c, 0x0f, 0xcd, 0x44, 0xe1, 0x48, + 0x60, 0xb7, 0x31, 0x1d, 0x25, 0x61, 0xc7, 0x7c, 0x1d, 0x32, 0xf6, 0xc6, + 0x9d, 0xc8, 0xf7, 0x79, 0x68, 0xc9, 0xd8, 0x81, 0xad, 0x9d, 0xb5, 0xe0, + 0xc1, 0x14, 0xfd, 0xa8, 0x62, 0x8b, 0xca, 0x03, 0x35, 0xeb, 0x7f, 0xb9, + 0xe1, 0x5e, 0x62, 0x5a, 0xab, 0xab, 0x58, 0xfc, 0x01, 0x19, 0x4c, 0x81, + 0xbf, 0x6f, 0xb2, 0xce, 0x54, 0x07, 0x7b, 0x82, 0x25, 0x0e, 0x57, 0xc6, + 0xa7, 0xb2, 0x5d, 0xeb, 0x6e, 0xe3, 0x9d, 0x4b, 0x68, 0x6a, 0x5c, 0x30, + 0x7a, 0x76, 0x12, 0xb2, 0xd8, 0x5e, 0xe9, 0x25, 0x12, 0x41, 0x3d, 0xea, + 0x29, 0x7e, 0x44, 0xf3, 0x17, 0xbe, 0x7c, 0xeb, 0x70, 0xa3, 0x32, 0x8a, + 0xf0, 0xb4, 0x01, 0x00, 0x1a, 0x41, 0x85, 0x62, 0xb8, 0xff, 0xe4, 0xe9, + 0x77, 0x1b, 0x4b, 0x4a, 0x8e, 0x0b, 0x40, 0xc7, 0x91, 0x34, 0x9d, 0x5d, + 0x4e, 0x45, 0x9f, 0xe6, 0x20, 0xa1, 0xa2, 0xfc, 0x72, 0xe2, 0xf6, 0xca, + 0x28, 0x56, 0x7d, 0x4c, 0x26, 0x32, 0xbb, 0xde, 0x1b, 0x49, 0x86, 0x4c, + 0x06, 0xbb, 0x12, 0x61, 0x9f, 0x13, 0x2c, 0x1d, 0xa8, 0xf5, 0x71, 0xef, + 0x61, 0x3e, 0xac, 0x73, 0x9f, 0x66, 0xab, 0x39, 0x14, 0xcb, 0x3f, 0xa1, + 0xab, 0x86, 0xe0, 0x5e, 0x50, 0x82, 0xeb, 0xaa, 0x24, 0xeb, 0xee, 0xa4, + 0xcf, 0x51, 0xbe, 0xef, 0xc2, 0x7d, 0xf5, 0x12, 0xfe, 0x3f, 0xee, 0x7d +}; +static const uint8_t ac_dsa_vect226_ptx[] = { +/* Msg */ + 0xca, 0x84, 0xaf, 0x5c, 0x9a, 0xdb, 0xc0, 0x04, 0x4d, 0xb0, 0x0d, 0x7a, + 0xcf, 0xb1, 0xb4, 0x93, 0xaa, 0xb0, 0x38, 0x8f, 0xfb, 0xad, 0x47, 0xb3, + 0x8c, 0xd3, 0xe9, 0xe3, 0x11, 0x1c, 0xfe, 0x2c, 0xda, 0x2a, 0x45, 0xf7, + 0x51, 0xc4, 0x68, 0x62, 0xf0, 0x5b, 0xdc, 0xec, 0x4b, 0x69, 0x8a, 0xdf, + 0xd2, 0xe1, 0x60, 0x6e, 0x48, 0x4c, 0x3b, 0xe4, 0xac, 0x0c, 0x37, 0x9d, + 0x4f, 0xbc, 0x7c, 0x2c, 0xda, 0x43, 0xe9, 0x22, 0x81, 0x1d, 0x7f, 0x6c, + 0x33, 0x04, 0x0e, 0x8e, 0x65, 0xd5, 0xf3, 0x17, 0x68, 0x4b, 0x90, 0xe2, + 0x63, 0x87, 0xcf, 0x93, 0x1f, 0xe7, 0xc2, 0xf5, 0x15, 0x05, 0x8d, 0x75, + 0x3b, 0x08, 0x13, 0x7f, 0xf2, 0xc6, 0xb7, 0x9c, 0x91, 0x0d, 0xe8, 0x28, + 0x31, 0x49, 0xe6, 0x87, 0x2c, 0xb6, 0x6f, 0x7e, 0x02, 0xe6, 0x6f, 0x23, + 0x71, 0x78, 0x51, 0x29, 0x56, 0x93, 0x62, 0xf1 +}; +static const uint8_t ac_dsa_vect226_priv_val[] = { +/* X */ + 0x43, 0x3c, 0xfd, 0x05, 0x32, 0xcc, 0xfd, 0x8c, 0xdd, 0x1b, 0x25, 0x92, + 0x0d, 0x2b, 0xb7, 0x39, 0x69, 0x87, 0xb7, 0x66, 0x24, 0x03, 0x79, 0x03, + 0x5b, 0x0e, 0x86, 0x52, 0x7c, 0xe9, 0xc5, 0x2d +}; +static const uint8_t ac_dsa_vect226_pub_val[] = { +/* Y */ + 0xe7, 0xc2, 0xee, 0x18, 0xc3, 0xaa, 0x36, 0x2c, 0x01, 0x82, 0xc6, 0xa5, + 0x6c, 0x25, 0x84, 0x62, 0x80, 0x83, 0xc7, 0x3e, 0x04, 0x5b, 0xed, 0xa8, + 0xd6, 0x53, 0x69, 0x0c, 0x9c, 0x2f, 0x65, 0x44, 0xed, 0xf9, 0x70, 0x2c, + 0x57, 0xc4, 0x55, 0x27, 0x39, 0x05, 0x33, 0x6a, 0x5f, 0x51, 0x71, 0x10, + 0x7a, 0x31, 0x3c, 0xd7, 0xd0, 0xb0, 0xf5, 0x0f, 0x8d, 0x33, 0x42, 0xc6, + 0x02, 0x19, 0xf2, 0x2a, 0x90, 0x23, 0x39, 0x40, 0x59, 0xd0, 0x5f, 0x46, + 0x4c, 0x44, 0x96, 0xd5, 0x5d, 0xab, 0x6e, 0xb0, 0x89, 0x85, 0x27, 0xff, + 0x4c, 0xf5, 0x67, 0x8e, 0x7b, 0x5b, 0xfb, 0x5e, 0x18, 0xd9, 0x2c, 0x4a, + 0x9d, 0x73, 0x28, 0x8c, 0xce, 0x14, 0x53, 0x0f, 0xc4, 0x70, 0x2f, 0x6d, + 0x03, 0x97, 0xec, 0x39, 0xa8, 0x80, 0xc4, 0xa7, 0x2d, 0x35, 0x87, 0x30, + 0xc5, 0x66, 0x33, 0x38, 0x6e, 0xde, 0x02, 0x80, 0x23, 0xc1, 0x79, 0x1f, + 0x31, 0x64, 0xd1, 0x57, 0x4e, 0x78, 0x23, 0xc7, 0x9b, 0x8a, 0x3c, 0xa1, + 0x34, 0x3e, 0xa1, 0x66, 0xba, 0x6f, 0x02, 0xb7, 0xff, 0x7e, 0x9e, 0xf2, + 0x19, 0x8d, 0xb1, 0x07, 0xf7, 0xcc, 0x15, 0x9f, 0x3b, 0x6a, 0x1c, 0x00, + 0xa7, 0x8c, 0x35, 0x5c, 0x56, 0x6d, 0xeb, 0x0a, 0xc6, 0xfd, 0xe3, 0xf6, + 0x33, 0xcb, 0x91, 0x77, 0xa1, 0xfb, 0xc6, 0xc1, 0x76, 0x6c, 0xa0, 0x21, + 0xd5, 0xfe, 0xc4, 0x70, 0x10, 0x1a, 0xbb, 0x44, 0x0d, 0x2f, 0x06, 0x98, + 0x21, 0x81, 0xa8, 0xc9, 0x2b, 0x7c, 0xdd, 0x76, 0x53, 0x36, 0xb9, 0xa1, + 0xe1, 0xab, 0x70, 0x28, 0x3d, 0x6d, 0xb0, 0xa9, 0x63, 0xfb, 0x64, 0x8c, + 0x37, 0xc4, 0xe2, 0x9a, 0x74, 0xc3, 0x75, 0x77, 0x29, 0x10, 0x49, 0xab, + 0x47, 0xcd, 0xbc, 0x10, 0x4c, 0x04, 0xdb, 0x96, 0x66, 0x81, 0xea, 0x8e, + 0xbb, 0x9f, 0x00, 0xcf, 0x4c, 0x4a, 0x54, 0x62, 0x11, 0x73, 0x79, 0x57, + 0x5f, 0xbd, 0xa4, 0xb8, 0x01, 0x97, 0x94, 0x51, 0xfa, 0x94, 0xb1, 0x9b, + 0x4e, 0x93, 0x65, 0x67, 0x05, 0xc0, 0xf7, 0x34, 0xf3, 0xe0, 0x91, 0x4b, + 0xb9, 0x6c, 0x1e, 0x2b, 0x8a, 0x0f, 0xb6, 0x8f, 0xaf, 0x14, 0x29, 0x6e, + 0xfd, 0xf3, 0x30, 0x0a, 0xd9, 0x5b, 0xcd, 0xe8, 0xb6, 0x7c, 0xc4, 0xb2, + 0x6e, 0x64, 0x88, 0xee, 0xf9, 0x25, 0xcf, 0xae, 0xac, 0x6f, 0x0d, 0x65, + 0x67, 0xe8, 0xb4, 0x13, 0x55, 0xf8, 0x9d, 0x1c, 0x2b, 0x8f, 0xe6, 0x87, + 0xbf, 0xa2, 0xdf, 0x5e, 0x28, 0x7e, 0x13, 0x05, 0xb8, 0x9b, 0x8c, 0x38, + 0x8c, 0x26, 0x19, 0x60, 0x90, 0xac, 0x03, 0x51, 0xab, 0xc5, 0x61, 0xaa, + 0xdc, 0x79, 0x7d, 0xa8, 0xcc, 0xea, 0x41, 0x46, 0xc3, 0xe9, 0x60, 0x95, + 0xeb, 0xce, 0x35, 0x3e, 0x0d, 0xa4, 0xc5, 0x50, 0x19, 0x05, 0x2c, 0xaa +}; +/* K = 40f503abd70fd49a76c67a83e08b062b3fd465ad92be433c080e5f295bb9f559 */ +static const uint8_t ac_dsa_vect226_out[] = { +/* R */ + 0x21, 0xca, 0x14, 0x8c, 0xdf, 0x44, 0xbe, 0x4a, 0xe9, 0x3b, 0x2f, 0x35, + 0x3b, 0x8e, 0x51, 0x2d, 0x03, 0xad, 0x96, 0xda, 0xfa, 0x80, 0x62, 0x3f, + 0xde, 0x49, 0x22, 0xa9, 0x5f, 0x03, 0x27, 0x32, +/* S */ + 0x73, 0xe4, 0x8b, 0x77, 0xa3, 0xaa, 0x44, 0x30, 0x74, 0x83, 0xc2, 0xdd, + 0x89, 0x5c, 0xb5, 0x1d, 0xb2, 0x11, 0x21, 0x77, 0xc1, 0x85, 0xc5, 0x9c, + 0xb1, 0xdc, 0xff, 0x32, 0xfd, 0xa0, 0x2a, 0x4f +}; +#define ac_dsa_vect227_prime ac_dsa_vect226_prime +#define ac_dsa_vect227_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect227_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect227_ptx[] = { +/* Msg */ + 0x3c, 0xca, 0xd0, 0x01, 0x85, 0x19, 0xa8, 0x98, 0xf8, 0x7d, 0x8c, 0xe5, + 0xf2, 0x8c, 0x0d, 0x93, 0xab, 0x16, 0xc5, 0x1a, 0xdd, 0xf4, 0x17, 0x33, + 0x22, 0xcb, 0xc4, 0x9d, 0x48, 0xca, 0x9e, 0xa3, 0x7e, 0xbe, 0x8b, 0xc9, + 0xd8, 0xc1, 0xb3, 0xf7, 0x83, 0xf8, 0xcf, 0x59, 0xcf, 0x3f, 0xcb, 0xa1, + 0x0a, 0x39, 0x3e, 0xb2, 0xdd, 0xd9, 0x89, 0xce, 0x25, 0x8e, 0x73, 0x78, + 0x8c, 0xe7, 0x4b, 0x0c, 0xe8, 0x22, 0x3d, 0x24, 0xe9, 0x93, 0xcf, 0xea, + 0xfa, 0x49, 0xcc, 0x8e, 0xc1, 0xb8, 0xec, 0xee, 0x01, 0x7d, 0x83, 0xa1, + 0x1b, 0xb7, 0x03, 0x4c, 0x77, 0x92, 0x06, 0xc3, 0x64, 0xac, 0x46, 0x3c, + 0xfe, 0xd3, 0x04, 0x7e, 0x1a, 0x2b, 0xf5, 0xc5, 0x91, 0x77, 0x3b, 0x1d, + 0x88, 0x2b, 0x31, 0x0b, 0xfb, 0xa2, 0xdb, 0x87, 0x89, 0x3c, 0x89, 0xa5, + 0x44, 0x2c, 0x08, 0x45, 0xbf, 0x64, 0x4e, 0x21 +}; +static const uint8_t ac_dsa_vect227_priv_val[] = { +/* X */ + 0x30, 0x6c, 0x13, 0x04, 0xb3, 0x80, 0xb7, 0xc3, 0xe0, 0x9e, 0x7a, 0x4b, + 0x48, 0x9c, 0x64, 0xa2, 0x95, 0x58, 0x2b, 0xb3, 0xe0, 0x3c, 0xe5, 0x26, + 0xf1, 0x3d, 0x74, 0x82, 0xef, 0x82, 0x63, 0xf0 +}; +static const uint8_t ac_dsa_vect227_pub_val[] = { +/* Y */ + 0x37, 0x50, 0xd3, 0x63, 0x53, 0xbf, 0xd2, 0xe9, 0x97, 0x3e, 0x26, 0xa5, + 0x55, 0xbc, 0xf0, 0xd8, 0x34, 0xd3, 0xd6, 0x62, 0x0c, 0xb6, 0x65, 0x79, + 0x19, 0x9e, 0x04, 0x0c, 0xe8, 0xec, 0xcf, 0xae, 0xe6, 0x60, 0x04, 0x6e, + 0x78, 0xdf, 0x66, 0xe8, 0xff, 0x64, 0x15, 0x23, 0x04, 0x6a, 0xdc, 0xf4, + 0x25, 0xb8, 0x31, 0x9d, 0xb2, 0x44, 0x76, 0x80, 0x19, 0x4c, 0x3a, 0x38, + 0x6b, 0x52, 0x01, 0xdd, 0x1a, 0xc6, 0xbf, 0x3e, 0x66, 0x39, 0x4e, 0x93, + 0x9e, 0xaa, 0xac, 0xa4, 0xfd, 0x3f, 0x38, 0x6f, 0xcf, 0xe1, 0xd5, 0xef, + 0x45, 0x24, 0xb0, 0x6c, 0x5e, 0xd9, 0xa1, 0x57, 0x46, 0xf2, 0x4b, 0xae, + 0xf1, 0xee, 0xc4, 0x1e, 0x68, 0x3b, 0xf3, 0x53, 0x71, 0x08, 0x44, 0x95, + 0xd4, 0xda, 0x8e, 0x72, 0x7a, 0xeb, 0xa3, 0x07, 0xfb, 0xa0, 0x00, 0xa7, + 0x69, 0xa2, 0x34, 0xe3, 0xc4, 0x60, 0x97, 0x04, 0xb3, 0xba, 0x4d, 0xfd, + 0x6a, 0x86, 0x44, 0xfb, 0xa5, 0x60, 0x83, 0xda, 0xc8, 0x48, 0x75, 0x1b, + 0x52, 0xa8, 0xc2, 0xcd, 0xc4, 0x79, 0x46, 0xcd, 0x21, 0xea, 0x24, 0x38, + 0x3c, 0xc6, 0x24, 0x4f, 0x00, 0x09, 0x18, 0xe9, 0xa2, 0x32, 0x76, 0xb6, + 0x06, 0xc5, 0x68, 0x85, 0x65, 0xc4, 0x4d, 0xdf, 0x77, 0x88, 0x18, 0x1b, + 0x78, 0x95, 0x65, 0xa6, 0xbe, 0xcd, 0x25, 0x71, 0x23, 0xbb, 0x81, 0xa2, + 0xcb, 0xf9, 0xdb, 0x7f, 0xa3, 0x84, 0xe0, 0xca, 0x41, 0x80, 0x4e, 0xd7, + 0xcd, 0x3c, 0x9c, 0xa0, 0xe1, 0xf8, 0xbb, 0x39, 0x0b, 0xff, 0x50, 0x21, + 0x3b, 0x06, 0x29, 0x68, 0x24, 0x09, 0x93, 0x37, 0x70, 0xf6, 0xe0, 0x3a, + 0x5c, 0x4e, 0x7e, 0x89, 0xad, 0xe9, 0x02, 0x55, 0x60, 0x97, 0x86, 0xf6, + 0xb2, 0xfc, 0x5a, 0x7a, 0xa7, 0x56, 0x6b, 0xcf, 0x7f, 0x72, 0x5a, 0xea, + 0xd4, 0xcf, 0x45, 0x6c, 0x5f, 0x5e, 0xd7, 0xdc, 0x3e, 0x91, 0xe2, 0x0d, + 0x94, 0xd1, 0xaa, 0x2f, 0x65, 0x68, 0xc9, 0x7a, 0xbd, 0xf2, 0x1e, 0x0b, + 0xa8, 0xcb, 0xfb, 0x65, 0x61, 0x30, 0x5c, 0xb4, 0x51, 0x75, 0xb1, 0xab, + 0xd7, 0xf3, 0x9b, 0x9a, 0x11, 0xc7, 0x97, 0x92, 0x6b, 0x94, 0x4f, 0x5d, + 0x13, 0xc3, 0xd7, 0x0e, 0x0b, 0x2a, 0x8c, 0xa1, 0x8e, 0x1f, 0x5c, 0xda, + 0x8c, 0xe6, 0xac, 0x43, 0xec, 0xbc, 0x1f, 0xef, 0x88, 0x1f, 0x5e, 0xef, + 0x5a, 0x84, 0x2f, 0xd5, 0x98, 0x4a, 0xd1, 0xe3, 0x21, 0xa3, 0x17, 0x00, + 0x5a, 0xd4, 0x78, 0xcb, 0x47, 0xc9, 0xcf, 0xf6, 0x12, 0x67, 0xf1, 0xd4, + 0x96, 0xfd, 0xed, 0x0a, 0x48, 0x32, 0x8d, 0x62, 0x9b, 0x7b, 0x20, 0x0c, + 0x44, 0x16, 0x34, 0xee, 0x90, 0x88, 0x79, 0x01, 0x17, 0x45, 0xbc, 0xab, + 0x66, 0x60, 0xe1, 0x55, 0x83, 0x74, 0x80, 0x14, 0xd6, 0xde, 0x2f, 0xe2 +}; +/* K = 223e52fc516c0a79f55a5474321264fcce78c050cf79b3d9961b37e24d7f32d3 */ +static const uint8_t ac_dsa_vect227_out[] = { +/* R */ + 0x1e, 0xf7, 0x72, 0x33, 0x45, 0xb2, 0x01, 0x3b, 0x71, 0x10, 0x4c, 0xee, + 0xdb, 0xe7, 0xa9, 0xca, 0xd4, 0x30, 0x01, 0x89, 0x68, 0xbb, 0x29, 0x5b, + 0x67, 0x2c, 0x2b, 0x57, 0xb9, 0xa1, 0x08, 0xb9, +/* S */ + 0x72, 0x85, 0x2d, 0xa4, 0x85, 0xc0, 0x83, 0x6a, 0x8e, 0xbd, 0xbc, 0x4c, + 0x99, 0x6f, 0x7f, 0x6c, 0xb6, 0x5e, 0x99, 0x39, 0x1c, 0xe0, 0x6b, 0x19, + 0xa7, 0x18, 0x76, 0x18, 0xe9, 0xa9, 0x55, 0x84 +}; +#define ac_dsa_vect228_prime ac_dsa_vect226_prime +#define ac_dsa_vect228_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect228_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect228_ptx[] = { +/* Msg */ + 0x1f, 0xc9, 0x82, 0x88, 0x85, 0x7f, 0xb3, 0xa8, 0x3a, 0xb5, 0x07, 0x46, + 0x5a, 0x53, 0xc0, 0x79, 0xed, 0x66, 0x67, 0x9c, 0xaf, 0xdf, 0xb8, 0x65, + 0x3b, 0xfd, 0xeb, 0xb0, 0x30, 0x20, 0xfe, 0x86, 0xa9, 0x43, 0x18, 0x2d, + 0x4f, 0x13, 0x77, 0xd5, 0x8e, 0xca, 0x3c, 0x77, 0x10, 0xd3, 0x2e, 0x21, + 0x0d, 0x8d, 0x03, 0x72, 0x8b, 0xc6, 0x9e, 0x1b, 0x80, 0x03, 0x94, 0x4f, + 0xfe, 0xda, 0xa1, 0xb6, 0x9a, 0xe6, 0xcc, 0x50, 0x63, 0x02, 0xbd, 0x69, + 0x17, 0x01, 0x9f, 0x58, 0x8c, 0xc2, 0x95, 0x01, 0xcc, 0x82, 0x63, 0x57, + 0x2e, 0xbc, 0x0f, 0xeb, 0x15, 0x38, 0x77, 0x17, 0x4b, 0xcf, 0xdb, 0xad, + 0x4a, 0x58, 0x65, 0x91, 0x75, 0xd2, 0xde, 0x71, 0xd5, 0xf5, 0x01, 0x9c, + 0x46, 0xd1, 0x12, 0xb6, 0x63, 0x1c, 0xf0, 0xc3, 0xf9, 0x12, 0xaa, 0xc8, + 0x31, 0x40, 0xcd, 0x56, 0xcd, 0xf9, 0x03, 0xee +}; +static const uint8_t ac_dsa_vect228_priv_val[] = { +/* X */ + 0x04, 0x7a, 0x5e, 0x52, 0x03, 0x9d, 0xa4, 0x05, 0x23, 0xfe, 0xff, 0xe6, + 0x33, 0x12, 0x88, 0x7e, 0x4d, 0x1e, 0xcd, 0xf6, 0x4f, 0x32, 0xab, 0xb3, + 0x1d, 0xfe, 0x68, 0x0b, 0xd1, 0x51, 0x30, 0x77 +}; +static const uint8_t ac_dsa_vect228_pub_val[] = { +/* Y */ + 0x33, 0x53, 0x72, 0x77, 0x0c, 0x0e, 0x8e, 0x59, 0x1a, 0x36, 0x7d, 0xe9, + 0x98, 0x33, 0xbd, 0xe6, 0xf0, 0x12, 0x40, 0xbc, 0x6e, 0x23, 0x6a, 0x5b, + 0x4e, 0x36, 0x23, 0x3e, 0x12, 0x0b, 0x8e, 0xe6, 0xd1, 0xc1, 0x9c, 0x77, + 0xf4, 0xcd, 0xbc, 0x29, 0x4d, 0x32, 0x78, 0xc3, 0xd4, 0xcf, 0x73, 0xed, + 0x9e, 0x8e, 0xa5, 0x03, 0x2b, 0x05, 0x24, 0xa3, 0x91, 0xcf, 0x29, 0x3b, + 0x35, 0xee, 0x7e, 0x02, 0x34, 0x30, 0x22, 0x22, 0x16, 0xd9, 0xf1, 0x8b, + 0x45, 0x02, 0x2f, 0x4d, 0x5f, 0x93, 0x85, 0xf6, 0x38, 0x4d, 0x9f, 0xaf, + 0x1a, 0x0f, 0xfa, 0x4a, 0x80, 0x0d, 0xa2, 0x3b, 0x93, 0x76, 0x51, 0xa0, + 0x9e, 0x82, 0xc2, 0x22, 0x85, 0xb9, 0xde, 0x6a, 0x40, 0x8e, 0x23, 0x38, + 0x6f, 0xfa, 0x67, 0xab, 0xb9, 0xd1, 0xc7, 0x1c, 0xda, 0x7b, 0xc0, 0xc9, + 0x35, 0x25, 0xfc, 0xd7, 0x9e, 0x83, 0x15, 0x3e, 0x74, 0x60, 0x70, 0x78, + 0x24, 0x67, 0x85, 0x8b, 0x69, 0x7a, 0xd1, 0x49, 0x14, 0x67, 0x30, 0x33, + 0xfe, 0xdb, 0x2d, 0x7a, 0x10, 0x5a, 0xd2, 0xd4, 0x38, 0xda, 0xaa, 0x35, + 0xb5, 0x03, 0xb5, 0x18, 0x31, 0x4a, 0xc3, 0x70, 0xfc, 0x5b, 0x11, 0x12, + 0xd4, 0xfe, 0x51, 0x4e, 0x58, 0x35, 0xd9, 0xa8, 0x6d, 0xe2, 0x5e, 0x6b, + 0x35, 0x69, 0x13, 0x92, 0xd1, 0xcd, 0x04, 0x83, 0x6d, 0x41, 0x26, 0xb2, + 0x95, 0xb8, 0xa8, 0x9f, 0x21, 0x7d, 0x58, 0x12, 0x58, 0xaf, 0x95, 0x27, + 0x7b, 0x8b, 0x91, 0xc3, 0x1e, 0x6b, 0x0d, 0x23, 0xa7, 0xc5, 0x2b, 0x0c, + 0xe2, 0x64, 0x1c, 0xf1, 0xa2, 0x52, 0x83, 0x8b, 0x6e, 0x28, 0xe2, 0x26, + 0xcf, 0xc4, 0xfa, 0x9d, 0xc9, 0x14, 0xc5, 0xf6, 0x75, 0xfc, 0x90, 0x0e, + 0xd6, 0x80, 0xdc, 0x1a, 0xa9, 0xe1, 0xd1, 0x71, 0x93, 0xc4, 0x32, 0xaf, + 0x40, 0x32, 0xeb, 0xab, 0x95, 0x41, 0x91, 0x32, 0x70, 0x83, 0xc5, 0x9a, + 0x5f, 0x64, 0xc1, 0xea, 0x18, 0x10, 0x7c, 0xe4, 0xd7, 0x21, 0x1d, 0x1c, + 0x22, 0xf0, 0x48, 0x05, 0xed, 0x54, 0x8f, 0xc2, 0x2d, 0xf4, 0xb1, 0x62, + 0xf3, 0x0b, 0x6f, 0xf3, 0xa7, 0xf7, 0xc3, 0x8a, 0x5a, 0x95, 0xfe, 0x82, + 0x4d, 0x29, 0x61, 0x18, 0x0e, 0x98, 0xb3, 0x02, 0x08, 0xdc, 0x7e, 0xa7, + 0x07, 0x1f, 0x79, 0x22, 0x61, 0xd4, 0x5c, 0x7b, 0xb7, 0xb9, 0x11, 0xf3, + 0xb1, 0x9c, 0x3e, 0xe0, 0x17, 0x1a, 0x32, 0x6c, 0x03, 0x3c, 0xf5, 0xfc, + 0x2b, 0xf7, 0x9d, 0xe7, 0xd5, 0x11, 0x5a, 0xc5, 0x68, 0xe0, 0x47, 0x89, + 0xcb, 0x44, 0xe0, 0x8f, 0x3a, 0x86, 0x27, 0xa1, 0xb1, 0xf3, 0x76, 0x23, + 0x42, 0xb4, 0x9b, 0x76, 0x79, 0xbd, 0x7e, 0xdb, 0xe4, 0x7b, 0xc3, 0xee, + 0x9c, 0x3f, 0x02, 0xdb, 0x15, 0xd5, 0x32, 0x56, 0xa5, 0xea, 0x28, 0x47 +}; +/* K = 69a22d61b152af35c1b43deda88d5ad456d38df75b318b82712b2690a5f2f647 */ +static const uint8_t ac_dsa_vect228_out[] = { +/* R */ + 0x5d, 0xd0, 0xc7, 0xe8, 0xa3, 0x99, 0x3b, 0x9d, 0xe0, 0x67, 0x6a, 0x57, + 0x9c, 0x89, 0x7e, 0xa3, 0x99, 0x43, 0xa4, 0x3d, 0xbe, 0xc5, 0x99, 0x6e, + 0x58, 0xc1, 0x98, 0x5b, 0x54, 0x1d, 0x7c, 0x1a, +/* S */ + 0x67, 0x97, 0x10, 0x01, 0x82, 0x2a, 0x08, 0xa2, 0x14, 0x8a, 0x6b, 0x1a, + 0xdb, 0x50, 0x27, 0x4a, 0x57, 0xda, 0xfe, 0x89, 0x6f, 0xb0, 0x4a, 0x12, + 0xa6, 0xf9, 0x97, 0x07, 0x55, 0x53, 0x06, 0xac +}; +#define ac_dsa_vect229_prime ac_dsa_vect226_prime +#define ac_dsa_vect229_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect229_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect229_ptx[] = { +/* Msg */ + 0xfd, 0xa9, 0x76, 0x5c, 0xc9, 0x1a, 0x9d, 0xb9, 0x22, 0xae, 0xc7, 0xb1, + 0x3f, 0xc3, 0x2a, 0xc4, 0xec, 0x4e, 0x3b, 0x85, 0x34, 0xf9, 0xe9, 0x5a, + 0xf9, 0x6e, 0x8e, 0xbe, 0xab, 0x89, 0xd8, 0x47, 0xdc, 0xd1, 0x50, 0x44, + 0x48, 0x68, 0xcf, 0xaf, 0x42, 0x13, 0xf8, 0xd8, 0xba, 0xa6, 0xb1, 0xd0, + 0x88, 0x62, 0x24, 0xe2, 0xaf, 0xd0, 0xae, 0xb9, 0x3d, 0x59, 0xb8, 0x86, + 0x57, 0x20, 0x88, 0xd0, 0x5b, 0xf7, 0x21, 0xc7, 0xad, 0xfb, 0x54, 0xda, + 0x47, 0xc6, 0xc4, 0x85, 0x12, 0x04, 0xa7, 0xa9, 0x2a, 0x11, 0xde, 0xb3, + 0x9b, 0xa1, 0x7c, 0xf6, 0xc0, 0x7f, 0xb7, 0xce, 0x8b, 0xa3, 0x50, 0xa9, + 0x9d, 0x01, 0x8d, 0x4e, 0xa6, 0x4b, 0xd5, 0x6d, 0x1d, 0x9f, 0x8f, 0x7d, + 0x88, 0x15, 0x7f, 0x19, 0x0f, 0xcb, 0x37, 0x2a, 0xcf, 0x6f, 0x8d, 0x31, + 0xcf, 0x7b, 0x79, 0x5b, 0x36, 0xc1, 0x0f, 0x5e +}; +static const uint8_t ac_dsa_vect229_priv_val[] = { +/* X */ + 0x7f, 0x6c, 0xe3, 0x53, 0x84, 0x19, 0x63, 0xc8, 0xa6, 0xff, 0x34, 0x05, + 0x71, 0x3e, 0x36, 0x1e, 0xf9, 0xf1, 0xe0, 0x76, 0x5e, 0x66, 0x51, 0x95, + 0xe7, 0xc1, 0x47, 0xdd, 0x98, 0x12, 0x0c, 0x4f +}; +static const uint8_t ac_dsa_vect229_pub_val[] = { +/* Y */ + 0x05, 0x39, 0xcc, 0x99, 0x2c, 0xa7, 0x0f, 0x91, 0x35, 0x37, 0xb1, 0x21, + 0x1d, 0xd3, 0x26, 0xd8, 0x5f, 0x75, 0x31, 0xba, 0xa6, 0xbe, 0x05, 0x83, + 0xba, 0x45, 0xb9, 0x57, 0x1b, 0xaa, 0x81, 0xcd, 0x58, 0x28, 0x05, 0x0d, + 0xcd, 0x9a, 0xb7, 0xa2, 0x03, 0xbc, 0x4f, 0xe1, 0xd8, 0x74, 0xf7, 0x6e, + 0xc1, 0xf3, 0x4d, 0x93, 0x55, 0x79, 0xed, 0x21, 0x32, 0x25, 0x57, 0x89, + 0xd7, 0xe6, 0x01, 0x0c, 0xf5, 0x04, 0xb4, 0xc7, 0xf5, 0x86, 0xd4, 0x4a, + 0x71, 0x66, 0x00, 0xac, 0xf8, 0xa0, 0x4a, 0xd3, 0x0c, 0xb7, 0xca, 0x05, + 0x5d, 0x72, 0x23, 0xf9, 0x76, 0x1c, 0xda, 0xeb, 0xfd, 0xf7, 0xef, 0x72, + 0xbd, 0xea, 0x3d, 0xfc, 0xd0, 0x20, 0x06, 0x9a, 0x96, 0x9c, 0x56, 0x01, + 0x60, 0xf0, 0x53, 0x46, 0x76, 0xbe, 0xff, 0x5e, 0xa6, 0x11, 0xfc, 0xbc, + 0x0f, 0xd4, 0x7c, 0x86, 0x7f, 0x31, 0x63, 0xe1, 0x37, 0x1e, 0x1d, 0xe6, + 0x7a, 0x1a, 0x3c, 0x3e, 0x37, 0x16, 0x8b, 0xf0, 0xbe, 0x79, 0xc0, 0x9f, + 0x45, 0xf2, 0xbc, 0x43, 0x51, 0x7a, 0xee, 0xa0, 0x10, 0x0a, 0x2a, 0x25, + 0xd1, 0x48, 0xff, 0x19, 0x90, 0xc0, 0x61, 0x43, 0xfa, 0x25, 0x3d, 0x83, + 0x06, 0xf4, 0x8d, 0x77, 0x36, 0x22, 0x24, 0xbc, 0x3e, 0xfe, 0x93, 0x38, + 0x9e, 0x92, 0x2d, 0xef, 0x0f, 0xd1, 0x1d, 0x19, 0x92, 0xf5, 0x50, 0xed, + 0x82, 0x94, 0xb6, 0x13, 0x65, 0x47, 0xff, 0xd6, 0x12, 0xb0, 0xbc, 0x8e, + 0x4e, 0xe9, 0x0b, 0x31, 0x00, 0xbb, 0x89, 0x92, 0x21, 0x77, 0x14, 0x7b, + 0xe0, 0x08, 0x32, 0x81, 0xbf, 0x66, 0x3f, 0x83, 0x70, 0x41, 0x7f, 0xa7, + 0x90, 0xd4, 0x10, 0x5e, 0xb9, 0x8c, 0xc1, 0x26, 0xf5, 0x00, 0x5b, 0x7c, + 0x08, 0xbc, 0x21, 0x1d, 0xea, 0x28, 0x98, 0xaa, 0x65, 0x3c, 0x3d, 0x2b, + 0x51, 0xfc, 0x67, 0x73, 0x2b, 0xff, 0x56, 0x44, 0xe8, 0x04, 0xaa, 0xe6, + 0x92, 0x00, 0xc4, 0x16, 0x03, 0x5a, 0xa0, 0xba, 0x5a, 0x14, 0xcc, 0x43, + 0x9b, 0x56, 0x9f, 0x46, 0x21, 0x17, 0xb7, 0xdf, 0xcf, 0x3f, 0x2c, 0xc1, + 0x3e, 0x72, 0x3a, 0x93, 0xff, 0x95, 0x33, 0x20, 0x8f, 0x20, 0x24, 0x1d, + 0xaf, 0x36, 0xcd, 0x16, 0x06, 0x6b, 0xe3, 0xdb, 0xa2, 0x01, 0x17, 0xcb, + 0x14, 0x5d, 0x75, 0x6f, 0x5a, 0x6f, 0x79, 0xce, 0x23, 0x56, 0xa0, 0x51, + 0x64, 0x7a, 0xed, 0xd6, 0x45, 0xbf, 0xa6, 0xfa, 0xf8, 0xf8, 0x0a, 0x6f, + 0xdf, 0x3e, 0xec, 0x42, 0xdd, 0xd4, 0x2b, 0xb2, 0xe7, 0xb7, 0x73, 0x82, + 0x96, 0xe2, 0x39, 0x78, 0xc8, 0xbd, 0x63, 0xb8, 0x04, 0x59, 0x53, 0xe0, + 0x6c, 0xef, 0x12, 0x63, 0xbf, 0xe0, 0x3b, 0xe2, 0xf6, 0x1b, 0x16, 0x00, + 0x7d, 0xf1, 0xeb, 0x19, 0x85, 0x67, 0xa7, 0xbc, 0x6b, 0xff, 0x27, 0x4e +}; +/* K = 01cd3cdd3feb4d1a995103b1520fef17f60cd9370ad59b3efe9383a2c0126f00 */ +static const uint8_t ac_dsa_vect229_out[] = { +/* R */ + 0x55, 0xc2, 0xb2, 0x7e, 0x76, 0x9f, 0xac, 0x99, 0xb4, 0x7b, 0xc0, 0xa5, + 0x4f, 0xf1, 0x82, 0x1c, 0x7a, 0x46, 0xbe, 0x60, 0x01, 0xab, 0x66, 0x4f, + 0xb6, 0x8f, 0xb1, 0xba, 0xfc, 0x04, 0x44, 0x6f, +/* S */ + 0x30, 0x59, 0xdb, 0x42, 0xa3, 0x99, 0xc4, 0x28, 0xf3, 0xcf, 0xbb, 0x10, + 0x2d, 0x6c, 0x04, 0x09, 0xb0, 0x6f, 0x20, 0x06, 0x8d, 0x1c, 0xa8, 0xcb, + 0xea, 0x48, 0x58, 0xac, 0x6e, 0x5d, 0xe1, 0xd3 +}; +#define ac_dsa_vect230_prime ac_dsa_vect226_prime +#define ac_dsa_vect230_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect230_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect230_ptx[] = { +/* Msg */ + 0xe4, 0x9a, 0x12, 0xb8, 0xd7, 0x61, 0xef, 0x7a, 0xfb, 0xcb, 0x1c, 0x37, + 0x7e, 0xed, 0xf6, 0x29, 0xd0, 0x8c, 0xc5, 0x09, 0xa8, 0x75, 0x3a, 0x5b, + 0x92, 0xe2, 0x6a, 0x23, 0x97, 0x36, 0x51, 0x56, 0xe7, 0xc0, 0x81, 0xbc, + 0xb4, 0x68, 0x66, 0x95, 0x57, 0x5c, 0x6a, 0x64, 0xf5, 0xd7, 0x7d, 0xfd, + 0x55, 0x0b, 0x04, 0xdf, 0x39, 0x0a, 0xa5, 0x5e, 0x0d, 0x05, 0x1c, 0x75, + 0x9f, 0x19, 0x7a, 0x75, 0x1a, 0x60, 0x41, 0xe2, 0xdd, 0x09, 0x59, 0xf9, + 0x02, 0xf2, 0xe3, 0x59, 0xa1, 0x67, 0xd8, 0x80, 0xc4, 0x9c, 0xfa, 0x81, + 0xe7, 0x19, 0x6f, 0xa1, 0x60, 0x4a, 0xd3, 0x2a, 0x80, 0x17, 0x07, 0x1f, + 0x09, 0x8d, 0x4c, 0xb3, 0x46, 0xb3, 0x92, 0x66, 0xfb, 0xe7, 0x56, 0x59, + 0xdf, 0xc6, 0x60, 0x7b, 0xf0, 0xd8, 0x29, 0x64, 0x07, 0x82, 0xcf, 0x3e, + 0x12, 0xe3, 0x83, 0x76, 0xc5, 0xa9, 0x92, 0x82 +}; +static const uint8_t ac_dsa_vect230_priv_val[] = { +/* X */ + 0x28, 0xd9, 0xbc, 0x1d, 0x9a, 0xab, 0xa8, 0x82, 0x42, 0x7e, 0xe2, 0x6c, + 0x26, 0x2b, 0xd4, 0x00, 0x3a, 0xae, 0xba, 0x42, 0x2b, 0xf0, 0x53, 0xb0, + 0xdd, 0xe1, 0x4b, 0xb6, 0xd6, 0xd7, 0x4b, 0xdc +}; +static const uint8_t ac_dsa_vect230_pub_val[] = { +/* Y */ + 0xee, 0x7f, 0xff, 0x18, 0x82, 0x2f, 0xf4, 0x54, 0xa2, 0x07, 0xf9, 0xdb, + 0x54, 0x2d, 0x24, 0x29, 0x8b, 0xb5, 0xed, 0xb1, 0x1d, 0x80, 0xdd, 0xc6, + 0xdd, 0xb9, 0xbf, 0xae, 0x0c, 0x95, 0x2d, 0x4f, 0xe8, 0xd9, 0xdb, 0x0f, + 0x1a, 0x86, 0xe8, 0xa0, 0xf2, 0x19, 0x3a, 0xf7, 0xca, 0xae, 0xe7, 0x26, + 0x4d, 0x74, 0x10, 0x6d, 0xe5, 0xaf, 0x0a, 0x6c, 0x14, 0xf7, 0x10, 0xbb, + 0x86, 0x3e, 0xb7, 0xdc, 0x16, 0x7a, 0x1e, 0x43, 0x78, 0xb6, 0xcd, 0xb7, + 0xab, 0x68, 0x41, 0xc6, 0x64, 0xe9, 0x82, 0x45, 0x29, 0x11, 0x97, 0x73, + 0x57, 0x8e, 0xf5, 0x5b, 0x7c, 0x35, 0xed, 0x22, 0x1e, 0xf0, 0x70, 0xdd, + 0x46, 0x90, 0xb4, 0xc1, 0x2f, 0x27, 0x67, 0x3e, 0x5d, 0x1f, 0xe9, 0x64, + 0xff, 0xe2, 0x9d, 0xa5, 0x7e, 0x2d, 0x1a, 0xcd, 0x21, 0xef, 0x13, 0xe0, + 0x66, 0x9f, 0xa9, 0x76, 0x68, 0xbb, 0x19, 0x9b, 0x56, 0xa3, 0xa5, 0x3e, + 0x10, 0x46, 0x91, 0x33, 0x02, 0x20, 0x81, 0xcd, 0xf6, 0x26, 0x48, 0x10, + 0x0d, 0xca, 0x26, 0x7c, 0x4f, 0x6a, 0x3c, 0xa3, 0xa7, 0x5b, 0x57, 0x3b, + 0xb1, 0xb3, 0x9c, 0x8a, 0x4e, 0x1f, 0xcf, 0x81, 0x26, 0x9e, 0x9e, 0x1b, + 0x10, 0xc6, 0x3f, 0x5b, 0xa4, 0xfe, 0x75, 0xcf, 0x71, 0x39, 0xd0, 0x38, + 0xd0, 0x2f, 0x5f, 0x53, 0x4a, 0xa0, 0x81, 0xfc, 0xe7, 0x32, 0xcd, 0x50, + 0x51, 0x60, 0x9b, 0xc0, 0x6f, 0x18, 0x87, 0x4d, 0xd0, 0x11, 0x21, 0xd3, + 0xc1, 0x79, 0xf0, 0xc3, 0xf0, 0x39, 0x9c, 0x18, 0x5e, 0xeb, 0xdc, 0x34, + 0x63, 0x5b, 0x31, 0x39, 0xf1, 0xca, 0x50, 0xfb, 0xff, 0xb3, 0xb0, 0xad, + 0x12, 0xe4, 0x81, 0xc1, 0xa6, 0x46, 0x82, 0x14, 0x37, 0x93, 0xf0, 0x72, + 0xc7, 0xdb, 0x8b, 0x5b, 0x9e, 0xef, 0x41, 0xcc, 0xdd, 0x66, 0xb9, 0x04, + 0x13, 0x9d, 0x64, 0x44, 0x42, 0xa9, 0x2f, 0x62, 0x55, 0xed, 0xb9, 0xbc, + 0x12, 0x34, 0xe2, 0x7d, 0x07, 0xa6, 0xba, 0x32, 0xb1, 0xf1, 0x4c, 0xdf, + 0x98, 0xa2, 0x2c, 0x6a, 0x12, 0x30, 0x0d, 0xff, 0x50, 0xac, 0x1b, 0x65, + 0x56, 0x8b, 0x6e, 0x91, 0x55, 0x41, 0xbb, 0x38, 0x6e, 0xc7, 0x25, 0xda, + 0x44, 0x44, 0x67, 0xca, 0x25, 0xe8, 0x14, 0x48, 0xcb, 0x78, 0x37, 0x51, + 0x46, 0xad, 0x20, 0x78, 0xa8, 0x30, 0xe7, 0xd9, 0x05, 0xde, 0x9a, 0xd7, + 0xd8, 0x95, 0x59, 0xc9, 0xd4, 0x30, 0xcf, 0x5f, 0x41, 0x9c, 0xe9, 0x45, + 0x70, 0x4a, 0x42, 0x6a, 0xb2, 0x64, 0x01, 0x6e, 0xd8, 0x7c, 0x90, 0xd9, + 0x7f, 0x51, 0xa7, 0xd6, 0xe1, 0xee, 0x2f, 0x51, 0xbb, 0xb3, 0xa8, 0xde, + 0x81, 0x39, 0x16, 0x97, 0xb0, 0xe4, 0x22, 0xdf, 0x9e, 0x5d, 0x35, 0x51, + 0xe9, 0x33, 0x74, 0xe5, 0xf3, 0x80, 0x16, 0xb2, 0x96, 0xd5, 0x3b, 0xc2 +}; +/* K = 0650ebc3e21bf1d90ffb3ef5a707013dfce78fbd2c21a0da9c8106d1fa98a46f */ +static const uint8_t ac_dsa_vect230_out[] = { +/* R */ + 0x21, 0xd3, 0x4d, 0xf6, 0x05, 0x23, 0x79, 0x75, 0xdb, 0x31, 0xb8, 0x64, + 0xf9, 0x8c, 0x9a, 0xb6, 0xe4, 0x65, 0xdb, 0xf0, 0xb3, 0xfc, 0x58, 0x68, + 0xd6, 0x7c, 0xd6, 0xcb, 0x3a, 0x13, 0x96, 0x3b, +/* S */ + 0x70, 0xc4, 0x88, 0x07, 0xd6, 0x2d, 0x1f, 0xe7, 0x4d, 0x58, 0x95, 0x93, + 0x47, 0xab, 0x12, 0xc9, 0x7b, 0x50, 0x0d, 0x20, 0x60, 0x7e, 0xd2, 0xa9, + 0x5d, 0x8a, 0x38, 0x8f, 0xee, 0x26, 0x58, 0x12 +}; +#define ac_dsa_vect231_prime ac_dsa_vect226_prime +#define ac_dsa_vect231_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect231_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect231_ptx[] = { +/* Msg */ + 0x28, 0xf7, 0xa0, 0x67, 0xa0, 0xea, 0x7f, 0x0a, 0x4d, 0x79, 0x7c, 0xea, + 0x39, 0x39, 0xf6, 0x6b, 0x28, 0x1e, 0xd1, 0x9c, 0xc9, 0x8b, 0x85, 0x63, + 0xef, 0x37, 0x57, 0x98, 0xb4, 0x06, 0x14, 0xf4, 0xdd, 0x85, 0xac, 0x2f, + 0xcf, 0xcc, 0xbc, 0x5e, 0xbf, 0x0a, 0xc9, 0x32, 0x28, 0xc0, 0xb7, 0x29, + 0x37, 0xa4, 0x81, 0xca, 0x4f, 0x9d, 0xf7, 0xa7, 0xe5, 0xd2, 0xe5, 0xda, + 0x9a, 0xf0, 0x48, 0x74, 0xdc, 0xec, 0x35, 0x03, 0x5f, 0x6a, 0x7d, 0xb4, + 0x93, 0x79, 0x3a, 0xa2, 0x36, 0x1f, 0xb6, 0x6e, 0xf2, 0xee, 0xdb, 0x75, + 0x74, 0xd0, 0x4e, 0x21, 0x47, 0xc3, 0x57, 0x29, 0x8a, 0x2a, 0xdf, 0x99, + 0xac, 0xa1, 0xee, 0xbe, 0x00, 0xce, 0xfa, 0x44, 0xb3, 0x91, 0x57, 0xeb, + 0x1e, 0x94, 0xaa, 0x8a, 0xa9, 0x8d, 0x54, 0x51, 0x51, 0xfb, 0xb4, 0xde, + 0x67, 0x07, 0x0b, 0x39, 0x04, 0xcc, 0xe9, 0x30 +}; +static const uint8_t ac_dsa_vect231_priv_val[] = { +/* X */ + 0x0c, 0x50, 0x88, 0xf5, 0xd3, 0x37, 0x80, 0x27, 0x70, 0xe6, 0xf9, 0x83, + 0x49, 0xd5, 0x34, 0x61, 0xf1, 0x31, 0x61, 0x02, 0x0a, 0xb9, 0xa2, 0x41, + 0xef, 0xed, 0x4f, 0xae, 0xd2, 0xe5, 0x69, 0xee +}; +static const uint8_t ac_dsa_vect231_pub_val[] = { +/* Y */ + 0xcd, 0xb9, 0x92, 0x2d, 0x69, 0xe9, 0x9c, 0x7f, 0x34, 0xa9, 0x21, 0x0e, + 0x2a, 0xfc, 0x5b, 0xe0, 0x11, 0x5d, 0xa4, 0xaa, 0xf6, 0x82, 0xd9, 0xea, + 0x37, 0x78, 0x8e, 0x0b, 0x6c, 0xaa, 0x6f, 0xde, 0x13, 0xc8, 0x8e, 0x51, + 0xf5, 0x58, 0x82, 0x06, 0x68, 0xb5, 0x9d, 0x14, 0xc0, 0x6d, 0x2c, 0xbe, + 0x65, 0x49, 0xd3, 0xf0, 0x6d, 0x10, 0xdb, 0xee, 0xe4, 0x6f, 0x59, 0x15, + 0x4c, 0xd4, 0x67, 0xae, 0x19, 0xe1, 0x6b, 0xe2, 0x5e, 0x6f, 0x6c, 0xd2, + 0x38, 0xcc, 0xd1, 0x94, 0x7f, 0xc5, 0x81, 0x56, 0x2d, 0x30, 0xca, 0x32, + 0x9b, 0xb3, 0x27, 0x25, 0x8c, 0xa4, 0xae, 0xb9, 0x01, 0xf8, 0x14, 0x41, + 0x40, 0x58, 0xb6, 0xf1, 0x69, 0xa4, 0x5f, 0xf5, 0x5e, 0x40, 0x23, 0x2d, + 0x78, 0x70, 0x49, 0x9a, 0xe7, 0x8c, 0x05, 0x13, 0x77, 0x71, 0x40, 0x75, + 0x2d, 0x55, 0xf0, 0xa4, 0x70, 0x76, 0x1b, 0xdc, 0xff, 0x5a, 0x66, 0x09, + 0xcc, 0xa2, 0xd1, 0x80, 0x9f, 0x18, 0x4b, 0x29, 0x87, 0x18, 0x07, 0x1d, + 0x21, 0x6a, 0x14, 0xad, 0x01, 0xf5, 0x6c, 0xcc, 0xce, 0xd2, 0x39, 0x69, + 0x60, 0x7b, 0x62, 0xd4, 0xd1, 0x40, 0xc9, 0xef, 0x28, 0x50, 0x76, 0x74, + 0xf5, 0x9f, 0xec, 0xc7, 0xe7, 0xce, 0x8a, 0xd2, 0x63, 0x6a, 0x5c, 0x53, + 0xf0, 0x70, 0xad, 0x31, 0x7c, 0x8c, 0xd0, 0x23, 0x1f, 0x50, 0x0a, 0x79, + 0x0e, 0xf6, 0x9a, 0xc7, 0x86, 0x00, 0x0f, 0xaf, 0x68, 0xe7, 0xb7, 0x85, + 0x4d, 0x6e, 0xb2, 0x64, 0x99, 0xa9, 0xd5, 0x24, 0xcb, 0xf8, 0xf3, 0x73, + 0xca, 0x41, 0xdd, 0x6a, 0x2f, 0xa5, 0x19, 0x8e, 0xba, 0x2a, 0x8e, 0x22, + 0x8f, 0x5a, 0xb2, 0x9b, 0xe9, 0xf6, 0xd4, 0x50, 0xf7, 0xf5, 0xa1, 0x49, + 0xae, 0xb2, 0x0d, 0x8a, 0x27, 0x79, 0x71, 0xfa, 0x6e, 0x64, 0xa0, 0xde, + 0x36, 0xc8, 0x75, 0x0a, 0xfc, 0x38, 0x19, 0x61, 0x75, 0x69, 0x75, 0x62, + 0x1f, 0x28, 0x7a, 0x39, 0x50, 0xf8, 0x84, 0x02, 0xc5, 0x08, 0x1f, 0xe0, + 0xc5, 0x4f, 0x44, 0xf9, 0xfa, 0x7c, 0x50, 0xdf, 0x90, 0x6b, 0x26, 0x40, + 0x98, 0x85, 0x36, 0x46, 0xb3, 0xd0, 0x5a, 0x4f, 0x04, 0xc6, 0xf1, 0xbb, + 0xc6, 0xc4, 0x40, 0xf7, 0xe7, 0x35, 0x8d, 0x3a, 0x72, 0xb2, 0x9f, 0x76, + 0x43, 0xf4, 0x40, 0x6b, 0x7d, 0xb1, 0x73, 0x69, 0x0d, 0x40, 0xaa, 0x29, + 0x38, 0xea, 0xf0, 0x18, 0x74, 0xd2, 0xba, 0x80, 0x94, 0xcc, 0x5b, 0xe1, + 0x14, 0x5b, 0x2b, 0x2e, 0xe9, 0xe7, 0xcf, 0x15, 0xbf, 0x39, 0x8e, 0x50, + 0x83, 0x2d, 0x95, 0x01, 0x74, 0x30, 0xb1, 0x86, 0x99, 0x38, 0x73, 0x2c, + 0xdd, 0x1d, 0xf5, 0x93, 0xf5, 0xdb, 0x2b, 0x2b, 0xd7, 0x13, 0x08, 0xd8, + 0xc2, 0x53, 0xd2, 0x54, 0xef, 0x39, 0xb4, 0x75, 0xe2, 0x49, 0xd8, 0x90 +}; +/* K = 2be962ca1f82b879255e20d6971e633ba68582a5137bc55058fa42b48ddf0566 */ +static const uint8_t ac_dsa_vect231_out[] = { +/* R */ + 0x12, 0xde, 0x25, 0x2d, 0xa2, 0x59, 0x3c, 0x59, 0x69, 0xa6, 0x49, 0x6a, + 0xe8, 0x08, 0xd8, 0x51, 0xca, 0xd1, 0xde, 0xd2, 0x95, 0x9e, 0xa8, 0x90, + 0x57, 0xa9, 0x2e, 0x5e, 0xc9, 0x1c, 0x5f, 0x95, +/* S */ + 0x16, 0x53, 0x38, 0x07, 0x5e, 0x6a, 0x4f, 0xea, 0x0b, 0x23, 0x8f, 0x9f, + 0xac, 0x90, 0x4b, 0x7b, 0x33, 0xdb, 0xee, 0x5a, 0x55, 0x26, 0x46, 0xdf, + 0xbe, 0xd8, 0x27, 0xf6, 0xd2, 0x8d, 0x64, 0x92 +}; +#define ac_dsa_vect232_prime ac_dsa_vect226_prime +#define ac_dsa_vect232_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect232_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect232_ptx[] = { +/* Msg */ + 0x0e, 0x15, 0x6b, 0x0b, 0xd8, 0x45, 0x95, 0x15, 0x5e, 0xf4, 0xfc, 0x21, + 0x3d, 0xfc, 0x7e, 0x46, 0xbf, 0x27, 0xa8, 0x9c, 0x27, 0x57, 0x23, 0xe0, + 0x98, 0x40, 0x76, 0xb0, 0x27, 0xc4, 0x9c, 0xb2, 0xee, 0xe6, 0xac, 0x86, + 0x6d, 0x75, 0x33, 0x35, 0x81, 0xcc, 0xa6, 0xf8, 0x97, 0xe1, 0x14, 0x18, + 0xfb, 0x37, 0xba, 0x5c, 0xab, 0x13, 0x91, 0xcd, 0x23, 0x7e, 0x2c, 0x6a, + 0xb3, 0xf1, 0x1a, 0x05, 0x5d, 0x3b, 0xd0, 0x3f, 0x42, 0x5b, 0xaa, 0xab, + 0xe5, 0xa6, 0xa3, 0x4e, 0xba, 0x4b, 0x11, 0x8a, 0xf7, 0x3e, 0xdd, 0x61, + 0x07, 0x87, 0xcb, 0x8e, 0xaf, 0x47, 0x6b, 0xd2, 0x17, 0x04, 0x82, 0x08, + 0xea, 0x4c, 0x1d, 0x05, 0x91, 0x37, 0x29, 0x47, 0xa1, 0xc0, 0xef, 0x94, + 0x69, 0x65, 0x68, 0x98, 0x34, 0x24, 0xfd, 0x1d, 0x80, 0x2f, 0xc9, 0x11, + 0xe7, 0xbf, 0x71, 0x22, 0x4a, 0xfd, 0xbd, 0xd9 +}; +static const uint8_t ac_dsa_vect232_priv_val[] = { +/* X */ + 0x2c, 0x4d, 0x97, 0x2b, 0xb3, 0x53, 0x98, 0x76, 0xb8, 0xf3, 0x2c, 0xc6, + 0x45, 0xcf, 0xf0, 0xd4, 0xbe, 0x87, 0x71, 0x75, 0xf3, 0x1a, 0x02, 0x8b, + 0x9b, 0xfe, 0x97, 0x3f, 0x06, 0x51, 0x78, 0x9a +}; +static const uint8_t ac_dsa_vect232_pub_val[] = { +/* Y */ + 0xd0, 0x97, 0x36, 0x41, 0xd5, 0x6d, 0x8b, 0xaa, 0xa2, 0xc2, 0xd4, 0x30, + 0x50, 0x1d, 0xff, 0x44, 0xea, 0xf9, 0xa3, 0x65, 0x74, 0x78, 0x79, 0x91, + 0x34, 0xb0, 0xf3, 0x35, 0xae, 0x94, 0xff, 0x27, 0x91, 0xdf, 0xd4, 0x94, + 0x40, 0x13, 0x32, 0x48, 0x6b, 0xa6, 0x37, 0x68, 0x3e, 0x70, 0x4b, 0xd9, + 0x85, 0xf5, 0x26, 0x91, 0x9e, 0x66, 0x1a, 0x22, 0x80, 0xd9, 0x9b, 0xd4, + 0x82, 0x62, 0xb6, 0xc9, 0x30, 0x5e, 0x0c, 0x8f, 0xd8, 0x79, 0xcd, 0x0a, + 0x83, 0x61, 0x28, 0xd8, 0x8e, 0xdd, 0xae, 0x51, 0xfc, 0xfb, 0x51, 0xf7, + 0x44, 0xb2, 0x3d, 0x2d, 0x2d, 0x27, 0xa2, 0xcc, 0x1e, 0xa5, 0xa9, 0xd5, + 0xe0, 0xa7, 0xfa, 0xf4, 0x22, 0x7a, 0x2a, 0xdb, 0xfb, 0x7e, 0xd4, 0x5d, + 0x6a, 0xa9, 0xc3, 0x37, 0x98, 0xab, 0xf0, 0x7b, 0xc6, 0x9e, 0xfc, 0x5f, + 0xdd, 0xe5, 0xdc, 0x5c, 0x78, 0x01, 0x96, 0x25, 0x70, 0x93, 0xec, 0xa7, + 0x54, 0x68, 0xb1, 0x61, 0xcb, 0xa4, 0x4b, 0xcd, 0x14, 0x2b, 0x21, 0xfa, + 0xe9, 0xed, 0xc6, 0xab, 0x32, 0x78, 0x30, 0xc2, 0x8e, 0x1b, 0x3d, 0x2d, + 0x7c, 0x81, 0x2d, 0x8a, 0xec, 0x3a, 0x19, 0x52, 0x62, 0x7a, 0x04, 0x01, + 0x10, 0x87, 0x2e, 0x14, 0x8e, 0x15, 0xde, 0x5c, 0x7b, 0x4c, 0xa2, 0x4f, + 0x08, 0x63, 0x36, 0xda, 0xec, 0xbb, 0xf9, 0x81, 0x6c, 0xdb, 0x9d, 0xc7, + 0x30, 0xdb, 0x8a, 0x66, 0xa1, 0x92, 0x9a, 0xbe, 0xcd, 0x4b, 0x09, 0xa0, + 0x39, 0xa1, 0x9b, 0xff, 0xa4, 0x5f, 0xfc, 0x85, 0xdd, 0xf0, 0xbe, 0x32, + 0x77, 0xbf, 0x07, 0x5b, 0xbb, 0x46, 0xf0, 0x7b, 0xf0, 0xda, 0xea, 0x24, + 0x89, 0x7e, 0x07, 0x04, 0x4b, 0x5e, 0xe3, 0x7f, 0x9f, 0x44, 0xfe, 0xe7, + 0x57, 0x18, 0x81, 0x70, 0xda, 0x22, 0x92, 0x4f, 0xa1, 0x5e, 0xd9, 0xc0, + 0x7f, 0x11, 0x3c, 0xdf, 0x37, 0xa8, 0xc4, 0x86, 0x48, 0xe5, 0x86, 0xfb, + 0x55, 0xa0, 0xc3, 0x5f, 0x3b, 0x63, 0xa6, 0x96, 0x67, 0x24, 0x41, 0x93, + 0xc7, 0x0d, 0x94, 0xbb, 0xe3, 0x6d, 0x04, 0x3b, 0x25, 0xa0, 0x41, 0xfb, + 0xa9, 0x2a, 0x20, 0x42, 0xe2, 0xee, 0xf7, 0x67, 0xe7, 0xcd, 0x18, 0xdd, + 0x1c, 0x1b, 0x5c, 0xa4, 0x87, 0x8f, 0xe7, 0x74, 0xc8, 0x33, 0xcb, 0x5c, + 0x5a, 0xff, 0x9f, 0x67, 0xbf, 0xd6, 0xcf, 0xbf, 0x2d, 0xfc, 0x63, 0xb8, + 0x84, 0x2a, 0xd2, 0xd4, 0x9c, 0xeb, 0xca, 0xff, 0x4c, 0x39, 0x27, 0xf3, + 0x19, 0x9c, 0x10, 0x6d, 0x0c, 0x14, 0x9a, 0x9b, 0x1b, 0x49, 0xbe, 0xf1, + 0xd6, 0xf8, 0x14, 0x3d, 0x93, 0xd2, 0x5d, 0xf9, 0xdb, 0x1b, 0x5b, 0x37, + 0xd5, 0x22, 0xe7, 0x23, 0xff, 0x64, 0xd9, 0xee, 0x52, 0xe4, 0x76, 0x20, + 0x67, 0x12, 0xa3, 0x82, 0x46, 0xdd, 0x92, 0x62, 0x71, 0xf5, 0x59, 0x0e +}; +/* K = 5e12de89504bc84836c14fc47628a517e898fa46769eba2b36e7c69e580a6473 */ +static const uint8_t ac_dsa_vect232_out[] = { +/* R */ + 0x5e, 0xf5, 0xd7, 0x8c, 0x42, 0x1a, 0xe5, 0xa6, 0x39, 0x78, 0xbc, 0xbf, + 0x7d, 0x20, 0x37, 0xb5, 0x02, 0x2b, 0xc4, 0x7b, 0xe7, 0xb2, 0x93, 0x80, + 0x65, 0x80, 0xad, 0x5b, 0x4d, 0xe2, 0x7a, 0x4e, +/* S */ + 0x67, 0xcc, 0xb2, 0x83, 0x3c, 0x1d, 0x32, 0xc6, 0x8e, 0x91, 0xae, 0x38, + 0x90, 0xb4, 0xc9, 0xa6, 0xe5, 0x22, 0x9b, 0x22, 0xa5, 0x79, 0x91, 0x68, + 0xc0, 0x04, 0x6e, 0xad, 0x92, 0x57, 0x3c, 0x85 +}; +#define ac_dsa_vect233_prime ac_dsa_vect226_prime +#define ac_dsa_vect233_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect233_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect233_ptx[] = { +/* Msg */ + 0x84, 0x9c, 0x53, 0x37, 0xd8, 0x8b, 0x3b, 0x24, 0x7d, 0xf5, 0x73, 0xeb, + 0x0d, 0x66, 0x55, 0x48, 0xb6, 0x42, 0x37, 0x63, 0xd5, 0x57, 0x1f, 0x8a, + 0xcb, 0x5e, 0x61, 0xe3, 0x16, 0xd7, 0xcd, 0xc2, 0x08, 0xcd, 0xa5, 0xb3, + 0x9a, 0x19, 0x44, 0xa7, 0x17, 0x58, 0x7e, 0x58, 0xe2, 0x1b, 0x86, 0xed, + 0x22, 0x2b, 0x8e, 0xe2, 0x65, 0x10, 0x5a, 0x32, 0xba, 0xff, 0x36, 0x92, + 0xdc, 0xf7, 0xb8, 0x71, 0x3d, 0x0b, 0x53, 0x92, 0x62, 0xa5, 0xbd, 0x9a, + 0x95, 0x4c, 0xb7, 0x14, 0x3e, 0xe6, 0x6f, 0x87, 0x64, 0xdb, 0x62, 0x36, + 0x13, 0x6c, 0xb1, 0xcb, 0x3b, 0x34, 0xa8, 0x7c, 0xbd, 0x3f, 0xee, 0x3b, + 0x11, 0x28, 0x8b, 0xc9, 0x4a, 0xc9, 0x91, 0x79, 0xc6, 0x81, 0xa4, 0x69, + 0xd6, 0x2d, 0x9b, 0xcd, 0x91, 0xd4, 0x03, 0x32, 0xa6, 0x50, 0xa5, 0xbc, + 0xe3, 0x3b, 0x60, 0x26, 0x88, 0x4e, 0xf9, 0x4a +}; +static const uint8_t ac_dsa_vect233_priv_val[] = { +/* X */ + 0x68, 0x08, 0x78, 0xe3, 0x82, 0xb7, 0x13, 0xd4, 0xdc, 0x9b, 0xed, 0x8b, + 0x7e, 0xae, 0x88, 0x0f, 0x10, 0x54, 0xf5, 0x8e, 0x70, 0xcd, 0xa2, 0x71, + 0x75, 0x77, 0xfe, 0xd3, 0xc6, 0x33, 0x93, 0xdc +}; +static const uint8_t ac_dsa_vect233_pub_val[] = { +/* Y */ + 0x1e, 0x8d, 0x4d, 0x6f, 0xef, 0x99, 0x05, 0xd6, 0x39, 0xe2, 0x56, 0x4d, + 0x87, 0xdc, 0xbe, 0x0d, 0x8f, 0x99, 0xbd, 0xe3, 0x80, 0x82, 0xff, 0x09, + 0x1a, 0x97, 0x7f, 0x2a, 0xff, 0xca, 0xb8, 0x65, 0x05, 0xae, 0xff, 0xe6, + 0xef, 0x1d, 0xdb, 0xac, 0xf1, 0x5d, 0x91, 0x65, 0xb0, 0x06, 0xac, 0x05, + 0x17, 0x43, 0x4a, 0xaa, 0x65, 0xdb, 0x21, 0x04, 0x52, 0xfb, 0x2f, 0xf4, + 0xc9, 0x90, 0xb8, 0x7f, 0x25, 0xfe, 0xe7, 0xad, 0x5b, 0x26, 0xad, 0x87, + 0x74, 0x95, 0x75, 0x19, 0x00, 0x89, 0xa5, 0x6c, 0xdb, 0xce, 0xee, 0x67, + 0x82, 0xce, 0xaa, 0xf5, 0x69, 0x81, 0x4b, 0xb9, 0xe6, 0x58, 0xff, 0x50, + 0xae, 0xbf, 0x6f, 0x3c, 0x97, 0x91, 0x89, 0x3e, 0x5d, 0x6a, 0xda, 0x5f, + 0xdf, 0x8c, 0x47, 0x20, 0xfa, 0xfa, 0x18, 0x4c, 0xc8, 0x4a, 0x84, 0xf5, + 0xfc, 0xa7, 0x9d, 0x89, 0x96, 0x36, 0xe0, 0x07, 0xbd, 0x0e, 0x1a, 0x89, + 0xda, 0x09, 0x4a, 0x37, 0x8e, 0xdb, 0x6d, 0x72, 0x24, 0x0c, 0xc2, 0xd1, + 0xd7, 0x09, 0x8b, 0x53, 0xba, 0x48, 0x37, 0xa5, 0xd0, 0xd7, 0xd0, 0x20, + 0x19, 0xb9, 0x52, 0x71, 0x2e, 0x4f, 0x14, 0x20, 0xe5, 0x8a, 0xf2, 0x3d, + 0x13, 0x77, 0xcd, 0x6d, 0x5f, 0x39, 0x89, 0xb3, 0xd6, 0x0b, 0x5f, 0xc5, + 0x72, 0x04, 0x3b, 0x96, 0xc4, 0xf7, 0xbe, 0xb7, 0x13, 0x7c, 0x08, 0x94, + 0xfa, 0x99, 0xd7, 0x27, 0xa5, 0xa8, 0x8a, 0x5d, 0x5d, 0xcb, 0xf2, 0xda, + 0x7b, 0x0b, 0x2d, 0x83, 0xdb, 0x88, 0x74, 0x7f, 0xb0, 0xcc, 0xaa, 0x89, + 0x91, 0xd2, 0x4f, 0xcc, 0xde, 0xf4, 0x21, 0x11, 0xff, 0x40, 0x2e, 0xd0, + 0xd9, 0xbd, 0xb8, 0xa4, 0xad, 0x13, 0xf8, 0xfc, 0xff, 0x6a, 0x1d, 0xf5, + 0x6c, 0x82, 0xa5, 0xf8, 0x8f, 0x57, 0x5f, 0x49, 0xa0, 0x62, 0x75, 0xa9, + 0xe6, 0x60, 0x67, 0xf1, 0x5d, 0xae, 0xc4, 0x02, 0xed, 0x87, 0x70, 0x48, + 0x49, 0x99, 0x09, 0xb9, 0xe7, 0x6e, 0x5f, 0xde, 0x52, 0xfe, 0xac, 0x94, + 0x4e, 0x1d, 0xe7, 0x89, 0x4c, 0xf1, 0x3c, 0x51, 0x52, 0x99, 0xac, 0xc6, + 0x44, 0x2d, 0x90, 0xf0, 0x27, 0x31, 0x7b, 0x07, 0x13, 0x80, 0x5a, 0x95, + 0x12, 0x25, 0x6b, 0xca, 0xa7, 0x96, 0x3b, 0x94, 0x29, 0xa5, 0x10, 0xc5, + 0x86, 0x97, 0x92, 0xc1, 0xe2, 0x90, 0x82, 0x92, 0x1d, 0x0e, 0x7d, 0x0c, + 0xef, 0xff, 0xc3, 0x4d, 0x30, 0x76, 0x2f, 0xb8, 0x3e, 0x2a, 0xbb, 0x78, + 0x21, 0xfa, 0xb4, 0xca, 0x89, 0xd0, 0x8b, 0x49, 0x7f, 0x75, 0xe3, 0x14, + 0x9a, 0x5c, 0xd3, 0xd2, 0x3b, 0x29, 0xbc, 0x52, 0x13, 0x7d, 0x8b, 0xe9, + 0xc4, 0xa9, 0x5c, 0x63, 0x76, 0xf6, 0x2e, 0xd6, 0x4f, 0xdc, 0x15, 0x9b, + 0x1b, 0xb6, 0xc8, 0x42, 0xbd, 0x07, 0xf8, 0xcf, 0x03, 0xf7, 0xf2, 0xeb +}; +/* K = 48ea48cad85abe488665eb75359217b63387427093318bdfb5d7d8092d342caa */ +static const uint8_t ac_dsa_vect233_out[] = { +/* R */ + 0x11, 0xb1, 0x63, 0x51, 0xf8, 0xf7, 0x20, 0x31, 0xba, 0x2a, 0x77, 0x20, + 0x00, 0xac, 0x87, 0x26, 0xa4, 0x79, 0xe1, 0xbe, 0x45, 0x23, 0xa9, 0xee, + 0xfa, 0xbe, 0x23, 0x94, 0x7a, 0x1d, 0xf0, 0xd9, +/* S */ + 0x26, 0x60, 0xfb, 0xb4, 0x4e, 0x29, 0xe7, 0x68, 0x7c, 0x10, 0xe2, 0x9d, + 0xe9, 0x6f, 0xa1, 0xab, 0x03, 0xc0, 0x87, 0xcc, 0xce, 0x08, 0x6c, 0xdd, + 0xab, 0x48, 0xec, 0x63, 0x77, 0x41, 0x41, 0xc1 +}; +#define ac_dsa_vect234_prime ac_dsa_vect226_prime +#define ac_dsa_vect234_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect234_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect234_ptx[] = { +/* Msg */ + 0x4c, 0x37, 0xa4, 0xc8, 0xb4, 0x11, 0x09, 0x24, 0x0c, 0x4f, 0x53, 0xd8, + 0x72, 0x77, 0xd3, 0xc7, 0x90, 0xb2, 0xf0, 0x71, 0x10, 0x5d, 0x15, 0xaa, + 0x10, 0xbd, 0x0f, 0x77, 0x09, 0xda, 0x27, 0x4c, 0xce, 0xa1, 0x96, 0x1e, + 0x0b, 0x99, 0x63, 0x5b, 0x31, 0xac, 0xd2, 0xc8, 0x05, 0x30, 0xd2, 0xb4, + 0x03, 0xd7, 0x11, 0x0a, 0xd7, 0xcd, 0x0e, 0x35, 0x72, 0x51, 0x89, 0x09, + 0xc1, 0x36, 0xe7, 0x3e, 0x57, 0xd3, 0x8c, 0x1c, 0x74, 0x43, 0xe5, 0x8a, + 0x25, 0x7f, 0x07, 0x36, 0xb9, 0xf6, 0xf5, 0x1d, 0xa8, 0xfd, 0x1a, 0xe9, + 0x21, 0x3e, 0x81, 0x93, 0x00, 0x3d, 0x69, 0x58, 0x33, 0x81, 0xf0, 0x20, + 0xcc, 0xe7, 0xfc, 0x59, 0xba, 0x1b, 0x1e, 0xd5, 0x54, 0x1d, 0xbe, 0xf6, + 0xb5, 0x99, 0x25, 0x75, 0x0d, 0x50, 0xb6, 0x51, 0x5a, 0x97, 0x7a, 0xa4, + 0x32, 0x5d, 0x5f, 0xad, 0xe4, 0x2f, 0x82, 0x87 +}; +static const uint8_t ac_dsa_vect234_priv_val[] = { +/* X */ + 0x6b, 0xc0, 0x51, 0xfb, 0xa9, 0x3b, 0x92, 0x85, 0x9a, 0x8a, 0x06, 0xeb, + 0x36, 0x1f, 0x34, 0x8f, 0x5e, 0x50, 0xd0, 0x91, 0xc5, 0x5b, 0x99, 0x84, + 0x76, 0xec, 0xaa, 0x17, 0x77, 0xf2, 0x6f, 0xb8 +}; +static const uint8_t ac_dsa_vect234_pub_val[] = { +/* Y */ + 0x88, 0xa4, 0xdd, 0x59, 0x3b, 0x64, 0xa4, 0xeb, 0xcb, 0x27, 0xff, 0xea, + 0x3d, 0xe9, 0xa7, 0xed, 0x78, 0x01, 0xf9, 0x67, 0x2b, 0x5c, 0x8d, 0xc2, + 0x7b, 0x38, 0x3d, 0x6c, 0xba, 0x58, 0xb4, 0xf0, 0x01, 0x81, 0x63, 0x4d, + 0x05, 0xeb, 0x49, 0x02, 0x82, 0xce, 0x4e, 0x57, 0xf0, 0x94, 0x03, 0x73, + 0xd3, 0xa7, 0xbd, 0x7e, 0x9c, 0xca, 0xa9, 0xbb, 0x29, 0x65, 0x32, 0x2a, + 0xb5, 0xfb, 0x21, 0xb4, 0x32, 0x7b, 0x47, 0xef, 0x4e, 0x2b, 0x42, 0x42, + 0x4c, 0x13, 0x83, 0xbb, 0xd8, 0x55, 0x8b, 0x50, 0x6a, 0x7b, 0xf5, 0x53, + 0x7b, 0x04, 0x9f, 0xff, 0x35, 0xc5, 0x58, 0xbc, 0xc7, 0x39, 0xb7, 0x60, + 0x44, 0x37, 0x28, 0xc0, 0x90, 0xc3, 0x4d, 0x6d, 0x4e, 0xba, 0x81, 0xe2, + 0x4e, 0x42, 0x39, 0x4f, 0x8f, 0xb8, 0x26, 0xf7, 0xc9, 0x2c, 0xa7, 0x1a, + 0x9d, 0xab, 0x16, 0xe9, 0x99, 0x27, 0x47, 0x26, 0xb0, 0xc5, 0xd8, 0xf7, + 0x2f, 0xb9, 0x14, 0x18, 0x70, 0xda, 0xc0, 0xbb, 0x9e, 0xc0, 0x42, 0x98, + 0x02, 0xb6, 0x29, 0xad, 0x71, 0xae, 0x05, 0x60, 0xe5, 0x86, 0x2e, 0xcf, + 0x3e, 0xab, 0xa9, 0xc2, 0xa5, 0x84, 0x88, 0x5b, 0x32, 0xc6, 0x84, 0xf6, + 0xd5, 0x5f, 0xd1, 0xb0, 0x90, 0xd9, 0x3d, 0x03, 0x6a, 0x4e, 0x98, 0x58, + 0xa4, 0xd8, 0x9b, 0x9b, 0x57, 0x50, 0x84, 0x9d, 0x92, 0x6c, 0x51, 0x91, + 0x20, 0x13, 0x1d, 0x45, 0x6f, 0xce, 0x9d, 0x24, 0x73, 0x41, 0xeb, 0x17, + 0x33, 0x6c, 0xa9, 0x72, 0x9a, 0x90, 0x80, 0xac, 0x5b, 0x12, 0x72, 0xfb, + 0xf7, 0x07, 0x52, 0x6a, 0xfc, 0x8a, 0xe6, 0xa8, 0xc6, 0x61, 0xef, 0x3c, + 0x15, 0x18, 0x45, 0xf6, 0xee, 0x09, 0x02, 0xde, 0x9a, 0xbb, 0x43, 0x22, + 0xaf, 0xe5, 0x85, 0xe5, 0x9d, 0x6d, 0x41, 0x8e, 0x87, 0xd7, 0xcd, 0xce, + 0x48, 0x97, 0xcc, 0xac, 0x81, 0xd0, 0x13, 0xfd, 0x72, 0xda, 0xe1, 0xa5, + 0x55, 0x77, 0x62, 0x52, 0x73, 0x12, 0x58, 0x7c, 0xa6, 0x76, 0xf0, 0xe0, + 0x67, 0x60, 0x00, 0xfc, 0x0c, 0x76, 0xb8, 0x26, 0x58, 0x42, 0xf2, 0xdb, + 0x7e, 0x18, 0xe6, 0x21, 0xc0, 0xe3, 0xc2, 0xca, 0x92, 0x95, 0xe9, 0xe3, + 0x6e, 0xc8, 0xce, 0x1c, 0x85, 0x09, 0x7c, 0xa5, 0xff, 0xfa, 0x62, 0xe7, + 0xb8, 0x96, 0xbb, 0x16, 0x83, 0x6d, 0x06, 0x33, 0x86, 0xb1, 0xe6, 0x63, + 0xef, 0x29, 0xec, 0x17, 0x02, 0x96, 0x5a, 0x7e, 0x05, 0x62, 0xd2, 0xd2, + 0x82, 0xf8, 0x09, 0x52, 0xd7, 0x47, 0x6b, 0x32, 0x2f, 0xfa, 0x79, 0x29, + 0xa4, 0x53, 0xa6, 0x38, 0xea, 0x3b, 0xed, 0xe8, 0x02, 0xff, 0x5f, 0x8f, + 0x56, 0x60, 0x85, 0xa6, 0xe2, 0xa2, 0x41, 0x4e, 0xf7, 0xa6, 0xf1, 0x17, + 0xac, 0x86, 0x28, 0x48, 0x6b, 0x23, 0x60, 0x3b, 0x14, 0x08, 0xfa, 0xae +}; +/* K = 40c6be904308e25af6616fe77c23e6e6570ac32ba5bf54aa81f6773a5071a904 */ +static const uint8_t ac_dsa_vect234_out[] = { +/* R */ + 0x23, 0xe1, 0x3a, 0x35, 0x77, 0x7c, 0x18, 0x9a, 0xe5, 0x65, 0x09, 0xc7, + 0xaf, 0xb4, 0x11, 0xb3, 0x13, 0x07, 0x73, 0x7e, 0x2f, 0xfc, 0x8d, 0xb3, + 0xf2, 0x08, 0x94, 0x0c, 0x5e, 0x76, 0xed, 0xb3, +/* S */ + 0x05, 0x44, 0x75, 0x83, 0x62, 0xcb, 0xb6, 0x1d, 0x66, 0xb6, 0x68, 0x26, + 0x95, 0x8a, 0xca, 0x63, 0xaf, 0x1b, 0x8a, 0xd6, 0x15, 0xa4, 0x9b, 0xa5, + 0x57, 0x92, 0x39, 0x59, 0xb6, 0x8f, 0x82, 0x28 +}; +#define ac_dsa_vect235_prime ac_dsa_vect226_prime +#define ac_dsa_vect235_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect235_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect235_ptx[] = { +/* Msg */ + 0x44, 0x34, 0x73, 0xd6, 0x15, 0xbe, 0xdc, 0xba, 0x2c, 0x8d, 0x9a, 0x9a, + 0x45, 0xa2, 0x8c, 0x42, 0x8d, 0x7f, 0x1a, 0x26, 0xab, 0x14, 0x70, 0x56, + 0x27, 0xd9, 0xad, 0x13, 0xf5, 0x3b, 0x76, 0x7c, 0xbb, 0x60, 0xbe, 0x52, + 0x3f, 0xc2, 0x1a, 0x99, 0xc3, 0x73, 0xbd, 0x77, 0x61, 0x81, 0x7b, 0x31, + 0x42, 0x90, 0xf2, 0xf6, 0xa8, 0x0e, 0x06, 0xe1, 0x2c, 0xce, 0x23, 0x89, + 0x54, 0xc6, 0x48, 0xac, 0xe5, 0x0f, 0x3b, 0x0d, 0xfd, 0xf7, 0x1d, 0xc3, + 0x08, 0xe1, 0xa8, 0xee, 0x11, 0x59, 0xfc, 0x1f, 0x19, 0xb7, 0x3a, 0xb6, + 0x01, 0x5d, 0x18, 0x6d, 0x9b, 0x6b, 0xad, 0x96, 0x5a, 0x9a, 0xd6, 0x2e, + 0x44, 0x0a, 0x9c, 0xed, 0x13, 0x55, 0x0a, 0x44, 0x4b, 0x5f, 0x04, 0x00, + 0xb9, 0x6e, 0x2d, 0x23, 0x8e, 0x9e, 0x3d, 0xc6, 0xe6, 0xde, 0x12, 0xf4, + 0x42, 0x05, 0xd4, 0xfd, 0x57, 0xf6, 0x0e, 0x9d +}; +static const uint8_t ac_dsa_vect235_priv_val[] = { +/* X */ + 0x0b, 0xdf, 0x6e, 0xd0, 0x48, 0x35, 0x8d, 0xcc, 0x9a, 0x2d, 0xc5, 0x55, + 0xc3, 0xd4, 0x5a, 0xc3, 0x94, 0x57, 0x11, 0x35, 0xab, 0x36, 0x16, 0x8d, + 0x9f, 0xc4, 0xff, 0xe4, 0xa3, 0x52, 0x9a, 0x80 +}; +static const uint8_t ac_dsa_vect235_pub_val[] = { +/* Y */ + 0x0f, 0x4e, 0xc6, 0xe2, 0xba, 0xae, 0xa9, 0xc8, 0x1e, 0x90, 0x70, 0x05, + 0x19, 0xf2, 0xf0, 0x5f, 0x54, 0x5d, 0xdc, 0x0a, 0xe9, 0xbd, 0x3a, 0x09, + 0x1e, 0x8b, 0x6b, 0xa5, 0x25, 0x5c, 0x15, 0xfc, 0xe5, 0xef, 0x3c, 0x04, + 0x67, 0x71, 0xc5, 0xf3, 0x1b, 0xb0, 0x1d, 0xe4, 0x37, 0x7e, 0x14, 0x28, + 0x31, 0xac, 0x17, 0x49, 0x90, 0x3f, 0x93, 0x17, 0xc7, 0xb0, 0x1a, 0x99, + 0x07, 0x14, 0x98, 0x5f, 0x92, 0x51, 0x19, 0x8c, 0x82, 0x90, 0x73, 0x20, + 0x59, 0x24, 0xc5, 0x68, 0x05, 0x0a, 0xcd, 0x6d, 0xcc, 0xa7, 0x57, 0x61, + 0x8c, 0xd2, 0x80, 0x9b, 0xb7, 0xaa, 0xb6, 0x4d, 0xb1, 0xe8, 0x6c, 0xa9, + 0x2e, 0xeb, 0x85, 0x41, 0x20, 0xc9, 0xd8, 0x9f, 0xb9, 0x36, 0x35, 0x96, + 0xbe, 0x9c, 0xbb, 0xaf, 0x8e, 0xac, 0xae, 0x2f, 0x18, 0xf3, 0xed, 0x48, + 0x35, 0x89, 0xeb, 0x46, 0x6a, 0x51, 0x44, 0x82, 0x4f, 0xeb, 0x1f, 0x88, + 0xc3, 0x0c, 0xfc, 0xbb, 0x76, 0x28, 0xf7, 0xcb, 0x41, 0x59, 0xce, 0x32, + 0xe7, 0xc2, 0xed, 0x04, 0xd0, 0xff, 0x04, 0x81, 0xc9, 0x58, 0xe5, 0xff, + 0x74, 0x45, 0x22, 0x94, 0x4c, 0xf3, 0x20, 0x20, 0x38, 0x9b, 0x32, 0x95, + 0x9b, 0x5e, 0x12, 0xf8, 0x0f, 0x08, 0x06, 0x49, 0x08, 0xa2, 0x70, 0xf8, + 0x69, 0x5a, 0x3f, 0x99, 0xe7, 0x5e, 0x7e, 0x85, 0xba, 0x3b, 0x3c, 0x77, + 0x3f, 0x04, 0xef, 0x9e, 0x09, 0xe7, 0x6b, 0x6c, 0x47, 0x30, 0x2e, 0x41, + 0xd5, 0x0e, 0xad, 0x04, 0x54, 0x1e, 0x0f, 0xca, 0x4a, 0x42, 0x50, 0x27, + 0x22, 0x26, 0x5f, 0x82, 0xff, 0x60, 0xef, 0x46, 0xaa, 0x75, 0x47, 0xf9, + 0xde, 0x24, 0x91, 0x35, 0xdd, 0x07, 0x7f, 0x24, 0xa4, 0xe7, 0xe0, 0x3b, + 0xe2, 0xe3, 0x09, 0x47, 0x72, 0x76, 0x7a, 0x97, 0x60, 0x88, 0x3c, 0x52, + 0x08, 0x16, 0xfa, 0xe6, 0x37, 0xc0, 0x30, 0x95, 0x6e, 0xa2, 0x5f, 0x0a, + 0x86, 0x9e, 0x4a, 0x00, 0xa4, 0xa8, 0x01, 0x7b, 0xcb, 0x72, 0xb2, 0xf2, + 0xfd, 0x83, 0x64, 0x3b, 0xdc, 0x01, 0xd8, 0xff, 0x28, 0x68, 0xd3, 0xca, + 0xf1, 0x00, 0xae, 0x8b, 0x81, 0x8b, 0x92, 0x6c, 0x96, 0xa8, 0x50, 0xbd, + 0x69, 0xd8, 0x93, 0x1d, 0xbf, 0xdc, 0xff, 0x31, 0xc6, 0x7c, 0x53, 0x7c, + 0x4f, 0x59, 0x59, 0xd0, 0x4b, 0x74, 0x4a, 0x34, 0x66, 0x47, 0x06, 0x6d, + 0xcc, 0x61, 0xf6, 0x3b, 0xe6, 0x25, 0x1b, 0x59, 0x0d, 0x68, 0x8a, 0xe3, + 0xc9, 0xb5, 0x3f, 0x39, 0x20, 0x07, 0xd8, 0x58, 0x4e, 0x46, 0x24, 0xff, + 0xd2, 0x94, 0x16, 0x50, 0xa3, 0x1d, 0xcd, 0x5a, 0xbf, 0xae, 0x7c, 0xa1, + 0x20, 0xb1, 0x1c, 0x8d, 0x01, 0x94, 0xbe, 0x96, 0xe8, 0xdd, 0x09, 0xb6, + 0x43, 0xd5, 0x68, 0x5d, 0x10, 0x65, 0xd9, 0x8f, 0x39, 0xb6, 0xed, 0x7c +}; +/* K = 63066e05d16e79fd013a6ae456aa3f036e9d58675b3c9e08a412420a64c1f977 */ +static const uint8_t ac_dsa_vect235_out[] = { +/* R */ + 0x76, 0xbb, 0x0e, 0xcb, 0x9f, 0xae, 0xc7, 0xc9, 0x71, 0x13, 0x7e, 0xa6, + 0xfe, 0xac, 0xf1, 0x79, 0x20, 0x73, 0xae, 0x80, 0xbe, 0x1c, 0xa8, 0xed, + 0x9c, 0xec, 0x2a, 0x5c, 0xa6, 0xcd, 0x51, 0x0f, +/* S */ + 0x34, 0x92, 0x02, 0x46, 0x73, 0x0e, 0x09, 0x74, 0xfb, 0x0f, 0xaa, 0x57, + 0xe7, 0x7f, 0xc5, 0x0a, 0xb7, 0x87, 0x26, 0xc8, 0xe5, 0x15, 0x79, 0xa0, + 0xef, 0x5e, 0xbe, 0x3f, 0xce, 0x3b, 0xa7, 0xcb +}; +#define ac_dsa_vect236_prime ac_dsa_vect226_prime +#define ac_dsa_vect236_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect236_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect236_ptx[] = { +/* Msg */ + 0xce, 0xe0, 0x6f, 0x79, 0x23, 0x32, 0x08, 0x0d, 0x6e, 0x73, 0xb3, 0xf0, + 0x2f, 0x5e, 0xc1, 0x69, 0x96, 0xb6, 0x69, 0x95, 0xbe, 0xab, 0x4a, 0x2b, + 0xa0, 0x92, 0xf4, 0x0d, 0x85, 0xc8, 0xac, 0x1a, 0xcc, 0xf5, 0x4f, 0xba, + 0x06, 0x81, 0x28, 0xc8, 0xcd, 0xba, 0xda, 0x20, 0x93, 0x60, 0x77, 0x6a, + 0x77, 0x06, 0x45, 0x50, 0x15, 0xe7, 0x3e, 0x92, 0xc6, 0x24, 0xad, 0xa1, + 0xdf, 0xa6, 0x2e, 0xc7, 0x94, 0xcf, 0x2a, 0x1a, 0x92, 0x94, 0xf3, 0xfb, + 0x55, 0x99, 0x4b, 0xc5, 0x21, 0x1a, 0xdd, 0x1c, 0x68, 0x5d, 0x9a, 0x54, + 0xac, 0xd5, 0xbc, 0xd8, 0x30, 0xd9, 0xa4, 0xfc, 0xff, 0x29, 0xae, 0xc5, + 0x00, 0x1c, 0x3b, 0x2b, 0x2a, 0x97, 0x06, 0x04, 0x6f, 0x38, 0xbf, 0xe4, + 0x8e, 0x85, 0x22, 0x76, 0x8f, 0x1c, 0x6f, 0x08, 0xa8, 0xe2, 0x40, 0xe1, + 0x23, 0xed, 0x30, 0xe2, 0x0f, 0xc4, 0x6c, 0x19 +}; +static const uint8_t ac_dsa_vect236_priv_val[] = { +/* X */ + 0x53, 0x0e, 0x54, 0xbf, 0x51, 0xb3, 0xea, 0x01, 0x2e, 0x76, 0x20, 0x6b, + 0x5f, 0xf5, 0x3c, 0x1d, 0x5a, 0xe6, 0xf3, 0x43, 0x3f, 0x2a, 0x50, 0xb6, + 0x6b, 0x69, 0x47, 0xe8, 0x4d, 0xd5, 0x21, 0x71 +}; +static const uint8_t ac_dsa_vect236_pub_val[] = { +/* Y */ + 0x5c, 0x92, 0x05, 0xfb, 0x64, 0x9d, 0x3b, 0x4b, 0xa2, 0xd4, 0x4c, 0x80, + 0xa9, 0x25, 0xe3, 0x0d, 0x27, 0xb0, 0x5b, 0xd3, 0x39, 0xf1, 0xce, 0x35, + 0xe0, 0xd0, 0x41, 0x9a, 0x91, 0xed, 0x31, 0xfd, 0x10, 0x8c, 0x51, 0xa2, + 0xa6, 0x2c, 0xf9, 0xd0, 0xad, 0xfd, 0x87, 0x7d, 0x27, 0xcf, 0x55, 0x75, + 0xe4, 0x3a, 0xc7, 0xbf, 0xcf, 0xce, 0xec, 0x56, 0x73, 0x73, 0x6c, 0xae, + 0x08, 0x95, 0x16, 0xdf, 0x8e, 0xb1, 0xea, 0x6b, 0x56, 0x31, 0x98, 0xb2, + 0x4a, 0x6e, 0x25, 0x22, 0xf3, 0x20, 0xb1, 0x23, 0xbf, 0xb2, 0x50, 0xd4, + 0x3b, 0x60, 0x0d, 0xf9, 0x29, 0x8e, 0x12, 0x1b, 0x6c, 0x5d, 0x2e, 0x63, + 0x7a, 0x98, 0x92, 0x15, 0xe0, 0x95, 0xe6, 0x03, 0xee, 0x6d, 0x4e, 0x8a, + 0x2d, 0xcd, 0x17, 0xb9, 0x08, 0x91, 0x8a, 0xa5, 0x14, 0xc8, 0x6a, 0x33, + 0xd8, 0xc7, 0x17, 0x57, 0x8d, 0x86, 0x12, 0x61, 0xda, 0x43, 0xf7, 0x32, + 0x50, 0xff, 0x2b, 0xe7, 0x46, 0xc6, 0x91, 0x6f, 0xc7, 0x28, 0x71, 0xfb, + 0x42, 0xa2, 0x79, 0xd2, 0x25, 0x95, 0x05, 0x1b, 0x8a, 0xc0, 0x4a, 0xfb, + 0xf2, 0x01, 0x30, 0x63, 0xe3, 0x16, 0x61, 0xb1, 0x17, 0xc5, 0xd0, 0x94, + 0xb4, 0xc2, 0x32, 0xb2, 0x2f, 0x21, 0xd2, 0xc6, 0x5d, 0x63, 0x61, 0x29, + 0x0c, 0x08, 0xf1, 0x2b, 0xef, 0xd1, 0xf5, 0xa2, 0xb9, 0xb5, 0x25, 0x9a, + 0xf0, 0x43, 0x5b, 0x97, 0xb4, 0x32, 0x82, 0x97, 0xc2, 0x52, 0xd8, 0x13, + 0x49, 0x9f, 0x52, 0x09, 0xdf, 0xa3, 0x5e, 0x91, 0x98, 0xde, 0x68, 0x50, + 0x1a, 0xf4, 0xca, 0x86, 0x58, 0x94, 0x2d, 0x05, 0x9b, 0xb6, 0x2b, 0x8e, + 0x55, 0xa3, 0xce, 0x61, 0x20, 0xa7, 0x8e, 0xe0, 0x98, 0x13, 0x2e, 0x8d, + 0x2d, 0xc3, 0x75, 0x7f, 0x7e, 0x60, 0xf8, 0xc0, 0x8c, 0x4e, 0x43, 0xfe, + 0xac, 0x67, 0xab, 0xcd, 0xdd, 0x1e, 0xa2, 0xf0, 0x16, 0x83, 0x9f, 0xb1, + 0xa0, 0xf7, 0x97, 0xb8, 0xb1, 0x37, 0xab, 0x43, 0xb6, 0x45, 0x08, 0xef, + 0x69, 0xf6, 0xae, 0x0f, 0x3a, 0xbc, 0x4e, 0xd6, 0x82, 0xaa, 0x7e, 0x38, + 0xfa, 0x51, 0x46, 0xfe, 0xc6, 0x2e, 0x01, 0xe0, 0x95, 0x1a, 0x6e, 0x81, + 0x15, 0x2d, 0xe4, 0x31, 0x71, 0xca, 0x88, 0x69, 0xfa, 0x1a, 0x42, 0xa4, + 0xfb, 0x2d, 0x8a, 0xe5, 0x12, 0xc0, 0x05, 0xfd, 0x97, 0xd1, 0x2b, 0xb1, + 0x3f, 0x29, 0x9a, 0xb9, 0xf5, 0x32, 0x1e, 0xe2, 0xfc, 0x39, 0xb2, 0x8e, + 0x61, 0xc9, 0xeb, 0xcb, 0x91, 0xec, 0xd2, 0xb6, 0x10, 0xfd, 0x82, 0x91, + 0xf5, 0x38, 0xa0, 0x0d, 0x06, 0xd0, 0x57, 0xc3, 0xe7, 0x94, 0x22, 0xa9, + 0x31, 0x27, 0x9f, 0xed, 0x9d, 0x93, 0xb0, 0xb6, 0x53, 0x3f, 0xae, 0x44, + 0x1e, 0x98, 0x41, 0x30, 0x25, 0xfb, 0x4f, 0xa7, 0x3c, 0xde, 0xfa, 0x80 +}; +/* K = 4e500b513c2e24ad17fcb8cc0d6a8c54e654e00a892545a33cb5af8877589520 */ +static const uint8_t ac_dsa_vect236_out[] = { +/* R */ + 0x6d, 0x02, 0x53, 0x6d, 0xb5, 0x46, 0xf2, 0xbb, 0x1f, 0x65, 0xff, 0x0b, + 0x91, 0xb9, 0x64, 0x80, 0x2b, 0x38, 0xd1, 0x71, 0xe6, 0x78, 0x05, 0x4e, + 0xe4, 0x1f, 0x2b, 0x85, 0x63, 0x80, 0x9c, 0xfa, +/* S */ + 0x6b, 0xc5, 0x11, 0x20, 0xe3, 0x5c, 0x95, 0x5a, 0xb8, 0xf7, 0x17, 0xf8, + 0x93, 0x0d, 0x8c, 0xc8, 0xde, 0xf8, 0x50, 0x54, 0x15, 0xcf, 0x15, 0x9d, + 0x25, 0x16, 0xf9, 0x65, 0x78, 0x84, 0x2f, 0x31 +}; +#define ac_dsa_vect237_prime ac_dsa_vect226_prime +#define ac_dsa_vect237_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect237_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect237_ptx[] = { +/* Msg */ + 0x58, 0xab, 0xa2, 0x4e, 0x94, 0x81, 0xd1, 0x15, 0x1b, 0x57, 0x4b, 0x14, + 0x6a, 0xc2, 0x1b, 0x17, 0x11, 0x0e, 0xd0, 0xb9, 0xbf, 0xaa, 0x55, 0xa4, + 0xe2, 0xe0, 0x6d, 0xcd, 0xc1, 0x8b, 0xd1, 0x0c, 0xdf, 0xaf, 0xac, 0x04, + 0x71, 0x89, 0xf5, 0xba, 0x9f, 0x10, 0x37, 0x7a, 0xff, 0xb4, 0x0a, 0x51, + 0x4d, 0x52, 0x8a, 0x34, 0x83, 0xfe, 0x8e, 0x64, 0xb8, 0x31, 0xea, 0x0c, + 0xd0, 0x76, 0xce, 0x58, 0x39, 0x42, 0xb9, 0x38, 0xa4, 0xb2, 0x57, 0xd0, + 0xb5, 0xa9, 0x24, 0x12, 0xe0, 0x1d, 0xfd, 0xa8, 0x21, 0x7d, 0x5f, 0x80, + 0x54, 0x59, 0x6a, 0x61, 0xd5, 0x73, 0x7d, 0x8a, 0xd8, 0x11, 0x2a, 0xe2, + 0x28, 0x22, 0x0e, 0x3b, 0xff, 0x60, 0xe2, 0xe8, 0x91, 0xd0, 0x3d, 0x53, + 0xfb, 0x14, 0xf1, 0x4d, 0xd9, 0x19, 0x75, 0xdc, 0x15, 0xd6, 0xb7, 0xbd, + 0x62, 0xe9, 0x9d, 0x74, 0xef, 0x38, 0x39, 0xfd +}; +static const uint8_t ac_dsa_vect237_priv_val[] = { +/* X */ + 0x7b, 0xc2, 0x31, 0x6b, 0x63, 0x01, 0xb7, 0x72, 0xb6, 0x74, 0x2d, 0x0c, + 0x50, 0xf2, 0xc1, 0xc3, 0x9b, 0xbe, 0xde, 0x01, 0x44, 0x80, 0x26, 0xb6, + 0xa2, 0x01, 0x79, 0x3b, 0xfe, 0x7d, 0xc3, 0xe3 +}; +static const uint8_t ac_dsa_vect237_pub_val[] = { +/* Y */ + 0x2a, 0xdb, 0xc0, 0x7d, 0x8a, 0xee, 0x28, 0x4e, 0xc9, 0x82, 0xc4, 0xb9, + 0x5e, 0x1e, 0xc3, 0xec, 0x3f, 0x5f, 0xd5, 0x17, 0x23, 0x68, 0xdd, 0xf8, + 0x3f, 0x9a, 0x3c, 0x69, 0x65, 0x52, 0x91, 0xde, 0xe6, 0xb9, 0x9e, 0xd7, + 0x13, 0xe5, 0xa1, 0xfe, 0xc3, 0x38, 0x23, 0x9b, 0x81, 0x99, 0xc5, 0xa3, + 0xbb, 0x2b, 0x5e, 0x2e, 0x7f, 0x23, 0xfc, 0x79, 0x50, 0x58, 0xa9, 0xac, + 0x70, 0xeb, 0xdf, 0xf2, 0xb3, 0xda, 0xaf, 0xfa, 0x38, 0x9e, 0x97, 0xfe, + 0xe3, 0x5f, 0x17, 0x49, 0x61, 0xf1, 0x2d, 0x63, 0x4e, 0x8b, 0x82, 0x50, + 0xb8, 0xb7, 0x70, 0xb8, 0xd7, 0x11, 0x3d, 0x0f, 0xbc, 0x02, 0x0b, 0x7b, + 0x10, 0x8f, 0x8d, 0x6b, 0x2d, 0x7c, 0xb6, 0xc5, 0x9e, 0x2e, 0x15, 0x10, + 0x15, 0x14, 0x5a, 0x8e, 0x37, 0x4f, 0x9b, 0x73, 0x96, 0xe9, 0x70, 0xd9, + 0x1e, 0x3c, 0x1f, 0x85, 0xce, 0x23, 0xdc, 0xae, 0x12, 0xb2, 0xf5, 0x37, + 0x41, 0xcf, 0xc2, 0x35, 0x0b, 0x58, 0x2c, 0xa8, 0x7f, 0x0f, 0xf9, 0xab, + 0x50, 0xad, 0x0c, 0xa2, 0x87, 0x9e, 0x21, 0x6e, 0x61, 0xa5, 0xc3, 0x58, + 0x97, 0x0a, 0x3c, 0x35, 0x28, 0xdc, 0xd9, 0xec, 0xe6, 0xb8, 0x3d, 0x52, + 0x5b, 0x31, 0xfe, 0x68, 0x76, 0x96, 0xa2, 0xa2, 0xc6, 0x5e, 0x34, 0xf2, + 0x85, 0x4f, 0xea, 0x6f, 0xf9, 0x22, 0x44, 0xd2, 0x75, 0x00, 0xf7, 0xda, + 0x94, 0x6c, 0x37, 0x16, 0x97, 0x56, 0xf4, 0xa4, 0x66, 0x4b, 0x29, 0x09, + 0x61, 0x15, 0x49, 0xad, 0x2b, 0x93, 0xeb, 0xac, 0xeb, 0xfc, 0x27, 0x0e, + 0xcf, 0x42, 0x04, 0xe6, 0x64, 0x1d, 0xbc, 0xe0, 0x5d, 0xa2, 0xc0, 0x00, + 0xa4, 0xca, 0x5a, 0xc8, 0x85, 0x40, 0x6b, 0xa1, 0x55, 0x80, 0x74, 0x94, + 0x70, 0x61, 0x80, 0xd5, 0x4c, 0xc0, 0x12, 0xce, 0x06, 0xe7, 0x34, 0x02, + 0x4f, 0x4c, 0xcd, 0x88, 0x2b, 0xdd, 0xd2, 0x25, 0x7a, 0xfb, 0x5c, 0x28, + 0x7b, 0xc3, 0xa8, 0x57, 0x0e, 0xdf, 0x21, 0xa2, 0x0a, 0xfe, 0xda, 0x0c, + 0x76, 0x2a, 0xd6, 0x96, 0xfb, 0xa1, 0x77, 0xa5, 0xf2, 0xf9, 0xd6, 0x09, + 0x35, 0x5c, 0xb9, 0x1d, 0x72, 0xcc, 0xac, 0x8b, 0xb9, 0xe7, 0xc3, 0xcf, + 0xf1, 0x83, 0x4d, 0x86, 0xb0, 0x77, 0x2a, 0xec, 0x74, 0x1d, 0x7b, 0x4b, + 0x3c, 0x3e, 0x43, 0xbb, 0x26, 0xec, 0x9f, 0x5e, 0x86, 0xb8, 0x68, 0x5e, + 0xa5, 0xc6, 0x25, 0xb6, 0xae, 0xa4, 0x50, 0xa4, 0x6e, 0x85, 0xe3, 0x80, + 0xb1, 0x58, 0xde, 0x6a, 0xaa, 0x27, 0x01, 0xff, 0xad, 0x0c, 0x7d, 0x1e, + 0xd0, 0xdf, 0x35, 0x5d, 0x09, 0xd0, 0x6f, 0xe1, 0x75, 0x8b, 0x2f, 0x27, + 0xa5, 0xd0, 0x2a, 0xa2, 0x83, 0xae, 0xc9, 0xfd, 0x12, 0xd3, 0xb6, 0x2d, + 0x50, 0x4d, 0xca, 0x0b, 0x66, 0x32, 0xe8, 0x9f, 0xc5, 0x5f, 0xb0, 0x83 +}; +/* K = 0c2a0d2b326ad63e869384e3e2e32fcff8db83285fa0a5b9a7b13589a7dd7fc1 */ +static const uint8_t ac_dsa_vect237_out[] = { +/* R */ + 0x2c, 0x46, 0x2d, 0x49, 0x34, 0x4f, 0x3a, 0xd0, 0x3b, 0x67, 0x98, 0xf9, + 0x64, 0x52, 0xf7, 0xd6, 0x63, 0x51, 0xce, 0xad, 0x91, 0x9e, 0x82, 0x01, + 0xb7, 0x66, 0x5c, 0x87, 0x7f, 0x82, 0x55, 0xbb, +/* S */ + 0x50, 0xe8, 0x90, 0x8a, 0x1c, 0x66, 0x84, 0xa2, 0xca, 0xa8, 0xaa, 0xfb, + 0x43, 0x2c, 0xda, 0x4b, 0x76, 0x99, 0x00, 0x8c, 0x72, 0xd8, 0xd6, 0x22, + 0xc3, 0xda, 0x41, 0x71, 0xe5, 0x1c, 0xfd, 0xbf +}; +#define ac_dsa_vect238_prime ac_dsa_vect226_prime +#define ac_dsa_vect238_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect238_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect238_ptx[] = { +/* Msg */ + 0xe1, 0x06, 0x04, 0xca, 0x00, 0x72, 0x8e, 0x53, 0x36, 0x21, 0xdb, 0xb6, + 0x61, 0x8b, 0x0c, 0x87, 0x7c, 0x49, 0x02, 0xa2, 0xed, 0x79, 0xaa, 0xf4, + 0x0a, 0x4d, 0xaa, 0x34, 0xd6, 0xcc, 0x21, 0x6a, 0xd4, 0x64, 0x8d, 0xaa, + 0xb6, 0xcc, 0x1e, 0x18, 0x45, 0x1b, 0xb9, 0x4e, 0x6a, 0x1c, 0x0c, 0x6f, + 0x9d, 0x0d, 0x88, 0x39, 0x62, 0xee, 0xbd, 0x50, 0x7d, 0xa0, 0x99, 0x78, + 0x80, 0x08, 0xda, 0x23, 0x20, 0x5e, 0x3b, 0x4e, 0x90, 0xfa, 0xd9, 0xae, + 0x85, 0x70, 0x74, 0xff, 0xea, 0xc6, 0x34, 0x30, 0xc0, 0xfa, 0xcb, 0xae, + 0x48, 0x9c, 0x54, 0xc9, 0x57, 0xdb, 0x09, 0xd5, 0x3e, 0x12, 0xb6, 0x56, + 0xcc, 0x27, 0x86, 0x15, 0xa3, 0xa5, 0x61, 0x2a, 0xf4, 0xc2, 0xf1, 0x68, + 0xbd, 0xeb, 0x11, 0x8a, 0x42, 0xa2, 0xa6, 0x71, 0x03, 0xfa, 0xc3, 0x21, + 0xad, 0xf5, 0x68, 0x8b, 0x05, 0x84, 0x8f, 0x7c +}; +static const uint8_t ac_dsa_vect238_priv_val[] = { +/* X */ + 0x6d, 0xd5, 0x00, 0xe2, 0xae, 0xce, 0x9a, 0xe3, 0x31, 0xdf, 0x26, 0x9c, + 0x26, 0xa4, 0xe5, 0xd5, 0x8f, 0xc6, 0xbe, 0x39, 0x63, 0xf5, 0x00, 0x2e, + 0x36, 0xbd, 0x9c, 0xd0, 0x4c, 0x1a, 0xdb, 0xbd +}; +static const uint8_t ac_dsa_vect238_pub_val[] = { +/* Y */ + 0xb0, 0x44, 0x8d, 0x43, 0xc5, 0x20, 0x37, 0x7b, 0x7d, 0xf2, 0x14, 0x96, + 0x9f, 0x59, 0xff, 0xd4, 0xe0, 0x01, 0x0c, 0x12, 0xd7, 0xe5, 0xfa, 0x8f, + 0x24, 0x1e, 0x9c, 0xe1, 0xc6, 0x34, 0x43, 0x9c, 0x94, 0x70, 0x0e, 0xd5, + 0x74, 0x2a, 0x83, 0x22, 0xd4, 0x05, 0xdd, 0x05, 0xde, 0x99, 0x53, 0x44, + 0x78, 0x31, 0xc7, 0x67, 0x4e, 0x5a, 0xe1, 0xb8, 0x90, 0x41, 0xfb, 0x8f, + 0x2e, 0xc1, 0x05, 0x4b, 0x92, 0x8c, 0x64, 0xab, 0x86, 0x2f, 0x02, 0x1a, + 0x55, 0xeb, 0xce, 0x83, 0x8d, 0x2a, 0x3d, 0x2c, 0x76, 0x45, 0xec, 0x7c, + 0x0a, 0x1a, 0x46, 0x03, 0x61, 0x7e, 0x4f, 0x50, 0x89, 0x29, 0x14, 0x4c, + 0x1e, 0xf2, 0xb0, 0x39, 0xbc, 0x78, 0xb5, 0x93, 0x62, 0xd5, 0xba, 0x95, + 0x37, 0x90, 0x6e, 0x66, 0xc8, 0xe9, 0xc9, 0xa3, 0xc6, 0x8e, 0x71, 0xb3, + 0x5d, 0x88, 0xb8, 0xba, 0xc8, 0x6c, 0xac, 0xbe, 0xbd, 0x96, 0x2c, 0x66, + 0xe1, 0x81, 0x29, 0x63, 0x7f, 0xad, 0x2d, 0x98, 0xd2, 0x1e, 0x45, 0xa3, + 0x26, 0x72, 0x64, 0x94, 0x92, 0xf1, 0x31, 0xba, 0xe8, 0x8c, 0x99, 0x89, + 0xbd, 0x63, 0x72, 0xe1, 0x74, 0x92, 0xbe, 0xdf, 0xf4, 0xd9, 0xb0, 0x91, + 0xb3, 0xdd, 0x00, 0xeb, 0xca, 0x6b, 0xcc, 0x49, 0x14, 0x84, 0x80, 0x58, + 0x9f, 0x95, 0x93, 0xe3, 0x27, 0x95, 0x29, 0x9f, 0x3d, 0xe7, 0xe0, 0x9d, + 0x88, 0xbc, 0x0e, 0xd2, 0x7b, 0x7e, 0xf2, 0x2e, 0xf7, 0xd2, 0x02, 0x20, + 0x7f, 0xb5, 0xce, 0x8c, 0x91, 0x71, 0x2c, 0x3b, 0xd5, 0xe7, 0x58, 0xd2, + 0x82, 0x28, 0x09, 0xea, 0x5d, 0x2c, 0xb2, 0x88, 0x33, 0x2a, 0xa0, 0x76, + 0x03, 0x68, 0x25, 0x92, 0x81, 0xa3, 0x44, 0x47, 0xff, 0x5a, 0x98, 0xc9, + 0xc9, 0x7c, 0x1d, 0x58, 0x38, 0x3c, 0xd1, 0x4f, 0x6d, 0x59, 0xbb, 0x5e, + 0x57, 0x63, 0x21, 0x7b, 0x23, 0x37, 0xec, 0x23, 0x21, 0x26, 0x81, 0x97, + 0xf0, 0x2c, 0xec, 0xd0, 0xd9, 0xfd, 0x93, 0xdb, 0x39, 0xf8, 0x05, 0x9a, + 0x38, 0xbb, 0xb3, 0x57, 0x92, 0xba, 0x0d, 0x4e, 0xd1, 0xba, 0xd9, 0x5a, + 0x05, 0xb4, 0x81, 0xc3, 0x9f, 0x6a, 0xdc, 0x90, 0x17, 0xde, 0xc1, 0xd6, + 0x62, 0xb0, 0x80, 0x3f, 0x2e, 0xcf, 0x08, 0x45, 0x93, 0x57, 0x65, 0xf9, + 0x35, 0x6d, 0xb5, 0x36, 0xc8, 0xc1, 0x18, 0x87, 0xd9, 0xe4, 0x4b, 0x73, + 0xb6, 0x99, 0x6a, 0xe7, 0xac, 0x24, 0xfc, 0xad, 0x9c, 0x23, 0x01, 0x7e, + 0x5c, 0x2a, 0xca, 0x88, 0xb5, 0xa1, 0x36, 0xb6, 0x30, 0x72, 0x98, 0xb8, + 0x5f, 0xf0, 0x10, 0xf9, 0x64, 0xb7, 0x47, 0x7a, 0x4f, 0x98, 0x08, 0x00, + 0xe6, 0x9d, 0x3c, 0xc0, 0xf4, 0x38, 0xaf, 0xf7, 0xf2, 0xdf, 0x8a, 0xc6, + 0x1d, 0x64, 0x43, 0x5f, 0xfa, 0xf5, 0xe4, 0x66, 0x33, 0x60, 0x9e, 0x87 +}; +/* K = 65243ccac0a014b9e52638171b4a88b02a8c6e617ab9467da523487122e6650c */ +static const uint8_t ac_dsa_vect238_out[] = { +/* R */ + 0x56, 0xab, 0x99, 0x47, 0xac, 0x94, 0xfe, 0x3d, 0xf7, 0xe3, 0x58, 0x01, + 0x66, 0x0f, 0x68, 0x75, 0x3b, 0x0b, 0x62, 0x0a, 0x26, 0x59, 0x4c, 0xb8, + 0xfd, 0x37, 0x5b, 0xe3, 0xea, 0x4d, 0xbf, 0x05, +/* S */ + 0x60, 0x8e, 0xd1, 0x83, 0x51, 0x39, 0xaf, 0x29, 0xa2, 0xe3, 0xd8, 0x74, + 0xdf, 0x46, 0x5e, 0xdd, 0x8d, 0x64, 0x28, 0xf4, 0x03, 0x57, 0xd9, 0xae, + 0x49, 0x04, 0xef, 0xe8, 0xbc, 0xcb, 0xd0, 0x35 +}; +#define ac_dsa_vect239_prime ac_dsa_vect226_prime +#define ac_dsa_vect239_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect239_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect239_ptx[] = { +/* Msg */ + 0x8a, 0xf3, 0x1f, 0x66, 0x77, 0x2f, 0xb0, 0xc3, 0x1a, 0x8c, 0x5b, 0x28, + 0xe5, 0x68, 0xe6, 0x36, 0x8c, 0xb6, 0x6b, 0x59, 0x1e, 0xdf, 0xb0, 0xdb, + 0x86, 0x7f, 0xd9, 0x9e, 0x83, 0xfe, 0xb3, 0x63, 0x8b, 0xc8, 0x0f, 0x0b, + 0x14, 0x48, 0x3d, 0x06, 0x9e, 0x8f, 0x2e, 0x16, 0x7c, 0x8b, 0x0f, 0x10, + 0xcd, 0x6b, 0x45, 0xd0, 0x39, 0xb7, 0xd6, 0xf8, 0x33, 0xbd, 0x58, 0xd9, + 0x9b, 0x00, 0x59, 0x7a, 0xee, 0xf8, 0x2f, 0xa3, 0xaa, 0xe2, 0xe5, 0x5d, + 0xed, 0x62, 0xab, 0x66, 0x08, 0x10, 0xde, 0x0f, 0xe1, 0xc9, 0x2d, 0x53, + 0xad, 0xf9, 0x8c, 0x83, 0x8c, 0x18, 0xfd, 0x76, 0xa2, 0x73, 0xea, 0x12, + 0x11, 0x9d, 0x67, 0x5a, 0xf7, 0x27, 0x01, 0x18, 0x69, 0x94, 0x3d, 0x76, + 0x5b, 0x96, 0xef, 0x26, 0x62, 0x70, 0xb4, 0xf8, 0x9a, 0xc7, 0x2e, 0xda, + 0xdc, 0xf7, 0x07, 0xa4, 0xa2, 0x1b, 0x75, 0x33 +}; +static const uint8_t ac_dsa_vect239_priv_val[] = { +/* X */ + 0x14, 0x5a, 0xbc, 0xe3, 0xea, 0xa8, 0xfa, 0x6b, 0x67, 0x0a, 0xfd, 0x65, + 0x8b, 0xa0, 0xc1, 0x4f, 0xa9, 0x8d, 0x2d, 0x20, 0xe1, 0x42, 0x23, 0x67, + 0xd4, 0x45, 0x59, 0x67, 0xf9, 0x84, 0x48, 0x58 +}; +static const uint8_t ac_dsa_vect239_pub_val[] = { +/* Y */ + 0x22, 0xf3, 0xdb, 0x9e, 0xa3, 0x69, 0x93, 0x8e, 0xd7, 0x50, 0xd5, 0xed, + 0x37, 0x81, 0x36, 0x8d, 0x59, 0x4e, 0x62, 0x63, 0x5c, 0x6b, 0x6e, 0x10, + 0x3d, 0x6d, 0xb4, 0x89, 0xa9, 0x97, 0x2f, 0x39, 0x82, 0x03, 0xab, 0xb9, + 0x73, 0xd5, 0xad, 0x9c, 0x0d, 0xc1, 0x10, 0x58, 0x69, 0x78, 0xd2, 0x06, + 0x14, 0x83, 0xc0, 0x20, 0x27, 0x38, 0xce, 0xb0, 0x1a, 0x66, 0x5d, 0xd2, + 0x2f, 0xc5, 0x68, 0xcb, 0xdf, 0xf2, 0x14, 0x8a, 0xe6, 0x64, 0xdf, 0xfb, + 0xf8, 0x88, 0xe4, 0xdd, 0xa5, 0xa0, 0x4f, 0xd3, 0xe8, 0x93, 0x98, 0xb4, + 0xf1, 0xff, 0xc3, 0xa3, 0x81, 0x3a, 0xe9, 0x4d, 0xa1, 0xf8, 0x96, 0x5e, + 0xfb, 0xe7, 0xf3, 0x00, 0x94, 0x87, 0x49, 0xe9, 0x75, 0x7c, 0xc7, 0xc0, + 0x5f, 0x6e, 0x53, 0xfd, 0xbf, 0xf9, 0x94, 0xc2, 0x23, 0xab, 0xa2, 0xc1, + 0x37, 0x15, 0x1b, 0x6a, 0x32, 0x0f, 0x5b, 0x7f, 0x8c, 0xdd, 0x60, 0x03, + 0xba, 0xa6, 0x60, 0x20, 0x16, 0x29, 0x90, 0x62, 0x40, 0x99, 0xf3, 0xcf, + 0x56, 0xd6, 0x8b, 0x74, 0xe9, 0x6e, 0xe0, 0x92, 0x40, 0xf2, 0xcf, 0x11, + 0xe3, 0x95, 0x4e, 0x75, 0xb2, 0x61, 0xef, 0x9e, 0x8e, 0x35, 0x51, 0xc6, + 0xc0, 0x0f, 0x41, 0xe9, 0xeb, 0x17, 0x42, 0x12, 0x03, 0xa4, 0x56, 0x53, + 0x88, 0xc3, 0x21, 0xc1, 0x32, 0x5f, 0x72, 0xeb, 0x10, 0xc2, 0x8a, 0x9d, + 0xee, 0xdd, 0xcb, 0x48, 0x06, 0xf6, 0x25, 0x38, 0x2b, 0x37, 0xf0, 0xbe, + 0xcf, 0x77, 0x93, 0x6b, 0x7f, 0x83, 0xd2, 0x6b, 0xf1, 0xee, 0x1f, 0xe0, + 0x5e, 0x8a, 0x00, 0x05, 0xa4, 0x05, 0x8c, 0x67, 0x8e, 0xb5, 0x69, 0xe3, + 0x39, 0x42, 0x3e, 0x7c, 0x84, 0x43, 0x05, 0xf4, 0xa1, 0x8b, 0x11, 0x60, + 0xa0, 0xc4, 0x30, 0x51, 0x3f, 0xad, 0x71, 0x58, 0x96, 0xb6, 0x2b, 0x9d, + 0x6e, 0x24, 0x68, 0x23, 0x2a, 0xe3, 0x75, 0xf5, 0xf3, 0xc0, 0x05, 0x62, + 0x45, 0xeb, 0x46, 0x16, 0xba, 0x11, 0xa6, 0x02, 0x94, 0x10, 0xa9, 0x55, + 0xaf, 0x09, 0xf0, 0x75, 0x95, 0xfe, 0xfa, 0x03, 0xe5, 0x51, 0x6c, 0x95, + 0xa4, 0xcf, 0xcd, 0x66, 0x04, 0x6b, 0xe2, 0xa4, 0xf7, 0xb3, 0xab, 0x27, + 0x4b, 0x21, 0xc0, 0xa4, 0xf1, 0x26, 0xc4, 0x82, 0xc9, 0x34, 0xc7, 0x9d, + 0xcb, 0xbd, 0x69, 0x16, 0xf3, 0xb8, 0x87, 0xb2, 0x60, 0x04, 0x72, 0x49, + 0x5c, 0x83, 0x35, 0xde, 0x12, 0x1c, 0x77, 0x20, 0xf2, 0x9a, 0xe5, 0x6f, + 0x5c, 0xcf, 0x9b, 0x99, 0xc9, 0xce, 0x56, 0x55, 0xc5, 0xe1, 0xd1, 0x5d, + 0x67, 0x89, 0x5a, 0xf0, 0xde, 0xe5, 0x86, 0xbc, 0x49, 0x1a, 0x97, 0x24, + 0x1f, 0x7e, 0xff, 0x43, 0x4b, 0xb7, 0x9a, 0xad, 0x83, 0x1d, 0xb0, 0x69, + 0x57, 0x81, 0xe6, 0xb5, 0x12, 0xe8, 0x70, 0x24, 0x07, 0xa7, 0xd7, 0x48 +}; +/* K = 06f085f77088ec97cebe5397a588369e3dc15b70f2a5316a6dd5f94967fe3dbc */ +static const uint8_t ac_dsa_vect239_out[] = { +/* R */ + 0x0f, 0xda, 0x7a, 0x8a, 0x3e, 0x5d, 0x32, 0x4f, 0xc0, 0xa1, 0xc2, 0x84, + 0x1c, 0xd2, 0x2f, 0x98, 0x75, 0x7a, 0x0c, 0x6a, 0x2a, 0x46, 0x5b, 0x0d, + 0x9d, 0x65, 0xbd, 0xa9, 0xb2, 0x3b, 0x3c, 0x1a, +/* S */ + 0x40, 0x86, 0x02, 0x65, 0x22, 0x90, 0x85, 0x45, 0x3f, 0xe5, 0x84, 0x87, + 0xa9, 0x33, 0xed, 0xf3, 0xc2, 0x84, 0x33, 0x69, 0x4c, 0x7b, 0x85, 0xf6, + 0x37, 0x0d, 0x9a, 0x47, 0x83, 0x16, 0x82, 0x37 +}; +#define ac_dsa_vect240_prime ac_dsa_vect226_prime +#define ac_dsa_vect240_sub_prime ac_dsa_vect226_sub_prime +#define ac_dsa_vect240_base ac_dsa_vect226_base +static const uint8_t ac_dsa_vect240_ptx[] = { +/* Msg */ + 0xe2, 0x45, 0x6e, 0xf5, 0xd4, 0x65, 0x73, 0x1b, 0x97, 0x6f, 0x2a, 0xd1, + 0xfc, 0x94, 0x63, 0x4c, 0x05, 0x69, 0xa0, 0xff, 0x75, 0x66, 0xa4, 0x9d, + 0x47, 0xd6, 0x9e, 0x60, 0xb3, 0xb6, 0xd7, 0xeb, 0x2a, 0xb2, 0x5c, 0xd4, + 0x9c, 0x93, 0x12, 0x99, 0x79, 0x6b, 0xff, 0x7e, 0x97, 0x74, 0x07, 0x5e, + 0xa2, 0x0a, 0x97, 0x2e, 0x39, 0x49, 0xa2, 0x9d, 0xfb, 0x50, 0xb2, 0xb5, + 0x61, 0x3b, 0x45, 0xc5, 0x96, 0xca, 0x5d, 0xab, 0x28, 0x2f, 0xf1, 0x83, + 0xf5, 0x64, 0xa0, 0x63, 0x11, 0xa4, 0x96, 0x01, 0xa1, 0xe8, 0x56, 0x0d, + 0x43, 0xc6, 0xa4, 0x81, 0xce, 0x71, 0x3f, 0x46, 0xc6, 0xea, 0x85, 0xbf, + 0x4c, 0x16, 0x48, 0x9f, 0xbd, 0x72, 0xcf, 0x55, 0x2b, 0x26, 0x51, 0x62, + 0x98, 0xbc, 0x66, 0x94, 0x2a, 0x05, 0xd5, 0xa8, 0xe6, 0xd0, 0xf6, 0xa8, + 0x8f, 0x3e, 0x67, 0x8d, 0x31, 0x0e, 0x29, 0x7b +}; +static const uint8_t ac_dsa_vect240_priv_val[] = { +/* X */ + 0x28, 0x6d, 0x3c, 0xec, 0x1d, 0x2a, 0xd2, 0xa8, 0x5f, 0x0f, 0x16, 0x32, + 0x45, 0x26, 0x74, 0x38, 0xf7, 0xd7, 0xd6, 0x21, 0x49, 0xba, 0x9e, 0x59, + 0xa1, 0x8d, 0xff, 0xfa, 0xef, 0xe4, 0x43, 0x58 +}; +static const uint8_t ac_dsa_vect240_pub_val[] = { +/* Y */ + 0xdc, 0x9d, 0x68, 0xb5, 0x3f, 0x35, 0xc2, 0x9f, 0x7c, 0xa0, 0x03, 0xa2, + 0x58, 0x3e, 0xc8, 0xf8, 0xef, 0x5d, 0x78, 0xa0, 0xe4, 0x5d, 0xb3, 0xc8, + 0x84, 0xd3, 0x5d, 0xf4, 0xfb, 0x53, 0x1a, 0x08, 0x0e, 0xe3, 0x83, 0x1b, + 0xff, 0xd3, 0xc7, 0x56, 0xea, 0x50, 0x42, 0xc7, 0x61, 0x45, 0x70, 0xfb, + 0xa2, 0xf6, 0xca, 0x48, 0x70, 0xdb, 0x4a, 0x45, 0x3d, 0x0f, 0x79, 0x3f, + 0xb4, 0xd0, 0x22, 0x5d, 0x94, 0xf2, 0x74, 0x12, 0xdb, 0xdf, 0x43, 0x43, + 0x2f, 0x52, 0xcb, 0x8f, 0x86, 0x7f, 0xe5, 0xf4, 0x92, 0xa8, 0x87, 0x6d, + 0x7b, 0xd8, 0x50, 0xd8, 0x99, 0xba, 0x2f, 0x0a, 0x53, 0x82, 0x0c, 0x44, + 0x08, 0x41, 0xfe, 0x0c, 0xb7, 0x6f, 0xe0, 0x44, 0x4b, 0xd6, 0xc3, 0x23, + 0x57, 0x85, 0xa3, 0xda, 0x30, 0x81, 0xfe, 0xf9, 0x9f, 0x53, 0xa1, 0x95, + 0x31, 0x4a, 0xef, 0xe9, 0x55, 0xf2, 0x96, 0x4c, 0x56, 0x50, 0x6f, 0xcc, + 0x96, 0x9b, 0x67, 0xb3, 0x23, 0x76, 0x6d, 0x29, 0x9c, 0x0b, 0x02, 0x98, + 0x1c, 0x72, 0xa2, 0xce, 0x3d, 0x75, 0x24, 0xae, 0x6f, 0x08, 0x45, 0x87, + 0x95, 0xfd, 0x32, 0xe3, 0x1b, 0x47, 0xaa, 0x1f, 0x97, 0x4e, 0x35, 0x60, + 0x81, 0x16, 0x3c, 0xb2, 0x3e, 0xfd, 0x73, 0xa9, 0xe6, 0x55, 0xde, 0xef, + 0xe5, 0xe7, 0x34, 0xce, 0xb5, 0x8e, 0x88, 0xa9, 0xdb, 0xb5, 0x24, 0xef, + 0xf7, 0xe1, 0x1c, 0x3e, 0x30, 0x68, 0x07, 0x02, 0xd8, 0x56, 0x0d, 0xd8, + 0xb6, 0xad, 0x9f, 0x61, 0xe7, 0x24, 0x6c, 0x6d, 0xde, 0x16, 0x4e, 0x91, + 0x49, 0x51, 0xd6, 0xa0, 0x57, 0x31, 0x52, 0xec, 0x8b, 0xde, 0xa6, 0x79, + 0xdc, 0xa1, 0x98, 0x5b, 0xcf, 0x26, 0x73, 0x04, 0xd5, 0xf1, 0xbc, 0xe2, + 0xf3, 0x2b, 0xb9, 0x94, 0x6a, 0x05, 0x68, 0x57, 0x35, 0x9a, 0xfb, 0xaf, + 0xfa, 0x59, 0xbe, 0xe6, 0x1a, 0xd9, 0x60, 0xc5, 0x67, 0xef, 0xe3, 0xf1, + 0x14, 0x5a, 0x8a, 0x87, 0xc2, 0x49, 0x1f, 0xa6, 0xb3, 0x3f, 0x7e, 0x71, + 0xfc, 0xdd, 0x8f, 0x1f, 0xfb, 0xcd, 0x2b, 0x89, 0x92, 0x09, 0x07, 0xd1, + 0x14, 0x4a, 0x8c, 0xf0, 0x57, 0x3f, 0x5b, 0x89, 0x21, 0x7b, 0xc0, 0x59, + 0x8c, 0x6e, 0x17, 0x54, 0xf1, 0xae, 0x7d, 0x9d, 0x42, 0xa6, 0x08, 0xa0, + 0x51, 0x62, 0x14, 0x19, 0xda, 0x91, 0xd1, 0x1b, 0xda, 0x9b, 0xb9, 0xdf, + 0xa7, 0x11, 0x8e, 0x4b, 0x66, 0x3e, 0x7b, 0xff, 0xe6, 0xe9, 0x94, 0x6c, + 0x77, 0xce, 0x9f, 0x80, 0x86, 0xdf, 0xc8, 0x22, 0xa7, 0xef, 0x72, 0x88, + 0x88, 0xb3, 0x16, 0x54, 0xa1, 0x9b, 0x6d, 0xeb, 0xd2, 0xca, 0x62, 0xf5, + 0xe3, 0xb4, 0xe2, 0x89, 0x81, 0x04, 0x35, 0xb3, 0x63, 0xec, 0xab, 0x51, + 0x1f, 0x47, 0xe9, 0xe1, 0x57, 0xf0, 0xf4, 0x19, 0x88, 0x62, 0xca, 0x13 +}; +/* K = 183ca3afd082bf3de19e89faffc5cfa7dd713a873c02c723279b3091f9bc627c */ +static const uint8_t ac_dsa_vect240_out[] = { +/* R */ + 0x77, 0x86, 0x40, 0xce, 0x75, 0xda, 0x58, 0x4a, 0x6a, 0x83, 0xf9, 0x79, + 0x4c, 0x4f, 0xfd, 0xbe, 0x30, 0x41, 0x1b, 0xe4, 0x30, 0x27, 0x75, 0x8c, + 0x74, 0xf8, 0x9f, 0x7c, 0xcc, 0x7f, 0x39, 0x83, +/* S */ + 0x61, 0x25, 0x48, 0x1e, 0x10, 0x3f, 0x78, 0x03, 0xb2, 0xf1, 0x6d, 0x9a, + 0x4d, 0x00, 0xf8, 0x81, 0xe0, 0xb3, 0x67, 0x02, 0x4d, 0xf5, 0x82, 0x2f, + 0x7c, 0xbe, 0xb5, 0x71, 0x1e, 0x0e, 0x44, 0x01 +}; +/* [mod = L=3072, N=256, SHA-224] */ +static const uint8_t ac_dsa_vect241_prime[] = { +/* P */ + 0xf6, 0x3b, 0x3c, 0xdd, 0x64, 0x6d, 0x8e, 0x7d, 0xdb, 0x57, 0x21, 0x6a, + 0xa6, 0xee, 0xc2, 0x13, 0x4d, 0x70, 0x74, 0x88, 0xa1, 0xf2, 0x9c, 0xfa, + 0x99, 0x70, 0x64, 0x5f, 0x12, 0x27, 0xea, 0x5d, 0xb2, 0xe3, 0x18, 0xee, + 0xa5, 0xda, 0x16, 0x87, 0xc7, 0xed, 0x90, 0x50, 0x96, 0x69, 0x34, 0x5e, + 0xd6, 0x13, 0x4c, 0xff, 0x32, 0x20, 0x3a, 0xb7, 0x2a, 0xec, 0xbf, 0xa6, + 0x93, 0xd2, 0x16, 0xae, 0xb5, 0x5d, 0x8d, 0x28, 0xa9, 0x81, 0xf4, 0xab, + 0xff, 0x07, 0xd1, 0x31, 0x9a, 0x79, 0x9b, 0xe5, 0xdd, 0x74, 0x6f, 0x84, + 0x84, 0x28, 0x17, 0x92, 0x9c, 0x30, 0x5b, 0x40, 0x85, 0x98, 0xaf, 0x12, + 0x04, 0x5d, 0xaa, 0x2f, 0x1c, 0xcc, 0x8b, 0xe4, 0xd8, 0x1b, 0x51, 0x3c, + 0x63, 0x0f, 0x01, 0x7f, 0xec, 0x16, 0x58, 0xac, 0xa1, 0x08, 0xa1, 0xaf, + 0x61, 0x20, 0xec, 0x05, 0xe3, 0x01, 0x8c, 0x42, 0x53, 0xc9, 0xdd, 0x35, + 0xbc, 0xe0, 0x62, 0xb7, 0x3d, 0x0f, 0x2a, 0x93, 0xd4, 0x1c, 0x48, 0x1a, + 0x5c, 0x43, 0xbb, 0x97, 0x90, 0x96, 0x82, 0xd3, 0x9a, 0x9a, 0x60, 0xdc, + 0x3c, 0x35, 0xe3, 0x63, 0x75, 0xde, 0xc6, 0xce, 0xd0, 0xd2, 0xdb, 0x3b, + 0xa0, 0xd1, 0x11, 0xbe, 0xde, 0xa7, 0x01, 0xa0, 0xe4, 0x75, 0x36, 0x24, + 0x97, 0x7a, 0x9e, 0x75, 0xb7, 0x0a, 0x74, 0xe2, 0xb8, 0x1e, 0x38, 0xa5, + 0x2a, 0xb2, 0x2d, 0xa1, 0x31, 0xb3, 0x54, 0x16, 0xd3, 0xce, 0xc9, 0x66, + 0x30, 0x79, 0x74, 0x6a, 0x76, 0x34, 0x76, 0xe5, 0x75, 0x98, 0x14, 0x2e, + 0x39, 0x86, 0x15, 0x45, 0xda, 0xaf, 0x8d, 0x38, 0xa1, 0x76, 0xf2, 0x6c, + 0x71, 0xf5, 0xaf, 0xeb, 0xd9, 0xc5, 0x62, 0x0d, 0xa8, 0x0c, 0xf3, 0x45, + 0x2b, 0x55, 0xc3, 0x7c, 0x66, 0x1b, 0x4a, 0x1e, 0xc0, 0x35, 0x17, 0x10, + 0xb9, 0xde, 0x4a, 0x3c, 0xbe, 0x0b, 0x98, 0xb4, 0xd9, 0xec, 0x89, 0x12, + 0x8d, 0x97, 0xaa, 0x7e, 0xfb, 0x19, 0xdb, 0x8b, 0xa4, 0x3c, 0xc0, 0xbe, + 0x25, 0xc2, 0x00, 0xf9, 0x0e, 0x15, 0x06, 0xcb, 0x78, 0xec, 0x0c, 0x33, + 0x6d, 0x7a, 0x95, 0x61, 0x3d, 0x42, 0x04, 0xe8, 0xed, 0x68, 0xd0, 0xf0, + 0xa6, 0xc7, 0x84, 0x20, 0x10, 0x5a, 0x8d, 0x2d, 0x43, 0x8f, 0xbd, 0x25, + 0x51, 0xa6, 0x4a, 0x1a, 0x0b, 0x03, 0xff, 0xb8, 0x78, 0x74, 0x2f, 0x8c, + 0x99, 0x79, 0xcf, 0xa8, 0x73, 0x94, 0x15, 0x02, 0x81, 0x99, 0x8d, 0x51, + 0x70, 0x1d, 0x5f, 0xcf, 0xa9, 0x69, 0x6a, 0x49, 0x89, 0xfd, 0x25, 0xf4, + 0x00, 0x95, 0x5e, 0x62, 0x6b, 0x1a, 0xbe, 0x92, 0x6c, 0x0a, 0xfa, 0x69, + 0xaa, 0x69, 0x81, 0x90, 0x0e, 0xff, 0xcd, 0xd0, 0x30, 0x59, 0x2f, 0x82, + 0xb2, 0x04, 0x2a, 0x47, 0xa9, 0xa5, 0xa8, 0xcb, 0x02, 0x83, 0xdc, 0x4d +}; +static const uint8_t ac_dsa_vect241_sub_prime[] = { +/* Q */ + 0x80, 0x00, 0x00, 0x00, 0xba, 0x46, 0x34, 0xb5, 0xfa, 0x4d, 0xa0, 0x54, + 0xbd, 0x0c, 0xa4, 0x8a, 0xe4, 0x90, 0xe5, 0x77, 0x11, 0xf3, 0x81, 0x19, + 0x38, 0x42, 0x42, 0x91, 0x59, 0xba, 0x7c, 0xa1 +}; +static const uint8_t ac_dsa_vect241_base[] = { +/* G */ + 0x8a, 0xd4, 0x55, 0x3c, 0x4e, 0x49, 0xaa, 0x24, 0x72, 0x8a, 0xb5, 0x02, + 0x44, 0x17, 0xb1, 0x32, 0xd2, 0xca, 0x53, 0xa5, 0x5d, 0x95, 0x94, 0x58, + 0xf2, 0xf7, 0x59, 0xad, 0xb0, 0x43, 0x5b, 0xee, 0xef, 0xa3, 0xa2, 0xcf, + 0xcd, 0x00, 0x38, 0xe2, 0x42, 0x06, 0x43, 0xfc, 0x4a, 0x4d, 0xee, 0xb5, + 0xd9, 0xfe, 0xaa, 0x1e, 0xdf, 0x21, 0x19, 0x3b, 0x40, 0xe1, 0x4b, 0x42, + 0x98, 0x2a, 0x94, 0xf3, 0x5c, 0x58, 0xb8, 0x11, 0x47, 0xd7, 0x18, 0x9d, + 0x26, 0x3c, 0x9b, 0x12, 0xfe, 0x63, 0xab, 0x9f, 0xa5, 0xf6, 0xf0, 0x3a, + 0x28, 0x60, 0xc1, 0x86, 0x43, 0x2e, 0x3a, 0xb0, 0x4f, 0x2a, 0xb0, 0xf2, + 0xfb, 0x61, 0x47, 0xbd, 0x9b, 0xf7, 0xed, 0x5d, 0x20, 0x71, 0x3b, 0x9d, + 0xa2, 0x13, 0x83, 0xe2, 0xc3, 0xa1, 0x68, 0xe7, 0xd0, 0x9d, 0x3d, 0x8a, + 0x5a, 0x05, 0x8f, 0xd2, 0x30, 0x95, 0xb5, 0xac, 0xfe, 0xb8, 0x64, 0xa3, + 0x30, 0x6b, 0xe2, 0x42, 0x5f, 0xa1, 0xad, 0x32, 0xad, 0x6d, 0x93, 0x82, + 0xe6, 0x03, 0xb0, 0x3c, 0x68, 0xaf, 0x4a, 0xf0, 0x24, 0x63, 0x97, 0x10, + 0x2c, 0x41, 0x55, 0xcb, 0xa8, 0x11, 0xab, 0xf9, 0x9d, 0xa7, 0x83, 0x9e, + 0x77, 0xb2, 0xea, 0xc9, 0x97, 0x05, 0x88, 0xca, 0x1d, 0x0a, 0x23, 0x61, + 0x72, 0x3a, 0x16, 0x4a, 0xc9, 0x22, 0x9c, 0x2e, 0x80, 0xdc, 0xfa, 0x8d, + 0xb4, 0xf9, 0xe2, 0x98, 0x03, 0xef, 0xfb, 0x31, 0x68, 0xc7, 0xfe, 0xd7, + 0xa3, 0xa6, 0xde, 0x40, 0xdd, 0xa1, 0x9a, 0x05, 0x36, 0xaf, 0x9b, 0x5b, + 0x7a, 0xfa, 0xef, 0xb9, 0xc7, 0x0d, 0x6a, 0xe8, 0xdf, 0x12, 0xda, 0x65, + 0x8f, 0x62, 0x36, 0x04, 0x3a, 0xea, 0x87, 0x3d, 0xb2, 0x9c, 0xeb, 0x6f, + 0x07, 0xd1, 0x08, 0xf5, 0x22, 0x56, 0x87, 0xbd, 0x0c, 0x30, 0xe3, 0x08, + 0x4e, 0x20, 0x90, 0xb4, 0x5a, 0xe2, 0xf9, 0x2a, 0x97, 0xb8, 0xec, 0xb7, + 0xa9, 0x70, 0x5c, 0x49, 0x56, 0xb8, 0xb3, 0x1c, 0x4a, 0x3d, 0x61, 0x10, + 0x7c, 0x84, 0xe4, 0x7a, 0xdd, 0xa6, 0xc8, 0x0d, 0x5d, 0x22, 0xda, 0xb3, + 0xd8, 0x59, 0x22, 0x0f, 0x9d, 0x5a, 0xab, 0x13, 0x67, 0x7a, 0xe3, 0xdf, + 0x16, 0x8f, 0x0c, 0x17, 0x6d, 0x17, 0x6b, 0x54, 0x50, 0x6c, 0x63, 0x98, + 0x53, 0xf0, 0x4d, 0xde, 0xf2, 0x72, 0x2f, 0x39, 0xc1, 0x8e, 0x5c, 0xe4, + 0x26, 0xe1, 0x45, 0x62, 0xad, 0x8f, 0xf2, 0x62, 0x47, 0xaf, 0x88, 0x87, + 0x0e, 0xfb, 0x72, 0xc0, 0xcc, 0xe8, 0x36, 0xde, 0x8f, 0xee, 0x67, 0xa6, + 0x62, 0x37, 0x82, 0x45, 0xb5, 0x02, 0xbf, 0x1f, 0x83, 0x09, 0x99, 0x88, + 0xa0, 0x93, 0xce, 0x7c, 0xdc, 0x81, 0x36, 0x4c, 0x78, 0xb1, 0xf4, 0xa5, + 0x1b, 0x80, 0x0d, 0xf6, 0x13, 0x7c, 0x71, 0xd6, 0x5e, 0x6b, 0x08, 0x9a +}; +static const uint8_t ac_dsa_vect241_ptx[] = { +/* Msg */ + 0x95, 0x79, 0x73, 0xfc, 0x3f, 0x3f, 0xe3, 0xf5, 0x59, 0x06, 0x5b, 0xe5, + 0xd4, 0xa0, 0xc2, 0x81, 0xcf, 0x17, 0x95, 0x90, 0x18, 0xb9, 0xa6, 0x70, + 0xd2, 0xb3, 0x70, 0x6d, 0x41, 0xd5, 0x81, 0x2e, 0x37, 0x30, 0x10, 0x05, + 0xf8, 0xb7, 0x0e, 0xbd, 0x2f, 0xba, 0x3c, 0x40, 0xa3, 0xf3, 0x77, 0xa7, + 0x51, 0xb6, 0xcb, 0x96, 0x93, 0xe3, 0xcb, 0x00, 0xd9, 0x28, 0x88, 0x24, + 0x7d, 0x07, 0x92, 0x1d, 0x3c, 0x1e, 0x92, 0x57, 0xce, 0x08, 0x73, 0x3b, + 0x89, 0x26, 0xe0, 0xdf, 0x7b, 0xdb, 0x6e, 0x85, 0x5f, 0x1f, 0x85, 0x10, + 0x75, 0xd4, 0xe6, 0x28, 0xd1, 0x10, 0xd4, 0x2b, 0x64, 0x3b, 0x54, 0x87, + 0x6e, 0x5f, 0xaa, 0x36, 0x11, 0x47, 0x7e, 0xe6, 0x83, 0x71, 0x56, 0x25, + 0x55, 0x26, 0x9e, 0xd6, 0x2a, 0x92, 0x71, 0xba, 0xd5, 0x0c, 0xc4, 0xd4, + 0x60, 0x38, 0xde, 0x2d, 0xd4, 0x19, 0x20, 0xc2 +}; +static const uint8_t ac_dsa_vect241_priv_val[] = { +/* X */ + 0x52, 0x4a, 0x7e, 0xa5, 0x97, 0x7f, 0x81, 0x02, 0xb3, 0x55, 0x29, 0x30, + 0x47, 0x7f, 0x5f, 0x04, 0x24, 0x01, 0x16, 0x5d, 0x46, 0x37, 0xdc, 0xd8, + 0xb9, 0xd1, 0x3d, 0xf4, 0xf3, 0xaa, 0xe5, 0xd0 +}; +static const uint8_t ac_dsa_vect241_pub_val[] = { +/* Y */ + 0x42, 0x24, 0x35, 0x39, 0xe4, 0x9d, 0xb9, 0xea, 0x19, 0xd9, 0x8d, 0x97, + 0xf6, 0xf2, 0xa9, 0x4b, 0x23, 0x52, 0x98, 0x12, 0xdf, 0x88, 0x9e, 0xaa, + 0xbc, 0xfe, 0xda, 0x01, 0xce, 0x4c, 0x75, 0x94, 0x87, 0xfb, 0x89, 0xbc, + 0x82, 0xda, 0x75, 0xfe, 0x1c, 0x91, 0x34, 0x36, 0x1f, 0x86, 0xde, 0x47, + 0xd1, 0x6d, 0x8e, 0xee, 0x80, 0xe5, 0x6a, 0xc5, 0x02, 0x17, 0x8e, 0x8e, + 0xd8, 0x12, 0x94, 0x77, 0xaf, 0x8b, 0xfb, 0xd8, 0x26, 0x2c, 0x5e, 0xdd, + 0x93, 0x7e, 0x1a, 0x86, 0xc0, 0xf0, 0xe7, 0xb2, 0xaf, 0xe7, 0xbc, 0xbd, + 0xdf, 0xcb, 0x58, 0x14, 0xce, 0xd0, 0xb7, 0x56, 0xa7, 0x6c, 0xa1, 0x78, + 0x42, 0x3b, 0xb4, 0xd5, 0x78, 0xc5, 0xda, 0x18, 0x37, 0x12, 0xd9, 0x68, + 0x58, 0x26, 0x40, 0xaa, 0x0e, 0xc7, 0xe9, 0xfb, 0x56, 0xbf, 0xd9, 0x60, + 0xd7, 0xa5, 0x75, 0x49, 0x74, 0x7d, 0x8f, 0xb7, 0xad, 0xe4, 0x7c, 0xfe, + 0x81, 0x6c, 0x1e, 0x57, 0xda, 0x66, 0x33, 0xda, 0xcc, 0x53, 0x7d, 0xe0, + 0x60, 0x81, 0x39, 0x64, 0xbb, 0x5b, 0x27, 0x57, 0xa3, 0x12, 0xf9, 0xda, + 0x3d, 0x84, 0xe6, 0x0a, 0xff, 0x98, 0x17, 0x00, 0x51, 0xd3, 0xd9, 0x0e, + 0x38, 0x0b, 0x8b, 0xcc, 0x19, 0x86, 0xc5, 0x8f, 0xf9, 0xdc, 0x91, 0xe8, + 0x82, 0x7d, 0x4f, 0x9f, 0x5f, 0xc4, 0xb2, 0xb2, 0xe7, 0x43, 0xcf, 0x93, + 0x89, 0xff, 0x02, 0xde, 0xc0, 0x1f, 0x5d, 0x43, 0x4b, 0x43, 0x0d, 0x16, + 0x2e, 0x89, 0x1c, 0x33, 0x55, 0xf9, 0x18, 0x55, 0x33, 0x9f, 0x8d, 0xf5, + 0x83, 0x00, 0xe4, 0xc9, 0x93, 0xae, 0x4d, 0xf8, 0xc4, 0x31, 0x8b, 0x5c, + 0x4b, 0xd0, 0x52, 0x83, 0xca, 0x4b, 0x46, 0xb7, 0xd2, 0xfb, 0x0f, 0x64, + 0x76, 0xbf, 0x15, 0x90, 0x7f, 0x50, 0xdd, 0x41, 0x41, 0xaa, 0x7a, 0xca, + 0xc9, 0xda, 0xa6, 0x2e, 0xcc, 0xd3, 0xa6, 0x73, 0x57, 0x12, 0x20, 0x60, + 0xb6, 0xce, 0xce, 0x04, 0x46, 0xa9, 0x3e, 0xb2, 0x30, 0xad, 0x93, 0xbc, + 0x9a, 0x4d, 0x1b, 0x1e, 0xfe, 0xec, 0xa1, 0xe3, 0xfc, 0x83, 0xc1, 0x19, + 0x78, 0x50, 0x35, 0xb4, 0x39, 0x50, 0x9f, 0xfb, 0x79, 0x68, 0xb1, 0xa4, + 0x48, 0xb7, 0xbd, 0x83, 0x15, 0x75, 0x3f, 0xdf, 0x04, 0xa2, 0x56, 0xec, + 0xa1, 0x56, 0x2a, 0x11, 0xb0, 0x96, 0xc9, 0x0a, 0x36, 0xb3, 0x53, 0x65, + 0x9c, 0xbd, 0xe4, 0x42, 0x0e, 0x17, 0xe9, 0x0b, 0x94, 0xc4, 0x3c, 0x75, + 0x19, 0xc6, 0x06, 0x41, 0xce, 0xec, 0x05, 0x6f, 0x89, 0x7b, 0x97, 0xd6, + 0xbb, 0x18, 0x61, 0x26, 0x8e, 0x0d, 0xc7, 0x9b, 0x7c, 0x3b, 0x6b, 0x76, + 0x39, 0xc2, 0x55, 0xbf, 0x06, 0x86, 0x57, 0x37, 0x45, 0x91, 0x26, 0xcb, + 0x46, 0x5b, 0xc1, 0xda, 0x4a, 0x04, 0x3a, 0x19, 0x63, 0xda, 0x7d, 0x63 +}; +/* K = 29e4d7790e181b4767903fe0eb37757f33f13337c33588c1fdbfba0e655ab621 */ +static const uint8_t ac_dsa_vect241_out[] = { +/* R */ + 0x2e, 0x59, 0xd5, 0xf3, 0x0f, 0x73, 0x78, 0x1d, 0x38, 0x25, 0x5b, 0x70, + 0xde, 0xde, 0xeb, 0x38, 0xae, 0x78, 0xdf, 0x4f, 0x00, 0x2c, 0x1f, 0x74, + 0x7c, 0x08, 0xde, 0xad, 0xc6, 0x53, 0x01, 0x55, +/* S */ + 0x61, 0x5c, 0x55, 0xb2, 0xdf, 0x0c, 0xa2, 0x8c, 0x60, 0xa6, 0xb3, 0x85, + 0xc5, 0x8f, 0xa0, 0x36, 0xdf, 0x8c, 0x4b, 0x2f, 0x4f, 0x19, 0x35, 0x73, + 0x0b, 0xf8, 0xf4, 0xf0, 0xbe, 0xd1, 0x36, 0x10 +}; +#define ac_dsa_vect242_prime ac_dsa_vect241_prime +#define ac_dsa_vect242_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect242_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect242_ptx[] = { +/* Msg */ + 0x54, 0x07, 0x1a, 0xca, 0x28, 0x96, 0x97, 0x49, 0xce, 0x2e, 0x2d, 0xc8, + 0x55, 0x05, 0x20, 0x19, 0xbe, 0xc2, 0x7d, 0x0d, 0xd6, 0xa3, 0x10, 0x21, + 0x93, 0x11, 0xb4, 0xb6, 0xd8, 0x22, 0x46, 0x7b, 0x22, 0xb3, 0xf0, 0x2f, + 0xb8, 0x31, 0x39, 0x93, 0xfc, 0x77, 0xc4, 0xaf, 0x1d, 0x76, 0xab, 0x9d, + 0xb9, 0x9b, 0x0b, 0x2b, 0x78, 0x20, 0x4a, 0xa4, 0x5f, 0x40, 0x32, 0xa7, + 0xd9, 0x45, 0xf9, 0x3d, 0x55, 0xbc, 0xb8, 0xa6, 0xbb, 0xd4, 0x7f, 0x98, + 0x29, 0x9a, 0x09, 0x29, 0x71, 0x04, 0x61, 0x41, 0x9e, 0xdb, 0xe1, 0x13, + 0x2d, 0xc2, 0x25, 0x75, 0xf5, 0xaf, 0xbe, 0x70, 0x78, 0xcf, 0x5f, 0x05, + 0xb2, 0x31, 0x00, 0x0f, 0x4a, 0x0f, 0x9f, 0x36, 0x7d, 0x90, 0x25, 0xed, + 0x3a, 0xe1, 0x78, 0x6e, 0x01, 0x83, 0xea, 0xc9, 0x3e, 0xa9, 0x6b, 0x55, + 0x30, 0x4a, 0x8c, 0x2d, 0xbf, 0x69, 0x08, 0x21 +}; +static const uint8_t ac_dsa_vect242_priv_val[] = { +/* X */ + 0x4b, 0x2d, 0x62, 0xd0, 0xe7, 0xb8, 0x84, 0x36, 0x73, 0x7d, 0x03, 0xd6, + 0xf6, 0x4d, 0xd6, 0xa6, 0xdd, 0x07, 0x57, 0x02, 0x18, 0x17, 0x16, 0x9b, + 0xa3, 0x73, 0xe3, 0xa3, 0x1b, 0xc1, 0x2c, 0xb7 +}; +static const uint8_t ac_dsa_vect242_pub_val[] = { +/* Y */ + 0xef, 0x78, 0x15, 0x2e, 0xfd, 0x88, 0x13, 0x0a, 0x4f, 0xec, 0xfe, 0x23, + 0x50, 0x37, 0xde, 0x23, 0x09, 0xb1, 0xe2, 0xf3, 0x22, 0xd4, 0xf4, 0x15, + 0x47, 0x56, 0xca, 0xa8, 0xf0, 0xb3, 0xe4, 0x1b, 0xe4, 0x5c, 0x80, 0xd8, + 0x95, 0xde, 0x56, 0x38, 0x92, 0x57, 0xc3, 0x91, 0x30, 0x72, 0x86, 0xbe, + 0x8e, 0x87, 0x09, 0xb8, 0x01, 0x86, 0xe2, 0x72, 0x41, 0x72, 0xb0, 0xf2, + 0x97, 0x4b, 0xe5, 0x91, 0x58, 0x49, 0x16, 0xfc, 0x0e, 0x75, 0x0c, 0x0c, + 0xaf, 0x83, 0xd8, 0x39, 0xb5, 0xc2, 0x48, 0xf5, 0xde, 0x65, 0x86, 0x68, + 0x66, 0x5f, 0x00, 0x4b, 0xab, 0x8a, 0xd3, 0x10, 0x11, 0x88, 0x35, 0x95, + 0x7c, 0x02, 0xda, 0x6a, 0xe9, 0xa2, 0xa7, 0x9d, 0xa0, 0x39, 0xad, 0xc8, + 0x84, 0xf9, 0xeb, 0x8b, 0x62, 0xe3, 0x79, 0xe2, 0x7f, 0x54, 0x9e, 0x7f, + 0x8a, 0xff, 0x8a, 0xd2, 0xfc, 0x27, 0x6e, 0xce, 0x15, 0xf0, 0x42, 0x35, + 0x28, 0xa0, 0x9e, 0x31, 0xb2, 0x64, 0x21, 0xdf, 0x93, 0x57, 0x3b, 0xec, + 0x7a, 0x4d, 0x6c, 0x2c, 0xbf, 0xbe, 0x5c, 0xe0, 0xfc, 0xe0, 0x70, 0x20, + 0x88, 0xfb, 0x38, 0x4a, 0xd1, 0xdc, 0x35, 0xbb, 0x2c, 0x1c, 0x74, 0x2d, + 0x43, 0xd7, 0x9a, 0xd1, 0x36, 0xe7, 0x10, 0x57, 0xcb, 0x9f, 0x22, 0xca, + 0x04, 0x2e, 0x61, 0xd2, 0xc5, 0xcc, 0x4c, 0xcf, 0x5b, 0x75, 0xa7, 0x37, + 0x99, 0x22, 0xbc, 0x4f, 0xd8, 0x83, 0x72, 0xd2, 0xa8, 0xf6, 0xa2, 0x75, + 0x08, 0x65, 0xf9, 0x1c, 0x14, 0x34, 0x12, 0xa3, 0xfc, 0x61, 0xe4, 0xad, + 0x4a, 0xbd, 0x03, 0xdc, 0x1c, 0xa0, 0xfc, 0x42, 0x97, 0xab, 0x10, 0x7a, + 0x19, 0x63, 0x53, 0x3a, 0x3d, 0x80, 0xa2, 0x4a, 0xe2, 0xec, 0x41, 0x46, + 0xe8, 0x26, 0x5a, 0xcf, 0xd4, 0x44, 0x6f, 0xc2, 0x81, 0x03, 0xc5, 0x04, + 0x7c, 0x17, 0x79, 0x6c, 0x41, 0x48, 0xb8, 0xe6, 0x58, 0xe4, 0x4e, 0x9b, + 0x1c, 0x25, 0x9d, 0x63, 0xc9, 0x7f, 0x0e, 0x76, 0x6f, 0xba, 0x8d, 0x9a, + 0x73, 0x94, 0xcd, 0xb7, 0x34, 0x50, 0x8b, 0xfa, 0x09, 0xae, 0x42, 0xd2, + 0xda, 0x30, 0x68, 0xe2, 0xc8, 0x5a, 0xf2, 0x06, 0x5f, 0x61, 0x8e, 0xc3, + 0xf3, 0xc7, 0x3d, 0x73, 0xa7, 0x50, 0xc1, 0x36, 0x44, 0xc9, 0x6e, 0x3d, + 0xbb, 0xb7, 0x47, 0x43, 0x25, 0xaf, 0x48, 0xd1, 0xd1, 0x45, 0xc2, 0x8d, + 0x69, 0xf2, 0x2c, 0xbb, 0x4a, 0x90, 0x73, 0x05, 0x9a, 0x9c, 0x40, 0x89, + 0x18, 0x04, 0xc7, 0x3a, 0x22, 0x9f, 0x01, 0xce, 0xf0, 0x67, 0x8c, 0xf4, + 0x85, 0x5d, 0x18, 0xf9, 0x00, 0xf0, 0x25, 0x3a, 0xcd, 0x6b, 0x3e, 0xe5, + 0x3d, 0xd9, 0x6c, 0x4c, 0x92, 0xaf, 0xff, 0x1f, 0x30, 0x87, 0xee, 0xb4, + 0xfb, 0xa8, 0x6d, 0x2e, 0x94, 0x95, 0xc5, 0xf7, 0x34, 0xa4, 0x6c, 0xa2 +}; +/* K = 5af719a9e5d8567dc26576782e8f247517fad5ac5de0f7115c5158748fc73b40 */ +static const uint8_t ac_dsa_vect242_out[] = { +/* R */ + 0x0d, 0xeb, 0xcf, 0x6c, 0x88, 0x50, 0x4a, 0x88, 0x2a, 0x01, 0x91, 0xe6, + 0xfa, 0x4c, 0x77, 0x4c, 0x10, 0x85, 0x83, 0x62, 0x62, 0x94, 0x28, 0xaf, + 0xf2, 0x4c, 0x22, 0xe3, 0x36, 0x4b, 0xaa, 0x15, +/* S */ + 0x53, 0xd8, 0xc1, 0xdb, 0xb3, 0xa2, 0xc1, 0x02, 0x35, 0x21, 0xb7, 0x05, + 0x00, 0x5c, 0xe6, 0x35, 0x0b, 0xcf, 0x66, 0xc0, 0x93, 0x58, 0x8c, 0x35, + 0xd7, 0x68, 0xfc, 0xa2, 0x95, 0xa4, 0xa9, 0xce +}; +#define ac_dsa_vect243_prime ac_dsa_vect241_prime +#define ac_dsa_vect243_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect243_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect243_ptx[] = { +/* Msg */ + 0x49, 0xd5, 0xf2, 0x0a, 0xcf, 0x1e, 0x9d, 0x59, 0xa6, 0x56, 0xbd, 0x16, + 0x3f, 0xe4, 0x6f, 0xc8, 0x68, 0x47, 0x6c, 0xcd, 0x92, 0x63, 0x77, 0xa4, + 0x0e, 0xd3, 0xd7, 0x47, 0x6e, 0x9e, 0xb7, 0xa8, 0xa7, 0x0c, 0x4b, 0x88, + 0xb1, 0x6e, 0x79, 0x91, 0x48, 0xd2, 0x5f, 0xa2, 0x3b, 0xd0, 0xc9, 0x16, + 0x11, 0xb7, 0x6c, 0x96, 0x65, 0xf5, 0x72, 0x2f, 0x40, 0x4f, 0xd9, 0x0e, + 0xfd, 0xb8, 0xad, 0x14, 0xb7, 0x59, 0xc3, 0x49, 0xff, 0x6c, 0x83, 0x06, + 0x42, 0xd5, 0x10, 0x76, 0xcc, 0xbd, 0xc5, 0x7f, 0x15, 0x2f, 0xba, 0x41, + 0xc6, 0xa7, 0xf3, 0xcd, 0x39, 0x05, 0xfa, 0x7c, 0x85, 0x72, 0x65, 0xff, + 0xc7, 0x59, 0x6a, 0x64, 0xdc, 0x69, 0x49, 0x0a, 0x93, 0x2b, 0x95, 0xad, + 0xbc, 0x79, 0xa3, 0xb4, 0xf2, 0x1b, 0x2c, 0x6f, 0xb5, 0xd5, 0x83, 0x5d, + 0x8b, 0xca, 0xe5, 0xd4, 0x4d, 0x91, 0x2a, 0x0a +}; +static const uint8_t ac_dsa_vect243_priv_val[] = { +/* X */ + 0x4a, 0xbe, 0xf2, 0x4f, 0x71, 0x5c, 0xfb, 0x3b, 0xa6, 0xe3, 0x9c, 0x26, + 0xb0, 0x7c, 0xa4, 0x6b, 0x70, 0x0a, 0xac, 0x69, 0xfb, 0x8d, 0xf3, 0xc0, + 0xe0, 0x9b, 0xe0, 0x8d, 0xf9, 0x0e, 0x44, 0xe2 +}; +static const uint8_t ac_dsa_vect243_pub_val[] = { +/* Y */ + 0x8f, 0xf1, 0x30, 0x22, 0x08, 0x03, 0x16, 0xbe, 0xa4, 0x9b, 0x89, 0xa0, + 0x6d, 0xd5, 0xa9, 0x71, 0xd8, 0x6e, 0x0c, 0x9a, 0x3a, 0xf4, 0x14, 0x25, + 0x8a, 0x8f, 0x48, 0x50, 0x88, 0xb6, 0x6c, 0xc3, 0x8c, 0xde, 0xa0, 0x2c, + 0xdd, 0x62, 0x09, 0x6c, 0x00, 0xeb, 0x0d, 0x1c, 0x2e, 0xe6, 0x62, 0xcf, + 0xf1, 0x6f, 0x6d, 0x2d, 0x30, 0x44, 0x0b, 0x2a, 0xd9, 0xe8, 0x97, 0xb9, + 0xeb, 0x93, 0x9b, 0x12, 0x99, 0xff, 0x87, 0x95, 0x57, 0xf1, 0x63, 0xf1, + 0x7c, 0x8a, 0xc6, 0x0d, 0x0c, 0x6e, 0x99, 0x8b, 0x3a, 0x04, 0x4b, 0x43, + 0xfb, 0xfa, 0xc7, 0xb0, 0xcc, 0x30, 0xa5, 0x79, 0xa6, 0xbd, 0xa1, 0xb4, + 0xff, 0x59, 0x8a, 0x53, 0x1f, 0x9e, 0x37, 0xcc, 0x19, 0x01, 0xa7, 0xb0, + 0x8e, 0x79, 0x4a, 0x74, 0x01, 0xd0, 0xf8, 0xca, 0x4b, 0xe5, 0x5b, 0xff, + 0x7b, 0x17, 0x63, 0x21, 0x82, 0x85, 0x75, 0xa4, 0x77, 0x68, 0x6a, 0x98, + 0xb4, 0xb1, 0x72, 0x66, 0xe1, 0x01, 0x60, 0x1f, 0x43, 0x6e, 0x55, 0x4b, + 0x9e, 0x42, 0x88, 0x05, 0x79, 0x70, 0xfa, 0x34, 0x63, 0x34, 0x3e, 0x7e, + 0x52, 0xa5, 0x8c, 0xa1, 0x45, 0xec, 0x9b, 0xef, 0xd7, 0xbe, 0x31, 0xea, + 0x76, 0x6e, 0xd7, 0x4a, 0xc1, 0x78, 0xbc, 0xcd, 0xfe, 0xe9, 0xd2, 0x95, + 0x65, 0xe7, 0x93, 0x5e, 0x8d, 0x70, 0xc3, 0xeb, 0x09, 0x1e, 0x3e, 0x3b, + 0x3e, 0x6e, 0x77, 0x71, 0x69, 0x31, 0xed, 0x72, 0x9c, 0x49, 0xb9, 0x64, + 0x43, 0x60, 0x60, 0x98, 0xbd, 0x08, 0x10, 0x98, 0x9e, 0x0e, 0x6f, 0x25, + 0x3c, 0xf3, 0xec, 0x38, 0x29, 0x42, 0x31, 0xb7, 0x11, 0xb0, 0x9a, 0x94, + 0x16, 0x09, 0xac, 0xc8, 0x97, 0x68, 0x19, 0x07, 0x65, 0x43, 0x92, 0x6e, + 0xc4, 0xe0, 0x6f, 0x3e, 0x4d, 0x7f, 0x12, 0x3c, 0x2b, 0x87, 0x71, 0xe5, + 0x45, 0x89, 0xe0, 0x45, 0x24, 0xe3, 0xb4, 0xf9, 0x50, 0xda, 0x56, 0x0a, + 0x25, 0xd1, 0x21, 0x72, 0xd4, 0xeb, 0xda, 0xdc, 0x17, 0x19, 0x40, 0x0d, + 0x91, 0xcf, 0x02, 0x64, 0x70, 0x87, 0x14, 0x47, 0x92, 0x00, 0xc5, 0x0e, + 0xf0, 0x0e, 0xc0, 0xe6, 0x04, 0x90, 0x9a, 0x54, 0x6c, 0x95, 0xeb, 0x2f, + 0xa5, 0x3c, 0x65, 0xee, 0x72, 0xad, 0x53, 0xf1, 0x49, 0xc9, 0x38, 0xdc, + 0x21, 0x93, 0x49, 0x6d, 0xb0, 0x7a, 0xf3, 0xb3, 0x0a, 0x1f, 0x43, 0x97, + 0x08, 0xaa, 0x11, 0x5c, 0x8d, 0xd4, 0x7c, 0x81, 0xc1, 0xbc, 0x68, 0xea, + 0x3a, 0xbd, 0x90, 0x26, 0x11, 0x3c, 0x01, 0xeb, 0x05, 0x55, 0x8b, 0x8a, + 0x2b, 0xe9, 0x09, 0x34, 0x76, 0xf0, 0x12, 0x47, 0xbf, 0xbe, 0xb3, 0xf2, + 0x85, 0x8b, 0x13, 0xe6, 0x22, 0x8b, 0x98, 0x20, 0x5f, 0xa7, 0x10, 0xb6, + 0xaf, 0x1c, 0x5f, 0x71, 0x48, 0x0d, 0xee, 0x40, 0x1d, 0x74, 0x72, 0xd7 +}; +/* K = 5472e89286e6ccbed316fe7564e3eae899ed7bfc55ca7fb6fbc392d191304bfa */ +static const uint8_t ac_dsa_vect243_out[] = { +/* R */ + 0x19, 0xa7, 0x3b, 0x04, 0x9b, 0x16, 0x4d, 0xbf, 0x7f, 0xb2, 0x82, 0x6f, + 0x42, 0x53, 0x61, 0x7c, 0xf1, 0xc5, 0xbb, 0x46, 0xff, 0xc5, 0x20, 0x4e, + 0xfa, 0x00, 0x00, 0x2a, 0x79, 0xe2, 0x3c, 0x0b, +/* S */ + 0x7b, 0xe1, 0x37, 0xc1, 0x09, 0xe6, 0x8f, 0x33, 0x7b, 0x5a, 0x21, 0xcb, + 0x59, 0x1a, 0x87, 0xaf, 0x1c, 0xb8, 0x68, 0x14, 0x19, 0xf8, 0x75, 0xff, + 0x8f, 0x04, 0x1e, 0x82, 0x99, 0x91, 0xfe, 0x28 +}; +#define ac_dsa_vect244_prime ac_dsa_vect241_prime +#define ac_dsa_vect244_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect244_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect244_ptx[] = { +/* Msg */ + 0x11, 0x90, 0x85, 0x3e, 0xfb, 0x7e, 0x04, 0xcd, 0x49, 0x47, 0xc1, 0xea, + 0x5b, 0x1b, 0x5d, 0x9e, 0x0a, 0xc5, 0xe6, 0xdf, 0x1d, 0xd0, 0x50, 0x87, + 0x73, 0x08, 0xf1, 0xb2, 0xc7, 0xe0, 0xa4, 0x91, 0x7e, 0x58, 0x81, 0x03, + 0xd2, 0x8c, 0x0f, 0x6e, 0x8b, 0x72, 0xd9, 0x67, 0xaa, 0x06, 0xac, 0xa6, + 0x8a, 0x98, 0x6d, 0x80, 0x77, 0x40, 0xf2, 0xdd, 0xdd, 0xe7, 0x28, 0x1e, + 0x55, 0x0a, 0xf4, 0xf6, 0x37, 0xea, 0xdf, 0x61, 0xf8, 0x80, 0xc7, 0x35, + 0x1b, 0x48, 0x66, 0x15, 0x09, 0x6f, 0x6b, 0xa5, 0x0d, 0x87, 0x54, 0xbb, + 0xf9, 0xba, 0x1c, 0x49, 0xa3, 0x48, 0x58, 0x15, 0xef, 0x06, 0xb3, 0xcd, + 0x76, 0x1b, 0x55, 0x86, 0xc3, 0xfc, 0x2b, 0x46, 0x4c, 0x6f, 0xe1, 0x2c, + 0x16, 0x0a, 0xb0, 0xf6, 0xf4, 0x46, 0xfa, 0xbf, 0x74, 0x21, 0x24, 0x30, + 0xce, 0xc1, 0x5e, 0x75, 0xa5, 0x7b, 0x10, 0x2e +}; +static const uint8_t ac_dsa_vect244_priv_val[] = { +/* X */ + 0x7b, 0x25, 0x10, 0xc7, 0x3e, 0xa6, 0x44, 0x7b, 0xc3, 0x19, 0xde, 0x79, + 0xaf, 0xeb, 0xcf, 0x45, 0x48, 0x29, 0x17, 0x04, 0x2a, 0x3c, 0xa3, 0xc1, + 0xcb, 0x1c, 0x97, 0xd1, 0xa1, 0x21, 0x6b, 0x2b +}; +static const uint8_t ac_dsa_vect244_pub_val[] = { +/* Y */ + 0x9b, 0xb8, 0x1c, 0x80, 0xd2, 0xb8, 0xa6, 0x01, 0xa0, 0x9e, 0x22, 0x47, + 0x5d, 0x70, 0xd1, 0xdc, 0x55, 0x13, 0x40, 0x9f, 0xb4, 0x66, 0x8b, 0x17, + 0x6c, 0x76, 0xb3, 0xaa, 0x1a, 0xf8, 0x63, 0x0a, 0xc7, 0x79, 0x0a, 0x44, + 0x44, 0xab, 0x82, 0x37, 0x87, 0xf6, 0xf5, 0x69, 0xbd, 0xf0, 0x2b, 0x9e, + 0xef, 0x5e, 0x7b, 0xb2, 0x1a, 0x88, 0xe3, 0xd3, 0x29, 0x68, 0x57, 0xe9, + 0x19, 0x19, 0xf3, 0xc4, 0x73, 0xad, 0xd1, 0x6b, 0xcd, 0x76, 0x3f, 0x31, + 0xa2, 0xf9, 0x84, 0x4d, 0x7c, 0xbd, 0x8d, 0x48, 0x06, 0x72, 0xa0, 0x36, + 0xc4, 0xb1, 0x04, 0xbe, 0x66, 0xac, 0xd6, 0x6e, 0x6e, 0xf0, 0xe8, 0xa7, + 0x44, 0xb3, 0xd8, 0x78, 0x09, 0x0d, 0x1d, 0xe9, 0xf1, 0x05, 0x56, 0x02, + 0x47, 0xc6, 0x21, 0x53, 0xe1, 0x17, 0xef, 0xa5, 0x5e, 0xc6, 0x1c, 0x17, + 0x7c, 0xd8, 0x2f, 0x8d, 0x72, 0xc5, 0x1d, 0x25, 0x3f, 0x4d, 0xc7, 0x33, + 0x6f, 0x79, 0x82, 0x60, 0x25, 0x61, 0x9f, 0xb2, 0x10, 0x3f, 0x91, 0x14, + 0x4f, 0x90, 0xf6, 0xa6, 0x89, 0xab, 0xcc, 0x51, 0xc6, 0x8a, 0xff, 0xd2, + 0x84, 0x62, 0x57, 0x8b, 0x18, 0x3e, 0xec, 0x94, 0x20, 0x58, 0xf4, 0x8a, + 0xbf, 0x54, 0x6f, 0x73, 0x89, 0x40, 0xa6, 0xc2, 0x6d, 0x30, 0x1c, 0x4b, + 0x90, 0xca, 0x40, 0xea, 0x49, 0xc1, 0x17, 0xd6, 0x11, 0x47, 0xe8, 0x68, + 0x39, 0x89, 0xba, 0xed, 0x7a, 0x22, 0x1c, 0x4f, 0x22, 0x09, 0x2f, 0x72, + 0xb1, 0xed, 0x60, 0x4b, 0x6a, 0xa9, 0x4f, 0xf6, 0xa5, 0x74, 0xb4, 0x21, + 0x5b, 0xd6, 0xf8, 0xe9, 0xd7, 0xb6, 0x38, 0xaf, 0xa4, 0x35, 0xa3, 0x34, + 0x65, 0x89, 0xa6, 0x1b, 0x1d, 0x1d, 0xb2, 0x98, 0x9d, 0x7b, 0x45, 0xf3, + 0x23, 0x45, 0x45, 0xe8, 0xa2, 0x2d, 0x60, 0x5a, 0xd6, 0xcb, 0x03, 0x6e, + 0xf7, 0x91, 0xf6, 0x25, 0xd2, 0xc6, 0xa9, 0x95, 0xed, 0xa3, 0xe0, 0xca, + 0xfc, 0xe7, 0x04, 0xa2, 0xbf, 0x15, 0xab, 0x5d, 0xfa, 0xd0, 0x16, 0x21, + 0x04, 0x59, 0x2d, 0x23, 0xf5, 0x2a, 0xa0, 0xfe, 0xa1, 0xf4, 0x32, 0xf0, + 0xa3, 0x08, 0xd1, 0x6a, 0x45, 0xe1, 0xf4, 0x1f, 0x82, 0x32, 0x62, 0x07, + 0x4e, 0x91, 0x73, 0x75, 0x4c, 0xeb, 0xa7, 0x0c, 0xd8, 0xa3, 0x70, 0xdb, + 0xab, 0x1a, 0x14, 0xf8, 0x41, 0x59, 0x11, 0x6d, 0xa7, 0x3d, 0x3a, 0x9c, + 0xf8, 0x25, 0x94, 0xcb, 0x3a, 0xf9, 0x57, 0x97, 0xcf, 0x44, 0x42, 0x72, + 0x85, 0x05, 0x89, 0xac, 0xc6, 0xbc, 0xa4, 0x71, 0xd0, 0x76, 0x33, 0x5d, + 0x67, 0xc4, 0x61, 0xdb, 0x60, 0x23, 0x95, 0xbf, 0xb1, 0x7c, 0x39, 0xbf, + 0xa2, 0x4d, 0xf1, 0x40, 0xc0, 0xac, 0x43, 0x88, 0xdb, 0x05, 0x34, 0xa5, + 0x0d, 0xfd, 0x26, 0x13, 0x74, 0xf8, 0x1b, 0x31, 0x0f, 0x75, 0x1d, 0x16 +}; +/* K = 0fd7617bfdc671127a1d7465f683b98d8951a741f85d43cf5a5bef9232a16ae8 */ +static const uint8_t ac_dsa_vect244_out[] = { +/* R */ + 0x58, 0x7d, 0x7f, 0x44, 0x54, 0xd5, 0x94, 0x18, 0xa7, 0x52, 0x75, 0x70, + 0xf2, 0x8f, 0x1b, 0x07, 0x45, 0x1f, 0x3b, 0xaf, 0x28, 0xf5, 0xca, 0xbe, + 0x03, 0x10, 0xc4, 0xd7, 0x9e, 0x42, 0x53, 0xa5, +/* S */ + 0x18, 0x83, 0x94, 0x04, 0xaa, 0xad, 0x59, 0xff, 0x24, 0xd6, 0xac, 0xce, + 0xc3, 0xb7, 0xcc, 0x6a, 0xc7, 0x00, 0x3d, 0xd4, 0xad, 0xf9, 0x6b, 0x77, + 0xba, 0xb0, 0x68, 0xae, 0x72, 0xf2, 0x5f, 0x61 +}; +#define ac_dsa_vect245_prime ac_dsa_vect241_prime +#define ac_dsa_vect245_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect245_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect245_ptx[] = { +/* Msg */ + 0xb1, 0xcb, 0x43, 0x0c, 0x5a, 0x1d, 0x72, 0x78, 0x8c, 0x79, 0x5a, 0xb5, + 0x67, 0xa8, 0x4c, 0x7f, 0x59, 0x77, 0x96, 0x59, 0x33, 0xa5, 0xbf, 0x23, + 0x80, 0x58, 0xf2, 0xfc, 0x81, 0x88, 0x80, 0xd2, 0x5b, 0x4d, 0xde, 0xf9, + 0x63, 0x54, 0x81, 0xfd, 0x9f, 0xdd, 0x45, 0x98, 0xae, 0xce, 0xc3, 0x76, + 0x4f, 0xa7, 0x30, 0x93, 0xa2, 0x25, 0xd4, 0xe4, 0xeb, 0xcf, 0x01, 0xe4, + 0xb7, 0x5b, 0xdc, 0x18, 0x41, 0xdc, 0x01, 0x65, 0x2c, 0x4d, 0x99, 0x16, + 0xaf, 0xa2, 0x4b, 0x89, 0xc2, 0xd6, 0x85, 0x4b, 0x72, 0xea, 0xa7, 0xb1, + 0xf3, 0x08, 0x9d, 0x1a, 0x91, 0x92, 0x10, 0x83, 0x1a, 0xc8, 0x0f, 0x99, + 0x83, 0x57, 0x90, 0xce, 0x64, 0xab, 0xc3, 0x42, 0x70, 0xcd, 0x45, 0x51, + 0xd3, 0x1b, 0x8f, 0x53, 0x48, 0xce, 0x8a, 0x70, 0xdf, 0x60, 0xb8, 0x8e, + 0x08, 0x5a, 0x98, 0x4a, 0xca, 0xc6, 0x65, 0xa7 +}; +static const uint8_t ac_dsa_vect245_priv_val[] = { +/* X */ + 0x40, 0x3b, 0x21, 0x37, 0xad, 0xe3, 0x9c, 0x1e, 0x5b, 0x81, 0x7f, 0xfb, + 0xd0, 0xbc, 0x34, 0x48, 0x02, 0x40, 0x89, 0xfc, 0x19, 0x25, 0x55, 0x0b, + 0x5b, 0x86, 0x04, 0x03, 0xe7, 0xba, 0x65, 0xbc +}; +static const uint8_t ac_dsa_vect245_pub_val[] = { +/* Y */ + 0xa8, 0x1a, 0x54, 0xbe, 0x06, 0x85, 0xf3, 0x35, 0x05, 0xae, 0xd9, 0x59, + 0x1f, 0x33, 0x3a, 0x74, 0xa8, 0x42, 0x99, 0x5d, 0xa5, 0x13, 0x5f, 0xa4, + 0x8f, 0x50, 0x53, 0xfa, 0xc2, 0x9f, 0xff, 0x08, 0xaf, 0xd9, 0xb9, 0x01, + 0xc3, 0xdf, 0x13, 0x47, 0x20, 0x4a, 0x3f, 0x13, 0x3a, 0x7d, 0xff, 0x6b, + 0x1a, 0xdb, 0xab, 0x07, 0x75, 0x26, 0xb6, 0x38, 0xa6, 0x38, 0x37, 0xd7, + 0x84, 0x43, 0x39, 0xd4, 0x8f, 0xe1, 0x07, 0xaf, 0x08, 0xed, 0x62, 0xe8, + 0x7d, 0xe5, 0x47, 0xce, 0xd8, 0x4d, 0xf9, 0xa2, 0xcc, 0xc4, 0x58, 0x76, + 0xb2, 0x9b, 0xc5, 0x36, 0x1c, 0xe8, 0xa9, 0xa2, 0x1b, 0x81, 0xd4, 0xf8, + 0x5d, 0x3b, 0x67, 0x1c, 0x9b, 0x44, 0xb5, 0x48, 0x3f, 0x26, 0x10, 0xef, + 0xa0, 0x17, 0x51, 0xd3, 0xa0, 0x7f, 0xd6, 0x94, 0xe4, 0x66, 0x53, 0xac, + 0x47, 0xac, 0x64, 0xa9, 0x10, 0xb7, 0xfc, 0x42, 0x1f, 0x07, 0xe5, 0xde, + 0x54, 0xe8, 0x98, 0x78, 0x99, 0x89, 0x09, 0x1e, 0x9e, 0xd5, 0x8b, 0x7c, + 0x04, 0xe9, 0xe1, 0xdc, 0xed, 0x60, 0x47, 0x5d, 0xc6, 0x93, 0xa0, 0xeb, + 0x40, 0x15, 0xed, 0x65, 0x81, 0x10, 0xb8, 0x2f, 0x8e, 0x72, 0x0d, 0xc7, + 0xaf, 0xff, 0x69, 0xce, 0xa7, 0xb8, 0xe5, 0x6b, 0x8a, 0x97, 0x55, 0xbf, + 0x1e, 0x29, 0x33, 0xd0, 0x83, 0x60, 0x83, 0x77, 0x50, 0x4c, 0xab, 0x52, + 0xd3, 0x8c, 0xce, 0x1b, 0xa8, 0x2f, 0x84, 0xc2, 0x62, 0x65, 0xe6, 0x93, + 0xf1, 0x8c, 0xf5, 0x2e, 0x93, 0x0d, 0xc0, 0xd8, 0xbc, 0x9d, 0x41, 0xf4, + 0xd2, 0x8b, 0x32, 0xb7, 0x40, 0x5c, 0xb1, 0xfc, 0xe8, 0x8a, 0x55, 0xbe, + 0x40, 0xdc, 0xa1, 0xb1, 0xa3, 0x51, 0xaa, 0x7d, 0x77, 0xfa, 0x6e, 0xf8, + 0x4c, 0x77, 0x6f, 0xa3, 0x01, 0xdb, 0xa2, 0xe2, 0x36, 0x93, 0x3d, 0x89, + 0xc8, 0xb9, 0x44, 0xf5, 0x34, 0x03, 0x41, 0x4d, 0xf0, 0xd4, 0x34, 0xdb, + 0x72, 0xca, 0xa7, 0x49, 0xfb, 0xcd, 0x56, 0x6d, 0x76, 0xf4, 0xf6, 0xf0, + 0xbc, 0x40, 0xe4, 0x2a, 0x29, 0xae, 0xbe, 0x62, 0x10, 0xe8, 0x9f, 0xa0, + 0xca, 0x8b, 0x6a, 0xc0, 0x8a, 0x4c, 0xac, 0x65, 0xc5, 0x90, 0x50, 0x35, + 0x33, 0xc3, 0xe4, 0xf1, 0xb3, 0xc5, 0xbd, 0xe8, 0x68, 0xe7, 0x9d, 0x9d, + 0xa9, 0x18, 0xb7, 0x2d, 0x1b, 0x09, 0x8a, 0x72, 0x78, 0x76, 0x95, 0x46, + 0xb7, 0x84, 0x50, 0xe0, 0x0e, 0x46, 0xdd, 0x40, 0x0e, 0xfe, 0x97, 0xc8, + 0x84, 0xdb, 0x96, 0x12, 0xba, 0xaa, 0xee, 0xe2, 0x48, 0x6f, 0x64, 0xcd, + 0x83, 0x02, 0xa4, 0xc3, 0x2d, 0x8f, 0xdb, 0x87, 0x3f, 0xe0, 0xaf, 0xff, + 0xd7, 0xbb, 0x74, 0x81, 0x12, 0x20, 0xb0, 0x13, 0x39, 0xdf, 0xc5, 0xe5, + 0x67, 0xc7, 0x66, 0xaf, 0x28, 0x05, 0xec, 0x1c, 0x30, 0x12, 0x63, 0x99 +}; +/* K = 2c1ca8b5ce7247dca6173fbaf854d00020ded6300311f53ebec8eccef9570d07 */ +static const uint8_t ac_dsa_vect245_out[] = { +/* R */ + 0x60, 0xd2, 0x76, 0x3f, 0x01, 0x38, 0x07, 0x6e, 0x9e, 0x0e, 0x20, 0xf8, + 0x3e, 0x4a, 0xa2, 0xe9, 0xaa, 0x35, 0x2c, 0x19, 0xca, 0x79, 0xe3, 0x72, + 0x63, 0x03, 0xfe, 0x89, 0xb1, 0x2e, 0x27, 0xf2, +/* S */ + 0x07, 0xe0, 0x8d, 0x91, 0x6c, 0x8a, 0x10, 0xba, 0x26, 0x9d, 0xc4, 0x60, + 0xee, 0x9d, 0x83, 0xf8, 0x6a, 0x7b, 0x3d, 0x98, 0x62, 0x1b, 0xb7, 0x32, + 0x4a, 0x6a, 0x7e, 0x60, 0x72, 0x38, 0xba, 0xa3 +}; +#define ac_dsa_vect246_prime ac_dsa_vect241_prime +#define ac_dsa_vect246_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect246_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect246_ptx[] = { +/* Msg */ + 0x3b, 0xb9, 0x43, 0x0e, 0xea, 0x69, 0x79, 0x12, 0x9b, 0xe7, 0x45, 0xd5, + 0xae, 0x6b, 0xab, 0xd4, 0x96, 0x6e, 0x3a, 0xbf, 0x7d, 0x9e, 0xe5, 0x85, + 0x6f, 0x2c, 0xaa, 0xe6, 0x01, 0x4c, 0xb3, 0x40, 0xee, 0xbd, 0x28, 0xbd, + 0x9f, 0x39, 0x1e, 0xb4, 0x6b, 0x3a, 0x2b, 0x8a, 0x4c, 0xdc, 0x22, 0x4e, + 0x55, 0x08, 0x53, 0x2c, 0xa0, 0x8c, 0xb1, 0x04, 0xaf, 0xf6, 0x77, 0x13, + 0x3c, 0xf4, 0x39, 0x3a, 0x20, 0xfe, 0x44, 0x99, 0x96, 0x7d, 0xfa, 0x64, + 0x51, 0x54, 0x55, 0x93, 0x0c, 0x65, 0x9d, 0x43, 0xbb, 0xee, 0x23, 0x40, + 0xb1, 0x4a, 0x3b, 0x33, 0x42, 0xd4, 0xb9, 0xa4, 0x66, 0xb8, 0x89, 0xe8, + 0x50, 0xdf, 0xf4, 0xb2, 0xa5, 0x1d, 0x38, 0x9c, 0xa3, 0x2f, 0xb6, 0xa5, + 0xf4, 0x33, 0xed, 0x93, 0x03, 0x2b, 0xe4, 0xe5, 0x63, 0x69, 0x57, 0x97, + 0xb8, 0xc1, 0xe1, 0xe0, 0x19, 0x18, 0x41, 0x72 +}; +static const uint8_t ac_dsa_vect246_priv_val[] = { +/* X */ + 0x0d, 0x3f, 0xc8, 0xfc, 0x4c, 0x59, 0x97, 0x1a, 0x96, 0x3e, 0x8e, 0x41, + 0xd2, 0x6a, 0x86, 0x49, 0x9c, 0x96, 0x26, 0x15, 0xc6, 0x4a, 0xbe, 0x01, + 0x1e, 0x88, 0xe5, 0x90, 0xbd, 0xdd, 0x3b, 0x0b +}; +static const uint8_t ac_dsa_vect246_pub_val[] = { +/* Y */ + 0x75, 0xb7, 0x65, 0xec, 0xa4, 0xeb, 0xde, 0x0b, 0x65, 0x64, 0xc3, 0x13, + 0x7f, 0x16, 0xcd, 0xae, 0x00, 0xee, 0xad, 0xd2, 0xd0, 0xb2, 0xcb, 0x83, + 0xcd, 0x15, 0x00, 0xcd, 0x05, 0xed, 0x0d, 0xd1, 0x67, 0x30, 0xc9, 0x50, + 0x1c, 0x8a, 0x35, 0x3a, 0x64, 0x63, 0x4d, 0x06, 0x5f, 0x61, 0x37, 0xff, + 0xcf, 0x95, 0x63, 0xd9, 0x61, 0x27, 0x90, 0x6f, 0xb1, 0x7d, 0x5a, 0x79, + 0xad, 0x29, 0x10, 0x24, 0xa4, 0xa6, 0xfb, 0x7e, 0x7d, 0x08, 0x02, 0x19, + 0xa6, 0x23, 0x1c, 0xa1, 0x58, 0xb6, 0x5f, 0x52, 0x02, 0x91, 0x2d, 0xdc, + 0xb8, 0xdd, 0x1f, 0x01, 0x8c, 0x9b, 0x0e, 0x76, 0xb3, 0xa4, 0x76, 0x33, + 0x6c, 0x50, 0x41, 0xbc, 0x50, 0x2f, 0x8a, 0xcb, 0x74, 0x8f, 0x13, 0x6c, + 0x3d, 0x78, 0xcb, 0x2c, 0x42, 0x9c, 0x8f, 0x1a, 0xc1, 0x7b, 0x63, 0xdd, + 0x7e, 0x9e, 0x57, 0xb6, 0x07, 0xf9, 0xde, 0xbe, 0x57, 0x14, 0x59, 0xdf, + 0x36, 0x88, 0xcf, 0x4c, 0x11, 0xfa, 0x1e, 0x84, 0x53, 0x3a, 0xec, 0xda, + 0x2d, 0xfe, 0xce, 0x05, 0xf4, 0xbd, 0xb2, 0x68, 0xcc, 0x7b, 0x0c, 0x8f, + 0xe7, 0xaf, 0x5a, 0x63, 0x3a, 0x83, 0x51, 0x5a, 0xda, 0x95, 0xf3, 0x18, + 0x24, 0xd6, 0xa3, 0xc7, 0x12, 0x2f, 0xdc, 0xd1, 0x2f, 0x54, 0x99, 0x2c, + 0xbe, 0x64, 0xd1, 0xd6, 0xbd, 0xbd, 0x0a, 0xb5, 0xae, 0x4d, 0x19, 0xaa, + 0x52, 0x60, 0x97, 0x50, 0xa1, 0xde, 0x18, 0x6a, 0xfa, 0xb5, 0xa1, 0x63, + 0x98, 0xda, 0x47, 0x3d, 0x12, 0x88, 0x82, 0xb0, 0x65, 0xe8, 0x73, 0x80, + 0x9f, 0xae, 0x0b, 0xbd, 0xc0, 0x1a, 0x9c, 0x73, 0xb5, 0xc6, 0xee, 0x65, + 0x85, 0x7f, 0xa7, 0x94, 0xa1, 0x50, 0x58, 0xdd, 0xfb, 0x24, 0xa9, 0xa1, + 0x7a, 0x04, 0x08, 0x64, 0x6f, 0x20, 0x09, 0xdd, 0xa6, 0x10, 0xc8, 0x29, + 0x1a, 0xe1, 0x48, 0xa1, 0x8c, 0x17, 0x3f, 0x83, 0x6b, 0x19, 0x7c, 0x78, + 0xed, 0xe5, 0x65, 0x48, 0x95, 0xb4, 0x5a, 0x34, 0x19, 0xe9, 0xc3, 0x17, + 0x7f, 0x25, 0x03, 0xa9, 0x3c, 0xe5, 0x26, 0xbe, 0x14, 0xad, 0x91, 0x99, + 0x39, 0xeb, 0xe3, 0xf2, 0xd0, 0x7f, 0x00, 0x6a, 0x0b, 0x02, 0x2d, 0x6a, + 0x62, 0x3c, 0x60, 0x17, 0xf0, 0xc7, 0x66, 0x19, 0xf0, 0x78, 0x05, 0x31, + 0xd5, 0x39, 0x0d, 0x42, 0x39, 0xb2, 0xf9, 0x00, 0xef, 0xb4, 0x4c, 0x95, + 0x30, 0xc7, 0xd9, 0xb3, 0xe8, 0x4a, 0x70, 0xc9, 0x04, 0xb1, 0x79, 0xad, + 0x0c, 0x4f, 0x90, 0x92, 0x50, 0xf7, 0xcc, 0xf8, 0x3c, 0x5f, 0x42, 0xd6, + 0x43, 0x7c, 0xbc, 0x9f, 0x03, 0xfb, 0xae, 0x81, 0x31, 0xa1, 0x2d, 0x33, + 0xe0, 0x17, 0x21, 0xe6, 0x50, 0xae, 0xe9, 0x1e, 0x1c, 0x89, 0x3f, 0x5e, + 0x7e, 0x03, 0x9e, 0x0d, 0x58, 0x5c, 0xd7, 0xcd, 0x74, 0x95, 0xc4, 0x0d +}; +/* K = 32d9aa04b104b5d7b59a122b368fe0cf476e28098b898662a78efee764545ea5 */ +static const uint8_t ac_dsa_vect246_out[] = { +/* R */ + 0x74, 0x16, 0x72, 0x9a, 0x1f, 0x60, 0x20, 0x8b, 0x7f, 0x83, 0x74, 0x80, + 0xfb, 0xa8, 0x18, 0x40, 0xe4, 0x5b, 0x33, 0x8a, 0xb9, 0x84, 0x6e, 0x9b, + 0xbb, 0x91, 0x68, 0x22, 0x9f, 0x64, 0xbc, 0xea, +/* S */ + 0x58, 0xeb, 0x90, 0x40, 0x76, 0xa3, 0xac, 0x69, 0x07, 0xd7, 0x50, 0xff, + 0x6c, 0xdf, 0xaa, 0x46, 0x54, 0x35, 0xe9, 0x98, 0x2e, 0xcb, 0xdf, 0x72, + 0x19, 0x7b, 0x09, 0xbb, 0x6d, 0xf1, 0x37, 0x3a +}; +#define ac_dsa_vect247_prime ac_dsa_vect241_prime +#define ac_dsa_vect247_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect247_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect247_ptx[] = { +/* Msg */ + 0x55, 0xa6, 0x9f, 0xc1, 0x6f, 0x6b, 0x75, 0x3d, 0x0b, 0xf6, 0x5e, 0x84, + 0x4d, 0x06, 0x78, 0x59, 0xf5, 0x1d, 0xd3, 0x29, 0x27, 0x99, 0x80, 0x19, + 0x60, 0x63, 0xfb, 0x59, 0xf8, 0x9b, 0xd7, 0x78, 0xa9, 0x24, 0x4f, 0x93, + 0x2c, 0x2a, 0xdb, 0x68, 0x11, 0x18, 0x36, 0x12, 0x10, 0x5d, 0x1c, 0x52, + 0x7e, 0x83, 0x02, 0xdf, 0xee, 0x50, 0x42, 0xcf, 0xce, 0x5d, 0xbe, 0xab, + 0x16, 0x5a, 0x39, 0x6f, 0x5a, 0x4c, 0x21, 0x33, 0x9b, 0xe1, 0x02, 0x1b, + 0x7e, 0xce, 0xc6, 0x6f, 0x21, 0x77, 0xf9, 0x42, 0x43, 0xef, 0x62, 0x61, + 0x60, 0x8c, 0x56, 0x91, 0x96, 0x79, 0xd4, 0x48, 0x63, 0xcf, 0x9d, 0x2a, + 0xfc, 0x60, 0x10, 0xfc, 0x2b, 0xf8, 0x21, 0xb9, 0x31, 0xca, 0x39, 0x70, + 0xd6, 0x9b, 0x1e, 0x62, 0x2a, 0x90, 0x83, 0x89, 0xdb, 0x50, 0x49, 0xd7, + 0x18, 0xe3, 0x57, 0x07, 0x10, 0x63, 0xae, 0xf8 +}; +static const uint8_t ac_dsa_vect247_priv_val[] = { +/* X */ + 0x3d, 0xd2, 0x24, 0xf0, 0x0e, 0xe1, 0xd4, 0x64, 0x8c, 0x60, 0x0b, 0x10, + 0xba, 0x05, 0xff, 0x36, 0xad, 0x2c, 0x06, 0xdd, 0xc5, 0xa9, 0xf0, 0x11, + 0x2e, 0x03, 0x31, 0xae, 0x95, 0x8f, 0x36, 0xaf +}; +static const uint8_t ac_dsa_vect247_pub_val[] = { +/* Y */ + 0x61, 0x46, 0xa5, 0x1d, 0xeb, 0x79, 0x95, 0x7a, 0x83, 0xb2, 0xc7, 0xa3, + 0x20, 0x4b, 0x5c, 0x34, 0xae, 0x4f, 0x8e, 0x0d, 0xb6, 0x0f, 0x0c, 0x07, + 0xe7, 0x08, 0x03, 0xf2, 0x2b, 0xf9, 0x9a, 0x39, 0x64, 0x72, 0x63, 0xdb, + 0x9e, 0x28, 0x5d, 0x72, 0xf6, 0x27, 0x0e, 0xe1, 0x0f, 0x18, 0x58, 0x4c, + 0x39, 0x08, 0x1d, 0x25, 0x44, 0xd4, 0x05, 0x02, 0xc5, 0x0d, 0xf1, 0xe3, + 0x5a, 0x45, 0x76, 0x00, 0xb5, 0x56, 0x9d, 0x61, 0xe8, 0x12, 0x6c, 0x05, + 0x5f, 0x7b, 0x96, 0x45, 0x72, 0xe9, 0xf3, 0x28, 0x2e, 0x4d, 0x97, 0x45, + 0x00, 0x69, 0x55, 0xc2, 0x42, 0x61, 0xc6, 0x8d, 0x7c, 0x0c, 0xb3, 0xf0, + 0x8b, 0x0b, 0x0d, 0x8e, 0xaa, 0x97, 0x1e, 0x1a, 0x63, 0x1c, 0x68, 0xa3, + 0xa9, 0x14, 0xd3, 0x5e, 0xfe, 0x89, 0xf7, 0x6b, 0x9c, 0x21, 0x16, 0xaf, + 0xb7, 0xbd, 0x19, 0x89, 0xe2, 0x02, 0xe0, 0x92, 0xb5, 0xb5, 0x70, 0xea, + 0xef, 0xcc, 0x93, 0x35, 0x42, 0xe6, 0x50, 0xd9, 0x2c, 0x03, 0x3b, 0x59, + 0x73, 0x82, 0x1d, 0x6d, 0x77, 0xcf, 0xc2, 0x43, 0xf7, 0x44, 0xda, 0x80, + 0xb5, 0x6e, 0xae, 0xa7, 0x65, 0x0b, 0xf5, 0x08, 0x02, 0x51, 0x62, 0x28, + 0xad, 0x6d, 0x5b, 0x0d, 0x4e, 0x88, 0x9c, 0x57, 0x5e, 0x36, 0x78, 0xff, + 0xdb, 0x1c, 0x28, 0x9e, 0x59, 0xd9, 0xff, 0x7f, 0x84, 0xa3, 0xd6, 0x3d, + 0x39, 0xd6, 0x88, 0x8d, 0xbe, 0x21, 0x3e, 0x2c, 0x3b, 0x31, 0x14, 0x08, + 0x5e, 0x00, 0x6a, 0xd7, 0x45, 0x05, 0x73, 0x9f, 0xce, 0x82, 0x6f, 0x96, + 0x32, 0x84, 0xdc, 0x4e, 0x2b, 0x01, 0xec, 0x2f, 0x92, 0x33, 0xd3, 0x47, + 0x0e, 0x82, 0xd8, 0x72, 0xed, 0x94, 0x4e, 0x62, 0x96, 0x1f, 0x64, 0x13, + 0x4e, 0x80, 0x80, 0xda, 0xf2, 0xdf, 0x49, 0x4a, 0x76, 0x24, 0x0a, 0xc0, + 0xcd, 0x22, 0xf9, 0xaf, 0xae, 0x7e, 0x80, 0xd3, 0xcf, 0x3e, 0xfb, 0xe0, + 0x55, 0x14, 0x7f, 0x62, 0xff, 0x8c, 0x61, 0x92, 0xe3, 0x88, 0xb4, 0x9e, + 0x47, 0xd9, 0xfe, 0xaf, 0x19, 0xec, 0xcd, 0x65, 0xdc, 0xa9, 0x99, 0x16, + 0x38, 0xeb, 0xd7, 0xb0, 0x48, 0x07, 0x77, 0x07, 0xad, 0xab, 0x1c, 0xb2, + 0xa4, 0x35, 0x8e, 0xef, 0xc4, 0xaa, 0xb8, 0x25, 0x1f, 0xb0, 0xf9, 0xd5, + 0xf0, 0xb0, 0x9f, 0x29, 0x9c, 0x72, 0x0d, 0x3a, 0x8c, 0x00, 0xa5, 0xa4, + 0xd8, 0x4f, 0xee, 0xc0, 0x40, 0x05, 0x70, 0x40, 0xb7, 0x09, 0xcc, 0x0e, + 0xd1, 0x85, 0xa8, 0x32, 0x53, 0x7b, 0xc4, 0xb2, 0xdf, 0x0e, 0xc1, 0xf7, + 0x71, 0x69, 0xac, 0x96, 0xe9, 0x12, 0x82, 0xde, 0x21, 0xf3, 0x42, 0xd5, + 0x42, 0x9e, 0xc3, 0xd6, 0x6a, 0xd9, 0xd3, 0x36, 0xc4, 0x40, 0x94, 0x9a, + 0x12, 0x11, 0x21, 0x7b, 0xf5, 0x4a, 0xad, 0x93, 0xbb, 0x4b, 0x0a, 0x43 +}; +/* K = 7969d08c0cafe4019b64ad3e6614be0aaabc2c2be61b3b3dcdd10d5f75fa24bb */ +static const uint8_t ac_dsa_vect247_out[] = { +/* R */ + 0x13, 0x6f, 0x93, 0xdc, 0xc7, 0xd3, 0x3e, 0x55, 0x9b, 0x8d, 0xb0, 0xaf, + 0x13, 0xe0, 0x0c, 0x71, 0x90, 0x92, 0x8b, 0xff, 0x50, 0x86, 0xee, 0xdf, + 0xd1, 0x17, 0x06, 0xe6, 0xf2, 0x34, 0x9a, 0xd0, +/* S */ + 0x32, 0xb9, 0x5b, 0x9b, 0x14, 0x7c, 0x7d, 0x1a, 0xc2, 0xa2, 0xf0, 0x05, + 0x7f, 0xc0, 0x53, 0x8a, 0x4b, 0x7c, 0x9c, 0xd4, 0x65, 0x2e, 0x67, 0x83, + 0xe5, 0xd7, 0xe3, 0x53, 0x46, 0x55, 0x63, 0x1a +}; +#define ac_dsa_vect248_prime ac_dsa_vect241_prime +#define ac_dsa_vect248_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect248_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect248_ptx[] = { +/* Msg */ + 0x15, 0x67, 0x89, 0x0c, 0x69, 0xe5, 0x78, 0xa2, 0x7d, 0x62, 0x08, 0x91, + 0x3d, 0xfb, 0xc2, 0x0e, 0xdd, 0xc6, 0x1f, 0x5f, 0xee, 0xd4, 0x57, 0x40, + 0x06, 0x93, 0xdd, 0x17, 0x0f, 0x80, 0x67, 0xbf, 0x29, 0x0b, 0x11, 0x15, + 0x07, 0x80, 0x68, 0x4c, 0x20, 0xd5, 0xcf, 0xd2, 0xbf, 0x1d, 0x53, 0x6d, + 0xd3, 0xb7, 0x00, 0x25, 0x88, 0x3f, 0xb4, 0x17, 0x03, 0x43, 0x6f, 0xd0, + 0x9c, 0x0a, 0x14, 0x11, 0x25, 0x78, 0x4f, 0x90, 0x91, 0x15, 0x13, 0x03, + 0xef, 0x80, 0xcd, 0x34, 0x5e, 0x5a, 0x7d, 0x28, 0x54, 0x33, 0x5c, 0x29, + 0x84, 0x53, 0x8c, 0x5c, 0xd7, 0x39, 0xb0, 0x07, 0x24, 0x8c, 0xd9, 0x9f, + 0x1d, 0xbc, 0xd3, 0x14, 0x8c, 0xb0, 0xff, 0x0d, 0xb6, 0x33, 0xf8, 0xca, + 0xfc, 0x7a, 0x0b, 0x99, 0xc6, 0x1e, 0x78, 0x4d, 0x03, 0x03, 0xa5, 0x12, + 0x03, 0x07, 0xd3, 0xfb, 0x3c, 0x4c, 0x21, 0x9e +}; +static const uint8_t ac_dsa_vect248_priv_val[] = { +/* X */ + 0x3a, 0xc3, 0x74, 0xb2, 0xa4, 0x94, 0x0d, 0x92, 0xab, 0x35, 0xeb, 0xb8, + 0xe5, 0x96, 0x77, 0xfb, 0xf9, 0x59, 0x80, 0xfe, 0x63, 0x2f, 0xfb, 0xb1, + 0xdb, 0x4f, 0x38, 0x5e, 0xe4, 0xe1, 0x3a, 0x15 +}; +static const uint8_t ac_dsa_vect248_pub_val[] = { +/* Y */ + 0x5c, 0x53, 0xd1, 0x3a, 0x1b, 0xee, 0x17, 0xa2, 0x87, 0x20, 0xb7, 0x08, + 0x96, 0x46, 0xd0, 0x7a, 0x3f, 0xd5, 0x8b, 0x9b, 0x2b, 0x23, 0xec, 0x94, + 0xaf, 0x31, 0x44, 0x83, 0x07, 0x46, 0x17, 0x7b, 0x0d, 0x20, 0x73, 0x70, + 0x7b, 0x6b, 0x84, 0x90, 0x1f, 0xfa, 0xa7, 0xa4, 0x16, 0x5c, 0xef, 0xf2, + 0x42, 0x56, 0x40, 0xfc, 0xfe, 0x5d, 0x17, 0x65, 0x0a, 0x44, 0xa1, 0x68, + 0xeb, 0xd7, 0x69, 0xc8, 0x33, 0x44, 0x5f, 0x1b, 0x2d, 0x26, 0x43, 0x4c, + 0x22, 0x8c, 0x1e, 0x2e, 0xdf, 0x17, 0x04, 0xd7, 0x11, 0xa8, 0x62, 0x57, + 0xbe, 0x25, 0x23, 0x5a, 0x7c, 0xea, 0x1e, 0x5c, 0xba, 0xc4, 0x12, 0x23, + 0x5b, 0x75, 0x96, 0xd1, 0xdf, 0xa0, 0x39, 0x80, 0x81, 0xa4, 0xf1, 0x81, + 0x51, 0xcb, 0xb5, 0x1d, 0xc6, 0x2c, 0x22, 0x6a, 0x2a, 0xbc, 0xaf, 0x33, + 0x35, 0xe8, 0x6a, 0xb5, 0x46, 0x08, 0x04, 0x0e, 0xe8, 0x14, 0xe4, 0x43, + 0xb6, 0x43, 0x98, 0x21, 0x3b, 0xa6, 0x0d, 0x7b, 0x5a, 0x3c, 0x8e, 0xa7, + 0x8e, 0xc6, 0xb9, 0x89, 0x34, 0xc8, 0x9a, 0xca, 0x05, 0xb9, 0x7d, 0xf5, + 0xf6, 0x5b, 0xc5, 0x74, 0xa3, 0x0a, 0xcd, 0xdd, 0x09, 0xf7, 0x3c, 0xec, + 0x14, 0x52, 0x8b, 0xe4, 0x9a, 0x2f, 0xbe, 0xca, 0x70, 0x29, 0x1b, 0x1b, + 0x29, 0xf7, 0x04, 0x2c, 0x59, 0x49, 0x94, 0xda, 0x12, 0x8f, 0xda, 0x22, + 0xb3, 0xed, 0x3a, 0x93, 0x5a, 0x1a, 0x00, 0x57, 0x5f, 0xf1, 0xff, 0xd1, + 0x93, 0xc4, 0xca, 0xc5, 0x3a, 0x2a, 0x2d, 0x4b, 0x0c, 0x51, 0x02, 0x28, + 0xa7, 0x6a, 0x74, 0x33, 0x36, 0x07, 0xd1, 0x5b, 0x56, 0x86, 0x14, 0x42, + 0x71, 0x44, 0xb4, 0x17, 0x4d, 0xa3, 0x58, 0xe3, 0x83, 0xf6, 0x58, 0xc6, + 0x0b, 0x45, 0x71, 0x00, 0x36, 0xf5, 0x4f, 0x93, 0xf1, 0x7b, 0xc8, 0x08, + 0xb3, 0x02, 0x67, 0x4e, 0x83, 0x8c, 0x1d, 0xfd, 0x7f, 0x81, 0x6f, 0x7e, + 0xa4, 0x4b, 0x0d, 0x97, 0x38, 0x6e, 0x4e, 0x16, 0x34, 0xc9, 0x53, 0x95, + 0x68, 0xdd, 0x6a, 0xe1, 0xc2, 0x8f, 0x25, 0xb2, 0x7a, 0xa9, 0x44, 0x99, + 0xae, 0x38, 0x9a, 0x09, 0x26, 0xc8, 0xfa, 0x62, 0x95, 0x6c, 0x6e, 0x24, + 0xdc, 0xed, 0x0a, 0xfb, 0x04, 0x91, 0xdd, 0x9f, 0xac, 0x05, 0x16, 0xd2, + 0x7f, 0xd4, 0xd2, 0xdd, 0x01, 0x50, 0xee, 0x6b, 0x4c, 0xff, 0x7b, 0xfd, + 0x57, 0x50, 0x43, 0xd7, 0x01, 0xda, 0xad, 0x0f, 0x1b, 0x94, 0x2a, 0x0e, + 0x4c, 0x61, 0x95, 0x6b, 0x32, 0xa6, 0x8c, 0x90, 0x78, 0xf6, 0x07, 0x7f, + 0xa9, 0x94, 0x51, 0x98, 0xd4, 0x47, 0xa5, 0xbf, 0x3c, 0x47, 0xb7, 0x28, + 0x84, 0x27, 0xed, 0xc6, 0xf9, 0x96, 0x55, 0xae, 0xad, 0xf8, 0xde, 0x18, + 0x51, 0x57, 0x14, 0xc6, 0xb9, 0xc0, 0xd4, 0xce, 0x5a, 0xb0, 0x92, 0xc2 +}; +/* K = 7ca690c92c8d4a3ac1d5255a2e5a12922093b8b2ee95906eab29b67f84fd21cc */ +static const uint8_t ac_dsa_vect248_out[] = { +/* R */ + 0x49, 0x47, 0xd3, 0x6e, 0x74, 0x26, 0xf1, 0x44, 0x1b, 0xe5, 0xa7, 0x5d, + 0xc9, 0xcd, 0x84, 0x54, 0x50, 0xc6, 0x11, 0x04, 0xf1, 0x9e, 0xd4, 0x0c, + 0xe3, 0x3e, 0x25, 0x2f, 0xa2, 0xc2, 0x62, 0x68, +/* S */ + 0x35, 0x68, 0x79, 0xde, 0xb1, 0xda, 0xef, 0x01, 0xda, 0x04, 0x75, 0x0d, + 0x58, 0xe5, 0x98, 0xdb, 0x47, 0xaa, 0xaf, 0xf5, 0x0b, 0x1c, 0xf4, 0x2d, + 0x87, 0x33, 0x4a, 0x61, 0x57, 0x80, 0xff, 0x8c +}; +#define ac_dsa_vect249_prime ac_dsa_vect241_prime +#define ac_dsa_vect249_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect249_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect249_ptx[] = { +/* Msg */ + 0x4f, 0x7d, 0x89, 0x4d, 0xfb, 0x7d, 0x82, 0x04, 0x0a, 0x9f, 0xed, 0x6c, + 0x26, 0xa7, 0xd2, 0x7a, 0x9a, 0x15, 0x11, 0x38, 0x8c, 0x11, 0x3c, 0x64, + 0x71, 0x5a, 0x06, 0xdc, 0x46, 0xfc, 0xf4, 0xf9, 0x04, 0x07, 0x0a, 0x6e, + 0xd9, 0x5b, 0xdd, 0x8d, 0xc1, 0x73, 0x0a, 0x27, 0x64, 0x5d, 0x37, 0xeb, + 0x3b, 0x02, 0x84, 0x7c, 0xb1, 0xc6, 0x31, 0xec, 0x0c, 0x67, 0xb2, 0xee, + 0x07, 0xb8, 0x80, 0x5b, 0x34, 0xdd, 0x9b, 0x84, 0xe6, 0xab, 0x3f, 0x9a, + 0xfb, 0x92, 0x46, 0x99, 0x4e, 0xa5, 0x79, 0x56, 0x7a, 0x8f, 0x4a, 0xf7, + 0xfe, 0xb8, 0x68, 0x98, 0xcc, 0x9c, 0xb5, 0x34, 0xc3, 0x87, 0x99, 0x3c, + 0x6e, 0xc1, 0x65, 0x84, 0xac, 0x85, 0xbe, 0xd3, 0x6b, 0xbc, 0x2c, 0x30, + 0x57, 0x70, 0xf2, 0x11, 0x63, 0x68, 0x61, 0x67, 0xdd, 0x53, 0xfe, 0x56, + 0x23, 0x62, 0xff, 0x54, 0x9d, 0x90, 0x35, 0x39 +}; +static const uint8_t ac_dsa_vect249_priv_val[] = { +/* X */ + 0x2c, 0x14, 0xcd, 0x97, 0x5b, 0xc1, 0x63, 0xf9, 0x74, 0x0d, 0xcb, 0x4a, + 0x5b, 0xa9, 0xd8, 0x52, 0x9c, 0x5a, 0x07, 0x50, 0x16, 0xe0, 0x24, 0x00, + 0xdb, 0xfe, 0xde, 0x8d, 0xd4, 0xf0, 0xd2, 0x45 +}; +static const uint8_t ac_dsa_vect249_pub_val[] = { +/* Y */ + 0x00, 0x96, 0x74, 0x78, 0x35, 0x8d, 0x7c, 0x16, 0x96, 0xce, 0xb9, 0x2b, + 0xe8, 0x50, 0xf5, 0x53, 0x8a, 0xd8, 0x54, 0x3e, 0x15, 0x1a, 0xad, 0xd8, + 0x4c, 0xab, 0xa1, 0xb7, 0x2f, 0x36, 0x36, 0xa2, 0x09, 0x2a, 0x86, 0xb6, + 0x46, 0x28, 0x73, 0x90, 0x3d, 0x5b, 0xf1, 0x7f, 0x61, 0x2b, 0x45, 0xb5, + 0x13, 0x3e, 0xac, 0x16, 0x30, 0xbf, 0x07, 0xc0, 0x37, 0x14, 0x23, 0xd2, + 0xe5, 0xd7, 0x14, 0x7c, 0xea, 0xcc, 0x9b, 0xaa, 0x8c, 0xb3, 0xb0, 0x4c, + 0xbc, 0x3c, 0xbd, 0xa4, 0x29, 0xab, 0x40, 0xd7, 0xe5, 0x92, 0x73, 0x0d, + 0xc4, 0x77, 0xb0, 0xa9, 0x5f, 0x1f, 0xb5, 0xed, 0x5d, 0x91, 0xe1, 0x4b, + 0x9d, 0x5a, 0x1a, 0xc8, 0xd4, 0x03, 0xa5, 0x5a, 0x65, 0x8d, 0x1c, 0x38, + 0x3b, 0xb5, 0x98, 0x05, 0x3b, 0xe2, 0x38, 0xcd, 0x82, 0x38, 0x69, 0x68, + 0xae, 0xdb, 0x81, 0x15, 0x86, 0xfa, 0x2a, 0x14, 0x11, 0x93, 0x24, 0x89, + 0x6f, 0x21, 0x11, 0xb9, 0xbc, 0x7c, 0xff, 0x66, 0x6d, 0x37, 0xaf, 0xfe, + 0x76, 0x04, 0x1d, 0x98, 0xf3, 0x62, 0xda, 0xa0, 0x9f, 0xf6, 0x5e, 0x82, + 0xe8, 0x65, 0xeb, 0x29, 0xc5, 0xd4, 0x71, 0x0c, 0xa7, 0x80, 0x08, 0x86, + 0x88, 0x7d, 0x38, 0x3d, 0xa0, 0xcb, 0x59, 0x9b, 0x22, 0x5f, 0xdd, 0x21, + 0x0a, 0x3d, 0x70, 0x92, 0x9d, 0x35, 0xfb, 0x9c, 0xa8, 0x07, 0xe5, 0x6c, + 0x91, 0xc0, 0x85, 0x12, 0x52, 0xb9, 0x5c, 0x07, 0xb6, 0xb1, 0x20, 0xb3, + 0xb6, 0x50, 0x41, 0x8e, 0x0f, 0x54, 0xf4, 0x57, 0x36, 0xf8, 0x20, 0x18, + 0xd0, 0x92, 0x94, 0x46, 0x2d, 0xde, 0x6e, 0xea, 0xfc, 0xb1, 0x5a, 0x2a, + 0x72, 0x85, 0x77, 0xfa, 0xf3, 0xef, 0x3e, 0xb1, 0x3d, 0xb0, 0x44, 0x96, + 0x5e, 0xa3, 0x89, 0x2f, 0x7e, 0xb0, 0x88, 0x4e, 0x47, 0x76, 0x60, 0x89, + 0xd2, 0xa4, 0x3a, 0xbc, 0x62, 0xa3, 0xc3, 0x75, 0x83, 0x1c, 0x20, 0x84, + 0x8d, 0xfd, 0xe8, 0xf8, 0x3c, 0x24, 0x9a, 0x8e, 0x27, 0xf2, 0x89, 0x7c, + 0xaf, 0xcf, 0x5a, 0x06, 0xb7, 0xc3, 0x59, 0x1e, 0x09, 0xb4, 0x2f, 0x82, + 0x84, 0x9d, 0x49, 0x86, 0x64, 0xf4, 0x85, 0xde, 0x26, 0xc7, 0x88, 0xe5, + 0x59, 0xad, 0x5b, 0x15, 0xf9, 0x99, 0xdb, 0x92, 0x7f, 0x81, 0xf5, 0x4b, + 0x96, 0xe9, 0x97, 0xb9, 0x09, 0x6b, 0x2a, 0x7e, 0x3e, 0x75, 0x6f, 0x5a, + 0x9a, 0xab, 0x54, 0xc1, 0x60, 0xcf, 0xc2, 0xe6, 0x44, 0x92, 0x17, 0x94, + 0x87, 0xc9, 0x8d, 0x0a, 0xa3, 0x83, 0x08, 0xd6, 0x74, 0x28, 0xf3, 0xa1, + 0x13, 0x22, 0x8b, 0xc6, 0xdc, 0xdf, 0x7a, 0xb9, 0x3c, 0xbb, 0x1d, 0xa2, + 0x25, 0xc7, 0x2c, 0x63, 0x6f, 0x49, 0xd2, 0x74, 0x42, 0xcf, 0x3c, 0xf2, + 0xf9, 0xc4, 0x9b, 0x90, 0xac, 0x8b, 0xaf, 0xe7, 0x40, 0xdb, 0xbf, 0xd5 +}; +/* K = 141936264e075533a96952808935238d715e7cbd840c016ee7a9f508608e4808 */ +static const uint8_t ac_dsa_vect249_out[] = { +/* R */ + 0x09, 0x40, 0x72, 0x48, 0x55, 0xa0, 0x67, 0x1d, 0x60, 0x14, 0x7d, 0xc6, + 0x1f, 0xd2, 0x83, 0x19, 0x01, 0x34, 0xa6, 0x8c, 0x17, 0x81, 0x14, 0xd5, + 0x9a, 0xb5, 0x8d, 0xa7, 0x3a, 0x1c, 0x81, 0x82, +/* S */ + 0x43, 0xf1, 0x94, 0xb9, 0x70, 0x78, 0xdc, 0x9b, 0x84, 0xc8, 0xe8, 0xe8, + 0x67, 0xa7, 0x4b, 0xaf, 0xdc, 0x22, 0x11, 0x70, 0x6a, 0xe1, 0x10, 0xb5, + 0xae, 0xc0, 0xb9, 0x9e, 0xde, 0x1f, 0xfe, 0xd8 +}; +#define ac_dsa_vect250_prime ac_dsa_vect241_prime +#define ac_dsa_vect250_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect250_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect250_ptx[] = { +/* Msg */ + 0x9b, 0x62, 0xa7, 0x4b, 0xc4, 0x9e, 0xf4, 0xff, 0x5c, 0x62, 0x16, 0x5e, + 0x7d, 0x25, 0x52, 0x1f, 0x13, 0x5c, 0x83, 0x6b, 0xc4, 0xef, 0x02, 0x3f, + 0xb4, 0xbb, 0x1d, 0x6b, 0x42, 0xc6, 0x29, 0x10, 0x71, 0xea, 0xe0, 0xb4, + 0x65, 0xc5, 0x92, 0x31, 0xcb, 0x29, 0x7c, 0xac, 0x6d, 0x14, 0x58, 0x75, + 0xfd, 0x84, 0xf5, 0x72, 0x9f, 0x79, 0xf9, 0x22, 0x18, 0x52, 0x2b, 0x9e, + 0x55, 0xcb, 0x70, 0xd4, 0x71, 0x03, 0x0d, 0x36, 0x29, 0x1a, 0x24, 0x92, + 0x5a, 0xb7, 0x31, 0xa2, 0xd4, 0x45, 0x8c, 0xff, 0x67, 0x70, 0x79, 0xd2, + 0x07, 0xce, 0x86, 0x5b, 0x3d, 0x55, 0x26, 0x00, 0x92, 0x38, 0x86, 0x1d, + 0x64, 0x50, 0x6a, 0x92, 0xb7, 0x6b, 0xaf, 0xf5, 0x9b, 0x37, 0xb8, 0x63, + 0x08, 0x75, 0x58, 0xd5, 0x96, 0x5d, 0x76, 0x68, 0x5f, 0x0f, 0xbd, 0x1f, + 0xab, 0x1b, 0x1f, 0x95, 0x61, 0xf8, 0xf6, 0x9c +}; +static const uint8_t ac_dsa_vect250_priv_val[] = { +/* X */ + 0x70, 0xe1, 0x2e, 0x51, 0xa2, 0x54, 0x83, 0x1b, 0xde, 0xc0, 0x81, 0xa8, + 0x88, 0x2e, 0x5a, 0x24, 0xd7, 0x8b, 0x48, 0xb6, 0xdd, 0x16, 0x37, 0x27, + 0xb9, 0x3f, 0x80, 0x37, 0x34, 0xe0, 0x6a, 0x3e +}; +static const uint8_t ac_dsa_vect250_pub_val[] = { +/* Y */ + 0x75, 0xd7, 0xd9, 0xa5, 0xdb, 0xdd, 0x47, 0xce, 0xcd, 0x12, 0xf6, 0x9a, + 0xb2, 0x12, 0xdf, 0xe0, 0x8a, 0x96, 0x56, 0xe2, 0xbc, 0xa9, 0x2c, 0x81, + 0xdb, 0x2d, 0x26, 0x8a, 0x29, 0x3a, 0x32, 0x5e, 0x51, 0x1c, 0xd5, 0xaa, + 0x1b, 0xa5, 0x9d, 0xee, 0xf2, 0xab, 0x63, 0x11, 0x66, 0x5d, 0xda, 0x58, + 0x23, 0x0d, 0x48, 0xf1, 0x41, 0x63, 0x71, 0xde, 0x1a, 0x83, 0x64, 0xb3, + 0x8f, 0x5a, 0xd5, 0x99, 0xc4, 0x72, 0xd3, 0x63, 0xa1, 0x8a, 0x2c, 0x13, + 0xd5, 0x72, 0xcf, 0x84, 0x9b, 0xe2, 0xfe, 0xf9, 0xa1, 0x66, 0xe8, 0x38, + 0xaa, 0x58, 0xb7, 0x21, 0xec, 0xfc, 0x4b, 0x36, 0x1f, 0xda, 0xb1, 0xd0, + 0x87, 0x6b, 0x78, 0xe2, 0xe8, 0xf2, 0x3e, 0xf1, 0xc8, 0x2c, 0xc0, 0xe1, + 0x70, 0x0f, 0xa0, 0x15, 0xa4, 0x00, 0x7b, 0x1d, 0x7b, 0x53, 0x5c, 0x82, + 0xd2, 0x3c, 0x12, 0x9d, 0x1d, 0x1c, 0x9c, 0x4a, 0xfe, 0x87, 0x5a, 0x06, + 0xc0, 0x5f, 0x71, 0xf0, 0x78, 0xcb, 0x8d, 0x90, 0x60, 0xf4, 0xd9, 0x36, + 0x67, 0x1f, 0xae, 0xe2, 0x17, 0xd4, 0x04, 0x55, 0x25, 0xd5, 0x70, 0xb0, + 0xc8, 0xca, 0x0c, 0x4e, 0x8b, 0x55, 0xdf, 0xe9, 0xb7, 0x80, 0xba, 0x69, + 0xc9, 0xd8, 0xcd, 0xa1, 0x0c, 0x50, 0xfd, 0x61, 0xc4, 0xe7, 0x21, 0x4b, + 0x94, 0x3c, 0x1c, 0x29, 0x79, 0x7b, 0x09, 0x9f, 0x57, 0xa4, 0xc6, 0x48, + 0x59, 0x7c, 0xed, 0xd9, 0xd9, 0x09, 0xbc, 0x58, 0x4a, 0x9b, 0x75, 0x4b, + 0x20, 0x95, 0x15, 0xdb, 0xfa, 0x0f, 0xec, 0xce, 0x2a, 0xd0, 0x5c, 0x84, + 0x8e, 0x99, 0xdc, 0xa2, 0x1a, 0x6d, 0x0d, 0x5f, 0x2d, 0xac, 0x23, 0x61, + 0xe4, 0xc0, 0xea, 0xf9, 0x6d, 0xf1, 0x99, 0xad, 0x28, 0x88, 0xd6, 0x71, + 0x97, 0x4e, 0xf0, 0x5d, 0x65, 0xc9, 0x27, 0x88, 0x43, 0x4a, 0xb4, 0x2f, + 0x1f, 0x1f, 0x79, 0xed, 0xc4, 0x9e, 0xc1, 0xfa, 0x92, 0x13, 0x95, 0xbd, + 0x0f, 0xeb, 0x6a, 0x9e, 0x6a, 0x06, 0x22, 0xe8, 0x25, 0x5b, 0x0e, 0xf6, + 0x93, 0x7b, 0x89, 0xd0, 0xcc, 0xcd, 0x58, 0x52, 0x87, 0x2d, 0x2b, 0x0a, + 0xb5, 0xd7, 0x9c, 0x2f, 0x19, 0x8b, 0xff, 0x6b, 0x8a, 0xa3, 0x8a, 0xce, + 0xe2, 0x1d, 0x6c, 0x3a, 0xdd, 0x55, 0x62, 0xd8, 0x4d, 0x96, 0x87, 0x58, + 0xd9, 0x3e, 0x8c, 0x1d, 0x61, 0x1f, 0x7d, 0x61, 0x82, 0xb6, 0x2e, 0x44, + 0xf5, 0x7d, 0xf3, 0x42, 0x89, 0x9b, 0xb5, 0x64, 0xa7, 0x94, 0xd1, 0x39, + 0x15, 0x88, 0x21, 0x43, 0xd9, 0xdf, 0x45, 0xf8, 0xf2, 0x1c, 0xc0, 0x30, + 0xaf, 0x33, 0x97, 0xe9, 0xe9, 0x49, 0x68, 0x3d, 0xdd, 0x8d, 0x8d, 0xa9, + 0x90, 0x9c, 0xc1, 0x13, 0x96, 0x19, 0xe4, 0xb7, 0xb2, 0x52, 0xaa, 0xdd, + 0x02, 0xc6, 0x6a, 0x5e, 0x20, 0x10, 0x5a, 0xdf, 0x26, 0xf2, 0xf0, 0x21 +}; +/* K = 5de7fe70b5c60ec0ba66ade4fb6b0c925d1d56d26d6f57c5d12d07b5f6f800ed */ +static const uint8_t ac_dsa_vect250_out[] = { +/* R */ + 0x01, 0xe3, 0xde, 0x39, 0x8b, 0x01, 0x8a, 0x69, 0x47, 0x80, 0xdd, 0xc6, + 0xca, 0x12, 0xb7, 0x8d, 0xc5, 0x5e, 0x7a, 0xd9, 0xfd, 0xdd, 0xb5, 0xa3, + 0xf5, 0xb2, 0xca, 0xd0, 0x10, 0x32, 0x53, 0xdd, +/* S */ + 0x03, 0xc9, 0x82, 0x80, 0xab, 0xe3, 0x05, 0x0a, 0x67, 0xf8, 0x8e, 0xf2, + 0x9f, 0xb2, 0x14, 0xa8, 0x01, 0x24, 0xf4, 0x73, 0x21, 0xc6, 0x2e, 0x41, + 0xe3, 0x90, 0x5b, 0x85, 0x32, 0xf4, 0x93, 0x6c +}; +#define ac_dsa_vect251_prime ac_dsa_vect241_prime +#define ac_dsa_vect251_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect251_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect251_ptx[] = { +/* Msg */ + 0x6c, 0x66, 0x05, 0x1e, 0x04, 0xc2, 0xe6, 0xaa, 0xa4, 0x3d, 0xe9, 0xaa, + 0x42, 0xcd, 0x9f, 0x61, 0xe8, 0x32, 0x9c, 0x12, 0x4e, 0xd3, 0x03, 0x1b, + 0x67, 0x45, 0x2d, 0xb4, 0xc4, 0x35, 0xdb, 0x29, 0x1d, 0x75, 0x6b, 0xa6, + 0xef, 0x90, 0xab, 0x06, 0x30, 0x7c, 0xb8, 0xd7, 0x0f, 0x34, 0x96, 0x79, + 0x2e, 0x63, 0x3b, 0xf5, 0xac, 0x98, 0x5c, 0x37, 0xc4, 0x3b, 0xdb, 0x4e, + 0x45, 0x5c, 0x7f, 0x76, 0x1a, 0x5e, 0xe4, 0x50, 0x56, 0x7f, 0x85, 0xcc, + 0x97, 0x7e, 0x96, 0x8e, 0x7f, 0xa4, 0x2a, 0x42, 0x8c, 0x1a, 0x7e, 0x91, + 0x5c, 0x82, 0x87, 0x48, 0x65, 0x63, 0x1d, 0x80, 0x78, 0x89, 0x93, 0x77, + 0x25, 0x59, 0x47, 0xc3, 0x44, 0x61, 0x82, 0x97, 0xb8, 0x3c, 0x96, 0x11, + 0x4d, 0x11, 0xd7, 0x4d, 0x8c, 0xd5, 0x79, 0xb5, 0x53, 0x66, 0x7c, 0xac, + 0x1d, 0x97, 0xae, 0xa4, 0xd1, 0x68, 0x49, 0x87 +}; +static const uint8_t ac_dsa_vect251_priv_val[] = { +/* X */ + 0x11, 0xd2, 0xf1, 0x02, 0x93, 0xc3, 0x88, 0x4b, 0x1e, 0x28, 0xa6, 0x00, + 0xdd, 0x71, 0xb2, 0xed, 0x37, 0xbe, 0xa1, 0x33, 0x25, 0x5a, 0x0f, 0x97, + 0xe6, 0x41, 0xf9, 0x53, 0x0b, 0xb4, 0x69, 0x3c +}; +static const uint8_t ac_dsa_vect251_pub_val[] = { +/* Y */ + 0xed, 0x2e, 0x10, 0xa4, 0x43, 0x16, 0xd6, 0x77, 0x46, 0x7d, 0x79, 0x94, + 0x7b, 0xec, 0x9e, 0x40, 0x5d, 0x30, 0xf3, 0x2d, 0x86, 0x0a, 0x1c, 0xe4, + 0x6b, 0x36, 0x68, 0x45, 0xdf, 0x9a, 0xd2, 0x22, 0xb0, 0xf9, 0x92, 0xf5, + 0x84, 0x45, 0x71, 0xb1, 0x96, 0xa3, 0x10, 0xd5, 0x87, 0xff, 0xfa, 0x74, + 0xbd, 0x51, 0x02, 0x15, 0xf3, 0xbd, 0xaf, 0xa1, 0xc9, 0x3d, 0x1b, 0x13, + 0x15, 0x24, 0x6f, 0xd2, 0xf7, 0x94, 0xc4, 0xda, 0x07, 0xbd, 0x72, 0x2a, + 0x98, 0xdd, 0xa9, 0xa0, 0x2a, 0xd4, 0x25, 0x5b, 0x6d, 0x52, 0x67, 0x73, + 0x82, 0x56, 0xcb, 0x86, 0x39, 0xa1, 0x45, 0xc2, 0x84, 0x04, 0x56, 0x2a, + 0xdd, 0x2b, 0xc7, 0x69, 0x1d, 0xac, 0x12, 0x60, 0x0b, 0xa9, 0xf8, 0xeb, + 0xe0, 0x06, 0x14, 0xee, 0x3f, 0xc6, 0xe6, 0xb2, 0x48, 0x4d, 0x9c, 0x5c, + 0x70, 0x90, 0xb3, 0xf3, 0xb1, 0x34, 0xba, 0x19, 0x90, 0x98, 0x64, 0x56, + 0x30, 0x40, 0xfe, 0x87, 0x52, 0xd6, 0xc6, 0xab, 0x95, 0x11, 0x1f, 0xe1, + 0x01, 0x4b, 0xf7, 0xbb, 0xe4, 0xe6, 0x74, 0xc9, 0xd0, 0x3b, 0xb8, 0xd2, + 0x29, 0xe4, 0xb5, 0xf6, 0xa6, 0xe4, 0x71, 0xc6, 0x78, 0xb0, 0x26, 0x5e, + 0x88, 0xcc, 0xad, 0x79, 0x60, 0xff, 0xfa, 0xe7, 0x00, 0xf3, 0xa7, 0x5e, + 0x61, 0xa2, 0x4e, 0xa8, 0x82, 0xb9, 0x70, 0x53, 0x5e, 0xb7, 0x01, 0x7e, + 0x16, 0xc4, 0x8c, 0xe9, 0xe2, 0xbc, 0x83, 0x57, 0xf7, 0xf0, 0x88, 0x9c, + 0x87, 0x1d, 0x0b, 0x4c, 0xe2, 0x9d, 0x27, 0x9a, 0xfd, 0x1d, 0x11, 0x49, + 0x98, 0xd1, 0xeb, 0x6f, 0xe4, 0xa5, 0x66, 0x1e, 0x42, 0x9b, 0x13, 0x27, + 0xf0, 0xa3, 0x9e, 0x9e, 0xf0, 0x0a, 0x41, 0xa7, 0x4f, 0xe4, 0x79, 0xb9, + 0x0f, 0xdd, 0xa2, 0x1d, 0x93, 0x15, 0x55, 0x5a, 0xfe, 0x22, 0x72, 0x74, + 0xc1, 0x1a, 0x71, 0xc0, 0xd1, 0x0c, 0x9e, 0x5d, 0xfc, 0x89, 0x75, 0x0e, + 0xda, 0x53, 0xc6, 0xa8, 0xb5, 0x2a, 0x52, 0x72, 0xc7, 0x55, 0x26, 0x37, + 0x5e, 0x5f, 0xb9, 0x1f, 0xf7, 0x5d, 0x02, 0x8d, 0xf7, 0xaa, 0x2b, 0xce, + 0xb5, 0xfd, 0xf6, 0xf8, 0xe3, 0xbc, 0x1e, 0xc3, 0xf1, 0xe2, 0x26, 0xd0, + 0x4d, 0xf1, 0xd8, 0x42, 0xe4, 0xc8, 0xf4, 0x58, 0x98, 0x8c, 0xb7, 0x41, + 0x5f, 0x0d, 0x2c, 0xa4, 0x49, 0x8b, 0x0c, 0xd6, 0x7e, 0x8b, 0x08, 0x5b, + 0x00, 0x8f, 0xc4, 0xca, 0x06, 0x43, 0x93, 0xa0, 0xdf, 0x51, 0x7f, 0x0b, + 0x48, 0x33, 0xea, 0x40, 0x51, 0xac, 0x3f, 0x1d, 0xe5, 0x68, 0x6d, 0xcc, + 0xb7, 0xbb, 0xa8, 0xbd, 0x93, 0x90, 0x92, 0xd6, 0xd7, 0x8f, 0xa0, 0x8f, + 0x5b, 0xf9, 0xbf, 0x6f, 0x13, 0xd7, 0xae, 0xf7, 0x2f, 0x04, 0x7f, 0xcc, + 0x47, 0xa8, 0x82, 0x23, 0xdf, 0x6e, 0x1a, 0x62, 0xd2, 0x18, 0x16, 0x9f +}; +/* K = 2621703fb8f5094bc68eea72d5b5caf26f8ea3a173158b8d3e7f9565296767f0 */ +static const uint8_t ac_dsa_vect251_out[] = { +/* R */ + 0x31, 0xf2, 0xc8, 0x62, 0x87, 0xe5, 0x72, 0xff, 0x4d, 0x07, 0x42, 0x1a, + 0x58, 0xdc, 0x7b, 0x3d, 0x72, 0x7d, 0xe1, 0x13, 0x76, 0x99, 0x52, 0xb6, + 0xd8, 0xd7, 0x36, 0x08, 0x8b, 0x36, 0xa8, 0x25, +/* S */ + 0x30, 0xac, 0xbd, 0x1c, 0x4c, 0xd6, 0xaa, 0x66, 0x6e, 0xe5, 0x2b, 0x0b, + 0xdc, 0x41, 0xfc, 0x3b, 0x23, 0x9b, 0x60, 0xd5, 0x7e, 0x27, 0x9b, 0x3f, + 0x54, 0x83, 0xc4, 0xd5, 0x4b, 0xdd, 0x97, 0xa6 +}; +#define ac_dsa_vect252_prime ac_dsa_vect241_prime +#define ac_dsa_vect252_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect252_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect252_ptx[] = { +/* Msg */ + 0x5f, 0x8d, 0x7f, 0x28, 0x3a, 0xf0, 0x03, 0x84, 0xa5, 0x19, 0x76, 0x90, + 0x29, 0xd2, 0x08, 0xb6, 0x1e, 0xee, 0x0e, 0x1c, 0xb2, 0x1c, 0xe9, 0xfb, + 0x80, 0xe9, 0xd8, 0x59, 0x6b, 0x89, 0x45, 0x80, 0xda, 0x7a, 0xb3, 0x45, + 0x74, 0x29, 0xe7, 0x2d, 0xfa, 0x64, 0xe7, 0xcb, 0x83, 0x94, 0x14, 0xde, + 0x34, 0x4d, 0xa2, 0x1c, 0xff, 0x55, 0xb1, 0xb3, 0xa8, 0x31, 0x89, 0xd2, + 0x08, 0xad, 0x20, 0x89, 0xb3, 0x5a, 0xbd, 0x78, 0xe2, 0x41, 0x6b, 0xce, + 0xb6, 0x64, 0x66, 0x76, 0x2f, 0xd7, 0xab, 0x9c, 0x23, 0x4c, 0x4a, 0xec, + 0x38, 0x72, 0xcb, 0xc8, 0x44, 0x3c, 0x92, 0xb8, 0xce, 0x4e, 0xe4, 0x59, + 0x54, 0x25, 0xe7, 0x46, 0xe4, 0xb6, 0xf7, 0x97, 0x2e, 0xbd, 0x5d, 0x06, + 0x5f, 0xb3, 0xfd, 0xc5, 0xe3, 0x29, 0xe8, 0xa8, 0x7e, 0xd3, 0xcd, 0xdb, + 0xe2, 0x79, 0xd5, 0x72, 0x27, 0xae, 0x4b, 0x13 +}; +static const uint8_t ac_dsa_vect252_priv_val[] = { +/* X */ + 0x1d, 0xe9, 0x25, 0xbf, 0x53, 0x2a, 0x50, 0xdc, 0x7a, 0x10, 0x98, 0x4b, + 0xd1, 0xdb, 0xd9, 0x05, 0x00, 0xec, 0x9a, 0xd2, 0x2d, 0xf0, 0xf2, 0xd6, + 0xf1, 0x85, 0xfd, 0x1b, 0xa8, 0x06, 0x0d, 0x37 +}; +static const uint8_t ac_dsa_vect252_pub_val[] = { +/* Y */ + 0xaa, 0x4d, 0x06, 0x52, 0x70, 0xc3, 0x8b, 0xdf, 0x99, 0x6b, 0x1f, 0x5f, + 0x1e, 0xe4, 0xb6, 0x7a, 0x76, 0xef, 0x1e, 0x7b, 0x13, 0x4e, 0xa2, 0x1f, + 0xd0, 0xa6, 0x13, 0x75, 0x21, 0x24, 0x50, 0x52, 0xe7, 0x49, 0x54, 0xb9, + 0x65, 0x44, 0xc7, 0x00, 0xd4, 0x0f, 0x36, 0x24, 0x8f, 0xf2, 0x9a, 0x71, + 0x2a, 0x09, 0x8d, 0x80, 0xca, 0x12, 0xe2, 0x8f, 0xdd, 0x79, 0x01, 0xa6, + 0x22, 0xdd, 0x09, 0x88, 0xe1, 0xc4, 0xd6, 0x7d, 0xe4, 0xc4, 0x97, 0xa9, + 0x57, 0x88, 0x2c, 0xe9, 0x92, 0xfc, 0xb0, 0x8c, 0x5b, 0x85, 0xc6, 0x85, + 0x84, 0x47, 0xed, 0x6f, 0xcb, 0xad, 0x26, 0xd8, 0xc4, 0x04, 0x85, 0xf0, + 0xa8, 0x9d, 0x9d, 0x02, 0x0f, 0xe2, 0x33, 0xe8, 0x93, 0x19, 0x03, 0x84, + 0x55, 0x64, 0x4c, 0x82, 0x8d, 0x60, 0x8d, 0xf9, 0x70, 0x7c, 0x63, 0x17, + 0x0d, 0xd0, 0x61, 0x8c, 0x0b, 0xae, 0xf3, 0xec, 0xa8, 0xd1, 0x45, 0x54, + 0x60, 0xa2, 0xeb, 0x25, 0xfa, 0xff, 0x44, 0x4f, 0x80, 0x3b, 0xca, 0x29, + 0x7b, 0xb6, 0x80, 0xe5, 0xf0, 0xfd, 0x06, 0xe8, 0x87, 0xed, 0x50, 0xc8, + 0x06, 0x0f, 0x55, 0xd0, 0x16, 0x0e, 0xc6, 0x45, 0x17, 0x08, 0x6f, 0x4e, + 0x1d, 0x62, 0x4a, 0xb7, 0xd1, 0x2d, 0xf1, 0xb5, 0x94, 0x70, 0x17, 0xe6, + 0x22, 0xeb, 0xbc, 0xd6, 0xf4, 0xed, 0xdb, 0x0a, 0x41, 0xdc, 0xba, 0x82, + 0x74, 0x3e, 0xfd, 0xc5, 0x80, 0x42, 0x88, 0xd2, 0x86, 0x3f, 0x54, 0x00, + 0x3e, 0xea, 0x12, 0x75, 0x32, 0x46, 0xe6, 0xe0, 0x35, 0x7d, 0xf0, 0x55, + 0x01, 0xb1, 0x95, 0xfd, 0xf3, 0xa7, 0x76, 0x1c, 0x4c, 0x3a, 0xcf, 0x26, + 0x53, 0x7b, 0xf9, 0x8b, 0x32, 0xf2, 0xe7, 0x2f, 0xf1, 0xe0, 0x15, 0x9d, + 0x04, 0x6b, 0xbc, 0x05, 0x31, 0x71, 0xe3, 0xd5, 0x18, 0x34, 0x4f, 0x05, + 0x37, 0xf2, 0xe7, 0x20, 0x0b, 0xcd, 0xd9, 0x57, 0xec, 0x96, 0x36, 0x5c, + 0xaf, 0x55, 0xfc, 0xd2, 0x46, 0xaf, 0xe7, 0x71, 0x70, 0x9e, 0xce, 0xc2, + 0x83, 0x48, 0xa3, 0x56, 0xa1, 0xd4, 0xeb, 0x13, 0x6a, 0x17, 0x6a, 0xdb, + 0x5f, 0xa1, 0x02, 0xf5, 0xfa, 0x5c, 0x96, 0x9f, 0x90, 0x89, 0x64, 0x62, + 0xe0, 0x67, 0x7a, 0xfc, 0x60, 0x6a, 0x94, 0x8b, 0x25, 0x58, 0x7c, 0x10, + 0x31, 0x6d, 0x22, 0xe1, 0x26, 0x9f, 0xc6, 0x4f, 0x91, 0x5a, 0x79, 0x6c, + 0x96, 0x5b, 0x8b, 0xe9, 0x7e, 0x5b, 0xea, 0xb0, 0x47, 0xca, 0x51, 0x98, + 0xbf, 0x2f, 0xf8, 0x56, 0xdf, 0x74, 0x0a, 0xfb, 0xbc, 0x1a, 0xef, 0xaf, + 0xef, 0xb1, 0xed, 0x47, 0x27, 0x8b, 0x15, 0x0e, 0x6a, 0x72, 0x22, 0x41, + 0x7d, 0x3a, 0x86, 0x49, 0x4b, 0xdb, 0x51, 0xed, 0xd0, 0x61, 0x68, 0x99, + 0x52, 0x6c, 0x27, 0xac, 0xc2, 0xa8, 0x18, 0xe8, 0x3b, 0xaf, 0x57, 0x9b +}; +/* K = 5f0d6676776f40cfd5ca255fd8e32b10bf3472b193818914876d4c3be68a83b9 */ +static const uint8_t ac_dsa_vect252_out[] = { +/* R */ + 0x71, 0x87, 0xca, 0xe8, 0x36, 0x82, 0x36, 0x18, 0xf9, 0xa6, 0xe8, 0x47, + 0x05, 0x5c, 0xa2, 0xbc, 0x38, 0xc8, 0x6e, 0x72, 0x6d, 0x02, 0xd3, 0x8f, + 0x49, 0x50, 0xeb, 0x6b, 0x71, 0xb3, 0x6b, 0xcb, +/* S */ + 0x21, 0xf6, 0xff, 0x41, 0x75, 0x76, 0x54, 0x30, 0xe2, 0xdb, 0xed, 0x34, + 0x2a, 0x85, 0xd3, 0x00, 0x56, 0xb2, 0x89, 0x05, 0x74, 0x4e, 0xce, 0x5d, + 0xad, 0x79, 0x75, 0x5e, 0xe3, 0xd7, 0xbb, 0xbd +}; +#define ac_dsa_vect253_prime ac_dsa_vect241_prime +#define ac_dsa_vect253_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect253_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect253_ptx[] = { +/* Msg */ + 0xb2, 0x16, 0xa0, 0x35, 0xb0, 0xff, 0x29, 0xfe, 0xaf, 0x7d, 0x4c, 0x34, + 0xee, 0xb1, 0x60, 0x41, 0x55, 0xc9, 0x03, 0x38, 0x00, 0x67, 0x53, 0xee, + 0x2b, 0x36, 0x06, 0x2d, 0x72, 0xf6, 0x2b, 0x52, 0x45, 0x04, 0x65, 0x9f, + 0x70, 0xb9, 0x76, 0xc6, 0x89, 0x52, 0xa6, 0x2c, 0x2b, 0x9a, 0x2a, 0x00, + 0xcf, 0x00, 0x66, 0xa5, 0xe5, 0x09, 0x8a, 0x63, 0x2d, 0xf2, 0xee, 0x56, + 0xdd, 0x1a, 0x14, 0x0a, 0x98, 0xf7, 0xb3, 0xac, 0x12, 0xdb, 0x35, 0x76, + 0xb6, 0x10, 0xd7, 0x65, 0x63, 0xe4, 0x62, 0x16, 0x37, 0xda, 0x10, 0x98, + 0xaa, 0x20, 0xf3, 0xc8, 0x32, 0x47, 0xb7, 0x27, 0x88, 0x60, 0x41, 0x7c, + 0xec, 0xf7, 0xe1, 0x37, 0x19, 0x4c, 0xf1, 0xba, 0xe1, 0x2b, 0xbc, 0x63, + 0xa7, 0xba, 0xe0, 0x2c, 0x90, 0x6d, 0x50, 0x3f, 0x69, 0x4d, 0xea, 0x3b, + 0xd5, 0x34, 0x71, 0x8e, 0x37, 0x70, 0x49, 0x62 +}; +static const uint8_t ac_dsa_vect253_priv_val[] = { +/* X */ + 0x3b, 0xae, 0x93, 0x30, 0xb4, 0x7a, 0xab, 0x85, 0xce, 0xc9, 0x48, 0xf9, + 0x44, 0xac, 0x13, 0x22, 0x1a, 0xd3, 0x5d, 0x85, 0x9d, 0xe5, 0x6d, 0xb5, + 0x6c, 0x31, 0xaa, 0xe8, 0x83, 0x45, 0xcb, 0xea +}; +static const uint8_t ac_dsa_vect253_pub_val[] = { +/* Y */ + 0x7d, 0x6b, 0x3b, 0x71, 0xb1, 0x41, 0x58, 0x07, 0xd1, 0x59, 0x01, 0x42, + 0x7e, 0x6a, 0xb0, 0x02, 0xee, 0x98, 0x5c, 0xe7, 0xc8, 0xd8, 0x44, 0x96, + 0x9c, 0x6e, 0x72, 0x94, 0xa2, 0x16, 0x7b, 0x4c, 0x26, 0x17, 0x1b, 0xcd, + 0x64, 0x6f, 0x0d, 0x1b, 0xce, 0x14, 0xdf, 0x05, 0xe4, 0xce, 0x58, 0xa3, + 0xae, 0x50, 0xb2, 0xab, 0xa5, 0xfb, 0x74, 0x45, 0x52, 0x33, 0xfa, 0x6d, + 0x17, 0x9a, 0x07, 0x94, 0xcb, 0x26, 0xe9, 0x2c, 0xa9, 0x10, 0xcd, 0x1c, + 0x16, 0xe5, 0x46, 0x4e, 0x8f, 0xa7, 0xba, 0x93, 0x63, 0x41, 0xd3, 0xac, + 0x21, 0x1a, 0xc1, 0xf8, 0xa2, 0xf2, 0xa1, 0x9c, 0x14, 0x8a, 0x1c, 0x3d, + 0x6b, 0x00, 0xac, 0x44, 0xc3, 0x5e, 0xa3, 0x45, 0xa3, 0xff, 0x73, 0xae, + 0x9d, 0x5a, 0xbc, 0xc6, 0xab, 0x65, 0x16, 0x2a, 0x53, 0xda, 0xab, 0xdf, + 0x6d, 0xa2, 0x5f, 0x96, 0x95, 0x8e, 0xaf, 0x89, 0xf5, 0x59, 0x89, 0x5c, + 0xbe, 0xc5, 0x23, 0x51, 0x39, 0x4f, 0x91, 0x32, 0xc9, 0x56, 0x4d, 0x61, + 0xaa, 0xc7, 0x92, 0x64, 0x0f, 0x11, 0xe0, 0x9a, 0xa6, 0xf6, 0xcd, 0xe9, + 0xee, 0x9c, 0xa5, 0xe0, 0x5f, 0xd9, 0x02, 0x91, 0x11, 0x63, 0x81, 0x71, + 0x77, 0xbf, 0x05, 0x4c, 0xf2, 0xea, 0xbf, 0x7c, 0xe8, 0xf3, 0x4b, 0xb1, + 0xc4, 0xad, 0xed, 0x8d, 0xad, 0x93, 0x41, 0x1f, 0xb2, 0x76, 0xd2, 0xd0, + 0xa2, 0x96, 0x79, 0x96, 0x61, 0x30, 0x7d, 0xe5, 0x79, 0x64, 0x1e, 0x60, + 0x7f, 0xda, 0xd0, 0x58, 0xd9, 0xa3, 0xf1, 0x94, 0x57, 0x4e, 0xa7, 0x6f, + 0x4b, 0xec, 0x46, 0xbe, 0xf8, 0xad, 0xc5, 0xd6, 0x2c, 0x73, 0x90, 0xda, + 0x1c, 0x45, 0xf6, 0xfc, 0x5d, 0x9a, 0x78, 0x4f, 0x69, 0x6f, 0x24, 0xae, + 0x7e, 0x6b, 0x27, 0xa8, 0x09, 0x02, 0x94, 0x18, 0xdd, 0x18, 0xa4, 0x20, + 0x45, 0x5c, 0x2c, 0xc9, 0x69, 0x5e, 0x7c, 0x0f, 0xe0, 0x02, 0x19, 0xa1, + 0x71, 0x14, 0x68, 0xe2, 0x86, 0x6b, 0x71, 0xf3, 0xf9, 0xc5, 0x38, 0x78, + 0x9e, 0xd2, 0x84, 0x3f, 0x44, 0xf2, 0xa8, 0x21, 0x77, 0x3c, 0x52, 0xd2, + 0x11, 0xdd, 0x13, 0x33, 0xb5, 0xf1, 0x64, 0xec, 0xdf, 0x6c, 0x3f, 0xfd, + 0x71, 0xde, 0x66, 0x78, 0xb0, 0xc2, 0x72, 0xf9, 0x23, 0x55, 0xd5, 0x97, + 0x4e, 0xb2, 0x1c, 0x3c, 0x8f, 0xbd, 0x0b, 0xca, 0x75, 0x38, 0xbb, 0xd9, + 0x89, 0x47, 0x50, 0xb1, 0xdd, 0x01, 0x42, 0xbe, 0xa8, 0x51, 0x04, 0x35, + 0x6f, 0x9a, 0x51, 0x5e, 0xf1, 0xab, 0x69, 0xda, 0xed, 0x98, 0xd9, 0x48, + 0x03, 0xac, 0x91, 0x2c, 0x77, 0x0e, 0x26, 0xef, 0xa2, 0xfa, 0x0b, 0x04, + 0xe1, 0x10, 0x51, 0xce, 0xd2, 0xf7, 0x0f, 0x06, 0xf2, 0xf0, 0x5e, 0xac, + 0x80, 0x29, 0xd6, 0x8e, 0x12, 0x26, 0x16, 0x57, 0xcf, 0x4d, 0xbc, 0xc1 +}; +/* K = 248048e6fc52c48398f5cd2ccd8a659c4b7b76dedf54f3fb90c5bb173c5d24f7 */ +static const uint8_t ac_dsa_vect253_out[] = { +/* R */ + 0x67, 0xdf, 0x1d, 0x51, 0x0d, 0x06, 0x3c, 0x90, 0x67, 0xe9, 0x75, 0x91, + 0x80, 0xbe, 0x47, 0x0c, 0x71, 0xfe, 0x09, 0xc4, 0xf1, 0x33, 0xac, 0xa1, + 0x81, 0xbd, 0xb4, 0x7b, 0xb8, 0x7b, 0x20, 0x97, +/* S */ + 0x73, 0x28, 0xb8, 0x87, 0xbf, 0x0d, 0x52, 0x0a, 0xbe, 0x6f, 0x24, 0xaf, + 0xf2, 0x15, 0x3f, 0x40, 0xde, 0x00, 0x9e, 0x27, 0x06, 0xae, 0x04, 0x3d, + 0xd3, 0xaa, 0x55, 0x52, 0x1d, 0x95, 0x72, 0xd6 +}; +#define ac_dsa_vect254_prime ac_dsa_vect241_prime +#define ac_dsa_vect254_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect254_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect254_ptx[] = { +/* Msg */ + 0x6c, 0x67, 0x11, 0x6f, 0xbd, 0x21, 0xa0, 0xe3, 0xed, 0x16, 0xb3, 0xc4, + 0xca, 0x58, 0xac, 0x49, 0x66, 0x19, 0x18, 0xbf, 0xc6, 0xa7, 0xc3, 0xa6, + 0xac, 0xdb, 0xcd, 0x53, 0xdd, 0x40, 0x87, 0x03, 0x4f, 0xca, 0x16, 0x4d, + 0xf8, 0xd3, 0x8f, 0x7e, 0xf7, 0xdb, 0x03, 0x36, 0x37, 0x01, 0x40, 0x92, + 0x46, 0x38, 0x2e, 0xe0, 0x53, 0xc6, 0x9c, 0x84, 0xfa, 0xfa, 0x3c, 0x77, + 0xad, 0x2c, 0xe0, 0x8d, 0xc7, 0xf4, 0x1c, 0x34, 0xa3, 0x1d, 0xa4, 0x96, + 0xd0, 0x70, 0xa9, 0x94, 0x35, 0x79, 0x9f, 0x26, 0x9d, 0xc8, 0xef, 0xfd, + 0x06, 0xd3, 0x1f, 0x85, 0x87, 0x9c, 0x29, 0x9c, 0xf7, 0x24, 0x1b, 0x37, + 0xb9, 0xa4, 0xcf, 0xd5, 0x45, 0x08, 0x63, 0x93, 0x15, 0x67, 0x37, 0xcd, + 0x9d, 0xa2, 0xd2, 0x82, 0xe7, 0xd5, 0x69, 0xfc, 0xfa, 0x5c, 0xbd, 0xe4, + 0xbb, 0xa5, 0x1b, 0xd8, 0x9f, 0xdc, 0xc9, 0x13 +}; +static const uint8_t ac_dsa_vect254_priv_val[] = { +/* X */ + 0x7f, 0xa6, 0x61, 0x20, 0xc5, 0xac, 0xd5, 0xba, 0xc1, 0x32, 0xd0, 0x70, + 0x83, 0xd0, 0x79, 0x68, 0xb2, 0x10, 0xcd, 0x9c, 0x26, 0xc2, 0xc5, 0x6d, + 0x9b, 0x16, 0xd9, 0x80, 0x66, 0xf5, 0xdf, 0x6e +}; +static const uint8_t ac_dsa_vect254_pub_val[] = { +/* Y */ + 0x6a, 0x50, 0xd1, 0x12, 0x5f, 0x9f, 0x3f, 0xc2, 0xf7, 0xe0, 0x23, 0xc0, + 0x93, 0xb3, 0x60, 0x8e, 0x69, 0x72, 0xac, 0xef, 0xe2, 0x9c, 0x0c, 0x6b, + 0xa0, 0x7a, 0x2f, 0x61, 0xed, 0x74, 0x71, 0x53, 0xad, 0xa4, 0xa9, 0xb6, + 0x80, 0x62, 0x2a, 0x84, 0x2b, 0x9a, 0x82, 0x01, 0x19, 0x67, 0x56, 0x20, + 0xc1, 0x16, 0x88, 0x70, 0x0b, 0x85, 0x5d, 0x4b, 0x8d, 0x13, 0xbf, 0x72, + 0x6c, 0x36, 0xac, 0xf9, 0x23, 0x25, 0x6f, 0xef, 0x1b, 0x53, 0x09, 0x36, + 0x22, 0xd1, 0xbc, 0xbc, 0xf0, 0x23, 0x84, 0x8b, 0x8b, 0x8f, 0x4a, 0xbf, + 0x43, 0xbb, 0x6e, 0x87, 0xb8, 0x4d, 0x06, 0x1d, 0xeb, 0x75, 0x23, 0x62, + 0x24, 0xce, 0xda, 0x91, 0x4b, 0x18, 0xf7, 0xce, 0xb7, 0x27, 0x08, 0x78, + 0x9d, 0xfb, 0x94, 0x07, 0x04, 0x13, 0xb0, 0xe6, 0x5c, 0x12, 0x31, 0xad, + 0x02, 0xdb, 0x42, 0xde, 0xcb, 0xe0, 0xe5, 0x58, 0xae, 0xa0, 0x6c, 0x31, + 0x0a, 0xa1, 0xa8, 0xd1, 0x13, 0xbe, 0x1f, 0x07, 0x14, 0x82, 0xfc, 0x61, + 0x91, 0x32, 0x25, 0xf0, 0x07, 0xb5, 0x69, 0xb6, 0xe8, 0x67, 0xcf, 0xb3, + 0x92, 0x72, 0x57, 0x76, 0xad, 0x71, 0xf5, 0x0d, 0xc9, 0x7b, 0x83, 0x4a, + 0x71, 0x37, 0x5b, 0xac, 0x18, 0xfa, 0xbf, 0x78, 0x11, 0x26, 0xd0, 0x6d, + 0xf6, 0x21, 0x24, 0x06, 0x4e, 0x6a, 0x72, 0x3b, 0x48, 0x63, 0x5e, 0x67, + 0x54, 0xfc, 0x76, 0x7a, 0x50, 0x94, 0xd0, 0x64, 0x59, 0x74, 0x04, 0x15, + 0x91, 0xd0, 0xad, 0x48, 0x28, 0xf6, 0x37, 0x83, 0x35, 0x66, 0x96, 0xaf, + 0x7f, 0xf7, 0x7c, 0xd0, 0x01, 0x07, 0x94, 0x9f, 0xbf, 0xf4, 0x70, 0x9d, + 0xff, 0x8a, 0x66, 0x0a, 0x41, 0x3f, 0x5b, 0x6c, 0x0d, 0xf3, 0x7a, 0xde, + 0x84, 0xfc, 0xbc, 0x1d, 0x32, 0x53, 0xba, 0x61, 0x72, 0x65, 0xa1, 0x0c, + 0xc0, 0x87, 0x60, 0x61, 0x30, 0x29, 0x09, 0x09, 0xa4, 0xf8, 0x13, 0x34, + 0x1e, 0xfd, 0xb6, 0x11, 0x69, 0x6f, 0xeb, 0x5b, 0xea, 0x3d, 0x7d, 0x00, + 0xa5, 0x3a, 0x81, 0xf3, 0xa2, 0x04, 0x3b, 0x88, 0x7a, 0x77, 0x60, 0x75, + 0xd2, 0x50, 0xc1, 0xa0, 0x10, 0xec, 0x47, 0x66, 0x00, 0x87, 0xf3, 0xef, + 0x05, 0x78, 0x2d, 0xd2, 0x1d, 0x29, 0x8d, 0x6d, 0x37, 0x55, 0x9c, 0xd4, + 0x73, 0x00, 0x8f, 0x47, 0x4d, 0x8d, 0xec, 0xa6, 0x81, 0x7c, 0x13, 0x90, + 0x18, 0x02, 0x76, 0x09, 0x7a, 0x81, 0xf4, 0x62, 0xc0, 0x52, 0x79, 0x28, + 0xf9, 0x3a, 0x46, 0x1f, 0x4a, 0xc2, 0xd6, 0xed, 0x8c, 0x9d, 0x6d, 0x10, + 0x1a, 0x2a, 0x9a, 0x29, 0x20, 0x1a, 0x83, 0xd0, 0x58, 0x9f, 0x57, 0xbe, + 0x28, 0xa7, 0x27, 0x48, 0x45, 0x18, 0xc7, 0x42, 0x5c, 0xf5, 0x74, 0x4d, + 0xf3, 0x96, 0xa0, 0xe1, 0x4a, 0x4d, 0x26, 0x0a, 0x5c, 0x8d, 0x29, 0xbf +}; +/* K = 5771223a25f539c80481baebe7b2862156fcf26220d6e953c37f2a22bce77c0e */ +static const uint8_t ac_dsa_vect254_out[] = { +/* R */ + 0x7d, 0x48, 0x9a, 0xb0, 0xd4, 0x4b, 0xc7, 0x32, 0x71, 0xef, 0x42, 0xe2, + 0x8a, 0x60, 0xe1, 0xb7, 0xef, 0x7d, 0xd2, 0x7a, 0xf4, 0x04, 0x55, 0x46, + 0x04, 0x70, 0x85, 0xda, 0x40, 0x8b, 0xcc, 0xc7, +/* S */ + 0x31, 0x01, 0x51, 0xd9, 0x43, 0xf0, 0x88, 0xbb, 0x7d, 0xfd, 0xcd, 0x52, + 0xd8, 0x28, 0x84, 0xa7, 0xf1, 0xee, 0x64, 0xd4, 0x6f, 0x9d, 0x60, 0x0d, + 0x23, 0xf5, 0x2f, 0x4c, 0xea, 0x4d, 0x28, 0x62 +}; +#define ac_dsa_vect255_prime ac_dsa_vect241_prime +#define ac_dsa_vect255_sub_prime ac_dsa_vect241_sub_prime +#define ac_dsa_vect255_base ac_dsa_vect241_base +static const uint8_t ac_dsa_vect255_ptx[] = { +/* Msg */ + 0xc8, 0xd4, 0x16, 0xc1, 0xef, 0xe6, 0x86, 0x63, 0x70, 0x78, 0x12, 0x2f, + 0x79, 0x8d, 0x88, 0x04, 0xf6, 0x4a, 0x6e, 0x85, 0xe0, 0x5f, 0x7e, 0x8e, + 0x07, 0x63, 0x4a, 0x30, 0x9a, 0x98, 0xe9, 0x2a, 0xbd, 0x54, 0x06, 0x1c, + 0xcc, 0xc3, 0x19, 0xf1, 0xac, 0xd4, 0xa0, 0x87, 0xb1, 0xd7, 0xdb, 0xf0, + 0xb6, 0xbf, 0x2a, 0x09, 0xc5, 0xdc, 0x50, 0x8e, 0xd1, 0x4d, 0xcd, 0x54, + 0x42, 0x05, 0x6e, 0xad, 0xe7, 0x69, 0x1b, 0x7f, 0xb6, 0x5b, 0x67, 0x8e, + 0xc2, 0xe1, 0x37, 0xb5, 0xfb, 0xe8, 0x75, 0x20, 0x8a, 0x42, 0x7c, 0x2a, + 0x7a, 0xd9, 0x06, 0x65, 0x42, 0x6f, 0xbc, 0xbc, 0x76, 0x55, 0xe4, 0x8a, + 0x89, 0x65, 0xd2, 0x3f, 0xde, 0xf1, 0x1c, 0xa8, 0x09, 0x2f, 0x51, 0x12, + 0x07, 0xa6, 0x07, 0x35, 0x9f, 0x94, 0xe9, 0x1b, 0x19, 0x7f, 0xcc, 0x99, + 0x3e, 0xe6, 0xce, 0x3c, 0x37, 0xad, 0x3b, 0x71 +}; +static const uint8_t ac_dsa_vect255_priv_val[] = { +/* X */ + 0x1f, 0x4a, 0x3c, 0xf1, 0xfb, 0x60, 0x36, 0x0d, 0xb3, 0x79, 0x0a, 0x03, + 0xfe, 0x55, 0x19, 0x49, 0x85, 0x97, 0x7c, 0x68, 0x84, 0xa5, 0xfc, 0x05, + 0xa6, 0xfb, 0x5e, 0xaf, 0xd5, 0x35, 0x87, 0xf5 +}; +static const uint8_t ac_dsa_vect255_pub_val[] = { +/* Y */ + 0xcc, 0x9b, 0x9d, 0x02, 0x92, 0x91, 0x5d, 0x63, 0x1a, 0xa0, 0xd9, 0xeb, + 0x61, 0x61, 0xf9, 0x24, 0x70, 0x5c, 0x56, 0x6e, 0xe0, 0x9e, 0x74, 0xe4, + 0x18, 0xd8, 0x8e, 0x6b, 0x67, 0xb7, 0xf5, 0x7a, 0xff, 0x51, 0x70, 0xf6, + 0xc4, 0x2a, 0x83, 0x9b, 0xa8, 0x39, 0x40, 0x2b, 0xfe, 0x51, 0x7c, 0x28, + 0x77, 0x81, 0xdc, 0x97, 0xdf, 0x2e, 0x05, 0x50, 0xb3, 0x86, 0x24, 0x84, + 0xd2, 0x53, 0x15, 0x2f, 0x6c, 0xff, 0x89, 0x5f, 0x09, 0x23, 0x58, 0xb5, + 0xc4, 0x45, 0x90, 0x48, 0x58, 0x13, 0x09, 0xef, 0xf2, 0xf6, 0x89, 0x23, + 0x0b, 0x4c, 0x49, 0x51, 0xdb, 0x84, 0x13, 0x57, 0x3b, 0x6e, 0xae, 0x85, + 0xc2, 0xdc, 0x50, 0xfd, 0x61, 0x34, 0x46, 0x13, 0x28, 0xe5, 0xb6, 0x43, + 0x9f, 0x41, 0x44, 0x2b, 0x91, 0xe3, 0xa3, 0x42, 0x04, 0x42, 0x8d, 0x1e, + 0x2c, 0x22, 0x41, 0x2b, 0x01, 0x22, 0x42, 0xb1, 0x4f, 0x92, 0xe2, 0xd1, + 0xba, 0xd6, 0x26, 0xaf, 0x95, 0x05, 0x1b, 0xf0, 0x6c, 0x74, 0xda, 0x40, + 0x81, 0xb0, 0xd6, 0x19, 0xe1, 0x36, 0xa9, 0x9c, 0x8d, 0xa3, 0xa9, 0x1a, + 0xdb, 0x3b, 0x8c, 0xf8, 0xbc, 0x59, 0x64, 0xff, 0x65, 0x5d, 0x45, 0xc7, + 0x5a, 0xda, 0x25, 0x3a, 0xba, 0x91, 0xc6, 0x40, 0x95, 0x39, 0x4c, 0x70, + 0x1c, 0x53, 0xdd, 0xc1, 0x1f, 0x38, 0x8d, 0x61, 0x98, 0x4c, 0x32, 0xd4, + 0x32, 0x6a, 0x8c, 0x62, 0x7d, 0xf8, 0x45, 0xb4, 0x10, 0x0f, 0x17, 0x1b, + 0xbd, 0xb2, 0x52, 0xd3, 0xe2, 0x84, 0x94, 0xac, 0x17, 0x34, 0x32, 0xdd, + 0x55, 0x31, 0xe0, 0x30, 0x40, 0x30, 0x2a, 0xac, 0x8c, 0x07, 0xc9, 0xea, + 0x92, 0xa9, 0xab, 0x67, 0xfa, 0xf0, 0xc7, 0x8b, 0x3a, 0xd8, 0xd4, 0x54, + 0xdc, 0xd4, 0x28, 0xf9, 0x42, 0xd8, 0xce, 0x6e, 0x29, 0x87, 0x30, 0x49, + 0xfd, 0xbf, 0xa1, 0xdf, 0x0e, 0x6e, 0xc2, 0x24, 0xc9, 0xdd, 0x06, 0x6b, + 0x98, 0x1a, 0x40, 0x0b, 0x1f, 0x51, 0x94, 0xfe, 0xe1, 0x3c, 0xc5, 0xca, + 0x7f, 0xfb, 0xec, 0xa9, 0x8e, 0xd0, 0xa0, 0x22, 0x13, 0x77, 0xa1, 0xae, + 0x61, 0x27, 0x40, 0xfc, 0xe7, 0x74, 0xee, 0xed, 0x68, 0x38, 0x2b, 0x32, + 0xb6, 0x86, 0xa2, 0x5f, 0xfc, 0x01, 0x66, 0x82, 0x18, 0x64, 0x48, 0x20, + 0x7c, 0x4d, 0x97, 0x83, 0xe8, 0x3d, 0xa2, 0x0a, 0x5e, 0x8b, 0x22, 0x8a, + 0x13, 0x4d, 0xc3, 0xf4, 0x4e, 0xcc, 0x56, 0x5a, 0xb9, 0xae, 0x16, 0x2b, + 0x85, 0x5e, 0xcd, 0x37, 0xe6, 0x40, 0x7e, 0x71, 0x40, 0x45, 0xf4, 0xe8, + 0x3b, 0x97, 0x1a, 0x5f, 0x4e, 0x30, 0x4c, 0xd7, 0x78, 0xf3, 0xd3, 0x41, + 0x37, 0x74, 0x5f, 0xc6, 0xea, 0x15, 0xb4, 0xb7, 0x4d, 0x60, 0x17, 0x6e, + 0xf8, 0x07, 0x41, 0x0b, 0x1b, 0x26, 0xf6, 0x8e, 0xa1, 0x4f, 0x8f, 0x91 +}; +/* K = 589da8a8ac79ad6b62b353422691f35e6474e9c605d877670dd95738b4935f06 */ +static const uint8_t ac_dsa_vect255_out[] = { +/* R */ + 0x7f, 0xa5, 0x12, 0x31, 0xbc, 0x84, 0x5f, 0xa8, 0xb6, 0x68, 0x39, 0x3b, + 0x78, 0xa7, 0xb0, 0x40, 0x81, 0x13, 0xfb, 0x77, 0xc1, 0xe3, 0x6f, 0x3c, + 0x78, 0xc6, 0x7d, 0x65, 0x71, 0x5a, 0x8b, 0x58, +/* S */ + 0x73, 0x0c, 0x9e, 0x34, 0x83, 0x81, 0x1c, 0x52, 0xcf, 0x29, 0x5b, 0xad, + 0x04, 0x2a, 0xcb, 0x5d, 0xd6, 0xee, 0x90, 0x08, 0x38, 0x57, 0xbe, 0xe9, + 0x5b, 0x63, 0x92, 0xb0, 0x80, 0xb5, 0x04, 0x1d +}; +/* [mod = L=3072, N=256, SHA-256] */ +static const uint8_t ac_dsa_vect256_prime[] = { +/* P */ + 0xc7, 0xb8, 0x6d, 0x70, 0x44, 0x21, 0x8e, 0x36, 0x74, 0x53, 0xd2, 0x10, + 0xe7, 0x64, 0x33, 0xe4, 0xe2, 0x7a, 0x98, 0x3d, 0xb1, 0xc5, 0x60, 0xbb, + 0x97, 0x55, 0xa8, 0xfb, 0x7d, 0x81, 0x99, 0x12, 0xc5, 0x6c, 0xfe, 0x00, + 0x2a, 0xb1, 0xff, 0x3f, 0x72, 0x16, 0x5b, 0x94, 0x3c, 0x0b, 0x28, 0xed, + 0x46, 0x03, 0x9a, 0x07, 0xde, 0x50, 0x7d, 0x7a, 0x29, 0xf7, 0x38, 0x60, + 0x3d, 0xec, 0xd1, 0x27, 0x03, 0x80, 0xa4, 0x1f, 0x97, 0x1f, 0x25, 0x92, + 0x66, 0x1a, 0x64, 0xba, 0x2f, 0x35, 0x1d, 0x9a, 0x69, 0xe5, 0x1a, 0x88, + 0x8a, 0x05, 0x15, 0x6b, 0x7f, 0xe1, 0x56, 0x3c, 0x4b, 0x77, 0xee, 0x93, + 0xa4, 0x49, 0x49, 0x13, 0x84, 0x38, 0xa2, 0xab, 0x8b, 0xdc, 0xfc, 0x49, + 0xb4, 0xe7, 0x8d, 0x1c, 0xde, 0x76, 0x6e, 0x54, 0x98, 0x47, 0x60, 0x05, + 0x7d, 0x76, 0xcd, 0x74, 0x0c, 0x94, 0xa4, 0xdd, 0x25, 0xa4, 0x6a, 0xa7, + 0x7b, 0x18, 0xe9, 0xd7, 0x07, 0xd6, 0x73, 0x84, 0x97, 0xd4, 0xea, 0xc3, + 0x64, 0xf4, 0x79, 0x2d, 0x97, 0x66, 0xa1, 0x6a, 0x0e, 0x23, 0x48, 0x07, + 0xe9, 0x6b, 0x8c, 0x64, 0xd4, 0x04, 0xbb, 0xdb, 0x87, 0x6e, 0x39, 0xb5, + 0x79, 0x9e, 0xf5, 0x3f, 0xe6, 0xcb, 0x9b, 0xab, 0x62, 0xef, 0x19, 0xfd, + 0xcc, 0x2b, 0xdd, 0x90, 0x5b, 0xed, 0xa1, 0x3b, 0x9e, 0xf7, 0xac, 0x35, + 0xf1, 0xf5, 0x57, 0xcb, 0x0d, 0xc4, 0x58, 0xc0, 0x19, 0xe2, 0xbc, 0x19, + 0xa9, 0xf5, 0xdf, 0xc1, 0xe4, 0xec, 0xa9, 0xe6, 0xd4, 0x66, 0x56, 0x41, + 0x24, 0x30, 0x4a, 0x31, 0xf0, 0x38, 0x60, 0x5a, 0x3e, 0x34, 0x2d, 0xa0, + 0x1b, 0xe1, 0xc2, 0xb5, 0x45, 0x61, 0x0e, 0xdd, 0x2c, 0x13, 0x97, 0xa3, + 0xc8, 0x39, 0x65, 0x88, 0xc6, 0x32, 0x9e, 0xfe, 0xb4, 0xe1, 0x65, 0xaf, + 0x5b, 0x36, 0x8a, 0x39, 0xa8, 0x8e, 0x48, 0x88, 0xe3, 0x9f, 0x40, 0xbb, + 0x3d, 0xe4, 0xeb, 0x14, 0x16, 0x67, 0x2f, 0x99, 0x9f, 0xea, 0xd3, 0x7a, + 0xef, 0x1c, 0xa9, 0x64, 0x3f, 0xf3, 0x2c, 0xdb, 0xc0, 0xfc, 0xeb, 0xe6, + 0x28, 0xd7, 0xe4, 0x6d, 0x28, 0x1a, 0x98, 0x9d, 0x43, 0xdd, 0x21, 0x43, + 0x21, 0x51, 0xaf, 0x68, 0xbe, 0x3f, 0x6d, 0x56, 0xac, 0xfb, 0xdb, 0x6c, + 0x97, 0xd8, 0x7f, 0xcb, 0x5e, 0x62, 0x91, 0xbf, 0x8b, 0x4e, 0xe1, 0x27, + 0x5a, 0xe0, 0xeb, 0x43, 0x83, 0xcc, 0x75, 0x39, 0x03, 0xc8, 0xd2, 0x9f, + 0x4a, 0xdb, 0x6a, 0x54, 0x7e, 0x40, 0x5d, 0xec, 0xdf, 0xf2, 0x88, 0xc5, + 0xf6, 0xc7, 0xaa, 0x30, 0xdc, 0xb1, 0x2f, 0x84, 0xd3, 0x92, 0x49, 0x3a, + 0x70, 0x93, 0x33, 0x17, 0xc0, 0xf5, 0xe6, 0x55, 0x26, 0x01, 0xfa, 0xe1, + 0x8f, 0x17, 0xe6, 0xe5, 0xbb, 0x6b, 0xf3, 0x96, 0xd3, 0x2d, 0x8a, 0xb9 +}; +static const uint8_t ac_dsa_vect256_sub_prime[] = { +/* Q */ + 0x87, 0x6f, 0xa0, 0x9e, 0x1d, 0xc6, 0x2b, 0x23, 0x6c, 0xe1, 0xc3, 0x15, + 0x5b, 0xa4, 0x8b, 0x0c, 0xcf, 0xda, 0x29, 0xf3, 0xac, 0x5a, 0x97, 0xf7, + 0xff, 0xa1, 0xbd, 0x87, 0xb6, 0x8d, 0x2a, 0x4b +}; +static const uint8_t ac_dsa_vect256_base[] = { +/* G */ + 0x11, 0x0a, 0xfe, 0xbb, 0x12, 0xc7, 0xf8, 0x62, 0xb6, 0xde, 0x03, 0xd4, + 0x7f, 0xdb, 0xc3, 0x32, 0x6e, 0x0d, 0x4d, 0x31, 0xb1, 0x2a, 0x8c, 0xa9, + 0x5b, 0x2d, 0xee, 0x21, 0x23, 0xbc, 0xc6, 0x67, 0xd4, 0xf7, 0x2c, 0x1e, + 0x72, 0x09, 0x76, 0x7d, 0x27, 0x21, 0xf9, 0x5f, 0xbd, 0x9a, 0x4d, 0x03, + 0x23, 0x6d, 0x54, 0x17, 0x4f, 0xbf, 0xaf, 0xf2, 0xc4, 0xff, 0x7d, 0xea, + 0xe4, 0x73, 0x8b, 0x20, 0xd9, 0xf3, 0x7b, 0xf0, 0xa1, 0x13, 0x4c, 0x28, + 0x8b, 0x42, 0x0a, 0xf0, 0xb5, 0x79, 0x2e, 0x47, 0xa9, 0x25, 0x13, 0xc0, + 0x41, 0x3f, 0x34, 0x6a, 0x4e, 0xdb, 0xab, 0x2c, 0x45, 0xbd, 0xca, 0x13, + 0xf5, 0x34, 0x1c, 0x2b, 0x55, 0xb8, 0xba, 0x54, 0x93, 0x2b, 0x92, 0x17, + 0xb5, 0xa8, 0x59, 0xe5, 0x53, 0xf1, 0x4b, 0xb8, 0xc1, 0x20, 0xfb, 0xb9, + 0xd9, 0x99, 0x09, 0xdf, 0xf5, 0xea, 0x68, 0xe1, 0x4b, 0x37, 0x99, 0x64, + 0xfd, 0x3f, 0x38, 0x61, 0xe5, 0xba, 0x5c, 0xc9, 0x70, 0xc4, 0xa1, 0x80, + 0xee, 0xf5, 0x44, 0x28, 0x70, 0x39, 0x61, 0x02, 0x1e, 0x7b, 0xd6, 0x8c, + 0xb6, 0x37, 0x92, 0x7b, 0x8c, 0xbe, 0xe6, 0x80, 0x5f, 0xa2, 0x72, 0x85, + 0xbf, 0xee, 0x4d, 0x1e, 0xf7, 0x0e, 0x02, 0xc1, 0xa1, 0x8a, 0x7c, 0xd7, + 0x8b, 0xef, 0x1d, 0xd9, 0xcd, 0xad, 0x45, 0xdd, 0xe9, 0xcd, 0x69, 0x07, + 0x55, 0x05, 0x0f, 0xc4, 0x66, 0x29, 0x37, 0xee, 0x1d, 0x6f, 0x4d, 0xb1, + 0x28, 0x07, 0xcc, 0xc9, 0x5b, 0xc4, 0x35, 0xf1, 0x1b, 0x71, 0xe7, 0x08, + 0x60, 0x48, 0xb1, 0xda, 0xb5, 0x91, 0x3c, 0x60, 0x55, 0x01, 0x2d, 0xe8, + 0x2e, 0x43, 0xa4, 0xe5, 0x0c, 0xf9, 0x3f, 0xef, 0xf5, 0xdc, 0xab, 0x81, + 0x4a, 0xbc, 0x22, 0x4c, 0x5e, 0x00, 0x25, 0xbd, 0x86, 0x8c, 0x3f, 0xc5, + 0x92, 0x04, 0x1b, 0xba, 0x04, 0x74, 0x7c, 0x10, 0xaf, 0x51, 0x3f, 0xc3, + 0x6e, 0x4d, 0x91, 0xc6, 0x3e, 0xe5, 0x25, 0x34, 0x22, 0xcf, 0x40, 0x63, + 0x39, 0x8d, 0x77, 0xc5, 0x2f, 0xcb, 0x01, 0x14, 0x27, 0xcb, 0xfc, 0xfa, + 0x67, 0xb1, 0xb2, 0xc2, 0xd1, 0xaa, 0x4a, 0x3d, 0xa7, 0x26, 0x45, 0xcb, + 0x1c, 0x76, 0x70, 0x36, 0x05, 0x4e, 0x2f, 0x31, 0xf8, 0x86, 0x65, 0xa5, + 0x44, 0x61, 0xc8, 0x85, 0xfb, 0x32, 0x19, 0xd5, 0xad, 0x87, 0x48, 0xa0, + 0x11, 0x58, 0xf6, 0xc7, 0xc0, 0xdf, 0x5a, 0x8c, 0x90, 0x8b, 0xa8, 0xc3, + 0xe5, 0x36, 0x82, 0x24, 0x28, 0x88, 0x6c, 0x7b, 0x50, 0x0b, 0xbc, 0x15, + 0xb4, 0x9d, 0xf7, 0x46, 0xb9, 0xde, 0x5a, 0x78, 0xfe, 0x3b, 0x4f, 0x69, + 0x91, 0xd0, 0x11, 0x0c, 0x3c, 0xbf, 0xf4, 0x58, 0x03, 0x9d, 0xc3, 0x62, + 0x61, 0xcf, 0x46, 0xaf, 0x4b, 0xc2, 0x51, 0x53, 0x68, 0xf4, 0xab, 0xb7 +}; +static const uint8_t ac_dsa_vect256_ptx[] = { +/* Msg */ + 0xcb, 0x06, 0xe0, 0x22, 0x34, 0x26, 0x3c, 0x22, 0xb8, 0x0e, 0x83, 0x2d, + 0x6d, 0xc5, 0xa1, 0xbe, 0xe5, 0xea, 0x8a, 0xf3, 0xbc, 0x2d, 0xa7, 0x52, + 0x44, 0x1c, 0x04, 0x02, 0x7f, 0x17, 0x61, 0x58, 0xbf, 0xe6, 0x83, 0x72, + 0xbd, 0x67, 0xf8, 0x4d, 0x48, 0x9c, 0x0d, 0x49, 0xb0, 0x7d, 0x40, 0x25, + 0x96, 0x29, 0x76, 0xbe, 0x60, 0x43, 0x7b, 0xe1, 0xa2, 0xd0, 0x1d, 0x3b, + 0xe0, 0x99, 0x2a, 0xfa, 0x5a, 0xbe, 0x09, 0x80, 0xe2, 0x6a, 0x9d, 0xa4, + 0xae, 0x72, 0xf8, 0x27, 0xb4, 0x23, 0x66, 0x51, 0x95, 0xcc, 0x4e, 0xed, + 0x6f, 0xe8, 0x5c, 0x33, 0x5b, 0x32, 0xd9, 0xc0, 0x3c, 0x94, 0x5a, 0x86, + 0xe7, 0xfa, 0x99, 0x37, 0x3f, 0x0a, 0x30, 0xc6, 0xec, 0xa9, 0x38, 0xb3, + 0xaf, 0xb6, 0xdf, 0xf6, 0x7a, 0xdb, 0x8b, 0xec, 0xe6, 0xf8, 0xcf, 0xec, + 0x4b, 0x6a, 0x12, 0xea, 0x28, 0x1e, 0x23, 0x23 +}; +static const uint8_t ac_dsa_vect256_priv_val[] = { +/* X */ + 0x34, 0x70, 0x83, 0x20, 0x55, 0xda, 0xde, 0x94, 0xe1, 0x4c, 0xd8, 0x77, + 0x71, 0x71, 0xd1, 0x8e, 0x5d, 0x06, 0xf6, 0x6a, 0xef, 0xf4, 0xc6, 0x14, + 0x71, 0xe4, 0xeb, 0xa7, 0x4e, 0xe5, 0x61, 0x64 +}; +static const uint8_t ac_dsa_vect256_pub_val[] = { +/* Y */ + 0x45, 0x6a, 0x10, 0x5c, 0x71, 0x35, 0x66, 0x23, 0x48, 0x38, 0xbc, 0x07, + 0x0b, 0x8a, 0x75, 0x1a, 0x0b, 0x57, 0x76, 0x7c, 0xb7, 0x5e, 0x99, 0x11, + 0x4a, 0x1a, 0x46, 0x64, 0x1e, 0x11, 0xda, 0x1f, 0xa9, 0xf2, 0x29, 0x14, + 0xd8, 0x08, 0xad, 0x71, 0x48, 0x61, 0x2c, 0x1e, 0xa5, 0x5d, 0x25, 0x30, + 0x17, 0x81, 0xe9, 0xae, 0x0c, 0x9a, 0xe3, 0x6a, 0x69, 0xd8, 0x7b, 0xa0, + 0x39, 0xec, 0x7c, 0xd8, 0x64, 0xc3, 0xad, 0x09, 0x48, 0x73, 0xe6, 0xe5, + 0x67, 0x09, 0xfd, 0x10, 0xd9, 0x66, 0x85, 0x3d, 0x61, 0x1b, 0x1c, 0xff, + 0x15, 0xd3, 0x7f, 0xde, 0xe4, 0x24, 0x50, 0x6c, 0x18, 0x4d, 0x62, 0xc7, + 0x03, 0x33, 0x58, 0xbe, 0x78, 0xc2, 0x25, 0x09, 0x43, 0xb6, 0xf6, 0xd0, + 0x43, 0xd6, 0x3b, 0x31, 0x7d, 0xe5, 0x6e, 0x5a, 0xd8, 0xd1, 0xfd, 0x97, + 0xdd, 0x35, 0x5a, 0xbe, 0x96, 0x45, 0x2f, 0x8e, 0x43, 0x54, 0x85, 0xfb, + 0x3b, 0x90, 0x7b, 0x51, 0x90, 0x0a, 0xa3, 0xf2, 0x44, 0x18, 0xdf, 0x50, + 0xb4, 0xfc, 0xda, 0xfb, 0xf6, 0x13, 0x75, 0x48, 0xc3, 0x93, 0x73, 0xb8, + 0xbc, 0x4b, 0xa3, 0xda, 0xbb, 0x47, 0x46, 0xeb, 0xd1, 0x7b, 0x87, 0xfc, + 0xd6, 0xa2, 0xf1, 0x97, 0xc1, 0x07, 0xb1, 0x8e, 0xc5, 0xb4, 0x65, 0xe6, + 0xe4, 0xcb, 0x43, 0x0d, 0x9c, 0x0c, 0xe7, 0x8d, 0xa5, 0x98, 0x84, 0x41, + 0x05, 0x4a, 0x37, 0x07, 0x92, 0xb7, 0x30, 0xda, 0x9a, 0xba, 0x41, 0xa3, + 0x16, 0x9a, 0xf2, 0x61, 0x76, 0xf7, 0x4e, 0x6f, 0x7c, 0x0c, 0x9c, 0x9b, + 0x55, 0xb6, 0x2b, 0xbe, 0x7c, 0xe3, 0x8d, 0x46, 0x95, 0xd4, 0x81, 0x57, + 0xe6, 0x60, 0xc2, 0xac, 0xb6, 0x3f, 0x48, 0x2f, 0x55, 0x41, 0x81, 0x50, + 0xe5, 0xfe, 0xe4, 0x3a, 0xce, 0x84, 0xc5, 0x40, 0xc3, 0xba, 0x76, 0x62, + 0xae, 0x80, 0x83, 0x5c, 0x1a, 0x2d, 0x51, 0x89, 0x0e, 0xa9, 0x6b, 0xa2, + 0x06, 0x42, 0x7c, 0x41, 0xef, 0x8c, 0x38, 0xaa, 0x07, 0xd2, 0xa3, 0x65, + 0xe7, 0xe5, 0x83, 0x80, 0xd8, 0xf4, 0x78, 0x2e, 0x22, 0xac, 0x21, 0x01, + 0xaf, 0x73, 0x2e, 0xe2, 0x27, 0x58, 0x33, 0x7b, 0x25, 0x36, 0x37, 0x83, + 0x8e, 0x16, 0xf5, 0x0f, 0x56, 0xd3, 0x13, 0xd0, 0x79, 0x81, 0x88, 0x0d, + 0x68, 0x55, 0x57, 0xf7, 0xd7, 0x9a, 0x6d, 0xb8, 0x23, 0xc6, 0x1f, 0x1b, + 0xb3, 0xdb, 0xc5, 0xd5, 0x04, 0x21, 0xa4, 0x84, 0x3a, 0x6f, 0x29, 0x69, + 0x0e, 0x78, 0xaa, 0x0f, 0x0c, 0xff, 0x30, 0x42, 0x31, 0x81, 0x8b, 0x81, + 0xfc, 0x4a, 0x24, 0x3f, 0xc0, 0x0f, 0x09, 0xa5, 0x4c, 0x46, 0x6d, 0x6a, + 0x8c, 0x73, 0xd3, 0x2a, 0x55, 0xe1, 0xab, 0xd5, 0xec, 0x8b, 0x4e, 0x1a, + 0xfa, 0x32, 0xa7, 0x9b, 0x01, 0xdf, 0x85, 0xa8, 0x1f, 0x3f, 0x5c, 0xfe +}; +/* K = 3d7c068a3978b2d8fe9034bcad65ad7c300c4440e4085de280e577eea72c1207 */ +static const uint8_t ac_dsa_vect256_out[] = { +/* R */ + 0x53, 0xba, 0xe6, 0xc6, 0xf3, 0x36, 0xe2, 0xeb, 0x31, 0x1c, 0x1e, 0x92, + 0xd9, 0x5f, 0xc4, 0x49, 0xa9, 0x29, 0x44, 0x4e, 0xf8, 0x1e, 0xc4, 0x27, + 0x96, 0x60, 0xb2, 0x00, 0xd5, 0x94, 0x33, 0xde, +/* S */ + 0x49, 0xf3, 0xa7, 0x4e, 0x95, 0x3e, 0x77, 0xa7, 0x94, 0x1a, 0xf3, 0xae, + 0xfe, 0xef, 0x4e, 0xd4, 0x99, 0xbe, 0x20, 0x99, 0x76, 0xa0, 0xed, 0xb3, + 0xfa, 0x5e, 0x7c, 0xb9, 0x61, 0xb0, 0xc1, 0x12 +}; +#define ac_dsa_vect257_prime ac_dsa_vect256_prime +#define ac_dsa_vect257_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect257_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect257_ptx[] = { +/* Msg */ + 0x06, 0x61, 0xc1, 0xbf, 0x79, 0xee, 0xd7, 0x8a, 0xd4, 0x87, 0x9e, 0x24, + 0x0a, 0x46, 0xb9, 0x5a, 0x0d, 0xb2, 0xb2, 0x9b, 0xf8, 0x12, 0x63, 0xb9, + 0xb1, 0x67, 0x6d, 0xaa, 0x25, 0x54, 0xaa, 0xd7, 0x22, 0x2c, 0x9e, 0xb7, + 0xa8, 0x93, 0x04, 0x8e, 0x46, 0xfb, 0xd2, 0x82, 0x6a, 0xb6, 0xe8, 0xcf, + 0x42, 0xab, 0x0c, 0xd6, 0x31, 0xc4, 0xc4, 0xa1, 0xa8, 0x19, 0x56, 0x0f, + 0x73, 0xcc, 0x86, 0x1a, 0x5b, 0x64, 0x65, 0xcf, 0x28, 0x80, 0xa7, 0x30, + 0x63, 0x5e, 0xd7, 0xf4, 0x9e, 0x28, 0xf7, 0xb5, 0x65, 0x76, 0x8f, 0x02, + 0x9d, 0xb2, 0xa4, 0x43, 0xba, 0x0a, 0x1b, 0xd1, 0x07, 0x73, 0xf2, 0x6f, + 0x75, 0x2c, 0x83, 0xda, 0x40, 0xfc, 0xd3, 0x3f, 0x32, 0xf7, 0x8d, 0x24, + 0xac, 0x98, 0x20, 0xd0, 0xbf, 0x70, 0xda, 0xe5, 0x68, 0xa1, 0x25, 0x38, + 0xaf, 0xfa, 0x86, 0x71, 0x60, 0xc8, 0x1e, 0x39 +}; +static const uint8_t ac_dsa_vect257_priv_val[] = { +/* X */ + 0x80, 0x76, 0x75, 0xfb, 0xaa, 0xf0, 0xb6, 0xd6, 0xba, 0x3d, 0x82, 0x06, + 0x3c, 0xc0, 0x73, 0x27, 0xcc, 0xa3, 0xf3, 0x52, 0x2d, 0x39, 0x6f, 0xe5, + 0xd2, 0xc6, 0x59, 0x90, 0x45, 0xd6, 0x68, 0xc5 +}; +static const uint8_t ac_dsa_vect257_pub_val[] = { +/* Y */ + 0x54, 0xb6, 0x81, 0x80, 0x54, 0xcc, 0x00, 0x0c, 0x3a, 0xf6, 0x1b, 0x62, + 0xef, 0x41, 0x89, 0xba, 0x35, 0xe0, 0x48, 0x45, 0xde, 0xe0, 0x01, 0x5b, + 0xe6, 0x27, 0x33, 0x92, 0xc6, 0x73, 0x32, 0xe2, 0xe0, 0x45, 0x10, 0xcd, + 0x5b, 0x2b, 0xbf, 0x47, 0x23, 0xcd, 0x81, 0x96, 0xe0, 0x25, 0x51, 0x1f, + 0x66, 0x23, 0xf0, 0x36, 0x07, 0xe5, 0x66, 0x48, 0x4c, 0x33, 0x07, 0x51, + 0xd0, 0x3c, 0x71, 0x30, 0x68, 0xa7, 0x7e, 0x08, 0xbd, 0xe9, 0x07, 0xfc, + 0x57, 0xb3, 0xc0, 0x21, 0xe3, 0x73, 0x03, 0x37, 0x3d, 0x9d, 0x81, 0x1e, + 0x38, 0xf1, 0x4b, 0x54, 0x7d, 0x2b, 0xd8, 0x7d, 0x98, 0x12, 0x69, 0xc6, + 0x77, 0xda, 0xc6, 0xad, 0xe6, 0xac, 0xbb, 0xae, 0x30, 0x14, 0xeb, 0xd3, + 0x81, 0xb4, 0x00, 0x86, 0x37, 0x03, 0x1c, 0x9b, 0x6d, 0x49, 0xca, 0x90, + 0x87, 0x65, 0x47, 0x2b, 0x05, 0x96, 0x2f, 0x55, 0xaa, 0x36, 0x1f, 0x7d, + 0xd5, 0xa4, 0x26, 0x07, 0x05, 0xff, 0x5e, 0xcf, 0x7b, 0x31, 0x7d, 0xb1, + 0xfe, 0x5d, 0x33, 0xfd, 0xbf, 0x48, 0xe6, 0xa3, 0x3b, 0x3c, 0x78, 0xb1, + 0x4e, 0x62, 0x0d, 0x93, 0x80, 0x6b, 0x52, 0xe8, 0x6e, 0x08, 0x2f, 0xe4, + 0xf5, 0x4d, 0x52, 0x65, 0xe8, 0xdf, 0x62, 0x3b, 0x0c, 0x9a, 0x25, 0x9f, + 0x61, 0xb7, 0xfa, 0x2c, 0x04, 0x55, 0xfa, 0xdf, 0x39, 0x69, 0x3e, 0xf3, + 0x97, 0x74, 0x40, 0xf3, 0x02, 0x06, 0x7c, 0x3a, 0xff, 0xbc, 0x45, 0x74, + 0x22, 0x4d, 0x5a, 0x22, 0x04, 0x4e, 0x9b, 0xfe, 0x11, 0xd0, 0xd6, 0xed, + 0xe2, 0x73, 0x9c, 0x7f, 0xfe, 0x92, 0x77, 0xc8, 0x64, 0x4d, 0x46, 0xbe, + 0xec, 0xb9, 0x46, 0xf8, 0x17, 0x75, 0xc1, 0x16, 0x38, 0x8f, 0xd6, 0xc2, + 0x4a, 0xf0, 0x2e, 0xc5, 0x9f, 0x62, 0x12, 0x33, 0xef, 0xe8, 0x79, 0x2d, + 0x6d, 0x0c, 0xd2, 0xc8, 0x43, 0x33, 0xb1, 0x1f, 0x07, 0x65, 0x73, 0x33, + 0xda, 0x4e, 0x27, 0x4b, 0x8c, 0xd3, 0x91, 0x4d, 0x97, 0x77, 0x06, 0xe7, + 0x86, 0xf3, 0x25, 0xe1, 0x8a, 0x33, 0x9b, 0x80, 0x5c, 0x51, 0xb4, 0x5e, + 0xac, 0xb3, 0xce, 0x24, 0x18, 0x45, 0x97, 0x0a, 0xcb, 0x9f, 0xd1, 0xa4, + 0x82, 0xa5, 0x64, 0xb2, 0xae, 0xec, 0xda, 0xeb, 0x0a, 0x0d, 0xb3, 0x9f, + 0x33, 0xad, 0x29, 0x91, 0xf2, 0x5c, 0xf6, 0x22, 0xbf, 0x22, 0xf0, 0xc4, + 0x43, 0x0c, 0xf9, 0x4d, 0xf1, 0xdb, 0x59, 0xaa, 0x2d, 0x7c, 0x20, 0x04, + 0xb5, 0x17, 0x7b, 0x9e, 0xa6, 0x9f, 0xf5, 0x56, 0xdd, 0x4c, 0x07, 0xed, + 0xec, 0x62, 0x59, 0xee, 0x13, 0x9b, 0x42, 0x15, 0x73, 0xa1, 0x1c, 0xf8, + 0x5d, 0x11, 0xe2, 0x45, 0xe2, 0x51, 0x19, 0x0b, 0xa8, 0x69, 0xc9, 0xcb, + 0x4d, 0xaf, 0x9f, 0x49, 0x45, 0x1a, 0x85, 0xf3, 0x8b, 0x9b, 0x90, 0x3e +}; +/* K = 6215e72ef2d6f6e040b7b6ef4cf566a21fcc4f37783a68db445c1ddf3042a150 */ +static const uint8_t ac_dsa_vect257_out[] = { +/* R */ + 0x51, 0x9f, 0xe4, 0xc5, 0xf9, 0xb7, 0x70, 0x7a, 0xe4, 0xb3, 0x62, 0x17, + 0xea, 0x17, 0x07, 0xa1, 0x87, 0x1d, 0x8f, 0xce, 0x98, 0xee, 0xe9, 0xe6, + 0x43, 0xc4, 0x5c, 0xd3, 0xeb, 0x50, 0xc5, 0xd3, +/* S */ + 0x1d, 0xf2, 0x24, 0xaf, 0x0b, 0x51, 0x51, 0x9e, 0x11, 0xd8, 0x42, 0x29, + 0x99, 0xb1, 0xd3, 0xab, 0x09, 0x72, 0x06, 0x41, 0x80, 0xff, 0xc3, 0xf1, + 0x11, 0x4c, 0x9f, 0x87, 0x6a, 0x1d, 0xe3, 0xb1 +}; +#define ac_dsa_vect258_prime ac_dsa_vect256_prime +#define ac_dsa_vect258_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect258_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect258_ptx[] = { +/* Msg */ + 0x15, 0x97, 0x35, 0x3f, 0x24, 0xaa, 0xf5, 0x15, 0xfd, 0x7c, 0x0b, 0x0a, + 0x74, 0x53, 0x44, 0x4d, 0x5f, 0x32, 0x9d, 0x6c, 0x3f, 0x09, 0x91, 0x13, + 0xbb, 0x3a, 0x13, 0x30, 0x9b, 0x05, 0x3e, 0x6c, 0x12, 0x3a, 0x56, 0x22, + 0x7a, 0x81, 0xe8, 0xb1, 0xa0, 0xc8, 0xab, 0x4b, 0x46, 0x16, 0x0c, 0xc5, + 0x38, 0x0d, 0xf5, 0x91, 0xb1, 0x9d, 0x8a, 0x38, 0x6d, 0x29, 0xa8, 0xe4, + 0x3c, 0xca, 0xb5, 0xd8, 0xc0, 0xe5, 0x47, 0xfb, 0xa2, 0x1b, 0xff, 0xcf, + 0x5e, 0xf4, 0x2e, 0xfb, 0x9f, 0xb2, 0xe9, 0xbe, 0x62, 0x97, 0xc0, 0x3d, + 0x57, 0xda, 0x0b, 0x58, 0x89, 0xb3, 0xb9, 0x74, 0x2d, 0xdc, 0x2c, 0x54, + 0xb8, 0x37, 0x3f, 0xed, 0x1f, 0x21, 0x95, 0xf5, 0xbb, 0x23, 0x29, 0xa8, + 0xf1, 0xf3, 0xf8, 0xaf, 0xce, 0xc2, 0x5e, 0xb1, 0x52, 0xe7, 0xfa, 0x81, + 0x9e, 0x5d, 0x36, 0xcf, 0xd3, 0x62, 0x52, 0x39 +}; +static const uint8_t ac_dsa_vect258_priv_val[] = { +/* X */ + 0x16, 0x9b, 0x11, 0xd0, 0x3c, 0xba, 0x7e, 0x81, 0x7d, 0xa2, 0x7d, 0x88, + 0x9c, 0xdb, 0x14, 0x7a, 0xe9, 0xcb, 0x04, 0x59, 0x35, 0x9b, 0xbf, 0x85, + 0xa3, 0x67, 0xc6, 0x4c, 0x2a, 0xb5, 0x56, 0xad +}; +static const uint8_t ac_dsa_vect258_pub_val[] = { +/* Y */ + 0x50, 0x62, 0xaa, 0x1f, 0xdc, 0x67, 0x29, 0x4c, 0xd5, 0x76, 0x23, 0xce, + 0xdd, 0x28, 0x08, 0x30, 0x3c, 0xeb, 0x43, 0x53, 0x7e, 0x3a, 0xbf, 0xa1, + 0xbd, 0xbc, 0x49, 0x2b, 0x1a, 0xee, 0xce, 0xe6, 0x1b, 0x1f, 0xd9, 0x6c, + 0xc0, 0x55, 0xd1, 0x45, 0x9a, 0xb5, 0x2d, 0xdc, 0x3f, 0x23, 0x44, 0x38, + 0x9e, 0x5f, 0x21, 0x44, 0x8a, 0x90, 0xcb, 0x36, 0xe4, 0x48, 0xe6, 0x07, + 0x87, 0xb1, 0xff, 0x5a, 0xb6, 0xe5, 0x54, 0x9a, 0x39, 0x21, 0x49, 0x6e, + 0x83, 0x54, 0x64, 0x6b, 0xc1, 0xfd, 0x6c, 0xd5, 0xf2, 0x35, 0x9a, 0xe2, + 0x99, 0xc0, 0xa0, 0x47, 0xfa, 0xc3, 0x92, 0x05, 0x12, 0xa1, 0xf4, 0x11, + 0xc4, 0x38, 0xba, 0xfd, 0x03, 0xe9, 0x5e, 0x53, 0x8c, 0x6e, 0x21, 0xd1, + 0xdd, 0x1f, 0x15, 0xa8, 0x9d, 0x38, 0xd4, 0x8f, 0x26, 0x30, 0x5c, 0x25, + 0x34, 0xfa, 0x8e, 0x31, 0xd0, 0x54, 0xdc, 0xb0, 0x07, 0x74, 0x13, 0x8f, + 0xb8, 0xfc, 0x61, 0xc6, 0xa8, 0xd4, 0xae, 0x1c, 0xa4, 0x64, 0x30, 0xd0, + 0xe3, 0x1b, 0x4b, 0x92, 0xdf, 0xb1, 0x5b, 0xd6, 0xb8, 0x73, 0x9f, 0xd5, + 0x37, 0x10, 0x1e, 0x77, 0x33, 0x4e, 0x6f, 0x3c, 0xe5, 0x46, 0x9e, 0x82, + 0xa8, 0xdb, 0xc5, 0x8b, 0x3b, 0xe5, 0xca, 0x37, 0x03, 0x59, 0xf4, 0xa6, + 0x13, 0x2f, 0xe0, 0x33, 0x60, 0xb8, 0xf6, 0xbe, 0x24, 0x8c, 0x34, 0x22, + 0x0a, 0x80, 0x03, 0x77, 0x26, 0x48, 0x66, 0x40, 0x59, 0xf1, 0xf6, 0xa3, + 0x22, 0xe0, 0xc1, 0x22, 0xf4, 0x27, 0xef, 0xdb, 0x7d, 0x64, 0x0e, 0xb5, + 0xbb, 0x7f, 0x3d, 0xb2, 0xd9, 0x67, 0xa2, 0x15, 0x90, 0x92, 0xd8, 0xf8, + 0xdf, 0x33, 0x3f, 0xf5, 0xba, 0x13, 0x56, 0x02, 0xb9, 0xee, 0x7e, 0x9d, + 0xb6, 0xae, 0x0b, 0x95, 0x88, 0x6d, 0xf3, 0x8d, 0x4b, 0x4a, 0x26, 0xa4, + 0xb2, 0xd7, 0x90, 0xc2, 0x4f, 0xa2, 0x14, 0xcd, 0x68, 0xd0, 0xa7, 0xed, + 0xe6, 0x3e, 0x7d, 0xfa, 0xca, 0xea, 0xe1, 0x4d, 0x97, 0x85, 0xbe, 0x69, + 0x3a, 0xd7, 0x8d, 0x88, 0x24, 0x2d, 0xfa, 0xd9, 0x88, 0xb7, 0x12, 0x2a, + 0xdf, 0x5a, 0xfa, 0x9e, 0xfd, 0xd0, 0xc2, 0x04, 0x74, 0x70, 0xc6, 0x07, + 0xd4, 0x7b, 0x30, 0x08, 0x9f, 0xf8, 0xbf, 0xc4, 0xcf, 0x5d, 0x7a, 0x8b, + 0xa6, 0x9a, 0x7d, 0x0a, 0xb6, 0xc5, 0x4c, 0x05, 0x28, 0x0d, 0x66, 0xaa, + 0x40, 0x19, 0xf6, 0x36, 0x2e, 0xa2, 0x4a, 0x1d, 0x3f, 0x8f, 0xcd, 0x80, + 0xc3, 0xeb, 0x20, 0x83, 0x1b, 0x6e, 0x0d, 0xb0, 0x10, 0xfa, 0xf8, 0x26, + 0x48, 0x8f, 0x01, 0x5f, 0x63, 0xf0, 0xb9, 0xac, 0x6d, 0xf7, 0x28, 0x83, + 0xef, 0xd2, 0x86, 0xf0, 0x53, 0x2b, 0x5b, 0xef, 0xf1, 0xb9, 0xe8, 0x10, + 0xff, 0x6a, 0x2b, 0x2d, 0x32, 0x8a, 0xf6, 0x75, 0xea, 0xfc, 0x2f, 0x56 +}; +/* K = 467e04dcd564f36cfe47c8fb9fa09cb142a99417a61797e047fcfd51e16e3e00 */ +static const uint8_t ac_dsa_vect258_out[] = { +/* R */ + 0x05, 0x02, 0xa6, 0xe1, 0xd8, 0xc8, 0xdf, 0xdf, 0x56, 0xeb, 0x67, 0xf9, + 0xa6, 0xf6, 0x60, 0x57, 0x35, 0xe4, 0xd1, 0xb0, 0x07, 0x6c, 0x8b, 0x08, + 0xb6, 0x1d, 0xaf, 0x8e, 0x7c, 0x2b, 0xf2, 0xd6, +/* S */ + 0x7c, 0x67, 0xab, 0xdc, 0xf4, 0xe5, 0x80, 0x81, 0x2b, 0x13, 0xd0, 0xa4, + 0xed, 0xba, 0xe8, 0xa2, 0x78, 0x6d, 0x66, 0x12, 0xbc, 0x86, 0x6e, 0x3c, + 0x13, 0xbc, 0x09, 0xf3, 0xe9, 0x66, 0x16, 0xe0 +}; +#define ac_dsa_vect259_prime ac_dsa_vect256_prime +#define ac_dsa_vect259_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect259_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect259_ptx[] = { +/* Msg */ + 0x71, 0x5f, 0x29, 0x69, 0x30, 0x31, 0x23, 0x68, 0xa2, 0xa9, 0x8d, 0x3f, + 0x42, 0x81, 0x0d, 0xa5, 0x71, 0x15, 0xf0, 0x0f, 0xfc, 0x4a, 0x12, 0x02, + 0x9c, 0x27, 0x6b, 0x10, 0x62, 0x9e, 0x6b, 0xdd, 0xd6, 0x0b, 0xca, 0x2c, + 0x53, 0x5b, 0x79, 0xa5, 0xf4, 0xa0, 0x06, 0x81, 0x77, 0x91, 0xf7, 0xf3, + 0xad, 0x2e, 0x01, 0xa0, 0x02, 0x16, 0x67, 0x2e, 0xe5, 0xad, 0xec, 0x57, + 0x9d, 0xeb, 0x07, 0xe9, 0xd2, 0xb0, 0xdb, 0x22, 0x2c, 0x4e, 0x01, 0xe1, + 0xf8, 0x19, 0xc1, 0xa5, 0x2d, 0x10, 0x1b, 0x1e, 0xf6, 0x78, 0xcf, 0xca, + 0x85, 0x65, 0x5d, 0xd6, 0xb2, 0x42, 0x6f, 0x1a, 0xc3, 0x79, 0xa9, 0x2a, + 0x9c, 0x69, 0xb0, 0xf8, 0x98, 0x74, 0x32, 0xd1, 0x09, 0xcd, 0x9a, 0x7b, + 0xc0, 0x4e, 0xf2, 0x87, 0xc2, 0xaf, 0xb6, 0x63, 0x44, 0x46, 0x88, 0x60, + 0x1c, 0xe3, 0xc5, 0x5f, 0xd9, 0x0d, 0x0f, 0xa3 +}; +static const uint8_t ac_dsa_vect259_priv_val[] = { +/* X */ + 0x4e, 0xe8, 0x0e, 0x4c, 0xf4, 0x6b, 0x4e, 0x07, 0x2e, 0x97, 0x68, 0x93, + 0xa2, 0xd1, 0xe3, 0x4c, 0x03, 0xd2, 0x0f, 0x3a, 0xa1, 0x78, 0x5a, 0x74, + 0x56, 0x4d, 0x6b, 0x46, 0x54, 0xb1, 0x1a, 0x54 +}; +static const uint8_t ac_dsa_vect259_pub_val[] = { +/* Y */ + 0xb6, 0x33, 0x40, 0xd6, 0xa1, 0x95, 0x57, 0x31, 0x28, 0x30, 0x64, 0xf6, + 0xf2, 0x2a, 0xd7, 0xf0, 0xe2, 0x81, 0x99, 0xf6, 0xa5, 0x8c, 0x57, 0xdd, + 0xcb, 0x44, 0xa0, 0x26, 0xc6, 0x1e, 0x44, 0x13, 0x18, 0xc4, 0xf8, 0x75, + 0x5d, 0xfd, 0x71, 0xb2, 0x95, 0xe9, 0xe7, 0xba, 0xbe, 0x00, 0x08, 0x49, + 0xc9, 0x72, 0xf6, 0x8d, 0x4b, 0xe0, 0x09, 0x54, 0xa3, 0xc2, 0x9c, 0xd4, + 0xb4, 0xe8, 0x3a, 0xd5, 0x18, 0x30, 0x08, 0x0e, 0x29, 0xe7, 0x61, 0x9e, + 0x45, 0xd3, 0xab, 0xbf, 0x9d, 0x82, 0xfd, 0x87, 0xe9, 0x75, 0x81, 0xfe, + 0x90, 0x9d, 0x3d, 0xa1, 0xe3, 0xe9, 0x6c, 0xb3, 0xf0, 0xc8, 0x93, 0xaf, + 0x9d, 0x07, 0xf4, 0x18, 0xdf, 0x90, 0x2e, 0x76, 0xb0, 0xbb, 0xc1, 0xc9, + 0x71, 0x39, 0xcb, 0xd5, 0x12, 0x26, 0xac, 0x44, 0x2b, 0x3d, 0x0b, 0x05, + 0x25, 0xc7, 0x84, 0xba, 0x13, 0x81, 0x31, 0x42, 0x1c, 0x60, 0x54, 0x3e, + 0x6e, 0x29, 0x60, 0x69, 0xf6, 0x11, 0xb9, 0xc3, 0x7c, 0xf6, 0x03, 0x06, + 0x36, 0xee, 0xca, 0xf4, 0x1c, 0x3b, 0x48, 0x38, 0xf5, 0x06, 0xc0, 0x2c, + 0xc8, 0x4c, 0xde, 0x6b, 0x99, 0xca, 0xbd, 0x2c, 0xa5, 0x78, 0x44, 0x9c, + 0xc1, 0x71, 0x8a, 0xa4, 0x18, 0xca, 0x12, 0xa2, 0xb7, 0x6f, 0x78, 0x25, + 0x9c, 0x16, 0x91, 0xe0, 0xb4, 0x9f, 0x09, 0xdb, 0xda, 0xf5, 0x85, 0xf6, + 0x26, 0xcf, 0x74, 0xd7, 0x32, 0x12, 0xb3, 0x42, 0x78, 0x45, 0xc6, 0x6f, + 0x22, 0x83, 0xb6, 0x07, 0x03, 0xad, 0xf1, 0xa2, 0x62, 0xbb, 0x8b, 0x10, + 0xac, 0x7a, 0xc5, 0xd1, 0xec, 0x73, 0x61, 0x4f, 0xdd, 0x37, 0xee, 0x51, + 0xb7, 0x1c, 0xd1, 0xfb, 0x4e, 0x6d, 0xb8, 0x93, 0x83, 0x82, 0x64, 0x3c, + 0x72, 0x1f, 0xbc, 0x4c, 0xfc, 0x98, 0x7b, 0xc5, 0xef, 0xbc, 0x81, 0x29, + 0x9b, 0x37, 0x5a, 0x56, 0x0c, 0xde, 0x5a, 0xda, 0xe6, 0x28, 0x31, 0xca, + 0x41, 0x38, 0xc3, 0x99, 0xd8, 0x2f, 0x1f, 0x8b, 0xc6, 0x80, 0xf9, 0xc6, + 0xb4, 0x7e, 0xb4, 0x64, 0xa1, 0xe0, 0xaa, 0xc4, 0x48, 0xfe, 0x3b, 0x5c, + 0x25, 0xbd, 0x8c, 0x0b, 0x7a, 0xfb, 0x70, 0x1b, 0x06, 0x80, 0xdb, 0x87, + 0xab, 0x51, 0x73, 0x8f, 0x19, 0xf5, 0xb9, 0x65, 0x37, 0x5d, 0xd4, 0x8d, + 0xac, 0xa0, 0x7b, 0xff, 0x38, 0x85, 0x63, 0x21, 0x75, 0x70, 0x0c, 0x67, + 0x86, 0x19, 0xf1, 0x94, 0xe4, 0xee, 0x5f, 0x55, 0xaa, 0x44, 0x8a, 0xec, + 0xa7, 0xf7, 0xb3, 0x32, 0x2f, 0x64, 0xa5, 0x47, 0x31, 0x5c, 0x5c, 0xee, + 0x04, 0x51, 0x22, 0x54, 0x9f, 0xb3, 0x8b, 0x8a, 0xcc, 0x95, 0xda, 0x5e, + 0x83, 0x30, 0x22, 0xb3, 0xb8, 0x94, 0xf0, 0x3c, 0xcb, 0x7f, 0x73, 0xb9, + 0x1c, 0x1f, 0xe8, 0x2c, 0xe4, 0x14, 0xe1, 0x21, 0x94, 0x11, 0x78, 0x0e +}; +/* K = 3d7728ce25def9a31dfbe442fef8b162b30544065d9cb7bcc4914662a282bc10 */ +static const uint8_t ac_dsa_vect259_out[] = { +/* R */ + 0x4c, 0x5e, 0x99, 0x0a, 0x6e, 0x24, 0xfe, 0xdd, 0xab, 0x48, 0xd0, 0xaf, + 0x4a, 0x08, 0xb4, 0x5a, 0xe8, 0x09, 0x25, 0x94, 0xbf, 0xb3, 0xc0, 0x12, + 0xfa, 0x1c, 0x32, 0x5c, 0x97, 0x7a, 0x3c, 0xc0, +/* S */ + 0x82, 0x0b, 0x6c, 0xaf, 0xa8, 0x9b, 0x41, 0xc4, 0xcc, 0xbe, 0xc8, 0x42, + 0xd7, 0xc4, 0x08, 0xc6, 0x5d, 0x49, 0x98, 0xab, 0x1a, 0xc6, 0xb6, 0xbc, + 0xe8, 0xd4, 0xd5, 0x69, 0xcd, 0xf0, 0x47, 0x26 +}; +#define ac_dsa_vect260_prime ac_dsa_vect256_prime +#define ac_dsa_vect260_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect260_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect260_ptx[] = { +/* Msg */ + 0x1f, 0xe5, 0xad, 0x49, 0xe1, 0x1c, 0x20, 0x7d, 0x3d, 0x5e, 0x19, 0x23, + 0x06, 0x08, 0x32, 0xaf, 0xbf, 0xc0, 0xaa, 0x0c, 0xb2, 0x9f, 0xc0, 0xb2, + 0x2b, 0x3b, 0xe5, 0x9a, 0x59, 0x8f, 0x8c, 0x70, 0x3b, 0x9b, 0xf2, 0xc7, + 0x34, 0x7f, 0x8a, 0xbd, 0xe2, 0x56, 0x77, 0xea, 0x9c, 0xc6, 0x0a, 0xf9, + 0x30, 0x7d, 0x21, 0xd3, 0x01, 0xfd, 0xd2, 0x3c, 0x28, 0x27, 0x7f, 0xce, + 0x11, 0x40, 0x03, 0x10, 0x03, 0x39, 0x62, 0xc0, 0x4e, 0xcd, 0x37, 0x7f, + 0xd4, 0x46, 0x35, 0x8a, 0x34, 0x49, 0xef, 0xd6, 0xbc, 0x05, 0x72, 0x1b, + 0x78, 0x4d, 0xdf, 0x0e, 0x23, 0x8f, 0x28, 0x60, 0x8e, 0x86, 0xbd, 0x4c, + 0x3d, 0x7a, 0xc6, 0x31, 0xff, 0xf8, 0xbe, 0x06, 0x78, 0xd3, 0x7b, 0xfb, + 0xac, 0x16, 0xb7, 0x5b, 0xc1, 0x5a, 0x50, 0xce, 0x13, 0x97, 0xdd, 0x4b, + 0xa3, 0xbf, 0xfc, 0xf9, 0x4d, 0x34, 0x12, 0x74 +}; +static const uint8_t ac_dsa_vect260_priv_val[] = { +/* X */ + 0x0d, 0x69, 0x0f, 0x2c, 0x87, 0xfe, 0x2c, 0xeb, 0xc9, 0xf1, 0x55, 0x46, + 0xf0, 0x5a, 0xfa, 0xf6, 0xdc, 0x84, 0x3b, 0x80, 0xab, 0xd2, 0x04, 0x6f, + 0x33, 0xde, 0x30, 0xc2, 0xe8, 0x06, 0x35, 0x8f +}; +static const uint8_t ac_dsa_vect260_pub_val[] = { +/* Y */ + 0x53, 0xfc, 0xd0, 0x73, 0x99, 0xe4, 0xd3, 0x1b, 0x09, 0xab, 0xef, 0xf2, + 0xf0, 0x96, 0xa7, 0xb2, 0xcc, 0x5c, 0xf4, 0x17, 0xde, 0xe1, 0x20, 0x7d, + 0x8a, 0x5a, 0xab, 0xf9, 0xe8, 0xf9, 0xfb, 0x0f, 0x66, 0xbe, 0x48, 0x82, + 0x6a, 0x3d, 0xc1, 0x1e, 0x39, 0xbe, 0xba, 0x2f, 0xf4, 0x7b, 0x76, 0x54, + 0x4b, 0xcf, 0x55, 0x48, 0x5a, 0xcf, 0x1e, 0x3d, 0x49, 0xe1, 0x90, 0x57, + 0x01, 0x5e, 0x49, 0xed, 0x01, 0x2a, 0x48, 0x77, 0xbe, 0x74, 0x16, 0x07, + 0x74, 0x9b, 0x6f, 0x4b, 0xf9, 0x5c, 0x44, 0xec, 0x3c, 0x9e, 0x8b, 0x89, + 0x3a, 0xae, 0x8d, 0x80, 0xe3, 0x69, 0x97, 0x8a, 0x35, 0x80, 0x37, 0x1c, + 0xc1, 0x3d, 0xe8, 0xe7, 0x14, 0x09, 0x2b, 0xb8, 0x92, 0xe4, 0xa9, 0x56, + 0xad, 0x36, 0x54, 0x03, 0x2f, 0x77, 0x58, 0xfb, 0x94, 0x54, 0xa1, 0xcb, + 0x56, 0x40, 0x6e, 0x1b, 0xf4, 0x58, 0x55, 0x10, 0x8e, 0xe9, 0x60, 0x10, + 0x7a, 0x65, 0xd4, 0x54, 0x53, 0xcb, 0x48, 0x2d, 0xc1, 0x90, 0x49, 0xb6, + 0xc8, 0x3b, 0xac, 0x11, 0x17, 0x56, 0xca, 0xf6, 0x5b, 0xdb, 0xe5, 0xe6, + 0xb2, 0x70, 0xd5, 0x87, 0x5b, 0x99, 0x7a, 0x17, 0x22, 0xee, 0x9d, 0x58, + 0x38, 0x49, 0x41, 0xaa, 0x40, 0xe8, 0x10, 0xb6, 0x0b, 0x83, 0x41, 0x2e, + 0xaf, 0xd0, 0xa7, 0x42, 0x8a, 0x0a, 0xbb, 0x55, 0xdf, 0x45, 0x68, 0x0c, + 0xf2, 0x26, 0x56, 0x71, 0x1d, 0xb6, 0xbf, 0xce, 0x8b, 0xdc, 0xbb, 0x4c, + 0x08, 0x3a, 0x40, 0x1c, 0xdb, 0x68, 0x28, 0x4e, 0x0c, 0x7e, 0xc0, 0x0f, + 0x7d, 0xe7, 0x4e, 0x57, 0x14, 0x6a, 0xda, 0xe2, 0x21, 0xe5, 0x4c, 0xc4, + 0xa5, 0x66, 0xb0, 0x5a, 0x11, 0x3d, 0xdb, 0x22, 0xcb, 0xc1, 0x9d, 0x88, + 0x1a, 0x41, 0xcd, 0x75, 0xde, 0x8c, 0xf6, 0xc7, 0xb8, 0x9a, 0x5f, 0xae, + 0x65, 0x0d, 0xf5, 0x85, 0xaa, 0x70, 0xc0, 0x45, 0xb8, 0x4b, 0x2c, 0xbb, + 0xcc, 0xd0, 0xe7, 0xab, 0x72, 0x0c, 0x58, 0x96, 0xab, 0xfd, 0x35, 0x6a, + 0x66, 0xf3, 0xdc, 0xbb, 0xb5, 0x38, 0x6b, 0xe6, 0xd0, 0x2e, 0xa9, 0xb3, + 0x19, 0x1c, 0xa2, 0x75, 0xd2, 0x22, 0x48, 0xae, 0xdc, 0x36, 0x0e, 0xcd, + 0x40, 0x57, 0xae, 0x06, 0xab, 0x2c, 0x2a, 0xaf, 0xb5, 0x06, 0x57, 0xa9, + 0x1c, 0x62, 0xe0, 0x38, 0xea, 0xc9, 0xf5, 0xc4, 0xd8, 0x81, 0x06, 0xdb, + 0x4c, 0x69, 0x26, 0xfb, 0x5d, 0xd2, 0xde, 0x1e, 0xc7, 0xe4, 0xe0, 0x05, + 0xce, 0x18, 0x45, 0x70, 0xe7, 0xe9, 0x7d, 0x76, 0x42, 0x2f, 0xa0, 0x37, + 0x62, 0x1a, 0x6f, 0x6d, 0x46, 0xcb, 0x83, 0xab, 0x6f, 0x4d, 0x43, 0x4b, + 0x6a, 0x8f, 0x07, 0x39, 0x00, 0xcb, 0x03, 0xa7, 0x81, 0x04, 0x55, 0xd1, + 0x9e, 0x77, 0xd4, 0xdf, 0x62, 0x4d, 0x08, 0xe7, 0x82, 0x09, 0x0f, 0xfa +}; +/* K = 796cef38518aed8644ec5a1b3389da5ee9b063b88e7fb4602af0709999f9a938 */ +static const uint8_t ac_dsa_vect260_out[] = { +/* R */ + 0x41, 0xa2, 0xc9, 0x55, 0xf4, 0x14, 0x13, 0xa7, 0xab, 0x06, 0x7b, 0x4f, + 0x50, 0xc6, 0x1e, 0x39, 0x6f, 0x9f, 0xeb, 0xff, 0x61, 0xc1, 0x50, 0x0b, + 0x1a, 0x4b, 0xc6, 0x9e, 0x50, 0xa5, 0x19, 0x35, +/* S */ + 0x79, 0xed, 0xd7, 0x51, 0xa9, 0xdc, 0x23, 0x72, 0xb4, 0x05, 0x80, 0xfa, + 0x4d, 0x53, 0x8f, 0xbe, 0x2c, 0xda, 0x41, 0x49, 0xf6, 0xb1, 0x19, 0x39, + 0xdd, 0xad, 0x92, 0xc5, 0x74, 0x74, 0x08, 0x83 +}; +#define ac_dsa_vect261_prime ac_dsa_vect256_prime +#define ac_dsa_vect261_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect261_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect261_ptx[] = { +/* Msg */ + 0xa3, 0x26, 0x97, 0x30, 0x93, 0xce, 0x50, 0x2c, 0x16, 0x47, 0x3d, 0x89, + 0xba, 0x19, 0x65, 0x07, 0xd9, 0x22, 0x81, 0x50, 0x47, 0x59, 0xcb, 0x34, + 0xc6, 0xcc, 0x35, 0x3d, 0x45, 0x19, 0x7f, 0x91, 0x5b, 0x5e, 0x73, 0x6b, + 0x8f, 0xf8, 0x57, 0xa8, 0xb2, 0xec, 0x99, 0x64, 0x9a, 0x32, 0x24, 0xf8, + 0x57, 0x40, 0x18, 0x98, 0xc9, 0xea, 0x60, 0x7e, 0x6a, 0x2c, 0x1d, 0x32, + 0x0f, 0x27, 0x56, 0x4c, 0xcf, 0xf5, 0xdb, 0xda, 0xcf, 0xd8, 0x7a, 0x14, + 0x5f, 0x1a, 0x02, 0x94, 0x25, 0xd7, 0x65, 0x02, 0xc0, 0x81, 0xac, 0x0f, + 0x6a, 0x14, 0xde, 0x5b, 0x2c, 0xad, 0x1c, 0x23, 0xa6, 0x1d, 0x4e, 0x9e, + 0xc6, 0xa0, 0x4e, 0x1a, 0x45, 0x5f, 0xd7, 0x10, 0xc3, 0xc7, 0x8c, 0x09, + 0x67, 0x53, 0xc0, 0xb7, 0xf1, 0x51, 0x1e, 0x8b, 0xa5, 0xf5, 0xf1, 0xaf, + 0x4f, 0x07, 0x41, 0xfe, 0xe8, 0x8b, 0x77, 0xeb +}; +static const uint8_t ac_dsa_vect261_priv_val[] = { +/* X */ + 0x37, 0xd0, 0xfa, 0x99, 0xe5, 0xee, 0xd0, 0xfb, 0x51, 0xc6, 0xe6, 0x90, + 0xf0, 0xac, 0x55, 0x6a, 0xe7, 0x4c, 0xab, 0x9a, 0x84, 0xd8, 0x87, 0xa0, + 0x73, 0x63, 0x59, 0x9b, 0x19, 0x84, 0x75, 0xdd +}; +static const uint8_t ac_dsa_vect261_pub_val[] = { +/* Y */ + 0x92, 0x91, 0x5d, 0xb2, 0x1c, 0x2c, 0x3e, 0x57, 0xfc, 0xcc, 0xb7, 0xdf, + 0xdc, 0xe2, 0x8a, 0x12, 0xaa, 0xf6, 0xdd, 0x10, 0x58, 0x11, 0x93, 0xb9, + 0x8b, 0x7d, 0x51, 0xa7, 0x28, 0xc3, 0x85, 0x16, 0xe3, 0x9e, 0xf5, 0xcf, + 0xb1, 0xff, 0x9f, 0xa1, 0x65, 0x9c, 0x9b, 0xee, 0x56, 0xd4, 0xeb, 0xc1, + 0xcd, 0x69, 0x64, 0x6c, 0x3c, 0xc3, 0xf7, 0xca, 0xae, 0x0c, 0x42, 0xd9, + 0xcc, 0xa9, 0x21, 0x91, 0x48, 0xe4, 0x99, 0x8c, 0x2d, 0xdc, 0x89, 0xeb, + 0x9a, 0x3e, 0xdc, 0xfa, 0x6f, 0x45, 0x71, 0x29, 0x00, 0x7a, 0x93, 0x44, + 0x01, 0x3d, 0xd1, 0x23, 0xaf, 0xf1, 0x97, 0xbf, 0xcd, 0x3d, 0xb1, 0xd9, + 0xe2, 0x19, 0x9b, 0xce, 0xa1, 0x61, 0x65, 0xa4, 0xc3, 0x4e, 0xd2, 0xac, + 0x32, 0x16, 0x7a, 0xbd, 0x16, 0x77, 0x04, 0xea, 0xd3, 0x1d, 0x5f, 0xc2, + 0x86, 0x0b, 0x83, 0x4d, 0x44, 0xf8, 0x6c, 0xb5, 0x30, 0xda, 0xd9, 0xe8, + 0x87, 0x01, 0x3c, 0xa4, 0xd6, 0xe8, 0x83, 0x00, 0x8c, 0x28, 0x6d, 0x20, + 0x6b, 0x6c, 0x7c, 0xb2, 0x52, 0xd1, 0x32, 0x8b, 0x50, 0x3a, 0xe0, 0x67, + 0x9b, 0x50, 0x2e, 0xc1, 0x64, 0x6f, 0x69, 0xf2, 0x60, 0x2d, 0x5e, 0x3d, + 0x63, 0x1d, 0x4a, 0x5a, 0x63, 0xfc, 0x7a, 0x5d, 0x06, 0xf2, 0x79, 0x26, + 0xa4, 0xd6, 0xb1, 0xef, 0x2f, 0x77, 0xdd, 0xff, 0x3d, 0x85, 0x0d, 0x3d, + 0x9f, 0x58, 0xa9, 0x58, 0xc3, 0xf4, 0xf1, 0x2c, 0xf0, 0x29, 0xf1, 0x48, + 0x38, 0x6c, 0x5b, 0x8a, 0x71, 0xba, 0xe9, 0x09, 0x4d, 0xec, 0x85, 0x27, + 0x9b, 0x1e, 0x38, 0x77, 0x99, 0xd2, 0x6b, 0x2a, 0x6a, 0x0e, 0x0d, 0xbf, + 0x06, 0x49, 0x73, 0x66, 0xe4, 0x90, 0x3e, 0x55, 0x9e, 0x70, 0x97, 0x5d, + 0xed, 0xc7, 0xd4, 0x93, 0x4d, 0x4e, 0x2d, 0x3d, 0x2c, 0xd3, 0x05, 0xab, + 0x82, 0x64, 0x02, 0xea, 0x8f, 0x27, 0x78, 0xe2, 0x66, 0x25, 0x11, 0x9e, + 0x7b, 0x0c, 0x24, 0xc4, 0x5d, 0xd9, 0xc0, 0x5a, 0x38, 0x90, 0xdd, 0x1d, + 0x9d, 0x93, 0x0b, 0xd0, 0xbb, 0x40, 0x93, 0x66, 0xb0, 0x7a, 0x47, 0xce, + 0x57, 0x2e, 0xd5, 0xbc, 0xd5, 0xf6, 0x3c, 0x46, 0x7d, 0x49, 0xc5, 0x68, + 0x11, 0xfc, 0x3e, 0x40, 0x13, 0x41, 0xb9, 0xa4, 0x53, 0x1f, 0x77, 0x6d, + 0xeb, 0xde, 0xa5, 0x40, 0xa3, 0x4c, 0x7c, 0xca, 0x3c, 0x3f, 0xb2, 0xea, + 0x99, 0xc5, 0xfa, 0x9f, 0x9f, 0xdf, 0xde, 0x91, 0x8a, 0x94, 0xf7, 0x4e, + 0x08, 0x0d, 0x19, 0x86, 0xb6, 0x8f, 0xc1, 0xe3, 0xfb, 0x97, 0x80, 0x54, + 0x87, 0x2c, 0xed, 0x97, 0xba, 0xfd, 0x96, 0x73, 0x1e, 0x6d, 0x4f, 0x1c, + 0x4a, 0x91, 0x27, 0x8c, 0x38, 0x3d, 0x47, 0x61, 0xc9, 0x74, 0x10, 0x09, + 0x74, 0x52, 0x2f, 0x7b, 0x6e, 0x8a, 0x28, 0x84, 0xd5, 0xb3, 0xbb, 0xf6 +}; +/* K = 0b5c9b613708ea26bea151a0dd4222bb573d950588483483cd2b8ab537469e53 */ +static const uint8_t ac_dsa_vect261_out[] = { +/* R */ + 0x73, 0xf1, 0x92, 0x2e, 0x26, 0xd9, 0xb8, 0x06, 0x8b, 0x68, 0xf8, 0x3c, + 0x2b, 0xd5, 0xdb, 0xbb, 0x59, 0x60, 0x40, 0x3b, 0x49, 0x22, 0x3c, 0x02, + 0xa4, 0x2c, 0xe6, 0xcf, 0x38, 0x10, 0xdb, 0x66, +/* S */ + 0x3a, 0xd3, 0x0b, 0xe9, 0xa6, 0x0f, 0x6d, 0x42, 0x27, 0x03, 0x94, 0x56, + 0xc9, 0x82, 0x7d, 0x54, 0x24, 0x85, 0x8a, 0x02, 0xa8, 0xe6, 0xd3, 0x89, + 0x17, 0x72, 0xcf, 0x80, 0xa5, 0xe4, 0xee, 0x21 +}; +#define ac_dsa_vect262_prime ac_dsa_vect256_prime +#define ac_dsa_vect262_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect262_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect262_ptx[] = { +/* Msg */ + 0x75, 0x04, 0x38, 0x2f, 0xb7, 0xfb, 0xa1, 0xda, 0xb3, 0xc9, 0x3b, 0xd3, + 0x1b, 0x16, 0xe7, 0x3d, 0x9a, 0xe1, 0xd0, 0x27, 0xdd, 0x23, 0x16, 0x6b, + 0x3b, 0x94, 0xc7, 0x12, 0x41, 0x83, 0xfa, 0xf3, 0x96, 0x3c, 0x42, 0x0b, + 0xe5, 0x20, 0x5a, 0x1f, 0x44, 0xa9, 0xa9, 0x02, 0x6c, 0x6e, 0xf7, 0x7e, + 0x7c, 0x4e, 0xf1, 0xec, 0x48, 0x45, 0xfe, 0xf6, 0xe5, 0xea, 0x24, 0x87, + 0xce, 0x01, 0x2f, 0xf5, 0x3f, 0x94, 0x50, 0xfc, 0xeb, 0x0d, 0x3a, 0xc6, + 0x2f, 0x21, 0x02, 0xd7, 0x17, 0xe3, 0x28, 0x7d, 0xb3, 0x71, 0x47, 0x17, + 0xa2, 0x8c, 0xd8, 0xb7, 0xfc, 0x64, 0x55, 0x6a, 0x86, 0x17, 0x3e, 0x6e, + 0x7f, 0x47, 0x9f, 0x8a, 0x8d, 0xcd, 0x89, 0x54, 0x29, 0xcd, 0x7f, 0x0f, + 0x53, 0x04, 0xef, 0x6a, 0xaf, 0x27, 0x5d, 0x94, 0xa7, 0xf4, 0xb3, 0x0a, + 0xcc, 0x10, 0x71, 0x78, 0x7c, 0xa5, 0xf0, 0x62 +}; +static const uint8_t ac_dsa_vect262_priv_val[] = { +/* X */ + 0x1c, 0x21, 0xaa, 0x2e, 0xf3, 0xb1, 0x1d, 0x31, 0xf3, 0xc9, 0x4a, 0x27, + 0x88, 0x59, 0xcb, 0x74, 0xbc, 0x40, 0xda, 0xf5, 0x99, 0x3d, 0xbd, 0x77, + 0x4b, 0x32, 0xea, 0x3c, 0xa2, 0x4b, 0xf1, 0x62 +}; +static const uint8_t ac_dsa_vect262_pub_val[] = { +/* Y */ + 0x20, 0x55, 0xbb, 0xe8, 0x9d, 0xa0, 0xa0, 0xc4, 0x88, 0xc3, 0xdb, 0xf2, + 0x95, 0x31, 0xf1, 0xf7, 0xcd, 0x3f, 0xb5, 0x5a, 0x26, 0xef, 0xc5, 0x40, + 0xc2, 0xed, 0xdc, 0xcc, 0xea, 0x16, 0x15, 0xdd, 0x92, 0x3f, 0xea, 0x4c, + 0x8d, 0x0c, 0x95, 0xa5, 0xaf, 0x7e, 0x1e, 0x78, 0x16, 0x04, 0x8f, 0x2a, + 0xe8, 0x53, 0x23, 0xa9, 0x64, 0x11, 0xe7, 0xd1, 0xad, 0x62, 0xc4, 0xca, + 0x67, 0x5b, 0x63, 0xdf, 0x9d, 0xba, 0x31, 0xc1, 0xc7, 0x68, 0x03, 0xfb, + 0x1c, 0x82, 0x92, 0x46, 0x5a, 0xd0, 0xa7, 0xe4, 0x9b, 0xa3, 0x75, 0x6a, + 0x8a, 0xd4, 0xc6, 0xce, 0x86, 0xfd, 0x30, 0xb8, 0xb2, 0x8e, 0x08, 0xc4, + 0xb4, 0x77, 0x7e, 0x07, 0x9f, 0xaf, 0xf1, 0x0f, 0xf8, 0x52, 0xf7, 0xd8, + 0x91, 0xa9, 0x84, 0x19, 0x8d, 0xd0, 0x49, 0x77, 0x97, 0x21, 0x08, 0xc5, + 0x2c, 0xe8, 0xbd, 0xb1, 0x15, 0x64, 0x62, 0x24, 0xa7, 0x93, 0x37, 0x74, + 0x6e, 0x36, 0x47, 0x21, 0x31, 0x98, 0xf1, 0x12, 0x74, 0x30, 0xf5, 0x60, + 0x87, 0x33, 0xd8, 0x82, 0x04, 0xa6, 0x2b, 0xe6, 0xea, 0xee, 0x84, 0x62, + 0x9f, 0xc7, 0x28, 0x2a, 0xce, 0xf4, 0xc4, 0xf5, 0xd3, 0xad, 0xbe, 0x72, + 0x41, 0x0b, 0x1e, 0xdf, 0xb7, 0x4b, 0xe1, 0x6b, 0x2d, 0x67, 0x5c, 0xca, + 0x89, 0x1b, 0xd8, 0xce, 0xf2, 0x05, 0x17, 0x89, 0x02, 0xb9, 0x92, 0x71, + 0xb4, 0x80, 0x41, 0xab, 0xe3, 0x3a, 0xc1, 0x19, 0xad, 0x6b, 0x75, 0x6a, + 0x47, 0x7a, 0x63, 0x06, 0x3a, 0xae, 0x8a, 0x17, 0xcc, 0xfb, 0xe2, 0xac, + 0xae, 0x3c, 0x0a, 0x3c, 0x63, 0x0c, 0x13, 0xad, 0xe1, 0x97, 0xcf, 0x3d, + 0x05, 0xa9, 0xfa, 0x9d, 0x68, 0x99, 0xc0, 0xa3, 0xf9, 0x48, 0x7e, 0x61, + 0x48, 0x73, 0x2d, 0xc6, 0x3e, 0x90, 0x7e, 0xf7, 0x94, 0x88, 0xdf, 0x33, + 0x73, 0xb8, 0xa2, 0x13, 0x70, 0x5d, 0x69, 0xdc, 0xce, 0x6e, 0xd9, 0xa2, + 0x20, 0x9f, 0x59, 0xeb, 0xc5, 0x8b, 0xbb, 0xeb, 0x08, 0x05, 0x45, 0x10, + 0xb5, 0xa6, 0x51, 0x69, 0xd0, 0xfc, 0x1d, 0x4d, 0x10, 0xbd, 0xa6, 0x8a, + 0xa7, 0xec, 0xea, 0xe2, 0xe7, 0x2f, 0x03, 0x39, 0xa2, 0xea, 0xae, 0xa0, + 0x83, 0x03, 0x06, 0x4d, 0xd6, 0x58, 0x84, 0x14, 0xee, 0x77, 0x05, 0xdf, + 0x3a, 0xb9, 0x74, 0xde, 0xbe, 0xf5, 0x88, 0xf4, 0xe3, 0x1f, 0xd6, 0xa8, + 0xf2, 0x59, 0x79, 0xc9, 0xf5, 0x21, 0xd2, 0x34, 0x31, 0x20, 0xe4, 0x07, + 0x94, 0xf4, 0x1a, 0x46, 0x01, 0xbe, 0x57, 0x91, 0x83, 0xb8, 0x77, 0xe6, + 0xa8, 0xf6, 0xc0, 0xab, 0x7c, 0xe8, 0x48, 0x0e, 0x7f, 0xbf, 0xf4, 0x67, + 0xa5, 0x81, 0xdf, 0x57, 0x0a, 0xf8, 0x99, 0x29, 0xbc, 0x4b, 0x56, 0x39, + 0x7b, 0x78, 0x7d, 0xf4, 0xd7, 0x29, 0xe6, 0x5f, 0x9b, 0x98, 0xee, 0x7e +}; +/* K = 44efaf7a15a1eb2a7ba04fd4717e938fe738666040b3d81560497ce166f31e86 */ +static const uint8_t ac_dsa_vect262_out[] = { +/* R */ + 0x56, 0xe2, 0x1a, 0x7a, 0xb6, 0x1f, 0x9e, 0xab, 0xbf, 0xf4, 0x7c, 0x75, + 0xe5, 0xf6, 0x8c, 0x31, 0x87, 0x3a, 0x9e, 0x1f, 0x2e, 0x1d, 0xb6, 0x62, + 0x73, 0x11, 0x82, 0xf9, 0xa0, 0x29, 0xb8, 0xf6, +/* S */ + 0x2f, 0x24, 0xc5, 0x2f, 0x7b, 0xaa, 0xe2, 0x9c, 0x0b, 0x46, 0x33, 0xa3, + 0x85, 0x52, 0x33, 0x18, 0x0e, 0xba, 0x80, 0x61, 0x1d, 0xbc, 0x7e, 0x88, + 0xe2, 0x35, 0x48, 0xa5, 0x20, 0xb6, 0x0f, 0x66 +}; +#define ac_dsa_vect263_prime ac_dsa_vect256_prime +#define ac_dsa_vect263_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect263_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect263_ptx[] = { +/* Msg */ + 0x0c, 0x0f, 0x7b, 0x0f, 0x99, 0x55, 0xbb, 0x54, 0xf1, 0x6e, 0x4e, 0x39, + 0xad, 0x9b, 0xfd, 0x1d, 0xeb, 0x04, 0xb8, 0xe8, 0xb3, 0x8e, 0x67, 0x4d, + 0xa4, 0x55, 0x69, 0x6b, 0xdf, 0x7c, 0xf2, 0x8e, 0x24, 0x11, 0x4a, 0xd0, + 0x05, 0x13, 0xd8, 0xdd, 0x4e, 0x5c, 0x89, 0x5d, 0x35, 0x1e, 0xa9, 0x13, + 0xfe, 0xe5, 0x16, 0xb6, 0x46, 0x82, 0x00, 0x87, 0x72, 0x1d, 0x9a, 0x0b, + 0x5e, 0xcd, 0x76, 0x9b, 0x38, 0x25, 0x73, 0x91, 0x23, 0x54, 0x4e, 0x70, + 0x58, 0xb6, 0x6d, 0x23, 0x42, 0xb0, 0x44, 0x62, 0xd5, 0xd1, 0x73, 0xcd, + 0xb0, 0x0e, 0xf6, 0xac, 0xa6, 0x04, 0xaa, 0xa4, 0x38, 0xb8, 0x86, 0x8d, + 0x15, 0xdd, 0x66, 0x24, 0xab, 0xb8, 0xd1, 0x93, 0x84, 0xdb, 0x48, 0xbd, + 0xaa, 0x66, 0x47, 0x14, 0x13, 0xa8, 0x94, 0xd3, 0x61, 0x0b, 0xc9, 0x7d, + 0x84, 0x8a, 0x59, 0xe2, 0xc6, 0x9c, 0x0c, 0x0a +}; +static const uint8_t ac_dsa_vect263_priv_val[] = { +/* X */ + 0x34, 0x65, 0x1f, 0x58, 0x44, 0xcb, 0xf8, 0x59, 0x60, 0xe9, 0x87, 0x19, + 0x0e, 0xda, 0x4c, 0xa1, 0xfc, 0xf3, 0x2d, 0x8c, 0xbe, 0x1a, 0xd0, 0x8d, + 0xd5, 0xaa, 0x36, 0xfb, 0xd0, 0xd4, 0x20, 0x00 +}; +static const uint8_t ac_dsa_vect263_pub_val[] = { +/* Y */ + 0x45, 0xef, 0x38, 0x4e, 0xd8, 0x17, 0x38, 0x66, 0x68, 0xe1, 0xb9, 0x0b, + 0x42, 0xf1, 0xd4, 0x23, 0xad, 0x9b, 0x17, 0xea, 0x87, 0x01, 0x19, 0xc0, + 0x93, 0x2a, 0xc2, 0xf5, 0x15, 0xf5, 0x46, 0xa3, 0xb6, 0xb8, 0x0a, 0x61, + 0x2e, 0xe6, 0x6d, 0xfc, 0x00, 0xcc, 0x4d, 0x9e, 0x3b, 0x5d, 0xd1, 0x53, + 0x03, 0xd5, 0xeb, 0xc0, 0xaa, 0x40, 0xcb, 0xcd, 0x77, 0x46, 0xf5, 0x4a, + 0x3f, 0xfe, 0xa2, 0x3a, 0xea, 0x07, 0x04, 0xae, 0x9c, 0xf5, 0xad, 0x61, + 0x45, 0x62, 0x9c, 0x61, 0xd1, 0x58, 0xdb, 0x6e, 0xe3, 0x9a, 0xc8, 0x99, + 0xbb, 0xda, 0x59, 0x79, 0x4b, 0x17, 0x69, 0xa9, 0x29, 0x82, 0x08, 0x2b, + 0x77, 0xa1, 0xd4, 0x88, 0x56, 0x42, 0x7b, 0x78, 0xbb, 0x6e, 0x07, 0x7e, + 0x27, 0x33, 0x5f, 0x11, 0x5b, 0xb8, 0x42, 0xe5, 0x32, 0x51, 0xf6, 0x99, + 0xf0, 0x44, 0x88, 0xbe, 0xaf, 0x83, 0xa6, 0xc4, 0xaa, 0x6a, 0x4b, 0x76, + 0x37, 0x0c, 0xef, 0xc9, 0x09, 0x9c, 0x0a, 0x45, 0xbc, 0xf9, 0x73, 0x24, + 0x2d, 0xf2, 0xa0, 0x1e, 0xf6, 0x8e, 0x66, 0xc8, 0x7e, 0xff, 0xd7, 0xf9, + 0x8f, 0x44, 0x1e, 0x94, 0xa0, 0x9a, 0x28, 0x30, 0x07, 0x6c, 0x28, 0x95, + 0xf9, 0x97, 0xaf, 0xd0, 0xa9, 0x09, 0xb4, 0x5b, 0x3c, 0x05, 0x91, 0x77, + 0x00, 0x02, 0x36, 0xc5, 0x01, 0xbf, 0xaa, 0x56, 0xda, 0x80, 0x0e, 0xcf, + 0x08, 0x70, 0x1d, 0x21, 0x20, 0x16, 0xb5, 0x25, 0xf3, 0x0d, 0x63, 0xcc, + 0xf3, 0xaf, 0xea, 0x09, 0xdf, 0x39, 0xe1, 0xcf, 0xab, 0x7b, 0xf4, 0x5d, + 0xe1, 0xa3, 0x9a, 0xc7, 0xf2, 0x8d, 0xe0, 0x03, 0x7e, 0xc5, 0x52, 0xe2, + 0xea, 0x10, 0xc6, 0xb5, 0x6a, 0x5d, 0xb8, 0xc1, 0x3f, 0xcb, 0xf7, 0x3d, + 0x2e, 0x50, 0xd5, 0x8b, 0x4f, 0x3c, 0xf2, 0x78, 0x50, 0x6f, 0x1e, 0xaf, + 0x08, 0x73, 0xe9, 0xee, 0x94, 0x65, 0xcb, 0xaf, 0xf4, 0xae, 0x62, 0x6f, + 0x3a, 0xa1, 0x09, 0xfc, 0xe4, 0x9e, 0x55, 0xd5, 0x7f, 0xe8, 0x81, 0xc5, + 0x0f, 0x72, 0x79, 0x26, 0x26, 0x21, 0x28, 0x2a, 0xdc, 0xf3, 0x79, 0x14, + 0x1c, 0x9b, 0x2c, 0x39, 0x81, 0x3f, 0xaf, 0x82, 0x3a, 0x7e, 0xc0, 0x77, + 0xc6, 0xe6, 0xbf, 0x95, 0x3f, 0x13, 0x0a, 0xca, 0x58, 0xf3, 0x6e, 0x7a, + 0x87, 0xab, 0x1a, 0xae, 0xea, 0x5e, 0xeb, 0x44, 0x02, 0xfa, 0x9e, 0x26, + 0xef, 0x89, 0x38, 0xc8, 0xf3, 0x8a, 0x6c, 0x04, 0x08, 0x09, 0xf4, 0xd0, + 0x4c, 0x81, 0xe2, 0x94, 0x83, 0x87, 0xd7, 0xbe, 0x81, 0x3a, 0x97, 0x3a, + 0x9c, 0x95, 0x17, 0x67, 0x00, 0x11, 0x7d, 0xe2, 0xf3, 0x3e, 0x61, 0x94, + 0x03, 0x87, 0xf8, 0x51, 0xa7, 0x3d, 0xfa, 0x4a, 0xc5, 0xc9, 0x84, 0xec, + 0x97, 0x91, 0x8c, 0x96, 0x7b, 0xfe, 0xdd, 0x88, 0x6d, 0x1b, 0xb7, 0x05 +}; +/* K = 52c16c3e7b17f3e73d7965f584bfd7ca036423b0d42cc00e58d1ccbc419d33b2 */ +static const uint8_t ac_dsa_vect263_out[] = { +/* R */ + 0x77, 0x56, 0x3b, 0x3b, 0x48, 0xfc, 0x9e, 0xe0, 0xdb, 0xea, 0x79, 0xfc, + 0x74, 0xdd, 0x6c, 0x69, 0xb7, 0x2c, 0x42, 0x70, 0x91, 0x8e, 0x6a, 0x1b, + 0xe2, 0xc9, 0x98, 0x17, 0x70, 0x23, 0xb4, 0x0f, +/* S */ + 0x09, 0x9c, 0xdd, 0x62, 0xdc, 0x04, 0x4a, 0x57, 0xea, 0x25, 0xd1, 0xb5, + 0xc1, 0xf6, 0xed, 0x84, 0xd1, 0x1b, 0xac, 0xbb, 0x09, 0x75, 0x97, 0x6d, + 0x58, 0x21, 0xc4, 0x14, 0xb5, 0x41, 0x6b, 0xde +}; +#define ac_dsa_vect264_prime ac_dsa_vect256_prime +#define ac_dsa_vect264_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect264_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect264_ptx[] = { +/* Msg */ + 0xc6, 0x77, 0x35, 0x69, 0x8a, 0xe7, 0xbb, 0xae, 0xb6, 0xf3, 0x21, 0xa1, + 0x08, 0x86, 0x17, 0x38, 0x2a, 0x5c, 0x92, 0x09, 0x21, 0x51, 0xec, 0x36, + 0x45, 0x82, 0x96, 0x2c, 0x9c, 0x0e, 0xd9, 0xed, 0x8f, 0xc7, 0x90, 0xcd, + 0xe0, 0xd9, 0x74, 0x4d, 0x4e, 0x38, 0x97, 0x0a, 0x84, 0x82, 0x40, 0x1c, + 0x0f, 0x61, 0xe9, 0x18, 0x05, 0xf4, 0x98, 0x4b, 0x8c, 0xfd, 0xf9, 0xdc, + 0x80, 0x93, 0xa5, 0xc6, 0x68, 0x1d, 0xac, 0x13, 0x80, 0x9b, 0xc4, 0x1d, + 0x16, 0x7d, 0x3e, 0x11, 0xbc, 0x99, 0x69, 0x8a, 0x4b, 0xc0, 0x7f, 0xd2, + 0x48, 0xa6, 0x74, 0x91, 0xe8, 0x64, 0x10, 0x81, 0xff, 0x1e, 0x97, 0x87, + 0x17, 0x45, 0x15, 0x7c, 0xf9, 0x30, 0x19, 0x5a, 0x35, 0xa1, 0x4d, 0x08, + 0x83, 0xa2, 0x6d, 0xb4, 0x42, 0xe4, 0xed, 0xb9, 0x62, 0xaa, 0x61, 0x87, + 0xb8, 0xd1, 0xc7, 0x79, 0x1d, 0x61, 0xbd, 0x25 +}; +static const uint8_t ac_dsa_vect264_priv_val[] = { +/* X */ + 0x2a, 0xd2, 0x0d, 0x2e, 0x78, 0xa9, 0xec, 0x23, 0x4f, 0x99, 0xa4, 0xb2, + 0xff, 0x52, 0xfa, 0xf4, 0x92, 0xc3, 0xe3, 0x24, 0x2a, 0xe6, 0xc0, 0x4e, + 0xa8, 0xa3, 0x7d, 0x5f, 0x10, 0xfc, 0xe6, 0xdb +}; +static const uint8_t ac_dsa_vect264_pub_val[] = { +/* Y */ + 0x0d, 0x3b, 0x3c, 0x3d, 0xf0, 0x72, 0xb5, 0xf5, 0x12, 0x91, 0x18, 0x13, + 0x2b, 0xb7, 0xbc, 0xa3, 0xc5, 0x2f, 0x51, 0xdf, 0x36, 0x76, 0x7f, 0x11, + 0x52, 0x38, 0x7e, 0xc0, 0x0d, 0xf6, 0x5c, 0x72, 0x8f, 0x0c, 0xff, 0xc1, + 0xcb, 0x6f, 0x22, 0x42, 0x58, 0xcb, 0x6d, 0x3e, 0x90, 0xf7, 0x9d, 0xd9, + 0x76, 0xb5, 0xa1, 0x80, 0xb8, 0x39, 0x03, 0xd2, 0x10, 0xf0, 0xc4, 0xda, + 0xb8, 0x2e, 0xb7, 0x2a, 0x1f, 0x89, 0x97, 0xbf, 0x09, 0x30, 0x1d, 0x0f, + 0x7c, 0x89, 0x07, 0x5d, 0x55, 0x2c, 0x81, 0xfd, 0x95, 0x85, 0xb0, 0xb1, + 0xb1, 0x29, 0x17, 0x44, 0xd2, 0x1b, 0xd1, 0xed, 0xcb, 0x51, 0x12, 0x17, + 0xc2, 0x96, 0x2e, 0x1a, 0x6d, 0xe9, 0xbb, 0x01, 0xc2, 0xb9, 0x69, 0x8f, + 0xf5, 0x5e, 0xa7, 0x5d, 0xcf, 0xe4, 0x56, 0xbe, 0x48, 0x1c, 0xb6, 0xf0, + 0x64, 0xfe, 0xd4, 0xbf, 0xf8, 0x74, 0xeb, 0x1c, 0x9b, 0x74, 0x51, 0x97, + 0x9f, 0x7d, 0xe7, 0x01, 0x1b, 0xaf, 0x5a, 0x47, 0xc9, 0x76, 0xa1, 0x79, + 0xae, 0xe9, 0x09, 0xd2, 0x5c, 0xa8, 0x7f, 0xd5, 0xe3, 0xc7, 0x5d, 0xf7, + 0x78, 0xe2, 0x12, 0x72, 0x93, 0x7c, 0x5b, 0xa7, 0x80, 0x6a, 0xef, 0xa7, + 0x06, 0x47, 0x22, 0x1e, 0x5f, 0x7c, 0xc3, 0x2a, 0xb8, 0x01, 0x59, 0x21, + 0xa5, 0xa9, 0x5e, 0xcb, 0xb3, 0xca, 0x4b, 0x66, 0x72, 0x49, 0xd0, 0xf3, + 0x4d, 0xd2, 0xd8, 0xba, 0x86, 0xdc, 0x15, 0x8f, 0x9e, 0x84, 0x25, 0x17, + 0x6e, 0x98, 0x80, 0x48, 0xef, 0xd9, 0xf7, 0xb7, 0xcc, 0x53, 0xe9, 0xfc, + 0xdb, 0x29, 0xad, 0x24, 0x12, 0xab, 0x4c, 0xa6, 0xeb, 0xbd, 0xe6, 0xf4, + 0xef, 0xca, 0x59, 0x45, 0xb5, 0x3b, 0x27, 0x53, 0xbf, 0xc4, 0xea, 0xbe, + 0x62, 0x80, 0x23, 0x56, 0x20, 0xc4, 0x46, 0x4f, 0x69, 0x40, 0xac, 0xca, + 0x1a, 0x94, 0x65, 0x9a, 0x52, 0x7a, 0xa1, 0x4c, 0xc7, 0xc5, 0x46, 0x73, + 0x82, 0xa5, 0x4f, 0xe4, 0x79, 0x65, 0x6d, 0xfb, 0xc1, 0x19, 0x23, 0x09, + 0x4f, 0xe8, 0x01, 0x9a, 0x08, 0xc3, 0xce, 0x7e, 0x99, 0xa2, 0x8f, 0x08, + 0x6b, 0xda, 0xaf, 0x0f, 0xaa, 0xc6, 0xee, 0x16, 0x19, 0x0d, 0xca, 0x8e, + 0x94, 0xbf, 0x87, 0x65, 0x70, 0x58, 0x49, 0x5a, 0xd0, 0x79, 0x31, 0xc8, + 0x90, 0x08, 0xca, 0x1e, 0x56, 0x50, 0x76, 0x25, 0x6a, 0x93, 0xcb, 0x24, + 0x68, 0xaa, 0x71, 0x22, 0x75, 0x8b, 0x8e, 0x17, 0x4f, 0x6a, 0x80, 0xf4, + 0x1a, 0x90, 0xfc, 0x92, 0xf0, 0x5b, 0xf1, 0xf1, 0xf4, 0x7d, 0xa1, 0x85, + 0xb2, 0xf2, 0x5a, 0x1a, 0xbf, 0x5e, 0x0c, 0xcc, 0x66, 0x13, 0xe3, 0xae, + 0xf8, 0x71, 0x93, 0x40, 0x0d, 0x75, 0x1b, 0x4c, 0x87, 0xb4, 0x4d, 0x9b, + 0xdf, 0x5c, 0x0e, 0x20, 0x7f, 0x0f, 0x6a, 0x7d, 0xc2, 0x11, 0x37, 0x99 +}; +/* K = 654dff8f0500b52adbb70fb7bb7aec4b4820963706964c19c8320e161c3ba365 */ +static const uint8_t ac_dsa_vect264_out[] = { +/* R */ + 0x42, 0xc9, 0x02, 0xc5, 0x82, 0x68, 0x74, 0x77, 0x45, 0x50, 0x46, 0x4c, + 0x4b, 0xb7, 0x36, 0xf2, 0xaf, 0x7f, 0xd2, 0xa3, 0x47, 0xf2, 0x7c, 0x65, + 0xba, 0xe1, 0x18, 0x20, 0xee, 0xb7, 0x52, 0xaa, +/* S */ + 0x64, 0x11, 0xb4, 0x59, 0x47, 0xa4, 0x3c, 0x5b, 0x01, 0xc2, 0xf6, 0xce, + 0xfc, 0xd4, 0x1c, 0xab, 0x73, 0xfc, 0xb6, 0xea, 0x0f, 0x2a, 0x35, 0xa2, + 0x14, 0x75, 0x56, 0x30, 0x55, 0x31, 0x6e, 0x3e +}; +#define ac_dsa_vect265_prime ac_dsa_vect256_prime +#define ac_dsa_vect265_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect265_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect265_ptx[] = { +/* Msg */ + 0xeb, 0x6a, 0x03, 0x59, 0xc6, 0xe4, 0x6e, 0x09, 0xa4, 0x2c, 0x55, 0x47, + 0x05, 0xbc, 0xfc, 0x5c, 0x0c, 0x02, 0x26, 0x70, 0xb2, 0xf6, 0xc1, 0xa5, + 0xbf, 0xe1, 0x4e, 0xa8, 0x05, 0x75, 0x9c, 0xa2, 0x25, 0x61, 0x53, 0xfd, + 0xf8, 0x15, 0x05, 0x7c, 0xa9, 0xbd, 0x5f, 0x4c, 0xf8, 0x37, 0xe1, 0x4f, + 0xdb, 0xa3, 0xad, 0x17, 0x61, 0x2c, 0xcd, 0x19, 0xfd, 0xe0, 0x07, 0x64, + 0xba, 0x2e, 0x8e, 0xcd, 0x8f, 0x5a, 0x18, 0x5c, 0xb2, 0x65, 0x12, 0xf7, + 0x45, 0x72, 0x59, 0xc2, 0xf0, 0x67, 0x08, 0x52, 0x74, 0x1e, 0x73, 0x93, + 0xb4, 0x0c, 0x8b, 0xab, 0x67, 0x3b, 0xe2, 0xfa, 0x51, 0x9b, 0x48, 0xa9, + 0x5d, 0xee, 0x65, 0x52, 0x36, 0x5f, 0xdb, 0x7d, 0xdb, 0x63, 0x2b, 0x1b, + 0x33, 0xf1, 0xa5, 0x29, 0x0b, 0x82, 0x8d, 0xa5, 0x96, 0x5e, 0x82, 0xd8, + 0x74, 0xf7, 0x9c, 0xdb, 0x92, 0x88, 0x14, 0xfb +}; +static const uint8_t ac_dsa_vect265_priv_val[] = { +/* X */ + 0x0d, 0x06, 0xd4, 0x05, 0xd2, 0x28, 0xc0, 0xed, 0x86, 0x0b, 0x9e, 0x21, + 0xba, 0xe5, 0x70, 0xa6, 0xfd, 0x94, 0x0c, 0xc7, 0x02, 0xdd, 0x6e, 0x9a, + 0x08, 0x46, 0xe7, 0xb2, 0xa4, 0xbe, 0x47, 0xa5 +}; +static const uint8_t ac_dsa_vect265_pub_val[] = { +/* Y */ + 0x6d, 0xb8, 0x3b, 0x06, 0xc6, 0x98, 0xed, 0x80, 0x12, 0x2e, 0xc4, 0xa2, + 0x18, 0x33, 0x70, 0xed, 0x7d, 0xbd, 0x6e, 0xa4, 0x4d, 0xbb, 0x45, 0x42, + 0x14, 0x95, 0x68, 0x57, 0x0c, 0x53, 0x52, 0x1d, 0x33, 0x99, 0xab, 0x44, + 0xfe, 0x2b, 0xab, 0xd4, 0x90, 0x68, 0xe1, 0x19, 0x53, 0xc5, 0xd3, 0x8f, + 0x7f, 0xfe, 0x3b, 0xcb, 0xe4, 0xcb, 0xce, 0xb9, 0x1c, 0x15, 0x5a, 0xc8, + 0x74, 0x1d, 0xcf, 0x22, 0x6a, 0x59, 0xed, 0xe1, 0x0b, 0x05, 0x0b, 0x9f, + 0x37, 0x43, 0xf2, 0x96, 0x89, 0x26, 0x6c, 0xe6, 0xee, 0x02, 0x0c, 0xa1, + 0x7f, 0x9f, 0xa0, 0xe7, 0x5b, 0x3f, 0x71, 0x58, 0xa6, 0x5c, 0xef, 0x9f, + 0xac, 0x76, 0xc8, 0x87, 0x86, 0xb5, 0xe3, 0x77, 0xaf, 0xea, 0xcb, 0x9b, + 0x3d, 0xda, 0x55, 0xbe, 0x92, 0x2d, 0xa0, 0xef, 0x95, 0x8a, 0xa5, 0x56, + 0xab, 0xfb, 0x43, 0x06, 0x7a, 0x41, 0x4e, 0x91, 0x5e, 0x31, 0xaf, 0x5f, + 0x53, 0x70, 0x88, 0x1e, 0xd9, 0x7b, 0x25, 0xb4, 0xbf, 0xec, 0xbe, 0x08, + 0x2a, 0x14, 0x5d, 0x02, 0x71, 0x7a, 0xf8, 0x00, 0xe7, 0x7e, 0x28, 0x96, + 0x3c, 0xc0, 0xa6, 0xa1, 0xc1, 0x1b, 0x02, 0x83, 0x5e, 0x14, 0xbd, 0xba, + 0x1a, 0x8c, 0x9c, 0xe4, 0xbf, 0xeb, 0x06, 0xaa, 0xeb, 0xd7, 0x60, 0xd7, + 0xc4, 0x3c, 0xf5, 0x6b, 0xa2, 0x12, 0xd0, 0xc7, 0x5d, 0xa0, 0x26, 0x17, + 0x65, 0x35, 0xf9, 0x82, 0xe8, 0xd7, 0x49, 0xf2, 0x0c, 0x2a, 0x8d, 0x5f, + 0x53, 0x87, 0x5d, 0x89, 0x33, 0x74, 0xd8, 0x59, 0xb7, 0xce, 0xe5, 0x8b, + 0x0e, 0xb3, 0x19, 0xd3, 0x31, 0x3c, 0xb8, 0xd1, 0x76, 0x02, 0xf4, 0x7e, + 0x12, 0x0d, 0x1a, 0x24, 0xa0, 0xf8, 0xa6, 0x3c, 0xfe, 0x45, 0xa5, 0x02, + 0x8c, 0xc0, 0x93, 0x7b, 0xbe, 0x89, 0xf6, 0xb3, 0xb7, 0xcd, 0xca, 0xa7, + 0xdc, 0xd5, 0xec, 0x5f, 0x3e, 0xd2, 0xaa, 0x9f, 0x3a, 0xa8, 0xe9, 0x1a, + 0x49, 0x6a, 0x8b, 0xad, 0x78, 0x74, 0xdd, 0x34, 0xbd, 0x8f, 0x2a, 0x95, + 0x91, 0x99, 0x7d, 0x54, 0xf9, 0x2d, 0x58, 0x64, 0x21, 0x6c, 0x95, 0x36, + 0x46, 0x84, 0x0b, 0x37, 0x8c, 0x7a, 0x05, 0x21, 0x5e, 0xcd, 0x97, 0xb6, + 0xba, 0x94, 0x4c, 0xa1, 0x85, 0x97, 0xb7, 0xa5, 0x48, 0x32, 0xec, 0x98, + 0xc1, 0xca, 0xc0, 0x00, 0x3d, 0x50, 0xd5, 0xa0, 0x53, 0x12, 0xcb, 0xc8, + 0x52, 0xd5, 0x07, 0xcc, 0x97, 0x3e, 0xcb, 0x56, 0xf4, 0x24, 0xe8, 0xa1, + 0xc1, 0x98, 0xbc, 0xdb, 0xaf, 0xaa, 0x6f, 0x92, 0x8f, 0xd2, 0x7a, 0x7c, + 0x91, 0xf8, 0x4b, 0xc2, 0x34, 0xf2, 0x53, 0x26, 0x39, 0xa8, 0xaa, 0x21, + 0x96, 0xf8, 0xfc, 0x2b, 0x71, 0x11, 0xb3, 0xd0, 0xb1, 0x15, 0x31, 0x65, + 0xa0, 0xe0, 0x52, 0x5d, 0x4e, 0xa5, 0x95, 0xf8, 0x9a, 0xec, 0x33, 0xb6 +}; +/* K = 521906f186797e7f5ce85112ab2457ddc030d6f34be361929f4d373dda576e08 */ +static const uint8_t ac_dsa_vect265_out[] = { +/* R */ + 0x04, 0x93, 0xdb, 0x0c, 0x18, 0xa3, 0x88, 0x27, 0x09, 0xb3, 0xcc, 0x9f, + 0x8d, 0xbe, 0x05, 0x45, 0x45, 0x06, 0xc0, 0x4c, 0x3a, 0x12, 0xa4, 0x1d, + 0x59, 0x9d, 0x20, 0x1d, 0x76, 0x15, 0xb6, 0xd8, +/* S */ + 0x74, 0x94, 0xb4, 0xd1, 0xb2, 0xf3, 0xae, 0x22, 0x79, 0x72, 0x55, 0xa1, + 0xd0, 0x66, 0x27, 0x46, 0x35, 0x2a, 0x3d, 0x05, 0x32, 0x29, 0x04, 0x02, + 0x06, 0x85, 0x94, 0xcf, 0xe4, 0x8c, 0x23, 0xa3 +}; +#define ac_dsa_vect266_prime ac_dsa_vect256_prime +#define ac_dsa_vect266_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect266_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect266_ptx[] = { +/* Msg */ + 0x5c, 0x59, 0xb2, 0x09, 0xbb, 0xc0, 0xa1, 0xe0, 0x10, 0xcb, 0x10, 0x8d, + 0xb4, 0x10, 0x1b, 0x8e, 0x2d, 0x04, 0xce, 0xd9, 0x12, 0x99, 0xa8, 0x74, + 0x23, 0x22, 0x10, 0x2e, 0x0d, 0x57, 0x8c, 0x36, 0x98, 0x42, 0x2b, 0x43, + 0xd1, 0x9d, 0x33, 0x16, 0x08, 0x18, 0x8b, 0xed, 0x4c, 0x7e, 0xdc, 0x03, + 0xa4, 0x42, 0xf8, 0x9a, 0xae, 0x60, 0xf4, 0xe7, 0xee, 0x9b, 0x63, 0x25, + 0xde, 0x3a, 0x8b, 0xb7, 0x02, 0x91, 0x8c, 0x21, 0x34, 0x3b, 0xc9, 0xb2, + 0x66, 0xf2, 0xeb, 0xcf, 0x5a, 0x62, 0x03, 0x36, 0xa7, 0xbc, 0x99, 0xae, + 0x36, 0x85, 0xf1, 0x90, 0x80, 0xdb, 0x46, 0xf2, 0x4a, 0x50, 0x12, 0x28, + 0xc5, 0xbb, 0xfd, 0x9c, 0x0b, 0x4b, 0x0a, 0xbe, 0xcb, 0xfb, 0xd6, 0x76, + 0xc3, 0x59, 0x60, 0x7c, 0xe2, 0x92, 0xcf, 0xfd, 0x52, 0xd2, 0x6a, 0xf8, + 0x0b, 0x22, 0xe3, 0xc4, 0xd5, 0x16, 0xba, 0x0f +}; +static const uint8_t ac_dsa_vect266_priv_val[] = { +/* X */ + 0x42, 0x14, 0xd5, 0x5b, 0x0a, 0x05, 0x8c, 0x3d, 0xee, 0x27, 0x51, 0x40, + 0x7d, 0x92, 0x96, 0x16, 0x8f, 0xed, 0x9f, 0x25, 0x5e, 0x5c, 0x68, 0x27, + 0x3e, 0x1e, 0x5a, 0xeb, 0x3e, 0x50, 0x4e, 0x67 +}; +static const uint8_t ac_dsa_vect266_pub_val[] = { +/* Y */ + 0xbe, 0x31, 0xfd, 0x5d, 0x62, 0xdb, 0x69, 0x0b, 0xcd, 0xbc, 0x09, 0xe4, + 0x53, 0xd4, 0x41, 0x7f, 0x82, 0xe8, 0x62, 0x1a, 0xd7, 0x17, 0xca, 0xb9, + 0x46, 0x48, 0x20, 0x1a, 0x74, 0xf6, 0xff, 0xdf, 0xab, 0x96, 0x53, 0x11, + 0xe8, 0xff, 0x35, 0xc4, 0xa0, 0xb5, 0xdd, 0xa3, 0x39, 0xb4, 0x35, 0xf1, + 0x73, 0x17, 0x17, 0x5a, 0xc6, 0x42, 0xf7, 0x85, 0x12, 0x9e, 0x15, 0x16, + 0x94, 0xea, 0x8b, 0x24, 0x46, 0x27, 0xe3, 0x00, 0xce, 0xb0, 0xf3, 0xbe, + 0x08, 0xf9, 0x1c, 0x0f, 0x52, 0x7f, 0x2e, 0x0d, 0xf7, 0xc9, 0xf5, 0x54, + 0x92, 0xd1, 0x32, 0x9b, 0x7d, 0x96, 0x89, 0x63, 0x4c, 0x8a, 0x4f, 0x52, + 0x10, 0x15, 0x7e, 0x24, 0x19, 0xe6, 0x15, 0xd9, 0x43, 0x17, 0x36, 0xf8, + 0x04, 0xb1, 0x64, 0x11, 0x03, 0x37, 0x1e, 0x7f, 0xfe, 0x72, 0x00, 0xe7, + 0x42, 0x96, 0x12, 0x7d, 0x59, 0xa8, 0xf9, 0x7d, 0x41, 0xaf, 0x11, 0xd7, + 0x0c, 0x3f, 0xd0, 0x25, 0x31, 0xf7, 0xb8, 0x11, 0xda, 0xa7, 0x51, 0x6a, + 0xa2, 0xf2, 0xa9, 0xba, 0x70, 0xdc, 0xb7, 0x04, 0xf3, 0xfe, 0xe4, 0x7f, + 0x2c, 0xbe, 0xd6, 0x5c, 0x1e, 0x3d, 0x06, 0xc8, 0x81, 0x4e, 0x1b, 0x28, + 0xab, 0xe2, 0x9f, 0x3d, 0x05, 0x67, 0x92, 0xef, 0xdf, 0x9a, 0xc9, 0x30, + 0x7e, 0xd0, 0x10, 0x6c, 0x5a, 0x32, 0x87, 0x21, 0xaf, 0x0e, 0x20, 0x2b, + 0x6d, 0xf7, 0x37, 0xec, 0x4d, 0x82, 0x14, 0x3d, 0xd2, 0x50, 0x5e, 0x10, + 0x3a, 0xd8, 0x45, 0x86, 0x3c, 0x45, 0x86, 0x9e, 0x69, 0xab, 0xd9, 0xe0, + 0x2c, 0x7b, 0x6e, 0xaa, 0xff, 0x9e, 0x2e, 0x12, 0xbc, 0x18, 0x81, 0x38, + 0x68, 0x8c, 0x0b, 0xe3, 0xe6, 0x94, 0x1c, 0x37, 0xc7, 0xdd, 0xc9, 0xb6, + 0xd2, 0x89, 0xf7, 0xcc, 0x8f, 0xde, 0x42, 0xbc, 0x3c, 0x14, 0xe3, 0xee, + 0x52, 0x16, 0x35, 0xf3, 0x2f, 0x54, 0x28, 0x0d, 0x11, 0x9c, 0xce, 0xdf, + 0xc5, 0x10, 0x90, 0xa0, 0xad, 0x00, 0x6b, 0x24, 0x27, 0x60, 0x40, 0x14, + 0xea, 0x4d, 0x0e, 0x0c, 0xd1, 0xef, 0xbc, 0xe0, 0x9c, 0x7f, 0x8e, 0x99, + 0x81, 0xf9, 0x69, 0xae, 0xd6, 0xd4, 0x81, 0xca, 0xfb, 0x32, 0x9f, 0x99, + 0x53, 0x43, 0x54, 0x1d, 0x36, 0x68, 0x6d, 0xe6, 0xcb, 0x8e, 0x4b, 0x1e, + 0x7e, 0x37, 0x27, 0xab, 0xd5, 0xc1, 0xe3, 0xff, 0xa6, 0x93, 0x6a, 0xd4, + 0x4b, 0x92, 0x60, 0x63, 0x56, 0x15, 0x12, 0xc0, 0xe9, 0xac, 0x78, 0x7f, + 0x8e, 0xb7, 0x91, 0xf9, 0x63, 0xf7, 0x90, 0xba, 0x1b, 0x21, 0xdf, 0xe1, + 0xb8, 0xd3, 0x1d, 0x4c, 0x16, 0xb1, 0x52, 0xa6, 0xde, 0x65, 0xbf, 0x54, + 0xab, 0x0f, 0x0d, 0x1e, 0x3d, 0x45, 0x03, 0x17, 0xb1, 0xcf, 0x0c, 0x4e, + 0x33, 0x1d, 0x18, 0x58, 0x7a, 0xcc, 0xb6, 0x96, 0x0c, 0xcd, 0x04, 0xdd +}; +/* K = 574cca3bd87ec1994449da2f2324a3945fa3047791274367bac0f12d4c064343 */ +static const uint8_t ac_dsa_vect266_out[] = { +/* R */ + 0x7f, 0xc9, 0xba, 0xb3, 0x50, 0x5a, 0xdc, 0xd1, 0xb1, 0xc8, 0x12, 0x7e, + 0x2d, 0x1f, 0xbc, 0xd0, 0xe1, 0x5e, 0xaa, 0xc3, 0x14, 0x25, 0x0d, 0xc1, + 0xc6, 0x84, 0xfc, 0xc4, 0x7f, 0xda, 0x29, 0x93, +/* S */ + 0x70, 0xf2, 0x00, 0x7e, 0xdd, 0x68, 0xfb, 0x9d, 0xfe, 0x19, 0xa6, 0x3e, + 0xee, 0x4d, 0x5a, 0x97, 0x72, 0x91, 0xab, 0xd2, 0x35, 0xed, 0x26, 0xe4, + 0x29, 0x14, 0x76, 0xca, 0x5d, 0x0c, 0x81, 0x71 +}; +#define ac_dsa_vect267_prime ac_dsa_vect256_prime +#define ac_dsa_vect267_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect267_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect267_ptx[] = { +/* Msg */ + 0xc8, 0x05, 0xd1, 0x8c, 0x0b, 0xb5, 0x3d, 0x32, 0xb5, 0x7c, 0xb6, 0x52, + 0xf5, 0xb0, 0xe5, 0x29, 0x3b, 0xe4, 0x92, 0xa1, 0xc8, 0x8d, 0xfb, 0xec, + 0x5b, 0xaf, 0x47, 0xee, 0x09, 0x3e, 0x2d, 0xf0, 0x69, 0x18, 0x99, 0x4e, + 0x5c, 0xac, 0xbc, 0x3d, 0xff, 0xf2, 0x29, 0xab, 0xd3, 0x1f, 0xab, 0x7a, + 0x95, 0xad, 0xe2, 0xfb, 0x53, 0xad, 0xaa, 0x7d, 0xff, 0x51, 0xf6, 0xc8, + 0x58, 0x1c, 0x69, 0xeb, 0x5b, 0x09, 0x0b, 0xae, 0xc3, 0x86, 0x07, 0xee, + 0x94, 0x35, 0x44, 0x7a, 0xd8, 0x13, 0x74, 0x55, 0xb6, 0xba, 0x17, 0x9f, + 0xc5, 0x3a, 0xc0, 0x94, 0xf9, 0x7e, 0x3e, 0x29, 0xd0, 0x72, 0x4c, 0xd1, + 0x08, 0x11, 0xf1, 0x42, 0xd6, 0x7d, 0x1c, 0xfc, 0xd5, 0xc3, 0xd1, 0xe9, + 0xb4, 0x11, 0xda, 0xc3, 0x8f, 0x6e, 0x1c, 0x0c, 0x14, 0xdc, 0x9a, 0x50, + 0xd8, 0x4b, 0xcf, 0x00, 0xec, 0xe8, 0xa6, 0x03 +}; +static const uint8_t ac_dsa_vect267_priv_val[] = { +/* X */ + 0x3c, 0xc7, 0xe5, 0x85, 0x77, 0x38, 0x25, 0x00, 0xcb, 0x46, 0x1c, 0x0a, + 0xb8, 0xff, 0x01, 0xec, 0xe8, 0xfa, 0x76, 0x6b, 0x66, 0xf8, 0xbe, 0x74, + 0x6e, 0x34, 0x7e, 0xd2, 0xeb, 0xc1, 0x8e, 0xbb +}; +static const uint8_t ac_dsa_vect267_pub_val[] = { +/* Y */ + 0x2b, 0x6e, 0x1a, 0x8d, 0x44, 0x82, 0xb4, 0x16, 0x97, 0xbb, 0xbe, 0x50, + 0xb5, 0x5b, 0x3d, 0xcd, 0xec, 0xea, 0x8d, 0x2e, 0x2e, 0xb5, 0xcf, 0x27, + 0xb8, 0x92, 0xbc, 0xbc, 0xab, 0xfb, 0x25, 0x3c, 0x19, 0x48, 0x6f, 0xa7, + 0x7c, 0x98, 0xc1, 0x5a, 0xdd, 0x41, 0x49, 0x92, 0x5b, 0x55, 0x01, 0xe5, + 0xa5, 0xef, 0x45, 0xb3, 0x2a, 0xd0, 0x9a, 0x87, 0x24, 0x62, 0xa0, 0xf4, + 0x1d, 0x04, 0x8a, 0xf4, 0xe5, 0x30, 0x66, 0x0a, 0x38, 0x64, 0x93, 0x7b, + 0xa6, 0xa9, 0xeb, 0x07, 0x34, 0xe9, 0x0f, 0xda, 0x3c, 0x9b, 0x6f, 0xcd, + 0x30, 0xc9, 0x07, 0x87, 0x71, 0x29, 0x5a, 0x93, 0x80, 0x2d, 0x9e, 0x19, + 0x92, 0xa4, 0xee, 0xe9, 0xaf, 0x7a, 0x04, 0x13, 0x88, 0x0f, 0x33, 0xbc, + 0x0b, 0x62, 0x03, 0x62, 0x03, 0x28, 0x68, 0x44, 0xbc, 0x38, 0x41, 0x87, + 0xec, 0x51, 0xa3, 0x3d, 0x39, 0x0e, 0xaa, 0xc0, 0xcc, 0x33, 0x28, 0x09, + 0x8a, 0x84, 0x75, 0x09, 0x12, 0x9b, 0xda, 0x73, 0x59, 0x09, 0xfc, 0x7a, + 0x11, 0x89, 0x3a, 0xd0, 0xec, 0x61, 0x27, 0x6b, 0x7a, 0x5d, 0xcd, 0x4e, + 0x62, 0x6d, 0x9b, 0xa6, 0x76, 0x10, 0xea, 0xf0, 0xaf, 0x87, 0x6a, 0xfc, + 0x04, 0x19, 0xfa, 0x4f, 0x00, 0x9a, 0xa5, 0xf9, 0x13, 0xa1, 0xc7, 0x37, + 0x98, 0xc2, 0x70, 0x7e, 0xeb, 0x8f, 0xa7, 0x7f, 0x4e, 0xe0, 0x58, 0x22, + 0x9a, 0x0a, 0xd3, 0x7e, 0x84, 0x57, 0x39, 0x66, 0x8d, 0x95, 0xde, 0x22, + 0x67, 0x60, 0x89, 0x8c, 0x02, 0xd0, 0x6f, 0x15, 0x5f, 0x82, 0xdc, 0x16, + 0x36, 0x0c, 0x3a, 0xbc, 0xa3, 0x78, 0x0b, 0xcd, 0xb7, 0x94, 0x46, 0xc8, + 0x34, 0x35, 0x83, 0xdc, 0x0f, 0x69, 0x25, 0x43, 0x4b, 0x0d, 0xae, 0x7b, + 0x59, 0xcb, 0x26, 0xb1, 0x00, 0x08, 0xf8, 0x65, 0x70, 0xca, 0x03, 0x50, + 0xde, 0x34, 0x0b, 0x27, 0x55, 0x24, 0xf0, 0x05, 0x51, 0x31, 0x0f, 0x1d, + 0x09, 0x5d, 0xb8, 0x48, 0x0b, 0x4a, 0xcc, 0x48, 0x9c, 0xf5, 0xe2, 0x94, + 0x7e, 0xb9, 0x29, 0x04, 0xeb, 0xfd, 0x0d, 0x97, 0x8b, 0xbf, 0xb5, 0xd0, + 0xc6, 0xa1, 0xa9, 0xdb, 0x50, 0xcc, 0x69, 0x17, 0x94, 0x9c, 0x71, 0x85, + 0x46, 0x32, 0xb4, 0x40, 0x8b, 0xad, 0xe5, 0x19, 0x5d, 0x40, 0xdc, 0xaf, + 0x61, 0xfe, 0x95, 0x0e, 0xff, 0x0c, 0x89, 0x97, 0xc3, 0x74, 0xf1, 0xd4, + 0x65, 0xc8, 0x0b, 0xc6, 0x5a, 0xdd, 0xa6, 0x36, 0x43, 0x3e, 0x94, 0xf2, + 0x2c, 0x5f, 0xbc, 0xf0, 0x9e, 0x99, 0x66, 0x6a, 0x53, 0x59, 0x19, 0xee, + 0x6f, 0x88, 0x15, 0x49, 0x34, 0xf1, 0x13, 0x77, 0xa9, 0xa9, 0xe0, 0x21, + 0xf2, 0xd7, 0xec, 0xab, 0xa3, 0x25, 0x10, 0xe9, 0x2b, 0xf5, 0xad, 0x67, + 0xfa, 0x8b, 0x3d, 0x70, 0xdd, 0x20, 0x92, 0xb1, 0x38, 0x9e, 0x31, 0x93 +}; +/* K = 179c02ec8f18fd88146120fcc51628f23e250ad694aa47bd691c0f442a63a92d */ +static const uint8_t ac_dsa_vect267_out[] = { +/* R */ + 0x38, 0x20, 0x8c, 0x09, 0x85, 0x62, 0x4b, 0xb9, 0xd6, 0x27, 0x13, 0xbc, + 0x71, 0x50, 0x94, 0x2c, 0xbc, 0x92, 0xb8, 0xe8, 0xa3, 0x6e, 0xf6, 0xd1, + 0xec, 0x4d, 0x08, 0xd1, 0xd9, 0xa5, 0x71, 0x5f, +/* S */ + 0x65, 0xd2, 0xba, 0x78, 0x7e, 0xd4, 0xc0, 0x8b, 0xea, 0xbf, 0x24, 0x34, + 0x3d, 0x06, 0xed, 0x61, 0x87, 0x2d, 0x6d, 0x68, 0x4a, 0x3b, 0xc7, 0x03, + 0x07, 0xfc, 0xb7, 0xe2, 0x0d, 0xf9, 0x31, 0xda +}; +#define ac_dsa_vect268_prime ac_dsa_vect256_prime +#define ac_dsa_vect268_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect268_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect268_ptx[] = { +/* Msg */ + 0x9e, 0x0c, 0x66, 0xa4, 0xf1, 0x20, 0xe8, 0x5a, 0xea, 0x06, 0x4e, 0x7a, + 0x8b, 0xa1, 0x32, 0xcf, 0x30, 0xa4, 0x5d, 0xe2, 0x88, 0x9f, 0x35, 0x47, + 0x38, 0x4e, 0x4e, 0x84, 0xf4, 0x5b, 0x35, 0x72, 0xbb, 0x04, 0x23, 0xb8, + 0x34, 0xde, 0x9f, 0x2c, 0x96, 0x36, 0xfa, 0xff, 0xdb, 0x63, 0x31, 0x92, + 0x4f, 0x0d, 0x2f, 0x5b, 0x68, 0x76, 0x14, 0x5d, 0x9c, 0xae, 0x11, 0x0a, + 0xb0, 0xcf, 0x6f, 0xc9, 0x0c, 0x2e, 0xef, 0xf9, 0x8c, 0x61, 0xfa, 0x18, + 0x6c, 0xc3, 0x95, 0x2b, 0x57, 0x29, 0x9a, 0x73, 0x67, 0x8f, 0x45, 0x85, + 0xbb, 0x18, 0xfb, 0xb8, 0x4e, 0xf4, 0x16, 0x67, 0x79, 0xff, 0x10, 0xee, + 0xd1, 0x4d, 0x47, 0xae, 0x52, 0x8e, 0x03, 0x29, 0x8d, 0xbb, 0x97, 0xcf, + 0x4f, 0x88, 0xb7, 0xe6, 0xd0, 0x95, 0x9b, 0x58, 0x94, 0x55, 0x0a, 0x3e, + 0x2e, 0x35, 0x69, 0x47, 0xd2, 0x5f, 0xfe, 0x73 +}; +static const uint8_t ac_dsa_vect268_priv_val[] = { +/* X */ + 0x5c, 0x57, 0x91, 0xdd, 0x64, 0x87, 0x03, 0xf2, 0x90, 0x99, 0x73, 0x61, + 0x46, 0xf5, 0xb1, 0xb5, 0xe3, 0x5d, 0xc7, 0x1a, 0x74, 0xd6, 0xee, 0xd3, + 0x12, 0xd3, 0x7a, 0xeb, 0x6d, 0x38, 0x9e, 0xf0 +}; +static const uint8_t ac_dsa_vect268_pub_val[] = { +/* Y */ + 0xa6, 0x2a, 0xdb, 0xda, 0xa5, 0xa5, 0x5a, 0x2d, 0x1e, 0x43, 0x9b, 0x54, + 0x89, 0xcd, 0x6c, 0x8f, 0xcb, 0x23, 0xe9, 0xc6, 0x4f, 0xbf, 0xae, 0x7c, + 0x83, 0xe9, 0xd5, 0x59, 0x93, 0x19, 0xbf, 0x3f, 0x06, 0xc3, 0xc2, 0x90, + 0xb9, 0x89, 0xa6, 0x38, 0x94, 0x0b, 0x1d, 0x0b, 0x7e, 0x8b, 0xf6, 0x74, + 0x13, 0x19, 0xab, 0x4c, 0x38, 0xd4, 0x6e, 0x77, 0xeb, 0xd4, 0x94, 0x5e, + 0x25, 0xcb, 0x89, 0xcb, 0xb6, 0x4e, 0x44, 0xb9, 0x47, 0x4b, 0xc7, 0xc9, + 0xd9, 0xf6, 0x1a, 0x36, 0xe5, 0x7e, 0xb6, 0xaf, 0xab, 0x6c, 0x7a, 0x14, + 0x9a, 0xfe, 0x02, 0xc1, 0xcd, 0x68, 0x54, 0x83, 0x20, 0x8c, 0x55, 0xfe, + 0xec, 0xb0, 0xd0, 0xbd, 0x96, 0x69, 0x7b, 0x43, 0x79, 0x91, 0x05, 0x92, + 0x67, 0xd7, 0x6a, 0x48, 0x84, 0x65, 0xfa, 0xab, 0x4a, 0x7e, 0x17, 0x59, + 0x23, 0x29, 0x56, 0x70, 0x05, 0xfa, 0xa4, 0x21, 0xe0, 0x11, 0xd6, 0x7f, + 0x4d, 0xa7, 0x5a, 0xcc, 0xb6, 0x27, 0x53, 0x7e, 0x93, 0x3e, 0x9e, 0xf0, + 0xbe, 0x3c, 0x70, 0xf2, 0x1e, 0xd3, 0xf8, 0xc3, 0xb3, 0xd7, 0xd7, 0x69, + 0xbb, 0x61, 0x1f, 0x82, 0xf2, 0xba, 0xa1, 0x0f, 0xbc, 0x73, 0x13, 0xad, + 0x08, 0x19, 0x04, 0x8d, 0x35, 0x3d, 0x67, 0x97, 0x36, 0xc4, 0xd1, 0x4b, + 0xca, 0x99, 0x85, 0xec, 0xd3, 0x70, 0x41, 0xaf, 0xff, 0xb2, 0x91, 0xa7, + 0xd9, 0x09, 0xc7, 0x45, 0x81, 0x81, 0xd0, 0x15, 0x92, 0xe6, 0xc9, 0x0c, + 0x0e, 0x34, 0xb4, 0x94, 0x61, 0xed, 0xe6, 0x6c, 0x5a, 0xc0, 0x02, 0x67, + 0x1a, 0x49, 0x85, 0x54, 0x6a, 0x60, 0x75, 0xdf, 0x95, 0xb5, 0x23, 0xf1, + 0x66, 0xd2, 0xe0, 0xd1, 0xf5, 0xda, 0x77, 0xba, 0xff, 0x5a, 0x24, 0xdf, + 0x77, 0x5c, 0xc9, 0xd3, 0x67, 0xf2, 0xa0, 0x72, 0x8c, 0x48, 0x02, 0xd7, + 0x97, 0x04, 0x17, 0x88, 0xc5, 0x6c, 0xb8, 0x71, 0x29, 0x03, 0x32, 0xc1, + 0x36, 0x1f, 0x8d, 0xa8, 0x89, 0x7b, 0x5b, 0x8e, 0x25, 0xd4, 0xa9, 0x35, + 0x94, 0xac, 0x64, 0x8b, 0xc5, 0x3c, 0x9d, 0x85, 0xb4, 0xfc, 0xdd, 0x7a, + 0xb0, 0xf5, 0xa3, 0xee, 0x9c, 0x25, 0xcc, 0x14, 0xba, 0x65, 0x43, 0xb0, + 0x78, 0x85, 0x95, 0x24, 0xec, 0x7f, 0x0b, 0x61, 0xcd, 0xb2, 0x09, 0xcc, + 0x51, 0xc4, 0x0a, 0xa9, 0xaf, 0x08, 0x2e, 0xa9, 0xc1, 0xd4, 0xb9, 0x1b, + 0x2c, 0x1f, 0x6d, 0xc1, 0x1c, 0xd8, 0x79, 0xfb, 0x38, 0x65, 0xd8, 0x79, + 0xfe, 0x00, 0x0f, 0x0e, 0x0b, 0x4b, 0x23, 0x3d, 0xbd, 0x01, 0xc9, 0xc9, + 0x8d, 0x01, 0xa6, 0x64, 0x74, 0x65, 0x77, 0xa6, 0x4b, 0xf2, 0x8d, 0x88, + 0x25, 0x6b, 0x76, 0xde, 0x2b, 0xab, 0xf1, 0x49, 0x61, 0x11, 0x37, 0x33, + 0xb1, 0xbb, 0x55, 0x53, 0x25, 0xc0, 0x9d, 0x8e, 0xc9, 0x18, 0x9f, 0xca +}; +/* K = 8327daa2fbd001858dea53d2dc0cb005e0ae5fb15bebc0c5efd33371637ef318 */ +static const uint8_t ac_dsa_vect268_out[] = { +/* R */ + 0x4e, 0x35, 0xf5, 0x86, 0xfa, 0xd4, 0xf5, 0x12, 0x86, 0x3c, 0x48, 0x5e, + 0xc6, 0x1e, 0xd0, 0x16, 0x29, 0xaa, 0x13, 0x99, 0xb1, 0x6f, 0xef, 0x4d, + 0x80, 0xcb, 0x33, 0x27, 0x52, 0xb1, 0xda, 0x92, +/* S */ + 0x26, 0x2d, 0xfe, 0x6a, 0xc7, 0x2a, 0x2f, 0x60, 0x44, 0xf6, 0x26, 0x98, + 0xe4, 0x2d, 0xd2, 0xf9, 0x2b, 0x1f, 0x9a, 0x91, 0xbe, 0x42, 0xb5, 0xfd, + 0xd2, 0x93, 0xb1, 0xbf, 0x9a, 0x14, 0x5f, 0x00 +}; +#define ac_dsa_vect269_prime ac_dsa_vect256_prime +#define ac_dsa_vect269_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect269_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect269_ptx[] = { +/* Msg */ + 0xed, 0x88, 0xd7, 0x07, 0x6c, 0x5f, 0x6a, 0x5e, 0x0f, 0x94, 0x75, 0x43, + 0xd5, 0xfe, 0x74, 0x6a, 0xfc, 0xa9, 0xb2, 0xc4, 0xd0, 0x66, 0x55, 0xda, + 0x46, 0x07, 0x68, 0x5c, 0x79, 0x9c, 0x21, 0x0b, 0xe4, 0xaa, 0xee, 0x0e, + 0x6e, 0xd1, 0x97, 0x13, 0x81, 0x41, 0x82, 0xc7, 0xf7, 0xd5, 0x84, 0xdd, + 0xbe, 0xd4, 0x88, 0xc8, 0xe3, 0x23, 0x9d, 0xdd, 0x81, 0x05, 0x55, 0xad, + 0x63, 0x16, 0xd1, 0xdb, 0x37, 0xfd, 0x95, 0x53, 0xad, 0x74, 0xe3, 0xce, + 0xef, 0x9e, 0xee, 0xfa, 0xf5, 0x45, 0x63, 0x60, 0x2f, 0x55, 0x47, 0xaa, + 0xd4, 0x16, 0x1e, 0x93, 0x84, 0xed, 0xab, 0x65, 0x5a, 0x89, 0x84, 0x16, + 0xdb, 0x53, 0xf7, 0x12, 0x37, 0xac, 0x5a, 0x14, 0x85, 0x71, 0x11, 0x82, + 0xbc, 0x5b, 0xff, 0xf7, 0x24, 0x60, 0x25, 0x27, 0x84, 0xab, 0x1b, 0xba, + 0x23, 0x63, 0x4a, 0x36, 0xbe, 0x77, 0x53, 0x3f +}; +static const uint8_t ac_dsa_vect269_priv_val[] = { +/* X */ + 0x22, 0xb4, 0x4b, 0xd6, 0xd2, 0x3e, 0xe6, 0x5e, 0xbc, 0x2e, 0x88, 0x03, + 0x0f, 0x83, 0x7e, 0xf6, 0x55, 0x93, 0xee, 0xef, 0x09, 0x66, 0x23, 0x9a, + 0x92, 0xd5, 0x12, 0x6c, 0xde, 0x86, 0x7a, 0x13 +}; +static const uint8_t ac_dsa_vect269_pub_val[] = { +/* Y */ + 0x3e, 0x1c, 0xe8, 0x78, 0x0f, 0x39, 0x44, 0x4c, 0x21, 0x30, 0xdb, 0xf9, + 0xd8, 0x0c, 0xa4, 0xb2, 0x58, 0x17, 0xdc, 0x16, 0xd0, 0x8e, 0x2c, 0xda, + 0xca, 0x0b, 0x56, 0xcd, 0x2a, 0xbd, 0xb9, 0xef, 0x5a, 0xdb, 0x74, 0x1c, + 0xcc, 0x1a, 0xbe, 0xcf, 0x62, 0x80, 0x6a, 0xd7, 0xe8, 0x76, 0x36, 0xf5, + 0x28, 0x31, 0xc6, 0xde, 0xa4, 0x8e, 0x07, 0x29, 0xb9, 0x04, 0xe5, 0xa0, + 0x61, 0x5d, 0x7a, 0xb4, 0x45, 0x01, 0x04, 0x20, 0x8a, 0x5d, 0xdf, 0xdb, + 0x2f, 0x25, 0x69, 0x14, 0x6e, 0xe8, 0x3a, 0xc9, 0xaa, 0x27, 0xb4, 0xd0, + 0x66, 0x35, 0x5f, 0xc5, 0x3d, 0xc1, 0xa3, 0x68, 0x32, 0x11, 0xad, 0x3e, + 0xfa, 0xd1, 0xae, 0x69, 0xb8, 0xa7, 0x73, 0x7b, 0xbd, 0x89, 0xf5, 0xff, + 0x48, 0x48, 0x2e, 0x2c, 0x56, 0xed, 0xaa, 0x77, 0x6e, 0x43, 0xb2, 0xa0, + 0xba, 0x62, 0xe5, 0x13, 0x86, 0x2d, 0xa2, 0x90, 0x28, 0x8f, 0x07, 0xf8, + 0x4c, 0xa5, 0xa0, 0x68, 0x37, 0xd1, 0x9e, 0x9b, 0x18, 0x6d, 0xc8, 0xd3, + 0x69, 0x52, 0x96, 0x6e, 0x08, 0xf7, 0x21, 0x33, 0x40, 0x18, 0x6d, 0x31, + 0xfd, 0x41, 0xa2, 0xd1, 0x45, 0x5a, 0x08, 0x3a, 0xee, 0x62, 0x12, 0x7a, + 0x28, 0xdf, 0xe4, 0xda, 0x6c, 0x87, 0x6a, 0x5a, 0x6f, 0x36, 0xc4, 0x52, + 0x45, 0xde, 0xe6, 0xf6, 0x56, 0x6b, 0x83, 0x18, 0xd3, 0xd0, 0x19, 0x43, + 0xb2, 0xad, 0xf8, 0xce, 0x94, 0xea, 0x01, 0xa0, 0x1b, 0xa4, 0x1a, 0x6e, + 0x28, 0x68, 0x20, 0xa9, 0x67, 0x07, 0xcb, 0xd4, 0x00, 0x28, 0x75, 0xb7, + 0x9d, 0x9f, 0xe2, 0xdb, 0x6c, 0xc3, 0xf8, 0x08, 0xef, 0x0f, 0x71, 0x38, + 0x0e, 0xa9, 0xa7, 0x3f, 0xc7, 0xe3, 0x68, 0x50, 0xd0, 0x22, 0xff, 0xac, + 0x13, 0x16, 0x36, 0x36, 0x78, 0x86, 0xa6, 0xe9, 0x96, 0x57, 0x59, 0xd7, + 0x3f, 0x03, 0xac, 0xe6, 0x97, 0x04, 0xb5, 0x21, 0x44, 0xf6, 0x7b, 0x67, + 0x8e, 0x2f, 0xa2, 0x01, 0xc1, 0x9b, 0xb3, 0x7b, 0x00, 0x37, 0x7d, 0xaa, + 0xbc, 0x93, 0x77, 0xad, 0xcb, 0xdd, 0xea, 0x28, 0x16, 0xcb, 0xb5, 0x0b, + 0x26, 0xad, 0x2e, 0x42, 0x9e, 0xa0, 0x57, 0x6e, 0x77, 0x21, 0xb3, 0xb7, + 0x5c, 0x4f, 0xed, 0xb3, 0x1f, 0xdf, 0x1f, 0x0c, 0x6c, 0x2e, 0xaa, 0x13, + 0x5f, 0x52, 0xc9, 0xa9, 0x7f, 0x0d, 0xf5, 0xfb, 0x25, 0xef, 0x28, 0x84, + 0x8b, 0xdd, 0x73, 0x90, 0xcd, 0x05, 0x40, 0x03, 0x72, 0x25, 0x82, 0xd9, + 0x4e, 0x90, 0xa3, 0xbb, 0xe8, 0x5b, 0xeb, 0x34, 0x70, 0x12, 0x71, 0xb4, + 0xbb, 0x48, 0xbd, 0xf9, 0xb3, 0xd0, 0xe1, 0xbb, 0x56, 0x23, 0x44, 0x5c, + 0x78, 0x28, 0xc9, 0x37, 0xa4, 0x23, 0xbe, 0x51, 0x2c, 0x11, 0x77, 0xc9, + 0xc0, 0xb5, 0xb0, 0xb6, 0xb0, 0xe1, 0xf6, 0x39, 0xd3, 0x30, 0xe0, 0x51 +}; +/* K = 0c37eecd48682f897accf43b3e4a538cccdfd784625a6cc046dc54b093d16162 */ +static const uint8_t ac_dsa_vect269_out[] = { +/* R */ + 0x2e, 0x7c, 0xb4, 0x04, 0xa6, 0xda, 0xaa, 0x8e, 0x00, 0x76, 0x0d, 0xaf, + 0xc9, 0x5b, 0x4e, 0xb5, 0x54, 0x56, 0x83, 0x22, 0x4a, 0x61, 0xa1, 0xbc, + 0xd6, 0x12, 0x8b, 0xc4, 0xe7, 0xac, 0x53, 0x5e, +/* S */ + 0x3a, 0x70, 0xb3, 0xa9, 0x7e, 0x06, 0xe6, 0x3b, 0x89, 0xd5, 0x6e, 0xd5, + 0x23, 0x23, 0x46, 0x46, 0x1c, 0x1a, 0x3b, 0x6b, 0x14, 0x5d, 0x89, 0x04, + 0x3a, 0x48, 0xd6, 0x66, 0xde, 0x02, 0x56, 0xd5 +}; +#define ac_dsa_vect270_prime ac_dsa_vect256_prime +#define ac_dsa_vect270_sub_prime ac_dsa_vect256_sub_prime +#define ac_dsa_vect270_base ac_dsa_vect256_base +static const uint8_t ac_dsa_vect270_ptx[] = { +/* Msg */ + 0x9e, 0x44, 0x00, 0x52, 0xed, 0x92, 0x73, 0x21, 0x94, 0x83, 0x88, 0x77, + 0x6d, 0x37, 0x19, 0xbe, 0x06, 0x87, 0x39, 0xdc, 0x2d, 0x6c, 0x64, 0xc5, + 0x93, 0x71, 0x76, 0xb2, 0x00, 0x5c, 0x2d, 0x70, 0xa9, 0x38, 0x9e, 0x6a, + 0x65, 0x56, 0x63, 0x36, 0x6c, 0x09, 0x70, 0xa8, 0xe2, 0xe3, 0x11, 0x7e, + 0xce, 0xf2, 0x57, 0xe9, 0x51, 0xac, 0x81, 0xc0, 0x73, 0x1d, 0xfc, 0xd4, + 0xfb, 0xdb, 0x12, 0x41, 0xbc, 0x24, 0x9a, 0xdd, 0xe9, 0xcb, 0x39, 0x8c, + 0x7d, 0x15, 0xe3, 0x81, 0x36, 0x8a, 0xd3, 0xd2, 0x4e, 0xde, 0xe2, 0x33, + 0x97, 0xc1, 0x5a, 0x5a, 0x35, 0x6e, 0x78, 0x7d, 0x8f, 0x2f, 0xe9, 0xbe, + 0x76, 0x26, 0x0b, 0xd3, 0x63, 0xe1, 0x70, 0x06, 0x28, 0x1c, 0x19, 0x9f, + 0xe5, 0xb7, 0x10, 0xf9, 0xdf, 0xca, 0xc5, 0x28, 0x95, 0xe3, 0x92, 0xf7, + 0x38, 0x4d, 0x71, 0xbb, 0x83, 0x05, 0x3f, 0xfc +}; +static const uint8_t ac_dsa_vect270_priv_val[] = { +/* X */ + 0x68, 0x08, 0x83, 0xca, 0xf2, 0x36, 0x65, 0xe8, 0x13, 0x57, 0x2c, 0x1e, + 0x42, 0x30, 0x21, 0x8e, 0xdf, 0x53, 0xb3, 0xa5, 0x16, 0x7f, 0x56, 0xa7, + 0xd8, 0x0e, 0x53, 0xe7, 0xd3, 0xad, 0x1d, 0xf9 +}; +static const uint8_t ac_dsa_vect270_pub_val[] = { +/* Y */ + 0x89, 0xe8, 0x59, 0xfc, 0x63, 0xa2, 0x63, 0xbc, 0xc0, 0x51, 0xbc, 0x2e, + 0xf5, 0x8c, 0xc9, 0x19, 0xee, 0x53, 0x73, 0x85, 0xcb, 0x36, 0x36, 0xd8, + 0x3a, 0x62, 0x4a, 0x42, 0x30, 0xd4, 0xb0, 0x02, 0x4e, 0xc5, 0xe2, 0x8b, + 0xcb, 0x88, 0x46, 0x67, 0xcd, 0x2b, 0xf8, 0xc2, 0x84, 0x51, 0xb6, 0x4d, + 0xe0, 0x97, 0xf2, 0x19, 0x4c, 0xbb, 0x8c, 0x6e, 0x1c, 0xec, 0xbd, 0x6f, + 0x9f, 0xbd, 0x57, 0x64, 0x81, 0x55, 0x5d, 0x0f, 0x0e, 0x8f, 0x13, 0x75, + 0x2f, 0x24, 0x72, 0xf7, 0x61, 0x9d, 0x05, 0x23, 0x18, 0x42, 0x43, 0x10, + 0xf6, 0x9d, 0x50, 0xde, 0x78, 0xad, 0x6c, 0x45, 0x7b, 0x98, 0xc6, 0x11, + 0xf8, 0x48, 0x1d, 0x45, 0x43, 0x03, 0x1a, 0x73, 0xf8, 0x3d, 0x1e, 0x85, + 0x2c, 0x1f, 0x20, 0x38, 0xa6, 0x43, 0x5e, 0x57, 0x1f, 0x77, 0x6b, 0xbb, + 0x5c, 0xf9, 0x78, 0xa9, 0xb2, 0xc8, 0x8f, 0x05, 0xd1, 0x34, 0xfd, 0x5f, + 0xf4, 0x65, 0x6a, 0x69, 0xd6, 0xfe, 0x6b, 0x66, 0x7d, 0xa6, 0xda, 0x54, + 0xbe, 0x48, 0x38, 0x62, 0x50, 0x39, 0x4c, 0x75, 0xb4, 0x95, 0x68, 0x9f, + 0xd4, 0x62, 0x8f, 0x66, 0x64, 0x24, 0xeb, 0x08, 0x00, 0x94, 0x44, 0x8d, + 0x41, 0xb7, 0x06, 0x29, 0x2e, 0x51, 0xe7, 0x53, 0x86, 0x54, 0x3e, 0x5f, + 0xcc, 0xe6, 0xa6, 0xf3, 0xaa, 0xc0, 0x3a, 0x7d, 0x6d, 0x5c, 0x25, 0x51, + 0xca, 0x6b, 0x5b, 0x85, 0xfa, 0xdc, 0x86, 0xbf, 0xf1, 0x4c, 0x79, 0xa1, + 0x60, 0x2f, 0xb0, 0xc1, 0xd4, 0x3d, 0x88, 0xd5, 0x67, 0x90, 0x21, 0xe8, + 0x26, 0x06, 0x2e, 0xcf, 0x18, 0x6a, 0xaa, 0xae, 0xfc, 0x31, 0x2e, 0xab, + 0x9f, 0x9e, 0x2d, 0xa1, 0x20, 0xa8, 0xd7, 0xd0, 0x8b, 0xa0, 0x9a, 0xa9, + 0xab, 0xf4, 0xe3, 0x4f, 0x6d, 0x88, 0xc4, 0xc3, 0x14, 0xc5, 0x9c, 0x36, + 0xba, 0x57, 0xf9, 0x28, 0xd8, 0x8d, 0x5d, 0x70, 0xfe, 0x48, 0xac, 0x67, + 0x00, 0xf5, 0xcf, 0x60, 0x7a, 0x55, 0xe3, 0x64, 0x6d, 0xd0, 0x3d, 0x47, + 0xe9, 0x6a, 0xd8, 0x69, 0xf7, 0xba, 0x2b, 0xcc, 0x7d, 0x65, 0xa9, 0x9c, + 0x32, 0x21, 0xd4, 0x90, 0x9d, 0x1f, 0x22, 0xe4, 0xcc, 0xba, 0x81, 0x5f, + 0xa5, 0xb7, 0x20, 0x57, 0x0e, 0x42, 0xf8, 0x62, 0x6c, 0x31, 0xd9, 0x9f, + 0x60, 0xcd, 0x6a, 0x01, 0x53, 0x91, 0xfa, 0xb3, 0x53, 0x74, 0x46, 0xf7, + 0x47, 0xc0, 0x11, 0x12, 0x93, 0xc5, 0xbd, 0x6b, 0x5d, 0xab, 0x2b, 0xc3, + 0xd5, 0x13, 0x7d, 0x21, 0x24, 0x02, 0x9e, 0xed, 0x12, 0xdb, 0x71, 0xbd, + 0xf7, 0x94, 0xde, 0x1a, 0x2e, 0xc5, 0x07, 0x0d, 0x83, 0xf8, 0x71, 0x95, + 0x26, 0x4f, 0xf0, 0x9c, 0xb4, 0x8c, 0xdd, 0xb5, 0xe8, 0x52, 0xb2, 0x33, + 0x57, 0x0f, 0x1b, 0x70, 0xcd, 0x45, 0x7c, 0xf8, 0x64, 0xe2, 0xef, 0x3b +}; +/* K = 69e6cb5bcf8cae88c96e464a9b26c6e1bbac1e229909e27542278a50c66959f1 */ +static const uint8_t ac_dsa_vect270_out[] = { +/* R */ + 0x37, 0xc3, 0x4f, 0x9c, 0xce, 0x91, 0x6d, 0xf3, 0xde, 0xff, 0x26, 0xbe, + 0x08, 0xa4, 0xe6, 0xbb, 0xae, 0x06, 0x61, 0xfb, 0xbb, 0x5d, 0x81, 0xd6, + 0x03, 0x9f, 0x00, 0xb1, 0xe5, 0x63, 0x2b, 0x67, +/* S */ + 0x3f, 0x4a, 0x29, 0x32, 0x91, 0x7e, 0x6b, 0xb0, 0x88, 0x59, 0x9a, 0x26, + 0x9d, 0x7b, 0x59, 0x07, 0x69, 0xac, 0xf9, 0x80, 0x7d, 0xc5, 0xa9, 0x42, + 0x0a, 0x95, 0xe1, 0x2c, 0x73, 0x64, 0xc5, 0xfa +}; +/* [mod = L=3072, N=256, SHA-384] */ +static const uint8_t ac_dsa_vect271_prime[] = { +/* P */ + 0xa4, 0x10, 0xd2, 0x3e, 0xd9, 0xad, 0x99, 0x64, 0xd3, 0xe4, 0x01, 0xcb, + 0x93, 0x17, 0xa2, 0x52, 0x13, 0xf7, 0x57, 0x12, 0xac, 0xbc, 0x5c, 0x12, + 0x19, 0x1a, 0xbf, 0x3f, 0x1c, 0x0e, 0x72, 0x3e, 0x23, 0x33, 0xb4, 0x9e, + 0xb1, 0xf9, 0x5b, 0x0f, 0x97, 0x48, 0xd9, 0x52, 0xf0, 0x4a, 0x5a, 0xe3, + 0x58, 0x85, 0x9d, 0x38, 0x44, 0x03, 0xce, 0x36, 0x4a, 0xa3, 0xf5, 0x8d, + 0xd9, 0x76, 0x99, 0x09, 0xb4, 0x50, 0x48, 0x54, 0x8c, 0x55, 0x87, 0x2a, + 0x6a, 0xfb, 0xb3, 0xb1, 0x5c, 0x54, 0x88, 0x2f, 0x96, 0xc2, 0x0d, 0xf1, + 0xb2, 0xdf, 0x16, 0x4f, 0x0b, 0xac, 0x84, 0x9c, 0xa1, 0x7a, 0xd2, 0xdf, + 0x63, 0xab, 0xd7, 0x5c, 0x88, 0x19, 0x22, 0xe7, 0x9a, 0x50, 0x09, 0xf0, + 0x0b, 0x7d, 0x63, 0x16, 0x22, 0xe9, 0x0e, 0x7f, 0xa4, 0xe9, 0x80, 0x61, + 0x85, 0x75, 0xe1, 0xd6, 0xbd, 0x1a, 0x72, 0xd5, 0xb6, 0xa5, 0x0f, 0x4f, + 0x6a, 0x68, 0xb7, 0x93, 0x93, 0x7c, 0x4a, 0xf9, 0x5f, 0xc1, 0x15, 0x41, + 0x75, 0x9a, 0x17, 0x36, 0x57, 0x7d, 0x94, 0x48, 0xb8, 0x77, 0x92, 0xdf, + 0xf0, 0x72, 0x32, 0x41, 0x55, 0x12, 0xe9, 0x33, 0x75, 0x5e, 0x12, 0x25, + 0x0d, 0x46, 0x6e, 0x9c, 0xc8, 0xdf, 0x15, 0x07, 0x27, 0xd7, 0x47, 0xe5, + 0x1f, 0xea, 0x79, 0x64, 0x15, 0x83, 0x26, 0xb1, 0x36, 0x5d, 0x58, 0x0c, + 0xb1, 0x90, 0xf4, 0x51, 0x82, 0x91, 0x59, 0x82, 0x21, 0xfd, 0xf3, 0x6c, + 0x63, 0x05, 0xc8, 0xb8, 0xa8, 0xed, 0x05, 0x66, 0x3d, 0xd7, 0xb0, 0x06, + 0xe9, 0x45, 0xf5, 0x92, 0xab, 0xbe, 0xca, 0xe4, 0x60, 0xf7, 0x7c, 0x71, + 0xb6, 0xec, 0x64, 0x9d, 0x3f, 0xd5, 0x39, 0x42, 0x02, 0xed, 0x7b, 0xbb, + 0xd0, 0x40, 0xf7, 0xb8, 0xfd, 0x57, 0xcb, 0x06, 0xa9, 0x9b, 0xe2, 0x54, + 0xfa, 0x25, 0xd7, 0x1a, 0x37, 0x60, 0x73, 0x40, 0x46, 0xc2, 0xa0, 0xdb, + 0x38, 0x3e, 0x02, 0x39, 0x79, 0x13, 0xae, 0x67, 0xce, 0x65, 0x87, 0x0d, + 0x9f, 0x6c, 0x6f, 0x67, 0xa9, 0xd0, 0x04, 0x97, 0xbe, 0x1d, 0x76, 0x3b, + 0x21, 0x93, 0x7c, 0xf9, 0xcb, 0xf9, 0xa2, 0x4e, 0xf9, 0x7b, 0xbc, 0xaa, + 0x07, 0x91, 0x6f, 0x88, 0x94, 0xe5, 0xb7, 0xfb, 0x03, 0x25, 0x88, 0x21, + 0xac, 0x46, 0x14, 0x09, 0x65, 0xb2, 0x3c, 0x54, 0x09, 0xca, 0x49, 0x02, + 0x6e, 0xfb, 0x2b, 0xf9, 0x5b, 0xce, 0x02, 0x5c, 0x41, 0x83, 0xa5, 0xf6, + 0x59, 0xbf, 0x6a, 0xae, 0xef, 0x56, 0xd7, 0x93, 0x3b, 0xb2, 0x96, 0x97, + 0xd7, 0xd5, 0x41, 0x34, 0x8c, 0x87, 0x1f, 0xa0, 0x1f, 0x86, 0x96, 0x78, + 0xb2, 0xe3, 0x45, 0x06, 0xf6, 0xdc, 0x0a, 0x4c, 0x13, 0x2b, 0x68, 0x9a, + 0x0e, 0xd2, 0x7d, 0xc3, 0xc8, 0xd5, 0x37, 0x02, 0xaa, 0x58, 0x48, 0x77 +}; +static const uint8_t ac_dsa_vect271_sub_prime[] = { +/* Q */ + 0xab, 0xc6, 0x74, 0x17, 0x72, 0x5c, 0xf2, 0x8f, 0xc7, 0x64, 0x0d, 0x5d, + 0xe4, 0x38, 0x25, 0xf4, 0x16, 0xeb, 0xfa, 0x80, 0xe1, 0x91, 0xc4, 0x2e, + 0xe8, 0x86, 0x30, 0x33, 0x38, 0xf5, 0x60, 0x45 +}; +static const uint8_t ac_dsa_vect271_base[] = { +/* G */ + 0x86, 0x7d, 0x5f, 0xb7, 0x2f, 0x59, 0x36, 0xd1, 0xa1, 0x4e, 0xd3, 0xb6, + 0x04, 0x99, 0x66, 0x2f, 0x31, 0x24, 0x68, 0x6e, 0xf1, 0x08, 0xc5, 0xb3, + 0xda, 0x66, 0x63, 0xa0, 0xe8, 0x61, 0x97, 0xec, 0x2c, 0xc4, 0xc9, 0x46, + 0x01, 0x93, 0xa7, 0x4f, 0xf1, 0x60, 0x28, 0xac, 0x94, 0x41, 0xb0, 0xc7, + 0xd2, 0x7c, 0x22, 0x72, 0xd4, 0x83, 0xac, 0x7c, 0xd7, 0x94, 0xd5, 0x98, + 0x41, 0x6c, 0x4f, 0xf9, 0x09, 0x9a, 0x61, 0x67, 0x9d, 0x41, 0x7d, 0x47, + 0x8c, 0xe5, 0xdd, 0x97, 0x4b, 0xf3, 0x49, 0xa1, 0x45, 0x75, 0xaf, 0xe7, + 0x4a, 0x88, 0xb1, 0x2d, 0xd5, 0xf6, 0xd1, 0xcb, 0xd3, 0xf9, 0x1d, 0xdd, + 0x59, 0x7e, 0xd6, 0x8e, 0x79, 0xeb, 0xa4, 0x02, 0x61, 0x31, 0x30, 0xc2, + 0x24, 0xb9, 0x4a, 0xc2, 0x87, 0x14, 0xa1, 0xf1, 0xc5, 0x52, 0x47, 0x5a, + 0x5d, 0x29, 0xcf, 0xcd, 0xd8, 0xe0, 0x8a, 0x6b, 0x1d, 0x65, 0x66, 0x1e, + 0x28, 0xef, 0x31, 0x35, 0x14, 0xd1, 0x40, 0x8f, 0x5a, 0xbd, 0x3e, 0x06, + 0xeb, 0xe3, 0xa7, 0xd8, 0x14, 0xd1, 0xed, 0xe3, 0x16, 0xbf, 0x49, 0x52, + 0x73, 0xca, 0x1d, 0x57, 0x4f, 0x42, 0xb4, 0x82, 0xee, 0xa3, 0x0d, 0xb5, + 0x34, 0x66, 0xf4, 0x54, 0xb5, 0x1a, 0x17, 0x5a, 0x0b, 0x89, 0xb3, 0xc0, + 0x5d, 0xda, 0x00, 0x6e, 0x71, 0x9a, 0x2e, 0x63, 0x71, 0x66, 0x90, 0x80, + 0xd7, 0x68, 0xcc, 0x03, 0x8c, 0xdf, 0xb8, 0x09, 0x8e, 0x9a, 0xad, 0x9b, + 0x8d, 0x83, 0xd4, 0xb7, 0x59, 0xf4, 0x3a, 0xc9, 0xd2, 0x2b, 0x35, 0x3e, + 0xd8, 0x8a, 0x33, 0x72, 0x35, 0x50, 0x15, 0x0d, 0xe0, 0x36, 0x1b, 0x7a, + 0x37, 0x6f, 0x37, 0xb4, 0x5d, 0x43, 0x7f, 0x71, 0xcb, 0x71, 0x1f, 0x28, + 0x47, 0xde, 0x67, 0x1a, 0xd1, 0x05, 0x95, 0x16, 0xa1, 0xd4, 0x57, 0x55, + 0x22, 0x4a, 0x15, 0xd3, 0x7b, 0x4a, 0xea, 0xda, 0x3f, 0x58, 0xc6, 0x9a, + 0x13, 0x6d, 0xae, 0xf0, 0x63, 0x6f, 0xe3, 0x8e, 0x37, 0x52, 0x06, 0x4a, + 0xfe, 0x59, 0x84, 0x33, 0xe8, 0x00, 0x89, 0xfd, 0xa2, 0x4b, 0x14, 0x4a, + 0x46, 0x27, 0x34, 0xbe, 0xf8, 0xf7, 0x76, 0x38, 0x84, 0x5b, 0x00, 0xe5, + 0x9c, 0xe7, 0xfa, 0x4f, 0x1d, 0xaf, 0x48, 0x7a, 0x2c, 0xad, 0xa1, 0x1e, + 0xab, 0xa7, 0x2b, 0xb2, 0x3e, 0x1d, 0xf6, 0xb6, 0x6a, 0x18, 0x3e, 0xdd, + 0x22, 0x6c, 0x44, 0x02, 0x72, 0xdd, 0x9b, 0x06, 0xbe, 0xc0, 0xe5, 0x7f, + 0x1a, 0x08, 0x22, 0xd2, 0xe0, 0x02, 0x12, 0x06, 0x4b, 0x6d, 0xba, 0x64, + 0x56, 0x20, 0x85, 0xf5, 0xa7, 0x59, 0x29, 0xaf, 0xa5, 0xfe, 0x50, 0x9e, + 0x0b, 0x78, 0xe6, 0x30, 0xaa, 0xf1, 0x2f, 0x91, 0xe4, 0x98, 0x0c, 0x9b, + 0x0d, 0x6f, 0x7e, 0x05, 0x9a, 0x2e, 0xa3, 0xe2, 0x34, 0x79, 0xd9, 0x30 +}; +static const uint8_t ac_dsa_vect271_ptx[] = { +/* Msg */ + 0xed, 0x9a, 0x64, 0xd3, 0x10, 0x9e, 0xf8, 0xa9, 0x29, 0x29, 0x56, 0xb9, + 0x46, 0x87, 0x3c, 0xa4, 0xbd, 0x88, 0x7c, 0xe6, 0x24, 0xb8, 0x1b, 0xe8, + 0x1b, 0x82, 0xc6, 0x9c, 0x67, 0xaa, 0xdd, 0xf5, 0x65, 0x5f, 0x70, 0xfe, + 0x47, 0x68, 0x11, 0x4d, 0xb2, 0x83, 0x4c, 0x71, 0x78, 0x7f, 0x85, 0x8e, + 0x51, 0x65, 0xda, 0x1a, 0x7f, 0xa9, 0x61, 0xd8, 0x55, 0xad, 0x7e, 0x5b, + 0xc4, 0xb7, 0xbe, 0x31, 0xb9, 0x7d, 0xbe, 0x77, 0x07, 0x98, 0xef, 0x79, + 0x66, 0x15, 0x2b, 0x14, 0xb8, 0x6a, 0xe3, 0x56, 0x25, 0xa2, 0x8a, 0xee, + 0x56, 0x63, 0xb9, 0xef, 0x30, 0x67, 0xcb, 0xdf, 0xba, 0xbd, 0x87, 0x19, + 0x7e, 0x5c, 0x84, 0x2d, 0x30, 0x92, 0xeb, 0x88, 0xdc, 0xa5, 0x7c, 0x6c, + 0x8a, 0xd4, 0xc0, 0x0a, 0x19, 0xdd, 0xf2, 0xe1, 0x96, 0x7b, 0x59, 0xbd, + 0x06, 0xcc, 0xae, 0xf9, 0x33, 0xbc, 0x28, 0xe7 +}; +static const uint8_t ac_dsa_vect271_priv_val[] = { +/* X */ + 0x6d, 0x4c, 0x93, 0x43, 0x91, 0xb7, 0xf6, 0xfb, 0x6e, 0x19, 0xe3, 0x14, + 0x1f, 0x8c, 0x00, 0x18, 0xef, 0x57, 0x26, 0x11, 0x8a, 0x11, 0x06, 0x43, + 0x58, 0xc7, 0xd3, 0x5b, 0x37, 0x73, 0x73, 0x77 +}; +static const uint8_t ac_dsa_vect271_pub_val[] = { +/* Y */ + 0x1f, 0x0a, 0x5c, 0x75, 0xe7, 0x98, 0x5d, 0x6e, 0x70, 0xe4, 0xfb, 0xfd, + 0xa5, 0x1a, 0x10, 0xb9, 0x25, 0xf6, 0xac, 0xcb, 0x60, 0x0d, 0x7c, 0x65, + 0x10, 0xdb, 0x90, 0xec, 0x36, 0x7b, 0x93, 0xbb, 0x06, 0x9b, 0xd2, 0x86, + 0xe8, 0xf9, 0x79, 0xb2, 0x2e, 0xf0, 0x70, 0x2f, 0x71, 0x7a, 0x87, 0x55, + 0xc1, 0x83, 0x09, 0xc8, 0x7d, 0xae, 0x3f, 0xe8, 0x2c, 0xc3, 0xdc, 0x8f, + 0x4b, 0x7a, 0xa3, 0xd5, 0xf3, 0x87, 0x6f, 0x4d, 0x4b, 0x3e, 0xb6, 0x8b, + 0xfe, 0x91, 0x0c, 0x43, 0x07, 0x6d, 0x6c, 0xd0, 0xd3, 0x9f, 0xc8, 0x8d, + 0xde, 0x78, 0xf0, 0x94, 0x80, 0xdb, 0x55, 0x23, 0x4e, 0x6c, 0x8c, 0xa5, + 0x9f, 0xe2, 0x70, 0x0e, 0xfe, 0xc0, 0x4f, 0xee, 0xe6, 0xb4, 0xe8, 0xee, + 0x24, 0x13, 0x72, 0x18, 0x58, 0xbe, 0x71, 0x90, 0xdb, 0xe9, 0x05, 0xf4, + 0x56, 0xed, 0xca, 0xb5, 0x5b, 0x2d, 0xc2, 0x91, 0x6d, 0xc1, 0xe8, 0x73, + 0x19, 0x88, 0xd9, 0xef, 0x8b, 0x61, 0x9a, 0xbc, 0xf8, 0x95, 0x5a, 0xa9, + 0x60, 0xef, 0x02, 0xb3, 0xf0, 0x2a, 0x8d, 0xc6, 0x49, 0x36, 0x92, 0x22, + 0xaf, 0x50, 0xf1, 0x33, 0x8e, 0xd2, 0x8d, 0x66, 0x7f, 0x3f, 0x10, 0xca, + 0xe2, 0xa3, 0xc2, 0x8a, 0x3c, 0x1d, 0x08, 0xdf, 0x63, 0x9c, 0x81, 0xad, + 0xa1, 0x3c, 0x8f, 0xd1, 0x98, 0xc6, 0xda, 0xe3, 0xd6, 0x2a, 0x3f, 0xe9, + 0xf0, 0x4c, 0x98, 0x5c, 0x65, 0xf6, 0x10, 0xc0, 0x6c, 0xb8, 0xfa, 0xea, + 0x68, 0xed, 0xb8, 0x0d, 0xe6, 0xcf, 0x07, 0xa8, 0xe8, 0x9c, 0x00, 0x21, + 0x81, 0x85, 0xa9, 0x52, 0xb2, 0x35, 0x72, 0xe3, 0x4d, 0xf0, 0x7c, 0xe5, + 0xb4, 0x26, 0x1e, 0x5d, 0xe4, 0x27, 0xeb, 0x50, 0x3e, 0xe1, 0xba, 0xf5, + 0x99, 0x2d, 0xb6, 0xd4, 0x38, 0xb4, 0x74, 0x34, 0xc4, 0x0c, 0x22, 0x65, + 0x7b, 0xc1, 0x63, 0xe7, 0x95, 0x3f, 0xa3, 0x3e, 0xff, 0x39, 0xdc, 0x27, + 0x34, 0x60, 0x70, 0x39, 0xaa, 0xdd, 0x6a, 0xc2, 0x7e, 0x43, 0x67, 0x13, + 0x10, 0x41, 0xf8, 0x45, 0xff, 0xa1, 0xa1, 0x3f, 0x55, 0x6b, 0xfb, 0xa2, + 0x30, 0x7a, 0x5c, 0x78, 0xf2, 0xcc, 0xf1, 0x12, 0x98, 0xc7, 0x62, 0xe0, + 0x88, 0x71, 0x96, 0x8e, 0x48, 0xdc, 0x3d, 0x15, 0x69, 0xd0, 0x99, 0x65, + 0xcd, 0x09, 0xda, 0x43, 0xcf, 0x03, 0x09, 0xa1, 0x6a, 0xf1, 0xe2, 0x0f, + 0xee, 0x7d, 0xa3, 0xdc, 0x21, 0xb3, 0x64, 0xc4, 0x61, 0x5c, 0xd5, 0x12, + 0x3f, 0xa5, 0xf9, 0xb2, 0x3c, 0xfc, 0x4f, 0xfd, 0x9c, 0xfd, 0xce, 0xa6, + 0x70, 0x62, 0x38, 0x40, 0xb0, 0x62, 0xd4, 0x64, 0x8d, 0x2e, 0xba, 0x78, + 0x6a, 0xd3, 0xf7, 0xae, 0x33, 0x7a, 0x42, 0x84, 0x32, 0x4a, 0xce, 0x23, + 0x6f, 0x9f, 0x71, 0x74, 0xfb, 0xf4, 0x42, 0xb9, 0x90, 0x43, 0x00, 0x2f +}; +/* K = 40b5cc685c3d1f59072228af9551683b5b8c8ff65240114ad2dacfccf3928057 */ +static const uint8_t ac_dsa_vect271_out[] = { +/* R */ + 0x76, 0x95, 0x69, 0x8a, 0x14, 0x75, 0x5d, 0xb4, 0x20, 0x6e, 0x85, 0x0b, + 0x4f, 0x5f, 0x19, 0xc5, 0x40, 0xb0, 0x7d, 0x07, 0xe0, 0x8a, 0xac, 0x59, + 0x1e, 0x20, 0x08, 0x16, 0x46, 0xe6, 0xee, 0xdc, +/* S */ + 0x3d, 0xae, 0x01, 0x15, 0x4e, 0xcf, 0xf7, 0xb1, 0x90, 0x07, 0xa9, 0x53, + 0xf1, 0x85, 0xf0, 0x66, 0x3e, 0xf7, 0xf2, 0x53, 0x7f, 0x0b, 0x15, 0xe0, + 0x4f, 0xb3, 0x43, 0xc9, 0x61, 0xf3, 0x6d, 0xe2 +}; +#define ac_dsa_vect272_prime ac_dsa_vect271_prime +#define ac_dsa_vect272_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect272_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect272_ptx[] = { +/* Msg */ + 0x4b, 0xfd, 0x28, 0xa0, 0xa7, 0x9c, 0x94, 0xdb, 0xd6, 0x67, 0xc2, 0x75, + 0xef, 0x77, 0xa2, 0x35, 0xd8, 0xea, 0xd7, 0xc6, 0x98, 0xd4, 0x2f, 0xb7, + 0xf7, 0xc1, 0xfd, 0x3c, 0x8c, 0x2d, 0xc4, 0x8d, 0x0d, 0xda, 0x24, 0x08, + 0xde, 0xa5, 0x63, 0x25, 0xd6, 0x92, 0x83, 0x69, 0x2a, 0x52, 0x3d, 0x28, + 0x1f, 0xfe, 0xa8, 0x56, 0xff, 0xd9, 0xf8, 0x41, 0x7e, 0xaf, 0xbe, 0xa6, + 0x06, 0xd8, 0x62, 0xdc, 0x58, 0x97, 0xbd, 0xf2, 0x41, 0xf3, 0xe8, 0xe4, + 0x9a, 0xde, 0xd5, 0xea, 0xdc, 0x72, 0x95, 0xe5, 0xaf, 0xbf, 0x96, 0xb3, + 0x97, 0x5d, 0x0e, 0x25, 0xda, 0xa2, 0x43, 0x36, 0x12, 0xe1, 0x20, 0xf6, + 0x59, 0x03, 0x6b, 0x80, 0x7c, 0x18, 0x53, 0xc0, 0x3c, 0x90, 0xfa, 0xde, + 0x2c, 0x19, 0xdc, 0xd9, 0x23, 0x49, 0x2e, 0xcc, 0x90, 0x6c, 0xaf, 0xc5, + 0x7a, 0x95, 0xda, 0x6f, 0x20, 0xdd, 0x59, 0xd6 +}; +static const uint8_t ac_dsa_vect272_priv_val[] = { +/* X */ + 0x95, 0xfd, 0xed, 0x7e, 0x5e, 0x94, 0x96, 0x02, 0xc1, 0x12, 0x3d, 0x80, + 0xf8, 0x95, 0x03, 0xcc, 0x5f, 0xb7, 0x45, 0x4b, 0xe3, 0x17, 0x3a, 0xf4, + 0x95, 0xa1, 0x87, 0x09, 0xc1, 0xc2, 0x50, 0x6e +}; +static const uint8_t ac_dsa_vect272_pub_val[] = { +/* Y */ + 0x6c, 0x77, 0x8b, 0xcb, 0x14, 0x65, 0x82, 0x27, 0x76, 0x33, 0x93, 0x1b, + 0xfd, 0x02, 0x9e, 0x69, 0xc9, 0xe8, 0xc0, 0xae, 0x9e, 0x24, 0x91, 0x3f, + 0xa7, 0x34, 0x55, 0x4f, 0x24, 0xf6, 0x4a, 0xa6, 0x4f, 0xd9, 0xbc, 0x60, + 0x8e, 0xf6, 0x77, 0xa1, 0xd4, 0x82, 0x9a, 0xa8, 0xa8, 0x56, 0x4c, 0x2f, + 0xf0, 0xff, 0xa2, 0xfa, 0x6a, 0x0c, 0x1a, 0x2c, 0xcb, 0x60, 0x6d, 0xda, + 0x01, 0x8b, 0xf0, 0x95, 0xf8, 0xc8, 0x97, 0xd7, 0xa4, 0x33, 0x49, 0xbe, + 0xb9, 0x80, 0x7b, 0x7b, 0x11, 0x8f, 0x8d, 0xe8, 0x85, 0x6b, 0x16, 0x4b, + 0x8d, 0x8b, 0xab, 0xdc, 0x17, 0xb4, 0x8f, 0x3a, 0x2b, 0x97, 0x2c, 0xe5, + 0x37, 0xab, 0x4e, 0x7a, 0x7d, 0x9b, 0xa5, 0xd7, 0xe6, 0xfa, 0x36, 0x98, + 0xac, 0xa9, 0x19, 0x73, 0xcd, 0x17, 0x87, 0xef, 0x7b, 0x6b, 0x4d, 0x04, + 0x10, 0xde, 0x59, 0xcd, 0x31, 0x43, 0xe0, 0xf3, 0xac, 0xfd, 0xaa, 0xbe, + 0x56, 0xb3, 0x71, 0xb4, 0x35, 0x4d, 0x0d, 0x32, 0xdb, 0xd1, 0xb5, 0xca, + 0x6a, 0x87, 0x20, 0x54, 0xf3, 0xe6, 0x56, 0x63, 0x19, 0xd5, 0xd5, 0x0b, + 0x2c, 0xf5, 0x4c, 0x12, 0x3f, 0xfc, 0x92, 0x90, 0x07, 0xad, 0x18, 0x57, + 0xba, 0x13, 0xb7, 0xc4, 0x03, 0xf5, 0x51, 0xc2, 0xfa, 0x41, 0x09, 0xc4, + 0x4e, 0x19, 0xef, 0x97, 0xaf, 0xb6, 0x2a, 0x61, 0x03, 0x35, 0x6f, 0xcc, + 0x2e, 0xf4, 0x51, 0xe7, 0x36, 0x26, 0x10, 0x10, 0xb0, 0xef, 0x58, 0xae, + 0x07, 0xa0, 0xc8, 0x01, 0xff, 0x75, 0xeb, 0xaf, 0x6c, 0xdd, 0x76, 0x3f, + 0x8d, 0xf2, 0xf8, 0x3f, 0x0e, 0xbb, 0xda, 0x40, 0x84, 0x5b, 0x2f, 0x42, + 0xd3, 0xfe, 0xea, 0xc0, 0x71, 0xfc, 0x62, 0x6e, 0xe5, 0xb5, 0x1f, 0x9b, + 0xc1, 0xa1, 0x30, 0x51, 0x4f, 0x22, 0x04, 0x97, 0x1b, 0x4b, 0x72, 0x61, + 0xb4, 0xbd, 0x78, 0x3f, 0xf7, 0x57, 0x75, 0xaa, 0x73, 0xa6, 0x3d, 0x7e, + 0xbe, 0x99, 0x0b, 0x93, 0x9b, 0x0f, 0x44, 0xa9, 0x09, 0xec, 0x39, 0x00, + 0x36, 0xf2, 0x97, 0xc3, 0x56, 0x3f, 0x64, 0xd1, 0x42, 0xc1, 0x4e, 0xa4, + 0x3c, 0x5d, 0x3c, 0x6d, 0xef, 0x4a, 0x3a, 0x9c, 0xcf, 0x62, 0x74, 0x18, + 0x2b, 0x93, 0x9b, 0x88, 0x65, 0x01, 0xae, 0xb4, 0xef, 0xb2, 0x3d, 0x00, + 0x73, 0x43, 0x4c, 0xec, 0x6a, 0x91, 0x5a, 0x67, 0xe2, 0x4c, 0xbb, 0x23, + 0x54, 0xc9, 0xbb, 0x10, 0x89, 0xaf, 0x48, 0x7e, 0xab, 0x5d, 0x8e, 0x49, + 0x9a, 0x63, 0x2e, 0x6c, 0x61, 0x49, 0x2e, 0xa1, 0x5d, 0x2c, 0x44, 0x4c, + 0x26, 0x9d, 0xe3, 0x32, 0x71, 0xa9, 0x00, 0x42, 0x46, 0x8d, 0xe2, 0x76, + 0x7f, 0x0d, 0xcf, 0x7a, 0x66, 0x42, 0x4a, 0x3a, 0x40, 0xa6, 0x3e, 0xeb, + 0xd1, 0x9c, 0xb8, 0x9c, 0x8d, 0x74, 0xc5, 0x85, 0x04, 0xc4, 0xe1, 0x03 +}; +/* K = 6bd1eede564ecb1b3fbbf2d96e334ab4cc002e6624e2cb8448d8608fe0e8c43b */ +static const uint8_t ac_dsa_vect272_out[] = { +/* R */ + 0x37, 0xc3, 0xf7, 0x55, 0x6d, 0x6e, 0x5a, 0xcf, 0x79, 0x89, 0xf0, 0xba, + 0xa7, 0x70, 0xc2, 0x45, 0x0d, 0xee, 0xbd, 0x4d, 0x5f, 0x58, 0xb6, 0x1e, + 0x17, 0xb4, 0xb2, 0xb9, 0x26, 0xb5, 0x80, 0x31, +/* S */ + 0xa6, 0x1d, 0x86, 0x36, 0x5f, 0x10, 0xca, 0x5e, 0x1e, 0xe2, 0xc4, 0xbf, + 0x27, 0x6f, 0x23, 0x74, 0xe8, 0x8b, 0x5a, 0x2d, 0x1a, 0xcd, 0x8e, 0xcc, + 0x11, 0xe9, 0x77, 0x85, 0xb4, 0xfd, 0x99, 0x31 +}; +#define ac_dsa_vect273_prime ac_dsa_vect271_prime +#define ac_dsa_vect273_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect273_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect273_ptx[] = { +/* Msg */ + 0xe3, 0xfc, 0x75, 0x1b, 0x69, 0x78, 0xfc, 0xf4, 0x0f, 0x09, 0x60, 0x6e, + 0xe4, 0x26, 0x3e, 0x16, 0x60, 0xff, 0x20, 0xe9, 0xc6, 0x3a, 0x71, 0x38, + 0xf0, 0x78, 0xae, 0x3e, 0x3e, 0x60, 0x3d, 0xfc, 0xad, 0x17, 0x2f, 0x3c, + 0x7c, 0xb3, 0xf3, 0x54, 0x5f, 0xc2, 0x3b, 0xc3, 0x0c, 0x37, 0xc8, 0x43, + 0x9c, 0x7b, 0x23, 0x83, 0x41, 0xf2, 0x91, 0x48, 0x27, 0x6e, 0xa2, 0x12, + 0x2e, 0xa8, 0xed, 0x0f, 0xea, 0xcb, 0x14, 0x9d, 0xe1, 0x7c, 0xfd, 0x33, + 0xb8, 0xc9, 0x40, 0x8a, 0xee, 0x8a, 0xb0, 0xea, 0x8b, 0xa4, 0xa2, 0xb2, + 0xea, 0x23, 0x74, 0x18, 0xbc, 0x31, 0x65, 0x36, 0x9c, 0x8c, 0xd4, 0x20, + 0x24, 0x2f, 0x8d, 0x32, 0xbc, 0xab, 0xe0, 0xc3, 0x52, 0xe2, 0x1f, 0x65, + 0xde, 0x80, 0xd5, 0x87, 0xba, 0x27, 0x13, 0xce, 0xa6, 0xe5, 0x3c, 0xa5, + 0x24, 0xae, 0xc3, 0x65, 0xbd, 0xf2, 0x1a, 0xdc +}; +static const uint8_t ac_dsa_vect273_priv_val[] = { +/* X */ + 0x3a, 0x09, 0x00, 0x6f, 0xae, 0xde, 0xc9, 0x14, 0x46, 0x99, 0x5a, 0x39, + 0x3b, 0x03, 0x4b, 0x0c, 0x7f, 0xf3, 0xfc, 0xd0, 0x5c, 0xda, 0x2e, 0x9e, + 0x3b, 0x2f, 0x98, 0xe3, 0xa4, 0xbb, 0xb9, 0xf5 +}; +static const uint8_t ac_dsa_vect273_pub_val[] = { +/* Y */ + 0x13, 0x49, 0xbb, 0xf1, 0x6d, 0x37, 0x5c, 0x39, 0x2a, 0x9a, 0xcd, 0x5b, + 0xdc, 0xe6, 0x55, 0xf1, 0x4d, 0x61, 0x62, 0x74, 0x38, 0x8a, 0x45, 0xcd, + 0x37, 0x29, 0x25, 0xc5, 0x07, 0xac, 0x12, 0x9f, 0xe6, 0x1b, 0x99, 0x8e, + 0x25, 0x12, 0x7f, 0x21, 0x09, 0x26, 0xad, 0x11, 0x91, 0x58, 0x3e, 0xee, + 0x8c, 0x41, 0x90, 0x02, 0x6b, 0xa0, 0xa9, 0x58, 0x94, 0xbe, 0x3f, 0x0a, + 0xd5, 0xd0, 0x58, 0x86, 0xc5, 0x9a, 0x3c, 0x7a, 0x00, 0x44, 0xf7, 0xe2, + 0xbd, 0x9b, 0xbe, 0x28, 0xbf, 0x93, 0x66, 0xd0, 0x34, 0xdb, 0x42, 0x4f, + 0x34, 0x96, 0x0e, 0x30, 0xa8, 0xe7, 0x88, 0x8f, 0x92, 0x7d, 0x0b, 0xf9, + 0x84, 0xb0, 0xff, 0x99, 0xea, 0x27, 0x18, 0x71, 0x12, 0x4a, 0xa1, 0x2e, + 0x0c, 0x0e, 0x19, 0x62, 0x4e, 0x53, 0x3c, 0xb4, 0x14, 0x9c, 0xed, 0xb3, + 0xe1, 0x1d, 0x32, 0x16, 0x00, 0xdc, 0x07, 0xb3, 0x2e, 0x53, 0x1a, 0x61, + 0x5c, 0x8f, 0x7f, 0xd7, 0xf3, 0x3a, 0x07, 0x1c, 0xaa, 0xa7, 0x64, 0x33, + 0xd1, 0xaa, 0xb0, 0xb7, 0x10, 0xfa, 0x7b, 0xa3, 0xdd, 0xb0, 0x17, 0x5c, + 0xed, 0x4e, 0x55, 0x8d, 0x51, 0x17, 0xaf, 0xc7, 0x54, 0x2b, 0x9b, 0x07, + 0xa8, 0xfe, 0x8e, 0x4b, 0x08, 0xa1, 0xde, 0x45, 0x64, 0x43, 0x55, 0x3f, + 0xe8, 0x7a, 0x4c, 0x24, 0x55, 0xde, 0xd7, 0x2f, 0x98, 0x54, 0x4d, 0x6c, + 0x41, 0xd6, 0xef, 0x66, 0xb7, 0x14, 0x2a, 0x4a, 0xa9, 0xaa, 0x1d, 0x3d, + 0x20, 0xf7, 0x00, 0x01, 0x03, 0x89, 0xe4, 0x17, 0x84, 0x07, 0x82, 0xfa, + 0xd6, 0x82, 0x15, 0x3d, 0x56, 0x9f, 0x94, 0x4d, 0x3d, 0x3a, 0xd1, 0xd8, + 0x8d, 0xb5, 0xbf, 0xba, 0x34, 0x99, 0xe4, 0xc3, 0x66, 0x0b, 0x76, 0xb4, + 0x4d, 0xa4, 0xb0, 0xe6, 0x72, 0x7e, 0xbc, 0x3f, 0x22, 0xb2, 0xa0, 0xaa, + 0xf6, 0x2d, 0xc2, 0xa2, 0x9d, 0xb8, 0xba, 0xbc, 0xac, 0xc2, 0x16, 0x9c, + 0x2b, 0x86, 0x74, 0x05, 0x4c, 0x89, 0xfd, 0x77, 0x0d, 0xb9, 0x8b, 0x12, + 0xaf, 0x2d, 0x93, 0x3b, 0xec, 0xbe, 0xca, 0x9f, 0x22, 0x44, 0x4b, 0x52, + 0x7a, 0xa8, 0x94, 0xb3, 0x76, 0x52, 0x92, 0xdc, 0xff, 0xaf, 0x34, 0x08, + 0xe6, 0x99, 0x49, 0x5d, 0xf7, 0x9b, 0x98, 0xd9, 0x57, 0xfd, 0xba, 0x7e, + 0x4c, 0x8e, 0x7a, 0xce, 0x3f, 0x98, 0x7a, 0x95, 0xdc, 0xb2, 0xe7, 0x77, + 0xfa, 0x2d, 0x13, 0x04, 0x47, 0x9a, 0x6d, 0x13, 0x7e, 0xfc, 0xb0, 0xc4, + 0x04, 0xe6, 0xd8, 0xed, 0x39, 0xd6, 0xaf, 0xba, 0x25, 0x49, 0xf3, 0xee, + 0x2b, 0x9a, 0x45, 0xf3, 0x24, 0x56, 0x7c, 0x02, 0x27, 0x31, 0x9d, 0xc5, + 0x9b, 0xca, 0xdf, 0xcf, 0xdf, 0x15, 0x66, 0xf3, 0x56, 0xf7, 0xc2, 0xba, + 0x6d, 0xb2, 0x1c, 0xca, 0x2a, 0x8f, 0xb2, 0xfb, 0xea, 0xf3, 0x1c, 0xb7 +}; +/* K = 4212971feb32e25fbb22845ab8c9333cb2a265f003542838a128a25108a88365 */ +static const uint8_t ac_dsa_vect273_out[] = { +/* R */ + 0x2d, 0x3f, 0x3c, 0x60, 0x5e, 0xca, 0x8f, 0xec, 0x37, 0xa7, 0x6d, 0x60, + 0x6d, 0x20, 0xfd, 0xe8, 0x9c, 0xb6, 0xf9, 0x71, 0xa4, 0x47, 0x96, 0x09, + 0x5a, 0x01, 0xdc, 0xf8, 0xe9, 0x00, 0xf5, 0xb2, +/* S */ + 0x6a, 0x43, 0x16, 0x83, 0x34, 0xe5, 0xb0, 0xea, 0x07, 0xcf, 0xa5, 0x97, + 0x86, 0x09, 0xe8, 0x6f, 0x96, 0x9d, 0x10, 0x05, 0x52, 0x8e, 0xbb, 0x3e, + 0xe9, 0x07, 0x3d, 0x56, 0x55, 0xd5, 0x4b, 0x44 +}; +#define ac_dsa_vect274_prime ac_dsa_vect271_prime +#define ac_dsa_vect274_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect274_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect274_ptx[] = { +/* Msg */ + 0x45, 0xf6, 0x56, 0xa1, 0xef, 0x0e, 0x61, 0xde, 0x46, 0xdf, 0x2c, 0xa2, + 0xd8, 0xea, 0x26, 0x64, 0x0a, 0x99, 0x4c, 0x30, 0x38, 0x0c, 0x0c, 0xfd, + 0x66, 0xbe, 0x39, 0x98, 0xd8, 0x98, 0x49, 0x16, 0x1b, 0xbc, 0xf3, 0xbe, + 0xe7, 0x7a, 0xd3, 0x0e, 0x76, 0x9f, 0x10, 0xe2, 0x3a, 0xad, 0x5b, 0x4d, + 0xf4, 0xed, 0xc1, 0x9a, 0x86, 0xfb, 0xb5, 0xab, 0xde, 0xec, 0x87, 0x79, + 0xb7, 0x6b, 0xe2, 0x79, 0x53, 0x2d, 0x76, 0x92, 0xbc, 0x58, 0x6c, 0x62, + 0x69, 0x2f, 0xa1, 0xe3, 0xdb, 0xcc, 0xe3, 0x3f, 0xfd, 0xdc, 0x9f, 0x97, + 0x58, 0x91, 0x72, 0xf6, 0x4a, 0x48, 0x53, 0x56, 0x93, 0xde, 0xd6, 0xbc, + 0x73, 0xb2, 0xca, 0x32, 0x46, 0x9d, 0x0e, 0xaf, 0x67, 0x06, 0xd2, 0xa5, + 0xf5, 0x8f, 0x8d, 0x28, 0xa7, 0x45, 0xdc, 0x32, 0x8b, 0xcc, 0x75, 0xb3, + 0x41, 0x5c, 0xa9, 0x3e, 0x29, 0xea, 0xbb, 0x1e +}; +static const uint8_t ac_dsa_vect274_priv_val[] = { +/* X */ + 0x9f, 0x35, 0xb1, 0x03, 0x86, 0x86, 0xbd, 0xe0, 0x7a, 0x5f, 0x51, 0x7d, + 0x68, 0xf5, 0x62, 0x73, 0x9c, 0xb7, 0x15, 0x0f, 0xa4, 0x7e, 0xba, 0xf7, + 0xff, 0xd2, 0x93, 0x06, 0xaf, 0xd4, 0x68, 0x8a +}; +static const uint8_t ac_dsa_vect274_pub_val[] = { +/* Y */ + 0x31, 0xa9, 0x89, 0x60, 0x1f, 0x32, 0xb2, 0x05, 0x94, 0x3a, 0x84, 0x18, + 0x87, 0xdf, 0x3c, 0x68, 0x14, 0xcf, 0xb2, 0x25, 0x8e, 0x52, 0x04, 0xd0, + 0x4d, 0x39, 0x28, 0xdd, 0xfa, 0xba, 0x0d, 0xff, 0xad, 0x43, 0x15, 0x1e, + 0x27, 0xd6, 0x66, 0xd2, 0x92, 0x8b, 0xed, 0xc6, 0x72, 0x75, 0x44, 0x0f, + 0xb5, 0x02, 0xed, 0x3e, 0xaf, 0xc3, 0xad, 0xc1, 0x10, 0x09, 0xee, 0x70, + 0x3f, 0x01, 0xea, 0xa0, 0x34, 0xaa, 0x72, 0x4f, 0xcc, 0x63, 0xc5, 0x9a, + 0x8a, 0x59, 0x63, 0xf3, 0x35, 0x2f, 0x72, 0x93, 0xea, 0x24, 0x25, 0xea, + 0x89, 0xbb, 0xf1, 0xe4, 0x17, 0x24, 0xb6, 0x9f, 0x38, 0x3b, 0xf1, 0x0a, + 0x97, 0x31, 0x46, 0xed, 0x02, 0xf5, 0x52, 0x08, 0xb0, 0x48, 0x33, 0xd1, + 0xbb, 0x53, 0x99, 0xa6, 0x7f, 0x04, 0x08, 0x15, 0x90, 0xac, 0xfc, 0xfb, + 0xb1, 0x21, 0x05, 0x42, 0x3e, 0x26, 0x09, 0x1d, 0x09, 0x07, 0x8c, 0x45, + 0x00, 0x7d, 0x43, 0x6e, 0xb1, 0x9f, 0x95, 0x2f, 0x87, 0x98, 0xb0, 0x01, + 0xa3, 0xc6, 0x4a, 0x3b, 0xaa, 0x54, 0x96, 0xc9, 0xdb, 0xe6, 0x58, 0x07, + 0x81, 0xd4, 0x02, 0x0b, 0xb7, 0xe4, 0xe7, 0xae, 0x23, 0x80, 0xce, 0x79, + 0x65, 0x8c, 0x10, 0xa2, 0xe5, 0x7b, 0xbb, 0x8c, 0xac, 0x12, 0x08, 0x77, + 0x28, 0xce, 0x43, 0xba, 0x2b, 0x9f, 0x38, 0x0e, 0x3a, 0xbc, 0x2d, 0xd1, + 0x2a, 0x68, 0x24, 0x88, 0xc6, 0xb4, 0xfb, 0x2f, 0x8d, 0xd7, 0xf3, 0x84, + 0x6b, 0x6a, 0x26, 0xf9, 0x13, 0xac, 0x15, 0x68, 0x79, 0xee, 0x6a, 0x1a, + 0xe0, 0xad, 0xa9, 0x56, 0x85, 0x21, 0xa4, 0x42, 0x8e, 0xd9, 0xf7, 0x41, + 0xe0, 0xe7, 0x9a, 0x84, 0x28, 0x80, 0x01, 0x9c, 0x01, 0xb3, 0x4e, 0x98, + 0x8a, 0x7c, 0xf7, 0xe6, 0x35, 0x24, 0xe8, 0xcd, 0x02, 0x54, 0x53, 0x22, + 0x3a, 0x26, 0x60, 0x27, 0x3e, 0x49, 0x19, 0x68, 0xaf, 0x7f, 0x4b, 0x1d, + 0xc2, 0x12, 0x39, 0x61, 0xde, 0x37, 0x53, 0xab, 0x16, 0xec, 0xa5, 0xb1, + 0x85, 0x9a, 0x4f, 0x71, 0x17, 0x25, 0x38, 0xf0, 0x5a, 0x2a, 0x82, 0xa3, + 0x4f, 0x98, 0xba, 0x07, 0xc1, 0xe5, 0x31, 0xd8, 0x2e, 0xf5, 0x92, 0xe5, + 0x49, 0x35, 0x33, 0x41, 0x6b, 0xd6, 0xc6, 0xa4, 0xc7, 0xca, 0x3b, 0x0d, + 0x2a, 0x2f, 0xff, 0x88, 0xa8, 0xf0, 0x73, 0xa7, 0x6c, 0x69, 0x18, 0x02, + 0xaa, 0xae, 0xce, 0x4e, 0x85, 0x2d, 0x66, 0x50, 0x87, 0x1a, 0x17, 0xcc, + 0xa0, 0xf5, 0x25, 0x1e, 0xf2, 0x2d, 0xfc, 0x8e, 0x3b, 0x26, 0x1b, 0xfc, + 0xbd, 0x5a, 0x22, 0xb2, 0x73, 0x2a, 0xa1, 0x7d, 0x7d, 0xf1, 0xf7, 0xb8, + 0x2f, 0x6b, 0x22, 0x2e, 0x5f, 0x60, 0x65, 0xbf, 0x80, 0xd0, 0x4c, 0x2e, + 0x57, 0x74, 0x09, 0x40, 0x84, 0xe4, 0xd5, 0xce, 0x0d, 0x3e, 0x89, 0x17 +}; +/* K = 55d1ffc73b52b6364d660fa4658a6351142ac538fd3cfb4eec40ba07bef5418b */ +static const uint8_t ac_dsa_vect274_out[] = { +/* R */ + 0x3c, 0xed, 0x0e, 0xa5, 0xf7, 0xfd, 0x58, 0x86, 0x68, 0xa4, 0x1e, 0xfe, + 0x0e, 0x90, 0x95, 0x4c, 0x09, 0x30, 0xaf, 0xb6, 0xbe, 0x18, 0xd9, 0x07, + 0x52, 0x83, 0x1f, 0x68, 0x3c, 0xd9, 0x2a, 0x9c, +/* S */ + 0x9e, 0x46, 0xca, 0x12, 0x94, 0x17, 0x45, 0xea, 0x1a, 0x12, 0xc5, 0xa2, + 0xd6, 0x09, 0x88, 0x4c, 0xb5, 0x79, 0x2f, 0x46, 0xaf, 0xaa, 0xcf, 0xf0, + 0x72, 0x37, 0x13, 0x74, 0x00, 0x36, 0x68, 0x68 +}; +#define ac_dsa_vect275_prime ac_dsa_vect271_prime +#define ac_dsa_vect275_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect275_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect275_ptx[] = { +/* Msg */ + 0xc7, 0x37, 0xd5, 0xae, 0x24, 0x8a, 0x96, 0x06, 0x2d, 0x6a, 0xfa, 0x8d, + 0xca, 0xcc, 0x03, 0x84, 0xc5, 0xfb, 0xfb, 0x9d, 0x8b, 0x60, 0x52, 0xb5, + 0x24, 0x93, 0xc6, 0x0d, 0x3e, 0xdf, 0xc5, 0x24, 0xb5, 0x67, 0xb1, 0xf8, + 0x96, 0xe7, 0x44, 0x7d, 0x0e, 0x24, 0x01, 0x94, 0x03, 0xed, 0x83, 0xe4, + 0x88, 0x9c, 0x0c, 0x4d, 0xe5, 0x7c, 0x70, 0xfa, 0xda, 0x6c, 0x8b, 0x5a, + 0x09, 0x90, 0x43, 0x50, 0xa4, 0x4d, 0xfa, 0xf7, 0x7d, 0x60, 0xaf, 0x62, + 0xde, 0x3e, 0xdf, 0xd8, 0x76, 0x0d, 0x07, 0x74, 0x73, 0xf2, 0x6d, 0xf2, + 0x83, 0x7c, 0xfc, 0x20, 0x15, 0xf2, 0x27, 0xdd, 0x7d, 0x35, 0x1a, 0x53, + 0x50, 0xf1, 0x42, 0x8f, 0x26, 0x99, 0xfd, 0x3f, 0x51, 0x83, 0x26, 0xfe, + 0xa8, 0xae, 0xf9, 0x8f, 0xc4, 0xea, 0x67, 0x31, 0x30, 0xc8, 0x07, 0x9f, + 0xac, 0x38, 0x95, 0xfe, 0x85, 0x6c, 0x77, 0xf8 +}; +static const uint8_t ac_dsa_vect275_priv_val[] = { +/* X */ + 0x40, 0xdb, 0xd4, 0x96, 0xfc, 0x46, 0x44, 0xbe, 0x7c, 0xcb, 0x24, 0xd9, + 0xdc, 0x55, 0x89, 0x5c, 0x1b, 0x92, 0x3a, 0x05, 0xf4, 0xda, 0x56, 0x10, + 0x58, 0x9d, 0x56, 0x4e, 0xe8, 0xaa, 0xc3, 0x3f +}; +static const uint8_t ac_dsa_vect275_pub_val[] = { +/* Y */ + 0x61, 0x12, 0xd3, 0xcd, 0x31, 0x91, 0xd1, 0x7d, 0xee, 0x77, 0x88, 0xf5, + 0x68, 0x81, 0x5a, 0x0a, 0xab, 0x50, 0x00, 0x60, 0x02, 0xc9, 0xde, 0x2b, + 0xd1, 0xa9, 0xbb, 0xa2, 0x45, 0xba, 0x02, 0x89, 0x4b, 0x02, 0xe9, 0x24, + 0x75, 0x17, 0xac, 0xe6, 0x98, 0xae, 0x0a, 0x05, 0x17, 0x6b, 0x62, 0xb3, + 0xa0, 0x25, 0xa5, 0x63, 0xdd, 0xa8, 0xde, 0xb7, 0xf2, 0xfc, 0x3e, 0x17, + 0x7a, 0xe3, 0x47, 0x74, 0x48, 0xd3, 0x9a, 0xe4, 0xeb, 0xe7, 0xae, 0x8e, + 0xc6, 0x5a, 0x44, 0x21, 0xf7, 0x54, 0x66, 0x7f, 0xd6, 0xd7, 0xc2, 0xeb, + 0x93, 0xf1, 0xa1, 0x8d, 0x3d, 0x1a, 0x62, 0x35, 0x73, 0x6b, 0xcd, 0xb7, + 0x47, 0x46, 0xf4, 0x6d, 0x88, 0xe6, 0x5d, 0xc0, 0x7c, 0x25, 0x91, 0xe1, + 0xf9, 0x5d, 0xda, 0x5e, 0x5e, 0x20, 0xe1, 0x05, 0xee, 0x8b, 0x4d, 0xdc, + 0xaa, 0xf3, 0x60, 0x21, 0x29, 0x0d, 0x6b, 0x64, 0x93, 0x67, 0x1d, 0x8a, + 0xaf, 0xae, 0x14, 0x5d, 0x9b, 0x90, 0xbe, 0xc3, 0xcc, 0x60, 0x17, 0x9b, + 0xb8, 0xfc, 0x30, 0xf1, 0x43, 0xc5, 0x75, 0xd5, 0xd8, 0x61, 0x62, 0x37, + 0x21, 0xb6, 0x54, 0x7d, 0x3a, 0xaa, 0xad, 0xe4, 0x55, 0xf0, 0x5f, 0xef, + 0x93, 0x18, 0xab, 0xcd, 0x29, 0xbd, 0x19, 0xb1, 0x2c, 0x35, 0xca, 0x75, + 0x6d, 0xe5, 0x10, 0x8c, 0x18, 0x5e, 0xce, 0x4a, 0xa1, 0xbf, 0x1a, 0x8e, + 0x38, 0x80, 0x97, 0x97, 0x06, 0x7b, 0xd1, 0xf5, 0x2b, 0x6c, 0xf2, 0xc4, + 0x15, 0xe7, 0x3f, 0x92, 0x46, 0xbd, 0x5b, 0xfa, 0xdd, 0x7b, 0x9a, 0x9d, + 0x2b, 0x53, 0x69, 0x70, 0x1e, 0x72, 0x14, 0x7e, 0x22, 0xda, 0x7e, 0x09, + 0x2d, 0x9b, 0x57, 0x8f, 0xb0, 0xc0, 0x44, 0xa3, 0x6e, 0xff, 0xcb, 0xd7, + 0x09, 0x25, 0x85, 0x00, 0xa0, 0x0c, 0xff, 0x23, 0x09, 0x62, 0xc4, 0x42, + 0x25, 0x71, 0x2f, 0xc4, 0x3f, 0x9e, 0x80, 0x2b, 0xae, 0xad, 0x7f, 0x9c, + 0xb4, 0x6a, 0xb4, 0x93, 0x1f, 0x66, 0x3c, 0x6e, 0x3e, 0xd4, 0x08, 0x2d, + 0x59, 0x61, 0x0f, 0x01, 0x74, 0x1b, 0x5f, 0x24, 0x56, 0x6b, 0x01, 0xb3, + 0xe3, 0x93, 0x3b, 0x29, 0xe0, 0x28, 0xc5, 0x4b, 0xd2, 0xfc, 0x75, 0xb5, + 0x49, 0xfd, 0x05, 0xe6, 0x4c, 0x58, 0xc9, 0xae, 0x0b, 0xa4, 0x17, 0xa9, + 0xe9, 0x85, 0x81, 0xdb, 0x77, 0xbe, 0x75, 0x23, 0x3a, 0x42, 0xf7, 0x71, + 0xc9, 0x9f, 0x0a, 0x49, 0xb4, 0x94, 0xf0, 0x95, 0x52, 0x02, 0xb1, 0x9d, + 0x6c, 0x74, 0x0e, 0x86, 0x60, 0x66, 0x10, 0x4e, 0x46, 0x3e, 0x65, 0xe4, + 0xba, 0xd9, 0xa0, 0x81, 0x63, 0x6d, 0x05, 0x36, 0x74, 0x26, 0x15, 0x3f, + 0x04, 0xbc, 0xb2, 0x71, 0x21, 0x86, 0xdc, 0xa6, 0x83, 0x43, 0x88, 0xe8, + 0x25, 0x20, 0xd3, 0x4e, 0xfd, 0x8a, 0x89, 0x31, 0x3b, 0x2c, 0x7e, 0x60 +}; +/* K = aa63e91cb3fa545c447a8b8309a569d48104e14d5d05b8951033ac8a7d711c3f */ +static const uint8_t ac_dsa_vect275_out[] = { +/* R */ + 0x00, 0x41, 0xb1, 0xc7, 0x56, 0xdd, 0x2e, 0x42, 0x71, 0x4f, 0x9e, 0xe7, + 0xed, 0xce, 0x21, 0xea, 0x33, 0xef, 0x49, 0xdb, 0xf4, 0x52, 0xcc, 0xd9, + 0x35, 0x7d, 0x5f, 0x45, 0xff, 0xab, 0x08, 0xf9, +/* S */ + 0x10, 0x2c, 0x6e, 0xaa, 0xd3, 0x8d, 0x39, 0xc0, 0xd0, 0x36, 0x33, 0x5a, + 0xe1, 0x9d, 0xd0, 0xd7, 0x5e, 0x8d, 0xca, 0xba, 0xe5, 0x9b, 0x12, 0x0f, + 0x69, 0xcb, 0xd2, 0xb5, 0xcf, 0x48, 0xab, 0xdb +}; +#define ac_dsa_vect276_prime ac_dsa_vect271_prime +#define ac_dsa_vect276_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect276_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect276_ptx[] = { +/* Msg */ + 0xa6, 0xfc, 0x89, 0xa2, 0x23, 0x02, 0x2e, 0xe9, 0xe5, 0x08, 0x72, 0x52, + 0x78, 0x58, 0x2f, 0x56, 0xdb, 0x9c, 0xd2, 0x4c, 0x0d, 0x75, 0xd0, 0x72, + 0xa5, 0x28, 0xd0, 0xc6, 0x0f, 0x27, 0x17, 0x1e, 0xa3, 0x76, 0xe2, 0xdc, + 0x28, 0xa9, 0xdc, 0x0b, 0x12, 0xe6, 0x68, 0xaf, 0x77, 0xdc, 0xbb, 0x38, + 0x17, 0x37, 0xe1, 0xba, 0x7d, 0x9e, 0x80, 0xb9, 0xbe, 0xc8, 0x0b, 0xf9, + 0x06, 0x1b, 0x8f, 0xa1, 0x0e, 0x43, 0xa7, 0x40, 0x3a, 0x29, 0x16, 0x24, + 0xa6, 0x00, 0xdd, 0x4f, 0x5c, 0x2b, 0x50, 0xc5, 0x2d, 0x5c, 0x61, 0x55, + 0xd5, 0x2b, 0xe5, 0xa3, 0x25, 0xf6, 0xad, 0x81, 0x3f, 0xb3, 0xec, 0xaf, + 0x6d, 0x1f, 0x92, 0xe9, 0x8c, 0xc8, 0x7c, 0x26, 0xc6, 0x8c, 0xbd, 0x15, + 0xd5, 0x48, 0xa3, 0x78, 0x2b, 0xff, 0xdd, 0x11, 0x16, 0xc7, 0xc1, 0x1f, + 0xca, 0xbd, 0xe4, 0x02, 0x5f, 0xec, 0x51, 0x54 +}; +static const uint8_t ac_dsa_vect276_priv_val[] = { +/* X */ + 0x1b, 0x41, 0xc2, 0x93, 0x64, 0x94, 0x77, 0x68, 0x87, 0x6a, 0xd4, 0xe7, + 0xab, 0xca, 0xe5, 0x9c, 0x8e, 0x61, 0x37, 0x3d, 0x25, 0x27, 0x4b, 0xa4, + 0x2c, 0xeb, 0x3d, 0x87, 0x6d, 0x6c, 0xe6, 0x72 +}; +static const uint8_t ac_dsa_vect276_pub_val[] = { +/* Y */ + 0x6c, 0x1d, 0x4d, 0x6b, 0x52, 0xaa, 0x4b, 0xff, 0x35, 0xf4, 0x30, 0x23, + 0x30, 0x05, 0x27, 0x77, 0xf5, 0x1f, 0x6a, 0x08, 0x49, 0x16, 0x1f, 0x90, + 0x6e, 0xf2, 0x17, 0xb0, 0x4b, 0x18, 0x54, 0x5c, 0xe5, 0x2a, 0xe4, 0xae, + 0x42, 0x3a, 0xd1, 0xb4, 0xf8, 0xb1, 0x73, 0x5a, 0xe0, 0x0a, 0xb0, 0xc0, + 0x44, 0xa5, 0x6f, 0x94, 0x5d, 0xa8, 0x4d, 0x1c, 0xdc, 0x26, 0xe0, 0x82, + 0xd7, 0xac, 0xd7, 0x72, 0xdf, 0xab, 0xcd, 0x18, 0xb5, 0xe1, 0x3c, 0x05, + 0xc2, 0x79, 0x1a, 0x8d, 0xc1, 0x61, 0x46, 0xe1, 0x51, 0x32, 0x3e, 0x4e, + 0xf2, 0xce, 0x5d, 0x64, 0x38, 0x9f, 0x69, 0xd9, 0x34, 0x7a, 0xa2, 0xa5, + 0xbd, 0x01, 0x14, 0xde, 0x0e, 0xec, 0xdf, 0x99, 0x0a, 0x44, 0x0d, 0x1b, + 0xf9, 0x89, 0x0d, 0xd9, 0x5f, 0xd6, 0x40, 0xd2, 0xfb, 0x17, 0x89, 0xca, + 0x6a, 0x6d, 0xbe, 0xe1, 0x83, 0x6a, 0xd7, 0xcb, 0x47, 0x37, 0x0b, 0x74, + 0x56, 0xe4, 0x9f, 0x3b, 0xac, 0x03, 0x31, 0x0f, 0x8c, 0xbe, 0x61, 0xdd, + 0x1c, 0xc0, 0x6d, 0x78, 0xc7, 0x6f, 0xec, 0x63, 0x97, 0xe6, 0x08, 0xa4, + 0xca, 0xc4, 0xe2, 0xc3, 0x89, 0x83, 0xce, 0x5a, 0xa9, 0xdc, 0xba, 0x07, + 0x4a, 0x20, 0x6f, 0xa6, 0x08, 0xdb, 0x35, 0xf2, 0xad, 0x3d, 0x63, 0xd9, + 0x5b, 0x2c, 0xb7, 0xa0, 0x1c, 0x33, 0xd4, 0x98, 0x76, 0x7e, 0x8e, 0x68, + 0x57, 0x8e, 0x4e, 0x99, 0x53, 0x8b, 0xf3, 0xd7, 0x03, 0xe6, 0x38, 0x63, + 0xa2, 0x50, 0x91, 0x45, 0x2e, 0x73, 0xb9, 0x6a, 0x37, 0x16, 0xe9, 0xcc, + 0x10, 0x9b, 0x66, 0x00, 0x8f, 0xa5, 0xca, 0xfd, 0xbf, 0x96, 0xb7, 0xfc, + 0x10, 0xc3, 0xbb, 0x89, 0xd7, 0x9d, 0x45, 0xff, 0xef, 0xc0, 0x19, 0x08, + 0xd2, 0x47, 0xef, 0x1d, 0x4f, 0xcb, 0x90, 0x3b, 0xf5, 0xe7, 0x91, 0x7a, + 0xf8, 0x86, 0x18, 0xa5, 0x2a, 0x12, 0x00, 0x47, 0x98, 0x89, 0x05, 0x40, + 0xa5, 0xa7, 0x5c, 0x65, 0xfb, 0xc0, 0x57, 0xd8, 0x60, 0xf4, 0xb6, 0x5d, + 0x8b, 0x08, 0xb8, 0xd2, 0x15, 0xf0, 0x56, 0xd8, 0xe5, 0xe3, 0x8b, 0xf0, + 0xb3, 0x19, 0xe2, 0x94, 0xdb, 0x24, 0x2a, 0x4f, 0xc7, 0x9b, 0x2e, 0x10, + 0x6f, 0xec, 0xa2, 0x55, 0x6d, 0x14, 0x6f, 0x52, 0x03, 0xfd, 0x72, 0xad, + 0xc7, 0x3a, 0x48, 0xe3, 0xa5, 0xaa, 0xdb, 0xb2, 0x93, 0xa2, 0xef, 0x58, + 0x62, 0x65, 0x4c, 0x31, 0x53, 0x9a, 0xd8, 0x56, 0xa1, 0x6e, 0x57, 0x16, + 0xc4, 0x37, 0xb4, 0x74, 0xf3, 0x33, 0x9c, 0xd8, 0x4f, 0x0a, 0xc9, 0x2b, + 0xc2, 0xca, 0x6f, 0xac, 0x10, 0xc7, 0x51, 0xd0, 0x99, 0xa9, 0x04, 0x08, + 0xde, 0xf6, 0x10, 0x6c, 0xa8, 0x38, 0x93, 0xd8, 0x7e, 0x32, 0x81, 0x8d, + 0x76, 0x34, 0x53, 0x7a, 0x4e, 0xf6, 0x67, 0xce, 0x7f, 0x26, 0xa5, 0xcb +}; +/* K = 4c9ace2c908648032151f638e3c909d1f0646fe018a1c9c22a170eff64447fbe */ +static const uint8_t ac_dsa_vect276_out[] = { +/* R */ + 0x48, 0xbd, 0x01, 0x0c, 0x1a, 0xf7, 0x7b, 0x3c, 0x40, 0xdb, 0x50, 0x34, + 0x97, 0x06, 0xd6, 0x4d, 0x16, 0xcb, 0xb7, 0x2d, 0xb5, 0x19, 0x43, 0xd3, + 0x45, 0x15, 0x1d, 0xea, 0xcd, 0x4a, 0x41, 0x33, +/* S */ + 0x0f, 0x1c, 0x4b, 0xdb, 0x47, 0x58, 0xab, 0x3b, 0x55, 0x18, 0xd4, 0x60, + 0x5b, 0x98, 0x64, 0x80, 0x57, 0x23, 0xd3, 0x3a, 0x36, 0x11, 0x6e, 0xa6, + 0x50, 0x54, 0x6f, 0xee, 0xf1, 0x1c, 0x4a, 0x5e +}; +#define ac_dsa_vect277_prime ac_dsa_vect271_prime +#define ac_dsa_vect277_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect277_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect277_ptx[] = { +/* Msg */ + 0x2a, 0xe4, 0xac, 0x7c, 0xe2, 0x9a, 0xe7, 0xd3, 0x24, 0x90, 0xd3, 0xa5, + 0x4b, 0x71, 0x5d, 0xb3, 0xf4, 0x73, 0x06, 0xf8, 0x4b, 0x59, 0xb3, 0x3b, + 0x21, 0x62, 0x2a, 0x18, 0xaa, 0x2c, 0x06, 0x0a, 0x44, 0x34, 0xad, 0xfa, + 0x01, 0xff, 0x16, 0x86, 0xb5, 0xd1, 0xdd, 0x30, 0x35, 0x30, 0x8e, 0x92, + 0xf7, 0xac, 0xc7, 0x6d, 0xea, 0x96, 0x9d, 0xee, 0xfb, 0x98, 0xc2, 0x97, + 0x2b, 0x42, 0xa5, 0x96, 0xe1, 0x05, 0x5a, 0x5a, 0xa2, 0xc6, 0x61, 0xf0, + 0xb7, 0x34, 0xba, 0x4f, 0x0b, 0x34, 0x1c, 0x77, 0x82, 0x7d, 0x88, 0x91, + 0x5a, 0x5e, 0x89, 0xf9, 0x5a, 0x98, 0xd6, 0x3d, 0x77, 0x29, 0x87, 0x4f, + 0xce, 0x4f, 0xf7, 0x5d, 0x7a, 0xdd, 0x74, 0xf4, 0x31, 0x3d, 0xff, 0x78, + 0x4e, 0x41, 0x7b, 0x2e, 0xe1, 0xfc, 0xd2, 0x70, 0xc0, 0x38, 0xdb, 0xbb, + 0xb9, 0x6a, 0x77, 0x68, 0x48, 0x4b, 0x88, 0x54 +}; +static const uint8_t ac_dsa_vect277_priv_val[] = { +/* X */ + 0x87, 0x98, 0x0d, 0xa0, 0x68, 0x45, 0x58, 0xf8, 0x7e, 0x58, 0x64, 0xae, + 0x58, 0x58, 0x64, 0x62, 0x5a, 0xed, 0x61, 0xb1, 0x30, 0x9c, 0x1d, 0x5f, + 0x30, 0xf6, 0x47, 0x7f, 0x94, 0x7c, 0x44, 0xfb +}; +static const uint8_t ac_dsa_vect277_pub_val[] = { +/* Y */ + 0x0a, 0x84, 0x29, 0x8f, 0x47, 0x68, 0xe9, 0xd7, 0xbf, 0x79, 0x6d, 0x06, + 0x58, 0x5e, 0x8b, 0x75, 0xfb, 0xde, 0x65, 0x83, 0x98, 0xa2, 0x24, 0xa8, + 0xac, 0x3a, 0x49, 0xfb, 0x91, 0x23, 0x5e, 0xaa, 0xa1, 0x83, 0xaa, 0x88, + 0x27, 0xcc, 0x2a, 0xf7, 0x9e, 0xa3, 0x34, 0xdc, 0x8b, 0xe4, 0xcc, 0x72, + 0x90, 0x29, 0xab, 0x5f, 0x81, 0x61, 0xf7, 0x18, 0xf7, 0xbf, 0xbe, 0x90, + 0xad, 0x2a, 0x15, 0x98, 0x88, 0x52, 0x39, 0x82, 0xb6, 0xd4, 0x93, 0x2d, + 0x81, 0x59, 0x49, 0x5b, 0xa8, 0x4d, 0x0a, 0xb3, 0x5d, 0x7e, 0x39, 0x5d, + 0x14, 0xdb, 0xa9, 0x06, 0xa1, 0x67, 0x9a, 0xe3, 0xcb, 0xb7, 0x2c, 0x10, + 0xed, 0x6f, 0xa1, 0x4d, 0xa4, 0xd6, 0x00, 0x77, 0xb0, 0xbf, 0xb5, 0x91, + 0xa3, 0xde, 0xc6, 0x43, 0x99, 0x6c, 0x39, 0x63, 0x38, 0xa5, 0x1d, 0x44, + 0x6b, 0xde, 0x62, 0x24, 0xae, 0xa1, 0x6a, 0xef, 0x41, 0xf3, 0x54, 0xe0, + 0x9a, 0x9d, 0xce, 0x9f, 0x3a, 0x00, 0xcb, 0x44, 0x5a, 0x5c, 0x9c, 0xae, + 0x4a, 0x6c, 0x3c, 0x19, 0x19, 0xc9, 0xe0, 0xc5, 0x30, 0x82, 0x17, 0x3d, + 0x0e, 0xc0, 0x0a, 0xe5, 0xe1, 0x5a, 0xa7, 0x26, 0x07, 0x50, 0xb6, 0xa0, + 0x3e, 0xf0, 0x5a, 0x51, 0x8a, 0x48, 0x61, 0x53, 0x40, 0xac, 0x20, 0x98, + 0x40, 0x73, 0xce, 0xa5, 0xfc, 0x99, 0x0d, 0x48, 0x98, 0x58, 0x94, 0x9a, + 0xaf, 0x6e, 0x9e, 0x34, 0x7b, 0x48, 0x02, 0xaf, 0xbe, 0x25, 0xa0, 0x66, + 0x94, 0x72, 0xbd, 0x93, 0x16, 0xba, 0x2c, 0x23, 0xa6, 0x1c, 0xc3, 0xaa, + 0xdf, 0x1b, 0x70, 0xd9, 0xfd, 0x97, 0x61, 0xbb, 0x03, 0x5f, 0x0c, 0xa5, + 0x1e, 0xdb, 0x2b, 0x12, 0xfc, 0xfd, 0x65, 0x1c, 0xb9, 0x23, 0x63, 0xef, + 0x48, 0x00, 0x5a, 0x26, 0x83, 0xfd, 0x2e, 0xd8, 0x66, 0x5d, 0x70, 0x58, + 0x8f, 0xd9, 0xa1, 0xbe, 0x3a, 0xa5, 0x1c, 0x95, 0x8b, 0x81, 0xf1, 0x3e, + 0x4a, 0xcf, 0xaf, 0x0d, 0x2a, 0x90, 0xaa, 0xae, 0xf2, 0x1b, 0x2c, 0xc9, + 0xef, 0x2e, 0xd3, 0x7b, 0xce, 0x3c, 0x47, 0xc8, 0xbc, 0xbf, 0xc1, 0xfb, + 0x9f, 0x94, 0xe4, 0x9b, 0xd2, 0xf1, 0xa3, 0x0a, 0x88, 0xdf, 0x22, 0x73, + 0x5a, 0x0f, 0xdf, 0x0a, 0xc6, 0x02, 0x8a, 0x00, 0x8b, 0x06, 0x2c, 0x95, + 0x60, 0xc4, 0x2a, 0x47, 0x69, 0x97, 0xdd, 0x21, 0x10, 0x06, 0x92, 0xef, + 0x63, 0x96, 0xd5, 0xf3, 0xfb, 0x2c, 0x15, 0x53, 0x28, 0x25, 0x7e, 0x7b, + 0x7d, 0x2b, 0xc0, 0x5f, 0xab, 0xd5, 0x4a, 0x81, 0xa2, 0x27, 0x29, 0x93, + 0xd3, 0x42, 0xbe, 0xc8, 0x57, 0x7c, 0x64, 0xd5, 0x1b, 0x4c, 0xdb, 0xe3, + 0x65, 0x4d, 0xae, 0x56, 0x8c, 0x4d, 0xa0, 0x18, 0x61, 0x8c, 0x30, 0x47, + 0xae, 0xe0, 0x6b, 0xf2, 0x62, 0x1e, 0x05, 0x6b, 0x33, 0x5d, 0x04, 0x4b +}; +/* K = 25b9d8fbe7e3ab7017f2b1e53da579df460dfb72ba5fe4ae4c85b8c23472bc8c */ +static const uint8_t ac_dsa_vect277_out[] = { +/* R */ + 0x6b, 0x7e, 0xd3, 0xa4, 0xc2, 0xa4, 0xf7, 0x85, 0x00, 0xc7, 0xe9, 0x47, + 0xe6, 0x17, 0x5c, 0x5c, 0xa8, 0x57, 0xc9, 0xd6, 0x13, 0xe7, 0x79, 0x0b, + 0x9b, 0xe0, 0xd1, 0x4e, 0xc8, 0x40, 0x3e, 0x5f, +/* S */ + 0xa1, 0x16, 0xf3, 0xde, 0x16, 0x62, 0x60, 0xd1, 0x10, 0xe2, 0x0e, 0x84, + 0xeb, 0x8c, 0x97, 0xc3, 0xf0, 0x18, 0x17, 0x86, 0x08, 0xa2, 0xea, 0x3e, + 0x3e, 0x2f, 0x5e, 0xd9, 0x1d, 0x43, 0xde, 0x11 +}; +#define ac_dsa_vect278_prime ac_dsa_vect271_prime +#define ac_dsa_vect278_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect278_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect278_ptx[] = { +/* Msg */ + 0x3e, 0xad, 0xe9, 0xa1, 0x0f, 0xb5, 0x9a, 0xf3, 0x6a, 0x54, 0x01, 0x70, + 0x73, 0x7f, 0xbc, 0x53, 0x6e, 0x4c, 0x52, 0x30, 0xb8, 0xf6, 0xc4, 0xb2, + 0x16, 0xed, 0xdd, 0x3e, 0xa9, 0x23, 0x42, 0x12, 0x3a, 0x33, 0x74, 0xd0, + 0xc7, 0x51, 0xb2, 0x4b, 0x62, 0x7f, 0x9e, 0xad, 0x4d, 0xe2, 0x6e, 0x9a, + 0x78, 0x97, 0xd9, 0xbc, 0x5d, 0x58, 0xa6, 0xa3, 0xac, 0x74, 0xcd, 0x45, + 0x75, 0xb3, 0x28, 0x6e, 0xc1, 0x5f, 0x84, 0x53, 0x22, 0x4f, 0x37, 0x17, + 0x9e, 0x51, 0xd9, 0xc4, 0xad, 0x8a, 0x60, 0xbf, 0x37, 0xd7, 0x1c, 0x62, + 0xad, 0x7f, 0xc5, 0x3e, 0x5c, 0x7b, 0x12, 0xf4, 0xaa, 0xa2, 0xd4, 0x28, + 0xe5, 0xc8, 0x89, 0xfd, 0x7f, 0x06, 0x2c, 0x91, 0x3d, 0x9b, 0x57, 0x4f, + 0x4b, 0x5d, 0xb5, 0x16, 0xc9, 0x76, 0xba, 0xd5, 0x88, 0x30, 0x2f, 0x21, + 0x9f, 0xd8, 0x3e, 0x18, 0xbe, 0xe8, 0xe6, 0x8e +}; +static const uint8_t ac_dsa_vect278_priv_val[] = { +/* X */ + 0x6c, 0xf4, 0x53, 0x17, 0x8d, 0xb0, 0xdd, 0x7f, 0x2f, 0x94, 0xf9, 0xa1, + 0xf5, 0x18, 0xc6, 0x22, 0xc1, 0xdd, 0xee, 0x46, 0xd4, 0xb0, 0x90, 0x46, + 0x28, 0x12, 0xe9, 0xf7, 0xb8, 0x62, 0x26, 0x5b +}; +static const uint8_t ac_dsa_vect278_pub_val[] = { +/* Y */ + 0x08, 0xa1, 0x5b, 0x23, 0x84, 0xdf, 0xf4, 0xf3, 0x03, 0x3c, 0x87, 0x16, + 0x86, 0x73, 0xc5, 0x67, 0x05, 0x98, 0x70, 0xc8, 0xe7, 0x8d, 0x2f, 0xdd, + 0xc7, 0x54, 0x0a, 0xfd, 0xa8, 0x05, 0x8d, 0xf3, 0x84, 0xd3, 0x18, 0x2a, + 0x42, 0x61, 0x54, 0x32, 0xff, 0x93, 0x77, 0x7d, 0x3f, 0xce, 0x49, 0xc1, + 0x17, 0xc7, 0xbb, 0xe8, 0x21, 0xe6, 0x78, 0x9b, 0x51, 0x37, 0xdd, 0xf0, + 0x84, 0x65, 0x60, 0x98, 0xaa, 0x7b, 0x05, 0x16, 0xfd, 0x30, 0xa4, 0x2c, + 0x8c, 0x86, 0xd9, 0x4e, 0x6b, 0x26, 0x8b, 0x6e, 0x13, 0x01, 0x1d, 0x25, + 0xeb, 0xa0, 0x18, 0xca, 0x40, 0xcf, 0x8a, 0x35, 0xe1, 0x96, 0x31, 0x35, + 0xd5, 0xcd, 0x65, 0xa5, 0x7a, 0xca, 0x8b, 0x00, 0x79, 0x88, 0xa5, 0xea, + 0x75, 0xad, 0xb4, 0xd0, 0x1c, 0xc0, 0xf0, 0x83, 0x8a, 0xb4, 0x2d, 0x3d, + 0xf6, 0x43, 0xa7, 0xd2, 0x56, 0x1c, 0xfd, 0x1f, 0xde, 0xbe, 0x3a, 0xd8, + 0x6a, 0xd0, 0x3d, 0xe3, 0x17, 0x02, 0x75, 0x33, 0xd5, 0x23, 0x35, 0x1b, + 0xe5, 0x32, 0xbc, 0x73, 0x1a, 0xaf, 0x43, 0xb8, 0x64, 0x2a, 0x7d, 0xa8, + 0x08, 0x73, 0xb8, 0x0d, 0xc6, 0x1b, 0x7a, 0x24, 0x9e, 0x58, 0x60, 0xfd, + 0x1a, 0x3e, 0xae, 0x0f, 0x8f, 0x0c, 0xf2, 0x1e, 0x20, 0x5d, 0x6f, 0x40, + 0x3c, 0xb0, 0xa1, 0x03, 0x29, 0x0c, 0x9e, 0x69, 0xd3, 0x8c, 0xbe, 0xd9, + 0xe0, 0x92, 0xb6, 0x9f, 0x71, 0xf9, 0x17, 0x2b, 0x36, 0x76, 0xf2, 0x9a, + 0x97, 0x13, 0x3f, 0xc3, 0xe1, 0x87, 0x46, 0xfe, 0xdc, 0x65, 0x3f, 0xbf, + 0xb6, 0x2c, 0x5e, 0x0a, 0xfe, 0x89, 0xa8, 0xe1, 0xb8, 0x72, 0x4b, 0x1a, + 0x33, 0x14, 0xc4, 0xca, 0xcc, 0x4b, 0xb8, 0xf3, 0x90, 0x43, 0x97, 0x01, + 0xa6, 0x14, 0xae, 0x9b, 0xcd, 0xaf, 0xd4, 0x72, 0xb0, 0xab, 0x13, 0x16, + 0x67, 0xdb, 0xbf, 0x1c, 0x79, 0x0f, 0x73, 0xab, 0x90, 0x46, 0xa5, 0x89, + 0x32, 0x69, 0x1a, 0x93, 0x0b, 0x3c, 0x42, 0xe9, 0x08, 0xb4, 0xd1, 0xf4, + 0x7e, 0xd6, 0xe2, 0xff, 0x18, 0xd6, 0xb7, 0x0b, 0xb1, 0x6d, 0x1a, 0xf7, + 0x99, 0x3b, 0xdb, 0x2c, 0xa3, 0xcb, 0x35, 0x9a, 0x0b, 0x43, 0xf8, 0xdc, + 0x84, 0x4d, 0xea, 0x6a, 0xeb, 0xaa, 0x34, 0xb8, 0xd2, 0xb6, 0xfc, 0x28, + 0x84, 0x19, 0x78, 0x0f, 0xf9, 0x80, 0x90, 0x89, 0x26, 0xc4, 0x6c, 0x3b, + 0x0e, 0x59, 0x5f, 0xa3, 0x08, 0xf4, 0xe8, 0x94, 0xec, 0xb6, 0x83, 0xc8, + 0x04, 0xc9, 0x31, 0x40, 0xd9, 0x17, 0x69, 0x13, 0x2d, 0x37, 0xe9, 0x37, + 0x91, 0xb9, 0xf8, 0x9d, 0x59, 0x5e, 0x69, 0x8f, 0x04, 0x9b, 0x3a, 0x95, + 0x02, 0xab, 0xc4, 0x88, 0xbd, 0xd9, 0x47, 0x2f, 0x11, 0x31, 0xa7, 0x57, + 0xf3, 0xd5, 0x4b, 0x14, 0x90, 0x67, 0x50, 0x7d, 0x1b, 0x04, 0xa9, 0x76 +}; +/* K = a3fb61e544d59206d334049e8554d97b6699db616871fd2b421229c28e84f73c */ +static const uint8_t ac_dsa_vect278_out[] = { +/* R */ + 0x9e, 0x83, 0x3e, 0xc3, 0xde, 0xd9, 0xd8, 0x1e, 0xa7, 0x42, 0x2b, 0xda, + 0xc7, 0x84, 0x22, 0x27, 0x4f, 0xa3, 0x53, 0x48, 0xe3, 0xfc, 0xe3, 0xbb, + 0xc9, 0x3b, 0x3c, 0x10, 0xd7, 0x0b, 0x4f, 0x1e, +/* S */ + 0x65, 0x37, 0x56, 0x59, 0x4e, 0xac, 0x68, 0x1d, 0x48, 0xa2, 0x35, 0x8a, + 0x0f, 0x82, 0xa1, 0x0f, 0xaa, 0x79, 0x29, 0xb0, 0x0f, 0xd9, 0xcd, 0x43, + 0x94, 0xc3, 0x26, 0x79, 0x06, 0x0f, 0x96, 0xe3 +}; +#define ac_dsa_vect279_prime ac_dsa_vect271_prime +#define ac_dsa_vect279_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect279_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect279_ptx[] = { +/* Msg */ + 0x33, 0xde, 0xcf, 0xc1, 0xe0, 0x6b, 0x92, 0xed, 0x81, 0xcd, 0x30, 0xee, + 0x37, 0x71, 0x47, 0x0b, 0x59, 0xe2, 0x2c, 0x15, 0x64, 0x64, 0x7f, 0x1a, + 0xae, 0x85, 0x10, 0x72, 0x97, 0x15, 0xa8, 0xce, 0x94, 0x62, 0x4a, 0x11, + 0x55, 0x4a, 0xc9, 0x09, 0xc9, 0x24, 0xae, 0xc8, 0x53, 0xdf, 0x64, 0x32, + 0x75, 0x46, 0xdb, 0x85, 0xd3, 0xdf, 0x59, 0x79, 0x16, 0xa3, 0x93, 0x53, + 0x38, 0x8a, 0x8b, 0x33, 0x63, 0x76, 0x52, 0x81, 0xa4, 0x35, 0x27, 0x01, + 0xff, 0x1a, 0xf4, 0x3f, 0xba, 0x6d, 0x03, 0x66, 0x41, 0x27, 0xc1, 0x5d, + 0xa7, 0xb8, 0x4c, 0x04, 0xd5, 0x40, 0x9c, 0x36, 0x40, 0x94, 0xdc, 0x62, + 0xe3, 0x79, 0x83, 0xa8, 0xeb, 0x06, 0x68, 0x80, 0xde, 0x81, 0x36, 0x70, + 0x14, 0x06, 0xe6, 0x72, 0x50, 0x67, 0x93, 0x00, 0xd2, 0xb9, 0x7d, 0x22, + 0x83, 0x27, 0xc1, 0x51, 0x4c, 0x0b, 0xc1, 0xea +}; +static const uint8_t ac_dsa_vect279_priv_val[] = { +/* X */ + 0x3b, 0xf2, 0xbe, 0x01, 0xd1, 0x54, 0xc2, 0x3c, 0xca, 0xe9, 0x2a, 0xe9, + 0x3f, 0x78, 0xea, 0x36, 0xf7, 0x0e, 0xfc, 0xf7, 0xfb, 0x7e, 0xb4, 0x3c, + 0xdc, 0xae, 0xb9, 0xff, 0xb8, 0x47, 0x1b, 0x10 +}; +static const uint8_t ac_dsa_vect279_pub_val[] = { +/* Y */ + 0x16, 0xea, 0x2e, 0x79, 0x5c, 0x63, 0x6c, 0x9d, 0x31, 0x21, 0x59, 0xa5, + 0x79, 0xb8, 0xdf, 0x32, 0x9f, 0xfc, 0x28, 0xfe, 0xcc, 0x4a, 0x4c, 0x13, + 0xb1, 0x6a, 0x29, 0x0b, 0xd1, 0x52, 0x5a, 0x53, 0xa9, 0x7d, 0x72, 0x31, + 0x5b, 0xe2, 0x51, 0xd1, 0x1d, 0x23, 0xca, 0x78, 0xbb, 0xec, 0x45, 0xc0, + 0xe2, 0x43, 0x27, 0x9b, 0x1e, 0xb6, 0xe2, 0x06, 0xa9, 0x27, 0x3c, 0x1e, + 0x76, 0x6e, 0x21, 0x36, 0x48, 0xbd, 0xf9, 0x0c, 0x40, 0x47, 0x9d, 0xf4, + 0x8a, 0xcf, 0xd9, 0xc2, 0x09, 0xa5, 0x23, 0xc8, 0xb4, 0xa9, 0x9a, 0x48, + 0x1c, 0xa8, 0xdf, 0x47, 0x74, 0xb3, 0xbb, 0x29, 0xf8, 0x25, 0x26, 0x52, + 0x0c, 0x2d, 0xc2, 0x8a, 0xb3, 0x14, 0xfe, 0x14, 0x14, 0x0f, 0x2b, 0xe1, + 0x79, 0x2e, 0x1a, 0xc3, 0xc7, 0x59, 0xad, 0x44, 0xf7, 0x84, 0x5a, 0x20, + 0x12, 0xf6, 0x4e, 0xca, 0xb0, 0xb1, 0xfe, 0xc0, 0xed, 0x16, 0x6b, 0xd1, + 0x75, 0x95, 0x57, 0x04, 0xf6, 0x2d, 0x94, 0x01, 0x11, 0x1f, 0xfc, 0x04, + 0xf8, 0x04, 0xe4, 0x8f, 0xe7, 0x74, 0xdf, 0xd3, 0x46, 0xbb, 0x41, 0xf4, + 0xbe, 0xca, 0x2b, 0x34, 0xa8, 0x31, 0x34, 0xa3, 0x88, 0x4a, 0x01, 0x72, + 0x9c, 0xce, 0x1a, 0xbc, 0x5b, 0x8d, 0x0d, 0xe3, 0xfe, 0x26, 0x54, 0xc3, + 0x74, 0xde, 0xb2, 0x46, 0xd9, 0x6f, 0xfa, 0xff, 0xc7, 0xaa, 0x20, 0x55, + 0xb7, 0x4e, 0x81, 0x9b, 0xbe, 0xec, 0x13, 0x7e, 0xb3, 0xca, 0xed, 0x1f, + 0xc7, 0x1f, 0x12, 0x9c, 0x8e, 0xa8, 0xb7, 0x63, 0xf2, 0xf5, 0x7e, 0x88, + 0xde, 0x08, 0x45, 0xf7, 0x6c, 0xeb, 0x18, 0x41, 0x55, 0x90, 0x19, 0x87, + 0x2a, 0x5b, 0x5a, 0x96, 0x9c, 0x9c, 0xf3, 0x85, 0xd6, 0x57, 0x8b, 0x4f, + 0x27, 0xb5, 0xb7, 0x6b, 0xe3, 0xef, 0x0a, 0x8f, 0xd3, 0xee, 0x47, 0xee, + 0xd6, 0x95, 0xe1, 0x6f, 0x14, 0xe2, 0xa3, 0xb7, 0x91, 0xf2, 0xa0, 0x16, + 0xd6, 0xb8, 0x6f, 0xf8, 0xec, 0x23, 0x43, 0xc6, 0xa5, 0xc8, 0x0a, 0xb6, + 0x22, 0x4b, 0x65, 0x02, 0xeb, 0x37, 0x4c, 0x8f, 0xa6, 0x51, 0x0b, 0xce, + 0x99, 0x0d, 0x70, 0xef, 0xdf, 0xa9, 0xa0, 0xb7, 0x02, 0x58, 0x55, 0x95, + 0x18, 0x45, 0x14, 0xc7, 0x8f, 0x7e, 0x90, 0x5b, 0x6f, 0xd6, 0xc2, 0x37, + 0x33, 0x3d, 0x56, 0x0f, 0xcc, 0x06, 0x30, 0x36, 0x37, 0xac, 0x0b, 0x2c, + 0x7f, 0x7c, 0x4d, 0xa5, 0x59, 0xe3, 0x1f, 0x53, 0x1d, 0xf2, 0xe5, 0xd6, + 0xc6, 0x51, 0x59, 0x17, 0x71, 0xd7, 0xea, 0x45, 0x75, 0x88, 0x8a, 0xfc, + 0x40, 0x11, 0xfa, 0x11, 0x24, 0xfb, 0xd1, 0xa2, 0x82, 0xa4, 0x1d, 0x93, + 0x39, 0x89, 0xef, 0xf9, 0x1a, 0x51, 0xcd, 0x39, 0xbc, 0xe7, 0xfb, 0x0d, + 0x56, 0x9f, 0xed, 0xcc, 0x42, 0xde, 0x48, 0xbf, 0x18, 0xee, 0x75, 0x5f +}; +/* K = a0c97f80ca449fd8f69733e046664408da590dbbab6865c3275c389a478aa248 */ +static const uint8_t ac_dsa_vect279_out[] = { +/* R */ + 0x6f, 0x77, 0xa5, 0x21, 0x69, 0xa2, 0xe8, 0x80, 0xa3, 0xb5, 0x5a, 0xa2, + 0x78, 0xf6, 0x46, 0x30, 0x32, 0xdc, 0x5f, 0x81, 0xc3, 0x84, 0x68, 0x22, + 0x4d, 0x55, 0x32, 0xf6, 0xa6, 0x01, 0xf2, 0xd9, +/* S */ + 0x96, 0xb7, 0x53, 0xef, 0xb4, 0xab, 0xbc, 0x8c, 0x17, 0x9d, 0x03, 0xcc, + 0x2a, 0x1a, 0x0c, 0x12, 0x56, 0xe2, 0x3d, 0x1f, 0xa2, 0xe9, 0x7c, 0xfb, + 0xf5, 0x5d, 0x2b, 0xb6, 0x98, 0x12, 0xd1, 0x00 +}; +#define ac_dsa_vect280_prime ac_dsa_vect271_prime +#define ac_dsa_vect280_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect280_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect280_ptx[] = { +/* Msg */ + 0x6a, 0xe5, 0xa6, 0xda, 0x79, 0x4f, 0x92, 0x3f, 0x6d, 0x80, 0x32, 0x54, + 0x9b, 0x81, 0xd0, 0x4a, 0xe7, 0xaa, 0x35, 0xc2, 0x09, 0x9d, 0xff, 0xbd, + 0xd8, 0x3b, 0xb9, 0x4d, 0xb5, 0x74, 0xfa, 0xf8, 0xf9, 0x5c, 0x71, 0x26, + 0xdb, 0x2d, 0xb6, 0x0f, 0xed, 0x50, 0xf7, 0x40, 0xe8, 0x7c, 0x35, 0x95, + 0x44, 0xdc, 0x2e, 0xbf, 0xbc, 0xaf, 0xb0, 0x94, 0xdd, 0xca, 0x69, 0xc9, + 0x14, 0xd2, 0x7e, 0x5f, 0x3d, 0x10, 0xfa, 0x0c, 0xe3, 0x2d, 0x2a, 0x13, + 0x55, 0xbc, 0xf6, 0x1a, 0x25, 0x74, 0xc7, 0x55, 0xd7, 0xc3, 0x24, 0xa2, + 0xe0, 0xed, 0x6f, 0x77, 0x19, 0xba, 0x2f, 0x2c, 0x9f, 0x11, 0x3d, 0xf8, + 0xd0, 0x40, 0x25, 0xf4, 0xab, 0xd2, 0xe1, 0xc4, 0xb7, 0xbc, 0x18, 0xd8, + 0xac, 0xec, 0x9f, 0x6d, 0x8d, 0x79, 0x7c, 0xd7, 0xb0, 0x42, 0xf5, 0x03, + 0x48, 0xee, 0xb3, 0xf7, 0xa2, 0x92, 0x2d, 0xa7 +}; +static const uint8_t ac_dsa_vect280_priv_val[] = { +/* X */ + 0x3b, 0x4a, 0x52, 0xc8, 0xb5, 0xc3, 0x86, 0xf2, 0x6a, 0xc6, 0xff, 0xab, + 0xce, 0xf2, 0xdf, 0x3b, 0xf8, 0xb2, 0x5e, 0x61, 0x08, 0xab, 0x54, 0x0d, + 0x31, 0x4d, 0xd3, 0xd9, 0x24, 0x5c, 0x07, 0x5d +}; +static const uint8_t ac_dsa_vect280_pub_val[] = { +/* Y */ + 0x93, 0x10, 0x6f, 0xb0, 0x00, 0xc6, 0x7f, 0x11, 0x11, 0xc6, 0xfd, 0x3d, + 0xa0, 0xf4, 0x4b, 0x4a, 0xe4, 0xcb, 0x36, 0x95, 0xde, 0x2e, 0x35, 0xb2, + 0x41, 0xdf, 0xe8, 0x8d, 0x32, 0x69, 0xb8, 0xfd, 0xa2, 0x5b, 0xf3, 0x48, + 0x00, 0x87, 0x25, 0xfd, 0x61, 0x3c, 0xd6, 0x1a, 0xa8, 0x26, 0xbd, 0x8f, + 0x1a, 0xaa, 0xee, 0x22, 0xb4, 0xdc, 0x0a, 0x02, 0x84, 0x22, 0x90, 0xbb, + 0x7d, 0xad, 0x91, 0xaf, 0x0b, 0x28, 0x54, 0xff, 0xab, 0x16, 0x93, 0x22, + 0x08, 0xd2, 0x72, 0xf2, 0xc0, 0x81, 0xc1, 0x38, 0x89, 0xdb, 0x3e, 0xd0, + 0xb2, 0x46, 0x46, 0xc6, 0x65, 0xaf, 0x9f, 0x4b, 0x72, 0x38, 0x98, 0xeb, + 0x1a, 0xc0, 0x05, 0x3f, 0x2a, 0x0f, 0x4c, 0xf2, 0x2f, 0xd4, 0xe1, 0x29, + 0x40, 0xb5, 0xb5, 0x22, 0x69, 0x48, 0x4e, 0xbb, 0x8a, 0xbc, 0x48, 0x4c, + 0x06, 0xed, 0xdb, 0xd9, 0xb1, 0xa4, 0x26, 0x13, 0x2f, 0x40, 0x2e, 0xfd, + 0xcd, 0x88, 0xab, 0x29, 0xe7, 0xe5, 0x10, 0x96, 0x1a, 0xf8, 0xec, 0x83, + 0xa6, 0x42, 0xe3, 0x40, 0x15, 0x85, 0x8a, 0xc3, 0xf3, 0x21, 0x97, 0x60, + 0x1a, 0x88, 0x8e, 0x16, 0xc7, 0x59, 0xc9, 0x4e, 0xc5, 0xb8, 0xde, 0xc0, + 0xda, 0x30, 0x64, 0x3b, 0x9d, 0x9d, 0xb2, 0x57, 0x4a, 0xf2, 0x9e, 0x78, + 0xf9, 0xd3, 0xf6, 0xa7, 0xb4, 0xc7, 0x6f, 0x45, 0xcd, 0x0b, 0x2a, 0xb5, + 0xe8, 0x52, 0x49, 0x35, 0xb8, 0x86, 0x91, 0x8b, 0x5d, 0x9e, 0x9c, 0xcb, + 0x5a, 0x68, 0x53, 0xe6, 0x2e, 0xfa, 0xd2, 0xdf, 0xf8, 0x3a, 0x85, 0x20, + 0x98, 0x5e, 0xe8, 0x44, 0x2f, 0x2b, 0xdd, 0x1c, 0x5f, 0x9d, 0x48, 0x06, + 0x2a, 0xde, 0x6b, 0x28, 0x8c, 0x8a, 0xd8, 0x2a, 0x41, 0xdb, 0x6c, 0x34, + 0xe2, 0xde, 0xba, 0x54, 0x1a, 0xaa, 0xc3, 0xcd, 0x31, 0x56, 0xc9, 0x75, + 0xef, 0xbb, 0xc7, 0x18, 0xeb, 0xd4, 0x96, 0x19, 0x96, 0xb3, 0xed, 0x1c, + 0xc5, 0xc2, 0x98, 0x7a, 0xb7, 0x79, 0x05, 0x2c, 0xdb, 0xec, 0xf5, 0x1d, + 0x17, 0x66, 0x1b, 0x49, 0x8e, 0x84, 0x37, 0x1f, 0xf8, 0x59, 0xf8, 0x99, + 0x06, 0xf4, 0x26, 0xf5, 0x63, 0x57, 0x2f, 0x66, 0xc2, 0x79, 0xef, 0x3d, + 0x03, 0x6a, 0x42, 0x77, 0x78, 0x46, 0x3f, 0x67, 0xf8, 0xd4, 0xde, 0x62, + 0x3f, 0xb4, 0xb2, 0x80, 0x30, 0x07, 0x87, 0x1d, 0x0a, 0x34, 0x9e, 0xc2, + 0x02, 0xa9, 0xaa, 0x1c, 0xff, 0xef, 0x70, 0x13, 0x7e, 0x00, 0x93, 0x03, + 0x49, 0x72, 0x14, 0xad, 0xa7, 0x86, 0x35, 0x7a, 0x4d, 0x80, 0x46, 0x25, + 0x5e, 0x40, 0xf8, 0x9e, 0xa5, 0x88, 0x00, 0x06, 0x34, 0xe7, 0xf0, 0xaa, + 0xf6, 0x4d, 0x92, 0xaa, 0x21, 0xff, 0xf8, 0xfb, 0xe0, 0x78, 0xba, 0xa9, + 0x69, 0x61, 0x69, 0x97, 0x38, 0xb2, 0x68, 0x23, 0x7e, 0xab, 0x60, 0x6c +}; +/* K = 39f68875cade6ae208d3043b010541624679df649cc5d97b09a3ebbe2c9d59be */ +static const uint8_t ac_dsa_vect280_out[] = { +/* R */ + 0x86, 0x36, 0xd4, 0xd3, 0x20, 0x3a, 0xa0, 0x91, 0x2f, 0xbf, 0xc9, 0x38, + 0xbe, 0x43, 0x70, 0x07, 0x7e, 0xa9, 0xc7, 0x51, 0x95, 0xcd, 0x2f, 0x67, + 0xe6, 0xee, 0x42, 0x7c, 0xde, 0x53, 0x1c, 0x40, +/* S */ + 0x93, 0x02, 0x3d, 0x97, 0xef, 0xb4, 0x32, 0x7e, 0x9e, 0x88, 0x6e, 0x7b, + 0x78, 0x37, 0x41, 0xe9, 0xd2, 0xc3, 0x97, 0xaf, 0x9c, 0x67, 0xb9, 0x1c, + 0xdb, 0x8a, 0xa2, 0x7f, 0x83, 0xbb, 0x02, 0x5d +}; +#define ac_dsa_vect281_prime ac_dsa_vect271_prime +#define ac_dsa_vect281_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect281_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect281_ptx[] = { +/* Msg */ + 0x86, 0xe0, 0x3b, 0xc3, 0xf4, 0xdd, 0xea, 0x6a, 0x93, 0x88, 0x8e, 0xe3, + 0x89, 0xb1, 0x5e, 0xb6, 0x90, 0x82, 0x2c, 0x71, 0xf9, 0xb8, 0x5e, 0xfa, + 0xaf, 0xfc, 0x52, 0xe4, 0x86, 0xb1, 0x14, 0x4a, 0xd7, 0xfc, 0xff, 0x3f, + 0x53, 0xbf, 0x97, 0xda, 0x24, 0x81, 0xe8, 0x5e, 0x09, 0x83, 0xee, 0x1d, + 0x52, 0x79, 0xe2, 0x7a, 0x36, 0x4d, 0x0e, 0x69, 0x0f, 0x58, 0x7a, 0x31, + 0x53, 0x5f, 0xb9, 0x4e, 0xec, 0xe7, 0x47, 0xf8, 0xb6, 0x05, 0x72, 0x4a, + 0xdf, 0xb2, 0x58, 0xc9, 0x98, 0x3c, 0x90, 0x02, 0xe0, 0xc1, 0x1b, 0x79, + 0x76, 0x62, 0x76, 0x90, 0xd5, 0x82, 0x81, 0x30, 0x5e, 0xa9, 0x30, 0x8d, + 0xb7, 0x4c, 0x49, 0x1a, 0x28, 0x19, 0x2e, 0x35, 0x4b, 0x60, 0x0e, 0x83, + 0x76, 0x81, 0x1c, 0xce, 0xfb, 0x75, 0x1b, 0xb1, 0x0c, 0x7d, 0x97, 0xb4, + 0x2f, 0xfe, 0x30, 0x4b, 0xee, 0x97, 0xec, 0xaf +}; +static const uint8_t ac_dsa_vect281_priv_val[] = { +/* X */ + 0x7f, 0x56, 0xc7, 0x4b, 0x49, 0x5a, 0x12, 0xdb, 0x96, 0x3e, 0x03, 0xcf, + 0xaf, 0xe6, 0x0a, 0xc9, 0x5e, 0x80, 0x19, 0xcb, 0x21, 0x2c, 0x33, 0x2d, + 0x1f, 0x19, 0xc6, 0x46, 0x15, 0x56, 0x81, 0x19 +}; +static const uint8_t ac_dsa_vect281_pub_val[] = { +/* Y */ + 0x23, 0xed, 0x54, 0x45, 0x39, 0x1a, 0x5b, 0xb9, 0x4e, 0x00, 0xc7, 0x6e, + 0xc8, 0x0d, 0x83, 0x72, 0x8d, 0x5d, 0x46, 0x1b, 0xe4, 0x25, 0xda, 0x79, + 0xf9, 0x21, 0xbc, 0xa2, 0x7d, 0x62, 0x5c, 0xb4, 0x2b, 0x32, 0x39, 0x71, + 0x02, 0x2a, 0xd4, 0xc3, 0xf0, 0x5b, 0xca, 0x10, 0x99, 0x10, 0xfd, 0x06, + 0xba, 0x39, 0xe9, 0x5b, 0xeb, 0xe7, 0x94, 0xed, 0x10, 0x8d, 0x2e, 0xad, + 0x29, 0x7a, 0xd7, 0x94, 0xf9, 0x9c, 0x32, 0xc2, 0x19, 0xe6, 0x5f, 0xb7, + 0x26, 0x53, 0x27, 0x15, 0xb1, 0xbc, 0x20, 0x75, 0xdd, 0x4b, 0x69, 0x49, + 0x29, 0x77, 0x12, 0xf9, 0x1d, 0x5b, 0xa0, 0x61, 0x19, 0x6f, 0xb2, 0x57, + 0x54, 0xc3, 0x43, 0x77, 0xbb, 0xbe, 0x6a, 0x37, 0xf6, 0x17, 0x87, 0xea, + 0x84, 0x4d, 0x35, 0x92, 0x85, 0xc7, 0x8e, 0x73, 0x3e, 0xb6, 0x5f, 0x66, + 0x5a, 0x6b, 0x15, 0x7f, 0x83, 0x2b, 0x56, 0x38, 0xd7, 0x4e, 0xbe, 0x1d, + 0x5d, 0xce, 0x66, 0xd5, 0x28, 0x92, 0x5e, 0x44, 0xee, 0xf1, 0x3b, 0xf2, + 0x3f, 0x80, 0x7d, 0xa3, 0x5f, 0x34, 0xd1, 0x69, 0xa6, 0x87, 0x75, 0x82, + 0x29, 0xb9, 0x9a, 0x31, 0x3a, 0xce, 0xcf, 0xb2, 0x0b, 0x14, 0x2b, 0x53, + 0x49, 0x26, 0xd5, 0x9a, 0xaa, 0x76, 0x43, 0xa7, 0x90, 0x30, 0xe9, 0x33, + 0x5e, 0xf2, 0x8a, 0xbe, 0xdd, 0xac, 0x8a, 0xc9, 0x47, 0x1d, 0xa4, 0x99, + 0x7e, 0x33, 0xf3, 0xe4, 0x91, 0xdb, 0x86, 0x68, 0xa2, 0xc3, 0x92, 0x0a, + 0x3b, 0x3a, 0x37, 0x22, 0x51, 0x79, 0x36, 0x1d, 0x55, 0x39, 0xbe, 0xb3, + 0x3f, 0x32, 0x52, 0x24, 0x42, 0x67, 0x46, 0x5e, 0x48, 0xfa, 0xf5, 0x75, + 0xcd, 0xac, 0x93, 0x81, 0x33, 0xef, 0xfe, 0x9d, 0x1f, 0x69, 0xf1, 0x9f, + 0x1b, 0x44, 0xb2, 0x45, 0xa4, 0x47, 0xb1, 0xfc, 0x2b, 0x85, 0x92, 0x44, + 0xe2, 0xe3, 0x90, 0x53, 0x59, 0x5c, 0xf7, 0x97, 0x89, 0x33, 0xc3, 0xd4, + 0x68, 0xc6, 0x5c, 0x23, 0x16, 0x63, 0x07, 0x0a, 0xea, 0xf2, 0xec, 0x23, + 0x13, 0x8d, 0x16, 0x60, 0x08, 0x1a, 0x55, 0xbd, 0xc3, 0xdd, 0x3f, 0x24, + 0x46, 0x17, 0x6b, 0x1d, 0x6d, 0x99, 0x77, 0xa1, 0x4e, 0xbd, 0x0e, 0xd4, + 0xd8, 0xdf, 0xcd, 0xfc, 0x4a, 0x43, 0x31, 0x18, 0x40, 0x1f, 0x2c, 0x26, + 0x32, 0x09, 0x5c, 0xe7, 0xae, 0x62, 0x00, 0xc7, 0x4b, 0xda, 0x5d, 0x2f, + 0xd3, 0x85, 0x45, 0x24, 0xc3, 0x08, 0x17, 0x41, 0x97, 0x5a, 0x07, 0x6a, + 0x1b, 0x4f, 0x93, 0x3e, 0xc3, 0x2a, 0x2b, 0xac, 0x91, 0x71, 0xbe, 0xbf, + 0xdf, 0x3b, 0x35, 0x5e, 0xdd, 0xb1, 0xf4, 0x55, 0xec, 0xaf, 0x73, 0x39, + 0x6e, 0x85, 0xfb, 0x04, 0x79, 0x75, 0x58, 0xba, 0x4f, 0x2b, 0xbc, 0x49, + 0xd9, 0xf2, 0x32, 0x9a, 0x23, 0xb3, 0x93, 0x30, 0x1a, 0xe0, 0xdb, 0x92 +}; +/* K = 407180cc311aebdc1cdcb4685241597783f34076672362a24a21193c0d45d24d */ +static const uint8_t ac_dsa_vect281_out[] = { +/* R */ + 0x68, 0xef, 0xaa, 0x05, 0xeb, 0x90, 0xc4, 0x8c, 0x6a, 0x7a, 0x45, 0x33, + 0x7c, 0x29, 0x17, 0x5f, 0x8e, 0xe5, 0xb1, 0x9b, 0x53, 0xdb, 0x4e, 0xbd, + 0x83, 0xa0, 0x2f, 0x53, 0xc5, 0xb2, 0x10, 0x4b, +/* S */ + 0x14, 0x5f, 0x13, 0xf1, 0xae, 0x36, 0x75, 0xc5, 0x21, 0xb3, 0x34, 0xce, + 0x6a, 0x49, 0xfc, 0x6f, 0x50, 0x2e, 0x3a, 0xc6, 0xb2, 0xb5, 0x14, 0x3b, + 0xe0, 0x64, 0x1d, 0x0d, 0x57, 0xb3, 0xc7, 0x22 +}; +#define ac_dsa_vect282_prime ac_dsa_vect271_prime +#define ac_dsa_vect282_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect282_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect282_ptx[] = { +/* Msg */ + 0x1d, 0x09, 0x54, 0xee, 0x0d, 0xe1, 0xe9, 0xce, 0xee, 0x05, 0x32, 0x59, + 0x7e, 0xe4, 0x34, 0xc7, 0x3f, 0xe4, 0xf6, 0x66, 0x35, 0xf7, 0xe7, 0x2d, + 0x38, 0xb6, 0x77, 0x63, 0xc6, 0x68, 0x17, 0xf5, 0x3c, 0xf3, 0x6c, 0xa0, + 0xf6, 0x13, 0xe0, 0x18, 0x96, 0xce, 0xbc, 0x9f, 0x77, 0xa7, 0x72, 0x60, + 0x7f, 0x4a, 0xee, 0xdd, 0x38, 0x56, 0xc7, 0x3f, 0xc2, 0xf1, 0x91, 0x00, + 0xaa, 0x7b, 0x54, 0x0c, 0xcd, 0x05, 0x7f, 0x26, 0xcd, 0x95, 0x64, 0xd6, + 0x73, 0x22, 0x8c, 0x68, 0x08, 0x8e, 0x5f, 0x1a, 0xbf, 0x12, 0x54, 0xa9, + 0x7e, 0xd1, 0x45, 0x3e, 0xe5, 0x58, 0xe0, 0x62, 0x71, 0x1c, 0xeb, 0x76, + 0x43, 0xb3, 0x45, 0xad, 0x33, 0xb6, 0x49, 0xaf, 0xfb, 0xe8, 0xa6, 0x20, + 0x67, 0xf9, 0xd8, 0x4e, 0xd4, 0xc8, 0x50, 0x6f, 0xcf, 0xf5, 0x78, 0xd2, + 0xeb, 0xa5, 0x96, 0xa2, 0x05, 0x26, 0x73, 0x87 +}; +static const uint8_t ac_dsa_vect282_priv_val[] = { +/* X */ + 0x0b, 0x48, 0x49, 0x96, 0x25, 0xf0, 0xc2, 0x54, 0x8b, 0xf8, 0xa2, 0xfe, + 0xd1, 0xf6, 0x69, 0x6f, 0x59, 0xdf, 0x8f, 0xbe, 0x6e, 0xaf, 0x91, 0xb8, + 0x23, 0x85, 0x99, 0x42, 0x09, 0xc2, 0xd0, 0x4f +}; +static const uint8_t ac_dsa_vect282_pub_val[] = { +/* Y */ + 0x2f, 0x0d, 0x89, 0xac, 0x78, 0xa6, 0x1f, 0xb7, 0x4f, 0x81, 0x14, 0x2b, + 0x17, 0x76, 0x66, 0x56, 0xd1, 0x78, 0x89, 0x40, 0x07, 0x78, 0x08, 0xe3, + 0xd8, 0x80, 0xce, 0x10, 0xec, 0x60, 0xe2, 0xbb, 0xb1, 0x58, 0xd5, 0x4e, + 0x02, 0x0d, 0xbc, 0x5f, 0x67, 0x86, 0xc0, 0xb4, 0x3c, 0xca, 0x2c, 0xb0, + 0x02, 0xc8, 0xce, 0x13, 0xb2, 0x91, 0xb2, 0x50, 0xf3, 0x99, 0xe8, 0xe0, + 0x2f, 0x19, 0x59, 0x26, 0x97, 0x8f, 0x6c, 0x5b, 0x00, 0x7d, 0x4f, 0x0a, + 0x66, 0x04, 0x89, 0x96, 0xa9, 0x93, 0x2a, 0x91, 0x8b, 0x23, 0x63, 0xc4, + 0x00, 0x8f, 0x54, 0x7a, 0xdc, 0xaa, 0x7d, 0x12, 0x69, 0x4b, 0xae, 0xe4, + 0xfb, 0xca, 0x34, 0xbc, 0x6d, 0x7e, 0x29, 0xc5, 0x04, 0x9c, 0xda, 0x13, + 0x69, 0x8f, 0xcc, 0xe6, 0x1b, 0xd3, 0xb3, 0xdb, 0x05, 0xd2, 0x15, 0x81, + 0x32, 0xdd, 0x38, 0x0c, 0xf6, 0x53, 0xcc, 0xcd, 0xf2, 0x79, 0xaa, 0x16, + 0x41, 0x34, 0xbf, 0xbd, 0xdd, 0x7e, 0xa3, 0x47, 0x76, 0x00, 0x41, 0xf9, + 0x2c, 0x3a, 0x4c, 0xfd, 0xe0, 0x09, 0x2d, 0x5c, 0xb9, 0x6b, 0xb8, 0xc2, + 0x4e, 0x98, 0x25, 0x94, 0x75, 0x59, 0x6f, 0x33, 0x77, 0xd5, 0x9f, 0x11, + 0x66, 0x1b, 0xcc, 0x0d, 0x47, 0xe8, 0x3c, 0xb3, 0x1a, 0xae, 0x9d, 0xcb, + 0x4a, 0x6f, 0x25, 0x61, 0x9a, 0x29, 0x05, 0x4b, 0x62, 0xaa, 0x8b, 0x42, + 0x1e, 0x52, 0x9e, 0x61, 0xac, 0x95, 0xa0, 0xde, 0x01, 0xc5, 0x0b, 0x09, + 0xe1, 0x19, 0x51, 0x6c, 0x2c, 0x5b, 0x35, 0x63, 0xd4, 0x7e, 0xed, 0x67, + 0x9a, 0x1c, 0xf8, 0x0b, 0xa7, 0x0a, 0x50, 0x25, 0x4d, 0x85, 0x1a, 0x13, + 0xa7, 0x78, 0xe1, 0xa0, 0x8d, 0xa8, 0x66, 0x7e, 0x46, 0xe3, 0x59, 0x79, + 0xc1, 0x5d, 0xf4, 0x5c, 0xf7, 0x88, 0x6d, 0xde, 0x5a, 0xf9, 0xd7, 0x44, + 0x62, 0x4b, 0x98, 0x1a, 0xcd, 0x25, 0x2e, 0xc5, 0xba, 0x46, 0x87, 0x0b, + 0x8e, 0xe4, 0xb3, 0x2b, 0x1b, 0xe1, 0xb9, 0x44, 0x80, 0x2d, 0x91, 0xd8, + 0x14, 0x8d, 0x38, 0xf5, 0x43, 0x15, 0xa7, 0xad, 0x4e, 0x38, 0x07, 0x9e, + 0xa2, 0xbe, 0xd9, 0xdf, 0x8f, 0xa5, 0x94, 0x14, 0xdd, 0xde, 0xd3, 0xa1, + 0xd2, 0x30, 0x8b, 0xa7, 0x69, 0xae, 0x2a, 0x65, 0x2f, 0x10, 0xc2, 0xd9, + 0x69, 0x17, 0xed, 0xfe, 0x58, 0x74, 0x88, 0x5f, 0x3c, 0x99, 0xd6, 0x91, + 0x2f, 0x69, 0xae, 0x3f, 0xc3, 0xb4, 0xde, 0x82, 0xde, 0xcc, 0x30, 0xed, + 0xc9, 0x31, 0x4f, 0x7e, 0xc9, 0xe5, 0x67, 0xb7, 0xe0, 0x0d, 0xe2, 0x19, + 0x59, 0x48, 0x6a, 0x88, 0x7d, 0x74, 0xa5, 0xb2, 0x18, 0x02, 0x93, 0xdf, + 0x5d, 0xbe, 0xae, 0x1e, 0x35, 0xa6, 0xe9, 0x37, 0xb2, 0x50, 0x6d, 0x20, + 0x50, 0x92, 0xcc, 0x4c, 0x35, 0x95, 0xdb, 0x92, 0xfc, 0x25, 0x5a, 0xf5 +}; +/* K = 1c020abb0e1d52b3ad95467f7baaf665e2281f34c342401ef1fb4c1fc2d7b2bd */ +static const uint8_t ac_dsa_vect282_out[] = { +/* R */ + 0xa6, 0x72, 0x10, 0x34, 0x1a, 0x04, 0xcd, 0x3a, 0x4b, 0x63, 0xeb, 0xc7, + 0xe6, 0x20, 0x8f, 0x37, 0xe4, 0x87, 0xa8, 0xc6, 0xf1, 0x13, 0x4c, 0xd2, + 0x60, 0x1b, 0x84, 0x4d, 0x69, 0x03, 0x20, 0x3f, +/* S */ + 0x6b, 0x97, 0x2c, 0x62, 0x2c, 0xab, 0x48, 0xd8, 0x5a, 0x2d, 0xde, 0x35, + 0x5f, 0x94, 0x7a, 0x81, 0x51, 0xa1, 0x7a, 0x0a, 0xcf, 0x06, 0xb7, 0xf3, + 0x65, 0x9f, 0x86, 0x8d, 0x5e, 0xce, 0x92, 0xd9 +}; +#define ac_dsa_vect283_prime ac_dsa_vect271_prime +#define ac_dsa_vect283_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect283_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect283_ptx[] = { +/* Msg */ + 0x14, 0xf5, 0x66, 0xc5, 0xfe, 0x44, 0xaa, 0xad, 0x6e, 0x8b, 0x3c, 0x62, + 0x75, 0x70, 0xaa, 0xbd, 0xd4, 0xef, 0xb7, 0xfc, 0xfa, 0x1a, 0xb1, 0xbb, + 0x74, 0xf2, 0xc6, 0xd8, 0x79, 0x5e, 0x88, 0x23, 0x3d, 0xac, 0x4e, 0x7d, + 0x24, 0x0a, 0xbd, 0x5e, 0x9b, 0xbd, 0x8e, 0x1f, 0xb0, 0x3a, 0x3b, 0xf5, + 0x0c, 0x0c, 0xa9, 0x2c, 0x9a, 0xef, 0x18, 0x94, 0xf2, 0xae, 0xd6, 0x00, + 0xfc, 0x58, 0x73, 0xd2, 0x34, 0x51, 0xd3, 0x20, 0x4d, 0x75, 0xab, 0x95, + 0x81, 0xcb, 0xcf, 0x82, 0xae, 0x8c, 0x0d, 0xf0, 0xdf, 0xbd, 0x3a, 0x1f, + 0x14, 0x9f, 0x70, 0x66, 0x08, 0x65, 0x72, 0x6c, 0xdc, 0x73, 0xc0, 0x15, + 0xd5, 0xdd, 0xbf, 0x75, 0x13, 0xee, 0xdc, 0xd1, 0xef, 0x17, 0x57, 0x8d, + 0x27, 0x19, 0xfe, 0xa1, 0xe5, 0xba, 0x39, 0xae, 0xf3, 0xfa, 0x6f, 0x00, + 0x84, 0x6f, 0x0f, 0xb8, 0xd9, 0xa1, 0xa4, 0x36 +}; +static const uint8_t ac_dsa_vect283_priv_val[] = { +/* X */ + 0x79, 0x28, 0xd3, 0xed, 0xc1, 0x1a, 0x89, 0x0f, 0xe3, 0x32, 0xc0, 0xd3, + 0x75, 0x9b, 0xc6, 0xec, 0xb8, 0x22, 0x43, 0x8d, 0x7f, 0x60, 0x4d, 0xa7, + 0x6b, 0x4f, 0xd7, 0x85, 0x90, 0x72, 0x0d, 0xdb +}; +static const uint8_t ac_dsa_vect283_pub_val[] = { +/* Y */ + 0xa3, 0x6a, 0x33, 0x39, 0x00, 0x03, 0x5d, 0x34, 0x53, 0x13, 0x9b, 0x28, + 0x35, 0x6b, 0xf0, 0x12, 0x4e, 0x57, 0x1f, 0x55, 0xa5, 0xe4, 0x25, 0x9b, + 0x8b, 0x2e, 0xe1, 0x45, 0x7c, 0xc3, 0x58, 0x80, 0x56, 0xd6, 0xc6, 0xa6, + 0x45, 0xd4, 0x22, 0xca, 0xc7, 0x24, 0x74, 0xc5, 0x90, 0x1d, 0x0a, 0x7f, + 0x41, 0x0d, 0xf7, 0xf9, 0xb4, 0xe2, 0x2f, 0x86, 0x84, 0x86, 0x7d, 0x93, + 0x32, 0xe2, 0xd4, 0x26, 0x6a, 0x6e, 0x59, 0x5e, 0x51, 0x5b, 0xec, 0xff, + 0x7f, 0xb9, 0x4d, 0x21, 0xa8, 0xa9, 0xad, 0x72, 0x11, 0x57, 0x2e, 0x44, + 0xce, 0x84, 0x48, 0x31, 0x7b, 0x34, 0xc3, 0xc0, 0xb8, 0x9b, 0x30, 0x97, + 0xab, 0x2e, 0xc1, 0x34, 0xec, 0x7c, 0x17, 0x8c, 0x22, 0x78, 0x30, 0x9c, + 0xf9, 0x15, 0x2b, 0x22, 0x3b, 0xb9, 0x37, 0xe6, 0x86, 0x82, 0xf1, 0xf6, + 0x80, 0xc1, 0x7e, 0xe5, 0x9e, 0xcd, 0x06, 0x98, 0xa0, 0x5c, 0x24, 0xc1, + 0x35, 0xd2, 0xb0, 0x23, 0x8e, 0x71, 0xf8, 0x07, 0xe0, 0x79, 0xf1, 0x75, + 0xe1, 0x16, 0x71, 0x30, 0x8f, 0x5b, 0xd9, 0xe5, 0xa6, 0x97, 0x12, 0xa9, + 0xc5, 0x08, 0xb3, 0xb5, 0x09, 0x25, 0xd1, 0x27, 0x6d, 0x55, 0x2b, 0xda, + 0x51, 0xce, 0xf3, 0xbd, 0x0f, 0xbd, 0x00, 0xa9, 0xd2, 0xdd, 0xdf, 0x0e, + 0x5e, 0xcb, 0x6b, 0x32, 0x83, 0x78, 0xea, 0x63, 0x7b, 0x49, 0x38, 0x46, + 0x48, 0x0e, 0xd7, 0x5a, 0x31, 0x52, 0xd9, 0xe6, 0xa4, 0x88, 0x4e, 0xeb, + 0xad, 0x12, 0xb0, 0x7c, 0xad, 0x8d, 0x10, 0x1b, 0x3d, 0x00, 0x1b, 0xc9, + 0x9f, 0xb1, 0xee, 0xe4, 0xe9, 0x8f, 0xd6, 0xfc, 0x92, 0x0c, 0xb5, 0x76, + 0x5e, 0xc2, 0x4e, 0x62, 0xab, 0xd3, 0x2f, 0x97, 0x5a, 0x47, 0xd5, 0x0f, + 0x61, 0x55, 0x3e, 0x1c, 0x14, 0x77, 0x51, 0x93, 0xb5, 0x3b, 0x05, 0xb7, + 0xd0, 0x20, 0x24, 0xaa, 0xce, 0x81, 0x8a, 0xb6, 0x59, 0xd7, 0x17, 0xd1, + 0x1d, 0xea, 0xcc, 0x98, 0x77, 0xb8, 0x18, 0xa5, 0x16, 0x89, 0xd2, 0x39, + 0xb6, 0x0f, 0x7f, 0x9e, 0xd4, 0xca, 0xf7, 0x32, 0x5a, 0xc0, 0xb3, 0x1b, + 0x31, 0x6c, 0x03, 0x65, 0x99, 0xea, 0x66, 0x95, 0x9d, 0x52, 0x5f, 0xd1, + 0x6f, 0x5c, 0x1a, 0x2a, 0x80, 0x9f, 0x28, 0x66, 0xee, 0x9e, 0x99, 0xf6, + 0xd8, 0xa3, 0xc4, 0x2b, 0x58, 0xd3, 0x3d, 0x0e, 0x5d, 0x38, 0x05, 0x5c, + 0x55, 0xc7, 0xbc, 0xcd, 0xef, 0x31, 0x0c, 0xcd, 0x34, 0x26, 0x20, 0x7d, + 0xbb, 0xc6, 0x0f, 0xaf, 0x9f, 0x2a, 0x21, 0x9a, 0xb3, 0x67, 0xce, 0x84, + 0x62, 0x3b, 0x81, 0x10, 0x48, 0x22, 0xe2, 0xc7, 0x7e, 0xc5, 0xb1, 0x33, + 0xce, 0x70, 0x50, 0xca, 0xed, 0x09, 0x09, 0x46, 0xc1, 0xf1, 0x35, 0x5d, + 0x87, 0x8a, 0x13, 0x17, 0xde, 0x69, 0x4e, 0x68, 0x6c, 0x62, 0xff, 0xdf +}; +/* K = 01f77e5f125a9a1385349f77d7a32f26b1efa5b0a5d4a212753bb54d300d088e */ +static const uint8_t ac_dsa_vect283_out[] = { +/* R */ + 0x12, 0xb4, 0x0b, 0xd1, 0xc8, 0x66, 0xce, 0x38, 0xe7, 0xda, 0x07, 0x64, + 0xd8, 0x07, 0xae, 0x82, 0x51, 0x2b, 0x33, 0xb5, 0x1d, 0xc9, 0x08, 0xe5, + 0xa5, 0xb3, 0xd7, 0xc1, 0x6f, 0x0d, 0x08, 0xa5, +/* S */ + 0x5c, 0xac, 0xce, 0xe2, 0xbc, 0x85, 0xe2, 0x8d, 0x50, 0x6a, 0x9b, 0xc6, + 0xd2, 0x60, 0xdb, 0xd0, 0x82, 0x05, 0xb7, 0x5d, 0x20, 0x69, 0x0e, 0x26, + 0xaa, 0x6b, 0xed, 0x30, 0xd7, 0x32, 0x70, 0x99 +}; +#define ac_dsa_vect284_prime ac_dsa_vect271_prime +#define ac_dsa_vect284_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect284_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect284_ptx[] = { +/* Msg */ + 0x60, 0xc2, 0x9d, 0x99, 0x75, 0x3d, 0x08, 0x47, 0xbb, 0x52, 0xe9, 0x06, + 0xc8, 0x62, 0xa1, 0xb0, 0x62, 0x84, 0x96, 0x41, 0x6c, 0x14, 0xdf, 0x5d, + 0xcf, 0xbb, 0x5e, 0x28, 0x04, 0xf5, 0x02, 0xcb, 0x0a, 0x2d, 0x16, 0x3e, + 0x9b, 0xc2, 0xd8, 0x41, 0x22, 0xc0, 0xb3, 0xf5, 0xd0, 0x60, 0x9b, 0x82, + 0xac, 0x16, 0xaa, 0x15, 0xef, 0xd5, 0x5f, 0x55, 0xc8, 0xca, 0xa3, 0xd1, + 0x11, 0x4a, 0xc0, 0xcb, 0x83, 0xe5, 0xff, 0x3d, 0xb1, 0x2a, 0x24, 0xb8, + 0x9a, 0xca, 0x5f, 0x05, 0x14, 0xd2, 0xce, 0xb0, 0x9b, 0x14, 0xfa, 0x91, + 0x60, 0x00, 0xc0, 0xf4, 0xde, 0xb0, 0x16, 0xdb, 0x75, 0x5e, 0x88, 0xb3, + 0x26, 0x17, 0x21, 0x44, 0xe4, 0xf1, 0xa7, 0x05, 0xa8, 0x00, 0x55, 0x9b, + 0x3d, 0xa3, 0xc2, 0x7a, 0xf5, 0x5c, 0xb3, 0x2b, 0x11, 0x47, 0x46, 0x0c, + 0x31, 0x18, 0x6d, 0x99, 0xdc, 0x1c, 0xf2, 0xe5 +}; +static const uint8_t ac_dsa_vect284_priv_val[] = { +/* X */ + 0x3d, 0xd6, 0x4d, 0xb4, 0xbd, 0x8e, 0x28, 0xe7, 0x01, 0x23, 0x5a, 0xd8, + 0x3a, 0x5d, 0x5e, 0x9d, 0xd1, 0x3e, 0xe8, 0xa3, 0xb3, 0xdc, 0xb4, 0xc9, + 0x9c, 0x1b, 0xc9, 0x5b, 0x6a, 0xe2, 0x52, 0x91 +}; +static const uint8_t ac_dsa_vect284_pub_val[] = { +/* Y */ + 0xa3, 0x73, 0x97, 0xe6, 0xea, 0xfb, 0xdc, 0xf1, 0xe0, 0x15, 0x8f, 0x1f, + 0x4e, 0xa1, 0xcb, 0x3a, 0x1e, 0xbd, 0x73, 0x9c, 0x85, 0x59, 0xa5, 0x00, + 0xde, 0xf3, 0xb7, 0x55, 0x17, 0x99, 0xd6, 0x52, 0xb3, 0x27, 0x10, 0x1c, + 0xfe, 0xa0, 0xb8, 0x70, 0x16, 0xdb, 0x59, 0x15, 0x22, 0xb9, 0xb3, 0x4e, + 0xd2, 0x67, 0x13, 0x2c, 0x52, 0x55, 0xe7, 0x76, 0x53, 0xc4, 0xeb, 0x93, + 0x5c, 0xe0, 0xc8, 0x22, 0xb4, 0xb1, 0x0a, 0x5e, 0x8f, 0x3c, 0xce, 0x39, + 0xad, 0x1b, 0x96, 0x06, 0xde, 0x5b, 0xe2, 0xb2, 0xd3, 0x6e, 0x1c, 0x54, + 0x11, 0xf0, 0x6a, 0xba, 0x04, 0x61, 0xea, 0x8d, 0xc4, 0x8b, 0x64, 0x9f, + 0x10, 0x8e, 0xba, 0x88, 0xde, 0xf4, 0x4d, 0xaa, 0x2a, 0x5c, 0x65, 0x3d, + 0xcc, 0xf1, 0xd8, 0xae, 0x29, 0x20, 0x5d, 0xd5, 0xc3, 0x40, 0xe3, 0x4b, + 0x7b, 0xd6, 0x98, 0xec, 0xcd, 0xcd, 0x34, 0x5b, 0xd4, 0xaa, 0x5e, 0xee, + 0x3c, 0x08, 0xb9, 0x16, 0x2c, 0xa1, 0x80, 0x48, 0x72, 0xde, 0x3c, 0x57, + 0x5d, 0x57, 0x2f, 0x34, 0xdd, 0x48, 0xb4, 0x1f, 0x82, 0x35, 0xd0, 0xf5, + 0x11, 0xc8, 0xdc, 0x65, 0xda, 0xeb, 0x07, 0x09, 0x5c, 0x3b, 0x5d, 0xbd, + 0x3a, 0x07, 0x6f, 0x8e, 0xb2, 0x44, 0x12, 0xf3, 0x62, 0x1f, 0x49, 0x21, + 0x26, 0x73, 0x7a, 0x9d, 0x73, 0x01, 0x4d, 0xef, 0xa5, 0xf5, 0xd5, 0x7b, + 0xdc, 0x6f, 0xaf, 0x53, 0x14, 0x2e, 0xb1, 0x91, 0x60, 0x6f, 0x2f, 0xd3, + 0xdc, 0x03, 0x5f, 0x4b, 0x8a, 0xe8, 0x4d, 0x65, 0x5c, 0xb6, 0xda, 0xaa, + 0xf8, 0x89, 0x00, 0x5c, 0x3c, 0x33, 0x4f, 0xfd, 0x7e, 0x3b, 0x04, 0x98, + 0xfa, 0xe2, 0xa6, 0xf8, 0xdc, 0x1b, 0xc6, 0x2f, 0x37, 0x04, 0xc8, 0xf8, + 0xc0, 0x05, 0xc8, 0x01, 0x9e, 0x0b, 0xf4, 0x5b, 0x7a, 0xa8, 0xe0, 0x80, + 0x3b, 0x93, 0xa9, 0x92, 0x67, 0x5e, 0x38, 0x1f, 0x61, 0xa8, 0x98, 0x58, + 0x29, 0x50, 0xb9, 0xce, 0x40, 0xe7, 0xcd, 0xb0, 0x30, 0x0f, 0x4b, 0x26, + 0xf9, 0xb4, 0x44, 0x84, 0xe8, 0x9c, 0x92, 0x34, 0x17, 0x9b, 0x60, 0xa3, + 0x72, 0xfe, 0x94, 0x76, 0xf8, 0x4d, 0xe0, 0xed, 0x4b, 0x93, 0x49, 0x72, + 0x16, 0xfb, 0x96, 0xba, 0xe4, 0x32, 0x97, 0xdc, 0xdc, 0x84, 0x96, 0xc6, + 0x34, 0x10, 0x0c, 0xf0, 0x66, 0x40, 0x2c, 0x7d, 0x29, 0x0a, 0x7c, 0xd2, + 0x8c, 0xbc, 0xf8, 0xb0, 0x8a, 0xd4, 0xc1, 0x36, 0xdb, 0x2f, 0xe9, 0x92, + 0xff, 0xa0, 0x45, 0xbf, 0x8c, 0xb2, 0x49, 0x23, 0x4f, 0x29, 0xa6, 0x74, + 0x76, 0x2a, 0x56, 0xd2, 0x08, 0x97, 0xea, 0x55, 0x38, 0xc6, 0x74, 0xa1, + 0x43, 0x53, 0xdb, 0x64, 0xba, 0x60, 0xfe, 0x40, 0x52, 0xa0, 0x52, 0x8e, + 0xb0, 0xb2, 0x58, 0x87, 0xe3, 0xc5, 0xea, 0x69, 0xb4, 0x1f, 0x68, 0xb3 +}; +/* K = 453b64f2dedfeb1419b5dbeb726a2c92b1a37ef11a7732c911d9a96184285f40 */ +static const uint8_t ac_dsa_vect284_out[] = { +/* R */ + 0x72, 0xcf, 0x0e, 0x18, 0xe4, 0xbc, 0x37, 0x49, 0x64, 0x7c, 0xdf, 0xa6, + 0x2d, 0xcb, 0xd2, 0x51, 0x3c, 0x7c, 0x2b, 0x1d, 0x39, 0x7c, 0x1f, 0xcb, + 0xc7, 0xf6, 0xa4, 0x25, 0xeb, 0xb8, 0x97, 0xce, +/* S */ + 0x7b, 0x7d, 0x0a, 0x9e, 0x93, 0x34, 0x09, 0x41, 0xbb, 0x55, 0xf6, 0xaf, + 0xa6, 0xcd, 0x63, 0xf7, 0x36, 0x49, 0x63, 0x67, 0x10, 0x08, 0xed, 0xe4, + 0x57, 0xd0, 0x5b, 0x65, 0x45, 0xfa, 0xb1, 0xf1 +}; +#define ac_dsa_vect285_prime ac_dsa_vect271_prime +#define ac_dsa_vect285_sub_prime ac_dsa_vect271_sub_prime +#define ac_dsa_vect285_base ac_dsa_vect271_base +static const uint8_t ac_dsa_vect285_ptx[] = { +/* Msg */ + 0xb3, 0xde, 0xa6, 0x2a, 0x20, 0xa9, 0xed, 0x9d, 0xa9, 0x90, 0x46, 0x5b, + 0xeb, 0xe1, 0x8a, 0xa7, 0x1f, 0x08, 0xf9, 0x3f, 0xba, 0xee, 0x4f, 0xe5, + 0xd5, 0x81, 0xff, 0xaa, 0x6f, 0xd5, 0x5c, 0xbe, 0x27, 0x2a, 0x11, 0x5d, + 0x7f, 0xa1, 0x8f, 0xb9, 0xcf, 0x56, 0x62, 0xf5, 0x95, 0xb7, 0xcb, 0x9b, + 0xdb, 0x97, 0xa8, 0x1b, 0xdc, 0x07, 0x8e, 0xe3, 0xbd, 0xce, 0xb2, 0xc0, + 0x37, 0x22, 0x61, 0x01, 0x34, 0xc3, 0xbb, 0xfd, 0x7a, 0x6f, 0x8b, 0x79, + 0xec, 0xc6, 0xa9, 0xa7, 0x70, 0x92, 0x65, 0x68, 0x7f, 0x9c, 0x23, 0x6f, + 0xc6, 0x8b, 0x02, 0x20, 0x3b, 0xa6, 0x66, 0xe9, 0xec, 0xed, 0x51, 0x61, + 0xde, 0x90, 0xc1, 0x10, 0xee, 0x7a, 0xf9, 0xbf, 0x54, 0xd8, 0x4a, 0x22, + 0x18, 0x1f, 0x17, 0xb4, 0x32, 0x93, 0x48, 0xbd, 0xee, 0xfb, 0xb3, 0x24, + 0x96, 0x2e, 0x63, 0x56, 0x9f, 0x07, 0xc2, 0x85 +}; +static const uint8_t ac_dsa_vect285_priv_val[] = { +/* X */ + 0x63, 0x27, 0xd3, 0x81, 0x8c, 0x87, 0xe4, 0xc9, 0x9b, 0x7e, 0x51, 0x16, + 0xfc, 0x09, 0x1a, 0x9d, 0xa1, 0xe4, 0xc0, 0x2a, 0xab, 0x9b, 0x20, 0x7d, + 0x61, 0xe8, 0x59, 0xdd, 0xa8, 0xd8, 0x59, 0xed +}; +static const uint8_t ac_dsa_vect285_pub_val[] = { +/* Y */ + 0x45, 0x01, 0x33, 0x18, 0xb9, 0x41, 0xa7, 0x10, 0xb8, 0xab, 0x10, 0x10, + 0xd8, 0x18, 0xc3, 0x10, 0x36, 0x34, 0x65, 0x8d, 0x2e, 0x3e, 0x2f, 0x41, + 0x31, 0x65, 0x86, 0x08, 0x05, 0xe0, 0x8d, 0x5c, 0x1e, 0x80, 0xad, 0xd9, + 0x96, 0x9a, 0x3d, 0x3a, 0x0d, 0x23, 0x43, 0x2c, 0x8a, 0x48, 0xcc, 0xe8, + 0x36, 0xb2, 0x4a, 0x41, 0x08, 0x92, 0x09, 0x9b, 0xbf, 0x53, 0xcc, 0x5a, + 0x84, 0xa9, 0x5e, 0x1e, 0xb3, 0xb6, 0x82, 0xd2, 0x75, 0x4e, 0x72, 0x1e, + 0xfc, 0x86, 0xd3, 0xf4, 0x24, 0x8b, 0xaa, 0x33, 0x7d, 0x6f, 0x6e, 0x5d, + 0xac, 0x47, 0x59, 0xb2, 0x96, 0x16, 0x59, 0x18, 0xa7, 0x1b, 0x31, 0xce, + 0xd2, 0x5b, 0xf1, 0xb0, 0x5d, 0x67, 0x5b, 0xfa, 0x22, 0x29, 0x80, 0x60, + 0x8f, 0xda, 0x8f, 0x9d, 0x0e, 0xba, 0x9a, 0xa0, 0x84, 0x75, 0x51, 0x2d, + 0x04, 0xc6, 0x12, 0x13, 0x3c, 0x88, 0x25, 0x3b, 0xf3, 0xe2, 0x7e, 0x9f, + 0xfe, 0x3a, 0x85, 0x70, 0xbe, 0x20, 0x4f, 0x54, 0xbf, 0x8f, 0xf1, 0xc7, + 0xfe, 0x42, 0xae, 0xce, 0x83, 0x20, 0x50, 0xaa, 0xbd, 0xd9, 0x41, 0x57, + 0x64, 0xb8, 0xc8, 0x72, 0x69, 0x7f, 0x9c, 0x8e, 0x78, 0xe2, 0xf5, 0x6b, + 0xd2, 0x35, 0xeb, 0xbb, 0xb4, 0xb9, 0xcf, 0x8f, 0x05, 0x4b, 0x60, 0x29, + 0x29, 0x63, 0x76, 0x45, 0x36, 0xd6, 0xfd, 0x4c, 0x6c, 0xfa, 0xa1, 0xba, + 0xea, 0x53, 0x54, 0x6c, 0x6f, 0xfb, 0x56, 0xa0, 0x4f, 0xbf, 0xae, 0xe0, + 0x01, 0x22, 0x82, 0x80, 0xae, 0xc4, 0x0e, 0x66, 0xd9, 0xdc, 0x19, 0x2f, + 0x9b, 0xa7, 0x43, 0xbd, 0x3f, 0xfc, 0x0e, 0xaf, 0x27, 0x7b, 0x6b, 0xa3, + 0xd3, 0x3c, 0x36, 0x97, 0x02, 0x48, 0x92, 0xb0, 0xb3, 0x54, 0x19, 0x53, + 0x48, 0x73, 0xfb, 0x7a, 0x3d, 0x59, 0x4d, 0xd6, 0xae, 0x07, 0x51, 0xa2, + 0xfa, 0x43, 0x0b, 0xa4, 0x62, 0x37, 0xf4, 0xa5, 0x5e, 0x4a, 0x67, 0x80, + 0x72, 0xc6, 0x51, 0xfe, 0x6a, 0xd3, 0x14, 0xa0, 0x10, 0xfd, 0xfe, 0x8f, + 0x8b, 0x53, 0x42, 0xbd, 0xab, 0xe9, 0xae, 0x59, 0x10, 0xc6, 0xf4, 0x4a, + 0x51, 0xf4, 0x75, 0x24, 0xa6, 0xfe, 0x82, 0x16, 0x83, 0x0c, 0xca, 0xed, + 0xed, 0x26, 0xce, 0x1f, 0x13, 0xf7, 0xf2, 0x16, 0xe0, 0xb7, 0x80, 0x9e, + 0x92, 0x72, 0x56, 0x3c, 0xab, 0x33, 0x52, 0xb8, 0xed, 0x76, 0x66, 0x50, + 0x22, 0x7b, 0xfe, 0x16, 0xe9, 0x81, 0xb5, 0x05, 0x60, 0x9c, 0x41, 0xf0, + 0x3d, 0xca, 0x98, 0xe2, 0x19, 0xd0, 0x2a, 0xa7, 0xd9, 0x19, 0x21, 0xed, + 0xb3, 0xa8, 0x92, 0x29, 0xe7, 0x8c, 0x30, 0x16, 0x1c, 0xc1, 0x39, 0x73, + 0xb3, 0x5d, 0xe3, 0xc8, 0x77, 0x79, 0x37, 0x8b, 0x8d, 0x60, 0x7a, 0x19, + 0x32, 0x04, 0x05, 0x66, 0x13, 0x12, 0x43, 0x2d, 0xd8, 0xd0, 0x7a, 0xf2 +}; +/* K = 94a0f6f58f004e45ce5ffffa6e63abca8daf7768cdafd517f3a5e399828b1e72 */ +static const uint8_t ac_dsa_vect285_out[] = { +/* R */ + 0x3e, 0xc6, 0x77, 0xe9, 0x1c, 0x63, 0xe6, 0x5a, 0xaa, 0x17, 0x4a, 0xee, + 0x27, 0x91, 0xdc, 0x40, 0x92, 0x44, 0xcb, 0x80, 0xc0, 0x22, 0x09, 0x91, + 0xdc, 0xb4, 0x97, 0x39, 0x7a, 0x3c, 0x5e, 0x9b, +/* S */ + 0x1d, 0xe0, 0xec, 0x46, 0x6b, 0x2a, 0xd4, 0xed, 0x1a, 0xdc, 0xe3, 0xbc, + 0x38, 0xee, 0x52, 0x18, 0x03, 0xdc, 0x87, 0x08, 0x5e, 0x2f, 0xbf, 0xc5, + 0x61, 0xd6, 0x38, 0x44, 0xc1, 0xa9, 0xa2, 0xe6 +}; +/* [mod = L=3072, N=256, SHA-512] */ +static const uint8_t ac_dsa_vect286_prime[] = { +/* P */ + 0xc1, 0xd0, 0xa6, 0xd0, 0xb5, 0xed, 0x61, 0x5d, 0xee, 0x76, 0xac, 0x5a, + 0x60, 0xdd, 0x35, 0xec, 0xb0, 0x00, 0xa2, 0x02, 0x06, 0x30, 0x18, 0xb1, + 0xba, 0x0a, 0x06, 0xfe, 0x7a, 0x00, 0xf7, 0x65, 0xdb, 0x1c, 0x59, 0xa6, + 0x80, 0xce, 0xcf, 0xe3, 0xad, 0x41, 0x47, 0x5b, 0xad, 0xb5, 0xad, 0x50, + 0xb6, 0x14, 0x7e, 0x25, 0x96, 0xb8, 0x8d, 0x34, 0x65, 0x60, 0x52, 0xac, + 0xa7, 0x94, 0x86, 0xea, 0x6f, 0x6e, 0xc9, 0x0b, 0x23, 0xe3, 0x63, 0xf3, + 0xab, 0x8c, 0xdc, 0x8b, 0x93, 0xb6, 0x2a, 0x07, 0x0e, 0x02, 0x68, 0x8e, + 0xa8, 0x77, 0x84, 0x3a, 0x46, 0x85, 0xc2, 0xba, 0x6d, 0xb1, 0x11, 0xe9, + 0xad, 0xdb, 0xd7, 0xca, 0x4b, 0xce, 0x65, 0xbb, 0x10, 0xc9, 0xce, 0xb6, + 0x9b, 0xf8, 0x06, 0xe2, 0xeb, 0xd7, 0xe5, 0x4e, 0xde, 0xb7, 0xf9, 0x96, + 0xa6, 0x5c, 0x90, 0x7b, 0x50, 0xef, 0xdf, 0x8e, 0x57, 0x5b, 0xae, 0x46, + 0x2a, 0x21, 0x9c, 0x30, 0x2f, 0xef, 0x2a, 0xe8, 0x1d, 0x73, 0xce, 0xe7, + 0x52, 0x74, 0x62, 0x5b, 0x5f, 0xc2, 0x9c, 0x6d, 0x60, 0xc0, 0x57, 0xed, + 0x9e, 0x7b, 0x0d, 0x46, 0xad, 0x2f, 0x57, 0xfe, 0x01, 0xf8, 0x23, 0x23, + 0x0f, 0x31, 0x42, 0x27, 0x22, 0x31, 0x9c, 0xe0, 0xab, 0xf1, 0xf1, 0x41, + 0xf3, 0x26, 0xc0, 0x0f, 0xbc, 0x2b, 0xe4, 0xcd, 0xb8, 0x94, 0x4b, 0x6f, + 0xd0, 0x50, 0xbd, 0x30, 0x0b, 0xdb, 0x1c, 0x5f, 0x4d, 0xa7, 0x25, 0x37, + 0xe5, 0x53, 0xe0, 0x1d, 0x51, 0x23, 0x9c, 0x4d, 0x46, 0x18, 0x60, 0xf1, + 0xfb, 0x4f, 0xd8, 0xfa, 0x79, 0xf5, 0xd5, 0x26, 0x3f, 0xf6, 0x2f, 0xed, + 0x70, 0x08, 0xe2, 0xe0, 0xa2, 0xd3, 0x6b, 0xf7, 0xb9, 0x06, 0x2d, 0x0d, + 0x75, 0xdb, 0x22, 0x6c, 0x34, 0x64, 0xb6, 0x7b, 0xa2, 0x41, 0x01, 0xb0, + 0x85, 0xf2, 0xc6, 0x70, 0xc0, 0xf8, 0x7a, 0xe5, 0x30, 0xd9, 0x8e, 0xe6, + 0x0c, 0x54, 0x72, 0xf4, 0xaa, 0x15, 0xfb, 0x25, 0x04, 0x1e, 0x19, 0x10, + 0x63, 0x54, 0xda, 0x06, 0xbc, 0x2b, 0x1d, 0x32, 0x2d, 0x40, 0xed, 0x97, + 0xb2, 0x1f, 0xd1, 0xcd, 0xad, 0x30, 0x25, 0xc6, 0x9d, 0xa6, 0xce, 0x9c, + 0x7d, 0xdf, 0x3d, 0xcf, 0x1e, 0xa4, 0xd5, 0x65, 0x77, 0xbf, 0xde, 0xc2, + 0x30, 0x71, 0xc1, 0xf0, 0x5e, 0xe4, 0x07, 0x7b, 0x53, 0x91, 0xe9, 0xa4, + 0x04, 0xea, 0xff, 0xe1, 0x2d, 0x1e, 0xa6, 0x2d, 0x06, 0xac, 0xd6, 0xbf, + 0x19, 0xe9, 0x1a, 0x15, 0x8d, 0x20, 0x66, 0xb4, 0xcd, 0x20, 0xe4, 0xc4, + 0xe5, 0x2f, 0xfb, 0x1d, 0x52, 0x04, 0xcd, 0x02, 0x2b, 0xc7, 0x10, 0x8f, + 0x2c, 0x79, 0x9f, 0xb4, 0x68, 0x86, 0x6e, 0xf1, 0xcb, 0x09, 0xbc, 0xe0, + 0x9d, 0xfd, 0x49, 0xe4, 0x74, 0x0f, 0xf8, 0x14, 0x04, 0x97, 0xbe, 0x61 +}; +static const uint8_t ac_dsa_vect286_sub_prime[] = { +/* Q */ + 0xbf, 0x65, 0x44, 0x1c, 0x98, 0x7b, 0x77, 0x37, 0x38, 0x5e, 0xad, 0xec, + 0x15, 0x8d, 0xd0, 0x16, 0x14, 0xda, 0x6f, 0x15, 0x38, 0x62, 0x48, 0xe5, + 0x9f, 0x3c, 0xdd, 0xbe, 0xfc, 0x8e, 0x9d, 0xd1 +}; +static const uint8_t ac_dsa_vect286_base[] = { +/* G */ + 0xc0, 0x2a, 0xc8, 0x53, 0x75, 0xfa, 0xb8, 0x0b, 0xa2, 0xa7, 0x84, 0xb9, + 0x4e, 0x4d, 0x14, 0x5b, 0x3b, 0xe0, 0xf9, 0x20, 0x90, 0xeb, 0xa1, 0x7b, + 0xd1, 0x23, 0x58, 0xcf, 0x3e, 0x03, 0xf4, 0x37, 0x95, 0x84, 0xf8, 0x74, + 0x22, 0x52, 0xf7, 0x6b, 0x1e, 0xde, 0x3f, 0xc3, 0x72, 0x81, 0x42, 0x0e, + 0x74, 0xa9, 0x63, 0xe4, 0xc0, 0x88, 0x79, 0x6f, 0xf2, 0xba, 0xb8, 0xdb, + 0x6e, 0x9a, 0x45, 0x30, 0xfc, 0x67, 0xd5, 0x1f, 0x88, 0xb9, 0x05, 0xab, + 0x43, 0x99, 0x5a, 0xab, 0x46, 0x36, 0x4c, 0xb4, 0x0c, 0x12, 0x56, 0xf0, + 0x46, 0x6f, 0x3d, 0xbc, 0xe3, 0x62, 0x03, 0xef, 0x22, 0x8b, 0x35, 0xe9, + 0x02, 0x47, 0xe9, 0x5e, 0x51, 0x15, 0xe8, 0x31, 0xb1, 0x26, 0xb6, 0x28, + 0xee, 0x98, 0x4f, 0x34, 0x99, 0x11, 0xd3, 0x0f, 0xfb, 0x9d, 0x61, 0x3b, + 0x50, 0xa8, 0x4d, 0xfa, 0x1f, 0x04, 0x2b, 0xa5, 0x36, 0xb8, 0x2d, 0x51, + 0x01, 0xe7, 0x11, 0xc6, 0x29, 0xf9, 0xf2, 0x09, 0x6d, 0xc8, 0x34, 0xde, + 0xec, 0x63, 0xb7, 0x0f, 0x2a, 0x23, 0x15, 0xa6, 0xd2, 0x73, 0x23, 0xb9, + 0x95, 0xaa, 0x20, 0xd3, 0xd0, 0x73, 0x70, 0x75, 0x18, 0x6f, 0x50, 0x49, + 0xaf, 0x6f, 0x51, 0x2a, 0x0c, 0x38, 0xa9, 0xda, 0x06, 0x81, 0x7f, 0x4b, + 0x61, 0x9b, 0x94, 0x52, 0x0e, 0xdf, 0xac, 0x85, 0xc4, 0xa6, 0xe2, 0xe1, + 0x86, 0x22, 0x5c, 0x95, 0xa0, 0x4e, 0xc3, 0xc3, 0x42, 0x2b, 0x8d, 0xeb, + 0x28, 0x4e, 0x98, 0xd2, 0x4b, 0x31, 0x46, 0x58, 0x02, 0x00, 0x8a, 0x09, + 0x7c, 0x25, 0x96, 0x9e, 0x82, 0x6c, 0x2b, 0xaa, 0x59, 0xd2, 0xcb, 0xa3, + 0x3d, 0x6c, 0x1d, 0x9f, 0x39, 0x62, 0x33, 0x0c, 0x1f, 0xcd, 0xa7, 0xcf, + 0xb1, 0x85, 0x08, 0xfe, 0xa7, 0xd0, 0x55, 0x5e, 0x3a, 0x16, 0x9d, 0xae, + 0xd3, 0x53, 0xf3, 0xee, 0x6f, 0x4b, 0xb3, 0x02, 0x44, 0x31, 0x91, 0x61, + 0xdf, 0xf6, 0x43, 0x8a, 0x37, 0xca, 0x79, 0x3b, 0x24, 0xbb, 0xb1, 0xb1, + 0xbc, 0x21, 0x94, 0xfc, 0x6e, 0x6e, 0xf6, 0x02, 0x78, 0x15, 0x78, 0x99, + 0xcb, 0x03, 0xc5, 0xdd, 0x6f, 0xc9, 0x1a, 0x83, 0x6e, 0xb2, 0x0a, 0x25, + 0xc0, 0x99, 0x45, 0x64, 0x3d, 0x95, 0xf7, 0xbd, 0x50, 0xd2, 0x06, 0x68, + 0x4d, 0x6f, 0xfc, 0x14, 0xd1, 0x6d, 0x82, 0xd5, 0xf7, 0x81, 0x22, 0x5b, + 0xff, 0x90, 0x83, 0x92, 0xa5, 0x79, 0x3b, 0x80, 0x3f, 0x9b, 0x70, 0xb4, + 0xdf, 0xcb, 0x39, 0x4f, 0x9e, 0xd8, 0x1c, 0x18, 0xe3, 0x91, 0xa0, 0x9e, + 0xb3, 0xf9, 0x3a, 0x03, 0x2d, 0x81, 0xba, 0x67, 0x0c, 0xab, 0xfd, 0x6f, + 0x64, 0xaa, 0x5e, 0x33, 0x74, 0xcb, 0x7c, 0x20, 0x29, 0xf4, 0x52, 0x00, + 0xe4, 0xf0, 0xbf, 0xd8, 0x20, 0xc8, 0xbd, 0x58, 0xdc, 0x5e, 0xeb, 0x34 +}; +static const uint8_t ac_dsa_vect286_ptx[] = { +/* Msg */ + 0x49, 0x41, 0x80, 0xee, 0xd0, 0x95, 0x13, 0x71, 0xbb, 0xaf, 0x0a, 0x85, + 0x0e, 0xf1, 0x36, 0x79, 0xdf, 0x49, 0xc1, 0xf1, 0x3f, 0xe3, 0x77, 0x0b, + 0x6c, 0x13, 0x28, 0x5b, 0xf3, 0xad, 0x93, 0xdc, 0x4a, 0xb0, 0x18, 0xaa, + 0xb9, 0x13, 0x9d, 0x74, 0x20, 0x08, 0x08, 0xe9, 0xc5, 0x5b, 0xf8, 0x83, + 0x00, 0x32, 0x4c, 0xc6, 0x97, 0xef, 0xea, 0xa6, 0x41, 0xd3, 0x7f, 0x3a, + 0xcf, 0x72, 0xd8, 0xc9, 0x7b, 0xff, 0x01, 0x82, 0xa3, 0x5b, 0x94, 0x01, + 0x50, 0xc9, 0x8a, 0x03, 0xef, 0x41, 0xa3, 0xe1, 0x48, 0x74, 0x40, 0xc9, + 0x23, 0xa9, 0x88, 0xe5, 0x3c, 0xa3, 0xce, 0x88, 0x3a, 0x2f, 0xb5, 0x32, + 0xbb, 0x74, 0x41, 0xc1, 0x22, 0xf1, 0xdc, 0x2f, 0x9d, 0x0b, 0x0b, 0xc0, + 0x7f, 0x26, 0xba, 0x29, 0xa3, 0x5c, 0xdf, 0x0d, 0xa8, 0x46, 0xa9, 0xd8, + 0xea, 0xb4, 0x05, 0xcb, 0xf8, 0xc8, 0xe7, 0x7f +}; +static const uint8_t ac_dsa_vect286_priv_val[] = { +/* X */ + 0x15, 0x0b, 0x5c, 0x51, 0xea, 0x64, 0x02, 0x27, 0x6b, 0xc9, 0x12, 0x32, + 0x2f, 0x04, 0x04, 0xf6, 0xd5, 0x7f, 0xf7, 0xd3, 0x2a, 0xfc, 0xaa, 0x83, + 0xb6, 0xdf, 0xde, 0x11, 0xab, 0xb4, 0x81, 0x81 +}; +static const uint8_t ac_dsa_vect286_pub_val[] = { +/* Y */ + 0x6d, 0xa5, 0x4f, 0x2b, 0x0d, 0xdb, 0x4d, 0xcc, 0xe2, 0xda, 0x1e, 0xdf, + 0xa1, 0x6b, 0xa8, 0x49, 0x53, 0xd8, 0x42, 0x9c, 0xe6, 0x0c, 0xd1, 0x11, + 0xa5, 0xc6, 0x5e, 0xdc, 0xf7, 0xba, 0x5b, 0x8d, 0x93, 0x87, 0xab, 0x68, + 0x81, 0xc2, 0x48, 0x80, 0xb2, 0xaf, 0xbd, 0xb4, 0x37, 0xe9, 0xed, 0x7f, + 0xfb, 0x8e, 0x96, 0xbe, 0xca, 0x7e, 0xa8, 0x0d, 0x1d, 0x90, 0xf2, 0x4d, + 0x54, 0x61, 0x12, 0x62, 0x9d, 0xf5, 0xc9, 0xe9, 0x66, 0x17, 0x42, 0xcc, + 0x87, 0x2f, 0xdb, 0x3d, 0x40, 0x9b, 0xc7, 0x7b, 0x75, 0xb1, 0x7c, 0x7e, + 0x6c, 0xff, 0xf8, 0x62, 0x61, 0x07, 0x1c, 0x4b, 0x5c, 0x9f, 0x98, 0x98, + 0xbe, 0x1e, 0x9e, 0x27, 0x34, 0x9b, 0x93, 0x3c, 0x34, 0xfb, 0x34, 0x56, + 0x85, 0xf8, 0xfc, 0x6c, 0x12, 0x47, 0x0d, 0x12, 0x4c, 0xec, 0xf5, 0x1b, + 0x5d, 0x5a, 0xdb, 0xf5, 0xe7, 0xa2, 0x49, 0x0f, 0x8d, 0x67, 0xaa, 0xc5, + 0x3a, 0x82, 0xed, 0x6a, 0x21, 0x10, 0x68, 0x6c, 0xf6, 0x31, 0xc3, 0x48, + 0xbc, 0xbc, 0x4c, 0xf1, 0x56, 0xf3, 0xa6, 0x98, 0x01, 0x63, 0xe2, 0xfe, + 0xca, 0x72, 0xa4, 0x5f, 0x6b, 0x3d, 0x68, 0xc1, 0x0e, 0x5a, 0x22, 0x83, + 0xb4, 0x70, 0xb7, 0x29, 0x26, 0x74, 0x49, 0x03, 0x83, 0xf7, 0x5f, 0xa2, + 0x6c, 0xcf, 0x93, 0xc0, 0xe1, 0xc8, 0xd0, 0x62, 0x8c, 0xa3, 0x5f, 0x2f, + 0x3d, 0x9b, 0x68, 0x76, 0x50, 0x5d, 0x11, 0x89, 0x88, 0x95, 0x72, 0x37, + 0xa2, 0xfc, 0x80, 0x51, 0xcb, 0x47, 0xb4, 0x10, 0xe8, 0xb7, 0xa6, 0x19, + 0xe7, 0x3b, 0x13, 0x50, 0xa9, 0xf6, 0xa2, 0x60, 0xc5, 0xf1, 0x68, 0x41, + 0xe7, 0xc4, 0xdb, 0x53, 0xd8, 0xea, 0xa0, 0xb4, 0x70, 0x8d, 0x62, 0xf9, + 0x5b, 0x2a, 0x72, 0xe2, 0xf0, 0x4c, 0xa1, 0x46, 0x47, 0xbc, 0xa6, 0xb5, + 0xe3, 0xee, 0x70, 0x7f, 0xcd, 0xf7, 0x58, 0xb9, 0x25, 0xeb, 0x8d, 0x4e, + 0x6a, 0xce, 0x4f, 0xc7, 0x44, 0x3c, 0x9b, 0xc5, 0x81, 0x9f, 0xf9, 0xe5, + 0x55, 0xbe, 0x09, 0x8a, 0xa0, 0x55, 0x06, 0x68, 0x28, 0xe2, 0x1b, 0x81, + 0x8f, 0xed, 0xc3, 0xaa, 0xc5, 0x17, 0xa0, 0xee, 0x8f, 0x90, 0x60, 0xbd, + 0x86, 0xe0, 0xd4, 0xcc, 0xe2, 0x12, 0xab, 0x6a, 0x3a, 0x24, 0x3c, 0x5e, + 0xc0, 0x27, 0x45, 0x63, 0x35, 0x3c, 0xa7, 0x10, 0x3a, 0xf0, 0x85, 0xe8, + 0xf4, 0x1b, 0xe5, 0x24, 0xfb, 0xb7, 0x5c, 0xda, 0x88, 0x90, 0x39, 0x07, + 0xdf, 0x94, 0xbf, 0xd6, 0x93, 0x73, 0xe2, 0x88, 0x94, 0x9b, 0xd0, 0x62, + 0x6d, 0x85, 0xc1, 0x39, 0x8b, 0x30, 0x73, 0xa1, 0x39, 0xd5, 0xc7, 0x47, + 0xd2, 0x4a, 0xfd, 0xae, 0x7a, 0x3e, 0x74, 0x54, 0x37, 0x33, 0x5d, 0x0e, + 0xe9, 0x93, 0xee, 0xf3, 0x6a, 0x30, 0x41, 0xc9, 0x12, 0xf7, 0xeb, 0x58 +}; +/* K = b599111b9f78402cefe7bde8bf553b6ca00d5abaf9a158aa42f2607bf78510bc */ +static const uint8_t ac_dsa_vect286_out[] = { +/* R */ + 0xa4, 0x0a, 0x6c, 0x90, 0x56, 0x54, 0xc5, 0x5f, 0xc5, 0x8e, 0x99, 0xc7, + 0xd1, 0xa3, 0xfe, 0xea, 0x2c, 0x5b, 0xe6, 0x48, 0x23, 0xd4, 0x08, 0x6c, + 0xe8, 0x11, 0xf3, 0x34, 0xcf, 0xdc, 0x44, 0x8d, +/* S */ + 0x64, 0x78, 0x05, 0x09, 0x77, 0xec, 0x58, 0x59, 0x80, 0x45, 0x4e, 0x0a, + 0x2f, 0x26, 0xa0, 0x30, 0x37, 0xb9, 0x21, 0xca, 0x58, 0x8a, 0x78, 0xa4, + 0xda, 0xff, 0x7e, 0x84, 0xd4, 0x9a, 0x8a, 0x6c +}; +#define ac_dsa_vect287_prime ac_dsa_vect286_prime +#define ac_dsa_vect287_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect287_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect287_ptx[] = { +/* Msg */ + 0xc0, 0x1c, 0x47, 0xbf, 0xa2, 0x08, 0xe2, 0xf1, 0x9d, 0xdd, 0xa5, 0xcd, + 0xe5, 0x83, 0x33, 0x25, 0xd1, 0x6a, 0x83, 0xfb, 0xda, 0x29, 0xe6, 0x66, + 0xfe, 0x67, 0xff, 0x34, 0x89, 0x80, 0x3a, 0x64, 0x78, 0xa5, 0xac, 0x17, + 0xff, 0x01, 0xed, 0xc7, 0x97, 0x3d, 0x15, 0xfe, 0x49, 0x98, 0xf6, 0x3b, + 0xbc, 0x09, 0x5f, 0xc1, 0xac, 0x07, 0x53, 0x42, 0x41, 0xc6, 0x43, 0xa4, + 0x44, 0x44, 0xdc, 0x9a, 0x35, 0x6f, 0xa8, 0x12, 0xd5, 0xca, 0x19, 0x1a, + 0x2f, 0x6e, 0xd1, 0x62, 0xa2, 0xd5, 0xfd, 0x6d, 0x0a, 0xa8, 0x98, 0xa2, + 0x05, 0x63, 0xd9, 0x93, 0x83, 0x02, 0x54, 0xdb, 0x8a, 0x4b, 0xf6, 0x5b, + 0xa8, 0x60, 0x99, 0xcc, 0x6b, 0x58, 0xa1, 0xbf, 0x6e, 0xbb, 0x01, 0xa1, + 0x9c, 0x79, 0x30, 0x43, 0x08, 0xac, 0xeb, 0xe1, 0xda, 0x09, 0xf1, 0x75, + 0x3a, 0x19, 0x5e, 0x9e, 0xf5, 0x86, 0xc7, 0xe1 +}; +static const uint8_t ac_dsa_vect287_priv_val[] = { +/* X */ + 0x9f, 0x11, 0x37, 0x0d, 0xdb, 0x3c, 0x43, 0xe2, 0xf4, 0x16, 0x2d, 0xc6, + 0x1f, 0x7e, 0x08, 0xdf, 0xc6, 0xe8, 0x6d, 0x5d, 0x71, 0x74, 0x2c, 0x6a, + 0xdc, 0xb5, 0x34, 0x0f, 0x7b, 0xea, 0x2a, 0xda +}; +static const uint8_t ac_dsa_vect287_pub_val[] = { +/* Y */ + 0x97, 0x0d, 0x38, 0xcd, 0x8b, 0x3f, 0x16, 0x65, 0x9e, 0xc4, 0x2a, 0x46, + 0xa1, 0x9f, 0xf0, 0x6c, 0xe8, 0x49, 0x5b, 0x9f, 0x47, 0x7d, 0x9b, 0x7e, + 0x35, 0xae, 0x10, 0x35, 0xb0, 0x8b, 0x0e, 0xe1, 0x7a, 0x0c, 0x3c, 0xee, + 0xdf, 0x02, 0x98, 0x46, 0xe3, 0xae, 0xb9, 0x12, 0xf8, 0x50, 0x88, 0x1c, + 0x22, 0x77, 0xf8, 0x22, 0x81, 0xe7, 0xc0, 0x74, 0x1d, 0x2f, 0x87, 0xe9, + 0xfa, 0x5c, 0x30, 0x67, 0x7f, 0xe7, 0x26, 0x8c, 0xc5, 0xfd, 0x9a, 0xed, + 0x29, 0xf3, 0x08, 0xd9, 0xbe, 0x8d, 0xe9, 0x2b, 0x96, 0x1e, 0x39, 0xc1, + 0xdb, 0xc4, 0x67, 0x90, 0xc9, 0x9b, 0x7e, 0x29, 0x57, 0x9d, 0xaf, 0x88, + 0x81, 0x76, 0xd5, 0xce, 0x16, 0xdb, 0x5c, 0xab, 0xfc, 0xbe, 0x42, 0x09, + 0xac, 0x47, 0x53, 0xb0, 0xe9, 0x6b, 0x15, 0xd0, 0xb8, 0x2c, 0x7e, 0xef, + 0xb4, 0x2a, 0x10, 0xde, 0x88, 0xf8, 0xa7, 0x72, 0x34, 0x92, 0xa2, 0xbe, + 0x54, 0x51, 0xc1, 0xc6, 0xec, 0x68, 0xca, 0x75, 0x9d, 0x8b, 0x4e, 0xe4, + 0x18, 0x82, 0x6e, 0x71, 0xf3, 0x9c, 0xd0, 0x76, 0x54, 0xd0, 0x0d, 0x0e, + 0x0f, 0x88, 0xd0, 0x92, 0x4b, 0xdb, 0x97, 0xaa, 0xca, 0x5a, 0x63, 0x46, + 0xad, 0x69, 0xfc, 0x22, 0x3c, 0xd5, 0x7f, 0x5b, 0xb0, 0x30, 0x04, 0x77, + 0xb5, 0x94, 0xaa, 0x44, 0x5e, 0x5e, 0xa8, 0x89, 0x6c, 0xdf, 0x3b, 0xc8, + 0x82, 0xe8, 0xfa, 0x55, 0x23, 0xb8, 0xa3, 0x32, 0xfd, 0x98, 0xe9, 0xd0, + 0xa9, 0x24, 0x57, 0x89, 0x44, 0xd2, 0x4a, 0x41, 0xcb, 0xea, 0xe3, 0xed, + 0x7b, 0x37, 0xdf, 0xfb, 0x2f, 0x60, 0xc0, 0x08, 0x4e, 0xaf, 0x00, 0x5c, + 0x12, 0x51, 0x82, 0x3d, 0xa4, 0x1d, 0x2a, 0x5d, 0x97, 0x7d, 0x8e, 0x48, + 0x3d, 0xdb, 0x33, 0xf7, 0x3f, 0xbc, 0x27, 0x25, 0x4a, 0x81, 0x4b, 0x61, + 0x6d, 0x6a, 0x39, 0x05, 0x13, 0xf0, 0x56, 0x7a, 0x56, 0x3a, 0xc0, 0x53, + 0xa7, 0x66, 0x67, 0x19, 0x7b, 0x45, 0x58, 0xf8, 0x71, 0xb6, 0x9c, 0xbf, + 0x2c, 0x11, 0x6c, 0xe4, 0x57, 0x51, 0x3f, 0x60, 0xb4, 0xf5, 0x28, 0xe2, + 0xdc, 0xda, 0xa7, 0x1a, 0x9a, 0x3a, 0x4c, 0xcc, 0xb3, 0x73, 0x8a, 0x22, + 0x93, 0x7b, 0xca, 0x2a, 0x04, 0x2b, 0xef, 0x8a, 0x74, 0xa6, 0x00, 0xac, + 0xd2, 0x69, 0x75, 0xc8, 0x91, 0x46, 0x6d, 0x7e, 0x57, 0xcc, 0x93, 0x09, + 0x84, 0x21, 0x2e, 0xe0, 0xea, 0xf1, 0x74, 0xeb, 0xcb, 0xaf, 0xbe, 0xb8, + 0xcc, 0x12, 0xbc, 0x43, 0xbf, 0xdb, 0x00, 0xfd, 0x11, 0x57, 0x6c, 0x43, + 0x95, 0x13, 0xef, 0x5b, 0x59, 0xa8, 0x8f, 0xa5, 0xa9, 0xae, 0x96, 0x3d, + 0x94, 0xda, 0xfd, 0x78, 0xf8, 0x1e, 0xe7, 0xb0, 0xd7, 0xfa, 0xb5, 0x3e, + 0x41, 0xbb, 0xf6, 0x5f, 0x84, 0x49, 0xa4, 0xf5, 0x8b, 0x44, 0xf9, 0xe3 +}; +/* K = ab53984e0b154992ace73bba548185b49719bcc3b11fb150b5da279529750078 */ +static const uint8_t ac_dsa_vect287_out[] = { +/* R */ + 0x5b, 0xb5, 0x0e, 0x4f, 0x53, 0x8a, 0x6e, 0x46, 0x38, 0x20, 0x6b, 0xe1, + 0x19, 0xdb, 0xf7, 0x12, 0x77, 0x61, 0x54, 0xac, 0xfb, 0x4c, 0x06, 0xd6, + 0x5d, 0x66, 0xc8, 0x02, 0x12, 0x34, 0x17, 0x39, +/* S */ + 0x7b, 0x7e, 0x64, 0x0c, 0xd7, 0x60, 0x86, 0xd3, 0xf6, 0x40, 0xd1, 0x8c, + 0xeb, 0x26, 0xbb, 0x53, 0xe3, 0x02, 0x82, 0xaf, 0xb1, 0x74, 0x01, 0xe7, + 0xb4, 0x8a, 0xa6, 0x81, 0x89, 0x34, 0xdc, 0x5c +}; +#define ac_dsa_vect288_prime ac_dsa_vect286_prime +#define ac_dsa_vect288_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect288_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect288_ptx[] = { +/* Msg */ + 0x47, 0xe7, 0xaf, 0x22, 0xc9, 0x29, 0x8a, 0xd3, 0xbf, 0xef, 0x9b, 0xee, + 0x50, 0x86, 0xbe, 0xdb, 0xdc, 0x51, 0x3d, 0x67, 0x41, 0x6d, 0x5f, 0x4e, + 0x79, 0x81, 0xcd, 0xdb, 0x10, 0x02, 0xcb, 0xa2, 0x47, 0x00, 0xc4, 0x5d, + 0xd6, 0xd4, 0xdc, 0xef, 0x4f, 0x81, 0xd0, 0x03, 0xf0, 0x51, 0x3d, 0xab, + 0x4e, 0x04, 0xeb, 0x4c, 0x70, 0xd9, 0x44, 0x04, 0x2e, 0x1b, 0x72, 0x6d, + 0x8a, 0x33, 0x05, 0x0d, 0x0e, 0x4f, 0x70, 0xc0, 0xa8, 0x34, 0x1b, 0x75, + 0xfd, 0x4e, 0x27, 0xc7, 0x94, 0x87, 0x54, 0xe4, 0x41, 0x20, 0x8e, 0xb9, + 0x3f, 0xc7, 0xb7, 0xc3, 0x73, 0x54, 0x25, 0x2f, 0x73, 0xb8, 0x38, 0xfd, + 0x02, 0xd0, 0x78, 0xc6, 0xa1, 0xae, 0x07, 0x3e, 0xf1, 0x23, 0x3a, 0xa1, + 0xc8, 0xaa, 0x27, 0x81, 0xe1, 0x93, 0xba, 0x28, 0x97, 0xcc, 0xdd, 0x8c, + 0xf6, 0x17, 0xca, 0x23, 0x54, 0x1c, 0xe1, 0xc5 +}; +static const uint8_t ac_dsa_vect288_priv_val[] = { +/* X */ + 0x23, 0x2c, 0x1c, 0x88, 0xd5, 0x71, 0x49, 0x27, 0x79, 0x17, 0x2c, 0xe6, + 0x65, 0x05, 0x24, 0xcb, 0x6d, 0x91, 0x17, 0x4e, 0x8a, 0x23, 0x78, 0x0d, + 0x0f, 0xdf, 0x7c, 0x44, 0xff, 0xd8, 0x0c, 0x1a +}; +static const uint8_t ac_dsa_vect288_pub_val[] = { +/* Y */ + 0x75, 0x16, 0x3a, 0xf1, 0x5c, 0xd6, 0xb2, 0x28, 0x25, 0x15, 0x04, 0xba, + 0x02, 0x4d, 0xf5, 0x1d, 0xf3, 0x2f, 0x63, 0x8e, 0x37, 0xf0, 0xf2, 0xf9, + 0xd0, 0x88, 0x37, 0xf8, 0xc6, 0xec, 0xfb, 0xa4, 0x3e, 0xb5, 0x15, 0xcc, + 0xba, 0xbe, 0xa1, 0x1b, 0x01, 0xe1, 0xe1, 0xfd, 0x3c, 0xfe, 0x7e, 0x40, + 0x5f, 0xc7, 0xf8, 0x14, 0x2b, 0x07, 0x31, 0x5e, 0x1d, 0xc3, 0x7b, 0x08, + 0xc7, 0x86, 0x68, 0x42, 0x1e, 0x2a, 0x21, 0xfc, 0x5d, 0x81, 0x1d, 0x26, + 0x55, 0x8c, 0x50, 0x4a, 0xbc, 0x4e, 0x6f, 0xdd, 0xf0, 0x37, 0x40, 0xb8, + 0xa2, 0x7f, 0xa2, 0xeb, 0xcd, 0xa5, 0x46, 0x0a, 0xd7, 0x85, 0x70, 0x6c, + 0x53, 0xcd, 0x2d, 0x14, 0x09, 0x3d, 0x92, 0x3d, 0xf9, 0x42, 0x05, 0x1c, + 0xbb, 0xa2, 0x58, 0x6b, 0x4d, 0x54, 0x70, 0x9d, 0x24, 0xba, 0xbe, 0x2f, + 0x7c, 0x61, 0xa5, 0x0d, 0xa8, 0x45, 0x18, 0x95, 0x99, 0x91, 0x66, 0xe8, + 0x0c, 0x0f, 0xab, 0x89, 0x2a, 0x37, 0xeb, 0x67, 0x82, 0x74, 0x55, 0x96, + 0xb4, 0x9f, 0x96, 0xe1, 0x1e, 0x9a, 0x95, 0x7c, 0x8e, 0xc6, 0x50, 0xd2, + 0xd9, 0xa4, 0x0a, 0xa4, 0xb0, 0x14, 0xd2, 0xe9, 0xa4, 0xc0, 0x8b, 0x9d, + 0x7b, 0xfe, 0xaf, 0x1e, 0xcd, 0x42, 0x78, 0x5b, 0x95, 0xc0, 0x17, 0x2a, + 0xe2, 0x1c, 0xf2, 0x5c, 0x4d, 0x36, 0x8b, 0xb5, 0x10, 0x0b, 0x6e, 0x6d, + 0x92, 0x31, 0x0b, 0x28, 0xb7, 0xb1, 0xaf, 0xe6, 0x4d, 0x49, 0x6b, 0x9c, + 0x60, 0xb7, 0x63, 0xca, 0xc0, 0x8a, 0xc4, 0x6a, 0x6b, 0xce, 0x1b, 0xbd, + 0x3a, 0xc8, 0xbb, 0x76, 0xbb, 0x55, 0xb6, 0x49, 0xb7, 0x59, 0x48, 0x20, + 0xab, 0x6e, 0xf7, 0xdd, 0x1b, 0x09, 0xbb, 0x12, 0x85, 0x28, 0x16, 0xb6, + 0x1e, 0x6d, 0xbe, 0xfa, 0xb7, 0x42, 0xe0, 0xea, 0x2c, 0xda, 0x47, 0xea, + 0xc7, 0xd9, 0xd9, 0x13, 0xdd, 0xd4, 0xbf, 0xd8, 0xb2, 0xeb, 0x5f, 0x01, + 0x95, 0x1c, 0xaa, 0x4f, 0x41, 0x3e, 0xb5, 0xe7, 0xa4, 0x1a, 0x06, 0x85, + 0x69, 0x5f, 0x83, 0x31, 0xa3, 0x94, 0xe0, 0x6b, 0x14, 0x95, 0xc1, 0x70, + 0xf3, 0x0a, 0xc2, 0x94, 0x66, 0x0e, 0x89, 0x09, 0x84, 0x3f, 0x9f, 0x11, + 0xc4, 0xbf, 0xa6, 0x4e, 0x87, 0x92, 0xdf, 0x67, 0x7d, 0xa0, 0xa0, 0x8a, + 0xae, 0x32, 0xa8, 0xa4, 0xe7, 0x06, 0x7f, 0xc3, 0x5e, 0xee, 0x03, 0x96, + 0x4e, 0x8a, 0xfb, 0xdb, 0x6a, 0x42, 0x1b, 0x82, 0x48, 0xad, 0xd2, 0x84, + 0x78, 0x9e, 0x4e, 0xd3, 0xca, 0xce, 0x71, 0x06, 0xc2, 0x3f, 0xe6, 0x66, + 0x6c, 0x4b, 0x12, 0xb8, 0x36, 0xe7, 0x30, 0x7a, 0x55, 0xab, 0x24, 0xd9, + 0x2d, 0x58, 0xac, 0x84, 0xe7, 0x1f, 0x81, 0xdc, 0x9b, 0x0b, 0x74, 0x36, + 0xad, 0x07, 0xf7, 0x49, 0x94, 0xaf, 0x7d, 0x0b, 0x04, 0x9b, 0xd0, 0x9a +}; +/* K = 101acd88a048a6a87c13ff23225dc2c4d2fe3fff039e072fbb268ef2dbfab9c3 */ +static const uint8_t ac_dsa_vect288_out[] = { +/* R */ + 0x61, 0x75, 0x47, 0x3d, 0x7a, 0xa7, 0xd5, 0xce, 0x55, 0x59, 0x0c, 0x95, + 0x2a, 0x19, 0x89, 0x72, 0x06, 0x08, 0x68, 0x87, 0xfd, 0x84, 0xbf, 0x2b, + 0x56, 0x69, 0x26, 0xe4, 0x79, 0x81, 0xc2, 0xa3, +/* S */ + 0x71, 0xd7, 0x85, 0x7b, 0x6f, 0xf0, 0x6c, 0xa6, 0x78, 0x85, 0xfa, 0x9c, + 0x9c, 0x71, 0xb8, 0xcc, 0x24, 0x6d, 0x03, 0x39, 0xb6, 0xc2, 0x72, 0x52, + 0x47, 0x17, 0x2a, 0x29, 0x7e, 0x26, 0xa7, 0xb5 +}; +#define ac_dsa_vect289_prime ac_dsa_vect286_prime +#define ac_dsa_vect289_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect289_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect289_ptx[] = { +/* Msg */ + 0x93, 0x11, 0xd8, 0xf9, 0x51, 0x14, 0x17, 0x13, 0xf4, 0x59, 0xeb, 0x65, + 0xf0, 0x18, 0x80, 0xb9, 0x61, 0xc0, 0xa5, 0x90, 0xb3, 0x6f, 0x78, 0x5f, + 0x1a, 0xeb, 0x88, 0x0e, 0xe7, 0x13, 0x00, 0xc0, 0xcb, 0xc6, 0x01, 0xb3, + 0xa6, 0x07, 0x21, 0x93, 0xda, 0xd6, 0xdd, 0xf2, 0x02, 0x8e, 0xca, 0x4c, + 0x8b, 0xd7, 0xb8, 0x57, 0x51, 0x87, 0x92, 0x8f, 0x84, 0xbd, 0x69, 0xc5, + 0xdc, 0xfb, 0x0b, 0x9d, 0x32, 0x00, 0x03, 0xc3, 0xa8, 0x63, 0xc0, 0x9e, + 0xe5, 0x03, 0xe3, 0x8a, 0xbe, 0x07, 0xce, 0x2e, 0x0d, 0x46, 0xb3, 0xce, + 0xc9, 0x26, 0x23, 0x1a, 0x57, 0xde, 0xfa, 0x0a, 0xeb, 0xd1, 0xa6, 0xe0, + 0x1e, 0xef, 0x4f, 0x9b, 0x53, 0x7a, 0xe1, 0xfc, 0xdf, 0x64, 0xe0, 0x14, + 0x34, 0xd4, 0x0a, 0xb5, 0x01, 0x9f, 0x39, 0x65, 0xc7, 0x35, 0x41, 0x1a, + 0x5c, 0x19, 0x94, 0x1f, 0x41, 0xfe, 0xbf, 0x4f +}; +static const uint8_t ac_dsa_vect289_priv_val[] = { +/* X */ + 0x87, 0xbd, 0xe6, 0x35, 0x0d, 0xa1, 0x58, 0x32, 0x96, 0x6f, 0xe7, 0x03, + 0x00, 0xe5, 0xdc, 0x66, 0xb9, 0x6e, 0xc2, 0x63, 0x34, 0x4b, 0xcf, 0xb5, + 0xde, 0x05, 0x1b, 0xe3, 0x4d, 0x76, 0x26, 0x2b +}; +static const uint8_t ac_dsa_vect289_pub_val[] = { +/* Y */ + 0x28, 0x7d, 0xdc, 0x19, 0x69, 0x15, 0x6c, 0x18, 0x42, 0x07, 0x43, 0xad, + 0xe0, 0xfa, 0x12, 0x71, 0xea, 0x34, 0x6c, 0x33, 0x29, 0xf9, 0xca, 0x9b, + 0x5d, 0x54, 0xeb, 0xfa, 0x21, 0xf6, 0x76, 0xf9, 0xe0, 0x13, 0x61, 0x62, + 0x39, 0xf4, 0xbb, 0xe6, 0x0e, 0xaf, 0x8e, 0x19, 0x02, 0xed, 0x9a, 0xc7, + 0x42, 0xd8, 0xdf, 0x91, 0x88, 0x76, 0x77, 0x08, 0x94, 0xb5, 0x12, 0xaa, + 0xa2, 0x5c, 0x06, 0x8b, 0xde, 0x96, 0x1f, 0x56, 0xc9, 0xb5, 0xb8, 0x78, + 0x06, 0xd7, 0xd0, 0xa9, 0xde, 0x78, 0x43, 0xd3, 0xcb, 0x07, 0x97, 0x90, + 0x31, 0x26, 0xa4, 0x7b, 0xd9, 0x42, 0x23, 0x37, 0xe3, 0xb4, 0x6b, 0xb1, + 0xf4, 0xf4, 0xa7, 0x9f, 0xdf, 0x9c, 0xf6, 0x76, 0x21, 0x57, 0x11, 0x8a, + 0xee, 0xe1, 0xe7, 0x11, 0x16, 0xf3, 0x4d, 0xaf, 0xce, 0x00, 0x47, 0xf0, + 0x5d, 0x43, 0xc7, 0xf2, 0xcb, 0xd4, 0xcd, 0x52, 0xd6, 0x14, 0xb7, 0xa9, + 0x45, 0xd4, 0x8b, 0xe4, 0x4c, 0xfe, 0xbf, 0x78, 0x43, 0x32, 0xfe, 0x99, + 0xc1, 0xee, 0x1a, 0xa8, 0x31, 0x08, 0x67, 0xdf, 0x20, 0xb2, 0x80, 0xda, + 0x85, 0x5b, 0x19, 0x02, 0x9f, 0xa7, 0x9e, 0xcd, 0x6d, 0xd6, 0x91, 0x9a, + 0x4d, 0x22, 0xb5, 0xa1, 0x40, 0x0c, 0x30, 0xe6, 0x2c, 0xe7, 0xac, 0xc4, + 0xb2, 0x8e, 0xfb, 0xdb, 0x94, 0xea, 0x23, 0xaf, 0xbb, 0x64, 0xd6, 0xe5, + 0xf7, 0xb3, 0x97, 0x5d, 0x2a, 0xc6, 0x3b, 0x1d, 0x04, 0x8f, 0xee, 0xa8, + 0x35, 0xc7, 0xf5, 0x0b, 0x42, 0x5c, 0xe3, 0xcb, 0x41, 0x8a, 0xfd, 0xf4, + 0xdc, 0x84, 0x00, 0x84, 0x73, 0x60, 0x65, 0x74, 0xe2, 0x0d, 0xb5, 0xeb, + 0xf8, 0x6c, 0xb1, 0xad, 0x27, 0x73, 0x7d, 0x46, 0x49, 0x4b, 0x2e, 0x48, + 0x5b, 0x26, 0xb8, 0xc9, 0x5d, 0x82, 0x9c, 0xf6, 0x56, 0xf8, 0x0f, 0x96, + 0xb1, 0xa6, 0x2e, 0x7c, 0x03, 0xc8, 0xf2, 0x0f, 0x18, 0xdc, 0x58, 0xbf, + 0x59, 0x91, 0x66, 0x82, 0xe6, 0xdc, 0xc6, 0x8d, 0x34, 0xc8, 0x9c, 0x1b, + 0x1b, 0xd6, 0xe6, 0xb1, 0xe1, 0x5a, 0x7d, 0xc3, 0x25, 0xe2, 0x3f, 0xd7, + 0xa3, 0x50, 0x99, 0x83, 0x1d, 0xbd, 0x75, 0x98, 0x9c, 0x73, 0x80, 0x20, + 0xbf, 0x4d, 0xc4, 0x07, 0x9c, 0xcb, 0x0b, 0xf1, 0x2f, 0xaf, 0x3b, 0x9d, + 0x64, 0x94, 0xa3, 0x79, 0xaa, 0xcb, 0x1b, 0x66, 0xd0, 0x7c, 0xbc, 0xeb, + 0xbf, 0x77, 0xa6, 0xe2, 0x9a, 0xef, 0x22, 0xf4, 0xba, 0xa3, 0xdf, 0x40, + 0xd2, 0x70, 0xb4, 0x57, 0xdd, 0xe6, 0x4f, 0x00, 0xb5, 0x37, 0x59, 0xae, + 0x57, 0x81, 0x1b, 0x64, 0xe0, 0x40, 0xcb, 0xd4, 0x2e, 0xa9, 0x0f, 0x4e, + 0x28, 0x08, 0xbc, 0x81, 0xdf, 0xd6, 0x63, 0xb2, 0x85, 0x84, 0xcd, 0xb8, + 0x19, 0x9d, 0xa9, 0x6d, 0x3e, 0x03, 0xd0, 0x3f, 0xb4, 0x13, 0x3e, 0x2f +}; +/* K = 7d1b5d39e51af0c22a56bc57ba6bf8bb6de18f2c256bb2d6fea684add38b1f6f */ +static const uint8_t ac_dsa_vect289_out[] = { +/* R */ + 0x66, 0xf7, 0x29, 0x71, 0x64, 0x56, 0xa2, 0x78, 0x1b, 0xdb, 0x85, 0x78, + 0xfa, 0x18, 0xd1, 0xe6, 0x4a, 0xf0, 0xed, 0xf8, 0xec, 0x1d, 0xee, 0x0a, + 0x50, 0xd2, 0x59, 0x81, 0x91, 0x2f, 0xc4, 0x5a, +/* S */ + 0x8c, 0x3c, 0xcc, 0xfe, 0x6f, 0x0c, 0xfd, 0xc0, 0xac, 0x3a, 0x54, 0x2c, + 0x8e, 0x8c, 0x85, 0x21, 0x0b, 0xbd, 0x7f, 0x95, 0x13, 0x4c, 0x8f, 0x03, + 0x5d, 0x1c, 0xe1, 0x6f, 0x44, 0xab, 0x7a, 0x06 +}; +#define ac_dsa_vect290_prime ac_dsa_vect286_prime +#define ac_dsa_vect290_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect290_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect290_ptx[] = { +/* Msg */ + 0x80, 0x86, 0x03, 0xf7, 0xf8, 0x43, 0x94, 0x41, 0x27, 0x79, 0x13, 0xb2, + 0x1b, 0xef, 0x4e, 0x01, 0xc8, 0x9e, 0x41, 0x13, 0xe0, 0x7c, 0xac, 0xc3, + 0x3f, 0x65, 0xac, 0x98, 0x49, 0xdb, 0x1a, 0xd1, 0xa1, 0xcb, 0x7d, 0xd2, + 0xfe, 0xcd, 0x88, 0xee, 0x41, 0x39, 0xb1, 0x63, 0x83, 0x55, 0xc6, 0x23, + 0x82, 0x13, 0x09, 0xf3, 0x26, 0xc1, 0x6b, 0xc6, 0x58, 0xbb, 0x48, 0x21, + 0x51, 0x82, 0x38, 0x98, 0x2e, 0x52, 0x51, 0xf7, 0xcd, 0x37, 0x80, 0x72, + 0x92, 0x15, 0x3d, 0x2b, 0x07, 0xdd, 0xdc, 0x06, 0x6e, 0x00, 0x3c, 0x60, + 0x69, 0xc3, 0x71, 0x15, 0x5d, 0x2d, 0x19, 0x1f, 0x15, 0x11, 0x1f, 0x20, + 0x89, 0xce, 0x42, 0x3f, 0x5c, 0x2a, 0x1f, 0x85, 0x34, 0xe3, 0x01, 0x31, + 0x3c, 0x69, 0x62, 0x3f, 0x62, 0xba, 0x63, 0x5a, 0xdc, 0xe8, 0x55, 0x17, + 0x33, 0xa8, 0x2a, 0x8f, 0xac, 0x1a, 0x66, 0xb1 +}; +static const uint8_t ac_dsa_vect290_priv_val[] = { +/* X */ + 0x94, 0x64, 0xce, 0x02, 0x94, 0x52, 0xe8, 0x60, 0x22, 0x14, 0xc5, 0x23, + 0x6d, 0x96, 0x37, 0xce, 0x7e, 0x59, 0xf9, 0x25, 0x36, 0xa0, 0x7a, 0xc5, + 0xba, 0x30, 0xf6, 0x39, 0xe0, 0x98, 0x14, 0xd4 +}; +static const uint8_t ac_dsa_vect290_pub_val[] = { +/* Y */ + 0x38, 0x96, 0x72, 0xec, 0x6d, 0xe0, 0xb8, 0x66, 0x55, 0xcb, 0x10, 0xf1, + 0x19, 0x9f, 0x85, 0x70, 0x13, 0xb6, 0x32, 0x0d, 0x52, 0xc8, 0x72, 0x8f, + 0xbb, 0xb5, 0x36, 0x0a, 0x97, 0x01, 0xb1, 0xd6, 0xca, 0x4f, 0x9e, 0xec, + 0xb8, 0x48, 0x7f, 0xb8, 0x79, 0x69, 0x0f, 0x85, 0x43, 0x0c, 0x58, 0x2d, + 0x3d, 0x91, 0xef, 0x18, 0x4c, 0x82, 0x47, 0xd1, 0x62, 0xb9, 0x4d, 0x6d, + 0xfd, 0xfe, 0x7c, 0x4a, 0xe8, 0x67, 0xac, 0x16, 0x72, 0x82, 0x79, 0x70, + 0x41, 0x5a, 0xa6, 0x7a, 0x14, 0x06, 0xac, 0x1a, 0x6e, 0x2c, 0x6c, 0x13, + 0x16, 0x77, 0x19, 0xe1, 0xd1, 0xa5, 0x36, 0xd1, 0x00, 0x78, 0x42, 0x7c, + 0x21, 0x1c, 0xf6, 0x82, 0x05, 0x1a, 0x75, 0xee, 0x83, 0x22, 0xc1, 0x40, + 0x8b, 0x89, 0xd9, 0x63, 0xbd, 0x8e, 0x85, 0xf9, 0xef, 0xf7, 0xbb, 0x8c, + 0xe0, 0x5c, 0xa4, 0x22, 0x25, 0xb4, 0xbd, 0xfe, 0xad, 0x6b, 0x89, 0x7b, + 0x0f, 0xea, 0xb7, 0x6c, 0x22, 0x72, 0xb4, 0x87, 0xd2, 0x7d, 0x4e, 0x8d, + 0xcd, 0xe0, 0xf1, 0x9e, 0x46, 0x15, 0xf7, 0xe1, 0x11, 0x45, 0x41, 0xf6, + 0x1d, 0x43, 0x53, 0x3c, 0xe7, 0x88, 0xcc, 0x45, 0x05, 0x60, 0x0b, 0x83, + 0x26, 0x6b, 0x1b, 0xea, 0x66, 0x59, 0x12, 0x19, 0x6c, 0x2c, 0x84, 0xc3, + 0x6a, 0xa9, 0x3b, 0xaf, 0x5b, 0x74, 0x64, 0xa6, 0xdd, 0xf5, 0x47, 0x18, + 0x3e, 0x2c, 0xd0, 0x58, 0xbb, 0x50, 0xa1, 0x27, 0x65, 0x53, 0x6f, 0x0a, + 0x4d, 0x35, 0x24, 0xaf, 0x4f, 0x31, 0xac, 0xc6, 0x09, 0xfc, 0x44, 0x7e, + 0x17, 0x29, 0xaa, 0xb9, 0x7b, 0x5a, 0x36, 0xb0, 0x17, 0x64, 0xb8, 0x4b, + 0xc5, 0xf7, 0x7f, 0x6c, 0xc5, 0x84, 0x86, 0x6d, 0x1a, 0x6c, 0xfb, 0x3a, + 0xa8, 0x43, 0x78, 0x95, 0xf7, 0x77, 0xf2, 0xdc, 0x68, 0x97, 0x49, 0x9f, + 0x6c, 0x5f, 0x02, 0xfa, 0x1e, 0x6c, 0x1e, 0xad, 0x68, 0xf3, 0x38, 0x5b, + 0x73, 0x33, 0x87, 0xc6, 0xb5, 0x8f, 0x2d, 0x11, 0x28, 0x4a, 0x63, 0xae, + 0x7c, 0x7c, 0xfe, 0xe4, 0x2c, 0x3f, 0x44, 0xa3, 0xc9, 0x26, 0xad, 0xad, + 0x81, 0x07, 0xcc, 0xa1, 0xc3, 0xf9, 0x44, 0xf9, 0xb9, 0xe2, 0x37, 0xd9, + 0xab, 0x35, 0xc8, 0x13, 0x91, 0xd7, 0xc5, 0xf5, 0x29, 0x2d, 0x1a, 0x32, + 0x2f, 0x7a, 0x12, 0xce, 0x10, 0x8a, 0x86, 0x23, 0x7b, 0xa4, 0xde, 0x3c, + 0x61, 0x2f, 0xa7, 0x38, 0xf5, 0x31, 0x94, 0xba, 0x67, 0xbe, 0xd8, 0x43, + 0xcd, 0x2d, 0x43, 0x30, 0xa5, 0xd1, 0x94, 0xd6, 0x7c, 0xf4, 0x5f, 0xa0, + 0x51, 0x83, 0xe0, 0xcb, 0x46, 0xc2, 0xd2, 0x3a, 0x1b, 0xae, 0x76, 0x75, + 0x5c, 0x30, 0x9f, 0xa1, 0xc3, 0x16, 0x05, 0xc8, 0x8a, 0x92, 0x14, 0x22, + 0x7c, 0xe0, 0x2f, 0xe9, 0x15, 0xbc, 0xf0, 0xd3, 0x4b, 0xce, 0x8c, 0x8e +}; +/* K = 5c2bb856c4d87b27e01e2ac1ae6f2fc526ab8bb49a67eda5c1d8cd4253610df3 */ +static const uint8_t ac_dsa_vect290_out[] = { +/* R */ + 0x98, 0xfe, 0x58, 0x7e, 0x43, 0xaa, 0x96, 0xf9, 0xa9, 0xbb, 0xe8, 0xaf, + 0x40, 0x4a, 0x08, 0xb0, 0x23, 0x07, 0xb3, 0x60, 0x53, 0xdb, 0x87, 0xf6, + 0xdb, 0x25, 0xa3, 0xaa, 0x36, 0xfc, 0xc3, 0xdb, +/* S */ + 0x5c, 0x94, 0xea, 0x70, 0xf9, 0x9f, 0x9f, 0xf1, 0x4b, 0x8e, 0x5d, 0xd4, + 0xa6, 0x68, 0x83, 0x98, 0x26, 0x09, 0x07, 0x17, 0x6e, 0xa8, 0x0e, 0x19, + 0xc3, 0x9b, 0x14, 0x62, 0x11, 0x49, 0xf0, 0xd6 +}; +#define ac_dsa_vect291_prime ac_dsa_vect286_prime +#define ac_dsa_vect291_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect291_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect291_ptx[] = { +/* Msg */ + 0xce, 0x2a, 0xa3, 0xed, 0x12, 0xc1, 0xb8, 0x84, 0x3a, 0x3e, 0x11, 0xb0, + 0x6b, 0x5f, 0x0e, 0x5e, 0x63, 0xfe, 0x8e, 0x19, 0xc1, 0xa3, 0x8a, 0xc4, + 0x46, 0xa4, 0x8e, 0xec, 0xa8, 0xda, 0xc6, 0xd8, 0xb7, 0x69, 0xd7, 0x80, + 0x94, 0x42, 0xc3, 0x2a, 0xc8, 0x2e, 0x93, 0xf6, 0x86, 0xec, 0x64, 0x34, + 0x7e, 0x94, 0x44, 0xc3, 0xf4, 0x52, 0x82, 0x3c, 0x84, 0x0e, 0x8d, 0x0c, + 0xd3, 0x34, 0xb4, 0x15, 0x20, 0x02, 0x14, 0x8d, 0xa1, 0x6a, 0xc8, 0x85, + 0x9d, 0x18, 0x9d, 0x87, 0xd6, 0x71, 0x64, 0xc5, 0xdb, 0x16, 0x19, 0x5c, + 0x08, 0x1d, 0x2e, 0xdd, 0x7d, 0x81, 0x57, 0xe2, 0xbf, 0x3b, 0x97, 0xa9, + 0x0b, 0x4b, 0x47, 0x84, 0x32, 0x4e, 0xb8, 0xce, 0xac, 0x42, 0x61, 0x80, + 0x9f, 0x67, 0x42, 0x56, 0xda, 0xf0, 0x07, 0xc4, 0xab, 0x1f, 0x22, 0x2f, + 0x5f, 0xd2, 0x83, 0x98, 0xa5, 0xb8, 0x24, 0xde +}; +static const uint8_t ac_dsa_vect291_priv_val[] = { +/* X */ + 0xb8, 0x87, 0xc1, 0x46, 0x73, 0xcb, 0xc6, 0x3f, 0x04, 0xf0, 0x83, 0x9e, + 0xa5, 0x6a, 0x76, 0x15, 0x40, 0x27, 0xd7, 0xee, 0xcf, 0x41, 0xd8, 0xd0, + 0xb5, 0x3d, 0x48, 0x92, 0x35, 0x3a, 0xe9, 0xa4 +}; +static const uint8_t ac_dsa_vect291_pub_val[] = { +/* Y */ + 0x58, 0x4f, 0xe0, 0xeb, 0x31, 0x4a, 0xfb, 0x86, 0x6c, 0x04, 0x66, 0xc3, + 0x98, 0x0a, 0x2d, 0xf5, 0x45, 0x98, 0xd8, 0xa7, 0x05, 0xdc, 0x2d, 0x1b, + 0xf5, 0x10, 0x2e, 0xac, 0x86, 0x31, 0x27, 0x84, 0xee, 0xbd, 0x01, 0x9b, + 0x81, 0xa7, 0x64, 0x2d, 0x4a, 0x3c, 0x4c, 0xc6, 0x5d, 0xbe, 0xdd, 0x81, + 0x87, 0xe3, 0x59, 0x3f, 0x0a, 0x9b, 0xcc, 0x06, 0xea, 0x36, 0x70, 0x09, + 0xb7, 0xeb, 0x4d, 0x29, 0xb0, 0x45, 0x00, 0x61, 0x37, 0x8e, 0xdb, 0xe1, + 0x63, 0xef, 0xd3, 0xf3, 0x44, 0xbb, 0x36, 0x23, 0x4f, 0xc8, 0x6f, 0xe1, + 0xc3, 0x2f, 0x2c, 0x99, 0x95, 0xa0, 0x7c, 0x6e, 0x95, 0x7d, 0x19, 0x5e, + 0x81, 0x05, 0xf5, 0x17, 0x9c, 0x2b, 0xd9, 0x76, 0xb3, 0x12, 0x70, 0x67, + 0xc8, 0x0c, 0xa9, 0x34, 0x56, 0xc1, 0x6b, 0x98, 0xdf, 0xcc, 0x7d, 0xe3, + 0x55, 0x79, 0x0f, 0x0b, 0x15, 0xcf, 0xd2, 0xff, 0x91, 0xdb, 0x09, 0x34, + 0x55, 0x32, 0xd4, 0x60, 0x96, 0xc0, 0x6b, 0x40, 0xa2, 0x30, 0x46, 0x81, + 0xd6, 0x28, 0x57, 0x67, 0x5a, 0xc5, 0x0e, 0x22, 0xc7, 0xd1, 0xab, 0x47, + 0x58, 0x92, 0x35, 0x41, 0x9c, 0xbe, 0xdd, 0x4b, 0x7d, 0x24, 0xb9, 0x05, + 0x31, 0xe5, 0xbf, 0xd8, 0x53, 0xe8, 0x8a, 0x28, 0x83, 0x6a, 0xc4, 0x6b, + 0x6d, 0xf2, 0x67, 0x60, 0x98, 0x5b, 0x96, 0x2c, 0x6a, 0x24, 0x45, 0x80, + 0x98, 0x66, 0xb4, 0x61, 0x26, 0x21, 0x2a, 0xa2, 0x63, 0xab, 0x2a, 0x46, + 0x03, 0xff, 0x41, 0xa8, 0x52, 0xc7, 0x98, 0x8c, 0x2d, 0x43, 0x86, 0x24, + 0x16, 0x55, 0xa7, 0x22, 0x2f, 0xa4, 0xe9, 0xf6, 0xea, 0xc6, 0xa1, 0x44, + 0xa1, 0x6b, 0x05, 0x9e, 0xa2, 0x5b, 0x71, 0xa2, 0x13, 0x84, 0x91, 0xd5, + 0x4e, 0xe9, 0x5a, 0x9d, 0x68, 0x19, 0x97, 0x7f, 0x90, 0xfe, 0x6a, 0x59, + 0xe0, 0xca, 0xd8, 0x1b, 0x32, 0x9e, 0xba, 0x3e, 0x68, 0x27, 0x7d, 0xf0, + 0x4f, 0x98, 0x28, 0xef, 0x6f, 0x08, 0x16, 0x10, 0xb4, 0x59, 0x5a, 0x92, + 0x11, 0x3e, 0xc6, 0xd0, 0x69, 0xff, 0xe9, 0x71, 0x96, 0xd9, 0x56, 0x19, + 0x1d, 0xaa, 0xbe, 0x98, 0x77, 0x37, 0x7a, 0xd0, 0x41, 0x6b, 0x0e, 0xe0, + 0x65, 0x86, 0x63, 0x37, 0x7e, 0x07, 0xad, 0xb2, 0x46, 0x44, 0xe8, 0xa0, + 0xe3, 0xce, 0x5f, 0xc1, 0x78, 0xf1, 0x52, 0xbe, 0x0c, 0xd9, 0xb0, 0x40, + 0x71, 0x89, 0x04, 0x27, 0xc6, 0xb0, 0x01, 0xd5, 0x92, 0x62, 0xf3, 0x8f, + 0xe8, 0x97, 0xce, 0x32, 0x04, 0x0d, 0xaa, 0x78, 0x07, 0x82, 0x1c, 0x40, + 0xac, 0x8c, 0x63, 0x50, 0x5b, 0xed, 0x0a, 0xf0, 0x70, 0x44, 0x33, 0x37, + 0xc9, 0xe9, 0xa6, 0x4e, 0x44, 0x20, 0x3c, 0x36, 0xa8, 0xca, 0x50, 0x64, + 0xd8, 0x7a, 0xa0, 0xd3, 0xcd, 0x1d, 0x40, 0x3a, 0xa6, 0xa2, 0x4e, 0xcc +}; +/* K = 49548238215fed6525693bc3cca3872944a97790087fb35f329b206e6046b32a */ +static const uint8_t ac_dsa_vect291_out[] = { +/* R */ + 0x54, 0xc9, 0x9b, 0x21, 0xf2, 0x8f, 0xee, 0xe2, 0x7f, 0x0e, 0x99, 0x9a, + 0xac, 0x6b, 0x49, 0xb6, 0xb0, 0x76, 0x33, 0xe1, 0xdb, 0x18, 0xa4, 0x59, + 0x52, 0xfc, 0xf7, 0xe7, 0x3b, 0x16, 0x6b, 0xdb, +/* S */ + 0x7a, 0x18, 0x58, 0x8e, 0xa1, 0x45, 0x6f, 0x67, 0x56, 0x2d, 0x67, 0x78, + 0x78, 0x34, 0x6f, 0xb3, 0x4b, 0x68, 0x4b, 0x9a, 0x8a, 0x61, 0xa7, 0x21, + 0xb3, 0xdb, 0x0e, 0x95, 0x69, 0x5a, 0xb4, 0x3a +}; +#define ac_dsa_vect292_prime ac_dsa_vect286_prime +#define ac_dsa_vect292_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect292_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect292_ptx[] = { +/* Msg */ + 0x17, 0xb9, 0x25, 0xe2, 0xa1, 0xa5, 0x1c, 0x20, 0x36, 0xe2, 0x25, 0x71, + 0x5f, 0x2f, 0x77, 0x1d, 0x8f, 0x0a, 0x6d, 0x98, 0xc7, 0xed, 0x9c, 0xac, + 0xf5, 0xaa, 0x4c, 0xd3, 0x0a, 0xb1, 0x6a, 0xfb, 0x94, 0xe2, 0x1a, 0x7c, + 0x95, 0x3e, 0x01, 0xca, 0x21, 0x1c, 0x28, 0x78, 0x2a, 0x06, 0x07, 0x3f, + 0xda, 0xd2, 0x77, 0x13, 0xaa, 0x8c, 0x26, 0xae, 0x9e, 0xc4, 0x49, 0xaa, + 0xaa, 0x8c, 0xcf, 0xda, 0x8c, 0x94, 0x71, 0x72, 0xde, 0x94, 0xb3, 0xf2, + 0x0b, 0x54, 0xaf, 0x98, 0xdf, 0x15, 0x2d, 0x5d, 0x3a, 0x63, 0x6c, 0x73, + 0x6f, 0xf0, 0x1b, 0xfa, 0x69, 0x9d, 0x62, 0x14, 0x00, 0x2d, 0xc7, 0x6d, + 0xbb, 0x3f, 0x38, 0x60, 0xd9, 0x4e, 0x0e, 0x34, 0xed, 0xab, 0xa5, 0xf2, + 0xbf, 0xd6, 0xb2, 0xbf, 0x66, 0x00, 0x86, 0xbe, 0x87, 0x64, 0x51, 0xa5, + 0x0f, 0x6a, 0x2d, 0xc7, 0xc2, 0xb0, 0x98, 0xb7 +}; +static const uint8_t ac_dsa_vect292_priv_val[] = { +/* X */ + 0x06, 0x84, 0xa8, 0xfa, 0xd5, 0x51, 0xc8, 0xd0, 0x8b, 0xeb, 0x05, 0x03, + 0x31, 0x85, 0xe3, 0xb4, 0xb6, 0xb6, 0xf6, 0xf4, 0x92, 0x0e, 0xf9, 0x98, + 0x2d, 0x72, 0xd0, 0xa9, 0xc7, 0x54, 0x98, 0x55 +}; +static const uint8_t ac_dsa_vect292_pub_val[] = { +/* Y */ + 0x42, 0xa9, 0x3b, 0xf4, 0x4e, 0xc7, 0xd2, 0xfb, 0xd6, 0x51, 0xcc, 0x1d, + 0x1a, 0xc3, 0x91, 0xd6, 0x3c, 0xab, 0x00, 0x97, 0x1a, 0x7f, 0xf7, 0xa5, + 0x61, 0x66, 0x76, 0x8b, 0x22, 0xe6, 0x11, 0xdc, 0x4d, 0x72, 0x9f, 0xaf, + 0x8c, 0x94, 0xe7, 0xed, 0x4d, 0x6f, 0x82, 0xb7, 0x02, 0x0b, 0x7b, 0x4d, + 0x2f, 0xb3, 0x59, 0x1c, 0xf2, 0x29, 0x5c, 0xc6, 0xe1, 0xb4, 0xbe, 0x2c, + 0x25, 0x6c, 0x2f, 0xdd, 0xa4, 0x3e, 0x00, 0x05, 0x11, 0x14, 0x64, 0x5d, + 0xa9, 0x1c, 0xbe, 0xd5, 0xcc, 0x08, 0x70, 0x85, 0xf7, 0xce, 0xcd, 0x8b, + 0xac, 0xe6, 0x78, 0x89, 0x10, 0x0b, 0xcc, 0xe7, 0x92, 0x82, 0x20, 0x26, + 0x6f, 0xd3, 0xfa, 0xf2, 0xea, 0xd9, 0xc2, 0x1e, 0x42, 0x3c, 0x99, 0x48, + 0xec, 0x70, 0xc2, 0xd3, 0x1b, 0x66, 0x8c, 0xdc, 0x36, 0x0d, 0xdc, 0xeb, + 0xdf, 0x42, 0x97, 0x20, 0x60, 0x7f, 0x96, 0xd8, 0x51, 0x23, 0x55, 0x15, + 0xd6, 0xdb, 0xdf, 0x16, 0x3f, 0x7e, 0xa5, 0xdd, 0xf3, 0x51, 0xba, 0xa7, + 0x6f, 0x38, 0x66, 0x3f, 0xdb, 0xfb, 0xd5, 0x87, 0x1b, 0xb2, 0x15, 0x7d, + 0xf0, 0xa4, 0x34, 0x20, 0x64, 0x8c, 0x10, 0xe4, 0x82, 0x7f, 0x54, 0x06, + 0x56, 0x14, 0x62, 0x3e, 0xd3, 0xab, 0xad, 0x10, 0xd3, 0x17, 0xbe, 0x9d, + 0x49, 0xa4, 0xc6, 0x65, 0x64, 0xf2, 0x0d, 0xca, 0xc1, 0x76, 0xb6, 0x60, + 0x5a, 0x2e, 0x3c, 0x3c, 0x01, 0xc3, 0x62, 0x22, 0x0f, 0x35, 0x2e, 0x47, + 0x74, 0x19, 0xf2, 0xb4, 0xb2, 0x38, 0xaf, 0xfb, 0xc3, 0x92, 0x0e, 0x5b, + 0xb5, 0x7c, 0xeb, 0xb9, 0xa7, 0x47, 0x46, 0xd6, 0x2c, 0xdd, 0x07, 0x0f, + 0x4a, 0x13, 0xaf, 0x00, 0x1d, 0x26, 0x2d, 0xef, 0x01, 0x4f, 0x29, 0xb7, + 0xf7, 0x54, 0xfa, 0xc8, 0x4e, 0x02, 0xd2, 0x92, 0x85, 0xb7, 0x3b, 0xb2, + 0x0a, 0xc0, 0xc8, 0x62, 0x41, 0x23, 0xa5, 0x77, 0xbe, 0x8d, 0x6a, 0x6b, + 0x97, 0x39, 0x18, 0x5e, 0x44, 0x58, 0x09, 0x0d, 0xdb, 0x42, 0xb0, 0x05, + 0xea, 0x4f, 0xa8, 0xb5, 0x10, 0x07, 0xbd, 0x9c, 0xa5, 0xb4, 0xcf, 0x2a, + 0x3d, 0xca, 0x44, 0x6a, 0x87, 0xec, 0x83, 0xc9, 0x54, 0x8d, 0xab, 0x46, + 0xcf, 0x3d, 0xaf, 0x86, 0xdb, 0x3b, 0xc6, 0x9a, 0x99, 0xba, 0xed, 0x45, + 0x9d, 0x6a, 0x19, 0x7f, 0x9b, 0xf5, 0x03, 0x2c, 0x1d, 0xc3, 0xa8, 0x77, + 0xdd, 0x7e, 0x5c, 0x11, 0x61, 0x12, 0x4a, 0x6d, 0x70, 0x13, 0x24, 0xe9, + 0xa9, 0x71, 0x2b, 0x82, 0x4a, 0x4f, 0xc3, 0xb1, 0xb3, 0x53, 0x25, 0x9a, + 0xf2, 0x25, 0x81, 0x3c, 0x27, 0xe8, 0x20, 0xb0, 0xba, 0x72, 0xfb, 0x4e, + 0x78, 0xf5, 0xc7, 0x86, 0x73, 0x92, 0x4e, 0x7f, 0xa2, 0xf4, 0x86, 0x03, + 0x02, 0x84, 0xf2, 0x6c, 0xb6, 0xfa, 0x31, 0xda, 0x56, 0xf4, 0x9d, 0x3f +}; +/* K = 4a258c125db1f7b775432b53c7a0ff47c00bf7af27abec7fcd42a2916e95e26d */ +static const uint8_t ac_dsa_vect292_out[] = { +/* R */ + 0x72, 0x6e, 0x4d, 0x3b, 0xaf, 0x00, 0xb2, 0x59, 0xf4, 0xbd, 0xca, 0x8b, + 0x0a, 0x5e, 0x1c, 0xbf, 0xd3, 0x78, 0x27, 0xc4, 0x83, 0x73, 0xef, 0x50, + 0x29, 0xf7, 0x60, 0x1a, 0x77, 0x69, 0x47, 0x8c, +/* S */ + 0x90, 0x30, 0x79, 0x43, 0x9e, 0xbd, 0xe1, 0xf7, 0x66, 0xd1, 0xa8, 0xff, + 0x33, 0xe0, 0xf7, 0x78, 0xd7, 0x7b, 0x5e, 0x8b, 0x7b, 0x0d, 0x68, 0x74, + 0x43, 0xc2, 0x71, 0xe8, 0xa6, 0x3b, 0x59, 0x75 +}; +#define ac_dsa_vect293_prime ac_dsa_vect286_prime +#define ac_dsa_vect293_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect293_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect293_ptx[] = { +/* Msg */ + 0x1c, 0x11, 0x69, 0xf0, 0xe7, 0x90, 0x05, 0x3c, 0xd7, 0xdf, 0x78, 0x0b, + 0x5c, 0x83, 0x2c, 0x64, 0x14, 0x76, 0x94, 0xb4, 0xa6, 0x44, 0x8b, 0xa1, + 0x4a, 0x42, 0x6d, 0x9d, 0xef, 0x7d, 0xdc, 0x78, 0xe3, 0xed, 0x36, 0xa1, + 0x2d, 0xa8, 0x1c, 0xf9, 0xc3, 0xf2, 0x45, 0xd6, 0x4c, 0x85, 0x9b, 0x6b, + 0x4d, 0x81, 0x21, 0xd1, 0x12, 0x85, 0x19, 0x74, 0xdf, 0x17, 0x8d, 0xef, + 0xc9, 0x77, 0xdb, 0x69, 0x12, 0x34, 0xd1, 0x42, 0xdf, 0xf9, 0x9b, 0xea, + 0x19, 0x57, 0x89, 0x1b, 0x5d, 0x6f, 0xe8, 0xa7, 0x87, 0xe9, 0x63, 0x69, + 0xd9, 0x3c, 0x24, 0x68, 0x2d, 0xeb, 0xd1, 0xcf, 0x3f, 0xdb, 0x64, 0x37, + 0x9b, 0x8c, 0x1b, 0x3b, 0x73, 0xe1, 0xbc, 0x24, 0x67, 0xdc, 0xb0, 0x8b, + 0x86, 0xcb, 0xd4, 0x94, 0xc0, 0x14, 0x77, 0xbe, 0x24, 0xd7, 0x90, 0x0f, + 0x5a, 0x57, 0x89, 0x30, 0xf4, 0xbd, 0xdc, 0xb6 +}; +static const uint8_t ac_dsa_vect293_priv_val[] = { +/* X */ + 0x3f, 0xa4, 0x47, 0x78, 0xb4, 0x14, 0xff, 0x27, 0x43, 0x6e, 0x27, 0x6c, + 0xa4, 0x90, 0x45, 0x46, 0xd3, 0x54, 0x2d, 0x12, 0x8f, 0x73, 0xc4, 0x46, + 0x3c, 0x69, 0xff, 0x9c, 0xea, 0x2b, 0x7a, 0x41 +}; +static const uint8_t ac_dsa_vect293_pub_val[] = { +/* Y */ + 0x7f, 0xca, 0x22, 0x68, 0xfb, 0xa3, 0x3b, 0xf9, 0x4e, 0x76, 0x41, 0x6a, + 0x9e, 0x38, 0x69, 0xf8, 0xa9, 0x0c, 0x3b, 0x0d, 0x2d, 0x37, 0xaa, 0xce, + 0xcd, 0x3f, 0x67, 0x85, 0xb9, 0xa9, 0x5a, 0xee, 0xfe, 0x93, 0x24, 0xc3, + 0xab, 0x09, 0xce, 0x61, 0xff, 0xde, 0x37, 0xb5, 0x0f, 0x82, 0xb6, 0x99, + 0x41, 0x3f, 0x3b, 0x54, 0xf2, 0x4d, 0x6c, 0x52, 0xec, 0xa6, 0x23, 0x25, + 0x02, 0x95, 0x23, 0xde, 0xb0, 0x5d, 0xb1, 0x38, 0x77, 0x84, 0x47, 0xbc, + 0x3d, 0x0d, 0x05, 0xaf, 0xf7, 0xd8, 0x5b, 0x55, 0x25, 0xf2, 0xb8, 0x63, + 0xd2, 0x64, 0x86, 0xe8, 0x4c, 0xde, 0x13, 0xe2, 0xe2, 0x11, 0x7d, 0x3f, + 0xa3, 0x8a, 0x38, 0xd1, 0x07, 0x3a, 0xaa, 0x79, 0x4e, 0xd8, 0xea, 0xa7, + 0xb3, 0xd1, 0xda, 0xa4, 0xac, 0x3e, 0x80, 0x8c, 0x37, 0x38, 0xa9, 0xcb, + 0xef, 0x35, 0x46, 0xcd, 0x79, 0xec, 0xcb, 0x4f, 0xaa, 0x28, 0xb5, 0x0f, + 0xce, 0x57, 0xcd, 0xc2, 0x40, 0x15, 0xfe, 0xc3, 0x90, 0xf0, 0xe7, 0xa7, + 0xdc, 0x9f, 0x9c, 0x47, 0x1d, 0x22, 0xb3, 0x0c, 0x3e, 0x41, 0x74, 0x35, + 0x8f, 0x1a, 0xd0, 0x73, 0x4c, 0xf7, 0x9a, 0x09, 0xa6, 0x39, 0xbd, 0xf3, + 0xf3, 0xea, 0xbd, 0xa2, 0xb4, 0x7b, 0x81, 0xf9, 0x2e, 0x2a, 0x4f, 0x90, + 0x04, 0xdd, 0x64, 0x13, 0x70, 0x33, 0x8c, 0x02, 0x02, 0x9b, 0xbf, 0x49, + 0x71, 0xaa, 0x67, 0x48, 0x3e, 0xea, 0x7a, 0x4b, 0xf7, 0xdf, 0xf3, 0x88, + 0x9f, 0x84, 0xfa, 0xa5, 0x76, 0x56, 0x17, 0xcc, 0xab, 0x37, 0xd1, 0x90, + 0xa9, 0x4c, 0x57, 0xf9, 0x9d, 0x79, 0x28, 0x07, 0xa6, 0x96, 0x5e, 0x21, + 0x13, 0x58, 0x6c, 0x6c, 0x5d, 0x1a, 0x81, 0xab, 0xfd, 0x37, 0x2e, 0x1c, + 0x79, 0x54, 0xe2, 0xe0, 0x90, 0x64, 0xdf, 0x4d, 0x2d, 0x82, 0x88, 0xf5, + 0xcd, 0xd8, 0x10, 0x6e, 0xd8, 0x4f, 0xfa, 0x79, 0x88, 0x19, 0xa0, 0x9a, + 0x73, 0x2b, 0xc2, 0x04, 0xa8, 0x12, 0xc0, 0x35, 0x2e, 0x4e, 0x39, 0xd2, + 0xce, 0xb8, 0x8f, 0x8e, 0x7d, 0x36, 0x24, 0xa5, 0xa5, 0xf3, 0xdc, 0x56, + 0xea, 0x0f, 0x9c, 0x52, 0x90, 0x78, 0x8e, 0x12, 0xdc, 0x46, 0x31, 0x61, + 0x60, 0x1f, 0xf3, 0xab, 0x68, 0x1b, 0xd0, 0x40, 0x3e, 0xe0, 0x3a, 0xf4, + 0x5d, 0x5e, 0x58, 0x6d, 0x84, 0xd9, 0xc9, 0x01, 0x98, 0x67, 0x18, 0x19, + 0x3e, 0x66, 0x12, 0x56, 0xf4, 0x02, 0xde, 0x73, 0x5d, 0x2c, 0xa6, 0x96, + 0xef, 0x6b, 0x59, 0x48, 0x68, 0x95, 0x0a, 0xe1, 0x73, 0xf2, 0x2d, 0x95, + 0x85, 0x66, 0x56, 0xa9, 0xd0, 0x06, 0x10, 0xfe, 0x8c, 0x2b, 0xd7, 0x25, + 0xae, 0x55, 0xd7, 0x91, 0x27, 0x7b, 0x13, 0x17, 0x08, 0x5b, 0x67, 0x18, + 0x8d, 0xa0, 0x06, 0x45, 0xce, 0x91, 0xbb, 0xe6, 0x2e, 0x32, 0x43, 0x11 +}; +/* K = a05b9ca1c9532bc050cd0c1150c27bc192154cf64d59dc9a949906f1ded57e35 */ +static const uint8_t ac_dsa_vect293_out[] = { +/* R */ + 0x10, 0x26, 0xec, 0xee, 0x0a, 0xc3, 0x1b, 0xdc, 0xdb, 0xd6, 0x10, 0x3b, + 0x13, 0x43, 0xf8, 0x4b, 0x44, 0x1f, 0xc3, 0x26, 0xe1, 0xd8, 0x6a, 0xd0, + 0x90, 0x3d, 0x0b, 0x17, 0xcf, 0xb2, 0xff, 0x9c, +/* S */ + 0xa5, 0xd3, 0xcb, 0x2e, 0x7c, 0x39, 0xd8, 0x76, 0x40, 0xc4, 0x54, 0x7a, + 0xc6, 0xc3, 0x3a, 0xfc, 0xcb, 0xfc, 0x18, 0x20, 0x90, 0x5b, 0xa1, 0xe5, + 0xbe, 0x5b, 0x26, 0x23, 0x13, 0x27, 0x7c, 0xb9 +}; +#define ac_dsa_vect294_prime ac_dsa_vect286_prime +#define ac_dsa_vect294_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect294_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect294_ptx[] = { +/* Msg */ + 0x80, 0x5b, 0xaa, 0xbd, 0xd0, 0x18, 0xd9, 0xe5, 0xeb, 0xb4, 0xdc, 0x51, + 0x43, 0x5b, 0xe6, 0x32, 0xd2, 0x38, 0x78, 0x69, 0x75, 0x6d, 0x74, 0x37, + 0x88, 0x44, 0x27, 0x90, 0xd5, 0x5b, 0xb1, 0x83, 0xe2, 0x66, 0x55, 0xae, + 0x3a, 0xac, 0x86, 0xdc, 0x16, 0xa4, 0x8d, 0xdd, 0x26, 0x8d, 0xd1, 0x5e, + 0x18, 0xd8, 0x32, 0x0d, 0xf9, 0xa1, 0xa0, 0xa6, 0xcb, 0x2b, 0x49, 0xbc, + 0x70, 0x1d, 0x7a, 0x15, 0xe3, 0xfe, 0x8d, 0xdd, 0x58, 0x4a, 0x75, 0xc8, + 0xc9, 0xaa, 0xae, 0xcd, 0x1e, 0xfe, 0x17, 0x32, 0x4d, 0x62, 0x61, 0x88, + 0x1f, 0x3d, 0x34, 0x68, 0x5b, 0x04, 0xf6, 0x2e, 0x96, 0x85, 0x05, 0x96, + 0x6c, 0x9a, 0x5f, 0xeb, 0x0c, 0x39, 0xb5, 0x09, 0x5e, 0x55, 0x68, 0xe4, + 0x0f, 0x20, 0xaa, 0x21, 0xcb, 0x25, 0x05, 0x35, 0x6d, 0xc9, 0x04, 0x9c, + 0xe5, 0x61, 0x82, 0xd9, 0x4a, 0x2d, 0x94, 0xa9 +}; +static const uint8_t ac_dsa_vect294_priv_val[] = { +/* X */ + 0x77, 0x0b, 0x99, 0x93, 0x5d, 0x39, 0x3e, 0xb9, 0x0b, 0x58, 0x3d, 0x12, + 0x51, 0x69, 0x60, 0x07, 0xcb, 0xeb, 0x1b, 0x35, 0xe6, 0xc3, 0xf4, 0xf9, + 0xbc, 0xb6, 0x28, 0x79, 0x07, 0x0e, 0x09, 0x40 +}; +static const uint8_t ac_dsa_vect294_pub_val[] = { +/* Y */ + 0x43, 0x4d, 0x06, 0x12, 0xb2, 0xa8, 0x33, 0x2b, 0x0a, 0xb1, 0x56, 0x14, + 0xe3, 0xee, 0x9f, 0xa2, 0x45, 0x13, 0x17, 0x12, 0xfb, 0x2b, 0xa8, 0x4f, + 0x71, 0x39, 0x6f, 0xff, 0x94, 0x88, 0xdc, 0xa3, 0x40, 0xa3, 0x7e, 0x82, + 0x0f, 0x44, 0xc1, 0x3a, 0xa8, 0x7f, 0xc9, 0xdf, 0x0b, 0x7a, 0xab, 0xea, + 0xe2, 0xed, 0x85, 0xa9, 0x62, 0x2b, 0x8d, 0xef, 0xad, 0x47, 0x4a, 0xc3, + 0x62, 0xa7, 0x03, 0x9a, 0xbd, 0xe3, 0x3d, 0x1d, 0xf7, 0x32, 0xa0, 0x52, + 0x44, 0x6a, 0xff, 0x78, 0x57, 0xbc, 0x24, 0xd8, 0xf6, 0x1d, 0x25, 0x80, + 0x15, 0xed, 0x2a, 0x30, 0x60, 0xa8, 0xbf, 0x9d, 0x44, 0x7e, 0x7d, 0x83, + 0xd7, 0xb4, 0x97, 0xa8, 0xe6, 0x54, 0x73, 0x19, 0x69, 0xe4, 0x37, 0xb3, + 0xf4, 0x6f, 0x83, 0xeb, 0x58, 0xf7, 0x88, 0x4f, 0xf2, 0xa2, 0x39, 0x0f, + 0x5d, 0x82, 0x1e, 0xca, 0xa7, 0xfd, 0x09, 0xa1, 0x46, 0xc5, 0x5f, 0xc1, + 0x18, 0x00, 0x73, 0xcc, 0x5a, 0xaa, 0x60, 0x7c, 0xab, 0xb9, 0x44, 0xf6, + 0x07, 0x8a, 0x44, 0x86, 0xcf, 0x20, 0x6d, 0xdc, 0x56, 0x35, 0x24, 0x2d, + 0xef, 0x2d, 0x3e, 0x2e, 0xdc, 0xbc, 0x02, 0x6b, 0xb8, 0x4e, 0x84, 0x95, + 0x18, 0xf1, 0x97, 0x39, 0x9c, 0x22, 0xa9, 0x00, 0x9d, 0xde, 0x9a, 0xfc, + 0xd8, 0x76, 0x9b, 0x24, 0x1c, 0x75, 0xd4, 0xcc, 0xce, 0x7f, 0x93, 0x90, + 0x0b, 0x5f, 0x48, 0x83, 0x33, 0xdf, 0x47, 0xc0, 0x26, 0xc4, 0xf2, 0xb2, + 0x76, 0x7e, 0x70, 0xd2, 0xd9, 0xdd, 0xe7, 0x84, 0x05, 0xe2, 0x26, 0xc9, + 0x95, 0x2f, 0x6d, 0xb1, 0xa2, 0xe5, 0x58, 0x29, 0xbc, 0x8a, 0x76, 0xc7, + 0xde, 0x5c, 0x2b, 0x58, 0x8f, 0x3f, 0x3e, 0x93, 0xce, 0x72, 0xfa, 0xda, + 0xba, 0xcb, 0x75, 0xc7, 0xc1, 0x46, 0x69, 0x70, 0x1e, 0x0a, 0x2b, 0xa1, + 0x27, 0xba, 0xc5, 0x68, 0x63, 0xc8, 0xc4, 0xe7, 0x20, 0x5c, 0xc0, 0xa7, + 0x3c, 0x42, 0x9a, 0x80, 0x1e, 0x97, 0x97, 0xda, 0x4f, 0x26, 0xe8, 0x48, + 0x98, 0x23, 0x06, 0xcc, 0x3c, 0x34, 0x39, 0xf9, 0xe3, 0x94, 0xdd, 0xc8, + 0x0b, 0x0f, 0x13, 0xe0, 0xd5, 0x28, 0x19, 0x06, 0x38, 0xd8, 0xb9, 0x6b, + 0xba, 0x3a, 0xf8, 0x89, 0xde, 0x37, 0x3b, 0x35, 0x49, 0xfc, 0x90, 0xa6, + 0x82, 0x29, 0x64, 0xc2, 0x21, 0x71, 0xe7, 0x60, 0x1f, 0xde, 0xfb, 0xe5, + 0x70, 0x89, 0x88, 0xb8, 0x4f, 0x3e, 0xa5, 0x54, 0xd6, 0x21, 0x60, 0x0a, + 0x87, 0x64, 0x15, 0xd5, 0xbc, 0x1e, 0x55, 0x7e, 0x94, 0x8c, 0xaa, 0xce, + 0x56, 0x3b, 0x37, 0x02, 0xf0, 0x91, 0x5a, 0x90, 0xa1, 0x3a, 0xad, 0xa7, + 0x77, 0x09, 0xee, 0xba, 0x8c, 0x50, 0xa8, 0x62, 0x93, 0x51, 0xa4, 0x78, + 0x7d, 0x0d, 0x58, 0x80, 0x8f, 0xfb, 0x8b, 0x21, 0x7c, 0x1d, 0x16, 0x4f +}; +/* K = 424a43cfd90f7b84e9e375572f82ebce7ffb197bd3237a353bf15ddc1a17095f */ +static const uint8_t ac_dsa_vect294_out[] = { +/* R */ + 0x2d, 0x63, 0xe6, 0xd2, 0x56, 0x85, 0x71, 0xac, 0xfe, 0x4a, 0x93, 0x15, + 0x80, 0xa0, 0x4b, 0x97, 0x4c, 0x7a, 0xae, 0x4c, 0xa9, 0xaa, 0x96, 0x10, + 0xd8, 0x7b, 0xe1, 0xa9, 0x1c, 0x65, 0x7c, 0x31, +/* S */ + 0x57, 0x4b, 0x10, 0xd1, 0x4d, 0xcb, 0x8f, 0x07, 0x94, 0x61, 0xb2, 0x9a, + 0xe1, 0xb9, 0x1e, 0xd6, 0xc5, 0xef, 0x32, 0xf9, 0x3c, 0xba, 0xd3, 0x06, + 0x69, 0x75, 0x52, 0xc1, 0x17, 0x48, 0xfe, 0x0c +}; +#define ac_dsa_vect295_prime ac_dsa_vect286_prime +#define ac_dsa_vect295_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect295_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect295_ptx[] = { +/* Msg */ + 0xbe, 0x8c, 0xa5, 0xed, 0x4c, 0x22, 0xa0, 0x50, 0xd8, 0x30, 0x9c, 0x7a, + 0x31, 0xac, 0xf6, 0x67, 0xf0, 0xc0, 0xfb, 0xaa, 0xdc, 0x64, 0xa3, 0x4d, + 0x2b, 0x63, 0x07, 0x4a, 0x76, 0x3a, 0x2b, 0x8d, 0xb7, 0x3b, 0x24, 0xcd, + 0xba, 0xad, 0x26, 0xcc, 0x6f, 0x2c, 0x3e, 0x90, 0xdf, 0x4b, 0x25, 0xbf, + 0xa7, 0x24, 0xfc, 0xe5, 0x87, 0xfa, 0xa0, 0xfd, 0x65, 0xff, 0xb7, 0x19, + 0xf0, 0xa0, 0x35, 0x16, 0x48, 0x23, 0x0d, 0x53, 0x54, 0xd7, 0x21, 0xd8, + 0xfa, 0x6d, 0x0d, 0x68, 0x6c, 0x37, 0xf2, 0x57, 0xd7, 0xd9, 0xdb, 0xd1, + 0x5f, 0x55, 0x5d, 0x50, 0x73, 0xf8, 0xbc, 0x71, 0xc9, 0x21, 0x39, 0xd1, + 0xf6, 0x27, 0xd7, 0x43, 0xf7, 0xd6, 0x58, 0x6d, 0x51, 0x0d, 0x19, 0xd0, + 0xd8, 0xa5, 0x55, 0xd0, 0xbf, 0x79, 0xec, 0x70, 0x59, 0x6e, 0x71, 0x21, + 0x83, 0x88, 0x0c, 0x89, 0xca, 0xf6, 0x9d, 0x6f +}; +static const uint8_t ac_dsa_vect295_priv_val[] = { +/* X */ + 0x98, 0x86, 0x13, 0x8d, 0x83, 0x7d, 0x20, 0xe8, 0xc6, 0xbe, 0x85, 0x3c, + 0xd7, 0xde, 0x1a, 0x66, 0xa2, 0x57, 0x48, 0xc7, 0xa3, 0x3f, 0xd5, 0x51, + 0x21, 0xa2, 0x72, 0x37, 0x62, 0x3d, 0x68, 0xd6 +}; +static const uint8_t ac_dsa_vect295_pub_val[] = { +/* Y */ + 0xaf, 0xaf, 0xf7, 0xa4, 0xd4, 0x38, 0xb4, 0x64, 0xf2, 0x74, 0x15, 0xd2, + 0xe0, 0x3e, 0xd9, 0xc4, 0x16, 0xdb, 0x2b, 0xeb, 0xfb, 0xe0, 0xab, 0x34, + 0xf1, 0x4e, 0xe1, 0x06, 0x44, 0x88, 0x5b, 0x5a, 0x45, 0x88, 0x87, 0x71, + 0x50, 0xf4, 0x63, 0x27, 0xc2, 0xc7, 0xa6, 0xf7, 0x12, 0x67, 0x0b, 0xfd, + 0x62, 0x37, 0xa2, 0x94, 0x52, 0x49, 0x48, 0x59, 0x94, 0x8f, 0x5e, 0x37, + 0xc0, 0xe5, 0x86, 0x65, 0x6b, 0x11, 0x9a, 0x0e, 0x01, 0xc8, 0x1a, 0xce, + 0xe5, 0x7c, 0x17, 0x75, 0xa3, 0xa1, 0x46, 0xe8, 0xfb, 0xaf, 0xc9, 0x9c, + 0xd2, 0x03, 0xfc, 0x98, 0x19, 0x56, 0x87, 0xfb, 0x94, 0xa8, 0x8a, 0x4f, + 0x44, 0x28, 0x0b, 0x03, 0xf0, 0x89, 0x5e, 0x0e, 0xca, 0x84, 0xdb, 0x08, + 0x7c, 0x1b, 0xf7, 0xc4, 0x84, 0x3c, 0x85, 0x59, 0x73, 0x68, 0xe8, 0x39, + 0x84, 0x11, 0x31, 0xe0, 0x27, 0x10, 0x9d, 0xaa, 0x7b, 0x81, 0x72, 0xa2, + 0x5e, 0x11, 0x35, 0x5f, 0xa9, 0xa9, 0x20, 0x5a, 0xc3, 0x24, 0x94, 0x1a, + 0x9f, 0xe4, 0x92, 0xc4, 0x84, 0x21, 0xf0, 0x68, 0x1a, 0x47, 0xe2, 0x80, + 0x80, 0x3e, 0x8b, 0xd9, 0x1b, 0x11, 0x3e, 0x0f, 0xa1, 0x59, 0x76, 0x07, + 0x43, 0x0b, 0xcb, 0x0a, 0xd5, 0x0b, 0x94, 0x08, 0xde, 0x00, 0x66, 0xd6, + 0xa2, 0x32, 0x4d, 0x09, 0xcf, 0x6e, 0x99, 0x13, 0x36, 0x54, 0xdd, 0x64, + 0xe8, 0xc8, 0xf7, 0x0c, 0xd6, 0x44, 0x53, 0x43, 0x75, 0x8b, 0x5c, 0xd5, + 0xa0, 0xe7, 0x7e, 0x2d, 0x3f, 0xa1, 0xcb, 0x3f, 0x7e, 0xfe, 0xd7, 0x61, + 0x24, 0xb2, 0x88, 0x1d, 0xfd, 0x20, 0x28, 0xab, 0x59, 0x18, 0xc3, 0x89, + 0xb9, 0xc3, 0x97, 0x82, 0x71, 0xdb, 0x54, 0xa5, 0x17, 0x15, 0x15, 0xab, + 0x2e, 0x85, 0xee, 0xb1, 0x0a, 0xb3, 0x07, 0x13, 0x01, 0x59, 0xbc, 0xa5, + 0xfe, 0x13, 0xcc, 0x4a, 0x95, 0x9e, 0x88, 0xe9, 0x26, 0x72, 0x21, 0xac, + 0x8d, 0x14, 0xee, 0x69, 0x38, 0xe1, 0x49, 0xf5, 0x2e, 0xc5, 0x91, 0x25, + 0xb4, 0x49, 0xcb, 0x55, 0xc5, 0xa0, 0x02, 0x9f, 0x01, 0x87, 0x70, 0xb3, + 0x1f, 0x08, 0x44, 0x0c, 0xe6, 0x87, 0x6e, 0x66, 0x00, 0xa3, 0x24, 0x11, + 0x72, 0x2f, 0x58, 0xe6, 0x26, 0x33, 0x39, 0xbd, 0x9d, 0x34, 0xe1, 0x7a, + 0xa5, 0x74, 0xb9, 0x21, 0x22, 0x89, 0x26, 0xff, 0x66, 0x8c, 0xe9, 0x03, + 0x62, 0xc4, 0x39, 0x1e, 0xcd, 0x0c, 0x03, 0x74, 0x54, 0xe1, 0x2f, 0xdf, + 0x80, 0xc9, 0x6b, 0xb7, 0xa8, 0x40, 0xcd, 0x86, 0x6e, 0x85, 0x70, 0xbb, + 0x7d, 0x65, 0x86, 0xfb, 0xe3, 0xd1, 0xea, 0xe5, 0x33, 0x29, 0x31, 0x19, + 0x8b, 0xa1, 0xd5, 0xd9, 0x02, 0xd6, 0xb7, 0xa1, 0x22, 0xdf, 0xa7, 0x70, + 0x18, 0x55, 0x3a, 0x2d, 0xd3, 0x68, 0x0a, 0x80, 0x9b, 0xb0, 0x60, 0x53 +}; +/* K = 1689eba0aac66b3d0cca9ae1911602f9638937b6be17c23a187be323d0dec7be */ +static const uint8_t ac_dsa_vect295_out[] = { +/* R */ + 0x9c, 0x7d, 0x40, 0xe2, 0x14, 0x08, 0x2b, 0xd5, 0xe7, 0x1f, 0x3b, 0xf4, + 0xbe, 0x99, 0x78, 0x93, 0x03, 0xf3, 0x8e, 0x85, 0x1a, 0x76, 0xf8, 0x8c, + 0xb9, 0x0a, 0xff, 0x71, 0x30, 0x80, 0xc5, 0x87, +/* S */ + 0x24, 0xca, 0x23, 0xbe, 0x94, 0xc6, 0x24, 0xb9, 0xd7, 0x36, 0x32, 0x8b, + 0x53, 0x78, 0x2b, 0x5f, 0xeb, 0x38, 0x4d, 0xc9, 0xfe, 0x63, 0x70, 0x01, + 0x6c, 0xc3, 0xf9, 0x7d, 0x8f, 0x48, 0xb6, 0xd0 +}; +#define ac_dsa_vect296_prime ac_dsa_vect286_prime +#define ac_dsa_vect296_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect296_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect296_ptx[] = { +/* Msg */ + 0x62, 0xf0, 0xcb, 0x1b, 0xb0, 0x7f, 0x64, 0x97, 0xa1, 0xdc, 0x7a, 0x66, + 0x95, 0x57, 0x65, 0xa9, 0xcc, 0x40, 0x3b, 0xde, 0x03, 0xfe, 0xf4, 0xe1, + 0x6b, 0x09, 0xd7, 0xec, 0x54, 0x5b, 0x4c, 0x75, 0xd0, 0x8b, 0x6e, 0x9c, + 0x4c, 0x5a, 0xf7, 0x23, 0x25, 0x48, 0xd4, 0x54, 0x45, 0x63, 0x8d, 0x71, + 0x94, 0xa1, 0x99, 0xef, 0x15, 0x34, 0xe8, 0x12, 0x41, 0xea, 0xa9, 0xc7, + 0xe7, 0x67, 0xfd, 0x54, 0xe2, 0xca, 0xce, 0xea, 0x4d, 0x2f, 0x72, 0x15, + 0xd3, 0x7b, 0xaa, 0xd6, 0xb0, 0x5e, 0x28, 0xea, 0x09, 0x34, 0x97, 0xe2, + 0xe8, 0xe1, 0xdb, 0x6e, 0x41, 0xa5, 0xeb, 0x13, 0xff, 0xa4, 0xca, 0xa2, + 0x71, 0x08, 0xf2, 0x26, 0x3a, 0x74, 0xcf, 0x54, 0xbd, 0x5b, 0x6a, 0x6b, + 0x62, 0x28, 0x4b, 0xac, 0x99, 0xfd, 0x79, 0x77, 0xaa, 0xa8, 0xff, 0xff, + 0x18, 0xfa, 0x8a, 0x70, 0xab, 0x0d, 0xeb, 0xdf +}; +static const uint8_t ac_dsa_vect296_priv_val[] = { +/* X */ + 0xba, 0xde, 0xce, 0x34, 0x25, 0x7d, 0xa3, 0xd7, 0xb8, 0x71, 0x3f, 0x8f, + 0x0f, 0x9f, 0x01, 0x07, 0xb1, 0x90, 0x9c, 0x7f, 0x99, 0xa7, 0x65, 0xad, + 0x84, 0x05, 0xd8, 0xc2, 0xa2, 0x03, 0x10, 0xee +}; +static const uint8_t ac_dsa_vect296_pub_val[] = { +/* Y */ + 0x73, 0x55, 0x4a, 0x69, 0xe1, 0xa0, 0x9f, 0x61, 0x91, 0xf0, 0xad, 0xed, + 0x54, 0x2a, 0x07, 0x7e, 0xe8, 0xc8, 0x14, 0x26, 0x5d, 0x74, 0x5d, 0x9a, + 0xe5, 0xc7, 0x92, 0xf4, 0x42, 0xc5, 0xfa, 0x47, 0xb3, 0x46, 0x43, 0xd3, + 0xba, 0x1d, 0x51, 0x47, 0x16, 0x18, 0x98, 0xde, 0x51, 0x88, 0xa8, 0x07, + 0x14, 0xee, 0x36, 0x51, 0x2a, 0x61, 0x8a, 0x33, 0xe4, 0x03, 0x00, 0xff, + 0x11, 0x87, 0xe5, 0x53, 0xf5, 0x44, 0x33, 0xe1, 0x74, 0x66, 0xaf, 0x48, + 0x64, 0x72, 0xbc, 0x07, 0x78, 0xaf, 0x55, 0xba, 0x73, 0x46, 0xc9, 0x61, + 0xd7, 0xf1, 0x3a, 0xc6, 0xd8, 0xd6, 0xac, 0x9a, 0x42, 0x09, 0x2c, 0x01, + 0x57, 0x9e, 0xe2, 0x17, 0x05, 0x90, 0xcb, 0xc3, 0xb4, 0x5e, 0xef, 0x79, + 0x5b, 0x5d, 0x9e, 0x5d, 0x0a, 0x84, 0x49, 0x43, 0x9a, 0xb3, 0x07, 0xc1, + 0x4c, 0x56, 0x74, 0xc4, 0xa7, 0xa3, 0xea, 0xf8, 0xb2, 0x40, 0xef, 0x36, + 0xdd, 0x21, 0xf4, 0x3c, 0xce, 0xd5, 0x8c, 0x2d, 0xcf, 0x23, 0xc3, 0x14, + 0x36, 0x4e, 0x8e, 0x31, 0x4e, 0x96, 0x71, 0xe8, 0x08, 0x13, 0xd1, 0x85, + 0x80, 0x13, 0x58, 0xd5, 0xdf, 0x61, 0xd7, 0xe7, 0xec, 0x0d, 0xd6, 0x9e, + 0x90, 0xc2, 0xcc, 0x75, 0xc1, 0xc3, 0x54, 0x3e, 0xfe, 0xca, 0x82, 0xb2, + 0xec, 0x6e, 0xc5, 0x9e, 0x6c, 0x99, 0xbc, 0xd1, 0xa8, 0x63, 0x1c, 0x62, + 0x28, 0xe2, 0x16, 0x88, 0x40, 0x82, 0xda, 0x11, 0x91, 0x25, 0xcb, 0x0a, + 0x80, 0xc8, 0xfe, 0x34, 0x4a, 0xfe, 0x66, 0xe0, 0xf2, 0x06, 0x46, 0x43, + 0x24, 0x65, 0xf3, 0xe0, 0x09, 0x6a, 0x17, 0x72, 0x5a, 0x88, 0x67, 0xb3, + 0xbd, 0xba, 0x3c, 0x69, 0xa1, 0xaa, 0xcb, 0xb8, 0xd6, 0x47, 0x55, 0xb7, + 0xf2, 0xa3, 0xdf, 0x0a, 0x49, 0xba, 0x0b, 0x21, 0x14, 0xe1, 0x12, 0xd4, + 0xca, 0xe0, 0xad, 0x6d, 0x8d, 0x0f, 0xd6, 0x18, 0xe5, 0x4d, 0x53, 0xf0, + 0x7b, 0xa1, 0x09, 0xb7, 0x5a, 0x54, 0xa9, 0x89, 0x61, 0x8b, 0x28, 0x63, + 0xe4, 0x41, 0x5e, 0x17, 0x6e, 0x0b, 0xfd, 0x88, 0xdb, 0xf3, 0x65, 0x53, + 0xca, 0x85, 0x3b, 0xb3, 0x63, 0x16, 0xc6, 0x6e, 0xb9, 0x3d, 0xa3, 0x4f, + 0xf3, 0xae, 0x74, 0xcd, 0x5f, 0x18, 0x7f, 0x49, 0xbf, 0x38, 0xaf, 0x0f, + 0x39, 0x3b, 0x2d, 0x7f, 0x85, 0x4d, 0xf1, 0x92, 0xad, 0xe2, 0xdf, 0x6b, + 0x39, 0xa1, 0x76, 0xd2, 0x15, 0x2c, 0x91, 0x2b, 0xba, 0x24, 0x8d, 0x84, + 0xa5, 0xb0, 0xaa, 0x40, 0x84, 0xa1, 0x8b, 0xb6, 0x4f, 0xd1, 0x36, 0x97, + 0x3f, 0x73, 0xb4, 0x13, 0xd7, 0x7d, 0xb2, 0x75, 0xea, 0x5e, 0xce, 0x93, + 0xce, 0x2f, 0xa0, 0x0d, 0x7c, 0x88, 0x87, 0xb7, 0xe5, 0x0b, 0x00, 0x64, + 0x9d, 0x03, 0x53, 0xa7, 0xf5, 0x8c, 0xc6, 0x3f, 0x6b, 0x5f, 0xbd, 0xfc +}; +/* K = 2d468a99e315c158a1af18abd4d58872d6e281dcd4c9b0b43298eddf346496d7 */ +static const uint8_t ac_dsa_vect296_out[] = { +/* R */ + 0x54, 0xff, 0x5d, 0x3d, 0xc8, 0x76, 0x78, 0x56, 0xa1, 0x0f, 0x54, 0x08, + 0x88, 0x82, 0xe2, 0x8c, 0x11, 0x09, 0x80, 0xef, 0x9b, 0x20, 0x4e, 0xb5, + 0xf1, 0x62, 0xdb, 0xef, 0x73, 0xa3, 0x7c, 0x73, +/* S */ + 0x57, 0xed, 0x07, 0x48, 0x42, 0x7c, 0x08, 0x9d, 0x63, 0x95, 0x52, 0x8b, + 0x2b, 0x45, 0x55, 0xc0, 0x1b, 0x4c, 0x13, 0x41, 0xab, 0x5f, 0xb9, 0x9c, + 0x64, 0xd1, 0xcc, 0x24, 0x7a, 0x41, 0xc3, 0xa8 +}; +#define ac_dsa_vect297_prime ac_dsa_vect286_prime +#define ac_dsa_vect297_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect297_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect297_ptx[] = { +/* Msg */ + 0xba, 0xeb, 0x12, 0xa1, 0xeb, 0xd8, 0x05, 0x7a, 0x99, 0xa0, 0x13, 0x7e, + 0xe6, 0x0f, 0x60, 0xee, 0xd1, 0x0d, 0x26, 0xf1, 0xea, 0xb2, 0x2a, 0xe2, + 0xd9, 0xad, 0xbc, 0x3e, 0x5f, 0xfc, 0x32, 0x52, 0xab, 0xf6, 0x2b, 0x61, + 0x47, 0x07, 0xad, 0x25, 0x46, 0x14, 0x1b, 0xed, 0x77, 0x9f, 0x0c, 0xfa, + 0xd9, 0x54, 0x4a, 0x74, 0xe5, 0x62, 0xda, 0x54, 0x9e, 0x2f, 0x7b, 0x28, + 0x6e, 0xfb, 0x61, 0x54, 0x49, 0xb0, 0x94, 0x6d, 0xc7, 0xc4, 0x98, 0xd8, + 0xf1, 0x21, 0x50, 0xb2, 0xea, 0xcb, 0xd2, 0x71, 0x57, 0x96, 0x6f, 0x59, + 0x2a, 0xd5, 0xf3, 0xe4, 0x3a, 0x24, 0xc6, 0x0b, 0x7e, 0x06, 0x63, 0x0b, + 0x82, 0xa4, 0xfd, 0xb6, 0x99, 0x11, 0x9d, 0xbd, 0x87, 0x8b, 0x13, 0xa9, + 0x8b, 0xf2, 0x2a, 0x7b, 0x3d, 0xc7, 0xef, 0xdd, 0x99, 0x2c, 0xe6, 0xb8, + 0xa9, 0x50, 0xe6, 0x12, 0x99, 0xc5, 0x66, 0x3b +}; +static const uint8_t ac_dsa_vect297_priv_val[] = { +/* X */ + 0xbd, 0x30, 0x06, 0xcf, 0x5d, 0x3a, 0xc0, 0x4a, 0x8a, 0x51, 0x28, 0x14, + 0x0d, 0xf6, 0x02, 0x5d, 0x99, 0x42, 0xd7, 0x85, 0x44, 0xe9, 0xb2, 0x7e, + 0xfe, 0x28, 0xb2, 0xca, 0x1f, 0x79, 0xe3, 0x13 +}; +static const uint8_t ac_dsa_vect297_pub_val[] = { +/* Y */ + 0x00, 0x72, 0x8e, 0x23, 0xe7, 0x4b, 0xb8, 0x2d, 0xe0, 0xe1, 0x31, 0x5d, + 0x58, 0x16, 0x4a, 0x5c, 0xec, 0xc8, 0x95, 0x1d, 0x89, 0xe8, 0x8d, 0xa7, + 0x02, 0xf5, 0xb8, 0x78, 0x02, 0x0f, 0xd8, 0xd2, 0xa1, 0x79, 0x1b, 0x3e, + 0x8a, 0xb7, 0x70, 0xe0, 0x84, 0xac, 0x23, 0x97, 0xd2, 0x97, 0x97, 0x1c, + 0xa8, 0x70, 0x8a, 0x30, 0xa4, 0x09, 0x7d, 0x86, 0x74, 0x01, 0x53, 0xee, + 0x2d, 0xb6, 0xab, 0x63, 0x43, 0xc5, 0xb6, 0xcc, 0x2c, 0x8a, 0x7f, 0xa5, + 0x90, 0x82, 0xa8, 0xd6, 0x59, 0x93, 0x1c, 0xc4, 0x8a, 0x04, 0x33, 0xa0, + 0x33, 0xdb, 0xb2, 0xff, 0xf3, 0xaa, 0x54, 0x56, 0x86, 0xf9, 0x22, 0xc7, + 0x06, 0x3d, 0xa1, 0xd5, 0x2d, 0x96, 0x88, 0x14, 0x2e, 0xc6, 0x4a, 0x10, + 0x02, 0x94, 0x8e, 0x5d, 0xa8, 0x91, 0x65, 0xd9, 0xdf, 0x8e, 0xed, 0x9a, + 0xa4, 0x69, 0xb6, 0x1e, 0xe0, 0x21, 0x0b, 0x40, 0x33, 0x56, 0x23, 0x33, + 0x09, 0x7b, 0xa8, 0x65, 0x99, 0x44, 0xe5, 0xf7, 0x92, 0x4e, 0x04, 0xa2, + 0x1b, 0xc3, 0xed, 0xc6, 0xd5, 0x51, 0xe2, 0x02, 0xe4, 0xc5, 0x43, 0xe9, + 0x75, 0x18, 0xf9, 0x1e, 0x0c, 0xab, 0x49, 0x11, 0x10, 0x29, 0xb2, 0x9c, + 0x3a, 0xa1, 0xbe, 0xd5, 0xf3, 0x5e, 0x5c, 0x90, 0xfe, 0xb9, 0xd3, 0xc7, + 0x45, 0x95, 0x3d, 0xbf, 0x85, 0x9d, 0xef, 0xce, 0x45, 0x37, 0xb4, 0xa0, + 0x98, 0x01, 0xfd, 0xc8, 0xfe, 0x69, 0x99, 0xfb, 0xde, 0x39, 0x90, 0x80, + 0x79, 0x81, 0x1b, 0x4b, 0x99, 0x2c, 0x2e, 0x83, 0x33, 0xb9, 0xf8, 0x00, + 0xea, 0x0d, 0x9f, 0x0a, 0x5f, 0x53, 0x60, 0x7e, 0x30, 0x89, 0x42, 0xe6, + 0x8e, 0xfe, 0xf0, 0x1e, 0x03, 0xd7, 0xcc, 0xa6, 0xf1, 0x96, 0x87, 0x2b, + 0xf0, 0x1f, 0x43, 0x6d, 0x4a, 0x8e, 0x05, 0xfc, 0x59, 0xd8, 0xfb, 0xc6, + 0xb8, 0x8a, 0x16, 0x6f, 0x57, 0xa4, 0xe9, 0x9d, 0x67, 0xdd, 0xae, 0xce, + 0x84, 0x46, 0x53, 0xbe, 0x77, 0x81, 0x97, 0x47, 0xdd, 0x2e, 0x07, 0xd5, + 0x81, 0xc5, 0x18, 0xcb, 0x97, 0x79, 0xe9, 0xf7, 0x96, 0x0c, 0x17, 0xff, + 0x0b, 0xae, 0x71, 0x0e, 0xcf, 0x57, 0x5b, 0x09, 0x59, 0x1b, 0x01, 0x3b, + 0x48, 0x05, 0xc8, 0x8b, 0x23, 0x5d, 0xf2, 0x62, 0xe6, 0x1a, 0x4c, 0x94, + 0xf4, 0x6b, 0xf9, 0xa0, 0x82, 0x84, 0x61, 0x1d, 0xf4, 0x4e, 0xad, 0xd9, + 0x4f, 0x44, 0xce, 0xf6, 0x22, 0x5a, 0x80, 0x8e, 0x21, 0x1e, 0x4d, 0x3a, + 0xf5, 0xe9, 0x6b, 0xce, 0x64, 0xa9, 0x0f, 0x80, 0x13, 0x87, 0x4f, 0x10, + 0x74, 0x9a, 0x83, 0x82, 0xa6, 0x02, 0x6a, 0x85, 0x5d, 0x90, 0x85, 0x34, + 0x40, 0xbf, 0xce, 0x31, 0xf2, 0x58, 0xb3, 0xa2, 0x58, 0xf7, 0xb5, 0xe6, + 0x59, 0xb4, 0x3e, 0x70, 0x2d, 0xee, 0x7c, 0x24, 0xc0, 0x2d, 0x22, 0x84 +}; +/* K = 16aedfbe554de17a3e5b83e942702bd60702d9823ba154baa6d1e7e94308324d */ +static const uint8_t ac_dsa_vect297_out[] = { +/* R */ + 0x8d, 0x35, 0x7b, 0x0b, 0x95, 0x6f, 0xb9, 0x0e, 0x8e, 0x0b, 0x9f, 0xf2, + 0x84, 0xce, 0xdc, 0x88, 0xa0, 0x4d, 0x17, 0x1a, 0x90, 0xc5, 0x99, 0x7d, + 0x8e, 0xe1, 0xe9, 0xbc, 0x4d, 0x0b, 0x35, 0xff, +/* S */ + 0xab, 0x37, 0x32, 0x9c, 0x50, 0x14, 0x5d, 0x14, 0x65, 0x05, 0x01, 0x57, + 0x04, 0xfd, 0xc4, 0xfb, 0x0f, 0xd7, 0x20, 0x7e, 0x0b, 0x11, 0xd8, 0xbe, + 0xcb, 0xad, 0x93, 0x4e, 0x62, 0x55, 0xc3, 0x0c +}; +#define ac_dsa_vect298_prime ac_dsa_vect286_prime +#define ac_dsa_vect298_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect298_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect298_ptx[] = { +/* Msg */ + 0x18, 0x4e, 0x59, 0x9a, 0x4c, 0x1d, 0xe8, 0x6c, 0x41, 0x51, 0x20, 0x57, + 0x54, 0xdf, 0x0b, 0x19, 0x12, 0xc2, 0xb3, 0xc5, 0x32, 0x55, 0x2c, 0x51, + 0xa6, 0x1c, 0x64, 0x59, 0xdb, 0x98, 0xc8, 0x3e, 0x59, 0xd4, 0xa4, 0x08, + 0x06, 0xc6, 0xa2, 0xc6, 0xb3, 0xfe, 0x74, 0xe3, 0xbb, 0x9e, 0x72, 0x0d, + 0x7d, 0x0a, 0x3c, 0xc1, 0x1e, 0xf8, 0x89, 0x59, 0xa8, 0x99, 0x0c, 0x0f, + 0xa0, 0x57, 0xa3, 0x91, 0x5f, 0xe0, 0xdd, 0x9a, 0x13, 0x8a, 0xa0, 0xec, + 0x1c, 0xb1, 0xab, 0x69, 0xd9, 0x39, 0x10, 0xd8, 0xd6, 0xf9, 0xe1, 0x4f, + 0x3b, 0x8a, 0x13, 0x5d, 0x3f, 0x03, 0x1a, 0x56, 0xc7, 0x6a, 0x9d, 0xc3, + 0xae, 0xd1, 0x96, 0x2b, 0xdf, 0x05, 0x81, 0x5c, 0x24, 0x92, 0xd1, 0x4f, + 0x23, 0x24, 0xd2, 0xda, 0x49, 0x18, 0x10, 0xd1, 0x67, 0x2b, 0x63, 0x3f, + 0x24, 0x19, 0xda, 0x4e, 0x7e, 0xbd, 0xef, 0x24 +}; +static const uint8_t ac_dsa_vect298_priv_val[] = { +/* X */ + 0xa2, 0x9e, 0x90, 0xd3, 0x3f, 0x20, 0x0b, 0x1f, 0xaf, 0x61, 0xbe, 0xe5, + 0xd9, 0x2c, 0xa8, 0xa3, 0x92, 0xb1, 0xea, 0xee, 0xaa, 0x08, 0x17, 0xce, + 0xc9, 0x8b, 0x40, 0xc9, 0x7e, 0x25, 0x01, 0x8c +}; +static const uint8_t ac_dsa_vect298_pub_val[] = { +/* Y */ + 0x60, 0x15, 0x97, 0x20, 0x02, 0x1f, 0xd2, 0xd5, 0xa2, 0xf5, 0x75, 0xb3, + 0x22, 0x09, 0x05, 0x78, 0x8d, 0x32, 0x8d, 0x0c, 0x46, 0x89, 0x5a, 0x46, + 0xbb, 0x98, 0x59, 0x42, 0x46, 0x72, 0x09, 0xec, 0x28, 0xd8, 0xdd, 0xfd, + 0xc9, 0x7e, 0xc3, 0x4d, 0xa6, 0x5b, 0x16, 0x4c, 0xf4, 0x86, 0x52, 0xac, + 0x47, 0x5d, 0x89, 0x78, 0x95, 0x9c, 0xfc, 0x43, 0x30, 0x74, 0x3e, 0xd9, + 0x81, 0x37, 0x55, 0x93, 0x91, 0xb1, 0x20, 0x4d, 0xa6, 0xb2, 0x6b, 0x45, + 0x12, 0x11, 0x40, 0x7e, 0x8f, 0xc7, 0x7d, 0x81, 0x99, 0x34, 0xc4, 0x87, + 0x09, 0xc8, 0xea, 0xdc, 0x62, 0x0f, 0x6d, 0xb2, 0x59, 0x2b, 0x65, 0x48, + 0x32, 0x65, 0x14, 0x9a, 0x32, 0x44, 0x67, 0xd9, 0x3c, 0x37, 0x5d, 0x97, + 0x23, 0x0f, 0x2b, 0x1a, 0x68, 0x28, 0x97, 0xcf, 0x6d, 0x28, 0x0d, 0xf6, + 0x1a, 0x34, 0xf2, 0x0f, 0x0c, 0x7c, 0x72, 0x9a, 0x40, 0x14, 0x19, 0x58, + 0x04, 0x48, 0x76, 0xc4, 0x4e, 0x59, 0x5d, 0x23, 0x78, 0xa7, 0xd2, 0x2c, + 0x6c, 0xda, 0x9a, 0xb8, 0x16, 0x48, 0x6c, 0x29, 0x4e, 0x4e, 0xdd, 0xea, + 0x7a, 0xda, 0x88, 0xb1, 0x5e, 0xca, 0x53, 0x71, 0xda, 0x16, 0x44, 0x71, + 0xed, 0xaf, 0xcd, 0xef, 0xc6, 0x54, 0xe6, 0x4a, 0x1f, 0x99, 0x50, 0x68, + 0xfa, 0x85, 0xdb, 0xbb, 0x55, 0x16, 0x13, 0x7b, 0xc4, 0x42, 0xf6, 0x07, + 0x17, 0xfe, 0x59, 0xc6, 0x29, 0x08, 0x1c, 0x23, 0x4f, 0x27, 0x19, 0x5d, + 0x5f, 0x9c, 0x2b, 0xf8, 0x5c, 0xdc, 0x1e, 0xa4, 0xca, 0xe5, 0x7a, 0xa9, + 0x08, 0xcb, 0xff, 0x9b, 0x2a, 0x53, 0x35, 0x3b, 0x13, 0xe9, 0xf6, 0xfe, + 0x45, 0xda, 0xa5, 0x17, 0x4c, 0xd9, 0x56, 0x23, 0x6d, 0x44, 0x7b, 0x52, + 0x01, 0x1d, 0x68, 0x8c, 0xd2, 0x2f, 0x23, 0x01, 0x84, 0x09, 0xb3, 0x9a, + 0x36, 0x07, 0x9c, 0xb5, 0x3e, 0x03, 0xb6, 0xd3, 0xa7, 0x52, 0x73, 0x32, + 0x97, 0xfe, 0xa4, 0xca, 0x27, 0xc6, 0x39, 0x5b, 0xec, 0xef, 0x40, 0x81, + 0xd2, 0x01, 0xf4, 0x1d, 0x4a, 0x00, 0xe9, 0x9d, 0x95, 0xf4, 0x22, 0x81, + 0xdc, 0xf4, 0x4b, 0x9e, 0xf6, 0x75, 0x49, 0x98, 0xd9, 0x42, 0x31, 0x93, + 0x7c, 0x82, 0x59, 0x42, 0x18, 0xa7, 0x84, 0x63, 0xcc, 0x83, 0x71, 0x93, + 0xde, 0x6b, 0xf1, 0xd3, 0xc3, 0xec, 0x31, 0xd8, 0xdc, 0x54, 0x68, 0xcb, + 0x56, 0xde, 0xfc, 0x9c, 0x70, 0xd0, 0x8b, 0x95, 0xb0, 0x29, 0xd9, 0x7a, + 0xa0, 0x43, 0xd5, 0x57, 0xf6, 0x28, 0x6b, 0x87, 0xee, 0x40, 0x98, 0x44, + 0x2d, 0xf4, 0x95, 0xc0, 0xad, 0x8a, 0xe4, 0xd4, 0xae, 0x03, 0x73, 0x12, + 0xc5, 0xf7, 0x23, 0x90, 0x32, 0xc0, 0x3b, 0x08, 0x8c, 0x10, 0x36, 0xfa, + 0xd7, 0x77, 0x4b, 0x15, 0x19, 0x70, 0x92, 0x42, 0xc9, 0x51, 0x1e, 0x6e +}; +/* K = 78e781b2874ca2441e2ce74a2a2a16417b51537eca876831f6593ae25fbd796c */ +static const uint8_t ac_dsa_vect298_out[] = { +/* R */ + 0x07, 0x9d, 0x4d, 0xf1, 0x4a, 0xd7, 0x03, 0xa4, 0x35, 0xb2, 0x1b, 0xc7, + 0x0a, 0x03, 0x45, 0x6c, 0xa8, 0x22, 0xb8, 0x76, 0xc9, 0xac, 0xcb, 0x01, + 0x8b, 0xdd, 0xd6, 0x74, 0xbd, 0x63, 0x92, 0xd7, +/* S */ + 0x6c, 0x77, 0x65, 0xe1, 0xf1, 0xed, 0xdf, 0x91, 0x5a, 0x56, 0xa5, 0x73, + 0x90, 0xdb, 0x45, 0x63, 0x6e, 0x52, 0xf0, 0x83, 0xce, 0x44, 0x07, 0x66, + 0xad, 0x4f, 0x32, 0x58, 0x0f, 0x72, 0x24, 0x83 +}; +#define ac_dsa_vect299_prime ac_dsa_vect286_prime +#define ac_dsa_vect299_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect299_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect299_ptx[] = { +/* Msg */ + 0xb1, 0x89, 0xdd, 0x34, 0xf5, 0x8f, 0x3e, 0xfa, 0x85, 0xb6, 0xf9, 0x76, + 0x77, 0xed, 0xfb, 0x82, 0x66, 0x4c, 0xbe, 0x43, 0xa2, 0x55, 0x0c, 0x33, + 0x6f, 0xfa, 0x08, 0x70, 0x5b, 0xbd, 0xa2, 0x54, 0x5e, 0xf2, 0x44, 0xa2, + 0x75, 0x01, 0x4c, 0x6a, 0x26, 0x59, 0x71, 0xf4, 0xc3, 0x65, 0x8e, 0x5e, + 0x8d, 0x6a, 0x3f, 0xaf, 0xc8, 0x89, 0xf3, 0xc4, 0xed, 0xa6, 0xb5, 0x61, + 0x60, 0x92, 0x95, 0x4b, 0x15, 0xc6, 0x04, 0x35, 0xef, 0xd7, 0x68, 0x06, + 0xe2, 0x85, 0x57, 0xc0, 0x5f, 0xaa, 0xaa, 0x8a, 0x05, 0xc2, 0x62, 0x65, + 0x78, 0x40, 0x86, 0x5f, 0xf6, 0x9c, 0x51, 0x1a, 0x68, 0xd1, 0x30, 0x22, + 0xa7, 0x12, 0xd3, 0x5b, 0xde, 0x13, 0x8e, 0xb7, 0xa2, 0xf8, 0xf1, 0xa8, + 0x7b, 0x34, 0x2c, 0x7c, 0xaf, 0x38, 0x8c, 0x1a, 0x8b, 0x95, 0x07, 0x9b, + 0xc4, 0xa8, 0x00, 0x3e, 0xef, 0x84, 0xb8, 0x99 +}; +static const uint8_t ac_dsa_vect299_priv_val[] = { +/* X */ + 0x97, 0x59, 0xc2, 0x48, 0x20, 0x67, 0x0e, 0xae, 0xaf, 0x92, 0x37, 0x01, + 0x97, 0xd0, 0x03, 0x7f, 0x9f, 0x71, 0xdc, 0xc2, 0x83, 0x97, 0x0f, 0x34, + 0x11, 0x17, 0xfb, 0x56, 0xa1, 0x76, 0x40, 0x01 +}; +static const uint8_t ac_dsa_vect299_pub_val[] = { +/* Y */ + 0x05, 0xe2, 0x80, 0x31, 0x08, 0x10, 0x71, 0x5d, 0x29, 0xea, 0x1c, 0xa0, + 0x0a, 0x70, 0x03, 0x78, 0xbd, 0x59, 0x79, 0x49, 0x3b, 0x98, 0x03, 0x17, + 0x4c, 0x93, 0x2b, 0x7d, 0xad, 0xb7, 0x02, 0x9a, 0x9a, 0x9f, 0x9c, 0x91, + 0xcf, 0x8f, 0x93, 0x8a, 0xf2, 0xbc, 0xea, 0xa0, 0x52, 0xf2, 0x27, 0x3f, + 0x0d, 0xe3, 0x93, 0xb0, 0xf7, 0x54, 0x44, 0x90, 0xd6, 0x93, 0xf5, 0x29, + 0xa6, 0x8b, 0x81, 0x2e, 0x2e, 0x58, 0x9c, 0xc0, 0x92, 0xb8, 0x3e, 0xf8, + 0x47, 0xc5, 0x30, 0x60, 0x39, 0xaa, 0x8e, 0xaf, 0x22, 0x51, 0x28, 0x92, + 0x61, 0x45, 0x89, 0x3a, 0x51, 0x55, 0x1d, 0xb3, 0x82, 0xfd, 0xa4, 0xb6, + 0x3e, 0x5a, 0xbc, 0x10, 0xfd, 0x07, 0x61, 0x00, 0x68, 0x4d, 0x4c, 0xa6, + 0x57, 0xc8, 0x9b, 0x22, 0x65, 0xde, 0x6e, 0x0f, 0x04, 0x73, 0xf0, 0x1b, + 0xb2, 0x22, 0xb2, 0xbc, 0x50, 0xec, 0x1c, 0x5f, 0xcd, 0xe9, 0x16, 0x18, + 0x31, 0x01, 0x8a, 0xab, 0x30, 0x14, 0xa9, 0x56, 0x03, 0x3b, 0xb0, 0xa8, + 0x38, 0x66, 0xdf, 0x11, 0x91, 0x58, 0x08, 0xf9, 0xe7, 0x46, 0x16, 0x45, + 0xc8, 0x9c, 0x6e, 0x17, 0xab, 0x65, 0xdb, 0xf9, 0x7c, 0xbf, 0x4a, 0xc1, + 0x16, 0x4d, 0x67, 0x1a, 0x15, 0x16, 0xca, 0x81, 0x64, 0x5b, 0xc3, 0xe0, + 0x99, 0x13, 0xa0, 0x3f, 0x30, 0x64, 0x1b, 0xd0, 0x92, 0x00, 0x83, 0x57, + 0x8c, 0xa8, 0x4d, 0xf7, 0x1f, 0x62, 0xeb, 0x75, 0x6b, 0xa4, 0x45, 0xa0, + 0xdc, 0x44, 0xf8, 0x5a, 0x9e, 0x4f, 0x72, 0xce, 0x5f, 0x6b, 0xf8, 0x2c, + 0xcb, 0xd6, 0x74, 0xd2, 0xce, 0x3c, 0x4a, 0xfc, 0x30, 0x05, 0x62, 0xa7, + 0xdb, 0xd3, 0xe8, 0xab, 0x83, 0x89, 0x93, 0xf9, 0xde, 0xcc, 0x99, 0x33, + 0xdc, 0x07, 0xdc, 0x01, 0xb5, 0x02, 0xfe, 0xe5, 0xb3, 0x90, 0x46, 0x1a, + 0x8c, 0x82, 0xc4, 0xe6, 0x96, 0x15, 0xf1, 0x21, 0xb3, 0xf9, 0xfd, 0x4f, + 0x0c, 0x8b, 0x76, 0x20, 0xa2, 0x59, 0x96, 0xdf, 0x43, 0xd7, 0xcf, 0x35, + 0x5f, 0x15, 0xbe, 0x09, 0xe2, 0xc8, 0x21, 0x78, 0xc6, 0xf8, 0x83, 0x6c, + 0x36, 0xc1, 0xd3, 0xef, 0x26, 0xad, 0x05, 0x21, 0x9f, 0xb5, 0x7e, 0x85, + 0xef, 0x16, 0x2c, 0x8d, 0xd8, 0xf0, 0xe5, 0x50, 0x14, 0x76, 0x9d, 0x53, + 0xcb, 0xa4, 0x78, 0xa2, 0xaa, 0x66, 0xd9, 0x0d, 0x8a, 0xcd, 0x6c, 0xb0, + 0x48, 0x9d, 0x1e, 0xea, 0x46, 0xc2, 0xc4, 0x1b, 0xd5, 0x49, 0x5a, 0xb8, + 0xde, 0xf4, 0x3b, 0x2c, 0xd5, 0xbb, 0x26, 0x73, 0x94, 0x5c, 0x21, 0xc8, + 0x0a, 0x48, 0x33, 0xfd, 0x75, 0xd8, 0x84, 0xc7, 0x67, 0x5c, 0x09, 0xe7, + 0x19, 0x1f, 0xb2, 0x6e, 0x92, 0xc5, 0x4c, 0x7c, 0x82, 0x08, 0xd0, 0xa0, + 0xe8, 0xde, 0xe7, 0x5c, 0x29, 0x68, 0xe9, 0x62, 0xde, 0x44, 0x93, 0xe8 +}; +/* K = 86050bf276a649b13c18814430eadcff54edf7416f1a8b1559c6c2c808e8dc9f */ +static const uint8_t ac_dsa_vect299_out[] = { +/* R */ + 0x9f, 0xd1, 0x05, 0xc7, 0x4a, 0x0d, 0x36, 0x97, 0x37, 0x40, 0x86, 0x7c, + 0xcc, 0x1c, 0x73, 0x1c, 0xf1, 0xc5, 0x0c, 0x79, 0x35, 0xd5, 0xc0, 0x9e, + 0x92, 0xf5, 0x74, 0xd7, 0xa5, 0x69, 0x15, 0x7e, +/* S */ + 0x50, 0x1f, 0x50, 0xc3, 0x2b, 0x02, 0x88, 0x67, 0x2e, 0x02, 0xac, 0xa7, + 0x8f, 0x90, 0xf4, 0x46, 0xac, 0xf9, 0x26, 0x26, 0x36, 0x59, 0x57, 0xa3, + 0x75, 0x55, 0x0c, 0x77, 0x98, 0x0c, 0x3c, 0x17 +}; +#define ac_dsa_vect300_prime ac_dsa_vect286_prime +#define ac_dsa_vect300_sub_prime ac_dsa_vect286_sub_prime +#define ac_dsa_vect300_base ac_dsa_vect286_base +static const uint8_t ac_dsa_vect300_ptx[] = { +/* Msg */ + 0x42, 0xc0, 0x65, 0xfa, 0xdd, 0x56, 0xd6, 0xa1, 0xfe, 0x68, 0xdd, 0x4e, + 0x86, 0xc1, 0x7e, 0xfd, 0x76, 0xd0, 0xf9, 0xdb, 0x87, 0x03, 0x6b, 0xd7, + 0xb6, 0x09, 0x15, 0x9d, 0x66, 0x84, 0x7f, 0x46, 0xde, 0x01, 0xb8, 0xae, + 0x43, 0x59, 0x03, 0x60, 0xfa, 0x32, 0x45, 0x59, 0xa2, 0xd7, 0x09, 0xd4, + 0x5c, 0xf0, 0x10, 0x34, 0xf5, 0xfa, 0xcb, 0x7f, 0x52, 0x32, 0x4e, 0x60, + 0xdd, 0x46, 0x4a, 0x58, 0x3d, 0x42, 0xe4, 0x12, 0x65, 0x9d, 0x84, 0x20, + 0xf7, 0x26, 0x5e, 0x30, 0xcf, 0x82, 0xbb, 0xbc, 0xb2, 0xc9, 0x9b, 0x0f, + 0x00, 0xca, 0x6a, 0x46, 0xd2, 0x85, 0x56, 0x42, 0x87, 0x89, 0xf4, 0x15, + 0x00, 0x0d, 0xc3, 0x1b, 0xab, 0xbd, 0x67, 0xcc, 0xc8, 0xfb, 0xaa, 0x84, + 0xa8, 0x80, 0x46, 0x6b, 0xca, 0x47, 0x83, 0xea, 0xf0, 0x0b, 0x7f, 0x78, + 0x23, 0x1c, 0x66, 0x71, 0x26, 0x43, 0x3e, 0x6a +}; +static const uint8_t ac_dsa_vect300_priv_val[] = { +/* X */ + 0x30, 0x75, 0x55, 0x89, 0x36, 0x10, 0xe1, 0x55, 0x49, 0xa5, 0xbf, 0xb2, + 0xb4, 0x46, 0x25, 0x1f, 0x95, 0x95, 0xeb, 0x0c, 0x16, 0xdf, 0x5f, 0xe3, + 0xb7, 0x84, 0xeb, 0xfc, 0x3f, 0xc3, 0x01, 0x40 +}; +static const uint8_t ac_dsa_vect300_pub_val[] = { +/* Y */ + 0xb2, 0x65, 0xed, 0xfe, 0xd7, 0x7b, 0x3a, 0xd5, 0x11, 0xe5, 0x6d, 0x58, + 0x31, 0x29, 0xb1, 0x2e, 0x57, 0x96, 0xd6, 0x59, 0xd4, 0x84, 0xa2, 0xfc, + 0xe3, 0x50, 0x66, 0x1f, 0x79, 0xe5, 0x45, 0xdd, 0x0a, 0x06, 0xc2, 0x37, + 0x74, 0xc8, 0xba, 0x2f, 0xb5, 0x10, 0x1a, 0x28, 0x48, 0xc4, 0x13, 0xdf, + 0xc5, 0xb3, 0x74, 0xa7, 0xc5, 0xff, 0x3a, 0xcc, 0x73, 0x32, 0xf0, 0xff, + 0x8b, 0xd6, 0xf5, 0xfa, 0x88, 0x2c, 0x0a, 0x67, 0x68, 0x93, 0x08, 0xbe, + 0x71, 0x54, 0xc4, 0xef, 0xc5, 0x18, 0x35, 0xf3, 0x49, 0x52, 0x54, 0x19, + 0xed, 0x72, 0x2a, 0x90, 0xbf, 0x26, 0xdd, 0xde, 0xd6, 0x5b, 0xc8, 0x96, + 0x2b, 0xa1, 0x1d, 0xe9, 0xe7, 0x34, 0x44, 0x25, 0x71, 0xaf, 0xfc, 0x2d, + 0x42, 0xb9, 0xf3, 0xf5, 0x4a, 0x46, 0x53, 0x5a, 0xe9, 0xeb, 0x01, 0x36, + 0x1a, 0xdf, 0x03, 0xfc, 0x28, 0x41, 0x0a, 0xbf, 0x41, 0xdb, 0x3a, 0xe4, + 0x11, 0x3d, 0xa4, 0xc4, 0x0e, 0x9a, 0x36, 0x8f, 0x9c, 0xd0, 0x29, 0xbe, + 0x4d, 0x98, 0xc6, 0x6d, 0x83, 0x5d, 0x03, 0x4e, 0x3c, 0x86, 0x54, 0x4b, + 0x60, 0xbc, 0xb0, 0x1f, 0xeb, 0x38, 0x3b, 0x2a, 0xdd, 0x9a, 0xfe, 0x7b, + 0x62, 0x51, 0xa1, 0x7a, 0xd4, 0xe5, 0x43, 0x9a, 0x9c, 0xd2, 0xd1, 0xbf, + 0x62, 0xb6, 0xcf, 0x53, 0x77, 0xc0, 0x97, 0xb7, 0x26, 0x8b, 0xd7, 0x36, + 0xcc, 0xa9, 0xce, 0xb8, 0x22, 0xe5, 0xd1, 0x84, 0x4a, 0x09, 0xfa, 0x69, + 0xc7, 0x82, 0x17, 0xc3, 0xd6, 0x73, 0x7f, 0x0b, 0xf4, 0x5e, 0x32, 0x36, + 0x50, 0x8b, 0x5a, 0x3f, 0x5c, 0x46, 0x6d, 0xd0, 0xd7, 0x5a, 0xce, 0x95, + 0xd4, 0x47, 0xf9, 0xbd, 0x7a, 0xa9, 0xee, 0x57, 0xbd, 0x10, 0xee, 0x3c, + 0x5e, 0x83, 0x89, 0xa0, 0x6c, 0x00, 0x85, 0x7e, 0x69, 0x97, 0x94, 0xf5, + 0xca, 0xcc, 0x7d, 0xc5, 0xbb, 0x15, 0x04, 0x42, 0x1d, 0xc9, 0x20, 0x56, + 0x56, 0x18, 0xbe, 0xf0, 0x5d, 0xc1, 0x71, 0x3b, 0x6f, 0x08, 0xbc, 0x00, + 0x68, 0x1c, 0x5a, 0x1c, 0x06, 0x85, 0x35, 0x97, 0x29, 0xfe, 0x4b, 0x54, + 0x40, 0x90, 0xcc, 0xce, 0xaa, 0x82, 0xf4, 0xfe, 0xfa, 0x9f, 0x11, 0x17, + 0xbf, 0x1e, 0x37, 0x1b, 0x99, 0xfe, 0x4e, 0xd7, 0x16, 0x35, 0xda, 0xd4, + 0x15, 0x01, 0x7a, 0x62, 0x34, 0x1d, 0x70, 0x42, 0x27, 0xee, 0x7c, 0xfb, + 0x64, 0xa8, 0xde, 0xae, 0x90, 0xd8, 0x6c, 0x0c, 0xfd, 0x37, 0xed, 0x36, + 0x3d, 0x91, 0xa4, 0xa0, 0x6f, 0xd0, 0x6f, 0x64, 0xdb, 0xd8, 0x14, 0x2c, + 0x12, 0x50, 0x3f, 0x49, 0xee, 0xb1, 0xb9, 0xa9, 0x71, 0xae, 0xb3, 0x43, + 0xf1, 0x5c, 0xd2, 0x7d, 0x27, 0x9b, 0x99, 0xd4, 0xcf, 0xa5, 0x1f, 0x12, + 0x12, 0x59, 0xb3, 0xc1, 0xb5, 0x5d, 0x28, 0xd9, 0x94, 0xbb, 0x32, 0x99 +}; +/* K = 5359fe067eb9d98ec2217500de743b0dbe88e8d94552b53a0117aac4d3390083 */ +static const uint8_t ac_dsa_vect300_out[] = { +/* R */ + 0x6e, 0xd8, 0x2a, 0xf8, 0xe8, 0x9e, 0x38, 0xc4, 0x9a, 0x58, 0x01, 0x0f, + 0x05, 0x64, 0x16, 0x5a, 0x16, 0xa7, 0x6a, 0x2b, 0xfb, 0x34, 0x84, 0x66, + 0xd9, 0xb4, 0xa9, 0x1e, 0x5c, 0xe5, 0x3a, 0xb2, +/* S */ + 0x8c, 0x46, 0x6a, 0x8b, 0x3e, 0x4c, 0x90, 0x88, 0x6f, 0x29, 0x98, 0x6a, + 0x4d, 0x51, 0x39, 0x04, 0xf3, 0x1d, 0xb4, 0x3a, 0x68, 0xce, 0x88, 0x03, + 0x11, 0x40, 0x3c, 0xc7, 0x55, 0x46, 0x66, 0x04 +}; diff --git a/optee/optee_test/host/xtest/nist/ecccdhtestvectors.h b/optee/optee_test/host/xtest/nist/ecccdhtestvectors.h new file mode 100644 index 0000000..256802d --- /dev/null +++ b/optee/optee_test/host/xtest/nist/ecccdhtestvectors.h @@ -0,0 +1,11245 @@ +/* + * ECDH Test data automatically generated from + * http://csrc.nist.gov/groups/STM/cavp/documents/components/ecccdhtestvectors.zip + * KAS_ECC_CDH_PrimitiveTest.txt + */ +/* [P-192] */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_1_public_x[] = { +/* QCAVSx */ + 0x42, 0xea, 0x6d, 0xd9, 0x96, 0x9d, 0xd2, 0xa6, 0x1f, 0xea, 0x1a, 0xac, + 0x7f, 0x8e, 0x98, 0xed, 0xcc, 0x89, 0x6c, 0x6e, 0x55, 0x85, 0x7c, 0xc0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_1_public_y[] = { +/* QCAVSy */ + 0xdf, 0xbe, 0x5d, 0x7c, 0x61, 0xfa, 0xc8, 0x8b, 0x11, 0x81, 0x1b, 0xde, + 0x32, 0x8e, 0x8a, 0x0d, 0x12, 0xbf, 0x01, 0xa9, 0xd2, 0x04, 0xb5, 0x23 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_1_private[] = { +/* dIUT */ + 0xf1, 0x7d, 0x3f, 0xea, 0x36, 0x7b, 0x74, 0xd3, 0x40, 0x85, 0x1c, 0xa4, + 0x27, 0x0d, 0xcb, 0x24, 0xc2, 0x71, 0xf4, 0x45, 0xbe, 0xd9, 0xd5, 0x27 +}; +/* QIUTx = b15053401f57285637ec324c1cd2139e3a67de3739234b37 */ +/* QIUTy = f269c158637482aad644cd692dd1d3ef2c8a7c49e389f7f6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_1_out[] = { +/* ZIUT */ + 0x80, 0x3d, 0x8a, 0xb2, 0xe5, 0xb6, 0xe6, 0xfc, 0xa7, 0x15, 0x73, 0x7c, + 0x3a, 0x82, 0xf7, 0xce, 0x3c, 0x78, 0x31, 0x24, 0xf6, 0xd5, 0x1c, 0xd0 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_2_public_x[] = { +/* QCAVSx */ + 0xde, 0xb5, 0x71, 0x2f, 0xa0, 0x27, 0xac, 0x8d, 0x2f, 0x22, 0xc4, 0x55, + 0xcc, 0xb7, 0x3a, 0x91, 0xe1, 0x7b, 0x65, 0x12, 0xb5, 0xe0, 0x30, 0xe7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_2_public_y[] = { +/* QCAVSy */ + 0x7e, 0x26, 0x90, 0xa0, 0x2c, 0xc9, 0xb2, 0x87, 0x08, 0x43, 0x1a, 0x29, + 0xfb, 0x54, 0xb8, 0x7b, 0x1f, 0x0c, 0x14, 0xe0, 0x11, 0xac, 0x21, 0x25 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_2_private[] = { +/* dIUT */ + 0x56, 0xe8, 0x53, 0x34, 0x9d, 0x96, 0xfe, 0x4c, 0x44, 0x24, 0x48, 0xda, + 0xcb, 0x7c, 0xf9, 0x2b, 0xb7, 0xa9, 0x5d, 0xcf, 0x57, 0x4a, 0x9b, 0xd5 +}; +/* QIUTx = c00d435716ffea53fd8c162792414c37665187e582716539 */ +/* QIUTy = ab711c62aa71a5a18e8a3c48f89dc6fa52fac0108e52a8a0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_2_out[] = { +/* ZIUT */ + 0xc2, 0x08, 0x84, 0x75, 0x68, 0xb9, 0x88, 0x35, 0xd7, 0x31, 0x2c, 0xef, + 0x1f, 0x97, 0xf7, 0xaa, 0x29, 0x82, 0x83, 0x15, 0x23, 0x13, 0xc2, 0x9d +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_3_public_x[] = { +/* QCAVSx */ + 0x4e, 0xda, 0xa8, 0xef, 0xc5, 0xa0, 0xf4, 0x0f, 0x84, 0x36, 0x63, 0xec, + 0x58, 0x15, 0xe7, 0x76, 0x2d, 0xdd, 0xc0, 0x08, 0xe6, 0x63, 0xc2, 0x0f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_3_public_y[] = { +/* QCAVSy */ + 0x0a, 0x9f, 0x8d, 0xc6, 0x7a, 0x3e, 0x60, 0xef, 0x6d, 0x64, 0xb5, 0x22, + 0x18, 0x5d, 0x03, 0xdf, 0x1f, 0xc0, 0xad, 0xfd, 0x42, 0x47, 0x82, 0x79 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_3_private[] = { +/* dIUT */ + 0xc6, 0xef, 0x61, 0xfe, 0x12, 0xe8, 0x0b, 0xf5, 0x6f, 0x2d, 0x3f, 0x7d, + 0x0b, 0xb7, 0x57, 0x39, 0x45, 0x19, 0x90, 0x6d, 0x55, 0x50, 0x09, 0x49 +}; +/* QIUTx = e184bc182482f3403c8787b83842477467fcd011db0f6c64 */ +/* QIUTy = f9d1c14142f40de8639db97d51a63d2cce1007ccf773cdcb */ +static const uint8_t nist_kas_ecc_cdh_testvector_3_out[] = { +/* ZIUT */ + 0x87, 0x22, 0x91, 0x07, 0x04, 0x7a, 0x3b, 0x61, 0x19, 0x20, 0xd6, 0xe3, + 0xb2, 0xc0, 0xc8, 0x9b, 0xea, 0x4f, 0x49, 0x41, 0x22, 0x60, 0xb8, 0xdd +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_4_public_x[] = { +/* QCAVSx */ + 0x88, 0x87, 0xc2, 0x76, 0xed, 0xee, 0xd3, 0xe9, 0xe8, 0x66, 0xb4, 0x6d, + 0x58, 0xd8, 0x95, 0xc7, 0x3f, 0xbd, 0x80, 0xb6, 0x3e, 0x38, 0x2e, 0x88 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_4_public_y[] = { +/* QCAVSy */ + 0x04, 0xc5, 0x09, 0x7b, 0xa6, 0x64, 0x5e, 0x16, 0x20, 0x6c, 0xfb, 0x70, + 0xf7, 0x05, 0x26, 0x55, 0x94, 0x7d, 0xd4, 0x4a, 0x17, 0xf1, 0xf9, 0xd5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_4_private[] = { +/* dIUT */ + 0xe6, 0x74, 0x7b, 0x9c, 0x23, 0xba, 0x70, 0x44, 0xf3, 0x8f, 0xf7, 0xe6, + 0x2c, 0x35, 0xe4, 0x03, 0x89, 0x20, 0xf5, 0xa0, 0x16, 0x3d, 0x3c, 0xda +}; +/* QIUTx = 2b838dbe73735f37a39a78d3195783d26991e86ff4d92d1a */ +/* QIUTy = 60d344942274489f98903b2e7f93f8d197fc9ae60a0ed53a */ +static const uint8_t nist_kas_ecc_cdh_testvector_4_out[] = { +/* ZIUT */ + 0xee, 0xc0, 0xbe, 0xd8, 0xfc, 0x55, 0xe1, 0xfe, 0xdd, 0xc8, 0x21, 0x58, + 0xfd, 0x6d, 0xc0, 0xd4, 0x8a, 0x4d, 0x79, 0x6a, 0xaf, 0x47, 0xd4, 0x6c +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_5_public_x[] = { +/* QCAVSx */ + 0x0d, 0x04, 0x5f, 0x30, 0x25, 0x4a, 0xdc, 0x1f, 0xce, 0xfa, 0x8a, 0x5b, + 0x1f, 0x31, 0xbf, 0x4e, 0x73, 0x9d, 0xd3, 0x27, 0xcd, 0x18, 0xd5, 0x94 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_5_public_y[] = { +/* QCAVSy */ + 0x54, 0x2c, 0x31, 0x4e, 0x41, 0x42, 0x7c, 0x08, 0x27, 0x8a, 0x08, 0xce, + 0x8d, 0x73, 0x05, 0xf3, 0xb5, 0xb8, 0x49, 0xc7, 0x2d, 0x8a, 0xff, 0x73 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_5_private[] = { +/* dIUT */ + 0xbe, 0xab, 0xed, 0xd0, 0x15, 0x4a, 0x1a, 0xfc, 0xfc, 0x85, 0xd5, 0x21, + 0x81, 0xc1, 0x0f, 0x5e, 0xb4, 0x7a, 0xdc, 0x51, 0xf6, 0x55, 0x04, 0x7d +}; +/* QIUTx = 1f65cf6e8978e1c1bc10bb61a7db311de310088c8cf9768b */ +/* QIUTy = f7d438168e7f42ab14b16af53a7a2f646ff40b53d74cbcc7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_5_out[] = { +/* ZIUT */ + 0x71, 0x6e, 0x74, 0x3b, 0x1b, 0x37, 0xa2, 0xcd, 0x84, 0x79, 0xf0, 0xa3, + 0xd5, 0xa7, 0x4c, 0x10, 0xba, 0x25, 0x99, 0xbe, 0x18, 0xd7, 0xe2, 0xf4 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_6_public_x[] = { +/* QCAVSx */ + 0xfb, 0x35, 0xca, 0x20, 0xd2, 0xe9, 0x66, 0x65, 0xc5, 0x1b, 0x98, 0xe8, + 0xf6, 0xeb, 0x3d, 0x79, 0x11, 0x35, 0x08, 0xd8, 0xbc, 0xcd, 0x45, 0x16 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_6_public_y[] = { +/* QCAVSy */ + 0x36, 0x8e, 0xec, 0x0d, 0x5b, 0xfb, 0x84, 0x77, 0x21, 0xdf, 0x6a, 0xaf, + 0xf0, 0xe5, 0xd4, 0x8c, 0x44, 0x4f, 0x74, 0xbf, 0x9c, 0xd8, 0xa5, 0xa7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_6_private[] = { +/* dIUT */ + 0xcf, 0x70, 0x35, 0x42, 0x26, 0x66, 0x73, 0x21, 0xd6, 0xe2, 0xba, 0xf4, + 0x09, 0x99, 0xe2, 0xfd, 0x74, 0xc7, 0xa0, 0xf7, 0x93, 0xfa, 0x86, 0x99 +}; +/* QIUTx = 5f4844ffcce61005d24f737db98675e92f7b6543aeb6106c */ +/* QIUTy = 5424f598139215d389b6b12b86d58014857f2ddadb540f51 */ +static const uint8_t nist_kas_ecc_cdh_testvector_6_out[] = { +/* ZIUT */ + 0xf6, 0x70, 0x53, 0xb9, 0x34, 0x45, 0x99, 0x85, 0xa3, 0x15, 0xcb, 0x01, + 0x7b, 0xf0, 0x30, 0x28, 0x91, 0x79, 0x8d, 0x45, 0xd0, 0xe1, 0x95, 0x08 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_7_public_x[] = { +/* QCAVSx */ + 0x82, 0x47, 0x52, 0x96, 0x0c, 0x13, 0x07, 0xe5, 0xf1, 0x3a, 0x83, 0xda, + 0x21, 0xc7, 0x99, 0x8c, 0xa8, 0xb5, 0xb0, 0x0b, 0x95, 0x49, 0xf6, 0xd0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_7_public_y[] = { +/* QCAVSy */ + 0xbc, 0x52, 0xd9, 0x1e, 0x23, 0x43, 0x63, 0xbc, 0x32, 0xee, 0x0b, 0x67, + 0x78, 0xf2, 0x5c, 0xd8, 0xc1, 0x84, 0x75, 0x10, 0xf4, 0x34, 0x8b, 0x94 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_7_private[] = { +/* dIUT */ + 0xfe, 0x94, 0x25, 0x15, 0x23, 0x7f, 0xff, 0xdd, 0x7b, 0x4e, 0xb5, 0xc6, + 0x49, 0x09, 0xee, 0xe4, 0x85, 0x6a, 0x07, 0x6c, 0xdf, 0x12, 0xba, 0xe2 +}; +/* QIUTx = e6369df79b207b8b8679f7c869cfc264859d1ab55aa401e8 */ +/* QIUTy = 1f99c71f801a30b52f74da6e5e6dbb62ee4c5da1090cc020 */ +static const uint8_t nist_kas_ecc_cdh_testvector_7_out[] = { +/* ZIUT */ + 0x75, 0x82, 0x29, 0x71, 0x19, 0x3e, 0xdd, 0x47, 0x2b, 0xf3, 0x01, 0x51, + 0xa7, 0x82, 0x61, 0x9c, 0x55, 0xad, 0x0b, 0x27, 0x9c, 0x93, 0x03, 0xdd +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_8_public_x[] = { +/* QCAVSx */ + 0x10, 0xbb, 0x57, 0x02, 0x02, 0x91, 0x14, 0x19, 0x81, 0xf8, 0x33, 0xb4, + 0x74, 0x9e, 0x56, 0x11, 0x03, 0x4b, 0x30, 0x8e, 0x84, 0x01, 0x1d, 0x21 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_8_public_y[] = { +/* QCAVSy */ + 0xe1, 0xca, 0xcd, 0x6b, 0x7b, 0xd1, 0x7e, 0xd8, 0xdd, 0xb5, 0x0b, 0x6a, + 0xee, 0x06, 0x54, 0xc3, 0x5f, 0x2d, 0x0e, 0xdd, 0xc1, 0xcf, 0xfc, 0xf6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_8_private[] = { +/* dIUT */ + 0x33, 0xfe, 0xd1, 0x04, 0x92, 0xaf, 0xa5, 0xbe, 0xa0, 0x33, 0x3c, 0x0a, + 0xf1, 0x2c, 0xac, 0x94, 0x0c, 0x4d, 0x22, 0x24, 0x55, 0xbc, 0xd0, 0xfe +}; +/* QIUTx = ef0b28afc41637d737f42e4c8aaceadc84ba2e0b849ca18c */ +/* QIUTy = 57797942e552173bba17f73278e029f42335068bd770ddf2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_8_out[] = { +/* ZIUT */ + 0x67, 0xcb, 0xa2, 0xcb, 0xb6, 0x9e, 0xe7, 0x8b, 0xf1, 0xab, 0xaf, 0xb0, + 0xe6, 0xfb, 0xe3, 0x3f, 0xa2, 0x09, 0x4c, 0x12, 0x8d, 0x59, 0x65, 0x2d +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_9_public_x[] = { +/* QCAVSx */ + 0x51, 0x92, 0xfc, 0xe4, 0x18, 0x5a, 0x77, 0x58, 0xea, 0x1b, 0xc5, 0x6e, + 0x0e, 0x4f, 0x4e, 0x8b, 0x2d, 0xce, 0x32, 0x34, 0x8d, 0x0d, 0xce, 0xd1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_9_public_y[] = { +/* QCAVSy */ + 0x20, 0x98, 0x99, 0x81, 0xbe, 0xaa, 0xf0, 0x00, 0x6d, 0x88, 0xa9, 0x6e, + 0x79, 0x71, 0xa2, 0xfa, 0x3a, 0x33, 0xba, 0x46, 0x04, 0x7f, 0xc7, 0xba +}; +static const uint8_t nist_kas_ecc_cdh_testvector_9_private[] = { +/* dIUT */ + 0xf3, 0x55, 0x7c, 0x5d, 0x70, 0xb4, 0xc7, 0x95, 0x49, 0x60, 0xc3, 0x35, + 0x68, 0x77, 0x6a, 0xdb, 0xe8, 0xe4, 0x36, 0x19, 0xab, 0xe2, 0x6b, 0x13 +}; +/* QIUTx = d70112c5f0f0844386494ac1ad99dce2214134176ebfb9af */ +/* QIUTy = d3c187a038510ab31d459e2b7af1a380dd7576af06267548 */ +static const uint8_t nist_kas_ecc_cdh_testvector_9_out[] = { +/* ZIUT */ + 0xcf, 0x99, 0xa2, 0x77, 0x0a, 0x38, 0x6c, 0xa0, 0x13, 0x7d, 0x1e, 0xca, + 0x0a, 0x22, 0x6e, 0x48, 0x42, 0x97, 0xac, 0x3c, 0x51, 0x3f, 0x36, 0x31 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_10_public_x[] = { +/* QCAVSx */ + 0x26, 0xd0, 0x19, 0xdb, 0xe2, 0x79, 0xea, 0xd0, 0x1e, 0xed, 0x14, 0x3a, + 0x91, 0x60, 0x1a, 0xda, 0x26, 0xe2, 0xf4, 0x22, 0x25, 0xb1, 0xc6, 0x2b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_10_public_y[] = { +/* QCAVSy */ + 0x6c, 0xa6, 0x53, 0xf0, 0x82, 0x72, 0xe0, 0x38, 0x6f, 0xc9, 0x42, 0x1f, + 0xbd, 0x58, 0x00, 0x93, 0xd7, 0xae, 0x63, 0x01, 0xbc, 0xa9, 0x44, 0x76 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_10_private[] = { +/* dIUT */ + 0x58, 0x6c, 0xfb, 0xa1, 0xc6, 0xe8, 0x17, 0x66, 0xed, 0x52, 0x82, 0x8f, + 0x17, 0x7b, 0x1b, 0xe1, 0x4e, 0xbb, 0xc5, 0xb8, 0x33, 0x48, 0xc3, 0x11 +}; +/* QIUTx = 58b3c63e56bec9d696bf9a88df2873738391f76368aa2b49 */ +/* QIUTy = 5776773b261faf7ba2fdc4fe43b92c0b1c7a2fd054a43650 */ +static const uint8_t nist_kas_ecc_cdh_testvector_10_out[] = { +/* ZIUT */ + 0x57, 0x63, 0x31, 0xe2, 0xb4, 0xfb, 0x38, 0xa1, 0x12, 0x81, 0x0e, 0x15, + 0x29, 0x83, 0x4d, 0xe8, 0x30, 0x7f, 0xb0, 0xa0, 0xd2, 0x75, 0x68, 0x77 +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_11_public_x[] = { +/* QCAVSx */ + 0x53, 0x9b, 0xc4, 0x0f, 0xe2, 0x0a, 0x0f, 0xb2, 0x67, 0x88, 0x8b, 0x64, + 0x7b, 0x03, 0xea, 0xaf, 0x6e, 0xc2, 0x0c, 0x02, 0xa1, 0xe1, 0xf8, 0xc8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_11_public_y[] = { +/* QCAVSy */ + 0x69, 0x09, 0x5e, 0x5b, 0xb7, 0xb4, 0xd4, 0x4c, 0x32, 0x78, 0xa7, 0xee, + 0x6b, 0xec, 0xa3, 0x97, 0xc4, 0x52, 0x46, 0xda, 0x9a, 0x34, 0xc8, 0xbe +}; +static const uint8_t nist_kas_ecc_cdh_testvector_11_private[] = { +/* dIUT */ + 0xca, 0xd8, 0x10, 0x06, 0x03, 0xa4, 0xf6, 0x5b, 0xe0, 0x8d, 0x8f, 0xc8, + 0xa1, 0xb7, 0xe8, 0x84, 0xc5, 0xff, 0x65, 0xde, 0xb3, 0xc9, 0x6d, 0x99 +}; +/* QIUTx = b7fcc0f52c7a411edbed39e10bf02b6ae0f26614c6b325a2 */ +/* QIUTy = 47483b26eb67776de2b93ab7119d5447573739e3d55e72fb */ +static const uint8_t nist_kas_ecc_cdh_testvector_11_out[] = { +/* ZIUT */ + 0x90, 0x2f, 0x45, 0x01, 0x91, 0x6a, 0x0d, 0xd9, 0x45, 0x55, 0x4c, 0x3a, + 0x37, 0xb3, 0xd7, 0x80, 0xd3, 0x75, 0xa6, 0xda, 0x71, 0x31, 0x97, 0xc4 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_12_public_x[] = { +/* QCAVSx */ + 0x5d, 0x34, 0x3d, 0xdb, 0x96, 0x31, 0x8f, 0xb4, 0x79, 0x4d, 0x10, 0xf6, + 0xc5, 0x73, 0xf9, 0x9f, 0xee, 0x5d, 0x0d, 0x57, 0xb9, 0x96, 0x25, 0x0f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_12_public_y[] = { +/* QCAVSy */ + 0x99, 0xfb, 0xdf, 0x9d, 0x97, 0xdd, 0x88, 0xad, 0x41, 0x02, 0x35, 0xda, + 0xc3, 0x6e, 0x5b, 0x92, 0xce, 0x28, 0x24, 0xb8, 0xe5, 0x87, 0xa8, 0x2c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_12_private[] = { +/* dIUT */ + 0x1e, 0xdd, 0x87, 0x9c, 0xc5, 0xc7, 0x96, 0x19, 0xca, 0xe6, 0xc7, 0x3a, + 0x69, 0x1b, 0xd5, 0xa0, 0x39, 0x5c, 0x0e, 0xf3, 0xb3, 0x56, 0xfc, 0xd2 +}; +/* QIUTx = 6ce6adb2c30808f590048c33dffad4524ebf7a5fd39b747b */ +/* QIUTy = 4966bd2f3d00569b4d4c0409fbd7a2db752f6d09bca8c25f */ +static const uint8_t nist_kas_ecc_cdh_testvector_12_out[] = { +/* ZIUT */ + 0x46, 0xe4, 0xde, 0x33, 0x50, 0x54, 0xd4, 0x29, 0x86, 0x32, 0x18, 0xae, + 0x33, 0x63, 0x6f, 0xc9, 0xb8, 0x9c, 0x62, 0x8b, 0x64, 0xb5, 0x06, 0xc7 +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_13_public_x[] = { +/* QCAVSx */ + 0x8d, 0x3d, 0xb9, 0xbd, 0xce, 0x13, 0x7f, 0xfb, 0xfb, 0x89, 0x13, 0x88, + 0xc3, 0x7d, 0xf6, 0xc0, 0xcb, 0xc9, 0x0a, 0xa5, 0xe5, 0x37, 0x62, 0x20 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_13_public_y[] = { +/* QCAVSy */ + 0x13, 0x5d, 0x30, 0xb5, 0xcb, 0x66, 0x0e, 0xef, 0x87, 0x64, 0xff, 0xc7, + 0x44, 0xf1, 0x5c, 0x1b, 0x5d, 0x6d, 0xc0, 0x6b, 0xa4, 0x41, 0x6d, 0x37 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_13_private[] = { +/* dIUT */ + 0x46, 0x0e, 0x45, 0x22, 0x73, 0xfe, 0x18, 0x27, 0x60, 0x21, 0x87, 0xad, + 0x3b, 0xeb, 0xee, 0x65, 0xcb, 0x84, 0x42, 0x3b, 0xb4, 0xf4, 0x75, 0x37 +}; +/* QIUTx = d1bd3a3efabf4767fe6380bdf0dbf49d52d4cf0cbb89404c */ +/* QIUTy = c150c2b4c8b3aa35f765f847e4f7f8fd8704d241a181ee99 */ +static const uint8_t nist_kas_ecc_cdh_testvector_13_out[] = { +/* ZIUT */ + 0x1b, 0xfe, 0x9e, 0x5a, 0x20, 0xac, 0x7a, 0x38, 0xd8, 0xf6, 0x05, 0xb4, + 0x25, 0xbb, 0x90, 0x30, 0xbe, 0x31, 0xef, 0x97, 0xc1, 0x01, 0xc7, 0x6c +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_14_public_x[] = { +/* QCAVSx */ + 0x9e, 0x0a, 0x69, 0x49, 0x51, 0x9c, 0x7f, 0x5b, 0xe6, 0x8c, 0x04, 0x33, + 0xc5, 0xfd, 0xf1, 0x30, 0x64, 0xaa, 0x13, 0xfb, 0x29, 0x48, 0x3d, 0xc3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_14_public_y[] = { +/* QCAVSy */ + 0xe1, 0xc8, 0xba, 0x63, 0xe1, 0xf4, 0x71, 0xdb, 0x23, 0x18, 0x5f, 0x50, + 0xd9, 0xc8, 0x71, 0xed, 0xea, 0x21, 0x25, 0x5b, 0x3a, 0x63, 0xb4, 0xb7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_14_private[] = { +/* dIUT */ + 0xb9, 0x70, 0x36, 0x50, 0x08, 0x45, 0x6f, 0x87, 0x58, 0xec, 0xc5, 0xa3, + 0xb3, 0x3c, 0xf3, 0xae, 0x6a, 0x8d, 0x56, 0x81, 0x07, 0xa5, 0x21, 0x67 +}; +/* QIUTx = c1b8610c8c63f8d4abda093b9a11a566044bf65c6faa8999 */ +/* QIUTy = a5bc4b3ca095382e9738aee95fe9479b17879b3ad5295559 */ +static const uint8_t nist_kas_ecc_cdh_testvector_14_out[] = { +/* ZIUT */ + 0x0e, 0x8c, 0x49, 0x3a, 0x4a, 0xdc, 0x44, 0x5d, 0xc9, 0x28, 0x8a, 0x3b, + 0x9b, 0x27, 0x25, 0x99, 0x22, 0x40, 0x54, 0x59, 0x2d, 0x72, 0x65, 0xb3 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_15_public_x[] = { +/* QCAVSx */ + 0xbe, 0x08, 0x82, 0x38, 0x90, 0x2e, 0x99, 0x39, 0xb3, 0xd0, 0x54, 0xee, + 0xeb, 0x84, 0x92, 0xda, 0xf4, 0xbd, 0xcf, 0x09, 0xa2, 0xab, 0x77, 0xf1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_15_public_y[] = { +/* QCAVSy */ + 0x58, 0xd6, 0x74, 0x9a, 0x3a, 0x92, 0x3d, 0xc8, 0x04, 0x40, 0xf2, 0x66, + 0x1f, 0xd3, 0x5b, 0x65, 0x16, 0x17, 0xe6, 0x52, 0x94, 0xb4, 0x63, 0x75 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_15_private[] = { +/* dIUT */ + 0x59, 0xc1, 0x5b, 0x8a, 0x24, 0x64, 0xe4, 0x1d, 0xfe, 0x43, 0x71, 0xc7, + 0xf7, 0xda, 0xdf, 0x47, 0x0a, 0xe4, 0x25, 0x54, 0x4f, 0x81, 0x13, 0xbd +}; +/* QIUTx = 1fe776f73567b6ac0b0d6764164de6c5be751ba8d1ff455e */ +/* QIUTy = 4c160bf38afb2b71f684261664115ce874553e8b059432d2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_15_out[] = { +/* ZIUT */ + 0x0f, 0x19, 0x91, 0x08, 0x6b, 0x45, 0x5d, 0xed, 0x6a, 0x1c, 0x41, 0x46, + 0xf7, 0xbf, 0x59, 0xfe, 0x9b, 0x49, 0x5d, 0xe5, 0x66, 0xeb, 0xc6, 0xbf +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_16_public_x[] = { +/* QCAVSx */ + 0xbf, 0x5a, 0xe0, 0x50, 0x25, 0xe1, 0xbe, 0x61, 0x7e, 0x66, 0x6d, 0x87, + 0xa4, 0x16, 0x83, 0x63, 0x87, 0x3d, 0x57, 0x61, 0xb3, 0x76, 0xb5, 0x03 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_16_public_y[] = { +/* QCAVSy */ + 0xe1, 0xe6, 0xe3, 0x8b, 0x37, 0x2b, 0x6b, 0xee, 0x0f, 0xf5, 0xb3, 0x50, + 0x2d, 0x83, 0x73, 0x5e, 0x3b, 0x2c, 0x26, 0x82, 0x5e, 0x4f, 0x0f, 0xcc +}; +static const uint8_t nist_kas_ecc_cdh_testvector_16_private[] = { +/* dIUT */ + 0xa6, 0xe9, 0xb8, 0x85, 0xc6, 0x6b, 0x95, 0x9d, 0x1f, 0xc2, 0x70, 0x8d, + 0x59, 0x1b, 0x6d, 0x32, 0x28, 0xe4, 0x9e, 0xb9, 0x8f, 0x72, 0x6d, 0x61 +}; +/* QIUTx = 632bb7651dbf49dde9dd125d13fb234e06617723beed3d1b */ +/* QIUTy = f4ad5209638488397c5f44f994dd7479807e79f4887d2e71 */ +static const uint8_t nist_kas_ecc_cdh_testvector_16_out[] = { +/* ZIUT */ + 0xb3, 0x0f, 0x21, 0x27, 0xc3, 0x4d, 0xf3, 0x5a, 0xaa, 0x91, 0xdb, 0xf0, + 0xbb, 0xe1, 0x57, 0x98, 0xe7, 0x99, 0xa0, 0x3e, 0xd1, 0x16, 0x98, 0xc1 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_17_public_x[] = { +/* QCAVSx */ + 0x6c, 0xc4, 0xfe, 0xed, 0x84, 0xc7, 0xab, 0x0d, 0x09, 0x00, 0x5d, 0x66, + 0x0e, 0xd3, 0x4d, 0xe6, 0x95, 0x5a, 0x94, 0x61, 0xc4, 0x13, 0x8d, 0x11 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_17_public_y[] = { +/* QCAVSy */ + 0x31, 0x22, 0x5f, 0x33, 0x86, 0x4e, 0xd4, 0x8d, 0xa0, 0x6f, 0xa4, 0x5a, + 0x91, 0x3b, 0x46, 0xcf, 0x42, 0x55, 0x77, 0x42, 0xe3, 0x50, 0x85, 0xe6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_17_private[] = { +/* dIUT */ + 0xbd, 0xb7, 0x54, 0x09, 0x6f, 0xfb, 0xfb, 0xd8, 0xb0, 0xf3, 0xcb, 0x04, + 0x6c, 0xcb, 0x7c, 0xa1, 0x49, 0xc4, 0xe7, 0x19, 0x20, 0x67, 0xa3, 0xee +}; +/* QIUTx = d9c098d421d741f6faab116f3e4731d28c5558e19fe112a1 */ +/* QIUTy = 38d4dc48ccdb1d3ed8d31fd06784a4f87a68aec1cbd5b08f */ +static const uint8_t nist_kas_ecc_cdh_testvector_17_out[] = { +/* ZIUT */ + 0x64, 0xa5, 0xc2, 0x46, 0x59, 0x9d, 0x3e, 0x81, 0x77, 0xa2, 0x40, 0x2a, + 0x11, 0x10, 0xeb, 0x81, 0xe6, 0xc4, 0x56, 0xab, 0x4e, 0xdb, 0x51, 0x27 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_18_public_x[] = { +/* QCAVSx */ + 0x36, 0x15, 0x73, 0x15, 0xbe, 0xe7, 0xaf, 0xed, 0xde, 0xd5, 0x8c, 0x4e, + 0x8b, 0xa1, 0x4d, 0x34, 0x21, 0xc4, 0x01, 0xe5, 0x11, 0x35, 0xbc, 0xc9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_18_public_y[] = { +/* QCAVSy */ + 0x37, 0xc2, 0x97, 0xca, 0x70, 0x3f, 0x77, 0xc5, 0x2b, 0xb0, 0x62, 0xd8, + 0xce, 0x97, 0x1d, 0xb8, 0x40, 0x97, 0xba, 0x0c, 0x75, 0x3a, 0x41, 0x8f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_18_private[] = { +/* dIUT */ + 0xd5, 0xbc, 0xf2, 0x53, 0x4d, 0xaf, 0xc3, 0xd9, 0x99, 0x64, 0xc7, 0xbd, + 0x63, 0xab, 0x7b, 0xd1, 0x59, 0x99, 0xfe, 0x56, 0xdd, 0x96, 0x9c, 0x42 +}; +/* QIUTx = fda1d5d28d6fe0e7909d6a8bafa7824db5572ab92ffe7de6 */ +/* QIUTy = 134a297c1d9c8bbab249abacd951ed11e5a99f92e7991572 */ +static const uint8_t nist_kas_ecc_cdh_testvector_18_out[] = { +/* ZIUT */ + 0x01, 0x7b, 0x8c, 0xa5, 0x3c, 0x82, 0xfa, 0xb1, 0x63, 0xda, 0x2a, 0xb7, + 0x83, 0x96, 0x6a, 0x39, 0xe0, 0x61, 0xb3, 0x2c, 0x8c, 0xfa, 0x33, 0x4d +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_19_public_x[] = { +/* QCAVSx */ + 0x98, 0x46, 0x4d, 0x47, 0xf0, 0x25, 0x6f, 0x82, 0x92, 0xe0, 0x27, 0xe8, + 0xc9, 0x25, 0x82, 0xea, 0x77, 0xcf, 0x90, 0x51, 0xf5, 0xce, 0x8e, 0x5d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_19_public_y[] = { +/* QCAVSy */ + 0x44, 0x95, 0x52, 0xef, 0x75, 0x78, 0xbe, 0x96, 0x23, 0x6f, 0xe5, 0xed, + 0x9d, 0x06, 0x43, 0xc0, 0xbb, 0x6c, 0x5a, 0x91, 0x34, 0xb0, 0x10, 0x8d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_19_private[] = { +/* dIUT */ + 0x43, 0xd4, 0xb9, 0xdf, 0x10, 0x53, 0xbe, 0x5b, 0x42, 0x68, 0x10, 0x4c, + 0x02, 0x24, 0x4d, 0x3b, 0xf9, 0x59, 0x4b, 0x01, 0x0b, 0x46, 0xa8, 0xb2 +}; +/* QIUTx = c3020b7091463d788f1f1d76f7cfeec82ecdb3b7d99c345c */ +/* QIUTy = 9a7710d5179591d8f3df0aa122301768ae7db7eee2d7f583 */ +static const uint8_t nist_kas_ecc_cdh_testvector_19_out[] = { +/* ZIUT */ + 0x34, 0x0e, 0xf3, 0xdb, 0x3d, 0xbe, 0xbd, 0xd9, 0x1c, 0x62, 0xc3, 0xd4, + 0xe1, 0xa3, 0xda, 0x2c, 0x7c, 0x52, 0xa3, 0x33, 0x8b, 0x86, 0x52, 0x59 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_20_public_x[] = { +/* QCAVSx */ + 0x56, 0x3e, 0xb6, 0x6c, 0x33, 0x4c, 0xf6, 0xf1, 0x23, 0xbf, 0x04, 0xc7, + 0x80, 0x3b, 0x48, 0xa3, 0x11, 0x02, 0x14, 0x23, 0x7e, 0x98, 0x3b, 0xf5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_20_public_y[] = { +/* QCAVSy */ + 0x0f, 0x35, 0x11, 0x04, 0x81, 0x91, 0x99, 0xef, 0x07, 0xc9, 0xa6, 0x05, + 0x1d, 0x20, 0x75, 0x8f, 0x3a, 0xf7, 0x90, 0x27, 0xea, 0x66, 0xa5, 0x3f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_20_private[] = { +/* dIUT */ + 0x94, 0xca, 0xc2, 0xc2, 0xca, 0x71, 0x47, 0x46, 0x40, 0x16, 0x70, 0xd9, + 0x4e, 0xdb, 0xf3, 0xf6, 0x77, 0x86, 0x7b, 0x5a, 0x03, 0xbe, 0xe7, 0xad +}; +/* QIUTx = b18554a2e743ef0aa2f040987c4c451004e096df3d80ddae */ +/* QIUTy = 6e3e2c618f896e36ba620077684b70a05ffb79bf5e6c7640 */ +static const uint8_t nist_kas_ecc_cdh_testvector_20_out[] = { +/* ZIUT */ + 0x21, 0x62, 0x14, 0x49, 0x21, 0xdf, 0x51, 0x03, 0xd0, 0xe6, 0xa6, 0x50, + 0xfb, 0x13, 0xfd, 0x24, 0x6f, 0x47, 0x38, 0xd0, 0x89, 0x6c, 0xe9, 0x2f +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_21_public_x[] = { +/* QCAVSx */ + 0x86, 0x82, 0x8c, 0x4a, 0xc9, 0x2b, 0x55, 0x07, 0x61, 0x8a, 0xec, 0x78, + 0x73, 0xa1, 0xd4, 0xfc, 0x65, 0x43, 0xc5, 0xbe, 0x33, 0xcf, 0x30, 0x78 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_21_public_y[] = { +/* QCAVSy */ + 0xb2, 0x2c, 0xa7, 0x24, 0x37, 0x54, 0x5e, 0x10, 0xd6, 0xd4, 0xf0, 0x52, + 0x42, 0x2e, 0xb8, 0x98, 0xb7, 0x37, 0xa4, 0xb8, 0x54, 0x3e, 0xe5, 0x50 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_21_private[] = { +/* dIUT */ + 0x2a, 0x3a, 0x9e, 0x33, 0xc8, 0xcc, 0x31, 0x07, 0xa9, 0xf9, 0x26, 0x5c, + 0x3b, 0xde, 0xa1, 0x20, 0x65, 0x70, 0xe8, 0x6f, 0x92, 0xac, 0x70, 0x14 +}; +/* QIUTx = a7ba38be1bc669dd23ccfcee0645b1f0db8cf942deafaeb6 */ +/* QIUTy = b82db79d80cd0e37f28d4163adc389dee8fc7797b5c9831b */ +static const uint8_t nist_kas_ecc_cdh_testvector_21_out[] = { +/* ZIUT */ + 0x4c, 0x69, 0xe7, 0xfe, 0xed, 0x4b, 0x11, 0x15, 0x9a, 0xdf, 0xc1, 0x6a, + 0x60, 0x47, 0xa9, 0x25, 0x72, 0xea, 0x44, 0xe0, 0x74, 0x0b, 0x23, 0xaf +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_22_public_x[] = { +/* QCAVSx */ + 0x67, 0x00, 0xa1, 0x02, 0x43, 0x77, 0x81, 0xa9, 0x58, 0x1d, 0xa2, 0xbc, + 0x25, 0xce, 0xd5, 0xab, 0xf4, 0x19, 0xda, 0x91, 0xd3, 0xc8, 0x03, 0xdf +}; +static const uint8_t nist_kas_ecc_cdh_testvector_22_public_y[] = { +/* QCAVSy */ + 0x71, 0x39, 0x6c, 0x9c, 0xf0, 0x8b, 0xcd, 0x91, 0x85, 0x4e, 0x3e, 0x6e, + 0x42, 0xd8, 0xc6, 0x57, 0xce, 0x0f, 0x27, 0xab, 0x77, 0xa9, 0xdc, 0x4b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_22_private[] = { +/* dIUT */ + 0x4a, 0x6b, 0x78, 0xa9, 0x8a, 0xc9, 0x8f, 0xa8, 0xe9, 0x9a, 0x8e, 0xce, + 0x08, 0xec, 0x02, 0x51, 0x12, 0x5f, 0x85, 0xc6, 0xfd, 0x0e, 0x28, 0x9b +}; +/* QIUTx = e769dbbcd5ce2d83514b768d3d2d5aa0bcd8f66af15f5500 */ +/* QIUTy = 2fc6d0b039e0f28f74fbeffe9e883d4dd72296e4e95cae71 */ +static const uint8_t nist_kas_ecc_cdh_testvector_22_out[] = { +/* ZIUT */ + 0x46, 0x07, 0x2a, 0xce, 0xfd, 0x67, 0xbf, 0xf5, 0x0d, 0xe3, 0x55, 0xca, + 0x7a, 0x31, 0xfa, 0x6b, 0xe5, 0x9f, 0x26, 0xe4, 0x67, 0x58, 0x72, 0x59 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_23_public_x[] = { +/* QCAVSx */ + 0xa8, 0x2f, 0x35, 0x4c, 0xf9, 0x7b, 0xee, 0x5d, 0x22, 0xdc, 0x6c, 0x07, + 0x9f, 0x29, 0x02, 0xea, 0xd4, 0x4d, 0x96, 0xa8, 0xf6, 0x14, 0xf1, 0x78 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_23_public_y[] = { +/* QCAVSy */ + 0xa6, 0x54, 0xa9, 0xaa, 0x8a, 0x1a, 0x08, 0x02, 0xf2, 0xce, 0x0e, 0xe8, + 0xa0, 0xf4, 0xeb, 0xe9, 0x6d, 0xee, 0x1b, 0x37, 0x46, 0x4b, 0x1f, 0xf2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_23_private[] = { +/* dIUT */ + 0xc5, 0xa6, 0x49, 0x1d, 0x78, 0x84, 0x4d, 0x66, 0x17, 0xef, 0x33, 0xbe, + 0x6b, 0x8b, 0xd5, 0x4d, 0xa2, 0x21, 0x45, 0x08, 0x85, 0xd5, 0x95, 0x0f +}; +/* QIUTx = db1b24f7466bc154e9d7d2c3ca52dcfe0bfc9563c5fdb6f3 */ +/* QIUTy = 1c74fbbf5bd99921f1a9a744f8e1cf770bd6a76a772b3003 */ +static const uint8_t nist_kas_ecc_cdh_testvector_23_out[] = { +/* ZIUT */ + 0xec, 0x55, 0x80, 0xea, 0xbc, 0xa9, 0xf3, 0x38, 0x9d, 0x2b, 0x42, 0x7d, + 0xdf, 0x6e, 0x49, 0xe2, 0x6d, 0x62, 0x9a, 0xfd, 0x03, 0xfa, 0x76, 0x6e +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_24_public_x[] = { +/* QCAVSx */ + 0x3c, 0xec, 0x21, 0xb2, 0x86, 0x68, 0xa1, 0x2a, 0x2c, 0xf7, 0x8e, 0x1a, + 0x8e, 0x55, 0xd0, 0xef, 0xe0, 0x65, 0x15, 0x2f, 0xff, 0xc3, 0x47, 0x18 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_24_public_y[] = { +/* QCAVSy */ + 0x10, 0x29, 0x55, 0x7b, 0xeb, 0xa4, 0xff, 0x19, 0x92, 0xbd, 0x21, 0xc2, + 0x3c, 0xb4, 0x82, 0x5f, 0x6d, 0xae, 0x70, 0xe3, 0x31, 0x8f, 0xd1, 0xca +}; +static const uint8_t nist_kas_ecc_cdh_testvector_24_private[] = { +/* dIUT */ + 0x2b, 0xa2, 0x70, 0x3c, 0x5e, 0x23, 0xf6, 0x46, 0x3c, 0x5b, 0x88, 0xdc, + 0x37, 0x29, 0x2f, 0xab, 0xd3, 0x39, 0x9b, 0x5e, 0x1f, 0xb6, 0x7c, 0x05 +}; +/* QIUTx = 7543148906cef9b37a71a7c08363cdd3bba50142d65241aa */ +/* QIUTy = 8b3a6973de8dc271e27c1ead1e962fdaae3710c724daac38 */ +static const uint8_t nist_kas_ecc_cdh_testvector_24_out[] = { +/* ZIUT */ + 0x7f, 0x39, 0x29, 0xdd, 0x3c, 0xbf, 0x76, 0x73, 0xbc, 0x30, 0xd8, 0x59, + 0xd9, 0x0b, 0x88, 0x03, 0x07, 0x47, 0x5f, 0x80, 0x06, 0x60, 0xea, 0x32 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_25_public_x[] = { +/* QCAVSx */ + 0x70, 0x82, 0x64, 0x47, 0x15, 0xb8, 0xb7, 0x31, 0xf8, 0x22, 0x8b, 0x51, + 0x18, 0xe7, 0x27, 0x0d, 0x34, 0xd1, 0x81, 0xf3, 0x61, 0xa2, 0x21, 0xfc +}; +static const uint8_t nist_kas_ecc_cdh_testvector_25_public_y[] = { +/* QCAVSy */ + 0x46, 0x46, 0x49, 0xd6, 0xc8, 0x8c, 0xa8, 0x96, 0x14, 0x48, 0x8a, 0x1c, + 0xc7, 0xb8, 0x44, 0x2b, 0xb4, 0x2f, 0x9f, 0xb3, 0x02, 0x0a, 0x3d, 0x76 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_25_private[] = { +/* dIUT */ + 0x83, 0x61, 0x18, 0xc6, 0x24, 0x8f, 0x88, 0x2e, 0x91, 0x47, 0x97, 0x6f, + 0x76, 0x48, 0x26, 0xc1, 0xa2, 0x87, 0x55, 0xa6, 0x10, 0x29, 0x77, 0xd5 +}; +/* QIUTx = fcd345a976c720caaa97de6697226825615e1287a9eff67e */ +/* QIUTy = 58ea42edbeeafca9ff44cfd7f29abd2cbde7626d79e422c9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_25_out[] = { +/* ZIUT */ + 0x72, 0xe8, 0x8f, 0x3e, 0xa6, 0x7d, 0x46, 0xd4, 0x6d, 0xbf, 0x83, 0x92, + 0x6e, 0x7e, 0x2a, 0x6b, 0x85, 0xb5, 0x45, 0x36, 0x74, 0x1e, 0x6d, 0x2c +}; +/* [P-224] */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_26_public_x[] = { +/* QCAVSx */ + 0xaf, 0x33, 0xcd, 0x06, 0x29, 0xbc, 0x7e, 0x99, 0x63, 0x20, 0xa3, 0xf4, + 0x03, 0x68, 0xf7, 0x4d, 0xe8, 0x70, 0x4f, 0xa3, 0x7b, 0x8f, 0xab, 0x69, + 0xab, 0xaa, 0xe2, 0x80 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_26_public_y[] = { +/* QCAVSy */ + 0x88, 0x20, 0x92, 0xcc, 0xbb, 0xa7, 0x93, 0x0f, 0x41, 0x9a, 0x8a, 0x4f, + 0x9b, 0xb1, 0x69, 0x78, 0xbb, 0xc3, 0x83, 0x87, 0x29, 0x99, 0x25, 0x59, + 0xa6, 0xf2, 0xe2, 0xd7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_26_private[] = { +/* dIUT */ + 0x83, 0x46, 0xa6, 0x0f, 0xc6, 0xf2, 0x93, 0xca, 0x5a, 0x0d, 0x2a, 0xf6, + 0x8b, 0xa7, 0x1d, 0x1d, 0xd3, 0x89, 0xe5, 0xe4, 0x08, 0x37, 0x94, 0x2d, + 0xf3, 0xe4, 0x3c, 0xbd +}; +/* QIUTx = 8de2e26adf72c582d6568ef638c4fd59b18da171bdf501f1d929e048 */ +/* QIUTy = 4a68a1c2b0fb22930d120555c1ece50ea98dea8407f71be36efac0de */ +static const uint8_t nist_kas_ecc_cdh_testvector_26_out[] = { +/* ZIUT */ + 0x7d, 0x96, 0xf9, 0xa3, 0xbd, 0x3c, 0x05, 0xcf, 0x5c, 0xc3, 0x7f, 0xeb, + 0x8b, 0x9d, 0x52, 0x09, 0xd5, 0xc2, 0x59, 0x74, 0x64, 0xde, 0xc3, 0xe9, + 0x98, 0x37, 0x43, 0xe8 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_27_public_x[] = { +/* QCAVSx */ + 0x13, 0xbf, 0xcd, 0x4f, 0x8e, 0x94, 0x42, 0x39, 0x3c, 0xab, 0x8f, 0xb4, + 0x6b, 0x9f, 0x05, 0x66, 0xc2, 0x26, 0xb2, 0x2b, 0x37, 0x07, 0x69, 0x76, + 0xf0, 0x61, 0x7a, 0x46 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_27_public_y[] = { +/* QCAVSy */ + 0xee, 0xb2, 0x42, 0x75, 0x29, 0xb2, 0x88, 0xc6, 0x3c, 0x2f, 0x89, 0x63, + 0xc1, 0xe4, 0x73, 0xdf, 0x2f, 0xca, 0x6c, 0xaa, 0x90, 0xd5, 0x2e, 0x2f, + 0x8d, 0xb5, 0x6d, 0xd4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_27_private[] = { +/* dIUT */ + 0x04, 0x3c, 0xb2, 0x16, 0xf4, 0xb7, 0x2c, 0xdf, 0x76, 0x29, 0xd6, 0x37, + 0x20, 0xa5, 0x4a, 0xee, 0x0c, 0x99, 0xeb, 0x32, 0xd7, 0x44, 0x77, 0xda, + 0xc0, 0xc2, 0xf7, 0x3d +}; +/* QIUTx = 2f90f5c8eac9c7decdbb97b6c2f715ab725e4fe40fe6d746efbf4e1b */ +/* QIUTy = 66897351454f927a309b269c5a6d31338be4c19a5acfc32cf656f45c */ +static const uint8_t nist_kas_ecc_cdh_testvector_27_out[] = { +/* ZIUT */ + 0xee, 0x93, 0xce, 0x06, 0xb8, 0x9f, 0xf7, 0x20, 0x09, 0xe8, 0x58, 0xc6, + 0x8e, 0xb7, 0x08, 0xe7, 0xbc, 0x79, 0xee, 0x03, 0x00, 0xf7, 0x3b, 0xed, + 0x69, 0xbb, 0xca, 0x09 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_28_public_x[] = { +/* QCAVSx */ + 0x75, 0x6d, 0xd8, 0x06, 0xb9, 0xd9, 0xc3, 0x4d, 0x89, 0x96, 0x91, 0xec, + 0xb4, 0x5b, 0x77, 0x1a, 0xf4, 0x68, 0xec, 0x00, 0x44, 0x86, 0xa0, 0xfd, + 0xd2, 0x83, 0x41, 0x1e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_28_public_y[] = { +/* QCAVSy */ + 0x4d, 0x02, 0xc2, 0xca, 0x61, 0x7b, 0xb2, 0xc5, 0xd9, 0x61, 0x3f, 0x25, + 0xdd, 0x72, 0x41, 0x3d, 0x22, 0x9f, 0xd2, 0x90, 0x15, 0x13, 0xaa, 0x29, + 0x50, 0x4e, 0xee, 0xfb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_28_private[] = { +/* dIUT */ + 0x5a, 0xd0, 0xdd, 0x6d, 0xba, 0xbb, 0x4f, 0x3c, 0x2e, 0xa5, 0xfe, 0x32, + 0xe5, 0x61, 0xb2, 0xca, 0x55, 0x08, 0x14, 0x86, 0xdf, 0x2c, 0x7c, 0x15, + 0xc9, 0x62, 0x2b, 0x08 +}; +/* QIUTx = 005bca45d793e7fe99a843704ed838315ab14a5f6277507e9bc37531 */ +/* QIUTy = 43e9d421e1486ae5893bfd23c210e5c140d7c6b1ada59d842c9a98de */ +static const uint8_t nist_kas_ecc_cdh_testvector_28_out[] = { +/* ZIUT */ + 0x3f, 0xcc, 0x01, 0xe3, 0x4d, 0x44, 0x49, 0xda, 0x2a, 0x97, 0x4b, 0x23, + 0xfc, 0x36, 0xf9, 0x56, 0x67, 0x54, 0x25, 0x9d, 0x39, 0x14, 0x97, 0x90, + 0xcf, 0xa1, 0xeb, 0xd3 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_29_public_x[] = { +/* QCAVSx */ + 0x0f, 0x53, 0x7b, 0xf1, 0xc1, 0x12, 0x2c, 0x55, 0x65, 0x6d, 0x25, 0xe8, + 0xaa, 0x84, 0x17, 0xe0, 0xb4, 0x4b, 0x15, 0x26, 0xae, 0x05, 0x23, 0x14, + 0x4f, 0x99, 0x21, 0xc4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_29_public_y[] = { +/* QCAVSy */ + 0xf7, 0x9b, 0x26, 0xd3, 0x0e, 0x49, 0x1a, 0x77, 0x36, 0x96, 0xcc, 0x2c, + 0x79, 0xb4, 0xf0, 0x59, 0x6b, 0xc5, 0xb9, 0xee, 0xba, 0xf3, 0x94, 0xd1, + 0x62, 0xfb, 0x86, 0x84 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_29_private[] = { +/* dIUT */ + 0x0a, 0xa6, 0xff, 0x55, 0xa5, 0xd8, 0x20, 0xef, 0xcb, 0x4e, 0x7d, 0x10, + 0xb8, 0x45, 0xea, 0x3c, 0x9f, 0x9b, 0xc5, 0xdf, 0xf8, 0x61, 0x06, 0xdb, + 0x85, 0x31, 0x8e, 0x22 +}; +/* QIUTx = 2f96754131e0968198aa78fbe8c201dc5f3581c792de487340d32448 */ +/* QIUTy = 61e8a5cd79615203b6d89e9496f9e236fe3b6be8731e743d615519c6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_29_out[] = { +/* ZIUT */ + 0x49, 0x12, 0x96, 0x28, 0xb2, 0x3a, 0xfc, 0xef, 0x48, 0x13, 0x9a, 0x3f, + 0x6f, 0x59, 0xff, 0x5e, 0x98, 0x11, 0xaa, 0x74, 0x6a, 0xa4, 0xff, 0x33, + 0xc2, 0x4b, 0xb9, 0x40 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_30_public_x[] = { +/* QCAVSx */ + 0x2b, 0x36, 0x31, 0xd2, 0xb0, 0x61, 0x79, 0xb3, 0x17, 0x4a, 0x10, 0x0f, + 0x7f, 0x57, 0x13, 0x1e, 0xee, 0xa8, 0x94, 0x7b, 0xe0, 0x78, 0x6c, 0x3d, + 0xc6, 0x4b, 0x22, 0x39 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_30_public_y[] = { +/* QCAVSy */ + 0x83, 0xde, 0x29, 0xae, 0x3d, 0xad, 0x31, 0xad, 0xc0, 0x23, 0x6c, 0x6d, + 0xe7, 0xf1, 0x45, 0x61, 0xca, 0x2e, 0xa0, 0x83, 0xc5, 0x27, 0x0c, 0x78, + 0xa2, 0xe6, 0xcb, 0xc0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_30_private[] = { +/* dIUT */ + 0xef, 0xe6, 0xe6, 0xe2, 0x5a, 0xff, 0xaf, 0x54, 0xc9, 0x8d, 0x00, 0x2a, + 0xbb, 0xc6, 0x32, 0x8d, 0xa1, 0x59, 0x40, 0x5a, 0x1b, 0x75, 0x2e, 0x32, + 0xdc, 0x23, 0x95, 0x0a +}; +/* QIUTx = 355e962920bde043695f6bffb4b355c63da6f5de665ed46f2ec817e2 */ +/* QIUTy = 748e095368f62e1d364edd461719793b404adbdaacbcadd88922ff37 */ +static const uint8_t nist_kas_ecc_cdh_testvector_30_out[] = { +/* ZIUT */ + 0xfc, 0xdc, 0x69, 0xa4, 0x05, 0x01, 0xd3, 0x08, 0xa6, 0x83, 0x96, 0x53, + 0xa8, 0xf0, 0x43, 0x09, 0xec, 0x00, 0x23, 0x39, 0x49, 0x52, 0x29, 0x02, + 0xff, 0xa5, 0xea, 0xc6 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_31_public_x[] = { +/* QCAVSx */ + 0x45, 0x11, 0x40, 0x3d, 0xe2, 0x90, 0x59, 0xf6, 0x9a, 0x47, 0x5c, 0x5a, + 0x6a, 0x5f, 0x6c, 0xab, 0xed, 0x5d, 0x9f, 0x01, 0x44, 0x36, 0xa8, 0xcb, + 0x70, 0xa0, 0x23, 0x38 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_31_public_y[] = { +/* QCAVSy */ + 0x7d, 0x2d, 0x1b, 0x62, 0xaa, 0x04, 0x6d, 0xf9, 0x34, 0x0f, 0x9c, 0x37, + 0xa0, 0x87, 0xa0, 0x6b, 0x32, 0xcf, 0x7f, 0x08, 0xa2, 0x23, 0xf9, 0x92, + 0x81, 0x2a, 0x82, 0x8b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_31_private[] = { +/* dIUT */ + 0x61, 0xcb, 0x29, 0x32, 0x52, 0x40, 0x01, 0xe5, 0xe9, 0xee, 0xed, 0x6d, + 0xf7, 0xd9, 0xc8, 0x93, 0x5e, 0xe3, 0x32, 0x20, 0x29, 0xed, 0xd7, 0xaa, + 0x8a, 0xcb, 0xfd, 0x51 +}; +/* QIUTx = d50e4adabfd989d7dbc7cf4052546cc7c447a97630436997ad4b9536 */ +/* QIUTy = 5bea503473c5eaef9552d42c40b1f2f7ca292733b255b9bbe1b12337 */ +static const uint8_t nist_kas_ecc_cdh_testvector_31_out[] = { +/* ZIUT */ + 0x82, 0x7e, 0x90, 0x25, 0xcb, 0x62, 0xe0, 0xe8, 0x37, 0xc5, 0x96, 0x06, + 0x3f, 0x3b, 0x9b, 0x5a, 0x0f, 0x7a, 0xfd, 0x8d, 0x87, 0x83, 0x20, 0x00, + 0x86, 0xd6, 0x1e, 0xc1 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_32_public_x[] = { +/* QCAVSx */ + 0x31, 0x4a, 0x0b, 0x26, 0xdd, 0x31, 0xc2, 0x48, 0x84, 0x5d, 0x7c, 0xc1, + 0x7b, 0x61, 0xca, 0xd4, 0x60, 0x82, 0x59, 0xbe, 0xd8, 0x5a, 0x58, 0xd1, + 0xf1, 0xff, 0xd3, 0x78 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_32_public_y[] = { +/* QCAVSy */ + 0x66, 0xe4, 0xb3, 0x50, 0x35, 0x2e, 0x11, 0x9e, 0xec, 0xad, 0xa3, 0x82, + 0x90, 0x7f, 0x36, 0x19, 0xfd, 0x74, 0x8e, 0xa7, 0x3a, 0xe4, 0x89, 0x9d, + 0xfd, 0x49, 0x63, 0x02 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_32_private[] = { +/* dIUT */ + 0x8c, 0x7a, 0xce, 0x34, 0x71, 0x71, 0xf9, 0x2d, 0xef, 0x98, 0xd8, 0x45, + 0x47, 0x5f, 0xc8, 0x2e, 0x1d, 0x14, 0x96, 0xda, 0x81, 0xee, 0x58, 0xf5, + 0x05, 0xb9, 0x85, 0xfa +}; +/* QIUTx = b1a8dcac89aca2799320b451df1c7ff4d97567abb68141c0d95fc2aa */ +/* QIUTy = 3524950902b1510bdc987d860afc27ad871ceaea66935abd3c0a99a8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_32_out[] = { +/* ZIUT */ + 0x33, 0x5b, 0xa5, 0x12, 0x28, 0xd9, 0x4a, 0xcb, 0xed, 0x85, 0x1c, 0xa7, + 0x82, 0x1c, 0x80, 0x1d, 0x5c, 0xb1, 0xc7, 0x97, 0x5d, 0x7a, 0xa9, 0x0a, + 0x71, 0x59, 0xf8, 0xfa +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_33_public_x[] = { +/* QCAVSx */ + 0xab, 0xe6, 0x84, 0x3b, 0xee, 0xc2, 0xfd, 0x9e, 0x5f, 0xb6, 0x47, 0x30, + 0xd0, 0xbe, 0x4d, 0x16, 0x54, 0x38, 0xce, 0x92, 0x2e, 0xd7, 0x5d, 0xd8, + 0x0b, 0x46, 0x03, 0xe5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_33_public_y[] = { +/* QCAVSy */ + 0x6a, 0xfe, 0x86, 0x73, 0xa9, 0x6c, 0x4b, 0xa9, 0x90, 0x0a, 0xd8, 0x59, + 0x95, 0xe6, 0x31, 0xe4, 0x36, 0xc6, 0xcc, 0x88, 0xa2, 0xc2, 0xb4, 0x7b, + 0x7c, 0x48, 0x86, 0xb8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_33_private[] = { +/* dIUT */ + 0x38, 0x2f, 0xeb, 0x9b, 0x9b, 0xa1, 0x0f, 0x18, 0x9d, 0x99, 0xe7, 0x1a, + 0x89, 0xcd, 0xfe, 0x44, 0xcb, 0x55, 0x4c, 0xec, 0x13, 0xa2, 0x12, 0x84, + 0x09, 0x77, 0xfb, 0x68 +}; +/* QIUTx = abb6f1e3773ff8fc73aea2a0b107809ce70adcefed6e41fc5cb43045 */ +/* QIUTy = a963897ae906c10a055eeadb97ffdd6f748d3e5621e5fff304e48ba7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_33_out[] = { +/* ZIUT */ + 0x8c, 0x2e, 0x62, 0x75, 0x94, 0x20, 0x6b, 0x34, 0xf7, 0x35, 0x6d, 0x34, + 0x26, 0xeb, 0x3d, 0x79, 0xf5, 0x18, 0xef, 0x84, 0x3f, 0xbe, 0x94, 0x01, + 0x4c, 0xce, 0xac, 0xe3 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_34_public_x[] = { +/* QCAVSx */ + 0x13, 0xcf, 0x9d, 0x6d, 0x2c, 0x9a, 0xae, 0x82, 0x74, 0xc2, 0x7d, 0x44, + 0x6a, 0xfd, 0x0c, 0x88, 0x8f, 0xfd, 0xd5, 0x2a, 0xe2, 0x99, 0xa3, 0x59, + 0x84, 0xd4, 0xf5, 0x27 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_34_public_y[] = { +/* QCAVSy */ + 0xdc, 0xbe, 0xe7, 0x5b, 0x51, 0x57, 0x51, 0xf8, 0xee, 0x2a, 0xe3, 0x55, + 0xe8, 0xaf, 0xd5, 0xde, 0x21, 0xc6, 0x2a, 0x93, 0x9a, 0x65, 0x07, 0xb5, + 0x38, 0xcb, 0xc4, 0xaf +}; +static const uint8_t nist_kas_ecc_cdh_testvector_34_private[] = { +/* dIUT */ + 0xe0, 0xd6, 0x20, 0x35, 0x10, 0x1e, 0xf4, 0x87, 0xc4, 0x85, 0xc6, 0x0f, + 0xb4, 0x50, 0x0e, 0xeb, 0xe6, 0xa3, 0x2e, 0xc6, 0x4d, 0xbe, 0x97, 0xdb, + 0xe0, 0x23, 0x2c, 0x46 +}; +/* QIUTx = 88537735e9b23e3e0e076f135a82d33f9bffb465f3abce8322a62a62 */ +/* QIUTy = b4c8c123673197875c0bd14ed097606d330fba2b9200ef65a44764d3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_34_out[] = { +/* ZIUT */ + 0x63, 0x2a, 0xbb, 0x66, 0x27, 0x28, 0xdb, 0xc9, 0x94, 0x50, 0x88, 0x73, + 0xd5, 0xc5, 0x27, 0xca, 0x5e, 0xf9, 0x23, 0xc0, 0xd3, 0x1f, 0xa6, 0xc4, + 0x7e, 0xf4, 0xc8, 0x25 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_35_public_x[] = { +/* QCAVSx */ + 0x96, 0x5b, 0x63, 0x7c, 0x0d, 0xfb, 0xc0, 0xcf, 0x95, 0x40, 0x35, 0x68, + 0x6d, 0x70, 0xf7, 0xec, 0x30, 0x92, 0x9e, 0x66, 0x4e, 0x52, 0x1d, 0xba, + 0xa2, 0x28, 0x06, 0x59 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_35_public_y[] = { +/* QCAVSy */ + 0x82, 0xa5, 0x8f, 0xf6, 0x1b, 0xc9, 0x00, 0x19, 0xbb, 0xcb, 0xb5, 0x87, + 0x5d, 0x38, 0x63, 0xdb, 0x0b, 0xc2, 0xa1, 0xfa, 0x34, 0xb0, 0xad, 0x4d, + 0xe1, 0xa8, 0x3f, 0x99 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_35_private[] = { +/* dIUT */ + 0xb9, 0x6a, 0xde, 0x5b, 0x73, 0xba, 0x72, 0xaa, 0x8b, 0x6e, 0x4d, 0x74, + 0xd7, 0xbf, 0x9c, 0x58, 0xe9, 0x62, 0xff, 0x78, 0xeb, 0x54, 0x22, 0x87, + 0xc7, 0xb4, 0x4b, 0xa2 +}; +/* QIUTx = 37682926a54f70a4c1748f54d50d5b00138a055f924f2c65e5b0bbe4 */ +/* QIUTy = 596afefcdd640d29635015b89bdddd1f8c2723686d332e7a06ca8799 */ +static const uint8_t nist_kas_ecc_cdh_testvector_35_out[] = { +/* ZIUT */ + 0x34, 0x64, 0x11, 0x41, 0xaa, 0xb0, 0x5e, 0xf5, 0x8b, 0xd3, 0x76, 0xd6, + 0x09, 0x34, 0x59, 0x01, 0xfb, 0x8f, 0x63, 0x47, 0x7c, 0x6b, 0xe9, 0x09, + 0x7f, 0x03, 0x7f, 0x1f +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_36_public_x[] = { +/* QCAVSx */ + 0x73, 0xcc, 0x64, 0x53, 0x72, 0xca, 0x2e, 0x71, 0x63, 0x7c, 0xda, 0x94, + 0x3d, 0x81, 0x48, 0xf3, 0x38, 0x2a, 0xb6, 0xdd, 0x0f, 0x2e, 0x1a, 0x49, + 0xda, 0x94, 0xe1, 0x34 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_36_public_y[] = { +/* QCAVSy */ + 0xdf, 0x5c, 0x35, 0x5c, 0x23, 0xe6, 0xe2, 0x32, 0xeb, 0xc3, 0xbe, 0xe2, + 0xab, 0x18, 0x73, 0xee, 0x0d, 0x83, 0xe3, 0x38, 0x2f, 0x8e, 0x6f, 0xe6, + 0x13, 0xf6, 0x34, 0x3c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_36_private[] = { +/* dIUT */ + 0xa4, 0x0d, 0x7e, 0x12, 0x04, 0x9c, 0x71, 0xe6, 0x52, 0x2c, 0x7f, 0xf2, + 0x38, 0x42, 0x24, 0x06, 0x1c, 0x3a, 0x45, 0x70, 0x58, 0xb3, 0x10, 0x55, + 0x76, 0x55, 0xb8, 0x54 +}; +/* QIUTx = 399801243bfe0c2da9b0a53c8ca57f2eee87aaa94a8e4d5e029f42ca */ +/* QIUTy = aa49e6d4b47cee7a5c4ab71d5a67da84e0b9b425ce3e70da68c889e7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_36_out[] = { +/* ZIUT */ + 0x4f, 0x74, 0xac, 0x85, 0x07, 0x50, 0x1a, 0x32, 0xbf, 0xc5, 0xa7, 0x8d, + 0x82, 0x71, 0xc2, 0x00, 0xe8, 0x35, 0x96, 0x6e, 0x18, 0x7e, 0x8d, 0x00, + 0x01, 0x1a, 0x8c, 0x75 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_37_public_x[] = { +/* QCAVSx */ + 0x54, 0x65, 0x78, 0x21, 0x62, 0x50, 0x35, 0x4e, 0x44, 0x9e, 0x21, 0x54, + 0x6d, 0xd1, 0x1c, 0xd1, 0xc5, 0x17, 0x42, 0x36, 0x73, 0x9a, 0xca, 0xd9, + 0xce, 0x0f, 0x45, 0x12 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_37_public_y[] = { +/* QCAVSy */ + 0xd2, 0xa2, 0x2f, 0xcd, 0x66, 0xd1, 0xab, 0xed, 0xc7, 0x67, 0x66, 0x83, + 0x27, 0xc5, 0xcb, 0x9c, 0x59, 0x90, 0x43, 0x27, 0x62, 0x39, 0xcf, 0x3c, + 0x85, 0x16, 0xaf, 0x24 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_37_private[] = { +/* dIUT */ + 0xad, 0x25, 0x19, 0xbc, 0x72, 0x4d, 0x48, 0x4e, 0x02, 0xa6, 0x9f, 0x05, + 0x14, 0x9b, 0xb0, 0x47, 0x71, 0x4b, 0xf0, 0xf5, 0x98, 0x6f, 0xac, 0x2e, + 0x22, 0x2c, 0xd9, 0x46 +}; +/* QIUTx = df9c1e0ef15e53b9f626e2be1cbe893639c06f3e0439ee95d7d4b1e3 */ +/* QIUTy = 7a52a7386adda243efdf8941085c84e31239cab92b8017336748965e */ +static const uint8_t nist_kas_ecc_cdh_testvector_37_out[] = { +/* ZIUT */ + 0xad, 0x09, 0xc9, 0xae, 0x4d, 0x23, 0x24, 0xea, 0x81, 0xbb, 0x55, 0x5b, + 0x20, 0x0d, 0x3c, 0x00, 0x3e, 0x22, 0xa6, 0x87, 0x0e, 0xe0, 0x3b, 0x52, + 0xdf, 0x49, 0xe4, 0xde +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_38_public_x[] = { +/* QCAVSx */ + 0x1d, 0x46, 0xb1, 0xdc, 0x3a, 0x28, 0x12, 0x3c, 0xb5, 0x13, 0x46, 0xe6, + 0x7b, 0xae, 0xc5, 0x64, 0x04, 0x86, 0x86, 0x78, 0xfa, 0xf7, 0xd0, 0xe8, + 0xb2, 0xaf, 0xa2, 0x2a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_38_public_y[] = { +/* QCAVSy */ + 0x0e, 0xc9, 0xe6, 0x5e, 0xc9, 0x7e, 0x21, 0x83, 0x73, 0xe7, 0xfc, 0x11, + 0x5c, 0x22, 0x74, 0xd5, 0xb8, 0x29, 0xa6, 0x0d, 0x93, 0xf7, 0x1e, 0x01, + 0xd5, 0x81, 0x36, 0xc3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_38_private[] = { +/* dIUT */ + 0x3d, 0x31, 0x2a, 0x9b, 0x9d, 0x8e, 0xd0, 0x91, 0x40, 0x90, 0x0b, 0xba, + 0xc1, 0xe0, 0x95, 0x52, 0x7e, 0xbc, 0x9e, 0x3c, 0x64, 0x93, 0xbc, 0xf3, + 0x66, 0x6e, 0x3a, 0x29 +}; +/* QIUTx = b4a0198dc8810e884425b750928b0c960c31f7a99663400b01a179df */ +/* QIUTy = 812b601bfc0738242c6f86f830f27acd632ca618a0b5280c9d5769f7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_38_out[] = { +/* ZIUT */ + 0xef, 0x02, 0x9c, 0x28, 0xc6, 0x80, 0x64, 0xb8, 0xab, 0xd2, 0x96, 0x5a, + 0x38, 0xc4, 0x04, 0xfb, 0x5e, 0x94, 0x4a, 0xce, 0x57, 0xe8, 0x63, 0x8d, + 0xab, 0xa9, 0xd3, 0xcd +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_39_public_x[] = { +/* QCAVSx */ + 0x26, 0x6d, 0x03, 0x8c, 0xc7, 0xa4, 0xfe, 0x21, 0xf6, 0xc9, 0x76, 0x31, + 0x8e, 0x82, 0x7b, 0x82, 0xbb, 0x5b, 0x8f, 0x74, 0x43, 0xa5, 0x52, 0x98, + 0x13, 0x65, 0x06, 0xe0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_39_public_y[] = { +/* QCAVSy */ + 0xdf, 0x12, 0x3d, 0x98, 0xa7, 0xa2, 0x0b, 0xbd, 0xf3, 0x94, 0x3d, 0xf2, + 0xe3, 0x56, 0x34, 0x22, 0xf8, 0xc0, 0xcf, 0x74, 0xd5, 0x3a, 0xaa, 0xbd, + 0xd7, 0xc9, 0x73, 0xba +}; +static const uint8_t nist_kas_ecc_cdh_testvector_39_private[] = { +/* dIUT */ + 0x8c, 0xe0, 0x82, 0x2d, 0xc2, 0x4c, 0x15, 0x39, 0x95, 0x75, 0x5a, 0xc3, + 0x50, 0x73, 0x7e, 0xf5, 0x06, 0x64, 0x1c, 0x7d, 0x75, 0x2b, 0x4f, 0x93, + 0x00, 0xc6, 0x12, 0xed +}; +/* QIUTx = 00dfc7ec137690cd6d12fdb2fd0b8c5314582108769c2b722ffb3958 */ +/* QIUTy = 5eef3da4ba458127346bb64023868bddb7558a2ecfc813645f4ce9fe */ +static const uint8_t nist_kas_ecc_cdh_testvector_39_out[] = { +/* ZIUT */ + 0xf8, 0x3c, 0x16, 0x66, 0x1d, 0xfc, 0xba, 0xd0, 0x21, 0xcc, 0x3b, 0x5a, + 0x5a, 0xf5, 0x1d, 0x9a, 0x18, 0xdb, 0x46, 0x53, 0x86, 0x6b, 0x3f, 0xf9, + 0x07, 0x87, 0xce, 0x3e +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_40_public_x[] = { +/* QCAVSx */ + 0xeb, 0x0a, 0x09, 0xf7, 0xa1, 0xc2, 0x36, 0xa6, 0x1f, 0x59, 0x58, 0x09, + 0xec, 0x56, 0x70, 0xef, 0xd9, 0x2e, 0x45, 0x98, 0xd5, 0xe6, 0x13, 0xe0, + 0x92, 0xcd, 0xfd, 0xca +}; +static const uint8_t nist_kas_ecc_cdh_testvector_40_public_y[] = { +/* QCAVSy */ + 0x50, 0x78, 0x7a, 0xe2, 0xf2, 0xf1, 0x5b, 0x88, 0xbc, 0x10, 0xf7, 0xb5, + 0xf0, 0xae, 0xe1, 0x41, 0x83, 0x73, 0xf1, 0x61, 0x53, 0xae, 0xbd, 0x1f, + 0xba, 0x54, 0x28, 0x8d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_40_private[] = { +/* dIUT */ + 0x0f, 0xf9, 0xb4, 0x85, 0x32, 0x5a, 0xb7, 0x7f, 0x29, 0xe7, 0xbc, 0x37, + 0x9f, 0xed, 0x74, 0xbf, 0xac, 0x85, 0x94, 0x82, 0xda, 0x0d, 0xee, 0x75, + 0x28, 0xc1, 0x9d, 0xb2 +}; +/* QIUTx = 7e603e6976db83c36011508fa695d1b515249e2e54b48fcbcfb90247 */ +/* QIUTy = 0179a600ce86adfca9b1b931fa5173d618da09e841803d19b0264286 */ +static const uint8_t nist_kas_ecc_cdh_testvector_40_out[] = { +/* ZIUT */ + 0xf5, 0x12, 0x58, 0xc6, 0x3f, 0x23, 0x2e, 0x55, 0xa6, 0x6a, 0xa2, 0x5e, + 0xbd, 0x59, 0x7b, 0x20, 0x18, 0xd1, 0x05, 0x2c, 0x02, 0xee, 0xb6, 0x38, + 0x66, 0x75, 0x80, 0x05 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_41_public_x[] = { +/* QCAVSx */ + 0x6b, 0x2f, 0x6b, 0x18, 0xa5, 0x87, 0xf5, 0x62, 0xff, 0xc6, 0x1b, 0xd9, + 0xb0, 0x04, 0x73, 0x22, 0x28, 0x69, 0x86, 0xa7, 0x8f, 0x1f, 0xd1, 0x39, + 0xb8, 0x4f, 0x7c, 0x24 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_41_public_y[] = { +/* QCAVSy */ + 0x70, 0x96, 0x90, 0x8e, 0x46, 0x15, 0x26, 0x6b, 0xe5, 0x9a, 0x53, 0xcd, + 0x65, 0x55, 0x15, 0x05, 0x6f, 0xf9, 0x23, 0x70, 0xa6, 0x27, 0x1a, 0x5d, + 0x38, 0x23, 0xd7, 0x04 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_41_private[] = { +/* dIUT */ + 0x19, 0xcf, 0x5f, 0xf6, 0x30, 0x64, 0x67, 0xf2, 0x8b, 0x9f, 0xe0, 0x67, + 0x5a, 0x43, 0xc0, 0x58, 0x25, 0x52, 0xc8, 0xc1, 0x2e, 0x59, 0xce, 0x7c, + 0x38, 0xf2, 0x92, 0xb1 +}; +/* QIUTx = fc20e906e609c112cfc2e0fea6303882c5db94e87e022373ab2c082a */ +/* QIUTy = aecdf1daa71782bc5a26bbbd8d7e8a76490e26abc17dffc774bd7341 */ +static const uint8_t nist_kas_ecc_cdh_testvector_41_out[] = { +/* ZIUT */ + 0x7f, 0xdc, 0x96, 0x9a, 0x18, 0x6f, 0xf1, 0x84, 0x29, 0xf2, 0xa2, 0x76, + 0xda, 0xc4, 0x3b, 0xee, 0xa2, 0x11, 0x82, 0xd8, 0x2c, 0xe2, 0xe5, 0xa0, + 0x87, 0x65, 0x52, 0xb1 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_42_public_x[] = { +/* QCAVSx */ + 0x32, 0x81, 0x01, 0xba, 0x82, 0x6a, 0xcd, 0x75, 0xff, 0x9f, 0x34, 0xd5, + 0x57, 0x4c, 0xe0, 0xdb, 0xc9, 0x2f, 0x70, 0x9b, 0xad, 0x8d, 0x7a, 0x33, + 0xc4, 0x79, 0x40, 0xc1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_42_public_y[] = { +/* QCAVSy */ + 0xdf, 0x39, 0xf1, 0xea, 0x88, 0x48, 0x8c, 0x55, 0xd5, 0x53, 0x81, 0x60, + 0x87, 0x8b, 0x9c, 0xed, 0x18, 0xa8, 0x87, 0xea, 0x26, 0x1d, 0xd7, 0x12, + 0xd1, 0x40, 0x24, 0xff +}; +static const uint8_t nist_kas_ecc_cdh_testvector_42_private[] = { +/* dIUT */ + 0x90, 0xa1, 0x53, 0x68, 0xe3, 0x53, 0x2c, 0x0b, 0x1e, 0x51, 0xe5, 0x5d, + 0x13, 0x94, 0x47, 0xc2, 0xc8, 0x9b, 0xc1, 0x60, 0x71, 0x9d, 0x69, 0x72, + 0x91, 0xea, 0x7c, 0x14 +}; +/* QIUTx = c6837d506e976da7db3ad1267c359dff2ea6fb0b7f7f8e77024c59e9 */ +/* QIUTy = 67eb491d2fc8a530c46525d2a8b2d7c1df5fba1ae740a4649c683ee6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_42_out[] = { +/* ZIUT */ + 0x3d, 0x60, 0xab, 0x6d, 0xb2, 0xb3, 0xff, 0xe2, 0xd2, 0x9c, 0xcf, 0xf4, + 0x6d, 0x05, 0x6e, 0x54, 0x23, 0x0c, 0xf3, 0x49, 0x82, 0xe2, 0x41, 0x55, + 0x6e, 0xd2, 0x92, 0x0c +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_43_public_x[] = { +/* QCAVSx */ + 0x00, 0x81, 0xe3, 0x42, 0x70, 0x87, 0x1e, 0x2e, 0xbb, 0xd9, 0x41, 0x83, + 0xf6, 0x17, 0xb4, 0xae, 0x15, 0xf0, 0x41, 0x6d, 0xd6, 0x34, 0xfe, 0x6e, + 0x93, 0x4c, 0xf3, 0xc0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_43_public_y[] = { +/* QCAVSy */ + 0x3a, 0x1e, 0x9f, 0x38, 0xa7, 0xb9, 0x0b, 0x73, 0x17, 0xd2, 0x6b, 0x9f, + 0x63, 0x11, 0x06, 0x3a, 0xb5, 0x8b, 0x26, 0x8c, 0xf4, 0x89, 0xb2, 0xe5, + 0x03, 0x86, 0xd5, 0xd6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_43_private[] = { +/* dIUT */ + 0x8e, 0x08, 0x38, 0xe0, 0x5e, 0x17, 0x21, 0x49, 0x10, 0x67, 0xe1, 0xca, + 0xbc, 0x2e, 0x80, 0x51, 0xb2, 0x90, 0xe2, 0x61, 0x6e, 0xec, 0x42, 0x7b, + 0x71, 0x21, 0x89, 0x7d +}; +/* QIUTx = e9150f770075626019e18f95473b71e6828041791d3f08d3faeeaa2b */ +/* QIUTy = 475f70735eaae52308a3b763dc88efe18ab590ebafa035f6e08b001c */ +static const uint8_t nist_kas_ecc_cdh_testvector_43_out[] = { +/* ZIUT */ + 0x91, 0x16, 0xd7, 0x27, 0x86, 0xf4, 0xdb, 0x5d, 0xf7, 0xa8, 0xb4, 0x30, + 0x78, 0xc6, 0xab, 0x91, 0x60, 0xd4, 0x23, 0x51, 0x3d, 0x35, 0xea, 0x5e, + 0x25, 0x59, 0x30, 0x6d +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_44_public_x[] = { +/* QCAVSx */ + 0x26, 0x23, 0x63, 0x2f, 0xdf, 0x0b, 0xd8, 0x56, 0x80, 0x5a, 0x69, 0xaa, + 0x18, 0x6d, 0x41, 0x33, 0xef, 0x59, 0x04, 0xe1, 0xf6, 0x55, 0xa9, 0x72, + 0xd6, 0x6c, 0xce, 0x07 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_44_public_y[] = { +/* QCAVSy */ + 0x2c, 0xef, 0x97, 0x28, 0xdd, 0x06, 0xfb, 0x8b, 0x50, 0x15, 0x0f, 0x52, + 0x9b, 0x69, 0x50, 0x76, 0xd4, 0x50, 0x79, 0x83, 0x91, 0x25, 0x85, 0xc8, + 0x9b, 0xd0, 0x68, 0x2e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_44_private[] = { +/* dIUT */ + 0x38, 0x10, 0x6e, 0x93, 0xf1, 0x6a, 0x38, 0x1a, 0xdb, 0x1d, 0x72, 0xce, + 0xe3, 0xda, 0x66, 0xae, 0x46, 0x2a, 0xd4, 0xbb, 0xfe, 0xa9, 0xec, 0xdf, + 0x35, 0xd0, 0x81, 0x4e +}; +/* QIUTx = 7be6c4c917829ab657dd79e8637d7aefd2f81f0de7654d957e97658d */ +/* QIUTy = 430d22d9e8438310f61e0d43f25fa3e34585f432baad27db3021bf0d */ +static const uint8_t nist_kas_ecc_cdh_testvector_44_out[] = { +/* ZIUT */ + 0x20, 0x7c, 0x53, 0xdc, 0xef, 0xac, 0x78, 0x9a, 0xaa, 0x02, 0x76, 0xd9, + 0x20, 0x0b, 0x3a, 0x94, 0x0c, 0xe5, 0xf2, 0x29, 0x6f, 0x4c, 0xb2, 0xe8, + 0x1a, 0x18, 0x5d, 0x3d +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_45_public_x[] = { +/* QCAVSx */ + 0x8e, 0xe4, 0xd1, 0xdc, 0xc3, 0x1d, 0xee, 0x4b, 0xf6, 0xfe, 0x21, 0xca, + 0x8a, 0x58, 0x77, 0x21, 0xd9, 0x10, 0xac, 0xfb, 0x12, 0x2c, 0x16, 0xc2, + 0xa7, 0x7a, 0x81, 0x52 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_45_public_y[] = { +/* QCAVSy */ + 0x4e, 0xbf, 0x32, 0x3f, 0xff, 0x04, 0xeb, 0x47, 0x70, 0x69, 0xa0, 0xac, + 0x68, 0xb3, 0x45, 0xf6, 0xb1, 0xae, 0x13, 0x4e, 0xfc, 0x31, 0x94, 0x0e, + 0x51, 0x3c, 0xb9, 0x9f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_45_private[] = { +/* dIUT */ + 0xe5, 0xd1, 0x71, 0x84, 0x31, 0xcf, 0x50, 0xf6, 0xcb, 0xd1, 0xbc, 0x80, + 0x19, 0xfa, 0x16, 0x76, 0x2d, 0xfa, 0x12, 0xc9, 0x89, 0xe5, 0x99, 0x99, + 0x77, 0xfb, 0x4e, 0xa2 +}; +/* QIUTx = 2ea4966e7f92ed7f5cc61fde792045f63b731d6e7d0de2577f2d8ece */ +/* QIUTy = 1c4a7b1ede6f839162292df424be78e8176fb6f942a3c02391700f31 */ +static const uint8_t nist_kas_ecc_cdh_testvector_45_out[] = { +/* ZIUT */ + 0x10, 0xe4, 0x67, 0xda, 0x34, 0xf4, 0x8a, 0xd7, 0x07, 0x20, 0x05, 0xbc, + 0xcd, 0x6d, 0xa1, 0xb2, 0xba, 0x3f, 0x71, 0xea, 0xfa, 0x1c, 0x39, 0x38, + 0x42, 0xf9, 0x1d, 0x74 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_46_public_x[] = { +/* QCAVSx */ + 0x97, 0xdc, 0xbe, 0x6d, 0x28, 0x33, 0x58, 0x82, 0xa6, 0xd1, 0x93, 0xcc, + 0x54, 0xa1, 0x06, 0x3d, 0xd0, 0x77, 0x5d, 0xc3, 0x28, 0x56, 0x53, 0x00, + 0xbb, 0x99, 0xe6, 0x91 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_46_public_y[] = { +/* QCAVSy */ + 0xda, 0xd1, 0x1d, 0xd5, 0xec, 0xe8, 0xcf, 0xd9, 0xf9, 0x7c, 0x9a, 0x52, + 0x6e, 0x4a, 0x15, 0x06, 0xe6, 0x35, 0x59, 0x69, 0xee, 0x87, 0x82, 0x6f, + 0xc3, 0x8b, 0xcd, 0x24 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_46_private[] = { +/* dIUT */ + 0x3d, 0x63, 0x56, 0x91, 0xb6, 0x2a, 0x9a, 0x92, 0x7c, 0x63, 0x39, 0x51, + 0xc9, 0x36, 0x9c, 0x88, 0x62, 0xbd, 0x21, 0x19, 0xd3, 0x09, 0x70, 0xc2, + 0x64, 0x47, 0x27, 0xd6 +}; +/* QIUTx = 438bbb980517afb20be1d674e3ac2b31cef07a9b23fb8f6e38e0d6c0 */ +/* QIUTy = 0be5f1c47d58d21b6ed28423b32f5a94750da47edcef33ea79942afd */ +static const uint8_t nist_kas_ecc_cdh_testvector_46_out[] = { +/* ZIUT */ + 0x82, 0xfd, 0x2f, 0x9c, 0x60, 0xc4, 0xf9, 0x99, 0xac, 0x00, 0xbb, 0xe6, + 0x4b, 0xfc, 0x11, 0xda, 0x8f, 0xf8, 0xcd, 0xa2, 0xe4, 0x99, 0xfc, 0xed, + 0x65, 0x23, 0x0b, 0xb1 +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_47_public_x[] = { +/* QCAVSx */ + 0xce, 0x91, 0x26, 0xdd, 0x53, 0x97, 0x2d, 0xea, 0x1d, 0xe1, 0xd1, 0x1e, + 0xfe, 0xf9, 0x00, 0xde, 0x34, 0xb6, 0x61, 0x85, 0x9c, 0x46, 0x48, 0xc5, + 0xc0, 0xe5, 0x34, 0xf7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_47_public_y[] = { +/* QCAVSy */ + 0xe1, 0x13, 0xb6, 0xf2, 0xc1, 0x65, 0x9d, 0x07, 0xf2, 0x71, 0x6e, 0x64, + 0xa8, 0x3c, 0x18, 0xbb, 0xce, 0x34, 0x4d, 0xd2, 0x12, 0x1f, 0xe8, 0x51, + 0x68, 0xea, 0xe0, 0x85 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_47_private[] = { +/* dIUT */ + 0xac, 0xf3, 0xc8, 0x5b, 0xbd, 0xc3, 0x79, 0xf0, 0x2f, 0x5e, 0xa3, 0x6e, + 0x7f, 0x0f, 0x53, 0x09, 0x5a, 0x9e, 0x70, 0x46, 0xa2, 0x86, 0x85, 0xa8, + 0x65, 0x9b, 0xf7, 0x98 +}; +/* QIUTx = ff7511215c71d796bd646e8474be4416b91684ce0d269ef6f422013b */ +/* QIUTy = b7bf5e79b5a9393bb9ea42c0bdb2d3c2dc806e1a7306aa58e4fdbea5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_47_out[] = { +/* ZIUT */ + 0x53, 0x0f, 0x7e, 0x7f, 0xc9, 0x32, 0x61, 0x3b, 0x29, 0xc9, 0x81, 0xf2, + 0x61, 0xcb, 0x03, 0x6c, 0xba, 0x3f, 0x1d, 0xf3, 0x86, 0x4e, 0x0e, 0x1c, + 0xba, 0x26, 0x85, 0xa2 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_48_public_x[] = { +/* QCAVSx */ + 0x84, 0x41, 0x99, 0x67, 0xd6, 0xcf, 0xad, 0x41, 0xe7, 0x5a, 0x02, 0xb6, + 0xda, 0x60, 0x5a, 0x97, 0x94, 0x9a, 0x18, 0x3a, 0x97, 0xc3, 0x06, 0xc4, + 0xb4, 0x6e, 0x66, 0xa5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_48_public_y[] = { +/* QCAVSy */ + 0x5c, 0xc9, 0xb2, 0x59, 0x71, 0x8b, 0x1b, 0xc8, 0xb1, 0x44, 0xfd, 0xe6, + 0x33, 0xa8, 0x94, 0x61, 0x6f, 0xfd, 0x59, 0xa3, 0xa6, 0xd5, 0xd8, 0xe9, + 0x42, 0xc7, 0xcb, 0xb7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_48_private[] = { +/* dIUT */ + 0xcf, 0xfd, 0x62, 0xcb, 0x00, 0xa0, 0xe3, 0x16, 0x3f, 0xbf, 0x2c, 0x39, + 0x7f, 0xad, 0xc9, 0x61, 0x82, 0x10, 0xf8, 0x6b, 0x4f, 0x54, 0xa6, 0x75, + 0x28, 0x73, 0x05, 0xf0 +}; +/* QIUTx = 04bf4d948f4430d18b4ed6c96dbaf981fa11a403ed16887f06754981 */ +/* QIUTy = 7c1326a9cef51f79d4e78303d6064b459f612584ac2fdf593d7d5d84 */ +static const uint8_t nist_kas_ecc_cdh_testvector_48_out[] = { +/* ZIUT */ + 0x49, 0xf6, 0xfd, 0x01, 0x39, 0x24, 0x8e, 0xf4, 0xdf, 0x2d, 0xb0, 0x5d, + 0x13, 0x19, 0xbd, 0x5b, 0x14, 0x89, 0xe2, 0x49, 0x82, 0x7a, 0x45, 0xa8, + 0xa5, 0xf1, 0x24, 0x27 +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_49_public_x[] = { +/* QCAVSx */ + 0x7c, 0x9c, 0xac, 0x35, 0x76, 0x80, 0x63, 0xc2, 0x82, 0x7f, 0x60, 0xa7, + 0xf5, 0x13, 0x88, 0xf2, 0xa8, 0xf4, 0xb7, 0xf8, 0xcd, 0x73, 0x6b, 0xd6, + 0xbc, 0x33, 0x74, 0x77 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_49_public_y[] = { +/* QCAVSy */ + 0x29, 0xee, 0x6b, 0x84, 0x9c, 0x60, 0x25, 0xd5, 0x77, 0xdb, 0xcc, 0x55, + 0xfb, 0xd1, 0x70, 0x18, 0xf4, 0xed, 0xbc, 0x2e, 0xf1, 0x05, 0xb0, 0x04, + 0xd6, 0x25, 0x7b, 0xcd +}; +static const uint8_t nist_kas_ecc_cdh_testvector_49_private[] = { +/* dIUT */ + 0x85, 0xf9, 0x03, 0xe4, 0x39, 0x43, 0xd1, 0x3c, 0x68, 0x93, 0x2e, 0x71, + 0x0e, 0x80, 0xde, 0x52, 0xcb, 0xc0, 0xb8, 0xf1, 0xa1, 0x41, 0x8e, 0xa4, + 0xda, 0x07, 0x92, 0x99 +}; +/* QIUTx = 970a4a7e01d4188497ceb46955eb1b842d9085819a9b925c84529d3d */ +/* QIUTy = dfa2526480f833ea0edbd204e4e365fef3472888fe7d9691c3ebc09f */ +static const uint8_t nist_kas_ecc_cdh_testvector_49_out[] = { +/* ZIUT */ + 0x8f, 0x7e, 0x34, 0xe5, 0x97, 0xae, 0x80, 0x93, 0xb9, 0x82, 0x70, 0xa7, + 0x4a, 0x8d, 0xfc, 0xdb, 0xed, 0x45, 0x7f, 0x42, 0xf4, 0x3d, 0xf4, 0x87, + 0xc5, 0x48, 0x71, 0x61 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_50_public_x[] = { +/* QCAVSx */ + 0x08, 0x5a, 0x76, 0x42, 0xad, 0x8e, 0x59, 0xb1, 0xa3, 0xe8, 0x72, 0x6a, + 0x75, 0x47, 0xaf, 0xbe, 0xcf, 0xfd, 0xac, 0x1d, 0xab, 0x7e, 0x57, 0x23, + 0x0c, 0x6a, 0x9d, 0xf4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_50_public_y[] = { +/* QCAVSy */ + 0xf9, 0x1c, 0x36, 0xd8, 0x81, 0xfe, 0x9b, 0x80, 0x47, 0xa3, 0x53, 0x07, + 0x13, 0x55, 0x4a, 0x1a, 0xf4, 0xc2, 0x5c, 0x5a, 0x8e, 0x65, 0x4d, 0xcd, + 0xcf, 0x68, 0x9f, 0x2e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_50_private[] = { +/* dIUT */ + 0xcc, 0xe6, 0x48, 0x91, 0xa3, 0xd0, 0x12, 0x9f, 0xee, 0x0d, 0x4a, 0x96, + 0xcf, 0xbe, 0x7a, 0xc4, 0x70, 0xb8, 0x5e, 0x96, 0x75, 0x29, 0x05, 0x7c, + 0xfa, 0x31, 0xa1, 0xd9 +}; +/* QIUTx = a6b29632db94da2125dc1cf80e03702687b2acc1122022fa2174765a */ +/* QIUTy = 61723edd73e10daed73775278f1958ba56f1fc9d085ebc2b64c84fe5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_50_out[] = { +/* ZIUT */ + 0x71, 0x95, 0x4e, 0x22, 0x61, 0xe8, 0x51, 0x0b, 0xe1, 0xa0, 0x60, 0x73, + 0x36, 0x71, 0xd2, 0xe9, 0xd0, 0xa2, 0xd0, 0x12, 0xeb, 0x4e, 0x09, 0x55, + 0x6d, 0x69, 0x7d, 0x2a +}; +/* [P-256] */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_51_public_x[] = { +/* QCAVSx */ + 0x70, 0x0c, 0x48, 0xf7, 0x7f, 0x56, 0x58, 0x4c, 0x5c, 0xc6, 0x32, 0xca, + 0x65, 0x64, 0x0d, 0xb9, 0x1b, 0x6b, 0xac, 0xce, 0x3a, 0x4d, 0xf6, 0xb4, + 0x2c, 0xe7, 0xcc, 0x83, 0x88, 0x33, 0xd2, 0x87 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_51_public_y[] = { +/* QCAVSy */ + 0xdb, 0x71, 0xe5, 0x09, 0xe3, 0xfd, 0x9b, 0x06, 0x0d, 0xdb, 0x20, 0xba, + 0x5c, 0x51, 0xdc, 0xc5, 0x94, 0x8d, 0x46, 0xfb, 0xf6, 0x40, 0xdf, 0xe0, + 0x44, 0x17, 0x82, 0xca, 0xb8, 0x5f, 0xa4, 0xac +}; +static const uint8_t nist_kas_ecc_cdh_testvector_51_private[] = { +/* dIUT */ + 0x7d, 0x7d, 0xc5, 0xf7, 0x1e, 0xb2, 0x9d, 0xda, 0xf8, 0x0d, 0x62, 0x14, + 0x63, 0x2e, 0xea, 0xe0, 0x3d, 0x90, 0x58, 0xaf, 0x1f, 0xb6, 0xd2, 0x2e, + 0xd8, 0x0b, 0xad, 0xb6, 0x2b, 0xc1, 0xa5, 0x34 +}; +/* QIUTx = ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230 */ +/* QIUTy = 28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141 */ +static const uint8_t nist_kas_ecc_cdh_testvector_51_out[] = { +/* ZIUT */ + 0x46, 0xfc, 0x62, 0x10, 0x64, 0x20, 0xff, 0x01, 0x2e, 0x54, 0xa4, 0x34, + 0xfb, 0xdd, 0x2d, 0x25, 0xcc, 0xc5, 0x85, 0x20, 0x60, 0x56, 0x1e, 0x68, + 0x04, 0x0d, 0xd7, 0x77, 0x89, 0x97, 0xbd, 0x7b +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_52_public_x[] = { +/* QCAVSx */ + 0x80, 0x9f, 0x04, 0x28, 0x9c, 0x64, 0x34, 0x8c, 0x01, 0x51, 0x5e, 0xb0, + 0x3d, 0x5c, 0xe7, 0xac, 0x1a, 0x8c, 0xb9, 0x49, 0x8f, 0x5c, 0xaa, 0x50, + 0x19, 0x7e, 0x58, 0xd4, 0x3a, 0x86, 0xa7, 0xae +}; +static const uint8_t nist_kas_ecc_cdh_testvector_52_public_y[] = { +/* QCAVSy */ + 0xb2, 0x9d, 0x84, 0xe8, 0x11, 0x19, 0x7f, 0x25, 0xeb, 0xa8, 0xf5, 0x19, + 0x40, 0x92, 0xcb, 0x6f, 0xf4, 0x40, 0xe2, 0x6d, 0x44, 0x21, 0x01, 0x13, + 0x72, 0x46, 0x1f, 0x57, 0x92, 0x71, 0xcd, 0xa3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_52_private[] = { +/* dIUT */ + 0x38, 0xf6, 0x5d, 0x6d, 0xce, 0x47, 0x67, 0x60, 0x44, 0xd5, 0x8c, 0xe5, + 0x13, 0x95, 0x82, 0xd5, 0x68, 0xf6, 0x4b, 0xb1, 0x60, 0x98, 0xd1, 0x79, + 0xdb, 0xab, 0x07, 0x74, 0x1d, 0xd5, 0xca, 0xf5 +}; +/* QIUTx = 119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d0 */ +/* QIUTy = 8f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d */ +static const uint8_t nist_kas_ecc_cdh_testvector_52_out[] = { +/* ZIUT */ + 0x05, 0x7d, 0x63, 0x60, 0x96, 0xcb, 0x80, 0xb6, 0x7a, 0x8c, 0x03, 0x8c, + 0x89, 0x0e, 0x88, 0x7d, 0x1a, 0xdf, 0xa4, 0x19, 0x5e, 0x9b, 0x3c, 0xe2, + 0x41, 0xc8, 0xa7, 0x78, 0xc5, 0x9c, 0xda, 0x67 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_53_public_x[] = { +/* QCAVSx */ + 0xa2, 0x33, 0x9c, 0x12, 0xd4, 0xa0, 0x3c, 0x33, 0x54, 0x6d, 0xe5, 0x33, + 0x26, 0x8b, 0x4a, 0xd6, 0x67, 0xde, 0xbf, 0x45, 0x8b, 0x46, 0x4d, 0x77, + 0x44, 0x36, 0x36, 0x44, 0x0e, 0xe7, 0xfe, 0xc3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_53_public_y[] = { +/* QCAVSy */ + 0xef, 0x48, 0xa3, 0xab, 0x26, 0xe2, 0x02, 0x20, 0xbc, 0xda, 0x2c, 0x18, + 0x51, 0x07, 0x68, 0x39, 0xda, 0xe8, 0x8e, 0xae, 0x96, 0x28, 0x69, 0xa4, + 0x97, 0xbf, 0x73, 0xcb, 0x66, 0xfa, 0xf5, 0x36 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_53_private[] = { +/* dIUT */ + 0x1a, 0xcc, 0xfa, 0xf1, 0xb9, 0x77, 0x12, 0xb8, 0x5a, 0x6f, 0x54, 0xb1, + 0x48, 0x98, 0x5a, 0x1b, 0xdc, 0x4c, 0x9b, 0xec, 0x0b, 0xd2, 0x58, 0xca, + 0xd4, 0xb3, 0xd6, 0x03, 0xf4, 0x9f, 0x32, 0xc8 +}; +/* QIUTx = d9f2b79c172845bfdb560bbb01447ca5ecc0470a09513b6126902c6b4f8d1051 */ +/* QIUTy = f815ef5ec32128d3487834764678702e64e164ff7315185e23aff5facd96d7bc */ +static const uint8_t nist_kas_ecc_cdh_testvector_53_out[] = { +/* ZIUT */ + 0x2d, 0x45, 0x7b, 0x78, 0xb4, 0x61, 0x41, 0x32, 0x47, 0x76, 0x18, 0xa5, + 0xb0, 0x77, 0x96, 0x5e, 0xc9, 0x07, 0x30, 0xa8, 0xc8, 0x1a, 0x1c, 0x75, + 0xd6, 0xd4, 0xec, 0x68, 0x00, 0x5d, 0x67, 0xec +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_54_public_x[] = { +/* QCAVSx */ + 0xdf, 0x39, 0x89, 0xb9, 0xfa, 0x55, 0x49, 0x57, 0x19, 0xb3, 0xcf, 0x46, + 0xdc, 0xcd, 0x28, 0xb5, 0x15, 0x3f, 0x78, 0x08, 0x19, 0x1d, 0xd5, 0x18, + 0xef, 0xf0, 0xc3, 0xcf, 0xf2, 0xb7, 0x05, 0xed +}; +static const uint8_t nist_kas_ecc_cdh_testvector_54_public_y[] = { +/* QCAVSy */ + 0x42, 0x22, 0x94, 0xff, 0x46, 0x00, 0x34, 0x29, 0xd7, 0x39, 0xa3, 0x32, + 0x06, 0xc8, 0x75, 0x25, 0x52, 0xc8, 0xba, 0x54, 0xa2, 0x70, 0xde, 0xfc, + 0x06, 0xe2, 0x21, 0xe0, 0xfe, 0xaf, 0x6a, 0xc4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_54_private[] = { +/* dIUT */ + 0x20, 0x7c, 0x43, 0xa7, 0x9b, 0xfe, 0xe0, 0x3d, 0xb6, 0xf4, 0xb9, 0x44, + 0xf5, 0x3d, 0x2f, 0xb7, 0x6c, 0xc4, 0x9e, 0xf1, 0xc9, 0xc4, 0xd3, 0x4d, + 0x51, 0xb6, 0xc6, 0x5c, 0x4d, 0xb6, 0x93, 0x2d +}; +/* QIUTx = 24277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0d */ +/* QIUTy = c4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88 */ +static const uint8_t nist_kas_ecc_cdh_testvector_54_out[] = { +/* ZIUT */ + 0x96, 0x44, 0x12, 0x59, 0x53, 0x4b, 0x80, 0xf6, 0xae, 0xe3, 0xd2, 0x87, + 0xa6, 0xbb, 0x17, 0xb5, 0x09, 0x4d, 0xd4, 0x27, 0x7d, 0x9e, 0x29, 0x4f, + 0x8f, 0xe7, 0x3e, 0x48, 0xbf, 0x2a, 0x00, 0x24 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_55_public_x[] = { +/* QCAVSx */ + 0x41, 0x19, 0x2d, 0x28, 0x13, 0xe7, 0x95, 0x61, 0xe6, 0xa1, 0xd6, 0xf5, + 0x3c, 0x8b, 0xc1, 0xa4, 0x33, 0xa1, 0x99, 0xc8, 0x35, 0xe1, 0x41, 0xb0, + 0x5a, 0x74, 0xa9, 0x7b, 0x0f, 0xae, 0xb9, 0x22 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_55_public_y[] = { +/* QCAVSy */ + 0x1a, 0xf9, 0x8c, 0xc4, 0x5e, 0x98, 0xa7, 0xe0, 0x41, 0xb0, 0x1c, 0xf3, + 0x5f, 0x46, 0x2b, 0x75, 0x62, 0x28, 0x13, 0x51, 0xc8, 0xeb, 0xf3, 0xff, + 0xa0, 0x2e, 0x33, 0xa0, 0x72, 0x2a, 0x13, 0x28 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_55_private[] = { +/* dIUT */ + 0x59, 0x13, 0x7e, 0x38, 0x15, 0x23, 0x50, 0xb1, 0x95, 0xc9, 0x71, 0x8d, + 0x39, 0x67, 0x3d, 0x51, 0x98, 0x38, 0x05, 0x5a, 0xd9, 0x08, 0xdd, 0x47, + 0x57, 0x15, 0x2f, 0xd8, 0x25, 0x5c, 0x09, 0xbf +}; +/* QIUTx = a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b */ +/* QIUTy = 806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a */ +static const uint8_t nist_kas_ecc_cdh_testvector_55_out[] = { +/* ZIUT */ + 0x19, 0xd4, 0x4c, 0x8d, 0x63, 0xe8, 0xe8, 0xdd, 0x12, 0xc2, 0x2a, 0x87, + 0xb8, 0xcd, 0x4e, 0xce, 0x27, 0xac, 0xdd, 0xe0, 0x4d, 0xbf, 0x47, 0xf7, + 0xf2, 0x75, 0x37, 0xa6, 0x99, 0x9a, 0x8e, 0x62 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_56_public_x[] = { +/* QCAVSx */ + 0x33, 0xe8, 0x20, 0x92, 0xa0, 0xf1, 0xfb, 0x38, 0xf5, 0x64, 0x9d, 0x58, + 0x67, 0xfb, 0xa2, 0x8b, 0x50, 0x31, 0x72, 0xb7, 0x03, 0x55, 0x74, 0xbf, + 0x8e, 0x5b, 0x71, 0x00, 0xa3, 0x05, 0x27, 0x92 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_56_public_y[] = { +/* QCAVSy */ + 0xf2, 0xcf, 0x6b, 0x60, 0x1e, 0x0a, 0x05, 0x94, 0x5e, 0x33, 0x55, 0x50, + 0xbf, 0x64, 0x8d, 0x78, 0x2f, 0x46, 0x18, 0x6c, 0x77, 0x2c, 0x0f, 0x20, + 0xd3, 0xcd, 0x0d, 0x6b, 0x8c, 0xa1, 0x4b, 0x2f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_56_private[] = { +/* dIUT */ + 0xf5, 0xf8, 0xe0, 0x17, 0x46, 0x10, 0xa6, 0x61, 0x27, 0x79, 0x79, 0xb5, + 0x8c, 0xe5, 0xc9, 0x0f, 0xee, 0x6c, 0x9b, 0x3b, 0xb3, 0x46, 0xa9, 0x0a, + 0x71, 0x96, 0x25, 0x5e, 0x40, 0xb1, 0x32, 0xef +}; +/* QIUTx = 7b861dcd2844a5a8363f6b8ef8d493640f55879217189d80326aad9480dfc149 */ +/* QIUTy = c4675b45eeb306405f6c33c38bc69eb2bdec9b75ad5af4706aab84543b9cc63a */ +static const uint8_t nist_kas_ecc_cdh_testvector_56_out[] = { +/* ZIUT */ + 0x66, 0x4e, 0x45, 0xd5, 0xbb, 0xa4, 0xac, 0x93, 0x1c, 0xd6, 0x5d, 0x52, + 0x01, 0x7e, 0x4b, 0xe9, 0xb1, 0x9a, 0x51, 0x5f, 0x66, 0x9b, 0xea, 0x47, + 0x03, 0x54, 0x2a, 0x2c, 0x52, 0x5c, 0xd3, 0xd3 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_57_public_x[] = { +/* QCAVSx */ + 0x6a, 0x9e, 0x0c, 0x3f, 0x91, 0x6e, 0x4e, 0x31, 0x5c, 0x91, 0x14, 0x7b, + 0xe5, 0x71, 0x68, 0x6d, 0x90, 0x46, 0x4e, 0x8b, 0xf9, 0x81, 0xd3, 0x4a, + 0x90, 0xb6, 0x35, 0x3b, 0xca, 0x6e, 0xeb, 0xa7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_57_public_y[] = { +/* QCAVSy */ + 0x40, 0xf9, 0xbe, 0xad, 0x39, 0xc2, 0xf2, 0xbc, 0xc2, 0x60, 0x2f, 0x75, + 0xb8, 0xa7, 0x3e, 0xc7, 0xbd, 0xff, 0xcb, 0xce, 0xad, 0x15, 0x9d, 0x01, + 0x74, 0xc6, 0xc4, 0xd3, 0xc5, 0x35, 0x7f, 0x05 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_57_private[] = { +/* dIUT */ + 0x3b, 0x58, 0x9a, 0xf7, 0xdb, 0x03, 0x45, 0x9c, 0x23, 0x06, 0x8b, 0x64, + 0xf6, 0x3f, 0x28, 0xd3, 0xc3, 0xc6, 0xbc, 0x25, 0xb5, 0xbf, 0x76, 0xac, + 0x05, 0xf3, 0x54, 0x82, 0x88, 0x8b, 0x51, 0x90 +}; +/* QIUTx = 9fb38e2d58ea1baf7622e96720101cae3cde4ba6c1e9fa26d9b1de0899102863 */ +/* QIUTy = d5561b900406edf50802dd7d73e89395f8aed72fba0e1d1b61fe1d22302260f0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_57_out[] = { +/* ZIUT */ + 0xca, 0x34, 0x2d, 0xaa, 0x50, 0xdc, 0x09, 0xd6, 0x1b, 0xe7, 0xc1, 0x96, + 0xc8, 0x5e, 0x60, 0xa8, 0x0c, 0x5c, 0xb0, 0x49, 0x31, 0x74, 0x68, 0x20, + 0xbe, 0x54, 0x8c, 0xdd, 0xe0, 0x55, 0x67, 0x9d +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_58_public_x[] = { +/* QCAVSx */ + 0xa9, 0xc0, 0xac, 0xad, 0xe5, 0x5c, 0x2a, 0x73, 0xea, 0xd1, 0xa8, 0x6f, + 0xb0, 0xa9, 0x71, 0x32, 0x23, 0xc8, 0x24, 0x75, 0x79, 0x1c, 0xd0, 0xe2, + 0x10, 0xb0, 0x46, 0x41, 0x2c, 0xe2, 0x24, 0xbb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_58_public_y[] = { +/* QCAVSy */ + 0xf6, 0xde, 0x0a, 0xfa, 0x20, 0xe9, 0x3e, 0x07, 0x84, 0x67, 0xc0, 0x53, + 0xd2, 0x41, 0x90, 0x3e, 0xda, 0xd7, 0x34, 0xc6, 0xb4, 0x03, 0xba, 0x75, + 0x8c, 0x2b, 0x5f, 0xf0, 0x4c, 0x9d, 0x42, 0x29 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_58_private[] = { +/* dIUT */ + 0xd8, 0xbf, 0x92, 0x9a, 0x20, 0xea, 0x74, 0x36, 0xb2, 0x46, 0x1b, 0x54, + 0x1a, 0x11, 0xc8, 0x0e, 0x61, 0xd8, 0x26, 0xc0, 0xa4, 0xc9, 0xd3, 0x22, + 0xb3, 0x1d, 0xd5, 0x4e, 0x7f, 0x58, 0xb9, 0xc8 +}; +/* QIUTx = 20f07631e4a6512a89ad487c4e9d63039e579cb0d7a556cb9e661cd59c1e7fa4 */ +/* QIUTy = 6de91846b3eee8a5ec09c2ab1f41e21bd83620ccdd1bdce3ab7ea6e02dd274f5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_58_out[] = { +/* ZIUT */ + 0x35, 0xaa, 0x9b, 0x52, 0x53, 0x6a, 0x46, 0x1b, 0xfd, 0xe4, 0xe8, 0x5f, + 0xc7, 0x56, 0xbe, 0x92, 0x8c, 0x7d, 0xe9, 0x79, 0x23, 0xf0, 0x41, 0x6c, + 0x7a, 0x3a, 0xc8, 0xf8, 0x8b, 0x3d, 0x44, 0x89 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_59_public_x[] = { +/* QCAVSx */ + 0x94, 0xe9, 0x4f, 0x16, 0xa9, 0x82, 0x55, 0xff, 0xf2, 0xb9, 0xac, 0x0c, + 0x95, 0x98, 0xaa, 0xc3, 0x54, 0x87, 0xb3, 0x23, 0x2d, 0x32, 0x31, 0xbd, + 0x93, 0xb7, 0xdb, 0x7d, 0xf3, 0x6f, 0x9e, 0xb9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_59_public_y[] = { +/* QCAVSy */ + 0xd8, 0x04, 0x9a, 0x43, 0x57, 0x9c, 0xfa, 0x90, 0xb8, 0x09, 0x3a, 0x94, + 0x41, 0x6c, 0xbe, 0xfb, 0xf9, 0x33, 0x86, 0xf1, 0x5b, 0x3f, 0x6e, 0x19, + 0x0b, 0x6e, 0x34, 0x55, 0xfe, 0xdf, 0xe6, 0x9a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_59_private[] = { +/* dIUT */ + 0x0f, 0x98, 0x83, 0xba, 0x0e, 0xf3, 0x2e, 0xe7, 0x5d, 0xed, 0x0d, 0x8b, + 0xda, 0x39, 0xa5, 0x14, 0x6a, 0x29, 0xf1, 0xf2, 0x50, 0x7b, 0x3b, 0xd4, + 0x58, 0xdb, 0xea, 0x0b, 0x2b, 0xb0, 0x5b, 0x4d +}; +/* QIUTx = abb61b423be5d6c26e21c605832c9142dc1dfe5a5fff28726737936e6fbf516d */ +/* QIUTy = 733d2513ef58beab202090586fac91bf0fee31e80ab33473ab23a2d89e58fad6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_59_out[] = { +/* ZIUT */ + 0x60, 0x5c, 0x16, 0x17, 0x8a, 0x9b, 0xc8, 0x75, 0xdc, 0xbf, 0xf5, 0x4d, + 0x63, 0xfe, 0x00, 0xdf, 0x69, 0x9c, 0x03, 0xe8, 0xa8, 0x88, 0xe9, 0xe9, + 0x4d, 0xfb, 0xab, 0x90, 0xb2, 0x5f, 0x39, 0xb4 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_60_public_x[] = { +/* QCAVSx */ + 0xe0, 0x99, 0xbf, 0x2a, 0x4d, 0x55, 0x74, 0x60, 0xb5, 0x54, 0x44, 0x30, + 0xbb, 0xf6, 0xda, 0x11, 0x00, 0x4d, 0x12, 0x7c, 0xb5, 0xd6, 0x7f, 0x64, + 0xab, 0x07, 0xc9, 0x4f, 0xcd, 0xf5, 0x27, 0x4f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_60_public_y[] = { +/* QCAVSy */ + 0xd9, 0xc5, 0x0d, 0xbe, 0x70, 0xd7, 0x14, 0xed, 0xb5, 0xe2, 0x21, 0xf4, + 0xe0, 0x20, 0x61, 0x0e, 0xeb, 0x62, 0x70, 0x51, 0x7e, 0x68, 0x8c, 0xa6, + 0x4f, 0xb0, 0xe9, 0x8c, 0x7e, 0xf8, 0xc1, 0xc5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_60_private[] = { +/* dIUT */ + 0x2b, 0xee, 0xdb, 0x04, 0xb0, 0x5c, 0x69, 0x88, 0xf6, 0xa6, 0x75, 0x00, + 0xbb, 0x81, 0x3f, 0xaf, 0x2c, 0xae, 0x0d, 0x58, 0x0c, 0x92, 0x53, 0xb6, + 0x33, 0x9e, 0x4a, 0x33, 0x37, 0xbb, 0x6c, 0x08 +}; +/* QIUTx = 3d63e429cb5fa895a9247129bf4e48e89f35d7b11de8158efeb3e106a2a87395 */ +/* QIUTy = 0cae9e477ef41e7c8c1064379bb7b554ddcbcae79f9814281f1e50f0403c61f3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_60_out[] = { +/* ZIUT */ + 0xf9, 0x6e, 0x40, 0xa1, 0xb7, 0x28, 0x40, 0x85, 0x4b, 0xb6, 0x2b, 0xc1, + 0x3c, 0x40, 0xcc, 0x27, 0x95, 0xe3, 0x73, 0xd4, 0xe7, 0x15, 0x98, 0x0b, + 0x26, 0x14, 0x76, 0x83, 0x5a, 0x09, 0x2e, 0x0b +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_61_public_x[] = { +/* QCAVSx */ + 0xf7, 0x5a, 0x5f, 0xe5, 0x6b, 0xda, 0x34, 0xf3, 0xc1, 0x39, 0x62, 0x96, + 0x62, 0x6e, 0xf0, 0x12, 0xdc, 0x07, 0xe4, 0x82, 0x58, 0x38, 0x77, 0x8a, + 0x64, 0x5c, 0x82, 0x48, 0xcf, 0xf0, 0x16, 0x58 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_61_public_y[] = { +/* QCAVSy */ + 0x33, 0xbb, 0xdf, 0x1b, 0x17, 0x72, 0xd8, 0x05, 0x9d, 0xf5, 0x68, 0xb0, + 0x61, 0xf3, 0xf1, 0x12, 0x2f, 0x28, 0xa8, 0xd8, 0x19, 0x16, 0x7c, 0x97, + 0xbe, 0x44, 0x8e, 0x3d, 0xc3, 0xfb, 0x0c, 0x3c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_61_private[] = { +/* dIUT */ + 0x77, 0xc1, 0x5d, 0xcf, 0x44, 0x61, 0x0e, 0x41, 0x69, 0x6b, 0xab, 0x75, + 0x89, 0x43, 0xef, 0xf1, 0x40, 0x93, 0x33, 0xe4, 0xd5, 0xa1, 0x1b, 0xbe, + 0x72, 0xc8, 0xf6, 0xc3, 0x95, 0xe9, 0xf8, 0x48 +}; +/* QIUTx = ad5d13c3db508ddcd38457e5991434a251bed49cf5ddcb59cdee73865f138c9f */ +/* QIUTy = 62cec1e70588aa4fdfc7b9a09daa678081c04e1208b9d662b8a2214bf8e81a21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_61_out[] = { +/* ZIUT */ + 0x83, 0x88, 0xfa, 0x79, 0xc4, 0xba, 0xbd, 0xca, 0x02, 0xa8, 0xe8, 0xa3, + 0x4f, 0x9e, 0x43, 0x55, 0x49, 0x76, 0xe4, 0x20, 0xa4, 0xad, 0x27, 0x3c, + 0x81, 0xb2, 0x6e, 0x42, 0x28, 0xe9, 0xd3, 0xa3 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_62_public_x[] = { +/* QCAVSx */ + 0x2d, 0xb4, 0x54, 0x0d, 0x50, 0x23, 0x07, 0x56, 0x15, 0x8a, 0xbf, 0x61, + 0xd9, 0x83, 0x57, 0x12, 0xb6, 0x48, 0x6c, 0x74, 0x31, 0x21, 0x83, 0xcc, + 0xef, 0xca, 0xef, 0x27, 0x97, 0xb7, 0x67, 0x4d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_62_public_y[] = { +/* QCAVSy */ + 0x62, 0xf5, 0x7f, 0x31, 0x4e, 0x3f, 0x34, 0x95, 0xdc, 0x4e, 0x09, 0x90, + 0x12, 0xf5, 0xe0, 0xba, 0x71, 0x77, 0x0f, 0x96, 0x60, 0xa1, 0xea, 0xda, + 0x54, 0x10, 0x4c, 0xdf, 0xde, 0x77, 0x24, 0x3e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_62_private[] = { +/* dIUT */ + 0x42, 0xa8, 0x3b, 0x98, 0x50, 0x11, 0xd1, 0x23, 0x03, 0xdb, 0x1a, 0x80, + 0x0f, 0x26, 0x10, 0xf7, 0x4a, 0xa7, 0x1c, 0xdf, 0x19, 0xc6, 0x7d, 0x54, + 0xce, 0x6c, 0x9e, 0xd9, 0x51, 0xe9, 0x09, 0x3e +}; +/* QIUTx = ab48caa61ea35f13f8ed07ffa6a13e8db224dfecfae1a7df8b1bb6ebaf0cb97d */ +/* QIUTy = 1274530ca2c385a3218bddfbcbf0b4024c9badd5243bff834ebff24a8618dccb */ +static const uint8_t nist_kas_ecc_cdh_testvector_62_out[] = { +/* ZIUT */ + 0x72, 0x87, 0x7c, 0xea, 0x33, 0xcc, 0xc4, 0x71, 0x50, 0x38, 0xd4, 0xbc, + 0xbd, 0xfe, 0x0e, 0x43, 0xf4, 0x2a, 0x9e, 0x2c, 0x0c, 0x3b, 0x01, 0x7f, + 0xc2, 0x37, 0x0f, 0x4b, 0x9a, 0xcb, 0xda, 0x4a +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_63_public_x[] = { +/* QCAVSx */ + 0xcd, 0x94, 0xfc, 0x94, 0x97, 0xe8, 0x99, 0x07, 0x50, 0x30, 0x9e, 0x9a, + 0x85, 0x34, 0xfd, 0x11, 0x4b, 0x0a, 0x6e, 0x54, 0xda, 0x89, 0xc4, 0x79, + 0x61, 0x01, 0x89, 0x70, 0x41, 0xd1, 0x4e, 0xcb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_63_public_y[] = { +/* QCAVSy */ + 0xc3, 0xde, 0xf4, 0xb5, 0xfe, 0x04, 0xfa, 0xee, 0x0a, 0x11, 0x93, 0x22, + 0x29, 0xff, 0xf5, 0x63, 0x63, 0x7b, 0xfd, 0xee, 0x0e, 0x79, 0xc6, 0xde, + 0xea, 0xf4, 0x49, 0xf8, 0x54, 0x01, 0xc5, 0xc4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_63_private[] = { +/* dIUT */ + 0xce, 0xed, 0x35, 0x50, 0x7b, 0x5c, 0x93, 0xea, 0xd5, 0x98, 0x91, 0x19, + 0xb9, 0xba, 0x34, 0x2c, 0xfe, 0x38, 0xe6, 0xe6, 0x38, 0xba, 0x6e, 0xea, + 0x34, 0x3a, 0x55, 0x47, 0x5d, 0xe2, 0x80, 0x0b +}; +/* QIUTx = 9a8cd9bd72e71752df91440f77c547509a84df98114e7de4f26cdb39234a625d */ +/* QIUTy = d07cfc84c8e144fab2839f5189bb1d7c88631d579bbc58012ed9a2327da52f62 */ +static const uint8_t nist_kas_ecc_cdh_testvector_63_out[] = { +/* ZIUT */ + 0xe4, 0xe7, 0x40, 0x8d, 0x85, 0xff, 0x0e, 0x0e, 0x9c, 0x83, 0x80, 0x03, + 0xf2, 0x8c, 0xdb, 0xd5, 0x24, 0x7c, 0xdc, 0xe3, 0x1f, 0x32, 0xf6, 0x24, + 0x94, 0xb7, 0x0e, 0x5f, 0x1b, 0xc3, 0x63, 0x07 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_64_public_x[] = { +/* QCAVSx */ + 0x15, 0xb9, 0xe4, 0x67, 0xaf, 0x4d, 0x29, 0x0c, 0x41, 0x74, 0x02, 0xe0, + 0x40, 0x42, 0x6f, 0xe4, 0xcf, 0x23, 0x6b, 0xae, 0x72, 0xba, 0xa3, 0x92, + 0xed, 0x89, 0x78, 0x0d, 0xfc, 0xcd, 0xb4, 0x71 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_64_public_y[] = { +/* QCAVSy */ + 0xcd, 0xf4, 0xe9, 0x17, 0x0f, 0xb9, 0x04, 0x30, 0x2b, 0x8f, 0xd9, 0x3a, + 0x82, 0x0b, 0xa8, 0xcc, 0x7e, 0xd4, 0xef, 0xd3, 0xa6, 0xf2, 0xd6, 0xb0, + 0x5b, 0x80, 0xb2, 0xff, 0x2a, 0xee, 0x4e, 0x77 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_64_private[] = { +/* dIUT */ + 0x43, 0xe0, 0xe9, 0xd9, 0x5a, 0xf4, 0xdc, 0x36, 0x48, 0x3c, 0xdd, 0x19, + 0x68, 0xd2, 0xb7, 0xee, 0xb8, 0x61, 0x1f, 0xcc, 0xe7, 0x7f, 0x3a, 0x4e, + 0x7d, 0x05, 0x9a, 0xe4, 0x3e, 0x50, 0x96, 0x04 +}; +/* QIUTx = f989cf8ee956a82e7ebd9881cdbfb2fd946189b08db53559bc8cfdd48071eb14 */ +/* QIUTy = 5eff28f1a18a616b04b7d337868679f6dd84f9a7b3d7b6f8af276c19611a541d */ +static const uint8_t nist_kas_ecc_cdh_testvector_64_out[] = { +/* ZIUT */ + 0xed, 0x56, 0xbc, 0xf6, 0x95, 0xb7, 0x34, 0x14, 0x2c, 0x24, 0xec, 0xb1, + 0xfc, 0x1b, 0xb6, 0x4d, 0x08, 0xf1, 0x75, 0xeb, 0x24, 0x3a, 0x31, 0xf3, + 0x7b, 0x3d, 0x9b, 0xb4, 0x40, 0x7f, 0x3b, 0x96 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_65_public_x[] = { +/* QCAVSx */ + 0x49, 0xc5, 0x03, 0xba, 0x6c, 0x4f, 0xa6, 0x05, 0x18, 0x2e, 0x18, 0x6b, + 0x5e, 0x81, 0x11, 0x3f, 0x07, 0x5b, 0xc1, 0x1d, 0xcf, 0xd5, 0x1c, 0x93, + 0x2f, 0xb2, 0x1e, 0x95, 0x1e, 0xee, 0x2f, 0xa1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_65_public_y[] = { +/* QCAVSy */ + 0x8a, 0xf7, 0x06, 0xff, 0x09, 0x22, 0xd8, 0x7b, 0x3f, 0x0c, 0x5e, 0x4e, + 0x31, 0xd8, 0xb2, 0x59, 0xae, 0xb2, 0x60, 0xa9, 0x26, 0x96, 0x43, 0xed, + 0x52, 0x0a, 0x13, 0xbb, 0x25, 0xda, 0x59, 0x24 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_65_private[] = { +/* dIUT */ + 0xb2, 0xf3, 0x60, 0x0d, 0xf3, 0x36, 0x8e, 0xf8, 0xa0, 0xbb, 0x85, 0xab, + 0x22, 0xf4, 0x1f, 0xc0, 0xe5, 0xf4, 0xfd, 0xd5, 0x4b, 0xe8, 0x16, 0x7a, + 0x5c, 0x3c, 0xd4, 0xb0, 0x8d, 0xb0, 0x49, 0x03 +}; +/* QIUTx = 69c627625b36a429c398b45c38677cb35d8beb1cf78a571e40e99fe4eac1cd4e */ +/* QIUTy = 81690112b0a88f20f7136b28d7d47e5fbc2ada3c8edd87589bc19ec9590637bd */ +static const uint8_t nist_kas_ecc_cdh_testvector_65_out[] = { +/* ZIUT */ + 0xbc, 0x5c, 0x70, 0x55, 0x08, 0x9f, 0xc9, 0xd6, 0xc8, 0x9f, 0x83, 0xc1, + 0xea, 0x1a, 0xda, 0x87, 0x9d, 0x99, 0x34, 0xb2, 0xea, 0x28, 0xfc, 0xf4, + 0xe4, 0xa7, 0xe9, 0x84, 0xb2, 0x8a, 0xd2, 0xcf +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_66_public_x[] = { +/* QCAVSx */ + 0x19, 0xb3, 0x8d, 0xe3, 0x9f, 0xdd, 0x2f, 0x70, 0xf7, 0x09, 0x16, 0x31, + 0xa4, 0xf7, 0x5d, 0x19, 0x93, 0x74, 0x0b, 0xa9, 0x42, 0x91, 0x62, 0xc2, + 0xa4, 0x53, 0x12, 0x40, 0x16, 0x36, 0xb2, 0x9c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_66_public_y[] = { +/* QCAVSy */ + 0x09, 0xae, 0xd7, 0x23, 0x2b, 0x28, 0xe0, 0x60, 0x94, 0x17, 0x41, 0xb6, + 0x82, 0x8b, 0xcd, 0xfa, 0x2b, 0xc4, 0x9c, 0xc8, 0x44, 0xf3, 0x77, 0x36, + 0x11, 0x50, 0x4f, 0x82, 0xa3, 0x90, 0xa5, 0xae +}; +static const uint8_t nist_kas_ecc_cdh_testvector_66_private[] = { +/* dIUT */ + 0x40, 0x02, 0x53, 0x43, 0x07, 0xf8, 0xb6, 0x2a, 0x9b, 0xf6, 0x7f, 0xf6, + 0x41, 0xdd, 0xc6, 0x0f, 0xef, 0x59, 0x3b, 0x17, 0xc3, 0x34, 0x12, 0x39, + 0xe9, 0x5b, 0xdb, 0x3e, 0x57, 0x9b, 0xfd, 0xc8 +}; +/* QIUTx = 5fe964671315a18aa68a2a6e3dd1fde7e23b8ce7181471cfac43c99e1ae80262 */ +/* QIUTy = d5827be282e62c84de531b963884ba832db5d6b2c3a256f0e604fe7e6b8a7f72 */ +static const uint8_t nist_kas_ecc_cdh_testvector_66_out[] = { +/* ZIUT */ + 0x9a, 0x4e, 0x8e, 0x65, 0x7f, 0x6b, 0x0e, 0x09, 0x7f, 0x47, 0x95, 0x4a, + 0x63, 0xc7, 0x5d, 0x74, 0xfc, 0xba, 0x71, 0xa3, 0x0d, 0x83, 0x65, 0x1e, + 0x3e, 0x5a, 0x91, 0xaa, 0x7c, 0xcd, 0x83, 0x43 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_67_public_x[] = { +/* QCAVSx */ + 0x2c, 0x91, 0xc6, 0x1f, 0x33, 0xad, 0xfe, 0x93, 0x11, 0xc9, 0x42, 0xfd, + 0xbf, 0xf6, 0xba, 0x47, 0x02, 0x0f, 0xef, 0xf4, 0x16, 0xb7, 0xbb, 0x63, + 0xce, 0xc1, 0x3f, 0xaf, 0x9b, 0x09, 0x99, 0x54 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_67_public_y[] = { +/* QCAVSy */ + 0x6c, 0xab, 0x31, 0xb0, 0x64, 0x19, 0xe5, 0x22, 0x1f, 0xca, 0x01, 0x4f, + 0xb8, 0x4e, 0xc8, 0x70, 0x62, 0x2a, 0x1b, 0x12, 0xba, 0xb5, 0xae, 0x43, + 0x68, 0x2a, 0xa7, 0xea, 0x73, 0xea, 0x08, 0xd0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_67_private[] = { +/* dIUT */ + 0x4d, 0xfa, 0x12, 0xde, 0xfc, 0x60, 0x31, 0x90, 0x21, 0xb6, 0x81, 0xb3, + 0xff, 0x84, 0xa1, 0x0a, 0x51, 0x19, 0x58, 0xc8, 0x50, 0x93, 0x9e, 0xd4, + 0x56, 0x35, 0x93, 0x4b, 0xa4, 0x97, 0x91, 0x47 +}; +/* QIUTx = c9b2b8496f1440bd4a2d1e52752fd372835b364885e154a7dac49295f281ec7c */ +/* QIUTy = fbe6b926a8a4de26ccc83b802b1212400754be25d9f3eeaf008b09870ae76321 */ +static const uint8_t nist_kas_ecc_cdh_testvector_67_out[] = { +/* ZIUT */ + 0x3c, 0xa1, 0xfc, 0x7a, 0xd8, 0x58, 0xfb, 0x1a, 0x6a, 0xba, 0x23, 0x25, + 0x42, 0xf3, 0xe2, 0xa7, 0x49, 0xff, 0xc7, 0x20, 0x3a, 0x23, 0x74, 0xa3, + 0xf3, 0xd3, 0x26, 0x7f, 0x1f, 0xc9, 0x7b, 0x78 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_68_public_x[] = { +/* QCAVSx */ + 0xa2, 0x8a, 0x2e, 0xdf, 0x58, 0x02, 0x56, 0x68, 0xf7, 0x24, 0xaa, 0xf8, + 0x3a, 0x50, 0x95, 0x6b, 0x7a, 0xc1, 0xcf, 0xbb, 0xff, 0x79, 0xb0, 0x8c, + 0x3b, 0xf8, 0x7d, 0xfd, 0x28, 0x28, 0xd7, 0x67 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_68_public_y[] = { +/* QCAVSy */ + 0xdf, 0xa7, 0xbf, 0xff, 0xd4, 0xc7, 0x66, 0xb8, 0x6a, 0xbe, 0xaf, 0x5c, + 0x99, 0xb6, 0xe5, 0x0c, 0xb9, 0xcc, 0xc9, 0xd9, 0xd0, 0x0b, 0x7f, 0xfc, + 0x78, 0x04, 0xb0, 0x49, 0x1b, 0x67, 0xbc, 0x03 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_68_private[] = { +/* dIUT */ + 0x13, 0x31, 0xf6, 0xd8, 0x74, 0xa4, 0xed, 0x3b, 0xc4, 0xa2, 0xc6, 0xe9, + 0xc7, 0x43, 0x31, 0xd3, 0x03, 0x97, 0x96, 0x31, 0x4b, 0xee, 0xe3, 0xb7, + 0x15, 0x2f, 0xcd, 0xba, 0x55, 0x56, 0x30, 0x4e +}; +/* QIUTx = 59e1e101521046ad9cf1d082e9d2ec7dd22530cce064991f1e55c5bcf5fcb591 */ +/* QIUTy = 482f4f673176c8fdaa0bb6e59b15a3e47454e3a04297d3863c9338d98add1f37 */ +static const uint8_t nist_kas_ecc_cdh_testvector_68_out[] = { +/* ZIUT */ + 0x1a, 0xaa, 0xbe, 0x7e, 0xe6, 0xe4, 0xa6, 0xfa, 0x73, 0x22, 0x91, 0x20, + 0x24, 0x33, 0xa2, 0x37, 0xdf, 0x1b, 0x49, 0xbc, 0x53, 0x86, 0x6b, 0xfb, + 0xe0, 0x0d, 0xb9, 0x6a, 0x0f, 0x58, 0x22, 0x4f +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_69_public_x[] = { +/* QCAVSx */ + 0xa2, 0xef, 0x85, 0x7a, 0x08, 0x1f, 0x9d, 0x6e, 0xb2, 0x06, 0xa8, 0x1c, + 0x4c, 0xf7, 0x8a, 0x80, 0x2b, 0xdf, 0x59, 0x8a, 0xe3, 0x80, 0xc8, 0x88, + 0x6e, 0xcd, 0x85, 0xfd, 0xc1, 0xed, 0x76, 0x44 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_69_public_y[] = { +/* QCAVSy */ + 0x56, 0x3c, 0x4c, 0x20, 0x41, 0x9f, 0x07, 0xbc, 0x17, 0xd0, 0x53, 0x9f, + 0xad, 0xe1, 0x85, 0x5e, 0x34, 0x83, 0x95, 0x15, 0xb8, 0x92, 0xc0, 0xf5, + 0xd2, 0x65, 0x61, 0xf9, 0x7f, 0xa0, 0x4d, 0x1a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_69_private[] = { +/* dIUT */ + 0xdd, 0x5e, 0x9f, 0x70, 0xae, 0x74, 0x00, 0x73, 0xca, 0x02, 0x04, 0xdf, + 0x60, 0x76, 0x3f, 0xb6, 0x03, 0x6c, 0x45, 0x70, 0x9b, 0xf4, 0xa7, 0xbb, + 0x4e, 0x67, 0x14, 0x12, 0xfa, 0xd6, 0x5d, 0xa3 +}; +/* QIUTx = 30b9db2e2e977bcdc98cb87dd736cbd8e78552121925cf16e1933657c2fb2314 */ +/* QIUTy = 6a45028800b81291bce5c2e1fed7ded650620ebbe6050c6f3a7f0dfb4673ab5c */ +static const uint8_t nist_kas_ecc_cdh_testvector_69_out[] = { +/* ZIUT */ + 0x43, 0x0e, 0x6a, 0x4f, 0xba, 0x44, 0x49, 0xd7, 0x00, 0xd2, 0x73, 0x3e, + 0x55, 0x7f, 0x66, 0xa3, 0xbf, 0x3d, 0x50, 0x51, 0x7c, 0x12, 0x71, 0xb1, + 0xdd, 0xae, 0x11, 0x61, 0xb7, 0xac, 0x79, 0x8c +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_70_public_x[] = { +/* QCAVSx */ + 0xcc, 0xd8, 0xa2, 0xd8, 0x6b, 0xc9, 0x2f, 0x2e, 0x01, 0xbc, 0xe4, 0xd6, + 0x92, 0x2c, 0xf7, 0xfe, 0x16, 0x26, 0xae, 0xd0, 0x44, 0x68, 0x5e, 0x95, + 0xe2, 0xee, 0xbd, 0x46, 0x45, 0x05, 0xf0, 0x1f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_70_public_y[] = { +/* QCAVSy */ + 0xe9, 0xdd, 0xd5, 0x83, 0xa9, 0x63, 0x5a, 0x66, 0x77, 0x77, 0xd5, 0xb8, + 0xa8, 0xf3, 0x1b, 0x0f, 0x79, 0xeb, 0xa1, 0x2c, 0x75, 0x02, 0x34, 0x10, + 0xb5, 0x4b, 0x85, 0x67, 0xdd, 0xdc, 0x0f, 0x38 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_70_private[] = { +/* dIUT */ + 0x5a, 0xe0, 0x26, 0xcf, 0xc0, 0x60, 0xd5, 0x56, 0x00, 0x71, 0x7e, 0x55, + 0xb8, 0xa1, 0x2e, 0x11, 0x6d, 0x1d, 0x0d, 0xf3, 0x4a, 0xf8, 0x31, 0x97, + 0x90, 0x57, 0x60, 0x7c, 0x2d, 0x9c, 0x2f, 0x76 +}; +/* QIUTx = 46c9ebd1a4a3c8c0b6d572b5dcfba12467603208a9cb5d2acfbb733c40cf6391 */ +/* QIUTy = 46c913a27d044185d38b467ace011e04d4d9bbbb8cb9ae25fa92aaf15a595e86 */ +static const uint8_t nist_kas_ecc_cdh_testvector_70_out[] = { +/* ZIUT */ + 0x1c, 0xe9, 0xe6, 0x74, 0x05, 0x29, 0x49, 0x9f, 0x98, 0xd1, 0xf1, 0xd7, + 0x13, 0x29, 0x14, 0x7a, 0x33, 0xdf, 0x1d, 0x05, 0xe4, 0x76, 0x5b, 0x53, + 0x9b, 0x11, 0xcf, 0x61, 0x5d, 0x69, 0x74, 0xd3 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_71_public_x[] = { +/* QCAVSx */ + 0xc1, 0x88, 0xff, 0xc8, 0x94, 0x7f, 0x73, 0x01, 0xfb, 0x7b, 0x53, 0xe3, + 0x67, 0x46, 0x09, 0x7c, 0x21, 0x34, 0xbf, 0x9c, 0xc9, 0x81, 0xba, 0x74, + 0xb4, 0xe9, 0xc4, 0x36, 0x1f, 0x59, 0x5e, 0x4e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_71_public_y[] = { +/* QCAVSy */ + 0xbf, 0x7d, 0x2f, 0x20, 0x56, 0xe7, 0x24, 0x21, 0xef, 0x39, 0x3f, 0x0c, + 0x0f, 0x2b, 0x0e, 0x00, 0x13, 0x0e, 0x3c, 0xac, 0x4a, 0xbb, 0xcc, 0x00, + 0x28, 0x61, 0x68, 0xe8, 0x5e, 0xc5, 0x50, 0x51 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_71_private[] = { +/* dIUT */ + 0xb6, 0x01, 0xac, 0x42, 0x5d, 0x5d, 0xbf, 0x9e, 0x17, 0x35, 0xc5, 0xe2, + 0xd5, 0xbd, 0xb7, 0x9c, 0xa9, 0x8b, 0x3d, 0x5b, 0xe4, 0xa2, 0xcf, 0xd6, + 0xf2, 0x27, 0x3f, 0x15, 0x0e, 0x06, 0x4d, 0x9d +}; +/* QIUTx = 7c9e950841d26c8dde8994398b8f5d475a022bc63de7773fcf8d552e01f1ba0a */ +/* QIUTy = cc42b9885c9b3bee0f8d8c57d3a8f6355016c019c4062fa22cff2f209b5cc2e1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_71_out[] = { +/* ZIUT */ + 0x46, 0x90, 0xe3, 0x74, 0x3c, 0x07, 0xd6, 0x43, 0xf1, 0xbc, 0x18, 0x36, + 0x36, 0xab, 0x2a, 0x9c, 0xb9, 0x36, 0xa6, 0x0a, 0x80, 0x21, 0x13, 0xc4, + 0x9b, 0xb1, 0xb3, 0xf2, 0xd0, 0x66, 0x16, 0x60 +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_72_public_x[] = { +/* QCAVSx */ + 0x31, 0x7e, 0x10, 0x20, 0xff, 0x53, 0xfc, 0xce, 0xf1, 0x8b, 0xf4, 0x7b, + 0xb7, 0xf2, 0xdd, 0x77, 0x07, 0xfb, 0x7b, 0x7a, 0x75, 0x78, 0xe0, 0x4f, + 0x35, 0xb3, 0xbe, 0xed, 0x22, 0x2a, 0x0e, 0xb6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_72_public_y[] = { +/* QCAVSy */ + 0x09, 0x42, 0x0c, 0xe5, 0xa1, 0x9d, 0x77, 0xc6, 0xfe, 0x1e, 0xe5, 0x87, + 0xe6, 0xa4, 0x9f, 0xba, 0xf8, 0xf2, 0x80, 0xe8, 0xdf, 0x03, 0x3d, 0x75, + 0x40, 0x33, 0x02, 0xe5, 0xa2, 0x7d, 0xb2, 0xae +}; +static const uint8_t nist_kas_ecc_cdh_testvector_72_private[] = { +/* dIUT */ + 0xfe, 0xfb, 0x1d, 0xda, 0x18, 0x45, 0x31, 0x2b, 0x5f, 0xce, 0x6b, 0x81, + 0xb2, 0xbe, 0x20, 0x5a, 0xf2, 0xf3, 0xa2, 0x74, 0xf5, 0xa2, 0x12, 0xf6, + 0x6c, 0x0d, 0x9f, 0xc3, 0x3d, 0x7a, 0xe5, 0x35 +}; +/* QIUTx = 38b54db85500cb20c61056edd3d88b6a9dc26780a047f213a6e1b900f76596eb */ +/* QIUTy = 6387e4e5781571e4eb8ae62991a33b5dc33301c5bc7e125d53794a39160d8fd0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_72_out[] = { +/* ZIUT */ + 0x30, 0xc2, 0x26, 0x1b, 0xd0, 0x00, 0x4e, 0x61, 0xfe, 0xda, 0x2c, 0x16, + 0xaa, 0x5e, 0x21, 0xff, 0xa8, 0xd7, 0xe7, 0xf7, 0xdb, 0xf6, 0xec, 0x37, + 0x9a, 0x43, 0xb4, 0x8e, 0x4b, 0x36, 0xae, 0xb0 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_73_public_x[] = { +/* QCAVSx */ + 0x45, 0xfb, 0x02, 0xb2, 0xce, 0xb9, 0xd7, 0xc7, 0x9d, 0x9c, 0x2f, 0xa9, + 0x3e, 0x9c, 0x79, 0x67, 0xc2, 0xfa, 0x4d, 0xf5, 0x78, 0x9f, 0x96, 0x40, + 0xb2, 0x42, 0x64, 0xb1, 0xe5, 0x24, 0xfc, 0xb1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_73_public_y[] = { +/* QCAVSy */ + 0x5c, 0x6e, 0x8e, 0xcf, 0x1f, 0x7d, 0x30, 0x23, 0x89, 0x3b, 0x7b, 0x1c, + 0xa1, 0xe4, 0xd1, 0x78, 0x97, 0x2e, 0xe2, 0xa2, 0x30, 0x75, 0x7d, 0xdc, + 0x56, 0x4f, 0xfe, 0x37, 0xf5, 0xc5, 0xa3, 0x21 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_73_private[] = { +/* dIUT */ + 0x33, 0x4a, 0xe0, 0xc4, 0x69, 0x3d, 0x23, 0x93, 0x5a, 0x7e, 0x8e, 0x04, + 0x3e, 0xbb, 0xde, 0x21, 0xe1, 0x68, 0xa7, 0xcb, 0xa3, 0xfa, 0x50, 0x7c, + 0x9b, 0xe4, 0x1d, 0x76, 0x81, 0xe0, 0x49, 0xce +}; +/* QIUTx = 3f2bf1589abf3047bf3e54ac9a95379bff95f8f55405f64eca36a7eebe8ffca7 */ +/* QIUTy = 5212a94e66c5ae9a8991872f66a72723d80ec5b2e925745c456f5371943b3a06 */ +static const uint8_t nist_kas_ecc_cdh_testvector_73_out[] = { +/* ZIUT */ + 0x2a, 0xda, 0xe4, 0xa1, 0x38, 0xa2, 0x39, 0xdc, 0xd9, 0x3c, 0x24, 0x3a, + 0x38, 0x03, 0xc3, 0xe4, 0xcf, 0x96, 0xe3, 0x7f, 0xe1, 0x4e, 0x6a, 0x9b, + 0x71, 0x7b, 0xe9, 0x59, 0x99, 0x59, 0xb1, 0x1c +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_74_public_x[] = { +/* QCAVSx */ + 0xa1, 0x9e, 0xf7, 0xbf, 0xf9, 0x8a, 0xda, 0x78, 0x18, 0x42, 0xfb, 0xfc, + 0x51, 0xa4, 0x7a, 0xff, 0x39, 0xb5, 0x93, 0x5a, 0x1c, 0x7d, 0x96, 0x25, + 0xc8, 0xd3, 0x23, 0xd5, 0x11, 0xc9, 0x2d, 0xe6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_74_public_y[] = { +/* QCAVSy */ + 0xe9, 0xc1, 0x84, 0xdf, 0x75, 0xc9, 0x55, 0xe0, 0x2e, 0x02, 0xe4, 0x00, + 0xff, 0xe4, 0x5f, 0x78, 0xf3, 0x39, 0xe1, 0xaf, 0xe6, 0xd0, 0x56, 0xfb, + 0x32, 0x45, 0xf4, 0x70, 0x0c, 0xe6, 0x06, 0xef +}; +static const uint8_t nist_kas_ecc_cdh_testvector_74_private[] = { +/* dIUT */ + 0x2c, 0x4b, 0xde, 0x40, 0x21, 0x4f, 0xcc, 0x3b, 0xfc, 0x47, 0xd4, 0xcf, + 0x43, 0x4b, 0x62, 0x9a, 0xcb, 0xe9, 0x15, 0x7f, 0x8f, 0xd0, 0x28, 0x25, + 0x40, 0x33, 0x1d, 0xe7, 0x94, 0x2c, 0xf0, 0x9d +}; +/* QIUTx = 29c0807f10cbc42fb45c9989da50681eead716daa7b9e91fd32e062f5eb92ca0 */ +/* QIUTy = ff1d6d1955d7376b2da24fe1163a271659136341bc2eb1195fc706dc62e7f34d */ +static const uint8_t nist_kas_ecc_cdh_testvector_74_out[] = { +/* ZIUT */ + 0x2e, 0x27, 0x7e, 0xc3, 0x0f, 0x5e, 0xa0, 0x7d, 0x6c, 0xe5, 0x13, 0x14, + 0x9b, 0x94, 0x79, 0xb9, 0x6e, 0x07, 0xf4, 0xb6, 0x91, 0x3b, 0x1b, 0x5c, + 0x11, 0x30, 0x5c, 0x14, 0x44, 0xa1, 0xbc, 0x0b +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_75_public_x[] = { +/* QCAVSx */ + 0x35, 0x6c, 0x5a, 0x44, 0x4c, 0x04, 0x9a, 0x52, 0xfe, 0xe0, 0xad, 0xeb, + 0x7e, 0x5d, 0x82, 0xae, 0x5a, 0xa8, 0x30, 0x30, 0xbf, 0xff, 0x31, 0xbb, + 0xf8, 0xce, 0x20, 0x96, 0xcf, 0x16, 0x1c, 0x4b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_75_public_y[] = { +/* QCAVSy */ + 0x57, 0xd1, 0x28, 0xde, 0x8b, 0x2a, 0x57, 0xa0, 0x94, 0xd1, 0xa0, 0x01, + 0xe5, 0x72, 0x17, 0x3f, 0x96, 0xe8, 0x86, 0x6a, 0xe3, 0x52, 0xbf, 0x29, + 0xcd, 0xda, 0xf9, 0x2f, 0xc8, 0x5b, 0x2f, 0x92 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_75_private[] = { +/* dIUT */ + 0x85, 0xa2, 0x68, 0xf9, 0xd7, 0x77, 0x2f, 0x99, 0x0c, 0x36, 0xb4, 0x2b, + 0x0a, 0x33, 0x1a, 0xdc, 0x92, 0xb5, 0x94, 0x1d, 0xe0, 0xb8, 0x62, 0xd5, + 0xd8, 0x9a, 0x34, 0x7c, 0xbf, 0x8f, 0xaa, 0xb0 +}; +/* QIUTx = 9cf4b98581ca1779453cc816ff28b4100af56cf1bf2e5bc312d83b6b1b21d333 */ +/* QIUTy = 7a5504fcac5231a0d12d658218284868229c844a04a3450d6c7381abe080bf3b */ +static const uint8_t nist_kas_ecc_cdh_testvector_75_out[] = { +/* ZIUT */ + 0x1e, 0x51, 0x37, 0x3b, 0xd2, 0xc6, 0x04, 0x4c, 0x12, 0x9c, 0x43, 0x6e, + 0x74, 0x2a, 0x55, 0xbe, 0x2a, 0x66, 0x8a, 0x85, 0xae, 0x08, 0x44, 0x1b, + 0x67, 0x56, 0x44, 0x5d, 0xf5, 0x49, 0x38, 0x57 +}; +/* [P-384] */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_76_public_x[] = { +/* QCAVSx */ + 0xa7, 0xc7, 0x6b, 0x97, 0x0c, 0x3b, 0x5f, 0xe8, 0xb0, 0x5d, 0x28, 0x38, + 0xae, 0x04, 0xab, 0x47, 0x69, 0x7b, 0x9e, 0xaf, 0x52, 0xe7, 0x64, 0x59, + 0x2e, 0xfd, 0xa2, 0x7f, 0xe7, 0x51, 0x32, 0x72, 0x73, 0x44, 0x66, 0xb4, + 0x00, 0x09, 0x1a, 0xdb, 0xf2, 0xd6, 0x8c, 0x58, 0xe0, 0xc5, 0x00, 0x66 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_76_public_y[] = { +/* QCAVSy */ + 0xac, 0x68, 0xf1, 0x9f, 0x2e, 0x1c, 0xb8, 0x79, 0xae, 0xd4, 0x3a, 0x99, + 0x69, 0xb9, 0x1a, 0x08, 0x39, 0xc4, 0xc3, 0x8a, 0x49, 0x74, 0x9b, 0x66, + 0x1e, 0xfe, 0xdf, 0x24, 0x34, 0x51, 0x91, 0x5e, 0xd0, 0x90, 0x5a, 0x32, + 0xb0, 0x60, 0x99, 0x2b, 0x46, 0x8c, 0x64, 0x76, 0x6f, 0xc8, 0x43, 0x7a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_76_private[] = { +/* dIUT */ + 0x3c, 0xc3, 0x12, 0x2a, 0x68, 0xf0, 0xd9, 0x50, 0x27, 0xad, 0x38, 0xc0, + 0x67, 0x91, 0x6b, 0xa0, 0xeb, 0x8c, 0x38, 0x89, 0x4d, 0x22, 0xe1, 0xb1, + 0x56, 0x18, 0xb6, 0x81, 0x8a, 0x66, 0x17, 0x74, 0xad, 0x46, 0x3b, 0x20, + 0x5d, 0xa8, 0x8c, 0xf6, 0x99, 0xab, 0x4d, 0x43, 0xc9, 0xcf, 0x98, 0xa1 +}; +/* QIUTx = 9803807f2f6d2fd966cdd0290bd410c0190352fbec7ff6247de1302df86f25d34fe4a97bef60cff548355c015dbb3e5f */ +/* QIUTy = ba26ca69ec2f5b5d9dad20cc9da711383a9dbe34ea3fa5a2af75b46502629ad54dd8b7d73a8abb06a3a3be47d650cc99 */ +static const uint8_t nist_kas_ecc_cdh_testvector_76_out[] = { +/* ZIUT */ + 0x5f, 0x9d, 0x29, 0xdc, 0x5e, 0x31, 0xa1, 0x63, 0x06, 0x03, 0x56, 0x21, + 0x36, 0x69, 0xc8, 0xce, 0x13, 0x2e, 0x22, 0xf5, 0x7c, 0x9a, 0x04, 0xf4, + 0x0b, 0xa7, 0xfc, 0xea, 0xd4, 0x93, 0xb4, 0x57, 0xe5, 0x62, 0x1e, 0x76, + 0x6c, 0x40, 0xa2, 0xe3, 0xd4, 0xd6, 0xa0, 0x4b, 0x25, 0xe5, 0x33, 0xf1 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_77_public_x[] = { +/* QCAVSx */ + 0x30, 0xf4, 0x3f, 0xcf, 0x2b, 0x6b, 0x00, 0xde, 0x53, 0xf6, 0x24, 0xf1, + 0x54, 0x30, 0x90, 0x68, 0x18, 0x39, 0x71, 0x7d, 0x53, 0xc7, 0xc9, 0x55, + 0xd1, 0xd6, 0x9e, 0xfa, 0xf0, 0x34, 0x9b, 0x73, 0x63, 0xac, 0xb4, 0x47, + 0x24, 0x01, 0x01, 0xcb, 0xb3, 0xaf, 0x66, 0x41, 0xce, 0x4b, 0x88, 0xe0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_77_public_y[] = { +/* QCAVSy */ + 0x25, 0xe4, 0x6c, 0x0c, 0x54, 0xf0, 0x16, 0x2a, 0x77, 0xef, 0xcc, 0x27, + 0xb6, 0xea, 0x79, 0x20, 0x02, 0xae, 0x2b, 0xa8, 0x27, 0x14, 0x29, 0x9c, + 0x86, 0x08, 0x57, 0xa6, 0x81, 0x53, 0xab, 0x62, 0xe5, 0x25, 0xec, 0x05, + 0x30, 0xd8, 0x1b, 0x5a, 0xa1, 0x58, 0x97, 0x98, 0x1e, 0x85, 0x87, 0x57 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_77_private[] = { +/* dIUT */ + 0x92, 0x86, 0x0c, 0x21, 0xbd, 0xe0, 0x61, 0x65, 0xf8, 0xe9, 0x00, 0xc6, + 0x87, 0xf8, 0xef, 0x0a, 0x05, 0xd1, 0x4f, 0x29, 0x0b, 0x3f, 0x07, 0xd8, + 0xb3, 0xa8, 0xcc, 0x64, 0x04, 0x36, 0x6e, 0x5d, 0x51, 0x19, 0xcd, 0x6d, + 0x03, 0xfb, 0x12, 0xdc, 0x58, 0xe8, 0x9f, 0x13, 0xdf, 0x9c, 0xd7, 0x83 +}; +/* QIUTx = ea4018f5a307c379180bf6a62fd2ceceebeeb7d4df063a66fb838aa35243419791f7e2c9d4803c9319aa0eb03c416b66 */ +/* QIUTy = 68835a91484f05ef028284df6436fb88ffebabcdd69ab0133e6735a1bcfb37203d10d340a8328a7b68770ca75878a1a6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_77_out[] = { +/* ZIUT */ + 0xa2, 0x37, 0x42, 0xa2, 0xc2, 0x67, 0xd7, 0x42, 0x5f, 0xda, 0x94, 0xb9, + 0x3f, 0x93, 0xbb, 0xcc, 0x24, 0x79, 0x1a, 0xc5, 0x1c, 0xd8, 0xfd, 0x50, + 0x1a, 0x23, 0x8d, 0x40, 0x81, 0x2f, 0x4c, 0xbf, 0xc5, 0x9a, 0xac, 0x95, + 0x20, 0xd7, 0x58, 0xcf, 0x78, 0x9c, 0x76, 0x30, 0x0c, 0x69, 0xd2, 0xff +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_78_public_x[] = { +/* QCAVSx */ + 0x1a, 0xef, 0xbf, 0xa2, 0xc6, 0xc8, 0xc8, 0x55, 0xa1, 0xa2, 0x16, 0x77, + 0x45, 0x50, 0xb7, 0x9a, 0x24, 0xcd, 0xa3, 0x76, 0x07, 0xbb, 0x1f, 0x7c, + 0xc9, 0x06, 0x65, 0x0e, 0xe4, 0xb3, 0x81, 0x6d, 0x68, 0xf6, 0xa9, 0xc7, + 0x5d, 0xa6, 0xe4, 0x24, 0x2c, 0xeb, 0xfb, 0x66, 0x52, 0xf6, 0x51, 0x80 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_78_public_y[] = { +/* QCAVSy */ + 0x41, 0x9d, 0x28, 0xb7, 0x23, 0xeb, 0xad, 0xb7, 0x65, 0x8f, 0xce, 0xbb, + 0x9a, 0xd9, 0xb7, 0xad, 0xea, 0x67, 0x4f, 0x1d, 0xa3, 0xdc, 0x6b, 0x63, + 0x97, 0xb5, 0x5d, 0xa0, 0xf6, 0x1a, 0x3e, 0xdd, 0xac, 0xb4, 0xac, 0xdb, + 0x14, 0x44, 0x1c, 0xb2, 0x14, 0xb0, 0x4a, 0x08, 0x44, 0xc0, 0x2f, 0xa3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_78_private[] = { +/* dIUT */ + 0x12, 0xcf, 0x6a, 0x22, 0x3a, 0x72, 0x35, 0x25, 0x43, 0x83, 0x0f, 0x3f, + 0x18, 0x53, 0x0d, 0x5c, 0xb3, 0x7f, 0x26, 0x88, 0x0a, 0x0b, 0x29, 0x44, + 0x82, 0xc8, 0xa8, 0xef, 0x8a, 0xfa, 0xd0, 0x9a, 0xa7, 0x8b, 0x7d, 0xc2, + 0xf2, 0x78, 0x9a, 0x78, 0xc6, 0x6a, 0xf5, 0xd1, 0xcc, 0x55, 0x38, 0x53 +}; +/* QIUTx = fcfcea085e8cf74d0dced1620ba8423694f903a219bbf901b0b59d6ac81baad316a242ba32bde85cb248119b852fab66 */ +/* QIUTy = 972e3c68c7ab402c5836f2a16ed451a33120a7750a6039f3ff15388ee622b7065f7122bf6d51aefbc29b37b03404581b */ +static const uint8_t nist_kas_ecc_cdh_testvector_78_out[] = { +/* ZIUT */ + 0x3d, 0x2e, 0x64, 0x0f, 0x35, 0x08, 0x05, 0xee, 0xd1, 0xff, 0x43, 0xb4, + 0x0a, 0x72, 0xb2, 0xab, 0xed, 0x0a, 0x51, 0x8b, 0xce, 0xbe, 0x8f, 0x2d, + 0x15, 0xb1, 0x11, 0xb6, 0x77, 0x32, 0x23, 0xda, 0x3c, 0x34, 0x89, 0x12, + 0x1d, 0xb1, 0x73, 0xd4, 0x14, 0xb5, 0xbd, 0x5a, 0xd7, 0x15, 0x34, 0x35 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_79_public_x[] = { +/* QCAVSx */ + 0x8b, 0xc0, 0x89, 0x32, 0x6e, 0xc5, 0x5b, 0x9c, 0xf5, 0x9b, 0x34, 0xf0, + 0xeb, 0x75, 0x4d, 0x93, 0x59, 0x6c, 0xa2, 0x90, 0xfc, 0xb3, 0x44, 0x4c, + 0x83, 0xd4, 0xde, 0x3a, 0x56, 0x07, 0x03, 0x7e, 0xc3, 0x97, 0x68, 0x3f, + 0x8c, 0xef, 0x07, 0xea, 0xb2, 0xfe, 0x35, 0x7e, 0xae, 0x36, 0xc4, 0x49 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_79_public_y[] = { +/* QCAVSy */ + 0xd9, 0xd1, 0x6c, 0xe8, 0xac, 0x85, 0xb3, 0xf1, 0xe9, 0x45, 0x68, 0x52, + 0x1a, 0xae, 0x53, 0x4e, 0x67, 0x13, 0x9e, 0x31, 0x0e, 0xc7, 0x26, 0x93, + 0x52, 0x6a, 0xa2, 0xe9, 0x27, 0xb5, 0xb3, 0x22, 0xc9, 0x5a, 0x1a, 0x03, + 0x3c, 0x22, 0x9c, 0xb6, 0x77, 0x0c, 0x95, 0x7c, 0xd3, 0x14, 0x8d, 0xd7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_79_private[] = { +/* dIUT */ + 0x8d, 0xd4, 0x80, 0x63, 0xa3, 0xa0, 0x58, 0xc3, 0x34, 0xb5, 0xcc, 0x7a, + 0x4c, 0xe0, 0x7d, 0x02, 0xe5, 0xee, 0x6d, 0x8f, 0x1f, 0x3c, 0x51, 0xa1, + 0x60, 0x09, 0x62, 0xcb, 0xab, 0x46, 0x26, 0x90, 0xae, 0x3c, 0xd9, 0x74, + 0xfb, 0x39, 0xe4, 0x0b, 0x0e, 0x84, 0x3d, 0xaa, 0x0f, 0xd3, 0x2d, 0xe1 +}; +/* QIUTx = e38c9846248123c3421861ea4d32669a7b5c3c08376ad28104399494c84ff5efa3894adb2c6cbe8c3c913ef2eec5bd3c */ +/* QIUTy = 9fa84024a1028796df84021f7b6c9d02f0f4bd1a612a03cbf75a0beea43fef8ae84b48c60172aadf09c1ad016d0bf3ce */ +static const uint8_t nist_kas_ecc_cdh_testvector_79_out[] = { +/* ZIUT */ + 0x6a, 0x42, 0xcf, 0xc3, 0x92, 0xab, 0xa0, 0xbf, 0xd3, 0xd1, 0x7b, 0x7c, + 0xcf, 0x06, 0x2b, 0x91, 0xfc, 0x09, 0xbb, 0xf3, 0x41, 0x76, 0x12, 0xd0, + 0x2a, 0x90, 0xbd, 0xde, 0x62, 0xae, 0x40, 0xc5, 0x4b, 0xb2, 0xe5, 0x6e, + 0x16, 0x7d, 0x6b, 0x70, 0xdb, 0x67, 0x00, 0x97, 0xeb, 0x8d, 0xb8, 0x54 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_80_public_x[] = { +/* QCAVSx */ + 0xeb, 0x95, 0x2e, 0x2d, 0x9a, 0xc0, 0xc2, 0x0c, 0x6c, 0xc4, 0x8f, 0xb2, + 0x25, 0xc2, 0xad, 0x15, 0x4f, 0x53, 0xc8, 0x75, 0x0b, 0x00, 0x3f, 0xd3, + 0xb4, 0xed, 0x8e, 0xd1, 0xdc, 0x0d, 0xef, 0xac, 0x61, 0xbc, 0xdd, 0xe0, + 0x2a, 0x2b, 0xcf, 0xee, 0x70, 0x67, 0xd7, 0x5d, 0x34, 0x2e, 0xd2, 0xb0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_80_public_y[] = { +/* QCAVSy */ + 0xf1, 0x82, 0x82, 0x05, 0xba, 0xec, 0xe8, 0x2d, 0x1b, 0x26, 0x7d, 0x0d, + 0x7f, 0xf2, 0xf9, 0xc9, 0xe1, 0x5b, 0x69, 0xa7, 0x2d, 0xf4, 0x70, 0x58, + 0xa9, 0x7f, 0x38, 0x91, 0x00, 0x5d, 0x1f, 0xb3, 0x88, 0x58, 0xf5, 0x60, + 0x3d, 0xe8, 0x40, 0xe5, 0x91, 0xdf, 0xa4, 0xf6, 0xe7, 0xd4, 0x89, 0xe1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_80_private[] = { +/* dIUT */ + 0x84, 0xec, 0xe6, 0xcc, 0x34, 0x29, 0x30, 0x9b, 0xd5, 0xb2, 0x3e, 0x95, + 0x97, 0x93, 0xed, 0x2b, 0x11, 0x1e, 0xc5, 0xcb, 0x43, 0xb6, 0xc1, 0x80, + 0x85, 0xfc, 0xae, 0xa9, 0xef, 0xa0, 0x68, 0x5d, 0x98, 0xa6, 0x26, 0x2e, + 0xe0, 0xd3, 0x30, 0xee, 0x25, 0x0b, 0xc8, 0xa6, 0x7d, 0x0e, 0x73, 0x3f +}; +/* QIUTx = 3222063a2997b302ee60ee1961108ff4c7acf1c0ef1d5fb0d164b84bce71c431705cb9aea9a45f5d73806655a058bee3 */ +/* QIUTy = e61fa9e7fbe7cd43abf99596a3d3a039e99fa9dc93b0bdd9cad81966d17eeaf557068afa7c78466bb5b22032d1100fa6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_80_out[] = { +/* ZIUT */ + 0xce, 0x7b, 0xa4, 0x54, 0xd4, 0x41, 0x27, 0x29, 0xa3, 0x2b, 0xb8, 0x33, + 0xa2, 0xd1, 0xfd, 0x2a, 0xe6, 0x12, 0xd4, 0x66, 0x7c, 0x3a, 0x90, 0x0e, + 0x06, 0x92, 0x14, 0x81, 0x86, 0x13, 0x44, 0x7d, 0xf8, 0xc6, 0x11, 0xde, + 0x66, 0xda, 0x20, 0x0d, 0xb7, 0xc3, 0x75, 0xcf, 0x91, 0x3e, 0x44, 0x05 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_81_public_x[] = { +/* QCAVSx */ + 0x44, 0x1d, 0x02, 0x9e, 0x24, 0x4e, 0xb7, 0x16, 0x8d, 0x64, 0x7d, 0x4d, + 0xf5, 0x0d, 0xb5, 0xf4, 0xe4, 0x97, 0x4a, 0xb3, 0xfd, 0xaf, 0x02, 0x2a, + 0xff, 0x05, 0x8b, 0x36, 0x95, 0xd0, 0xb8, 0xc8, 0x14, 0xcc, 0x88, 0xda, + 0x62, 0x85, 0xdc, 0x6d, 0xf1, 0xac, 0x55, 0xc5, 0x53, 0x88, 0x50, 0x03 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_81_public_y[] = { +/* QCAVSy */ + 0xe8, 0x02, 0x5a, 0xc2, 0x3a, 0x41, 0xd4, 0xb1, 0xea, 0x2a, 0xa4, 0x6c, + 0x50, 0xc6, 0xe4, 0x79, 0x94, 0x6b, 0x59, 0xb6, 0xd7, 0x64, 0x97, 0xcd, + 0x92, 0x49, 0x97, 0x7e, 0x0b, 0xfe, 0x4a, 0x62, 0x62, 0x62, 0x2f, 0x13, + 0xd4, 0x2a, 0x3c, 0x43, 0xd6, 0x6b, 0xdb, 0xb3, 0x04, 0x03, 0xc3, 0x45 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_81_private[] = { +/* dIUT */ + 0x68, 0xfc, 0xe2, 0x12, 0x1d, 0xc3, 0xa1, 0xe3, 0x7b, 0x10, 0xf1, 0xdd, + 0xe3, 0x09, 0xf9, 0xe2, 0xe1, 0x8f, 0xac, 0x47, 0xcd, 0x17, 0x70, 0x95, + 0x14, 0x51, 0xc3, 0x48, 0x4c, 0xdb, 0x77, 0xcb, 0x13, 0x6d, 0x00, 0xe7, + 0x31, 0x26, 0x05, 0x97, 0xcc, 0x28, 0x59, 0x60, 0x1c, 0x01, 0xa2, 0x5b +}; +/* QIUTx = 868be0e694841830e424d913d8e7d86b84ee1021d82b0ecf523f09fe89a76c0c95c49f2dfbcf829c1e39709d55efbb3b */ +/* QIUTy = 9195eb183675b40fd92f51f37713317e4a9b4f715c8ab22e0773b1bc71d3a219f05b8116074658ee86b52e36f3897116 */ +static const uint8_t nist_kas_ecc_cdh_testvector_81_out[] = { +/* ZIUT */ + 0xba, 0x69, 0xf0, 0xac, 0xdf, 0x3e, 0x1c, 0xa9, 0x5c, 0xaa, 0xac, 0x4e, + 0xca, 0xf4, 0x75, 0xbb, 0xe5, 0x1b, 0x54, 0x77, 0x7e, 0xfc, 0xe0, 0x1c, + 0xa3, 0x81, 0xf4, 0x53, 0x70, 0xe4, 0x86, 0xfe, 0x87, 0xf9, 0xf4, 0x19, + 0xb1, 0x50, 0xc6, 0x1e, 0x32, 0x9a, 0x28, 0x6d, 0x1a, 0xa2, 0x65, 0xec +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_82_public_x[] = { +/* QCAVSx */ + 0x3d, 0x4e, 0x6b, 0xf0, 0x8a, 0x73, 0x40, 0x4a, 0xcc, 0xc1, 0x62, 0x98, + 0x73, 0x46, 0x8e, 0x42, 0x69, 0xe8, 0x2d, 0x90, 0xd8, 0x32, 0xe5, 0x8a, + 0xd7, 0x21, 0x42, 0x63, 0x9b, 0x5a, 0x05, 0x6a, 0xd8, 0xd3, 0x5c, 0x66, + 0xc6, 0x0e, 0x81, 0x49, 0xfa, 0xc0, 0xc7, 0x97, 0xbc, 0xeb, 0x7c, 0x2f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_82_public_y[] = { +/* QCAVSy */ + 0x9b, 0x03, 0x08, 0xdc, 0x7f, 0x0e, 0x6d, 0x29, 0xf8, 0xc2, 0x77, 0xac, + 0xbc, 0x65, 0xa2, 0x1e, 0x5a, 0xdb, 0x83, 0xd1, 0x1e, 0x68, 0x73, 0xbc, + 0x0a, 0x07, 0xfd, 0xa0, 0x99, 0x7f, 0x48, 0x25, 0x04, 0x60, 0x2f, 0x59, + 0xe1, 0x0b, 0xc5, 0xcb, 0x47, 0x6b, 0x83, 0xd0, 0xa4, 0xf7, 0x5e, 0x71 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_82_private[] = { +/* dIUT */ + 0xb1, 0x76, 0x4c, 0x54, 0x89, 0x7e, 0x7a, 0xae, 0x6d, 0xe9, 0xe7, 0x75, + 0x1f, 0x2f, 0x37, 0xde, 0x84, 0x92, 0x91, 0xf8, 0x8f, 0x0f, 0x91, 0x09, + 0x31, 0x55, 0xb8, 0x58, 0xd1, 0xcc, 0x32, 0xa3, 0xa8, 0x79, 0x80, 0xf7, + 0x06, 0xb8, 0x6c, 0xc8, 0x3f, 0x92, 0x7b, 0xdf, 0xdb, 0xea, 0xe0, 0xbd +}; +/* QIUTx = c371222feaa6770c6f3ea3e0dac9740def4fcf821378b7f91ff937c21e0470f70f3a31d5c6b2912195f10926942b48ae */ +/* QIUTy = 047d6b4d765123563f81116bc665b7b8cc6207830d805fd84da7cb805a65baa7c12fd592d1b5b5e3e65d9672a9ef7662 */ +static const uint8_t nist_kas_ecc_cdh_testvector_82_out[] = { +/* ZIUT */ + 0x1a, 0x66, 0x88, 0xee, 0x1d, 0x6e, 0x59, 0x86, 0x5d, 0x8e, 0x3a, 0xda, + 0x37, 0x78, 0x1d, 0x36, 0xbb, 0x0c, 0x27, 0x17, 0xee, 0xf9, 0x2e, 0x61, + 0x96, 0x4d, 0x39, 0x27, 0xcb, 0x76, 0x5c, 0x29, 0x65, 0xea, 0x80, 0xf7, + 0xf6, 0x3e, 0x58, 0xc3, 0x22, 0xba, 0x03, 0x97, 0xfa, 0xea, 0xf6, 0x2b +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_83_public_x[] = { +/* QCAVSx */ + 0xf5, 0xf6, 0xbe, 0xf1, 0xd1, 0x10, 0xda, 0x03, 0xbe, 0x00, 0x17, 0xea, + 0xc7, 0x60, 0xcc, 0x34, 0xb2, 0x4d, 0x09, 0x2f, 0x73, 0x6f, 0x23, 0x7b, + 0xc7, 0x05, 0x4b, 0x38, 0x65, 0x31, 0x2a, 0x81, 0x3b, 0xcb, 0x62, 0xd2, + 0x97, 0xfb, 0x10, 0xa4, 0xf7, 0xab, 0xf5, 0x47, 0x08, 0xfe, 0x2d, 0x3d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_83_public_y[] = { +/* QCAVSy */ + 0x06, 0xfd, 0xf8, 0xd7, 0xdc, 0x03, 0x2f, 0x4e, 0x10, 0x01, 0x0b, 0xf1, + 0x9c, 0xbf, 0x61, 0x59, 0x32, 0x12, 0x52, 0xff, 0x41, 0x5f, 0xb9, 0x19, + 0x20, 0xd4, 0x38, 0xf2, 0x4e, 0x67, 0xe6, 0x0c, 0x2e, 0xb0, 0x46, 0x32, + 0x04, 0x67, 0x9f, 0xa3, 0x56, 0xaf, 0x44, 0xce, 0xa9, 0xc9, 0xeb, 0xf5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_83_private[] = { +/* dIUT */ + 0xf0, 0xf7, 0xa9, 0x6e, 0x70, 0xd9, 0x8f, 0xd5, 0xa3, 0x0a, 0xd6, 0x40, + 0x6c, 0xf5, 0x6e, 0xb5, 0xb7, 0x2a, 0x51, 0x0e, 0x9f, 0x19, 0x2f, 0x50, + 0xe1, 0xf8, 0x45, 0x24, 0xdb, 0xf3, 0xd2, 0x43, 0x9f, 0x72, 0x87, 0xbb, + 0x36, 0xf5, 0xaa, 0x91, 0x2a, 0x79, 0xde, 0xaa, 0xb4, 0xad, 0xea, 0x82 +}; +/* QIUTx = 99c8c41cb1ab5e0854a346e4b08a537c1706a61553387c8d94943ab15196d40dbaa55b8210a77a5d00915f2c4ea69eab */ +/* QIUTy = 5531065bdcf17bfb3cb55a02e41a57c7f694c383ad289f900fbd656c2233a93c92e933e7a26f54cbb56f0ad875c51bb0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_83_out[] = { +/* ZIUT */ + 0xd0, 0x6a, 0x56, 0x8b, 0xf2, 0x33, 0x6b, 0x90, 0xcb, 0xac, 0x32, 0x51, + 0x61, 0xbe, 0x76, 0x95, 0xea, 0xcb, 0x22, 0x95, 0xf5, 0x99, 0x50, 0x0d, + 0x78, 0x7f, 0x07, 0x26, 0x12, 0xac, 0xa3, 0x13, 0xee, 0x5d, 0x87, 0x4f, + 0x80, 0x7d, 0xde, 0xf6, 0xc1, 0xf0, 0x23, 0xfe, 0x2b, 0x6e, 0x7c, 0xd0 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_84_public_x[] = { +/* QCAVSx */ + 0x7c, 0xde, 0xc7, 0x7e, 0x07, 0x37, 0xea, 0x37, 0xc6, 0x7b, 0x89, 0xb7, + 0x13, 0x7f, 0xe3, 0x88, 0x18, 0x01, 0x0f, 0x44, 0x64, 0x43, 0x8e, 0xe4, + 0xd1, 0xd3, 0x5a, 0x0c, 0x48, 0x8c, 0xad, 0x3f, 0xde, 0x2f, 0x37, 0xd0, + 0x08, 0x85, 0xd3, 0x6d, 0x3b, 0x79, 0x5b, 0x9f, 0x93, 0xd2, 0x3a, 0x67 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_84_public_y[] = { +/* QCAVSy */ + 0x28, 0xc4, 0x2e, 0xe8, 0xd6, 0x02, 0x7c, 0x56, 0xcf, 0x97, 0x9b, 0xa4, + 0xc2, 0x29, 0xfd, 0xb0, 0x1d, 0x23, 0x49, 0x44, 0xf8, 0xac, 0x43, 0x36, + 0x50, 0x11, 0x2c, 0x3c, 0xf0, 0xf0, 0x28, 0x44, 0xe8, 0x88, 0xa3, 0x56, + 0x9d, 0xfe, 0xf7, 0x82, 0x8a, 0x8a, 0x88, 0x45, 0x89, 0xaa, 0x05, 0x5e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_84_private[] = { +/* dIUT */ + 0x9e, 0xfb, 0x87, 0xdd, 0xc6, 0x1d, 0x43, 0xc4, 0x82, 0xba, 0x66, 0xe1, + 0xb1, 0x43, 0xae, 0xf6, 0x78, 0xfb, 0xd0, 0xd1, 0xbe, 0xbc, 0x20, 0x00, + 0x94, 0x1f, 0xab, 0xe6, 0x77, 0xfe, 0x5b, 0x70, 0x6b, 0xf7, 0x8f, 0xce, + 0x36, 0xd1, 0x00, 0xb1, 0x7c, 0xc7, 0x87, 0xea, 0xd7, 0x4b, 0xbc, 0xa2 +}; +/* QIUTx = 4c34efee8f0c95565d2065d1bbac2a2dd25ae964320eb6bccedc5f3a9b42a881a1afca1bb6b880584fa27b01c193cd92 */ +/* QIUTy = d8fb01dbf7cd0a3868c26b951f393c3c56c2858cee901f7793ff5d271925d13a41f8e52409f4eba1990f33acb0bac669 */ +static const uint8_t nist_kas_ecc_cdh_testvector_84_out[] = { +/* ZIUT */ + 0xbb, 0x3b, 0x1e, 0xda, 0x9c, 0x65, 0x60, 0xd8, 0x2f, 0xf5, 0xbe, 0xe4, + 0x03, 0x33, 0x9f, 0x1e, 0x80, 0x34, 0x23, 0x38, 0xa9, 0x91, 0x34, 0x48, + 0x53, 0xb5, 0x6b, 0x24, 0xf1, 0x09, 0xa4, 0xd9, 0x4b, 0x92, 0xf6, 0x54, + 0xf0, 0x42, 0x5e, 0xdd, 0x4c, 0x20, 0x59, 0x03, 0xd7, 0x58, 0x61, 0x04 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_85_public_x[] = { +/* QCAVSx */ + 0x8e, 0xee, 0xa3, 0xa3, 0x19, 0xc8, 0xdf, 0x99, 0xfb, 0xc2, 0x9c, 0xb5, + 0x5f, 0x24, 0x3a, 0x72, 0x0d, 0x95, 0x50, 0x95, 0x15, 0xee, 0x5c, 0xc5, + 0x87, 0xa5, 0xc5, 0xae, 0x22, 0xfb, 0xbd, 0x00, 0x9e, 0x62, 0x6d, 0xb3, + 0xe9, 0x11, 0xde, 0xf0, 0xb9, 0x9a, 0x4f, 0x7a, 0xe3, 0x04, 0xb1, 0xba +}; +static const uint8_t nist_kas_ecc_cdh_testvector_85_public_y[] = { +/* QCAVSy */ + 0x73, 0x87, 0x7d, 0xc9, 0x4d, 0xb9, 0xad, 0xdd, 0xc0, 0xd9, 0xa4, 0xb2, + 0x4e, 0x89, 0x76, 0xc2, 0x2d, 0x73, 0xc8, 0x44, 0x37, 0x0e, 0x1e, 0xe8, + 0x57, 0xf8, 0xd1, 0xb1, 0x29, 0xa3, 0xbd, 0x5f, 0x63, 0xf4, 0x0c, 0xaf, + 0x3b, 0xd0, 0x53, 0x3e, 0x38, 0xa5, 0xf5, 0x77, 0x70, 0x74, 0xff, 0x9e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_85_private[] = { +/* dIUT */ + 0xd7, 0x87, 0xa5, 0x7f, 0xde, 0x22, 0xec, 0x65, 0x6a, 0x0a, 0x52, 0x5c, + 0xf3, 0xc7, 0x38, 0xb3, 0x0d, 0x73, 0xaf, 0x61, 0xe7, 0x43, 0xea, 0x90, + 0x89, 0x3e, 0xcb, 0x2d, 0x7b, 0x62, 0x2a, 0xdd, 0x2f, 0x94, 0xee, 0x25, + 0xc2, 0x17, 0x14, 0x67, 0xaf, 0xb0, 0x93, 0xf3, 0xf8, 0x4d, 0x00, 0x18 +}; +/* QIUTx = 171546923b87b2cbbad664f01ce932bf09d6a6118168678446bfa9f0938608cb4667a98f4ec8ac1462285c2508f74862 */ +/* QIUTy = fa41cb4db68ae71f1f8a3e8939dc52c2dec61a83c983beb2a02baf29ec49278088882ed0cf56c74b5c173b552ccf63cf */ +static const uint8_t nist_kas_ecc_cdh_testvector_85_out[] = { +/* ZIUT */ + 0x1e, 0x97, 0xb6, 0x0a, 0xdd, 0x7c, 0xb3, 0x5c, 0x74, 0x03, 0xdd, 0x88, + 0x4c, 0x0a, 0x75, 0x79, 0x5b, 0x76, 0x83, 0xff, 0xf8, 0xb4, 0x9f, 0x9d, + 0x86, 0x72, 0xa8, 0x20, 0x6b, 0xfd, 0xcf, 0x0a, 0x10, 0x6b, 0x87, 0x68, + 0xf9, 0x83, 0x25, 0x8c, 0x74, 0x16, 0x74, 0x22, 0xe4, 0x4e, 0x4d, 0x14 +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_86_public_x[] = { +/* QCAVSx */ + 0xa7, 0x21, 0xf6, 0xa2, 0xd4, 0x52, 0x74, 0x11, 0x83, 0x4b, 0x13, 0xd4, + 0xd3, 0xa3, 0x3c, 0x29, 0xbe, 0xb8, 0x3a, 0xb7, 0x68, 0x24, 0x65, 0xc6, + 0xcb, 0xaf, 0x66, 0x24, 0xac, 0xa6, 0xea, 0x58, 0xc3, 0x0e, 0xb0, 0xf2, + 0x9d, 0xd8, 0x42, 0x88, 0x66, 0x95, 0x40, 0x0d, 0x72, 0x54, 0xf2, 0x0f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_86_public_y[] = { +/* QCAVSy */ + 0x14, 0xba, 0x6e, 0x26, 0x35, 0x51, 0x09, 0xad, 0x35, 0x12, 0x93, 0x66, + 0xd5, 0xe3, 0xa6, 0x40, 0xae, 0x79, 0x85, 0x05, 0xa7, 0xfa, 0x55, 0xa9, + 0x6a, 0x36, 0xb5, 0xda, 0xd3, 0x3d, 0xe0, 0x04, 0x74, 0xf6, 0x67, 0x0f, + 0x52, 0x22, 0x14, 0xdd, 0x79, 0x52, 0x14, 0x0a, 0xb0, 0xa7, 0xeb, 0x68 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_86_private[] = { +/* dIUT */ + 0x83, 0xd7, 0x0f, 0x7b, 0x16, 0x4d, 0x9f, 0x4c, 0x22, 0x7c, 0x76, 0x70, + 0x46, 0xb2, 0x0e, 0xb3, 0x4d, 0xfc, 0x77, 0x8f, 0x53, 0x87, 0xe3, 0x2e, + 0x83, 0x4b, 0x1e, 0x6d, 0xae, 0xc2, 0x0e, 0xdb, 0x8c, 0xa5, 0xbb, 0x41, + 0x92, 0x09, 0x3f, 0x54, 0x3b, 0x68, 0xe6, 0xae, 0xb7, 0xce, 0x78, 0x8b +}; +/* QIUTx = 57cd770f3bbcbe0c78c770eab0b169bc45e139f86378ffae1c2b16966727c2f2eb724572b8f3eb228d130db4ff862c63 */ +/* QIUTy = 7ec5c8813b685558d83e924f14bc719f6eb7ae0cbb2c474227c5bda88637a4f26c64817929af999592da6f787490332f */ +static const uint8_t nist_kas_ecc_cdh_testvector_86_out[] = { +/* ZIUT */ + 0x10, 0x23, 0x47, 0x88, 0x40, 0xe5, 0x47, 0x75, 0xbf, 0xc6, 0x92, 0x93, + 0xa3, 0xcf, 0x97, 0xf5, 0xbc, 0x91, 0x47, 0x26, 0x45, 0x5c, 0x66, 0x53, + 0x8e, 0xb5, 0x62, 0x3e, 0x21, 0x8f, 0xee, 0xf7, 0xdf, 0x4b, 0xef, 0xa2, + 0x3e, 0x09, 0xd7, 0x71, 0x45, 0xad, 0x57, 0x7d, 0xb3, 0x2b, 0x41, 0xf9 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_87_public_x[] = { +/* QCAVSx */ + 0xd8, 0x82, 0xa8, 0x50, 0x5c, 0x2d, 0x5c, 0xb9, 0xb8, 0x85, 0x1f, 0xc6, + 0x76, 0x67, 0x7b, 0xb0, 0x08, 0x76, 0x81, 0xad, 0x53, 0xfa, 0xce, 0xba, + 0x17, 0x38, 0x28, 0x6b, 0x45, 0x82, 0x75, 0x61, 0xe7, 0xda, 0x37, 0xb8, + 0x80, 0x27, 0x6c, 0x65, 0x6c, 0xfc, 0x38, 0xb3, 0x2a, 0xde, 0x84, 0x7e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_87_public_y[] = { +/* QCAVSy */ + 0x34, 0xb3, 0x14, 0xbd, 0xc1, 0x34, 0x57, 0x56, 0x54, 0x57, 0x3c, 0xff, + 0xaf, 0x40, 0x44, 0x5d, 0xa2, 0xe6, 0xaa, 0xf9, 0x87, 0xf7, 0xe9, 0x13, + 0xcd, 0x4c, 0x30, 0x91, 0x52, 0x30, 0x58, 0x98, 0x4a, 0x25, 0xd8, 0xf2, + 0x1d, 0xa8, 0x32, 0x61, 0x92, 0x45, 0x6c, 0x6a, 0x0f, 0xa5, 0xf6, 0x0c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_87_private[] = { +/* dIUT */ + 0x8f, 0x55, 0x8e, 0x05, 0x81, 0x8b, 0x88, 0xed, 0x38, 0x3d, 0x5f, 0xca, + 0x96, 0x2e, 0x53, 0x41, 0x3d, 0xb1, 0xa0, 0xe4, 0x63, 0x7e, 0xda, 0x19, + 0x4f, 0x76, 0x19, 0x44, 0xcb, 0xea, 0x11, 0x4a, 0xb9, 0xd5, 0xda, 0x17, + 0x5a, 0x7d, 0x57, 0x88, 0x25, 0x50, 0xb0, 0xe4, 0x32, 0xf3, 0x95, 0xa9 +}; +/* QIUTx = 9a2f57f4867ce753d72b0d95195df6f96c1fae934f602efd7b6a54582f556cfa539d89005ca2edac08ad9b72dd1f60ba */ +/* QIUTy = d9b94ee82da9cc601f346044998ba387aee56404dc6ecc8ab2b590443319d0b2b6176f9d0eac2d44678ed561607d09a9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_87_out[] = { +/* ZIUT */ + 0x6a, 0xd6, 0xb9, 0xdc, 0x8a, 0x6c, 0xf0, 0xd3, 0x69, 0x1c, 0x50, 0x1c, + 0xbb, 0x96, 0x78, 0x67, 0xf6, 0xe4, 0xbb, 0xb7, 0x64, 0xb6, 0x0d, 0xbf, + 0xf8, 0xfc, 0xff, 0x3e, 0xd4, 0x2d, 0xbb, 0xa3, 0x9d, 0x63, 0xcf, 0x32, + 0x5b, 0x4b, 0x40, 0x78, 0x85, 0x84, 0x95, 0xdd, 0xee, 0x75, 0xf9, 0x54 +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_88_public_x[] = { +/* QCAVSx */ + 0x81, 0x5c, 0x9d, 0x77, 0x3d, 0xbf, 0x5f, 0xb6, 0xa1, 0xb8, 0x67, 0x99, + 0x96, 0x62, 0x47, 0xf4, 0x00, 0x6a, 0x23, 0xc9, 0x2e, 0x68, 0xc5, 0x5e, + 0x9e, 0xaa, 0x99, 0x8b, 0x17, 0xd8, 0x83, 0x2d, 0xd4, 0xd8, 0x4d, 0x92, + 0x7d, 0x83, 0x1d, 0x4f, 0x68, 0xda, 0xc6, 0x7c, 0x64, 0x88, 0x21, 0x9f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_88_public_y[] = { +/* QCAVSy */ + 0xe7, 0x92, 0x69, 0x94, 0x8b, 0x26, 0x11, 0x48, 0x45, 0x60, 0xfd, 0x49, + 0x0f, 0xee, 0xc8, 0x87, 0xcb, 0x55, 0xef, 0x99, 0xa4, 0xb5, 0x24, 0x88, + 0x0f, 0xa7, 0x49, 0x9d, 0x6a, 0x07, 0x28, 0x3a, 0xae, 0x2a, 0xfa, 0x33, + 0xfe, 0xab, 0x97, 0xde, 0xca, 0x40, 0xbc, 0x60, 0x6c, 0x4d, 0x87, 0x64 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_88_private[] = { +/* dIUT */ + 0x0f, 0x5d, 0xee, 0x0a, 0xff, 0xa7, 0xbb, 0xf2, 0x39, 0xd5, 0xdf, 0xf3, + 0x29, 0x87, 0xeb, 0xb7, 0xcf, 0x84, 0xfc, 0xce, 0xed, 0x64, 0x3e, 0x1d, + 0x3c, 0x62, 0xd0, 0xb3, 0x35, 0x2a, 0xec, 0x23, 0xb6, 0xe5, 0xac, 0x7f, + 0xa4, 0x10, 0x5c, 0x8c, 0xb2, 0x61, 0x26, 0xad, 0x2d, 0x18, 0x92, 0xcb +}; +/* QIUTx = 23346bdfbc9d7c7c736e02bdf607671ff6082fdd27334a8bc75f3b23681ebe614d0597dd614fae58677c835a9f0b273b */ +/* QIUTy = 82ba36290d2f94db41479eb45ab4eaf67928a2315138d59eecc9b5285dfddd6714f77557216ea44cc6fc119d8243efaf */ +static const uint8_t nist_kas_ecc_cdh_testvector_88_out[] = { +/* ZIUT */ + 0xcc, 0x9e, 0x06, 0x35, 0x66, 0xd4, 0x6b, 0x35, 0x7b, 0x3f, 0xca, 0xe2, + 0x18, 0x27, 0x37, 0x73, 0x31, 0xe5, 0xe2, 0x90, 0xa3, 0x6e, 0x60, 0xcd, + 0x7c, 0x39, 0x10, 0x2b, 0x82, 0x8a, 0xe0, 0xb9, 0x18, 0xdc, 0x5a, 0x02, + 0x21, 0x6b, 0x07, 0xfe, 0x6f, 0x19, 0x58, 0xd8, 0x34, 0xe4, 0x24, 0x37 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_89_public_x[] = { +/* QCAVSx */ + 0x1c, 0x0e, 0xed, 0xa7, 0xa2, 0xbe, 0x00, 0x0c, 0x5b, 0xdc, 0xda, 0x04, + 0x78, 0xae, 0xd4, 0xdb, 0x73, 0x3d, 0x2a, 0x9e, 0x34, 0x12, 0x24, 0x37, + 0x91, 0x23, 0xad, 0x84, 0x70, 0x30, 0xf2, 0x9e, 0x3b, 0x16, 0x8f, 0xa1, + 0x8e, 0x89, 0xa3, 0xc0, 0xfb, 0xa2, 0xa6, 0xce, 0x1c, 0x28, 0xfc, 0x3b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_89_public_y[] = { +/* QCAVSy */ + 0xec, 0x8c, 0x1c, 0x83, 0xc1, 0x18, 0xc4, 0xdb, 0xea, 0x94, 0x27, 0x18, + 0x69, 0xf2, 0xd8, 0x68, 0xeb, 0x65, 0xe8, 0xb4, 0x4e, 0x21, 0xe6, 0xf1, + 0x4b, 0x0f, 0x4d, 0x9b, 0x38, 0xc0, 0x68, 0xda, 0xef, 0xa2, 0x71, 0x14, + 0x25, 0x5b, 0x9a, 0x41, 0xd0, 0x84, 0xcc, 0x4a, 0x1a, 0xd8, 0x54, 0x56 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_89_private[] = { +/* dIUT */ + 0x03, 0x7b, 0x63, 0x3b, 0x5b, 0x8b, 0xa8, 0x57, 0xc0, 0xfc, 0x85, 0x65, + 0x68, 0x68, 0x23, 0x2e, 0x2f, 0xeb, 0xf5, 0x95, 0x78, 0x71, 0x83, 0x91, + 0xb8, 0x1d, 0xa8, 0x54, 0x1a, 0x00, 0xbf, 0xe5, 0x3c, 0x30, 0xae, 0x04, + 0x15, 0x18, 0x47, 0xf2, 0x74, 0x99, 0xf8, 0xd7, 0xab, 0xad, 0x8c, 0xf4 +}; +/* QIUTx = 8878ac8a947f7d5cb2b47aad24fbb8210d86126585399a2871f84aa9c5fde3074ae540c6bf82275ca822d0feb862bc74 */ +/* QIUTy = 632f5cd2f900c2711c32f8930728eb647d31edd8d650f9654e7d33e5ed1b475489d08daa30d8cbcba6bfc3b60d9b5a37 */ +static const uint8_t nist_kas_ecc_cdh_testvector_89_out[] = { +/* ZIUT */ + 0xde, 0xff, 0x7f, 0x03, 0xbd, 0x09, 0x86, 0x5b, 0xaf, 0x94, 0x5e, 0x73, + 0xed, 0xff, 0x6d, 0x51, 0x22, 0xc0, 0x3f, 0xb5, 0x61, 0xdb, 0x87, 0xde, + 0xc8, 0x66, 0x2e, 0x09, 0xbe, 0xd4, 0x34, 0x0b, 0x28, 0xa9, 0xef, 0xe1, + 0x18, 0x33, 0x7b, 0xb7, 0xd3, 0xd4, 0xf7, 0xf5, 0x68, 0x63, 0x5f, 0xf9 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_90_public_x[] = { +/* QCAVSx */ + 0xc9, 0x5c, 0x18, 0x5e, 0x25, 0x6b, 0xf9, 0x97, 0xf3, 0x0b, 0x31, 0x15, + 0x48, 0xae, 0x7f, 0x76, 0x8a, 0x38, 0xde, 0xe4, 0x3e, 0xee, 0xef, 0x43, + 0x08, 0x3f, 0x30, 0x77, 0xbe, 0x70, 0xe2, 0xbf, 0x39, 0xac, 0x1d, 0x4d, + 0xaf, 0x36, 0x0c, 0x51, 0x4c, 0x8c, 0x6b, 0xe6, 0x23, 0x44, 0x3d, 0x1a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_90_public_y[] = { +/* QCAVSy */ + 0x3e, 0x63, 0xa6, 0x63, 0xea, 0xf7, 0x5d, 0x8a, 0x76, 0x5a, 0xb2, 0xb9, + 0xa3, 0x55, 0x13, 0xd7, 0x93, 0x3f, 0xa5, 0xe2, 0x64, 0x20, 0xa5, 0x24, + 0x45, 0x50, 0xec, 0x6c, 0x3b, 0x6f, 0x03, 0x3b, 0x96, 0xdb, 0x2a, 0xca, + 0x3d, 0x6a, 0xc6, 0xaa, 0xb0, 0x52, 0xce, 0x92, 0x95, 0x95, 0xae, 0xa5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_90_private[] = { +/* dIUT */ + 0xe3, 0xd0, 0x71, 0x06, 0xbe, 0xdc, 0xc0, 0x96, 0xe7, 0xd9, 0x16, 0x30, + 0xff, 0xd3, 0x09, 0x4d, 0xf2, 0xc7, 0x85, 0x9d, 0xb8, 0xd7, 0xed, 0xbb, + 0x2e, 0x37, 0xb4, 0xac, 0x47, 0xf4, 0x29, 0xa6, 0x37, 0xd0, 0x6a, 0x67, + 0xd2, 0xfb, 0xa3, 0x38, 0x38, 0x76, 0x4e, 0xf2, 0x03, 0x46, 0x49, 0x91 +}; +/* QIUTx = e74a1a2b85f1cbf8dbbdf050cf1aff8acb02fda2fb6591f9d3cfe4e79d0ae938a9c1483e7b75f8db24505d65065cdb18 */ +/* QIUTy = 1773ee591822f7abaa856a1a60bc0a5203548dbd1cb5025466eff8481bd07614eaa04a16c3db76905913e972a5b6b59d */ +static const uint8_t nist_kas_ecc_cdh_testvector_90_out[] = { +/* ZIUT */ + 0xc8, 0xb1, 0x03, 0x8f, 0x73, 0x5a, 0xd3, 0xbb, 0x3e, 0x46, 0x37, 0xc3, + 0xe4, 0x7e, 0xab, 0x48, 0x76, 0x37, 0x91, 0x1a, 0x6b, 0x79, 0x50, 0xa4, + 0xe4, 0x61, 0x94, 0x83, 0x29, 0xd3, 0x92, 0x3b, 0x96, 0x9e, 0x5d, 0xb6, + 0x63, 0x67, 0x56, 0x23, 0x61, 0x1a, 0x45, 0x7f, 0xcd, 0xa3, 0x5a, 0x71 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_91_public_x[] = { +/* QCAVSx */ + 0x34, 0x97, 0x23, 0x8a, 0x7e, 0x6a, 0xd1, 0x66, 0xdf, 0x2d, 0xac, 0x03, + 0x9a, 0xa4, 0xda, 0xc8, 0xd1, 0x7a, 0xa9, 0x25, 0xe7, 0xc7, 0x63, 0x1e, + 0xb3, 0xb5, 0x6e, 0x3a, 0xaa, 0x1c, 0x54, 0x5f, 0xcd, 0x54, 0xd2, 0xe5, + 0x98, 0x58, 0x07, 0x91, 0x0f, 0xb2, 0x02, 0xb1, 0xfc, 0x19, 0x1d, 0x2a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_91_public_y[] = { +/* QCAVSy */ + 0xa4, 0x9e, 0x5c, 0x48, 0x7d, 0xcc, 0x7a, 0xa4, 0x0a, 0x8f, 0x23, 0x4c, + 0x97, 0x94, 0x46, 0x04, 0x0d, 0x91, 0x74, 0xe3, 0xad, 0x35, 0x7d, 0x40, + 0x4d, 0x77, 0x65, 0x18, 0x31, 0x95, 0xae, 0xd3, 0xf9, 0x13, 0x64, 0x1b, + 0x90, 0xc8, 0x1a, 0x30, 0x6e, 0xbf, 0x0d, 0x89, 0x13, 0x86, 0x13, 0x16 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_91_private[] = { +/* dIUT */ + 0xf3, 0xf9, 0xb0, 0xc6, 0x5a, 0x49, 0xa5, 0x06, 0x63, 0x2c, 0x8a, 0x45, + 0xb1, 0x0f, 0x66, 0xb5, 0x31, 0x6f, 0x9e, 0xeb, 0x06, 0xfa, 0xe2, 0x18, + 0xf2, 0xda, 0x62, 0x33, 0x3f, 0x99, 0x90, 0x51, 0x17, 0xb1, 0x41, 0xc7, + 0x60, 0xe8, 0x97, 0x4e, 0xfc, 0x4a, 0xf1, 0x05, 0x70, 0x63, 0x57, 0x91 +}; +/* QIUTx = a4ad77aa7d86e5361118a6b921710c820721210712f4c347985fdee58aa4effa1e28be80a17b120b139f96300f89b49b */ +/* QIUTy = 1ddf22e07e03f1560d8f45a480094560dba9fae7f9531130c1b57ebb95982496524f31d3797793396fa823f22bdb4328 */ +static const uint8_t nist_kas_ecc_cdh_testvector_91_out[] = { +/* ZIUT */ + 0xd3, 0x37, 0xea, 0xa3, 0x2b, 0x9f, 0x71, 0x6b, 0x87, 0x47, 0xb0, 0x05, + 0xb9, 0x7a, 0x55, 0x3c, 0x59, 0xda, 0xb0, 0xc5, 0x1d, 0xf4, 0x1a, 0x2d, + 0x49, 0x03, 0x9c, 0xda, 0xe7, 0x05, 0xaa, 0x75, 0xc7, 0xb9, 0xe7, 0xbc, + 0x0b, 0x6a, 0x0e, 0x8c, 0x57, 0x8c, 0x90, 0x2b, 0xc4, 0xff, 0xf2, 0x3e +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_92_public_x[] = { +/* QCAVSx */ + 0x90, 0xa3, 0x47, 0x37, 0xd4, 0x5b, 0x1a, 0xa6, 0x5f, 0x74, 0xe0, 0xbd, + 0x06, 0x59, 0xbc, 0x11, 0x8f, 0x8e, 0x4b, 0x77, 0x4b, 0x76, 0x19, 0x44, + 0xff, 0xa6, 0x57, 0x3c, 0x6d, 0xf4, 0xf4, 0x1d, 0xec, 0x0d, 0x11, 0xb6, + 0x97, 0xab, 0xd9, 0x34, 0xd3, 0x90, 0x87, 0x1d, 0x4b, 0x45, 0x32, 0x40 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_92_public_y[] = { +/* QCAVSy */ + 0x9b, 0x59, 0x07, 0x19, 0xbb, 0x33, 0x07, 0xc1, 0x49, 0xa7, 0x81, 0x7b, + 0xe3, 0x55, 0xd6, 0x84, 0x89, 0x3a, 0x30, 0x77, 0x64, 0xb5, 0x12, 0xee, + 0xff, 0xe0, 0x7c, 0xb6, 0x99, 0xed, 0xb5, 0xa6, 0xff, 0xbf, 0x8d, 0x60, + 0x32, 0xe6, 0xc7, 0x9d, 0x5e, 0x93, 0xe9, 0x42, 0x12, 0xc2, 0xaa, 0x4e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_92_private[] = { +/* dIUT */ + 0x59, 0xfc, 0xe7, 0xfa, 0xd7, 0xde, 0x28, 0xba, 0xc0, 0x23, 0x06, 0x90, + 0xc9, 0x57, 0x10, 0xc7, 0x20, 0xe5, 0x28, 0xf9, 0xa4, 0xe5, 0x4d, 0x3a, + 0x6a, 0x8c, 0xd5, 0xfc, 0x5c, 0x5f, 0x21, 0x63, 0x70, 0x31, 0xce, 0x1c, + 0x5b, 0x4e, 0x3d, 0x39, 0x64, 0x7d, 0x8d, 0xcb, 0x9b, 0x79, 0x46, 0x64 +}; +/* QIUTx = 9c43bf971edf09402876ee742095381f78b1bd3aa39b5132af75dbfe7e98bd78bde10fe2e903c2b6379e1deee175a1b0 */ +/* QIUTy = a6c58ecea5a477bb01bd543b339f1cc49f1371a2cda4d46eb4e53e250597942351a99665a122ffea9bde0636c375daf2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_92_out[] = { +/* ZIUT */ + 0x32, 0xd2, 0x92, 0xb6, 0x95, 0xa4, 0x48, 0x8e, 0x42, 0xa7, 0xb7, 0x92, + 0x2e, 0x1a, 0xe5, 0x37, 0xd7, 0x6a, 0x3d, 0x21, 0xa0, 0xb2, 0xe3, 0x68, + 0x75, 0xf6, 0x0e, 0x9f, 0x6d, 0x3e, 0x87, 0x79, 0xc2, 0xaf, 0xb3, 0xa4, + 0x13, 0xb9, 0xdd, 0x79, 0xae, 0x18, 0xe7, 0x0b, 0x47, 0xd3, 0x37, 0xc1 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_93_public_x[] = { +/* QCAVSx */ + 0xdd, 0xa5, 0x46, 0xac, 0xfc, 0x8f, 0x90, 0x3d, 0x11, 0xe2, 0xe3, 0x92, + 0x06, 0x69, 0x63, 0x6d, 0x44, 0xb2, 0x06, 0x8a, 0xeb, 0x66, 0xff, 0x07, + 0xaa, 0x26, 0x6f, 0x00, 0x30, 0xe1, 0x53, 0x5b, 0x0e, 0xd0, 0x20, 0x3c, + 0xb8, 0xa4, 0x60, 0xac, 0x99, 0x0f, 0x13, 0x94, 0xfa, 0xf2, 0x2f, 0x1d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_93_public_y[] = { +/* QCAVSy */ + 0x15, 0xbb, 0xb2, 0x59, 0x79, 0x13, 0x03, 0x5f, 0xaa, 0xdf, 0x41, 0x34, + 0x76, 0xf4, 0xc7, 0x0f, 0x72, 0x79, 0x76, 0x9a, 0x40, 0xc9, 0x86, 0xf4, + 0x70, 0xc4, 0x27, 0xb4, 0xee, 0x49, 0x62, 0xab, 0xdf, 0x81, 0x73, 0xbb, + 0xad, 0x81, 0x87, 0x47, 0x72, 0x92, 0x5f, 0xd3, 0x2f, 0x0b, 0x15, 0x9f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_93_private[] = { +/* dIUT */ + 0x3e, 0x49, 0xfb, 0xf9, 0x50, 0xa4, 0x24, 0xc5, 0xd8, 0x02, 0x28, 0xdc, + 0x4b, 0xc3, 0x5e, 0x9f, 0x6c, 0x6c, 0x0c, 0x1d, 0x04, 0x44, 0x09, 0x98, + 0xda, 0x0a, 0x60, 0x9a, 0x87, 0x75, 0x75, 0xdb, 0xe4, 0x37, 0xd6, 0xa5, + 0xce, 0xda, 0xa2, 0xdd, 0xd2, 0xa1, 0xa1, 0x7f, 0xd1, 0x12, 0xad, 0xed +}; +/* QIUTx = 5a949594228b1a3d6f599eb3db0d06070fbc551c657b58234ba164ce3fe415fa5f3eb823c08dc29b8c341219c77b6b3d */ +/* QIUTy = 2baad447c8c290cfed25edd9031c41d0b76921457327f42db31122b81f337bbf0b1039ec830ce9061a3761953c75e4a8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_93_out[] = { +/* ZIUT */ + 0x12, 0x20, 0xe7, 0xe6, 0xca, 0xd7, 0xb2, 0x5d, 0xf9, 0x8e, 0x5b, 0xbd, + 0xcc, 0x6c, 0x0b, 0x65, 0xca, 0x6c, 0x2a, 0x50, 0xc5, 0xff, 0x6c, 0x41, + 0xdc, 0xa7, 0x1e, 0x47, 0x56, 0x46, 0xfd, 0x48, 0x96, 0x15, 0x97, 0x9c, + 0xa9, 0x2f, 0xb4, 0x38, 0x9a, 0xea, 0xde, 0xfd, 0xe7, 0x9a, 0x24, 0xf1 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_94_public_x[] = { +/* QCAVSx */ + 0x78, 0x8b, 0xe2, 0x33, 0x6c, 0x52, 0xf4, 0x45, 0x4d, 0x63, 0xee, 0x94, + 0x4b, 0x1e, 0x49, 0xbf, 0xb6, 0x19, 0xa0, 0x83, 0x71, 0x04, 0x8e, 0x6d, + 0xa9, 0x2e, 0x58, 0x4e, 0xae, 0x70, 0xbd, 0xe1, 0xf1, 0x71, 0xc4, 0xdf, + 0x37, 0x8b, 0xd1, 0xf3, 0xc0, 0xab, 0x03, 0x04, 0x8a, 0x23, 0x78, 0x02 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_94_public_y[] = { +/* QCAVSy */ + 0x46, 0x73, 0xeb, 0xd8, 0xdb, 0x60, 0x4e, 0xaf, 0x41, 0x71, 0x17, 0x48, + 0xba, 0xb2, 0x96, 0x8a, 0x23, 0xca, 0x44, 0x76, 0xce, 0x14, 0x4e, 0x72, + 0x82, 0x47, 0xf0, 0x8a, 0xf7, 0x52, 0x92, 0x91, 0x57, 0xb5, 0x83, 0x0f, + 0x1e, 0x26, 0x06, 0x74, 0x66, 0xbd, 0xfa, 0x8b, 0x65, 0x14, 0x5a, 0x33 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_94_private[] = { +/* dIUT */ + 0x50, 0xcc, 0xc1, 0xf7, 0x07, 0x6e, 0x92, 0xf4, 0x63, 0x8e, 0x85, 0xf2, + 0xdb, 0x98, 0xe0, 0xb4, 0x83, 0xe6, 0xe2, 0x20, 0x4c, 0x92, 0xbd, 0xd4, + 0x40, 0xa6, 0xde, 0xea, 0x04, 0xe3, 0x7a, 0x07, 0xc6, 0xe7, 0x27, 0x91, + 0xc1, 0x90, 0xad, 0x4e, 0x4e, 0x86, 0xe0, 0x1e, 0xfb, 0xa8, 0x42, 0x69 +}; +/* QIUTx = 756c07df0ce32c839dac9fb4733c9c28b70113a676a7057c38d223f22a3a9095a8d564653af528e04c7e1824be4a6512 */ +/* QIUTy = 17c2ce6962cbd2a2e066297b39d57dd9bb4680f0191d390f70b4e461419b2972ce68ad46127fdda6c39195774ea86df3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_94_out[] = { +/* ZIUT */ + 0x79, 0x3b, 0xb9, 0xcd, 0x22, 0xa9, 0x3c, 0xf4, 0x68, 0xfa, 0xf8, 0x04, + 0xa3, 0x8d, 0x12, 0xb7, 0x8c, 0xb1, 0x21, 0x89, 0xec, 0x67, 0x9d, 0xdd, + 0x2e, 0x9a, 0xa2, 0x1f, 0xa9, 0xa5, 0xa0, 0xb0, 0x49, 0xab, 0x16, 0xa2, + 0x35, 0x74, 0xfe, 0x04, 0xc1, 0xc3, 0xc0, 0x23, 0x43, 0xb9, 0x1b, 0xeb +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_95_public_x[] = { +/* QCAVSx */ + 0xd0, 0x9b, 0xb8, 0x22, 0xeb, 0x99, 0xe3, 0x80, 0x60, 0x95, 0x47, 0x47, + 0xc8, 0x2b, 0xb3, 0x27, 0x8c, 0xf9, 0x6b, 0xbf, 0x36, 0xfe, 0xce, 0x34, + 0x00, 0xf4, 0xc8, 0x73, 0x83, 0x8a, 0x40, 0xc1, 0x35, 0xeb, 0x3b, 0xab, + 0xb9, 0x29, 0x3b, 0xd1, 0x00, 0x1b, 0xf3, 0xec, 0xde, 0xe7, 0xbf, 0x26 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_95_public_y[] = { +/* QCAVSy */ + 0xd4, 0x16, 0xdb, 0x6e, 0x1b, 0x87, 0xbb, 0xb7, 0x42, 0x77, 0x88, 0xa3, + 0xb6, 0xc7, 0xa7, 0xab, 0x2c, 0x16, 0x5b, 0x1e, 0x36, 0x6f, 0x96, 0x08, + 0xdf, 0x51, 0x20, 0x37, 0x58, 0x4f, 0x21, 0x3a, 0x64, 0x8d, 0x47, 0xf1, + 0x6a, 0xc3, 0x26, 0xe1, 0x9a, 0xae, 0x97, 0x2f, 0x63, 0xfd, 0x76, 0xc9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_95_private[] = { +/* dIUT */ + 0x06, 0xf1, 0x32, 0xb7, 0x1f, 0x74, 0xd8, 0x7b, 0xf9, 0x98, 0x57, 0xe1, + 0xe4, 0x35, 0x0a, 0x59, 0x4e, 0x5f, 0xe3, 0x55, 0x33, 0xb8, 0x88, 0x55, + 0x2c, 0xec, 0xcb, 0xc0, 0xd8, 0x92, 0x3c, 0x90, 0x2e, 0x36, 0x14, 0x1d, + 0x76, 0x91, 0xe2, 0x86, 0x31, 0xb8, 0xbc, 0x9b, 0xaf, 0xe5, 0xe0, 0x64 +}; +/* QIUTx = 2a3cc6b8ff5cde926e7e3a189a1bd029c9b586351af8838f4f201cb8f4b70ef3b0da06d352c80fc26baf8f42b784459e */ +/* QIUTy = bf9985960176da6d23c7452a2954ffcbbcb24249b43019a2a023e0b3dabd461f19ad3e775c364f3f11ad49f3099400d3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_95_out[] = { +/* ZIUT */ + 0x01, 0x2d, 0x19, 0x1c, 0xf7, 0x40, 0x4a, 0x52, 0x36, 0x78, 0xc6, 0xfc, + 0x07, 0x5d, 0xe8, 0x28, 0x5b, 0x24, 0x37, 0x20, 0xa9, 0x03, 0x04, 0x77, + 0x08, 0xbb, 0x33, 0xe5, 0x01, 0xe0, 0xdb, 0xee, 0x5b, 0xcc, 0x40, 0xd7, + 0xc3, 0xef, 0x6c, 0x6d, 0xa3, 0x9e, 0xa2, 0x4d, 0x83, 0x0d, 0xa1, 0xe8 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_96_public_x[] = { +/* QCAVSx */ + 0x13, 0x74, 0x12, 0x62, 0xed, 0xe5, 0x86, 0x1d, 0xad, 0x71, 0x06, 0x3d, + 0xfd, 0x20, 0x4b, 0x91, 0xea, 0x1d, 0x3b, 0x7c, 0x63, 0x1d, 0xf6, 0x8e, + 0xb9, 0x49, 0x96, 0x95, 0x27, 0xd7, 0x9a, 0x1d, 0xc5, 0x92, 0x95, 0xef, + 0x7d, 0x2b, 0xca, 0x67, 0x43, 0xe8, 0xcd, 0x77, 0xb0, 0x4d, 0x1b, 0x58 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_96_public_y[] = { +/* QCAVSy */ + 0x0b, 0xaa, 0xea, 0xdc, 0x7e, 0x19, 0xd7, 0x4a, 0x8a, 0x04, 0x45, 0x1a, + 0x13, 0x5f, 0x1b, 0xe1, 0xb0, 0x2f, 0xe2, 0x99, 0xf9, 0xdc, 0x00, 0xbf, + 0xdf, 0x20, 0x1e, 0x83, 0xd9, 0x95, 0xc6, 0x95, 0x0b, 0xcc, 0x1c, 0xb8, + 0x9d, 0x6f, 0x7b, 0x30, 0xbf, 0x54, 0x65, 0x6b, 0x9a, 0x4d, 0xa5, 0x86 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_96_private[] = { +/* dIUT */ + 0x12, 0x04, 0x8e, 0xbb, 0x43, 0x31, 0xec, 0x19, 0xa1, 0xe2, 0x3f, 0x1a, + 0x2c, 0x77, 0x3b, 0x66, 0x4c, 0xcf, 0xe9, 0x0a, 0x28, 0xbf, 0xb8, 0x46, + 0xfc, 0x12, 0xf8, 0x1d, 0xff, 0x44, 0xb7, 0x44, 0x3c, 0x77, 0x64, 0x71, + 0x64, 0xbf, 0x1e, 0x9e, 0x67, 0xfd, 0x2c, 0x07, 0xa6, 0x76, 0x62, 0x41 +}; +/* QIUTx = bc18836bc7a9fdf54b5352f37d7528ab8fa8ec544a8c6180511cbfdd49cce377c39e34c031b5240dc9980503ed2f262c */ +/* QIUTy = 8086cbe338191080f0b7a16c7afc4c7b0326f9ac66f58552ef4bb9d24de3429ed5d3277ed58fcf48f2b5f61326bec6c6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_96_out[] = { +/* ZIUT */ + 0xad, 0x0f, 0xd3, 0xdd, 0xff, 0xe8, 0x88, 0x4b, 0x92, 0x63, 0xf3, 0xc1, + 0x5f, 0xe1, 0xf0, 0x7f, 0x2a, 0x5a, 0x22, 0xff, 0xdc, 0x7e, 0x96, 0x70, + 0x85, 0xee, 0xa4, 0x5f, 0x0c, 0xd9, 0x59, 0xf2, 0x0f, 0x18, 0xf5, 0x22, + 0x76, 0x3e, 0x28, 0xbc, 0xc9, 0x25, 0xe4, 0x96, 0xa5, 0x2d, 0xda, 0x98 +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_97_public_x[] = { +/* QCAVSx */ + 0x9e, 0x22, 0xcb, 0xc1, 0x86, 0x57, 0xf5, 0x16, 0xa8, 0x64, 0xb3, 0x7b, + 0x78, 0x33, 0x48, 0xb6, 0x6f, 0x1a, 0xa9, 0x62, 0x6c, 0xd6, 0x31, 0xf4, + 0xfa, 0x1b, 0xd3, 0x2a, 0xd8, 0x8c, 0xf1, 0x1d, 0xb5, 0x20, 0x57, 0xc6, + 0x60, 0x86, 0x0d, 0x39, 0xd1, 0x1f, 0xbf, 0x02, 0x4f, 0xab, 0xd4, 0x44 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_97_public_y[] = { +/* QCAVSy */ + 0x6b, 0x0d, 0x53, 0xc7, 0x96, 0x81, 0xc2, 0x81, 0x16, 0xdf, 0x71, 0xe9, + 0xce, 0xe7, 0x4f, 0xd5, 0x6c, 0x8b, 0x7f, 0x04, 0xb3, 0x9f, 0x11, 0x98, + 0xcc, 0x72, 0x28, 0x4e, 0x98, 0xbe, 0x95, 0x62, 0xe3, 0x59, 0x26, 0xfb, + 0x4f, 0x48, 0xa9, 0xfb, 0xec, 0xaf, 0xe7, 0x29, 0x30, 0x9e, 0x8b, 0x6f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_97_private[] = { +/* dIUT */ + 0x34, 0xd6, 0x1a, 0x69, 0x9c, 0xa5, 0x76, 0x16, 0x9f, 0xcd, 0xc0, 0xcc, + 0x7e, 0x44, 0xe4, 0xe1, 0x22, 0x1d, 0xb0, 0xfe, 0x63, 0xd1, 0x68, 0x50, + 0xc8, 0x10, 0x40, 0x29, 0xf7, 0xd4, 0x84, 0x49, 0x71, 0x4b, 0x98, 0x84, + 0x32, 0x8c, 0xae, 0x18, 0x99, 0x78, 0x75, 0x4a, 0xb4, 0x60, 0xb4, 0x86 +}; +/* QIUTx = 867f81104ccd6b163a7902b670ef406042cb0cce7dcdc63d1dfc91b2c40e3cdf7595834bf9eceb79849f1636fc8462fc */ +/* QIUTy = 9d4bde8e875ec49697d258d1d59465f8431c6f5531e1c59e9f9ebe3cf164a8d9ce10a12f1979283a959bad244dd83863 */ +static const uint8_t nist_kas_ecc_cdh_testvector_97_out[] = { +/* ZIUT */ + 0xdc, 0x4c, 0xa3, 0x92, 0xdc, 0x15, 0xe2, 0x01, 0x85, 0xf2, 0xc6, 0xa8, + 0xea, 0x5e, 0xc3, 0x1d, 0xfc, 0x96, 0xf5, 0x61, 0x53, 0xa4, 0x73, 0x94, + 0xb3, 0x07, 0x2b, 0x13, 0xd0, 0x01, 0x5f, 0x5d, 0x4a, 0xe1, 0x3b, 0xeb, + 0x3b, 0xed, 0x54, 0xd6, 0x58, 0x48, 0xf9, 0xb8, 0x38, 0x3e, 0x6c, 0x95 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_98_public_x[] = { +/* QCAVSx */ + 0x2d, 0xb5, 0xda, 0x5f, 0x94, 0x0e, 0xaa, 0x88, 0x4f, 0x4d, 0xb5, 0xec, + 0x21, 0x39, 0xb0, 0x46, 0x9f, 0x38, 0xe4, 0xe6, 0xfb, 0xbc, 0xc5, 0x2d, + 0xf1, 0x5c, 0x0f, 0x7c, 0xf7, 0xfc, 0xb1, 0x80, 0x8c, 0x74, 0x97, 0x64, + 0xb6, 0xbe, 0x85, 0xd2, 0xfd, 0xc5, 0xb1, 0x6f, 0x58, 0xad, 0x5d, 0xc0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_98_public_y[] = { +/* QCAVSy */ + 0x22, 0xe8, 0xb0, 0x2d, 0xcf, 0x33, 0xe1, 0xb5, 0xa0, 0x83, 0x84, 0x95, + 0x45, 0xf8, 0x4a, 0xd5, 0xe4, 0x3f, 0x77, 0xcb, 0x71, 0x54, 0x6d, 0xbb, + 0xac, 0x0d, 0x11, 0xbd, 0xb2, 0xee, 0x20, 0x2e, 0x9d, 0x38, 0x72, 0xe8, + 0xd0, 0x28, 0xc0, 0x89, 0x90, 0x74, 0x6c, 0x5e, 0x1d, 0xde, 0x99, 0x89 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_98_private[] = { +/* dIUT */ + 0xdc, 0x60, 0xfa, 0x87, 0x36, 0xd7, 0x02, 0x13, 0x5f, 0xf1, 0x6a, 0xab, + 0x99, 0x2b, 0xb8, 0x8e, 0xac, 0x39, 0x7f, 0x59, 0x72, 0x45, 0x6c, 0x72, + 0xec, 0x44, 0x73, 0x74, 0xd0, 0xd8, 0xce, 0x61, 0x15, 0x38, 0x31, 0xbf, + 0xc8, 0x6a, 0xd5, 0xa6, 0xeb, 0x5b, 0x60, 0xbf, 0xb9, 0x6a, 0x86, 0x2c +}; +/* QIUTx = b69beede85d0f829fec1b893ccb9c3e052ff692e13b974537bc5b0f9feaf7b22e84f03231629b24866bdb4b8cf908914 */ +/* QIUTy = 66f85e2bfcaba2843285b0e14ebc07ef7dafff8b424416fee647b59897b619f20eed95a632e6a4206bf7da429c04c560 */ +static const uint8_t nist_kas_ecc_cdh_testvector_98_out[] = { +/* ZIUT */ + 0xd7, 0x65, 0xb2, 0x08, 0x11, 0x2d, 0x2b, 0x9e, 0xd5, 0xad, 0x10, 0xc4, + 0x04, 0x6e, 0x2e, 0x3b, 0x0d, 0xbf, 0x57, 0xc4, 0x69, 0x32, 0x95, 0x19, + 0xe2, 0x39, 0xac, 0x28, 0xb2, 0x5c, 0x7d, 0x85, 0x2b, 0xf7, 0x57, 0xd5, + 0xde, 0x0e, 0xe2, 0x71, 0xca, 0xdd, 0x02, 0x1d, 0x86, 0xcf, 0xd3, 0x47 +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_99_public_x[] = { +/* QCAVSx */ + 0x32, 0x96, 0x47, 0xba, 0xa3, 0x54, 0x22, 0x4e, 0xb4, 0x41, 0x48, 0x29, + 0xc5, 0x36, 0x8c, 0x82, 0xd7, 0x89, 0x3b, 0x39, 0x80, 0x4e, 0x08, 0xcb, + 0xb2, 0x18, 0x0f, 0x45, 0x9b, 0xef, 0xc4, 0xb3, 0x47, 0xa3, 0x89, 0xa7, + 0x0c, 0x91, 0xa2, 0x3b, 0xd9, 0xd3, 0x0c, 0x83, 0xbe, 0x52, 0x95, 0xd3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_99_public_y[] = { +/* QCAVSy */ + 0xcc, 0x8f, 0x61, 0x92, 0x3f, 0xad, 0x2a, 0xa8, 0xe5, 0x05, 0xd6, 0xcf, + 0xa1, 0x26, 0xb9, 0xfa, 0xbd, 0x5a, 0xf9, 0xdc, 0xe2, 0x90, 0xb7, 0x56, + 0x60, 0xef, 0x06, 0xd1, 0xca, 0xa7, 0x36, 0x81, 0xd0, 0x60, 0x89, 0xc3, + 0x3b, 0xc4, 0x24, 0x6b, 0x3a, 0xa3, 0x0d, 0xbc, 0xd2, 0x43, 0x5b, 0x12 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_99_private[] = { +/* dIUT */ + 0x6f, 0xa6, 0xa1, 0xc7, 0x04, 0x73, 0x09, 0x87, 0xaa, 0x63, 0x4b, 0x05, + 0x16, 0xa8, 0x26, 0xab, 0xa8, 0xc6, 0xd6, 0x41, 0x1d, 0x3a, 0x4c, 0x89, + 0x77, 0x2d, 0x7a, 0x62, 0x61, 0x02, 0x56, 0xa2, 0xe2, 0xf2, 0x89, 0xf5, + 0xc3, 0x44, 0x0b, 0x0e, 0xc1, 0xe7, 0x0f, 0xa3, 0x39, 0xe2, 0x51, 0xce +}; +/* QIUTx = 53de1fc1328e8de14aecab29ad8a40d6b13768f86f7d298433d20fec791f86f8bc73f358098b256a298bb488de257bf4 */ +/* QIUTy = ac28944fd27f17b82946c04c66c41f0053d3692f275da55cd8739a95bd8cd3af2f96e4de959ea8344d8945375905858b */ +static const uint8_t nist_kas_ecc_cdh_testvector_99_out[] = { +/* ZIUT */ + 0xd3, 0x77, 0x88, 0x50, 0xae, 0xb5, 0x88, 0x04, 0xfb, 0xe9, 0xdf, 0xe6, + 0xf3, 0x8b, 0x9f, 0xa8, 0xe2, 0x0c, 0x2c, 0xa4, 0xe0, 0xde, 0xc3, 0x35, + 0xaa, 0xfc, 0xec, 0xa0, 0x33, 0x3e, 0x3f, 0x24, 0x90, 0xb5, 0x3c, 0x0c, + 0x1a, 0x14, 0xa8, 0x31, 0xba, 0x37, 0xc4, 0xb9, 0xd7, 0x4b, 0xe0, 0xf2 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_100_public_x[] = { +/* QCAVSx */ + 0x29, 0xd8, 0xa3, 0x6d, 0x22, 0x20, 0x0a, 0x75, 0xb7, 0xae, 0xa1, 0xbb, + 0x47, 0xcd, 0xfc, 0xb1, 0xb7, 0xfd, 0x66, 0xde, 0x96, 0x70, 0x41, 0x43, + 0x47, 0x28, 0xab, 0x5d, 0x53, 0x3a, 0x06, 0x0d, 0xf7, 0x32, 0x13, 0x06, + 0x00, 0xfe, 0x6f, 0x75, 0x85, 0x2a, 0x87, 0x1f, 0xb2, 0x93, 0x8e, 0x39 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_100_public_y[] = { +/* QCAVSy */ + 0xe1, 0x9b, 0x53, 0xdb, 0x52, 0x83, 0x95, 0xde, 0x89, 0x7a, 0x45, 0x10, + 0x89, 0x67, 0x71, 0x5e, 0xb8, 0xcb, 0x55, 0xc3, 0xfc, 0xbf, 0x23, 0x37, + 0x93, 0x72, 0xc0, 0x87, 0x3a, 0x05, 0x8d, 0x57, 0x54, 0x4b, 0x10, 0x2e, + 0xcc, 0xe7, 0x22, 0xb2, 0xcc, 0xab, 0xb1, 0xa6, 0x03, 0x77, 0x4f, 0xd5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_100_private[] = { +/* dIUT */ + 0x74, 0xad, 0x83, 0x86, 0xc1, 0xcb, 0x2c, 0xa0, 0xfc, 0xde, 0xb3, 0x1e, + 0x08, 0x69, 0xbb, 0x3f, 0x48, 0xc0, 0x36, 0xaf, 0xe2, 0xef, 0x11, 0x0c, + 0xa3, 0x02, 0xbc, 0x8b, 0x91, 0x0f, 0x62, 0x1c, 0x9f, 0xcc, 0x54, 0xce, + 0xc3, 0x2b, 0xb8, 0x9e, 0xc7, 0xca, 0xa8, 0x4c, 0x7b, 0x8e, 0x54, 0xa8 +}; +/* QIUTx = 27a3e83cfb9d5122e73129d801615857da7cc089cccc9c54ab3032a19e0a0a9f677346e37f08a0b3ed8da6e5dd691063 */ +/* QIUTy = 8d60e44aa5e0fd30c918456796af37f0e41957901645e5c596c6d989f5859b03a0bd7d1f4e77936fff3c74d204e5388e */ +static const uint8_t nist_kas_ecc_cdh_testvector_100_out[] = { +/* ZIUT */ + 0x81, 0xe1, 0xe7, 0x15, 0x75, 0xbb, 0x45, 0x05, 0x49, 0x8d, 0xe0, 0x97, + 0x35, 0x01, 0x86, 0x43, 0x0a, 0x62, 0x42, 0xfa, 0x6c, 0x57, 0xb8, 0x5a, + 0x5f, 0x98, 0x4a, 0x23, 0x37, 0x11, 0x23, 0xd2, 0xd1, 0x42, 0x4e, 0xef, + 0xbf, 0x80, 0x42, 0x58, 0x39, 0x2b, 0xc7, 0x23, 0xe4, 0xef, 0x1e, 0x35 +}; +/* [P-521] */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_101_public_x[] = { +/* QCAVSx */ + 0x00, 0x68, 0x5a, 0x48, 0xe8, 0x6c, 0x79, 0xf0, 0xf0, 0x87, 0x5f, 0x7b, + 0xc1, 0x8d, 0x25, 0xeb, 0x5f, 0xc8, 0xc0, 0xb0, 0x7e, 0x5d, 0xa4, 0xf4, + 0x37, 0x0f, 0x3a, 0x94, 0x90, 0x34, 0x08, 0x54, 0x33, 0x4b, 0x1e, 0x1b, + 0x87, 0xfa, 0x39, 0x54, 0x64, 0xc6, 0x06, 0x26, 0x12, 0x4a, 0x4e, 0x70, + 0xd0, 0xf7, 0x85, 0x60, 0x1d, 0x37, 0xc0, 0x98, 0x70, 0xeb, 0xf1, 0x76, + 0x66, 0x68, 0x77, 0xa2, 0x04, 0x6d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_101_public_y[] = { +/* QCAVSy */ + 0x01, 0xba, 0x52, 0xc5, 0x6f, 0xc8, 0x77, 0x6d, 0x9e, 0x8f, 0x5d, 0xb4, + 0xf0, 0xcc, 0x27, 0x63, 0x6d, 0x0b, 0x74, 0x1b, 0xbe, 0x05, 0x40, 0x06, + 0x97, 0x94, 0x2e, 0x80, 0xb7, 0x39, 0x88, 0x4a, 0x83, 0xbd, 0xe9, 0x9e, + 0x0f, 0x67, 0x16, 0x93, 0x9e, 0x63, 0x2b, 0xc8, 0x98, 0x6f, 0xa1, 0x8d, + 0xcc, 0xd4, 0x43, 0xa3, 0x48, 0xb6, 0xc3, 0xe5, 0x22, 0x49, 0x79, 0x55, + 0xa4, 0xf3, 0xc3, 0x02, 0xf6, 0x76 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_101_private[] = { +/* dIUT */ + 0x01, 0x7e, 0xec, 0xc0, 0x7a, 0xb4, 0xb3, 0x29, 0x06, 0x8f, 0xba, 0x65, + 0xe5, 0x6a, 0x1f, 0x88, 0x90, 0xaa, 0x93, 0x5e, 0x57, 0x13, 0x4a, 0xe0, + 0xff, 0xcc, 0xe8, 0x02, 0x73, 0x51, 0x51, 0xf4, 0xea, 0xc6, 0x56, 0x4f, + 0x6e, 0xe9, 0x97, 0x4c, 0x5e, 0x68, 0x87, 0xa1, 0xfe, 0xfe, 0xe5, 0x74, + 0x3a, 0xe2, 0x24, 0x1b, 0xfe, 0xb9, 0x5d, 0x5c, 0xe3, 0x1d, 0xdc, 0xb6, + 0xf9, 0xed, 0xb4, 0xd6, 0xfc, 0x47 +}; +/* QIUTx = 000000602f9d0cf9e526b29e22381c203c48a886c2b0673033366314f1ffbcba240ba42f4ef38a76174635f91e6b4ed34275eb01c8467d05ca80315bf1a7bbd945f550a5 */ +/* QIUTy = 000001b7c85f26f5d4b2d7355cf6b02117659943762b6d1db5ab4f1dbc44ce7b2946eb6c7de342962893fd387d1b73d7a8672d1f236961170b7eb3579953ee5cdc88cd2d */ +static const uint8_t nist_kas_ecc_cdh_testvector_101_out[] = { +/* ZIUT */ + 0x00, 0x5f, 0xc7, 0x04, 0x77, 0xc3, 0xe6, 0x3b, 0xc3, 0x95, 0x4b, 0xd0, + 0xdf, 0x3e, 0xa0, 0xd1, 0xf4, 0x1e, 0xe2, 0x17, 0x46, 0xed, 0x95, 0xfc, + 0x5e, 0x1f, 0xdf, 0x90, 0x93, 0x0d, 0x5e, 0x13, 0x66, 0x72, 0xd7, 0x2c, + 0xc7, 0x70, 0x74, 0x2d, 0x17, 0x11, 0xc3, 0xc3, 0xa4, 0xc3, 0x34, 0xa0, + 0xad, 0x97, 0x59, 0x43, 0x6a, 0x4d, 0x3c, 0x5b, 0xf6, 0xe7, 0x4b, 0x95, + 0x78, 0xfa, 0xc1, 0x48, 0xc8, 0x31 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_102_public_x[] = { +/* QCAVSx */ + 0x01, 0xdf, 0x27, 0x7c, 0x15, 0x21, 0x08, 0x34, 0x9b, 0xc3, 0x4d, 0x53, + 0x9e, 0xe0, 0xcf, 0x06, 0xb2, 0x4f, 0x5d, 0x35, 0x00, 0x67, 0x7b, 0x44, + 0x45, 0x45, 0x3c, 0xcc, 0x21, 0x40, 0x94, 0x53, 0xaa, 0xfb, 0x8a, 0x72, + 0xa0, 0xbe, 0x9e, 0xbe, 0x54, 0xd1, 0x22, 0x70, 0xaa, 0x51, 0xb3, 0xab, + 0x7f, 0x31, 0x6a, 0xa5, 0xe7, 0x4a, 0x95, 0x1c, 0x5e, 0x53, 0xf7, 0x4c, + 0xd9, 0x5f, 0xc2, 0x9a, 0xee, 0x7a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_102_public_y[] = { +/* QCAVSy */ + 0x01, 0x3d, 0x52, 0xf3, 0x3a, 0x9f, 0x3c, 0x14, 0x38, 0x4d, 0x15, 0x87, + 0xfa, 0x8a, 0xbe, 0x7a, 0xed, 0x74, 0xbc, 0x33, 0x74, 0x9a, 0xd9, 0xc5, + 0x70, 0xb4, 0x71, 0x77, 0x64, 0x22, 0xc7, 0xd4, 0x50, 0x5d, 0x9b, 0x0a, + 0x96, 0xb3, 0xbf, 0xac, 0x04, 0x1e, 0x4c, 0x6a, 0x69, 0x90, 0xae, 0x7f, + 0x70, 0x0e, 0x5b, 0x4a, 0x66, 0x40, 0x22, 0x91, 0x12, 0xde, 0xaf, 0xa0, + 0xcd, 0x8b, 0xb0, 0xd0, 0x89, 0xb0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_102_private[] = { +/* dIUT */ + 0x00, 0x81, 0x6f, 0x19, 0xc1, 0xfb, 0x10, 0xef, 0x94, 0xd4, 0xa1, 0xd8, + 0x1c, 0x15, 0x6e, 0xc3, 0xd1, 0xde, 0x08, 0xb6, 0x67, 0x61, 0xf0, 0x3f, + 0x06, 0xee, 0x4b, 0xb9, 0xdc, 0xeb, 0xbb, 0xfe, 0x1e, 0xaa, 0x1e, 0xd4, + 0x9a, 0x6a, 0x99, 0x08, 0x38, 0xd8, 0xed, 0x31, 0x8c, 0x14, 0xd7, 0x4c, + 0xc8, 0x72, 0xf9, 0x5d, 0x05, 0xd0, 0x7a, 0xd5, 0x0f, 0x62, 0x1c, 0xeb, + 0x62, 0x0c, 0xd9, 0x05, 0xcf, 0xb8 +}; +/* QIUTx = 000000d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f4671105309ec9b6879d0551d930dac8ba45d255 */ +/* QIUTy = 000001425332844e592b440c0027972ad1526431c06732df19cd46a242172d4dd67c2c8c99dfc22e49949a56cf90c6473635ce82f25b33682fb19bc33bd910ed8ce3a7fa */ +static const uint8_t nist_kas_ecc_cdh_testvector_102_out[] = { +/* ZIUT */ + 0x00, 0x0b, 0x39, 0x20, 0xac, 0x83, 0x0a, 0xde, 0x81, 0x2c, 0x8f, 0x96, + 0x80, 0x5d, 0xa2, 0x23, 0x6e, 0x00, 0x2a, 0xcb, 0xbf, 0x13, 0x59, 0x6a, + 0x9a, 0xb2, 0x54, 0xd4, 0x4d, 0x0e, 0x91, 0xb6, 0x25, 0x5e, 0xbf, 0x12, + 0x29, 0xf3, 0x66, 0xfb, 0x5a, 0x05, 0xc5, 0x88, 0x4e, 0xf4, 0x60, 0x32, + 0xc2, 0x6d, 0x42, 0x18, 0x92, 0x73, 0xca, 0x4e, 0xfa, 0x4c, 0x3d, 0xb6, + 0xbd, 0x12, 0xa6, 0x85, 0x37, 0x59 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_103_public_x[] = { +/* QCAVSx */ + 0x00, 0x92, 0xdb, 0x31, 0x42, 0x56, 0x4d, 0x27, 0xa5, 0xf0, 0x00, 0x6f, + 0x81, 0x99, 0x08, 0xfb, 0xa1, 0xb8, 0x50, 0x38, 0xa5, 0xbc, 0x25, 0x09, + 0x90, 0x6a, 0x49, 0x7d, 0xaa, 0xc6, 0x7f, 0xd7, 0xae, 0xe0, 0xfc, 0x2d, + 0xab, 0xa4, 0xe4, 0x33, 0x4e, 0xea, 0xef, 0x0e, 0x00, 0x19, 0x20, 0x4b, + 0x47, 0x1c, 0xd8, 0x80, 0x24, 0xf8, 0x21, 0x15, 0xd8, 0x14, 0x9c, 0xc0, + 0xcf, 0x4f, 0x7c, 0xe1, 0xa4, 0xd5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_103_public_y[] = { +/* QCAVSy */ + 0x01, 0x6b, 0xad, 0x06, 0x23, 0xf5, 0x17, 0xb1, 0x58, 0xd9, 0x88, 0x18, + 0x41, 0xd2, 0x57, 0x1e, 0xfb, 0xad, 0x63, 0xf8, 0x5c, 0xbe, 0x2e, 0x58, + 0x19, 0x60, 0xc5, 0xd6, 0x70, 0x60, 0x1a, 0x67, 0x60, 0x27, 0x26, 0x75, + 0xa5, 0x48, 0x99, 0x62, 0x17, 0xe4, 0xab, 0x2b, 0x8e, 0xbc, 0xe3, 0x1d, + 0x71, 0xfc, 0xa6, 0x3f, 0xcc, 0x3c, 0x08, 0xe9, 0x1c, 0x1d, 0x8e, 0xdd, + 0x91, 0xcf, 0x6f, 0xe8, 0x45, 0xf8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_103_private[] = { +/* dIUT */ + 0x01, 0x2f, 0x2e, 0x0c, 0x6d, 0x9e, 0x9d, 0x11, 0x7c, 0xeb, 0x97, 0x23, + 0xbc, 0xed, 0x02, 0xeb, 0x3d, 0x4e, 0xeb, 0xf5, 0xfe, 0xea, 0xf8, 0xee, + 0x01, 0x13, 0xcc, 0xd8, 0x05, 0x7b, 0x13, 0xdd, 0xd4, 0x16, 0xe0, 0xb7, + 0x42, 0x80, 0xc2, 0xd0, 0xba, 0x8e, 0xd2, 0x91, 0xc4, 0x43, 0xbc, 0x1b, + 0x14, 0x1c, 0xaf, 0x8a, 0xfb, 0x3a, 0x71, 0xf9, 0x7f, 0x57, 0xc2, 0x25, + 0xc0, 0x3e, 0x1e, 0x4d, 0x42, 0xb0 +}; +/* QIUTx = 000000717fcb3d4a40d103871ede044dc803db508aaa4ae74b70b9fb8d8dfd84bfecfad17871879698c292d2fd5e17b4f9343636c531a4fac68a35a93665546b9a878679 */ +/* QIUTy = 000000f3d96a8637036993ab5d244500fff9d2772112826f6436603d3eb234a44d5c4e5c577234679c4f9df725ee5b9118f23d8a58d0cc01096daf70e8dfec0128bdc2e8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_103_out[] = { +/* ZIUT */ + 0x00, 0x6b, 0x38, 0x0a, 0x6e, 0x95, 0x67, 0x92, 0x77, 0xcf, 0xee, 0x4e, + 0x83, 0x53, 0xbf, 0x96, 0xef, 0x2a, 0x1e, 0xbd, 0xd0, 0x60, 0x74, 0x9f, + 0x2f, 0x04, 0x6f, 0xe5, 0x71, 0x05, 0x37, 0x40, 0xbb, 0xcc, 0x9a, 0x0b, + 0x55, 0x79, 0x0b, 0xc9, 0xab, 0x56, 0xc3, 0x20, 0x8a, 0xa0, 0x5d, 0xdf, + 0x74, 0x6a, 0x10, 0xa3, 0xad, 0x69, 0x4d, 0xaa, 0xe0, 0x0d, 0x98, 0x0d, + 0x94, 0x4a, 0xab, 0xc6, 0xa0, 0x8f +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_104_public_x[] = { +/* QCAVSx */ + 0x00, 0xfd, 0xd4, 0x0d, 0x9e, 0x9d, 0x97, 0x40, 0x27, 0xcb, 0x3b, 0xae, + 0x68, 0x21, 0x62, 0xea, 0xc1, 0x32, 0x8a, 0xd6, 0x1b, 0xc4, 0x35, 0x3c, + 0x45, 0xbf, 0x5a, 0xfe, 0x76, 0xbf, 0x60, 0x7d, 0x28, 0x94, 0xc8, 0xcc, + 0xe2, 0x36, 0x95, 0xd9, 0x20, 0xf2, 0x46, 0x4f, 0xda, 0x47, 0x73, 0xd4, + 0x69, 0x3b, 0xe4, 0xb3, 0x77, 0x35, 0x84, 0x69, 0x1b, 0xdb, 0x03, 0x29, + 0xb7, 0xf4, 0xc8, 0x6c, 0xc2, 0x99 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_104_public_y[] = { +/* QCAVSy */ + 0x00, 0x34, 0xce, 0xac, 0x6a, 0x3f, 0xef, 0x1c, 0x3e, 0x1c, 0x49, 0x4b, + 0xfe, 0x8d, 0x87, 0x2b, 0x18, 0x38, 0x32, 0x21, 0x9a, 0x7e, 0x14, 0xda, + 0x41, 0x4d, 0x4e, 0x34, 0x74, 0x57, 0x36, 0x71, 0xec, 0x19, 0xb0, 0x33, + 0xbe, 0x83, 0x1b, 0x91, 0x54, 0x35, 0x90, 0x59, 0x25, 0xb4, 0x49, 0x47, + 0xc5, 0x92, 0x95, 0x99, 0x45, 0xb4, 0xeb, 0x7c, 0x95, 0x1c, 0x3b, 0x9c, + 0x8c, 0xf5, 0x25, 0x30, 0xba, 0x23 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_104_private[] = { +/* dIUT */ + 0x00, 0xe5, 0x48, 0xa7, 0x9d, 0x8b, 0x05, 0xf9, 0x23, 0xb9, 0x82, 0x5d, + 0x11, 0xb6, 0x56, 0xf2, 0x22, 0xe8, 0xcb, 0x98, 0xb0, 0xf8, 0x9d, 0xe1, + 0xd3, 0x17, 0x18, 0x4d, 0xc5, 0xa6, 0x98, 0xf7, 0xc7, 0x11, 0x61, 0xee, + 0x7d, 0xc1, 0x1c, 0xd3, 0x1f, 0x4f, 0x4f, 0x8a, 0xe3, 0xa9, 0x81, 0xe1, + 0xa3, 0xe7, 0x8b, 0xde, 0xbb, 0x97, 0xd7, 0xc2, 0x04, 0xb9, 0x26, 0x1b, + 0x4e, 0xf9, 0x2e, 0x09, 0x18, 0xe0 +}; +/* QIUTx = 0000000ce800217ed243dd10a79ad73df578aa8a3f9194af528cd1094bbfee27a3b5481ad5862c8876c0c3f91294c0ab3aa806d9020cbaa2ed72b7fecdc5a09a6dad6f32 */ +/* QIUTy = 000001543c9ab45b12469232918e21d5a351f9a4b9cbf9efb2afcc402fa9b31650bec2d641a05c440d35331c0893d11fb13151335988b303341301a73dc5f61d574e67d9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_104_out[] = { +/* ZIUT */ + 0x00, 0xfb, 0xbc, 0xd0, 0xb8, 0xd0, 0x53, 0x31, 0xfe, 0xf6, 0x08, 0x6f, + 0x22, 0xa6, 0xcc, 0xe4, 0xd3, 0x57, 0x24, 0xab, 0x7a, 0x2f, 0x49, 0xdd, + 0x84, 0x58, 0xd0, 0xbf, 0xd5, 0x7a, 0x0b, 0x8b, 0x70, 0xf2, 0x46, 0xc1, + 0x7c, 0x44, 0x68, 0xc0, 0x76, 0x87, 0x4b, 0x0d, 0xff, 0x7a, 0x03, 0x36, + 0x82, 0x3b, 0x19, 0xe9, 0x8b, 0xf1, 0xce, 0xc0, 0x5e, 0x4b, 0xef, 0xfb, + 0x05, 0x91, 0xf9, 0x77, 0x13, 0xc6 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_105_public_x[] = { +/* QCAVSx */ + 0x00, 0x98, 0xd9, 0x9d, 0xee, 0x08, 0x16, 0x55, 0x0e, 0x84, 0xdb, 0xfc, + 0xed, 0x7e, 0x88, 0x13, 0x7f, 0xdd, 0xcf, 0x58, 0x1a, 0x72, 0x5a, 0x45, + 0x50, 0x21, 0x11, 0x5f, 0xe4, 0x9f, 0x8d, 0xc3, 0xcf, 0x23, 0x3c, 0xd9, + 0xea, 0x0e, 0x6f, 0x03, 0x9d, 0xc7, 0x91, 0x9d, 0xa9, 0x73, 0xcd, 0xce, + 0xac, 0xa2, 0x05, 0xda, 0x39, 0xe0, 0xbd, 0x98, 0xc8, 0x06, 0x25, 0x36, + 0xc4, 0x7f, 0x25, 0x8f, 0x44, 0xb5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_105_public_y[] = { +/* QCAVSy */ + 0x00, 0xcd, 0x22, 0x5c, 0x87, 0x97, 0x37, 0x1b, 0xe0, 0xc4, 0x29, 0x7d, + 0x2b, 0x45, 0x77, 0x40, 0x10, 0x0c, 0x77, 0x41, 0x41, 0xd8, 0xf2, 0x14, + 0xc2, 0x3b, 0x61, 0xaa, 0x2b, 0x6c, 0xd4, 0x80, 0x6b, 0x9b, 0x70, 0x72, + 0x2a, 0xa4, 0x96, 0x5f, 0xb6, 0x22, 0xf4, 0x2b, 0x73, 0x91, 0xe2, 0x7e, + 0x5e, 0xc2, 0x1c, 0x56, 0x79, 0xc5, 0xb0, 0x6b, 0x59, 0x12, 0x73, 0x72, + 0x99, 0x7d, 0x42, 0x1a, 0xdc, 0x1e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_105_private[] = { +/* dIUT */ + 0x01, 0xc8, 0xaa, 0xe9, 0x4b, 0xb1, 0x0b, 0x8c, 0xa4, 0xf7, 0xbe, 0x57, + 0x7b, 0x4f, 0xb3, 0x2b, 0xb2, 0x38, 0x10, 0x32, 0xc4, 0x94, 0x2c, 0x24, + 0xfc, 0x2d, 0x75, 0x3e, 0x7c, 0xc5, 0xe4, 0x7b, 0x48, 0x33, 0x89, 0xd9, + 0xf3, 0xb9, 0x56, 0xd2, 0x0e, 0xe9, 0x00, 0x1b, 0x1e, 0xef, 0x9f, 0x23, + 0x54, 0x5f, 0x72, 0xc5, 0x60, 0x21, 0x40, 0x04, 0x68, 0x39, 0xe9, 0x63, + 0x31, 0x3c, 0x3d, 0xec, 0xc8, 0x64 +}; +/* QIUTx = 00000106a14e2ee8ff970aa8ab0c79b97a33bba2958e070b75b94736b77bbe3f777324fa52872771aa88a63a9e8490c3378df4dc760cd14d62be700779dd1a4377943656 */ +/* QIUTy = 0000002366ce3941e0b284b1aa81215d0d3b9778fce23c8cd1e4ed6fa0abf62156c91d4b3eb55999c3471bed275e9e60e5aa9d690d310bfb15c9c5bbd6f5e9eb39682b74 */ +static const uint8_t nist_kas_ecc_cdh_testvector_105_out[] = { +/* ZIUT */ + 0x01, 0x45, 0xcf, 0xa3, 0x8f, 0x25, 0x94, 0x35, 0x16, 0xc9, 0x6a, 0x5f, + 0xd4, 0xbf, 0xeb, 0xb2, 0xf6, 0x45, 0xd1, 0x05, 0x20, 0x11, 0x7a, 0xa5, + 0x19, 0x71, 0xef, 0xf4, 0x42, 0x80, 0x8a, 0x23, 0xb4, 0xe2, 0x3c, 0x18, + 0x7e, 0x63, 0x9f, 0xf9, 0x28, 0xc3, 0x72, 0x5f, 0xbd, 0x1c, 0x0c, 0x2a, + 0xd0, 0xd4, 0xae, 0xb2, 0x07, 0xbc, 0x1a, 0x6f, 0xb6, 0xcb, 0x6d, 0x46, + 0x78, 0x88, 0xdc, 0x04, 0x4b, 0x3c +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_106_public_x[] = { +/* QCAVSx */ + 0x00, 0x7a, 0xe1, 0x15, 0xad, 0xaa, 0xf0, 0x41, 0x69, 0x1a, 0xb6, 0xb7, + 0xfb, 0x8c, 0x92, 0x1f, 0x99, 0xd8, 0xed, 0x32, 0xd2, 0x83, 0xd6, 0x70, + 0x84, 0xe8, 0x0b, 0x9a, 0xd9, 0xc4, 0x0c, 0x56, 0xcd, 0x98, 0x38, 0x9f, + 0xb0, 0xa8, 0x49, 0xd9, 0xec, 0xf7, 0x26, 0x8c, 0x29, 0x7b, 0x6f, 0x93, + 0x40, 0x61, 0x19, 0xf4, 0x0e, 0x32, 0xb5, 0x77, 0x3e, 0xd2, 0x5a, 0x28, + 0xa9, 0xa8, 0x5c, 0x4a, 0x75, 0x88 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_106_public_y[] = { +/* QCAVSy */ + 0x01, 0xa2, 0x8e, 0x00, 0x4e, 0x37, 0xee, 0xae, 0xfe, 0x1f, 0x4d, 0xbb, + 0x71, 0xf1, 0x87, 0x86, 0x96, 0x14, 0x1a, 0xf3, 0xa1, 0x0a, 0x96, 0x91, + 0xc4, 0xed, 0x93, 0x48, 0x72, 0x14, 0x64, 0x3b, 0x76, 0x1f, 0xa4, 0xb0, + 0xfb, 0xee, 0xb2, 0x47, 0xcf, 0x6d, 0x3f, 0xba, 0x7a, 0x60, 0x69, 0x75, + 0x36, 0xad, 0x03, 0xf4, 0x9b, 0x80, 0xa9, 0xd1, 0xcb, 0x07, 0x96, 0x73, + 0x65, 0x49, 0x77, 0xc5, 0xfa, 0x94 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_106_private[] = { +/* dIUT */ + 0x00, 0x9b, 0x0a, 0xf1, 0x37, 0xc9, 0x69, 0x6c, 0x75, 0xb7, 0xe6, 0xdf, + 0x7b, 0x73, 0x15, 0x6b, 0xb2, 0xd4, 0x5f, 0x48, 0x2e, 0x5a, 0x42, 0x17, + 0x32, 0x4f, 0x47, 0x8b, 0x10, 0xce, 0xb7, 0x6a, 0xf0, 0x97, 0x24, 0xcf, + 0x86, 0xaf, 0xa3, 0x16, 0xe7, 0xf8, 0x99, 0x18, 0xd3, 0x1d, 0x54, 0x82, + 0x4a, 0x5c, 0x33, 0x10, 0x7a, 0x48, 0x3c, 0x15, 0xc1, 0x5b, 0x96, 0xed, + 0xc6, 0x61, 0x34, 0x0b, 0x1c, 0x0e +}; +/* QIUTx = 000000748cdbb875d35f4bccb62abe20e82d32e4c14dc2feb5b87da2d0ccb11c9b6d4b7737b6c46f0dfb4d896e2db92fcf53cdbbae2a404c0babd564ad7adeac6273efa3 */ +/* QIUTy = 000001984acab8d8f173323de0bb60274b228871609373bb22a17287e9dec7495873abc09a8915b54c8455c8e02f654f602e23a2bbd7a9ebb74f3009bd65ecc650814cc0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_106_out[] = { +/* ZIUT */ + 0x00, 0x5c, 0x57, 0x21, 0xe9, 0x6c, 0x27, 0x33, 0x19, 0xfd, 0x60, 0xec, + 0xc4, 0x6b, 0x59, 0x62, 0xf6, 0x98, 0xe9, 0x74, 0xb4, 0x29, 0xf2, 0x8f, + 0xe6, 0x96, 0x2f, 0x4a, 0xc6, 0x56, 0xbe, 0x2e, 0xb8, 0x67, 0x4c, 0x4a, + 0xaf, 0xc0, 0x37, 0xea, 0xb4, 0x8e, 0xce, 0x61, 0x29, 0x53, 0xb1, 0xe8, + 0xd8, 0x61, 0x01, 0x6b, 0x6a, 0xd0, 0xc7, 0x98, 0x05, 0x78, 0x4c, 0x67, + 0xf7, 0x3a, 0xda, 0x96, 0xf3, 0x51 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_107_public_x[] = { +/* QCAVSx */ + 0x01, 0x25, 0x88, 0x11, 0x5e, 0x6f, 0x7f, 0x7b, 0xdc, 0xfd, 0xf5, 0x7f, + 0x03, 0xb1, 0x69, 0xb4, 0x79, 0x75, 0x8b, 0xaa, 0xfd, 0xaf, 0x56, 0x9d, + 0x04, 0x13, 0x59, 0x87, 0xb2, 0xce, 0x61, 0x64, 0xc0, 0x2a, 0x57, 0x68, + 0x5e, 0xb5, 0x27, 0x6b, 0x5d, 0xae, 0x62, 0x95, 0xd3, 0xfe, 0x90, 0x62, + 0x0f, 0x38, 0xb5, 0x53, 0x5c, 0x6d, 0x22, 0x60, 0xc1, 0x73, 0xe6, 0x1e, + 0xb8, 0x88, 0xca, 0x92, 0x02, 0x03 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_107_public_y[] = { +/* QCAVSy */ + 0x01, 0x54, 0x2c, 0x16, 0x9c, 0xf9, 0x7c, 0x25, 0x96, 0xfe, 0x2d, 0xdd, + 0x84, 0x8a, 0x22, 0x2e, 0x36, 0x7c, 0x5f, 0x7e, 0x62, 0x67, 0xeb, 0xc1, + 0xbc, 0xd9, 0xab, 0x5d, 0xcf, 0x49, 0x15, 0x8f, 0x1a, 0x48, 0xe4, 0xaf, + 0x29, 0xa8, 0x97, 0xb7, 0xe6, 0xa8, 0x20, 0x91, 0xc2, 0xdb, 0x87, 0x4d, + 0x8e, 0x7a, 0xbf, 0x0f, 0x58, 0x06, 0x46, 0x91, 0x34, 0x41, 0x54, 0xf3, + 0x96, 0xdb, 0xae, 0xd1, 0x88, 0xb6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_107_private[] = { +/* dIUT */ + 0x01, 0xe4, 0x8f, 0xaa, 0xce, 0xe6, 0xde, 0xc8, 0x3f, 0xfc, 0xde, 0x94, + 0x4c, 0xf6, 0xbd, 0xf4, 0xce, 0x4b, 0xae, 0x72, 0x74, 0x78, 0x88, 0xeb, + 0xaf, 0xee, 0x45, 0x5b, 0x1e, 0x91, 0x58, 0x49, 0x71, 0xef, 0xb4, 0x91, + 0x27, 0x97, 0x6a, 0x52, 0xf4, 0x14, 0x29, 0x52, 0xf7, 0xc2, 0x07, 0xec, + 0x02, 0x65, 0xf2, 0xb7, 0x18, 0xcf, 0x3e, 0xad, 0x96, 0xea, 0x4f, 0x62, + 0xc7, 0x52, 0xe4, 0xf7, 0xac, 0xd3 +}; +/* QIUTx = 0000010eb1b4d9172bcc23f4f20cc9560fc54928c3f34ea61c00391dc766c76ed9fa608449377d1e4fadd1236025417330b4b91086704ace3e4e6484c606e2a943478c86 */ +/* QIUTy = 00000149413864069825ee1d0828da9f4a97713005e9bd1adbc3b38c5b946900721a960fe96ad2c1b3a44fe3de9156136d44cb17cbc2415729bb782e16bfe2deb3069e43 */ +static const uint8_t nist_kas_ecc_cdh_testvector_107_out[] = { +/* ZIUT */ + 0x01, 0x73, 0x6d, 0x97, 0x17, 0x42, 0x9b, 0x4f, 0x41, 0x2e, 0x90, 0x3f, + 0xeb, 0xe2, 0xf9, 0xe0, 0xff, 0xfd, 0x81, 0x35, 0x5d, 0x6c, 0xe2, 0xc0, + 0x6f, 0xf3, 0xf6, 0x6a, 0x3b, 0xe1, 0x5c, 0xee, 0xc6, 0xe6, 0x5e, 0x30, + 0x83, 0x47, 0x59, 0x3f, 0x00, 0xd7, 0xf3, 0x35, 0x91, 0xda, 0x40, 0x43, + 0xc3, 0x07, 0x63, 0xd7, 0x27, 0x49, 0xf7, 0x2c, 0xdc, 0xee, 0xbe, 0x82, + 0x5e, 0x4b, 0x34, 0xec, 0xd5, 0x70 +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_108_public_x[] = { +/* QCAVSx */ + 0x01, 0x69, 0x49, 0x1d, 0x55, 0xbd, 0x09, 0x04, 0x9f, 0xdf, 0x4c, 0x2a, + 0x53, 0xa6, 0x60, 0x48, 0x0f, 0xee, 0x4c, 0x03, 0xa0, 0x53, 0x86, 0x75, + 0xd1, 0xcd, 0x09, 0xb5, 0xbb, 0xa7, 0x8d, 0xac, 0x48, 0x54, 0x3e, 0xf1, + 0x18, 0xa1, 0x17, 0x3b, 0x3f, 0xbf, 0x8b, 0x20, 0xe3, 0x9c, 0xe0, 0xe6, + 0xb8, 0x90, 0xa1, 0x63, 0xc5, 0x0f, 0x96, 0x45, 0xb3, 0xd2, 0x1d, 0x1c, + 0xbb, 0x3b, 0x60, 0xa6, 0xff, 0xf4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_108_public_y[] = { +/* QCAVSy */ + 0x00, 0x83, 0x49, 0x4b, 0x2e, 0xba, 0x76, 0x91, 0x0f, 0xed, 0x33, 0xc7, + 0x61, 0x80, 0x45, 0x15, 0x01, 0x1f, 0xab, 0x50, 0xe3, 0xb3, 0x77, 0xab, + 0xd8, 0xa8, 0xa0, 0x45, 0xd8, 0x86, 0xd2, 0x23, 0x8d, 0x2c, 0x26, 0x8a, + 0xc1, 0xb6, 0xec, 0x88, 0xbd, 0x71, 0xb7, 0xba, 0x78, 0xe2, 0xc3, 0x3c, + 0x15, 0x2e, 0x4b, 0xf7, 0xda, 0x5d, 0x56, 0x5e, 0x4a, 0xcb, 0xec, 0xf5, + 0xe9, 0x2c, 0x7a, 0xd6, 0x62, 0xbb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_108_private[] = { +/* dIUT */ + 0x00, 0xc2, 0x9a, 0xa2, 0x23, 0xea, 0x8d, 0x64, 0xb4, 0xa1, 0xed, 0xa2, + 0x7f, 0x39, 0xd3, 0xbc, 0x98, 0xea, 0x01, 0x48, 0xdd, 0x98, 0xc1, 0xcb, + 0xe5, 0x95, 0xf8, 0xfd, 0x2b, 0xfb, 0xde, 0x11, 0x9c, 0x9e, 0x01, 0x7a, + 0x50, 0xf5, 0xd1, 0xfc, 0x12, 0x1c, 0x08, 0xc1, 0xce, 0xf3, 0x1b, 0x75, + 0x88, 0x59, 0x55, 0x6e, 0xb3, 0xe0, 0xe0, 0x42, 0xd8, 0xdd, 0x6a, 0xaa, + 0xc5, 0x7a, 0x05, 0xca, 0x61, 0xe3 +}; +/* QIUTx = 0000001511c848ef60d5419a98d10204db0fe58224124370061bcfa4e9249d50618c56bf3722471b259f38263bb7b280d23caf2a1ee8737f9371cdb2732cdc958369930c */ +/* QIUTy = 000001d461681ae6d8c49b4c5f4d6016143fb1bd7491573e3ed0e6c48b82e821644f87f82f0e5f08fd16f1f98fa17586200ab02ed8c627b35c3f27617ec5fd92f456203f */ +static const uint8_t nist_kas_ecc_cdh_testvector_108_out[] = { +/* ZIUT */ + 0x01, 0x8f, 0x2a, 0xe9, 0x47, 0x6c, 0x77, 0x17, 0x26, 0xa7, 0x77, 0x80, + 0x20, 0x8d, 0xed, 0xfe, 0xfa, 0x20, 0x54, 0x88, 0x99, 0x6b, 0x18, 0xfe, + 0xcc, 0x50, 0xbf, 0xd4, 0xc1, 0x32, 0x75, 0x3f, 0x57, 0x66, 0xb2, 0xcd, + 0x74, 0x4a, 0xfa, 0x99, 0x18, 0x60, 0x6d, 0xe2, 0xe0, 0x16, 0xef, 0xfc, + 0x63, 0x62, 0x2e, 0x90, 0x29, 0xe7, 0x6d, 0xc6, 0xe3, 0xf0, 0xc6, 0x9f, + 0x7a, 0xec, 0xed, 0x56, 0x5c, 0x2c +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_109_public_x[] = { +/* QCAVSx */ + 0x00, 0x84, 0x15, 0xf5, 0xbb, 0xd0, 0xee, 0xe3, 0x87, 0xd6, 0xc0, 0x9d, + 0x0e, 0xf8, 0xac, 0xaf, 0x29, 0xc6, 0x6d, 0xb4, 0x5d, 0x6b, 0xa1, 0x01, + 0x86, 0x0a, 0xe4, 0x5d, 0x3c, 0x60, 0xe1, 0xe0, 0xe3, 0xf7, 0x24, 0x7a, + 0x46, 0x26, 0xa6, 0x0f, 0xdd, 0x40, 0x49, 0x65, 0xc3, 0x56, 0x6c, 0x79, + 0xf6, 0x44, 0x9e, 0x85, 0x6c, 0xe0, 0xbf, 0x94, 0x61, 0x9f, 0x97, 0xda, + 0x8d, 0xa2, 0x4b, 0xd2, 0xcf, 0xb6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_109_public_y[] = { +/* QCAVSy */ + 0x00, 0xfd, 0xd7, 0xc5, 0x9c, 0x58, 0xc3, 0x61, 0xbc, 0x50, 0xa7, 0xa5, + 0xd0, 0xd3, 0x6f, 0x72, 0x3b, 0x17, 0xc4, 0xf2, 0xad, 0x2b, 0x03, 0xc2, + 0x4d, 0x42, 0xdc, 0x50, 0xf7, 0x4a, 0x8c, 0x46, 0x5a, 0x0a, 0xfc, 0x46, + 0x83, 0xf1, 0x0f, 0xab, 0x84, 0x65, 0x2d, 0xfe, 0x9e, 0x92, 0x8c, 0x26, + 0x26, 0xb5, 0x45, 0x64, 0x53, 0xe1, 0x57, 0x3f, 0xf6, 0x0b, 0xe1, 0x50, + 0x74, 0x67, 0xd4, 0x31, 0xfb, 0xb2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_109_private[] = { +/* dIUT */ + 0x00, 0x28, 0x69, 0x2b, 0xe2, 0xbf, 0x5c, 0x4b, 0x48, 0x93, 0x98, 0x46, + 0xfb, 0x3d, 0x5b, 0xce, 0x74, 0x65, 0x4b, 0xb2, 0x64, 0x6e, 0x15, 0xf8, + 0x38, 0x9e, 0x23, 0x70, 0x8a, 0x1a, 0xfa, 0xdf, 0x56, 0x15, 0x11, 0xea, + 0x0d, 0x99, 0x57, 0xd0, 0xb5, 0x34, 0x53, 0x81, 0x9d, 0x60, 0xfb, 0xa8, + 0xf6, 0x5a, 0x18, 0xf7, 0xb2, 0x9d, 0xf0, 0x21, 0xb1, 0xbb, 0x01, 0xcd, + 0x16, 0x32, 0x93, 0xac, 0xc3, 0xcc +}; +/* QIUTx = 000001cfdc10c799f5c79cb6930a65fba351748e07567993e5e410ef4cacc4cd8a25784991eb4674e41050f930c7190ac812b9245f48a7973b658daf408822fe5b85f668 */ +/* QIUTy = 00000180d9ddfc9af77b9c4a6f02a834db15e535e0b3845b2cce30388301b51cecbe3276307ef439b5c9e6a72dc2d94d879bc395052dbb4a5787d06efb280210fb8be037 */ +static const uint8_t nist_kas_ecc_cdh_testvector_109_out[] = { +/* ZIUT */ + 0x01, 0x05, 0xa3, 0x46, 0x98, 0x8b, 0x92, 0xed, 0x8c, 0x7a, 0x25, 0xce, + 0x4d, 0x79, 0xd2, 0x1b, 0xc8, 0x6c, 0xfc, 0xc7, 0xf9, 0x9c, 0x6c, 0xd1, + 0x9d, 0xbb, 0x4a, 0x39, 0xf4, 0x8a, 0xb9, 0x43, 0xb7, 0x9e, 0x4f, 0x06, + 0x47, 0x34, 0x8d, 0xa0, 0xb8, 0x0b, 0xd8, 0x64, 0xb8, 0x5c, 0x6b, 0x8d, + 0x92, 0x53, 0x6d, 0x6a, 0xa5, 0x44, 0xdc, 0x75, 0x37, 0xa0, 0x0c, 0x85, + 0x8f, 0x8b, 0x66, 0x31, 0x9e, 0x25 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_110_public_x[] = { +/* QCAVSx */ + 0x01, 0xc7, 0x21, 0xee, 0xa8, 0x05, 0xa5, 0xcb, 0xa2, 0x9f, 0x34, 0xba, + 0x57, 0x58, 0x77, 0x5b, 0xe0, 0xcf, 0x61, 0x60, 0xe6, 0xc0, 0x87, 0x23, + 0xf5, 0xab, 0x17, 0xbf, 0x96, 0xa1, 0xff, 0x2b, 0xd9, 0x42, 0x79, 0x61, + 0xa4, 0xf3, 0x4b, 0x07, 0xfc, 0x0b, 0x14, 0xca, 0x4b, 0x2b, 0xf6, 0x84, + 0x5d, 0xeb, 0xd5, 0xa8, 0x69, 0xf1, 0x24, 0xeb, 0xfa, 0x7a, 0xa7, 0x2f, + 0xe5, 0x65, 0x05, 0x0b, 0x7f, 0x18 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_110_public_y[] = { +/* QCAVSy */ + 0x00, 0xb6, 0xe8, 0x9e, 0xb0, 0xe1, 0xdc, 0xf1, 0x81, 0x23, 0x6f, 0x7c, + 0x54, 0x8f, 0xd1, 0xa8, 0xc1, 0x6b, 0x25, 0x8b, 0x52, 0xc1, 0xa9, 0xbf, + 0xd3, 0xfe, 0x8f, 0x22, 0x84, 0x1b, 0x26, 0x76, 0x32, 0x65, 0xf0, 0x74, + 0xc4, 0xcc, 0xf2, 0xd6, 0x34, 0xae, 0x97, 0xb7, 0x01, 0x95, 0x6f, 0x67, + 0xa1, 0x10, 0x06, 0xc5, 0x2d, 0x97, 0x19, 0x7d, 0x92, 0xf5, 0x85, 0xf5, + 0x74, 0x8b, 0xc2, 0x67, 0x2e, 0xeb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_110_private[] = { +/* dIUT */ + 0x01, 0x19, 0x4d, 0x1e, 0xe6, 0x13, 0xf5, 0x36, 0x6c, 0xbc, 0x44, 0xb5, + 0x04, 0xd2, 0x1a, 0x0c, 0xf6, 0x71, 0x5e, 0x20, 0x9c, 0xd3, 0x58, 0xf2, + 0xdd, 0x5f, 0x3e, 0x71, 0xcc, 0x0d, 0x67, 0xd0, 0xe9, 0x64, 0x16, 0x8c, + 0x42, 0xa0, 0x84, 0xeb, 0xda, 0x74, 0x6f, 0x98, 0x63, 0xa8, 0x6b, 0xac, + 0xff, 0xc8, 0x19, 0xf1, 0xed, 0xf1, 0xb8, 0xc7, 0x27, 0xcc, 0xfb, 0x30, + 0x47, 0x24, 0x0a, 0x57, 0xc4, 0x35 +}; +/* QIUTx = 0000016bd15c8a58d366f7f2b2f298cc87b7485e9ee70d11d12448b8377c0a82c7626f67aff7f97be7a3546bf417eeeddf75a93c130191c84108042ea2fca17fd3f80d14 */ +/* QIUTy = 000001560502d04b74fce1743aab477a9d1eac93e5226981fdb97a7478ce4ce566ff7243931284fad850b0c2bcae0ddd2d97790160c1a2e77c3ed6c95ecc44b89e2637fc */ +static const uint8_t nist_kas_ecc_cdh_testvector_110_out[] = { +/* ZIUT */ + 0x00, 0x45, 0x31, 0xb3, 0xd2, 0xc6, 0xcd, 0x12, 0xf2, 0x16, 0x04, 0xc8, + 0x61, 0x0e, 0x67, 0x23, 0xdb, 0xf4, 0xda, 0xf8, 0x0b, 0x5a, 0x45, 0x9d, + 0x6b, 0xa5, 0x81, 0x43, 0x97, 0xd1, 0xc1, 0xf7, 0xa2, 0x1d, 0x7c, 0x11, + 0x4b, 0xe9, 0x64, 0xe2, 0x73, 0x76, 0xaa, 0xeb, 0xe3, 0xa7, 0xbc, 0x3d, + 0x6a, 0xf7, 0xa7, 0xf8, 0xc7, 0xbe, 0xfb, 0x61, 0x1a, 0xfe, 0x48, 0x7f, + 0xf0, 0x32, 0x92, 0x1f, 0x75, 0x0f +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_111_public_x[] = { +/* QCAVSx */ + 0x01, 0xc3, 0x58, 0x23, 0xe4, 0x40, 0xa9, 0x36, 0x3a, 0xb9, 0x8d, 0x9f, + 0xc7, 0xa7, 0xbc, 0x0c, 0x05, 0x32, 0xdc, 0x79, 0x77, 0xa7, 0x91, 0x65, + 0x59, 0x9b, 0xf1, 0xa9, 0xcc, 0x64, 0xc0, 0x0f, 0xb3, 0x87, 0xb4, 0x2c, + 0xca, 0x36, 0x52, 0x86, 0xe8, 0x43, 0x03, 0x60, 0xbf, 0xad, 0x36, 0x43, + 0xbc, 0x31, 0x35, 0x4e, 0xda, 0x50, 0xdc, 0x93, 0x6c, 0x32, 0x9e, 0xcd, + 0xb6, 0x09, 0x05, 0xc4, 0x0f, 0xcb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_111_public_y[] = { +/* QCAVSy */ + 0x00, 0xd9, 0xe7, 0xf4, 0x33, 0x53, 0x1e, 0x44, 0xdf, 0x4f, 0x6d, 0x51, + 0x42, 0x01, 0xcb, 0xaa, 0xbb, 0x06, 0xba, 0xdd, 0x67, 0x83, 0xe0, 0x11, + 0x11, 0x72, 0x6d, 0x81, 0x55, 0x31, 0xd2, 0x33, 0xc5, 0xcd, 0xb7, 0x22, + 0x89, 0x3f, 0xfb, 0xb2, 0x02, 0x72, 0x59, 0xd5, 0x94, 0xde, 0x77, 0x43, + 0x88, 0x09, 0x73, 0x81, 0x20, 0xc6, 0xf7, 0x83, 0x93, 0x4f, 0x92, 0x6c, + 0x3f, 0xb6, 0x9b, 0x40, 0xc4, 0x09 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_111_private[] = { +/* dIUT */ + 0x01, 0xfd, 0x90, 0xe3, 0xe4, 0x16, 0xe9, 0x8a, 0xa3, 0xf2, 0xb6, 0xaf, + 0xa7, 0xf3, 0xbf, 0x36, 0x8e, 0x45, 0x1a, 0xd9, 0xca, 0x5b, 0xd5, 0x4b, + 0x5b, 0x14, 0xae, 0xe2, 0xed, 0x67, 0x23, 0xdd, 0xe5, 0x18, 0x1f, 0x50, + 0x85, 0xb6, 0x81, 0x69, 0xb0, 0x9f, 0xbe, 0xc7, 0x21, 0x37, 0x2c, 0xcf, + 0x6b, 0x28, 0x47, 0x13, 0xf9, 0xa6, 0x35, 0x6b, 0x8d, 0x56, 0x0a, 0x8f, + 0xf7, 0x8c, 0xa3, 0x73, 0x7c, 0x88 +}; +/* QIUTx = 000001ebea1b10d3e3b971b7efb69fc878de11c7f472e4e4d384c31b8d6288d8071517acade9b39796c7af5163bcf71aeda777533f382c6cf0a4d9bbb938c85f44b78037 */ +/* QIUTy = 0000016b0e3e19c2996b2cbd1ff64730e7ca90edca1984f9b2951333535e5748baa34a99f61ff4d5f812079e0f01e87789f34efdad8098015ee74a4f846dd190d16dc6e1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_111_out[] = { +/* ZIUT */ + 0x01, 0x00, 0xc8, 0x93, 0x59, 0x69, 0x07, 0x7b, 0xae, 0x0b, 0xa8, 0x9e, + 0xf0, 0xdf, 0x81, 0x61, 0xd9, 0x75, 0xec, 0x58, 0x70, 0xac, 0x81, 0x1a, + 0xe7, 0xe6, 0x5c, 0xa5, 0x39, 0x4e, 0xfb, 0xa4, 0xf0, 0x63, 0x3d, 0x41, + 0xbf, 0x79, 0xea, 0x5e, 0x5b, 0x94, 0x96, 0xbb, 0xd7, 0xaa, 0xe0, 0x00, + 0xb0, 0x59, 0x4b, 0xaa, 0x82, 0xef, 0x8f, 0x24, 0x4e, 0x69, 0x84, 0xae, + 0x87, 0xae, 0x1e, 0xd1, 0x24, 0xb7 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_112_public_x[] = { +/* QCAVSx */ + 0x00, 0x09, 0x30, 0x57, 0xfb, 0x86, 0x2f, 0x2a, 0xd2, 0xe8, 0x2e, 0x58, + 0x1b, 0xae, 0xb3, 0x32, 0x4e, 0x7b, 0x32, 0x94, 0x6f, 0x2b, 0xa8, 0x45, + 0xa9, 0xbe, 0xee, 0xd8, 0x7d, 0x69, 0x95, 0xf5, 0x49, 0x18, 0xec, 0x66, + 0x19, 0xb9, 0x93, 0x19, 0x55, 0xd5, 0xa8, 0x9d, 0x4d, 0x74, 0xad, 0xf1, + 0x04, 0x6b, 0xb3, 0x62, 0x19, 0x2f, 0x2e, 0xf6, 0xbd, 0x3e, 0x3d, 0x2d, + 0x04, 0xdd, 0x1f, 0x87, 0x05, 0x4a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_112_public_y[] = { +/* QCAVSy */ + 0x00, 0xaa, 0x3f, 0xb2, 0x44, 0x83, 0x35, 0xf6, 0x94, 0xe3, 0xcd, 0xa4, + 0xae, 0x0c, 0xc7, 0x1b, 0x1b, 0x2f, 0x2a, 0x20, 0x6f, 0xa8, 0x02, 0xd7, + 0x26, 0x2f, 0x19, 0x98, 0x3c, 0x44, 0x67, 0x4f, 0xe1, 0x53, 0x27, 0xac, + 0xaa, 0xc1, 0xfa, 0x40, 0x42, 0x4c, 0x39, 0x5a, 0x65, 0x56, 0xcb, 0x81, + 0x67, 0x31, 0x25, 0x27, 0xfa, 0xe5, 0x86, 0x5e, 0xcf, 0xfc, 0x14, 0xbb, + 0xdc, 0x17, 0xda, 0x78, 0xcd, 0xcf +}; +static const uint8_t nist_kas_ecc_cdh_testvector_112_private[] = { +/* dIUT */ + 0x00, 0x90, 0x12, 0xec, 0xfd, 0xad, 0xc8, 0x5c, 0xed, 0x63, 0x0a, 0xfe, + 0xa5, 0x34, 0xcd, 0xc8, 0xe9, 0xd1, 0xab, 0x8b, 0xe5, 0xf3, 0x75, 0x3d, + 0xcf, 0x5f, 0x2b, 0x09, 0xb4, 0x0e, 0xda, 0x66, 0xfc, 0x68, 0x58, 0x54, + 0x9b, 0xc3, 0x6e, 0x6f, 0x8d, 0xf5, 0x59, 0x98, 0xcf, 0xa9, 0xa0, 0x70, + 0x3a, 0xec, 0xf6, 0xc4, 0x27, 0x99, 0xc2, 0x45, 0x01, 0x10, 0x64, 0xf5, + 0x30, 0xc0, 0x9d, 0xb9, 0x83, 0x69 +}; +/* QIUTx = 000000234e32be0a907131d2d128a6477e0caceb86f02479745e0fe245cb332de631c078871160482eeef584e274df7fa412cea3e1e91f71ecba8781d9205d48386341ad */ +/* QIUTy = 000001cf86455b09b1c005cffba8d76289a3759628c874beea462f51f30bd581e3803134307dedbb771b3334ee15be2e242cd79c3407d2f58935456c6941dd9b6d155a46 */ +static const uint8_t nist_kas_ecc_cdh_testvector_112_out[] = { +/* ZIUT */ + 0x01, 0x7f, 0x36, 0xaf, 0x19, 0x30, 0x38, 0x41, 0xd1, 0x3a, 0x38, 0x9d, + 0x95, 0xec, 0x0b, 0x80, 0x1c, 0x7f, 0x9a, 0x67, 0x9a, 0x82, 0x31, 0x46, + 0xc7, 0x5c, 0x17, 0xbc, 0x44, 0x25, 0x6e, 0x9a, 0xd4, 0x22, 0xa4, 0xf8, + 0xb3, 0x1f, 0x14, 0x64, 0x7b, 0x2c, 0x7d, 0x31, 0x7b, 0x93, 0x3f, 0x7c, + 0x29, 0x46, 0xc4, 0xb8, 0xab, 0xd1, 0xd5, 0x6d, 0x62, 0x0f, 0xab, 0x1b, + 0x5f, 0xf1, 0xa3, 0xad, 0xc7, 0x1f +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_113_public_x[] = { +/* QCAVSx */ + 0x00, 0x83, 0x19, 0x2e, 0xd0, 0xb1, 0xcb, 0x31, 0xf7, 0x58, 0x17, 0x79, + 0x49, 0x37, 0xf6, 0x6a, 0xd9, 0x1c, 0xf7, 0x45, 0x52, 0xcd, 0x51, 0x0c, + 0xed, 0xb9, 0xfd, 0x64, 0x13, 0x10, 0x42, 0x2a, 0xf5, 0xd0, 0x9f, 0x22, + 0x1c, 0xad, 0x24, 0x9e, 0xe8, 0x14, 0xd1, 0x6d, 0xd7, 0xac, 0x84, 0xde, + 0xd9, 0xea, 0xcd, 0xc2, 0x83, 0x40, 0xfc, 0xfc, 0x9c, 0x0c, 0x06, 0xab, + 0xe3, 0x0a, 0x2f, 0xc2, 0x8c, 0xd8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_113_public_y[] = { +/* QCAVSy */ + 0x00, 0x22, 0x12, 0xed, 0x86, 0x8c, 0x9b, 0xa0, 0xfb, 0x2c, 0x91, 0xe2, + 0xc3, 0x9b, 0xa9, 0x39, 0x96, 0xa3, 0xe4, 0xeb, 0xf4, 0x5f, 0x28, 0x52, + 0xd0, 0x92, 0x8c, 0x48, 0x93, 0x0e, 0x87, 0x5c, 0xc7, 0xb4, 0x28, 0xd0, + 0xe7, 0xf3, 0xf4, 0xd5, 0x03, 0xe5, 0xd6, 0x0c, 0x68, 0xcb, 0x49, 0xb1, + 0x3c, 0x24, 0x80, 0xcd, 0x48, 0x6b, 0xed, 0x92, 0x00, 0xca, 0xdd, 0xad, + 0xdf, 0xe4, 0xff, 0x8e, 0x35, 0x62 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_113_private[] = { +/* dIUT */ + 0x01, 0xb5, 0xff, 0x84, 0x7f, 0x8e, 0xff, 0x20, 0xb8, 0x8c, 0xfa, 0xd4, + 0x2c, 0x06, 0xe5, 0x8c, 0x37, 0x42, 0xf2, 0xf8, 0xf1, 0xfd, 0xfd, 0x64, + 0xb5, 0x39, 0xba, 0x48, 0xc2, 0x59, 0x26, 0x92, 0x6b, 0xd5, 0xe3, 0x32, + 0xb4, 0x56, 0x49, 0xc0, 0xb1, 0x84, 0xf7, 0x72, 0x55, 0xe9, 0xd5, 0x8f, + 0xe8, 0xaf, 0xa1, 0xa6, 0xd9, 0x68, 0xe2, 0xcb, 0x1d, 0x46, 0x37, 0x77, + 0x71, 0x20, 0xc7, 0x65, 0xc1, 0x28 +}; +/* QIUTx = 000001de3dc9263bc8c4969dc684be0eec54befd9a9f3dba194d8658a789341bf0d78d84da6735227cafaf09351951691197573c8c360a11e5285712b8bbdf5ac91b977c */ +/* QIUTy = 000000812de58cd095ec2e5a9b247eb3ed41d8bef6aeace194a7a05b65aa5d289fbc9b1770ec84bb6be0c2c64cc37c1d54a7f5d71377a9adbe20f26f6f2b544a821ea831 */ +static const uint8_t nist_kas_ecc_cdh_testvector_113_out[] = { +/* ZIUT */ + 0x00, 0x06, 0x2f, 0x9f, 0xc2, 0x9a, 0xe1, 0xa6, 0x8b, 0x2e, 0xe0, 0xdc, + 0xf9, 0x56, 0xcb, 0xd3, 0x8c, 0x88, 0xae, 0x5f, 0x64, 0x5e, 0xaa, 0x54, + 0x6b, 0x00, 0xeb, 0xe8, 0x7a, 0x72, 0x60, 0xbf, 0x72, 0x4b, 0xe2, 0x0d, + 0x34, 0xb9, 0xd0, 0x20, 0x76, 0x65, 0x5c, 0x93, 0x3d, 0x05, 0x6b, 0x21, + 0xe3, 0x04, 0xc2, 0x4d, 0xdb, 0x1d, 0xed, 0xf1, 0xdd, 0x76, 0xde, 0x61, + 0x1f, 0xc4, 0xa2, 0x34, 0x03, 0x36 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_114_public_x[] = { +/* QCAVSx */ + 0x01, 0xa8, 0x9b, 0x63, 0x6a, 0x93, 0xe5, 0xd2, 0xba, 0x6c, 0x22, 0x92, + 0xbf, 0x23, 0x03, 0x3a, 0x84, 0xf0, 0x6a, 0x3a, 0xc1, 0x22, 0x0e, 0xa7, + 0x1e, 0x80, 0x6a, 0xfb, 0xe0, 0x97, 0xa8, 0x04, 0xcc, 0x67, 0xe9, 0xba, + 0xa5, 0x14, 0xcf, 0xb6, 0xc1, 0x2c, 0x91, 0x94, 0xbe, 0x30, 0x21, 0x2b, + 0xf7, 0xaa, 0xe7, 0xfd, 0xf6, 0xd3, 0x76, 0xc2, 0x12, 0xf0, 0x55, 0x4e, + 0x65, 0x64, 0x63, 0xff, 0xab, 0x7e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_114_public_y[] = { +/* QCAVSy */ + 0x01, 0x82, 0xef, 0xca, 0xf7, 0x0f, 0xc4, 0x12, 0xd3, 0x36, 0x60, 0x2e, + 0x01, 0x4d, 0xa4, 0x72, 0x56, 0xa0, 0xb6, 0x06, 0xf2, 0xad, 0xdc, 0xce, + 0x80, 0x53, 0xbf, 0x81, 0x7a, 0xc8, 0x65, 0x6b, 0xb4, 0xe4, 0x2f, 0x14, + 0xc8, 0xcb, 0xf2, 0xa6, 0x8f, 0x48, 0x8a, 0xb3, 0x5d, 0xcd, 0xf6, 0x40, + 0x56, 0x27, 0x1d, 0xee, 0x1f, 0x60, 0x6a, 0x44, 0x0b, 0xa4, 0xbd, 0x4e, + 0x5a, 0x11, 0xb8, 0xb8, 0xe5, 0x4f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_114_private[] = { +/* dIUT */ + 0x01, 0x1a, 0x63, 0x47, 0xd4, 0xe8, 0x01, 0xc9, 0x19, 0x23, 0x48, 0x83, + 0x54, 0xcc, 0x53, 0x3e, 0x7e, 0x35, 0xfd, 0xdf, 0x81, 0xff, 0x0f, 0xb7, + 0xf5, 0x6b, 0xb0, 0x72, 0x6e, 0x0c, 0x29, 0xee, 0x5d, 0xcd, 0xc5, 0xf3, + 0x94, 0xba, 0x54, 0xcf, 0x57, 0x26, 0x90, 0x48, 0xaa, 0xb6, 0xe0, 0x55, + 0x89, 0x5c, 0x8d, 0xa2, 0x4b, 0x8b, 0x06, 0x39, 0xa7, 0x42, 0x31, 0x43, + 0x90, 0xcc, 0x04, 0x19, 0x0e, 0xd6 +}; +/* QIUTx = 000000fe30267f33ba5cdefc25cbb3c9320dad9ccb1d7d376644620ca4fadee5626a3cede25ad254624def727a7048f7145f76162aa98042f9b123b2076f8e8cf59b3fdf */ +/* QIUTy = 0000001145dc6631953b6e2945e94301d6cbb098fe4b04f7ee9b09411df104dc82d7d79ec46a01ed0f2d3e7db6eb680694bdeb107c1078aec6cabd9ebee3d342fe7e54df */ +static const uint8_t nist_kas_ecc_cdh_testvector_114_out[] = { +/* ZIUT */ + 0x01, 0x28, 0xab, 0x09, 0xbf, 0xec, 0x54, 0x06, 0x79, 0x9e, 0x61, 0x0f, + 0x77, 0x2b, 0xa1, 0x7e, 0x89, 0x22, 0x49, 0xfa, 0x8e, 0x0e, 0x7b, 0x18, + 0xa0, 0x4b, 0x91, 0x97, 0x03, 0x4b, 0x25, 0x0b, 0x48, 0x29, 0x4f, 0x18, + 0x67, 0xfb, 0x96, 0x41, 0x51, 0x8f, 0x92, 0x76, 0x60, 0x66, 0xa0, 0x7a, + 0x8b, 0x91, 0x7b, 0x0e, 0x76, 0x87, 0x9e, 0x10, 0x11, 0xe5, 0x1c, 0xcb, + 0xd9, 0xf5, 0x40, 0xc5, 0x4d, 0x4f +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_115_public_x[] = { +/* QCAVSx */ + 0x01, 0x72, 0x00, 0xb3, 0xf1, 0x6a, 0x68, 0xcb, 0xae, 0xd2, 0xbf, 0x78, + 0xba, 0x8c, 0xdd, 0xfb, 0x6c, 0xff, 0xac, 0x26, 0x2b, 0xba, 0x00, 0xfb, + 0xc2, 0x5f, 0x9d, 0xc7, 0x2a, 0x07, 0xce, 0x59, 0x37, 0x29, 0x04, 0x89, + 0x9f, 0x36, 0x4c, 0x44, 0xcb, 0x26, 0x4c, 0x09, 0x7b, 0x64, 0x7d, 0x44, + 0x12, 0xbe, 0xe3, 0xe5, 0x19, 0x89, 0x2d, 0x53, 0x4d, 0x91, 0x29, 0xf8, + 0xa2, 0x8f, 0x75, 0x00, 0xfe, 0xe7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_115_public_y[] = { +/* QCAVSy */ + 0x00, 0xba, 0xba, 0x8d, 0x67, 0x2a, 0x4f, 0x4a, 0x3b, 0x63, 0xde, 0x48, + 0xb9, 0x6f, 0x56, 0xe1, 0x8d, 0xf5, 0xd6, 0x8f, 0x7d, 0x70, 0xd5, 0x10, + 0x98, 0x33, 0xf4, 0x37, 0x70, 0xd6, 0x73, 0x2e, 0x06, 0xb3, 0x9a, 0xd6, + 0x0d, 0x93, 0xe5, 0xb4, 0x3d, 0xb8, 0x78, 0x9f, 0x1e, 0xc0, 0xab, 0xa4, + 0x72, 0x86, 0xa3, 0x9e, 0xa5, 0x84, 0x23, 0x5a, 0xce, 0xa7, 0x57, 0xdb, + 0xf1, 0x3d, 0x53, 0xb5, 0x83, 0x64 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_115_private[] = { +/* dIUT */ + 0x00, 0x22, 0xb6, 0xd2, 0xa2, 0x2d, 0x71, 0xdf, 0xaa, 0x81, 0x1d, 0x2d, + 0x9f, 0x9f, 0x31, 0xfb, 0xed, 0x27, 0xf2, 0xe1, 0xf3, 0xd2, 0x39, 0x53, + 0x8d, 0xdf, 0x3e, 0x4c, 0xc8, 0xc3, 0x9a, 0x33, 0x02, 0x66, 0xdb, 0x25, + 0xb7, 0xbc, 0x0a, 0x97, 0x04, 0xf1, 0x7b, 0xde, 0x7f, 0x35, 0x92, 0xbf, + 0x5f, 0x1f, 0x2d, 0x4b, 0x56, 0x01, 0x3a, 0xac, 0xc3, 0xd8, 0xd1, 0xbc, + 0x02, 0xf0, 0x0d, 0x31, 0x46, 0xcc +}; +/* QIUTx = 000000ba38cfbf9fd2518a3f61d43549e7a6a6d28b2be57ffd3e0faceb636b34ed17e044a9f249dae8fc132e937e2d9349cd2ed77bb1049ceb692a2ec5b17ad61502a64c */ +/* QIUTy = 0000001ec91d3058573fa6c0564a02a1a010160c313bc7c73510dc983e5461682b5be00dbce7e2c682ad73f29ca822cdc111f68fabe33a7b384a648342c3cdb9f050bcdb */ +static const uint8_t nist_kas_ecc_cdh_testvector_115_out[] = { +/* ZIUT */ + 0x01, 0x01, 0xe4, 0x62, 0xe9, 0xd9, 0x15, 0x99, 0x68, 0xf6, 0x44, 0x0e, + 0x95, 0x6f, 0x11, 0xdc, 0xf2, 0x22, 0x7a, 0xe4, 0xae, 0xa8, 0x16, 0x67, + 0x12, 0x2b, 0x6a, 0xf9, 0x23, 0x9a, 0x29, 0x1e, 0xb5, 0xd6, 0xcf, 0x5a, + 0x40, 0x87, 0xf3, 0x58, 0x52, 0x5f, 0xca, 0xcf, 0xa4, 0x6b, 0xb2, 0xdb, + 0x01, 0xa7, 0x5a, 0xf1, 0xba, 0x51, 0x9b, 0x2d, 0x31, 0xda, 0x33, 0xed, + 0xa8, 0x7a, 0x9d, 0x56, 0x57, 0x48 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_116_public_x[] = { +/* QCAVSx */ + 0x00, 0x4e, 0xfd, 0x5d, 0xbd, 0x2f, 0x97, 0x9e, 0x38, 0x31, 0xce, 0x98, + 0xf8, 0x23, 0x55, 0xd6, 0xca, 0x14, 0xa5, 0x75, 0x78, 0x42, 0x87, 0x58, + 0x82, 0x99, 0x0a, 0xb8, 0x5a, 0xb9, 0xb7, 0x35, 0x2d, 0xd6, 0xb9, 0xb2, + 0xf4, 0xea, 0x9a, 0x1e, 0x95, 0xc3, 0x88, 0x0d, 0x65, 0xd1, 0xf3, 0x60, + 0x2f, 0x9c, 0xa6, 0x53, 0xdc, 0x34, 0x6f, 0xac, 0x85, 0x86, 0x58, 0xd7, + 0x56, 0x26, 0xf4, 0xd4, 0xfb, 0x08 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_116_public_y[] = { +/* QCAVSy */ + 0x00, 0x61, 0xcf, 0x15, 0xdb, 0xda, 0xa7, 0xf3, 0x15, 0x89, 0xc9, 0x84, + 0x00, 0x37, 0x3d, 0xa2, 0x84, 0x50, 0x6d, 0x70, 0xc8, 0x9f, 0x07, 0x4e, + 0xd2, 0x62, 0xa9, 0xe2, 0x81, 0x40, 0x79, 0x6b, 0x72, 0x36, 0xc2, 0xee, + 0xf9, 0x90, 0x16, 0x08, 0x5e, 0x71, 0x55, 0x2f, 0xf4, 0x88, 0xc7, 0x2b, + 0x73, 0x39, 0xfe, 0xfb, 0x79, 0x15, 0xc3, 0x84, 0x59, 0xcb, 0x20, 0xab, + 0x85, 0xae, 0xc4, 0xe4, 0x50, 0x52 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_116_private[] = { +/* dIUT */ + 0x00, 0x5b, 0xac, 0xff, 0xf2, 0x68, 0xac, 0xf6, 0x55, 0x3c, 0x3c, 0x58, + 0x3b, 0x46, 0x4e, 0xa3, 0x6a, 0x1d, 0x35, 0xe2, 0xb2, 0x57, 0xa5, 0xd4, + 0x9e, 0xb3, 0x41, 0x9d, 0x5a, 0x09, 0x50, 0x87, 0xc2, 0xfb, 0x4d, 0x15, + 0xcf, 0x5b, 0xf5, 0xaf, 0x81, 0x6d, 0x0f, 0x3f, 0xf7, 0x58, 0x64, 0x90, + 0xcc, 0xd3, 0xdd, 0xc1, 0xa9, 0x8b, 0x39, 0xce, 0x63, 0x74, 0x9c, 0x62, + 0x88, 0xce, 0x0d, 0xbd, 0xac, 0x7d +}; +/* QIUTx = 00000036e488da7581472a9d8e628c58d6ad727311b7e6a3f6ae33a8544f34b09280249020be7196916fafd90e2ec54b66b5468d2361b99b56fa00d7ac37abb8c6f16653 */ +/* QIUTy = 0000011edb9fb8adb6a43f4f5f5fdc1421c9fe04fc8ba46c9b66334e3af927c8befb4307104f299acec4e30f812d9345c9720d19869dbfffd4ca3e7d2713eb5fc3f42615 */ +static const uint8_t nist_kas_ecc_cdh_testvector_116_out[] = { +/* ZIUT */ + 0x01, 0x41, 0xd6, 0xa4, 0xb7, 0x19, 0xab, 0x67, 0xea, 0xf0, 0x4a, 0x92, + 0xc0, 0xa4, 0x1e, 0x2d, 0xda, 0x78, 0xf4, 0x35, 0x4f, 0xb9, 0x0b, 0xdc, + 0x35, 0x20, 0x2c, 0xc7, 0x69, 0x9b, 0x9b, 0x04, 0xd4, 0x96, 0x16, 0xf8, + 0x22, 0x55, 0xde, 0xbf, 0x7b, 0xbe, 0xc0, 0x45, 0xae, 0x58, 0xf9, 0x82, + 0xa6, 0x69, 0x05, 0xfc, 0xfa, 0xe6, 0x9d, 0x68, 0x97, 0x85, 0xe3, 0x8c, + 0x86, 0x8e, 0xb4, 0xa2, 0x7e, 0x7b +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_117_public_x[] = { +/* QCAVSx */ + 0x01, 0x29, 0x89, 0x1d, 0xe0, 0xcf, 0x3c, 0xf8, 0x2e, 0x8c, 0x2c, 0xf1, + 0xbf, 0x90, 0xbb, 0x29, 0x6f, 0xe0, 0x0a, 0xb0, 0x8c, 0xa4, 0x5b, 0xb7, + 0x89, 0x2e, 0x0e, 0x22, 0x7a, 0x50, 0x4f, 0xdd, 0x05, 0xd2, 0x38, 0x1a, + 0x44, 0x48, 0xb6, 0x8a, 0xdf, 0xf9, 0xc4, 0x15, 0x3c, 0x87, 0xea, 0xcb, + 0x78, 0x33, 0x0d, 0x8b, 0xd5, 0x25, 0x15, 0xf9, 0xf9, 0xa0, 0xb5, 0x8e, + 0x85, 0xf4, 0x46, 0xbb, 0x4e, 0x10 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_117_public_y[] = { +/* QCAVSy */ + 0x00, 0x9e, 0xdd, 0x67, 0x96, 0x96, 0xd3, 0xd1, 0xd0, 0xef, 0x32, 0x7f, + 0x20, 0x03, 0x83, 0x25, 0x3f, 0x64, 0x13, 0x68, 0x3d, 0x9e, 0x4f, 0xcc, + 0x87, 0xbb, 0x35, 0xf1, 0x12, 0xc2, 0xf1, 0x10, 0x09, 0x8d, 0x15, 0xe5, + 0x70, 0x1d, 0x7c, 0xee, 0xe4, 0x16, 0x29, 0x1f, 0xf5, 0xfe, 0xd8, 0x5e, + 0x68, 0x7f, 0x72, 0x73, 0x88, 0xb9, 0xaf, 0xe2, 0x6a, 0x4f, 0x6f, 0xee, + 0xd5, 0x60, 0xb2, 0x18, 0xe6, 0xbb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_117_private[] = { +/* dIUT */ + 0x00, 0x8e, 0x2c, 0x93, 0xc5, 0x42, 0x38, 0x76, 0x22, 0x3a, 0x63, 0x7c, + 0xad, 0x36, 0x7c, 0x85, 0x89, 0xda, 0x69, 0xa2, 0xd0, 0xfc, 0x68, 0x61, + 0x2f, 0x31, 0x92, 0x3a, 0xe5, 0x02, 0x19, 0xdf, 0x24, 0x52, 0xe7, 0xcc, + 0x92, 0x61, 0x5b, 0x67, 0xf1, 0x7b, 0x57, 0xff, 0xd2, 0xf5, 0x2b, 0x19, + 0x15, 0x4b, 0xb4, 0x0d, 0x77, 0x15, 0x33, 0x64, 0x20, 0xfd, 0xe2, 0xe8, + 0x9f, 0xee, 0x24, 0x4f, 0x59, 0xdc +}; +/* QIUTx = 000000fa3b35118d6c422570f724a26f90b2833b19239174cea081c53133f64db60d6940ea1261299c04c1f4587cdb0c4c39616479c1bb0c146799a118032dcf98f899c0 */ +/* QIUTy = 00000069f040229006151fa32b51f679c8816f7c17506b403809dc77cd58a2aec430d94d13b6c916de99f355aa45fcfbc6853d686c71be496a067d24bfaea4818fc51f75 */ +static const uint8_t nist_kas_ecc_cdh_testvector_117_out[] = { +/* ZIUT */ + 0x00, 0x34, 0x5e, 0x26, 0xe0, 0xab, 0xb1, 0xaa, 0xc1, 0x2b, 0x75, 0xf3, + 0xa9, 0xcf, 0x41, 0xef, 0xe1, 0xc3, 0x36, 0x39, 0x6d, 0xff, 0xa4, 0xa0, + 0x67, 0xa4, 0xc2, 0xcf, 0xeb, 0x87, 0x8c, 0x68, 0xb2, 0xb0, 0x45, 0xfa, + 0xa4, 0xe5, 0xb4, 0xe6, 0xfa, 0x46, 0x78, 0xf5, 0xb6, 0x03, 0xc3, 0x51, + 0x90, 0x3b, 0x14, 0xbf, 0x9a, 0x6a, 0x70, 0xc4, 0x39, 0x25, 0x71, 0x99, + 0xa6, 0x40, 0x89, 0x0b, 0x61, 0xd1 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_118_public_x[] = { +/* QCAVSx */ + 0x01, 0xa3, 0xc2, 0x02, 0x40, 0xe5, 0x9f, 0x5b, 0x7a, 0x3e, 0x17, 0xc2, + 0x75, 0xd2, 0x31, 0x4b, 0xa1, 0x74, 0x12, 0x10, 0xad, 0x58, 0xb7, 0x10, + 0x36, 0xf8, 0xc8, 0x3c, 0xc1, 0xf6, 0xb0, 0xf4, 0x09, 0xdf, 0xdd, 0x91, + 0x13, 0xe9, 0x4b, 0x67, 0xec, 0x39, 0xc3, 0x29, 0x14, 0x26, 0xc2, 0x3f, + 0xfc, 0xc4, 0x47, 0x05, 0x46, 0x70, 0xd2, 0x90, 0x8f, 0xf8, 0xfe, 0x67, + 0xdc, 0x23, 0x06, 0x03, 0x4c, 0x5c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_118_public_y[] = { +/* QCAVSy */ + 0x01, 0xd2, 0x82, 0x5b, 0xfd, 0x3a, 0xf8, 0xb1, 0xe1, 0x32, 0x05, 0x78, + 0x0c, 0x13, 0x7f, 0xe9, 0x38, 0xf8, 0x4f, 0xde, 0x40, 0x18, 0x8e, 0x61, + 0xea, 0x02, 0xce, 0xad, 0x81, 0xba, 0xdf, 0xdb, 0x42, 0x5c, 0x29, 0xf7, + 0xd7, 0xfb, 0x03, 0x24, 0xde, 0xba, 0xdc, 0x10, 0xbb, 0xb9, 0x3d, 0xe6, + 0x8f, 0x62, 0xc3, 0x50, 0x69, 0x26, 0x82, 0x83, 0xf5, 0x26, 0x58, 0x65, + 0xdb, 0x57, 0xa7, 0x9f, 0x7b, 0xf7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_118_private[] = { +/* dIUT */ + 0x00, 0x04, 0xd4, 0x9d, 0x39, 0xd4, 0x0d, 0x81, 0x11, 0xbf, 0x16, 0xd2, + 0x8c, 0x59, 0x36, 0x55, 0x43, 0x26, 0xb1, 0x97, 0x35, 0x3e, 0xeb, 0xbc, + 0xf4, 0x75, 0x45, 0x39, 0x3b, 0xc8, 0xd3, 0xaa, 0xf9, 0x8f, 0x14, 0xf5, + 0xbe, 0x70, 0x74, 0xbf, 0xb3, 0x8e, 0x6c, 0xc9, 0x7b, 0x98, 0x97, 0x54, + 0x07, 0x4d, 0xad, 0xdb, 0x30, 0x45, 0xf4, 0xe4, 0xce, 0x74, 0x56, 0x69, + 0xfd, 0xb3, 0xec, 0x0d, 0x5f, 0xa8 +}; +/* QIUTx = 0000012ec226d050ce07c79b3df4d0f0891f9f7adf462e8c98dbc1a2a14f5e53a3f5ad894433587cc429a8be9ea1d84fa33b1803690dae04da7218d30026157fc995cf52 */ +/* QIUTy = 0000004837dfbf3426f57b5c793269130abb9a38f618532211931154db4eeb9aede88e57290f842ea0f2ea9a5f74c6203a3920fe4e305f6118f676b154e1d75b9cb5eb88 */ +static const uint8_t nist_kas_ecc_cdh_testvector_118_out[] = { +/* ZIUT */ + 0x00, 0x6f, 0xe9, 0xde, 0x6f, 0xb8, 0xe6, 0x72, 0xe7, 0xfd, 0x15, 0x0f, + 0xdc, 0x5e, 0x61, 0x7f, 0xab, 0xb0, 0xd4, 0x39, 0x06, 0x35, 0x4c, 0xcf, + 0xd2, 0x24, 0x75, 0x7c, 0x72, 0x76, 0xf7, 0xa1, 0x01, 0x00, 0x91, 0xb1, + 0x7e, 0xd0, 0x72, 0x07, 0x4f, 0x8d, 0x10, 0xa5, 0xec, 0x97, 0x1e, 0xb3, + 0x5a, 0x5c, 0xb7, 0x07, 0x66, 0x03, 0xb7, 0xbc, 0x38, 0xd4, 0x32, 0xcb, + 0xc0, 0x59, 0xf8, 0x0f, 0x94, 0x88 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_119_public_x[] = { +/* QCAVSx */ + 0x00, 0x7e, 0x2d, 0x13, 0x8f, 0x28, 0x32, 0xe3, 0x45, 0xae, 0x8f, 0xf6, + 0x59, 0x57, 0xe4, 0x0e, 0x5e, 0xc7, 0x16, 0x3f, 0x01, 0x6b, 0xdf, 0x6d, + 0x24, 0xa2, 0x24, 0x3d, 0xaa, 0x63, 0x1d, 0x87, 0x8a, 0x4a, 0x16, 0x78, + 0x39, 0x90, 0xc7, 0x22, 0x38, 0x21, 0x30, 0xf9, 0xe5, 0x1f, 0x0c, 0x1b, + 0xd6, 0xff, 0x5a, 0xc9, 0x67, 0x80, 0xe4, 0x8b, 0x68, 0xf5, 0xde, 0xc9, + 0x5f, 0x42, 0xe6, 0x14, 0x4b, 0xb5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_119_public_y[] = { +/* QCAVSy */ + 0x00, 0xb0, 0xde, 0x5c, 0x89, 0x67, 0x91, 0xf5, 0x28, 0x86, 0xb0, 0xf0, + 0x99, 0x13, 0xe2, 0x6e, 0x78, 0xdd, 0x0b, 0x69, 0x79, 0x8f, 0xc4, 0xdf, + 0x6d, 0x95, 0xe3, 0xca, 0x70, 0x8e, 0xcb, 0xcb, 0xcc, 0xe1, 0xc1, 0x89, + 0x5f, 0x55, 0x61, 0xbb, 0xab, 0xaa, 0xe3, 0x72, 0xe9, 0xe6, 0x7e, 0x6e, + 0x1a, 0x3b, 0xe6, 0x0e, 0x19, 0xb4, 0x70, 0xcd, 0xf6, 0x73, 0xec, 0x1f, + 0xc3, 0x93, 0xd3, 0x42, 0x6e, 0x20 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_119_private[] = { +/* dIUT */ + 0x01, 0x1a, 0x5d, 0x1c, 0xc7, 0x9c, 0xd2, 0xbf, 0x73, 0xea, 0x10, 0x6f, + 0x0e, 0x60, 0xa5, 0xac, 0xe2, 0x20, 0x81, 0x3b, 0x53, 0xe2, 0x7b, 0x73, + 0x98, 0x64, 0x33, 0x4a, 0x07, 0xc0, 0x33, 0x67, 0xef, 0xda, 0x7a, 0x46, + 0x19, 0xfa, 0x6e, 0xef, 0x3a, 0x97, 0x46, 0x49, 0x22, 0x83, 0xb3, 0xc4, + 0x45, 0x61, 0x0a, 0x02, 0x3a, 0x9c, 0xc4, 0x9b, 0xf4, 0x59, 0x11, 0x40, + 0x38, 0x4f, 0xca, 0x5c, 0x8b, 0xb5 +}; +/* QIUTx = 000000eb07c7332eedb7d3036059d35f7d2288d4377d5f42337ad3964079fb120ccd4c8bd384b585621055217023acd9a94fcb3b965bfb394675e788ade41a1de73e620c */ +/* QIUTy = 000000491a835de2e6e7deb7e090f4a11f2c460c0b1f3d5e94ee8d751014dc720784fd3b54500c86ebaef18429f09e8e876d5d1538968a030d7715dde99f0d8f06e29d59 */ +static const uint8_t nist_kas_ecc_cdh_testvector_119_out[] = { +/* ZIUT */ + 0x01, 0xe4, 0xe7, 0x59, 0xec, 0xed, 0xce, 0x10, 0x13, 0xba, 0xf7, 0x3e, + 0x6f, 0xcc, 0x0b, 0x92, 0x45, 0x1d, 0x03, 0xbd, 0xd5, 0x04, 0x89, 0xb7, + 0x88, 0x71, 0xc3, 0x33, 0x11, 0x49, 0x90, 0xc9, 0xba, 0x6a, 0x9b, 0x2f, + 0xc7, 0xb1, 0xa2, 0xd9, 0xa1, 0x79, 0x4c, 0x1b, 0x60, 0xd9, 0x27, 0x9a, + 0xf6, 0xf1, 0x46, 0xf0, 0xbb, 0xfb, 0x06, 0x83, 0x14, 0x04, 0x03, 0xbf, + 0xa4, 0xcc, 0xdb, 0x52, 0x4a, 0x29 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_120_public_x[] = { +/* QCAVSx */ + 0x00, 0x11, 0x8c, 0x36, 0x02, 0x22, 0x09, 0xb1, 0xaf, 0x8e, 0xba, 0xd1, + 0xa1, 0x2b, 0x56, 0x6f, 0xc4, 0x87, 0x44, 0x57, 0x6e, 0x11, 0x99, 0xfe, + 0x80, 0xde, 0x1c, 0xdf, 0x85, 0x1c, 0xdf, 0x03, 0xe5, 0xb9, 0x09, 0x1a, + 0x8f, 0x7e, 0x07, 0x9e, 0x83, 0xb7, 0xf8, 0x27, 0x25, 0x9b, 0x69, 0x1d, + 0x0c, 0x22, 0xee, 0x29, 0xd6, 0xbd, 0xf7, 0x3e, 0xc7, 0xbb, 0xfd, 0x74, + 0x6f, 0x2c, 0xd9, 0x7a, 0x35, 0x7d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_120_public_y[] = { +/* QCAVSy */ + 0x00, 0xda, 0x5f, 0xf4, 0x90, 0x45, 0x48, 0xa3, 0x42, 0xe2, 0xe7, 0xba, + 0x6a, 0x1f, 0x4e, 0xe5, 0xf8, 0x40, 0x41, 0x1a, 0x96, 0xcf, 0x63, 0xe6, + 0xfe, 0x62, 0x2f, 0x22, 0xc1, 0x3e, 0x61, 0x4e, 0x0a, 0x84, 0x7c, 0x11, + 0xa1, 0xab, 0x3f, 0x1d, 0x12, 0xcc, 0x85, 0x0c, 0x32, 0xe0, 0x95, 0x61, + 0x4c, 0xa8, 0xf7, 0xe2, 0x72, 0x14, 0x77, 0xb4, 0x86, 0xe9, 0xff, 0x40, + 0x37, 0x29, 0x77, 0xc3, 0xf6, 0x5c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_120_private[] = { +/* dIUT */ + 0x01, 0x0c, 0x90, 0x8c, 0xaf, 0x1b, 0xe7, 0x4c, 0x61, 0x6b, 0x62, 0x5f, + 0xc8, 0xc1, 0xf5, 0x14, 0x44, 0x6a, 0x6a, 0xec, 0x83, 0xb5, 0x93, 0x71, + 0x41, 0xd6, 0xaf, 0xbb, 0x0a, 0x8c, 0x76, 0x66, 0xa7, 0x74, 0x6f, 0xa1, + 0xf7, 0xa6, 0x66, 0x4a, 0x21, 0x23, 0xe8, 0xcd, 0xf6, 0xcd, 0x8b, 0xf8, + 0x36, 0xc5, 0x6d, 0x3c, 0x0e, 0xbd, 0xcc, 0x98, 0x0e, 0x43, 0xa1, 0x86, + 0xf9, 0x38, 0xf3, 0xa7, 0x8a, 0xe7 +}; +/* QIUTx = 00000031890f4c7abec3f723362285d77d2636f876817db3bbc88b01e773597b969ff6f013ea470c854ab4a7739004eb8cbea69b82ddf36acadd406871798ecb2ac3aa7f */ +/* QIUTy = 000000d8b429ae3250266b9643c0c765a60dc10155bc2531cf8627296f4978b6640a9e600e19d0037d58503fa80799546a814d7478a550aa90e5ebeb052527faaeae5d08 */ +static const uint8_t nist_kas_ecc_cdh_testvector_120_out[] = { +/* ZIUT */ + 0x01, 0x63, 0xc9, 0x19, 0x1d, 0x65, 0x10, 0x39, 0xa5, 0xfe, 0x98, 0x5a, + 0x0e, 0xea, 0x1e, 0xba, 0x01, 0x8a, 0x40, 0xab, 0x19, 0x37, 0xfc, 0xd2, + 0xb6, 0x12, 0x20, 0x82, 0x0e, 0xe8, 0xf2, 0x30, 0x2e, 0x97, 0x99, 0xf6, + 0xed, 0xfc, 0x3f, 0x51, 0x74, 0xf3, 0x69, 0xd6, 0x72, 0xd3, 0x77, 0xea, + 0x89, 0x54, 0xa8, 0xd0, 0xc8, 0xb8, 0x51, 0xe8, 0x1a, 0x56, 0xfd, 0xa9, + 0x52, 0x12, 0xa6, 0x57, 0x8f, 0x0e +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_121_public_x[] = { +/* QCAVSx */ + 0x01, 0x78, 0x0e, 0xdf, 0xf1, 0xca, 0x1c, 0x03, 0xcf, 0xbe, 0x59, 0x3e, + 0xdc, 0x6c, 0x04, 0x9b, 0xcb, 0x28, 0x60, 0x29, 0x4a, 0x92, 0xc3, 0x55, + 0x48, 0x9d, 0x9a, 0xfb, 0x2e, 0x70, 0x20, 0x75, 0xad, 0xe1, 0xc9, 0x53, + 0x89, 0x5a, 0x45, 0x62, 0x30, 0xa0, 0xcd, 0xe9, 0x05, 0xde, 0x4a, 0x3f, + 0x38, 0x57, 0x3d, 0xbf, 0xcc, 0xcd, 0x67, 0xad, 0x6e, 0x7e, 0x93, 0xf0, + 0xb5, 0x58, 0x1e, 0x92, 0x6a, 0x5d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_121_public_y[] = { +/* QCAVSy */ + 0x00, 0xa5, 0x48, 0x19, 0x62, 0xc9, 0x16, 0x29, 0x62, 0xe7, 0xf0, 0xeb, + 0xde, 0xc9, 0x36, 0x93, 0x5d, 0x0e, 0xaa, 0x81, 0x3e, 0x82, 0x26, 0xd4, + 0x0d, 0x7f, 0x61, 0x19, 0xbf, 0xd9, 0x40, 0x60, 0x23, 0x80, 0xc8, 0x67, + 0x21, 0xe6, 0x1d, 0xb1, 0x83, 0x0f, 0x51, 0xe1, 0x39, 0xf2, 0x10, 0x00, + 0x0b, 0xce, 0xc0, 0xd8, 0xed, 0xd3, 0x9e, 0x54, 0xd7, 0x3a, 0x9a, 0x12, + 0x9f, 0x95, 0xcd, 0x5f, 0xa9, 0x79 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_121_private[] = { +/* dIUT */ + 0x01, 0xb3, 0x7d, 0x6b, 0x72, 0x88, 0xde, 0x67, 0x13, 0x60, 0x42, 0x5d, + 0x3e, 0x5a, 0xc1, 0xcc, 0xb2, 0x18, 0x15, 0x07, 0x9d, 0x8d, 0x73, 0x43, + 0x1e, 0x9b, 0x74, 0xa6, 0xf0, 0xe7, 0xae, 0x00, 0x4a, 0x35, 0x75, 0x75, + 0xb1, 0x1a, 0xd6, 0x66, 0x42, 0xce, 0x8b, 0x77, 0x55, 0x93, 0xeb, 0xa9, + 0xd9, 0x8b, 0xf2, 0x5c, 0x75, 0xef, 0x0b, 0x4d, 0x3a, 0x20, 0x98, 0xbb, + 0xc6, 0x41, 0xf5, 0x9a, 0x2b, 0x77 +}; +/* QIUTx = 000000189a5ee34de7e35aefeaeef9220c18071b4c29a4c3bd9d954458bd3e82a7a34da34cff5579b8101c065b1f2f527cf4581501e28ef5671873e65267733d003520af */ +/* QIUTy = 000001eb4bc50a7b4d4599d7e3fa773ddb9eb252c9b3422872e544bdf75c7bf60f5166ddc11eb08fa7c30822dabaee373ab468eb2d922e484e2a527fff2ebb804b7d9a37 */ +static const uint8_t nist_kas_ecc_cdh_testvector_121_out[] = { +/* ZIUT */ + 0x01, 0x5d, 0x61, 0x3e, 0x26, 0x7a, 0x36, 0x34, 0x2e, 0x0d, 0x12, 0x5c, + 0xda, 0xd6, 0x43, 0xd8, 0x0d, 0x97, 0xed, 0x06, 0x00, 0xaf, 0xb9, 0xe6, + 0xb9, 0x54, 0x5c, 0x9e, 0x64, 0xa9, 0x8c, 0xc6, 0xda, 0x7c, 0x5a, 0xaa, + 0x3a, 0x8d, 0xa0, 0xbd, 0xd9, 0xdd, 0x3b, 0x97, 0xe9, 0x78, 0x82, 0x18, + 0xa8, 0x0a, 0xba, 0xfc, 0x10, 0x6e, 0xf0, 0x65, 0xc8, 0xf1, 0xc4, 0xe1, + 0x11, 0x9e, 0xf5, 0x8d, 0x29, 0x8b +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_122_public_x[] = { +/* QCAVSx */ + 0x01, 0x6d, 0xac, 0xff, 0xa1, 0x83, 0xe5, 0x30, 0x30, 0x83, 0xa3, 0x34, + 0xf7, 0x65, 0xde, 0x72, 0x4e, 0xc5, 0xec, 0x94, 0x02, 0x02, 0x6d, 0x47, + 0x97, 0x88, 0x4a, 0x98, 0x28, 0xa0, 0xd3, 0x21, 0xa8, 0xcf, 0xac, 0x74, + 0xab, 0x73, 0x7f, 0xe2, 0x0a, 0x7d, 0x6b, 0xef, 0xcf, 0xc7, 0x3b, 0x6a, + 0x35, 0xc1, 0xc7, 0xb0, 0x1d, 0x37, 0x3e, 0x31, 0xab, 0xc1, 0x92, 0xd4, + 0x8a, 0x42, 0x41, 0xa3, 0x58, 0x03 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_122_public_y[] = { +/* QCAVSy */ + 0x01, 0x1e, 0x53, 0x27, 0xca, 0xc2, 0x2d, 0x30, 0x5e, 0x71, 0x56, 0xe5, + 0x59, 0x17, 0x6e, 0x19, 0xbe, 0xe7, 0xe4, 0xf2, 0xf5, 0x9e, 0x86, 0xf1, + 0xa9, 0xd0, 0xb6, 0x60, 0x3b, 0x6a, 0x7d, 0xf1, 0x06, 0x9b, 0xde, 0x63, + 0x87, 0xfe, 0xb7, 0x15, 0x87, 0xb8, 0xff, 0xce, 0x5b, 0x26, 0x6e, 0x1b, + 0xae, 0x86, 0xde, 0x29, 0x37, 0x8a, 0x34, 0xe5, 0xc7, 0x4b, 0x67, 0x24, + 0xc4, 0xd4, 0x0a, 0x71, 0x99, 0x23 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_122_private[] = { +/* dIUT */ + 0x00, 0xf2, 0x66, 0x1a, 0xc7, 0x62, 0xf6, 0x0c, 0x5f, 0xff, 0x23, 0xbe, + 0x5d, 0x96, 0x9c, 0xcd, 0x4e, 0xc6, 0xf9, 0x8e, 0x4e, 0x72, 0x61, 0x8d, + 0x12, 0xbd, 0xcd, 0xb9, 0xb4, 0x10, 0x21, 0x62, 0x33, 0x37, 0x88, 0xc0, + 0xba, 0xe5, 0x9f, 0x91, 0xcd, 0xfc, 0x17, 0x2c, 0x7a, 0x16, 0x81, 0xee, + 0x44, 0xd9, 0x6a, 0xb2, 0x13, 0x5a, 0x6e, 0x5f, 0x34, 0x15, 0xeb, 0xbc, + 0xd5, 0x51, 0x65, 0xb1, 0xaf, 0xb0 +}; +/* QIUTx = 000000a8e25a6902d687b4787cdc94c364ac7cecc5c495483ed363dc0aa95ee2bd739c4c4d46b17006c728b076350d7d7e54c6822f52f47162a25109aaaba690cab696ec */ +/* QIUTy = 00000168d2f08fe19e4dc9ee7a195b03c9f7fe6676f9f520b6270557504e72ca4394a2c6918625e15ac0c51b8f95cd560123653fb8e8ee6db961e2c4c62cc54e92e2a2a9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_122_out[] = { +/* ZIUT */ + 0x01, 0x4d, 0x60, 0x82, 0xa3, 0xb5, 0xce, 0xd1, 0xab, 0x8c, 0xa2, 0x65, + 0xa8, 0x10, 0x6f, 0x30, 0x21, 0x46, 0xc4, 0xac, 0xb8, 0xc3, 0x0b, 0xb1, + 0x4a, 0x4c, 0x99, 0x1e, 0x3c, 0x82, 0xa9, 0x73, 0x12, 0x88, 0xbd, 0xb9, + 0x1e, 0x0e, 0x85, 0xbd, 0xa3, 0x13, 0x91, 0x2d, 0x06, 0x38, 0x4f, 0xc4, + 0x4f, 0x21, 0x53, 0xfb, 0x13, 0x50, 0x6f, 0xa9, 0xcf, 0x43, 0xc9, 0xaa, + 0xb5, 0x75, 0x09, 0x88, 0xc9, 0x43 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_123_public_x[] = { +/* QCAVSx */ + 0x00, 0xa0, 0x91, 0x42, 0x1d, 0x37, 0x03, 0xe3, 0xb3, 0x41, 0xe9, 0xf1, + 0xe7, 0xd5, 0x8f, 0x8c, 0xf7, 0xbd, 0xbd, 0x17, 0x98, 0xd0, 0x01, 0x96, + 0x7b, 0x80, 0x1d, 0x1c, 0xec, 0x27, 0xe6, 0x05, 0xc5, 0x80, 0xb2, 0x38, + 0x7c, 0x1c, 0xb4, 0x64, 0xf5, 0x5c, 0xe7, 0xac, 0x80, 0x33, 0x41, 0x02, + 0xab, 0x03, 0xcf, 0xb8, 0x6d, 0x88, 0xaf, 0x76, 0xc9, 0xf4, 0x12, 0x9c, + 0x01, 0xbe, 0xdd, 0x3b, 0xbf, 0xc4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_123_public_y[] = { +/* QCAVSy */ + 0x00, 0x8c, 0x9c, 0x57, 0x7a, 0x8e, 0x6f, 0xc4, 0x46, 0x81, 0x5e, 0x9d, + 0x40, 0xba, 0xa6, 0x60, 0x25, 0xf1, 0x5d, 0xae, 0x28, 0x5f, 0x19, 0xeb, + 0x66, 0x8e, 0xe6, 0x0a, 0xe9, 0xc9, 0x8e, 0x7e, 0xcd, 0xbf, 0x2b, 0x2a, + 0x68, 0xe2, 0x29, 0x28, 0x05, 0x9f, 0x67, 0xdb, 0x18, 0x80, 0x07, 0x16, + 0x1d, 0x3e, 0xcf, 0x39, 0x7e, 0x08, 0x83, 0xf0, 0xc4, 0xeb, 0x7e, 0xaf, + 0x78, 0x27, 0xa6, 0x22, 0x05, 0xcc +}; +static const uint8_t nist_kas_ecc_cdh_testvector_123_private[] = { +/* dIUT */ + 0x00, 0xf4, 0x30, 0xca, 0x12, 0x61, 0xf0, 0x96, 0x81, 0xa9, 0x28, 0x2e, + 0x9e, 0x97, 0x0a, 0x92, 0x34, 0x22, 0x7b, 0x1d, 0x5e, 0x58, 0xd5, 0x58, + 0xc3, 0xcc, 0x6e, 0xff, 0x44, 0xd1, 0xbd, 0xf5, 0x3d, 0xe1, 0x6a, 0xd5, + 0xee, 0x2b, 0x18, 0xb9, 0x2d, 0x62, 0xfc, 0x79, 0x58, 0x61, 0x16, 0xb0, + 0xef, 0xc1, 0x5f, 0x79, 0x34, 0x0f, 0xb7, 0xea, 0xf5, 0xce, 0x6c, 0x44, + 0x34, 0x1d, 0xcf, 0x8d, 0xde, 0x27 +}; +/* QIUTx = 0000006c1d9b5eca87de1fb871a0a32f807c725adccde9b3967453a71347d608f0c030cd09e338cdecbf4a02015bc8a6e8d3e2595fe773ffc2fc4e4a55d0b1a2cc00323b */ +/* QIUTy = 000001141b2109e7f4981c952aa818a2b9f6f5c41feccdb7a7a45b9b4b672937771b008cae5f934dfe3fed10d383ab1f38769c92ce88d9be5414817ecb073a31ab368ccb */ +static const uint8_t nist_kas_ecc_cdh_testvector_123_out[] = { +/* ZIUT */ + 0x00, 0x20, 0xc0, 0x07, 0x47, 0xcb, 0x8d, 0x49, 0x2f, 0xd4, 0x97, 0xe0, + 0xfe, 0xc5, 0x46, 0x44, 0xbf, 0x02, 0x7d, 0x41, 0x8a, 0xb6, 0x86, 0x38, + 0x1f, 0x10, 0x97, 0x12, 0xa9, 0x9c, 0xab, 0xe3, 0x28, 0xb9, 0x74, 0x3d, + 0x22, 0x25, 0x83, 0x6f, 0x9a, 0xd6, 0x6e, 0x5d, 0x7f, 0xed, 0x1d, 0xe2, + 0x47, 0xe0, 0xda, 0x92, 0xf6, 0x0d, 0x5b, 0x31, 0xf9, 0xe4, 0x76, 0x72, + 0xe5, 0x7f, 0x71, 0x05, 0x98, 0xf4 +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_124_public_x[] = { +/* QCAVSx */ + 0x00, 0x4f, 0x38, 0x81, 0x66, 0x81, 0x77, 0x12, 0x89, 0xce, 0x0c, 0xb8, + 0x3a, 0x5e, 0x29, 0xa1, 0xab, 0x06, 0xfc, 0x91, 0xf7, 0x86, 0x99, 0x4b, + 0x23, 0x70, 0x8f, 0xf0, 0x8a, 0x08, 0xa0, 0xf6, 0x75, 0xb8, 0x09, 0xae, + 0x99, 0xe9, 0xf9, 0x96, 0x7e, 0xb1, 0xa4, 0x9f, 0x19, 0x60, 0x57, 0xd6, + 0x9e, 0x50, 0xd6, 0xde, 0xdb, 0x4d, 0xd2, 0xd9, 0xa8, 0x1c, 0x02, 0xbd, + 0xcc, 0x8f, 0x7f, 0x51, 0x84, 0x60 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_124_public_y[] = { +/* QCAVSy */ + 0x00, 0x9e, 0xfb, 0x24, 0x4c, 0x8b, 0x91, 0x08, 0x7d, 0xe1, 0xee, 0xd7, + 0x66, 0x50, 0x0f, 0x0e, 0x81, 0x53, 0x07, 0x52, 0xd4, 0x69, 0x25, 0x6e, + 0xf7, 0x9f, 0x6b, 0x96, 0x5d, 0x8a, 0x22, 0x32, 0xa0, 0xc2, 0xdb, 0xc4, + 0xe8, 0xe1, 0xd0, 0x92, 0x14, 0xba, 0xb3, 0x84, 0x85, 0xbe, 0x6e, 0x35, + 0x7c, 0x42, 0x00, 0xd0, 0x73, 0xb5, 0x2f, 0x04, 0xe4, 0xa1, 0x6f, 0xc6, + 0xf5, 0x24, 0x71, 0x87, 0xae, 0xcb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_124_private[] = { +/* dIUT */ + 0x00, 0x5d, 0xc3, 0x3a, 0xed, 0xa0, 0x3c, 0x2e, 0xb2, 0x33, 0x01, 0x4e, + 0xe4, 0x68, 0xdf, 0xf7, 0x53, 0xb7, 0x2f, 0x73, 0xb0, 0x09, 0x91, 0x04, + 0x3e, 0xa3, 0x53, 0x82, 0x8a, 0xe6, 0x9d, 0x4c, 0xd0, 0xfa, 0xde, 0xda, + 0x7b, 0xb2, 0x78, 0xb5, 0x35, 0xd7, 0xc5, 0x74, 0x06, 0xff, 0x2e, 0x6e, + 0x47, 0x3a, 0x5a, 0x4f, 0xf9, 0x8e, 0x90, 0xf9, 0x0d, 0x6d, 0xad, 0xd2, + 0x51, 0x00, 0xe8, 0xd8, 0x56, 0x66 +}; +/* QIUTx = 000000c825ba307373cec8dd2498eef82e21fd9862168dbfeb83593980ca9f82875333899fe94f137daf1c4189eb502937c3a367ea7951ed8b0f3377fcdf2922021d46a5 */ +/* QIUTy = 0000016b8a2540d5e65493888bc337249e67c0a68774f3e8d81e3b4574a0125165f0bd58b8af9de74b35832539f95c3cd9f1b759408560aa6851ae3ac7555347b0d3b13b */ +static const uint8_t nist_kas_ecc_cdh_testvector_124_out[] = { +/* ZIUT */ + 0x00, 0xc2, 0xbf, 0xaf, 0xcd, 0x7f, 0xbd, 0x3e, 0x2f, 0xd1, 0xc7, 0x50, + 0xfd, 0xea, 0x61, 0xe7, 0x0b, 0xd4, 0x78, 0x7a, 0x7e, 0x68, 0x46, 0x8c, + 0x57, 0x4e, 0xe9, 0x9e, 0xbc, 0x47, 0xee, 0xde, 0xf0, 0x64, 0xe8, 0x94, + 0x4a, 0x73, 0xbc, 0xb7, 0x91, 0x3d, 0xba, 0xb5, 0xd9, 0x3d, 0xca, 0x66, + 0x0d, 0x21, 0x6c, 0x55, 0x36, 0x22, 0x36, 0x27, 0x94, 0xf7, 0xa2, 0xac, + 0xc7, 0x10, 0x22, 0xbd, 0xb1, 0x6f +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_125_public_x[] = { +/* QCAVSx */ + 0x01, 0xa3, 0x20, 0x99, 0xb0, 0x2c, 0x0b, 0xd8, 0x53, 0x71, 0xf6, 0x0b, + 0x0d, 0xd2, 0x08, 0x90, 0xe6, 0xc7, 0xaf, 0x04, 0x8c, 0x81, 0x79, 0x89, + 0x0f, 0xda, 0x30, 0x8b, 0x35, 0x9d, 0xbb, 0xc2, 0xb7, 0xa8, 0x32, 0xbb, + 0x8c, 0x65, 0x26, 0xc4, 0xaf, 0x99, 0xa7, 0xea, 0x3f, 0x0b, 0x3c, 0xb9, + 0x6a, 0xe1, 0xeb, 0x76, 0x84, 0x13, 0x27, 0x95, 0xc4, 0x78, 0xad, 0x6f, + 0x96, 0x2e, 0x4a, 0x6f, 0x44, 0x6d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_125_public_y[] = { +/* QCAVSy */ + 0x01, 0x76, 0x27, 0x35, 0x7b, 0x39, 0xe9, 0xd7, 0x63, 0x2a, 0x13, 0x70, + 0xb3, 0xe9, 0x3c, 0x1a, 0xfb, 0x5c, 0x85, 0x1b, 0x91, 0x0e, 0xb4, 0xea, + 0xd0, 0xc9, 0xd3, 0x87, 0xdf, 0x67, 0xcd, 0xe8, 0x50, 0x03, 0xe0, 0xe4, + 0x27, 0x55, 0x2f, 0x1c, 0xd0, 0x90, 0x59, 0xaa, 0xd0, 0x26, 0x2e, 0x23, + 0x5c, 0xce, 0x5f, 0xba, 0x8c, 0xed, 0xc4, 0xfd, 0xc1, 0x46, 0x3d, 0xa7, + 0x6d, 0xcd, 0x4b, 0x6d, 0x1a, 0x46 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_125_private[] = { +/* dIUT */ + 0x00, 0xdf, 0x14, 0xb1, 0xf1, 0x43, 0x2a, 0x7b, 0x0f, 0xb0, 0x53, 0x96, + 0x5f, 0xd8, 0x64, 0x3a, 0xfe, 0xe2, 0x6b, 0x24, 0x51, 0xec, 0xb6, 0xa8, + 0xa5, 0x3a, 0x65, 0x5d, 0x5f, 0xbe, 0x16, 0xe4, 0xc6, 0x4c, 0xe8, 0x64, + 0x72, 0x25, 0xeb, 0x11, 0xe7, 0xfd, 0xcb, 0x23, 0x62, 0x74, 0x71, 0xdf, + 0xfc, 0x5c, 0x25, 0x23, 0xbd, 0x2a, 0xe8, 0x99, 0x57, 0xcb, 0xa3, 0xa5, + 0x7a, 0x23, 0x93, 0x3e, 0x5a, 0x78 +}; +/* QIUTx = 0000004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f3c560229664329baa5138c3bb1c36428abd4e23d17fcb7a2cfcc224b2e734c8941f6f121722d7b6b94154576 */ +/* QIUTy = 000001cf0874f204b0363f020864672fadbf87c8811eb147758b254b74b14fae742159f0f671a018212bbf25b8519e126d4cad778cfff50d288fd39ceb0cac635b175ec0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_125_out[] = { +/* ZIUT */ + 0x01, 0xaa, 0xf2, 0x4e, 0x5d, 0x47, 0xe4, 0x08, 0x0c, 0x18, 0xc5, 0x5e, + 0xa3, 0x55, 0x81, 0xcd, 0x8d, 0xa3, 0x0f, 0x1a, 0x07, 0x95, 0x65, 0x04, + 0x5d, 0x20, 0x08, 0xd5, 0x1b, 0x12, 0xd0, 0xab, 0xb4, 0x41, 0x1c, 0xda, + 0x7a, 0x07, 0x85, 0xb1, 0x5d, 0x14, 0x9e, 0xd3, 0x01, 0xa3, 0x69, 0x70, + 0x62, 0xf4, 0x2d, 0xa2, 0x37, 0xaa, 0x7f, 0x07, 0xe0, 0xaf, 0x3f, 0xd0, + 0x0e, 0xb1, 0x80, 0x0d, 0x9c, 0x41 +}; +/* [K-163] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_126_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x05, 0x74, 0x23, 0x6f, 0x14, 0x28, 0xc4, 0x32, 0x13, + 0x09, 0x46, 0x78, 0x3a, 0x5b, 0x3a, 0xab, 0xb6, 0xc2, 0x7e, 0xa5, 0xd6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_126_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x07, 0x90, 0x8c, 0x25, 0x1b, 0x8d, 0xa0, 0x21, 0xcb, + 0xac, 0x28, 0x1f, 0x12, 0x3f, 0x7a, 0xf4, 0xfa, 0xc5, 0xb3, 0xdb, 0xb8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_126_private[] = { +/* dIUT */ + 0x66, 0x53, 0xb6, 0x07, 0x73, 0x98, 0xfa, 0xdc, 0x7b, 0xf5, 0xe6, 0x01, + 0x58, 0x17, 0x01, 0x48, 0xc3, 0xdc, 0x45, 0x27 +}; +/* QIUTx = 000000071f8b2877d6027d9c1ade4244f2dea12692ef23d5 */ +/* QIUTy = 00000005c15ee776221c72b84b347ce383f38067b89c3e9a */ +static const uint8_t nist_kas_ecc_cdh_testvector_126_out[] = { +/* ZIUT */ + 0x04, 0x32, 0x5b, 0xff, 0x38, 0xf1, 0xb0, 0xc8, 0x3c, 0x27, 0xf5, 0x54, + 0xa6, 0xc9, 0x72, 0xa8, 0x0f, 0x14, 0xbc, 0x23, 0xbc +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_127_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x01, 0x69, 0x97, 0x44, 0x09, 0x2f, 0xe2, 0xb5, 0xfe, + 0x7e, 0xcb, 0xf6, 0x98, 0x7b, 0x7a, 0xea, 0x0a, 0x06, 0xfd, 0x2c, 0xb0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_127_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x03, 0x5d, 0xe4, 0x41, 0xdf, 0x94, 0x08, 0xd9, 0x1f, + 0x0e, 0x02, 0x1d, 0xf8, 0xf0, 0x52, 0x6b, 0x80, 0x63, 0x03, 0x14, 0x95 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_127_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0xae, 0xf4, 0x47, 0x54, 0xd0, 0xca, 0x97, 0xd4, + 0x2b, 0x4e, 0x97, 0xaa, 0x92, 0x15, 0x62, 0x63, 0xc0, 0xe0, 0x78, 0xf6 +}; +/* QIUTx = 00000001b0108c786bf4d340f0505bdfc7d45b514611ad94 */ +/* QIUTy = 000000022c9c39d5fb9456b8a2221cea4f058f6a8d2cd84a */ +static const uint8_t nist_kas_ecc_cdh_testvector_127_out[] = { +/* ZIUT */ + 0x05, 0xf9, 0xac, 0x3a, 0x3d, 0xd8, 0x84, 0x29, 0x60, 0x09, 0x58, 0x38, + 0x6c, 0x55, 0xbe, 0xf4, 0xb1, 0xaa, 0x5f, 0x0c, 0x24 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_128_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0x96, 0x5d, 0xb1, 0x59, 0x17, 0x1f, 0x5c, 0xb7, + 0xe7, 0xa1, 0xbc, 0xc6, 0x16, 0x11, 0xae, 0xac, 0xa8, 0xc5, 0x2c, 0x9b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_128_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x06, 0x87, 0x1d, 0x1e, 0x9c, 0x1f, 0xe8, 0x45, 0x26, + 0x80, 0x76, 0xa9, 0x95, 0x80, 0x3a, 0x6d, 0x49, 0xcd, 0x07, 0x55, 0x54 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_128_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x11, 0x72, 0x34, 0x2e, 0x6d, 0x37, 0xcc, 0x1e, + 0x06, 0x2a, 0x44, 0x94, 0xc3, 0x9c, 0xba, 0x48, 0xf9, 0xad, 0x9a, 0x8c +}; +/* QIUTx = 00000003a27ecaec2b66feac2040f6890128bd0058d31924 */ +/* QIUTy = 000000014007e3209b6d7127b0f393e5e58b1590b9f40be2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_128_out[] = { +/* ZIUT */ + 0x02, 0x2e, 0x02, 0x90, 0xed, 0xa5, 0xd3, 0x48, 0x89, 0x41, 0x29, 0xf7, + 0x45, 0x5d, 0x1c, 0x76, 0x6d, 0x32, 0xd5, 0xc2, 0xc2 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_129_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x05, 0x5b, 0x68, 0xc0, 0xc2, 0xc2, 0x46, 0xfe, 0x0f, + 0x2c, 0xd5, 0x48, 0x4b, 0x58, 0x81, 0x4c, 0x65, 0x21, 0x3e, 0xa5, 0x41 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_129_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x05, 0x39, 0xc1, 0x1d, 0x25, 0x92, 0xa2, 0xf6, 0x39, + 0x3b, 0x6e, 0x86, 0xc5, 0x4d, 0xf9, 0x09, 0xb9, 0x5f, 0xe0, 0xd5, 0xa8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_129_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x2a, 0x51, 0x1c, 0xdc, 0xd4, 0xbf, 0xc5, 0x67, + 0xce, 0xac, 0x8c, 0x24, 0xed, 0x04, 0xe8, 0x89, 0x4d, 0xf7, 0x8d, 0xdf +}; +/* QIUTx = 00000006978dacaa47d8f3bc90b41ec7f4f8ac79a86ddd07 */ +/* QIUTy = 00000007f8b0ef4270760376bc2d5faed83da7872631d09f */ +static const uint8_t nist_kas_ecc_cdh_testvector_129_out[] = { +/* ZIUT */ + 0x03, 0x7f, 0x65, 0x9f, 0x43, 0x00, 0x09, 0xfc, 0xda, 0xe4, 0xe9, 0xf6, + 0xe6, 0x31, 0x6b, 0x0f, 0x5d, 0xbb, 0x26, 0x82, 0x12 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_130_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x06, 0xb8, 0xef, 0x5a, 0x62, 0xd3, 0xb6, 0x36, 0xa5, + 0xa7, 0x6b, 0xfe, 0xb1, 0xef, 0x8f, 0xf4, 0xd8, 0xb3, 0xd9, 0xe2, 0xfc +}; +static const uint8_t nist_kas_ecc_cdh_testvector_130_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x06, 0x75, 0xa7, 0x57, 0x26, 0x67, 0x18, 0x39, 0x8d, + 0x8a, 0xf6, 0x6d, 0x29, 0x71, 0x79, 0x84, 0x78, 0xe2, 0xf3, 0x7d, 0x28 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_130_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0xc6, 0xf6, 0x4f, 0xe6, 0x09, 0xeb, 0x8e, 0xeb, + 0x5b, 0x53, 0xfa, 0xb6, 0x30, 0x88, 0x98, 0xe6, 0x3f, 0xf2, 0xe3, 0xf6 +}; +/* QIUTx = 0000000549e1a82ec284bf77d528627e52d832e236c92ad3 */ +/* QIUTy = 000000019883aa9b458b35bd544d6882812150c1497d31d4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_130_out[] = { +/* ZIUT */ + 0x00, 0x50, 0x3b, 0xbb, 0x9b, 0x62, 0xf5, 0x0a, 0xe7, 0xa8, 0xdf, 0xd7, + 0x4a, 0x17, 0x41, 0x82, 0x6f, 0x09, 0x29, 0x06, 0x51 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_131_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x05, 0x6c, 0x4a, 0x35, 0x86, 0xac, 0xb0, 0x30, 0x99, + 0xd5, 0x2b, 0x2c, 0xd4, 0xac, 0x59, 0x26, 0x9c, 0xf5, 0x1b, 0x87, 0x30 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_131_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x02, 0x42, 0x65, 0x61, 0xcb, 0xd9, 0xda, 0x1b, 0x23, + 0xa6, 0x00, 0x3d, 0xe0, 0xe5, 0xf7, 0xc4, 0xa0, 0x65, 0xa5, 0xc2, 0xb8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_131_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0x6a, 0x56, 0x86, 0x75, 0x13, 0xdd, 0xd8, 0xca, + 0x94, 0xd7, 0x92, 0x3b, 0xaa, 0x1f, 0x7f, 0xb0, 0x0d, 0xaa, 0x38, 0xfa +}; +/* QIUTx = 00000006c28a40dc4e5503d2c4b8ab0b6b7046e8e25ac09f */ +/* QIUTy = 0000000121911654a5836005d8036d976585ff1d831e587b */ +static const uint8_t nist_kas_ecc_cdh_testvector_131_out[] = { +/* ZIUT */ + 0x01, 0x2c, 0xf1, 0x77, 0x99, 0xfd, 0xef, 0xa2, 0x94, 0x0b, 0x18, 0xd5, + 0x6e, 0x80, 0xd4, 0x44, 0x14, 0xc5, 0xb1, 0x38, 0x84 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_132_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x07, 0x41, 0xc6, 0x9a, 0x4e, 0xdb, 0x38, 0x6c, 0x94, + 0xf8, 0x19, 0xd1, 0xb5, 0xdd, 0xd0, 0x28, 0x1e, 0x4f, 0xf2, 0x97, 0x65 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_132_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2f, 0x97, 0x2a, 0xba, 0xc9, 0x1b, 0xe8, + 0x5a, 0x70, 0x9e, 0xba, 0x07, 0xf5, 0xd1, 0x62, 0x15, 0xae, 0x60, 0x2d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_132_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x86, 0x81, 0x10, 0x79, 0xc8, 0x02, 0x1c, 0x2d, + 0x79, 0xf4, 0xde, 0x95, 0x2c, 0xb2, 0xe5, 0x99, 0xc4, 0x2e, 0x19, 0xed +}; +/* QIUTx = 000000060aa42a62e21eea37e362b4d3de837f0c49d3ac13 */ +/* QIUTy = 000000069b20d6fd16d13b1883df05629ac7d1b82386b344 */ +static const uint8_t nist_kas_ecc_cdh_testvector_132_out[] = { +/* ZIUT */ + 0x06, 0x2a, 0x2f, 0x92, 0x6a, 0xb4, 0x35, 0xac, 0x14, 0xe0, 0x5d, 0x44, + 0xc2, 0x7b, 0x46, 0xb6, 0x82, 0x0b, 0x71, 0x3a, 0xee +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_133_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x01, 0xef, 0x47, 0x79, 0x5f, 0xb0, 0xe3, 0x80, 0x40, + 0x5a, 0xb5, 0xe8, 0x8d, 0xef, 0xc3, 0xce, 0xd9, 0xa9, 0x25, 0x14, 0xa6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_133_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x00, 0xbe, 0x61, 0x81, 0xd7, 0xfc, 0x03, 0xca, 0x8b, + 0xfd, 0xf1, 0x18, 0x69, 0xce, 0xa2, 0x8c, 0xfa, 0x0e, 0x5f, 0x5f, 0x64 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_133_private[] = { +/* dIUT */ + 0xe4, 0x6e, 0x9c, 0x96, 0x52, 0x68, 0x64, 0x7f, 0x20, 0x48, 0x47, 0x4c, + 0x7b, 0x1a, 0x54, 0xdf, 0xfe, 0x72, 0x8f, 0x1f +}; +/* QIUTx = 00000007a984ead440310cef2e1338972ff2dddb65cac3d2 */ +/* QIUTy = 0000000333c1a93427fe6ac502760b7778898a8bb6a40ad9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_133_out[] = { +/* ZIUT */ + 0x03, 0x99, 0xb9, 0x29, 0x4e, 0x89, 0x54, 0x86, 0xbd, 0xef, 0xba, 0xad, + 0x7a, 0x72, 0x93, 0x53, 0xce, 0x09, 0x58, 0x63, 0x57 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_134_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x03, 0x74, 0xd7, 0xf9, 0xba, 0x8c, 0xda, 0x8a, 0x68, + 0xde, 0x72, 0x79, 0xd3, 0xff, 0x86, 0x74, 0x03, 0x2f, 0xd4, 0x7c, 0x02 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_134_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x03, 0xed, 0xe9, 0x95, 0xc3, 0xa4, 0xe8, 0xa6, 0xfe, + 0x21, 0xcd, 0x1e, 0x4c, 0xd4, 0xca, 0x38, 0x12, 0xc0, 0xd6, 0x92, 0xa5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_134_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0x73, 0x34, 0x97, 0x14, 0x05, 0xb0, 0x46, 0x1c, + 0x3e, 0xde, 0x67, 0xf2, 0xba, 0x33, 0x67, 0x34, 0x45, 0x1a, 0x83, 0x78 +}; +/* QIUTx = 0000000767c31ee9303b1b2cd3059f81507ef304ebd3102c */ +/* QIUTy = 0000000251e0d430dc3f63f3a37bab1e7a957652cf67e22c */ +static const uint8_t nist_kas_ecc_cdh_testvector_134_out[] = { +/* ZIUT */ + 0x02, 0x23, 0x25, 0xa9, 0xa7, 0x69, 0xa9, 0x02, 0xc2, 0xe6, 0x4c, 0x80, + 0xa1, 0xd3, 0x54, 0x29, 0xce, 0xd4, 0x2a, 0xe0, 0xa4 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_135_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x06, 0x57, 0x7d, 0xf5, 0x4e, 0x11, 0xc7, 0xe7, 0x62, + 0x02, 0xf9, 0x4f, 0x56, 0x4e, 0x61, 0x37, 0xb2, 0x3c, 0xe6, 0xe4, 0x41 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_135_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x06, 0x89, 0x36, 0x60, 0x0a, 0xad, 0xcb, 0x25, 0xfd, + 0x40, 0x24, 0xed, 0x3e, 0x84, 0x5b, 0x2b, 0xbf, 0x80, 0x72, 0x80, 0xe6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_135_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0x9b, 0xb4, 0x80, 0x73, 0x90, 0x11, 0x23, 0x5c, + 0x6d, 0x5c, 0x6e, 0x74, 0xd6, 0xa7, 0xbb, 0x4f, 0x20, 0xf6, 0x1b, 0x7a +}; +/* QIUTx = 0000000093549075704d79dae772317dd65244fa772569eb */ +/* QIUTy = 00000002a8a2821dd39d7e7653ca71cfc1a9ed857801a39b */ +static const uint8_t nist_kas_ecc_cdh_testvector_135_out[] = { +/* ZIUT */ + 0x05, 0x13, 0x92, 0xd5, 0x37, 0x70, 0x16, 0x35, 0x84, 0x05, 0x03, 0x0b, + 0x48, 0x74, 0x40, 0x03, 0xdb, 0x66, 0x44, 0x0a, 0x2d +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_136_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0x61, 0xd1, 0x53, 0x45, 0xce, 0xb4, 0x92, 0x22, + 0x9a, 0x8d, 0x74, 0x59, 0x7e, 0x7d, 0xfd, 0x19, 0xae, 0xb6, 0x84, 0x8a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_136_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x01, 0x14, 0xa1, 0x22, 0xce, 0x28, 0xca, 0x15, 0x62, + 0x0f, 0x7b, 0x40, 0xa1, 0xf2, 0x6b, 0x42, 0x34, 0xc9, 0x56, 0xbd, 0xc1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_136_private[] = { +/* dIUT */ + 0xf4, 0xed, 0xb5, 0x8b, 0xcc, 0x3d, 0x6e, 0x9d, 0x31, 0x72, 0x29, 0x42, + 0x0a, 0x73, 0x32, 0x81, 0xec, 0xcf, 0xf1, 0xcf +}; +/* QIUTx = 000000027183609b7593b1845365c081d45ff66c9ab5e370 */ +/* QIUTy = 000000069b981236fe930947b6b77f374282a18e4be993cb */ +static const uint8_t nist_kas_ecc_cdh_testvector_136_out[] = { +/* ZIUT */ + 0x04, 0x5d, 0xac, 0x07, 0x6e, 0x79, 0xde, 0x2f, 0xc6, 0x31, 0x31, 0x54, + 0x65, 0xd3, 0xef, 0x62, 0x45, 0xf2, 0x66, 0x47, 0xe5 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_137_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x07, 0x0e, 0x38, 0x0f, 0x49, 0x37, 0x0a, 0x00, 0x27, + 0x95, 0x4a, 0x4e, 0xa8, 0x80, 0xbc, 0x19, 0x29, 0xb2, 0x8c, 0x53, 0x29 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_137_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x04, 0x6f, 0xe3, 0xb4, 0x54, 0xaf, 0x94, 0x20, 0xa8, + 0x11, 0xf1, 0xe1, 0x5f, 0x77, 0x4d, 0xa5, 0xae, 0x1a, 0x40, 0xb4, 0x59 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_137_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0xb9, 0x90, 0x49, 0x1a, 0x12, 0xfd, 0xee, 0x23, + 0x1a, 0xa2, 0xa1, 0x16, 0xe1, 0xe3, 0xc1, 0xc9, 0x1d, 0x0f, 0xd4, 0x78 +}; +/* QIUTx = 00000003da869d09c4e4545ac1689fc72316012632d0abd9 */ +/* QIUTy = 00000002c820f40310e5ffd2f8bf439fba879bb2ef621b2a */ +static const uint8_t nist_kas_ecc_cdh_testvector_137_out[] = { +/* ZIUT */ + 0x01, 0x4f, 0x7a, 0x46, 0x84, 0x7e, 0xd6, 0xa7, 0xff, 0x60, 0x5b, 0x0e, + 0x52, 0xc6, 0x16, 0xe4, 0xad, 0x3f, 0x0d, 0x50, 0x29 +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_138_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x06, 0xe6, 0x0a, 0xf7, 0x74, 0x19, 0xb9, 0xfe, 0x0f, + 0xc5, 0xc7, 0x9c, 0xa1, 0xa2, 0x2a, 0x10, 0x11, 0x40, 0x24, 0x05, 0xb6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_138_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x06, 0x9b, 0xca, 0x34, 0x00, 0x5b, 0x57, 0x8c, 0xd7, + 0xa7, 0xa6, 0x92, 0x9b, 0xd3, 0xf6, 0xce, 0x29, 0x94, 0x3b, 0x5e, 0xd9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_138_private[] = { +/* dIUT */ + 0xe8, 0x29, 0xb9, 0x94, 0x2f, 0xd9, 0x64, 0x87, 0xf6, 0x01, 0x29, 0x08, + 0xfe, 0x04, 0xf6, 0xd8, 0xea, 0xaf, 0x19, 0x66 +}; +/* QIUTx = 00000005ab2074c04df57160167735f7fc2d8f629d34ff18 */ +/* QIUTy = 000000012e9da6d05bb3e2acbe5ba4afb4a0dd72db07d6ac */ +static const uint8_t nist_kas_ecc_cdh_testvector_138_out[] = { +/* ZIUT */ + 0x00, 0xea, 0xca, 0xbc, 0x34, 0x55, 0x59, 0x56, 0x99, 0x56, 0x23, 0xe6, + 0x04, 0x82, 0xe5, 0xc1, 0x18, 0xe3, 0x4e, 0x20, 0x94 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_139_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x04, 0xf7, 0x50, 0xe2, 0x75, 0x00, 0xe1, 0x0f, 0x0a, + 0x17, 0x6b, 0x83, 0xf1, 0x4b, 0xc2, 0x6d, 0x6b, 0xd7, 0x1e, 0xbd, 0x74 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_139_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x03, 0x9e, 0x50, 0x09, 0x06, 0x7c, 0x0e, 0xe2, 0xc8, + 0xf5, 0x5b, 0x7e, 0x84, 0xda, 0x7a, 0x39, 0x1f, 0x08, 0xaf, 0x75, 0x04 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_139_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0x57, 0xce, 0x8f, 0x0b, 0x6c, 0xe9, 0x2e, 0x42, + 0x6e, 0xc9, 0x9f, 0x22, 0x3a, 0xd8, 0x27, 0x63, 0xe4, 0xbd, 0x3f, 0xf3 +}; +/* QIUTx = 00000005d3989cca4ae732de93672b25c9260861b4c0dce3 */ +/* QIUTy = 0000000436a331ead24f2807b55260f9dc3de668cfbfebb7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_139_out[] = { +/* ZIUT */ + 0x04, 0x14, 0xa6, 0x22, 0x64, 0x51, 0x07, 0xf1, 0x15, 0x57, 0x6f, 0x51, + 0xcd, 0xf3, 0x9d, 0x13, 0x93, 0xa2, 0xd7, 0x85, 0x1f +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_140_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0xab, 0x9f, 0x5b, 0xa9, 0x41, 0x02, 0xd2, 0x1a, + 0x70, 0x67, 0x61, 0xea, 0xc0, 0x09, 0x21, 0x90, 0xf1, 0xcd, 0xad, 0x04 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_140_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x04, 0xad, 0xdd, 0x77, 0xe1, 0x99, 0xc1, 0x32, 0xd1, + 0x8a, 0xc5, 0x41, 0xb1, 0x17, 0x74, 0x8d, 0x23, 0x19, 0xdb, 0x7f, 0xe5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_140_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x79, 0x88, 0x5f, 0x45, 0xf2, 0xd7, 0x07, 0xbe, + 0x1c, 0x11, 0xd8, 0x6c, 0x41, 0xba, 0xda, 0x49, 0x3b, 0x2a, 0x56, 0x03 +}; +/* QIUTx = 00000005ae31cb29b31d24f5f94c30e9c02f07f38bff0ac8 */ +/* QIUTy = 00000004d8d8e39bf87f058543dc8990a91214da416cc558 */ +static const uint8_t nist_kas_ecc_cdh_testvector_140_out[] = { +/* ZIUT */ + 0x05, 0x6b, 0xe0, 0x02, 0xda, 0xff, 0x11, 0xc4, 0x06, 0x6e, 0x10, 0xac, + 0xd0, 0x46, 0xa8, 0x5e, 0x17, 0x0f, 0xa4, 0xc1, 0x22 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_141_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x04, 0x3d, 0x25, 0xd2, 0xde, 0x92, 0x93, 0xb8, 0x4d, + 0x35, 0x1a, 0x33, 0xcb, 0x1a, 0x52, 0xf5, 0x93, 0x0a, 0x4c, 0x8b, 0x76 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_141_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x03, 0xd2, 0x59, 0xd8, 0x23, 0x6e, 0x9c, 0x8d, 0x64, + 0x37, 0xf4, 0x1e, 0x6d, 0x54, 0x61, 0x1c, 0x52, 0x23, 0x8f, 0xe2, 0xd5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_141_private[] = { +/* dIUT */ + 0xba, 0x8c, 0x58, 0x64, 0xdb, 0x3e, 0xfd, 0x76, 0x8b, 0x93, 0x76, 0xfc, + 0x2b, 0x6c, 0x1f, 0x85, 0xf4, 0x6f, 0x6a, 0xf2 +}; +/* QIUTx = 000000062f622149823f255b4f86906666f3a3556af080ea */ +/* QIUTy = 0000000274ca32c10f9add61a026d20ad3ad56b17fb06a46 */ +static const uint8_t nist_kas_ecc_cdh_testvector_141_out[] = { +/* ZIUT */ + 0x02, 0x1f, 0xef, 0x8e, 0x47, 0x3d, 0xae, 0xda, 0x8e, 0xf6, 0xbf, 0x07, + 0x81, 0x4d, 0x7b, 0x9b, 0x61, 0x3e, 0x30, 0x76, 0xa3 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_142_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x00, 0x56, 0x0e, 0x1a, 0x42, 0x18, 0x65, 0x11, 0x8b, + 0xea, 0x16, 0xcd, 0xad, 0x6b, 0x67, 0xab, 0xa3, 0x84, 0xef, 0x38, 0x7b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_142_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x05, 0x8b, 0x21, 0x3e, 0xc2, 0xab, 0x39, 0x42, 0xf8, + 0xf6, 0xad, 0x60, 0xa9, 0x56, 0x95, 0x5b, 0x58, 0x90, 0x66, 0xb8, 0x56 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_142_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0xe5, 0x08, 0x04, 0x84, 0xd3, 0x73, 0x0b, 0x22, + 0x48, 0xcc, 0xc4, 0x82, 0x60, 0xd4, 0xbd, 0x18, 0x57, 0x60, 0x5a, 0xd1 +}; +/* QIUTx = 000000058aea6e40b8cb25e6622a7be4ff01b79c92de72a5 */ +/* QIUTy = 000000043f6776b6deff3d29b4c703899d705c7fecf525c4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_142_out[] = { +/* ZIUT */ + 0x03, 0xa2, 0x87, 0xfd, 0x1c, 0xca, 0x68, 0xdb, 0x47, 0xa3, 0xc7, 0x4c, + 0x12, 0x62, 0x7f, 0xc3, 0x72, 0x85, 0x68, 0xdd, 0x66 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_143_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x03, 0x8e, 0x48, 0x5d, 0xe9, 0x2e, 0x41, 0xf1, 0xca, + 0xca, 0x6c, 0x0e, 0xb9, 0xd8, 0x11, 0xa5, 0xac, 0xa8, 0x9b, 0xf3, 0x45 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_143_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x03, 0x31, 0xa1, 0x67, 0x7c, 0x46, 0xa6, 0x8e, 0x96, + 0x48, 0x11, 0xa9, 0xcc, 0x5e, 0x4e, 0x53, 0xea, 0x71, 0xe2, 0x31, 0x29 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_143_private[] = { +/* dIUT */ + 0x5d, 0x05, 0x2b, 0xa1, 0xab, 0xea, 0x72, 0x49, 0x78, 0xca, 0xef, 0x18, + 0x79, 0x24, 0x56, 0x72, 0xd5, 0xae, 0xf8, 0x91 +}; +/* QIUTx = 000000036b84a77337a9de5c1dd7ae3c899381382f0fffa4 */ +/* QIUTy = 000000056d4ac39fe881fdb8e60d4559658aaade45663ee5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_143_out[] = { +/* ZIUT */ + 0x02, 0x95, 0x58, 0xb4, 0x1b, 0x8b, 0x92, 0x38, 0x7b, 0xc2, 0x2c, 0x86, + 0x8f, 0x51, 0xbb, 0x7a, 0xcb, 0x6e, 0x4e, 0xe2, 0xe3 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_144_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x06, 0x42, 0x59, 0xe5, 0x00, 0x47, 0x6d, 0xda, 0x3e, + 0x97, 0xe2, 0x5e, 0x49, 0x1d, 0x46, 0x6c, 0x2b, 0x79, 0x58, 0xbd, 0x49 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_144_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x03, 0xc2, 0xe5, 0x32, 0x81, 0x39, 0x36, 0x41, 0xa5, + 0x18, 0xd1, 0xdc, 0xef, 0xfa, 0xbe, 0xe8, 0xb2, 0x9b, 0xde, 0x14, 0x02 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_144_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x91, 0x80, 0x18, 0x7a, 0x9e, 0xdd, 0xcf, 0x38, + 0xdc, 0x26, 0x4f, 0x05, 0x5b, 0x07, 0xd2, 0x0b, 0x9f, 0x9a, 0x8b, 0xc4 +}; +/* QIUTx = 00000004b292d1fa09dfc5e6a3ad99fd02feb74d480e34f2 */ +/* QIUTy = 00000006e1888009a0a0491c0be6abfac943d377f0b4863b */ +static const uint8_t nist_kas_ecc_cdh_testvector_144_out[] = { +/* ZIUT */ + 0x05, 0x30, 0x02, 0x0c, 0x8f, 0x63, 0x62, 0x31, 0x2b, 0xfb, 0xe5, 0xc1, + 0xc6, 0x05, 0xb4, 0x0d, 0xc2, 0xe0, 0x32, 0xe8, 0x1c +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_145_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x03, 0x71, 0x42, 0x76, 0x99, 0x7b, 0x44, 0x78, 0xe2, + 0xd8, 0xb5, 0x9a, 0xf5, 0xf2, 0xe6, 0x3e, 0x22, 0xbc, 0x4c, 0x31, 0xe4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_145_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x06, 0x73, 0xf2, 0x8d, 0x96, 0x2a, 0xbf, 0xed, 0xee, + 0x62, 0xea, 0xb4, 0x7c, 0x3b, 0x45, 0x79, 0xa1, 0xe5, 0x16, 0x83, 0x36 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_145_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0x6d, 0x37, 0x86, 0x2b, 0x19, 0x57, 0x63, 0xc6, + 0xa0, 0x1d, 0x5e, 0x39, 0xb9, 0x45, 0x9a, 0x32, 0x50, 0x7c, 0x2b, 0x21 +}; +/* QIUTx = 000000033440e460c475f2058a767ec466ca18bce41f830e */ +/* QIUTy = 0000000372aee323d063fa89acbffbf55024ae24e4929f19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_145_out[] = { +/* ZIUT */ + 0x05, 0x21, 0x67, 0x30, 0x06, 0xa1, 0xd9, 0x60, 0x89, 0x11, 0xd5, 0x45, + 0x36, 0xe1, 0x22, 0xd8, 0x09, 0xe9, 0x19, 0xd8, 0x04 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_146_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0x75, 0xec, 0x15, 0xf2, 0x7d, 0xd2, 0xda, 0x6e, + 0x44, 0xdf, 0xe6, 0x23, 0x54, 0x72, 0xd5, 0xbd, 0x3a, 0x25, 0x02, 0xf8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_146_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x05, 0x8f, 0xd0, 0x22, 0x62, 0xb2, 0x7c, 0x18, 0x5d, + 0xde, 0x26, 0xb2, 0xc7, 0x7d, 0x5a, 0x4f, 0x4d, 0x50, 0xdc, 0x99, 0x28 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_146_private[] = { +/* dIUT */ + 0x6c, 0x65, 0x87, 0x94, 0xb0, 0x39, 0xc8, 0x20, 0xa8, 0xb0, 0x33, 0x00, + 0x8f, 0xa8, 0xac, 0x75, 0x56, 0xbc, 0xae, 0xc3 +}; +/* QIUTx = 00000004cbfb286691e415081a1785ec6b0aacdb1d231d1d */ +/* QIUTy = 00000005dd6acfe91d68a8ec23686478c0ee8c89277aef14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_146_out[] = { +/* ZIUT */ + 0x04, 0x60, 0x57, 0x9b, 0xec, 0xa1, 0x6c, 0xcc, 0xce, 0x31, 0x4f, 0xf3, + 0x04, 0x0d, 0xe4, 0x78, 0x53, 0x36, 0xfc, 0x35, 0x8c +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_147_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0x33, 0xaf, 0x36, 0x10, 0x30, 0x39, 0x22, 0x6f, + 0x41, 0x6d, 0xd2, 0x2e, 0x1a, 0x26, 0xb7, 0x3f, 0x90, 0x93, 0xd3, 0x8a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_147_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x07, 0x34, 0x25, 0x8a, 0x17, 0x5c, 0x97, 0x76, 0x8a, + 0x9f, 0x72, 0xb8, 0x24, 0xb9, 0x9a, 0x91, 0xf5, 0xcf, 0x8e, 0x3d, 0x96 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_147_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0x69, 0xc8, 0xda, 0x22, 0xc3, 0x5a, 0x85, 0x54, + 0x95, 0x04, 0x7a, 0x10, 0x4b, 0xe0, 0x0b, 0x15, 0x75, 0xb6, 0x52, 0xab +}; +/* QIUTx = 000000045efed9c8bd2a4e429588f344f49d1e63e668bd01 */ +/* QIUTy = 000000025d1af85ac21d59822d7df8f0e4bebadf3b5d4401 */ +static const uint8_t nist_kas_ecc_cdh_testvector_147_out[] = { +/* ZIUT */ + 0x05, 0xba, 0x66, 0x96, 0x44, 0x83, 0xfe, 0x47, 0x3c, 0xcb, 0xd0, 0x0c, + 0x37, 0xad, 0x3b, 0xa4, 0x0c, 0xc5, 0x96, 0x9f, 0x62 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_148_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x06, 0xd0, 0x32, 0x15, 0x22, 0x40, 0xf2, 0x8b, 0xe7, + 0xf7, 0x4d, 0xf8, 0xf6, 0xd2, 0xa4, 0x50, 0xc1, 0x22, 0x9a, 0x5a, 0x95 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_148_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x07, 0xaa, 0xda, 0xc7, 0x7c, 0xc4, 0x44, 0x89, 0x85, + 0xd1, 0x79, 0x46, 0x36, 0xbc, 0x1d, 0x58, 0x2f, 0x3d, 0x10, 0x1a, 0x33 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_148_private[] = { +/* dIUT */ + 0x03, 0x2f, 0xc7, 0x90, 0x86, 0x46, 0x32, 0x63, 0x0c, 0x49, 0xa2, 0x9e, + 0x9a, 0xd0, 0xfb, 0x6d, 0x10, 0xf2, 0xb5, 0x8c +}; +/* QIUTx = 0000000779cfb3e17c902a2584ed3382a8bed8262db98424 */ +/* QIUTy = 000000004af273875f8a2ab9a94ac0d1e4a23390b2bb505c */ +static const uint8_t nist_kas_ecc_cdh_testvector_148_out[] = { +/* ZIUT */ + 0x02, 0x77, 0xc4, 0xa7, 0x6e, 0x16, 0x13, 0xb2, 0xed, 0xe6, 0x99, 0xa6, + 0x75, 0xc1, 0x64, 0x5a, 0x78, 0x60, 0x75, 0x00, 0x9e +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_149_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x01, 0xf8, 0x58, 0x1e, 0xc6, 0x1d, 0xf1, 0x40, 0x92, + 0x27, 0xaa, 0xb7, 0xa0, 0x15, 0xf2, 0xc7, 0x1d, 0x29, 0xe3, 0x71, 0x6c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_149_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x01, 0xc1, 0xf5, 0x1c, 0xc4, 0x18, 0x5b, 0x68, 0xa2, + 0x60, 0xe3, 0x1b, 0x4b, 0x00, 0xc0, 0x3a, 0x44, 0x03, 0xf6, 0x5c, 0x25 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_149_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0xc1, 0xde, 0x5b, 0xb4, 0x0e, 0x70, 0x93, 0x3e, + 0xd7, 0xdb, 0x84, 0xce, 0x2c, 0xb4, 0x68, 0xcb, 0xba, 0x29, 0x9b, 0x3a +}; +/* QIUTx = 00000005ffe0f16018bd4bdee5f73bfdad04d713f2216f50 */ +/* QIUTy = 000000042361c881f0081cb0544efab0c3b34f59eaadeec4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_149_out[] = { +/* ZIUT */ + 0x03, 0xc6, 0x48, 0x1d, 0xac, 0x38, 0x7a, 0xf3, 0x9e, 0x8c, 0x09, 0xa5, + 0x53, 0x06, 0x8a, 0xc4, 0x96, 0xee, 0xa0, 0x36, 0x91 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_150_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0xba, 0x22, 0xfb, 0xda, 0xaa, 0xa8, 0x06, 0xc8, + 0x57, 0x0f, 0x14, 0xad, 0x4c, 0x88, 0x2a, 0x61, 0x0c, 0xcb, 0x8d, 0x84 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_150_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x06, 0xd4, 0x43, 0x8e, 0x52, 0x8c, 0xa8, 0x87, 0xb0, + 0x5b, 0xd2, 0x56, 0x4d, 0xf9, 0x3b, 0xef, 0x9b, 0xf6, 0x60, 0xda, 0x78 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_150_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x88, 0x12, 0x75, 0xba, 0x48, 0xbe, 0xa0, 0xbe, + 0xcc, 0x02, 0x11, 0x90, 0x34, 0x67, 0xf5, 0xd0, 0xaa, 0xe3, 0x21, 0xaa +}; +/* QIUTx = 0000000776e40fe7149985337ef1b6c9b830cb3608752aa6 */ +/* QIUTy = 000000058e6ecbb27b0b2d3cd0e3a7ba538de3576fd5b9f6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_150_out[] = { +/* ZIUT */ + 0x07, 0xb5, 0xd0, 0x96, 0xd0, 0x6d, 0x41, 0xc3, 0xad, 0x64, 0x58, 0xcc, + 0x93, 0x41, 0x7e, 0x6f, 0xac, 0xc9, 0x9b, 0xc7, 0xb8 +}; +/* [K-233] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_151_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0xf4, 0x0e, 0x34, 0xb3, 0xed, 0x4a, 0x1b, 0x2d, 0x40, + 0xc0, 0x56, 0xfb, 0x75, 0xf2, 0xad, 0x54, 0x3c, 0x89, 0x7c, 0xfd, 0x82, + 0xf5, 0x42, 0xcf, 0x74, 0x6a, 0x0f, 0x20, 0x2f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_151_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xc1, 0x30, 0xa1, 0xab, 0xe9, 0x2b, 0xc4, 0xc9, 0x77, + 0xc8, 0x00, 0x77, 0x79, 0x96, 0xcc, 0xc5, 0x0b, 0x90, 0xdf, 0x99, 0x1a, + 0x2e, 0x81, 0xdd, 0x51, 0x5c, 0x18, 0x85, 0x99 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_151_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x13, 0x5a, 0x5b, 0x8c, 0x3c, 0xe0, 0x47, 0xfb, 0xc5, + 0xdf, 0x26, 0x27, 0x7d, 0x3b, 0xf8, 0x3a, 0xc3, 0x3d, 0xda, 0xdb, 0x5c, + 0xf4, 0xa0, 0x50, 0xca, 0x82, 0xbe, 0x48, 0xf0 +}; +/* QIUTx = 000001a53e5c138b3d83905d563aa1db01274633c986b52f78225a92e33e7952 */ +/* QIUTy = 000000ecabd3e2e26729a965604e560ed4498a22b31c39642e1cf99b1dde3ec7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_151_out[] = { +/* ZIUT */ + 0x00, 0xa8, 0x22, 0xb1, 0x41, 0xca, 0x1f, 0x5a, 0xd3, 0x28, 0x99, 0xe6, + 0x8c, 0x54, 0xd1, 0xfe, 0xc3, 0xdf, 0x81, 0x00, 0xdf, 0x48, 0x5e, 0xbf, + 0x1c, 0x58, 0x68, 0xa9, 0xac, 0x89 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_152_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xc8, 0x64, 0xc2, 0xa4, 0x62, 0xa9, 0x36, 0x3a, 0x4a, + 0xc3, 0xd8, 0x18, 0x21, 0x1b, 0xca, 0x03, 0x69, 0x47, 0x2d, 0x18, 0x62, + 0x88, 0xa2, 0x75, 0x67, 0x43, 0x3b, 0xda, 0x45 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_152_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x68, 0x9d, 0x4d, 0x00, 0x06, 0xeb, 0xa0, 0x54, 0xdc, + 0x69, 0xfc, 0xc0, 0x78, 0x67, 0x80, 0xfb, 0x5f, 0x74, 0xd3, 0x98, 0x92, + 0x13, 0x50, 0x4e, 0x2f, 0x6e, 0x66, 0x69, 0x80 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_152_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x51, 0xbe, 0x6f, 0xbc, 0xd4, 0x87, 0x8c, 0x55, 0x43, + 0x9b, 0x0b, 0xcb, 0xbe, 0x5e, 0xa8, 0xe8, 0x4b, 0xc9, 0xdb, 0x89, 0xe7, + 0x0a, 0x8e, 0x8e, 0xbf, 0x34, 0x78, 0x2d, 0xa8 +}; +/* QIUTx = 000001c5a1e5d3ee516e3ede723fa2d5cd3456b116326303c5ee49273a5604c4 */ +/* QIUTy = 000000568d0fe7130295541bfa265074147546e9733736ba007559d716d8e094 */ +static const uint8_t nist_kas_ecc_cdh_testvector_152_out[] = { +/* ZIUT */ + 0x01, 0x66, 0x26, 0x82, 0xbe, 0xc2, 0xdf, 0xae, 0x05, 0xe3, 0x85, 0x87, + 0xc8, 0xe6, 0xa4, 0xd1, 0x8a, 0xef, 0x4c, 0xb3, 0x41, 0x69, 0x89, 0xc4, + 0x7c, 0x11, 0xbb, 0xe2, 0x81, 0x0f +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_153_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x78, 0x2d, 0x82, 0xfc, 0xd2, 0x11, 0xc0, 0x24, 0x7c, + 0x87, 0xe6, 0x57, 0xef, 0xcc, 0x5d, 0x2f, 0xf6, 0xb0, 0x5e, 0xb9, 0x35, + 0x33, 0x0a, 0x53, 0x90, 0x3f, 0xb3, 0xbf, 0xa3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_153_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xcc, 0xe8, 0x30, 0xa5, 0x15, 0xd6, 0x90, 0xab, 0x98, + 0x14, 0x95, 0x79, 0xad, 0x34, 0x81, 0x38, 0x48, 0x59, 0xe5, 0x65, 0xd0, + 0x7f, 0xa6, 0x1f, 0x50, 0xeb, 0xd6, 0x69, 0xa2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_153_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x2e, 0xcc, 0xa5, 0x95, 0xe5, 0x5e, 0x6c, 0x85, 0xc5, + 0xaf, 0x78, 0xc5, 0x95, 0x40, 0xfd, 0xb7, 0x49, 0x00, 0x3f, 0xf4, 0xec, + 0x36, 0x1c, 0x38, 0xb4, 0x8e, 0x7d, 0xa6, 0xbc +}; +/* QIUTx = 0000005a48fac476c31cad0c68e64e65e687ae4418fb5d3b4bb2abb990dd0de4 */ +/* QIUTy = 0000002d9add706626f2859ece110df2dde89faf3e8aac433e2595e23c274082 */ +static const uint8_t nist_kas_ecc_cdh_testvector_153_out[] = { +/* ZIUT */ + 0x00, 0x21, 0x5d, 0x51, 0x1c, 0xb9, 0x5e, 0x0e, 0x07, 0x3e, 0xe9, 0x99, + 0x90, 0x8a, 0x7a, 0x84, 0x4a, 0xfd, 0x75, 0xc9, 0xac, 0xb7, 0xa9, 0xd7, + 0x24, 0xf7, 0xfd, 0x32, 0x2b, 0x01 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_154_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x8d, 0x80, 0x0d, 0x37, 0x67, 0xab, 0xf5, 0x73, 0x16, + 0x95, 0x75, 0x4e, 0xe8, 0x82, 0x9b, 0x85, 0x8f, 0xf4, 0xeb, 0x60, 0x4a, + 0x44, 0x8a, 0xd6, 0x64, 0x90, 0xb4, 0x9c, 0x19 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_154_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0xbc, 0x0f, 0x03, 0x39, 0x64, 0x9a, 0xd4, 0xd7, 0xb7, + 0xcf, 0xf3, 0xfc, 0xa9, 0xe9, 0x65, 0xa3, 0x86, 0x25, 0xe8, 0xf4, 0x5b, + 0xc9, 0x60, 0x2a, 0x33, 0xc0, 0x79, 0x8a, 0x33 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_154_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x6a, 0x7c, 0x03, 0x89, 0x2d, 0xf1, 0x84, 0xd5, 0x6c, + 0xdc, 0xcb, 0x9d, 0x5e, 0x9a, 0x16, 0x48, 0x3a, 0x6c, 0x93, 0x88, 0xae, + 0x21, 0x2a, 0xa9, 0x26, 0xc8, 0xfd, 0xfb, 0x5e +}; +/* QIUTx = 0000014aaf880e81db69aba2b403bbda7f361e3339b483ce2699f30bf5281ead */ +/* QIUTy = 000001b71559bd7d9384e517b87f1138a696fbceb3510d8c41c2158d4aa3e5b2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_154_out[] = { +/* ZIUT */ + 0x01, 0x39, 0x4e, 0x02, 0xc7, 0x01, 0x04, 0xf2, 0xa5, 0x30, 0x8b, 0x2d, + 0x10, 0x1b, 0x02, 0xc7, 0x0e, 0xf2, 0xd1, 0x35, 0x40, 0x60, 0x2b, 0x8e, + 0x8f, 0x82, 0xdc, 0x6d, 0x56, 0x9f +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_155_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x4a, 0x3e, 0x12, 0x1a, 0xdd, 0x7a, 0x52, 0x67, 0xf5, + 0xca, 0xd2, 0x04, 0xb3, 0xf4, 0x92, 0x15, 0x08, 0x47, 0x86, 0xb2, 0x3f, + 0x8d, 0x94, 0xd9, 0xfd, 0xa0, 0x2e, 0x0f, 0x19 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_155_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x39, 0x4f, 0xea, 0x17, 0x5d, 0xad, 0x9b, 0x34, 0xd5, + 0x25, 0x43, 0x46, 0x54, 0xd0, 0xc8, 0x66, 0x37, 0x92, 0x6c, 0xac, 0x3a, + 0x32, 0x92, 0xa2, 0xe4, 0xa5, 0x14, 0xb5, 0xf5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_155_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x2e, 0x2f, 0xf8, 0x79, 0x1b, 0xc6, 0x4c, 0x00, 0xf3, + 0xb0, 0xf1, 0xd5, 0xd5, 0xcf, 0xb9, 0xdd, 0xb3, 0xb1, 0x93, 0x81, 0x45, + 0x99, 0xf7, 0xdb, 0xdd, 0xed, 0xef, 0xcf, 0xa3 +}; +/* QIUTx = 0000018045cc9e65f6e275e322a62c18efe2d00cf93995feb53561273a3f1306 */ +/* QIUTy = 00000164e0073c0d4b3e12e22f837bd3fec421e3bb09e0c0dd997422830f6403 */ +static const uint8_t nist_kas_ecc_cdh_testvector_155_out[] = { +/* ZIUT */ + 0x00, 0x85, 0x56, 0xa4, 0xc3, 0xa8, 0x90, 0x6d, 0xdb, 0xcb, 0x94, 0x60, + 0x99, 0xca, 0x5d, 0xbe, 0x7b, 0xdb, 0x6c, 0xd8, 0xf3, 0x7f, 0xbb, 0x50, + 0xc9, 0x6f, 0xce, 0xfe, 0xd3, 0x2d +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_156_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x89, 0x66, 0x78, 0x88, 0xf8, 0x42, 0x5c, 0x5a, 0x62, + 0x31, 0x34, 0x62, 0x2f, 0x1e, 0xa9, 0xd9, 0xaf, 0x36, 0xdf, 0x97, 0x72, + 0xc4, 0x10, 0xd6, 0xe3, 0x1f, 0x2b, 0x4d, 0xb8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_156_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x84, 0x43, 0x0f, 0xa4, 0x71, 0x64, 0xd1, 0xc0, 0xeb, + 0x97, 0x04, 0x2a, 0x44, 0xcb, 0xef, 0x40, 0x0b, 0xbb, 0x54, 0x5f, 0xae, + 0xa4, 0xef, 0x49, 0xba, 0x5e, 0x3b, 0xef, 0x42 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_156_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x66, 0x97, 0x2e, 0x71, 0x56, 0x67, 0x46, 0xf2, 0xf7, + 0x6c, 0x87, 0x79, 0x37, 0x74, 0x05, 0x4e, 0xa2, 0x75, 0xe2, 0xa7, 0xe2, + 0x7a, 0xb7, 0xc2, 0xd0, 0x5c, 0x5f, 0x24, 0x12 +}; +/* QIUTx = 00000020226dd73e318e4fc8d49dd43e59e260193d1bb248cbe4c06b4d6b8389 */ +/* QIUTy = 000000ed12a4f389696ab31c93ea3ec4d8eaf18be097fc9152e2c42b73ff4528 */ +static const uint8_t nist_kas_ecc_cdh_testvector_156_out[] = { +/* ZIUT */ + 0x00, 0x4e, 0xa6, 0xe0, 0xe3, 0x4e, 0xc7, 0xc9, 0xbb, 0xad, 0x47, 0xf0, + 0xf6, 0xf8, 0xec, 0x06, 0x08, 0xe7, 0x36, 0xd9, 0x1e, 0x0e, 0x56, 0xcf, + 0x3e, 0x5c, 0xff, 0xe8, 0xc3, 0x70 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_157_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x64, 0xda, 0x09, 0x92, 0x25, 0xeb, 0x3c, 0x64, 0x1f, + 0xc8, 0x3c, 0x77, 0x20, 0x4a, 0x39, 0x6e, 0xab, 0x94, 0x95, 0xb1, 0x2a, + 0x22, 0xf6, 0x8e, 0x7a, 0x4b, 0x83, 0x99, 0xd5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_157_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xcd, 0x98, 0xf2, 0x70, 0x4c, 0x74, 0x94, 0xe6, 0xd2, + 0x03, 0x75, 0xe7, 0x45, 0x28, 0xc8, 0xf5, 0x6f, 0x86, 0x7e, 0x9d, 0xd7, + 0x63, 0x29, 0x81, 0x42, 0xea, 0x01, 0x72, 0x4b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_157_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x1e, 0x53, 0xba, 0xa1, 0x6b, 0xc0, 0x26, 0x2b, 0x53, + 0x29, 0xa7, 0x11, 0xb0, 0xeb, 0x18, 0x8a, 0x1b, 0xca, 0x7e, 0xf4, 0xb5, + 0xc8, 0x50, 0x61, 0x22, 0x5d, 0x41, 0xd4, 0xa9 +}; +/* QIUTx = 0000007d6d785fa323174eb9cde5b705428e4019244835bc94702f280c25ffe5 */ +/* QIUTy = 0000019aa0ef433074c484d14e611372f03ef8912f1a8246ceb1e90c817db3db */ +static const uint8_t nist_kas_ecc_cdh_testvector_157_out[] = { +/* ZIUT */ + 0x01, 0x60, 0xd0, 0xb9, 0xb9, 0x2a, 0x4a, 0xcd, 0x08, 0x97, 0x38, 0xfd, + 0x48, 0x9a, 0xe3, 0x97, 0x34, 0x55, 0x1e, 0x88, 0x8f, 0xd0, 0x5a, 0x02, + 0x0c, 0xe2, 0x64, 0x98, 0x27, 0x0a +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_158_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x33, 0xa8, 0xb0, 0x8a, 0x3c, 0x33, 0xc3, 0x43, 0x03, + 0x2c, 0xed, 0x1c, 0x0f, 0x5e, 0x82, 0x6f, 0x93, 0x2d, 0xee, 0x87, 0x9e, + 0xc1, 0x60, 0x7a, 0x2a, 0xf5, 0xd4, 0x62, 0x98 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_158_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x6c, 0x4f, 0x27, 0xa4, 0x9b, 0x51, 0xa8, 0x9f, 0x6d, + 0x09, 0x60, 0x16, 0x0b, 0xa5, 0xb8, 0xfe, 0xc0, 0x8d, 0xd2, 0xcd, 0x4b, + 0xc9, 0x09, 0xa4, 0x90, 0xae, 0xbe, 0x4f, 0x7b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_158_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x42, 0xa8, 0x03, 0x2a, 0x11, 0xd1, 0x65, 0x77, 0x55, + 0xc4, 0x9e, 0x47, 0x70, 0x33, 0xb0, 0xd3, 0x41, 0xda, 0x2f, 0xe9, 0x93, + 0xa4, 0x57, 0x7b, 0x41, 0xa4, 0x0c, 0xee, 0x1a +}; +/* QIUTx = 000001f6629697da620d597fc1f51c83374213f37e952fc117ee65a9e766aefb */ +/* QIUTy = 0000002b36dedc787ac951d2879d72414da2e7575a6cd7c42e0fa20b32d461f7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_158_out[] = { +/* ZIUT */ + 0x00, 0x38, 0x38, 0x1b, 0x34, 0x2e, 0xfa, 0xa7, 0x0b, 0xb7, 0x9a, 0xdb, + 0x76, 0xce, 0xb7, 0x75, 0xde, 0x5f, 0x45, 0xf8, 0x63, 0x55, 0x9e, 0xca, + 0xee, 0x1d, 0xdb, 0xbd, 0x03, 0x13 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_159_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xcf, 0xe1, 0x5f, 0x86, 0x1a, 0xa0, 0x15, 0x34, 0x85, + 0xf3, 0x8a, 0xc0, 0x33, 0xdf, 0x9c, 0x8d, 0x81, 0x2a, 0xfd, 0xe1, 0x67, + 0xb8, 0x91, 0x8b, 0xb9, 0x4a, 0x08, 0xd9, 0x63 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_159_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0xbe, 0xbf, 0x06, 0x7f, 0x85, 0x12, 0x6d, 0x11, 0x49, + 0x32, 0x16, 0x21, 0x64, 0x20, 0x1b, 0x13, 0x74, 0xbf, 0x18, 0x40, 0xaa, + 0x11, 0xd5, 0xe2, 0x50, 0x63, 0x9d, 0x06, 0x08 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_159_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x43, 0xe5, 0x77, 0x09, 0x78, 0x19, 0x5f, 0x91, 0x71, + 0x52, 0xf0, 0x57, 0xba, 0x1f, 0xb0, 0x15, 0x6d, 0x89, 0x4d, 0x32, 0xe8, + 0xbb, 0x54, 0xc7, 0xf6, 0x2f, 0x73, 0x40, 0xa6 +}; +/* QIUTx = 000001487d1fdabccd7d89da25685b042980ab170aee3c11f31180e3b7c50a4a */ +/* QIUTy = 0000017e383dd65a1ec8a409007f75035e5b161335d9c7756ed970490fbd171a */ +static const uint8_t nist_kas_ecc_cdh_testvector_159_out[] = { +/* ZIUT */ + 0x01, 0x22, 0x16, 0x9f, 0x1d, 0xff, 0x44, 0x5e, 0xc6, 0x63, 0x27, 0x03, + 0x75, 0xdf, 0xe9, 0x14, 0x01, 0x6c, 0x38, 0xce, 0x6c, 0x2d, 0x40, 0xd0, + 0xb8, 0x09, 0x8a, 0xbc, 0x60, 0xac +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_160_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x76, 0x3e, 0x28, 0x6b, 0xe5, 0x07, 0x40, 0xb7, 0xf8, + 0xbd, 0x78, 0xfa, 0x70, 0xbc, 0xac, 0x88, 0x0d, 0xf3, 0xd7, 0x37, 0x1e, + 0xb3, 0x3f, 0xda, 0x24, 0x53, 0xb3, 0xed, 0x23 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_160_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x57, 0xbe, 0x6c, 0x5f, 0x7d, 0x99, 0x0b, 0x75, 0x43, + 0x98, 0x68, 0x33, 0x9a, 0xe3, 0x27, 0xaf, 0x04, 0xa0, 0x49, 0xb3, 0x8b, + 0x92, 0x33, 0x2b, 0x9c, 0xb8, 0xcb, 0x27, 0xd9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_160_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x4c, 0x67, 0xc6, 0x10, 0x3e, 0x62, 0x12, 0x46, 0x00, + 0xa0, 0xd9, 0xe9, 0x23, 0xdc, 0x21, 0x7a, 0x02, 0x2f, 0x57, 0xc6, 0xfe, + 0xb2, 0x19, 0xc7, 0x03, 0x33, 0x4f, 0xf3, 0x39 +}; +/* QIUTx = 0000002352fe9341e62c609fc1538e0270405e7001d747b87500e644a112c5d9 */ +/* QIUTy = 00000041f3b15b714a6f7ef647e23665ea530efcbe19b0740436cda812e83939 */ +static const uint8_t nist_kas_ecc_cdh_testvector_160_out[] = { +/* ZIUT */ + 0x00, 0x54, 0xd4, 0x7c, 0x9d, 0x0a, 0x9f, 0xee, 0x25, 0x81, 0x22, 0x32, + 0x6b, 0xe2, 0x5d, 0xaf, 0x35, 0xf0, 0xba, 0x0b, 0x84, 0x49, 0xe1, 0x6b, + 0x46, 0x23, 0xa8, 0xc0, 0xfd, 0x7e +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_161_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xbc, 0x8a, 0x71, 0xad, 0x4c, 0x11, 0x34, 0xde, 0xf0, + 0x26, 0xe4, 0x72, 0x3e, 0x31, 0x02, 0x23, 0xfb, 0x2c, 0x58, 0x59, 0xbc, + 0x75, 0x94, 0x05, 0x4c, 0x89, 0x4d, 0xa5, 0x52 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_161_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xc3, 0x65, 0x05, 0x63, 0x50, 0x55, 0x35, 0x03, 0x3c, + 0x7a, 0x6c, 0x44, 0x8d, 0x73, 0xbf, 0xa0, 0x8f, 0xb8, 0x37, 0x02, 0x34, + 0xc7, 0xfd, 0xba, 0xc1, 0xb3, 0x4d, 0xaa, 0x22 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_161_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x19, 0xe5, 0x4d, 0xa8, 0x72, 0x99, 0x5e, 0xb3, 0xdc, + 0xdc, 0xcc, 0x50, 0x41, 0x8e, 0xc3, 0x51, 0x40, 0x08, 0x89, 0xfa, 0xe7, + 0x5a, 0x0b, 0xa4, 0xdc, 0xff, 0x25, 0xf1, 0xf9 +}; +/* QIUTx = 0000015e67eaebe52ba37f5b73a199d950812cec1012fd410581444bbf23e0c8 */ +/* QIUTy = 00000022055ef821df33042fb8316ddad76485dbd2590e2f5498a914e4f0ad39 */ +static const uint8_t nist_kas_ecc_cdh_testvector_161_out[] = { +/* ZIUT */ + 0x00, 0x71, 0xae, 0xd3, 0x9f, 0x5c, 0x44, 0xa7, 0xff, 0x72, 0xdb, 0x3e, + 0x0f, 0x82, 0x84, 0xda, 0x39, 0xdf, 0xb2, 0xd8, 0x94, 0xf2, 0x78, 0xd2, + 0x00, 0x6f, 0x9d, 0x26, 0x86, 0xe3 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_162_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x6c, 0xc1, 0xae, 0x13, 0xfb, 0x34, 0x82, 0x52, 0x49, + 0x30, 0x21, 0xcd, 0x61, 0x46, 0xd5, 0x31, 0xf0, 0xb7, 0x22, 0x84, 0x2a, + 0x44, 0xc7, 0x97, 0x96, 0x89, 0xf1, 0xff, 0x38 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_162_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x8c, 0x09, 0x63, 0xff, 0x0e, 0xa3, 0x70, 0x48, 0xc9, + 0xf6, 0xf4, 0x76, 0x44, 0xf2, 0xa7, 0xc8, 0xc5, 0x03, 0x86, 0x3c, 0x27, + 0xcf, 0x21, 0xee, 0x6e, 0x0a, 0x32, 0x24, 0xea +}; +static const uint8_t nist_kas_ecc_cdh_testvector_162_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x13, 0xa5, 0xff, 0xc9, 0xa0, 0xf7, 0x06, 0x9c, 0x1c, + 0x66, 0x14, 0x86, 0x99, 0x61, 0x2e, 0x5c, 0xfa, 0xb7, 0xe2, 0xbf, 0x7b, + 0x32, 0x55, 0xf1, 0x81, 0xa0, 0x22, 0x71, 0x92 +}; +/* QIUTx = 0000018de4dc4f6a4de5c3638ebba24dc7064983b159f55b139c7680a1cb90d1 */ +/* QIUTy = 00000135532d8148af3e227d4a8960e768c565f72c1ac0a1c9a7bd185cf994d0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_162_out[] = { +/* ZIUT */ + 0x01, 0xca, 0x68, 0xea, 0xd4, 0xed, 0xdc, 0x88, 0x47, 0xa3, 0xa6, 0x61, + 0xcc, 0x66, 0x28, 0xe0, 0x76, 0xbd, 0xd4, 0xb4, 0x50, 0x47, 0xec, 0xe7, + 0x22, 0x45, 0xd0, 0x94, 0xdd, 0x3b +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_163_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xe4, 0x9e, 0x18, 0x2a, 0xc5, 0xd9, 0x32, 0xbe, 0x8b, + 0x05, 0xfe, 0x34, 0x0e, 0x8c, 0xb7, 0x2d, 0xf3, 0x56, 0x47, 0xde, 0xcd, + 0x67, 0x9a, 0x8c, 0x59, 0xb5, 0xd8, 0xfb, 0xfa +}; +static const uint8_t nist_kas_ecc_cdh_testvector_163_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x81, 0xb9, 0x5a, 0x96, 0x5a, 0xbd, 0x16, 0xec, 0x24, + 0x30, 0xc2, 0x6d, 0xd0, 0x71, 0x98, 0x4e, 0x85, 0x4a, 0x96, 0x7f, 0xf1, + 0x14, 0xee, 0x78, 0x31, 0xbd, 0x31, 0x4b, 0x2a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_163_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x2f, 0x5d, 0x2a, 0x7e, 0x08, 0x77, 0xa4, 0xc9, 0x90, + 0x73, 0x73, 0x23, 0x86, 0xe8, 0xd5, 0x97, 0x34, 0xa2, 0x3d, 0xd7, 0xf0, + 0xdf, 0x7f, 0xcd, 0x54, 0xd9, 0x41, 0xe7, 0x60 +}; +/* QIUTx = 0000014798094680cbd32fb1ee9dcaa6b8739a556305235933fb27157d319e57 */ +/* QIUTy = 000001c855f0d453c1ffb5f668b32a8b3e309e0e8101bc39b6dbe7de214015e3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_163_out[] = { +/* ZIUT */ + 0x01, 0x7a, 0x89, 0x3b, 0x2e, 0x09, 0x07, 0x80, 0xff, 0x8d, 0xaa, 0xf3, + 0x58, 0x8f, 0x9d, 0xfc, 0x0a, 0xc4, 0xdf, 0xe1, 0xf1, 0xe2, 0x63, 0x69, + 0x7a, 0x9d, 0x1f, 0x39, 0x8a, 0xb3 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_164_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x59, 0x8b, 0x2f, 0xdb, 0x5b, 0xf1, 0xa3, 0x95, 0x1f, + 0xb9, 0xec, 0x01, 0x6e, 0xcb, 0x4d, 0x28, 0xf6, 0x6c, 0x2e, 0x9d, 0x13, + 0x59, 0x67, 0x86, 0x59, 0x35, 0x85, 0xd7, 0x19 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_164_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0xef, 0x65, 0xca, 0xf1, 0x57, 0x95, 0xd1, 0x4a, 0x0b, + 0xe8, 0x9c, 0xac, 0x7c, 0x68, 0x03, 0x23, 0xbc, 0x59, 0x80, 0x3b, 0xa8, + 0x74, 0xcb, 0x29, 0x68, 0x67, 0x2c, 0xb8, 0xa9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_164_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x65, 0x2a, 0x11, 0xf6, 0xc3, 0x11, 0x7f, 0x13, 0x26, + 0xfa, 0x68, 0x77, 0x40, 0x5c, 0xec, 0x73, 0x31, 0xc4, 0xf1, 0x46, 0xa9, + 0x7f, 0x74, 0xab, 0x0c, 0x44, 0xde, 0x01, 0xb7 +}; +/* QIUTx = 0000002cd6d4c1d2cc5e34205eadb94f4cfd35bb569da722c4d9b19b8d5cc2de */ +/* QIUTy = 000000ea3004e5b0930df7f8bda314c8bc1145463eb60022cd2dcf6c0c824e50 */ +static const uint8_t nist_kas_ecc_cdh_testvector_164_out[] = { +/* ZIUT */ + 0x00, 0x41, 0xfa, 0x5f, 0xdf, 0x49, 0x5b, 0x88, 0x56, 0x99, 0x24, 0x9b, + 0x77, 0x46, 0x33, 0x4b, 0x76, 0xc5, 0x9e, 0x1c, 0x91, 0x7b, 0xfc, 0x1a, + 0xe3, 0x71, 0xb9, 0x69, 0x41, 0xf4 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_165_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0xb6, 0xcf, 0xf3, 0xb7, 0xfa, 0x21, 0x5e, 0x37, 0x86, + 0x05, 0xc9, 0x3f, 0x86, 0xf5, 0xcd, 0x38, 0x45, 0xf4, 0x5f, 0xbd, 0xe8, + 0xbe, 0x07, 0x9d, 0xec, 0x29, 0xbc, 0x88, 0x62 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_165_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x66, 0x22, 0x2e, 0xfa, 0x5d, 0xba, 0x9e, 0x85, 0x8c, + 0x24, 0x5d, 0xbb, 0x5d, 0xa6, 0x68, 0x23, 0x9a, 0xb5, 0xba, 0x72, 0x86, + 0x18, 0xfb, 0x85, 0xa9, 0x0d, 0xdc, 0x76, 0x0a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_165_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x2a, 0xd5, 0xf7, 0x1c, 0x63, 0x84, 0xaf, 0x62, 0x68, + 0x9b, 0x35, 0xc2, 0x4c, 0x4d, 0xdf, 0xb3, 0x5a, 0xcf, 0x81, 0x06, 0xcb, + 0x0c, 0x19, 0x50, 0x2c, 0x2c, 0xa1, 0x84, 0xaf +}; +/* QIUTx = 000000fe1b52408a712841bd62f0ee51307f26331d402bcc3a5ab0405d1c5e80 */ +/* QIUTy = 0000010a731a7d6a6a4f5b40b2eaa810c1902db27b28d297bc05f3714cacafc0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_165_out[] = { +/* ZIUT */ + 0x01, 0x5f, 0x5a, 0xdb, 0xa5, 0x9d, 0x1e, 0xe0, 0x16, 0x96, 0xce, 0xcc, + 0xe4, 0xb6, 0x3e, 0x78, 0xe6, 0x85, 0x08, 0x30, 0x3e, 0xe4, 0x96, 0xff, + 0x5a, 0xbc, 0xea, 0x25, 0xad, 0x3b +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_166_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xcf, 0x40, 0x2a, 0xeb, 0xc3, 0xe4, 0x24, 0x7a, 0x9a, + 0xb4, 0x3d, 0xa9, 0x75, 0x51, 0x76, 0xa8, 0x10, 0xe0, 0x11, 0xf9, 0xfd, + 0x97, 0x7d, 0xe1, 0xbe, 0x2f, 0xd5, 0x34, 0xfb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_166_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0xba, 0xc4, 0x5f, 0xa4, 0x2d, 0x60, 0x5a, 0xd3, 0x47, + 0x9c, 0x7c, 0x43, 0xe7, 0x24, 0x91, 0x07, 0x16, 0x73, 0x79, 0x53, 0xcc, + 0x85, 0x04, 0xaf, 0x14, 0xf3, 0x31, 0xd3, 0x4f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_166_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x6f, 0x01, 0xcb, 0x54, 0x78, 0x1c, 0xbd, 0xa6, 0xd8, + 0x8d, 0xeb, 0x59, 0x84, 0x3a, 0xe0, 0x83, 0x6b, 0x1a, 0xf6, 0x83, 0xef, + 0xc7, 0x56, 0x50, 0xbe, 0x84, 0xf2, 0x08, 0xa7 +}; +/* QIUTx = 0000004d00a8f0820da9097fe50e8e7defdac29607dd4cb1dd881d4e61f1e78b */ +/* QIUTy = 0000008a4a8e9c811b444367952752ab8c2a5198efb28fbedbf3fbd701a857a9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_166_out[] = { +/* ZIUT */ + 0x00, 0x3d, 0x5c, 0x29, 0xb3, 0x75, 0x3e, 0x89, 0xce, 0x50, 0x64, 0x57, + 0x53, 0x93, 0x39, 0x2b, 0x37, 0x7c, 0xa6, 0x57, 0xa0, 0xb7, 0x38, 0x72, + 0xc8, 0x21, 0x65, 0xfc, 0x43, 0xae +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_167_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xf3, 0x8c, 0xcc, 0xcf, 0x08, 0xe5, 0xbd, 0xff, 0x3b, + 0xb3, 0x5f, 0x7e, 0x75, 0xbd, 0xce, 0xd6, 0x8d, 0x37, 0x91, 0xdc, 0xf7, + 0x84, 0x3c, 0xa8, 0x8f, 0xf0, 0x92, 0x13, 0x6d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_167_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x5e, 0xd7, 0x69, 0x7a, 0x4b, 0x8c, 0x99, 0xd0, 0x14, + 0x78, 0x28, 0xf6, 0xc8, 0x61, 0xff, 0xc9, 0xcf, 0xb0, 0xf3, 0x3d, 0xce, + 0x9d, 0x14, 0xb0, 0x73, 0x1e, 0x1d, 0xa2, 0x62 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_167_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x5d, 0xc1, 0xba, 0x18, 0x39, 0xf5, 0xd1, 0xfe, 0xa8, + 0x5a, 0xb3, 0x61, 0x4c, 0x55, 0xa9, 0xc5, 0xfe, 0x60, 0x08, 0x53, 0xc7, + 0x1a, 0x61, 0x98, 0x3c, 0x7d, 0xc8, 0x2d, 0xe2 +}; +/* QIUTx = 000000b6cb6ffa4e2eabcf7b987ebb520165a8ec9a22a6f9ffb100f38172a0fb */ +/* QIUTy = 000000d39814e1852476e56e89ce8cdd64372840c01570a86940ace24bb9cf6a */ +static const uint8_t nist_kas_ecc_cdh_testvector_167_out[] = { +/* ZIUT */ + 0x00, 0x7c, 0x01, 0xf9, 0x06, 0xca, 0xa5, 0x90, 0x89, 0x8a, 0x09, 0xf4, + 0x6b, 0x6f, 0x53, 0x83, 0x65, 0x8e, 0x7f, 0xee, 0x65, 0x6a, 0xca, 0x0f, + 0x11, 0x1f, 0x22, 0x93, 0x99, 0x60 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_168_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0xe3, 0x28, 0x57, 0x1d, 0xf9, 0x33, 0xac, 0xfd, 0x4c, + 0x96, 0xf3, 0xc4, 0xbd, 0xe7, 0x1e, 0x91, 0x75, 0xcb, 0xcd, 0x62, 0xae, + 0xec, 0xd7, 0x63, 0x84, 0x74, 0x4a, 0x0f, 0x3f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_168_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x9f, 0xf4, 0x8a, 0xae, 0x0c, 0x25, 0x2e, 0xda, 0x8d, + 0x34, 0x0b, 0x25, 0xc4, 0xdd, 0xa0, 0x1a, 0x2f, 0x21, 0xaa, 0xa3, 0x5d, + 0x39, 0xba, 0xf0, 0x36, 0x69, 0x6a, 0x11, 0x01 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_168_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x24, 0x1e, 0x1d, 0xf5, 0x58, 0x70, 0x31, 0xdd, 0xda, + 0xe1, 0x96, 0x89, 0x1c, 0x28, 0x82, 0x1c, 0xc7, 0x87, 0x9a, 0xd3, 0x58, + 0x32, 0xae, 0x71, 0x8f, 0x6e, 0x79, 0x2e, 0x66 +}; +/* QIUTx = 000001c172cee2b76503eb4d90b39ddace825b23c32375cb68eaecd7348490a3 */ +/* QIUTy = 000000c246ef9c6e2fadac77c73ee9dd5adee828b7918417395b5997be1a0278 */ +static const uint8_t nist_kas_ecc_cdh_testvector_168_out[] = { +/* ZIUT */ + 0x01, 0x9e, 0xec, 0xe7, 0xd3, 0xfa, 0xfc, 0x92, 0x74, 0xd3, 0x61, 0xc6, + 0xfa, 0xfd, 0x9e, 0xfd, 0x9e, 0xe4, 0x85, 0xcb, 0xac, 0xb3, 0xba, 0xaf, + 0x68, 0x34, 0xfe, 0xb4, 0xdf, 0x6a +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_169_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xf4, 0xaa, 0x7f, 0x93, 0x40, 0xa9, 0xda, 0x46, 0xc4, + 0xf0, 0x67, 0x28, 0x75, 0x3a, 0x4a, 0xdc, 0x5a, 0xf5, 0x3a, 0x4d, 0xcb, + 0x46, 0x7f, 0x70, 0xb4, 0x87, 0x3d, 0xa7, 0x85 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_169_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x7f, 0x32, 0x1e, 0x2b, 0xc4, 0xe2, 0x9a, 0x68, 0xac, + 0x23, 0xc7, 0x7c, 0xed, 0xd3, 0xbb, 0xcd, 0xe0, 0xbf, 0x7b, 0x92, 0xa2, + 0x7f, 0xfa, 0x76, 0x49, 0x69, 0x88, 0x98, 0x1d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_169_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x04, 0x4a, 0xc5, 0x5a, 0x91, 0x3a, 0x8c, 0x7f, 0x7e, + 0xd7, 0xfc, 0x56, 0x79, 0xf5, 0x2f, 0x47, 0xcb, 0xb9, 0x73, 0x03, 0x25, + 0xbe, 0x21, 0xb7, 0x99, 0x37, 0x79, 0xd1, 0x87 +}; +/* QIUTx = 0000009794861017b3debeff302e425327fe269d78753b73bc1bfb3a77f716dc */ +/* QIUTy = 00000002581a49c1269f5ec868dc6d7f5c2d8e749632d47ab6d9e68dbad985f0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_169_out[] = { +/* ZIUT */ + 0x01, 0xe4, 0xb7, 0xe8, 0x9f, 0xb1, 0xb5, 0x11, 0x79, 0xb8, 0x79, 0x2f, + 0x5c, 0xd5, 0x81, 0xc3, 0x91, 0x7e, 0x11, 0x24, 0x6d, 0x38, 0x46, 0xf6, + 0x34, 0x4e, 0xe8, 0x2e, 0xed, 0x66 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_170_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x68, 0xd9, 0xe5, 0x5e, 0x7a, 0x10, 0x5b, 0x7b, 0xb4, + 0x4b, 0x21, 0xd6, 0x69, 0xbb, 0x0e, 0xf6, 0x57, 0xa9, 0x14, 0x37, 0xad, + 0x84, 0xbf, 0x6d, 0x58, 0x53, 0x27, 0x0c, 0x98 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_170_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x14, 0x3c, 0x8b, 0xed, 0xb5, 0x4d, 0xb0, 0x7d, 0xf8, + 0xf6, 0x70, 0x83, 0xc5, 0x9a, 0x0a, 0xa7, 0xcd, 0x8a, 0x0e, 0xfa, 0x42, + 0xf4, 0x2f, 0xd6, 0x2e, 0x44, 0x2e, 0x0b, 0x62 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_170_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x2b, 0xc1, 0x36, 0x77, 0x85, 0x31, 0x08, 0x9d, 0xa5, + 0xc2, 0xfa, 0xb3, 0xca, 0xee, 0xc2, 0x56, 0xc5, 0x4b, 0x0b, 0x35, 0xfc, + 0x2c, 0x65, 0xf7, 0xb8, 0xee, 0x61, 0x61, 0xc3 +}; +/* QIUTx = 000001fb258a31d166bef9cd664cd7b66cd8c186e7025c77f0bae731587e9ef6 */ +/* QIUTy = 00000060dfd4e475e92805d1935d0382dc1767067915cc00ed3b24f65382d21a */ +static const uint8_t nist_kas_ecc_cdh_testvector_170_out[] = { +/* ZIUT */ + 0x01, 0x45, 0x71, 0x0c, 0x3a, 0xb0, 0x78, 0x0e, 0xc2, 0x33, 0x42, 0x4d, + 0x4e, 0x28, 0xb3, 0x8d, 0x29, 0xf8, 0x86, 0x96, 0x5b, 0xbc, 0xac, 0x49, + 0xfa, 0x30, 0x0e, 0x1e, 0xd8, 0x86 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_171_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x99, 0xeb, 0x91, 0xcd, 0xa9, 0x86, 0x20, 0x10, 0x3c, + 0x32, 0x05, 0xd6, 0x48, 0x9e, 0x68, 0xad, 0x7e, 0x57, 0xd0, 0xa5, 0x1d, + 0xc5, 0x02, 0xd6, 0xe3, 0x05, 0x88, 0xf4, 0x18 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_171_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x3f, 0xbf, 0x82, 0x99, 0x29, 0xed, 0xd2, 0x8e, 0x90, + 0x6f, 0x58, 0xf8, 0x7a, 0xbe, 0xd6, 0xd6, 0xd1, 0x77, 0xf4, 0x36, 0xf0, + 0xdd, 0x94, 0x0d, 0xda, 0x25, 0xea, 0xf1, 0x88 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_171_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x0d, 0x56, 0x59, 0x54, 0x71, 0x43, 0x5d, 0x95, 0xfe, + 0xc3, 0x7d, 0xf6, 0x22, 0xf1, 0x8e, 0xe7, 0xda, 0xbb, 0x24, 0x37, 0x9c, + 0x82, 0xbb, 0xf7, 0x14, 0xc5, 0xab, 0xc5, 0xe3 +}; +/* QIUTx = 000001a52940a452aaf420b37b5f32c2c337306894a882feea7addadc01927ee */ +/* QIUTy = 000000771b9f62a2a6fa892503225275490388b8bfc2df77df3e806bedba7d88 */ +static const uint8_t nist_kas_ecc_cdh_testvector_171_out[] = { +/* ZIUT */ + 0x00, 0x69, 0x41, 0xa2, 0xa5, 0x31, 0x08, 0x35, 0x63, 0xdd, 0x88, 0x6b, + 0x06, 0xc0, 0x86, 0x07, 0x70, 0xa4, 0x72, 0x4b, 0xb0, 0x4a, 0x4e, 0xbb, + 0x2a, 0xfb, 0x1b, 0xa2, 0x63, 0x6b +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_172_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xdc, 0xca, 0xa2, 0x2b, 0x43, 0x39, 0x1d, 0xc0, 0x52, + 0x59, 0x7a, 0xe3, 0xbd, 0x07, 0xc6, 0xe5, 0xf0, 0x21, 0xf3, 0x9e, 0x98, + 0x77, 0x56, 0xf6, 0x54, 0x81, 0x71, 0xee, 0x94 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_172_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x28, 0xef, 0xd4, 0x9a, 0xf3, 0xa6, 0xb3, 0x2d, 0xc1, + 0x67, 0x97, 0xa9, 0x78, 0xf0, 0xad, 0x4a, 0xb0, 0xdb, 0x66, 0xab, 0xab, + 0xd6, 0xad, 0x56, 0x72, 0xf4, 0xf8, 0x12, 0xc9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_172_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x19, 0xc8, 0xab, 0x2b, 0x32, 0xf2, 0xee, 0x93, 0xbf, + 0x2f, 0xf6, 0xbc, 0x44, 0x37, 0x8b, 0x60, 0x87, 0x2b, 0xda, 0xeb, 0x6b, + 0xa5, 0x6b, 0x51, 0x4c, 0x8f, 0x38, 0x8b, 0xa7 +}; +/* QIUTx = 00000083530fa3df315a8740ac52f4d394b80c4a5f210baba0b6dc2205e12493 */ +/* QIUTy = 00000037b9d02ed43e9d41d0dbb8403b9021b4d2c1bd360ee53c31c27b492005 */ +static const uint8_t nist_kas_ecc_cdh_testvector_172_out[] = { +/* ZIUT */ + 0x00, 0x1d, 0x75, 0x4e, 0xe5, 0x35, 0x1d, 0x45, 0x82, 0x97, 0x47, 0x34, + 0x07, 0x2a, 0xba, 0xc2, 0x33, 0x76, 0xe2, 0x43, 0x48, 0x37, 0x09, 0x34, + 0xe7, 0xb8, 0x64, 0xdb, 0x0f, 0x52 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_173_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x70, 0x91, 0x7b, 0x33, 0xb3, 0x7b, 0x8e, 0xaf, 0xf2, + 0x46, 0x1e, 0x5f, 0x9e, 0xb8, 0xf0, 0x79, 0x7b, 0x13, 0xaa, 0xbd, 0x91, + 0x5a, 0x60, 0x70, 0x6c, 0xd4, 0xf3, 0x2c, 0xb6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_173_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x76, 0x51, 0xe0, 0x74, 0x2c, 0x0d, 0x83, 0xd4, 0xb6, + 0x85, 0x52, 0xe9, 0xb7, 0xab, 0xec, 0x36, 0x44, 0xba, 0x97, 0x55, 0xcf, + 0xfe, 0x6d, 0x4e, 0x56, 0x94, 0x3a, 0x6b, 0x9b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_173_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x50, 0x31, 0x60, 0x10, 0x4d, 0x88, 0xa0, 0xc0, 0xf6, + 0x39, 0x56, 0xe7, 0xc3, 0xbb, 0xa7, 0x02, 0x96, 0x3f, 0x9f, 0x1b, 0x53, + 0xfc, 0x11, 0x9a, 0x59, 0x2e, 0xee, 0xa4, 0xf5 +}; +/* QIUTx = 000001463c78e498abf34033ec3e1d973dc12509e2d234fb91403715e42f61f7 */ +/* QIUTy = 000000ade7abb98a0308886696353aad33c05bab5cf3c0d4e969cbf4c4ceec93 */ +static const uint8_t nist_kas_ecc_cdh_testvector_173_out[] = { +/* ZIUT */ + 0x01, 0x13, 0x46, 0xb8, 0x37, 0x91, 0xe4, 0xbe, 0xa7, 0xf6, 0xba, 0x6b, + 0x12, 0x65, 0xe5, 0x05, 0x08, 0x95, 0xd8, 0x40, 0x27, 0xc1, 0x06, 0xf7, + 0x73, 0x53, 0x41, 0x8f, 0x75, 0xd7 +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_174_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xd8, 0xed, 0x31, 0x83, 0x82, 0xb8, 0x5c, 0x25, 0x25, + 0xa0, 0x2c, 0x22, 0xc6, 0x7f, 0x5b, 0xf3, 0x66, 0x33, 0x5d, 0x94, 0x76, + 0x7e, 0xb5, 0xcb, 0x45, 0x73, 0x96, 0x64, 0xc5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_174_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x7d, 0x8f, 0xde, 0x7b, 0xbc, 0x56, 0x8f, 0xdc, 0x80, + 0x2a, 0x3e, 0x34, 0x55, 0xf3, 0xcf, 0x35, 0x60, 0x2d, 0xf7, 0x06, 0x84, + 0xc8, 0xac, 0xdd, 0xa1, 0x65, 0xa0, 0x26, 0x56 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_174_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x45, 0x47, 0xea, 0xf9, 0xbe, 0x1c, 0xe5, 0xaf, 0x13, + 0x86, 0xe3, 0x11, 0x04, 0x6e, 0xc8, 0x32, 0x60, 0xb8, 0x4a, 0x2c, 0xa9, + 0x10, 0x55, 0xf6, 0x06, 0x68, 0xb9, 0x46, 0xe0 +}; +/* QIUTx = 000001504938c167680afb8b6d5858cfaa191c40196fc4e500c662c5346ecc90 */ +/* QIUTy = 00000137d1ba942228dae68c450b1a033a2c810a995971f01c24089e4a6fdcc5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_174_out[] = { +/* ZIUT */ + 0x00, 0xb4, 0x93, 0x8e, 0xd1, 0xed, 0x01, 0x2a, 0x9a, 0x53, 0x89, 0x2e, + 0xd9, 0x94, 0x93, 0x97, 0xcd, 0xc4, 0xe4, 0xa6, 0x12, 0xd5, 0x4d, 0xcf, + 0x80, 0xcd, 0xb0, 0x39, 0xf4, 0x7b +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_175_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x7f, 0x87, 0xf1, 0x3f, 0x6d, 0xfe, 0xe6, 0x08, 0x1b, + 0xb5, 0xcc, 0xa5, 0x32, 0xfe, 0x26, 0x8c, 0x27, 0x1d, 0x27, 0x56, 0xb3, + 0x1b, 0xdf, 0x64, 0x32, 0x97, 0xcf, 0x69, 0x5b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_175_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xf3, 0xa7, 0x46, 0x95, 0x5e, 0x12, 0xdd, 0x0b, 0x71, + 0x91, 0x9e, 0xdb, 0xf2, 0x3b, 0x23, 0x22, 0xca, 0xb3, 0x28, 0xdd, 0x09, + 0xbd, 0xf8, 0x7b, 0xca, 0xfd, 0xcd, 0x28, 0x84 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_175_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x42, 0xfb, 0xe5, 0x54, 0x86, 0x2f, 0x35, 0x95, 0x18, + 0x4a, 0x45, 0x51, 0x0c, 0xa5, 0x3d, 0xf9, 0x7c, 0x45, 0x17, 0x55, 0x84, + 0xb5, 0xd2, 0xde, 0x04, 0x27, 0x23, 0x35, 0x8e +}; +/* QIUTx = 00000131b8d61b9cfb0536c588214e45888ebe48391eeecb4d7fb5be8eff4acf */ +/* QIUTy = 00000165da49557a0aa9d45dd378d5f899272cc697682276ae91d2c0b675c469 */ +static const uint8_t nist_kas_ecc_cdh_testvector_175_out[] = { +/* ZIUT */ + 0x01, 0xb3, 0xd2, 0x57, 0x8b, 0xde, 0x30, 0x66, 0xa2, 0x53, 0xdb, 0x53, + 0x22, 0xc8, 0x5c, 0xf9, 0x48, 0x7c, 0xe7, 0x7b, 0x67, 0xec, 0xe9, 0x55, + 0xe2, 0x81, 0xb0, 0xd7, 0xd0, 0xe7 +}; +/* [K-283] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_176_public_x[] = { +/* QCAVSx */ + 0x03, 0xf0, 0x75, 0xc2, 0x4c, 0x35, 0xa9, 0xdc, 0x99, 0x52, 0xbe, 0x6f, + 0xd3, 0x2b, 0x76, 0x1d, 0xce, 0x63, 0xf4, 0x72, 0x0a, 0x22, 0x40, 0x8e, + 0x3a, 0x14, 0xbb, 0xd0, 0x97, 0xe0, 0x12, 0xb5, 0x69, 0x4c, 0x22, 0xa0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_176_public_y[] = { +/* QCAVSy */ + 0x06, 0x75, 0x82, 0x5b, 0x40, 0x20, 0x2e, 0x95, 0xbe, 0x7d, 0xab, 0x5a, + 0x82, 0x61, 0x47, 0xe0, 0x4b, 0x8c, 0x51, 0xa0, 0x9b, 0x00, 0x34, 0x57, + 0x7c, 0x1f, 0x31, 0xf8, 0xc1, 0x6a, 0x70, 0xc8, 0xe1, 0xc8, 0x5b, 0x89 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_176_private[] = { +/* dIUT */ + 0x01, 0x5f, 0xde, 0x49, 0xb8, 0x02, 0x54, 0x2a, 0x52, 0xc7, 0x0b, 0x23, + 0xa0, 0xb1, 0x78, 0x4e, 0x5f, 0x87, 0x80, 0xb5, 0x68, 0x53, 0xf9, 0xa5, + 0xf8, 0xc3, 0xa5, 0x26, 0x6e, 0x87, 0x27, 0xdc, 0xe9, 0x7d, 0x4a, 0x17 +}; +/* QIUTx = 0611edc045dbe43ecc4ef6b324cd51f70fe3d7ddf877ec68b798909c3c4561756aa30e5f */ +/* QIUTy = 00833b25511704af09b62d9f7cbac59814e75bbb9c735f55538491dbfa60c1e0115efe42 */ +static const uint8_t nist_kas_ecc_cdh_testvector_176_out[] = { +/* ZIUT */ + 0x07, 0x45, 0x55, 0x28, 0x17, 0xb5, 0xd7, 0x29, 0x31, 0x0b, 0x7d, 0xbe, + 0xba, 0xe6, 0x87, 0x64, 0x87, 0x14, 0xa9, 0xae, 0x69, 0x5d, 0xad, 0x20, + 0xca, 0x1a, 0xb6, 0x11, 0x1c, 0x3d, 0x05, 0x46, 0x70, 0xf2, 0x11, 0x32 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_177_public_x[] = { +/* QCAVSx */ + 0x07, 0x99, 0xb4, 0x30, 0xe9, 0x23, 0x20, 0xff, 0xea, 0xbf, 0x2d, 0x6c, + 0xc8, 0x73, 0x99, 0xe3, 0x0c, 0x0a, 0xa8, 0x44, 0x20, 0xff, 0x8e, 0xba, + 0x23, 0x09, 0xb9, 0x94, 0x87, 0xb7, 0x42, 0xd7, 0x22, 0xe8, 0xb7, 0xa5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_177_public_y[] = { +/* QCAVSy */ + 0x02, 0x17, 0x36, 0x28, 0x01, 0xfd, 0x6d, 0x2d, 0x28, 0x6e, 0x5c, 0xdf, + 0x37, 0x5c, 0xd0, 0xae, 0x56, 0x9b, 0x70, 0x00, 0x05, 0x31, 0x2e, 0x37, + 0xe8, 0xe3, 0x5b, 0x15, 0x92, 0xef, 0xb9, 0xb5, 0xea, 0xf4, 0x7b, 0x3a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_177_private[] = { +/* dIUT */ + 0x01, 0x3b, 0x91, 0x1f, 0x62, 0xf3, 0xaa, 0x88, 0x43, 0x54, 0x63, 0x45, + 0x47, 0xee, 0x62, 0x28, 0x07, 0xd5, 0xd1, 0x06, 0x02, 0x03, 0x30, 0xae, + 0x2b, 0x97, 0x98, 0xc0, 0xc4, 0xcd, 0x0e, 0xad, 0xb1, 0x0b, 0xa9, 0x48 +}; +/* QIUTx = 078d2ecd4d902332b6b3c7bd4ba7d200fc34c45eda30998b6025ed47b1f4f8e68f328624 */ +/* QIUTy = 04d5e53647dddf2fccc8816dac8bc70c29807622cc95539a72aa3a9b230ca1d25ee7b516 */ +static const uint8_t nist_kas_ecc_cdh_testvector_177_out[] = { +/* ZIUT */ + 0x02, 0xeb, 0x0c, 0x1c, 0xeb, 0x61, 0x79, 0x23, 0x2e, 0x91, 0xcf, 0xf9, + 0x1f, 0xc8, 0xa3, 0x05, 0x53, 0xc6, 0xed, 0x7e, 0x0a, 0x71, 0xde, 0xb1, + 0xbd, 0xa0, 0xa1, 0x07, 0x35, 0xa8, 0x45, 0x93, 0xdd, 0x90, 0x36, 0x36 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_178_public_x[] = { +/* QCAVSx */ + 0x00, 0xce, 0x47, 0xa7, 0x43, 0xd4, 0x8b, 0x86, 0xfe, 0xfd, 0x6b, 0x5c, + 0x02, 0xf2, 0xa9, 0x7b, 0x27, 0x62, 0xa2, 0xfe, 0x57, 0xe0, 0xbd, 0xf8, + 0x5c, 0x1d, 0x6a, 0x29, 0xde, 0x88, 0x62, 0xc4, 0xc9, 0x9e, 0xd5, 0x3a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_178_public_y[] = { +/* QCAVSy */ + 0x03, 0x22, 0xe5, 0x96, 0x06, 0x9f, 0x91, 0x65, 0x68, 0xca, 0x24, 0x8c, + 0xed, 0x57, 0xef, 0xe9, 0x05, 0x34, 0xaf, 0x4a, 0x9f, 0x90, 0xa4, 0xf4, + 0x0f, 0x79, 0x7e, 0x45, 0x29, 0x67, 0x03, 0x17, 0x26, 0xbf, 0x41, 0xd7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_178_private[] = { +/* dIUT */ + 0x01, 0x77, 0x63, 0x2b, 0x69, 0xe7, 0xed, 0xda, 0x3c, 0xf0, 0x07, 0x30, + 0x75, 0x04, 0x34, 0x3c, 0xc2, 0x16, 0x23, 0x26, 0xf6, 0x20, 0x17, 0xcb, + 0xdd, 0xf3, 0x60, 0xa8, 0x76, 0xdc, 0x93, 0xb8, 0x1f, 0x04, 0xc5, 0x8e +}; +/* QIUTx = 03815ab6480e4ad24a6628275ef2ee0ce7d58699239dbce23338842bc58c42cca94d2412 */ +/* QIUTy = 02de833cc664cac90d30fbeac603efbbce9276d4f16ab1c46e7e11c81a9aa9e25c82969a */ +static const uint8_t nist_kas_ecc_cdh_testvector_178_out[] = { +/* ZIUT */ + 0x04, 0xa9, 0xdd, 0x2c, 0xf5, 0x07, 0x68, 0x14, 0xe5, 0x32, 0x9c, 0x51, + 0x8c, 0x4f, 0x27, 0xb4, 0x29, 0xdb, 0xe0, 0x1d, 0x46, 0x68, 0x2d, 0x47, + 0x6e, 0x7e, 0x78, 0x88, 0x0d, 0xe3, 0x68, 0xb0, 0x64, 0x23, 0x6b, 0xa9 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_179_public_x[] = { +/* QCAVSx */ + 0x07, 0x28, 0x97, 0x58, 0x39, 0xb4, 0x2c, 0x62, 0x03, 0x6a, 0x7a, 0xff, + 0xfa, 0xdd, 0xef, 0xc3, 0x02, 0x4b, 0x72, 0x58, 0x40, 0x7b, 0xed, 0x56, + 0x5c, 0xae, 0xa9, 0x39, 0xbe, 0x33, 0xd1, 0x6a, 0xc9, 0x44, 0x45, 0xc7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_179_public_y[] = { +/* QCAVSy */ + 0x07, 0x71, 0x26, 0x30, 0x79, 0x0b, 0x05, 0xae, 0x04, 0xd8, 0xd7, 0xd9, + 0xf2, 0x36, 0x5d, 0xae, 0x9a, 0xd2, 0x4c, 0x4c, 0x61, 0xb3, 0xeb, 0x20, + 0xc0, 0xa7, 0x98, 0x7e, 0x6a, 0x4c, 0x4b, 0x0f, 0x59, 0x8c, 0x37, 0x1f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_179_private[] = { +/* dIUT */ + 0x00, 0x3b, 0xfe, 0x9a, 0x1c, 0x98, 0x53, 0x86, 0xe5, 0xba, 0x2b, 0x31, + 0x55, 0x3a, 0x55, 0x15, 0x1e, 0x78, 0xdd, 0xc3, 0x8f, 0x07, 0x43, 0x2b, + 0x5c, 0x42, 0xa1, 0xcd, 0x2d, 0xa2, 0x78, 0xfd, 0x0b, 0x68, 0xe0, 0x47 +}; +/* QIUTx = 01d9c3337da95ec6e5a4bff1cc92783989b66c9230107870d4a578699338e38eb2d92eff */ +/* QIUTy = 00cdaad7d0eb0f445aa763a5dfb8f38f55355777ce24f753b5ad3d3cbab125f491698d56 */ +static const uint8_t nist_kas_ecc_cdh_testvector_179_out[] = { +/* ZIUT */ + 0x04, 0x4e, 0x2c, 0xd2, 0xbc, 0x16, 0x4d, 0x21, 0xcf, 0x4b, 0x98, 0x33, + 0xc0, 0xaa, 0x62, 0xed, 0x05, 0x92, 0x82, 0xe6, 0x2b, 0x82, 0xf4, 0x50, + 0x0a, 0xeb, 0x42, 0x2d, 0x17, 0xe1, 0xf6, 0xe7, 0xe8, 0xbb, 0xd5, 0x00 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_180_public_x[] = { +/* QCAVSx */ + 0x05, 0x56, 0x72, 0xd7, 0x39, 0x98, 0x45, 0x10, 0x89, 0xe2, 0xb7, 0xc7, + 0x10, 0x4b, 0x42, 0x24, 0x7d, 0xdd, 0xd1, 0x32, 0xd4, 0x0a, 0xd0, 0x87, + 0xb5, 0x88, 0xd6, 0xa3, 0x85, 0xda, 0x64, 0xf5, 0xa2, 0xf4, 0x68, 0x38 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_180_public_y[] = { +/* QCAVSy */ + 0x02, 0xb4, 0xcb, 0x15, 0x81, 0xf9, 0xe2, 0xb3, 0x78, 0xeb, 0x7a, 0x4f, + 0x64, 0xf5, 0xa7, 0xd4, 0x32, 0x0b, 0x2c, 0xa3, 0xd3, 0x47, 0x47, 0x26, + 0xf6, 0x70, 0xc3, 0x88, 0x3b, 0xb8, 0xda, 0x47, 0xf3, 0xd7, 0x45, 0xbe +}; +static const uint8_t nist_kas_ecc_cdh_testvector_180_private[] = { +/* dIUT */ + 0x00, 0xd9, 0x5a, 0xf5, 0x2a, 0x70, 0x8e, 0x69, 0x2d, 0x02, 0x67, 0x7b, + 0x21, 0x03, 0x2f, 0x7a, 0xea, 0xd6, 0x00, 0x3f, 0x12, 0x4e, 0x72, 0x01, + 0x3f, 0x37, 0xc0, 0x6e, 0x0b, 0xbc, 0x20, 0xe3, 0x53, 0x2b, 0x3c, 0xea +}; +/* QIUTx = 06e487f91e73bdd344fb8bc8f4c1f476e727fb2671e9d6c8fbd775f1aaa24caf2e9a36f5 */ +/* QIUTy = 0663e1cff8099757bb9ff1b87890283aa49cff0f7b12fe184ed2a428375d2796cd81de91 */ +static const uint8_t nist_kas_ecc_cdh_testvector_180_out[] = { +/* ZIUT */ + 0x04, 0xd4, 0xf0, 0x4d, 0x2f, 0xcf, 0x1b, 0xcd, 0x81, 0x50, 0xea, 0xde, + 0xd9, 0x0e, 0x46, 0x7d, 0x3d, 0x38, 0xf7, 0x53, 0xb6, 0xfb, 0x54, 0xee, + 0xd8, 0xf9, 0xd2, 0x9c, 0xd3, 0xdc, 0xc7, 0xbe, 0x2c, 0x83, 0xde, 0x11 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_181_public_x[] = { +/* QCAVSx */ + 0x02, 0xcc, 0x28, 0xa4, 0xcb, 0x76, 0xd1, 0x47, 0xd9, 0x8d, 0xfa, 0x67, + 0x7d, 0xca, 0x14, 0xe1, 0x77, 0x13, 0x47, 0xb9, 0x68, 0x1c, 0x65, 0xcd, + 0xb5, 0x40, 0xf2, 0x2c, 0x90, 0x76, 0x13, 0xfd, 0xcc, 0xb0, 0xc8, 0xda +}; +static const uint8_t nist_kas_ecc_cdh_testvector_181_public_y[] = { +/* QCAVSy */ + 0x07, 0xd4, 0x06, 0x5f, 0x99, 0x0c, 0x8f, 0xc3, 0x7d, 0x10, 0x0e, 0xce, + 0x38, 0xfb, 0xf5, 0x74, 0xce, 0x44, 0x4d, 0xc3, 0x73, 0x55, 0xe0, 0x70, + 0x2b, 0x80, 0xd1, 0xeb, 0x1b, 0xdd, 0x67, 0x09, 0x97, 0xe8, 0xf2, 0x71 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_181_private[] = { +/* dIUT */ + 0x00, 0xc7, 0x33, 0xd9, 0x09, 0x40, 0x32, 0xcc, 0x7a, 0xed, 0x6c, 0x54, + 0xa8, 0xce, 0xd7, 0x53, 0xea, 0xf2, 0xa4, 0x88, 0x82, 0x28, 0x5a, 0x3b, + 0x4c, 0x7e, 0x60, 0x21, 0xf2, 0x6b, 0xec, 0xe0, 0x72, 0x28, 0x40, 0xad +}; +/* QIUTx = 026896b039d7068d98a326710ebb7a978bd47661154645ae30cd83d60535067e05151ccb */ +/* QIUTy = 00d83a263bdbd8c8abf0310bfbfc83917a86b0d8c4be0b155ab7b9e2c705605628bbcdd9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_181_out[] = { +/* ZIUT */ + 0x01, 0xc3, 0x43, 0x54, 0x05, 0x41, 0x60, 0x4f, 0x68, 0xdd, 0xbd, 0x63, + 0xc4, 0x83, 0x76, 0x0d, 0x82, 0x4d, 0xed, 0x5c, 0x18, 0xbe, 0x7e, 0x56, + 0xe6, 0xd3, 0x6a, 0x9a, 0xc6, 0xd2, 0x57, 0x72, 0xaf, 0xb0, 0xa9, 0x0a +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_182_public_x[] = { +/* QCAVSx */ + 0x06, 0x38, 0x80, 0xeb, 0x53, 0x8c, 0x72, 0x75, 0xec, 0xba, 0x4d, 0xb5, + 0x3d, 0x9b, 0x68, 0xc2, 0x87, 0xfb, 0x37, 0x78, 0xbe, 0xf5, 0x14, 0x97, + 0x4d, 0x1e, 0x7e, 0x31, 0xa9, 0xae, 0x36, 0x5a, 0x21, 0x81, 0x41, 0x5f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_182_public_y[] = { +/* QCAVSy */ + 0x04, 0xaf, 0x9f, 0x2c, 0xf9, 0x25, 0x42, 0xe1, 0xff, 0x8f, 0xf2, 0x8f, + 0x8e, 0x7c, 0x8e, 0x80, 0x95, 0x84, 0xe2, 0x43, 0xa4, 0x90, 0x29, 0x49, + 0xa7, 0x65, 0xa2, 0x84, 0x98, 0x6c, 0x75, 0x0b, 0x1b, 0x06, 0xc8, 0x9a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_182_private[] = { +/* dIUT */ + 0x00, 0xdb, 0x39, 0xd7, 0x53, 0x60, 0x72, 0xdc, 0x34, 0x48, 0xcd, 0x7d, + 0x21, 0x60, 0xe5, 0x0c, 0x81, 0x1f, 0x64, 0x83, 0x58, 0xeb, 0x0d, 0xb1, + 0xd5, 0x42, 0x8e, 0x81, 0xaa, 0x7a, 0x68, 0x6b, 0x78, 0x65, 0xad, 0xfd +}; +/* QIUTx = 03a721906ad13dc15c311fd4e552f3bc87b7d92ceeedbb0c316a952785ba4689fc0ba270 */ +/* QIUTy = 029514f3873bbc3b9e217061f7a6261fdc6268685f9656f1d5eea472cc2db5a8c162e6e9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_182_out[] = { +/* ZIUT */ + 0x05, 0xe3, 0x80, 0x79, 0x81, 0x54, 0x77, 0xb8, 0xa7, 0x90, 0x96, 0xce, + 0x33, 0x9c, 0x4a, 0x25, 0x5f, 0x8b, 0x21, 0x3b, 0xe7, 0x47, 0x15, 0xea, + 0x61, 0xef, 0x7d, 0xd0, 0xc0, 0xb5, 0xf1, 0x61, 0xd9, 0xde, 0x75, 0x21 +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_183_public_x[] = { +/* QCAVSx */ + 0x05, 0xbf, 0xd2, 0x89, 0x5a, 0x2e, 0x66, 0x36, 0x6d, 0xb7, 0xa8, 0x37, + 0x88, 0xc7, 0x2b, 0xce, 0x48, 0xf7, 0x9b, 0x5c, 0x95, 0x24, 0xa0, 0x8a, + 0xe2, 0x73, 0xc7, 0x8c, 0xeb, 0x39, 0xae, 0x97, 0x55, 0x9d, 0x5a, 0xc3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_183_public_y[] = { +/* QCAVSy */ + 0x04, 0xa2, 0xb0, 0xa5, 0x5f, 0x80, 0x15, 0x5a, 0x1a, 0x33, 0x0f, 0xde, + 0x6c, 0xb6, 0xd9, 0x7e, 0xdd, 0xb0, 0xa9, 0xdc, 0xb6, 0x6c, 0x49, 0xb3, + 0x92, 0x90, 0x4a, 0xbe, 0x8b, 0x38, 0x1f, 0x91, 0x09, 0x0d, 0xbb, 0x21 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_183_private[] = { +/* dIUT */ + 0x00, 0x66, 0x49, 0xbf, 0xd6, 0x41, 0xda, 0xbf, 0x1b, 0x9d, 0x49, 0x9d, + 0x4f, 0xb0, 0x4b, 0xeb, 0x09, 0x94, 0x75, 0xd0, 0xaa, 0x15, 0xd5, 0xef, + 0x68, 0x48, 0xb7, 0x34, 0xd2, 0xd4, 0x13, 0x00, 0x8b, 0x60, 0x43, 0x08 +}; +/* QIUTx = 008f6576d62affc71836d19adbbc3d504210f12efb61c42057824515290c502f2e09b6d8 */ +/* QIUTy = 0021643be87ae6e549b0d5fbb558c1303d14b1ccd77703ec74f9602f35ca8d7a5139bce7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_183_out[] = { +/* ZIUT */ + 0x05, 0x31, 0xcc, 0xf5, 0x1d, 0x10, 0x96, 0x98, 0x2f, 0x7c, 0x2e, 0xc5, + 0x13, 0xa9, 0x2b, 0xf5, 0x1c, 0x7a, 0xc5, 0x06, 0x9c, 0xb1, 0x5c, 0x5e, + 0x2a, 0x05, 0x3c, 0xea, 0xe7, 0xe5, 0x55, 0x09, 0x08, 0xa1, 0x91, 0x01 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_184_public_x[] = { +/* QCAVSx */ + 0x06, 0x35, 0x47, 0xf7, 0x57, 0x0b, 0xd6, 0x95, 0x97, 0x33, 0xc0, 0x3d, + 0x2e, 0x6c, 0x4c, 0x88, 0x97, 0x1f, 0x31, 0x4a, 0xdc, 0xf2, 0x8b, 0xc8, + 0x51, 0xdc, 0x52, 0xed, 0x4e, 0x8c, 0x1a, 0x4e, 0xa0, 0x6f, 0x87, 0x02 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_184_public_y[] = { +/* QCAVSy */ + 0x01, 0x22, 0xd3, 0x77, 0x3b, 0x09, 0x34, 0xe9, 0x00, 0xfb, 0xa7, 0xeb, + 0xfe, 0x1a, 0xd5, 0xed, 0x5b, 0xec, 0x0f, 0xb1, 0xa9, 0xdd, 0xcf, 0x4e, + 0xeb, 0x61, 0xcb, 0xed, 0x04, 0x00, 0x74, 0x31, 0x3c, 0x0b, 0x31, 0x70 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_184_private[] = { +/* dIUT */ + 0x00, 0x81, 0x86, 0x0a, 0x65, 0x3d, 0x6d, 0x94, 0x44, 0x6d, 0x77, 0x66, + 0x16, 0x4f, 0xf9, 0x2c, 0x6c, 0x5c, 0x15, 0x45, 0xc7, 0x35, 0x30, 0x4b, + 0x3a, 0xd4, 0xd5, 0x17, 0x8c, 0x8b, 0x14, 0xd0, 0x18, 0x1e, 0x94, 0x71 +}; +/* QIUTx = 06b68815bb83691d16749c4be16125e2a6d6dae94252739ba7bf0db0d50198ea2fe43ddf */ +/* QIUTy = 039e0d93018a46125620f6ffaca5a0668343c57025a60c31a9d6e51191cab338993b46b5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_184_out[] = { +/* ZIUT */ + 0x06, 0xff, 0xe7, 0x9d, 0x2b, 0x76, 0x64, 0xee, 0x2d, 0x83, 0x03, 0xff, + 0xe0, 0xce, 0xca, 0x8c, 0x49, 0xa5, 0x81, 0xfc, 0xdb, 0x49, 0xc4, 0xaf, + 0x6a, 0x06, 0x0f, 0xf2, 0x04, 0xee, 0xa7, 0x4f, 0x4c, 0xf3, 0x9c, 0xef +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_185_public_x[] = { +/* QCAVSx */ + 0x00, 0x90, 0x47, 0xf7, 0xd7, 0x73, 0x97, 0xdb, 0x70, 0xe3, 0x9f, 0xe9, + 0xe4, 0xba, 0x9d, 0x97, 0xa9, 0x95, 0xa7, 0xee, 0x06, 0x6e, 0xcf, 0x53, + 0x81, 0x79, 0xe9, 0x37, 0xac, 0x86, 0xca, 0xcd, 0xac, 0x51, 0x09, 0x50 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_185_public_y[] = { +/* QCAVSy */ + 0x00, 0x7c, 0xd8, 0x75, 0x16, 0x7f, 0x06, 0xa2, 0xfb, 0x9a, 0x81, 0x9e, + 0x2c, 0xbd, 0xac, 0xef, 0xc1, 0x6c, 0xae, 0x0e, 0xef, 0x2c, 0xbb, 0x0b, + 0x2d, 0x49, 0xbe, 0xae, 0x10, 0x9d, 0xb7, 0x53, 0xc9, 0x50, 0x61, 0x70 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_185_private[] = { +/* dIUT */ + 0x00, 0x22, 0x43, 0xe8, 0x91, 0x9b, 0xd7, 0xa9, 0x7c, 0xef, 0x0e, 0x9c, + 0xde, 0x63, 0xc7, 0x6d, 0x4e, 0x10, 0x71, 0x50, 0x29, 0x4f, 0xcf, 0x8d, + 0xd7, 0x67, 0x64, 0x51, 0xca, 0x3b, 0xfa, 0x5c, 0x5e, 0xdb, 0x96, 0x4c +}; +/* QIUTx = 03e439e3ebdfa7a23a9deb09de141905c653c4f202edf2cf5f09faef88ba3113701e49f0 */ +/* QIUTy = 071d071b86ed0f468fc6019de23fe4ba2cb3b50032be35e92d2e5af40de706ab524e82ab */ +static const uint8_t nist_kas_ecc_cdh_testvector_185_out[] = { +/* ZIUT */ + 0x03, 0x11, 0xc4, 0x30, 0xdb, 0x78, 0xb6, 0x20, 0x3e, 0x27, 0xb5, 0x29, + 0x88, 0xe1, 0xe9, 0xda, 0xe8, 0x90, 0xc6, 0x55, 0xda, 0xc4, 0xac, 0xef, + 0xa7, 0xee, 0x96, 0x12, 0xbe, 0xc3, 0x2e, 0x3e, 0x5f, 0x52, 0xbe, 0x55 +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_186_public_x[] = { +/* QCAVSx */ + 0x04, 0xbd, 0xec, 0x19, 0x30, 0x0c, 0x8a, 0xfd, 0xee, 0xd8, 0x64, 0x99, + 0xd2, 0x70, 0x39, 0x22, 0xdf, 0x57, 0xb2, 0xff, 0xec, 0x37, 0xe4, 0x5c, + 0x03, 0xa5, 0xe2, 0x90, 0x9d, 0xe3, 0xc3, 0x33, 0xbd, 0x06, 0xa5, 0xe1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_186_public_y[] = { +/* QCAVSy */ + 0x01, 0xaa, 0x4f, 0x40, 0x84, 0x4f, 0x24, 0x13, 0xf1, 0xfc, 0xbd, 0xed, + 0x00, 0x3b, 0x1d, 0x15, 0xc9, 0xf1, 0xdf, 0x75, 0x48, 0xde, 0x2a, 0x2b, + 0xbf, 0x71, 0xb5, 0x16, 0x65, 0x7a, 0xd8, 0xd8, 0xc7, 0x7c, 0xf7, 0x2d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_186_private[] = { +/* dIUT */ + 0x00, 0x51, 0x2a, 0x42, 0x84, 0x1e, 0x12, 0x27, 0xfc, 0x9f, 0xed, 0x51, + 0xc2, 0x26, 0x87, 0x31, 0x68, 0x41, 0x36, 0xf2, 0x25, 0xcf, 0xbf, 0x45, + 0x64, 0x89, 0x87, 0xe2, 0x45, 0x3a, 0x71, 0x86, 0xf6, 0xa7, 0xed, 0xef +}; +/* QIUTx = 022f76e5ab714fdf78571e84c2b6ea3a17f12999be483bc67e1b843d209bdfec0347a43e */ +/* QIUTy = 02eec1fc0e85f330c53dad7bff4862d8afff8aa14f94756e95b8f01fd7eeb8fc54527787 */ +static const uint8_t nist_kas_ecc_cdh_testvector_186_out[] = { +/* ZIUT */ + 0x07, 0x01, 0xd9, 0x2e, 0xd8, 0x68, 0x71, 0x38, 0x01, 0x4b, 0x43, 0x79, + 0xf1, 0xc3, 0x46, 0x77, 0xe1, 0x74, 0x4f, 0x6a, 0xe8, 0xc8, 0x99, 0x58, + 0xa5, 0x96, 0x2f, 0x14, 0x40, 0x8d, 0x58, 0x7b, 0x95, 0x47, 0x2d, 0xb3 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_187_public_x[] = { +/* QCAVSx */ + 0x06, 0x11, 0xf5, 0x3a, 0xf4, 0xb4, 0x88, 0x99, 0x0e, 0x7a, 0x52, 0xe5, + 0xc7, 0x38, 0x56, 0xa1, 0xe7, 0x42, 0x79, 0xbb, 0x0f, 0x36, 0xd3, 0xab, + 0x19, 0x89, 0xb2, 0xcc, 0xd9, 0x93, 0x91, 0xb6, 0xc6, 0xb3, 0xa1, 0x3d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_187_public_y[] = { +/* QCAVSy */ + 0x05, 0x4e, 0xa9, 0x5a, 0x23, 0x4f, 0x65, 0x89, 0x71, 0x95, 0xbc, 0x97, + 0xb0, 0x3f, 0xa6, 0xd2, 0x46, 0xea, 0x5a, 0xb5, 0xf4, 0x1d, 0xa2, 0x2c, + 0x08, 0xed, 0x81, 0x7a, 0xa7, 0xc0, 0x4a, 0xdf, 0x37, 0x29, 0x82, 0xb3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_187_private[] = { +/* dIUT */ + 0x00, 0x2a, 0x8a, 0xf4, 0x97, 0xd1, 0xa3, 0xda, 0xc0, 0x73, 0x2a, 0x39, + 0x3d, 0xed, 0xf7, 0x53, 0x94, 0xa3, 0xf5, 0x19, 0xce, 0x07, 0xfa, 0xed, + 0x3f, 0x77, 0xdc, 0x0e, 0x66, 0x9f, 0x3a, 0x1b, 0x1c, 0x6d, 0xda, 0xdb +}; +/* QIUTx = 0571f0c87f88888ec0738961834021765cc4f5c8db2b1f9ea9b8fe9847f8964349fdc44f */ +/* QIUTy = 04ef7c8044a609694746ccaafe87fc7f9f1a78d00f8354f5da7ee2f5da7235ac1ad4b57c */ +static const uint8_t nist_kas_ecc_cdh_testvector_187_out[] = { +/* ZIUT */ + 0x04, 0xf2, 0x30, 0x1e, 0xd8, 0x5a, 0x5c, 0x91, 0xc3, 0x1a, 0x7f, 0xd1, + 0x25, 0x85, 0x49, 0x04, 0x34, 0x0a, 0x55, 0xe3, 0x49, 0x76, 0xa2, 0x07, + 0x43, 0xbd, 0x33, 0xd9, 0x5e, 0x47, 0x64, 0x50, 0xf3, 0x01, 0xee, 0x62 +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_188_public_x[] = { +/* QCAVSx */ + 0x01, 0x27, 0x06, 0xec, 0x0a, 0x0e, 0x76, 0x42, 0x5d, 0x8a, 0xb4, 0xe0, + 0xd5, 0x59, 0x30, 0xa4, 0x41, 0x6e, 0x4d, 0xd0, 0xa1, 0xaf, 0x6d, 0x97, + 0x98, 0x72, 0x52, 0x98, 0x8d, 0xa0, 0xac, 0x96, 0x27, 0x57, 0x7c, 0xbe +}; +static const uint8_t nist_kas_ecc_cdh_testvector_188_public_y[] = { +/* QCAVSy */ + 0x04, 0x21, 0x5e, 0x87, 0x15, 0x12, 0x9c, 0xc7, 0x63, 0x01, 0x79, 0x17, + 0x01, 0xdc, 0x5f, 0xe1, 0xab, 0xcd, 0x67, 0x2b, 0x6a, 0xa1, 0x9b, 0xa4, + 0xc7, 0xe5, 0x32, 0xee, 0x7a, 0x91, 0x3e, 0xea, 0x60, 0xdb, 0xc9, 0xd0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_188_private[] = { +/* dIUT */ + 0x01, 0xde, 0x9f, 0xba, 0x4a, 0xb2, 0x4d, 0x06, 0xe7, 0x4a, 0xe5, 0xad, + 0x36, 0xae, 0x19, 0x5c, 0x23, 0x60, 0xc7, 0x28, 0xeb, 0x38, 0xc5, 0x0e, + 0xf5, 0x33, 0x32, 0x9e, 0x70, 0xc5, 0xae, 0x19, 0xf4, 0x89, 0xb6, 0xd5 +}; +/* QIUTx = 048d61e0b9b8064bcca8ce40d4f9e68b23684137726a44ea75c8f2f8850f0333fbe985e6 */ +/* QIUTy = 05fcaba38d51e2112b6b9f34e6779c10c0c559c3ecd156022966cf92a8c7f65020a79ebd */ +static const uint8_t nist_kas_ecc_cdh_testvector_188_out[] = { +/* ZIUT */ + 0x06, 0x43, 0x90, 0x0f, 0x33, 0x7e, 0xd3, 0x62, 0x81, 0x5f, 0x18, 0x1e, + 0x06, 0x28, 0xed, 0x51, 0x84, 0xda, 0xd3, 0xe6, 0x6a, 0x1f, 0x03, 0x0e, + 0x94, 0x7f, 0x11, 0x66, 0x96, 0x31, 0x2d, 0x83, 0x5f, 0x7f, 0x6e, 0x7b +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_189_public_x[] = { +/* QCAVSx */ + 0x05, 0xbb, 0x20, 0xbe, 0xa4, 0xfd, 0x85, 0xd0, 0x16, 0x26, 0x89, 0xc5, + 0x50, 0x05, 0x40, 0x01, 0x40, 0x9b, 0x6c, 0x71, 0x2d, 0x35, 0x6a, 0x52, + 0xf7, 0x93, 0xd7, 0x8a, 0xa2, 0xd8, 0x26, 0x1a, 0x43, 0xc5, 0xb6, 0xde +}; +static const uint8_t nist_kas_ecc_cdh_testvector_189_public_y[] = { +/* QCAVSy */ + 0x03, 0x1b, 0xe5, 0xca, 0xfc, 0x8a, 0xae, 0xf1, 0x9b, 0x86, 0x15, 0x03, + 0x41, 0x3a, 0x7b, 0x73, 0xb6, 0x0b, 0x37, 0xb0, 0x18, 0x04, 0x93, 0xd8, + 0x2e, 0x94, 0x26, 0xf4, 0x7b, 0x65, 0x87, 0x39, 0x3d, 0x08, 0xde, 0x08 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_189_private[] = { +/* dIUT */ + 0x01, 0x5d, 0x3a, 0x22, 0x2d, 0x57, 0x09, 0xcb, 0x33, 0x9d, 0x93, 0xcd, + 0x29, 0x65, 0x06, 0x64, 0xf3, 0x9b, 0xf3, 0x20, 0x1c, 0x5d, 0x1e, 0x86, + 0xd3, 0xae, 0xf8, 0xf7, 0x95, 0xb9, 0xfd, 0xdf, 0x47, 0xd8, 0xc4, 0xa8 +}; +/* QIUTx = 01e2b88de3772b09c63d036e0dbba435246987497b6283dab8ccf1002486de0730277b43 */ +/* QIUTy = 03ce182b7f0cea21a06a1d4de8722cbfc59b9d9d79bc760b9d17d85671561aeaadd54941 */ +static const uint8_t nist_kas_ecc_cdh_testvector_189_out[] = { +/* ZIUT */ + 0x06, 0x3b, 0x1a, 0x3d, 0xb3, 0x31, 0xf9, 0x1a, 0xbd, 0x0a, 0xf8, 0x37, + 0xdb, 0x9d, 0x5f, 0x04, 0x06, 0x20, 0xd1, 0xdd, 0xd7, 0xfc, 0xcf, 0x8b, + 0x58, 0xe0, 0xdf, 0x43, 0x69, 0x83, 0x51, 0xea, 0x19, 0x42, 0x54, 0x8e +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_190_public_x[] = { +/* QCAVSx */ + 0x01, 0x0a, 0x3c, 0xa2, 0x43, 0x5b, 0x13, 0x5f, 0xfe, 0xa0, 0x87, 0x92, + 0xb7, 0xf1, 0x9b, 0x4e, 0xe1, 0x81, 0x20, 0x7c, 0x29, 0xbe, 0x1c, 0xe1, + 0xfd, 0xea, 0xcd, 0xb6, 0x9a, 0x66, 0x9f, 0x9c, 0xdd, 0xe9, 0x18, 0x1a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_190_public_y[] = { +/* QCAVSy */ + 0x02, 0x49, 0x08, 0x27, 0x4b, 0x1e, 0x98, 0xc6, 0xd1, 0x97, 0xed, 0x27, + 0x83, 0xc3, 0xc9, 0x53, 0xc1, 0xb3, 0xb3, 0x4f, 0xa4, 0x3a, 0x8b, 0x2f, + 0x57, 0x42, 0x58, 0x4e, 0x37, 0xfe, 0xa4, 0x07, 0x26, 0x9b, 0x43, 0xbf +}; +static const uint8_t nist_kas_ecc_cdh_testvector_190_private[] = { +/* dIUT */ + 0x00, 0x98, 0xc5, 0x70, 0x66, 0x67, 0x92, 0xef, 0xda, 0x65, 0xfc, 0x9e, + 0x79, 0x09, 0x93, 0x11, 0x58, 0xdf, 0xd4, 0x47, 0x7b, 0xe9, 0x33, 0x32, + 0xe4, 0x93, 0xd6, 0x98, 0x66, 0xb6, 0x60, 0x2c, 0x49, 0x51, 0xde, 0x6f +}; +/* QIUTx = 04dc6774fe46ab0ed2768d379e7564a37c6bb1dd1bfc555727ad94c20f4732cabf2a2c82 */ +/* QIUTy = 06c6cf0f421f91fca22b4871216a9f1fe3878f07914e96ae94ac770b6762f9dce08ffa2d */ +static const uint8_t nist_kas_ecc_cdh_testvector_190_out[] = { +/* ZIUT */ + 0x05, 0x16, 0xda, 0x1d, 0x64, 0xbc, 0x4b, 0x25, 0xce, 0x47, 0x63, 0xe6, + 0x43, 0x82, 0x57, 0xd6, 0x2f, 0xb1, 0xff, 0xde, 0xae, 0x16, 0xd6, 0x87, + 0x01, 0xd6, 0x3b, 0x60, 0x3a, 0xd5, 0x3e, 0x85, 0x87, 0x92, 0x76, 0x69 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_191_public_x[] = { +/* QCAVSx */ + 0x05, 0x3a, 0x0d, 0xd6, 0x13, 0x5e, 0x43, 0xa1, 0x14, 0xe5, 0x00, 0x0a, + 0xec, 0x40, 0xba, 0x27, 0x09, 0xb3, 0xa6, 0x13, 0x73, 0x0f, 0x1c, 0xc2, + 0x00, 0x6b, 0x44, 0x69, 0x35, 0xe2, 0x37, 0xbf, 0xcc, 0xc3, 0x94, 0xd8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_191_public_y[] = { +/* QCAVSy */ + 0x03, 0xb6, 0x6c, 0xe6, 0xcf, 0x01, 0x50, 0x7d, 0x46, 0x2e, 0xee, 0xff, + 0xf6, 0x21, 0x1b, 0xd4, 0xc5, 0x60, 0x70, 0x11, 0x6c, 0x69, 0x07, 0x46, + 0x8f, 0x7c, 0x76, 0xfe, 0x01, 0x14, 0x0b, 0xf0, 0xd5, 0xfb, 0x7b, 0x79 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_191_private[] = { +/* dIUT */ + 0x00, 0xf4, 0xb6, 0xdb, 0x4a, 0x87, 0xcd, 0xd3, 0x00, 0x29, 0xcc, 0x3b, + 0xe8, 0x9e, 0x40, 0xb9, 0xbc, 0xb0, 0x14, 0xd0, 0x10, 0xa9, 0x1a, 0x25, + 0x2c, 0x56, 0xcb, 0x28, 0x67, 0x1f, 0x35, 0x4a, 0x80, 0x4c, 0xb4, 0xd8 +}; +/* QIUTx = 066ddf04831fd1c72bc48b709061c1aeaaad19c9da3d8c1506fa775d4f5a5412eee0286d */ +/* QIUTy = 03aa1d13146ff192792b74a5c64ad3150fae344fa830e0f44733d867f4e0ae053526c62b */ +static const uint8_t nist_kas_ecc_cdh_testvector_191_out[] = { +/* ZIUT */ + 0x04, 0x9c, 0x68, 0xc3, 0x33, 0xb9, 0x67, 0x05, 0xee, 0xe4, 0xa3, 0xde, + 0xf0, 0xd5, 0x68, 0xb0, 0xd4, 0xfa, 0xf2, 0x4d, 0xf2, 0xfc, 0x2f, 0x1b, + 0xf4, 0x0d, 0xa0, 0xaf, 0x09, 0x46, 0x24, 0x0c, 0x38, 0xe9, 0x7f, 0x74 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_192_public_x[] = { +/* QCAVSx */ + 0x06, 0xd4, 0xa6, 0xf3, 0xe8, 0x7b, 0x6d, 0x8c, 0x49, 0xcb, 0xe5, 0x17, + 0xa9, 0x75, 0xd2, 0xab, 0x8c, 0x63, 0x39, 0x13, 0x55, 0x96, 0xd6, 0xb3, + 0x0c, 0xc6, 0x5c, 0xc8, 0x0c, 0x12, 0x84, 0x50, 0x8f, 0x49, 0x78, 0x9b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_192_public_y[] = { +/* QCAVSy */ + 0x02, 0x96, 0x3b, 0x35, 0x6f, 0x24, 0x34, 0xec, 0x24, 0x9b, 0xcb, 0x65, + 0x89, 0xed, 0xe4, 0xde, 0x36, 0xce, 0xcd, 0x34, 0x50, 0xe6, 0xf5, 0xe4, + 0x77, 0xbf, 0xcd, 0xc2, 0x9a, 0xda, 0x4a, 0xef, 0x0f, 0x45, 0xac, 0x53 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_192_private[] = { +/* dIUT */ + 0x01, 0xab, 0x82, 0xc5, 0xa6, 0x2a, 0xe4, 0x7e, 0xcb, 0xcc, 0xf6, 0x66, + 0xcc, 0x33, 0x23, 0xb3, 0x51, 0x28, 0xc5, 0x2d, 0x17, 0xbe, 0x11, 0xba, + 0xf3, 0xbd, 0xb5, 0x60, 0x06, 0xe5, 0xd5, 0x68, 0xba, 0xad, 0x8b, 0xbc +}; +/* QIUTx = 00a04ad7a583666a40437f968b02cac7946745b4ca949021c5443deb70183f88e1778fe0 */ +/* QIUTy = 02bb591c32f0db3430342f0e37c45449c293c54f6b7df6f797c0992c2829858b680f2bdc */ +static const uint8_t nist_kas_ecc_cdh_testvector_192_out[] = { +/* ZIUT */ + 0x04, 0xdd, 0x44, 0xc1, 0xa3, 0x0e, 0xda, 0xc2, 0xe3, 0x9a, 0x5b, 0xc9, + 0x90, 0x26, 0x25, 0x88, 0x0a, 0x18, 0x51, 0x63, 0x85, 0xc9, 0x0a, 0x9c, + 0xc6, 0xb9, 0x4c, 0x4f, 0x11, 0x1e, 0x02, 0x60, 0x86, 0x3c, 0xca, 0xb2 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_193_public_x[] = { +/* QCAVSx */ + 0x07, 0x64, 0x52, 0xe1, 0x9d, 0x7a, 0x10, 0xb8, 0x85, 0x12, 0x3d, 0x50, + 0x3f, 0x5d, 0x04, 0x33, 0xe1, 0x63, 0xdf, 0x13, 0x4f, 0xff, 0xb8, 0x55, + 0x8f, 0x8a, 0xc2, 0x6c, 0xfb, 0x30, 0x62, 0x9f, 0x8c, 0xfb, 0x09, 0x3e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_193_public_y[] = { +/* QCAVSy */ + 0x06, 0xb3, 0xa2, 0x4b, 0x2a, 0x4b, 0x07, 0x77, 0x70, 0xd3, 0x96, 0xbb, + 0xf1, 0x54, 0xaf, 0x41, 0xee, 0xe3, 0x50, 0x35, 0x73, 0xa6, 0xde, 0x9a, + 0xfe, 0x0f, 0x6d, 0x18, 0xb0, 0x2f, 0xc9, 0x76, 0x1c, 0xa1, 0x64, 0x3d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_193_private[] = { +/* dIUT */ + 0x00, 0x12, 0x54, 0xaf, 0x17, 0x91, 0xcc, 0x75, 0x69, 0x4c, 0xe5, 0x90, + 0xbb, 0x51, 0x8a, 0x77, 0x0a, 0x75, 0x04, 0x46, 0x17, 0x1a, 0x30, 0xed, + 0xd6, 0xc0, 0x38, 0x2a, 0x17, 0xe6, 0x88, 0x0a, 0x1a, 0xea, 0x5b, 0x81 +}; +/* QIUTx = 02b766c993b398d2426a7a0a49e9d001079d0fc32197181c56eac1805e4f87c9df055dea */ +/* QIUTy = 036e7bbd3be9139d4d43a8655ef7d51a062d9947d1a48010ef1ea10eedeb27f0d1ffe765 */ +static const uint8_t nist_kas_ecc_cdh_testvector_193_out[] = { +/* ZIUT */ + 0x00, 0x49, 0xc1, 0x65, 0x33, 0x9e, 0x9a, 0xeb, 0x2b, 0x51, 0x66, 0x84, + 0xb4, 0x42, 0x92, 0x1f, 0x1f, 0xef, 0x30, 0x91, 0xcf, 0x78, 0x1e, 0x03, + 0xfb, 0x3f, 0x56, 0xe9, 0x3a, 0xf1, 0xf3, 0xd6, 0xe5, 0x00, 0xc8, 0x1f +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_194_public_x[] = { +/* QCAVSx */ + 0x01, 0x8e, 0x0b, 0xb7, 0x51, 0x6d, 0x2c, 0x42, 0xe9, 0xdd, 0x96, 0xca, + 0xaf, 0xf5, 0xf2, 0x0b, 0xfd, 0xdf, 0x3e, 0x86, 0x23, 0xfc, 0x94, 0x7d, + 0x4d, 0x70, 0x49, 0x15, 0x36, 0x79, 0x0b, 0x87, 0x41, 0xcd, 0xd3, 0x72 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_194_public_y[] = { +/* QCAVSy */ + 0x03, 0x2c, 0x0f, 0xff, 0xbd, 0xa2, 0xfa, 0x86, 0x3c, 0xb9, 0xd1, 0x5c, + 0x36, 0x54, 0x50, 0x20, 0xd5, 0xbb, 0x24, 0xd9, 0x30, 0xda, 0xf2, 0xfe, + 0xa4, 0x55, 0x5f, 0x7c, 0x24, 0xd6, 0xae, 0xfb, 0xb2, 0xc0, 0x1d, 0x92 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_194_private[] = { +/* dIUT */ + 0x01, 0x20, 0x17, 0xb9, 0xa0, 0x59, 0x9f, 0xbf, 0x13, 0xce, 0xe1, 0x08, + 0x50, 0xa8, 0xf8, 0xbd, 0x06, 0xcc, 0xc0, 0x0b, 0xd2, 0x9a, 0xc6, 0x77, + 0x9f, 0x1b, 0xd9, 0x33, 0x46, 0xb2, 0x2c, 0x98, 0x32, 0x7e, 0x0f, 0xa7 +}; +/* QIUTx = 0421c62dcab54ba800eafac232fc730ce70f6d5cc53ff53d371269cf046daeaf451b33e7 */ +/* QIUTy = 03d635f55233da3c490a959c6e63a94fcdbe471fbfca19d2c5a3fd12b04db380c3c895cc */ +static const uint8_t nist_kas_ecc_cdh_testvector_194_out[] = { +/* ZIUT */ + 0x06, 0x45, 0xd7, 0xf4, 0xc5, 0x47, 0x9b, 0xaf, 0xf5, 0xbc, 0x0c, 0xba, + 0x65, 0x4a, 0x3d, 0xcf, 0xda, 0x56, 0xc0, 0xe9, 0xd1, 0x9f, 0x50, 0xf9, + 0xd8, 0xd8, 0xc6, 0x35, 0x7c, 0x09, 0xa1, 0x40, 0xef, 0xfb, 0xf2, 0x23 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_195_public_x[] = { +/* QCAVSx */ + 0x02, 0x4a, 0xbb, 0x15, 0x5e, 0x49, 0x12, 0x42, 0x82, 0xea, 0x32, 0xe5, + 0xb5, 0x44, 0x62, 0x1a, 0xe9, 0xb5, 0x13, 0xaa, 0x04, 0x76, 0xda, 0x3b, + 0xdd, 0xb7, 0x52, 0x60, 0xd5, 0xf5, 0xfa, 0x2e, 0x7b, 0x89, 0x89, 0x87 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_195_public_y[] = { +/* QCAVSy */ + 0x01, 0xbd, 0xfb, 0x0a, 0x07, 0x9a, 0x55, 0xbc, 0xfc, 0xe1, 0xca, 0x8b, + 0xce, 0x30, 0x19, 0xcb, 0xca, 0xe6, 0x16, 0x40, 0x03, 0x38, 0x41, 0x66, + 0xeb, 0xbb, 0x0b, 0xb7, 0x33, 0x53, 0x95, 0x65, 0xad, 0xc4, 0x46, 0xf3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_195_private[] = { +/* dIUT */ + 0x00, 0x4f, 0x19, 0x7c, 0x85, 0x43, 0x2c, 0xb4, 0x2a, 0x17, 0x77, 0x24, + 0x9a, 0xe4, 0x11, 0xef, 0x4b, 0xb2, 0x65, 0x7b, 0xa4, 0xba, 0xd3, 0x5a, + 0xe5, 0x38, 0x63, 0x5a, 0x15, 0x1c, 0x8d, 0x6a, 0x56, 0x4f, 0x9c, 0xca +}; +/* QIUTx = 040c88924d5a24a853fae408aea5b3bc827d7315fbb58e6ea1f6a65677dd4c4d304bd75f */ +/* QIUTy = 054b82869ada4433f7208f8570f24f06cb64046e8ac086ac57d3707fc882c6352733dff6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_195_out[] = { +/* ZIUT */ + 0x02, 0x80, 0x17, 0xc2, 0xa0, 0x24, 0x0f, 0xd7, 0x46, 0xee, 0x72, 0xa0, + 0xbc, 0xae, 0x1e, 0x53, 0xe0, 0x5b, 0x7a, 0xf2, 0x54, 0x29, 0x80, 0x94, + 0xc3, 0x81, 0xe7, 0x35, 0x52, 0x38, 0x54, 0xea, 0x5f, 0xdd, 0x4f, 0x5c +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_196_public_x[] = { +/* QCAVSx */ + 0x07, 0x52, 0x75, 0x12, 0xbc, 0x93, 0x49, 0x38, 0xcc, 0x52, 0x40, 0xce, + 0x70, 0xef, 0x65, 0x22, 0x2d, 0xb8, 0x5c, 0x13, 0xc9, 0x61, 0xc1, 0xf3, + 0x1f, 0x91, 0x42, 0x05, 0x06, 0x7d, 0x64, 0xb1, 0xa4, 0xc8, 0x53, 0x14 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_196_public_y[] = { +/* QCAVSy */ + 0x02, 0xaa, 0xbd, 0xb8, 0x1f, 0xfe, 0xd2, 0xc0, 0x01, 0xac, 0xbb, 0x4d, + 0x0b, 0x7b, 0xe5, 0x39, 0x30, 0x4e, 0x32, 0xe4, 0x31, 0xe0, 0x2d, 0xf8, + 0xb1, 0x92, 0xad, 0x74, 0xed, 0x1b, 0x4b, 0x06, 0x06, 0xbf, 0xc9, 0x0b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_196_private[] = { +/* dIUT */ + 0x01, 0x4e, 0x89, 0x34, 0x83, 0xd1, 0xd8, 0xb7, 0x62, 0x1c, 0xf4, 0x8b, + 0xd2, 0x4b, 0xc8, 0xa1, 0xb9, 0x5b, 0xb4, 0x0a, 0x08, 0xc1, 0x6c, 0x32, + 0x87, 0x4a, 0x65, 0x2b, 0x59, 0xa2, 0x25, 0x21, 0x39, 0x42, 0x8d, 0xac +}; +/* QIUTx = 01574e17ce26311c40abf3243f4889a2eae74a8341aa7838551056f4395b8f02bdc327be */ +/* QIUTy = 0086e59f985348f3f8d7953800b1d75e141521249c43fe0616913db5d1d4bd5400abce55 */ +static const uint8_t nist_kas_ecc_cdh_testvector_196_out[] = { +/* ZIUT */ + 0x02, 0x60, 0x3c, 0x00, 0x99, 0x8d, 0xeb, 0xa5, 0x2d, 0xb1, 0x28, 0x14, + 0xb1, 0xf7, 0x7b, 0x21, 0x20, 0xcb, 0xc1, 0xdc, 0xa5, 0x90, 0x09, 0xc0, + 0xd6, 0xea, 0x40, 0xdc, 0xbc, 0xab, 0xca, 0x32, 0xc5, 0x03, 0x80, 0xd8 +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_197_public_x[] = { +/* QCAVSx */ + 0x07, 0xec, 0x29, 0xda, 0x2f, 0x30, 0x4c, 0xeb, 0xa8, 0xd5, 0xe2, 0x49, + 0xeb, 0x60, 0x54, 0xa4, 0xe4, 0xf5, 0x95, 0x34, 0xee, 0x59, 0xd2, 0x5c, + 0x1d, 0xc0, 0xe1, 0x2c, 0xc3, 0x8f, 0x76, 0x8b, 0x83, 0xda, 0xff, 0xee +}; +static const uint8_t nist_kas_ecc_cdh_testvector_197_public_y[] = { +/* QCAVSy */ + 0x01, 0x12, 0xc7, 0xd4, 0xa3, 0x7f, 0xec, 0x84, 0x22, 0x71, 0xa0, 0xa8, + 0x22, 0xd3, 0x76, 0x37, 0xe6, 0xed, 0x55, 0x19, 0x07, 0x13, 0x00, 0x1a, + 0xef, 0xe1, 0x1b, 0x06, 0xf7, 0xe1, 0xd3, 0x4e, 0x00, 0xfc, 0xde, 0xcb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_197_private[] = { +/* dIUT */ + 0x01, 0xeb, 0x6f, 0x6c, 0x91, 0xa8, 0x80, 0xa5, 0x46, 0x21, 0x85, 0xc6, + 0xa7, 0x00, 0xe8, 0x63, 0x7b, 0x8f, 0x44, 0x7d, 0x09, 0xd1, 0xb2, 0x51, + 0x46, 0x0f, 0xe5, 0x7f, 0x1b, 0xf4, 0x62, 0xef, 0xdd, 0xdd, 0xae, 0xc0 +}; +/* QIUTx = 031b3026104388374cfb7c7b4ef64211a47e20b9561a3bbca53516040b7bda2837309454 */ +/* QIUTy = 024f8aeb23a35e1c22225967c7911868c84efdd873dbbccbc763ead67e72a2324aa4c6f2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_197_out[] = { +/* ZIUT */ + 0x02, 0x6a, 0x71, 0x9b, 0xff, 0x31, 0xda, 0x4b, 0x4e, 0xba, 0xed, 0x7b, + 0xd0, 0x43, 0x06, 0x4f, 0x9c, 0x39, 0x30, 0xb5, 0x77, 0x4c, 0x4a, 0x99, + 0x80, 0x93, 0x32, 0xc8, 0x08, 0xaa, 0xcb, 0xa4, 0xb9, 0xe3, 0x73, 0x3a +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_198_public_x[] = { +/* QCAVSx */ + 0x06, 0x1e, 0xf5, 0x93, 0x89, 0xed, 0xf8, 0xf8, 0x27, 0x3a, 0x66, 0x2a, + 0x41, 0x95, 0x41, 0x1e, 0x94, 0x48, 0xbb, 0x1b, 0x77, 0xfb, 0x08, 0x00, + 0xbe, 0x52, 0x5e, 0xb5, 0xa6, 0xa0, 0x3b, 0x19, 0x66, 0x57, 0x19, 0xa9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_198_public_y[] = { +/* QCAVSy */ + 0x02, 0x96, 0x86, 0xf8, 0x47, 0x7f, 0xb5, 0xc7, 0x69, 0xef, 0xb0, 0x82, + 0xcb, 0x3f, 0x1a, 0x0c, 0x79, 0xdb, 0x55, 0xcb, 0x26, 0x4e, 0x21, 0x12, + 0xc0, 0xe7, 0x79, 0xe7, 0xb5, 0x58, 0xf7, 0x00, 0x45, 0x81, 0x6a, 0x10 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_198_private[] = { +/* dIUT */ + 0x01, 0x47, 0xbe, 0x4e, 0x38, 0x66, 0x7e, 0x32, 0xa6, 0xa6, 0x1a, 0xb9, + 0x80, 0xce, 0xd9, 0x2e, 0x42, 0x69, 0x59, 0x25, 0xb1, 0x13, 0xc6, 0x94, + 0xa7, 0x96, 0x0a, 0xed, 0xea, 0x2e, 0x1d, 0x57, 0x1a, 0x42, 0xd3, 0xde +}; +/* QIUTx = 06f599f0c149457a32f1a2ffabd4dff916259382912b6402b50cdf5c235fdd1b790e5eaf */ +/* QIUTy = 04ccf1d8a4bfeb77ff3290e65ac601ee5b97fc1b1869a2eb9f0b76277e8066c086776c40 */ +static const uint8_t nist_kas_ecc_cdh_testvector_198_out[] = { +/* ZIUT */ + 0x04, 0x8c, 0x48, 0xc9, 0x93, 0x04, 0x06, 0x19, 0x53, 0x6f, 0x45, 0x48, + 0x2c, 0x49, 0x4a, 0x39, 0xb3, 0x2e, 0x75, 0xfe, 0x69, 0xe4, 0x78, 0xba, + 0x06, 0xe3, 0x76, 0x22, 0x8b, 0x79, 0xeb, 0x83, 0xd3, 0xff, 0x91, 0x68 +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_199_public_x[] = { +/* QCAVSx */ + 0x07, 0x9d, 0x57, 0x60, 0xee, 0x6e, 0xf9, 0x78, 0x51, 0x8b, 0xbc, 0xe5, + 0x36, 0xb0, 0x31, 0xc6, 0x55, 0xa8, 0xac, 0xf5, 0x60, 0x44, 0x97, 0xba, + 0x43, 0xde, 0x0b, 0xeb, 0x68, 0x77, 0xa5, 0x47, 0xc3, 0xed, 0xd4, 0x58 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_199_public_y[] = { +/* QCAVSy */ + 0x04, 0x21, 0xb3, 0x05, 0x1d, 0xd3, 0x63, 0x96, 0xd2, 0x0f, 0xfc, 0xd7, + 0xcf, 0x34, 0xfc, 0xa0, 0x22, 0x51, 0x6d, 0xd4, 0xbf, 0xfa, 0xc7, 0x3f, + 0xc9, 0x95, 0xae, 0x9e, 0xa8, 0x14, 0xce, 0x0e, 0x40, 0x27, 0xf7, 0xc6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_199_private[] = { +/* dIUT */ + 0x01, 0xe1, 0x90, 0x0b, 0xe6, 0x1a, 0xdb, 0x7e, 0x55, 0x55, 0x9d, 0x99, + 0xa0, 0xb7, 0xd9, 0x35, 0x44, 0x56, 0xf5, 0x15, 0x1e, 0x2f, 0xd7, 0xb8, + 0x3c, 0x00, 0x5b, 0x10, 0xb1, 0x60, 0x04, 0xeb, 0xe8, 0x76, 0xc0, 0x68 +}; +/* QIUTx = 042ecc99ff48b53f6619b484af8fa59b234a981c9c3e9107bbd1cdaacce81885d06e02a9 */ +/* QIUTy = 0183da0d7fee7f3e70e117f0e8a4a742cad10aefcdc4aab9bb31458237686afb4facf3a9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_199_out[] = { +/* ZIUT */ + 0x05, 0xd8, 0x5b, 0x16, 0xbb, 0x2a, 0x0d, 0x32, 0xc7, 0x3d, 0x14, 0x02, + 0x83, 0x8b, 0xdf, 0xa5, 0x12, 0xd7, 0x44, 0xfa, 0x88, 0xc7, 0x4d, 0x3d, + 0x90, 0xcf, 0x71, 0x4c, 0x24, 0x80, 0xe0, 0x33, 0x63, 0xd5, 0xc6, 0xec +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_200_public_x[] = { +/* QCAVSx */ + 0x02, 0x47, 0x84, 0xd3, 0xd3, 0xd5, 0xe8, 0x02, 0x1f, 0xfe, 0xd8, 0xa2, + 0x70, 0x9a, 0x9f, 0x54, 0xd5, 0x39, 0x5d, 0x98, 0xfa, 0x44, 0x2a, 0x65, + 0x5a, 0x05, 0xdd, 0x94, 0x26, 0x2b, 0x60, 0x35, 0x96, 0xf8, 0xbf, 0xf1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_200_public_y[] = { +/* QCAVSy */ + 0x03, 0xe8, 0xe3, 0x9e, 0x08, 0xcc, 0xe5, 0x5e, 0x1b, 0xed, 0x2d, 0xfe, + 0x0d, 0x2f, 0x8c, 0x14, 0x1b, 0x06, 0x40, 0x1d, 0xba, 0x03, 0x7e, 0xcb, + 0x38, 0x47, 0x44, 0x93, 0x0c, 0x81, 0x78, 0xd1, 0x46, 0x41, 0x63, 0x24 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_200_private[] = { +/* dIUT */ + 0x00, 0x77, 0xe4, 0x1a, 0xb2, 0xd0, 0x9c, 0x34, 0xc5, 0x88, 0xab, 0xc7, + 0x6d, 0x43, 0x12, 0x60, 0x2e, 0x71, 0xf6, 0x00, 0x19, 0x02, 0x7b, 0x98, + 0x6e, 0x0d, 0xed, 0x37, 0x25, 0x35, 0xc2, 0xb6, 0xa9, 0x33, 0xa5, 0x33 +}; +/* QIUTx = 02923323f170074222d3a6a287adafd3d1fe12715d57b91b1ff476a2b4fcc385de261ecc */ +/* QIUTy = 04cc498d67c6267cc7c4c2d40a56cdc2a6e715edd8b2a9614eeb33d0b6fd162cbb85a714 */ +static const uint8_t nist_kas_ecc_cdh_testvector_200_out[] = { +/* ZIUT */ + 0x06, 0x6a, 0xbb, 0x83, 0x8b, 0x5f, 0x12, 0xb6, 0xfc, 0x15, 0xce, 0xb7, + 0x45, 0x60, 0x06, 0x86, 0xbc, 0x2d, 0x57, 0x73, 0xe5, 0x34, 0x69, 0xc2, + 0xee, 0x92, 0x0c, 0xfb, 0xa5, 0x45, 0x9a, 0x1c, 0xab, 0x20, 0xd1, 0x53 +}; +/* [K-409] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_201_public_x[] = { +/* QCAVSx */ + 0x01, 0x77, 0xf7, 0x36, 0xf6, 0x11, 0x63, 0x20, 0xca, 0xfb, 0xb5, 0xb4, + 0xde, 0xc2, 0x02, 0xd4, 0x05, 0x08, 0x18, 0x2f, 0xe0, 0x11, 0x18, 0x9b, + 0x81, 0xe1, 0xf3, 0x99, 0x8f, 0x54, 0x08, 0x60, 0x7a, 0x46, 0xbb, 0x15, + 0x0a, 0xc4, 0x7b, 0xca, 0xaa, 0xfd, 0xe4, 0x7b, 0x8a, 0x7b, 0x72, 0xf4, + 0x78, 0xbc, 0x22, 0xd2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_201_public_y[] = { +/* QCAVSy */ + 0x01, 0xdf, 0x4e, 0xf4, 0xb3, 0x7e, 0x01, 0x24, 0xe5, 0x5b, 0x67, 0xf3, + 0x58, 0x6d, 0xe2, 0x4a, 0x88, 0xa6, 0xc5, 0xd9, 0x88, 0x54, 0x00, 0x7d, + 0x4b, 0x0c, 0x4b, 0x4c, 0xcd, 0x68, 0xd5, 0x1f, 0xaf, 0xa7, 0x63, 0x8b, + 0xbe, 0x55, 0x5d, 0x60, 0xb7, 0x4d, 0xef, 0x21, 0x7c, 0x6a, 0x63, 0xc5, + 0xb4, 0x06, 0x8f, 0xb7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_201_private[] = { +/* dIUT */ + 0x00, 0x08, 0x4b, 0x71, 0x1e, 0x3c, 0x60, 0x82, 0x2e, 0x70, 0xfa, 0x68, + 0x28, 0xb5, 0xab, 0xfb, 0x0e, 0x44, 0x88, 0x88, 0xb3, 0x5b, 0x0c, 0x8b, + 0xb0, 0x9f, 0x80, 0x66, 0x16, 0xdc, 0x1e, 0xcf, 0x22, 0xdd, 0x86, 0x23, + 0x7d, 0x93, 0x7c, 0x1b, 0xfd, 0xe6, 0x2b, 0x75, 0xae, 0x65, 0x59, 0x53, + 0xfc, 0x6b, 0x2f, 0x7e +}; +/* QIUTx = 0068a3f8b12e02d10e2f52095526bc4048b8f6ac3a84531772870789938f1aeff813e05e509ea9587d2b7e4aa14344bac3ec46f0 */ +/* QIUTy = 00d1ceb40c7d5f3297e2955f0f3eb1422b3e6bbbfbf7eb518b9c17ae8d40feb84aaf36f5e5bd96075b2b4dbe538ac011962ac705 */ +static const uint8_t nist_kas_ecc_cdh_testvector_201_out[] = { +/* ZIUT */ + 0x01, 0x76, 0xbc, 0x5c, 0x40, 0x36, 0xce, 0x51, 0x25, 0x49, 0x3a, 0x58, + 0xdd, 0x26, 0x5f, 0x04, 0xd1, 0x90, 0xf0, 0x28, 0x36, 0x6f, 0x77, 0x99, + 0xf7, 0x0a, 0xed, 0xf2, 0x9a, 0xc6, 0x7b, 0x5b, 0x37, 0xc3, 0x72, 0x38, + 0x59, 0x33, 0x77, 0xa4, 0x79, 0x44, 0xf5, 0xb6, 0x39, 0xf4, 0x38, 0x56, + 0xdb, 0xd5, 0x60, 0xec +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_202_public_x[] = { +/* QCAVSx */ + 0x01, 0x0c, 0x4c, 0x68, 0xa9, 0xf1, 0xa6, 0x2a, 0x32, 0x65, 0x56, 0xb6, + 0xd9, 0x77, 0xa7, 0x9c, 0xd9, 0xc4, 0x47, 0x6c, 0x05, 0xb1, 0xad, 0xd4, + 0xa2, 0xcf, 0xd3, 0x06, 0x82, 0x49, 0xa3, 0xc3, 0x92, 0x38, 0x22, 0x42, + 0x8d, 0x35, 0x2c, 0x5d, 0x74, 0xe5, 0xd6, 0x4a, 0xcc, 0xee, 0xdb, 0xda, + 0xa6, 0xef, 0xbe, 0x4c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_202_public_y[] = { +/* QCAVSy */ + 0x00, 0x86, 0x6a, 0xe9, 0x40, 0xdd, 0x31, 0xb5, 0xe6, 0xe3, 0xf2, 0x0b, + 0x3b, 0x4d, 0x87, 0xa6, 0xa0, 0x2c, 0x78, 0x17, 0x3c, 0x80, 0xaa, 0x51, + 0x0a, 0x6e, 0xdf, 0xf8, 0x52, 0xc6, 0x29, 0xe6, 0x06, 0x4d, 0xf5, 0xd7, + 0xc6, 0x00, 0xfd, 0x98, 0xe5, 0x8e, 0x8e, 0x8c, 0x66, 0x2b, 0xb4, 0xb9, + 0x6c, 0x8b, 0xa9, 0x05 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_202_private[] = { +/* dIUT */ + 0x00, 0x65, 0x18, 0x8b, 0xb7, 0x79, 0x6e, 0x45, 0x1f, 0x44, 0x72, 0x7a, + 0x1a, 0x06, 0x74, 0x44, 0x0d, 0xd3, 0x3d, 0x25, 0x8a, 0xd2, 0xfd, 0xc7, + 0xb9, 0x8f, 0xaf, 0x64, 0xb1, 0x1e, 0x7e, 0x8c, 0xe5, 0xe8, 0xc2, 0x1e, + 0x79, 0x9f, 0x1f, 0xf2, 0xfd, 0x29, 0xd4, 0xc9, 0x4a, 0xa1, 0x58, 0x96, + 0x20, 0x68, 0xa5, 0x9f +}; +/* QIUTx = 0032c5768452f3c1f3bc54879379ad420891267742b37fb096ee7b8c21ceed0041e9470cec3bedcb799e90bdbb31192083ff0344 */ +/* QIUTy = 00f9c6122927fb824246d1dc1ce0fde71a6849a82d41065da1d85256a9b1979bf7f286366fc8b324893ebe34e59c046007399414 */ +static const uint8_t nist_kas_ecc_cdh_testvector_202_out[] = { +/* ZIUT */ + 0x00, 0x57, 0x5d, 0x9e, 0x7f, 0x70, 0xa4, 0xa1, 0xc5, 0xc8, 0x07, 0xb6, + 0xb5, 0xd6, 0xb7, 0x33, 0x0b, 0xdd, 0x76, 0x4d, 0xb2, 0xaa, 0x60, 0xf3, + 0xbf, 0xe4, 0x97, 0xe6, 0xbf, 0xe9, 0x0f, 0x03, 0x8f, 0xb4, 0xf6, 0xac, + 0xf7, 0xac, 0x06, 0xef, 0xc3, 0xd1, 0x57, 0xc3, 0xdc, 0x90, 0x7b, 0x2a, + 0xe0, 0x93, 0xc6, 0xa2 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_203_public_x[] = { +/* QCAVSx */ + 0x01, 0xe4, 0xd5, 0x80, 0xd5, 0xe9, 0xad, 0x81, 0x67, 0x1c, 0x6c, 0xd6, + 0x62, 0xd5, 0x56, 0x9b, 0xaf, 0xe4, 0xd7, 0x5a, 0xa4, 0xf4, 0x49, 0xae, + 0xd5, 0x6b, 0xd8, 0x00, 0x61, 0x95, 0x20, 0xc9, 0xf3, 0x2c, 0x4e, 0x23, + 0x0c, 0x4d, 0x91, 0xb1, 0xc4, 0x11, 0xf9, 0x08, 0x6d, 0x52, 0x91, 0xba, + 0x13, 0x70, 0x14, 0xa2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_203_public_y[] = { +/* QCAVSy */ + 0x00, 0x0c, 0x8f, 0xfb, 0x42, 0x39, 0x2f, 0xf3, 0x97, 0xbb, 0xd4, 0x67, + 0x97, 0x2f, 0x3e, 0xd2, 0x51, 0xd5, 0xa0, 0x79, 0x96, 0x5d, 0xa0, 0xb1, + 0xd2, 0xa3, 0xcc, 0x16, 0xc3, 0x1d, 0x25, 0x5d, 0xce, 0x98, 0x86, 0x93, + 0x7b, 0x2d, 0xc9, 0x41, 0xea, 0xb0, 0xd8, 0xbe, 0x8b, 0xbc, 0xd1, 0x5a, + 0xa6, 0xed, 0x96, 0xd6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_203_private[] = { +/* dIUT */ + 0x00, 0x6c, 0xb1, 0x7c, 0x3f, 0xc2, 0x1a, 0xb4, 0x8e, 0x5c, 0x37, 0x17, + 0xc7, 0x91, 0x11, 0x8d, 0x47, 0x61, 0xe2, 0xc5, 0x19, 0x86, 0xbf, 0x14, + 0x79, 0x42, 0x55, 0x4d, 0xc5, 0xa1, 0x8b, 0xf9, 0xbb, 0x6c, 0x67, 0xbd, + 0xbb, 0xa9, 0x08, 0xa1, 0xe8, 0xba, 0x8e, 0x77, 0x90, 0xf5, 0x9a, 0x39, + 0x71, 0x34, 0xf6, 0x83 +}; +/* QIUTx = 002b890418afc5797c9746a44ca059367ae0663bcf058156860c613ee05e11da3f2f799c70a68fe72fd5dac2469daa18107029de */ +/* QIUTy = 01356904b197bf9e0657f4349d252bbb375c66206fc0d8312599bdbefee8608ec948dce486807baa535ed06adac9c797634711ab */ +static const uint8_t nist_kas_ecc_cdh_testvector_203_out[] = { +/* ZIUT */ + 0x00, 0xce, 0x87, 0xaa, 0x5e, 0x77, 0x00, 0x38, 0x4d, 0xf5, 0x9d, 0x3f, + 0x10, 0x75, 0xd2, 0x82, 0xc1, 0xaa, 0x51, 0x13, 0x91, 0xc4, 0x2e, 0xf6, + 0x09, 0xb8, 0xde, 0x12, 0x64, 0xec, 0xa8, 0xf7, 0x73, 0x7d, 0xf9, 0x15, + 0x65, 0xc7, 0x3e, 0xe8, 0x84, 0xea, 0x88, 0x2d, 0x47, 0xc5, 0x6d, 0x97, + 0x91, 0x41, 0xf0, 0xf2 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_204_public_x[] = { +/* QCAVSx */ + 0x00, 0xb7, 0xd1, 0x93, 0x54, 0xca, 0xdc, 0xc9, 0x47, 0x08, 0x26, 0x7a, + 0xed, 0x8b, 0x23, 0xe4, 0x84, 0xe3, 0x2a, 0x03, 0x81, 0x4b, 0x02, 0x6a, + 0x80, 0x0f, 0x5b, 0xa0, 0x1e, 0x92, 0x04, 0xc4, 0x30, 0x52, 0xe4, 0xd4, + 0x7c, 0x6f, 0xcd, 0x92, 0x32, 0x96, 0x54, 0xe0, 0xe9, 0x01, 0x5b, 0x01, + 0x2f, 0x79, 0x34, 0x4a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_204_public_y[] = { +/* QCAVSy */ + 0x01, 0x79, 0x95, 0xc1, 0x57, 0x96, 0xc5, 0xae, 0x93, 0xe0, 0xa2, 0x07, + 0xa2, 0x70, 0x70, 0x04, 0xfb, 0xb1, 0xa4, 0x9a, 0x0d, 0x47, 0xfd, 0x40, + 0x4f, 0x12, 0xd5, 0x78, 0x49, 0xd8, 0x39, 0x7c, 0xd4, 0xd2, 0xc6, 0xd2, + 0xb4, 0xb9, 0x0f, 0x86, 0x44, 0x03, 0xd4, 0xac, 0xd1, 0x6a, 0x32, 0xb7, + 0xff, 0x48, 0x77, 0xb4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_204_private[] = { +/* dIUT */ + 0x00, 0x11, 0xd4, 0x3b, 0xc0, 0x8d, 0xa9, 0xce, 0x5d, 0xef, 0xc9, 0x4b, + 0x4e, 0xf9, 0x0d, 0x93, 0x24, 0xde, 0x08, 0x03, 0x47, 0xff, 0x4d, 0xf8, + 0x66, 0x45, 0xd3, 0x25, 0x60, 0x3a, 0x2d, 0xff, 0xd2, 0x8e, 0xca, 0xf0, + 0x77, 0x5e, 0xc5, 0x3c, 0xaf, 0x5a, 0x55, 0x4e, 0xaf, 0x8b, 0x68, 0x48, + 0x7d, 0xf8, 0x86, 0x54 +}; +/* QIUTx = 01257b6abd470d294b59ddaedacd545dcf43808af890f576288803342fc61eb396f560af74342e10bb94d224c24d8e5900e5b972 */ +/* QIUTy = 01dccad97ecef4387a1cf512b16dd5bc7ab615fbc5087ac19d5fc2762f615b4904ea39343bbb185db64a19f7f70ecf0d557b15e8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_204_out[] = { +/* ZIUT */ + 0x00, 0x69, 0x1d, 0xd6, 0xb5, 0x17, 0x77, 0x02, 0xd6, 0xa0, 0xb1, 0xf8, + 0xb0, 0x7f, 0x3b, 0x01, 0x84, 0x78, 0x68, 0x0d, 0xe7, 0xee, 0x07, 0x92, + 0x72, 0xff, 0x75, 0x65, 0x93, 0x35, 0xc9, 0x6a, 0xfc, 0xea, 0x76, 0x50, + 0xca, 0xa0, 0x1f, 0x99, 0x6a, 0xa3, 0x79, 0x46, 0xb7, 0x8e, 0x14, 0xa8, + 0x3e, 0x57, 0x9f, 0xb4 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_205_public_x[] = { +/* QCAVSx */ + 0x00, 0xf2, 0xa1, 0x1c, 0xcd, 0x3a, 0x53, 0xc9, 0x5e, 0xa9, 0x8f, 0x31, + 0x44, 0xfb, 0x77, 0xd4, 0xa6, 0x84, 0xf9, 0xa1, 0xf4, 0x23, 0xeb, 0x81, + 0xe3, 0xa8, 0xbf, 0xbe, 0x22, 0xb6, 0x80, 0xf2, 0x18, 0x70, 0xf5, 0x8c, + 0xae, 0xb6, 0x94, 0x6c, 0x6b, 0x3b, 0x87, 0x36, 0x99, 0xcf, 0xfd, 0x31, + 0x40, 0x63, 0xf4, 0x08 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_205_public_y[] = { +/* QCAVSy */ + 0x00, 0xfd, 0xf2, 0x6e, 0xed, 0xe6, 0xcb, 0xa7, 0x24, 0x82, 0x40, 0x72, + 0x09, 0x06, 0xce, 0x07, 0x6c, 0xc4, 0x32, 0x2d, 0x18, 0xbc, 0x76, 0x83, + 0xd2, 0x24, 0x0b, 0xa6, 0x84, 0x76, 0xce, 0x79, 0x02, 0x27, 0x80, 0xb2, + 0xfa, 0x54, 0xe0, 0xf7, 0xc7, 0x65, 0x28, 0xb7, 0x7f, 0xa6, 0x31, 0xfe, + 0x5a, 0xbb, 0x5b, 0x95 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_205_private[] = { +/* dIUT */ + 0x00, 0x0d, 0x6b, 0x25, 0x96, 0x56, 0xd5, 0x26, 0x77, 0x7d, 0xed, 0xb5, + 0x24, 0x6a, 0x19, 0x2f, 0x0c, 0x05, 0xc7, 0x27, 0x0a, 0x3b, 0x4e, 0x64, + 0xa9, 0xd6, 0xc8, 0x77, 0xcd, 0x06, 0xd2, 0x96, 0x2a, 0x1a, 0xc8, 0x4e, + 0xc2, 0xd8, 0x97, 0x65, 0xf9, 0x67, 0xf6, 0x04, 0x4f, 0x2d, 0xfa, 0x56, + 0x90, 0x31, 0x07, 0xf3 +}; +/* QIUTx = 0193afa13bd1e081cee5df1286fe44a293b7d1b10c290a5f2ae7be2d02736009a26d83aaaa9017a8c8bf60efa15fcead07767d48 */ +/* QIUTy = 01d02fd66a7806c4c8445fa615254ff32bb9c1d85a3904f939c1061e250d3eb6413130a2a5570994795310e96dc3aff3b8218ad3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_205_out[] = { +/* ZIUT */ + 0x01, 0x36, 0xf5, 0xc0, 0x4c, 0xf9, 0xa5, 0x6d, 0xb2, 0x4a, 0xd9, 0x9b, + 0xd2, 0x86, 0xfe, 0xb8, 0x00, 0xae, 0xa3, 0x8d, 0x44, 0xf8, 0x19, 0xbe, + 0x1c, 0x2a, 0x9d, 0xba, 0x15, 0xc6, 0x35, 0xc4, 0xe1, 0x22, 0x89, 0x35, + 0x70, 0x23, 0x3a, 0x4c, 0x57, 0x54, 0xa4, 0x14, 0x99, 0xea, 0xfa, 0x39, + 0xa3, 0x5a, 0xa5, 0x7e +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_206_public_x[] = { +/* QCAVSx */ + 0x01, 0x17, 0x44, 0x9f, 0xbe, 0xa6, 0xb2, 0xd5, 0xf4, 0xe8, 0xe4, 0xd3, + 0x9a, 0x72, 0x28, 0x42, 0x4c, 0xf0, 0x6f, 0x45, 0x6b, 0xf3, 0xae, 0x39, + 0xbc, 0x1f, 0xb2, 0xa9, 0x9e, 0x41, 0x83, 0xb7, 0x16, 0xe1, 0x94, 0xfc, + 0x50, 0x74, 0x65, 0x66, 0x4d, 0x00, 0x9d, 0x5b, 0xce, 0xe3, 0xa4, 0x26, + 0xba, 0x93, 0x2c, 0x10 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_206_public_y[] = { +/* QCAVSy */ + 0x01, 0x14, 0x6d, 0x32, 0xb7, 0x0f, 0x09, 0xe6, 0x5f, 0xcf, 0x69, 0xeb, + 0x9a, 0xe6, 0x61, 0x62, 0xd1, 0x0b, 0xd0, 0x43, 0x69, 0xde, 0x8e, 0x81, + 0x87, 0xfa, 0x9c, 0x3d, 0x1b, 0x5d, 0xda, 0x26, 0xf1, 0x0b, 0x46, 0x9c, + 0xd4, 0x92, 0x5c, 0xa3, 0x7e, 0x09, 0x94, 0x41, 0x57, 0x57, 0xe6, 0x89, + 0x5e, 0x58, 0x81, 0x45 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_206_private[] = { +/* dIUT */ + 0x00, 0x4b, 0xf7, 0x35, 0x1b, 0x19, 0x58, 0x75, 0xd0, 0x1f, 0x63, 0x06, + 0xca, 0x12, 0x7d, 0xb8, 0xa1, 0xa5, 0xf5, 0x97, 0x71, 0x9c, 0x0d, 0x10, + 0xe1, 0xd6, 0x8f, 0x5d, 0x48, 0x55, 0xbf, 0x07, 0x60, 0x57, 0x90, 0x69, + 0x1f, 0xcd, 0x0d, 0x8b, 0x5d, 0xb1, 0x37, 0xd3, 0xfc, 0x26, 0x79, 0xde, + 0x75, 0xa0, 0x67, 0x81 +}; +/* QIUTx = 01d386645aaa48e2fd0950e6a9ace9dff62c8f5e94cdba45bd73c6be6bf7b763a2c9a807846312da3ab821c049ac0861f82337f0 */ +/* QIUTy = 002a6436ef8a1261aecc38c821da774a391fdcc7750c9437d9dfe64c823350813999f0fd4f07f1d6d98074098612bc52044249d4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_206_out[] = { +/* ZIUT */ + 0x00, 0x4f, 0x68, 0x4f, 0x9d, 0x55, 0x9d, 0x16, 0x48, 0x5f, 0x00, 0x23, + 0xbf, 0x01, 0x20, 0x06, 0x26, 0x5e, 0xd8, 0x1f, 0x06, 0xfb, 0xc1, 0x44, + 0x13, 0x34, 0xa5, 0x59, 0xe5, 0x50, 0x0a, 0x3f, 0x77, 0x60, 0x35, 0x65, + 0x01, 0x36, 0x94, 0x02, 0x3e, 0x0d, 0x8f, 0x44, 0xfd, 0x12, 0xdc, 0xf6, + 0x9e, 0xb8, 0xd6, 0x54 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_207_public_x[] = { +/* QCAVSx */ + 0x01, 0x19, 0x98, 0x0f, 0x11, 0x14, 0x9d, 0xee, 0x5e, 0x2c, 0x2d, 0x00, + 0x56, 0x1d, 0x3c, 0x26, 0xa4, 0x2a, 0x5a, 0x44, 0xe8, 0x74, 0x76, 0x5d, + 0xdd, 0xa4, 0xd8, 0x18, 0xea, 0x70, 0x4e, 0xdb, 0xba, 0x23, 0xab, 0xed, + 0x5e, 0x08, 0xbe, 0x92, 0xd6, 0x55, 0xd7, 0x9e, 0x55, 0xc5, 0xbc, 0x54, + 0x78, 0x7b, 0x4d, 0xd4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_207_public_y[] = { +/* QCAVSy */ + 0x01, 0x36, 0x6b, 0x3d, 0xda, 0x3e, 0x98, 0x79, 0xc4, 0x48, 0x1d, 0xdc, + 0x36, 0x7e, 0x51, 0xc1, 0xc0, 0x54, 0x19, 0x45, 0x96, 0x46, 0x36, 0xd5, + 0x02, 0x16, 0x87, 0xc2, 0x85, 0xc4, 0x7d, 0x40, 0xe7, 0x9f, 0xf7, 0xf0, + 0xbb, 0x56, 0xa9, 0x3a, 0xc5, 0x60, 0xbe, 0x8d, 0xcb, 0x97, 0x0f, 0x58, + 0xb2, 0x3b, 0x10, 0xa7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_207_private[] = { +/* dIUT */ + 0x00, 0x69, 0xda, 0x65, 0x90, 0x10, 0x34, 0x5c, 0x69, 0x00, 0xfd, 0xec, + 0xb3, 0x1d, 0xf9, 0xba, 0xbe, 0xdb, 0xe4, 0x25, 0x33, 0x98, 0x29, 0x0b, + 0x34, 0x01, 0x2f, 0xb1, 0x34, 0xbc, 0x59, 0x14, 0x75, 0x72, 0xe6, 0x2a, + 0x60, 0xf5, 0xca, 0xcc, 0xed, 0x87, 0xb0, 0xf8, 0xd1, 0xff, 0x7c, 0x04, + 0x9d, 0xfe, 0x96, 0x92 +}; +/* QIUTx = 0038687019f7c219ddd9567b20f5ea1e8a50451dd40bf5b65f7b2e133de6f36e4a3f8fa2f977efe920f845d176c8a57023cc55c2 */ +/* QIUTy = 0149397fbc42bacf85c59e04535df1d52715761eea997d4ff87204866cdc3d4a54c2425ad214a7a0dd592f4a991ab768c8f404be */ +static const uint8_t nist_kas_ecc_cdh_testvector_207_out[] = { +/* ZIUT */ + 0x00, 0x13, 0x78, 0x94, 0xf6, 0x37, 0x46, 0x0a, 0x63, 0x57, 0x68, 0x24, + 0x53, 0x69, 0x44, 0xcd, 0xdb, 0x42, 0xdf, 0xe6, 0x31, 0x69, 0xc8, 0x40, + 0x40, 0xa0, 0x34, 0x5a, 0xd7, 0x51, 0x6e, 0xc4, 0xf1, 0xad, 0x00, 0xbb, + 0x4d, 0xe2, 0x0e, 0xa6, 0xea, 0x43, 0x82, 0x4b, 0x9b, 0x0f, 0x74, 0xdf, + 0xa6, 0x88, 0x1c, 0xfc +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_208_public_x[] = { +/* QCAVSx */ + 0x01, 0xfa, 0x39, 0xb5, 0xd3, 0x37, 0x5d, 0x43, 0x24, 0x7a, 0xc9, 0x50, + 0x00, 0x61, 0xeb, 0xff, 0x7a, 0x0c, 0x15, 0xb8, 0xc5, 0xdf, 0xe9, 0xc7, + 0x51, 0x78, 0x43, 0x86, 0xc9, 0x81, 0x86, 0x0d, 0xe6, 0xe1, 0xb9, 0x58, + 0x4d, 0xa0, 0xf4, 0x21, 0x19, 0x41, 0x7f, 0x32, 0x33, 0x82, 0x90, 0x91, + 0x0a, 0x9a, 0x25, 0x9e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_208_public_y[] = { +/* QCAVSy */ + 0x00, 0x2b, 0xde, 0xcd, 0x50, 0x2b, 0xa6, 0x4a, 0x6f, 0x21, 0xd0, 0x8f, + 0xa4, 0x25, 0x03, 0x89, 0xd4, 0x27, 0x03, 0x24, 0x45, 0x6e, 0x94, 0x41, + 0x65, 0x74, 0x95, 0xc7, 0x2a, 0xd7, 0x60, 0xfb, 0x34, 0x83, 0x25, 0xf8, + 0x9b, 0x7a, 0x54, 0x04, 0xa2, 0xc2, 0x1c, 0x2a, 0xa0, 0x77, 0x11, 0xbc, + 0xf5, 0xf3, 0x04, 0x12 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_208_private[] = { +/* dIUT */ + 0x00, 0x06, 0xdf, 0xda, 0xb3, 0xca, 0x1b, 0x2a, 0x28, 0x21, 0xce, 0xfd, + 0xb5, 0x87, 0x2b, 0xb9, 0x5f, 0x02, 0x31, 0x61, 0xae, 0x4e, 0x2d, 0x54, + 0x9d, 0x0f, 0xb1, 0xf3, 0x82, 0x56, 0x34, 0x13, 0x58, 0x44, 0x91, 0x65, + 0x7d, 0xb1, 0x01, 0xc3, 0x23, 0x51, 0x48, 0x32, 0xc3, 0x63, 0xf6, 0x36, + 0xa9, 0xe6, 0x9e, 0x83 +}; +/* QIUTx = 003e9a9b5f282066e233870dcb00c4aed2d73a331f79d49c8d5c2d93908b0ef5e72b748814d1b8840642d75b7a9a55301b1e7c82 */ +/* QIUTy = 01085f57691e04afac6e884e2fdbd8df802f4d435bce611231ab3274761ead5e2e6a344a53f33c0fa156e3132062f72bcda3fc0c */ +static const uint8_t nist_kas_ecc_cdh_testvector_208_out[] = { +/* ZIUT */ + 0x00, 0xf0, 0x3b, 0x0b, 0x43, 0xa3, 0x51, 0x31, 0x16, 0x89, 0xeb, 0x1d, + 0x3f, 0xc4, 0x57, 0x01, 0x3f, 0x29, 0x4a, 0x7d, 0x02, 0xad, 0x85, 0x0c, + 0x72, 0xe4, 0xff, 0x9b, 0x64, 0xce, 0x68, 0xa4, 0x7b, 0xeb, 0x49, 0xbc, + 0x5b, 0xcb, 0xdc, 0x82, 0x85, 0x34, 0xf8, 0xc8, 0xa5, 0xe1, 0x3d, 0xe5, + 0xfe, 0x52, 0x2e, 0xb0 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_209_public_x[] = { +/* QCAVSx */ + 0x01, 0xb2, 0x55, 0xd5, 0xbb, 0x75, 0xd2, 0x59, 0x70, 0x30, 0x1d, 0xe9, + 0xe0, 0xe3, 0x95, 0x9a, 0x12, 0x20, 0x5d, 0x51, 0x1f, 0x8e, 0x64, 0xf0, + 0x42, 0xa0, 0x1c, 0x95, 0x0d, 0xb4, 0x71, 0xb1, 0xd6, 0xd5, 0x84, 0x7f, + 0x75, 0x66, 0x9e, 0xeb, 0x0b, 0xf1, 0x87, 0xf1, 0x55, 0x9d, 0xb3, 0xb2, + 0x2a, 0xee, 0xc0, 0x96 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_209_public_y[] = { +/* QCAVSy */ + 0x01, 0x7e, 0x59, 0x0c, 0xfa, 0x85, 0x53, 0x49, 0x13, 0x61, 0x98, 0xc2, + 0xdd, 0xd8, 0xa5, 0x21, 0x08, 0x82, 0x47, 0x3c, 0x9d, 0xd5, 0x91, 0xc0, + 0x2e, 0x20, 0x2c, 0xa0, 0x40, 0x4b, 0xbc, 0x9f, 0x63, 0x91, 0xd7, 0x3a, + 0xe0, 0x11, 0xda, 0xc9, 0x96, 0x51, 0x55, 0xd2, 0x65, 0x01, 0x39, 0xfe, + 0x2e, 0x54, 0xec, 0x67 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_209_private[] = { +/* dIUT */ + 0x00, 0x29, 0xb2, 0xfc, 0xb3, 0x08, 0x59, 0x6a, 0x97, 0x5c, 0x5b, 0x4c, + 0xd1, 0xe7, 0x52, 0x67, 0xc5, 0x42, 0x4e, 0x00, 0x77, 0x41, 0x14, 0xec, + 0x20, 0x51, 0xa5, 0x71, 0xb2, 0x99, 0x76, 0x61, 0x89, 0xfa, 0xd2, 0x4e, + 0x92, 0xf9, 0x6e, 0x3d, 0x52, 0x77, 0x36, 0xea, 0x48, 0x03, 0x67, 0xbd, + 0xbd, 0xd0, 0x53, 0x0e +}; +/* QIUTx = 014c757399be201e08afd8b4a671e7d3b6d7f8844498ab592e1bf69315347ce82dbd785d45922660d4d0d27fa2b0ac62e707fcec */ +/* QIUTy = 0098f0773d3efe9c290a992eca05875d3463f0736b2dfef4affd9ff00f96ade53399917dea074c798fc535738f0c5689a2447f86 */ +static const uint8_t nist_kas_ecc_cdh_testvector_209_out[] = { +/* ZIUT */ + 0x01, 0x8f, 0x55, 0xb8, 0x1f, 0x15, 0xf8, 0x62, 0xae, 0xd0, 0x42, 0xf3, + 0x74, 0x33, 0x05, 0x0a, 0xc6, 0x17, 0x18, 0xc9, 0x93, 0x9d, 0x43, 0x2b, + 0x2a, 0x20, 0xe1, 0x2d, 0x64, 0x7f, 0x99, 0x75, 0x3b, 0x8d, 0xd5, 0x12, + 0x7c, 0xf8, 0x96, 0x32, 0x47, 0xfe, 0x7e, 0x1d, 0x5a, 0xde, 0x14, 0x42, + 0x22, 0x9b, 0xc6, 0x46 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_210_public_x[] = { +/* QCAVSx */ + 0x00, 0xec, 0xf7, 0x06, 0x4f, 0x52, 0x8f, 0xad, 0xae, 0x38, 0x0c, 0xb3, + 0x82, 0x98, 0x48, 0x11, 0x04, 0x7a, 0x0d, 0x7d, 0xd9, 0xa8, 0xde, 0x8e, + 0x76, 0xf8, 0x17, 0x8a, 0xa6, 0x00, 0x69, 0xe7, 0x7a, 0x94, 0x8a, 0xcf, + 0xa7, 0x4d, 0x2c, 0x77, 0xa7, 0x68, 0x51, 0x65, 0x9a, 0x98, 0x19, 0x70, + 0x54, 0xda, 0x8d, 0x44 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_210_public_y[] = { +/* QCAVSy */ + 0x00, 0xb9, 0x8e, 0x13, 0x49, 0x7f, 0x77, 0x60, 0x72, 0x71, 0x1c, 0x42, + 0xc1, 0x8d, 0xbf, 0xc8, 0xeb, 0x8c, 0x85, 0x23, 0xff, 0x63, 0x3a, 0xf9, + 0x88, 0xa1, 0xf2, 0x42, 0xed, 0x3c, 0x3c, 0x56, 0x5d, 0x18, 0xcf, 0x22, + 0x4f, 0x87, 0x51, 0xf2, 0x94, 0x2e, 0x36, 0x0b, 0xa1, 0x6e, 0x0f, 0x58, + 0x30, 0x95, 0x29, 0x19 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_210_private[] = { +/* dIUT */ + 0x00, 0x1b, 0x98, 0x01, 0x5c, 0x02, 0x02, 0xea, 0x16, 0x41, 0x79, 0x71, + 0xa3, 0x73, 0x04, 0x25, 0x08, 0x39, 0xbd, 0x6a, 0x6e, 0x5d, 0x83, 0x49, + 0x7f, 0x7f, 0x93, 0xf0, 0xf7, 0x47, 0x2a, 0x21, 0xfc, 0xe4, 0xbe, 0x5b, + 0xe7, 0x76, 0xe9, 0x09, 0x59, 0xdb, 0xc4, 0x1a, 0x0e, 0x85, 0xed, 0x22, + 0x58, 0x37, 0xe8, 0xd5 +}; +/* QIUTx = 01fec09f94571614e7cd8e958ebcd7a2fcd8c248d408cdba359630545c31383922774d3b24e20591d8b41e954e16654fe85cbaca */ +/* QIUTy = 0031e0eb1dd1ce467a8b78d10d25b9de92cfdc2773831e6e28a152d02ae2a5a510994cc010462254441ea41121c0677fb4178bda */ +static const uint8_t nist_kas_ecc_cdh_testvector_210_out[] = { +/* ZIUT */ + 0x00, 0x2b, 0x56, 0x0d, 0x19, 0x49, 0x29, 0x7d, 0xc7, 0xe1, 0xbb, 0xe8, + 0xce, 0x49, 0xa5, 0x95, 0x76, 0x29, 0x24, 0xaf, 0xcf, 0x02, 0x71, 0xe9, + 0xc4, 0x93, 0xc1, 0x8a, 0xd5, 0xcb, 0xfc, 0xea, 0x5f, 0x39, 0x00, 0xc7, + 0xb7, 0x93, 0xae, 0x5d, 0xd4, 0x4f, 0x48, 0x88, 0x4b, 0x0b, 0xc3, 0xb5, + 0x2c, 0x66, 0xe0, 0x5a +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_211_public_x[] = { +/* QCAVSx */ + 0x00, 0x4e, 0x05, 0xc3, 0x4d, 0xac, 0x44, 0xe6, 0xe1, 0xb0, 0x8c, 0xdf, + 0xae, 0x63, 0x57, 0xc2, 0x0d, 0xb7, 0xa5, 0x44, 0xdc, 0x25, 0x3d, 0xff, + 0x1c, 0x23, 0xd4, 0xdb, 0xa8, 0x71, 0xb9, 0x67, 0x81, 0xb6, 0xa6, 0x16, + 0x38, 0xd7, 0x38, 0x65, 0xda, 0xfe, 0x0a, 0x94, 0x43, 0xc3, 0xec, 0x32, + 0x88, 0x57, 0xd2, 0x3e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_211_public_y[] = { +/* QCAVSy */ + 0x01, 0x22, 0x6c, 0x42, 0x77, 0x78, 0xbb, 0x22, 0x46, 0x24, 0xcd, 0x21, + 0x54, 0x93, 0xd7, 0xa4, 0xf3, 0x2a, 0x4f, 0x14, 0x19, 0x79, 0x23, 0x64, + 0x09, 0x50, 0x5d, 0x8c, 0xf5, 0x8d, 0x81, 0xdf, 0xd3, 0xc7, 0x93, 0xe5, + 0x95, 0x43, 0xa7, 0x80, 0x31, 0x4f, 0x3c, 0xd8, 0xee, 0x17, 0x66, 0x4d, + 0xc2, 0xe4, 0x63, 0x9e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_211_private[] = { +/* dIUT */ + 0x00, 0x47, 0x3b, 0xce, 0xcb, 0x13, 0x77, 0x11, 0xe5, 0xe8, 0x97, 0x63, + 0xa4, 0x0f, 0x77, 0xdb, 0xe2, 0xea, 0x8c, 0x25, 0x09, 0xd2, 0x09, 0x06, + 0x4e, 0x39, 0xcf, 0x90, 0x5a, 0xfa, 0xa9, 0x01, 0x08, 0x5f, 0x8e, 0x79, + 0x5c, 0x9b, 0x80, 0x17, 0xc9, 0xa5, 0xd0, 0xa1, 0xb9, 0x68, 0x12, 0xc1, + 0x24, 0xa3, 0xff, 0xbf +}; +/* QIUTx = 01c8e9adc4816e6606ffff5e1a7d48a7854c35aaf055d31833f0cabde8bbc4d2458e3cd3c82a4af80745f595b3ba12f8b5c0ce90 */ +/* QIUTy = 00fc43f193b5589aee62985735e3628374dd45a86a61baaf78c21fa6e787856ea6b8b88316540571825865ce6b8578add5faa69f */ +static const uint8_t nist_kas_ecc_cdh_testvector_211_out[] = { +/* ZIUT */ + 0x00, 0x0b, 0x43, 0xcb, 0x53, 0x9b, 0xb4, 0xbb, 0x42, 0xf1, 0x95, 0xff, + 0xdb, 0xcd, 0xeb, 0x48, 0x2b, 0x69, 0x30, 0x1c, 0x01, 0x55, 0xa8, 0x40, + 0xcd, 0x38, 0x1f, 0x55, 0xc4, 0x65, 0xa8, 0xe5, 0x7e, 0xc5, 0x1d, 0x65, + 0x55, 0x87, 0x15, 0x37, 0xb5, 0x6b, 0xf8, 0x4a, 0x15, 0x44, 0xca, 0xe2, + 0xb2, 0xb8, 0xeb, 0x38 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_212_public_x[] = { +/* QCAVSx */ + 0x01, 0x6f, 0x69, 0x60, 0xfd, 0x23, 0x57, 0xd2, 0xf7, 0x0b, 0x5f, 0x77, + 0x8b, 0xe5, 0xe0, 0xaa, 0x71, 0x55, 0x6b, 0x9d, 0x2f, 0x4c, 0xce, 0xb1, + 0x4f, 0x78, 0x12, 0xda, 0x85, 0x8a, 0xb8, 0x72, 0x81, 0x8b, 0x46, 0x10, + 0xd4, 0x1a, 0x8f, 0x66, 0x20, 0x0b, 0x43, 0x43, 0x42, 0x22, 0x27, 0xd9, + 0xfd, 0xdf, 0x71, 0x2e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_212_public_y[] = { +/* QCAVSy */ + 0x00, 0xaa, 0xf5, 0x92, 0xa7, 0x25, 0xe7, 0x73, 0x83, 0x88, 0x89, 0x6b, + 0x9b, 0xe9, 0xf7, 0x8c, 0x1c, 0x3d, 0x69, 0x72, 0xb9, 0xf9, 0x90, 0x34, + 0xd0, 0x2c, 0xc0, 0xf9, 0x77, 0x6a, 0x9f, 0x6c, 0x2f, 0x9b, 0x7d, 0x50, + 0x1f, 0x75, 0xbe, 0x18, 0x59, 0x9b, 0x08, 0x8c, 0x4c, 0x58, 0x81, 0xc6, + 0x61, 0x46, 0xe5, 0xb9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_212_private[] = { +/* dIUT */ + 0x00, 0x20, 0xdd, 0xdd, 0x67, 0x13, 0x4a, 0x41, 0x83, 0x78, 0xba, 0xa0, + 0xdd, 0xfc, 0x91, 0x11, 0xc0, 0xa2, 0xed, 0x49, 0x2b, 0x28, 0x95, 0x69, + 0xdd, 0x00, 0x61, 0xbf, 0x12, 0x26, 0xd2, 0x35, 0xbd, 0xaa, 0x52, 0x03, + 0xd3, 0xef, 0xa2, 0xbd, 0x01, 0x41, 0xd2, 0xac, 0xe2, 0x7c, 0x3a, 0xe8, + 0xe6, 0xda, 0xf1, 0x1f +}; +/* QIUTx = 0167d577b2a43cc1a7d88a6be883c28dbf48c3e1fbf21ad83e7a7e3d753fb0b6d3f80cd1376fd98be260f494757cdc063256d5b2 */ +/* QIUTy = 015ed7003b7d2bd5e0359303660add090049039cf7df396989ea18c702f704c45cf6fde7ad072d31253d1d5295e9c5d1d5c62c3b */ +static const uint8_t nist_kas_ecc_cdh_testvector_212_out[] = { +/* ZIUT */ + 0x01, 0x13, 0xdd, 0x2c, 0xf8, 0x73, 0x2c, 0xeb, 0x8a, 0x89, 0x3e, 0x14, + 0x9f, 0x13, 0xd5, 0x20, 0x26, 0xe5, 0xd8, 0x29, 0x32, 0x2d, 0x0f, 0x12, + 0x33, 0xa6, 0x24, 0xfd, 0x6b, 0x74, 0xd5, 0x6e, 0x7e, 0x63, 0x74, 0xd7, + 0x09, 0x42, 0xa2, 0x51, 0x52, 0xce, 0x50, 0x73, 0x83, 0x16, 0x60, 0x33, + 0x3f, 0xb3, 0xe0, 0x70 +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_213_public_x[] = { +/* QCAVSx */ + 0x00, 0xf5, 0x49, 0xc4, 0x7d, 0xc8, 0xe9, 0x2f, 0xec, 0xd3, 0x8b, 0x57, + 0x50, 0x89, 0x58, 0x80, 0xe4, 0x49, 0xf1, 0xe3, 0x1a, 0xbe, 0x0b, 0xb1, + 0xea, 0xcc, 0x84, 0x29, 0x8f, 0x83, 0x61, 0x08, 0xe5, 0xa3, 0x08, 0xcc, + 0xb9, 0x57, 0x8d, 0xcb, 0xd4, 0xbe, 0x61, 0x77, 0x75, 0x2e, 0xb2, 0x31, + 0xe7, 0x8f, 0x01, 0x1c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_213_public_y[] = { +/* QCAVSy */ + 0x00, 0x93, 0x66, 0x3e, 0xc3, 0xfc, 0xb5, 0x4d, 0x67, 0x68, 0x97, 0xbf, + 0xc9, 0x5d, 0xb5, 0xe5, 0x4a, 0xd6, 0xee, 0xa1, 0xec, 0x7b, 0x46, 0xca, + 0x4b, 0xf3, 0xd2, 0x53, 0x58, 0x39, 0xf1, 0x01, 0xcb, 0x3e, 0x6d, 0x5f, + 0x11, 0xb6, 0xa3, 0x6b, 0xf4, 0x03, 0x63, 0xc3, 0x1c, 0x9f, 0x88, 0x13, + 0x78, 0x62, 0x67, 0x4f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_213_private[] = { +/* dIUT */ + 0x00, 0x60, 0x7a, 0x5a, 0x65, 0x32, 0x17, 0x7b, 0x52, 0xf2, 0x34, 0x92, + 0x71, 0x7d, 0xd0, 0xa7, 0xb2, 0xaf, 0x98, 0xe0, 0x48, 0x84, 0xf7, 0x70, + 0x75, 0xe4, 0x60, 0x44, 0x10, 0xc5, 0x04, 0x4a, 0x08, 0x46, 0x1e, 0xcf, + 0x37, 0xc4, 0xef, 0xa3, 0xed, 0xc2, 0xcb, 0x66, 0x7c, 0x84, 0xb8, 0x64, + 0x15, 0x93, 0x6b, 0x70 +}; +/* QIUTx = 000a5677ac6c00d2646054dbebfc536db0a9b351a2408a73e083ad62d182fb87cb80322c539553ecdbc213ce84c66ddf8dc1d234 */ +/* QIUTy = 01327a0a3769240fda45f94bb07361c74aa8c8d119414a7b5666e25a3ab6881975396325a77f541a1ba268012a82c5110d2a49e2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_213_out[] = { +/* ZIUT */ + 0x00, 0xc8, 0xe6, 0x2a, 0xc2, 0x5c, 0x11, 0xe8, 0x6b, 0x98, 0x64, 0x2e, + 0x4e, 0xc7, 0xad, 0xde, 0x9d, 0x94, 0x36, 0xf9, 0x33, 0x73, 0x69, 0xfb, + 0x06, 0x5a, 0xbc, 0x9e, 0xa7, 0x84, 0xf9, 0x0b, 0x8b, 0x8b, 0xeb, 0xae, + 0x35, 0xda, 0x92, 0x18, 0x54, 0x86, 0x19, 0x1d, 0xd9, 0xf4, 0x93, 0x70, + 0xb1, 0x14, 0x8c, 0xe6 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_214_public_x[] = { +/* QCAVSx */ + 0x00, 0x41, 0x1e, 0x5d, 0x4c, 0x96, 0xe3, 0x5d, 0xe9, 0xb5, 0x41, 0xda, + 0x5f, 0xac, 0x69, 0x13, 0x36, 0x46, 0x2c, 0x88, 0x2d, 0x8e, 0x8c, 0xe4, + 0xd6, 0xeb, 0x71, 0x21, 0x41, 0x7e, 0x70, 0x95, 0x0c, 0x4d, 0x95, 0x02, + 0xf6, 0x45, 0x65, 0xd5, 0xa6, 0xcf, 0xa7, 0x35, 0xc9, 0x0e, 0xef, 0x83, + 0xc7, 0xb8, 0x61, 0xe2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_214_public_y[] = { +/* QCAVSy */ + 0x00, 0x96, 0xb9, 0x04, 0xe3, 0x7c, 0xa1, 0xc2, 0xdb, 0x59, 0xa5, 0x46, + 0x15, 0x62, 0x7e, 0x1c, 0x33, 0x56, 0x16, 0x0f, 0xe1, 0x75, 0x28, 0x4a, + 0xad, 0xc3, 0xb2, 0xfa, 0x06, 0xba, 0x0b, 0x30, 0xaa, 0xa0, 0x7c, 0x84, + 0xe6, 0x4e, 0x48, 0x65, 0x2e, 0x5f, 0xeb, 0x30, 0x35, 0x95, 0x06, 0x6e, + 0x0f, 0x84, 0x68, 0xf7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_214_private[] = { +/* dIUT */ + 0x00, 0x34, 0xda, 0x9a, 0x45, 0x37, 0x11, 0xf0, 0x4a, 0x0b, 0x1e, 0xa1, + 0xb9, 0xaf, 0x70, 0x1e, 0x0d, 0xc3, 0xa5, 0x5c, 0xdd, 0x58, 0x5e, 0x43, + 0xe3, 0xec, 0xf4, 0x1e, 0x93, 0x4e, 0xca, 0xf8, 0x80, 0xff, 0x16, 0x14, + 0xdc, 0xe5, 0xcc, 0x99, 0x2a, 0x69, 0xad, 0xdf, 0xc4, 0x08, 0xda, 0xe1, + 0xb0, 0x9b, 0x8d, 0x05 +}; +/* QIUTx = 01f7bff435547a89516d017d1bdac4cda36041a0d3dfd03258562b2e28f40cd64f6ae2b70457773f9675cffc40c021e4702b08d6 */ +/* QIUTy = 0013c59a72f0c83f5bb90a0bfee798952fb91ee329c98c4b5914f445ae7c8483767052b5f529974621545ddcd6377f5e387d573c */ +static const uint8_t nist_kas_ecc_cdh_testvector_214_out[] = { +/* ZIUT */ + 0x01, 0x25, 0x05, 0x74, 0x6f, 0x1a, 0x40, 0xef, 0x75, 0xf9, 0x50, 0x59, + 0x52, 0x11, 0xce, 0x04, 0xf8, 0x7f, 0x1d, 0xaf, 0xff, 0xfd, 0xf8, 0xc1, + 0x26, 0x00, 0xa9, 0xe2, 0x99, 0x4c, 0x8c, 0x1d, 0x8b, 0x19, 0xc0, 0xe0, + 0x55, 0x9a, 0xdf, 0x9a, 0x94, 0x76, 0x2c, 0xb9, 0x83, 0x56, 0x9d, 0xe6, + 0xd0, 0xd8, 0xba, 0xca +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_215_public_x[] = { +/* QCAVSx */ + 0x00, 0x0f, 0xa8, 0x24, 0x3f, 0x00, 0x0a, 0x33, 0x98, 0x80, 0x8a, 0x1f, + 0x88, 0xff, 0xc5, 0xa3, 0x42, 0x96, 0x8f, 0xee, 0x5c, 0x7b, 0x26, 0xa9, + 0xe1, 0xff, 0xa2, 0x6e, 0xfa, 0x88, 0x5e, 0x74, 0xe1, 0xc5, 0x62, 0x02, + 0x7d, 0x95, 0xdb, 0x08, 0xcc, 0x15, 0xbd, 0x25, 0xa3, 0xfc, 0x11, 0xab, + 0x4d, 0xc1, 0x3c, 0xa2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_215_public_y[] = { +/* QCAVSy */ + 0x00, 0xfe, 0xd6, 0x87, 0xc7, 0x19, 0x7f, 0xf1, 0xae, 0xb9, 0x80, 0xe7, + 0x2a, 0x3a, 0x7c, 0x31, 0x81, 0x42, 0x05, 0x2c, 0x23, 0x89, 0xb0, 0x86, + 0x6d, 0xb3, 0xb8, 0x7e, 0x5c, 0x80, 0x25, 0xe7, 0x9b, 0xb4, 0xf4, 0xf9, + 0x96, 0xfa, 0x63, 0x52, 0xab, 0x9c, 0xb2, 0x01, 0x72, 0xef, 0x78, 0xd6, + 0xff, 0xca, 0x90, 0x6f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_215_private[] = { +/* dIUT */ + 0x00, 0x31, 0x41, 0xaf, 0xbb, 0xa8, 0xb4, 0xd9, 0xf0, 0xcb, 0xe8, 0x29, + 0x7f, 0x36, 0x58, 0x73, 0x19, 0x67, 0x39, 0x46, 0x5e, 0x3e, 0x20, 0xa8, + 0x9a, 0xf9, 0xfd, 0xf8, 0xb0, 0x1d, 0x19, 0x5a, 0xa1, 0x05, 0x2e, 0x61, + 0x76, 0xb5, 0xfa, 0xd8, 0x56, 0x13, 0x6b, 0x6b, 0x32, 0x0e, 0xeb, 0xfc, + 0x08, 0xc1, 0xcd, 0x01 +}; +/* QIUTx = 01805ffc576e8a45f06297b2335d03abc8adfd15ad37e76d80d3b4180d5f72efc90f3f2b036acd817f40fd49064aa25ea383c82e */ +/* QIUTy = 01f22da6b50ac5628943f05b141493cacc0f02bcdf3bffdb43582343b68615761a180bd7d1ab1ddc15f5374a8f665d13b4b91272 */ +static const uint8_t nist_kas_ecc_cdh_testvector_215_out[] = { +/* ZIUT */ + 0x01, 0x9a, 0x71, 0xab, 0x57, 0x65, 0x46, 0xe2, 0x35, 0x1a, 0xa9, 0x2b, + 0x60, 0x75, 0xe8, 0x22, 0x98, 0x13, 0xe6, 0xa2, 0xcb, 0x36, 0x47, 0x14, + 0x7b, 0x19, 0x2b, 0x45, 0x97, 0xf1, 0x21, 0x72, 0x23, 0xe7, 0x19, 0x7d, + 0x84, 0x6c, 0x0d, 0x65, 0xea, 0x0d, 0x4a, 0xa4, 0xc5, 0x03, 0xbd, 0x00, + 0x0b, 0xa3, 0x12, 0xba +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_216_public_x[] = { +/* QCAVSx */ + 0x00, 0xbe, 0x7d, 0x58, 0x04, 0x32, 0x63, 0xab, 0x2f, 0x42, 0x25, 0x2d, + 0x41, 0xb5, 0x82, 0xd8, 0x62, 0xc2, 0xb2, 0x43, 0xce, 0x18, 0x57, 0x60, + 0x81, 0xbd, 0x6e, 0xdd, 0x2f, 0x63, 0xf0, 0x16, 0x4f, 0x36, 0x5c, 0xae, + 0x67, 0x26, 0x8d, 0x22, 0x7f, 0x39, 0x44, 0x67, 0x7e, 0x1c, 0x14, 0x6a, + 0xf8, 0x64, 0xb8, 0xae +}; +static const uint8_t nist_kas_ecc_cdh_testvector_216_public_y[] = { +/* QCAVSy */ + 0x01, 0xa4, 0xbc, 0xbc, 0x64, 0x16, 0xd8, 0x65, 0x97, 0xa1, 0x48, 0xca, + 0x4d, 0x61, 0x0e, 0xe6, 0x56, 0xa0, 0x00, 0x26, 0xce, 0x60, 0x47, 0xbd, + 0x9f, 0xbd, 0x40, 0xd8, 0x95, 0x30, 0x19, 0x6a, 0x46, 0x93, 0xae, 0x59, + 0x5d, 0x69, 0x95, 0x65, 0x03, 0xb9, 0xd2, 0xab, 0x4a, 0xab, 0xe7, 0xc9, + 0x58, 0xa1, 0x4c, 0x69 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_216_private[] = { +/* dIUT */ + 0x00, 0x4e, 0x51, 0x77, 0x96, 0xca, 0xc9, 0xd7, 0xc7, 0x53, 0x16, 0xeb, + 0x5e, 0x68, 0x96, 0x3f, 0xe6, 0x32, 0x47, 0x81, 0xfa, 0xb9, 0x86, 0xe9, + 0x40, 0x20, 0x0e, 0x71, 0x1d, 0xdb, 0xf9, 0x88, 0x2d, 0x99, 0xa6, 0x20, + 0xa9, 0x76, 0x35, 0x2e, 0x24, 0x96, 0x74, 0x8c, 0xfb, 0x61, 0xdc, 0xcb, + 0xf6, 0xd6, 0x59, 0xcc +}; +/* QIUTx = 0056a452fb1d558079c3e91bf22f86884ca89788806fe7d6d6ca40b5485079d77dc43e466a71259792c65ff6ab7204066c0e67a8 */ +/* QIUTy = 01f29b723d9f7d4de6ccc2f9708079c5d30ae5d960e62a7c4f6dc98bfc95b4f531f197c39486705432594203c25147156dfd5b5c */ +static const uint8_t nist_kas_ecc_cdh_testvector_216_out[] = { +/* ZIUT */ + 0x01, 0x4f, 0x4b, 0x7e, 0xa9, 0x3c, 0x9d, 0xd8, 0x46, 0xd2, 0x22, 0x8c, + 0x2b, 0x6a, 0x8d, 0xfe, 0x61, 0x60, 0x57, 0x23, 0x2b, 0x7a, 0xf8, 0x45, + 0xa5, 0x70, 0xcb, 0x6c, 0xac, 0xf9, 0xfe, 0xef, 0x2d, 0x8e, 0xf4, 0xfa, + 0xfb, 0x28, 0x5b, 0x38, 0xe6, 0x3c, 0xce, 0x0a, 0x09, 0xb4, 0xd8, 0x2d, + 0xbe, 0x43, 0xa3, 0x90 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_217_public_x[] = { +/* QCAVSx */ + 0x01, 0x1f, 0xea, 0x58, 0xd9, 0xe3, 0x6c, 0xf8, 0xed, 0x4e, 0xf3, 0xb4, + 0x2f, 0x77, 0xcc, 0xea, 0x93, 0xbf, 0x54, 0x2a, 0xc9, 0x21, 0x41, 0xdc, + 0x2c, 0x09, 0x40, 0x61, 0x98, 0x5f, 0x3d, 0xf7, 0x86, 0xd1, 0x92, 0xa5, + 0x7b, 0xee, 0x07, 0x25, 0x50, 0xb3, 0x02, 0x58, 0x3f, 0x0f, 0x94, 0x28, + 0x30, 0x1b, 0x1b, 0x76 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_217_public_y[] = { +/* QCAVSy */ + 0x01, 0xb3, 0xdc, 0xc1, 0xb8, 0xa3, 0x54, 0x52, 0x64, 0x42, 0x73, 0x86, + 0x32, 0x9e, 0xb8, 0x1f, 0xe9, 0x92, 0x65, 0x40, 0x40, 0x69, 0x47, 0x81, + 0xc0, 0xd8, 0xb2, 0x7c, 0x1e, 0x49, 0x44, 0x2b, 0x99, 0xba, 0xb9, 0x3e, + 0xf9, 0x66, 0x6f, 0xea, 0x14, 0xd4, 0x84, 0x3e, 0xe4, 0xbc, 0x5b, 0x04, + 0x5a, 0xc5, 0x0c, 0x11 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_217_private[] = { +/* dIUT */ + 0x00, 0x1c, 0x80, 0xb6, 0x4d, 0x51, 0xe8, 0x02, 0x56, 0x99, 0xe7, 0xbe, + 0x2c, 0x4b, 0x98, 0x3c, 0xfa, 0x4b, 0x7e, 0x91, 0xb1, 0x12, 0xe2, 0xec, + 0xa5, 0xf9, 0xd0, 0xcb, 0x7e, 0x3d, 0x4f, 0x85, 0xaf, 0xf7, 0xb3, 0x3a, + 0x92, 0x1e, 0xaa, 0x12, 0x4c, 0xb7, 0x00, 0x2e, 0xab, 0x62, 0x97, 0x3d, + 0x65, 0xe1, 0x6b, 0xc9 +}; +/* QIUTx = 01fd0e4eafb26c08c9f8e747d4991f468c76b4864166e37642b583db285a4bc4c33979917d9129a91cb0a75c1aee7cd4fbab73ce */ +/* QIUTy = 00468efabcf448fcce821f3de81e994d79a7d99ea989ac81fa135f7ac88b154c767909c681f7e48c00b2e66bbaeb8f8688f44672 */ +static const uint8_t nist_kas_ecc_cdh_testvector_217_out[] = { +/* ZIUT */ + 0x00, 0x1f, 0xe2, 0xed, 0x30, 0xad, 0x41, 0x43, 0xc5, 0xee, 0xb0, 0xb7, + 0x62, 0x2e, 0x6a, 0xa4, 0x9e, 0x4e, 0x4d, 0x51, 0xc1, 0xdd, 0xc4, 0x67, + 0xb3, 0xfc, 0x54, 0x21, 0x5d, 0xae, 0x93, 0x1b, 0xe0, 0xb6, 0xb6, 0x44, + 0x3e, 0x71, 0x68, 0x95, 0xac, 0xb6, 0x57, 0x0c, 0xdc, 0x21, 0xfc, 0xbd, + 0xae, 0x46, 0xe5, 0xd6 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_218_public_x[] = { +/* QCAVSx */ + 0x00, 0xca, 0x80, 0x93, 0x40, 0xbd, 0x13, 0x35, 0x4b, 0x60, 0x71, 0xd0, + 0x73, 0xe6, 0x5b, 0x9b, 0x0d, 0x2b, 0xac, 0x82, 0xe2, 0x2a, 0xbf, 0xca, + 0xc7, 0xe7, 0x0a, 0xfd, 0x9d, 0x22, 0x48, 0x52, 0xf0, 0xe2, 0x12, 0x97, + 0x6e, 0x5e, 0xc8, 0x23, 0xeb, 0x89, 0x50, 0xe0, 0x2b, 0xc7, 0x59, 0xec, + 0xf5, 0x6f, 0x79, 0xa8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_218_public_y[] = { +/* QCAVSy */ + 0x00, 0x31, 0x28, 0x1e, 0x89, 0x76, 0x40, 0x1a, 0xab, 0x58, 0xfa, 0x8e, + 0xaf, 0x86, 0x36, 0xfe, 0xb0, 0x13, 0x17, 0x0b, 0xca, 0xb5, 0x78, 0x1b, + 0xe0, 0xa2, 0x8d, 0x27, 0x33, 0x9e, 0x94, 0x70, 0xe1, 0x66, 0xc7, 0xf6, + 0x85, 0xf2, 0xea, 0x91, 0x43, 0x31, 0x0d, 0xca, 0x1b, 0x3a, 0xb8, 0xe1, + 0xc8, 0xe6, 0x05, 0x92 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_218_private[] = { +/* dIUT */ + 0x00, 0x43, 0xc9, 0x6c, 0x32, 0xcf, 0x64, 0x8b, 0x03, 0x61, 0x12, 0x42, + 0x1a, 0xdb, 0xaa, 0x92, 0x5c, 0xd5, 0x41, 0x75, 0xab, 0xad, 0x39, 0xe5, + 0x68, 0x1b, 0xfc, 0x9e, 0xb4, 0xb1, 0xb6, 0x49, 0xae, 0xc1, 0xc8, 0x76, + 0xec, 0x1e, 0xc4, 0x61, 0x0f, 0x1b, 0x3b, 0x06, 0x51, 0x4a, 0x48, 0xe6, + 0xea, 0x7a, 0x4a, 0x25 +}; +/* QIUTx = 00de181e81b9e7776d474694a2d124d0b876d9548f20ee3386304945d9131f90457d9b938df098b035bedaaf80ed6d979404fc70 */ +/* QIUTy = 0181a3516dbea9da97d6ececdb10f96d54469d273ab366e89a40fdcedcf1bda837d5c14bd10c0b6a2a9c8a47810125c764dd35ef */ +static const uint8_t nist_kas_ecc_cdh_testvector_218_out[] = { +/* ZIUT */ + 0x01, 0x61, 0x0e, 0xfb, 0x48, 0xfd, 0x22, 0x26, 0x19, 0x21, 0xf7, 0x48, + 0x4e, 0xd6, 0x38, 0x2f, 0xce, 0xb6, 0xbd, 0xf2, 0x8f, 0x3b, 0xc2, 0x34, + 0x0a, 0x17, 0x5b, 0x79, 0x71, 0xb9, 0x3e, 0xd5, 0xff, 0x35, 0x7e, 0xd5, + 0x5e, 0x53, 0x07, 0xbb, 0xf4, 0x2e, 0x40, 0xa5, 0xb3, 0xfa, 0xbd, 0xae, + 0xd0, 0xce, 0x19, 0xa2 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_219_public_x[] = { +/* QCAVSx */ + 0x00, 0x74, 0x79, 0x5b, 0x0a, 0x9c, 0xa0, 0x70, 0x49, 0x1f, 0xb5, 0x4a, + 0x3b, 0xc2, 0x49, 0x98, 0x1d, 0xef, 0xbe, 0xc0, 0x37, 0xe4, 0x04, 0x0f, + 0x76, 0x65, 0x64, 0x28, 0xb1, 0x53, 0x8b, 0x97, 0x85, 0x03, 0xf8, 0x1f, + 0x80, 0xad, 0x9e, 0xf9, 0x7c, 0x5e, 0x12, 0x7b, 0xa5, 0x1e, 0xc0, 0x40, + 0x58, 0x4b, 0x9a, 0x20 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_219_public_y[] = { +/* QCAVSy */ + 0x00, 0x3e, 0xce, 0x27, 0xf3, 0xda, 0xef, 0xe7, 0xbd, 0xff, 0xdf, 0xa7, + 0x27, 0xb2, 0xaf, 0x95, 0xaf, 0x85, 0x91, 0xaf, 0x94, 0x6c, 0xdd, 0xfe, + 0x37, 0xe8, 0x56, 0x43, 0xb8, 0xd1, 0x79, 0xca, 0x8b, 0x95, 0x29, 0x10, + 0x6f, 0x9c, 0x5f, 0x3a, 0x95, 0xa8, 0x81, 0x92, 0x25, 0xf9, 0xd7, 0xd4, + 0xa7, 0x30, 0xfd, 0x22 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_219_private[] = { +/* dIUT */ + 0x00, 0x36, 0x36, 0x85, 0x4b, 0x8e, 0xe0, 0x25, 0x4b, 0xb2, 0xd0, 0xeb, + 0xed, 0xc7, 0x20, 0xb6, 0x6b, 0x20, 0x12, 0x9a, 0x21, 0xf1, 0xa4, 0xfe, + 0x39, 0x11, 0x8c, 0xfd, 0xd4, 0xd1, 0x37, 0xdb, 0xe5, 0xe5, 0x70, 0xeb, + 0xe2, 0xc4, 0x8a, 0x7f, 0x9a, 0xc2, 0x1c, 0xff, 0x3e, 0x5a, 0xdf, 0x47, + 0x43, 0x46, 0x97, 0xdb +}; +/* QIUTx = 01efc0cd1a86ce7544f25f44e63a0913c11fd6b08bc09ad8cd82f3af7e32a7a7ecacd56e25526589313879d4a7fd4382d4114e4a */ +/* QIUTy = 005a34ef7403599c2f83f3e83299524893f2418ff95d6c2fdc0a3db970e62fddcf4cda182aa78b54fd8c2e818fb1ee2dd2776763 */ +static const uint8_t nist_kas_ecc_cdh_testvector_219_out[] = { +/* ZIUT */ + 0x00, 0x8d, 0x99, 0x09, 0x82, 0xaa, 0xc8, 0xd5, 0x37, 0x1b, 0x86, 0x7d, + 0xe2, 0x1e, 0x09, 0x06, 0x4f, 0xef, 0x30, 0xe7, 0x33, 0x21, 0x33, 0x7d, + 0xc2, 0x4f, 0x19, 0xad, 0x5d, 0xdb, 0x6c, 0x4a, 0xd2, 0x17, 0x13, 0x6b, + 0x7c, 0x61, 0xe3, 0x60, 0xa7, 0x3f, 0xa7, 0x57, 0x1d, 0x52, 0x6c, 0x8f, + 0x51, 0x4a, 0x06, 0xd4 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_220_public_x[] = { +/* QCAVSx */ + 0x01, 0x1e, 0xb6, 0x4e, 0xd4, 0x24, 0x9e, 0x11, 0x95, 0xb2, 0xd1, 0x30, + 0x7a, 0x35, 0xa5, 0x14, 0xd6, 0x6d, 0x29, 0xba, 0x6f, 0x90, 0x44, 0xf9, + 0xc0, 0x2b, 0x4b, 0x2d, 0x3c, 0xb3, 0xe3, 0xd4, 0xc0, 0xcd, 0xc5, 0x48, + 0x9c, 0xdd, 0xfb, 0x96, 0x22, 0x6c, 0x9c, 0xe3, 0xe3, 0x6f, 0xb8, 0xff, + 0x2e, 0xef, 0x20, 0x8c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_220_public_y[] = { +/* QCAVSy */ + 0x00, 0x99, 0x88, 0x0b, 0x0d, 0x0d, 0x43, 0xc5, 0xc5, 0x79, 0xad, 0x77, + 0xdd, 0xae, 0x68, 0xf2, 0xc9, 0x17, 0xf4, 0xb0, 0x62, 0xea, 0x8d, 0x77, + 0x7b, 0x9c, 0xdf, 0x46, 0x5c, 0xbb, 0x59, 0x10, 0x7e, 0x70, 0x99, 0x27, + 0x14, 0xe8, 0xcb, 0xfa, 0xc7, 0x62, 0x96, 0xd5, 0xed, 0xe9, 0x9c, 0x48, + 0xd3, 0x8a, 0x89, 0x73 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_220_private[] = { +/* dIUT */ + 0x00, 0x49, 0x98, 0xa0, 0x62, 0xa3, 0x21, 0x70, 0xbb, 0x35, 0x89, 0x54, + 0xd2, 0xc2, 0x49, 0x6d, 0xa8, 0x86, 0x20, 0x08, 0x27, 0xfa, 0x13, 0x56, + 0x68, 0x36, 0xae, 0x26, 0xe3, 0x8d, 0x51, 0x92, 0x6c, 0xa3, 0xd2, 0x02, + 0x58, 0x9f, 0x7b, 0xfa, 0x27, 0xea, 0x22, 0xd3, 0x99, 0x97, 0x3d, 0xb6, + 0xf9, 0xfd, 0xe9, 0xf4 +}; +/* QIUTx = 00f71590b04290b5f3cd9ba0e394a3be5a1514f45e53497f6cdedbf839728e0288135d769e4b28932c875823fe256e891997c476 */ +/* QIUTy = 009d16ba726a5a9e09103bc94a09d8079ac8edf23410c8469f79f55f3355cfb3ad703624ec6d75eceae3881da20903c71de1f5ac */ +static const uint8_t nist_kas_ecc_cdh_testvector_220_out[] = { +/* ZIUT */ + 0x01, 0x55, 0xdc, 0x98, 0x72, 0x9c, 0x8c, 0x1b, 0xc6, 0x5e, 0xb8, 0xa3, + 0xec, 0x09, 0x13, 0x5f, 0x46, 0xbf, 0xa3, 0x13, 0xbf, 0x56, 0xaa, 0x31, + 0x69, 0xe3, 0x12, 0xdb, 0x89, 0x91, 0xab, 0xda, 0x33, 0x8f, 0x8a, 0xc7, + 0xa7, 0x5b, 0xce, 0x42, 0x88, 0x40, 0x68, 0xef, 0xb7, 0xe6, 0xe6, 0x25, + 0x93, 0x9d, 0x2b, 0x88 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_221_public_x[] = { +/* QCAVSx */ + 0x00, 0xa1, 0x5e, 0x96, 0xa7, 0x76, 0xea, 0xdb, 0x8f, 0x8a, 0x0b, 0x61, + 0x36, 0x03, 0x35, 0xcb, 0x50, 0x17, 0xd7, 0xd9, 0x71, 0x16, 0x48, 0x93, + 0x41, 0xe9, 0x95, 0x15, 0x7f, 0x1a, 0xdf, 0x17, 0x8e, 0x56, 0x28, 0xba, + 0xd3, 0xe8, 0x30, 0xbe, 0xe5, 0x44, 0x33, 0x11, 0x91, 0x64, 0x88, 0x6d, + 0xb5, 0xc3, 0x46, 0x54 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_221_public_y[] = { +/* QCAVSy */ + 0x00, 0x55, 0x1c, 0xa5, 0x60, 0x5e, 0x4a, 0xe0, 0x53, 0x45, 0x34, 0xa0, + 0xab, 0x34, 0x3d, 0x03, 0x9a, 0x3b, 0xa7, 0xa1, 0xcc, 0xe8, 0x32, 0xc4, + 0xd6, 0x5e, 0x26, 0xba, 0xe7, 0xab, 0x8e, 0x5f, 0x9c, 0x74, 0xb3, 0xd4, + 0x21, 0xa5, 0x28, 0xe5, 0x59, 0x77, 0x8a, 0xb2, 0x7b, 0x59, 0xaa, 0xe1, + 0xa9, 0x16, 0xd4, 0xeb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_221_private[] = { +/* dIUT */ + 0x00, 0x5a, 0x3f, 0x80, 0x5f, 0xe3, 0xc3, 0x26, 0x6f, 0xeb, 0x3e, 0x0b, + 0xb7, 0xda, 0x67, 0x61, 0xbb, 0x11, 0x76, 0x18, 0xbc, 0x57, 0xaf, 0x35, + 0x7b, 0x53, 0xf1, 0x99, 0xe6, 0xe4, 0xcb, 0xc1, 0x28, 0x19, 0x75, 0x32, + 0x14, 0x03, 0xea, 0x6d, 0xe6, 0x18, 0xec, 0x32, 0xe8, 0x6b, 0x8c, 0xa1, + 0xe1, 0x0d, 0x7c, 0x43 +}; +/* QIUTx = 01ae460e1248504d33d67ed750f1d618e53728d55e390dfc18d94b56dbb3d3c0bdc96c92ca1eca9f44fb8a58cf36dcfcc0588cbe */ +/* QIUTy = 00f7011fc321ef6258dcfc1fdc2c0a4e54c86ec939bc9ceca6c291750c1ff540b34a418793842a2c5cab6061dbbe9b5be3fa6115 */ +static const uint8_t nist_kas_ecc_cdh_testvector_221_out[] = { +/* ZIUT */ + 0x01, 0x09, 0xe8, 0x5c, 0x68, 0x4d, 0x02, 0x7a, 0x62, 0x5e, 0xc5, 0xe6, + 0xdf, 0x95, 0x2e, 0x2f, 0x20, 0xa1, 0x4e, 0xd5, 0xb0, 0x92, 0xd1, 0xb1, + 0xb3, 0x84, 0x35, 0x25, 0x13, 0x03, 0x84, 0x4d, 0x23, 0x0f, 0xff, 0xc5, + 0x3d, 0x84, 0xb9, 0x23, 0x55, 0x5e, 0x1e, 0x1c, 0xbe, 0xbe, 0x20, 0xb5, + 0xd6, 0x8c, 0x3b, 0xc6 +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_222_public_x[] = { +/* QCAVSx */ + 0x01, 0x64, 0x27, 0xe7, 0x2b, 0xc5, 0x7d, 0x26, 0xa9, 0x10, 0xa6, 0x72, + 0x2e, 0xac, 0x2c, 0x78, 0xfb, 0xa8, 0xab, 0xff, 0xcc, 0xbc, 0x11, 0xa9, + 0xf8, 0x37, 0x7b, 0xfe, 0x21, 0x3e, 0xd9, 0xad, 0x64, 0xbd, 0xe2, 0xae, + 0x86, 0x87, 0xf8, 0xff, 0x1d, 0xfd, 0xb2, 0x9b, 0x5d, 0xce, 0xcd, 0x02, + 0x26, 0x98, 0x28, 0xc2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_222_public_y[] = { +/* QCAVSy */ + 0x00, 0xad, 0x4f, 0x9a, 0xbc, 0x21, 0xda, 0x0d, 0x31, 0xf1, 0x96, 0x59, + 0xcd, 0x3b, 0x0c, 0x18, 0x55, 0x81, 0x43, 0x6a, 0xc0, 0x8b, 0x15, 0xc0, + 0xb4, 0x8a, 0x7a, 0xc3, 0x9e, 0xed, 0x03, 0xe0, 0xee, 0x97, 0xe1, 0x64, + 0xcf, 0xaa, 0x5a, 0xbc, 0x77, 0x44, 0x12, 0xcb, 0xff, 0xf9, 0x4a, 0x9e, + 0xa2, 0xa9, 0x63, 0x6a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_222_private[] = { +/* dIUT */ + 0x00, 0x55, 0x90, 0x1e, 0x9b, 0x65, 0x86, 0xb7, 0xf3, 0x37, 0x26, 0x60, + 0xeb, 0xcf, 0xe9, 0x02, 0x49, 0x90, 0x0c, 0x90, 0x2d, 0x7c, 0x63, 0x2a, + 0x8d, 0x17, 0xfa, 0xe2, 0x1d, 0x3f, 0xde, 0x30, 0x37, 0x32, 0x5b, 0x57, + 0x75, 0xea, 0xc5, 0xa1, 0x74, 0xa1, 0xee, 0x2b, 0x3f, 0xf2, 0xbc, 0x5c, + 0xe6, 0x9d, 0x8c, 0xc1 +}; +/* QIUTx = 00ba952233531b6a6c7ade6f338d24fc65777b5d305297e66d32cb1bc506c5bca2287d3acd33fe19653d6c88a06eca3712ce9caa */ +/* QIUTy = 00716beb14f02233630f34603e309bf6e2572f0b791dfa4c582af6a37abcdd64e8d785a95ddff59bbc6fbe1b7fc735725efcf0ba */ +static const uint8_t nist_kas_ecc_cdh_testvector_222_out[] = { +/* ZIUT */ + 0x01, 0xae, 0x81, 0x4e, 0x02, 0xc4, 0x68, 0x4c, 0x21, 0xdd, 0x7e, 0x58, + 0xa6, 0x5e, 0xc5, 0x1e, 0xc6, 0x8c, 0x37, 0xe5, 0x9e, 0x29, 0x9c, 0xe6, + 0x56, 0x08, 0x18, 0x6c, 0x0a, 0xcc, 0xe0, 0x8e, 0x41, 0xc8, 0x32, 0x0b, + 0x19, 0x41, 0xa6, 0x11, 0xfe, 0x66, 0xb1, 0x92, 0x1b, 0x55, 0x8d, 0x7f, + 0x40, 0x2d, 0x0e, 0xb0 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_223_public_x[] = { +/* QCAVSx */ + 0x01, 0x2e, 0x89, 0xdc, 0xcd, 0xf9, 0x75, 0x85, 0x1a, 0xcc, 0xf0, 0x29, + 0x4c, 0xf4, 0xbd, 0xe1, 0x25, 0x9c, 0x90, 0x7a, 0x6d, 0x3a, 0xce, 0xf6, + 0x9f, 0x19, 0x39, 0xb5, 0x58, 0xc4, 0xd2, 0x11, 0x52, 0x2e, 0x4e, 0xaa, + 0xc6, 0x13, 0xe3, 0xac, 0x84, 0x91, 0xc9, 0x3d, 0xeb, 0x6d, 0x34, 0x4a, + 0x9f, 0x87, 0xac, 0xbe +}; +static const uint8_t nist_kas_ecc_cdh_testvector_223_public_y[] = { +/* QCAVSy */ + 0x01, 0xa5, 0x26, 0x08, 0xea, 0xd0, 0x9d, 0x2d, 0xb1, 0x23, 0xa0, 0xdc, + 0x78, 0x2a, 0xb2, 0x0d, 0xdb, 0x79, 0x3d, 0x5b, 0xb7, 0x0a, 0xc9, 0x5c, + 0x58, 0xe6, 0x21, 0x46, 0xbe, 0xb6, 0x2b, 0xb6, 0x68, 0xfd, 0x57, 0xf9, + 0x20, 0x38, 0xe4, 0x58, 0x5c, 0xde, 0x1f, 0x91, 0xee, 0x8c, 0x52, 0x52, + 0x6a, 0xfe, 0xb1, 0xb5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_223_private[] = { +/* dIUT */ + 0x00, 0x04, 0x4a, 0xe4, 0x3b, 0xd2, 0x47, 0xe7, 0x5a, 0xfa, 0x7b, 0xd8, + 0xdc, 0x28, 0xe7, 0x5b, 0xdb, 0x9d, 0xdd, 0x99, 0xdf, 0x56, 0x66, 0x8c, + 0x83, 0x14, 0x54, 0xdc, 0x28, 0xf3, 0xe9, 0xa4, 0x4e, 0xcf, 0xd4, 0x7b, + 0xa8, 0x42, 0x0a, 0x28, 0x6f, 0x1e, 0xf3, 0x72, 0xfd, 0x29, 0xb3, 0x65, + 0xdf, 0x9b, 0x82, 0xf1 +}; +/* QIUTx = 00202694f378d70965d42828ad5f37137bf8b63cec2c0d158e5ba94cab1f8e61e5a300986ba349b3adf3efc05e65670af88cd3d6 */ +/* QIUTy = 00baf0da4aedb972f88a215dfbff64e4290fadc25da3f0d83f35e65bc4177d3025d71d8eeb9c41470f3c719e00ef1fb7552e6a89 */ +static const uint8_t nist_kas_ecc_cdh_testvector_223_out[] = { +/* ZIUT */ + 0x01, 0x40, 0xe7, 0xdb, 0x3f, 0x64, 0x15, 0xd8, 0x84, 0x82, 0x2c, 0xcc, + 0x73, 0x16, 0xa3, 0x29, 0xdf, 0xed, 0x17, 0x7b, 0x76, 0xc0, 0x11, 0x7a, + 0xbd, 0x72, 0x2f, 0xec, 0xa8, 0x89, 0xbe, 0xe4, 0xe1, 0x4e, 0x65, 0xd2, + 0x6c, 0x6c, 0xc9, 0x35, 0xc0, 0xe9, 0x42, 0x05, 0xf0, 0x5f, 0xc1, 0xa7, + 0xab, 0xfb, 0x03, 0x48 +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_224_public_x[] = { +/* QCAVSx */ + 0x00, 0xab, 0xa9, 0x3a, 0xe1, 0xd1, 0x55, 0x28, 0x80, 0xb3, 0x1f, 0x50, + 0x3f, 0xc4, 0xbe, 0x9f, 0x91, 0xd1, 0x02, 0x47, 0xf1, 0x4c, 0x81, 0x60, + 0x15, 0xff, 0xb2, 0xba, 0xd2, 0x9a, 0xb8, 0x18, 0x0e, 0x7b, 0x50, 0xa2, + 0x71, 0x44, 0xe0, 0x1c, 0x21, 0xe6, 0x3c, 0x3d, 0xaf, 0xcd, 0x25, 0x13, + 0x08, 0xba, 0xc7, 0x68 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_224_public_y[] = { +/* QCAVSy */ + 0x00, 0xe4, 0xab, 0x66, 0xe5, 0x14, 0xbd, 0x02, 0xab, 0xea, 0xe1, 0xc7, + 0x12, 0x37, 0x88, 0xa6, 0x92, 0x58, 0x4d, 0xdb, 0x4a, 0x90, 0x9a, 0x21, + 0x7f, 0xb3, 0x5d, 0xe6, 0x65, 0x88, 0x23, 0x3d, 0xad, 0xef, 0x70, 0x36, + 0xff, 0x9d, 0x9f, 0x24, 0xeb, 0xa3, 0x77, 0x2e, 0x2f, 0xa3, 0x03, 0x7b, + 0xba, 0xe6, 0x3c, 0xfe +}; +static const uint8_t nist_kas_ecc_cdh_testvector_224_private[] = { +/* dIUT */ + 0x00, 0x56, 0xd7, 0x37, 0x30, 0x75, 0x3a, 0xda, 0x70, 0xfd, 0x80, 0x1c, + 0x74, 0x9c, 0x2f, 0x1f, 0x1a, 0x61, 0xef, 0x5b, 0xd6, 0xec, 0xb7, 0x96, + 0xa9, 0xe1, 0x5e, 0xfe, 0x9b, 0xbe, 0x61, 0x58, 0xf6, 0x69, 0x54, 0x27, + 0x87, 0x35, 0x0f, 0x4d, 0x64, 0x3b, 0xda, 0x6f, 0x3e, 0x8c, 0x64, 0x23, + 0xb8, 0x17, 0xb5, 0x30 +}; +/* QIUTx = 0025a06b71a0ae252f2f905221983ebfce21ad96121a5c0dcc5ef0d0fec301ec77ef4b915818fedcda7f3fd733c7f9e529079cb6 */ +/* QIUTy = 00026890d5303b619c7f81f60fb82b26b0b98d8f24c45cab41a44eeb3a3a312944e889b4035e04360b305043e30d0cb9041a89de */ +static const uint8_t nist_kas_ecc_cdh_testvector_224_out[] = { +/* ZIUT */ + 0x00, 0x2e, 0xc4, 0xde, 0xac, 0x3e, 0x83, 0xd6, 0x0a, 0xd3, 0x99, 0x69, + 0xf2, 0xf9, 0x3b, 0x49, 0xf3, 0x18, 0x75, 0x83, 0x1e, 0xcd, 0x51, 0xea, + 0x5c, 0x37, 0xca, 0x48, 0xde, 0x08, 0x1c, 0x0c, 0x8c, 0xc6, 0x60, 0xed, + 0xc5, 0x3a, 0x22, 0x2f, 0x30, 0x43, 0x44, 0x7f, 0x9c, 0xb7, 0x52, 0x76, + 0x3b, 0xe7, 0x49, 0x4a +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_225_public_x[] = { +/* QCAVSx */ + 0x00, 0xaa, 0x4e, 0xb8, 0x98, 0x44, 0x3c, 0xce, 0x3e, 0xd2, 0xc0, 0x72, + 0xd8, 0x58, 0x77, 0x5a, 0xc2, 0x21, 0xc2, 0x4e, 0x33, 0xec, 0xa6, 0xf3, + 0x15, 0x79, 0x66, 0x35, 0x44, 0xbb, 0x33, 0xa4, 0xa0, 0x68, 0xa8, 0x6d, + 0x13, 0xf1, 0x67, 0xb6, 0x53, 0x04, 0xc5, 0xf7, 0xf2, 0x5f, 0x89, 0x5f, + 0x65, 0xb2, 0xf4, 0x28 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_225_public_y[] = { +/* QCAVSy */ + 0x00, 0x83, 0xcd, 0xed, 0x30, 0x21, 0x1b, 0x66, 0xf1, 0xad, 0xf1, 0x73, + 0x18, 0xb6, 0xde, 0x50, 0xd7, 0x72, 0x4c, 0x05, 0x84, 0x99, 0x5e, 0x06, + 0x8b, 0x72, 0x47, 0x03, 0xae, 0x08, 0xed, 0x71, 0xa3, 0x2b, 0x33, 0x49, + 0x87, 0xa7, 0xb3, 0x1d, 0x6c, 0x26, 0x37, 0x15, 0x29, 0x17, 0x32, 0x7d, + 0x37, 0xac, 0xcd, 0x33 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_225_private[] = { +/* dIUT */ + 0x00, 0x62, 0xb0, 0x26, 0xd4, 0x97, 0x20, 0x66, 0x0c, 0xf6, 0xa4, 0xf5, + 0x69, 0xbe, 0x98, 0xdf, 0xa1, 0x08, 0xc8, 0xeb, 0xa0, 0x82, 0x34, 0xae, + 0x9a, 0x87, 0xf3, 0xc8, 0x8b, 0x6c, 0x65, 0x93, 0x4b, 0x99, 0x68, 0x15, + 0x32, 0x2a, 0x16, 0xf9, 0xaa, 0xbe, 0xd1, 0x33, 0x17, 0xbf, 0x77, 0x25, + 0xbe, 0xa5, 0x80, 0x8e +}; +/* QIUTx = 000f52925394cb52bc330e06390c0c0a2e10ed9797149fbcc88d80fbcaec173e24a05daef98401d5e47f3b765bedbb8246312856 */ +/* QIUTy = 013d99c1710805d5fc7db7259ac9e134b411d00d73fb0762e3d211cdc56bf7f714512d04a630c8732551ee734287476cf511e836 */ +static const uint8_t nist_kas_ecc_cdh_testvector_225_out[] = { +/* ZIUT */ + 0x01, 0xc9, 0xcc, 0x05, 0xd1, 0x9f, 0x96, 0xc4, 0xd2, 0x33, 0x03, 0x9c, + 0xfb, 0xc4, 0x3a, 0xb6, 0x8d, 0x65, 0x7b, 0xb5, 0x07, 0xf4, 0x6a, 0x35, + 0x30, 0x91, 0xfe, 0x98, 0xfc, 0x0f, 0x42, 0x2a, 0x8e, 0x75, 0x93, 0xc1, + 0x95, 0xd3, 0x26, 0x97, 0x7a, 0x2b, 0xe6, 0xbb, 0xd2, 0xcb, 0x44, 0xeb, + 0x1f, 0xe8, 0x16, 0x50 +}; +/* [K-571] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_226_public_x[] = { +/* QCAVSx */ + 0x03, 0x10, 0x6a, 0x5c, 0x1d, 0x92, 0x3a, 0x09, 0x90, 0xea, 0x8c, 0x60, + 0x08, 0xc3, 0x6c, 0x36, 0x6b, 0x53, 0xe5, 0x62, 0x2b, 0x98, 0x46, 0x40, + 0x44, 0x74, 0x1f, 0xbc, 0x78, 0x40, 0x28, 0x4d, 0xb8, 0xbb, 0xf6, 0x02, + 0x86, 0x6c, 0x30, 0xcc, 0xbf, 0x5f, 0x9b, 0x7e, 0x59, 0xcc, 0x1d, 0x9b, + 0xfc, 0xc5, 0xb9, 0x70, 0xfa, 0x62, 0x4d, 0xa9, 0xb1, 0x5f, 0x6c, 0xb3, + 0x36, 0xf5, 0xdd, 0xa7, 0xe6, 0xb9, 0x92, 0x4d, 0x5d, 0xce, 0x45, 0x43 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_226_public_y[] = { +/* QCAVSy */ + 0x00, 0x5c, 0x5c, 0x7b, 0xbd, 0x5a, 0x78, 0x9a, 0xc4, 0xc6, 0x28, 0x3d, + 0xeb, 0x0d, 0x0d, 0x37, 0xc4, 0x85, 0x2b, 0xaa, 0x57, 0xd6, 0xbc, 0x2b, + 0x0a, 0xc6, 0x33, 0x7f, 0xeb, 0x09, 0x70, 0x4c, 0x44, 0xd1, 0xb3, 0x85, + 0xb7, 0x0c, 0xc3, 0x94, 0xfa, 0x23, 0x5d, 0x83, 0xe6, 0xe7, 0x11, 0x17, + 0x87, 0xe5, 0x7d, 0x09, 0x02, 0xc0, 0xcb, 0x13, 0x2a, 0x19, 0x0a, 0x6e, + 0x62, 0xf3, 0x98, 0x51, 0x1c, 0x0c, 0x2c, 0x4c, 0xd5, 0x0d, 0x45, 0x70 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_226_private[] = { +/* dIUT */ + 0x01, 0x73, 0xcd, 0x16, 0x31, 0xe1, 0x8e, 0xce, 0x01, 0xb7, 0x3b, 0x35, + 0x72, 0xff, 0xaa, 0x74, 0x95, 0xc4, 0xbc, 0x81, 0xf4, 0x07, 0x8a, 0xe5, + 0x0d, 0x69, 0xcb, 0x1e, 0x33, 0x8a, 0xcf, 0x13, 0x46, 0x91, 0x17, 0x11, + 0x29, 0x21, 0x16, 0x6d, 0xdf, 0x2d, 0x29, 0xf3, 0xa9, 0xf8, 0xe1, 0x0c, + 0x67, 0xe8, 0x8c, 0x9a, 0x99, 0x20, 0x3a, 0x83, 0x45, 0x65, 0xbe, 0x76, + 0xac, 0x59, 0x12, 0x64, 0x36, 0x73, 0x9a, 0x6a, 0xfa, 0x02, 0x9c, 0xc5 +}; +/* QIUTx = 03fbfbbcfba609157f68a23126d805f7c75efb19befb595e3a975e08ff46bd34c8b87b9645c0e86ea0ad915465d5c856c69bb9b722b0d17bf97ad95c4602dea17c6b512054cb22d8 */ +/* QIUTy = 071c16df71e1b71b4bd3d9938827d3959093b9db1ff86bed73944a42dcb67cc33102e28c1d0e9804a6450656f4bf33ad72ecf7bb83bd282cde4bc15d4e48064aa8ad2f02979f5f3f */ +static const uint8_t nist_kas_ecc_cdh_testvector_226_out[] = { +/* ZIUT */ + 0x00, 0x31, 0x98, 0xa6, 0xb5, 0xd6, 0xcc, 0xe8, 0x47, 0xe2, 0x43, 0x48, + 0xa6, 0xa6, 0xce, 0xff, 0x7a, 0x89, 0xed, 0x37, 0x94, 0xd7, 0xac, 0xed, + 0xc4, 0xe8, 0x58, 0xc8, 0x0a, 0xd0, 0x4a, 0x74, 0xdb, 0xc0, 0x2c, 0x70, + 0x38, 0xe0, 0x5a, 0xb2, 0x6b, 0x2a, 0x29, 0x9e, 0xc9, 0x2e, 0xe0, 0xd2, + 0xc7, 0xe6, 0x6a, 0x81, 0x87, 0x2a, 0x51, 0x57, 0xfb, 0xc5, 0xd4, 0xd3, + 0x7a, 0xd5, 0x98, 0xd6, 0xdd, 0xee, 0x99, 0x5e, 0xd2, 0x8a, 0x2d, 0x74 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_227_public_x[] = { +/* QCAVSx */ + 0x02, 0x11, 0x22, 0x3c, 0x4b, 0x72, 0x9b, 0x20, 0x6b, 0xe0, 0x1f, 0x80, + 0x85, 0xa9, 0x97, 0xe1, 0xdd, 0xe5, 0xcd, 0xb2, 0x7c, 0x04, 0x89, 0x25, + 0xa2, 0x73, 0x69, 0xbc, 0xca, 0x6a, 0x3e, 0x2f, 0xbf, 0xc6, 0x56, 0x37, + 0xf1, 0xec, 0xeb, 0x13, 0x3b, 0xe7, 0x49, 0x67, 0x9a, 0x17, 0xb1, 0xce, + 0x58, 0x82, 0x1f, 0x46, 0xbd, 0x18, 0x44, 0xa8, 0x9c, 0xf0, 0x04, 0x2c, + 0x80, 0x43, 0xcb, 0x10, 0x5e, 0x01, 0xa3, 0xfc, 0x94, 0x8d, 0x26, 0x63 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_227_public_y[] = { +/* QCAVSy */ + 0x02, 0xb1, 0xec, 0x2e, 0x6e, 0x2c, 0x23, 0x75, 0xb4, 0x64, 0xb0, 0xa5, + 0x02, 0xc5, 0x05, 0x3b, 0x5b, 0x34, 0x8b, 0xd0, 0x81, 0x78, 0xc7, 0x2c, + 0x60, 0x31, 0x05, 0xd0, 0x46, 0x81, 0x96, 0xa4, 0x69, 0x5d, 0xc2, 0x67, + 0xd6, 0xe1, 0x09, 0xf1, 0xb1, 0x27, 0x44, 0x53, 0xb6, 0xef, 0xf1, 0x4d, + 0xdf, 0x37, 0x83, 0x96, 0x9e, 0x88, 0x25, 0x64, 0x8d, 0xeb, 0xc2, 0x16, + 0xaf, 0xff, 0x92, 0x58, 0xf6, 0x44, 0xd7, 0x7e, 0xcd, 0x99, 0x11, 0xcf +}; +static const uint8_t nist_kas_ecc_cdh_testvector_227_private[] = { +/* dIUT */ + 0x00, 0x93, 0x7e, 0xdb, 0x3a, 0xa2, 0x95, 0x63, 0xd2, 0x24, 0x85, 0x91, + 0xc9, 0xfb, 0x44, 0x89, 0x85, 0x09, 0x5f, 0x91, 0x3a, 0x74, 0x58, 0x31, + 0x55, 0x93, 0xcf, 0xce, 0x87, 0xe6, 0x8f, 0xb0, 0xf1, 0xa5, 0x25, 0xb7, + 0x31, 0x0a, 0x10, 0x11, 0x76, 0xe3, 0x4d, 0x45, 0xc1, 0x00, 0x45, 0x38, + 0x95, 0x4e, 0x20, 0x44, 0x54, 0x38, 0x17, 0xca, 0xb0, 0xd5, 0x63, 0xdf, + 0x6c, 0xb0, 0xd5, 0xe8, 0x61, 0x7b, 0xbb, 0xa1, 0x50, 0xe7, 0x55, 0xe1 +}; +/* QIUTx = 02363cc5624b06df1956befa597d4c757cc2b1001a3e1544d24408290f694877455ba92e56088462f0ffacbd393cf835b56b7046a15d4b724dc6c3573cb156c0df298aa8b1255cb8 */ +/* QIUTy = 0409f773b98d5edc2734d835953281b82ac0e15d902d887a7c6ba75629a37671b101d18ddfdc4193d98b18551414c49173004530f7976d27c273a73ddbb898fcb5fade9c0bb7883f */ +static const uint8_t nist_kas_ecc_cdh_testvector_227_out[] = { +/* ZIUT */ + 0x00, 0x57, 0x71, 0x47, 0x45, 0x92, 0x62, 0xe5, 0xad, 0x42, 0xf2, 0x22, + 0x82, 0x7f, 0x20, 0xed, 0x57, 0x4b, 0x21, 0x18, 0x92, 0x42, 0x05, 0xbc, + 0xdb, 0xd3, 0x39, 0xce, 0x20, 0xcf, 0xb0, 0x85, 0xd0, 0x72, 0xfd, 0x70, + 0xf4, 0xca, 0x1f, 0x57, 0x68, 0xfa, 0xfa, 0xeb, 0x57, 0x10, 0xf7, 0xcc, + 0xbe, 0xa4, 0xfc, 0x2a, 0xe5, 0x37, 0x7b, 0x0c, 0xff, 0x20, 0xa8, 0x89, + 0xa2, 0x20, 0x17, 0x39, 0x13, 0x9b, 0xf7, 0x88, 0xa9, 0xbf, 0x2d, 0x7d +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_228_public_x[] = { +/* QCAVSx */ + 0x00, 0x4d, 0x48, 0xbe, 0x59, 0x9e, 0xbb, 0x1e, 0xd6, 0x02, 0x47, 0x2d, + 0x7a, 0x87, 0xf4, 0xcd, 0x20, 0x80, 0xf4, 0x4e, 0xc2, 0x88, 0x55, 0xfe, + 0xcc, 0x3a, 0x9c, 0xdd, 0xe2, 0x55, 0x51, 0x78, 0x7a, 0xbd, 0x27, 0xcc, + 0x1d, 0xa7, 0xe7, 0x78, 0x17, 0xe9, 0x4c, 0x9c, 0x02, 0x89, 0xc0, 0x05, + 0xa0, 0xe3, 0x6e, 0x3b, 0xcf, 0xb0, 0xd3, 0x81, 0xe8, 0xcc, 0x96, 0x84, + 0xb6, 0xf7, 0xdd, 0x05, 0x17, 0x7f, 0x16, 0xf6, 0x3f, 0x87, 0x21, 0xca +}; +static const uint8_t nist_kas_ecc_cdh_testvector_228_public_y[] = { +/* QCAVSy */ + 0x06, 0x2c, 0xf7, 0x1a, 0xf0, 0xa2, 0xf8, 0xe3, 0x5c, 0x4d, 0x7f, 0x93, + 0x12, 0xbd, 0x34, 0xa8, 0x46, 0xa3, 0x80, 0xf6, 0x3f, 0x0d, 0xc7, 0x29, + 0x4c, 0x18, 0x87, 0x71, 0x03, 0x35, 0x7e, 0x20, 0xd1, 0xf0, 0xee, 0xff, + 0x31, 0x2a, 0x99, 0x3d, 0xeb, 0x2a, 0x1e, 0xcf, 0xc8, 0x0a, 0xea, 0x06, + 0xa5, 0xb7, 0x1e, 0x4f, 0x8b, 0x9c, 0xef, 0xae, 0xbc, 0xd3, 0x26, 0x26, + 0x91, 0x90, 0x64, 0xf8, 0x8a, 0xf4, 0x16, 0xd8, 0x6e, 0x3e, 0x7a, 0xf3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_228_private[] = { +/* dIUT */ + 0x00, 0x34, 0x09, 0x9b, 0x07, 0x73, 0xf0, 0x21, 0xee, 0x0d, 0x3d, 0xd1, + 0x85, 0xc7, 0x04, 0xb5, 0x15, 0x8a, 0x94, 0x32, 0x8d, 0xaa, 0x09, 0x76, + 0x8f, 0xad, 0x58, 0x04, 0xdf, 0x1d, 0xa2, 0xfc, 0x06, 0x71, 0x90, 0xcf, + 0x10, 0x28, 0xc3, 0x02, 0x37, 0xbf, 0x2a, 0x48, 0xda, 0x13, 0xab, 0xae, + 0x35, 0xa2, 0x5c, 0x3e, 0x63, 0x87, 0xd3, 0x99, 0x3f, 0x9b, 0x56, 0x83, + 0x05, 0xb8, 0xbf, 0x08, 0x18, 0xff, 0x52, 0x7d, 0xd8, 0x20, 0x5d, 0xf4 +}; +/* QIUTx = 0674dcc4f755c44fdabdc078488107bb64a460ba932c7e185484ccd27fa870031107e9955204b0630b9b4d3608d9aa931d7c766cc2e45878eb6d8cd96bdf711b2fe8b47b8d233ed5 */ +/* QIUTy = 05d96be6b7e2ba74c8032af19ca2f2b39d2fd4e8c89b156b6b25c2ea4f71f74a02ca7da2a463acd7605d5350fd16a9c9052534e7e81d648e4060a2b01c459c260cb6567da1fc5314 */ +static const uint8_t nist_kas_ecc_cdh_testvector_228_out[] = { +/* ZIUT */ + 0x01, 0x46, 0x62, 0xb2, 0x61, 0xd0, 0xbc, 0x21, 0x68, 0x64, 0x2b, 0xfa, + 0x4f, 0x80, 0xc4, 0xb3, 0xfe, 0x81, 0x76, 0xf6, 0x04, 0xad, 0x37, 0x03, + 0xf4, 0x43, 0xec, 0x7a, 0xaa, 0x3d, 0xcf, 0x3c, 0x54, 0x65, 0xb8, 0x69, + 0xa8, 0xfc, 0xea, 0x60, 0xb8, 0xf5, 0x5c, 0xe7, 0x11, 0x88, 0x06, 0xc5, + 0xd2, 0x8a, 0x04, 0x84, 0x8b, 0xd9, 0x61, 0xdb, 0x00, 0x61, 0x20, 0x9b, + 0x59, 0xbc, 0x02, 0x97, 0x9a, 0xcc, 0xe9, 0x32, 0x4d, 0x7c, 0x0c, 0x31 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_229_public_x[] = { +/* QCAVSx */ + 0x06, 0xbf, 0x25, 0x2e, 0x62, 0xc9, 0x96, 0x91, 0x71, 0xa9, 0x71, 0x76, + 0x71, 0xda, 0x0f, 0x70, 0x32, 0xe9, 0x52, 0x0a, 0x49, 0x7e, 0xc8, 0x31, + 0xf4, 0xdc, 0x77, 0x6a, 0xc8, 0x7e, 0x01, 0x94, 0xaf, 0x99, 0x54, 0x6c, + 0x41, 0xd0, 0x80, 0x48, 0xea, 0x06, 0xda, 0x92, 0x35, 0xcf, 0x13, 0x69, + 0xc3, 0xea, 0x53, 0xe6, 0xb8, 0xcb, 0xb7, 0xa7, 0xfd, 0x42, 0x96, 0x35, + 0x45, 0x48, 0xd4, 0x4e, 0xdf, 0x46, 0x3f, 0x77, 0xad, 0x34, 0x1b, 0x02 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_229_public_y[] = { +/* QCAVSy */ + 0x02, 0x94, 0xd5, 0xf7, 0xe7, 0x36, 0xdc, 0xd8, 0x99, 0x01, 0x98, 0xe4, + 0xe0, 0xf0, 0xb3, 0x98, 0xb8, 0xac, 0x6a, 0x87, 0x76, 0x4a, 0xf6, 0x01, + 0x59, 0x62, 0x34, 0xa2, 0xe1, 0x62, 0xc9, 0xc6, 0x67, 0xe4, 0x7e, 0xb3, + 0xd9, 0x87, 0xef, 0xba, 0xeb, 0x03, 0xb5, 0xe3, 0x69, 0x9a, 0x38, 0xef, + 0x95, 0x3c, 0x74, 0xfb, 0x28, 0xfd, 0x7d, 0x8a, 0x4e, 0xc5, 0xa3, 0x63, + 0x19, 0xcc, 0xc4, 0x4a, 0x19, 0xaa, 0x88, 0x20, 0x1d, 0xda, 0xcb, 0xf8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_229_private[] = { +/* dIUT */ + 0x00, 0x15, 0x47, 0x43, 0x8d, 0xf7, 0x6f, 0xcb, 0x5e, 0x2a, 0xe6, 0x92, + 0x58, 0x45, 0xbb, 0xfb, 0x03, 0xb4, 0xfb, 0xe8, 0x25, 0x56, 0x16, 0xec, + 0x7f, 0xbd, 0x97, 0xb4, 0x8f, 0x11, 0x26, 0x92, 0x21, 0x9f, 0x4f, 0x12, + 0x75, 0xe6, 0xd2, 0x45, 0x3d, 0x5b, 0xcf, 0x3b, 0xac, 0x41, 0x06, 0xf0, + 0x16, 0x1b, 0x81, 0x19, 0xf4, 0x87, 0xd8, 0x8b, 0x5f, 0x8c, 0x8e, 0x08, + 0xb3, 0xaa, 0x17, 0xb8, 0x3f, 0xe0, 0x11, 0x02, 0xd7, 0x63, 0x92, 0xd3 +}; +/* QIUTx = 0427e2dc11ee5223bd9c3d9418c79114682f91dda06e7d88c339a7e56e0dfb636b6e63fde8a381146ecb705ca202d2b73df408451763c5166066a97ff4e4f32f0b4cc942344b0b2d */ +/* QIUTy = 0760c8a388e2eea27ef6838c7d45052e38cbee2096cbe89f774774134076658df90c62c7dc0e3fde995d7a99090993009ab6c535677dbdb376f183eb5092d2cb6a8837b6bea35dcd */ +static const uint8_t nist_kas_ecc_cdh_testvector_229_out[] = { +/* ZIUT */ + 0x05, 0x1e, 0xc4, 0xdb, 0x06, 0x22, 0xb7, 0xb1, 0xc7, 0x98, 0x36, 0x64, + 0x53, 0xc7, 0x0f, 0x95, 0x93, 0x76, 0xea, 0x39, 0x42, 0xae, 0xd2, 0xe9, + 0x31, 0xff, 0x62, 0xa4, 0x01, 0x9e, 0xb1, 0x2b, 0xa5, 0xff, 0x11, 0x92, + 0x14, 0xc8, 0xbf, 0xd8, 0xbd, 0xb6, 0x6e, 0x62, 0xb5, 0x62, 0x40, 0x0f, + 0x2d, 0x3d, 0x48, 0xa8, 0x4b, 0x1b, 0x3b, 0xaa, 0xd3, 0x66, 0x7f, 0x73, + 0x5a, 0xd4, 0xd0, 0xf1, 0x83, 0xbd, 0xb9, 0x1a, 0xae, 0xdc, 0xf1, 0xf1 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_230_public_x[] = { +/* QCAVSx */ + 0x05, 0x70, 0x1e, 0x63, 0xb0, 0x1c, 0x16, 0xc4, 0xeb, 0x19, 0x93, 0x82, + 0x65, 0xba, 0x13, 0x4c, 0xac, 0x73, 0x16, 0x27, 0x8e, 0x2f, 0x1e, 0xb4, + 0x0a, 0x04, 0x77, 0x54, 0x48, 0xbd, 0xed, 0x97, 0xe7, 0xa3, 0x7d, 0x01, + 0xfe, 0xd8, 0xa4, 0xe0, 0xb4, 0x3f, 0xf4, 0xdb, 0xa2, 0x1a, 0x47, 0x75, + 0x9c, 0xcd, 0x45, 0xbf, 0x96, 0x71, 0xdd, 0x22, 0xee, 0xc6, 0x5b, 0x4a, + 0xff, 0x8b, 0x8d, 0xb8, 0x9d, 0xfe, 0x3e, 0x49, 0x0c, 0x0a, 0xc9, 0xd6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_230_public_y[] = { +/* QCAVSy */ + 0x02, 0xdd, 0x97, 0xb6, 0x41, 0x5a, 0xee, 0x2b, 0x01, 0xcf, 0xeb, 0x3c, + 0xd2, 0xa0, 0x35, 0x78, 0xab, 0xfe, 0xd9, 0xca, 0x87, 0xbe, 0x9a, 0x26, + 0xd8, 0x99, 0x59, 0x5a, 0x87, 0xbc, 0xbd, 0x97, 0x27, 0x48, 0xfa, 0x6a, + 0x0b, 0xe4, 0xeb, 0x55, 0x7e, 0x69, 0xc6, 0xd2, 0x8e, 0x2b, 0xba, 0x15, + 0x80, 0xdc, 0x74, 0xe2, 0x75, 0x1d, 0x7c, 0xcd, 0x91, 0x8c, 0x46, 0xb4, + 0xbe, 0x68, 0x75, 0xa4, 0xe4, 0xc2, 0x90, 0xd9, 0x59, 0xc2, 0x3c, 0x12 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_230_private[] = { +/* dIUT */ + 0x00, 0xc7, 0xb4, 0x25, 0x2c, 0xa9, 0xb1, 0x92, 0xc5, 0xfe, 0xaa, 0x9a, + 0x21, 0x0f, 0xd8, 0x4e, 0x2e, 0x48, 0x32, 0x02, 0x71, 0xf1, 0x0f, 0x67, + 0xea, 0x9e, 0xb3, 0x0b, 0x0d, 0xe8, 0x08, 0x6d, 0x59, 0xda, 0xe0, 0x42, + 0x59, 0xfd, 0x12, 0xb0, 0x86, 0xd8, 0x90, 0xe2, 0x2d, 0x45, 0xd2, 0x7d, + 0x7c, 0x84, 0x55, 0xdc, 0xf7, 0xad, 0xa7, 0x96, 0xe3, 0x5e, 0x3a, 0x31, + 0x38, 0x34, 0x2c, 0xc7, 0x36, 0xbc, 0x3e, 0xd3, 0x78, 0x1c, 0x41, 0x19 +}; +/* QIUTx = 0325623838e8b18d81b68060734254eb02b8ebb2264556fc9850c36d3035449aa764f351dbaf7bbca9b9adb11f27cc88a1ac6fb71aa10ef8d0d09392b0ca7eaa7a5cc14078cc18bb */ +/* QIUTy = 0098fc7656d9de3a51923dba290ecbe413ef8d951f24e9248cb552309f97127fb9429ecf6dd07b6de894e16ab60e33b4ee73024ccbe866de5e17f1b478dc7727a1bb42371820b12d */ +static const uint8_t nist_kas_ecc_cdh_testvector_230_out[] = { +/* ZIUT */ + 0x05, 0xb3, 0x55, 0xeb, 0x5c, 0x47, 0xd8, 0x02, 0x7b, 0x6c, 0x53, 0x01, + 0xd2, 0x46, 0x3b, 0x99, 0xc6, 0x36, 0xdb, 0x20, 0x77, 0x92, 0xe2, 0x97, + 0x5a, 0xb1, 0xa5, 0x3c, 0x1c, 0xbb, 0x13, 0x12, 0x80, 0x28, 0x84, 0x32, + 0xa7, 0x9a, 0x3b, 0x47, 0x27, 0x1d, 0x6a, 0x2b, 0xd7, 0x77, 0x29, 0x8b, + 0xaf, 0x8a, 0x67, 0x5f, 0x66, 0xbe, 0x9d, 0xc7, 0x2c, 0x35, 0x88, 0xd2, + 0x99, 0xdf, 0x8b, 0x52, 0xe7, 0x84, 0x03, 0x22, 0xb4, 0x3c, 0x20, 0x71 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_231_public_x[] = { +/* QCAVSx */ + 0x03, 0x2f, 0xa1, 0x81, 0x6f, 0xd2, 0x31, 0x7c, 0x16, 0xb5, 0xb1, 0x9a, + 0x25, 0xd4, 0x6f, 0xa5, 0xe4, 0x5a, 0xb1, 0x5e, 0xe9, 0xf2, 0xb1, 0xd1, + 0x27, 0x4c, 0x2a, 0x06, 0x02, 0x39, 0x94, 0xdb, 0x30, 0x9f, 0xad, 0x56, + 0xf6, 0x0b, 0x3c, 0xe5, 0x7f, 0x32, 0xdf, 0xc7, 0xd0, 0x45, 0xa8, 0x4b, + 0x7d, 0x80, 0x52, 0x32, 0xbe, 0x34, 0xc7, 0xe7, 0x59, 0x51, 0x4c, 0x30, + 0xa2, 0x52, 0x07, 0xba, 0x80, 0x02, 0x15, 0xb2, 0x06, 0x0f, 0x04, 0xc2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_231_public_y[] = { +/* QCAVSy */ + 0x04, 0x14, 0x69, 0x59, 0x3d, 0x57, 0x48, 0x07, 0x2b, 0x9a, 0xc8, 0xfd, + 0xe0, 0x23, 0x09, 0x52, 0x89, 0xbc, 0xdf, 0x65, 0xab, 0x1b, 0xfc, 0x08, + 0x56, 0xf8, 0x3e, 0x9a, 0xe0, 0x6c, 0x89, 0x73, 0x03, 0xbd, 0x16, 0xf5, + 0xe4, 0x58, 0x23, 0xd6, 0x5f, 0xec, 0x83, 0x10, 0xfd, 0x43, 0x32, 0xb6, + 0x5c, 0xff, 0x47, 0xa7, 0x99, 0xaf, 0x4f, 0x7c, 0x86, 0x38, 0xe2, 0xd7, + 0xf8, 0x59, 0x48, 0xc4, 0x3f, 0x10, 0x53, 0x4c, 0x98, 0x0c, 0xcb, 0x62 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_231_private[] = { +/* dIUT */ + 0x00, 0x66, 0xcc, 0x51, 0x98, 0x0d, 0x38, 0x51, 0xb4, 0x88, 0xc2, 0xc1, + 0x81, 0x49, 0x6c, 0x83, 0x50, 0x5f, 0xb9, 0x57, 0xb1, 0xec, 0x4a, 0x84, + 0xdf, 0x1e, 0x10, 0x5e, 0x30, 0xd0, 0x02, 0xbc, 0xb9, 0x78, 0xb6, 0xd0, + 0xbd, 0xc3, 0xb7, 0x64, 0x4e, 0xd3, 0xdf, 0xbc, 0x33, 0xca, 0x6b, 0xfe, + 0x43, 0x62, 0xcd, 0x8c, 0xc5, 0x41, 0x74, 0x0b, 0x0d, 0xe8, 0xcf, 0x2e, + 0xdc, 0xce, 0x45, 0x92, 0xe3, 0x4f, 0xa1, 0x1a, 0xc2, 0x6e, 0xc9, 0x22 +}; +/* QIUTx = 0771fa29e5930d6dfd36d3a9e7159675fd23d0b5e1fd9ae6454aca9e8127f1e7e3f5322b5c16b095573b3266d08f0dc33043ffb3d7b08e4e052ed3f0349a329025ea6ff3e1668547 */ +/* QIUTy = 022f994f9974692dbb6e58cc7ae5f90652ee231e0a3961569dc646d114522a3777410c1b352d668079f80010bb540e4c28408665810fe61fd60e70d30c688eab8fde04364dee5c9b */ +static const uint8_t nist_kas_ecc_cdh_testvector_231_out[] = { +/* ZIUT */ + 0x05, 0x2b, 0xd7, 0x8b, 0xf1, 0x32, 0x6c, 0x6d, 0x91, 0x84, 0x0a, 0x35, + 0x1d, 0x48, 0x74, 0xd3, 0x6b, 0x14, 0x71, 0x39, 0x88, 0x23, 0x56, 0xc5, + 0x95, 0xb8, 0x60, 0x7f, 0x99, 0x98, 0x77, 0x30, 0x92, 0xa9, 0x9a, 0xdf, + 0x70, 0xad, 0xee, 0xd1, 0x9e, 0x12, 0x2d, 0x4d, 0x2f, 0xec, 0x16, 0x28, + 0x5f, 0x00, 0x01, 0x61, 0x14, 0x51, 0x35, 0xd9, 0x63, 0x55, 0xcb, 0xa0, + 0x39, 0xa9, 0x63, 0x35, 0xe7, 0x71, 0x67, 0x24, 0xc2, 0x49, 0xf8, 0x8b +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_232_public_x[] = { +/* QCAVSx */ + 0x03, 0xe6, 0x3d, 0xd4, 0xc9, 0x8c, 0x15, 0x13, 0x61, 0xc9, 0x90, 0x2b, + 0x76, 0x3a, 0xe3, 0x2f, 0x2d, 0x6d, 0xe7, 0x59, 0x53, 0xfa, 0x3d, 0x68, + 0x38, 0xc1, 0xd6, 0x13, 0xd4, 0x48, 0xfc, 0xa7, 0x3b, 0xf3, 0x02, 0xd3, + 0x02, 0x12, 0xa9, 0x6d, 0x32, 0xb9, 0x54, 0x9e, 0x17, 0xc5, 0xcf, 0x39, + 0x5c, 0x56, 0x51, 0x91, 0xf6, 0xa2, 0x2d, 0xac, 0x4d, 0xa7, 0xc1, 0xe1, + 0xa9, 0xd9, 0xba, 0xe8, 0x6e, 0xbf, 0xb7, 0x2c, 0x82, 0xea, 0x19, 0x9a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_232_public_y[] = { +/* QCAVSy */ + 0x04, 0x16, 0x09, 0xab, 0x9c, 0x12, 0xc1, 0x5e, 0x51, 0x27, 0x00, 0x5e, + 0xbe, 0xff, 0x6f, 0xd1, 0xf7, 0x3b, 0x69, 0x12, 0xed, 0x07, 0x0a, 0xf8, + 0x7f, 0x5f, 0xfc, 0x21, 0xdf, 0x90, 0x3d, 0xde, 0x1d, 0x71, 0x55, 0x82, + 0xdd, 0x2f, 0x69, 0x90, 0x40, 0x20, 0x00, 0x45, 0xcd, 0xba, 0x9e, 0xcd, + 0x75, 0x8a, 0xc4, 0xd0, 0x84, 0xd4, 0xc8, 0xd7, 0x82, 0x19, 0xf6, 0xfa, + 0xd9, 0x4d, 0x34, 0x1a, 0xd7, 0x7d, 0xac, 0xcd, 0xab, 0xb5, 0x4a, 0x2b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_232_private[] = { +/* dIUT */ + 0x01, 0x99, 0x0d, 0x15, 0xfa, 0x2c, 0xc9, 0x0e, 0x78, 0x3d, 0x43, 0x22, + 0x01, 0x78, 0x4b, 0xab, 0x56, 0xb6, 0xd2, 0x9d, 0x1f, 0x26, 0x65, 0xa7, + 0x6c, 0xd0, 0x13, 0xeb, 0x96, 0xf6, 0x30, 0x0e, 0xd8, 0xf7, 0x62, 0xb7, + 0x8a, 0x55, 0x96, 0xac, 0x7e, 0x8c, 0x1e, 0x76, 0x16, 0x7f, 0x10, 0x7c, + 0x20, 0x44, 0x3b, 0x1a, 0xc7, 0x32, 0x10, 0x1e, 0x9f, 0x0a, 0xca, 0x12, + 0x55, 0x1a, 0x53, 0x6d, 0x15, 0x2d, 0xf2, 0xb3, 0xdb, 0x0f, 0x20, 0xde +}; +/* QIUTx = 076c3d72f0e715f2491bc9d99278a8ef3c390b3a96e9997b37e5b7bd8a5f07af68f8e0ee3892b63ff112a73a849f0e84a782d4fb426eb5f2f15adacce9e5476a6daccf3a7fa9a291 */ +/* QIUTy = 0540a763823599e0c86027bacc8cbb30e3a2467276fc4f7e5fd4ed385dfc6f883fed7bca69df21a0668b55ebd292da8fd6356a3ec5cd1c762c01473aa067004cacedad564fe06910 */ +static const uint8_t nist_kas_ecc_cdh_testvector_232_out[] = { +/* ZIUT */ + 0x02, 0x26, 0xc2, 0x8e, 0x5a, 0x6b, 0xc7, 0x35, 0x93, 0x5f, 0x9d, 0xf2, + 0xc1, 0xb0, 0x2d, 0x09, 0x6d, 0x4d, 0xee, 0x41, 0xff, 0xb9, 0x5a, 0x67, + 0x90, 0x5a, 0xab, 0x8d, 0xe1, 0xb2, 0xd8, 0xc6, 0x6e, 0x2b, 0xb4, 0x71, + 0x29, 0x30, 0x91, 0x43, 0x8d, 0x3f, 0x05, 0xdf, 0x7e, 0x48, 0x00, 0x3e, + 0x58, 0xa9, 0x58, 0xb7, 0x2f, 0x83, 0x9f, 0x7f, 0x2e, 0x2c, 0x54, 0x28, + 0x7f, 0xa3, 0xca, 0xdc, 0xd4, 0x1a, 0x25, 0x42, 0xae, 0x4e, 0xc0, 0x3a +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_233_public_x[] = { +/* QCAVSx */ + 0x06, 0xf9, 0x1a, 0x7c, 0xe1, 0x1b, 0xa9, 0xbf, 0x2d, 0xe1, 0xfe, 0x07, + 0x0f, 0x9d, 0xc8, 0x43, 0xbb, 0x71, 0x7c, 0x30, 0x6d, 0x9c, 0x63, 0xb5, + 0x07, 0x8d, 0x2a, 0x11, 0x32, 0x3f, 0x20, 0xc9, 0xc0, 0xd7, 0xb7, 0x74, + 0x3d, 0x31, 0x1d, 0xda, 0xcd, 0xcf, 0x5d, 0xd0, 0x0f, 0x49, 0x8b, 0x19, + 0x96, 0x72, 0xc7, 0x8a, 0xe2, 0x5e, 0x68, 0x64, 0xd6, 0x2b, 0xdc, 0x16, + 0x93, 0x5d, 0x6f, 0xb8, 0xda, 0xd2, 0x08, 0x2d, 0x36, 0x76, 0xeb, 0xf3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_233_public_y[] = { +/* QCAVSy */ + 0x04, 0x59, 0x3c, 0x5b, 0xad, 0x12, 0xc3, 0xd6, 0x55, 0xc6, 0x61, 0x1c, + 0x7c, 0xa9, 0x71, 0x1f, 0x9e, 0x32, 0xa2, 0x8f, 0xee, 0x54, 0xb3, 0xb8, + 0x24, 0x39, 0x62, 0xa3, 0xc5, 0x5d, 0x41, 0xf2, 0xc1, 0x85, 0xe4, 0xc5, + 0x8b, 0x7a, 0x29, 0x98, 0xe9, 0x78, 0x02, 0x1b, 0x95, 0xb7, 0x24, 0x63, + 0x5d, 0xac, 0xcb, 0xd7, 0xfc, 0x30, 0xd2, 0x07, 0x20, 0x79, 0x7b, 0xc2, + 0x91, 0x36, 0x2c, 0x55, 0xb0, 0x24, 0xac, 0xb2, 0xbd, 0xcf, 0x3d, 0x59 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_233_private[] = { +/* dIUT */ + 0x00, 0x2b, 0x09, 0x37, 0xe7, 0x31, 0xf5, 0x9d, 0xdd, 0xdf, 0x0e, 0x94, + 0xfb, 0xa9, 0x2b, 0xb1, 0xa6, 0xce, 0xb8, 0x19, 0xe7, 0x65, 0x9b, 0xcf, + 0x6e, 0xdd, 0x4b, 0x4a, 0xf4, 0x9c, 0x2e, 0xf2, 0x5c, 0x5b, 0x60, 0x39, + 0x25, 0x6f, 0x92, 0x83, 0x63, 0xe1, 0x84, 0x04, 0xb1, 0x65, 0x3d, 0x39, + 0x98, 0x05, 0x4c, 0x2c, 0x25, 0xa3, 0xf8, 0x3a, 0x0c, 0x55, 0x48, 0xa1, + 0x39, 0xe3, 0xe6, 0xa1, 0x80, 0x75, 0x67, 0x46, 0xcd, 0x34, 0xee, 0x29 +}; +/* QIUTx = 0270c4c00de2709010c7cf047a0ce69b87f41dca48d35b71fba4b258886d73ae42defb8653951c1bd3eb4ce0e6175a946c67afa67753475c51fd525b0fd9f5a26dafca319faa5e15 */ +/* QIUTy = 06680bbdc281505f5d3fbe29744a999e07ff612576993f6f8be3113db1ee6cf23799867bbc80a140376a9b6327451f98bf8fd1db46f9d9cc05e88704d5712d4567e1df40d39e99ef */ +static const uint8_t nist_kas_ecc_cdh_testvector_233_out[] = { +/* ZIUT */ + 0x05, 0x1a, 0x3d, 0xeb, 0x05, 0x2d, 0x3e, 0x99, 0xbb, 0x6a, 0xb6, 0xc6, + 0xb2, 0x84, 0xdb, 0x2c, 0x99, 0x8e, 0x9b, 0xee, 0x54, 0x3e, 0x02, 0xe5, + 0x7f, 0x1b, 0x13, 0xfe, 0x9f, 0xaf, 0xbf, 0xe5, 0x3a, 0x89, 0x65, 0x8c, + 0x58, 0xeb, 0x94, 0x7d, 0xbd, 0x17, 0x8a, 0xea, 0x2f, 0x6c, 0xb2, 0x8e, + 0x30, 0x5c, 0x98, 0x67, 0xbd, 0x65, 0xbb, 0x26, 0xf7, 0x17, 0x93, 0xf9, + 0x0c, 0x98, 0x4c, 0xa1, 0x11, 0x13, 0xe1, 0xa8, 0xdb, 0xc8, 0xf7, 0xd1 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_234_public_x[] = { +/* QCAVSx */ + 0x05, 0xab, 0x2a, 0x7f, 0x10, 0xac, 0x89, 0xf9, 0x8c, 0x40, 0x95, 0x80, + 0xab, 0xc1, 0x1a, 0xd9, 0x0c, 0x93, 0x36, 0x0e, 0x6a, 0xb2, 0x82, 0x92, + 0x0b, 0x59, 0xd3, 0x16, 0xca, 0x9f, 0x2b, 0x23, 0xae, 0xb5, 0x08, 0x76, + 0xcb, 0x1b, 0xcb, 0xe8, 0xee, 0x9a, 0xe6, 0xb5, 0x53, 0x3f, 0xdc, 0xd1, + 0x1a, 0xd4, 0xf8, 0x6d, 0x89, 0x18, 0xd6, 0x63, 0x89, 0xda, 0x87, 0xc9, + 0x8b, 0xf1, 0xd6, 0x32, 0x3b, 0xd0, 0x94, 0x7d, 0x80, 0x99, 0x08, 0x3b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_234_public_y[] = { +/* QCAVSy */ + 0x06, 0x89, 0xe1, 0x94, 0x72, 0x76, 0x79, 0x1d, 0xcb, 0x95, 0x27, 0x18, + 0x3e, 0x32, 0xa0, 0x80, 0x72, 0xb7, 0xe0, 0x3d, 0xca, 0xd1, 0x75, 0xfe, + 0x3c, 0xfd, 0x7b, 0xee, 0xfc, 0x84, 0x8d, 0xce, 0xf4, 0x83, 0x38, 0x0c, + 0x60, 0x05, 0x41, 0x13, 0x85, 0xc7, 0x02, 0x7c, 0x9a, 0x52, 0xb6, 0x0a, + 0x6e, 0x53, 0x7a, 0x87, 0x53, 0x80, 0xd2, 0x5b, 0xc4, 0x7c, 0x7b, 0xf2, + 0x36, 0x4d, 0xd6, 0x8a, 0x66, 0xf2, 0x1d, 0x0f, 0x57, 0x86, 0x6a, 0x42 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_234_private[] = { +/* dIUT */ + 0x01, 0xcd, 0x41, 0xcf, 0xf7, 0x62, 0x40, 0x2a, 0x83, 0x4e, 0x7e, 0x0a, + 0xb9, 0x08, 0xfc, 0x54, 0x94, 0x0f, 0x69, 0x7b, 0x50, 0x02, 0x2a, 0x4d, + 0xfe, 0xd8, 0xcf, 0x0b, 0x13, 0xd7, 0xe0, 0xee, 0x52, 0x3f, 0xbf, 0x33, + 0xee, 0x96, 0x93, 0x89, 0x5f, 0x91, 0x8d, 0x94, 0xe1, 0x5b, 0x08, 0x46, + 0x55, 0xd6, 0x1b, 0x22, 0x94, 0xca, 0x51, 0xc4, 0x12, 0x3f, 0xe5, 0xe0, + 0x86, 0x8e, 0x9d, 0x0d, 0x1c, 0xac, 0x21, 0x38, 0xf0, 0x57, 0x7a, 0x17 +}; +/* QIUTx = 0610797bbc6d9131180ae54ab66e6780849258369741470e076cf05e0785bb4e7900b908d38d8dab3b9427b952add20efb758cff80aeb641c4dde1eeda5509f386d5658559609cef */ +/* QIUTy = 068d2515f425a0e3037547342f1b6ff931763f5052e536ea4f78377b5c941459c8c2201482afcf3cda7390e9e5d319451864ca03683541ab2cd77a9d88fd7a610ca845ee5cd3d498 */ +static const uint8_t nist_kas_ecc_cdh_testvector_234_out[] = { +/* ZIUT */ + 0x00, 0x69, 0x7c, 0x75, 0x1d, 0xdb, 0xca, 0x70, 0x34, 0xfb, 0x4d, 0x3f, + 0xc1, 0xb2, 0x61, 0x8d, 0xaf, 0x78, 0xcd, 0xae, 0x46, 0x4e, 0x83, 0x32, + 0xd1, 0x21, 0x50, 0x20, 0xc8, 0xf8, 0x96, 0xf4, 0x86, 0x4c, 0x7a, 0x6f, + 0x2c, 0x61, 0xa3, 0x63, 0xf7, 0x30, 0xf5, 0x8f, 0xd3, 0xbd, 0xb4, 0xf7, + 0x8a, 0x90, 0xb4, 0x0a, 0xeb, 0x83, 0xb4, 0xfb, 0xc1, 0xd8, 0xd3, 0x7c, + 0xf6, 0xa2, 0x7a, 0x6f, 0x72, 0x2c, 0x68, 0xa8, 0x29, 0x79, 0xfa, 0x16 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_235_public_x[] = { +/* QCAVSx */ + 0x00, 0x34, 0x09, 0x1c, 0x3a, 0xc6, 0xfc, 0x52, 0x99, 0xdf, 0x18, 0xf1, + 0x62, 0xea, 0xf7, 0xa2, 0x07, 0xfc, 0x15, 0x43, 0xaa, 0x49, 0x8e, 0x72, + 0x72, 0xe1, 0x5a, 0x92, 0x77, 0x2f, 0x57, 0x77, 0x22, 0x29, 0x06, 0x94, + 0x56, 0xe2, 0x19, 0xc9, 0xc2, 0x87, 0x2b, 0xd5, 0x37, 0x83, 0xb0, 0xfb, + 0x13, 0x45, 0xf5, 0xe8, 0x46, 0x74, 0xc4, 0x34, 0x41, 0x29, 0xa3, 0x14, + 0x14, 0x6b, 0x70, 0x30, 0xfc, 0x75, 0x19, 0x7a, 0x20, 0xc5, 0x88, 0xaa +}; +static const uint8_t nist_kas_ecc_cdh_testvector_235_public_y[] = { +/* QCAVSy */ + 0x04, 0x9e, 0x3a, 0x3f, 0x5e, 0xe6, 0x58, 0x75, 0xe1, 0x40, 0x10, 0x89, + 0x97, 0x06, 0x38, 0xb8, 0x07, 0xdf, 0x97, 0x56, 0x8a, 0x59, 0x95, 0xc8, + 0xfe, 0x2f, 0x50, 0x24, 0x73, 0xb8, 0x3f, 0x58, 0xc5, 0x56, 0xc5, 0xf2, + 0x14, 0xed, 0x6f, 0x03, 0xef, 0x8e, 0xce, 0x01, 0x40, 0x1a, 0x21, 0x34, + 0xbc, 0x04, 0x1f, 0x66, 0x92, 0x2f, 0xcc, 0x4e, 0x39, 0x38, 0xe0, 0xc6, + 0xd3, 0x02, 0xeb, 0x42, 0x20, 0x06, 0x78, 0xa9, 0x71, 0x39, 0xf2, 0x91 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_235_private[] = { +/* dIUT */ + 0x01, 0x9d, 0xff, 0x0d, 0x72, 0xa8, 0xb0, 0x42, 0xc4, 0xe9, 0x2f, 0x1d, + 0xae, 0x74, 0x07, 0xbf, 0x4a, 0x10, 0x6c, 0xda, 0x56, 0x4d, 0xb7, 0x50, + 0x8e, 0x5a, 0x76, 0xb0, 0x31, 0x30, 0xc9, 0x1d, 0x5e, 0x5c, 0xbc, 0xf2, + 0xf5, 0x78, 0xc2, 0xe9, 0xde, 0xe4, 0x38, 0x49, 0xf9, 0x11, 0xd7, 0x77, + 0x3d, 0x4c, 0x26, 0x7e, 0x28, 0x2c, 0x27, 0x7b, 0x73, 0x1f, 0x88, 0xa6, + 0xef, 0x0e, 0xed, 0xdd, 0x52, 0x0f, 0x57, 0xe7, 0x43, 0xeb, 0xf9, 0x65 +}; +/* QIUTx = 05bb60a5fe8e3b173cf8413eaf413a3286a5a7aa378f21446c61057696012746d02d10a831f785c9c96561ffc6ad4f9ecdf4937fffd8e698408e660fe896f7ed44af6b3b42ea849f */ +/* QIUTy = 037e3a35e48aa66bd851c59f851d4a1ff334e0e589dac30986acd06d6eb8ce236f2a9688f278a14dcfe0660b5fa0e97ecfcebbf5b40d3d3f5150a5545acba6239c00419ac72dc2cc */ +static const uint8_t nist_kas_ecc_cdh_testvector_235_out[] = { +/* ZIUT */ + 0x03, 0x22, 0x51, 0x7d, 0xa3, 0x0e, 0x01, 0x0a, 0xea, 0xa2, 0xec, 0x9b, + 0xad, 0x27, 0x45, 0xd8, 0xe6, 0x7f, 0x90, 0x62, 0x94, 0xec, 0xd6, 0xb1, + 0xd1, 0x68, 0x08, 0xbe, 0x38, 0x37, 0xf7, 0x90, 0x70, 0xd0, 0xe1, 0xbb, + 0xbd, 0x61, 0x7f, 0x4b, 0x8b, 0x03, 0x1d, 0x3b, 0x51, 0xea, 0x2a, 0xcc, + 0x59, 0xde, 0x40, 0x8a, 0x13, 0x01, 0x38, 0xc7, 0x85, 0x71, 0xf8, 0x80, + 0x0f, 0xa9, 0x07, 0xca, 0xf5, 0x50, 0xd2, 0x33, 0x23, 0xd1, 0xc8, 0x18 +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_236_public_x[] = { +/* QCAVSx */ + 0x05, 0x7b, 0x7c, 0x65, 0xbc, 0x51, 0xe8, 0x7b, 0xda, 0xd3, 0x7c, 0x2b, + 0x4d, 0xae, 0x67, 0xfb, 0x00, 0x8c, 0xe7, 0x1f, 0xd3, 0x07, 0x2e, 0x41, + 0xb7, 0x7c, 0x56, 0x2d, 0x7c, 0x41, 0x74, 0x88, 0x72, 0xa2, 0x0b, 0xef, + 0x85, 0x17, 0xba, 0x4b, 0xe8, 0x96, 0x37, 0xdd, 0xe9, 0x8e, 0x2b, 0xa1, + 0xb3, 0xb0, 0x1f, 0x63, 0x94, 0x07, 0x13, 0xe2, 0x82, 0x3d, 0x8d, 0xab, + 0x68, 0xa5, 0xcc, 0x78, 0x56, 0x1d, 0xe1, 0x40, 0x85, 0xe4, 0xcf, 0x87 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_236_public_y[] = { +/* QCAVSy */ + 0x00, 0xba, 0x77, 0x43, 0x0a, 0x55, 0x60, 0x08, 0x9d, 0xfa, 0xc4, 0xf6, + 0x8b, 0x4f, 0x34, 0x93, 0x7a, 0x38, 0x4d, 0xd6, 0x07, 0xbc, 0xbb, 0x5f, + 0xab, 0x56, 0x77, 0xa7, 0xfa, 0xe0, 0x9e, 0xd0, 0x7c, 0xfa, 0xde, 0x39, + 0x9e, 0x87, 0xce, 0x9f, 0xdd, 0x93, 0x97, 0xc6, 0x81, 0xaa, 0x33, 0x78, + 0xce, 0x3b, 0xc8, 0x2b, 0x00, 0x7f, 0x6d, 0xe4, 0xf7, 0xcb, 0x96, 0xda, + 0xdf, 0x55, 0xa4, 0xc8, 0x73, 0x4a, 0x37, 0xf3, 0x9a, 0x5c, 0x2f, 0x25 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_236_private[] = { +/* dIUT */ + 0x01, 0xe1, 0x41, 0x6d, 0x42, 0x99, 0x26, 0xca, 0xbe, 0xa5, 0x47, 0xbb, + 0x27, 0x76, 0x71, 0x0a, 0x52, 0xf7, 0x13, 0x03, 0x93, 0x08, 0x10, 0x20, + 0x31, 0x2b, 0x39, 0x62, 0x19, 0x5e, 0xb6, 0xed, 0x17, 0xc6, 0xd4, 0x36, + 0xbc, 0x46, 0xa5, 0xb4, 0x7a, 0x7a, 0xaa, 0xcf, 0x8f, 0x81, 0x17, 0xfe, + 0xa3, 0xca, 0xfa, 0x16, 0x66, 0x5c, 0xc1, 0x84, 0x5b, 0x0e, 0xc9, 0x4f, + 0xaf, 0x68, 0x75, 0x79, 0xb1, 0xc1, 0x16, 0xba, 0x18, 0x3e, 0x82, 0x5f +}; +/* QIUTx = 065660a58688a16588a9c16b8272040a30afe3150630676023fe165686dfbda64fc85995ddc18c9c5b029bffbd4dffa8f62989c639a68623eca78009cb088ee1cb42c4855b79d302 */ +/* QIUTy = 0492c3867f137bf2787a7ab0568d3079b8d9a1e0b0ba5d29d0c7ba616d0bb27725da2ca6bc67bf084fab52599ed42b0ef48743423cbc6f4135692c309ae2630cc4a5390be93f274b */ +static const uint8_t nist_kas_ecc_cdh_testvector_236_out[] = { +/* ZIUT */ + 0x00, 0x09, 0x11, 0xec, 0x1c, 0xf8, 0x2a, 0x22, 0xc8, 0x49, 0xb4, 0x01, + 0xdf, 0xe5, 0x64, 0x53, 0xa0, 0x6f, 0x4a, 0xf3, 0x26, 0x44, 0xea, 0x8b, + 0x63, 0x13, 0x5b, 0x68, 0xa9, 0x79, 0x23, 0x6d, 0x05, 0x96, 0x8e, 0xea, + 0xdc, 0xa7, 0xf0, 0xcd, 0x33, 0x9d, 0x29, 0x5c, 0xc5, 0x89, 0x67, 0xa7, + 0xf3, 0x8c, 0xfa, 0xd6, 0xe9, 0x47, 0xa7, 0x12, 0x95, 0x73, 0x3e, 0x42, + 0xca, 0x3c, 0x1b, 0xa9, 0xb4, 0xff, 0x61, 0x95, 0x60, 0x7b, 0xb5, 0x30 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_237_public_x[] = { +/* QCAVSx */ + 0x06, 0xfa, 0x74, 0x77, 0xed, 0xec, 0x5f, 0x1e, 0x74, 0x28, 0x81, 0xf8, + 0xd7, 0xb2, 0xaf, 0x56, 0x37, 0x51, 0x13, 0xe9, 0x92, 0xb7, 0x97, 0xfd, + 0x38, 0x7e, 0xb5, 0xb5, 0x3c, 0x33, 0xc6, 0xba, 0x72, 0x36, 0x41, 0x7b, + 0x2c, 0x7e, 0x6e, 0x34, 0x62, 0x67, 0xf1, 0xb8, 0xc6, 0xd7, 0x85, 0x7d, + 0x6e, 0x08, 0xf9, 0xa6, 0x0e, 0x86, 0xde, 0x23, 0xda, 0x4b, 0x36, 0x84, + 0x24, 0xfb, 0x00, 0x3f, 0x96, 0xb4, 0xc8, 0x9f, 0x5d, 0x24, 0x4a, 0x74 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_237_public_y[] = { +/* QCAVSy */ + 0x07, 0x3e, 0x1f, 0xed, 0xf6, 0x2e, 0x8c, 0x81, 0x28, 0x36, 0x22, 0xb5, + 0x3e, 0xb2, 0xcd, 0xb2, 0x7b, 0x64, 0xc3, 0xc1, 0xdd, 0x78, 0xda, 0x0c, + 0x90, 0xdd, 0x6c, 0x3c, 0x77, 0x6a, 0xd1, 0x46, 0x30, 0x2e, 0x43, 0xab, + 0xa5, 0x41, 0x37, 0x9b, 0xc8, 0xf3, 0xbd, 0xdc, 0x2e, 0x19, 0xff, 0x15, + 0xd9, 0x66, 0x64, 0xce, 0x2d, 0x09, 0xeb, 0x6f, 0xb5, 0xb1, 0x38, 0x48, + 0xa8, 0x2b, 0x31, 0xb4, 0x52, 0xd8, 0xe8, 0x4d, 0xa3, 0xb8, 0x53, 0x18 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_237_private[] = { +/* dIUT */ + 0x01, 0x96, 0x36, 0x3e, 0xef, 0x1a, 0x0e, 0x5b, 0xe9, 0x7d, 0x8f, 0x76, + 0x01, 0xfe, 0x40, 0xff, 0x40, 0x10, 0xf4, 0x94, 0x9f, 0x01, 0x69, 0x08, + 0xa9, 0x06, 0xed, 0x5c, 0xda, 0xf1, 0x22, 0x1d, 0x3a, 0x59, 0x3b, 0x3a, + 0x46, 0x76, 0xbe, 0xaf, 0xd1, 0xfa, 0x14, 0xbc, 0x0f, 0x7c, 0x53, 0x3b, + 0x17, 0x08, 0x6f, 0x20, 0x7f, 0x9c, 0x48, 0x4c, 0xfc, 0x2f, 0xbc, 0x3d, + 0xb2, 0xbe, 0x41, 0x23, 0xa8, 0xe8, 0x6f, 0x3b, 0x49, 0x11, 0xcc, 0xe3 +}; +/* QIUTx = 01b12e38914ee0075a888d6d61cdc7570c511d90a9e3a0e2738c3a9981ab9aba9a6c61460bad079a28429a5207d2c801af2fdceda366440a11686765e9ba77f7a6bc55012d4c9510 */ +/* QIUTy = 070ede5877665fd636adcfd07220d745ed7ac0a9b0202159f450c9f6c1b837192a69ee6ad955327eb9cd326a0588b59723db4e8fd258b11db888a53eb14f2be08512688329059892 */ +static const uint8_t nist_kas_ecc_cdh_testvector_237_out[] = { +/* ZIUT */ + 0x07, 0x24, 0xc9, 0x79, 0xaf, 0xfb, 0x3a, 0xb8, 0xd3, 0x07, 0x52, 0x97, + 0x59, 0xba, 0xe5, 0xfa, 0x67, 0x31, 0x9d, 0x44, 0x18, 0x51, 0xe5, 0x81, + 0x7f, 0xef, 0x01, 0x43, 0x50, 0xe3, 0x01, 0x4e, 0x06, 0x84, 0x28, 0xc9, + 0xda, 0xc3, 0x95, 0xc5, 0xe7, 0xb9, 0xe5, 0xb8, 0x87, 0x74, 0x57, 0xb3, + 0xe4, 0x62, 0x5e, 0xf4, 0x9e, 0xde, 0x4a, 0xe3, 0x62, 0x67, 0x55, 0xee, + 0xfc, 0x3f, 0xb3, 0xcf, 0x09, 0xc2, 0x3e, 0x8a, 0x5a, 0x9f, 0x8c, 0x25 +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_238_public_x[] = { +/* QCAVSx */ + 0x01, 0x8b, 0xb6, 0xcb, 0xfc, 0xbf, 0xba, 0xed, 0x46, 0x85, 0x64, 0xb3, + 0x68, 0xf0, 0xb0, 0xab, 0xc3, 0xfb, 0xca, 0x47, 0xdc, 0xc1, 0x9f, 0x2c, + 0x84, 0x6b, 0xfa, 0x28, 0x73, 0x70, 0xe1, 0xb9, 0x12, 0xf6, 0xb7, 0x0e, + 0x08, 0x51, 0x9f, 0x57, 0x7f, 0x0c, 0xac, 0x32, 0x5b, 0x79, 0xfd, 0x66, + 0xb6, 0xb2, 0x3a, 0xa1, 0xe2, 0xae, 0x26, 0x2b, 0xcd, 0x2e, 0x7a, 0x8b, + 0x2c, 0x2d, 0x98, 0xd9, 0xed, 0x77, 0xa5, 0x4c, 0x72, 0x95, 0xf9, 0x8d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_238_public_y[] = { +/* QCAVSy */ + 0x05, 0xbe, 0x9b, 0xbd, 0x91, 0x77, 0x2b, 0xb4, 0x22, 0x66, 0xab, 0xa9, + 0xc8, 0x93, 0xe5, 0x66, 0x70, 0xcf, 0xb6, 0x6c, 0xaf, 0xbe, 0x44, 0x01, + 0xca, 0x2c, 0xb5, 0x76, 0x5b, 0x46, 0x95, 0x04, 0x84, 0x85, 0x97, 0xc7, + 0xf4, 0x46, 0xe9, 0x98, 0x14, 0x74, 0x67, 0x87, 0x15, 0x8a, 0x83, 0xeb, + 0xf8, 0xe3, 0x79, 0x68, 0x57, 0x36, 0x3a, 0x8e, 0x04, 0xf8, 0x74, 0x2a, + 0x09, 0xd7, 0xec, 0xa1, 0x63, 0x86, 0xd6, 0x0f, 0xd7, 0xc8, 0x58, 0xdf +}; +static const uint8_t nist_kas_ecc_cdh_testvector_238_private[] = { +/* dIUT */ + 0x00, 0xa1, 0x9a, 0x0e, 0xdf, 0x50, 0x83, 0x47, 0xf4, 0x40, 0x2c, 0xec, + 0xbc, 0xe1, 0x27, 0xdc, 0x64, 0x10, 0xb1, 0x96, 0x7d, 0x3f, 0x89, 0xe6, + 0xb3, 0xba, 0x08, 0xb4, 0x8a, 0xad, 0x08, 0xcd, 0x6c, 0xa5, 0xe5, 0xd1, + 0x22, 0x8c, 0xdc, 0xc4, 0x1a, 0x1c, 0x38, 0x0f, 0x2a, 0xe9, 0x05, 0x2d, + 0x73, 0xdb, 0x75, 0x50, 0xe7, 0xa3, 0xc1, 0xd8, 0x57, 0x05, 0x6c, 0x98, + 0x94, 0x7f, 0x5b, 0x2c, 0x71, 0xc3, 0x3c, 0x4e, 0xeb, 0xc1, 0x21, 0x0c +}; +/* QIUTx = 0629f70558308708e6929b1ad0fe3128a8af7f96591b47cb8ea2c3454120a6d393ed989d13231c661966a378b967efa64d3c0938e9c0b8b16c99d7349bdd59e2d44804f8fee1fb47 */ +/* QIUTy = 06a5e50fd5024d8953e32242823250e998ca602b52599405129735a874e833b3bd73d7a9dc53adea092ba8d24207f5ea5657a29919b88a6d63fd0a943b56dde4c8478481b57723e4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_238_out[] = { +/* ZIUT */ + 0x00, 0x5a, 0x52, 0x65, 0x88, 0xa3, 0xa2, 0xce, 0x08, 0xb2, 0x09, 0x25, + 0xe8, 0x39, 0x87, 0xeb, 0x0a, 0x1e, 0x68, 0xf9, 0x97, 0x10, 0x2d, 0xf7, + 0xf9, 0xaf, 0x83, 0x82, 0x3a, 0xc8, 0xe0, 0x6a, 0xbb, 0xd2, 0x9c, 0x04, + 0xcb, 0x1f, 0x97, 0x4b, 0xa9, 0xc9, 0xac, 0x49, 0xb4, 0x8b, 0x5a, 0xf3, + 0x76, 0x79, 0xa3, 0x9b, 0x53, 0x2d, 0x35, 0x9c, 0xde, 0xc3, 0xd4, 0x1b, + 0x3f, 0x80, 0xa1, 0xee, 0x12, 0xc8, 0x02, 0x76, 0x25, 0x6b, 0x73, 0x8d +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_239_public_x[] = { +/* QCAVSx */ + 0x03, 0x21, 0x84, 0xb6, 0x86, 0x3e, 0x2c, 0xb5, 0xbc, 0x71, 0xba, 0xff, + 0x5b, 0x6b, 0x57, 0xa1, 0x05, 0x94, 0x83, 0x1c, 0xc1, 0x1a, 0x9e, 0x5e, + 0xed, 0xec, 0x48, 0x04, 0xe2, 0x01, 0x6e, 0x3d, 0xd0, 0x64, 0xcf, 0xfd, + 0x12, 0xa1, 0xee, 0xa0, 0xf6, 0x93, 0x29, 0x11, 0xde, 0xd3, 0x45, 0xac, + 0xe5, 0xc1, 0xff, 0x25, 0x0b, 0x96, 0x48, 0xd9, 0x3b, 0x95, 0x33, 0x86, + 0xda, 0xe9, 0xb5, 0x62, 0x8c, 0x3c, 0x62, 0x52, 0x7b, 0x89, 0x05, 0x19 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_239_public_y[] = { +/* QCAVSy */ + 0x07, 0xf7, 0x83, 0xe0, 0x34, 0x1a, 0x87, 0x1e, 0x62, 0x56, 0xda, 0x34, + 0x9e, 0xbb, 0x53, 0x9f, 0x88, 0x76, 0x7d, 0x7d, 0xac, 0x15, 0x11, 0xe3, + 0xc3, 0xe4, 0xd4, 0x3b, 0x0f, 0xd3, 0x1d, 0x5d, 0xd2, 0xc2, 0xf0, 0xf1, + 0x76, 0xea, 0xc5, 0x44, 0xa8, 0x71, 0xf4, 0x2b, 0x98, 0x3f, 0x8f, 0xba, + 0x4d, 0xf6, 0x7a, 0xb6, 0xa2, 0x39, 0xb7, 0xdf, 0x99, 0x72, 0x26, 0x30, + 0x4b, 0x73, 0x16, 0x5d, 0x96, 0x2f, 0x4e, 0x1d, 0x2d, 0x18, 0xde, 0x9f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_239_private[] = { +/* dIUT */ + 0x00, 0x4c, 0xac, 0x3f, 0xcc, 0x00, 0x73, 0x44, 0x42, 0xcd, 0xd8, 0x0e, + 0xaf, 0x82, 0x44, 0x12, 0xc2, 0x0e, 0xa9, 0xee, 0xb0, 0x3d, 0x43, 0xb9, + 0x99, 0xd4, 0x9d, 0xe6, 0x18, 0x73, 0x60, 0x20, 0x20, 0xa2, 0xb3, 0xc4, + 0x79, 0x65, 0xf6, 0xf4, 0x53, 0xb9, 0x1b, 0x7a, 0x2c, 0x1d, 0x93, 0xe1, + 0x3a, 0x89, 0x54, 0x45, 0x33, 0xe3, 0x5a, 0x12, 0x2c, 0xfc, 0x86, 0x12, + 0xc8, 0x69, 0x0b, 0x69, 0xbb, 0x7a, 0x55, 0x78, 0x75, 0xf9, 0x60, 0xb2 +}; +/* QIUTx = 03e211c3b4986927c4388d1680cb4770dee6c78266724582c66ccc50c6cb28239474d521facc7206af6bb29cced733edbbc0d20b9264ce63d9437188e3d31c0e0bc3e9f9d88429e4 */ +/* QIUTy = 037a7c59012a82d59cc1e2f0fd4fd751e5737acb77f2a0799e0af38996ab5e11090a6396cc480e6f2aabd8fad44611691e5822115fd49d2a000c9b49d1f4964e24d43fbb81fa879f */ +static const uint8_t nist_kas_ecc_cdh_testvector_239_out[] = { +/* ZIUT */ + 0x04, 0x9d, 0xb6, 0x8d, 0xc9, 0xfb, 0x4c, 0xfb, 0xad, 0x82, 0x47, 0xca, + 0x4f, 0xe7, 0xc5, 0x73, 0xc0, 0x64, 0x0a, 0xbe, 0xad, 0x8f, 0x31, 0x91, + 0x94, 0xd6, 0x65, 0xec, 0xaf, 0x4f, 0x04, 0xb6, 0x1f, 0x84, 0xf5, 0xdf, + 0x0d, 0x8a, 0x63, 0x86, 0xf6, 0xdf, 0x04, 0xca, 0x1a, 0x68, 0x5a, 0x73, + 0x94, 0x56, 0x7e, 0xba, 0x5d, 0xeb, 0x9f, 0x73, 0x9b, 0x1e, 0x62, 0x3e, + 0xd6, 0x50, 0x70, 0x21, 0x59, 0x3f, 0x0e, 0x22, 0xe2, 0xdf, 0xc3, 0xf6 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_240_public_x[] = { +/* QCAVSx */ + 0x07, 0x1e, 0x16, 0x7e, 0x59, 0xe2, 0xa7, 0x09, 0xeb, 0xf4, 0xbe, 0x3d, + 0x83, 0xfb, 0x9d, 0xc6, 0x9e, 0xd7, 0x49, 0xe3, 0xab, 0x8a, 0x54, 0xe2, + 0x02, 0xc3, 0x5f, 0x8d, 0x45, 0xde, 0xaa, 0x2b, 0xda, 0x86, 0xc2, 0xaf, + 0xa1, 0xb0, 0xa0, 0x47, 0x54, 0xd1, 0x88, 0x98, 0xfc, 0xdd, 0x9b, 0x18, + 0x5f, 0x1d, 0x8b, 0xa2, 0xe1, 0x80, 0xa4, 0x7a, 0xc2, 0x91, 0xbb, 0x4a, + 0xad, 0x8f, 0x99, 0x7f, 0x73, 0xb1, 0x42, 0x3b, 0xcd, 0x7e, 0x9b, 0x92 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_240_public_y[] = { +/* QCAVSy */ + 0x05, 0x71, 0x19, 0x08, 0x5b, 0xc7, 0xcb, 0x20, 0x23, 0xd2, 0x3f, 0x88, + 0x10, 0x14, 0x20, 0xf9, 0xf5, 0x08, 0xf0, 0xdb, 0x94, 0xf8, 0xdf, 0xbe, + 0xdd, 0x5c, 0xbe, 0x88, 0xce, 0xc8, 0x0a, 0x9d, 0xc7, 0x08, 0xdf, 0x6c, + 0xcc, 0xdf, 0x81, 0x5d, 0x75, 0xb1, 0x46, 0x28, 0x0d, 0x7c, 0xd2, 0xeb, + 0x97, 0xcf, 0x1a, 0x7d, 0xd5, 0x50, 0xbe, 0x52, 0x38, 0x24, 0xf9, 0x32, + 0xa7, 0x77, 0x67, 0x9f, 0x2e, 0xe9, 0xf6, 0x6d, 0x42, 0x58, 0xdd, 0xa6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_240_private[] = { +/* dIUT */ + 0x00, 0xd5, 0x14, 0x14, 0x4d, 0x45, 0x48, 0xbc, 0xfc, 0xbc, 0xf5, 0x70, + 0x09, 0xf7, 0xe8, 0xee, 0x10, 0x4b, 0x15, 0x45, 0x6f, 0x49, 0x18, 0x26, + 0xbd, 0xfd, 0x9b, 0xa6, 0x7e, 0x87, 0x1f, 0xdb, 0xd8, 0xfc, 0x84, 0x90, + 0xec, 0xbc, 0xb2, 0x69, 0x09, 0x1f, 0xc7, 0x52, 0x9e, 0x5e, 0x55, 0x71, + 0x3a, 0x81, 0xde, 0x20, 0xc0, 0xed, 0x01, 0xec, 0xb3, 0x15, 0x9a, 0xe6, + 0x14, 0x24, 0xbd, 0xbc, 0x56, 0x53, 0x73, 0x25, 0x87, 0xd1, 0xe9, 0x4f +}; +/* QIUTx = 03ee5f877b737dae40baf91e0cc581dfe8d291f8c451d5bfc0b690df7025875d9569d52021b3b6890e01a2ba95899e2928a902cd5dc8143c07ea26749a9c94068b5c34c596b0943e */ +/* QIUTy = 058e1ba516a818cae9b37086287e088083e2b421fef0b59ba816ab031375d09d7af7d57866744687be3bb41ce2276d3a38f97bbb9fb59f24a92f0085b04ee5ed1ac0efa671394f73 */ +static const uint8_t nist_kas_ecc_cdh_testvector_240_out[] = { +/* ZIUT */ + 0x03, 0x43, 0xc4, 0x5d, 0xaa, 0xb4, 0xf9, 0x1e, 0x02, 0xef, 0x9b, 0xd6, + 0xe1, 0xcd, 0x15, 0x7b, 0x00, 0xab, 0x0a, 0xb0, 0xa3, 0xe0, 0xd9, 0x73, + 0x49, 0x18, 0xa1, 0xd8, 0x96, 0xcd, 0xf7, 0xcc, 0x12, 0x12, 0xbf, 0x74, + 0xd7, 0xbb, 0x9b, 0xf9, 0x6b, 0xd4, 0xab, 0xf4, 0x2d, 0xf3, 0x25, 0x75, + 0x6c, 0x40, 0x72, 0x17, 0xf4, 0x4a, 0x59, 0x50, 0xc2, 0xb6, 0x6a, 0xf8, + 0x20, 0x69, 0x27, 0x42, 0xed, 0x7e, 0xbe, 0x14, 0xe4, 0x8d, 0x2d, 0x88 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_241_public_x[] = { +/* QCAVSx */ + 0x07, 0x4f, 0x1a, 0x7b, 0x5c, 0xfb, 0x0e, 0xee, 0xf1, 0xe1, 0x5e, 0x63, + 0x51, 0x2c, 0x73, 0x18, 0x8d, 0xaf, 0xbe, 0x88, 0xe8, 0xe9, 0xc4, 0x20, + 0x73, 0xb2, 0xb6, 0x52, 0xb9, 0xf0, 0x28, 0x21, 0x4f, 0x0b, 0xec, 0x79, + 0x14, 0x2d, 0x88, 0x89, 0x41, 0x6a, 0xbf, 0x7a, 0x83, 0xe2, 0x9f, 0x47, + 0x9e, 0x7b, 0xc3, 0xca, 0x65, 0x7e, 0xf0, 0xa1, 0x0c, 0x2e, 0xa3, 0xad, + 0xe3, 0x11, 0x7c, 0x0d, 0x36, 0x9d, 0xac, 0xc2, 0x33, 0x9d, 0x1c, 0x12 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_241_public_y[] = { +/* QCAVSy */ + 0x00, 0xe8, 0x99, 0x2a, 0x54, 0x07, 0x67, 0x53, 0x02, 0x9f, 0x2c, 0x0e, + 0x9d, 0x8c, 0x16, 0x6e, 0x6b, 0xa8, 0x48, 0x96, 0xa4, 0x78, 0x5f, 0xff, + 0xf5, 0x98, 0xc4, 0x82, 0x3e, 0x54, 0x61, 0xff, 0x00, 0x54, 0x90, 0xbb, + 0x7f, 0xb6, 0xd8, 0x78, 0xac, 0x34, 0xf4, 0x27, 0xfd, 0x9d, 0xb4, 0x8c, + 0xbd, 0xf1, 0x2e, 0xb9, 0x82, 0x6d, 0x68, 0xfd, 0x2c, 0xf1, 0x71, 0xd4, + 0xd6, 0x1c, 0x3f, 0x27, 0x5d, 0x44, 0x94, 0x7d, 0x4d, 0xf4, 0xc7, 0x52 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_241_private[] = { +/* dIUT */ + 0x00, 0xcc, 0xc6, 0xdc, 0xa5, 0xa9, 0x85, 0x58, 0x3c, 0xe0, 0x08, 0x12, + 0xc3, 0xd0, 0x78, 0x22, 0xf6, 0x34, 0x1c, 0x79, 0xd7, 0x8c, 0x16, 0xb2, + 0xe7, 0xae, 0x4b, 0xbf, 0x5b, 0xff, 0xac, 0x1a, 0xcd, 0x9d, 0xea, 0xb6, + 0x78, 0x19, 0x3f, 0x8f, 0x89, 0xb0, 0xe2, 0xaa, 0xe5, 0x2e, 0x30, 0x31, + 0x14, 0x44, 0xdd, 0x11, 0x25, 0x3f, 0x96, 0xd6, 0x2d, 0xb3, 0xab, 0xfb, + 0x17, 0xe4, 0x23, 0xf0, 0xdd, 0xf0, 0xe9, 0x91, 0x08, 0x11, 0x54, 0xc3 +}; +/* QIUTx = 03826215343cfd4ad968d572bab2dee2279f9e8effa0ff80b0df5dd2ea822b502274e507c87d2429dd8bbdba6eb8ab433b1ee1cad3a97c7d244194fd9a43f3e1ff33144e2db80864 */ +/* QIUTy = 070f4508ae391ce24154b38873af0082d95895ac92fd1aa321ba93beef404a63f7b1afa1feec997885523a6688ada94dd45eb32ca7f1bb87e63c4de97493196c3b53cf83d218dc37 */ +static const uint8_t nist_kas_ecc_cdh_testvector_241_out[] = { +/* ZIUT */ + 0x04, 0xa5, 0x65, 0xcb, 0x3e, 0x15, 0x23, 0x6a, 0x7f, 0x6c, 0x41, 0x3a, + 0xfe, 0xb4, 0x19, 0xc0, 0x82, 0x42, 0x7b, 0x10, 0xa6, 0xd0, 0x7f, 0xf8, + 0x7e, 0x81, 0x74, 0x07, 0x16, 0x43, 0x3c, 0x06, 0xb3, 0x25, 0x44, 0x14, + 0x38, 0x1e, 0x4f, 0xf9, 0x86, 0x03, 0x40, 0xdd, 0x62, 0x01, 0xab, 0x66, + 0x21, 0xd1, 0x62, 0xcd, 0x12, 0x04, 0x7a, 0x55, 0x15, 0xab, 0x1d, 0x65, + 0xf2, 0x0c, 0x97, 0xeb, 0x3d, 0x71, 0x32, 0x64, 0x2f, 0x8a, 0xd5, 0x8a +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_242_public_x[] = { +/* QCAVSx */ + 0x00, 0x4b, 0x54, 0xb3, 0xce, 0xfd, 0x41, 0x5f, 0x5e, 0xaa, 0xca, 0x4a, + 0xe4, 0xe5, 0xda, 0xcf, 0xbc, 0xe2, 0x0c, 0xba, 0x19, 0x32, 0xa2, 0xf5, + 0x05, 0x49, 0xbc, 0xd3, 0x16, 0x30, 0x01, 0x7a, 0xd2, 0x14, 0x75, 0xdf, + 0x15, 0x4f, 0xf3, 0x7b, 0xe1, 0x3c, 0xa6, 0x1a, 0x4c, 0x60, 0x33, 0x6b, + 0x33, 0xd0, 0xff, 0xc7, 0x62, 0xaa, 0x9e, 0x9e, 0x9f, 0xc6, 0xe6, 0xfd, + 0x17, 0x25, 0x0b, 0x5e, 0x40, 0x22, 0xb5, 0x51, 0x41, 0xd2, 0x3f, 0xbf +}; +static const uint8_t nist_kas_ecc_cdh_testvector_242_public_y[] = { +/* QCAVSy */ + 0x05, 0x6f, 0x7c, 0x8d, 0x65, 0xc5, 0x68, 0xde, 0x95, 0xbd, 0x16, 0x64, + 0xff, 0xf7, 0x14, 0x29, 0xec, 0x73, 0x89, 0x87, 0x69, 0x7f, 0x21, 0x7d, + 0xe5, 0xad, 0xf3, 0x6d, 0x14, 0xa8, 0x0b, 0x6f, 0xe5, 0x85, 0xe4, 0x68, + 0x5e, 0x03, 0xc8, 0x18, 0x38, 0xab, 0xed, 0xfd, 0xc0, 0x5a, 0x1e, 0x01, + 0x40, 0x7a, 0xf4, 0xab, 0x98, 0x9f, 0xc1, 0xd1, 0x27, 0x3b, 0xa8, 0xa1, + 0x82, 0xc4, 0x61, 0x85, 0x6d, 0x5e, 0xff, 0xe7, 0x05, 0xd7, 0xdf, 0xe5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_242_private[] = { +/* dIUT */ + 0x01, 0x88, 0x62, 0x13, 0x65, 0x8b, 0xd1, 0x7e, 0x7d, 0xc3, 0x34, 0xdd, + 0x80, 0x03, 0x92, 0x6a, 0x44, 0x7c, 0x34, 0xa1, 0x97, 0xee, 0x5d, 0x6d, + 0x0b, 0xbc, 0x46, 0xe8, 0x5e, 0xc1, 0xcf, 0xa6, 0x80, 0x28, 0x58, 0xd1, + 0xc3, 0x67, 0x27, 0x6c, 0xa5, 0x72, 0xba, 0x27, 0xaa, 0x7a, 0x5d, 0x1e, + 0x21, 0x69, 0x02, 0x41, 0x6b, 0x48, 0xaf, 0x6e, 0x42, 0x77, 0x94, 0x5e, + 0x46, 0x5d, 0x7d, 0x84, 0x0d, 0xff, 0x14, 0x38, 0x54, 0x3c, 0xaa, 0x46 +}; +/* QIUTx = 047f6cc42107c40c168dc679a864f969b53f756257113b7502796efa54cdcce704b9344ee4bf964752d68910262bd26ab6b347084404b28306ca3425f29894ce6fd4293c5973522f */ +/* QIUTy = 060cfdb5467675a789923be973c6645dbe26d00a39d4e81255217291a3882cfa8f91f4aa8214d3524c95ef6a24e47b3b9d0ef55f670756ae4a4d9c65f075f4170b2d18aafbca0265 */ +static const uint8_t nist_kas_ecc_cdh_testvector_242_out[] = { +/* ZIUT */ + 0x04, 0x72, 0x65, 0x83, 0x1f, 0x1f, 0x58, 0x9b, 0x5f, 0x30, 0x80, 0x6e, + 0x2f, 0xb8, 0x0a, 0xa7, 0x84, 0x4c, 0xbf, 0x32, 0xb6, 0x99, 0x33, 0x84, + 0xbe, 0xaa, 0xc7, 0xd9, 0x92, 0xb3, 0x27, 0xb9, 0x7d, 0xfd, 0x0b, 0xb8, + 0x9c, 0xa0, 0x9e, 0x71, 0x15, 0x07, 0xe8, 0x46, 0xed, 0x4a, 0xd0, 0x03, + 0xe7, 0x11, 0x5f, 0xa8, 0x84, 0x3b, 0x23, 0xd3, 0x8f, 0x32, 0x0e, 0x43, + 0xb5, 0xeb, 0x50, 0x6b, 0xde, 0x48, 0xfb, 0xd7, 0xaf, 0x49, 0x83, 0xb9 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_243_public_x[] = { +/* QCAVSx */ + 0x07, 0xec, 0x71, 0xbe, 0xa0, 0x81, 0x19, 0x0a, 0x9c, 0x4c, 0xdf, 0xf8, + 0x09, 0xed, 0x2b, 0x65, 0xa7, 0x78, 0x00, 0xcd, 0x1b, 0x3b, 0xef, 0xfd, + 0x1e, 0x40, 0x04, 0xd1, 0x26, 0xac, 0x35, 0x2d, 0x24, 0x23, 0x5c, 0x79, + 0x7a, 0x5a, 0x56, 0x7d, 0xae, 0xf7, 0x39, 0x3d, 0x27, 0x66, 0x38, 0x13, + 0x2e, 0xa7, 0xf0, 0xf6, 0x1e, 0x55, 0x0d, 0xc2, 0x51, 0xd3, 0x41, 0xf6, + 0x61, 0x02, 0xf9, 0x6c, 0x2a, 0xbf, 0x7e, 0xe3, 0x7c, 0x0f, 0xc9, 0xed +}; +static const uint8_t nist_kas_ecc_cdh_testvector_243_public_y[] = { +/* QCAVSy */ + 0x00, 0xef, 0xc2, 0xac, 0x87, 0x05, 0xb2, 0xf9, 0xc9, 0xc0, 0x6a, 0x91, + 0x0a, 0x30, 0x4c, 0x42, 0xb1, 0xad, 0x53, 0x10, 0x1a, 0xeb, 0x0d, 0x14, + 0x63, 0x19, 0xdc, 0x24, 0x81, 0x5c, 0x7c, 0xc1, 0x98, 0x3b, 0x1c, 0xad, + 0x91, 0xd5, 0xf9, 0xc6, 0xd5, 0xee, 0xf1, 0x67, 0x7a, 0x1f, 0x2d, 0x2b, + 0xdd, 0x75, 0xa1, 0xfb, 0x4c, 0x57, 0x96, 0xa4, 0xc5, 0x69, 0x64, 0xaa, + 0x3e, 0x43, 0xf3, 0xda, 0x26, 0xc7, 0x37, 0xed, 0xd9, 0xcb, 0x09, 0x10 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_243_private[] = { +/* dIUT */ + 0x00, 0x4c, 0x0d, 0xd3, 0x71, 0x5e, 0x88, 0x88, 0xdc, 0x22, 0x22, 0x06, + 0x9e, 0x7f, 0x61, 0x18, 0x01, 0x68, 0x51, 0x40, 0x30, 0x3e, 0x16, 0xb8, + 0xb4, 0x43, 0x43, 0x3d, 0x5e, 0x18, 0xa4, 0xb1, 0x80, 0x3d, 0x56, 0x80, + 0x41, 0x6a, 0xeb, 0xda, 0x7a, 0xe7, 0xe9, 0x44, 0x91, 0x54, 0xbe, 0x34, + 0x6a, 0x7d, 0xcb, 0x36, 0xc1, 0xdb, 0x22, 0x74, 0x46, 0x73, 0xfb, 0x3b, + 0x24, 0x5e, 0x58, 0x44, 0x07, 0x87, 0xed, 0x3d, 0xec, 0x6d, 0x3d, 0xb5 +}; +/* QIUTx = 02fb241eb2c28a1b0675b5760fe5663efa603eb0590842f455973f0573e148a47e63f97e8df9a570b0655d5afc42019fe95fe44fdb02a68271d82df580010f91dff0cb3d9bda8992 */ +/* QIUTy = 033f93a9dc39d87403b6a94dc0632dec6757842d0aaf8ad8c41ebb637058bfc11c19a3a9abddf204201ef4f96fe9629233a5070a08794d14470091e30cdd876aaf65407627233234 */ +static const uint8_t nist_kas_ecc_cdh_testvector_243_out[] = { +/* ZIUT */ + 0x05, 0x9b, 0x62, 0xc2, 0x5c, 0x96, 0x95, 0x5b, 0x8f, 0xb4, 0xde, 0xdd, + 0xcf, 0x90, 0xeb, 0xe6, 0x84, 0x5e, 0xe7, 0x1e, 0xa3, 0x57, 0x73, 0x92, + 0x73, 0xd6, 0xd6, 0x7f, 0x21, 0xa0, 0xc4, 0x7d, 0x15, 0x4a, 0xdd, 0x9d, + 0x5d, 0x4d, 0x2b, 0x65, 0x7f, 0xe1, 0x98, 0x8a, 0xd6, 0x14, 0xb0, 0xb4, + 0x90, 0x2f, 0xaa, 0x92, 0xfe, 0x99, 0x9a, 0xbd, 0x75, 0x4a, 0xd3, 0x3c, + 0xd6, 0xb9, 0x2f, 0xe2, 0xf6, 0xa6, 0x8a, 0x6f, 0x2c, 0x1e, 0xeb, 0x27 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_244_public_x[] = { +/* QCAVSx */ + 0x06, 0x70, 0x86, 0x86, 0xb4, 0xf5, 0xad, 0x2f, 0xec, 0x45, 0x7a, 0xad, + 0x5a, 0xc4, 0xa3, 0xdc, 0x48, 0x67, 0xa4, 0x77, 0xeb, 0x54, 0xfc, 0x0d, + 0x49, 0x35, 0x11, 0xb5, 0x56, 0x1e, 0xa1, 0x51, 0xdd, 0x4c, 0xaf, 0x5d, + 0x43, 0x11, 0x98, 0x35, 0x00, 0xb4, 0x8c, 0x80, 0x43, 0xaf, 0x09, 0xe3, + 0xf4, 0x04, 0x2d, 0x5a, 0x07, 0xeb, 0xf0, 0x50, 0xa4, 0xe8, 0x01, 0xda, + 0xee, 0xf3, 0x31, 0x7b, 0xe0, 0x93, 0x95, 0x50, 0x20, 0x45, 0x2b, 0x29 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_244_public_y[] = { +/* QCAVSy */ + 0x05, 0x25, 0xc8, 0x68, 0x25, 0x83, 0xb5, 0x5f, 0x7e, 0xce, 0xc5, 0x9b, + 0x92, 0x08, 0x46, 0xf7, 0x5d, 0x11, 0xd0, 0x21, 0xe9, 0xff, 0xb2, 0x00, + 0x18, 0x63, 0x9f, 0x6a, 0xb9, 0x30, 0x22, 0x47, 0x2c, 0x19, 0x2d, 0x39, + 0x8e, 0x15, 0x0c, 0xdc, 0x63, 0x0a, 0x11, 0xfc, 0xf9, 0x42, 0xe5, 0xd2, + 0x38, 0xcd, 0x6c, 0x14, 0xb3, 0x0f, 0x44, 0xa2, 0x4d, 0x2f, 0x84, 0x3e, + 0xc5, 0xd1, 0x35, 0xdd, 0xc7, 0xab, 0xda, 0x56, 0x04, 0x7a, 0xbc, 0x21 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_244_private[] = { +/* dIUT */ + 0x00, 0x7d, 0x54, 0x19, 0x4f, 0xc2, 0x26, 0xcc, 0x39, 0xf6, 0x40, 0xd3, + 0xd1, 0x7b, 0x9b, 0x95, 0xb7, 0x0b, 0x51, 0xf9, 0x8a, 0xd5, 0xca, 0x19, + 0x91, 0x56, 0x61, 0x08, 0xd8, 0x39, 0xe3, 0x77, 0xe2, 0x1b, 0xa4, 0x8c, + 0xbf, 0x44, 0x15, 0x30, 0xb3, 0x34, 0x1d, 0xdc, 0x61, 0xb0, 0xa5, 0x81, + 0x41, 0xaa, 0xa6, 0x65, 0x30, 0x24, 0x1f, 0xa5, 0x29, 0x50, 0x5d, 0x70, + 0x80, 0x4b, 0x25, 0x60, 0xc5, 0xbe, 0x48, 0x13, 0x10, 0xb9, 0x96, 0x2d +}; +/* QIUTx = 02ed5f3a2efa4ab0f9db5fced7b1300de4d457a9ad0827457e5e1c4bc15ebd183775de4b73c1f820dd4033366100e48b4164d04e9fb6cf1a4bdb55122a86005fbd0bd2cddbc95fa7 */ +/* QIUTy = 0327fe654ef68563cc8888acca85163c2b154fb70b0f4a2b58c36388a0c25f80a4c887977d46000dc4d86e95cfd8f9065c00eb28653c8fb477bbb5c63dd47b83ca5e0f871e9eed3d */ +static const uint8_t nist_kas_ecc_cdh_testvector_244_out[] = { +/* ZIUT */ + 0x02, 0x77, 0x7c, 0x72, 0x85, 0x3b, 0x76, 0xb2, 0x9f, 0x69, 0xd3, 0xaa, + 0x27, 0xa1, 0x65, 0x97, 0x89, 0xa0, 0x25, 0xaf, 0x06, 0x33, 0xd8, 0x33, + 0xb2, 0x2b, 0x57, 0xbf, 0x32, 0x8d, 0x23, 0x1e, 0xbd, 0x12, 0x8b, 0xf9, + 0x6a, 0x4c, 0x8a, 0x7f, 0xfd, 0x2e, 0xe7, 0xa5, 0x1e, 0x5e, 0xbb, 0x7a, + 0x8e, 0x5b, 0xca, 0x20, 0xe4, 0xad, 0x49, 0x67, 0x1a, 0x21, 0x23, 0xdf, + 0xbc, 0x0d, 0x6c, 0x40, 0x59, 0x4e, 0x04, 0x76, 0x51, 0x86, 0xde, 0x06 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_245_public_x[] = { +/* QCAVSx */ + 0x07, 0xce, 0x76, 0x74, 0x40, 0x3d, 0xfc, 0x62, 0x89, 0x5d, 0x71, 0xe2, + 0xab, 0x58, 0x7c, 0xe7, 0x35, 0xf2, 0x79, 0xf1, 0x2f, 0x7d, 0xf3, 0x16, + 0x13, 0x35, 0xbe, 0x43, 0xfc, 0x29, 0x08, 0xea, 0x73, 0x6f, 0x6f, 0x58, + 0xb9, 0x32, 0xd7, 0x93, 0xaf, 0xf6, 0x6f, 0x33, 0x27, 0x35, 0xd4, 0xd3, + 0x8f, 0x05, 0xcb, 0x03, 0xcf, 0x27, 0x5c, 0xa0, 0xe0, 0x0d, 0xa1, 0xf5, + 0x73, 0x81, 0xe0, 0x8b, 0xfe, 0xb5, 0x01, 0x78, 0x77, 0x34, 0x22, 0x72 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_245_public_y[] = { +/* QCAVSy */ + 0x07, 0xd6, 0x64, 0x9f, 0x3d, 0x91, 0xe7, 0xbf, 0x5f, 0x8d, 0xe6, 0x11, + 0xbd, 0x97, 0x18, 0x18, 0x10, 0x6d, 0xf2, 0xe3, 0x79, 0x35, 0xbb, 0x46, + 0x4c, 0xd9, 0xe7, 0x46, 0x96, 0x29, 0xc6, 0xae, 0x7e, 0x7f, 0x2b, 0x22, + 0x40, 0x27, 0x6c, 0xb0, 0xee, 0xdb, 0x7a, 0x26, 0xd0, 0xc7, 0xd3, 0x77, + 0xf4, 0x00, 0x9a, 0x1d, 0xd4, 0x8a, 0x79, 0x3c, 0xc9, 0x93, 0xfb, 0x0d, + 0x4a, 0x04, 0xdb, 0x1d, 0xba, 0xd4, 0x49, 0x33, 0x04, 0xbc, 0x5c, 0x0e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_245_private[] = { +/* dIUT */ + 0x01, 0x07, 0x40, 0xb9, 0x58, 0x28, 0x52, 0x42, 0x04, 0x5c, 0xd5, 0x35, + 0x8d, 0x7f, 0xf9, 0x23, 0x2b, 0x7d, 0x7d, 0x41, 0x3a, 0xf7, 0xe2, 0x05, + 0xc2, 0x85, 0xf8, 0x84, 0x92, 0xef, 0x27, 0xa2, 0xfb, 0x85, 0x0e, 0x05, + 0x67, 0xec, 0x24, 0xc4, 0x80, 0xc7, 0x5a, 0xd3, 0x2f, 0x70, 0x34, 0x20, + 0x25, 0xc8, 0x62, 0x67, 0xdb, 0xe4, 0xff, 0x80, 0xa2, 0xc5, 0x09, 0xe5, + 0xb9, 0xa4, 0x51, 0x30, 0xe9, 0x9e, 0x7c, 0x7c, 0xc8, 0xcc, 0x6e, 0xce +}; +/* QIUTx = 03f3f585cafd46a663b6cf8b8323ef9159d5195d3118f3edf38732ca0ff73b2d065d9e69ae1e3978b2ce6dc61500f7b8bbf6f6a70b47bb64cc4fd195bba6ac932b70beafe174148a */ +/* QIUTy = 00b1566fe619f2cc00aba05e24a6cccbc91338b2eef553da0d477d6c8c0ac4c656e134dbcf31ffb15c67d589bd2918f1174909e5428c71c90e38c4e11b56236abfa1de6a8579eb4d */ +static const uint8_t nist_kas_ecc_cdh_testvector_245_out[] = { +/* ZIUT */ + 0x02, 0xc2, 0xec, 0x16, 0x32, 0xe8, 0x34, 0x16, 0x18, 0x2a, 0x9a, 0x43, + 0x8f, 0x73, 0x60, 0xb8, 0x80, 0x61, 0xba, 0xb8, 0x4f, 0x5b, 0xde, 0xd3, + 0xdd, 0x8a, 0x0c, 0x87, 0xba, 0xf4, 0x45, 0x07, 0xdf, 0x94, 0xfd, 0xcf, + 0x99, 0x35, 0x3b, 0x10, 0x7e, 0x61, 0xcf, 0xcf, 0xc8, 0xaf, 0x07, 0x1b, + 0x3a, 0xa8, 0xce, 0xc7, 0xb3, 0x4a, 0x54, 0x2b, 0xf2, 0xab, 0x8e, 0xa0, + 0xbd, 0x9d, 0xb6, 0x7d, 0x66, 0xb4, 0x28, 0xc9, 0xa6, 0xc1, 0x44, 0x58 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_246_public_x[] = { +/* QCAVSx */ + 0x04, 0x83, 0xad, 0x73, 0x82, 0xe3, 0x48, 0xaf, 0xc7, 0xf2, 0x71, 0xd5, + 0x0d, 0x8d, 0x39, 0xb8, 0x14, 0xb7, 0xd6, 0xdc, 0x0c, 0x56, 0x2a, 0x6b, + 0xa5, 0x56, 0x56, 0x80, 0x45, 0xbd, 0x2d, 0x62, 0x09, 0x06, 0xab, 0x11, + 0x06, 0xf9, 0x13, 0x7f, 0xf7, 0x25, 0x89, 0x2e, 0x84, 0x36, 0xa8, 0xcd, + 0x7b, 0x88, 0x89, 0x2a, 0x32, 0xf1, 0x9a, 0xb2, 0x69, 0xe2, 0xad, 0x30, + 0xd7, 0xf0, 0xec, 0x00, 0xe3, 0xa0, 0x52, 0xfb, 0xbc, 0x46, 0x63, 0x07 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_246_public_y[] = { +/* QCAVSy */ + 0x04, 0x1c, 0xc4, 0xb0, 0xf1, 0x95, 0xdc, 0x73, 0xc4, 0xa8, 0xe1, 0x06, + 0x05, 0xf2, 0xa3, 0x82, 0x92, 0x3a, 0xbd, 0x23, 0x81, 0xf2, 0x4e, 0x4a, + 0xbb, 0xd4, 0x01, 0xe0, 0x87, 0xc5, 0x0d, 0x18, 0xf6, 0xda, 0xb0, 0x1a, + 0x25, 0xdb, 0x7e, 0x89, 0xdf, 0xff, 0x68, 0xc6, 0x63, 0x49, 0x4f, 0xb4, + 0xd0, 0x87, 0xa8, 0x16, 0xb8, 0x54, 0x44, 0xd8, 0x82, 0xbe, 0xc2, 0xac, + 0x25, 0xe4, 0x2f, 0xde, 0x78, 0xeb, 0xcc, 0xa7, 0x9a, 0x6f, 0xdd, 0xf0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_246_private[] = { +/* dIUT */ + 0x00, 0xc8, 0x5e, 0x5d, 0x2d, 0xed, 0x5b, 0xc3, 0xb6, 0xb5, 0x53, 0xfe, + 0x0a, 0x02, 0x31, 0x1b, 0x72, 0xbc, 0x5c, 0xdc, 0x8e, 0x96, 0xdf, 0x17, + 0x9c, 0xe5, 0x75, 0x11, 0xc2, 0x6a, 0xc9, 0xe8, 0x73, 0xfc, 0x1f, 0x76, + 0xcd, 0xde, 0x9a, 0x7d, 0x8e, 0x52, 0xa7, 0xe9, 0xbe, 0x5c, 0x77, 0x53, + 0x62, 0x03, 0x31, 0xe8, 0x97, 0x7a, 0x98, 0x90, 0x2b, 0x48, 0xae, 0x98, + 0x99, 0xce, 0x8a, 0x6a, 0x66, 0x36, 0x61, 0x12, 0x76, 0xae, 0x23, 0x83 +}; +/* QIUTx = 0289aa5209fe7b1ad7b9c5e0e630ba5e02929ea1b1f114d30a0648012bf029e066453f2d28e1d503665dd0833f0ba37e4583b434dd9956100a1ae6e54f96d9347d806741d3a76e31 */ +/* QIUTy = 033afe87b29edef447ff5a02e63f64905b5f53ac856cfd7755ad542812ecdd568e8ae1f9d32fea0f02018dcfd0e16d6a6a2797b7e3dc855bfdb6b0d0b2525e143678d539bf8c0672 */ +static const uint8_t nist_kas_ecc_cdh_testvector_246_out[] = { +/* ZIUT */ + 0x07, 0xe1, 0xd2, 0x02, 0xa5, 0x4d, 0x34, 0x02, 0x09, 0x39, 0xf7, 0xae, + 0xd5, 0x69, 0x31, 0xf2, 0x1b, 0x20, 0x67, 0x61, 0xe4, 0xfc, 0x79, 0xb9, + 0xa7, 0xb3, 0x20, 0xf8, 0x10, 0x77, 0xbe, 0x32, 0x2a, 0xe7, 0x80, 0x94, + 0x46, 0xb5, 0xb3, 0xea, 0x70, 0x16, 0x18, 0xec, 0xdb, 0x0a, 0x17, 0x96, + 0xab, 0x80, 0x40, 0x7a, 0x28, 0x1b, 0xdb, 0xcb, 0x4d, 0x58, 0x01, 0x31, + 0xb6, 0x1f, 0x87, 0x43, 0xbf, 0xef, 0x7a, 0x4d, 0x9c, 0x59, 0x41, 0xf1 +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_247_public_x[] = { +/* QCAVSx */ + 0x07, 0xa5, 0xe8, 0xeb, 0x49, 0x68, 0x49, 0x7a, 0x11, 0xb9, 0x0c, 0x60, + 0xe1, 0x3d, 0x5f, 0x3c, 0x61, 0xc6, 0x86, 0x85, 0x73, 0xa6, 0xb6, 0xdb, + 0x7c, 0x20, 0x8a, 0x85, 0x6d, 0x54, 0xe7, 0x4f, 0x43, 0x68, 0xe2, 0x81, + 0x00, 0xb9, 0xe0, 0xbf, 0x49, 0xfc, 0x31, 0x04, 0xe1, 0x46, 0xfb, 0xda, + 0x78, 0x46, 0x23, 0xa3, 0x6d, 0x9f, 0x01, 0xf2, 0x3e, 0xba, 0xdf, 0xab, + 0x04, 0xd7, 0xf4, 0x8f, 0xf6, 0x65, 0x06, 0xc6, 0x98, 0xbe, 0xdd, 0x11 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_247_public_y[] = { +/* QCAVSy */ + 0x01, 0x3d, 0xb9, 0x68, 0xfc, 0x7c, 0xd3, 0x38, 0xcb, 0x8e, 0x30, 0x42, + 0xa1, 0x71, 0xfa, 0x30, 0x6f, 0x9a, 0xb6, 0xf6, 0xc8, 0x65, 0xdd, 0xc5, + 0xba, 0x5f, 0xe9, 0x94, 0xa3, 0x0d, 0x8f, 0xc1, 0xfa, 0x12, 0x71, 0x91, + 0xf0, 0x8e, 0x4e, 0x14, 0xb9, 0xaa, 0x08, 0x6a, 0x52, 0xfb, 0xca, 0xa4, + 0x6d, 0x22, 0x10, 0x7f, 0xd6, 0xdf, 0x53, 0x10, 0x8b, 0x53, 0xfe, 0x0b, + 0xb9, 0x6b, 0xc9, 0x74, 0xc0, 0x3a, 0x8c, 0x65, 0x28, 0xf9, 0x79, 0x2d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_247_private[] = { +/* dIUT */ + 0x00, 0x53, 0xa4, 0x8c, 0xfd, 0xa8, 0xee, 0x23, 0x2c, 0xea, 0x35, 0x49, + 0x92, 0x7b, 0x22, 0xf3, 0x75, 0xd6, 0x09, 0x65, 0x60, 0x02, 0x5e, 0x21, + 0x31, 0x61, 0xd4, 0x3e, 0xed, 0x02, 0xd0, 0x73, 0x65, 0xd9, 0xed, 0xe7, + 0xc9, 0x3d, 0x45, 0x7e, 0xa5, 0x1e, 0xa2, 0x36, 0x9e, 0x87, 0x46, 0x3e, + 0xdd, 0xbf, 0x25, 0xa0, 0x6b, 0xb1, 0xf0, 0x80, 0xfb, 0x47, 0x63, 0x07, + 0x4a, 0x82, 0x83, 0xdd, 0x3d, 0x69, 0xf1, 0xde, 0x86, 0x52, 0x95, 0xe3 +}; +/* QIUTx = 04790f9db600b9a0a57e03d274a3d23a55aa0d86b2d6fa07fafe3c9d4c3393771dde89c70a6470a31bad105c21d4844cd7bfc3b59738f9d6c528c414d524f88e0c862e4e17aff454 */ +/* QIUTy = 05dc12db04e2489db8a46cdeff9f8d9d2e00d024f656c781eb4d2db167624b3a70addaaa158ca00601d4cad065917bebe766912faba9987fcc5fc8a78dd21643aa650e6a4a7e2061 */ +static const uint8_t nist_kas_ecc_cdh_testvector_247_out[] = { +/* ZIUT */ + 0x07, 0xf4, 0x9e, 0xe5, 0xd8, 0x22, 0xb1, 0x7e, 0x3f, 0x1e, 0xc9, 0x94, + 0x6f, 0xad, 0x8d, 0x0a, 0x0a, 0x6b, 0x32, 0x72, 0x42, 0xaf, 0xe6, 0x75, + 0x80, 0x6b, 0x3e, 0x6b, 0x75, 0x41, 0x74, 0x5e, 0x21, 0xcd, 0x1b, 0x70, + 0xdf, 0x92, 0x6a, 0xf0, 0x57, 0xa9, 0xf8, 0xde, 0xae, 0x4c, 0xb9, 0xa1, + 0xed, 0xc7, 0x82, 0x01, 0x44, 0x26, 0x15, 0x2e, 0x8a, 0xa4, 0xcf, 0x6a, + 0x40, 0x80, 0xda, 0xd4, 0x67, 0x8d, 0xc8, 0xff, 0x0d, 0x9e, 0x1a, 0xf9 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_248_public_x[] = { +/* QCAVSx */ + 0x01, 0x3c, 0xaa, 0xf8, 0xce, 0x2e, 0x23, 0x21, 0xcf, 0x25, 0x6f, 0x2b, + 0x64, 0xaa, 0x89, 0xad, 0xd6, 0x96, 0x8c, 0x29, 0x86, 0x24, 0xa2, 0x2b, + 0xd3, 0x8e, 0xf9, 0x4d, 0xeb, 0x3a, 0x70, 0xea, 0x44, 0xce, 0x87, 0xa9, + 0x48, 0xea, 0x56, 0xbf, 0x0e, 0xe9, 0x40, 0x71, 0x34, 0xf8, 0xc9, 0x7b, + 0x17, 0xb1, 0xf5, 0x45, 0x61, 0xff, 0x77, 0x47, 0xe3, 0xf6, 0xb6, 0x56, + 0xf8, 0x0d, 0x60, 0x77, 0x8d, 0x05, 0xb8, 0xc4, 0xcb, 0xbb, 0xcf, 0x3c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_248_public_y[] = { +/* QCAVSy */ + 0x00, 0x47, 0xa2, 0xdc, 0xa3, 0xeb, 0x67, 0x54, 0xb0, 0xa9, 0xfd, 0x16, + 0xb0, 0x81, 0xfc, 0xa4, 0x97, 0xb2, 0x9d, 0xd2, 0xec, 0x9e, 0x6a, 0x75, + 0x96, 0xd0, 0x6b, 0x05, 0x9c, 0x2a, 0xb1, 0x89, 0x00, 0xfc, 0xc5, 0x87, + 0x15, 0x24, 0x72, 0x76, 0xe3, 0x90, 0xdf, 0x1d, 0xba, 0xb2, 0x6b, 0xa8, + 0x12, 0x35, 0xa4, 0xdc, 0x67, 0x38, 0x23, 0x7f, 0xce, 0xfd, 0x38, 0x12, + 0xb7, 0xab, 0x43, 0x6c, 0x92, 0x6c, 0x50, 0xc6, 0x00, 0xe6, 0xe9, 0x07 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_248_private[] = { +/* dIUT */ + 0x01, 0x5a, 0x5e, 0x59, 0x46, 0xfe, 0x2c, 0x9c, 0xae, 0x6d, 0x41, 0x2c, + 0x61, 0x8c, 0x1b, 0xd0, 0x77, 0x24, 0x43, 0x2b, 0x2f, 0x1d, 0xed, 0xb1, + 0x32, 0x7d, 0x8a, 0x99, 0xce, 0x83, 0x0e, 0x6b, 0x03, 0x0f, 0x40, 0x25, + 0xc1, 0x4b, 0x4e, 0x3d, 0x19, 0x12, 0xea, 0x9a, 0x78, 0x29, 0x0a, 0x1c, + 0xfc, 0x7d, 0x01, 0x89, 0xa3, 0x0c, 0x61, 0x40, 0x10, 0xc8, 0x73, 0x14, + 0x6a, 0x18, 0x2f, 0x63, 0x91, 0x93, 0xa2, 0x91, 0x2e, 0xdc, 0xd0, 0x4a +}; +/* QIUTx = 03140887e87039797869f5d9db50d91ba69d0bfdc5a677c700610562f680d951a5e0517cb2f966367d48e423b046db4e68bc1c4b3183dc80bee126e89014994cdf83c4312a3e5ea7 */ +/* QIUTy = 07b8d706962cb192f0ed14c4da710d1b1b073fd8ca497a94379a7454c9c3d4ce6e5fd2e6386852a77c5435abb23536dcc83986cedd4512752f295ca500f055f462763c29fb678caa */ +static const uint8_t nist_kas_ecc_cdh_testvector_248_out[] = { +/* ZIUT */ + 0x05, 0x8c, 0xd5, 0x60, 0x8d, 0xd9, 0xd6, 0x4d, 0x4d, 0x82, 0x2b, 0xae, + 0xca, 0x12, 0x33, 0x58, 0xa4, 0xd7, 0xe5, 0x6d, 0x37, 0x77, 0xec, 0xdf, + 0x56, 0x9a, 0x14, 0x9c, 0x2f, 0x85, 0xed, 0x35, 0x47, 0x9e, 0xae, 0xaa, + 0xba, 0xbd, 0x0b, 0x02, 0x6d, 0xc3, 0xb5, 0x6a, 0xed, 0xaf, 0xed, 0xfc, + 0x84, 0x91, 0x04, 0x04, 0x13, 0xf8, 0x5b, 0x66, 0x9d, 0x85, 0x12, 0xa3, + 0xef, 0x7b, 0xc8, 0xfe, 0x87, 0x06, 0xb5, 0xc7, 0x58, 0x53, 0x70, 0xaa +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_249_public_x[] = { +/* QCAVSx */ + 0x07, 0x43, 0xb3, 0xc9, 0x65, 0xa8, 0x3e, 0xe9, 0xf6, 0xbd, 0xb9, 0x90, + 0x1a, 0x1d, 0xcc, 0x1f, 0x78, 0x19, 0x65, 0x44, 0xa8, 0x8b, 0x9c, 0xf8, + 0x11, 0x7f, 0x89, 0xed, 0x15, 0x74, 0xe5, 0xc5, 0xd8, 0x04, 0xfc, 0x45, + 0x11, 0x12, 0xc2, 0x57, 0x87, 0x7e, 0x12, 0xb0, 0xa6, 0x6c, 0x69, 0x3c, + 0x66, 0x55, 0xc1, 0x2b, 0xba, 0x45, 0x35, 0xd9, 0x9d, 0x62, 0x40, 0x5f, + 0x4a, 0x9d, 0xce, 0xbc, 0x05, 0x6d, 0x8b, 0x7c, 0xbb, 0xad, 0xa1, 0x20 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_249_public_y[] = { +/* QCAVSy */ + 0x03, 0xef, 0xa5, 0x8a, 0xa3, 0xa8, 0xc6, 0xa2, 0x4f, 0x43, 0xc5, 0x58, + 0x1f, 0xec, 0x04, 0x14, 0x42, 0xae, 0x95, 0x52, 0x75, 0xdb, 0xc1, 0xd4, + 0x6d, 0x10, 0x15, 0x60, 0x59, 0xd2, 0x63, 0x7b, 0x9a, 0x82, 0x99, 0x4b, + 0x02, 0x4a, 0x24, 0x7d, 0x2a, 0x66, 0x72, 0x4b, 0xa9, 0x0d, 0x02, 0x78, + 0x7b, 0x16, 0x8b, 0x1f, 0xa1, 0xf4, 0xb6, 0x74, 0x96, 0x45, 0x40, 0x6c, + 0x43, 0x8f, 0x8d, 0x31, 0x6d, 0x67, 0x0f, 0x1e, 0x0d, 0x8b, 0x03, 0x01 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_249_private[] = { +/* dIUT */ + 0x00, 0xbd, 0x58, 0xe1, 0x9c, 0x05, 0xdf, 0x7e, 0x99, 0xbd, 0x96, 0x20, + 0x70, 0xe0, 0xb4, 0xc7, 0x57, 0x60, 0x42, 0x85, 0x84, 0x47, 0xe0, 0x23, + 0xb4, 0x1b, 0xb2, 0x97, 0x45, 0xa8, 0x9a, 0x48, 0x74, 0xdf, 0xe3, 0x25, + 0xa1, 0x5d, 0x38, 0xd2, 0xfb, 0x9e, 0x87, 0x0f, 0x41, 0x9d, 0xd1, 0x5f, + 0x4a, 0xaa, 0xc6, 0x5d, 0xbb, 0xc5, 0xac, 0x2c, 0x54, 0x0f, 0x57, 0xcd, + 0xb0, 0xe4, 0x5b, 0xc8, 0x66, 0x21, 0x72, 0x6d, 0x92, 0x2d, 0x14, 0xaa +}; +/* QIUTx = 01e4b2a277ddd78f2f119c05b6ae1ea7a2a744961e08940f6569ee8808c53bc7a12138064ed5c8c222eef2774e70c28bce3a6c05f3a654e121006ab62bc94381d01ca0d1b08234d6 */ +/* QIUTy = 07eed8cd7a8a3549b0d9ef8786879efdc9c0f4ce90b3991a33cbbb1d3704db93513138b19a50ecac880e578de21046f03a200048180884bc42cf9aafe58cc1eaf536d6d25f1541d8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_249_out[] = { +/* ZIUT */ + 0x03, 0xbf, 0x7a, 0x59, 0xbb, 0xdd, 0x68, 0x86, 0x82, 0xc4, 0x56, 0x64, + 0xd2, 0x0c, 0x19, 0xcb, 0x2d, 0x24, 0xfc, 0xca, 0x67, 0x72, 0x12, 0x0c, + 0xbe, 0xed, 0x1c, 0xde, 0x76, 0x2d, 0x44, 0x9e, 0xbf, 0x22, 0x85, 0x56, + 0x27, 0xeb, 0x6b, 0x2b, 0xe6, 0xe7, 0xf7, 0xc0, 0xf0, 0x03, 0x4d, 0x02, + 0x68, 0x6f, 0x2a, 0x44, 0x88, 0x54, 0x9f, 0x8c, 0xb1, 0x98, 0xe0, 0x2b, + 0x46, 0x97, 0x2b, 0xcb, 0x88, 0x91, 0x4b, 0xea, 0x66, 0xdd, 0x64, 0x00 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_250_public_x[] = { +/* QCAVSx */ + 0x07, 0x22, 0xf1, 0xe7, 0xa0, 0x60, 0x77, 0x50, 0xda, 0xe2, 0xd6, 0x2c, + 0x5d, 0x3d, 0x47, 0x0f, 0x00, 0x6c, 0x32, 0x54, 0x55, 0x8e, 0xaa, 0xa2, + 0x94, 0xee, 0xed, 0xbc, 0xa8, 0xd3, 0x0b, 0xf4, 0xab, 0xb9, 0x55, 0xde, + 0xb6, 0x2e, 0x41, 0x79, 0x92, 0x5f, 0x6c, 0xba, 0xdf, 0x3b, 0xf8, 0x77, + 0x6f, 0x15, 0xdc, 0xae, 0x35, 0x56, 0xad, 0xdf, 0x79, 0x71, 0x05, 0xa7, + 0x7b, 0x7f, 0x6f, 0x71, 0x20, 0x6c, 0xa0, 0xe6, 0xea, 0x91, 0xe1, 0x88 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_250_public_y[] = { +/* QCAVSy */ + 0x03, 0x5d, 0x10, 0x8c, 0xa0, 0xd6, 0x20, 0xca, 0xb9, 0x6b, 0x7c, 0xbf, + 0x61, 0x7d, 0x1b, 0x5a, 0xc0, 0x6e, 0x37, 0x79, 0x26, 0x29, 0x88, 0x65, + 0x64, 0xfd, 0x14, 0x7c, 0x58, 0xe5, 0x5e, 0x42, 0x33, 0x44, 0xff, 0x4f, + 0x1f, 0xba, 0x4a, 0xf0, 0xfe, 0x34, 0x15, 0x2b, 0x38, 0x4b, 0x76, 0x85, + 0xca, 0xad, 0x15, 0xd3, 0xbc, 0x27, 0x0e, 0x43, 0x42, 0x2a, 0xd8, 0x74, + 0xe7, 0x1e, 0x40, 0x8a, 0x71, 0xa6, 0xc8, 0xa9, 0x0d, 0x2a, 0xd9, 0x78 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_250_private[] = { +/* dIUT */ + 0x01, 0x14, 0x63, 0x07, 0x0f, 0xcb, 0x4a, 0x28, 0xbe, 0x4e, 0x2a, 0x67, + 0xc2, 0x9c, 0x7f, 0xa4, 0x8a, 0x4c, 0x58, 0x5a, 0x30, 0x74, 0x05, 0xd0, + 0x6a, 0x1a, 0x06, 0x78, 0xe9, 0x09, 0xdd, 0x6e, 0xaf, 0xb8, 0x98, 0x66, + 0x2c, 0xdd, 0x8b, 0xcc, 0x01, 0x9d, 0xeb, 0x14, 0xe5, 0xd9, 0x2d, 0x17, + 0x2b, 0xa1, 0xc4, 0x38, 0xef, 0x0f, 0x64, 0xd8, 0x01, 0x07, 0xc7, 0xe8, + 0xe6, 0x80, 0x29, 0xf4, 0xe0, 0xaa, 0x81, 0x4a, 0x10, 0x99, 0xca, 0x38 +}; +/* QIUTx = 00939398e463886f0dbb48a74f573a1215000668e10b57989dc300b2f9a8c08cd43d6cbb7f46ec77c1c294b23f86299027d2b93fd6eb18210a8230bf46e3921f182c9260c30847ab */ +/* QIUTy = 03d48ec633b9da1650ea762656b3e31f26aec07e7ca6aafc1ed7cb466eaaf3993e0467048c967bb1e9b4ae073a230c1e2f74e2e618666cf56a06f2b65ec3955b6ffbb06a908cf616 */ +static const uint8_t nist_kas_ecc_cdh_testvector_250_out[] = { +/* ZIUT */ + 0x06, 0xd4, 0x10, 0xe9, 0xba, 0x6b, 0x8b, 0x87, 0xb0, 0x0d, 0x0f, 0x67, + 0x6d, 0xe8, 0xba, 0x27, 0xf6, 0xaf, 0xe7, 0xe3, 0x08, 0xc2, 0xe9, 0x92, + 0xf3, 0x18, 0xfc, 0x14, 0xcb, 0xa0, 0xa4, 0x47, 0x31, 0x6a, 0xd8, 0x6e, + 0x8e, 0x6c, 0x1d, 0x33, 0x45, 0xd8, 0xe4, 0x03, 0x57, 0x35, 0x23, 0x2c, + 0x2c, 0x59, 0x7e, 0x76, 0x0b, 0x88, 0x00, 0xa8, 0x9a, 0x52, 0x15, 0x67, + 0xb0, 0x94, 0x08, 0xf9, 0xc7, 0xbe, 0x27, 0x9c, 0x13, 0x7c, 0x96, 0x3f +}; +/* [B-163] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_251_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x03, 0xa6, 0x47, 0xba, 0x32, 0xda, 0xc7, 0x1e, 0xc6, + 0x78, 0x0b, 0x06, 0x38, 0xa7, 0x0c, 0xd2, 0x4f, 0xc3, 0xbd, 0x4c, 0x8e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_251_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x02, 0xe6, 0x9e, 0x96, 0x15, 0x41, 0x84, 0x4a, 0x4a, + 0xa3, 0x37, 0x69, 0xa7, 0xbc, 0xe7, 0x10, 0xf6, 0x64, 0x0a, 0x56, 0x0c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_251_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0xed, 0xae, 0x17, 0x3d, 0xe8, 0xfa, 0x0c, 0xf0, + 0x41, 0x2d, 0x6a, 0x7b, 0xdc, 0x81, 0xfd, 0xbd, 0x06, 0x17, 0xad, 0xf8 +}; +/* QIUTx = 000000035466701d0b0030d098b6ed2343d355c24c907271 */ +/* QIUTy = 00000000d8bc02f341d261860dfb65f0cb7f0b488d8296cc */ +static const uint8_t nist_kas_ecc_cdh_testvector_251_out[] = { +/* ZIUT */ + 0x01, 0x00, 0xfb, 0x42, 0xd1, 0x77, 0xff, 0xe6, 0xc3, 0x13, 0x78, 0xe2, + 0xe0, 0x4e, 0x0d, 0xa7, 0x37, 0x6f, 0xfe, 0x87, 0x65 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_252_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x01, 0x28, 0x28, 0x98, 0x93, 0x64, 0x86, 0xdc, 0x2e, + 0x3c, 0xd1, 0x58, 0x5f, 0x32, 0xd5, 0x54, 0x42, 0x64, 0xe1, 0x91, 0xe4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_252_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x05, 0xe9, 0xe9, 0x8b, 0xb7, 0x49, 0x9b, 0xf8, 0x95, + 0xf7, 0x7f, 0x8f, 0xc8, 0x30, 0x1d, 0x6e, 0x1c, 0x7a, 0x9f, 0x61, 0x91 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_252_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0x78, 0xdc, 0xc8, 0x21, 0x64, 0x25, 0xd4, 0xbf, + 0x71, 0xc8, 0xf2, 0x92, 0x5d, 0xd1, 0xaf, 0x86, 0xdc, 0x04, 0xa2, 0x68 +}; +/* QIUTx = 000000011e49430cdd06f2e765b8f2cc067cd424e2e75485 */ +/* QIUTy = 0000000083af15b22cd7dfd1dff7396bf3f3038f50524991 */ +static const uint8_t nist_kas_ecc_cdh_testvector_252_out[] = { +/* ZIUT */ + 0x06, 0x81, 0xc9, 0xe5, 0x9e, 0xb7, 0xeb, 0xa7, 0x69, 0xf5, 0xb6, 0xf2, + 0xb0, 0x6d, 0xdf, 0x1e, 0xfd, 0x12, 0x99, 0x79, 0x95 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_253_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x05, 0x87, 0x4f, 0xcc, 0x8c, 0x48, 0x4c, 0x01, 0x41, + 0x73, 0x10, 0x2d, 0xcb, 0x70, 0xc6, 0x24, 0xee, 0x61, 0x08, 0xd3, 0x1d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_253_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x00, 0x49, 0x69, 0x3f, 0x4e, 0xdc, 0x71, 0x4b, 0x0d, + 0x0b, 0xaa, 0x5b, 0xfc, 0x5d, 0x8b, 0xc6, 0xac, 0x04, 0x08, 0x9d, 0xe4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_253_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0xea, 0x1e, 0x79, 0xe5, 0x2a, 0x07, 0x08, 0x98, + 0xd6, 0xa3, 0xc4, 0xe7, 0x48, 0xe9, 0x5a, 0xc8, 0x71, 0x0d, 0x77, 0xf6 +}; +/* QIUTx = 0000000137860ba3458af13c22af8225f561e01331cd87a8 */ +/* QIUTy = 00000007720356e15dc73f9fee7a1c021feca97cd41204e3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_253_out[] = { +/* ZIUT */ + 0x01, 0xe0, 0x74, 0x9a, 0x21, 0xfc, 0x50, 0x8f, 0x76, 0xda, 0xde, 0x85, + 0x43, 0x5b, 0xbb, 0xe1, 0x2c, 0x44, 0x8b, 0xd8, 0xc4 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_254_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x00, 0x37, 0x48, 0xd7, 0x98, 0xf1, 0x40, 0x26, 0x8f, + 0x1e, 0x71, 0x8b, 0x3b, 0x23, 0xaa, 0x2a, 0xcc, 0x03, 0x33, 0xc0, 0x74 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_254_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x00, 0xc4, 0x2a, 0x92, 0x7a, 0xb5, 0x79, 0x69, 0x61, + 0x23, 0x09, 0x55, 0x75, 0xac, 0x94, 0x9b, 0x07, 0xa7, 0xd1, 0xd4, 0xbc +}; +static const uint8_t nist_kas_ecc_cdh_testvector_254_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0xad, 0x5c, 0xa9, 0xab, 0xc8, 0xbc, 0xdc, 0xc4, + 0x82, 0x99, 0x5a, 0xd1, 0xa9, 0x77, 0xe4, 0x72, 0x71, 0x50, 0xbb, 0x36 +}; +/* QIUTx = 000000025ae78311b0fcf369566a319f89849546aeaec305 */ +/* QIUTy = 0000000640eb0fdf520480afbeb9f2674feb1d6df482d7f5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_254_out[] = { +/* ZIUT */ + 0x03, 0x20, 0x39, 0x8f, 0x7a, 0xcf, 0x79, 0x1e, 0x0d, 0x60, 0x2d, 0x7b, + 0x94, 0x74, 0x2c, 0xce, 0x58, 0xe9, 0xfd, 0xdb, 0xac +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_255_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0xdb, 0x3d, 0xf2, 0xb1, 0xc0, 0x15, 0x4a, + 0x8e, 0x8c, 0xb3, 0x04, 0xae, 0xcd, 0x58, 0x1d, 0x35, 0xf3, 0x15, 0xcd +}; +static const uint8_t nist_kas_ecc_cdh_testvector_255_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x07, 0x15, 0x34, 0xec, 0x2e, 0x8b, 0x35, 0x7d, 0x9e, + 0x06, 0x9d, 0x7f, 0x1f, 0xa9, 0x8b, 0xd4, 0x4e, 0xd8, 0xb0, 0x68, 0x26 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_255_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0xd2, 0x8a, 0x8a, 0xa1, 0xd8, 0x9f, 0xa3, 0xe5, + 0xe5, 0x96, 0xff, 0xd1, 0x80, 0x82, 0x54, 0xee, 0x17, 0xa0, 0xd0, 0xfa +}; +/* QIUTx = 00000006e6c52494ab63c89c9788556f716677f3b48042a0 */ +/* QIUTy = 00000004e98258b9c56f02d3edb4ca5b0aeeaa9daaa6fe0f */ +static const uint8_t nist_kas_ecc_cdh_testvector_255_out[] = { +/* ZIUT */ + 0x03, 0xe4, 0xde, 0x43, 0xde, 0x85, 0x22, 0x3d, 0x81, 0x8e, 0x5b, 0xe6, + 0x54, 0x9c, 0x29, 0xcd, 0xfa, 0x1a, 0xfe, 0x17, 0x82 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_256_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x01, 0x36, 0xe0, 0xd0, 0x5b, 0x4f, 0x39, 0x8b, 0x82, + 0x7e, 0x19, 0x80, 0x46, 0x14, 0x8b, 0x2f, 0x41, 0x57, 0x3f, 0xc0, 0x7c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_256_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x07, 0x39, 0x93, 0x4c, 0xec, 0x10, 0x57, 0x28, 0x52, + 0xe1, 0xf6, 0x19, 0x22, 0x2e, 0x2f, 0x5e, 0xc4, 0xe0, 0xfa, 0x5a, 0xa6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_256_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0xe1, 0x70, 0xf7, 0xf4, 0xdc, 0x15, 0x2f, 0xe4, + 0x70, 0x6f, 0x99, 0xd9, 0xbe, 0x22, 0x9e, 0x13, 0x17, 0xd8, 0x2b, 0xbd +}; +/* QIUTx = 00000007900dac251de8a944cf0a1bf2eb2efeee14676e9b */ +/* QIUTy = 0000000091e7df67f77622729d59b7e34b947127e7fa2e5d */ +static const uint8_t nist_kas_ecc_cdh_testvector_256_out[] = { +/* ZIUT */ + 0x03, 0x7b, 0x17, 0x8a, 0xab, 0x01, 0x4d, 0x5a, 0xba, 0xb3, 0x05, 0xe3, + 0x7d, 0xee, 0xd7, 0xf4, 0x79, 0x8c, 0xdb, 0x86, 0x2c +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_257_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x07, 0x6c, 0x3a, 0xe4, 0xa7, 0x81, 0x67, 0x36, 0x27, + 0xd0, 0xe9, 0xbc, 0xb6, 0x15, 0xf6, 0x26, 0xa1, 0x60, 0xa5, 0x5d, 0xda +}; +static const uint8_t nist_kas_ecc_cdh_testvector_257_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x05, 0x8c, 0x0e, 0xc8, 0xf2, 0x64, 0x9c, 0x2d, 0xdc, + 0xd9, 0xc2, 0x4b, 0x64, 0x34, 0x33, 0xb1, 0x4d, 0x90, 0x7c, 0x59, 0x03 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_257_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0x92, 0x3d, 0x2c, 0x80, 0x2c, 0xec, 0x42, 0xde, + 0xf2, 0x63, 0x3d, 0xeb, 0xdc, 0xa7, 0x59, 0xd5, 0x97, 0x44, 0xd3, 0xe8 +}; +/* QIUTx = 00000002cdcb4f91ed7d17768db80be2b3ac9e0956b1d971 */ +/* QIUTy = 000000032433f455a6cd253e91582d2f6f5a712655da1d69 */ +static const uint8_t nist_kas_ecc_cdh_testvector_257_out[] = { +/* ZIUT */ + 0x00, 0x95, 0x8b, 0x2a, 0xaa, 0x60, 0x61, 0x22, 0x2d, 0xd2, 0x48, 0xa6, + 0xb9, 0x70, 0x0f, 0xb6, 0x83, 0x9d, 0xac, 0xdc, 0x99 +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_258_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x00, 0xd6, 0x5f, 0x05, 0x16, 0xc1, 0xb3, 0xee, 0xd9, + 0x22, 0x0e, 0x59, 0xb3, 0xd0, 0x49, 0xdd, 0x11, 0x53, 0x17, 0x9a, 0xc5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_258_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x02, 0x0b, 0xfe, 0x10, 0x7a, 0x89, 0xa7, 0x36, 0x0c, + 0xd2, 0xe2, 0x17, 0x53, 0x4d, 0x6d, 0xf2, 0x98, 0xcc, 0x4b, 0xc4, 0x58 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_258_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0x5b, 0x17, 0xbd, 0x6e, 0x42, 0x07, 0xd9, 0xfb, + 0x1a, 0x3a, 0xf0, 0x2f, 0xd5, 0xdb, 0x26, 0xaf, 0x83, 0x48, 0xae, 0xb0 +}; +/* QIUTx = 00000006f6f5b1f3b18f45db4fb3777e6840fb5a5b61a914 */ +/* QIUTy = 0000000737ce14aeb24e0591585a7417b89256749f461de6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_258_out[] = { +/* ZIUT */ + 0x03, 0x93, 0x38, 0x7e, 0x1d, 0xab, 0x35, 0x74, 0x8f, 0x20, 0xd5, 0x06, + 0xa0, 0xe2, 0xb4, 0xdc, 0x0e, 0xe6, 0xc3, 0xff, 0x39 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_259_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x04, 0x0d, 0x90, 0x3c, 0xe2, 0xb3, 0x0f, 0x70, 0xa6, + 0xa0, 0x38, 0x49, 0xb0, 0xe1, 0x75, 0x8f, 0xef, 0x88, 0x87, 0xbd, 0x31 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_259_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x04, 0xab, 0xd8, 0xbd, 0xb7, 0xc1, 0x32, 0x7c, 0x99, + 0xb3, 0x38, 0x20, 0xdb, 0xe1, 0x8a, 0xe1, 0x14, 0xfb, 0x43, 0x59, 0x49 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_259_private[] = { +/* dIUT */ + 0x13, 0x7e, 0x81, 0x32, 0xad, 0x28, 0x89, 0x23, 0xe6, 0x48, 0x11, 0xe9, + 0x22, 0x98, 0xf5, 0xc0, 0xdc, 0xc9, 0x57, 0x05 +}; +/* QIUTx = 00000006f2cdd1d630dd731ed77f901c7b0e735515e26d4e */ +/* QIUTy = 00000001062f2f715c4d2af97bb1be8b6cfa2e3ee314253e */ +static const uint8_t nist_kas_ecc_cdh_testvector_259_out[] = { +/* ZIUT */ + 0x02, 0x12, 0x35, 0x8d, 0x3f, 0x8b, 0xce, 0x69, 0xb6, 0x62, 0x44, 0x73, + 0x33, 0xb3, 0xed, 0xbb, 0xc9, 0xb2, 0xf7, 0xe8, 0x05 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_260_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0x2e, 0xd2, 0x46, 0x43, 0xf0, 0xce, 0xc6, 0x8c, + 0x8e, 0x4a, 0xd1, 0xaa, 0x2c, 0x43, 0x69, 0xd8, 0xaa, 0x03, 0xf5, 0x94 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_260_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x05, 0xcc, 0xca, 0x62, 0xb6, 0xdd, 0x1d, 0x31, 0x6d, + 0xed, 0xbd, 0x0f, 0x1d, 0x53, 0x0b, 0xed, 0x6e, 0x55, 0x6b, 0x3a, 0xd8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_260_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0xc4, 0x8c, 0x50, 0xb7, 0xd3, 0xec, 0xdf, 0x3b, + 0x90, 0x1b, 0xad, 0x0e, 0xef, 0xc3, 0xe3, 0x82, 0x6e, 0x3c, 0xea, 0x9f +}; +/* QIUTx = 000000019175573117dd851e6eebfd9fb1e5a884ebfefee5 */ +/* QIUTy = 00000003adf37e4ded52573fa57c8cb2bfca6c65c3674462 */ +static const uint8_t nist_kas_ecc_cdh_testvector_260_out[] = { +/* ZIUT */ + 0x02, 0x34, 0x72, 0xfa, 0x59, 0x84, 0x6f, 0x7b, 0xe0, 0x7c, 0xf0, 0x60, + 0xcd, 0xd6, 0x9a, 0x9f, 0xbb, 0x27, 0xd4, 0xfe, 0x44 +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_261_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x07, 0x93, 0xf4, 0xb3, 0x11, 0x72, 0xee, 0xe6, 0x6f, + 0x27, 0x69, 0xeb, 0x30, 0x5d, 0x03, 0xb5, 0xc3, 0xf7, 0xcf, 0xff, 0x8b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_261_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x01, 0xf3, 0xec, 0xec, 0x6b, 0xbd, 0xa9, 0xbd, 0xe8, + 0xa4, 0xda, 0x14, 0xdb, 0x3e, 0x5f, 0xf9, 0x34, 0xb9, 0x83, 0x5b, 0x17 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_261_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0x16, 0x2d, 0x9e, 0xd3, 0xa6, 0x60, 0x45, 0x5e, + 0x8c, 0x01, 0x5d, 0x1e, 0x45, 0xd1, 0x51, 0x57, 0x49, 0xa3, 0xdc, 0xd2 +}; +/* QIUTx = 00000004283eb0e5085d198b378fc95f6fb4c3198b4d3c78 */ +/* QIUTy = 0000000107a1168f2f47b963e4b3a9024e0c357a5ebdf92c */ +static const uint8_t nist_kas_ecc_cdh_testvector_261_out[] = { +/* ZIUT */ + 0x01, 0x73, 0xa0, 0x56, 0xc4, 0xc9, 0xef, 0x67, 0x07, 0xcd, 0x23, 0x92, + 0x89, 0x99, 0xc4, 0x68, 0x0f, 0x42, 0xb7, 0x1f, 0x7c +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_262_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0xea, 0x7a, 0x50, 0x83, 0x46, 0x02, 0xf1, 0x12, + 0xf6, 0xdd, 0x0e, 0x6d, 0x25, 0xf0, 0x64, 0xf9, 0xd0, 0x5e, 0xff, 0x26 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_262_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x01, 0xbf, 0x3f, 0x69, 0xd1, 0x4a, 0xcc, 0x83, 0x33, + 0x53, 0x3a, 0x88, 0xc2, 0xe8, 0x82, 0x48, 0x63, 0xa4, 0x7a, 0xe0, 0x27 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_262_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0x9a, 0x1d, 0x16, 0xf4, 0xa5, 0x72, 0xf3, 0xc1, + 0xb5, 0x1e, 0xa2, 0xac, 0xe6, 0x92, 0x80, 0xe7, 0x13, 0x7b, 0x8f, 0x8c +}; +/* QIUTx = 00000005cede96a70f714cd68963f2d6ca236269a938f311 */ +/* QIUTy = 00000006cdadd54b6f733c80934787e28c2ccf58b1227bc0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_262_out[] = { +/* ZIUT */ + 0x03, 0xd3, 0x4f, 0x41, 0x1a, 0x29, 0x7d, 0x7c, 0x99, 0x0f, 0xa4, 0xa8, + 0x3b, 0x5f, 0x54, 0x75, 0x96, 0x07, 0xf9, 0xd3, 0x3f +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_263_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x06, 0xdd, 0x13, 0x05, 0x34, 0x9e, 0x8a, 0xa0, 0x80, + 0x20, 0x07, 0x3a, 0x0d, 0xe5, 0xaf, 0xc5, 0xdc, 0x1b, 0x6a, 0x62, 0xd3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_263_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x03, 0x49, 0x7e, 0xb7, 0xbf, 0x40, 0x89, 0xef, 0x02, + 0xcd, 0x0a, 0x5d, 0xd0, 0xf8, 0x6b, 0xd8, 0x79, 0x8a, 0x44, 0xc5, 0x6c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_263_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0xef, 0xd4, 0x40, 0x0d, 0xad, 0x3c, 0xfa, 0xd8, + 0xd1, 0x63, 0x7f, 0xa9, 0x29, 0x0c, 0x4b, 0x75, 0x8a, 0x30, 0x15, 0xb6 +}; +/* QIUTx = 0000000513131b4bcb72ef68ab043ee84fc8cb03b6d8f187 */ +/* QIUTy = 0000000120b7d5772bbb17ecb1c9e80c36f808fd54a93aae */ +static const uint8_t nist_kas_ecc_cdh_testvector_263_out[] = { +/* ZIUT */ + 0x06, 0x12, 0x0a, 0xed, 0x8d, 0x4c, 0x1e, 0x50, 0x67, 0x10, 0xe2, 0xcf, + 0xb9, 0x8c, 0xa2, 0x02, 0x2e, 0x64, 0x2c, 0xa8, 0x9f +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_264_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x05, 0xa0, 0xe3, 0x41, 0x11, 0x8e, 0x69, 0x82, 0x7d, + 0x6a, 0x7f, 0x82, 0x82, 0xfb, 0xf0, 0xb9, 0x44, 0x00, 0xf0, 0x82, 0x40 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_264_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x04, 0x23, 0xb9, 0x93, 0xd4, 0x36, 0x7f, 0xbf, 0x4f, + 0x65, 0x04, 0xd9, 0xe0, 0x9a, 0x64, 0x12, 0x3a, 0x3b, 0x53, 0xd1, 0x28 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_264_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0x2b, 0x0d, 0x64, 0x97, 0x7c, 0xfc, 0x13, 0xb4, + 0x83, 0x45, 0xef, 0x70, 0x72, 0xd1, 0xa3, 0x89, 0x0e, 0xaf, 0xb9, 0x5b +}; +/* QIUTx = 00000001b9363cf48735676878d80ce1481b8588683f7444 */ +/* QIUTy = 0000000768fa7327cd7252c8f696ed4947868915ada1fb5d */ +static const uint8_t nist_kas_ecc_cdh_testvector_264_out[] = { +/* ZIUT */ + 0x02, 0x1a, 0x58, 0x08, 0x79, 0x68, 0xc5, 0xdf, 0x57, 0xaf, 0xd7, 0xc3, + 0x43, 0xa4, 0xcf, 0xa2, 0xee, 0x8e, 0x70, 0x73, 0xf1 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_265_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x00, 0x1a, 0x92, 0x3d, 0x61, 0x91, 0x63, 0x43, 0x06, + 0x12, 0x4c, 0x1e, 0x26, 0x73, 0x09, 0xb0, 0x7d, 0xba, 0x32, 0xde, 0xcb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_265_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x05, 0xa3, 0x51, 0x7f, 0x54, 0x26, 0xa3, 0x41, 0x1a, + 0x72, 0x7e, 0xdd, 0xc2, 0x9a, 0x3e, 0xc2, 0x29, 0x55, 0x83, 0x68, 0xd1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_265_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x3a, 0xc9, 0x53, 0x80, 0x3d, 0x04, 0x46, 0xb3, + 0xcd, 0xa4, 0xeb, 0xd0, 0x71, 0xb4, 0xeb, 0x02, 0x7c, 0x11, 0xbf, 0xd8 +}; +/* QIUTx = 00000005c446e9896ca44cca733e9f4e5b64afddc0537211 */ +/* QIUTy = 00000006bad1b2522692f970b38be6935dc7d1c09dcd206f */ +static const uint8_t nist_kas_ecc_cdh_testvector_265_out[] = { +/* ZIUT */ + 0x03, 0xda, 0x9c, 0x08, 0x79, 0x21, 0x9e, 0x48, 0xc3, 0xdf, 0x56, 0x17, + 0x48, 0x98, 0xfa, 0xb9, 0xee, 0x5b, 0x0a, 0x6b, 0xcd +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_266_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x02, 0xfa, 0x8b, 0xaf, 0x0d, 0x61, 0x28, 0xad, 0xd9, + 0xb9, 0x02, 0xaa, 0x18, 0x1c, 0x81, 0xe2, 0x42, 0x98, 0x45, 0x1e, 0x2e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_266_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x02, 0xb9, 0x3d, 0x1f, 0x69, 0x13, 0x91, 0x4f, 0xfe, + 0x15, 0x59, 0xc7, 0xc1, 0x14, 0xc6, 0x31, 0xbb, 0x6b, 0x29, 0x61, 0x7e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_266_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x01, 0xbd, 0x79, 0x14, 0x5a, 0xe7, 0xf4, 0x2c, 0x6b, + 0x25, 0xd1, 0xc3, 0x89, 0x65, 0xec, 0x08, 0xfd, 0x27, 0x53, 0x3a, 0x7a +}; +/* QIUTx = 00000000e9d8fc3a026925c8add508f920fa2e5ff5282688 */ +/* QIUTy = 00000005b7bf631259ac7d36936c130ff206d820b13bde81 */ +static const uint8_t nist_kas_ecc_cdh_testvector_266_out[] = { +/* ZIUT */ + 0x05, 0xb3, 0x3f, 0xe3, 0x87, 0x4d, 0x32, 0xae, 0xd9, 0x99, 0x19, 0x26, + 0x5c, 0xc0, 0x07, 0x49, 0x02, 0xe5, 0x38, 0xfe, 0x54 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_267_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x03, 0x53, 0xe2, 0xda, 0x45, 0xab, 0x7c, 0x49, 0x30, + 0x28, 0x0c, 0x3e, 0xdb, 0x4b, 0xa9, 0x00, 0x12, 0xd5, 0x6d, 0xf6, 0x2f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_267_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x02, 0x69, 0x31, 0xe3, 0x0b, 0x97, 0xff, 0x5e, 0xf7, + 0xba, 0xcc, 0x0d, 0xe4, 0xd9, 0x49, 0x07, 0x08, 0x52, 0x2e, 0x3b, 0x2b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_267_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x30, 0xca, 0x1f, 0x5a, 0xd7, 0x7d, 0x7a, 0x66, + 0xd8, 0x74, 0x23, 0x32, 0x80, 0x20, 0xc9, 0x1e, 0xc7, 0x9f, 0x37, 0x64 +}; +/* QIUTx = 00000005ba37d36997c4f2abe603dfe042232738e82b0b3a */ +/* QIUTy = 000000073c8cd950044972a005c6f1af8e4306e0ccefb946 */ +static const uint8_t nist_kas_ecc_cdh_testvector_267_out[] = { +/* ZIUT */ + 0x05, 0x3d, 0xbc, 0xe9, 0x82, 0x6a, 0xf4, 0xd2, 0x90, 0x03, 0x6f, 0xeb, + 0x46, 0x87, 0x5e, 0x97, 0x5b, 0x78, 0x48, 0xa9, 0xc4 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_268_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x07, 0x21, 0x67, 0x08, 0x84, 0xda, 0xa8, 0xcd, 0x62, + 0x76, 0x38, 0xec, 0x90, 0xf3, 0x44, 0x8e, 0xfb, 0x0f, 0x24, 0x89, 0xba +}; +static const uint8_t nist_kas_ecc_cdh_testvector_268_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x04, 0xf8, 0x4a, 0x98, 0x3b, 0xec, 0x6b, 0x28, 0x89, + 0xc8, 0x21, 0x1b, 0xf2, 0x31, 0x14, 0x9b, 0x5b, 0xeb, 0xcc, 0x75, 0xe0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_268_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0xd2, 0x31, 0x40, 0x07, 0x4d, 0x6e, 0xdd, 0xd5, + 0xbc, 0x09, 0x9b, 0x17, 0xde, 0x12, 0xaf, 0xb9, 0xdd, 0xf2, 0xec, 0xbe +}; +/* QIUTx = 00000006e06cc7c30f5ed7e686c3a75a1d44257770601cb2 */ +/* QIUTy = 000000030dc414c4afb390ed467af471aa9bd2b75f32dfd8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_268_out[] = { +/* ZIUT */ + 0x00, 0xd4, 0x9b, 0x97, 0x1c, 0xab, 0x93, 0x7f, 0x40, 0x90, 0x89, 0x13, + 0xfe, 0x25, 0x98, 0x49, 0x67, 0x9c, 0xa0, 0x76, 0xd9 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_269_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x01, 0xd6, 0x31, 0x9e, 0xc2, 0xdc, 0x5c, 0x08, 0xf0, + 0x26, 0x1a, 0xed, 0x02, 0x31, 0x41, 0x8d, 0x6d, 0xc3, 0xd0, 0xcd, 0xa7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_269_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x03, 0x8e, 0x64, 0x95, 0x3f, 0x7c, 0xda, 0xc7, 0x1d, + 0x05, 0x2e, 0x55, 0x85, 0x57, 0x46, 0xb4, 0x3d, 0x44, 0x18, 0x1b, 0x91 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_269_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0x44, 0x9c, 0x1b, 0x9f, 0xf0, 0x9e, 0x7a, 0x9a, + 0x03, 0xb1, 0x7f, 0x5f, 0xf4, 0x61, 0x11, 0x5f, 0x5f, 0x3f, 0x1a, 0x7f +}; +/* QIUTx = 000000073f9ddddc4650933deccc9546d392a35dbbc66a76 */ +/* QIUTy = 00000004de7558dde649f72322b39e31c8e29ce6f599485e */ +static const uint8_t nist_kas_ecc_cdh_testvector_269_out[] = { +/* ZIUT */ + 0x04, 0x83, 0xad, 0x0b, 0x7f, 0x8a, 0x71, 0x62, 0x73, 0xf6, 0x24, 0xb8, + 0x97, 0x9c, 0x19, 0x12, 0x67, 0x05, 0x26, 0x6e, 0x4b +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_270_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x04, 0xf1, 0x67, 0x90, 0x7b, 0xf4, 0xb9, 0x8e, 0x86, + 0x96, 0xd8, 0x1d, 0xa7, 0xd2, 0xc1, 0x05, 0x6e, 0xfa, 0x0d, 0xc1, 0x4c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_270_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x06, 0xcb, 0x9a, 0xb6, 0x51, 0x43, 0x83, 0x2b, 0x9c, + 0xef, 0xd5, 0xd9, 0xce, 0x69, 0xec, 0x4d, 0xb2, 0xed, 0xd0, 0x67, 0xaa +}; +static const uint8_t nist_kas_ecc_cdh_testvector_270_private[] = { +/* dIUT */ + 0xd0, 0x8b, 0x95, 0xd9, 0xa4, 0xce, 0x72, 0x4e, 0xc4, 0x62, 0xcc, 0xe1, + 0x27, 0x01, 0xfd, 0x8c, 0x3d, 0x53, 0xfd, 0xcd +}; +/* QIUTx = 0000000026a770d86e1c89ba7a86aef649ba7ea86fc7d5b2 */ +/* QIUTy = 00000001db1020e0f764df54a53c23c938cec98d9a77ad1d */ +static const uint8_t nist_kas_ecc_cdh_testvector_270_out[] = { +/* ZIUT */ + 0x00, 0xf6, 0x9d, 0xcb, 0x54, 0x71, 0x19, 0xfc, 0x9b, 0x8c, 0x45, 0x43, + 0x35, 0xaa, 0xb1, 0x84, 0xc3, 0xad, 0xa5, 0xf1, 0xc6 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_271_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x07, 0x9b, 0x6d, 0x14, 0xc7, 0x43, 0x27, 0x14, 0x02, + 0xd1, 0x32, 0x36, 0x03, 0x21, 0x5f, 0xeb, 0x3c, 0x68, 0xb1, 0x44, 0x55 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_271_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x04, 0xe3, 0x90, 0x56, 0x86, 0xa5, 0x38, 0xc2, 0x5a, + 0x02, 0xbe, 0xa9, 0x2f, 0x42, 0x18, 0x40, 0x21, 0xb5, 0xea, 0x25, 0x93 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_271_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x80, 0x8e, 0xfe, 0x6a, 0xd5, 0x0d, 0x25, 0x0d, + 0x87, 0x19, 0x2e, 0x16, 0x49, 0x9c, 0xe3, 0x25, 0x94, 0x28, 0xf3, 0xb8 +}; +/* QIUTx = 0000000013a02e25fc927875afa557bd673f65870459e671 */ +/* QIUTy = 00000004038dbae5c5e54084708a24bc3fd072e769c12377 */ +static const uint8_t nist_kas_ecc_cdh_testvector_271_out[] = { +/* ZIUT */ + 0x01, 0xbc, 0x5e, 0xe5, 0x26, 0x1b, 0x2b, 0xba, 0x55, 0xb1, 0x0c, 0xba, + 0xa6, 0xcc, 0x3c, 0x97, 0xb9, 0x8d, 0x00, 0xff, 0xea +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_272_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x07, 0x72, 0xf4, 0x2d, 0x27, 0x2a, 0x05, 0x7d, 0xe0, + 0xff, 0x92, 0x6c, 0x9f, 0x94, 0x60, 0x5c, 0x66, 0x75, 0xd2, 0x15, 0x26 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_272_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x06, 0x02, 0xe7, 0xe5, 0x32, 0x55, 0xde, 0x9b, 0xf5, + 0x8c, 0x05, 0x7e, 0xef, 0xb7, 0x9b, 0xce, 0x43, 0x1b, 0x5c, 0x38, 0x08 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_272_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x02, 0xad, 0x23, 0x2a, 0x7a, 0x41, 0xe6, 0xcc, 0x24, + 0x95, 0x53, 0x8d, 0x87, 0xb0, 0x23, 0xcd, 0xec, 0x7b, 0x6e, 0x1f, 0x23 +}; +/* QIUTx = 0000000549e30780d93f796fdcf691905575d85c66453bdb */ +/* QIUTy = 00000002162a885bea31344543f5d06191369dec6e70e967 */ +static const uint8_t nist_kas_ecc_cdh_testvector_272_out[] = { +/* ZIUT */ + 0x00, 0x85, 0x74, 0xd8, 0x38, 0xd3, 0xde, 0x87, 0x96, 0x5f, 0xc1, 0xb4, + 0x34, 0x3f, 0xe4, 0xf0, 0x78, 0x58, 0x8c, 0x4e, 0xa1 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_273_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x05, 0x0b, 0x24, 0x29, 0x46, 0x09, 0x71, 0x73, 0x9a, + 0x9d, 0x6d, 0x56, 0x70, 0xbc, 0x6d, 0x75, 0x9e, 0x56, 0x56, 0x76, 0x8b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_273_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x04, 0x92, 0xbc, 0x2d, 0x3f, 0x63, 0x8d, 0x49, 0x78, + 0xe4, 0xca, 0x58, 0xca, 0x5a, 0x4e, 0xf1, 0x9c, 0x5e, 0xcc, 0xea, 0x8d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_273_private[] = { +/* dIUT */ + 0xdc, 0x99, 0xb1, 0x9f, 0x3d, 0x88, 0x47, 0x87, 0x51, 0x90, 0xe9, 0x58, + 0x8b, 0x2b, 0xbd, 0x83, 0x0d, 0xbd, 0x3a, 0x95 +}; +/* QIUTx = 00000000f65d984d71dcc18bf172abe4d3993ce0f7cf324c */ +/* QIUTy = 000000001b49e6a2cf1173aadac3af6c09e966f31141abd9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_273_out[] = { +/* ZIUT */ + 0x04, 0x57, 0x9b, 0x47, 0x7a, 0x92, 0xed, 0x96, 0x1c, 0xfd, 0xb2, 0x01, + 0x44, 0x07, 0xe8, 0x8e, 0x77, 0x16, 0x45, 0x2a, 0x4b +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_274_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x01, 0x7d, 0x52, 0x11, 0x6f, 0x0c, 0x95, 0x58, 0x7f, + 0x1b, 0x7b, 0x06, 0xc7, 0x6e, 0x98, 0xd9, 0x9c, 0x82, 0xdc, 0xf2, 0x0c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_274_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x02, 0x4e, 0xa2, 0x2b, 0xdd, 0x99, 0x0b, 0xd7, 0x9e, + 0x63, 0xe7, 0x35, 0xb2, 0x12, 0x82, 0xae, 0x1b, 0x5e, 0xa6, 0x66, 0x48 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_274_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x03, 0x56, 0xab, 0x85, 0xb0, 0x4d, 0x08, 0x51, 0xb8, + 0xf6, 0x6b, 0x4a, 0x79, 0x65, 0x26, 0xd3, 0xf3, 0xe3, 0x88, 0x28, 0x44 +}; +/* QIUTx = 0000000776a2e1af932d74519070bfa941eaa93e9ff5e97a */ +/* QIUTy = 00000005abe9ed46245fd0146250d2a563c46ebf7acd2342 */ +static const uint8_t nist_kas_ecc_cdh_testvector_274_out[] = { +/* ZIUT */ + 0x03, 0x5a, 0x8c, 0x10, 0xe6, 0x44, 0x03, 0xc5, 0x2e, 0xf8, 0xd1, 0x7c, + 0x5f, 0x4d, 0xea, 0xd0, 0xdf, 0x81, 0xfb, 0x1f, 0x21 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_275_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x03, 0xa7, 0xea, 0x10, 0xba, 0x1d, 0x6a, 0xa5, 0x45, + 0x70, 0x0b, 0x40, 0xb7, 0x37, 0x95, 0x1a, 0x9e, 0x73, 0x6d, 0xfa, 0x0c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_275_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x04, 0xf9, 0x35, 0x2f, 0xb2, 0xac, 0x24, 0x44, 0xe9, + 0x28, 0x75, 0x4e, 0x36, 0x55, 0xfd, 0x62, 0xe3, 0xa4, 0x25, 0x64, 0xe8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_275_private[] = { +/* dIUT */ + 0x7a, 0x7b, 0x54, 0x75, 0x50, 0xc7, 0x58, 0xa9, 0xde, 0x7f, 0x06, 0xe2, + 0xf3, 0x8e, 0x55, 0xf5, 0xe9, 0xe4, 0x4c, 0xe6 +}; +/* QIUTx = 000000045952c0b517e685cab09470327f9d4b212751b049 */ +/* QIUTy = 000000044a429a6efb04bcea0240ab5805de740aa61f994e */ +static const uint8_t nist_kas_ecc_cdh_testvector_275_out[] = { +/* ZIUT */ + 0x00, 0x01, 0x42, 0x61, 0x5e, 0x36, 0x07, 0xac, 0x14, 0x8c, 0x4d, 0xe8, + 0xf3, 0x34, 0xbe, 0x84, 0x92, 0x35, 0xd0, 0x1c, 0xdb +}; +/* [B-233] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_276_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x47, 0x56, 0xba, 0xdd, 0xef, 0xc3, 0xdc, 0x33, 0x7a, + 0xb2, 0x7b, 0x54, 0x52, 0xeb, 0x10, 0xaf, 0xfd, 0x9e, 0x31, 0xf5, 0xb5, + 0x5c, 0x33, 0x0e, 0x90, 0xf0, 0xf6, 0x86, 0xa2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_276_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x2a, 0x79, 0xf6, 0x52, 0x32, 0x30, 0x8a, 0x21, 0xc9, + 0x8c, 0x01, 0x55, 0x5c, 0xca, 0xfc, 0x7d, 0xce, 0x15, 0xc8, 0xfe, 0xd3, + 0x02, 0x5a, 0x76, 0x0c, 0xbd, 0x6c, 0x23, 0x27 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_276_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x3c, 0x3e, 0xe4, 0x74, 0xac, 0x0d, 0x0b, 0xc1, 0xdf, + 0x56, 0x7e, 0x3c, 0x35, 0xf5, 0xf7, 0x66, 0xc5, 0x33, 0x2b, 0x2d, 0x67, + 0x30, 0xff, 0x0e, 0x4d, 0x8e, 0x75, 0xae, 0xdb +}; +/* QIUTx = 00000061e8a9b517fd05a026ec376616229fd8639a1fa76defe5398022f9d9c8 */ +/* QIUTy = 000000706b5cb08738a94552fee584b1372fead4af79040909fcf6f50084bbfa */ +static const uint8_t nist_kas_ecc_cdh_testvector_276_out[] = { +/* ZIUT */ + 0x00, 0xe9, 0xf3, 0xd8, 0xc4, 0xf1, 0xbe, 0xc0, 0xf9, 0x20, 0xe7, 0x63, + 0xea, 0x1b, 0xb7, 0x41, 0x58, 0x99, 0xf0, 0x17, 0x34, 0x60, 0x9e, 0x75, + 0x47, 0xdc, 0x42, 0x5e, 0xc9, 0x46 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_277_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x18, 0x6a, 0x02, 0x8f, 0x9a, 0x18, 0xdb, 0x92, 0x7f, + 0x63, 0x25, 0x3c, 0x20, 0x3e, 0xb2, 0x6a, 0xa3, 0xab, 0xa0, 0xd4, 0x0b, + 0x1a, 0x3a, 0xbc, 0x64, 0xe4, 0x7a, 0x22, 0xad +}; +static const uint8_t nist_kas_ecc_cdh_testvector_277_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xcb, 0xd8, 0xb9, 0x5f, 0x89, 0xe4, 0x21, 0x12, 0x8b, + 0xc7, 0x3a, 0x43, 0xc5, 0xcc, 0x25, 0x4e, 0x38, 0x67, 0x09, 0x6a, 0xb8, + 0x9d, 0x78, 0x8b, 0x2e, 0xd3, 0xb9, 0x0a, 0x96 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_277_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xaa, 0x41, 0xa5, 0xa0, 0x1a, 0x4e, 0x66, 0xa6, 0x79, + 0x97, 0xb0, 0xbe, 0x16, 0xf5, 0x6b, 0x16, 0x0b, 0x05, 0x61, 0xad, 0x07, + 0xf3, 0xaf, 0x29, 0x64, 0x38, 0x64, 0x61, 0xd0 +}; +/* QIUTx = 0000002d91402446557068c40fc075dee93916b0f1a9392e47e56b747125ae1f */ +/* QIUTy = 0000013ab0915e4acf779516826fa1dc1885a06abc5d0809c92240ccf9c3d8a4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_277_out[] = { +/* ZIUT */ + 0x00, 0xf1, 0xfb, 0xec, 0xfa, 0xdb, 0x15, 0x8d, 0x62, 0xeb, 0x11, 0x09, + 0xc0, 0x85, 0x12, 0x4f, 0xad, 0x67, 0xa8, 0x79, 0x5b, 0x58, 0x81, 0x5e, + 0xb3, 0x96, 0xc9, 0x5d, 0xb4, 0xb9 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_278_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x93, 0xbf, 0x85, 0x62, 0x16, 0x02, 0x23, 0x8e, 0x98, + 0xd0, 0x9c, 0x98, 0x82, 0x8d, 0x51, 0xa4, 0x94, 0x60, 0x36, 0x2c, 0x23, + 0xc5, 0x14, 0x1d, 0x3d, 0x1b, 0x23, 0x52, 0x96 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_278_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x84, 0x97, 0x15, 0x21, 0x87, 0xa8, 0xb3, 0xb2, 0x95, + 0x8a, 0x1d, 0x0a, 0x2e, 0xec, 0xff, 0x44, 0x92, 0x25, 0x18, 0x07, 0xcb, + 0xfd, 0x03, 0xd5, 0xf2, 0x68, 0x5b, 0xca, 0x37 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_278_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xc6, 0x67, 0x7c, 0x28, 0x06, 0x8b, 0x46, 0x2e, 0x34, + 0x86, 0x2c, 0xe6, 0xc9, 0xd8, 0xad, 0x8c, 0x1b, 0x3c, 0x7e, 0xfe, 0x80, + 0xcb, 0xab, 0x41, 0xda, 0x41, 0x92, 0x78, 0xe4 +}; +/* QIUTx = 00000042cb311dcff2482a2cece696c1eb64c69ac2aa599209a5c18763a3150a */ +/* QIUTy = 000001b0329f36c135d002f08be3e3ffa9da18c5d6a70c360f4f871f12bf3f95 */ +static const uint8_t nist_kas_ecc_cdh_testvector_278_out[] = { +/* ZIUT */ + 0x01, 0x9e, 0xa8, 0x31, 0xc5, 0x1d, 0x88, 0xa7, 0xcf, 0x75, 0x44, 0x95, + 0xa1, 0xc4, 0x74, 0x08, 0x2e, 0xd4, 0x81, 0xc8, 0xeb, 0x83, 0x19, 0x0a, + 0x77, 0xde, 0xfb, 0x09, 0xd4, 0x79 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_279_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x45, 0x49, 0x64, 0x86, 0x92, 0xaf, 0x95, 0xd8, 0x8e, + 0x4e, 0x1d, 0x49, 0x14, 0xd8, 0xc9, 0x76, 0x9a, 0xad, 0xac, 0x5a, 0x0f, + 0x75, 0x78, 0x32, 0x65, 0xf3, 0xeb, 0x96, 0x57 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_279_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0xb0, 0x94, 0xb4, 0x80, 0x2f, 0x39, 0x76, 0x63, 0xd0, + 0xe6, 0x82, 0xfa, 0xbf, 0x1c, 0x94, 0xc4, 0xe2, 0x14, 0xe4, 0x83, 0x27, + 0xb9, 0x5e, 0xef, 0xcb, 0x92, 0xb7, 0x71, 0xfd +}; +static const uint8_t nist_kas_ecc_cdh_testvector_279_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x9c, 0x61, 0x02, 0x4b, 0x3d, 0xff, 0x21, 0x9b, 0x37, + 0xf1, 0xbe, 0x67, 0x01, 0x80, 0x4a, 0xdf, 0x24, 0x74, 0x14, 0x44, 0x8d, + 0xd0, 0xf0, 0xdc, 0x51, 0x29, 0x3a, 0xc9, 0x13 +}; +/* QIUTx = 000000124120d8409850e71e33c9e2d9c40ea32bed11d77804786e9b076892ab */ +/* QIUTy = 0000006dae1ba4817296ff63073bac9ce065d4331ba1a5c899cc1c07405dae3e */ +static const uint8_t nist_kas_ecc_cdh_testvector_279_out[] = { +/* ZIUT */ + 0x00, 0x08, 0x84, 0x25, 0xfb, 0x04, 0xc2, 0xce, 0x40, 0x8f, 0x08, 0xd8, + 0x13, 0x85, 0xa3, 0x22, 0x70, 0x3a, 0x07, 0x7b, 0xf0, 0x0b, 0xa0, 0x79, + 0x1e, 0x4e, 0x79, 0xb8, 0x04, 0x19 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_280_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x73, 0xc5, 0xcf, 0x4a, 0x01, 0xd0, 0x9e, 0x3b, 0x41, + 0xb5, 0xe7, 0x77, 0x8c, 0x6b, 0x9b, 0xa5, 0x2d, 0xaf, 0x88, 0xfc, 0x40, + 0x4f, 0x8e, 0x2f, 0xd0, 0x9d, 0xb4, 0x02, 0x7e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_280_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x70, 0x39, 0x1e, 0xda, 0xa7, 0x6f, 0x0e, 0x39, 0x70, + 0x39, 0x4c, 0xac, 0x03, 0x38, 0x06, 0x10, 0x58, 0x85, 0x8c, 0x3c, 0x73, + 0xd5, 0xcb, 0x51, 0x2e, 0x53, 0x26, 0x30, 0x4f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_280_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x6e, 0x69, 0xd0, 0x64, 0xdb, 0xd9, 0xa7, 0x94, 0xf6, + 0x8e, 0x69, 0x9a, 0x0e, 0x94, 0x1b, 0xdd, 0xa6, 0xa5, 0x3a, 0x1c, 0xec, + 0xa3, 0xb3, 0xdb, 0x82, 0x92, 0x5b, 0x6f, 0x8b +}; +/* QIUTx = 000000c57d61fcb1fee90d5d8c97cbf188c8ef8259b0ae2587ecf1ff8cd2e2fa */ +/* QIUTy = 000000b8ad86c6805a4ab44513dbba2f5098b9e9c1e05b679f52937aece2b182 */ +static const uint8_t nist_kas_ecc_cdh_testvector_280_out[] = { +/* ZIUT */ + 0x01, 0x9b, 0x5e, 0xfb, 0x23, 0xbc, 0x18, 0xa4, 0xf1, 0x8c, 0x22, 0xfe, + 0x2f, 0xd5, 0xcd, 0xbd, 0x02, 0x37, 0x2c, 0xab, 0xde, 0x5e, 0x5c, 0x9f, + 0x4b, 0x4f, 0x9a, 0x49, 0x43, 0x8f +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_281_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x23, 0xa6, 0xb0, 0x81, 0xa7, 0x61, 0xe8, 0x6c, 0x04, + 0x2e, 0x19, 0x14, 0xaf, 0x47, 0xf0, 0x93, 0xb2, 0x65, 0x55, 0x43, 0xe5, + 0x64, 0x58, 0x4b, 0x60, 0x64, 0x25, 0x39, 0xa9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_281_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x51, 0x8e, 0xe3, 0xc1, 0xae, 0x54, 0x64, 0x04, 0xdf, + 0x1e, 0xcc, 0xd6, 0x9a, 0xa6, 0x85, 0x64, 0x31, 0xd1, 0xc8, 0x88, 0x1c, + 0xf0, 0x57, 0x8c, 0xff, 0x4e, 0xb8, 0xc1, 0x1b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_281_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x5a, 0xe5, 0xde, 0x30, 0xc7, 0xc3, 0x17, 0x18, 0x13, + 0xa2, 0xdd, 0x3e, 0x3e, 0xa2, 0xc5, 0xce, 0xaa, 0x04, 0x73, 0xc3, 0x94, + 0x57, 0xe9, 0x92, 0x90, 0x71, 0xe1, 0xa4, 0x20 +}; +/* QIUTx = 0000017cf9fca05d4a55e4b68fee7a3bd43f047303f2a266d81bb5e1ec7e2558 */ +/* QIUTy = 0000003b0af43de05003397de1d4b27827ad2fcd675cbf61a445a1ec40a569b6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_281_out[] = { +/* ZIUT */ + 0x01, 0xf3, 0x6d, 0x95, 0x19, 0xc3, 0xd4, 0x7f, 0x03, 0x0e, 0xea, 0xc3, + 0x33, 0x8d, 0xb5, 0x83, 0xb9, 0x6f, 0xef, 0xa5, 0x51, 0xa4, 0xb5, 0x6c, + 0xc5, 0x56, 0x7f, 0x2d, 0x9d, 0x7a +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_282_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x41, 0xfb, 0xbf, 0x2b, 0x36, 0x1c, 0x2c, 0x8c, 0xe5, + 0xed, 0xab, 0xfa, 0x22, 0xaa, 0x47, 0x55, 0x58, 0x1e, 0x5b, 0x1a, 0x66, + 0x60, 0x03, 0x62, 0xa0, 0xee, 0x7b, 0xc5, 0x74 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_282_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0xae, 0xa3, 0xca, 0xc2, 0x03, 0xf8, 0xc7, 0x80, 0x47, + 0x5a, 0x26, 0x09, 0xb2, 0x97, 0x0c, 0xc8, 0x6f, 0x96, 0xea, 0x40, 0x11, + 0xc3, 0x48, 0xda, 0x82, 0x62, 0xb3, 0x34, 0xaa +}; +static const uint8_t nist_kas_ecc_cdh_testvector_282_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xc6, 0x87, 0x96, 0x95, 0x5b, 0x68, 0xb5, 0xf8, 0x82, + 0x7e, 0x38, 0xac, 0x07, 0x82, 0xb1, 0xac, 0x2c, 0x45, 0x52, 0xca, 0xef, + 0x0c, 0x60, 0x95, 0x84, 0x67, 0xcd, 0x85, 0xc1 +}; +/* QIUTx = 00000034789fbc60f1086034c8f2ce86fd4aa335194c9146890357dc475699e4 */ +/* QIUTy = 000001d37f796327f71ec31510468463d0b2905488a4a60267870dfee567c250 */ +static const uint8_t nist_kas_ecc_cdh_testvector_282_out[] = { +/* ZIUT */ + 0x00, 0xe5, 0x4b, 0x1c, 0x91, 0x6f, 0xf3, 0xba, 0x1a, 0xa0, 0xb2, 0xb9, + 0x9f, 0x0e, 0xbd, 0xe4, 0xf1, 0xa4, 0xcc, 0x6a, 0x10, 0xd9, 0x59, 0xbb, + 0x2f, 0x7f, 0x4c, 0x77, 0x7b, 0x84 +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_283_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x96, 0xa0, 0xd3, 0xf3, 0x6e, 0x8f, 0x75, 0x37, 0x91, + 0x07, 0x4c, 0xea, 0x69, 0x7b, 0x24, 0x71, 0x62, 0x7e, 0x0c, 0x9e, 0x7a, + 0x29, 0x4a, 0x02, 0x9a, 0x9d, 0x3b, 0x94, 0x29 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_283_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xb7, 0x67, 0x17, 0x4a, 0x29, 0x20, 0xb6, 0x2f, 0x1f, + 0x02, 0xfa, 0x79, 0x09, 0x78, 0x45, 0xd5, 0x1d, 0x93, 0xe0, 0xc8, 0x10, + 0x44, 0x10, 0x83, 0x1a, 0x2d, 0xd5, 0x5c, 0x3c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_283_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x74, 0x24, 0x5c, 0xc9, 0x7d, 0xd4, 0x50, 0x93, 0x56, + 0x89, 0xea, 0x3f, 0xca, 0x7b, 0x0b, 0x30, 0xc1, 0xd6, 0x7c, 0xe6, 0xe8, + 0xbe, 0x17, 0xcb, 0x11, 0x92, 0x57, 0x5c, 0xaf +}; +/* QIUTx = 000001e1c570acc653c706fd7740194a554de7f3799a12b820d6a941197f761d */ +/* QIUTy = 000001e2225e8d0d41c808f6ead7af320fb25fed29a99098a0f0e11cd869e53c */ +static const uint8_t nist_kas_ecc_cdh_testvector_283_out[] = { +/* ZIUT */ + 0x00, 0xbc, 0x0d, 0xcf, 0x75, 0x85, 0x75, 0x3c, 0xc7, 0x9a, 0xa4, 0x12, + 0xd2, 0x74, 0x0b, 0x4b, 0x2d, 0x1c, 0x64, 0x4f, 0xc9, 0x75, 0x5c, 0xb0, + 0x55, 0x02, 0x86, 0xbc, 0xf6, 0x8e +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_284_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x66, 0xbe, 0x24, 0x26, 0xb3, 0xbf, 0x8e, 0x6d, 0x05, + 0xa2, 0x4d, 0x7d, 0x1f, 0x2c, 0x0e, 0x32, 0x9e, 0x41, 0x20, 0xcf, 0xc8, + 0xe6, 0xff, 0x52, 0x48, 0x6f, 0x09, 0x55, 0x86 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_284_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x73, 0x71, 0xe2, 0x88, 0x14, 0x5f, 0xc2, 0x5a, 0x5a, + 0x9c, 0xb5, 0xf2, 0xa3, 0x86, 0x03, 0x4f, 0x2f, 0x32, 0x8c, 0x6e, 0xaa, + 0x24, 0xc8, 0xb0, 0x96, 0xe8, 0xab, 0x1f, 0x0c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_284_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x97, 0xbe, 0xed, 0x4b, 0x73, 0x8a, 0x62, 0x05, 0xcc, + 0x9e, 0xa0, 0x46, 0xb4, 0x48, 0xb5, 0x23, 0x12, 0x8b, 0x93, 0x10, 0x1a, + 0x02, 0xd9, 0x64, 0x43, 0x5e, 0xb1, 0x78, 0x06 +}; +/* QIUTx = 0000018358da94079a700a10b20a2325d33d80e95eb4fc4a98101c312635939c */ +/* QIUTy = 0000000c4f442d0071c7bd1d217cf235fd031dec309e85ea2014e68b50fc2ba0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_284_out[] = { +/* ZIUT */ + 0x01, 0xb7, 0xef, 0x31, 0x48, 0xbe, 0x33, 0x11, 0x15, 0x32, 0x1b, 0x1c, + 0x2a, 0x68, 0x83, 0x2f, 0xdf, 0xb9, 0x91, 0xb2, 0x62, 0x24, 0xa6, 0x0d, + 0xdd, 0xce, 0x3e, 0x06, 0x0d, 0x27 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_285_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x81, 0xf3, 0xbb, 0x0b, 0x09, 0x77, 0x13, 0x27, 0x7c, + 0x5f, 0x3b, 0x46, 0xce, 0xf0, 0x2a, 0xa9, 0xcb, 0xe2, 0x9a, 0xb9, 0x5c, + 0x76, 0xe9, 0xb6, 0x0a, 0x1f, 0x7a, 0x51, 0xe5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_285_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0x2e, 0x2f, 0xb6, 0x72, 0xd7, 0x2b, 0xf7, 0x8f, 0x7c, + 0xfe, 0xdc, 0x40, 0xd3, 0x72, 0x6c, 0x6b, 0x4f, 0xb5, 0x85, 0x41, 0x7c, + 0x74, 0x76, 0xb6, 0x55, 0xe3, 0x2b, 0xbd, 0x3b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_285_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x75, 0x9c, 0x55, 0xda, 0x55, 0xe1, 0xfd, 0xb5, 0xba, + 0x7f, 0x8b, 0x89, 0x3a, 0xba, 0xae, 0x59, 0x25, 0xb9, 0xb0, 0x81, 0x84, + 0xa3, 0xd5, 0x54, 0x95, 0x7a, 0xcf, 0x3e, 0xc0 +}; +/* QIUTx = 0000002af25f810e18a81b69da254a65b8a6c7ab80ddc27c85622e2348add132 */ +/* QIUTy = 00000128b753e4b21a8c3acf85aab92a9aa6a7b33f2cb69d7024baf8e8b07142 */ +static const uint8_t nist_kas_ecc_cdh_testvector_285_out[] = { +/* ZIUT */ + 0x00, 0x41, 0x24, 0x98, 0x65, 0xc9, 0x13, 0xb2, 0x87, 0xa2, 0x53, 0x15, + 0x0b, 0x20, 0x7e, 0x26, 0x82, 0xef, 0xd9, 0x60, 0x57, 0xcb, 0x07, 0x09, + 0xe9, 0xbb, 0xb4, 0x8c, 0x0f, 0xc9 +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_286_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x65, 0xaa, 0x41, 0x15, 0xe5, 0x9e, 0x60, 0x45, 0xaa, + 0xf9, 0x9e, 0xe1, 0xbe, 0xca, 0x1f, 0xab, 0x92, 0x3b, 0xbd, 0xc9, 0x19, + 0x20, 0x6e, 0x09, 0x31, 0x62, 0x0b, 0xa9, 0x96 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_286_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x28, 0xd0, 0x0b, 0x77, 0x58, 0x99, 0xa5, 0x8a, 0x59, + 0xbc, 0xb2, 0xab, 0x79, 0xd6, 0x09, 0xe2, 0xdc, 0xda, 0x98, 0xe6, 0x52, + 0x3b, 0xb6, 0x71, 0x68, 0x55, 0x4f, 0x84, 0xe6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_286_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xee, 0x63, 0x9d, 0x89, 0xf0, 0xe4, 0x33, 0xc0, 0x75, + 0xe2, 0xef, 0x57, 0xcc, 0x24, 0x35, 0x81, 0xe9, 0x5b, 0x26, 0x1f, 0x8a, + 0x93, 0xb8, 0xef, 0x6f, 0x5e, 0xbf, 0x80, 0x15 +}; +/* QIUTx = 00000006638f6bcd85043395d01d767ff77e9d677f37ef400f2e16fee86dbaf2 */ +/* QIUTy = 0000006c12496266debb1d8343b9684e27c5f7129c17024a8e6704672a5f3d63 */ +static const uint8_t nist_kas_ecc_cdh_testvector_286_out[] = { +/* ZIUT */ + 0x01, 0xcf, 0x48, 0x0f, 0xbc, 0x2b, 0xe2, 0xc2, 0xc4, 0x44, 0x8c, 0x88, + 0x89, 0x09, 0x72, 0xc7, 0xff, 0x9c, 0xbe, 0x08, 0xa7, 0x5e, 0x26, 0xc3, + 0x80, 0x95, 0x96, 0xb8, 0xb5, 0xc0 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_287_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x35, 0x76, 0xe7, 0x00, 0xf3, 0x63, 0x67, 0xfb, 0x74, + 0x18, 0x42, 0xf2, 0x31, 0x88, 0x9f, 0x36, 0x82, 0x2a, 0xab, 0x29, 0x33, + 0xc2, 0x45, 0xee, 0xd5, 0x7b, 0x9d, 0xac, 0xad +}; +static const uint8_t nist_kas_ecc_cdh_testvector_287_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x79, 0x10, 0xe9, 0x07, 0x1a, 0x3e, 0x42, 0xe7, 0xf2, + 0x1b, 0x36, 0x3f, 0x0e, 0x68, 0x7d, 0x28, 0x98, 0x10, 0xa4, 0xec, 0x29, + 0xc3, 0x6e, 0xce, 0x14, 0x85, 0x4e, 0x1d, 0xd1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_287_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x92, 0x9b, 0x09, 0xb6, 0x7b, 0x29, 0xaa, 0x4f, 0xf1, + 0x5d, 0x67, 0x79, 0xa1, 0x73, 0x30, 0x65, 0x04, 0x9f, 0xae, 0xb2, 0xc2, + 0x27, 0x01, 0x2c, 0x49, 0xf2, 0x77, 0xed, 0x51 +}; +/* QIUTx = 000000ca0403d95d85f0cb0ae4d2aeae18e187b79c201ed68c14ad24ed003922 */ +/* QIUTy = 000000cf6b0a502b290d0aeee820661accf6ea597687c45c7f93a773d25f62a6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_287_out[] = { +/* ZIUT */ + 0x01, 0xce, 0x8a, 0xbf, 0x3c, 0x8c, 0xcf, 0xa3, 0x0e, 0x5f, 0x35, 0xdd, + 0xb7, 0x5f, 0x5e, 0x10, 0x6a, 0xab, 0x1e, 0x67, 0x08, 0x61, 0x56, 0xa1, + 0xed, 0xed, 0xa1, 0x71, 0x7b, 0x77 +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_288_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xe9, 0xfb, 0xa7, 0x1a, 0x64, 0xab, 0xb1, 0x77, 0xfa, + 0x43, 0x6c, 0xb9, 0x73, 0x9c, 0x9f, 0x68, 0xc0, 0x15, 0x5a, 0xdc, 0x89, + 0x71, 0x39, 0xc1, 0xbf, 0x3d, 0xf9, 0x9a, 0x53 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_288_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x9a, 0xf1, 0x13, 0x1b, 0xe4, 0x7d, 0xe0, 0x88, 0x70, + 0x83, 0x5d, 0xa1, 0x49, 0x46, 0xfe, 0xd7, 0x30, 0x34, 0x17, 0x9f, 0x80, + 0x92, 0x98, 0xd0, 0x14, 0x9b, 0x16, 0xdd, 0x36 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_288_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xe2, 0x7a, 0xf0, 0x4e, 0xfe, 0x2d, 0x86, 0xff, 0xed, + 0x6e, 0xcd, 0xf7, 0x18, 0xfc, 0x0b, 0x8e, 0x04, 0x9e, 0xd2, 0x22, 0xe7, + 0x60, 0x0c, 0x3c, 0xe3, 0x1c, 0xe4, 0xe9, 0x7a +}; +/* QIUTx = 00000145ec0db5fe62b92547792012268af21ba928a8fd98d0a1dee3d8fb2559 */ +/* QIUTy = 0000010a031cea56b183e93093008ab705cc9099e5b65c5cb4407324b96fee90 */ +static const uint8_t nist_kas_ecc_cdh_testvector_288_out[] = { +/* ZIUT */ + 0x00, 0x25, 0xdf, 0x75, 0x9a, 0x20, 0x31, 0x23, 0x61, 0xb9, 0xf6, 0x76, + 0x7e, 0xfe, 0x8e, 0x8d, 0x69, 0x97, 0x9e, 0x34, 0x63, 0x94, 0x69, 0xa9, + 0x1f, 0xed, 0x9f, 0xce, 0x04, 0xf8 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_289_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x1f, 0x99, 0x4a, 0x41, 0x6c, 0xc1, 0x99, 0x0b, 0x8c, + 0x61, 0x76, 0x7a, 0x3d, 0x68, 0xfb, 0xea, 0x73, 0xaf, 0x7b, 0x48, 0xb6, + 0x55, 0xe4, 0x74, 0x70, 0xfc, 0xcc, 0x79, 0x1f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_289_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x5d, 0xe9, 0x88, 0x83, 0x5d, 0x68, 0x12, 0xf0, 0xbd, + 0xd7, 0x00, 0x7a, 0x89, 0x59, 0x71, 0xe1, 0xa0, 0x6f, 0x4d, 0x22, 0xce, + 0x13, 0x03, 0xc9, 0xf5, 0x5e, 0xfe, 0x64, 0x7c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_289_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x1a, 0x72, 0x6d, 0x7b, 0x99, 0x28, 0x69, 0x1e, 0xb0, + 0x14, 0x9c, 0xa8, 0xf0, 0xed, 0xee, 0x47, 0xbd, 0x0c, 0x73, 0x41, 0x13, + 0xab, 0x60, 0x03, 0x24, 0x1e, 0xe1, 0x93, 0xde +}; +/* QIUTx = 0000007426bfa8878fe59b16a9b8c63910a1e2fbc6b07ba995ba04c31402112e */ +/* QIUTy = 000000944e9616676cb2fc7fa0f9e1b87a358748243e80fb62264284645a6a4d */ +static const uint8_t nist_kas_ecc_cdh_testvector_289_out[] = { +/* ZIUT */ + 0x00, 0x43, 0x7a, 0xb4, 0xa5, 0x37, 0x56, 0xff, 0x67, 0x8a, 0x1f, 0x58, + 0x0c, 0x0f, 0xd1, 0xf3, 0x3b, 0x23, 0x02, 0x1d, 0x62, 0x06, 0x08, 0x08, + 0x45, 0x3b, 0x4a, 0xab, 0xe6, 0x27 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_290_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x05, 0x13, 0x62, 0x0a, 0xee, 0x0d, 0x04, 0x78, 0x87, + 0x24, 0x38, 0xe9, 0x9b, 0x23, 0xea, 0x49, 0x00, 0x15, 0x3f, 0x93, 0x66, + 0xeb, 0x17, 0xd6, 0x1b, 0xdf, 0x35, 0xaa, 0x19 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_290_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x13, 0x6d, 0xfb, 0xc8, 0x40, 0x1b, 0xbd, 0xa0, 0xd6, + 0x75, 0xca, 0x06, 0xa0, 0xcf, 0xf6, 0xbd, 0xd4, 0x67, 0xc0, 0xac, 0x9a, + 0x97, 0x82, 0x93, 0x30, 0x07, 0x28, 0xe7, 0xdc +}; +static const uint8_t nist_kas_ecc_cdh_testvector_290_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xf4, 0x59, 0xc7, 0x67, 0x21, 0x69, 0xc1, 0x25, 0x9e, + 0x4e, 0x19, 0x93, 0x33, 0x96, 0x4c, 0x1f, 0xff, 0xbc, 0xe7, 0x5a, 0xd3, + 0x0d, 0xde, 0x12, 0x64, 0xf5, 0xcb, 0x86, 0xd1 +}; +/* QIUTx = 000001b44a81895d2105fa16a6e09526c09ae7f6cbdbce210870f4e33db8b6f4 */ +/* QIUTy = 000000b1e072c62a2642975f06c687c6467da295ef93f04d1c5494a624683c80 */ +static const uint8_t nist_kas_ecc_cdh_testvector_290_out[] = { +/* ZIUT */ + 0x01, 0xeb, 0xd5, 0x58, 0x23, 0xc5, 0x7d, 0x1f, 0xc7, 0xb3, 0x6c, 0xf1, + 0xed, 0x20, 0x51, 0xea, 0xd6, 0x4d, 0xb6, 0xd1, 0x14, 0x01, 0x4d, 0x34, + 0x07, 0x18, 0x6f, 0x50, 0xd9, 0x57 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_291_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x35, 0xdf, 0xfe, 0xc9, 0x11, 0x7e, 0xd7, 0x16, 0x76, + 0x27, 0xa2, 0x4a, 0x3e, 0xbd, 0xdd, 0x49, 0xa3, 0xf4, 0x5d, 0x91, 0xad, + 0x18, 0x40, 0x1d, 0x3d, 0x44, 0x9b, 0x2f, 0xef +}; +static const uint8_t nist_kas_ecc_cdh_testvector_291_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x93, 0x17, 0x54, 0xce, 0x5c, 0xf5, 0x57, 0xa1, 0xc1, + 0xac, 0xed, 0xfe, 0x5e, 0x9a, 0x7b, 0x0b, 0x91, 0xf8, 0x16, 0x43, 0xda, + 0x85, 0x86, 0xa6, 0x86, 0x58, 0x85, 0xf0, 0x42 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_291_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x65, 0x6a, 0x47, 0xb8, 0x77, 0x2b, 0x08, 0xb1, 0xd9, + 0x07, 0xc8, 0x23, 0xfb, 0x6c, 0x45, 0xc6, 0x5f, 0x9f, 0x18, 0xf8, 0xb4, + 0x3f, 0x3a, 0x61, 0xe6, 0xc7, 0x46, 0x11, 0xe1 +}; +/* QIUTx = 00000153cdbad92eb8d20da0c1c7aad46d08336cbc976e8d6f83947e4f4d6616 */ +/* QIUTy = 000001c977b97a5e1205ca66545df3a526b6e325e087c0e070839fe7ec1ee788 */ +static const uint8_t nist_kas_ecc_cdh_testvector_291_out[] = { +/* ZIUT */ + 0x00, 0x6d, 0x07, 0xf6, 0xe0, 0x8b, 0x11, 0xa0, 0x60, 0xcc, 0xec, 0x43, + 0xb0, 0x7c, 0xa7, 0xd9, 0xea, 0xf6, 0xc3, 0xec, 0xe0, 0x6f, 0x47, 0x85, + 0x51, 0x92, 0x84, 0xbf, 0x6f, 0x0a +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_292_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x48, 0x45, 0xce, 0x66, 0x1b, 0x1e, 0xae, 0x34, 0xc1, + 0x69, 0x9f, 0x1b, 0xfe, 0x38, 0xdc, 0x87, 0xef, 0x28, 0xb8, 0xb0, 0xa7, + 0x77, 0x1f, 0xf3, 0x66, 0xdc, 0x21, 0xd8, 0x63 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_292_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x09, 0x6b, 0x19, 0x54, 0xb0, 0x6e, 0xaa, 0x70, 0x73, + 0xed, 0x93, 0x98, 0x01, 0xaa, 0x29, 0x74, 0xda, 0x1d, 0x60, 0xd6, 0x6e, + 0x97, 0xc3, 0x1d, 0xf0, 0xf6, 0x87, 0x6f, 0xaf +}; +static const uint8_t nist_kas_ecc_cdh_testvector_292_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xf1, 0x4f, 0x5e, 0xc4, 0xef, 0xaf, 0x86, 0xe4, 0x3f, + 0xec, 0xe6, 0x5f, 0x17, 0xff, 0x91, 0xb1, 0xa8, 0xd6, 0x1b, 0xe3, 0x41, + 0x6e, 0xee, 0xb8, 0x84, 0xf4, 0xe2, 0xd1, 0x4e +}; +/* QIUTx = 000001d9f8c01e9c20f6150ec7620a75e39e96f9247bece137b0365bec54254c */ +/* QIUTy = 0000006008373b9e087805294dadae00894667fdb9f6b8a4d16295e5b9d21a6d */ +static const uint8_t nist_kas_ecc_cdh_testvector_292_out[] = { +/* ZIUT */ + 0x00, 0xae, 0xa5, 0x94, 0xf0, 0x92, 0xb4, 0x05, 0x2f, 0x75, 0x64, 0xb2, + 0xe5, 0x65, 0x1b, 0xcf, 0x43, 0xef, 0x7e, 0x33, 0x6a, 0x06, 0x4d, 0x6b, + 0xfb, 0x1a, 0x89, 0xcf, 0x5e, 0x51 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_293_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x47, 0x34, 0x19, 0x21, 0x65, 0xc9, 0x6f, 0xbd, 0xb7, + 0x94, 0xca, 0xb1, 0xe2, 0xd1, 0xef, 0x11, 0x1e, 0x1a, 0x20, 0xa7, 0x20, + 0x5d, 0xb0, 0x1a, 0xa8, 0x03, 0xa0, 0x32, 0xa2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_293_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0xec, 0xdf, 0xc3, 0x94, 0x0b, 0x7d, 0x06, 0x18, 0xcd, + 0x63, 0x15, 0x44, 0x17, 0x51, 0xf6, 0x63, 0xdf, 0x74, 0xd3, 0x56, 0x49, + 0x2e, 0xf9, 0x34, 0xb4, 0xba, 0x2b, 0x2a, 0xd1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_293_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x1f, 0xa5, 0xcb, 0xd8, 0x8a, 0x14, 0x6f, 0x6c, 0xcf, + 0x5f, 0x79, 0xdf, 0xbc, 0x70, 0x86, 0x8f, 0xd9, 0xbb, 0x4c, 0x81, 0x15, + 0x97, 0x6c, 0x96, 0x27, 0x0f, 0xf7, 0xbc, 0x5e +}; +/* QIUTx = 0000014d276f4281cb50a26b29ec81fced96d0e909994b2285433855256d58db */ +/* QIUTy = 000000ac4792af62a0dc4fd4eec384fbf3fbb82c8347486bc1eb1338bc7f3ab0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_293_out[] = { +/* ZIUT */ + 0x00, 0x99, 0xd6, 0xd0, 0x76, 0xe1, 0x4c, 0xcf, 0xee, 0x15, 0xed, 0x7e, + 0x7e, 0xf3, 0x84, 0xbf, 0xee, 0x12, 0xde, 0xba, 0x8c, 0x9a, 0xe8, 0xf6, + 0xcc, 0xa3, 0x48, 0x6a, 0x14, 0x94 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_294_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x7e, 0x1f, 0x32, 0x51, 0xe2, 0xa0, 0xaa, 0x6d, 0xe1, + 0xf8, 0xdf, 0x86, 0xb8, 0x5e, 0xd9, 0xd1, 0x1d, 0xa5, 0xeb, 0x71, 0x36, + 0xad, 0xd4, 0x5e, 0xa7, 0xd2, 0x5c, 0x86, 0x7c +}; +static const uint8_t nist_kas_ecc_cdh_testvector_294_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xd9, 0x62, 0x81, 0xe0, 0x75, 0x6d, 0xe9, 0xda, 0xa5, + 0x5d, 0x2e, 0xf6, 0x57, 0x3b, 0xb2, 0xfe, 0x2d, 0xd0, 0x9b, 0x71, 0xd9, + 0x11, 0x91, 0xa5, 0xa0, 0x43, 0xba, 0xe0, 0xf3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_294_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xf5, 0x86, 0x84, 0xea, 0x14, 0xa6, 0x8f, 0xef, 0xb8, + 0xcc, 0x26, 0xb2, 0x67, 0xa1, 0x34, 0x19, 0xc6, 0x2d, 0x72, 0x61, 0xba, + 0xd1, 0x4e, 0x53, 0x68, 0xa9, 0x81, 0x9a, 0x18 +}; +/* QIUTx = 0000009a65a85394070fe0e5a108164eb289cc3d77ed0848fd57f384e62caa20 */ +/* QIUTy = 000000e7f56f2c27be4faeb20e274c2604c6dc2d88597030ad2164fad03cb904 */ +static const uint8_t nist_kas_ecc_cdh_testvector_294_out[] = { +/* ZIUT */ + 0x01, 0xb1, 0xe9, 0x77, 0xc4, 0x3a, 0xfd, 0x20, 0x31, 0x32, 0xc0, 0x85, + 0xb9, 0x5d, 0xb0, 0xe2, 0x04, 0x6a, 0x4b, 0x6a, 0xc2, 0xc0, 0x46, 0xee, + 0x9a, 0xd6, 0x65, 0x05, 0x05, 0x78 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_295_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xbe, 0x1e, 0xe7, 0x50, 0xf2, 0x71, 0x2b, 0x2a, 0xcb, + 0x20, 0xc4, 0x5e, 0x97, 0x35, 0x7c, 0x50, 0xdb, 0x3b, 0xe8, 0x95, 0xb3, + 0x3f, 0x83, 0x0c, 0x71, 0xbc, 0x9f, 0x4f, 0x3d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_295_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x5f, 0xec, 0x81, 0x0c, 0xdb, 0x17, 0x9f, 0xcd, 0x1c, + 0xe8, 0xe4, 0xdc, 0x1a, 0x24, 0x99, 0xe4, 0x0d, 0xe8, 0xa4, 0xa4, 0x9a, + 0x94, 0x20, 0xf0, 0x0e, 0x56, 0x11, 0x0c, 0xf4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_295_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xee, 0xfb, 0x24, 0x78, 0x9b, 0x32, 0xb4, 0x36, 0xce, + 0x39, 0x62, 0x2c, 0x11, 0x4c, 0x39, 0xa6, 0xcd, 0x1e, 0x58, 0xec, 0x94, + 0x43, 0xc8, 0x87, 0x0e, 0x5e, 0xe2, 0xf8, 0x01 +}; +/* QIUTx = 0000013fb1ca9ed709bb386fba02cc7862fd6c64e1087be5f61ea733946c1634 */ +/* QIUTy = 000001cb4097e44a730700debfe8143fbf9bca3a3d6c46985a27cd5043b2ca5a */ +static const uint8_t nist_kas_ecc_cdh_testvector_295_out[] = { +/* ZIUT */ + 0x00, 0x0e, 0x4c, 0xb7, 0x04, 0x35, 0x5c, 0xba, 0x1b, 0x40, 0xce, 0xe3, + 0xda, 0x10, 0x2c, 0xb0, 0x48, 0x51, 0x9a, 0x91, 0xb4, 0xc7, 0x89, 0xb3, + 0x75, 0x7c, 0xfd, 0xd9, 0x33, 0xaa +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_296_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x5c, 0x2e, 0x2c, 0xe0, 0xbc, 0x72, 0x2c, 0xea, 0x4c, + 0xbc, 0x7c, 0x33, 0x52, 0xcb, 0xe0, 0xd2, 0x8b, 0x5b, 0x00, 0x2e, 0x44, + 0xd9, 0x37, 0x05, 0x89, 0x5d, 0x79, 0x1a, 0xfc +}; +static const uint8_t nist_kas_ecc_cdh_testvector_296_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x4f, 0x61, 0x69, 0x83, 0xad, 0x08, 0xe7, 0x45, 0x31, + 0x5c, 0x47, 0x67, 0xb0, 0xae, 0x21, 0xa6, 0xfd, 0x8a, 0x62, 0x9c, 0x25, + 0x8c, 0xe7, 0xae, 0xfa, 0x4c, 0x17, 0xa8, 0xe0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_296_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x17, 0x52, 0x4d, 0x50, 0x66, 0x16, 0xbd, 0x20, 0x5c, + 0xb3, 0x97, 0x8b, 0xc7, 0x5e, 0x3a, 0x34, 0x76, 0x23, 0x3e, 0x49, 0xb6, + 0xdc, 0x20, 0x6f, 0x97, 0x11, 0x69, 0x75, 0x57 +}; +/* QIUTx = 00000150a17327845e7bc79d8ece12930dc2b77654caa1082b57b0cf8e05b1ac */ +/* QIUTy = 000000151c76822d8df5effd8c6943395b6a8d538431d42e846e9ff8de7eaee6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_296_out[] = { +/* ZIUT */ + 0x00, 0xd8, 0xc1, 0x3b, 0xc5, 0xe8, 0x19, 0xc6, 0x10, 0x1d, 0xae, 0xf3, + 0xf6, 0xfb, 0x5b, 0xe6, 0xbc, 0xce, 0xcf, 0x23, 0x3c, 0x4b, 0x7f, 0xc6, + 0x50, 0x54, 0xe8, 0xe8, 0xd3, 0xbc +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_297_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0xba, 0xfa, 0x9b, 0xba, 0x92, 0x72, 0x5e, 0xef, 0x0c, + 0x4a, 0x0a, 0xfc, 0xbd, 0x42, 0x63, 0xe5, 0x5f, 0x51, 0x55, 0x64, 0x5b, + 0x5c, 0x58, 0xa9, 0x6b, 0xc3, 0xe9, 0xe9, 0x65 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_297_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xd1, 0xb3, 0xd0, 0xe3, 0x5d, 0x61, 0x7e, 0x09, 0xe0, + 0x78, 0xc5, 0x71, 0xa5, 0xf4, 0x1e, 0xa2, 0x2d, 0xfd, 0x11, 0x2d, 0x67, + 0xa9, 0x4d, 0x8d, 0xfb, 0xba, 0x66, 0xe9, 0xa9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_297_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0xa6, 0xb0, 0x5d, 0x30, 0xa7, 0x03, 0xf1, 0x17, 0x9a, + 0x80, 0xf8, 0xa8, 0x64, 0xb3, 0x4c, 0xa1, 0x5c, 0x45, 0x3e, 0x82, 0x80, + 0x8a, 0x10, 0x95, 0xe4, 0x35, 0xe9, 0xba, 0xcb +}; +/* QIUTx = 00000093b3252251fd9d6d9c81d78cf1f134cdd554d63c2a1e2f1afa14e2d4e4 */ +/* QIUTy = 0000008aeb0a8ab3ff5e4fb023f7e1917f0108890af11abca7da027fadacc3b4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_297_out[] = { +/* ZIUT */ + 0x01, 0x29, 0xaf, 0x50, 0xfa, 0x08, 0x51, 0x33, 0x77, 0x17, 0x53, 0xf2, + 0x97, 0xa3, 0x13, 0xbb, 0xa0, 0xd2, 0xf5, 0x88, 0x2e, 0x76, 0x34, 0xb7, + 0xef, 0x5a, 0xdc, 0xe7, 0x60, 0xff +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_298_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x79, 0x8b, 0xf5, 0xab, 0x76, 0x1b, 0xb6, 0xac, 0xfe, + 0xd0, 0xce, 0xf1, 0xcd, 0x71, 0xb3, 0xef, 0x46, 0xf2, 0x50, 0x43, 0x23, + 0xca, 0xfc, 0x40, 0x81, 0x59, 0x2d, 0xd6, 0xf6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_298_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x62, 0x77, 0xae, 0xb3, 0xe1, 0xca, 0xc0, 0x12, 0x1b, + 0x07, 0xd9, 0x37, 0x8a, 0x3a, 0x0c, 0xbc, 0x65, 0x67, 0xb4, 0x84, 0x23, + 0x92, 0x9e, 0x36, 0xdc, 0x85, 0x5e, 0x9d, 0x1a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_298_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x16, 0x8d, 0x09, 0x80, 0x9e, 0xb9, 0xf6, 0xac, 0xf3, + 0x11, 0x34, 0xeb, 0x5e, 0xb1, 0xaf, 0x96, 0x6e, 0x21, 0x2b, 0x9b, 0x6b, + 0xe6, 0x8c, 0xfd, 0x22, 0x40, 0x14, 0x25, 0xe9 +}; +/* QIUTx = 000001710a05f02b5505729516b1ac73d45f3cf08f1c5134d2f73d12570243c9 */ +/* QIUTy = 0000018611b10dab507583f2be10fd4296f537d4af09576f96979f1eadfe291c */ +static const uint8_t nist_kas_ecc_cdh_testvector_298_out[] = { +/* ZIUT */ + 0x00, 0x77, 0xc4, 0xea, 0x10, 0x95, 0xfa, 0xdc, 0x4c, 0xb4, 0x19, 0x0a, + 0x3f, 0xd5, 0x30, 0xc7, 0xd1, 0x53, 0x25, 0xe5, 0xd7, 0x9b, 0x8e, 0x8a, + 0x2b, 0x70, 0x8e, 0x23, 0x44, 0xcf +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_299_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x01, 0x5f, 0x72, 0x3d, 0xa9, 0xa3, 0x8c, 0x2d, 0xa5, 0x06, + 0x2c, 0x17, 0xd0, 0xb8, 0x37, 0x52, 0x2f, 0x7c, 0x69, 0xc7, 0x93, 0xf7, + 0x9c, 0x17, 0xfb, 0x69, 0x65, 0xd4, 0x4a, 0x03 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_299_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x01, 0x32, 0xb1, 0x77, 0x60, 0xac, 0x2e, 0x2b, 0xb9, 0xf8, + 0x13, 0xed, 0x77, 0x90, 0xc5, 0xcd, 0x3a, 0xa0, 0xd3, 0x8a, 0xb6, 0x4e, + 0x2e, 0x27, 0x2d, 0xdf, 0x4a, 0x4c, 0x2c, 0x1a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_299_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x38, 0x24, 0xf7, 0x1e, 0xc3, 0x25, 0x5b, 0xbd, 0x03, + 0x64, 0x2d, 0x78, 0x2c, 0xc6, 0x79, 0x4e, 0x1e, 0x54, 0xaa, 0x8f, 0xa5, + 0xf2, 0xa3, 0x31, 0xee, 0x13, 0xf7, 0x84, 0x50 +}; +/* QIUTx = 000001a4e35a8c32717f2aaa3eeef177848e580e0fed6c8096868f6acc4e1c09 */ +/* QIUTy = 0000013727604e81d3a9d93d243fe79e2db8a442334a8ea1852b9f83cae1bc3e */ +static const uint8_t nist_kas_ecc_cdh_testvector_299_out[] = { +/* ZIUT */ + 0x00, 0xd9, 0xeb, 0x3c, 0x79, 0xcf, 0x44, 0x25, 0x95, 0xda, 0xd0, 0x3e, + 0xd4, 0xa3, 0x8d, 0xaf, 0x35, 0x8b, 0x97, 0xd5, 0xdf, 0xc0, 0x1c, 0xb6, + 0x1f, 0xf2, 0x00, 0xa4, 0x79, 0x58 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_300_public_x[] = { +/* QCAVSx */ + 0x00, 0x00, 0x00, 0x51, 0xb7, 0x0b, 0xb8, 0xb8, 0xe2, 0x34, 0x1b, 0x86, + 0x82, 0x1d, 0x54, 0xb9, 0x74, 0xb6, 0x96, 0xbd, 0xa4, 0x43, 0xac, 0xb7, + 0xea, 0x65, 0x96, 0x5d, 0x27, 0xd2, 0xac, 0x70 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_300_public_y[] = { +/* QCAVSy */ + 0x00, 0x00, 0x00, 0xc7, 0x78, 0x4e, 0xef, 0x88, 0x9c, 0x47, 0x1c, 0x9d, + 0x26, 0xb3, 0xe0, 0xde, 0x24, 0xad, 0x2b, 0x4b, 0xf8, 0xbb, 0xba, 0x6f, + 0xe1, 0x8f, 0x51, 0xa4, 0x12, 0x18, 0x80, 0x58 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_300_private[] = { +/* dIUT */ + 0x00, 0x00, 0x00, 0x90, 0xad, 0xc0, 0xb2, 0x07, 0xda, 0xe3, 0x81, 0x62, + 0x2c, 0xf9, 0x2e, 0x04, 0xbc, 0xe7, 0x47, 0x91, 0x80, 0xec, 0x6e, 0x17, + 0x71, 0x66, 0x2f, 0x5c, 0x31, 0x79, 0xbd, 0x99 +}; +/* QIUTx = 00000106adbf9bbfdb3083598a7f6db2e91d2e7c174f705fc216631b7d05edf2 */ +/* QIUTy = 00000190d84ca6f4695fdbca40d26a74998a05c3d761dbf08981b645c0ea239e */ +static const uint8_t nist_kas_ecc_cdh_testvector_300_out[] = { +/* ZIUT */ + 0x01, 0x24, 0xc1, 0x9c, 0xff, 0xc0, 0xb9, 0x54, 0x9b, 0xfa, 0x37, 0x8a, + 0x54, 0x8e, 0x8c, 0xe1, 0x1e, 0xe7, 0xfc, 0xa2, 0x8d, 0x2d, 0x89, 0x8d, + 0xe4, 0x9a, 0xe1, 0xf2, 0xff, 0x61 +}; +/* [B-283] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_301_public_x[] = { +/* QCAVSx */ + 0x02, 0x50, 0x4e, 0x1a, 0x17, 0x81, 0x9d, 0x39, 0xf0, 0x10, 0xa4, 0xa6, + 0x9a, 0x05, 0x68, 0x29, 0x94, 0x02, 0xb5, 0x8f, 0x94, 0x4a, 0x38, 0x4c, + 0x7d, 0x1a, 0x62, 0xc9, 0xc9, 0x3e, 0xa4, 0xd1, 0xff, 0x30, 0x0e, 0x13 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_301_public_y[] = { +/* QCAVSy */ + 0x02, 0x65, 0x13, 0x2f, 0x7b, 0x4c, 0x64, 0xb7, 0x4b, 0x91, 0x79, 0xed, + 0x0f, 0x2e, 0x21, 0x1f, 0x43, 0x28, 0xd6, 0x25, 0x40, 0x50, 0x22, 0xf5, + 0x54, 0x17, 0x0d, 0xa9, 0x32, 0xb8, 0x0f, 0xdf, 0x7c, 0x1a, 0xab, 0x12 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_301_private[] = { +/* dIUT */ + 0x02, 0xf4, 0x34, 0x55, 0x84, 0x22, 0x46, 0xa2, 0xcc, 0x8e, 0xc0, 0x68, + 0xe9, 0xd6, 0xc6, 0xe4, 0x16, 0x0f, 0x6b, 0xa4, 0xe3, 0xb5, 0xd8, 0x31, + 0xd9, 0x3c, 0x1d, 0xaa, 0x8f, 0xd3, 0xd5, 0xa9, 0x66, 0x0c, 0x7b, 0xb1 +}; +/* QIUTx = 0561e495563018169804d4c8e2435b4afd85da376d914b69d39246f8e06113aa32e642d2 */ +/* QIUTy = 0781a7f59de7f42f5f9d6c3481f33fc5deb357c6ecf4c758e370d2435de3d8ee737703f4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_301_out[] = { +/* ZIUT */ + 0x06, 0x51, 0x94, 0xe2, 0x60, 0x90, 0xe7, 0x40, 0x47, 0xee, 0x75, 0xf1, + 0x3f, 0x97, 0x69, 0xd2, 0x0e, 0x1b, 0x52, 0x18, 0x96, 0x50, 0x01, 0x1e, + 0x28, 0x3d, 0xaa, 0x09, 0x07, 0x32, 0xcc, 0x53, 0x75, 0x5d, 0xc3, 0x66 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_302_public_x[] = { +/* QCAVSx */ + 0x01, 0x62, 0x3a, 0x96, 0x75, 0xe8, 0xc4, 0x03, 0x66, 0xe2, 0x61, 0x31, + 0xe4, 0x7b, 0x1a, 0xf0, 0x6c, 0x8b, 0x33, 0xac, 0xf5, 0xe9, 0x2f, 0x54, + 0x64, 0x48, 0x16, 0xdc, 0xb8, 0x44, 0x38, 0x2c, 0x94, 0x4c, 0xc2, 0x1f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_302_public_y[] = { +/* QCAVSy */ + 0x02, 0x9d, 0x28, 0x0f, 0x4d, 0x4c, 0x0c, 0x5f, 0xd7, 0x0f, 0x7e, 0x24, + 0x09, 0x59, 0x50, 0x12, 0x8b, 0xea, 0x3c, 0xae, 0x3c, 0xa4, 0x6f, 0x6a, + 0x5f, 0x70, 0xb7, 0x39, 0xfe, 0x1a, 0x99, 0x02, 0x68, 0x80, 0x4e, 0x38 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_302_private[] = { +/* dIUT */ + 0x02, 0xb9, 0x41, 0xe6, 0x92, 0xe0, 0xa9, 0x84, 0xc5, 0xff, 0xa8, 0x83, + 0xc9, 0xf9, 0xf8, 0x25, 0x6a, 0x43, 0xab, 0x1f, 0xd1, 0xad, 0x97, 0x82, + 0xa4, 0x2e, 0x42, 0x9a, 0x94, 0xe9, 0x10, 0xe4, 0x82, 0xb9, 0x1c, 0x23 +}; +/* QIUTx = 07b90af116b737d9008e4c18f6ad539d29ee1790008a1daf2e856fa672eca4aafc96ca63 */ +/* QIUTy = 06aaf78d0f20657b77b97cca30eab79b679a3aaa90b10907f979cde988ce718491010c2a */ +static const uint8_t nist_kas_ecc_cdh_testvector_302_out[] = { +/* ZIUT */ + 0x07, 0x5c, 0x53, 0x5c, 0xc7, 0x0d, 0xe1, 0x9c, 0x92, 0xd7, 0x31, 0x4a, + 0xfa, 0x2f, 0x33, 0x20, 0x09, 0x03, 0x43, 0x1f, 0x69, 0x90, 0xad, 0x40, + 0xac, 0x31, 0xda, 0xda, 0xf4, 0xe4, 0x92, 0xa7, 0x99, 0xb7, 0x5b, 0x05 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_303_public_x[] = { +/* QCAVSx */ + 0x07, 0xb8, 0x36, 0x97, 0x28, 0x43, 0x2f, 0x75, 0x28, 0xd3, 0xee, 0xc8, + 0xa6, 0x78, 0x8e, 0x69, 0xcd, 0x2e, 0xb8, 0x81, 0x62, 0xc4, 0x75, 0x12, + 0x74, 0x2e, 0xe0, 0xf0, 0x27, 0xcc, 0xb4, 0x15, 0x7a, 0x28, 0xa2, 0x23 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_303_public_y[] = { +/* QCAVSy */ + 0x05, 0x98, 0x6e, 0xb7, 0xf1, 0x09, 0xaa, 0x1f, 0x85, 0x56, 0xeb, 0xa2, + 0xbd, 0xc8, 0x8e, 0x49, 0x13, 0xb6, 0x5e, 0xff, 0xb9, 0x44, 0xea, 0xe6, + 0x39, 0x63, 0x6c, 0xba, 0x7e, 0x01, 0xdc, 0x37, 0x18, 0xbc, 0xb3, 0x61 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_303_private[] = { +/* dIUT */ + 0x02, 0x87, 0xde, 0x17, 0x2b, 0xa5, 0x0f, 0x32, 0x7b, 0xfc, 0x7d, 0x5a, + 0x8c, 0x01, 0x56, 0xd2, 0x5a, 0x1f, 0x0b, 0x9f, 0x71, 0xd3, 0x89, 0x85, + 0x2f, 0x2e, 0x3b, 0x58, 0x74, 0x06, 0xcb, 0x74, 0xef, 0x3b, 0xd0, 0x41 +}; +/* QIUTx = 00a03490765fc90c23553c0e2b79dfa232b51a73f21554e5eb18da4c994d925f8ed2bbef */ +/* QIUTy = 0304ffd41c5b0ab2a70b82188e8f1578d6ab7d3ce3ce34fa45dcc32207f163e91c5d6814 */ +static const uint8_t nist_kas_ecc_cdh_testvector_303_out[] = { +/* ZIUT */ + 0x02, 0x95, 0x6f, 0x63, 0xd4, 0x8a, 0x49, 0xa3, 0x30, 0xe2, 0x06, 0x89, + 0x55, 0xcc, 0x28, 0x86, 0xdb, 0xfd, 0x5b, 0xf7, 0x2a, 0x81, 0xb1, 0x0e, + 0xd8, 0x3f, 0x2d, 0x75, 0x8d, 0xd3, 0x15, 0xec, 0xa1, 0x72, 0x92, 0x7d +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_304_public_x[] = { +/* QCAVSx */ + 0x07, 0x3b, 0x09, 0x2a, 0x2a, 0x4d, 0x7c, 0x9a, 0x17, 0xbb, 0x88, 0xe7, + 0x5b, 0x40, 0xa9, 0xe4, 0xe4, 0x3b, 0x99, 0x81, 0x3c, 0xf6, 0x16, 0x82, + 0xd4, 0x9b, 0x92, 0x90, 0x5c, 0x2d, 0xd6, 0x06, 0x79, 0x0a, 0xed, 0x39 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_304_public_y[] = { +/* QCAVSy */ + 0x05, 0x66, 0xad, 0x45, 0x2a, 0x2d, 0x8e, 0xf0, 0xa3, 0x27, 0xce, 0x8e, + 0x28, 0x56, 0x14, 0x6f, 0xec, 0xaf, 0x09, 0xe4, 0x43, 0x1c, 0xcc, 0x04, + 0x25, 0x6a, 0x07, 0x7f, 0x60, 0x70, 0x1c, 0xe4, 0x47, 0x6b, 0x6d, 0xac +}; +static const uint8_t nist_kas_ecc_cdh_testvector_304_private[] = { +/* dIUT */ + 0x01, 0x53, 0xbb, 0xb8, 0xa3, 0xce, 0x4a, 0x1b, 0x99, 0x96, 0x0f, 0x56, + 0x18, 0x6a, 0xb5, 0x02, 0x07, 0xf5, 0x88, 0xf3, 0x0c, 0x94, 0xbe, 0xef, + 0x28, 0x40, 0x84, 0x23, 0xba, 0x44, 0xfc, 0x87, 0x5f, 0xaf, 0x38, 0xd8 +}; +/* QIUTx = 04f2c2454899623af13b65820aba145738407f77186abafa52d24b35bfdf5808ffeae076 */ +/* QIUTy = 0111f448460ad2430aaec788de291548475a1e5836dac520d8e493c9f601275e70ea29d2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_304_out[] = { +/* ZIUT */ + 0x06, 0x8a, 0x3f, 0x69, 0x38, 0xc4, 0x4b, 0x79, 0x75, 0x24, 0x37, 0x75, + 0x08, 0x58, 0x58, 0x42, 0xc6, 0xa7, 0xf1, 0xaf, 0x5f, 0xfe, 0x91, 0x31, + 0xdd, 0x3f, 0xf7, 0x86, 0xae, 0x56, 0xe1, 0x73, 0x93, 0x45, 0xd3, 0xd7 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_305_public_x[] = { +/* QCAVSx */ + 0x04, 0x55, 0xe8, 0x7b, 0xc2, 0x30, 0xce, 0x7f, 0xc5, 0x86, 0x31, 0x2d, + 0xd2, 0x07, 0xc5, 0x29, 0xe4, 0x7e, 0x3c, 0x74, 0xcc, 0x0c, 0xe5, 0xd0, + 0x73, 0xfb, 0xf4, 0xb1, 0xc9, 0x57, 0xf8, 0xcb, 0xbd, 0x91, 0x13, 0xbc +}; +static const uint8_t nist_kas_ecc_cdh_testvector_305_public_y[] = { +/* QCAVSy */ + 0x02, 0x1f, 0xfb, 0xf6, 0x2f, 0xb2, 0x53, 0x1d, 0xb3, 0x9e, 0xf2, 0xd0, + 0xbd, 0xce, 0x0d, 0x9c, 0x14, 0x1c, 0x92, 0xe9, 0xcd, 0xca, 0x62, 0x7c, + 0xaa, 0x39, 0xb5, 0x93, 0xfc, 0x4a, 0x02, 0x10, 0xe8, 0xee, 0x48, 0x1f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_305_private[] = { +/* dIUT */ + 0x03, 0x2a, 0xc0, 0xdc, 0xb9, 0xaa, 0x39, 0x72, 0x40, 0x1f, 0x9f, 0x58, + 0x84, 0x5e, 0xd7, 0x65, 0xda, 0x36, 0xb7, 0xd6, 0xf7, 0x73, 0x55, 0x77, + 0x9b, 0xfb, 0x24, 0x39, 0x82, 0x7f, 0xf3, 0x55, 0x6a, 0x75, 0x78, 0x1c +}; +/* QIUTx = 07159c86b9c6adb2160c28d86118f84564a90c149ede28329463677a4c87729f897c2f98 */ +/* QIUTy = 008a78167e1690625992b0efc2e0ef6f6d61e81837c8ecdfdab51d15340e37e7d8d05120 */ +static const uint8_t nist_kas_ecc_cdh_testvector_305_out[] = { +/* ZIUT */ + 0x01, 0x9b, 0x48, 0xd5, 0xee, 0xae, 0xb0, 0x5b, 0x58, 0x80, 0x1a, 0xe8, + 0xf3, 0x45, 0xad, 0x9b, 0xac, 0xb9, 0x1d, 0xaa, 0xc8, 0x85, 0xe5, 0x06, + 0x94, 0x9b, 0x84, 0x9e, 0xbc, 0x67, 0xbc, 0xbf, 0xa3, 0x08, 0xaa, 0xb7 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_306_public_x[] = { +/* QCAVSx */ + 0x06, 0x52, 0xcc, 0xc8, 0x92, 0x1f, 0x43, 0x9a, 0xf4, 0x2a, 0x23, 0x01, + 0x23, 0x6b, 0x58, 0x43, 0xa4, 0x2f, 0x1f, 0xd9, 0x9e, 0xcf, 0xe1, 0xb4, + 0x13, 0x4c, 0x3d, 0xe0, 0x14, 0xcd, 0xc7, 0x60, 0x35, 0x34, 0x7c, 0xc0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_306_public_y[] = { +/* QCAVSy */ + 0x03, 0x34, 0x1d, 0x80, 0x74, 0x9f, 0x1a, 0x5e, 0xc9, 0xf7, 0xac, 0x62, + 0x52, 0x38, 0x4f, 0xef, 0xd3, 0x8b, 0x6f, 0x2b, 0xbc, 0xdc, 0x18, 0xfe, + 0xbe, 0x86, 0xc1, 0x60, 0xf5, 0xe7, 0x8c, 0x00, 0x3f, 0x06, 0x6e, 0x06 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_306_private[] = { +/* dIUT */ + 0x02, 0x68, 0x9b, 0xf2, 0x14, 0x75, 0xd3, 0x2f, 0xe7, 0x1a, 0x73, 0x55, + 0xef, 0xd9, 0xa7, 0x78, 0x7c, 0xaa, 0x95, 0x45, 0xeb, 0xeb, 0x85, 0x3e, + 0x51, 0x84, 0xce, 0x42, 0x15, 0x24, 0x29, 0x05, 0x1f, 0x40, 0xcb, 0xc4 +}; +/* QIUTx = 00d7e5bcfac578fcd728180645176d7e088b68d330a209f18b968662fed16342b3921a20 */ +/* QIUTy = 06f750b3b5e98e0099b695965aa1d16475d1074f9231127ed703e2696d4b56afdebbceaa */ +static const uint8_t nist_kas_ecc_cdh_testvector_306_out[] = { +/* ZIUT */ + 0x06, 0x1b, 0x3b, 0xef, 0x17, 0x66, 0x46, 0x0f, 0x62, 0x96, 0xed, 0x47, + 0xd3, 0x9e, 0xbf, 0x5a, 0x71, 0x0d, 0x20, 0x2d, 0x2b, 0x7e, 0x7c, 0xac, + 0x0f, 0x0d, 0x3b, 0x23, 0x54, 0x05, 0xee, 0xce, 0x99, 0xaa, 0x30, 0xd7 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_307_public_x[] = { +/* QCAVSx */ + 0x06, 0x23, 0x31, 0xb9, 0x33, 0xaf, 0xb4, 0x38, 0x4f, 0xa3, 0xa4, 0xd2, + 0x24, 0x55, 0x1a, 0xe8, 0x12, 0x0b, 0xc5, 0x5f, 0xc7, 0xea, 0x73, 0xf2, + 0xbe, 0x74, 0x9e, 0x21, 0x7a, 0xfc, 0x4e, 0x1b, 0xa7, 0x9e, 0x76, 0x0f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_307_public_y[] = { +/* QCAVSy */ + 0x02, 0xbf, 0x51, 0xc4, 0x4f, 0x83, 0x61, 0xc3, 0x05, 0x4c, 0xad, 0x64, + 0x0f, 0x92, 0x44, 0x6f, 0xe3, 0x82, 0x0b, 0x06, 0x3c, 0xf4, 0xbb, 0x22, + 0xca, 0x17, 0xc0, 0xa2, 0x74, 0xfd, 0x46, 0xf5, 0x05, 0x04, 0xfb, 0xec +}; +static const uint8_t nist_kas_ecc_cdh_testvector_307_private[] = { +/* dIUT */ + 0x01, 0x05, 0x20, 0x42, 0x98, 0x8d, 0xdd, 0xf4, 0x70, 0xd0, 0xa2, 0xe3, + 0x6f, 0xff, 0x5b, 0x93, 0xec, 0x69, 0xf4, 0xd2, 0x40, 0xa8, 0xe3, 0x7c, + 0x06, 0x4c, 0xc4, 0xd5, 0x99, 0x46, 0x7b, 0xa2, 0x7a, 0xf3, 0xc9, 0xf1 +}; +/* QIUTx = 00c7c9ff77e018b8801bddf886702556b126a6d9a1831a1f60f35872e524c134d553e4a4 */ +/* QIUTy = 0035d767b58b499d9fb54562c3830411af59e7088a4a3333d5dc7fe5b0f7f1e1c5e3ac2b */ +static const uint8_t nist_kas_ecc_cdh_testvector_307_out[] = { +/* ZIUT */ + 0x05, 0x5d, 0x57, 0x94, 0x58, 0x86, 0x0a, 0x3d, 0xd9, 0x2a, 0xc6, 0x57, + 0x08, 0x47, 0x63, 0x2f, 0x04, 0x46, 0x07, 0x55, 0xc2, 0x2a, 0x4c, 0x43, + 0x2c, 0xf4, 0xdd, 0xe9, 0x61, 0x1d, 0x2c, 0xe1, 0x60, 0x8c, 0xa1, 0x85 +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_308_public_x[] = { +/* QCAVSx */ + 0x02, 0x1e, 0x82, 0xd6, 0xaf, 0x6d, 0x32, 0x11, 0x98, 0x17, 0x6f, 0xf8, + 0x98, 0x6c, 0x2b, 0xc7, 0x86, 0xa0, 0x08, 0x13, 0x26, 0xcc, 0x85, 0xf0, + 0x26, 0xb7, 0x1b, 0x32, 0xac, 0x06, 0xc0, 0xba, 0xe6, 0xb4, 0xcb, 0xa2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_308_public_y[] = { +/* QCAVSy */ + 0x01, 0xe9, 0x73, 0x3f, 0xa9, 0xd2, 0x99, 0x61, 0x26, 0x94, 0x20, 0xdb, + 0x24, 0xed, 0xc0, 0xd5, 0xae, 0x28, 0x5d, 0x78, 0xc9, 0xae, 0x14, 0xb3, + 0x8b, 0x10, 0x19, 0xf1, 0x36, 0x52, 0xf1, 0x90, 0x27, 0x7d, 0xc4, 0x7f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_308_private[] = { +/* dIUT */ + 0x03, 0xbb, 0x9a, 0xd5, 0xfa, 0x55, 0x2d, 0x38, 0xd1, 0xa7, 0x7c, 0xb5, + 0x53, 0xc6, 0x31, 0xe2, 0xd0, 0x94, 0x0d, 0xb6, 0xb0, 0x4f, 0x0b, 0xd7, + 0x01, 0x1e, 0xa7, 0x35, 0xbe, 0x50, 0xd0, 0x45, 0xda, 0x9a, 0x9c, 0x1d +}; +/* QIUTx = 0687071805c25a7d0b1739f7cf681b2f295c4f9d8937351d21d1d43f634e9a57105bf127 */ +/* QIUTy = 0633ba21872e379c50e448372b1c0e65e85d07edd712d7dc06fa69a299f6037dece660dc */ +static const uint8_t nist_kas_ecc_cdh_testvector_308_out[] = { +/* ZIUT */ + 0x05, 0x4f, 0xa7, 0xc6, 0xc8, 0x4f, 0xb8, 0x9e, 0x58, 0x92, 0xd9, 0x19, + 0x45, 0x40, 0x86, 0x0e, 0xa3, 0x1a, 0xe2, 0xb6, 0xe3, 0x7a, 0x86, 0x97, + 0x13, 0x44, 0x23, 0x0e, 0xa5, 0x12, 0xa3, 0xf6, 0xc0, 0x56, 0x92, 0x16 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_309_public_x[] = { +/* QCAVSx */ + 0x04, 0x5d, 0x62, 0xd0, 0x1d, 0xb5, 0xef, 0x17, 0x3d, 0x0c, 0xff, 0x31, + 0x5a, 0x92, 0xa9, 0xa1, 0x05, 0xd1, 0xad, 0x78, 0x4f, 0xf9, 0xb0, 0x8e, + 0x72, 0x1f, 0x35, 0x80, 0xe0, 0x62, 0x65, 0xff, 0x53, 0x8a, 0x19, 0x4b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_309_public_y[] = { +/* QCAVSy */ + 0x06, 0xb7, 0x64, 0xc1, 0xff, 0x76, 0x98, 0x54, 0x96, 0xb9, 0x44, 0x51, + 0xb7, 0x56, 0xc4, 0xf3, 0x0f, 0xdf, 0xc6, 0x38, 0xd8, 0x99, 0x03, 0x12, + 0xbb, 0xec, 0xcb, 0xfb, 0xd7, 0x3e, 0x8c, 0x5a, 0x85, 0x5a, 0xdb, 0x75 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_309_private[] = { +/* dIUT */ + 0x01, 0x33, 0xaa, 0x44, 0x5d, 0xc8, 0x0d, 0x7d, 0x5a, 0x09, 0x7d, 0x1d, + 0xa1, 0x1d, 0x51, 0x0e, 0x65, 0x71, 0xa7, 0x83, 0xb4, 0xfb, 0x23, 0x54, + 0x02, 0x71, 0x7d, 0x68, 0xba, 0x8f, 0xd1, 0x45, 0x4e, 0x6b, 0x31, 0x9f +}; +/* QIUTx = 02d26e46a6ed9fcf1d2f89c63d80e0172dedb4f5aeddff092836aac8599094885557ead9 */ +/* QIUTy = 07d6713974701c160aedec8f94e6446bf7d3c790cbff8702cc7840a7818e5b626271f723 */ +static const uint8_t nist_kas_ecc_cdh_testvector_309_out[] = { +/* ZIUT */ + 0x03, 0x53, 0xff, 0x03, 0xaf, 0xda, 0x37, 0x72, 0x98, 0x4a, 0xad, 0xc4, + 0x00, 0x0e, 0x12, 0x75, 0x65, 0x66, 0x07, 0x15, 0x4b, 0x06, 0xc3, 0xa5, + 0x9c, 0x66, 0x49, 0x45, 0xfa, 0x6f, 0xde, 0x1c, 0x25, 0x5f, 0xfa, 0x86 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_310_public_x[] = { +/* QCAVSx */ + 0x04, 0xa5, 0x61, 0xb5, 0x18, 0x4a, 0xde, 0xd9, 0xc7, 0xbd, 0x98, 0x68, + 0xf3, 0x04, 0x3b, 0x5e, 0x2d, 0xe5, 0x19, 0x08, 0xf9, 0xc0, 0x3d, 0x5e, + 0x6b, 0x08, 0xa3, 0x08, 0x8b, 0xcc, 0x50, 0xee, 0x32, 0x03, 0xe2, 0x63 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_310_public_y[] = { +/* QCAVSy */ + 0x05, 0x81, 0x5b, 0x57, 0x9f, 0xf5, 0xde, 0xc6, 0xfa, 0xc9, 0x77, 0xba, + 0x70, 0x88, 0xb3, 0x33, 0xbf, 0x4c, 0x02, 0x31, 0xda, 0x02, 0x18, 0x74, + 0xee, 0x00, 0xd7, 0x1f, 0xe2, 0x5d, 0x3f, 0x4d, 0x50, 0xa5, 0x7a, 0xc3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_310_private[] = { +/* dIUT */ + 0x00, 0x46, 0x61, 0xf1, 0x07, 0xa9, 0xb5, 0x70, 0x04, 0x5d, 0xdb, 0xb0, + 0x73, 0x8a, 0xb6, 0x9b, 0x1c, 0x17, 0xa9, 0xac, 0xc1, 0x1d, 0xa5, 0xda, + 0xc7, 0xfd, 0x86, 0x4b, 0x3d, 0xfc, 0x36, 0xa2, 0x52, 0x82, 0xd6, 0xaa +}; +/* QIUTx = 061babbefee5211c4917506ce5f9f9e3d1e52b2506f38ca096e1b653ca9fb69f46105702 */ +/* QIUTy = 0014bfd2ef228b5a03e26230c1e897ad081a704013cee55166ca46de395fc52f5d21203a */ +static const uint8_t nist_kas_ecc_cdh_testvector_310_out[] = { +/* ZIUT */ + 0x05, 0x07, 0x95, 0xba, 0x09, 0x3d, 0x2e, 0x02, 0x39, 0x8c, 0x35, 0x89, + 0x51, 0xf2, 0x0c, 0x9e, 0x3b, 0x4f, 0x60, 0x62, 0x8a, 0x96, 0xa4, 0xd0, + 0xc4, 0x6c, 0xb8, 0xfc, 0x00, 0x05, 0xe5, 0x33, 0x1b, 0x38, 0xa0, 0x9a +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_311_public_x[] = { +/* QCAVSx */ + 0x01, 0xd7, 0xd7, 0x53, 0x6c, 0xd8, 0x38, 0x3e, 0x1c, 0x0b, 0x1b, 0x8a, + 0xae, 0x02, 0xba, 0xa9, 0xfd, 0x2c, 0x4e, 0x68, 0xb2, 0x18, 0x08, 0xc1, + 0x75, 0x4d, 0x0b, 0x15, 0x13, 0x61, 0x15, 0x7f, 0x81, 0x24, 0x59, 0x30 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_311_public_y[] = { +/* QCAVSy */ + 0x07, 0x30, 0x34, 0xda, 0x41, 0x67, 0x97, 0xda, 0x95, 0xa3, 0x83, 0x6e, + 0xef, 0x27, 0xb1, 0xfa, 0x27, 0x1f, 0x59, 0xa4, 0x34, 0x84, 0x8e, 0x98, + 0x0b, 0xad, 0x2f, 0xdd, 0x53, 0xff, 0xd1, 0xe3, 0x66, 0xff, 0x69, 0x17 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_311_private[] = { +/* dIUT */ + 0x00, 0x36, 0xbd, 0x21, 0xf8, 0x4a, 0xb9, 0xdb, 0x6f, 0x4b, 0xdd, 0xc9, + 0x46, 0x35, 0xf1, 0x9f, 0x80, 0xac, 0xb2, 0x81, 0x3d, 0xa5, 0x39, 0x9e, + 0x07, 0x77, 0x83, 0x2c, 0x2f, 0xeb, 0xdc, 0x71, 0x86, 0x2a, 0xbe, 0x33 +}; +/* QIUTx = 068ee3245754d51df7780046af39acb407c4998c620bff94fb374faf4b498006eea0cf88 */ +/* QIUTy = 0366a449f09ecfbaecc49d880307f57246c11c5bea00af42718677a8def15e5926da1822 */ +static const uint8_t nist_kas_ecc_cdh_testvector_311_out[] = { +/* ZIUT */ + 0x02, 0xab, 0x08, 0xd6, 0x3c, 0xdb, 0x4b, 0xe2, 0x50, 0x25, 0x58, 0xe6, + 0x7e, 0xab, 0x27, 0x57, 0x0f, 0x2d, 0x02, 0x9e, 0x7f, 0x98, 0x1d, 0x15, + 0x3b, 0x97, 0x30, 0x80, 0x58, 0x5d, 0x01, 0xe4, 0x2f, 0x71, 0x87, 0xd9 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_312_public_x[] = { +/* QCAVSx */ + 0x02, 0x04, 0x2f, 0x5a, 0x3f, 0xe5, 0xe3, 0xd3, 0x33, 0x5b, 0xb7, 0xbc, + 0xdb, 0x9d, 0xcb, 0xd8, 0x71, 0x6e, 0xd1, 0x8d, 0x7f, 0xc2, 0xff, 0x42, + 0x97, 0xbc, 0x1f, 0xeb, 0x7c, 0xca, 0x31, 0x00, 0x22, 0xe2, 0x21, 0x3d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_312_public_y[] = { +/* QCAVSy */ + 0x07, 0xbe, 0xbb, 0x6c, 0x0e, 0x04, 0x6d, 0x5a, 0xfd, 0xbf, 0xa8, 0x7e, + 0xa9, 0x8c, 0xa7, 0xf5, 0x5e, 0x9c, 0xdb, 0xb0, 0x55, 0xd0, 0xcc, 0x54, + 0x9b, 0x44, 0x58, 0xd6, 0x99, 0x8b, 0xdb, 0xb3, 0x45, 0x17, 0x73, 0x88 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_312_private[] = { +/* dIUT */ + 0x01, 0x65, 0x97, 0xae, 0x6e, 0x49, 0xe7, 0x9d, 0x06, 0x90, 0x34, 0x97, + 0x2a, 0x63, 0x52, 0x5a, 0x3c, 0x3e, 0x2d, 0x2c, 0x25, 0x3b, 0x9e, 0x1d, + 0xd3, 0xf3, 0x78, 0x16, 0x81, 0x2c, 0xf5, 0x4a, 0xd6, 0x5c, 0x54, 0x6a +}; +/* QIUTx = 050ea073522dbe51408f85f0a6086bd4c8efe572f80aadadd7e70ebb4b728bfdbfd4f1bc */ +/* QIUTy = 07da520017c7ad2916a2719b8558958f77c712d352cff9c0ad99fbc98a0e065eb7ac7feb */ +static const uint8_t nist_kas_ecc_cdh_testvector_312_out[] = { +/* ZIUT */ + 0x05, 0x99, 0x75, 0x7e, 0x3f, 0xfe, 0xb4, 0x84, 0xb3, 0x2d, 0x3b, 0x47, + 0x82, 0x8b, 0x68, 0x23, 0xd4, 0x67, 0x86, 0xd3, 0x54, 0x77, 0x08, 0x2c, + 0xea, 0xcf, 0x3a, 0x5a, 0x11, 0x55, 0x23, 0x94, 0xfe, 0x58, 0xf5, 0x3b +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_313_public_x[] = { +/* QCAVSx */ + 0x06, 0x7a, 0xfd, 0xf7, 0x88, 0xf8, 0xf4, 0x83, 0x1c, 0x3c, 0x7d, 0x76, + 0x04, 0xd0, 0x7a, 0x5b, 0xdc, 0x59, 0xda, 0x42, 0xd9, 0x32, 0x73, 0x1f, + 0xaf, 0x5e, 0xaf, 0x07, 0x53, 0x28, 0x09, 0x66, 0xab, 0x69, 0x37, 0x90 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_313_public_y[] = { +/* QCAVSy */ + 0x00, 0x1b, 0x39, 0xd1, 0xd8, 0x72, 0xb6, 0x5e, 0x31, 0x25, 0x1c, 0x1f, + 0x58, 0x4e, 0x4f, 0xe3, 0xed, 0x75, 0xd5, 0x3a, 0xd9, 0x0e, 0x83, 0x6f, + 0xe9, 0x0c, 0x8d, 0xb9, 0x4f, 0xe7, 0x7c, 0xef, 0x0b, 0xca, 0x72, 0x04 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_313_private[] = { +/* dIUT */ + 0x01, 0x5e, 0xa8, 0x56, 0x7c, 0x7b, 0x82, 0xb4, 0x83, 0xfa, 0x36, 0x5e, + 0x8e, 0x68, 0x1c, 0x0a, 0x63, 0x5f, 0x56, 0x3a, 0x1c, 0x81, 0x47, 0x0b, + 0x4d, 0xfe, 0x44, 0xf1, 0x94, 0xfa, 0x91, 0xeb, 0x78, 0x42, 0x18, 0x1e +}; +/* QIUTx = 07afe2b22b54fe895c242c20c054989fa804e591970dda8a7ce109d6bd31b6daa8f2fc74 */ +/* QIUTy = 060733bd5a4ea9b5ea7090acfee918106b7f25272f3f7cb36eda38bacd21375610cde928 */ +static const uint8_t nist_kas_ecc_cdh_testvector_313_out[] = { +/* ZIUT */ + 0x00, 0x5e, 0x33, 0x1a, 0xf5, 0x5e, 0x96, 0x15, 0x3d, 0x8a, 0x7b, 0x90, + 0x6a, 0x4a, 0x19, 0x01, 0x6a, 0x26, 0x38, 0x19, 0x77, 0xb4, 0x9f, 0x80, + 0xb9, 0xd7, 0x0d, 0xb0, 0x99, 0x05, 0x3c, 0x6a, 0x3b, 0x8e, 0x80, 0xd5 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_314_public_x[] = { +/* QCAVSx */ + 0x01, 0x88, 0x66, 0xa4, 0xfa, 0x2f, 0x7c, 0x25, 0x34, 0xe5, 0x63, 0xa2, + 0x91, 0xde, 0x87, 0x1a, 0x8b, 0x30, 0x52, 0xa6, 0x74, 0xf5, 0xdb, 0xc2, + 0x3b, 0x9d, 0xea, 0x0e, 0x8c, 0xef, 0xda, 0x06, 0xab, 0xc3, 0x2c, 0x8f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_314_public_y[] = { +/* QCAVSy */ + 0x05, 0x8d, 0xc4, 0xcf, 0x1b, 0xf9, 0x85, 0xd1, 0xb5, 0x66, 0x97, 0x08, + 0x47, 0xcb, 0xa6, 0xb8, 0xa4, 0xf4, 0x0c, 0x7e, 0x62, 0xa5, 0x80, 0x8b, + 0x07, 0x20, 0xbb, 0xb8, 0xcd, 0xf3, 0xb4, 0x53, 0x1e, 0x38, 0x0b, 0xe7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_314_private[] = { +/* dIUT */ + 0x00, 0x29, 0x11, 0xd9, 0x38, 0xd9, 0x50, 0x8a, 0xec, 0xcb, 0x98, 0x77, + 0xe1, 0x27, 0xd1, 0xb1, 0x46, 0x1a, 0xcd, 0xae, 0xd0, 0x35, 0xf2, 0x0e, + 0x0f, 0x74, 0x4c, 0x77, 0x4f, 0x1c, 0x72, 0x70, 0x3b, 0x5c, 0x4b, 0x49 +}; +/* QIUTx = 0386bfdfe60373be114b417c4dceb443223fde67c0fef29ed0f867b5a15f5ea0ccb4dcca */ +/* QIUTy = 02fac38ec8494cf7576233ec8282de384b67f0ca8048084201039d194c8bda4f6e0aff3e */ +static const uint8_t nist_kas_ecc_cdh_testvector_314_out[] = { +/* ZIUT */ + 0x07, 0xe1, 0x32, 0xea, 0x71, 0xa1, 0x6c, 0x7c, 0xc2, 0x61, 0xb9, 0xd6, + 0xff, 0x6f, 0xc5, 0x2c, 0xc4, 0x90, 0xda, 0x61, 0x6b, 0x07, 0xd9, 0x2f, + 0x9e, 0x59, 0x1f, 0xc1, 0xe6, 0x30, 0xd3, 0x44, 0x25, 0x72, 0x33, 0x8f +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_315_public_x[] = { +/* QCAVSx */ + 0x00, 0x05, 0x71, 0xd7, 0xbe, 0xf0, 0x56, 0x08, 0x91, 0x72, 0xf1, 0x34, + 0x23, 0xa5, 0x85, 0xab, 0x97, 0x9f, 0x4b, 0x8f, 0x77, 0xe7, 0x52, 0xc0, + 0x42, 0xc0, 0xc6, 0x52, 0x63, 0xb4, 0x76, 0x98, 0x1e, 0x5f, 0x31, 0x57 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_315_public_y[] = { +/* QCAVSy */ + 0x04, 0x4b, 0xca, 0x69, 0x3e, 0x9d, 0x3b, 0x1a, 0x7f, 0xa6, 0xad, 0x42, + 0xdb, 0x7f, 0x36, 0xb1, 0xa6, 0x57, 0x12, 0xd0, 0x9e, 0xf3, 0xbb, 0x71, + 0x5e, 0x26, 0x40, 0xa1, 0x82, 0xf4, 0x36, 0x62, 0x06, 0x86, 0xc0, 0xa4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_315_private[] = { +/* dIUT */ + 0x01, 0x66, 0x2f, 0x55, 0x48, 0x56, 0xc0, 0x20, 0x8a, 0x31, 0xb1, 0x95, + 0x14, 0x8f, 0x82, 0x8e, 0x0b, 0x5c, 0x92, 0xa4, 0xea, 0x4c, 0x03, 0x32, + 0x48, 0xbe, 0xbf, 0x95, 0x7b, 0x58, 0x6b, 0x40, 0x9e, 0xd5, 0x98, 0x50 +}; +/* QIUTx = 07055264c3de3a622d26fe7ad700bdea045d4b3ce718f4e6ae44cf376c3a96a2650b3221 */ +/* QIUTy = 00f45cc1138668adc8150d37c072bb4245660c18785683c7b17aa1fb8591ba6cda23657a */ +static const uint8_t nist_kas_ecc_cdh_testvector_315_out[] = { +/* ZIUT */ + 0x01, 0x0f, 0x26, 0x81, 0x70, 0x98, 0xce, 0x1b, 0xbd, 0x67, 0x43, 0x78, + 0x4d, 0x6f, 0xb6, 0x5e, 0x60, 0x69, 0x9c, 0x14, 0x93, 0x3a, 0x2c, 0x8d, + 0x85, 0x40, 0x27, 0xaa, 0x58, 0xb5, 0x8d, 0xb9, 0xe6, 0x6a, 0x53, 0xa7 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_316_public_x[] = { +/* QCAVSx */ + 0x01, 0x6e, 0xb4, 0xbb, 0xb3, 0xc3, 0x86, 0xe0, 0xf4, 0x2f, 0xb0, 0x37, + 0xbe, 0xe4, 0x78, 0xc4, 0xc0, 0xdb, 0xfb, 0xe5, 0x5c, 0xc6, 0x8e, 0x33, + 0xfd, 0xb0, 0x29, 0xb9, 0xe5, 0xe7, 0x24, 0xaf, 0xf4, 0xfd, 0x8b, 0xf6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_316_public_y[] = { +/* QCAVSy */ + 0x02, 0x51, 0x43, 0x2f, 0x84, 0x56, 0x8a, 0x44, 0x97, 0x1e, 0x86, 0xab, + 0x71, 0x5d, 0x38, 0x79, 0xe6, 0x14, 0xe1, 0x07, 0x25, 0x73, 0x5e, 0xf8, + 0xfb, 0x66, 0x52, 0xd0, 0x79, 0xc7, 0x90, 0x8f, 0x11, 0xbd, 0x1f, 0x01 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_316_private[] = { +/* dIUT */ + 0x01, 0x2c, 0x01, 0x00, 0xa9, 0x96, 0x3e, 0xe1, 0x7d, 0x7a, 0xcf, 0x4d, + 0xdf, 0x8e, 0x02, 0xd8, 0xae, 0x75, 0xf3, 0xb9, 0x91, 0x14, 0xf5, 0x36, + 0x6a, 0xfb, 0x4a, 0x00, 0xad, 0xe9, 0xa3, 0xc0, 0xee, 0x39, 0xa8, 0x87 +}; +/* QIUTx = 07794fa19c6b10d399e0f52d36f483c7851848e62bacf95b5af51eca09ad445ee19ef34d */ +/* QIUTy = 06140d2ee16cd0a6cb1960509a7ccc664be97644a95ae16f4a173d9a867015f0837f0560 */ +static const uint8_t nist_kas_ecc_cdh_testvector_316_out[] = { +/* ZIUT */ + 0x00, 0xbd, 0xd8, 0xcc, 0xd1, 0xb4, 0x0c, 0x5b, 0xc2, 0xef, 0xc1, 0xc1, + 0x05, 0x99, 0x93, 0x50, 0xfe, 0xfa, 0xf7, 0x84, 0x71, 0x09, 0x14, 0xff, + 0x63, 0x95, 0x82, 0xf1, 0x27, 0x76, 0x78, 0x69, 0x94, 0x91, 0x14, 0x0c +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_317_public_x[] = { +/* QCAVSx */ + 0x02, 0x41, 0x7c, 0x65, 0x69, 0x4d, 0x85, 0x0c, 0x7c, 0x86, 0x6f, 0x7e, + 0x11, 0x63, 0x9a, 0x5f, 0x87, 0x18, 0xca, 0x9a, 0xab, 0xb3, 0x92, 0xfa, + 0x86, 0x10, 0xe2, 0xd5, 0xd7, 0xdd, 0xa3, 0x37, 0x5a, 0x60, 0x7f, 0x9b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_317_public_y[] = { +/* QCAVSy */ + 0x05, 0x13, 0x39, 0x38, 0xdc, 0x99, 0x14, 0x4d, 0x16, 0xea, 0x75, 0x25, + 0xc3, 0xfe, 0x4e, 0x32, 0xe3, 0x20, 0xed, 0x07, 0x5b, 0x96, 0x52, 0x7e, + 0x13, 0xb2, 0xa9, 0x9c, 0x9f, 0x27, 0xad, 0xe9, 0xef, 0x9e, 0xdc, 0xb6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_317_private[] = { +/* dIUT */ + 0x03, 0x45, 0xc2, 0x76, 0xb0, 0x5e, 0xce, 0x9e, 0x7c, 0x86, 0x81, 0x1f, + 0x8c, 0x8a, 0xf4, 0x8b, 0x22, 0xdb, 0x41, 0xd4, 0x06, 0x62, 0x75, 0x00, + 0x96, 0x11, 0xb8, 0x80, 0xd7, 0xd2, 0xce, 0xf3, 0x29, 0xc5, 0x0e, 0x82 +}; +/* QIUTx = 007afffcfa31c110aab3bb394530a41c416af566bfba8f159f984437e799dddaaf8cdfd2 */ +/* QIUTy = 065fb3c68446a74068bab7e36ab80e984707e39a4a143f5a46d646342f9f12f26a32291b */ +static const uint8_t nist_kas_ecc_cdh_testvector_317_out[] = { +/* ZIUT */ + 0x01, 0x4a, 0x83, 0xe7, 0x47, 0xc9, 0x0a, 0xec, 0x61, 0x01, 0xc0, 0xa7, + 0x52, 0xd9, 0x2e, 0xef, 0x74, 0x75, 0xb0, 0x00, 0x51, 0xec, 0xad, 0x3d, + 0x7c, 0x2e, 0x50, 0xcf, 0x4e, 0xba, 0x1e, 0xf3, 0xc8, 0x0b, 0x8c, 0x94 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_318_public_x[] = { +/* QCAVSx */ + 0x00, 0xc5, 0xd6, 0x14, 0x9f, 0x87, 0x17, 0x4b, 0xa3, 0x7f, 0x4c, 0x1c, + 0x6f, 0x67, 0xf6, 0x90, 0x5a, 0xbb, 0x31, 0x9f, 0x52, 0x6b, 0x7a, 0xa1, + 0xbe, 0x1d, 0xd2, 0x05, 0xdf, 0x93, 0x0a, 0xb1, 0xc9, 0x1b, 0xb1, 0xf8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_318_public_y[] = { +/* QCAVSy */ + 0x00, 0xc2, 0xe2, 0x1e, 0x12, 0x06, 0xcd, 0x4b, 0xb5, 0xb6, 0x22, 0xab, + 0xe9, 0x7c, 0xa3, 0xf2, 0x52, 0xcb, 0xc6, 0x8d, 0x05, 0x4a, 0x77, 0xf8, + 0xeb, 0xab, 0xad, 0x59, 0x3f, 0xb1, 0x86, 0x33, 0x06, 0x92, 0x8b, 0xf7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_318_private[] = { +/* dIUT */ + 0x03, 0xaf, 0xd5, 0xaf, 0xfa, 0x34, 0x6b, 0x52, 0x59, 0x69, 0x7d, 0x92, + 0x17, 0x95, 0x2a, 0xfc, 0xd0, 0x3d, 0xdf, 0xec, 0x04, 0x63, 0x1b, 0xd9, + 0x95, 0xc1, 0x0a, 0xc2, 0x58, 0x3b, 0x0c, 0xa8, 0xd2, 0x46, 0x1f, 0x5d +}; +/* QIUTx = 06b4c2c3615b266543de189c896cff77b5557c782c215961ac7324185fc9a81098f2ebea */ +/* QIUTy = 047fef1960739ae0aee39a3ffdb82e890d4236fc22dad395d490bc3a5eea58e8cd03edbb */ +static const uint8_t nist_kas_ecc_cdh_testvector_318_out[] = { +/* ZIUT */ + 0x00, 0xaf, 0xd2, 0x9e, 0x35, 0x27, 0x79, 0xa3, 0x90, 0x21, 0x53, 0x6e, + 0xa5, 0x0c, 0x24, 0xfa, 0x26, 0x4c, 0x59, 0x9f, 0x8f, 0x8f, 0xe8, 0xf2, + 0xcc, 0xf0, 0x61, 0x5a, 0x65, 0x47, 0xa0, 0x64, 0xd7, 0xc1, 0xa1, 0x50 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_319_public_x[] = { +/* QCAVSx */ + 0x01, 0x73, 0x04, 0x4e, 0x5b, 0xe6, 0x39, 0x97, 0xd7, 0x92, 0x5e, 0x43, + 0x1b, 0xbf, 0x00, 0x4c, 0xf0, 0xf0, 0xba, 0x85, 0xaa, 0x29, 0x5a, 0x34, + 0x1e, 0x8f, 0x58, 0x57, 0xa1, 0x20, 0xbe, 0x89, 0xd7, 0x76, 0x53, 0xe9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_319_public_y[] = { +/* QCAVSy */ + 0x07, 0x37, 0xcc, 0x04, 0x96, 0x90, 0xf9, 0x70, 0x82, 0x4a, 0x7b, 0x0c, + 0x20, 0x22, 0x43, 0x96, 0x82, 0xc9, 0xd8, 0x2f, 0x4f, 0x23, 0xe4, 0x8e, + 0x5f, 0x07, 0xfe, 0xa9, 0x62, 0x67, 0xca, 0x3b, 0xd4, 0xd7, 0x30, 0xa5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_319_private[] = { +/* dIUT */ + 0x03, 0xd5, 0x77, 0x1f, 0x84, 0x85, 0xc3, 0xb8, 0xbe, 0x62, 0xa5, 0x6f, + 0x39, 0x36, 0x51, 0x3e, 0x3b, 0x63, 0x1a, 0x56, 0x1a, 0x94, 0x26, 0x13, + 0xdf, 0x95, 0x14, 0x0f, 0x47, 0x32, 0x14, 0xdf, 0x61, 0x7c, 0x4c, 0x4e +}; +/* QIUTx = 05906cc4529b220228efbb0545bf55ec03c86f87e2f4e3a3cbf404e07b73a5b1a5f528cd */ +/* QIUTy = 016588e480c4856cd2ee9aaf1e302812fbc0b33f527c29b77ce0f4878ea089d025a440c0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_319_out[] = { +/* ZIUT */ + 0x04, 0x77, 0x99, 0x0f, 0x17, 0xd6, 0x55, 0x89, 0x28, 0x9c, 0x28, 0xe5, + 0x4a, 0x56, 0xa8, 0x3b, 0xc0, 0x5e, 0xf4, 0xea, 0x68, 0x63, 0xc5, 0xeb, + 0xe8, 0x40, 0x92, 0x5c, 0x9f, 0xbe, 0xf6, 0x4c, 0xcd, 0x6e, 0x69, 0xa4 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_320_public_x[] = { +/* QCAVSx */ + 0x06, 0x85, 0x87, 0xe6, 0x9d, 0xed, 0xdf, 0x4b, 0x55, 0xac, 0x51, 0xf2, + 0xa1, 0x7d, 0xd8, 0xbf, 0xd6, 0xf9, 0x4e, 0x72, 0x10, 0x03, 0x21, 0x42, + 0x15, 0xbf, 0xb2, 0x4b, 0x24, 0x82, 0x81, 0xe7, 0x5a, 0x3c, 0x65, 0x94 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_320_public_y[] = { +/* QCAVSy */ + 0x04, 0x4e, 0xee, 0x9c, 0x70, 0x2b, 0xc4, 0xc1, 0xe2, 0x10, 0xc7, 0xcc, + 0x21, 0x45, 0x24, 0x59, 0x25, 0x68, 0xac, 0x0f, 0x9f, 0xd6, 0x7d, 0x6e, + 0xa0, 0x2b, 0x4d, 0xc3, 0xef, 0xb4, 0x2c, 0xfb, 0xb2, 0x26, 0x3d, 0xac +}; +static const uint8_t nist_kas_ecc_cdh_testvector_320_private[] = { +/* dIUT */ + 0x00, 0xe2, 0xc0, 0xc6, 0x02, 0xfb, 0x13, 0x23, 0x99, 0xee, 0x9f, 0x31, + 0x00, 0x83, 0x65, 0xea, 0x22, 0xcc, 0x12, 0x60, 0xf7, 0x9f, 0xe3, 0xae, + 0x61, 0x08, 0x9b, 0x8a, 0x6f, 0xa4, 0x55, 0x9c, 0xac, 0x91, 0xae, 0xc8 +}; +/* QIUTx = 06e6e318c0c4c0b661dfd3e722090ecd32fdc9ca3d168d9c7174c1d40adbb2ce672d9252 */ +/* QIUTy = 040bdc1dbc7b163f7c9551f47daa8294ac2dc4fe0d472c4e2f2cfefc95d523ff59e0e880 */ +static const uint8_t nist_kas_ecc_cdh_testvector_320_out[] = { +/* ZIUT */ + 0x06, 0x7a, 0x66, 0x13, 0x46, 0xfe, 0x05, 0x2c, 0xa2, 0x7f, 0x3f, 0x03, + 0xe7, 0x5b, 0xbd, 0xfc, 0x8f, 0xe6, 0xd0, 0xd8, 0x5c, 0x62, 0xc8, 0xf7, + 0x95, 0x25, 0x25, 0x2a, 0xa2, 0x41, 0xae, 0x9d, 0xe9, 0x7d, 0x56, 0xc3 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_321_public_x[] = { +/* QCAVSx */ + 0x03, 0xf1, 0x22, 0x6d, 0x80, 0x2c, 0x57, 0x5f, 0x87, 0x1a, 0x21, 0x3b, + 0x81, 0x50, 0xf7, 0x81, 0x8b, 0xbd, 0x62, 0x56, 0x63, 0xb7, 0x3e, 0x72, + 0x0a, 0x73, 0x7f, 0x07, 0x18, 0x96, 0x08, 0x6d, 0xa0, 0xb1, 0x4c, 0xd9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_321_public_y[] = { +/* QCAVSy */ + 0x07, 0xd1, 0xcb, 0x0c, 0xe1, 0x9c, 0x98, 0xa6, 0x3a, 0xaf, 0x7b, 0x31, + 0x4f, 0x1f, 0x57, 0x20, 0xe3, 0x28, 0x87, 0x05, 0x33, 0x84, 0xac, 0x0f, + 0x5e, 0xb6, 0x9b, 0x6c, 0x47, 0x1a, 0x8e, 0x3d, 0x3d, 0x16, 0xe7, 0x6f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_321_private[] = { +/* dIUT */ + 0x03, 0x2d, 0x57, 0x3f, 0xde, 0xb8, 0x5a, 0x4d, 0xa2, 0x29, 0x78, 0x96, + 0x63, 0x14, 0x14, 0x51, 0x8d, 0x4b, 0xa0, 0x7d, 0xc4, 0xdd, 0x72, 0xf7, + 0x31, 0x72, 0x88, 0x90, 0xd0, 0xb4, 0x4d, 0x36, 0xf2, 0x30, 0x9c, 0x0e +}; +/* QIUTx = 06f6ffea0a87bd9eeb539c48a3fcbf388159862259c7f7840e64809fbedb01a83812c0c6 */ +/* QIUTy = 07c795b8f2847fc39fa56c2de1e6cbbf4945087cb2e3b919dc776b4cc1c83e4b1c79b8ba */ +static const uint8_t nist_kas_ecc_cdh_testvector_321_out[] = { +/* ZIUT */ + 0x06, 0x47, 0x6b, 0x06, 0x20, 0xee, 0xf1, 0x65, 0x94, 0x1a, 0x45, 0x07, + 0xe6, 0xd7, 0x98, 0xd6, 0xf1, 0x50, 0xab, 0x29, 0x33, 0x3c, 0x05, 0x52, + 0x28, 0x1b, 0x62, 0x91, 0x70, 0xd3, 0x29, 0x1b, 0x2f, 0x9b, 0x3f, 0x41 +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_322_public_x[] = { +/* QCAVSx */ + 0x02, 0xa9, 0x11, 0xe7, 0xe6, 0xd2, 0xfc, 0x77, 0x0d, 0x1e, 0xab, 0xc7, + 0xdf, 0x70, 0x1b, 0xb1, 0x19, 0x08, 0x4a, 0x68, 0x59, 0x00, 0xd2, 0x2d, + 0x52, 0xd5, 0x98, 0xfe, 0x1d, 0x28, 0xfc, 0x89, 0x1b, 0x31, 0xb4, 0x87 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_322_public_y[] = { +/* QCAVSy */ + 0x01, 0xb8, 0xdc, 0x67, 0x13, 0xca, 0x45, 0x3e, 0x91, 0xb2, 0xec, 0x4e, + 0x4d, 0x1f, 0x83, 0x4b, 0x08, 0xee, 0xbc, 0x7e, 0x88, 0x86, 0xc3, 0xa4, + 0x58, 0xe7, 0x09, 0x25, 0x24, 0x2c, 0x4b, 0x22, 0xbf, 0x0b, 0x20, 0x53 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_322_private[] = { +/* dIUT */ + 0x00, 0xa6, 0xaa, 0xcb, 0x5d, 0xd3, 0xe8, 0x35, 0x81, 0x4f, 0x45, 0x2d, + 0x82, 0x07, 0xd1, 0x5a, 0x53, 0x36, 0x38, 0xf7, 0x0e, 0x94, 0xf8, 0x7c, + 0x06, 0x19, 0x6e, 0xff, 0x88, 0x38, 0xd4, 0x8e, 0xed, 0x2e, 0x26, 0x74 +}; +/* QIUTx = 02dd0093a8d419831f34bac6c60a570c51d08e699b181c964b667d0d17ed72a49119acd9 */ +/* QIUTy = 01a91976be5d5e037f22350d67ab7bfab51bbc4fa6026d347d28fb4407bccc40dd10a00e */ +static const uint8_t nist_kas_ecc_cdh_testvector_322_out[] = { +/* ZIUT */ + 0x07, 0x46, 0x71, 0x9f, 0x2a, 0xd0, 0x8f, 0x8a, 0x8d, 0x6d, 0x6f, 0xbf, + 0x15, 0x72, 0x3f, 0x33, 0x62, 0x85, 0xce, 0x75, 0xd3, 0xa2, 0xfc, 0xbd, + 0x5a, 0x0c, 0x54, 0xc5, 0x77, 0x51, 0x7a, 0x22, 0xbc, 0x26, 0x41, 0x61 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_323_public_x[] = { +/* QCAVSx */ + 0x07, 0x54, 0x1a, 0xa5, 0x1d, 0x73, 0x02, 0xe2, 0xbb, 0x55, 0x7c, 0x27, + 0xec, 0x15, 0xd7, 0xf9, 0xc3, 0xae, 0x3b, 0x76, 0xec, 0x2f, 0x86, 0xcb, + 0x95, 0xe8, 0xde, 0xad, 0x7f, 0xa0, 0x6b, 0x57, 0x83, 0x97, 0xf1, 0xf1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_323_public_y[] = { +/* QCAVSy */ + 0x01, 0x7e, 0xa2, 0x2f, 0x6b, 0x54, 0x74, 0xf0, 0xf5, 0xf0, 0xf4, 0xea, + 0xd5, 0x41, 0x72, 0x06, 0x40, 0x51, 0x53, 0x8d, 0x3e, 0x23, 0x2a, 0x53, + 0x0d, 0xfc, 0xa5, 0xf2, 0xa0, 0xdc, 0x67, 0x74, 0x6c, 0x8b, 0xb1, 0xda +}; +static const uint8_t nist_kas_ecc_cdh_testvector_323_private[] = { +/* dIUT */ + 0x00, 0x11, 0x2f, 0xb2, 0xab, 0x56, 0x44, 0x37, 0x65, 0x67, 0x6a, 0x1e, + 0x41, 0xb3, 0xcb, 0x91, 0xeb, 0x1a, 0x67, 0x90, 0xe9, 0x64, 0xee, 0x90, + 0x0c, 0xfc, 0x92, 0x95, 0x63, 0x6b, 0xa4, 0xc6, 0xfa, 0x87, 0xaa, 0xd2 +}; +/* QIUTx = 03f507d99cc2498e2c7f54fb3c9c032f382548e2e3168fa140125a526048568f3bb3e5a1 */ +/* QIUTy = 05270df77efc7d6c55f9259bc82273c9b6bdf3676e13c3601b1b3022b962de1129cb3b14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_323_out[] = { +/* ZIUT */ + 0x03, 0xcd, 0xa4, 0xb5, 0xf4, 0x4b, 0x5d, 0x3d, 0xc2, 0x48, 0x31, 0x0f, + 0x99, 0x44, 0x19, 0xfb, 0xcb, 0xd6, 0x65, 0x11, 0x5d, 0x18, 0x76, 0x04, + 0x66, 0x52, 0x25, 0x1a, 0xd4, 0xae, 0xeb, 0x1d, 0xcf, 0x18, 0x42, 0x88 +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_324_public_x[] = { +/* QCAVSx */ + 0x02, 0x1f, 0xb1, 0x4e, 0x52, 0xcd, 0x42, 0x43, 0xa5, 0x20, 0xf6, 0x30, + 0x22, 0x9b, 0x1d, 0xd6, 0x96, 0x1c, 0x49, 0xbd, 0x96, 0xf4, 0x3f, 0xa9, + 0xca, 0xe3, 0x7a, 0xdd, 0x84, 0xda, 0x7a, 0xe7, 0x2d, 0xc3, 0x07, 0x8e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_324_public_y[] = { +/* QCAVSy */ + 0x00, 0xdd, 0x63, 0x8b, 0xf9, 0x05, 0x3f, 0xad, 0x6a, 0xa4, 0xff, 0x2d, + 0x33, 0x0b, 0x8a, 0x4a, 0x20, 0xbf, 0xe3, 0x02, 0x0f, 0x40, 0xb9, 0x69, + 0x23, 0x02, 0xd0, 0xb0, 0xa3, 0xc2, 0xd8, 0x77, 0x85, 0x6e, 0xc4, 0x6a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_324_private[] = { +/* dIUT */ + 0x03, 0xe4, 0xf1, 0xc4, 0xf3, 0x0e, 0x2a, 0x8d, 0x6f, 0xd5, 0x59, 0xf7, + 0xfe, 0x88, 0x20, 0xe8, 0x86, 0x94, 0x9d, 0xe8, 0x7c, 0x01, 0xd8, 0xeb, + 0x64, 0xc7, 0xb4, 0x0f, 0x15, 0x48, 0xcb, 0x61, 0x7a, 0x92, 0x60, 0x33 +}; +/* QIUTx = 05e3fc56ec162885c1291e4ae9c19c8eb2bb559eb7ecd5817549b5a2ea3a66d951880aa6 */ +/* QIUTy = 04c004f2ae4db4f748b437bc115e06ea2017a87798298dd6004616fcffdcc7ec2dfd6db9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_324_out[] = { +/* ZIUT */ + 0x01, 0x5c, 0x89, 0x2f, 0x95, 0x76, 0x8a, 0x96, 0xab, 0x5a, 0x4f, 0x95, + 0x23, 0xb7, 0xfd, 0x46, 0x6e, 0x10, 0x1f, 0x63, 0xb8, 0x8a, 0xd8, 0xf1, + 0xfe, 0xcb, 0x30, 0x27, 0xcd, 0x70, 0xaa, 0x00, 0x73, 0x5d, 0xcc, 0x90 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_325_public_x[] = { +/* QCAVSx */ + 0x00, 0xd0, 0x8e, 0xd3, 0x85, 0x6a, 0xbe, 0xf7, 0xd4, 0xa6, 0x22, 0x43, + 0xc9, 0x2d, 0x6e, 0x67, 0x0c, 0xeb, 0x3a, 0xf3, 0x23, 0x57, 0xfd, 0xb9, + 0xd3, 0x9c, 0x19, 0x17, 0x5a, 0x10, 0xd1, 0xcb, 0xab, 0x36, 0xce, 0x78 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_325_public_y[] = { +/* QCAVSy */ + 0x05, 0xdb, 0x9f, 0xad, 0x7f, 0xc8, 0xaf, 0xe7, 0x9c, 0x8b, 0x9c, 0xe4, + 0x8e, 0x62, 0xff, 0xa0, 0xd4, 0x6b, 0x80, 0x5a, 0x9e, 0x58, 0x21, 0xe2, + 0x76, 0x1c, 0x25, 0xc0, 0xed, 0xba, 0x92, 0xb1, 0x20, 0xb0, 0x63, 0xf2 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_325_private[] = { +/* dIUT */ + 0x00, 0xae, 0x7e, 0xb3, 0xd4, 0x03, 0x54, 0xf9, 0xf8, 0xfe, 0xd1, 0x8f, + 0x21, 0x62, 0xde, 0xe3, 0x81, 0x56, 0xca, 0xe0, 0x53, 0x5b, 0x55, 0x37, + 0x0d, 0xa3, 0x63, 0x8f, 0x01, 0x66, 0x8a, 0xec, 0xf9, 0x70, 0x8b, 0xe6 +}; +/* QIUTx = 061e8858e368d9c917f129d932ddc4cca521ff419f1d74230e8aa5b1b3e9ce67f41c4b4c */ +/* QIUTy = 02b0d7fbdc636a3bc34bbdd2a89291b567b0fb2af32383868bd40d4ba4cac9880c2540b8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_325_out[] = { +/* ZIUT */ + 0x01, 0xad, 0xf5, 0xa9, 0x63, 0x58, 0xe1, 0x8d, 0x69, 0xfd, 0x38, 0x3b, + 0x4d, 0xc7, 0xb2, 0x0d, 0xd6, 0x46, 0xb6, 0x8a, 0x5c, 0x9f, 0x14, 0x17, + 0xbc, 0xf4, 0x26, 0x24, 0x0c, 0xa2, 0x2b, 0x8f, 0x32, 0xbd, 0xf1, 0xa4 +}; +/* [B-409] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_326_public_x[] = { +/* QCAVSx */ + 0x01, 0x46, 0x98, 0x9a, 0x50, 0x29, 0x7b, 0xe3, 0x73, 0xdd, 0x66, 0x5c, + 0x45, 0x45, 0x5a, 0x2a, 0xe4, 0xc2, 0x21, 0xda, 0x5c, 0xd4, 0x24, 0x00, + 0x7b, 0xd9, 0x7f, 0x9e, 0x8e, 0x84, 0x6f, 0x96, 0x74, 0x0f, 0x3f, 0xa5, + 0x8c, 0x3c, 0x94, 0x12, 0x96, 0x71, 0xcd, 0xd4, 0xd7, 0xea, 0x65, 0x0a, + 0x2a, 0xad, 0xe9, 0xd7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_326_public_y[] = { +/* QCAVSy */ + 0x01, 0xb4, 0x2b, 0xff, 0xda, 0x84, 0x39, 0x46, 0xa1, 0x4a, 0xd6, 0x08, + 0x0f, 0x95, 0xb8, 0xfc, 0x6b, 0x7e, 0x17, 0x35, 0x28, 0xd0, 0x8e, 0xd3, + 0x6f, 0xe6, 0x40, 0xaa, 0xf8, 0x5a, 0xa0, 0x0f, 0xb5, 0xed, 0xd5, 0x90, + 0x5a, 0x38, 0xb3, 0xc7, 0x96, 0x1b, 0x77, 0x22, 0xb7, 0x7b, 0x8d, 0xcb, + 0x44, 0xbb, 0x25, 0xf5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_326_private[] = { +/* dIUT */ + 0x00, 0xac, 0xe9, 0x21, 0x03, 0xff, 0xe2, 0x62, 0xac, 0x17, 0xad, 0x42, + 0xa4, 0x6d, 0x43, 0x66, 0xf4, 0xcb, 0x4c, 0x58, 0x0e, 0xff, 0x3a, 0xb1, + 0xdd, 0xe6, 0xbd, 0xdf, 0xdb, 0xb7, 0x37, 0x48, 0x11, 0xd5, 0x2b, 0x1f, + 0xa9, 0x93, 0x20, 0xb4, 0xaf, 0x5d, 0x4e, 0x92, 0x08, 0xc1, 0x4e, 0xb8, + 0xef, 0xa8, 0x91, 0x6c +}; +/* QIUTx = 004ebc4d4acf9b404dabc3af3e8cbea8b88b32999d3ecb7f367b12eb3a6280b840038e22681637a7d16436e014f69616abf72e45 */ +/* QIUTy = 009e24109541c8024217e9ab2c963fa9e373640095a6c25a26eefac58e4342c0c85448b2709592a12402fe2b68a793c558ce8cd6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_326_out[] = { +/* ZIUT */ + 0x01, 0xd4, 0x8a, 0x58, 0x6b, 0xe9, 0x28, 0x5f, 0xa3, 0x8d, 0xd3, 0xe7, + 0x0b, 0x03, 0x30, 0xb0, 0xff, 0xeb, 0xd3, 0x27, 0xce, 0xef, 0xef, 0x88, + 0xfd, 0xc1, 0x52, 0x1e, 0xf2, 0xfd, 0x61, 0xcb, 0xc9, 0x12, 0x4e, 0x03, + 0xb0, 0xc9, 0x26, 0xe7, 0x0f, 0xa5, 0x6a, 0xcb, 0x3e, 0xdb, 0x54, 0xc3, + 0xc4, 0x8f, 0xab, 0x2b +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_327_public_x[] = { +/* QCAVSx */ + 0x01, 0x7e, 0x9f, 0x01, 0xb1, 0xd6, 0xe5, 0x70, 0x23, 0x28, 0x33, 0x0d, + 0x23, 0x2a, 0x1d, 0xd3, 0xf2, 0xc5, 0x92, 0xcc, 0x40, 0x9f, 0x6c, 0xae, + 0xf0, 0x70, 0x84, 0x40, 0x83, 0x7f, 0x35, 0x97, 0x51, 0x0f, 0x11, 0x19, + 0x54, 0xaa, 0x51, 0xe5, 0x64, 0x6c, 0xcf, 0x47, 0xef, 0xf1, 0xf0, 0x7a, + 0x4f, 0x8a, 0xe1, 0xcb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_327_public_y[] = { +/* QCAVSy */ + 0x00, 0x37, 0x14, 0xf6, 0xea, 0x1f, 0xd1, 0x43, 0xce, 0x75, 0x1e, 0x2d, + 0x85, 0xba, 0xf5, 0x4c, 0x55, 0x23, 0x97, 0x61, 0x08, 0xed, 0x48, 0x2f, + 0xd6, 0xae, 0x10, 0x37, 0x43, 0x13, 0x1c, 0xa7, 0x16, 0x02, 0x6b, 0x16, + 0xa1, 0xe4, 0x96, 0x23, 0x1f, 0x99, 0x1c, 0xdc, 0x8f, 0x6d, 0xb4, 0x47, + 0xf5, 0xf9, 0x5f, 0x8e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_327_private[] = { +/* dIUT */ + 0x00, 0x3f, 0xf2, 0x2f, 0x7d, 0x7c, 0x04, 0x99, 0x89, 0xa4, 0x3e, 0x0e, + 0xa3, 0xf5, 0xd6, 0x17, 0x98, 0x15, 0x9c, 0x17, 0x8a, 0xa7, 0x92, 0xd7, + 0x9d, 0x1f, 0xfe, 0xbf, 0xf8, 0xdb, 0x70, 0xee, 0x1f, 0xde, 0x04, 0x0a, + 0x4b, 0x5f, 0x1e, 0xd3, 0x3f, 0xb3, 0xff, 0x23, 0xc4, 0x4e, 0x7c, 0x6b, + 0x21, 0xb0, 0x62, 0x3b +}; +/* QIUTx = 01d5c9260e73ea36e4deaaa4b8f4541f678066b690771a86f0dadc580fdb895981e6dd02dd264ed9f9c1763bd54a6052a2d3dba7 */ +/* QIUTy = 011a706826365ece28e38b33620bca016d2d9338518dfd6868370476dacb41e3b947465769ebe81b620731673576f77451d0fe14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_327_out[] = { +/* ZIUT */ + 0x01, 0x85, 0x6c, 0x92, 0xb4, 0x6d, 0x67, 0x1d, 0x8a, 0x7f, 0x6c, 0xc4, + 0x68, 0xef, 0xb6, 0x0a, 0x61, 0x09, 0x3d, 0x00, 0x6c, 0x95, 0xbb, 0x93, + 0x1c, 0x1f, 0xcc, 0xc3, 0x36, 0xd4, 0xa8, 0x49, 0x0f, 0xe1, 0x7f, 0xe1, + 0x63, 0xc9, 0x72, 0xba, 0xc3, 0x9f, 0xe7, 0x28, 0xf2, 0x45, 0x34, 0xa0, + 0xc3, 0x4d, 0x2d, 0x21 +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_328_public_x[] = { +/* QCAVSx */ + 0x01, 0x83, 0xee, 0x35, 0x5a, 0x93, 0xcd, 0x13, 0xaf, 0xf1, 0x75, 0x6a, + 0x08, 0xe5, 0x8e, 0x21, 0x95, 0xa8, 0x26, 0x29, 0x8d, 0x43, 0xf6, 0xd0, + 0x7b, 0xb1, 0xc3, 0x82, 0xb4, 0xe5, 0x68, 0xd0, 0x08, 0x09, 0x39, 0x26, + 0x00, 0x09, 0xc6, 0xaf, 0xcb, 0xed, 0x0f, 0x23, 0x25, 0x2e, 0x01, 0xd6, + 0xd1, 0x4c, 0x6d, 0x8f +}; +static const uint8_t nist_kas_ecc_cdh_testvector_328_public_y[] = { +/* QCAVSy */ + 0x01, 0xb2, 0x30, 0x9b, 0x38, 0x19, 0xc2, 0x45, 0x4a, 0x48, 0xad, 0x25, + 0x3a, 0xc9, 0x7b, 0xce, 0x3c, 0x79, 0xb5, 0x1f, 0x50, 0xed, 0x68, 0x03, + 0xcf, 0x05, 0x46, 0x4b, 0x74, 0xa5, 0xa1, 0xde, 0x22, 0x11, 0x3e, 0x23, + 0xc0, 0x18, 0xc5, 0xce, 0xd9, 0x18, 0x6d, 0xdb, 0x98, 0x1c, 0x62, 0x9e, + 0x2e, 0x9d, 0xb3, 0xee +}; +static const uint8_t nist_kas_ecc_cdh_testvector_328_private[] = { +/* dIUT */ + 0x00, 0x96, 0xde, 0x2c, 0x39, 0x29, 0xc4, 0x08, 0x5f, 0x9c, 0xc1, 0xd3, + 0x77, 0x8c, 0x2d, 0xbf, 0x3d, 0xb7, 0xf0, 0xf7, 0x7e, 0x7b, 0xa7, 0xbb, + 0xc4, 0xe4, 0x08, 0xc7, 0xd6, 0x5e, 0x2c, 0x8b, 0x88, 0xb0, 0x75, 0x5f, + 0x16, 0x0b, 0xad, 0xb5, 0x24, 0xe7, 0x69, 0x7c, 0x50, 0xe6, 0x0c, 0x8d, + 0x99, 0xe5, 0x6d, 0xa4 +}; +/* QIUTx = 019c47d79914c8bdae754ec5ec1e81c8ff329a938e6971eee3c945c4ebf489e14b15e6135616c898c80b7b06b8af67061c769ab5 */ +/* QIUTy = 000088022b4fb0e754ec4fab8cf4fc636255426755fa99b56805c15eac04325155dccbfa4145e161c40f189bdbaa3dd3e0c3d6c9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_328_out[] = { +/* ZIUT */ + 0x01, 0x97, 0x2e, 0x22, 0x5e, 0x08, 0xb4, 0x75, 0x12, 0xe9, 0x2c, 0x0d, + 0xa9, 0xa1, 0xbd, 0xdd, 0xb1, 0x80, 0x2b, 0xe4, 0x02, 0x22, 0x2c, 0xac, + 0x57, 0x88, 0xb3, 0x22, 0xe1, 0x01, 0xfe, 0xeb, 0x06, 0xb6, 0x6b, 0x2f, + 0xe7, 0x26, 0xc1, 0xcd, 0x8a, 0xec, 0x92, 0xe0, 0x2f, 0x37, 0xd1, 0x5f, + 0x4c, 0x97, 0xe6, 0x4d +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_329_public_x[] = { +/* QCAVSx */ + 0x00, 0xe8, 0x5d, 0xe9, 0xd6, 0x3e, 0x34, 0xe5, 0xc7, 0xbb, 0xa6, 0xff, + 0x9b, 0x16, 0xf4, 0xc8, 0x4d, 0x95, 0xf1, 0x1d, 0xfe, 0x92, 0x10, 0x7b, + 0x1f, 0xbe, 0xca, 0xe9, 0x8c, 0xe6, 0xef, 0xf3, 0xdb, 0x96, 0xd8, 0x69, + 0x00, 0xbf, 0xd2, 0x2c, 0xd4, 0x23, 0xdb, 0xce, 0x1e, 0x57, 0x26, 0xbe, + 0x8e, 0x59, 0x79, 0x33 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_329_public_y[] = { +/* QCAVSy */ + 0x00, 0xb7, 0x14, 0x17, 0x71, 0xf7, 0xc8, 0x16, 0xd5, 0x5e, 0xc8, 0xc5, + 0x38, 0x22, 0xd2, 0xe7, 0xa1, 0x92, 0xfa, 0x54, 0xa1, 0x7e, 0x5b, 0x99, + 0xb2, 0xd9, 0x09, 0x61, 0xb5, 0x4a, 0x99, 0xfe, 0xd5, 0x3a, 0xba, 0x4b, + 0xda, 0x1a, 0x40, 0x74, 0xad, 0x3d, 0x23, 0xf9, 0xc9, 0x11, 0x20, 0x57, + 0x95, 0xb5, 0x45, 0x0b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_329_private[] = { +/* dIUT */ + 0x00, 0xab, 0xd5, 0xd6, 0x1c, 0xde, 0x31, 0x18, 0x03, 0x01, 0xc2, 0x69, + 0xd5, 0x2a, 0xf8, 0x56, 0xba, 0xa3, 0x9b, 0x89, 0xf5, 0xef, 0x45, 0x36, + 0x7f, 0x55, 0x19, 0x21, 0x0c, 0x71, 0xd7, 0x7b, 0x31, 0x8d, 0x05, 0x3e, + 0xc0, 0xc2, 0xf4, 0x9b, 0xf4, 0x6d, 0xe0, 0x5c, 0xab, 0xf2, 0x3c, 0x7d, + 0x2b, 0xd7, 0xd2, 0x3f +}; +/* QIUTx = 01a7ef3d17c301e8661ba66c1cdee82a9b44d716909e3663b423dc06ef6be4f616cd179321ce7a572da4bca2e89b768edc8459b3 */ +/* QIUTy = 00df743849a20bc3026062b420d3942f18e2d6c5307e6e1955e33b09d5951dc59b31a2b1d58c233e2c896e2d9ccaa8eeb8e8f113 */ +static const uint8_t nist_kas_ecc_cdh_testvector_329_out[] = { +/* ZIUT */ + 0x00, 0xb6, 0x66, 0x1a, 0x86, 0x6a, 0xbb, 0xf1, 0x84, 0x3d, 0xea, 0x8f, + 0x22, 0x0e, 0x36, 0x0f, 0xe7, 0xcd, 0x7d, 0x9e, 0x85, 0xc3, 0x16, 0x13, + 0x8f, 0xd2, 0x53, 0x2a, 0x57, 0xd7, 0xd2, 0xa6, 0xbf, 0xe6, 0xe5, 0x51, + 0x80, 0x19, 0xc6, 0x03, 0xa2, 0xd0, 0xe3, 0x38, 0xac, 0x6a, 0x86, 0x90, + 0x09, 0x3c, 0x28, 0x83 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_330_public_x[] = { +/* QCAVSx */ + 0x00, 0xca, 0x87, 0x0a, 0xcb, 0xe4, 0xeb, 0x3a, 0xe6, 0x5e, 0xdd, 0x95, + 0xd6, 0x94, 0x4e, 0xb0, 0x90, 0xe0, 0xe5, 0x50, 0x71, 0x2b, 0xe3, 0xb1, + 0x36, 0x9e, 0x47, 0x32, 0x03, 0xf5, 0x2b, 0x18, 0x38, 0x65, 0x4f, 0x7a, + 0x43, 0x42, 0xbd, 0x83, 0x09, 0x70, 0x4f, 0xed, 0x69, 0x33, 0xae, 0x9d, + 0x16, 0x2c, 0xcd, 0x7d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_330_public_y[] = { +/* QCAVSy */ + 0x01, 0x79, 0x6c, 0xc2, 0x86, 0xbf, 0x3d, 0x53, 0xad, 0x63, 0x69, 0x77, + 0x37, 0x4f, 0x83, 0x56, 0xe4, 0x57, 0x30, 0xb7, 0xaa, 0x43, 0x80, 0x5f, + 0xb5, 0x28, 0x01, 0xf7, 0x3b, 0xe3, 0xe9, 0xb3, 0x28, 0x08, 0x98, 0x4a, + 0xae, 0xbb, 0xed, 0x7b, 0xe5, 0xe3, 0x9e, 0x51, 0x33, 0x5b, 0x0d, 0xff, + 0x34, 0x78, 0x29, 0x48 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_330_private[] = { +/* dIUT */ + 0x00, 0xf3, 0x23, 0xc8, 0xee, 0x43, 0x3c, 0x9b, 0xa1, 0x5d, 0x37, 0x08, + 0x06, 0x98, 0x34, 0xac, 0xc4, 0xd9, 0x37, 0xbe, 0x50, 0x17, 0xe1, 0xd1, + 0x82, 0xec, 0x76, 0x46, 0x6a, 0xba, 0x28, 0x2c, 0x73, 0xb5, 0xe3, 0xe9, + 0x6f, 0xe1, 0x06, 0x14, 0x36, 0x41, 0x40, 0x2c, 0x72, 0xc6, 0x24, 0x84, + 0xba, 0x1f, 0x12, 0xf2 +}; +/* QIUTx = 00b74f52520119fc08536cea584220de9b062401e64ff6359305c2e6b0c04a95f77baf53e23c326aee76211495c30b2c150b9275 */ +/* QIUTy = 01540588e2fd5688d1b35763908c1f823eeeca8942f6216ce04cef66ed6991df6a22fb74411b13d06513a65b64e62815ee020697 */ +static const uint8_t nist_kas_ecc_cdh_testvector_330_out[] = { +/* ZIUT */ + 0x01, 0x08, 0x89, 0x03, 0x7c, 0x70, 0x7d, 0x90, 0xb8, 0x33, 0xd0, 0x32, + 0x56, 0xff, 0x2e, 0x8a, 0x5f, 0xfc, 0xe1, 0x6f, 0xb3, 0x61, 0x34, 0x86, + 0x22, 0x14, 0x94, 0xa4, 0xfe, 0xe8, 0x2e, 0x74, 0x62, 0x5a, 0x93, 0xd9, + 0x66, 0xc2, 0x02, 0x8d, 0x09, 0x30, 0x11, 0x54, 0x94, 0xf9, 0x45, 0x6c, + 0xec, 0x4d, 0x2b, 0x6d +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_331_public_x[] = { +/* QCAVSx */ + 0x00, 0x7e, 0xb6, 0x1d, 0xfd, 0xdf, 0xc3, 0xc0, 0xd0, 0x83, 0xfe, 0x22, + 0x13, 0x96, 0x79, 0x86, 0x38, 0x1d, 0x9e, 0x30, 0xe6, 0x84, 0xaf, 0xdf, + 0x2b, 0xac, 0x8f, 0x1a, 0x36, 0x2e, 0x8c, 0x6d, 0x63, 0x58, 0xdf, 0x95, + 0x93, 0x06, 0x00, 0x42, 0x7d, 0xfc, 0x1e, 0xb1, 0x41, 0x18, 0xfd, 0x12, + 0x39, 0xb6, 0x7b, 0x69 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_331_public_y[] = { +/* QCAVSy */ + 0x01, 0x5b, 0xa8, 0x7f, 0x98, 0x11, 0x4c, 0xec, 0x8b, 0x2c, 0xb4, 0x5b, + 0xba, 0x3d, 0xcf, 0x00, 0x6b, 0x28, 0x7e, 0x07, 0xe3, 0xbe, 0xf1, 0xda, + 0x27, 0xce, 0x08, 0xda, 0x9e, 0x4f, 0x48, 0xbd, 0x24, 0x1f, 0x59, 0xa1, + 0xf9, 0xc9, 0x3c, 0x83, 0x78, 0x84, 0x71, 0x57, 0x50, 0xf4, 0x08, 0x5f, + 0x91, 0x3f, 0x4f, 0x7a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_331_private[] = { +/* dIUT */ + 0x00, 0x13, 0x3d, 0xa2, 0xba, 0x54, 0xb3, 0x62, 0x44, 0xc8, 0x04, 0x2f, + 0x0e, 0x2d, 0xa3, 0x71, 0x8e, 0x56, 0xdb, 0xd2, 0x84, 0x8e, 0xf4, 0x27, + 0xbd, 0xdb, 0x24, 0x17, 0x7f, 0x62, 0x44, 0x75, 0xb5, 0x34, 0x00, 0xaf, + 0xdc, 0xb1, 0x88, 0x79, 0xe8, 0xfe, 0x6b, 0x46, 0x09, 0xa4, 0xf7, 0xbb, + 0xc2, 0x15, 0x2b, 0x13 +}; +/* QIUTx = 00e3a2f4e63cfbc1ee844745ab3e1e5be573204609aece5e28b8fb8ab8ae06898467a95a7b59c0898a414abff2703ccbcdc09209 */ +/* QIUTy = 010d73c43b630170395104acad6c1a563d3296632332a1481ddc2c31836bd1a3ee1a7364d7f5b8295db95a3745b4bbbeb8095bc2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_331_out[] = { +/* ZIUT */ + 0x01, 0x0a, 0x8a, 0xaf, 0xbb, 0x24, 0x3f, 0xc9, 0x46, 0x6b, 0xf3, 0x81, + 0xea, 0xe1, 0x73, 0xc0, 0x1b, 0xe9, 0x5d, 0x88, 0xa9, 0xc1, 0x31, 0xb0, + 0x7e, 0xd5, 0x4d, 0x2f, 0x11, 0x7c, 0xd3, 0xaf, 0x40, 0x19, 0xff, 0xb1, + 0x96, 0xeb, 0xe8, 0x29, 0x0b, 0x12, 0x69, 0x62, 0x2f, 0x9d, 0xf2, 0x67, + 0x63, 0xff, 0xa2, 0x11 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_332_public_x[] = { +/* QCAVSx */ + 0x00, 0x82, 0xf1, 0x48, 0xec, 0x34, 0xd1, 0xd0, 0x8b, 0x26, 0xe7, 0x9e, + 0x37, 0x72, 0xe1, 0x2d, 0x65, 0x95, 0x98, 0xb7, 0x3b, 0x6f, 0xff, 0x0b, + 0xab, 0x18, 0x45, 0xe9, 0xa5, 0xb5, 0x07, 0x14, 0x49, 0xef, 0x27, 0x59, + 0xfe, 0xd6, 0x3a, 0xa8, 0x06, 0x24, 0xb8, 0x3a, 0x6b, 0x2e, 0x9d, 0x73, + 0x9b, 0x83, 0xf6, 0xdb +}; +static const uint8_t nist_kas_ecc_cdh_testvector_332_public_y[] = { +/* QCAVSy */ + 0x01, 0x09, 0xce, 0xa0, 0x48, 0xa7, 0x20, 0xba, 0x74, 0x9f, 0xc5, 0x22, + 0xc8, 0x5a, 0xf5, 0xfe, 0x78, 0x37, 0x51, 0xc3, 0x9f, 0xe8, 0xd0, 0x51, + 0x5b, 0xa0, 0xf0, 0xd3, 0xdc, 0xd1, 0x9f, 0x18, 0xc2, 0x2d, 0xa3, 0x90, + 0x9f, 0x02, 0xd7, 0x87, 0x35, 0xaa, 0x11, 0xb2, 0xfe, 0xba, 0x0f, 0x8d, + 0x33, 0x0c, 0x57, 0x03 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_332_private[] = { +/* dIUT */ + 0x00, 0xdf, 0x75, 0x54, 0xc0, 0x13, 0x2f, 0xd4, 0xe4, 0xa2, 0xb9, 0x21, + 0x78, 0x75, 0xf9, 0x92, 0x4a, 0x55, 0xca, 0xb3, 0x19, 0xb7, 0x6a, 0x7c, + 0x17, 0x9c, 0xf0, 0x22, 0x29, 0x37, 0x57, 0x99, 0x96, 0xcf, 0x94, 0x92, + 0x0b, 0xaf, 0xd4, 0x53, 0xe5, 0x2f, 0x5d, 0x2f, 0xc4, 0x80, 0x01, 0x32, + 0x9f, 0xbd, 0x78, 0xc4 +}; +/* QIUTx = 0160851cff947ce72a118aab4dad4ce2c3ce9bc330ce1d06efad7f630e45bbcf37097d94051d9d310abffa8d96ed22a847cbe693 */ +/* QIUTy = 0079a3ddde636bc62af41e6ec0e073fe6462e38ad4b9e3a36ecc8113a2c6394ced21abdc8ec5969e58e009ea13dbe929a96709ca */ +static const uint8_t nist_kas_ecc_cdh_testvector_332_out[] = { +/* ZIUT */ + 0x01, 0xe1, 0x7b, 0x88, 0x44, 0xc4, 0xc7, 0x57, 0x55, 0x3a, 0x62, 0x8d, + 0x6f, 0x4c, 0x48, 0xf3, 0xa3, 0x37, 0xed, 0x2b, 0xbb, 0x6e, 0x40, 0x47, + 0xdb, 0xfc, 0xfb, 0xfd, 0x02, 0xbb, 0x81, 0xc6, 0xe0, 0x96, 0xf8, 0xcc, + 0xbb, 0x7f, 0x2e, 0x5d, 0x10, 0xee, 0x9c, 0xbc, 0xc9, 0x60, 0xe3, 0xa9, + 0x9e, 0x79, 0xbd, 0x09 +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_333_public_x[] = { +/* QCAVSx */ + 0x00, 0x83, 0xca, 0x04, 0xdf, 0x84, 0x58, 0xe5, 0xe6, 0xce, 0x6e, 0x13, + 0xb9, 0x37, 0xda, 0xb4, 0x98, 0x52, 0x1d, 0x82, 0x6f, 0xb9, 0x54, 0x12, + 0x34, 0x56, 0x7e, 0x99, 0x5f, 0x06, 0x83, 0xc8, 0x0f, 0x43, 0x85, 0x16, + 0xee, 0xff, 0x0c, 0xf8, 0x91, 0x8a, 0x5f, 0x8b, 0x52, 0x62, 0xcc, 0xdc, + 0xa3, 0x99, 0x74, 0x17 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_333_public_y[] = { +/* QCAVSy */ + 0x00, 0x5f, 0x8b, 0x3c, 0x20, 0xe3, 0xfe, 0x25, 0x59, 0xef, 0xe0, 0xe8, + 0x5a, 0x12, 0x27, 0x6d, 0xf9, 0x22, 0xef, 0x0f, 0x42, 0x57, 0xfe, 0x70, + 0x3b, 0xe2, 0x52, 0x9f, 0x6e, 0xff, 0xb6, 0xf2, 0x99, 0xa1, 0xa2, 0x51, + 0xc0, 0x1e, 0x38, 0xd4, 0x3c, 0xa6, 0xca, 0x57, 0x6e, 0xf1, 0xe0, 0xbe, + 0xb6, 0xc9, 0x12, 0x1e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_333_private[] = { +/* dIUT */ + 0x00, 0x32, 0x73, 0x5d, 0xd7, 0xf1, 0x18, 0xd2, 0x9f, 0x9f, 0x3c, 0xab, + 0x3a, 0x07, 0x2d, 0xb8, 0xc8, 0x86, 0xd4, 0x2f, 0xa5, 0xde, 0x7b, 0xea, + 0x65, 0x03, 0x6e, 0xd3, 0xc8, 0xd4, 0x4a, 0x11, 0xe8, 0xf9, 0x6f, 0x4e, + 0x1a, 0x6f, 0x25, 0x48, 0x88, 0xca, 0xb2, 0x14, 0x30, 0x51, 0x91, 0xa2, + 0x6d, 0xd1, 0xda, 0xd1 +}; +/* QIUTx = 002d39e0f89fb875151ee3b354f8ea159e7fba6f23f8a764d49e07ef43f18d3cf86e1baaae0ad79d4000709a50252f1ce3603135 */ +/* QIUTy = 00ce44a9b775b03cf42b310249660794c25e0422b03ad9babaa23610613251fe0e54046e04f9210436dd376003d18f98dfdae189 */ +static const uint8_t nist_kas_ecc_cdh_testvector_333_out[] = { +/* ZIUT */ + 0x01, 0x16, 0x7e, 0xdf, 0x7a, 0x3c, 0x50, 0xe1, 0x3b, 0xe1, 0x26, 0xeb, + 0x2c, 0xaf, 0x6b, 0x5f, 0x8f, 0x76, 0x1c, 0xc8, 0xdb, 0xa4, 0x13, 0x24, + 0x64, 0x23, 0xb8, 0x77, 0xdf, 0x74, 0xa3, 0xaa, 0x3f, 0x48, 0x14, 0x4b, + 0x44, 0xcd, 0x13, 0x3a, 0xd9, 0xf2, 0xd0, 0x5e, 0xf9, 0x7a, 0x08, 0xf7, + 0xca, 0x51, 0x1d, 0x7f +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_334_public_x[] = { +/* QCAVSx */ + 0x01, 0x31, 0x15, 0x36, 0xa9, 0x74, 0x5b, 0x74, 0x75, 0xe6, 0xc2, 0xfd, + 0x72, 0x4c, 0x23, 0xd9, 0xea, 0x66, 0x80, 0x3a, 0x13, 0x9b, 0x47, 0xe3, + 0xae, 0x26, 0x3b, 0x0f, 0xb7, 0xe4, 0x2e, 0x33, 0x16, 0x27, 0x9b, 0xbf, + 0x62, 0x2a, 0xe2, 0x62, 0x53, 0x1b, 0x2e, 0x22, 0x83, 0xec, 0xc1, 0xa6, + 0x12, 0x7c, 0x9b, 0x09 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_334_public_y[] = { +/* QCAVSy */ + 0x01, 0xd4, 0x8c, 0xcc, 0x78, 0x1f, 0x0b, 0xde, 0xc3, 0x13, 0x09, 0x10, + 0x04, 0x4b, 0x76, 0x90, 0x9a, 0x9a, 0xbd, 0x7f, 0xcb, 0x18, 0x40, 0x7d, + 0xc4, 0x2f, 0x63, 0x91, 0x2f, 0xa2, 0x66, 0x72, 0x08, 0x00, 0x3a, 0xb2, + 0xd2, 0x81, 0x02, 0xad, 0xcf, 0xb9, 0x3d, 0xdc, 0x05, 0x37, 0x60, 0xe5, + 0x3c, 0x2d, 0xaa, 0x78 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_334_private[] = { +/* dIUT */ + 0x00, 0xb0, 0x4f, 0x33, 0xb6, 0x87, 0x99, 0x63, 0x0d, 0x62, 0xf4, 0x43, + 0x37, 0xc7, 0x7c, 0x5a, 0x6b, 0x6e, 0x0f, 0x76, 0x06, 0xb5, 0xc8, 0x72, + 0x44, 0xaa, 0x4e, 0x7d, 0xa6, 0x98, 0xcc, 0x8f, 0xf1, 0xd3, 0x31, 0x1b, + 0x48, 0xee, 0x7c, 0x9a, 0x68, 0x12, 0xba, 0xf9, 0x05, 0x43, 0x79, 0xae, + 0xb6, 0x1c, 0x0c, 0x13 +}; +/* QIUTx = 01c5940c2de2b3735824ae2994c15086fa958750e4d83123af047e9b3c264746c9b5d919da215355d8c28b2808a37d0cc5f2f6a1 */ +/* QIUTy = 000abfe6f1510a182eff78dd802e9ba21e668aea5732c732ddfc5df9301f5899f02bae80f8282601ef3eefe414ef2c726fe00258 */ +static const uint8_t nist_kas_ecc_cdh_testvector_334_out[] = { +/* ZIUT */ + 0x01, 0x5c, 0x0d, 0x20, 0x2b, 0xfd, 0xee, 0x2d, 0xfb, 0xd4, 0xbe, 0x91, + 0x62, 0x51, 0x71, 0x99, 0x2e, 0x6c, 0x6b, 0x1a, 0x1d, 0x06, 0xcc, 0x1b, + 0x2b, 0x66, 0xed, 0x64, 0xc9, 0xd9, 0x28, 0xbd, 0x4f, 0x06, 0x29, 0x12, + 0x90, 0x0d, 0x3f, 0x89, 0x04, 0x5c, 0x71, 0x90, 0xf5, 0x13, 0xd3, 0xb0, + 0x19, 0xa6, 0x34, 0xf5 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_335_public_x[] = { +/* QCAVSx */ + 0x01, 0x0c, 0x27, 0x35, 0x30, 0xf5, 0x4f, 0xe1, 0x74, 0xbb, 0xbd, 0x5c, + 0x27, 0x71, 0xa5, 0x5a, 0x42, 0xe6, 0x40, 0x50, 0xc3, 0xbf, 0x25, 0x23, + 0xe6, 0x08, 0x2a, 0xf4, 0x76, 0xeb, 0x02, 0x57, 0x87, 0x69, 0x6e, 0xdf, + 0x6e, 0x43, 0x8d, 0xd0, 0x56, 0xb5, 0x98, 0xf5, 0x00, 0x06, 0x33, 0xc2, + 0x64, 0xfd, 0x7b, 0xa5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_335_public_y[] = { +/* QCAVSy */ + 0x00, 0x44, 0x3e, 0x72, 0xda, 0x93, 0xb0, 0xc7, 0x82, 0x5f, 0x42, 0x23, + 0xc7, 0x96, 0x82, 0x6f, 0xd1, 0x32, 0x23, 0x45, 0xea, 0x25, 0xad, 0xf3, + 0xdf, 0x1a, 0x2c, 0x69, 0x58, 0x90, 0x8c, 0x0f, 0xd9, 0xb1, 0x3e, 0x93, + 0xcc, 0x00, 0x5f, 0x4e, 0xcb, 0x15, 0x5a, 0x2f, 0xff, 0x7a, 0xc5, 0x4f, + 0xa8, 0x18, 0x07, 0x85 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_335_private[] = { +/* dIUT */ + 0x00, 0xd4, 0xeb, 0xc3, 0x1c, 0x9a, 0x65, 0xee, 0x3b, 0x1a, 0xbd, 0x9d, + 0x6e, 0x64, 0x95, 0x78, 0x0c, 0x54, 0xe6, 0x33, 0xf5, 0xa2, 0xa9, 0xf6, + 0x1c, 0x84, 0x08, 0xd7, 0x67, 0xd0, 0x91, 0x6d, 0x91, 0xcb, 0x54, 0xcf, + 0xcd, 0x93, 0x75, 0x38, 0xdf, 0x92, 0xcf, 0xc4, 0x59, 0x38, 0xe3, 0x3b, + 0x77, 0xd7, 0x24, 0xf2 +}; +/* QIUTx = 014dfaaa70518f367cdfca89795a0db374bb7b407a58caac24ba46824dce78501067d7e0467d30b9e1fdbb0a7eace15fb0c208cf */ +/* QIUTy = 019d62be2b12a17a78f6c9f7e703669765f763c6235fe7af78f25044e99c4b1b90653640b3f0ae481a55d47d1eb17b86c5bada1b */ +static const uint8_t nist_kas_ecc_cdh_testvector_335_out[] = { +/* ZIUT */ + 0x00, 0x7c, 0x32, 0x38, 0x3a, 0xae, 0x80, 0xe1, 0x11, 0x12, 0x07, 0x89, + 0x4c, 0x8c, 0xc5, 0xbe, 0x66, 0xfe, 0x53, 0x8a, 0xf4, 0xa1, 0x91, 0x95, + 0x74, 0x2a, 0x94, 0xa4, 0xc3, 0xf5, 0xc7, 0x65, 0xd9, 0x77, 0x6a, 0x56, + 0x17, 0x7c, 0x48, 0x5d, 0xdb, 0x53, 0xc0, 0x38, 0xb7, 0x04, 0x78, 0x95, + 0x9d, 0x37, 0x46, 0x27 +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_336_public_x[] = { +/* QCAVSx */ + 0x01, 0x3b, 0xeb, 0x8d, 0x36, 0xd1, 0xe7, 0xf5, 0x3d, 0x80, 0xbe, 0xea, + 0x33, 0xef, 0xc3, 0xe0, 0x09, 0x8d, 0xea, 0xea, 0xa1, 0x79, 0x77, 0xda, + 0x8f, 0x9a, 0xae, 0x9c, 0x57, 0x6e, 0x79, 0x20, 0xe8, 0xf6, 0xda, 0x55, + 0xa2, 0x09, 0x30, 0xce, 0x60, 0xfd, 0x49, 0x0b, 0x4f, 0xb0, 0x15, 0x4d, + 0x49, 0x27, 0x7d, 0x99 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_336_public_y[] = { +/* QCAVSy */ + 0x01, 0x1d, 0xc1, 0xd8, 0x7f, 0x35, 0x2e, 0x12, 0xbd, 0xb4, 0x1a, 0x1b, + 0x7a, 0x1f, 0x1e, 0x51, 0x66, 0x29, 0xed, 0x32, 0x3c, 0x5d, 0x5b, 0x26, + 0x3f, 0xf0, 0x36, 0xf0, 0x23, 0xf0, 0xff, 0x5f, 0x72, 0x2d, 0x05, 0x6c, + 0x24, 0xa4, 0x11, 0xf5, 0x3b, 0x34, 0x7d, 0x07, 0x86, 0xd8, 0x4f, 0x7b, + 0xe8, 0x79, 0x10, 0x5a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_336_private[] = { +/* dIUT */ + 0x00, 0x26, 0x17, 0x6a, 0xaf, 0x98, 0xa6, 0x43, 0x35, 0x66, 0xf1, 0xdc, + 0xc1, 0x91, 0x9e, 0x94, 0x45, 0x3e, 0x9c, 0xbf, 0x3c, 0x97, 0xe0, 0x69, + 0xb4, 0xa1, 0x74, 0x26, 0x44, 0x91, 0x67, 0xf6, 0xa1, 0x08, 0x9a, 0xc1, + 0x6a, 0x10, 0x2a, 0x4b, 0x3e, 0x43, 0x2a, 0x97, 0x8b, 0xfb, 0x46, 0x25, + 0x5d, 0xc4, 0x3d, 0x1a +}; +/* QIUTx = 01535fc949b49030308bc0da9793d57088766ac8cf22e8d6c276d8f3f7650f30135e1f6c00300c1344e2f0306ea0e270b09a80af */ +/* QIUTy = 00b8fc3fa61dc22c55501f2a6b2944946d99f7bbfefbec7acf4fb200c1002e322c39172ec0a2b6ce0807f1e3ebb1ea3400353143 */ +static const uint8_t nist_kas_ecc_cdh_testvector_336_out[] = { +/* ZIUT */ + 0x01, 0x16, 0x61, 0x07, 0xab, 0x98, 0xdb, 0x1d, 0xbe, 0x22, 0xc5, 0x88, + 0x8a, 0x70, 0xc9, 0x92, 0xaf, 0x4f, 0xaf, 0x46, 0x23, 0xef, 0x59, 0x38, + 0x02, 0xae, 0xdf, 0xe4, 0x33, 0x80, 0x9c, 0x53, 0xef, 0x4a, 0xb0, 0xb2, + 0xdc, 0x4d, 0xc2, 0x54, 0x64, 0x88, 0xb3, 0x56, 0xef, 0x32, 0x65, 0x35, + 0x60, 0x55, 0xd8, 0xf5 +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_337_public_x[] = { +/* QCAVSx */ + 0x01, 0x69, 0x0c, 0x74, 0x64, 0x9e, 0x92, 0xe1, 0xc1, 0x00, 0x4f, 0x43, + 0xfd, 0x6e, 0x46, 0x90, 0xbe, 0x59, 0x59, 0x04, 0xc5, 0x6d, 0x2a, 0xcd, + 0x85, 0xa4, 0x9a, 0xf0, 0xa1, 0x7d, 0x34, 0x36, 0x8c, 0x87, 0x68, 0xd0, + 0x39, 0xed, 0xe9, 0xc9, 0x2a, 0xd2, 0x6b, 0x26, 0x30, 0x6b, 0x5f, 0xfd, + 0xef, 0x7b, 0xfd, 0x19 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_337_public_y[] = { +/* QCAVSy */ + 0x00, 0x81, 0x27, 0x5f, 0x7e, 0x2f, 0xf0, 0x68, 0xa6, 0xc1, 0xb9, 0x2d, + 0xd3, 0x8c, 0x03, 0x42, 0x56, 0xed, 0x73, 0x22, 0xb0, 0x27, 0x70, 0x29, + 0x94, 0xc7, 0x4f, 0x5b, 0x81, 0x81, 0x24, 0xd3, 0x4a, 0x19, 0x09, 0x87, + 0xfd, 0x65, 0x88, 0x92, 0xfc, 0x99, 0xe7, 0xac, 0xb9, 0x87, 0x7b, 0xd6, + 0xfe, 0x94, 0x69, 0x19 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_337_private[] = { +/* dIUT */ + 0x00, 0xbf, 0x3e, 0x73, 0x95, 0xc7, 0x2a, 0xa8, 0x4c, 0x09, 0x60, 0xe5, + 0xc6, 0x90, 0x22, 0xce, 0x39, 0x06, 0x74, 0x04, 0x53, 0x44, 0x73, 0xc4, + 0xc7, 0x82, 0x94, 0x24, 0xf8, 0x1f, 0x1d, 0x44, 0xb3, 0x1f, 0x20, 0xe2, + 0xb9, 0x82, 0xe2, 0x51, 0xcf, 0x9f, 0xfb, 0x32, 0x7a, 0x7d, 0x83, 0x4f, + 0x59, 0xd1, 0x94, 0x8a +}; +/* QIUTx = 011cbc4ed9036a27effc89ffd55fa1e3ead0fb93bacfa0a78bcafe3914ab1a97860fec1334caaba07243591603e67791aea4bcb7 */ +/* QIUTy = 0101074c444627630ad0a5258e24438d71f26ab94d05bb47d1ab97858c4b92c6ff1cb9be66b984fe8e16e44f393e63f9d64281c8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_337_out[] = { +/* ZIUT */ + 0x00, 0x7e, 0x7a, 0x24, 0x90, 0x94, 0xeb, 0x52, 0xbe, 0xe0, 0x11, 0x5b, + 0x8b, 0xd5, 0x54, 0x5f, 0x81, 0xbf, 0x0b, 0x7d, 0x66, 0x99, 0x8f, 0xe1, + 0x24, 0xc9, 0xa3, 0xdd, 0x3c, 0x57, 0x15, 0xd0, 0x3b, 0x2f, 0x97, 0x3d, + 0x47, 0xc1, 0x9a, 0xf5, 0x10, 0x8a, 0x2a, 0xe0, 0x05, 0xfc, 0xca, 0x65, + 0xe6, 0x1f, 0x33, 0x7d +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_338_public_x[] = { +/* QCAVSx */ + 0x00, 0x5c, 0x24, 0xf4, 0xad, 0x9b, 0xdc, 0xb1, 0x46, 0x06, 0x85, 0xa2, + 0x2d, 0xa5, 0x4d, 0xbd, 0xdd, 0x15, 0x07, 0xef, 0x6d, 0xe4, 0x69, 0xda, + 0x41, 0x70, 0xce, 0x30, 0x14, 0x75, 0x79, 0xa5, 0x49, 0x45, 0xdb, 0xb1, + 0xbc, 0xe9, 0xf0, 0x2e, 0x47, 0x00, 0x33, 0xbb, 0x15, 0xfc, 0x1a, 0x70, + 0xf8, 0x31, 0xe7, 0x9b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_338_public_y[] = { +/* QCAVSy */ + 0x01, 0x7c, 0xa9, 0x32, 0xb9, 0x0a, 0x08, 0xca, 0x2e, 0x3f, 0x55, 0xc5, + 0x0c, 0xc0, 0xe1, 0x3d, 0x27, 0x9d, 0x7b, 0xc9, 0x11, 0x9c, 0x57, 0x3c, + 0x3f, 0x74, 0x14, 0x10, 0xbb, 0x7c, 0x1c, 0xad, 0x10, 0x76, 0xc3, 0xba, + 0x42, 0xae, 0xd1, 0xce, 0x69, 0xd5, 0x62, 0x28, 0xb0, 0x82, 0xfb, 0x6d, + 0xe0, 0xee, 0xfb, 0x68 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_338_private[] = { +/* dIUT */ + 0x00, 0x96, 0xd4, 0x03, 0xb0, 0xfa, 0x60, 0x1c, 0x9a, 0x75, 0xaa, 0x7d, + 0xe9, 0xfe, 0x9e, 0x11, 0xd4, 0x2e, 0xfa, 0x93, 0xd9, 0x6d, 0xd3, 0x51, + 0x02, 0xda, 0x05, 0xd3, 0xac, 0x80, 0x7e, 0x44, 0x19, 0x4e, 0x18, 0xe7, + 0x9c, 0x8b, 0x5b, 0xe1, 0x1c, 0x5f, 0xb3, 0x9c, 0x8b, 0xd4, 0xe3, 0x12, + 0x32, 0x5a, 0xfa, 0xf2 +}; +/* QIUTx = 0009833946294d4aeecdb6f7254ca489c0ff13af2dc6e2ca5626835d5dd22241440c37a63690cd11867581ff61b7252d07afb8ff */ +/* QIUTy = 006183fee6f4d6ef5b723c53c96c5c1ecdd84652e379c937878d766f83370500412359c22d4778bdf807b3c84e5b83350910a1a9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_338_out[] = { +/* ZIUT */ + 0x00, 0xb9, 0xd8, 0xb6, 0x86, 0x42, 0xb2, 0x72, 0x93, 0x40, 0xd8, 0xb7, + 0xc5, 0xed, 0x3b, 0x3a, 0x89, 0x13, 0xc4, 0xa3, 0xf6, 0xb9, 0x47, 0x47, + 0x30, 0x17, 0xc0, 0xe1, 0x05, 0xbc, 0x7e, 0xdc, 0x60, 0xda, 0xa9, 0xb0, + 0x73, 0x27, 0x72, 0x22, 0x0f, 0x93, 0xec, 0xa4, 0x87, 0x80, 0x85, 0xf7, + 0x56, 0xe3, 0xad, 0xad +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_339_public_x[] = { +/* QCAVSx */ + 0x00, 0xaa, 0xbf, 0x6a, 0xab, 0xb3, 0xe9, 0x0f, 0x95, 0x6d, 0x70, 0x04, + 0xff, 0xc8, 0x93, 0xc7, 0x0f, 0x8e, 0x90, 0xcd, 0xc3, 0x1f, 0xc0, 0xc7, + 0xa8, 0x8f, 0x16, 0x32, 0x05, 0x41, 0xd5, 0x84, 0x43, 0xaf, 0x39, 0x40, + 0x5d, 0x88, 0x8d, 0x96, 0x76, 0x55, 0x7c, 0xdd, 0x39, 0x4b, 0x27, 0xdc, + 0x54, 0x49, 0xf9, 0x45 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_339_public_y[] = { +/* QCAVSy */ + 0x01, 0x27, 0xf2, 0x6d, 0xba, 0x06, 0xc3, 0x3f, 0x8f, 0xb4, 0x5d, 0x95, + 0x5c, 0xfd, 0xb5, 0xce, 0xdd, 0xa9, 0x3d, 0xd8, 0xa4, 0x5d, 0xb4, 0x2e, + 0xe0, 0xb9, 0x26, 0x4a, 0x05, 0x4c, 0x16, 0xa8, 0x7b, 0xed, 0xad, 0x45, + 0xc0, 0xd9, 0xa0, 0xf3, 0x5b, 0xbc, 0x6a, 0xa7, 0xa1, 0x29, 0x56, 0x22, + 0xe8, 0x3e, 0xbe, 0x8b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_339_private[] = { +/* dIUT */ + 0x00, 0x67, 0x12, 0x5e, 0xc3, 0x09, 0xab, 0x5d, 0xc7, 0xea, 0x56, 0x8f, + 0x88, 0x15, 0xa2, 0xb3, 0x0c, 0xfa, 0xc3, 0x36, 0x6b, 0xb4, 0xf0, 0x16, + 0x0d, 0x53, 0x73, 0x8a, 0xb9, 0x95, 0xce, 0x75, 0x68, 0x1f, 0xcd, 0x5e, + 0x49, 0x2f, 0x3a, 0x97, 0x25, 0xb4, 0xcf, 0x75, 0xba, 0x43, 0x01, 0xa7, + 0x86, 0x04, 0x93, 0x42 +}; +/* QIUTx = 01f1d1aee5fc594ca4a22b81bad707d821bef3253966f5d77956157483961696f4c60476a42b452b89c1ecb3615475ec9c96dc87 */ +/* QIUTy = 00755c5ef55889b415cefa0e881a3efc9be86f36c67615423b452eab4cd5611aef4198ddb31aecb434eeeec12edd05913af19fc4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_339_out[] = { +/* ZIUT */ + 0x01, 0x7d, 0x60, 0x39, 0x4c, 0x7e, 0xe6, 0x4b, 0xa7, 0x3d, 0xb9, 0x14, + 0x84, 0x71, 0x33, 0x70, 0xda, 0xa8, 0x21, 0x25, 0x58, 0x07, 0x34, 0x9c, + 0x23, 0x7e, 0x58, 0x49, 0x41, 0x1b, 0xf0, 0xba, 0xb3, 0xa1, 0xb3, 0x53, + 0xbe, 0x3c, 0xd0, 0x7e, 0xed, 0xdc, 0x5c, 0x2f, 0xfc, 0x74, 0x33, 0x62, + 0x25, 0xda, 0xe6, 0xf7 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_340_public_x[] = { +/* QCAVSx */ + 0x00, 0x1f, 0x4f, 0xfb, 0xf2, 0x2f, 0x67, 0xc1, 0x59, 0x1b, 0x0a, 0x77, + 0x0e, 0x56, 0x3c, 0x0a, 0xba, 0x66, 0xfe, 0x01, 0x56, 0x1c, 0x5e, 0x22, + 0x7e, 0x52, 0x2b, 0x5d, 0xde, 0x23, 0xc7, 0x48, 0xca, 0xcf, 0x8f, 0x4a, + 0x02, 0x29, 0x0d, 0xe2, 0x6b, 0x47, 0x76, 0x7d, 0x38, 0x8a, 0x5c, 0x83, + 0x6d, 0x3e, 0xff, 0x4b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_340_public_y[] = { +/* QCAVSy */ + 0x00, 0x2d, 0x27, 0x3f, 0x2e, 0x85, 0x16, 0xe5, 0x08, 0x38, 0x8f, 0x8e, + 0xd2, 0x01, 0x5e, 0xc9, 0xfe, 0x67, 0xc6, 0x6f, 0x83, 0x2c, 0xf2, 0xb2, + 0x61, 0xdf, 0xad, 0x58, 0x56, 0x12, 0x80, 0x42, 0xfb, 0x4a, 0x61, 0xa9, + 0x1a, 0x37, 0xb3, 0x41, 0xde, 0x42, 0x96, 0xd4, 0xbf, 0x63, 0xbf, 0x67, + 0xa3, 0x45, 0x8a, 0x74 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_340_private[] = { +/* dIUT */ + 0x00, 0x6b, 0x2c, 0xc2, 0x38, 0x7f, 0x69, 0xaf, 0xd4, 0x39, 0x78, 0xb7, + 0xf6, 0x6b, 0xd1, 0x76, 0x66, 0x25, 0x70, 0x81, 0xba, 0x4d, 0x66, 0xee, + 0x6a, 0x9a, 0x82, 0xb7, 0xc8, 0x7c, 0x4a, 0xc5, 0xf0, 0xeb, 0xa6, 0xbc, + 0x2d, 0x98, 0x1c, 0xa1, 0xda, 0x9f, 0xf2, 0x02, 0xba, 0x72, 0xcb, 0x7f, + 0xe9, 0xc0, 0x6c, 0xf0 +}; +/* QIUTx = 0086a44d6ee4e8c50d1e10d7d1d113a9610750210679e0e4cab8c62267842938ad5d933c980eef9d4644791bbfd35bbac649d213 */ +/* QIUTy = 011da63212631605fea0e93f5826b1929b2bd1db950615fcb05eb47bd9cb69eae03b1c33d7a9e47b335a40498238fedb8999b04d */ +static const uint8_t nist_kas_ecc_cdh_testvector_340_out[] = { +/* ZIUT */ + 0x00, 0xb1, 0x9e, 0x05, 0x2e, 0xdd, 0x44, 0x42, 0x1e, 0xe2, 0xf5, 0xba, + 0x84, 0x59, 0x11, 0xfe, 0xd9, 0x18, 0x3d, 0x88, 0x5d, 0xa8, 0x5d, 0x51, + 0xdc, 0x81, 0x9c, 0xa5, 0x65, 0xce, 0x57, 0x4f, 0x7d, 0xb2, 0x57, 0x50, + 0x98, 0x76, 0x37, 0x7b, 0x40, 0xc5, 0xa0, 0x83, 0x49, 0x01, 0x95, 0x63, + 0xb6, 0x0e, 0x13, 0xe9 +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_341_public_x[] = { +/* QCAVSx */ + 0x01, 0xb0, 0x83, 0x3e, 0xb3, 0x44, 0x04, 0x50, 0xe3, 0xfa, 0x51, 0x48, + 0xc2, 0x5c, 0x2d, 0xf2, 0xe0, 0x02, 0x06, 0x26, 0xf2, 0x40, 0x74, 0x22, + 0x21, 0x7e, 0x4e, 0xcb, 0x8b, 0xd8, 0xa7, 0x51, 0xa7, 0x2b, 0xab, 0x2e, + 0xc5, 0x64, 0x2a, 0xe9, 0x0f, 0xd2, 0x9d, 0x8c, 0x4d, 0x79, 0xe9, 0xcc, + 0x19, 0x1b, 0x5b, 0xa5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_341_public_y[] = { +/* QCAVSy */ + 0x00, 0x23, 0x07, 0x89, 0x05, 0xb6, 0xa3, 0x30, 0x09, 0xff, 0xea, 0x1a, + 0x19, 0x77, 0xdb, 0x94, 0x35, 0x79, 0xaf, 0xbe, 0xb8, 0x71, 0x97, 0x00, + 0x59, 0x69, 0x6b, 0x29, 0xef, 0x90, 0xdd, 0x84, 0x61, 0x77, 0x6b, 0x34, + 0x3a, 0x09, 0xc8, 0x53, 0xa5, 0x38, 0xe4, 0xf2, 0x2f, 0xdf, 0x85, 0x4f, + 0xcb, 0xf3, 0xb7, 0x34 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_341_private[] = { +/* dIUT */ + 0x00, 0x3e, 0x09, 0x8f, 0x3f, 0x19, 0x5e, 0x89, 0xda, 0x71, 0xd6, 0x36, + 0x70, 0x00, 0xf8, 0x04, 0x07, 0x9a, 0xdc, 0xa3, 0x27, 0x5b, 0x2e, 0x79, + 0x3e, 0x8d, 0x31, 0x2c, 0x8e, 0x40, 0x2c, 0xf0, 0xd0, 0xce, 0x53, 0x31, + 0x74, 0x2f, 0x87, 0x51, 0x5f, 0x4d, 0xd9, 0xcc, 0x66, 0x82, 0x46, 0x19, + 0x4b, 0x95, 0x72, 0xb6 +}; +/* QIUTx = 010af4ae334ba40bd6538e0f095aa56f61a2bd2b5f38e954b7617d92ba10603cdcca836554d0242ddb37d5e1576b0be69f0eece7 */ +/* QIUTy = 01b335521aec305f314d7f23ed28cc0c4d23f33a6785fc6c6de93e5fabce271302f9557f6d2ae77c52720eda5a2e15436443dfd2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_341_out[] = { +/* ZIUT */ + 0x01, 0x69, 0x75, 0x12, 0x67, 0x6a, 0xe5, 0x6f, 0xf5, 0xab, 0x77, 0x8c, + 0x41, 0x10, 0x42, 0xd2, 0x17, 0xad, 0x24, 0xa2, 0x4e, 0xa0, 0x5b, 0xbc, + 0x25, 0x3e, 0x43, 0x95, 0xfe, 0xcc, 0x8a, 0x07, 0xfe, 0x77, 0xae, 0x0c, + 0xa4, 0xed, 0x97, 0x74, 0x59, 0xf1, 0xa1, 0x4d, 0x9b, 0x83, 0x93, 0x1b, + 0xcc, 0xf4, 0x61, 0x07 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_342_public_x[] = { +/* QCAVSx */ + 0x01, 0x74, 0xbd, 0x23, 0x3f, 0x86, 0x1c, 0x7b, 0x85, 0x3c, 0xca, 0x8f, + 0x5a, 0x38, 0x35, 0x74, 0x84, 0x9e, 0xf2, 0xcd, 0x76, 0xef, 0x22, 0xbc, + 0x0e, 0x15, 0x9f, 0x71, 0x3a, 0x1d, 0x07, 0x38, 0x7c, 0x42, 0x03, 0xb1, + 0x1f, 0x4c, 0x33, 0x9b, 0x66, 0x96, 0x74, 0xfc, 0xf1, 0xda, 0xc1, 0x99, + 0x70, 0x3b, 0xeb, 0x07 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_342_public_y[] = { +/* QCAVSy */ + 0x01, 0xe2, 0xc7, 0x78, 0xcc, 0xa6, 0x49, 0x63, 0xd8, 0x73, 0x29, 0xe5, + 0x7c, 0x8b, 0xc9, 0x6d, 0x0f, 0x67, 0x37, 0x04, 0x1f, 0xd0, 0x87, 0xda, + 0xfc, 0x07, 0xdd, 0x67, 0x0e, 0x2c, 0xe7, 0x25, 0x54, 0x7e, 0x1a, 0x26, + 0x1c, 0x43, 0xfb, 0xc5, 0x4e, 0x14, 0xc3, 0x47, 0x3e, 0xbd, 0xbb, 0x31, + 0xfd, 0xa8, 0x47, 0x3a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_342_private[] = { +/* dIUT */ + 0x00, 0x7d, 0x84, 0x93, 0x13, 0xc6, 0x49, 0x9d, 0xae, 0x47, 0x2b, 0x0b, + 0xdd, 0xb7, 0x6d, 0xec, 0x45, 0x80, 0x6f, 0x82, 0xe0, 0x98, 0x72, 0x33, + 0x01, 0xdf, 0x33, 0xb6, 0xbb, 0xb9, 0x7f, 0x79, 0x4b, 0xf2, 0x68, 0x79, + 0xfc, 0x33, 0xc2, 0x97, 0x3f, 0x86, 0xc1, 0x55, 0x15, 0x49, 0x64, 0x1a, + 0x81, 0x9b, 0x57, 0x11 +}; +/* QIUTx = 004812af1937630b8ea7d0ff723cbb05b7a2740fc4c9be792db204f929674c32e47d85e4770b903d3290a6d62c274cb257b76837 */ +/* QIUTy = 008c6f61711786bf5c54eb0c1b3126d641b24a6662b67b257302a9a61aa8cd503846bcbb1b14fa5c97454368b6c27dd2de2ae80b */ +static const uint8_t nist_kas_ecc_cdh_testvector_342_out[] = { +/* ZIUT */ + 0x01, 0x59, 0x60, 0xea, 0x8b, 0x92, 0xbd, 0x77, 0xd5, 0x28, 0x74, 0xe3, + 0xea, 0x82, 0xed, 0x17, 0x63, 0x44, 0x01, 0x89, 0xd6, 0x87, 0x28, 0xd3, + 0x97, 0x4d, 0x4c, 0x01, 0xd6, 0xaa, 0xfd, 0xbb, 0x52, 0x74, 0x64, 0x8f, + 0x6f, 0x3e, 0xaa, 0x4f, 0xaf, 0x3f, 0xc7, 0x2d, 0x09, 0x89, 0x2a, 0xb0, + 0x38, 0xcb, 0x2f, 0xb7 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_343_public_x[] = { +/* QCAVSx */ + 0x00, 0xc1, 0xdc, 0xb7, 0x37, 0xd2, 0x53, 0x03, 0x5b, 0xb9, 0x1d, 0x2a, + 0x4a, 0x85, 0xf3, 0x7d, 0x00, 0x14, 0x2b, 0xe8, 0x1f, 0xc9, 0x27, 0x8c, + 0xb2, 0x3a, 0x4d, 0x1d, 0x79, 0xd2, 0x7c, 0x8d, 0x3c, 0x44, 0x40, 0xb2, + 0xc8, 0x42, 0xbc, 0x1e, 0x21, 0xf6, 0x92, 0x4e, 0x14, 0xdc, 0x83, 0x1b, + 0x0a, 0xbf, 0xb8, 0x45 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_343_public_y[] = { +/* QCAVSy */ + 0x00, 0x0c, 0x73, 0xd5, 0x68, 0x7b, 0x04, 0x90, 0xcc, 0xc0, 0x7f, 0x65, + 0x41, 0x01, 0xac, 0xdd, 0xb3, 0x6c, 0xd0, 0xc2, 0xee, 0xcc, 0xe1, 0x65, + 0xdf, 0x27, 0x6f, 0x83, 0xbe, 0x21, 0x1d, 0x01, 0xd3, 0x0f, 0xf5, 0xc2, + 0x43, 0xf0, 0x90, 0x05, 0x72, 0xee, 0x6d, 0xf0, 0x7f, 0x53, 0x9d, 0xf6, + 0xa4, 0x68, 0x9b, 0x0b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_343_private[] = { +/* dIUT */ + 0x00, 0xbf, 0xa5, 0x94, 0x85, 0x6c, 0x67, 0xc2, 0x83, 0x6b, 0x7f, 0xb1, + 0x71, 0xb6, 0x7c, 0x7a, 0x41, 0xae, 0x43, 0xef, 0x34, 0x50, 0x89, 0x80, + 0x24, 0xa9, 0x31, 0x36, 0x54, 0xfc, 0xf3, 0x1e, 0x1e, 0x1f, 0xba, 0xc7, + 0xad, 0x52, 0xb2, 0xbc, 0x43, 0x58, 0x97, 0x5a, 0x5c, 0x61, 0xab, 0x9f, + 0x4e, 0x3e, 0x4e, 0x9e +}; +/* QIUTx = 00e1b5309a44800a916ad8a4d19b82a58b00ee048248050a6ed6c33ce1bc9701547e93d7c9042f8490654b73a2cd7d73f733c0bf */ +/* QIUTy = 0180b20338746351faccfb9a3711a4e138457550bbf58316034c6f216a53749263dffe2359bddcdc89ec6446a9a4a9f4ef90c86d */ +static const uint8_t nist_kas_ecc_cdh_testvector_343_out[] = { +/* ZIUT */ + 0x01, 0x12, 0x74, 0x91, 0xff, 0x33, 0xa6, 0x7f, 0xfc, 0x47, 0x57, 0x41, + 0x6c, 0xd0, 0x2a, 0x08, 0x1c, 0xaf, 0xb7, 0x23, 0xaf, 0xf5, 0x2a, 0xf3, + 0x5b, 0x06, 0x9b, 0x89, 0x96, 0x3e, 0x8e, 0x3e, 0xf5, 0xbc, 0x19, 0xc5, + 0xa0, 0x93, 0xcc, 0xf5, 0x11, 0xe3, 0xc3, 0xc1, 0x9b, 0xe7, 0x89, 0x28, + 0x0e, 0x98, 0x68, 0x09 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_344_public_x[] = { +/* QCAVSx */ + 0x01, 0x3d, 0x96, 0xa2, 0x67, 0xd1, 0xa2, 0xa9, 0xea, 0x83, 0xae, 0xb1, + 0xb0, 0x1d, 0x8a, 0xce, 0x22, 0xe2, 0x51, 0xc8, 0x2f, 0x5f, 0x5f, 0xc3, + 0xef, 0x59, 0x97, 0xa3, 0x01, 0x1a, 0x74, 0xa1, 0x01, 0x15, 0xdf, 0x60, + 0xe9, 0x8d, 0x13, 0x9c, 0xdd, 0x36, 0x0e, 0x74, 0xd7, 0x6f, 0xa5, 0x22, + 0xee, 0xb5, 0x6f, 0x4b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_344_public_y[] = { +/* QCAVSy */ + 0x01, 0x6b, 0x65, 0x5a, 0xb7, 0xcd, 0x0d, 0x39, 0xf5, 0x88, 0xfb, 0xef, + 0xec, 0x54, 0xe4, 0xf4, 0x50, 0x47, 0x66, 0x4c, 0x8b, 0x3b, 0xe8, 0xe5, + 0x7a, 0xb1, 0x13, 0x77, 0x0f, 0x5f, 0xe0, 0xc6, 0x23, 0x00, 0xf4, 0xa0, + 0x9f, 0xa2, 0x89, 0x9e, 0x73, 0xbb, 0xc9, 0x82, 0x32, 0x65, 0xf5, 0x5d, + 0x5c, 0xf4, 0xae, 0x18 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_344_private[] = { +/* dIUT */ + 0x00, 0x4a, 0x02, 0x0e, 0x06, 0xc4, 0x00, 0xef, 0x24, 0x98, 0xc1, 0x11, + 0xcd, 0xe1, 0x50, 0x87, 0xcd, 0xa4, 0x8a, 0x6f, 0xb2, 0xec, 0xc0, 0x1d, + 0x98, 0x5b, 0x57, 0xf0, 0xd3, 0x92, 0x19, 0x20, 0xe9, 0x2c, 0x43, 0xf3, + 0xab, 0x68, 0x81, 0x29, 0xdc, 0x01, 0xad, 0x29, 0xfc, 0x31, 0xd6, 0x8e, + 0x96, 0x22, 0x31, 0x9b +}; +/* QIUTx = 0167227f62849594ed63f247f780b2d11dd9a2c2c71bd6b71294cf8b59ce690bfe00da9bc1db8d1daac9bff8c00e7bdf071fe0d3 */ +/* QIUTy = 0136c3ea77d093d9739fbe6891318b14959778599bd1e7d5a97bfc82ffe85fd5a9a01b82f72e11fad96d2f5cb5798f59efea15ed */ +static const uint8_t nist_kas_ecc_cdh_testvector_344_out[] = { +/* ZIUT */ + 0x01, 0x25, 0x45, 0x08, 0x55, 0x3e, 0xab, 0x09, 0xfb, 0xc2, 0xfa, 0xfe, + 0x13, 0xfa, 0x9b, 0x32, 0x4d, 0x92, 0x17, 0xd7, 0xd0, 0xba, 0x4c, 0xed, + 0xbe, 0x5d, 0xc8, 0x69, 0xad, 0x68, 0xde, 0x4f, 0x87, 0x77, 0x4d, 0xd1, + 0x7d, 0x64, 0x28, 0xed, 0x24, 0x2c, 0x71, 0x95, 0x6f, 0x25, 0x29, 0x69, + 0xe6, 0xbd, 0x58, 0x37 +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_345_public_x[] = { +/* QCAVSx */ + 0x01, 0x78, 0x7b, 0x30, 0xb3, 0xb2, 0x04, 0xe2, 0x98, 0x69, 0x0b, 0x9d, + 0x71, 0x1f, 0xfe, 0xef, 0x16, 0x7a, 0xdc, 0x57, 0x92, 0x06, 0x8b, 0x5c, + 0x8d, 0x42, 0x2e, 0xc9, 0x0f, 0x94, 0xc2, 0xbd, 0xd2, 0x84, 0xcd, 0xbf, + 0x8b, 0xee, 0x64, 0x2f, 0x70, 0xbd, 0x7b, 0xe2, 0xda, 0x90, 0x6b, 0x9e, + 0xdb, 0xbc, 0x2c, 0xd1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_345_public_y[] = { +/* QCAVSy */ + 0x00, 0x43, 0x07, 0x8f, 0x91, 0x21, 0x10, 0x29, 0x0a, 0x13, 0xd9, 0x01, + 0x60, 0xf0, 0xe7, 0x15, 0x82, 0xfa, 0x39, 0xc0, 0xe7, 0x5d, 0x81, 0x90, + 0xeb, 0x81, 0x1d, 0x45, 0x02, 0x20, 0x04, 0x4c, 0xc6, 0xd6, 0x80, 0xd9, + 0x56, 0xa9, 0x88, 0x60, 0xe6, 0xfc, 0x85, 0xbb, 0x86, 0xd6, 0x59, 0x90, + 0xa1, 0x60, 0xc5, 0xb8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_345_private[] = { +/* dIUT */ + 0x00, 0xc1, 0x9b, 0x39, 0x16, 0x65, 0xf5, 0x03, 0x53, 0x54, 0x7f, 0xc7, + 0x2c, 0x9e, 0xd0, 0x19, 0xf5, 0x31, 0x16, 0x90, 0xee, 0x41, 0xe7, 0xc8, + 0x95, 0xaa, 0x7e, 0xf9, 0x2c, 0x60, 0xfb, 0x9f, 0x34, 0x54, 0xdf, 0xac, + 0x57, 0x52, 0x45, 0xa6, 0x86, 0x9f, 0x1f, 0xde, 0xc7, 0x45, 0xd6, 0x3e, + 0xa5, 0x6c, 0x89, 0x22 +}; +/* QIUTx = 0053a7a62a8b4044b60af76efa5b44429bf65f65987d6a062163dd55f08dc9a91b8bb9b6270f8a026123f99eb9372ccbdd27ca3b */ +/* QIUTy = 00add46f7ea7092f48ddaa2feb96cb24bf92d2628fb6e4f7cddf523e5f84011cf8aababd6009a13f29a63b6b7ee664c66f3829f3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_345_out[] = { +/* ZIUT */ + 0x00, 0x4b, 0x9a, 0xcc, 0xc2, 0x1d, 0x71, 0x22, 0x83, 0x5f, 0xc2, 0x14, + 0x10, 0xed, 0x1d, 0x83, 0x76, 0x7c, 0x47, 0xa5, 0x4f, 0xfe, 0xe5, 0xf0, + 0xc1, 0x80, 0xfc, 0x55, 0xf3, 0xd0, 0xe8, 0x48, 0x4a, 0xf3, 0xad, 0x38, + 0x02, 0x02, 0x94, 0xbe, 0x92, 0xf0, 0x2f, 0x0b, 0xa7, 0xe2, 0xb4, 0xf4, + 0xeb, 0x1d, 0xb0, 0x7f +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_346_public_x[] = { +/* QCAVSx */ + 0x01, 0xe9, 0xda, 0x0a, 0xd1, 0xa1, 0x5a, 0xc3, 0xc4, 0x31, 0xf2, 0x20, + 0x95, 0x4e, 0xd2, 0xe5, 0x02, 0xaf, 0x7b, 0x74, 0x6c, 0x3f, 0xd5, 0x7b, + 0x2e, 0xce, 0xb7, 0x74, 0x86, 0x58, 0x02, 0x0a, 0x09, 0x56, 0x64, 0x87, + 0x83, 0x54, 0xdf, 0x0a, 0xa1, 0x81, 0xe5, 0x7e, 0x5e, 0xad, 0x2c, 0x98, + 0x5a, 0xd3, 0x02, 0x3d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_346_public_y[] = { +/* QCAVSy */ + 0x00, 0x9c, 0xce, 0x73, 0xa5, 0x47, 0x08, 0x34, 0x8b, 0x48, 0xf8, 0xf3, + 0xf6, 0x74, 0xbb, 0x76, 0x54, 0xf4, 0x41, 0xf2, 0x83, 0xd4, 0xe8, 0xa4, + 0xec, 0x8f, 0x85, 0x92, 0xef, 0x52, 0x39, 0x5f, 0x24, 0xc1, 0x12, 0xd5, + 0x94, 0x2d, 0x3a, 0xe0, 0x8f, 0xfe, 0x8d, 0x99, 0x9e, 0xfd, 0xe3, 0x99, + 0x88, 0x8a, 0x7c, 0xf3 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_346_private[] = { +/* dIUT */ + 0x00, 0x6c, 0x90, 0x98, 0xb5, 0x3d, 0x10, 0xf2, 0xac, 0x02, 0x84, 0xa9, + 0x99, 0x02, 0x65, 0x8f, 0x66, 0x7e, 0xa4, 0xca, 0xb2, 0x86, 0x98, 0xaf, + 0x3f, 0xa0, 0x70, 0x06, 0xa1, 0xbb, 0x46, 0x36, 0x3b, 0x10, 0x3c, 0x4a, + 0xa4, 0xc9, 0x2c, 0x1c, 0x3f, 0xe7, 0x53, 0x90, 0x97, 0xfa, 0x70, 0xb8, + 0xa4, 0xfa, 0x46, 0xc5 +}; +/* QIUTx = 00d3edf652f43f9c9a92a2e4d34ba83f5d7e950c28346a2a6851bf75547050140a4e9c1c1b500e1d2ad364c306b9a44af503a621 */ +/* QIUTy = 0099b26c64367f1903da95df51562d25042c01a1adda75bba58bdb0d8aab350b52ecfbe98488c2619de01cd70f5e008953bca547 */ +static const uint8_t nist_kas_ecc_cdh_testvector_346_out[] = { +/* ZIUT */ + 0x00, 0x93, 0xe2, 0x58, 0x1c, 0x15, 0x9d, 0x74, 0xd1, 0x1f, 0x86, 0x67, + 0xee, 0x03, 0x39, 0x92, 0x08, 0xb5, 0xc1, 0xa4, 0xee, 0x5b, 0x20, 0x07, + 0x0c, 0xe8, 0xd9, 0x7d, 0x25, 0x1e, 0xf1, 0x23, 0x6d, 0xc8, 0x1d, 0xd6, + 0x88, 0xb2, 0xf0, 0x7a, 0x73, 0x0e, 0x6b, 0x8a, 0xec, 0xa0, 0xc1, 0x93, + 0xa2, 0x8b, 0x17, 0x8f +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_347_public_x[] = { +/* QCAVSx */ + 0x00, 0xc4, 0x92, 0x94, 0xfb, 0x71, 0x29, 0x42, 0x22, 0x1a, 0x25, 0x00, + 0x32, 0x4a, 0xf7, 0xbd, 0x8c, 0x7e, 0xc1, 0xcd, 0x1b, 0x80, 0x94, 0xde, + 0xd1, 0xba, 0xc0, 0x01, 0x0a, 0x86, 0x96, 0x08, 0x3f, 0x7e, 0xfa, 0xec, + 0xaa, 0x51, 0x03, 0xd6, 0x76, 0x24, 0x99, 0xe1, 0xbe, 0x48, 0x57, 0xd3, + 0x20, 0x03, 0x02, 0x81 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_347_public_y[] = { +/* QCAVSy */ + 0x00, 0x56, 0x4f, 0xa1, 0x11, 0x0b, 0x39, 0x39, 0x25, 0xdf, 0xbb, 0x24, + 0xba, 0x9a, 0x6b, 0x33, 0x73, 0xf4, 0x62, 0x4e, 0xcb, 0xc3, 0xe1, 0x2f, + 0x97, 0x06, 0xf3, 0xab, 0x05, 0x42, 0x99, 0x2d, 0x8d, 0xb6, 0xc8, 0xd8, + 0xbb, 0x25, 0xfa, 0x06, 0x14, 0xd4, 0x86, 0xf6, 0xd1, 0xac, 0x9f, 0x3d, + 0x98, 0xb9, 0xed, 0xfe +}; +static const uint8_t nist_kas_ecc_cdh_testvector_347_private[] = { +/* dIUT */ + 0x00, 0xa7, 0xfa, 0x38, 0xa8, 0xab, 0x80, 0x30, 0xd6, 0xb4, 0x97, 0xa2, + 0x3b, 0xde, 0x5e, 0x50, 0x07, 0xe3, 0x9d, 0x14, 0xda, 0x9f, 0x82, 0xdc, + 0x56, 0x4a, 0xe3, 0xcd, 0xb4, 0xaf, 0x5f, 0xcf, 0x41, 0xbc, 0xfe, 0xf7, + 0xad, 0xad, 0xb5, 0x91, 0x71, 0xe6, 0xd7, 0xd3, 0xd3, 0xc3, 0xac, 0x67, + 0xf7, 0xbe, 0x70, 0x73 +}; +/* QIUTx = 0013bb3ba91d5d2488af572d995cef8fffb1fd85d113421e8d2c0c3aa97cdb8a933fc0d3f05f4646ce841ebdcf1a98604bffa3df */ +/* QIUTy = 01f2e04ea16a012d4864cf2ca7564846de73a33f24578dc4d221359c4f2f86ca823cb0596bfe4760e9eadcb4ad508ab1a171ecbd */ +static const uint8_t nist_kas_ecc_cdh_testvector_347_out[] = { +/* ZIUT */ + 0x00, 0x8e, 0x2f, 0x1c, 0x4b, 0xad, 0x19, 0xc4, 0x6a, 0x51, 0x34, 0xaf, + 0xcc, 0xf7, 0xf4, 0xec, 0x14, 0xab, 0x59, 0x1c, 0x8b, 0x8e, 0xa4, 0x8d, + 0x9c, 0x3d, 0x1e, 0x73, 0x54, 0xab, 0x43, 0xba, 0x20, 0xaa, 0x39, 0xa6, + 0x5f, 0xd9, 0x2c, 0xdc, 0x17, 0x6c, 0xf3, 0xde, 0xde, 0xcb, 0xf9, 0xda, + 0x49, 0xa8, 0xd8, 0x55 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_348_public_x[] = { +/* QCAVSx */ + 0x01, 0x34, 0xad, 0xd2, 0xc4, 0x99, 0x17, 0x2d, 0xf7, 0x92, 0xd9, 0x4a, + 0x9b, 0x38, 0x95, 0xe2, 0x45, 0xb8, 0x40, 0x73, 0xc3, 0x25, 0x26, 0x3a, + 0x85, 0x8c, 0x1e, 0x9f, 0x7c, 0xf3, 0x0a, 0x44, 0xf2, 0x68, 0xd3, 0xf8, + 0x35, 0x84, 0x11, 0xdc, 0x0a, 0x9c, 0xaa, 0xb5, 0x05, 0xc0, 0xab, 0xc0, + 0x16, 0x13, 0x0b, 0xf5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_348_public_y[] = { +/* QCAVSy */ + 0x00, 0x31, 0xc2, 0x36, 0xb1, 0x43, 0xca, 0x03, 0x6c, 0x88, 0x36, 0x41, + 0xf7, 0xf9, 0xb9, 0x57, 0xf4, 0xf7, 0x98, 0xa3, 0x16, 0x67, 0xc4, 0x15, + 0x60, 0x34, 0x02, 0x79, 0xfc, 0xe0, 0x96, 0x2a, 0x21, 0xbd, 0x8b, 0xb5, + 0x2f, 0xa2, 0x3d, 0xb7, 0x1a, 0x84, 0xf3, 0x5a, 0x57, 0x94, 0xef, 0x5e, + 0x07, 0x59, 0x72, 0xdd +}; +static const uint8_t nist_kas_ecc_cdh_testvector_348_private[] = { +/* dIUT */ + 0x00, 0xce, 0x9f, 0x82, 0x7b, 0xd2, 0x4c, 0x01, 0x4c, 0x3e, 0xe5, 0x9e, + 0xde, 0xf7, 0x47, 0x17, 0x8d, 0x6c, 0x03, 0x0c, 0x19, 0x66, 0x9a, 0xd8, + 0xe7, 0x18, 0xba, 0x13, 0x02, 0xbe, 0xf4, 0xb5, 0xad, 0x2c, 0x12, 0x33, + 0x44, 0x8f, 0x52, 0x75, 0xb2, 0x9a, 0x89, 0x6c, 0x0b, 0x2e, 0x7b, 0x0d, + 0xa9, 0x20, 0x68, 0xbe +}; +/* QIUTx = 0176e31012d9c604b2d1a1922a28d8a574f060cc36388b2816d2f8117da20c0699ab0a08f76fbaa476f0a9c424bf4c952b4754fd */ +/* QIUTy = 011fedc3e8f8e828e0ffbf02fd85d29c0201fd0f53bf2614c10ae51ccb58cbc4900c38cc4c9a52d86d89f9b8c2de4e227f4e228e */ +static const uint8_t nist_kas_ecc_cdh_testvector_348_out[] = { +/* ZIUT */ + 0x01, 0x90, 0xa1, 0x69, 0x3e, 0xeb, 0xe2, 0x87, 0xec, 0x98, 0x02, 0x36, + 0xd8, 0x76, 0x28, 0x04, 0xd2, 0x3f, 0xdb, 0x6f, 0x22, 0x27, 0x63, 0xa0, + 0xef, 0xc3, 0x64, 0xf9, 0x28, 0x0f, 0xdd, 0x53, 0x39, 0x4c, 0x2b, 0xad, + 0xcc, 0x51, 0xff, 0x09, 0x55, 0x7f, 0x3b, 0x97, 0xca, 0xe7, 0xf7, 0x0d, + 0x79, 0x0b, 0xf9, 0xdf +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_349_public_x[] = { +/* QCAVSx */ + 0x00, 0xf0, 0xec, 0x97, 0x2d, 0xc9, 0xfd, 0xfd, 0x08, 0xcd, 0x8d, 0xfc, + 0xba, 0x72, 0x98, 0xb4, 0xdf, 0x2d, 0xbd, 0x80, 0xc2, 0x0b, 0x28, 0x89, + 0xe6, 0x63, 0xac, 0x58, 0xcc, 0x34, 0x8c, 0xbf, 0x8f, 0x9f, 0xfd, 0x31, + 0xff, 0xb5, 0x06, 0x18, 0xd6, 0xc3, 0x8d, 0x72, 0xa9, 0x9d, 0x5c, 0x5d, + 0x2e, 0xac, 0xc0, 0x01 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_349_public_y[] = { +/* QCAVSy */ + 0x00, 0xbb, 0x0b, 0x48, 0x89, 0x3c, 0xdb, 0x91, 0x5e, 0x65, 0xcd, 0x5d, + 0x79, 0x78, 0x04, 0x80, 0x20, 0x17, 0xa2, 0x95, 0x34, 0x36, 0x54, 0x24, + 0x6a, 0x37, 0xfe, 0x3a, 0x60, 0xd7, 0xde, 0x98, 0x7e, 0x6a, 0x9a, 0x10, + 0xaa, 0xf0, 0x63, 0xd9, 0x6b, 0x10, 0x18, 0x46, 0x12, 0xcc, 0xd2, 0x64, + 0x07, 0xd7, 0xe0, 0x3e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_349_private[] = { +/* dIUT */ + 0x00, 0xe3, 0x6f, 0x3b, 0x9a, 0x13, 0x41, 0x99, 0x5b, 0x13, 0xfe, 0x70, + 0xbc, 0x54, 0x5d, 0x27, 0x9e, 0x6d, 0xb1, 0x48, 0x2c, 0x92, 0xb1, 0x3c, + 0xe8, 0xcc, 0x0d, 0xa1, 0xc1, 0x00, 0xea, 0x2f, 0xaa, 0x80, 0x3a, 0x64, + 0xa5, 0x8c, 0xc7, 0xeb, 0x1c, 0xfd, 0x16, 0x75, 0x70, 0x83, 0x5c, 0x52, + 0x2f, 0x65, 0x93, 0x47 +}; +/* QIUTx = 00d1ca82393b8d50bd1898a909bf39333eca3bde98b0b0dced66f828630e69e6eb128b7cec23f07260047073260a765331dd6f57 */ +/* QIUTy = 006c535ff943a0fe750fc6c39904a6912ba1ebc0f46c1b0823e4013c77475ea29b3f32481966f1b165bedba6c17a1494fb6d4f3d */ +static const uint8_t nist_kas_ecc_cdh_testvector_349_out[] = { +/* ZIUT */ + 0x00, 0x14, 0x69, 0xda, 0xbc, 0xf2, 0x21, 0x0a, 0xa7, 0xde, 0x00, 0x40, + 0xb2, 0x01, 0x22, 0x1e, 0xb4, 0xd1, 0xa4, 0x72, 0x54, 0x31, 0xfb, 0x5a, + 0x93, 0x21, 0x2a, 0x66, 0xdd, 0xea, 0x41, 0x87, 0xe0, 0x78, 0xf5, 0xe3, + 0xd8, 0x26, 0x06, 0xf6, 0xcd, 0xfc, 0x0f, 0xfe, 0x6b, 0x69, 0x57, 0x4d, + 0x1d, 0x0b, 0xa6, 0x43 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_350_public_x[] = { +/* QCAVSx */ + 0x01, 0x37, 0x84, 0x44, 0xe0, 0xde, 0xec, 0xff, 0x3a, 0xec, 0x5a, 0xb6, + 0xe7, 0x4e, 0x81, 0x23, 0xba, 0x98, 0xd8, 0xb9, 0x1a, 0x50, 0x7c, 0xfc, + 0xa0, 0xd8, 0x50, 0x97, 0xaa, 0xd9, 0x44, 0xc1, 0x5b, 0x4f, 0xd8, 0x9c, + 0x8c, 0xbe, 0x2c, 0x74, 0x51, 0xd8, 0xec, 0x64, 0x10, 0x45, 0x42, 0x1b, + 0x4b, 0xf6, 0x97, 0x8b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_350_public_y[] = { +/* QCAVSy */ + 0x01, 0x64, 0x47, 0xc2, 0x13, 0xc9, 0x03, 0x5d, 0xe7, 0xbc, 0xc2, 0x9b, + 0xdd, 0x61, 0xd6, 0xee, 0x6e, 0xd5, 0x57, 0x9c, 0x36, 0xbe, 0xc5, 0x6b, + 0xc6, 0xb4, 0x4f, 0x92, 0x86, 0xbf, 0x9e, 0x99, 0xfa, 0xc9, 0x7f, 0x35, + 0x67, 0x08, 0xcd, 0x03, 0x10, 0xdb, 0xf6, 0x33, 0x8f, 0x9a, 0xf8, 0xd7, + 0xb1, 0x35, 0x91, 0x02 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_350_private[] = { +/* dIUT */ + 0x00, 0x08, 0xa0, 0x67, 0x16, 0xed, 0x6f, 0x4c, 0xf7, 0x28, 0xf9, 0x01, + 0x99, 0x28, 0xf3, 0x67, 0xc7, 0x7a, 0x90, 0x52, 0x49, 0x0b, 0x9a, 0x8b, + 0xa8, 0x7a, 0x59, 0xcd, 0xca, 0x84, 0xe7, 0x7c, 0x6a, 0x29, 0x98, 0x53, + 0xf5, 0x49, 0x6f, 0xeb, 0xe6, 0x52, 0xf4, 0xba, 0x33, 0x35, 0x01, 0xc4, + 0xfc, 0xf2, 0xba, 0x2f +}; +/* QIUTx = 00a045b5e6bbb7950495f6d5d645a2b7d72006725d0223c7ff75534022c9260ab0d2d8d333789a3dccfc3a89502ca500bd0c1f61 */ +/* QIUTy = 01ec556e1b1621ec1893654e198d5923e311478a8bd2ffff280c9092ffc0737289a997492b6e9ebf931947634ef7f43b429cf36a */ +static const uint8_t nist_kas_ecc_cdh_testvector_350_out[] = { +/* ZIUT */ + 0x00, 0x5c, 0x70, 0x1a, 0x93, 0xd7, 0x79, 0x03, 0x22, 0xaa, 0x7c, 0x67, + 0x44, 0x0f, 0xdd, 0x9e, 0xe8, 0x05, 0x7a, 0x0d, 0xae, 0x86, 0xd1, 0xe8, + 0x56, 0xae, 0x89, 0xe7, 0x89, 0x3d, 0xa1, 0x78, 0xbd, 0x67, 0x77, 0x7f, + 0x86, 0xdb, 0x2b, 0xe5, 0xc8, 0xe3, 0x1d, 0xc5, 0x0e, 0xd8, 0xa4, 0x40, + 0xaa, 0xbc, 0x34, 0x2d +}; +/* [B-571] - GP NOT SUPPORTED */ +/* COUNT = 0 */ +static const uint8_t nist_kas_ecc_cdh_testvector_351_public_x[] = { +/* QCAVSx */ + 0x03, 0xb6, 0x3f, 0x5f, 0xa1, 0x12, 0xae, 0x6b, 0x5f, 0x11, 0x3c, 0x76, + 0x51, 0x44, 0xfe, 0x4c, 0xbd, 0x60, 0x20, 0xe2, 0x6d, 0x40, 0x0c, 0x11, + 0x60, 0x9a, 0x3a, 0x63, 0x4b, 0x9a, 0x32, 0x5f, 0x41, 0x6b, 0x0e, 0x3d, + 0x32, 0x15, 0x73, 0x4c, 0x68, 0xa1, 0xc2, 0xc8, 0xfa, 0xd1, 0xd0, 0xbb, + 0x9e, 0xb3, 0x93, 0x9a, 0x41, 0xaf, 0x22, 0x42, 0x1f, 0x68, 0x78, 0x1e, + 0x7e, 0xb0, 0x66, 0x4b, 0x9d, 0xf5, 0xce, 0xa4, 0x48, 0xde, 0xaa, 0x3b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_351_public_y[] = { +/* QCAVSy */ + 0x00, 0x8e, 0x6c, 0xc7, 0x7b, 0xcd, 0xdc, 0x81, 0x6e, 0x84, 0xcf, 0xc1, + 0xf6, 0x26, 0x82, 0x4f, 0xa2, 0x4d, 0x3d, 0x5f, 0xd3, 0x3d, 0x80, 0x93, + 0xcb, 0xfe, 0x1f, 0xc4, 0xd8, 0x81, 0xb6, 0x3b, 0x49, 0x41, 0x23, 0xbc, + 0x75, 0x96, 0x70, 0xed, 0xcb, 0x18, 0x87, 0xbb, 0x3b, 0x9d, 0x5a, 0x8b, + 0x51, 0x6b, 0xc5, 0x03, 0x82, 0x81, 0x63, 0x70, 0x9d, 0x4d, 0xac, 0xb5, + 0x94, 0xd2, 0x77, 0xa1, 0x5a, 0x92, 0xc0, 0x64, 0xe5, 0x77, 0x0d, 0x1b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_351_private[] = { +/* dIUT */ + 0x03, 0x44, 0xf2, 0x2b, 0xe8, 0x79, 0x99, 0xb9, 0x5b, 0x22, 0x87, 0xf6, + 0x74, 0x30, 0xea, 0x8f, 0xe6, 0x46, 0xc6, 0x2f, 0xe3, 0x8b, 0x7c, 0xe6, + 0x1f, 0x1f, 0x95, 0x65, 0x97, 0xc2, 0x7b, 0xdd, 0xd9, 0x90, 0x2e, 0x20, + 0xd4, 0x43, 0x6a, 0xbf, 0x3b, 0xeb, 0xd8, 0x24, 0x3e, 0xc2, 0x9a, 0x00, + 0x48, 0x1a, 0x8a, 0x2c, 0x19, 0xf5, 0x50, 0xe9, 0x96, 0x41, 0xb5, 0xf1, + 0x4a, 0xaf, 0xbb, 0x5b, 0xda, 0x95, 0x3a, 0x75, 0x59, 0xf8, 0x65, 0x3a +}; +/* QIUTx = 06af71fcec1a2904116fe14878663764c1ec74870e5d2d53919f0b635912db80dd5460d9e699458ff8494c5bfc74fba8d3b12f65f015e8def10de33f1800191f4cb502d21938b951 */ +/* QIUTy = 019584177b189c6641ffb678b6d7833d8d4bb25dee5018dda4e4c0d219048c01cd0da9eaffe346d53cf1a07b33b3dbdd4bc3acabe4832f9981eff2660991aac852147985eea3a51e */ +static const uint8_t nist_kas_ecc_cdh_testvector_351_out[] = { +/* ZIUT */ + 0x06, 0x77, 0x5e, 0x1b, 0x99, 0xa2, 0x36, 0xe0, 0x2b, 0x02, 0x0b, 0xc7, + 0x36, 0x66, 0xe5, 0x75, 0x1c, 0x12, 0x10, 0xdc, 0xb6, 0xe9, 0xb0, 0x2a, + 0x69, 0xf4, 0x07, 0x53, 0x76, 0xe4, 0x9f, 0x7a, 0x14, 0x76, 0xd2, 0x20, + 0x9e, 0x86, 0x1a, 0xbb, 0x73, 0xf5, 0xe3, 0xad, 0x18, 0x9d, 0x26, 0x8e, + 0x03, 0x5b, 0x1d, 0xe9, 0x3d, 0x47, 0xb3, 0xa6, 0x4d, 0xe5, 0x78, 0x3c, + 0x9a, 0x09, 0xbc, 0x22, 0x3e, 0x1c, 0xc6, 0x12, 0xf2, 0x6d, 0xcd, 0xf1 +}; +/* COUNT = 1 */ +static const uint8_t nist_kas_ecc_cdh_testvector_352_public_x[] = { +/* QCAVSx */ + 0x05, 0x75, 0xcb, 0xb0, 0x59, 0xf4, 0x23, 0x30, 0x9f, 0x99, 0x3b, 0x6c, + 0x06, 0xac, 0x71, 0xd7, 0xbc, 0xc5, 0xd1, 0xe6, 0xa1, 0x9a, 0xfe, 0x72, + 0x81, 0x1c, 0xb6, 0x12, 0xa6, 0x23, 0x8c, 0x9c, 0xcc, 0x33, 0x1e, 0x67, + 0xda, 0x0c, 0x10, 0xb8, 0x8c, 0xc2, 0xa5, 0xf1, 0xef, 0x2f, 0xf6, 0xd6, + 0xb7, 0x44, 0x06, 0x5d, 0x24, 0x2f, 0x59, 0x8d, 0xa2, 0xd6, 0x33, 0x5d, + 0x4c, 0x3b, 0xec, 0xf5, 0xc3, 0x95, 0x39, 0x40, 0xc6, 0x0e, 0xfc, 0xc7 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_352_public_y[] = { +/* QCAVSy */ + 0x06, 0xb4, 0x33, 0x65, 0x2e, 0x3a, 0x36, 0xa0, 0x70, 0x18, 0xaa, 0x8a, + 0xd3, 0xd2, 0xff, 0x31, 0xed, 0x78, 0x5c, 0xe5, 0x60, 0x17, 0x16, 0xef, + 0xf7, 0x71, 0x0f, 0xc1, 0x3c, 0x6f, 0xf9, 0xff, 0x75, 0xc7, 0xf3, 0x70, + 0x1d, 0x45, 0x9f, 0xd8, 0xfe, 0x70, 0xc0, 0xb4, 0xaf, 0xce, 0xda, 0x08, + 0x68, 0x17, 0x17, 0xdb, 0x98, 0x21, 0xd8, 0xc8, 0x58, 0xfd, 0x39, 0xe2, + 0x74, 0xff, 0x37, 0x77, 0x2f, 0x8e, 0x84, 0x85, 0x6e, 0x70, 0x67, 0x45 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_352_private[] = { +/* dIUT */ + 0x02, 0xf4, 0xd2, 0xb7, 0xe6, 0x36, 0x60, 0xe6, 0xc2, 0x09, 0x49, 0xe0, + 0x6d, 0xc6, 0x70, 0xbe, 0x8a, 0xaf, 0x82, 0x53, 0x0e, 0x0b, 0x6e, 0xaf, + 0xe2, 0x10, 0x11, 0xfe, 0x9d, 0x0f, 0x44, 0x07, 0xc8, 0x54, 0x95, 0x15, + 0x73, 0x45, 0x28, 0xcd, 0xa2, 0x99, 0xe9, 0xfc, 0xf7, 0x38, 0xa9, 0x7f, + 0xbf, 0x43, 0xc4, 0xbb, 0xa2, 0x67, 0x44, 0xb3, 0x27, 0x53, 0x1b, 0x40, + 0x14, 0x3e, 0x15, 0x8b, 0xc8, 0x64, 0x59, 0x09, 0xea, 0x88, 0x84, 0x56 +}; +/* QIUTx = 06ea711827ad8ed589b709ef35f6a9cd4625798bd887e5fe59c51f0f41c328b7ecdf84736c43fb70e3986ee5e5f986e009f641158a75cce6b39f53a8bf0682830194e4007148deef */ +/* QIUTy = 04c6b9f2a6099fc0367fa9609394c3221ad8c6fb111d2bdc4305053804788d32eaf76431406e768a448cb5c8e34c81225eec9015abbd92725c002712ed3192d807b36afea853f722 */ +static const uint8_t nist_kas_ecc_cdh_testvector_352_out[] = { +/* ZIUT */ + 0x03, 0xa8, 0x0e, 0xa8, 0xcf, 0xec, 0xb8, 0x58, 0xf9, 0xb7, 0x7b, 0xdb, + 0x46, 0xb6, 0xcd, 0xa2, 0x63, 0x20, 0xee, 0x8c, 0x56, 0x1a, 0x2f, 0xd6, + 0xb7, 0xe0, 0xa2, 0xb6, 0x22, 0x01, 0xfb, 0xfe, 0x60, 0xf5, 0x77, 0x78, + 0x0c, 0x75, 0xa9, 0x8a, 0x11, 0xa6, 0x9d, 0xe4, 0xc4, 0xee, 0x91, 0x19, + 0x30, 0xd2, 0x20, 0x0b, 0x69, 0x72, 0xbc, 0x31, 0x23, 0xd7, 0xf2, 0x78, + 0x61, 0x5e, 0xcc, 0x65, 0x98, 0x4a, 0x59, 0xfe, 0x35, 0x2a, 0x1c, 0xec +}; +/* COUNT = 2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_353_public_x[] = { +/* QCAVSx */ + 0x06, 0x4a, 0xa6, 0x68, 0x30, 0xff, 0x44, 0x32, 0x4a, 0x67, 0xae, 0x8a, + 0x90, 0x78, 0x96, 0x89, 0x7b, 0x50, 0x75, 0x66, 0xcf, 0x52, 0xdf, 0xe1, + 0x3e, 0x3a, 0xdb, 0xb1, 0xe7, 0x93, 0x66, 0x5d, 0x2b, 0x71, 0x83, 0x58, + 0x75, 0x4e, 0xfe, 0x80, 0x9e, 0x44, 0x96, 0x21, 0x85, 0x02, 0xfe, 0xb5, + 0x60, 0x4d, 0xbf, 0xbc, 0x04, 0xa1, 0x10, 0x7c, 0xa9, 0xec, 0x4e, 0xad, + 0xc7, 0xd1, 0x0a, 0x9d, 0x6d, 0x14, 0x74, 0xce, 0xdf, 0x57, 0x81, 0x45 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_353_public_y[] = { +/* QCAVSy */ + 0x06, 0xf6, 0x3f, 0x69, 0xf8, 0xc1, 0x8b, 0x67, 0xf1, 0x10, 0x51, 0xb3, + 0xd3, 0x02, 0x36, 0xa1, 0xa2, 0x49, 0x08, 0x8b, 0x2b, 0xca, 0xb5, 0xcf, + 0xf8, 0x30, 0xcd, 0xb9, 0xeb, 0x3e, 0x75, 0xc1, 0xe8, 0x72, 0x52, 0xe5, + 0xd8, 0xe6, 0x1b, 0xb1, 0xa6, 0x63, 0x48, 0xfb, 0x68, 0x1e, 0x96, 0x2d, + 0x65, 0xab, 0xc5, 0x4d, 0x5d, 0xea, 0x2d, 0xd7, 0x2c, 0x55, 0x45, 0x90, + 0x74, 0x00, 0x74, 0xf7, 0xc6, 0x6c, 0x4b, 0x8d, 0xfd, 0x30, 0x75, 0x61 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_353_private[] = { +/* dIUT */ + 0x01, 0x2b, 0x63, 0x13, 0xb5, 0x68, 0x53, 0xcf, 0x8d, 0x02, 0x73, 0x04, + 0x9c, 0xf7, 0xed, 0x2a, 0xb8, 0xe6, 0x32, 0xe5, 0x92, 0x56, 0xed, 0x04, + 0x33, 0x66, 0x85, 0x76, 0x48, 0xf3, 0xf2, 0xa9, 0x67, 0x4c, 0xae, 0xb6, + 0xfb, 0x0f, 0xcd, 0x5f, 0xba, 0xb0, 0xbb, 0xab, 0xbc, 0xe1, 0x7a, 0x0f, + 0xc4, 0xa7, 0x81, 0x48, 0x49, 0x9c, 0x38, 0x9a, 0xf5, 0x74, 0x86, 0x37, + 0x46, 0x41, 0x69, 0x5b, 0x0e, 0x85, 0x2f, 0x31, 0x52, 0xee, 0xc7, 0x24 +}; +/* QIUTx = 040a78763d170459dd34b5c04ec782e698cbe903a5a348551c5248d9dacf19bcb9a498ea05e80e2d6cc1f3ea5ba3a43855b801c8c0356fe3e29ee224bb91f4ed0c85678379b72542 */ +/* QIUTy = 01ff49ce0a62e9edae6aa63a9848e44f185412d0feb46b87f91424bdaffed5168321ed76f235f75d33667f6d7d6a9c857bb4f85442fc40f9a20c04ae06362a46eceea15c45d69beb */ +static const uint8_t nist_kas_ecc_cdh_testvector_353_out[] = { +/* ZIUT */ + 0x03, 0xed, 0xea, 0x7e, 0x47, 0xde, 0xd7, 0xc2, 0xab, 0x11, 0x15, 0xf4, + 0xeb, 0xcb, 0xb4, 0x26, 0x77, 0xc7, 0xfb, 0xa6, 0xe0, 0xcf, 0xd8, 0x11, + 0x60, 0x28, 0x96, 0x25, 0x1a, 0xda, 0x1d, 0x5a, 0x0b, 0x46, 0x1a, 0xaf, + 0x4e, 0x00, 0x0f, 0x4d, 0x42, 0x31, 0xb9, 0x6d, 0x8d, 0xee, 0x76, 0x30, + 0xd9, 0xf1, 0xb7, 0x86, 0x0e, 0x64, 0x18, 0xda, 0xc8, 0xc3, 0xb0, 0x7b, + 0x66, 0xaf, 0x6f, 0xd1, 0xac, 0xdb, 0x44, 0xb2, 0x68, 0x3b, 0x29, 0xb4 +}; +/* COUNT = 3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_354_public_x[] = { +/* QCAVSx */ + 0x05, 0x06, 0x71, 0xaf, 0x65, 0xcb, 0xef, 0x92, 0xf3, 0x05, 0xe5, 0xfa, + 0xcb, 0x42, 0x88, 0xcc, 0x04, 0xa4, 0xc6, 0x97, 0x8a, 0x3b, 0x78, 0xaf, + 0xe4, 0x04, 0x9c, 0x6a, 0x99, 0x5f, 0xe8, 0xc3, 0xc0, 0xbb, 0x60, 0x9a, + 0xbe, 0x49, 0xd1, 0x52, 0xb1, 0xee, 0xd6, 0xc7, 0x14, 0xd2, 0x54, 0xfe, + 0x6e, 0xff, 0x15, 0x9a, 0x9e, 0xbd, 0x24, 0xad, 0x16, 0x91, 0x9e, 0xf7, + 0x6f, 0x44, 0x70, 0x05, 0x7e, 0xb7, 0xc2, 0x65, 0xa4, 0xbd, 0x96, 0xe8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_354_public_y[] = { +/* QCAVSy */ + 0x05, 0x1d, 0x08, 0xe2, 0x1d, 0x26, 0x4d, 0x8e, 0x4d, 0xbc, 0x73, 0x40, + 0x88, 0x42, 0xab, 0x57, 0xcd, 0x78, 0xd3, 0x23, 0xe7, 0xde, 0xb6, 0x25, + 0xb3, 0x74, 0x19, 0x94, 0xb8, 0xaf, 0xfe, 0x01, 0xaf, 0x44, 0x61, 0x62, + 0x2d, 0xb4, 0x19, 0xaf, 0xee, 0xad, 0x04, 0x58, 0x45, 0xf6, 0xc3, 0xdb, + 0x6d, 0x98, 0x2f, 0x45, 0xb6, 0x92, 0xbe, 0xa1, 0x1c, 0xf2, 0x5d, 0x18, + 0xac, 0xa3, 0xc8, 0x3b, 0xec, 0x84, 0x0c, 0x75, 0x82, 0xa7, 0x06, 0x2d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_354_private[] = { +/* dIUT */ + 0x02, 0x19, 0x97, 0xb5, 0x48, 0x1c, 0x0c, 0xf6, 0xcf, 0x43, 0x6b, 0xfe, + 0x36, 0x0c, 0x3b, 0x11, 0x9b, 0x9e, 0x4d, 0xd5, 0x6f, 0x3c, 0x28, 0x47, + 0xaf, 0xfb, 0x20, 0x21, 0xcb, 0xac, 0x4b, 0x57, 0xdc, 0x18, 0xf5, 0x07, + 0x5d, 0x67, 0x8a, 0xf2, 0xba, 0x6e, 0x9e, 0xef, 0xbc, 0x41, 0x38, 0xd8, + 0x18, 0x05, 0x3f, 0x2d, 0xf3, 0x2a, 0x10, 0xe8, 0xae, 0x5d, 0x64, 0x09, + 0xf5, 0xb2, 0xf1, 0xf3, 0xca, 0xbf, 0x36, 0xf8, 0x08, 0xfd, 0xc0, 0x7c +}; +/* QIUTx = 0560cf91328c26bba13f71c9b5dddd05c185969d88bd0e9d34a3607a923b23a5b675452167003ae2f0add5141ea4be41ebae91d3a6aa15c393dbf585ad6c9214b269e86b4f054bf5 */ +/* QIUTy = 02e32ec240418a9a4f9017e632f8a77897a2233d6f1f45b8f7aa818f847ddb3ceab5a5a12c754fce8d57b0320a076b53441dcf9f65ef3204e089191ef156ff762294897a72fca932 */ +static const uint8_t nist_kas_ecc_cdh_testvector_354_out[] = { +/* ZIUT */ + 0x00, 0x5b, 0x64, 0x00, 0x15, 0x33, 0x0f, 0x84, 0x16, 0xf2, 0xbb, 0xbf, + 0x8b, 0x56, 0x60, 0xe0, 0x1a, 0x7a, 0xbb, 0xa8, 0xb0, 0x19, 0x7a, 0x29, + 0xe5, 0x2b, 0xb5, 0x35, 0xd6, 0x2f, 0x89, 0xad, 0x04, 0x43, 0xe0, 0x8b, + 0x6e, 0x0d, 0x1d, 0x15, 0xf4, 0xeb, 0x03, 0xc0, 0xfe, 0x35, 0xe3, 0xe4, + 0x3b, 0xd7, 0x73, 0x9c, 0xb6, 0x92, 0x09, 0x26, 0x98, 0xa2, 0xcd, 0x13, + 0x12, 0x6c, 0xee, 0x44, 0x32, 0x83, 0x1e, 0xc7, 0x42, 0x3b, 0x34, 0x34 +}; +/* COUNT = 4 */ +static const uint8_t nist_kas_ecc_cdh_testvector_355_public_x[] = { +/* QCAVSx */ + 0x03, 0x9a, 0xc9, 0xe9, 0x1a, 0xf5, 0x94, 0x07, 0x4d, 0xcd, 0x33, 0x8d, + 0xa4, 0xf5, 0x24, 0x05, 0x74, 0xf0, 0x1e, 0x41, 0x3a, 0x49, 0xb9, 0x22, + 0x46, 0xba, 0x3d, 0x6d, 0xe8, 0x55, 0xe3, 0xde, 0xdf, 0x6e, 0x7f, 0xde, + 0xda, 0x9a, 0xb7, 0xf7, 0xf8, 0x47, 0x6e, 0x77, 0x0c, 0xe9, 0xbb, 0xc3, + 0xa9, 0xa5, 0xeb, 0x98, 0x45, 0x43, 0xdc, 0xc3, 0x7f, 0x5f, 0x11, 0xbe, + 0x6e, 0x28, 0xa1, 0xd1, 0x09, 0x09, 0x31, 0xf5, 0xc5, 0xb5, 0xa3, 0x51 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_355_public_y[] = { +/* QCAVSy */ + 0x07, 0x80, 0xd3, 0x2d, 0xbb, 0x13, 0x48, 0x99, 0xbd, 0xa2, 0xe9, 0x88, + 0x48, 0x94, 0x18, 0x78, 0x38, 0x7a, 0xba, 0x66, 0x65, 0xfd, 0x24, 0x25, + 0x21, 0x60, 0xce, 0x31, 0x23, 0xf6, 0x8f, 0x9b, 0x5b, 0xd8, 0xf2, 0x54, + 0xa3, 0x8b, 0x84, 0xec, 0x53, 0x65, 0x25, 0xfe, 0x00, 0x7a, 0x86, 0x3b, + 0x6f, 0xcc, 0x48, 0x9f, 0x93, 0x7a, 0x05, 0xa5, 0xfd, 0x94, 0x6d, 0x62, + 0x82, 0x53, 0x28, 0xa0, 0x9f, 0x83, 0xa7, 0xcb, 0xa2, 0x7f, 0xea, 0x5e +}; +static const uint8_t nist_kas_ecc_cdh_testvector_355_private[] = { +/* dIUT */ + 0x02, 0xb5, 0x39, 0xac, 0xc7, 0x70, 0x75, 0x87, 0x99, 0xf4, 0x39, 0x67, + 0x0e, 0xae, 0x85, 0xb9, 0xba, 0x34, 0xa8, 0xb4, 0xf3, 0x71, 0xcc, 0x93, + 0x5a, 0x20, 0xce, 0x8c, 0x56, 0x65, 0x21, 0xee, 0xcd, 0x8c, 0x4f, 0x5a, + 0xff, 0x11, 0x6a, 0xe0, 0xdb, 0x2a, 0xd6, 0xea, 0xe1, 0xa3, 0x38, 0x44, + 0x34, 0xc5, 0x99, 0x37, 0x98, 0x21, 0xad, 0x05, 0xd8, 0x1a, 0xda, 0x05, + 0x48, 0x29, 0x9d, 0xfd, 0x98, 0xcf, 0xd6, 0xd3, 0xf1, 0x57, 0x35, 0x24 +}; +/* QIUTx = 06dae538c820443977415cef4e79974ba762b69b434810200cc6fff326a2344cd21be19c153642df82a3e57a5531a8bf19767e1995d2728fcb661d58ec561ef23a34d8607971490d */ +/* QIUTy = 0504243c792b903184ea725a947ca89218ca9c8fa1e09a7dd68de88eae90f9bd2a8df414dd69a8b2b1a2ded2c6d7f514c8907997624eb0bc9ea933a2d474ef8f83baea3243834de2 */ +static const uint8_t nist_kas_ecc_cdh_testvector_355_out[] = { +/* ZIUT */ + 0x02, 0x7a, 0xf0, 0x5e, 0xcd, 0x03, 0x32, 0x78, 0x4d, 0x64, 0xb0, 0xb1, + 0xbd, 0xb4, 0x5c, 0x31, 0x0f, 0xd4, 0x45, 0xc5, 0xa6, 0xd6, 0xb3, 0x4f, + 0x35, 0xf4, 0xea, 0xa3, 0xfa, 0x3e, 0x17, 0x1a, 0xb9, 0x87, 0x63, 0xd2, + 0x43, 0xa1, 0xde, 0xdf, 0x46, 0xaa, 0x29, 0x86, 0x46, 0x20, 0xa4, 0x7d, + 0x05, 0xee, 0xae, 0xfd, 0x74, 0x81, 0x86, 0xbc, 0xbc, 0xf1, 0x87, 0xc0, + 0x1e, 0x7c, 0xe3, 0x6e, 0x2a, 0x53, 0xde, 0xd0, 0x71, 0x03, 0x6b, 0x59 +}; +/* COUNT = 5 */ +static const uint8_t nist_kas_ecc_cdh_testvector_356_public_x[] = { +/* QCAVSx */ + 0x06, 0xf6, 0x58, 0x84, 0x91, 0x06, 0x0a, 0x1e, 0x88, 0x14, 0x8e, 0x4b, + 0xde, 0xe3, 0x8b, 0xc6, 0x74, 0x71, 0x3f, 0xe3, 0x84, 0xd7, 0xcf, 0xdb, + 0xf5, 0xbd, 0x90, 0xc9, 0xdb, 0xb6, 0xe1, 0x58, 0x7e, 0x45, 0x9d, 0xce, + 0x6e, 0x0d, 0x69, 0xb8, 0xb2, 0xcf, 0xeb, 0x50, 0x55, 0xbe, 0xe5, 0x6a, + 0x73, 0xc1, 0x34, 0x36, 0x06, 0x01, 0x98, 0xad, 0x47, 0x50, 0xda, 0xe8, + 0x25, 0x3e, 0xa8, 0x39, 0xa2, 0xe2, 0x46, 0xd5, 0x41, 0x45, 0x97, 0x75 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_356_public_y[] = { +/* QCAVSy */ + 0x05, 0xb6, 0x1b, 0x8f, 0x7d, 0x8d, 0x6c, 0x81, 0x62, 0xa2, 0x26, 0x9e, + 0x72, 0x87, 0xd4, 0x59, 0x03, 0x4b, 0x8f, 0xaa, 0xc0, 0x36, 0x0f, 0xcf, + 0x99, 0xfb, 0x21, 0xda, 0x34, 0xa3, 0x14, 0xe6, 0x73, 0x53, 0x19, 0xb9, + 0xd0, 0x36, 0x26, 0xb9, 0x26, 0x83, 0x69, 0x34, 0x5f, 0x3a, 0x62, 0x4a, + 0xca, 0xdb, 0x21, 0x9b, 0x20, 0x71, 0x88, 0xd0, 0xe9, 0x45, 0xcb, 0xc6, + 0x7c, 0x98, 0x20, 0x68, 0xd3, 0x26, 0x13, 0xfc, 0x21, 0xf8, 0xb0, 0xf4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_356_private[] = { +/* dIUT */ + 0x03, 0x18, 0xa9, 0x6e, 0x38, 0x27, 0x82, 0xd4, 0x47, 0x6f, 0x1b, 0xeb, + 0xf6, 0x97, 0xa1, 0x07, 0x6f, 0x22, 0xe1, 0xd2, 0xec, 0x84, 0x74, 0x7f, + 0x9f, 0xc4, 0x25, 0x05, 0xd5, 0x54, 0x7d, 0xaa, 0xa0, 0x8d, 0x81, 0x47, + 0x21, 0x75, 0x96, 0x59, 0x95, 0x86, 0x85, 0xcf, 0x4e, 0xa4, 0xbb, 0xa1, + 0x2f, 0xff, 0xb6, 0x6a, 0xf0, 0x9f, 0x66, 0x94, 0x52, 0x1f, 0x11, 0xc0, + 0x9b, 0x66, 0x26, 0xc8, 0xae, 0x52, 0xfb, 0xfb, 0x33, 0x6a, 0x52, 0xa1 +}; +/* QIUTx = 06770f2fcd2e9b7f8bc5c292d283abad85155071fe37ef7ce84f34c7616da3dbe1bdce9ab04cea7bc4bc258c5d2ab77239d3d084568b2dff779988288d9fc6bb364f519d0e855ad3 */ +/* QIUTy = 04f6a1f4e5fe00fe9a25d8459b88803988ef2bf2fef5a23f13e7a7e7f3459abfc3d5c00303abcc5080fab81b09d5be0320ef990519a06af13c29562ee955715a82cc0daef2c5e0eb */ +static const uint8_t nist_kas_ecc_cdh_testvector_356_out[] = { +/* ZIUT */ + 0x07, 0x63, 0xc0, 0xd6, 0x59, 0xa7, 0xc0, 0x80, 0x91, 0x20, 0x05, 0xa2, + 0xaf, 0xd6, 0x0c, 0xe5, 0x7e, 0x61, 0x06, 0x19, 0xb3, 0x88, 0xef, 0x3d, + 0x5d, 0xd3, 0xc9, 0x38, 0x6a, 0xb1, 0x20, 0x69, 0xc6, 0xef, 0x3a, 0x8e, + 0x72, 0xeb, 0x74, 0x1c, 0xba, 0x2d, 0xa5, 0xc6, 0xf9, 0x26, 0x7f, 0x6c, + 0x09, 0xfa, 0xda, 0x64, 0x59, 0x69, 0x0e, 0xd4, 0xe4, 0x32, 0x44, 0x5d, + 0x6f, 0x0f, 0x72, 0xdb, 0xcb, 0x05, 0x9c, 0x87, 0xdf, 0x36, 0xf6, 0x65 +}; +/* COUNT = 6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_357_public_x[] = { +/* QCAVSx */ + 0x05, 0xa5, 0x2c, 0xeb, 0xf6, 0x81, 0x03, 0xca, 0xb0, 0x26, 0x6c, 0xf2, + 0xc6, 0x89, 0xc4, 0x8f, 0x08, 0x05, 0x49, 0xff, 0xfc, 0x70, 0xdb, 0x98, + 0x09, 0xc2, 0xa4, 0x6f, 0x90, 0x8b, 0x72, 0x89, 0xbe, 0x59, 0x73, 0x29, + 0xf3, 0x9e, 0xe1, 0xe4, 0xcc, 0xa3, 0x98, 0x66, 0x4f, 0xfa, 0x9b, 0xdc, + 0xf0, 0x12, 0x93, 0xf4, 0x35, 0x93, 0xd1, 0x88, 0xe1, 0x24, 0x11, 0xd5, + 0x7e, 0x55, 0x9b, 0x3f, 0x6a, 0x30, 0xe9, 0x55, 0x48, 0x69, 0xf0, 0x49 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_357_public_y[] = { +/* QCAVSy */ + 0x01, 0x4e, 0x13, 0x71, 0x65, 0xfb, 0x0d, 0x53, 0x0e, 0x86, 0x53, 0xd7, + 0xcb, 0x2a, 0x84, 0x61, 0x8d, 0xd3, 0xaf, 0xcf, 0xa3, 0xf0, 0x85, 0x60, + 0x17, 0x91, 0x42, 0xaa, 0xe9, 0x72, 0x79, 0x0c, 0xe7, 0x46, 0xa2, 0xfd, + 0x44, 0x69, 0xd4, 0x15, 0x58, 0x74, 0x43, 0x78, 0xc6, 0x40, 0xae, 0x73, + 0xa4, 0x89, 0xbb, 0x7f, 0x81, 0xcd, 0xca, 0x6b, 0x1b, 0xb1, 0x67, 0xc7, + 0x94, 0xc2, 0x6d, 0x62, 0x38, 0xa0, 0xd2, 0x56, 0xaf, 0xc3, 0xba, 0x21 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_357_private[] = { +/* dIUT */ + 0x02, 0x8b, 0x43, 0x19, 0xeb, 0x70, 0x54, 0xcf, 0xf6, 0x38, 0x28, 0x20, + 0xc5, 0x2f, 0x9c, 0x33, 0x2e, 0xae, 0x67, 0x0d, 0x1f, 0x07, 0xcf, 0xc8, + 0xf1, 0x47, 0x2e, 0x92, 0x60, 0xf5, 0xe4, 0x7a, 0x38, 0x57, 0x68, 0x01, + 0x6c, 0xd2, 0x00, 0x67, 0x00, 0xca, 0x7b, 0xdc, 0x5d, 0x1d, 0x56, 0x7d, + 0x92, 0x46, 0x0a, 0xf7, 0xc2, 0xa4, 0x25, 0xdd, 0x0d, 0x78, 0xae, 0xee, + 0x3d, 0x15, 0xfb, 0x28, 0xd7, 0x11, 0x67, 0xe6, 0x48, 0x6b, 0x81, 0xc4 +}; +/* QIUTx = 05b1b114cef13aa5df306ce74197d680f9b8c9d8f6753a09db88466a6bb04eaf1eb873836022d7504f45fae85a8e4a5417edd7ce3a0e5eb9e79264884ed783577b3fc52d825f0b57 */ +/* QIUTy = 018e3226e36b4b336799c4684bba505e984dc8819166f17ceb840e36125b283a8c8635ddf7e770406d9856d82b37cff1fbcc5d3f5cf4b55eca41ee131f21ea7bcb19ce05f6564245 */ +static const uint8_t nist_kas_ecc_cdh_testvector_357_out[] = { +/* ZIUT */ + 0x04, 0x28, 0x41, 0x3f, 0x2d, 0x2a, 0xad, 0x4d, 0x52, 0x88, 0x88, 0x5c, + 0x2e, 0xdc, 0x8b, 0x97, 0x63, 0x21, 0xae, 0x1d, 0xd4, 0xfc, 0x6b, 0x41, + 0x27, 0x5f, 0xb8, 0x8b, 0x8c, 0x5e, 0x77, 0x76, 0x16, 0x5e, 0xff, 0xce, + 0x79, 0x02, 0x51, 0x63, 0x53, 0x8a, 0x0e, 0x83, 0xc9, 0x19, 0x22, 0x0a, + 0x40, 0x7e, 0xad, 0x6c, 0xef, 0xd6, 0x16, 0xb4, 0xb0, 0x52, 0x94, 0x48, + 0x8c, 0x2e, 0xf5, 0xd3, 0x0a, 0xb8, 0xca, 0xa5, 0x5c, 0xcb, 0xd1, 0xb1 +}; +/* COUNT = 7 */ +static const uint8_t nist_kas_ecc_cdh_testvector_358_public_x[] = { +/* QCAVSx */ + 0x02, 0x6e, 0x2f, 0x1e, 0xe6, 0x4e, 0x79, 0x58, 0xe9, 0x02, 0x54, 0x7a, + 0x7d, 0xb0, 0xa1, 0xe1, 0x48, 0x66, 0xf3, 0xd2, 0xc0, 0x12, 0x7c, 0x2b, + 0xb9, 0xb0, 0x9e, 0xe2, 0x32, 0xd3, 0xd9, 0x51, 0x8e, 0xe4, 0x4a, 0xe8, + 0xf5, 0xbb, 0x43, 0x3a, 0x08, 0x80, 0x69, 0xfa, 0x38, 0x6c, 0xd5, 0xc8, + 0x90, 0x27, 0x11, 0xb7, 0x62, 0xac, 0x0d, 0xa3, 0xa7, 0xa3, 0x42, 0x04, + 0x72, 0xc4, 0x7e, 0x85, 0x0f, 0x98, 0x8d, 0xd6, 0x0a, 0x63, 0x6d, 0x7d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_358_public_y[] = { +/* QCAVSy */ + 0x06, 0x77, 0xff, 0x51, 0x00, 0x52, 0xd4, 0xf4, 0x60, 0x84, 0x9f, 0xb8, + 0xef, 0x0d, 0x4f, 0x35, 0x19, 0xcd, 0x23, 0x8e, 0x4e, 0x1c, 0x68, 0x8b, + 0x73, 0x6c, 0xf6, 0xe3, 0x75, 0x95, 0x50, 0xd1, 0x34, 0xa1, 0xe6, 0xca, + 0x3c, 0xb4, 0x79, 0xd6, 0x8b, 0x4d, 0xc5, 0xd0, 0xbb, 0xa1, 0xae, 0xe1, + 0x78, 0xbd, 0x6f, 0xe1, 0x5e, 0xc1, 0x96, 0xfb, 0x1f, 0x62, 0x7d, 0x87, + 0x07, 0x93, 0x94, 0xf6, 0xf7, 0x85, 0x4e, 0x05, 0x32, 0x28, 0xde, 0xe5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_358_private[] = { +/* dIUT */ + 0x02, 0x01, 0x15, 0xd1, 0x7e, 0x41, 0xe1, 0x31, 0x78, 0xb4, 0x2a, 0x00, + 0x4c, 0x01, 0xd5, 0xe4, 0xef, 0x1c, 0x76, 0x24, 0x10, 0x49, 0xc7, 0xd3, + 0x1b, 0xf0, 0xea, 0x85, 0xd6, 0xe0, 0x70, 0xa2, 0xe2, 0xb9, 0x20, 0x80, + 0xe6, 0x1d, 0xe5, 0x46, 0xfc, 0xcb, 0xd4, 0xd9, 0x91, 0x23, 0x6b, 0xb3, + 0x60, 0xef, 0x3f, 0x20, 0x6e, 0xe1, 0x6d, 0x88, 0x43, 0xa0, 0xdd, 0xc8, + 0x03, 0x46, 0x36, 0x64, 0xa8, 0xcc, 0xdc, 0x2d, 0x87, 0xa1, 0x02, 0x77 +}; +/* QIUTx = 06c8ac34364acae35e3c417160333e48641868fcca04c0d577be06f58ab0a55fd7db779fe737779da33d009f57b5bad49702eacf575acbaf27df833070cd893a7924770c92eff3a0 */ +/* QIUTy = 061b82e545d41c62fef068b34cdbf01396115d2a1417f9719483d26986b6d52f8f6de06837795f6d9dd7cd095741114318c6e8a6206b3deeef014f0e44b0dc6684e100e4ac361650 */ +static const uint8_t nist_kas_ecc_cdh_testvector_358_out[] = { +/* ZIUT */ + 0x03, 0x1b, 0xd2, 0xa8, 0x43, 0x69, 0xe9, 0x3d, 0xfa, 0x00, 0x58, 0x14, + 0x46, 0xd5, 0x27, 0x62, 0x10, 0x0d, 0x98, 0x5c, 0xc7, 0xbb, 0x91, 0xc4, + 0xfa, 0x8b, 0xe7, 0x47, 0x2e, 0x2e, 0x8e, 0x97, 0x81, 0xc5, 0x2b, 0x19, + 0xa5, 0x43, 0x30, 0x44, 0x24, 0x41, 0xba, 0xca, 0xe2, 0x3f, 0x4b, 0xdc, + 0x76, 0x48, 0x6e, 0xb4, 0x75, 0xd5, 0x1f, 0x26, 0xaa, 0xfb, 0xfb, 0x27, + 0x2a, 0x5a, 0xb5, 0xdb, 0x18, 0x4a, 0x4d, 0x3c, 0x30, 0x06, 0xe5, 0xd1 +}; +/* COUNT = 8 */ +static const uint8_t nist_kas_ecc_cdh_testvector_359_public_x[] = { +/* QCAVSx */ + 0x02, 0x3e, 0xe4, 0xf9, 0xec, 0x24, 0xde, 0xe2, 0x03, 0xac, 0xfb, 0x65, + 0x86, 0x31, 0x31, 0x3c, 0x7a, 0xd4, 0x39, 0x4c, 0x47, 0xf1, 0x79, 0x4d, + 0x08, 0xb5, 0x99, 0xff, 0xc1, 0x5f, 0x0e, 0x5d, 0xab, 0x29, 0x11, 0xd9, + 0x7e, 0x03, 0x0d, 0xdf, 0x7c, 0xb4, 0xbb, 0xad, 0xf8, 0xa5, 0xbc, 0xe0, + 0x5c, 0x35, 0x35, 0x8f, 0xbd, 0x0c, 0xf9, 0x5d, 0x3d, 0x5c, 0x7f, 0xf3, + 0xcd, 0x8e, 0xe6, 0xb5, 0x4e, 0x37, 0x9d, 0x8d, 0x01, 0x23, 0x93, 0x9b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_359_public_y[] = { +/* QCAVSy */ + 0x06, 0x06, 0xbe, 0x23, 0xe7, 0xc5, 0x74, 0x6d, 0xbd, 0x38, 0x40, 0x4f, + 0xd6, 0x07, 0xfb, 0x7f, 0x27, 0x8e, 0xe2, 0x49, 0xdc, 0x8e, 0x27, 0x40, + 0xcf, 0x1b, 0xb9, 0xb1, 0xc0, 0x7b, 0x1c, 0xf7, 0xe0, 0xa5, 0x0a, 0x43, + 0x25, 0x67, 0xd1, 0x86, 0x97, 0x99, 0xa8, 0x03, 0x12, 0x25, 0x10, 0xdb, + 0x43, 0x79, 0x81, 0xa2, 0xaa, 0x12, 0x6e, 0xb9, 0xaa, 0xf3, 0xc7, 0xbe, + 0x05, 0xa8, 0x0f, 0xac, 0x14, 0x95, 0xe1, 0xc4, 0x0c, 0xa1, 0xc1, 0x06 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_359_private[] = { +/* dIUT */ + 0x00, 0x84, 0x7b, 0x54, 0x5e, 0xf4, 0x96, 0x15, 0x67, 0x1f, 0x08, 0xbe, + 0x73, 0xa4, 0x91, 0x47, 0x06, 0x31, 0x84, 0x49, 0x33, 0x40, 0x11, 0x1e, + 0xa4, 0xdc, 0xe1, 0x3c, 0x2f, 0x92, 0x1f, 0x07, 0xbf, 0xac, 0xff, 0xc8, + 0x44, 0x1f, 0x4c, 0x7c, 0x9d, 0x04, 0x79, 0xf5, 0x7f, 0x3a, 0x13, 0xf4, + 0xc3, 0x3c, 0x63, 0xed, 0x47, 0xc3, 0xa4, 0x3f, 0xb2, 0xf0, 0x6d, 0x06, + 0xa9, 0x78, 0x0e, 0x5c, 0x0b, 0x3a, 0xc3, 0x04, 0x10, 0xad, 0xc4, 0x91 +}; +/* QIUTx = 06994ddc5ae2c5b6f45dc32b710f1a49391a47f3a0f8c2d7846552fe487ef01cca0431155bb54533b067a29e8367373af95d6a7f0bf98d869b708f48f95f1b88a1530fe22547e97e */ +/* QIUTy = 04f6288d4d704f33a898031e7d0046fbf1e34a72c8af190f4d33163343c897ba0c0d8af8a86236a1c3b655b979dc4522d33d66a665b3b6501570f076322af0ad2bbaaa04ea2e995d */ +static const uint8_t nist_kas_ecc_cdh_testvector_359_out[] = { +/* ZIUT */ + 0x04, 0xdf, 0x20, 0x15, 0x4f, 0xa4, 0x9a, 0x1d, 0x6e, 0x04, 0xdc, 0x2b, + 0xa6, 0xe5, 0x5a, 0x7f, 0x2a, 0xe5, 0x75, 0xde, 0x5e, 0x2c, 0x6e, 0x40, + 0x91, 0xa4, 0xd2, 0xc3, 0x6a, 0xa9, 0x3c, 0xa9, 0x69, 0x9b, 0x89, 0x0f, + 0x0e, 0xe4, 0xdf, 0x53, 0xaa, 0x75, 0xd0, 0xd9, 0xba, 0xba, 0xd6, 0x86, + 0x05, 0xbc, 0x02, 0x7e, 0xc6, 0x7c, 0x18, 0x7a, 0x68, 0x26, 0xaa, 0xc0, + 0xf4, 0xbc, 0x59, 0x6b, 0xaa, 0xe7, 0x88, 0xb3, 0x76, 0x11, 0x02, 0x16 +}; +/* COUNT = 9 */ +static const uint8_t nist_kas_ecc_cdh_testvector_360_public_x[] = { +/* QCAVSx */ + 0x00, 0xd4, 0xa0, 0xb1, 0x1c, 0x17, 0x39, 0xbe, 0xd0, 0x94, 0xe7, 0x2d, + 0x7a, 0x69, 0x23, 0x83, 0x68, 0x36, 0xd9, 0x21, 0x57, 0x46, 0xc7, 0x2c, + 0xc6, 0x80, 0x04, 0x5a, 0x36, 0xd8, 0x1a, 0xdf, 0x5e, 0x25, 0x39, 0x4f, + 0x26, 0x9a, 0x2a, 0xda, 0x1d, 0x94, 0x39, 0xeb, 0xc3, 0x3b, 0xb9, 0x31, + 0xd6, 0xfa, 0x59, 0x5a, 0x25, 0x26, 0x1c, 0x24, 0x4a, 0x1e, 0x17, 0xb0, + 0x46, 0xfb, 0x10, 0xfb, 0x54, 0xbb, 0x31, 0x22, 0x88, 0xcf, 0x2e, 0x8d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_360_public_y[] = { +/* QCAVSy */ + 0x07, 0x52, 0x04, 0xf5, 0x0d, 0x32, 0xab, 0x8a, 0x6a, 0xbb, 0xff, 0x98, + 0x2d, 0x1f, 0xe3, 0x72, 0xb8, 0xc5, 0x41, 0x5b, 0xb5, 0xb7, 0x26, 0xb3, + 0x46, 0xaa, 0x4f, 0x08, 0xbe, 0x32, 0xf8, 0xca, 0x28, 0x2c, 0x1e, 0xf6, + 0xe1, 0x52, 0x42, 0x33, 0x60, 0xd9, 0x7b, 0x72, 0x8a, 0x07, 0x4e, 0x6b, + 0x3c, 0xf3, 0xb9, 0x12, 0x71, 0x8b, 0x16, 0x92, 0xcd, 0x98, 0x30, 0x19, + 0x74, 0x1a, 0x25, 0x41, 0x82, 0x42, 0x34, 0xbd, 0xc8, 0xc3, 0x23, 0xf9 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_360_private[] = { +/* dIUT */ + 0x03, 0x4c, 0x24, 0x58, 0x30, 0x2b, 0x43, 0x85, 0x7f, 0x12, 0xad, 0x8b, + 0xd9, 0xa8, 0x75, 0x23, 0x76, 0x41, 0xa2, 0x1e, 0x21, 0xca, 0x3c, 0xf9, + 0xa0, 0x95, 0x6d, 0x3c, 0xfe, 0xde, 0xd9, 0x6a, 0x5e, 0x1f, 0x53, 0x3d, + 0x82, 0x7b, 0x52, 0x8f, 0xbb, 0x58, 0x6d, 0xa9, 0x3e, 0xef, 0xbb, 0x66, + 0xd0, 0x77, 0x8b, 0x19, 0xb1, 0xa7, 0xfb, 0x6f, 0x17, 0xbb, 0xf9, 0xe7, + 0x9b, 0x9a, 0xce, 0xfc, 0xdd, 0x7b, 0x96, 0x05, 0xe7, 0x89, 0x8f, 0x26 +}; +/* QIUTx = 032d3a7a4099f089fea9189211f7366f2edc4abfb316c5c05948d8de57fca023bfb6a11b102ea4120ba62192c0df610bd8d2f63fc57727f4a6b640abf8d299fac56c4c7af88349ea */ +/* QIUTy = 04e6399f1ced2669d3a5506d35ea2bebfccf0cec84bc97383aadc3b48347f629626e6096f890435e5933675048fdcefcdede3ed616e6560d42e9e17c5492e30bc2de4689c0592ecb */ +static const uint8_t nist_kas_ecc_cdh_testvector_360_out[] = { +/* ZIUT */ + 0x03, 0x7a, 0x38, 0x0f, 0x52, 0x55, 0x90, 0x58, 0x26, 0x58, 0xe2, 0xdd, + 0x27, 0x2a, 0x32, 0xde, 0x67, 0xfc, 0x0c, 0xf5, 0x39, 0x0b, 0x37, 0xf4, + 0xd3, 0x3c, 0x13, 0x59, 0xf0, 0x75, 0xd4, 0x46, 0x1e, 0xa3, 0x8a, 0x55, + 0x02, 0x73, 0x17, 0x89, 0x2a, 0x3d, 0x1d, 0x22, 0xf5, 0xea, 0x33, 0x3a, + 0xd4, 0x37, 0x66, 0x7d, 0x2f, 0x3e, 0xb8, 0x78, 0x1c, 0x39, 0x50, 0x40, + 0x36, 0xae, 0x33, 0xe4, 0xb0, 0xa2, 0x6b, 0x68, 0x94, 0x72, 0x2f, 0x0b +}; +/* COUNT = 10 */ +static const uint8_t nist_kas_ecc_cdh_testvector_361_public_x[] = { +/* QCAVSx */ + 0x03, 0xbb, 0x84, 0x03, 0x2b, 0x7f, 0xff, 0xce, 0x27, 0xac, 0xcf, 0x35, + 0x4b, 0x89, 0xdd, 0xdf, 0x64, 0x6c, 0xdc, 0xb5, 0x66, 0x34, 0xdf, 0x0f, + 0x85, 0x20, 0xa7, 0x73, 0x0f, 0x8a, 0xbe, 0xb0, 0x5f, 0x99, 0x33, 0xd8, + 0xa4, 0x35, 0x2d, 0x1c, 0x77, 0x67, 0xcc, 0x3f, 0x9b, 0x80, 0xce, 0xff, + 0xcd, 0xd0, 0xcb, 0x3a, 0x97, 0xb5, 0x92, 0x83, 0xfd, 0x0a, 0x67, 0x4d, + 0xc4, 0xfd, 0x24, 0x03, 0x33, 0xf0, 0x20, 0xc8, 0x2b, 0x48, 0x04, 0xc5 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_361_public_y[] = { +/* QCAVSy */ + 0x07, 0x44, 0x99, 0x33, 0x6a, 0xc3, 0xa8, 0x05, 0x43, 0x07, 0x89, 0x90, + 0x27, 0x68, 0x25, 0x20, 0x26, 0xb5, 0x26, 0xec, 0xe5, 0x4a, 0xc2, 0x8e, + 0x8c, 0xc8, 0x78, 0xf1, 0x8b, 0xaf, 0x9f, 0xab, 0x42, 0xba, 0x4c, 0xe3, + 0x4e, 0x49, 0x68, 0xaa, 0xc1, 0xee, 0x6a, 0x0b, 0xb1, 0x5c, 0x9a, 0x70, + 0x98, 0x82, 0xa5, 0x37, 0x2a, 0xf5, 0x6e, 0xa0, 0xb3, 0x68, 0x17, 0x38, + 0x5f, 0xbb, 0xfe, 0xac, 0x4b, 0x90, 0x60, 0x69, 0xe5, 0x3f, 0xbf, 0xba +}; +static const uint8_t nist_kas_ecc_cdh_testvector_361_private[] = { +/* dIUT */ + 0x01, 0x2d, 0xb7, 0x85, 0xa0, 0x3c, 0x26, 0xbe, 0x3a, 0x6e, 0x9a, 0x58, + 0x2e, 0x5c, 0x32, 0xa8, 0x95, 0x70, 0xad, 0x43, 0x08, 0xb7, 0x13, 0xce, + 0x54, 0x71, 0xea, 0x19, 0x3d, 0xec, 0x1f, 0x32, 0xd6, 0x8b, 0x4f, 0xcd, + 0xfb, 0x16, 0x00, 0xfd, 0xb1, 0xec, 0xb6, 0x76, 0x9e, 0x26, 0xa0, 0xe0, + 0x57, 0x81, 0x2d, 0xbb, 0xf0, 0xed, 0x49, 0x55, 0x92, 0x66, 0x5e, 0x6b, + 0x8e, 0x9a, 0x97, 0x37, 0x8a, 0x30, 0xb5, 0xc6, 0x60, 0xfb, 0xad, 0xc1 +}; +/* QIUTx = 07edf7ee0ec77f5a6c3c9ec4ed8fd3cb814a342e9cc6470b54781ed6c141e2115c86dbd7ba27993eb7ebed7a38be488f96fddfa982f3691aa1c2a697f7706bff3d1add7396066194 */ +/* QIUTy = 07b3824b7f7b266fa42fe536adc2ac79b9d1e5b408e7217b3a99ddeb992f3123ff2d168774d300a818a32692e265afc6f6f578d9bd3121132b5979841f7a2d060e8948901d657c1c */ +static const uint8_t nist_kas_ecc_cdh_testvector_361_out[] = { +/* ZIUT */ + 0x04, 0x20, 0xde, 0x31, 0x3b, 0xdd, 0xce, 0x87, 0xd0, 0x73, 0x21, 0xe3, + 0xf0, 0xaf, 0x40, 0x4d, 0x9d, 0x13, 0xe5, 0x36, 0x9b, 0x79, 0x50, 0x6e, + 0x80, 0x71, 0x78, 0x71, 0x11, 0x53, 0xc9, 0xb1, 0x83, 0x7c, 0xd0, 0x55, + 0x56, 0x2e, 0xff, 0x3a, 0xad, 0xfc, 0x59, 0x54, 0xa2, 0x21, 0xee, 0xeb, + 0xb1, 0xbe, 0xc1, 0x69, 0x6d, 0x3d, 0xf1, 0xcc, 0xcf, 0xb8, 0xb6, 0x11, + 0x72, 0xa5, 0x0d, 0x83, 0xce, 0xe9, 0x5f, 0x41, 0x40, 0xba, 0x07, 0x0b +}; +/* COUNT = 11 */ +static const uint8_t nist_kas_ecc_cdh_testvector_362_public_x[] = { +/* QCAVSx */ + 0x06, 0x55, 0x6a, 0x4c, 0xc9, 0x84, 0x66, 0x79, 0x4a, 0x93, 0xd0, 0x33, + 0x88, 0x53, 0x67, 0x76, 0xf7, 0xa4, 0xb3, 0x34, 0x4c, 0x3d, 0xc4, 0xeb, + 0x96, 0x0a, 0x4a, 0x64, 0x58, 0xfc, 0x78, 0x69, 0xcd, 0x4e, 0x45, 0xb2, + 0xf1, 0x40, 0xc4, 0x68, 0xa7, 0xd4, 0xeb, 0xba, 0x84, 0xc9, 0x48, 0x23, + 0x37, 0xa2, 0xa8, 0xad, 0xaa, 0xc8, 0x8a, 0x9a, 0x62, 0x9d, 0xa0, 0x3d, + 0xd2, 0x47, 0x52, 0x66, 0x42, 0xb0, 0xab, 0x71, 0xfb, 0x7a, 0x8c, 0x70 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_362_public_y[] = { +/* QCAVSy */ + 0x05, 0x4b, 0x97, 0xd9, 0x52, 0xb1, 0x9f, 0x74, 0x28, 0x56, 0xda, 0xcf, + 0x4e, 0x50, 0xdf, 0x0c, 0x31, 0x03, 0xba, 0xf2, 0x53, 0xf4, 0xde, 0x65, + 0xa3, 0xd9, 0xca, 0xce, 0x63, 0xfe, 0x82, 0x90, 0x6d, 0x2c, 0x8e, 0x8a, + 0x33, 0x12, 0xfb, 0x53, 0x5e, 0x00, 0xf9, 0xb5, 0xca, 0x69, 0xf8, 0x7d, + 0xbc, 0x7f, 0xa3, 0xf7, 0xd8, 0x7f, 0xe0, 0x24, 0x53, 0x66, 0x04, 0xaa, + 0xfe, 0x46, 0x40, 0x59, 0x3c, 0xcc, 0xfe, 0xf6, 0xfa, 0xc0, 0x28, 0xa6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_362_private[] = { +/* dIUT */ + 0x02, 0x02, 0x60, 0x6a, 0x76, 0xb6, 0xa1, 0x3d, 0x6e, 0x29, 0x28, 0x0b, + 0xc1, 0x61, 0x3e, 0x11, 0x50, 0x25, 0x77, 0x0b, 0x24, 0x5f, 0x55, 0x61, + 0xd5, 0x88, 0x3e, 0x13, 0x5e, 0x15, 0x9c, 0xc4, 0x37, 0xb1, 0xc9, 0x35, + 0x5b, 0x2e, 0xee, 0x2b, 0x3b, 0xab, 0xef, 0x22, 0x9f, 0xe5, 0x45, 0xaa, + 0xb2, 0xbc, 0xca, 0x15, 0x5e, 0x89, 0x72, 0x49, 0x5f, 0x19, 0x74, 0xbd, + 0xb1, 0xec, 0x0e, 0x60, 0xc4, 0xe6, 0xc7, 0x9c, 0x48, 0xf2, 0x6a, 0x46 +}; +/* QIUTx = 06e74dba4e0702f186d334d3c49e2578e1edfac564645dda8c4a588158f8d7a3ef63243653c0d507427734fb4cc87adf4a36bd5abca1f920b9bd6e3bfa51c916d5710884594e9485 */ +/* QIUTy = 05b92147a2db48a3830ccfa28951a2b7e8eb84313b99b0a99031c7834c633f865a2f9844952528ae5dee02428a824cdfb7e20928ffc53420df38ead0b4240d0659d5adb1ff2e2dcb */ +static const uint8_t nist_kas_ecc_cdh_testvector_362_out[] = { +/* ZIUT */ + 0x06, 0x06, 0x22, 0x8f, 0x5a, 0x05, 0x07, 0x7a, 0xee, 0xfb, 0xef, 0xac, + 0x23, 0xc0, 0xd5, 0xba, 0xc7, 0xa6, 0x06, 0x2b, 0xfc, 0x2b, 0x02, 0xce, + 0x8b, 0xba, 0x66, 0x98, 0xea, 0x96, 0xb4, 0x56, 0xb1, 0xf0, 0xd3, 0x2c, + 0x6e, 0x05, 0xdb, 0xb9, 0xbe, 0x61, 0xa8, 0x30, 0x90, 0x42, 0x8e, 0xed, + 0xea, 0x18, 0xc7, 0x4f, 0x41, 0x23, 0x8e, 0xde, 0xde, 0x9e, 0x3a, 0x12, + 0xe2, 0x87, 0x22, 0xd2, 0xf3, 0x14, 0x61, 0x3c, 0x2e, 0x84, 0xd6, 0xdb +}; +/* COUNT = 12 */ +static const uint8_t nist_kas_ecc_cdh_testvector_363_public_x[] = { +/* QCAVSx */ + 0x01, 0x00, 0x51, 0x82, 0xb0, 0x29, 0xa4, 0x85, 0x28, 0xee, 0xf5, 0xff, + 0xd0, 0x22, 0x1a, 0xd8, 0x70, 0x85, 0xab, 0xac, 0x6a, 0x72, 0x70, 0x52, + 0x03, 0xa3, 0xc1, 0x68, 0x9a, 0xbb, 0xbc, 0x0e, 0x12, 0x92, 0x7a, 0x5e, + 0x83, 0xb3, 0x52, 0xa1, 0xba, 0xd9, 0x77, 0x06, 0x10, 0x1f, 0x44, 0xa1, + 0x02, 0x2c, 0xcc, 0x0d, 0x55, 0x22, 0xdc, 0x5d, 0x1c, 0xa1, 0x43, 0x3d, + 0xe0, 0x3a, 0x2b, 0xa1, 0xdf, 0x86, 0x48, 0x75, 0xf5, 0x22, 0xbe, 0x61 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_363_public_y[] = { +/* QCAVSy */ + 0x01, 0x8b, 0x02, 0xa9, 0x8f, 0x0b, 0x3e, 0x4c, 0xcf, 0x44, 0xa9, 0x69, + 0x39, 0xa2, 0x08, 0x3a, 0xb1, 0xf2, 0xa0, 0x4d, 0xaf, 0xd5, 0xbd, 0xce, + 0xe3, 0xcf, 0xf4, 0x38, 0xbb, 0x08, 0xbf, 0xf1, 0x20, 0x43, 0xaa, 0x19, + 0x2c, 0x5f, 0xcf, 0x34, 0xe1, 0x3b, 0x5c, 0x29, 0x74, 0x2c, 0x5d, 0x86, + 0x4b, 0x9c, 0xac, 0x46, 0xbe, 0xa6, 0xe9, 0x6d, 0xf2, 0xb1, 0xbe, 0x44, + 0x93, 0xac, 0xf9, 0x50, 0x22, 0x4d, 0x71, 0x73, 0x7f, 0x99, 0x06, 0x58 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_363_private[] = { +/* dIUT */ + 0x00, 0x48, 0x67, 0x83, 0x48, 0xac, 0x33, 0xb9, 0x2f, 0x2c, 0x59, 0x67, + 0x71, 0x03, 0xea, 0x40, 0x99, 0x46, 0xb5, 0x59, 0x3d, 0x10, 0x5f, 0xc4, + 0x98, 0x33, 0x51, 0xc4, 0xed, 0xe9, 0x29, 0xc4, 0xb9, 0x3b, 0xfc, 0x69, + 0x58, 0x76, 0x55, 0x5e, 0x3a, 0xce, 0x41, 0x7b, 0x82, 0xac, 0x05, 0xb8, + 0x32, 0x67, 0x6a, 0xc2, 0x3e, 0x29, 0x55, 0xa0, 0x9e, 0xe6, 0x4a, 0x20, + 0xa5, 0xf9, 0x8e, 0x62, 0x49, 0x9f, 0x43, 0xba, 0x7f, 0x7f, 0xc8, 0xe1 +}; +/* QIUTx = 031dd4808d2b341b8881f5e50a2dcce38df839009f92185978dfd9a60cdaee005cdba82655647736d407afb90c67cddb13ba2b01618f45e8a274317e02f770f80ef87bbbc1b11056 */ +/* QIUTy = 050a0671c9c0ce57a494e6911f1376cf1fc3393885ba8c26f6ddcbb5361876860a35afc1f4560f2970c30db3f1c817dbc8af2b025daed3a9da12d2fae9d714cead80445e6a0a0813 */ +static const uint8_t nist_kas_ecc_cdh_testvector_363_out[] = { +/* ZIUT */ + 0x05, 0x26, 0x69, 0x33, 0x60, 0x19, 0xdb, 0x5e, 0xdd, 0xef, 0x5e, 0xab, + 0x23, 0x36, 0xab, 0xeb, 0x60, 0xbb, 0xc7, 0x29, 0x5e, 0x4b, 0xb6, 0x63, + 0xab, 0x43, 0xe3, 0x73, 0xfb, 0x6d, 0x88, 0x8d, 0x74, 0x33, 0xec, 0x89, + 0xa4, 0x87, 0xa9, 0x1d, 0x4a, 0x59, 0xc2, 0x89, 0xa9, 0x50, 0x9d, 0xdd, + 0x1b, 0xab, 0x33, 0xcd, 0x02, 0xa7, 0xbf, 0x37, 0xaa, 0xad, 0x78, 0xdb, + 0xed, 0xf0, 0xb4, 0xae, 0x5f, 0x2f, 0x35, 0xd1, 0x5c, 0xb4, 0xe6, 0x28 +}; +/* COUNT = 13 */ +static const uint8_t nist_kas_ecc_cdh_testvector_364_public_x[] = { +/* QCAVSx */ + 0x07, 0xfa, 0xb4, 0xe5, 0x93, 0x28, 0xc7, 0x00, 0xf7, 0x46, 0x49, 0xbd, + 0x90, 0xa7, 0xd5, 0x1f, 0xf2, 0x89, 0x58, 0xfe, 0x72, 0x0d, 0xaa, 0xab, + 0x32, 0x8c, 0xfc, 0x9b, 0x00, 0x2a, 0xa7, 0x06, 0xce, 0xb3, 0x99, 0x34, + 0xdb, 0x9c, 0xcf, 0x81, 0xde, 0xec, 0x95, 0x68, 0x9c, 0xe8, 0xc7, 0x76, + 0xb4, 0xfc, 0x65, 0x42, 0xa8, 0x23, 0x58, 0xcc, 0x51, 0xeb, 0xbc, 0x6d, + 0x8e, 0x53, 0x22, 0xcb, 0x3f, 0xa6, 0xe4, 0x69, 0x5e, 0x17, 0x0f, 0xc1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_364_public_y[] = { +/* QCAVSy */ + 0x05, 0xac, 0xd4, 0x5c, 0xff, 0xa2, 0x9d, 0xdb, 0x34, 0xee, 0x42, 0xe7, + 0x41, 0x00, 0x26, 0x79, 0x8e, 0x37, 0xa8, 0xd1, 0xa9, 0xce, 0x9f, 0x92, + 0x94, 0xda, 0x51, 0x98, 0x16, 0x4b, 0x69, 0x01, 0x0c, 0x68, 0xc5, 0x32, + 0x81, 0xcc, 0xbf, 0xc4, 0x07, 0xd1, 0x41, 0x09, 0x7d, 0xa1, 0x37, 0xe7, + 0x84, 0x9f, 0x22, 0x8f, 0xdc, 0x1a, 0x07, 0xaa, 0x29, 0x8b, 0xe2, 0x6c, + 0xa7, 0x71, 0xf4, 0x7a, 0xc4, 0xfe, 0xb2, 0x72, 0x3d, 0x5a, 0x66, 0x66 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_364_private[] = { +/* dIUT */ + 0x00, 0x17, 0xba, 0xb7, 0x2d, 0x78, 0x8f, 0x8b, 0x78, 0xb9, 0xbf, 0xc4, + 0x91, 0x28, 0x63, 0xc5, 0xa4, 0x89, 0x22, 0xfe, 0x69, 0xe8, 0xa4, 0xcf, + 0x5e, 0x6e, 0x91, 0x76, 0x3e, 0xfd, 0x54, 0x77, 0xa1, 0xcd, 0x43, 0x9d, + 0xed, 0xd0, 0xaf, 0xea, 0x50, 0x4e, 0x3b, 0x3a, 0xf6, 0x82, 0x3e, 0xa3, + 0x08, 0x9c, 0x03, 0x74, 0xed, 0x9a, 0xee, 0x24, 0xa8, 0x85, 0x16, 0xc8, + 0xcf, 0x3a, 0xfa, 0xbe, 0x99, 0x5b, 0x9b, 0x96, 0x75, 0xf3, 0xb5, 0xab +}; +/* QIUTx = 0161c14bbc84e42ec7677a8c3770065ecd1f0f44eac8242a715a61971e7e4ffff78ff57a1bf1b95cbfc2ed957d1195f9ea50809715c2439c7543e573520135426d47535b8bfc8533 */ +/* QIUTy = 01253633d02251464edcc53ed9e8a9ed9329320ef5eeaf35d64c59b9735c96e07f1a62ec17bcee4f04cd9a85a3eb504aaf37bb388c6c7d08d90aa0b68556b5c068ecbf0a5984460d */ +static const uint8_t nist_kas_ecc_cdh_testvector_364_out[] = { +/* ZIUT */ + 0x06, 0x2d, 0xe5, 0xaa, 0x98, 0xb4, 0x40, 0xc6, 0xcb, 0x7a, 0x14, 0x28, + 0xf6, 0xb5, 0xe4, 0x74, 0x52, 0xb3, 0x04, 0x54, 0xee, 0xc4, 0xd6, 0x51, + 0x98, 0x2b, 0x53, 0x11, 0x21, 0xfe, 0xbb, 0xd5, 0xa3, 0x83, 0x3b, 0x18, + 0x00, 0x17, 0xf7, 0xdd, 0xb5, 0xce, 0x38, 0xd7, 0xbb, 0x1c, 0x84, 0x2d, + 0xe1, 0xa8, 0xa8, 0xfc, 0x7f, 0xc9, 0x81, 0xe2, 0x47, 0x33, 0xb7, 0x66, + 0x28, 0x13, 0xfd, 0x01, 0x0a, 0x4e, 0x75, 0x7c, 0xa4, 0xea, 0x5c, 0x28 +}; +/* COUNT = 14 */ +static const uint8_t nist_kas_ecc_cdh_testvector_365_public_x[] = { +/* QCAVSx */ + 0x07, 0x26, 0x76, 0x30, 0x2a, 0xd1, 0x87, 0x31, 0xb7, 0x62, 0x02, 0xbc, + 0x51, 0x42, 0x9e, 0xbf, 0x7e, 0xcc, 0xf6, 0x32, 0x5f, 0x4e, 0x08, 0x4c, + 0x2f, 0x92, 0xe3, 0x28, 0x8e, 0xd2, 0x90, 0x48, 0x8b, 0x9e, 0x36, 0x72, + 0x0e, 0x29, 0xda, 0xa2, 0xdb, 0x19, 0x93, 0xa7, 0xd1, 0x7c, 0xe8, 0xef, + 0x9d, 0x8c, 0xce, 0xc6, 0x1d, 0xe8, 0xa4, 0x07, 0x17, 0x6e, 0x26, 0x74, + 0xc2, 0x5d, 0x57, 0xbf, 0xf2, 0xc4, 0x65, 0x96, 0x35, 0x8b, 0x36, 0x05 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_365_public_y[] = { +/* QCAVSy */ + 0x03, 0xc0, 0x02, 0x2d, 0x53, 0x22, 0x90, 0x91, 0xe1, 0x4a, 0xf0, 0xf7, + 0x45, 0x0d, 0xec, 0xa1, 0xcb, 0x5d, 0xb8, 0x21, 0xe7, 0x15, 0x90, 0x60, + 0x8f, 0xe0, 0x98, 0x6d, 0x73, 0xe8, 0x8c, 0x91, 0x5e, 0x5e, 0xe8, 0xdf, + 0xeb, 0xc8, 0x95, 0x59, 0x13, 0xd9, 0x16, 0x4f, 0x99, 0x2f, 0x56, 0x39, + 0x4a, 0x66, 0x2e, 0xf1, 0x1c, 0x82, 0x14, 0xe8, 0xad, 0xa8, 0x5d, 0xf1, + 0xb1, 0x7b, 0x0b, 0x97, 0x41, 0x4c, 0xdd, 0x66, 0x2d, 0x18, 0x8b, 0x5d +}; +static const uint8_t nist_kas_ecc_cdh_testvector_365_private[] = { +/* dIUT */ + 0x02, 0xab, 0x2d, 0x43, 0x02, 0x7b, 0x08, 0xf8, 0xab, 0xfa, 0x35, 0x98, + 0xef, 0x01, 0x44, 0x39, 0x9a, 0x60, 0xb6, 0x03, 0x7b, 0x17, 0xa3, 0xae, + 0x41, 0x3d, 0x42, 0x2e, 0xfa, 0x21, 0x67, 0xe9, 0xea, 0x4f, 0x19, 0xd7, + 0xec, 0xa9, 0x8d, 0x85, 0xc6, 0x7c, 0x1f, 0xe8, 0x5f, 0xbc, 0xbc, 0x1f, + 0x12, 0xba, 0xfa, 0x30, 0xa8, 0x5d, 0xbd, 0xf5, 0x42, 0x46, 0x68, 0x89, + 0x31, 0x5f, 0x15, 0x32, 0xde, 0xfc, 0x5d, 0x18, 0x15, 0x09, 0xf0, 0x08 +}; +/* QIUTx = 0328c0d67fd552ea10e5bdf7b87d50bf4dcba34dca569aeb869c5c7dc7d832ce30feed32e25a723793f97c557e2f978c5e1349e69b73ef9916001ffb0d6cdb2c6343e34538386e6e */ +/* QIUTy = 01d151b46ed004263cd9a5c0d46a840d03222631f92ff9280e95a35746cdbcafd9fed6811c7614b9d50aa2828dc7a275b39d3d418a349dd1e2b73211f4de9a34b42fca11b9760eca */ +static const uint8_t nist_kas_ecc_cdh_testvector_365_out[] = { +/* ZIUT */ + 0x07, 0xc7, 0xeb, 0x48, 0x92, 0x81, 0x6c, 0xc3, 0x38, 0x8e, 0xbc, 0xdf, + 0xb4, 0x12, 0x98, 0x4e, 0x05, 0x91, 0x0c, 0x11, 0x2d, 0xd1, 0x5b, 0x8e, + 0x54, 0x81, 0x71, 0x94, 0x01, 0x70, 0x1a, 0xce, 0xba, 0x22, 0xfc, 0xf3, + 0x5a, 0xab, 0x0c, 0x3b, 0x04, 0x00, 0x96, 0x16, 0x10, 0x11, 0xf6, 0x17, + 0x70, 0x97, 0xc5, 0x05, 0x39, 0x5d, 0x9d, 0x6d, 0x8a, 0x71, 0x3f, 0x6a, + 0x51, 0x00, 0xfb, 0x47, 0x6a, 0xdb, 0xe7, 0xb9, 0xcd, 0xf4, 0xb6, 0x8b +}; +/* COUNT = 15 */ +static const uint8_t nist_kas_ecc_cdh_testvector_366_public_x[] = { +/* QCAVSx */ + 0x06, 0xcd, 0x79, 0x31, 0xfc, 0xf1, 0x93, 0x5f, 0x81, 0xf3, 0x01, 0x47, + 0x9e, 0xd9, 0xad, 0x0c, 0x6f, 0x9a, 0x05, 0xbe, 0xcf, 0x4e, 0x57, 0x3a, + 0x2f, 0xf4, 0x09, 0xba, 0xfc, 0x44, 0x2e, 0xc1, 0x95, 0xf7, 0xe3, 0xfd, + 0xfd, 0x08, 0xe5, 0x81, 0x61, 0xd4, 0xe0, 0xfd, 0x37, 0xf6, 0x2a, 0x96, + 0x94, 0x21, 0xb1, 0x9c, 0xd4, 0x8f, 0xe8, 0x48, 0xa5, 0xd7, 0xf7, 0x4b, + 0x81, 0x37, 0xa7, 0xc7, 0x26, 0xa9, 0xcb, 0xd3, 0x7a, 0x2c, 0xf3, 0xb4 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_366_public_y[] = { +/* QCAVSy */ + 0x04, 0xb5, 0xb2, 0xcd, 0x83, 0xb2, 0x78, 0x95, 0x75, 0x1c, 0x34, 0xd3, + 0xac, 0x5b, 0x96, 0x0a, 0x13, 0x3e, 0xc1, 0x8b, 0x03, 0x9c, 0x2e, 0x12, + 0x8d, 0x34, 0x41, 0xdb, 0x4f, 0x76, 0xe8, 0xb7, 0x50, 0x64, 0x09, 0x46, + 0x19, 0xb1, 0x22, 0xe5, 0xfb, 0x2f, 0x1c, 0x27, 0x96, 0x55, 0x9a, 0xd9, + 0x53, 0xc7, 0x11, 0xe3, 0x30, 0xdc, 0x7b, 0xf5, 0x5e, 0xdf, 0x29, 0xf0, + 0x95, 0xca, 0xe4, 0x55, 0x57, 0xb7, 0xc8, 0xd5, 0x84, 0x3d, 0x89, 0xbd +}; +static const uint8_t nist_kas_ecc_cdh_testvector_366_private[] = { +/* dIUT */ + 0x00, 0x49, 0xc6, 0xe4, 0xc0, 0x5a, 0x19, 0x7b, 0x24, 0xaf, 0xd2, 0x70, + 0x72, 0x43, 0xff, 0xbf, 0xd5, 0x5b, 0x00, 0x88, 0xfd, 0x33, 0xd8, 0x7d, + 0xae, 0x4d, 0x21, 0x04, 0x8f, 0x75, 0xf2, 0xb8, 0x62, 0x56, 0x30, 0x75, + 0x24, 0x1d, 0x2f, 0x36, 0xfd, 0xd0, 0xe9, 0x40, 0x5a, 0xb4, 0x2a, 0xa5, + 0x5c, 0xbf, 0x20, 0x95, 0xda, 0xbc, 0x3d, 0xae, 0xdf, 0xae, 0x9d, 0xeb, + 0x92, 0x22, 0x20, 0x78, 0x3e, 0x85, 0x91, 0xcf, 0xd6, 0x76, 0x00, 0xb1 +}; +/* QIUTx = 001fe29a4c2dd000bbed129121b88edbb5c39b34003f170ac19fa9a85c5fe587aab821361f4963440f25acb49758810552f06b719a9eb43b720e9b7ad6ef9d41248d5f335f99515a */ +/* QIUTy = 01499db95808c719d24eb05c633db8b05cf969ca0bf656435b1fdf1b0928290f6a6bf880adb9fd53c86ec76e0f62ce89cbeb4c266f64a876d778231a0030c38aa00d66c6bd680785 */ +static const uint8_t nist_kas_ecc_cdh_testvector_366_out[] = { +/* ZIUT */ + 0x05, 0xc6, 0x38, 0x34, 0x90, 0x00, 0xec, 0x30, 0x88, 0x1c, 0xd1, 0x90, + 0xc0, 0x67, 0xe7, 0xf1, 0x2b, 0x6b, 0x42, 0xd5, 0x84, 0x2a, 0x82, 0x85, + 0xa8, 0xff, 0x0d, 0xc7, 0xe9, 0xc9, 0xea, 0xf4, 0x83, 0x30, 0x9e, 0x48, + 0x31, 0x4f, 0xdc, 0x2c, 0xe7, 0xf9, 0xda, 0x6a, 0x46, 0x8e, 0x54, 0x9c, + 0x8e, 0x70, 0xa5, 0x0b, 0x68, 0xd0, 0x7a, 0xee, 0x29, 0x70, 0x8a, 0x98, + 0x17, 0x22, 0x09, 0xe5, 0xcd, 0x2e, 0x8c, 0x09, 0xcb, 0x66, 0xd9, 0x82 +}; +/* COUNT = 16 */ +static const uint8_t nist_kas_ecc_cdh_testvector_367_public_x[] = { +/* QCAVSx */ + 0x02, 0x98, 0x4b, 0x65, 0x30, 0x74, 0xc3, 0x6a, 0x25, 0x9a, 0xd9, 0x56, + 0xd5, 0x55, 0x65, 0x12, 0xc2, 0xc7, 0x31, 0xfa, 0x50, 0xf2, 0x00, 0x5d, + 0x00, 0x49, 0xa9, 0xd9, 0x77, 0xde, 0x5c, 0x00, 0xb7, 0xa0, 0x54, 0xc9, + 0x60, 0xcd, 0xd7, 0x07, 0x89, 0x63, 0x21, 0x49, 0x0b, 0xe4, 0x33, 0xbd, + 0x5e, 0xff, 0xd4, 0x4c, 0x56, 0x4e, 0xaa, 0x2d, 0x50, 0x21, 0x17, 0x50, + 0x50, 0xc5, 0xbf, 0xc1, 0x63, 0xcd, 0xb1, 0xe8, 0x1d, 0xf1, 0x33, 0x5a +}; +static const uint8_t nist_kas_ecc_cdh_testvector_367_public_y[] = { +/* QCAVSy */ + 0x01, 0xa7, 0x86, 0xd2, 0x90, 0x98, 0xb3, 0x34, 0xf5, 0xc1, 0xc4, 0xae, + 0x86, 0xa4, 0x1b, 0xf2, 0x75, 0xcc, 0x67, 0x87, 0xda, 0x72, 0x06, 0x91, + 0x65, 0x57, 0xa4, 0xf4, 0x33, 0x19, 0x21, 0x41, 0x03, 0x45, 0x67, 0xe0, + 0x41, 0xd5, 0x5d, 0x79, 0x4a, 0x77, 0x07, 0xc7, 0xaa, 0xf2, 0x88, 0x42, + 0xd5, 0xc8, 0xf5, 0x90, 0x37, 0x5a, 0x43, 0x65, 0x69, 0x18, 0xaa, 0x80, + 0xe5, 0x5b, 0x02, 0x85, 0x34, 0x7c, 0xce, 0x8f, 0xfe, 0x1f, 0x15, 0xe8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_367_private[] = { +/* dIUT */ + 0x01, 0x86, 0xb3, 0x1c, 0xe4, 0x90, 0xc7, 0xf2, 0x8f, 0x27, 0x93, 0x07, + 0x5a, 0x4a, 0xe6, 0x45, 0xac, 0xb3, 0x9e, 0x71, 0xff, 0xe9, 0x44, 0xee, + 0x62, 0xbf, 0x82, 0x58, 0x7f, 0x1c, 0x3c, 0xbe, 0x28, 0x8c, 0xe6, 0x02, + 0x4d, 0x8d, 0x03, 0x5f, 0x10, 0x7d, 0x9a, 0x4f, 0xae, 0xd5, 0x7a, 0x7b, + 0x21, 0xee, 0x1d, 0x6e, 0x71, 0x29, 0xa0, 0x98, 0x00, 0x4f, 0x22, 0xcc, + 0xd5, 0x27, 0x40, 0xc0, 0x34, 0xa6, 0xdf, 0x37, 0xb5, 0x3d, 0x07, 0x32 +}; +/* QIUTx = 06b15f1a859e3d80924611b20c1b94dff6bd0574fef81937f1e54d148d2d31f8c21b0ea9ce031c9455706f085a69fd492418558c7de9aadc2c9a996e7ed1feda329c7d7609bb6b22 */ +/* QIUTy = 032910544cb136e2c29aa33572aa6c3471a52ebca6b228bee749fa9ffe29296a4a5b6aa0c6dc9f095216e7b1513d81cba00794a3f558f74a1b541c73b2308f4f8e74028b5c2bcdf3 */ +static const uint8_t nist_kas_ecc_cdh_testvector_367_out[] = { +/* ZIUT */ + 0x00, 0x7a, 0x40, 0xa5, 0x9b, 0x66, 0x32, 0x15, 0x6a, 0x43, 0x15, 0x85, + 0x65, 0xa4, 0xee, 0xaf, 0x80, 0x61, 0x8e, 0x50, 0x1c, 0x5a, 0xc5, 0xaf, + 0xda, 0xb4, 0xce, 0x3c, 0xb7, 0x6a, 0xc9, 0x9a, 0x0b, 0xcd, 0x17, 0xe9, + 0xee, 0xc5, 0x49, 0x37, 0x3a, 0xce, 0x8c, 0x96, 0xaa, 0xc7, 0x8e, 0x2a, + 0xf6, 0x60, 0x04, 0x83, 0xa2, 0xc4, 0x9e, 0xc8, 0x12, 0x98, 0xa0, 0x83, + 0xd5, 0x23, 0x71, 0x18, 0xde, 0x96, 0xa9, 0x53, 0x99, 0x9b, 0xeb, 0x26 +}; +/* COUNT = 17 */ +static const uint8_t nist_kas_ecc_cdh_testvector_368_public_x[] = { +/* QCAVSx */ + 0x01, 0xa8, 0x68, 0x2e, 0x09, 0xec, 0xcd, 0x18, 0x68, 0xda, 0x20, 0x29, + 0x16, 0xa5, 0x61, 0xee, 0x85, 0x13, 0xc0, 0xd7, 0x34, 0x70, 0xcd, 0x34, + 0x1a, 0xee, 0x79, 0xed, 0x93, 0x55, 0x6a, 0x3a, 0x6e, 0x7c, 0x7b, 0x20, + 0x30, 0x2e, 0xc7, 0x4a, 0x0c, 0x51, 0x70, 0xa8, 0xe3, 0x7d, 0x78, 0xa9, + 0xb5, 0xd0, 0xde, 0x39, 0x00, 0xeb, 0x2a, 0x66, 0x3a, 0x72, 0x47, 0xcf, + 0x79, 0x43, 0xfd, 0x38, 0x1d, 0x95, 0xb3, 0xaa, 0xfd, 0x15, 0x61, 0x67 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_368_public_y[] = { +/* QCAVSy */ + 0x05, 0x2f, 0xec, 0xc6, 0x8f, 0x76, 0x95, 0xd4, 0xe4, 0x1a, 0x08, 0x0c, + 0x47, 0x65, 0x0d, 0x20, 0x28, 0x74, 0xda, 0x16, 0x3a, 0x17, 0x48, 0xe5, + 0x50, 0x37, 0x39, 0x58, 0xe3, 0x1b, 0xd0, 0xaa, 0xe5, 0x20, 0x99, 0x6d, + 0x30, 0xf3, 0x84, 0x73, 0x0f, 0x48, 0x54, 0xf5, 0xe5, 0x4e, 0x68, 0xcc, + 0x24, 0x95, 0x8a, 0xdc, 0x52, 0xe2, 0xa4, 0xc4, 0x07, 0x35, 0x65, 0x14, + 0xf3, 0xea, 0x71, 0x66, 0x05, 0x6d, 0xc6, 0x7e, 0x4d, 0x11, 0x8f, 0xa8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_368_private[] = { +/* dIUT */ + 0x03, 0x41, 0xf8, 0xe8, 0x61, 0x82, 0xde, 0x4f, 0xc3, 0xf4, 0x38, 0x57, + 0x25, 0x0a, 0x92, 0x9a, 0x41, 0x99, 0x4d, 0x33, 0x1d, 0xa1, 0x54, 0xc0, + 0x24, 0x9f, 0xa0, 0xd1, 0xc2, 0x6a, 0x6d, 0xe0, 0xe8, 0x35, 0xfa, 0x08, + 0xa8, 0xcc, 0x52, 0x4e, 0x3d, 0xac, 0x28, 0x63, 0x83, 0xf9, 0x0b, 0xd2, + 0xf4, 0xd2, 0xc7, 0x51, 0x42, 0xf1, 0xd3, 0x81, 0x08, 0xd9, 0xc0, 0x62, + 0x14, 0x3c, 0x8e, 0x6e, 0xdb, 0xbd, 0xa0, 0xaf, 0x87, 0xa7, 0x6a, 0xd5 +}; +/* QIUTx = 02c5c5eb7327402672573c37b492890343ab422b51bc65b600766ec1d07908ff03bcfde7694d832bcde52946339df0aab4074ae07a89f821f5a1130d2b73db0c423ae7a023ae2c18 */ +/* QIUTy = 0476ed3dbd936d1c36987a43512c8f0562e316122d05a7edd4e4248984c11f6eb85215d5aaa0262a95f20666c9dbf45248ae177d2dfffa3a6a950533298b5c3f4a1b62da1eafcd51 */ +static const uint8_t nist_kas_ecc_cdh_testvector_368_out[] = { +/* ZIUT */ + 0x02, 0x1f, 0xd2, 0x72, 0x69, 0x73, 0x40, 0x5f, 0xc3, 0x0d, 0x2a, 0x1f, + 0x21, 0x15, 0x90, 0x7c, 0xbd, 0x0d, 0xe9, 0x0b, 0xb6, 0xbc, 0xb0, 0x49, + 0x64, 0x52, 0xe3, 0x89, 0xb1, 0xb1, 0x0c, 0xcf, 0x38, 0xe2, 0x40, 0x06, + 0x17, 0x04, 0x0c, 0xf0, 0xdb, 0xb1, 0x88, 0xf3, 0x45, 0x33, 0x76, 0x78, + 0xb0, 0xad, 0x86, 0x03, 0xdc, 0xfe, 0x92, 0x65, 0x82, 0xd4, 0x32, 0x1f, + 0x38, 0x4d, 0xae, 0xc0, 0x94, 0x3e, 0x2c, 0xd2, 0x67, 0xf4, 0x83, 0x43 +}; +/* COUNT = 18 */ +static const uint8_t nist_kas_ecc_cdh_testvector_369_public_x[] = { +/* QCAVSx */ + 0x02, 0xcd, 0xaf, 0x13, 0x9a, 0x0c, 0xda, 0x28, 0x00, 0xd6, 0x11, 0x28, + 0xff, 0xe4, 0xd7, 0x32, 0x3b, 0x34, 0xa0, 0xfc, 0xf4, 0x8c, 0x94, 0x00, + 0x47, 0x9f, 0xf4, 0xc8, 0x29, 0x1c, 0xbf, 0x46, 0xf1, 0x6c, 0x41, 0xe4, + 0x40, 0x9a, 0xae, 0xdf, 0x14, 0xbc, 0x60, 0xa6, 0x42, 0xb2, 0xd7, 0xba, + 0xac, 0xde, 0x8e, 0x00, 0x51, 0xdd, 0x8a, 0xe0, 0x1b, 0xf5, 0xad, 0x2e, + 0x6e, 0x64, 0x90, 0xc7, 0x7c, 0xd4, 0x06, 0xa9, 0x99, 0xc5, 0x65, 0xe6 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_369_public_y[] = { +/* QCAVSy */ + 0x07, 0x8e, 0xdd, 0x29, 0xdb, 0x6a, 0x3b, 0x87, 0xa1, 0x15, 0x05, 0xb5, + 0x7c, 0x54, 0x3f, 0xfb, 0x74, 0x6a, 0x5b, 0x40, 0xfb, 0x83, 0xd7, 0x20, + 0x61, 0x80, 0xf3, 0xae, 0x9f, 0xcb, 0x22, 0x2c, 0x54, 0x11, 0xa7, 0x74, + 0x76, 0x66, 0x0c, 0x7b, 0x31, 0x1b, 0x64, 0x63, 0x10, 0x90, 0x58, 0x89, + 0xa9, 0x5a, 0x0f, 0x2f, 0xdc, 0x35, 0xd3, 0x0f, 0xc6, 0x1c, 0xc5, 0x56, + 0x0a, 0x29, 0x14, 0x23, 0x2d, 0x62, 0xad, 0x36, 0x38, 0x6b, 0x91, 0x79 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_369_private[] = { +/* dIUT */ + 0x02, 0x07, 0xa7, 0x38, 0x2d, 0x8a, 0x22, 0x57, 0x12, 0x26, 0xe0, 0xc0, + 0x6c, 0x26, 0x81, 0xd0, 0x9b, 0xca, 0x19, 0xb5, 0xdb, 0x7e, 0x7b, 0xbf, + 0xc1, 0x3a, 0xc2, 0x08, 0x38, 0x9d, 0xf8, 0x16, 0x8d, 0x77, 0x61, 0x5e, + 0x30, 0xca, 0x86, 0x10, 0x39, 0x36, 0xe5, 0x3d, 0xd9, 0xaf, 0x01, 0xcd, + 0xfe, 0x24, 0xf5, 0x08, 0xec, 0x60, 0x93, 0x99, 0x77, 0x5c, 0xe8, 0x4c, + 0x86, 0x89, 0xf8, 0xd5, 0xf9, 0x6f, 0x65, 0x2e, 0x01, 0x4e, 0x0d, 0xe8 +}; +/* QIUTx = 04608dc0512bc55c734cd562ac5825f7ca38b793f8ece9b981cc1c4032ddd8039164d0c646b42b2fd453b5a1d3a74ae23c32c7d584007de3cd34e33121b90fab3ada6621b3ac9785 */ +/* QIUTy = 06aa9ffbfd65c509370846707674ac723dac24a6f33a1e0bbcdf8b24ba32cf7bdec8fdc9233b757bc073d64dedf484c6fa01ef28e874fb0d34f58b0e32b18645c30bdcb516ee3841 */ +static const uint8_t nist_kas_ecc_cdh_testvector_369_out[] = { +/* ZIUT */ + 0x07, 0xa4, 0x7b, 0xdc, 0x7d, 0x54, 0xec, 0xd3, 0x91, 0x67, 0x2f, 0x13, + 0x1b, 0x32, 0x14, 0xd0, 0xef, 0xc4, 0xd4, 0x01, 0x95, 0xdb, 0x1e, 0xc9, + 0x93, 0xa6, 0x2f, 0xe9, 0xda, 0x87, 0x5e, 0xff, 0xf5, 0x40, 0x3b, 0xd7, + 0x08, 0xfa, 0x49, 0x1a, 0x01, 0xa9, 0x4f, 0x4b, 0xdd, 0xc7, 0xd5, 0x16, + 0xba, 0xff, 0xff, 0x9f, 0xbd, 0xd2, 0x13, 0xca, 0x1a, 0x49, 0x05, 0xf9, + 0xaa, 0x67, 0x9d, 0x65, 0xda, 0x25, 0xc0, 0xf1, 0xfd, 0x2a, 0xfb, 0x0a +}; +/* COUNT = 19 */ +static const uint8_t nist_kas_ecc_cdh_testvector_370_public_x[] = { +/* QCAVSx */ + 0x00, 0x05, 0x15, 0x12, 0xe4, 0xa0, 0xdb, 0xc5, 0x35, 0xc9, 0x7b, 0xe1, + 0x0f, 0xfa, 0x74, 0x25, 0x75, 0x83, 0x82, 0x88, 0x30, 0x40, 0x46, 0x66, + 0x01, 0xd5, 0x39, 0x1b, 0xcb, 0x35, 0x82, 0xc1, 0x15, 0x25, 0x29, 0x32, + 0x49, 0xf2, 0x44, 0x97, 0xcc, 0x80, 0x72, 0x16, 0xb3, 0x4c, 0x92, 0xc1, + 0xe0, 0x75, 0x78, 0x1c, 0x83, 0x91, 0xc3, 0xf6, 0xd3, 0xd1, 0x4f, 0x88, + 0xa1, 0xd5, 0x0e, 0xa9, 0xfc, 0x75, 0xff, 0x8d, 0x51, 0xcc, 0xf9, 0x33 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_370_public_y[] = { +/* QCAVSy */ + 0x03, 0x9d, 0xa4, 0x6c, 0xac, 0x86, 0x6a, 0xb3, 0x47, 0x61, 0x7a, 0xc5, + 0xa8, 0xb4, 0xf1, 0x65, 0x70, 0x34, 0xe3, 0xb8, 0xdd, 0xb6, 0x6b, 0xc4, + 0x27, 0x3e, 0x2e, 0x1c, 0xe0, 0x16, 0x41, 0xec, 0xe6, 0x36, 0x97, 0x9d, + 0xe8, 0xb2, 0x49, 0x2d, 0xc6, 0x9e, 0x88, 0x53, 0x7c, 0x36, 0xb1, 0xc3, + 0xad, 0x0d, 0x35, 0x22, 0x7f, 0x86, 0x7e, 0x43, 0xdf, 0x9c, 0x89, 0x17, + 0xdc, 0xe9, 0xf8, 0xc1, 0xef, 0x3b, 0xa3, 0xcb, 0x5c, 0xa8, 0xba, 0x52 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_370_private[] = { +/* dIUT */ + 0x00, 0x6b, 0xa8, 0xf1, 0x2c, 0xc6, 0xe0, 0xe7, 0x8d, 0xf8, 0xcc, 0x62, + 0x98, 0x84, 0x8a, 0x74, 0x00, 0x25, 0xe7, 0x2c, 0x62, 0xd0, 0x99, 0xe9, + 0x25, 0x84, 0xac, 0x76, 0xf5, 0x95, 0xac, 0x1f, 0xc7, 0x24, 0xcb, 0x06, + 0xa8, 0x5a, 0x07, 0xf0, 0xd4, 0x44, 0x0f, 0xaf, 0x3d, 0xde, 0xa2, 0xf2, + 0x65, 0xf2, 0x01, 0x5d, 0xd0, 0x59, 0xa1, 0x6a, 0x03, 0xa2, 0x99, 0x15, + 0xb8, 0x73, 0x1d, 0x60, 0x45, 0x12, 0xce, 0xef, 0x22, 0xb8, 0x41, 0xf3 +}; +/* QIUTx = 0636f435e80600666108737300773a8ed6ffa8ebf8307c81ff5f44353e91bad086331b8feff3f1cdb86e061bde5f71c5fb938f117e2226a97d2b66b098e9ff525182c816e702c6a9 */ +/* QIUTy = 01c1bd8afae6a94108fc2c755d5de3fa2a4b3471fc2a5cdf4adda68529bf180ff28db154ab4311247b392e93a335bbe8796608bbd6013f43cdcc846ec22267423c3cfda2ce8a3d96 */ +static const uint8_t nist_kas_ecc_cdh_testvector_370_out[] = { +/* ZIUT */ + 0x07, 0x32, 0x61, 0x96, 0xa7, 0xde, 0xcc, 0x92, 0xc8, 0x1a, 0xe5, 0xa0, + 0x77, 0x9c, 0x9a, 0x42, 0xf5, 0x3d, 0x94, 0xcf, 0xa4, 0xc3, 0xa1, 0x3f, + 0x19, 0xdb, 0xb5, 0x54, 0x13, 0x8e, 0x0e, 0x86, 0x4e, 0xee, 0x6b, 0xc9, + 0x3e, 0x39, 0x21, 0x4e, 0x2f, 0x74, 0x70, 0x5a, 0x4b, 0x17, 0x2a, 0xab, + 0x51, 0x04, 0x44, 0xc9, 0x3b, 0x5b, 0x3e, 0x62, 0x51, 0x7b, 0xbb, 0x72, + 0x79, 0x33, 0x71, 0x02, 0xdb, 0x1c, 0x61, 0xde, 0x34, 0x9d, 0x97, 0x47 +}; +/* COUNT = 20 */ +static const uint8_t nist_kas_ecc_cdh_testvector_371_public_x[] = { +/* QCAVSx */ + 0x00, 0x4c, 0x2d, 0xe5, 0x64, 0x24, 0x31, 0xbc, 0xc6, 0xeb, 0x82, 0xef, + 0xd4, 0x35, 0x55, 0x40, 0xa8, 0xb5, 0xd2, 0x3b, 0x12, 0xb0, 0xdf, 0x7d, + 0x31, 0xad, 0x69, 0x42, 0x5b, 0x94, 0x54, 0x98, 0x77, 0x44, 0x3e, 0xe8, + 0xdd, 0x7c, 0x09, 0xcf, 0xbb, 0xed, 0x86, 0xf1, 0x36, 0x65, 0x93, 0x1d, + 0x4b, 0x2a, 0x21, 0x75, 0x9c, 0x33, 0xe1, 0x0b, 0x4a, 0xcf, 0xc6, 0x3b, + 0xa1, 0xef, 0x61, 0xac, 0xaa, 0xa1, 0x8c, 0x94, 0xe3, 0xcf, 0xc9, 0x33 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_371_public_y[] = { +/* QCAVSy */ + 0x01, 0x76, 0x5b, 0x7a, 0x37, 0xeb, 0x80, 0x6d, 0x43, 0x19, 0x6d, 0x29, + 0x31, 0xda, 0x1a, 0x19, 0x53, 0x74, 0x2d, 0x3e, 0x0d, 0xa7, 0xcc, 0xb6, + 0x7e, 0x0d, 0xfd, 0xba, 0x5e, 0x03, 0x49, 0x14, 0xcc, 0xe3, 0xee, 0x63, + 0x93, 0xbf, 0xde, 0x40, 0x67, 0x0f, 0x40, 0x61, 0x96, 0x06, 0x7d, 0xa8, + 0xb2, 0x93, 0xc6, 0x84, 0x35, 0x93, 0xdd, 0x22, 0x1c, 0x89, 0xbf, 0x97, + 0x96, 0x36, 0x76, 0xbd, 0x04, 0x4e, 0x8c, 0x8a, 0xb8, 0xe7, 0x17, 0xad +}; +static const uint8_t nist_kas_ecc_cdh_testvector_371_private[] = { +/* dIUT */ + 0x01, 0x07, 0x16, 0xf2, 0xe7, 0x74, 0xf2, 0x7f, 0x42, 0xde, 0x3f, 0x6c, + 0x96, 0x94, 0xd8, 0xec, 0xa2, 0x17, 0x98, 0x23, 0x09, 0x1d, 0x20, 0x2f, + 0x2b, 0xa1, 0x62, 0x91, 0x93, 0xa1, 0xc9, 0x87, 0x00, 0x69, 0x33, 0x98, + 0xff, 0xc8, 0x31, 0x57, 0xf7, 0xce, 0x48, 0x58, 0xe7, 0x53, 0x5e, 0x39, + 0x90, 0xd2, 0x19, 0xbc, 0x24, 0x9d, 0xe1, 0x64, 0x55, 0x8c, 0xac, 0x80, + 0x7e, 0xe1, 0x59, 0x77, 0x8a, 0x01, 0x2d, 0xa1, 0x9e, 0x50, 0x12, 0xbf +}; +/* QIUTx = 0150b3adde162a7f09350dacf460419fe86b99dcd94f44283fba3e43d281b93bb54282812ce52265a94838968d67a9d6ecdc1b6cb64cf1594521c4749ea43d8e4ec045e645ff238b */ +/* QIUTy = 07b43321b6118b87c46c7b52288df5dd1cf7da6183ece5633b4c17cae362d821191f7d57923928339aadf7d85f7f19de9486709e4d2ddef42c55bb4d76a3cb50cad2a098ead5952a */ +static const uint8_t nist_kas_ecc_cdh_testvector_371_out[] = { +/* ZIUT */ + 0x05, 0x90, 0x52, 0xd3, 0xe1, 0xc6, 0x6e, 0xfa, 0x4b, 0x7d, 0xd3, 0x9e, + 0x74, 0x29, 0x9e, 0x88, 0x63, 0x67, 0xd8, 0xfe, 0x49, 0xd7, 0xca, 0xb9, + 0x0e, 0x4f, 0x05, 0x1b, 0xec, 0x10, 0x31, 0x64, 0x38, 0xfb, 0x29, 0xb1, + 0x29, 0x0d, 0xfd, 0xae, 0xc1, 0x69, 0xde, 0xcd, 0x62, 0x2a, 0x10, 0x10, + 0xcf, 0x0a, 0x02, 0x75, 0x00, 0x88, 0x14, 0xf4, 0x86, 0x1b, 0x4d, 0x83, + 0xba, 0x78, 0x51, 0x5a, 0x87, 0x68, 0xd9, 0x78, 0xbe, 0x43, 0x00, 0x11 +}; +/* COUNT = 21 */ +static const uint8_t nist_kas_ecc_cdh_testvector_372_public_x[] = { +/* QCAVSx */ + 0x02, 0x50, 0x38, 0xa0, 0xe7, 0x2a, 0xe8, 0xc1, 0x6e, 0x36, 0xe3, 0xe3, + 0xb5, 0x04, 0xed, 0x73, 0x41, 0xef, 0x70, 0x9b, 0x9f, 0xec, 0x8b, 0xe9, + 0x01, 0x77, 0x34, 0x6d, 0x76, 0xca, 0x7b, 0xc7, 0x13, 0x3d, 0x0e, 0xc2, + 0x80, 0xac, 0xf0, 0x66, 0x00, 0x5c, 0x5c, 0xc1, 0x0b, 0x52, 0xaa, 0x65, + 0x43, 0x35, 0xfe, 0x82, 0x0a, 0x66, 0x17, 0xe5, 0x60, 0xe2, 0x70, 0x90, + 0x3f, 0xf1, 0xc2, 0xcc, 0x8a, 0xf1, 0x39, 0x8f, 0x24, 0xdf, 0xe2, 0xb0 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_372_public_y[] = { +/* QCAVSy */ + 0x03, 0x10, 0x74, 0xca, 0x39, 0x31, 0x80, 0x1a, 0x6a, 0xcb, 0x76, 0x5b, + 0x6e, 0x91, 0x44, 0x17, 0x2e, 0xd8, 0x1d, 0x99, 0x9e, 0xd9, 0xe8, 0x35, + 0xbd, 0x35, 0x52, 0x6b, 0x03, 0xef, 0x2a, 0x13, 0xf7, 0x83, 0x76, 0x03, + 0x2b, 0x0e, 0xb8, 0x14, 0x6c, 0x23, 0x13, 0x23, 0x65, 0xfc, 0xe1, 0x76, + 0xa7, 0xcb, 0xdc, 0xa4, 0x4b, 0x35, 0xaa, 0x37, 0x98, 0x59, 0xf6, 0x88, + 0xac, 0x26, 0xdc, 0x64, 0xc8, 0x14, 0x9a, 0x43, 0x22, 0xd0, 0x83, 0xd1 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_372_private[] = { +/* dIUT */ + 0x01, 0xd0, 0x10, 0x3f, 0xc7, 0x94, 0x8a, 0xf1, 0x07, 0xe5, 0x1f, 0x4d, + 0x2c, 0xc0, 0x39, 0x2b, 0x66, 0x80, 0x80, 0x59, 0xd1, 0xf2, 0x6c, 0xba, + 0x05, 0xbe, 0x6a, 0x38, 0x1f, 0x52, 0x2d, 0x4c, 0xb8, 0x54, 0x13, 0x79, + 0x34, 0xac, 0xcd, 0x1c, 0xea, 0x33, 0x60, 0x94, 0x8e, 0x40, 0x6d, 0x31, + 0x08, 0xc9, 0x43, 0x76, 0x9d, 0xc7, 0x00, 0xb4, 0xc9, 0xcc, 0x0c, 0xc1, + 0xd8, 0x4b, 0xab, 0x58, 0xa3, 0x5e, 0x27, 0xeb, 0x24, 0x04, 0x75, 0xf0 +}; +/* QIUTx = 012bda8ded3ed7e8b6d39b5855a58d725b65e3857c2a674996eb393a3e3f91595bbfa87253a56ebac2b10ed406af9dbff53b22265fbeb5a769cace2b60b45dbf97ceed2b0a04db50 */ +/* QIUTy = 026454827efe29b324ae3f2d4c0dca3a3a95491511c531645acf545b45ef6ac4a50c09d3d21f213ca76b96fb18242ecbe08af68755de4e1077173475826eaabed26a75c369cd7b0f */ +static const uint8_t nist_kas_ecc_cdh_testvector_372_out[] = { +/* ZIUT */ + 0x03, 0xac, 0xfa, 0x4b, 0x3d, 0x1c, 0x2a, 0x6b, 0x62, 0xaf, 0x23, 0xbd, + 0xff, 0x6a, 0x21, 0x5a, 0x41, 0x6d, 0x44, 0x37, 0xce, 0x6c, 0xc1, 0x14, + 0xd1, 0x7d, 0xc4, 0x20, 0x11, 0x95, 0x98, 0x7a, 0x5d, 0x73, 0x01, 0xda, + 0x11, 0xb9, 0x13, 0x25, 0x47, 0x02, 0xd7, 0x17, 0x2e, 0x31, 0xd6, 0x4e, + 0x59, 0xb2, 0x4d, 0xea, 0xa3, 0x27, 0x0f, 0x20, 0x44, 0x5e, 0x51, 0xdc, + 0x48, 0x4f, 0x7a, 0x2b, 0x8c, 0x3c, 0xbe, 0xb0, 0xbb, 0x9e, 0xfb, 0x28 +}; +/* COUNT = 22 */ +static const uint8_t nist_kas_ecc_cdh_testvector_373_public_x[] = { +/* QCAVSx */ + 0x01, 0xbd, 0xff, 0xfd, 0x69, 0xc2, 0xe0, 0x8f, 0xb0, 0x3c, 0x85, 0x3e, + 0xf2, 0xeb, 0xd0, 0x88, 0xe6, 0x8d, 0x23, 0x3f, 0xdb, 0x95, 0xf0, 0xb2, + 0x46, 0xde, 0x79, 0x55, 0xd6, 0x15, 0x07, 0x7d, 0xfd, 0x0b, 0x0f, 0xf0, + 0x2c, 0x64, 0xd0, 0x1d, 0xe7, 0x93, 0x35, 0x90, 0x96, 0xb8, 0x5e, 0x05, + 0x7b, 0x1b, 0x7f, 0x9f, 0x59, 0x26, 0x2d, 0xc2, 0x75, 0x7f, 0x18, 0x24, + 0x3e, 0x18, 0x2e, 0x1a, 0x0b, 0xfe, 0x9d, 0xcb, 0xb0, 0x27, 0xd6, 0x8b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_373_public_y[] = { +/* QCAVSy */ + 0x02, 0x18, 0xbe, 0x7d, 0x95, 0x60, 0x29, 0xf1, 0x39, 0xc1, 0x9d, 0x2d, + 0xa3, 0x46, 0x77, 0x3b, 0x16, 0xd7, 0xaf, 0xc8, 0x58, 0xab, 0x8d, 0xcb, + 0x60, 0xd7, 0xe4, 0x84, 0xae, 0xce, 0xc3, 0x09, 0xcb, 0x3f, 0xea, 0x96, + 0xaf, 0x39, 0x03, 0x63, 0x7e, 0x5d, 0xb4, 0xdb, 0x67, 0x8b, 0xb5, 0xdb, + 0x9b, 0x0b, 0x18, 0xd8, 0x3c, 0xf9, 0xeb, 0xc1, 0xb1, 0xaa, 0xf2, 0x4f, + 0x43, 0x67, 0xec, 0x53, 0x36, 0x84, 0xce, 0x9d, 0x56, 0x58, 0x2d, 0x43 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_373_private[] = { +/* dIUT */ + 0x03, 0x2d, 0x2f, 0x55, 0x7f, 0xe4, 0x7b, 0x8d, 0x28, 0x0f, 0x68, 0x2e, + 0x24, 0xfd, 0xa6, 0x27, 0xdd, 0x7a, 0x58, 0xe9, 0xb0, 0x08, 0x22, 0xa3, + 0xaa, 0xf6, 0xeb, 0x7a, 0x01, 0x4f, 0x47, 0x6c, 0x17, 0x94, 0x1a, 0xdc, + 0x5e, 0x22, 0x38, 0xa3, 0x08, 0x0d, 0x70, 0x6f, 0x1e, 0x16, 0xa4, 0x51, + 0xb7, 0xe9, 0x29, 0x42, 0x77, 0x99, 0x30, 0xc5, 0x67, 0x0a, 0x47, 0x32, + 0x81, 0xca, 0xc7, 0x8b, 0x85, 0x8d, 0x1f, 0x1c, 0xc9, 0x9b, 0x0a, 0xff +}; +/* QIUTx = 040f3130e74b1c8eb265e7c4e6921411eb971418267e8dea879c2e8b563864f23a61b23422c9a06fa178a8a155e3e78457597587f3e35b79f19d0c2e185aef46db95819cbe127b10 */ +/* QIUTy = 01c91d27c2ae7113eb03be98e94d3ad6dec791fac2fe0d2c8c98b71371b058a649fa9c3fa3ccdbba932395c27affa20d95ac041bc9978e3f530829a2c64c89b1bcceac06854fb903 */ +static const uint8_t nist_kas_ecc_cdh_testvector_373_out[] = { +/* ZIUT */ + 0x06, 0x7a, 0x58, 0xe5, 0xb3, 0x28, 0x7b, 0xb9, 0xaa, 0x83, 0xed, 0x9c, + 0xa2, 0xd7, 0x18, 0xcf, 0x71, 0x65, 0xfb, 0x57, 0x4b, 0x6a, 0x44, 0x6c, + 0x30, 0x19, 0x84, 0x9c, 0xd1, 0x58, 0x46, 0x73, 0xd5, 0x61, 0xb5, 0x74, + 0xbc, 0x8f, 0x68, 0x41, 0x94, 0x37, 0xc5, 0xe8, 0x11, 0x3e, 0x06, 0x08, + 0x47, 0xca, 0xd3, 0xb5, 0xdd, 0xc2, 0xf6, 0x7a, 0xd7, 0x5b, 0xc1, 0xe3, + 0xf0, 0x45, 0x54, 0xe6, 0x3a, 0x5e, 0x49, 0x45, 0xcf, 0xcb, 0x65, 0xf5 +}; +/* COUNT = 23 */ +static const uint8_t nist_kas_ecc_cdh_testvector_374_public_x[] = { +/* QCAVSx */ + 0x00, 0x8f, 0xc3, 0xb4, 0x14, 0xf3, 0x41, 0x2b, 0x40, 0x3f, 0x01, 0xc2, + 0x53, 0xbd, 0x22, 0x26, 0x15, 0x02, 0x25, 0xdd, 0xaa, 0xb3, 0x4d, 0x20, + 0x10, 0x89, 0xf4, 0x9d, 0x79, 0xe5, 0xdc, 0xc2, 0xe3, 0xb6, 0x82, 0x16, + 0xfa, 0xa6, 0x6d, 0xac, 0x44, 0x52, 0x9c, 0x7f, 0xe3, 0xba, 0x4d, 0x28, + 0xd8, 0x15, 0xb0, 0x88, 0x23, 0x59, 0x55, 0x71, 0x3b, 0xb7, 0x72, 0x13, + 0x83, 0x53, 0x3b, 0x5d, 0x94, 0x22, 0x1b, 0x4e, 0xd1, 0xe1, 0x62, 0xb8 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_374_public_y[] = { +/* QCAVSy */ + 0x02, 0xb3, 0x22, 0x01, 0xde, 0x27, 0x2b, 0x1b, 0x32, 0xb6, 0xa6, 0xa5, + 0x8e, 0xa2, 0x24, 0x11, 0xc4, 0x8f, 0x5d, 0xc5, 0xcf, 0x0f, 0x95, 0x87, + 0x2e, 0x67, 0x51, 0xed, 0x62, 0x2c, 0xee, 0xce, 0xa2, 0x2a, 0x55, 0x69, + 0x75, 0xde, 0x60, 0x03, 0x86, 0x9a, 0xe2, 0x0a, 0xf3, 0x9b, 0x42, 0xba, + 0x88, 0x71, 0x78, 0x9c, 0x82, 0xe8, 0xf3, 0xad, 0x3c, 0xf6, 0x00, 0x6f, + 0x43, 0xbc, 0x4c, 0x7d, 0x41, 0x02, 0x03, 0x2c, 0x43, 0xf8, 0xf7, 0x97 +}; +static const uint8_t nist_kas_ecc_cdh_testvector_374_private[] = { +/* dIUT */ + 0x03, 0xee, 0xe2, 0x91, 0x96, 0xa8, 0xbe, 0x70, 0xeb, 0x3a, 0x31, 0x04, + 0x64, 0x05, 0x9c, 0xc0, 0xc4, 0xc4, 0x2f, 0x13, 0x48, 0x7a, 0xb1, 0xa0, + 0x76, 0x2c, 0x2c, 0xbe, 0x30, 0x4e, 0xbe, 0x63, 0x50, 0x3e, 0x6c, 0x70, + 0x68, 0xa7, 0xf4, 0xbc, 0x19, 0x7f, 0x81, 0xf6, 0x5b, 0x42, 0x95, 0xc1, + 0x4b, 0x21, 0x0f, 0x3c, 0xb2, 0x37, 0x8b, 0x67, 0x40, 0x1f, 0xcf, 0x52, + 0xbe, 0xc0, 0x2c, 0x13, 0xb6, 0x1b, 0x6d, 0xe1, 0x4e, 0x1b, 0x7e, 0x5b +}; +/* QIUTx = 0177acc5fe9f42f4de2d27ab9bf6f7e0eace303c266ff8b3469082aba9367e66440bd6b1bd8b6e1aec92b65e35aea8f007f09d4cd67eea5d6000736cabbb9dccc943ebb5656a0586 */ +/* QIUTy = 0716f1898e2a8c27319de7a2698f21d5de58a4b8b8dd02b5e433110d3977fee8ec5c089d170af02a4ad3c1fab44b0d1e2a3beba9e0719cd8bf8364478d686c4e35f7457d24d021d6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_374_out[] = { +/* ZIUT */ + 0x06, 0xb2, 0x72, 0xca, 0x33, 0x30, 0xc0, 0xcd, 0xfb, 0xe6, 0x0a, 0x17, + 0x46, 0xbc, 0x0d, 0xde, 0xa6, 0x25, 0x75, 0x36, 0xcd, 0xd8, 0xe9, 0x76, + 0xf2, 0x51, 0x7e, 0xb5, 0x41, 0x46, 0x0a, 0x3f, 0x0e, 0x6e, 0xa7, 0xfe, + 0xc2, 0xb4, 0x95, 0xe0, 0xf5, 0x77, 0x12, 0xc8, 0xca, 0xc3, 0x5e, 0x8a, + 0x7d, 0x64, 0xd8, 0x76, 0xc2, 0x98, 0x51, 0xbb, 0xfe, 0xb6, 0xfe, 0x72, + 0x6d, 0x57, 0xe0, 0xbe, 0x43, 0xdc, 0x76, 0xa5, 0x84, 0xef, 0x9c, 0x93 +}; +/* COUNT = 24 */ +static const uint8_t nist_kas_ecc_cdh_testvector_375_public_x[] = { +/* QCAVSx */ + 0x05, 0x65, 0xa8, 0x29, 0x94, 0xd7, 0xe6, 0xf5, 0x3e, 0xeb, 0x6b, 0xf6, + 0x75, 0x23, 0xee, 0x68, 0x0f, 0xfb, 0x77, 0x01, 0x18, 0x67, 0x3c, 0x3e, + 0x15, 0xc3, 0x20, 0x0e, 0x6c, 0x8d, 0x1f, 0x26, 0xca, 0xba, 0xf0, 0x0c, + 0x1d, 0xa4, 0x8e, 0x63, 0x74, 0x31, 0x64, 0x97, 0xcb, 0xa5, 0xf1, 0x9f, + 0x17, 0x42, 0x0f, 0x26, 0x76, 0x33, 0xf4, 0x0e, 0x5b, 0x06, 0x36, 0x27, + 0x89, 0xbf, 0xf1, 0x1a, 0xdf, 0x59, 0x6d, 0x5b, 0x1c, 0xf7, 0x68, 0xef +}; +static const uint8_t nist_kas_ecc_cdh_testvector_375_public_y[] = { +/* QCAVSy */ + 0x01, 0x6b, 0x2d, 0x4d, 0xaa, 0xca, 0x9c, 0x6b, 0xed, 0x97, 0x6b, 0x20, + 0x64, 0xef, 0x54, 0x35, 0x2a, 0x58, 0xae, 0x34, 0x36, 0x78, 0x35, 0xa6, + 0x21, 0x0e, 0x15, 0x78, 0x29, 0x1c, 0x1d, 0xe8, 0xd6, 0x7c, 0x20, 0xbc, + 0x3d, 0x6f, 0xfa, 0x62, 0x0c, 0x87, 0xb3, 0x09, 0x8a, 0x2b, 0x9f, 0x3a, + 0xbb, 0x8d, 0x2c, 0xac, 0xd5, 0xb2, 0xee, 0x2b, 0x68, 0x39, 0x9e, 0xac, + 0x4e, 0x8f, 0x65, 0xce, 0xbd, 0xd6, 0x63, 0x00, 0xfd, 0x04, 0x9b, 0x5b +}; +static const uint8_t nist_kas_ecc_cdh_testvector_375_private[] = { +/* dIUT */ + 0x01, 0x69, 0xa2, 0xd8, 0x75, 0x86, 0x94, 0x4c, 0x31, 0x73, 0xbf, 0x9a, + 0x22, 0x75, 0xe3, 0x08, 0x00, 0x03, 0xdb, 0x64, 0x8c, 0x2d, 0x1e, 0x1c, + 0x56, 0xe2, 0xc3, 0x7c, 0xe0, 0xd7, 0xcd, 0x9f, 0x81, 0x8e, 0xa6, 0xb7, + 0xbb, 0xa3, 0x43, 0xf7, 0x74, 0xef, 0x0f, 0x33, 0x4e, 0xa5, 0xc1, 0x2e, + 0xf0, 0xbe, 0x75, 0x93, 0xd0, 0x4e, 0xd9, 0x45, 0x45, 0x8d, 0x71, 0xe1, + 0x71, 0x12, 0xeb, 0x01, 0xd9, 0x04, 0x1d, 0x21, 0x33, 0xb1, 0x34, 0x73 +}; +/* QIUTx = 051e521764265af7f01bcd9c3fd022dfdb2d4a2c58b3b23d2e550302c42aadd57d1df6fc18e465bd98442495eed22f3fd6700284c9fa7833b5165149b8e1a91e0e099a0a5732d5c2 */ +/* QIUTy = 0198e7e7d094e207528c583865d262a918fc2a39261e95c07dcbd044efd3981899078af3eb97398201a4650f0dccbf19f922c8dbc3839bf6be0053f84531c71843a9e6a102ab58d6 */ +static const uint8_t nist_kas_ecc_cdh_testvector_375_out[] = { +/* ZIUT */ + 0x02, 0xda, 0x26, 0x6a, 0x26, 0x9b, 0xdc, 0x8d, 0x8b, 0x2a, 0x0c, 0x6b, + 0xb5, 0x76, 0x2f, 0x10, 0x2f, 0xc8, 0x01, 0xc8, 0xd5, 0x39, 0x4a, 0x92, + 0x71, 0x53, 0x91, 0x36, 0xbd, 0x81, 0xd4, 0xb6, 0x9c, 0xfb, 0xb7, 0x52, + 0x5c, 0xd0, 0xa9, 0x83, 0xfb, 0x7f, 0x7e, 0x9d, 0xee, 0xc5, 0x83, 0xb8, + 0xf8, 0xe5, 0x74, 0xc6, 0x18, 0x4b, 0x2d, 0x79, 0x83, 0x1e, 0xc7, 0x70, + 0x64, 0x9e, 0x48, 0x4d, 0xc0, 0x06, 0xfa, 0x35, 0xb0, 0xbf, 0xfd, 0x0b +}; diff --git a/optee/optee_test/host/xtest/pkcs11_1000.c b/optee/optee_test/host/xtest/pkcs11_1000.c new file mode 100644 index 0000000..309d40f --- /dev/null +++ b/optee/optee_test/host/xtest/pkcs11_1000.c @@ -0,0 +1,8749 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include +#include +#include +#ifdef OPENSSL_FOUND +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "xtest_test.h" +#include "xtest_helpers.h" +#include "xtest_uuid_helpers.h" + +#include + +/* + * auth_type enumerates the types of user authentication + * + * PIN_AUTH Pin authentication. + * ACL_AUTH ACL authentication. + */ +enum auth_type { PIN_AUTH, ACL_AUTH }; + +/* + * Some PKCS#11 object resources used in the tests + */ +static const CK_BYTE cktest_aes128_key[16]; + +static const CK_BYTE cktest_aes128_iv[16]; + +static const CK_AES_CTR_PARAMS cktest_aes_ctr_params = { + .ulCounterBits = 1, +}; + +static CK_MECHANISM cktest_aes_ecb_mechanism = { + CKM_AES_ECB, + NULL, 0, +}; +static CK_MECHANISM cktest_aes_cbc_mechanism = { + CKM_AES_CBC, + (CK_BYTE_PTR)cktest_aes128_iv, sizeof(cktest_aes128_iv), +}; +static CK_MECHANISM cktest_aes_ctr_mechanism = { + CKM_AES_CTR, + (CK_BYTE_PTR)&cktest_aes_ctr_params, sizeof(cktest_aes_ctr_params), +}; +static CK_MECHANISM cktest_aes_cts_mechanism = { + CKM_AES_CTS, + (CK_BYTE_PTR)cktest_aes128_iv, sizeof(cktest_aes128_iv), +}; +static CK_MECHANISM cktest_aes_cmac_mechanism = { + CKM_AES_CMAC, NULL, 0, +}; +static CK_MECHANISM cktest_hmac_md5_mechanism = { + CKM_MD5_HMAC, NULL, 0, +}; +static CK_MECHANISM cktest_hmac_sha1_mechanism = { + CKM_SHA_1_HMAC, NULL, 0, +}; +static CK_MECHANISM cktest_hmac_sha224_mechanism = { + CKM_SHA224_HMAC, NULL, 0, +}; +static CK_MECHANISM cktest_hmac_sha256_mechanism = { + CKM_SHA256_HMAC, NULL, 0, +}; +static CK_MECHANISM cktest_hmac_sha384_mechanism = { + CKM_SHA384_HMAC, NULL, 0, +}; +static CK_MECHANISM cktest_hmac_sha512_mechanism = { + CKM_SHA512_HMAC, NULL, 0, +}; + +static const CK_ULONG cktest_general_mechanism_hmac_len = 8; + +static CK_MECHANISM cktest_aes_cmac_general_mechanism = { + CKM_AES_CMAC_GENERAL, + (CK_VOID_PTR)&cktest_general_mechanism_hmac_len, + sizeof(CK_ULONG), +}; +static CK_MECHANISM cktest_hmac_general_md5_mechanism = { + CKM_MD5_HMAC_GENERAL, + (CK_VOID_PTR)&cktest_general_mechanism_hmac_len, + sizeof(CK_ULONG), +}; +static CK_MECHANISM cktest_hmac_general_sha1_mechanism = { + CKM_SHA_1_HMAC_GENERAL, + (CK_VOID_PTR)&cktest_general_mechanism_hmac_len, + sizeof(CK_ULONG), +}; +static CK_MECHANISM cktest_hmac_general_sha224_mechanism = { + CKM_SHA224_HMAC_GENERAL, + (CK_VOID_PTR)&cktest_general_mechanism_hmac_len, + sizeof(CK_ULONG), +}; +static CK_MECHANISM cktest_hmac_general_sha256_mechanism = { + CKM_SHA256_HMAC_GENERAL, + (CK_VOID_PTR)&cktest_general_mechanism_hmac_len, + sizeof(CK_ULONG), +}; +static CK_MECHANISM cktest_hmac_general_sha384_mechanism = { + CKM_SHA384_HMAC_GENERAL, + (CK_VOID_PTR)&cktest_general_mechanism_hmac_len, + sizeof(CK_ULONG), +}; +static CK_MECHANISM cktest_hmac_general_sha512_mechanism = { + CKM_SHA512_HMAC_GENERAL, + (CK_VOID_PTR)&cktest_general_mechanism_hmac_len, + sizeof(CK_ULONG), +}; + +static CK_MECHANISM cktest_gensecret_keygen_mechanism = { + CKM_GENERIC_SECRET_KEY_GEN, NULL, 0, +}; +static CK_MECHANISM cktest_aes_keygen_mechanism = { + CKM_AES_KEY_GEN, NULL, 0, +}; + +/* + * Util to find a slot on which to open a session + */ +static CK_RV close_lib(void) +{ + return C_Finalize(0); +} + +static CK_RV init_lib_and_find_token_slot(CK_SLOT_ID *slot, enum auth_type at) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID_PTR slots = NULL; + CK_ULONG count = 0; + + rv = C_Initialize(0); + if (rv) + return rv; + + rv = C_GetSlotList(CK_TRUE, NULL, &count); + if (rv != CKR_OK) + goto bail; + + if (count < 1) { + rv = CKR_GENERAL_ERROR; + goto bail; + } + + slots = malloc(count * sizeof(CK_SLOT_ID)); + if (!slots) { + rv = CKR_HOST_MEMORY; + goto bail; + } + + rv = C_GetSlotList(CK_TRUE, slots, &count); + if (rv) + goto bail; + + if (at == PIN_AUTH) { + /* Use the last slot */ + *slot = slots[count - 1]; + } else { /* ACL_AUTH */ + /* Use the second to last slot */ + if (count >= 2) + *slot = slots[count - 2]; + else + rv = CKR_GENERAL_ERROR; + } + +bail: + free(slots); + if (rv) + close_lib(); + + return rv; +} + +static void xtest_pkcs11_test_1000(ADBG_Case_t *c) +{ + CK_RV rv; + + rv = C_Initialize(NULL); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_Finalize(NULL); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_Initialize(NULL); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_Initialize(NULL); + ADBG_EXPECT_CK_RESULT(c, CKR_CRYPTOKI_ALREADY_INITIALIZED, rv); + + rv = C_Finalize(NULL); + ADBG_EXPECT_CK_OK(c, rv); + + rv = C_Finalize(NULL); + ADBG_EXPECT_CK_RESULT(c, CKR_CRYPTOKI_NOT_INITIALIZED, rv); +} + +ADBG_CASE_DEFINE(pkcs11, 1000, xtest_pkcs11_test_1000, + "Initialize and close Cryptoki library"); + +static void xtest_pkcs11_test_1001(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID_PTR slot_ids = NULL; + CK_ULONG slot_count = 0; + CK_ULONG present_slot_count = 0; + CK_INFO lib_info = { }; + CK_SLOT_INFO slot_info = { }; + CK_TOKEN_INFO token_info = { }; + CK_FUNCTION_LIST_PTR ckfunc_list = NULL; + size_t i = 0; + CK_SLOT_ID max_slot_id = 0; + CK_MECHANISM_TYPE_PTR mecha_types = NULL; + CK_ULONG mecha_count = 0; + CK_MECHANISM_INFO mecha_info = { }; + + rv = C_Initialize(NULL); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + Do_ADBG_BeginSubCase(c, "Test C_GetFunctionList()"); + + rv = C_GetFunctionList(&ckfunc_list); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetInfo) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetSlotList) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetSlotInfo) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetTokenInfo) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetMechanismList) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetMechanismInfo)) + goto out; + + Do_ADBG_EndSubCase(c, "Test C_GetFunctionList()"); + Do_ADBG_BeginSubCase(c, "Test C_GetInfo()"); + + rv = C_GetInfo(&lib_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, "Test C_GetInfo()"); + Do_ADBG_BeginSubCase(c, "Test C_GetSlotList()"); + + rv = C_GetSlotList(0, NULL, &slot_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, slot_count, !=, 0)) + goto out; + + if (slot_count > 1) { + /* Ensure case non-NULL-buffer and zero-count is tested */ + CK_SLOT_ID id = 0; + + slot_count = 0; + rv = C_GetSlotList(0, &id, &slot_count); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto out; + } + + rv = C_GetSlotList(1, NULL, &present_slot_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, slot_count, ==, + present_slot_count)) + goto out; + + slot_ids = calloc(slot_count, sizeof(*slot_ids)); + if (!ADBG_EXPECT_NOT_NULL(c, slot_ids)) + goto out; + + slot_count--; + rv = C_GetSlotList(1, slot_ids, &slot_count); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto out; + + rv = C_GetSlotList(1, slot_ids, &slot_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, "Test C_GetSlotList()"); + Do_ADBG_BeginSubCase(c, "Test C_Get{Slot|Token}Info()"); + + for (i = 0; i < slot_count; i++) { + CK_SLOT_ID slot = slot_ids[i]; + + rv = C_GetSlotInfo(slot, &slot_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (max_slot_id < slot) + max_slot_id = slot; + } + + Do_ADBG_EndSubCase(c, "Test C_Get{Slot|Token}Info()"); + Do_ADBG_BeginSubCase(c, "Test C_GetMechanism{List|Info}()"); + + for (i = 0; i < slot_count; i++) { + CK_SLOT_ID slot = slot_ids[i]; + size_t j = 0; + + mecha_count = 0; + rv = C_GetMechanismList(slot, NULL, &mecha_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (mecha_count == 0) + continue; + + free(mecha_types); + mecha_types = calloc(mecha_count, sizeof(*mecha_types)); + if (!ADBG_EXPECT_NOT_NULL(c, mecha_types)) + goto out; + + /* Test specific case: valid buffer reference with 0 count */ + mecha_count = 0; + rv = C_GetMechanismList(slot, mecha_types, &mecha_count); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto out; + + rv = C_GetMechanismList(slot, mecha_types, &mecha_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + for (j = 0; j < mecha_count; j++) { + rv = C_GetMechanismInfo(slot, mecha_types[j], + &mecha_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + } + } + + Do_ADBG_EndSubCase(c, "Test C_GetMechanism{List|Info}()"); + Do_ADBG_BeginSubCase(c, "Test C_GetMechanismList() with larger result buffer"); + + for (i = 0; i < slot_count; i++) { + CK_SLOT_ID slot = slot_ids[i]; + CK_ULONG real_mecha_count = 0; + CK_ULONG alloc_mecha_count = 0; + uint8_t *data_ptr = NULL; + size_t j = 0; + + rv = C_GetMechanismList(slot, NULL, &real_mecha_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (real_mecha_count == 0) + continue; + + /* Allocate more memory for mechanisms than required */ + alloc_mecha_count = real_mecha_count + 16; + mecha_count = alloc_mecha_count; + + free(mecha_types); + mecha_types = calloc(mecha_count, sizeof(*mecha_types)); + if (!ADBG_EXPECT_NOT_NULL(c, mecha_types)) + goto out; + memset(mecha_types, 0xCC, + alloc_mecha_count * sizeof(*mecha_types)); + + rv = C_GetMechanismList(slot, mecha_types, &mecha_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, mecha_count, ==, + real_mecha_count)) + goto out; + + data_ptr = (uint8_t *)mecha_types; + for (j = real_mecha_count * sizeof(*mecha_types); + j < alloc_mecha_count * sizeof(*mecha_types); j++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, data_ptr[j], ==, + 0xCC)) + break; + } + + Do_ADBG_EndSubCase(c, "Test C_GetMechanismList() with larger result buffer"); + Do_ADBG_BeginSubCase(c, "Test C_Get*Info() with invalid reference"); + + rv = C_GetSlotInfo(max_slot_id + 1, &slot_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv)) + goto out; + + rv = C_GetTokenInfo(max_slot_id + 1, &token_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv)) + goto out; + + mecha_count = 1; + if (!mecha_types) + mecha_types = malloc(sizeof(*mecha_types)); + if (!ADBG_EXPECT_NOT_NULL(c, mecha_types)) + goto out; + + rv = C_GetMechanismList(max_slot_id + 1, mecha_types, &mecha_count); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv)) + goto out; + + rv = C_GetMechanismInfo(max_slot_id + 1, CKM_AES_KEY_GEN, &mecha_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv)) + goto out; + + rv = C_GetSlotInfo(ULONG_MAX, &slot_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv)) + goto out; + + rv = C_GetTokenInfo(ULONG_MAX, &token_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv)) + goto out; + + mecha_count = 1; + rv = C_GetMechanismList(ULONG_MAX, mecha_types, &mecha_count); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv)) + goto out; + + rv = C_GetMechanismInfo(ULONG_MAX, CKM_AES_KEY_GEN, &mecha_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SLOT_ID_INVALID, rv)) + goto out; + +out: + Do_ADBG_EndSubCase(c, NULL); + free(slot_ids); + free(mecha_types); + + rv = C_Finalize(NULL); + ADBG_EXPECT_CK_OK(c, rv); +} + +ADBG_CASE_DEFINE(pkcs11, 1001, xtest_pkcs11_test_1001, + "PKCS11: List PKCS#11 slots and get information from"); + +static void xtest_pkcs11_test_1002(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session[3] = { 0 }; + CK_FLAGS session_flags = 0; + CK_SESSION_INFO session_info = { }; + CK_FUNCTION_LIST_PTR ckfunc_list = NULL; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_GetFunctionList(&ckfunc_list); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_OpenSession) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_CloseSession) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_CloseAllSessions) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_GetSessionInfo)) + goto bail; + + Do_ADBG_BeginSubCase(c, "Test C_OpenSession()/C_GetSessionInfo()"); + + session_flags = CKF_RW_SESSION; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session[0]); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_PARALLEL_NOT_SUPPORTED, rv)) + goto bail; + + session_flags = CKF_SERIAL_SESSION; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session[0]); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + rv = C_GetSessionInfo(session[0], &session_info); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.slotID, ==, slot) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.flags, ==, + session_flags) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.state, ==, + CKS_RO_PUBLIC_SESSION) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.ulDeviceError, ==, 0)) + goto bail; + + session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session[1]); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + rv = C_GetSessionInfo(session[1], &session_info); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.slotID, ==, slot) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.flags, ==, + session_flags) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.state, ==, + CKS_RW_PUBLIC_SESSION) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.ulDeviceError, ==, 0)) + goto bail; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session[2]); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + rv = C_GetSessionInfo(session[2], &session_info); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.slotID, ==, slot) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.flags, ==, + session_flags) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.state, ==, + CKS_RW_PUBLIC_SESSION) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, session_info.ulDeviceError, ==, 0)) + goto bail; + + Do_ADBG_EndSubCase(c, "Test C_OpenSession()/C_GetSessionInfo()"); + Do_ADBG_BeginSubCase(c, "Test C_CloseSession()"); + + /* Close 2 of them */ + rv = C_CloseSession(session[0]); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + rv = C_GetSessionInfo(session[0], &session_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv)) + goto bail; + + rv = C_GetSessionInfo(session[1], &session_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + rv = C_GetSessionInfo(session[2], &session_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + /* Close all remaining sessions, later calls should failed on session */ + rv = C_CloseAllSessions(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + rv = C_CloseSession(session[1]); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv)) + goto bail; + + rv = C_CloseSession(session[2]); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv)) + goto bail; + + rv = C_GetSessionInfo(session[1], &session_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv)) + goto bail; + + rv = C_GetSessionInfo(session[2], &session_info); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv)) + goto bail; + + /* Open a session, should be closed from library closure */ + rv = C_OpenSession(slot, session_flags, NULL, 0, &session[0]); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + +bail: + Do_ADBG_EndSubCase(c, NULL); + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); +} + +ADBG_CASE_DEFINE(pkcs11, 1002, xtest_pkcs11_test_1002, + "PKCS11: Open and close PKCS#11 sessions"); + +/* + * Helpers for tests where we must log into the token. + * These define the genuine PINs and label to be used with the test token. + */ +static CK_UTF8CHAR test_token_so_pin[] = { '1', '2', '3', '4', '5', '6', '7', + '8' }; +static CK_UTF8CHAR deprecated_so_pin[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; +static CK_UTF8CHAR test_token_user_pin[] = { '1', '2', '3', '4', '5' }; +static CK_UTF8CHAR test_token_label[] = "PKCS11 TA test token"; + +/* + * Compatibility function for systems that would have run the PKCS#11 tests + * with the deprecated SO PIN (the one that was modified in commit "pkcs11: + * remove NULbyte from SO PIN and use ASCII characters"). + * The goal is to transparently upgrade the SO PIN to the new one if possible + * and avoid failing any tests. + */ +static CK_RV change_deprecated_so_pin(CK_SLOT_ID slot) +{ + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_RV rv = CKR_GENERAL_ERROR; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (rv != CKR_OK) + return rv; + + rv = C_Login(session, CKU_SO, deprecated_so_pin, + sizeof(deprecated_so_pin)); + if (rv != CKR_OK) + goto out; + + rv = C_SetPIN(session, deprecated_so_pin, sizeof(deprecated_so_pin), + test_token_so_pin, sizeof(test_token_so_pin)); + Do_ADBG_Log("Note: SO PIN for slot %lu updated successfully", slot); + + C_Logout(session); +out: + C_CloseSession(session); + return rv; +} + +static CK_RV init_test_token_pin_auth(CK_SLOT_ID slot) +{ + CK_RV rv = CKR_GENERAL_ERROR; + + rv = C_InitToken(slot, test_token_so_pin, sizeof(test_token_so_pin), + test_token_label); + if (rv == CKR_PIN_INCORRECT) { + rv = change_deprecated_so_pin(slot); + if (rv != CKR_OK) + return rv; + rv = C_InitToken(slot, test_token_so_pin, + sizeof(test_token_so_pin), test_token_label); + } + return rv; +} + +/* Login as user, eventually reset user PIN if needed */ +static CK_RV init_user_test_token_pin_auth(CK_SLOT_ID slot) +{ + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_RV rv = CKR_GENERAL_ERROR; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (rv) + return rv; + + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (rv == CKR_OK) { + C_Logout(session); + C_CloseSession(session); + return rv; + } + + rv = C_Login(session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + if (rv) { + C_CloseSession(session); + + rv = init_test_token_pin_auth(slot); + if (rv) + return rv; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (rv) + return rv; + + rv = C_Login(session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + if (rv) { + C_CloseSession(session); + return rv; + } + } + + rv = C_InitPIN(session, test_token_user_pin, + sizeof(test_token_user_pin)); + + C_Logout(session); + C_CloseSession(session); + + return rv; +} + +static CK_RV test_already_initialized_token(ADBG_Case_t *c, CK_SLOT_ID slot) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_TOKEN_INFO token_info = { }; + /* Same content as test_token_so_pin[] but 1 more byte */ + CK_UTF8CHAR pin1[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + /* Same content as test_token_so_pin[] but 1 different byte */ + CK_UTF8CHAR pin2[] = { '1', '2', '3', '4', '5', '5', '7', '8' }; + CK_FLAGS flags = 0; + + Do_ADBG_BeginSubCase(c, "C_InitToken() on initialized token"); + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_InitToken(slot, test_token_so_pin, + sizeof(test_token_so_pin) - 1, test_token_label); + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, rv, !=, CKR_OK)) + goto out; + + rv = C_InitToken(slot, pin1, sizeof(pin1), test_token_label); + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, rv, !=, CKR_OK)) + goto out; + + rv = C_InitToken(slot, pin2, sizeof(pin2), test_token_label); + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, rv, !=, CKR_OK)) + goto out; + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + flags = token_info.flags; + + /* Token should have set CKF_SO_PIN_COUNT_LOW to 1 */ + if (!ADBG_EXPECT_TRUE(c, !!(flags & CKF_SO_PIN_COUNT_LOW))) { + rv = CKR_GENERAL_ERROR; + goto out; + } + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + flags = token_info.flags; + + /* + * Token should have reset CKF_SO_PIN_COUNT_LOW to 0. + * Other flags should show a sane initialized state. + */ + if (!ADBG_EXPECT_TRUE(c, !(flags & CKF_SO_PIN_COUNT_LOW)) || + !ADBG_EXPECT_TRUE(c, !!(flags & CKF_TOKEN_INITIALIZED)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_ERROR_STATE)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_INITIALIZED))) { + rv = CKR_GENERAL_ERROR; + goto out; + } + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + flags = token_info.flags; + + if (!ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_COUNT_LOW)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_FINAL_TRY)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_LOCKED)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_TO_BE_CHANGED)) || + !ADBG_EXPECT_TRUE(c, !!(flags & CKF_USER_PIN_INITIALIZED)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_ERROR_STATE))) { + rv = CKR_GENERAL_ERROR; + goto out; + } + +out: + Do_ADBG_EndSubCase(c, "C_InitToken() on initialized token"); + + return rv; +} + +static CK_UTF8CHAR test_acl_auth_token_label[] = "PKCS11 TA test token for ACL based authentication"; + +static CK_RV init_test_token_acl_auth(CK_SLOT_ID slot) +{ + return C_InitToken(slot, NULL, 0, test_acl_auth_token_label); +} + +#define TEE_UUID_NS_NAME_SIZE 128 +#define ACL_PIN_LEN 43 + +/* + * TEE client UUID name space identifier + * Client UUIDs are derived from this UUID (which is defined in the Linux + * kernel) using the UUIDv5 scheme. + */ +static const char *client_uuid_linux_ns = "58ac9ca0-2086-4683-a1b8-ec4bc08e01b6"; + +static CK_RV init_user_test_token_acl_auth(ADBG_Case_t *c, CK_SLOT_ID slot) +{ + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_RV rv = CKR_GENERAL_ERROR; + TEEC_Result result = TEEC_ERROR_GENERIC; + TEEC_UUID expected_client_uuid = { 0 }; + TEEC_UUID uuid_ns = { 0 }; + char uuid_name[TEE_UUID_NS_NAME_SIZE] = { 0 }; + char test_token_acl_auth_pin[ACL_PIN_LEN] = { 0 }; + char *client_id_s = NULL; + int str_len = 0; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (rv) + return rv; + + rv = C_Login(session, CKU_USER, NULL, 0); + if (rv == CKR_OK) { + C_Logout(session); + C_CloseSession(session); + return CKR_OK; + } + + rv = C_Login(session, CKU_SO, NULL, 0); + if (rv) { + C_CloseSession(session); + + rv = init_test_token_acl_auth(slot); + if (rv) + return rv; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (rv) + return rv; + + rv = C_Login(session, CKU_SO, NULL, 0); + if (rv) { + C_CloseSession(session); + return rv; + } + } + + rv = CKR_GENERAL_ERROR; + + result = xtest_uuid_from_str(&uuid_ns, client_uuid_linux_ns); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + goto out; + + str_len = snprintf(uuid_name, sizeof(uuid_name), "gid=%x", getegid()); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, str_len, >=, 0)) + goto out; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, str_len, <, (int)sizeof(uuid_name))) + goto out; + + result = xtest_uuid_v5(&expected_client_uuid, &uuid_ns, uuid_name, + strlen(uuid_name)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + goto out; + + client_id_s = xtest_uuid_to_allocated_str(&expected_client_uuid); + if (!ADBG_EXPECT_NOT_NULL(c, client_id_s)) { + rv = CKR_HOST_MEMORY; + goto out; + } + + str_len = snprintf(test_token_acl_auth_pin, sizeof(test_token_acl_auth_pin), "group:%s", client_id_s); + free(client_id_s); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, str_len, >=, 0)) + goto out; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, str_len, <, (int)sizeof(test_token_acl_auth_pin))) + goto out; + + rv = C_InitPIN(session, (CK_UTF8CHAR_PTR)test_token_acl_auth_pin, + (CK_ULONG)strlen(test_token_acl_auth_pin)); + ADBG_EXPECT_CK_OK(c, rv); + +out: + C_Logout(session); + C_CloseSession(session); + + return rv; +} + +static CK_RV test_uninitialized_token(ADBG_Case_t *c, CK_SLOT_ID slot, enum auth_type at) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_TOKEN_INFO token_info = { }; + CK_FLAGS flags = 0; + + Do_ADBG_BeginSubCase(c, "C_InitToken() on uninitialized token"); + + if (at == PIN_AUTH) + rv = init_test_token_pin_auth(slot); + else /* ACL_AUTH */ + rv = init_test_token_acl_auth(slot); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + flags = token_info.flags; + + if (!ADBG_EXPECT_TRUE(c, !!(flags & CKF_TOKEN_INITIALIZED)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_ERROR_STATE)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_INITIALIZED))) { + rv = CKR_GENERAL_ERROR; + goto out; + } + + if (at == PIN_AUTH) + rv = init_user_test_token_pin_auth(slot); + else /* ACL_AUTH */ + rv = init_user_test_token_acl_auth(c, slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + flags = token_info.flags; + + if (!ADBG_EXPECT_TRUE(c, !!(flags & CKF_TOKEN_INITIALIZED)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_COUNT_LOW)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_FINAL_TRY)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_LOCKED)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_USER_PIN_TO_BE_CHANGED)) || + !ADBG_EXPECT_TRUE(c, !!(flags & CKF_USER_PIN_INITIALIZED)) || + !ADBG_EXPECT_TRUE(c, !(flags & CKF_ERROR_STATE))) + rv = CKR_GENERAL_ERROR; + +out: + Do_ADBG_EndSubCase(c, "C_InitToken() on uninitialized token"); + + return rv; +} + +static CK_RV test_login_logout_pin_auth(ADBG_Case_t *c, CK_SLOT_ID slot) +{ + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_RV rv = CKR_GENERAL_ERROR; + + Do_ADBG_BeginSubCase(c, "Test C_Login()/C_Logout() with PIN based authentication"); + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Logout: should fail as we did not log in yet */ + rv = C_Logout(session); + ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv); + + /* Login/re-log/logout user */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + ADBG_EXPECT_CK_RESULT(c, CKR_USER_ALREADY_LOGGED_IN, rv); + + rv = C_Logout(session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Login/re-log/logout security officer */ + rv = C_Login(session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Login(session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + ADBG_EXPECT_CK_RESULT(c, CKR_USER_ALREADY_LOGGED_IN, rv); + + rv = C_Logout(session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Login user then SO and reverse */ + rv = C_Login(session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + ADBG_EXPECT_CK_OK(c, rv); + + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + ADBG_EXPECT_CK_RESULT(c, CKR_USER_ANOTHER_ALREADY_LOGGED_IN, rv); + + rv = C_Logout(session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + ADBG_EXPECT_CK_OK(c, rv); + + rv = C_Login(session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + ADBG_EXPECT_CK_RESULT(c, CKR_USER_ANOTHER_ALREADY_LOGGED_IN, rv); + + rv = C_Logout(session); + ADBG_EXPECT_CK_OK(c, rv); + + /* Login context specifc, in an invalid case (need an operation) */ + rv = C_Login(session, CKU_CONTEXT_SPECIFIC, test_token_user_pin, + sizeof(test_token_user_pin)); + ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv); + + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); + +out: + Do_ADBG_EndSubCase(c, "Test C_Login()/C_Logout() with PIN based authentication"); + return rv; +} + +static CK_RV test_set_pin(ADBG_Case_t *c, CK_SLOT_ID slot, + CK_USER_TYPE user_type) +{ + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_UTF8CHAR some_pin[] = { '1', '2', '3', '3', '2', '1' }; + CK_UTF8CHAR_PTR old_pin = NULL; + CK_USER_TYPE ut = user_type; + size_t old_pin_sz = 0; + CK_RV rv2 = CKR_OK; + CK_RV rv = CKR_OK; + + Do_ADBG_BeginSubCase(c, "Test C_SetPIN() user_type %lu", user_type); + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (user_type == CKU_SO) { + old_pin = (CK_UTF8CHAR_PTR)test_token_so_pin; + old_pin_sz = sizeof(test_token_so_pin); + } else { + old_pin = (CK_UTF8CHAR_PTR)test_token_user_pin; + old_pin_sz = sizeof(test_token_user_pin); + ut = CKU_USER; + } + + if (ut == user_type) { + rv = C_Login(session, ut, old_pin, old_pin_sz); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_session; + } + + rv = C_SetPIN(session, old_pin, old_pin_sz, some_pin, sizeof(some_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) { + if (ut == user_type) + goto out_logout; + else + goto out_session; + } + + if (ut == user_type) { + rv = C_Logout(session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_session; + } + + rv = C_Login(session, ut, some_pin, sizeof(some_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_session; + + rv = C_SetPIN(session, some_pin, sizeof(some_pin), old_pin, old_pin_sz); + ADBG_EXPECT_CK_OK(c, rv); + +out_logout: + rv2 = C_Logout(session); + if (!ADBG_EXPECT_CK_OK(c, rv2) && !rv) + rv = rv2; +out_session: + rv2 = C_CloseSession(session); + if (!ADBG_EXPECT_CK_OK(c, rv2) && !rv) + rv = rv2; +out: + Do_ADBG_EndSubCase(c, "Test C_SetPIN() user_type %lu", user_type); + + return rv; +} + +static void xtest_pkcs11_test_1003(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_FUNCTION_LIST_PTR ckfunc_list = NULL; + CK_SLOT_ID slot = 0; + CK_TOKEN_INFO token_info = { }; + + rv = C_GetFunctionList(&ckfunc_list); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_InitToken) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_InitPIN) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_SetPIN) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_Login) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_Logout)) + return; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Abort test if token is about to lock */ + if (!ADBG_EXPECT_TRUE(c, !(token_info.flags & CKF_SO_PIN_FINAL_TRY))) + goto out; + + if (!(token_info.flags & CKF_TOKEN_INITIALIZED)) { + rv = test_uninitialized_token(c, slot, PIN_AUTH); + if (rv != CKR_OK) + goto out; + } + + rv = test_already_initialized_token(c, slot); + if (rv != CKR_OK) + goto out; + + rv = test_login_logout_pin_auth(c, slot); + if (rv != CKR_OK) + goto out; + + rv = test_set_pin(c, slot, CKU_USER); + if (rv != CKR_OK) + goto out; + + rv = test_set_pin(c, slot, CKU_SO); + if (rv != CKR_OK) + goto out; + + /* + * CKU_CONTEXT_SPECIFIC is anything not CKU_USER or CKU_SO in order + * to skip the initial login. + */ + test_set_pin(c, slot, CKU_CONTEXT_SPECIFIC); +out: + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); +} + +ADBG_CASE_DEFINE(pkcs11, 1003, xtest_pkcs11_test_1003, + "PKCS11: Login to PKCS#11 token with PIN based authentication"); + +static CK_ATTRIBUTE cktest_token_object[] = { + { CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) }, + { CKA_VALUE, (void *)cktest_aes128_key, sizeof(cktest_aes128_key) }, +}; + +static CK_ATTRIBUTE cktest_session_object[] = { + { CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) }, + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_VALUE, (void *)cktest_aes128_key, sizeof(cktest_aes128_key) }, +}; + +/* Create session object and token object from a session */ +static void test_create_destroy_single_object(ADBG_Case_t *c, bool persistent) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (persistent) { + rv = C_CreateObject(session, cktest_token_object, + ARRAY_SIZE(cktest_token_object), + &obj_hdl); + } else { + rv = C_CreateObject(session, cktest_session_object, + ARRAY_SIZE(cktest_session_object), + &obj_hdl); + } + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DestroyObject(session, obj_hdl); + ADBG_EXPECT_CK_OK(c, rv); +out: + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); + + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); +} + +static void test_create_destroy_session_objects(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE obj_hdl[512] = { 0 }; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(obj_hdl); n++) + obj_hdl[n] = CK_INVALID_HANDLE; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + for (n = 0; n < ARRAY_SIZE(obj_hdl); n++) { + rv = C_CreateObject(session, cktest_session_object, + ARRAY_SIZE(cktest_session_object), + obj_hdl + n); + + if (rv == CKR_DEVICE_MEMORY || !ADBG_EXPECT_CK_OK(c, rv)) + break; + } + + Do_ADBG_Log(" created object count: %zu", n); + + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_CreateObject(session, cktest_session_object, + ARRAY_SIZE(cktest_session_object), + obj_hdl); + + ADBG_EXPECT_CK_OK(c, rv); + +out: + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); + + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); +} + +/* Create session object and token object from a session */ +static void test_create_objects_in_session(ADBG_Case_t *c, bool readwrite) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE token_obj_hld = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE session_obj_hld = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + if (readwrite) + session_flags |= CKF_RW_SESSION; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_CreateObject(session, cktest_token_object, + ARRAY_SIZE(cktest_token_object), + &token_obj_hld); + + if (readwrite) { + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + } else { + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv)) + goto out; + } + + rv = C_CreateObject(session, cktest_session_object, + ARRAY_SIZE(cktest_session_object), + &session_obj_hld); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_tobj; + + rv = C_DestroyObject(session, session_obj_hld); + ADBG_EXPECT_CK_OK(c, rv); + +out_tobj: + if (readwrite) { + rv = C_DestroyObject(session, token_obj_hld); + ADBG_EXPECT_CK_OK(c, rv); + } +out: + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); + + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); +} + +static void xtest_pkcs11_test_1004(ADBG_Case_t *c) +{ + Do_ADBG_BeginSubCase(c, "Create and destroy a volatile object"); + test_create_destroy_single_object(c, false /*!persistent*/); + Do_ADBG_EndSubCase(c, "Create and destroy a volatile object"); + + Do_ADBG_BeginSubCase(c, "Create and destroy a persistent object"); + test_create_destroy_single_object(c, true /*persistent*/); + Do_ADBG_EndSubCase(c, "Create and destroy a persistent object"); + + Do_ADBG_BeginSubCase(c, "Create and destroy many session objects"); + test_create_destroy_session_objects(c); + Do_ADBG_EndSubCase(c, "Create and destroy many session objects"); + + Do_ADBG_BeginSubCase(c, "Create objects in a read-only session"); + test_create_objects_in_session(c, false /*!readwrite*/); + Do_ADBG_EndSubCase(c, "Create objects in a read-only session"); + + Do_ADBG_BeginSubCase(c, "Create objects in a read/write session"); + test_create_objects_in_session(c, true /*readwrite*/); + Do_ADBG_EndSubCase(c, "Create objects in a read/write session"); +} + +ADBG_CASE_DEFINE(pkcs11, 1004, xtest_pkcs11_test_1004, + "PKCS11: create/destroy PKCS#11 simple objects"); + + +static const CK_MECHANISM_TYPE allowed_only_aes_ecb[] = { + CKM_AES_ECB, +}; +static const CK_MECHANISM_TYPE allowed_not_aes_ecb[] = { + CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_AES_CTR, CKM_AES_CTS, + CKM_AES_GCM, CKM_AES_CCM, +}; +static const CK_MECHANISM_TYPE allowed_only_aes_cbcnopad[] = { + CKM_AES_CBC, +}; +static const CK_MECHANISM_TYPE allowed_not_aes_cbcnopad[] = { + CKM_AES_ECB, CKM_AES_CBC_PAD, CKM_AES_CTR, CKM_AES_CTS, + CKM_AES_GCM, CKM_AES_CCM, +}; +static const CK_MECHANISM_TYPE allowed_only_aes_ctr[] = { + CKM_AES_CTR, +}; +static const CK_MECHANISM_TYPE allowed_not_aes_ctr[] = { + CKM_AES_ECB, CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_AES_CTS, + CKM_AES_GCM, CKM_AES_CCM, +}; +static const CK_MECHANISM_TYPE allowed_only_aes_cts[] = { + CKM_AES_CTS, +}; +static const CK_MECHANISM_TYPE allowed_not_aes_cts[] = { + CKM_AES_ECB, CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_AES_CTR, + CKM_AES_GCM, CKM_AES_CCM, +}; + +#define CKTEST_AES_KEY \ + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, \ + sizeof(CK_OBJECT_CLASS) }, \ + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, \ + sizeof(CK_KEY_TYPE) }, \ + { CKA_VALUE, (void *)cktest_aes128_key, \ + sizeof(cktest_aes128_key) } + +#define CKTEST_AES_ALLOWED_KEY(_allowed) \ + { CKA_ALLOWED_MECHANISMS, (void *)_allowed, sizeof(_allowed), } + +#define CK_KEY_ALLOWED_AES_TEST(_label, _allowed) \ + static CK_ATTRIBUTE _label[] = { \ + CKTEST_AES_KEY, \ + { CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, \ + { CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, \ + CKTEST_AES_ALLOWED_KEY(_allowed), \ + } + +#define CK_KEY_ALLOWED_AES_ENC_TEST(_label, _allowed) \ + static CK_ATTRIBUTE _label[] = { \ + CKTEST_AES_KEY, \ + { CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, \ + CKTEST_AES_ALLOWED_KEY(_allowed), \ + } +#define CK_KEY_ALLOWED_AES_DEC_TEST(_label, _allowed) \ + static CK_ATTRIBUTE _label[] = { \ + CKTEST_AES_KEY, \ + { CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, \ + CKTEST_AES_ALLOWED_KEY(_allowed), \ + } + +CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_ecb, allowed_only_aes_ecb); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_ecb, allowed_not_aes_ecb); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_cbcnopad, allowed_only_aes_cbcnopad); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_cbcnopad, allowed_not_aes_cbcnopad); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_cts, allowed_only_aes_cts); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_cts, allowed_not_aes_cts); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_only_ctr, allowed_only_aes_ctr); +CK_KEY_ALLOWED_AES_TEST(cktest_aes_not_ctr, allowed_not_aes_ctr); + +struct cktest_allowed_test { + CK_ATTRIBUTE_PTR attr_key; + CK_ULONG attr_count; + CK_MECHANISM_PTR mechanism; +}; + +#define CKTEST_KEY_MECHA(key, mecha) { \ + .attr_key = key, \ + .attr_count = ARRAY_SIZE(key), \ + .mechanism = mecha, \ + } + +static const struct cktest_allowed_test cktest_allowed_valid[] = { + CKTEST_KEY_MECHA(cktest_aes_only_ecb, &cktest_aes_ecb_mechanism), + CKTEST_KEY_MECHA(cktest_aes_only_cbcnopad, &cktest_aes_cbc_mechanism), + CKTEST_KEY_MECHA(cktest_aes_only_cts, &cktest_aes_cts_mechanism), + CKTEST_KEY_MECHA(cktest_aes_only_ctr, &cktest_aes_ctr_mechanism), +}; + +static const struct cktest_allowed_test cktest_allowed_invalid[] = { + CKTEST_KEY_MECHA(cktest_aes_not_ecb, &cktest_aes_ecb_mechanism), + CKTEST_KEY_MECHA(cktest_aes_not_cbcnopad, &cktest_aes_cbc_mechanism), + CKTEST_KEY_MECHA(cktest_aes_not_cts, &cktest_aes_cts_mechanism), + CKTEST_KEY_MECHA(cktest_aes_not_ctr, &cktest_aes_ctr_mechanism), +}; + +/* Create session object and token object from a session */ +static CK_RV cipher_init_final(ADBG_Case_t *c, CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR attr_key, CK_ULONG attr_count, + CK_MECHANISM_PTR mechanism, uint32_t mode, + CK_RV expected_rc) +{ + CK_RV rv2 = CKR_GENERAL_ERROR; + CK_RV rv = CKR_GENERAL_ERROR; + CK_OBJECT_HANDLE object = CK_INVALID_HANDLE; + + switch (mode) { + case TEE_MODE_ENCRYPT: + case TEE_MODE_DECRYPT: + break; + default: + ADBG_EXPECT_TRUE(c, false); + } + + rv = C_CreateObject(session, attr_key, attr_count, &object); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return rv; + + if (mode == TEE_MODE_ENCRYPT) + rv = C_EncryptInit(session, mechanism, object); + if (mode == TEE_MODE_DECRYPT) + rv = C_DecryptInit(session, mechanism, object); + + if (!ADBG_EXPECT_CK_RESULT(c, expected_rc, rv)) { + rv = CKR_GENERAL_ERROR; + goto out; + } + + if (rv) { + /* + * If we're here it was the expected error code above and + * we're supposed to return OK below. + */ + rv = CKR_OK; + } else { + if (mode == TEE_MODE_ENCRYPT) + rv = C_EncryptFinal(session, NULL, NULL); + if (mode == TEE_MODE_DECRYPT) + rv = C_DecryptFinal(session, NULL, NULL); + + /* + * Check that return value is expected so that operation is + * released + */ + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) { + rv = CKR_GENERAL_ERROR; + goto out; + } + + rv = CKR_OK; + } + +out: + rv2 = C_DestroyObject(session, object); + ADBG_EXPECT_CK_OK(c, rv2); + + if (rv) + return rv; + else + return rv2; +} + +CK_KEY_ALLOWED_AES_ENC_TEST(cktest_aes_enc_only_cts, allowed_only_aes_cts); + +CK_KEY_ALLOWED_AES_DEC_TEST(cktest_aes_dec_only_ctr, allowed_only_aes_ctr); + +static void xtest_pkcs11_test_1005(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION; + size_t n = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + for (n = 0; n < ARRAY_SIZE(cktest_allowed_valid); n++) { + + Do_ADBG_BeginSubCase(c, "valid usage #%zu", n); + + rv = cipher_init_final(c, session, + cktest_allowed_valid[n].attr_key, + cktest_allowed_valid[n].attr_count, + cktest_allowed_valid[n].mechanism, + TEE_MODE_ENCRYPT, + CKR_OK); + + ADBG_EXPECT_CK_OK(c, rv); + + Do_ADBG_EndSubCase(c, NULL); + if (rv) + goto out; + + } + + for (n = 0; n < ARRAY_SIZE(cktest_allowed_invalid); n++) { + Do_ADBG_BeginSubCase(c, "invalid usage #%zu", n); + + rv = cipher_init_final(c, session, + cktest_allowed_invalid[n].attr_key, + cktest_allowed_invalid[n].attr_count, + cktest_allowed_invalid[n].mechanism, + TEE_MODE_ENCRYPT, + CKR_KEY_FUNCTION_NOT_PERMITTED); + + ADBG_EXPECT_CK_OK(c, rv); + + Do_ADBG_EndSubCase(c, NULL); + if (rv) + goto out; + + } + +out: + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); + + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); +} + + +ADBG_CASE_DEFINE(pkcs11, 1005, xtest_pkcs11_test_1005, + "PKCS11: Check ciphering with valid and invalid keys #1"); + +static void xtest_pkcs11_test_1006(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Encrypt only AES CTS key */ + rv = cipher_init_final(c, session, + cktest_aes_enc_only_cts, + ARRAY_SIZE(cktest_aes_enc_only_cts), + &cktest_aes_cts_mechanism, + TEE_MODE_ENCRYPT, + CKR_OK); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = cipher_init_final(c, session, + cktest_aes_enc_only_cts, + ARRAY_SIZE(cktest_aes_enc_only_cts), + &cktest_aes_cts_mechanism, + TEE_MODE_DECRYPT, + CKR_KEY_FUNCTION_NOT_PERMITTED); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Decrypt only AES CTR key */ + rv = cipher_init_final(c, session, + cktest_aes_dec_only_ctr, + ARRAY_SIZE(cktest_aes_dec_only_ctr), + &cktest_aes_ctr_mechanism, + TEE_MODE_ENCRYPT, + CKR_KEY_FUNCTION_NOT_PERMITTED); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = cipher_init_final(c, session, + cktest_aes_dec_only_ctr, + ARRAY_SIZE(cktest_aes_dec_only_ctr), + &cktest_aes_ctr_mechanism, + TEE_MODE_ENCRYPT, + CKR_KEY_FUNCTION_NOT_PERMITTED); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + +out: + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); + + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); +} +ADBG_CASE_DEFINE(pkcs11, 1006, xtest_pkcs11_test_1006, + "PKCS11: Check ciphering with valid and invalid keys #2"); + +static CK_RV open_cipher_session(ADBG_Case_t *c, + CK_SLOT_ID slot, CK_SESSION_HANDLE_PTR session, + CK_ATTRIBUTE_PTR attr_key, CK_ULONG attr_count, + CK_MECHANISM_PTR mechanism, uint32_t mode) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_OBJECT_HANDLE object = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION; + + switch (mode) { + case TEE_MODE_ENCRYPT: + case TEE_MODE_DECRYPT: + break; + default: + ADBG_EXPECT_TRUE(c, false); + return CKR_GENERAL_ERROR; + } + + rv = C_OpenSession(slot, session_flags, NULL, 0, session); + if (rv == CKR_DEVICE_MEMORY) + return rv; + if (!ADBG_EXPECT_CK_OK(c, rv)) + return rv; + + rv = C_CreateObject(*session, attr_key, attr_count, &object); + if (rv == CKR_DEVICE_MEMORY) + return rv; + if (!ADBG_EXPECT_CK_OK(c, rv)) + return rv; + + if (mode == TEE_MODE_ENCRYPT) + rv = C_EncryptInit(*session, mechanism, object); + if (mode == TEE_MODE_DECRYPT) + rv = C_DecryptInit(*session, mechanism, object); + + if (rv == CKR_DEVICE_MEMORY) + return rv; + if (!ADBG_EXPECT_CK_OK(c, rv)) + return CKR_GENERAL_ERROR; + + return rv; +} + +static void xtest_pkcs11_test_1007(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE sessions[128]; + size_t n = 0; + + for (n = 0; n < ARRAY_SIZE(sessions); n++) + sessions[n] = CK_INVALID_HANDLE; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + for (n = 0; n < ARRAY_SIZE(sessions); n++) { + + rv = open_cipher_session(c, slot, &sessions[n], + cktest_allowed_valid[0].attr_key, + cktest_allowed_valid[0].attr_count, + cktest_allowed_valid[0].mechanism, + TEE_MODE_ENCRYPT); + + /* Failure due to memory allocation is not a error case */ + if (rv == CKR_DEVICE_MEMORY) + break; + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + } + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, n, >, 0)) + goto out; + + Do_ADBG_Log(" created sessions count: %zu", n); + + /* Closing session with out bound and invalid IDs (or negative ID) */ + rv = C_CloseSession(sessions[n - 1] + 1024); + ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv); + rv = C_CloseSession(CK_INVALID_HANDLE); + ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv); + rv = C_CloseSession(~0); + ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_HANDLE_INVALID, rv); + + /* Closing each session: all related resources shall be free */ + for (n = 0; n < ARRAY_SIZE(sessions); n++) { + if (sessions[n] == CK_INVALID_HANDLE) + continue; + + rv = C_CloseSession(sessions[n]); + ADBG_EXPECT_CK_OK(c, rv); + sessions[n] = CK_INVALID_HANDLE; + } + + /* Open and close another session */ + rv = open_cipher_session(c, slot, &sessions[0], + cktest_allowed_valid[0].attr_key, + cktest_allowed_valid[0].attr_count, + cktest_allowed_valid[0].mechanism, + TEE_MODE_ENCRYPT); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_CloseSession(sessions[0]); + ADBG_EXPECT_CK_OK(c, rv); + sessions[0] = CK_INVALID_HANDLE; + +out: + for (n = 0; n < ARRAY_SIZE(sessions); n++) { + if (sessions[n] == CK_INVALID_HANDLE) + continue; + + rv = C_CloseSession(sessions[n]); + ADBG_EXPECT_CK_OK(c, rv); + } + + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); +} +ADBG_CASE_DEFINE(pkcs11, 1007, xtest_pkcs11_test_1007, + "PKCS11: Check operations release at session closure"); + +#define CK_MAC_KEY_AES(_key_array) \ + { \ + { CKA_SIGN, &(CK_BBOOL){CK_TRUE}, \ + sizeof(CK_BBOOL) }, \ + { CKA_VERIFY, &(CK_BBOOL){CK_TRUE}, \ + sizeof(CK_BBOOL) }, \ + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, \ + sizeof(CK_OBJECT_CLASS) }, \ + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, \ + sizeof(CK_KEY_TYPE) }, \ + { CKA_VALUE, (void *)(_key_array), \ + sizeof(_key_array) }, \ + } + +static CK_ATTRIBUTE cktest_aes_cmac_key1[] = + CK_MAC_KEY_AES(mac_cmac_vect1_key); + +static CK_ATTRIBUTE cktest_aes_cmac_key2[] = + CK_MAC_KEY_AES(mac_cmac_vect5_key); + +static CK_ATTRIBUTE cktest_aes_cmac_key3[] = + CK_MAC_KEY_AES(mac_cmac_vect9_key); + +#define CK_MAC_KEY_HMAC(_type, _key_array) \ + { \ + { CKA_SIGN, &(CK_BBOOL){CK_TRUE}, \ + sizeof(CK_BBOOL) }, \ + { CKA_VERIFY, &(CK_BBOOL){CK_TRUE}, \ + sizeof(CK_BBOOL) }, \ + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, \ + sizeof(CK_OBJECT_CLASS) }, \ + { CKA_KEY_TYPE, &(CK_KEY_TYPE){_type}, \ + sizeof(CK_KEY_TYPE) }, \ + { CKA_VALUE, (void *)(_key_array), \ + sizeof(_key_array) }, \ + } + +static CK_ATTRIBUTE cktest_hmac_md5_key[] = + CK_MAC_KEY_HMAC(CKK_MD5_HMAC, mac_data_md5_key1); + +static CK_ATTRIBUTE cktest_hmac_sha1_key[] = + CK_MAC_KEY_HMAC(CKK_SHA_1_HMAC, mac_data_sha1_key1); + +static CK_ATTRIBUTE cktest_hmac_sha224_key[] = + CK_MAC_KEY_HMAC(CKK_SHA224_HMAC, mac_data_sha224_key1); + +static CK_ATTRIBUTE cktest_hmac_sha256_key1[] = + CK_MAC_KEY_HMAC(CKK_SHA256_HMAC, mac_data_sha256_key1); + +static CK_ATTRIBUTE cktest_hmac_sha256_key2[] = + CK_MAC_KEY_HMAC(CKK_SHA256_HMAC, mac_data_sha256_key2); + +static CK_ATTRIBUTE cktest_hmac_sha384_key[] = + CK_MAC_KEY_HMAC(CKK_SHA384_HMAC, mac_data_sha384_key1); + +static CK_ATTRIBUTE cktest_hmac_sha512_key[] = + CK_MAC_KEY_HMAC(CKK_SHA512_HMAC, mac_data_sha512_key1); + +struct mac_test { + CK_ATTRIBUTE_PTR attr_key; + CK_ULONG attr_count; + CK_MECHANISM_PTR mechanism; + size_t in_incr; + const uint8_t *in; + size_t in_len; + const uint8_t *out; + size_t out_len; + bool multiple_incr; +}; + +#define CKTEST_MAC_TEST(key, mecha, input_incr, input, output, incr) { \ + .attr_key = key, \ + .attr_count = ARRAY_SIZE(key), \ + .mechanism = mecha, \ + .in_incr = input_incr, \ + .in = input, \ + .in_len = ARRAY_SIZE(input), \ + .out = output, \ + .out_len = ARRAY_SIZE(output), \ + .multiple_incr = incr, \ + } + +#define CKTEST_CMAC_TEST(key, mecha, input_incr, input, output, incr) { \ + .attr_key = key, \ + .attr_count = ARRAY_SIZE(key), \ + .mechanism = mecha, \ + .in_incr = input_incr, \ + .in = input, \ + .in_len = 0, \ + .out = output, \ + .out_len = ARRAY_SIZE(output), \ + .multiple_incr = incr, \ + } + +static const struct mac_test cktest_mac_cases[] = { + CKTEST_CMAC_TEST(cktest_aes_cmac_key1, &cktest_aes_cmac_mechanism, + 0, NULL, mac_cmac_vect1_out, false), + CKTEST_CMAC_TEST(cktest_aes_cmac_key2, &cktest_aes_cmac_mechanism, + 0, NULL, mac_cmac_vect5_out, false), + CKTEST_CMAC_TEST(cktest_aes_cmac_key3, &cktest_aes_cmac_mechanism, + 0, NULL, mac_cmac_vect9_out, false), + CKTEST_MAC_TEST(cktest_hmac_md5_key, &cktest_hmac_md5_mechanism, + 4, mac_data_md5_in1, mac_data_md5_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha1_key, &cktest_hmac_sha1_mechanism, + 5, mac_data_sha1_in1, mac_data_sha1_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha224_key, &cktest_hmac_sha224_mechanism, + 8, mac_data_sha224_in1, mac_data_sha224_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha256_key1, &cktest_hmac_sha256_mechanism, + 1, mac_data_sha256_in1, mac_data_sha256_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha256_key2, &cktest_hmac_sha256_mechanism, + 7, mac_data_sha256_in2, mac_data_sha256_out2, false), + CKTEST_MAC_TEST(cktest_hmac_sha384_key, &cktest_hmac_sha384_mechanism, + 11, mac_data_sha384_in1, mac_data_sha384_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha512_key, &cktest_hmac_sha512_mechanism, + 13, mac_data_sha512_in1, mac_data_sha512_out1, false), + CKTEST_CMAC_TEST(cktest_aes_cmac_key1, + &cktest_aes_cmac_general_mechanism, 0, NULL, + mac_cmac_vect1_out, false), + CKTEST_CMAC_TEST(cktest_aes_cmac_key2, + &cktest_aes_cmac_general_mechanism, 0, NULL, + mac_cmac_vect5_out, false), + CKTEST_CMAC_TEST(cktest_aes_cmac_key3, + &cktest_aes_cmac_general_mechanism, 0, NULL, + mac_cmac_vect9_out, false), + CKTEST_MAC_TEST(cktest_hmac_md5_key, + &cktest_hmac_general_md5_mechanism, 4, + mac_data_md5_in1, mac_data_md5_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha1_key, + &cktest_hmac_general_sha1_mechanism, 5, + mac_data_sha1_in1, mac_data_sha1_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha224_key, + &cktest_hmac_general_sha224_mechanism, 8, + mac_data_sha224_in1, mac_data_sha224_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha256_key1, + &cktest_hmac_general_sha256_mechanism, 1, + mac_data_sha256_in1, mac_data_sha256_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha256_key2, + &cktest_hmac_general_sha256_mechanism, 7, + mac_data_sha256_in2, mac_data_sha256_out2, false), + CKTEST_MAC_TEST(cktest_hmac_sha384_key, + &cktest_hmac_general_sha384_mechanism, 11, + mac_data_sha384_in1, mac_data_sha384_out1, false), + CKTEST_MAC_TEST(cktest_hmac_sha512_key, + &cktest_hmac_general_sha512_mechanism, 13, + mac_data_sha512_in1, mac_data_sha512_out1, false), +}; + +static bool ckm_is_hmac_general(struct mac_test const *test) +{ + switch (test->mechanism->mechanism) { + case CKM_AES_CMAC_GENERAL: + case CKM_MD5_HMAC_GENERAL: + case CKM_SHA_1_HMAC_GENERAL: + case CKM_SHA224_HMAC_GENERAL: + case CKM_SHA256_HMAC_GENERAL: + case CKM_SHA384_HMAC_GENERAL: + case CKM_SHA512_HMAC_GENERAL: + return true; + default: + return false; + } +} + +static size_t get_mac_test_len(struct mac_test const *test) +{ + if (ckm_is_hmac_general(test)) + return (size_t)cktest_general_mechanism_hmac_len; + + return test->out_len; +} + +static void xtest_pkcs11_test_1008(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION; + CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE; + uint8_t out[512] = { 0 }; + CK_ULONG out_size = 0; + struct mac_test const *test = NULL; + size_t n = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_close_lib; + + for (n = 0; n < ARRAY_SIZE(cktest_mac_cases); n++) { + + test = &cktest_mac_cases[n]; + Do_ADBG_BeginSubCase(c, "Sign case %zu algo (%s)", n, + ckm2str(test->mechanism->mechanism)); + + rv = C_CreateObject(session, test->attr_key, test->attr_count, + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + /* Test signature in 1 step */ + if (test->in != NULL) { + rv = C_SignInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Pass input buffer of size 0 */ + rv = C_SignUpdate(session, + (void *)test->in, 0); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_SignUpdate(session, + (void *)test->in, test->in_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Test too short buffer case */ + out_size = 1; + rv = C_SignFinal(session, out, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto err_destr_obj; + + /* + * Test NULL buffer case with size as 0 + * to get the out_size + */ + out_size = 0; + rv = C_SignFinal(session, NULL, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* + * Test NULL buffer case with size as non-zero + * to get the out_size + */ + out_size = 42; + rv = C_SignFinal(session, NULL, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Get to full output */ + memset(out, 0, out_size); + rv = C_SignFinal(session, out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + (void)ADBG_EXPECT_BUFFER(c, test->out, + get_mac_test_len(test), + out, out_size); + } + + /* Test 2 step update signature */ + rv = C_SignInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + if (test->in != NULL) { + rv = C_SignUpdate(session, + (void *)test->in, test->in_incr); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_SignUpdate(session, + (void *)(test->in + test->in_incr), + test->in_len - test->in_incr); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + } + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + + rv = C_SignFinal(session, out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + (void)ADBG_EXPECT_BUFFER(c, test->out, + get_mac_test_len(test), out, + out_size); + + /* Test 3 signature in one shot */ + if (test->in != NULL) { + rv = C_SignInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Test too short buffer case */ + out_size = 1; + rv = C_Sign(session,(void *)test->in, test->in_len, + out, &out_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto err_destr_obj; + + /* + * Test NULL buffer case with size as 0 + * to get the out_size + */ + out_size = 0; + rv = C_Sign(session, (void *)test->in, test->in_len, + NULL, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* + * Test NULL buffer case with size as non-zero + * to get the out_size + */ + out_size = 42; + rv = C_Sign(session, (void *)test->in, test->in_len, + NULL, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Get to full output */ + memset(out, 0, out_size); + rv = C_Sign(session,(void *)test->in, test->in_len, + out, &out_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + (void)ADBG_EXPECT_BUFFER(c, test->out, + get_mac_test_len(test), + out, out_size); + } + + rv = C_DestroyObject(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + } + goto out; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); +err: + Do_ADBG_EndSubCase(c, NULL); +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +err_close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1008, xtest_pkcs11_test_1008, + "PKCS11: Check Compliance of C_Sign - HMAC algorithms"); + +static void xtest_pkcs11_test_1009(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION; + CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE; + struct mac_test const *test = NULL; + size_t n = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_close_lib; + + for (n = 0; n < ARRAY_SIZE(cktest_mac_cases); n++) { + + test = &cktest_mac_cases[n]; + Do_ADBG_BeginSubCase(c, "Verify case %zu algo (%s)", n, + ckm2str(test->mechanism->mechanism)); + + rv = C_CreateObject(session, test->attr_key, test->attr_count, + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + /* Test Verification in 1 step */ + if (test->in != NULL) { + rv = C_VerifyInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Pass input buffer with size 0 - No affect */ + rv = C_VerifyUpdate(session, (void *)test->in, 0); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyUpdate(session, (void *)test->in, + test->in_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyFinal(session, + (void *)test->out, + get_mac_test_len(test)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + } + + /* Test 2 step update verification*/ + rv = C_VerifyInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + if (test->in != NULL) { + rv = C_VerifyUpdate(session, + (void *)test->in, test->in_incr); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyUpdate(session, + (void *)(test->in + test->in_incr), + test->in_len - test->in_incr); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + } + + rv = C_VerifyFinal(session, (void *)test->out, + get_mac_test_len(test)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Error as Operation has already completed */ + rv = C_Verify(session, + (void *)test->in, test->in_len, + (void *)test->out, get_mac_test_len(test)); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, + rv)) + goto err_destr_obj; + + /* Test 3 verification in one shot */ + if (test->in != NULL) { + rv = C_VerifyInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, + (void *)test->in, test->in_len, + (void *)test->out, + get_mac_test_len(test)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Try calling Verify again */ + rv = C_Verify(session, + (void *)test->in, test->in_len, + (void *)test->out, + get_mac_test_len(test)); + if (!ADBG_EXPECT_CK_RESULT(c, + CKR_OPERATION_NOT_INITIALIZED, + rv)) + goto err_destr_obj; + } + + /* + * Test 4 verification + * Error - Signature Length Range with C_VerifyFinal + */ + if (test->in != NULL) { + rv = C_VerifyInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyUpdate(session, (void *)test->in, + test->in_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyFinal(session, (void *)test->out, 3); + if (!ADBG_EXPECT_CK_RESULT(c, + ckm_is_hmac_general(test) ? + CKR_OK : + CKR_SIGNATURE_LEN_RANGE, + rv)) + goto err_destr_obj; + } + + /* + * Test 5 verification + * Error - Signature Length Range with C_Verify + */ + if (test->in != NULL) { + rv = C_VerifyInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, + (void *)test->in, test->in_len, + (void *)test->out, 0); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE, + rv)) + goto err_destr_obj; + + rv = C_VerifyInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, + (void *)test->in, test->in_len, + (void *)test->out, + TEE_MAX_HASH_SIZE + 1); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE, + rv)) + goto err_destr_obj; + } + + /* Test 6 verification - Invalid Operation sequence */ + if (test->in != NULL) { + rv = C_VerifyInit(session, test->mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, + (void *)test->in, test->in_len, + (void *)test->out, + get_mac_test_len(test)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* Init session has already terminated with C_Verify */ + rv = C_VerifyUpdate(session, (void *)test->in, + test->in_len); + if (!ADBG_EXPECT_CK_RESULT(c, + CKR_OPERATION_NOT_INITIALIZED, + rv)) + goto err_destr_obj; + } + + rv = C_DestroyObject(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + } + goto out; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); +err: + Do_ADBG_EndSubCase(c, NULL); +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +err_close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1009, xtest_pkcs11_test_1009, + "PKCS11: Check Compliance of C_Verify - HMAC Algorithms"); + +/* Bad key type */ +static CK_ATTRIBUTE cktest_generate_gensecret_object_error1[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, +}; + +/* Missing VALUE_LEN */ +static CK_ATTRIBUTE cktest_generate_gensecret_object_error2[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_GENERIC_SECRET}, + sizeof(CK_KEY_TYPE) }, +}; + +/* Bad object class */ +static CK_ATTRIBUTE cktest_generate_gensecret_object_error3[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_DATA}, sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_GENERIC_SECRET}, + sizeof(CK_KEY_TYPE) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, +}; + +/* Invalid template with CKA_LOCAL */ +static CK_ATTRIBUTE cktest_generate_gensecret_object_error4[] = { + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, + { CKA_LOCAL, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, +}; + +/* Valid template to generate a generic secret */ +static CK_ATTRIBUTE cktest_generate_gensecret_object_valid1[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_GENERIC_SECRET}, + sizeof(CK_KEY_TYPE) }, + { CKA_SIGN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, +}; + +/* Valid template to generate a generic secret with only VALUE_LEN */ +static CK_ATTRIBUTE cktest_generate_gensecret_object_valid2[] = { + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, + { CKA_SIGN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, +}; + + +/* Valid template to generate an all AES purpose key */ +static CK_ATTRIBUTE cktest_generate_aes_object[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) }, + { CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, +}; + +static void xtest_pkcs11_test_1010(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE; + struct mac_test test_sign = CKTEST_MAC_TEST(cktest_hmac_md5_key, + &cktest_hmac_md5_mechanism, + 4, mac_data_md5_in1, + mac_data_md5_out1, false); + uint8_t out[512] = { 0 }; + CK_ULONG out_len = 512; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* + * Generate Generic Secret key using invalid templates + */ + Do_ADBG_BeginSubCase(c, "Generate Secret Key with Invalid Templates"); + + /* NULL Template with !null template length */ + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, NULL, + 3, &key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) + goto err; + + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + cktest_generate_gensecret_object_error1, + ARRAY_SIZE(cktest_generate_gensecret_object_error1), + &key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv)) + goto err; + + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + cktest_generate_gensecret_object_error2, + ARRAY_SIZE(cktest_generate_gensecret_object_error2), + &key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCOMPLETE, rv)) + goto err; + + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + cktest_generate_gensecret_object_error3, + ARRAY_SIZE(cktest_generate_gensecret_object_error3), + &key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv)) + goto err; + + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + cktest_generate_gensecret_object_error4, + ARRAY_SIZE(cktest_generate_gensecret_object_error4), + &key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Generate a Generic Secret object. + * Try to encrypt with, it should fail... + */ + Do_ADBG_BeginSubCase(c, "Generate Generic Secret Key - Try Encrypting"); + + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + cktest_generate_gensecret_object_valid1, + ARRAY_SIZE(cktest_generate_gensecret_object_valid1), + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_FUNCTION_NOT_PERMITTED, rv)) + goto err_destr_obj; + + rv = C_DestroyObject(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Generate a Generic Secret object. + * Try to sign with it, it should pass... + */ + Do_ADBG_BeginSubCase(c, "Generate Generic Secret Key - Try Signing"); + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + cktest_generate_gensecret_object_valid2, + ARRAY_SIZE(cktest_generate_gensecret_object_valid2), + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + rv = C_SignInit(session, test_sign.mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Sign(session, (void *)test_sign.in, test_sign.in_len, + (void *)out, &out_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_DestroyObject(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Generate a 128 bit AES Secret Key. + * Try to encrypt with, it should pass... + */ + Do_ADBG_BeginSubCase(c, "Generate AES Key - Try Encrypting"); + + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + cktest_generate_aes_object, + ARRAY_SIZE(cktest_generate_aes_object), + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_EncryptFinal(session, NULL, NULL); + /* Only check that the operation is no more active */ + if (!ADBG_EXPECT_TRUE(c, rv != CKR_BUFFER_TOO_SMALL)) + goto err; + + rv = C_DestroyObject(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + goto out; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); +err: + Do_ADBG_EndSubCase(c, NULL); +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1010, xtest_pkcs11_test_1010, + "PKCS11: Key Generation"); + +static CK_RV create_data_object(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE *obj_handle, + CK_BBOOL token, CK_BBOOL private, + const char *label) +{ + CK_OBJECT_CLASS class = CKO_DATA; + CK_ATTRIBUTE object_template[] = { + { CKA_CLASS, &class, sizeof(class) }, + { CKA_TOKEN, &token, sizeof(token) }, + { CKA_PRIVATE, &private, sizeof(private) }, + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + }; + + return C_CreateObject(session, object_template, + ARRAY_SIZE(object_template), obj_handle); +} + +static CK_RV test_find_objects(ADBG_Case_t *c, CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR find_template, + CK_ULONG attr_count, + CK_OBJECT_HANDLE_PTR obj_found, + CK_ULONG obj_count, + CK_ULONG expected_cnt) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_ULONG hdl_count = 0; + + rv = C_FindObjectsInit(session, find_template, attr_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return rv; + + rv = C_FindObjects(session, obj_found, obj_count, &hdl_count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return rv; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, hdl_count, ==, expected_cnt)) + return CKR_GENERAL_ERROR; + + rv = C_FindObjectsFinal(session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return rv; + + return rv; +} + +static void destroy_persistent_objects(ADBG_Case_t *c, CK_SLOT_ID slot) +{ + uint32_t rv = CKR_GENERAL_ERROR; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE; + CK_ULONG count = 1; + CK_ATTRIBUTE cktest_find_all_token_objs[] = { + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + /* Login to destroy private objects */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + rv = C_FindObjectsInit(session, cktest_find_all_token_objs, + ARRAY_SIZE(cktest_find_all_token_objs)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + + while (1) { + rv = C_FindObjects(session, &obj_hdl, 1, &count); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto bail; + if (!count) + break; + + rv = C_DestroyObject(session, obj_hdl); + ADBG_EXPECT_CK_OK(c, rv); + } + + rv = C_FindObjectsFinal(session); + ADBG_EXPECT_CK_OK(c, rv); + + rv = C_Logout(session); + ADBG_EXPECT_CK_OK(c, rv); + +bail: + rv = C_CloseSession(session); + ADBG_EXPECT_CK_OK(c, rv); +} + +static void xtest_pkcs11_test_1011(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE obj_hdl[10] = { }; + CK_OBJECT_HANDLE obj_found[10] = { }; + const char *label = "Common Label"; + CK_ULONG hdl_count = 0; + size_t n = 0; + uint32_t i = 0; + uint32_t object_id = 0; + bool logged_in = false; + CK_ATTRIBUTE find_template[] = { + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + }; + CK_ATTRIBUTE find_token_template[] = { + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE find_session_template[] = { + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + { CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + }; + CK_BBOOL bToken = CK_FALSE; + CK_ATTRIBUTE get_attr_template[] = { + { CKA_TOKEN, &bToken, sizeof(bToken) }, + }; + + for (n = 0; n < ARRAY_SIZE(obj_hdl); n++) + obj_hdl[n] = CK_INVALID_HANDLE; + for (n = 0; n < ARRAY_SIZE(obj_found); n++) + obj_found[n] = CK_INVALID_HANDLE; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* + * Sub test: Create Session Public/Private, + * Token Public/Private objects and find them + */ + Do_ADBG_BeginSubCase(c, "Find created Data objects when logged in"); + + /* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(session, &obj_hdl[object_id++], CK_FALSE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(session, &obj_hdl[object_id++], CK_TRUE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE + * Expected error as User not logged in + */ + rv = create_data_object(session, &obj_hdl[object_id], CK_TRUE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto out; + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + logged_in = true; + + /* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(session, &obj_hdl[object_id++], CK_TRUE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(session, &obj_hdl[object_id++], CK_FALSE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = test_find_objects(c, session, find_template, + ARRAY_SIZE(find_template), + obj_found, ARRAY_SIZE(obj_found), 4); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Check if object handles returned when creating objects with this + * session are still valid + */ + for (i = 0; i < object_id; i++) { + rv = C_GetAttributeValue(session, obj_hdl[i], get_attr_template, + ARRAY_SIZE(get_attr_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + } + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Pass NULL template with count as 0. All objects should + * get returned + */ + Do_ADBG_BeginSubCase(c, "Find all objects by passing NULL template"); + + rv = test_find_objects(c, session, NULL, 0, obj_found, + ARRAY_SIZE(obj_found), 4); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: finalize search without getting the handles found + */ + Do_ADBG_BeginSubCase(c, "Initiate and finalize straight a search"); + + rv = C_FindObjectsInit(session, find_template, + ARRAY_SIZE(find_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_FindObjectsFinal(session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Check if object handles returned when creating objects with this + * session are still valid + */ + for (i = 0; i < object_id; i++) { + rv = C_GetAttributeValue(session, obj_hdl[i], get_attr_template, + ARRAY_SIZE(get_attr_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + } + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Logout and find objects. We will find only public + * objects (2) + */ + Do_ADBG_BeginSubCase(c, "Find created Data objects when logged out"); + + rv = C_Logout(session); + ADBG_EXPECT_CK_OK(c, rv); + + logged_in = false; + + rv = test_find_objects(c, session, find_template, + ARRAY_SIZE(find_template), + obj_found, ARRAY_SIZE(obj_found), 2); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test + */ + Do_ADBG_BeginSubCase(c, "Find objects 1 by 1 and match handles"); + + for (n = 0; n < ARRAY_SIZE(obj_found); n++) + obj_found[n] = CK_INVALID_HANDLE; + + rv = C_FindObjectsInit(session, find_template, + ARRAY_SIZE(find_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_FindObjects(session, obj_found, 1, &hdl_count); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, hdl_count, ==, 1) || + !ADBG_EXPECT_TRUE(c, (obj_found[0] == obj_hdl[0]) || + (obj_found[0] == obj_hdl[1]))) + goto out; + + rv = C_FindObjects(session, &obj_found[1], 1, &hdl_count); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, hdl_count, ==, 1) || + !ADBG_EXPECT_TRUE(c, (obj_found[1] == obj_hdl[0]) || + (obj_found[1] == obj_hdl[1])) || + !ADBG_EXPECT_TRUE(c, (obj_found[1] != obj_found[0]))) + goto out; + + rv = C_FindObjects(session, obj_found, 1, &hdl_count); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, hdl_count, ==, 0)) + goto out; + + rv = C_FindObjectsFinal(session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Find objects with CKA_TOKEN=TRUE + */ + Do_ADBG_BeginSubCase(c, "Find persistent objects"); + + rv = test_find_objects(c, session, find_token_template, + ARRAY_SIZE(find_token_template), + obj_found, ARRAY_SIZE(obj_found), 1); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Find only session objects + */ + Do_ADBG_BeginSubCase(c, "Find session objects"); + + rv = test_find_objects(c, session, find_session_template, + ARRAY_SIZE(find_session_template), + obj_found, ARRAY_SIZE(obj_found), 1); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: + */ + Do_ADBG_BeginSubCase(c, "Login again and find Data objects"); + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + logged_in = true; + + rv = test_find_objects(c, session, find_template, + ARRAY_SIZE(find_template), + obj_found, ARRAY_SIZE(obj_found), 3); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Logout(session); + ADBG_EXPECT_CK_OK(c, rv); + + logged_in = false; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Close session and open new session, find objects + * without logging and after logging + */ + Do_ADBG_BeginSubCase(c, "Find objects from brand new session"); + + rv = C_CloseSession(session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto destr_obj; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto destr_obj; + + rv = test_find_objects(c, session, find_template, + ARRAY_SIZE(find_template), + obj_found, ARRAY_SIZE(obj_found), 1); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + logged_in = true; + + rv = test_find_objects(c, session, find_template, + ARRAY_SIZE(find_template), + obj_found, ARRAY_SIZE(obj_found), 2); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Logout(session); + ADBG_EXPECT_CK_OK(c, rv); + + logged_in = false; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: invalid call cases + */ + Do_ADBG_BeginSubCase(c, "Invalid cases"); + + rv = C_FindObjectsFinal(session); + ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv); + + rv = C_FindObjects(session, + obj_found, ARRAY_SIZE(obj_found), &hdl_count); + ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv); + + rv = C_FindObjectsInit(session, find_template, + ARRAY_SIZE(find_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_FindObjectsInit(session, find_template, + ARRAY_SIZE(find_template)); + ADBG_EXPECT_COMPARE_UNSIGNED(c, rv, !=, CKR_OK); + + rv = C_FindObjectsFinal(session); + ADBG_EXPECT_CK_OK(c, rv); + + rv = C_FindObjectsInit(session, find_template, + ARRAY_SIZE(find_template)); + ADBG_EXPECT_CK_OK(c, rv); + + /* + * Intentionally do not finalize the active object search. It should be + * released together with the session closure. + */ + Do_ADBG_EndSubCase(c, NULL); + +out: + if (logged_in) + ADBG_EXPECT_CK_OK(c, C_Logout(session)); + + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); + +destr_obj: + destroy_persistent_objects(c, slot); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1011, xtest_pkcs11_test_1011, + "PKCS11: Test Find Objects"); + +static void xtest_pkcs11_test_1012(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE key_hdl = CK_INVALID_HANDLE; + size_t i = 0; + + CK_OBJECT_CLASS obj_class = CKO_DATA; + CK_BBOOL obj_token = CK_FALSE; + CK_BBOOL obj_private = CK_FALSE; + uint8_t obj_value[5] = { 1, 2, 3, 4, 5 }; + const char *obj_label = "Label"; + + CK_ATTRIBUTE object_template[] = { + { CKA_CLASS, &obj_class, sizeof(obj_class) }, + { CKA_TOKEN, &obj_token, sizeof(obj_token) }, + { CKA_PRIVATE, &obj_private, sizeof(obj_private) }, + { CKA_VALUE, obj_value, sizeof(obj_value) }, + { CKA_LABEL, (CK_UTF8CHAR_PTR)obj_label, strlen(obj_label) }, + }; + + CK_OBJECT_CLASS secret_class = CKO_SECRET_KEY; + CK_BBOOL secret_token = CK_FALSE; + CK_BBOOL secret_private = CK_FALSE; + CK_KEY_TYPE secret_key_type = CKK_GENERIC_SECRET; + CK_ULONG secret_len = 32; + CK_MECHANISM_TYPE secret_allowed_mecha[] = { CKM_SHA_1_HMAC, + CKM_SHA224_HMAC, + CKM_SHA256_HMAC }; + + CK_ATTRIBUTE secret_template[] = { + { CKA_CLASS, &secret_class, sizeof(secret_class) }, + { CKA_TOKEN, &secret_token, sizeof(secret_token) }, + { CKA_PRIVATE, &secret_private, sizeof(secret_private) }, + { CKA_KEY_TYPE, &secret_key_type, sizeof(secret_key_type) }, + { CKA_VALUE_LEN, &secret_len, sizeof(secret_len) }, + { CKA_ALLOWED_MECHANISMS, secret_allowed_mecha, + sizeof(secret_allowed_mecha) } + }; + + CK_BBOOL g_token = CK_TRUE; + CK_BBOOL g_private = CK_TRUE; + CK_OBJECT_CLASS g_class = ~0; + uint8_t g_value[128] = { 0 }; + CK_MECHANISM_TYPE g_mecha_list[10] = { 0 }; + + uint8_t *data_ptr = NULL; + + CK_ATTRIBUTE get_attr_template_bc[] = { + { CKA_TOKEN, &g_token, sizeof(g_token) }, + { CKA_CLASS, &g_class, sizeof(g_class) }, + }; + + CK_ATTRIBUTE get_attr_template_cb[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_TOKEN, &g_token, sizeof(g_token) }, + }; + + CK_ATTRIBUTE get_attr_template_query_bc[] = { + { CKA_TOKEN, NULL, 0 }, + { CKA_CLASS, NULL, 0 }, + }; + + CK_ATTRIBUTE get_attr_template_query_cb[] = { + { CKA_CLASS, NULL, 0 }, + { CKA_TOKEN, NULL, 0 }, + }; + + CK_ATTRIBUTE get_attr_template_ve[] = { + { CKA_VALUE, &g_value, sizeof(obj_value) }, + }; + + CK_ATTRIBUTE get_attr_template_vl[] = { + { CKA_VALUE, &g_value, sizeof(g_value) }, + }; + + CK_ATTRIBUTE get_attr_template_bvecb[] = { + { CKA_TOKEN, &g_token, sizeof(g_token) }, + { CKA_VALUE, &g_value, sizeof(obj_value) }, + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_TOKEN, &g_private, sizeof(g_private) }, + }; + + CK_ATTRIBUTE get_attr_template_bvlcb[] = { + { CKA_TOKEN, &g_token, sizeof(g_token) }, + { CKA_VALUE, &g_value, sizeof(g_value) }, + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_TOKEN, &g_private, sizeof(g_private) }, + }; + + CK_ATTRIBUTE get_attr_template_am[] = { + { CKA_ALLOWED_MECHANISMS, &g_mecha_list, sizeof(g_mecha_list) }, + }; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */ + rv = C_CreateObject(session, object_template, + ARRAY_SIZE(object_template), &obj_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Sub test: Test Boolean (1 byte) + object class (CK_ULONG) + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - boolean + class"); + g_token = CK_TRUE; + g_class = ~0; + + rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_bc, + ARRAY_SIZE(get_attr_template_bc)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_DATA); + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: object class (CK_ULONG) + Test Boolean (1 byte) + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - class + boolean"); + g_token = CK_TRUE; + g_class = ~0; + + rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_cb, + ARRAY_SIZE(get_attr_template_cb)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_DATA); + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Query size boolean (1 byte) + object class (CK_ULONG) + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - query size boolean + class"); + g_token = CK_TRUE; + g_class = ~0; + + rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_query_bc, + ARRAY_SIZE(get_attr_template_query_bc)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, + get_attr_template_query_bc[0].ulValueLen, ==, 1); + ADBG_EXPECT_COMPARE_UNSIGNED(c, + get_attr_template_query_bc[1].ulValueLen, ==, sizeof(CK_ULONG)); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Query size object class (CK_ULONG) + boolean (1 byte) + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - query size class + boolean"); + g_token = CK_TRUE; + g_class = ~0; + + rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_query_cb, + ARRAY_SIZE(get_attr_template_query_cb)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, + get_attr_template_query_cb[0].ulValueLen, ==, sizeof(CK_ULONG)); + ADBG_EXPECT_COMPARE_UNSIGNED(c, + get_attr_template_query_cb[1].ulValueLen, ==, 1); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: value with exact size + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - value with exact size buffer"); + memset(g_value, 0xCC, sizeof(g_value)); + + rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_ve, + ARRAY_SIZE(get_attr_template_ve)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_ve[0].ulValueLen, ==, sizeof(obj_value)); + ADBG_EXPECT_EQUAL(c, g_value, obj_value, sizeof(obj_value)); + for (i = sizeof(obj_value); i < sizeof(g_value); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_value[i], ==, 0xCC)) + break; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: value with larger buffer + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - value with larger buffer"); + memset(g_value, 0xCC, sizeof(g_value)); + + rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_vl, + ARRAY_SIZE(get_attr_template_vl)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_vl[0].ulValueLen, ==, sizeof(obj_value)); + ADBG_EXPECT_EQUAL(c, g_value, obj_value, sizeof(obj_value)); + for (i = sizeof(obj_value); i < sizeof(g_value); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_value[i], ==, 0xCC)) + break; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: bool + value with exact size + class + bool + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - bool + value with exact size + class + bool"); + memset(g_value, 0xCC, sizeof(g_value)); + g_token = CK_TRUE; + g_private = CK_TRUE; + g_class = ~0; + + rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_bvecb, + ARRAY_SIZE(get_attr_template_bvecb)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_bvecb[1].ulValueLen, + ==, sizeof(obj_value)); + ADBG_EXPECT_EQUAL(c, g_value, obj_value, sizeof(obj_value)); + for (i = sizeof(obj_value); i < sizeof(g_value); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_value[i], ==, 0xCC)) + break; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_DATA); + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE); + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: bool + value with larger buffer + class + bool + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - bool + value with larger buffer + class + bool"); + memset(g_value, 0xCC, sizeof(g_value)); + g_token = CK_TRUE; + g_private = CK_TRUE; + g_class = ~0; + + rv = C_GetAttributeValue(session, obj_hdl, get_attr_template_bvlcb, + ARRAY_SIZE(get_attr_template_bvlcb)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_bvlcb[1].ulValueLen, + ==, sizeof(obj_value)); + ADBG_EXPECT_EQUAL(c, g_value, obj_value, sizeof(obj_value)); + for (i = sizeof(obj_value); i < sizeof(g_value); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_value[i], ==, 0xCC)) + break; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_DATA); + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE); + ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE); + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: allowed mechanism list + */ + Do_ADBG_BeginSubCase(c, "Get Attribute - allowed mechanism list"); + memset(g_mecha_list, 0xCC, sizeof(g_mecha_list)); + + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + secret_template, ARRAY_SIZE(secret_template), + &key_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetAttributeValue(session, key_hdl, get_attr_template_am, + ARRAY_SIZE(get_attr_template_am)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, get_attr_template_am[0].ulValueLen, ==, + sizeof(secret_allowed_mecha)); + + for (i = 0; i < sizeof(secret_allowed_mecha) / sizeof(*secret_allowed_mecha); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, g_mecha_list[i], ==, secret_allowed_mecha[i])) + break; + + data_ptr = (uint8_t *)g_mecha_list; + for (i = sizeof(secret_allowed_mecha); i < sizeof(g_mecha_list); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, data_ptr[i], ==, 0xCC)) + break; + + Do_ADBG_EndSubCase(c, NULL); + +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); + +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1012, xtest_pkcs11_test_1012, + "PKCS11: Serializer tests"); + +static void xtest_pkcs11_test_1013(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE rw_session = CK_INVALID_HANDLE; + CK_SESSION_HANDLE ro_session = CK_INVALID_HANDLE; + CK_FLAGS rw_session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_FLAGS ro_session_flags = CKF_SERIAL_SESSION; + CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE; + const char *label = "Dummy Objects"; + bool ro_logged_in = false; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Open a RW session */ + rv = C_OpenSession(slot, rw_session_flags, NULL, 0, &rw_session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Open a RO session */ + rv = C_OpenSession(slot, ro_session_flags, NULL, 0, &ro_session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* + * Sub test: Check object creation from a R/O Public session + */ + Do_ADBG_BeginSubCase(c, "Create objects in R/O Public Session"); + + /* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(ro_session, &obj_hdl, CK_FALSE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(ro_session, &obj_hdl, CK_FALSE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto out; + + /* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(ro_session, &obj_hdl, CK_TRUE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv)) + goto out; + + /* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(ro_session, &obj_hdl, CK_TRUE, + CK_TRUE, label); + /* For Token object creation, SESSION_READ_ONLY will take priority */ + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Check access for a R/W Public session + */ + Do_ADBG_BeginSubCase(c, "Create objects in R/O Public Session"); + + /* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(rw_session, &obj_hdl, CK_FALSE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(rw_session, &obj_hdl, CK_FALSE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto out; + + /* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(rw_session, &obj_hdl, CK_TRUE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(rw_session, &obj_hdl, CK_TRUE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Check access for a R/O User session + */ + Do_ADBG_BeginSubCase(c, "Create objects in R/O User Session"); + + /* Login to Test Token */ + rv = C_Login(ro_session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ro_logged_in = true; + + /* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(ro_session, &obj_hdl, CK_FALSE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(ro_session, &obj_hdl, CK_FALSE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(ro_session, &obj_hdl, CK_TRUE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv)) + goto out; + + /* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(ro_session, &obj_hdl, CK_TRUE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Check access for a R/W User session + */ + Do_ADBG_BeginSubCase(c, "Create objects in R/W User Session"); + + /* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(rw_session, &obj_hdl, CK_FALSE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(rw_session, &obj_hdl, CK_FALSE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(rw_session, &obj_hdl, CK_TRUE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(rw_session, &obj_hdl, CK_TRUE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Log out */ + ADBG_EXPECT_CK_OK(c, C_Logout(ro_session)); + ro_logged_in = false; + + /* Close RO session */ + ADBG_EXPECT_CK_OK(c, C_CloseSession(ro_session)); + ro_session = CK_INVALID_HANDLE; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Sub test: Check access for a R/W SO session + */ + Do_ADBG_BeginSubCase(c, "Create objects in R/W SO Session"); + + /* Login as security officer in RW session */ + rv = C_Login(rw_session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Session Public Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(rw_session, &obj_hdl, CK_FALSE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto logout; + + /* Session Private Obj CKA_TOKEN = CK_FALSE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(rw_session, &obj_hdl, CK_FALSE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto logout; + + /* Token Public Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_FALSE */ + rv = create_data_object(rw_session, &obj_hdl, CK_TRUE, + CK_FALSE, label); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto logout; + + /* Token Private Obj CKA_TOKEN = CK_TRUE, CKA_PRIVATE = CK_TRUE */ + rv = create_data_object(rw_session, &obj_hdl, CK_TRUE, + CK_TRUE, label); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto logout; + +logout: + ADBG_EXPECT_CK_OK(c, C_Logout(rw_session)); +out: + if (ro_logged_in) + ADBG_EXPECT_CK_OK(c, C_Logout(ro_session)); + + if (ro_session != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_CloseSession(ro_session)); + + ADBG_EXPECT_CK_OK(c, C_CloseSession(rw_session)); + + Do_ADBG_EndSubCase(c, NULL); + + destroy_persistent_objects(c, slot); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); + +} +ADBG_CASE_DEFINE(pkcs11, 1013, xtest_pkcs11_test_1013, + "PKCS11: Object creation upon session type"); + +static void xtest_pkcs11_test_1014(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE; + const char *id = "1"; + const char *label = "Dummy Objects"; + const char *new_label = "New Object lable"; + size_t n = 0; + char *g_label[100] = { }; + char *g_id[100] = { }; + CK_MECHANISM_TYPE secret_allowed_mecha[] = { CKM_SHA_1_HMAC, + CKM_SHA224_HMAC, + CKM_SHA256_HMAC }; + CK_ATTRIBUTE secret_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_COPYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_DESTROYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_GENERIC_SECRET}, + sizeof(CK_KEY_TYPE) }, + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + { CKA_VALUE, (void *)cktest_aes128_key, sizeof(cktest_aes128_key) }, + { CKA_SIGN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_ALLOWED_MECHANISMS, secret_allowed_mecha, + sizeof(secret_allowed_mecha) }, + }; + CK_BBOOL g_derive = CK_FALSE; + CK_BBOOL g_sign = CK_FALSE; + CK_BBOOL g_verify = CK_FALSE; + CK_BBOOL g_encrypt = CK_FALSE; + CK_BBOOL g_decrypt = CK_FALSE; + CK_BBOOL g_wrap = CK_FALSE; + CK_BBOOL g_unwrap = CK_FALSE; + CK_ULONG g_len = 0; + CK_ATTRIBUTE get_template[] = { + { CKA_LABEL, (CK_UTF8CHAR_PTR)g_label, sizeof(g_label) }, + { CKA_ID, (CK_BYTE_PTR)g_id, sizeof(g_id) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_SIGN, &g_sign, sizeof(g_sign) }, + { CKA_VERIFY, &g_verify, sizeof(g_verify) }, + { CKA_ENCRYPT, &g_encrypt, sizeof(g_encrypt) }, + { CKA_DECRYPT, &g_decrypt, sizeof(g_decrypt) }, + { CKA_WRAP, &g_wrap, sizeof(g_wrap) }, + { CKA_UNWRAP, &g_unwrap, sizeof(g_unwrap) }, + { CKA_VALUE_LEN, &g_len, sizeof(g_len) }, + }; + CK_ATTRIBUTE set_template[] = { + { CKA_LABEL, (CK_UTF8CHAR_PTR)new_label, strlen(new_label) }, + { CKA_ID, (CK_BYTE_PTR)id, strlen(id) }, + { CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_WRAP, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_ENCRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + /* CKA_SENSITIVE -> CK_FALSE to CK_TRUE is allowed */ + { CKA_SENSITIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + /* CKA_EXTRACTABLE -> CK_TRUE to CK_FALSE is allowed */ + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + /* CKA_COPYABLE -> CK_TRUE to CK_FALSE is allowed */ + { CKA_COPYABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE set_inv_template1[] = { + /* Attributes Not Modifiable */ + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_DATA}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_LOCAL, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_ALWAYS_SENSITIVE, &(CK_BBOOL){CK_FALSE}, + sizeof(CK_BBOOL) }, + { CKA_NEVER_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, + sizeof(CK_BBOOL) }, + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_DESTROYABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + /* Change not allowed from CK_TRUE -> CK_FALSE */ + { CKA_SENSITIVE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + /* Change not allowed from CK_FALSE -> CK_TRUE */ + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_COPYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE set_inv_template2[] = { + { CKA_APPLICATION, (CK_UTF8CHAR_PTR)label, sizeof(label) }, + }; + CK_ATTRIBUTE set_trusted_template[] = { + { CKA_TRUSTED, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Open a RW session */ + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Create a secret key object */ + rv = C_CreateObject(session, secret_key_template, + ARRAY_SIZE(secret_key_template), &obj_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + Do_ADBG_BeginSubCase(c, "Set attributes on secret key object"); + + rv = C_GetAttributeValue(session, obj_hdl, get_template, + ARRAY_SIZE(get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_BUFFER(c, label, strlen(label), g_label, + get_template[0].ulValueLen) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_len, ==, 16) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, get_template[1].ulValueLen, ==, 0)) + goto out; + + rv = C_SetAttributeValue(session, obj_hdl, set_template, + ARRAY_SIZE(set_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + get_template[0].ulValueLen = sizeof(g_label); + get_template[1].ulValueLen = sizeof(g_id); + rv = C_GetAttributeValue(session, obj_hdl, get_template, + ARRAY_SIZE(get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_BUFFER(c, new_label, strlen(new_label), g_label, + get_template[0].ulValueLen) || + !ADBG_EXPECT_BUFFER(c, id, strlen(id), g_id, + get_template[1].ulValueLen) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_FALSE)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test Invalid template with R/O Attributes"); + + for (n = 0; n < ARRAY_SIZE(set_inv_template1); n++) { + rv = C_SetAttributeValue(session, obj_hdl, + &set_inv_template1[n], 1); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_READ_ONLY, rv)) + goto out; + } + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test Invalid template with Invalid Attribute"); + + rv = C_SetAttributeValue(session, obj_hdl, set_inv_template2, + ARRAY_SIZE(set_inv_template2)); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_TYPE_INVALID, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Set CKA_TRUSTED with and w/o SO Login"); + + rv = C_SetAttributeValue(session, obj_hdl, set_trusted_template, + ARRAY_SIZE(set_trusted_template)); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_READ_ONLY, rv)) + goto out; + + /* Login as SO in RW session */ + rv = C_Login(session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_SetAttributeValue(session, obj_hdl, set_trusted_template, + ARRAY_SIZE(set_trusted_template)); + ADBG_EXPECT_CK_OK(c, rv); + + ADBG_EXPECT_CK_OK(c, C_Logout(session)); +out: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, obj_hdl)); + + Do_ADBG_EndSubCase(c, NULL); + +close_session: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); + +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1014, xtest_pkcs11_test_1014, + "PKCS11: Test C_SetAttributeValue()"); + +static void xtest_pkcs11_test_1015(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE rw_session = CK_INVALID_HANDLE; + CK_SESSION_HANDLE ro_session = CK_INVALID_HANDLE; + CK_FLAGS rw_session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_FLAGS ro_session_flags = CKF_SERIAL_SESSION; + CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE obj_hdl_ro = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE obj_hdl_cp = CK_INVALID_HANDLE; + const char *label = "Dummy Objects"; + CK_ATTRIBUTE secret_key_create_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_COPYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_DESTROYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_VALUE, (void *)cktest_aes128_key, sizeof(cktest_aes128_key) }, + }; + CK_ATTRIBUTE secret_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_COPYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_DESTROYABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, + }; + CK_BBOOL g_token = CK_FALSE; + CK_BBOOL g_private = CK_FALSE; + CK_BBOOL g_modify = CK_FALSE; + CK_BBOOL g_copy = CK_FALSE; + CK_BBOOL g_destroy = CK_FALSE; + CK_BBOOL g_extract = CK_FALSE; + CK_BBOOL g_sensitive = CK_FALSE; + CK_BBOOL g_nextract = CK_FALSE; + CK_BBOOL g_asensitive = CK_FALSE; + CK_BBOOL g_local = CK_FALSE; + CK_BYTE g_value[16] = { }; + CK_ATTRIBUTE get_template[] = { + { CKA_TOKEN, &g_token, sizeof(g_token) }, + { CKA_PRIVATE, &g_private, sizeof(g_private) }, + { CKA_MODIFIABLE, &g_modify, sizeof(g_modify) }, + { CKA_COPYABLE, &g_copy, sizeof(g_copy) }, + { CKA_DESTROYABLE, &g_destroy, sizeof(g_destroy) }, + { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, + { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, + { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, + { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + }; + CK_ATTRIBUTE get_value_template[] = { + { CKA_VALUE, &g_value, sizeof(g_value) } + }; + CK_ATTRIBUTE copy_template[] = { + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_MODIFIABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE copy_template_inv[] = { + { CKA_APPLICATION, (CK_UTF8CHAR_PTR)label, sizeof(label) }, + }; + CK_ATTRIBUTE copy_template_priv[] = { + { CKA_PRIVATE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE set_template[] = { + { CKA_COPYABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + }; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Open a RW session */ + rv = C_OpenSession(slot, rw_session_flags, NULL, 0, &rw_session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Open a RO session */ + rv = C_OpenSession(slot, ro_session_flags, NULL, 0, &ro_session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + /* + * All objects in this test are session objects hence released at + * session closure on test completion. + */ + + /* Generate a secret key object in rw session */ + rv = C_GenerateKey(rw_session, &cktest_aes_keygen_mechanism, + secret_key_template, + ARRAY_SIZE(secret_key_template), &obj_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + /* Check its attribute values */ + rv = C_GetAttributeValue(rw_session, obj_hdl, get_template, + ARRAY_SIZE(get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_modify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_copy, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_destroy, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE)) + goto close_session; + + /* Check that we can get (secret) CKA_VALUE */ + get_value_template[0].ulValueLen = sizeof(g_value); + rv = C_GetAttributeValue(rw_session, obj_hdl, get_value_template, + ARRAY_SIZE(get_value_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, get_value_template[0].ulValueLen, + ==, sizeof(g_value))) + goto close_session; + + /* Create a secret key object in ro session*/ + rv = C_CreateObject(ro_session, secret_key_create_template, + ARRAY_SIZE(secret_key_create_template), &obj_hdl_ro); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + /* + * Duplicate the object generated in RW session using C_GenerateKey() to + * another object. Pass Template as NULL and test the attributes of + * new created object. + */ + Do_ADBG_BeginSubCase(c, "Copy Local Obj with NULL Template"); + rv = C_CopyObject(rw_session, obj_hdl, NULL, 0, &obj_hdl_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Check its attribute values, should match the original object. + * CKA_LOCAL shall be TRUE even in copied object as original object + * was generated using C_GenerateKey() + */ + rv = C_GetAttributeValue(rw_session, obj_hdl_cp, get_template, + ARRAY_SIZE(get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_modify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_copy, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_destroy, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE)) + goto out; + + rv = C_DestroyObject(rw_session, obj_hdl_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + obj_hdl_cp = CK_INVALID_HANDLE; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Duplicate the object generated in RO session using C_CreateObject() + * to another object. Pass Template as NULL and test the attributes of + * new created object. + */ + Do_ADBG_BeginSubCase(c, "Copy a non-local object with NULL Template"); + + /* Copy ro session object */ + rv = C_CopyObject(ro_session, obj_hdl_ro, NULL, 0, &obj_hdl_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Check its attribute values, should match the original object. + * CKA_LOCAL shall be FALSE even in copied object as original object + * was generated using C_CreateObject() + */ + rv = C_GetAttributeValue(ro_session, obj_hdl_cp, get_template, + ARRAY_SIZE(get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_private, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_modify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_copy, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_destroy, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE)) + goto out; + + rv = C_DestroyObject(ro_session, obj_hdl_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + obj_hdl_cp = CK_INVALID_HANDLE; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Test copying object with a valid template and check if attributes + * get modified as indicated in the template. Checks modification of + * attributes like CKA_TOKEN, CKA_MODIFIABLE which were not modifiable + * via C_SetAttributeValue(). Also modifies the CKA_SENSITIVE, + * CKA_EXTRACTABLE and checks corresponding values of RO attributes + * CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE. + */ + Do_ADBG_BeginSubCase(c, "Copy Object with Valid Template"); + + /* + * Copy Session Object as a Token object + * Properties CKA_MODIFIABLE turned to FALSE + * CKA_EXTRACTABLE changed from TRUE to FALSE + * CKA_NEVER_EXTRACTABLE should be FALSE. + * CKA_SENSITIVE set to TRUE + * However CKA_ALWAYS_SENSITIVE should be FALSE + */ + rv = C_CopyObject(rw_session, obj_hdl, copy_template, + ARRAY_SIZE(copy_template), &obj_hdl_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Check the changed attribute values */ + rv = C_GetAttributeValue(rw_session, obj_hdl_cp, get_template, + ARRAY_SIZE(get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_modify, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE)) + goto out; + + /* Check that we cannot anymore get (secret) CKA_VALUE */ + get_value_template[0].ulValueLen = sizeof(g_value); + rv = C_GetAttributeValue(rw_session, obj_hdl_cp, get_value_template, + ARRAY_SIZE(get_value_template)); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_SENSITIVE, rv) || + !(get_value_template[0].ulValueLen == CK_UNAVAILABLE_INFORMATION)) + goto close_session; + + /* + * The copied object has CKA_MODIFIABLE set to FALSE. Check if + * call to C_SetAttributeValue() returns CKR_ACTION_PROHIBITED + */ + rv = C_SetAttributeValue(rw_session, obj_hdl_cp, set_template, + ARRAY_SIZE(set_template)); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ACTION_PROHIBITED, rv)) + goto out; + + rv = C_DestroyObject(rw_session, obj_hdl_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + obj_hdl_cp = CK_INVALID_HANDLE; + + Do_ADBG_EndSubCase(c, NULL); + + /* + * Test changing the CKA_PRIVATE to TRUE when copying object. + * Fails when user is not logged in. Passes after user logs in + */ + Do_ADBG_BeginSubCase(c, "Copy Object as a Private Object"); + + /* The first attempt will fail as user is not logged in */ + rv = C_CopyObject(rw_session, obj_hdl, copy_template_priv, + ARRAY_SIZE(copy_template_priv), &obj_hdl_cp); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto out; + + /* Login to Test Token and repeat*/ + rv = C_Login(rw_session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Try copying a public object to a private object - should pass */ + rv = C_CopyObject(rw_session, obj_hdl, copy_template_priv, + ARRAY_SIZE(copy_template_priv), &obj_hdl_cp); + if (!ADBG_EXPECT_CK_OK(c, rv)) { + ADBG_EXPECT_CK_OK(c, C_Logout(rw_session)); + goto out; + } + + if (!ADBG_EXPECT_CK_OK(c, C_Logout(rw_session))) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Copy Object with Invalid Template"); + + rv = C_CopyObject(rw_session, obj_hdl, copy_template_inv, + ARRAY_SIZE(copy_template_inv), &obj_hdl_cp); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_TYPE_INVALID, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Copy Object with COPYABLE false"); + + rv = C_SetAttributeValue(rw_session, obj_hdl, set_template, + ARRAY_SIZE(set_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_CopyObject(rw_session, obj_hdl, copy_template, + ARRAY_SIZE(copy_template), &obj_hdl_cp); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ACTION_PROHIBITED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Copy session object to token in RO session"); + + rv = C_CopyObject(ro_session, obj_hdl_ro, copy_template, + ARRAY_SIZE(copy_template), &obj_hdl_cp); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SESSION_READ_ONLY, rv)) + goto out; + +out: + Do_ADBG_EndSubCase(c, NULL); + + /* Destroy any token objects which may have been created */ + destroy_persistent_objects(c, slot); + +close_session: + /* Closing session will also destroy all session objects */ + if (ro_session != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_CloseSession(ro_session)); + + ADBG_EXPECT_CK_OK(c, C_CloseSession(rw_session)); + +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1015, xtest_pkcs11_test_1015, + "PKCS11: Test C_CopyObject()"); + +static void xtest_pkcs11_test_1016(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + uint8_t buffer[64] = { 0 }; + size_t i = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + Do_ADBG_BeginSubCase(c, "Seed random bytes"); + + memset(buffer, 0xCC, sizeof(buffer)); + + rv = C_SeedRandom(session, buffer, sizeof(buffer)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Seed random bytes with zero length buffer"); + + rv = C_SeedRandom(session, buffer, 0); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_SeedRandom(session, NULL, 0); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Generate random bytes"); + + memset(buffer, 0xCC, sizeof(buffer)); + + rv = C_GenerateRandom(session, buffer, 61); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Verify that end of buffer is still 0xCC */ + for (i = 61; i < sizeof(buffer); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, buffer[i], ==, 0xCC)) + break; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Generate random bytes with zero length buffer"); + + memset(buffer, 0xCC, sizeof(buffer)); + + rv = C_GenerateRandom(session, buffer, 0); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Verify that whole buffer is still 0xCC */ + for (i = 0; i < sizeof(buffer); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, buffer[i], ==, 0xCC)) + break; + + rv = C_GenerateRandom(session, NULL, 0); + ADBG_EXPECT_CK_OK(c, rv); + +out: + Do_ADBG_EndSubCase(c, NULL); + + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); + +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1016, xtest_pkcs11_test_1016, + "PKCS11: Random number generator tests"); + +static CK_RV derive_sym_key(CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE parent_key, + CK_MECHANISM_TYPE mechanism, size_t data_len, + CK_OBJECT_HANDLE_PTR derv_key_hdl, size_t key_len, + CK_OBJECT_CLASS key_class, CK_KEY_TYPE key_type, + CK_BBOOL sensitive, CK_BBOOL extble) +{ + CK_RV rv = CKR_GENERAL_ERROR; + uint8_t buffer[512] = { 0 }; + uint8_t iv[16] = { 0 }; + CK_MECHANISM mech_derive = { 0 }; + CK_KEY_DERIVATION_STRING_DATA key_derv_param = { 0 }; + CK_AES_CBC_ENCRYPT_DATA_PARAMS aes_cbc_param = { }; + CK_ATTRIBUTE derived_key_template[] = { + { CKA_CLASS, &key_class, sizeof(key_class) }, + { CKA_KEY_TYPE, &key_type, sizeof(key_type) }, + { CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &sensitive, sizeof(sensitive) }, + { CKA_EXTRACTABLE, &extble, sizeof(extble) }, + { CKA_VALUE_LEN, &key_len, sizeof(key_len) } + }; + + if (data_len > sizeof(buffer)) + return rv; + + switch (mechanism) { + case CKM_AES_ECB_ENCRYPT_DATA: + key_derv_param.pData = buffer; + key_derv_param.ulLen = data_len; + mech_derive.mechanism = mechanism; + mech_derive.pParameter = &key_derv_param; + mech_derive.ulParameterLen = sizeof(key_derv_param); + break; + case CKM_AES_CBC_ENCRYPT_DATA: + memcpy(aes_cbc_param.iv, iv, 16); + aes_cbc_param.pData = buffer; + aes_cbc_param.length = data_len; + mech_derive.mechanism = mechanism; + mech_derive.pParameter = &aes_cbc_param; + mech_derive.ulParameterLen = sizeof(aes_cbc_param); + break; + case CKM_AES_ECB: + /* Not a derivation algorithm */ + mech_derive.mechanism = mechanism; + mech_derive.pParameter = NULL; + mech_derive.ulParameterLen = 0; + break; + default: + return rv; + } + + /* Don't use VALUE_LEN parameter if key_len passed is 0 */ + if (key_len) + rv = C_DeriveKey(session, &mech_derive, parent_key, + derived_key_template, + ARRAY_SIZE(derived_key_template), + derv_key_hdl); + else + /* last attribute in template is the derived key size */ + rv = C_DeriveKey(session, &mech_derive, parent_key, + derived_key_template, + ARRAY_SIZE(derived_key_template) - 1, + derv_key_hdl); + return rv; +} + +static void xtest_pkcs11_test_1017(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE derv_key_hdl = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE aes_key1 = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE aes_key2 = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE aes_key_enc = CK_INVALID_HANDLE; + size_t data_len = 0; + size_t key_len = 0; + CK_BBOOL g_extract = CK_FALSE; + CK_BBOOL g_sensitive = CK_FALSE; + CK_BBOOL g_nextract = CK_FALSE; + CK_BBOOL g_asensitive = CK_FALSE; + CK_BBOOL g_local = CK_FALSE; + CK_OBJECT_CLASS g_class = CKO_VENDOR_DEFINED; + CK_KEY_TYPE g_key_type = CKK_VENDOR_DEFINED; + uint8_t g_val[516] = { 0 }; + CK_ULONG secret_len = 0; + CK_ATTRIBUTE get_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, + { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, + { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, + { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_VALUE_LEN, &secret_len, sizeof(secret_len) }, + /* + * CKA_VALUE should remain last attribute in template, + * in this test case as we check the length returned + * from last index of the get_template in this test. + */ + { CKA_VALUE, g_val, sizeof(g_val) }, + }; + uint32_t idx = ARRAY_SIZE(get_template) - 1; + CK_ATTRIBUTE parent_template1[] = { + { CKA_SENSITIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, + { CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE parent_template2[] = { + { CKA_SENSITIVE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, + { CKA_ENCRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE parent_template_wo_derive[] = { + { CKA_SENSITIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, + }; + CK_ATTRIBUTE parent_template_w_enc_der[] = { + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, + { CKA_ENCRYPT, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + }; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* + * Parent AES Key 1 + * SENSITIVE = TRUE, EXTRACTABLE = FALSE + * ALWAYS_SENSITIVE = TRUE, NEVER_EXTRACTABLE = TRUE + */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + parent_template1, ARRAY_SIZE(parent_template1), + &aes_key1); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + /* + * Parent AES Key 2 + * SENSITIVE = FALSE, EXTRACTABLE = TRUE + * ALWAYS_SENSITIVE = FALSE, NEVER_EXTRACTABLE = FALSE + */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + parent_template2, ARRAY_SIZE(parent_template2), + &aes_key2); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + Do_ADBG_BeginSubCase(c, "Derive Generic secret - AES-ECB Mechanism"); + + /* + * Use AES key 1 as Parent key + * 1. VALUE_LEN attribute not given in derivation template. Length + * of key should be same as that of data length. + * 2. Derivation template has SENSITIVE = TRUE, EXTRACTABLE = FALSE + * Parent key has ALWAYS_SENSITIVE = TRUE, NEVER_EXTRACTABLE = TRUE + * So derived key, ALWAYS_SENSITIVE will be same as SENSITIVE and + * NEVER_EXTRACTABLE will be opposite of EXTRACTABLE + * 3. LOCAL should be false + */ + data_len = 512; + key_len = 0; + rv = derive_sym_key(session, aes_key1, CKM_AES_ECB_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_GENERIC_SECRET, CK_TRUE, CK_FALSE); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetAttributeValue(session, derv_key_hdl, get_template, + ARRAY_SIZE(get_template) - 1); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, secret_len, ==, data_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, + CKK_GENERIC_SECRET) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE)) + goto out; + + rv = C_DestroyObject(session, derv_key_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Derive AES key using AES-EBC"); + + /* + * Use AES key 2 as Parent key + * 1. VALUE_LEN < DATA_LEN, Derived key should have VALUE_LEN key size + * 2. Derivation template has SENSITIVE = TRUE, EXTRACTABLE = FALSE + * Parent key has ALWAYS_SENSITIVE = FALSE, NEVER_EXTRACTABLE = FALSE + * So derived key, ALWAYS_SENSITIVE will be FALSE and + * NEVER_EXTRACTABLE will be FALSE + * 3. LOCAL should be false + */ + data_len = 32; + key_len = 16; + rv = derive_sym_key(session, aes_key2, CKM_AES_ECB_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_AES, CK_TRUE, CK_FALSE); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* This being a SENSITIVE object, we can't get the VALUE */ + rv = C_GetAttributeValue(session, derv_key_hdl, get_template, + ARRAY_SIZE(get_template) - 1); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, secret_len, ==, key_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE)) + goto out; + + rv = C_DestroyObject(session, derv_key_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Derive AES key using AES-CBC"); + + /* + * Use AES key 1 as Parent key + * 1. VALUE_LEN = DATA_LEN, Derived key should have VALUE_LEN key size + * 2. Derivation template has SENSITIVE = FALSE, EXTRACTABLE = FALSE + * Parent key has ALWAYS_SENSITIVE = TRUE, NEVER_EXTRACTABLE = TRUE + * So derived key, ALWAYS_SENSITIVE will be same as SENSITIVE and + * NEVER_EXTRACTABLE will be opposite of EXTRACTABLE + * 3. LOCAL should be false + */ + data_len = 32; + key_len = 32; + rv = derive_sym_key(session, aes_key1, CKM_AES_CBC_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_AES, CK_FALSE, CK_FALSE); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetAttributeValue(session, derv_key_hdl, get_template, + ARRAY_SIZE(get_template) - 1); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, secret_len, ==, key_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE)) + goto out; + + rv = C_DestroyObject(session, derv_key_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Derive Generic secret key using AES-CBC"); + /* + * Use AES key 2 as Parent key + * 1. VALUE_LEN < DATA_LEN, Derived key should have VALUE_LEN key size + * 2. Derivation template has SENSITIVE = FALSE, EXTRACTABLE = TRUE + * Parent key has ALWAYS_SENSITIVE = TRUE, NEVER_EXTRACTABLE = TRUE + * So derived key, ALWAYS_SENSITIVE will be same as SENSITIVE and + * NEVER_EXTRACTABLE will be opposite of EXTRACTABLE + * 3. LOCAL should be false + */ + data_len = 512; + key_len = 256; + rv = derive_sym_key(session, aes_key2, CKM_AES_CBC_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_GENERIC_SECRET, CK_FALSE, CK_TRUE); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetAttributeValue(session, derv_key_hdl, get_template, + ARRAY_SIZE(get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, get_template[idx].ulValueLen, ==, + key_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, secret_len, ==, key_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, + CKK_GENERIC_SECRET) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE)) + goto out; + + rv = C_DestroyObject(session, derv_key_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Invalid parameters during derivation"); + + /* Length of data used for derivation < key length */ + data_len = 16; + key_len = 32; + rv = derive_sym_key(session, aes_key1, CKM_AES_ECB_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_AES, CK_FALSE, CK_TRUE); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv)) + goto out; + + /* Data is not multiple of 16 */ + data_len = 18; + key_len = 32; + rv = derive_sym_key(session, aes_key1, CKM_AES_ECB_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_AES, CK_FALSE, CK_TRUE); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv)) + goto out; + + /* Wrong Mechanism */ + rv = derive_sym_key(session, aes_key1, CKM_AES_ECB, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_AES, CK_FALSE, CK_TRUE); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_MECHANISM_INVALID, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Failure if operation already active"); + + /* Generate an AES key which can perform Encryption */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + parent_template_w_enc_der, + ARRAY_SIZE(parent_template_w_enc_der), + &aes_key_enc); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, aes_key_enc); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Initializing the encryption operation again should not alter or + * terminate already started operation. + */ + rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, aes_key_enc); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_ACTIVE, rv)) + goto out; + + data_len = 32; + key_len = 32; + rv = derive_sym_key(session, aes_key2, CKM_AES_ECB_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_AES, CK_FALSE, CK_TRUE); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_ACTIVE, rv)) + goto out; + + rv = C_EncryptFinal(session, NULL, NULL); + /* Only check that the operation is no more active */ + if (!ADBG_EXPECT_TRUE(c, rv != CKR_BUFFER_TOO_SMALL)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Failure if parent key CKA_ENCRYPT is TRUE"); + + data_len = 32; + key_len = 32; + rv = derive_sym_key(session, aes_key_enc, CKM_AES_ECB_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_AES, CK_FALSE, CK_TRUE); + /* + * Not strictly expecting FUNCTION_FAILED but expecting a failure + * as we have added a restriction that keys with attribute CKA_ENCRYPT + * set can't be used for derivation. + */ + if (!ADBG_EXPECT_CK_RESULT(c, CKR_FUNCTION_FAILED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Failure if parent key CKA_DERIVE is FALSE"); + + rv = C_DestroyObject(session, aes_key1); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + parent_template_wo_derive, + ARRAY_SIZE(parent_template_wo_derive), + &aes_key1); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + data_len = 32; + key_len = 32; + rv = derive_sym_key(session, aes_key1, CKM_AES_ECB_ENCRYPT_DATA, + data_len, &derv_key_hdl, key_len, CKO_SECRET_KEY, + CKK_AES, CK_FALSE, CK_TRUE); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_TYPE_INCONSISTENT, rv)) + goto out; + +out: + Do_ADBG_EndSubCase(c, NULL); + +close_session: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); + +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1017, xtest_pkcs11_test_1017, + "PKCS11: AES Key Derivation tests"); + +/* Digest test patterns */ +static const char digest_test_pattern[] = "The quick brown fox jumps over the lazy dog"; +static const char digest_test_pattern_empty[] = ""; + +/* MD5 checksums for digest test patterns */ +static const uint8_t digest_test_pattern_md5[] = { + 0x9e, 0x10, 0x7d, 0x9d, 0x37, 0x2b, 0xb6, 0x82, 0x6b, 0xd8, 0x1d, 0x35, + 0x42, 0xa4, 0x19, 0xd6 +}; +static const uint8_t digest_test_pattern_empty_md5[] = { + 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, + 0xec, 0xf8, 0x42, 0x7e +}; + +/* SHA-1 checksums for digest test patterns */ +static const uint8_t digest_test_pattern_sha1[] = { + 0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e, 0xe1, + 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12 +}; +static const uint8_t digest_test_pattern_empty_sha1[] = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, + 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 +}; + +/* SHA-224 checksums for digest test patterns */ +static const uint8_t digest_test_pattern_sha224[] = { + 0x73, 0x0e, 0x10, 0x9b, 0xd7, 0xa8, 0xa3, 0x2b, 0x1c, 0xb9, 0xd9, 0xa0, + 0x9a, 0xa2, 0x32, 0x5d, 0x24, 0x30, 0x58, 0x7d, 0xdb, 0xc0, 0xc3, 0x8b, + 0xad, 0x91, 0x15, 0x25 +}; +static const uint8_t digest_test_pattern_empty_sha224[] = { + 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47, 0x61, 0x02, 0xbb, + 0x28, 0x82, 0x34, 0xc4, 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, + 0xc5, 0xb3, 0xe4, 0x2f +}; + +/* SHA-256 checksums for digest test patterns */ +static const uint8_t digest_test_pattern_sha256[] = { + 0xd7, 0xa8, 0xfb, 0xb3, 0x07, 0xd7, 0x80, 0x94, 0x69, 0xca, 0x9a, 0xbc, + 0xb0, 0x08, 0x2e, 0x4f, 0x8d, 0x56, 0x51, 0xe4, 0x6d, 0x3c, 0xdb, 0x76, + 0x2d, 0x02, 0xd0, 0xbf, 0x37, 0xc9, 0xe5, 0x92 +}; +static const uint8_t digest_test_pattern_empty_sha256[] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, + 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 +}; + +/* SHA-384 checksums for digest test patterns */ +static const uint8_t digest_test_pattern_sha384[] = { + 0xca, 0x73, 0x7f, 0x10, 0x14, 0xa4, 0x8f, 0x4c, 0x0b, 0x6d, 0xd4, 0x3c, + 0xb1, 0x77, 0xb0, 0xaf, 0xd9, 0xe5, 0x16, 0x93, 0x67, 0x54, 0x4c, 0x49, + 0x40, 0x11, 0xe3, 0x31, 0x7d, 0xbf, 0x9a, 0x50, 0x9c, 0xb1, 0xe5, 0xdc, + 0x1e, 0x85, 0xa9, 0x41, 0xbb, 0xee, 0x3d, 0x7f, 0x2a, 0xfb, 0xc9, 0xb1 +}; +static const uint8_t digest_test_pattern_empty_sha384[] = { + 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, + 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, + 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, + 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b +}; + +/* SHA-512 checksums for digest test patterns */ +static const uint8_t digest_test_pattern_sha512[] = { + 0x07, 0xe5, 0x47, 0xd9, 0x58, 0x6f, 0x6a, 0x73, 0xf7, 0x3f, 0xba, 0xc0, + 0x43, 0x5e, 0xd7, 0x69, 0x51, 0x21, 0x8f, 0xb7, 0xd0, 0xc8, 0xd7, 0x88, + 0xa3, 0x09, 0xd7, 0x85, 0x43, 0x6b, 0xbb, 0x64, 0x2e, 0x93, 0xa2, 0x52, + 0xa9, 0x54, 0xf2, 0x39, 0x12, 0x54, 0x7d, 0x1e, 0x8a, 0x3b, 0x5e, 0xd6, + 0xe1, 0xbf, 0xd7, 0x09, 0x78, 0x21, 0x23, 0x3f, 0xa0, 0x53, 0x8f, 0x3d, + 0xb8, 0x54, 0xfe, 0xe6 +}; +static const uint8_t digest_test_pattern_empty_sha512[] = { + 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, + 0xd6, 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, + 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, + 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, + 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, + 0xf9, 0x27, 0xda, 0x3e +}; + +#define DIGEST_TEST(_test_name, _mecha, _data, _digest) \ + { \ + .test_name = _test_name, \ + .mecha = _mecha, \ + .data = _data, \ + .data_size = sizeof(_data) - 1, \ + .digest = _digest, \ + .digest_size = sizeof(_digest) \ + } + +/* Digest simple test suite */ +static struct { + const char *test_name; + CK_MECHANISM_TYPE mecha; + const void *data; + CK_ULONG data_size; + const uint8_t *digest; + CK_ULONG digest_size; +} digest_test_patterns[] = { + DIGEST_TEST("CKM_MD5/empty", CKM_MD5, digest_test_pattern_empty, + digest_test_pattern_empty_md5), + DIGEST_TEST("CKM_MD5/test pattern", CKM_MD5, digest_test_pattern, + digest_test_pattern_md5), + DIGEST_TEST("CKM_SHA_1/empty", CKM_SHA_1, digest_test_pattern_empty, + digest_test_pattern_empty_sha1), + DIGEST_TEST("CKM_SHA_1/test pattern", CKM_SHA_1, digest_test_pattern, + digest_test_pattern_sha1), + DIGEST_TEST("CKM_SHA224/empty", CKM_SHA224, digest_test_pattern_empty, + digest_test_pattern_empty_sha224), + DIGEST_TEST("CKM_SHA224/test pattern", CKM_SHA224, digest_test_pattern, + digest_test_pattern_sha224), + DIGEST_TEST("CKM_SHA256/empty", CKM_SHA256, digest_test_pattern_empty, + digest_test_pattern_empty_sha256), + DIGEST_TEST("CKM_SHA256/test pattern", CKM_SHA256, digest_test_pattern, + digest_test_pattern_sha256), + DIGEST_TEST("CKM_SHA384/empty", CKM_SHA384, digest_test_pattern_empty, + digest_test_pattern_empty_sha384), + DIGEST_TEST("CKM_SHA384/test pattern", CKM_SHA384, digest_test_pattern, + digest_test_pattern_sha384), + DIGEST_TEST("CKM_SHA512/empty", CKM_SHA512, digest_test_pattern_empty, + digest_test_pattern_empty_sha512), + DIGEST_TEST("CKM_SHA512/test pattern", CKM_SHA512, digest_test_pattern, + digest_test_pattern_sha512), +}; + +static CK_ATTRIBUTE digest_generate_aes_object[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_AES }, sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, +}; + +static CK_ATTRIBUTE digest_generate_gensecret_object[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET }, + sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){ 32 }, sizeof(CK_ULONG) }, +}; + +static CK_ATTRIBUTE digest_data_object[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_DATA }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, +}; + +static void xtest_pkcs11_test_1018(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + bool logged_in = false; + uint8_t data[128] = { 0 }; + CK_ULONG data_size = 0; + uint8_t digest[64] = { 0 }; + CK_ULONG digest_size = 0; + const uint8_t *expect_digest = NULL; + CK_ULONG expect_digest_size = 0; + CK_MECHANISM mechanism = { CKM_MD5, NULL, 0 }; + uint8_t secret_data[128] = { 0 }; + CK_ULONG secret_data_size __maybe_unused = 0; + CK_ATTRIBUTE digest_get_secret_value[] = { + { CKA_VALUE, &secret_data, sizeof(secret_data) }, + }; + CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE; +#ifdef OPENSSL_FOUND + EVP_MD_CTX *mdctx = NULL; + unsigned char hash[EVP_MAX_MD_SIZE] = { 0 }; + unsigned int md_len = 0; + int ret = 0; +#endif + size_t i = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Test out simple successful cases with init+update+final*/ + for (i = 0; i < ARRAY_SIZE(digest_test_patterns); i++) { + Do_ADBG_BeginSubCase(c, "Simple digest tests - update - %s", + digest_test_patterns[i].test_name); + + mechanism.mechanism = digest_test_patterns[i].mecha; + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[i].data, + digest_test_patterns[i].data_size); + data_size = digest_test_patterns[i].data_size; + + expect_digest = digest_test_patterns[i].digest; + expect_digest_size = digest_test_patterns[i].digest_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestUpdate(session, data, data_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestFinal(session, digest, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, expect_digest, expect_digest_size, + digest, digest_size)) + goto out; + + /* Verify that end of buffer is still 0xCC */ + for (i = expect_digest_size; i < sizeof(digest); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest[i], ==, + 0xCC)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + } + + /* Test out simple successful cases */ + for (i = 0; i < ARRAY_SIZE(digest_test_patterns); i++) { + Do_ADBG_BeginSubCase(c, "Simple digest tests - oneshot - %s", + digest_test_patterns[i].test_name); + + mechanism.mechanism = digest_test_patterns[i].mecha; + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[i].data, + digest_test_patterns[i].data_size); + data_size = digest_test_patterns[i].data_size; + + expect_digest = digest_test_patterns[i].digest; + expect_digest_size = digest_test_patterns[i].digest_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Digest(session, data, data_size, digest, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, expect_digest, expect_digest_size, + digest, digest_size)) + goto out; + + /* Verify that end of buffer is still 0xCC */ + for (i = expect_digest_size; i < sizeof(digest); i++) + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest[i], ==, + 0xCC)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + } + + /* Test out key updates */ + + Do_ADBG_BeginSubCase(c, "Simple digest tests - AES key update - SHA-256"); + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + logged_in = true; + + /* Generate AES key */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + digest_generate_aes_object, + ARRAY_SIZE(digest_generate_aes_object), + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + memset(secret_data, 0xCC, sizeof(data)); + digest_get_secret_value[0].ulValueLen = sizeof(secret_data); + + /* Get value of generated secret for verification purposes */ + rv = C_GetAttributeValue(session, key_handle, digest_get_secret_value, + ARRAY_SIZE(digest_get_secret_value)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + secret_data_size = digest_get_secret_value[0].ulValueLen; + + /* Calculate digest with PKCS11 */ + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestUpdate(session, data, data_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestKey(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestFinal(session, digest, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Verify digest with openssl */ +#ifdef OPENSSL_FOUND + mdctx = EVP_MD_CTX_create(); + if (!ADBG_EXPECT_NOT_NULL(c, mdctx)) + goto out; + ret = EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1)) + goto out; + ret = EVP_DigestUpdate(mdctx, data, data_size); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1)) + goto out; + ret = EVP_DigestUpdate(mdctx, secret_data, secret_data_size); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1)) + goto out; + ret = EVP_DigestFinal_ex(mdctx, hash, &md_len); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1)) + goto out; + EVP_MD_CTX_destroy(mdctx); + mdctx = NULL; + + if (!ADBG_EXPECT_BUFFER(c, hash, md_len, digest, digest_size)) + goto out; +#else + Do_ADBG_Log("OpenSSL not available, skipping C_DigestKey verification"); +#endif + + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); + key_handle = CK_INVALID_HANDLE; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Simple digest tests - generic secret key update - SHA-256"); + + /* Generate generic secret key */ + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + digest_generate_gensecret_object, + ARRAY_SIZE(digest_generate_gensecret_object), + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + memset(secret_data, 0xCC, sizeof(data)); + digest_get_secret_value[0].ulValueLen = sizeof(secret_data); + + /* Get value of generated secret for verification purposes */ + rv = C_GetAttributeValue(session, key_handle, digest_get_secret_value, + ARRAY_SIZE(digest_get_secret_value)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + secret_data_size = digest_get_secret_value[0].ulValueLen; + + /* Calculate digest with PKCS11 */ + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestUpdate(session, data, data_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestKey(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestFinal(session, digest, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Verify digest with openssl */ +#ifdef OPENSSL_FOUND + mdctx = EVP_MD_CTX_create(); + if (!ADBG_EXPECT_NOT_NULL(c, mdctx)) + goto out; + ret = EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1)) + goto out; + ret = EVP_DigestUpdate(mdctx, data, data_size); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1)) + goto out; + ret = EVP_DigestUpdate(mdctx, secret_data, secret_data_size); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1)) + goto out; + ret = EVP_DigestFinal_ex(mdctx, hash, &md_len); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, ret, ==, 1)) + goto out; + EVP_MD_CTX_destroy(mdctx); + mdctx = NULL; + + if (!ADBG_EXPECT_BUFFER(c, hash, md_len, digest, digest_size)) + goto out; +#else + Do_ADBG_Log("OpenSSL not available, skipping C_DigestKey verification"); +#endif + + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); + key_handle = CK_INVALID_HANDLE; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Query digest size - C_DigestFinal"); + + mechanism.mechanism = digest_test_patterns[0].mecha; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = 0; + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + expect_digest = digest_test_patterns[0].digest; + expect_digest_size = digest_test_patterns[0].digest_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestUpdate(session, data, data_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestFinal(session, NULL, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest_size, ==, + expect_digest_size)) + goto out; + + rv = C_DigestFinal(session, digest, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, expect_digest, expect_digest_size, + digest, digest_size)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Query digest size - C_Digest"); + + mechanism.mechanism = digest_test_patterns[0].mecha; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = 0; + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + expect_digest = digest_test_patterns[0].digest; + expect_digest_size = digest_test_patterns[0].digest_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Digest(session, data, data_size, NULL, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest_size, ==, + expect_digest_size)) + goto out; + + rv = C_Digest(session, data, data_size, digest, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, expect_digest, expect_digest_size, + digest, digest_size)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Query digest size - buffer too small"); + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = 0; + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestUpdate(session, data, data_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestFinal(session, digest, &digest_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv)) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, digest_size, ==, 32)) + goto out; + + rv = C_DigestFinal(session, digest, &digest_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + /* Test bad arguments & operation terminations */ + + Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestUpdate"); + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestUpdate(session, NULL, 10); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) + goto out; + + rv = C_DigestUpdate(session, data, data_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestFinal with NULL digest"); + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestUpdate(session, data, data_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestFinal(session, NULL, NULL); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) + goto out; + + rv = C_DigestFinal(session, digest, &digest_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestFinal with digest but NULL size"); + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestUpdate(session, data, data_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestFinal(session, digest, NULL); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) + goto out; + + rv = C_DigestFinal(session, digest, &digest_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test bad arguments - C_Digest with NULL data but non-zero size"); + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Digest(session, NULL, 10, digest, &digest_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) + goto out; + + rv = C_Digest(session, data, data_size, digest, &digest_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test bad arguments - C_Digest with NULL digest"); + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Digest(session, data, data_size, NULL, NULL); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) + goto out; + + rv = C_Digest(session, data, data_size, digest, &digest_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestFinal with digest but NULL size"); + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_Digest(session, data, data_size, digest, NULL); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) + goto out; + + rv = C_Digest(session, data, data_size, digest, &digest_size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestKey with invalid key handle"); + + rv = C_CreateObject(session, digest_data_object, + ARRAY_SIZE(digest_data_object), &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestKey(session, 9999); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_HANDLE_INVALID, rv)) + goto out; + + rv = C_DigestKey(session, key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test bad arguments - C_DigestKey with non-secret key type"); + + mechanism.mechanism = CKM_SHA256; + + memset(data, 0xCC, sizeof(data)); + memset(digest, 0xCC, sizeof(digest)); + digest_size = sizeof(digest); + + memcpy(data, digest_test_patterns[0].data, + digest_test_patterns[0].data_size); + data_size = digest_test_patterns[0].data_size; + + rv = C_DigestInit(session, &mechanism); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DigestKey(session, key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_INDIGESTIBLE, rv)) + goto out; + + rv = C_DigestKey(session, key_handle); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto out; + + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); + key_handle = CK_INVALID_HANDLE; + +out: +#ifdef OPENSSL_FOUND + if (!ADBG_EXPECT_POINTER(c, NULL, mdctx)) { + Do_ADBG_Log("Unexpected failure in openssl functions: %d", + ret); + EVP_MD_CTX_destroy(mdctx); + } +#endif + + Do_ADBG_EndSubCase(c, NULL); + + if (logged_in) + ADBG_EXPECT_CK_OK(c, C_Logout(session)); + + if (key_handle != CK_INVALID_HANDLE) { + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); + key_handle = CK_INVALID_HANDLE; + } + + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); + +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1018, xtest_pkcs11_test_1018, + "PKCS11: Digest tests"); + +/** + * 0:d=0 hl=2 l= 22 cons: SEQUENCE + * 2:d=1 hl=2 l= 20 cons: SET + * 4:d=2 hl=2 l= 18 cons: SEQUENCE + * 6:d=3 hl=2 l= 3 prim: OBJECT :commonName + * 11:d=3 hl=2 l= 11 prim: UTF8STRING :common name + */ +static uint8_t subject_common_name[] = { + 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65 +}; + +/** + * 0:d=0 hl=2 l= 8 prim: OBJECT :prime256v1 + */ +static uint8_t ecdsa_nist_p256[] = { + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x07 +}; + +/** + * 0:d=0 hl=2 l= 5 prim: OBJECT :secp384r1 + */ +static uint8_t ecdsa_nist_p384[] = { + 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 +}; + +/** + * 0:d=0 hl=2 l= 5 prim: OBJECT :secp521r1 + */ +static uint8_t ecdsa_nist_p521[] = { + 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23 +}; + +#define EC_SIGN_TEST(_test_name, _mecha, _data) \ + { \ + .test_name = _test_name, \ + .mecha = _mecha, \ + .data = _data, \ + .data_size = sizeof(_data) - 1, \ + } + +/* List of elliptic curve signing multi stage digest mechas */ +static struct { + const char *test_name; + CK_MECHANISM_TYPE mecha; + const void *data; + CK_ULONG data_size; +} ec_sign_tests[] = { + EC_SIGN_TEST("CKM_ECDSA_SHA1", CKM_ECDSA_SHA1, digest_test_pattern), + EC_SIGN_TEST("CKM_ECDSA_SHA224", CKM_ECDSA_SHA224, digest_test_pattern), + EC_SIGN_TEST("CKM_ECDSA_SHA256", CKM_ECDSA_SHA256, digest_test_pattern), + EC_SIGN_TEST("CKM_ECDSA_SHA384", CKM_ECDSA_SHA384, digest_test_pattern), + EC_SIGN_TEST("CKM_ECDSA_SHA512", CKM_ECDSA_SHA512, digest_test_pattern), +}; + +static int test_ec_operations(ADBG_Case_t *c, CK_SESSION_HANDLE session, + const char *curve_name, uint8_t *curve, + size_t curve_size) +{ + CK_RV rv = CKR_GENERAL_ERROR; + + CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE; + + CK_MECHANISM mechanism = { + CKM_EC_KEY_PAIR_GEN, NULL, 0 + }; + CK_MECHANISM sign_mechanism = { + CKM_ECDSA, NULL, 0 + }; + CK_BYTE id[] = { 123 }; + + CK_ATTRIBUTE public_key_template[] = { + { CKA_ENCRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_EC_PARAMS, ecdsa_nist_p256, sizeof(ecdsa_nist_p256) } + }; + + CK_ATTRIBUTE private_key_template[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SUBJECT, subject_common_name, + sizeof(subject_common_name) }, + { CKA_ID, id, sizeof(id) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) } + }; + + CK_OBJECT_CLASS g_class = 0; + CK_KEY_TYPE g_key_type = 0; + CK_BYTE g_id[32] = { 0 }; + CK_DATE g_start_date = { 0 }; + CK_DATE g_end_date = { 0 }; + CK_BBOOL g_derive = CK_FALSE; + CK_BBOOL g_local = CK_FALSE; + CK_MECHANISM_TYPE g_keygen_mecha = 0; + CK_BYTE g_subject[64] = { 0 }; + CK_BBOOL g_encrypt = CK_FALSE; + CK_BBOOL g_verify = CK_FALSE; + CK_BBOOL g_verify_recover = CK_FALSE; + CK_BBOOL g_wrap = CK_FALSE; + CK_BBOOL g_trusted = CK_FALSE; + CK_BYTE g_public_key_info[1024] = { 0 }; + CK_BBOOL g_sensitive = CK_FALSE; + CK_BBOOL g_decrypt = CK_FALSE; + CK_BBOOL g_sign = CK_FALSE; + CK_BBOOL g_sign_recover = CK_FALSE; + CK_BBOOL g_unwrap = CK_FALSE; + CK_BBOOL g_extract = CK_FALSE; + CK_BBOOL g_asensitive = CK_FALSE; + CK_BBOOL g_nextract = CK_FALSE; + CK_BBOOL g_wrap_with_trusted = CK_FALSE; + CK_BBOOL g_always_authenticate = CK_FALSE; + + CK_ATTRIBUTE get_public_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_START_DATE, &g_start_date, sizeof(g_start_date) }, + { CKA_END_DATE, &g_end_date, sizeof(g_end_date) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_ENCRYPT, &g_encrypt, sizeof(g_encrypt) }, + { CKA_VERIFY, &g_verify, sizeof(g_verify) }, + { CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(g_verify_recover) }, + { CKA_WRAP, &g_wrap, sizeof(g_wrap) }, + { CKA_TRUSTED, &g_trusted, sizeof(g_trusted) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + CK_ATTRIBUTE get_private_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_START_DATE, &g_start_date, sizeof(g_start_date) }, + { CKA_END_DATE, &g_end_date, sizeof(g_end_date) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, + { CKA_DECRYPT, &g_decrypt, sizeof(g_decrypt) }, + { CKA_SIGN, &g_sign, sizeof(g_sign) }, + { CKA_SIGN_RECOVER, &g_sign_recover, sizeof(g_sign_recover) }, + { CKA_UNWRAP, &g_unwrap, sizeof(g_unwrap) }, + { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, + { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, + { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, + { CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(g_wrap_with_trusted) }, + { CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(g_always_authenticate) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + uint8_t signature[512] = { 0 }; + CK_ULONG signature_len = 0; + + size_t i = 0; + + Do_ADBG_BeginSubCase(c, "%s: Generate key pair", + curve_name); + + public_key_template[3].pValue = curve; + public_key_template[3].ulValueLen = curve_size; + + rv = C_GenerateKeyPair(session, &mechanism, public_key_template, + ARRAY_SIZE(public_key_template), + private_key_template, + ARRAY_SIZE(private_key_template), + &public_key, &private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + /* reset get public key template */ + memset(g_id, 0, sizeof(g_id)); + memset(g_subject, 0, sizeof(g_subject)); + memset(g_public_key_info, 0, sizeof(g_public_key_info)); + get_public_template[2].ulValueLen = sizeof(g_id); + get_public_template[8].ulValueLen = sizeof(g_subject); + get_public_template[14].ulValueLen = sizeof(g_public_key_info); + + rv = C_GetAttributeValue(session, public_key, get_public_template, + ARRAY_SIZE(get_public_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_EC) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_EC_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE)) + goto err_destr_obj; + + /* reset get private key template */ + memset(g_id, 0, sizeof(g_id)); + memset(g_subject, 0, sizeof(g_subject)); + memset(g_public_key_info, 0, sizeof(g_public_key_info)); + get_private_template[2].ulValueLen = sizeof(g_id); + get_private_template[8].ulValueLen = sizeof(g_subject); + get_private_template[19].ulValueLen = sizeof(g_public_key_info); + + rv = C_GetAttributeValue(session, private_key, get_private_template, + ARRAY_SIZE(get_private_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_EC) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_EC_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, + "%s: Sign & verify tests - oneshot - CKM_ECDSA", + curve_name); + + sign_mechanism.mechanism = CKM_ECDSA; + memset(signature, 0, sizeof(signature)); + signature_len = sizeof(signature); + + rv = C_SignInit(session, &sign_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Sign(session, (void *)digest_test_pattern_sha256, + sizeof(digest_test_pattern_sha256), (void *)signature, + &signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, (void *)digest_test_pattern_sha256, + sizeof(digest_test_pattern_sha256), (void *)signature, + signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + for (i = 0; i < ARRAY_SIZE(ec_sign_tests); i++) { + Do_ADBG_BeginSubCase(c, "%s: Sign & verify - oneshot - %s", + curve_name, ec_sign_tests[i].test_name); + + sign_mechanism.mechanism = ec_sign_tests[i].mecha; + memset(signature, 0, sizeof(signature)); + signature_len = sizeof(signature); + + rv = C_SignInit(session, &sign_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Sign(session, (void *)ec_sign_tests[i].data, + ec_sign_tests[i].data_size, + (void *)signature, &signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, (void *)ec_sign_tests[i].data, + ec_sign_tests[i].data_size, + (void *)signature, signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + } + + Do_ADBG_BeginSubCase(c, "%s: Destroy keys", curve_name); + + rv = C_DestroyObject(session, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_DestroyObject(session, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + return 1; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key)); + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key)); +err: + Do_ADBG_EndSubCase(c, NULL); + + return 0; +} + +static void xtest_pkcs11_test_1019(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + int ret = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ret = test_ec_operations(c, session, "P-256", ecdsa_nist_p256, + sizeof(ecdsa_nist_p256)); + if (!ret) + goto out; + ret = test_ec_operations(c, session, "P-384", ecdsa_nist_p384, + sizeof(ecdsa_nist_p384)); + if (!ret) + goto out; + + if (level > 0) { + ret = test_ec_operations(c, session, "P-521", ecdsa_nist_p521, + sizeof(ecdsa_nist_p521)); + if (!ret) + goto out; + } +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1019, xtest_pkcs11_test_1019, + "PKCS11: Elliptic Curve key generation and signing"); + +#define WRAPPED_TEST_KEY_SIZE 48 + +static void xtest_pkcs11_test_1020(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE wrapping_key1 = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE wrapping_key2 = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE wrapping_key_inv = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE key_sz24 = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE key_sens = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE key_inv = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE; + CK_ATTRIBUTE set_w_unw_template[] = { + { CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE set_wwt_template[] = { + { CKA_WRAP_WITH_TRUSTED, &(CK_BBOOL){ CK_TRUE }, + sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE set_trusted_template[] = { + { CKA_TRUSTED, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE wrap_template[] = { + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE unwrap_template[] = { + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE wrapping_key_template[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + { CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE wrapping_key_temp_w_indirect[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + { CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_WRAP_TEMPLATE, &wrap_template, sizeof(wrap_template) }, + { CKA_UNWRAP_TEMPLATE, &unwrap_template, + sizeof(unwrap_template) }, + }; + CK_ATTRIBUTE unwrap_template2[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_AES }, sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + }; + CK_ATTRIBUTE wrapping_key_temp_w_indirect2[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + { CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP_TEMPLATE, &unwrap_template2, + sizeof(unwrap_template2) }, + }; + CK_ATTRIBUTE wrapping_key_template_inv1[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + { CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE key_template[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + { CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE key_template_sens[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE key_template_inv1[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE key_sz24_template[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 24 }, sizeof(CK_ULONG) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE new_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET }, + sizeof(CK_KEY_TYPE) }, + { CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE}, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE new_key_template_sens[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_AES }, sizeof(CK_KEY_TYPE) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE new_key_template2[] = { + { CKA_DERIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE new_key_template3[] = { + { CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_ATTRIBUTE new_key_template4[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET }, + sizeof(CK_KEY_TYPE) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + CK_BBOOL g_extract = CK_FALSE; + CK_BBOOL g_sensitive = CK_TRUE; + CK_BBOOL g_nextract = CK_TRUE; + CK_BBOOL g_asensitive = CK_TRUE; + CK_BBOOL g_local = CK_TRUE; + CK_BBOOL g_token = CK_FALSE; + CK_BBOOL g_derive = CK_FALSE; + CK_OBJECT_CLASS g_class = CKO_VENDOR_DEFINED; + CK_KEY_TYPE g_key_type = CKK_VENDOR_DEFINED; + uint8_t g_val[WRAPPED_TEST_KEY_SIZE] = { 0 }; + CK_ULONG key_len = 0; + uint8_t g_unwrapped_val[WRAPPED_TEST_KEY_SIZE] = { 0 }; + CK_ULONG unwrapped_key_len = 0; + /* Keep last attribute as CKA_VALUE */ + CK_ATTRIBUTE get_template_unwrapped[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, + { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, + { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, + { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_TOKEN, &g_token, sizeof(g_token) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_VALUE_LEN, &unwrapped_key_len, sizeof(unwrapped_key_len) }, + { CKA_VALUE, g_unwrapped_val, sizeof(g_unwrapped_val) }, + }; + CK_ATTRIBUTE get_template[] = { + { CKA_VALUE_LEN, &key_len, sizeof(key_len) }, + { CKA_VALUE, g_val, sizeof(g_val) }, + }; + uint8_t buf[WRAPPED_TEST_KEY_SIZE] = { 0 }; + CK_ULONG size = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Wrapping Key - AES Key */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + wrapping_key_template, + ARRAY_SIZE(wrapping_key_template), &wrapping_key1); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + /* Key to be wrapped - AES key */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + key_template, ARRAY_SIZE(key_template), + &key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + Do_ADBG_BeginSubCase(c, "Test key wrap with AES ECB"); + + /* + * Test NULL buffer and NULL out_size to verify bad argument processing + */ + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key, + NULL, NULL); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv)) + goto out; + + /* + * Test NULL buffer case with size as 0 to get the out_size + */ + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key, + NULL, &size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf))) + goto out; + + /* + * Test NULL buffer case with size non zero size to get the out_size + */ + size = 1; + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key, + NULL, &size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf))) + goto out; + + /* Test short buffer */ + size = 12; + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key, + buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf))) + goto out; + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key, + buf, &size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Get the size of the original key which was wrapped in key_len. + * This will be compared to the length of the key after unwrapping. + */ + rv = C_GetAttributeValue(session, key, get_template, + ARRAY_SIZE(get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test key unwrap with AES ECB"); + + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf, + size, new_key_template, ARRAY_SIZE(new_key_template), + &unwrapped_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * The key created after unwrapping should have CKA_LOCAL = FALSE, + * CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE as FALSE. + * Default value of CKA_EXTRACTABLE if not specified in the template + * is TRUE. We have deliberately set CKA_SENSITIVE to false for + * both original key and unwrapped_key. This is done to be able to + * extract the value of keys and compare them. This is done mainly + * for testing. In actual examples, we expect CKA_SENSITIVE of keys + * to be wrapped to be TRUE. + */ + rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped, + ARRAY_SIZE(get_template_unwrapped)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_BUFFER(c, g_unwrapped_val, unwrapped_key_len, g_val, + key_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, + CKK_GENERIC_SECRET) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE)) + goto out; + + rv = C_DestroyObject(session, unwrapped_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Invalid UnWrap cases"); + + /* Failure when unwrapping as a private session key */ + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf, + size, new_key_template4, ARRAY_SIZE(new_key_template4), + &unwrapped_key); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto out; + + /* Provide incomplete template */ + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf, + size, new_key_template2, ARRAY_SIZE(new_key_template2), + &unwrapped_key); + + /* + * The error code can also be CKR_TEMPLATE_INCOMPLETE. The + * current implementation returns CKR_TEMPLATE_INCONSISTENT + */ + if (!ADBG_EXPECT_TRUE(c, rv == CKR_TEMPLATE_INCOMPLETE || + rv == CKR_TEMPLATE_INCONSISTENT)) + goto out; + + /* Try unwrapping with a key without CKA_UNWRAP */ + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, key, buf, size, + new_key_template, ARRAY_SIZE(new_key_template), + &unwrapped_key); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Invalid Wrap cases"); + + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + wrapping_key_template_inv1, + ARRAY_SIZE(wrapping_key_template_inv1), + &wrapping_key_inv); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Wrapping key used without CKA_WRAP set */ + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key_inv, + key, buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, rv)) + goto out; + + rv = C_DestroyObject(session, wrapping_key_inv); + ADBG_EXPECT_CK_OK(c, rv); + + /* Use invalid wrapping key handle */ + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key_inv, + key, buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_HANDLE_INVALID, rv)) + goto out; + + /* CKA_EXTRACTABLE attribute of the key to be wrapped is CKA_FALSE */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + key_template_inv1, ARRAY_SIZE(key_template_inv1), + &key_inv); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, + key_inv, buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_UNEXTRACTABLE, rv)) + goto out; + + rv = C_DestroyObject(session, key_inv); + ADBG_EXPECT_CK_OK(c, rv); + + /* Use invalid key handle */ + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, + key_inv, buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_HANDLE_INVALID, rv)) + goto out; + + /* Try wrapping the wrapping key */ + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, + wrapping_key1, buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_HANDLE_INVALID, rv)) + goto out; + + /* Use invalid mechanism */ + rv = C_WrapKey(session, &cktest_hmac_md5_mechanism, wrapping_key1, key, + buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_MECHANISM_INVALID, rv)) + goto out; + + /* Try wrapping when an operation is already active */ + rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key, + buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_ACTIVE, rv)) + goto out; + + rv = C_EncryptFinal(session, NULL, NULL); + /* Only check that the operation is no more active */ + if (!ADBG_EXPECT_TRUE(c, rv != CKR_BUFFER_TOO_SMALL)) + goto out; + + /* + * Try wrapping using CKK_GENERIC_SECRET when mechanism used is + * AES_ECB. Generate a secret key object in rw session. + */ + rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism, + cktest_generate_gensecret_object_valid1, + ARRAY_SIZE(cktest_generate_gensecret_object_valid1), + &key_inv); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Make the Generic secret key wrapping/unwrapping key */ + rv = C_SetAttributeValue(session, key_inv, set_w_unw_template, + ARRAY_SIZE(set_w_unw_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, key_inv, key, buf, + &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, rv)) + goto out; + + rv = C_DestroyObject(session, key_inv); + ADBG_EXPECT_CK_OK(c, rv); + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Wrap with different length key"); + + /* Generate Key of size 192 bits */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + key_sz24_template, ARRAY_SIZE(key_sz24_template), + &key_sz24); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + size = 0; + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, + key_sz24, buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32)) + goto out; + + size = 24; + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, + key_sz24, buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32)) + goto out; + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, + key_sz24, buf, &size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test Wrap/Unwrap with indirect template"); + + /* Wrapping Key with indirect templates - AES Key */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + wrapping_key_temp_w_indirect, + ARRAY_SIZE(wrapping_key_temp_w_indirect), + &wrapping_key2); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Attribute mismatch with CKA_WRAP_TEMPLATE. + * Error expected when wrapping a key whose template doesn't match with + * the CKA_WRAP_TEMPLATE in the wrapping_key. In this example, the + * CKA_WRAP_TEMPLATE expects CKA_SENSITIVE of the key to be wrapped to + * be TRUE which is not the case here. + */ + size = sizeof(buf); + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, key, + buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_HANDLE_INVALID, rv)) + goto out; + + /* Generate SENSITIVE Key */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + key_template_sens, ARRAY_SIZE(key_template_sens), + &key_sens); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, + key_sens, buf, &size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Unwrap to create key with SENSITIVE set as FALSE. + * This should fail as indirect attribute CKA_UNWRAP_TEMPLATE restricts + * creation of key with CKA_SENSITIVE as FALSE. + */ + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf, + size, new_key_template, ARRAY_SIZE(new_key_template), + &unwrapped_key); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv)) + goto out; + + /* Unwrap a wrapped sensitive key to create a SENSITIVE key */ + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf, + size, new_key_template_sens, + ARRAY_SIZE(new_key_template_sens), &unwrapped_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Get the attributes of created. Skip last attribute in + * get_template_wrapped as that is CKA_VALUE which would give an + * error for a sensitive key + */ + rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped, + ARRAY_SIZE(get_template_unwrapped) - 1); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE)) + goto out; + + if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)) || + !ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, wrapping_key2)) || + !ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_sens))) + goto out; + + /* Create wrapping key with indirect template specifying class & key */ + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + wrapping_key_temp_w_indirect2, + ARRAY_SIZE(wrapping_key_temp_w_indirect2), + &wrapping_key2); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + size = sizeof(buf); + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, key, + buf, &size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Use minimal new key template just specifying attribute of key */ + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf, + size, new_key_template2, ARRAY_SIZE(new_key_template2), + &unwrapped_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped, + ARRAY_SIZE(get_template_unwrapped) - 1); + + /* Destroy created token object */ + if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key))) + goto out; + + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE)) + goto out; + + /* + * Unwrap with NULL template when CKA_UNWRAP_TEMPLATE has all + * attributes to generate a key + */ + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf, + size, NULL, 0, &unwrapped_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped, + ARRAY_SIZE(get_template_unwrapped) - 1); + + /* Destroy created token object */ + if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key))) + goto out; + + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE)) { + goto out; + } + + /* Unwrap and try create a Private token object */ + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf, + size, new_key_template3, ARRAY_SIZE(new_key_template3), + &unwrapped_key); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Test usage of CKA_WRAP_WITH_TRUSTED"); + + /* Set Attribute WRAP_WITH_TRUSTED on the key */ + rv = C_SetAttributeValue(session, key, set_wwt_template, + ARRAY_SIZE(set_wwt_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* + * Try wrapping the key with attribute CKA_WRAP_WITH_TRUSTED with + * normal wrapping key + */ + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key, + buf, &size); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_NOT_WRAPPABLE, rv)) + goto out; + + /* Login as SO in RW session */ + rv = C_Login(session, CKU_SO, test_token_so_pin, + sizeof(test_token_so_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_SetAttributeValue(session, wrapping_key1, set_trusted_template, + ARRAY_SIZE(set_trusted_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_CK_OK(c, C_Logout(session))) + goto out; + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key, + buf, &size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + +out: + Do_ADBG_EndSubCase(c, NULL); +close_session: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); + +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1020, xtest_pkcs11_test_1020, + "PKCS11: AES Key Wrap/UnWrap tests"); + +#define RSA_SIGN_TEST(_test_name, _mecha, _data) \ + { \ + .test_name = _test_name, \ + .mecha = _mecha, \ + .data = _data, \ + .data_size = sizeof(_data) - 1, \ + } + +/* List of RSA PKCS signing multi stage digest mechanisms */ +static struct { + const char *test_name; + CK_MECHANISM_TYPE mecha; + const void *data; + CK_ULONG data_size; +} rsa_pkcs_sign_tests[] = { +#ifndef CFG_CRYPTO_SE05X + RSA_SIGN_TEST("CKM_MD5_RSA_PKCS", CKM_MD5_RSA_PKCS, + digest_test_pattern), +#endif + RSA_SIGN_TEST("CKM_SHA1_RSA_PKCS", CKM_SHA1_RSA_PKCS, + digest_test_pattern), + RSA_SIGN_TEST("CKM_SHA224_RSA_PKCS", CKM_SHA224_RSA_PKCS, + digest_test_pattern), + RSA_SIGN_TEST("CKM_SHA256_RSA_PKCS", CKM_SHA256_RSA_PKCS, + digest_test_pattern), + RSA_SIGN_TEST("CKM_SHA384_RSA_PKCS", CKM_SHA384_RSA_PKCS, + digest_test_pattern), + RSA_SIGN_TEST("CKM_SHA512_RSA_PKCS", CKM_SHA512_RSA_PKCS, + digest_test_pattern), +}; + +static int test_rsa_pkcs_operations(ADBG_Case_t *c, + CK_SESSION_HANDLE session, + const char *rsa_name, uint32_t rsa_bits) +{ + CK_RV rv = CKR_GENERAL_ERROR; + + CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE; + + CK_MECHANISM mechanism = { + CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 + }; + CK_MECHANISM sign_mechanism = { + CKM_RSA_PKCS, NULL, 0 + }; + CK_ULONG modulus_bits = 0; + CK_BYTE public_exponent[] = { 1, 0, 1 }; + CK_BYTE id[] = { 123 }; + + CK_ATTRIBUTE public_key_template[] = { + { CKA_ENCRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_ULONG) }, + { CKA_PUBLIC_EXPONENT, public_exponent, + sizeof(public_exponent) } + }; + + CK_ATTRIBUTE private_key_template[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SUBJECT, subject_common_name, + sizeof(subject_common_name) }, + { CKA_ID, id, sizeof(id) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) } + }; + + CK_OBJECT_CLASS g_class = 0; + CK_KEY_TYPE g_key_type = 0; + CK_BYTE g_id[32] = { 0 }; + CK_DATE g_start_date = { 0 }; + CK_DATE g_end_date = { 0 }; + CK_BBOOL g_derive = CK_FALSE; + CK_BBOOL g_local = CK_FALSE; + CK_MECHANISM_TYPE g_keygen_mecha = 0; + CK_BYTE g_subject[64] = { 0 }; + CK_BBOOL g_encrypt = CK_FALSE; + CK_BBOOL g_verify = CK_FALSE; + CK_BBOOL g_verify_recover = CK_FALSE; + CK_BBOOL g_wrap = CK_FALSE; + CK_BBOOL g_trusted = CK_FALSE; + CK_BYTE g_public_key_info[1024] = { 0 }; + CK_BBOOL g_sensitive = CK_FALSE; + CK_BBOOL g_decrypt = CK_FALSE; + CK_BBOOL g_sign = CK_FALSE; + CK_BBOOL g_sign_recover = CK_FALSE; + CK_BBOOL g_unwrap = CK_FALSE; + CK_BBOOL g_extract = CK_FALSE; + CK_BBOOL g_asensitive = CK_FALSE; + CK_BBOOL g_nextract = CK_FALSE; + CK_BBOOL g_wrap_with_trusted = CK_FALSE; + CK_BBOOL g_always_authenticate = CK_FALSE; + + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE get_public_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_START_DATE, &g_start_date, sizeof(g_start_date) }, + { CKA_END_DATE, &g_end_date, sizeof(g_end_date) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_ENCRYPT, &g_encrypt, sizeof(g_encrypt) }, + { CKA_VERIFY, &g_verify, sizeof(g_verify) }, + { CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(g_verify_recover) }, + { CKA_WRAP, &g_wrap, sizeof(g_wrap) }, + { CKA_TRUSTED, &g_trusted, sizeof(g_trusted) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE get_private_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_START_DATE, &g_start_date, sizeof(g_start_date) }, + { CKA_END_DATE, &g_end_date, sizeof(g_end_date) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, + { CKA_DECRYPT, &g_decrypt, sizeof(g_decrypt) }, + { CKA_SIGN, &g_sign, sizeof(g_sign) }, + { CKA_SIGN_RECOVER, &g_sign_recover, sizeof(g_sign_recover) }, + { CKA_UNWRAP, &g_unwrap, sizeof(g_unwrap) }, + { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, + { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, + { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, + { CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(g_wrap_with_trusted) }, + { CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(g_always_authenticate) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + uint8_t signature[512] = { 0 }; + CK_ULONG signature_len = 0; + + size_t i = 0; + + Do_ADBG_BeginSubCase(c, "%s: Generate key pair", rsa_name); + + modulus_bits = rsa_bits; + + rv = C_GenerateKeyPair(session, &mechanism, public_key_template, + ARRAY_SIZE(public_key_template), + private_key_template, + ARRAY_SIZE(private_key_template), + &public_key, &private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + /* reset get public key template */ + memset(g_id, 0, sizeof(g_id)); + assert(get_public_template[2].type == CKA_ID); + get_public_template[2].ulValueLen = sizeof(g_id); + + memset(g_subject, 0, sizeof(g_subject)); + assert(get_public_template[8].type == CKA_SUBJECT); + get_public_template[8].ulValueLen = sizeof(g_subject); + + memset(g_public_key_info, 0, sizeof(g_public_key_info)); + assert(get_public_template[14].type == CKA_PUBLIC_KEY_INFO); + get_public_template[14].ulValueLen = sizeof(g_public_key_info); + + rv = C_GetAttributeValue(session, public_key, get_public_template, + ARRAY_SIZE(get_public_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_RSA_PKCS_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE)) + goto err_destr_obj; + + /* reset get private key template */ + memset(g_id, 0, sizeof(g_id)); + assert(get_private_template[2].type == CKA_ID); + get_private_template[2].ulValueLen = sizeof(g_id); + + memset(g_subject, 0, sizeof(g_subject)); + assert(get_private_template[8].type == CKA_SUBJECT); + get_private_template[8].ulValueLen = sizeof(g_subject); + + memset(g_public_key_info, 0, sizeof(g_public_key_info)); + assert(get_private_template[19].type == CKA_PUBLIC_KEY_INFO); + get_private_template[19].ulValueLen = sizeof(g_public_key_info); + + rv = C_GetAttributeValue(session, private_key, get_private_template, + ARRAY_SIZE(get_private_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_RSA_PKCS_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, + "%s: Sign & verify tests - oneshot - CKM_RSA_PKCS", + rsa_name); + + sign_mechanism.mechanism = CKM_RSA_PKCS; + memset(signature, 0, sizeof(signature)); + signature_len = sizeof(signature); + + rv = C_SignInit(session, &sign_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Sign(session, (void *)digest_test_pattern_sha256, + sizeof(digest_test_pattern_sha256), (void *)signature, + &signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, (void *)digest_test_pattern_sha256, + sizeof(digest_test_pattern_sha256), (void *)signature, + signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + for (i = 0; i < ARRAY_SIZE(rsa_pkcs_sign_tests); i++) { + /* + * Note: this order of end/begin here is just to get ADBG + * SubCases in sync with error handling. + */ + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "%s: Sign & verify - oneshot - %s", + rsa_name, + rsa_pkcs_sign_tests[i].test_name); + + sign_mechanism.mechanism = rsa_pkcs_sign_tests[i].mecha; + memset(signature, 0, sizeof(signature)); + signature_len = sizeof(signature); + + rv = C_SignInit(session, &sign_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Sign(session, (void *)rsa_pkcs_sign_tests[i].data, + rsa_pkcs_sign_tests[i].data_size, + (void *)signature, &signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, (void *)rsa_pkcs_sign_tests[i].data, + rsa_pkcs_sign_tests[i].data_size, + (void *)signature, signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + } + + rv = C_DestroyObject(session, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_pub_obj; + + rv = C_DestroyObject(session, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + return 1; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key)); +err_destr_pub_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key)); +err: + Do_ADBG_EndSubCase(c, NULL); + + return 0; +} + +static void xtest_pkcs11_test_1021(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + int ret = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ret = test_rsa_pkcs_operations(c, session, "RSA-1024", 1024); + if (!ret) + goto out; + ret = test_rsa_pkcs_operations(c, session, "RSA-2048", 2048); + if (!ret) + goto out; + if (level > 0) { + ret = test_rsa_pkcs_operations(c, session, "RSA-3072", 3072); + if (!ret) + goto out; + ret = test_rsa_pkcs_operations(c, session, "RSA-4096", 4096); + if (!ret) + goto out; + } +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1021, xtest_pkcs11_test_1021, + "PKCS11: RSA PKCS key generation and signing"); + +#define RSA_PSS_HASH_SIGN_TEST(_test_name, _min_rsa_bits, _mecha, _hash_algo, _mgf_algo, \ + _salt_len, _data) \ + { \ + .test_name = _test_name, \ + .min_rsa_bits = _min_rsa_bits, \ + .mecha = _mecha, \ + .hash_algo = _hash_algo, \ + .mgf_algo = _mgf_algo, \ + .salt_len = _salt_len, \ + .data = _data, \ + .data_size = sizeof(_data), \ + } + +#define RSA_PSS_CSTR_SIGN_TEST(_test_name, _min_rsa_bits, _mecha, _hash_algo, \ + _mgf_algo, _salt_len, _data) \ + { \ + .test_name = _test_name, \ + .min_rsa_bits = _min_rsa_bits, \ + .mecha = _mecha, \ + .hash_algo = _hash_algo, \ + .mgf_algo = _mgf_algo, \ + .salt_len = _salt_len, \ + .data = _data, \ + .data_size = sizeof(_data) - 1, \ + } + +/* List of RSA PSS signing multi stage digest mechanisms */ +static struct { + const char *test_name; + uint32_t min_rsa_bits; + CK_MECHANISM_TYPE mecha; + CK_MECHANISM_TYPE hash_algo; + CK_RSA_PKCS_MGF_TYPE mgf_algo; + CK_ULONG salt_len; + const void *data; + CK_ULONG data_size; +} rsa_pss_sign_tests[] = { + RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA1", 1024, CKM_RSA_PKCS_PSS, + CKM_SHA_1, CKG_MGF1_SHA1, 20, + digest_test_pattern_sha1), + RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA1/mech", 1024, + CKM_SHA1_RSA_PKCS_PSS, CKM_SHA_1, CKG_MGF1_SHA1, + 20, digest_test_pattern), + RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA224", 1024, CKM_RSA_PKCS_PSS, + CKM_SHA224, CKG_MGF1_SHA224, 28, + digest_test_pattern_sha224), + RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA224/mech", 1024, + CKM_SHA224_RSA_PKCS_PSS, CKM_SHA224, + CKG_MGF1_SHA224, 28, digest_test_pattern), + RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA256", 1024, CKM_RSA_PKCS_PSS, + CKM_SHA256, CKG_MGF1_SHA256, 32, + digest_test_pattern_sha256), + RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA256/mech", 1024, + CKM_SHA256_RSA_PKCS_PSS, CKM_SHA256, + CKG_MGF1_SHA256, 32, digest_test_pattern), + RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA384", 1024, CKM_RSA_PKCS_PSS, + CKM_SHA384, CKG_MGF1_SHA384, 48, + digest_test_pattern_sha384), + RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA384/mech", 1024, + CKM_SHA384_RSA_PKCS_PSS, CKM_SHA384, + CKG_MGF1_SHA384, 48, digest_test_pattern), + RSA_PSS_HASH_SIGN_TEST("RSA-PSS/SHA512", 2048, CKM_RSA_PKCS_PSS, + CKM_SHA512, CKG_MGF1_SHA512, 64, + digest_test_pattern_sha512), + RSA_PSS_CSTR_SIGN_TEST("RSA-PSS/SHA512/mech", 2048, + CKM_SHA512_RSA_PKCS_PSS, CKM_SHA512, + CKG_MGF1_SHA512, 64, digest_test_pattern), +}; + +static int test_rsa_pss_operations(ADBG_Case_t *c, + CK_SESSION_HANDLE session, + const char *rsa_name, uint32_t rsa_bits) +{ + CK_RV rv = CKR_GENERAL_ERROR; + + CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE; + + CK_MECHANISM mechanism = { + CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 + }; + CK_MECHANISM sign_mechanism = { + CKM_RSA_PKCS_PSS, NULL, 0 + }; + CK_RSA_PKCS_PSS_PARAMS pss_params = { + CKM_SHA256, CKG_MGF1_SHA256, 32, + }; + CK_ULONG modulus_bits = 0; + CK_BYTE public_exponent[] = { 1, 0, 1 }; + CK_BYTE id[] = { 123 }; + + CK_ATTRIBUTE public_key_template[] = { + { CKA_ENCRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_MODULUS_BITS, &modulus_bits, sizeof(modulus_bits) }, + { CKA_PUBLIC_EXPONENT, public_exponent, + sizeof(public_exponent) } + }; + + CK_ATTRIBUTE private_key_template[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SUBJECT, subject_common_name, + sizeof(subject_common_name) }, + { CKA_ID, id, sizeof(id) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) } + }; + + CK_OBJECT_CLASS g_class = 0; + CK_KEY_TYPE g_key_type = 0; + CK_BYTE g_id[32] = { 0 }; + CK_DATE g_start_date = { 0 }; + CK_DATE g_end_date = { 0 }; + CK_BBOOL g_derive = CK_FALSE; + CK_BBOOL g_local = CK_FALSE; + CK_MECHANISM_TYPE g_keygen_mecha = 0; + CK_BYTE g_subject[64] = { 0 }; + CK_BBOOL g_encrypt = CK_FALSE; + CK_BBOOL g_verify = CK_FALSE; + CK_BBOOL g_verify_recover = CK_FALSE; + CK_BBOOL g_wrap = CK_FALSE; + CK_BBOOL g_trusted = CK_FALSE; + CK_BYTE g_public_key_info[1024] = { 0 }; + CK_BBOOL g_sensitive = CK_FALSE; + CK_BBOOL g_decrypt = CK_FALSE; + CK_BBOOL g_sign = CK_FALSE; + CK_BBOOL g_sign_recover = CK_FALSE; + CK_BBOOL g_unwrap = CK_FALSE; + CK_BBOOL g_extract = CK_FALSE; + CK_BBOOL g_asensitive = CK_FALSE; + CK_BBOOL g_nextract = CK_FALSE; + CK_BBOOL g_wrap_with_trusted = CK_FALSE; + CK_BBOOL g_always_authenticate = CK_FALSE; + + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE get_public_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_START_DATE, &g_start_date, sizeof(g_start_date) }, + { CKA_END_DATE, &g_end_date, sizeof(g_end_date) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_ENCRYPT, &g_encrypt, sizeof(g_encrypt) }, + { CKA_VERIFY, &g_verify, sizeof(g_verify) }, + { CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(g_verify_recover) }, + { CKA_WRAP, &g_wrap, sizeof(g_wrap) }, + { CKA_TRUSTED, &g_trusted, sizeof(g_trusted) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE get_private_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_START_DATE, &g_start_date, sizeof(g_start_date) }, + { CKA_END_DATE, &g_end_date, sizeof(g_end_date) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, + { CKA_DECRYPT, &g_decrypt, sizeof(g_decrypt) }, + { CKA_SIGN, &g_sign, sizeof(g_sign) }, + { CKA_SIGN_RECOVER, &g_sign_recover, sizeof(g_sign_recover) }, + { CKA_UNWRAP, &g_unwrap, sizeof(g_unwrap) }, + { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, + { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, + { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, + { CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(g_wrap_with_trusted) }, + { CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(g_always_authenticate) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + uint8_t signature[512] = { 0 }; + CK_ULONG signature_len = 0; + + size_t i = 0; + + Do_ADBG_BeginSubCase(c, "%s: Generate key pair", rsa_name); + + modulus_bits = rsa_bits; + + rv = C_GenerateKeyPair(session, &mechanism, public_key_template, + ARRAY_SIZE(public_key_template), + private_key_template, + ARRAY_SIZE(private_key_template), + &public_key, &private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + /* reset get public key template */ + memset(g_id, 0, sizeof(g_id)); + assert(get_public_template[2].type == CKA_ID); + get_public_template[2].ulValueLen = sizeof(g_id); + + memset(g_subject, 0, sizeof(g_subject)); + assert(get_public_template[8].type == CKA_SUBJECT); + get_public_template[8].ulValueLen = sizeof(g_subject); + + memset(g_public_key_info, 0, sizeof(g_public_key_info)); + assert(get_public_template[14].type == CKA_PUBLIC_KEY_INFO); + get_public_template[14].ulValueLen = sizeof(g_public_key_info); + + rv = C_GetAttributeValue(session, public_key, get_public_template, + ARRAY_SIZE(get_public_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_RSA_PKCS_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE)) + goto err_destr_obj; + + /* reset get private key template */ + memset(g_id, 0, sizeof(g_id)); + assert(get_private_template[2].type == CKA_ID); + get_private_template[2].ulValueLen = sizeof(g_id); + + memset(g_subject, 0, sizeof(g_subject)); + assert(get_private_template[8].type == CKA_SUBJECT); + get_private_template[8].ulValueLen = sizeof(g_subject); + + memset(g_public_key_info, 0, sizeof(g_public_key_info)); + assert(get_private_template[19].type == CKA_PUBLIC_KEY_INFO); + get_private_template[19].ulValueLen = sizeof(g_public_key_info); + + rv = C_GetAttributeValue(session, private_key, get_private_template, + ARRAY_SIZE(get_private_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_RSA_PKCS_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE)) + goto err_destr_obj; + + for (i = 0; i < ARRAY_SIZE(rsa_pss_sign_tests); i++) { + /* + * Note: this order of end/begin here is just to get ADBG + * SubCases in sync with error handling. + */ + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "%s: Sign & verify - oneshot - %s", + rsa_name, + rsa_pss_sign_tests[i].test_name); + + sign_mechanism.mechanism = rsa_pss_sign_tests[i].mecha; + sign_mechanism.pParameter = &pss_params; + sign_mechanism.ulParameterLen = sizeof(pss_params); + pss_params.hashAlg = rsa_pss_sign_tests[i].hash_algo; + pss_params.mgf = rsa_pss_sign_tests[i].mgf_algo; + pss_params.sLen = rsa_pss_sign_tests[i].salt_len; + + memset(signature, 0, sizeof(signature)); + signature_len = sizeof(signature); + + rv = C_SignInit(session, &sign_mechanism, private_key); + if (rsa_bits >= rsa_pss_sign_tests[i].min_rsa_bits) { + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + } else { + if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_SIZE_RANGE, rv)) + goto err_destr_obj; + continue; + } + + rv = C_Sign(session, (void *)rsa_pss_sign_tests[i].data, + rsa_pss_sign_tests[i].data_size, + (void *)signature, &signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, (void *)rsa_pss_sign_tests[i].data, + rsa_pss_sign_tests[i].data_size, + (void *)signature, signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + } + + rv = C_DestroyObject(session, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_pub_obj; + + rv = C_DestroyObject(session, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + return 1; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key)); +err_destr_pub_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key)); +err: + Do_ADBG_EndSubCase(c, NULL); + + return 0; +} + +static void xtest_pkcs11_test_1022(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + int ret = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ret = test_rsa_pss_operations(c, session, "RSA-1024", 1024); + if (!ret) + goto out; + ret = test_rsa_pss_operations(c, session, "RSA-2048", 2048); + if (!ret) + goto out; + if (level > 0) { + ret = test_rsa_pss_operations(c, session, "RSA-3072", 3072); + if (!ret) + goto out; + ret = test_rsa_pss_operations(c, session, "RSA-4096", 4096); + if (!ret) + goto out; + } +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1022, xtest_pkcs11_test_1022, + "PKCS11: RSA PSS key generation and signing"); + +static const char rsa_oaep_message[] = "Hello World"; +static char rsa_oaep_label[] = "TestLabel"; + +#define RSA_OAEP_CRYPT_TEST(_test_name, _min_rsa_bits, _hash_algo, _mgf_algo, \ + _source_data, _source_data_len) \ + { \ + .test_name = _test_name, \ + .min_rsa_bits = _min_rsa_bits, \ + .hash_algo = _hash_algo, \ + .mgf_algo = _mgf_algo, \ + .source_data = _source_data, \ + .source_data_len = _source_data_len, \ + } + +/* List of RSA OAEP crypto params to test out */ +static struct { + const char *test_name; + uint32_t min_rsa_bits; + CK_MECHANISM_TYPE hash_algo; + CK_RSA_PKCS_MGF_TYPE mgf_algo; + void *source_data; + size_t source_data_len; +} rsa_oaep_crypt_tests[] = { + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA1", 1024, CKM_SHA_1, CKG_MGF1_SHA1, + NULL, 0), + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA1/label", 1024, CKM_SHA_1, + CKG_MGF1_SHA1, rsa_oaep_label, + sizeof(rsa_oaep_label)), +#ifndef CFG_CRYPTO_SE05X + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA224", 1024, CKM_SHA224, + CKG_MGF1_SHA224, NULL, 0), + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA224/label", 1024, CKM_SHA224, + CKG_MGF1_SHA224, rsa_oaep_label, + sizeof(rsa_oaep_label)), + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA256", 1024, CKM_SHA256, + CKG_MGF1_SHA256, NULL, 0), + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA256/label", 1024, CKM_SHA256, + CKG_MGF1_SHA256, rsa_oaep_label, + sizeof(rsa_oaep_label)), + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA384", 1024, CKM_SHA384, + CKG_MGF1_SHA384, NULL, 0), + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA384/label", 1024, CKM_SHA384, + CKG_MGF1_SHA384, rsa_oaep_label, + sizeof(rsa_oaep_label)), + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA512", 2048, CKM_SHA512, + CKG_MGF1_SHA512, NULL, 0), + RSA_OAEP_CRYPT_TEST("RSA-OAEP/SHA512/label", 2048, CKM_SHA512, + CKG_MGF1_SHA512, rsa_oaep_label, + sizeof(rsa_oaep_label)), +#endif +}; + +static int test_rsa_oaep_operations(ADBG_Case_t *c, + CK_SESSION_HANDLE session, + const char *rsa_name, uint32_t rsa_bits) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE; + + CK_MECHANISM mechanism = { + CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 + }; + CK_MECHANISM crypt_mechanism = { + CKM_RSA_PKCS_OAEP, NULL, 0 + }; + CK_RSA_PKCS_OAEP_PARAMS oaep_params = { + CKM_SHA256, CKG_MGF1_SHA256, CKZ_DATA_SPECIFIED, NULL, 0 + }; + CK_BYTE public_exponent[] = { 1, 0, 1 }; + CK_BYTE id[] = { 123 }; + CK_ULONG modulus_bits = 0; + CK_ATTRIBUTE public_key_template[] = { + { CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_MODULUS_BITS, &modulus_bits, sizeof(modulus_bits) }, + { CKA_PUBLIC_EXPONENT, public_exponent, + sizeof(public_exponent) } + }; + CK_ATTRIBUTE private_key_template[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SUBJECT, subject_common_name, + sizeof(subject_common_name) }, + { CKA_ID, id, sizeof(id) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) } + }; + + CK_OBJECT_CLASS g_class = 0; + CK_KEY_TYPE g_key_type = 0; + CK_BYTE g_id[32] = { 0 }; + CK_DATE g_start_date = { 0 }; + CK_DATE g_end_date = { 0 }; + CK_BBOOL g_derive = CK_FALSE; + CK_BBOOL g_local = CK_FALSE; + CK_MECHANISM_TYPE g_keygen_mecha = 0; + CK_BYTE g_subject[64] = { 0 }; + CK_BBOOL g_encrypt = CK_FALSE; + CK_BBOOL g_verify = CK_FALSE; + CK_BBOOL g_verify_recover = CK_FALSE; + CK_BBOOL g_wrap = CK_FALSE; + CK_BBOOL g_trusted = CK_FALSE; + CK_BYTE g_public_key_info[1024] = { 0 }; + CK_BBOOL g_sensitive = CK_FALSE; + CK_BBOOL g_decrypt = CK_FALSE; + CK_BBOOL g_sign = CK_FALSE; + CK_BBOOL g_sign_recover = CK_FALSE; + CK_BBOOL g_unwrap = CK_FALSE; + CK_BBOOL g_extract = CK_FALSE; + CK_BBOOL g_asensitive = CK_FALSE; + CK_BBOOL g_nextract = CK_FALSE; + CK_BBOOL g_wrap_with_trusted = CK_FALSE; + CK_BBOOL g_always_authenticate = CK_FALSE; + + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE get_public_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_START_DATE, &g_start_date, sizeof(g_start_date) }, + { CKA_END_DATE, &g_end_date, sizeof(g_end_date) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_ENCRYPT, &g_encrypt, sizeof(g_encrypt) }, + { CKA_VERIFY, &g_verify, sizeof(g_verify) }, + { CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(g_verify_recover) }, + { CKA_WRAP, &g_wrap, sizeof(g_wrap) }, + { CKA_TRUSTED, &g_trusted, sizeof(g_trusted) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE get_private_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_START_DATE, &g_start_date, sizeof(g_start_date) }, + { CKA_END_DATE, &g_end_date, sizeof(g_end_date) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, + { CKA_DECRYPT, &g_decrypt, sizeof(g_decrypt) }, + { CKA_SIGN, &g_sign, sizeof(g_sign) }, + { CKA_SIGN_RECOVER, &g_sign_recover, sizeof(g_sign_recover) }, + { CKA_UNWRAP, &g_unwrap, sizeof(g_unwrap) }, + { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, + { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, + { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, + { CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(g_wrap_with_trusted) }, + { CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(g_always_authenticate) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + uint8_t ciphertext[512] = { 0 }; + CK_ULONG ciphertext_len = 0; + uint8_t plaintext[512] = { 0 }; + CK_ULONG plaintext_len = 0; + size_t i = 0; + + Do_ADBG_BeginSubCase(c, "%s: Generate key pair", rsa_name); + + modulus_bits = rsa_bits; + + rv = C_GenerateKeyPair(session, &mechanism, public_key_template, + ARRAY_SIZE(public_key_template), + private_key_template, + ARRAY_SIZE(private_key_template), + &public_key, &private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + /* reset get public key template */ + memset(g_id, 0, sizeof(g_id)); + assert(get_public_template[2].type == CKA_ID); + get_public_template[2].ulValueLen = sizeof(g_id); + + memset(g_subject, 0, sizeof(g_subject)); + assert(get_public_template[8].type == CKA_SUBJECT); + get_public_template[8].ulValueLen = sizeof(g_subject); + + memset(g_public_key_info, 0, sizeof(g_public_key_info)); + assert(get_public_template[14].type == CKA_PUBLIC_KEY_INFO); + get_public_template[14].ulValueLen = sizeof(g_public_key_info); + + rv = C_GetAttributeValue(session, public_key, + get_public_template, + ARRAY_SIZE(get_public_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_RSA_PKCS_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE)) + goto err_destr_obj; + + /* reset get private key template */ + memset(g_id, 0, sizeof(g_id)); + assert(get_private_template[2].type == CKA_ID); + get_private_template[2].ulValueLen = sizeof(g_id); + + memset(g_subject, 0, sizeof(g_subject)); + assert(get_private_template[8].type == CKA_SUBJECT); + get_private_template[8].ulValueLen = sizeof(g_subject); + + memset(g_public_key_info, 0, sizeof(g_public_key_info)); + assert(get_private_template[19].type == CKA_PUBLIC_KEY_INFO); + get_private_template[19].ulValueLen = sizeof(g_public_key_info); + + rv = C_GetAttributeValue(session, private_key, + get_private_template, + ARRAY_SIZE(get_private_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_RSA_PKCS_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE)) + goto err_destr_obj; + + for (i = 0; i < ARRAY_SIZE(rsa_oaep_crypt_tests); i++) { + /* + * Note: this order of end/begin here is just to get ADBG + * SubCases in sync with error handling. + */ + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "%s: Encrypt & decrypt - oneshot - %s", + rsa_name, + rsa_oaep_crypt_tests[i].test_name); + + crypt_mechanism.mechanism = CKM_RSA_PKCS_OAEP; + crypt_mechanism.pParameter = &oaep_params; + crypt_mechanism.ulParameterLen = sizeof(oaep_params); + oaep_params.hashAlg = rsa_oaep_crypt_tests[i].hash_algo; + oaep_params.mgf = rsa_oaep_crypt_tests[i].mgf_algo; + oaep_params.pSourceData = rsa_oaep_crypt_tests[i].source_data; + oaep_params.ulSourceDataLen = rsa_oaep_crypt_tests[i].source_data_len; + + memset(ciphertext, 0, sizeof(ciphertext)); + memset(plaintext, 0, sizeof(plaintext)); + + ciphertext_len = 0; + + memcpy(plaintext, rsa_oaep_message, sizeof(rsa_oaep_message)); + plaintext_len = sizeof(rsa_oaep_message); + + rv = C_EncryptInit(session, &crypt_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Encrypt(session, plaintext, plaintext_len, NULL, + &ciphertext_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Encrypt(session, plaintext, plaintext_len, ciphertext, + &ciphertext_len); + if (rsa_bits >= rsa_oaep_crypt_tests[i].min_rsa_bits) { + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + } else { + if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv)) + goto err_destr_obj; + continue; + } + + memset(plaintext, 0, sizeof(plaintext)); + plaintext_len = 0; + + rv = C_DecryptInit(session, &crypt_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Decrypt(session, ciphertext, ciphertext_len, NULL, + &plaintext_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Decrypt(session, ciphertext, ciphertext_len, plaintext, + &plaintext_len); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_BUFFER(c, rsa_oaep_message, + sizeof(rsa_oaep_message), plaintext, + plaintext_len)) + goto err_destr_obj; + } + + rv = C_DestroyObject(session, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_pub_obj; + + rv = C_DestroyObject(session, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + return 1; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key)); +err_destr_pub_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key)); +err: + Do_ADBG_EndSubCase(c, NULL); + + return 0; +} + +static void xtest_pkcs11_test_1023(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + int ret = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ret = test_rsa_oaep_operations(c, session, "RSA-1024", 1024); + if (!ret) + goto out; + ret = test_rsa_oaep_operations(c, session, "RSA-2048", 2048); + if (!ret) + goto out; + if (level > 0) { + ret = test_rsa_oaep_operations(c, session, "RSA-3072", 3072); + if (!ret) + goto out; + ret = test_rsa_oaep_operations(c, session, "RSA-4096", 4096); + if (!ret) + goto out; + } +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1023, xtest_pkcs11_test_1023, + "PKCS11: RSA OAEP key generation and crypto operations"); + +#ifdef OPENSSL_FOUND +static const char x509_example_root_ca[] = + "-----BEGIN CERTIFICATE-----\n" + "MIICDTCCAZOgAwIBAgIBATAKBggqhkjOPQQDAzA+MQswCQYDVQQGEwJGSTEVMBMG\n" + "A1UECgwMTWFudWZhY3R1cmVyMRgwFgYDVQQDDA9FeGFtcGxlIFJvb3QgQ0EwIBcN\n" + "MjEwODE0MDc1NTU1WhgPOTk5OTEyMzEyMzU5NTlaMD4xCzAJBgNVBAYTAkZJMRUw\n" + "EwYDVQQKDAxNYW51ZmFjdHVyZXIxGDAWBgNVBAMMD0V4YW1wbGUgUm9vdCBDQTB2\n" + "MBAGByqGSM49AgEGBSuBBAAiA2IABP6jFf4PuIo0t78AeONf2ENbip4GdG9rfstp\n" + "bWMvH/0BIn2ioMbapYSK1WcVlOKUaZRrbRzoYWD7ZpwSYFwtd1XmMQkLJ1baIdrt\n" + "jibL9yBCYRJJLsmTHn5UiLCoA2EiFaNjMGEwHQYDVR0OBBYEFApC6125F2th+ujZ\n" + "PVxTtsI8llA1MB8GA1UdIwQYMBaAFApC6125F2th+ujZPVxTtsI8llA1MA8GA1Ud\n" + "EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMACW\n" + "r0/EpTD1uJ9JLsyC8aGP2rSr44J50K6fT0h3LZWMhL5fGkkNTCdmuWbWZznTswIx\n" + "APjyNm4f///vWUN3XFd+BRhS2YHR43c0K4oNVyLqigoMoSqu0zXt9Xm+Lsu5iqgJ\n" + "NQ==\n" + "-----END CERTIFICATE-----\n"; +#endif + +static void xtest_pkcs11_test_1024(ADBG_Case_t *c) +{ +#ifndef OPENSSL_FOUND + (void)c; + Do_ADBG_Log("OpenSSL not available, skipping X.509 Certificate tests"); +#else + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + BIO *x509_bio = NULL; + X509 *x509_cert = NULL; + uint8_t *x509_cert_der = NULL; + int x509_cert_der_size = 0; + X509_NAME *x509_subject_name = NULL; + uint8_t *x509_subject_name_der = NULL; + int x509_subject_name_der_size = 0; + X509_NAME *x509_issuer_name = NULL; + uint8_t *x509_issuer_name_der = NULL; + int x509_issuer_name_der_size = 0; + ASN1_INTEGER *x509_serial_number = NULL; + uint8_t *x509_serial_number_der = NULL; + int x509_serial_number_der_size = 0; + uint8_t *p = NULL; + CK_BYTE id[] = { 123 }; + const char *label = "example-root-ca"; + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE certificate_object[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 }, + sizeof(CK_CERTIFICATE_TYPE) }, + { CKA_CERTIFICATE_CATEGORY, + &(CK_ULONG){ CK_CERTIFICATE_CATEGORY_UNSPECIFIED }, + sizeof(CK_ULONG) }, + { CKA_NAME_HASH_ALGORITHM, &(CK_MECHANISM_TYPE){ CKM_SHA_1 }, + sizeof(CK_MECHANISM_TYPE) }, + { CKA_ID, id, sizeof(id) }, + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + { CKA_VALUE, NULL, 0 }, + { CKA_ISSUER, NULL, 0 }, + { CKA_SUBJECT, NULL, 0 }, + { CKA_SERIAL_NUMBER, NULL, 0 }, + }; + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE certificate_object2[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 }, + sizeof(CK_CERTIFICATE_TYPE) }, + { CKA_ID, id, sizeof(id) }, + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + { CKA_VALUE, NULL, 0 }, + { CKA_ISSUER, NULL, 0 }, + { CKA_SUBJECT, NULL, 0 }, + { CKA_SERIAL_NUMBER, NULL, 0 }, + }; + /* Note: Tests below expects specific order of elements */ + /* CKA_CERTIFICATE_CATEGORY is specified below with invalid ID */ + CK_ATTRIBUTE invalid_category_object[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 }, + sizeof(CK_CERTIFICATE_TYPE) }, + { CKA_CERTIFICATE_CATEGORY, &(CK_ULONG){ -1 }, + sizeof(CK_ULONG) }, + { CKA_ID, id, sizeof(id) }, + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + { CKA_VALUE, NULL, 0 }, + { CKA_ISSUER, NULL, 0 }, + { CKA_SUBJECT, NULL, 0 }, + { CKA_SERIAL_NUMBER, NULL, 0 }, + }; + /* Note: Tests below expects specific order of elements */ + /* CKA_CERTIFICATE_CATEGORY is specified below with invalid size */ + CK_ATTRIBUTE invalid_category_object2[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 }, + sizeof(CK_CERTIFICATE_TYPE) }, + { CKA_CERTIFICATE_CATEGORY, + &(CK_ULONG){ CK_CERTIFICATE_CATEGORY_UNSPECIFIED }, 0 }, + { CKA_ID, id, sizeof(id) }, + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + { CKA_VALUE, NULL, 0 }, + { CKA_ISSUER, NULL, 0 }, + { CKA_SUBJECT, NULL, 0 }, + { CKA_SERIAL_NUMBER, NULL, 0 }, + }; + /* Note: Tests below expects specific order of elements */ + /* CKA_NAME_HASH_ALGORITHM is specified below with invalid size */ + CK_ATTRIBUTE invalid_name_hash_alg_size[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_CERTIFICATE }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_CERTIFICATE_TYPE, &(CK_CERTIFICATE_TYPE){ CKC_X_509 }, + sizeof(CK_CERTIFICATE_TYPE) }, + { CKA_NAME_HASH_ALGORITHM, &(CK_MECHANISM_TYPE){ CKM_SHA_1 }, + sizeof(CK_MECHANISM_TYPE) - 1 }, + { CKA_ID, id, sizeof(id) }, + { CKA_LABEL, (CK_UTF8CHAR_PTR)label, strlen(label) }, + { CKA_VALUE, NULL, 0 }, + { CKA_ISSUER, NULL, 0 }, + { CKA_SUBJECT, NULL, 0 }, + { CKA_SERIAL_NUMBER, NULL, 0 }, + }; + CK_OBJECT_HANDLE obj_hdl = CK_INVALID_HANDLE; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + Do_ADBG_BeginSubCase(c, "Import X.509 Certificate"); + + /* Parse PEM to OpenSSL's internal X509 format */ + x509_bio = BIO_new_mem_buf(x509_example_root_ca, -1); + if (!ADBG_EXPECT_NOT_NULL(c, x509_bio)) + goto out; + + x509_cert = PEM_read_bio_X509(x509_bio, NULL, 0, NULL); + if (!ADBG_EXPECT_NOT_NULL(c, x509_cert)) + goto out; + + BIO_free(x509_bio); + x509_bio = NULL; + + /* Make DER version for storing it in token */ + x509_cert_der_size = i2d_X509(x509_cert, NULL); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_cert_der_size, >, 0)) + goto out; + + x509_cert_der = OPENSSL_malloc(x509_cert_der_size); + if (!ADBG_EXPECT_NOT_NULL(c, x509_cert_der)) + goto out; + + p = x509_cert_der; + x509_cert_der_size = i2d_X509(x509_cert, &p); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_cert_der_size, >, 0)) + goto out; + + /* Extract needed details from certificate */ + + /* Extract subject name */ + x509_subject_name = X509_get_subject_name(x509_cert); + if (!ADBG_EXPECT_NOT_NULL(c, x509_subject_name)) + goto out; + + x509_subject_name_der_size = i2d_X509_NAME(x509_subject_name, NULL); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_subject_name_der_size, >, 0)) + goto out; + + x509_subject_name_der = OPENSSL_malloc(x509_subject_name_der_size); + if (!ADBG_EXPECT_NOT_NULL(c, x509_subject_name_der)) + goto out; + + p = x509_subject_name_der; + x509_subject_name_der_size = i2d_X509_NAME(x509_subject_name, &p); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_subject_name_der_size, >, 0)) + goto out; + + /* Extract issuer's name */ + x509_issuer_name = X509_get_issuer_name(x509_cert); + if (!ADBG_EXPECT_NOT_NULL(c, x509_issuer_name)) + goto out; + + x509_issuer_name_der_size = i2d_X509_NAME(x509_issuer_name, NULL); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_issuer_name_der_size, >, 0)) + goto out; + + x509_issuer_name_der = OPENSSL_malloc(x509_issuer_name_der_size); + if (!ADBG_EXPECT_NOT_NULL(c, x509_issuer_name_der)) + goto out; + + p = x509_issuer_name_der; + x509_issuer_name_der_size = i2d_X509_NAME(x509_issuer_name, &p); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_issuer_name_der_size, >, 0)) + goto out; + + /* Extract certificate's serial number */ + x509_serial_number = X509_get_serialNumber(x509_cert); + if (!ADBG_EXPECT_NOT_NULL(c, x509_serial_number)) + goto out; + + x509_serial_number_der_size = i2d_ASN1_INTEGER(x509_serial_number, NULL); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_serial_number_der_size, >, 0)) + goto out; + + x509_serial_number_der = OPENSSL_malloc(x509_serial_number_der_size); + if (!ADBG_EXPECT_NOT_NULL(c, x509_serial_number_der)) + goto out; + + p = x509_serial_number_der; + x509_serial_number_der_size = i2d_ASN1_INTEGER(x509_serial_number, &p); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, x509_serial_number_der_size, >, 0)) + goto out; + + /* Create the actual object in session */ + assert(certificate_object[7].type == CKA_VALUE); + certificate_object[7].pValue = x509_cert_der; + certificate_object[7].ulValueLen = x509_cert_der_size; + + assert(certificate_object[8].type == CKA_ISSUER); + certificate_object[8].pValue = x509_issuer_name_der; + certificate_object[8].ulValueLen = x509_issuer_name_der_size; + + assert(certificate_object[9].type == CKA_SUBJECT); + certificate_object[9].pValue = x509_subject_name_der; + certificate_object[9].ulValueLen = x509_subject_name_der_size; + + assert(certificate_object[10].type == CKA_SERIAL_NUMBER); + certificate_object[10].pValue = x509_serial_number_der; + certificate_object[10].ulValueLen = x509_serial_number_der_size; + + rv = C_CreateObject(session, certificate_object, + ARRAY_SIZE(certificate_object), &obj_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DestroyObject(session, obj_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Import X.509 Certificate with default values"); + + /* Create the actual object in session */ + assert(certificate_object2[5].type == CKA_VALUE); + certificate_object2[5].pValue = x509_cert_der; + certificate_object2[5].ulValueLen = x509_cert_der_size; + + assert(certificate_object2[6].type == CKA_ISSUER); + certificate_object2[6].pValue = x509_issuer_name_der; + certificate_object2[6].ulValueLen = x509_issuer_name_der_size; + + assert(certificate_object2[7].type == CKA_SUBJECT); + certificate_object2[7].pValue = x509_subject_name_der; + certificate_object2[7].ulValueLen = x509_subject_name_der_size; + + assert(certificate_object2[8].type == CKA_SERIAL_NUMBER); + certificate_object2[8].pValue = x509_serial_number_der; + certificate_object2[8].ulValueLen = x509_serial_number_der_size; + + rv = C_CreateObject(session, certificate_object2, + ARRAY_SIZE(certificate_object2), &obj_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_DestroyObject(session, obj_hdl); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Try import with invalid category"); + + /* Create the actual object in session */ + assert(invalid_category_object[6].type == CKA_VALUE); + invalid_category_object[6].pValue = x509_cert_der; + invalid_category_object[6].ulValueLen = x509_cert_der_size; + + assert(invalid_category_object[7].type == CKA_ISSUER); + invalid_category_object[7].pValue = x509_issuer_name_der; + invalid_category_object[7].ulValueLen = x509_issuer_name_der_size; + + assert(invalid_category_object[8].type == CKA_SUBJECT); + invalid_category_object[8].pValue = x509_subject_name_der; + invalid_category_object[8].ulValueLen = x509_subject_name_der_size; + + assert(invalid_category_object[9].type == CKA_SERIAL_NUMBER); + invalid_category_object[9].pValue = x509_serial_number_der; + invalid_category_object[9].ulValueLen = x509_serial_number_der_size; + + rv = C_CreateObject(session, invalid_category_object, + ARRAY_SIZE(invalid_category_object), &obj_hdl); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Try import with invalid category size"); + + /* Create the actual object in session */ + assert(invalid_category_object2[6].type == CKA_VALUE); + invalid_category_object2[6].pValue = x509_cert_der; + invalid_category_object2[6].ulValueLen = x509_cert_der_size; + + assert(invalid_category_object2[7].type == CKA_ISSUER); + invalid_category_object2[7].pValue = x509_issuer_name_der; + invalid_category_object2[7].ulValueLen = x509_issuer_name_der_size; + + assert(invalid_category_object2[8].type == CKA_SUBJECT); + invalid_category_object2[8].pValue = x509_subject_name_der; + invalid_category_object2[8].ulValueLen = x509_subject_name_der_size; + + assert(invalid_category_object2[9].type == CKA_SERIAL_NUMBER); + invalid_category_object2[9].pValue = x509_serial_number_der; + invalid_category_object2[9].ulValueLen = x509_serial_number_der_size; + + rv = C_CreateObject(session, invalid_category_object2, + ARRAY_SIZE(invalid_category_object2), &obj_hdl); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Try import with invalid name hash alg size"); + + /* Create the actual object in session */ + assert(invalid_name_hash_alg_size[6].type == CKA_VALUE); + invalid_name_hash_alg_size[6].pValue = x509_cert_der; + invalid_name_hash_alg_size[6].ulValueLen = x509_cert_der_size; + + assert(invalid_name_hash_alg_size[7].type == CKA_ISSUER); + invalid_name_hash_alg_size[7].pValue = x509_issuer_name_der; + invalid_name_hash_alg_size[7].ulValueLen = x509_issuer_name_der_size; + + assert(invalid_name_hash_alg_size[8].type == CKA_SUBJECT); + invalid_name_hash_alg_size[8].pValue = x509_subject_name_der; + invalid_name_hash_alg_size[8].ulValueLen = x509_subject_name_der_size; + + assert(invalid_name_hash_alg_size[9].type == CKA_SERIAL_NUMBER); + invalid_name_hash_alg_size[9].pValue = x509_serial_number_der; + invalid_name_hash_alg_size[9].ulValueLen = x509_serial_number_der_size; + + rv = C_CreateObject(session, invalid_name_hash_alg_size, + ARRAY_SIZE(invalid_name_hash_alg_size), &obj_hdl); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv)) + goto out; + +out: + OPENSSL_free(x509_serial_number_der); + OPENSSL_free(x509_issuer_name_der); + OPENSSL_free(x509_subject_name_der); + OPENSSL_free(x509_cert_der); + X509_free(x509_cert); + BIO_free(x509_bio); + + Do_ADBG_EndSubCase(c, NULL); +close_session: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +#endif +} +ADBG_CASE_DEFINE(pkcs11, 1024, xtest_pkcs11_test_1024, + "PKCS11: X509 Certificate operations"); + +#define CKTEST_EDDSA_CTX_TEST(_ec_params, _vect, _flag) { \ + .ec_params = _ec_params, \ + .ec_params_len = ARRAY_SIZE(_ec_params), \ + .message = _vect ##_ptx, \ + .message_len = ARRAY_SIZE(_vect ##_ptx), \ + .private = _vect ##_private, \ + .private_len = ARRAY_SIZE(_vect ##_private), \ + .public = _vect ##_public, \ + .public_len = ARRAY_SIZE(_vect ##_public), \ + .ph_flag = _flag, \ + .context = _vect ## _context, \ + .context_len = ARRAY_SIZE(_vect ##_context), \ + } + +#define CKTEST_EDDSA_TEST(_ec_params, _vect, _flag) { \ + .ec_params = _ec_params, \ + .ec_params_len = ARRAY_SIZE(_ec_params), \ + .message = _vect ##_ptx, \ + .message_len = ARRAY_SIZE(_vect ##_ptx), \ + .private = _vect ##_private, \ + .private_len = ARRAY_SIZE(_vect ##_private), \ + .public = _vect ##_public, \ + .public_len = ARRAY_SIZE(_vect ##_public), \ + .ph_flag = _flag, \ + } + +#define CKTEST_EDDSA_KEY_GEN_TEST(_ec_params, _msg, _context, _flag) { \ + .ec_params = _ec_params, \ + .ec_params_len = ARRAY_SIZE(_ec_params), \ + .message = (const uint8_t *)_msg, \ + .message_len = strlen(_msg), \ + .context = (const uint8_t *)_context, \ + .context_len = strlen(_context), \ + } \ + +struct eddsa_test { + CK_BYTE *ec_params; + size_t ec_params_len; + const uint8_t *message; + size_t message_len; + const uint8_t *private; + size_t private_len; + const uint8_t *public; + size_t public_len; + const bool ph_flag; + const uint8_t *context; + size_t context_len; +}; + +static CK_BYTE ed25519_params[] = { + 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, + 0x47, 0x0f, 0x01, +}; + +static struct eddsa_test eddsa_sign_tests[] = { + CKTEST_EDDSA_KEY_GEN_TEST(ed25519_params, + "Ed25519 test message", "", 0), + CKTEST_EDDSA_KEY_GEN_TEST(ed25519_params, + "Ed25519ctx test message", + "Ed25519 context", 0), + CKTEST_EDDSA_KEY_GEN_TEST(ed25519_params, + "Ed25519ph test message", "", 1), + CKTEST_EDDSA_TEST(ed25519_params, ed25519_rfc_8032_7_1, 0), + CKTEST_EDDSA_CTX_TEST(ed25519_params, ed25519ctx_rfc_8032_7_2, 0), + CKTEST_EDDSA_TEST(ed25519_params, ed25519ph_rfc_8032_7_3, 1), +}; + +static void xtest_pkcs11_test_1025(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE; + size_t i = 0; + struct eddsa_test *test = NULL; + char sign[64] = { }; + CK_EDDSA_PARAMS eddsa_params = { }; + CK_ULONG sign_len = ARRAY_SIZE(sign); + + CK_MECHANISM gen_mechanism = { + .mechanism = CKM_EC_EDWARDS_KEY_PAIR_GEN, + .pParameter = NULL, + .ulParameterLen = 0, + }; + + CK_MECHANISM sign_mechanism = { + CKM_EDDSA, + &eddsa_params, + sizeof(eddsa_params), + }; + + CK_ATTRIBUTE public_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_PUBLIC_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_EC_EDWARDS }, + sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EC_PARAMS, NULL, 0 }, + { CKA_EC_POINT, NULL, 0 }, + }; + + CK_ATTRIBUTE private_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_PRIVATE_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_EC_EDWARDS }, + sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DERIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_VALUE, NULL, 0 }, + { CKA_EC_POINT, NULL, 0 }, + }; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, + CKF_SERIAL_SESSION | CKF_RW_SESSION, + NULL, NULL, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_close_lib; + + for (i = 0; i < ARRAY_SIZE(eddsa_sign_tests); i++) { + test = &eddsa_sign_tests[i]; + + eddsa_params.phFlag = test->ph_flag; + eddsa_params.pContextData = (uint8_t *)test->context; + eddsa_params.ulContextDataLen = test->context_len; + + assert(public_key_template[4].type == CKA_EC_PARAMS); + public_key_template[4].pValue = test->ec_params; + public_key_template[4].ulValueLen = test->ec_params_len; + + if (test->private) { + assert(public_key_template[5].type == CKA_EC_POINT); + public_key_template[5].pValue = + (CK_VOID_PTR)test->public; + public_key_template[5].ulValueLen = test->public_len; + + assert(private_key_template[6].type == CKA_VALUE); + private_key_template[6].pValue = + (CK_VOID_PTR)test->private; + private_key_template[6].ulValueLen = test->private_len; + + assert(private_key_template[7].type == CKA_EC_POINT); + private_key_template[7].pValue = + (CK_VOID_PTR)test->public; + private_key_template[7].ulValueLen = test->public_len; + + rv = C_CreateObject(session, public_key_template, + ARRAY_SIZE(public_key_template), + &public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_close_sess; + + rv = C_CreateObject(session, private_key_template, + ARRAY_SIZE(private_key_template), + &private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) { + C_DestroyObject(session, public_key); + goto err_close_sess; + } + + } else { + rv = C_GenerateKeyPair(session, &gen_mechanism, + public_key_template, + ARRAY_SIZE(public_key_template), + private_key_template, + ARRAY_SIZE(private_key_template), + &public_key, &private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_close_sess; + } + + rv = C_SignInit(session, &sign_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destroy_keys; + + rv = C_Sign(session, (CK_BYTE_PTR)test->message, + test->message_len, + (CK_BYTE_PTR)sign, &sign_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destroy_keys; + + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destroy_keys; + + rv = C_Verify(session, (CK_BYTE_PTR)test->message, + test->message_len, + (CK_BYTE_PTR)sign, sign_len); + + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key)); + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key)); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_close_sess; + } + + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); + ADBG_EXPECT_CK_OK(c, close_lib()); + return; + +err_destroy_keys: + C_DestroyObject(session, private_key); + C_DestroyObject(session, public_key); +err_close_sess: + C_CloseSession(session); +err_close_lib: + close_lib(); +} + +ADBG_CASE_DEFINE(pkcs11, 1025, xtest_pkcs11_test_1025, + "PKCS11: EDDSA key generation and signing"); + +#define RSA_AES_MAX_KEY_SIZE 32 + +#define RSA_AES_WRAP_KEY(vect) \ + { \ + .modulus = vect ## _modulus, \ + .modulus_len = ARRAY_SIZE(vect ## _modulus), \ + .pub_exp = vect ## _pub_exp, \ + .pub_exp_len = ARRAY_SIZE(vect ## _pub_exp), \ + .priv_exp = vect ## _priv_exp, \ + .priv_exp_len = ARRAY_SIZE(vect ## _priv_exp), \ + .prime1 = vect ## _prime1, \ + .prime1_len = ARRAY_SIZE(vect ## _prime1), \ + .prime2 = vect ## _prime2, \ + .prime2_len = ARRAY_SIZE(vect ## _prime2), \ + } + +#define RSA_AES_WRAP_RSA(vect) \ + { .rsa = RSA_AES_WRAP_KEY(vect) } + +#define RSA_AES_WRAP_AES(_size) { .aes = { .size = (_size) } } + +static struct rsa_aes_wrap_test { + CK_KEY_TYPE target_type; + union { + struct { + const uint8_t *modulus; + size_t modulus_len; + + const uint8_t *pub_exp; + size_t pub_exp_len; + + const uint8_t *priv_exp; + size_t priv_exp_len; + + const uint8_t *prime1; + size_t prime1_len; + const uint8_t *prime2; + size_t prime2_len; + } rsa; + struct { + CK_ULONG size; + } aes; + } target; + + struct { + const uint8_t *modulus; + size_t modulus_len; + + const uint8_t *pub_exp; + size_t pub_exp_len; + + const uint8_t *priv_exp; + size_t priv_exp_len; + + const uint8_t *prime1; + size_t prime1_len; + const uint8_t *prime2; + size_t prime2_len; + } key; +} rsa_aes_wrap_tests[] = { + { CKK_AES, RSA_AES_WRAP_AES(128), RSA_AES_WRAP_KEY(ac_rsassa_vect2) }, + { CKK_AES, RSA_AES_WRAP_AES(256), RSA_AES_WRAP_KEY(ac_rsassa_vect18) }, + { CKK_AES, RSA_AES_WRAP_AES(192), RSA_AES_WRAP_KEY(ac_rsassa_vect19) }, + { CKK_RSA, RSA_AES_WRAP_RSA(ac_rsassa_vect1), + RSA_AES_WRAP_KEY(ac_rsassa_vect2) }, + { CKK_RSA, RSA_AES_WRAP_RSA(ac_rsassa_vect1), + RSA_AES_WRAP_KEY(ac_rsassa_vect19) }, + { CKK_RSA, RSA_AES_WRAP_RSA(ac_rsassa_vect2), + RSA_AES_WRAP_KEY(ac_rsassa_vect18) }, + { CKK_RSA, RSA_AES_WRAP_RSA(ac_rsassa_vect18), + RSA_AES_WRAP_KEY(ac_rsassa_vect2) }, + { CKK_RSA, RSA_AES_WRAP_RSA(ac_rsassa_vect19), + RSA_AES_WRAP_KEY(ac_rsassa_vect2) }, + { CKK_RSA, RSA_AES_WRAP_RSA(ac_rsassa_vect19), + RSA_AES_WRAP_KEY(ac_rsassa_vect18) }, + { CKK_RSA, RSA_AES_WRAP_RSA(ac_rsassa_vect18), + RSA_AES_WRAP_KEY(ac_rsassa_vect19) }, +}; + +static CK_RV test_rsa_aes_wrap(ADBG_Case_t *c, CK_SESSION_HANDLE session, + struct rsa_aes_wrap_test *t) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_OBJECT_HANDLE wrapping_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE unwrapping_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE target_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE; + CK_ULONG target_size = t->target_type == CKK_AES ? + t->target.aes.size / 8 : + t->target.rsa.modulus_len; + CK_ULONG target_bits = target_size * 8; + + CK_ATTRIBUTE wrapping_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_PUBLIC_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_RSA }, + sizeof(CK_KEY_TYPE) }, + { CKA_ENCRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_MODULUS, (CK_VOID_PTR)t->key.modulus, + t->key.modulus_len }, + { CKA_PUBLIC_EXPONENT, (CK_VOID_PTR)t->key.pub_exp, + t->key.pub_exp_len }, + }; + + CK_ATTRIBUTE unwrapping_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_PRIVATE_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_RSA }, + sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_MODULUS, (CK_VOID_PTR)t->key.modulus, + t->key.modulus_len }, + { CKA_PRIVATE_EXPONENT, (CK_VOID_PTR)t->key.priv_exp, + t->key.priv_exp_len }, + { CKA_PUBLIC_EXPONENT, (CK_VOID_PTR)t->key.pub_exp, + t->key.pub_exp_len }, + { CKA_PRIME_1, (CK_VOID_PTR)t->key.prime1, + t->key.prime1_len }, + { CKA_PRIME_2, (CK_VOID_PTR)t->key.prime2, + t->key.prime2_len }, + }; + + CK_ATTRIBUTE aes_key_template[] = { + { CKA_VALUE_LEN, &target_size, sizeof(CK_ULONG) }, + { CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + }; + + CK_ATTRIBUTE target_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_PRIVATE_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_RSA }, + sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_MODULUS, (CK_VOID_PTR)t->target.rsa.modulus, + t->target.rsa.modulus_len }, + { CKA_PRIVATE_EXPONENT, (CK_VOID_PTR)t->target.rsa.priv_exp, + t->target.rsa.priv_exp_len }, + { CKA_PUBLIC_EXPONENT, (CK_VOID_PTR)t->target.rsa.pub_exp, + t->target.rsa.pub_exp_len }, + { CKA_PRIME_1, (CK_VOID_PTR)t->target.rsa.prime1, + t->target.rsa.prime1_len }, + { CKA_PRIME_2, (CK_VOID_PTR)t->target.rsa.prime2, + t->target.rsa.prime2_len }, + }; + + CK_ATTRIBUTE unwrapped_aes_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET }, + sizeof(CK_KEY_TYPE) }, + { CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE}, sizeof(CK_BBOOL) }, + }; + + CK_ATTRIBUTE unwrapped_rsa_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_PRIVATE_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_RSA }, + sizeof(CK_KEY_TYPE) }, + { CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE}, sizeof(CK_BBOOL) }, + }; + + CK_ATTRIBUTE *unwrapped_key_template = (t->target_type == CKK_AES) ? + unwrapped_aes_key_template : + unwrapped_rsa_key_template; + CK_ULONG unwrapped_key_template_size = t->target_type == CKK_AES ? + ARRAY_SIZE(unwrapped_aes_key_template) : + ARRAY_SIZE(unwrapped_rsa_key_template); + + CK_RSA_PKCS_OAEP_PARAMS oaep_params = { + CKM_SHA256, CKG_MGF1_SHA256, CKZ_DATA_SPECIFIED, NULL, 0, + }; + CK_RSA_AES_KEY_WRAP_PARAMS rsa_aes_params = { + 256, &oaep_params, + }; + CK_MECHANISM rsa_aes_key_wrap_mechanism = { + CKM_RSA_AES_KEY_WRAP, &rsa_aes_params, sizeof(rsa_aes_params), + }; + + CK_BYTE aes_val[RSA_AES_MAX_KEY_SIZE] = { 0 }; + CK_ULONG key_len = 0; + CK_ATTRIBUTE aes_get_template[] = { + { CKA_VALUE_LEN, &key_len, sizeof(key_len) }, + { CKA_VALUE, aes_val, sizeof(aes_val) }, + }; + + CK_BYTE unwrapped_val[RSA_AES_MAX_KEY_SIZE] = { 0 }; + CK_ULONG unwrapped_key_len = 0; + CK_ATTRIBUTE aes_get_template_unwrapped[] = { + { CKA_VALUE_LEN, &unwrapped_key_len, + sizeof(unwrapped_key_len) }, + { CKA_VALUE, unwrapped_val, sizeof(unwrapped_val) }, + }; + + CK_BYTE unwrapped_rsa_modulus[512] = { 0 }; + CK_BYTE unwrapped_rsa_private_exponent[512] = { 0 }; + CK_ATTRIBUTE rsa_template_unwrapped[] = { + { CKA_MODULUS, NULL, 0 }, + { CKA_MODULUS, unwrapped_rsa_modulus, + sizeof(unwrapped_rsa_modulus) }, + { CKA_PRIVATE_EXPONENT, NULL, 0 }, + { CKA_PRIVATE_EXPONENT, unwrapped_rsa_private_exponent, + sizeof(unwrapped_rsa_private_exponent) }, + }; + CK_BYTE buf[5120] = { 0 }; + CK_ULONG size = 0; + + assert(t != NULL); + assert(t->target_type == CKK_RSA || t->target_type == CKK_AES); + + Do_ADBG_BeginSubCase(c, + "Test RSA AES wrap/unwrap of %lu %s key with %zu RSA", + target_bits, (t->target_type == CKK_AES) ? "AES" : "RSA", + t->key.modulus_len * 8); + + rv = C_CreateObject(session, wrapping_key_template, + ARRAY_SIZE(wrapping_key_template), + &wrapping_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_CreateObject(session, unwrapping_key_template, + ARRAY_SIZE(unwrapping_key_template), + &unwrapping_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (t->target_type == CKK_AES) { + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + aes_key_template, + ARRAY_SIZE(aes_key_template), + &target_key); + } else { + rv = C_CreateObject(session, target_key_template, + ARRAY_SIZE(target_key_template), + &target_key); + } + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + size = sizeof(buf); + rv = C_WrapKey(session, &rsa_aes_key_wrap_mechanism, wrapping_key, + target_key, buf, &size); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf))) { + rv = CKR_ENCRYPTED_DATA_INVALID; + goto out; + } + + if (t->target_type == CKK_AES) { + rv = C_GetAttributeValue(session, target_key, aes_get_template, + ARRAY_SIZE(aes_get_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + } + + rv = C_UnwrapKey(session, &rsa_aes_key_wrap_mechanism, unwrapping_key, + buf, size, unwrapped_key_template, + unwrapped_key_template_size, &unwrapped_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (t->target_type == CKK_AES) { + rv = C_GetAttributeValue(session, unwrapped_key, + aes_get_template_unwrapped, + ARRAY_SIZE(aes_get_template_unwrapped)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + if (!ADBG_EXPECT_BUFFER(c, unwrapped_val, unwrapped_key_len, + aes_val, key_len)) { + rv = CKR_DATA_INVALID; + goto out; + } + } else { + rv = C_GetAttributeValue(session, unwrapped_key, + rsa_template_unwrapped, + ARRAY_SIZE(rsa_template_unwrapped)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, t->target.rsa.modulus, + t->target.rsa.modulus_len, + unwrapped_rsa_modulus, + rsa_template_unwrapped[0].ulValueLen) || + !ADBG_EXPECT_BUFFER(c, t->target.rsa.priv_exp, + t->target.rsa.priv_exp_len, + unwrapped_rsa_private_exponent, + rsa_template_unwrapped[2].ulValueLen)) { + rv = CKR_DATA_INVALID; + goto out; + } + } +out: + if (unwrapped_key != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)); + if (target_key != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, target_key)); + if (unwrapping_key != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapping_key)); + if (wrapping_key != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, wrapping_key)); + Do_ADBG_EndSubCase(c, NULL); + return rv; +} + +static void xtest_pkcs11_test_1026(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE; + + CK_ATTRIBUTE key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET }, + sizeof(CK_KEY_TYPE) }, + { CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE}, sizeof(CK_BBOOL) }, + }; + + CK_RSA_PKCS_OAEP_PARAMS oaep_params = { + CKM_SHA256, CKG_MGF1_SHA256, CKZ_DATA_SPECIFIED, NULL, 0, + }; + CK_RSA_AES_KEY_WRAP_PARAMS rsa_aes_params = { + 256, &oaep_params, + }; + CK_MECHANISM rsa_aes_key_wrap_mechanism = { + CKM_RSA_AES_KEY_WRAP, &rsa_aes_params, sizeof(rsa_aes_params), + }; + + uint8_t unwrapped_val[RSA_AES_MAX_KEY_SIZE] = { 0 }; + CK_ULONG unwrapped_key_len = 0; + CK_ATTRIBUTE get_template_unwrapped[] = { + { CKA_VALUE_LEN, &unwrapped_key_len, + sizeof(unwrapped_key_len) }, + { CKA_VALUE, unwrapped_val, sizeof(unwrapped_val) }, + }; + + CK_ULONG i = 0; + + CK_ATTRIBUTE private_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_PRIVATE_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_RSA }, sizeof(CK_KEY_TYPE) }, + { CKA_TOKEN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_MODULUS, (CK_VOID_PTR)ac_rsassa_vect2_modulus, + sizeof(ac_rsassa_vect2_modulus) }, + { CKA_PRIVATE_EXPONENT, (CK_VOID_PTR)ac_rsassa_vect2_priv_exp, + sizeof(ac_rsassa_vect2_priv_exp) }, + { CKA_PUBLIC_EXPONENT, (CK_VOID_PTR)ac_rsassa_vect2_pub_exp, + sizeof(ac_rsassa_vect2_pub_exp) }, + { CKA_PRIME_1, (CK_VOID_PTR)ac_rsassa_vect2_prime1, + sizeof(ac_rsassa_vect2_prime1) }, + { CKA_PRIME_2, (CK_VOID_PTR)ac_rsassa_vect2_prime2, + sizeof(ac_rsassa_vect2_prime2) }, + }; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_session; + + for (i = 0; i < ARRAY_SIZE(rsa_aes_wrap_tests); i++) { + rv = test_rsa_aes_wrap(c, session, &rsa_aes_wrap_tests[i]); + if (rv != CKR_OK) + goto logout; + } + + Do_ADBG_BeginSubCase(c, "Test external key unwrap with RSA AES"); + rv = C_CreateObject(session, private_key_template, + ARRAY_SIZE(private_key_template), &private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_UnwrapKey(session, &rsa_aes_key_wrap_mechanism, private_key, + (CK_VOID_PTR)pkcs11_rsa_aes_wrapped_key, + ARRAY_SIZE(pkcs11_rsa_aes_wrapped_key), key_template, + ARRAY_SIZE(key_template), &unwrapped_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped, + ARRAY_SIZE(get_template_unwrapped)); + ADBG_EXPECT_CK_OK(c, rv); + ADBG_EXPECT_BUFFER(c, unwrapped_val, unwrapped_key_len, + pkcs11_rsa_aes_tagret_key, + ARRAY_SIZE(pkcs11_rsa_aes_tagret_key)); +out: + if (unwrapped_key != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)); + if (private_key != CK_INVALID_HANDLE) + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key)); + Do_ADBG_EndSubCase(c, NULL); +logout: + ADBG_EXPECT_CK_OK(c, C_Logout(session)); +close_session: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} + +ADBG_CASE_DEFINE(pkcs11, 1026, xtest_pkcs11_test_1026, + "PKCS11: RSA AES Key Wrap/Unwrap tests"); + +static CK_RV test_login_logout_acl_auth(ADBG_Case_t *c, CK_SLOT_ID slot) +{ + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_RV rv = CKR_GENERAL_ERROR; + + Do_ADBG_BeginSubCase(c, "Test C_Login()/C_Logout() with ACL based authentication"); + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Logout: should fail as we did not log in yet */ + rv = C_Logout(session); + ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv); + + /* Login/re-log/logout user */ + rv = C_Login(session, CKU_USER, NULL, 0); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_close; + + rv = C_Login(session, CKU_USER, NULL, 0); + ADBG_EXPECT_CK_RESULT(c, CKR_USER_ALREADY_LOGGED_IN, rv); + + rv = C_Logout(session); + ADBG_EXPECT_CK_OK(c, rv); + +out_close: + C_CloseSession(session); +out: + Do_ADBG_EndSubCase(c, "Test C_Login()/C_Logout() with ACL based authentication"); + return rv; +} + +#define GID_STR_LEN 13 + +static void xtest_pkcs11_test_1027(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_FUNCTION_LIST_PTR ckfunc_list = NULL; + CK_SLOT_ID slot = 0; + CK_TOKEN_INFO token_info = { 0 }; + char gid_str[GID_STR_LEN] = { 0 }; + int str_len = 0; + + rv = C_GetFunctionList(&ckfunc_list); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_InitToken) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_InitPIN) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_Login) || + !ADBG_EXPECT_NOT_NULL(c, ckfunc_list->C_Logout)) { + Do_ADBG_Log(" - 1027 - skip test, ckfunc_list not found"); + return; + } + + if (!ADBG_EXPECT_TRUE(c, !setenv("CKTEEC_LOGIN_TYPE", "user", 1))) + return; + + rv = init_lib_and_find_token_slot(&slot, ACL_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_GetTokenInfo(slot, &token_info); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + /* Abort test if token is about to lock */ + if (!ADBG_EXPECT_TRUE(c, !(token_info.flags & CKF_SO_PIN_FINAL_TRY))) + goto out; + + if (!(token_info.flags & CKF_TOKEN_INITIALIZED)) { + rv = test_uninitialized_token(c, slot, ACL_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + } + + /* + * The current connection is closed and a new CKU_USER connection will be opened. + */ + rv = close_lib(); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_unsetenv; + + if (!ADBG_EXPECT_TRUE(c, !setenv("CKTEEC_LOGIN_TYPE", "group", 1))) + goto out_unsetenv; + + str_len = snprintf(gid_str, sizeof(gid_str), "%d", getegid()); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, str_len, >=, 0)) + goto out_unsetenv; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, str_len, <, (int)sizeof(gid_str))) + goto out_unsetenv; + + if (!ADBG_EXPECT_TRUE(c, !setenv("CKTEEC_LOGIN_GID", gid_str, 1))) + goto out_unsetenv; + + rv = init_lib_and_find_token_slot(&slot, ACL_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out_unsetenv; + + rv = test_login_logout_acl_auth(c, slot); + ADBG_EXPECT_CK_OK(c, rv); + +out: + rv = close_lib(); + ADBG_EXPECT_CK_OK(c, rv); + +out_unsetenv: + ADBG_EXPECT_TRUE(c, !unsetenv("CKTEEC_LOGIN_TYPE")); + ADBG_EXPECT_TRUE(c, !unsetenv("CKTEEC_LOGIN_GID")); +} + +ADBG_CASE_DEFINE(pkcs11, 1027, xtest_pkcs11_test_1027, + "PKCS11: Login to PKCS#11 token with ACL based authentication"); diff --git a/optee/optee_test/host/xtest/rand_stream.c b/optee/optee_test/host/xtest/rand_stream.c new file mode 100644 index 0000000..d8292b7 --- /dev/null +++ b/optee/optee_test/host/xtest/rand_stream.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include + +#include "rand_stream.h" + +#define STREAM_BUF_MIN_SIZE 4 + +struct rand_stream { + int32_t seed; + uint8_t word_buf[4]; + size_t w_offs; + size_t sb_size; + size_t sb_offs; + uint8_t stream_buf[]; +}; + +struct rand_stream *rand_stream_alloc(int seed, size_t stream_buffer_size) +{ + size_t sb_size = MAX(stream_buffer_size, STREAM_BUF_MIN_SIZE); + struct rand_stream *rs = calloc(1, sizeof(*rs) + sb_size); + + if (!rs) + return NULL; + + rs->sb_size = sb_size;; + rs->sb_offs = rs->sb_size; + rs->w_offs = sizeof(rs->word_buf); + rs->seed = seed; + + return rs; +} + +void rand_stream_free(struct rand_stream *rs) +{ + free(rs); +} + +static void get_random(struct rand_stream *rs, uint8_t *buf, size_t blen) +{ + uint8_t *b = buf; + size_t l = blen; + + + /* + * This function uses an LCG, + * https://en.wikipedia.org/wiki/Linear_congruential_generator + * to generate the byte stream. + */ + + while (l) { + size_t t = MIN(sizeof(rs->word_buf) - rs->w_offs, l); + + memcpy(b, rs->word_buf + rs->w_offs, t); + rs->w_offs += t; + l -= t; + b += t; + + if (rs->w_offs == sizeof(rs->word_buf)) { + rs->seed = rs->seed * 1103515245 + 12345; + memcpy(rs->word_buf, &rs->seed, sizeof(rs->seed)); + rs->w_offs = 0; + } + } +} + +const void *rand_stream_peek(struct rand_stream *rs, size_t *num_bytes) +{ + if (rs->sb_offs == rs->sb_size) { + rs->sb_offs = 0; + get_random(rs, rs->stream_buf, rs->sb_size); + } + + *num_bytes = MIN(*num_bytes, rs->sb_size - rs->sb_offs); + return rs->stream_buf + rs->sb_offs; +} + +void rand_stream_read(struct rand_stream *rs, void *buf, size_t num_bytes) +{ + size_t peek_bytes = num_bytes; + const void *peek = rand_stream_peek(rs, &peek_bytes); + + memcpy(buf, peek, peek_bytes); + rand_stream_advance(rs, peek_bytes); + + if (num_bytes - peek_bytes) + get_random(rs, (uint8_t *)buf + peek_bytes, + num_bytes - peek_bytes); +} + +void rand_stream_advance(struct rand_stream *rs, size_t num_bytes) +{ + size_t nb = num_bytes; + + if (nb <= (rs->sb_size - rs->sb_offs)) { + rs->sb_offs += nb; + return; + } + + nb -= rs->sb_size - rs->sb_offs; + rs->sb_offs = rs->sb_size; + + while (nb > rs->sb_size) { + get_random(rs, rs->stream_buf, rs->sb_size); + nb -= rs->sb_size; + } + + get_random(rs, rs->stream_buf, rs->sb_size); + rs->sb_offs = nb; +} diff --git a/optee/optee_test/host/xtest/rand_stream.h b/optee/optee_test/host/xtest/rand_stream.h new file mode 100644 index 0000000..e411a6f --- /dev/null +++ b/optee/optee_test/host/xtest/rand_stream.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef __RAND_STREAM_H +#define __RAND_STREAM_H + +#include + +struct rand_stream; + +struct rand_stream *rand_stream_alloc(int seed, size_t stream_buffer_size); +void rand_stream_free(struct rand_stream *rs); + +const void *rand_stream_peek(struct rand_stream *rs, size_t *num_bytes); +void rand_stream_advance(struct rand_stream *rs, size_t num_bytes); +void rand_stream_read(struct rand_stream *rs, void *buf, size_t num_bytes); + +#endif /*__RAND_STREAM_H*/ diff --git a/optee/optee_test/host/xtest/regression_1000.c b/optee/optee_test/host/xtest/regression_1000.c new file mode 100644 index 0000000..f40bf7b --- /dev/null +++ b/optee/optee_test/host/xtest/regression_1000.c @@ -0,0 +1,3274 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#ifdef OPENSSL_FOUND +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#ifdef CFG_SECURE_DATA_PATH +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xtest_helpers.h" +#include "xtest_test.h" +#include "xtest_uuid_helpers.h" + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#define STATS_UUID \ + { 0xd96a5b40, 0xe2c7, 0xb1af, \ + { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } + +#define STATS_CMD_PAGER_STATS 0 + +#define PAGER_PAGE_COUNT_THRESHOLD ((128 * 1024) / 4096) + +struct xtest_crypto_session { + ADBG_Case_t *c; + TEEC_Session *session; + uint32_t cmd_id_sha256; + uint32_t cmd_id_aes256ecb_encrypt; + uint32_t cmd_id_aes256ecb_decrypt; +}; + +static bool optee_pager_with_small_pool(void) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_UUID uuid = STATS_UUID; + TEEC_Context ctx = { }; + TEEC_Session sess = { }; + TEEC_Operation op = { }; + uint32_t eo = 0; + bool rc = false; + + res = TEEC_InitializeContext(NULL, &ctx); + if (res) + return false; + + res = TEEC_OpenSession(&ctx, &sess, &uuid, TEEC_LOGIN_PUBLIC, NULL, + NULL, &eo); + if (res) + goto out_ctx; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, TEEC_NONE); + res = TEEC_InvokeCommand(&sess, STATS_CMD_PAGER_STATS, &op, &eo); + if (res) + goto out_sess; + + if (op.params[0].value.b && + op.params[0].value.b <= PAGER_PAGE_COUNT_THRESHOLD) + rc = true; + +out_sess: + TEEC_CloseSession(&sess); +out_ctx: + TEEC_FinalizeContext(&ctx); + + return rc; +} + +static void xtest_crypto_test(struct xtest_crypto_session *cs) +{ + uint32_t ret_orig = 0; + uint8_t crypt_out[16] = { }; + uint8_t crypt_in[16] = { 22, 17 }; + + crypt_in[15] = 60; + + Do_ADBG_BeginSubCase(cs->c, "AES encrypt"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].tmpref.buffer = crypt_in; + op.params[0].tmpref.size = sizeof(crypt_in); + op.params[1].tmpref.buffer = crypt_out; + op.params[1].tmpref.size = sizeof(crypt_out); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(cs->c, + TEEC_InvokeCommand(cs->session, + cs-> + cmd_id_aes256ecb_encrypt, + &op, + &ret_orig)); + } + Do_ADBG_EndSubCase(cs->c, "AES encrypt"); + + Do_ADBG_BeginSubCase(cs->c, "AES decrypt"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint8_t out[16] = { }; + + op.params[0].tmpref.buffer = crypt_out; + op.params[0].tmpref.size = sizeof(crypt_out); + op.params[1].tmpref.buffer = out; + op.params[1].tmpref.size = sizeof(out); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(cs->c, + TEEC_InvokeCommand(cs->session, + cs-> + cmd_id_aes256ecb_decrypt, + &op, + &ret_orig)); + + if (!ADBG_EXPECT(cs->c, 0, + memcmp(crypt_in, out, sizeof(crypt_in)))) { + Do_ADBG_Log("crypt_in:"); + Do_ADBG_HexLog(crypt_in, sizeof(crypt_in), 16); + Do_ADBG_Log("out:"); + Do_ADBG_HexLog(out, sizeof(out), 16); + } + } + Do_ADBG_EndSubCase(cs->c, "AES decrypt"); + + Do_ADBG_BeginSubCase(cs->c, "SHA-256 test, 3 bytes input"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + static const uint8_t sha256_in[] = { 'a', 'b', 'c' }; + static const uint8_t sha256_out[] = { + 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 + }; + uint8_t out[32] = { }; + + op.params[0].tmpref.buffer = (void *)sha256_in; + op.params[0].tmpref.size = sizeof(sha256_in); + op.params[1].tmpref.buffer = out; + op.params[1].tmpref.size = sizeof(out); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(cs->c, + TEEC_InvokeCommand(cs->session, + cs-> + cmd_id_sha256, + &op, + &ret_orig)); + + if (!ADBG_EXPECT(cs->c, 0, memcmp(sha256_out, out, + sizeof(sha256_out)))) { + Do_ADBG_Log("sha256_out:"); + Do_ADBG_HexLog(sha256_out, sizeof(sha256_out), 16); + Do_ADBG_Log("out:"); + Do_ADBG_HexLog(out, sizeof(out), 16); + } + } + Do_ADBG_EndSubCase(cs->c, "SHA-256 test, 3 bytes input"); + + Do_ADBG_BeginSubCase(cs->c, "AES-256 ECB encrypt (32B, fixed key)"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + static const uint8_t in[] = { + 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 + }; + static const uint8_t exp_out[] = { + 0x5A, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, + 0xF0, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, + 0xE9, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, + 0xF0, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x8E + }; + uint8_t out[sizeof(exp_out)] = { }; + + op.params[0].tmpref.buffer = (void *)in; + op.params[0].tmpref.size = sizeof(in); + op.params[1].tmpref.buffer = out; + op.params[1].tmpref.size = sizeof(out); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(cs->c, + TEEC_InvokeCommand(cs->session, + cs-> + cmd_id_aes256ecb_encrypt, + &op, + &ret_orig)); + + if (!ADBG_EXPECT(cs->c, 0, + memcmp(exp_out, out, sizeof(exp_out)))) { + Do_ADBG_Log("exp_out:"); + Do_ADBG_HexLog(exp_out, sizeof(exp_out), 16); + Do_ADBG_Log("out:"); + Do_ADBG_HexLog(out, sizeof(out), 16); + } + } + Do_ADBG_EndSubCase(cs->c, "AES-256 ECB encrypt (32B, fixed key)"); + + Do_ADBG_BeginSubCase(cs->c, "AES-256 ECB decrypt (32B, fixed key)"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + static const uint8_t in[] = { + 0x5A, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, + 0xF0, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, + 0xE9, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, + 0xF0, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x8E + }; + static const uint8_t exp_out[] = { + 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 + }; + uint8_t out[sizeof(exp_out)] = { }; + + op.params[0].tmpref.buffer = (void *)in; + op.params[0].tmpref.size = sizeof(in); + op.params[1].tmpref.buffer = out; + op.params[1].tmpref.size = sizeof(out); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(cs->c, + TEEC_InvokeCommand(cs->session, + cs-> + cmd_id_aes256ecb_decrypt, + &op, + &ret_orig)); + + if (!ADBG_EXPECT(cs->c, 0, + memcmp(exp_out, out, sizeof(exp_out)))) { + Do_ADBG_Log("exp_out:"); + Do_ADBG_HexLog(exp_out, sizeof(exp_out), 16); + Do_ADBG_Log("out:"); + Do_ADBG_HexLog(out, sizeof(out), 16); + } + } + Do_ADBG_EndSubCase(cs->c, "AES-256 ECB decrypt (32B, fixed key)"); +} + +static void xtest_tee_test_1001(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + /* Pseudo TA is optional: warn and nicely exit if not found */ + res = xtest_teec_open_session(&session, &pta_invoke_tests_ta_uuid, NULL, + &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND) { + Do_ADBG_Log(" - 1001 - skip test, pseudo TA not found"); + return; + } + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + Do_ADBG_BeginSubCase(c, "Core self tests"); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, TEEC_InvokeCommand( + &session, PTA_INVOKE_TESTS_CMD_SELF_TESTS, NULL, &ret_orig)); + + Do_ADBG_EndSubCase(c, "Core self tests"); + + Do_ADBG_BeginSubCase(c, "Core dt_driver self tests"); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, TEEC_InvokeCommand( + &session, PTA_INVOKE_TESTS_CMD_DT_DRIVER_TESTS, NULL, + &ret_orig)); + + Do_ADBG_EndSubCase(c, "Core dt_driver self tests"); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1001, xtest_tee_test_1001, "Core self tests"); + +static void xtest_tee_test_1002(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + uint8_t buf[16 * 1024] = { }; + uint8_t exp_sum = 0; + size_t n = 0; + + /* Pseudo TA is optional: warn and nicely exit if not found */ + res = xtest_teec_open_session(&session, &pta_invoke_tests_ta_uuid, NULL, + &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND) { + Do_ADBG_Log(" - 1002 - skip test, pseudo TA not found"); + return; + } + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + op.params[0].tmpref.size = sizeof(buf); + op.params[0].tmpref.buffer = buf; + + for (n = 0; n < sizeof(buf); n++) + buf[n] = n + 1; + for (n = 0; n < sizeof(buf); n++) + exp_sum += buf[n]; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, TEEC_InvokeCommand( + &session, PTA_INVOKE_TESTS_CMD_PARAMS, &op, &ret_orig))) + goto out; + + ADBG_EXPECT_COMPARE_SIGNED(c, exp_sum, ==, buf[0]); +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1002, xtest_tee_test_1002, "PTA parameters"); + +struct test_1003_arg { + uint32_t test_type; + size_t repeat; + size_t max_before_lockers; + size_t max_during_lockers; + size_t before_lockers; + size_t during_lockers; + TEEC_Result res; + uint32_t error_orig; +}; + +static void *test_1003_thread(void *arg) +{ + struct test_1003_arg *a = arg; + TEEC_Session session = { }; + size_t rounds = 64 * 1024; + size_t n = 0; + + a->res = xtest_teec_open_session(&session, &pta_invoke_tests_ta_uuid, + NULL, &a->error_orig); + if (a->res != TEEC_SUCCESS) + return NULL; + + for (n = 0; n < a->repeat; n++) { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].value.a = a->test_type; + op.params[0].value.b = rounds; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + a->res = TEEC_InvokeCommand(&session, + PTA_INVOKE_TESTS_CMD_MUTEX, + &op, &a->error_orig); + if (a->test_type == PTA_MUTEX_TEST_WRITER && + op.params[1].value.b != 1) { + Do_ADBG_Log("n %zu %" PRIu32, n, op.params[1].value.b); + a->res = TEEC_ERROR_BAD_STATE; + a->error_orig = 42; + break; + } + + if (a->test_type == PTA_MUTEX_TEST_READER) { + if (op.params[1].value.a > a->max_before_lockers) + a->max_before_lockers = op.params[1].value.a; + + if (op.params[1].value.b > a->max_during_lockers) + a->max_during_lockers = op.params[1].value.b; + + a->before_lockers += op.params[1].value.a; + a->during_lockers += op.params[1].value.b; + } + } + TEEC_CloseSession(&session); + + return NULL; +} + +#define TEST_1003_THREAD_COUNT (3 * 2) + +static void xtest_tee_test_1003(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t repeat = 20; + struct test_1003_arg arg[TEST_1003_THREAD_COUNT] = { }; + size_t max_read_concurrency = 0; + size_t max_read_waiters = 0; + size_t num_concurrent_read_lockers = 0; + size_t num_concurrent_read_waiters = 0; + size_t n = 0; + size_t nt = TEST_1003_THREAD_COUNT; + double mean_read_concurrency = 0; + double mean_read_waiters = 0; + size_t num_writers = 0; + size_t num_readers = 0; + pthread_t thr[TEST_1003_THREAD_COUNT] = { }; + + /* Pseudo TA is optional: warn and nicely exit if not found */ + res = xtest_teec_open_session(&session, &pta_invoke_tests_ta_uuid, NULL, + &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND) { + Do_ADBG_Log(" - 1003 - skip test, pseudo TA not found"); + return; + } + ADBG_EXPECT_TEEC_SUCCESS(c, res); + TEEC_CloseSession(&session); + + for (n = 0; n < nt; n++) { + if (n % 3) { + arg[n].test_type = PTA_MUTEX_TEST_READER; + num_readers++; + } else { + arg[n].test_type = PTA_MUTEX_TEST_WRITER; + num_writers++; + } + arg[n].repeat = repeat; + if (!ADBG_EXPECT(c, 0, pthread_create(thr + n, NULL, + test_1003_thread, arg + n))) + nt = n; /* break loop and start cleanup */ + } + + for (n = 0; n < nt; n++) { + ADBG_EXPECT(c, 0, pthread_join(thr[n], NULL)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, arg[n].res)) + Do_ADBG_Log("error origin %" PRIu32, + arg[n].error_orig); + if (arg[n].test_type == PTA_MUTEX_TEST_READER) { + if (arg[n].max_during_lockers > max_read_concurrency) + max_read_concurrency = + arg[n].max_during_lockers; + + if (arg[n].max_before_lockers > max_read_waiters) + max_read_waiters = arg[n].max_before_lockers; + + num_concurrent_read_lockers += arg[n].during_lockers; + num_concurrent_read_waiters += arg[n].before_lockers; + } + } + + mean_read_concurrency = (double)num_concurrent_read_lockers / + (double)(repeat * num_readers); + mean_read_waiters = (double)num_concurrent_read_waiters / + (double)(repeat * num_readers); + + Do_ADBG_Log(" Number of parallel threads: %d (%zu writers and %zu readers)", + TEST_1003_THREAD_COUNT, num_writers, num_readers); + Do_ADBG_Log(" Max read concurrency: %zu", max_read_concurrency); + Do_ADBG_Log(" Max read waiters: %zu", max_read_waiters); + Do_ADBG_Log(" Mean read concurrency: %g", mean_read_concurrency); + Do_ADBG_Log(" Mean read waiting: %g", mean_read_waiters); +} +ADBG_CASE_DEFINE(regression, 1003, xtest_tee_test_1003, + "Core internal read/write mutex"); + +static void xtest_tee_test_1004(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + struct xtest_crypto_session cs = { c, &session, TA_CRYPT_CMD_SHA256, + TA_CRYPT_CMD_AES256ECB_ENC, + TA_CRYPT_CMD_AES256ECB_DEC }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + /* Run the "complete crypto test suite" */ + xtest_crypto_test(&cs); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1004, xtest_tee_test_1004, "Test User Crypt TA"); + +static void xtest_tee_test_invalid_mem_access(ADBG_Case_t *c, unsigned int n) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig))) + return; + + op.params[0].value.a = n; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_BAD_MEM_ACCESS, &op, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_BAD_MEM_ACCESS, &op, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + TEEC_CloseSession(&session); +} + +static void xtest_tee_test_invalid_mem_access2(ADBG_Case_t *c, unsigned int n, + size_t size) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + TEEC_SharedMemory shm = { }; + + shm.size = size; + shm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_AllocateSharedMemory(&xtest_teec_ctx, &shm))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig))) + goto rel_shm; + + op.params[0].value.a = (uint32_t)n; + op.params[1].memref.parent = &shm; + op.params[1].memref.size = size; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_MEMREF_WHOLE, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_BAD_MEM_ACCESS, &op, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_BAD_MEM_ACCESS, &op, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + TEEC_CloseSession(&session); +rel_shm: + TEEC_ReleaseSharedMemory(&shm); +} + +static void xtest_tee_test_1005(ADBG_Case_t *c) +{ + uint32_t ret_orig = 0; +#define MAX_SESSIONS 3 + TEEC_Session sessions[MAX_SESSIONS]; + int i = 0; + + for (i = 0; i < MAX_SESSIONS; i++) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sessions[i], + &concurrent_ta_uuid, + NULL, &ret_orig))) + break; + } + + for (; --i >= 0; ) + TEEC_CloseSession(&sessions[i]); +} +ADBG_CASE_DEFINE(regression, 1005, xtest_tee_test_1005, "Many sessions"); + +static void xtest_tee_test_1006(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint8_t buf[32] = { }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig))) + return; + + op.params[0].tmpref.buffer = buf; + op.params[0].tmpref.size = sizeof(buf); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_BASIC, &op, + &ret_orig)); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1006, xtest_tee_test_1006, + "Test Basic OS features"); + +static void xtest_tee_test_1007(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig))) + return; + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_PANIC, NULL, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_INIT, NULL, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1007, xtest_tee_test_1007, "Test Panic"); + +#ifndef TA_DIR +# ifdef __ANDROID__ +#define TA_DIR "/vendor/lib/optee_armtz" +# else +#define TA_DIR "/lib/optee_armtz" +# endif +#endif + +static FILE *open_ta_file(const TEEC_UUID *uuid, const char *mode) +{ + char buf[PATH_MAX] = { }; + + snprintf(buf, sizeof(buf), + "%s/%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x.ta", + TA_DIR, uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion, + uuid->clockSeqAndNode[0], uuid->clockSeqAndNode[1], + uuid->clockSeqAndNode[2], uuid->clockSeqAndNode[3], + uuid->clockSeqAndNode[4], uuid->clockSeqAndNode[5], + uuid->clockSeqAndNode[6], uuid->clockSeqAndNode[7]); + + return fopen(buf, mode); +} + +static bool load_corrupt_ta(ADBG_Case_t *c, size_t offs, uint8_t mask) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_UUID uuid = PTA_SECSTOR_TA_MGMT_UUID; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t ret_orig = 0; + FILE *f = NULL; + bool r = false; + uint8_t *buf = NULL; + size_t sz = 0; + size_t fread_res = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &uuid, NULL, &ret_orig))) + goto out; + + f = open_ta_file(&create_fail_test_ta_uuid, "rb"); + if (!ADBG_EXPECT_NOT_NULL(c, f)) + goto out; + if (!ADBG_EXPECT_TRUE(c, !fseek(f, 0, SEEK_END))) + goto out; + sz = ftell(f); + rewind(f); + + buf = malloc(sz); + if (!ADBG_EXPECT_NOT_NULL(c, buf)) + goto out; + + fread_res = fread(buf, 1, sz, f); + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, fread_res, ==, sz)) + goto out; + + fclose(f); + f = NULL; + + buf[MIN(offs, sz)] ^= mask; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + op.params[0].tmpref.buffer = buf; + op.params[0].tmpref.size = sz; + + res = TEEC_InvokeCommand(&session, PTA_SECSTOR_TA_MGMT_BOOTSTRAP, &op, + &ret_orig); + r = ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_SECURITY, res); +out: + free(buf); + if (f) + fclose(f); + TEEC_CloseSession(&session); + return r; +} + +static void test_1008_corrupt_ta(ADBG_Case_t *c) +{ + TEEC_UUID uuid = PTA_SECSTOR_TA_MGMT_UUID; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + res = xtest_teec_open_session(&session, &uuid, NULL, &ret_orig); + if (res) { + if (ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND, + res)) + Do_ADBG_Log("PTA Secure Storage TA Management not found: skip test"); + return; + } + TEEC_CloseSession(&session); + + ADBG_EXPECT_TRUE(c, + load_corrupt_ta(c, offsetof(struct shdr, magic), 1)); + ADBG_EXPECT_TRUE(c, + load_corrupt_ta(c, offsetof(struct shdr, img_type), 1)); + ADBG_EXPECT_TRUE(c, + load_corrupt_ta(c, offsetof(struct shdr, img_size), 1)); + ADBG_EXPECT_TRUE(c, + load_corrupt_ta(c, offsetof(struct shdr, algo), 1)); + ADBG_EXPECT_TRUE(c, + load_corrupt_ta(c, offsetof(struct shdr, hash_size), 1)); + ADBG_EXPECT_TRUE(c, + load_corrupt_ta(c, offsetof(struct shdr, sig_size), 1)); + ADBG_EXPECT_TRUE(c, + load_corrupt_ta(c, sizeof(struct shdr), 1)); /* hash */ + ADBG_EXPECT_TRUE(c, + load_corrupt_ta(c, sizeof(struct shdr) + 32, 1)); /* sig */ + ADBG_EXPECT_TRUE(c, load_corrupt_ta(c, 3000, 1)); /* payload */ + ADBG_EXPECT_TRUE(c, load_corrupt_ta(c, 8000, 1)); /* payload */ +} + +static void xtest_tee_test_1008(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Session session_crypt = { }; + uint32_t ret_orig = 0; + + Do_ADBG_BeginSubCase(c, "Invoke command"); + { + if (ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) { + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CLIENT, + NULL, &ret_orig)); + TEEC_CloseSession(&session); + } + + } + Do_ADBG_EndSubCase(c, "Invoke command"); + + Do_ADBG_BeginSubCase(c, "Invoke command with timeout"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].value.a = 2000; + op.paramTypes = TEEC_PARAM_TYPES( + TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE); + + if (ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, + &os_test_ta_uuid, + NULL, + &ret_orig))) { + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, + TA_OS_TEST_CMD_CLIENT_WITH_TIMEOUT, + &op, &ret_orig)); + TEEC_CloseSession(&session); + } + } + Do_ADBG_EndSubCase(c, "Invoke command with timeout"); + + Do_ADBG_BeginSubCase(c, "Create session fail"); + { + size_t n = 0; + + for (n = 0; n < 100; n++) { + Do_ADBG_Log("n = %zu", n); + (void)ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_GENERIC, + xtest_teec_open_session(&session_crypt, + &create_fail_test_ta_uuid, + NULL, &ret_orig)); + /* level > 0 may be used to detect/debug memory leaks */ + if (!level) + break; + } + } + Do_ADBG_EndSubCase(c, "Create session fail"); + + Do_ADBG_BeginSubCase(c, "Load corrupt TA"); + test_1008_corrupt_ta(c); + Do_ADBG_EndSubCase(c, "Load corrupt TA"); +} +ADBG_CASE_DEFINE(regression, 1008, xtest_tee_test_1008, + "TEE internal client API"); + +static void *cancellation_thread(void *arg) +{ + /* + * Sleep 0.5 seconds before cancellation to make sure that the other + * thread is in RPC_WAIT. + */ + (void)usleep(500000); + TEEC_RequestCancellation(arg); + return NULL; +} + +static void xtest_tee_test_1009_subcase(ADBG_Case_t *c, const char *subcase, + uint32_t timeout, bool cancel) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + pthread_t thr; + + memset(&thr, 0, sizeof(thr)); + + Do_ADBG_BeginSubCase(c, "%s", subcase); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + if (ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) { + + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, + TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + + op.params[0].value.a = timeout; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_NONE, + TEEC_NONE, TEEC_NONE); + if (cancel) { + (void)ADBG_EXPECT(c, 0, + pthread_create(&thr, NULL, + cancellation_thread, &op)); + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_CANCEL, + TEEC_InvokeCommand(&session, + TA_OS_TEST_CMD_WAIT, + &op, + &ret_orig)); + } else + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, + TA_OS_TEST_CMD_WAIT, + &op, + &ret_orig)); + if (cancel) + (void)ADBG_EXPECT(c, 0, pthread_join(thr, NULL)); + + TEEC_CloseSession(&session); + } + } + Do_ADBG_EndSubCase(c, "%s", subcase); +} + +static void xtest_tee_test_1009(ADBG_Case_t *c) +{ + xtest_tee_test_1009_subcase(c, "TEE Wait 0.1s", 100, false); + xtest_tee_test_1009_subcase(c, "TEE Wait 0.5s", 500, false); + xtest_tee_test_1009_subcase(c, "TEE Wait 2s cancel", 2000, true); + xtest_tee_test_1009_subcase(c, "TEE Wait 2s", 2000, false); +} +ADBG_CASE_DEFINE(regression, 1009, xtest_tee_test_1009, "TEE Wait"); + +static void xtest_tee_test_1010(ADBG_Case_t *c) +{ + unsigned int n = 0; + unsigned int idx = 0; + size_t memref_sz[] = { 1024, 65536 }; + + for (n = 1; n <= 7; n++) { + Do_ADBG_BeginSubCase(c, "Invalid memory access %u", n); + xtest_tee_test_invalid_mem_access(c, n); + Do_ADBG_EndSubCase(c, "Invalid memory access %u", n); + } + + for (idx = 0; idx < ARRAY_SIZE(memref_sz); idx++) { + for (n = 1; n <= 5; n++) { + Do_ADBG_BeginSubCase(c, + "Invalid memory access %u with %zu bytes memref", + n, memref_sz[idx]); + xtest_tee_test_invalid_mem_access2(c, n, memref_sz[idx]); + Do_ADBG_EndSubCase(c, + "Invalid memory access %u with %zu bytes memref", + n, memref_sz[idx]); + } + } +} +ADBG_CASE_DEFINE(regression, 1010, xtest_tee_test_1010, + "Invalid memory access"); + +static void xtest_tee_test_1011(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + struct xtest_crypto_session cs = { + c, &session, TA_RPC_CMD_CRYPT_SHA256, + TA_RPC_CMD_CRYPT_AES256ECB_ENC, + TA_RPC_CMD_CRYPT_AES256ECB_DEC + }; + struct xtest_crypto_session cs_privmem = { + c, &session, + TA_RPC_CMD_CRYPT_PRIVMEM_SHA256, + TA_RPC_CMD_CRYPT_PRIVMEM_AES256ECB_ENC, + TA_RPC_CMD_CRYPT_PRIVMEM_AES256ECB_DEC + }; + TEEC_UUID uuid = rpc_test_ta_uuid; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &uuid, NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "TA-to-TA via non-secure shared memory"); + /* + * Run the "complete crypto test suite" using TA-to-TA + * communication + */ + xtest_crypto_test(&cs); + Do_ADBG_EndSubCase(c, "TA-to-TA via non-secure shared memory"); + + Do_ADBG_BeginSubCase(c, "TA-to-TA via TA private memory"); + /* + * Run the "complete crypto test suite" using TA-to-TA + * communication via TA private memory. + */ + xtest_crypto_test(&cs_privmem); + Do_ADBG_EndSubCase(c, "TA-to-TA via TA private memory"); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1011, xtest_tee_test_1011, + "Test TA-to-TA features with User Crypt TA"); + +/* + * Note that this test is failing when + * - running twice in a raw + * - and the user TA is statically linked + * This is because the counter is not reseted when opening the first session + * in case the TA is statically linked + */ +static void xtest_tee_test_1012(ADBG_Case_t *c) +{ + TEEC_Session session1 = { }; + TEEC_Session session2 = { }; + uint32_t ret_orig = 0; + TEEC_UUID uuid = sims_test_ta_uuid; + + Do_ADBG_BeginSubCase(c, "Single Instance Multi Session"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + static const uint8_t in[] = { + 0x5A, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, + 0xF0, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, + 0xE9, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, + 0xF0, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x8E + }; + uint8_t out[32] = { }; + int i = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session1, &uuid, NULL, + &ret_orig))) + return; + + op.params[0].value.a = 0; + op.params[1].tmpref.buffer = (void *)in; + op.params[1].tmpref.size = sizeof(in); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session1, TA_SIMS_CMD_WRITE, &op, + &ret_orig)); + + for (i = 1; i < 3; i++) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session2, &uuid, NULL, + &ret_orig))) + continue; + + op.params[0].value.a = 0; + op.params[1].tmpref.buffer = out; + op.params[1].tmpref.size = sizeof(out); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session2, TA_SIMS_CMD_READ, + &op, &ret_orig)); + + if (!ADBG_EXPECT_BUFFER(c, in, sizeof(in), out, + sizeof(out))) { + Do_ADBG_Log("in:"); + Do_ADBG_HexLog(in, sizeof(in), 16); + Do_ADBG_Log("out:"); + Do_ADBG_HexLog(out, sizeof(out), 16); + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session1, + TA_SIMS_CMD_GET_COUNTER, + &op, &ret_orig)); + + (void)ADBG_EXPECT(c, 0, op.params[0].value.a); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session2, + TA_SIMS_CMD_GET_COUNTER, &op, + &ret_orig)); + + (void)ADBG_EXPECT(c, i, op.params[0].value.a); + TEEC_CloseSession(&session2); + } + + memset(out, 0, sizeof(out)); + op.params[0].value.a = 0; + op.params[1].tmpref.buffer = out; + op.params[1].tmpref.size = sizeof(out); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session1, TA_SIMS_CMD_READ, &op, + &ret_orig)); + + if (!ADBG_EXPECT(c, 0, memcmp(in, out, sizeof(in)))) { + Do_ADBG_Log("in:"); + Do_ADBG_HexLog(in, sizeof(in), 16); + Do_ADBG_Log("out:"); + Do_ADBG_HexLog(out, sizeof(out), 16); + } + + TEEC_CloseSession(&session1); + } + Do_ADBG_EndSubCase(c, "Single Instance Multi Session"); +} +ADBG_CASE_DEFINE(regression, 1012, xtest_tee_test_1012, + "Test Single Instance Multi Session features with SIMS TA"); + +struct test_1013_thread_arg { + const TEEC_UUID *uuid; + uint32_t cmd; + uint32_t repeat; + TEEC_SharedMemory *shm; + uint32_t error_orig; + TEEC_Result res; + uint32_t max_concurrency; + const uint8_t *in; + size_t in_len; + uint8_t *out; + size_t out_len; +}; + +static void *test_1013_thread(void *arg) +{ + struct test_1013_thread_arg *a = arg; + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint8_t p2 = TEEC_NONE; + uint8_t p3 = TEEC_NONE; + + a->res = xtest_teec_open_session(&session, a->uuid, NULL, + &a->error_orig); + if (a->res != TEEC_SUCCESS) + return NULL; + + op.params[0].memref.parent = a->shm; + op.params[0].memref.size = a->shm->size; + op.params[0].memref.offset = 0; + op.params[1].value.a = a->repeat; + op.params[1].value.b = 0; + op.params[2].tmpref.buffer = (void *)a->in; + op.params[2].tmpref.size = a->in_len; + op.params[3].tmpref.buffer = a->out; + op.params[3].tmpref.size = a->out_len; + + if (a->in_len) + p2 = TEEC_MEMREF_TEMP_INPUT; + if (a->out_len) + p3 = TEEC_MEMREF_TEMP_OUTPUT; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT, + TEEC_VALUE_INOUT, p2, p3); + + a->res = TEEC_InvokeCommand(&session, a->cmd, &op, &a->error_orig); + a->max_concurrency = op.params[1].value.b; + a->out_len = op.params[3].tmpref.size; + TEEC_CloseSession(&session); + return NULL; +} + +#define NUM_THREADS 3 + +static void xtest_tee_test_1013_single(ADBG_Case_t *c, double *mean_concurrency, + const TEEC_UUID *uuid) +{ + size_t nt = 0; + size_t n = 0; + size_t repeat = 1000; + TEEC_SharedMemory shm = { }; + size_t max_concurrency = 0; + struct test_1013_thread_arg arg[NUM_THREADS] = { }; + static const uint8_t sha256_in[] = { 'a', 'b', 'c' }; + static const uint8_t sha256_out[] = { + 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 + }; + uint8_t out[32] = { }; + pthread_t thr[NUM_THREADS] = { }; + bool skip = false; + + /* Decrease number of loops when pager has a small page pool */ + if (level == 0 && optee_pager_with_small_pool()) + repeat = 250; + + Do_ADBG_BeginSubCase(c, "Busy loop repeat %zu", repeat * 10); + *mean_concurrency = 0; + + shm.size = sizeof(struct ta_concurrent_shm); + shm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_AllocateSharedMemory(&xtest_teec_ctx, &shm))) + return; + + memset(shm.buffer, 0, shm.size); + max_concurrency = 0; + nt = NUM_THREADS; + + for (n = 0; n < nt; n++) { + arg[n].uuid = uuid; + arg[n].cmd = TA_CONCURRENT_CMD_BUSY_LOOP; + arg[n].repeat = repeat * 10; + arg[n].shm = &shm; + if (!ADBG_EXPECT(c, 0, pthread_create(thr + n, NULL, + test_1013_thread, arg + n))) + nt = n; /* break loop and start cleanup */ + } + + for (n = 0; n < nt; n++) { + ADBG_EXPECT(c, 0, pthread_join(thr[n], NULL)); + if (arg[n].res == TEEC_ERROR_OUT_OF_MEMORY && + !memcmp(uuid, &concurrent_large_ta_uuid, sizeof(*uuid))) { + Do_ADBG_Log("TEEC_ERROR_OUT_OF_MEMORY - ignored"); + skip = true; + continue; + } + ADBG_EXPECT_TEEC_SUCCESS(c, arg[n].res); + if (arg[n].max_concurrency > max_concurrency) + max_concurrency = arg[n].max_concurrency; + } + + /* + * Concurrency can be limited by several factors, for instance in a + * single CPU system it's dependent on the Preemption Model used by + * the kernel (Preemptible Kernel (Low-Latency Desktop) gives the + * best result there). + */ + if (!skip) { + (void)ADBG_EXPECT_COMPARE_UNSIGNED(c, max_concurrency, >, 0); + (void)ADBG_EXPECT_COMPARE_UNSIGNED(c, max_concurrency, <=, + NUM_THREADS); + *mean_concurrency += max_concurrency; + } + Do_ADBG_EndSubCase(c, "Busy loop repeat %zu", repeat * 10); + + Do_ADBG_BeginSubCase(c, "SHA-256 loop repeat %zu", repeat); + memset(shm.buffer, 0, shm.size); + memset(arg, 0, sizeof(arg)); + max_concurrency = 0; + nt = NUM_THREADS; + + for (n = 0; n < nt; n++) { + arg[n].uuid = uuid; + arg[n].cmd = TA_CONCURRENT_CMD_SHA256; + arg[n].repeat = repeat; + arg[n].shm = &shm; + arg[n].in = sha256_in; + arg[n].in_len = sizeof(sha256_in); + arg[n].out = out; + arg[n].out_len = sizeof(out); + if (!ADBG_EXPECT(c, 0, pthread_create(thr + n, NULL, + test_1013_thread, arg + n))) + nt = n; /* break loop and start cleanup */ + } + + for (n = 0; n < nt; n++) { + ADBG_EXPECT(c, 0, pthread_join(thr[n], NULL)); + if (arg[n].res == TEEC_ERROR_OUT_OF_MEMORY && + !memcmp(uuid, &concurrent_large_ta_uuid, sizeof(*uuid))) { + Do_ADBG_Log("TEEC_ERROR_OUT_OF_MEMORY - ignored"); + continue; + } + if (ADBG_EXPECT_TEEC_SUCCESS(c, arg[n].res)) + ADBG_EXPECT_BUFFER(c, sha256_out, sizeof(sha256_out), + arg[n].out, arg[n].out_len); + if (arg[n].max_concurrency > max_concurrency) + max_concurrency = arg[n].max_concurrency; + } + *mean_concurrency += max_concurrency; + Do_ADBG_EndSubCase(c, "SHA-256 loop repeat %zu", repeat); + + *mean_concurrency /= 2.0; + TEEC_ReleaseSharedMemory(&shm); +} + +static void xtest_tee_test_1013(ADBG_Case_t *c) +{ + int i = 0; + double mean_concurrency = 0; + double concurrency = 0; + int nb_loops = 24; + + if (level == 0) + nb_loops /= 2; + + Do_ADBG_BeginSubCase(c, "Using small concurrency TA"); + mean_concurrency = 0; + for (i = 0; i < nb_loops; i++) { + xtest_tee_test_1013_single(c, &concurrency, + &concurrent_ta_uuid); + mean_concurrency += concurrency; + } + mean_concurrency /= nb_loops; + + Do_ADBG_Log(" Number of parallel threads: %d", NUM_THREADS); + Do_ADBG_Log(" Mean concurrency: %g", mean_concurrency); + Do_ADBG_EndSubCase(c, "Using small concurrency TA"); + + Do_ADBG_BeginSubCase(c, "Using large concurrency TA"); + mean_concurrency = 0; + for (i = 0; i < nb_loops; i++) { + xtest_tee_test_1013_single(c, &concurrency, + &concurrent_large_ta_uuid); + mean_concurrency += concurrency; + } + mean_concurrency /= nb_loops; + + Do_ADBG_Log(" Number of parallel threads: %d", NUM_THREADS); + Do_ADBG_Log(" Mean concurrency: %g", mean_concurrency); + Do_ADBG_EndSubCase(c, "Using large concurrency TA"); +} +ADBG_CASE_DEFINE(regression, 1013, xtest_tee_test_1013, + "Test concurrency with concurrent TA"); + +#ifdef CFG_SECURE_DATA_PATH +static void xtest_tee_test_1014(ADBG_Case_t *c) +{ + UNUSED(c); + + int size = 17000; + int loop = 10; + const char *heap_name = DEFAULT_HEAP_NAME; + int rnd_offset = 1; + int test = 0; + int ret = 0; + + test = TEST_NS_TO_TA; + Do_ADBG_BeginSubCase(c, "SDP: NonSecure client invokes a SDP TA"); + ret = sdp_basic_test(test, size, loop, heap_name, rnd_offset, 0); + ADBG_EXPECT(c, 0, ret); + Do_ADBG_EndSubCase(c, "SDP: NonSecure client invokes a SDP TA"); + + test = TEST_TA_TO_TA; + Do_ADBG_BeginSubCase(c, "SDP: SDP TA invokes a SDP TA"); + ret = sdp_basic_test(test, size, loop, heap_name, rnd_offset, 0); + ADBG_EXPECT(c, 0, ret); + Do_ADBG_EndSubCase(c, "SDP: SDP TA invokes a SDP TA"); + + test = TEST_TA_TO_PTA; + Do_ADBG_BeginSubCase(c, "SDP: SDP TA invokes a test pTA (invoke_tests.pta)"); + ret = sdp_basic_test(test, size, loop, heap_name, rnd_offset, 0); + ADBG_EXPECT(c, 0, ret); + Do_ADBG_EndSubCase(c, "SDP: SDP TA invokes a test pTA (invoke_tests.pta)"); + + test = TEST_NS_TO_PTA; + Do_ADBG_BeginSubCase(c, "SDP: NSec CA invokes a test pTA (invoke_tests.pta) (should fail)"); + ret = sdp_basic_test(test, size, loop, heap_name, rnd_offset, 0); + ADBG_EXPECT(c, 1, ret); + Do_ADBG_EndSubCase(c, "SDP: NSec CA invokes a test pTA (invoke_tests.pta) (should fail)"); + + Do_ADBG_BeginSubCase(c, "SDP: Invoke TA with out of bounds SDP memref"); + ret = sdp_out_of_bounds_memref_test(size, heap_name, 0); + ADBG_EXPECT(c, 0, ret); + Do_ADBG_EndSubCase(c, NULL); +} +ADBG_CASE_DEFINE(regression, 1014, xtest_tee_test_1014, + "Test secure data path against SDP TAs and pTAs"); +#endif /*CFG_SECURE_DATA_PATH*/ + +#ifdef CFG_REE_FS +static void xtest_tee_test_1015(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + /* Pseudo TA is optional: warn and nicely exit if not found */ + res = xtest_teec_open_session(&session, &pta_invoke_tests_ta_uuid, NULL, + &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND) { + Do_ADBG_Log(" - 1015 - skip test, pseudo TA not found"); + return; + } + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, PTA_INVOKE_TESTS_CMD_FS_HTREE, + NULL, &ret_orig)); + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1015, xtest_tee_test_1015, + "FS hash-tree corner cases"); +#endif /*CFG_REE_FS*/ + +static void xtest_tee_test_1016(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig))) + return; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_TA2TA_MEMREF, &op, + &ret_orig)); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1016, xtest_tee_test_1016, + "Test TA to TA transfers (in/out/inout memrefs on the stack)"); + +static void xtest_tee_test_1017(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + TEEC_SharedMemory shm = { }; + size_t page_size = 4096; + + shm.size = 8 * page_size; + shm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_AllocateSharedMemory(&xtest_teec_ctx, &shm))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig))) + goto out; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT); + + /* + * The first two memrefs are supposed to be combined into in + * region and the last two memrefs should have one region each + * when the parameters are mapped for the TA. + */ + op.params[0].memref.parent = &shm; + op.params[0].memref.size = page_size; + op.params[0].memref.offset = 0; + + op.params[1].memref.parent = &shm; + op.params[1].memref.size = page_size; + op.params[1].memref.offset = page_size; + + op.params[2].memref.parent = &shm; + op.params[2].memref.size = page_size; + op.params[2].memref.offset = 4 * page_size; + + op.params[3].memref.parent = &shm; + op.params[3].memref.size = 2 * page_size; + op.params[3].memref.offset = 6 * page_size; + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_PARAMS, &op, + &ret_orig)); + + TEEC_CloseSession(&session); +out: + TEEC_ReleaseSharedMemory(&shm); +} +ADBG_CASE_DEFINE(regression, 1017, xtest_tee_test_1017, + "Test coalescing memrefs"); + +static void invoke_1byte_out_of_bounds(ADBG_Case_t *c, TEEC_Session *session, + TEEC_SharedMemory *shm) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result ret = TEEC_ERROR_GENERIC; + uint32_t ret_orig = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + + op.params[0].memref.parent = shm; + op.params[0].memref.size = shm->size / 2; + op.params[0].memref.offset = shm->size - (shm->size / 2) + 1; + + ret = TEEC_InvokeCommand(session, TA_OS_TEST_CMD_PARAMS, + &op, &ret_orig); + + ADBG_EXPECT_COMPARE_UNSIGNED(c, ret_orig, !=, TEEC_ORIGIN_TRUSTED_APP); + if (ret != TEEC_ERROR_BAD_PARAMETERS && ret != TEEC_ERROR_GENERIC) { + ADBG_EXPECT(c, TEEC_ERROR_BAD_PARAMETERS, ret); + ADBG_EXPECT(c, TEEC_ERROR_GENERIC, ret); + } +} + +static void xtest_tee_test_1018(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + TEEC_SharedMemory shm = { }; + TEEC_Result ret = TEEC_ERROR_GENERIC; + size_t page_size = 4096; + /* Intentionally not 4kB aligned and odd */ + uint8_t buffer[6001] = { }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, + &os_test_ta_uuid, + NULL, + &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "Out of bounds > 4kB on allocated shm"); + + shm.size = 8 * page_size; + shm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_AllocateSharedMemory(&xtest_teec_ctx, + &shm))) + goto out; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_MEMREF_PARTIAL_OUTPUT); + + /* + * The first two memrefs are supposed to be combined into in + * region and the last two memrefs should have one region each + * when the parameters are mapped for the TA. + */ + op.params[0].memref.parent = &shm; + op.params[0].memref.size = page_size; + op.params[0].memref.offset = 0; + + op.params[1].memref.parent = &shm; + op.params[1].memref.size = page_size; + op.params[1].memref.offset = page_size; + + op.params[2].memref.parent = &shm; + op.params[2].memref.size = page_size; + op.params[2].memref.offset = 4 * page_size; + + op.params[3].memref.parent = &shm; + op.params[3].memref.size = 3 * page_size; + op.params[3].memref.offset = 6 * page_size; + + ret = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_PARAMS, &op, + &ret_orig); + + ADBG_EXPECT_COMPARE_UNSIGNED(c, ret_orig, !=, TEEC_ORIGIN_TRUSTED_APP); + if (ret != TEEC_ERROR_BAD_PARAMETERS && ret != TEEC_ERROR_GENERIC) { + ADBG_EXPECT(c, TEEC_ERROR_BAD_PARAMETERS, ret); + ADBG_EXPECT(c, TEEC_ERROR_GENERIC, ret); + } + + TEEC_ReleaseSharedMemory(&shm); + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Out of bounds by 1 byte on registered shm"); + + memset(&shm, 0, sizeof(shm)); + shm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + shm.buffer = buffer; + shm.size = sizeof(buffer); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_RegisterSharedMemory(&xtest_teec_ctx, + &shm))) + goto out; + + invoke_1byte_out_of_bounds(c, &session, &shm); + + TEEC_ReleaseSharedMemory(&shm); + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Out of bounds by 1 byte ref on allocated shm"); + + memset(&shm, 0, sizeof(shm)); + shm.size = sizeof(buffer); + shm.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_AllocateSharedMemory(&xtest_teec_ctx, + &shm))) + goto out; + + invoke_1byte_out_of_bounds(c, &session, &shm); + + TEEC_ReleaseSharedMemory(&shm); + Do_ADBG_EndSubCase(c, NULL); + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1018, xtest_tee_test_1018, + "Test memref out of bounds"); + +static void xtest_tee_test_1019(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig))) + return; + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CALL_LIB, NULL, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CALL_LIB_PANIC, + NULL, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1019, xtest_tee_test_1019, + "Test dynamically linked TA"); + +static void xtest_tee_test_1020(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + /* Pseudo TA is optional: warn and nicely exit if not found */ + res = xtest_teec_open_session(&session, &pta_invoke_tests_ta_uuid, NULL, + &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND) { + Do_ADBG_Log(" - 1020 - skip test, pseudo TA not found"); + return; + } + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + res = TEEC_InvokeCommand(&session, PTA_INVOKE_TESTS_CMD_LOCKDEP, + NULL, &ret_orig); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) { + Do_ADBG_Log(" - 1020 - skip test, feature not " + "implemented"); + goto out; + } + /* Error */ + (void)ADBG_EXPECT_TEEC_SUCCESS(c, res); + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1020, xtest_tee_test_1020, + "Test lockdep algorithm"); + +static TEEC_Result open_sec_session(TEEC_Session *session, + const TEEC_UUID *uuid) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].tmpref.buffer = (void *)uuid; + op.params[0].tmpref.size = sizeof(*uuid); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(session, TA_SIMS_OPEN_TA_SESSION, + &op, &ret_orig); + if (res != TEEC_SUCCESS) + return TEEC_ERROR_GENERIC; + + return res; +} + +static TEEC_Result sims_get_counter(TEEC_Session *session, + uint32_t *counter) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(session, TA_SIMS_CMD_GET_COUNTER, + &op, &ret_orig); + if (res == TEEC_SUCCESS) + *counter = op.params[0].value.a; + + return res; +} + +static TEEC_Result trigger_panic(TEEC_Session *session, + const TEEC_UUID *uuid) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + if (!uuid) { + op.params[0].tmpref.buffer = NULL; + op.params[0].tmpref.size = 0; + } else { + op.params[0].tmpref.buffer = (void *)uuid; + op.params[0].tmpref.size = sizeof(*uuid); + } + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(session, TA_SIMS_CMD_PANIC, + &op, &ret_orig); +} + +static void test_panic_ca_to_ta(ADBG_Case_t *c, const TEEC_UUID *uuid, + bool multi_instance) +{ + TEEC_Result exp_res = TEEC_ERROR_GENERIC; + uint32_t counter = 0; + uint32_t ret_orig = 0; + uint32_t exp_counter = 0; + TEEC_Session cs[3] = { }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&cs[0], uuid, NULL, + &ret_orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&cs[1], uuid, NULL, + &ret_orig))) + goto bail0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, sims_get_counter(&cs[0], &counter))) + goto bail1; + + if (!ADBG_EXPECT(c, 0, counter)) + goto bail1; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, sims_get_counter(&cs[1], &counter))) + goto bail1; + + exp_counter = multi_instance ? 0 : 1; + if (!ADBG_EXPECT(c, exp_counter, counter)) + goto bail1; + + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + trigger_panic(&cs[1], NULL))) + goto bail1; + + exp_res = multi_instance ? TEEC_SUCCESS : TEEC_ERROR_TARGET_DEAD; + if (!ADBG_EXPECT_TEEC_RESULT(c, exp_res, + sims_get_counter(&cs[0], &counter))) + goto bail1; + + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + sims_get_counter(&cs[1], &counter))) + goto bail1; + + /* Attempt to open a session on panicked context */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&cs[1], uuid, NULL, + &ret_orig))) + goto bail1; + + /* Sanity check of still valid TA context */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&cs[2], uuid, NULL, + &ret_orig))) + goto bail1; + + /* Sanity check of still valid TA context */ + if (multi_instance) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + sims_get_counter(&cs[0], &counter))) + goto bail2; + + if (!ADBG_EXPECT(c, 0, counter)) + goto bail2; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, sims_get_counter(&cs[2], &counter))) + goto bail2; + + exp_counter = multi_instance ? 0 : 1; + if (!ADBG_EXPECT(c, exp_counter, counter)) + goto bail2; + +bail2: + TEEC_CloseSession(&cs[2]); +bail1: + TEEC_CloseSession(&cs[1]); +bail0: + TEEC_CloseSession(&cs[0]); +} + +static void test_panic_ta_to_ta(ADBG_Case_t *c, const TEEC_UUID *uuid1, + const TEEC_UUID *uuid2) +{ + uint32_t ret_orig = 0; + uint32_t counter = 0; + TEEC_Session cs[3] = { }; + + /* Test pre-conditions */ + /* 2.1 - CA opens a session toward TA1 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&cs[0], uuid1, NULL, + &ret_orig))) + return; + + /* 2.2 - CA opens a session toward TA2 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&cs[1], uuid2, NULL, + &ret_orig))) + goto bail0; + + /* 2.3 - TA1 opens a session toward TA2 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, open_sec_session(&cs[0], uuid2))) + goto bail1; + + /* 2.4 - CA invokes TA2 which panics */ + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + trigger_panic(&cs[1], NULL))) + goto bail1; + + /* Expected results */ + /* 2.5 - Expect CA->TA1 session is still alive */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, sims_get_counter(&cs[0], &counter))) + goto bail1; + + /* 2.6 - Expect CA->TA2 session is properly released */ + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + sims_get_counter(&cs[1], &counter))) + goto bail1; + +bail1: + TEEC_CloseSession(&cs[1]); +bail0: + TEEC_CloseSession(&cs[0]); + + memset(cs, 0, sizeof(cs)); + + /* Test pre-conditions */ + /* 2.1 - CA opens a session toward TA1 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&cs[0], uuid1, NULL, + &ret_orig))) + return; + + /* 2.2 - CA opens a session toward TA2 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&cs[1], uuid2, NULL, + &ret_orig))) + goto bail2; + + /* 2.3 - TA1 opens a session toward TA2 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, open_sec_session(&cs[0], uuid2))) + goto bail3; + + /* 2.4 - CA invokes TA1 which invokes TA2 which panics */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, trigger_panic(&cs[0], uuid2))) + goto bail3; + + /* Expected results */ + /* 2.5 - Expect CA->TA1 session is still alive */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, sims_get_counter(&cs[0], &counter))) + goto bail3; + + /* 2.6 - Expect CA->TA2 session is properly released */ + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + sims_get_counter(&cs[1], &counter))) + goto bail3; + +bail3: + TEEC_CloseSession(&cs[1]); +bail2: + TEEC_CloseSession(&cs[0]); +} + +static void xtest_tee_test_1021(ADBG_Case_t *c) +{ + Do_ADBG_BeginSubCase(c, "Multiple Instances Single Session"); + test_panic_ca_to_ta(c, &miss_test_ta_uuid, true); + Do_ADBG_EndSubCase(c, "Multiple Instances Single Session"); + + Do_ADBG_BeginSubCase(c, "Single Instance Multi Sessions"); + test_panic_ca_to_ta(c, &sims_test_ta_uuid, false); + Do_ADBG_EndSubCase(c, "Single Instance Multi Sessions"); + + Do_ADBG_BeginSubCase(c, "Single Instance Multi Sessions Keep Alive"); + test_panic_ca_to_ta(c, &sims_keepalive_test_ta_uuid, false); + Do_ADBG_EndSubCase(c, "Single Instance Multi Sessions Keep Alive"); + + Do_ADBG_BeginSubCase(c, "Multi Sessions TA to TA"); + test_panic_ta_to_ta(c, &sims_test_ta_uuid, + &sims_keepalive_test_ta_uuid); + Do_ADBG_EndSubCase(c, "Multi Sessions TA to TA"); +} +ADBG_CASE_DEFINE(regression, 1021, xtest_tee_test_1021, + "Test panic context release"); + +static void xtest_tee_test_1022(ADBG_Case_t *c) +{ + TEEC_Session session = { 0 }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CALL_LIB_DL, NULL, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CALL_LIB_DL_PANIC, + NULL, &ret_orig)); + + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1022, xtest_tee_test_1022, + "Test dlopen()/dlsym()/dlclose() API"); + +/* + * Testing the ELF initialization (.init_array) + * + * - The TA has a global variable which can also be accessed by the two shared + * libraries os_test_lib (linked with the TA) and os_test_lib_dl (loaded via + * dlopen()) + * - The TA and both libraries have initialization functions (declared with the + * "constructor" attribute) which perform the following: + * * The TA multiplies by 10 then adds 1 + * * os_test_lib multiplies by 10 then adds 2 + * * os_test_lib_dl multiplies by 10 then adds 3 + * By testing the variable value we make sure the initializations occurred in + * the correct order. + */ +static void xtest_tee_test_1023(ADBG_Case_t *c) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Session session = { 0 }; + uint32_t ret_orig = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_GET_GLOBAL_VAR, &op, + &ret_orig)); + + /* Expected: initialization of os_test_lib, then TA */ + (void)ADBG_EXPECT_COMPARE_SIGNED(c, op.params[0].value.a, ==, 21); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CALL_LIB_DL, NULL, + &ret_orig)); + + (void)ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_GET_GLOBAL_VAR, &op, + &ret_orig)); + + /* Expected: initialization of os_test_lib_dl */ + (void)ADBG_EXPECT_COMPARE_SIGNED(c, op.params[0].value.a, ==, 213); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1023, xtest_tee_test_1023, + "Test ELF initialization (.init_array)"); + +#ifdef CFG_CORE_TPM_EVENT_LOG +static void xtest_tee_test_1024(ADBG_Case_t *c) +{ + TEEC_Session session = {}; + uint32_t ret_orig = 0; + + xtest_teec_open_session(&session, &tpm_log_test_ta_uuid, + NULL, &ret_orig); + + Do_ADBG_BeginSubCase(c, "TPM test service invocation"); + ADBG_EXPECT_TEEC_SUCCESS(c, TEEC_InvokeCommand(&session, + TA_TPM_TEST_GET_LOG, + NULL, &ret_orig)); + Do_ADBG_EndSubCase(c, "TPM test service invocation"); + + Do_ADBG_BeginSubCase(c, "TPM test passing short buffer"); + ADBG_EXPECT_TEEC_SUCCESS(c, TEEC_InvokeCommand(&session, + TA_TPM_TEST_SHORT_BUF, + NULL, &ret_orig)); + Do_ADBG_EndSubCase(c, "TPM test passing short buffer"); + + TEEC_CloseSession(&session); +} + +ADBG_CASE_DEFINE(regression, 1024, xtest_tee_test_1024, + "Test PTA_SYSTEM_GET_TPM_EVENT_LOG Service"); +#endif /* CFG_CORE_TPM_EVENT_LOG */ + +static void xtest_tee_test_1025(ADBG_Case_t *c) +{ + TEEC_Session session = {}; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + uint8_t *empty_buf = NULL; + TEEC_SharedMemory shm = { }; + TEEC_Result res = TEEC_ERROR_GENERIC; + + Do_ADBG_BeginSubCase(c, "Invalid NULL buffer memref registration"); + + memset(&shm, 0, sizeof(shm)); + shm.flags = TEEC_MEM_INPUT; + shm.buffer = NULL; + shm.size = 0; + + ADBG_EXPECT(c, TEEC_ERROR_BAD_PARAMETERS, + TEEC_RegisterSharedMemory(&xtest_teec_ctx, &shm)); + + memset(&shm, 0, sizeof(shm)); + shm.flags = TEEC_MEM_OUTPUT; + shm.buffer = NULL; + shm.size = 0; + + ADBG_EXPECT(c, TEEC_ERROR_BAD_PARAMETERS, + TEEC_RegisterSharedMemory(&xtest_teec_ctx, &shm)); + + Do_ADBG_EndSubCase(c, "Invalid NULL buffer memref registration"); + + if (!xtest_teec_ctx.memref_null) { + Do_ADBG_Log("Skip subcases: MEMREF_NULL capability not supported"); + return; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, + &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + empty_buf = malloc(1); + if (!empty_buf) { + (void)ADBG_EXPECT_TEEC_SUCCESS(c, TEEC_ERROR_OUT_OF_MEMORY); + goto out_session; + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT); + + Do_ADBG_BeginSubCase(c, + "Input/Output MEMREF Buffer NULL - Size 0 bytes"); + + op.params[0].tmpref.buffer = empty_buf; + op.params[0].tmpref.size = 0; + + op.params[1].tmpref.buffer = NULL; + op.params[1].tmpref.size = 0; + + op.params[2].tmpref.buffer = empty_buf; + op.params[2].tmpref.size = 0; + + op.params[3].tmpref.buffer = NULL; + op.params[3].tmpref.size = 0; + + ADBG_EXPECT(c, TEE_SUCCESS, + TEEC_InvokeCommand(&session, + TA_OS_TEST_CMD_NULL_MEMREF_PARAMS, &op, + &ret_orig)); + + Do_ADBG_EndSubCase(c, "Input/Output MEMREF Buffer NULL - Size 0 bytes"); + + Do_ADBG_BeginSubCase(c, "Input MEMREF Buffer NULL - Size non 0 bytes"); + + op.params[0].tmpref.buffer = empty_buf; + op.params[0].tmpref.size = 1; + + op.params[1].tmpref.buffer = NULL; + op.params[1].tmpref.size = 0; + + op.params[2].tmpref.buffer = empty_buf; + op.params[2].tmpref.size = 0; + + op.params[3].tmpref.buffer = NULL; + op.params[3].tmpref.size = 0; + + ADBG_EXPECT(c, TEE_ERROR_BAD_PARAMETERS, + TEEC_InvokeCommand(&session, + TA_OS_TEST_CMD_NULL_MEMREF_PARAMS, &op, + &ret_orig)); + + TEEC_CloseSession(&session); + + Do_ADBG_EndSubCase(c, "Input MEMREF Buffer NULL - Size non 0 bytes"); + + Do_ADBG_BeginSubCase(c, "Input MEMREF Buffer NULL over PTA invocation"); + + /* Pseudo TA is optional: warn and nicely exit if not found */ + res = xtest_teec_open_session(&session, &pta_invoke_tests_ta_uuid, NULL, + &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND) { + Do_ADBG_Log(" - 1025 - skip test, pseudo TA not found"); + goto out; + } + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + op.params[0].tmpref.buffer = NULL; + op.params[0].tmpref.size = 0; + + ADBG_EXPECT(c, TEE_SUCCESS, + TEEC_InvokeCommand(&session, + PTA_INVOKE_TESTS_CMD_MEMREF_NULL, + &op, &ret_orig)); + +out_session: + TEEC_CloseSession(&session); +out: + Do_ADBG_EndSubCase(c, NULL); + free(empty_buf); +} +ADBG_CASE_DEFINE(regression, 1025, xtest_tee_test_1025, + "Test memref NULL and/or 0 bytes size"); + +#define TEE_UUID_NS_NAME_SIZE 128 + +/* + * TEE Client UUID name space identifier (UUIDv4) + * + * Value here is random UUID that is allocated as name space identifier for + * forming Client UUID's for TEE environment using UUIDv5 scheme. + */ +static const char *client_uuid_linux_ns = "58ac9ca0-2086-4683-a1b8-ec4bc08e01b6"; + +/* TEEC_LOGIN_PUBLIC's Client UUID is NIL UUID */ +static TEEC_UUID client_uuid_public = { }; + +static void xtest_tee_test_1026(ADBG_Case_t *c) +{ + TEEC_Result result = TEEC_ERROR_GENERIC; + uint32_t ret_orig = 0; + TEEC_Session session = { }; + uint32_t login = UINT32_MAX; + TEEC_UUID client_uuid = { }; + + result = TEEC_OpenSession(&xtest_teec_ctx, &session, &os_test_ta_uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + return; + + result = ta_os_test_cmd_client_identity(&session, &login, + &client_uuid); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, login, ==, TEEC_LOGIN_PUBLIC); + + ADBG_EXPECT_EQUAL(c, &client_uuid_public, &client_uuid, + sizeof(TEEC_UUID)); + +out: + TEEC_CloseSession(&session); +} + +ADBG_CASE_DEFINE(regression, 1026, xtest_tee_test_1026, + "Session: public login"); + +/* + * regression_1027 + * Depends on OpenSSL + * Depends on kernel commit c5b4312bea5d ("tee: optee: Add support for session + * login client UUID generation") + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c5b4312bea5d + * + * xtest skips the test when not built with OpenSSL. + */ +static void xtest_tee_test_1027(ADBG_Case_t *c) +{ +#ifdef OPENSSL_FOUND + TEEC_Result result = TEEC_ERROR_GENERIC; + uint32_t ret_orig = 0; + TEEC_Session session = { }; + uint32_t login = UINT32_MAX; + TEEC_UUID client_uuid = { }; + TEEC_UUID expected_client_uuid = { }; + TEEC_UUID uuid_ns = { }; + char uuid_name[TEE_UUID_NS_NAME_SIZE] = { }; + + result = xtest_uuid_from_str(&uuid_ns, client_uuid_linux_ns); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + return; + + sprintf(uuid_name, "uid=%x", geteuid()); + + result = xtest_uuid_v5(&expected_client_uuid, &uuid_ns, uuid_name, + strlen(uuid_name)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + return; + + result = TEEC_OpenSession(&xtest_teec_ctx, &session, &os_test_ta_uuid, + TEEC_LOGIN_USER, NULL, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + return; + + result = ta_os_test_cmd_client_identity(&session, &login, + &client_uuid); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, login, ==, TEEC_LOGIN_USER); + + ADBG_EXPECT_EQUAL(c, &expected_client_uuid, &client_uuid, + sizeof(TEEC_UUID)); + +out: + TEEC_CloseSession(&session); +#else /*!OPENSSL_FOUND*/ + UNUSED(c); + UNUSED(client_uuid_linux_ns); + /* xtest_uuid_v5() depends on OpenSSL */ + Do_ADBG_Log("OpenSSL not available, skipping test 1027"); +#endif +} + +ADBG_CASE_DEFINE(regression, 1027, xtest_tee_test_1027, + "Session: user login for current user"); + +/* + * regression_1028 + * Depends on kernel commit c5b4312bea5d ("tee: optee: Add support for session + * login client UUID generation") + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c5b4312bea5d + * + * xtest skips the test when not built with OpenSSL. + */ +static void xtest_tee_test_1028(ADBG_Case_t *c) +{ +#ifdef OPENSSL_FOUND + TEEC_Result result = TEEC_ERROR_GENERIC; + uint32_t ret_orig = 0; + TEEC_Session session = { }; + uint32_t login = UINT32_MAX; + TEEC_UUID client_uuid = { }; + TEEC_UUID expected_client_uuid = { }; + TEEC_UUID uuid_ns = { }; + char uuid_name[TEE_UUID_NS_NAME_SIZE] = { }; + uint32_t group = 0; + + group = getegid(); + + result = xtest_uuid_from_str(&uuid_ns, client_uuid_linux_ns); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + return; + + sprintf(uuid_name, "gid=%x", group); + + result = xtest_uuid_v5(&expected_client_uuid, &uuid_ns, uuid_name, + strlen(uuid_name)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + return; + + result = TEEC_OpenSession(&xtest_teec_ctx, &session, &os_test_ta_uuid, + TEEC_LOGIN_GROUP, &group, NULL, &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + return; + + result = ta_os_test_cmd_client_identity(&session, &login, + &client_uuid); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, result)) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(c, login, ==, TEEC_LOGIN_GROUP); + + ADBG_EXPECT_EQUAL(c, &expected_client_uuid, &client_uuid, + sizeof(TEEC_UUID)); + +out: + TEEC_CloseSession(&session); +#else /*!OPENSSL_FOUND*/ + UNUSED(c); + /* xtest_uuid_v5() depends on OpenSSL */ + Do_ADBG_Log("OpenSSL not available, skipping test 1028"); +#endif +} + +ADBG_CASE_DEFINE(regression, 1028, xtest_tee_test_1028, + "Session: group login for current user's effective group"); + +static void xtest_tee_test_1029(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Session session = { 0 }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "TLS variables (main program)"); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_TLS_TEST_MAIN, NULL, + &ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) + Do_ADBG_Log(" - 1029 - skip test, " + "TA returned TEEC_ERROR_NOT_SUPPORTED"); + else + ADBG_EXPECT_TEEC_SUCCESS(c, res); + Do_ADBG_EndSubCase(c, "TLS variables (main program)"); + + Do_ADBG_BeginSubCase(c, "TLS variables (shared library)"); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_TLS_TEST_SHLIB, NULL, + &ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) + Do_ADBG_Log(" - 1029 - skip test, " + "TA returned TEEC_ERROR_NOT_SUPPORTED"); + else + ADBG_EXPECT_TEEC_SUCCESS(c, res); + Do_ADBG_EndSubCase(c, "TLS variables (shared library)"); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1029, xtest_tee_test_1029, + "Test __thread attribute"); + +static void xtest_tee_test_1030(ADBG_Case_t *c) +{ + TEEC_Session session = { 0 }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "Before dlopen()"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_DL_PHDR, NULL, + &ret_orig)); + Do_ADBG_EndSubCase(c, "Before dlopen()"); + + Do_ADBG_BeginSubCase(c, "After dlopen()"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_DL_PHDR_DL, NULL, + &ret_orig)); + Do_ADBG_EndSubCase(c, "After dlopen()"); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1030, xtest_tee_test_1030, + "Test dl_iterate_phdr()"); + +#ifndef __clang__ +static void xtest_tee_test_1031(ADBG_Case_t *c) +{ + TEEC_Result ret = TEE_SUCCESS; + TEEC_Session session = { 0 }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "Global object constructor (main program)"); + ret = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CXX_CTOR_MAIN, NULL, + &ret_orig); + if (ret == TEEC_ERROR_NOT_SUPPORTED) { + printf("TA not built with C++ support, skipping C++ tests\n"); + Do_ADBG_EndSubCase(c, "Global object constructor (main program)"); + goto out; + + } + ADBG_EXPECT_TEEC_SUCCESS(c, ret); + Do_ADBG_EndSubCase(c, "Global object constructor (main program)"); + + Do_ADBG_BeginSubCase(c, "Global object constructor (shared library)"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CXX_CTOR_SHLIB, + NULL, &ret_orig)); + Do_ADBG_EndSubCase(c, "Global object constructor (shared library)"); + + Do_ADBG_BeginSubCase(c, "Global object constructor (dlopen()ed lib)"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CXX_CTOR_SHLIB_DL, + NULL, &ret_orig)); + Do_ADBG_EndSubCase(c, "Global object constructor (dlopen()ed lib)"); + + Do_ADBG_BeginSubCase(c, "Exceptions (simple)"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CXX_EXC_MAIN, NULL, + &ret_orig)); + Do_ADBG_EndSubCase(c, "Exceptions (simple)"); + + Do_ADBG_BeginSubCase(c, "Exceptions (mixed C/C++ frames)"); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CXX_EXC_MIXED, NULL, + &ret_orig)); + Do_ADBG_EndSubCase(c, "Exceptions (mixed C/C++ frames)"); +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1031, xtest_tee_test_1031, + "Test C++ features"); +#endif + +static void xtest_tee_test_1032(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Context ctx = { }; + TEEC_SharedMemory shm1 = { + .buffer = xtest_tee_test_1032, + .size = 32, + .flags = TEEC_MEM_INPUT, + }; + static const uint8_t dummy_data[32] = { 1, 2, 3, 4, }; + TEEC_SharedMemory shm2 = { + .buffer = (void *)dummy_data, + .size = sizeof(dummy_data), + .flags = TEEC_MEM_INPUT, + }; + + res = TEEC_InitializeContext(xtest_tee_name, &ctx); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + res = TEEC_RegisterSharedMemory(&ctx, &shm1); + if (ADBG_EXPECT_TEEC_SUCCESS(c, res)) + TEEC_ReleaseSharedMemory(&shm1); + + res = TEEC_RegisterSharedMemory(&ctx, &shm2); + if (ADBG_EXPECT_TEEC_SUCCESS(c, res)) + TEEC_ReleaseSharedMemory(&shm2); + + TEEC_FinalizeContext(&ctx); +} +ADBG_CASE_DEFINE(regression, 1032, xtest_tee_test_1032, + "Register read-only shared memory"); + +static void xtest_tee_test_1033(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + /* TA will ping the test plugin during open session operation */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &supp_plugin_test_ta_uuid, + NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "Pass values to/from a plugin"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].value.a = 20; + op.params[0].value.b = 10; + op.params[1].value.a = '+'; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, + TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE); + + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, + TA_SUPP_PLUGIN_CMD_PASS_VALUES, &op, + &ret_orig)); + ADBG_EXPECT(c, 30, op.params[0].value.a); + + /* reassign, because the values was changed during previous op */ + op.params[0].value.a = 20; + op.params[0].value.b = 10; + op.params[1].value.a = '-'; + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, + TA_SUPP_PLUGIN_CMD_PASS_VALUES, &op, + &ret_orig)); + ADBG_EXPECT(c, 10, op.params[0].value.a); + } + Do_ADBG_EndSubCase(c, "Pass values to/from a plugin"); + + Do_ADBG_BeginSubCase(c, "Pass array to a plugin"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint8_t to_plugin[] = { 0, 1, 2, 3, 4, 5 }; + + op.params[0].tmpref.buffer = to_plugin; + op.params[0].tmpref.size = sizeof(to_plugin); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, + TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, + TA_SUPP_PLUGIN_CMD_WRITE_ARR, + &op, &ret_orig)); + + /* + * The test plugin must calculate a sum of the input elements + * and store it to 'op.params[1].value.a' + */ + ADBG_EXPECT(c, 15, op.params[1].value.a); + } + Do_ADBG_EndSubCase(c, "Pass array to a plugin"); + + Do_ADBG_BeginSubCase(c, "Get array from a plugin"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + char from_plugin[64] = { }; + char expected_arr[] = "Array from plugin"; + size_t expectes_size = sizeof(expected_arr); + + op.params[0].tmpref.buffer = from_plugin; + op.params[0].tmpref.size = sizeof(from_plugin); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, + TEEC_VALUE_OUTPUT, TEEC_NONE, + TEEC_NONE); + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, + TA_SUPP_PLUGIN_CMD_GET_ARR, &op, + &ret_orig)); + ADBG_EXPECT(c, expectes_size, op.params[1].value.a); + ADBG_EXPECT_EQUAL(c, expected_arr, from_plugin, expectes_size); + } + Do_ADBG_EndSubCase(c, "Get array from a plugin"); + + Do_ADBG_BeginSubCase(c, "Not allow bad input to a plugin"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_BAD_PARAMETERS, + TEEC_InvokeCommand(&session, + TA_SUPP_PLUGIN_CMD_BAD_UUID, &op, + &ret_orig)); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_BAD_PARAMETERS, + TEEC_InvokeCommand(&session, + TA_SUPP_PLUGIN_CMD_BAD_IN_DATA, &op, + &ret_orig)); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_BAD_PARAMETERS, + TEEC_InvokeCommand(&session, + TA_SUPP_PLUGIN_CMD_BAD_IN_LEN, &op, + &ret_orig)); + } + Do_ADBG_EndSubCase(c, "Not allow bad input to a plugin"); + + Do_ADBG_BeginSubCase(c, "Call an unknown plugin"); + { + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND, + TEEC_InvokeCommand(&session, + TA_SUPP_PLUGIN_CMD_UNKNOWN_UUID, + &op, &ret_orig)); + } + Do_ADBG_EndSubCase(c, "Call an unknown plugin"); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1033, xtest_tee_test_1033, + "Test the supplicant plugin framework"); + +static void xtest_tee_test_1034(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + res = xtest_teec_open_session(&session, &large_ta_uuid, NULL, + &ret_orig); + if (res == TEEC_ERROR_OUT_OF_MEMORY) { + Do_ADBG_Log("TEEC_ERROR_OUT_OF_MEMORY - ignored"); + } else { + ADBG_EXPECT_TEEC_SUCCESS(c, res); + TEEC_CloseSession(&session); + } +} +ADBG_CASE_DEFINE(regression, 1034, xtest_tee_test_1034, + "Test loading a large TA"); + +#if defined(CFG_TA_BTI) +struct bti_test { + uint32_t cmd; + uint32_t func; +}; + +#define BTI_TEST(caller_func, bti_func) { \ + .cmd = caller_func, \ + .func = bti_func, \ + } + +static const struct bti_test bti_cases_success[] = { + BTI_TEST(TA_TEST_USING_BLR, TA_FUNC_BTI_C), + BTI_TEST(TA_TEST_USING_BLR, TA_FUNC_BTI_JC), + BTI_TEST(TA_TEST_USING_BR, TA_FUNC_BTI_J), + BTI_TEST(TA_TEST_USING_BR, TA_FUNC_BTI_JC), + BTI_TEST(TA_TEST_USING_BR_X16, TA_FUNC_BTI_C), + BTI_TEST(TA_TEST_USING_BR_X16, TA_FUNC_BTI_J), + BTI_TEST(TA_TEST_USING_BR_X16, TA_FUNC_BTI_JC), +}; + +static const struct bti_test bti_cases_panic[] = { + BTI_TEST(TA_TEST_USING_BLR, TA_FUNC_BTI_J), + BTI_TEST(TA_TEST_USING_BLR, TA_FUNC_BTI_NONE), + BTI_TEST(TA_TEST_USING_BR, TA_FUNC_BTI_C), + BTI_TEST(TA_TEST_USING_BR, TA_FUNC_BTI_NONE), + BTI_TEST(TA_TEST_USING_BR_X16, TA_FUNC_BTI_NONE), +}; + +static void get_cpu_feature(ADBG_Case_t *c, bool *bti) +{ + TEEC_Session session = {}; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + TEEC_Result res; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &bti_test_ta_uuid, + NULL, &ret_orig))) + return; + + res = TEEC_InvokeCommand(&session, TA_FEAT_BTI_IMPLEMENTED, &op, + &ret_orig); + if (!res) { + if(op.params[0].value.a) + *bti = true; + Do_ADBG_Log("FEAT_BTI is %simplemented", *bti ? "" : "NOT "); + } + + TEEC_CloseSession(&session); +} + +static void xtest_tee_test_1035(ADBG_Case_t *c) +{ + TEEC_Session session = {}; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + struct bti_test const *test = NULL; + uint32_t ret_orig = 0; + TEEC_Result res; + unsigned int n = 0; + bool cpu_feature_bti = false; + + Do_ADBG_BeginSubCase(c, "BTI Implemented"); + get_cpu_feature(c, &cpu_feature_bti); + Do_ADBG_EndSubCase(c, "BTI Implemented"); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &bti_test_ta_uuid, + NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "BTI Pass Cases"); + for (n = 0; n < ARRAY_SIZE(bti_cases_success); n++) { + test = &bti_cases_success[n]; + + op.params[0].value.a = test->func; + + res = TEEC_InvokeCommand(&session, test->cmd, &op, &ret_orig); + if (res == TEEC_ERROR_NOT_IMPLEMENTED) { + Do_ADBG_Log("Binary doesn't support BTI - skip tests"); + Do_ADBG_EndSubCase(c, "BTI Pass Cases"); + TEEC_CloseSession(&session); + return; + } + + Do_ADBG_BeginSubCase(c, "BTI Case %u", n); + + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + Do_ADBG_EndSubCase(c, "BTI Case %u", n); + } + Do_ADBG_EndSubCase(c, "BTI Pass Cases"); + + TEEC_CloseSession(&session); + + Do_ADBG_BeginSubCase(c, "BTI Exception Generation"); + for (n = 0; n < ARRAY_SIZE(bti_cases_panic); n++) { + test = &bti_cases_panic[n]; + res = TEEC_SUCCESS; + + if (cpu_feature_bti) + res = TEEC_ERROR_TARGET_DEAD; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &bti_test_ta_uuid, + NULL, &ret_orig))) + goto out; + + Do_ADBG_BeginSubCase(c, "BTI Case %u", n); + op.params[0].value.a = test->func; + + (void)ADBG_EXPECT_TEEC_RESULT(c, res, + TEEC_InvokeCommand(&session, test->cmd, &op, &ret_orig)); + + if (cpu_feature_bti) + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, + ret_orig); + + Do_ADBG_EndSubCase(c, "BTI Case %u", n); + + TEEC_CloseSession(&session); + } + +out: + Do_ADBG_EndSubCase(c, "BTI Exception Generation"); +} +ADBG_CASE_DEFINE(regression, 1035, xtest_tee_test_1035, "Test BTI"); +#endif + +static void xtest_tee_test_1036(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + TEEC_Result res = TEEC_SUCCESS; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "PAuth NOP test"); + + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_PAUTH_NOP, &op, + &ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) { + Do_ADBG_Log("Binary doesn't support PAuth - skip tests"); + goto out; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + Do_ADBG_EndSubCase(c, "PAuth NOP test"); + + Do_ADBG_BeginSubCase(c, "PAuth PAC corruption"); + + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + TEEC_InvokeCommand(&session, + TA_OS_TEST_CMD_PAUTH_CORRUPT_PAC, + &op, &ret_orig)); + + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + Do_ADBG_EndSubCase(c, "PAuth PAC corruption"); + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1036, xtest_tee_test_1036, + "Test PAuth (Pointer Authentication)"); + +#define ATT_MAX_KEYSZ 4096 + +#ifdef OPENSSL_FOUND +static RSA *att_key; +static size_t att_key_size; /* Actual key size (modulus size) in bytes */ + +/* + * buf = [ TA hash (32 bytes SHA256) | Signature (att_key_size bytes) ] + * Signature = RSA_SSA_PKCS1_PSS_MGF1(SHA256([nonce | TA hash]) + */ +static void check_signature(ADBG_Case_t *c, uint8_t *nonce, size_t nonce_size, + uint8_t *buf) +{ + unsigned char digest[SHA256_DIGEST_LENGTH] = { }; + unsigned char *sig = buf + SHA256_DIGEST_LENGTH; + unsigned char *ta_hash = buf; + uint8_t decr[ATT_MAX_KEYSZ / 8] = { }; + SHA256_CTX ctx = { }; + int salt_len = 32; /* Hard-coded in the PTA */ + int st = 0; + + if (!ADBG_EXPECT_NOT_NULL(c, att_key)) + return; + + SHA256_Init(&ctx); + SHA256_Update(&ctx, nonce, nonce_size); + SHA256_Update(&ctx, ta_hash, SHA256_DIGEST_LENGTH); + SHA256_Final(digest, &ctx); + + st = RSA_public_decrypt(att_key_size, sig, decr, att_key, + RSA_NO_PADDING); + ADBG_EXPECT_COMPARE_SIGNED(c, st, >, 0); + st = RSA_verify_PKCS1_PSS_mgf1(att_key, digest, EVP_sha256(), + EVP_sha256(), decr, salt_len); + ADBG_EXPECT_COMPARE_SIGNED(c, st, >, 0); +} + +static void free_att_key(void) +{ + RSA_free(att_key); + att_key = NULL; +} + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) + return 0; + + if (n != NULL) { + BN_free(r->n); + r->n = n; + } + + if (e != NULL) { + BN_free(r->e); + r->e = e; + } + + if (d != NULL) { + BN_free(r->d); + r->d = d; + } + + return 1; +} +#endif + +static void set_att_key(ADBG_Case_t *c, uint8_t *e, size_t e_sz, uint8_t *n, + size_t n_sz) +{ + BIGNUM *bn_e = NULL; + BIGNUM *bn_n = NULL; + int st = 0; + + att_key_size = n_sz; + att_key = RSA_new(); + if (!ADBG_EXPECT_NOT_NULL(c, att_key)) + return; + + bn_e = BN_bin2bn(e, e_sz, NULL); + if (!ADBG_EXPECT_NOT_NULL(c, bn_e)) + goto err; + bn_n = BN_bin2bn(n, n_sz, NULL); + if (!ADBG_EXPECT_NOT_NULL(c, bn_n)) + goto err; + + st = RSA_set0_key(att_key, bn_n, bn_e, BN_new()); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, st, !=, 0)) + goto err; + return; +err: + free_att_key(); +} +#else +#define check_signature(...) +#define set_att_key(...) +#define free_att_key() +#endif + +/* + * Verification of the output of the attestation PTA + * - (If hash != NULL) check buf contains the expected hash + * - (If OpenSSL is available) Check that the signature is valid + */ +static void check_measurement(ADBG_Case_t *c, uint8_t *nonce, size_t nonce_size, + uint8_t *hash, uint8_t *buf) +{ + (void)nonce; + (void)nonce_size; + + if (hash) + ADBG_EXPECT_BUFFER(c, hash, 32, buf, 32); + + check_signature(c, nonce, nonce_size, buf); +} + +/* Invoke attestation PTA to return the public key */ +static void get_att_public_key(ADBG_Case_t *c) +{ + uint8_t n[ATT_MAX_KEYSZ / 8] = { }; + uint8_t e[3] = { }; /* We know e == 65537... */ + size_t n_sz = sizeof(n); + size_t e_sz = sizeof(e); + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_UUID att_uuid = PTA_ATTESTATION_UUID; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_VALUE_OUTPUT, TEEC_NONE); + op.params[0].tmpref.buffer = e; + op.params[0].tmpref.size = e_sz; + op.params[1].tmpref.buffer = n; + op.params[1].tmpref.size = n_sz; + + res = xtest_teec_open_session(&session, &att_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + res = TEEC_InvokeCommand(&session, PTA_ATTESTATION_GET_PUBKEY, &op, + &ret_orig); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, op.params[2].value.a, ==, + TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256)) + goto out; + + e_sz = op.params[0].tmpref.size; + n_sz = op.params[1].tmpref.size; + set_att_key(c, e, e_sz, n, n_sz); +out: + TEEC_CloseSession(&session); +} + +/* Invoke attestation PTA to hash the TEE binary */ +static void attestation_tee(ADBG_Case_t *c) +{ + uint8_t measurement[TEE_SHA256_HASH_SIZE + ATT_MAX_KEYSZ / 8] = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint8_t nonce[4] = { 0x12, 0x34, 0x56, 0x78 }; + TEEC_UUID att_uuid = PTA_ATTESTATION_UUID; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + op.params[0].tmpref.buffer = nonce; + op.params[0].tmpref.size = sizeof(nonce); + op.params[1].tmpref.buffer = measurement; + op.params[1].tmpref.size = sizeof(measurement); + + res = xtest_teec_open_session(&session, &att_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + /* Hash TEE and check signature */ + res = TEEC_InvokeCommand(&session, PTA_ATTESTATION_HASH_TEE_MEMORY, &op, + &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + check_measurement(c, nonce, sizeof(nonce), NULL, measurement); + + TEEC_CloseSession(&session); +} + +/* Invoke attestation PTA to obtain the digest contained in the some TA shdr */ +static void attestation_ta_shdr(ADBG_Case_t *c) +{ + uint8_t measurement[TEE_SHA256_HASH_SIZE + ATT_MAX_KEYSZ / 8] = { }; + uint8_t nonce[6] = { 0xa0, 0x98, 0x76, 0x54, 0x32, 0x10 }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint8_t hash1[TEE_SHA256_HASH_SIZE] = { }; + uint8_t hash2[TEE_SHA256_HASH_SIZE] = { }; + TEEC_UUID att_uuid = PTA_ATTESTATION_UUID; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + int cmp = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE); + op.params[0].tmpref.buffer = (void *)&os_test_ta_uuid; + op.params[0].tmpref.size = sizeof(TEEC_UUID); + op.params[1].tmpref.buffer = nonce; + op.params[1].tmpref.size = sizeof(nonce); + op.params[2].tmpref.buffer = measurement; + op.params[2].tmpref.size = sizeof(measurement); + + res = xtest_teec_open_session(&session, &att_uuid, NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + /* Hash TA and check signature */ + res = TEEC_InvokeCommand(&session, PTA_ATTESTATION_GET_TA_SHDR_DIGEST, + &op, &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + check_measurement(c, nonce, sizeof(nonce), NULL, measurement); + /* Save hash */ + memcpy(hash1, measurement, 32); + + /* Hash TA again */ + memset(measurement, 0, sizeof(measurement)); + res = TEEC_InvokeCommand(&session, PTA_ATTESTATION_GET_TA_SHDR_DIGEST, + &op, &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + /* New hash should be identical */ + check_measurement(c, nonce, sizeof(nonce), hash1, measurement); + + /* Hash another TA */ + op.params[0].tmpref.buffer = (void *)&crypt_user_ta_uuid; + memset(measurement, 0, sizeof(measurement)); + res = TEEC_InvokeCommand(&session, PTA_ATTESTATION_GET_TA_SHDR_DIGEST, + &op, &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + check_measurement(c, nonce, sizeof(nonce), NULL, measurement); + memcpy(hash2, measurement, 32); + /* Different binaries should have different hashes */ + cmp = memcmp(hash1, hash2, sizeof(hash1)); + ADBG_EXPECT_COMPARE_SIGNED(c, cmp, !=, 0); + + TEEC_CloseSession(&session); +} + +/* + * Invoke os_test TA which will invoke attestation PTA to obtain a hash of + * itself. + */ +static void attestation_ta_memory(ADBG_Case_t *c) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint8_t nonce[6] = { 0xa0, 0x98, 0x76, 0x54, 0x32, 0x10 }; + uint8_t hash1[TEE_SHA256_HASH_SIZE] = { }; + uint8_t hash2[TEE_SHA256_HASH_SIZE] = { }; + uint8_t measurement[TEE_SHA256_HASH_SIZE + ATT_MAX_KEYSZ / 8] = { }; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + int cmp = 0; + + Do_ADBG_BeginSubCase(c, "Consecutive calls"); + + /* Open session to os_test TA */ + res = xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + op.params[0].tmpref.buffer = nonce; + op.params[0].tmpref.size = sizeof(nonce); + op.params[1].tmpref.buffer = measurement; + op.params[1].tmpref.size = sizeof(measurement); + + /* Hash TA */ + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ATTESTATION, &op, + &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + check_measurement(c, nonce, sizeof(nonce), NULL, measurement); + memcpy(hash1, measurement, 32); + + /* Hash TA again */ + memset(measurement, 0, sizeof(measurement)); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ATTESTATION, &op, + &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + /* New hash should be identical to hash1 */ + check_measurement(c, nonce, sizeof(nonce), hash1, measurement); + + Do_ADBG_EndSubCase(c, "Consecutive calls"); + + /* Close TA session, will cause unload of TA */ + TEEC_CloseSession(&session); + + Do_ADBG_BeginSubCase(c, "TA reload"); + + /* Load TA again and open a new session */ + res = xtest_teec_open_session(&session, &os_test_ta_uuid, NULL, + &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + if (res) + return; + + /* Hash TA one more time */ + memset(measurement, 0, sizeof(measurement)); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ATTESTATION, &op, + &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + /* Hash after reload should still be the same */ + check_measurement(c, nonce, sizeof(nonce), hash1, measurement); + + Do_ADBG_EndSubCase(c, "TA reload"); + + Do_ADBG_BeginSubCase(c, "Add shared library"); + + /* + * Invoke a TA command that causes some additional code to be mapped + * (shared library) + */ + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_CALL_LIB_DL, NULL, + &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + /* Hash TA one last time */ + memset(measurement, 0, sizeof(measurement)); + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_ATTESTATION, &op, + &ret_orig); + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + check_measurement(c, nonce, sizeof(nonce), NULL, measurement); + memcpy(hash2, measurement, 32); + + /* Different binaries mapped mean different hashes */ + cmp = memcmp(hash1, hash2, sizeof(hash1)); + ADBG_EXPECT_COMPARE_SIGNED(c, cmp, !=, 0); + + Do_ADBG_EndSubCase(c, "Add shared library"); + + TEEC_CloseSession(&session); +} + +static void xtest_tee_test_1037(ADBG_Case_t *c) +{ + TEEC_UUID att_uuid = PTA_ATTESTATION_UUID; + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + res = xtest_teec_open_session(&session, &att_uuid, NULL, &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND) { + Do_ADBG_Log(" skip test, pseudo TA not found"); + return; + } + + Do_ADBG_BeginSubCase(c, "Get public key"); + get_att_public_key(c); + Do_ADBG_EndSubCase(c, "Get public key"); + + Do_ADBG_BeginSubCase(c, "TEE attestation"); + attestation_tee(c); + Do_ADBG_EndSubCase(c, "TEE attestation"); + + Do_ADBG_BeginSubCase(c, "TA attestation (shdr)"); + attestation_ta_shdr(c); + Do_ADBG_EndSubCase(c, "TA attestation (shdr)"); + + Do_ADBG_BeginSubCase(c, "TA attestation (memory)"); + attestation_ta_memory(c); + Do_ADBG_EndSubCase(c, "TA attestation (memory)"); + + free_att_key(); +} +ADBG_CASE_DEFINE(regression, 1037, xtest_tee_test_1037, + "Remote attestation"); + +static void xtest_tee_test_1038(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + TEEC_Result res = TEEC_SUCCESS; + + Do_ADBG_BeginSubCase(c, "MTE use after free"); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_MEMTAG_USE_AFTER_FREE, + &op, &ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) { + Do_ADBG_Log("Binary doesn't support MTE - skip tests"); + goto out; + } + + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, res); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + TEEC_CloseSession(&session); + + Do_ADBG_EndSubCase(c, "MTE use after free"); + + Do_ADBG_BeginSubCase(c, "MTE invalid tag"); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_MEMTAG_INVALID_TAG, + &op, &ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) { + Do_ADBG_Log("Binary doesn't support MTE - skip tests"); + goto out; + } + + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, res); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + Do_ADBG_EndSubCase(c, "MTE invalid tag"); + + Do_ADBG_BeginSubCase(c, "MTE double free"); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_MEMTAG_DOUBLE_FREE, + &op, &ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) { + Do_ADBG_Log("Binary doesn't support MTE - skip tests"); + goto out; + } + + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, res); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + Do_ADBG_EndSubCase(c, "MTE double free"); + + Do_ADBG_BeginSubCase(c, "MTE buffer overrun"); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &os_test_ta_uuid, + NULL, &ret_orig))) + return; + + res = TEEC_InvokeCommand(&session, TA_OS_TEST_CMD_MEMTAG_BUFFER_OVERRUN, + &op, &ret_orig); + if (res == TEEC_ERROR_NOT_SUPPORTED) { + Do_ADBG_Log("Binary doesn't support MTE - skip tests"); + goto out; + } + + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, res); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TEE, ret_orig); + + Do_ADBG_EndSubCase(c, "MTE buffer overrun"); + + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 1038, xtest_tee_test_1038, + "Test MTE (Memory Tag Extension)"); + +static void xtest_tee_test_1039(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + Do_ADBG_BeginSubCase(c, "Load TA with two levels of subkeys"); + if (ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &subkey1_ta_uuid, + NULL, &ret_orig))) + TEEC_CloseSession(&session); + Do_ADBG_EndSubCase(c, "Load TA with two levels of subkeys"); + + Do_ADBG_BeginSubCase(c, "Load TA with identity subkey"); + if (ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &subkey2_ta_uuid, + NULL, &ret_orig))) + TEEC_CloseSession(&session); + Do_ADBG_EndSubCase(c, "Load TA with identity subkey"); + +} + + +ADBG_CASE_DEFINE(regression, 1039, xtest_tee_test_1039, + "Test subkey verification"); diff --git a/optee/optee_test/host/xtest/regression_2000.c b/optee/optee_test/host/xtest/regression_2000.c new file mode 100644 index 0000000..0591a42 --- /dev/null +++ b/optee/optee_test/host/xtest/regression_2000.c @@ -0,0 +1,929 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <__tee_tcpsocket_defines_extensions.h> +#include +#include + +#include "xtest_test.h" +#include "xtest_helpers.h" +#include "sock_server.h" +#include "rand_stream.h" + +struct socket_handle { + uint64_t buf[2]; + size_t blen; +}; + +static TEE_Result socket_tcp_open(TEEC_Session *session, uint32_t ip_vers, + const char *addr, uint16_t port, + struct socket_handle *handle, + uint32_t *error, uint32_t *ret_orig) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + memset(handle, 0, sizeof(*handle)); + + op.params[0].value.a = ip_vers; + op.params[0].value.b = port; + op.params[1].tmpref.buffer = (void *)addr; + op.params[1].tmpref.size = strlen(addr) + 1; + op.params[2].tmpref.buffer = handle->buf; + op.params[2].tmpref.size = sizeof(handle->buf); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_VALUE_OUTPUT); + + res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_TCP_OPEN, + &op, ret_orig); + + handle->blen = op.params[2].tmpref.size; + *error = op.params[3].value.a; + return res; +} + +static TEE_Result socket_udp_open(TEEC_Session *session, uint32_t ip_vers, + const char *addr, uint16_t port, + struct socket_handle *handle, + uint32_t *error, uint32_t *ret_orig) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + memset(handle, 0, sizeof(*handle)); + + op.params[0].value.a = ip_vers; + op.params[0].value.b = port; + op.params[1].tmpref.buffer = (void *)addr; + op.params[1].tmpref.size = strlen(addr) + 1; + op.params[2].tmpref.buffer = handle->buf; + op.params[2].tmpref.size = sizeof(handle->buf); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_VALUE_OUTPUT); + + res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_UDP_OPEN, + &op, ret_orig); + + handle->blen = op.params[2].tmpref.size; + *error = op.params[3].value.a; + return res; +} + +static TEE_Result socket_send(TEEC_Session *session, + struct socket_handle *handle, + const void *data, size_t *dlen, + uint32_t timeout, uint32_t *ret_orig) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].tmpref.buffer = handle->buf; + op.params[0].tmpref.size = handle->blen; + op.params[1].tmpref.buffer = (void *)data; + op.params[1].tmpref.size = *dlen; + op.params[2].value.a = timeout; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INOUT, TEEC_NONE); + + res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_SEND, &op, ret_orig); + + *dlen = op.params[2].value.b; + return res; +} + +static TEE_Result socket_recv(TEEC_Session *session, + struct socket_handle *handle, + void *data, size_t *dlen, + uint32_t timeout, uint32_t *ret_orig) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].tmpref.buffer = handle->buf; + op.params[0].tmpref.size = handle->blen; + op.params[1].tmpref.buffer = (void *)data; + op.params[1].tmpref.size = *dlen; + op.params[2].value.a = timeout; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_RECV, &op, ret_orig); + + *dlen = op.params[1].tmpref.size; + return res; +} + +static TEE_Result socket_get_error(TEEC_Session *session, + struct socket_handle *handle, + uint32_t *proto_error, uint32_t *ret_orig) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].tmpref.buffer = handle->buf; + op.params[0].tmpref.size = handle->blen; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_ERROR, &op, ret_orig); + + *proto_error = op.params[1].value.a; + return res; +} + +static TEE_Result socket_close(TEEC_Session *session, + struct socket_handle *handle, uint32_t *ret_orig) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].tmpref.buffer = handle->buf; + op.params[0].tmpref.size = handle->blen; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(session, TA_SOCKET_CMD_CLOSE, &op, ret_orig); +} + +static TEE_Result socket_ioctl(TEEC_Session *session, + struct socket_handle *handle, uint32_t ioctl_cmd, + void *data, size_t *dlen, uint32_t *ret_orig) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + op.params[0].tmpref.buffer = handle->buf; + op.params[0].tmpref.size = handle->blen; + op.params[1].tmpref.buffer = data; + op.params[1].tmpref.size = *dlen; + op.params[2].value.a = ioctl_cmd; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INOUT, + TEEC_VALUE_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(session, TA_SOCKET_CMD_IOCTL, &op, ret_orig); + + *dlen = op.params[1].tmpref.size; + return res; +} + + + +struct test_200x_io_state { + struct rand_stream *read_rs; + struct rand_stream *write_rs; + bool rfail; +}; + +static void test_200x_init_io_state(struct test_200x_io_state *s, + int read_seed, int write_seed) +{ + memset(s, 0, sizeof(*s)); + s->read_rs = rand_stream_alloc(read_seed, 100); + s->write_rs = rand_stream_alloc(write_seed, 100); + assert(s->read_rs && s->write_rs); +} + +static bool test_200x_tcp_accept_cb(void *ptr, int fd, short *events) +{ + (void)ptr; + (void)fd; + (void)events; + return true; +} + +static bool test_200x_tcp_read_cb(void *ptr, int fd, short *events) +{ + struct test_200x_io_state *iostate = ptr; + ssize_t r = 0; + uint8_t buf[100] = { }; + uint8_t buf2[100] = { }; + + (void)events; + r = read(fd, buf, sizeof(buf)); + if (r <= 0) + return false; + + rand_stream_read(iostate->read_rs, buf2, r); + if (memcmp(buf, buf2, r)) { + iostate->rfail = true; + return false; + } + + return true; +} + +static bool test_200x_tcp_write_cb(void *ptr, int fd, short *events) +{ + struct test_200x_io_state *iostate = ptr; + size_t num_bytes = 100; + const void *bytes = NULL; + ssize_t r = 0; + + (void)events; + + bytes = rand_stream_peek(iostate->write_rs, &num_bytes); + r = write(fd, bytes, num_bytes); + if (r < 0) + return false; + + rand_stream_advance(iostate->write_rs, num_bytes); + return true; +} + +static void xtest_tee_test_2001(ADBG_Case_t *c) +{ + struct sock_server ts = { }; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + uint32_t proto_error = 9; + struct socket_handle sh = { }; + uint8_t buf[64] = { }; + uint8_t buf2[64] = { }; + size_t blen = 0; + struct test_200x_io_state server_iostate = { }; + struct test_200x_io_state local_iostate = { }; + struct sock_io_cb cb = { + .accept = test_200x_tcp_accept_cb, + .read = test_200x_tcp_read_cb, + .write = test_200x_tcp_write_cb, + .ptr = &server_iostate, + }; + + test_200x_init_io_state(&server_iostate, 1, 2); + test_200x_init_io_state(&local_iostate, 2, 1); + + Do_ADBG_BeginSubCase(c, "Start server"); + if (!ADBG_EXPECT_TRUE(c, sock_server_init_tcp(&ts, &cb))) + return; + Do_ADBG_EndSubCase(c, "Start server"); + + Do_ADBG_BeginSubCase(c, "TCP Socket open"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &socket_ta_uuid, NULL, &ret_orig))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + Do_ADBG_EndSubCase(c, "TCP Socket open"); + + Do_ADBG_BeginSubCase(c, "TCP Socket send"); + blen = sizeof(buf); + rand_stream_read(local_iostate.write_rs, buf, blen); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(&session, &sh, + buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig))) + goto out_close_session; + ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf)); + Do_ADBG_EndSubCase(c, "TCP Socket send"); + + Do_ADBG_BeginSubCase(c, "TCP Socket recv"); + blen = sizeof(buf); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(&session, &sh, + buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig))) + goto out_close_session; + ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, sizeof(buf)); + rand_stream_read(local_iostate.read_rs, buf2, blen); + ADBG_EXPECT_BUFFER(c, buf2, blen, buf, blen); + Do_ADBG_EndSubCase(c, "TCP Socket recv"); + + /* + * All written bytes above (with the TA) is quite likely to have + * hit the tcp server by now. + */ + ADBG_EXPECT_TRUE(c, !server_iostate.rfail); + + Do_ADBG_BeginSubCase(c, "TCP Socket get error"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_get_error(&session, &sh, + &proto_error, &ret_orig))) + goto out_close_session; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, proto_error)) + goto out_close_session; + Do_ADBG_EndSubCase(c, "TCP Socket get error"); + + Do_ADBG_BeginSubCase(c, "TCP Socket close"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh, + &ret_orig))) + goto out_close_session; + Do_ADBG_EndSubCase(c, "TCP Socket close"); + + Do_ADBG_BeginSubCase(c, "TCP Socket ioctl"); + + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + blen = sizeof(buf); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, 0x00F00000, + buf, &blen, &ret_orig))) + goto out_close_session; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh, + &ret_orig))) + goto out_close_session; + + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + blen = sizeof(buf); + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + socket_ioctl(&session, &sh, + TEE_ISOCKET_PROTOCOLID_TCP << 24, + buf, &blen, &ret_orig)); + TEEC_CloseSession(&session); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &socket_ta_uuid, NULL, &ret_orig))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + blen = sizeof(buf); + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + socket_ioctl(&session, &sh, 0x32 << 24, + buf, &blen, &ret_orig)); + + Do_ADBG_EndSubCase(c, "TCP Socket ioctl"); + +out_close_session: + TEEC_CloseSession(&session); +out: + sock_server_uninit(&ts); +} +ADBG_CASE_DEFINE(regression, 2001, xtest_tee_test_2001, + "Trivial TCP iSocket API tests"); + +struct test_2002_barrier { + pthread_mutex_t mu; + pthread_barrier_t bar; +}; + +struct test_2002_arg { + bool success; + size_t tnum; + struct test_2002_barrier *bar; +}; + +static void xtest_2002_wait_barrier(struct test_2002_barrier *bar) +{ + /* + * Once the mutex is taken the barrier is initialized so the mutex + * can be released immediately. + */ + xtest_mutex_lock(&bar->mu); + xtest_mutex_unlock(&bar->mu); + xtest_barrier_wait(&bar->bar); +} + +static void *xtest_tee_test_2002_thread(void *arg) +{ + struct test_2002_arg *a = arg; + TEE_Result res = TEE_ERROR_GENERIC; + struct sock_server ts = { }; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + uint32_t proto_error = 0; + struct socket_handle sh = { }; + struct test_200x_io_state server_iostate = { }; + struct test_200x_io_state local_iostate = { }; + struct sock_io_cb cb = { + .accept = test_200x_tcp_accept_cb, + .read = test_200x_tcp_read_cb, + .write = test_200x_tcp_write_cb, + .ptr = &server_iostate, + }; + int seed[2] = { 1 + a->tnum * 2, 2 + a->tnum * 2 }; + size_t send_limit = 10000; + size_t recv_limit = 10000; + size_t sent_bytes = 0; + size_t recvd_bytes = 0; + + test_200x_init_io_state(&server_iostate, seed[0], seed[1]); + test_200x_init_io_state(&local_iostate, seed[1], seed[0]); + + if (!sock_server_init_tcp(&ts, &cb)) { + xtest_2002_wait_barrier(a->bar); + return NULL; + } + + res = xtest_teec_open_session(&session, &socket_ta_uuid, NULL, + &ret_orig); + + xtest_2002_wait_barrier(a->bar); + if (res != TEE_SUCCESS) + goto out; + + res = socket_tcp_open(&session, TEE_IP_VERSION_DC, ts.bind->host, + ts.bind->port, &sh, &proto_error, &ret_orig); + if (res != TEE_SUCCESS) + goto out_close_session; + + while (sent_bytes < send_limit && recvd_bytes < recv_limit) { + const void *peek = NULL; + uint8_t buf[64] = { }; + uint8_t buf2[64] = { }; + size_t blen = 0; + + blen = sizeof(buf); + peek = rand_stream_peek(local_iostate.write_rs, &blen); + res = socket_send(&session, &sh, peek, &blen, + TEE_TIMEOUT_INFINITE, &ret_orig); + if (res != TEE_SUCCESS) + goto out_close_session; + rand_stream_advance(local_iostate.write_rs, blen); + sent_bytes += blen; + + blen = sizeof(buf); + res = socket_recv(&session, &sh, buf, &blen, + TEE_TIMEOUT_INFINITE, &ret_orig); + if (res != TEE_SUCCESS) + goto out_close_session; + rand_stream_read(local_iostate.read_rs, buf2, blen); + if (memcmp(buf2, buf, blen)) + goto out_close_session; + recvd_bytes += blen; + } + + + res = socket_close(&session, &sh, &ret_orig); + if (res != TEE_SUCCESS) + goto out_close_session; + + /* + * All written bytes above (with the TA) is quite likely to have + * hit the tcp server by now. + */ + a->success = !server_iostate.rfail; + +out_close_session: + TEEC_CloseSession(&session); +out: + sock_server_uninit(&ts); + return NULL; +} + +#define NUM_THREADS 3 + +static void xtest_tee_test_2002(ADBG_Case_t *c) +{ + struct test_2002_barrier bar = { .mu = PTHREAD_MUTEX_INITIALIZER }; + struct test_2002_arg arg[NUM_THREADS] = { }; + size_t n = 0; + size_t nt = 0; + pthread_t thr[NUM_THREADS] = { }; + + Do_ADBG_BeginSubCase(c, "Stressing with %d threads", NUM_THREADS); + + xtest_mutex_lock(&bar.mu); + + nt = NUM_THREADS; + for (n = 0; n < nt; n++) { + arg[n].success = false; + arg[n].tnum = n; + arg[n].bar = &bar; + if (!ADBG_EXPECT(c, 0, pthread_create(thr + n, NULL, + xtest_tee_test_2002_thread, arg + n))) + nt = n; /* break loop and start cleanup */ + } + + xtest_barrier_init(&bar.bar, nt + 1); + xtest_mutex_unlock(&bar.mu); + xtest_barrier_wait(&bar.bar); + + for (n = 0; n < nt; n++) { + ADBG_EXPECT(c, 0, pthread_join(thr[n], NULL)); + ADBG_EXPECT_TRUE(c, arg[n].success); + } + + xtest_mutex_destroy(&bar.mu); + xtest_barrier_destroy(&bar.bar); + + Do_ADBG_EndSubCase(c, "Stressing with %d threads", NUM_THREADS); +} +ADBG_CASE_DEFINE(regression, 2002, xtest_tee_test_2002, + "Concurrent stressing TCP iSocket API tests"); + +static bool test_2003_accept_cb(void *ptr, int fd, short *events) +{ + int val = 0; + + (void)ptr; + (void)events; + + val = 4 * 1024; + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val))) + warn("test_2003_accept_cb: setsockopt"); + return true; +} + +static void xtest_tee_test_2003(ADBG_Case_t *c) +{ + struct sock_server ts = { }; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + uint32_t proto_error = 0; + struct socket_handle sh = { }; + void *buf = NULL; + const size_t blen0 = 16 * 1024; + size_t blen = 0; + uint32_t val = 0; + struct sock_io_cb cb = { .accept = test_2003_accept_cb }; + + Do_ADBG_BeginSubCase(c, "Start server"); + if (!ADBG_EXPECT_TRUE(c, sock_server_init_tcp(&ts, &cb))) + return; + buf = calloc(1, blen0); + if (!ADBG_EXPECT_NOT_NULL(c, buf)) + goto out; + Do_ADBG_EndSubCase(c, "Start server"); + + Do_ADBG_BeginSubCase(c, "TCP Socket open"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &socket_ta_uuid, NULL, &ret_orig))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_tcp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + blen = sizeof(val); + val = 4 * 1024; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, + TEE_TCP_SET_RECVBUF, &val, &blen, &ret_orig))) + goto out_close_session; + + blen = sizeof(val); + val = 4 * 1024; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, + TEE_TCP_SET_SENDBUF, &val, &blen, &ret_orig))) + goto out_close_session; + + Do_ADBG_EndSubCase(c, "TCP Socket open"); + + Do_ADBG_BeginSubCase(c, "TCP Socket send (10 ms timeout)"); + while (true) { + TEE_Result res = TEE_ERROR_GENERIC; + + blen = blen0; + memset(buf, 0, blen0); + res = socket_send(&session, &sh, buf, &blen, 10, &ret_orig); + if (res == TEE_ISOCKET_ERROR_TIMEOUT) + break; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out_close_session; + ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, blen0); + } + Do_ADBG_EndSubCase(c, "TCP Socket send (10 ms timeout)"); + + Do_ADBG_BeginSubCase(c, "TCP Socket recv (10 ms timeout)"); + blen = blen0; + ADBG_EXPECT_TEEC_RESULT(c, TEE_ISOCKET_ERROR_TIMEOUT, + socket_recv(&session, &sh, buf, &blen, + 10, &ret_orig)); + ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, blen0); + Do_ADBG_EndSubCase(c, "TCP Socket recv (10 ms timeout)"); + + Do_ADBG_BeginSubCase(c, "TCP Socket get error"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_get_error(&session, &sh, + &proto_error, &ret_orig))) + goto out_close_session; + ADBG_EXPECT_TEEC_RESULT(c, TEE_ISOCKET_ERROR_TIMEOUT, proto_error); + Do_ADBG_EndSubCase(c, "TCP Socket get error"); + +out_close_session: + TEEC_CloseSession(&session); +out: + free(buf); + sock_server_uninit(&ts); +} +ADBG_CASE_DEFINE(regression, 2003, xtest_tee_test_2003, + "Timeout TCP iSocket API tests"); + +static bool test_200x_udp_accept_cb(void *ptr, int fd, short *events) +{ + struct test_200x_io_state *iostate = ptr; + struct sockaddr_storage sass = { }; + struct sockaddr *sa = (struct sockaddr *)&sass; + socklen_t slen = sizeof(sass); + uint8_t buf[100] = { }; + uint8_t buf2[100] = { }; + ssize_t r = 0; + size_t l = 0; + + (void)events; + + r = recvfrom(fd, buf, sizeof(buf), 0, sa, &slen); + if (r == -1) + return false; + + l = r; + rand_stream_read(iostate->read_rs, buf2, l); + if (memcmp(buf, buf2, l)) + iostate->rfail = true; + + rand_stream_read(iostate->write_rs, buf, l); + return sendto(fd, buf, l, 0, sa, slen) != -1; +} + +static bool test_2004_send_recv(ADBG_Case_t *c, + struct test_200x_io_state *srv_ios, + struct test_200x_io_state *local_ios, + TEEC_Session *session, struct socket_handle *sh, + size_t send_sz, size_t recv_sz) +{ + bool ret = false; + uint32_t ret_orig = 0; + uint8_t *buf = calloc(1, send_sz); + uint8_t *buf2 = calloc(1, send_sz); + size_t blen = 0; + + /* If recv_sz < send_sz we're receiving a truncated datagram */ + + if (!ADBG_EXPECT_NOT_NULL(c, buf) || !ADBG_EXPECT_NOT_NULL(c, buf2) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, send_sz, >=, recv_sz)) + goto out; + + /* First we're sending the packet to the echo server */ + Do_ADBG_BeginSubCase(c, "UDP Socket send"); + blen = send_sz; + rand_stream_read(local_ios->write_rs, buf, blen); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_send(session, sh, + buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig))) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, send_sz)) + goto out; + Do_ADBG_EndSubCase(c, "UDP Socket send"); + + /* Then we're receiving the packet from the echo server */ + Do_ADBG_BeginSubCase(c, "UDP Socket recv"); + blen = 0; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(session, sh, + buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig))) + goto out; + /* + * blen was set to 0 so socket_recv() cannot block, this means the + * we have no guarantee that the sent UDP packet has reached its + * destination yet. If it has it must match the send size, else it + * must be 0. + */ + if (blen && !ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, send_sz)) + goto out; + blen = recv_sz; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_recv(session, sh, + buf, &blen, TEE_TIMEOUT_INFINITE, &ret_orig))) + goto out; + if (recv_sz < send_sz) { + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, >=, recv_sz)) + goto out; + } else { + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, send_sz)) + goto out; + } + rand_stream_read(local_ios->read_rs, buf2, send_sz); + if (!ADBG_EXPECT_BUFFER(c, buf2, recv_sz, buf, recv_sz)) + goto out; + if (!ADBG_EXPECT_TRUE(c, !srv_ios->rfail)) + goto out; + Do_ADBG_EndSubCase(c, "UDP Socket recv"); + + ret = true; +out: + free(buf); + free(buf2); + + return ret; +} + +static void xtest_tee_test_2004(ADBG_Case_t *c) +{ + struct sock_server ts = { }; + struct sock_server ts2 = { }; + struct sock_server ts3 = { }; + bool ts_inited = false; + bool ts2_inited = false; + bool ts3_inited = false; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + uint32_t proto_error = 0; + struct socket_handle sh = { }; + uint8_t buf[64] = { }; + size_t blen = 0; + uint16_t port = 0; + struct test_200x_io_state server_iostate = { }; + struct test_200x_io_state local_iostate = { }; + struct sock_io_cb cb = { + .accept = test_200x_udp_accept_cb, + .ptr = &server_iostate, + }; + + test_200x_init_io_state(&server_iostate, 1, 2); + test_200x_init_io_state(&local_iostate, 2, 1); + + Do_ADBG_BeginSubCase(c, "Start server"); + if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts, &cb))) + return; + ts_inited = true; + if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts2, &cb))) + goto out; + ts2_inited = true; + if (!ADBG_EXPECT_TRUE(c, sock_server_init_udp(&ts3, &cb))) + goto out; + ts3_inited = true; + Do_ADBG_EndSubCase(c, "Start server"); + + Do_ADBG_BeginSubCase(c, "UDP Socket open"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &socket_ta_uuid, NULL, &ret_orig))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + Do_ADBG_EndSubCase(c, "UDP Socket open"); + + Do_ADBG_BeginSubCase(c, "Normal send and receive"); + if (!ADBG_EXPECT_TRUE(c, test_2004_send_recv(c, &server_iostate, + &local_iostate, &session, + &sh, 64, 64))) + goto out_close_session; + Do_ADBG_EndSubCase(c, "Normal send and receive"); + + Do_ADBG_BeginSubCase(c, "UDP Socket truncated recv"); + if (!ADBG_EXPECT_TRUE(c, test_2004_send_recv(c, &server_iostate, + &local_iostate, &session, + &sh, 64, 32))) + goto out_close_session; + Do_ADBG_EndSubCase(c, "UDP Socket truncated recv"); + + Do_ADBG_BeginSubCase(c, "UDP Socket get error"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_get_error(&session, &sh, + &proto_error, &ret_orig))) + goto out_close_session; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, proto_error)) + goto out_close_session; + Do_ADBG_EndSubCase(c, "UDP Socket get error"); + + Do_ADBG_BeginSubCase(c, "UDP Socket close"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh, + &ret_orig))) + goto out_close_session; + Do_ADBG_EndSubCase(c, "UDP Socket close"); + + Do_ADBG_BeginSubCase(c, "UDP Socket ioctl"); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + blen = sizeof(buf); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, 0x00F00000, + buf, &blen, &ret_orig))) + goto out_close_session; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_close(&session, &sh, + &ret_orig))) + goto out_close_session; + + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + blen = sizeof(buf); + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + socket_ioctl(&session, &sh, + TEE_ISOCKET_PROTOCOLID_UDP << 24, + buf, &blen, &ret_orig)); + TEEC_CloseSession(&session); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &socket_ta_uuid, NULL, &ret_orig))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + + blen = sizeof(buf); + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + socket_ioctl(&session, &sh, 0x32 << 24, + buf, &blen, &ret_orig)); + TEEC_CloseSession(&session); + + Do_ADBG_EndSubCase(c, "UDP Socket ioctl"); + + Do_ADBG_BeginSubCase(c, "UDP Socket change port"); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &socket_ta_uuid, NULL, &ret_orig))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session, + TEE_IP_VERSION_DC, ts.bind->host, ts.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + sock_server_uninit(&ts); + ts_inited = false; + + port = ts2.bind->port; + blen = sizeof(port); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, + TEE_UDP_CHANGEPORT, &port, &blen, &ret_orig))) + goto out_close_session; + + + if (!ADBG_EXPECT_TRUE(c, test_2004_send_recv(c, &server_iostate, + &local_iostate, &session, + &sh, 64, 64))) + goto out_close_session; + TEEC_CloseSession(&session); + + Do_ADBG_EndSubCase(c, "UDP Socket change port"); + + Do_ADBG_BeginSubCase(c, "UDP Socket change addr"); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &socket_ta_uuid, NULL, &ret_orig))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_udp_open(&session, + TEE_IP_VERSION_DC, ts2.bind->host, ts2.bind->port, + &sh, &proto_error, &ret_orig))) + goto out_close_session; + sock_server_uninit(&ts2); + ts2_inited = false; + + port = ts3.bind->port; + blen = sizeof(port); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, + TEE_UDP_CHANGEPORT, &port, &blen, &ret_orig))) + goto out_close_session; + + blen = strlen(ts3.bind->host) + 1; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, socket_ioctl(&session, &sh, + TEE_UDP_CHANGEADDR, ts3.bind->host, &blen, &ret_orig))) + goto out_close_session; + + if (!ADBG_EXPECT_TRUE(c, test_2004_send_recv(c, &server_iostate, + &local_iostate, &session, + &sh, 64, 64))) + goto out_close_session; + + Do_ADBG_EndSubCase(c, "UDP Socket change addr"); + + +out_close_session: + TEEC_CloseSession(&session); +out: + if (ts_inited) + sock_server_uninit(&ts); + if (ts2_inited) + sock_server_uninit(&ts2); + if (ts3_inited) + sock_server_uninit(&ts3); +} +ADBG_CASE_DEFINE(regression, 2004, xtest_tee_test_2004, + "UDP iSocket API tests"); diff --git a/optee/optee_test/host/xtest/regression_4000.c b/optee/optee_test/host/xtest/regression_4000.c new file mode 100644 index 0000000..505c981 --- /dev/null +++ b/optee/optee_test/host/xtest/regression_4000.c @@ -0,0 +1,6167 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2021, SumUp Services GmbH + */ + +#include +#include +#include +#include +#include + +#include "xtest_test.h" +#include "xtest_helpers.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static TEEC_Result ta_crypt_cmd_reset_operation(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_RESET_OPERATION, &op, + &ret_orig); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + return res; +} + +static TEEC_Result ta_crypt_cmd_copy_operation(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle dst_oph, + TEE_OperationHandle src_oph) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)dst_oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)dst_oph; + + assert((uintptr_t)src_oph <= UINT32_MAX); + op.params[0].value.b = (uint32_t)(uintptr_t)src_oph; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_COPY_OPERATION, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + return res; +} + +static TEEC_Result ta_crypt_cmd_digest_update(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + const void *chunk, + size_t chunk_size) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + op.params[1].tmpref.buffer = (void *)chunk; + op.params[1].tmpref.size = chunk_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_DIGEST_UPDATE, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_digest_do_final(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + const void *chunk, + size_t chunk_len, void *hash, + size_t *hash_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)chunk; + op.params[1].tmpref.size = chunk_len; + + op.params[2].tmpref.buffer = (void *)hash; + op.params[2].tmpref.size = *hash_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_DIGEST_DO_FINAL, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *hash_len = op.params[2].tmpref.size; + + return res; +} + +static TEEC_Result ta_crypt_cmd_digest_extract(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + void *hash, size_t *hash_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)hash; + op.params[1].tmpref.size = *hash_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_DIGEST_EXTRACT, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *hash_len = op.params[1].tmpref.size; + + return res; +} +static TEE_Result ta_crypt_cmd_set_operation_key2(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + TEE_ObjectHandle key1, + TEE_ObjectHandle key2) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + assert((uintptr_t)key1 <= UINT32_MAX); + op.params[0].value.b = (uint32_t)(uintptr_t)key1; + + assert((uintptr_t)key2 <= UINT32_MAX); + op.params[1].value.a = (uint32_t)(uintptr_t)key2; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_SET_OPERATION_KEY2, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_mac_init(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + const void *iv, size_t iv_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + if (iv != NULL) { + op.params[1].tmpref.buffer = (void *)iv; + op.params[1].tmpref.size = iv_len; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE); + } else { + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + } + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_MAC_INIT, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_mac_update(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + const void *chunk, size_t chunk_size) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)chunk; + op.params[1].tmpref.size = chunk_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_MAC_UPDATE, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_mac_final_compute(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const void *chunk, + size_t chunk_len, + void *hash, + size_t *hash_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)chunk; + op.params[1].tmpref.size = chunk_len; + + op.params[2].tmpref.buffer = (void *)hash; + op.params[2].tmpref.size = *hash_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_MAC_FINAL_COMPUTE, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *hash_len = op.params[2].tmpref.size; + + return res; +} + +static TEEC_Result ta_crypt_cmd_mac_final_compare(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const void *chunk, + size_t chunk_len, + const uint8_t *hash, + size_t hash_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)chunk; + op.params[1].tmpref.size = chunk_len; + + op.params[2].tmpref.buffer = (void *)hash; + op.params[2].tmpref.size = hash_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_MAC_FINAL_COMPARE, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_cipher_init(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + const void *iv, size_t iv_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + if (iv != NULL) { + op.params[1].tmpref.buffer = (void *)iv; + op.params[1].tmpref.size = iv_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE); + } else { + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + } + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_CIPHER_INIT, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_cipher_update(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + const void *src, size_t src_len, + void *dst, size_t *dst_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)src; + op.params[1].tmpref.size = src_len; + + op.params[2].tmpref.buffer = dst; + op.params[2].tmpref.size = *dst_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_CIPHER_UPDATE, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *dst_len = op.params[2].tmpref.size; + + return res; +} + +static TEEC_Result ta_crypt_cmd_cipher_do_final(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const void *src, + size_t src_len, + void *dst, + size_t *dst_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)src; + op.params[1].tmpref.size = src_len; + + op.params[2].tmpref.buffer = (void *)dst; + op.params[2].tmpref.size = *dst_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_CIPHER_DO_FINAL, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *dst_len = op.params[2].tmpref.size; + + return res; +} + +static TEEC_Result ta_crypt_cmd_random_number_generate(ADBG_Case_t *c, + TEEC_Session *s, + void *buf, + size_t blen) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].tmpref.buffer = buf; + op.params[0].tmpref.size = blen; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_RANDOM_NUMBER_GENERATE, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + (void)ADBG_EXPECT_COMPARE_UNSIGNED(c, blen, ==, + op.params[0].tmpref.size); + return res; +} + +static TEEC_Result ta_crypt_cmd_ae_init(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + const void *nonce, size_t nonce_len, + size_t tag_len, size_t aad_len, + size_t payload_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + op.params[0].value.b = tag_len; + + op.params[1].tmpref.buffer = (void *)nonce; + op.params[1].tmpref.size = nonce_len; + + op.params[2].value.a = aad_len; + op.params[2].value.b = payload_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_AE_INIT, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + return res; +} + +static TEEC_Result ta_crypt_cmd_ae_update_aad(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + const void *aad, size_t aad_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)aad; + op.params[1].tmpref.size = aad_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_AE_UPDATE_AAD, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_ae_update(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const void *src, + size_t src_len, + void *dst, + size_t *dst_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)src; + op.params[1].tmpref.size = src_len; + + op.params[2].tmpref.buffer = (void *)dst; + op.params[2].tmpref.size = *dst_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_AE_UPDATE, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *dst_len = op.params[2].tmpref.size; + + return res; +} + +static TEEC_Result ta_crypt_cmd_ae_encrypt_final(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const void *src, + size_t src_len, void *dst, + size_t *dst_len, void *tag, + size_t *tag_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)src; + op.params[1].tmpref.size = src_len; + + op.params[2].tmpref.buffer = (void *)dst; + op.params[2].tmpref.size = *dst_len; + + op.params[3].tmpref.buffer = (void *)tag; + op.params[3].tmpref.size = *tag_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_AE_ENCRYPT_FINAL, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) { + *dst_len = op.params[2].tmpref.size; + *tag_len = op.params[3].tmpref.size; + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_ae_decrypt_final(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const void *src, size_t src_len, + void *dst, size_t *dst_len, + const void *tag, size_t tag_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = (void *)src; + op.params[1].tmpref.size = src_len; + + op.params[2].tmpref.buffer = dst; + op.params[2].tmpref.size = *dst_len; + + op.params[3].tmpref.buffer = (void *)tag; + op.params[3].tmpref.size = tag_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_INPUT); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_AE_DECRYPT_FINAL, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *dst_len = op.params[2].tmpref.size; + + return res; +} + +static TEEC_Result ta_crypt_cmd_asymmetric_operate(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + uint32_t cmd, + const TEE_Attribute *params, + uint32_t paramCount, + const void *src, + size_t src_len, + void *dst, + size_t *dst_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + uint8_t *buf = NULL; + size_t blen = 0; + + res = pack_attrs(params, paramCount, &buf, &blen); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = buf; + op.params[1].tmpref.size = blen; + + op.params[2].tmpref.buffer = (void *)src; + op.params[2].tmpref.size = src_len; + + op.params[3].tmpref.buffer = dst; + op.params[3].tmpref.size = *dst_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT); + + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *dst_len = op.params[3].tmpref.size; + + free(buf); + return res; +} + +static TEEC_Result ta_crypt_cmd_asymmetric_encrypt(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const TEE_Attribute *params, + uint32_t paramCount, + const void *src, + size_t src_len, + void *dst, + size_t *dst_len) +{ + return ta_crypt_cmd_asymmetric_operate(c, s, oph, + TA_CRYPT_CMD_ASYMMETRIC_ENCRYPT, + params, paramCount, + src, src_len, dst, dst_len); +} + +static TEEC_Result ta_crypt_cmd_asymmetric_decrypt(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const TEE_Attribute *params, + uint32_t paramCount, + const void *src, + size_t src_len, + void *dst, + size_t *dst_len) +{ + return ta_crypt_cmd_asymmetric_operate(c, s, oph, + TA_CRYPT_CMD_ASYMMETRIC_DECRYPT, + params, paramCount, + src, src_len, dst, dst_len); +} + +static TEEC_Result ta_crypt_cmd_asymmetric_sign(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const TEE_Attribute *params, + uint32_t paramCount, + const void *digest, + size_t digest_len, + void *signature, + size_t *signature_len) +{ + return ta_crypt_cmd_asymmetric_operate(c, s, oph, + TA_CRYPT_CMD_ASYMMETRIC_SIGN_DIGEST, params, paramCount, + digest, digest_len, signature, signature_len); +} + +static TEEC_Result ta_crypt_cmd_asymmetric_verify(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + const TEE_Attribute *params, + uint32_t paramCount, + const void *digest, + size_t digest_len, + const void *signature, + size_t signature_len) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + uint8_t *buf = NULL; + size_t blen = 0; + + res = pack_attrs(params, paramCount, &buf, &blen); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.params[1].tmpref.buffer = buf; + op.params[1].tmpref.size = blen; + + op.params[2].tmpref.buffer = (void *)digest; + op.params[2].tmpref.size = digest_len; + + op.params[3].tmpref.buffer = (void *)signature; + op.params[3].tmpref.size = signature_len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ASYMMETRIC_VERIFY_DIGEST, + &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + free(buf); + return res; +} + +static TEEC_Result ta_crypt_cmd_get_object_value_attribute(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectHandle o, + uint32_t attr_id, + uint32_t *valuea, + uint32_t *valueb) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)o <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)o; + op.params[0].value.b = attr_id; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_GET_OBJECT_VALUE_ATTRIBUTE, + &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) { + *valuea = op.params[1].value.a; + *valueb = op.params[1].value.b; + } + + return res; +} + +static TEEC_Result ta_crypt_cmd_generate_key(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectHandle o, + uint32_t key_size, + const TEE_Attribute *params, + uint32_t paramCount) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + uint8_t *buf = NULL; + size_t blen = 0; + + res = pack_attrs(params, paramCount, &buf, &blen); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + assert((uintptr_t)o <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)o; + op.params[0].value.b = key_size; + + op.params[1].tmpref.buffer = buf; + op.params[1].tmpref.size = blen; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_GENERATE_KEY, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + free(buf); + return res; +} + +static const uint8_t hash_data_md5_in1[] = { + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' +}; + +static const uint8_t hash_data_md5_out1[] = { + 0x61, 0x12, 0x71, 0x83, 0x70, 0x8d, 0x3a, 0xc7, + 0xf1, 0x9b, 0x66, 0x06, 0xfc, 0xae, 0x7d, 0xf6 +}; + +static const uint8_t hash_data_sha1_in1[] = { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' +}; + +static const uint8_t hash_data_sha1_out1[] = { + 0x4b, 0x98, 0x92, 0xb6, 0x52, 0x72, 0x14, 0xaf, + 0xc6, 0x55, 0xb8, 0xaa, 0x52, 0xf4, 0xd2, 0x03, + 0xc1, 0x5e, 0x7c, 0x9c +}; + +static const uint8_t hash_data_sha224_in1[] = { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' +}; + +static const uint8_t hash_data_sha224_out1[] = { + 0x08, 0x21, 0x69, 0xf9, 0x77, 0x1b, 0x80, 0x15, + 0xf3, 0x97, 0xae, 0xde, 0x5b, 0xba, 0xa2, 0x72, + 0x2d, 0x8f, 0x5c, 0x19, 0xfe, 0xd2, 0xe2, 0x68, + 0x92, 0x49, 0xd8, 0x44 +}; + +static const uint8_t hash_data_sha256_in1[] = { 'a', 'b', 'c' }; + +static const uint8_t hash_data_sha256_out1[] = { + 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 +}; + +static const uint8_t hash_data_sha256_in2[] = { 'e', 'f', 'g' }; + +static const uint8_t hash_data_sha256_out2[] = { + 0xd4, 0xff, 0xe8, 0xe9, 0xee, 0x0b, 0x48, 0xeb, + 0xa7, 0x16, 0x70, 0x61, 0x23, 0xa7, 0x18, 0x7f, + 0x32, 0xea, 0xe3, 0xbd, 0xcb, 0x0e, 0x77, 0x63, + 0xe4, 0x1e, 0x53, 0x32, 0x67, 0xbd, 0x8a, 0x53 +}; + + +static const uint8_t hash_data_sha384_in1[] = { + 'a', 'b', 'c', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' +}; + +static const uint8_t hash_data_sha384_out1[] = { + 0x4c, 0xab, 0x80, 0x9d, 0x96, 0x84, 0x01, 0x47, + 0x67, 0x0a, 0xc1, 0x7a, 0xb6, 0xb9, 0xf7, 0x6e, + 0x35, 0xa6, 0xb0, 0x8c, 0xf5, 0x2a, 0x3d, 0x64, + 0x9a, 0x8c, 0x7e, 0x0c, 0x55, 0x45, 0xd3, 0x7d, + 0x1f, 0x7f, 0x28, 0x34, 0x96, 0x14, 0x44, 0x2a, + 0xf5, 0x98, 0xa2, 0x95, 0x24, 0x76, 0x53, 0x97 +}; + +static const uint8_t hash_data_sha512_in1[] = { + 'a', 'b', 'c', 'd', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' +}; + +static const uint8_t hash_data_sha512_out1[] = { + 0x20, 0xd8, 0x64, 0x4f, 0x54, 0xa2, 0x5f, 0x6f, + 0x0a, 0xf9, 0xd5, 0x27, 0x7d, 0x17, 0xa8, 0x99, + 0x4c, 0x64, 0x3f, 0xd0, 0xf3, 0x83, 0x36, 0xee, + 0x93, 0x12, 0x55, 0xcd, 0x2e, 0x12, 0x34, 0xa0, + 0xc2, 0xaa, 0xf9, 0xbb, 0x15, 0xc5, 0xe9, 0xfa, + 0xf7, 0xa7, 0xda, 0xb8, 0x2f, 0x72, 0xa0, 0x47, + 0xe3, 0x02, 0x04, 0xe8, 0xa0, 0x35, 0x0c, 0x96, + 0x26, 0xd1, 0xcb, 0x8b, 0x47, 0x45, 0x25, 0xd0 +}; + +/* SHA-3 vectors from https://www.di-mgt.com.au/sha_testvectors.html */ +#define hash_data_sha3_in1 hash_data_sha256_in1 + +static const uint8_t hash_data_sha3_224_out1[] = { + 0xe6, 0x42, 0x82, 0x4c, 0x3f, 0x8c, 0xf2, 0x4a, + 0xd0, 0x92, 0x34, 0xee, 0x7d, 0x3c, 0x76, 0x6f, + 0xc9, 0xa3, 0xa5, 0x16, 0x8d, 0x0c, 0x94, 0xad, + 0x73, 0xb4, 0x6f, 0xdf +}; + +static const uint8_t hash_data_sha3_256_out1[] = { + 0x3a, 0x98, 0x5d, 0xa7, 0x4f, 0xe2, 0x25, 0xb2, + 0x04, 0x5c, 0x17, 0x2d, 0x6b, 0xd3, 0x90, 0xbd, + 0x85, 0x5f, 0x08, 0x6e, 0x3e, 0x9d, 0x52, 0x5b, + 0x46, 0xbf, 0xe2, 0x45, 0x11, 0x43, 0x15, 0x32 +}; + +static const uint8_t hash_data_sha3_384_out1[] = { + 0xec, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6f, 0xc9, + 0x26, 0x45, 0x9f, 0x58, 0xe2, 0xc6, 0xad, 0x8d, + 0xf9, 0xb4, 0x73, 0xcb, 0x0f, 0xc0, 0x8c, 0x25, + 0x96, 0xda, 0x7c, 0xf0, 0xe4, 0x9b, 0xe4, 0xb2, + 0x98, 0xd8, 0x8c, 0xea, 0x92, 0x7a, 0xc7, 0xf5, + 0x39, 0xf1, 0xed, 0xf2, 0x28, 0x37, 0x6d, 0x25 +}; + +static const uint8_t hash_data_sha3_512_out1[] = { + 0xb7, 0x51, 0x85, 0x0b, 0x1a, 0x57, 0x16, 0x8a, + 0x56, 0x93, 0xcd, 0x92, 0x4b, 0x6b, 0x09, 0x6e, + 0x08, 0xf6, 0x21, 0x82, 0x74, 0x44, 0xf7, 0x0d, + 0x88, 0x4f, 0x5d, 0x02, 0x40, 0xd2, 0x71, 0x2e, + 0x10, 0xe1, 0x16, 0xe9, 0x19, 0x2a, 0xf3, 0xc9, + 0x1a, 0x7e, 0xc5, 0x76, 0x47, 0xe3, 0x93, 0x40, + 0x57, 0x34, 0x0b, 0x4c, 0xf4, 0x08, 0xd5, 0xa5, + 0x65, 0x92, 0xf8, 0x27, 0x4e, 0xec, 0x53, 0xf0 +}; + +/* + * SHAKE output generated with: + * https://asecuritysite.com/hash/shake?m=abc&l=54 + */ +static const uint8_t hash_data_shake128_out1[] = { + 0x58, 0x81, 0x09, 0x2d, 0xd8, 0x18, 0xbf, 0x5c, + 0xf8, 0xa3, 0xdd, 0xb7, 0x93, 0xfb, 0xcb, 0xa7, + 0x40, 0x97, 0xd5, 0xc5, 0x26, 0xa6, 0xd3, 0x5f, + 0x97, 0xb8, 0x33, 0x51, 0x94, 0x0f, 0x2c, 0xc8, + 0x44, 0xc5, 0x0a, 0xf3, 0x2a, 0xcd, 0x3f, 0x2c, + 0xdd, 0x06, 0x65, 0x68, 0x70, 0x6f, 0x50, 0x9b, + 0xc1, 0xbd, 0xde, 0x58, 0x29, 0x5d +}; + +static const uint8_t hash_data_shake256_out1[] = { + 0x48, 0x33, 0x66, 0x60, 0x13, 0x60, 0xa8, 0x77, + 0x1c, 0x68, 0x63, 0x08, 0x0c, 0xc4, 0x11, 0x4d, + 0x8d, 0xb4, 0x45, 0x30, 0xf8, 0xf1, 0xe1, 0xee, + 0x4f, 0x94, 0xea, 0x37, 0xe7, 0x8b, 0x57, 0x39, + 0xd5, 0xa1, 0x5b, 0xef, 0x18, 0x6a, 0x53, 0x86, + 0xc7, 0x57, 0x44, 0xc0, 0x52, 0x7e, 0x1f, 0xaa, + 0x9f, 0x87, 0x26, 0xe4, 0x62, 0xa1 +}; + +/* + * SM3 + * https://tools.ietf.org/html/draft-sca-cfrg-sm3-02 + * Appendix A.1 + */ +static const uint8_t hash_data_sm3_a1_in[3] = "abc"; + +static const uint8_t hash_data_sm3_a1_out[] = { + 0x66, 0xc7, 0xf0, 0xf4, 0x62, 0xee, 0xed, 0xd9, + 0xd1, 0xf2, 0xd4, 0x6b, 0xdc, 0x10, 0xe4, 0xe2, + 0x41, 0x67, 0xc4, 0x87, 0x5c, 0xf2, 0xf7, 0xa2, + 0x29, 0x7d, 0xa0, 0x2b, 0x8f, 0x4b, 0xa8, 0xe0 +}; + +/* + * SM3 + * https://tools.ietf.org/html/draft-sca-cfrg-sm3-02 + * Appendix A.2 + */ +static const uint8_t hash_data_sm3_a2_in[] = { + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64, + 0x61, 0x62, 0x63, 0x64, 0x61, 0x62, 0x63, 0x64 +}; + +static const uint8_t hash_data_sm3_a2_out[] = { + 0xde, 0xbe, 0x9f, 0xf9, 0x22, 0x75, 0xb8, 0xa1, + 0x38, 0x60, 0x48, 0x89, 0xc1, 0x8e, 0x5a, 0x4d, + 0x6f, 0xdb, 0x70, 0xe5, 0x38, 0x7e, 0x57, 0x65, + 0x29, 0x3d, 0xcb, 0xa3, 0x9c, 0x0c, 0x57, 0x32 +}; + +struct xtest_hash_case { + uint32_t algo; + size_t in_incr; + const uint8_t *in; + size_t in_len; + const uint8_t *out; + size_t out_len; +}; + +#define XTEST_HASH_CASE(algo, in_incr, in, out) \ + { (algo), (in_incr), (in), ARRAY_SIZE(in), (out), ARRAY_SIZE(out) } + +static const struct xtest_hash_case hash_cases[] = { + XTEST_HASH_CASE(TEE_ALG_MD5, 6, hash_data_md5_in1, + hash_data_md5_out1), + XTEST_HASH_CASE(TEE_ALG_SHA1, 3, hash_data_sha1_in1, + hash_data_sha1_out1), + XTEST_HASH_CASE(TEE_ALG_SHA224, 7, hash_data_sha224_in1, + hash_data_sha224_out1), + XTEST_HASH_CASE(TEE_ALG_SHA256, 1, hash_data_sha256_in1, + hash_data_sha256_out1), + XTEST_HASH_CASE(TEE_ALG_SHA256, 1, hash_data_sha256_in2, + hash_data_sha256_out2), + XTEST_HASH_CASE(TEE_ALG_SHA384, 1, hash_data_sha384_in1, + hash_data_sha384_out1), + XTEST_HASH_CASE(TEE_ALG_SHA512, 1, hash_data_sha512_in1, + hash_data_sha512_out1), + XTEST_HASH_CASE(TEE_ALG_SHA3_224, 1, hash_data_sha3_in1, + hash_data_sha3_224_out1), + XTEST_HASH_CASE(TEE_ALG_SHA3_256, 1, hash_data_sha3_in1, + hash_data_sha3_256_out1), + XTEST_HASH_CASE(TEE_ALG_SHA3_384, 1, hash_data_sha3_in1, + hash_data_sha3_384_out1), + XTEST_HASH_CASE(TEE_ALG_SHA3_512, 1, hash_data_sha3_in1, + hash_data_sha3_512_out1), + XTEST_HASH_CASE(TEE_ALG_SHAKE128, 1, hash_data_sha3_in1, + hash_data_shake128_out1), + XTEST_HASH_CASE(TEE_ALG_SHAKE256, 1, hash_data_sha3_in1, + hash_data_shake256_out1), + XTEST_HASH_CASE(TEE_ALG_SM3, 2, hash_data_sm3_a1_in, + hash_data_sm3_a1_out), + XTEST_HASH_CASE(TEE_ALG_SM3, 19, hash_data_sm3_a2_in, + hash_data_sm3_a2_out), +}; + +static void xtest_tee_test_4001(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + + for (n = 0; n < ARRAY_SIZE(hash_cases); n++) { + TEE_OperationHandle op1 = TEE_HANDLE_NULL; + TEE_OperationHandle op2 = TEE_HANDLE_NULL; + uint8_t out[64] = { }; + size_t out_size = 0; + + if (hash_cases[n].algo == TEE_ALG_SM3 && + !ta_crypt_cmd_is_algo_supported(c, &session, TEE_ALG_SM3, + TEE_CRYPTO_ELEMENT_NONE)) { + Do_ADBG_Log("SM3 not supported: skip subcase"); + continue; + } + + Do_ADBG_BeginSubCase(c, "Hash case %d algo 0x%x", + (int)n, (unsigned int)hash_cases[n].algo); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op1, + hash_cases[n].algo, + TEE_MODE_DIGEST, 0))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op2, + hash_cases[n].algo, + TEE_MODE_DIGEST, 0))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_update(c, &session, op1, + hash_cases[n].in, + hash_cases[n].in_incr))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_copy_operation(c, &session, op2, op1))) + goto out; + + out_size = hash_cases[n].out_len; + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_do_final(c, &session, op2, + hash_cases[n].in + hash_cases[n].in_incr, + hash_cases[n].in_len - hash_cases[n].in_incr, + out, &out_size))) + goto out; + + (void)ADBG_EXPECT_BUFFER(c, hash_cases[n].out, + hash_cases[n].out_len, out, out_size); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_reset_operation(c, &session, op1))) + goto out; + + out_size = hash_cases[n].out_len; + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_do_final(c, &session, op1, + hash_cases[n].in, + hash_cases[n].in_len, out, + &out_size))) + goto out; + + (void)ADBG_EXPECT_BUFFER(c, hash_cases[n].out, + hash_cases[n].out_len, out, out_size); + + /* + * Invoke TEE_DigestDoFinal() a second time to check that state + * was properly reset + */ + out_size = hash_cases[n].out_len; + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_do_final(c, &session, op1, + hash_cases[n].in, + hash_cases[n].in_len, out, + &out_size))) + goto out; + + (void)ADBG_EXPECT_BUFFER(c, hash_cases[n].out, + hash_cases[n].out_len, out, out_size); + + /* + * Test that TEE_DigestExtract() and TEE_DigestDoFinal() + * work together. + */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_update(c, &session, op1, + hash_cases[n].in, + hash_cases[n].in_len))) + goto out; + + out_size = hash_cases[n].in_incr; + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_extract(c, &session, op1, + out, &out_size))) + goto out; + ADBG_EXPECT_BUFFER(c, hash_cases[n].out, + hash_cases[n].in_incr, out, out_size); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_copy_operation(c, &session, op2, op1))) + goto out; + + out_size = hash_cases[n].out_len - hash_cases[n].in_incr; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_do_final(c, &session, op1, + NULL, 0, out, &out_size))) + goto out; + ADBG_EXPECT_BUFFER(c, hash_cases[n].out + hash_cases[n].in_incr, + hash_cases[n].out_len - + hash_cases[n].in_incr, out, out_size); + + out_size = hash_cases[n].out_len - hash_cases[n].in_incr; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_extract(c, &session, op2, + out, &out_size))) + goto out; + ADBG_EXPECT_BUFFER(c, hash_cases[n].out + hash_cases[n].in_incr, + hash_cases[n].out_len - + hash_cases[n].in_incr, out, out_size); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op1))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op2))) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + } + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4001, xtest_tee_test_4001, + "Test TEE Internal API hash operations"); + +struct xtest_mac_case { + uint32_t algo; + uint32_t key_type; + const uint8_t *key; + size_t key_len; + size_t in_incr; + const uint8_t *in; + size_t in_len; + const uint8_t *out; + size_t out_len; + bool multiple_incr; +}; + +#define XTEST_MAC_CASE_1(algo, key_type, key, in_incr, in, out) \ + { (algo), (key_type), (key), ARRAY_SIZE(key), \ + (in_incr), (in), ARRAY_SIZE(in), (out), ARRAY_SIZE(out), false } + +#define XTEST_MAC_CASE_MULT(algo, key_type, key, in_incr, in, out) \ + { (algo), (key_type), (key), ARRAY_SIZE(key), \ + (in_incr), (in), ARRAY_SIZE(in), (out), ARRAY_SIZE(out), true } + +#define XTEST_MAC_CASE(algo, key_type, key, in_incr, in, out) \ + XTEST_MAC_CASE_1((algo), (key_type), (key), (in_incr), (in), (out)), \ + XTEST_MAC_CASE_MULT((algo), (key_type), (key), (in_incr), (in), (out)) + +#define XTEST_MAC_CBC_CASE(algo, key_type, vect, in_incr) \ + XTEST_MAC_CASE((algo), (key_type), \ + mac_cbc_ ## vect ## _key, (in_incr), \ + mac_cbc_ ## vect ## _data, mac_cbc_ ## vect ## _out) + +#define XTEST_MAC_CMAC_CASE(vect, in_incr) \ + XTEST_MAC_CASE(TEE_ALG_AES_CMAC, TEE_TYPE_AES, \ + mac_cmac_ ## vect ## _key, (in_incr), \ + mac_cmac_ ## vect ## _data, mac_cmac_ ## vect ## _out) + +#define XTEST_MAC_DES3_CMAC_CASE(vect, in_incr) \ + XTEST_MAC_CASE(TEE_ALG_DES3_CMAC, TEE_TYPE_DES3, \ + mac_des3_cmac_ ## vect ## _key, (in_incr), \ + mac_des3_cmac_ ## vect ## _data, mac_des3_cmac_ ## vect ## _out) + +static const struct xtest_mac_case mac_cases[] = { + XTEST_MAC_CASE(TEE_ALG_HMAC_MD5, TEE_TYPE_HMAC_MD5, + mac_data_md5_key1, + 4, mac_data_md5_in1, mac_data_md5_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA1, TEE_TYPE_HMAC_SHA1, + mac_data_sha1_key1, + 5, mac_data_sha1_in1, mac_data_sha1_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA224, TEE_TYPE_HMAC_SHA224, + mac_data_sha224_key1, + 8, mac_data_sha224_in1, mac_data_sha224_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA256, TEE_TYPE_HMAC_SHA256, + mac_data_sha256_key1, + 1, mac_data_sha256_in1, mac_data_sha256_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA256, TEE_TYPE_HMAC_SHA256, + mac_data_sha256_key2, + 7, mac_data_sha256_in2, mac_data_sha256_out2), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA384, TEE_TYPE_HMAC_SHA384, + mac_data_sha384_key1, + 11, mac_data_sha384_in1, mac_data_sha384_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA512, TEE_TYPE_HMAC_SHA512, + mac_data_sha512_key1, + 13, mac_data_sha512_in1, mac_data_sha512_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA3_224, TEE_TYPE_HMAC_SHA3_224, + mac_data_sha3_224_key1, + 13, mac_data_sha3_224_in1, mac_data_sha3_224_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA3_256, TEE_TYPE_HMAC_SHA3_256, + mac_data_sha3_256_key1, + 13, mac_data_sha3_256_in1, mac_data_sha3_256_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA3_384, TEE_TYPE_HMAC_SHA3_384, + mac_data_sha3_384_key1, + 13, mac_data_sha3_384_in1, mac_data_sha3_384_out1), + XTEST_MAC_CASE(TEE_ALG_HMAC_SHA3_512, TEE_TYPE_HMAC_SHA3_512, + mac_data_sha3_512_key1, + 13, mac_data_sha3_512_in1, mac_data_sha3_512_out1), + + XTEST_MAC_CBC_CASE(TEE_ALG_AES_CBC_MAC_NOPAD, TEE_TYPE_AES, vect1, 14), + XTEST_MAC_CBC_CASE(TEE_ALG_DES_CBC_MAC_NOPAD, TEE_TYPE_DES, vect2, 16), + XTEST_MAC_CBC_CASE(TEE_ALG_DES3_CBC_MAC_NOPAD, TEE_TYPE_DES3, vect3, + 17), + XTEST_MAC_CBC_CASE(TEE_ALG_AES_CBC_MAC_PKCS5, TEE_TYPE_AES, vect4, 11), + XTEST_MAC_CBC_CASE(TEE_ALG_DES_CBC_MAC_PKCS5, TEE_TYPE_DES, vect5, 9), + XTEST_MAC_CBC_CASE(TEE_ALG_DES3_CBC_MAC_PKCS5, TEE_TYPE_DES3, vect6, 4), + XTEST_MAC_CBC_CASE(TEE_ALG_AES_CBC_MAC_PKCS5, TEE_TYPE_AES, vect7, 3), + XTEST_MAC_CBC_CASE(TEE_ALG_DES_CBC_MAC_PKCS5, TEE_TYPE_DES, vect8, 23), + XTEST_MAC_CBC_CASE(TEE_ALG_DES3_CBC_MAC_PKCS5, TEE_TYPE_DES3, vect9, + 34), + XTEST_MAC_CBC_CASE(TEE_ALG_DES3_CBC_MAC_PKCS5, TEE_TYPE_DES3, vect10, 4), + + { TEE_ALG_AES_CMAC, TEE_TYPE_AES, mac_cmac_vect1_key, + ARRAY_SIZE(mac_cmac_vect1_key), 0, NULL, 0, mac_cmac_vect1_out, + ARRAY_SIZE(mac_cmac_vect1_out) }, + XTEST_MAC_CMAC_CASE(vect2, 9), + XTEST_MAC_CMAC_CASE(vect3, 9), + XTEST_MAC_CMAC_CASE(vect4, 9), + { TEE_ALG_AES_CMAC, TEE_TYPE_AES, mac_cmac_vect5_key, + ARRAY_SIZE(mac_cmac_vect5_key), 0, NULL, 0, mac_cmac_vect5_out, + ARRAY_SIZE(mac_cmac_vect5_out) }, + XTEST_MAC_CMAC_CASE(vect6, 9), + XTEST_MAC_CMAC_CASE(vect7, 9), + XTEST_MAC_CMAC_CASE(vect8, 9), + { TEE_ALG_AES_CMAC, TEE_TYPE_AES, mac_cmac_vect9_key, + ARRAY_SIZE(mac_cmac_vect9_key), 0, NULL, 0, mac_cmac_vect9_out, + ARRAY_SIZE(mac_cmac_vect9_out) }, + XTEST_MAC_CMAC_CASE(vect10, 9), + XTEST_MAC_CMAC_CASE(vect11, 9), + XTEST_MAC_CMAC_CASE(vect12, 9), + XTEST_MAC_CMAC_CASE(vect12, 16), + + { TEE_ALG_DES3_CMAC, TEE_TYPE_DES3, mac_des3_cmac_vect1_key, + ARRAY_SIZE(mac_des3_cmac_vect1_key), 0, NULL, 0, mac_des3_cmac_vect1_out, + ARRAY_SIZE(mac_des3_cmac_vect1_out) }, + XTEST_MAC_DES3_CMAC_CASE(vect2, 3), + XTEST_MAC_DES3_CMAC_CASE(vect3, 9), + XTEST_MAC_DES3_CMAC_CASE(vect4, 9), + { TEE_ALG_DES3_CMAC, TEE_TYPE_DES3, mac_des3_cmac_vect5_key, + ARRAY_SIZE(mac_des3_cmac_vect5_key), 0, NULL, 0, mac_des3_cmac_vect5_out, + ARRAY_SIZE(mac_des3_cmac_vect5_out) }, + XTEST_MAC_DES3_CMAC_CASE(vect6, 3), + XTEST_MAC_DES3_CMAC_CASE(vect7, 5), + XTEST_MAC_DES3_CMAC_CASE(vect8, 9), + + XTEST_MAC_CASE(TEE_ALG_HMAC_SM3, TEE_TYPE_HMAC_SM3, + mac_data_sm3_d31_key, + 13, mac_data_sm3_d31_in, mac_data_sm3_d31_out), + XTEST_MAC_CASE(TEE_ALG_HMAC_SM3, TEE_TYPE_HMAC_SM3, + mac_data_sm3_d32_key, + 13, mac_data_sm3_d32_in, mac_data_sm3_d32_out), +}; + +static void xtest_tee_test_4002(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEE_OperationHandle op1 = TEE_HANDLE_NULL; + TEE_OperationHandle op2 = TEE_HANDLE_NULL; + TEE_OperationHandle op3 = TEE_HANDLE_NULL; + TEE_ObjectHandle key_handle = TEE_HANDLE_NULL; + uint8_t out[64] = { }; + size_t out_size = 0; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(mac_cases); n++) { + TEE_Attribute key_attr = { }; + size_t key_size = 0; + size_t offs = 0; + + Do_ADBG_BeginSubCase(c, "MAC case %d algo 0x%x", + (int)n, (unsigned int)mac_cases[n].algo); + + key_attr.attributeID = TEE_ATTR_SECRET_VALUE; + key_attr.content.ref.buffer = (void *)mac_cases[n].key; + key_attr.content.ref.length = mac_cases[n].key_len; + + key_size = key_attr.content.ref.length * 8; + if (mac_cases[n].key_type == TEE_TYPE_DES || + mac_cases[n].key_type == TEE_TYPE_DES3) + /* Exclude parity in bit size of key */ + key_size -= key_size / 8; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op1, + mac_cases[n].algo, TEE_MODE_MAC, key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op2, + mac_cases[n].algo, TEE_MODE_MAC, key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op3, + mac_cases[n].algo, TEE_MODE_MAC, key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + mac_cases[n].key_type, key_size, &key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, + key_handle, &key_attr, 1))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op1, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_mac_init(c, &session, op1, NULL, 0))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_copy_operation(c, &session, op3, op1))) + goto out; + + offs = 0; + if (mac_cases[n].in != NULL) { + while (offs + mac_cases[n].in_incr < + mac_cases[n].in_len) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_mac_update(c, &session, + op1, mac_cases[n].in + offs, + mac_cases[n].in_incr))) + goto out; + offs += mac_cases[n].in_incr; + if (!mac_cases[n].multiple_incr) + break; + } + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_copy_operation(c, &session, op2, op1))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_mac_final_compute(c, &session, op2, + mac_cases[n].in + offs, + mac_cases [n].in_len - offs, + out, &out_size))) + goto out; + + (void)ADBG_EXPECT_BUFFER(c, mac_cases[n].out, + mac_cases[n].out_len, out, out_size); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_mac_init(c, &session, op1, NULL, 0))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_mac_final_compute(c, &session, op1, + mac_cases[n].in, mac_cases[n].in_len, out, + &out_size))) + goto out; + + (void)ADBG_EXPECT_BUFFER(c, mac_cases[n].out, + mac_cases[n].out_len, out, out_size); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_mac_final_compare(c, &session, op3, + mac_cases[n].in, mac_cases[n].in_len, + mac_cases[n].out, mac_cases[n].out_len))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op1))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op2))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op3))) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4002, xtest_tee_test_4002, + "Test TEE Internal API MAC operations"); + +static const uint8_t ciph_data_aes_key1[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ +}; + +static const uint8_t ciph_data_aes_key2[] = { + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, +}; + +static const uint8_t ciph_data_des_key1[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 /* 01234567 */ +}; + +static const uint8_t ciph_data_des_key2[] = { + 0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1 +}; + + +static const uint8_t ciph_data_des3_key1[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, /* 12345678 */ +}; + +static const uint8_t ciph_data_des3_key2[] = { + 0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1, + 0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1, + 0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1 +}; + +static const uint8_t ciph_data_des2_key1[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ +}; + +static const uint8_t ciph_data_in1[] = { + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* 23456789 */ + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, /* ABCDEF01 */ + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, /* 3456789A */ + 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, /* BCDEF012 */ + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, /* 456789AB */ + 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, /* CDEF0123 */ +}; + +static const uint8_t ciph_data_in3[] = { + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* 23456789 */ + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, /* ABCDEF01 */ + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, /* 3456789A */ + 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, /* BCDEF012 */ + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, /* 456789AB */ + 0x43, 0x44, 0x45, 0x46, 0x30, /* CDEF0 */ +}; + +static const uint8_t ciph_data_in4[] = { + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, /* 23456789 */ + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, /* ABCDEF01 */ + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, /* 3456789A */ + 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, /* BCDEF012 */ + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, /* 456789AB */ + 0x43, 0x44, 0x45, 0x46, 0x30, 0x31, 0x32, 0x33, /* CDEF0123 */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ +}; + +static const uint8_t ciph_data_in5[] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01 +}; + +static const uint8_t ciph_data_128_iv1[] = { + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, /* 12345678 */ + 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30, /* 9ABCDEF0 */ +}; + +static const uint8_t ciph_data_128_iv2[] = { + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +}; + +static const uint8_t ciph_data_64_iv1[] = { + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, /* 12345678 */ +}; + +static const uint8_t ciph_data_in2[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef +}; + +static const uint8_t ciph_data_aes_ecb_nopad_out1[] = { + 0xA5, 0xBE, 0x14, 0xD5, 0x01, 0x05, 0x24, 0x48, /* ......$H */ + 0x58, 0x1A, 0x6B, 0x82, 0xD4, 0x41, 0xD2, 0xB3, /* X.k..A.. */ + 0xBB, 0xF9, 0xAE, 0x37, 0x94, 0xAC, 0x18, 0x50, /* ...7...P */ + 0x87, 0x09, 0xCC, 0x3F, 0x43, 0xD2, 0xC2, 0xB7, /* ...?C... */ + 0xD7, 0x6F, 0x84, 0x07, 0xB4, 0x78, 0xCE, 0x34, /* .o...x.4 */ + 0x48, 0xC9, 0x16, 0x86, 0x42, 0xB8, 0xFF, 0xCF, /* H...B... */ +}; + +static const uint8_t ciph_data_aes_cbc_nopad_out1[] = { + 0x8D, 0x9F, 0x88, 0xD8, 0xAF, 0x9F, 0xC1, 0x3B, /* .......; */ + 0x02, 0x15, 0x43, 0x6A, 0x8C, 0x1E, 0x34, 0x5C, /* ..Cj..4\ */ + 0x83, 0xF4, 0x85, 0x3E, 0x43, 0x0F, 0xE5, 0x5F, /* ...>C.._ */ + 0x81, 0x4C, 0xC0, 0x28, 0x3F, 0xD9, 0x98, 0x53, /* .L.(?..S */ + 0xB1, 0x44, 0x51, 0x38, 0x21, 0xAB, 0x10, 0xCE, /* .DQ8!... */ + 0xC2, 0xEC, 0x65, 0x54, 0xDD, 0x5C, 0xEA, 0xDC, /* ..eT.\.. */ +}; + +static const uint8_t ciph_data_aes_ctr_out1[] = { + 0xD2, 0xDD, 0x11, 0xA8, 0xF7, 0xB0, 0xAE, 0x55, /* .......U */ + 0xBE, 0x61, 0x7A, 0xE6, 0xA1, 0x6C, 0x79, 0xF4, /* .az..ly. */ + 0x62, 0x51, 0x7B, 0xE9, 0x7C, 0xA0, 0x31, 0x0C, /* bQ{.|.1. */ + 0x24, 0x15, 0x70, 0x7F, 0x47, 0x37, 0x69, 0xE0, /* $.p.G7i. */ + 0x24, 0xC3, 0x29, 0xCD, 0xF2, 0x26, 0x69, 0xFF, /* $.)..&i. */ + 0x72, 0x0E, 0x3C, 0xD1, 0xA1, 0x2F, 0x5D, 0x33, /* r.<../]3 */ +}; + +static const uint8_t ciph_data_aes_ctr_out2[] = { + 0xD2, 0xDD, 0x11, 0xA8, 0xF7, 0xB0, 0xAE, 0x55, /* .......U */ + 0xBE, 0x61, 0x7A, 0xE6, 0xA1, 0x6C, 0x79, 0xF4, /* .az..ly. */ + 0x62, 0x51, 0x7B, 0xE9, 0x7C, 0xA0, 0x31, 0x0C, /* bQ{.|.1. */ + 0x24, 0x15, 0x70, 0x7F, 0x47, 0x37, 0x69, 0xE0, /* $.p.G7i. */ + 0x24, 0xC3, 0x29, 0xCD, 0xF2, 0x26, 0x69, 0xFF, /* $.)..&i. */ + 0x72, 0x0E, 0x3C, 0xD1, 0xA1, /* r.<.. */ +}; + +static const uint8_t ciph_data_aes_ctr_out4[] = { + 0xD2, 0xDD, 0x11, 0xA8, 0xF7, 0xB0, 0xAE, 0x55, /* .......U */ + 0xBE, 0x61, 0x7A, 0xE6, 0xA1, 0x6C, 0x79, 0xF4, /* .az..ly. */ + 0x62, 0x51, 0x7B, 0xE9, 0x7C, 0xA0, 0x31, 0x0C, /* bQ{.|.1. */ + 0x24, 0x15, 0x70, 0x7F, 0x47, 0x37, 0x69, 0xE0, /* $.p.G7i. */ + 0x24, 0xC3, 0x29, 0xCD, 0xF2, 0x26, 0x69, 0xFF, /* $.)..&i. */ + 0x72, 0x0E, 0x3C, 0xD1, 0xA1, 0x2F, 0x5D, 0x33, /* r.<../]3 */ + 0x9F, 0xD7, 0x0C, 0x92, 0xD4, 0xA5, 0x9D, 0x06, /* ........ */ + 0x01, 0x80, 0x38, 0xCD, 0xC2, 0x71, 0x5D, 0x4A, /* ..8..q]J */ +}; + +static const uint8_t ciph_data_aes_ctr_out5[] = { + 0xbb, 0xfe, 0x07, 0x04, 0x1c, 0x8e, 0x09, 0x61, + 0xfb, 0xb1, 0x7c, 0xa5, 0x4d, 0x2b, 0x30, 0xf6, + 0x26, 0x9e, 0xff, 0x61, 0x18, 0x47, 0xc6, 0x06, + 0x81, 0x02, 0x84, 0xcd, 0x9c, 0x4b, 0x6d, 0x21, + 0xe2, 0x64, 0xa6, 0x50, 0x7f, 0x28, 0x81, 0x6f, + 0x29, 0xda, 0xd5, 0x56, 0x3f, 0x46, 0xac, 0xca, + 0x37, 0xe7, 0x77, 0x36, 0xbc, 0x76, 0x39, 0x57, + 0xaa, 0x67, 0x1b, 0x2a, 0xe6, 0x36, 0x57, 0x6d, + 0x2a, 0xb8, 0x77, 0x41, 0xc2, 0x4e, 0x4f, 0x27, + 0x4c, 0x34, 0x7a, 0x01, 0x6a, 0xda, 0x75, 0x75, + 0x3e, 0x68, 0xb2 +}; + +static const uint8_t ciph_data_aes_cbc_vect1_key[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ +}; + +static const uint8_t ciph_data_aes_cbc_vect1_iv[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */ +}; + +static const uint8_t ciph_data_aes_cbc_vect1_ptx[] = { + 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, 0x62, /* Cipher b */ + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x63, 0x68, 0x61, /* lock cha */ + 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x28, 0x43, /* ining (C */ + 0x42, 0x43, 0x29, 0x20, 0x69, 0x73, 0x20, 0x61, /* BC) is a */ + 0x20, 0x63, 0x6F, 0x6D, 0x6D, 0x6F, 0x6E, 0x20, /* common */ + 0x63, 0x68, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, /* chaining */ + 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x20, 0x69, 0x6E, /* mode in */ + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, /* which t */ + 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, /* he previ */ + 0x6F, 0x75, 0x73, 0x20, 0x62, 0x6C, 0x6F, 0x63, /* ous bloc */ + 0x6B, 0x27, 0x73, 0x20, 0x63, 0x69, 0x70, 0x68, /* k's ciph */ + 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x20, 0x69, /* ertext i */ + 0x73, 0x20, 0x78, 0x6F, 0x72, 0x65, 0x64, 0x20, /* s xored */ + 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, /* with the */ + 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, /* current */ + 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x27, 0x73, /* block's */ + 0x20, 0x70, 0x6C, 0x61, 0x69, 0x6E, 0x74, 0x65, /* plainte */ + 0x78, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6F, 0x72, /* xt befor */ + 0x65, 0x20, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, /* e encryp */ + 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x2E, 0x2E, 0x2E, /* tion.... */ +}; + +static const uint8_t ciph_data_aes_cbc_vect1_ctx[] = { + 0xDD, 0x16, 0xC3, 0x47, 0x69, 0xEC, 0xF5, 0x86, /* ...Gi... */ + 0x20, 0xB4, 0xF7, 0xE3, 0xB9, 0x36, 0xE8, 0xAC, /* ....6.. */ + 0xC9, 0xA2, 0x11, 0x71, 0x3B, 0x10, 0x9D, 0x45, /* ...q;..E */ + 0xCA, 0xE2, 0x49, 0xA6, 0x4E, 0x56, 0x07, 0xC5, /* ..I.NV.. */ + 0xCE, 0xA3, 0x14, 0xB5, 0x30, 0x1B, 0x63, 0xBB, /* ....0.c. */ + 0x2D, 0x6F, 0xE9, 0xCA, 0x0B, 0x00, 0x31, 0x3F, /* -o....1? */ + 0xA4, 0x9A, 0x39, 0xE1, 0xC8, 0xD2, 0x24, 0x95, /* ..9...$. */ + 0x14, 0xE9, 0xD2, 0x43, 0xE8, 0xA8, 0x1E, 0x0A, /* ...C.... */ + 0xFE, 0x9D, 0x4F, 0xF5, 0xBB, 0x16, 0xB9, 0x54, /* ..O....T */ + 0x78, 0x07, 0x94, 0x05, 0x8E, 0x47, 0xC3, 0xCB, /* x....G.. */ + 0x7C, 0xEC, 0xF4, 0xF8, 0xF2, 0xA4, 0x59, 0x6E, /* |.....Yn */ + 0xED, 0xAD, 0x7F, 0x62, 0xAF, 0x89, 0xA8, 0x5B, /* ...b...[ */ + 0x75, 0xD4, 0x73, 0xE3, 0xBA, 0x9F, 0x9A, 0xD2, /* u.s..... */ + 0x0F, 0xFD, 0x3C, 0xE6, 0xC6, 0xA4, 0xD6, 0x6C, /* ..<....l */ + 0x6A, 0x09, 0xE2, 0x16, 0xB0, 0x8C, 0x69, 0x3C, /* j.....i< */ + 0xC8, 0x1C, 0xE4, 0x3E, 0x86, 0x4D, 0xB0, 0x2B, /* ...>.M.+ */ + 0x29, 0xA0, 0x5A, 0xA3, 0x67, 0xBA, 0xDC, 0x11, /* ).Z.g... */ + 0x08, 0x5E, 0x69, 0xB4, 0x6F, 0xA5, 0xE2, 0xB8, /* .^i.o... */ + 0xC9, 0x6E, 0x83, 0x7E, 0x35, 0xC8, 0xA7, 0xA0, /* .n.~5... */ + 0x33, 0xA3, 0xB1, 0x4B, 0x5A, 0x92, 0x51, 0x2E, /* 3..KZ.Q. */ +}; + +/* AES-CTS test vectors from http://tools.ietf.org/html/rfc3962 + * and http://tools.ietf.org/html/draft-raeburn-krb-rijndael-krb-02 */ +static const uint8_t ciph_data_aes_cts_vect1_key[] = { + 0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20, + 0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69 +}; + +static const uint8_t ciph_data_aes_cts_vect1_iv[16] = { + 0x00 +}; + +static const uint8_t ciph_data_aes_cts_vect1_ptx[] = { + 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20 +}; + +static const uint8_t ciph_data_aes_cts_vect1_ctx[] = { + 0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4, + 0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f, + 0x97 +}; + +#define ciph_data_aes_cts_vect2_key ciph_data_aes_cts_vect1_key +#define ciph_data_aes_cts_vect2_iv ciph_data_aes_cts_vect1_iv +static const uint8_t ciph_data_aes_cts_vect2_ptx[] = { + 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20 +}; + +static const uint8_t ciph_data_aes_cts_vect2_ctx[] = { + 0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1, + 0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22, + 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, + 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5 +}; + +#define ciph_data_aes_cts_vect3_key ciph_data_aes_cts_vect1_key +#define ciph_data_aes_cts_vect3_iv ciph_data_aes_cts_vect1_iv +static const uint8_t ciph_data_aes_cts_vect3_ptx[] = { + 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43, +}; + +static const uint8_t ciph_data_aes_cts_vect3_ctx[] = { + 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, + 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8, + 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, + 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, +}; + +#define ciph_data_aes_cts_vect4_key ciph_data_aes_cts_vect1_key +#define ciph_data_aes_cts_vect4_iv ciph_data_aes_cts_vect1_iv +static const uint8_t ciph_data_aes_cts_vect4_ptx[] = { + 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43, + 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20, + 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c, +}; + +static const uint8_t ciph_data_aes_cts_vect4_ctx[] = { + 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, + 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, + 0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c, + 0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e, + 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, + 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, +}; + +#define ciph_data_aes_cts_vect5_key ciph_data_aes_cts_vect1_key +#define ciph_data_aes_cts_vect5_iv ciph_data_aes_cts_vect1_iv +static const uint8_t ciph_data_aes_cts_vect5_ptx[] = { + 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43, + 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20, + 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c, 0x20, +}; + +static const uint8_t ciph_data_aes_cts_vect5_ctx[] = { + 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, + 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, + 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0, + 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8, + 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, + 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8, +}; + +#define ciph_data_aes_cts_vect6_key ciph_data_aes_cts_vect1_key +#define ciph_data_aes_cts_vect6_iv ciph_data_aes_cts_vect1_iv +static const uint8_t ciph_data_aes_cts_vect6_ptx[] = { + 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, + 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, + 0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43, + 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20, + 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x6e, 0x74, + 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x70, 0x2e, +}; + +static const uint8_t ciph_data_aes_cts_vect6_ctx[] = { + 0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0, + 0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84, + 0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5, + 0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8, + 0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5, + 0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40, + 0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0, + 0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8, +}; + +/* + * Test case for https://github.com/OP-TEE/optee_os/issues/1203 + * 80 bytes of data, processed in two steps (32 + 48). + */ + +#define ciph_data_aes_cts_issue1203_key ciph_data_aes_cts_vect1_key + +static const uint8_t ciph_data_aes_cts_issue1203_iv[] = { + 0x5b, 0x11, 0x7b, 0xf9, 0x83, 0x6a, 0x01, 0x27, + 0x1d, 0x2a, 0xae, 0x0a, 0xd3, 0x27, 0x35, 0x81, +}; + +static const uint8_t ciph_data_aes_cts_issue1203_ptx[] = { + 0x33, 0x2a, 0xf4, 0x8c, 0x18, 0xa1, 0x30, 0x7c, + 0xa7, 0x52, 0x76, 0xca, 0xa6, 0x68, 0xad, 0xf6, + 0x1e, 0xba, 0xc9, 0x66, 0x66, 0x52, 0x1a, 0xe7, + 0x3e, 0xbc, 0xba, 0x60, 0x95, 0x71, 0x04, 0x5e, + 0xb4, 0xb7, 0x10, 0xd7, 0x93, 0x6d, 0x5f, 0x9a, + 0xb8, 0xbb, 0x6b, 0xb0, 0x6d, 0x47, 0x93, 0x41, + 0x29, 0x21, 0xf2, 0x84, 0xf5, 0xb2, 0xf2, 0x6d, + 0xbe, 0xe5, 0x8a, 0x2b, 0x58, 0x8d, 0x1b, 0x5e, + 0x41, 0x04, 0xba, 0x9e, 0x92, 0xe9, 0x52, 0xb6, + 0x8b, 0x1e, 0x36, 0x72, 0x91, 0xe4, 0x56, 0x66, +}; + +/* + * Ciphertext was generated by an online tool for AES CBC. + * Since the input size is a multiple of the block size, and the ciphertext + * format is CS3, the output is the same as plain AES CBC with the last + * two blocks swapped. + */ +static const uint8_t ciph_data_aes_cts_issue1203_ctx[] = { + 0x6c, 0xfe, 0xef, 0x6a, 0x1c, 0x8f, 0xd3, 0xc3, + 0x66, 0xc4, 0xd9, 0x0e, 0xbe, 0x24, 0x17, 0x3f, + 0xcd, 0x19, 0xc9, 0xd2, 0x10, 0x3f, 0xcf, 0xdc, + 0xe9, 0x05, 0xab, 0xd5, 0x1a, 0x31, 0x41, 0x77, + 0x3b, 0xd7, 0x6a, 0x26, 0xae, 0x0d, 0xc9, 0x47, + 0x77, 0xd4, 0xa7, 0xd5, 0x73, 0x88, 0x9e, 0xde, + 0x72, 0x66, 0xe0, 0xe2, 0x3d, 0x62, 0x91, 0x22, + 0xae, 0x11, 0x01, 0x97, 0x22, 0x6a, 0x45, 0xa9, + 0xba, 0x56, 0xd2, 0xbc, 0x55, 0x2d, 0x99, 0x4d, + 0x3d, 0x22, 0x27, 0x9a, 0xac, 0x66, 0x2f, 0xf5, +}; + +static const uint8_t ciph_data_des_ecb_nopad_out1[] = { + 0x46, 0x2B, 0x91, 0xA8, 0x55, 0xE6, 0x7E, 0x75, /* F+..U.~u */ + 0x5E, 0x53, 0xF4, 0x8F, 0x29, 0x41, 0x4E, 0xEF, /* ^S..)AN. */ + 0x32, 0x1B, 0x58, 0x42, 0x9B, 0xB4, 0x3A, 0x1F, /* 2.XB..:. */ + 0x9A, 0xEA, 0xA4, 0xB4, 0xCD, 0xE9, 0x87, 0x7C, /* .......| */ + 0xC0, 0x05, 0x34, 0xED, 0x86, 0x3C, 0x2A, 0x81, /* ..4..<.. */ + 0x5E, 0x93, 0x0E, 0x86, 0xA9, 0xBB, 0x80, 0xFF, /* ^....... */ +}; + +static const uint8_t ciph_data_des_ecb_nopad_out2[] = { + 0x85, 0xE8, 0x13, 0x54, 0x0F, 0x0A, 0xB4, 0x05 +}; + +static const uint8_t ciph_data_des_cbc_nopad_out1[] = { + 0xAD, 0xD6, 0xD6, 0x3E, 0x88, 0xD0, 0xDD, 0xD4, /* ...>.... */ + 0x9A, 0x93, 0x95, 0xA0, 0x86, 0x22, 0x5B, 0x9E, /* ....."[. */ + 0x84, 0x0C, 0x6F, 0x12, 0x04, 0x11, 0x6F, 0xD4, /* ..o...o. */ + 0x12, 0x29, 0xC6, 0x78, 0x0C, 0xFB, 0x58, 0x5B, /* .).x..X[ */ + 0x66, 0x82, 0x0E, 0x52, 0xDC, 0x25, 0x16, 0x51, /* f..R.%.Q */ + 0x69, 0xDF, 0xFE, 0x4E, 0x11, 0x1D, 0x9D, 0x08, /* i..N.... */ +}; + +static const uint8_t ciph_data_des3_ecb_nopad_out1[] = { + 0xA7, 0x46, 0xEC, 0xA8, 0x6A, 0x7F, 0x4A, 0xF1, /* .F..j.J. */ + 0x44, 0x60, 0x37, 0x3B, 0x7F, 0x76, 0xE5, 0xFF, /* D`7;.v.. */ + 0xC1, 0xE7, 0xA5, 0x04, 0x9C, 0x29, 0x5C, 0xA5, /* .....)\. */ + 0xDD, 0xC8, 0xEE, 0x36, 0x1F, 0x48, 0xE0, 0xA9, /* ...6.H.. */ + 0x82, 0x2D, 0x53, 0x84, 0x49, 0x69, 0x78, 0xFA, /* .-S.Iix. */ + 0x23, 0x69, 0x1D, 0xF7, 0x08, 0x38, 0x44, 0x05, /* #i...8D. */ +}; + +static const uint8_t ciph_data_des3_cbc_nopad_out1[] = { + 0x18, 0x09, 0xEB, 0x98, 0xE4, 0x58, 0x72, 0x11, /* .....Xr. */ + 0x30, 0x58, 0xAB, 0x38, 0xB0, 0xC9, 0x2B, 0xED, /* 0X.8..+. */ + 0xDA, 0xC5, 0xE8, 0xA9, 0xF6, 0x8A, 0xA7, 0x80, /* ........ */ + 0xBE, 0x54, 0x1F, 0x63, 0xF6, 0xEE, 0xA2, 0x4C, /* .T.c...L */ + 0x7C, 0xEB, 0x84, 0x7D, 0xDA, 0xCA, 0x1E, 0xB2, /* |..}.... */ + 0xED, 0x5E, 0x96, 0xB8, 0x01, 0x4B, 0x77, 0x02, /* .^...Kw. */ +}; + +static const uint8_t ciph_data_des2_ecb_nopad_out1[] = { + 0xAB, 0x12, 0xB6, 0xE2, 0x4A, 0x3A, 0x26, 0x14, /* ....J:&. */ + 0xF0, 0x7D, 0x23, 0xD0, 0x55, 0xDF, 0x5C, 0x16, /* .}#.U.\. */ + 0x43, 0x59, 0x1E, 0x44, 0x01, 0x76, 0xD7, 0x50, /* CY.D.v.P */ + 0x44, 0xC0, 0x15, 0xDF, 0x2E, 0x7F, 0x8B, 0xC5, /* D....... */ + 0xFF, 0x8B, 0x87, 0xFE, 0x33, 0xD7, 0xCB, 0x2C, /* ....3.., */ + 0xDA, 0x79, 0x6F, 0xA4, 0x05, 0x2B, 0x30, 0xCE, /* .yo..+0. */ +}; + +static const uint8_t ciph_data_des2_cbc_nopad_out1[] = { + 0x47, 0x2F, 0xB1, 0x83, 0xC4, 0xBB, 0x93, 0x16, /* G/...... */ + 0x73, 0xF9, 0xAD, 0x6F, 0x00, 0xF9, 0xCB, 0x4A, /* s..o...J */ + 0x0F, 0x4F, 0x75, 0x75, 0xFB, 0x39, 0x0B, 0xFC, /* .Ouu.9.. */ + 0x9F, 0x48, 0x52, 0xAD, 0xA2, 0x75, 0x2C, 0xF1, /* .HR..u, . */ + 0x7D, 0xC3, 0x8F, 0x16, 0xCF, 0xC9, 0x76, 0x29, /* }.....v) */ + 0x1A, 0xBF, 0xB3, 0xD9, 0x10, 0x7E, 0xAA, 0x49, /* .....~.I */ +}; + +/* SM4 ECB */ + +static const uint8_t ciph_data_sm4_key1[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +static const uint8_t ciph_data_sm4_in1[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +static const uint8_t ciph_data_sm4_ecb_nopad_out1[] = { + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, +}; + +/* + * SM4 CBC + * https://tools.ietf.org/html/draft-ribose-cfrg-sm4-10#appendix-A.2.2.1 + */ +static const uint8_t ciph_data_sm4_cbc_a221_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +static const uint8_t ciph_data_sm4_cbc_a221_iv[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +}; + +static const uint8_t ciph_data_sm4_cbc_a221_in[] = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, + 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, + 0xee, 0xee, 0xee, 0xee, 0xff, 0xff, 0xff, 0xff, + 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, +}; + +static const uint8_t ciph_data_sm4_cbc_a221_out[] = { + 0x78, 0xeb, 0xb1, 0x1c, 0xc4, 0x0b, 0x0a, 0x48, + 0x31, 0x2a, 0xae, 0xb2, 0x04, 0x02, 0x44, 0xcb, + 0x4c, 0xb7, 0x01, 0x69, 0x51, 0x90, 0x92, 0x26, + 0x97, 0x9b, 0x0d, 0x15, 0xdc, 0x6a, 0x8f, 0x6d, +}; + +/* + * SM4 CBC + * https://tools.ietf.org/html/draft-ribose-cfrg-sm4-10#appendix-A.2.2.2 + */ +static const uint8_t ciph_data_sm4_cbc_a222_key[] = { + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, +}; + +static const uint8_t ciph_data_sm4_cbc_a222_iv[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +}; + +static const uint8_t ciph_data_sm4_cbc_a222_in[] = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, + 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd, + 0xee, 0xee, 0xee, 0xee, 0xff, 0xff, 0xff, 0xff, + 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, +}; + +static const uint8_t ciph_data_sm4_cbc_a222_out[] = { + 0x0d, 0x3a, 0x6d, 0xdc, 0x2d, 0x21, 0xc6, 0x98, + 0x85, 0x72, 0x15, 0x58, 0x7b, 0x7b, 0xb5, 0x9a, + 0x91, 0xf2, 0xc1, 0x47, 0x91, 0x1a, 0x41, 0x44, + 0x66, 0x5e, 0x1f, 0xa1, 0xd4, 0x0b, 0xae, 0x38, +}; + +/* + * SM4 CTR + * https://tools.ietf.org/html/draft-ribose-cfrg-sm4-10#appendix-A.2.5.1 + */ +static const uint8_t ciph_data_sm4_ctr_a251_key[] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +static const uint8_t ciph_data_sm4_ctr_a251_iv[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +}; + +static const uint8_t ciph_data_sm4_ctr_a251_in[] = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, +}; + +static const uint8_t ciph_data_sm4_ctr_a251_out[] = { + 0xac, 0x32, 0x36, 0xcb, 0x97, 0x0c, 0xc2, 0x07, + 0x91, 0x36, 0x4c, 0x39, 0x5a, 0x13, 0x42, 0xd1, + 0xa3, 0xcb, 0xc1, 0x87, 0x8c, 0x6f, 0x30, 0xcd, + 0x07, 0x4c, 0xce, 0x38, 0x5c, 0xdd, 0x70, 0xc7, + 0xf2, 0x34, 0xbc, 0x0e, 0x24, 0xc1, 0x19, 0x80, + 0xfd, 0x12, 0x86, 0x31, 0x0c, 0xe3, 0x7b, 0x92, + 0x6e, 0x02, 0xfc, 0xd0, 0xfa, 0xa0, 0xba, 0xf3, + 0x8b, 0x29, 0x33, 0x85, 0x1d, 0x82, 0x45, 0x14, +}; + +/* + * SM4 CTR + * https://tools.ietf.org/html/draft-ribose-cfrg-sm4-10#appendix-A.2.5.2 + */ +static const uint8_t ciph_data_sm4_ctr_a252_key[] = { + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, +}; + +static const uint8_t ciph_data_sm4_ctr_a252_iv[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +}; + +static const uint8_t ciph_data_sm4_ctr_a252_in[] = { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, +}; + +static const uint8_t ciph_data_sm4_ctr_a252_out[] = { + 0x5d, 0xcc, 0xcd, 0x25, 0xb9, 0x5a, 0xb0, 0x74, + 0x17, 0xa0, 0x85, 0x12, 0xee, 0x16, 0x0e, 0x2f, + 0x8f, 0x66, 0x15, 0x21, 0xcb, 0xba, 0xb4, 0x4c, + 0xc8, 0x71, 0x38, 0x44, 0x5b, 0xc2, 0x9e, 0x5c, + 0x0a, 0xe0, 0x29, 0x72, 0x05, 0xd6, 0x27, 0x04, + 0x17, 0x3b, 0x21, 0x23, 0x9b, 0x88, 0x7f, 0x6c, + 0x8c, 0xb5, 0xb8, 0x00, 0x91, 0x7a, 0x24, 0x88, + 0x28, 0x4b, 0xde, 0x9e, 0x16, 0xea, 0x29, 0x06, +}; + +struct xtest_ciph_case { + uint32_t algo; + uint32_t mode; + uint32_t key_type; + const uint8_t *key1; + size_t key1_len; + const uint8_t *key2; + size_t key2_len; + const uint8_t *iv; + size_t iv_len; + size_t in_incr; + const uint8_t *in; + size_t in_len; + const uint8_t *out; + size_t out_len; + size_t line; +}; + +#define XTEST_CIPH_CASE_NO_IV(algo, key_type, key, in_incr, ptx, ctx) \ + { (algo), TEE_MODE_ENCRYPT, (key_type), (key), ARRAY_SIZE(key), \ + NULL, 0, NULL, 0, \ + (in_incr), (ptx), ARRAY_SIZE(ptx), (ctx), ARRAY_SIZE(ctx), \ + __LINE__ }, \ + { (algo), TEE_MODE_DECRYPT, (key_type), (key), ARRAY_SIZE(key), \ + NULL, 0, NULL, 0, \ + (in_incr), (ctx), ARRAY_SIZE(ctx), (ptx), ARRAY_SIZE(ptx), __LINE__ } + +#define XTEST_CIPH_CASE(algo, key_type, key, iv, in_incr, ptx, ctx) \ + { (algo), TEE_MODE_ENCRYPT, (key_type), (key), ARRAY_SIZE(key), \ + NULL, 0, iv, ARRAY_SIZE(iv), (in_incr), (ptx), ARRAY_SIZE(ptx), \ + (ctx), ARRAY_SIZE(ctx), __LINE__ }, \ + { (algo), TEE_MODE_DECRYPT, (key_type), (key), ARRAY_SIZE(key), \ + NULL, 0, iv, ARRAY_SIZE(iv), (in_incr), (ctx), ARRAY_SIZE(ctx), \ + (ptx), ARRAY_SIZE(ptx), __LINE__ } + +#define XTEST_CIPH_CASE_AES_XTS(vect, in_incr) \ + { TEE_ALG_AES_XTS, TEE_MODE_ENCRYPT, TEE_TYPE_AES, \ + ciph_data_aes_xts_ ## vect ## _key1, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _key1), \ + ciph_data_aes_xts_ ## vect ## _key2, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _key2), \ + ciph_data_aes_xts_ ## vect ## _iv, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _iv), \ + (in_incr), \ + ciph_data_aes_xts_ ## vect ## _ptx, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _ptx), \ + ciph_data_aes_xts_ ## vect ## _ctx, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _ctx), __LINE__ }, \ + { TEE_ALG_AES_XTS, TEE_MODE_DECRYPT, TEE_TYPE_AES, \ + ciph_data_aes_xts_ ## vect ## _key1, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _key1), \ + ciph_data_aes_xts_ ## vect ## _key2, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _key2), \ + ciph_data_aes_xts_ ## vect ## _iv, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _iv), \ + (in_incr), \ + ciph_data_aes_xts_ ## vect ## _ctx, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _ctx), \ + ciph_data_aes_xts_ ## vect ## _ptx, \ + ARRAY_SIZE(ciph_data_aes_xts_ ## vect ## _ptx), __LINE__ } + +#define XTEST_CIPH_CASE_AES_CBC(vect, in_incr) \ + XTEST_CIPH_CASE(TEE_ALG_AES_CBC_NOPAD, TEE_TYPE_AES, \ + ciph_data_aes_cbc_ ## vect ## _key, \ + ciph_data_aes_cbc_ ## vect ## _iv, \ + (in_incr), ciph_data_aes_cbc_ ## vect ## _ptx, \ + ciph_data_aes_cbc_ ## vect ## _ctx) + +#define XTEST_CIPH_CASE_AES_CTS(vect, in_incr) \ + XTEST_CIPH_CASE(TEE_ALG_AES_CTS, TEE_TYPE_AES, \ + ciph_data_aes_cts_ ## vect ## _key, \ + ciph_data_aes_cts_ ## vect ## _iv, \ + (in_incr), ciph_data_aes_cts_ ## vect ## _ptx, \ + ciph_data_aes_cts_ ## vect ## _ctx) + +static const struct xtest_ciph_case ciph_cases[] = { + /* AES */ + XTEST_CIPH_CASE_NO_IV(TEE_ALG_AES_ECB_NOPAD, TEE_TYPE_AES, + ciph_data_aes_key1, 11, ciph_data_in1, + ciph_data_aes_ecb_nopad_out1), + XTEST_CIPH_CASE(TEE_ALG_AES_CBC_NOPAD, TEE_TYPE_AES, + ciph_data_aes_key1, ciph_data_128_iv1, 11, + ciph_data_in1, + ciph_data_aes_cbc_nopad_out1), + XTEST_CIPH_CASE(TEE_ALG_AES_CTR, TEE_TYPE_AES, + ciph_data_aes_key1, ciph_data_128_iv1, 13, + ciph_data_in1, + ciph_data_aes_ctr_out1), + XTEST_CIPH_CASE(TEE_ALG_AES_CTR, TEE_TYPE_AES, + ciph_data_aes_key1, ciph_data_128_iv1, 13, + ciph_data_in3, + ciph_data_aes_ctr_out2), + XTEST_CIPH_CASE(TEE_ALG_AES_CTR, TEE_TYPE_AES, + ciph_data_aes_key1, ciph_data_128_iv1, 16, + ciph_data_in3, + ciph_data_aes_ctr_out2), + XTEST_CIPH_CASE(TEE_ALG_AES_CTR, TEE_TYPE_AES, + ciph_data_aes_key1, ciph_data_128_iv1, 16, + ciph_data_in4, + ciph_data_aes_ctr_out4), + XTEST_CIPH_CASE(TEE_ALG_AES_CTR, TEE_TYPE_AES, + ciph_data_aes_key2, ciph_data_128_iv2, 11, + ciph_data_in5, + ciph_data_aes_ctr_out5), + + XTEST_CIPH_CASE_AES_CBC(vect1, 11), + XTEST_CIPH_CASE_AES_CBC(vect1, 64), + + /* AES-CTS */ + XTEST_CIPH_CASE_AES_CTS(vect1, 13), + XTEST_CIPH_CASE_AES_CTS(vect2, 14), + XTEST_CIPH_CASE_AES_CTS(vect3, 11), + XTEST_CIPH_CASE_AES_CTS(vect4, 9), + XTEST_CIPH_CASE_AES_CTS(vect5, 7), + XTEST_CIPH_CASE_AES_CTS(vect6, 17), + XTEST_CIPH_CASE_AES_CTS(vect6, 0x20), + XTEST_CIPH_CASE_AES_CTS(issue1203, 32), + + /* DES */ + XTEST_CIPH_CASE_NO_IV(TEE_ALG_DES_ECB_NOPAD, TEE_TYPE_DES, + ciph_data_des_key1, 14, ciph_data_in1, + ciph_data_des_ecb_nopad_out1), + XTEST_CIPH_CASE_NO_IV(TEE_ALG_DES_ECB_NOPAD, TEE_TYPE_DES, + ciph_data_des_key2, 3, ciph_data_in2, + ciph_data_des_ecb_nopad_out2), + XTEST_CIPH_CASE(TEE_ALG_DES_CBC_NOPAD, TEE_TYPE_DES, + ciph_data_des_key1, ciph_data_64_iv1, 15, ciph_data_in1, + ciph_data_des_cbc_nopad_out1), + + /* DES3 */ + XTEST_CIPH_CASE_NO_IV(TEE_ALG_DES3_ECB_NOPAD, TEE_TYPE_DES3, + ciph_data_des3_key1, 11, ciph_data_in1, + ciph_data_des3_ecb_nopad_out1), + XTEST_CIPH_CASE_NO_IV(TEE_ALG_DES3_ECB_NOPAD, TEE_TYPE_DES3, + ciph_data_des3_key2, 3, ciph_data_in2, + ciph_data_des_ecb_nopad_out2), + XTEST_CIPH_CASE(TEE_ALG_DES3_CBC_NOPAD, TEE_TYPE_DES3, + ciph_data_des3_key1, ciph_data_64_iv1, 11, + ciph_data_in1, + ciph_data_des3_cbc_nopad_out1), + + /* DES2 */ + XTEST_CIPH_CASE_NO_IV(TEE_ALG_DES3_ECB_NOPAD, TEE_TYPE_DES3, + ciph_data_des2_key1, 11, ciph_data_in1, + ciph_data_des2_ecb_nopad_out1), + XTEST_CIPH_CASE(TEE_ALG_DES3_CBC_NOPAD, TEE_TYPE_DES3, + ciph_data_des2_key1, ciph_data_64_iv1, 11, + ciph_data_in1, + ciph_data_des2_cbc_nopad_out1), + + /* AES-XTS */ + XTEST_CIPH_CASE_AES_XTS(vect1, 3), + XTEST_CIPH_CASE_AES_XTS(vect2, 6), + XTEST_CIPH_CASE_AES_XTS(vect3, 7), + XTEST_CIPH_CASE_AES_XTS(vect4, 8), + XTEST_CIPH_CASE_AES_XTS(vect5, 9), + XTEST_CIPH_CASE_AES_XTS(vect6, 13), + XTEST_CIPH_CASE_AES_XTS(vect7, 1), + XTEST_CIPH_CASE_AES_XTS(vect8, 3), + XTEST_CIPH_CASE_AES_XTS(vect9, 2), + XTEST_CIPH_CASE_AES_XTS(vect10, 5), + XTEST_CIPH_CASE_AES_XTS(vect11, 6), + XTEST_CIPH_CASE_AES_XTS(vect12, 7), + XTEST_CIPH_CASE_AES_XTS(vect13, 3), + XTEST_CIPH_CASE_AES_XTS(vect14, 2), + XTEST_CIPH_CASE_AES_XTS(vect15, 0), + XTEST_CIPH_CASE_AES_XTS(vect16, 9), + XTEST_CIPH_CASE_AES_XTS(vect17, 6), + XTEST_CIPH_CASE_AES_XTS(vect18, 8), + XTEST_CIPH_CASE_AES_XTS(vect19, 23), + + /* SM4 */ + XTEST_CIPH_CASE_NO_IV(TEE_ALG_SM4_ECB_NOPAD, TEE_TYPE_SM4, + ciph_data_sm4_key1, 11, ciph_data_sm4_in1, + ciph_data_sm4_ecb_nopad_out1), + XTEST_CIPH_CASE(TEE_ALG_SM4_CBC_NOPAD, TEE_TYPE_SM4, + ciph_data_sm4_cbc_a221_key, ciph_data_sm4_cbc_a221_iv, + 11, ciph_data_sm4_cbc_a221_in, + ciph_data_sm4_cbc_a221_out), + XTEST_CIPH_CASE(TEE_ALG_SM4_CBC_NOPAD, TEE_TYPE_SM4, + ciph_data_sm4_cbc_a222_key, ciph_data_sm4_cbc_a222_iv, + 11, ciph_data_sm4_cbc_a222_in, + ciph_data_sm4_cbc_a222_out), + XTEST_CIPH_CASE(TEE_ALG_SM4_CTR, TEE_TYPE_SM4, + ciph_data_sm4_ctr_a251_key, ciph_data_sm4_ctr_a251_iv, + 11, ciph_data_sm4_ctr_a251_in, + ciph_data_sm4_ctr_a251_out), + XTEST_CIPH_CASE(TEE_ALG_SM4_CTR, TEE_TYPE_SM4, + ciph_data_sm4_ctr_a252_key, ciph_data_sm4_ctr_a252_iv, + 11, ciph_data_sm4_ctr_a252_in, + ciph_data_sm4_ctr_a252_out), +}; + +static void xtest_tee_test_4003(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_OperationHandle op2 = TEE_HANDLE_NULL; + TEE_ObjectHandle key1_handle = TEE_HANDLE_NULL; + TEE_ObjectHandle key2_handle = TEE_HANDLE_NULL; + uint8_t out[2048] = { }; + size_t out_size = 0; + size_t out_offs = 0; + size_t out_offs2 = 0; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(ciph_cases); n++) { + TEE_Attribute key_attr = { }; + size_t key_size = 0; + size_t op_key_size = 0; + + switch (ciph_cases[n].algo) { + case TEE_ALG_SM4_CTR: + case TEE_ALG_SM4_CBC_NOPAD: + case TEE_ALG_SM4_ECB_NOPAD: + if (!ta_crypt_cmd_is_algo_supported(c, &session, + ciph_cases[n].algo, TEE_CRYPTO_ELEMENT_NONE)) { + Do_ADBG_Log("SM4 not supported: skip subcase"); + continue; + } + break; + default: + break; + } + + Do_ADBG_BeginSubCase(c, "Cipher case %d algo 0x%x line %d", + (int)n, (unsigned int)ciph_cases[n].algo, + (int)ciph_cases[n].line); + + key_attr.attributeID = TEE_ATTR_SECRET_VALUE; + key_attr.content.ref.buffer = (void *)ciph_cases[n].key1; + key_attr.content.ref.length = ciph_cases[n].key1_len; + + key_size = key_attr.content.ref.length * 8; + if (ciph_cases[n].key_type == TEE_TYPE_DES || + ciph_cases[n].key_type == TEE_TYPE_DES3) + /* Exclude parity in bit size of key */ + key_size -= key_size / 8; + + op_key_size = key_size; + if (ciph_cases[n].key2 != NULL) + op_key_size *= 2; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + ciph_cases[n].algo, ciph_cases[n].mode, + op_key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op2, + ciph_cases[n].algo, ciph_cases[n].mode, + op_key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + ciph_cases[n].key_type, key_size, + &key1_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, + key1_handle, &key_attr, 1))) + goto out; + + if (ciph_cases[n].key2 != NULL) { + key_attr.content.ref.buffer = + (void *)ciph_cases[n].key2; + key_attr.content.ref.length = ciph_cases[n].key2_len; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, + &session, ciph_cases[n].key_type, + key_attr.content.ref.length * 8, + &key2_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, + &session, key2_handle, &key_attr, 1))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key2(c, &session, op, + key1_handle, key2_handle))) + goto out; + } else { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + key1_handle))) + goto out; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + key1_handle))) + goto out; + key1_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + key2_handle))) + goto out; + key2_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_cipher_init(c, &session, op, + ciph_cases[n].iv, ciph_cases[n].iv_len))) + goto out; + + out_offs = 0; + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_cipher_update(c, &session, op, + ciph_cases[n].in, ciph_cases[n].in_incr, out, + &out_size))) + goto out; + + if (ciph_cases[n].algo == TEE_ALG_AES_CTR) + ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, ==, + ciph_cases[n].in_incr); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_copy_operation(c, &session, op2, op))) + goto out; + + out_offs += out_size; + out_size = sizeof(out) - out_offs; + out_offs2 = out_offs; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_cipher_do_final(c, &session, op, + ciph_cases[n].in + ciph_cases[n].in_incr, + ciph_cases[n].in_len - ciph_cases[n].in_incr, + out + out_offs, + &out_size))) + goto out; + + out_offs += out_size; + + (void)ADBG_EXPECT_BUFFER(c, ciph_cases[n].out, + ciph_cases[n].out_len, out, out_offs); + + /* test on the copied op2 */ + out_size = sizeof(out) - out_offs2; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_cipher_do_final(c, &session, op2, + ciph_cases[n].in + ciph_cases[n].in_incr, + ciph_cases[n].in_len - ciph_cases[n].in_incr, + out + out_offs2, + &out_size))) + goto out; + + out_offs2 += out_size; + + ADBG_EXPECT_BUFFER(c, ciph_cases[n].out, ciph_cases[n].out_len, + out, out_offs2); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op2))) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4003, xtest_tee_test_4003, + "Test TEE Internal API cipher operations"); + +static void xtest_tee_test_4004(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + uint8_t buf1[45] = { }; + uint8_t buf2[45] = { }; + static const uint8_t zeros[45]; + + Do_ADBG_BeginSubCase(c, "TEE get random"); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_random_number_generate(c, &session, buf1, + sizeof(buf1)))) + goto out; + + (void)ADBG_EXPECT_COMPARE_SIGNED(c, + 0, !=, memcmp(buf1, zeros, sizeof(buf1))); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_random_number_generate(c, &session, buf2, + sizeof(buf2)))) + goto out; + + (void)ADBG_EXPECT_COMPARE_SIGNED(c, + 0, !=, memcmp(buf2, zeros, sizeof(buf2))); + + (void)ADBG_EXPECT_COMPARE_SIGNED(c, + 0, !=, memcmp(buf2, buf1, sizeof(buf1))); +out: + TEEC_CloseSession(&session); + Do_ADBG_EndSubCase(c, "TEE get random"); +} +ADBG_CASE_DEFINE(regression, 4004, xtest_tee_test_4004, + "Test TEE Internal API get random"); + +struct xtest_ae_case { + uint32_t algo; + uint32_t mode; + uint32_t key_type; + const uint8_t *key; + size_t key_len; + const uint8_t *nonce; + size_t nonce_len; + size_t aad_incr; + const uint8_t *aad; + size_t aad_len; + size_t in_incr; + const uint8_t *ptx; + size_t ptx_len; + const uint8_t *ctx; + size_t ctx_len; + const uint8_t *tag; + size_t tag_len; + size_t line; +}; + + +#define ARRAY(a) a, ARRAY_SIZE(a) +#define NULL_ARRAY(a) NULL, 0 + +#define XTEST_AE_CASE(algo, vect, aad_incr, in_incr, \ + aad_array, ptx_array, ctx_array) \ + { (algo), TEE_MODE_ENCRYPT, TEE_TYPE_AES, ARRAY(vect ## _key), \ + ARRAY(vect ## _nonce), (aad_incr), \ + aad_array(vect ## _aad), (in_incr), \ + ptx_array(vect ## _ptx), ctx_array(vect ## _ctx), \ + ARRAY(vect ## _tag), \ + __LINE__ }, \ + { (algo), TEE_MODE_DECRYPT, TEE_TYPE_AES, ARRAY(vect ## _key), \ + ARRAY(vect ## _nonce), (aad_incr), \ + aad_array(vect ## _aad), (in_incr), \ + ptx_array(vect ## _ptx), ctx_array(vect ## _ctx), \ + ARRAY(vect ## _tag), \ + __LINE__ } + +#define XTEST_AE_CASE_AES_CCM(vect, aad_incr, in_incr) \ + XTEST_AE_CASE(TEE_ALG_AES_CCM, ae_data_aes_ccm_ ## vect, aad_incr, \ + in_incr, ARRAY, ARRAY, ARRAY) + +#define XTEST_AE_CASE_AES_GCM(vect, aad_incr, in_incr, \ + aad_array, ptx_array, ctx_array) \ + XTEST_AE_CASE(TEE_ALG_AES_GCM, ae_data_aes_gcm_ ## vect, aad_incr, \ + in_incr, aad_array, ptx_array, ctx_array) + + + +static const struct xtest_ae_case ae_cases[] = { + XTEST_AE_CASE_AES_CCM(vect1, 3, 2), + XTEST_AE_CASE_AES_CCM(vect2, 7, 13), + XTEST_AE_CASE_AES_CCM(vect3, 5, 21), + + XTEST_AE_CASE_AES_GCM(vect1, 0, 0, NULL_ARRAY, NULL_ARRAY, NULL_ARRAY), + XTEST_AE_CASE_AES_GCM(vect2, 0, 9, NULL_ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect3, 0, 9, NULL_ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect3, 0, 0x1F, NULL_ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect4, 5, 0x20, ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect5, 5, 9, ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect6, 5, 9, ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect7, 0, 0, NULL_ARRAY, NULL_ARRAY, NULL_ARRAY), + XTEST_AE_CASE_AES_GCM(vect8, 0, 9, NULL_ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect9, 0, 9, NULL_ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect10, 5, 9, ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect11, 5, 9, ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect12, 5, 9, ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect13, 0, 0, NULL_ARRAY, NULL_ARRAY, NULL_ARRAY), + XTEST_AE_CASE_AES_GCM(vect14, 0, 9, NULL_ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect15, 0, 9, NULL_ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect16, 5, 9, ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect17, 5, 9, ARRAY, ARRAY, ARRAY), + XTEST_AE_CASE_AES_GCM(vect18, 5, 9, ARRAY, ARRAY, ARRAY), +#ifdef CFG_GCM_NIST_VECTORS +#include "gcmDecrypt128.h" +#include "gcmDecrypt192.h" +#include "gcmDecrypt256.h" +#include "gcmEncryptExtIV128.h" +#include "gcmEncryptExtIV192.h" +#include "gcmEncryptExtIV256.h" +#endif +}; + +static void xtest_tee_test_4005(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_OperationHandle op2 = TEE_HANDLE_NULL; + TEE_ObjectHandle key_handle = TEE_HANDLE_NULL; + TEE_Attribute key_attr = { }; + uint8_t out[512] = { }; + size_t out_size = 0; + size_t out_offs = 0; + size_t out_offs2 = 0; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(ae_cases); n++) { + Do_ADBG_BeginSubCase(c, "AE case %d algo 0x%x line %d", + (int)n, (unsigned int)ae_cases[n].algo, + (int)ae_cases[n].line); + + key_attr.attributeID = TEE_ATTR_SECRET_VALUE; + key_attr.content.ref.buffer = (void *)ae_cases[n].key; + key_attr.content.ref.length = ae_cases[n].key_len; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + ae_cases[n].algo, ae_cases[n].mode, + key_attr.content.ref.length * 8))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op2, + ae_cases[n].algo, ae_cases[n].mode, + key_attr.content.ref.length * 8))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + ae_cases[n].key_type, + key_attr.content.ref.length * 8, + &key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, + key_handle, &key_attr, 1))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + key_handle))) + goto out; + key_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_init(c, &session, op, ae_cases[n].nonce, + ae_cases[n].nonce_len, ae_cases[n].tag_len, + ae_cases[n].aad_len, ae_cases[n].ptx_len))) + goto out; + + if (ae_cases[n].aad != NULL) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_update_aad(c, &session, op, + ae_cases[n].aad, ae_cases[n].aad_incr))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_update_aad(c, &session, op, + ae_cases[n].aad + ae_cases[n].aad_incr, + ae_cases [n].aad_len - + ae_cases[n].aad_incr))) + goto out; + } + + out_offs = 0; + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (ae_cases[n].mode == TEE_MODE_ENCRYPT) { + if (ae_cases[n].ptx != NULL) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_update(c, &session, op, + ae_cases[n].ptx, + ae_cases[n].in_incr, out, + &out_size))) + goto out; + out_offs += out_size; + if (ae_cases[n].algo == TEE_ALG_AES_GCM) + ADBG_EXPECT_COMPARE_UNSIGNED(c, + out_size, ==, ae_cases[n].in_incr); + } + } else { + if (ae_cases[n].ctx != NULL) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_update(c, &session, op, + ae_cases[n].ctx, + ae_cases[n].in_incr, out, + &out_size))) + goto out; + out_offs += out_size; + if (ae_cases[n].algo == TEE_ALG_AES_GCM) + ADBG_EXPECT_COMPARE_UNSIGNED(c, + out_size, ==, ae_cases[n].in_incr); + } + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_copy_operation(c, &session, op2, op))) + goto out; + + out_size = sizeof(out) - out_offs; + out_offs2 = out_offs; + if (ae_cases[n].mode == TEE_MODE_ENCRYPT) { + uint8_t out_tag[64]; + size_t out_tag_len = MIN(sizeof(out_tag), + ae_cases[n].tag_len); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_encrypt_final(c, &session, op, + ae_cases[n].ptx + ae_cases[n].in_incr, + ae_cases[n].ptx_len - + ae_cases[n].in_incr, + out + out_offs, + &out_size, out_tag, &out_tag_len))) + goto out; + + (void)ADBG_EXPECT_BUFFER(c, + ae_cases[n].tag, ae_cases[n].tag_len, out_tag, + out_tag_len); + + out_offs += out_size; + + (void)ADBG_EXPECT_BUFFER(c, ae_cases[n].ctx, + ae_cases[n].ctx_len, out, out_offs); + } else { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_decrypt_final(c, &session, op, + ae_cases[n].ctx + ae_cases[n].in_incr, + ae_cases[n].ctx_len - + ae_cases[n].in_incr, + out + out_offs, + &out_size, ae_cases[n].tag, + ae_cases[n].tag_len))) + goto out; + + out_offs += out_size; + + (void)ADBG_EXPECT_BUFFER(c, ae_cases[n].ptx, + ae_cases[n].ptx_len, out, out_offs); + } + + /* test on the copied op2 */ + out_size = sizeof(out) - out_offs2; + memset(out + out_offs2, 0, out_size); + if (ae_cases[n].mode == TEE_MODE_ENCRYPT) { + uint8_t out_tag[64] = { 0 }; + size_t out_tag_len = MIN(sizeof(out_tag), + ae_cases[n].tag_len); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_encrypt_final(c, &session, op2, + ae_cases[n].ptx + ae_cases[n].in_incr, + ae_cases[n].ptx_len - + ae_cases[n].in_incr, + out + out_offs2, + &out_size, out_tag, &out_tag_len))) + goto out; + + ADBG_EXPECT_BUFFER(c, ae_cases[n].tag, + ae_cases[n].tag_len, out_tag, + out_tag_len); + + out_offs2 += out_size; + + (void)ADBG_EXPECT_BUFFER(c, ae_cases[n].ctx, + ae_cases[n].ctx_len, out, out_offs2); + } else { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_ae_decrypt_final(c, &session, op2, + ae_cases[n].ctx + ae_cases[n].in_incr, + ae_cases[n].ctx_len - + ae_cases[n].in_incr, + out + out_offs2, + &out_size, ae_cases[n].tag, + ae_cases[n].tag_len))) + goto out; + + out_offs2 += out_size; + + (void)ADBG_EXPECT_BUFFER(c, ae_cases[n].ptx, + ae_cases[n].ptx_len, out, out_offs2); + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op2))) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4005, xtest_tee_test_4005, + "Test TEE Internal API Authenticated Encryption operations"); + +struct xtest_ac_case { + unsigned int level; + uint32_t algo; + TEE_OperationMode mode; + + union { + struct { + const uint8_t *modulus; + size_t modulus_len; + + const uint8_t *pub_exp; + size_t pub_exp_len; + + const uint8_t *priv_exp; + size_t priv_exp_len; + + const uint8_t *prime1; /* q */ + size_t prime1_len; + const uint8_t *prime2; /* p */ + size_t prime2_len; + const uint8_t *exp1; /* dp */ + size_t exp1_len; + const uint8_t *exp2; /* dq */ + size_t exp2_len; + const uint8_t *coeff; /* iq */ + size_t coeff_len; + + int salt_len; + } rsa; + struct { + const uint8_t *prime; + size_t prime_len; + const uint8_t *sub_prime; + size_t sub_prime_len; + const uint8_t *base; + size_t base_len; + const uint8_t *pub_val; + size_t pub_val_len; + const uint8_t *priv_val; + size_t priv_val_len; + } dsa; + struct { + const uint8_t *private; + size_t private_len; + const uint8_t *public_x; + size_t public_x_len; + const uint8_t *public_y; + size_t public_y_len; + } ecc; + struct { + const uint8_t *private; + size_t private_len; + const uint8_t *public; + size_t public_len; + const uint8_t flag; + const uint8_t *context; + size_t context_len; + } eddsa; + } params; + + const uint8_t *ptx; + size_t ptx_len; + const uint8_t *ctx; + size_t ctx_len; + size_t line; +}; + +#define WITHOUT_SALT(x) -1 +#define WITH_SALT(x) x + +#define XTEST_AC_CASE(level, algo, mode, vect, union_params) \ + { level, (algo), (mode), .params = union_params, \ + ARRAY(vect ## _ptx), \ + ARRAY(vect ## _out), \ + __LINE__ } + +#define XTEST_AC_RSA_UNION(vect, opt_crt_array, opt_salt) \ + { .rsa = { \ + ARRAY(vect ## _modulus), \ + ARRAY(vect ## _pub_exp), \ + ARRAY(vect ## _priv_exp), \ + opt_crt_array(vect ## _prime1), \ + opt_crt_array(vect ## _prime2), \ + opt_crt_array(vect ## _exp1), \ + opt_crt_array(vect ## _exp2), \ + opt_crt_array(vect ## _coeff), \ + opt_salt(vect ## _salt_len) \ + } } + +#define XTEST_AC_RSA_CASE(level, algo, mode, vect, opt_crt_array, opt_salt) \ + XTEST_AC_CASE(level, algo, mode, vect, \ + XTEST_AC_RSA_UNION(vect, opt_crt_array, opt_salt)) + +#define XTEST_AC_DSA_UNION(vect) \ + { .dsa = { \ + ARRAY(vect ## _prime), \ + ARRAY(vect ## _sub_prime), \ + ARRAY(vect ## _base), \ + ARRAY(vect ## _pub_val), \ + ARRAY(vect ## _priv_val), \ + } } + +#define XTEST_AC_DSA_CASE(level, algo, mode, vect) \ + XTEST_AC_CASE(level, algo, mode, vect, XTEST_AC_DSA_UNION(vect)) + +#define XTEST_AC_ECDSA_UNION(vect) \ + { .ecc = { \ + ARRAY(vect ## _private), \ + ARRAY(vect ## _public_x), \ + ARRAY(vect ## _public_y), \ + } } + +#define XTEST_AC_ECC_CASE(level, algo, mode, vect) \ + XTEST_AC_CASE(level, algo, mode, vect, XTEST_AC_ECDSA_UNION(vect)) + +#define XTEST_AC_EDDSA_UNION(vect, flag) \ + { .eddsa = { \ + ARRAY(vect ## _private), \ + ARRAY(vect ## _public), \ + flag, \ + } } + +#define XTEST_AC_EDDSA_CTX_UNION(vect, flag) \ + { .eddsa = { \ + ARRAY(vect ## _private), \ + ARRAY(vect ## _public), \ + flag, \ + ARRAY(vect ## _context), \ + } } + +#define XTEST_AC_EDDSA_CASE(level, algo, mode, vect, flag) \ + XTEST_AC_CASE(level, algo, mode, vect, XTEST_AC_EDDSA_UNION(vect, flag)) + +#define XTEST_AC_EDDSA_CTX_CASE(level, algo, mode, vect, flag) \ + XTEST_AC_CASE(level, algo, mode, vect, XTEST_AC_EDDSA_CTX_UNION(vect, flag)) + +static const struct xtest_ac_case xtest_ac_cases[] = { + /* RSA test without crt parameters */ + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_ENCRYPT, + ac_rsassa_vect1, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_DECRYPT, + ac_rsassa_vect1, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_ENCRYPT, + ac_rsassa_vect2, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_DECRYPT, + ac_rsassa_vect2, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_ENCRYPT, + ac_rsassa_vect18, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_DECRYPT, + ac_rsassa_vect18, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_ENCRYPT, + ac_rsassa_vect19, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_DECRYPT, + ac_rsassa_vect19, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect3, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect3, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect4, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect4, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect5, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect5, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect6, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect6, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect7, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect7, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect8, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect8, NULL_ARRAY, WITHOUT_SALT), + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224, TEE_MODE_SIGN, + ac_rsassa_vect16, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224, TEE_MODE_VERIFY, + ac_rsassa_vect16, NULL_ARRAY, WITHOUT_SALT), + +#ifdef CFG_CRYPTO_RSASSA_NA1 + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5, TEE_MODE_SIGN, + ac_rsassa_vect20, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5, TEE_MODE_VERIFY, + ac_rsassa_vect20, NULL_ARRAY, WITHOUT_SALT), +#endif + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, TEE_MODE_SIGN, + ac_rsassa_vect9, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, TEE_MODE_VERIFY, + ac_rsassa_vect9, NULL_ARRAY, WITHOUT_SALT), + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384, TEE_MODE_SIGN, + ac_rsassa_vect10, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384, TEE_MODE_VERIFY, + ac_rsassa_vect10, NULL_ARRAY, WITHOUT_SALT), + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512, TEE_MODE_SIGN, + ac_rsassa_vect11, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512, TEE_MODE_VERIFY, + ac_rsassa_vect11, NULL_ARRAY, WITHOUT_SALT), + + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, + TEE_MODE_VERIFY, + ac_rsassa_vect12, NULL_ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect12, NULL_ARRAY, WITH_SALT), + + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, + TEE_MODE_VERIFY, + ac_rsassa_vect17, NULL_ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, + TEE_MODE_SIGN, + ac_rsassa_vect17, NULL_ARRAY, WITH_SALT), + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, + TEE_MODE_VERIFY, + ac_rsassa_vect13, NULL_ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, + TEE_MODE_SIGN, + ac_rsassa_vect13, NULL_ARRAY, WITH_SALT), + + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, + TEE_MODE_VERIFY, + ac_rsassa_vect14, NULL_ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, + TEE_MODE_SIGN, + ac_rsassa_vect14, NULL_ARRAY, WITH_SALT), + + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, + TEE_MODE_VERIFY, + ac_rsassa_vect15, NULL_ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, + TEE_MODE_SIGN, + ac_rsassa_vect15, NULL_ARRAY, WITH_SALT), + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_DECRYPT, + ac_rsaes_pkcs1_v1_5_vect1, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_ENCRYPT, + ac_rsaes_pkcs1_v1_5_vect1, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_DECRYPT, + ac_rsaes_pkcs1_v1_5_vect2, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_ENCRYPT, + ac_rsaes_pkcs1_v1_5_vect2, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_DECRYPT, + ac_rsaes_pkcs1_v1_5_vect15, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_ENCRYPT, + ac_rsaes_pkcs1_v1_5_vect15, NULL_ARRAY, WITHOUT_SALT), + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_DECRYPT, + ac_rsaes_oaep_vect1, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_ENCRYPT, + ac_rsaes_oaep_vect1, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_DECRYPT, + ac_rsaes_oaep_vect2, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_ENCRYPT, + ac_rsaes_oaep_vect2, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_DECRYPT, + ac_rsaes_oaep_vect10, NULL_ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_ENCRYPT, + ac_rsaes_oaep_vect10, NULL_ARRAY, WITHOUT_SALT), + + /* RSA test with crt parameters */ + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_ENCRYPT, + ac_rsassa_vect1, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSA_NOPAD, TEE_MODE_DECRYPT, + ac_rsassa_vect1, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSA_NOPAD, TEE_MODE_ENCRYPT, + ac_rsassa_vect2, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSA_NOPAD, TEE_MODE_DECRYPT, + ac_rsassa_vect2, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect3, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect3, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect4, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect4, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect5, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect5, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect6, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect6, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect7, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect7, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect8, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + ac_rsassa_vect8, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, TEE_MODE_SIGN, + ac_rsassa_vect9, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, TEE_MODE_VERIFY, + ac_rsassa_vect9, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384, TEE_MODE_SIGN, + ac_rsassa_vect10, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384, TEE_MODE_VERIFY, + ac_rsassa_vect10, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512, TEE_MODE_SIGN, + ac_rsassa_vect11, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512, TEE_MODE_VERIFY, + ac_rsassa_vect11, ARRAY, WITHOUT_SALT), + + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, + TEE_MODE_VERIFY, + ac_rsassa_vect12, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1,TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, TEE_MODE_SIGN, + ac_rsassa_vect12, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, + TEE_MODE_VERIFY, + ac_rsassa_vect17, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, + TEE_MODE_SIGN, + ac_rsassa_vect17, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, + TEE_MODE_VERIFY, + ac_rsassa_vect13, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, + TEE_MODE_SIGN, + ac_rsassa_vect13, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, + TEE_MODE_VERIFY, + ac_rsassa_vect14, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, + TEE_MODE_SIGN, + ac_rsassa_vect14, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, + TEE_MODE_VERIFY, + ac_rsassa_vect15, ARRAY, WITH_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, + TEE_MODE_SIGN, + ac_rsassa_vect15, ARRAY, WITH_SALT), + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_DECRYPT, + ac_rsaes_pkcs1_v1_5_vect1, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_ENCRYPT, + ac_rsaes_pkcs1_v1_5_vect1, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_DECRYPT, + ac_rsaes_pkcs1_v1_5_vect2, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_ENCRYPT, + ac_rsaes_pkcs1_v1_5_vect2, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_DECRYPT, + ac_rsaes_pkcs1_v1_5_vect15, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_V1_5, TEE_MODE_ENCRYPT, + ac_rsaes_pkcs1_v1_5_vect15, ARRAY, WITHOUT_SALT), + + XTEST_AC_RSA_CASE(0, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_DECRYPT, + ac_rsaes_oaep_vect1, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(0, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_ENCRYPT, + ac_rsaes_oaep_vect1, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_DECRYPT, + ac_rsaes_oaep_vect2, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_ENCRYPT, + ac_rsaes_oaep_vect2, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_DECRYPT, + ac_rsaes_oaep_vect10, ARRAY, WITHOUT_SALT), + XTEST_AC_RSA_CASE(1, TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, + TEE_MODE_ENCRYPT, + ac_rsaes_oaep_vect10, ARRAY, WITHOUT_SALT), + + /* DSA tests */ + /* [mod = L=1024, N=160, SHA-1] */ + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect1), + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect1), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect2), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect2), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect3), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect3), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect4), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect4), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect5), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect5), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect6), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect6), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect7), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect7), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect8), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect8), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect9), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect9), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect10), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect10), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect11), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect11), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect12), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect12), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect13), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect13), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect14), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect14), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_VERIFY, ac_dsa_vect15), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA1, TEE_MODE_SIGN, ac_dsa_vect15), + /* [mod = L=1024, N=160, SHA-224] - GP NOT SUPPORTED */ + /* [mod = L=1024, N=160, SHA-256] - GP NOT SUPPORTED */ + /* [mod = L=1024, N=160, SHA-384] - GP NOT SUPPORTED */ + /* [mod = L=1024, N=160, SHA-512] - GP NOT SUPPORTED */ + /* [mod = L=2048, N=224, SHA-1] - GP NOT SUPPORTED */ + /* [mod = L=2048, N=224, SHA-224] */ + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect91), + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect91), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect92), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect92), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect93), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect93), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect94), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect94), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect95), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect95), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect96), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect96), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect97), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect97), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect98), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect98), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect99), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect99), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect100), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect100), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect101), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect101), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect102), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect102), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect103), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect103), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect104), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect104), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect105), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect105), + /* [mod = L=2048, N=224, SHA-256] */ + XTEST_AC_DSA_CASE(0, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect106), + XTEST_AC_DSA_CASE(0, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect106), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect107), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect107), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect108), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect108), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect109), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect109), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect110), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect110), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect111), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect111), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect112), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect112), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect113), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect113), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect114), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect114), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect115), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect115), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect116), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect116), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect117), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect117), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect118), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect118), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect119), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect119), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect120), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect120), + /* [mod = L=2048, N=224, SHA-384] - GP NOT SUPPORTED */ + /* [mod = L=2048, N=224, SHA-512] - GP NOT SUPPORTED */ + /* [mod = L=2048, N=256, SHA-1] - GP NOT SUPPORTED */ + /* [mod = L=2048, N=256, SHA-224] */ + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect166), + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect166), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect167), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect167), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect168), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect168), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect169), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect169), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect170), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect170), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect171), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect171), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect172), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect172), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect173), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect173), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect174), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect174), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect175), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect175), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect176), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect176), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect177), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect177), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect178), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect178), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect179), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect179), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_VERIFY, ac_dsa_vect180), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA224, TEE_MODE_SIGN, ac_dsa_vect180), + /* [mod = L=2048, N=256, SHA-256] */ + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect181), + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect181), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect182), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect182), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect183), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect183), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect184), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect184), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect185), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect185), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect186), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect186), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect187), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect187), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect188), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect188), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect189), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect189), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect190), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect190), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect191), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect191), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect192), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect192), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect193), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect193), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect194), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect194), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect195), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect195), + /* [mod = L=2048, N=256, SHA-384] - GP NOT SUPPORTED */ + /* [mod = L=2048, N=256, SHA-512] - GP NOT SUPPORTED */ + /* [mod = L=3072, N=256, SHA-1] - GP NOT SUPPORTED */ + /* [mod = L=3072, N=256, SHA-224] - GP NOT SUPPORTED */ + /* [mod = L=3072, N=256, SHA-256] */ + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect256), + XTEST_AC_DSA_CASE(1, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect256), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect257), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect257), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect258), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect258), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect259), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect259), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect260), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect260), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect261), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect261), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect262), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect262), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect263), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect263), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect264), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect264), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect265), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect265), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect266), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect266), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect267), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect267), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect268), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect268), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect269), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect269), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_VERIFY, ac_dsa_vect270), + XTEST_AC_DSA_CASE(15, TEE_ALG_DSA_SHA256, TEE_MODE_SIGN, ac_dsa_vect270), + /* [mod = L=3072, N=256, SHA-384] - GP NOT SUPPORTED */ + /* [mod = L=3072, N=256, SHA-512] - GP NOT SUPPORTED */ + + /* ECDSA tests */ + /* [P-192] */ + XTEST_AC_ECC_CASE(0, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_1), + XTEST_AC_ECC_CASE(0, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_1), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_2), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_2), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_3), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_3), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_4), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_4), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_5), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_5), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_6), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_6), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_7), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_7), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_8), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_8), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_9), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_9), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_10), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_10), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_11), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_11), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_12), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_12), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_13), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_13), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_14), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_14), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_15), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P192, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_15), + /* [P-224] */ + XTEST_AC_ECC_CASE(1, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_16), + XTEST_AC_ECC_CASE(1, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_16), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_17), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_17), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_18), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_18), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_19), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_19), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_20), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_20), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_21), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_21), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_22), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_22), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_23), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_23), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_24), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_24), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_25), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_25), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_26), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_26), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_27), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_27), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_28), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_28), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_29), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_29), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_30), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P224, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_30), + /* [P-256] */ + XTEST_AC_ECC_CASE(1, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_31), + XTEST_AC_ECC_CASE(1, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_31), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_32), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_32), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_33), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_33), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_34), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_34), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_35), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_35), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_36), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_36), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_37), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_37), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_38), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_38), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_39), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_39), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_40), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_40), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_41), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_41), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_42), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_42), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_43), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_43), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_44), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_44), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_45), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P256, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_45), + /* [P-384] */ + XTEST_AC_ECC_CASE(1, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_46), + XTEST_AC_ECC_CASE(1, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_46), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_47), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_47), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_48), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_48), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_49), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_49), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_50), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_50), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_51), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_51), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_52), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_52), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_53), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_53), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_54), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_54), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_55), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_55), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_56), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_56), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_57), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_57), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_58), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_58), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_59), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_59), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_60), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P384, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_60), + /* [P-521] */ + XTEST_AC_ECC_CASE(1, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_61), + XTEST_AC_ECC_CASE(1, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_61), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_62), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_62), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_63), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_63), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_64), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_64), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_65), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_65), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_66), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_66), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_67), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_67), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_68), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_68), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_69), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_69), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_70), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_70), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_71), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_71), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_72), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_72), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_73), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_73), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_74), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_74), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_VERIFY, + nist_186_2_ecdsa_testvector_75), + XTEST_AC_ECC_CASE(15, TEE_ALG_ECDSA_P521, TEE_MODE_SIGN, + nist_186_2_ecdsa_testvector_75), + /* [K-163] - GP NOT SUPPORTED */ + /* [K-233] - GP NOT SUPPORTED */ + /* [K-283] - GP NOT SUPPORTED */ + /* [K-409] - GP NOT SUPPORTED */ + /* [K-571] - GP NOT SUPPORTED */ + /* [B-163] - GP NOT SUPPORTED */ + /* [B-233] - GP NOT SUPPORTED */ + /* [B-283] - GP NOT SUPPORTED */ + /* [B-409] - GP NOT SUPPORTED */ + /* [B-571] - GP NOT SUPPORTED */ + + XTEST_AC_ECC_CASE(0, TEE_ALG_SM2_PKE, TEE_MODE_ENCRYPT, + gmt_0003_part5_c2_sm2_testvector), + XTEST_AC_ECC_CASE(0, TEE_ALG_SM2_PKE, TEE_MODE_DECRYPT, + gmt_0003_part5_c2_sm2_testvector), + XTEST_AC_ECC_CASE(0, TEE_ALG_SM2_PKE, TEE_MODE_ENCRYPT, + sm2_testvector2), + + XTEST_AC_ECC_CASE(0, TEE_ALG_SM2_DSA_SM3, TEE_MODE_VERIFY, + gmt_003_part5_a2), + XTEST_AC_ECC_CASE(0, TEE_ALG_SM2_DSA_SM3, TEE_MODE_SIGN, + gmt_003_part5_a2), +}; + +static const struct xtest_ac_case xtest_ac_eddsa_cases[] = { + + XTEST_AC_EDDSA_CASE(0, TEE_ALG_ED25519, TEE_MODE_SIGN, + ed25519_rfc_8032_7_1, 0), + XTEST_AC_EDDSA_CASE(0, TEE_ALG_ED25519, TEE_MODE_VERIFY, + ed25519_rfc_8032_7_1, 0), + + XTEST_AC_EDDSA_CTX_CASE(0, TEE_ALG_ED25519, TEE_MODE_SIGN, + ed25519ctx_rfc_8032_7_2, 0), + XTEST_AC_EDDSA_CTX_CASE(0, TEE_ALG_ED25519, TEE_MODE_VERIFY, + ed25519ctx_rfc_8032_7_2, 0), + + XTEST_AC_EDDSA_CASE(0, TEE_ALG_ED25519, TEE_MODE_SIGN, + ed25519ph_rfc_8032_7_3, 1), + XTEST_AC_EDDSA_CASE(0, TEE_ALG_ED25519, TEE_MODE_VERIFY, + ed25519ph_rfc_8032_7_3, 1), +}; + +static bool create_key(ADBG_Case_t *c, TEEC_Session *s, + uint32_t max_key_size, uint32_t key_type, + TEE_Attribute *attrs, size_t num_attrs, + TEE_ObjectHandle *handle) +{ + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, s, key_type, + max_key_size, handle))) + return false; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, s, *handle, attrs, + num_attrs))) + return false; + + for (n = 0; n < num_attrs; n++) { + uint8_t out[512] = { }; + size_t out_size = sizeof(out); + + if (attrs[n].attributeID == TEE_ATTR_ECC_CURVE) + continue; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, s, *handle, + attrs[n].attributeID, out, &out_size))) + return false; + + if (out_size < attrs[n].content.ref.length) { + memmove(out + (attrs[n].content.ref.length - out_size), + out, + attrs[n].content.ref.length); + memset(out, 0, attrs[n].content.ref.length - out_size); + out_size = attrs[n].content.ref.length; + } + + if (!ADBG_EXPECT_BUFFER(c, attrs[n].content.ref.buffer, + attrs[n].content.ref.length, out, out_size)) + return false; + } + + return true; +} + +#define XTEST_NO_CURVE 0xFFFFFFFF /* implementation-defined as per GP spec */ + +static void xtest_tee_test_4006(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle priv_key_handle = TEE_HANDLE_NULL; + TEE_ObjectHandle pub_key_handle = TEE_HANDLE_NULL; + TEE_Attribute key_attrs[8] = { }; + TEE_Attribute algo_params[2] = { }; + size_t num_algo_params = 0; + uint8_t out[512] = { }; + size_t out_size = 0; + uint8_t out_enc[512] = { }; + size_t out_enc_size = 0; + uint8_t ptx_hash[TEE_MAX_HASH_SIZE] = { }; + size_t ptx_hash_size = 0; + size_t max_key_size = 0; + size_t num_key_attrs = 0; + uint32_t ret_orig = 0; + size_t n = 0; + uint32_t curve = 0; + uint32_t pub_key_type = 0; + uint32_t priv_key_type = 0; + uint32_t hash_algo = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(xtest_ac_cases); n++) { + const struct xtest_ac_case *tv = xtest_ac_cases + n; + + if (tv->level > level) + continue; + + if ((tv->algo == TEE_ALG_SM2_PKE || + tv->algo == TEE_ALG_SM2_DSA_SM3) && + !ta_crypt_cmd_is_algo_supported(c, &session, tv->algo, + TEE_ECC_CURVE_SM2)) { + Do_ADBG_Log("SM2 not supported: skip subcase"); + continue; + } + + Do_ADBG_BeginSubCase(c, "Asym Crypto case %d algo 0x%x line %d", + (int)n, (unsigned int)tv->algo, + (int)tv->line); + + /* + * When signing or verifying we're working with the hash of + * the payload. + */ + if (tv->mode == TEE_MODE_VERIFY || tv->mode == TEE_MODE_SIGN) { + if (TEE_ALG_GET_MAIN_ALG(tv->algo) == TEE_MAIN_ALGO_ECDSA) + hash_algo = TEE_ALG_SHA1; +#if defined(CFG_CRYPTO_RSASSA_NA1) + else if (tv->algo == TEE_ALG_RSASSA_PKCS1_V1_5) + hash_algo = TEE_ALG_SHA256; +#endif + else + hash_algo = TEE_ALG_HASH_ALGO( + TEE_ALG_GET_DIGEST_HASH(tv->algo)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, + &op, hash_algo, TEE_MODE_DIGEST, 0))) + goto out; + + ptx_hash_size = sizeof(ptx_hash); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_digest_do_final(c, & session, op, + tv->ptx, tv->ptx_len, ptx_hash, + &ptx_hash_size))) + goto out; + + /* + * When we use DSA algorithms, the size of the hash we + * consider equals the min between the size of the + * "subprime" in the key and the size of the hash + */ + if (TEE_ALG_GET_MAIN_ALG(tv->algo) == + TEE_MAIN_ALGO_DSA) { + if (tv->params.dsa.sub_prime_len <= + ptx_hash_size) + ptx_hash_size = + tv->params.dsa.sub_prime_len; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + } + + num_algo_params = 0; + num_key_attrs = 0; + switch (TEE_ALG_GET_MAIN_ALG(tv->algo)) { + case TEE_MAIN_ALGO_RSA: + if (tv->params.rsa.salt_len > 0) { + algo_params[0].attributeID = + TEE_ATTR_RSA_PSS_SALT_LENGTH; + algo_params[0].content.value.a = + tv->params.rsa.salt_len; + algo_params[0].content.value.b = 0; + num_algo_params = 1; + } + + max_key_size = tv->params.rsa.modulus_len * 8; + + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_RSA_MODULUS, + tv->params.rsa.modulus, + tv->params.rsa.modulus_len); + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_RSA_PUBLIC_EXPONENT, + tv->params.rsa.pub_exp, + tv->params.rsa.pub_exp_len); + + if (!ADBG_EXPECT_TRUE(c, + create_key(c, &session, + max_key_size, + TEE_TYPE_RSA_PUBLIC_KEY, + key_attrs, + num_key_attrs, + &pub_key_handle))) + goto out; + + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_RSA_PRIVATE_EXPONENT, + tv->params.rsa.priv_exp, + tv->params.rsa.priv_exp_len); + + if (tv->params.rsa.prime1_len != 0) { + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_RSA_PRIME1, + tv->params.rsa.prime1, + tv->params.rsa.prime1_len); + } + + if (tv->params.rsa.prime2_len != 0) { + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_RSA_PRIME2, + tv->params.rsa.prime2, + tv->params.rsa.prime2_len); + } + + if (tv->params.rsa.exp1_len != 0) { + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_RSA_EXPONENT1, + tv->params.rsa.exp1, + tv->params.rsa.exp1_len); + } + + if (tv->params.rsa.exp2_len != 0) { + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_RSA_EXPONENT2, + tv->params.rsa.exp2, + tv->params.rsa.exp2_len); + } + + if (tv->params.rsa.coeff_len != 0) { + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_RSA_COEFFICIENT, + tv->params.rsa.coeff, + tv->params.rsa.coeff_len); + } + + if (!ADBG_EXPECT_TRUE(c, + create_key(c, &session, + max_key_size, + TEE_TYPE_RSA_KEYPAIR, + key_attrs, + num_key_attrs, + &priv_key_handle))) + goto out; + break; + + case TEE_MAIN_ALGO_DSA: + max_key_size = tv->params.dsa.prime_len * 8; + + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_DSA_PRIME, + tv->params.dsa.prime, + tv->params.dsa.prime_len); + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_DSA_SUBPRIME, + tv->params.dsa.sub_prime, + tv->params.dsa.sub_prime_len); + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_DSA_BASE, + tv->params.dsa.base, + tv->params.dsa.base_len); + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_DSA_PUBLIC_VALUE, + tv->params.dsa.pub_val, + tv->params.dsa.pub_val_len); + + if (!ADBG_EXPECT_TRUE(c, + create_key(c, &session, max_key_size, + TEE_TYPE_DSA_PUBLIC_KEY, key_attrs, + num_key_attrs, &pub_key_handle))) + goto out; + + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_DSA_PRIVATE_VALUE, + tv->params.dsa.priv_val, + tv->params.dsa.priv_val_len); + + if (!ADBG_EXPECT_TRUE(c, + create_key(c, &session, max_key_size, + TEE_TYPE_DSA_KEYPAIR, key_attrs, + num_key_attrs, &priv_key_handle))) + goto out; + break; + + case TEE_MAIN_ALGO_ECDSA: + case TEE_MAIN_ALGO_SM2_PKE: + case TEE_MAIN_ALGO_SM2_DSA_SM3: + switch (tv->algo) { + case TEE_ALG_ECDSA_P192: + curve = TEE_ECC_CURVE_NIST_P192; + pub_key_type = TEE_TYPE_ECDSA_PUBLIC_KEY; + priv_key_type = TEE_TYPE_ECDSA_KEYPAIR; + break; + case TEE_ALG_ECDSA_P224: + curve = TEE_ECC_CURVE_NIST_P224; + pub_key_type = TEE_TYPE_ECDSA_PUBLIC_KEY; + priv_key_type = TEE_TYPE_ECDSA_KEYPAIR; + break; + case TEE_ALG_ECDSA_P256: + curve = TEE_ECC_CURVE_NIST_P256; + pub_key_type = TEE_TYPE_ECDSA_PUBLIC_KEY; + priv_key_type = TEE_TYPE_ECDSA_KEYPAIR; + break; + case TEE_ALG_ECDSA_P384: + curve = TEE_ECC_CURVE_NIST_P384; + pub_key_type = TEE_TYPE_ECDSA_PUBLIC_KEY; + priv_key_type = TEE_TYPE_ECDSA_KEYPAIR; + break; + case TEE_ALG_ECDSA_P521: + curve = TEE_ECC_CURVE_NIST_P521; + pub_key_type = TEE_TYPE_ECDSA_PUBLIC_KEY; + priv_key_type = TEE_TYPE_ECDSA_KEYPAIR; + break; + case TEE_ALG_SM2_PKE: + curve = XTEST_NO_CURVE; + pub_key_type = TEE_TYPE_SM2_PKE_PUBLIC_KEY; + priv_key_type = TEE_TYPE_SM2_PKE_KEYPAIR; + break; + case TEE_ALG_SM2_DSA_SM3: + curve = XTEST_NO_CURVE; + pub_key_type = TEE_TYPE_SM2_DSA_PUBLIC_KEY; + priv_key_type = TEE_TYPE_SM2_DSA_KEYPAIR; + break; + default: + curve = 0xFF; + break; + } + + if (tv->algo == TEE_ALG_ECDSA_P521) + max_key_size = 521; + else + max_key_size = tv->params.ecc.private_len * 8; + + if (curve != XTEST_NO_CURVE) + xtest_add_attr_value(&num_key_attrs, key_attrs, + TEE_ATTR_ECC_CURVE, curve, 0); + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_ECC_PUBLIC_VALUE_X, + tv->params.ecc.public_x, + tv->params.ecc.public_x_len); + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_ECC_PUBLIC_VALUE_Y, + tv->params.ecc.public_y, + tv->params.ecc.public_y_len); + + if (!ADBG_EXPECT_TRUE(c, + create_key(c, &session, max_key_size, + pub_key_type, key_attrs, + num_key_attrs, &pub_key_handle))) + goto out; + + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_ECC_PRIVATE_VALUE, + tv->params.ecc.private, + tv->params.ecc.private_len); + + if (!ADBG_EXPECT_TRUE(c, + create_key(c, &session, max_key_size, + priv_key_type, key_attrs, + num_key_attrs, &priv_key_handle))) + goto out; + break; + + default: + ADBG_EXPECT_TRUE(c, false); + goto out; + } + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + switch (tv->mode) { + case TEE_MODE_ENCRYPT: + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, + &op, tv->algo, TEE_MODE_ENCRYPT, + max_key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + pub_key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + pub_key_handle))) + goto out; + pub_key_handle = TEE_HANDLE_NULL; + + num_algo_params = 0; + if (tv->algo == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1) { + algo_params[0].attributeID = + TEE_ATTR_RSA_OAEP_MGF_HASH; + algo_params[0].content.ref.length = + sizeof(uint32_t); + algo_params[0].content.ref.buffer = + &(uint32_t){TEE_ALG_SHA1}; + num_algo_params = 1; + } + + + out_enc_size = sizeof(out_enc); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_encrypt(c, &session, op, + algo_params, num_algo_params, tv->ptx, + tv->ptx_len, out_enc, &out_enc_size))) + goto out; + + /* + * A PS which is random is added when formatting the + * message internally of the algorithm so we can't + * verify against precomputed values, instead we use the + * decrypt operation to see that output is correct. + */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, + &op, tv->algo, TEE_MODE_DECRYPT, + max_key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + priv_key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + priv_key_handle))) + goto out; + + priv_key_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_decrypt(c, &session, op, + NULL, 0, out_enc, out_enc_size, out, + &out_size))) + goto out; + + (void)ADBG_EXPECT_BUFFER(c, tv->ptx, tv->ptx_len, out, + out_size); + break; + + case TEE_MODE_DECRYPT: + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, + &op, tv->algo, TEE_MODE_DECRYPT, + max_key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + priv_key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + priv_key_handle))) + goto out; + + priv_key_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_decrypt(c, &session, op, + NULL, 0, tv->ctx, tv->ctx_len, out, + &out_size))) + goto out; + + (void)ADBG_EXPECT_BUFFER(c, tv->ptx, tv->ptx_len, out, + out_size); + break; + + case TEE_MODE_VERIFY: + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, + &op, tv->algo, TEE_MODE_VERIFY, + max_key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + pub_key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + pub_key_handle))) + goto out; + + pub_key_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_verify(c, &session, op, + algo_params, num_algo_params, ptx_hash, + ptx_hash_size, tv->ctx, tv->ctx_len))) + goto out; + break; + + case TEE_MODE_SIGN: + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, + &op, tv->algo, TEE_MODE_SIGN, + max_key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + priv_key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + priv_key_handle))) + goto out; + + priv_key_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_sign(c, &session, op, + algo_params, num_algo_params, ptx_hash, + ptx_hash_size, out, &out_size))) + goto out; + + if (TEE_ALG_GET_CHAIN_MODE(tv->algo) == + TEE_CHAIN_MODE_PKCS1_PSS_MGF1 || + tv->algo == TEE_ALG_DSA_SHA1 || + tv->algo == TEE_ALG_DSA_SHA224 || + tv->algo == TEE_ALG_DSA_SHA256 || + TEE_ALG_GET_MAIN_ALG(tv->algo) == + TEE_MAIN_ALGO_ECDSA || + tv->algo == TEE_ALG_SM2_DSA_SM3) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, + op))) + goto out; + /* + * The salt or K is random so we can't verify + * signing against precomputed values, instead + * we use the verify operation to see that + * output is correct. + */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, + &session, &op, tv->algo, + TEE_MODE_VERIFY, max_key_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, + &session, op, pub_key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, + &session, pub_key_handle))) + goto out; + + pub_key_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_verify(c, + &session, op, algo_params, + num_algo_params, ptx_hash, + ptx_hash_size, out, out_size))) + goto out; + } else { + (void)ADBG_EXPECT_BUFFER(c, tv->ctx, + tv->ctx_len, out, + out_size); + } + break; + + default: + break; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + pub_key_handle))) + goto out; + pub_key_handle = TEE_HANDLE_NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + priv_key_handle))) + goto out; + + priv_key_handle = TEE_HANDLE_NULL; + + Do_ADBG_EndSubCase(c, NULL); + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4006, xtest_tee_test_4006, + "Test TEE Internal API Asymmetric Cipher operations"); + +#define KEY_ATTR(x, y) { #x, (x), y } + +struct key_attrs { + const char *name; + uint32_t attr; + /* + * When keysize_check != 0: size of attribute is checked + * Expected value is key_size bits except for DH in which case it is + * the value of keysize_check. + */ + uint32_t keysize_check; +}; + +static bool test_keygen_attributes(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle key, uint32_t key_size, + struct key_attrs *attrs, size_t num_attrs) +{ + uint8_t out[2048] = { }; + size_t out_size = 0; + size_t n = 0; + size_t m = 0; + + for (m = 0; m < num_attrs; m++) { + if ((attrs[m].attr & TEE_ATTR_BIT_VALUE) == 0) { + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, s, + key, attrs[m].attr, out, &out_size))) + return false; + + if (attrs[m].keysize_check) + ADBG_EXPECT_COMPARE_UNSIGNED(c, out_size, <=, + key_size / 8); + + if (out_size > 0) { + /* Check that buffer isn't all zeroes */ + for (n = 0; n < out_size; n++) + if (out[n] != 0) + break; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, n, <, + out_size)) + return false; + } + } else { + uint32_t a = 0; + uint32_t b = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_value_attribute(c, s, key, + attrs[m].attr, &a, &b))) + return false; + } + } + return true; +} + +static bool test_secret_value(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle key, uint32_t key_size) +{ + const struct key_attrs attrs[] = { + KEY_ATTR(TEE_ATTR_SECRET_VALUE, true), + }; + + return test_keygen_attributes(c, s, key, key_size, + (struct key_attrs *)&attrs, + ARRAY_SIZE(attrs)); +} + + +static bool test_rsa_key_pair(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle key, uint32_t key_size) +{ + const struct key_attrs attrs[] = { + KEY_ATTR(TEE_ATTR_RSA_MODULUS, true), + KEY_ATTR(TEE_ATTR_RSA_PUBLIC_EXPONENT, false), + KEY_ATTR(TEE_ATTR_RSA_PRIVATE_EXPONENT, false), + KEY_ATTR(TEE_ATTR_RSA_PRIME1, false), + KEY_ATTR(TEE_ATTR_RSA_PRIME2, false), + KEY_ATTR(TEE_ATTR_RSA_EXPONENT1, false), + KEY_ATTR(TEE_ATTR_RSA_EXPONENT2, false), + KEY_ATTR(TEE_ATTR_RSA_COEFFICIENT, false), + }; + + return test_keygen_attributes(c, s, key, key_size, + (struct key_attrs *)&attrs, + ARRAY_SIZE(attrs)); +} + +static bool test_ecc_key_pair(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle key, uint32_t key_size) +{ + const struct key_attrs attrs[] = { + KEY_ATTR(TEE_ATTR_ECC_PRIVATE_VALUE, false), + KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_X , false), + KEY_ATTR(TEE_ATTR_ECC_PUBLIC_VALUE_Y , false), + /* KEY_ATTR(TEE_ATTR_ECC_CURVE, false), - do not test */ + }; + + return test_keygen_attributes(c, s, key, key_size, + (struct key_attrs *)&attrs, + ARRAY_SIZE(attrs)); +} + +static bool test_dh_key_pair(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle key, uint32_t check_keysize) +{ + const struct key_attrs attrs[] = { + KEY_ATTR(TEE_ATTR_DH_PRIME, false), + KEY_ATTR(TEE_ATTR_DH_BASE, false), + KEY_ATTR(TEE_ATTR_DH_PUBLIC_VALUE, false), + KEY_ATTR(TEE_ATTR_DH_PRIVATE_VALUE, check_keysize), + KEY_ATTR(TEE_ATTR_DH_X_BITS, false), + }; + + return test_keygen_attributes(c, s, key, check_keysize, + (struct key_attrs *)&attrs, + ARRAY_SIZE(attrs)); +} + +static bool test_dsa_key_pair(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle key, uint32_t key_size) +{ + const struct key_attrs attrs[] = { + KEY_ATTR(TEE_ATTR_DSA_PRIME, true), + KEY_ATTR(TEE_ATTR_DSA_SUBPRIME, false), + KEY_ATTR(TEE_ATTR_DSA_BASE, false), + KEY_ATTR(TEE_ATTR_DSA_PUBLIC_VALUE, false), + KEY_ATTR(TEE_ATTR_DSA_PRIVATE_VALUE, false), + }; + + return test_keygen_attributes(c, s, key, key_size, + (struct key_attrs *)&attrs, + ARRAY_SIZE(attrs)); +} + +static bool test_x25519_key_pair(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle key, uint32_t key_size) +{ + const struct key_attrs attrs[] = { + KEY_ATTR(TEE_ATTR_X25519_PRIVATE_VALUE, false), + KEY_ATTR(TEE_ATTR_X25519_PUBLIC_VALUE, false), + }; + + return test_keygen_attributes(c, s, key, key_size, + (struct key_attrs *)&attrs, + ARRAY_SIZE(attrs)); +} + +static bool test_ed25519_key_pair(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle key, uint32_t key_size) +{ + const struct key_attrs attrs[] = { + KEY_ATTR(TEE_ATTR_ED25519_PRIVATE_VALUE, false), + KEY_ATTR(TEE_ATTR_ED25519_PUBLIC_VALUE, false), + }; + + return test_keygen_attributes(c, s, key, key_size, + (struct key_attrs *)&attrs, + ARRAY_SIZE(attrs)); +} + +static bool generate_and_test_key(ADBG_Case_t *c, TEEC_Session *s, + uint32_t key_type, uint32_t check_keysize, + uint32_t key_size, + TEE_Attribute *params, size_t param_count) +{ + TEE_ObjectHandle key = TEE_HANDLE_NULL; + bool ret_val = true; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, s, key_type, key_size, + &key))) + return false; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_generate_key(c, s, key, key_size, params, + param_count))) + return false; + + switch (key_type) { + case TEE_TYPE_DES: + case TEE_TYPE_DES3: + ret_val = ADBG_EXPECT_TRUE(c, + test_secret_value(c, s, key, + key_size + key_size / 7)); + break; + case TEE_TYPE_AES: + 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: + ret_val = ADBG_EXPECT_TRUE(c, + test_secret_value(c, s, key, key_size)); + break; + + case TEE_TYPE_RSA_KEYPAIR: + ret_val = ADBG_EXPECT_TRUE(c, + test_rsa_key_pair(c, s, key, key_size)); + break; + + case TEE_TYPE_ECDSA_KEYPAIR: + case TEE_TYPE_ECDH_KEYPAIR: + ret_val = ADBG_EXPECT_TRUE(c, + test_ecc_key_pair(c, s, key, key_size)); + break; + + case TEE_TYPE_DH_KEYPAIR: + ret_val = ADBG_EXPECT_TRUE(c, + test_dh_key_pair(c, s, key, check_keysize)); + break; + + case TEE_TYPE_DSA_KEYPAIR: + ret_val = ADBG_EXPECT_TRUE(c, + test_dsa_key_pair(c, s, key, key_size)); + break; + + case TEE_TYPE_X25519_KEYPAIR: + ret_val = ADBG_EXPECT_TRUE(c, + test_x25519_key_pair(c, s, key, key_size)); + break; + + case TEE_TYPE_ED25519_KEYPAIR: + ret_val = ADBG_EXPECT_TRUE(c, + test_ed25519_key_pair(c, s, key, key_size)); + break; + + default: + ret_val = false; + break; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, s, key))) + return false; + + return ret_val; +} + +struct key_types_noparam { + unsigned level; + const char *name; + uint32_t key_type; + uint32_t quanta; + uint32_t min_size; + uint32_t max_size; +}; + +static void keygen_noparams(ADBG_Case_t *c, TEEC_Session *session, + const struct key_types_noparam *key_types, + size_t num_key_types) +{ + size_t n = 0; + uint32_t key_size = 0; + + for (n = 0; n < num_key_types; n++) { + uint32_t min_size = key_types[n].min_size; + uint32_t max_size = key_types[n].max_size; + uint32_t quanta = key_types[n].quanta; + + if (key_types[n].level > level) + continue; + + Do_ADBG_BeginSubCase(c, "Generate %s key", key_types[n].name); + + for (key_size = min_size; key_size <= max_size; + key_size += quanta) { + if (!ADBG_EXPECT_TRUE(c, + generate_and_test_key(c, session, key_types + [n].key_type, 1, key_size, NULL, 0))) + break; + } + + Do_ADBG_EndSubCase(c, "Generate %s key", key_types[n].name); + } +} + +static void xtest_tee_test_4007_symmetric(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + static const struct key_types_noparam key_types[] = { + { 0, "AES", TEE_TYPE_AES, 64, 128, + 256 /* valid sizes 128, 192, 256 */ }, + { 0, "DES", TEE_TYPE_DES, 56, 56, 56 /* valid size 56 */ }, + { 0, "DES3", TEE_TYPE_DES3, 56, 112, + 168 /* valid sizes 112, 168 */ }, + { 0, "HMAC-MD5", TEE_TYPE_HMAC_MD5, 8, 64, 512 }, + { 0, "HMAC-SHA1", TEE_TYPE_HMAC_SHA1, 8, 80, 512 }, + { 0, "HMAC-SHA224", TEE_TYPE_HMAC_SHA224, 8, 112, 512 }, + { 0, "HMAC-SHA256", TEE_TYPE_HMAC_SHA256, 8, 192, 1024 }, + { 0, "HMAC-SHA384", TEE_TYPE_HMAC_SHA384, 8, 256, 1024 }, + { 0, "HMAC-SHA512", TEE_TYPE_HMAC_SHA512, 8, 256, 1024 }, + { 0, "Generic secret", TEE_TYPE_GENERIC_SECRET, 8, 128, 4096 }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + keygen_noparams(c, &session, key_types, ARRAY_SIZE(key_types)); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4007_symmetric, xtest_tee_test_4007_symmetric, + "Test TEE Internal API Generate Symmetric key"); + +static void xtest_tee_test_4007_rsa(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + static const struct key_types_noparam key_types[] = { +#ifndef CFG_CRYPTO_SE05X + { 0, "RSA-256", TEE_TYPE_RSA_KEYPAIR, 1, 256, 256 }, + { 1, "RSA-384", TEE_TYPE_RSA_KEYPAIR, 1, 384, 384 }, +#endif + { 1, "RSA-512", TEE_TYPE_RSA_KEYPAIR, 1, 512, 512 }, +#ifndef CFG_CRYPTO_SE05X + { 1, "RSA-640", TEE_TYPE_RSA_KEYPAIR, 1, 640, 640 }, + { 1, "RSA-768", TEE_TYPE_RSA_KEYPAIR, 1, 768, 768 }, + { 1, "RSA-896", TEE_TYPE_RSA_KEYPAIR, 1, 896, 896 }, +#endif + { 1, "RSA-1024", TEE_TYPE_RSA_KEYPAIR, 1, 1024, 1024 }, + { 1, "RSA-2048", TEE_TYPE_RSA_KEYPAIR, 1, 2048, 2048 }, + { 1, "RSA-3072", TEE_TYPE_RSA_KEYPAIR, 1, 3072, 3072 }, + { 1, "RSA-4096", TEE_TYPE_RSA_KEYPAIR, 1, 4096, 4096 }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + keygen_noparams(c, &session, key_types, ARRAY_SIZE(key_types)); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4007_rsa, xtest_tee_test_4007_rsa, + "Test TEE Internal API Generate RSA key"); + +static void xtest_tee_test_4007_dh(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + size_t param_count = 0; + /* + * Note that the key size parameter is not used when creating the keys + * but specifying these sizes make it possible to test the expected size + * of the private value. This also means that the keysize must match the + * size of p or what is specified in private_bits or the equvivalent + * size of the subprime parameter. + */ + TEE_Attribute params[4] = { }; + +#define XTEST_DH_GK_DATA(vect) \ + ARRAY(vect ## _p), \ + ARRAY(vect ## _g), \ + &vect ## _private_bits, \ + 0, 0 +#define XTEST_DH_GK_DATA_SUBPRIME(vect) \ + ARRAY(vect ## _p), \ + ARRAY(vect ## _g), \ + &vect ## _private_bits, \ + ARRAY(vect ## _subprime) + static const struct { + unsigned level; + uint32_t key_size; + const uint8_t *p; + size_t p_len; + const uint8_t *g; + size_t g_len; + const uint32_t *private_bits; + const uint8_t *subprime; + size_t subprime_len; + } key_types[] = { + { 0, 256, XTEST_DH_GK_DATA(keygen_dh256) }, + { 0, 320, XTEST_DH_GK_DATA(keygen_dh320) }, + { 1, 384, XTEST_DH_GK_DATA(keygen_dh384) }, + { 1, 448, XTEST_DH_GK_DATA(keygen_dh448) }, + { 1, 512, XTEST_DH_GK_DATA(keygen_dh512) }, + { 1, 576, XTEST_DH_GK_DATA(keygen_dh576) }, + { 1, 640, XTEST_DH_GK_DATA(keygen_dh640) }, + { 1, 704, XTEST_DH_GK_DATA(keygen_dh704) }, + { 1, 768, XTEST_DH_GK_DATA(keygen_dh768) }, + { 1, 832, XTEST_DH_GK_DATA(keygen_dh832) }, + { 1, 896, XTEST_DH_GK_DATA(keygen_dh896) }, + { 1, 960, XTEST_DH_GK_DATA(keygen_dh960) }, + { 1, 1024, XTEST_DH_GK_DATA(keygen_dh1024) }, + { 1, 1088, XTEST_DH_GK_DATA(keygen_dh1088) }, + { 1, 1152, XTEST_DH_GK_DATA(keygen_dh1152) }, + { 1, 1216, XTEST_DH_GK_DATA(keygen_dh1216) }, + { 1, 1280, XTEST_DH_GK_DATA(keygen_dh1280) }, + { 1, 1344, XTEST_DH_GK_DATA(keygen_dh1344) }, + { 1, 1408, XTEST_DH_GK_DATA(keygen_dh1408) }, + { 1, 1472, XTEST_DH_GK_DATA(keygen_dh1472) }, + { 1, 1536, XTEST_DH_GK_DATA(keygen_dh1536) }, + { 1, 1600, XTEST_DH_GK_DATA(keygen_dh1600) }, + { 1, 1664, XTEST_DH_GK_DATA(keygen_dh1664) }, + { 1, 1728, XTEST_DH_GK_DATA(keygen_dh1728) }, + { 1, 1792, XTEST_DH_GK_DATA(keygen_dh1792) }, + { 1, 1856, XTEST_DH_GK_DATA(keygen_dh1856) }, + { 1, 1920, XTEST_DH_GK_DATA(keygen_dh1920) }, + { 1, 1984, XTEST_DH_GK_DATA(keygen_dh1984) }, + { 1, 2048, XTEST_DH_GK_DATA(keygen_dh2048) }, + { 1, 2048, XTEST_DH_GK_DATA_SUBPRIME(keygen_dh2048_subprime) } + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(key_types); n++) { + if (key_types[n].level > level) + continue; + + Do_ADBG_BeginSubCase(c, + "Generate DH key %d bits - Private bits = %d", + key_types[n].key_size, + *key_types[n].private_bits); + param_count = 0; + + xtest_add_attr(¶m_count, params, + TEE_ATTR_DH_PRIME, + key_types[n].p, key_types[n].p_len); + + xtest_add_attr(¶m_count, params, TEE_ATTR_DH_BASE, + key_types[n].g, key_types[n].g_len); + + if (key_types[n].private_bits != 0) { + params[param_count].attributeID = TEE_ATTR_DH_X_BITS; + + params[param_count].content.value.a = + *key_types[n].private_bits; + + params[param_count].content.value.b = 0; + param_count++; + } + + if (key_types[n].subprime != 0) { + xtest_add_attr(¶m_count, params, + TEE_ATTR_DH_SUBPRIME, + key_types[n].subprime, + key_types[n].subprime_len); + } + + if (!ADBG_EXPECT_TRUE(c, + generate_and_test_key(c, &session, TEE_TYPE_DH_KEYPAIR, + *key_types[n].private_bits, + key_types[n]. key_size, params, param_count))) + break; + + Do_ADBG_EndSubCase(c, + "Generate DH key %d bits - Private bits = %d", + key_types[n].key_size, + *key_types[n].private_bits); + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4007_dh, xtest_tee_test_4007_dh, + "Test TEE Internal API Generate DH key"); + +static void xtest_tee_test_4007_dsa(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + size_t param_count = 0; + TEE_Attribute params[4] = { }; + +#define XTEST_DSA_GK_DATA(vect) \ + ARRAY(vect ## _p), \ + ARRAY(vect ## _g), \ + ARRAY(vect ## _q) + static const struct { + unsigned level; + uint32_t key_size; + const uint8_t *prime; + size_t prime_len; + const uint8_t *base; + size_t base_len; + const uint8_t *sub_prime; + size_t sub_prime_len; + } key_types[] = { + { 0, 1024, XTEST_DSA_GK_DATA(keygen_dsa_test1) }, + { 0, 512, XTEST_DSA_GK_DATA(keygen_dsa512) }, + { 0, 576, XTEST_DSA_GK_DATA(keygen_dsa576) }, + { 0, 640, XTEST_DSA_GK_DATA(keygen_dsa640) }, + { 0, 704, XTEST_DSA_GK_DATA(keygen_dsa704) }, + { 0, 768, XTEST_DSA_GK_DATA(keygen_dsa768) }, + { 0, 832, XTEST_DSA_GK_DATA(keygen_dsa832) }, + { 0, 896, XTEST_DSA_GK_DATA(keygen_dsa896) }, + { 0, 960, XTEST_DSA_GK_DATA(keygen_dsa960) }, + { 0, 1024, XTEST_DSA_GK_DATA(keygen_dsa1024) }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(key_types); n++) { + if (key_types[n].level > level) + continue; + + Do_ADBG_BeginSubCase(c, "Generate DSA key %d bits", + key_types[n].key_size); + param_count = 0; + + + xtest_add_attr(¶m_count, params, TEE_ATTR_DSA_PRIME, + key_types[n].prime, key_types[n].prime_len); + + xtest_add_attr(¶m_count, params, TEE_ATTR_DSA_SUBPRIME, + key_types[n].sub_prime, + key_types[n].sub_prime_len); + + xtest_add_attr(¶m_count, params, TEE_ATTR_DSA_BASE, + key_types[n].base, key_types[n].base_len); + + if (!ADBG_EXPECT_TRUE(c, + generate_and_test_key(c, &session, TEE_TYPE_DSA_KEYPAIR, + 1, key_types[n]. key_size, params, + param_count))) + break; + + Do_ADBG_EndSubCase(c, "Generate DSA key %d bits", + key_types[n].key_size); + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4007_dsa, xtest_tee_test_4007_dsa, + "Test TEE Internal API Generate DSA key"); + +static void xtest_tee_test_4007_ecc(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + size_t param_count = 0; + TEE_Attribute params[4] = { }; + + static const struct { + unsigned level; + const char *name; + uint32_t algo; + uint32_t curve; + uint32_t key_size; + } key_types[] = { + /* ECDSA */ + { 0, "ECDSA-192", TEE_TYPE_ECDSA_KEYPAIR, TEE_ECC_CURVE_NIST_P192, + 192 }, + { 1, "ECDSA-224", TEE_TYPE_ECDSA_KEYPAIR, TEE_ECC_CURVE_NIST_P224, + 224 }, + { 1, "ECDSA-256", TEE_TYPE_ECDSA_KEYPAIR, TEE_ECC_CURVE_NIST_P256, + 256 }, + { 1, "ECDSA-384", TEE_TYPE_ECDSA_KEYPAIR, TEE_ECC_CURVE_NIST_P384, + 384 }, + { 1, "ECDSA-521", TEE_TYPE_ECDSA_KEYPAIR, TEE_ECC_CURVE_NIST_P521, + 521 }, + + /* ECDH */ + { 0, "ECDH-192", TEE_TYPE_ECDH_KEYPAIR, TEE_ECC_CURVE_NIST_P192, + 192 }, + { 1, "ECDH-224", TEE_TYPE_ECDH_KEYPAIR, TEE_ECC_CURVE_NIST_P224, + 224 }, + { 1, "ECDH-256", TEE_TYPE_ECDH_KEYPAIR, TEE_ECC_CURVE_NIST_P256, + 256 }, + { 1, "ECDH-384", TEE_TYPE_ECDH_KEYPAIR, TEE_ECC_CURVE_NIST_P384, + 384 }, + { 1, "ECDH-521", TEE_TYPE_ECDH_KEYPAIR, TEE_ECC_CURVE_NIST_P521, + 521 }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(key_types); n++) { + if (key_types[n].level > level) + continue; + + Do_ADBG_BeginSubCase(c, "Generate %s", key_types[n].name); + param_count = 0; + + xtest_add_attr_value(¶m_count, params, TEE_ATTR_ECC_CURVE, + key_types[n].curve, 0); + + if (!ADBG_EXPECT_TRUE(c, + generate_and_test_key(c, &session, key_types[n].algo, + 0, key_types[n].key_size, params, + param_count))) + break; + + Do_ADBG_EndSubCase(c, "Generate %s", key_types[n].name); + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4007_ecc, xtest_tee_test_4007_ecc, + "Test TEE Internal API Generate ECC key"); + +static void xtest_tee_test_4007_x25519(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + if (!ta_crypt_cmd_is_algo_supported(c, &session, TEE_ALG_X25519, + TEE_ECC_CURVE_25519)) { + Do_ADBG_Log("X25519 not supported: skip subcase"); + goto out; + } + + Do_ADBG_BeginSubCase(c, "Generate X25519 key"); + + if (!ADBG_EXPECT_TRUE(c, + generate_and_test_key(c, &session, + TEE_TYPE_X25519_KEYPAIR, 0, 256, + NULL, 0))) + return; + + Do_ADBG_EndSubCase(c, "Generate X25519 key"); +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4007_x25519, xtest_tee_test_4007_x25519, + "Test TEE Internal API Generate X25519 key"); + + +static void xtest_tee_test_4007_ed25519(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + if (!ta_crypt_cmd_is_algo_supported(c, &session, TEE_ALG_ED25519, + TEE_ECC_CURVE_25519)) { + Do_ADBG_Log("ED25519 not supported: skip subcase"); + goto out; + } + + Do_ADBG_BeginSubCase(c, "Generate Ed25519 key"); + + ADBG_EXPECT_TRUE(c, generate_and_test_key(c, &session, + TEE_TYPE_ED25519_KEYPAIR, + 0, 256, NULL, 0)); + + Do_ADBG_EndSubCase(c, "Generate Ed25519 key"); +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4007_ed25519, xtest_tee_test_4007_ed25519, + "Test TEE Internal API Generate ed25519 key"); + +static void xtest_tee_test_4008(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle key_handle = TEE_HANDLE_NULL; + TEE_ObjectHandle sv_handle = TEE_HANDLE_NULL; + TEE_Attribute params[4] = { }; + size_t param_count = 0; + uint8_t out[2048] = { }; + size_t out_size = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "Derive DH key success"); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + TEE_ALG_DH_DERIVE_SHARED_SECRET, TEE_MODE_DERIVE, + derive_key_max_keysize))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, & session, + TEE_TYPE_DH_KEYPAIR, derive_key_max_keysize, + &key_handle))) + goto out; + + xtest_add_attr(¶m_count, params, TEE_ATTR_DH_PRIME, + ARRAY(derive_key_dh_prime)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_DH_BASE, + ARRAY(derive_key_dh_base)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_DH_PUBLIC_VALUE, + ARRAY(derive_key_dh_public_value)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_DH_PRIVATE_VALUE, + ARRAY(derive_key_dh_private_value)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, key_handle, + params, param_count))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, & session, key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_GENERIC_SECRET, derive_key_max_keysize, + &sv_handle))) + goto out; + + /* reuse but reset params and param-count */ + param_count = 0; + + xtest_add_attr(¶m_count, params, TEE_ATTR_DH_PUBLIC_VALUE, + ARRAY(derive_key_dh_public_value_2)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, &session, op, sv_handle, params, + param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, &session, sv_handle, + TEE_ATTR_SECRET_VALUE, out, &out_size))) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, derive_key_dh_shared_secret, + sizeof(derive_key_dh_shared_secret), out, + out_size)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, sv_handle))) + goto out; +out: + Do_ADBG_EndSubCase(c, "Derive DH key success"); + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4008, xtest_tee_test_4008, + "Test TEE Internal API Derive key"); + +static void xtest_tee_test_4009(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle key_handle = TEE_HANDLE_NULL; + TEE_ObjectHandle sv_handle = TEE_HANDLE_NULL; + TEE_Attribute params[4] = { }; + size_t param_count = 0; + uint8_t out[2048] = { }; + size_t out_size = 0; + uint32_t size_bytes = 0; + uint32_t i = 0; + struct derive_key_ecdh_t const *pt = NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + for (i = 0; i < ARRAY_SIZE(derive_key_ecdh); i++) { + pt = &derive_key_ecdh[i]; + + if (pt->level > level) + continue; + + Do_ADBG_BeginSubCase(c, "Derive ECDH key - algo = 0x%x", + pt->algo); + size_bytes = (pt->keysize + 7) / 8; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + pt->algo, + TEE_MODE_DERIVE, pt->keysize))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, & session, + TEE_TYPE_ECDH_KEYPAIR, pt->keysize, + &key_handle))) + goto out; + + param_count = 0; + xtest_add_attr_value(¶m_count, params, + TEE_ATTR_ECC_CURVE, pt->curve, 0); + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_PRIVATE_VALUE, + pt->private, size_bytes); + /* + * The public value is not used, but we should provide a valid + * one to avoid rejection in case TEE_PopulateTransientObject() + * checks for key validity. + */ + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_PUBLIC_VALUE_X, + pt->public_x, size_bytes); + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_PUBLIC_VALUE_Y, + pt->public_y, size_bytes); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, + &session, + key_handle, params, param_count))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, & session, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_GENERIC_SECRET, size_bytes * 8, + &sv_handle))) + goto out; + + /* reuse but reset params and param-count */ + param_count = 0; + + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_PUBLIC_VALUE_X, + pt->public_x, size_bytes); + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_PUBLIC_VALUE_Y, + pt->public_y, size_bytes); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, &session, op, sv_handle, + params, param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, &session, + sv_handle, + TEE_ATTR_SECRET_VALUE, out, &out_size))) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, pt->out, size_bytes, + out, out_size)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + sv_handle))) + goto out; + + Do_ADBG_EndSubCase(c, "Derive ECDH key - algo = 0x%x", + pt->algo); + } + + goto noerror; + +out: + Do_ADBG_EndSubCase(c, "Derive ECDH key - algo = 0x%x", pt->algo); + +noerror: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4009, xtest_tee_test_4009, + "Test TEE Internal API Derive key ECDH"); + +static void xtest_tee_test_4010(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + TEE_ObjectHandle o = TEE_HANDLE_NULL; + static const uint8_t large_key[1024] = { 1, 2, 3, 4, 5, 6 }; + static const TEE_Attribute attr = { + .attributeID = TEE_ATTR_SECRET_VALUE, + .content.ref.buffer = (void *)large_key, + .content.ref.length = sizeof(large_key), + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_HMAC_SHA256, 1024, &o))) + goto out; + + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_TARGET_DEAD, + ta_crypt_cmd_populate_transient_object(c, &session, o, + &attr, 1)); + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4010, xtest_tee_test_4010, + "Test TEE Internal API create transient object (negative)"); + +static void xtest_tee_test_4011(ADBG_Case_t *c) +{ + TEEC_Session s = { }; + size_t key_size = 512; + TEE_ObjectHandle key = TEE_HANDLE_NULL; + TEE_OperationHandle ops = TEE_HANDLE_NULL; + TEE_OperationHandle opv = TEE_HANDLE_NULL; + TEE_OperationHandle ope = TEE_HANDLE_NULL; + TEE_OperationHandle opd = TEE_HANDLE_NULL; + uint32_t ret_orig = 0; + uint8_t in[TEE_SHA1_HASH_SIZE] = { }; + uint8_t out[1024] = { }; + uint8_t tmp[1024] = { }; + size_t out_size = 0; + size_t tmp_size = 0; + size_t n = 0; + size_t m = 0; + size_t i = 0; + + /* Setup session, initialize message to sign, create a keypair */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session(&s, + &crypt_user_ta_uuid, NULL, &ret_orig))) + return; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, ta_crypt_cmd_random_number_generate(c, + &s, in, sizeof(in)))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, ta_crypt_cmd_allocate_transient_object( + c, &s, TEE_TYPE_RSA_KEYPAIR, key_size, &key))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, ta_crypt_cmd_generate_key(c, &s, + key, key_size, NULL, 0))) + goto out; + + /* Allocate operations for sign, verify, encrypt and decrypt */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, ta_crypt_cmd_allocate_operation(c, &s, + &ops, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_SIGN, + key_size))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, ta_crypt_cmd_allocate_operation(c, &s, + &opv, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_MODE_VERIFY, + key_size))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, ta_crypt_cmd_allocate_operation(c, &s, + &ope, TEE_ALG_RSA_NOPAD, TEE_MODE_ENCRYPT, key_size))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, ta_crypt_cmd_allocate_operation(c, &s, + &opd, TEE_ALG_RSA_NOPAD, TEE_MODE_DECRYPT, key_size))) + goto out; + + /* Assign the keypair to all operations */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &s, ops, key))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &s, opv, key))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &s, ope, key))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &s, opd, key))) + goto out; + + /* + * The core of the test case is inspired by the one in libtomcrypt: + * https://github.com/libtom/libtomcrypt/blob/6ad52252688bb34f90b5e79da4830a927e87b81f/testprof/rsa_test.c#L398 + * + * Testcase for Bleichenbacher attack + * + * (1) Create a valid signature + * (2) Check that it can be verified + * (3) Transform the package to fetch plain text (using the encrypt + * operation in GP TEE Internal API) + * (4) Forge the structure of PKCS#1-EMSA encoded data + * (4.1) Search for start and end of the padding string + * (4.2) Move the signature to the front of the padding string + * (4.3) Zero the message until the end + * (5) Transform the package back (using the decrypt operation in + * GP TEE Internal API) + * (6) The result should not be valid if the implementation is robust. + */ + + + for (i = 0; i < 9; i++) { + Do_ADBG_Log("Iteration %zu", i); + + /* 1 */ + out_size = sizeof(out); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_sign(c, &s, ops, NULL, 0, + in, sizeof(in), out, &out_size))) + goto out; + + /* 2 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_verify(c, &s, opv, NULL, 0, + in, sizeof(in), out, out_size))) + goto out; + + /* 3 */ + tmp_size = sizeof(tmp); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_encrypt(c, &s, ope, NULL, 0, + out, out_size, tmp, &tmp_size))) + goto out; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, tmp_size, <=, sizeof(tmp))) + goto out; + + /* 4.1 */ + for (n = 0; n < tmp_size - i; n++) + if (tmp[n] == 0xff) + break; + + /* Shall find at least a padding start before buffer end */ + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, n, <, tmp_size - i - 1)) + goto out; + + for (m = n + 1; m < tmp_size; m++) + if (tmp[m] != 0xff) + break; + + /* 4.2 */ + memmove(tmp + n + i, tmp + m, tmp_size - m); + + /* 4.3 */ + n = n + i + tmp_size - m; + + /* Prevent overrun when zeroing buffer end */ + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, n, <=, tmp_size)) + goto out; + + memset(tmp + n, 0, tmp_size - n); + + /* 5 */ + out_size = sizeof(out); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_decrypt(c, &s, opd, NULL, 0, + tmp, tmp_size, out, &out_size))) + goto out; + + /* 6 */ + if (!ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_SIGNATURE_INVALID, + ta_crypt_cmd_asymmetric_verify(c, &s, opv, NULL, 0, + in, sizeof(in), out, out_size))) + goto out; + } + +out: + TEEC_CloseSession(&s); +} +ADBG_CASE_DEFINE(regression, 4011, xtest_tee_test_4011, + "Test TEE Internal API Bleichenbacher attack (negative)"); + +static void xtest_tee_test_4012(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + /* Fortuna PRNG requires seed <= 32 bytes */ + uint8_t pool_input[32] = { }; + time_t t = 0; + struct tm tm_local = { }; + + t = time(NULL); + tm_local = *localtime(&t); + + memcpy((void *)pool_input, (void *)&tm_local, + sizeof(pool_input) < sizeof(tm_local) ? + sizeof(pool_input) : sizeof(tm_local)); + + + op.params[0].tmpref.buffer = pool_input; + op.params[0].tmpref.size = sizeof(pool_input); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + res = TEEC_InvokeCommand(&session, TA_CRYPT_CMD_SEED_RNG_POOL, + &op, &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND && + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, ret_orig, + TEEC_ORIGIN_TRUSTED_APP)) + Do_ADBG_Log("System PTA not available, skipping test 4012"); + else + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4012, xtest_tee_test_4012, + "Test seeding RNG entropy"); + +static void xtest_tee_test_4013(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint8_t key[32] = { }; + uint8_t extra_data[32] = { }; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + res = TEEC_InvokeCommand(&session, TA_CRYPT_CMD_DERIVE_TA_UNIQUE_KEY, + &op, &ret_orig); + if (res == TEEC_ERROR_ITEM_NOT_FOUND && + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, ret_orig, + TEEC_ORIGIN_TRUSTED_APP)) { + Do_ADBG_Log("System PTA not available, skipping test 4013"); + goto out; + } + ADBG_EXPECT_TEEC_SUCCESS(c, res); + + /* Negative test using non-secure memory */ + memset(&op, 0, sizeof(op)); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, + TEEC_NONE); + + op.params[0].tmpref.buffer = extra_data; + op.params[0].tmpref.size = sizeof(extra_data); + op.params[1].tmpref.buffer = key; + op.params[1].tmpref.size = sizeof(key); + (void)ADBG_EXPECT_TEEC_RESULT(c, + TEEC_ERROR_SECURITY, + TEEC_InvokeCommand(&session, + TA_CRYPT_CMD_DERIVE_TA_UNIQUE_KEY_SHM, + &op, + &ret_orig)); + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4013, xtest_tee_test_4013, + "Test generation of device unique TA keys"); + +static void xtest_tee_test_4014(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle keyA = TEE_HANDLE_NULL; + TEE_ObjectHandle eph_keyA = TEE_HANDLE_NULL; + TEE_ObjectHandle keyB = TEE_HANDLE_NULL; + TEE_ObjectHandle eph_keyB = TEE_HANDLE_NULL; + TEE_ObjectHandle sv_handle = TEE_HANDLE_NULL; + TEE_Attribute params[9] = { }; + size_t param_count = 0; + uint8_t out[128] = { }; + size_t out_size = 0; + uint8_t conf_A[32] = { }; + uint8_t conf_B[32] = { }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + if (!ta_crypt_cmd_is_algo_supported(c, &session, TEE_ALG_SM2_KEP, + TEE_ECC_CURVE_SM2)) { + Do_ADBG_Log("SM2 KEP not supported: skip subcase"); + goto out; + } + + Do_ADBG_BeginSubCase(c, "Initiator side"); + + /* + * Key exchange protocol running on user A's side. A is initiator. + */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + TEE_ALG_SM2_KEP, TEE_MODE_DERIVE, 512))) + goto out; + + /* Allocate and initialize keypair of user A */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_SM2_KEP_KEYPAIR, 256, &keyA))) + goto out; + + param_count = 0; + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_X, + ARRAY(gmt_003_part5_b2_public_xA)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_Y, + ARRAY(gmt_003_part5_b2_public_yA)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PRIVATE_VALUE, + ARRAY(gmt_003_part5_b2_private_A)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, keyA, + params, param_count))) + goto out; + + /* + * Allocate and set ephemeral key of user A. Note: it is a regular ECC + * key -- we don't use the *_EPHEMERAL_* attributes flags which are + * reserved for use in TEE_DeriveKey() to pass the ephermeral key of + * user B. + */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_SM2_KEP_KEYPAIR, 256, &eph_keyA))) + goto out; + + param_count = 0; + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_X, + ARRAY(gmt_003_part5_b2_eph_public_xA)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_Y, + ARRAY(gmt_003_part5_b2_eph_public_yA)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PRIVATE_VALUE, + ARRAY(gmt_003_part5_b2_eph_private_A)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, eph_keyA, + params, param_count))) + goto out; + + /* Associate user A keys with operation */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key2(c, &session, op, keyA, + eph_keyA))) + goto out; + + /* Keys have been set, free key objects */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, keyA))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, eph_keyA))) + goto out; + + /* Allocate output object */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_GENERIC_SECRET, + sizeof(gmt_003_part5_b2_shared_secret), + &sv_handle))) + goto out; + + /* Set key derivation parameters: user A role, user B information */ + + params[0].attributeID = TEE_ATTR_SM2_KEP_USER; + params[0].content.value.a = 0; /* Initiator role */ + params[0].content.value.b = 0; /* Not used */ + param_count = 1; + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_X, + ARRAY(gmt_003_part5_b2_public_xB)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_Y, + ARRAY(gmt_003_part5_b2_public_yB)); + + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X, + ARRAY(gmt_003_part5_b2_eph_public_xB)); + + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y, + ARRAY(gmt_003_part5_b2_eph_public_yB)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_SM2_ID_INITIATOR, + ARRAY(gmt_003_part5_b2_id_A)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_SM2_ID_RESPONDER, + ARRAY(gmt_003_part5_b2_id_B)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_SM2_KEP_CONFIRMATION_IN, + ARRAY(gmt_003_part5_b2_conf_B)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_SM2_KEP_CONFIRMATION_OUT, + ARRAY(conf_A)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, &session, op, sv_handle, params, + param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, &session, sv_handle, + TEE_ATTR_SECRET_VALUE, out, &out_size))) + goto out; + + /* Check derived key */ + if (!ADBG_EXPECT_BUFFER(c, gmt_003_part5_b2_shared_secret, + sizeof(gmt_003_part5_b2_shared_secret), out, + out_size)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, sv_handle))) + goto out; + + Do_ADBG_EndSubCase(c, "Initiator side"); + + Do_ADBG_BeginSubCase(c, "Responder side"); + + /* + * Key derivation on user B's side + */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + TEE_ALG_SM2_KEP, TEE_MODE_DERIVE, 512))) + goto out; + + /* Allocate and initialize keypair of user B */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_SM2_KEP_KEYPAIR, 256, &keyB))) + goto out; + + param_count = 0; + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_X, + ARRAY(gmt_003_part5_b2_public_xB)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_Y, + ARRAY(gmt_003_part5_b2_public_yB)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PRIVATE_VALUE, + ARRAY(gmt_003_part5_b2_private_B)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, keyB, + params, param_count))) + goto out; + + /* Allocate and set ephemeral key of user B */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_SM2_KEP_KEYPAIR, 256, &eph_keyB))) + goto out; + + param_count = 0; + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_X, + ARRAY(gmt_003_part5_b2_eph_public_xB)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_Y, + ARRAY(gmt_003_part5_b2_eph_public_yB)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PRIVATE_VALUE, + ARRAY(gmt_003_part5_b2_eph_private_B)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, eph_keyB, + params, param_count))) + goto out; + + /* Associate user B keys with operation */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key2(c, &session, op, keyB, + eph_keyB))) + goto out; + + /* Keys have been set, free key objects */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, keyB))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, eph_keyB))) + goto out; + + /* Allocate output object */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_GENERIC_SECRET, + sizeof(gmt_003_part5_b2_shared_secret), + &sv_handle))) + goto out; + + /* Set key derivation parameters: user B role, user A information */ + + params[0].attributeID = TEE_ATTR_SM2_KEP_USER; + params[0].content.value.a = 1; /* Responder role */ + params[0].content.value.b = 0; /* Not used */ + param_count = 1; + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_X, + ARRAY(gmt_003_part5_b2_public_xA)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_ECC_PUBLIC_VALUE_Y, + ARRAY(gmt_003_part5_b2_public_yA)); + + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X, + ARRAY(gmt_003_part5_b2_eph_public_xA)); + + xtest_add_attr(¶m_count, params, + TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y, + ARRAY(gmt_003_part5_b2_eph_public_yA)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_SM2_ID_INITIATOR, + ARRAY(gmt_003_part5_b2_id_A)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_SM2_ID_RESPONDER, + ARRAY(gmt_003_part5_b2_id_B)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_SM2_KEP_CONFIRMATION_IN, + ARRAY(gmt_003_part5_b2_conf_A)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_SM2_KEP_CONFIRMATION_OUT, + ARRAY(conf_B)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, &session, op, sv_handle, params, + param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, &session, sv_handle, + TEE_ATTR_SECRET_VALUE, out, &out_size))) + goto out; + + /* Check derived key */ + if (!ADBG_EXPECT_BUFFER(c, gmt_003_part5_b2_shared_secret, + sizeof(gmt_003_part5_b2_shared_secret), out, + out_size)) + goto out; + + Do_ADBG_EndSubCase(c, "Responder side"); + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4014, xtest_tee_test_4014, + "Test SM2 KEP (key derivation)"); + +static void xtest_tee_test_4015(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle key_alice = TEE_HANDLE_NULL; + TEE_ObjectHandle key_bob = TEE_HANDLE_NULL; + TEE_ObjectHandle sv_handle = TEE_HANDLE_NULL; + TEE_Attribute params[2] = { }; + size_t param_count = 0; + uint8_t out[32] = { }; + size_t out_size = 0; + char case_str[40] = "Alice side computes shared secret"; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "%s", case_str); + + if (!ta_crypt_cmd_is_algo_supported(c, &session, TEE_ALG_X25519, + TEE_ECC_CURVE_25519)) { + Do_ADBG_Log("X25519 not supported: skip subcase"); + goto out; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + TEE_ALG_X25519, TEE_MODE_DERIVE, 256))) + goto out; + + /* Allocate and initialize keypair of Alice */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_X25519_KEYPAIR, 256, &key_alice))) + goto out; + + param_count = 0; + + xtest_add_attr(¶m_count, params, TEE_ATTR_X25519_PUBLIC_VALUE, + ARRAY(x25519_alice_public)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_X25519_PRIVATE_VALUE, + ARRAY(x25519_alice_private)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, + key_alice, params, param_count))) + goto out; + + /* Associate Alices's keys with operation */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + key_alice))) + goto out; + + /* Keys have been set, free key objects */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + key_alice))) + goto out; + + /* Allocate shared secret output object */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_GENERIC_SECRET, + sizeof(x25519_shared_secret), &sv_handle))) + goto out; + + /* Reset params */ + param_count = 0; + + /* Set Bob's public key for Alice side */ + xtest_add_attr(¶m_count, params, TEE_ATTR_X25519_PUBLIC_VALUE, + ARRAY(x25519_bob_public)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, &session, op, sv_handle, + params, param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, &session, + sv_handle, TEE_ATTR_SECRET_VALUE, out, + &out_size))) + goto out; + + /* Check derived key */ + if (!ADBG_EXPECT_BUFFER(c, x25519_shared_secret, + sizeof(x25519_shared_secret), out, + out_size)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + sv_handle))) + goto out; + + Do_ADBG_EndSubCase(c, "%s", case_str); + + strncpy(case_str, "Bob side computes shared secret", + sizeof(case_str) - 1); + + Do_ADBG_BeginSubCase(c, "%s", case_str); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + TEE_ALG_X25519, TEE_MODE_DERIVE, 256))) + goto out; + + /* Allocate and initialize keypair of Bob */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_X25519_KEYPAIR, 256, &key_bob))) + goto out; + + /* Reset params */ + param_count = 0; + + xtest_add_attr(¶m_count, params, TEE_ATTR_X25519_PUBLIC_VALUE, + ARRAY(x25519_bob_public)); + + xtest_add_attr(¶m_count, params, TEE_ATTR_X25519_PRIVATE_VALUE, + ARRAY(x25519_bob_private)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, &session, + key_bob, params, param_count))) + goto out; + + /* Associate Bob's keys with operation */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, &session, op, + key_bob))) + goto out; + + /* Keys have been set, free key objects */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + key_bob))) + goto out; + + /* Allocate shared secret output object */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, &session, + TEE_TYPE_GENERIC_SECRET, + sizeof(x25519_shared_secret), &sv_handle))) + goto out; + + /* Reset params */ + param_count = 0; + + /* Set Alice's public key for Bob side */ + xtest_add_attr(¶m_count, params, TEE_ATTR_X25519_PUBLIC_VALUE, + ARRAY(x25519_alice_public)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, &session, op, sv_handle, + params, param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, &session, + sv_handle, TEE_ATTR_SECRET_VALUE, out, + &out_size))) + goto out; + + /* Check derived key */ + if (!ADBG_EXPECT_BUFFER(c, x25519_shared_secret, + sizeof(x25519_shared_secret), out, + out_size)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, &session, + sv_handle))) + goto out; + +out: + Do_ADBG_EndSubCase(c, "%s", case_str); + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4015, xtest_tee_test_4015, + "Test TEE Internal API Derive key X25519"); + +static void xtest_tee_test_4016_ed25519(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle key_handle = TEE_HANDLE_NULL; + TEE_Attribute key_attrs[2] = { }; + size_t num_key_attrs = 0; + TEE_Attribute attrs[2] = { }; + size_t num_attrs = 0; + uint8_t out[64] = { }; + size_t out_size = sizeof(out); + size_t n = 0; + uint32_t ret_orig = 0; + size_t max_key_size = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + if (!ta_crypt_cmd_is_algo_supported(c, &session, TEE_ALG_ED25519, + TEE_ECC_CURVE_25519)) { + Do_ADBG_Log("ED25519 not supported: skip subcase"); + goto out; + } + + for (n = 0; n < ARRAY_SIZE(xtest_ac_eddsa_cases); n++) { + const struct xtest_ac_case *tv = xtest_ac_eddsa_cases + n; + + if (tv->algo != TEE_ALG_ED25519) + continue; + + num_attrs = 0; + num_key_attrs = 0; + max_key_size = tv->params.eddsa.private_len * 8; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, &session, &op, + TEE_ALG_ED25519, tv->mode, max_key_size))) + goto out; + + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_ED25519_PUBLIC_VALUE, + tv->params.eddsa.public, + tv->params.eddsa.public_len); + + if (tv->params.eddsa.flag == 1) + xtest_add_attr_value(&num_attrs, attrs, + TEE_ATTR_EDDSA_PREHASH, 1, 0); + + if (tv->params.eddsa.context_len > 0) + xtest_add_attr(&num_attrs, attrs, TEE_ATTR_EDDSA_CTX, + tv->params.eddsa.context, + tv->params.eddsa.context_len); + + switch (tv->mode) { + case TEE_MODE_SIGN: + xtest_add_attr(&num_key_attrs, key_attrs, + TEE_ATTR_ED25519_PRIVATE_VALUE, + tv->params.eddsa.private, + tv->params.eddsa.private_len); + + if (!ADBG_EXPECT_TRUE(c, + create_key(c, &session, max_key_size, + TEE_TYPE_ED25519_KEYPAIR, + key_attrs, num_key_attrs, + &key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, + &session, op, key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_sign(c, + &session, op, + attrs, num_attrs, tv->ptx, + tv->ptx_len, out, &out_size))) + goto out; + + ADBG_EXPECT_BUFFER(c, tv->ctx, tv->ctx_len, out, out_size); + + break; + + case TEE_MODE_VERIFY: + if (!ADBG_EXPECT_TRUE(c, + create_key(c, &session, max_key_size, + TEE_TYPE_ED25519_PUBLIC_KEY, + key_attrs, num_key_attrs, + &key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, + &session, op, key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_asymmetric_verify(c, &session, op, + attrs, num_attrs, + tv->ptx, + tv->ptx_len, + tv->ctx, + tv->ctx_len))) + goto out; + break; + + default: + break; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, &session, op))) + goto out; + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4016, xtest_tee_test_4016_ed25519, + "Test TEE Internal API ED25519 sign/verify"); diff --git a/optee/optee_test/host/xtest/regression_4000_data.h b/optee/optee_test/host/xtest/regression_4000_data.h new file mode 100644 index 0000000..c1e9b1d --- /dev/null +++ b/optee/optee_test/host/xtest/regression_4000_data.h @@ -0,0 +1,8929 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2021, SumUp Services GmbH + */ + +#ifndef XTEST_4000_DATA_H +#define XTEST_4000_DATA_H +#include +#include +#include + +/* + * XTS-AES Test data from: + * http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + */ + +/* + * XTS-AES applied for a data unit of 32 bytes, 32 bytes key material. + */ + +/* Vector 1 */ +static const uint8_t ciph_data_aes_xts_vect1_key1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const uint8_t ciph_data_aes_xts_vect1_key2[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const uint8_t ciph_data_aes_xts_vect1_iv[16] = { + 0x0 +}; +static const uint8_t ciph_data_aes_xts_vect1_ptx[] = { + 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, +}; +/* TWK 66e94bd4ef8a2c3b884cfa59ca342b2eccd297a8df1559761099f4b39469565c */ +static const uint8_t ciph_data_aes_xts_vect1_ctx[] = { + 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, +}; + +/* Vector 2 */ +static const uint8_t ciph_data_aes_xts_vect2_key1[] = { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, +}; +static const uint8_t ciph_data_aes_xts_vect2_key2[] = { + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, +}; +static const uint8_t ciph_data_aes_xts_vect2_iv[16] = { + 0x33, 0x33, 0x33, 0x33, 0x33 +}; +static const uint8_t ciph_data_aes_xts_vect2_ptx[] = { + 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, +}; +/* TWK 3f803bcd0d7fd2b37558419f59d5cda6f900779a1bfea467ebb0823eb3aa9b4d */ +static const uint8_t ciph_data_aes_xts_vect2_ctx[] = { + 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, +}; + +/* Vector 3 */ +static const uint8_t ciph_data_aes_xts_vect3_key1[] = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, +}; +static const uint8_t ciph_data_aes_xts_vect3_key2[] = { + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, +}; +static const uint8_t ciph_data_aes_xts_vect3_iv[16] = { + 0x33, 0x33, 0x33, 0x33, 0x33 +}; +static const uint8_t ciph_data_aes_xts_vect3_ptx[] = { + 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, +}; +/* TWK 3f803bcd0d7fd2b37558419f59d5cda6f900779a1bfea467ebb0823eb3aa9b4d */ +static const uint8_t ciph_data_aes_xts_vect3_ctx[] = { + 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89, +}; + +/* + * XTS-AES-128 applied for a data unit of 512 bytes + */ + +/* Vector 4 */ +static const uint8_t ciph_data_aes_xts_vect4_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, +}; +static const uint8_t ciph_data_aes_xts_vect4_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, +}; +static const uint8_t ciph_data_aes_xts_vect4_iv[16] = { + 0x00 +}; +static const uint8_t ciph_data_aes_xts_vect4_ptx[] = { + 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, +}; +static const uint8_t ciph_data_aes_xts_vect4_ctx[] = { + 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, +}; + +/* Vector 5 */ +static const uint8_t ciph_data_aes_xts_vect5_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, +}; +static const uint8_t ciph_data_aes_xts_vect5_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, +}; +static const uint8_t ciph_data_aes_xts_vect5_iv[16] = { + 0x01 +}; +static const uint8_t ciph_data_aes_xts_vect5_ptx[] = { + 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, +}; +static const uint8_t ciph_data_aes_xts_vect5_ctx[] = { + 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe, + 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f, + 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60, + 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5, + + 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d, + 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce, + 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b, + 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb, + + 0x1c, 0x2f, 0xd3, 0x0f, 0x2f, 0x7f, 0x30, 0x49, + 0x2a, 0x61, 0xa5, 0x32, 0xa7, 0x9f, 0x51, 0xd3, + 0x6f, 0x5e, 0x31, 0xa7, 0xc9, 0xa1, 0x2c, 0x28, + 0x60, 0x82, 0xff, 0x7d, 0x23, 0x94, 0xd1, 0x8f, + + 0x78, 0x3e, 0x1a, 0x8e, 0x72, 0xc7, 0x22, 0xca, + 0xaa, 0xa5, 0x2d, 0x8f, 0x06, 0x56, 0x57, 0xd2, + 0x63, 0x1f, 0xd2, 0x5b, 0xfd, 0x8e, 0x5b, 0xaa, + 0xd6, 0xe5, 0x27, 0xd7, 0x63, 0x51, 0x75, 0x01, + + 0xc6, 0x8c, 0x5e, 0xdc, 0x3c, 0xdd, 0x55, 0x43, + 0x5c, 0x53, 0x2d, 0x71, 0x25, 0xc8, 0x61, 0x4d, + 0xee, 0xd9, 0xad, 0xaa, 0x3a, 0xca, 0xde, 0x58, + 0x88, 0xb8, 0x7b, 0xef, 0x64, 0x1c, 0x4c, 0x99, + + 0x4c, 0x80, 0x91, 0xb5, 0xbc, 0xd3, 0x87, 0xf3, + 0x96, 0x3f, 0xb5, 0xbc, 0x37, 0xaa, 0x92, 0x2f, + 0xbf, 0xe3, 0xdf, 0x4e, 0x5b, 0x91, 0x5e, 0x6e, + 0xb5, 0x14, 0x71, 0x7b, 0xdd, 0x2a, 0x74, 0x07, + + 0x9a, 0x50, 0x73, 0xf5, 0xc4, 0xbf, 0xd4, 0x6a, + 0xdf, 0x7d, 0x28, 0x2e, 0x7a, 0x39, 0x3a, 0x52, + 0x57, 0x9d, 0x11, 0xa0, 0x28, 0xda, 0x4d, 0x9c, + 0xd9, 0xc7, 0x71, 0x24, 0xf9, 0x64, 0x8e, 0xe3, + + 0x83, 0xb1, 0xac, 0x76, 0x39, 0x30, 0xe7, 0x16, + 0x2a, 0x8d, 0x37, 0xf3, 0x50, 0xb2, 0xf7, 0x4b, + 0x84, 0x72, 0xcf, 0x09, 0x90, 0x20, 0x63, 0xc6, + 0xb3, 0x2e, 0x8c, 0x2d, 0x92, 0x90, 0xce, 0xfb, + + 0xd7, 0x34, 0x6d, 0x1c, 0x77, 0x9a, 0x0d, 0xf5, + 0x0e, 0xdc, 0xde, 0x45, 0x31, 0xda, 0x07, 0xb0, + 0x99, 0xc6, 0x38, 0xe8, 0x3a, 0x75, 0x59, 0x44, + 0xdf, 0x2a, 0xef, 0x1a, 0xa3, 0x17, 0x52, 0xfd, + + 0x32, 0x3d, 0xcb, 0x71, 0x0f, 0xb4, 0xbf, 0xbb, + 0x9d, 0x22, 0xb9, 0x25, 0xbc, 0x35, 0x77, 0xe1, + 0xb8, 0x94, 0x9e, 0x72, 0x9a, 0x90, 0xbb, 0xaf, + 0xea, 0xcf, 0x7f, 0x78, 0x79, 0xe7, 0xb1, 0x14, + + 0x7e, 0x28, 0xba, 0x0b, 0xae, 0x94, 0x0d, 0xb7, + 0x95, 0xa6, 0x1b, 0x15, 0xec, 0xf4, 0xdf, 0x8d, + 0xb0, 0x7b, 0x82, 0x4b, 0xb0, 0x62, 0x80, 0x2c, + 0xc9, 0x8a, 0x95, 0x45, 0xbb, 0x2a, 0xae, 0xed, + + 0x77, 0xcb, 0x3f, 0xc6, 0xdb, 0x15, 0xdc, 0xd7, + 0xd8, 0x0d, 0x7d, 0x5b, 0xc4, 0x06, 0xc4, 0x97, + 0x0a, 0x34, 0x78, 0xad, 0xa8, 0x89, 0x9b, 0x32, + 0x91, 0x98, 0xeb, 0x61, 0xc1, 0x93, 0xfb, 0x62, + + 0x75, 0xaa, 0x8c, 0xa3, 0x40, 0x34, 0x4a, 0x75, + 0xa8, 0x62, 0xae, 0xbe, 0x92, 0xee, 0xe1, 0xce, + 0x03, 0x2f, 0xd9, 0x50, 0xb4, 0x7d, 0x77, 0x04, + 0xa3, 0x87, 0x69, 0x23, 0xb4, 0xad, 0x62, 0x84, + + 0x4b, 0xf4, 0xa0, 0x9c, 0x4d, 0xbe, 0x8b, 0x43, + 0x97, 0x18, 0x4b, 0x74, 0x71, 0x36, 0x0c, 0x95, + 0x64, 0x88, 0x0a, 0xed, 0xdd, 0xb9, 0xba, 0xa4, + 0xaf, 0x2e, 0x75, 0x39, 0x4b, 0x08, 0xcd, 0x32, + + 0xff, 0x47, 0x9c, 0x57, 0xa0, 0x7d, 0x3e, 0xab, + 0x5d, 0x54, 0xde, 0x5f, 0x97, 0x38, 0xb8, 0xd2, + 0x7f, 0x27, 0xa9, 0xf0, 0xab, 0x11, 0x79, 0x9d, + 0x7b, 0x7f, 0xfe, 0xfb, 0x27, 0x04, 0xc9, 0x5c, + + 0x6a, 0xd1, 0x2c, 0x39, 0xf1, 0xe8, 0x67, 0xa4, + 0xb7, 0xb1, 0xd7, 0x81, 0x8a, 0x4b, 0x75, 0x3d, + 0xfd, 0x2a, 0x89, 0xcc, 0xb4, 0x5e, 0x00, 0x1a, + 0x03, 0xa8, 0x67, 0xb1, 0x87, 0xf2, 0x25, 0xdd, +}; + +/* Vector 6 */ +static const uint8_t ciph_data_aes_xts_vect6_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, +}; +static const uint8_t ciph_data_aes_xts_vect6_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, +}; +static const uint8_t ciph_data_aes_xts_vect6_iv[16] = { + 0x02 +}; +static const uint8_t ciph_data_aes_xts_vect6_ptx[] = { + 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe, + 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f, + 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60, + 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5, + + 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d, + 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce, + 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b, + 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb, + + 0x1c, 0x2f, 0xd3, 0x0f, 0x2f, 0x7f, 0x30, 0x49, + 0x2a, 0x61, 0xa5, 0x32, 0xa7, 0x9f, 0x51, 0xd3, + 0x6f, 0x5e, 0x31, 0xa7, 0xc9, 0xa1, 0x2c, 0x28, + 0x60, 0x82, 0xff, 0x7d, 0x23, 0x94, 0xd1, 0x8f, + + 0x78, 0x3e, 0x1a, 0x8e, 0x72, 0xc7, 0x22, 0xca, + 0xaa, 0xa5, 0x2d, 0x8f, 0x06, 0x56, 0x57, 0xd2, + 0x63, 0x1f, 0xd2, 0x5b, 0xfd, 0x8e, 0x5b, 0xaa, + 0xd6, 0xe5, 0x27, 0xd7, 0x63, 0x51, 0x75, 0x01, + + 0xc6, 0x8c, 0x5e, 0xdc, 0x3c, 0xdd, 0x55, 0x43, + 0x5c, 0x53, 0x2d, 0x71, 0x25, 0xc8, 0x61, 0x4d, + 0xee, 0xd9, 0xad, 0xaa, 0x3a, 0xca, 0xde, 0x58, + 0x88, 0xb8, 0x7b, 0xef, 0x64, 0x1c, 0x4c, 0x99, + + 0x4c, 0x80, 0x91, 0xb5, 0xbc, 0xd3, 0x87, 0xf3, + 0x96, 0x3f, 0xb5, 0xbc, 0x37, 0xaa, 0x92, 0x2f, + 0xbf, 0xe3, 0xdf, 0x4e, 0x5b, 0x91, 0x5e, 0x6e, + 0xb5, 0x14, 0x71, 0x7b, 0xdd, 0x2a, 0x74, 0x07, + + 0x9a, 0x50, 0x73, 0xf5, 0xc4, 0xbf, 0xd4, 0x6a, + 0xdf, 0x7d, 0x28, 0x2e, 0x7a, 0x39, 0x3a, 0x52, + 0x57, 0x9d, 0x11, 0xa0, 0x28, 0xda, 0x4d, 0x9c, + 0xd9, 0xc7, 0x71, 0x24, 0xf9, 0x64, 0x8e, 0xe3, + + 0x83, 0xb1, 0xac, 0x76, 0x39, 0x30, 0xe7, 0x16, + 0x2a, 0x8d, 0x37, 0xf3, 0x50, 0xb2, 0xf7, 0x4b, + 0x84, 0x72, 0xcf, 0x09, 0x90, 0x20, 0x63, 0xc6, + 0xb3, 0x2e, 0x8c, 0x2d, 0x92, 0x90, 0xce, 0xfb, + + 0xd7, 0x34, 0x6d, 0x1c, 0x77, 0x9a, 0x0d, 0xf5, + 0x0e, 0xdc, 0xde, 0x45, 0x31, 0xda, 0x07, 0xb0, + 0x99, 0xc6, 0x38, 0xe8, 0x3a, 0x75, 0x59, 0x44, + 0xdf, 0x2a, 0xef, 0x1a, 0xa3, 0x17, 0x52, 0xfd, + + 0x32, 0x3d, 0xcb, 0x71, 0x0f, 0xb4, 0xbf, 0xbb, + 0x9d, 0x22, 0xb9, 0x25, 0xbc, 0x35, 0x77, 0xe1, + 0xb8, 0x94, 0x9e, 0x72, 0x9a, 0x90, 0xbb, 0xaf, + 0xea, 0xcf, 0x7f, 0x78, 0x79, 0xe7, 0xb1, 0x14, + + 0x7e, 0x28, 0xba, 0x0b, 0xae, 0x94, 0x0d, 0xb7, + 0x95, 0xa6, 0x1b, 0x15, 0xec, 0xf4, 0xdf, 0x8d, + 0xb0, 0x7b, 0x82, 0x4b, 0xb0, 0x62, 0x80, 0x2c, + 0xc9, 0x8a, 0x95, 0x45, 0xbb, 0x2a, 0xae, 0xed, + + 0x77, 0xcb, 0x3f, 0xc6, 0xdb, 0x15, 0xdc, 0xd7, + 0xd8, 0x0d, 0x7d, 0x5b, 0xc4, 0x06, 0xc4, 0x97, + 0x0a, 0x34, 0x78, 0xad, 0xa8, 0x89, 0x9b, 0x32, + 0x91, 0x98, 0xeb, 0x61, 0xc1, 0x93, 0xfb, 0x62, + + 0x75, 0xaa, 0x8c, 0xa3, 0x40, 0x34, 0x4a, 0x75, + 0xa8, 0x62, 0xae, 0xbe, 0x92, 0xee, 0xe1, 0xce, + 0x03, 0x2f, 0xd9, 0x50, 0xb4, 0x7d, 0x77, 0x04, + 0xa3, 0x87, 0x69, 0x23, 0xb4, 0xad, 0x62, 0x84, + + 0x4b, 0xf4, 0xa0, 0x9c, 0x4d, 0xbe, 0x8b, 0x43, + 0x97, 0x18, 0x4b, 0x74, 0x71, 0x36, 0x0c, 0x95, + 0x64, 0x88, 0x0a, 0xed, 0xdd, 0xb9, 0xba, 0xa4, + 0xaf, 0x2e, 0x75, 0x39, 0x4b, 0x08, 0xcd, 0x32, + + 0xff, 0x47, 0x9c, 0x57, 0xa0, 0x7d, 0x3e, 0xab, + 0x5d, 0x54, 0xde, 0x5f, 0x97, 0x38, 0xb8, 0xd2, + 0x7f, 0x27, 0xa9, 0xf0, 0xab, 0x11, 0x79, 0x9d, + 0x7b, 0x7f, 0xfe, 0xfb, 0x27, 0x04, 0xc9, 0x5c, + + 0x6a, 0xd1, 0x2c, 0x39, 0xf1, 0xe8, 0x67, 0xa4, + 0xb7, 0xb1, 0xd7, 0x81, 0x8a, 0x4b, 0x75, 0x3d, + 0xfd, 0x2a, 0x89, 0xcc, 0xb4, 0x5e, 0x00, 0x1a, + 0x03, 0xa8, 0x67, 0xb1, 0x87, 0xf2, 0x25, 0xdd, +}; +static const uint8_t ciph_data_aes_xts_vect6_ctx[] = { + 0xfa, 0x76, 0x2a, 0x36, 0x80, 0xb7, 0x60, 0x07, + 0x92, 0x8e, 0xd4, 0xa4, 0xf4, 0x9a, 0x94, 0x56, + 0x03, 0x1b, 0x70, 0x47, 0x82, 0xe6, 0x5e, 0x16, + 0xce, 0xcb, 0x54, 0xed, 0x7d, 0x01, 0x7b, 0x5e, + + 0x18, 0xab, 0xd6, 0x7b, 0x33, 0x8e, 0x81, 0x07, + 0x8f, 0x21, 0xed, 0xb7, 0x86, 0x8d, 0x90, 0x1e, + 0xbe, 0x9c, 0x73, 0x1a, 0x7c, 0x18, 0xb5, 0xe6, + 0xde, 0xc1, 0xd6, 0xa7, 0x2e, 0x07, 0x8a, 0xc9, + + 0xa4, 0x26, 0x2f, 0x86, 0x0b, 0xee, 0xfa, 0x14, + 0xf4, 0xe8, 0x21, 0x01, 0x82, 0x72, 0xe4, 0x11, + 0xa9, 0x51, 0x50, 0x2b, 0x6e, 0x79, 0x06, 0x6e, + 0x84, 0x25, 0x2c, 0x33, 0x46, 0xf3, 0xaa, 0x62, + + 0x34, 0x43, 0x51, 0xa2, 0x91, 0xd4, 0xbe, 0xdc, + 0x7a, 0x07, 0x61, 0x8b, 0xde, 0xa2, 0xaf, 0x63, + 0x14, 0x5c, 0xc7, 0xa4, 0xb8, 0xd4, 0x07, 0x06, + 0x91, 0xae, 0x89, 0x0c, 0xd6, 0x57, 0x33, 0xe7, + + 0x94, 0x6e, 0x90, 0x21, 0xa1, 0xdf, 0xfc, 0x4c, + 0x59, 0xf1, 0x59, 0x42, 0x5e, 0xe6, 0xd5, 0x0c, + 0xa9, 0xb1, 0x35, 0xfa, 0x61, 0x62, 0xce, 0xa1, + 0x8a, 0x93, 0x98, 0x38, 0xdc, 0x00, 0x0f, 0xb3, + + 0x86, 0xfa, 0xd0, 0x86, 0xac, 0xce, 0x5a, 0xc0, + 0x7c, 0xb2, 0xec, 0xe7, 0xfd, 0x58, 0x0b, 0x00, + 0xcf, 0xa5, 0xe9, 0x85, 0x89, 0x63, 0x1d, 0xc2, + 0x5e, 0x8e, 0x2a, 0x3d, 0xaf, 0x2f, 0xfd, 0xec, + + 0x26, 0x53, 0x16, 0x59, 0x91, 0x2c, 0x9d, 0x8f, + 0x7a, 0x15, 0xe5, 0x86, 0x5e, 0xa8, 0xfb, 0x58, + 0x16, 0xd6, 0x20, 0x70, 0x52, 0xbd, 0x71, 0x28, + 0xcd, 0x74, 0x3c, 0x12, 0xc8, 0x11, 0x87, 0x91, + + 0xa4, 0x73, 0x68, 0x11, 0x93, 0x5e, 0xb9, 0x82, + 0xa5, 0x32, 0x34, 0x9e, 0x31, 0xdd, 0x40, 0x1e, + 0x0b, 0x66, 0x0a, 0x56, 0x8c, 0xb1, 0xa4, 0x71, + 0x1f, 0x55, 0x2f, 0x55, 0xde, 0xd5, 0x9f, 0x1f, + + 0x15, 0xbf, 0x71, 0x96, 0xb3, 0xca, 0x12, 0xa9, + 0x1e, 0x48, 0x8e, 0xf5, 0x9d, 0x64, 0xf3, 0xa0, + 0x2b, 0xf4, 0x52, 0x39, 0x49, 0x9a, 0xc6, 0x17, + 0x6a, 0xe3, 0x21, 0xc4, 0xa2, 0x11, 0xec, 0x54, + + 0x53, 0x65, 0x97, 0x1c, 0x5d, 0x3f, 0x4f, 0x09, + 0xd4, 0xeb, 0x13, 0x9b, 0xfd, 0xf2, 0x07, 0x3d, + 0x33, 0x18, 0x0b, 0x21, 0x00, 0x2b, 0x65, 0xcc, + 0x98, 0x65, 0xe7, 0x6c, 0xb2, 0x4c, 0xd9, 0x2c, + + 0x87, 0x4c, 0x24, 0xc1, 0x83, 0x50, 0x39, 0x9a, + 0x93, 0x6a, 0xb3, 0x63, 0x70, 0x79, 0x29, 0x5d, + 0x76, 0xc4, 0x17, 0x77, 0x6b, 0x94, 0xef, 0xce, + 0x3a, 0x0e, 0xf7, 0x20, 0x6b, 0x15, 0x11, 0x05, + + 0x19, 0x65, 0x5c, 0x95, 0x6c, 0xbd, 0x8b, 0x24, + 0x89, 0x40, 0x5e, 0xe2, 0xb0, 0x9a, 0x6b, 0x6e, + 0xeb, 0xe0, 0xc5, 0x37, 0x90, 0xa1, 0x2a, 0x89, + 0x98, 0x37, 0x8b, 0x33, 0xa5, 0xb7, 0x11, 0x59, + + 0x62, 0x5f, 0x4b, 0xa4, 0x9d, 0x2a, 0x2f, 0xdb, + 0xa5, 0x9f, 0xbf, 0x08, 0x97, 0xbc, 0x7a, 0xab, + 0xd8, 0xd7, 0x07, 0xdc, 0x14, 0x0a, 0x80, 0xf0, + 0xf3, 0x09, 0xf8, 0x35, 0xd3, 0xda, 0x54, 0xab, + + 0x58, 0x4e, 0x50, 0x1d, 0xfa, 0x0e, 0xe9, 0x77, + 0xfe, 0xc5, 0x43, 0xf7, 0x41, 0x86, 0xa8, 0x02, + 0xb9, 0xa3, 0x7a, 0xdb, 0x3e, 0x82, 0x91, 0xec, + 0xa0, 0x4d, 0x66, 0x52, 0x0d, 0x22, 0x9e, 0x60, + + 0x40, 0x1e, 0x72, 0x82, 0xbe, 0xf4, 0x86, 0xae, + 0x05, 0x9a, 0xa7, 0x06, 0x96, 0xe0, 0xe3, 0x05, + 0xd7, 0x77, 0x14, 0x0a, 0x7a, 0x88, 0x3e, 0xcd, + 0xcb, 0x69, 0xb9, 0xff, 0x93, 0x8e, 0x8a, 0x42, + + 0x31, 0x86, 0x4c, 0x69, 0xca, 0x2c, 0x20, 0x43, + 0xbe, 0xd0, 0x07, 0xff, 0x3e, 0x60, 0x5e, 0x01, + 0x4b, 0xcf, 0x51, 0x81, 0x38, 0xdc, 0x3a, 0x25, + 0xc5, 0xe2, 0x36, 0x17, 0x1a, 0x2d, 0x01, 0xd6, +}; + +/* Vector 7 */ +static const uint8_t ciph_data_aes_xts_vect7_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, +}; +static const uint8_t ciph_data_aes_xts_vect7_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, +}; +static const uint8_t ciph_data_aes_xts_vect7_iv[16] = { + 0xfd +}; +static const uint8_t ciph_data_aes_xts_vect7_ptx[] = { + 0x8e, 0x41, 0xb7, 0x8c, 0x39, 0x0b, 0x5a, 0xf9, + 0xd7, 0x58, 0xbb, 0x21, 0x4a, 0x67, 0xe9, 0xf6, + 0xbf, 0x77, 0x27, 0xb0, 0x9a, 0xc6, 0x12, 0x40, + 0x84, 0xc3, 0x76, 0x11, 0x39, 0x8f, 0xa4, 0x5d, + + 0xaa, 0xd9, 0x48, 0x68, 0x60, 0x0e, 0xd3, 0x91, + 0xfb, 0x1a, 0xcd, 0x48, 0x57, 0xa9, 0x5b, 0x46, + 0x6e, 0x62, 0xef, 0x9f, 0x4b, 0x37, 0x72, 0x44, + 0xd1, 0xc1, 0x52, 0xe7, 0xb3, 0x0d, 0x73, 0x1a, + + 0xad, 0x30, 0xc7, 0x16, 0xd2, 0x14, 0xb7, 0x07, + 0xae, 0xd9, 0x9e, 0xb5, 0xb5, 0xe5, 0x80, 0xb3, + 0xe8, 0x87, 0xcf, 0x74, 0x97, 0x46, 0x56, 0x51, + 0xd4, 0xb6, 0x0e, 0x60, 0x42, 0x05, 0x1d, 0xa3, + + 0x69, 0x3c, 0x3b, 0x78, 0xc1, 0x44, 0x89, 0x54, + 0x3b, 0xe8, 0xb6, 0xad, 0x0b, 0xa6, 0x29, 0x56, + 0x5b, 0xba, 0x20, 0x23, 0x13, 0xba, 0x7b, 0x0d, + 0x0c, 0x94, 0xa3, 0x25, 0x2b, 0x67, 0x6f, 0x46, + + 0xcc, 0x02, 0xce, 0x0f, 0x8a, 0x7d, 0x34, 0xc0, + 0xed, 0x22, 0x91, 0x29, 0x67, 0x3c, 0x1f, 0x61, + 0xae, 0xd5, 0x79, 0xd0, 0x8a, 0x92, 0x03, 0xa2, + 0x5a, 0xac, 0x3a, 0x77, 0xe9, 0xdb, 0x60, 0x26, + + 0x79, 0x96, 0xdb, 0x38, 0xdf, 0x63, 0x73, 0x56, + 0xd9, 0xdc, 0xd1, 0x63, 0x2e, 0x36, 0x99, 0x39, + 0xf2, 0xa2, 0x9d, 0x89, 0x34, 0x5c, 0x66, 0xe0, + 0x50, 0x66, 0xf1, 0xa3, 0x67, 0x7a, 0xef, 0x18, + + 0xde, 0xa4, 0x11, 0x3f, 0xae, 0xb6, 0x29, 0xe4, + 0x67, 0x21, 0xa6, 0x6d, 0x0a, 0x7e, 0x78, 0x5d, + 0x3e, 0x29, 0xaf, 0x25, 0x94, 0xeb, 0x67, 0xdf, + 0xa9, 0x82, 0xaf, 0xfe, 0x0a, 0xac, 0x05, 0x8f, + + 0x6e, 0x15, 0x86, 0x42, 0x69, 0xb1, 0x35, 0x41, + 0x82, 0x61, 0xfc, 0x3a, 0xfb, 0x08, 0x94, 0x72, + 0xcf, 0x68, 0xc4, 0x5d, 0xd7, 0xf2, 0x31, 0xc6, + 0x24, 0x9b, 0xa0, 0x25, 0x5e, 0x1e, 0x03, 0x38, + + 0x33, 0xfc, 0x4d, 0x00, 0xa3, 0xfe, 0x02, 0x13, + 0x2d, 0x7b, 0xc3, 0x87, 0x36, 0x14, 0xb8, 0xae, + 0xe3, 0x42, 0x73, 0x58, 0x1e, 0xa0, 0x32, 0x5c, + 0x81, 0xf0, 0x27, 0x0a, 0xff, 0xa1, 0x36, 0x41, + + 0xd0, 0x52, 0xd3, 0x6f, 0x07, 0x57, 0xd4, 0x84, + 0x01, 0x43, 0x54, 0xd0, 0x2d, 0x68, 0x83, 0xca, + 0x15, 0xc2, 0x4d, 0x8c, 0x39, 0x56, 0xb1, 0xbd, + 0x02, 0x7b, 0xcf, 0x41, 0xf1, 0x51, 0xfd, 0x80, + + 0x23, 0xc5, 0x34, 0x0e, 0x56, 0x06, 0xf3, 0x7e, + 0x90, 0xfd, 0xb8, 0x7c, 0x86, 0xfb, 0x4f, 0xa6, + 0x34, 0xb3, 0x71, 0x8a, 0x30, 0xba, 0xce, 0x06, + 0xa6, 0x6e, 0xaf, 0x8f, 0x63, 0xc4, 0xaa, 0x3b, + + 0x63, 0x78, 0x26, 0xa8, 0x7f, 0xe8, 0xcf, 0xa4, + 0x42, 0x82, 0xe9, 0x2c, 0xb1, 0x61, 0x5a, 0xf3, + 0xa2, 0x8e, 0x53, 0xbc, 0x74, 0xc7, 0xcb, 0xa1, + 0xa0, 0x97, 0x7b, 0xe9, 0x06, 0x5d, 0x0c, 0x1a, + + 0x5d, 0xec, 0x6c, 0x54, 0xae, 0x38, 0xd3, 0x7f, + 0x37, 0xaa, 0x35, 0x28, 0x3e, 0x04, 0x8e, 0x55, + 0x30, 0xa8, 0x5c, 0x4e, 0x7a, 0x29, 0xd7, 0xb9, + 0x2e, 0xc0, 0xc3, 0x16, 0x9c, 0xdf, 0x2a, 0x80, + + 0x5c, 0x76, 0x04, 0xbc, 0xe6, 0x00, 0x49, 0xb9, + 0xfb, 0x7b, 0x8e, 0xaa, 0xc1, 0x0f, 0x51, 0xae, + 0x23, 0x79, 0x4c, 0xeb, 0xa6, 0x8b, 0xb5, 0x81, + 0x12, 0xe2, 0x93, 0xb9, 0xb6, 0x92, 0xca, 0x72, + + 0x1b, 0x37, 0xc6, 0x62, 0xf8, 0x57, 0x4e, 0xd4, + 0xdb, 0xa6, 0xf8, 0x8e, 0x17, 0x08, 0x81, 0xc8, + 0x2c, 0xdd, 0xc1, 0x03, 0x4a, 0x0c, 0xa7, 0xe2, + 0x84, 0xbf, 0x09, 0x62, 0xb6, 0xb2, 0x62, 0x92, + + 0xd8, 0x36, 0xfa, 0x9f, 0x73, 0xc1, 0xac, 0x77, + 0x0e, 0xef, 0x0f, 0x2d, 0x3a, 0x1e, 0xaf, 0x61, + 0xd3, 0xe0, 0x35, 0x55, 0xfd, 0x42, 0x4e, 0xed, + 0xd6, 0x7e, 0x18, 0xa1, 0x80, 0x94, 0xf8, 0x88, +}; +static const uint8_t ciph_data_aes_xts_vect7_ctx[] = { + 0xd5, 0x5f, 0x68, 0x4f, 0x81, 0xf4, 0x42, 0x6e, + 0x9f, 0xde, 0x92, 0xa5, 0xff, 0x02, 0xdf, 0x2a, + 0xc8, 0x96, 0xaf, 0x63, 0x96, 0x28, 0x88, 0xa9, + 0x79, 0x10, 0xc1, 0x37, 0x9e, 0x20, 0xb0, 0xa3, + + 0xb1, 0xdb, 0x61, 0x3f, 0xb7, 0xfe, 0x2e, 0x07, + 0x00, 0x43, 0x29, 0xea, 0x5c, 0x22, 0xbf, 0xd3, + 0x3e, 0x3d, 0xbe, 0x4c, 0xf5, 0x8c, 0xc6, 0x08, + 0xc2, 0xc2, 0x6c, 0x19, 0xa2, 0xe2, 0xfe, 0x22, + + 0xf9, 0x87, 0x32, 0xc2, 0xb5, 0xcb, 0x84, 0x4c, + 0xc6, 0xc0, 0x70, 0x2d, 0x91, 0xe1, 0xd5, 0x0f, + 0xc4, 0x38, 0x2a, 0x7e, 0xba, 0x56, 0x35, 0xcd, + 0x60, 0x24, 0x32, 0xa2, 0x30, 0x6a, 0xc4, 0xce, + + 0x82, 0xf8, 0xd7, 0x0c, 0x8d, 0x9b, 0xc1, 0x5f, + 0x91, 0x8f, 0xe7, 0x1e, 0x74, 0xc6, 0x22, 0xd5, + 0xcf, 0x71, 0x17, 0x8b, 0xf6, 0xe0, 0xb9, 0xcc, + 0x9f, 0x2b, 0x41, 0xdd, 0x8d, 0xbe, 0x44, 0x1c, + + 0x41, 0xcd, 0x0c, 0x73, 0xa6, 0xdc, 0x47, 0xa3, + 0x48, 0xf6, 0x70, 0x2f, 0x9d, 0x0e, 0x9b, 0x1b, + 0x14, 0x31, 0xe9, 0x48, 0xe2, 0x99, 0xb9, 0xec, + 0x22, 0x72, 0xab, 0x2c, 0x5f, 0x0c, 0x7b, 0xe8, + + 0x6a, 0xff, 0xa5, 0xde, 0xc8, 0x7a, 0x0b, 0xee, + 0x81, 0xd3, 0xd5, 0x00, 0x07, 0xed, 0xaa, 0x2b, + 0xcf, 0xcc, 0xb3, 0x56, 0x05, 0x15, 0x5f, 0xf3, + 0x6e, 0xd8, 0xed, 0xd4, 0xa4, 0x0d, 0xcd, 0x4b, + + 0x24, 0x3a, 0xcd, 0x11, 0xb2, 0xb9, 0x87, 0xbd, + 0xbf, 0xaf, 0x91, 0xa7, 0xca, 0xc2, 0x7e, 0x9c, + 0x5a, 0xea, 0x52, 0x5e, 0xe5, 0x3d, 0xe7, 0xb2, + 0xd3, 0x33, 0x2c, 0x86, 0x44, 0x40, 0x2b, 0x82, + + 0x3e, 0x94, 0xa7, 0xdb, 0x26, 0x27, 0x6d, 0x2d, + 0x23, 0xaa, 0x07, 0x18, 0x0f, 0x76, 0xb4, 0xfd, + 0x29, 0xb9, 0xc0, 0x82, 0x30, 0x99, 0xc9, 0xd6, + 0x2c, 0x51, 0x98, 0x80, 0xae, 0xe7, 0xe9, 0x69, + + 0x76, 0x17, 0xc1, 0x49, 0x7d, 0x47, 0xbf, 0x3e, + 0x57, 0x19, 0x50, 0x31, 0x14, 0x21, 0xb6, 0xb7, + 0x34, 0xd3, 0x8b, 0x0d, 0xb9, 0x1e, 0xb8, 0x53, + 0x31, 0xb9, 0x1e, 0xa9, 0xf6, 0x15, 0x30, 0xf5, + + 0x45, 0x12, 0xa5, 0xa5, 0x2a, 0x4b, 0xad, 0x58, + 0x9e, 0xb6, 0x97, 0x81, 0xd5, 0x37, 0xf2, 0x32, + 0x97, 0xbb, 0x45, 0x9b, 0xda, 0xd2, 0x94, 0x8a, + 0x29, 0xe1, 0x55, 0x0b, 0xf4, 0x78, 0x7e, 0x0b, + + 0xe9, 0x5b, 0xb1, 0x73, 0xcf, 0x5f, 0xab, 0x17, + 0xda, 0xb7, 0xa1, 0x3a, 0x05, 0x2a, 0x63, 0x45, + 0x3d, 0x97, 0xcc, 0xec, 0x1a, 0x32, 0x19, 0x54, + 0x88, 0x6b, 0x7a, 0x12, 0x99, 0xfa, 0xae, 0xec, + + 0xae, 0x35, 0xc6, 0xea, 0xac, 0xa7, 0x53, 0xb0, + 0x41, 0xb5, 0xe5, 0xf0, 0x93, 0xbf, 0x83, 0x39, + 0x7f, 0xd2, 0x1d, 0xd6, 0xb3, 0x01, 0x20, 0x66, + 0xfc, 0xc0, 0x58, 0xcc, 0x32, 0xc3, 0xb0, 0x9d, + + 0x75, 0x62, 0xde, 0xe2, 0x95, 0x09, 0xb5, 0x83, + 0x93, 0x92, 0xc9, 0xff, 0x05, 0xf5, 0x1f, 0x31, + 0x66, 0xaa, 0xac, 0x4a, 0xc5, 0xf2, 0x38, 0x03, + 0x8a, 0x30, 0x45, 0xe6, 0xf7, 0x2e, 0x48, 0xef, + + 0x0f, 0xe8, 0xbc, 0x67, 0x5e, 0x82, 0xc3, 0x18, + 0xa2, 0x68, 0xe4, 0x39, 0x70, 0x27, 0x1b, 0xf1, + 0x19, 0xb8, 0x1b, 0xf6, 0xa9, 0x82, 0x74, 0x65, + 0x54, 0xf8, 0x4e, 0x72, 0xb9, 0xf0, 0x02, 0x80, + + 0xa3, 0x20, 0xa0, 0x81, 0x42, 0x92, 0x3c, 0x23, + 0xc8, 0x83, 0x42, 0x3f, 0xf9, 0x49, 0x82, 0x7f, + 0x29, 0xbb, 0xac, 0xdc, 0x1c, 0xcd, 0xb0, 0x49, + 0x38, 0xce, 0x60, 0x98, 0xc9, 0x5b, 0xa6, 0xb3, + + 0x25, 0x28, 0xf4, 0xef, 0x78, 0xee, 0xd7, 0x78, + 0xb2, 0xe1, 0x22, 0xdd, 0xfd, 0x1c, 0xbd, 0xd1, + 0x1d, 0x1c, 0x0a, 0x67, 0x83, 0xe0, 0x11, 0xfc, + 0x53, 0x6d, 0x63, 0xd0, 0x53, 0x26, 0x06, 0x37, +}; + +/* Vector 8 */ +static const uint8_t ciph_data_aes_xts_vect8_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, +}; +static const uint8_t ciph_data_aes_xts_vect8_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, +}; +static const uint8_t ciph_data_aes_xts_vect8_iv[16] = { + 0xfe +}; +static const uint8_t ciph_data_aes_xts_vect8_ptx[] = { + 0xd5, 0x5f, 0x68, 0x4f, 0x81, 0xf4, 0x42, 0x6e, + 0x9f, 0xde, 0x92, 0xa5, 0xff, 0x02, 0xdf, 0x2a, + 0xc8, 0x96, 0xaf, 0x63, 0x96, 0x28, 0x88, 0xa9, + 0x79, 0x10, 0xc1, 0x37, 0x9e, 0x20, 0xb0, 0xa3, + + 0xb1, 0xdb, 0x61, 0x3f, 0xb7, 0xfe, 0x2e, 0x07, + 0x00, 0x43, 0x29, 0xea, 0x5c, 0x22, 0xbf, 0xd3, + 0x3e, 0x3d, 0xbe, 0x4c, 0xf5, 0x8c, 0xc6, 0x08, + 0xc2, 0xc2, 0x6c, 0x19, 0xa2, 0xe2, 0xfe, 0x22, + + 0xf9, 0x87, 0x32, 0xc2, 0xb5, 0xcb, 0x84, 0x4c, + 0xc6, 0xc0, 0x70, 0x2d, 0x91, 0xe1, 0xd5, 0x0f, + 0xc4, 0x38, 0x2a, 0x7e, 0xba, 0x56, 0x35, 0xcd, + 0x60, 0x24, 0x32, 0xa2, 0x30, 0x6a, 0xc4, 0xce, + + 0x82, 0xf8, 0xd7, 0x0c, 0x8d, 0x9b, 0xc1, 0x5f, + 0x91, 0x8f, 0xe7, 0x1e, 0x74, 0xc6, 0x22, 0xd5, + 0xcf, 0x71, 0x17, 0x8b, 0xf6, 0xe0, 0xb9, 0xcc, + 0x9f, 0x2b, 0x41, 0xdd, 0x8d, 0xbe, 0x44, 0x1c, + + 0x41, 0xcd, 0x0c, 0x73, 0xa6, 0xdc, 0x47, 0xa3, + 0x48, 0xf6, 0x70, 0x2f, 0x9d, 0x0e, 0x9b, 0x1b, + 0x14, 0x31, 0xe9, 0x48, 0xe2, 0x99, 0xb9, 0xec, + 0x22, 0x72, 0xab, 0x2c, 0x5f, 0x0c, 0x7b, 0xe8, + + 0x6a, 0xff, 0xa5, 0xde, 0xc8, 0x7a, 0x0b, 0xee, + 0x81, 0xd3, 0xd5, 0x00, 0x07, 0xed, 0xaa, 0x2b, + 0xcf, 0xcc, 0xb3, 0x56, 0x05, 0x15, 0x5f, 0xf3, + 0x6e, 0xd8, 0xed, 0xd4, 0xa4, 0x0d, 0xcd, 0x4b, + + 0x24, 0x3a, 0xcd, 0x11, 0xb2, 0xb9, 0x87, 0xbd, + 0xbf, 0xaf, 0x91, 0xa7, 0xca, 0xc2, 0x7e, 0x9c, + 0x5a, 0xea, 0x52, 0x5e, 0xe5, 0x3d, 0xe7, 0xb2, + 0xd3, 0x33, 0x2c, 0x86, 0x44, 0x40, 0x2b, 0x82, + + 0x3e, 0x94, 0xa7, 0xdb, 0x26, 0x27, 0x6d, 0x2d, + 0x23, 0xaa, 0x07, 0x18, 0x0f, 0x76, 0xb4, 0xfd, + 0x29, 0xb9, 0xc0, 0x82, 0x30, 0x99, 0xc9, 0xd6, + 0x2c, 0x51, 0x98, 0x80, 0xae, 0xe7, 0xe9, 0x69, + + 0x76, 0x17, 0xc1, 0x49, 0x7d, 0x47, 0xbf, 0x3e, + 0x57, 0x19, 0x50, 0x31, 0x14, 0x21, 0xb6, 0xb7, + 0x34, 0xd3, 0x8b, 0x0d, 0xb9, 0x1e, 0xb8, 0x53, + 0x31, 0xb9, 0x1e, 0xa9, 0xf6, 0x15, 0x30, 0xf5, + + 0x45, 0x12, 0xa5, 0xa5, 0x2a, 0x4b, 0xad, 0x58, + 0x9e, 0xb6, 0x97, 0x81, 0xd5, 0x37, 0xf2, 0x32, + 0x97, 0xbb, 0x45, 0x9b, 0xda, 0xd2, 0x94, 0x8a, + 0x29, 0xe1, 0x55, 0x0b, 0xf4, 0x78, 0x7e, 0x0b, + + 0xe9, 0x5b, 0xb1, 0x73, 0xcf, 0x5f, 0xab, 0x17, + 0xda, 0xb7, 0xa1, 0x3a, 0x05, 0x2a, 0x63, 0x45, + 0x3d, 0x97, 0xcc, 0xec, 0x1a, 0x32, 0x19, 0x54, + 0x88, 0x6b, 0x7a, 0x12, 0x99, 0xfa, 0xae, 0xec, + + 0xae, 0x35, 0xc6, 0xea, 0xac, 0xa7, 0x53, 0xb0, + 0x41, 0xb5, 0xe5, 0xf0, 0x93, 0xbf, 0x83, 0x39, + 0x7f, 0xd2, 0x1d, 0xd6, 0xb3, 0x01, 0x20, 0x66, + 0xfc, 0xc0, 0x58, 0xcc, 0x32, 0xc3, 0xb0, 0x9d, + + 0x75, 0x62, 0xde, 0xe2, 0x95, 0x09, 0xb5, 0x83, + 0x93, 0x92, 0xc9, 0xff, 0x05, 0xf5, 0x1f, 0x31, + 0x66, 0xaa, 0xac, 0x4a, 0xc5, 0xf2, 0x38, 0x03, + 0x8a, 0x30, 0x45, 0xe6, 0xf7, 0x2e, 0x48, 0xef, + + 0x0f, 0xe8, 0xbc, 0x67, 0x5e, 0x82, 0xc3, 0x18, + 0xa2, 0x68, 0xe4, 0x39, 0x70, 0x27, 0x1b, 0xf1, + 0x19, 0xb8, 0x1b, 0xf6, 0xa9, 0x82, 0x74, 0x65, + 0x54, 0xf8, 0x4e, 0x72, 0xb9, 0xf0, 0x02, 0x80, + + 0xa3, 0x20, 0xa0, 0x81, 0x42, 0x92, 0x3c, 0x23, + 0xc8, 0x83, 0x42, 0x3f, 0xf9, 0x49, 0x82, 0x7f, + 0x29, 0xbb, 0xac, 0xdc, 0x1c, 0xcd, 0xb0, 0x49, + 0x38, 0xce, 0x60, 0x98, 0xc9, 0x5b, 0xa6, 0xb3, + + 0x25, 0x28, 0xf4, 0xef, 0x78, 0xee, 0xd7, 0x78, + 0xb2, 0xe1, 0x22, 0xdd, 0xfd, 0x1c, 0xbd, 0xd1, + 0x1d, 0x1c, 0x0a, 0x67, 0x83, 0xe0, 0x11, 0xfc, + 0x53, 0x6d, 0x63, 0xd0, 0x53, 0x26, 0x06, 0x37, +}; +static const uint8_t ciph_data_aes_xts_vect8_ctx[] = { + 0x72, 0xef, 0xc1, 0xeb, 0xfe, 0x1e, 0xe2, 0x59, + 0x75, 0xa6, 0xeb, 0x3a, 0xa8, 0x58, 0x9d, 0xda, + 0x2b, 0x26, 0x1f, 0x1c, 0x85, 0xbd, 0xab, 0x44, + 0x2a, 0x9e, 0x5b, 0x2d, 0xd1, 0xd7, 0xc3, 0x95, + + 0x7a, 0x16, 0xfc, 0x08, 0xe5, 0x26, 0xd4, 0xb1, + 0x22, 0x3f, 0x1b, 0x12, 0x32, 0xa1, 0x1a, 0xf2, + 0x74, 0xc3, 0xd7, 0x0d, 0xac, 0x57, 0xf8, 0x3e, + 0x09, 0x83, 0xc4, 0x98, 0xf1, 0xa6, 0xf1, 0xae, + + 0xcb, 0x02, 0x1c, 0x3e, 0x70, 0x08, 0x5a, 0x1e, + 0x52, 0x7f, 0x1c, 0xe4, 0x1e, 0xe5, 0x91, 0x1a, + 0x82, 0x02, 0x01, 0x61, 0x52, 0x9c, 0xd8, 0x27, + 0x73, 0x76, 0x2d, 0xaf, 0x54, 0x59, 0xde, 0x94, + + 0xa0, 0xa8, 0x2a, 0xda, 0xe7, 0xe1, 0x70, 0x3c, + 0x80, 0x85, 0x43, 0xc2, 0x9e, 0xd6, 0xfb, 0x32, + 0xd9, 0xe0, 0x04, 0x32, 0x7c, 0x13, 0x55, 0x18, + 0x0c, 0x99, 0x5a, 0x07, 0x74, 0x14, 0x93, 0xa0, + + 0x9c, 0x21, 0xba, 0x01, 0xa3, 0x87, 0x88, 0x2d, + 0xa4, 0xf6, 0x25, 0x34, 0xb8, 0x7b, 0xb1, 0x5d, + 0x60, 0xd1, 0x97, 0x20, 0x1c, 0x0f, 0xd3, 0xbf, + 0x30, 0xc1, 0x50, 0x0a, 0x3e, 0xcf, 0xec, 0xdd, + + 0x66, 0xd8, 0x72, 0x1f, 0x90, 0xbc, 0xc4, 0xc1, + 0x7e, 0xe9, 0x25, 0xc6, 0x1b, 0x0a, 0x03, 0x72, + 0x7a, 0x9c, 0x0d, 0x5f, 0x5c, 0xa4, 0x62, 0xfb, + 0xfa, 0x0a, 0xf1, 0xc2, 0x51, 0x3a, 0x9d, 0x9d, + + 0x4b, 0x53, 0x45, 0xbd, 0x27, 0xa5, 0xf6, 0xe6, + 0x53, 0xf7, 0x51, 0x69, 0x3e, 0x6b, 0x6a, 0x2b, + 0x8e, 0xad, 0x57, 0xd5, 0x11, 0xe0, 0x0e, 0x58, + 0xc4, 0x5b, 0x7b, 0x8d, 0x00, 0x5a, 0xf7, 0x92, + + 0x88, 0xf5, 0xc7, 0xc2, 0x2f, 0xd4, 0xf1, 0xbf, + 0x7a, 0x89, 0x8b, 0x03, 0xa5, 0x63, 0x4c, 0x6a, + 0x1a, 0xe3, 0xf9, 0xfa, 0xe5, 0xde, 0x4f, 0x29, + 0x6a, 0x28, 0x96, 0xb2, 0x3e, 0x7e, 0xd4, 0x3e, + + 0xd1, 0x4f, 0xa5, 0xa2, 0x80, 0x3f, 0x4d, 0x28, + 0xf0, 0xd3, 0xff, 0xcf, 0x24, 0x75, 0x76, 0x77, + 0xae, 0xbd, 0xb4, 0x7b, 0xb3, 0x88, 0x37, 0x87, + 0x08, 0x94, 0x8a, 0x8d, 0x41, 0x26, 0xed, 0x18, + + 0x39, 0xe0, 0xda, 0x29, 0xa5, 0x37, 0xa8, 0xc1, + 0x98, 0xb3, 0xc6, 0x6a, 0xb0, 0x07, 0x12, 0xdd, + 0x26, 0x16, 0x74, 0xbf, 0x45, 0xa7, 0x3d, 0x67, + 0xf7, 0x69, 0x14, 0xf8, 0x30, 0xca, 0x01, 0x4b, + + 0x65, 0x59, 0x6f, 0x27, 0xe4, 0xcf, 0x62, 0xde, + 0x66, 0x12, 0x5a, 0x55, 0x66, 0xdf, 0x99, 0x75, + 0x15, 0x56, 0x28, 0xb4, 0x00, 0xfb, 0xfb, 0x3a, + 0x29, 0x04, 0x0e, 0xd5, 0x0f, 0xaf, 0xfd, 0xbb, + + 0x18, 0xae, 0xce, 0x7c, 0x5c, 0x44, 0x69, 0x32, + 0x60, 0xaa, 0xb3, 0x86, 0xc0, 0xa3, 0x7b, 0x11, + 0xb1, 0x14, 0xf1, 0xc4, 0x15, 0xae, 0xbb, 0x65, + 0x3b, 0xe4, 0x68, 0x17, 0x94, 0x28, 0xd4, 0x3a, + + 0x4d, 0x8b, 0xc3, 0xec, 0x38, 0x81, 0x3e, 0xca, + 0x30, 0xa1, 0x3c, 0xf1, 0xbb, 0x18, 0xd5, 0x24, + 0xf1, 0x99, 0x2d, 0x44, 0xd8, 0xb1, 0xa4, 0x2e, + 0xa3, 0x0b, 0x22, 0xe6, 0xc9, 0x5b, 0x19, 0x9d, + + 0x8d, 0x18, 0x2f, 0x88, 0x40, 0xb0, 0x9d, 0x05, + 0x95, 0x85, 0xc3, 0x1a, 0xd6, 0x91, 0xfa, 0x06, + 0x19, 0xff, 0x03, 0x8a, 0xca, 0x2c, 0x39, 0xa9, + 0x43, 0x42, 0x11, 0x57, 0x36, 0x17, 0x17, 0xc4, + + 0x9d, 0x32, 0x20, 0x28, 0xa7, 0x46, 0x48, 0x11, + 0x3b, 0xd8, 0xc9, 0xd7, 0xec, 0x77, 0xcf, 0x3c, + 0x89, 0xc1, 0xec, 0x87, 0x18, 0xce, 0xff, 0x85, + 0x16, 0xd9, 0x6b, 0x34, 0xc3, 0xc6, 0x14, 0xf1, + + 0x06, 0x99, 0xc9, 0xab, 0xc4, 0xed, 0x04, 0x11, + 0x50, 0x62, 0x23, 0xbe, 0xa1, 0x6a, 0xf3, 0x5c, + 0x88, 0x3a, 0xcc, 0xdb, 0xe1, 0x10, 0x4e, 0xef, + 0x0c, 0xfd, 0xb5, 0x4e, 0x12, 0xfb, 0x23, 0x0a, +}; + +/* Vector 9 */ +static const uint8_t ciph_data_aes_xts_vect9_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, +}; +static const uint8_t ciph_data_aes_xts_vect9_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, +}; +static const uint8_t ciph_data_aes_xts_vect9_iv[16] = { + 0xff +}; +static const uint8_t ciph_data_aes_xts_vect9_ptx[] = { + 0x72, 0xef, 0xc1, 0xeb, 0xfe, 0x1e, 0xe2, 0x59, + 0x75, 0xa6, 0xeb, 0x3a, 0xa8, 0x58, 0x9d, 0xda, + 0x2b, 0x26, 0x1f, 0x1c, 0x85, 0xbd, 0xab, 0x44, + 0x2a, 0x9e, 0x5b, 0x2d, 0xd1, 0xd7, 0xc3, 0x95, + + 0x7a, 0x16, 0xfc, 0x08, 0xe5, 0x26, 0xd4, 0xb1, + 0x22, 0x3f, 0x1b, 0x12, 0x32, 0xa1, 0x1a, 0xf2, + 0x74, 0xc3, 0xd7, 0x0d, 0xac, 0x57, 0xf8, 0x3e, + 0x09, 0x83, 0xc4, 0x98, 0xf1, 0xa6, 0xf1, 0xae, + + 0xcb, 0x02, 0x1c, 0x3e, 0x70, 0x08, 0x5a, 0x1e, + 0x52, 0x7f, 0x1c, 0xe4, 0x1e, 0xe5, 0x91, 0x1a, + 0x82, 0x02, 0x01, 0x61, 0x52, 0x9c, 0xd8, 0x27, + 0x73, 0x76, 0x2d, 0xaf, 0x54, 0x59, 0xde, 0x94, + + 0xa0, 0xa8, 0x2a, 0xda, 0xe7, 0xe1, 0x70, 0x3c, + 0x80, 0x85, 0x43, 0xc2, 0x9e, 0xd6, 0xfb, 0x32, + 0xd9, 0xe0, 0x04, 0x32, 0x7c, 0x13, 0x55, 0x18, + 0x0c, 0x99, 0x5a, 0x07, 0x74, 0x14, 0x93, 0xa0, + + 0x9c, 0x21, 0xba, 0x01, 0xa3, 0x87, 0x88, 0x2d, + 0xa4, 0xf6, 0x25, 0x34, 0xb8, 0x7b, 0xb1, 0x5d, + 0x60, 0xd1, 0x97, 0x20, 0x1c, 0x0f, 0xd3, 0xbf, + 0x30, 0xc1, 0x50, 0x0a, 0x3e, 0xcf, 0xec, 0xdd, + + 0x66, 0xd8, 0x72, 0x1f, 0x90, 0xbc, 0xc4, 0xc1, + 0x7e, 0xe9, 0x25, 0xc6, 0x1b, 0x0a, 0x03, 0x72, + 0x7a, 0x9c, 0x0d, 0x5f, 0x5c, 0xa4, 0x62, 0xfb, + 0xfa, 0x0a, 0xf1, 0xc2, 0x51, 0x3a, 0x9d, 0x9d, + + 0x4b, 0x53, 0x45, 0xbd, 0x27, 0xa5, 0xf6, 0xe6, + 0x53, 0xf7, 0x51, 0x69, 0x3e, 0x6b, 0x6a, 0x2b, + 0x8e, 0xad, 0x57, 0xd5, 0x11, 0xe0, 0x0e, 0x58, + 0xc4, 0x5b, 0x7b, 0x8d, 0x00, 0x5a, 0xf7, 0x92, + + 0x88, 0xf5, 0xc7, 0xc2, 0x2f, 0xd4, 0xf1, 0xbf, + 0x7a, 0x89, 0x8b, 0x03, 0xa5, 0x63, 0x4c, 0x6a, + 0x1a, 0xe3, 0xf9, 0xfa, 0xe5, 0xde, 0x4f, 0x29, + 0x6a, 0x28, 0x96, 0xb2, 0x3e, 0x7e, 0xd4, 0x3e, + + 0xd1, 0x4f, 0xa5, 0xa2, 0x80, 0x3f, 0x4d, 0x28, + 0xf0, 0xd3, 0xff, 0xcf, 0x24, 0x75, 0x76, 0x77, + 0xae, 0xbd, 0xb4, 0x7b, 0xb3, 0x88, 0x37, 0x87, + 0x08, 0x94, 0x8a, 0x8d, 0x41, 0x26, 0xed, 0x18, + + 0x39, 0xe0, 0xda, 0x29, 0xa5, 0x37, 0xa8, 0xc1, + 0x98, 0xb3, 0xc6, 0x6a, 0xb0, 0x07, 0x12, 0xdd, + 0x26, 0x16, 0x74, 0xbf, 0x45, 0xa7, 0x3d, 0x67, + 0xf7, 0x69, 0x14, 0xf8, 0x30, 0xca, 0x01, 0x4b, + + 0x65, 0x59, 0x6f, 0x27, 0xe4, 0xcf, 0x62, 0xde, + 0x66, 0x12, 0x5a, 0x55, 0x66, 0xdf, 0x99, 0x75, + 0x15, 0x56, 0x28, 0xb4, 0x00, 0xfb, 0xfb, 0x3a, + 0x29, 0x04, 0x0e, 0xd5, 0x0f, 0xaf, 0xfd, 0xbb, + + 0x18, 0xae, 0xce, 0x7c, 0x5c, 0x44, 0x69, 0x32, + 0x60, 0xaa, 0xb3, 0x86, 0xc0, 0xa3, 0x7b, 0x11, + 0xb1, 0x14, 0xf1, 0xc4, 0x15, 0xae, 0xbb, 0x65, + 0x3b, 0xe4, 0x68, 0x17, 0x94, 0x28, 0xd4, 0x3a, + + 0x4d, 0x8b, 0xc3, 0xec, 0x38, 0x81, 0x3e, 0xca, + 0x30, 0xa1, 0x3c, 0xf1, 0xbb, 0x18, 0xd5, 0x24, + 0xf1, 0x99, 0x2d, 0x44, 0xd8, 0xb1, 0xa4, 0x2e, + 0xa3, 0x0b, 0x22, 0xe6, 0xc9, 0x5b, 0x19, 0x9d, + + 0x8d, 0x18, 0x2f, 0x88, 0x40, 0xb0, 0x9d, 0x05, + 0x95, 0x85, 0xc3, 0x1a, 0xd6, 0x91, 0xfa, 0x06, + 0x19, 0xff, 0x03, 0x8a, 0xca, 0x2c, 0x39, 0xa9, + 0x43, 0x42, 0x11, 0x57, 0x36, 0x17, 0x17, 0xc4, + + 0x9d, 0x32, 0x20, 0x28, 0xa7, 0x46, 0x48, 0x11, + 0x3b, 0xd8, 0xc9, 0xd7, 0xec, 0x77, 0xcf, 0x3c, + 0x89, 0xc1, 0xec, 0x87, 0x18, 0xce, 0xff, 0x85, + 0x16, 0xd9, 0x6b, 0x34, 0xc3, 0xc6, 0x14, 0xf1, + + 0x06, 0x99, 0xc9, 0xab, 0xc4, 0xed, 0x04, 0x11, + 0x50, 0x62, 0x23, 0xbe, 0xa1, 0x6a, 0xf3, 0x5c, + 0x88, 0x3a, 0xcc, 0xdb, 0xe1, 0x10, 0x4e, 0xef, + 0x0c, 0xfd, 0xb5, 0x4e, 0x12, 0xfb, 0x23, 0x0a, +}; +static const uint8_t ciph_data_aes_xts_vect9_ctx[] = { + 0x32, 0x60, 0xae, 0x8d, 0xad, 0x1f, 0x4a, 0x32, + 0xc5, 0xca, 0xfe, 0x3a, 0xb0, 0xeb, 0x95, 0x54, + 0x9d, 0x46, 0x1a, 0x67, 0xce, 0xb9, 0xe5, 0xaa, + 0x2d, 0x3a, 0xfb, 0x62, 0xde, 0xce, 0x05, 0x53, + + 0x19, 0x3b, 0xa5, 0x0c, 0x75, 0xbe, 0x25, 0x1e, + 0x08, 0xd1, 0xd0, 0x8f, 0x10, 0x88, 0x57, 0x6c, + 0x7e, 0xfd, 0xfa, 0xaf, 0x3f, 0x45, 0x95, 0x59, + 0x57, 0x1e, 0x12, 0x51, 0x17, 0x53, 0xb0, 0x7a, + + 0xf0, 0x73, 0xf3, 0x5d, 0xa0, 0x6a, 0xf0, 0xce, + 0x0b, 0xbf, 0x6b, 0x8f, 0x5c, 0xcc, 0x5c, 0xea, + 0x50, 0x0e, 0xc1, 0xb2, 0x11, 0xbd, 0x51, 0xf6, + 0x3b, 0x60, 0x6b, 0xf6, 0x52, 0x87, 0x96, 0xca, + + 0x12, 0x17, 0x3b, 0xa3, 0x9b, 0x89, 0x35, 0xee, + 0x44, 0xcc, 0xce, 0x64, 0x6f, 0x90, 0xa4, 0x5b, + 0xf9, 0xcc, 0xc5, 0x67, 0xf0, 0xac, 0xe1, 0x3d, + 0xc2, 0xd5, 0x3e, 0xbe, 0xed, 0xc8, 0x1f, 0x58, + + 0xb2, 0xe4, 0x11, 0x79, 0xdd, 0xdf, 0x0d, 0x5a, + 0x5c, 0x42, 0xf5, 0xd8, 0x50, 0x6c, 0x1a, 0x5d, + 0x2f, 0x8f, 0x59, 0xf3, 0xea, 0x87, 0x3c, 0xbc, + 0xd0, 0xee, 0xc1, 0x9a, 0xcb, 0xf3, 0x25, 0x42, + + 0x3b, 0xd3, 0xdc, 0xb8, 0xc2, 0xb1, 0xbf, 0x1d, + 0x1e, 0xae, 0xd0, 0xeb, 0xa7, 0xf0, 0x69, 0x8e, + 0x43, 0x14, 0xfb, 0xeb, 0x2f, 0x15, 0x66, 0xd1, + 0xb9, 0x25, 0x30, 0x08, 0xcb, 0xcc, 0xf4, 0x5a, + + 0x2b, 0x0d, 0x9c, 0x5c, 0x9c, 0x21, 0x47, 0x4f, + 0x40, 0x76, 0xe0, 0x2b, 0xe2, 0x60, 0x50, 0xb9, + 0x9d, 0xee, 0x4f, 0xd6, 0x8a, 0x4c, 0xf8, 0x90, + 0xe4, 0x96, 0xe4, 0xfc, 0xae, 0x7b, 0x70, 0xf9, + + 0x4e, 0xa5, 0xa9, 0x06, 0x2d, 0xa0, 0xda, 0xeb, + 0xa1, 0x99, 0x3d, 0x2c, 0xcd, 0x1d, 0xd3, 0xc2, + 0x44, 0xb8, 0x42, 0x88, 0x01, 0x49, 0x5a, 0x58, + 0xb2, 0x16, 0x54, 0x7e, 0x7e, 0x84, 0x7c, 0x46, + + 0xd1, 0xd7, 0x56, 0x37, 0x7b, 0x62, 0x42, 0xd2, + 0xe5, 0xfb, 0x83, 0xbf, 0x75, 0x2b, 0x54, 0xe0, + 0xdf, 0x71, 0xe8, 0x89, 0xf3, 0xa2, 0xbb, 0x0f, + 0x4c, 0x10, 0x80, 0x5b, 0xf3, 0xc5, 0x90, 0x37, + + 0x6e, 0x3c, 0x24, 0xe2, 0x2f, 0xf5, 0x7f, 0x7f, + 0xa9, 0x65, 0x57, 0x73, 0x75, 0x32, 0x5c, 0xea, + 0x5d, 0x92, 0x0d, 0xb9, 0x4b, 0x9c, 0x33, 0x6b, + 0x45, 0x5f, 0x6e, 0x89, 0x4c, 0x01, 0x86, 0x6f, + + 0xe9, 0xfb, 0xb8, 0xc8, 0xd3, 0xf7, 0x0a, 0x29, + 0x57, 0x28, 0x5f, 0x6d, 0xfb, 0x5d, 0xcd, 0x8c, + 0xbf, 0x54, 0x78, 0x2f, 0x8f, 0xe7, 0x76, 0x6d, + 0x47, 0x23, 0x81, 0x99, 0x13, 0xac, 0x77, 0x34, + + 0x21, 0xe3, 0xa3, 0x10, 0x95, 0x86, 0x6b, 0xad, + 0x22, 0xc8, 0x6a, 0x60, 0x36, 0xb2, 0x51, 0x8b, + 0x20, 0x59, 0xb4, 0x22, 0x9d, 0x18, 0xc8, 0xc2, + 0xcc, 0xbd, 0xf9, 0x06, 0xc6, 0xcc, 0x6e, 0x82, + + 0x46, 0x4e, 0xe5, 0x7b, 0xdd, 0xb0, 0xbe, 0xbc, + 0xb1, 0xdc, 0x64, 0x53, 0x25, 0xbf, 0xb3, 0xe6, + 0x65, 0xef, 0x72, 0x51, 0x08, 0x2c, 0x88, 0xeb, + 0xb1, 0xcf, 0x20, 0x3b, 0xd7, 0x79, 0xfd, 0xd3, + + 0x86, 0x75, 0x71, 0x3c, 0x8d, 0xaa, 0xdd, 0x17, + 0xe1, 0xca, 0xbe, 0xe4, 0x32, 0xb0, 0x97, 0x87, + 0xb6, 0xdd, 0xf3, 0x30, 0x4e, 0x38, 0xb7, 0x31, + 0xb4, 0x5d, 0xf5, 0xdf, 0x51, 0xb7, 0x8f, 0xcf, + + 0xb3, 0xd3, 0x24, 0x66, 0x02, 0x8d, 0x0b, 0xa3, + 0x65, 0x55, 0xe7, 0xe1, 0x1a, 0xb0, 0xee, 0x06, + 0x66, 0x06, 0x1d, 0x16, 0x45, 0xd9, 0x62, 0x44, + 0x4b, 0xc4, 0x7a, 0x38, 0x18, 0x89, 0x30, 0xa8, + + 0x4b, 0x4d, 0x56, 0x13, 0x95, 0xc7, 0x3c, 0x08, + 0x70, 0x21, 0x92, 0x7c, 0xa6, 0x38, 0xb7, 0xaf, + 0xc8, 0xa8, 0x67, 0x9c, 0xcb, 0x84, 0xc2, 0x65, + 0x55, 0x44, 0x0e, 0xc7, 0xf1, 0x04, 0x45, 0xcd, +}; + +/* + * XTS-AES-256 applied for a data unit of 512 bytes + */ + +/* Vector 10 */ +static const uint8_t ciph_data_aes_xts_vect10_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, +}; +static const uint8_t ciph_data_aes_xts_vect10_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, +}; +static const uint8_t ciph_data_aes_xts_vect10_iv[16] = { + 0xff +}; +static const uint8_t ciph_data_aes_xts_vect10_ptx[] = { + 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, +}; +static const uint8_t ciph_data_aes_xts_vect10_ctx[] = { + 0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, + 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf, 0x9b, + 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, + 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3, 0xe6, 0x3b, + + 0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, + 0x66, 0xb3, 0x17, 0xf9, 0xac, 0x68, 0x3f, 0x44, + 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, + 0x45, 0xbe, 0xfe, 0xcb, 0x4b, 0xb1, 0x88, 0xfd, + + 0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, + 0xb1, 0x08, 0xfd, 0x10, 0x98, 0xba, 0xec, 0x70, + 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, + 0x7d, 0x84, 0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0, + + 0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, + 0xae, 0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, + 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10, + 0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca, + + 0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1, 0x03, + 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, + 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d, 0xc4, 0xcd, + 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0, + + 0xb5, 0x78, 0x1c, 0x34, 0x80, 0x3f, 0xa7, 0x54, + 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, + 0xf2, 0x80, 0xd7, 0x66, 0x7b, 0x32, 0x7f, 0x6c, + 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f, + + 0x93, 0xec, 0x05, 0xc5, 0x2e, 0x04, 0x93, 0xef, + 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, + 0x28, 0x9d, 0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, + 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec, + + 0x58, 0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, + 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6, + 0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, + 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02, 0x0a, + + 0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, + 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b, 0xe5, 0x4f, + 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, + 0x15, 0xe1, 0x32, 0x7a, 0x02, 0xb1, 0x40, 0xf1, + + 0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, + 0x8f, 0x83, 0x74, 0x59, 0x5c, 0x84, 0x9d, 0x84, + 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, + 0x43, 0xcb, 0x47, 0xbd, 0x71, 0xc5, 0xed, 0xae, + + 0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, + 0xc9, 0xde, 0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, + 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, + 0x6a, 0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29, + + 0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72, + 0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, + 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9, 0x91, + 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac, + + 0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a, 0xff, 0x04, + 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, + 0xdd, 0x7a, 0xe4, 0xc6, 0xe2, 0x91, 0x09, 0x00, + 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f, + + 0x64, 0x5e, 0x8b, 0x7e, 0x9b, 0xfd, 0xef, 0x33, + 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, + 0xc2, 0x7b, 0x34, 0x29, 0xea, 0xed, 0xb4, 0xed, + 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85, + + 0x1a, 0xd7, 0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, + 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, + 0xab, 0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, + 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa, + + 0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, + 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e, 0x54, + 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, + 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48, 0xc1, 0x51, +}; + +/* Vector 11 */ +static const uint8_t ciph_data_aes_xts_vect11_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, +}; +static const uint8_t ciph_data_aes_xts_vect11_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, +}; +static const uint8_t ciph_data_aes_xts_vect11_iv[16] = { + 0xff, 0xff +}; +static const uint8_t ciph_data_aes_xts_vect11_ptx[] = { + 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, +}; +static const uint8_t ciph_data_aes_xts_vect11_ctx[] = { + 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, + 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, + 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, + 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11, + + 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, + 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, + 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, + 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2, + + 0x46, 0x9e, 0xe4, 0xa4, 0xfa, 0x79, 0x4e, 0x4b, + 0xbc, 0x7f, 0x39, 0xbc, 0x02, 0x6e, 0x3c, 0xb7, + 0x2c, 0x33, 0xb0, 0x88, 0x8f, 0x25, 0xb4, 0xac, + 0xf5, 0x6a, 0x2a, 0x98, 0x04, 0xf1, 0xce, 0x6d, + + 0x3d, 0x6e, 0x1d, 0xc6, 0xca, 0x18, 0x1d, 0x4b, + 0x54, 0x61, 0x79, 0xd5, 0x55, 0x44, 0xaa, 0x77, + 0x60, 0xc4, 0x0d, 0x06, 0x74, 0x15, 0x39, 0xc7, + 0xe3, 0xcd, 0x9d, 0x2f, 0x66, 0x50, 0xb2, 0x01, + + 0x3f, 0xd0, 0xee, 0xb8, 0xc2, 0xb8, 0xe3, 0xd8, + 0xd2, 0x40, 0xcc, 0xae, 0x2d, 0x4c, 0x98, 0x32, + 0x0a, 0x74, 0x42, 0xe1, 0xc8, 0xd7, 0x5a, 0x42, + 0xd6, 0xe6, 0xcf, 0xa4, 0xc2, 0xec, 0xa1, 0x79, + + 0x8d, 0x15, 0x8c, 0x7a, 0xec, 0xdf, 0x82, 0x49, + 0x0f, 0x24, 0xbb, 0x9b, 0x38, 0xe1, 0x08, 0xbc, + 0xda, 0x12, 0xc3, 0xfa, 0xf9, 0xa2, 0x11, 0x41, + 0xc3, 0x61, 0x3b, 0x58, 0x36, 0x7f, 0x92, 0x2a, + + 0xaa, 0x26, 0xcd, 0x22, 0xf2, 0x3d, 0x70, 0x8d, + 0xae, 0x69, 0x9a, 0xd7, 0xcb, 0x40, 0xa8, 0xad, + 0x0b, 0x6e, 0x27, 0x84, 0x97, 0x3d, 0xcb, 0x60, + 0x56, 0x84, 0xc0, 0x8b, 0x8d, 0x69, 0x98, 0xc6, + + 0x9a, 0xac, 0x04, 0x99, 0x21, 0x87, 0x1e, 0xbb, + 0x65, 0x30, 0x1a, 0x46, 0x19, 0xca, 0x80, 0xec, + 0xb4, 0x85, 0xa3, 0x1d, 0x74, 0x42, 0x23, 0xce, + 0x8d, 0xdc, 0x23, 0x94, 0x82, 0x8d, 0x6a, 0x80, + + 0x47, 0x0c, 0x09, 0x2f, 0x5b, 0xa4, 0x13, 0xc3, + 0x37, 0x8f, 0xa6, 0x05, 0x42, 0x55, 0xc6, 0xf9, + 0xdf, 0x44, 0x95, 0x86, 0x2b, 0xbb, 0x32, 0x87, + 0x68, 0x1f, 0x93, 0x1b, 0x68, 0x7c, 0x88, 0x8a, + + 0xbf, 0x84, 0x4d, 0xfc, 0x8f, 0xc2, 0x83, 0x31, + 0xe5, 0x79, 0x92, 0x8c, 0xd1, 0x2b, 0xd2, 0x39, + 0x0a, 0xe1, 0x23, 0xcf, 0x03, 0x81, 0x8d, 0x14, + 0xde, 0xdd, 0xe5, 0xc0, 0xc2, 0x4c, 0x8a, 0xb0, + + 0x18, 0xbf, 0xca, 0x75, 0xca, 0x09, 0x6f, 0x2d, + 0x53, 0x1f, 0x3d, 0x16, 0x19, 0xe7, 0x85, 0xf1, + 0xad, 0xa4, 0x37, 0xca, 0xb9, 0x2e, 0x98, 0x05, + 0x58, 0xb3, 0xdc, 0xe1, 0x47, 0x4a, 0xfb, 0x75, + + 0xbf, 0xed, 0xbf, 0x8f, 0xf5, 0x4c, 0xb2, 0x61, + 0x8e, 0x02, 0x44, 0xc9, 0xac, 0x0d, 0x3c, 0x66, + 0xfb, 0x51, 0x59, 0x8c, 0xd2, 0xdb, 0x11, 0xf9, + 0xbe, 0x39, 0x79, 0x1a, 0xbe, 0x44, 0x7c, 0x63, + + 0x09, 0x4f, 0x7c, 0x45, 0x3b, 0x7f, 0xf8, 0x7c, + 0xb5, 0xbb, 0x36, 0xb7, 0xc7, 0x9e, 0xfb, 0x08, + 0x72, 0xd1, 0x70, 0x58, 0xb8, 0x3b, 0x15, 0xab, + 0x08, 0x66, 0xad, 0x8a, 0x58, 0x65, 0x6c, 0x5a, + + 0x7e, 0x20, 0xdb, 0xdf, 0x30, 0x8b, 0x24, 0x61, + 0xd9, 0x7c, 0x0e, 0xc0, 0x02, 0x4a, 0x27, 0x15, + 0x05, 0x52, 0x49, 0xcf, 0x3b, 0x47, 0x8d, 0xdd, + 0x47, 0x40, 0xde, 0x65, 0x4f, 0x75, 0xca, 0x68, + + 0x6e, 0x0d, 0x73, 0x45, 0xc6, 0x9e, 0xd5, 0x0c, + 0xdc, 0x2a, 0x8b, 0x33, 0x2b, 0x1f, 0x88, 0x24, + 0x10, 0x8a, 0xc9, 0x37, 0xeb, 0x05, 0x05, 0x85, + 0x60, 0x8e, 0xe7, 0x34, 0x09, 0x7f, 0xc0, 0x90, + + 0x54, 0xfb, 0xff, 0x89, 0xee, 0xae, 0xea, 0x79, + 0x1f, 0x4a, 0x7a, 0xb1, 0xf9, 0x86, 0x82, 0x94, + 0xa4, 0xf9, 0xe2, 0x7b, 0x42, 0xaf, 0x81, 0x00, + 0xcb, 0x9d, 0x59, 0xce, 0xf9, 0x64, 0x58, 0x03, +}; + + +/* Vector 12 */ +static const uint8_t ciph_data_aes_xts_vect12_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, +}; +static const uint8_t ciph_data_aes_xts_vect12_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, +}; +static const uint8_t ciph_data_aes_xts_vect12_iv[16] = { + 0xff, 0xff, 0xff +}; +static const uint8_t ciph_data_aes_xts_vect12_ptx[] = { + 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, +}; +static const uint8_t ciph_data_aes_xts_vect12_ctx[] = { + 0xe3, 0x87, 0xaa, 0xa5, 0x8b, 0xa4, 0x83, 0xaf, + 0xa7, 0xe8, 0xeb, 0x46, 0x97, 0x78, 0x31, 0x7e, + 0xcf, 0x4c, 0xf5, 0x73, 0xaa, 0x9d, 0x4e, 0xac, + 0x23, 0xf2, 0xcd, 0xf9, 0x14, 0xe4, 0xe2, 0x00, + + 0xa8, 0xb4, 0x90, 0xe4, 0x2e, 0xe6, 0x46, 0x80, + 0x2d, 0xc6, 0xee, 0x2b, 0x47, 0x1b, 0x27, 0x81, + 0x95, 0xd6, 0x09, 0x18, 0xec, 0xec, 0xb4, 0x4b, + 0xf7, 0x99, 0x66, 0xf8, 0x3f, 0xab, 0xa0, 0x49, + + 0x92, 0x98, 0xeb, 0xc6, 0x99, 0xc0, 0xc8, 0x63, + 0x47, 0x15, 0xa3, 0x20, 0xbb, 0x4f, 0x07, 0x5d, + 0x62, 0x2e, 0x74, 0xc8, 0xc9, 0x32, 0x00, 0x4f, + 0x25, 0xb4, 0x1e, 0x36, 0x10, 0x25, 0xb5, 0xa8, + + 0x78, 0x15, 0x39, 0x1f, 0x61, 0x08, 0xfc, 0x4a, + 0xfa, 0x6a, 0x05, 0xd9, 0x30, 0x3c, 0x6b, 0xa6, + 0x8a, 0x12, 0x8a, 0x55, 0x70, 0x5d, 0x41, 0x59, + 0x85, 0x83, 0x2f, 0xde, 0xaa, 0xe6, 0xc8, 0xe1, + + 0x91, 0x10, 0xe8, 0x4d, 0x1b, 0x1f, 0x19, 0x9a, + 0x26, 0x92, 0x11, 0x9e, 0xdc, 0x96, 0x13, 0x26, + 0x58, 0xf0, 0x9d, 0xa7, 0xc6, 0x23, 0xef, 0xce, + 0xc7, 0x12, 0x53, 0x7a, 0x3d, 0x94, 0xc0, 0xbf, + + 0x5d, 0x7e, 0x35, 0x2e, 0xc9, 0x4a, 0xe5, 0x79, + 0x7f, 0xdb, 0x37, 0x7d, 0xc1, 0x55, 0x11, 0x50, + 0x72, 0x1a, 0xdf, 0x15, 0xbd, 0x26, 0xa8, 0xef, + 0xc2, 0xfc, 0xaa, 0xd5, 0x68, 0x81, 0xfa, 0x9e, + + 0x62, 0x46, 0x2c, 0x28, 0xf3, 0x0a, 0xe1, 0xce, + 0xac, 0xa9, 0x3c, 0x34, 0x5c, 0xf2, 0x43, 0xb7, + 0x3f, 0x54, 0x2e, 0x20, 0x74, 0xa7, 0x05, 0xbd, + 0x26, 0x43, 0xbb, 0x9f, 0x7c, 0xc7, 0x9b, 0xb6, + + 0xe7, 0x09, 0x1e, 0xa6, 0xe2, 0x32, 0xdf, 0x0f, + 0x9a, 0xd0, 0xd6, 0xcf, 0x50, 0x23, 0x27, 0x87, + 0x6d, 0x82, 0x20, 0x7a, 0xbf, 0x21, 0x15, 0xcd, + 0xac, 0xf6, 0xd5, 0xa4, 0x8f, 0x6c, 0x18, 0x79, + + 0xa6, 0x5b, 0x11, 0x5f, 0x0f, 0x8b, 0x3c, 0xb3, + 0xc5, 0x9d, 0x15, 0xdd, 0x8c, 0x76, 0x9b, 0xc0, + 0x14, 0x79, 0x5a, 0x18, 0x37, 0xf3, 0x90, 0x1b, + 0x58, 0x45, 0xeb, 0x49, 0x1a, 0xdf, 0xef, 0xe0, + + 0x97, 0xb1, 0xfa, 0x30, 0xa1, 0x2f, 0xc1, 0xf6, + 0x5b, 0xa2, 0x29, 0x05, 0x03, 0x15, 0x39, 0x97, + 0x1a, 0x10, 0xf2, 0xf3, 0x6c, 0x32, 0x1b, 0xb5, + 0x13, 0x31, 0xcd, 0xef, 0xb3, 0x9e, 0x39, 0x64, + + 0xc7, 0xef, 0x07, 0x99, 0x94, 0xf5, 0xb6, 0x9b, + 0x2e, 0xdd, 0x83, 0xa7, 0x1e, 0xf5, 0x49, 0x97, + 0x1e, 0xe9, 0x3f, 0x44, 0xea, 0xc3, 0x93, 0x8f, + 0xcd, 0xd6, 0x1d, 0x01, 0xfa, 0x71, 0x79, 0x9d, + + 0xa3, 0xa8, 0x09, 0x1c, 0x4c, 0x48, 0xaa, 0x9e, + 0xd2, 0x63, 0xff, 0x07, 0x49, 0xdf, 0x95, 0xd4, + 0x4f, 0xef, 0x6a, 0x0b, 0xb5, 0x78, 0xec, 0x69, + 0x45, 0x6a, 0xa5, 0x40, 0x8a, 0xe3, 0x2c, 0x7a, + + 0xf0, 0x8a, 0xd7, 0xba, 0x89, 0x21, 0x28, 0x7e, + 0x3b, 0xbe, 0xe3, 0x1b, 0x76, 0x7b, 0xe0, 0x6a, + 0x0e, 0x70, 0x5c, 0x86, 0x4a, 0x76, 0x91, 0x37, + 0xdf, 0x28, 0x29, 0x22, 0x83, 0xea, 0x81, 0xa2, + + 0x48, 0x02, 0x41, 0xb4, 0x4d, 0x99, 0x21, 0xcd, + 0xbe, 0xc1, 0xbc, 0x28, 0xdc, 0x1f, 0xda, 0x11, + 0x4b, 0xd8, 0xe5, 0x21, 0x7a, 0xc9, 0xd8, 0xeb, + 0xaf, 0xa7, 0x20, 0xe9, 0xda, 0x4f, 0x9a, 0xce, + + 0x23, 0x1c, 0xc9, 0x49, 0xe5, 0xb9, 0x6f, 0xe7, + 0x6f, 0xfc, 0x21, 0x06, 0x3f, 0xdd, 0xc8, 0x3a, + 0x6b, 0x86, 0x79, 0xc0, 0x0d, 0x35, 0xe0, 0x95, + 0x76, 0xa8, 0x75, 0x30, 0x5b, 0xed, 0x5f, 0x36, + + 0xed, 0x24, 0x2c, 0x89, 0x00, 0xdd, 0x1f, 0xa9, + 0x65, 0xbc, 0x95, 0x0d, 0xfc, 0xe0, 0x9b, 0x13, + 0x22, 0x63, 0xa1, 0xee, 0xf5, 0x2d, 0xd6, 0x88, + 0x8c, 0x30, 0x9f, 0x5a, 0x7d, 0x71, 0x28, 0x26, +}; + +/* Vector 13 */ +static const uint8_t ciph_data_aes_xts_vect13_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, +}; +static const uint8_t ciph_data_aes_xts_vect13_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, +}; +static const uint8_t ciph_data_aes_xts_vect13_iv[16] = { + 0xff, 0xff, 0xff, 0xff +}; +static const uint8_t ciph_data_aes_xts_vect13_ptx[] = { + 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, +}; +static const uint8_t ciph_data_aes_xts_vect13_ctx[] = { + 0xbf, 0x53, 0xd2, 0xda, 0xde, 0x78, 0xe8, 0x22, + 0xa4, 0xd9, 0x49, 0xa9, 0xbc, 0x67, 0x66, 0xb0, + 0x1b, 0x06, 0xa8, 0xef, 0x70, 0xd2, 0x67, 0x48, + 0xc6, 0xa7, 0xfc, 0x36, 0xd8, 0x0a, 0xe4, 0xc5, + + 0x52, 0x0f, 0x7c, 0x4a, 0xb0, 0xac, 0x85, 0x44, + 0x42, 0x4f, 0xa4, 0x05, 0x16, 0x2f, 0xef, 0x5a, + 0x6b, 0x7f, 0x22, 0x94, 0x98, 0x06, 0x36, 0x18, + 0xd3, 0x9f, 0x00, 0x03, 0xcb, 0x5f, 0xb8, 0xd1, + + 0xc8, 0x6b, 0x64, 0x34, 0x97, 0xda, 0x1f, 0xf9, + 0x45, 0xc8, 0xd3, 0xbe, 0xde, 0xca, 0x4f, 0x47, + 0x97, 0x02, 0xa7, 0xa7, 0x35, 0xf0, 0x43, 0xdd, + 0xb1, 0xd6, 0xaa, 0xad, 0xe3, 0xc4, 0xa0, 0xac, + + 0x7c, 0xa7, 0xf3, 0xfa, 0x52, 0x79, 0xbe, 0xf5, + 0x6f, 0x82, 0xcd, 0x7a, 0x2f, 0x38, 0x67, 0x2e, + 0x82, 0x48, 0x14, 0xe1, 0x07, 0x00, 0x30, 0x0a, + 0x05, 0x5e, 0x16, 0x30, 0xb8, 0xf1, 0xcb, 0x0e, + + 0x91, 0x9f, 0x5e, 0x94, 0x20, 0x10, 0xa4, 0x16, + 0xe2, 0xbf, 0x48, 0xcb, 0x46, 0x99, 0x3d, 0x3c, + 0xb6, 0xa5, 0x1c, 0x19, 0xba, 0xcf, 0x86, 0x47, + 0x85, 0xa0, 0x0b, 0xc2, 0xec, 0xff, 0x15, 0xd3, + + 0x50, 0x87, 0x5b, 0x24, 0x6e, 0xd5, 0x3e, 0x68, + 0xbe, 0x6f, 0x55, 0xbd, 0x7e, 0x05, 0xcf, 0xc2, + 0xb2, 0xed, 0x64, 0x32, 0x19, 0x8a, 0x64, 0x44, + 0xb6, 0xd8, 0xc2, 0x47, 0xfa, 0xb9, 0x41, 0xf5, + + 0x69, 0x76, 0x8b, 0x5c, 0x42, 0x93, 0x66, 0xf1, + 0xd3, 0xf0, 0x0f, 0x03, 0x45, 0xb9, 0x61, 0x23, + 0xd5, 0x62, 0x04, 0xc0, 0x1c, 0x63, 0xb2, 0x2c, + 0xe7, 0x8b, 0xaf, 0x11, 0x6e, 0x52, 0x5e, 0xd9, + + 0x0f, 0xde, 0xa3, 0x9f, 0xa4, 0x69, 0x49, 0x4d, + 0x38, 0x66, 0xc3, 0x1e, 0x05, 0xf2, 0x95, 0xff, + 0x21, 0xfe, 0xa8, 0xd4, 0xe6, 0xe1, 0x3d, 0x67, + 0xe4, 0x7c, 0xe7, 0x22, 0xe9, 0x69, 0x8a, 0x1c, + + 0x10, 0x48, 0xd6, 0x8e, 0xbc, 0xde, 0x76, 0xb8, + 0x6f, 0xcf, 0x97, 0x6e, 0xab, 0x8a, 0xa9, 0x79, + 0x02, 0x68, 0xb7, 0x06, 0x8e, 0x01, 0x7a, 0x8b, + 0x9b, 0x74, 0x94, 0x09, 0x51, 0x4f, 0x10, 0x53, + + 0x02, 0x7f, 0xd1, 0x6c, 0x37, 0x86, 0xea, 0x1b, + 0xac, 0x5f, 0x15, 0xcb, 0x79, 0x71, 0x1e, 0xe2, + 0xab, 0xe8, 0x2f, 0x5c, 0xf8, 0xb1, 0x3a, 0xe7, + 0x30, 0x30, 0xef, 0x5b, 0x9e, 0x44, 0x57, 0xe7, + + 0x5d, 0x13, 0x04, 0xf9, 0x88, 0xd6, 0x2d, 0xd6, + 0xfc, 0x4b, 0x94, 0xed, 0x38, 0xba, 0x83, 0x1d, + 0xa4, 0xb7, 0x63, 0x49, 0x71, 0xb6, 0xcd, 0x8e, + 0xc3, 0x25, 0xd9, 0xc6, 0x1c, 0x00, 0xf1, 0xdf, + + 0x73, 0x62, 0x7e, 0xd3, 0x74, 0x5a, 0x5e, 0x84, + 0x89, 0xf3, 0xa9, 0x5c, 0x69, 0x63, 0x9c, 0x32, + 0xcd, 0x6e, 0x1d, 0x53, 0x7a, 0x85, 0xf7, 0x5c, + 0xc8, 0x44, 0x72, 0x6e, 0x8a, 0x72, 0xfc, 0x00, + + 0x77, 0xad, 0x22, 0x00, 0x0f, 0x1d, 0x50, 0x78, + 0xf6, 0xb8, 0x66, 0x31, 0x8c, 0x66, 0x8f, 0x1a, + 0xd0, 0x3d, 0x5a, 0x5f, 0xce, 0xd5, 0x21, 0x9f, + 0x2e, 0xab, 0xbd, 0x0a, 0xa5, 0xc0, 0xf4, 0x60, + + 0xd1, 0x83, 0xf0, 0x44, 0x04, 0xa0, 0xd6, 0xf4, + 0x69, 0x55, 0x8e, 0x81, 0xfa, 0xb2, 0x4a, 0x16, + 0x79, 0x05, 0xab, 0x4c, 0x78, 0x78, 0x50, 0x2a, + 0xd3, 0xe3, 0x8f, 0xdb, 0xe6, 0x2a, 0x41, 0x55, + + 0x6c, 0xec, 0x37, 0x32, 0x57, 0x59, 0x53, 0x3c, + 0xe8, 0xf2, 0x5f, 0x36, 0x7c, 0x87, 0xbb, 0x55, + 0x78, 0xd6, 0x67, 0xae, 0x93, 0xf9, 0xe2, 0xfd, + 0x99, 0xbc, 0xbc, 0x5f, 0x2f, 0xbb, 0xa8, 0x8c, + + 0xf6, 0x51, 0x61, 0x39, 0x42, 0x0f, 0xcf, 0xf3, + 0xb7, 0x36, 0x1d, 0x86, 0x32, 0x2c, 0x4b, 0xd8, + 0x4c, 0x82, 0xf3, 0x35, 0xab, 0xb1, 0x52, 0xc4, + 0xa9, 0x34, 0x11, 0x37, 0x3a, 0xaa, 0x82, 0x20, +}; + +/* Vector 14 */ +static const uint8_t ciph_data_aes_xts_vect14_key1[] = { + 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, + 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, + 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, + 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27, +}; +static const uint8_t ciph_data_aes_xts_vect14_key2[] = { + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, + 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, + 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, + 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92, +}; +static const uint8_t ciph_data_aes_xts_vect14_iv[16] = { + 0xff, 0xff, 0xff, 0xff, 0xff +}; +static const uint8_t ciph_data_aes_xts_vect14_ptx[] = { + 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, +}; +static const uint8_t ciph_data_aes_xts_vect14_ctx[] = { + 0x64, 0x49, 0x7e, 0x5a, 0x83, 0x1e, 0x4a, 0x93, + 0x2c, 0x09, 0xbe, 0x3e, 0x53, 0x93, 0x37, 0x6d, + 0xaa, 0x59, 0x95, 0x48, 0xb8, 0x16, 0x03, 0x1d, + 0x22, 0x4b, 0xbf, 0x50, 0xa8, 0x18, 0xed, 0x23, + + 0x50, 0xea, 0xe7, 0xe9, 0x60, 0x87, 0xc8, 0xa0, + 0xdb, 0x51, 0xad, 0x29, 0x0b, 0xd0, 0x0c, 0x1a, + 0xc1, 0x62, 0x08, 0x57, 0x63, 0x5b, 0xf2, 0x46, + 0xc1, 0x76, 0xab, 0x46, 0x3b, 0xe3, 0x0b, 0x80, + + 0x8d, 0xa5, 0x48, 0x08, 0x1a, 0xc8, 0x47, 0xb1, + 0x58, 0xe1, 0x26, 0x4b, 0xe2, 0x5b, 0xb0, 0x91, + 0x0b, 0xbc, 0x92, 0x64, 0x71, 0x08, 0x08, 0x94, + 0x15, 0xd4, 0x5f, 0xab, 0x1b, 0x3d, 0x26, 0x04, + + 0xe8, 0xa8, 0xef, 0xf1, 0xae, 0x40, 0x20, 0xcf, + 0xa3, 0x99, 0x36, 0xb6, 0x68, 0x27, 0xb2, 0x3f, + 0x37, 0x1b, 0x92, 0x20, 0x0b, 0xe9, 0x02, 0x51, + 0xe6, 0xd7, 0x3c, 0x5f, 0x86, 0xde, 0x5f, 0xd4, + + 0xa9, 0x50, 0x78, 0x19, 0x33, 0xd7, 0x9a, 0x28, + 0x27, 0x2b, 0x78, 0x2a, 0x2e, 0xc3, 0x13, 0xef, + 0xdf, 0xcc, 0x06, 0x28, 0xf4, 0x3d, 0x74, 0x4c, + 0x2d, 0xc2, 0xff, 0x3d, 0xcb, 0x66, 0x99, 0x9b, + + 0x50, 0xc7, 0xca, 0x89, 0x5b, 0x0c, 0x64, 0x79, + 0x1e, 0xea, 0xa5, 0xf2, 0x94, 0x99, 0xfb, 0x1c, + 0x02, 0x6f, 0x84, 0xce, 0x5b, 0x5c, 0x72, 0xba, + 0x10, 0x83, 0xcd, 0xdb, 0x5c, 0xe4, 0x54, 0x34, + + 0x63, 0x16, 0x65, 0xc3, 0x33, 0xb6, 0x0b, 0x11, + 0x59, 0x3f, 0xb2, 0x53, 0xc5, 0x17, 0x9a, 0x2c, + 0x8d, 0xb8, 0x13, 0x78, 0x2a, 0x00, 0x48, 0x56, + 0xa1, 0x65, 0x30, 0x11, 0xe9, 0x3f, 0xb6, 0xd8, + + 0x76, 0xc1, 0x83, 0x66, 0xdd, 0x86, 0x83, 0xf5, + 0x34, 0x12, 0xc0, 0xc1, 0x80, 0xf9, 0xc8, 0x48, + 0x59, 0x2d, 0x59, 0x3f, 0x86, 0x09, 0xca, 0x73, + 0x63, 0x17, 0xd3, 0x56, 0xe1, 0x3e, 0x2b, 0xff, + + 0x3a, 0x9f, 0x59, 0xcd, 0x9a, 0xeb, 0x19, 0xcd, + 0x48, 0x25, 0x93, 0xd8, 0xc4, 0x61, 0x28, 0xbb, + 0x32, 0x42, 0x3b, 0x37, 0xa9, 0xad, 0xfb, 0x48, + 0x2b, 0x99, 0x45, 0x3f, 0xbe, 0x25, 0xa4, 0x1b, + + 0xf6, 0xfe, 0xb4, 0xaa, 0x0b, 0xef, 0x5e, 0xd2, + 0x4b, 0xf7, 0x3c, 0x76, 0x29, 0x78, 0x02, 0x54, + 0x82, 0xc1, 0x31, 0x15, 0xe4, 0x01, 0x5a, 0xac, + 0x99, 0x2e, 0x56, 0x13, 0xa3, 0xb5, 0xc2, 0xf6, + + 0x85, 0xb8, 0x47, 0x95, 0xcb, 0x6e, 0x9b, 0x26, + 0x56, 0xd8, 0xc8, 0x81, 0x57, 0xe5, 0x2c, 0x42, + 0xf9, 0x78, 0xd8, 0x63, 0x4c, 0x43, 0xd0, 0x6f, + 0xea, 0x92, 0x8f, 0x28, 0x22, 0xe4, 0x65, 0xaa, + + 0x65, 0x76, 0xe9, 0xbf, 0x41, 0x93, 0x84, 0x50, + 0x6c, 0xc3, 0xce, 0x3c, 0x54, 0xac, 0x1a, 0x6f, + 0x67, 0xdc, 0x66, 0xf3, 0xb3, 0x01, 0x91, 0xe6, + 0x98, 0x38, 0x0b, 0xc9, 0x99, 0xb0, 0x5a, 0xbc, + + 0xe1, 0x9d, 0xc0, 0xc6, 0xdc, 0xc2, 0xdd, 0x00, + 0x1e, 0xc5, 0x35, 0xba, 0x18, 0xde, 0xb2, 0xdf, + 0x1a, 0x10, 0x10, 0x23, 0x10, 0x83, 0x18, 0xc7, + 0x5d, 0xc9, 0x86, 0x11, 0xa0, 0x9d, 0xc4, 0x8a, + + 0x0a, 0xcd, 0xec, 0x67, 0x6f, 0xab, 0xdf, 0x22, + 0x2f, 0x07, 0xe0, 0x26, 0xf0, 0x59, 0xb6, 0x72, + 0xb5, 0x6e, 0x5c, 0xbc, 0x8e, 0x1d, 0x21, 0xbb, + 0xd8, 0x67, 0xdd, 0x92, 0x72, 0x12, 0x05, 0x46, + + 0x81, 0xd7, 0x0e, 0xa7, 0x37, 0x13, 0x4c, 0xdf, + 0xce, 0x93, 0xb6, 0xf8, 0x2a, 0xe2, 0x24, 0x23, + 0x27, 0x4e, 0x58, 0xa0, 0x82, 0x1c, 0xc5, 0x50, + 0x2e, 0x2d, 0x0a, 0xb4, 0x58, 0x5e, 0x94, 0xde, + + 0x69, 0x75, 0xbe, 0x5e, 0x0b, 0x4e, 0xfc, 0xe5, + 0x1c, 0xd3, 0xe7, 0x0c, 0x25, 0xa1, 0xfb, 0xbb, + 0xd6, 0x09, 0xd2, 0x73, 0xad, 0x5b, 0x0d, 0x59, + 0x63, 0x1c, 0x53, 0x1f, 0x6a, 0x0a, 0x57, 0xb9, +}; + +/* + * XTS-AES-128 applied for a data unit that is not a multiple of 16 bytes + */ + +/* Vector 15 */ +static const uint8_t ciph_data_aes_xts_vect15_key1[] = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, +}; +static const uint8_t ciph_data_aes_xts_vect15_key2[] = { + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, +}; +static const uint8_t ciph_data_aes_xts_vect15_iv[16] = { + 0x9a, 0x78, 0x56, 0x34, 0x12 +}; +static const uint8_t ciph_data_aes_xts_vect15_ptx[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10 +}; +static const uint8_t ciph_data_aes_xts_vect15_ctx[] = { + 0x6c, 0x16, 0x25, 0xdb, 0x46, 0x71, 0x52, 0x2d, + 0x3d, 0x75, 0x99, 0x60, 0x1d, 0xe7, 0xca, 0x09, + 0xed +}; + +/* Vector 16 */ +static const uint8_t ciph_data_aes_xts_vect16_key1[] = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, +}; +static const uint8_t ciph_data_aes_xts_vect16_key2[] = { + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, +}; +static const uint8_t ciph_data_aes_xts_vect16_iv[16] = { + 0x9a, 0x78, 0x56, 0x34, 0x12 +}; +static const uint8_t ciph_data_aes_xts_vect16_ptx[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11 +}; +static const uint8_t ciph_data_aes_xts_vect16_ctx[] = { + 0xd0, 0x69, 0x44, 0x4b, 0x7a, 0x7e, 0x0c, 0xab, + 0x09, 0xe2, 0x44, 0x47, 0xd2, 0x4d, 0xeb, 0x1f, + 0xed, 0xbf +}; + +/* Vector 17 */ +static const uint8_t ciph_data_aes_xts_vect17_key1[] = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, +}; +static const uint8_t ciph_data_aes_xts_vect17_key2[] = { + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, +}; +static const uint8_t ciph_data_aes_xts_vect17_iv[16] = { + 0x9a, 0x78, 0x56, 0x34, 0x12 +}; +static const uint8_t ciph_data_aes_xts_vect17_ptx[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12 +}; +static const uint8_t ciph_data_aes_xts_vect17_ctx[] = { + 0xe5, 0xdf, 0x13, 0x51, 0xc0, 0x54, 0x4b, 0xa1, + 0x35, 0x0b, 0x33, 0x63, 0xcd, 0x8e, 0xf4, 0xbe, + 0xed, 0xbf, 0x9d +}; + +/* Vector 18 */ +static const uint8_t ciph_data_aes_xts_vect18_key1[] = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, +}; +static const uint8_t ciph_data_aes_xts_vect18_key2[] = { + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, +}; +static const uint8_t ciph_data_aes_xts_vect18_iv[16] = { + 0x9a, 0x78, 0x56, 0x34, 0x12 +}; +static const uint8_t ciph_data_aes_xts_vect18_ptx[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; +static const uint8_t ciph_data_aes_xts_vect18_ctx[] = { + 0x9d, 0x84, 0xc8, 0x13, 0xf7, 0x19, 0xaa, 0x2c, + 0x7b, 0xe3, 0xf6, 0x61, 0x71, 0xc7, 0xc5, 0xc2, + 0xed, 0xbf, 0x9d, 0xac +}; + +/* Vector 19 */ +static const uint8_t ciph_data_aes_xts_vect19_key1[] = { + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, +}; +static const uint8_t ciph_data_aes_xts_vect19_key2[] = { + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, +}; +static const uint8_t ciph_data_aes_xts_vect19_iv[16] = { + 0x21, 0x43, 0x65, 0x87, 0xa9 +}; +static const uint8_t ciph_data_aes_xts_vect19_ptx[] = { + 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, +}; +static const uint8_t ciph_data_aes_xts_vect19_ctx[] = { + 0x38, 0xb4, 0x58, 0x12, 0xef, 0x43, 0xa0, 0x5b, + 0xd9, 0x57, 0xe5, 0x45, 0x90, 0x7e, 0x22, 0x3b, + 0x95, 0x4a, 0xb4, 0xaa, 0xf0, 0x88, 0x30, 0x3a, + 0xd9, 0x10, 0xea, 0xdf, 0x14, 0xb4, 0x2b, 0xe6, + + 0x8b, 0x24, 0x61, 0x14, 0x9d, 0x8c, 0x8b, 0xa8, + 0x5f, 0x99, 0x2b, 0xe9, 0x70, 0xbc, 0x62, 0x1f, + 0x1b, 0x06, 0x57, 0x3f, 0x63, 0xe8, 0x67, 0xbf, + 0x58, 0x75, 0xac, 0xaf, 0xa0, 0x4e, 0x42, 0xcc, + + 0xbd, 0x7b, 0xd3, 0xc2, 0xa0, 0xfb, 0x1f, 0xff, + 0x79, 0x1e, 0xc5, 0xec, 0x36, 0xc6, 0x6a, 0xe4, + 0xac, 0x1e, 0x80, 0x6d, 0x81, 0xfb, 0xf7, 0x09, + 0xdb, 0xe2, 0x9e, 0x47, 0x1f, 0xad, 0x38, 0x54, + + 0x9c, 0x8e, 0x66, 0xf5, 0x34, 0x5d, 0x7c, 0x1e, + 0xb9, 0x4f, 0x40, 0x5d, 0x1e, 0xc7, 0x85, 0xcc, + 0x6f, 0x6a, 0x68, 0xf6, 0x25, 0x4d, 0xd8, 0x33, + 0x9f, 0x9d, 0x84, 0x05, 0x7e, 0x01, 0xa1, 0x77, + + 0x41, 0x99, 0x04, 0x82, 0x99, 0x95, 0x16, 0xb5, + 0x61, 0x1a, 0x38, 0xf4, 0x1b, 0xb6, 0x47, 0x8e, + 0x6f, 0x17, 0x3f, 0x32, 0x08, 0x05, 0xdd, 0x71, + 0xb1, 0x93, 0x2f, 0xc3, 0x33, 0xcb, 0x9e, 0xe3, + + 0x99, 0x36, 0xbe, 0xea, 0x9a, 0xd9, 0x6f, 0xa1, + 0x0f, 0xb4, 0x11, 0x2b, 0x90, 0x17, 0x34, 0xdd, + 0xad, 0x40, 0xbc, 0x18, 0x78, 0x99, 0x5f, 0x8e, + 0x11, 0xae, 0xe7, 0xd1, 0x41, 0xa2, 0xf5, 0xd4, + + 0x8b, 0x7a, 0x4e, 0x1e, 0x7f, 0x0b, 0x2c, 0x04, + 0x83, 0x0e, 0x69, 0xa4, 0xfd, 0x13, 0x78, 0x41, + 0x1c, 0x2f, 0x28, 0x7e, 0xdf, 0x48, 0xc6, 0xc4, + 0xe5, 0xc2, 0x47, 0xa1, 0x96, 0x80, 0xf7, 0xfe, + + 0x41, 0xce, 0xfb, 0xd4, 0x9b, 0x58, 0x21, 0x06, + 0xe3, 0x61, 0x6c, 0xbb, 0xe4, 0xdf, 0xb2, 0x34, + 0x4b, 0x2a, 0xe9, 0x51, 0x93, 0x91, 0xf3, 0xe0, + 0xfb, 0x49, 0x22, 0x25, 0x4b, 0x1d, 0x6d, 0x2d, + + 0x19, 0xc6, 0xd4, 0xd5, 0x37, 0xb3, 0xa2, 0x6f, + 0x3b, 0xcc, 0x51, 0x58, 0x8b, 0x32, 0xf3, 0xec, + 0xa0, 0x82, 0x9b, 0x6a, 0x5a, 0xc7, 0x25, 0x78, + 0xfb, 0x81, 0x4f, 0xb4, 0x3c, 0xf8, 0x0d, 0x64, + + 0xa2, 0x33, 0xe3, 0xf9, 0x97, 0xa3, 0xf0, 0x26, + 0x83, 0x34, 0x2f, 0x2b, 0x33, 0xd2, 0x5b, 0x49, + 0x25, 0x36, 0xb9, 0x3b, 0xec, 0xb2, 0xf5, 0xe1, + 0xa8, 0xb8, 0x2f, 0x5b, 0x88, 0x33, 0x42, 0x72, + + 0x9e, 0x8a, 0xe0, 0x9d, 0x16, 0x93, 0x88, 0x41, + 0xa2, 0x1a, 0x97, 0xfb, 0x54, 0x3e, 0xea, 0x3b, + 0xbf, 0xf5, 0x9f, 0x13, 0xc1, 0xa1, 0x84, 0x49, + 0xe3, 0x98, 0x70, 0x1c, 0x1a, 0xd5, 0x16, 0x48, + + 0x34, 0x6c, 0xbc, 0x04, 0xc2, 0x7b, 0xb2, 0xda, + 0x3b, 0x93, 0xa1, 0x37, 0x2c, 0xca, 0xe5, 0x48, + 0xfb, 0x53, 0xbe, 0xe4, 0x76, 0xf9, 0xe9, 0xc9, + 0x17, 0x73, 0xb1, 0xbb, 0x19, 0x82, 0x83, 0x94, + + 0xd5, 0x5d, 0x3e, 0x1a, 0x20, 0xed, 0x69, 0x11, + 0x3a, 0x86, 0x0b, 0x68, 0x29, 0xff, 0xa8, 0x47, + 0x22, 0x46, 0x04, 0x43, 0x50, 0x70, 0x22, 0x1b, + 0x25, 0x7e, 0x8d, 0xff, 0x78, 0x36, 0x15, 0xd2, + + 0xca, 0xe4, 0x80, 0x3a, 0x93, 0xaa, 0x43, 0x34, + 0xab, 0x48, 0x2a, 0x0a, 0xfa, 0xc9, 0xc0, 0xae, + 0xda, 0x70, 0xb4, 0x5a, 0x48, 0x1d, 0xf5, 0xde, + 0xc5, 0xdf, 0x8c, 0xc0, 0xf4, 0x23, 0xc7, 0x7a, + + 0x5f, 0xd4, 0x6c, 0xd3, 0x12, 0x02, 0x1d, 0x4b, + 0x43, 0x88, 0x62, 0x41, 0x9a, 0x79, 0x1b, 0xe0, + 0x3b, 0xb4, 0xd9, 0x7c, 0x0e, 0x59, 0x57, 0x85, + 0x42, 0x53, 0x1b, 0xa4, 0x66, 0xa8, 0x3b, 0xaf, + + 0x92, 0xce, 0xfc, 0x15, 0x1b, 0x5c, 0xc1, 0x61, + 0x1a, 0x16, 0x78, 0x93, 0x81, 0x9b, 0x63, 0xfb, + 0x8a, 0x6b, 0x18, 0xe8, 0x6d, 0xe6, 0x02, 0x90, + 0xfa, 0x72, 0xb7, 0x97, 0xb0, 0xce, 0x59, 0xf3, +}; + +/* AES-CCM test data from NIST Special Publication 800-38C */ + +/* + * Example1: + * K: 40414243 44454647 48494a4b 4c4d4e4f + * N: 10111213 141516 + * A: 00010203 04050607 + * P: 20212223 + * B: 4f101112 13141516 00000000 00000004 + * 00080001 02030405 06070000 00000000 + * 20212223 00000000 00000000 00000000 + * T: 6084341b + * Ctr0: 07101112 13141516 00000000 00000000 + * S0: 2d281146 10676c26 32bad748 559a679a + * Ctr1: 07101112 13141516 00000000 00000001 + * S1: 51432378 e474b339 71318484 103cddfb + * C: 7162015b 4dac255d + */ +static const uint8_t ae_data_aes_ccm_vect1_key[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; +static const uint8_t ae_data_aes_ccm_vect1_nonce[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 +}; +static const uint8_t ae_data_aes_ccm_vect1_aad[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 +}; +static const uint8_t ae_data_aes_ccm_vect1_ptx[] = { + 0x20, 0x21, 0x22, 0x23 +}; +static const uint8_t ae_data_aes_ccm_vect1_ctx[] = { + 0x71, 0x62, 0x01, 0x5b, +}; +static const uint8_t ae_data_aes_ccm_vect1_tag[] = { + 0x4d, 0xac, 0x25, 0x5d +}; + +/* + * Example 2: + * K: 40414243 44454647 48494a4b 4c4d4e4f + * N: 10111213 14151617 + * A: 00010203 04050607 08090a0b 0c0d0e0f + * P: 20212223 24252627 28292a2b 2c2d2e2f + * B: 56101112 13141516 17000000 00000010 + * 00100001 02030405 06070809 0a0b0c0d + * 0e0f0000 00000000 00000000 00000000 + * 20212223 24252627 28292a2b 2c2d2e2f + * T: 7f479ffc a464 + * Ctr0: 06101112 13141516 17000000 00000000 + * S0: 6081d043 08a97dcc 20cdcc60 bf947b78 + * Ctr1: 06101112 13141516 17000000 00000001 + * S1: f280d2c3 75cf7945 20335db9 2b107712 + * C: d2a1f0e0 51ea5f62 081a7792 073d593d + * 1fc64fbf accd + */ +static const uint8_t ae_data_aes_ccm_vect2_key[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; +static const uint8_t ae_data_aes_ccm_vect2_nonce[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 +}; +static const uint8_t ae_data_aes_ccm_vect2_aad[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f +}; +static const uint8_t ae_data_aes_ccm_vect2_ptx[] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f +}; +static const uint8_t ae_data_aes_ccm_vect2_ctx[] = { + 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, + 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, +}; +static const uint8_t ae_data_aes_ccm_vect2_tag[] = { + 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd +}; + +/* + * Example 3 + * K: 40414243 44454647 48494a4b 4c4d4e4f + * N: 10111213 14151617 18191a1b + * A: 00010203 04050607 08090a0b 0c0d0e0f + * 10111213 + * P: 20212223 24252627 28292a2b 2c2d2e2f + * 30313233 34353637 + * B: 5a101112 13141516 1718191a 1b000018 + * 00140001 02030405 06070809 0a0b0c0d + * 0e0f1011 12130000 00000000 00000000 + * 20212223 24252627 28292a2b 2c2d2e2f + * 30313233 34353637 00000000 00000000 + * T: 67c99240 c7d51048 + * Ctr0: 02101112 13141516 1718191a 1b000000 + * S0: 2f8a00bb 06658919 c3a040a6 eaed1a7f + * Ctr1: 02101112 13141516 1718191a 1b000001 + * S1: c393238a d1923c5d b335c0c7 e1bac924 + * Ctr2: 02101112 13141516 1718191a 1b000002 + * S2: 514798ea 9077bc92 6c22ebef 2ac732dc + * C: e3b201a9 f5b71a7a 9b1ceaec cd97e70b + * 6176aad9 a4428aa5 484392fb c1b09951 + */ +static const uint8_t ae_data_aes_ccm_vect3_key[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; +static const uint8_t ae_data_aes_ccm_vect3_nonce[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b +}; +static const uint8_t ae_data_aes_ccm_vect3_aad[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; +static const uint8_t ae_data_aes_ccm_vect3_ptx[] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 +}; +static const uint8_t ae_data_aes_ccm_vect3_ctx[] = { + 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, + 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, + 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, +}; +static const uint8_t ae_data_aes_ccm_vect3_tag[] = { + 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 +}; + +/* + * AES-GCM vectors from the reviced "The Galois/Counter Mode of Operation + * (GCM)" 2005-05-31 spec + */ + +/* + * Test case 1 + * K 00000000000000000000000000000000 + * P + * IV 000000000000000000000000 + * H 66e94bd4ef8a2c3b884cfa59ca342b2e + * Y0 00000000000000000000000000000001 + * E(K, Y0) 58e2fccefa7e3061367f1d57a4e7455a + * len(A)||len(C) 00000000000000000000000000000000 + * GHASH(H, A, C) 00000000000000000000000000000000 + * C + * T 58e2fccefa7e3061367f1d57a4e7455a + */ +static const uint8_t ae_data_aes_gcm_vect1_key[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const uint8_t ae_data_aes_gcm_vect1_nonce[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +#define ae_data_aes_gcm_vect1_aad NULL +#define ae_data_aes_gcm_vect1_ptx NULL +#define ae_data_aes_gcm_vect1_ctx NULL +static const uint8_t ae_data_aes_gcm_vect1_tag[] = { + 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a +}; + +/* + * Test case 2 + * K 00000000000000000000000000000000 + * P 00000000000000000000000000000000 + * IV 000000000000000000000000 + * H 66e94bd4ef8a2c3b884cfa59ca342b2e + * Y0 00000000000000000000000000000001 + * E(K, Y0) 58e2fccefa7e3061367f1d57a4e7455a + * Y1 00000000000000000000000000000002 + * E(K, Y1) 0388dace60b6a392f328c2b971b2fe78 + * X1 5e2ec746917062882c85b0685353deb7 + * len(A)||len(C) 00000000000000000000000000000080 + * GHASH(H, A, C) f38cbb1ad69223dcc3457ae5b6b0f885 + * C 0388dace60b6a392f328c2b971b2fe78 + * T ab6e47d42cec13bdf53a67b21257bddf + */ + +static const uint8_t ae_data_aes_gcm_vect2_key[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const uint8_t ae_data_aes_gcm_vect2_nonce[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; +#define ae_data_aes_gcm_vect2_aad NULL +static const uint8_t ae_data_aes_gcm_vect2_ptx[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static const uint8_t ae_data_aes_gcm_vect2_ctx[] = { + 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 +}; +static const uint8_t ae_data_aes_gcm_vect2_tag[] = { + 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf +}; + +/* + * Test case 3 + * K feffe9928665731c6d6a8f9467308308 + * P d9313225f88406e5a55909c5aff5269a + * 86a7a9531534f7da2e4c303d8a318a72 + * 1c3c0c95956809532fcf0e2449a6b525 + * b16aedf5aa0de657ba637b391aafd255 + * IV cafebabefacedbaddecaf888 + * H b83b533708bf535d0aa6e52980d53b78 + * Y0 cafebabefacedbaddecaf88800000001 + * E(K, Y0) 3247184b3c4f69a44dbcd22887bbb418 + * Y1 cafebabefacedbaddecaf88800000002 + * E(K, Y1) 9bb22ce7d9f372c1ee2b28722b25f206 + * Y2 cafebabefacedbaddecaf88800000003 + * E(K, Y2) 650d887c3936533a1b8d4e1ea39d2b5c + * Y3 cafebabefacedbaddecaf88800000004 + * E(K, Y3) 3de91827c10e9a4f5240647ee5221f20 + * Y4 cafebabefacedbaddecaf88800000005 + * E(K, Y4) aac9e6ccc0074ac0873b9ba85d908bd0 + * X1 59ed3f2bb1a0aaa07c9f56c6a504647b + * X2 b714c9048389afd9f9bc5c1d4378e052 + * X3 47400c6577b1ee8d8f40b2721e86ff10 + * X4 4796cf49464704b5dd91f159bb1b7f95 + * len(A)||len(C) 00000000000000000000000000000200 + * GHASH(H, A, C) 7f1b32b81b820d02614f8895ac1d4eac + * C 42831ec2217774244b7221b784d0d49c + * e3aa212f2c02a4e035c17e2329aca12e + * 21d514b25466931c7d8f6a5aac84aa05 + * 1ba30b396a0aac973d58e091473f5985 + * T 4d5c2af327cd64a62cf35abd2ba6fab4 + */ + +static const uint8_t ae_data_aes_gcm_vect3_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 +}; +static const uint8_t ae_data_aes_gcm_vect3_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 +}; +#define ae_data_aes_gcm_vect3_aad NULL +static const uint8_t ae_data_aes_gcm_vect3_ptx[] = { + 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 +}; +static const uint8_t ae_data_aes_gcm_vect3_ctx[] = { + 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 +}; +static const uint8_t ae_data_aes_gcm_vect3_tag[] = { + 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 +}; + +/* + * Test case 4 + * K feffe9928665731c6d6a8f9467308308 + * P d9313225f88406e5a55909c5aff5269a + * 86a7a9531534f7da2e4c303d8a318a72 + * 1c3c0c95956809532fcf0e2449a6b525 + * b16aedf5aa0de657ba637b39 + * A feedfacedeadbeeffeedfacedeadbeef + * abaddad2 + * IV cafebabefacedbaddecaf888 + * H b83b533708bf535d0aa6e52980d53b78 + * Y0 cafebabefacedbaddecaf88800000001 + * E(K, Y0) 3247184b3c4f69a44dbcd22887bbb418 + * X1 ed56aaf8a72d67049fdb9228edba1322 + * X2 cd47221ccef0554ee4bb044c88150352 + * Y1 cafebabefacedbaddecaf88800000002 + * E(K, Y1) 9bb22ce7d9f372c1ee2b28722b25f206 + * Y2 cafebabefacedbaddecaf88800000003 + * E(K, Y2) 650d887c3936533a1b8d4e1ea39d2b5c + * Y3 cafebabefacedbaddecaf88800000004 + * E(K, Y3) 3de91827c10e9a4f5240647ee5221f20 + * Y4 cafebabefacedbaddecaf88800000005 + * E(K, Y4) aac9e6ccc0074ac0873b9ba85d908bd0 + * X3 54f5e1b2b5a8f9525c23924751a3ca51 + * X4 324f585c6ffc1359ab371565d6c45f93 + * X5 ca7dd446af4aa70cc3c0cd5abba6aa1c + * X6 1590df9b2eb6768289e57d56274c8570 + * len(A)||len(C) 00000000000000a000000000000001e0 + * GHASH(H, A, C) 698e57f70e6ecc7fd9463b7260a9ae5f + * C 42831ec2217774244b7221b784d0d49c + * e3aa212f2c02a4e035c17e2329aca12e + * 21d514b25466931c7d8f6a5aac84aa05 + * 1ba30b396a0aac973d58e091 + * T 5bc94fbc3221a5db94fae95ae7121a47 + */ + +static const uint8_t ae_data_aes_gcm_vect4_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 +}; +static const uint8_t ae_data_aes_gcm_vect4_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 +}; +static const uint8_t ae_data_aes_gcm_vect4_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 +}; +static const uint8_t ae_data_aes_gcm_vect4_ptx[] = { + 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 +}; +static const uint8_t ae_data_aes_gcm_vect4_ctx[] = { + 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 +}; +static const uint8_t ae_data_aes_gcm_vect4_tag[] = { + 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 +}; + +/* + * Test case 5 + * K feffe9928665731c6d6a8f9467308308 + * P d9313225f88406e5a55909c5aff5269a + * 86a7a9531534f7da2e4c303d8a318a72 + * 1c3c0c95956809532fcf0e2449a6b525 + * b16aedf5aa0de657ba637b39 + * A feedfacedeadbeeffeedfacedeadbeef + * abaddad2 + * IV cafebabefacedbad + * H b83b533708bf535d0aa6e52980d53b78 + * N1 6f288b846e5fed9a18376829c86a6a16 + * len({})||len(IV ) 00000000000000000000000000000040 + * Y0 c43a83c4c4badec4354ca984db252f7d + * E(K, Y0) e94ab9535c72bea9e089c93d48e62fb0 + * X1 ed56aaf8a72d67049fdb9228edba1322 + * X2 cd47221ccef0554ee4bb044c88150352 + * Y1 c43a83c4c4badec4354ca984db252f7e + * E(K, Y1) b8040969d08295afd226fcda0ddf61cf + * Y2 c43a83c4c4badec4354ca984db252f7f + * E(K, Y2) ef3c83225af93122192ad5c4f15dfe51 + * Y3 c43a83c4c4badec4354ca984db252f80 + * E(K, Y3) 6fbc659571f72de104c67b609d2fde67 + * Y4 c43a83c4c4badec4354ca984db252f81 + * E(K, Y4) f8e3581441a1e950785c3ea1430c6fa6 + * X3 9379e2feae14649c86cf2250e3a81916 + * X4 65dde904c92a6b3db877c4817b50a5f4 + * X5 48c53cf863b49a1b0bbfc48c3baaa89d + * X6 08c873f1c8cec3effc209a07468caab1 + * len(A)||len(C) 00000000000000a000000000000001e0 + * GHASH(H, A, C) df586bb4c249b92cb6922877e444d37b + * C 61353b4c2806934a777ff51fa22a4755 + * 699b2a714fcdc6f83766e5f97b6c7423 + * 73806900e49f24b22b097544d4896b42 + * 4989b5e1ebac0f07c23f4598 + * T 3612d2e79e3b0785561be14aaca2fccb + */ + +static const uint8_t ae_data_aes_gcm_vect5_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 +}; +static const uint8_t ae_data_aes_gcm_vect5_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad +}; +static const uint8_t ae_data_aes_gcm_vect5_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 +}; +static const uint8_t ae_data_aes_gcm_vect5_ptx[] = { + 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 +}; +static const uint8_t ae_data_aes_gcm_vect5_ctx[] = { + 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 +}; +static const uint8_t ae_data_aes_gcm_vect5_tag[] = { + 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb +}; + +/* + * Test case 6 + * K feffe9928665731c6d6a8f9467308308 + * P d9313225f88406e5a55909c5aff5269a + * 86a7a9531534f7da2e4c303d8a318a72 + * 1c3c0c95956809532fcf0e2449a6b525 + * b16aedf5aa0de657ba637b39 + * A feedfacedeadbeeffeedfacedeadbeef + * abaddad2 + * IV 9313225df88406e555909c5aff5269aa + * 6a7a9538534f7da1e4c303d2a318a728 + * c3c0c95156809539fcf0e2429a6b5254 + * 16aedbf5a0de6a57a637b39b + * H b83b533708bf535d0aa6e52980d53b78 + * N1 004d6599d7fb1634756e1e299d81630f + * N2 88ffe8a3c8033df4b54d732f7f88408e + * N3 24e694cfab657beabba8055aad495e23 + * N4 d8349a5eda24943c8fbb2ef5168b20cb + * len({})||len(IV ) 000000000000000000000000000001e0 + * Y0 3bab75780a31c059f83d2a44752f9864 + * E(K, Y0) 7dc63b399f2d98d57ab073b6baa4138e + * X1 ed56aaf8a72d67049fdb9228edba1322 + * X2 cd47221ccef0554ee4bb044c88150352 + * Y1 3bab75780a31c059f83d2a44752f9865 + * E(K, Y1) 55d37bbd9ad21353a6f93a690eca9e0e + * Y2 3bab75780a31c059f83d2a44752f9866 + * E(K, Y2) 3836bbf6d696e672946a1a01404fa6d5 + * Y3 3bab75780a31c059f83d2a44752f9867 + * E(K, Y3) 1dd8a5316ecc35c3e313bca59d2ac94a + * Y4 3bab75780a31c059f83d2a44752f9868 + * E(K, Y4) 6742982706a9f154f657d5dc94b746db + * X3 31727669c63c6f078b5d22adbbbca384 + * X4 480c00db2679065a7ed2f771a53acacd + * X5 1c1ae3c355e2214466a9923d2ba6ab35 + * X6 0694c6f16bb0275a48891d06590344b0 + * len(A)||len(C) 00000000000000a000000000000001e0 + * GHASH(H, A, C) 1c5afe9760d3932f3c9a878aac3dc3de + * C 8ce24998625615b603a033aca13fb894 + * be9112a5c3a211a8ba262a3cca7e2ca7 + * 01e4a9a4fba43c90ccdcb281d48c7c6f + * d62875d2aca417034c34aee5 + * T 619cc5aefffe0bfa462af43c1699d050 + */ + +static const uint8_t ae_data_aes_gcm_vect6_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, +}; +static const uint8_t ae_data_aes_gcm_vect6_nonce[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect6_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, +}; +static const uint8_t ae_data_aes_gcm_vect6_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect6_ctx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect6_tag[] = { + 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, +}; + +/* + * Test case 7 + * K 00000000000000000000000000000000 + * 0000000000000000 + * P + * IV 000000000000000000000000 + * H aae06992acbf52a3e8f4a96ec9300bd7 + * Y0 00000000000000000000000000000001 + * E(K, Y0) cd33b28ac773f74ba00ed1f312572435 + * len(A)||len(C) 00000000000000000000000000000000 + * GHASH(H, A, C) 00000000000000000000000000000000 + * C + * T cd33b28ac773f74ba00ed1f312572435 + */ + +static const uint8_t ae_data_aes_gcm_vect7_key[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const uint8_t ae_data_aes_gcm_vect7_nonce[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +#define ae_data_aes_gcm_vect7_aad NULL +#define ae_data_aes_gcm_vect7_ptx NULL +#define ae_data_aes_gcm_vect7_ctx NULL +static const uint8_t ae_data_aes_gcm_vect7_tag[] = { + 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35, +}; + +/* + * Test case 8 + * K 00000000000000000000000000000000 + * 0000000000000000 + * P 00000000000000000000000000000000 + * IV 000000000000000000000000 + * H aae06992acbf52a3e8f4a96ec9300bd7 + * Y0 00000000000000000000000000000001 + * E(K, Y0) cd33b28ac773f74ba00ed1f312572435 + * Y1 00000000000000000000000000000002 + * E(K, Y1) 98e7247c07f0fe411c267e4384b0f600 + * X1 90e87315fb7d4e1b4092ec0cbfda5d7d + * len(A)||len(C) 00000000000000000000000000000080 + * GHASH(H, A, C) e2c63f0ac44ad0e02efa05ab6743d4ce + * C 98e7247c07f0fe411c267e4384b0f600 + * T 2ff58d80033927ab8ef4d4587514f0fb + */ + +static const uint8_t ae_data_aes_gcm_vect8_key[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const uint8_t ae_data_aes_gcm_vect8_nonce[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +#define ae_data_aes_gcm_vect8_aad NULL +static const uint8_t ae_data_aes_gcm_vect8_ptx[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const uint8_t ae_data_aes_gcm_vect8_ctx[] = { + 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00, +}; +static const uint8_t ae_data_aes_gcm_vect8_tag[] = { + 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb, +}; + +/* Test case 9 */ +static const uint8_t ae_data_aes_gcm_vect9_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, +}; +static const uint8_t ae_data_aes_gcm_vect9_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, +}; +#define ae_data_aes_gcm_vect9_aad NULL +static const uint8_t ae_data_aes_gcm_vect9_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect9_ctx[] = { + 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56, +}; +static const uint8_t ae_data_aes_gcm_vect9_tag[] = { + 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14, +}; + +/* Test case 10 */ +static const uint8_t ae_data_aes_gcm_vect10_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, +}; +static const uint8_t ae_data_aes_gcm_vect10_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, +}; +static const uint8_t ae_data_aes_gcm_vect10_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, +}; +static const uint8_t ae_data_aes_gcm_vect10_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect10_ctx[] = { + 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, +}; +static const uint8_t ae_data_aes_gcm_vect10_tag[] = { + 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c, +}; + +/* Test case 11 */ +static const uint8_t ae_data_aes_gcm_vect11_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, +}; +static const uint8_t ae_data_aes_gcm_vect11_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, +}; +static const uint8_t ae_data_aes_gcm_vect11_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, +}; +static const uint8_t ae_data_aes_gcm_vect11_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect11_ctx[] = { + 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7, +}; +static const uint8_t ae_data_aes_gcm_vect11_tag[] = { + 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8, +}; + +/* Test case 12 */ +static const uint8_t ae_data_aes_gcm_vect12_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, +}; +static const uint8_t ae_data_aes_gcm_vect12_nonce[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect12_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, +}; +static const uint8_t ae_data_aes_gcm_vect12_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect12_ctx[] = { + 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b, +}; +static const uint8_t ae_data_aes_gcm_vect12_tag[] = { + 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9, +}; + +/* Test case 13 */ +static const uint8_t ae_data_aes_gcm_vect13_key[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect13_nonce[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +#define ae_data_aes_gcm_vect13_aad NULL +#define ae_data_aes_gcm_vect13_ptx NULL +#define ae_data_aes_gcm_vect13_ctx NULL +static const uint8_t ae_data_aes_gcm_vect13_tag[] = { + 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b, +}; + +/* Test case 14 */ +static const uint8_t ae_data_aes_gcm_vect14_key[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect14_nonce[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; +#define ae_data_aes_gcm_vect14_aad NULL +static const uint8_t ae_data_aes_gcm_vect14_ptx[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; +static const uint8_t ae_data_aes_gcm_vect14_ctx[] = { + 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18, +}; +static const uint8_t ae_data_aes_gcm_vect14_tag[] = { + 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19, +}; + +/* Test case 15 */ +static const uint8_t ae_data_aes_gcm_vect15_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, +}; +static const uint8_t ae_data_aes_gcm_vect15_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, +}; +#define ae_data_aes_gcm_vect15_aad NULL +static const uint8_t ae_data_aes_gcm_vect15_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect15_ctx[] = { + 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad, +}; +static const uint8_t ae_data_aes_gcm_vect15_tag[] = { + 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c, +}; + +/* Test case 16 */ +static const uint8_t ae_data_aes_gcm_vect16_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, +}; +static const uint8_t ae_data_aes_gcm_vect16_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, +}; +static const uint8_t ae_data_aes_gcm_vect16_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, +}; +static const uint8_t ae_data_aes_gcm_vect16_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect16_ctx[] = { + 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, +}; +static const uint8_t ae_data_aes_gcm_vect16_tag[] = { + 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b, +}; + +/* Test case 17 */ +static const uint8_t ae_data_aes_gcm_vect17_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, +}; +static const uint8_t ae_data_aes_gcm_vect17_nonce[] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, +}; +static const uint8_t ae_data_aes_gcm_vect17_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, +}; +static const uint8_t ae_data_aes_gcm_vect17_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect17_ctx[] = { + 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f, +}; +static const uint8_t ae_data_aes_gcm_vect17_tag[] = { + 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2, +}; + +/* Test case 18 */ +static const uint8_t ae_data_aes_gcm_vect18_key[] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, +}; +static const uint8_t ae_data_aes_gcm_vect18_nonce[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect18_aad[] = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, +}; +static const uint8_t ae_data_aes_gcm_vect18_ptx[] = { + 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, +}; +static const uint8_t ae_data_aes_gcm_vect18_ctx[] = { + 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f, +}; +static const uint8_t ae_data_aes_gcm_vect18_tag[] = { + 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a, +}; + +/* + * Test data generated with + * http://www.mobilefish.com/services/rsa_key_generation/rsa_key_generation.php + * selecting 1024 bit key + */ +static const uint8_t ac_rsassa_vect1_modulus[] = { + 0xab, 0x42, 0x30, 0x54, 0x02, 0x15, 0x19, 0x4f, 0x03, 0x15, 0x73, 0xdf, + 0x96, 0x4c, 0x23, 0xeb, 0xd3, 0xd5, 0xf2, 0xff, 0x17, 0xf4, 0x1f, 0x5c, + 0x41, 0x26, 0x3e, 0x20, 0x15, 0x6d, 0x0a, 0x70, 0x8d, 0x9e, 0x9e, 0x67, + 0x47, 0x87, 0x6a, 0x15, 0xb5, 0x40, 0x38, 0x99, 0x64, 0x90, 0xc1, 0x32, + 0x32, 0x95, 0xc7, 0x63, 0x0a, 0xac, 0x5b, 0xcc, 0x21, 0x6b, 0x51, 0x7b, + 0xa5, 0xef, 0x7b, 0x62, 0x12, 0x34, 0x2d, 0x8d, 0xb6, 0x0d, 0x24, 0x92, + 0xa4, 0x83, 0xd4, 0x3b, 0xa5, 0x29, 0xe2, 0x94, 0xfc, 0xcd, 0x5e, 0xcb, + 0xc6, 0x52, 0x7b, 0xf7, 0x65, 0x80, 0x1f, 0x63, 0xcb, 0x4f, 0x40, 0x27, + 0x5b, 0x2d, 0x2a, 0x9f, 0xce, 0x9b, 0x33, 0x97, 0xeb, 0xbe, 0xcb, 0x34, + 0x22, 0xff, 0x5f, 0x21, 0x21, 0xba, 0x75, 0xb3, 0xba, 0x8f, 0x00, 0x9e, + 0x08, 0x66, 0x86, 0x4a, 0x8e, 0x40, 0xb2, 0x5f +}; +static const uint8_t ac_rsassa_vect1_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_rsassa_vect1_priv_exp[] = { + 0x91, 0xaa, 0x4f, 0xae, 0xf4, 0xc2, 0x7b, 0x6f, 0x60, 0x21, 0x1c, 0x18, + 0xde, 0x1e, 0xcf, 0x22, 0xe4, 0x60, 0x83, 0x3a, 0x04, 0x66, 0xc9, 0x51, + 0xcf, 0xbc, 0x36, 0x75, 0x55, 0xa4, 0x14, 0x90, 0x1d, 0x75, 0x00, 0x28, + 0xba, 0x87, 0x6c, 0x6d, 0x20, 0x68, 0x8a, 0x7b, 0xb6, 0x35, 0x05, 0x8e, + 0xab, 0xc6, 0x07, 0xfc, 0xae, 0xf4, 0x61, 0x74, 0x24, 0x2c, 0xc2, 0xf6, + 0xd7, 0xf1, 0xf5, 0x4f, 0xd3, 0x68, 0x86, 0x9b, 0x40, 0x47, 0x74, 0x51, + 0x2a, 0xe3, 0x87, 0xe3, 0x6f, 0x8c, 0x2e, 0x71, 0xb9, 0xe1, 0x49, 0x62, + 0x8b, 0x1f, 0x00, 0x92, 0x51, 0x82, 0x5b, 0x56, 0xeb, 0x55, 0x4e, 0x17, + 0x67, 0x91, 0x74, 0xc3, 0x01, 0xdc, 0x34, 0xda, 0x56, 0x03, 0x3c, 0x5d, + 0x50, 0xb5, 0xa5, 0xf5, 0xd0, 0xe1, 0x84, 0x7f, 0x2c, 0x16, 0x86, 0x34, + 0x1d, 0xb1, 0x8f, 0xd9, 0xb4, 0x0b, 0x35, 0x79 +}; +static const uint8_t ac_rsassa_vect1_prime1[] = { + 0xec, 0xbb, 0x19, 0x15, 0xc6, 0x52, 0xee, 0xf2, 0x75, 0x0b, 0x2f, 0x4f, + 0x1b, 0x2e, 0xd5, 0x14, 0x13, 0x26, 0xb4, 0xb4, 0x8d, 0x1d, 0xbd, 0x27, + 0xbb, 0x38, 0xba, 0x2f, 0xa7, 0xc7, 0xb6, 0x76, 0x88, 0xad, 0x73, 0x24, + 0x56, 0xe4, 0xd6, 0x9e, 0xe1, 0x20, 0x50, 0x4e, 0x90, 0x09, 0xb1, 0xf7, + 0x58, 0x1f, 0x47, 0x82, 0x88, 0xe7, 0xd8, 0xab, 0x3c, 0x1c, 0x9d, 0xc1, + 0xa7, 0x79, 0x5c, 0x65 +}; +static const uint8_t ac_rsassa_vect1_prime2[] = { + 0xb9, 0x32, 0xce, 0x2d, 0x38, 0xb4, 0x21, 0x7f, 0x9e, 0x79, 0x36, 0xf8, + 0x6a, 0xf4, 0x99, 0xae, 0x57, 0x1b, 0xd6, 0x1c, 0x53, 0xf7, 0xf9, 0x61, + 0xed, 0x47, 0xca, 0x7d, 0x76, 0xd7, 0x4e, 0xc6, 0x59, 0x51, 0x2d, 0xea, + 0x91, 0x0f, 0xdf, 0x56, 0x77, 0xa9, 0x2e, 0xf7, 0x63, 0x57, 0x14, 0x93, + 0x3b, 0x6f, 0x39, 0x4d, 0x88, 0x18, 0x2f, 0x78, 0xfc, 0xa3, 0xdb, 0xf6, + 0xc0, 0x05, 0xdd, 0x73 +}; +static const uint8_t ac_rsassa_vect1_exp1[] = { + 0xaa, 0xa7, 0x45, 0xb2, 0x18, 0xc1, 0xf8, 0x56, 0xf8, 0x61, 0x13, 0xbd, + 0xa7, 0x0e, 0xdf, 0xb4, 0x15, 0x0a, 0x36, 0x02, 0x62, 0x28, 0x2a, 0x0f, + 0xd6, 0x3b, 0x52, 0x9c, 0xc0, 0x0a, 0x8c, 0x52, 0x6e, 0xbc, 0xfa, 0xe0, + 0x1b, 0x73, 0xe3, 0xf3, 0xac, 0xbe, 0xaa, 0xa5, 0xb7, 0xd8, 0x05, 0x5f, + 0x15, 0x3b, 0x97, 0x45, 0x56, 0x84, 0x2c, 0x01, 0x64, 0xd8, 0x0c, 0x31, + 0x6a, 0x15, 0x66, 0xb1 +}; +static const uint8_t ac_rsassa_vect1_exp2[] = { + 0x82, 0xec, 0x11, 0xa9, 0x12, 0x5e, 0xf5, 0x17, 0x7c, 0xf6, 0x80, 0x0f, + 0xd9, 0xbc, 0x95, 0x30, 0x14, 0x50, 0x8f, 0x6a, 0x73, 0x49, 0xe8, 0x38, + 0x7c, 0x3f, 0xb6, 0x3c, 0x3f, 0xd9, 0x31, 0xcd, 0x32, 0xb3, 0x1a, 0xdc, + 0xaa, 0x34, 0x28, 0x54, 0xbe, 0x3f, 0x11, 0xfe, 0xbd, 0x71, 0x80, 0x10, + 0x1d, 0x82, 0x21, 0x66, 0x58, 0x01, 0x90, 0xfd, 0xdc, 0xcc, 0x11, 0xe2, + 0x3c, 0x19, 0x69, 0x55 +}; +static const uint8_t ac_rsassa_vect1_coeff[] = { + 0x2b, 0x9b, 0x48, 0xc0, 0xe1, 0xcb, 0x28, 0x9c, 0x03, 0xb2, 0xcf, 0xc6, + 0xf6, 0xbb, 0xbe, 0x1b, 0xad, 0xe6, 0x3b, 0xd3, 0x65, 0xbb, 0xca, 0xb7, + 0x43, 0x17, 0x8e, 0x3d, 0xb1, 0x6d, 0xc3, 0x06, 0xad, 0x7d, 0xe8, 0x81, + 0xb9, 0x5a, 0x13, 0xad, 0x18, 0x46, 0xcd, 0x93, 0xb6, 0x44, 0x1f, 0xd0, + 0x4d, 0x73, 0xb1, 0x00, 0x4d, 0x46, 0xc8, 0x22, 0x4a, 0x7e, 0xb8, 0xe6, + 0xdd, 0xae, 0x5f, 0x40 +}; +static const uint8_t ac_rsassa_vect1_ptx[] = { + 0x91, 0x07, 0xf4, 0x49, 0x0a, 0xf9, 0x99, 0x12, 0xaa, 0x95, 0x02, 0x76, + 0x95, 0x1b, 0xfa, 0x94, 0x32, 0xbf +}; +static const uint8_t ac_rsassa_vect1_out[] = { + 0x5f, 0xf8, 0xc0, 0x00, 0x4b, 0xd6, 0x5a, 0x3b, 0xf9, 0x34, 0xad, 0xca, + 0x24, 0x8f, 0x8f, 0x99, 0xba, 0x24, 0xb3, 0x84, 0x1b, 0x82, 0xff, 0xdb, + 0x35, 0x00, 0xa0, 0x66, 0x62, 0xc3, 0x85, 0x4d, 0xfc, 0x4b, 0x42, 0xce, + 0xd1, 0x29, 0x39, 0x04, 0x16, 0xcb, 0xa2, 0x53, 0x12, 0x5d, 0x71, 0x5c, + 0xcd, 0x37, 0xcb, 0x0a, 0x5d, 0x07, 0xdd, 0xb2, 0x18, 0x94, 0x47, 0x2a, + 0x82, 0x64, 0x7a, 0xd3, 0xbb, 0x83, 0xc5, 0x9c, 0x50, 0x85, 0x65, 0x94, + 0x0f, 0x01, 0xfe, 0x20, 0xa0, 0x83, 0x4f, 0x3b, 0x78, 0x99, 0x48, 0x94, + 0x36, 0xaf, 0x4a, 0xac, 0x89, 0xfa, 0xf6, 0xf8, 0x42, 0x86, 0xa5, 0xbe, + 0x0d, 0xb3, 0x39, 0x42, 0xa0, 0x70, 0x56, 0x5f, 0xea, 0xc6, 0x8f, 0x31, + 0xfe, 0x56, 0x56, 0xac, 0xf7, 0x4c, 0x9b, 0x8a, 0x06, 0x5a, 0xbd, 0x61, + 0x92, 0xfc, 0xef, 0x4b, 0x26, 0x36, 0x6d, 0x91 +}; + + +/* + * Test data generated with + * http://www.mobilefish.com/services/rsa_key_generation/rsa_key_generation.php + * selecting 2048 bit key + */ +static const uint8_t ac_rsassa_vect2_modulus[] = { + 0x9a, 0x83, 0xda, 0x0e, 0xfb, 0xa1, 0x77, 0xc5, 0x34, 0x88, 0xac, 0x3d, + 0xd1, 0x3e, 0x89, 0x3e, 0xca, 0xad, 0x40, 0x47, 0xdc, 0xff, 0xc6, 0x18, + 0xc3, 0x1a, 0x95, 0xd3, 0x82, 0xb9, 0x98, 0xa8, 0xec, 0x90, 0xbe, 0xab, + 0xef, 0x74, 0xb7, 0x58, 0xa0, 0x0d, 0x0f, 0xb5, 0x13, 0xb8, 0x7e, 0xf7, + 0xdb, 0x19, 0x77, 0x55, 0xc5, 0xed, 0xa6, 0x60, 0xa7, 0xaf, 0xea, 0x83, + 0x69, 0xcf, 0xcf, 0x50, 0x51, 0x94, 0xa7, 0xc0, 0x96, 0x68, 0xe6, 0x63, + 0xef, 0xdf, 0xa8, 0x28, 0x4a, 0x50, 0xbf, 0xd7, 0x44, 0xbf, 0x0b, 0x0a, + 0x41, 0xd6, 0x02, 0xfc, 0x3f, 0x06, 0x51, 0x82, 0xe4, 0x56, 0x3f, 0xe9, + 0x37, 0x40, 0xe0, 0xaa, 0x18, 0x56, 0xcb, 0x2e, 0xd4, 0x02, 0x66, 0xcc, + 0xfb, 0xbd, 0x6b, 0x34, 0xfd, 0x3d, 0x2c, 0xad, 0xeb, 0x8c, 0x7c, 0x85, + 0x09, 0xd1, 0x00, 0x4f, 0xaf, 0xc7, 0x9d, 0x25, 0x19, 0x45, 0x3a, 0x54, + 0x9d, 0xda, 0x4b, 0x3b, 0x11, 0x6b, 0xbc, 0x66, 0xb7, 0xb1, 0xa2, 0x79, + 0x1c, 0xd5, 0x38, 0x7a, 0x7b, 0x62, 0xae, 0x8a, 0x35, 0xc7, 0x4b, 0xdd, + 0x0e, 0x23, 0x78, 0xa3, 0xec, 0xcf, 0xe9, 0xa4, 0x26, 0x33, 0xca, 0x48, + 0x08, 0xc1, 0x3c, 0xb0, 0xe8, 0xfa, 0x2f, 0xbb, 0x75, 0x8a, 0x3d, 0x45, + 0xf4, 0xe5, 0x7a, 0x2f, 0x4d, 0xd8, 0x6f, 0x05, 0x14, 0x21, 0xb1, 0xfd, + 0xd1, 0xbb, 0x3c, 0xa7, 0x1d, 0x2f, 0xe7, 0x79, 0xc2, 0x99, 0x49, 0x25, + 0xef, 0x73, 0xd4, 0xe9, 0xbb, 0xf9, 0x1b, 0xeb, 0x0e, 0xb7, 0xdf, 0x53, + 0xc1, 0xdc, 0x41, 0xf9, 0x92, 0x01, 0x68, 0x63, 0x84, 0x52, 0x78, 0xfc, + 0xf8, 0x7f, 0x84, 0xa1, 0x47, 0xe3, 0x7c, 0x5b, 0x53, 0x82, 0x1b, 0x3a, + 0x78, 0x7a, 0xae, 0x8d, 0x6a, 0xef, 0x87, 0x38, 0x28, 0x14, 0x4c, 0xf5, + 0xd7, 0xb9, 0xd0, 0xad +}; +static const uint8_t ac_rsassa_vect2_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_rsassa_vect2_priv_exp[] = { + 0x73, 0xdd, 0x01, 0x0b, 0x91, 0x26, 0xb0, 0x00, 0x01, 0x77, 0xa6, 0xe8, + 0xa7, 0xd9, 0xe3, 0xe2, 0x60, 0xea, 0x6f, 0x34, 0x34, 0x04, 0xdb, 0x8f, + 0xbf, 0xe5, 0x54, 0x8a, 0x09, 0x11, 0x90, 0xe6, 0xc2, 0x95, 0x7b, 0x54, + 0xc4, 0x37, 0x5a, 0x30, 0xab, 0xbb, 0x7f, 0x96, 0xc1, 0xd5, 0xeb, 0xe7, + 0x81, 0xb4, 0xe3, 0xe6, 0x3e, 0x88, 0x08, 0xe5, 0x9b, 0x78, 0x6f, 0x3a, + 0xe1, 0x82, 0x41, 0xab, 0xb1, 0xb0, 0xed, 0xe5, 0x9d, 0x23, 0xc5, 0xf7, + 0x14, 0x6d, 0x3a, 0xd4, 0x13, 0x7d, 0xdf, 0x8c, 0xd5, 0x71, 0x08, 0x1f, + 0x45, 0xe4, 0xeb, 0xd2, 0x28, 0x94, 0x5d, 0x54, 0xf0, 0x51, 0xb8, 0x94, + 0xf1, 0xa8, 0xc5, 0x8e, 0xe6, 0xb7, 0x56, 0x9e, 0xa3, 0xbd, 0xb5, 0x46, + 0x6a, 0x52, 0xcc, 0x6c, 0x2c, 0xa4, 0xcd, 0xb7, 0x10, 0xd5, 0x04, 0x9e, + 0x62, 0x11, 0x05, 0xd1, 0xbb, 0x36, 0xcc, 0x9f, 0x55, 0x91, 0x21, 0x2e, + 0xe7, 0x10, 0x4a, 0xe9, 0xb1, 0xd2, 0xc7, 0x16, 0x45, 0x46, 0xd8, 0x9e, + 0xd4, 0xe6, 0x7e, 0x90, 0xc9, 0x33, 0xf0, 0x4e, 0x9d, 0x1f, 0x46, 0x79, + 0xcf, 0xcd, 0xf6, 0x77, 0x6a, 0x6c, 0x97, 0x77, 0x00, 0x3a, 0x78, 0x24, + 0x81, 0xec, 0x2a, 0xae, 0x51, 0x77, 0xa0, 0xb2, 0xc9, 0xb8, 0x4a, 0xca, + 0xab, 0x7a, 0x28, 0x3f, 0x99, 0x53, 0xa3, 0xab, 0xe8, 0x60, 0x7a, 0x6d, + 0x2e, 0xda, 0xa6, 0x90, 0x24, 0xf6, 0x34, 0x51, 0x22, 0x7d, 0x32, 0x81, + 0x0c, 0x50, 0xa5, 0x14, 0x69, 0x8b, 0xbc, 0x4e, 0x06, 0xcc, 0xc3, 0xe1, + 0x69, 0x5f, 0xaa, 0xc3, 0x99, 0x46, 0x2f, 0xb7, 0x86, 0xc9, 0x39, 0xba, + 0x58, 0x97, 0x4e, 0x40, 0xc1, 0x29, 0xe6, 0x0e, 0xa4, 0x7d, 0x4a, 0xdf, + 0x87, 0x8c, 0x93, 0x7c, 0x22, 0x67, 0xae, 0xbb, 0x0e, 0xfc, 0x05, 0x67, + 0x5f, 0xde, 0xe2, 0x21 +}; +static const uint8_t ac_rsassa_vect2_prime1[] = { + 0xcd, 0xff, 0x70, 0x4b, 0x87, 0xc8, 0xd3, 0xad, 0x23, 0xb4, 0xe9, 0x63, + 0x91, 0x50, 0xbd, 0x78, 0x28, 0x4f, 0x23, 0x5a, 0xd5, 0x32, 0x53, 0xae, + 0x04, 0xe5, 0x87, 0x9c, 0xb4, 0x18, 0x07, 0x90, 0x6e, 0xaa, 0x8a, 0xfe, + 0x1c, 0xfe, 0x60, 0x77, 0x85, 0x27, 0x87, 0x4b, 0x91, 0x72, 0x43, 0x9d, + 0xe1, 0x71, 0x39, 0xe4, 0x0e, 0x7d, 0x03, 0xa9, 0x5d, 0xbc, 0xc2, 0x02, + 0x87, 0xd9, 0x39, 0x98, 0xf0, 0x51, 0xac, 0x6a, 0x96, 0x7c, 0x00, 0xf9, + 0xe4, 0x95, 0x02, 0xb8, 0xbd, 0xf1, 0xae, 0x2c, 0x15, 0x5a, 0x12, 0x30, + 0x6e, 0x1d, 0xe4, 0x1e, 0x65, 0x65, 0xde, 0x2e, 0xdc, 0x93, 0x02, 0xc2, + 0xbb, 0x9f, 0x7e, 0xec, 0xa3, 0xc4, 0x8f, 0x05, 0x07, 0xce, 0xbb, 0x9a, + 0x53, 0x1c, 0x57, 0x77, 0x89, 0xff, 0x6c, 0xcb, 0xf8, 0xa1, 0xde, 0xbe, + 0x14, 0x4b, 0xee, 0xd6, 0xad, 0x27, 0x04, 0x99 +}; +static const uint8_t ac_rsassa_vect2_prime2[] = { + 0xc0, 0x05, 0x4f, 0x58, 0xa0, 0x22, 0x58, 0x60, 0x7b, 0xef, 0x87, 0x1f, + 0x87, 0x39, 0x47, 0x48, 0xa8, 0x86, 0x15, 0xd5, 0xf9, 0xb5, 0xf8, 0x71, + 0x81, 0xf9, 0xb7, 0x3e, 0x4a, 0xe8, 0x5d, 0xbc, 0xbf, 0x8f, 0x17, 0xc0, + 0x96, 0xdc, 0xc2, 0x7f, 0x5e, 0x60, 0x65, 0xe7, 0xa2, 0xc6, 0x30, 0x25, + 0x8b, 0xe9, 0xdb, 0x28, 0x10, 0xac, 0x02, 0x0e, 0x23, 0x0f, 0x14, 0x6b, + 0xff, 0xd4, 0x09, 0xdd, 0x7c, 0x06, 0x5d, 0xb2, 0x6e, 0x32, 0x49, 0x62, + 0xb7, 0x93, 0x5d, 0x24, 0x99, 0x03, 0x69, 0x9b, 0x60, 0x2e, 0x34, 0xa3, + 0x9f, 0x62, 0x33, 0xaf, 0xc5, 0xdc, 0x8f, 0x10, 0x61, 0xfa, 0xc5, 0x8d, + 0xa9, 0xcc, 0x86, 0x93, 0x7d, 0x1e, 0xa6, 0x7d, 0xcb, 0x6e, 0x69, 0xfe, + 0xe1, 0x3c, 0x64, 0x01, 0x58, 0xd8, 0x1a, 0x0f, 0xf8, 0xcc, 0x34, 0xe5, + 0x01, 0x2c, 0xb8, 0xf9, 0x90, 0x71, 0xe5, 0x35 +}; +static const uint8_t ac_rsassa_vect2_exp1[] = { + 0x8b, 0x46, 0xc7, 0x8f, 0xe9, 0xb0, 0x78, 0x9d, 0xb9, 0x64, 0x99, 0xdf, + 0xbd, 0xe2, 0x4f, 0x18, 0x2c, 0x78, 0xc5, 0x38, 0xa6, 0xa8, 0xae, 0x37, + 0x1c, 0x0c, 0x6c, 0x52, 0x20, 0xd9, 0x96, 0x53, 0xaa, 0xdf, 0x17, 0xb6, + 0x93, 0xb7, 0xd1, 0x55, 0x3d, 0xeb, 0xe9, 0xe7, 0xc7, 0xe0, 0xef, 0xa2, + 0x91, 0x48, 0x52, 0x91, 0xc4, 0xd1, 0xf5, 0x65, 0xcf, 0x80, 0xcd, 0xd3, + 0x94, 0x31, 0xe4, 0x65, 0x69, 0x26, 0x6f, 0x62, 0x69, 0x78, 0x51, 0xd8, + 0xa3, 0x19, 0xb4, 0x8b, 0x5f, 0xb1, 0x45, 0xc7, 0x7c, 0x70, 0x37, 0x98, + 0x12, 0xfb, 0x96, 0xbe, 0x8e, 0x63, 0xff, 0x82, 0xc3, 0x93, 0x89, 0xec, + 0x4b, 0x9a, 0x9c, 0xe0, 0x36, 0x21, 0xb1, 0x68, 0xff, 0x4c, 0x61, 0x3f, + 0x08, 0x2e, 0x43, 0x5d, 0x09, 0x2a, 0x6f, 0x4e, 0xc1, 0x3e, 0x00, 0x31, + 0x97, 0xdb, 0x77, 0x12, 0x22, 0x64, 0x1d, 0x11 +}; +static const uint8_t ac_rsassa_vect2_exp2[] = { + 0x88, 0x05, 0xfa, 0xec, 0x44, 0x1b, 0xb0, 0x51, 0x40, 0xda, 0x2f, 0xf5, + 0x14, 0x9c, 0x6d, 0xb3, 0xb9, 0xb5, 0xaa, 0x58, 0x36, 0x99, 0x42, 0x52, + 0x5e, 0x09, 0x60, 0x56, 0x5f, 0x47, 0xf5, 0xc7, 0x14, 0x47, 0xb0, 0x42, + 0xbc, 0x5b, 0xcb, 0xe7, 0xe0, 0x1a, 0x17, 0x76, 0x1c, 0x27, 0x9a, 0xc9, + 0xae, 0x30, 0x4e, 0x10, 0x36, 0xa7, 0x32, 0x99, 0x83, 0x1a, 0x56, 0x94, + 0x1e, 0xd8, 0xbc, 0xd8, 0x49, 0xd8, 0x54, 0x9d, 0x66, 0x54, 0x77, 0x09, + 0xd8, 0x13, 0x2b, 0x03, 0x16, 0xe5, 0x84, 0xf5, 0x0d, 0x10, 0x0e, 0x37, + 0xee, 0x5a, 0xe9, 0x54, 0x55, 0xac, 0x65, 0x27, 0xec, 0xd0, 0x71, 0x0b, + 0x66, 0x42, 0x3c, 0xfe, 0xd3, 0xbe, 0x57, 0xa0, 0x7a, 0xf0, 0x4f, 0x63, + 0xbf, 0x78, 0x41, 0x3b, 0x77, 0x0d, 0x36, 0x81, 0x23, 0xf4, 0xbc, 0x6f, + 0x91, 0x02, 0x76, 0x52, 0x4b, 0x91, 0x73, 0x15 +}; +static const uint8_t ac_rsassa_vect2_coeff[] = { + 0xb1, 0x70, 0x9b, 0x0c, 0xec, 0xc7, 0x8b, 0xc3, 0x50, 0xe4, 0x3a, 0x85, + 0xda, 0x6c, 0xf6, 0x36, 0x30, 0x27, 0xe5, 0xf5, 0xa2, 0x96, 0x1d, 0x78, + 0xa2, 0xd5, 0x89, 0xce, 0xef, 0xba, 0xd9, 0xfc, 0x3e, 0x91, 0x0e, 0x63, + 0x42, 0x31, 0x2d, 0x99, 0xd7, 0x47, 0x1d, 0xb2, 0x42, 0x56, 0xd3, 0x07, + 0x76, 0x31, 0x35, 0x92, 0x23, 0xcd, 0x81, 0x7d, 0xc2, 0x14, 0xfd, 0x90, + 0x71, 0xbb, 0x43, 0x5e, 0x8b, 0xec, 0x1f, 0x8a, 0xf5, 0xe6, 0x08, 0xee, + 0x26, 0x79, 0xa1, 0xb4, 0xee, 0x58, 0x99, 0x4c, 0xad, 0x91, 0x6a, 0xaa, + 0x5c, 0x4b, 0xbc, 0xbc, 0xad, 0xf7, 0xe1, 0xdd, 0x48, 0xfd, 0x98, 0x82, + 0x06, 0x11, 0xac, 0xc5, 0x74, 0xb5, 0xa9, 0x16, 0x4a, 0x6c, 0xc1, 0xae, + 0x25, 0x70, 0xde, 0x96, 0xcf, 0xad, 0x2a, 0x8b, 0x89, 0x39, 0x77, 0x94, + 0xae, 0x4b, 0x84, 0x02, 0x92, 0x0c, 0x05, 0x42 +}; +static const uint8_t ac_rsassa_vect2_ptx[] = { + 0x91, 0x07, 0xf4, 0x49, 0x0a, 0xf9, 0x99, 0x12, 0xaa, 0x95, 0x02, 0x76, + 0x95, 0x1b, 0xfa, 0x94, 0x32, 0xbf +}; +static const uint8_t ac_rsassa_vect2_out[] = { + 0x47, 0x16, 0xe1, 0xee, 0x54, 0xb7, 0xe0, 0x8a, 0xcc, 0x5d, 0x1b, 0xae, + 0xde, 0xc1, 0x43, 0x09, 0xd8, 0x4d, 0xe3, 0xcd, 0x5f, 0xd5, 0x48, 0x51, + 0xd3, 0x1c, 0x62, 0x5d, 0x1c, 0x13, 0x0b, 0x05, 0x89, 0x77, 0xd6, 0x95, + 0x4e, 0x8f, 0x4a, 0x0a, 0x51, 0xc2, 0x0c, 0xcf, 0xfe, 0x4c, 0x24, 0x6d, + 0x0c, 0x73, 0x33, 0x46, 0xd9, 0xdf, 0xfe, 0x6e, 0x06, 0xcb, 0x8c, 0x79, + 0x32, 0x3f, 0xbd, 0x1d, 0x10, 0x3a, 0x60, 0x3c, 0xe8, 0x1c, 0xbe, 0xd9, + 0xa8, 0x00, 0x76, 0x5b, 0x6d, 0x7a, 0x62, 0xdd, 0x3c, 0x21, 0x53, 0x16, + 0xab, 0x0b, 0x6c, 0x8d, 0x43, 0xfd, 0xba, 0x9a, 0xd9, 0x9a, 0xc1, 0x21, + 0x0c, 0x79, 0x78, 0x93, 0x86, 0xbd, 0xdf, 0x63, 0xca, 0xc8, 0xd6, 0xc6, + 0x20, 0xc9, 0x08, 0xf6, 0xc8, 0xfe, 0x22, 0xa4, 0xc6, 0xe3, 0x49, 0xe4, + 0x63, 0x01, 0x03, 0x5b, 0x78, 0x63, 0x3a, 0x02, 0x9c, 0xa1, 0xed, 0x20, + 0x01, 0x10, 0x79, 0x2e, 0x8d, 0xe5, 0x70, 0xae, 0x1a, 0x5f, 0x72, 0x9e, + 0x31, 0xab, 0x21, 0xd3, 0xd7, 0x59, 0x5f, 0x26, 0xbf, 0x45, 0x31, 0x6d, + 0xc3, 0xa6, 0x45, 0x7b, 0x6d, 0x8e, 0x3c, 0xb0, 0x42, 0xb4, 0xeb, 0x09, + 0xcf, 0x54, 0x0a, 0x72, 0x38, 0xf8, 0x67, 0x83, 0xa7, 0x7b, 0xce, 0x52, + 0x74, 0x0f, 0x03, 0x9d, 0x09, 0x1f, 0xe7, 0xf0, 0x85, 0x27, 0x3e, 0x1d, + 0x2f, 0xea, 0x2d, 0xa8, 0xdc, 0x58, 0x00, 0x9b, 0xdc, 0x10, 0x95, 0xe4, + 0x5f, 0x69, 0x20, 0x11, 0x1c, 0x3c, 0x58, 0x27, 0xcd, 0x1f, 0x23, 0xc9, + 0x28, 0xfa, 0x98, 0x53, 0xce, 0xa6, 0xe6, 0x64, 0x20, 0x2e, 0xe1, 0x2b, + 0x35, 0x30, 0x4e, 0xb2, 0x14, 0xaa, 0x7f, 0x89, 0x6f, 0xa8, 0xb1, 0xd6, + 0x30, 0x2c, 0x7c, 0xe5, 0x26, 0xe4, 0xce, 0x61, 0x6c, 0xc6, 0x06, 0xbc, + 0xea, 0x26, 0x6f, 0xe4 +}; + +/* + * 3072-bit RSA + * Test data generated with: + * openssl genrsa -out 3072.pem 3072 + * openssl rsa -in 3072.pem -text -noout + * (dd if=/dev/zero bs=1 count=368; \ + * printf '\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10';) | \ + * openssl rsautl -encrypt -raw -inkey 3072.pem | od -t x1 + */ +static const uint8_t ac_rsassa_vect18_modulus[] = { + 0xca, 0x72, 0xcc, 0xef, 0xad, 0x0a, 0xbe, 0xd6, 0x35, 0x16, 0x23, 0x93, + 0x16, 0x8f, 0xee, 0x31, 0x4c, 0xc2, 0x6f, 0x20, 0x99, 0x38, 0x69, 0xc1, + 0xcb, 0x57, 0x5f, 0x7e, 0x35, 0xba, 0x85, 0xa7, 0xe9, 0xe1, 0xe6, 0x1d, + 0x39, 0xc2, 0x41, 0x7d, 0xc3, 0xa3, 0xea, 0x6a, 0xdb, 0x5a, 0x07, 0x4a, + 0x4a, 0x3a, 0xcb, 0xce, 0xf2, 0xa0, 0xdd, 0xcd, 0x4b, 0x99, 0x67, 0x0d, + 0x38, 0xf1, 0x40, 0x41, 0xed, 0x5b, 0xb8, 0xf8, 0xea, 0xc7, 0xd9, 0x91, + 0x30, 0x42, 0x8d, 0xee, 0x48, 0xc4, 0x7c, 0x7f, 0x0d, 0x33, 0x7b, 0x8f, + 0x38, 0x18, 0xed, 0x7f, 0x02, 0x8c, 0x44, 0x52, 0x6a, 0x93, 0x37, 0xfd, + 0x6a, 0x27, 0x3e, 0xbf, 0x03, 0x78, 0xe3, 0xfc, 0x29, 0x83, 0x20, 0x65, + 0xe3, 0xfa, 0x2c, 0x93, 0xcb, 0x83, 0x90, 0x61, 0xd3, 0x1a, 0x9a, 0x65, + 0x53, 0xf0, 0xea, 0x2c, 0xf8, 0x61, 0x8d, 0x9f, 0x54, 0x22, 0x7e, 0x2e, + 0x1e, 0x36, 0x62, 0xd9, 0x9f, 0x7d, 0x56, 0xf4, 0xad, 0x61, 0xb6, 0x1a, + 0x7b, 0x40, 0x59, 0x10, 0x04, 0xff, 0xea, 0x16, 0x98, 0x36, 0x61, 0x9d, + 0x5c, 0x62, 0xcb, 0xf6, 0xc2, 0x95, 0x3b, 0x91, 0xc9, 0xff, 0xf0, 0x65, + 0x7e, 0x0e, 0xa2, 0x43, 0x89, 0x24, 0xaa, 0xdd, 0x0e, 0xed, 0xb0, 0x8c, + 0xb0, 0xb2, 0x4d, 0x80, 0x2a, 0x11, 0xcf, 0x35, 0xe9, 0x82, 0xc6, 0x67, + 0x37, 0x3b, 0xc9, 0xd5, 0xa1, 0xd8, 0x8e, 0x07, 0x93, 0xfd, 0xe7, 0x5a, + 0x54, 0xc6, 0xf0, 0xae, 0x82, 0x43, 0x86, 0x62, 0x70, 0x44, 0x09, 0xb7, + 0x62, 0x58, 0xb2, 0x17, 0x9f, 0x3c, 0xa5, 0x10, 0x60, 0xc6, 0x61, 0x47, + 0x83, 0x1f, 0x3e, 0xa7, 0xf2, 0x26, 0x5b, 0x70, 0xd5, 0x81, 0x47, 0x6a, + 0x78, 0xe0, 0x85, 0x16, 0x36, 0xc0, 0x2e, 0xbb, 0x01, 0x6c, 0x99, 0x19, + 0xeb, 0x22, 0xf5, 0x13, 0xe3, 0x38, 0x67, 0x9f, 0x85, 0xed, 0x0f, 0x05, + 0x22, 0x29, 0x34, 0xda, 0x4b, 0x8f, 0x44, 0xfa, 0x30, 0xf8, 0xe6, 0xc1, + 0xf6, 0x9d, 0x9b, 0xd6, 0x56, 0x81, 0x2c, 0x58, 0x4d, 0xf8, 0x90, 0xef, + 0xf9, 0xea, 0x31, 0x6f, 0x04, 0xd2, 0x8d, 0xc1, 0xc9, 0x6e, 0x90, 0xd1, + 0xff, 0xce, 0xab, 0x58, 0x9f, 0x98, 0x57, 0x7c, 0x7a, 0x79, 0x8a, 0xb2, + 0x3d, 0x32, 0x0d, 0x0c, 0x3b, 0x6a, 0xd4, 0x33, 0x49, 0x50, 0xe1, 0x41, + 0x3d, 0x07, 0x32, 0xfc, 0x6d, 0x9f, 0xfc, 0x8c, 0xad, 0x05, 0x74, 0xa9, + 0x37, 0x5e, 0x70, 0x0b, 0xe9, 0xdf, 0xc1, 0x96, 0xca, 0x7c, 0xca, 0xbd, + 0xab, 0x8e, 0x68, 0xd0, 0xf9, 0x3f, 0x5f, 0x90, 0xb4, 0x30, 0x17, 0x4d, + 0x3a, 0xf9, 0xa1, 0xf0, 0xcb, 0xc7, 0x54, 0xb3, 0xa6, 0x0f, 0xd7, 0xe7, + 0x68, 0x43, 0x5f, 0x39, 0xa6, 0x05, 0x83, 0x74, 0xf9, 0xd9, 0x94, 0xab +}; +static const uint8_t ac_rsassa_vect18_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_rsassa_vect18_priv_exp[] = { + 0xaf, 0xb1, 0xa9, 0xc1, 0x67, 0x7f, 0xa7, 0xd6, 0xe7, 0x03, 0x6b, 0xa4, + 0x3f, 0x34, 0x72, 0x17, 0x3e, 0xf2, 0x8e, 0xd6, 0xcf, 0xa2, 0x71, 0xc5, + 0xc9, 0xde, 0xed, 0xf4, 0xee, 0x54, 0x0d, 0xa2, 0x88, 0x0b, 0x90, 0x55, + 0x54, 0xc7, 0x0d, 0x67, 0x43, 0xde, 0x81, 0x96, 0x72, 0xff, 0x52, 0xcc, + 0x5a, 0x57, 0x64, 0x81, 0x19, 0x78, 0x1a, 0x86, 0x0c, 0x51, 0xf9, 0x69, + 0x34, 0x3d, 0xca, 0xf2, 0x6c, 0x37, 0xe9, 0xf3, 0xbc, 0x6d, 0xec, 0x97, + 0x60, 0x36, 0xa2, 0x4e, 0x65, 0xc0, 0x7f, 0xfb, 0x13, 0x4d, 0xd6, 0xb1, + 0x98, 0x91, 0xa9, 0xab, 0x4c, 0x5e, 0xc6, 0xfc, 0x6f, 0x99, 0x8c, 0x41, + 0xd5, 0x5a, 0x71, 0xcd, 0xfc, 0x09, 0x72, 0x72, 0x68, 0xe4, 0x6f, 0xbd, + 0x7d, 0x78, 0xa4, 0x2f, 0x2f, 0xb3, 0xe2, 0x1d, 0xc3, 0xc3, 0x96, 0xb2, + 0xd1, 0x82, 0x86, 0xf8, 0xb8, 0x26, 0x91, 0x6d, 0xf0, 0xea, 0x6e, 0x6f, + 0x3f, 0xb1, 0x1b, 0x60, 0x9a, 0x55, 0x80, 0x9d, 0x9f, 0xca, 0xe8, 0xeb, + 0x5a, 0x83, 0xa1, 0xc7, 0x91, 0x4f, 0x37, 0xac, 0x9c, 0x34, 0xb5, 0xca, + 0x87, 0x5f, 0x06, 0x7c, 0x04, 0xaa, 0xd6, 0xa3, 0xd3, 0x96, 0xd6, 0xde, + 0x7d, 0xe3, 0xdd, 0x56, 0x97, 0x32, 0xc7, 0x46, 0x49, 0xaa, 0x66, 0x49, + 0xf3, 0x1f, 0x0a, 0xbb, 0x6b, 0xc7, 0x40, 0xf9, 0x1c, 0xca, 0x6d, 0xbb, + 0xa2, 0x9a, 0xf4, 0xae, 0x38, 0xf6, 0x53, 0x12, 0xb9, 0xea, 0xef, 0x97, + 0xbd, 0xfa, 0x1d, 0xb3, 0x85, 0x25, 0x0e, 0x24, 0x8c, 0xd2, 0x2d, 0x6e, + 0x2d, 0xeb, 0xd0, 0x4c, 0x1f, 0x82, 0x99, 0x96, 0x7f, 0x7f, 0x55, 0x13, + 0x20, 0x24, 0xd0, 0xa3, 0x62, 0x47, 0x84, 0x24, 0x3e, 0x61, 0xc1, 0x97, + 0xa8, 0x56, 0x1a, 0x60, 0x88, 0x13, 0x36, 0x82, 0xc8, 0xfe, 0x8e, 0x96, + 0x83, 0x47, 0x40, 0xc4, 0x89, 0x5d, 0x8d, 0xb4, 0xa8, 0x4e, 0x44, 0x7e, + 0xc1, 0x72, 0x79, 0xd5, 0xc8, 0x10, 0x72, 0x76, 0x38, 0x84, 0x43, 0x92, + 0x17, 0x6b, 0x9e, 0xbd, 0xa8, 0x35, 0xbf, 0xe8, 0xb3, 0xd5, 0x97, 0xbf, + 0xb7, 0x6a, 0x3c, 0xca, 0xb9, 0x9c, 0x3f, 0x92, 0x94, 0xb3, 0x5d, 0x82, + 0xca, 0xa7, 0x19, 0xa4, 0x96, 0xa7, 0xbe, 0xfa, 0xc5, 0xd0, 0xb0, 0xf3, + 0x93, 0x8d, 0x2f, 0x39, 0x4a, 0x08, 0x5d, 0xfc, 0x5d, 0xfe, 0x99, 0x2a, + 0x4e, 0x3a, 0x90, 0x10, 0xc6, 0xf8, 0x4c, 0xe3, 0xae, 0xcb, 0xd5, 0x7f, + 0x18, 0xab, 0xe6, 0x3b, 0x48, 0xf5, 0xdf, 0x25, 0x51, 0xe4, 0xad, 0x3e, + 0x77, 0x60, 0x5d, 0x68, 0xa5, 0x91, 0xcb, 0x09, 0x6b, 0x2d, 0x98, 0x51, + 0x73, 0x6b, 0x5b, 0xa9, 0x45, 0xfa, 0xf5, 0xa1, 0xdc, 0x3b, 0x12, 0x05, + 0x70, 0x1d, 0x73, 0x63, 0x2d, 0xa3, 0x28, 0xac, 0x51, 0xe6, 0x0d, 0x61 +}; +static const uint8_t ac_rsassa_vect18_prime1[] = { + 0xea, 0x1e, 0xe9, 0x51, 0xc9, 0x72, 0xdf, 0x9e, 0x72, 0x8e, 0xea, 0xe8, + 0x09, 0x78, 0x52, 0x2e, 0xfe, 0x7f, 0x87, 0x6e, 0xc5, 0x04, 0x88, 0x6b, + 0x67, 0xf6, 0x2b, 0x0d, 0xd2, 0x0b, 0xfb, 0x4f, 0xa2, 0x1c, 0x8c, 0xf6, + 0x8a, 0xbe, 0x8b, 0x1b, 0x1c, 0xec, 0x7e, 0x75, 0xf8, 0xd9, 0xed, 0x55, + 0x04, 0x08, 0xcc, 0x2c, 0x8b, 0x67, 0xa8, 0xc2, 0xfb, 0x2e, 0x0d, 0xd9, + 0x14, 0x70, 0x13, 0xf7, 0x94, 0x15, 0x74, 0xdd, 0x23, 0x66, 0x45, 0x43, + 0x41, 0x30, 0xc8, 0xec, 0x06, 0x23, 0xfc, 0xd6, 0xaa, 0x9d, 0x95, 0xa6, + 0x2b, 0xee, 0x53, 0xf5, 0xd5, 0x6c, 0x01, 0x23, 0x42, 0xa9, 0x36, 0x93, + 0xe1, 0x03, 0x96, 0x01, 0xce, 0x55, 0x14, 0xc0, 0xc0, 0x46, 0x9b, 0x93, + 0xca, 0x8d, 0x45, 0xf7, 0x6a, 0x2c, 0x4e, 0x5b, 0x25, 0x63, 0x7b, 0xef, + 0xdd, 0x38, 0x75, 0x51, 0xc6, 0x12, 0x5a, 0xbd, 0x4a, 0x4a, 0xee, 0xbf, + 0x0d, 0xc4, 0x42, 0x45, 0xcc, 0xf0, 0xb6, 0x05, 0x59, 0x21, 0x84, 0xb1, + 0x1f, 0x2a, 0x5c, 0x25, 0x22, 0xb8, 0xea, 0xc5, 0x60, 0x23, 0x68, 0x0d, + 0xa3, 0xf2, 0xe8, 0x1c, 0xfe, 0x6f, 0xfd, 0x95, 0x8a, 0x33, 0xef, 0x4f, + 0x2e, 0x24, 0x90, 0xa7, 0x60, 0xd6, 0x5c, 0x72, 0x5a, 0xc5, 0xd7, 0x5b, + 0xcf, 0x50, 0x76, 0x32, 0xe5, 0xc3, 0x3d, 0xa7, 0xda, 0x65, 0x86, 0x97 +}; +static const uint8_t ac_rsassa_vect18_prime2[] = { + 0xdd, 0x5e, 0x29, 0xbb, 0x78, 0x73, 0x74, 0x49, 0xec, 0xd1, 0x71, 0x91, + 0xa6, 0x74, 0x11, 0xae, 0x4b, 0x64, 0x6a, 0x5b, 0x60, 0x89, 0x70, 0x0c, + 0x1a, 0x3e, 0x3d, 0x42, 0x02, 0xd9, 0x16, 0x18, 0xb5, 0x33, 0xf8, 0xda, + 0x7f, 0x76, 0x6d, 0xc3, 0xf2, 0xc1, 0xf6, 0x90, 0x97, 0x2a, 0xbe, 0xeb, + 0x15, 0x8a, 0x05, 0xc2, 0xa4, 0xb8, 0xb0, 0x80, 0xe4, 0xc4, 0xc8, 0xc4, + 0xb5, 0xcc, 0x1e, 0xf0, 0x02, 0x6e, 0x02, 0xef, 0x5e, 0x35, 0xdb, 0x2e, + 0x41, 0x2d, 0xbc, 0x23, 0x44, 0x41, 0xbc, 0x29, 0xbd, 0xa7, 0x70, 0x0c, + 0x06, 0x53, 0x12, 0x78, 0x9b, 0x7f, 0x51, 0xfe, 0xb5, 0x82, 0x9c, 0xc9, + 0xf6, 0x40, 0x8d, 0xf9, 0x25, 0xd2, 0xae, 0x3f, 0x54, 0x22, 0x62, 0x80, + 0x03, 0x1f, 0xa3, 0x14, 0xc3, 0x13, 0x9c, 0x3a, 0xee, 0x3b, 0x34, 0xa3, + 0x7e, 0xe2, 0x71, 0xe8, 0x9d, 0x7c, 0xbc, 0x0e, 0x01, 0x34, 0xd5, 0x6d, + 0x89, 0x62, 0xd0, 0xaf, 0xe6, 0x03, 0x76, 0x94, 0xe2, 0xdc, 0xea, 0x1a, + 0xc7, 0x55, 0x68, 0x81, 0x9d, 0xdc, 0xf7, 0xc9, 0x81, 0xc8, 0x0f, 0x7a, + 0x03, 0xc2, 0x83, 0x98, 0xde, 0xc4, 0x4a, 0x1c, 0x7a, 0xc6, 0x13, 0x01, + 0x01, 0x04, 0x9a, 0x39, 0x14, 0xa5, 0x8d, 0x6a, 0x47, 0xef, 0xa5, 0xc4, + 0x35, 0xee, 0x72, 0x8e, 0x83, 0xe1, 0x74, 0x4e, 0xe2, 0x7b, 0x19, 0x0d +}; +static const uint8_t ac_rsassa_vect18_exp1[] = { + 0x9d, 0xde, 0x7a, 0x36, 0x4c, 0x40, 0xc9, 0xc9, 0x6e, 0x36, 0x30, 0xf0, + 0x86, 0x72, 0x3b, 0xf8, 0xb4, 0x64, 0x0a, 0x4f, 0x07, 0x4b, 0x27, 0x32, + 0x45, 0xc8, 0x19, 0x00, 0x18, 0xc3, 0x3b, 0x93, 0x57, 0x1d, 0x29, 0x70, + 0x95, 0xde, 0x26, 0xaf, 0x01, 0xb1, 0xf7, 0x14, 0x55, 0xd9, 0x9d, 0xcf, + 0xd6, 0x08, 0x98, 0xa4, 0xf0, 0xdb, 0xd5, 0x50, 0xa5, 0x4f, 0x48, 0xc7, + 0x38, 0xa0, 0xda, 0xd5, 0xf7, 0x65, 0x00, 0x88, 0x9d, 0x76, 0x38, 0xfe, + 0x40, 0xd7, 0x44, 0xa4, 0xe2, 0xff, 0x21, 0x5f, 0x1f, 0x6d, 0x63, 0x9b, + 0xc9, 0xc3, 0xcb, 0x99, 0xd9, 0x70, 0x1a, 0xd4, 0x4b, 0xff, 0x0e, 0x6e, + 0x69, 0x2c, 0xa1, 0xda, 0x55, 0xe7, 0xc9, 0x36, 0xb0, 0x70, 0xec, 0x37, + 0x9c, 0x3d, 0xe7, 0x10, 0x0e, 0xe8, 0x11, 0x6e, 0x24, 0xa8, 0x10, 0xca, + 0x8d, 0xc1, 0xa4, 0x5a, 0x9f, 0xd5, 0x80, 0x9a, 0x63, 0x9e, 0x63, 0x9f, + 0x31, 0x09, 0x46, 0x27, 0x0b, 0x2a, 0xc5, 0x92, 0x95, 0xa7, 0xa4, 0x72, + 0x4b, 0x31, 0xa5, 0x30, 0xe5, 0x59, 0x0b, 0xf6, 0x4b, 0xfd, 0x94, 0x0c, + 0x9e, 0xa1, 0x0d, 0x23, 0x7f, 0xee, 0xc4, 0x70, 0x31, 0xe1, 0x13, 0x5d, + 0xb1, 0x1f, 0xb6, 0xeb, 0x26, 0xc1, 0x65, 0x55, 0x37, 0x20, 0x71, 0x37, + 0xd7, 0x73, 0xca, 0x40, 0x47, 0xee, 0x7f, 0x84, 0xd0, 0x1f, 0xe5, 0xc1 +}; +static const uint8_t ac_rsassa_vect18_exp2[] = { + 0x6d, 0xdb, 0xa9, 0x42, 0x4c, 0x48, 0x9f, 0xd1, 0x80, 0x21, 0x81, 0x07, + 0x13, 0x60, 0x4e, 0xd5, 0xfc, 0xbc, 0x5c, 0xbb, 0xf4, 0x70, 0xc0, 0x96, + 0x80, 0xff, 0x9a, 0x4f, 0x04, 0x32, 0xcf, 0xf0, 0x7b, 0x1c, 0xcb, 0xc7, + 0x43, 0xb2, 0x76, 0x4e, 0xe4, 0x4e, 0xb6, 0x1a, 0x93, 0xaa, 0xb7, 0x0c, + 0xdb, 0xa7, 0x9f, 0xac, 0x35, 0x2b, 0x23, 0x0d, 0x14, 0x7b, 0x44, 0x57, + 0xbb, 0x11, 0x0d, 0xd9, 0x76, 0x9b, 0x3a, 0x01, 0xa8, 0xf3, 0x79, 0x4e, + 0xbf, 0x31, 0xff, 0x48, 0x51, 0x3b, 0x7e, 0x32, 0x08, 0xd8, 0xeb, 0x96, + 0x4c, 0x1d, 0x35, 0xf1, 0x7c, 0xd9, 0xf6, 0xcb, 0x3d, 0x31, 0x10, 0xb6, + 0x79, 0xeb, 0x17, 0x8a, 0x29, 0xe7, 0x20, 0x6a, 0x75, 0x4a, 0x8b, 0x2f, + 0x94, 0x5d, 0x43, 0x05, 0xae, 0xba, 0x30, 0xb2, 0x5e, 0x40, 0x2b, 0xa3, + 0x67, 0xf8, 0xe1, 0x26, 0xdb, 0xe1, 0x67, 0x42, 0x5b, 0xfe, 0xe8, 0x5c, + 0x6f, 0xee, 0x06, 0x3b, 0x05, 0x1f, 0x7a, 0xdd, 0xf0, 0xa8, 0x49, 0xd5, + 0xf8, 0x4e, 0xbe, 0x8a, 0x74, 0xd9, 0x90, 0x6f, 0x04, 0x65, 0x50, 0xa8, + 0xf0, 0xec, 0xbb, 0x7a, 0x46, 0x33, 0x8b, 0xc4, 0x0e, 0x79, 0xf6, 0x3c, + 0x6d, 0x50, 0xe7, 0x68, 0xa4, 0x82, 0x74, 0x67, 0xe6, 0x43, 0x5c, 0x34, + 0xbf, 0xbf, 0x12, 0x42, 0xff, 0xd8, 0x07, 0x6c, 0x8e, 0xa1, 0x20, 0x91 +}; +static const uint8_t ac_rsassa_vect18_coeff[] = { + 0x83, 0x1f, 0x72, 0x3b, 0x3f, 0x9e, 0x46, 0x88, 0x83, 0xb3, 0xa0, 0xe2, + 0xa8, 0xf0, 0x56, 0x97, 0x3e, 0x4a, 0xed, 0x56, 0x46, 0xdf, 0xf8, 0x21, + 0xf5, 0xb8, 0xf9, 0xd8, 0x43, 0x3c, 0xf4, 0x39, 0x51, 0xd2, 0xf3, 0xa0, + 0x6f, 0x57, 0x18, 0xc0, 0xe1, 0x8a, 0x6a, 0xc0, 0x49, 0x34, 0xf6, 0x4d, + 0x60, 0xf6, 0xd0, 0x0f, 0x64, 0x58, 0xed, 0x17, 0x7d, 0x68, 0x47, 0x05, + 0x6f, 0x64, 0x2e, 0xa9, 0x53, 0xa8, 0x17, 0x65, 0x13, 0xdc, 0x27, 0x51, + 0xe3, 0x35, 0x01, 0xb8, 0x0c, 0x68, 0xfd, 0xaf, 0xa3, 0xf7, 0xb1, 0x9a, + 0xdc, 0x7b, 0x1b, 0xf7, 0xcc, 0x90, 0x8e, 0x93, 0xbc, 0x08, 0x15, 0xa7, + 0xc0, 0x92, 0xa0, 0xa3, 0xc9, 0x17, 0x9d, 0x8d, 0x3d, 0x10, 0x4f, 0xe6, + 0xa3, 0x4b, 0x91, 0x21, 0x42, 0x7c, 0xdf, 0x9c, 0x71, 0xed, 0xe1, 0x30, + 0x76, 0xf5, 0x1c, 0x71, 0xa0, 0x47, 0xc8, 0xa6, 0x2a, 0x94, 0x01, 0x49, + 0xae, 0x2e, 0x90, 0x47, 0x21, 0x17, 0xae, 0x10, 0x91, 0x53, 0x91, 0x88, + 0x88, 0xb4, 0x12, 0x50, 0x47, 0x7d, 0xf6, 0xfb, 0xde, 0x12, 0x6b, 0xc2, + 0x50, 0x4f, 0x59, 0x61, 0x81, 0x42, 0xe7, 0x19, 0x72, 0x73, 0xef, 0x9d, + 0x7c, 0xa0, 0xf4, 0x30, 0x91, 0xa8, 0x6a, 0x46, 0x9c, 0x5c, 0x0f, 0x9a, + 0xeb, 0x1f, 0x00, 0x1e, 0x0c, 0x49, 0x1f, 0xb8, 0x5f, 0x37, 0xd7, 0x4f +}; +static const uint8_t ac_rsassa_vect18_ptx[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10 }; +static const uint8_t ac_rsassa_vect18_out[] = { + 0x06, 0xe3, 0x94, 0xdc, 0x4b, 0xbc, 0xa5, 0x80, 0x7e, 0x65, 0x65, 0xe2, + 0x6c, 0x91, 0x8b, 0x57, 0x52, 0x29, 0xa0, 0x05, 0x20, 0xef, 0x49, 0xb1, + 0xf9, 0xdb, 0x9e, 0xd8, 0x2e, 0x65, 0x9d, 0x61, 0xa8, 0xda, 0x9a, 0x95, + 0xab, 0xa6, 0x8e, 0x7b, 0xfd, 0x89, 0x5f, 0x5b, 0xfc, 0x10, 0x12, 0x98, + 0x4a, 0x2b, 0x48, 0x38, 0x2d, 0x66, 0x4c, 0x5b, 0x2c, 0xe2, 0x4d, 0xaa, + 0xa3, 0x19, 0x64, 0xf1, 0xf1, 0x4b, 0xd5, 0x06, 0x14, 0x83, 0xf2, 0x71, + 0x5a, 0xef, 0x81, 0xa2, 0xaa, 0x5a, 0xfa, 0x48, 0x38, 0x4a, 0x46, 0x52, + 0xb2, 0xbd, 0x10, 0x1b, 0x11, 0xa1, 0x46, 0x2d, 0x51, 0x59, 0xc0, 0x49, + 0x32, 0x43, 0x83, 0x28, 0xe0, 0x59, 0x0b, 0x6a, 0xef, 0x5d, 0xee, 0x37, + 0xca, 0xd8, 0x8f, 0xd5, 0xcf, 0x57, 0x4b, 0xac, 0x80, 0x3d, 0x05, 0xa0, + 0x15, 0x0c, 0x27, 0xee, 0xa2, 0x91, 0xfb, 0x1d, 0x4f, 0xbd, 0x45, 0x39, + 0x34, 0x37, 0x05, 0x82, 0x8f, 0x19, 0x4e, 0x20, 0xb8, 0x3b, 0x7e, 0x60, + 0x0a, 0x2f, 0x48, 0xaa, 0xf9, 0xa3, 0x5e, 0xd5, 0xd8, 0xdb, 0xc1, 0x61, + 0xa3, 0x95, 0x72, 0x19, 0xba, 0x97, 0xd6, 0x5f, 0x5d, 0xb3, 0x50, 0x51, + 0xb8, 0x5a, 0x1a, 0x8a, 0x0f, 0xd2, 0x25, 0xdc, 0x12, 0xd1, 0x96, 0xac, + 0x8c, 0x70, 0x47, 0x46, 0x35, 0xdf, 0xb1, 0x15, 0xf6, 0x65, 0xc3, 0x6d, + 0xd5, 0xd7, 0x4c, 0xb2, 0xa3, 0xc7, 0x03, 0xd6, 0xc1, 0x8d, 0x33, 0x56, + 0x49, 0xf4, 0xf4, 0x4e, 0x44, 0x83, 0xee, 0x7a, 0xb9, 0xdc, 0x5f, 0x7c, + 0x85, 0x10, 0x0e, 0x30, 0x46, 0x73, 0x7e, 0x44, 0x42, 0x17, 0x8f, 0x20, + 0x12, 0x13, 0x39, 0x5d, 0x55, 0x6b, 0xb2, 0x3c, 0xde, 0xae, 0xb9, 0xa0, + 0xb3, 0x0a, 0x81, 0x08, 0x72, 0xf8, 0xb3, 0xc4, 0xb9, 0x79, 0x09, 0x5d, + 0x81, 0x56, 0x49, 0xab, 0x07, 0xbd, 0xce, 0xd7, 0x39, 0x94, 0xfb, 0xfc, + 0x73, 0x2d, 0xd6, 0x9f, 0x7f, 0x26, 0x39, 0x05, 0xe5, 0xc9, 0x0b, 0x67, + 0x71, 0x09, 0xac, 0xfd, 0x75, 0x26, 0x92, 0xd6, 0x02, 0xf1, 0xa8, 0x25, + 0xee, 0x7c, 0xb6, 0x46, 0x28, 0xb6, 0x92, 0xf0, 0x99, 0xdc, 0x6e, 0xf1, + 0xa4, 0x9d, 0xc1, 0x45, 0x9d, 0x19, 0xd5, 0x78, 0x93, 0xc0, 0x2c, 0x3c, + 0x8b, 0x3c, 0x96, 0xf9, 0x84, 0x26, 0xc9, 0xf0, 0xe0, 0xde, 0xce, 0x23, + 0x7e, 0xe4, 0x06, 0xef, 0x5a, 0xea, 0x24, 0x65, 0x97, 0x4c, 0xd8, 0x48, + 0x44, 0xb1, 0x59, 0x8a, 0x15, 0x95, 0x62, 0xc9, 0xee, 0x86, 0x63, 0x32, + 0xba, 0xe2, 0xfc, 0x05, 0x5e, 0x17, 0x5c, 0x69, 0x8f, 0x04, 0x02, 0x91, + 0xec, 0x46, 0xf8, 0x0a, 0xd1, 0xb0, 0x95, 0x40, 0x3d, 0x92, 0x6e, 0xdf, + 0xf6, 0xe7, 0x3e, 0xc6, 0x40, 0x05, 0xdf, 0x82, 0xe6, 0xe0, 0x9f, 0x1b +}; + +/* + * 4096-bit RSA + * Test data generated with: + * openssl genrsa -out 4096.pem 4096 + * openssl rsa -in 4096.pem -text -noout + * (dd if=/dev/zero bs=1 count=368; \ + * printf '\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd\xe\xf\x10';) | \ + * openssl rsautl -encrypt -raw -inkey 4096.pem | od -t x1 + */ +static const uint8_t ac_rsassa_vect19_modulus[] = { + 0xf6, 0x48, 0x38, 0x0c, 0x61, 0xc5, 0xf2, 0x8f, 0x1d, 0x36, 0x78, 0x3b, + 0xfd, 0x03, 0x74, 0x2f, 0xe7, 0xb0, 0xab, 0xbd, 0x25, 0x88, 0x46, 0xd8, + 0x4f, 0x6b, 0xc8, 0xcb, 0xb8, 0x5d, 0x88, 0x16, 0x8c, 0x68, 0xf2, 0xda, + 0x34, 0x25, 0xc9, 0x8a, 0xcf, 0xf8, 0x34, 0xbd, 0xa3, 0xc9, 0x42, 0x9a, + 0xb7, 0x4d, 0xab, 0xc3, 0x87, 0xad, 0xa6, 0xa7, 0x02, 0x69, 0xdf, 0x58, + 0x84, 0xeb, 0x6e, 0xf7, 0x77, 0xd7, 0x4d, 0xf2, 0x01, 0x4e, 0x7b, 0x79, + 0x72, 0xb0, 0x23, 0xb3, 0xb2, 0x22, 0x15, 0x14, 0x05, 0xce, 0xea, 0x98, + 0x88, 0x9e, 0xe4, 0x03, 0x9d, 0x5b, 0x07, 0x56, 0xac, 0x77, 0x56, 0x3a, + 0xd7, 0x0c, 0x7f, 0x74, 0x2d, 0xd1, 0x48, 0xdd, 0x1c, 0x99, 0xe3, 0x53, + 0x3a, 0xa3, 0x9e, 0x4b, 0xb2, 0xd7, 0xe9, 0xfd, 0x04, 0x2c, 0xa2, 0x05, + 0x60, 0xae, 0x2d, 0xd0, 0x59, 0x2a, 0x90, 0xf6, 0xe4, 0x99, 0x4d, 0x7a, + 0xf8, 0xe5, 0x80, 0xeb, 0x77, 0xa5, 0xae, 0xe2, 0x40, 0xb7, 0x0e, 0x6c, + 0x02, 0xbe, 0x33, 0x04, 0xb0, 0xab, 0x01, 0xfe, 0x0c, 0xc1, 0xd1, 0x86, + 0x58, 0x6a, 0xc1, 0xb2, 0x3b, 0xfb, 0x03, 0x16, 0x72, 0xf3, 0xbb, 0xd6, + 0x43, 0xd3, 0xbf, 0xf0, 0x5b, 0xce, 0xa8, 0x39, 0x53, 0xee, 0x49, 0xc9, + 0x2c, 0x04, 0xb3, 0x4a, 0x4c, 0xd7, 0xd1, 0x9b, 0xf6, 0x51, 0x28, 0xd3, + 0x24, 0x03, 0xff, 0xa1, 0xcb, 0xb7, 0x7a, 0x73, 0xee, 0xfa, 0x2c, 0x1e, + 0x43, 0xc2, 0xb6, 0x3a, 0x4c, 0x68, 0x23, 0x1e, 0x88, 0x85, 0xf2, 0xcb, + 0x1d, 0xc9, 0x79, 0x3b, 0x4a, 0x72, 0xe7, 0xdb, 0xfa, 0x62, 0x8d, 0xf5, + 0x93, 0xfd, 0x32, 0x40, 0x09, 0x17, 0xa9, 0xda, 0x72, 0x02, 0xf4, 0xcb, + 0x8e, 0xb1, 0xe8, 0x64, 0x57, 0xf1, 0x94, 0xba, 0xe6, 0x24, 0x84, 0xf0, + 0xca, 0x0d, 0x6a, 0xeb, 0x1e, 0xde, 0x6e, 0xc6, 0x05, 0x55, 0x09, 0x99, + 0x18, 0x41, 0xe2, 0x55, 0x1a, 0x1f, 0xcc, 0xee, 0xae, 0x5f, 0x49, 0xb9, + 0x2b, 0x6a, 0xf8, 0xdd, 0x0e, 0x10, 0x9c, 0xef, 0x6e, 0xaa, 0xe9, 0x59, + 0x81, 0x1b, 0x4e, 0x8a, 0xac, 0x48, 0x6f, 0x7b, 0xc4, 0x62, 0x5f, 0x8c, + 0x59, 0x83, 0x96, 0xdb, 0x62, 0x88, 0x8f, 0x22, 0x57, 0x91, 0x0b, 0x9f, + 0xcd, 0xca, 0x6a, 0x3c, 0x71, 0x0b, 0x36, 0x8d, 0xf9, 0xbf, 0x3b, 0x37, + 0x05, 0xeb, 0xc3, 0x45, 0xc5, 0xeb, 0xe0, 0xdb, 0x12, 0x24, 0xe8, 0xad, + 0x83, 0xe8, 0x18, 0xd7, 0x67, 0x47, 0x0e, 0x53, 0x37, 0xf4, 0x16, 0xc5, + 0x5e, 0x82, 0x68, 0xfa, 0x8b, 0xe0, 0xde, 0xd1, 0x93, 0xea, 0x94, 0x70, + 0x4e, 0xfd, 0x5c, 0xd6, 0x4d, 0x99, 0x7b, 0xfc, 0x99, 0x2c, 0x65, 0x2b, + 0xe2, 0x29, 0xf1, 0x8f, 0x5c, 0x77, 0x30, 0x46, 0x11, 0x3f, 0x33, 0x2b, + 0xb1, 0x00, 0x50, 0x14, 0x97, 0x26, 0x39, 0xfd, 0xd5, 0xc2, 0x83, 0x0a, + 0x07, 0xe3, 0x4e, 0xa7, 0x82, 0x21, 0x4e, 0xb3, 0xef, 0xae, 0x0d, 0x7b, + 0xee, 0xe8, 0x1d, 0xf7, 0x31, 0xcb, 0x1e, 0x05, 0x4f, 0x8e, 0xf0, 0x67, + 0x36, 0x71, 0x23, 0x72, 0x11, 0x37, 0x0f, 0x4f, 0xf8, 0xc2, 0x04, 0xff, + 0x76, 0xb2, 0x77, 0xa2, 0xee, 0x79, 0xf1, 0x5f, 0x34, 0x6f, 0xf8, 0xda, + 0x93, 0xeb, 0x6f, 0x38, 0x7e, 0x14, 0xf0, 0xca, 0x14, 0x40, 0x5e, 0xb8, + 0x56, 0x7e, 0x61, 0x3e, 0xc0, 0x20, 0x3f, 0x2a, 0xac, 0x43, 0x69, 0xf2, + 0x10, 0xce, 0x33, 0x22, 0xe4, 0xdc, 0x9a, 0xac, 0x53, 0x95, 0x38, 0x16, + 0x81, 0xbc, 0xf0, 0x45, 0x64, 0x52, 0xbb, 0x20, 0x77, 0x3b, 0xa0, 0x92, + 0x40, 0xfd, 0x4b, 0x46, 0xe0, 0x5c, 0xaf, 0x3d, 0x87, 0xad, 0xf8, 0x90, + 0x2f, 0xdc, 0x27, 0x4f, 0x2d, 0xe6, 0xcd, 0x25 +}; +static const uint8_t ac_rsassa_vect19_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_rsassa_vect19_priv_exp[] = { + 0xae, 0x48, 0xc9, 0x31, 0x29, 0xf7, 0xd5, 0x01, 0x26, 0x21, 0x27, 0xd0, + 0xfb, 0xe9, 0xf7, 0xcc, 0xf6, 0xde, 0xf5, 0x89, 0xf3, 0x07, 0x8f, 0x6b, + 0x00, 0x39, 0x3c, 0x6d, 0xbe, 0x58, 0xa2, 0x37, 0xa2, 0xc1, 0x9a, 0x2a, + 0x84, 0x80, 0xc1, 0x31, 0x74, 0x9f, 0x27, 0x63, 0x94, 0x86, 0x96, 0x95, + 0xba, 0x66, 0x42, 0xc9, 0x2a, 0x38, 0xdf, 0x18, 0x8d, 0x02, 0xb3, 0x45, + 0x87, 0x3a, 0xbc, 0xda, 0x6f, 0x7a, 0x73, 0xf4, 0x70, 0xac, 0x43, 0x80, + 0xdc, 0x82, 0x7d, 0xa1, 0x6a, 0xcb, 0xe7, 0xb2, 0xb5, 0xb1, 0x8a, 0x1e, + 0xcb, 0x7f, 0xf5, 0xc8, 0x01, 0x11, 0x2c, 0x0e, 0x50, 0x1a, 0x5b, 0x71, + 0x64, 0x41, 0xb9, 0xe8, 0x53, 0x8c, 0x29, 0x4e, 0x20, 0x31, 0x5e, 0xc7, + 0xc5, 0x55, 0x88, 0x6d, 0xf5, 0x70, 0x0a, 0x6c, 0x3d, 0x0a, 0x00, 0xd6, + 0x61, 0x66, 0xa1, 0x91, 0x31, 0xa8, 0x87, 0xd1, 0xd0, 0x50, 0x14, 0x9e, + 0x93, 0x88, 0x86, 0x45, 0x1b, 0xf4, 0xa9, 0xdf, 0xff, 0x00, 0x0c, 0x3a, + 0xaf, 0x6e, 0x3d, 0xd8, 0x71, 0xd5, 0x72, 0xa1, 0x80, 0x11, 0xa0, 0xde, + 0xbb, 0xaf, 0x40, 0xc7, 0x8a, 0xde, 0xc5, 0x7e, 0x9b, 0x76, 0x94, 0x54, + 0xba, 0xc7, 0x1c, 0xab, 0x51, 0xac, 0xdb, 0x2b, 0x46, 0x93, 0xf8, 0xaf, + 0x5e, 0x71, 0x2d, 0x17, 0xc5, 0x6d, 0x6d, 0x2e, 0x3b, 0x8f, 0x8f, 0x9e, + 0x6b, 0x7c, 0x50, 0xe9, 0x04, 0xab, 0x21, 0x02, 0xed, 0xf9, 0x28, 0x43, + 0x7a, 0x9c, 0x4e, 0x2c, 0xcf, 0x69, 0x5a, 0x80, 0xff, 0x08, 0x1b, 0x9b, + 0x55, 0xc6, 0xff, 0xfd, 0xcf, 0x5f, 0xa5, 0x68, 0xec, 0xb5, 0xd5, 0xd4, + 0x16, 0x18, 0x35, 0xf9, 0x4e, 0xf5, 0xea, 0x03, 0x66, 0x6f, 0x65, 0x20, + 0xb0, 0x28, 0x82, 0x56, 0x90, 0x4d, 0xab, 0x7c, 0xdf, 0xe4, 0xb4, 0x17, + 0x5a, 0x45, 0x48, 0x85, 0x1b, 0x7e, 0x08, 0x71, 0xef, 0x4c, 0xd0, 0xdd, + 0x2a, 0x19, 0x3a, 0xed, 0x1f, 0x96, 0xa1, 0xf9, 0xca, 0xe0, 0x52, 0x27, + 0xd8, 0xf7, 0x9b, 0x0d, 0x4c, 0x82, 0x08, 0x46, 0xb6, 0xef, 0x53, 0x1b, + 0x72, 0x63, 0xb6, 0xe7, 0x3f, 0xa4, 0x5b, 0xed, 0x89, 0xeb, 0xc8, 0x10, + 0x78, 0x61, 0x68, 0x98, 0x8f, 0x87, 0x2f, 0xb9, 0x41, 0x31, 0x47, 0x20, + 0xf2, 0xde, 0x52, 0x2a, 0x17, 0x3f, 0x84, 0xad, 0x39, 0xec, 0x42, 0x1c, + 0x37, 0xbc, 0xb2, 0x7c, 0x43, 0xdb, 0x2e, 0x65, 0x43, 0x17, 0x9e, 0x8f, + 0xa0, 0x5b, 0x96, 0xc3, 0xd4, 0x2d, 0xc0, 0x52, 0x3b, 0xe4, 0x0b, 0xe5, + 0xaa, 0xcc, 0x1f, 0x57, 0xf0, 0xd6, 0xdd, 0x9a, 0xd1, 0x77, 0xea, 0x0c, + 0x7a, 0x8b, 0x69, 0xdb, 0xe9, 0x36, 0x63, 0x1d, 0x46, 0x23, 0x51, 0x9f, + 0x45, 0xce, 0xa4, 0x68, 0xb4, 0x6e, 0x65, 0x32, 0xef, 0xdf, 0xe8, 0xce, + 0xb6, 0x91, 0x91, 0xbc, 0x3a, 0xc0, 0xd3, 0xb2, 0x7f, 0xf4, 0x14, 0xbf, + 0xb8, 0xc9, 0x3d, 0x60, 0x99, 0x5f, 0x14, 0x45, 0x22, 0x07, 0x77, 0x08, + 0x32, 0xdd, 0xc8, 0x46, 0x3a, 0x3d, 0x2d, 0xa1, 0x4d, 0xc2, 0xa0, 0x3f, + 0xa1, 0xe8, 0x9d, 0x28, 0x57, 0x4c, 0x65, 0x03, 0x54, 0x6f, 0xbb, 0x1c, + 0x86, 0x47, 0x29, 0x44, 0x5c, 0xd4, 0x17, 0xed, 0x84, 0x60, 0xbf, 0xb6, + 0xb6, 0x0d, 0x0e, 0x47, 0xe2, 0x73, 0x95, 0xf4, 0x4d, 0x6a, 0x6a, 0x04, + 0x1b, 0xd4, 0x98, 0xb4, 0xcf, 0x8f, 0xe4, 0x0d, 0x14, 0x66, 0xa0, 0xf5, + 0x8d, 0x65, 0xdc, 0xb9, 0xdd, 0x1a, 0x2c, 0x9e, 0x71, 0x78, 0x5a, 0x98, + 0x13, 0x0d, 0x91, 0x40, 0xd1, 0x6f, 0x1c, 0x7a, 0x06, 0xab, 0x0b, 0xc1, + 0xd1, 0x19, 0x00, 0xca, 0x7a, 0xde, 0x45, 0x5c, 0x50, 0x53, 0x83, 0x71, + 0x45, 0x0a, 0x4b, 0x0f, 0x2f, 0x67, 0x3b, 0x39 +}; +static const uint8_t ac_rsassa_vect19_prime1[] = { + 0xfc, 0x1e, 0xca, 0x69, 0x92, 0x80, 0xf8, 0x54, 0x87, 0x29, 0xd4, 0x68, + 0xcb, 0xd6, 0xba, 0x1d, 0x4a, 0x29, 0x4c, 0xa1, 0x49, 0xd7, 0x42, 0x68, + 0x09, 0xb0, 0x66, 0xa1, 0x1e, 0xf8, 0x8a, 0xf2, 0x8b, 0xdc, 0x57, 0x70, + 0xa2, 0x29, 0x7f, 0x18, 0xce, 0x18, 0x88, 0x8a, 0x02, 0x60, 0xcf, 0x05, + 0x15, 0xa0, 0x98, 0x23, 0x77, 0xf4, 0x1a, 0xba, 0xc5, 0x9e, 0x61, 0xea, + 0x42, 0xfd, 0x86, 0x88, 0xca, 0x93, 0xa1, 0xf3, 0xf4, 0x0c, 0x38, 0x62, + 0x3a, 0x6e, 0x30, 0x0d, 0x52, 0xce, 0xc8, 0xdd, 0xf2, 0xc4, 0x75, 0x8b, + 0x44, 0xf9, 0x14, 0xcd, 0x09, 0xd9, 0x37, 0x0d, 0x09, 0x75, 0x82, 0xd6, + 0x1d, 0x86, 0x23, 0x29, 0xc7, 0x6f, 0xea, 0x88, 0x5a, 0x88, 0xc5, 0x69, + 0x4e, 0x67, 0x8b, 0x90, 0xd5, 0xc6, 0xe8, 0xd8, 0xd6, 0x05, 0xc9, 0xfe, + 0x2c, 0x56, 0x8f, 0xcb, 0xb7, 0x7e, 0x59, 0xfa, 0x16, 0x60, 0x8a, 0xf6, + 0xdc, 0x63, 0xe5, 0xfc, 0x24, 0x87, 0xc6, 0x2d, 0x94, 0x3d, 0x29, 0x0d, + 0xe8, 0xc7, 0x75, 0xe6, 0x32, 0xa3, 0x74, 0x50, 0xae, 0xdd, 0x03, 0x14, + 0x70, 0xbc, 0x61, 0x04, 0x07, 0xf4, 0x62, 0xa8, 0x79, 0x2b, 0xf8, 0xc4, + 0x69, 0xdb, 0x9a, 0x78, 0x97, 0xa7, 0x71, 0x4c, 0xde, 0x78, 0x5b, 0xab, + 0x08, 0x85, 0x0e, 0x34, 0xad, 0x64, 0x24, 0x41, 0x75, 0x24, 0xe0, 0x9b, + 0xa8, 0x98, 0x14, 0xe6, 0xe3, 0xf9, 0x59, 0xcc, 0x06, 0x67, 0xf0, 0x5e, + 0x3c, 0x75, 0x03, 0xb3, 0xcf, 0x35, 0x57, 0x28, 0x02, 0x6b, 0x42, 0x0f, + 0x9b, 0x3d, 0x7d, 0xa0, 0x26, 0xc6, 0xe0, 0x06, 0x3b, 0x97, 0x07, 0x0d, + 0x9b, 0xa4, 0xc5, 0x16, 0x91, 0x9d, 0xa3, 0xec, 0x8b, 0x49, 0x47, 0x44, + 0xd2, 0xdd, 0xd4, 0xd3, 0xc9, 0x88, 0xe3, 0x88, 0x57, 0xce, 0x3f, 0xc2, + 0x08, 0x77, 0x8f, 0x13 +}; +static const uint8_t ac_rsassa_vect19_prime2[] = { + 0xfa, 0x12, 0x6d, 0xe1, 0x5b, 0x6b, 0x88, 0x0e, 0x28, 0x61, 0x4c, 0x18, + 0xc8, 0x2f, 0xf5, 0xe7, 0x0e, 0xc6, 0x1e, 0x14, 0x3b, 0x5a, 0xe1, 0x51, + 0xbf, 0x64, 0x6f, 0x9e, 0xb7, 0xca, 0x3f, 0x57, 0xdb, 0xc2, 0x87, 0x8a, + 0x41, 0x57, 0xfb, 0xcd, 0x5d, 0x1a, 0xe6, 0x2a, 0x50, 0x0f, 0x60, 0xe1, + 0x81, 0x4a, 0x7c, 0xc5, 0xbf, 0xba, 0x37, 0x6f, 0xec, 0x30, 0xba, 0xcf, + 0x13, 0x51, 0x43, 0x19, 0x29, 0xaf, 0xb8, 0xc9, 0xee, 0x8d, 0x56, 0xee, + 0x3d, 0x90, 0x8e, 0x5e, 0x4d, 0xe6, 0x01, 0xbe, 0x26, 0xf9, 0x7e, 0x3a, + 0xaf, 0xa0, 0x56, 0xda, 0x9f, 0x29, 0x42, 0x84, 0x1c, 0x4b, 0xde, 0x67, + 0x32, 0xc1, 0xf0, 0xde, 0x5f, 0x89, 0x01, 0xc7, 0xb1, 0x8e, 0x2b, 0x15, + 0xf1, 0x59, 0x80, 0xf1, 0x9a, 0x15, 0x20, 0xfd, 0x53, 0xc1, 0x9f, 0xb7, + 0x4a, 0xde, 0xe0, 0x58, 0xac, 0x6c, 0xd2, 0x44, 0xb7, 0x9a, 0x0f, 0x8e, + 0xdc, 0xa2, 0x57, 0xf6, 0x69, 0x61, 0x37, 0xe3, 0x8a, 0xb4, 0xa6, 0xf4, + 0x08, 0x41, 0xfb, 0x22, 0xd1, 0xe4, 0x62, 0x4d, 0xac, 0x2d, 0x71, 0x7b, + 0x32, 0xe1, 0x5d, 0xa4, 0x29, 0xbd, 0xde, 0xa4, 0x87, 0xb9, 0xe7, 0xe4, + 0xd1, 0x12, 0x81, 0x15, 0xfd, 0x13, 0xff, 0xf0, 0xce, 0x8b, 0x4c, 0x3f, + 0x66, 0xe8, 0xb4, 0xd5, 0xa7, 0x09, 0xb0, 0x31, 0x2e, 0xbd, 0x86, 0x56, + 0xb4, 0xa2, 0xee, 0xc4, 0x17, 0xda, 0x86, 0x26, 0xb1, 0x14, 0x27, 0x1a, + 0x12, 0xed, 0x6a, 0xe2, 0xb5, 0x3f, 0x53, 0x3a, 0x23, 0xf6, 0x19, 0xb6, + 0xcc, 0x3b, 0x72, 0xcc, 0xf8, 0xde, 0xec, 0xe0, 0x68, 0x62, 0x5c, 0xe0, + 0xff, 0x34, 0x80, 0xab, 0x4d, 0x65, 0x46, 0x06, 0x06, 0xce, 0xb5, 0xd6, + 0xb0, 0xca, 0x76, 0x82, 0xed, 0x13, 0x5d, 0x5b, 0xc9, 0x8c, 0xf0, 0x1e, + 0xfd, 0x47, 0xe1, 0xe7 +}; +static const uint8_t ac_rsassa_vect19_exp1[] = { + 0xa2, 0x90, 0xf0, 0x0f, 0x56, 0xca, 0x16, 0x55, 0xda, 0xb9, 0x9c, 0x1e, + 0xde, 0xa0, 0xdc, 0x6d, 0x1a, 0x6e, 0xba, 0xdc, 0x9d, 0x12, 0x51, 0xdd, + 0x67, 0xb1, 0xf8, 0xdb, 0x17, 0x6f, 0x47, 0x98, 0xd1, 0x9a, 0x08, 0x3f, + 0xb6, 0x30, 0x6f, 0xa5, 0x7c, 0xee, 0xd0, 0xcb, 0xbc, 0x70, 0xd3, 0xcc, + 0x01, 0x80, 0x05, 0xd9, 0x88, 0xf5, 0x3b, 0x6f, 0x07, 0x11, 0xf3, 0x2c, + 0xec, 0x79, 0x31, 0x10, 0x6f, 0x1e, 0xf6, 0xa4, 0xa8, 0xce, 0x60, 0x64, + 0xe6, 0x2c, 0x3a, 0x8b, 0xbc, 0xc3, 0x5d, 0x3d, 0xcf, 0xd5, 0xe1, 0xbd, + 0x25, 0x82, 0x3e, 0x69, 0x5f, 0x5a, 0x52, 0x66, 0xf3, 0x9c, 0x73, 0xfa, + 0xc0, 0x1a, 0xc7, 0xfd, 0x9e, 0x7d, 0x89, 0x8a, 0xd6, 0x65, 0xae, 0x75, + 0x12, 0x7b, 0x2d, 0xc0, 0xfc, 0x37, 0x3f, 0xd8, 0xe1, 0x57, 0xe6, 0x41, + 0x20, 0x31, 0xc8, 0x92, 0xa1, 0x04, 0xb5, 0xdb, 0xce, 0x25, 0xfe, 0x34, + 0xe3, 0x32, 0xff, 0x0e, 0xb0, 0x37, 0x64, 0x0f, 0xeb, 0xaf, 0xec, 0x12, + 0xed, 0xef, 0xff, 0x13, 0xa9, 0xbf, 0x3f, 0xb6, 0xee, 0xa9, 0xcf, 0xdc, + 0x94, 0x3c, 0xc3, 0x89, 0xa7, 0xdf, 0x6a, 0xe6, 0x1b, 0x0b, 0xc1, 0x62, + 0x54, 0xa7, 0xa7, 0x58, 0xee, 0xe0, 0xa6, 0xeb, 0xdb, 0xdf, 0x5b, 0xac, + 0x52, 0xd8, 0x08, 0xaa, 0xea, 0xca, 0xd1, 0x9d, 0xeb, 0x7d, 0x15, 0xdf, + 0x08, 0xbc, 0xd7, 0x6d, 0x71, 0xbe, 0x4c, 0xaa, 0x83, 0xce, 0xed, 0x6c, + 0xb6, 0x2a, 0xf5, 0x72, 0x31, 0xbf, 0xc1, 0x2d, 0x29, 0x32, 0x23, 0xec, + 0x90, 0x3a, 0xfc, 0x10, 0x12, 0x30, 0xd6, 0x2e, 0xee, 0xa9, 0x99, 0x80, + 0xaa, 0xc5, 0x79, 0xd7, 0xed, 0x98, 0xea, 0x24, 0x12, 0x43, 0xf3, 0xd2, + 0x6a, 0xed, 0x62, 0xd8, 0x14, 0xf1, 0x51, 0x55, 0x8e, 0xd8, 0x8c, 0xbf, + 0xfe, 0x59, 0xa9, 0x45 +}; +static const uint8_t ac_rsassa_vect19_exp2[] = { + 0xd8, 0x59, 0x37, 0x5d, 0x1f, 0xd5, 0xa1, 0x48, 0xf6, 0x60, 0x6f, 0x10, + 0x85, 0xa9, 0x10, 0xaa, 0x8d, 0x1a, 0x94, 0x0d, 0x56, 0xe8, 0xa2, 0x45, + 0x32, 0x3b, 0x77, 0x62, 0x2e, 0x89, 0xb8, 0x51, 0x8f, 0x9b, 0xf5, 0xdd, + 0x83, 0xf8, 0xd5, 0xad, 0x6f, 0x5e, 0x85, 0x40, 0x98, 0x31, 0x25, 0xd5, + 0x13, 0x21, 0x59, 0x5f, 0x50, 0x27, 0x90, 0x2c, 0xb1, 0x7f, 0xdb, 0x2e, + 0xa9, 0xfc, 0xc4, 0xfb, 0x31, 0x18, 0x88, 0xdb, 0x93, 0x1a, 0x0e, 0xda, + 0x60, 0xc2, 0xfe, 0x98, 0xd1, 0xf6, 0x2b, 0x0d, 0xd2, 0xf4, 0x48, 0xe4, + 0x06, 0xeb, 0xc6, 0x18, 0xb0, 0x58, 0x66, 0xe6, 0x9b, 0x00, 0x7c, 0x72, + 0x75, 0xf4, 0x5a, 0x2a, 0x59, 0x26, 0xd4, 0x36, 0x6b, 0x03, 0x9f, 0x7d, + 0x05, 0x68, 0x34, 0xe9, 0x51, 0x2f, 0xf4, 0x71, 0x96, 0x93, 0xce, 0x55, + 0x2a, 0x5e, 0x36, 0x64, 0x21, 0x10, 0xa8, 0xbd, 0xb0, 0xc6, 0x85, 0xad, + 0x48, 0x6e, 0xdf, 0x81, 0x1c, 0xdc, 0x72, 0x18, 0xd6, 0xf8, 0xc1, 0xf4, + 0x20, 0x6c, 0xcd, 0x13, 0xeb, 0xd9, 0x15, 0xbf, 0x33, 0x35, 0xc1, 0x97, + 0x1f, 0x86, 0xe0, 0x97, 0xd5, 0x51, 0x22, 0x1c, 0xe0, 0x1b, 0xd3, 0x67, + 0x20, 0x06, 0x4d, 0x4d, 0xb3, 0xbd, 0x28, 0xd1, 0xb2, 0x2f, 0xcb, 0x90, + 0x92, 0xbc, 0xc3, 0x2e, 0x90, 0xac, 0x0e, 0x16, 0x0e, 0xe5, 0x03, 0x23, + 0x62, 0x76, 0x0f, 0xf1, 0xf0, 0xdd, 0x2a, 0xf0, 0xb0, 0x84, 0xc9, 0xeb, + 0x81, 0xf2, 0x8b, 0x65, 0x85, 0xff, 0x3a, 0x46, 0xf3, 0xb3, 0xc7, 0xbd, + 0x61, 0x66, 0x11, 0x45, 0x0a, 0x0e, 0xfb, 0x8a, 0x8e, 0x64, 0x83, 0x0c, + 0x59, 0x5e, 0x97, 0xef, 0x1c, 0x2f, 0x80, 0xec, 0x57, 0xd9, 0x60, 0x72, + 0x54, 0x53, 0x65, 0x42, 0x92, 0x4f, 0x0d, 0x97, 0x0a, 0x81, 0x77, 0x80, + 0xa8, 0x0a, 0x17, 0x83 +}; +static const uint8_t ac_rsassa_vect19_coeff[] = { + 0x47, 0xcc, 0x01, 0x3c, 0xe5, 0xd4, 0x0f, 0xce, 0xd4, 0x07, 0x20, 0x80, + 0x3b, 0xb3, 0xfc, 0x46, 0x34, 0x46, 0x8f, 0xe7, 0xf4, 0x31, 0xf4, 0x13, + 0x7b, 0x13, 0x3c, 0xb4, 0x55, 0x3d, 0x77, 0xcb, 0x38, 0xb4, 0xe1, 0x56, + 0x27, 0x96, 0xcd, 0x55, 0x4b, 0x73, 0x2e, 0xf6, 0x13, 0x3b, 0x9d, 0x23, + 0x01, 0x4d, 0x05, 0xce, 0x44, 0x46, 0xc4, 0xa3, 0xc6, 0x1d, 0x86, 0x16, + 0xcc, 0xf0, 0xe5, 0x66, 0xcf, 0xc0, 0xed, 0x35, 0x44, 0xe9, 0x58, 0x42, + 0x32, 0x9a, 0x5b, 0x6d, 0x47, 0xcc, 0x11, 0x7a, 0x79, 0x47, 0x46, 0x82, + 0xda, 0x57, 0x80, 0x8f, 0xe2, 0xf6, 0xd5, 0xc4, 0x71, 0x57, 0x1e, 0x1a, + 0xe5, 0x04, 0x06, 0x3e, 0x9e, 0xec, 0xcd, 0x16, 0x17, 0xaf, 0x25, 0x85, + 0xcd, 0xdb, 0x55, 0xce, 0x9b, 0xab, 0xbc, 0x57, 0x36, 0x66, 0x48, 0xdb, + 0x6c, 0x3a, 0x96, 0x71, 0x83, 0x90, 0x7a, 0xa4, 0x87, 0xb5, 0xcd, 0x6a, + 0x8a, 0x27, 0x21, 0x2c, 0xa5, 0xba, 0x62, 0x07, 0x28, 0xe3, 0x77, 0xca, + 0x19, 0xed, 0x7a, 0x55, 0xb8, 0x0c, 0x1c, 0x17, 0x08, 0xa6, 0xf6, 0xd3, + 0xda, 0x2c, 0x20, 0x25, 0xb9, 0xb7, 0x3e, 0x2e, 0xe6, 0x25, 0x32, 0xb2, + 0xc3, 0x06, 0x63, 0xfb, 0xfb, 0x16, 0x3f, 0x66, 0x18, 0x82, 0x0d, 0x15, + 0x37, 0x35, 0x97, 0x17, 0x79, 0xad, 0xd8, 0x96, 0xa1, 0x20, 0x51, 0xd5, + 0xb8, 0xb9, 0x53, 0x85, 0x20, 0xbe, 0x71, 0xac, 0xa3, 0xe6, 0x8d, 0xeb, + 0xef, 0x1b, 0x8e, 0x42, 0x89, 0xf4, 0x5c, 0x10, 0x80, 0x8a, 0xac, 0xe4, + 0xbf, 0xd1, 0xbd, 0x40, 0x47, 0x62, 0x95, 0xfb, 0xab, 0xd1, 0xac, 0x28, + 0x6c, 0xa4, 0xfc, 0xbb, 0x77, 0x1f, 0xdb, 0x91, 0xa7, 0xff, 0x90, 0x49, + 0x74, 0xee, 0x32, 0x28, 0xbc, 0x15, 0x44, 0x17, 0xdf, 0x30, 0x5a, 0xb6, + 0x91, 0xe2, 0x87, 0x02 +}; +static const uint8_t ac_rsassa_vect19_ptx[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10 +}; +static const uint8_t ac_rsassa_vect19_out[] = { + 0x5c, 0x9c, 0x79, 0x1b, 0xd1, 0x64, 0x6a, 0xb5, 0xc7, 0xd9, 0xb1, 0x7c, + 0xd0, 0x3b, 0x05, 0xae, 0x9f, 0x93, 0x36, 0xcd, 0xa3, 0x38, 0x1b, 0xc6, + 0x23, 0x81, 0x72, 0xd7, 0x57, 0xa4, 0x16, 0x07, 0x2c, 0xc0, 0x63, 0x38, + 0x01, 0x51, 0x58, 0x6d, 0x24, 0xcd, 0x7b, 0x24, 0x86, 0xd4, 0x5a, 0xb5, + 0x44, 0x47, 0x13, 0xc4, 0xaf, 0xce, 0x1d, 0x1e, 0x5d, 0x23, 0xb2, 0xe8, + 0xae, 0x14, 0x2f, 0x61, 0xf5, 0xf4, 0x7f, 0x37, 0x83, 0x1c, 0x55, 0xdb, + 0xb8, 0xd9, 0x27, 0xf4, 0xa7, 0x39, 0x77, 0x3b, 0x73, 0xdb, 0x1a, 0x1d, + 0xf7, 0x21, 0x82, 0xb7, 0xda, 0xce, 0x76, 0x90, 0xf2, 0xda, 0x18, 0x0b, + 0xf9, 0x11, 0x4f, 0x64, 0xc4, 0x1d, 0xe2, 0xd4, 0xd0, 0x6a, 0xfb, 0x6f, + 0x1b, 0x32, 0x2f, 0x4a, 0xcc, 0x6f, 0x5b, 0x28, 0x7f, 0x26, 0xe8, 0x4b, + 0x6e, 0x0a, 0x4b, 0x62, 0xef, 0xd9, 0x88, 0x23, 0x1c, 0xea, 0x4f, 0x1a, + 0x0a, 0x3a, 0xbd, 0xf6, 0x7d, 0xdc, 0xca, 0x57, 0xc8, 0x68, 0xa6, 0xb3, + 0x16, 0xa2, 0xe9, 0x6e, 0x56, 0x69, 0xc9, 0x62, 0xf4, 0x12, 0xf5, 0x48, + 0xcf, 0x34, 0x2a, 0x5b, 0x4f, 0xf1, 0x0c, 0xb6, 0x24, 0x04, 0x9d, 0x4f, + 0xb0, 0xd3, 0x11, 0x43, 0x29, 0x89, 0x99, 0x9b, 0xb1, 0xe3, 0x8c, 0x00, + 0x83, 0xe3, 0xbe, 0x94, 0xbf, 0x1f, 0xf1, 0x5c, 0x83, 0xe9, 0x01, 0xb9, + 0xec, 0x41, 0x73, 0x23, 0x98, 0x5e, 0x20, 0x91, 0xca, 0x56, 0x3f, 0x6f, + 0x6b, 0x50, 0x6d, 0x94, 0x3e, 0x2e, 0x1b, 0xb3, 0xc5, 0x74, 0x8f, 0x3a, + 0xaf, 0x21, 0x49, 0x7e, 0x9a, 0xe8, 0x85, 0x95, 0xd5, 0x87, 0xb1, 0xd7, + 0x0a, 0xf2, 0x35, 0x59, 0x1d, 0xe5, 0x8e, 0x9e, 0xc8, 0xa0, 0x84, 0xd1, + 0xdf, 0xea, 0x20, 0x16, 0x16, 0x1c, 0x35, 0x69, 0x37, 0x3d, 0x38, 0x3a, + 0x53, 0x97, 0x1f, 0xa8, 0x3a, 0xa6, 0x41, 0xc6, 0xd4, 0x7e, 0xac, 0xd3, + 0x9e, 0x24, 0x22, 0x9b, 0xb9, 0x6e, 0xfb, 0xd9, 0x23, 0x65, 0xd5, 0xda, + 0x28, 0xb3, 0x0c, 0x74, 0x8b, 0xb6, 0xfa, 0x5b, 0xd4, 0x1e, 0x95, 0x1c, + 0x08, 0xd0, 0x38, 0x7c, 0xef, 0x6e, 0xb3, 0xee, 0x5b, 0x3b, 0x66, 0xa9, + 0x5f, 0x74, 0xab, 0x29, 0x3c, 0x6d, 0x58, 0x51, 0x95, 0x5f, 0xb0, 0x68, + 0x5d, 0xc5, 0x78, 0xe4, 0x7a, 0x1c, 0x1d, 0x37, 0xde, 0xdf, 0xd9, 0xae, + 0xa0, 0x9b, 0xcd, 0x42, 0x60, 0x74, 0x07, 0x6d, 0xbc, 0x37, 0x80, 0x49, + 0x8f, 0xdf, 0x7e, 0x6e, 0x7d, 0x54, 0xde, 0x7f, 0x0c, 0x06, 0xb9, 0xe8, + 0xc2, 0x5b, 0xed, 0xaa, 0xe5, 0x87, 0xc7, 0xed, 0xe5, 0x90, 0x98, 0xbb, + 0xf4, 0xf3, 0x76, 0x96, 0x7f, 0xc1, 0xe8, 0x49, 0xbc, 0x78, 0x56, 0xf1, + 0x5e, 0x87, 0xbd, 0xca, 0xd9, 0xdb, 0xf7, 0xa4, 0x13, 0xc5, 0x32, 0x51, + 0x27, 0xa4, 0xeb, 0xd8, 0x1b, 0xf5, 0x37, 0xcd, 0x1c, 0xba, 0x7b, 0xb5, + 0x0c, 0xce, 0x71, 0xcb, 0x18, 0xfb, 0x61, 0x60, 0xe7, 0xc0, 0x06, 0xd0, + 0x09, 0xc7, 0xbf, 0x3f, 0x7b, 0x55, 0x52, 0x88, 0xa8, 0x7a, 0x94, 0xcf, + 0x15, 0x5d, 0x97, 0xba, 0x9a, 0xa8, 0xe2, 0x37, 0xe6, 0xe7, 0xf3, 0x2b, + 0xc2, 0xec, 0x33, 0x0b, 0xe7, 0x60, 0xa2, 0xc3, 0x63, 0x89, 0xc6, 0xf1, + 0xe5, 0xda, 0x13, 0xd5, 0xcc, 0x27, 0x35, 0xf8, 0x9f, 0xa8, 0x21, 0x49, + 0x09, 0x5b, 0x6b, 0xaf, 0x65, 0xbf, 0xb8, 0x6e, 0x5b, 0xf1, 0x61, 0xf4, + 0xd3, 0xe9, 0xb5, 0x20, 0x01, 0x40, 0xd6, 0x81, 0x1e, 0x4f, 0xcd, 0x77, + 0x51, 0x80, 0x6d, 0x69, 0xc7, 0xba, 0xf8, 0x2b, 0x38, 0x02, 0xa1, 0x9b, + 0x36, 0x8d, 0x56, 0xcf, 0x88, 0xb8, 0x71, 0x29, 0x08, 0x69, 0xbe, 0x68, + 0x98, 0x84, 0xbb, 0x38, 0xe7, 0xc0, 0x0f, 0x05 +}; + +/* + * Test data from ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt + * + * As specified in PKCS#1, the block type for this operation + * is 1. The digest algorithm is SHA-1; i.e. the given message + * must be hashed and the SHA-1 hash must be encapsulated in a + * DigestInfo structure as specified in PKCS#1 v1.5. + */ + +/* PKCS#1 v1.5 Signature Example 1 1024-bit RSA key pair */ +static const uint8_t ac_rsassa_example1_modulus[] = { + 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51, 0x87, 0xdc, + 0x7e, 0xa8, 0x41, 0xd1, + 0x56, 0xf2, 0xec, 0x0e, 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, + 0x1f, 0x7a, 0xd9, 0x91, + 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62, 0xb4, 0xc0, 0xf2, 0x83, + 0xa1, 0x2a, 0x88, 0xa3, + 0x94, 0xdf, 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab, + 0xfc, 0xe0, 0xb1, 0xdf, + 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d, 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, + 0x71, 0xef, 0x63, 0x77, + 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59, 0x8e, 0x6f, + 0xf8, 0x9d, 0x19, 0xf1, + 0x05, 0xac, 0xc2, 0xd3, 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, + 0x6b, 0x6f, 0x64, 0xc4, + 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8, 0xcf, 0xfb, 0x22, 0x49, + 0xbd, 0x9a, 0x21, 0x37, +}; +static const uint8_t ac_rsassa_example1_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_rsassa_example1_priv_exp[] = { + 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51, 0xca, 0x9b, + 0xbb, 0xd0, 0xb4, 0x47, + 0x71, 0xa1, 0x01, 0xaf, 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, + 0x4b, 0xbe, 0x92, 0xe8, + 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f, 0x97, 0x85, 0x3a, 0xd0, + 0x7c, 0x02, 0x66, 0xc8, + 0xc6, 0xa3, 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44, + 0x29, 0xfc, 0x4d, 0x9a, + 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10, 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, + 0x34, 0xe4, 0x47, 0x27, + 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c, 0x2a, 0xba, + 0xca, 0xba, 0x28, 0x3c, + 0x31, 0xb4, 0xbd, 0x2f, 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, + 0x4f, 0x9e, 0x50, 0x3b, + 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc, 0xee, 0x88, 0x35, 0x47, + 0xc6, 0xa3, 0xb3, 0x25, +}; +static const uint8_t ac_rsassa_example1_prime1[] = { + 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73, 0xa3, 0x56, + 0x05, 0x3e, 0xa2, 0xa1, + 0xbc, 0x0c, 0x94, 0xaa, 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, + 0xfc, 0x96, 0x79, 0x48, + 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb, 0x35, 0x70, 0x6e, 0x09, + 0xa1, 0xdf, 0x55, 0xa1, + 0x53, 0x5b, 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e, + 0xda, 0x8e, 0x64, 0x43, +}; +static const uint8_t ac_rsassa_example1_prime2[] = { + 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7, 0x5b, 0x90, + 0xfc, 0xca, 0x87, 0x4a, + 0xbc, 0xde, 0x12, 0x3f, 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, + 0x6e, 0x48, 0xde, 0x8d, + 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba, 0x27, 0x58, 0x74, 0xf5, + 0x42, 0xcd, 0x20, 0xdc, + 0x72, 0x3e, 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26, + 0x9a, 0x67, 0x99, 0xfd, +}; +static const uint8_t ac_rsassa_example1_exp1[] = { + 0x28, 0xfa, 0x13, 0x93, 0x86, 0x55, 0xbe, 0x1f, 0x8a, 0x15, 0x9c, 0xba, + 0xca, 0x5a, 0x72, 0xea, + 0x19, 0x0c, 0x30, 0x08, 0x9e, 0x19, 0xcd, 0x27, 0x4a, 0x55, 0x6f, 0x36, + 0xc4, 0xf6, 0xe1, 0x9f, + 0x55, 0x4b, 0x34, 0xc0, 0x77, 0x79, 0x04, 0x27, 0xbb, 0xdd, 0x8d, 0xd3, + 0xed, 0xe2, 0x44, 0x83, + 0x28, 0xf3, 0x85, 0xd8, 0x1b, 0x30, 0xe8, 0xe4, 0x3b, 0x2f, 0xff, 0xa0, + 0x27, 0x86, 0x19, 0x79, +}; +static const uint8_t ac_rsassa_example1_exp2[] = { + 0x1a, 0x8b, 0x38, 0xf3, 0x98, 0xfa, 0x71, 0x20, 0x49, 0x89, 0x8d, 0x7f, + 0xb7, 0x9e, 0xe0, 0xa7, + 0x76, 0x68, 0x79, 0x12, 0x99, 0xcd, 0xfa, 0x09, 0xef, 0xc0, 0xe5, 0x07, + 0xac, 0xb2, 0x1e, 0xd7, + 0x43, 0x01, 0xef, 0x5b, 0xfd, 0x48, 0xbe, 0x45, 0x5e, 0xae, 0xb6, 0xe1, + 0x67, 0x82, 0x55, 0x82, + 0x75, 0x80, 0xa8, 0xe4, 0xe8, 0xe1, 0x41, 0x51, 0xd1, 0x51, 0x0a, 0x82, + 0xa3, 0xf2, 0xe7, 0x29, +}; +static const uint8_t ac_rsassa_example1_coeff[] = { + 0x27, 0x15, 0x6a, 0xba, 0x41, 0x26, 0xd2, 0x4a, 0x81, 0xf3, 0xa5, 0x28, + 0xcb, 0xfb, 0x27, 0xf5, + 0x68, 0x86, 0xf8, 0x40, 0xa9, 0xf6, 0xe8, 0x6e, 0x17, 0xa4, 0x4b, 0x94, + 0xfe, 0x93, 0x19, 0x58, + 0x4b, 0x8e, 0x22, 0xfd, 0xde, 0x1e, 0x5a, 0x2e, 0x3b, 0xd8, 0xaa, 0x5b, + 0xa8, 0xd8, 0x58, 0x41, + 0x94, 0xeb, 0x21, 0x90, 0xac, 0xf8, 0x32, 0xb8, 0x47, 0xf1, 0x3a, 0x3d, + 0x24, 0xa7, 0x9f, 0x4d, +}; + +/* PKCS#1 v1.5 Signature Example 1.1 */ +#define ac_rsassa_vect3_modulus ac_rsassa_example1_modulus +#define ac_rsassa_vect3_pub_exp ac_rsassa_example1_pub_exp +#define ac_rsassa_vect3_priv_exp ac_rsassa_example1_priv_exp +#define ac_rsassa_vect3_prime1 ac_rsassa_example1_prime1 +#define ac_rsassa_vect3_prime2 ac_rsassa_example1_prime2 +#define ac_rsassa_vect3_exp1 ac_rsassa_example1_exp1 +#define ac_rsassa_vect3_exp2 ac_rsassa_example1_exp2 +#define ac_rsassa_vect3_coeff ac_rsassa_example1_coeff +static const uint8_t ac_rsassa_vect3_ptx[] = { + 0xcd, 0xc8, 0x7d, 0xa2, 0x23, 0xd7, 0x86, 0xdf, 0x3b, 0x45, 0xe0, 0xbb, + 0xbc, 0x72, 0x13, 0x26, + 0xd1, 0xee, 0x2a, 0xf8, 0x06, 0xcc, 0x31, 0x54, 0x75, 0xcc, 0x6f, 0x0d, + 0x9c, 0x66, 0xe1, 0xb6, + 0x23, 0x71, 0xd4, 0x5c, 0xe2, 0x39, 0x2e, 0x1a, 0xc9, 0x28, 0x44, 0xc3, + 0x10, 0x10, 0x2f, 0x15, + 0x6a, 0x0d, 0x8d, 0x52, 0xc1, 0xf4, 0xc4, 0x0b, 0xa3, 0xaa, 0x65, 0x09, + 0x57, 0x86, 0xcb, 0x76, + 0x97, 0x57, 0xa6, 0x56, 0x3b, 0xa9, 0x58, 0xfe, 0xd0, 0xbc, 0xc9, 0x84, + 0xe8, 0xb5, 0x17, 0xa3, + 0xd5, 0xf5, 0x15, 0xb2, 0x3b, 0x8a, 0x41, 0xe7, 0x4a, 0xa8, 0x67, 0x69, + 0x3f, 0x90, 0xdf, 0xb0, + 0x61, 0xa6, 0xe8, 0x6d, 0xfa, 0xae, 0xe6, 0x44, 0x72, 0xc0, 0x0e, 0x5f, + 0x20, 0x94, 0x57, 0x29, + 0xcb, 0xeb, 0xe7, 0x7f, 0x06, 0xce, 0x78, 0xe0, 0x8f, 0x40, 0x98, 0xfb, + 0xa4, 0x1f, 0x9d, 0x61, + 0x93, 0xc0, 0x31, 0x7e, 0x8b, 0x60, 0xd4, 0xb6, 0x08, 0x4a, 0xcb, 0x42, + 0xd2, 0x9e, 0x38, 0x08, + 0xa3, 0xbc, 0x37, 0x2d, 0x85, 0xe3, 0x31, 0x17, 0x0f, 0xcb, 0xf7, 0xcc, + 0x72, 0xd0, 0xb7, 0x1c, + 0x29, 0x66, 0x48, 0xb3, 0xa4, 0xd1, 0x0f, 0x41, 0x62, 0x95, 0xd0, 0x80, + 0x7a, 0xa6, 0x25, 0xca, + 0xb2, 0x74, 0x4f, 0xd9, 0xea, 0x8f, 0xd2, 0x23, 0xc4, 0x25, 0x37, 0x02, + 0x98, 0x28, 0xbd, 0x16, + 0xbe, 0x02, 0x54, 0x6f, 0x13, 0x0f, 0xd2, 0xe3, 0x3b, 0x93, 0x6d, 0x26, + 0x76, 0xe0, 0x8a, 0xed, + 0x1b, 0x73, 0x31, 0x8b, 0x75, 0x0a, 0x01, 0x67, 0xd0, +}; +static const uint8_t ac_rsassa_vect3_out[] = { + 0x6b, 0xc3, 0xa0, 0x66, 0x56, 0x84, 0x29, 0x30, 0xa2, 0x47, 0xe3, 0x0d, + 0x58, 0x64, 0xb4, 0xd8, + 0x19, 0x23, 0x6b, 0xa7, 0xc6, 0x89, 0x65, 0x86, 0x2a, 0xd7, 0xdb, 0xc4, + 0xe2, 0x4a, 0xf2, 0x8e, + 0x86, 0xbb, 0x53, 0x1f, 0x03, 0x35, 0x8b, 0xe5, 0xfb, 0x74, 0x77, 0x7c, + 0x60, 0x86, 0xf8, 0x50, + 0xca, 0xef, 0x89, 0x3f, 0x0d, 0x6f, 0xcc, 0x2d, 0x0c, 0x91, 0xec, 0x01, + 0x36, 0x93, 0xb4, 0xea, + 0x00, 0xb8, 0x0c, 0xd4, 0x9a, 0xac, 0x4e, 0xcb, 0x5f, 0x89, 0x11, 0xaf, + 0xe5, 0x39, 0xad, 0xa4, + 0xa8, 0xf3, 0x82, 0x3d, 0x1d, 0x13, 0xe4, 0x72, 0xd1, 0x49, 0x05, 0x47, + 0xc6, 0x59, 0xc7, 0x61, + 0x7f, 0x3d, 0x24, 0x08, 0x7d, 0xdb, 0x6f, 0x2b, 0x72, 0x09, 0x61, 0x67, + 0xfc, 0x09, 0x7c, 0xab, + 0x18, 0xe9, 0xa4, 0x58, 0xfc, 0xb6, 0x34, 0xcd, 0xce, 0x8e, 0xe3, 0x58, + 0x94, 0xc4, 0x84, 0xd7, +}; + +/* PKCS#1 v1.5 Signature Example 1.2 */ +#define ac_rsassa_vect4_modulus ac_rsassa_example1_modulus +#define ac_rsassa_vect4_pub_exp ac_rsassa_example1_pub_exp +#define ac_rsassa_vect4_priv_exp ac_rsassa_example1_priv_exp +#define ac_rsassa_vect4_prime1 ac_rsassa_example1_prime1 +#define ac_rsassa_vect4_prime2 ac_rsassa_example1_prime2 +#define ac_rsassa_vect4_exp1 ac_rsassa_example1_exp1 +#define ac_rsassa_vect4_exp2 ac_rsassa_example1_exp2 +#define ac_rsassa_vect4_coeff ac_rsassa_example1_coeff +static const uint8_t ac_rsassa_vect4_ptx[] = { + 0x85, 0x13, 0x84, 0xcd, 0xfe, 0x81, 0x9c, 0x22, 0xed, 0x6c, 0x4c, 0xcb, + 0x30, 0xda, 0xeb, 0x5c, + 0xf0, 0x59, 0xbc, 0x8e, 0x11, 0x66, 0xb7, 0xe3, 0x53, 0x0c, 0x4c, 0x23, + 0x3e, 0x2b, 0x5f, 0x8f, + 0x71, 0xa1, 0xcc, 0xa5, 0x82, 0xd4, 0x3e, 0xcc, 0x72, 0xb1, 0xbc, 0xa1, + 0x6d, 0xfc, 0x70, 0x13, + 0x22, 0x6b, 0x9e, +}; +static const uint8_t ac_rsassa_vect4_out[] = { + 0x84, 0xfd, 0x2c, 0xe7, 0x34, 0xec, 0x1d, 0xa8, 0x28, 0xd0, 0xf1, 0x5b, + 0xf4, 0x9a, 0x87, 0x07, + 0xc1, 0x5d, 0x05, 0x94, 0x81, 0x36, 0xde, 0x53, 0x7a, 0x3d, 0xb4, 0x21, + 0x38, 0x41, 0x67, 0xc8, + 0x6f, 0xae, 0x02, 0x25, 0x87, 0xee, 0x9e, 0x13, 0x7d, 0xae, 0xe7, 0x54, + 0x73, 0x82, 0x62, 0x93, + 0x2d, 0x27, 0x1c, 0x74, 0x4c, 0x6d, 0x3a, 0x18, 0x9a, 0xd4, 0x31, 0x1b, + 0xdb, 0x02, 0x04, 0x92, + 0xe3, 0x22, 0xfb, 0xdd, 0xc4, 0x04, 0x06, 0xea, 0x86, 0x0d, 0x4e, 0x8e, + 0xa2, 0xa4, 0x08, 0x4a, + 0xa9, 0x8b, 0x96, 0x22, 0xa4, 0x46, 0x75, 0x6f, 0xdb, 0x74, 0x0d, 0xdb, + 0x3d, 0x91, 0xdb, 0x76, + 0x70, 0xe2, 0x11, 0x66, 0x1b, 0xbf, 0x87, 0x09, 0xb1, 0x1c, 0x08, 0xa7, + 0x07, 0x71, 0x42, 0x2d, + 0x1a, 0x12, 0xde, 0xf2, 0x9f, 0x06, 0x88, 0xa1, 0x92, 0xae, 0xbd, 0x89, + 0xe0, 0xf8, 0x96, 0xf8, +}; + +/* PKCS#1 v1.5 Signature Example 1.3 */ +#define ac_rsassa_vect5_modulus ac_rsassa_example1_modulus +#define ac_rsassa_vect5_pub_exp ac_rsassa_example1_pub_exp +#define ac_rsassa_vect5_priv_exp ac_rsassa_example1_priv_exp +#define ac_rsassa_vect5_prime1 ac_rsassa_example1_prime1 +#define ac_rsassa_vect5_prime2 ac_rsassa_example1_prime2 +#define ac_rsassa_vect5_exp1 ac_rsassa_example1_exp1 +#define ac_rsassa_vect5_exp2 ac_rsassa_example1_exp2 +#define ac_rsassa_vect5_coeff ac_rsassa_example1_coeff +static const uint8_t ac_rsassa_vect5_ptx[] = { + 0xa4, 0xb1, 0x59, 0x94, 0x17, 0x61, 0xc4, 0x0c, 0x6a, 0x82, 0xf2, 0xb8, + 0x0d, 0x1b, 0x94, 0xf5, + 0xaa, 0x26, 0x54, 0xfd, 0x17, 0xe1, 0x2d, 0x58, 0x88, 0x64, 0x67, 0x9b, + 0x54, 0xcd, 0x04, 0xef, + 0x8b, 0xd0, 0x30, 0x12, 0xbe, 0x8d, 0xc3, 0x7f, 0x4b, 0x83, 0xaf, 0x79, + 0x63, 0xfa, 0xff, 0x0d, + 0xfa, 0x22, 0x54, 0x77, 0x43, 0x7c, 0x48, 0x01, 0x7f, 0xf2, 0xbe, 0x81, + 0x91, 0xcf, 0x39, 0x55, + 0xfc, 0x07, 0x35, 0x6e, 0xab, 0x3f, 0x32, 0x2f, 0x7f, 0x62, 0x0e, 0x21, + 0xd2, 0x54, 0xe5, 0xdb, + 0x43, 0x24, 0x27, 0x9f, 0xe0, 0x67, 0xe0, 0x91, 0x0e, 0x2e, 0x81, 0xca, + 0x2c, 0xab, 0x31, 0xc7, + 0x45, 0xe6, 0x7a, 0x54, 0x05, 0x8e, 0xb5, 0x0d, 0x99, 0x3c, 0xdb, 0x9e, + 0xd0, 0xb4, 0xd0, 0x29, + 0xc0, 0x6d, 0x21, 0xa9, 0x4c, 0xa6, 0x61, 0xc3, 0xce, 0x27, 0xfa, 0xe1, + 0xd6, 0xcb, 0x20, 0xf4, + 0x56, 0x4d, 0x66, 0xce, 0x47, 0x67, 0x58, 0x3d, 0x0e, 0x5f, 0x06, 0x02, + 0x15, 0xb5, 0x90, 0x17, + 0xbe, 0x85, 0xea, 0x84, 0x89, 0x39, 0x12, 0x7b, 0xd8, 0xc9, 0xc4, 0xd4, + 0x7b, 0x51, 0x05, 0x6c, + 0x03, 0x1c, 0xf3, 0x36, 0xf1, 0x7c, 0x99, 0x80, 0xf3, 0xb8, 0xf5, 0xb9, + 0xb6, 0x87, 0x8e, 0x8b, + 0x79, 0x7a, 0xa4, 0x3b, 0x88, 0x26, 0x84, 0x33, 0x3e, 0x17, 0x89, 0x3f, + 0xe9, 0xca, 0xa6, 0xaa, + 0x29, 0x9f, 0x7e, 0xd1, 0xa1, 0x8e, 0xe2, 0xc5, 0x48, 0x64, 0xb7, 0xb2, + 0xb9, 0x9b, 0x72, 0x61, + 0x8f, 0xb0, 0x25, 0x74, 0xd1, 0x39, 0xef, 0x50, 0xf0, 0x19, 0xc9, 0xee, + 0xf4, 0x16, 0x97, 0x13, + 0x38, 0xe7, 0xd4, 0x70 +}; +static const uint8_t ac_rsassa_vect5_out[] = { + 0x0b, 0x1f, 0x2e, 0x51, 0x80, 0xe5, 0xc7, 0xb4, 0xb5, 0xe6, 0x72, 0x92, + 0x9f, 0x66, 0x4c, 0x48, + 0x96, 0xe5, 0x0c, 0x35, 0x13, 0x4b, 0x6d, 0xe4, 0xd5, 0xa9, 0x34, 0x25, + 0x2a, 0x3a, 0x24, 0x5f, + 0xf4, 0x83, 0x40, 0x92, 0x0e, 0x10, 0x34, 0xb7, 0xd5, 0xa5, 0xb5, 0x24, + 0xeb, 0x0e, 0x1c, 0xf1, + 0x2b, 0xef, 0xef, 0x49, 0xb2, 0x7b, 0x73, 0x2d, 0x2c, 0x19, 0xe1, 0xc4, + 0x32, 0x17, 0xd6, 0xe1, + 0x41, 0x73, 0x81, 0x11, 0x1a, 0x1d, 0x36, 0xde, 0x63, 0x75, 0xcf, 0x45, + 0x5b, 0x3c, 0x98, 0x12, + 0x63, 0x9d, 0xbc, 0x27, 0x60, 0x0c, 0x75, 0x19, 0x94, 0xfb, 0x61, 0x79, + 0x9e, 0xcf, 0x7d, 0xa6, + 0xbc, 0xf5, 0x15, 0x40, 0xaf, 0xd0, 0x17, 0x4d, 0xb4, 0x03, 0x31, 0x88, + 0x55, 0x66, 0x75, 0xb1, + 0xd7, 0x63, 0x36, 0x0a, 0xf4, 0x6f, 0xee, 0xca, 0x5b, 0x60, 0xf8, 0x82, + 0x82, 0x9e, 0xe7, 0xb2, +}; + +/* PKCS#1 v1.5 Signature Example 1.4 */ +#define ac_rsassa_vect6_modulus ac_rsassa_example1_modulus +#define ac_rsassa_vect6_pub_exp ac_rsassa_example1_pub_exp +#define ac_rsassa_vect6_priv_exp ac_rsassa_example1_priv_exp +#define ac_rsassa_vect6_prime1 ac_rsassa_example1_prime1 +#define ac_rsassa_vect6_prime2 ac_rsassa_example1_prime2 +#define ac_rsassa_vect6_exp1 ac_rsassa_example1_exp1 +#define ac_rsassa_vect6_exp2 ac_rsassa_example1_exp2 +#define ac_rsassa_vect6_coeff ac_rsassa_example1_coeff +static const uint8_t ac_rsassa_vect6_ptx[] = { + 0xbc, 0x65, 0x67, 0x47, 0xfa, 0x9e, 0xaf, 0xb3, 0xf0 +}; +static const uint8_t ac_rsassa_vect6_out[] = { + 0x45, 0x60, 0x7a, 0xd6, 0x11, 0xcf, 0x57, 0x47, 0xa4, 0x1a, 0xc9, 0x4d, + 0x0f, 0xfe, 0xc8, 0x78, + 0xbd, 0xaf, 0x63, 0xf6, 0xb5, 0x7a, 0x4b, 0x08, 0x8b, 0xf3, 0x6e, 0x34, + 0xe1, 0x09, 0xf8, 0x40, + 0xf2, 0x4b, 0x74, 0x2a, 0xda, 0x16, 0x10, 0x2d, 0xab, 0xf9, 0x51, 0xcb, + 0xc4, 0x4f, 0x89, 0x82, + 0xe9, 0x4e, 0xd4, 0xcd, 0x09, 0x44, 0x8d, 0x20, 0xec, 0x0e, 0xfa, 0x73, + 0x54, 0x5f, 0x80, 0xb6, + 0x54, 0x06, 0xbe, 0xd6, 0x19, 0x4a, 0x61, 0xc3, 0x40, 0xb4, 0xad, 0x15, + 0x68, 0xcb, 0xb7, 0x58, + 0x51, 0x04, 0x9f, 0x11, 0xaf, 0x17, 0x34, 0x96, 0x40, 0x76, 0xe0, 0x20, + 0x29, 0xae, 0xe2, 0x00, + 0xe4, 0x0e, 0x80, 0xbe, 0x0f, 0x43, 0x61, 0xf6, 0x98, 0x41, 0xc4, 0xf9, + 0x2a, 0x44, 0x50, 0xa2, + 0x28, 0x6d, 0x43, 0x28, 0x9b, 0x40, 0x55, 0x54, 0xc5, 0x4d, 0x25, 0xc6, + 0xec, 0xb5, 0x84, 0xf4, +}; + +/* PKCS#1 v1.5 Signature Example 7 1025-bit RSA key pair */ +static const uint8_t ac_rsassa_example2_modulus[] = { + 0x01, 0x69, 0x34, 0xcd, 0xff, 0x48, 0x50, 0xb6, 0x00, 0x2c, 0xc0, 0xf0, + 0xf4, 0x01, 0x0a, 0x32, + 0xc6, 0x55, 0xe5, 0xcf, 0x6e, 0x7c, 0x89, 0x93, 0x7f, 0xd7, 0x55, 0xef, + 0x6a, 0xbe, 0x37, 0x9d, + 0xad, 0xde, 0x70, 0xcc, 0x21, 0x77, 0x51, 0xf1, 0x4c, 0xba, 0x6d, 0x90, + 0xfe, 0x52, 0xdc, 0x0a, + 0xf5, 0x8b, 0x25, 0x2f, 0x26, 0xbf, 0x72, 0xda, 0x57, 0x9f, 0xda, 0xf5, + 0x7d, 0xdd, 0x6c, 0xd6, + 0x02, 0x18, 0x79, 0x94, 0x9a, 0x02, 0x76, 0xb4, 0x43, 0x3f, 0xf0, 0x1e, + 0xfc, 0xcc, 0xf3, 0x5a, + 0x11, 0xe7, 0xc7, 0x7b, 0x38, 0xc1, 0x8c, 0xca, 0x94, 0xae, 0x01, 0x2d, + 0x0f, 0x37, 0x04, 0x21, + 0x49, 0x1c, 0x52, 0xad, 0x15, 0xac, 0x76, 0xb1, 0x2e, 0xcd, 0x21, 0x8f, + 0x52, 0xe7, 0x57, 0x86, + 0x6e, 0x08, 0x9d, 0xd8, 0xad, 0xbb, 0x48, 0xe9, 0xba, 0x89, 0x43, 0x36, + 0xc5, 0x75, 0xc4, 0x06, + 0x55 +}; +static const uint8_t ac_rsassa_example2_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_rsassa_example2_priv_exp[] = { + 0x0d, 0x17, 0x19, 0xe5, 0xbd, 0x47, 0x6d, 0x87, 0xc7, 0xec, 0xc3, 0x1e, + 0xb8, 0xab, 0x42, 0x5d, + 0x4f, 0xe4, 0xc8, 0xf5, 0xc7, 0xae, 0x23, 0x0a, 0x10, 0x47, 0x55, 0x3f, + 0xfb, 0x53, 0x9f, 0xd3, + 0x85, 0x5a, 0xf5, 0xa4, 0x3b, 0x2d, 0xdd, 0x4e, 0x95, 0xa2, 0xb3, 0x0d, + 0x40, 0x7a, 0xa8, 0x81, + 0x59, 0xbb, 0xad, 0x2a, 0x87, 0x3d, 0x80, 0x93, 0xb4, 0x8a, 0x4b, 0xce, + 0x20, 0xad, 0x99, 0x26, + 0x25, 0x3e, 0xd3, 0x39, 0xac, 0x3b, 0x54, 0x3f, 0xc7, 0x42, 0x96, 0x95, + 0x33, 0x8d, 0xb0, 0xbc, + 0x1d, 0xc3, 0x68, 0x6c, 0xfd, 0x13, 0x9b, 0xb5, 0xb2, 0x87, 0x36, 0xbc, + 0x16, 0x60, 0xa9, 0x53, + 0x48, 0xfc, 0x91, 0xc3, 0x25, 0xd0, 0x3a, 0x7f, 0xb2, 0x16, 0xd2, 0xd9, + 0xcd, 0x93, 0x64, 0xde, + 0x4e, 0xe7, 0xd2, 0x11, 0x9c, 0x3b, 0x0f, 0xbb, 0xa8, 0xa7, 0x1f, 0x0d, + 0x3f, 0x5a, 0xb9, 0xb9, +}; +static const uint8_t ac_rsassa_example2_prime1[] = { + 0x01, 0x58, 0xc0, 0x24, 0x6c, 0xd1, 0x69, 0xfc, 0x59, 0x3b, 0x25, 0x8b, + 0xbf, 0x45, 0x23, 0xab, + 0x2b, 0x55, 0xc4, 0x60, 0x73, 0x3a, 0x7f, 0xb4, 0x69, 0x10, 0x90, 0x77, + 0xb3, 0x0e, 0x4d, 0x35, + 0xf2, 0x1a, 0x35, 0xb1, 0xf4, 0x1e, 0x42, 0x04, 0xe8, 0x1d, 0x2e, 0x4c, + 0x46, 0x3c, 0x24, 0x11, + 0x39, 0x34, 0x09, 0x8b, 0x45, 0x2d, 0xab, 0x4b, 0xe1, 0x59, 0x97, 0x20, + 0xef, 0x68, 0x72, 0x83, + 0x3d +}; +static const uint8_t ac_rsassa_example2_prime2[] = { + 0x01, 0x0c, 0x38, 0x2d, 0xea, 0x5e, 0x7d, 0x79, 0x29, 0x8c, 0x64, 0x1f, + 0xb2, 0xe4, 0xfa, 0x09, + 0xf2, 0x4f, 0x6a, 0x7a, 0x45, 0x9a, 0x88, 0x2c, 0x87, 0xa8, 0x03, 0x49, + 0x5f, 0x05, 0x6e, 0xcc, + 0x3b, 0x43, 0xc5, 0x37, 0x73, 0x1f, 0x85, 0xef, 0xc8, 0xfb, 0x53, 0x87, + 0xad, 0x67, 0x31, 0xa6, + 0x43, 0x53, 0x32, 0x15, 0xde, 0xcc, 0x38, 0x7d, 0x96, 0x76, 0x12, 0x2c, + 0x17, 0x0e, 0x91, 0xe0, + 0xf9 +}; +static const uint8_t ac_rsassa_example2_exp1[] = { + 0xd5, 0x78, 0xdc, 0xd5, 0x38, 0xf2, 0xfc, 0xdc, 0x30, 0x00, 0xb6, 0xc0, + 0xf0, 0x49, 0xfe, 0xe2, + 0xad, 0x90, 0x14, 0xfd, 0x24, 0xfb, 0x10, 0xb6, 0x82, 0x18, 0x42, 0xd6, + 0x70, 0x03, 0xa5, 0x64, + 0xcd, 0x8f, 0xf4, 0x2a, 0x2a, 0x56, 0x4c, 0xfd, 0x81, 0x9c, 0x3a, 0x84, + 0xbf, 0x16, 0xc2, 0x47, + 0x7e, 0x8e, 0x6e, 0x5b, 0x9e, 0xc4, 0xd4, 0x0e, 0xad, 0x50, 0x24, 0x87, + 0xba, 0x50, 0x36, 0x2d, +}; +static const uint8_t ac_rsassa_example2_exp2[] = { + 0x88, 0x88, 0xdc, 0x8e, 0xae, 0x94, 0xee, 0xa5, 0x80, 0xca, 0xc2, 0xfc, + 0x1c, 0xe5, 0x4f, 0x44, + 0xe2, 0xba, 0x50, 0x0d, 0xb8, 0x71, 0x53, 0x41, 0xa6, 0xfc, 0x2d, 0x50, + 0x4a, 0x82, 0xb1, 0x42, + 0x05, 0xe8, 0x91, 0xa6, 0x6f, 0xc8, 0x8d, 0x5c, 0x60, 0xdb, 0x8f, 0x78, + 0x6c, 0xcc, 0x70, 0x57, + 0x5b, 0x35, 0x66, 0xbe, 0xa8, 0x74, 0xa5, 0x31, 0x7f, 0x5f, 0x16, 0xc4, + 0x91, 0xed, 0x1e, 0x79, +}; +static const uint8_t ac_rsassa_example2_coeff[] = { + 0x17, 0xb0, 0xd6, 0x23, 0x36, 0x19, 0x1e, 0x63, 0xbc, 0xa1, 0x59, 0x93, + 0x4d, 0x06, 0x16, 0xcb, + 0x89, 0x97, 0x40, 0x9c, 0xbf, 0xca, 0x37, 0x05, 0x69, 0x5b, 0x14, 0xfb, + 0x64, 0xa0, 0x81, 0xc1, + 0xc9, 0xf5, 0x86, 0x19, 0x3e, 0x52, 0x3a, 0xbd, 0x0b, 0xeb, 0x8d, 0x72, + 0x0c, 0xfe, 0x53, 0x7d, + 0xfa, 0x1e, 0xde, 0xc4, 0xa6, 0x64, 0x37, 0xd2, 0x41, 0x19, 0x6b, 0x7a, + 0x2c, 0xe5, 0x56, 0xc4, +}; + + +/* PKCS#1 v1.5 Signature Example 7.1 */ +#define ac_rsassa_vect7_modulus ac_rsassa_example2_modulus +#define ac_rsassa_vect7_pub_exp ac_rsassa_example2_pub_exp +#define ac_rsassa_vect7_priv_exp ac_rsassa_example2_priv_exp +#define ac_rsassa_vect7_prime1 ac_rsassa_example2_prime1 +#define ac_rsassa_vect7_prime2 ac_rsassa_example2_prime2 +#define ac_rsassa_vect7_exp1 ac_rsassa_example2_exp1 +#define ac_rsassa_vect7_exp2 ac_rsassa_example2_exp2 +#define ac_rsassa_vect7_coeff ac_rsassa_example2_coeff +static const uint8_t ac_rsassa_vect7_ptx[] = { + 0x35, 0x39, 0x99, 0x7a, 0xe7, 0x09, 0xfe, 0x32, 0xc1, 0x03, 0x6a, 0x13, + 0x27, 0x57, 0xf2, 0xa1, + 0x66, 0x7a, 0x91, 0xcc, 0x83, 0xbe, 0x73, 0x3a, 0xad, 0xa1, 0xbd, 0xd2, + 0x17, 0x92, 0x4c, 0x9a, + 0x2c, 0x9f, 0xed, 0x1f, 0xec, 0xf6, 0x1d, 0x1c, 0xf7, 0x9d, 0xae, 0x9a, + 0x83, 0xf8, 0xae, 0x3f, + 0x4d, 0x05, 0x1b, 0x34, 0xfb, 0xb5, 0x59, 0xcb, 0xfd, 0xa4, 0x92, 0xf1, + 0xd8, 0x3b, 0x8b, 0xeb, + 0xa0, 0x45, 0xd4, 0xae, 0x1c, 0x8f, 0xea, 0x15, 0xb7, 0x57, 0x7a, 0x1b, + 0x8a, 0x3f, 0x55, 0xba, + 0xc1, 0x72, 0x7e, 0xdc, 0xa7, 0xf8, 0xf5, 0x2c, 0xb4, 0xba, 0x61, 0xca, + 0xf1, 0xfa, 0x8f, 0x8f, + 0xd9, 0xaa, 0xc7, 0x79, 0x09, 0x5c, 0xa8, 0x4c, 0x79, 0x91, 0x52, 0x9f, + 0xb8, 0x06, 0x99, 0xd0, + 0xd4, 0x68, 0x8d, 0xfd, 0xb1, 0x42, 0xed, 0x61, 0xa9, 0x5b, 0x89, 0xce, + 0x33, 0x06, 0xbf, 0x97, + 0x80, 0xe1, 0xb9, 0x1b, 0x84, 0x8c, 0x8d, 0x20, 0x03, 0x97, 0x0e, 0x52, + 0x70, 0x2a, 0x1f, 0x61, + 0x2e, 0x2f, 0x40, 0x17, 0xcf, 0xe0, 0xa9, 0x1d, 0xb9, 0xe4, 0x6d, 0xb9, + 0xdc +}; +static const uint8_t ac_rsassa_vect7_out[] = { + 0x00, 0x08, 0x0f, 0x77, 0x0a, 0x2d, 0x1f, 0x6a, 0xbf, 0x5f, 0x22, 0x1f, + 0x62, 0xe1, 0x66, 0xab, + 0xd7, 0x9d, 0x06, 0xc7, 0xb9, 0xa8, 0x78, 0xd6, 0x1b, 0x80, 0xfc, 0x4d, + 0x5b, 0xa2, 0x90, 0xb2, + 0x3a, 0xba, 0xab, 0x51, 0x8f, 0x09, 0x44, 0x7e, 0x45, 0xae, 0xe6, 0xf3, + 0xbd, 0x06, 0x10, 0x24, + 0x44, 0x36, 0xa4, 0x73, 0x01, 0x60, 0xe6, 0xa6, 0x72, 0x11, 0x0c, 0x01, + 0xae, 0xb5, 0x62, 0x4b, + 0x71, 0x8d, 0xc7, 0xc0, 0x86, 0x1e, 0x58, 0x6b, 0xa8, 0xb6, 0x0a, 0x29, + 0xd6, 0xa5, 0x75, 0x5c, + 0xd2, 0xcc, 0x50, 0x85, 0x99, 0xc6, 0xe2, 0x8d, 0x73, 0x55, 0xb2, 0x7e, + 0x40, 0xb7, 0x40, 0xc6, + 0xfb, 0xbb, 0xb1, 0xa9, 0x18, 0x23, 0xb1, 0xc1, 0x24, 0x2b, 0xa6, 0x93, + 0xd4, 0x52, 0x69, 0x51, + 0x47, 0xdb, 0xb2, 0x3e, 0xa8, 0x9c, 0xbf, 0x11, 0xeb, 0x8b, 0x07, 0xec, + 0x3a, 0x02, 0x7b, 0x0f, + 0x17 +}; + +/* + * Test data from 186-2rsatestvectors.zip SigVet15_186-3.rsp with CRT + * parameters created with: + * http://sourceforge.net/projects/rsaconverter/ + */ + +/* SigGen15_186-2.txt line 9 mod 1024 */ +static const uint8_t ac_siggen15_186_2_modulus[] = { + 0xc8, 0xa2, 0x06, 0x91, 0x82, 0x39, 0x4a, 0x2a, 0xb7, 0xc3, 0xf4, 0x19, + 0x0c, 0x15, 0x58, 0x9c, 0x56, 0xa2, 0xd4, 0xbc, 0x42, 0xdc, 0xa6, 0x75, + 0xb3, 0x4c, 0xc9, 0x50, 0xe2, 0x46, 0x63, 0x04, 0x84, 0x41, 0xe8, 0xaa, + 0x59, 0x3b, 0x2b, 0xc5, 0x9e, 0x19, 0x8b, 0x8c, 0x25, 0x7e, 0x88, 0x21, + 0x20, 0xc6, 0x23, 0x36, 0xe5, 0xcc, 0x74, 0x50, 0x12, 0xc7, 0xff, 0xb0, + 0x63, 0xee, 0xbe, 0x53, 0xf3, 0xc6, 0x50, 0x4c, 0xba, 0x6c, 0xfe, 0x51, + 0xba, 0xa3, 0xb6, 0xd1, 0x07, 0x4b, 0x2f, 0x39, 0x81, 0x71, 0xf4, 0xb1, + 0x98, 0x2f, 0x4d, 0x65, 0xca, 0xf8, 0x82, 0xea, 0x4d, 0x56, 0xf3, 0x2a, + 0xb5, 0x7d, 0x0c, 0x44, 0xe6, 0xad, 0x4e, 0x9c, 0xf5, 0x7a, 0x43, 0x39, + 0xeb, 0x69, 0x62, 0x40, 0x6e, 0x35, 0x0c, 0x1b, 0x15, 0x39, 0x71, 0x83, + 0xfb, 0xf1, 0xf0, 0x35, 0x3c, 0x9f, 0xc9, 0x91 +}; +static const uint8_t ac_siggen15_186_2_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_siggen15_186_2_priv_exp[] = { + 0x5d, 0xfc, 0xb1, 0x11, 0x07, 0x2d, 0x29, 0x56, 0x5b, 0xa1, 0xdb, 0x3e, + 0xc4, 0x8f, 0x57, 0x64, 0x5d, 0x9d, 0x88, 0x04, 0xed, 0x59, 0x8a, 0x4d, + 0x47, 0x02, 0x68, 0xa8, 0x90, 0x67, 0xa2, 0xc9, 0x21, 0xdf, 0xf2, 0x4b, + 0xa2, 0xe3, 0x7a, 0x3c, 0xe8, 0x34, 0x55, 0x50, 0x00, 0xdc, 0x86, 0x8e, + 0xe6, 0x58, 0x8b, 0x74, 0x93, 0x30, 0x35, 0x28, 0xb1, 0xb3, 0xa9, 0x4f, + 0x0b, 0x71, 0x73, 0x0c, 0xf1, 0xe8, 0x6f, 0xca, 0x5a, 0xee, 0xdc, 0x3a, + 0xfa, 0x16, 0xf6, 0x5c, 0x01, 0x89, 0xd8, 0x10, 0xdd, 0xcd, 0x81, 0x04, + 0x9e, 0xbb, 0xd0, 0x39, 0x18, 0x68, 0xc5, 0x0e, 0xde, 0xc9, 0x58, 0xb3, + 0xa2, 0xaa, 0xef, 0xf6, 0xa5, 0x75, 0x89, 0x7e, 0x2f, 0x20, 0xa3, 0xab, + 0x54, 0x55, 0xc1, 0xbf, 0xa5, 0x50, 0x10, 0xac, 0x51, 0xa7, 0x79, 0x9b, + 0x1f, 0xf8, 0x48, 0x36, 0x44, 0xa3, 0xd4, 0x25 +}; +static const uint8_t ac_siggen15_186_2_prime1[] = { + 0xF6, 0x6A, 0x24, 0x68, 0xB1, 0x48, 0x1A, 0x0D, 0x6B, 0x60, 0x49, 0x67, + 0xF0, 0x58, 0x03, 0x89, 0xD6, 0x06, 0x1F, 0x03, 0x3A, 0x9B, 0x57, 0xB7, + 0x4D, 0x1B, 0xEF, 0xE8, 0x10, 0x11, 0x98, 0x94, 0x5B, 0x80, 0x93, 0x04, + 0x24, 0x1D, 0x02, 0xFD, 0x5F, 0x92, 0x1F, 0xE9, 0x59, 0xFB, 0xEC, 0xDB, + 0x18, 0x00, 0x54, 0x86, 0x9A, 0xDB, 0x17, 0xD3, 0x21, 0xF9, 0xD5, 0xD5, + 0x98, 0x12, 0x3E, 0x73 +}; +static const uint8_t ac_siggen15_186_2_prime2[] = { + 0xD0, 0x6F, 0xFA, 0x56, 0x3B, 0xD0, 0xB8, 0xB9, 0x7F, 0x00, 0x72, 0xEA, + 0x07, 0x51, 0x03, 0xEC, 0x1F, 0xF0, 0xB1, 0x7F, 0xD6, 0xBD, 0xAF, 0x94, + 0xA7, 0x5A, 0xE6, 0x03, 0x59, 0x82, 0xF6, 0x80, 0x24, 0x9D, 0x77, 0xCC, + 0x15, 0x96, 0xA6, 0x54, 0xF1, 0x4C, 0x51, 0x7A, 0x13, 0xB9, 0x5F, 0x1A, + 0x8C, 0x5D, 0xE8, 0xCC, 0x84, 0xAD, 0x38, 0xD2, 0xE6, 0xAA, 0x4F, 0xCD, + 0x54, 0x1A, 0x32, 0xEB +}; +static const uint8_t ac_siggen15_186_2_exp1[] = { + 0xD4, 0xD4, 0xB6, 0x9F, 0xCA, 0x47, 0x89, 0x60, 0xFF, 0xD6, 0x49, 0x70, + 0xC1, 0xD1, 0x73, 0x34, 0xF1, 0x2B, 0x96, 0x4B, 0xB6, 0xAA, 0x07, 0xA8, + 0x25, 0xAC, 0xB4, 0x98, 0xCE, 0x90, 0x34, 0x26, 0x27, 0xA6, 0x34, 0xD5, + 0x05, 0xD0, 0x1D, 0x0D, 0xF5, 0x27, 0x03, 0xF3, 0x0C, 0x2A, 0xA0, 0xD8, + 0x57, 0xB1, 0xA9, 0x50, 0x1D, 0x9E, 0x90, 0xC4, 0x66, 0x7B, 0x20, 0x6B, + 0x7D, 0x0E, 0x7C, 0xEB +}; +static const uint8_t ac_siggen15_186_2_exp2[] = { + 0x28, 0x4F, 0xEF, 0xE7, 0xAB, 0xAB, 0xE3, 0x7E, 0x24, 0xBC, 0xEE, 0x7C, + 0xAA, 0xAB, 0x95, 0x89, 0x9E, 0x67, 0xCB, 0xBC, 0x80, 0xC8, 0xB0, 0xE3, + 0x9C, 0x36, 0x6D, 0x53, 0xEA, 0x84, 0xF4, 0xAD, 0xB5, 0xE7, 0x2A, 0x9B, + 0x32, 0xF5, 0xAE, 0xF7, 0xB0, 0xAF, 0x64, 0xF6, 0xAA, 0x47, 0xE8, 0xC7, + 0xD6, 0xAB, 0xF6, 0xF1, 0x4F, 0x1B, 0xBD, 0x68, 0xB4, 0xA9, 0xED, 0xC3, + 0x35, 0x67, 0xD7, 0xBF +}; +static const uint8_t ac_siggen15_186_2_coeff[] = { + 0xE3, 0xBD, 0x88, 0x1C, 0x5A, 0x8F, 0x4A, 0xFC, 0xA0, 0x8C, 0xBC, 0x04, + 0x7C, 0xF0, 0xE3, 0x89, 0x7C, 0x85, 0x18, 0x9A, 0xF4, 0xF9, 0xA7, 0x00, + 0x93, 0x2C, 0xF4, 0x9E, 0x72, 0xF6, 0x44, 0x04, 0x39, 0x0D, 0xA5, 0x04, + 0x82, 0x79, 0xCE, 0x47, 0xF5, 0xAF, 0x58, 0x9B, 0x1B, 0xE9, 0xE4, 0x61, + 0xBB, 0xD8, 0xCC, 0x07, 0xAB, 0x8B, 0xC6, 0x8B, 0xAF, 0x6C, 0xC9, 0x13, + 0xB2, 0xE6, 0x26, 0x72 +}; + +/* SigGen15_186-2.txt line 13 SHA-1*/ +#define ac_rsassa_vect8_modulus ac_siggen15_186_2_modulus +#define ac_rsassa_vect8_pub_exp ac_siggen15_186_2_pub_exp +#define ac_rsassa_vect8_priv_exp ac_siggen15_186_2_priv_exp +#define ac_rsassa_vect8_prime1 ac_siggen15_186_2_prime1 +#define ac_rsassa_vect8_prime2 ac_siggen15_186_2_prime2 +#define ac_rsassa_vect8_exp1 ac_siggen15_186_2_exp1 +#define ac_rsassa_vect8_exp2 ac_siggen15_186_2_exp2 +#define ac_rsassa_vect8_coeff ac_siggen15_186_2_coeff +static const uint8_t ac_rsassa_vect8_ptx[] = { + 0xe8, 0x31, 0x27, 0x42, 0xae, 0x23, 0xc4, 0x56, 0xef, 0x28, 0xa2, 0x31, + 0x42, 0xc4, 0x49, 0x08, 0x95, 0x83, 0x27, 0x65, 0xda, 0xdc, 0xe0, 0x2a, + 0xfe, 0x5b, 0xe5, 0xd3, 0x1b, 0x00, 0x48, 0xfb, 0xee, 0xe2, 0xcf, 0x21, + 0x8b, 0x17, 0x47, 0xad, 0x4f, 0xd8, 0x1a, 0x2e, 0x17, 0xe1, 0x24, 0xe6, + 0xaf, 0x17, 0xc3, 0x88, 0x8e, 0x6d, 0x2d, 0x40, 0xc0, 0x08, 0x07, 0xf4, + 0x23, 0xa2, 0x33, 0xca, 0xd6, 0x2c, 0xe9, 0xea, 0xef, 0xb7, 0x09, 0x85, + 0x6c, 0x94, 0xaf, 0x16, 0x6d, 0xba, 0x08, 0xe7, 0xa0, 0x69, 0x65, 0xd7, + 0xfc, 0x0d, 0x8e, 0x5c, 0xb2, 0x65, 0x59, 0xc4, 0x60, 0xe4, 0x7b, 0xc0, + 0x88, 0x58, 0x9d, 0x22, 0x42, 0xc9, 0xb3, 0xe6, 0x2d, 0xa4, 0x89, 0x6f, + 0xab, 0x19, 0x9e, 0x14, 0x4e, 0xc1, 0x36, 0xdb, 0x8d, 0x84, 0xab, 0x84, + 0xbc, 0xba, 0x04, 0xca, 0x3b, 0x90, 0xc8, 0xe5 +}; +static const uint8_t ac_rsassa_vect8_out[] = { + 0x28, 0x92, 0x8e, 0x19, 0xeb, 0x86, 0xf9, 0xc0, 0x00, 0x70, 0xa5, 0x9e, + 0xdf, 0x6b, 0xf8, 0x43, 0x3a, 0x45, 0xdf, 0x49, 0x5c, 0xd1, 0xc7, 0x36, + 0x13, 0xc2, 0x12, 0x98, 0x40, 0xf4, 0x8c, 0x4a, 0x2c, 0x24, 0xf1, 0x1d, + 0xf7, 0x9b, 0xc5, 0xc0, 0x78, 0x2b, 0xce, 0xdd, 0xe9, 0x7d, 0xbb, 0xb2, + 0xac, 0xc6, 0xe5, 0x12, 0xd1, 0x9f, 0x08, 0x50, 0x27, 0xcd, 0x57, 0x50, + 0x38, 0x45, 0x3d, 0x04, 0x90, 0x54, 0x13, 0xe9, 0x47, 0xe6, 0xe1, 0xdd, + 0xdb, 0xeb, 0x35, 0x35, 0xcd, 0xb3, 0xd8, 0x97, 0x1f, 0xe0, 0x20, 0x05, + 0x06, 0x94, 0x10, 0x56, 0xf2, 0x12, 0x43, 0x50, 0x3c, 0x83, 0xea, 0xdd, + 0xe0, 0x53, 0xed, 0x86, 0x6c, 0x0e, 0x02, 0x50, 0xbe, 0xdd, 0xd9, 0x27, + 0xa0, 0x82, 0x12, 0xaa, 0x8a, 0xc0, 0xef, 0xd6, 0x16, 0x31, 0xef, 0x89, + 0xd8, 0xd0, 0x49, 0xef, 0xb3, 0x6b, 0xb3, 0x5f +}; + +/* SigGen15_186-2.txt line 54 SHA-224*/ +#define ac_rsassa_vect16_modulus ac_siggen15_186_2_modulus +#define ac_rsassa_vect16_pub_exp ac_siggen15_186_2_pub_exp +#define ac_rsassa_vect16_priv_exp ac_siggen15_186_2_priv_exp +#define ac_rsassa_vect16_prime1 ac_siggen15_186_2_prime1 +#define ac_rsassa_vect16_prime2 ac_siggen15_186_2_prime2 +#define ac_rsassa_vect16_exp1 ac_siggen15_186_2_exp1 +#define ac_rsassa_vect16_exp2 ac_siggen15_186_2_exp2 +#define ac_rsassa_vect16_coeff ac_siggen15_186_2_coeff +static const uint8_t ac_rsassa_vect16_ptx[] = { + 0xe5, 0x67, 0xa3, 0x9a, 0xe4, 0xe5, 0xef, 0x9b, 0x68, 0x01, 0xea, 0x05, + 0x61, 0xb7, 0x2a, 0x5d, 0x4b, 0x5f, 0x38, 0x5f, 0x05, 0x32, 0xfc, 0x9f, + 0xe1, 0x0a, 0x75, 0x70, 0xf8, 0x69, 0xae, 0x05, 0xc0, 0xbd, 0xed, 0xd6, + 0xe0, 0xe2, 0x2d, 0x45, 0x42, 0xe9, 0xce, 0x82, 0x6a, 0x18, 0x8c, 0xac, + 0x07, 0x31, 0xae, 0x39, 0xc8, 0xf8, 0x7f, 0x97, 0x71, 0xef, 0x02, 0x13, + 0x2e, 0x64, 0xe2, 0xfb, 0x27, 0xad, 0xa8, 0xff, 0x54, 0xb3, 0x30, 0xdd, + 0x93, 0xad, 0x5e, 0x3e, 0xf8, 0x2e, 0x0d, 0xda, 0x64, 0x62, 0x48, 0xe3, + 0x59, 0x94, 0xbd, 0xa1, 0x0c, 0xf4, 0x6e, 0x5a, 0xbc, 0x98, 0xaa, 0x74, + 0x43, 0xc0, 0x3c, 0xdd, 0xeb, 0x5e, 0xe2, 0xab, 0x82, 0xd6, 0x01, 0x00, + 0xb1, 0x02, 0x96, 0x31, 0x89, 0x79, 0x70, 0x27, 0x5f, 0x11, 0x9d, 0x05, + 0xda, 0xa2, 0x22, 0x0a, 0x4a, 0x0d, 0xef, 0xba +}; +static const uint8_t ac_rsassa_vect16_out[] = { + 0x5a, 0xa5, 0x03, 0x33, 0x81, 0xbd, 0xd0, 0xac, 0xce, 0x33, 0x2d, 0xd3, + 0x14, 0xda, 0xf0, 0x08, 0xac, 0xaa, 0x9e, 0x83, 0x5f, 0x83, 0x29, 0x79, + 0x89, 0x1d, 0x1b, 0xda, 0x2b, 0x55, 0xd5, 0xea, 0xe3, 0x5c, 0x47, 0x9c, + 0x06, 0xca, 0xc5, 0xbf, 0x33, 0xf4, 0x32, 0xc8, 0xc0, 0xa5, 0x54, 0x9d, + 0x1d, 0x1b, 0x29, 0xc5, 0xe2, 0x58, 0x90, 0x24, 0xd2, 0x78, 0x00, 0xa0, + 0xc2, 0x35, 0xa6, 0x15, 0x32, 0xc2, 0x03, 0xcb, 0xc4, 0x06, 0xac, 0x6e, + 0xcf, 0x63, 0xf5, 0x2a, 0xe7, 0x71, 0xb9, 0x7c, 0x08, 0xe4, 0xb1, 0x08, + 0xec, 0x91, 0x69, 0x00, 0xe5, 0xa1, 0x1b, 0x1d, 0x48, 0xcc, 0xa8, 0x6c, + 0xa5, 0xa5, 0xa7, 0x99, 0xed, 0x32, 0xe9, 0x9c, 0x81, 0x5c, 0xef, 0x04, + 0xcf, 0x8e, 0xb5, 0x52, 0x23, 0xbf, 0xd4, 0xd9, 0xc3, 0x44, 0x92, 0x64, + 0xb6, 0x00, 0x61, 0xbc, 0x36, 0x84, 0xbc, 0x82 +}; + +/* SigGen15_186-2.txt line 93 SHA-256 */ +#define ac_rsassa_vect9_modulus ac_siggen15_186_2_modulus +#define ac_rsassa_vect9_pub_exp ac_siggen15_186_2_pub_exp +#define ac_rsassa_vect9_priv_exp ac_siggen15_186_2_priv_exp +#define ac_rsassa_vect9_prime1 ac_siggen15_186_2_prime1 +#define ac_rsassa_vect9_prime2 ac_siggen15_186_2_prime2 +#define ac_rsassa_vect9_exp1 ac_siggen15_186_2_exp1 +#define ac_rsassa_vect9_exp2 ac_siggen15_186_2_exp2 +#define ac_rsassa_vect9_coeff ac_siggen15_186_2_coeff +static const uint8_t ac_rsassa_vect9_ptx[] = { + 0xe5, 0x67, 0xa3, 0x9a, 0xe4, 0xe5, 0xef, 0x9b, 0x68, 0x01, 0xea, 0x05, + 0x61, 0xb7, 0x2a, 0x5d, 0x4b, 0x5f, 0x38, 0x5f, 0x05, 0x32, 0xfc, 0x9f, + 0xe1, 0x0a, 0x75, 0x70, 0xf8, 0x69, 0xae, 0x05, 0xc0, 0xbd, 0xed, 0xd6, + 0xe0, 0xe2, 0x2d, 0x45, 0x42, 0xe9, 0xce, 0x82, 0x6a, 0x18, 0x8c, 0xac, + 0x07, 0x31, 0xae, 0x39, 0xc8, 0xf8, 0x7f, 0x97, 0x71, 0xef, 0x02, 0x13, + 0x2e, 0x64, 0xe2, 0xfb, 0x27, 0xad, 0xa8, 0xff, 0x54, 0xb3, 0x30, 0xdd, + 0x93, 0xad, 0x5e, 0x3e, 0xf8, 0x2e, 0x0d, 0xda, 0x64, 0x62, 0x48, 0xe3, + 0x59, 0x94, 0xbd, 0xa1, 0x0c, 0xf4, 0x6e, 0x5a, 0xbc, 0x98, 0xaa, 0x74, + 0x43, 0xc0, 0x3c, 0xdd, 0xeb, 0x5e, 0xe2, 0xab, 0x82, 0xd6, 0x01, 0x00, + 0xb1, 0x02, 0x96, 0x31, 0x89, 0x79, 0x70, 0x27, 0x5f, 0x11, 0x9d, 0x05, + 0xda, 0xa2, 0x22, 0x0a, 0x4a, 0x0d, 0xef, 0xba +}; +static const uint8_t ac_rsassa_vect9_out[] = { + 0x0e, 0x7c, 0xdd, 0x12, 0x1e, 0x40, 0x32, 0x3c, 0xa6, 0x11, 0x5d, 0x1e, + 0xc6, 0xd1, 0xf9, 0x56, 0x17, 0x38, 0x45, 0x5f, 0x0e, 0x9e, 0x1c, 0xd8, + 0x58, 0xe8, 0xb5, 0x66, 0xae, 0x2d, 0xa5, 0xe8, 0xee, 0x63, 0xd8, 0xf1, + 0x5c, 0x3c, 0xdd, 0x88, 0x02, 0x7e, 0x13, 0x40, 0x6d, 0xb6, 0x09, 0x36, + 0x9c, 0x88, 0xca, 0x99, 0xb3, 0x4f, 0xa1, 0x56, 0xc7, 0xee, 0x62, 0xbc, + 0x5a, 0x39, 0x23, 0xbb, 0x5a, 0x1e, 0xda, 0xbd, 0x45, 0xc1, 0xa4, 0x22, + 0xaa, 0xfc, 0xbb, 0x47, 0xe0, 0x94, 0x7f, 0x35, 0xcf, 0xef, 0x87, 0x97, + 0x0b, 0x4b, 0x71, 0x31, 0x62, 0xb2, 0x19, 0x16, 0xca, 0xfb, 0x8c, 0x86, + 0x4a, 0x3e, 0x5b, 0x9f, 0xfc, 0x98, 0x94, 0x01, 0xd4, 0xea, 0xe9, 0x92, + 0x31, 0x2a, 0x32, 0xc5, 0xbc, 0x88, 0xab, 0xbb, 0x45, 0xf9, 0x9a, 0xc8, + 0x85, 0xb5, 0x4d, 0x6b, 0x8e, 0x61, 0xb6, 0xec +}; + +/* SigGen15_186-2.txt line 93 SHA-256 without ASN.1 */ +#define ac_rsassa_vect20_modulus ac_siggen15_186_2_modulus +#define ac_rsassa_vect20_pub_exp ac_siggen15_186_2_pub_exp +#define ac_rsassa_vect20_priv_exp ac_siggen15_186_2_priv_exp +#define ac_rsassa_vect20_prime1 ac_siggen15_186_2_prime1 +#define ac_rsassa_vect20_prime2 ac_siggen15_186_2_prime2 +#define ac_rsassa_vect20_exp1 ac_siggen15_186_2_exp1 +#define ac_rsassa_vect20_exp2 ac_siggen15_186_2_exp2 +#define ac_rsassa_vect20_coeff ac_siggen15_186_2_coeff +static const uint8_t ac_rsassa_vect20_ptx[] = { + 0xe5, 0x67, 0xa3, 0x9a, 0xe4, 0xe5, 0xef, 0x9b, 0x68, 0x01, 0xea, 0x05, + 0x61, 0xb7, 0x2a, 0x5d, 0x4b, 0x5f, 0x38, 0x5f, 0x05, 0x32, 0xfc, 0x9f, + 0xe1, 0x0a, 0x75, 0x70, 0xf8, 0x69, 0xae, 0x05, 0xc0, 0xbd, 0xed, 0xd6, + 0xe0, 0xe2, 0x2d, 0x45, 0x42, 0xe9, 0xce, 0x82, 0x6a, 0x18, 0x8c, 0xac, + 0x07, 0x31, 0xae, 0x39, 0xc8, 0xf8, 0x7f, 0x97, 0x71, 0xef, 0x02, 0x13, + 0x2e, 0x64, 0xe2, 0xfb, 0x27, 0xad, 0xa8, 0xff, 0x54, 0xb3, 0x30, 0xdd, + 0x93, 0xad, 0x5e, 0x3e, 0xf8, 0x2e, 0x0d, 0xda, 0x64, 0x62, 0x48, 0xe3, + 0x59, 0x94, 0xbd, 0xa1, 0x0c, 0xf4, 0x6e, 0x5a, 0xbc, 0x98, 0xaa, 0x74, + 0x43, 0xc0, 0x3c, 0xdd, 0xeb, 0x5e, 0xe2, 0xab, 0x82, 0xd6, 0x01, 0x00, + 0xb1, 0x02, 0x96, 0x31, 0x89, 0x79, 0x70, 0x27, 0x5f, 0x11, 0x9d, 0x05, + 0xda, 0xa2, 0x22, 0x0a, 0x4a, 0x0d, 0xef, 0xba +}; +static const uint8_t ac_rsassa_vect20_out[] = { + 0xbe, 0x03, 0x14, 0xbb, 0x4e, 0x73, 0xae, 0xa0, 0x8c, 0x3b, 0xd3, 0x47, + 0xc5, 0x71, 0x81, 0x6a, 0xb6, 0x0d, 0xc8, 0xd4, 0xbd, 0x6d, 0x8e, 0x5c, + 0xa3, 0x59, 0xd7, 0x31, 0xb3, 0x44, 0xa8, 0x17, 0x09, 0xc5, 0x00, 0x96, + 0x1a, 0xaa, 0x8b, 0xb2, 0xb4, 0xdc, 0x63, 0xda, 0xa2, 0x66, 0xe1, 0xf6, + 0xbb, 0x73, 0xb3, 0x03, 0x6d, 0x9a, 0x2d, 0x65, 0x9e, 0x10, 0x9c, 0x0c, + 0x46, 0xa3, 0xf4, 0xd3, 0x91, 0x23, 0x6d, 0x40, 0xb5, 0x0d, 0xd3, 0x31, + 0xea, 0xd3, 0x0d, 0x22, 0xf5, 0xfc, 0xfa, 0x8d, 0x67, 0x08, 0x65, 0x76, + 0xd4, 0x41, 0x24, 0xd6, 0x74, 0x2b, 0xfe, 0x44, 0xe5, 0x88, 0xde, 0x28, + 0xca, 0x2f, 0xb8, 0xd1, 0xc8, 0xb4, 0x65, 0xb3, 0x8a, 0x4e, 0x1d, 0xdd, + 0x43, 0x80, 0x68, 0x72, 0xf7, 0x52, 0x46, 0x56, 0xa0, 0x9e, 0x1d, 0x76, + 0x89, 0xee, 0x20, 0x71, 0x66, 0xd1, 0x19, 0xb7 +}; + +/* SigGen15_186-2.txt line 133 SHA-384*/ +#define ac_rsassa_vect10_modulus ac_siggen15_186_2_modulus +#define ac_rsassa_vect10_pub_exp ac_siggen15_186_2_pub_exp +#define ac_rsassa_vect10_priv_exp ac_siggen15_186_2_priv_exp +#define ac_rsassa_vect10_prime1 ac_siggen15_186_2_prime1 +#define ac_rsassa_vect10_prime2 ac_siggen15_186_2_prime2 +#define ac_rsassa_vect10_exp1 ac_siggen15_186_2_exp1 +#define ac_rsassa_vect10_exp2 ac_siggen15_186_2_exp2 +#define ac_rsassa_vect10_coeff ac_siggen15_186_2_coeff +static const uint8_t ac_rsassa_vect10_ptx[] = { + 0xe5, 0x67, 0xa3, 0x9a, 0xe4, 0xe5, 0xef, 0x9b, 0x68, 0x01, 0xea, 0x05, + 0x61, 0xb7, 0x2a, 0x5d, 0x4b, 0x5f, 0x38, 0x5f, 0x05, 0x32, 0xfc, 0x9f, + 0xe1, 0x0a, 0x75, 0x70, 0xf8, 0x69, 0xae, 0x05, 0xc0, 0xbd, 0xed, 0xd6, + 0xe0, 0xe2, 0x2d, 0x45, 0x42, 0xe9, 0xce, 0x82, 0x6a, 0x18, 0x8c, 0xac, + 0x07, 0x31, 0xae, 0x39, 0xc8, 0xf8, 0x7f, 0x97, 0x71, 0xef, 0x02, 0x13, + 0x2e, 0x64, 0xe2, 0xfb, 0x27, 0xad, 0xa8, 0xff, 0x54, 0xb3, 0x30, 0xdd, + 0x93, 0xad, 0x5e, 0x3e, 0xf8, 0x2e, 0x0d, 0xda, 0x64, 0x62, 0x48, 0xe3, + 0x59, 0x94, 0xbd, 0xa1, 0x0c, 0xf4, 0x6e, 0x5a, 0xbc, 0x98, 0xaa, 0x74, + 0x43, 0xc0, 0x3c, 0xdd, 0xeb, 0x5e, 0xe2, 0xab, 0x82, 0xd6, 0x01, 0x00, + 0xb1, 0x02, 0x96, 0x31, 0x89, 0x79, 0x70, 0x27, 0x5f, 0x11, 0x9d, 0x05, + 0xda, 0xa2, 0x22, 0x0a, 0x4a, 0x0d, 0xef, 0xba +}; +static const uint8_t ac_rsassa_vect10_out[] = { + 0x16, 0x89, 0xa8, 0x52, 0x39, 0x19, 0xac, 0x77, 0xcc, 0x99, 0x7e, 0xbc, + 0x59, 0xcb, 0x90, 0x88, 0x72, 0xd8, 0x8b, 0x28, 0x55, 0xa3, 0x09, 0xea, + 0xd2, 0x77, 0x9b, 0x88, 0x8b, 0x22, 0xb4, 0x23, 0x2d, 0xa9, 0xb9, 0x3b, + 0xb1, 0x9b, 0x32, 0xc1, 0xdb, 0x77, 0xad, 0x73, 0x8c, 0x6e, 0x43, 0x36, + 0x1e, 0x9e, 0xb6, 0xb1, 0xa3, 0x7c, 0x49, 0xa8, 0xf3, 0xc7, 0xc7, 0xae, + 0x7e, 0x78, 0x4d, 0x19, 0xa6, 0x21, 0x38, 0x74, 0x12, 0x93, 0xe4, 0x9b, + 0x18, 0x31, 0xc0, 0xc3, 0x61, 0x7e, 0xb4, 0x3c, 0x56, 0x70, 0x6d, 0x83, + 0x31, 0x49, 0x53, 0x47, 0x06, 0x36, 0x44, 0x10, 0x86, 0x41, 0x9a, 0xb9, + 0xe6, 0xfd, 0x1e, 0xc4, 0xf9, 0xd5, 0xcc, 0x65, 0x44, 0x81, 0x5d, 0x1e, + 0x02, 0xed, 0x96, 0xa3, 0xae, 0x64, 0xc6, 0x99, 0x8b, 0x2c, 0xf2, 0x38, + 0xe7, 0x9a, 0x12, 0x16, 0x43, 0x52, 0xd1, 0x2a +}; + +/* SigGen15_186-2.txt line 173 SHA-512*/ +#define ac_rsassa_vect11_modulus ac_siggen15_186_2_modulus +#define ac_rsassa_vect11_pub_exp ac_siggen15_186_2_pub_exp +#define ac_rsassa_vect11_priv_exp ac_siggen15_186_2_priv_exp +#define ac_rsassa_vect11_prime1 ac_siggen15_186_2_prime1 +#define ac_rsassa_vect11_prime2 ac_siggen15_186_2_prime2 +#define ac_rsassa_vect11_exp1 ac_siggen15_186_2_exp1 +#define ac_rsassa_vect11_exp2 ac_siggen15_186_2_exp2 +#define ac_rsassa_vect11_coeff ac_siggen15_186_2_coeff +static const uint8_t ac_rsassa_vect11_ptx[] = { + 0xe5, 0x67, 0xa3, 0x9a, 0xe4, 0xe5, 0xef, 0x9b, 0x68, 0x01, 0xea, 0x05, + 0x61, 0xb7, 0x2a, 0x5d, 0x4b, 0x5f, 0x38, 0x5f, 0x05, 0x32, 0xfc, 0x9f, + 0xe1, 0x0a, 0x75, 0x70, 0xf8, 0x69, 0xae, 0x05, 0xc0, 0xbd, 0xed, 0xd6, + 0xe0, 0xe2, 0x2d, 0x45, 0x42, 0xe9, 0xce, 0x82, 0x6a, 0x18, 0x8c, 0xac, + 0x07, 0x31, 0xae, 0x39, 0xc8, 0xf8, 0x7f, 0x97, 0x71, 0xef, 0x02, 0x13, + 0x2e, 0x64, 0xe2, 0xfb, 0x27, 0xad, 0xa8, 0xff, 0x54, 0xb3, 0x30, 0xdd, + 0x93, 0xad, 0x5e, 0x3e, 0xf8, 0x2e, 0x0d, 0xda, 0x64, 0x62, 0x48, 0xe3, + 0x59, 0x94, 0xbd, 0xa1, 0x0c, 0xf4, 0x6e, 0x5a, 0xbc, 0x98, 0xaa, 0x74, + 0x43, 0xc0, 0x3c, 0xdd, 0xeb, 0x5e, 0xe2, 0xab, 0x82, 0xd6, 0x01, 0x00, + 0xb1, 0x02, 0x96, 0x31, 0x89, 0x79, 0x70, 0x27, 0x5f, 0x11, 0x9d, 0x05, + 0xda, 0xa2, 0x22, 0x0a, 0x4a, 0x0d, 0xef, 0xba +}; +static const uint8_t ac_rsassa_vect11_out[] = { + 0xbf, 0x3f, 0xf2, 0xc6, 0x96, 0x75, 0xf1, 0xb8, 0xed, 0x42, 0x10, 0x21, + 0x80, 0x1f, 0xb4, 0xce, 0x29, 0xa7, 0x57, 0xf7, 0xf8, 0x86, 0x9c, 0xe4, + 0x36, 0xd0, 0xd7, 0x5a, 0xb7, 0x49, 0xef, 0xc8, 0xb9, 0x03, 0xd9, 0xf9, + 0xcb, 0x21, 0x46, 0x86, 0x14, 0x7f, 0x12, 0xf3, 0x33, 0x5f, 0xa9, 0x36, + 0x68, 0x9c, 0x19, 0x2f, 0x31, 0x0a, 0xe3, 0xc5, 0xd7, 0x54, 0x93, 0xf4, + 0x4b, 0x24, 0xbc, 0x1c, 0xd3, 0x50, 0x15, 0x84, 0xaa, 0xa5, 0x00, 0x4b, + 0x65, 0xa8, 0x71, 0x6d, 0x1e, 0xda, 0x72, 0x40, 0xad, 0x8a, 0x52, 0x9d, + 0x5a, 0x0c, 0xf1, 0x69, 0xf4, 0x05, 0x4b, 0x45, 0x0e, 0x07, 0x6e, 0xe0, + 0xd4, 0x1a, 0x00, 0x11, 0xc5, 0x57, 0xaa, 0x69, 0xa8, 0x4a, 0x81, 0x04, + 0xc9, 0x09, 0x20, 0x1d, 0x60, 0xfe, 0x39, 0xc7, 0x9e, 0x68, 0x43, 0x47, + 0xef, 0x4d, 0x14, 0x4e, 0xa1, 0x8f, 0x7a, 0x4e +}; + + +/* SigGenPSS_186-2.txt line 9 mod 1024 */ +static const uint8_t ac_siggenpss_186_2_modulus[] = { + 0xbc, 0xb4, 0x7b, 0x2e, 0x0d, 0xaf, 0xcb, 0xa8, 0x1f, 0xf2, 0xa2, 0xb5, + 0xcb, 0x11, 0x5c, 0xa7, 0xe7, 0x57, 0x18, 0x4c, 0x9d, 0x72, 0xbc, 0xdc, + 0xda, 0x70, 0x7a, 0x14, 0x6b, 0x3b, 0x4e, 0x29, 0x98, 0x9d, 0xdc, 0x66, + 0x0b, 0xd6, 0x94, 0x86, 0x5b, 0x93, 0x2b, 0x71, 0xca, 0x24, 0xa3, 0x35, + 0xcf, 0x4d, 0x33, 0x9c, 0x71, 0x91, 0x83, 0xe6, 0x22, 0x2e, 0x4c, 0x9e, + 0xa6, 0x87, 0x5a, 0xcd, 0x52, 0x8a, 0x49, 0xba, 0x21, 0x86, 0x3f, 0xe0, + 0x81, 0x47, 0xc3, 0xa4, 0x7e, 0x41, 0x99, 0x0b, 0x51, 0xa0, 0x3f, 0x77, + 0xd2, 0x21, 0x37, 0xf8, 0xd7, 0x4c, 0x43, 0xa5, 0xa4, 0x5f, 0x4e, 0x9e, + 0x18, 0xa2, 0xd1, 0x5d, 0xb0, 0x51, 0xdc, 0x89, 0x38, 0x5d, 0xb9, 0xcf, + 0x83, 0x74, 0xb6, 0x3a, 0x8c, 0xc8, 0x81, 0x13, 0x71, 0x0e, 0x6d, 0x81, + 0x79, 0x07, 0x5b, 0x7d, 0xc7, 0x9e, 0xe7, 0x6b +}; +static const uint8_t ac_siggenpss_186_2_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_siggenpss_186_2_priv_exp[] = { + 0x38, 0x3a, 0x6f, 0x19, 0xe1, 0xea, 0x27, 0xfd, 0x08, 0xc7, 0xfb, 0xc3, + 0xbf, 0xa6, 0x84, 0xbd, 0x63, 0x29, 0x88, 0x8c, 0x0b, 0xbe, 0x4c, 0x98, + 0x62, 0x5e, 0x71, 0x81, 0xf4, 0x11, 0xcf, 0xd0, 0x85, 0x31, 0x44, 0xa3, + 0x03, 0x94, 0x04, 0xdd, 0xa4, 0x1b, 0xce, 0x2e, 0x31, 0xd5, 0x88, 0xec, + 0x57, 0xc0, 0xe1, 0x48, 0x14, 0x6f, 0x0f, 0xa6, 0x5b, 0x39, 0x00, 0x8b, + 0xa5, 0x83, 0x5f, 0x82, 0x9b, 0xa3, 0x5a, 0xe2, 0xf1, 0x55, 0xd6, 0x1b, + 0x8a, 0x12, 0x58, 0x1b, 0x99, 0xc9, 0x27, 0xfd, 0x2f, 0x22, 0x25, 0x2c, + 0x5e, 0x73, 0xcb, 0xa4, 0xa6, 0x10, 0xdb, 0x39, 0x73, 0xe0, 0x19, 0xee, + 0x0f, 0x95, 0x13, 0x0d, 0x43, 0x19, 0xed, 0x41, 0x34, 0x32, 0xf2, 0xe5, + 0xe2, 0x0d, 0x52, 0x15, 0xcd, 0xd2, 0x7c, 0x21, 0x64, 0x20, 0x6b, 0x3f, + 0x80, 0xed, 0xee, 0x51, 0x93, 0x8a, 0x25, 0xc1 +}; +static const uint8_t ac_siggenpss_186_2_prime1[] = { + 0xE5, 0x56, 0x3B, 0x14, 0x5D, 0xB6, 0xFF, 0x5A, 0x16, 0x28, 0x0D, 0x3E, + 0x80, 0xEF, 0xF0, 0x2F, 0x18, 0x1D, 0xBD, 0x03, 0x32, 0x4E, 0xF2, 0x47, + 0xF5, 0x96, 0xA4, 0xD4, 0xA7, 0xB8, 0xDA, 0xA3, 0x2B, 0x99, 0x34, 0xE3, + 0xC7, 0xF4, 0xDC, 0xF6, 0xA3, 0x10, 0x54, 0x62, 0xDE, 0xC6, 0x38, 0x39, + 0x63, 0x86, 0x18, 0x41, 0x8B, 0x51, 0xDB, 0x02, 0x69, 0x3F, 0xAB, 0xB4, + 0xE6, 0x83, 0x87, 0x25 +}; +static const uint8_t ac_siggenpss_186_2_prime2[] = { + 0xD2, 0xA4, 0xEC, 0x0F, 0xA2, 0x22, 0x6C, 0xDE, 0x82, 0xDA, 0x77, 0x65, + 0x3B, 0x07, 0x2C, 0xD0, 0x98, 0x53, 0x5D, 0x3E, 0x90, 0xED, 0x4D, 0x72, + 0x24, 0xDC, 0xB8, 0xCB, 0x8B, 0x93, 0x14, 0x76, 0x8D, 0xC5, 0x17, 0xE2, + 0x2D, 0x7C, 0x8F, 0xA1, 0x3F, 0x25, 0x3D, 0xAA, 0x74, 0x65, 0xA7, 0x99, + 0x56, 0x09, 0x8A, 0xA4, 0xCC, 0x3A, 0x6E, 0x35, 0xE8, 0xB1, 0xFC, 0xC4, + 0xF9, 0x7E, 0x77, 0x4F +}; +static const uint8_t ac_siggenpss_186_2_exp1[] = { + 0x1F, 0x6A, 0xCA, 0xB9, 0x25, 0x85, 0x76, 0x41, 0xCF, 0x1B, 0x39, 0x85, + 0x40, 0x80, 0x9E, 0x34, 0xB5, 0x67, 0x0D, 0x87, 0xAC, 0x92, 0xA8, 0x1A, + 0x37, 0x88, 0xA5, 0x98, 0x04, 0x4A, 0x0C, 0x99, 0xA1, 0xD5, 0x61, 0x2B, + 0x7B, 0x2F, 0x0E, 0x3E, 0x33, 0x64, 0x7F, 0x4A, 0xF4, 0x1D, 0xCF, 0x81, + 0xFD, 0x22, 0x57, 0x9C, 0x53, 0x0B, 0xA9, 0xA7, 0x10, 0xE8, 0x0A, 0x0B, + 0xC4, 0x30, 0x6C, 0x89 +}; +static const uint8_t ac_siggenpss_186_2_exp2[] = { + 0x59, 0xF2, 0x84, 0xBE, 0xD4, 0x3C, 0x21, 0x03, 0x0F, 0x1B, 0x5C, 0xDA, + 0x84, 0x4F, 0x37, 0x0A, 0xC7, 0xD0, 0xE9, 0x43, 0x3B, 0x3D, 0xA9, 0xD1, + 0x70, 0xFE, 0x33, 0x86, 0xEF, 0x4D, 0xD9, 0xF2, 0x19, 0xED, 0xAC, 0x9A, + 0x2F, 0x54, 0x3E, 0x3C, 0xDB, 0xAA, 0xFA, 0x5F, 0x1C, 0x1F, 0x00, 0x67, + 0x50, 0xBE, 0xF8, 0x4E, 0x10, 0xCB, 0x6E, 0x9E, 0x64, 0x84, 0x04, 0x6C, + 0xD4, 0x20, 0xF5, 0xAF +}; +static const uint8_t ac_siggenpss_186_2_coeff[] = { + 0x83, 0x5F, 0xC1, 0xB6, 0x52, 0x1C, 0x83, 0xE7, 0x6F, 0x80, 0x64, 0xFF, + 0xF8, 0x38, 0x80, 0xE1, 0xC9, 0x8F, 0x81, 0x13, 0x1E, 0xE8, 0x6E, 0x5D, + 0xF8, 0x57, 0x6A, 0xDA, 0x7D, 0x75, 0xC2, 0x6F, 0x8D, 0xB8, 0xBA, 0x8B, + 0x46, 0xF4, 0x6C, 0x69, 0xA5, 0x9D, 0xC5, 0xF2, 0x11, 0x8A, 0x9A, 0x90, + 0x8E, 0xC0, 0x8F, 0x45, 0xB0, 0x50, 0x4D, 0x2A, 0x42, 0x86, 0x49, 0x5E, + 0x2A, 0x1B, 0x78, 0x2E +}; +/* Salt: 6f2841166a64471d4f0b8ed0dbb7db32161da13b */ +#define ac_siggenpss_186_2_salt_len 20 + + +/* SigGen15_186-2.txt line 173 SHA-1 */ +#define ac_rsassa_vect12_modulus ac_siggenpss_186_2_modulus +#define ac_rsassa_vect12_pub_exp ac_siggenpss_186_2_pub_exp +#define ac_rsassa_vect12_priv_exp ac_siggenpss_186_2_priv_exp +#define ac_rsassa_vect12_prime1 ac_siggenpss_186_2_prime1 +#define ac_rsassa_vect12_prime2 ac_siggenpss_186_2_prime2 +#define ac_rsassa_vect12_exp1 ac_siggenpss_186_2_exp1 +#define ac_rsassa_vect12_exp2 ac_siggenpss_186_2_exp2 +#define ac_rsassa_vect12_coeff ac_siggenpss_186_2_coeff +#define ac_rsassa_vect12_salt_len ac_siggenpss_186_2_salt_len +static const uint8_t ac_rsassa_vect12_ptx[] = { + 0x12, 0x48, 0xf6, 0x2a, 0x43, 0x89, 0xf4, 0x2f, 0x7b, 0x4b, 0xb1, 0x31, + 0x05, 0x3d, 0x6c, 0x88, 0xa9, 0x94, 0xdb, 0x20, 0x75, 0xb9, 0x12, 0xcc, + 0xbe, 0x3e, 0xa7, 0xdc, 0x61, 0x17, 0x14, 0xf1, 0x4e, 0x07, 0x5c, 0x10, + 0x48, 0x58, 0xf2, 0xf6, 0xe6, 0xcf, 0xd6, 0xab, 0xde, 0xdf, 0x01, 0x5a, + 0x82, 0x1d, 0x03, 0x60, 0x8b, 0xf4, 0xeb, 0xa3, 0x16, 0x9a, 0x67, 0x25, + 0xec, 0x42, 0x2c, 0xd9, 0x06, 0x94, 0x98, 0xb5, 0x51, 0x5a, 0x96, 0x08, + 0xae, 0x7c, 0xc3, 0x0e, 0x3d, 0x2e, 0xcf, 0xc1, 0xdb, 0x68, 0x25, 0xf3, + 0xe9, 0x96, 0xce, 0x9a, 0x50, 0x92, 0x92, 0x6b, 0xc1, 0xcf, 0x61, 0xaa, + 0x42, 0xd7, 0xf2, 0x40, 0xe6, 0xf7, 0xaa, 0x0e, 0xdb, 0x38, 0xbf, 0x81, + 0xaa, 0x92, 0x9d, 0x66, 0xbb, 0x5d, 0x89, 0x00, 0x18, 0x08, 0x84, 0x58, + 0x72, 0x0d, 0x72, 0xd5, 0x69, 0x24, 0x7b, 0x0c +}; +static const uint8_t ac_rsassa_vect12_out[] = { + 0x68, 0x2c, 0xf5, 0x3c, 0x11, 0x45, 0xd2, 0x2a, 0x50, 0xca, 0xa9, 0xeb, + 0x1a, 0x9b, 0xa7, 0x06, 0x70, 0xc5, 0x91, 0x5e, 0x0f, 0xdf, 0xde, 0x64, + 0x57, 0xa7, 0x65, 0xde, 0x2a, 0x8f, 0xe1, 0x2d, 0xe9, 0x79, 0x41, 0x72, + 0xa7, 0x8d, 0x14, 0xe6, 0x68, 0xd4, 0x98, 0xac, 0xed, 0xad, 0x61, 0x65, + 0x04, 0xbb, 0x17, 0x64, 0xd0, 0x94, 0x60, 0x70, 0x70, 0x08, 0x05, 0x92, + 0xc3, 0xa6, 0x9c, 0x34, 0x3d, 0x98, 0x2b, 0xd7, 0x78, 0x65, 0x87, 0x3d, + 0x35, 0xe2, 0x48, 0x22, 0xca, 0xf4, 0x34, 0x43, 0xcc, 0x10, 0x24, 0x9a, + 0xf6, 0xa1, 0xe2, 0x6e, 0xf3, 0x44, 0xf2, 0x8b, 0x9e, 0xf6, 0xf1, 0x4e, + 0x09, 0xad, 0x83, 0x97, 0x48, 0xe5, 0x14, 0x8b, 0xcc, 0xeb, 0x0f, 0xd2, + 0xaa, 0x63, 0x70, 0x9c, 0xb4, 0x89, 0x75, 0xcb, 0xf9, 0xc7, 0xb4, 0x9a, + 0xbc, 0x66, 0xa1, 0xdc, 0x6c, 0xb5, 0xb3, 0x1a +}; + +/* SigGenPSS_186-2.txt line 66 SHA-224 */ +#define ac_rsassa_vect17_modulus ac_siggenpss_186_2_modulus +#define ac_rsassa_vect17_pub_exp ac_siggenpss_186_2_pub_exp +#define ac_rsassa_vect17_priv_exp ac_siggenpss_186_2_priv_exp +#define ac_rsassa_vect17_prime1 ac_siggenpss_186_2_prime1 +#define ac_rsassa_vect17_prime2 ac_siggenpss_186_2_prime2 +#define ac_rsassa_vect17_exp1 ac_siggenpss_186_2_exp1 +#define ac_rsassa_vect17_exp2 ac_siggenpss_186_2_exp2 +#define ac_rsassa_vect17_coeff ac_siggenpss_186_2_coeff +#define ac_rsassa_vect17_salt_len ac_siggenpss_186_2_salt_len +static const uint8_t ac_rsassa_vect17_ptx[] = { + 0x12, 0x48, 0xf6, 0x2a, 0x43, 0x89, 0xf4, 0x2f, 0x7b, 0x4b, 0xb1, 0x31, + 0x05, 0x3d, 0x6c, 0x88, 0xa9, 0x94, 0xdb, 0x20, 0x75, 0xb9, 0x12, 0xcc, + 0xbe, 0x3e, 0xa7, 0xdc, 0x61, 0x17, 0x14, 0xf1, 0x4e, 0x07, 0x5c, 0x10, + 0x48, 0x58, 0xf2, 0xf6, 0xe6, 0xcf, 0xd6, 0xab, 0xde, 0xdf, 0x01, 0x5a, + 0x82, 0x1d, 0x03, 0x60, 0x8b, 0xf4, 0xeb, 0xa3, 0x16, 0x9a, 0x67, 0x25, + 0xec, 0x42, 0x2c, 0xd9, 0x06, 0x94, 0x98, 0xb5, 0x51, 0x5a, 0x96, 0x08, + 0xae, 0x7c, 0xc3, 0x0e, 0x3d, 0x2e, 0xcf, 0xc1, 0xdb, 0x68, 0x25, 0xf3, + 0xe9, 0x96, 0xce, 0x9a, 0x50, 0x92, 0x92, 0x6b, 0xc1, 0xcf, 0x61, 0xaa, + 0x42, 0xd7, 0xf2, 0x40, 0xe6, 0xf7, 0xaa, 0x0e, 0xdb, 0x38, 0xbf, 0x81, + 0xaa, 0x92, 0x9d, 0x66, 0xbb, 0x5d, 0x89, 0x00, 0x18, 0x08, 0x84, 0x58, + 0x72, 0x0d, 0x72, 0xd5, 0x69, 0x24, 0x7b, 0x0c, +}; +static const uint8_t ac_rsassa_vect17_out[] = { + 0x53, 0xd8, 0x59, 0xc9, 0xf1, 0x0a, 0xbf, 0x1c, 0x00, 0x28, 0x4a, 0x4b, + 0x55, 0xbf, 0x2b, 0xd8, 0x4d, 0x8e, 0x31, 0x3b, 0x4f, 0x3c, 0x35, 0xb8, + 0xde, 0xc7, 0xbc, 0x3a, 0xfe, 0x39, 0xb9, 0xb8, 0xa1, 0x55, 0x41, 0x8e, + 0xad, 0x19, 0x31, 0x89, 0x57, 0x69, 0xce, 0x23, 0x40, 0xbe, 0x20, 0x91, + 0xf2, 0x38, 0x5b, 0xbc, 0xf1, 0x0d, 0x9e, 0x92, 0xbc, 0xf5, 0xd0, 0xe2, + 0x96, 0x0d, 0x10, 0xe7, 0x92, 0xe7, 0xd8, 0x65, 0xc6, 0x4e, 0x50, 0xd1, + 0x9f, 0xfa, 0x13, 0xe5, 0x28, 0x17, 0xd7, 0xd8, 0xd8, 0xdb, 0x34, 0x39, + 0x2c, 0x23, 0x74, 0xa2, 0xe9, 0xb6, 0x91, 0x84, 0xf9, 0x2a, 0x4a, 0xd9, + 0xb1, 0xb8, 0xba, 0xe9, 0x9c, 0xa6, 0x14, 0xd2, 0x04, 0xb6, 0x5a, 0x43, + 0x8e, 0x38, 0xdb, 0xbf, 0xc8, 0xc7, 0xcc, 0x44, 0xed, 0x56, 0x77, 0xaf, + 0x70, 0xce, 0x6c, 0x4f, 0x95, 0x1f, 0x02, 0x44, +}; + +/* SigGen15_186-2.txt line 114 SHA-256 */ +#define ac_rsassa_vect13_modulus ac_siggenpss_186_2_modulus +#define ac_rsassa_vect13_pub_exp ac_siggenpss_186_2_pub_exp +#define ac_rsassa_vect13_priv_exp ac_siggenpss_186_2_priv_exp +#define ac_rsassa_vect13_prime1 ac_siggenpss_186_2_prime1 +#define ac_rsassa_vect13_prime2 ac_siggenpss_186_2_prime2 +#define ac_rsassa_vect13_exp1 ac_siggenpss_186_2_exp1 +#define ac_rsassa_vect13_exp2 ac_siggenpss_186_2_exp2 +#define ac_rsassa_vect13_coeff ac_siggenpss_186_2_coeff +#define ac_rsassa_vect13_salt_len ac_siggenpss_186_2_salt_len +static const uint8_t ac_rsassa_vect13_ptx[] = { + 0x12, 0x48, 0xf6, 0x2a, 0x43, 0x89, 0xf4, 0x2f, 0x7b, 0x4b, 0xb1, 0x31, + 0x05, 0x3d, 0x6c, 0x88, 0xa9, 0x94, 0xdb, 0x20, 0x75, 0xb9, 0x12, 0xcc, + 0xbe, 0x3e, 0xa7, 0xdc, 0x61, 0x17, 0x14, 0xf1, 0x4e, 0x07, 0x5c, 0x10, + 0x48, 0x58, 0xf2, 0xf6, 0xe6, 0xcf, 0xd6, 0xab, 0xde, 0xdf, 0x01, 0x5a, + 0x82, 0x1d, 0x03, 0x60, 0x8b, 0xf4, 0xeb, 0xa3, 0x16, 0x9a, 0x67, 0x25, + 0xec, 0x42, 0x2c, 0xd9, 0x06, 0x94, 0x98, 0xb5, 0x51, 0x5a, 0x96, 0x08, + 0xae, 0x7c, 0xc3, 0x0e, 0x3d, 0x2e, 0xcf, 0xc1, 0xdb, 0x68, 0x25, 0xf3, + 0xe9, 0x96, 0xce, 0x9a, 0x50, 0x92, 0x92, 0x6b, 0xc1, 0xcf, 0x61, 0xaa, + 0x42, 0xd7, 0xf2, 0x40, 0xe6, 0xf7, 0xaa, 0x0e, 0xdb, 0x38, 0xbf, 0x81, + 0xaa, 0x92, 0x9d, 0x66, 0xbb, 0x5d, 0x89, 0x00, 0x18, 0x08, 0x84, 0x58, + 0x72, 0x0d, 0x72, 0xd5, 0x69, 0x24, 0x7b, 0x0c +}; +static const uint8_t ac_rsassa_vect13_out[] = { + 0x7b, 0x1d, 0x37, 0x27, 0x8e, 0x54, 0x98, 0x98, 0xd4, 0x08, 0x4e, 0x22, + 0x10, 0xc4, 0xa9, 0x96, 0x1e, 0xdf, 0xe7, 0xb5, 0x96, 0x35, 0x50, 0xcc, + 0xa1, 0x90, 0x42, 0x48, 0xc8, 0x68, 0x15, 0x13, 0x53, 0x90, 0x17, 0x82, + 0x0f, 0x0e, 0x9b, 0xd0, 0x74, 0xb9, 0xf8, 0xa0, 0x67, 0xb9, 0xfe, 0xff, + 0xf7, 0xf1, 0xfa, 0x20, 0xbf, 0x2d, 0x0c, 0x75, 0x01, 0x5f, 0xf0, 0x20, + 0xb2, 0x21, 0x0c, 0xc7, 0xf7, 0x90, 0x34, 0xfe, 0xdf, 0x68, 0xe8, 0xd4, + 0x4a, 0x00, 0x7a, 0xbf, 0x4d, 0xd8, 0x2c, 0x26, 0xe8, 0xb0, 0x03, 0x93, + 0x72, 0x3a, 0xea, 0x15, 0xab, 0xfb, 0xc2, 0x29, 0x41, 0xc8, 0xcf, 0x79, + 0x48, 0x17, 0x18, 0xc0, 0x08, 0xda, 0x71, 0x3f, 0xb8, 0xf5, 0x4c, 0xb3, + 0xfc, 0xa8, 0x90, 0xbd, 0xe1, 0x13, 0x73, 0x14, 0x33, 0x4b, 0x9b, 0x0a, + 0x18, 0x51, 0x5b, 0xfa, 0x48, 0xe5, 0xcc, 0xd0 +}; + +/* SigGen15_186-2.txt line 164 SHA-384 */ +#define ac_rsassa_vect14_modulus ac_siggenpss_186_2_modulus +#define ac_rsassa_vect14_pub_exp ac_siggenpss_186_2_pub_exp +#define ac_rsassa_vect14_priv_exp ac_siggenpss_186_2_priv_exp +#define ac_rsassa_vect14_prime1 ac_siggenpss_186_2_prime1 +#define ac_rsassa_vect14_prime2 ac_siggenpss_186_2_prime2 +#define ac_rsassa_vect14_exp1 ac_siggenpss_186_2_exp1 +#define ac_rsassa_vect14_exp2 ac_siggenpss_186_2_exp2 +#define ac_rsassa_vect14_coeff ac_siggenpss_186_2_coeff +#define ac_rsassa_vect14_salt_len ac_siggenpss_186_2_salt_len +static const uint8_t ac_rsassa_vect14_ptx[] = { + 0x12, 0x48, 0xf6, 0x2a, 0x43, 0x89, 0xf4, 0x2f, 0x7b, 0x4b, 0xb1, 0x31, + 0x05, 0x3d, 0x6c, 0x88, 0xa9, 0x94, 0xdb, 0x20, 0x75, 0xb9, 0x12, 0xcc, + 0xbe, 0x3e, 0xa7, 0xdc, 0x61, 0x17, 0x14, 0xf1, 0x4e, 0x07, 0x5c, 0x10, + 0x48, 0x58, 0xf2, 0xf6, 0xe6, 0xcf, 0xd6, 0xab, 0xde, 0xdf, 0x01, 0x5a, + 0x82, 0x1d, 0x03, 0x60, 0x8b, 0xf4, 0xeb, 0xa3, 0x16, 0x9a, 0x67, 0x25, + 0xec, 0x42, 0x2c, 0xd9, 0x06, 0x94, 0x98, 0xb5, 0x51, 0x5a, 0x96, 0x08, + 0xae, 0x7c, 0xc3, 0x0e, 0x3d, 0x2e, 0xcf, 0xc1, 0xdb, 0x68, 0x25, 0xf3, + 0xe9, 0x96, 0xce, 0x9a, 0x50, 0x92, 0x92, 0x6b, 0xc1, 0xcf, 0x61, 0xaa, + 0x42, 0xd7, 0xf2, 0x40, 0xe6, 0xf7, 0xaa, 0x0e, 0xdb, 0x38, 0xbf, 0x81, + 0xaa, 0x92, 0x9d, 0x66, 0xbb, 0x5d, 0x89, 0x00, 0x18, 0x08, 0x84, 0x58, + 0x72, 0x0d, 0x72, 0xd5, 0x69, 0x24, 0x7b, 0x0c +}; +static const uint8_t ac_rsassa_vect14_out[] = { + 0x8f, 0x16, 0xc8, 0x07, 0xbe, 0xf3, 0xed, 0x6f, 0x74, 0xee, 0x7f, 0xf5, + 0xc3, 0x60, 0xa5, 0x42, 0x8c, 0x6c, 0x2f, 0x10, 0x51, 0x78, 0xb5, 0x8f, + 0xf7, 0xd0, 0x73, 0xe5, 0x66, 0xda, 0xd6, 0xe7, 0x71, 0x8d, 0x31, 0x29, + 0xc7, 0x68, 0xcd, 0x5a, 0x96, 0x66, 0xde, 0x2b, 0x6c, 0x94, 0x71, 0x77, + 0xb4, 0x57, 0x09, 0xdc, 0x7c, 0xd0, 0xf4, 0x3b, 0x0b, 0xa6, 0xfc, 0x75, + 0x57, 0x8e, 0x11, 0x96, 0xac, 0xc1, 0x5c, 0xa3, 0xaf, 0xe4, 0xa7, 0x8c, + 0x14, 0x4c, 0xb6, 0x88, 0x5c, 0x1c, 0xc8, 0x15, 0xf7, 0xf9, 0x89, 0x25, + 0xbc, 0x04, 0xad, 0x2f, 0xf2, 0x0f, 0xc1, 0x06, 0x8b, 0x04, 0x5d, 0x94, + 0x50, 0xe2, 0xa1, 0xdc, 0xf5, 0xa1, 0x61, 0xce, 0xab, 0xba, 0x2b, 0x0b, + 0x66, 0xc7, 0x35, 0x4f, 0xdb, 0x80, 0xfa, 0x1d, 0x72, 0x9e, 0x5f, 0x97, + 0x63, 0x87, 0xf2, 0x4a, 0x69, 0x7a, 0x7e, 0x56 +}; + +/* SigGen15_186-2.txt line 214 SHA-512 */ +#define ac_rsassa_vect15_modulus ac_siggenpss_186_2_modulus +#define ac_rsassa_vect15_pub_exp ac_siggenpss_186_2_pub_exp +#define ac_rsassa_vect15_priv_exp ac_siggenpss_186_2_priv_exp +#define ac_rsassa_vect15_prime1 ac_siggenpss_186_2_prime1 +#define ac_rsassa_vect15_prime2 ac_siggenpss_186_2_prime2 +#define ac_rsassa_vect15_exp1 ac_siggenpss_186_2_exp1 +#define ac_rsassa_vect15_exp2 ac_siggenpss_186_2_exp2 +#define ac_rsassa_vect15_coeff ac_siggenpss_186_2_coeff +#define ac_rsassa_vect15_salt_len ac_siggenpss_186_2_salt_len +static const uint8_t ac_rsassa_vect15_ptx[] = { + 0x12, 0x48, 0xf6, 0x2a, 0x43, 0x89, 0xf4, 0x2f, 0x7b, 0x4b, 0xb1, 0x31, + 0x05, 0x3d, 0x6c, 0x88, 0xa9, 0x94, 0xdb, 0x20, 0x75, 0xb9, 0x12, 0xcc, + 0xbe, 0x3e, 0xa7, 0xdc, 0x61, 0x17, 0x14, 0xf1, 0x4e, 0x07, 0x5c, 0x10, + 0x48, 0x58, 0xf2, 0xf6, 0xe6, 0xcf, 0xd6, 0xab, 0xde, 0xdf, 0x01, 0x5a, + 0x82, 0x1d, 0x03, 0x60, 0x8b, 0xf4, 0xeb, 0xa3, 0x16, 0x9a, 0x67, 0x25, + 0xec, 0x42, 0x2c, 0xd9, 0x06, 0x94, 0x98, 0xb5, 0x51, 0x5a, 0x96, 0x08, + 0xae, 0x7c, 0xc3, 0x0e, 0x3d, 0x2e, 0xcf, 0xc1, 0xdb, 0x68, 0x25, 0xf3, + 0xe9, 0x96, 0xce, 0x9a, 0x50, 0x92, 0x92, 0x6b, 0xc1, 0xcf, 0x61, 0xaa, + 0x42, 0xd7, 0xf2, 0x40, 0xe6, 0xf7, 0xaa, 0x0e, 0xdb, 0x38, 0xbf, 0x81, + 0xaa, 0x92, 0x9d, 0x66, 0xbb, 0x5d, 0x89, 0x00, 0x18, 0x08, 0x84, 0x58, + 0x72, 0x0d, 0x72, 0xd5, 0x69, 0x24, 0x7b, 0x0c +}; +static const uint8_t ac_rsassa_vect15_out[] = { + 0xa8, 0x33, 0xba, 0x31, 0x63, 0x4f, 0x87, 0x73, 0xe4, 0xfe, 0x6e, 0xa0, + 0xc6, 0x9e, 0x1a, 0x23, 0x76, 0x6a, 0x93, 0x9d, 0x34, 0xb3, 0x2f, 0xc7, + 0x8b, 0x77, 0x4b, 0x22, 0xe4, 0x6a, 0x64, 0x6c, 0x25, 0xe6, 0xe1, 0x06, + 0x2d, 0x23, 0x4e, 0xd4, 0x8b, 0x1a, 0xba, 0x0f, 0x83, 0x05, 0x29, 0xff, + 0x6a, 0xfc, 0x29, 0x6c, 0xc8, 0xdc, 0x20, 0x7b, 0xbc, 0x15, 0x39, 0x16, + 0x23, 0xbe, 0xac, 0x5f, 0x6c, 0x3d, 0xb5, 0x57, 0xca, 0x49, 0xd0, 0xe4, + 0x2c, 0x96, 0x2d, 0xe9, 0x5b, 0x5f, 0xf5, 0x48, 0xcf, 0xf9, 0x70, 0xf5, + 0xc7, 0x3f, 0x43, 0x9c, 0xfe, 0x82, 0xd3, 0x90, 0x7b, 0xe6, 0x02, 0x40, + 0xf5, 0x6b, 0x6a, 0x42, 0x59, 0xcc, 0x96, 0xdf, 0xd8, 0xfe, 0x02, 0xa0, + 0xbf, 0xa2, 0x6e, 0x02, 0x23, 0xf6, 0x82, 0x14, 0x42, 0x8f, 0xff, 0x0a, + 0xe4, 0x01, 0x62, 0x19, 0x8c, 0xc5, 0xcb, 0xd1 +}; + +/* + * Test data from ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt + * + * As specified in PKCS#1, the block type for this operation is 2. + * The seed value of each example provides the pseudo random bytes + * to be used for padding. This makes the result predictable. + */ + +/* PKCS#1 v1.5 Signature Example 1 1024-bit RSA key pair */ +static const uint8_t ac_rsaes_pkcs1_v1_5_example1_modulus[] = { + 0xa8, 0xb3, 0xb2, 0x84, 0xaf, 0x8e, 0xb5, 0x0b, 0x38, 0x70, 0x34, 0xa8, + 0x60, 0xf1, 0x46, 0xc4, 0x91, 0x9f, 0x31, 0x87, 0x63, 0xcd, 0x6c, 0x55, + 0x98, 0xc8, 0xae, 0x48, 0x11, 0xa1, 0xe0, 0xab, 0xc4, 0xc7, 0xe0, 0xb0, + 0x82, 0xd6, 0x93, 0xa5, 0xe7, 0xfc, 0xed, 0x67, 0x5c, 0xf4, 0x66, 0x85, + 0x12, 0x77, 0x2c, 0x0c, 0xbc, 0x64, 0xa7, 0x42, 0xc6, 0xc6, 0x30, 0xf5, + 0x33, 0xc8, 0xcc, 0x72, 0xf6, 0x2a, 0xe8, 0x33, 0xc4, 0x0b, 0xf2, 0x58, + 0x42, 0xe9, 0x84, 0xbb, 0x78, 0xbd, 0xbf, 0x97, 0xc0, 0x10, 0x7d, 0x55, + 0xbd, 0xb6, 0x62, 0xf5, 0xc4, 0xe0, 0xfa, 0xb9, 0x84, 0x5c, 0xb5, 0x14, + 0x8e, 0xf7, 0x39, 0x2d, 0xd3, 0xaa, 0xff, 0x93, 0xae, 0x1e, 0x6b, 0x66, + 0x7b, 0xb3, 0xd4, 0x24, 0x76, 0x16, 0xd4, 0xf5, 0xba, 0x10, 0xd4, 0xcf, + 0xd2, 0x26, 0xde, 0x88, 0xd3, 0x9f, 0x16, 0xfb +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_example1_pub_exp[] = { + 0x01, 0x00, 0x01 +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_example1_priv_exp[] = { + 0x53, 0x33, 0x9c, 0xfd, 0xb7, 0x9f, 0xc8, 0x46, 0x6a, 0x65, 0x5c, 0x73, + 0x16, 0xac, 0xa8, 0x5c, 0x55, 0xfd, 0x8f, 0x6d, 0xd8, 0x98, 0xfd, 0xaf, + 0x11, 0x95, 0x17, 0xef, 0x4f, 0x52, 0xe8, 0xfd, 0x8e, 0x25, 0x8d, 0xf9, + 0x3f, 0xee, 0x18, 0x0f, 0xa0, 0xe4, 0xab, 0x29, 0x69, 0x3c, 0xd8, 0x3b, + 0x15, 0x2a, 0x55, 0x3d, 0x4a, 0xc4, 0xd1, 0x81, 0x2b, 0x8b, 0x9f, 0xa5, + 0xaf, 0x0e, 0x7f, 0x55, 0xfe, 0x73, 0x04, 0xdf, 0x41, 0x57, 0x09, 0x26, + 0xf3, 0x31, 0x1f, 0x15, 0xc4, 0xd6, 0x5a, 0x73, 0x2c, 0x48, 0x31, 0x16, + 0xee, 0x3d, 0x3d, 0x2d, 0x0a, 0xf3, 0x54, 0x9a, 0xd9, 0xbf, 0x7c, 0xbf, + 0xb7, 0x8a, 0xd8, 0x84, 0xf8, 0x4d, 0x5b, 0xeb, 0x04, 0x72, 0x4d, 0xc7, + 0x36, 0x9b, 0x31, 0xde, 0xf3, 0x7d, 0x0c, 0xf5, 0x39, 0xe9, 0xcf, 0xcd, + 0xd3, 0xde, 0x65, 0x37, 0x29, 0xea, 0xd5, 0xd1 +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_example1_prime1[] = { + 0xd3, 0x27, 0x37, 0xe7, 0x26, 0x7f, 0xfe, 0x13, 0x41, 0xb2, 0xd5, 0xc0, + 0xd1, 0x50, 0xa8, 0x1b, 0x58, 0x6f, 0xb3, 0x13, 0x2b, 0xed, 0x2f, 0x8d, + 0x52, 0x62, 0x86, 0x4a, 0x9c, 0xb9, 0xf3, 0x0a, 0xf3, 0x8b, 0xe4, 0x48, + 0x59, 0x8d, 0x41, 0x3a, 0x17, 0x2e, 0xfb, 0x80, 0x2c, 0x21, 0xac, 0xf1, + 0xc1, 0x1c, 0x52, 0x0c, 0x2f, 0x26, 0xa4, 0x71, 0xdc, 0xad, 0x21, 0x2e, + 0xac, 0x7c, 0xa3, 0x9d +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_example1_prime2[] = { + 0xcc, 0x88, 0x53, 0xd1, 0xd5, 0x4d, 0xa6, 0x30, 0xfa, 0xc0, 0x04, 0xf4, + 0x71, 0xf2, 0x81, 0xc7, 0xb8, 0x98, 0x2d, 0x82, 0x24, 0xa4, 0x90, 0xed, + 0xbe, 0xb3, 0x3d, 0x3e, 0x3d, 0x5c, 0xc9, 0x3c, 0x47, 0x65, 0x70, 0x3d, + 0x1d, 0xd7, 0x91, 0x64, 0x2f, 0x1f, 0x11, 0x6a, 0x0d, 0xd8, 0x52, 0xbe, + 0x24, 0x19, 0xb2, 0xaf, 0x72, 0xbf, 0xe9, 0xa0, 0x30, 0xe8, 0x60, 0xb0, + 0x28, 0x8b, 0x5d, 0x77 +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_example1_exp1[] = { + 0x0e, 0x12, 0xbf, 0x17, 0x18, 0xe9, 0xce, 0xf5, 0x59, 0x9b, 0xa1, 0xc3, + 0x88, 0x2f, 0xe8, 0x04, 0x6a, 0x90, 0x87, 0x4e, 0xef, 0xce, 0x8f, 0x2c, + 0xcc, 0x20, 0xe4, 0xf2, 0x74, 0x1f, 0xb0, 0xa3, 0x3a, 0x38, 0x48, 0xae, + 0xc9, 0xc9, 0x30, 0x5f, 0xbe, 0xcb, 0xd2, 0xd7, 0x68, 0x19, 0x96, 0x7d, + 0x46, 0x71, 0xac, 0xc6, 0x43, 0x1e, 0x40, 0x37, 0x96, 0x8d, 0xb3, 0x78, + 0x78, 0xe6, 0x95, 0xc1 +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_example1_exp2[] = { + 0x95, 0x29, 0x7b, 0x0f, 0x95, 0xa2, 0xfa, 0x67, 0xd0, 0x07, 0x07, 0xd6, + 0x09, 0xdf, 0xd4, 0xfc, 0x05, 0xc8, 0x9d, 0xaf, 0xc2, 0xef, 0x6d, 0x6e, + 0xa5, 0x5b, 0xec, 0x77, 0x1e, 0xa3, 0x33, 0x73, 0x4d, 0x92, 0x51, 0xe7, + 0x90, 0x82, 0xec, 0xda, 0x86, 0x6e, 0xfe, 0xf1, 0x3c, 0x45, 0x9e, 0x1a, + 0x63, 0x13, 0x86, 0xb7, 0xe3, 0x54, 0xc8, 0x99, 0xf5, 0xf1, 0x12, 0xca, + 0x85, 0xd7, 0x15, 0x83 +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_example1_coeff[] = { + 0x4f, 0x45, 0x6c, 0x50, 0x24, 0x93, 0xbd, 0xc0, 0xed, 0x2a, 0xb7, 0x56, + 0xa3, 0xa6, 0xed, 0x4d, 0x67, 0x35, 0x2a, 0x69, 0x7d, 0x42, 0x16, 0xe9, + 0x32, 0x12, 0xb1, 0x27, 0xa6, 0x3d, 0x54, 0x11, 0xce, 0x6f, 0xa9, 0x8d, + 0x5d, 0xbe, 0xfd, 0x73, 0x26, 0x3e, 0x37, 0x28, 0x14, 0x27, 0x43, 0x81, + 0x81, 0x66, 0xed, 0x7d, 0xd6, 0x36, 0x87, 0xdd, 0x2a, 0x8c, 0xa1, 0xd2, + 0xf4, 0xfb, 0xd8, 0xe1 +}; + + +/* PKCS#1 v1.5 Encrypt Example 1.1 */ +#define ac_rsaes_pkcs1_v1_5_vect1_modulus ac_rsaes_pkcs1_v1_5_example1_modulus +#define ac_rsaes_pkcs1_v1_5_vect1_pub_exp ac_rsaes_pkcs1_v1_5_example1_pub_exp +#define ac_rsaes_pkcs1_v1_5_vect1_priv_exp ac_rsaes_pkcs1_v1_5_example1_priv_exp +#define ac_rsaes_pkcs1_v1_5_vect1_prime1 ac_rsaes_pkcs1_v1_5_example1_prime1 +#define ac_rsaes_pkcs1_v1_5_vect1_prime2 ac_rsaes_pkcs1_v1_5_example1_prime2 +#define ac_rsaes_pkcs1_v1_5_vect1_exp1 ac_rsaes_pkcs1_v1_5_example1_exp1 +#define ac_rsaes_pkcs1_v1_5_vect1_exp2 ac_rsaes_pkcs1_v1_5_example1_exp2 +#define ac_rsaes_pkcs1_v1_5_vect1_coeff ac_rsaes_pkcs1_v1_5_example1_coeff +static const uint8_t ac_rsaes_pkcs1_v1_5_vect1_ptx[] = { + 0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, 0x3b, 0xa9, 0x4c, 0xda, + 0x9e, 0xf9, 0x53, 0x23, + 0x97, 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, 0x4a, 0xfe, 0xfe, 0x34, +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_vect1_out[] = { + 0x50, 0xb4, 0xc1, 0x41, 0x36, 0xbd, 0x19, 0x8c, 0x2f, 0x3c, 0x3e, 0xd2, + 0x43, 0xfc, 0xe0, 0x36, + 0xe1, 0x68, 0xd5, 0x65, 0x17, 0x98, 0x4a, 0x26, 0x3c, 0xd6, 0x64, 0x92, + 0xb8, 0x08, 0x04, 0xf1, + 0x69, 0xd2, 0x10, 0xf2, 0xb9, 0xbd, 0xfb, 0x48, 0xb1, 0x2f, 0x9e, 0xa0, + 0x50, 0x09, 0xc7, 0x7d, + 0xa2, 0x57, 0xcc, 0x60, 0x0c, 0xce, 0xfe, 0x3a, 0x62, 0x83, 0x78, 0x9d, + 0x8e, 0xa0, 0xe6, 0x07, + 0xac, 0x58, 0xe2, 0x69, 0x0e, 0xc4, 0xeb, 0xc1, 0x01, 0x46, 0xe8, 0xcb, + 0xaa, 0x5e, 0xd4, 0xd5, + 0xcc, 0xe6, 0xfe, 0x7b, 0x0f, 0xf9, 0xef, 0xc1, 0xea, 0xbb, 0x56, 0x4d, + 0xbf, 0x49, 0x82, 0x85, + 0xf4, 0x49, 0xee, 0x61, 0xdd, 0x7b, 0x42, 0xee, 0x5b, 0x58, 0x92, 0xcb, + 0x90, 0x60, 0x1f, 0x30, + 0xcd, 0xa0, 0x7b, 0xf2, 0x64, 0x89, 0x31, 0x0b, 0xcd, 0x23, 0xb5, 0x28, + 0xce, 0xab, 0x3c, 0x31, +}; + + +/* PKCS#1 v1.5 Encrypt Example 1.2 */ +#define ac_rsaes_pkcs1_v1_5_vect2_modulus ac_rsaes_pkcs1_v1_5_example1_modulus +#define ac_rsaes_pkcs1_v1_5_vect2_pub_exp ac_rsaes_pkcs1_v1_5_example1_pub_exp +#define ac_rsaes_pkcs1_v1_5_vect2_priv_exp ac_rsaes_pkcs1_v1_5_example1_priv_exp +#define ac_rsaes_pkcs1_v1_5_vect2_prime1 ac_rsaes_pkcs1_v1_5_example1_prime1 +#define ac_rsaes_pkcs1_v1_5_vect2_prime2 ac_rsaes_pkcs1_v1_5_example1_prime2 +#define ac_rsaes_pkcs1_v1_5_vect2_exp1 ac_rsaes_pkcs1_v1_5_example1_exp1 +#define ac_rsaes_pkcs1_v1_5_vect2_exp2 ac_rsaes_pkcs1_v1_5_example1_exp2 +#define ac_rsaes_pkcs1_v1_5_vect2_coeff ac_rsaes_pkcs1_v1_5_example1_coeff +static const uint8_t ac_rsaes_pkcs1_v1_5_vect2_ptx[] = { + 0x75, 0x0c, 0x40, 0x47, 0xf5, 0x47, 0xe8, 0xe4, 0x14, 0x11, 0x85, 0x65, + 0x23, 0x29, 0x8a, 0xc9, 0xba, 0xe2, 0x45, 0xef, 0xaf, 0x13, 0x97, 0xfb, + 0xe5, 0x6f, 0x9d, 0xd5 +}; +static const uint8_t ac_rsaes_pkcs1_v1_5_vect2_out[] = { + 0x68, 0x42, 0xe5, 0xe2, 0xcc, 0x00, 0x41, 0xd6, 0xb0, 0xc8, 0x1a, 0x56, + 0x2c, 0x39, 0xa6, 0x17, 0x37, 0x9a, 0x51, 0x5c, 0xab, 0x74, 0xab, 0xcb, + 0x26, 0x19, 0xc7, 0x74, 0x0a, 0x54, 0x1d, 0x95, 0x55, 0xdd, 0x91, 0x65, + 0x97, 0x5b, 0xf8, 0xa3, 0xeb, 0xd0, 0xd0, 0x45, 0x66, 0x61, 0xdf, 0xb1, + 0xa6, 0x86, 0x1b, 0xa2, 0x33, 0x22, 0x69, 0x93, 0x0e, 0x0d, 0xb5, 0x14, + 0xfc, 0xa0, 0x73, 0x3e, 0xeb, 0x9c, 0x40, 0x57, 0x13, 0xeb, 0x1f, 0x9d, + 0x76, 0x80, 0x33, 0xed, 0x29, 0x3e, 0x1e, 0x08, 0x1a, 0x12, 0x5f, 0x32, + 0xdd, 0xb9, 0xea, 0x52, 0xed, 0xbe, 0x27, 0x5c, 0x4a, 0xf6, 0x0f, 0x8a, + 0x7b, 0xf8, 0x32, 0xbd, 0x22, 0x75, 0x61, 0xc2, 0x08, 0xdc, 0x00, 0x31, + 0xa8, 0x4b, 0x50, 0x12, 0xc9, 0xdd, 0x9f, 0x74, 0x45, 0x9d, 0xcb, 0x07, + 0x0b, 0xdb, 0xe1, 0x3c, 0xfa, 0x8c, 0x2d, 0x50 +}; + +/* + * Test data from ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + * + * The underlying hash function is SHA-1; the mask generation function is + * MGF1 with SHA-1 as specified in PKCS #1 v2.1. + */ + +/* Example 1: A 1024-bit RSA Key Pair */ +#define ac_rsaes_oaep_example1_modulus ac_rsaes_pkcs1_v1_5_example1_modulus +#define ac_rsaes_oaep_example1_pub_exp ac_rsaes_pkcs1_v1_5_example1_pub_exp +#define ac_rsaes_oaep_example1_priv_exp ac_rsaes_pkcs1_v1_5_example1_priv_exp +#define ac_rsaes_oaep_example1_prime1 ac_rsaes_pkcs1_v1_5_example1_prime1 +#define ac_rsaes_oaep_example1_prime2 ac_rsaes_pkcs1_v1_5_example1_prime2 +#define ac_rsaes_oaep_example1_exp1 ac_rsaes_pkcs1_v1_5_example1_exp1 +#define ac_rsaes_oaep_example1_exp2 ac_rsaes_pkcs1_v1_5_example1_exp2 +#define ac_rsaes_oaep_example1_coeff ac_rsaes_pkcs1_v1_5_example1_coeff + + +/* RSAES-OAEP Encryption Example 1.1 */ +#define ac_rsaes_oaep_vect1_modulus ac_rsaes_oaep_example1_modulus +#define ac_rsaes_oaep_vect1_pub_exp ac_rsaes_oaep_example1_pub_exp +#define ac_rsaes_oaep_vect1_priv_exp ac_rsaes_oaep_example1_priv_exp +#define ac_rsaes_oaep_vect1_prime1 ac_rsaes_oaep_example1_prime1 +#define ac_rsaes_oaep_vect1_prime2 ac_rsaes_oaep_example1_prime2 +#define ac_rsaes_oaep_vect1_exp1 ac_rsaes_oaep_example1_exp1 +#define ac_rsaes_oaep_vect1_exp2 ac_rsaes_oaep_example1_exp2 +#define ac_rsaes_oaep_vect1_coeff ac_rsaes_oaep_example1_coeff +static const uint8_t ac_rsaes_oaep_vect1_ptx[] = { + 0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, 0x3b, 0xa9, 0x4c, 0xda, + 0x9e, 0xf9, 0x53, 0x23, 0x97, 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, + 0x4a, 0xfe, 0xfe, 0x34, +}; +static const uint8_t ac_rsaes_oaep_vect1_out[] = { + 0x35, 0x4f, 0xe6, 0x7b, 0x4a, 0x12, 0x6d, 0x5d, 0x35, 0xfe, 0x36, 0xc7, + 0x77, 0x79, 0x1a, 0x3f, 0x7b, 0xa1, 0x3d, 0xef, 0x48, 0x4e, 0x2d, 0x39, + 0x08, 0xaf, 0xf7, 0x22, 0xfa, 0xd4, 0x68, 0xfb, 0x21, 0x69, 0x6d, 0xe9, + 0x5d, 0x0b, 0xe9, 0x11, 0xc2, 0xd3, 0x17, 0x4f, 0x8a, 0xfc, 0xc2, 0x01, + 0x03, 0x5f, 0x7b, 0x6d, 0x8e, 0x69, 0x40, 0x2d, 0xe5, 0x45, 0x16, 0x18, + 0xc2, 0x1a, 0x53, 0x5f, 0xa9, 0xd7, 0xbf, 0xc5, 0xb8, 0xdd, 0x9f, 0xc2, + 0x43, 0xf8, 0xcf, 0x92, 0x7d, 0xb3, 0x13, 0x22, 0xd6, 0xe8, 0x81, 0xea, + 0xa9, 0x1a, 0x99, 0x61, 0x70, 0xe6, 0x57, 0xa0, 0x5a, 0x26, 0x64, 0x26, + 0xd9, 0x8c, 0x88, 0x00, 0x3f, 0x84, 0x77, 0xc1, 0x22, 0x70, 0x94, 0xa0, + 0xd9, 0xfa, 0x1e, 0x8c, 0x40, 0x24, 0x30, 0x9c, 0xe1, 0xec, 0xcc, 0xb5, + 0x21, 0x00, 0x35, 0xd4, 0x7a, 0xc7, 0x2e, 0x8a +}; + +/* RSAES-OAEP Encryption Example 1.2 */ +#define ac_rsaes_oaep_vect2_modulus ac_rsaes_oaep_example1_modulus +#define ac_rsaes_oaep_vect2_pub_exp ac_rsaes_oaep_example1_pub_exp +#define ac_rsaes_oaep_vect2_priv_exp ac_rsaes_oaep_example1_priv_exp +#define ac_rsaes_oaep_vect2_prime1 ac_rsaes_oaep_example1_prime1 +#define ac_rsaes_oaep_vect2_prime2 ac_rsaes_oaep_example1_prime2 +#define ac_rsaes_oaep_vect2_exp1 ac_rsaes_oaep_example1_exp1 +#define ac_rsaes_oaep_vect2_exp2 ac_rsaes_oaep_example1_exp2 +#define ac_rsaes_oaep_vect2_coeff ac_rsaes_oaep_example1_coeff +static const uint8_t ac_rsaes_oaep_vect2_ptx[] = { + 0x75, 0x0c, 0x40, 0x47, 0xf5, 0x47, 0xe8, 0xe4, 0x14, 0x11, 0x85, 0x65, + 0x23, 0x29, 0x8a, 0xc9, 0xba, 0xe2, 0x45, 0xef, 0xaf, 0x13, 0x97, 0xfb, + 0xe5, 0x6f, 0x9d, 0xd5 +}; +static const uint8_t ac_rsaes_oaep_vect2_out[] = { + 0x64, 0x0d, 0xb1, 0xac, 0xc5, 0x8e, 0x05, 0x68, 0xfe, 0x54, 0x07, 0xe5, + 0xf9, 0xb7, 0x01, 0xdf, 0xf8, 0xc3, 0xc9, 0x1e, 0x71, 0x6c, 0x53, 0x6f, + 0xc7, 0xfc, 0xec, 0x6c, 0xb5, 0xb7, 0x1c, 0x11, 0x65, 0x98, 0x8d, 0x4a, + 0x27, 0x9e, 0x15, 0x77, 0xd7, 0x30, 0xfc, 0x7a, 0x29, 0x93, 0x2e, 0x3f, + 0x00, 0xc8, 0x15, 0x15, 0x23, 0x6d, 0x8d, 0x8e, 0x31, 0x01, 0x7a, 0x7a, + 0x09, 0xdf, 0x43, 0x52, 0xd9, 0x04, 0xcd, 0xeb, 0x79, 0xaa, 0x58, 0x3a, + 0xdc, 0xc3, 0x1e, 0xa6, 0x98, 0xa4, 0xc0, 0x52, 0x83, 0xda, 0xba, 0x90, + 0x89, 0xbe, 0x54, 0x91, 0xf6, 0x7c, 0x1a, 0x4e, 0xe4, 0x8d, 0xc7, 0x4b, + 0xbb, 0xe6, 0x64, 0x3a, 0xef, 0x84, 0x66, 0x79, 0xb4, 0xcb, 0x39, 0x5a, + 0x35, 0x2d, 0x5e, 0xd1, 0x15, 0x91, 0x2d, 0xf6, 0x96, 0xff, 0xe0, 0x70, + 0x29, 0x32, 0x94, 0x6d, 0x71, 0x49, 0x2b, 0x44 +}; + +/* + * PKCS#1 v1.5 Signature Example 15 2048-bit RSA key pair + * from http://armcryptolib.das-labor.org/trac/browser/testvectors/rsa-pkcs-1v2-1-vec/oaep-vect.txt + */ +static const uint8_t ac_rsaes_pkcs1_v1_5_example15_modulus[] = { + 0xdc, 0xfa, 0x10, 0xff, 0xa7, 0x46, 0x65, 0xae, 0xef, 0x87, 0x09, 0x74, 0xea, 0x99, 0xb2, 0xce, + 0x54, 0x54, 0x7c, 0x67, 0xf4, 0x2a, 0xaa, 0x6d, 0xd0, 0x1a, 0x2e, 0xd3, 0x1f, 0xd2, 0xc2, 0x42, + 0xaf, 0x5d, 0x96, 0x0b, 0x1f, 0x89, 0x6e, 0xfb, 0xa3, 0x54, 0x3d, 0x65, 0x54, 0xb7, 0xb1, 0x26, + 0x87, 0xa5, 0xc6, 0x88, 0x56, 0x8f, 0x32, 0xe0, 0x26, 0xc5, 0x32, 0xd2, 0x59, 0x93, 0xb9, 0x7a, + 0x7c, 0x28, 0x42, 0xec, 0x2b, 0x8e, 0x12, 0x35, 0xee, 0xe2, 0x41, 0x4d, 0x25, 0x80, 0x6c, 0x6f, + 0xba, 0xe4, 0x38, 0x95, 0x4e, 0xba, 0x9d, 0x27, 0x55, 0xdf, 0xfe, 0xeb, 0x1b, 0x47, 0x70, 0x09, + 0x57, 0x81, 0x5a, 0x8a, 0x23, 0x3f, 0x97, 0xb1, 0xa2, 0xc7, 0x14, 0xb3, 0xe2, 0xbe, 0x2e, 0x42, + 0xd8, 0xbe, 0x30, 0xb1, 0x96, 0x15, 0x82, 0xea, 0x99, 0x48, 0x91, 0x0e, 0x0c, 0x79, 0x7c, 0x50, + 0xfc, 0x4b, 0xb4, 0x55, 0xf0, 0xfc, 0x45, 0xe5, 0xe3, 0x4e, 0x63, 0x96, 0xac, 0x5b, 0x2d, 0x46, + 0x23, 0x93, 0x65, 0xc7, 0xf3, 0xda, 0xaf, 0x09, 0x09, 0x40, 0x0d, 0x61, 0xcf, 0x9e, 0x0c, 0xa8, + 0x08, 0x3e, 0xaf, 0x33, 0x5a, 0x6f, 0xce, 0xb6, 0x86, 0x3c, 0x1c, 0xc0, 0xcf, 0x5a, 0x17, 0x1a, + 0xff, 0x35, 0xd9, 0x7e, 0xcb, 0x60, 0xef, 0x25, 0x1c, 0x7e, 0xc2, 0xc8, 0xa5, 0x88, 0x36, 0x1d, + 0xc4, 0x12, 0x66, 0xa4, 0xb7, 0xed, 0x38, 0xb0, 0x26, 0xce, 0x0d, 0x53, 0x78, 0x64, 0x49, 0xdb, + 0xb1, 0x1a, 0x06, 0xea, 0x33, 0xcc, 0xf1, 0xec, 0xa5, 0x75, 0x20, 0x1e, 0xd1, 0xaa, 0x47, 0x3e, + 0xd1, 0x18, 0x7e, 0xc1, 0xd8, 0xa7, 0x44, 0xea, 0x34, 0x5b, 0xed, 0x7e, 0xa0, 0x0e, 0xe4, 0xe8, + 0x1b, 0xba, 0x46, 0x48, 0x60, 0x1d, 0xd5, 0x37, 0xdc, 0x91, 0x01, 0x5d, 0x31, 0xf0, 0xc2, 0xc1, +}; + +static const uint8_t ac_rsaes_pkcs1_v1_5_example15_pub_exp[] = { + 0x01, 0x00, 0x01, +}; + +static const uint8_t ac_rsaes_pkcs1_v1_5_example15_priv_exp[] = { + 0x21, 0x95, 0x08, 0x51, 0xcd, 0xf2, 0x53, 0x20, 0x31, 0x8b, 0x30, 0x5a, 0xfa, 0x0f, 0x37, 0x1f, + 0x07, 0xae, 0x5a, 0x44, 0xb3, 0x14, 0xeb, 0xd7, 0x29, 0xf5, 0xdc, 0xb1, 0x5d, 0xa7, 0xfa, 0x39, + 0x47, 0xac, 0xdd, 0x91, 0x5d, 0xae, 0xd5, 0x74, 0xbd, 0x16, 0xdf, 0x88, 0xbf, 0x85, 0xf6, 0x10, + 0x60, 0xb3, 0x87, 0x17, 0x2f, 0xae, 0x6e, 0x01, 0x26, 0x2b, 0x38, 0x64, 0xc2, 0xd3, 0xc2, 0x2f, + 0x94, 0xe0, 0x4a, 0x81, 0x59, 0x42, 0x2b, 0x4e, 0xd2, 0x79, 0xc4, 0x8a, 0x4c, 0x9d, 0x76, 0x7d, + 0x49, 0x66, 0x07, 0x1a, 0x5b, 0xbf, 0x5d, 0x04, 0x3e, 0x16, 0xff, 0x46, 0xec, 0x1b, 0xa0, 0x71, + 0x6f, 0x00, 0xbb, 0xc9, 0x7b, 0xff, 0x5d, 0x56, 0x93, 0xe2, 0x14, 0xe9, 0x9c, 0x97, 0x21, 0xf1, + 0x2b, 0x3e, 0xc6, 0x28, 0x2a, 0xe2, 0xa4, 0x85, 0x72, 0x1b, 0x96, 0xdd, 0xcf, 0x74, 0x03, 0xfa, + 0x03, 0x7d, 0x0c, 0x57, 0xab, 0x46, 0x3c, 0x44, 0x8d, 0xe5, 0xcc, 0x12, 0x26, 0x5a, 0xdd, 0x88, + 0x6d, 0x31, 0x1e, 0xa8, 0xd8, 0xa5, 0x90, 0x3f, 0xa5, 0x6c, 0x5f, 0x1c, 0x9c, 0xf2, 0xeb, 0x11, + 0xcb, 0x65, 0x7a, 0x1a, 0x7d, 0x3e, 0x41, 0x35, 0x2d, 0xc3, 0xe6, 0x86, 0x89, 0x8c, 0x4c, 0xe4, + 0x30, 0x5e, 0x8b, 0x63, 0x8e, 0x1b, 0x08, 0xa2, 0xa8, 0x6c, 0xc9, 0xeb, 0x98, 0x66, 0xf3, 0x49, + 0x9a, 0xc7, 0x7b, 0x61, 0x36, 0xb8, 0x1c, 0xb2, 0x76, 0xd6, 0x14, 0xcf, 0xeb, 0x7b, 0x6e, 0xd3, + 0xf3, 0xbc, 0x77, 0x5e, 0x46, 0xc0, 0x00, 0x66, 0xeb, 0xee, 0xe2, 0xcf, 0xf7, 0x16, 0x6b, 0x57, + 0x52, 0x05, 0x98, 0x94, 0x7f, 0xf6, 0x21, 0x03, 0x20, 0xb2, 0x88, 0xfb, 0x4f, 0x2c, 0x3f, 0x8f, + 0xe9, 0x7b, 0x27, 0x94, 0x14, 0xeb, 0xf7, 0x20, 0x30, 0x00, 0xa1, 0x9f, 0xc0, 0x42, 0x48, 0x75, +}; + +static const uint8_t ac_rsaes_pkcs1_v1_5_example15_prime1[] = { + 0xf1, 0x23, 0xbf, 0xe5, 0x3d, 0xe9, 0x7a, 0x56, 0x9d, 0x91, 0xad, 0xcf, 0x55, 0x6f, 0xa6, 0x25, + 0xad, 0x30, 0xf3, 0xfd, 0x3d, 0x81, 0x1f, 0x9e, 0x91, 0xe6, 0xaf, 0x44, 0xb6, 0xe7, 0x80, 0xcb, + 0x0f, 0x32, 0x78, 0x29, 0xfb, 0x21, 0x19, 0x0a, 0xe2, 0x80, 0x66, 0x46, 0xd7, 0x28, 0xcd, 0x9b, + 0x65, 0x31, 0x13, 0x2b, 0x1e, 0xbf, 0xef, 0x12, 0x72, 0x99, 0x30, 0x60, 0xf1, 0xce, 0x70, 0xb1, + 0x24, 0x39, 0x30, 0x91, 0xee, 0x85, 0x93, 0xb7, 0x27, 0x36, 0x7e, 0xdb, 0xba, 0x00, 0x9e, 0xc5, + 0xbe, 0x17, 0xc4, 0xac, 0xee, 0x12, 0x0c, 0x84, 0x12, 0x67, 0xd4, 0x76, 0x31, 0xa1, 0x6c, 0x36, + 0xa6, 0xd1, 0xc9, 0x99, 0x73, 0xc1, 0xb0, 0xb5, 0xa8, 0x35, 0xbf, 0x39, 0xfe, 0xaf, 0xe8, 0xf6, + 0x42, 0x1f, 0xd9, 0xc2, 0xa9, 0x0b, 0xc2, 0x79, 0x76, 0x65, 0x9e, 0x67, 0xbc, 0x83, 0x12, 0x4d, +}; + +static const uint8_t ac_rsaes_pkcs1_v1_5_example15_prime2[] = { + 0xea, 0x98, 0x39, 0xb7, 0xe3, 0x7e, 0xa8, 0x9b, 0xbd, 0xa2, 0x7e, 0x4c, 0x93, 0x47, 0x1c, 0xb4, + 0xfd, 0x92, 0x18, 0x9a, 0x0a, 0x96, 0xbc, 0xb4, 0xd7, 0x56, 0x93, 0xf1, 0x8a, 0x5c, 0x2f, 0x74, + 0x2a, 0xf9, 0xe3, 0x6f, 0xde, 0x67, 0x9f, 0xbd, 0x9e, 0xae, 0x34, 0x5f, 0xa2, 0x69, 0x52, 0x7b, + 0x69, 0x65, 0x02, 0x1c, 0x4b, 0xdf, 0x54, 0xd6, 0x85, 0xbf, 0x08, 0x96, 0x0c, 0xc9, 0x76, 0xf6, + 0x8d, 0xca, 0x21, 0xce, 0xbf, 0x44, 0xf2, 0x68, 0xa5, 0x9d, 0xab, 0x8d, 0x1a, 0x25, 0xe5, 0x19, + 0xf5, 0x14, 0x7e, 0x1f, 0x45, 0xfe, 0x28, 0x7d, 0x74, 0xcf, 0x72, 0x5b, 0xec, 0x13, 0x26, 0xd3, + 0x42, 0x12, 0xc5, 0x6c, 0xf4, 0xff, 0xfa, 0x20, 0x2f, 0x57, 0xb6, 0x8e, 0xe8, 0xcc, 0xa9, 0x43, + 0xf3, 0xc1, 0x38, 0xc4, 0xcd, 0xe3, 0x3b, 0xdf, 0x2c, 0x94, 0x40, 0xdf, 0x65, 0x32, 0x24, 0x45, +}; + +static const uint8_t ac_rsaes_pkcs1_v1_5_example15_exp1[] = { + 0xca, 0x0c, 0x9b, 0x60, 0xb8, 0xe4, 0xa6, 0x06, 0x67, 0x56, 0xc6, 0x5d, 0x20, 0x88, 0x41, 0x9d, + 0xf6, 0x25, 0x3b, 0x7b, 0x68, 0x8a, 0x85, 0xf4, 0xf6, 0xe9, 0x64, 0xd8, 0x5d, 0xad, 0x52, 0xa4, + 0x52, 0x62, 0x86, 0x7f, 0x1e, 0x96, 0x18, 0x06, 0x9f, 0xcc, 0xd8, 0x65, 0xe9, 0x28, 0x9e, 0x46, + 0xe3, 0x9e, 0x20, 0x22, 0x94, 0x4c, 0x5c, 0x44, 0x87, 0xd3, 0x45, 0xcf, 0x25, 0x2d, 0x46, 0x0d, + 0x97, 0x7d, 0x77, 0xed, 0xfe, 0xfe, 0xdb, 0xcb, 0xae, 0x46, 0xa2, 0x3a, 0xf7, 0xfa, 0x47, 0x0f, + 0x07, 0x7d, 0xa0, 0xe5, 0x09, 0x42, 0x04, 0x4c, 0xb1, 0xa3, 0x60, 0x49, 0x7c, 0xc2, 0x76, 0x0a, + 0xc0, 0xf2, 0xad, 0x4a, 0x2f, 0xcd, 0x0e, 0x84, 0xd7, 0xa1, 0xd9, 0x4d, 0xfd, 0xd2, 0x65, 0x8f, + 0xd9, 0xce, 0x18, 0x47, 0x5c, 0x1f, 0xa7, 0x5e, 0xe0, 0xce, 0xba, 0xd0, 0xcf, 0x0a, 0xc0, 0x4d, +}; + +static const uint8_t ac_rsaes_pkcs1_v1_5_example15_exp2[] = { + 0x52, 0x81, 0x71, 0x23, 0x3c, 0x4e, 0x4a, 0x6c, 0x63, 0xb8, 0x67, 0x64, 0xf5, 0x13, 0x38, 0x84, + 0x6a, 0xfd, 0xdb, 0xcb, 0x29, 0x58, 0x34, 0x4c, 0x01, 0xc4, 0x00, 0x4a, 0x1d, 0xd8, 0x28, 0x14, + 0x5a, 0x1d, 0x02, 0xa1, 0x50, 0x7d, 0xef, 0x4f, 0x58, 0x24, 0x7a, 0x64, 0xfc, 0x10, 0xc0, 0xa2, + 0x88, 0xc1, 0xae, 0x89, 0x57, 0x21, 0xd7, 0x8b, 0x8f, 0x04, 0x4d, 0xb7, 0xc0, 0x0d, 0x86, 0xda, + 0x55, 0xa9, 0xb6, 0x54, 0x29, 0x2e, 0xcd, 0x76, 0x82, 0x70, 0xbe, 0x69, 0xe4, 0xbd, 0x59, 0x22, + 0xd4, 0xef, 0xfd, 0x1f, 0x70, 0x95, 0x5f, 0x96, 0x27, 0xe3, 0xe1, 0x9b, 0x74, 0x9e, 0x93, 0xb4, + 0x0e, 0xf3, 0xdd, 0x1d, 0x61, 0xd9, 0x39, 0x15, 0xe2, 0xb0, 0x9d, 0x93, 0x0b, 0x4b, 0x17, 0x68, + 0xbf, 0xac, 0xc0, 0x13, 0x6f, 0x39, 0xb0, 0xcf, 0xdf, 0xb4, 0xd0, 0x50, 0x01, 0x1e, 0x2e, 0x65, +}; + +static const uint8_t ac_rsaes_pkcs1_v1_5_example15_coeff[] = { + 0xdf, 0x2e, 0xb2, 0x32, 0x2c, 0xc2, 0xda, 0xab, 0xf4, 0xd1, 0x46, 0x55, 0x08, 0xf4, 0x15, 0x21, + 0xcd, 0xa7, 0xce, 0xff, 0x23, 0xeb, 0xe6, 0x1d, 0x00, 0xd4, 0x41, 0xee, 0x72, 0x8d, 0xda, 0x5d, + 0x16, 0xc7, 0xbf, 0x92, 0x0c, 0xd9, 0x5f, 0x34, 0xbe, 0xb4, 0xfe, 0x32, 0xee, 0x81, 0x7e, 0xf3, + 0x36, 0x2e, 0x0b, 0xcd, 0x1d, 0x12, 0x45, 0xf7, 0xb0, 0x77, 0x93, 0xea, 0xa1, 0x90, 0xdc, 0x5a, + 0x37, 0xfd, 0xaf, 0x4c, 0x68, 0xe2, 0xca, 0x13, 0x97, 0x2d, 0x7f, 0x51, 0x48, 0xb7, 0x96, 0xb6, + 0xfb, 0x6d, 0x7a, 0xdd, 0xa0, 0x7b, 0xd2, 0xcd, 0x13, 0xbe, 0x98, 0xce, 0xbe, 0xd1, 0xed, 0xc6, + 0xca, 0x41, 0x2e, 0x39, 0x53, 0x50, 0xc5, 0x9a, 0x1d, 0x84, 0x2b, 0xc4, 0xaa, 0x2f, 0x3c, 0x0b, + 0x24, 0x3f, 0xde, 0x7d, 0xfd, 0x95, 0x35, 0x6f, 0x24, 0x39, 0x25, 0x1a, 0x11, 0x72, 0xc4, 0x5e, +}; + +/* PKCS#1 v1.5 Encrypt Example 15.9 */ +#define ac_rsaes_pkcs1_v1_5_vect15_modulus ac_rsaes_pkcs1_v1_5_example15_modulus +#define ac_rsaes_pkcs1_v1_5_vect15_pub_exp ac_rsaes_pkcs1_v1_5_example15_pub_exp +#define ac_rsaes_pkcs1_v1_5_vect15_priv_exp ac_rsaes_pkcs1_v1_5_example15_priv_exp +#define ac_rsaes_pkcs1_v1_5_vect15_prime1 ac_rsaes_pkcs1_v1_5_example15_prime1 +#define ac_rsaes_pkcs1_v1_5_vect15_prime2 ac_rsaes_pkcs1_v1_5_example15_prime2 +#define ac_rsaes_pkcs1_v1_5_vect15_exp1 ac_rsaes_pkcs1_v1_5_example15_exp1 +#define ac_rsaes_pkcs1_v1_5_vect15_exp2 ac_rsaes_pkcs1_v1_5_example15_exp2 +#define ac_rsaes_pkcs1_v1_5_vect15_coeff ac_rsaes_pkcs1_v1_5_example15_coeff + +/* + * PKCS#1 v1.5 Encryption Example 15.9 + * from ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt + */ +static const uint8_t ac_rsaes_pkcs1_v1_5_vect15_ptx[] = { + 0x9a, 0x13, 0x96, 0x62, 0x2d, 0x06, 0x6c, 0x10, 0x56, 0x08, 0x58, 0xc2, 0xc4, 0xcd, 0x5c, 0x04, + 0x44, 0x9e, 0x2b, 0x95, 0x50, 0xc5, 0xbc, 0x92, 0x93, 0x76, 0x1a, 0x91, 0x04, 0x41, 0x1d, 0xa1, + 0x8a, 0x57, 0xd9, 0xb6, 0xa9, 0x97, 0x33, 0x3c, 0xdb, 0xce, 0x77, 0xe9, 0xfd, 0xbe, 0x6b, 0xb8, + 0x31, +}; + +static const uint8_t ac_rsaes_pkcs1_v1_5_vect15_out[] = { + 0x10, 0x0e, 0xce, 0x63, 0x45, 0x25, 0xd4, 0x67, 0xf6, 0xd4, 0xa6, 0xb6, 0x6e, 0xde, 0x1c, 0xc2, + 0x37, 0xf6, 0x1f, 0xb2, 0xb6, 0x70, 0x23, 0xa8, 0x3d, 0xc4, 0x56, 0xb9, 0x2c, 0xda, 0x18, 0x3e, + 0xd6, 0x62, 0x0f, 0xe5, 0x7d, 0x5a, 0x67, 0x33, 0x2c, 0x77, 0x23, 0x3a, 0xc1, 0xe8, 0x72, 0x5b, + 0x36, 0xf8, 0xe1, 0xb1, 0x08, 0x41, 0x2c, 0xa6, 0xfb, 0x35, 0xdc, 0xd4, 0xd8, 0x16, 0x77, 0xa2, + 0xb3, 0x0d, 0x5e, 0xaf, 0x25, 0xe0, 0xb9, 0x19, 0x1b, 0x38, 0xf7, 0xee, 0xf8, 0x3f, 0x91, 0x21, + 0xa8, 0x08, 0x43, 0x8c, 0x92, 0xab, 0x03, 0xf5, 0x20, 0x80, 0x7b, 0xc9, 0xa8, 0x94, 0x70, 0x5e, + 0xaf, 0x4e, 0xed, 0x06, 0x68, 0x23, 0xa6, 0x7a, 0xa2, 0xa5, 0x59, 0x9c, 0xd9, 0x5e, 0x58, 0xda, + 0x7c, 0x09, 0x48, 0x36, 0xd2, 0xaf, 0xeb, 0xa3, 0x9d, 0xd0, 0x09, 0xa6, 0x4a, 0xde, 0x03, 0x05, + 0x33, 0x76, 0xf0, 0x29, 0x36, 0xcf, 0x3f, 0x56, 0xbf, 0x64, 0xc1, 0xf3, 0xbd, 0xc0, 0x7c, 0x45, + 0xa9, 0x5b, 0x9f, 0xcd, 0x93, 0x96, 0xcd, 0x9a, 0x8d, 0x41, 0xbc, 0xc5, 0x64, 0x24, 0x93, 0x7a, + 0x13, 0x71, 0xb3, 0x84, 0x7c, 0x90, 0x5b, 0x9a, 0xb5, 0x84, 0x02, 0x39, 0x3d, 0x40, 0x46, 0xe4, + 0xa0, 0x15, 0xc1, 0x47, 0x08, 0xf7, 0x4c, 0xe7, 0x79, 0x0e, 0xba, 0x8a, 0xf7, 0x92, 0x07, 0x24, + 0x40, 0xbc, 0xaf, 0xb1, 0x4c, 0x0f, 0x81, 0x08, 0x97, 0x11, 0x87, 0xc8, 0x0f, 0x46, 0x3a, 0x1f, + 0xff, 0x25, 0x86, 0x46, 0xea, 0x16, 0xe5, 0x1c, 0x6e, 0xe3, 0x61, 0xb6, 0x61, 0xa1, 0x4f, 0x07, + 0xcd, 0x4f, 0x5a, 0x82, 0xc7, 0x09, 0xf4, 0x94, 0xf1, 0xdf, 0x0f, 0x80, 0x3b, 0x6f, 0x64, 0xa7, + 0x2f, 0xb9, 0xc4, 0x50, 0xff, 0xe2, 0x68, 0xfc, 0xab, 0x48, 0x7d, 0x4d, 0x63, 0x01, 0x3e, 0x41, +}; + +/* + * PKCS#1 v1.5 Encryption Example 10.1 + * from http://armcryptolib.das-labor.org/trac/browser/testvectors/rsa-pkcs-1v2-1-vec/oaep-vect.txt + */ + +static const uint8_t ac_rsaes_oaep_vect10_modulus[] = { + 0xae, 0x45, 0xed, 0x56, 0x01, 0xce, 0xc6, 0xb8, 0xcc, 0x05, 0xf8, 0x03, 0x93, 0x5c, 0x67, 0x4d, + 0xdb, 0xe0, 0xd7, 0x5c, 0x4c, 0x09, 0xfd, 0x79, 0x51, 0xfc, 0x6b, 0x0c, 0xae, 0xc3, 0x13, 0xa8, + 0xdf, 0x39, 0x97, 0x0c, 0x51, 0x8b, 0xff, 0xba, 0x5e, 0xd6, 0x8f, 0x3f, 0x0d, 0x7f, 0x22, 0xa4, + 0x02, 0x9d, 0x41, 0x3f, 0x1a, 0xe0, 0x7e, 0x4e, 0xbe, 0x9e, 0x41, 0x77, 0xce, 0x23, 0xe7, 0xf5, + 0x40, 0x4b, 0x56, 0x9e, 0x4e, 0xe1, 0xbd, 0xcf, 0x3c, 0x1f, 0xb0, 0x3e, 0xf1, 0x13, 0x80, 0x2d, + 0x4f, 0x85, 0x5e, 0xb9, 0xb5, 0x13, 0x4b, 0x5a, 0x7c, 0x80, 0x85, 0xad, 0xca, 0xe6, 0xfa, 0x2f, + 0xa1, 0x41, 0x7e, 0xc3, 0x76, 0x3b, 0xe1, 0x71, 0xb0, 0xc6, 0x2b, 0x76, 0x0e, 0xde, 0x23, 0xc1, + 0x2a, 0xd9, 0x2b, 0x98, 0x08, 0x84, 0xc6, 0x41, 0xf5, 0xa8, 0xfa, 0xc2, 0x6b, 0xda, 0xd4, 0xa0, + 0x33, 0x81, 0xa2, 0x2f, 0xe1, 0xb7, 0x54, 0x88, 0x50, 0x94, 0xc8, 0x25, 0x06, 0xd4, 0x01, 0x9a, + 0x53, 0x5a, 0x28, 0x6a, 0xfe, 0xb2, 0x71, 0xbb, 0x9b, 0xa5, 0x92, 0xde, 0x18, 0xdc, 0xf6, 0x00, + 0xc2, 0xae, 0xea, 0xe5, 0x6e, 0x02, 0xf7, 0xcf, 0x79, 0xfc, 0x14, 0xcf, 0x3b, 0xdc, 0x7c, 0xd8, + 0x4f, 0xeb, 0xbb, 0xf9, 0x50, 0xca, 0x90, 0x30, 0x4b, 0x22, 0x19, 0xa7, 0xaa, 0x06, 0x3a, 0xef, + 0xa2, 0xc3, 0xc1, 0x98, 0x0e, 0x56, 0x0c, 0xd6, 0x4a, 0xfe, 0x77, 0x95, 0x85, 0xb6, 0x10, 0x76, + 0x57, 0xb9, 0x57, 0x85, 0x7e, 0xfd, 0xe6, 0x01, 0x09, 0x88, 0xab, 0x7d, 0xe4, 0x17, 0xfc, 0x88, + 0xd8, 0xf3, 0x84, 0xc4, 0xe6, 0xe7, 0x2c, 0x3f, 0x94, 0x3e, 0x0c, 0x31, 0xc0, 0xc4, 0xa5, 0xcc, + 0x36, 0xf8, 0x79, 0xd8, 0xa3, 0xac, 0x9d, 0x7d, 0x59, 0x86, 0x0e, 0xaa, 0xda, 0x6b, 0x83, 0xbb, +}; + +static const uint8_t ac_rsaes_oaep_vect10_pub_exp[] = { + 0x01, 0x00, 0x01, +}; + +static const uint8_t ac_rsaes_oaep_vect10_priv_exp[] = { + 0x05, 0x6b, 0x04, 0x21, 0x6f, 0xe5, 0xf3, 0x54, 0xac, 0x77, 0x25, 0x0a, 0x4b, 0x6b, 0x0c, 0x85, + 0x25, 0xa8, 0x5c, 0x59, 0xb0, 0xbd, 0x80, 0xc5, 0x64, 0x50, 0xa2, 0x2d, 0x5f, 0x43, 0x8e, 0x59, + 0x6a, 0x33, 0x3a, 0xa8, 0x75, 0xe2, 0x91, 0xdd, 0x43, 0xf4, 0x8c, 0xb8, 0x8b, 0x9d, 0x5f, 0xc0, + 0xd4, 0x99, 0xf9, 0xfc, 0xd1, 0xc3, 0x97, 0xf9, 0xaf, 0xc0, 0x70, 0xcd, 0x9e, 0x39, 0x8c, 0x8d, + 0x19, 0xe6, 0x1d, 0xb7, 0xc7, 0x41, 0x0a, 0x6b, 0x26, 0x75, 0xdf, 0xbf, 0x5d, 0x34, 0x5b, 0x80, + 0x4d, 0x20, 0x1a, 0xdd, 0x50, 0x2d, 0x5c, 0xe2, 0xdf, 0xcb, 0x09, 0x1c, 0xe9, 0x99, 0x7b, 0xbe, + 0xbe, 0x57, 0x30, 0x6f, 0x38, 0x3e, 0x4d, 0x58, 0x81, 0x03, 0xf0, 0x36, 0xf7, 0xe8, 0x5d, 0x19, + 0x34, 0xd1, 0x52, 0xa3, 0x23, 0xe4, 0xa8, 0xdb, 0x45, 0x1d, 0x6f, 0x4a, 0x5b, 0x1b, 0x0f, 0x10, + 0x2c, 0xc1, 0x50, 0xe0, 0x2f, 0xee, 0xe2, 0xb8, 0x8d, 0xea, 0x4a, 0xd4, 0xc1, 0xba, 0xcc, 0xb2, + 0x4d, 0x84, 0x07, 0x2d, 0x14, 0xe1, 0xd2, 0x4a, 0x67, 0x71, 0xf7, 0x40, 0x8e, 0xe3, 0x05, 0x64, + 0xfb, 0x86, 0xd4, 0x39, 0x3a, 0x34, 0xbc, 0xf0, 0xb7, 0x88, 0x50, 0x1d, 0x19, 0x33, 0x03, 0xf1, + 0x3a, 0x22, 0x84, 0xb0, 0x01, 0xf0, 0xf6, 0x49, 0xea, 0xf7, 0x93, 0x28, 0xd4, 0xac, 0x5c, 0x43, + 0x0a, 0xb4, 0x41, 0x49, 0x20, 0xa9, 0x46, 0x0e, 0xd1, 0xb7, 0xbc, 0x40, 0xec, 0x65, 0x3e, 0x87, + 0x6d, 0x09, 0xab, 0xc5, 0x09, 0xae, 0x45, 0xb5, 0x25, 0x19, 0x01, 0x16, 0xa0, 0xc2, 0x61, 0x01, + 0x84, 0x82, 0x98, 0x50, 0x9c, 0x1c, 0x3b, 0xf3, 0xa4, 0x83, 0xe7, 0x27, 0x40, 0x54, 0xe1, 0x5e, + 0x97, 0x07, 0x50, 0x36, 0xe9, 0x89, 0xf6, 0x09, 0x32, 0x80, 0x7b, 0x52, 0x57, 0x75, 0x1e, 0x79, +}; + +static const uint8_t ac_rsaes_oaep_vect10_prime1[] = { + 0xec, 0xf5, 0xae, 0xcd, 0x1e, 0x55, 0x15, 0xff, 0xfa, 0xcb, 0xd7, 0x5a, 0x28, 0x16, 0xc6, 0xeb, + 0xf4, 0x90, 0x18, 0xcd, 0xfb, 0x46, 0x38, 0xe1, 0x85, 0xd6, 0x6a, 0x73, 0x96, 0xb6, 0xf8, 0x09, + 0x0f, 0x80, 0x18, 0xc7, 0xfd, 0x95, 0xcc, 0x34, 0xb8, 0x57, 0xdc, 0x17, 0xf0, 0xcc, 0x65, 0x16, + 0xbb, 0x13, 0x46, 0xab, 0x4d, 0x58, 0x2c, 0xad, 0xad, 0x7b, 0x41, 0x03, 0x35, 0x23, 0x87, 0xb7, + 0x03, 0x38, 0xd0, 0x84, 0x04, 0x7c, 0x9d, 0x95, 0x39, 0xb6, 0x49, 0x62, 0x04, 0xb3, 0xdd, 0x6e, + 0xa4, 0x42, 0x49, 0x92, 0x07, 0xbe, 0xc0, 0x1f, 0x96, 0x42, 0x87, 0xff, 0x63, 0x36, 0xc3, 0x98, + 0x46, 0x58, 0x33, 0x68, 0x46, 0xf5, 0x6e, 0x46, 0x86, 0x18, 0x81, 0xc1, 0x02, 0x33, 0xd2, 0x17, + 0x6b, 0xf1, 0x5a, 0x5e, 0x96, 0xdd, 0xc7, 0x80, 0xbc, 0x86, 0x8a, 0xa7, 0x7d, 0x3c, 0xe7, 0x69, +}; + +static const uint8_t ac_rsaes_oaep_vect10_prime2[] = { + 0xbc, 0x46, 0xc4, 0x64, 0xfc, 0x6a, 0xc4, 0xca, 0x78, 0x3b, 0x0e, 0xb0, 0x8a, 0x3c, 0x84, 0x1b, + 0x77, 0x2f, 0x7e, 0x9b, 0x2f, 0x28, 0xba, 0xbd, 0x58, 0x8a, 0xe8, 0x85, 0xe1, 0xa0, 0xc6, 0x1e, + 0x48, 0x58, 0xa0, 0xfb, 0x25, 0xac, 0x29, 0x99, 0x90, 0xf3, 0x5b, 0xe8, 0x51, 0x64, 0xc2, 0x59, + 0xba, 0x11, 0x75, 0xcd, 0xd7, 0x19, 0x27, 0x07, 0x13, 0x51, 0x84, 0x99, 0x2b, 0x6c, 0x29, 0xb7, + 0x46, 0xdd, 0x0d, 0x2c, 0xab, 0xe1, 0x42, 0x83, 0x5f, 0x7d, 0x14, 0x8c, 0xc1, 0x61, 0x52, 0x4b, + 0x4a, 0x09, 0x94, 0x6d, 0x48, 0xb8, 0x28, 0x47, 0x3f, 0x1c, 0xe7, 0x6b, 0x6c, 0xb6, 0x88, 0x6c, + 0x34, 0x5c, 0x03, 0xe0, 0x5f, 0x41, 0xd5, 0x1b, 0x5c, 0x3a, 0x90, 0xa3, 0xf2, 0x40, 0x73, 0xc7, + 0xd7, 0x4a, 0x4f, 0xe2, 0x5d, 0x9c, 0xf2, 0x1c, 0x75, 0x96, 0x0f, 0x3f, 0xc3, 0x86, 0x31, 0x83, +}; + +static const uint8_t ac_rsaes_oaep_vect10_exp1[] = { + 0xc7, 0x35, 0x64, 0x57, 0x1d, 0x00, 0xfb, 0x15, 0xd0, 0x8a, 0x3d, 0xe9, 0x95, 0x7a, 0x50, 0x91, + 0x5d, 0x71, 0x26, 0xe9, 0x44, 0x2d, 0xac, 0xf4, 0x2b, 0xc8, 0x2e, 0x86, 0x2e, 0x56, 0x73, 0xff, + 0x6a, 0x00, 0x8e, 0xd4, 0xd2, 0xe3, 0x74, 0x61, 0x7d, 0xf8, 0x9f, 0x17, 0xa1, 0x60, 0xb4, 0x3b, + 0x7f, 0xda, 0x9c, 0xb6, 0xb6, 0xb7, 0x42, 0x18, 0x60, 0x98, 0x15, 0xf7, 0xd4, 0x5c, 0xa2, 0x63, + 0xc1, 0x59, 0xaa, 0x32, 0xd2, 0x72, 0xd1, 0x27, 0xfa, 0xf4, 0xbc, 0x8c, 0xa2, 0xd7, 0x73, 0x78, + 0xe8, 0xae, 0xb1, 0x9b, 0x0a, 0xd7, 0xda, 0x3c, 0xb3, 0xde, 0x0a, 0xe7, 0x31, 0x49, 0x80, 0xf6, + 0x2b, 0x6d, 0x4b, 0x0a, 0x87, 0x5d, 0x1d, 0xf0, 0x3c, 0x1b, 0xae, 0x39, 0xcc, 0xd8, 0x33, 0xef, + 0x6c, 0xd7, 0xe2, 0xd9, 0x52, 0x8b, 0xf0, 0x84, 0xd1, 0xf9, 0x69, 0xe7, 0x94, 0xe9, 0xf6, 0xc1, +}; + +static const uint8_t ac_rsaes_oaep_vect10_exp2[] = { + 0x26, 0x58, 0xb3, 0x7f, 0x6d, 0xf9, 0xc1, 0x03, 0x0b, 0xe1, 0xdb, 0x68, 0x11, 0x7f, 0xa9, 0xd8, + 0x7e, 0x39, 0xea, 0x2b, 0x69, 0x3b, 0x7e, 0x6d, 0x3a, 0x2f, 0x70, 0x94, 0x74, 0x13, 0xee, 0xc6, + 0x14, 0x2e, 0x18, 0xfb, 0x8d, 0xfc, 0xb6, 0xac, 0x54, 0x5d, 0x7c, 0x86, 0xa0, 0xad, 0x48, 0xf8, + 0x45, 0x71, 0x70, 0xf0, 0xef, 0xb2, 0x6b, 0xc4, 0x81, 0x26, 0xc5, 0x3e, 0xfd, 0x1d, 0x16, 0x92, + 0x01, 0x98, 0xdc, 0x2a, 0x11, 0x07, 0xdc, 0x28, 0x2d, 0xb6, 0xa8, 0x0c, 0xd3, 0x06, 0x23, 0x60, + 0xba, 0x3f, 0xa1, 0x3f, 0x70, 0xe4, 0x31, 0x2f, 0xf1, 0xa6, 0xcd, 0x6b, 0x8f, 0xc4, 0xcd, 0x9c, + 0x5c, 0x3d, 0xb1, 0x7c, 0x6d, 0x6a, 0x57, 0x21, 0x2f, 0x73, 0xae, 0x29, 0xf6, 0x19, 0x32, 0x7b, + 0xad, 0x59, 0xb1, 0x53, 0x85, 0x85, 0x85, 0xba, 0x4e, 0x28, 0xb6, 0x0a, 0x62, 0xa4, 0x5e, 0x49, +}; + +static const uint8_t ac_rsaes_oaep_vect10_coeff[] = { + 0x6f, 0x38, 0x52, 0x6b, 0x39, 0x25, 0x08, 0x55, 0x34, 0xef, 0x3e, 0x41, 0x5a, 0x83, 0x6e, 0xde, + 0x8b, 0x86, 0x15, 0x8a, 0x2c, 0x7c, 0xbf, 0xec, 0xcb, 0x0b, 0xd8, 0x34, 0x30, 0x4f, 0xec, 0x68, + 0x3b, 0xa8, 0xd4, 0xf4, 0x79, 0xc4, 0x33, 0xd4, 0x34, 0x16, 0xe6, 0x32, 0x69, 0x62, 0x3c, 0xea, + 0x10, 0x07, 0x76, 0xd8, 0x5a, 0xff, 0x40, 0x1d, 0x3f, 0xff, 0x61, 0x0e, 0xe6, 0x54, 0x11, 0xce, + 0x3b, 0x13, 0x63, 0xd6, 0x3a, 0x97, 0x09, 0xee, 0xde, 0x42, 0x64, 0x7c, 0xea, 0x56, 0x14, 0x93, + 0xd5, 0x45, 0x70, 0xa8, 0x79, 0xc1, 0x86, 0x82, 0xcd, 0x97, 0x71, 0x0b, 0x96, 0x20, 0x5e, 0xc3, + 0x11, 0x17, 0xd7, 0x3b, 0x5f, 0x36, 0x22, 0x3f, 0xad, 0xd6, 0xe8, 0xba, 0x90, 0xdd, 0x7c, 0x0e, + 0xe6, 0x1d, 0x44, 0xe1, 0x63, 0x25, 0x1e, 0x20, 0xc7, 0xf6, 0x6e, 0xb3, 0x05, 0x11, 0x7c, 0xb8, +}; + +static const uint8_t ac_rsaes_oaep_vect10_ptx[] = { + 0x8b, 0xba, 0x6b, 0xf8, 0x2a, 0x6c, 0x0f, 0x86, 0xd5, 0xf1, 0x75, 0x6e, 0x97, 0x95, 0x68, 0x70, + 0xb0, 0x89, 0x53, 0xb0, 0x6b, 0x4e, 0xb2, 0x05, 0xbc, 0x16, 0x94, 0xee, +}; + +static const uint8_t ac_rsaes_oaep_vect10_out[] = { + 0x53, 0xea, 0x5d, 0xc0, 0x8c, 0xd2, 0x60, 0xfb, 0x3b, 0x85, 0x85, 0x67, 0x28, 0x7f, 0xa9, 0x15, + 0x52, 0xc3, 0x0b, 0x2f, 0xeb, 0xfb, 0xa2, 0x13, 0xf0, 0xae, 0x87, 0x70, 0x2d, 0x06, 0x8d, 0x19, + 0xba, 0xb0, 0x7f, 0xe5, 0x74, 0x52, 0x3d, 0xfb, 0x42, 0x13, 0x9d, 0x68, 0xc3, 0xc5, 0xaf, 0xee, + 0xe0, 0xbf, 0xe4, 0xcb, 0x79, 0x69, 0xcb, 0xf3, 0x82, 0xb8, 0x04, 0xd6, 0xe6, 0x13, 0x96, 0x14, + 0x4e, 0x2d, 0x0e, 0x60, 0x74, 0x1f, 0x89, 0x93, 0xc3, 0x01, 0x4b, 0x58, 0xb9, 0xb1, 0x95, 0x7a, + 0x8b, 0xab, 0xcd, 0x23, 0xaf, 0x85, 0x4f, 0x4c, 0x35, 0x6f, 0xb1, 0x66, 0x2a, 0xa7, 0x2b, 0xfc, + 0xc7, 0xe5, 0x86, 0x55, 0x9d, 0xc4, 0x28, 0x0d, 0x16, 0x0c, 0x12, 0x67, 0x85, 0xa7, 0x23, 0xeb, + 0xee, 0xbe, 0xff, 0x71, 0xf1, 0x15, 0x94, 0x44, 0x0a, 0xae, 0xf8, 0x7d, 0x10, 0x79, 0x3a, 0x87, + 0x74, 0xa2, 0x39, 0xd4, 0xa0, 0x4c, 0x87, 0xfe, 0x14, 0x67, 0xb9, 0xda, 0xf8, 0x52, 0x08, 0xec, + 0x6c, 0x72, 0x55, 0x79, 0x4a, 0x96, 0xcc, 0x29, 0x14, 0x2f, 0x9a, 0x8b, 0xd4, 0x18, 0xe3, 0xc1, + 0xfd, 0x67, 0x34, 0x4b, 0x0c, 0xd0, 0x82, 0x9d, 0xf3, 0xb2, 0xbe, 0xc6, 0x02, 0x53, 0x19, 0x62, + 0x93, 0xc6, 0xb3, 0x4d, 0x3f, 0x75, 0xd3, 0x2f, 0x21, 0x3d, 0xd4, 0x5c, 0x62, 0x73, 0xd5, 0x05, + 0xad, 0xf4, 0xcc, 0xed, 0x10, 0x57, 0xcb, 0x75, 0x8f, 0xc2, 0x6a, 0xee, 0xfa, 0x44, 0x12, 0x55, + 0xed, 0x4e, 0x64, 0xc1, 0x99, 0xee, 0x07, 0x5e, 0x7f, 0x16, 0x64, 0x61, 0x82, 0xfd, 0xb4, 0x64, + 0x73, 0x9b, 0x68, 0xab, 0x5d, 0xaf, 0xf0, 0xe6, 0x3e, 0x95, 0x52, 0x01, 0x68, 0x24, 0xf0, 0x54, + 0xbf, 0x4d, 0x3c, 0x8c, 0x90, 0xa9, 0x7b, 0xb6, 0xb6, 0x55, 0x32, 0x84, 0xeb, 0x42, 0x9f, 0xcc, +}; + +/* diffie hellman test data */ +/* p and g testdata generated using the following line: + * for i in {256..2048..64}; do openssl dhparam -C -5 $i; done + */ +static const uint8_t keygen_dh256_p[] = { + 0xB6, 0x73, 0x91, 0xB5, 0xD6, 0xBC, 0x95, 0x73, 0x0D, 0x53, 0x64, 0x13, + 0xB0, 0x51, 0xC6, 0xB4, 0xEB, 0x9D, 0x74, 0x57, 0x8D, 0x65, 0x3A, 0x4B, + 0x7A, 0xB2, 0x93, 0x27, 0xA6, 0xC1, 0xBC, 0xAB, +}; + +static const uint8_t keygen_dh256_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh320_p[] = { + 0x80, 0x72, 0x50, 0x4F, 0x85, 0xD2, 0x32, 0x70, 0xA3, 0x11, 0xF4, 0x46, + 0x01, 0x72, 0xD0, 0x72, 0x96, 0xA5, 0x1B, 0xFA, 0x8F, 0x35, 0x49, 0x75, + 0x04, 0xA5, 0x5A, 0x62, 0xB6, 0x33, 0xD6, 0x3C, 0x46, 0xD1, 0xED, 0xD7, + 0xB1, 0xD4, 0xBA, 0xF3, +}; + +static const uint8_t keygen_dh320_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh384_p[] = { + 0xC2, 0x04, 0xC8, 0x0E, 0xE8, 0x3F, 0x02, 0x1F, 0xDE, 0x0C, 0xAA, 0x2E, + 0x67, 0x13, 0xF4, 0x33, 0x67, 0x82, 0x59, 0xE7, 0x80, 0xE5, 0x42, 0xEA, + 0x2F, 0xC4, 0x71, 0x93, 0xA7, 0x1C, 0x86, 0xEC, 0x8C, 0x39, 0xF8, 0xC7, + 0xF1, 0xE3, 0xE0, 0xEE, 0xC4, 0x55, 0xF5, 0x4F, 0xE7, 0x98, 0xF0, 0x47, +}; + +static const uint8_t keygen_dh384_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh448_p[] = { + 0x91, 0xB9, 0x28, 0x8F, 0x01, 0x62, 0xA1, 0x40, 0x4D, 0x53, 0xC7, 0xD5, + 0xEE, 0x97, 0x40, 0x03, 0x39, 0x39, 0x41, 0x5F, 0x17, 0x0F, 0xA2, 0x78, + 0xBF, 0x3D, 0x6B, 0x33, 0x33, 0x39, 0x3B, 0x57, 0x21, 0x5B, 0xF9, 0xB1, + 0x6C, 0xE3, 0xB8, 0x19, 0xBE, 0x81, 0xBD, 0xC4, 0xFF, 0x4C, 0xFA, 0x48, + 0x63, 0x24, 0x10, 0x33, 0xDE, 0x3A, 0xFD, 0x3B, +}; + +static const uint8_t keygen_dh448_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh512_p[] = { + 0xCF, 0x09, 0xB8, 0xCD, 0x0B, 0xC5, 0x9D, 0xBD, 0x7A, 0x34, 0x50, 0x55, + 0xEC, 0xD4, 0xED, 0x92, 0x9D, 0x63, 0x92, 0xF9, 0x1D, 0x42, 0xF3, 0x64, + 0x04, 0x3D, 0xCC, 0xAA, 0x5F, 0xD1, 0xBB, 0xEA, 0x44, 0x12, 0xFC, 0xF0, + 0xFB, 0xFF, 0x26, 0x57, 0xE3, 0x6E, 0xA8, 0x3F, 0x45, 0x43, 0x11, 0x81, + 0xC6, 0x79, 0xF0, 0x0B, 0x11, 0x23, 0x1D, 0x7B, 0x1E, 0x59, 0xA8, 0xB8, + 0x69, 0x44, 0xA7, 0xE3, +}; + +static const uint8_t keygen_dh512_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh576_p[] = { + 0xEF, 0xA2, 0xD7, 0x81, 0x88, 0xAA, 0xBF, 0x70, 0x03, 0x70, 0xD4, 0x75, + 0xA6, 0x3E, 0x5B, 0xCF, 0x73, 0xDE, 0x7D, 0x45, 0x67, 0x47, 0xB1, 0xCF, + 0xA8, 0x62, 0xA9, 0x13, 0x9F, 0xC3, 0x9B, 0x96, 0xCE, 0xB9, 0x0C, 0x24, + 0xAC, 0xCB, 0xB6, 0x40, 0x30, 0x25, 0x26, 0x4E, 0x9D, 0x50, 0xA7, 0x8F, + 0x09, 0x1C, 0x9B, 0xDE, 0x77, 0x8A, 0xE8, 0xAA, 0xDA, 0xC2, 0x31, 0x08, + 0x55, 0x2C, 0xC1, 0x13, 0x24, 0x6E, 0x5A, 0xE7, 0xA1, 0xBC, 0xE5, 0x5B, +}; + +static const uint8_t keygen_dh576_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh640_p[] = { + 0xED, 0xB6, 0x90, 0x9C, 0x72, 0x5C, 0x63, 0x11, 0x17, 0xA9, 0xB6, 0x0E, + 0x6C, 0x80, 0xA9, 0xF3, 0x15, 0x36, 0x9D, 0x49, 0x02, 0x2B, 0x4F, 0x12, + 0x1A, 0xFD, 0x00, 0xC0, 0x9B, 0x12, 0x10, 0x96, 0x18, 0x55, 0x3F, 0x0C, + 0x75, 0x46, 0x6E, 0xDF, 0x0A, 0x58, 0x8E, 0x1B, 0x4B, 0xFF, 0x24, 0x70, + 0xFC, 0x29, 0xE8, 0x67, 0x8F, 0x0B, 0x72, 0x14, 0x80, 0x6F, 0xE9, 0xCD, + 0x30, 0x3C, 0x16, 0xB9, 0xB0, 0x32, 0xBE, 0x6A, 0x1D, 0x06, 0xEE, 0x6D, + 0x15, 0x44, 0x49, 0x55, 0xA8, 0x08, 0x2D, 0x0F, +}; + +static const uint8_t keygen_dh640_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh704_p[] = { + 0xA6, 0xBF, 0xA1, 0x02, 0x02, 0xA7, 0x7A, 0x6E, 0xFC, 0x48, 0x55, 0x81, + 0x23, 0x3F, 0x08, 0x8E, 0x83, 0xE9, 0x10, 0x92, 0x96, 0x82, 0x5F, 0xB8, + 0x88, 0x28, 0x0C, 0x6A, 0x04, 0x41, 0xEF, 0x4C, 0xCC, 0x2F, 0x16, 0xCD, + 0xA4, 0x2F, 0x24, 0x3B, 0xB6, 0x8A, 0x45, 0x76, 0xB3, 0xFA, 0x23, 0x83, + 0x53, 0xB2, 0x8F, 0x0C, 0xAE, 0xF9, 0xE8, 0xDB, 0x46, 0x5B, 0xBF, 0x7E, + 0xC3, 0x6F, 0x4F, 0xE6, 0xE7, 0x51, 0x75, 0x49, 0xB5, 0x4B, 0xBE, 0x48, + 0x51, 0x64, 0x9F, 0x5D, 0x56, 0xC7, 0x28, 0x9C, 0xC5, 0xBD, 0x0C, 0xD2, + 0x3A, 0x63, 0x49, 0x57, +}; + +static const uint8_t keygen_dh704_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh768_p[] = { + 0xEA, 0x9B, 0x0E, 0xD5, 0xDF, 0xC6, 0x9C, 0x8A, 0x26, 0x29, 0xD4, 0x2A, + 0x94, 0x4F, 0xD5, 0x3E, 0xEA, 0xEC, 0xCD, 0x89, 0xDA, 0x9C, 0x12, 0x52, + 0x94, 0xA7, 0x1A, 0x7D, 0x14, 0x94, 0xB1, 0x89, 0x79, 0xF3, 0x4A, 0xC3, + 0xD6, 0xF5, 0x52, 0xA6, 0x65, 0xC6, 0x0C, 0xD2, 0x2B, 0x16, 0xCB, 0x4F, + 0x69, 0x4C, 0x41, 0x6C, 0xA6, 0xAF, 0xCE, 0xFD, 0x50, 0x0E, 0x8C, 0x9E, + 0xA7, 0x19, 0x46, 0x6E, 0xC2, 0x27, 0xB9, 0xAF, 0x61, 0x4B, 0xDA, 0x3A, + 0x60, 0xBA, 0x6D, 0xCE, 0xBA, 0x39, 0x1C, 0x02, 0xBF, 0x09, 0xF0, 0xF9, + 0x87, 0xBE, 0xA1, 0xDE, 0x4E, 0x34, 0x7B, 0x28, 0x3A, 0xC2, 0x9E, 0x83, +}; + +static const uint8_t keygen_dh768_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh832_p[] = { + 0xB9, 0x0C, 0x79, 0x82, 0x7B, 0x23, 0xB7, 0x2F, 0x5A, 0x7B, 0xB1, 0xB9, + 0x63, 0x30, 0x7C, 0xD4, 0x0B, 0xEB, 0x7B, 0x8A, 0x67, 0x3E, 0x3B, 0x67, + 0xF1, 0x72, 0x90, 0x0E, 0xBF, 0x67, 0xEF, 0xBB, 0x95, 0xC1, 0x47, 0xED, + 0x89, 0x11, 0x79, 0x40, 0x63, 0x02, 0xF0, 0x41, 0x0C, 0xD1, 0x76, 0x15, + 0xAA, 0x24, 0x6A, 0xAE, 0x98, 0xFB, 0x19, 0x1F, 0x43, 0xB9, 0x92, 0xC7, + 0xB6, 0x33, 0xD8, 0x85, 0xBD, 0x06, 0x7D, 0x68, 0x32, 0xEE, 0xDB, 0x41, + 0xEF, 0x7B, 0xBD, 0xB4, 0xFE, 0x53, 0x4F, 0x6C, 0xA8, 0x26, 0xE0, 0x62, + 0x7D, 0x06, 0x06, 0xC5, 0xFB, 0x47, 0xD0, 0x3F, 0x4B, 0xC1, 0x7A, 0xC4, + 0x2A, 0xF3, 0x69, 0xF2, 0xDE, 0x77, 0xCD, 0x03, +}; + +static const uint8_t keygen_dh832_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh896_p[] = { + 0xA8, 0x1A, 0xFB, 0xF4, 0x12, 0xF8, 0x17, 0x16, 0x89, 0x20, 0xAE, 0x6F, + 0x07, 0x55, 0x13, 0xCA, 0x99, 0x66, 0xA3, 0x1F, 0x07, 0xAC, 0x32, 0x5C, + 0xF5, 0xF0, 0x39, 0xA3, 0xDA, 0xF5, 0x55, 0xF9, 0x3C, 0xF3, 0x15, 0xF8, + 0x44, 0xC1, 0x10, 0x6A, 0x3D, 0x2F, 0x97, 0xFD, 0xAC, 0x74, 0x1E, 0xEE, + 0xCF, 0xDD, 0xEE, 0x70, 0x57, 0xBA, 0x4B, 0x41, 0xD6, 0x3F, 0xDD, 0x01, + 0xFB, 0x0C, 0x26, 0xA9, 0x06, 0xCD, 0x1B, 0xA2, 0xD3, 0x3E, 0xAD, 0x2D, + 0x29, 0xFB, 0x79, 0xB8, 0x8E, 0x50, 0xCC, 0xA1, 0x85, 0x37, 0xFA, 0xF1, + 0xBB, 0xB1, 0x5D, 0x3B, 0x51, 0x54, 0x16, 0x4C, 0x98, 0x2B, 0x26, 0xAD, + 0x70, 0x0B, 0x01, 0x87, 0x5C, 0xF1, 0xE8, 0x02, 0xF3, 0x57, 0xA9, 0x40, + 0x5C, 0xC5, 0xE0, 0xFF, +}; + +static const uint8_t keygen_dh896_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh960_p[] = { + 0xD9, 0x31, 0xE0, 0xF3, 0x80, 0xED, 0xBD, 0xEC, 0x35, 0x99, 0xC9, 0x28, + 0xA8, 0x88, 0x3C, 0x84, 0x41, 0x8A, 0x6C, 0xC7, 0x83, 0x09, 0xCE, 0x07, + 0x51, 0x72, 0xBE, 0xE9, 0x21, 0x4F, 0xCB, 0x92, 0xAE, 0xA5, 0xF0, 0x9A, + 0x40, 0x9B, 0x02, 0x1D, 0xA5, 0x5E, 0xAB, 0x17, 0x25, 0x5B, 0x70, 0x0F, + 0xF9, 0x27, 0xEF, 0x49, 0xCD, 0x7F, 0x6E, 0x9A, 0x62, 0x51, 0xE6, 0xEA, + 0x4B, 0x7E, 0xBE, 0xB3, 0x72, 0xFB, 0xAF, 0x98, 0xA1, 0x7D, 0x77, 0x7E, + 0x53, 0xF9, 0xFC, 0x7A, 0xEB, 0xC7, 0xB0, 0x84, 0x2F, 0x70, 0xCC, 0xA2, + 0x34, 0x52, 0x9F, 0xD3, 0x46, 0xE3, 0x32, 0x2F, 0xE0, 0x6F, 0x83, 0x3B, + 0x8B, 0x17, 0x01, 0x0C, 0x1D, 0xEA, 0x04, 0x7D, 0xB1, 0xD4, 0xB2, 0x2D, + 0xC7, 0xD3, 0x2D, 0xE0, 0x47, 0x00, 0x6D, 0xE8, 0x1F, 0xAA, 0x39, 0x67, +}; + +static const uint8_t keygen_dh960_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1024_p[] = { + 0xB9, 0xF5, 0xB6, 0xFF, 0x49, 0xA7, 0x31, 0x3C, 0xD3, 0xAA, 0x42, 0xAE, + 0x3D, 0xA6, 0xD4, 0xC1, 0x92, 0xB0, 0x1C, 0xD5, 0x24, 0x9D, 0x67, 0x04, + 0xFA, 0xED, 0x0B, 0x2D, 0x8B, 0xA1, 0xB8, 0x72, 0x43, 0x48, 0xC2, 0x75, + 0x00, 0x9F, 0x43, 0xD7, 0xF0, 0x8F, 0xD8, 0xCD, 0x1C, 0x64, 0x48, 0x82, + 0x63, 0x52, 0x89, 0x78, 0x43, 0xEF, 0x00, 0xF6, 0x62, 0x04, 0x26, 0xD5, + 0x69, 0x2C, 0x2B, 0x9B, 0x53, 0x72, 0x57, 0xD5, 0x05, 0xA6, 0x53, 0x24, + 0x43, 0x81, 0x49, 0xEC, 0xBB, 0x43, 0x58, 0x66, 0x6A, 0xBD, 0xAC, 0xBA, + 0xD9, 0xC8, 0xC9, 0x95, 0x93, 0xCB, 0x79, 0x89, 0x86, 0x30, 0x0D, 0x45, + 0x3F, 0x89, 0x04, 0xC4, 0xEC, 0x96, 0xBF, 0x4E, 0x8E, 0x88, 0x51, 0xED, + 0xEF, 0x91, 0x8A, 0x03, 0xDC, 0x4E, 0x28, 0x69, 0x46, 0xDA, 0x1B, 0xD4, + 0x7E, 0xC5, 0xEB, 0x95, 0xBC, 0x9D, 0x14, 0x77, +}; + +static const uint8_t keygen_dh1024_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1088_p[] = { + 0xE3, 0x67, 0x7B, 0x2C, 0x68, 0xE3, 0x7C, 0xDB, 0x30, 0x3A, 0xF3, 0x20, + 0x33, 0x02, 0xB5, 0x08, 0x83, 0xC5, 0x8B, 0x07, 0xDD, 0x08, 0x92, 0x82, + 0xD6, 0x2A, 0x2B, 0x7F, 0xC6, 0xF0, 0xBD, 0xB8, 0x01, 0xF8, 0xCF, 0x78, + 0x4F, 0xFE, 0xE2, 0x9D, 0x2F, 0xF4, 0x2D, 0xC5, 0x48, 0xE0, 0xFD, 0x8A, + 0xC2, 0xCF, 0x1B, 0xD9, 0xE1, 0x23, 0xC6, 0xDA, 0xFC, 0x1C, 0x9B, 0xA4, + 0x70, 0x91, 0x1A, 0x6A, 0x35, 0x00, 0x5E, 0x63, 0x14, 0x04, 0xAB, 0x3B, + 0x00, 0xEE, 0x44, 0xE6, 0xAE, 0x49, 0xDB, 0xB7, 0xEF, 0xE1, 0x6E, 0xF9, + 0x88, 0xCC, 0xAB, 0x5E, 0x0A, 0x20, 0x84, 0x09, 0x03, 0xFA, 0xAA, 0x8C, + 0xFE, 0xB8, 0xEA, 0x31, 0x78, 0xD2, 0x92, 0xF3, 0x77, 0xCF, 0xEC, 0xB9, + 0xF8, 0x3C, 0x79, 0x4A, 0x9B, 0xB6, 0xCC, 0xC0, 0x5E, 0xAB, 0x92, 0xE6, + 0x39, 0x74, 0x5E, 0x8D, 0x2B, 0x28, 0x3B, 0x4D, 0x26, 0x6B, 0x2F, 0xF6, + 0xA8, 0xB1, 0x01, 0x53, +}; + +static const uint8_t keygen_dh1088_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1152_p[] = { + 0xCA, 0xD6, 0x34, 0x4F, 0xAE, 0x99, 0x47, 0x51, 0x14, 0x5D, 0xF4, 0xCA, + 0x47, 0xE2, 0xE7, 0x62, 0x7D, 0xB9, 0xC9, 0xE7, 0xF7, 0xEE, 0xD4, 0xF0, + 0x04, 0xC1, 0x93, 0x06, 0xC2, 0xC8, 0x5E, 0x9D, 0xD3, 0x9F, 0x4A, 0x87, + 0xF2, 0x22, 0x5A, 0x72, 0x8D, 0xEB, 0x8B, 0x12, 0x26, 0x82, 0x3A, 0xA7, + 0x6B, 0xE1, 0x55, 0xB0, 0x9F, 0x97, 0x4C, 0xC5, 0xEC, 0x5C, 0x1C, 0x23, + 0xAB, 0x95, 0xDC, 0x17, 0xD5, 0x80, 0x0A, 0xE6, 0x53, 0x9E, 0xD8, 0xC6, + 0xB9, 0x9E, 0xFA, 0x62, 0x60, 0x2A, 0x8D, 0xD5, 0x3D, 0x36, 0x5E, 0x4E, + 0x42, 0x1F, 0xAF, 0x2B, 0x87, 0x0E, 0xC6, 0x44, 0xB7, 0x55, 0x1C, 0x81, + 0x7E, 0x48, 0x96, 0x1B, 0xF9, 0x73, 0x1C, 0x3D, 0x80, 0xDF, 0x43, 0xDB, + 0x93, 0xB6, 0x1E, 0xC1, 0x04, 0x12, 0x9E, 0x33, 0x21, 0xCE, 0xF7, 0x49, + 0x41, 0x7E, 0x97, 0x31, 0xC3, 0x74, 0x1D, 0x95, 0x85, 0x6F, 0x3A, 0xA1, + 0xCF, 0x61, 0xD9, 0xEB, 0x67, 0x67, 0xED, 0x91, 0xDF, 0x23, 0xCD, 0xC3, +}; + +static const uint8_t keygen_dh1152_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1216_p[] = { + 0xB1, 0xFC, 0x4E, 0xF5, 0xDE, 0xC5, 0xDD, 0x33, 0xDD, 0xB2, 0x2E, 0x44, + 0x52, 0xDD, 0x74, 0x2F, 0x1F, 0x61, 0x20, 0x21, 0x72, 0x65, 0xC5, 0xEC, + 0x5A, 0xAA, 0xF1, 0x24, 0xA1, 0xD0, 0xEB, 0x4B, 0x4C, 0x32, 0x8A, 0xDD, + 0x4F, 0x9F, 0xEE, 0xFA, 0x5F, 0x81, 0xD4, 0x18, 0x3D, 0xCD, 0x39, 0x38, + 0xDC, 0x3D, 0x2E, 0x37, 0xEB, 0xFE, 0x73, 0xEF, 0x99, 0x53, 0x54, 0xA6, + 0xAB, 0x25, 0xFE, 0x9A, 0x10, 0xAE, 0x3E, 0xC9, 0x63, 0x45, 0x75, 0xAF, + 0xCA, 0xD9, 0x57, 0xF7, 0x71, 0xE0, 0xBE, 0x0D, 0x90, 0xE9, 0xC5, 0x5A, + 0xC6, 0x2E, 0x3D, 0xDE, 0xE4, 0x8B, 0x38, 0x8E, 0x83, 0x06, 0xA6, 0xE2, + 0x38, 0xA6, 0x88, 0x81, 0xDE, 0x8E, 0xA6, 0x6A, 0xBF, 0xF4, 0x75, 0xFB, + 0xAB, 0xAA, 0x02, 0xEA, 0x0E, 0xCF, 0xCA, 0xEA, 0x45, 0xFE, 0x1C, 0xC2, + 0xF9, 0xBE, 0x26, 0x31, 0xA6, 0x8F, 0xFE, 0x07, 0x9E, 0x79, 0x47, 0x11, + 0xA1, 0x25, 0xA4, 0xE5, 0xFB, 0xEA, 0xE7, 0xC1, 0xFF, 0x12, 0x12, 0x71, + 0x5D, 0xC1, 0x99, 0x44, 0xD1, 0xCE, 0x82, 0xA7, +}; + +static const uint8_t keygen_dh1216_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1280_p[] = { + 0xF0, 0x10, 0x04, 0x04, 0x08, 0x13, 0x79, 0x15, 0x62, 0x5C, 0xFA, 0x2A, + 0x6D, 0xFC, 0x3F, 0x23, 0x4C, 0x47, 0x83, 0x45, 0xE7, 0x6F, 0x64, 0x04, + 0x1A, 0xFD, 0xBF, 0xD2, 0xB9, 0x0A, 0x98, 0x14, 0x16, 0xA4, 0xB5, 0x03, + 0x13, 0xBB, 0xFB, 0x72, 0x1E, 0xF5, 0x23, 0x12, 0xB8, 0x74, 0x49, 0x3F, + 0x84, 0xF3, 0x02, 0x3A, 0x50, 0x6F, 0xB7, 0xC7, 0x6F, 0x37, 0x8F, 0x61, + 0x88, 0x60, 0x7C, 0xF1, 0xE7, 0x1E, 0xED, 0x55, 0xF1, 0xCD, 0x64, 0x93, + 0xA7, 0x12, 0xB7, 0x74, 0x5F, 0x23, 0x20, 0xF7, 0x87, 0xC2, 0x83, 0x2A, + 0x86, 0x0C, 0xF3, 0x4B, 0x88, 0x32, 0xF5, 0xB7, 0x86, 0x2F, 0xBF, 0xEE, + 0xA1, 0x59, 0xC4, 0xDB, 0x0F, 0xEF, 0x06, 0xC8, 0xF2, 0xEE, 0x39, 0xB4, + 0x19, 0x24, 0x8A, 0x2C, 0xE7, 0xF8, 0xA0, 0x34, 0x2A, 0x15, 0xA9, 0x54, + 0x4D, 0x04, 0x1B, 0xC0, 0xC5, 0x15, 0xCF, 0x38, 0x96, 0x83, 0x3E, 0xEE, + 0xD0, 0xFD, 0xBC, 0x62, 0xD9, 0x84, 0xA3, 0x02, 0x6D, 0x2A, 0x7B, 0x4B, + 0x3E, 0xCC, 0xAD, 0xA1, 0xF0, 0xA0, 0x44, 0xDD, 0x7E, 0x4B, 0xBD, 0x75, + 0xAD, 0x8F, 0xF1, 0x57, +}; + +static const uint8_t keygen_dh1280_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1344_p[] = { + 0x8E, 0x0F, 0xCC, 0x61, 0x96, 0xCA, 0xF2, 0x3A, 0x13, 0xD5, 0xF9, 0x2A, + 0xD0, 0xF0, 0x5A, 0x4C, 0x1B, 0xC2, 0xD2, 0xDE, 0xD6, 0x54, 0x53, 0x83, + 0x70, 0x1E, 0x0A, 0x17, 0x6D, 0x4C, 0xBA, 0xCD, 0xEE, 0x32, 0x08, 0x55, + 0xD8, 0xD3, 0x80, 0x81, 0x07, 0x04, 0xF3, 0x19, 0xDD, 0x20, 0x30, 0x6A, + 0x6C, 0x74, 0x25, 0x56, 0xEB, 0xA0, 0x9E, 0x0A, 0x08, 0x94, 0x88, 0xE8, + 0xD2, 0xFD, 0xC3, 0x16, 0x27, 0x51, 0xE2, 0xF8, 0xAE, 0x8B, 0x2B, 0xFF, + 0x2A, 0x75, 0xEC, 0x21, 0xEB, 0xA9, 0xE2, 0x24, 0x8A, 0xAE, 0xF9, 0x7D, + 0x90, 0x8B, 0x31, 0x10, 0x6B, 0x14, 0x97, 0x2D, 0xB2, 0x93, 0x59, 0xFF, + 0x4B, 0x9A, 0x0A, 0x90, 0xA8, 0x0E, 0xDE, 0x19, 0x2B, 0x74, 0xF2, 0xCC, + 0x2D, 0x5B, 0x4F, 0x91, 0xBE, 0x43, 0x86, 0xA2, 0x91, 0xDD, 0x01, 0xDD, + 0x24, 0x75, 0xD8, 0x9F, 0x85, 0x53, 0xC3, 0xDB, 0x08, 0x5F, 0x01, 0x24, + 0xA7, 0x45, 0xAA, 0x6E, 0xB4, 0xFB, 0x05, 0x1C, 0x58, 0x51, 0x3D, 0xFD, + 0x39, 0x57, 0xD4, 0xF9, 0x11, 0x81, 0x60, 0x48, 0xF1, 0xD7, 0x7C, 0xAE, + 0xDE, 0x58, 0x6E, 0x6A, 0x02, 0xC5, 0x51, 0x69, 0x47, 0xF3, 0xAC, 0x47, +}; + +static const uint8_t keygen_dh1344_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1408_p[] = { + 0xE1, 0xE7, 0xA6, 0xF3, 0x5C, 0x06, 0x00, 0x8B, 0x4B, 0x3C, 0x7A, 0xF9, + 0x4D, 0x30, 0x08, 0x73, 0x69, 0xCF, 0x79, 0x6F, 0xAB, 0x66, 0x47, 0x05, + 0x65, 0xA8, 0x4A, 0x5C, 0xA6, 0x5E, 0x3D, 0x46, 0x10, 0x0A, 0x58, 0x3E, + 0x7C, 0x3F, 0x0F, 0x3A, 0xE1, 0xFF, 0x2C, 0x7D, 0xE1, 0x40, 0x05, 0xED, + 0xC3, 0x0B, 0x6C, 0x36, 0x90, 0xDC, 0x10, 0x94, 0x9B, 0xEB, 0xA9, 0x31, + 0xD9, 0x1F, 0x46, 0xBF, 0xC0, 0xF4, 0x49, 0x44, 0x39, 0xF2, 0xE9, 0xB8, + 0x86, 0x52, 0xCB, 0x60, 0xAC, 0xAF, 0x2C, 0x38, 0x9A, 0x63, 0xCE, 0xB7, + 0x30, 0x17, 0x81, 0xA9, 0x1C, 0x3D, 0x73, 0x0D, 0x3F, 0xCE, 0xC8, 0xA6, + 0x95, 0x65, 0x8F, 0x9F, 0x5C, 0xE8, 0xEB, 0x5C, 0x69, 0x59, 0x8B, 0xA5, + 0x1D, 0x74, 0x23, 0x35, 0x3C, 0x35, 0x08, 0x50, 0x53, 0xE5, 0xDB, 0x93, + 0x69, 0x8F, 0x17, 0xF7, 0xA0, 0xBA, 0xED, 0xD6, 0xE9, 0x7C, 0x4F, 0x97, + 0xAB, 0x25, 0x26, 0x39, 0xF9, 0xF3, 0x12, 0x0A, 0xB1, 0xE0, 0x7C, 0xCD, + 0x60, 0x5C, 0x46, 0x2E, 0x22, 0xAB, 0xEF, 0x8D, 0x09, 0xB8, 0x3D, 0xB1, + 0xA6, 0xB0, 0x1C, 0x5D, 0x75, 0x66, 0x02, 0x0E, 0xFD, 0xB9, 0xD6, 0x47, + 0x5F, 0x80, 0xF3, 0xAF, 0xB3, 0x39, 0x7B, 0xF7, +}; + +static const uint8_t keygen_dh1408_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1472_p[] = { + 0x9D, 0x8A, 0x3D, 0x5A, 0xC0, 0x90, 0x55, 0x02, 0x4E, 0x28, 0xB7, 0x8F, + 0x33, 0x91, 0xDC, 0xEB, 0xD2, 0x81, 0x00, 0x16, 0x2D, 0x89, 0x9A, 0x3C, + 0x83, 0xD5, 0xF3, 0x2A, 0x59, 0x5D, 0x63, 0x86, 0xFB, 0xEB, 0xA8, 0xFD, + 0x27, 0x1E, 0x18, 0x9F, 0x3C, 0xF7, 0xEF, 0xAE, 0xDE, 0x6C, 0xA5, 0x30, + 0x16, 0x93, 0xF0, 0x00, 0xB3, 0x36, 0xD2, 0xF6, 0x2C, 0x95, 0xF1, 0x31, + 0x4A, 0x75, 0xA8, 0x4F, 0xF6, 0xA8, 0x0F, 0xE9, 0x0B, 0xB4, 0xAF, 0xEE, + 0xFF, 0x50, 0x6D, 0xE8, 0xFC, 0x3A, 0xCC, 0x04, 0x71, 0x21, 0x74, 0x38, + 0xEB, 0x7E, 0x66, 0x70, 0x85, 0xA7, 0x35, 0x50, 0x07, 0x21, 0x2D, 0x24, + 0x45, 0xCC, 0x00, 0xB1, 0x7F, 0x7A, 0x73, 0x54, 0x9B, 0x96, 0x7B, 0x60, + 0x46, 0xDE, 0x57, 0x4B, 0xE3, 0xF5, 0xEA, 0x0E, 0xFC, 0x7A, 0xC1, 0xFE, + 0x8D, 0x13, 0xD8, 0x2D, 0xAB, 0xDD, 0xA6, 0x61, 0x5C, 0x95, 0xB4, 0x15, + 0x6F, 0x2A, 0x40, 0x6C, 0xB3, 0xC6, 0xC2, 0x1C, 0xC6, 0x74, 0x6F, 0x31, + 0x73, 0x47, 0x94, 0x95, 0x23, 0x8D, 0xCD, 0x4F, 0x4D, 0xA8, 0xF3, 0x67, + 0x5D, 0xDE, 0x83, 0x49, 0x9C, 0xD3, 0xD9, 0xB5, 0x0D, 0xD4, 0x0E, 0xD1, + 0x99, 0xB7, 0x53, 0x2E, 0xE5, 0xFD, 0xB5, 0x75, 0xFD, 0xE6, 0xD6, 0xC6, + 0xA2, 0x43, 0x33, 0x83, +}; + +static const uint8_t keygen_dh1472_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1536_p[] = { + 0xE2, 0x5A, 0x3F, 0x8E, 0xE8, 0x72, 0x92, 0x84, 0x2F, 0xB2, 0xC0, 0x01, + 0x1F, 0xE9, 0x42, 0x0A, 0x0B, 0x1A, 0x71, 0x27, 0x51, 0xD8, 0xB5, 0xD8, + 0x31, 0x7B, 0xEE, 0xEE, 0xAA, 0xA5, 0x67, 0x67, 0x36, 0xAF, 0xAB, 0x55, + 0xB9, 0x07, 0xA7, 0xF7, 0x55, 0xE3, 0x08, 0x52, 0x7C, 0x55, 0xF3, 0x28, + 0x6F, 0x37, 0x84, 0xC7, 0x26, 0x66, 0x2F, 0x84, 0x8C, 0x09, 0xA5, 0x0C, + 0x5A, 0x60, 0x45, 0x7A, 0xDC, 0x11, 0x11, 0xB6, 0xF8, 0x6B, 0x2A, 0x63, + 0x6E, 0x86, 0x00, 0x65, 0x92, 0x8F, 0xE8, 0xB8, 0x4A, 0x2F, 0xDC, 0x62, + 0xE0, 0x2C, 0x1F, 0x95, 0x8F, 0x16, 0x7D, 0xB9, 0xC2, 0xCE, 0x58, 0x9A, + 0x12, 0x55, 0xC2, 0x01, 0xE2, 0xBE, 0xE5, 0xF0, 0x80, 0x04, 0xFD, 0xDD, + 0x95, 0x04, 0x11, 0xCA, 0xE3, 0xAA, 0x9E, 0x3F, 0x4C, 0x9A, 0xE9, 0x8C, + 0x11, 0xD9, 0x1C, 0x3A, 0x22, 0xEF, 0xEC, 0xB0, 0x9D, 0x73, 0x0C, 0xBB, + 0x4E, 0x3F, 0xFC, 0xF4, 0xFF, 0x63, 0x85, 0x7C, 0xE6, 0x5C, 0x22, 0x60, + 0x0A, 0x92, 0x32, 0xEC, 0x7C, 0x6B, 0x01, 0x72, 0x93, 0x42, 0x9D, 0x8D, + 0xC5, 0x78, 0x88, 0x8F, 0xCB, 0xA8, 0x93, 0xD1, 0x8F, 0x67, 0x74, 0x7A, + 0xA2, 0x93, 0x18, 0xDB, 0x84, 0xA5, 0xA6, 0xB9, 0x35, 0x0C, 0xCD, 0x8B, + 0x85, 0x2F, 0xC0, 0xBA, 0x27, 0x3D, 0x9C, 0x55, 0xDA, 0xB8, 0x94, 0x1F, +}; + +static const uint8_t keygen_dh1536_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1600_p[] = { + 0xAC, 0xF5, 0x91, 0x7E, 0xA3, 0x07, 0xD1, 0x24, 0x69, 0x38, 0x4D, 0x1B, + 0x1D, 0x60, 0x81, 0xF5, 0x22, 0x71, 0xE3, 0xEC, 0x17, 0x7B, 0x22, 0x81, + 0x22, 0xC7, 0x55, 0xBC, 0x61, 0x41, 0x03, 0xA5, 0x9D, 0xDC, 0x58, 0x28, + 0x6C, 0xE6, 0xF7, 0x9B, 0x0D, 0x2F, 0xD5, 0x4F, 0x3E, 0x4D, 0x6B, 0x26, + 0x5B, 0x09, 0x09, 0x79, 0x58, 0xC4, 0x39, 0x33, 0x8C, 0x29, 0x9E, 0x9F, + 0x5C, 0x76, 0xA5, 0xC8, 0x99, 0xF8, 0x69, 0xEE, 0x8F, 0xBA, 0x2C, 0xD4, + 0x68, 0x4F, 0xB2, 0xDC, 0xE6, 0xD9, 0x20, 0xE8, 0x02, 0xF2, 0x43, 0x9C, + 0xDD, 0x31, 0x79, 0xBD, 0x39, 0x78, 0x31, 0xC6, 0x03, 0x66, 0x69, 0x05, + 0xD6, 0x1E, 0xFE, 0x11, 0x1D, 0x9E, 0x01, 0xB8, 0xCB, 0xE8, 0xC7, 0x51, + 0xD9, 0xCD, 0x49, 0xEA, 0xD6, 0xC3, 0xC7, 0xF1, 0xC0, 0xA2, 0x6B, 0xD1, + 0x52, 0xD3, 0x80, 0xFD, 0x52, 0x35, 0x5C, 0x3D, 0xD3, 0x97, 0x61, 0x58, + 0x69, 0x1B, 0x4F, 0x9C, 0xF9, 0xC9, 0x34, 0xDA, 0x9B, 0x8B, 0x04, 0x18, + 0x12, 0x2F, 0xF1, 0x22, 0x78, 0x0F, 0xD3, 0xAA, 0x85, 0x06, 0xA9, 0xCA, + 0x9E, 0x80, 0x39, 0x25, 0x12, 0x41, 0xDD, 0x86, 0x58, 0x1F, 0x4D, 0x1F, + 0x9B, 0xDB, 0x63, 0xD0, 0x80, 0x5E, 0x53, 0xAC, 0x86, 0x0C, 0x1E, 0x11, + 0xB1, 0x0D, 0xB6, 0x1F, 0xFE, 0x7C, 0x23, 0x6A, 0x71, 0x47, 0xA5, 0xC2, + 0x20, 0x23, 0x9F, 0x1D, 0xDF, 0xB9, 0x91, 0x4B, +}; + +static const uint8_t keygen_dh1600_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1664_p[] = { + 0xAB, 0xF8, 0x74, 0x92, 0xCE, 0x1A, 0x3F, 0x89, 0xE1, 0xB7, 0x75, 0x5E, + 0x99, 0xBE, 0xFF, 0x73, 0x3E, 0x78, 0x86, 0xB0, 0x5E, 0x2F, 0x5C, 0xA4, + 0xB2, 0xE4, 0x72, 0x2C, 0x59, 0xB6, 0x64, 0x6F, 0x63, 0x72, 0xE3, 0x82, + 0xA4, 0xFB, 0x03, 0x57, 0x40, 0x6D, 0x6B, 0x1E, 0x2B, 0xB9, 0x8C, 0xB0, + 0x19, 0xB0, 0xE8, 0xC3, 0x3D, 0xEC, 0xC2, 0xA0, 0x91, 0x15, 0x02, 0x79, + 0x93, 0x31, 0xE4, 0x3A, 0x17, 0x9D, 0x9F, 0x68, 0xCD, 0x73, 0x28, 0x83, + 0xC3, 0x07, 0x43, 0x15, 0x05, 0x50, 0x9F, 0x78, 0x91, 0x2A, 0x98, 0x35, + 0xA3, 0xE4, 0x84, 0x84, 0x55, 0xDF, 0x32, 0x29, 0x27, 0x91, 0xC8, 0xFF, + 0x8B, 0x7B, 0x4E, 0x1B, 0xA1, 0x02, 0xBA, 0x31, 0x33, 0x79, 0x2E, 0x73, + 0x1D, 0x00, 0x30, 0xF2, 0x1E, 0x83, 0xB4, 0x7B, 0xD1, 0x76, 0xD4, 0x9E, + 0x2E, 0x32, 0xB6, 0xA5, 0x69, 0xB2, 0x28, 0x8E, 0xC4, 0xE3, 0xB0, 0x33, + 0x7E, 0x59, 0x90, 0x92, 0x40, 0x3F, 0x2C, 0x98, 0xC6, 0xEE, 0x26, 0xF1, + 0xE0, 0xE2, 0xB0, 0xA6, 0x50, 0xB0, 0x2E, 0xF1, 0xE3, 0x2D, 0x4F, 0xB5, + 0x58, 0xDA, 0x07, 0xBE, 0x9D, 0x20, 0x7C, 0x10, 0x23, 0x6D, 0x60, 0x96, + 0x11, 0xC9, 0xB4, 0xD4, 0x9C, 0xF0, 0x01, 0x8F, 0x9B, 0xC4, 0x83, 0xC6, + 0x47, 0x53, 0x74, 0xDD, 0x74, 0x01, 0x03, 0x9C, 0x99, 0xA0, 0x5E, 0xE2, + 0xA0, 0x05, 0x6E, 0x66, 0xB0, 0x01, 0xDD, 0x44, 0xFF, 0xA6, 0x65, 0x96, + 0x92, 0x2B, 0x89, 0x57, +}; + +static const uint8_t keygen_dh1664_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1728_p[] = { + 0xED, 0x9F, 0xF6, 0x0C, 0xD6, 0x18, 0x33, 0xE8, 0x26, 0x13, 0xF2, 0x56, + 0xE7, 0x9D, 0x03, 0x45, 0x99, 0xA0, 0x12, 0xB1, 0xBC, 0x45, 0xAD, 0xA7, + 0x14, 0xCC, 0x37, 0x97, 0x4D, 0x21, 0x6D, 0x52, 0x16, 0x6B, 0x20, 0x0B, + 0x8D, 0xA6, 0x43, 0xDF, 0x6C, 0x5C, 0x5A, 0xF2, 0x24, 0xBF, 0x04, 0x03, + 0x2E, 0xF6, 0xFE, 0x45, 0x30, 0x88, 0x2B, 0x07, 0x5C, 0xAA, 0xAE, 0x7E, + 0x33, 0xEF, 0xE6, 0x92, 0xD6, 0xFD, 0x61, 0x5F, 0xEF, 0xAC, 0xFB, 0x64, + 0x8D, 0x41, 0xE7, 0x52, 0xD2, 0x56, 0x74, 0x3A, 0xE5, 0x5E, 0x7E, 0x88, + 0x8D, 0xCD, 0xEA, 0xA8, 0xEF, 0x09, 0x9E, 0xDC, 0xBB, 0xC2, 0x10, 0xA8, + 0xE8, 0x7B, 0x24, 0x1B, 0x28, 0xA7, 0x1C, 0x0C, 0x53, 0xB8, 0xC2, 0xF3, + 0x01, 0x32, 0xBA, 0xE5, 0x8B, 0x6F, 0x3B, 0xB9, 0x36, 0x44, 0x5B, 0x3A, + 0x73, 0x44, 0x8F, 0xDE, 0x99, 0x69, 0x22, 0xE0, 0x2C, 0x45, 0x71, 0xA9, + 0x52, 0x1C, 0xCD, 0x19, 0x02, 0xBD, 0x06, 0xD2, 0x57, 0x45, 0xE3, 0x6C, + 0x96, 0x6D, 0x0B, 0x25, 0x56, 0x4C, 0x40, 0x2E, 0x7E, 0x83, 0xEE, 0xE1, + 0xB2, 0x65, 0x51, 0x04, 0x8D, 0x6A, 0x08, 0x44, 0xF0, 0x80, 0xB1, 0xFE, + 0x13, 0x15, 0x9B, 0x82, 0x65, 0xF0, 0x89, 0xBC, 0x7E, 0x63, 0xF6, 0x08, + 0xD3, 0xBA, 0xA9, 0x66, 0x35, 0x5F, 0x0C, 0xF7, 0xE9, 0x52, 0xA3, 0x4D, + 0x66, 0x01, 0xE7, 0x28, 0xF4, 0xDC, 0xF2, 0x46, 0xBB, 0x02, 0x95, 0x21, + 0x6A, 0x8F, 0x97, 0xA7, 0x3F, 0x06, 0x2E, 0xB2, 0x97, 0xEC, 0x5A, 0xFB, +}; + + +static const uint8_t keygen_dh1728_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1792_p[] = { + 0x9A, 0x87, 0x16, 0x1D, 0x23, 0x55, 0xC7, 0x06, 0x55, 0xD7, 0xB1, 0xB3, + 0x71, 0x66, 0x9A, 0x16, 0x5A, 0xA6, 0x8F, 0x54, 0x50, 0x99, 0xBD, 0x90, + 0x8C, 0x84, 0xB3, 0xBC, 0x02, 0xFE, 0xCB, 0x07, 0x3A, 0x7E, 0x97, 0x12, + 0x32, 0xEC, 0xA0, 0x0B, 0xEA, 0x96, 0x51, 0xB4, 0x50, 0x4E, 0x3A, 0xCB, + 0x27, 0xA9, 0x42, 0x51, 0x49, 0x35, 0x9F, 0x45, 0x6B, 0xDA, 0xE0, 0x6C, + 0x10, 0x80, 0x00, 0x41, 0xC2, 0xFC, 0x91, 0xB6, 0x59, 0xCE, 0x76, 0x7F, + 0x21, 0xC6, 0x10, 0x8A, 0x68, 0x68, 0x54, 0x76, 0xCE, 0x33, 0xA6, 0x37, + 0xCF, 0x80, 0xDF, 0x37, 0x12, 0x77, 0xBA, 0xBF, 0x15, 0x10, 0x22, 0x4A, + 0xA1, 0x9B, 0xA6, 0x6B, 0x8E, 0x14, 0x4F, 0x64, 0xF4, 0x87, 0x64, 0xAA, + 0x6E, 0xBC, 0xB5, 0xB2, 0x96, 0x27, 0xD1, 0x1A, 0x6E, 0x6D, 0x4B, 0xC6, + 0x43, 0x28, 0xE9, 0xFC, 0xA4, 0xCB, 0x61, 0x8F, 0xEA, 0xE8, 0x40, 0xF2, + 0x0A, 0x19, 0xBA, 0x17, 0x49, 0x9A, 0x9F, 0xEF, 0x65, 0xBC, 0x70, 0x85, + 0xDD, 0x98, 0xB9, 0x8B, 0x25, 0x2C, 0xE1, 0x89, 0xC4, 0x60, 0xA0, 0xA9, + 0x7E, 0xFB, 0xEC, 0xBC, 0x4C, 0x1D, 0x25, 0x5D, 0x70, 0x2E, 0x73, 0x29, + 0x22, 0xA7, 0x83, 0x11, 0xC0, 0x64, 0xA9, 0xB6, 0xFA, 0x11, 0xC8, 0xC4, + 0x14, 0x30, 0x64, 0xE4, 0x76, 0xBE, 0x41, 0x62, 0xE6, 0x9F, 0xD6, 0x2A, + 0xEC, 0x60, 0xCF, 0xBD, 0x25, 0x2E, 0x3C, 0x6C, 0x40, 0x16, 0x32, 0x5C, + 0xB5, 0x3D, 0xFB, 0xD7, 0x3C, 0x59, 0x06, 0xBE, 0x37, 0x54, 0x40, 0x90, + 0x3D, 0x51, 0x01, 0x9A, 0x1E, 0x87, 0x05, 0xE3, +}; + +static const uint8_t keygen_dh1792_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1856_p[] = { + 0xA8, 0xD1, 0xC4, 0xCA, 0x89, 0xB5, 0xB3, 0x17, 0xEB, 0x4D, 0xB1, 0x58, + 0x73, 0x28, 0xDD, 0x7F, 0x67, 0x78, 0x13, 0x7D, 0x0D, 0x0E, 0x77, 0x43, + 0xB8, 0xA5, 0xCD, 0x84, 0xD3, 0x29, 0x3F, 0x00, 0xD7, 0xB0, 0x66, 0x95, + 0x52, 0x9D, 0x49, 0xAD, 0x9C, 0xCE, 0x83, 0xB1, 0xDB, 0x86, 0x90, 0x9A, + 0x40, 0xAD, 0x0A, 0xB0, 0x3A, 0x93, 0x33, 0x07, 0xC8, 0x32, 0x4D, 0x75, + 0x1E, 0x7B, 0xDC, 0xD3, 0x23, 0x5C, 0xCB, 0x83, 0x62, 0x79, 0x3A, 0x88, + 0xE8, 0xD0, 0x9B, 0x75, 0x4D, 0xA0, 0x1F, 0x3E, 0x08, 0x61, 0x5D, 0xEF, + 0x7C, 0xF0, 0x4D, 0xF8, 0xDD, 0x95, 0xEC, 0x31, 0xDD, 0x50, 0xA5, 0x4B, + 0xAA, 0x8E, 0xED, 0x45, 0x34, 0xCB, 0x87, 0x09, 0x4F, 0x36, 0xF6, 0xF4, + 0xF7, 0x08, 0x0D, 0xBA, 0xBC, 0x06, 0x22, 0x59, 0x83, 0x93, 0xF6, 0x4B, + 0xBC, 0x35, 0xAD, 0x48, 0x82, 0x40, 0x55, 0x51, 0xBC, 0xF8, 0xE2, 0x9A, + 0x11, 0xF2, 0x08, 0x1E, 0xCA, 0x55, 0x40, 0x36, 0x00, 0xBE, 0x1C, 0xC8, + 0x94, 0x2E, 0x35, 0x7D, 0xB0, 0xA4, 0xCD, 0x1C, 0xC1, 0xFF, 0x58, 0xE1, + 0xBB, 0x31, 0xE9, 0x13, 0x16, 0x7F, 0x43, 0x88, 0xB2, 0x43, 0x62, 0x2A, + 0x79, 0xE3, 0x61, 0xDF, 0xF5, 0xC9, 0x9C, 0x33, 0xDD, 0x93, 0x58, 0xFC, + 0x08, 0x51, 0xE8, 0xA8, 0x30, 0x61, 0x64, 0x83, 0xB3, 0x20, 0xC4, 0x53, + 0x95, 0xD6, 0xB3, 0x74, 0xB5, 0xFA, 0xB1, 0x65, 0xD1, 0xF9, 0xED, 0xB1, + 0x9B, 0x97, 0x86, 0xC6, 0xDE, 0x6E, 0x5F, 0xF4, 0x6A, 0x42, 0xFA, 0x1F, + 0x6E, 0xEA, 0x5B, 0x43, 0x4C, 0xCC, 0x62, 0x76, 0xFE, 0x9B, 0xA0, 0xB9, + 0x7C, 0x50, 0x5E, 0x8B, +}; + +static const uint8_t keygen_dh1856_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1920_p[] = { + 0xC2, 0x68, 0xB1, 0x2E, 0x41, 0xB7, 0xA3, 0xCC, 0xE8, 0x10, 0x48, 0xE8, + 0x80, 0xA5, 0x56, 0x82, 0x3C, 0x05, 0xA3, 0xC4, 0x20, 0xD5, 0xD7, 0x19, + 0x54, 0x60, 0xA4, 0x97, 0x95, 0x09, 0x3D, 0xDF, 0x10, 0xFF, 0x21, 0x0D, + 0x68, 0x19, 0x15, 0x89, 0xD1, 0x44, 0x14, 0x1E, 0xF2, 0xD8, 0xFD, 0x9D, + 0x35, 0x8C, 0xA6, 0x2B, 0x7D, 0x73, 0x9A, 0xEB, 0x86, 0x28, 0x4D, 0x3B, + 0x22, 0xEF, 0x1A, 0x35, 0xB6, 0x95, 0xA2, 0xFF, 0x03, 0x40, 0x49, 0x60, + 0x59, 0xD2, 0x2D, 0xAD, 0x00, 0xEF, 0x6A, 0x5B, 0xFB, 0xA6, 0x16, 0x01, + 0x92, 0x5E, 0x7D, 0x95, 0x2E, 0x18, 0xD5, 0x23, 0x9E, 0x9E, 0x87, 0xF2, + 0x2F, 0xFC, 0xE4, 0xF7, 0xC2, 0x28, 0x44, 0x97, 0xAB, 0xB5, 0xC1, 0xD3, + 0x8A, 0x53, 0xD7, 0xE5, 0x04, 0x78, 0xF2, 0xD9, 0x21, 0xD5, 0x46, 0x17, + 0x8A, 0xFC, 0xDB, 0x57, 0x29, 0xDD, 0x78, 0x5B, 0x05, 0xA9, 0xB0, 0x13, + 0x45, 0x1C, 0x84, 0xEE, 0x46, 0x73, 0x1B, 0x8E, 0x80, 0x45, 0x73, 0x04, + 0xF9, 0x23, 0x96, 0xBA, 0xBD, 0x51, 0x69, 0x81, 0xE4, 0xAE, 0x0D, 0x0A, + 0xC4, 0x93, 0xD9, 0x67, 0x14, 0x92, 0x5A, 0x96, 0x86, 0x9F, 0xCD, 0x6E, + 0x9A, 0x2A, 0x17, 0xA9, 0x1A, 0xDD, 0x00, 0x7C, 0x78, 0xD8, 0x06, 0xC5, + 0xB4, 0xA4, 0xF6, 0xCF, 0x22, 0xCD, 0xCA, 0x0E, 0x27, 0x97, 0xDD, 0x22, + 0x02, 0x31, 0x2B, 0x9C, 0xFF, 0x7E, 0x35, 0x3C, 0xDA, 0xAB, 0x51, 0x68, + 0x5A, 0x81, 0xF3, 0xA5, 0xA9, 0x04, 0xDA, 0x45, 0x07, 0xC6, 0x4A, 0xEF, + 0x5D, 0x0E, 0xC3, 0x41, 0xD6, 0xAC, 0xD0, 0x8D, 0x56, 0xAC, 0xB4, 0x89, + 0x53, 0x41, 0x06, 0x99, 0x83, 0x04, 0xBE, 0x6D, 0x2B, 0x28, 0xEB, 0x47, +}; + +static const uint8_t keygen_dh1920_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh1984_p[] = { + 0xD8, 0xF3, 0xDC, 0x89, 0xE0, 0x6E, 0xD4, 0x07, 0xC3, 0x95, 0xC0, 0x17, + 0x39, 0xCE, 0xF6, 0xD0, 0x8A, 0xD7, 0x85, 0xD3, 0x83, 0x4D, 0xDC, 0x0B, + 0x85, 0x3B, 0xB7, 0x47, 0xEA, 0xDF, 0xE3, 0x34, 0xCA, 0xA9, 0x60, 0x9A, + 0x4F, 0x8E, 0x8B, 0xAE, 0x8A, 0xAF, 0xD3, 0x96, 0x56, 0xFC, 0x1D, 0x37, + 0x9A, 0x96, 0x57, 0x21, 0x32, 0xF0, 0x22, 0xE8, 0x68, 0x8B, 0x73, 0xAE, + 0x1B, 0xAB, 0xFB, 0x79, 0x1B, 0x7E, 0xDC, 0xAD, 0x9D, 0xA2, 0xF3, 0x5E, + 0x11, 0x46, 0x54, 0x4E, 0x88, 0x92, 0x2B, 0x79, 0x3B, 0xBB, 0x14, 0xD8, + 0x3B, 0x0B, 0xB0, 0x55, 0xE5, 0x9A, 0xA9, 0xA0, 0x94, 0x3C, 0x72, 0xE0, + 0x47, 0x58, 0xA5, 0x85, 0xDC, 0x4A, 0x6D, 0x50, 0x98, 0x28, 0x9B, 0xA1, + 0xB2, 0x95, 0xBB, 0x1A, 0x41, 0x05, 0xBC, 0x32, 0x02, 0x72, 0xBB, 0xF7, + 0x1A, 0x48, 0xC3, 0xD9, 0x4F, 0xBD, 0x32, 0xC8, 0x82, 0xAB, 0xCE, 0xDE, + 0x24, 0x6A, 0x0C, 0x92, 0xF8, 0xFB, 0xFF, 0x18, 0x33, 0x48, 0xAC, 0xD7, + 0xA3, 0x12, 0x0D, 0x52, 0x15, 0x3A, 0xA4, 0x6D, 0x85, 0x0A, 0xBF, 0x19, + 0x63, 0x82, 0x3E, 0xB9, 0x52, 0x98, 0xEA, 0xCC, 0x56, 0x66, 0x0F, 0x96, + 0x90, 0x1D, 0x35, 0xD6, 0xE1, 0xF6, 0x2B, 0x5B, 0xF7, 0x75, 0x12, 0xE5, + 0xD9, 0xED, 0x2E, 0x20, 0xA0, 0xF5, 0x68, 0xA8, 0xC9, 0x6E, 0x08, 0xD0, + 0xD2, 0xE7, 0xB6, 0xCB, 0x51, 0xA2, 0x5A, 0x34, 0x0B, 0xF3, 0x13, 0xAF, + 0x5A, 0x46, 0x8B, 0xCB, 0xC9, 0x46, 0x02, 0x15, 0xFE, 0x96, 0x45, 0x25, + 0x7D, 0x76, 0x56, 0x16, 0x8C, 0x97, 0xF3, 0x74, 0xFC, 0x2F, 0x5D, 0xFA, + 0xCD, 0x62, 0x23, 0x02, 0xF8, 0x19, 0x94, 0xEE, 0xE6, 0x18, 0x09, 0xDE, + 0x64, 0xB4, 0x3A, 0xDC, 0x0A, 0x5E, 0x26, 0x83, +}; + +static const uint8_t keygen_dh1984_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh2048_p[] = { + 0x8F, 0x3E, 0xC1, 0x36, 0xCA, 0x60, 0xCE, 0xD1, 0xC5, 0xFD, 0x22, 0x05, + 0xD6, 0x94, 0x38, 0x20, 0x4F, 0xE1, 0xAF, 0xBC, 0xA6, 0x82, 0xBD, 0x71, + 0xFD, 0xD6, 0xC2, 0x61, 0xE8, 0xC1, 0xBD, 0xA9, 0x5E, 0xFD, 0x02, 0x51, + 0xB6, 0x1F, 0x38, 0x30, 0x44, 0x76, 0x94, 0xB3, 0x26, 0x79, 0x35, 0xC4, + 0xDF, 0x51, 0x80, 0xAF, 0x0D, 0x81, 0xCC, 0xA2, 0x33, 0xD1, 0x1E, 0x77, + 0xB8, 0x06, 0xD7, 0xE5, 0x83, 0x34, 0x04, 0xF2, 0x96, 0x24, 0x37, 0xFE, + 0xBC, 0x20, 0x9C, 0x66, 0x4C, 0xEB, 0x4F, 0xFD, 0x1F, 0x99, 0x56, 0x40, + 0xD9, 0xE8, 0x6B, 0x2A, 0x8D, 0x6B, 0x56, 0xB2, 0xB4, 0x6D, 0x83, 0x47, + 0x4C, 0x18, 0x53, 0x8B, 0xB1, 0xA3, 0x51, 0xC2, 0x07, 0xA3, 0x36, 0x43, + 0x4B, 0x94, 0x10, 0xFD, 0x24, 0xA3, 0x77, 0x74, 0x77, 0xFA, 0x98, 0x4B, + 0x43, 0x0B, 0xB6, 0xEC, 0x7F, 0x5C, 0x7E, 0xBA, 0xB7, 0xC7, 0xAA, 0x72, + 0x11, 0x9F, 0x73, 0x14, 0x45, 0x03, 0x7A, 0x4E, 0xE5, 0xE7, 0x5C, 0x64, + 0xB8, 0x66, 0x66, 0xCE, 0xEE, 0xF8, 0xFF, 0x61, 0x0F, 0x5D, 0x4E, 0xF6, + 0xED, 0xB1, 0xE5, 0x2F, 0x52, 0xAC, 0x2B, 0x8F, 0x34, 0x0D, 0x13, 0xF6, + 0x4A, 0x3A, 0x6C, 0x56, 0xB3, 0x3C, 0x52, 0xA8, 0xB9, 0xBC, 0x27, 0xCA, + 0x3B, 0xFB, 0x6E, 0xE7, 0x52, 0xFB, 0xB0, 0x2B, 0x4F, 0xC4, 0xBD, 0x24, + 0x36, 0xE4, 0x71, 0x07, 0x74, 0x69, 0x5F, 0xE0, 0xB8, 0x59, 0x5F, 0x74, + 0x2F, 0xCC, 0x03, 0xB0, 0x6D, 0x90, 0xD8, 0xD3, 0x7C, 0x5A, 0x31, 0x46, + 0x5C, 0x7D, 0x1C, 0xC8, 0x0D, 0x18, 0x80, 0x8E, 0x5A, 0xA8, 0x5E, 0x4D, + 0x11, 0x2B, 0x76, 0xAC, 0x1E, 0x00, 0x51, 0x80, 0xE3, 0xED, 0x7A, 0xC0, + 0x4F, 0x80, 0xFA, 0x5F, 0xD5, 0xD7, 0x4F, 0xA7, 0x14, 0xE1, 0x60, 0x3C, + 0x95, 0x77, 0xCA, 0x3B, +}; + +static const uint8_t keygen_dh2048_g[] = { + 0x05, +}; + +static const uint8_t keygen_dh2048_subprime_p[] = { + 0x8F, 0x3E, 0xC1, 0x36, 0xCA, 0x60, 0xCE, 0xD1, 0xC5, 0xFD, 0x22, 0x05, + 0xD6, 0x94, 0x38, 0x20, 0x4F, 0xE1, 0xAF, 0xBC, 0xA6, 0x82, 0xBD, 0x71, + 0xFD, 0xD6, 0xC2, 0x61, 0xE8, 0xC1, 0xBD, 0xA9, 0x5E, 0xFD, 0x02, 0x51, + 0xB6, 0x1F, 0x38, 0x30, 0x44, 0x76, 0x94, 0xB3, 0x26, 0x79, 0x35, 0xC4, + 0xDF, 0x51, 0x80, 0xAF, 0x0D, 0x81, 0xCC, 0xA2, 0x33, 0xD1, 0x1E, 0x77, + 0xB8, 0x06, 0xD7, 0xE5, 0x83, 0x34, 0x04, 0xF2, 0x96, 0x24, 0x37, 0xFE, + 0xBC, 0x20, 0x9C, 0x66, 0x4C, 0xEB, 0x4F, 0xFD, 0x1F, 0x99, 0x56, 0x40, + 0xD9, 0xE8, 0x6B, 0x2A, 0x8D, 0x6B, 0x56, 0xB2, 0xB4, 0x6D, 0x83, 0x47, + 0x4C, 0x18, 0x53, 0x8B, 0xB1, 0xA3, 0x51, 0xC2, 0x07, 0xA3, 0x36, 0x43, + 0x4B, 0x94, 0x10, 0xFD, 0x24, 0xA3, 0x77, 0x74, 0x77, 0xFA, 0x98, 0x4B, + 0x43, 0x0B, 0xB6, 0xEC, 0x7F, 0x5C, 0x7E, 0xBA, 0xB7, 0xC7, 0xAA, 0x72, + 0x11, 0x9F, 0x73, 0x14, 0x45, 0x03, 0x7A, 0x4E, 0xE5, 0xE7, 0x5C, 0x64, + 0xB8, 0x66, 0x66, 0xCE, 0xEE, 0xF8, 0xFF, 0x61, 0x0F, 0x5D, 0x4E, 0xF6, + 0xED, 0xB1, 0xE5, 0x2F, 0x52, 0xAC, 0x2B, 0x8F, 0x34, 0x0D, 0x13, 0xF6, + 0x4A, 0x3A, 0x6C, 0x56, 0xB3, 0x3C, 0x52, 0xA8, 0xB9, 0xBC, 0x27, 0xCA, + 0x3B, 0xFB, 0x6E, 0xE7, 0x52, 0xFB, 0xB0, 0x2B, 0x4F, 0xC4, 0xBD, 0x24, + 0x36, 0xE4, 0x71, 0x07, 0x74, 0x69, 0x5F, 0xE0, 0xB8, 0x59, 0x5F, 0x74, + 0x2F, 0xCC, 0x03, 0xB0, 0x6D, 0x90, 0xD8, 0xD3, 0x7C, 0x5A, 0x31, 0x46, + 0x5C, 0x7D, 0x1C, 0xC8, 0x0D, 0x18, 0x80, 0x8E, 0x5A, 0xA8, 0x5E, 0x4D, + 0x11, 0x2B, 0x76, 0xAC, 0x1E, 0x00, 0x51, 0x80, 0xE3, 0xED, 0x7A, 0xC0, + 0x4F, 0x80, 0xFA, 0x5F, 0xD5, 0xD7, 0x4F, 0xA7, 0x14, 0xE1, 0x60, 0x3C, + 0x95, 0x77, 0xCA, 0x3B, +}; + +static const uint8_t keygen_dh2048_subprime_g[] = { + 0x05, +}; +static const uint32_t keygen_dh256_private_bits; + +static const uint32_t keygen_dh320_private_bits = 256; + +static const uint32_t keygen_dh384_private_bits; + +static const uint32_t keygen_dh448_private_bits = 256; + +static const uint32_t keygen_dh512_private_bits; + +static const uint32_t keygen_dh576_private_bits = 288; + +static const uint32_t keygen_dh640_private_bits; + +static const uint32_t keygen_dh704_private_bits = 352; + +static const uint32_t keygen_dh768_private_bits; + +static const uint32_t keygen_dh832_private_bits = 416; + +static const uint32_t keygen_dh896_private_bits; + +static const uint32_t keygen_dh960_private_bits = 480; + +static const uint32_t keygen_dh1024_private_bits; + +static const uint32_t keygen_dh1088_private_bits = 544; + +static const uint32_t keygen_dh1152_private_bits; + +static const uint32_t keygen_dh1216_private_bits = 608; + +static const uint32_t keygen_dh1280_private_bits; + +static const uint32_t keygen_dh1344_private_bits = 672; + +static const uint32_t keygen_dh1408_private_bits; + +static const uint32_t keygen_dh1472_private_bits = 736; + +static const uint32_t keygen_dh1536_private_bits; + +static const uint32_t keygen_dh1600_private_bits = 800; + +static const uint32_t keygen_dh1664_private_bits; + +static const uint32_t keygen_dh1728_private_bits = 864; + +static const uint32_t keygen_dh1792_private_bits; + +static const uint32_t keygen_dh1856_private_bits = 928; + +static const uint32_t keygen_dh1920_private_bits; + +static const uint32_t keygen_dh1984_private_bits = 992; + +static const uint32_t keygen_dh2048_private_bits; + +static const uint32_t keygen_dh2048_subprime_private_bits; + +static const uint8_t keygen_dh2048_subprime_subprime[] = { + 0x01, 0x01, 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 +}; + +/* + * Test data from 186-3dsatestvectors.zip KeyPair.rsp + * http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3dsatestvectors.zip + */ +/* [mod = L=1024, N=160] */ +static const uint8_t keygen_dsa_test1_p[] = { + 0xd3, 0x83, 0x11, 0xe2, 0xcd, 0x38, 0x8c, 0x3e, 0xd6, 0x98, 0xe8, 0x2f, + 0xdf, 0x88, 0xeb, 0x92, 0xb5, 0xa9, 0xa4, 0x83, 0xdc, 0x88, 0x00, 0x5d, + 0x4b, 0x72, 0x5e, 0xf3, 0x41, 0xea, 0xbb, 0x47, 0xcf, 0x8a, 0x7a, 0x8a, + 0x41, 0xe7, 0x92, 0xa1, 0x56, 0xb7, 0xce, 0x97, 0x20, 0x6c, 0x4f, 0x9c, + 0x5c, 0xe6, 0xfc, 0x5a, 0xe7, 0x91, 0x21, 0x02, 0xb6, 0xb5, 0x02, 0xe5, + 0x90, 0x50, 0xb5, 0xb2, 0x1c, 0xe2, 0x63, 0xdd, 0xdb, 0x20, 0x44, 0xb6, + 0x52, 0x23, 0x6f, 0x4d, 0x42, 0xab, 0x4b, 0x5d, 0x6a, 0xa7, 0x31, 0x89, + 0xce, 0xf1, 0xac, 0xe7, 0x78, 0xd7, 0x84, 0x5a, 0x5c, 0x1c, 0x1c, 0x71, + 0x47, 0x12, 0x31, 0x88, 0xf8, 0xdc, 0x55, 0x10, 0x54, 0xee, 0x16, 0x2b, + 0x63, 0x4d, 0x60, 0xf0, 0x97, 0xf7, 0x19, 0x07, 0x66, 0x40, 0xe2, 0x09, + 0x80, 0xa0, 0x09, 0x31, 0x13, 0xa8, 0xbd, 0x73 +}; + +static const uint8_t keygen_dsa_test1_q[] = { + 0x96, 0xc5, 0x39, 0x0a, 0x8b, 0x61, 0x2c, 0x0e, 0x42, 0x2b, 0xb2, 0xb0, + 0xea, 0x19, 0x4a, 0x3e, 0xc9, 0x35, 0xa2, 0x81 +}; + +static const uint8_t keygen_dsa_test1_g[] = { + 0x06, 0xb7, 0x86, 0x1a, 0xbb, 0xd3, 0x5c, 0xc8, 0x9e, 0x79, 0xc5, 0x2f, + 0x68, 0xd2, 0x08, 0x75, 0x38, 0x9b, 0x12, 0x73, 0x61, 0xca, 0x66, 0x82, + 0x21, 0x38, 0xce, 0x49, 0x91, 0xd2, 0xb8, 0x62, 0x25, 0x9d, 0x6b, 0x45, + 0x48, 0xa6, 0x49, 0x5b, 0x19, 0x5a, 0xa0, 0xe0, 0xb6, 0x13, 0x7c, 0xa3, + 0x7e, 0xb2, 0x3b, 0x94, 0x07, 0x4d, 0x3c, 0x3d, 0x30, 0x00, 0x42, 0xbd, + 0xf1, 0x57, 0x62, 0x81, 0x2b, 0x63, 0x33, 0xef, 0x7b, 0x07, 0xce, 0xba, + 0x78, 0x60, 0x76, 0x10, 0xfc, 0xc9, 0xee, 0x68, 0x49, 0x1d, 0xbc, 0x1e, + 0x34, 0xcd, 0x12, 0x61, 0x54, 0x74, 0xe5, 0x2b, 0x18, 0xbc, 0x93, 0x4f, + 0xb0, 0x0c, 0x61, 0xd3, 0x9e, 0x7d, 0xa8, 0x90, 0x22, 0x91, 0xc4, 0x43, + 0x4a, 0x4e, 0x22, 0x24, 0xc3, 0xf4, 0xfd, 0x9f, 0x93, 0xcd, 0x6f, 0x4f, + 0x17, 0xfc, 0x07, 0x63, 0x41, 0xa7, 0xe7, 0xd9 +}; + +/* for i in {512..1024..64}; do openssl dsaparam -C $i; done */ +static const uint8_t keygen_dsa512_p[] = { + 0xC8, 0x6B, 0xB7, 0x91, 0xD6, 0x63, 0xCE, 0xC0, 0xC6, 0xB8, 0xAC, 0x5B, + 0xEB, 0xA7, 0xEF, 0x17, 0xBE, 0x1A, 0x1A, 0x36, 0x6B, 0x38, 0x40, 0x0E, + 0x69, 0x13, 0x32, 0xD4, 0x4B, 0xBE, 0x00, 0xB5, 0x29, 0x7F, 0x6B, 0x87, + 0xAA, 0x1D, 0x98, 0x37, 0xD2, 0xAC, 0x62, 0x26, 0xD7, 0xFD, 0xE1, 0xC9, + 0x13, 0x4F, 0x2A, 0xF2, 0x82, 0xEC, 0xA8, 0x83, 0x6F, 0x29, 0xD3, 0xF5, + 0x16, 0xB9, 0x13, 0xCD, +}; + +static const uint8_t keygen_dsa512_q[] = { + 0x8D, 0xF9, 0x8B, 0x8A, 0xDA, 0x3B, 0x0B, 0x1C, 0xFA, 0x1C, 0xA7, 0xE8, + 0x9A, 0xA2, 0xD7, 0xC3, 0x2D, 0xD5, 0x9D, 0x1B, +}; + +static const uint8_t keygen_dsa512_g[] = { + 0xB3, 0xE2, 0xFD, 0x38, 0xE0, 0x9A, 0x21, 0x64, 0x8F, 0x6D, 0x7E, 0x4F, + 0xC2, 0x24, 0x18, 0x88, 0xEC, 0xA4, 0xCB, 0xB0, 0x5F, 0x43, 0xD8, 0x2B, + 0x5B, 0xDE, 0x01, 0xB4, 0xD2, 0x24, 0x1F, 0x80, 0xE7, 0xFC, 0xF3, 0x15, + 0xFA, 0x0C, 0x5B, 0x6F, 0x81, 0x55, 0x8C, 0x80, 0x36, 0xFB, 0x4D, 0xB5, + 0x8C, 0x5A, 0x26, 0xBE, 0xFB, 0x78, 0xEA, 0x62, 0x6A, 0x9D, 0x5E, 0xD0, + 0x21, 0x0C, 0xD9, 0x4E, +}; + +static const uint8_t keygen_dsa576_p[] = { + 0xF7, 0x85, 0x23, 0x2C, 0x2C, 0x86, 0xD4, 0x2B, 0xE5, 0x09, 0xAB, 0x60, + 0xD6, 0x79, 0x05, 0x13, 0x75, 0x78, 0x1E, 0xAE, 0xEB, 0x5F, 0xBA, 0xFA, + 0x6E, 0x05, 0xE7, 0xB3, 0x8D, 0x33, 0x4B, 0xE5, 0xB5, 0xAA, 0xD4, 0xE6, + 0xA3, 0x9B, 0xA2, 0xF5, 0x7B, 0xF6, 0x32, 0xE6, 0x31, 0x6F, 0x34, 0x46, + 0x16, 0xEA, 0xD8, 0x94, 0x79, 0xD7, 0x69, 0x23, 0xA4, 0x04, 0xE2, 0x25, + 0xBB, 0x6D, 0xCC, 0x6E, 0x99, 0xB7, 0x90, 0x90, 0x89, 0xB9, 0x88, 0x19, +}; + +static const uint8_t keygen_dsa576_q[] = { + 0xF0, 0xD8, 0x71, 0x31, 0xB5, 0x01, 0xC1, 0x6B, 0x09, 0xCE, 0x7D, 0x2F, + 0x82, 0x48, 0xB0, 0x21, 0x9C, 0xD6, 0xB5, 0xB1, +}; + +static const uint8_t keygen_dsa576_g[] = { + 0x33, 0x45, 0xB8, 0x9A, 0x17, 0x4B, 0xBF, 0xD3, 0xB2, 0xBA, 0xD2, 0xE4, + 0xAC, 0x54, 0xA0, 0x9B, 0x5F, 0x5D, 0x95, 0x88, 0x9C, 0x0C, 0x59, 0xCE, + 0x40, 0x0C, 0x05, 0xFD, 0xC4, 0x9D, 0x22, 0x27, 0xDA, 0xA6, 0xD1, 0x10, + 0x61, 0x46, 0x31, 0x5C, 0x7D, 0x4E, 0xF6, 0x01, 0x38, 0x9A, 0x7E, 0x72, + 0x4E, 0x7A, 0x07, 0xFB, 0x6D, 0x20, 0x9D, 0x59, 0xC6, 0x33, 0x6A, 0x64, + 0xBF, 0x14, 0x30, 0x4E, 0x0C, 0x64, 0x9D, 0x11, 0xCF, 0x64, 0xCE, 0x29, +}; + +static const uint8_t keygen_dsa640_p[] = { + 0x88, 0x8C, 0x58, 0x99, 0xF4, 0x78, 0xEA, 0x31, 0x56, 0xB7, 0x2C, 0x70, + 0xDC, 0x09, 0x5D, 0xB9, 0x13, 0x16, 0xCE, 0xDF, 0xFD, 0x8C, 0x4E, 0xF8, + 0x32, 0x59, 0x00, 0x58, 0xD6, 0x44, 0x4F, 0x95, 0xF7, 0x85, 0x14, 0xC3, + 0x10, 0x5A, 0xA2, 0x44, 0x2F, 0xA2, 0xC9, 0xB4, 0x88, 0x89, 0xA1, 0xAE, + 0x0E, 0x82, 0xE1, 0xC1, 0x45, 0x09, 0x98, 0xF7, 0xCB, 0xF2, 0xD8, 0xA0, + 0x6E, 0x32, 0x02, 0xE4, 0x0E, 0x7A, 0x43, 0x3A, 0xE1, 0x04, 0x4C, 0xC5, + 0x78, 0x0E, 0x02, 0x27, 0xC4, 0xD0, 0xCA, 0x29, +}; + +static const uint8_t keygen_dsa640_q[] = { + 0xD7, 0x63, 0x4F, 0x3E, 0x6D, 0x52, 0x93, 0x69, 0xFA, 0xFF, 0xDE, 0x0D, + 0x57, 0x3F, 0x24, 0xBB, 0x01, 0xF8, 0x01, 0xAD, +}; + +static const uint8_t keygen_dsa640_g[] = { + 0x76, 0xCB, 0x07, 0xB9, 0xE9, 0x3F, 0x3C, 0xA5, 0x18, 0x43, 0x83, 0xE6, + 0xBC, 0x42, 0x09, 0xD9, 0xC5, 0x1C, 0x56, 0x57, 0x0B, 0x5B, 0x46, 0x65, + 0x00, 0x67, 0xCA, 0x33, 0xC0, 0xA6, 0x37, 0xEA, 0x89, 0xAE, 0xDF, 0x1D, + 0x79, 0x96, 0xC7, 0x0C, 0xD2, 0xAC, 0xD3, 0x2C, 0x46, 0xC2, 0xA0, 0x9D, + 0x4B, 0x06, 0xB5, 0xDF, 0xAE, 0x73, 0xEB, 0x9A, 0x6A, 0x54, 0x39, 0x2C, + 0xB1, 0x98, 0xAD, 0x44, 0xF3, 0x29, 0xC9, 0xC5, 0x75, 0xF1, 0x3C, 0xD8, + 0x3B, 0xA1, 0x85, 0x29, 0x38, 0xB9, 0x17, 0xA5, +}; + +static const uint8_t keygen_dsa704_p[] = { + 0xDA, 0xEA, 0x9B, 0x6B, 0x35, 0x06, 0x2E, 0x7E, 0x71, 0xB2, 0x11, 0xD0, + 0x37, 0x84, 0x88, 0xC0, 0x50, 0x94, 0x73, 0x78, 0xA8, 0x9C, 0xBD, 0x8C, + 0xB1, 0x0A, 0xD5, 0x89, 0x52, 0x39, 0xBF, 0x41, 0xDC, 0xB9, 0xE5, 0x16, + 0x1A, 0x86, 0xD5, 0xCF, 0xD6, 0x26, 0x84, 0x95, 0xE9, 0x0D, 0xCD, 0x98, + 0x21, 0x6B, 0x3C, 0xFE, 0x6D, 0x2D, 0x42, 0x1A, 0x3F, 0xE0, 0xFF, 0x07, + 0x41, 0x82, 0x30, 0x15, 0x17, 0xF3, 0x0F, 0x7B, 0xA0, 0xD3, 0x46, 0xFA, + 0x1F, 0x1E, 0xEC, 0xBD, 0x26, 0xCE, 0x4C, 0xE3, 0xBD, 0x73, 0xA3, 0xA6, + 0xA0, 0x12, 0xE1, 0xFD, +}; + +static const uint8_t keygen_dsa704_q[] = { + 0xCE, 0xB3, 0x2E, 0x41, 0xEB, 0xFD, 0x22, 0x2A, 0xCE, 0x9A, 0xAF, 0x24, + 0xE3, 0x02, 0x50, 0xDE, 0x47, 0xBC, 0x4C, 0x1F, +}; + +static const uint8_t keygen_dsa704_g[] = { + 0x08, 0x83, 0x72, 0x6D, 0x0A, 0x8F, 0x19, 0x61, 0xE4, 0x62, 0x40, 0x29, + 0x66, 0x6B, 0xDE, 0xBD, 0xAB, 0xE3, 0x5B, 0x58, 0x3F, 0xF5, 0xEA, 0xDE, + 0x8E, 0x7A, 0x34, 0xAF, 0x1C, 0x99, 0x03, 0x1A, 0x51, 0x17, 0xFC, 0xE0, + 0xA3, 0x22, 0x43, 0x63, 0xB6, 0x7E, 0x29, 0x4B, 0x23, 0x6C, 0xD1, 0xDE, + 0x59, 0xEC, 0x1D, 0x67, 0x94, 0xDD, 0x2E, 0x88, 0x86, 0xD3, 0xD6, 0x68, + 0x58, 0x36, 0x48, 0xF8, 0xEF, 0x38, 0x3F, 0xF5, 0x87, 0x96, 0x38, 0xD3, + 0x48, 0x50, 0x1F, 0xA3, 0x4A, 0xCA, 0xD7, 0x4D, 0xC3, 0x84, 0x83, 0xB1, + 0x8A, 0x95, 0xE0, 0xB3, +}; + +static const uint8_t keygen_dsa768_p[] = { + 0xF0, 0xB1, 0x93, 0xFD, 0x53, 0x98, 0x23, 0x43, 0xFB, 0x04, 0xB1, 0x31, + 0x80, 0x3D, 0xD3, 0x95, 0x56, 0x51, 0xCC, 0x32, 0xA4, 0x51, 0x00, 0x8A, + 0x80, 0xB6, 0x87, 0x70, 0xD7, 0x77, 0x8D, 0xA6, 0xC2, 0xB5, 0x85, 0xE1, + 0xE0, 0x9E, 0x11, 0x28, 0x72, 0xE9, 0x45, 0x5B, 0x4D, 0xC9, 0xDC, 0x46, + 0x64, 0x2F, 0x44, 0xD8, 0x24, 0xE3, 0x9B, 0xCC, 0xF9, 0x66, 0x31, 0x9C, + 0x40, 0x64, 0xED, 0xC5, 0x48, 0x30, 0x84, 0x0C, 0xF9, 0x1F, 0xBC, 0x75, + 0xD8, 0x8C, 0x53, 0x30, 0x25, 0xB6, 0xBD, 0xDA, 0xBE, 0xBC, 0xBA, 0x86, + 0xB3, 0x7D, 0x27, 0x74, 0x9D, 0x68, 0xEA, 0xB8, 0xE0, 0x09, 0x3A, 0x7F, +}; + +static const uint8_t keygen_dsa768_q[] = { + 0xC9, 0x8C, 0x79, 0x7B, 0x98, 0xB5, 0xFD, 0x80, 0x5D, 0x4B, 0x26, 0x30, + 0x42, 0x63, 0xDE, 0x37, 0xAB, 0x4B, 0xB7, 0xAF, +}; + +static const uint8_t keygen_dsa768_g[] = { + 0xD4, 0xE8, 0xF1, 0xB9, 0x6D, 0x40, 0x26, 0x19, 0x72, 0x39, 0x5C, 0x6F, + 0x68, 0x4C, 0x8C, 0x18, 0xD8, 0x49, 0x3C, 0xB6, 0x5D, 0x72, 0xE3, 0xF4, + 0x89, 0x24, 0x69, 0xC8, 0x76, 0x83, 0x38, 0xA2, 0x23, 0xF5, 0xB3, 0xD5, + 0xCB, 0x0F, 0xC4, 0xFE, 0x45, 0x65, 0x2F, 0x2C, 0x3D, 0x32, 0x02, 0x28, + 0xE5, 0xCA, 0x34, 0xEC, 0x1A, 0xBB, 0x82, 0x93, 0x2A, 0xD9, 0x64, 0x1E, + 0xC5, 0x91, 0x34, 0x60, 0xF2, 0xE2, 0x2D, 0x64, 0x4E, 0x46, 0xAA, 0x00, + 0x6F, 0x26, 0xD8, 0x98, 0x97, 0xBF, 0xCC, 0xF1, 0x1B, 0x4A, 0x8A, 0x7D, + 0x39, 0xA4, 0xA4, 0x23, 0x82, 0x64, 0x78, 0x40, 0xED, 0x4C, 0x96, 0xB9, +}; + +static const uint8_t keygen_dsa832_p[] = { + 0x93, 0x47, 0x85, 0x69, 0x79, 0xF2, 0xAA, 0xC2, 0x83, 0xA4, 0x08, 0x2F, + 0x3C, 0xE5, 0x4D, 0x3B, 0xFF, 0x4D, 0xC5, 0xF4, 0x03, 0x20, 0xFA, 0x15, + 0xA8, 0x27, 0x80, 0x55, 0x29, 0x57, 0x60, 0x0B, 0x75, 0x01, 0x7B, 0x65, + 0xCE, 0x4D, 0x7C, 0xF6, 0x7C, 0x4F, 0x1D, 0xC3, 0x67, 0xF2, 0xC1, 0x64, + 0x38, 0x49, 0x54, 0x60, 0x57, 0x05, 0xEB, 0x31, 0xFA, 0x7B, 0x50, 0xA1, + 0x0F, 0xCB, 0xC4, 0x4E, 0xDF, 0x92, 0x5A, 0x8B, 0x11, 0xBA, 0x6B, 0x7E, + 0x7A, 0xB4, 0x80, 0xD0, 0x9A, 0xE2, 0x88, 0x7D, 0x83, 0xA6, 0x81, 0x81, + 0x71, 0xD0, 0x06, 0xDE, 0xCC, 0xA4, 0xB9, 0x0A, 0x6B, 0x81, 0x31, 0x28, + 0x1D, 0xEF, 0x5F, 0x99, 0xDE, 0xEC, 0xDA, 0x4D, +}; + +static const uint8_t keygen_dsa832_q[] = { + 0xF8, 0xF5, 0xAF, 0x31, 0x0D, 0xBE, 0x6F, 0x4B, 0x79, 0x87, 0xA2, 0x98, + 0xED, 0xF1, 0x2A, 0x93, 0x3D, 0x12, 0x5D, 0x25, +}; + +static const uint8_t keygen_dsa832_g[] = { + 0x11, 0x21, 0xBC, 0x83, 0x7A, 0xD9, 0x5F, 0x0E, 0xA2, 0xF7, 0x96, 0xB7, + 0x6A, 0xDD, 0xAE, 0xBA, 0x11, 0x26, 0x58, 0xF6, 0xB1, 0xCF, 0x94, 0x35, + 0x3B, 0xFB, 0x9C, 0x9B, 0x16, 0xB8, 0x58, 0xBA, 0x2F, 0x5C, 0xE5, 0x18, + 0xE1, 0x29, 0xA6, 0xA3, 0x1C, 0x0C, 0xA5, 0xC7, 0xAE, 0xE8, 0x31, 0x26, + 0x8C, 0xCD, 0xA5, 0x69, 0xB2, 0x74, 0x31, 0x15, 0xCE, 0x82, 0xCD, 0x32, + 0xF7, 0xC8, 0x90, 0x60, 0x96, 0x61, 0x07, 0x60, 0x63, 0x6B, 0x48, 0x03, + 0xCD, 0x1F, 0x58, 0x7D, 0x8E, 0xAF, 0x26, 0x16, 0x3B, 0xC6, 0xA6, 0x03, + 0xB4, 0xE1, 0x3E, 0xBE, 0x5B, 0xC9, 0xD3, 0xBD, 0xB6, 0x31, 0xC9, 0x34, + 0x2C, 0x2B, 0x08, 0x3C, 0xE0, 0x1C, 0x1E, 0x01, +}; + +static const uint8_t keygen_dsa896_p[] = { + 0xCA, 0x16, 0xD2, 0xB2, 0x7C, 0xC5, 0x25, 0x99, 0x3A, 0xCC, 0xCB, 0x3F, + 0x72, 0xAE, 0xD4, 0xA0, 0x1E, 0xE0, 0x19, 0x6A, 0x8A, 0xC2, 0xFC, 0xD5, + 0xB2, 0xCC, 0xD1, 0x6F, 0xA3, 0x95, 0x30, 0xEC, 0x2B, 0x4A, 0x46, 0x6C, + 0x72, 0xC3, 0x31, 0xFD, 0x94, 0x00, 0x55, 0xE7, 0x03, 0xC3, 0xDE, 0xD7, + 0xE3, 0xF8, 0xAF, 0x32, 0x0A, 0x29, 0x32, 0xC5, 0x97, 0x93, 0x2A, 0xE6, + 0xC6, 0x82, 0x49, 0x5C, 0x76, 0xB3, 0xCB, 0x47, 0xD7, 0xFF, 0xEA, 0xE5, + 0x47, 0x87, 0x08, 0x6C, 0xEA, 0x6D, 0x1A, 0xF6, 0x47, 0xBA, 0xE3, 0x94, + 0xE9, 0xFE, 0xF6, 0x06, 0xA1, 0x99, 0xDC, 0xCB, 0x3D, 0x7A, 0x06, 0x31, + 0xAC, 0x25, 0xD3, 0x3C, 0x35, 0xAD, 0x36, 0x8D, 0x25, 0x41, 0xE9, 0x21, + 0xD1, 0xF9, 0xC3, 0xC9, +}; + +static const uint8_t keygen_dsa896_q[] = { + 0xAE, 0x42, 0x0A, 0x1D, 0x76, 0xA9, 0xFB, 0xF1, 0xCB, 0x2D, 0x73, 0x35, + 0x3F, 0x98, 0x63, 0x34, 0xE1, 0xCD, 0x3C, 0xCF, +}; + +static const uint8_t keygen_dsa896_g[] = { + 0x12, 0xD0, 0x15, 0x32, 0x0B, 0x7D, 0xE3, 0xD0, 0x36, 0x51, 0x79, 0x3E, + 0xB4, 0x4E, 0xE2, 0x1E, 0x5E, 0x3E, 0x43, 0x4C, 0x5D, 0x49, 0x9D, 0xD4, + 0xA3, 0xE3, 0xC8, 0x1F, 0x46, 0xA2, 0xCE, 0x95, 0xF9, 0x8D, 0xFC, 0xFD, + 0x50, 0x48, 0xBF, 0xB5, 0x25, 0xB6, 0xFD, 0xF9, 0xF1, 0x97, 0xD5, 0x82, + 0xEE, 0xE7, 0xDF, 0xC6, 0xDD, 0x09, 0x96, 0x15, 0xC0, 0x95, 0x60, 0xF4, + 0x53, 0xF6, 0x19, 0xA4, 0x84, 0x53, 0xE4, 0x87, 0xB6, 0x0C, 0x6C, 0x01, + 0x31, 0x72, 0x56, 0xA4, 0x2E, 0x25, 0xFC, 0x46, 0xB0, 0x47, 0xF3, 0x5A, + 0x90, 0x69, 0xAC, 0x64, 0x02, 0xCB, 0x1F, 0x5F, 0x10, 0x70, 0x2B, 0x71, + 0xF7, 0x9B, 0x70, 0x22, 0x7F, 0x05, 0xEB, 0xCB, 0x6D, 0x66, 0xDE, 0xFC, + 0xED, 0x51, 0xC2, 0x4D, +}; + +static const uint8_t keygen_dsa960_p[] = { + 0xCA, 0x86, 0x31, 0x0C, 0x62, 0xC7, 0x25, 0x2F, 0xAA, 0x8D, 0xA5, 0x51, + 0x97, 0x81, 0xB8, 0xC5, 0xFD, 0xDB, 0x47, 0xC4, 0x8E, 0xDF, 0x06, 0xAA, + 0x76, 0xAD, 0x47, 0xDD, 0x56, 0x6C, 0x97, 0xEB, 0x8C, 0xEC, 0x59, 0x79, + 0x1B, 0xBF, 0x96, 0x80, 0x50, 0x72, 0x8E, 0x2F, 0x34, 0x71, 0x5B, 0x03, + 0x2D, 0xB0, 0x31, 0x37, 0x8C, 0xC4, 0x62, 0x99, 0x9D, 0xC2, 0xDF, 0x68, + 0x35, 0xD5, 0x3F, 0xC1, 0x4B, 0xC4, 0x2F, 0xFA, 0xBD, 0x7E, 0xA5, 0x20, + 0x8F, 0xB9, 0x5F, 0x98, 0xA9, 0x1B, 0xAF, 0x8A, 0xF8, 0x29, 0xEB, 0x44, + 0xB6, 0x50, 0x96, 0xE2, 0xB4, 0x3D, 0x3C, 0xE6, 0x8B, 0xD5, 0x15, 0x39, + 0x4F, 0xF4, 0xC3, 0x32, 0xD3, 0xE6, 0x36, 0x0D, 0x23, 0xFF, 0x76, 0x15, + 0x05, 0xC1, 0xDF, 0xC2, 0x82, 0xCE, 0xDD, 0x60, 0x05, 0x92, 0x56, 0xE5, +}; + +static const uint8_t keygen_dsa960_q[] = { + 0xCE, 0x0A, 0x68, 0xA4, 0xAC, 0x5E, 0x8E, 0x4C, 0xA6, 0x8A, 0xAB, 0xA9, + 0x39, 0xC7, 0xB4, 0x10, 0xCC, 0xF6, 0x1E, 0x2F, +}; + +static const uint8_t keygen_dsa960_g[] = { + 0x8A, 0x50, 0x28, 0x45, 0x69, 0x0E, 0x55, 0xB8, 0x86, 0xB5, 0xCB, 0xBC, + 0x49, 0x8D, 0x73, 0x79, 0xE3, 0x26, 0x4E, 0x90, 0x71, 0xF2, 0xBB, 0x50, + 0x18, 0xF8, 0x6D, 0x14, 0x8F, 0xCA, 0x20, 0xF7, 0x02, 0x31, 0x71, 0x8A, + 0x7E, 0xF0, 0xFE, 0x9C, 0xAD, 0x05, 0x5E, 0x11, 0xB3, 0x40, 0x66, 0xE1, + 0x2B, 0x0D, 0x84, 0x15, 0x18, 0x65, 0x00, 0xFA, 0x0D, 0x8A, 0x87, 0xC9, + 0xBF, 0x4A, 0x5C, 0x53, 0x29, 0xEB, 0x44, 0xCA, 0xAE, 0x86, 0x50, 0x3B, + 0xBB, 0x73, 0x06, 0x83, 0x72, 0x77, 0x17, 0xDB, 0x6E, 0x14, 0xAD, 0xCE, + 0xD2, 0x51, 0xE6, 0x1F, 0xA2, 0x64, 0xE4, 0x5F, 0x35, 0x7D, 0x7A, 0xBE, + 0x55, 0x9B, 0xB6, 0x0F, 0x3C, 0xA1, 0xD2, 0x45, 0xDD, 0xF8, 0xC4, 0x03, + 0x45, 0xAA, 0x12, 0xE4, 0x90, 0x8C, 0xAC, 0x04, 0x45, 0x74, 0x11, 0x28, +}; + +static const uint8_t keygen_dsa1024_p[] = { + 0xAF, 0xA6, 0x9C, 0x37, 0x47, 0xD4, 0x65, 0xA6, 0xB1, 0x8D, 0xAC, 0x2E, + 0xAB, 0xD5, 0x36, 0xCC, 0x83, 0x47, 0xDD, 0xB6, 0x12, 0xCC, 0x93, 0xA5, + 0xBF, 0x7B, 0x24, 0xE7, 0x4A, 0xED, 0xEC, 0x63, 0x9E, 0x0B, 0x2D, 0xF8, + 0xB3, 0x6B, 0xBB, 0xF9, 0x40, 0x8D, 0x56, 0x26, 0x60, 0xD0, 0xDD, 0x03, + 0xF8, 0xC3, 0x82, 0x00, 0x2C, 0x27, 0x82, 0x5E, 0x30, 0x8B, 0x9D, 0xF1, + 0xF7, 0xB2, 0x61, 0x01, 0x31, 0x30, 0xF3, 0x05, 0x2F, 0xF4, 0xB7, 0x1C, + 0x1C, 0x3C, 0xB0, 0x2D, 0x2F, 0x1F, 0xE6, 0x2E, 0x21, 0x81, 0x0D, 0xFD, + 0x66, 0x36, 0x90, 0x39, 0x4D, 0xA0, 0xCF, 0xFA, 0xDD, 0xF7, 0xD5, 0xE4, + 0x09, 0xAA, 0x45, 0xDB, 0xE1, 0x55, 0x39, 0xD9, 0xF7, 0xDF, 0x34, 0x67, + 0xBF, 0x95, 0x9B, 0xF2, 0x4A, 0x15, 0x42, 0x6F, 0x32, 0x1F, 0xDE, 0xA6, + 0xFE, 0x18, 0x46, 0x6B, 0x8C, 0x4E, 0x01, 0x7F, +}; + +static const uint8_t keygen_dsa1024_q[] = { + 0xCC, 0x18, 0x69, 0xCE, 0x9E, 0x92, 0xE7, 0xCD, 0xBF, 0x94, 0xB5, 0xAD, + 0x83, 0x5A, 0x56, 0xD6, 0x4E, 0xC4, 0xF7, 0xED, +}; + +static const uint8_t keygen_dsa1024_g[] = { + 0x14, 0x1D, 0x91, 0xAB, 0x8F, 0xFF, 0xFB, 0x2D, 0xD3, 0x2A, 0x43, 0xB5, + 0x01, 0x40, 0xA4, 0xC7, 0x48, 0x0E, 0xE0, 0x10, 0xA9, 0xF7, 0x8B, 0x7E, + 0x45, 0x90, 0xE0, 0x17, 0xC1, 0xB4, 0xE9, 0xBA, 0xC0, 0x04, 0xEF, 0x0F, + 0xD6, 0x07, 0x78, 0x05, 0x25, 0xCF, 0x9D, 0x39, 0x66, 0x59, 0x53, 0xF8, + 0xCE, 0x1C, 0x61, 0x1B, 0x7F, 0x95, 0x9B, 0xD5, 0xB6, 0xF9, 0xC7, 0xE3, + 0xB8, 0x00, 0x78, 0x50, 0xE3, 0x4C, 0x76, 0xF8, 0x0E, 0x96, 0x11, 0xDB, + 0x28, 0x53, 0xA5, 0xBB, 0x22, 0xC5, 0x71, 0x97, 0x09, 0xBC, 0xEE, 0x55, + 0x9B, 0x6B, 0x22, 0x64, 0xE4, 0x49, 0x2C, 0xCD, 0x9E, 0xA5, 0x86, 0xF0, + 0x3F, 0x08, 0xCD, 0x88, 0x07, 0xF6, 0x6E, 0x3F, 0x8E, 0x99, 0x31, 0xBA, + 0x1A, 0xB9, 0x8E, 0xEC, 0xA3, 0x13, 0xC2, 0x85, 0xA5, 0xDC, 0xA4, 0xF0, + 0x1F, 0xB2, 0xC8, 0xD5, 0x19, 0x79, 0xCA, 0x6A, +}; + +/* derive key test data, taken from GP test specifikation */ +static const uint8_t derive_key_dh_prime[] = { + 0xe0, 0x01, 0xe8, 0x96, 0x7d, 0xb4, 0x93, 0x53, 0xe1, 0x6f, 0x8e, 0x89, + 0x22, 0x0c, 0xce, 0xfc, 0x5c, 0x5f, 0x12, 0xe3, 0xdf, 0xf8, 0xf1, 0xd1, + 0x49, 0x90, 0x12, 0xe6, 0xef, 0x53, 0xe3, 0x1f, 0x02, 0xea, 0xcc, 0x5a, + 0xdd, 0xf3, 0x37, 0x89, 0x35, 0xc9, 0x5b, 0x21, 0xea, 0x3d, 0x6f, 0x1c, + 0xd7, 0xce, 0x63, 0x75, 0x52, 0xec, 0x38, 0x6c, 0x0e, 0x34, 0xf7, 0x36, + 0xad, 0x95, 0x17, 0xef, 0xfe, 0x5e, 0x4d, 0xa7, 0xa8, 0x6a, 0xf9, 0x0e, + 0x2c, 0x22, 0x8f, 0xe4, 0xb9, 0xe6, 0xd8, 0xf8, 0xf0, 0x2d, 0x20, 0xaf, + 0x78, 0xab, 0xb6, 0x92, 0xac, 0xbc, 0x4b, 0x23, 0xfa, 0xf2, 0xc5, 0xcc, + 0xd4, 0x9a, 0x0c, 0x9a, 0x8b, 0xcd, 0x91, 0xac, 0x0c, 0x55, 0x92, 0x01, + 0xe6, 0xc2, 0xfd, 0x1f, 0x47, 0xc2, 0xcb, 0x2a, 0x88, 0xa8, 0x3c, 0x21, + 0x0f, 0xc0, 0x54, 0xdb, 0x29, 0x2d, 0xbc, 0x45 +}; + +static const uint8_t derive_key_dh_base[] = { + 0x1c, 0xe0, 0xf6, 0x69, 0x26, 0x46, 0x11, 0x97, 0xef, 0x45, 0xc4, 0x65, + 0x8b, 0x83, 0xb8, 0xab +}; + +static const uint8_t derive_key_dh_public_value[] = { + 0xbb, 0xe9, 0x18, 0xdd, 0x4b, 0x2b, 0x94, 0x1b, 0x10, 0x0e, 0x88, 0x35, + 0x28, 0x68, 0xfc, 0x62, 0x04, 0x38, 0xa6, 0xdb, 0x32, 0xa6, 0x9e, 0xee, + 0x6c, 0x6f, 0x45, 0x1c, 0xa3, 0xa6, 0xd5, 0x37, 0x77, 0x75, 0x5b, 0xc1, + 0x37, 0x0a, 0xce, 0xfe, 0x2b, 0x8f, 0x13, 0xa9, 0x14, 0x2c, 0x5b, 0x44, + 0x15, 0x78, 0x86, 0x30, 0xd6, 0x95, 0xb1, 0x92, 0x20, 0x63, 0xa3, 0xcf, + 0x9d, 0xef, 0x65, 0x61, 0x27, 0x4d, 0x24, 0x01, 0xe7, 0xa1, 0x45, 0xf2, + 0xd8, 0xb9, 0x3a, 0x45, 0x17, 0xf4, 0x19, 0xd0, 0x5e, 0xf8, 0xcb, 0x35, + 0x59, 0x37, 0x9d, 0x04, 0x20, 0xa3, 0xbf, 0x02, 0xad, 0xfe, 0xa8, 0x60, + 0xb2, 0xc3, 0xee, 0x85, 0x58, 0x90, 0xf3, 0xb5, 0x57, 0x2b, 0xb4, 0xef, + 0xd7, 0x8f, 0x37, 0x68, 0x78, 0x7c, 0x71, 0x52, 0x9d, 0x5e, 0x0a, 0x61, + 0x4f, 0x09, 0x89, 0x92, 0x39, 0xf7, 0x4b, 0x01 +}; + +static const uint8_t derive_key_dh_private_value[] = { + 0x53, 0x8d, 0x3d, 0x64, 0x27, 0x4a, 0x40, 0x05, 0x9b, 0x9c, 0x26, 0xe9, + 0x13, 0xe6, 0x91, 0x53, 0x23, 0x7b, 0x55, 0x83 +}; + +static const uint8_t derive_key_dh_public_value_2[] = { + 0xa3, 0xf5, 0x7d, 0xbe, 0x9e, 0x2f, 0x0a, 0xda, 0xa9, 0x4e, 0x4e, 0x6a, + 0xf0, 0xe0, 0x71, 0x47, 0x0e, 0x2e, 0x41, 0x2e, 0xde, 0x73, 0x2a, 0x62, + 0x14, 0xc3, 0x7c, 0x26, 0xd4, 0xe9, 0x9a, 0x54, 0xba, 0x3d, 0xe7, 0x49, + 0x85, 0x95, 0x0e, 0xe9, 0x14, 0xb2, 0x90, 0x22, 0x91, 0xdc, 0xff, 0x61, + 0xb2, 0xfc, 0xd1, 0xd0, 0x1b, 0x11, 0x14, 0xb6, 0x02, 0x64, 0x2b, 0x26, + 0x5d, 0x88, 0xea, 0x8d, 0xbb, 0xe2, 0x07, 0x0b, 0x48, 0xfb, 0x01, 0x53, + 0x55, 0x1e, 0x59, 0x51, 0x36, 0xf2, 0xf9, 0xd1, 0x97, 0xfb, 0x66, 0x12, + 0x84, 0x5d, 0xed, 0xb8, 0x9b, 0x2d, 0x3e, 0x2b, 0x8c, 0xeb, 0x2a, 0x72, + 0x40, 0x9d, 0x55, 0x4c, 0xed, 0xeb, 0x55, 0x02, 0xff, 0x8c, 0xb0, 0x2e, + 0x03, 0x65, 0x3f, 0x41, 0xb1, 0xac, 0xa3, 0x30, 0x6b, 0xff, 0x6d, 0xf4, + 0x6d, 0xe6, 0xe1, 0x0f, 0x86, 0x7c, 0x43, 0x64 +}; + +static const uint8_t derive_key_dh_shared_secret[] = { + 0x4e, 0x6a, 0xcf, 0xfd, 0x7d, 0x14, 0x27, 0x65, 0xeb, 0xf4, 0xc7, 0x12, + 0x41, 0x4f, 0xe4, 0xb6, 0xab, 0x95, 0x7f, 0x4c, 0xb4, 0x66, 0xb4, 0x66, + 0x01, 0x28, 0x9b, 0xb8, 0x20, 0x60, 0x42, 0x82, 0x72, 0x84, 0x2e, 0xe2, + 0x8f, 0x11, 0x3c, 0xd1, 0x1f, 0x39, 0x43, 0x1c, 0xbf, 0xfd, 0x82, 0x32, + 0x54, 0xce, 0x47, 0x2e, 0x21, 0x05, 0xe4, 0x9b, 0x3d, 0x7f, 0x11, 0x3b, + 0x82, 0x50, 0x76, 0xe6, 0x26, 0x45, 0x85, 0x80, 0x7b, 0xc4, 0x64, 0x54, + 0x66, 0x5f, 0x27, 0xc5, 0xe4, 0xe1, 0xa4, 0xbd, 0x03, 0x47, 0x04, 0x86, + 0x32, 0x29, 0x81, 0xfd, 0xc8, 0x94, 0xcc, 0xa1, 0xe2, 0x93, 0x09, 0x87, + 0xc9, 0x2c, 0x15, 0xa3, 0x8b, 0xc4, 0x2e, 0xb3, 0x88, 0x10, 0xe8, 0x67, + 0xc4, 0x43, 0x2f, 0x07, 0x25, 0x9e, 0xc0, 0x0c, 0xdb, 0xbb, 0x0f, 0xb9, + 0x9e, 0x17, 0x27, 0xc7, 0x06, 0xda, 0x58, 0xdd +}; + +static const uint32_t derive_key_max_keysize = 1024; + +static struct derive_key_ecdh_t { + uint32_t level; /* test suite level */ + uint32_t algo; /* TEE_ALG_ECDH_P192,... */ + uint32_t curve; /* TEE_ECC_CURVE_NIST_P192,... */ + uint32_t keysize; /* key size, in bits */ + const uint8_t *public_x; /* public key - x == QCAVSx */ + const uint8_t *public_y; /* public key - y == QCAVSy */ + const uint8_t *private; /* private key == dIUT */ + const uint8_t *out; /* expected result - ZIUT */ +} const derive_key_ecdh[] = { + /* [P-192] */ + { + .level = 0, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_1_public_x, + .public_y = nist_kas_ecc_cdh_testvector_1_public_y, + .private = nist_kas_ecc_cdh_testvector_1_private, + .out = nist_kas_ecc_cdh_testvector_1_out, + }, + { + .level = 1, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_2_public_x, + .public_y = nist_kas_ecc_cdh_testvector_2_public_y, + .private = nist_kas_ecc_cdh_testvector_2_private, + .out = nist_kas_ecc_cdh_testvector_2_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_3_public_x, + .public_y = nist_kas_ecc_cdh_testvector_3_public_y, + .private = nist_kas_ecc_cdh_testvector_3_private, + .out = nist_kas_ecc_cdh_testvector_3_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_4_public_x, + .public_y = nist_kas_ecc_cdh_testvector_4_public_y, + .private = nist_kas_ecc_cdh_testvector_4_private, + .out = nist_kas_ecc_cdh_testvector_4_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_5_public_x, + .public_y = nist_kas_ecc_cdh_testvector_5_public_y, + .private = nist_kas_ecc_cdh_testvector_5_private, + .out = nist_kas_ecc_cdh_testvector_5_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_6_public_x, + .public_y = nist_kas_ecc_cdh_testvector_6_public_y, + .private = nist_kas_ecc_cdh_testvector_6_private, + .out = nist_kas_ecc_cdh_testvector_6_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_7_public_x, + .public_y = nist_kas_ecc_cdh_testvector_7_public_y, + .private = nist_kas_ecc_cdh_testvector_7_private, + .out = nist_kas_ecc_cdh_testvector_7_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_8_public_x, + .public_y = nist_kas_ecc_cdh_testvector_8_public_y, + .private = nist_kas_ecc_cdh_testvector_8_private, + .out = nist_kas_ecc_cdh_testvector_8_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_9_public_x, + .public_y = nist_kas_ecc_cdh_testvector_9_public_y, + .private = nist_kas_ecc_cdh_testvector_9_private, + .out = nist_kas_ecc_cdh_testvector_9_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_10_public_x, + .public_y = nist_kas_ecc_cdh_testvector_10_public_y, + .private = nist_kas_ecc_cdh_testvector_10_private, + .out = nist_kas_ecc_cdh_testvector_10_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_11_public_x, + .public_y = nist_kas_ecc_cdh_testvector_11_public_y, + .private = nist_kas_ecc_cdh_testvector_11_private, + .out = nist_kas_ecc_cdh_testvector_11_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_12_public_x, + .public_y = nist_kas_ecc_cdh_testvector_12_public_y, + .private = nist_kas_ecc_cdh_testvector_12_private, + .out = nist_kas_ecc_cdh_testvector_12_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_13_public_x, + .public_y = nist_kas_ecc_cdh_testvector_13_public_y, + .private = nist_kas_ecc_cdh_testvector_13_private, + .out = nist_kas_ecc_cdh_testvector_13_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_14_public_x, + .public_y = nist_kas_ecc_cdh_testvector_14_public_y, + .private = nist_kas_ecc_cdh_testvector_14_private, + .out = nist_kas_ecc_cdh_testvector_14_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_15_public_x, + .public_y = nist_kas_ecc_cdh_testvector_15_public_y, + .private = nist_kas_ecc_cdh_testvector_15_private, + .out = nist_kas_ecc_cdh_testvector_15_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_16_public_x, + .public_y = nist_kas_ecc_cdh_testvector_16_public_y, + .private = nist_kas_ecc_cdh_testvector_16_private, + .out = nist_kas_ecc_cdh_testvector_16_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_17_public_x, + .public_y = nist_kas_ecc_cdh_testvector_17_public_y, + .private = nist_kas_ecc_cdh_testvector_17_private, + .out = nist_kas_ecc_cdh_testvector_17_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_18_public_x, + .public_y = nist_kas_ecc_cdh_testvector_18_public_y, + .private = nist_kas_ecc_cdh_testvector_18_private, + .out = nist_kas_ecc_cdh_testvector_18_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_19_public_x, + .public_y = nist_kas_ecc_cdh_testvector_19_public_y, + .private = nist_kas_ecc_cdh_testvector_19_private, + .out = nist_kas_ecc_cdh_testvector_19_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_20_public_x, + .public_y = nist_kas_ecc_cdh_testvector_20_public_y, + .private = nist_kas_ecc_cdh_testvector_20_private, + .out = nist_kas_ecc_cdh_testvector_20_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_21_public_x, + .public_y = nist_kas_ecc_cdh_testvector_21_public_y, + .private = nist_kas_ecc_cdh_testvector_21_private, + .out = nist_kas_ecc_cdh_testvector_21_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_22_public_x, + .public_y = nist_kas_ecc_cdh_testvector_22_public_y, + .private = nist_kas_ecc_cdh_testvector_22_private, + .out = nist_kas_ecc_cdh_testvector_22_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_23_public_x, + .public_y = nist_kas_ecc_cdh_testvector_23_public_y, + .private = nist_kas_ecc_cdh_testvector_23_private, + .out = nist_kas_ecc_cdh_testvector_23_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_24_public_x, + .public_y = nist_kas_ecc_cdh_testvector_24_public_y, + .private = nist_kas_ecc_cdh_testvector_24_private, + .out = nist_kas_ecc_cdh_testvector_24_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P192, + .curve = TEE_ECC_CURVE_NIST_P192, + .keysize = 192, + .public_x = nist_kas_ecc_cdh_testvector_25_public_x, + .public_y = nist_kas_ecc_cdh_testvector_25_public_y, + .private = nist_kas_ecc_cdh_testvector_25_private, + .out = nist_kas_ecc_cdh_testvector_25_out, + }, + /* [P-224] */ + { + .level = 0, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_26_public_x, + .public_y = nist_kas_ecc_cdh_testvector_26_public_y, + .private = nist_kas_ecc_cdh_testvector_26_private, + .out = nist_kas_ecc_cdh_testvector_26_out, + }, + { + .level = 1, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_27_public_x, + .public_y = nist_kas_ecc_cdh_testvector_27_public_y, + .private = nist_kas_ecc_cdh_testvector_27_private, + .out = nist_kas_ecc_cdh_testvector_27_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_28_public_x, + .public_y = nist_kas_ecc_cdh_testvector_28_public_y, + .private = nist_kas_ecc_cdh_testvector_28_private, + .out = nist_kas_ecc_cdh_testvector_28_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_29_public_x, + .public_y = nist_kas_ecc_cdh_testvector_29_public_y, + .private = nist_kas_ecc_cdh_testvector_29_private, + .out = nist_kas_ecc_cdh_testvector_29_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_30_public_x, + .public_y = nist_kas_ecc_cdh_testvector_30_public_y, + .private = nist_kas_ecc_cdh_testvector_30_private, + .out = nist_kas_ecc_cdh_testvector_30_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_31_public_x, + .public_y = nist_kas_ecc_cdh_testvector_31_public_y, + .private = nist_kas_ecc_cdh_testvector_31_private, + .out = nist_kas_ecc_cdh_testvector_31_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_32_public_x, + .public_y = nist_kas_ecc_cdh_testvector_32_public_y, + .private = nist_kas_ecc_cdh_testvector_32_private, + .out = nist_kas_ecc_cdh_testvector_32_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_33_public_x, + .public_y = nist_kas_ecc_cdh_testvector_33_public_y, + .private = nist_kas_ecc_cdh_testvector_33_private, + .out = nist_kas_ecc_cdh_testvector_33_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_34_public_x, + .public_y = nist_kas_ecc_cdh_testvector_34_public_y, + .private = nist_kas_ecc_cdh_testvector_34_private, + .out = nist_kas_ecc_cdh_testvector_34_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_35_public_x, + .public_y = nist_kas_ecc_cdh_testvector_35_public_y, + .private = nist_kas_ecc_cdh_testvector_35_private, + .out = nist_kas_ecc_cdh_testvector_35_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_36_public_x, + .public_y = nist_kas_ecc_cdh_testvector_36_public_y, + .private = nist_kas_ecc_cdh_testvector_36_private, + .out = nist_kas_ecc_cdh_testvector_36_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_37_public_x, + .public_y = nist_kas_ecc_cdh_testvector_37_public_y, + .private = nist_kas_ecc_cdh_testvector_37_private, + .out = nist_kas_ecc_cdh_testvector_37_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_38_public_x, + .public_y = nist_kas_ecc_cdh_testvector_38_public_y, + .private = nist_kas_ecc_cdh_testvector_38_private, + .out = nist_kas_ecc_cdh_testvector_38_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_39_public_x, + .public_y = nist_kas_ecc_cdh_testvector_39_public_y, + .private = nist_kas_ecc_cdh_testvector_39_private, + .out = nist_kas_ecc_cdh_testvector_39_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_40_public_x, + .public_y = nist_kas_ecc_cdh_testvector_40_public_y, + .private = nist_kas_ecc_cdh_testvector_40_private, + .out = nist_kas_ecc_cdh_testvector_40_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_41_public_x, + .public_y = nist_kas_ecc_cdh_testvector_41_public_y, + .private = nist_kas_ecc_cdh_testvector_41_private, + .out = nist_kas_ecc_cdh_testvector_41_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_42_public_x, + .public_y = nist_kas_ecc_cdh_testvector_42_public_y, + .private = nist_kas_ecc_cdh_testvector_42_private, + .out = nist_kas_ecc_cdh_testvector_42_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_43_public_x, + .public_y = nist_kas_ecc_cdh_testvector_43_public_y, + .private = nist_kas_ecc_cdh_testvector_43_private, + .out = nist_kas_ecc_cdh_testvector_43_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_44_public_x, + .public_y = nist_kas_ecc_cdh_testvector_44_public_y, + .private = nist_kas_ecc_cdh_testvector_44_private, + .out = nist_kas_ecc_cdh_testvector_44_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_45_public_x, + .public_y = nist_kas_ecc_cdh_testvector_45_public_y, + .private = nist_kas_ecc_cdh_testvector_45_private, + .out = nist_kas_ecc_cdh_testvector_45_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_46_public_x, + .public_y = nist_kas_ecc_cdh_testvector_46_public_y, + .private = nist_kas_ecc_cdh_testvector_46_private, + .out = nist_kas_ecc_cdh_testvector_46_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_47_public_x, + .public_y = nist_kas_ecc_cdh_testvector_47_public_y, + .private = nist_kas_ecc_cdh_testvector_47_private, + .out = nist_kas_ecc_cdh_testvector_47_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_48_public_x, + .public_y = nist_kas_ecc_cdh_testvector_48_public_y, + .private = nist_kas_ecc_cdh_testvector_48_private, + .out = nist_kas_ecc_cdh_testvector_48_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_49_public_x, + .public_y = nist_kas_ecc_cdh_testvector_49_public_y, + .private = nist_kas_ecc_cdh_testvector_49_private, + .out = nist_kas_ecc_cdh_testvector_49_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P224, + .curve = TEE_ECC_CURVE_NIST_P224, + .keysize = 224, + .public_x = nist_kas_ecc_cdh_testvector_50_public_x, + .public_y = nist_kas_ecc_cdh_testvector_50_public_y, + .private = nist_kas_ecc_cdh_testvector_50_private, + .out = nist_kas_ecc_cdh_testvector_50_out, + }, + /* [P-256] */ + { + .level = 0, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_51_public_x, + .public_y = nist_kas_ecc_cdh_testvector_51_public_y, + .private = nist_kas_ecc_cdh_testvector_51_private, + .out = nist_kas_ecc_cdh_testvector_51_out, + }, + { + .level = 1, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_52_public_x, + .public_y = nist_kas_ecc_cdh_testvector_52_public_y, + .private = nist_kas_ecc_cdh_testvector_52_private, + .out = nist_kas_ecc_cdh_testvector_52_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_53_public_x, + .public_y = nist_kas_ecc_cdh_testvector_53_public_y, + .private = nist_kas_ecc_cdh_testvector_53_private, + .out = nist_kas_ecc_cdh_testvector_53_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_54_public_x, + .public_y = nist_kas_ecc_cdh_testvector_54_public_y, + .private = nist_kas_ecc_cdh_testvector_54_private, + .out = nist_kas_ecc_cdh_testvector_54_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_55_public_x, + .public_y = nist_kas_ecc_cdh_testvector_55_public_y, + .private = nist_kas_ecc_cdh_testvector_55_private, + .out = nist_kas_ecc_cdh_testvector_55_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_56_public_x, + .public_y = nist_kas_ecc_cdh_testvector_56_public_y, + .private = nist_kas_ecc_cdh_testvector_56_private, + .out = nist_kas_ecc_cdh_testvector_56_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_57_public_x, + .public_y = nist_kas_ecc_cdh_testvector_57_public_y, + .private = nist_kas_ecc_cdh_testvector_57_private, + .out = nist_kas_ecc_cdh_testvector_57_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_58_public_x, + .public_y = nist_kas_ecc_cdh_testvector_58_public_y, + .private = nist_kas_ecc_cdh_testvector_58_private, + .out = nist_kas_ecc_cdh_testvector_58_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_59_public_x, + .public_y = nist_kas_ecc_cdh_testvector_59_public_y, + .private = nist_kas_ecc_cdh_testvector_59_private, + .out = nist_kas_ecc_cdh_testvector_59_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_60_public_x, + .public_y = nist_kas_ecc_cdh_testvector_60_public_y, + .private = nist_kas_ecc_cdh_testvector_60_private, + .out = nist_kas_ecc_cdh_testvector_60_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_61_public_x, + .public_y = nist_kas_ecc_cdh_testvector_61_public_y, + .private = nist_kas_ecc_cdh_testvector_61_private, + .out = nist_kas_ecc_cdh_testvector_61_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_62_public_x, + .public_y = nist_kas_ecc_cdh_testvector_62_public_y, + .private = nist_kas_ecc_cdh_testvector_62_private, + .out = nist_kas_ecc_cdh_testvector_62_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_63_public_x, + .public_y = nist_kas_ecc_cdh_testvector_63_public_y, + .private = nist_kas_ecc_cdh_testvector_63_private, + .out = nist_kas_ecc_cdh_testvector_63_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_64_public_x, + .public_y = nist_kas_ecc_cdh_testvector_64_public_y, + .private = nist_kas_ecc_cdh_testvector_64_private, + .out = nist_kas_ecc_cdh_testvector_64_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_65_public_x, + .public_y = nist_kas_ecc_cdh_testvector_65_public_y, + .private = nist_kas_ecc_cdh_testvector_65_private, + .out = nist_kas_ecc_cdh_testvector_65_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_66_public_x, + .public_y = nist_kas_ecc_cdh_testvector_66_public_y, + .private = nist_kas_ecc_cdh_testvector_66_private, + .out = nist_kas_ecc_cdh_testvector_66_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_67_public_x, + .public_y = nist_kas_ecc_cdh_testvector_67_public_y, + .private = nist_kas_ecc_cdh_testvector_67_private, + .out = nist_kas_ecc_cdh_testvector_67_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_68_public_x, + .public_y = nist_kas_ecc_cdh_testvector_68_public_y, + .private = nist_kas_ecc_cdh_testvector_68_private, + .out = nist_kas_ecc_cdh_testvector_68_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_69_public_x, + .public_y = nist_kas_ecc_cdh_testvector_69_public_y, + .private = nist_kas_ecc_cdh_testvector_69_private, + .out = nist_kas_ecc_cdh_testvector_69_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_70_public_x, + .public_y = nist_kas_ecc_cdh_testvector_70_public_y, + .private = nist_kas_ecc_cdh_testvector_70_private, + .out = nist_kas_ecc_cdh_testvector_70_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_71_public_x, + .public_y = nist_kas_ecc_cdh_testvector_71_public_y, + .private = nist_kas_ecc_cdh_testvector_71_private, + .out = nist_kas_ecc_cdh_testvector_71_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_72_public_x, + .public_y = nist_kas_ecc_cdh_testvector_72_public_y, + .private = nist_kas_ecc_cdh_testvector_72_private, + .out = nist_kas_ecc_cdh_testvector_72_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_73_public_x, + .public_y = nist_kas_ecc_cdh_testvector_73_public_y, + .private = nist_kas_ecc_cdh_testvector_73_private, + .out = nist_kas_ecc_cdh_testvector_73_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_74_public_x, + .public_y = nist_kas_ecc_cdh_testvector_74_public_y, + .private = nist_kas_ecc_cdh_testvector_74_private, + .out = nist_kas_ecc_cdh_testvector_74_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P256, + .curve = TEE_ECC_CURVE_NIST_P256, + .keysize = 256, + .public_x = nist_kas_ecc_cdh_testvector_75_public_x, + .public_y = nist_kas_ecc_cdh_testvector_75_public_y, + .private = nist_kas_ecc_cdh_testvector_75_private, + .out = nist_kas_ecc_cdh_testvector_75_out, + }, + /* [P-384] */ + { + .level = 0, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_76_public_x, + .public_y = nist_kas_ecc_cdh_testvector_76_public_y, + .private = nist_kas_ecc_cdh_testvector_76_private, + .out = nist_kas_ecc_cdh_testvector_76_out, + }, + { + .level = 1, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_77_public_x, + .public_y = nist_kas_ecc_cdh_testvector_77_public_y, + .private = nist_kas_ecc_cdh_testvector_77_private, + .out = nist_kas_ecc_cdh_testvector_77_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_78_public_x, + .public_y = nist_kas_ecc_cdh_testvector_78_public_y, + .private = nist_kas_ecc_cdh_testvector_78_private, + .out = nist_kas_ecc_cdh_testvector_78_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_79_public_x, + .public_y = nist_kas_ecc_cdh_testvector_79_public_y, + .private = nist_kas_ecc_cdh_testvector_79_private, + .out = nist_kas_ecc_cdh_testvector_79_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_80_public_x, + .public_y = nist_kas_ecc_cdh_testvector_80_public_y, + .private = nist_kas_ecc_cdh_testvector_80_private, + .out = nist_kas_ecc_cdh_testvector_80_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_81_public_x, + .public_y = nist_kas_ecc_cdh_testvector_81_public_y, + .private = nist_kas_ecc_cdh_testvector_81_private, + .out = nist_kas_ecc_cdh_testvector_81_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_82_public_x, + .public_y = nist_kas_ecc_cdh_testvector_82_public_y, + .private = nist_kas_ecc_cdh_testvector_82_private, + .out = nist_kas_ecc_cdh_testvector_82_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_83_public_x, + .public_y = nist_kas_ecc_cdh_testvector_83_public_y, + .private = nist_kas_ecc_cdh_testvector_83_private, + .out = nist_kas_ecc_cdh_testvector_83_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_84_public_x, + .public_y = nist_kas_ecc_cdh_testvector_84_public_y, + .private = nist_kas_ecc_cdh_testvector_84_private, + .out = nist_kas_ecc_cdh_testvector_84_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_85_public_x, + .public_y = nist_kas_ecc_cdh_testvector_85_public_y, + .private = nist_kas_ecc_cdh_testvector_85_private, + .out = nist_kas_ecc_cdh_testvector_85_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_86_public_x, + .public_y = nist_kas_ecc_cdh_testvector_86_public_y, + .private = nist_kas_ecc_cdh_testvector_86_private, + .out = nist_kas_ecc_cdh_testvector_86_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_87_public_x, + .public_y = nist_kas_ecc_cdh_testvector_87_public_y, + .private = nist_kas_ecc_cdh_testvector_87_private, + .out = nist_kas_ecc_cdh_testvector_87_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_88_public_x, + .public_y = nist_kas_ecc_cdh_testvector_88_public_y, + .private = nist_kas_ecc_cdh_testvector_88_private, + .out = nist_kas_ecc_cdh_testvector_88_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_89_public_x, + .public_y = nist_kas_ecc_cdh_testvector_89_public_y, + .private = nist_kas_ecc_cdh_testvector_89_private, + .out = nist_kas_ecc_cdh_testvector_89_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_90_public_x, + .public_y = nist_kas_ecc_cdh_testvector_90_public_y, + .private = nist_kas_ecc_cdh_testvector_90_private, + .out = nist_kas_ecc_cdh_testvector_90_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_91_public_x, + .public_y = nist_kas_ecc_cdh_testvector_91_public_y, + .private = nist_kas_ecc_cdh_testvector_91_private, + .out = nist_kas_ecc_cdh_testvector_91_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_92_public_x, + .public_y = nist_kas_ecc_cdh_testvector_92_public_y, + .private = nist_kas_ecc_cdh_testvector_92_private, + .out = nist_kas_ecc_cdh_testvector_92_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_93_public_x, + .public_y = nist_kas_ecc_cdh_testvector_93_public_y, + .private = nist_kas_ecc_cdh_testvector_93_private, + .out = nist_kas_ecc_cdh_testvector_93_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_94_public_x, + .public_y = nist_kas_ecc_cdh_testvector_94_public_y, + .private = nist_kas_ecc_cdh_testvector_94_private, + .out = nist_kas_ecc_cdh_testvector_94_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_95_public_x, + .public_y = nist_kas_ecc_cdh_testvector_95_public_y, + .private = nist_kas_ecc_cdh_testvector_95_private, + .out = nist_kas_ecc_cdh_testvector_95_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_96_public_x, + .public_y = nist_kas_ecc_cdh_testvector_96_public_y, + .private = nist_kas_ecc_cdh_testvector_96_private, + .out = nist_kas_ecc_cdh_testvector_96_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_97_public_x, + .public_y = nist_kas_ecc_cdh_testvector_97_public_y, + .private = nist_kas_ecc_cdh_testvector_97_private, + .out = nist_kas_ecc_cdh_testvector_97_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_98_public_x, + .public_y = nist_kas_ecc_cdh_testvector_98_public_y, + .private = nist_kas_ecc_cdh_testvector_98_private, + .out = nist_kas_ecc_cdh_testvector_98_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_99_public_x, + .public_y = nist_kas_ecc_cdh_testvector_99_public_y, + .private = nist_kas_ecc_cdh_testvector_99_private, + .out = nist_kas_ecc_cdh_testvector_99_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P384, + .curve = TEE_ECC_CURVE_NIST_P384, + .keysize = 384, + .public_x = nist_kas_ecc_cdh_testvector_100_public_x, + .public_y = nist_kas_ecc_cdh_testvector_100_public_y, + .private = nist_kas_ecc_cdh_testvector_100_private, + .out = nist_kas_ecc_cdh_testvector_100_out, + }, + /* [P-521] */ + { + .level = 0, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_101_public_x, + .public_y = nist_kas_ecc_cdh_testvector_101_public_y, + .private = nist_kas_ecc_cdh_testvector_101_private, + .out = nist_kas_ecc_cdh_testvector_101_out, + }, + { + .level = 1, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_102_public_x, + .public_y = nist_kas_ecc_cdh_testvector_102_public_y, + .private = nist_kas_ecc_cdh_testvector_102_private, + .out = nist_kas_ecc_cdh_testvector_102_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_103_public_x, + .public_y = nist_kas_ecc_cdh_testvector_103_public_y, + .private = nist_kas_ecc_cdh_testvector_103_private, + .out = nist_kas_ecc_cdh_testvector_103_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_104_public_x, + .public_y = nist_kas_ecc_cdh_testvector_104_public_y, + .private = nist_kas_ecc_cdh_testvector_104_private, + .out = nist_kas_ecc_cdh_testvector_104_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_105_public_x, + .public_y = nist_kas_ecc_cdh_testvector_105_public_y, + .private = nist_kas_ecc_cdh_testvector_105_private, + .out = nist_kas_ecc_cdh_testvector_105_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_106_public_x, + .public_y = nist_kas_ecc_cdh_testvector_106_public_y, + .private = nist_kas_ecc_cdh_testvector_106_private, + .out = nist_kas_ecc_cdh_testvector_106_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_107_public_x, + .public_y = nist_kas_ecc_cdh_testvector_107_public_y, + .private = nist_kas_ecc_cdh_testvector_107_private, + .out = nist_kas_ecc_cdh_testvector_107_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_108_public_x, + .public_y = nist_kas_ecc_cdh_testvector_108_public_y, + .private = nist_kas_ecc_cdh_testvector_108_private, + .out = nist_kas_ecc_cdh_testvector_108_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_109_public_x, + .public_y = nist_kas_ecc_cdh_testvector_109_public_y, + .private = nist_kas_ecc_cdh_testvector_109_private, + .out = nist_kas_ecc_cdh_testvector_109_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_110_public_x, + .public_y = nist_kas_ecc_cdh_testvector_110_public_y, + .private = nist_kas_ecc_cdh_testvector_110_private, + .out = nist_kas_ecc_cdh_testvector_110_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_111_public_x, + .public_y = nist_kas_ecc_cdh_testvector_111_public_y, + .private = nist_kas_ecc_cdh_testvector_111_private, + .out = nist_kas_ecc_cdh_testvector_111_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_112_public_x, + .public_y = nist_kas_ecc_cdh_testvector_112_public_y, + .private = nist_kas_ecc_cdh_testvector_112_private, + .out = nist_kas_ecc_cdh_testvector_112_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_113_public_x, + .public_y = nist_kas_ecc_cdh_testvector_113_public_y, + .private = nist_kas_ecc_cdh_testvector_113_private, + .out = nist_kas_ecc_cdh_testvector_113_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_114_public_x, + .public_y = nist_kas_ecc_cdh_testvector_114_public_y, + .private = nist_kas_ecc_cdh_testvector_114_private, + .out = nist_kas_ecc_cdh_testvector_114_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_115_public_x, + .public_y = nist_kas_ecc_cdh_testvector_115_public_y, + .private = nist_kas_ecc_cdh_testvector_115_private, + .out = nist_kas_ecc_cdh_testvector_115_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_116_public_x, + .public_y = nist_kas_ecc_cdh_testvector_116_public_y, + .private = nist_kas_ecc_cdh_testvector_116_private, + .out = nist_kas_ecc_cdh_testvector_116_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_117_public_x, + .public_y = nist_kas_ecc_cdh_testvector_117_public_y, + .private = nist_kas_ecc_cdh_testvector_117_private, + .out = nist_kas_ecc_cdh_testvector_117_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_118_public_x, + .public_y = nist_kas_ecc_cdh_testvector_118_public_y, + .private = nist_kas_ecc_cdh_testvector_118_private, + .out = nist_kas_ecc_cdh_testvector_118_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_119_public_x, + .public_y = nist_kas_ecc_cdh_testvector_119_public_y, + .private = nist_kas_ecc_cdh_testvector_119_private, + .out = nist_kas_ecc_cdh_testvector_119_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_120_public_x, + .public_y = nist_kas_ecc_cdh_testvector_120_public_y, + .private = nist_kas_ecc_cdh_testvector_120_private, + .out = nist_kas_ecc_cdh_testvector_120_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_121_public_x, + .public_y = nist_kas_ecc_cdh_testvector_121_public_y, + .private = nist_kas_ecc_cdh_testvector_121_private, + .out = nist_kas_ecc_cdh_testvector_121_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_122_public_x, + .public_y = nist_kas_ecc_cdh_testvector_122_public_y, + .private = nist_kas_ecc_cdh_testvector_122_private, + .out = nist_kas_ecc_cdh_testvector_122_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_123_public_x, + .public_y = nist_kas_ecc_cdh_testvector_123_public_y, + .private = nist_kas_ecc_cdh_testvector_123_private, + .out = nist_kas_ecc_cdh_testvector_123_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_124_public_x, + .public_y = nist_kas_ecc_cdh_testvector_124_public_y, + .private = nist_kas_ecc_cdh_testvector_124_private, + .out = nist_kas_ecc_cdh_testvector_124_out, + }, + { + .level = 15, + .algo = TEE_ALG_ECDH_P521, + .curve = TEE_ECC_CURVE_NIST_P521, + .keysize = 521, + .public_x = nist_kas_ecc_cdh_testvector_125_public_x, + .public_y = nist_kas_ecc_cdh_testvector_125_public_y, + .private = nist_kas_ecc_cdh_testvector_125_private, + .out = nist_kas_ecc_cdh_testvector_125_out, + }, + /* [K-163] - GP NOT SUPPORTED */ + /* [K-233] - GP NOT SUPPORTED */ + /* [K-283] - GP NOT SUPPORTED */ + /* [K-409] - GP NOT SUPPORTED */ + /* [K-571] - GP NOT SUPPORTED */ + /* [B-163] - GP NOT SUPPORTED */ + /* [B-233] - GP NOT SUPPORTED */ + /* [B-283] - GP NOT SUPPORTED */ + /* [B-409] - GP NOT SUPPORTED */ + /* [B-571] - GP NOT SUPPORTED */ +}; + +/* G/MT 0003 (SM2) Part 5 Annex C.2 - encryption/decryption */ +static const uint8_t gmt_0003_part5_c2_sm2_testvector_ptx[19] = +/* M */ + "encryption standard"; +static const uint8_t gmt_0003_part5_c2_sm2_testvector_private[] = { +/* dB */ + 0x39, 0x45, 0x20, 0x8F, 0x7B, 0x21, 0x44, 0xB1, 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, 0x4D, 0xF7, 0xC5, 0xB8 +}; +static const uint8_t gmt_0003_part5_c2_sm2_testvector_public_x[] = { +/* xB */ + 0x09, 0xF9, 0xDF, 0x31, 0x1E, 0x54, 0x21, 0xA1, 0x50, 0xDD, 0x7D, 0x16, + 0x1E, 0x4B, 0xC5, 0xC6, 0x72, 0x17, 0x9F, 0xAD, 0x18, 0x33, 0xFC, 0x07, + 0x6B, 0xB0, 0x8F, 0xF3, 0x56, 0xF3, 0x50, 0x20 +}; +static const uint8_t gmt_0003_part5_c2_sm2_testvector_public_y[] = { +/* yB */ + 0xCC, 0xEA, 0x49, 0x0C, 0xE2, 0x67, 0x75, 0xA5, 0x2D, 0xC6, 0xEA, 0x71, + 0x8C, 0xC1, 0xAA, 0x60, 0x0A, 0xED, 0x05, 0xFB, 0xF3, 0x5E, 0x08, 0x4A, + 0x66, 0x32, 0xF6, 0x07, 0x2D, 0xA9, 0xAD, 0x13 +}; +static const uint8_t gmt_0003_part5_c2_sm2_testvector_out[] = { +/* C */ + /* C1 */ + 0x04, + 0x04, 0xEB, 0xFC, 0x71, 0x8E, 0x8D, 0x17, 0x98, 0x62, 0x04, 0x32, 0x26, + 0x8E, 0x77, 0xFE, 0xB6, 0x41, 0x5E, 0x2E, 0xDE, 0x0E, 0x07, 0x3C, 0x0F, + 0x4F, 0x64, 0x0E, 0xCD, 0x2E, 0x14, 0x9A, 0x73, 0xE8, 0x58, 0xF9, 0xD8, + 0x1E, 0x54, 0x30, 0xA5, 0x7B, 0x36, 0xDA, 0xAB, 0x8F, 0x95, 0x0A, 0x3C, + 0x64, 0xE6, 0xEE, 0x6A, 0x63, 0x09, 0x4D, 0x99, 0x28, 0x3A, 0xFF, 0x76, + 0x7E, 0x12, 0x4D, 0xF0, + /* C2 */ + 0x21, 0x88, 0x6C, 0xA9, 0x89, 0xCA, 0x9C, 0x7D, 0x58, 0x08, 0x73, 0x07, + 0xCA, 0x93, 0x09, 0x2D, 0x65, 0x1E, 0xFA, + /* C3 */ + 0x59, 0x98, 0x3C, 0x18, 0xF8, 0x09, 0xE2, 0x62, 0x92, 0x3C, 0x53, 0xAE, + 0xC2, 0x95, 0xD3, 0x03, 0x83, 0xB5, 0x4E, 0x39, 0xD6, 0x09, 0xD1, 0x60, + 0xAF, 0xCB, 0x19, 0x08, 0xD0, 0xBD, 0x87, 0x66 +}; + +/* SM2 encryption/decryption */ +static const uint8_t sm2_testvector2_ptx[] = +/* M */ + "This test vector is used to test encryption then decryption. The " + "plain text is longer than 64 characters, so it will exercise parts " + "of the code that are not used for shorter messages."; +static const uint8_t sm2_testvector2_private[] = { +/* dB */ + 0x39, 0x45, 0x20, 0x8F, 0x7B, 0x21, 0x44, 0xB1, 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, 0x4D, 0xF7, 0xC5, 0xB8 +}; +static const uint8_t sm2_testvector2_public_x[] = { +/* xB */ + 0x09, 0xF9, 0xDF, 0x31, 0x1E, 0x54, 0x21, 0xA1, 0x50, 0xDD, 0x7D, 0x16, + 0x1E, 0x4B, 0xC5, 0xC6, 0x72, 0x17, 0x9F, 0xAD, 0x18, 0x33, 0xFC, 0x07, + 0x6B, 0xB0, 0x8F, 0xF3, 0x56, 0xF3, 0x50, 0x20 +}; +static const uint8_t sm2_testvector2_public_y[] = { +/* yB */ + 0xCC, 0xEA, 0x49, 0x0C, 0xE2, 0x67, 0x75, 0xA5, 0x2D, 0xC6, 0xEA, 0x71, + 0x8C, 0xC1, 0xAA, 0x60, 0x0A, 0xED, 0x05, 0xFB, 0xF3, 0x5E, 0x08, 0x4A, + 0x66, 0x32, 0xF6, 0x07, 0x2D, 0xA9, 0xAD, 0x13 +}; +static const uint8_t sm2_testvector2_out[] = { + 0x00, /* Not used -- test runs in encrypt/decrypt mode */ +}; + +/* + * G/MT 0003 (SM2) Part 5 Annex A.2 - SM2 digital signature based on + * elliptic curves + */ +static const uint8_t gmt_003_part5_a2_ptx[] = { + /* ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */ + 0xB2, 0xE1, 0x4C, 0x5C, 0x79, 0xC6, 0xDF, 0x5B, 0x85, 0xF4, 0xFE, 0x7E, + 0xD8, 0xDB, 0x7A, 0x26, 0x2B, 0x9D, 0xA7, 0xE0, 0x7C, 0xCB, 0x0E, 0xA9, + 0xF4, 0x74, 0x7B, 0x8C, 0xCD, 0xA8, 0xA4, 0xF3, + /* M */ + 0x6D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x64, 0x69, 0x67, 0x65, + 0x73, 0x74 +}; +static const uint8_t gmt_003_part5_a2_private[] = { + /* dA */ + 0x39, 0x45, 0x20, 0x8F, 0x7B, 0x21, 0x44, 0xB1, 0x3F, 0x36, 0xE3, 0x8A, + 0xC6, 0xD3, 0x9F, 0x95, 0x88, 0x93, 0x93, 0x69, 0x28, 0x60, 0xB5, 0x1A, + 0x42, 0xFB, 0x81, 0xEF, 0x4D, 0xF7, 0xC5, 0xB8, +}; +static const uint8_t gmt_003_part5_a2_public_x[] = { + /* xA */ + 0x09, 0xF9, 0xDF, 0x31, 0x1E, 0x54, 0x21, 0xA1, 0x50, 0xDD, 0x7D, 0x16, + 0x1E, 0x4B, 0xC5, 0xC6, 0x72, 0x17, 0x9F, 0xAD, 0x18, 0x33, 0xFC, 0x07, + 0x6B, 0xB0, 0x8F, 0xF3, 0x56, 0xF3, 0x50, 0x20, +}; +static const uint8_t gmt_003_part5_a2_public_y[] = { + /* yA */ + 0xCC, 0xEA, 0x49, 0x0C, 0xE2, 0x67, 0x75, 0xA5, 0x2D, 0xC6, 0xEA, 0x71, + 0x8C, 0xC1, 0xAA, 0x60, 0x0A, 0xED, 0x05, 0xFB, 0xF3, 0x5E, 0x08, 0x4A, + 0x66, 0x32, 0xF6, 0x07, 0x2D, 0xA9, 0xAD, 0x13, +}; +static const uint8_t gmt_003_part5_a2_out[] = { + /* r */ + 0xF5, 0xA0, 0x3B, 0x06, 0x48, 0xD2, 0xC4, 0x63, 0x0E, 0xEA, 0xC5, 0x13, + 0xE1, 0xBB, 0x81, 0xA1, 0x59, 0x44, 0xDA, 0x38, 0x27, 0xD5, 0xB7, 0x41, + 0x43, 0xAC, 0x7E, 0xAC, 0xEE, 0xE7, 0x20, 0xB3, + /* s */ + 0xB1, 0xB6, 0xAA, 0x29, 0xDF, 0x21, 0x2F, 0xD8, 0x76, 0x31, 0x82, 0xBC, + 0x0D, 0x42, 0x1C, 0xA1, 0xBB, 0x90, 0x38, 0xFD, 0x1F, 0x7F, 0x42, 0xD4, + 0x84, 0x0B, 0x69, 0xC4, 0x85, 0xBB, 0xC1, 0xAA, +}; + +/* + * G/MT 0003 (SM2) Part 5 Annex B.2 - key exchange protocol based on elliptic + * curves + */ +static const uint8_t gmt_003_part5_b2_private_A[] = { + /* dA */ + 0x81, 0xEB, 0x26, 0xE9, 0x41, 0xBB, 0x5A, 0xF1, 0x6D, 0xF1, 0x16, 0x49, + 0x5F, 0x90, 0x69, 0x52, 0x72, 0xAE, 0x2C, 0xD6, 0x3D, 0x6C, 0x4A, 0xE1, + 0x67, 0x84, 0x18, 0xBE, 0x48, 0x23, 0x00, 0x29, +}; +static const uint8_t gmt_003_part5_b2_public_xA[] = { + /* xA */ + 0x16, 0x0E, 0x12, 0x89, 0x7D, 0xF4, 0xED, 0xB6, 0x1D, 0xD8, 0x12, 0xFE, + 0xB9, 0x67, 0x48, 0xFB, 0xD3, 0xCC, 0xF4, 0xFF, 0xE2, 0x6A, 0xA6, 0xF6, + 0xDB, 0x95, 0x40, 0xAF, 0x49, 0xC9, 0x42, 0x32, +}; +static const uint8_t gmt_003_part5_b2_public_yA[] = { + /* xA */ + 0x4A, 0x7D, 0xAD, 0x08, 0xBB, 0x9A, 0x45, 0x95, 0x31, 0x69, 0x4B, 0xEB, + 0x20, 0xAA, 0x48, 0x9D, 0x66, 0x49, 0x97, 0x5E, 0x1B, 0xFC, 0xF8, 0xC4, + 0x74, 0x1B, 0x78, 0xB4, 0xB2, 0x23, 0x00, 0x7F, +}; +static const uint8_t gmt_003_part5_b2_eph_private_A[] = { + /* rA */ + 0xD4, 0xDE, 0x15, 0x47, 0x4D, 0xB7, 0x4D, 0x06, 0x49, 0x1C, 0x44, 0x0D, + 0x30, 0x5E, 0x01, 0x24, 0x00, 0x99, 0x0F, 0x3E, 0x39, 0x0C, 0x7E, 0x87, + 0x15, 0x3C, 0x12, 0xDB, 0x2E, 0xA6, 0x0B, 0xB3, +}; +static const uint8_t gmt_003_part5_b2_eph_public_xA[] = { + /* x1 where (x1, y1) = [rA]G */ + 0x64, 0xCE, 0xD1, 0xBD, 0xBC, 0x99, 0xD5, 0x90, 0x04, 0x9B, 0x43, 0x4D, + 0x0F, 0xD7, 0x34, 0x28, 0xCF, 0x60, 0x8A, 0x5D, 0xB8, 0xFE, 0x5C, 0xE0, + 0x7F, 0x15, 0x02, 0x69, 0x40, 0xBA, 0xE4, 0x0E, +}; +static const uint8_t gmt_003_part5_b2_eph_public_yA[] = { + /* y1 where (x1, y1) = [rA]G */ + 0x37, 0x66, 0x29, 0xC7, 0xAB, 0x21, 0xE7, 0xDB, 0x26, 0x09, 0x22, 0x49, + 0x9D, 0xDB, 0x11, 0x8F, 0x07, 0xCE, 0x8E, 0xAA, 0xE3, 0xE7, 0x72, 0x0A, + 0xFE, 0xF6, 0xA5, 0xCC, 0x06, 0x20, 0x70, 0xC0, +}; +static const uint8_t gmt_003_part5_b2_public_xB[] = { + /* xB */ + 0x6A, 0xE8, 0x48, 0xC5, 0x7C, 0x53, 0xC7, 0xB1, 0xB5, 0xFA, 0x99, 0xEB, + 0x22, 0x86, 0xAF, 0x07, 0x8B, 0xA6, 0x4C, 0x64, 0x59, 0x1B, 0x8B, 0x56, + 0x6F, 0x73, 0x57, 0xD5, 0x76, 0xF1, 0x6D, 0xFB, +}; +static const uint8_t gmt_003_part5_b2_private_B[] = { + /* dB */ + 0x78, 0x51, 0x29, 0x91, 0x7D, 0x45, 0xA9, 0xEA, 0x54, 0x37, 0xA5, 0x93, + 0x56, 0xB8, 0x23, 0x38, 0xEA, 0xAD, 0xDA, 0x6C, 0xEB, 0x19, 0x90, 0x88, + 0xF1, 0x4A, 0xE1, 0x0D, 0xEF, 0xA2, 0x29, 0xB5, +}; +static const uint8_t gmt_003_part5_b2_public_yB[] = { + /* yB */ + 0xEE, 0x48, 0x9D, 0x77, 0x16, 0x21, 0xA2, 0x7B, 0x36, 0xC5, 0xC7, 0x99, + 0x20, 0x62, 0xE9, 0xCD, 0x09, 0xA9, 0x26, 0x43, 0x86, 0xF3, 0xFB, 0xEA, + 0x54, 0xDF, 0xF6, 0x93, 0x05, 0x62, 0x1C, 0x4D, +}; +static const uint8_t gmt_003_part5_b2_eph_private_B[] = { + /* rB */ + 0x7E, 0x07, 0x12, 0x48, 0x14, 0xB3, 0x09, 0x48, 0x91, 0x25, 0xEA, 0xED, + 0x10, 0x11, 0x13, 0x16, 0x4E, 0xBF, 0x0F, 0x34, 0x58, 0xC5, 0xBD, 0x88, + 0x33, 0x5C, 0x1F, 0x9D, 0x59, 0x62, 0x43, 0xD6, +}; +static const uint8_t gmt_003_part5_b2_eph_public_xB[] = { + /* x2 where (x2, y2) = [rB]G */ + 0xAC, 0xC2, 0x76, 0x88, 0xA6, 0xF7, 0xB7, 0x06, 0x09, 0x8B, 0xC9, 0x1F, + 0xF3, 0xAD, 0x1B, 0xFF, 0x7D, 0xC2, 0x80, 0x2C, 0xDB, 0x14, 0xCC, 0xCC, + 0xDB, 0x0A, 0x90, 0x47, 0x1F, 0x9B, 0xD7, 0x07, +}; +static const uint8_t gmt_003_part5_b2_eph_public_yB[] = { + /* y2 where (x2, y2) = [rB]G */ + 0x2F, 0xED, 0xAC, 0x04, 0x94, 0xB2, 0xFF, 0xC4, 0xD6, 0x85, 0x38, 0x76, + 0xC7, 0x9B, 0x8F, 0x30, 0x1C, 0x65, 0x73, 0xAD, 0x0A, 0xA5, 0x0F, 0x39, + 0xFC, 0x87, 0x18, 0x1E, 0x1A, 0x1B, 0x46, 0xFE, +}; +static const uint8_t gmt_003_part5_b2_id_A[] = { + /* IDA */ + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, +}; +static const uint8_t gmt_003_part5_b2_id_B[] = { + /* IDB */ + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, +}; +static const uint8_t gmt_003_part5_b2_conf_A[] = { + /* S2 = SA */ + 0x18, 0xC7, 0x89, 0x4B, 0x38, 0x16, 0xDF, 0x16, 0xCF, 0x07, 0xB0, 0x5C, + 0x5E, 0xC0, 0xBE, 0xF5, 0xD6, 0x55, 0xD5, 0x8F, 0x77, 0x9C, 0xC1, 0xB4, + 0x00, 0xA4, 0xF3, 0x88, 0x46, 0x44, 0xDB, 0x88, +}; +static const uint8_t gmt_003_part5_b2_conf_B[] = { + /* S1 = SB */ + 0xD3, 0xA0, 0xFE, 0x15, 0xDE, 0xE1, 0x85, 0xCE, 0xAE, 0x90, 0x7A, 0x6B, + 0x59, 0x5C, 0xC3, 0x2A, 0x26, 0x6E, 0xD7, 0xB3, 0x36, 0x7E, 0x99, 0x83, + 0xA8, 0x96, 0xDC, 0x32, 0xFA, 0x20, 0xF8, 0xEB, +}; +static const uint8_t gmt_003_part5_b2_shared_secret[] = { + /* KA = KB */ + 0x6C, 0x89, 0x34, 0x73, 0x54, 0xDE, 0x24, 0x84, 0xC6, 0x0B, 0x4A, 0xB1, + 0xFD, 0xE4, 0xC6, 0xE5, +}; + +/* MAC Tests Data and Keys */ + +static const uint8_t mac_data_md5_key1[10] = { + 0x6B, 0x65, 0x79, /* key */ +}; + +static const uint8_t mac_data_md5_in1[] = { + 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, /* The quic */ + 0x6B, 0x20, 0x62, 0x72, 0x6F, 0x77, 0x6E, 0x20, /* k brown */ + 0x66, 0x6F, 0x78, 0x20, 0x6A, 0x75, 0x6D, 0x70, /* fox jump */ + 0x73, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x20, 0x74, /* s over t */ + 0x68, 0x65, 0x20, 0x6C, 0x61, 0x7A, 0x79, 0x20, /* he lazy */ + 0x64, 0x6F, 0x67, /* dog */ +}; + +static const uint8_t mac_data_md5_out1[] = { + 0x80, 0x07, 0x07, 0x13, 0x46, 0x3e, 0x77, 0x49, + 0xb9, 0x0c, 0x2d, 0xc2, 0x49, 0x11, 0xe2, 0x75 +}; + + +/* generated with scripts/digest_hmac.pl */ +static const uint8_t mac_data_sha1_key1[10] = { + 0x6B, 0x65, 0x79, /* key */ +}; + +static const uint8_t mac_data_sha1_in1[] = { + 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, /* The quic */ + 0x6B, 0x20, 0x62, 0x72, 0x6F, 0x77, 0x6E, 0x20, /* k brown */ + 0x66, 0x6F, 0x78, 0x20, 0x6A, 0x75, 0x6D, 0x70, /* fox jump */ + 0x73, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x20, 0x74, /* s over t */ + 0x68, 0x65, 0x20, 0x6C, 0x61, 0x7A, 0x79, 0x20, /* he lazy */ + 0x64, 0x6F, 0x67, /* dog */ +}; + +static const uint8_t mac_data_sha1_out1[] = { + 0xDE, 0x7C, 0x9B, 0x85, 0xB8, 0xB7, 0x8A, 0xA6, /* .|...... */ + 0xBC, 0x8A, 0x7A, 0x36, 0xF7, 0x0A, 0x90, 0x70, /* ..z6...p */ + 0x1C, 0x9D, 0xB4, 0xD9, /* .... */ +}; + +static const uint8_t mac_data_sha224_key1[24] = { + 0x6B, 0x65, 0x79, /* key */ +}; + +static const uint8_t mac_data_sha224_in1[] = { + 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, /* The quic */ + 0x6B, 0x20, 0x62, 0x72, 0x6F, 0x77, 0x6E, 0x20, /* k brown */ + 0x66, 0x6F, 0x78, 0x20, 0x6A, 0x75, 0x6D, 0x70, /* fox jump */ + 0x73, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x20, 0x74, /* s over t */ + 0x68, 0x65, 0x20, 0x6C, 0x61, 0x7A, 0x79, 0x20, /* he lazy */ + 0x64, 0x6F, 0x67, /* dog */ +}; + +static const uint8_t mac_data_sha224_out1[] = { + 0x88, 0xFF, 0x8B, 0x54, 0x67, 0x5D, 0x39, 0xB8, /* ...Tg]9. */ + 0xF7, 0x23, 0x22, 0xE6, 0x5F, 0xF9, 0x45, 0xC5, /* .#"._.E. */ + 0x2D, 0x96, 0x37, 0x99, 0x88, 0xAD, 0xA2, 0x56, /* -.7....V */ + 0x39, 0x74, 0x7E, 0x69, /* 9t~i */ +}; + + +static const uint8_t mac_data_sha256_key1[24] = { + 'Q', 'W', 'E', 'R', 'T', 'Y' +}; + +static const uint8_t mac_data_sha256_in1[] = { 'a', 'b', 'c' }; + +static const uint8_t mac_data_sha256_out1[] = { + 0xee, 0x2e, 0x5d, 0x9b, 0x51, 0xe2, 0x9c, 0x1d, + 0x49, 0xe9, 0xae, 0x6f, 0x0a, 0xcc, 0x15, 0x18, + 0xde, 0x1e, 0xa3, 0x88, 0x8e, 0xee, 0x48, 0xbb, + 0x82, 0x77, 0xe9, 0x09, 0x74, 0x4b, 0xa2, 0xf2 +}; + +/* generated with scripts/digest_hmac.pl */ +static const uint8_t mac_data_sha256_key2[24] = { + 0x6B, 0x65, 0x79, /* key */ +}; + +static const uint8_t mac_data_sha256_in2[] = { + 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, /* The quic */ + 0x6B, 0x20, 0x62, 0x72, 0x6F, 0x77, 0x6E, 0x20, /* k brown */ + 0x66, 0x6F, 0x78, 0x20, 0x6A, 0x75, 0x6D, 0x70, /* fox jump */ + 0x73, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x20, 0x74, /* s over t */ + 0x68, 0x65, 0x20, 0x6C, 0x61, 0x7A, 0x79, 0x20, /* he lazy */ + 0x64, 0x6F, 0x67, /* dog */ +}; + +static const uint8_t mac_data_sha256_out2[] = { + 0xF7, 0xBC, 0x83, 0xF4, 0x30, 0x53, 0x84, 0x24, /* ....0S.$ */ + 0xB1, 0x32, 0x98, 0xE6, 0xAA, 0x6F, 0xB1, 0x43, /* .2...o.C */ + 0xEF, 0x4D, 0x59, 0xA1, 0x49, 0x46, 0x17, 0x59, /* .MY.IF.Y */ + 0x97, 0x47, 0x9D, 0xBC, 0x2D, 0x1A, 0x3C, 0xD8, /* .G..-.<. */ +}; + +static const uint8_t mac_data_sha384_key1[32] = { + 0x6B, 0x65, 0x79, /* key */ +}; + +static const uint8_t mac_data_sha384_in1[] = { + 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, /* The quic */ + 0x6B, 0x20, 0x62, 0x72, 0x6F, 0x77, 0x6E, 0x20, /* k brown */ + 0x66, 0x6F, 0x78, 0x20, 0x6A, 0x75, 0x6D, 0x70, /* fox jump */ + 0x73, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x20, 0x74, /* s over t */ + 0x68, 0x65, 0x20, 0x6C, 0x61, 0x7A, 0x79, 0x20, /* he lazy */ + 0x64, 0x6F, 0x67, /* dog */ +}; + +static const uint8_t mac_data_sha384_out1[] = { + 0xD7, 0xF4, 0x72, 0x7E, 0x2C, 0x0B, 0x39, 0xAE, /* ..r~, .9. */ + 0x0F, 0x1E, 0x40, 0xCC, 0x96, 0xF6, 0x02, 0x42, /* ..@....B */ + 0xD5, 0xB7, 0x80, 0x18, 0x41, 0xCE, 0xA6, 0xFC, /* ....A... */ + 0x59, 0x2C, 0x5D, 0x3E, 0x1A, 0xE5, 0x07, 0x00, /* Y, ]>.... */ + 0x58, 0x2A, 0x96, 0xCF, 0x35, 0xE1, 0xE5, 0x54, /* X...5..T */ + 0x99, 0x5F, 0xE4, 0xE0, 0x33, 0x81, 0xC2, 0x37, /* ._..3..7 */ +}; + +static const uint8_t mac_data_sha512_key1[32] = { + 0x6B, 0x65, 0x79, /* key */ +}; + +static const uint8_t mac_data_sha512_in1[] = { + 0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, /* The quic */ + 0x6B, 0x20, 0x62, 0x72, 0x6F, 0x77, 0x6E, 0x20, /* k brown */ + 0x66, 0x6F, 0x78, 0x20, 0x6A, 0x75, 0x6D, 0x70, /* fox jump */ + 0x73, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x20, 0x74, /* s over t */ + 0x68, 0x65, 0x20, 0x6C, 0x61, 0x7A, 0x79, 0x20, /* he lazy */ + 0x64, 0x6F, 0x67, /* dog */ +}; + +static const uint8_t mac_data_sha512_out1[] = { + 0xB4, 0x2A, 0xF0, 0x90, 0x57, 0xBA, 0xC1, 0xE2, /* ....W... */ + 0xD4, 0x17, 0x08, 0xE4, 0x8A, 0x90, 0x2E, 0x09, /* ........ */ + 0xB5, 0xFF, 0x7F, 0x12, 0xAB, 0x42, 0x8A, 0x4F, /* .....B.O */ + 0xE8, 0x66, 0x53, 0xC7, 0x3D, 0xD2, 0x48, 0xFB, /* .fS.=.H. */ + 0x82, 0xF9, 0x48, 0xA5, 0x49, 0xF7, 0xB7, 0x91, /* ..H.I... */ + 0xA5, 0xB4, 0x19, 0x15, 0xEE, 0x4D, 0x1E, 0xC3, /* .....M.. */ + 0x93, 0x53, 0x57, 0xE4, 0xE2, 0x31, 0x72, 0x50, /* .SW..1rP */ + 0xD0, 0x37, 0x2A, 0xFA, 0x2E, 0xBE, 0xEB, 0x3A, /* .7.....: */ +}; + +/* + * First example from + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-224.pdf + */ +static const uint8_t mac_data_sha3_224_key1[28] = { + 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, +}; +static const uint8_t mac_data_sha3_224_in1[] = { + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x6c, 0x65, + 0x6e, 0x3c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, + 0x65, 0x6e, +}; +static const uint8_t mac_data_sha3_224_out1[] = { + 0x33, 0x2c, 0xfd, 0x59, 0x34, 0x7f, 0xdb, 0x8e, + 0x57, 0x6e, 0x77, 0x26, 0x0b, 0xe4, 0xab, 0xa2, + 0xd6, 0xdc, 0x53, 0x11, 0x7b, 0x3b, 0xfb, 0x52, + 0xc6, 0xd1, 0x8c, 0x04, +}; + +/* + * First example from + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf + */ +static const uint8_t mac_data_sha3_256_key1[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, +}; +static const uint8_t mac_data_sha3_256_in1[] = { + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x6c, 0x65, + 0x6e, 0x3c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, + 0x65, 0x6e, +}; +static const uint8_t mac_data_sha3_256_out1[] = { + 0x4f, 0xe8, 0xe2, 0x02, 0xc4, 0xf0, 0x58, 0xe8, + 0xdd, 0xdc, 0x23, 0xd8, 0xc3, 0x4e, 0x46, 0x73, + 0x43, 0xe2, 0x35, 0x55, 0xe2, 0x4f, 0xc2, 0xf0, + 0x25, 0xd5, 0x98, 0xf5, 0x58, 0xf6, 0x72, 0x05, +}; + +/* + * First example from + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf + */ +static const uint8_t mac_data_sha3_384_key1[48] = { + 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, +}; +static const uint8_t mac_data_sha3_384_in1[] = { + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x6c, 0x65, + 0x6e, 0x3c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, + 0x65, 0x6e, +}; +static const uint8_t mac_data_sha3_384_out1[] = { + 0xd5, 0x88, 0xa3, 0xc5, 0x1f, 0x3f, 0x2d, 0x90, + 0x6e, 0x82, 0x98, 0xc1, 0x19, 0x9a, 0xa8, 0xff, + 0x62, 0x96, 0x21, 0x81, 0x27, 0xf6, 0xb3, 0x8a, + 0x90, 0xb6, 0xaf, 0xe2, 0xc5, 0x61, 0x77, 0x25, + 0xbc, 0x99, 0x98, 0x7f, 0x79, 0xb2, 0x2a, 0x55, + 0x7b, 0x65, 0x20, 0xdb, 0x71, 0x0b, 0x7f, 0x42, +}; + +/* + * First example from + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf + */ +static const uint8_t mac_data_sha3_512_key1[64] = { + 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, +}; +static const uint8_t mac_data_sha3_512_in1[] = { + 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x6b, 0x65, 0x79, 0x6c, 0x65, + 0x6e, 0x3c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x6c, + 0x65, 0x6e, +}; +static const uint8_t mac_data_sha3_512_out1[] = { + 0x4e, 0xfd, 0x62, 0x9d, 0x6c, 0x71, 0xbf, 0x86, + 0x16, 0x26, 0x58, 0xf2, 0x99, 0x43, 0xb1, 0xc3, + 0x08, 0xce, 0x27, 0xcd, 0xfa, 0x6d, 0xb0, 0xd9, + 0xc3, 0xce, 0x81, 0x76, 0x3f, 0x9c, 0xbc, 0xe5, + 0xf7, 0xeb, 0xe9, 0x86, 0x80, 0x31, 0xdb, 0x1a, + 0x8f, 0x8e, 0xb7, 0xb6, 0xb9, 0x5e, 0x5c, 0x5e, + 0x3f, 0x65, 0x7a, 0x89, 0x96, 0xc8, 0x6a, 0x2f, + 0x65, 0x27, 0xe3, 0x07, 0xf0, 0x21, 0x31, 0x96, +}; + +/* + * SM3 HMAC + * GM/T 0042-2015 + * Section D.3 Test vector 1 + */ +static const uint8_t mac_data_sm3_d31_in[112] = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomn" + "opnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmn" + "lmnomnopnopq"; + +static const uint8_t mac_data_sm3_d31_key[] = { + 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, +}; + +static const uint8_t mac_data_sm3_d31_out[] = { + 0xca, 0x05, 0xe1, 0x44, 0xed, 0x05, 0xd1, 0x85, + 0x78, 0x40, 0xd1, 0xf3, 0x18, 0xa4, 0xa8, 0x66, + 0x9e, 0x55, 0x9f, 0xc8, 0x39, 0x1f, 0x41, 0x44, + 0x85, 0xbf, 0xdf, 0x7b, 0xb4, 0x08, 0x96, 0x3a, +}; + +/* + * SM3 HMAC + * GM/T 0042-2015 + * Section D.3 Test vector 2 + */ +static const uint8_t mac_data_sm3_d32_in[] = { + 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 +}; + +static const uint8_t mac_data_sm3_d32_key[] = { + 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, +}; + +static const uint8_t mac_data_sm3_d32_out[] = { + 0x22, 0x0b, 0xf5, 0x79, 0xde, 0xd5, 0x55, 0x39, + 0x3f, 0x01, 0x59, 0xf6, 0x6c, 0x99, 0x87, 0x78, + 0x22, 0xa3, 0xec, 0xf6, 0x10, 0xd1, 0x55, 0x21, + 0x54, 0xb4, 0x1d, 0x44, 0xb9, 0x4d, 0xb3, 0xae, +}; + +/* AES-CBC-MAC */ +static const uint8_t mac_cbc_vect1_key[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ +}; + +static const uint8_t mac_cbc_vect1_data[] = { + 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, 0x62, /* Cipher b */ + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x63, 0x68, 0x61, /* lock cha */ + 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x28, 0x43, /* ining (C */ + 0x42, 0x43, 0x29, 0x20, 0x69, 0x73, 0x20, 0x61, /* BC) is a */ + 0x20, 0x63, 0x6F, 0x6D, 0x6D, 0x6F, 0x6E, 0x20, /* common */ + 0x63, 0x68, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, /* chaining */ + 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x20, 0x69, 0x6E, /* mode in */ + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, /* which t */ + 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, /* he previ */ + 0x6F, 0x75, 0x73, 0x20, 0x62, 0x6C, 0x6F, 0x63, /* ous bloc */ + 0x6B, 0x27, 0x73, 0x20, 0x63, 0x69, 0x70, 0x68, /* k's ciph */ + 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x20, 0x69, /* ertext i */ + 0x73, 0x20, 0x78, 0x6F, 0x72, 0x65, 0x64, 0x20, /* s xored */ + 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, /* with the */ + 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, /* current */ + 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x27, 0x73, /* block's */ + 0x20, 0x70, 0x6C, 0x61, 0x69, 0x6E, 0x74, 0x65, /* plainte */ + 0x78, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6F, 0x72, /* xt befor */ + 0x65, 0x20, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, /* e encryp */ + 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x2E, 0x2E, 0x2E, /* tion.... */ +}; + +static const uint8_t mac_cbc_vect1_out[] = { + 0xC9, 0x6E, 0x83, 0x7E, 0x35, 0xC8, 0xA7, 0xA0, /* .n.~5... */ + 0x33, 0xA3, 0xB1, 0x4B, 0x5A, 0x92, 0x51, 0x2E, /* 3..KZ.Q. */ +}; + +/* DES-CBC-MAC */ +static const uint8_t mac_cbc_vect2_key[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ +}; + +#define mac_cbc_vect2_data mac_cbc_vect1_data +static const uint8_t mac_cbc_vect2_out[] = { + 0xE9, 0x41, 0x46, 0x30, 0x69, 0x32, 0xBD, 0xD6, /* .AF0i2.. */ +}; + +/* DES3-CBC-MAC */ +static const uint8_t mac_cbc_vect3_key[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, /* 12345678 */ +}; + +#define mac_cbc_vect3_data mac_cbc_vect2_data +static const uint8_t mac_cbc_vect3_out[] = { + 0x1C, 0x17, 0xB7, 0xB5, 0x9F, 0x54, 0x9C, 0x63, /* .....T.c */ +}; + +/* AES-CBC-MAC PKCS#5 pad*/ +static const uint8_t mac_cbc_vect4_key[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ +}; + +#define mac_cbc_vect4_data mac_cbc_vect1_data +static const uint8_t mac_cbc_vect4_out[] = { + 0x0B, 0x46, 0xC7, 0xA2, 0xE1, 0x5A, 0xE2, 0x23, /* .F...Z.# */ + 0x83, 0x34, 0x1C, 0x86, 0x53, 0xF8, 0x51, 0x24, /* .4..S.Q$ */ +}; + +/* DES-CBC-MAC PKCS#5 pad*/ +static const uint8_t mac_cbc_vect5_key[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ +}; + +#define mac_cbc_vect5_data mac_cbc_vect1_data +static const uint8_t mac_cbc_vect5_out[] = { + 0x30, 0x81, 0x4F, 0x42, 0x03, 0x7E, 0xD8, 0xA9, /* 0.OB.~.. */ +}; + +/* DES3-CBC-MAC PKCS#5 pad*/ +static const uint8_t mac_cbc_vect6_key[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, /* 12345678 */ +}; + +#define mac_cbc_vect6_data mac_cbc_vect1_data +static const uint8_t mac_cbc_vect6_out[] = { + 0x6E, 0x37, 0x6E, 0x14, 0x5E, 0x21, 0xDD, 0xF8, /* n7n.^!.. */ +}; + +/* AES-CBC-MAC PKCS#5 pad*/ +#define mac_cbc_vect7_key mac_cbc_vect4_key +static const uint8_t mac_cbc_vect7_data[] = { + 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, 0x62, /* Cipher b */ + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x63, 0x68, 0x61, /* lock cha */ + 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x28, 0x43, /* ining (C */ + 0x42, 0x43, 0x29, 0x20, 0x69, 0x73, 0x20, 0x61, /* BC) is a */ + 0x20, 0x63, 0x6F, 0x6D, 0x6D, 0x6F, 0x6E, 0x20, /* common */ + 0x63, 0x68, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, /* chaining */ + 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x20, 0x69, 0x6E, /* mode in */ + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, /* which t */ + 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x76, 0x69, /* he previ */ + 0x6F, 0x75, 0x73, 0x20, 0x62, 0x6C, 0x6F, 0x63, /* ous bloc */ + 0x6B, 0x27, 0x73, 0x20, 0x63, 0x69, 0x70, 0x68, /* k's ciph */ + 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x20, 0x69, /* ertext i */ + 0x73, 0x20, 0x78, 0x6F, 0x72, 0x65, 0x64, 0x20, /* s xored */ + 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, /* with the */ + 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, /* current */ + 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x27, 0x73, /* block's */ + 0x20, 0x70, 0x6C, 0x61, 0x69, 0x6E, 0x74, 0x65, /* plainte */ + 0x78, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6F, 0x72, /* xt befor */ + 0x65, 0x20, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, /* e encryp */ + 0x74, 0x69, 0x6F, 0x6E, 0x2E, /* tion. */ +}; + +static const uint8_t mac_cbc_vect7_out[] = { + 0xFD, 0x89, 0x35, 0xB3, 0x93, 0x7F, 0xBB, 0xA2, /* ..5..... */ + 0xFB, 0x65, 0x60, 0xC4, 0x0A, 0x62, 0xA0, 0xF9, /* .e`..b.. */ +}; + +/* DES-CBC-MAC PKCS#5 pad*/ +#define mac_cbc_vect8_key mac_cbc_vect5_key +#define mac_cbc_vect8_data mac_cbc_vect7_data +static const uint8_t mac_cbc_vect8_out[] = { + 0x02, 0x2A, 0xA8, 0x2E, 0x47, 0xC6, 0xBB, 0x7C, /* ....G..| */ +}; + +/* DES3-CBC-MAC PKCS#5 pad*/ +#define mac_cbc_vect9_key mac_cbc_vect6_key +#define mac_cbc_vect9_data mac_cbc_vect7_data +static const uint8_t mac_cbc_vect9_out[] = { + 0xD4, 0xF7, 0x3E, 0x27, 0x78, 0x0E, 0x1C, 0x79, /* ..>'x..y */ +}; + +/* + * DES3-CBC-MAC, with key size of 112bit + * out obtained with: + * echo -n "Cipher block chaining (CBC) is a common chaining mode in which the previous block's ciphertext is xored with the current block's plaintext before encryption...."|openssl enc -iv 0 -des3 -K 303132333435363738394142434445463031323334353637 |xxd + */ +/* DES3-CBC-MAC PKCS#5 pad*/ +static const uint8_t mac_cbc_vect10_key[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */ + 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, /* 89ABCDEF */ +}; +#define mac_cbc_vect10_data mac_cbc_vect1_data +static const uint8_t mac_cbc_vect10_out[] = { + 0x30, 0x92, 0x60, 0x99, 0x66, 0xac, 0x8c, 0xa6, +}; + + +/* + * AES-CMAC + * Test vectors from + * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf + */ + +/* AES-128 */ +static const uint8_t mac_cmac_vect1_key[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; + +static const uint8_t mac_cmac_vect1_out[] = { + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 +}; + +#define mac_cmac_vect2_key mac_cmac_vect1_key +static const uint8_t mac_cmac_vect2_data[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a +}; + +static const uint8_t mac_cmac_vect2_out[] = { + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c +}; + +#define mac_cmac_vect3_key mac_cmac_vect1_key +static const uint8_t mac_cmac_vect3_data[] = { + 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 +}; + +static const uint8_t mac_cmac_vect3_out[] = { + 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 +}; + +#define mac_cmac_vect4_key mac_cmac_vect1_key +static const uint8_t mac_cmac_vect4_data[] = { + 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 +}; + +static const uint8_t mac_cmac_vect4_out[] = { + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe +}; + +/* AES-192 */ +static const uint8_t mac_cmac_vect5_key[] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; + +static const uint8_t mac_cmac_vect5_out[] = { + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 +}; + + +#define mac_cmac_vect6_key mac_cmac_vect5_key +static const uint8_t mac_cmac_vect6_data[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a +}; + +static const uint8_t mac_cmac_vect6_out[] = { + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 +}; + +#define mac_cmac_vect7_key mac_cmac_vect5_key +static const uint8_t mac_cmac_vect7_data[] = { + 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 +}; + +static const uint8_t mac_cmac_vect7_out[] = { + 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad, + 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e +}; + +#define mac_cmac_vect8_key mac_cmac_vect5_key +static const uint8_t mac_cmac_vect8_data[] = { + 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 +}; + +static const uint8_t mac_cmac_vect8_out[] = { + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 +}; + +/* AES-256 */ +static const uint8_t mac_cmac_vect9_key[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; + +static const uint8_t mac_cmac_vect9_out[] = { + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 +}; + +#define mac_cmac_vect10_key mac_cmac_vect9_key +static const uint8_t mac_cmac_vect10_data[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a +}; + +static const uint8_t mac_cmac_vect10_out[] = { + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c +}; + +#define mac_cmac_vect11_key mac_cmac_vect9_key +static const uint8_t mac_cmac_vect11_data[] = { + 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 +}; + +static const uint8_t mac_cmac_vect11_out[] = { + 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2, + 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6 +}; + +#define mac_cmac_vect12_key mac_cmac_vect9_key +static const uint8_t mac_cmac_vect12_data[] = { + 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 +}; + +static const uint8_t mac_cmac_vect12_out[] = { + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 +}; + +/* + * DES3-CMAC + * Test vectors from + * https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/cavp-testing-block-cipher-modes + */ + +/* Three Key TDEA */ + +/* CMACGenTDES3.rsp Count = 8 */ +static const uint8_t mac_des3_cmac_vect1_key[] = { + 0xf8, 0x7c, 0x4c, 0x3d, 0xf7, 0x1f, 0xd9, 0x8c, + 0xe5, 0x32, 0xf4, 0x1f, 0xfe, 0x31, 0x58, 0x20, + 0x51, 0x4f, 0xad, 0x7c, 0x7a, 0xae, 0x2f, 0x46 +}; + +static const uint8_t mac_des3_cmac_vect1_out[] = { + 0x19, 0xfb, 0xd3, 0xdc, 0x15, 0x4b, 0xc1, 0x39 +}; + +/* CMACVerTDES3.rsp Count = 25 */ +static const uint8_t mac_des3_cmac_vect2_key[] = { + 0xa2, 0x52, 0xda, 0xad, 0x73, 0x1c, 0x10, 0x97, + 0x45, 0x46, 0x38, 0xab, 0xf1, 0xf8, 0x40, 0x6d, + 0xd0, 0xae, 0xcb, 0xc7, 0x8c, 0x01, 0x8a, 0xa8 +}; + +static const uint8_t mac_des3_cmac_vect2_data[] = { + 0x1d, 0x99, 0x92, 0x0c, 0x59, 0x73, 0x99, 0x7c, + 0xc0, 0x59, 0xd4, 0x42, 0x46, 0x7f, 0x76, 0x59 +}; + +static const uint8_t mac_des3_cmac_vect2_out[] = { + 0x7c, 0x14, 0x90, 0x12, 0xd6, 0x12, 0x0e, 0xc6 +}; + +/* CMACVerTDES3.rsp Count = 40 */ +static const uint8_t mac_des3_cmac_vect3_key[] = { + 0xf2, 0x45, 0xf8, 0xd5, 0x85, 0x13, 0x3e, 0x31, + 0x04, 0xd3, 0xfb, 0xc2, 0xd0, 0xec, 0x80, 0xf4, + 0x3e, 0xce, 0x1f, 0xd9, 0xa2, 0x8f, 0x5e, 0xd5 +}; + +static const uint8_t mac_des3_cmac_vect3_data[] = { + 0x99, 0x3d, 0xac, 0xbc, 0x22, 0x1e, 0xd3, 0x2a, + 0x6f, 0xb3, 0xd9, 0x05, 0x59, 0xc6, 0x74, 0xfb, + 0x68, 0x08, 0x9e, 0xea, 0x8d, 0xf9, 0xea, 0xec, + 0x14, 0x07, 0x19, 0x91, 0xd4, 0xfa, 0xe8, 0x6b +}; + +static const uint8_t mac_des3_cmac_vect3_out[] = { + 0x25, 0xfb, 0x96, 0x2e, 0xa9, 0x3b, 0x89, 0x7f +}; + +/* CMACVerTDES3.rsp Count = 57 */ +static const uint8_t mac_des3_cmac_vect4_key[] = { + 0xc2, 0x9e, 0xc1, 0x2c, 0xa4, 0x83, 0xc2, 0x61, + 0xc1, 0xfe, 0xa7, 0x34, 0xf4, 0xad, 0x08, 0x10, + 0x8a, 0xc2, 0x75, 0x02, 0x68, 0x2c, 0x67, 0xdc +}; + +static const uint8_t mac_des3_cmac_vect4_data[] = { + 0x19, 0x5c, 0x0b, 0x84, 0xba, 0xac, 0xc8, 0x8a, 0x33 +}; + +static const uint8_t mac_des3_cmac_vect4_out[] = { + 0xe3, 0xeb, 0xff, 0x96, 0x12, 0x49, 0x42, 0x45 +}; + +/* Two Key TDEA */ + +/* CMACVerTDES2.rsp Count = 55 */ +static const uint8_t mac_des3_cmac_vect5_key[] = { + 0xb6, 0xe0, 0xe5, 0x80, 0x20, 0x92, 0x34, 0x94, + 0xdc, 0x76, 0x80, 0x08, 0xe9, 0x98, 0x8f, 0xc2, + 0xb6, 0xe0, 0xe5, 0x80, 0x20, 0x92, 0x34, 0x94 +}; + +static const uint8_t mac_des3_cmac_vect5_out[] = { + 0x5c, 0x73, 0x43, 0xa4, 0x16, 0x8a, 0x37, 0x0f +}; + +/* CMACVerTDES2.rsp Count = 101 */ +static const uint8_t mac_des3_cmac_vect6_key[] = { + 0x61, 0xc4, 0xec, 0x20, 0x70, 0xe9, 0xbf, 0x2a, + 0xec, 0x02, 0xd0, 0xb0, 0xe9, 0x9e, 0x8f, 0x01, + 0x61, 0xc4, 0xec, 0x20, 0x70, 0xe9, 0xbf, 0x2a +}; + +static const uint8_t mac_des3_cmac_vect6_data[] = { + 0xff, 0xbd, 0x75, 0x61, 0x93, 0x91, 0x88, 0xbc +}; + +static const uint8_t mac_des3_cmac_vect6_out[] = { + 0x55, 0xa0, 0x4c, 0x23, 0xd5, 0xb4, 0x3e, 0x49 +}; + +/* CMACVerTDES2.rsp Count = 223 */ +static const uint8_t mac_des3_cmac_vect7_key[] = { + 0xb6, 0xc8, 0x9d, 0x79, 0x85, 0x70, 0xab, 0x6e, + 0xcd, 0x54, 0x54, 0xc1, 0xa7, 0x29, 0xf2, 0xd9, + 0xb6, 0xc8, 0x9d, 0x79, 0x85, 0x70, 0xab, 0x6e +}; + +static const uint8_t mac_des3_cmac_vect7_data[] = { + 0x83, 0xd2, 0xc3, 0x86, 0xe8, 0x73, 0xad, 0xa1, + 0x49, 0x76, 0x71, 0x2b, 0x67, 0x27, 0x7c +}; + +static const uint8_t mac_des3_cmac_vect7_out[] = { + 0x03, 0xbf, 0x2c, 0x9f, 0x49, 0x6e, 0x4f, 0xa9 +}; + +/* CMACVerTDES2.rsp Count = 358 */ +static const uint8_t mac_des3_cmac_vect8_key[] = { + 0xe0, 0x85, 0xab, 0xa8, 0x58, 0x83, 0xc7, 0x5d, + 0x62, 0x76, 0x75, 0x7a, 0x54, 0x31, 0xc8, 0x37, + 0xe0, 0x85, 0xab, 0xa8, 0x58, 0x83, 0xc7, 0x5d +}; + +static const uint8_t mac_des3_cmac_vect8_data[] = { + 0xb0, 0x53, 0x76, 0xdb, 0x71, 0xce, 0x06, 0x66, + 0x63, 0x81, 0x95, 0x03, 0xeb, 0x0a, 0xd5, 0xef, + 0x63, 0x2d, 0x0c, 0xa4, 0x6c, 0xd4, 0x0e, 0xfe, + 0x86, 0x54, 0x69, 0x9d, 0xde, 0xf2, 0xdf, 0x8a, + 0x66, 0xa6, 0x19, 0x1d, 0x2b, 0x1f, 0x99, 0x1e +}; + +static const uint8_t mac_des3_cmac_vect8_out[] = { + 0xd5, 0xe7, 0x9f, 0x0b, 0x3c, 0x67, 0xd7, 0xf3 +}; + +/* X25519 test vectors (RFC 7748 - 6.1) */ +static const uint8_t x25519_alice_private[] = { + 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, + 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, + 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a, + 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a +}; +static const uint8_t x25519_alice_public[] = { + 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, + 0x74, 0x8b, 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, + 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a, 0xf4, + 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a +}; +static const uint8_t x25519_bob_private[] = { + 0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, + 0x79, 0xe1, 0x7f, 0x8b, 0x83, 0x80, 0x0e, 0xe6, + 0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 0xb6, 0xfd, + 0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb +}; +static const uint8_t x25519_bob_public[] = { + 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, + 0xd3, 0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, + 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d, + 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f +}; +static const uint8_t x25519_shared_secret[] = { + 0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, + 0x72, 0x8e, 0x3b, 0xf4, 0x80, 0x35, 0x0f, 0x25, + 0xe0, 0x7e, 0x21, 0xc9, 0x47, 0xd1, 0x9e, 0x33, + 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16, 0x17, 0x42 +}; + +/* Ed25519 test vectors (RFC 8032 - 7.1) */ +static const uint8_t ed25519_rfc_8032_7_1_private[] = { + 0x83, 0x3f, 0xe6, 0x24, 0x9, 0x23, 0x7b, 0x9d, + 0x62, 0xec, 0x77, 0x58, 0x75, 0x20, 0x91, 0x1e, + 0x9a, 0x75, 0x9c, 0xec, 0x1d, 0x19, 0x75, 0x5b, + 0x7d, 0xa9, 0x01, 0xb9, 0x6d, 0xca, 0x3d, 0x42 +}; +static const uint8_t ed25519_rfc_8032_7_1_public[] = { + 0xec, 0x17, 0x2b, 0x93, 0xad, 0x5e, 0x56, 0x3b, + 0xf4, 0x93, 0x2c, 0x70, 0xe1, 0x24, 0x50, 0x34, + 0xc3, 0x54, 0x67, 0xef, 0x2e, 0xfd, 0x4d, 0x64, + 0xeb, 0xf8, 0x19, 0x68, 0x34, 0x67, 0xe2, 0xbf +}; +static const uint8_t ed25519_rfc_8032_7_1_ptx[] = { + 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, 0xe, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f +}; +static const uint8_t ed25519_rfc_8032_7_1_out[] = { + 0xdc, 0x2a, 0x44, 0x59, 0xe7, 0x36, 0x96, 0x33, + 0xa5, 0x2b, 0x1b, 0xf2, 0x77, 0x83, 0x9a, 0x0, + 0x20, 0x10, 0x09, 0xa3, 0xef, 0xbf, 0x3e, 0xcb, + 0x69, 0xbe, 0xa2, 0x18, 0x6c, 0x26, 0xb5, 0x89, + 0x09, 0x35, 0x1f, 0xc9, 0xac, 0x90, 0xb3, 0xec, + 0xfd, 0xfb, 0xc7, 0xc6, 0x64, 0x31, 0xe0, 0x30, + 0x3d, 0xca, 0x17, 0x9c, 0x13, 0x8a, 0xc1, 0x7a, + 0xd9, 0xbe, 0xf1, 0x17, 0x73, 0x31, 0xa7, 0x4 +}; + +/* Ed25519 test vectors (RFC 8032 - 7.2) */ +static const uint8_t ed25519ctx_rfc_8032_7_2_private[] = { + 0x03, 0x05, 0x33, 0x4e, 0x38, 0x1a, 0xf7, 0x8f, + 0x14, 0x1c, 0xb6, 0x66, 0xf6, 0x19, 0x9f, 0x57, + 0xbc, 0x34, 0x95, 0x33, 0x5a, 0x25, 0x6a, 0x95, + 0xbd, 0x2a, 0x55, 0xbf, 0x54, 0x66, 0x63, 0xf6 +}; +static const uint8_t ed25519ctx_rfc_8032_7_2_public[] = { + 0xdf, 0xc9, 0x42, 0x5e, 0x4f, 0x96, 0x8f, 0x7f, + 0x0c, 0x29, 0xf0, 0x25, 0x9c, 0xf5, 0xf9, 0xae, + 0xd6, 0x85, 0x1c, 0x2b, 0xb4, 0xad, 0x8b, 0xfb, + 0x86, 0x0c, 0xfe, 0xe0, 0xab, 0x24, 0x82, 0x92 +}; +static const uint8_t ed25519ctx_rfc_8032_7_2_ptx[] = { + 0xf7, 0x26, 0x93, 0x6d, 0x19, 0xc8, 0x00, 0x49, + 0x4e, 0x3f, 0xda, 0xff, 0x20, 0xb2, 0x76, 0xa8 +}; +static const uint8_t ed25519ctx_rfc_8032_7_2_out[] = { + 0x55, 0xa4, 0xcc, 0x2f, 0x70, 0xa5, 0x4e, 0x4, + 0x28, 0x8c, 0x5f, 0x4c, 0xd1, 0xe4, 0x5a, 0x7b, + 0xb5, 0x20, 0xb3, 0x62, 0x92, 0x91, 0x18, 0x76, + 0xca, 0xda, 0x73, 0x23, 0x19, 0x8d, 0xd8, 0x7a, + 0x8b, 0x36, 0x95, 0x0b, 0x95, 0x13, 0x00, 0x22, + 0x90, 0x7a, 0x7f, 0xb7, 0xc4, 0xe9, 0xb2, 0xd5, + 0xf6, 0xcc, 0xa6, 0x85, 0xa5, 0x87, 0xb4, 0xb2, + 0x1f, 0x4b, 0x88, 0x8e, 0x4e, 0x7e, 0xdb, 0xd +}; +static const uint8_t ed25519ctx_rfc_8032_7_2_context[] = { + 0x66, 0x6f, 0x6f +}; + +/* Ed25519 test vectors (RFC 8032 - 7.3) */ +static const uint8_t ed25519ph_rfc_8032_7_3_private[] = { + 0x83, 0x3f, 0xe6, 0x24, 0x09, 0x23, 0x7b, 0x9d, + 0x62, 0xec, 0x77, 0x58, 0x75, 0x20, 0x91, 0x1e, + 0x9a, 0x75, 0x9c, 0xec, 0x1d, 0x19, 0x75, 0x5b, + 0x7d, 0xa9, 0x01, 0xb9, 0x6d, 0xca, 0x3d, 0x42 +}; +static const uint8_t ed25519ph_rfc_8032_7_3_public[] = { + 0xec, 0x17, 0x2b, 0x93, 0xad, 0x5e, 0x56, 0x3b, + 0xf4, 0x93, 0x2c, 0x70, 0xe1, 0x24, 0x50, 0x34, + 0xc3, 0x54, 0x67, 0xef, 0x2e, 0xfd, 0x4d, 0x64, + 0xeb, 0xf8, 0x19, 0x68, 0x34, 0x67, 0xe2, 0xbf +}; +static const uint8_t ed25519ph_rfc_8032_7_3_ptx[] = { + 0x61, 0x62, 0x63 +}; +static const uint8_t ed25519ph_rfc_8032_7_3_out[] = { + 0x98, 0xa7, 0x02, 0x22, 0xf0, 0xb8, 0x12, 0x1a, + 0xa9, 0xd3, 0x0f, 0x81, 0x3d, 0x68, 0x3f, 0x80, + 0x9e, 0x46, 0x2b, 0x46, 0x9c, 0x7f, 0xf8, 0x76, + 0x39, 0x49, 0x9b, 0xb9, 0x4e, 0x6d, 0xae, 0x41, + 0x31, 0xf8, 0x50, 0x42, 0x46, 0x3c, 0x2a, 0x35, + 0x5a, 0x20, 0x03, 0xd0, 0x62, 0xad, 0xf5, 0xaa, + 0xa1, 0x0b, 0x8c, 0x61, 0xe6, 0x36, 0x06, 0x2a, + 0xaa, 0xd1, 0x1c, 0x2a, 0x26, 0x08, 0x34, 0x06 +}; + +/* + * RSA AES wrapped key + * Test data generated as follows: + * - generate target AES-256 key (target.aes) + * - generate wrapping RSA keypair (we use ac_rsassa_vect2 in this case) + * - generate intermediate AES-256 KEK + * - wrap target key using KEK (RFC 5649): + * openssl enc \ + * -id-aes256-wrap-pad \ + * -iv A65959A6 \ + * -K $( hexdump -v -e '/1 "%02x"' < kek.aes ) \ + * -in target.aes \ + * -out target_wrapped.enc + * - encrypt KEK using wrapping RSA public key: + * openssl pkeyutl \ + * -encrypt \ + * -pubin \ + * -inkey vect2_pub.key \ + * -in kek.aes -out kek_wrapped.enc \ + * -pkeyopt rsa_padding_mode:oaep \ + * -pkeyopt rsa_oaep_md:sha256 \ + * -pkeyopt rsa_mgf1_md:sha256 + * + * - concatenate both: + * cat kek_wrapped.enc target_wrapped.enc > pkcs11_rsa_aes_wrapped_key + */ +static const uint8_t pkcs11_rsa_aes_wrapped_key[] = { + 0x5c, 0x1f, 0x2d, 0x4f, 0xe9, 0x72, 0xf2, 0x67, + 0xc7, 0x82, 0x78, 0x28, 0x15, 0xe0, 0x25, 0x75, + 0xc5, 0xf0, 0x5c, 0x0b, 0x11, 0x78, 0xbc, 0x3e, + 0xf7, 0x3d, 0x8e, 0x33, 0x44, 0x2a, 0xb5, 0x81, + 0xc6, 0x4c, 0x06, 0xea, 0x8a, 0xfa, 0x34, 0x86, + 0x17, 0x07, 0x87, 0x80, 0x0f, 0x8e, 0x47, 0xe6, + 0xaf, 0x48, 0x6c, 0x8b, 0x29, 0x98, 0xb4, 0x69, + 0xe2, 0x91, 0x03, 0x51, 0xea, 0x90, 0xa4, 0x66, + 0x5c, 0x07, 0xa2, 0xa3, 0x4c, 0x02, 0x3b, 0x71, + 0x0c, 0xf2, 0x57, 0x4a, 0x4f, 0x63, 0x14, 0xce, + 0x63, 0x17, 0x15, 0xa4, 0x1d, 0x4e, 0x38, 0x53, + 0x56, 0x11, 0x56, 0xcc, 0x2e, 0x80, 0xb3, 0xc1, + 0xf2, 0x1a, 0x54, 0xd5, 0x5b, 0x80, 0xb5, 0xd8, + 0xd7, 0x29, 0x37, 0x76, 0x79, 0xbd, 0xa9, 0xfa, + 0x8f, 0x8c, 0x8d, 0x8d, 0xd8, 0xe2, 0x94, 0xe5, + 0xf0, 0x62, 0x62, 0x0c, 0x8c, 0x28, 0x5e, 0x77, + 0xb6, 0xf3, 0xa9, 0x64, 0x76, 0xe6, 0xd7, 0x9f, + 0x0b, 0xe7, 0x17, 0xba, 0x23, 0xe5, 0x13, 0x6f, + 0xf8, 0x0f, 0x51, 0xd6, 0x2a, 0x2c, 0x75, 0xb4, + 0xd8, 0x1b, 0x13, 0xc8, 0xd4, 0x7f, 0x2a, 0x2c, + 0x2c, 0x34, 0x58, 0x6e, 0x26, 0x7a, 0x6c, 0xa9, + 0x77, 0x18, 0xb1, 0xbd, 0xb5, 0x0a, 0xdd, 0x46, + 0xd6, 0x31, 0x80, 0x51, 0xc1, 0x7c, 0x6b, 0x74, + 0x4d, 0x91, 0x9e, 0xbf, 0xce, 0x3a, 0x39, 0xbb, + 0x79, 0xab, 0x5f, 0x9e, 0xb5, 0xab, 0x76, 0x37, + 0xea, 0x11, 0xf6, 0xe1, 0x50, 0xcb, 0x74, 0xf9, + 0x1c, 0x91, 0x5f, 0xf6, 0xc9, 0xd5, 0x9b, 0xc1, + 0xfc, 0x76, 0x5a, 0x58, 0xfb, 0xaa, 0x88, 0xcc, + 0xaa, 0x4e, 0x31, 0x8e, 0xe5, 0x3d, 0x22, 0xc3, + 0xcb, 0x21, 0x3b, 0xd5, 0x95, 0x3a, 0x09, 0xd8, + 0xce, 0x7f, 0x39, 0x9b, 0x38, 0x8c, 0x51, 0x61, + 0x87, 0x18, 0x7e, 0xf5, 0x5a, 0x0b, 0x70, 0x2b, + 0x35, 0xd3, 0x18, 0x0f, 0xc9, 0xe7, 0xc4, 0xf3, + 0x9d, 0x14, 0x20, 0x85, 0x64, 0xb1, 0xfb, 0x3b, + 0xc0, 0xc1, 0x21, 0x08, 0x8f, 0x2f, 0x3f, 0xb9, + 0xde, 0xe9, 0x11, 0x57, 0xaf, 0x35, 0x65, 0xa0, + 0x5b, 0x9c, 0x62, 0xfb, 0xc9, 0x80, 0x8b, 0xcc +}; + +/* + * Sample AES-256 key + */ +static const uint8_t pkcs11_rsa_aes_tagret_key[] = { + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x20, 0x41, 0x45, 0x53, 0x20, + 0x32, 0x35, 0x36, 0x20, 0x6b, 0x65, 0x79, 0x0a +}; + +#endif /*XTEST_4000_DATA_H*/ diff --git a/optee/optee_test/host/xtest/regression_4100.c b/optee/optee_test/host/xtest/regression_4100.c new file mode 100644 index 0000000..8c13b43 --- /dev/null +++ b/optee/optee_test/host/xtest/regression_4100.c @@ -0,0 +1,2770 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018, Linaro Limited */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xtest_test.h" +#include "xtest_helpers.h" + +static TEEC_Result cmd_new_var(ADBG_Case_t *c, TEEC_Session *s, + uint32_t num_bits, uint32_t *handle) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = num_bits; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_NEW_VAR, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + if (!res) + *handle = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_new_fmm_var(ADBG_Case_t *c, TEEC_Session *s, + uint32_t num_bits, uint32_t *handle) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = num_bits; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_NEW_FMM_VAR, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + if (!res) + *handle = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_new_fmm_ctx(ADBG_Case_t *c, TEEC_Session *s, + uint32_t num_bits, uint32_t hmodulus, + uint32_t *handle) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = num_bits; + op.params[0].value.b = hmodulus; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_NEW_FMM_CTX, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + if (!res) + *handle = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_free_handle(ADBG_Case_t *c, TEEC_Session *s, + uint32_t handle) +{ + if (handle == TA_CRYPT_ARITH_INVALID_HANDLE) + return TEEC_SUCCESS; + + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = handle; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_FREE_HANDLE, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_from_octet_string(ADBG_Case_t *c, TEEC_Session *s, + uint8_t *buf, uint32_t buf_len, + int32_t sign, uint32_t h) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = h; + op.params[0].value.b = sign; + op.params[1].tmpref.buffer = buf; + op.params[1].tmpref.size = buf_len; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_FROM_OCTET_STRING, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_from_s32(ADBG_Case_t *c, TEEC_Session *s, + uint32_t handle, int32_t v) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = handle; + op.params[0].value.b = v; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_FROM_S32, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_get_bit(ADBG_Case_t *c, TEEC_Session *s, + uint32_t handle, uint32_t bit_num, uint32_t *v) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = handle; + op.params[0].value.b = bit_num; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_GET_BIT, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + if (!res) + *v = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_set_bit(ADBG_Case_t *c, TEEC_Session *s, + uint32_t handle, uint32_t bit_num, uint32_t v) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = handle; + op.params[0].value.b = bit_num; + op.params[1].value.a = v; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_SET_BIT, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_get_bit_count(ADBG_Case_t *c, TEEC_Session *s, + uint32_t handle, uint32_t *v) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = handle; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_GET_BIT_COUNT, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + if (!res) + *v = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_binary_cmd(ADBG_Case_t *c, TEEC_Session *s, uint32_t cmd, + uint32_t hop1, uint32_t hop2, uint32_t hres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop1; + op.params[0].value.b = hop2; + op.params[1].value.a = hres; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_unary_cmd(ADBG_Case_t *c, TEEC_Session *s, uint32_t cmd, + uint32_t hop, uint32_t hres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop; + op.params[0].value.b = hres; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_ternary_cmd(ADBG_Case_t *c, TEEC_Session *s, + uint32_t cmd, uint32_t hop1, uint32_t hop2, + uint32_t hn, uint32_t hres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop1; + op.params[0].value.b = hop2; + op.params[1].value.a = hn; + op.params[1].value.b = hres; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, cmd, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_neg(ADBG_Case_t *c, TEEC_Session *s, uint32_t hop, + uint32_t hres) +{ + return cmd_unary_cmd(c, s, TA_CRYPT_CMD_ARITH_NEG, hop, hres); +} + +static TEEC_Result cmd_abs(ADBG_Case_t *c, TEEC_Session *s, uint32_t hop, + uint32_t hres) +{ + return cmd_unary_cmd(c, s, TA_CRYPT_CMD_ARITH_ABS, hop, hres); +} + +static TEEC_Result cmd_assign(ADBG_Case_t *c, TEEC_Session *s, uint32_t hop, + uint32_t hres) +{ + return cmd_unary_cmd(c, s, TA_CRYPT_CMD_ARITH_ASSIGN, hop, hres); +} + +static TEEC_Result cmd_add(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hres) +{ + return cmd_binary_cmd(c, s, TA_CRYPT_CMD_ARITH_ADD, hop1, hop2, hres); +} + +static TEEC_Result cmd_sub(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hres) +{ + return cmd_binary_cmd(c, s, TA_CRYPT_CMD_ARITH_SUB, hop1, hop2, hres); +} + +static TEEC_Result cmd_mul(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hres) +{ + return cmd_binary_cmd(c, s, TA_CRYPT_CMD_ARITH_MUL, hop1, hop2, hres); +} + +static TEEC_Result cmd_mod(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hres) +{ + return cmd_binary_cmd(c, s, TA_CRYPT_CMD_ARITH_MOD, hop1, hop2, hres); +} + +static TEEC_Result cmd_invmod(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hres) +{ + return cmd_binary_cmd(c, s, TA_CRYPT_CMD_ARITH_INVMOD, hop1, hop2, + hres); +} + +static TEEC_Result cmd_addmod(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hn, + uint32_t hres) +{ + return cmd_ternary_cmd(c, s, TA_CRYPT_CMD_ARITH_ADDMOD, hop1, hop2, + hn, hres); +} + +static TEEC_Result cmd_submod(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hn, + uint32_t hres) +{ + return cmd_ternary_cmd(c, s, TA_CRYPT_CMD_ARITH_SUBMOD, hop1, hop2, + hn, hres); +} + +static TEEC_Result cmd_mulmod(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hn, + uint32_t hres) +{ + return cmd_ternary_cmd(c, s, TA_CRYPT_CMD_ARITH_MULMOD, hop1, hop2, + hn, hres); +} + +static TEEC_Result cmd_is_prime(ADBG_Case_t *c, TEEC_Session *s, uint32_t hop, + uint32_t conf_level, int32_t *pres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop; + op.params[0].value.b = conf_level; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_IS_PRIME, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + if (!res) + *pres = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_shift_right(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop, uint32_t bits, uint32_t hres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop; + op.params[0].value.b = bits; + op.params[1].value.a = hres; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_SHIFT_RIGHT, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_to_fmm(ADBG_Case_t *c, TEEC_Session *s, uint32_t hsrc, + uint32_t hn, uint32_t hctx, uint32_t hres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hsrc; + op.params[0].value.b = hn; + op.params[1].value.a = hctx; + op.params[1].value.b = hres; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_TO_FMM, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_from_fmm(ADBG_Case_t *c, TEEC_Session *s, uint32_t hsrc, + uint32_t hn, uint32_t hctx, uint32_t hres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hsrc; + op.params[0].value.b = hn; + op.params[1].value.a = hctx; + op.params[1].value.b = hres; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_FROM_FMM, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_compute_fmm(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hn, + uint32_t hctx, uint32_t hres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop1; + op.params[0].value.b = hop2; + op.params[1].value.a = hn; + op.params[1].value.b = hctx; + op.params[2].value.a = hres; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_COMPUTE_FMM, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_compute_egcd(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hu, + uint32_t hv, uint32_t hgcd) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop1; + op.params[0].value.b = hop2; + op.params[1].value.a = hu; + op.params[1].value.b = hv; + op.params[2].value.a = hgcd; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_COMPUTE_EGCD, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static TEEC_Result cmd_compute_gcd(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hgcd) +{ + return cmd_compute_egcd(c, s, hop1, hop2, TA_CRYPT_ARITH_INVALID_HANDLE, + TA_CRYPT_ARITH_INVALID_HANDLE, hgcd); +} + +static TEEC_Result cmd_expmod(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, uint32_t hn, + uint32_t hctx, uint32_t hres) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop1; + op.params[0].value.b = hop2; + op.params[1].value.a = hn; + op.params[1].value.b = hctx; + op.params[2].value.a = hres; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_EXPMOD, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static int digit_value(char ch) +{ + if ((ch >= '0') && (ch <= '9')) + return ch - '0'; + + if ((ch >= 'A') && (ch <= 'F')) + return ch - 'A' + 10; + + if ((ch >= 'a') && (ch <= 'f')) + return ch - 'a' + 10; + + return -1; +} + +static TEEC_Result convert_from_string(ADBG_Case_t *c, TEEC_Session *s, + const char *str, uint32_t h) +{ + TEEC_Result res = TEEC_ERROR_BAD_FORMAT; + size_t spos = strlen(str); + int32_t sign = 1; + size_t os_len = (spos + 1) / 2; + uint8_t *os = calloc(1, os_len); + int ospos = os_len - 1; + int nibble = 0; + + if (!os) + return TEEC_ERROR_OUT_OF_MEMORY; + + while (spos) { + spos--; + nibble = digit_value(str[spos]); + if (nibble == -1) + break; + os[ospos] = nibble; + + if (!spos) + break; + spos--; + nibble = digit_value(str[spos]); + if (nibble == -1) + break; + + os[ospos] |= nibble << 4; + ospos--; + } + + if (spos) + goto out; + + if (str[spos] == '-') + sign = -1; + + res = cmd_from_octet_string(c, s, os, os_len, sign, h); +out: + free(os); + return res; +} + +static TEEC_Result cmd_get_value(ADBG_Case_t *c, TEEC_Session *s, uint8_t *buf, + uint32_t *buf_len, int32_t *sign, uint32_t h) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = h; + op.params[2].tmpref.buffer = buf; + op.params[2].tmpref.size = *buf_len; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_GET_VALUE, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + if (!res) + *sign = op.params[1].value.a; + *buf_len = op.params[2].tmpref.size; + + return res; +} + +static TEEC_Result __maybe_unused print_handle(ADBG_Case_t *c, TEEC_Session *s, + const char *name, uint32_t h) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + uint8_t *os = NULL; + uint32_t os_len = 0; + int32_t sign = 0; + + res = cmd_get_value(c, s, os, &os_len, &sign, h); + if (res) { + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_SHORT_BUFFER, res)) + return res; + + os = malloc(os_len); + if (!ADBG_EXPECT_NOT_NULL(c, os)) + return TEEC_ERROR_OUT_OF_MEMORY; + + res = cmd_get_value(c, s, os, &os_len, &sign, h); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + } + + Do_ADBG_Log("%s sign %" PRId32 " (length %" PRIu32 ")", + name, sign, os_len); + Do_ADBG_HexLog(os, os_len, 16); +out: + free(os); + return res; +} + +static TEEC_Result cmd_get_value_s32(ADBG_Case_t *c, TEEC_Session *s, + uint32_t h, int32_t *val) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = h; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_GET_VALUE_S32, &op, + &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + if (!res) + *val = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_cmp(ADBG_Case_t *c, TEEC_Session *s, uint32_t hop1, + uint32_t hop2, int32_t *cmp_res) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop1; + op.params[0].value.b = hop2; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_CMP, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + if (!res) + *cmp_res = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_cmp_s32(ADBG_Case_t *c, TEEC_Session *s, uint32_t hop, + int32_t s32, int32_t *cmp_res) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop; + op.params[0].value.b = s32; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_CMP_S32, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + if (!res) + *cmp_res = op.params[1].value.a; + + return res; +} + +static TEEC_Result cmd_div(ADBG_Case_t *c, TEEC_Session *s, uint32_t hop1, + uint32_t hop2, uint32_t hq, uint32_t hr) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = hop1; + op.params[0].value.b = hop2; + op.params[1].value.a = hq; + op.params[1].value.b = hr; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ARITH_DIV, &op, &ret_orig); + ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, ret_orig); + + return res; +} + +static void test_4101(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + uint32_t handle = TA_CRYPT_ARITH_INVALID_HANDLE; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "Normal allocation and initialization"); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_new_var(c, &session, 512, &handle))) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + handle, !=, TA_CRYPT_ARITH_INVALID_HANDLE)) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, handle))) + goto out; + + Do_ADBG_EndSubCase(c, "Normal allocation and initialization"); + + Do_ADBG_BeginSubCase(c, "Zero allocation"); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_new_var(c, &session, 0, &handle))) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + handle, !=, TA_CRYPT_ARITH_INVALID_HANDLE)) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, handle))) + goto out; + + Do_ADBG_EndSubCase(c, "Zero allocation"); + + Do_ADBG_BeginSubCase(c, "Too large"); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_new_var(c, &session, 4096, &handle))) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + handle, !=, TA_CRYPT_ARITH_INVALID_HANDLE)) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, handle))) + goto out; + + Do_ADBG_EndSubCase(c, "Too large"); + + Do_ADBG_BeginSubCase(c, "Boundaries"); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_new_var(c, &session, 2048, &handle))) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + handle, !=, TA_CRYPT_ARITH_INVALID_HANDLE)) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_new_var(c, &session, 2049, &handle))) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + handle, !=, TA_CRYPT_ARITH_INVALID_HANDLE)) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, handle))) + goto out; + + Do_ADBG_EndSubCase(c, "Boundaries"); +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4101, test_4101, + "Test TEE Internal API Arithmetical API - Bigint init"); + +static void test_4102(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + uint32_t ha = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hb = TA_CRYPT_ARITH_INVALID_HANDLE; + size_t n = 0; + const struct { + const uint8_t *os; + uint32_t os_len; + const char *str; + int32_t sign; + } data[] = { + { .os = (const uint8_t []){ 1, 2, 3, 4 }, + .os_len = 4, .sign = 1, .str = "01020304", }, + { .os = (const uint8_t []){ 1, 2, 3, 4, 5 }, + .os_len = 5, .sign = 1, .str = "0102030405", }, + { .os = (const uint8_t []){ + 0x11, 0x22, 0x44, 0x55, 0x66, 0x77, 0x88 }, + .os_len = 7, .sign = 1, .str = "11224455667788", }, + { .os = (const uint8_t []){ 0, 1, 2, 3, 4 }, + .os_len = 5, .sign = 1, .str = "01020304", }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 512, &ha))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 512, &hb))) + goto out; + + for (n = 0; n < ARRAY_SIZE(data); n++) { + int32_t sign = 0; + int32_t cmp_res = 0; + size_t len_diff = 0; + uint8_t os_res[10]; + uint32_t os_len; + + Do_ADBG_BeginSubCase(c, "\"%s\"", data[n].str); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, + &session, data[n].str, ha))) + goto out; + + /* Check that it's read back correctly */ + os_len = data[n].os_len; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_get_value(c, &session, + os_res, &os_len, &sign, ha))) + goto out; + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, data[n].os_len, + >=, os_len)) + goto out; + + len_diff = data[n].os_len - os_len; + if (!ADBG_EXPECT_BUFFER(c, data[n].os + len_diff, + data[n].os_len - len_diff, + os_res, os_len)) + goto out; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, sign, ==, data[n].sign)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_from_octet_string(c, + &session, os_res, os_len, sign, hb))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_cmp(c, &session, + ha, hb, &cmp_res))) + goto out; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cmp_res, ==, 0)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4102, test_4102, + "Test TEE Internal API Arithmetical API - Octet string"); + +static void test_4103(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + uint32_t h = TA_CRYPT_ARITH_INVALID_HANDLE; + int32_t v = 0; + static const int32_t data[] = { + 1, -1, 123, -123, 0x7FFFFFFF, (int32_t)0x80000000, + (int32_t)0xFFFFFFFF, 0, + }; + static const char *data_str[] = { "1FFFFFFFFF", "-1FFFFFFFFF" }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 512, &h))) + goto out; + + for (n = 0; n < ARRAY_SIZE(data); n++) { + int32_t cmp_res = 0; + + Do_ADBG_BeginSubCase(c, "%" PRId32 " (0x%" PRIx32 ")", + data[n], (uint32_t)data[n]); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_from_s32(c, &session, h, data[n]))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_cmp_s32(c, &session, h, data[n], &cmp_res))) + goto out; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cmp_res, ==, 0)) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_get_value_s32(c, &session, h, &v))) { + Do_ADBG_Log("n %zu", n); + goto out; + } + if (!ADBG_EXPECT_COMPARE_SIGNED(c, data[n], ==, v)) + goto out; + + Do_ADBG_EndSubCase(c, NULL); + } + + for (n = 0; n < ARRAY_SIZE(data_str); n++) { + Do_ADBG_BeginSubCase(c, "\"%s\" (overflow)", data_str[n]); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, + &session, data_str[n], h))) + goto out; + if (!ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_OVERFLOW, + cmd_get_value_s32(c, &session, h, &v))) + goto out; + Do_ADBG_EndSubCase(c, NULL); + } + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4103, test_4103, + "Test TEE Internal API Arithmetical API - S32"); + +static TEEC_Result compare_str(ADBG_Case_t *c, TEEC_Session *s, + const char str1[], const char str2[], + int32_t cmp_res) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + int32_t cres = 0; + uint32_t h1 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t h2 = TA_CRYPT_ARITH_INVALID_HANDLE; + + res = cmd_new_var(c, s, 512, &h1); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + res = cmd_new_var(c, s, 512, &h2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = convert_from_string(c, s, str1, h1); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + res = convert_from_string(c, s, str2, h2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = cmd_cmp(c, s, h1, h2, &cres); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + ADBG_EXPECT_COMPARE_SIGNED(c, cres, ==, cmp_res); +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, h1)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, h2)); + return res; +} + +static TEEC_Result compare_s32(ADBG_Case_t *c, TEEC_Session *s, + const char str[], int32_t val, + int32_t cmp_res) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + int32_t cres = 0; + uint32_t h = TA_CRYPT_ARITH_INVALID_HANDLE; + + res = cmd_new_var(c, s, 512, &h); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + res = convert_from_string(c, s, str, h); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = cmd_cmp_s32(c, s, h, val, &cres); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + ADBG_EXPECT_COMPARE_SIGNED(c, cres, ==, cmp_res); +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, h)); + + return res; +} + +static void test_4104(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + const struct { + const char *str1; + const char *str2; + int32_t cmp_res; + } data[] = { + { "0", "1", -1 }, + { "1", "0", 1 }, + { "1", "2", -1 }, + { "2", "1", 1 }, + { "-1", "FFFFFFFFFF", -1 }, + { "FFFFFFFFFF", "-1", 1 }, + { "1", "-FFFFFFFFFF", 1 }, + { "-FFFFFFFFFF", "1", -1 }, + { "1", "100000000", -1 }, + { "0", "0", 0 }, + { "1", "1", 0 }, + { "-1", "-1", 0} + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + Do_ADBG_BeginSubCase(c, "Compare bigints"); + for (n = 0; n < ARRAY_SIZE(data); n++) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_str(c, &session, + data[n].str1, data[n].str2, data[n].cmp_res))) + goto out; + } + Do_ADBG_EndSubCase(c, "Compare bigints"); + + const struct { + const char *str; + int32_t val; + int32_t cmp_res; + } data_s32[] = { + {"0", 0, 0 }, + {"0", 1, -1 }, + {"1", 0, 1 }, + {"0", -1, 1 }, + {"-1", 0, -1 }, + {"1", 1, 0 }, + {"-1", -1, 0 }, + {"-1", 1, -1 }, + {"1", -1, 1 }, + {"123", 0x123, 0 }, + {"-123", -0x123, 0 }, + + /* corner case */ + {"7FFFFFFF", INT32_MAX, 0 }, + {"-7FFFFFFF", INT32_MIN, 1 }, + {"7FFFFFFF", 0, 1 }, + {"-7FFFFFFF", 0, -1 }, + {"-80000000", INT32_MIN, 0 }, + {"80000000", INT32_MAX, 1 }, + {"-80000001", INT32_MIN, -1 }, + {"-7FFFFFFF", INT32_MIN, 1 }, + + /* large BigInt */ + {"1FFFFFFFF", 1, 1 }, + {"-1FFFFFFFF", 1, -1 }, + }; + + Do_ADBG_BeginSubCase(c, "Compare S32"); + for (n = 0; n < ARRAY_SIZE(data_s32); n++) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_s32(c, &session, + data_s32[n].str, data_s32[n].val, + data_s32[n].cmp_res))) + goto out; + } + Do_ADBG_EndSubCase(c, "Compare S32"); + +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4104, test_4104, + "Test TEE Internal API Arithmetical API - Compare"); + +static TEEC_Result compare_handle(ADBG_Case_t *c, TEEC_Session *s, + uint32_t hop1, uint32_t hop2, int32_t cmp_res) +{ + int32_t cres = 0; + TEEC_Result res = cmd_cmp(c, s, hop1, hop2, &cres); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cres, ==, cmp_res)) + return TEEC_ERROR_GENERIC; + + return TEEC_SUCCESS; +} + +static bool do_addsub(ADBG_Case_t *c, TEEC_Session *s, const char *str_s, + const char *str_t, const char *str_r) +{ + bool res = false; + uint32_t ha = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hb = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hc = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hr = TA_CRYPT_ARITH_INVALID_HANDLE; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 1024, &ha))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 1024, &hb))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 1024, &hc))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 1024, &hr))) + goto out; + + /* First do the ADD dominated phase */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_r, hr))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_s, ha))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_t, hb))) + goto out; + + /* hc = ha + hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_add(c, s, ha, hb, hc))) + goto out; + /* check hc == hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hr, 0))) + goto out; + /* ha = ha + hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_add(c, s, ha, hb, ha))) + goto out; + /* check ha == hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, ha, hr, 0))) + goto out; + /* ha = ha - hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_sub(c, s, ha, hb, ha))) + goto out; + /* hb = ha + hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_add(c, s, ha, hb, hb))) + goto out; + /* check hb == hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hb, hr, 0))) + goto out; + + /* Do the SUB dominated phase */ + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_s, hr))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_r, ha))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_t, hb))) + goto out; + + /* hc = ha - hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_sub(c, s, ha, hb, hc))) + goto out; + /* check hc == hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hr, 0))) + goto out; + /* ha = ha - hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_sub(c, s, ha, hb, ha))) + goto out; + /* check ha == hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, ha, hr, 0))) + goto out; + /* ha = ha + hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_add(c, s, ha, hb, ha))) + goto out; + /* hb = ha - hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_sub(c, s, ha, hb, hb))) + goto out; + /* check hb == hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hb, hr, 0))) + goto out; + + /* Test assignment, ha = hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_assign(c, s, hb, ha))) + goto out; + /* check ha == hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, ha, hb, 0))) + goto out; + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, ha)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hb)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hc)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hr)); + + return res; +} + +static void test_4105(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + static const struct { + const char *s; + const char *t; + const char *r; + } data[] = { + { "1", "1", "2" }, + { "-1", "1", "0" }, + { "0", "0", "0" }, + { "0", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" }, + /* single word, no carry */ + { "FF", "FF", "1FE" }, + /* single word, with carry */ + { "FFFFFFFF", "FFFFFFFF", "1FFFFFFFE" }, + /* mult word with partial carry */ + { "FFFFFFFF", "100000000FFFFFFFFFFFFFFFF", + "10000000100000000FFFFFFFE" }, + /* mult word with carry all the way */ + { "FFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFF", + "1FFFFFFFFFFFFFFFE" }, + /* single word, no carry */ + { "-FF", "-FF", "-1FE" }, + /* single word, with carry */ + { "-FFFFFFFF", "-FFFFFFFF", "-1FFFFFFFE" }, + /* mult word with partial carry */ + { "-FFFFFFFF", "-100000000FFFFFFFFFFFFFFFF", + "-10000000100000000FFFFFFFE" }, + /* mult word with carry */ + { "-FFFFFFFFFFFFFFFF", "-FFFFFFFFFFFFFFFF", + "-1FFFFFFFFFFFFFFFE" }, + /* single word, no carry */ + { "FFFF", "-FF", "FF00" }, + /* single word, with carry */ + { "F00000000", "-00000FFFF", "EFFFF0001" }, + /* multi words with carry */ + { "FFFFFFFF00000000", "-FFFFFFFF", "FFFFFFFE00000001" }, + { "10000000FFFFFFFF00000000", "-FFFFFFFF", + "10000000FFFFFFFE00000001" }, + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE", "1" }, + { "FF", "-FFFF", "-FF00" }, + { "FFFFFFFF", "-1FFFFFFFF", "-100000000" }, + /* single word, no carry */ + { "-FFFF", "FF", "-FF00" }, + /* single word, with carry */ + { "-F00000000", "00000FFFF", "-EFFFF0001" }, + /* multi words with carry */ + { "-FFFFFFFF00000000", "FFFFFFFF", "-FFFFFFFE00000001" }, + { "-10000000FFFFFFFF00000000", "FFFFFFFF", + "-10000000FFFFFFFE00000001" }, + { "-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE", "-1" }, + { "-FF", "FFFF", "FF00" }, + { "-FFFFFFFF", "1FFFFFFFF", "100000000" }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(data); n++) { + if (!ADBG_EXPECT_TRUE(c, do_addsub(c, &session, data[n].s, + data[n].t, data[n].r))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4105, test_4105, + "Test TEE Internal API Arithmetical API - Add, Sub"); + +static void test_4106(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + uint32_t h1 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t h2 = TA_CRYPT_ARITH_INVALID_HANDLE; + static const struct { + const char *val; + const char *neg_val; + } data[] = { + { "0", "0" }, + { "1", "-1" }, + { "123", "-123" }, + { "123456789123456789", "-123456789123456789" }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &h1))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &h2))) + goto out; + + for (n = 0; n < ARRAY_SIZE(data); n++) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, + &session, data[n].val, h1))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, + &session, data[n].neg_val, h2))) + goto out; + + if (n && !ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, + &session, h1, h2, 1))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_neg(c, &session, h1, h1))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, &session, + h1, h2, 0))) + goto out; + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4106, test_4106, + "Test TEE Internal API Arithmetical API - Neg"); + +static bool do_mul(ADBG_Case_t *c, TEEC_Session *s, const char *str_s, + const char *str_t, const char *str_r) +{ + bool res = false; + uint32_t ha = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hb = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hc = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hr = TA_CRYPT_ARITH_INVALID_HANDLE; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 1024, &ha))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 1024, &hb))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hc))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hr))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_r, hr))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_s, ha))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_t, hb))) + goto out; + + /* hc = ha * hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_mul(c, s, ha, hb, hc))) + goto out; + /* check hc == hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hr, 0))) + goto out; + /* ha = ha * hb */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_mul(c, s, ha, hb, ha))) + goto out; + /* check ha == hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, ha, hr, 0))) + goto out; + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, ha)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hb)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hc)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hr)); + + return res; +} + +static void test_4107(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + static const struct { + const char *s; + const char *t; + const char *r; + } data[] = { + { "0", "0", "0" }, + { "0", "FFFFFFFF", "0" }, + { "1", "1", "1" }, + { "-1", "1", "-1" }, + { "-1", "-1", "1" }, + { "FF", "1", "FF" }, + { "2", "2", "4" }, + { "3", "3", "9" }, + { "100", "100", "10000" }, + { "FFFFFFFF", "FFFFFFFF", "FFFFFFFE00000001" }, + { "4F239BBAE89A447149CDB0B50A103C69591DD9E0C91A57955A6C266" + "C7ED42A5ED5F4", + "44FF5A67036657E041D55AE42AE25517A1", + "155465C8221717FFC135C87ABF6D34184DF5E6906D2EBA7C364879AA" + "0BE840FD06F1E0A7036BC3B7B1844FF95F07A39CE17A74" }, + { "4F239BBAE89A447149CDB0B50A103C69591DD9E0C91A57955A6C266C" + "7ED42A5ED5F4", + "-44FF5A67036657E041D55AE42AE25517A1", + "-155465C8221717FFC135C87ABF6D34184DF5E6906D2EBA7C364879A" + "A0BE840FD06F1E0A7036BC3B7B1844FF95F07A39CE17A74" }, + { "-4F239BBAE89A447149CDB0B50A103C69591DD9E0C91A57955A6C266" + "C7ED42A5ED5F4", + "-44FF5A67036657E041D55AE42AE25517A1", + "155465C8221717FFC135C87ABF6D34184DF5E6906D2EBA7C364879AA" + "0BE840FD06F1E0A7036BC3B7B1844FF95F07A39CE17A74" }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(data); n++) { + if (!ADBG_EXPECT_TRUE(c, do_mul(c, &session, data[n].s, + data[n].t, data[n].r))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4107, test_4107, + "Test TEE Internal API Arithmetical API - Mul"); + +static bool do_div(ADBG_Case_t *c, TEEC_Session *s, const char *str_s, + const char *str_t, const char *str_out, int32_t qsign, + int32_t rsign) +{ + bool res = false; + int32_t cres = 0; + uint32_t hn = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hd = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hq = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hr = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hv = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hout = TA_CRYPT_ARITH_INVALID_HANDLE; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hn))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hd))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hq))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hr))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hv))) + goto out; + + if (str_out) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_new_var(c, s, 2048, &hout))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_out, hout))) + goto out; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_s, hn))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_t, hd))) + goto out; + + /* (hq, hr) = n / d */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_div(c, s, hn, hd, hq, hr))) + goto out; + if (str_out) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + compare_handle(c, s, hq, hout, 0))) + goto out; + } + + /* hv = hq * hd */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_mul(c, s, hq, hd, hv))) + goto out; + /* hv = hv + hr */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_add(c, s, hv, hr, hv))) + goto out; + /* check hn == hv */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hn, hv, 0))) + goto out; + + if (qsign) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_cmp_s32(c, s, hq, 0, &cres))) + goto out; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cres, ==, qsign)) + goto out; + } + + if (rsign) { + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_cmp_s32(c, s, hr, 0, &cres))) + goto out; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cres, ==, rsign)) + goto out; + } + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hn)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hd)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hq)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hr)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hv)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hout)); + + return res; +} + +static void test_4108(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + static const struct { + const char *s; + const char *t; + const char *out; + int32_t qsign; + int32_t rsign; + } data[] = { + { "811111100000000112345678", "8000000012345678" }, + { "0", "1", "0" }, + { "1", "1", "1" }, + { "b7fb", "5", "24CB" }, + { "124378912734891273894712890347102358129034789120374", + "1984086C15FA011154C86FA68", "B73D14EC7205D3311F6E78411D" }, + { "124378912734891273894712890347102358129034789120374", + "1984086C15FA011154C86FA68" }, + { "-124378912734891273894712890347102358129034789120374", + "1984086C15FA011154C86FA68" }, + { "124378912734891273894712890347102358129034789120374", + "-1984086C15FA011154C86FA68" }, + { "-124378912734891273894712890347102358129034789120374", + "-1984086C15FA011154C86FA68" }, + { "12345678", "10" }, + { "-12345678", "10" }, + { "12345678", "-10" }, + { "-12345678", "-10" }, + { "12345678901234567890123456789012345678901", "10" }, + { "1234567890123456789012345678901234567890", "10" }, + { "123456789012345678901234567890123456789", "10" }, + { "53", "7", NULL, 1, 1 }, + { "-53", "7", NULL, -1, -1 }, + { "53", "-7", NULL, -1, 1 }, + { "-53", "-7", NULL, 1, -1 }, + { "123456789abcdef123456789abcdef", "fedcba98765432100", + NULL, 1, 1 }, + { "-123456789abcdef123456789abcdef", "fedcba98765432100", + NULL, -1, -1 }, + { "123456789abcdef123456789abcdef", "-fedcba98765432100", + NULL, -1, 1 }, + { "-123456789abcdef123456789abcdef", "-fedcba98765432100", + NULL, 1, -1 }, + }; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(data); n++) { + if (!ADBG_EXPECT_TRUE(c, do_div(c, &session, data[n].s, + data[n].t, data[n].out, data[n].qsign, + data[n].rsign))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4108, test_4108, + "Test TEE Internal API Arithmetical API - Div"); + +static const struct { + const char *op; + const char *n; + const char *res; +} test_4109_data[] = { + { "10", "A", "6" }, + { "10", "20", "10" }, + { "-1", "123", "122" }, + { "-122", "123", "1" }, + { "-1", "100000000000000000000", "FFFFFFFFFFFFFFFFFFFF" }, + + { "42176E7CD0386C94194C3C3DACFA7237" + "CCF4E0829E2EBEAB59DE12CAE3305C9E" + "576F837A42D9C13BB1D83E4DFD330B65" + "76FD516B2AE9FBDD152F0A820C5DD18E" + "D048D476EC791DC989D6D8C30B2B30FF" + "C2A4ABAC082C672B38E138610B74CE0C" + "30D1B378BE6FE0C44E09EC11586245CD" + "8F1216619392E6B2C857C71EA78DD4D8" + "61A482D9D1251C341D1D6205AFB2BFB5" + "3DD1F272B5624FA61B020936745387CD" + "F1F3EBC4435CBE6C6B323497098FDE9D" + "61AA0CC87416235E706A71F73EC3C291" + "D9ACA2EECD712DA40966DD251310AE94" + "9713F69B2A32E42732A7F6669547D88A" + "415B25C582FDBBF06C5EC5F5750053D4" + "9F7ED68DED168C92F9C531828A", + "A9A9C49F0015DBEF9EB0D927F379821AE2C59", + "3460EB99F07BC4617A7586E6522B98F66E5B2" }, + + { "42176E7CD0386C94194C3C3DACFA7237" + "CCF4E0829E2EBEAB59DE12CAE3305C9E" + "576F837A42D9C13BB1D83E4DFD330B65" + "76FD516B2AE9FBDD152F0A820C5DD18E" + "D048D476EC791DC989D6D8C30B2B30FF" + "C2A4ABAC082C672B38E138610B74CE0C" + "30D1B378BE6FE0C44E09EC11586245CD" + "8F1216619392E6B2C857C71EA78DD4D8" + "61A482D9D1251C341D1D6205AFB2BFB5" + "3DD1F272B5624FA61B020936745387CD" + "F1F3EBC4435CBE6C6B323497098FDE9D" + "61AA0CC87416235E706A71F73EC3C291" + "D9ACA2EECD712DA40966DD251310AE94" + "9713F69B2A32E42732A7F6669547D88A" + "415B25C582FDBBF06C5EC5F5750053D4" + "9F7ED68DED168C92F9C531828A", + "1234", "1082" }, + + { "FFFF6E7CD0386C94194C3C3DACFA7237" + "CCF4E0829E2EBEAB59DE12CAE3305C9E" + "576F837A42D9C13BB1D83E4DFD330B65" + "76FD516B2AE9FBDD152F0A820C5DD18E" + "D048D476EC791DC989D6D8C30B2B30FF" + "C2A4ABAC082C672B38E138610B74CE0C" + "30D1B378BE6FE0C44E09EC11586245CD" + "8F1216619392E6B2C857C71EA78DD4D8" + "61A482D9D1251C341D1D6205AFB2BFB5" + "3DD1F272B5624FA61B020936745387CD" + "F1F3EBC4435CBE6C6B323497098FDE9D" + "61AA0CC87416235E706A71F73EC3C291" + "D9ACA2EECD712DA40966DD251310AE94" + "9713F69B2A32E42732A7F6669547D88A" + "415B25C582FDBBF06C5EC5F5750053D4" + "9F7ED68DED168C92F9C531828A", + "2", "0" }, + + { "FFFF6E7CD0386C94194C3C3DACFA7237" + "CCF4E0829E2EBEAB59DE12CAE3305C9E" + "576F837A42D9C13BB1D83E4DFD330B65" + "76FD516B2AE9FBDD152F0A820C5DD18E" + "D048D476EC791DC989D6D8C30B2B30FF" + "C2A4ABAC082C672B38E138610B74CE0C" + "30D1B378BE6FE0C44E09EC11586245CD" + "8F1216619392E6B2C857C71EA78DD4D8" + "61A482D9D1251C341D1D6205AFB2BFB5" + "3DD1F272B5624FA61B020936745387CD" + "F1F3EBC4435CBE6C6B323497098FDE9D" + "61AA0CC87416235E706A71F73EC3C291" + "D9ACA2EECD712DA40966DD251310AE94" + "9713F69B2A32E42732A7F6669547D88A" + "415B25C582FDBBF06C5EC5F5750053D4" + "9F7ED68DED168C92F9C531828A", + "FFFF6E7CD0386C94194C3C3DACFA7237" + "CCF4E0829E2EBEAB59DE12CAE3305C9E" + "576F837A42D9C13BB1D83E4DFD330B65" + "76FD516B2AE9FBDD152F0A820C5DD18E" + "D048D476EC791DC989D6D8C30B2B30FF" + "C2A4ABAC082C672B38E138610B74CE0C" + "30D1B378BE6FE0C44E09EC11586245CD" + "8F1216619392E6B2C857C71EA78DD4D8" + "61A482D9D1251C341D1D6205AFB2BFB5" + "3DD1F272B5624FA61B020936745387CD" + "F1F3EBC4435CBE6C6B323497098FDE9D" + "61AA0CC87416235E706A71F73EC3C291" + "D9ACA2EECD712DA40966DD251310AE94" + "9713F69B2A32E42732A7F6669547D88A" + "415B25C582FDBBF06C5EC5F5750053D4" + "9F7ED68DED168C92F9C531828A", + "0" }, + + { "FFFF6E7CD0386C94194C3C3DACFA7237" + "CCF4E0829E2EBEAB59DE12CAE3305C9E" + "576F837A42D9C13BB1D83E4DFD330B65" + "76FD516B2AE9FBDD152F0A820C5DD18E" + "D048D476EC791DC989D6D8C30B2B30FF" + "C2A4ABAC082C672B38E138610B74CE0C" + "30D1B378BE6FE0C44E09EC11586245CD" + "8F1216619392E6B2C857C71EA78DD4D8" + "61A482D9D1251C341D1D6205AFB2BFB5" + "3DD1F272B5624FA61B020936745387CD" + "F1F3EBC4435CBE6C6B323497098FDE9D" + "61AA0CC87416235E706A71F73EC3C291" + "D9ACA2EECD712DA40966DD251310AE94" + "9713F69B2A32E42732A7F6669547D88A" + "415B25C582FDBBF06C5EC5F5750053D4" + "9F7ED68DED168C92F9C531828A", + "FFFF6E7CD0386C94194C3C3DACFA7237" + "CCF4E0829E2EBEAB59DE12CAE3305C9E" + "576F837A42D9C13BB1D83E4DFD330B65" + "76FD516B2AE9FBDD152F0A820C5DD18E" + "D048D476EC791DC989D6D8C30B2B30FF" + "C2A4ABAC082C672B38E138610B74CE0C" + "30D1B378BE6FE0C44E09EC11586245CD" + "8F1216619392E6B2C857C71EA78DD4D8" + "61A482D9D1251C341D1D6205AFB2BFB5" + "3DD1F272B5624FA61B020936745387CD" + "F1F3EBC4435CBE6C6B323497098FDE9D" + "61AA0CC87416235E706A71F73EC3C291" + "D9ACA2EECD712DA40966DD251310AE94" + "9713F69B2A32E42732A7F6669547D88A" + "415B25C582FDBBF06C5EC5F5750053D4" + "9F7ED68DED168C92F9C531828B", + "FFFF6E7CD0386C94194C3C3DACFA7237" + "CCF4E0829E2EBEAB59DE12CAE3305C9E" + "576F837A42D9C13BB1D83E4DFD330B65" + "76FD516B2AE9FBDD152F0A820C5DD18E" + "D048D476EC791DC989D6D8C30B2B30FF" + "C2A4ABAC082C672B38E138610B74CE0C" + "30D1B378BE6FE0C44E09EC11586245CD" + "8F1216619392E6B2C857C71EA78DD4D8" + "61A482D9D1251C341D1D6205AFB2BFB5" + "3DD1F272B5624FA61B020936745387CD" + "F1F3EBC4435CBE6C6B323497098FDE9D" + "61AA0CC87416235E706A71F73EC3C291" + "D9ACA2EECD712DA40966DD251310AE94" + "9713F69B2A32E42732A7F6669547D88A" + "415B25C582FDBBF06C5EC5F5750053D4" + "9F7ED68DED168C92F9C531828A" }, +}; + +static bool test_4109_mod(ADBG_Case_t *c, TEEC_Session *s, const char *str_op, + const char *str_n, const char *str_res) +{ + bool res = false; + uint32_t hop = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hn = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hc = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hres = TA_CRYPT_ARITH_INVALID_HANDLE; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hop))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hn))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hc))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hres))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_res, hres))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_op, hop))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_n, hn))) + goto out; + + /* hc = hop mod hn */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_mod(c, s, hop, hn, hc))) + goto out; + /* check hc == hres */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hres, 0))) + goto out; + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hop)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hn)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hc)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hres)); + + return res; +} + +static void test_4109(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(test_4109_data); n++) { + if (!ADBG_EXPECT_TRUE(c, test_4109_mod(c, &session, + test_4109_data[n].op, test_4109_data[n].n, + test_4109_data[n].res))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4109, test_4109, + "Test TEE Internal API Arithmetical API - Mod"); + +static const char n2048str[] = "F9000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "000000000000000000000000000005C5"; + +static const struct { + const char *op1; + const char *op2; + const char *n; + const char *addres; + const char *mulres; +} test_4110_data[] = { + { "0", "0", "2", "0", "0" }, + { "1", "1", "2", "0", "1" }, + { "2", "2", "9", "4", "4" }, + { "123", "123", "200", "46", "C9" }, + { "0", "123", "200", "123", "0" }, + { "123", "0", "200", "123", "0" }, + + /* Testing some 2048 bit numbers */ + { "F9000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + , + "F9000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000001", + n2048str, + "F8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3C", + "2143D4" }, + + { "F9000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000", + "5C5", n2048str, "0", + "F8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFDEBC2C" }, +}; + +static bool test_4110_mod(ADBG_Case_t *c, TEEC_Session *s, + const char *str_op1, const char *str_op2, + const char *str_n, const char *str_add_res, + const char *str_mul_res) +{ + bool res = false; + uint32_t hop1 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hop2 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hn = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hc = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t haddres = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hmulres = TA_CRYPT_ARITH_INVALID_HANDLE; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hop1))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hop2))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hn))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hc))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &haddres))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hmulres))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_add_res, haddres))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_mul_res, hmulres))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_op1, hop1))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_op2, hop2))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_n, hn))) + goto out; + + /* hc = (hop1 + hop2) mod hn */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_addmod(c, s, hop1, hop2, hn, hc))) + goto out; + /* check hc == haddres */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, haddres, 0))) + goto out; + /* hc = (haddres - hop2) mod hn */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_submod(c, s, haddres, hop2, hn, + hc))) + goto out; + /* check hc == hop1 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hop1, 0))) + goto out; + + /* hc = (hop1 * hop2) mod hn */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_mulmod(c, s, hop1, hop2, hn, hc))) + goto out; + /* check hc == hmulres */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hmulres, 0))) + goto out; + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hop1)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hop2)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hn)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hc)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, haddres)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hmulres)); + + return res; +} + +static bool test_4110_fmm(ADBG_Case_t *c, TEEC_Session *s, + const char *str_op1, const char *str_op2, + const char *str_n, const char *str_res) +{ + bool res = false; + uint32_t hop1 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hop2 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hn = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hres = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hfmmres = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hc = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hctx = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t nbitsize = 0; + uint32_t n_is_odd = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_fmm_var(c, s, 2048, &hop1))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_fmm_var(c, s, 2048, &hop2))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hn))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hres))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_fmm_var(c, s, 2048, &hfmmres))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hc))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, str_n, hn))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_res, hres))) + goto out; + /* Check if FMM is applicable on this modulus */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_get_bit(c, s, hn, 0, &n_is_odd))) + goto out; + if (!n_is_odd) { + res = true; + goto out; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_get_bit_count(c, s, hn, &nbitsize))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_new_fmm_ctx(c, s, nbitsize, hn, &hctx))) + goto out; + + /* hop1 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_op1, hc))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_to_fmm(c, s, hc, hn, hctx, hop1))) + goto out; + + /* hop2 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_op2, hc))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_to_fmm(c, s, hc, hn, hctx, hop2))) + goto out; + + /* hfmmres = hop1 * hop2 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_compute_fmm(c, s, hop1, hop2, hn, hctx, hfmmres))) + goto out; + /* hc = hfmmres mod hn*/ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_from_fmm(c, s, hfmmres, hn, hctx, hc))) + goto out; + /* check hc == hres */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hres, 0))) + goto out; + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hop1)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hop2)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hn)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hres)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hfmmres)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hc)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hctx)); + return res; +} + +static void test_4110(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(test_4110_data); n++) { + if (!ADBG_EXPECT_TRUE(c, test_4110_mod(c, &session, + test_4110_data[n].op1, test_4110_data[n].op2, + test_4110_data[n].n, + test_4110_data[n].addres, + test_4110_data[n].mulres))) { + Do_ADBG_Log("n %zu", n); + break; + } + if (!ADBG_EXPECT_TRUE(c, test_4110_fmm(c, &session, + test_4110_data[n].op1, test_4110_data[n].op2, + test_4110_data[n].n, + test_4110_data[n].mulres))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4110, test_4110, + "Test TEE Internal API Arithmetical API - Mod arith"); + +static const struct { + const char *op; + const char *n; + const char *res; +} test_4111_data[] = { + { "2", "3", "2" }, + { "3", "7", "5" }, + { "5", "7", "3" }, + { "7B", "FA1", "8E5" }, + { "462D578CF0F88", "AB54A98CEB1F0AD3", "5ABBF22B54DBD000" }, + { "7", n2048str, + "B1DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6" + "DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB" + "6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D" + "B6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6" + "DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB" + "6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D" + "B6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6" + "DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB" + "6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D" + "B6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6" + "DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB" + "6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D" + "B6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6" + "DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB" + "6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D" + "B6DB6DB6DB6DB6DB6DB6DB6DB6DB71D6" }, +}; + +static bool test_4111_invmod(ADBG_Case_t *c, TEEC_Session *s, + const char *str_op, const char *str_n, + const char *str_res) +{ + bool res = false; + uint32_t hop = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hn = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hc = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hres = TA_CRYPT_ARITH_INVALID_HANDLE; + int32_t cres = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hop))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hn))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hc))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hres))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_res, hres))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_op, hop))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_n, hn))) + goto out; + + /* hc = hop^-1 mod hn */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_invmod(c, s, hop, hn, hc))) + goto out; + /* check hc == hres */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hres, 0))) + goto out; + + /* hc = (hres * hop) mod hn */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_mulmod(c, s, hres, hop, hn, hc))) + goto out; + /* check hc == 1 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_cmp_s32(c, s, hc, 1, &cres))) + goto out; + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cres, ==, 0)) + goto out; + + /* hc = hres^-1 mod hn */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_invmod(c, s, hres, hn, hc))) + goto out; + /* check hc == hop */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hop, 0))) + goto out; + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hop)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hn)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hc)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hres)); + + return res; +} + +static void test_4111(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(test_4111_data); n++) { + if (!ADBG_EXPECT_TRUE(c, test_4111_invmod(c, &session, + test_4111_data[n].op, test_4111_data[n].n, + test_4111_data[n].res))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4111, test_4111, + "Test TEE Internal API Arithmetical API - Invmod"); + +static const struct { + uint32_t level; + int32_t res1; + int32_t res2; + const char *op; +} test_4112_data[] = { + /* Simple cases */ + { 80, 0, 0, "0" }, + { 80, 0, 0, "1" }, + { 80, 1, -1, "2" }, + { 80, 1, -1, "3" }, + { 80, 1, -1, "17" }, + { 80, 1, -1, "FA1" }, + { 80, 0, 0, "FA0" }, + /* + * Testing large composites and the only allowed classification is + * "composite", aka "0". + */ + { 80, 0, 0, "136233FDE5569" }, + { 80, 0, 0, "177B96388FD94D5D7EC9AE513" }, + { 80, 0, 0, "22770A7DC599BC90B2FF981CCB5CF057" + "03344C8F3504189ED" }, + { 80, 0, 0, "0002ECD53B2150542D1494A424D50322" + "EBABBBD5DB89392A368D7759" }, + { 80, 0, 0, "00000004C8971C2B6F7A8503AB80749E" + "2BBA5BB6B6031BD43564DCA8003F0E3E" + "54E677A0A4B1B6153662B3130C11C273" + "C0F9408445B2ABB47D64153BEB48C154" + "659FDFDEDC496C8EA81AA7B7CE2B2CB1" + "AA7C8B407DE8C86F122607B2A226385D" + "9432F6CB30B5E4DE033E3363D48A1865" + "D9BC95DC7883D9DC9331691A17964979" }, + { 80, 0, 0, "00038AFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFEA5C6D11EDD2905192" + "C5429E6A6D796E89250BF563DA53D393" + "25129B70435894B56E337D5866F0BEF6" + "63D6C26DA889B69D4B1508ED63A17AFD" + "8BC0C5BE09AC18B64B2B7D87279D32EB" + "4F3375C10D58DF1F7CA2147A61CFA557" + "235244D4A4700AB5953C4C6ED428EB5F" + "09F07DAED46A995B8FFE48EFB93390C9" + "60685A31987879F818CCE9B9816E13DE" + "E4BEA5CC38C56A5D1983425DDD909C88" + "463B447F" }, + /* Large primes */ + { 80, 1, -1, "000136A352B2C7A5" }, + { 80, 1, -1, "000000022770A7DC599BC90B2FF981CC" + "B5CF05703344C8F350418AAD" }, + + { 80, 1, -1, "000067E04F440C5FECCA2694B1A4AB4F" + "CEC2D2B2D286FC93DD259D2B36A3A00D" + "F3726A4D4DFA99195998D92F43DD7370" + "B8C079E23072036F0C13F3F6ABA1D6DF" }, + + { 80, 1, -1, "000BC9F7E42CE74132EC6933DE1B8357" + "CD2AEB9E4B8A5F26BD233D1E6F295555" + "4D2CFA9760F3F69CCC52E8E428F68C37" + "AD5BC70CDB12F4DCEF23CB101C36A2A7" }, + + { 80, 1, -1, "00000005233FE157B5B44102598513AE" + "BB8876B0D1791769C8A1B0F36875D06F" + "E26951C7372192C7B21CAB67ADF0D6FE" + "1A718FB3FC4A51454DE87CD3F852005B" + "AAEC35D5" }, + + { 80, 1, -1, "0000001A655954FBC4408E09FE97EB82" + "5E0F096426B42317A36E53FF9608DD3F" + "A661040245906334496987EFB14BEA5F" + "7C050444C9B22A09EC76AF4EBDC609D8" + "A90C05E9E5AF06829C542DFCF7E6B9DC" + "0B065659C1816309CD6012C37F8CE649" + "8DECF850F33943F0F83081406846D306" + "22E0BCE697E612FC1F7A5D902280D6E0" + "3009E585" }, +}; + +static bool test_4112_is_prime(ADBG_Case_t *c, TEEC_Session *s, + uint32_t conf_level, int32_t res1, int32_t res2, + const char *str_val) +{ + bool res = false; + uint32_t hop = TA_CRYPT_ARITH_INVALID_HANDLE; + int32_t pres = 11; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hop))) + return res; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_val, hop))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_is_prime(c, s, hop, conf_level, + &pres))) + goto out; + if (!ADBG_EXPECT_TRUE(c, pres == res1 || pres == res2)) { + Do_ADBG_Log("Unexpected prime clasification %" PRId32 ", expected %" PRId32 " or %" PRId32, + pres, res1, res2); + goto out; + } + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hop)); + + return res; +} + +static void test_4112(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(test_4112_data); n++) { + if (!ADBG_EXPECT_TRUE(c, test_4112_is_prime(c, &session, + test_4112_data[n].level, + test_4112_data[n].res1, + test_4112_data[n].res2, + test_4112_data[n].op))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4112, test_4112, + "Test TEE Internal API Arithmetical API - Is prime"); + +static const struct { + const char *res; + size_t bits; + const char *op; +} test_4113_data[] = { + { "0", 31, "7FFFFFFF" }, + { "0", 65, "7FFFFFFF" }, + { "0", 1, "0" }, + { "-1",1, "-2" }, + { "1", 0, "1" }, + { "1", 1, "2" }, + { "1", 2, "4" }, + { "1", 3, "8" }, + { "1", 4, "10" }, + { "1", 5, "20" }, + { "1", 6, "40" }, + { "1", 7, "80" }, + { "1", 8, "100" }, + { "1", 9, "200" }, + { "1", 10, "400" }, + { "1", 11, "800" }, + { "1", 12, "1000" }, + { "1", 13, "2000" }, + { "1", 14, "4000" }, + { "1", 15, "8000" }, + { "1", 16, "10000" }, + { "1", 17, "20000" }, + { "1", 18, "40000" }, + { "1", 19, "80000" }, + { "1", 20, "100000" }, + { "1", 21, "200000" }, + { "1", 22, "400000" }, + { "1", 23, "800000" }, + { "1", 24, "1000000" }, + { "1", 25, "2000000" }, + { "1", 26, "4000000" }, + { "1", 27, "8000000" }, + { "1", 28, "10000000" }, + { "1", 29, "20000000" }, + { "1", 30, "40000000" }, + { "1", 31, "80000000" }, + { "1", 32, "100000000" }, + { "1", 64, "10000000000000000" }, + { "FFFFFFFF", 64, "FFFFFFFF0000000000000000" }, + { "1111FFFF0000", 64," 1111FFFF00000000000000000000" }, + { "1", 33, "200000000" }, + { "1", 65, "20000000000000000" }, + { "FFFFFFFF", 65, "1FFFFFFFE0000000000000000" }, + { "24B0D975EC8FCC8E1D54CA4BF7ACFC4534F04", 81, + "4961B2EBD91F991C3AA99497EF59F88A69E08AD5C340167793C3CC32F" }, +}; + +static bool test_4113_shift_right(ADBG_Case_t *c, TEEC_Session *s, + const char *str_op, size_t bits, + const char *str_res) +{ + bool res = false; + uint32_t hop = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hc = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hres = TA_CRYPT_ARITH_INVALID_HANDLE; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hop))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hc))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hres))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_res, hres))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + convert_from_string(c, s, str_op, hop))) + goto out; + + /* hc = hop shift_right bits */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_shift_right(c, s, hop, bits, hc))) + goto out; + /* check hc == hres */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hc, hres, 0))) + goto out; + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hop)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hc)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hres)); + + return res; +} + +static void test_4113(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(test_4113_data); n++) { + if (!ADBG_EXPECT_TRUE(c, test_4113_shift_right(c, &session, + test_4113_data[n].op, test_4113_data[n].bits, + test_4113_data[n].res))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4113, test_4113, + "Test TEE Internal API Arithmetical API - shift right"); + +static const struct { + const char *strx; + const char *stry; +} test_4114_data[] = { + { "0", "0" }, + { "0", "123" }, + { "1", "1" }, + { "1", "-1" }, + { "2", "2" }, + { "-2", "2" }, + { "2", "4" }, + { "-2", "-4" }, + { "400", "800" }, + { "261", "2B5" }, + { "F", "A" }, + { "C", "13" }, + { "165D662", "1664FEA" }, + { "AB59CDFD83CE2B24", + "4961BF04008953A7F9567AAFBA94D4AF55F473F14FD68AA022982F0FE" }, + /* two large primes */ + { "5D0A380DC40EDE5E036FA051FC6D7F93", + "3277FD425328576569AFB2EAC6B1430578099CA8ADA4BC73" }, + /* two large powers of 2 */ + { "20000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "0", + "40000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "00000000000000000000000000000000" + "000000000000000000000" }, +}; + +static bool test_4114_gcd(ADBG_Case_t *c, TEEC_Session *s, const char *strx, + const char *stry) +{ + bool res = false; + uint32_t hx = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hy = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t ha = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hb = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hgcd = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t ht1 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t ht2 = TA_CRYPT_ARITH_INVALID_HANDLE; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hx))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hy))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &ha))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hb))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &hgcd))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &ht1))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, s, 2048, &ht2))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, strx, hx))) + goto out; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, convert_from_string(c, s, stry, hy))) + goto out; + + /* (hgcd, a, b) = ExtendedGCD(x, y) */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + cmd_compute_egcd(c, s, hx, hy, ha, hb, hgcd))) + goto out; + /* ht1 = GCD(x, y) */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_compute_gcd(c, s, hx, hy, ht1))) + goto out; + /* check hgcd == ht1 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hgcd, ht1, 0))) + goto out; + + /* ht1 = a * x */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_mul(c, s, ha, hx, ht1))) + goto out; + /* ht2 = b * y */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_mul(c, s, hb, hy, ht2))) + goto out; + /* ht1 = ht1 + ht2 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_add(c, s, ht1, ht2, ht1))) + goto out; + /* check hgcd == ht1 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, compare_handle(c, s, hgcd, ht1, 0))) + goto out; + + res = true; +out: + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hx)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hy)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, ha)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hb)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, hgcd)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, ht1)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, s, ht2)); + + return res; +} + +static void test_4114(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + for (n = 0; n < ARRAY_SIZE(test_4114_data); n++) { + if (!ADBG_EXPECT_TRUE(c, test_4114_gcd(c, &session, + test_4114_data[n].strx, + test_4114_data[n].stry))) { + Do_ADBG_Log("n %zu", n); + break; + } + } + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4114, test_4114, + "Test TEE Internal API Arithmetical API - GCD"); + +static void test_4115(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + int32_t cres = 0; + size_t n = 0; + uint32_t h1 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t h2 = TA_CRYPT_ARITH_INVALID_HANDLE; + static const char *data[] = { + "1", "-1", "123", "-123", + "123456789123456789", "-123456789123456789", + }; + + res = xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &h1)) || + !ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &h2))) + goto out; + + for (n = 0; n < ARRAY_SIZE(data); n++) { + const char *d = data[n]; + + res = convert_from_string(c, &session, d, h1); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + if (*d == '-') + d++; + res = convert_from_string(c, &session, d, h2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = cmd_cmp_s32(c, &session, h1, 0, &cres); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + if (n % 2) { + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cres, <, 0)) + goto out; + } else { + if (!ADBG_EXPECT_COMPARE_SIGNED(c, cres, >, 0)) + goto out; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_abs(c, &session, h1, h1))) + goto out; + + res = cmd_cmp_s32(c, &session, h1, 0, &cres); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res) || + !ADBG_EXPECT_COMPARE_SIGNED(c, cres, >, 0)) + goto out; + + res = cmd_cmp(c, &session, h1, h2, &cres); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res) || + !ADBG_EXPECT_COMPARE_SIGNED(c, cres, ==, 0)) + goto out; + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4115, test_4115, + "Test TEE Internal API Arithmetical API - Abs"); + + +static void test_4116(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + uint32_t val = 0; + size_t n = 0; + uint32_t h = TA_CRYPT_ARITH_INVALID_HANDLE; + static const uint32_t bit_idx[] = { 1, 4, 9, 113, 1013, 1023 }; + + res = xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &h))) + goto out; + + for (n = 0; n < ARRAY_SIZE(bit_idx); n++) { + res = cmd_get_bit(c, &session, h, bit_idx[n], &val); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res) || + !ADBG_EXPECT_COMPARE_SIGNED(c, val, ==, 0)) + goto out; + + res = cmd_set_bit(c, &session, h, bit_idx[n], 1); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = cmd_get_bit(c, &session, h, bit_idx[n], &val); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res) || + !ADBG_EXPECT_COMPARE_SIGNED(c, val, ==, 1)) + goto out; + + res = cmd_set_bit(c, &session, h, bit_idx[n], 0); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = cmd_get_bit(c, &session, h, bit_idx[n], &val); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res) || + !ADBG_EXPECT_COMPARE_SIGNED(c, val, ==, 0)) + goto out; + } +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4116, test_4116, + "Test TEE Internal API Arithmetical API - Get/Set Bit"); + +static void test_4117(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Session session = { }; + uint32_t ret_orig = 0; + size_t n = 0; + uint32_t hb = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t he = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hm = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hr = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hr2 = TA_CRYPT_ARITH_INVALID_HANDLE; + uint32_t hc = TA_CRYPT_ARITH_INVALID_HANDLE; + static const struct { + const char *base; + const char *exp; + const char *mod; + const char *result; + } data[] = { + { .base = "4", .exp = "D" /* 13 */, + .mod = "1F1" /* 497 */, .result = "1BD" /* 445 */ }, + { .base = "109fe45714866e56fdd4ad9b6b686df27224afb7868cf4f0" + "cbb794526932853cbf0beea61594166654d13cd9fe0d9da5" + "94a97ee20230f12fb5434de73fb4f8102725a01622b31b1e" + "a42e3a265019039ac1df31869bd97930d792fb72cdaa971d" + "8a8015af", + .exp = "33ae3764fd06a00cdc3cba5c45dc79a9edb4e67e4d057cc7" + "4139d531c25190d111775fc4a0f4439b8b1930bbd766e7b4" + "6f170601f316c8a18ff8d5cb5ca5581f168345d101edb462" + "b7d93b7c520ccb8fb276b447a63d869203cc11f67a1122dc" + "4da034218de85e39", + .mod = "11a9351d2d32ccd568e75bf8b4ebbb2a36be691b55832eda" + "c662ff79803df8af525fba453068be16ac3920bcc1b468f8" + "f7fe786e0fa4ecbabcad31e5e3b05def802eb8600deaf11e" + "f452487db878df20a80606e4bb6a163b83895d034cc8b53d" + "bcd005be42ffdd2ce99bed06089a0b79d", + .result = "37880b547b41bda303bddda307eefe24b4aedf076c9b814b" + "903aaf328a10825c7e259a20afc6b70b487bb21a6d32d0ee" + "98a0b9f42ff812c901e2f79237fe3e00856992dd69d93ebc" + "0664c75863829621751b0ac35a8ae8a0965841607d3099b8" + "e0ed24442749ba09acbcb165598dcd40" + }, + }; + + res = xtest_teec_open_session(&session, &crypt_user_ta_uuid, + NULL, &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &hb)) || + !ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &he)) || + !ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &hm)) || + !ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &hr)) || + !ADBG_EXPECT_TEEC_SUCCESS(c, cmd_new_var(c, &session, 1024, &hr2))) + goto out; + + for (n = 0; n < ARRAY_SIZE(data); n++) { + res = convert_from_string(c, &session, data[n].base, hb); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + res = convert_from_string(c, &session, data[n].exp, he); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + res = convert_from_string(c, &session, data[n].mod, hm); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + res = convert_from_string(c, &session, data[n].result, hr2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + res = cmd_new_fmm_ctx(c, &session, 1024, hm, &hc); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = cmd_expmod(c, &session, hb, he, hm, hc, hr); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = compare_handle(c, &session, hr, hr2, 0); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + res = cmd_free_handle(c, &session, hc); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + } + + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, hb)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, he)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, hm)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, hr)); + ADBG_EXPECT_TEEC_SUCCESS(c, cmd_free_handle(c, &session, hr2)); +out: + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 4117, test_4117, + "Test TEE Internal API Arithmetical API - ExpMod"); diff --git a/optee/optee_test/host/xtest/regression_5000.c b/optee/optee_test/host/xtest/regression_5000.c new file mode 100644 index 0000000..af06548 --- /dev/null +++ b/optee/optee_test/host/xtest/regression_5000.c @@ -0,0 +1,515 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include + +#include "xtest_test.h" +#include "xtest_helpers.h" +#include "tee_api_defines.h" +#include "tee_client_api.h" + +#define OFFSET0 0 + +#define PARAM_0 0 +#define PARAM_1 1 +#define PARAM_2 2 +#define PARAM_3 3 + +struct xtest_session { + ADBG_Case_t *c; + TEEC_Session session; + TEEC_Context context; +}; + +/* Compares two memories and checks if their length and content is the same */ +#define EXPECT_SHARED_MEM_BUFFER(c, exp_buf, exp_blen, op, param_num, shrm) \ + do { \ + if ((exp_buf) == NULL) { \ + ADBG_EXPECT((c), exp_blen, \ + (op)->params[(param_num)].memref.size); \ + } else { \ + ADBG_EXPECT_COMPARE_POINTER((c), (shrm), ==, \ + (op)->params[(param_num)].memref.parent); \ + ADBG_EXPECT_BUFFER((c), (exp_buf), (exp_blen), \ + (shrm)->buffer, \ + (op)->params[(param_num)].memref.size); \ + } \ + } while (0) + +/* + * Compares the content of the memory cells in OP with the expected value + * contained. + */ +#define EXPECT_OP_TMP_MEM_BUFFER(c, exp_buf, exp_blen, op, param_num, buf) \ + do { \ + if ((exp_buf) == NULL) { \ + ADBG_EXPECT((c), exp_blen, \ + (op)->params[(param_num)].tmpref.size); \ + } else { \ + ADBG_EXPECT_COMPARE_POINTER((c), (buf), ==, \ + (op)->params[(param_num)].tmpref.buffer); \ + ADBG_EXPECT_BUFFER((c), (exp_buf), (exp_blen), \ + (buf), \ + (op)->params[(param_num)].memref.size); \ + } \ + } while (0) + +/* Registers the TEEC_SharedMemory to the TEE. */ +static TEEC_Result RegisterSharedMemory(TEEC_Context *ctx, + TEEC_SharedMemory *shm, size_t size, + uint32_t flags) +{ + shm->flags = flags; + shm->size = size; + return TEEC_RegisterSharedMemory(ctx, shm); +} + +/* Allocates shared memory inside of the TEE. */ +static TEEC_Result AllocateSharedMemory(TEEC_Context *ctx, + TEEC_SharedMemory *shm, size_t size, + uint32_t flags) +{ + shm->flags = flags; + shm->size = size; + return TEEC_AllocateSharedMemory(ctx, shm); +} + +static void CloseSession_null(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "CloseSession_null"); + { + /* In reality doesn't test anything. */ + TEEC_CloseSession(NULL); + } + Do_ADBG_EndSubCase(cs->c, "CloseSession_null"); +} + +static void Allocate_In(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Allocate_In"); + { + TEEC_SharedMemory shm = { }; + size_t size = 1024; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + AllocateSharedMemory(&cs->context, &shm, size, + TEEC_MEM_INPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Allocate_In"); +} + +static void Allocate_out_of_memory(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Allocate_out_of_memory"); + { + TEEC_SharedMemory shm = { }; + size_t SIZE_OVER_MEMORY_CAPACITY = SIZE_MAX; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + ADBG_EXPECT_TEEC_RESULT(cs->c, TEEC_ERROR_OUT_OF_MEMORY, + AllocateSharedMemory(&cs->context, &shm, + SIZE_OVER_MEMORY_CAPACITY, + TEEC_MEM_INPUT)); + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Allocate_out_of_memory"); +} + +static void OpenSession_error_notExistingTA(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "OpenSession_error_notExistingTA"); + { + TEEC_UUID NONEXISTING_TA_UUID = { 0x534D1192, 0x6143, 0x234C, + { 0x47, 0x55, 0x53, 0x52, + 0x54, 0x4F, 0x4F, 0x59 } }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + ADBG_EXPECT_COMPARE_UNSIGNED(cs->c, TEEC_SUCCESS, !=, + TEEC_OpenSession(&cs->context, &cs->session, + &NONEXISTING_TA_UUID, + TEEC_LOGIN_PUBLIC, NULL, NULL, + &ret_orig)); + ADBG_EXPECT_COMPARE_UNSIGNED(cs->c, TEEC_ORIGIN_TRUSTED_APP, !=, + ret_orig); + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "OpenSession_error_notExistingTA"); +} + +static void Allocate_InOut(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Allocate_InOut"); + { + TEEC_SharedMemory shm = { }; + uint8_t val[] = { 54, 76, 98, 32 }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + AllocateSharedMemory(&cs->context, &shm, sizeof(val), + TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Allocate_InOut"); +} + +static void Register_In(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Register_In"); + { + TEEC_SharedMemory shm = { }; + uint8_t val[] = { 32, 65, 43, 21, 98 }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + shm.buffer = val; + + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + RegisterSharedMemory(&cs->context, &shm, sizeof(val), + TEEC_MEM_INPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Register_In"); +} + +static void Register_notZeroLength_Out(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Register_notZeroLength_Out"); + { + TEEC_SharedMemory shm = { }; + uint8_t val[] = { 56, 67, 78, 99 }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + shm.buffer = val; + + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + RegisterSharedMemory(&cs->context, &shm, sizeof(val), + TEEC_MEM_OUTPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Register_notZeroLength_Out"); +} + +static void Register_InOut(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Register_InOut"); + { + TEEC_SharedMemory shm = { }; + uint8_t val[] = { 54, 76, 23, 98, 255, 23, 86 }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + shm.buffer = val; + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + RegisterSharedMemory(&cs->context, &shm, sizeof(val), + TEEC_MEM_INPUT | TEEC_MEM_OUTPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Register_InOut"); +} + +static void Register_zeroLength_Out(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Register_zeroLength_Out"); + { + uint8_t val[] = { 65, 76, 98, 32 }; + TEEC_SharedMemory shm = { }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + shm.buffer = val; + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + RegisterSharedMemory(&cs->context, &shm, 0, + TEEC_MEM_OUTPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Register_zeroLength_Out"); +} + +static void Allocate_Out(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Allocate_Out"); + { + TEEC_SharedMemory shm = { }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + AllocateSharedMemory(&cs->context, &shm, 0, + TEEC_MEM_OUTPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Allocate_Out"); +} + +static void FinalizeContext_null(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "FinalizeContext_null"); + { + TEEC_FinalizeContext(NULL); + } + Do_ADBG_EndSubCase(cs->c, "FinalizeContext_null"); +} + +static void InitializeContext_NotExistingTEE(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "InitializeContext_NotExistingTEE"); + { + if (!ADBG_EXPECT_COMPARE_UNSIGNED(cs->c, TEEC_SUCCESS, !=, + TEEC_InitializeContext("Invalid TEE name", + &cs->context))) + TEEC_FinalizeContext(&cs->context); + } + Do_ADBG_EndSubCase(cs->c, "InitializeContext_NotExistingTEE"); +} + +static void AllocateThenRegister_SameMemory(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "AllocateThenRegister_SameMemory"); + { + TEEC_SharedMemory shm = { }; + size_t size_allocation = 32; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + AllocateSharedMemory(&cs->context, &shm, + size_allocation, TEEC_MEM_INPUT))) + goto out_final; + + ADBG_EXPECT_TEEC_SUCCESS(cs->c, + RegisterSharedMemory(&cs->context, &shm, + size_allocation, TEEC_MEM_INPUT)); + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "AllocateThenRegister_SameMemory"); +} + +static void AllocateSameMemory_twice(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "AllocateSameMemory_twice"); + { + TEEC_SharedMemory shm = { }; + size_t size_allocation = 32; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + AllocateSharedMemory(&cs->context, &shm, + size_allocation, TEEC_MEM_INPUT))) + goto out_final; + + ADBG_EXPECT_TEEC_SUCCESS(cs->c, + AllocateSharedMemory(&cs->context, &shm, + size_allocation, TEEC_MEM_INPUT)); + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "AllocateSameMemory_twice"); +} + +static void RegisterSameMemory_twice(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "RegisterSameMemory_twice"); + { + uint8_t val[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + TEEC_SharedMemory shm = { }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + shm.buffer = val; + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + RegisterSharedMemory(&cs->context, &shm, sizeof(val), + TEEC_MEM_INPUT))) + goto out_final; + + ADBG_EXPECT_TEEC_SUCCESS(cs->c, + RegisterSharedMemory(&cs->context, &shm, sizeof(val), + TEEC_MEM_INPUT)); + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "RegisterSameMemory_twice"); +} + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static void Allocate_sharedMemory_32k(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Allocate_sharedMemory_32k"); + { + size_t size = MIN(32 * 1024, + TEEC_CONFIG_SHAREDMEM_MAX_SIZE); + TEEC_SharedMemory shm = { }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + AllocateSharedMemory(&cs->context, &shm, size, + TEEC_MEM_INPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Allocate_sharedMemory_32k"); +} + +#define SHM_32K_SIZE MIN(32 * 1024, TEEC_CONFIG_SHAREDMEM_MAX_SIZE) + +static void Register_sharedMemory_32k(struct xtest_session *cs) +{ + Do_ADBG_BeginSubCase(cs->c, "Register_sharedMemory_32k"); + { + uint8_t val[SHM_32K_SIZE] = { }; + TEEC_SharedMemory shm = { }; + + if (!ADBG_EXPECT(cs->c, TEEC_SUCCESS, + TEEC_InitializeContext(xtest_tee_name, &cs->context))) + goto out; + + shm.buffer = val; + if (!ADBG_EXPECT_TEEC_SUCCESS(cs->c, + RegisterSharedMemory(&cs->context, &shm, SHM_32K_SIZE, + TEEC_MEM_INPUT))) + goto out_final; + + TEEC_ReleaseSharedMemory(&shm); +out_final: + TEEC_FinalizeContext(&cs->context); + } +out: + Do_ADBG_EndSubCase(cs->c, "Register_sharedMemory_32k"); +} + +static void xtest_teec_TEE(ADBG_Case_t *c) +{ + struct xtest_session connection = { c }; + + CloseSession_null(&connection); + + Allocate_In(&connection); + + Allocate_out_of_memory(&connection); + + OpenSession_error_notExistingTA(&connection); + + Allocate_InOut(&connection); + + Register_In(&connection); + + Register_notZeroLength_Out(&connection); + + Register_InOut(&connection); + + Register_zeroLength_Out(&connection); + + Allocate_Out(&connection); + + FinalizeContext_null(&connection); + + InitializeContext_NotExistingTEE(&connection); + + AllocateThenRegister_SameMemory(&connection); + + AllocateSameMemory_twice(&connection); + + RegisterSameMemory_twice(&connection); + + Allocate_sharedMemory_32k(&connection); + + Register_sharedMemory_32k(&connection); +} + +ADBG_CASE_DEFINE(regression, 5006, xtest_teec_TEE, + "Tests for Global platform TEEC"); diff --git a/optee/optee_test/host/xtest/regression_6000.c b/optee/optee_test/host/xtest/regression_6000.c new file mode 100644 index 0000000..e8c5dcb --- /dev/null +++ b/optee/optee_test/host/xtest/regression_6000.c @@ -0,0 +1,2256 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define DEFINE_TEST_MULTIPLE_STORAGE_IDS(test_name) \ +static void test_name(ADBG_Case_t *c) \ +{ \ + size_t i = 0; \ + \ + if (init_storage_info()) { \ + Do_ADBG_Log("init_storage_info() failed"); \ + return; \ + } \ + for (i = 0; i < ARRAY_SIZE(storage_info); i++) { \ + uint32_t id = storage_info[i].id; \ + \ + if (!storage_info[i].available) \ + continue; \ + Do_ADBG_BeginSubCase(c, "Storage id: %08x", id); \ + test_name##_single(c, id); \ + Do_ADBG_EndSubCase(c, "Storage id: %08x", id); \ + } \ +} + +static uint8_t file_00[] = { + 0x00, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, + 0xF0, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, + 0xE9, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, + 0xF0, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x8E +}; + +static uint8_t file_01[] = { + 0x01, 0x00 +}; + +static uint8_t file_02[] = { + 0x02, 0x11, 0x02 +}; + +static uint8_t file_03[] = { + 0x03, 0x13, 0x03 +}; + +static uint8_t file_04[] = { + 0x00, 0x01, 0x02 +}; + +static uint8_t data_00[] = { + 0x00, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, + 0x00, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, + 0x00, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, + 0x00, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x00 +}; + +static uint8_t data_01[] = { + 0x01, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96, + 0x01, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92, + 0x01, 0xC3, 0xEF, 0x8A, 0xB2, 0x34, 0x53, 0xE6, + 0x01, 0x74, 0x9C, 0xD6, 0x36, 0xE7, 0xA8, 0x01 +}; + +static TEEC_Result fs_open(TEEC_Session *sess, void *id, uint32_t id_size, + uint32_t flags, uint32_t *obj, uint32_t storage_id) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t org = 0; + + op.params[0].tmpref.buffer = id; + op.params[0].tmpref.size = id_size; + op.params[1].value.a = flags; + op.params[1].value.b = 0; + op.params[2].value.a = storage_id; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INOUT, TEEC_VALUE_INPUT, + TEEC_NONE); + + res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_OPEN, &op, &org); + + if (res == TEEC_SUCCESS) + *obj = op.params[1].value.b; + + return res; +} + +static TEEC_Result fs_create(TEEC_Session *sess, void *id, uint32_t id_size, + uint32_t flags, uint32_t attr, void *data, + uint32_t data_size, uint32_t *obj, + uint32_t storage_id) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t org = 0; + + op.params[0].tmpref.buffer = id; + op.params[0].tmpref.size = id_size; + op.params[1].value.a = flags; + op.params[1].value.b = 0; + op.params[2].value.a = attr; + op.params[2].value.b = storage_id; + op.params[3].tmpref.buffer = data; + op.params[3].tmpref.size = data_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INOUT, TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT); + + res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_CREATE, &op, &org); + + if (res == TEEC_SUCCESS) + *obj = op.params[1].value.b; + + return res; +} + +static TEEC_Result fs_create_overwrite(TEEC_Session *sess, void *id, + uint32_t id_size, uint32_t storage_id) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t org = 0; + + op.params[0].tmpref.buffer = id; + op.params[0].tmpref.size = id_size; + op.params[1].value.a = storage_id; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_CREATE_OVERWRITE, &op, &org); + + return res; +} + +static TEEC_Result fs_close(TEEC_Session *sess, uint32_t obj) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_CLOSE, &op, &org); +} + +static TEEC_Result fs_read(TEEC_Session *sess, uint32_t obj, void *data, + uint32_t data_size, uint32_t *count) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].tmpref.buffer = data; + op.params[0].tmpref.size = data_size; + op.params[1].value.a = obj; + op.params[1].value.b = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, + TEEC_VALUE_INOUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_READ, &op, &org); + + if (res == TEEC_SUCCESS) + *count = op.params[1].value.b; + + return res; +} + +static TEEC_Result fs_write(TEEC_Session *sess, uint32_t obj, void *data, + uint32_t data_size) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].tmpref.buffer = data; + op.params[0].tmpref.size = data_size; + op.params[1].value.a = obj; + op.params[1].value.b = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_WRITE, &op, &org); +} + +static TEEC_Result fs_seek(TEEC_Session *sess, uint32_t obj, int32_t offset, + int32_t whence) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj; + op.params[0].value.b = *(uint32_t *)&offset; + op.params[1].value.a = whence; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_INOUT, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_SEEK, &op, &org); +} + +static TEEC_Result fs_unlink(TEEC_Session *sess, uint32_t obj) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_UNLINK, &op, &org); +} + +static TEEC_Result fs_trunc(TEEC_Session *sess, uint32_t obj, uint32_t len) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj; + op.params[0].value.b = len; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_TRUNC, &op, &org); +} + +static TEEC_Result fs_rename(TEEC_Session *sess, uint32_t obj, void *id, + uint32_t id_size) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj; + op.params[1].tmpref.buffer = id; + op.params[1].tmpref.size = id_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_RENAME, &op, &org); +} + +static TEEC_Result fs_alloc_enum(TEEC_Session *sess, uint32_t *e) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_ALLOC_ENUM, &op, &org); + + if (res == TEEC_SUCCESS) + *e = op.params[0].value.a; + + return res; +} + +static TEEC_Result fs_reset_enum(TEEC_Session *sess, uint32_t e) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + op.params[0].value.a = e; + res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_RESET_ENUM, &op, &org); + + return res; +} + +static TEEC_Result fs_free_enum(TEEC_Session *sess, uint32_t e) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + op.params[0].value.a = e; + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_FREE_ENUM, &op, &org); +} + +static TEEC_Result fs_start_enum(TEEC_Session *sess, uint32_t e, + uint32_t storage_id) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + op.params[0].value.a = e; + op.params[0].value.b = storage_id; + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_START_ENUM, &op, &org); +} + +static TEEC_Result fs_next_enum(TEEC_Session *sess, uint32_t e, void *obj_info, + size_t info_size, void *id, uint32_t id_size) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + if (obj_info && info_size) + op.paramTypes |= (TEEC_MEMREF_TEMP_OUTPUT << 4); + + op.params[0].value.a = e; + op.params[1].tmpref.buffer = obj_info; + op.params[1].tmpref.size = info_size; + op.params[2].tmpref.buffer = id; + op.params[2].tmpref.size = id_size; + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_NEXT_ENUM, &op, &org); +} + +static TEEC_Result fs_restrict_usage(TEEC_Session *sess, uint32_t obj, + uint32_t obj_usage) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj; + op.params[0].value.b = obj_usage; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_RESTRICT_USAGE, + &op, &org); +} + +static TEEC_Result fs_alloc_obj(TEEC_Session *sess, uint32_t obj_type, + uint32_t max_key_size, uint32_t *obj) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj_type; + op.params[0].value.b = max_key_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_ALLOC_OBJ, &op, &org); + *obj = op.params[1].value.a; + return res; +} + +static TEEC_Result fs_free_obj(TEEC_Session *sess, uint32_t obj) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_FREE_OBJ, &op, &org); +} + +static TEEC_Result fs_reset_obj(TEEC_Session *sess, uint32_t obj) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t org = 0; + + op.params[0].value.a = obj; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + return TEEC_InvokeCommand(sess, TA_STORAGE_CMD_RESET_OBJ, &op, &org); +} + +static TEEC_Result fs_get_obj_info(TEEC_Session *sess, uint32_t obj, + TEE_ObjectInfo *obj_info) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + struct ta_storage_obj_info oi = { }; + uint32_t org = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + op.params[0].value.a = obj; + op.params[1].tmpref.buffer = &oi; + op.params[1].tmpref.size = sizeof(oi); + + res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_GET_OBJ_INFO, &op, &org); + if (!res) { + obj_info->objectType = oi.object_type; + obj_info->objectSize = oi.object_size; + obj_info->maxObjectSize = oi.max_object_size; + obj_info->objectUsage = oi.object_usage; + obj_info->dataSize = oi.data_size; + obj_info->dataPosition = oi.data_position; + obj_info->handleFlags = oi.handle_flags; + } + + return res; +} + +/* Record availability of all secure storage types at runtime */ +struct storage_info { + uint32_t id; + bool available; +}; + +static struct storage_info storage_info[] = { + { .id = TEE_STORAGE_PRIVATE }, + { .id = TEE_STORAGE_PRIVATE_REE }, + { .id = TEE_STORAGE_PRIVATE_RPMB }, +}; + +static TEEC_Result check_storage_available(uint32_t id, bool *avail) +{ + TEE_Result res = TEEC_SUCCESS; + TEEC_Session sess = { }; + uint32_t obj = 0; + uint32_t orig = 0; + char name[] = "xtest_storage_test"; + + res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); + if (res != TEEC_SUCCESS) + return res; + + res = fs_create(&sess, name, sizeof(name), TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, NULL, 0, &obj, id); + switch (res) { + case TEEC_SUCCESS: + *avail = true; + fs_unlink(&sess, obj); + break; + case TEE_ERROR_ITEM_NOT_FOUND: + case TEE_ERROR_STORAGE_NOT_AVAILABLE: + case TEE_ERROR_STORAGE_NOT_AVAILABLE_2: + *avail = false; + res = TEEC_SUCCESS; + break; + default: + res = TEE_ERROR_GENERIC; + break; + } + + + TEEC_CloseSession(&sess); + + return res; +} + +static TEE_Result init_storage_info(void) +{ + TEE_Result res = TEE_SUCCESS; + static bool done = false; + size_t i = 0; + + if (done) + return TEE_SUCCESS; + + for (i = 0; i < ARRAY_SIZE(storage_info); i++) { + res = check_storage_available(storage_info[i].id, + &storage_info[i].available); + if (res) + return res; + } + done = true; + return TEE_SUCCESS; +} + +static bool is_storage_available(uint32_t id) +{ + size_t i = 0; + + if (init_storage_info()) + return false; + + for (i = 0; i < ARRAY_SIZE(storage_info); i++) { + if (id == storage_info[i].id) + return storage_info[i].available; + } + return false; +} + +#ifndef TEE_STORAGE_ILLEGAL_VALUE +/* GP TEE Internal Core API >= 1.2 table 5-2 */ +#define TEE_STORAGE_ILLEGAL_VALUE 0x7FFFFFFF +#endif + +static uint32_t fs_id_for_tee_storage_private(void) +{ + /* + * Assumes that REE FS is preferred over RPMB FS at compile time in + * optee_os + */ + if (is_storage_available(TEE_STORAGE_PRIVATE_REE)) + return TEE_STORAGE_PRIVATE_REE; + if (is_storage_available(TEE_STORAGE_PRIVATE_RPMB)) + return TEE_STORAGE_PRIVATE_RPMB; + + return TEE_STORAGE_ILLEGAL_VALUE; +} + +static uint32_t real_id_for(uint32_t id) +{ + if (id == TEE_STORAGE_PRIVATE) + return fs_id_for_tee_storage_private(); + return id; +} + +static bool storage_is(uint32_t id1, uint32_t id2) +{ + return (real_id_for(id1) == real_id_for(id2)); +} + +/* trunc */ +static void test_truncate_file_length(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint8_t out[10] = { }; + uint32_t count = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + /* create */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + /* trunc */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_trunc(&sess, obj, 10))) + goto exit; + + /* seek */ + if (!ADBG_EXPECT_TEEC_SUCCESS( + c, fs_seek(&sess, obj, 5, TEE_DATA_SEEK_SET))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + /* check buffer */ + (void)ADBG_EXPECT_BUFFER(c, &data_00[5], 5, out, count); + + /* close */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + /* open */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + /* seek */ + if (!ADBG_EXPECT_TEEC_SUCCESS( + c, fs_seek(&sess, obj, 5, TEE_DATA_SEEK_SET))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + /* check buffer */ + (void)ADBG_EXPECT_BUFFER(c, &data_00[5], 5, out, count); + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} + +/* extend */ +static void test_extend_file_length(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint8_t out[10] = { }; + uint8_t expect[10] = { }; + uint32_t count = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + /* create */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + /* extend */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_trunc(&sess, obj, 40))) + goto exit; + + /* seek */ + if (!ADBG_EXPECT_TEEC_SUCCESS( + c, fs_seek(&sess, obj, 30, TEE_DATA_SEEK_SET))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + /* check buffer */ + expect[0] = data_00[30]; + expect[1] = data_00[31]; + (void)ADBG_EXPECT_BUFFER(c, &expect[0], 10, out, count); + + /* close */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + /* open */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + /* seek */ + if (!ADBG_EXPECT_TEEC_SUCCESS( + c, fs_seek(&sess, obj, 30, TEE_DATA_SEEK_SET))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + /* check buffer */ + expect[0] = data_00[30]; + expect[1] = data_00[31]; + (void)ADBG_EXPECT_BUFFER(c, &expect[0], 10, out, count); + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} + +/* file hole */ +static void test_file_hole(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint8_t out[10] = { }; + uint8_t expect[10] = { }; + uint32_t count = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + /* create */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + /* seek */ + if (!ADBG_EXPECT_TEEC_SUCCESS( + c, fs_seek(&sess, obj, 80, TEE_DATA_SEEK_SET))) + goto exit; + + /* write */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_write(&sess, obj, data_00, + sizeof(data_00)))) + goto exit; + + /* seek */ + if (!ADBG_EXPECT_TEEC_SUCCESS( + c, fs_seek(&sess, obj, 74, TEE_DATA_SEEK_SET))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + /* check buffer */ + expect[6] = data_00[0]; + expect[7] = data_00[1]; + expect[8] = data_00[2]; + expect[9] = data_00[3]; + (void)ADBG_EXPECT_BUFFER(c, &expect[0], 10, out, count); + + /* close */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + /* open */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + /* seek */ + if (!ADBG_EXPECT_TEEC_SUCCESS( + c, fs_seek(&sess, obj, 74, TEE_DATA_SEEK_SET))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + /* check buffer */ + expect[6] = data_00[0]; + expect[7] = data_00[1]; + expect[8] = data_00[2]; + expect[9] = data_00[3]; + (void)ADBG_EXPECT_BUFFER(c, &expect[0], 10, out, count); + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} + +/* create */ +static void xtest_tee_test_6001_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, sizeof(file_00), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, 0, + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, NULL, 0, + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6001) +ADBG_CASE_DEFINE(regression, 6001, xtest_tee_test_6001, + "Test TEE_CreatePersistentObject"); + +/* open */ +static void xtest_tee_test_6002_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, 0, + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_01, 0, + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, NULL, 0, + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, NULL, 0, + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6002) +ADBG_CASE_DEFINE(regression, 6002, xtest_tee_test_6002, + "Test TEE_OpenPersistentObject"); + +/* read */ +static void xtest_tee_test_6003_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint8_t out[10] = { }; + uint32_t count = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, + sizeof(data_01), &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + (void)ADBG_EXPECT_BUFFER(c, data_01, 10, out, count); + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6003) +ADBG_CASE_DEFINE(regression, 6003, xtest_tee_test_6003, + "Test TEE_ReadObjectData"); + +/* write */ +static void xtest_tee_test_6004_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint8_t out[10] = { }; + uint32_t count = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + /* create */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, + sizeof(data_01), &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + /* write new data */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_WRITE, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_write(&sess, obj, data_00, sizeof(data_00)))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + (void)ADBG_EXPECT_BUFFER(c, data_00, 10, out, count); + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6004) +ADBG_CASE_DEFINE(regression, 6004, xtest_tee_test_6004, + "Test TEE_WriteObjectData"); + +/* seek */ +static void xtest_tee_test_6005_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint8_t out[10] = { }; + uint32_t count = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + /* create */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + /* seek */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_seek(&sess, obj, 10, TEE_DATA_SEEK_SET))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + (void)ADBG_EXPECT_BUFFER(c, &data_00[10], 10, out, count); + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6005) +ADBG_CASE_DEFINE(regression, 6005, xtest_tee_test_6005, + "Test TEE_SeekObjectData"); + +/* unlink */ +static void xtest_tee_test_6006_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + /* create */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + /* del & close */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + + /* check result */ + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND, + fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_READ, &obj, storage_id))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6006) +ADBG_CASE_DEFINE(regression, 6006, xtest_tee_test_6006, + "Test TEE_CloseAndDeletePersistentObject"); + +static void xtest_tee_test_6007_single(ADBG_Case_t *c, uint32_t storage_id) +{ + Do_ADBG_BeginSubCase(c, "Test truncate file length"); + test_truncate_file_length(c, storage_id); + Do_ADBG_EndSubCase(c, "Test truncate file length"); + + Do_ADBG_BeginSubCase(c, "Test extend file length"); + test_extend_file_length(c, storage_id); + Do_ADBG_EndSubCase(c, "Test extend file length"); + + Do_ADBG_BeginSubCase(c, "Test file hole"); + test_file_hole(c, storage_id); + Do_ADBG_EndSubCase(c, "Test file hole"); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6007) +ADBG_CASE_DEFINE(regression, 6007, xtest_tee_test_6007, + "Test TEE_TruncateObjectData"); + +static void xtest_tee_test_6008_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj = 0; + uint8_t out[10] = { }; + uint32_t count = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + /* create */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, + sizeof(data_01), &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + /* write new data */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_write(&sess, obj, data_00, sizeof(data_00)))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_rename(&sess, obj, file_03, sizeof(file_03)))) + goto exit; + + /* close */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_03, sizeof(file_03), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + /* check buffer */ + (void)ADBG_EXPECT_BUFFER(c, data_00, 10, out, count); + + /* Object ID = (non-NULL, 0) */ + + memset(out, 0, sizeof(out)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_rename(&sess, obj, file_03, 0))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_03, 0, + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + (void)ADBG_EXPECT_BUFFER(c, data_00, 10, out, count); + + /* Object ID = (NULL, 0) */ + + memset(out, 0, sizeof(out)); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_rename(&sess, obj, file_03, sizeof(file_03)))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_rename(&sess, obj, NULL, 0))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, NULL, 0, + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + (void)ADBG_EXPECT_BUFFER(c, data_00, 10, out, count); + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6008) +ADBG_CASE_DEFINE(regression, 6008, xtest_tee_test_6008, + "Test TEE_RenamePersistentObject"); + +static void xtest_tee_test_6009_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t obj0 = 0; + uint32_t obj1 = 0; + uint32_t obj2 = 0; + uint32_t e = 0; + uint8_t info[200] = { }; + uint8_t id[200] = { }; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + /* create file 00 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, sizeof(file_00), + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, + sizeof(data_01), &obj0, storage_id))) + goto exit; + + /* create file 01 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, + sizeof(data_01), &obj1, storage_id))) + goto exit; + + /* create file 02 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, + sizeof(data_01), &obj2, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj0))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj1))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj2))) + goto exit; + + /* iterate */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_alloc_enum(&sess, &e))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_start_enum(&sess, e, storage_id))) + goto exit; + + /* get 00 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_next_enum(&sess, e, info, sizeof(info), id, sizeof(id)))) + goto exit; + + /* get 01 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_next_enum(&sess, e, NULL, 0, id, sizeof(id)))) + goto exit; + + /* get 02 */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_next_enum(&sess, e, info, sizeof(info), id, sizeof(id)))) + goto exit; + + /* we should not have more files */ + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND, + fs_next_enum(&sess, e, info, sizeof(info), id, sizeof(id)))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_free_enum(&sess, e))) + goto exit; + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_00, sizeof(file_00), + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj0, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj0))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj1, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj1))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_02, sizeof(file_02), + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj2, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj2))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6009) +ADBG_CASE_DEFINE(regression, 6009, xtest_tee_test_6009, + "Test TEE Internal API Persistent Object Enumeration Functions"); + +static void xtest_tee_test_6010_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t orig = 0; + uint32_t o1 = 0; + uint32_t o2 = 0; + uint32_t e = 0; + uint32_t f = 0; + uint8_t data[1024] = { }; + uint8_t out[1024] = { }; + uint32_t n = 0; + + for (n = 0; n < ARRAY_SIZE(data); n++) + data[n] = n; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + Do_ADBG_BeginSubCase(c, "CreatePersistentObject AccessConflict"); + + o1 = TEE_HANDLE_NULL; + o2 = TEE_HANDLE_NULL; + f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; + + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, sizeof(file_00), f, 0, data, + sizeof(data), &o1, storage_id)); + + f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE; + ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ACCESS_CONFLICT, + fs_create(&sess, file_00, sizeof(file_00), f, 0, data, + sizeof(data), &o2, storage_id)); + + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); + if (o2) + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o2)); + + Do_ADBG_EndSubCase(c, "CreatePersistentObject AccessConflict"); + + + + Do_ADBG_BeginSubCase(c, "RestrictObjectUsage Panic"); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, + fs_restrict_usage(&sess, 0xffffbad0, 0xffffffff)); + Do_ADBG_EndSubCase(c, "RestrictObjectUsage Panic"); + + TEEC_CloseSession(&sess); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + Do_ADBG_BeginSubCase(c, "SeekObjectData BadHandle"); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, + fs_seek(&sess, 0xffffbad0, 5, TEE_DATA_SEEK_SET)); + Do_ADBG_EndSubCase(c, "SeekObjectData BadHandle"); + + TEEC_CloseSession(&sess); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + Do_ADBG_BeginSubCase(c, "SeekObjectData NotPersist"); + o1 = 0; + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_alloc_obj(&sess, TEE_TYPE_AES, 256, &o1)); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, + fs_seek(&sess, o1, 5, TEE_DATA_SEEK_SET)); + Do_ADBG_EndSubCase(c, "SeekObjectData NotPersist"); + + TEEC_CloseSession(&sess); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + Do_ADBG_BeginSubCase(c, "SeekWriteRead"); + o1 = 0; + f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, sizeof(file_00), f, 0, data, + sizeof(data), &o1, storage_id))) + goto seek_write_read_out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_seek(&sess, o1, 2, TEE_DATA_SEEK_SET))) + goto seek_write_read_out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_seek(&sess, o1, 0, TEE_DATA_SEEK_END))) + goto seek_write_read_out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_write(&sess, o1, data, sizeof(data)))) + goto seek_write_read_out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_seek(&sess, o1, sizeof(data), TEE_DATA_SEEK_SET))) + goto seek_write_read_out; + + memset(out, 0xab, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_read(&sess, o1, out, sizeof(out), &n))) + goto seek_write_read_out; + + ADBG_EXPECT_BUFFER(c, data, sizeof(data), out, n); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_seek(&sess, o1, 10, TEE_DATA_SEEK_END))) + goto seek_write_read_out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_read(&sess, o1, out, sizeof(out), &n))) + goto seek_write_read_out; + ADBG_EXPECT_COMPARE_UNSIGNED(c, n, ==, 0); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_seek(&sess, o1, -(int32_t)sizeof(data) / 2, + TEE_DATA_SEEK_END))) + goto seek_write_read_out; + + memset(out, 0xab, sizeof(out) / 2); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_read(&sess, o1, out, sizeof(out) / 2, &n))) + goto seek_write_read_out; + + ADBG_EXPECT_BUFFER(c, + data + sizeof(data) / 2, sizeof(data) / 2, + out, n); + +seek_write_read_out: + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); + Do_ADBG_EndSubCase(c, "SeekWriteRead"); + + Do_ADBG_BeginSubCase(c, "Rename Access Conflict"); + + o1 = TEE_HANDLE_NULL; + o2 = TEE_HANDLE_NULL; + f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, sizeof(file_00), f, 0, data, + sizeof(data), &o1, storage_id)); + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), f, 0, data, + sizeof(data) / 2, &o2, storage_id)); + + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_ACCESS_CONFLICT, + fs_rename(&sess, o2, file_00, sizeof(file_00))); + + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o2)); + + Do_ADBG_EndSubCase(c, "Rename Access Conflict"); + + Do_ADBG_BeginSubCase(c, "Rename Access Conflict 2"); + + o1 = TEE_HANDLE_NULL; + o2 = TEE_HANDLE_NULL; + f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, sizeof(file_00), f, 0, data, + sizeof(data), &o1, storage_id)); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, o1)); + + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), f, 0, data, + sizeof(data) / 2, &o2, storage_id)); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_ACCESS_CONFLICT, + fs_rename(&sess, o2, file_00, sizeof(file_00))); + + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, sizeof(file_00), f, 0, data, + sizeof(data), &o1, storage_id)); + + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o2)); + + Do_ADBG_EndSubCase(c, "Rename Access Conflict 2"); + + Do_ADBG_BeginSubCase(c, "AllocPersistentObjectEnumerator + " + "ResetPersistentObjectEnumerator"); + e = TEE_HANDLE_NULL; + ADBG_EXPECT_TEEC_SUCCESS(c, fs_alloc_enum(&sess, &e)); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_reset_enum(&sess, e)); + Do_ADBG_EndSubCase(c, "AllocPersistentObjectEnumerator + " + "ResetPersistentObjectEnumerator"); + + Do_ADBG_BeginSubCase(c, "StartPersistentObjectEnumerator ItemNotFound"); + e = TEE_HANDLE_NULL; + ADBG_EXPECT_TEEC_SUCCESS(c, fs_alloc_enum(&sess, &e)); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_ITEM_NOT_FOUND, + fs_next_enum(&sess, e, NULL, 0, out, sizeof(out))); + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_ITEM_NOT_FOUND, + fs_start_enum(&sess, e, storage_id)); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_free_enum(&sess, e)); + Do_ADBG_EndSubCase(c, "StartPersistentObjectEnumerator ItemNotFound"); + + Do_ADBG_BeginSubCase(c, "RenamePersistent ReadWrite"); + o1 = TEE_HANDLE_NULL; + f = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_00, sizeof(file_00), f, 0, data, + sizeof(data), &o1, storage_id)); + ADBG_EXPECT_TEEC_SUCCESS(c, + fs_rename(&sess, o1, file_01, sizeof(file_01))); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, o1)); + Do_ADBG_EndSubCase(c, "RenamePersistent ReadWrite"); + + Do_ADBG_BeginSubCase(c, "Close Free Reset Null"); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, TEE_HANDLE_NULL)); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_free_obj(&sess, TEE_HANDLE_NULL)); + ADBG_EXPECT_TEEC_SUCCESS(c, fs_reset_obj(&sess, TEE_HANDLE_NULL)); + Do_ADBG_EndSubCase(c, "Close Free Reset Null"); + + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6010) +ADBG_CASE_DEFINE(regression, 6010, xtest_tee_test_6010, "Test Storage"); + +static void xtest_tee_test_6012_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t orig = 0; + uint32_t obj = 0; + + /* + * create the object a first time (forced through with overwrite attribute) + */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create_overwrite(&sess, file_04, sizeof(file_04), storage_id))) + goto bail1; + + TEEC_CloseSession(&sess); + + /* + * re-create the object two times with overwrite attribute + */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create_overwrite(&sess, file_04, sizeof(file_04), + storage_id))) + goto bail1; + + /* re-create it with an object */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_04, sizeof(file_04), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_OVERWRITE, 0, NULL, 0, &obj, + storage_id))) + goto bail2; + + TEEC_CloseSession(&sess); + + /* + * re-create it again without overwrite flag: should fail and + * existing object should not be altered. + */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ACCESS_CONFLICT, + fs_create(&sess, file_04, sizeof(file_04), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, NULL, 0, &obj, + storage_id))) + goto bail2; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_04, sizeof(file_04), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, + storage_id))) + goto bail1; + +bail2: + /* remove the object so that xtest 600x can be replayed */ + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); +bail1: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6012) +ADBG_CASE_DEFINE(regression, 6012, xtest_tee_test_6012, + "Test TEE GP TTA DS init objects"); + +static void xtest_tee_test_6013_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t orig = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + op.params[0].value.a = storage_id; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, TA_STORAGE_CMD_KEY_IN_PERSISTENT, + &op, &orig)); + + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6013) +ADBG_CASE_DEFINE(regression, 6013, xtest_tee_test_6013, + "Key usage in Persistent objects"); + +static void xtest_tee_test_6014_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + uint32_t orig = 0; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + op.params[0].value.a = storage_id; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, + TEEC_NONE, TEEC_NONE); + + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&sess, TA_STORAGE_CMD_LOOP, &op, &orig)); + + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6014) +ADBG_CASE_DEFINE(regression, 6014, xtest_tee_test_6014, + "Loop on Persistent objects"); + +static void xtest_tee_test_6015_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + TEEC_Session sess2 = { }; + uint32_t orig = 0; + uint32_t obj = 0; + uint32_t obj2 = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess2, &storage2_ta_uuid, NULL, + &orig))) + goto exit2; + + /* TA #1 creates a persistent object */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit; + + /* TA #2 tries to open the object created by TA #1 */ + if (!ADBG_EXPECT_TEEC_RESULT(c, TEEC_ERROR_ITEM_NOT_FOUND, + fs_open(&sess2, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_READ, &obj2, storage_id))) + goto clean; + +clean: + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); +exit: + TEEC_CloseSession(&sess2); +exit2: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6015) +ADBG_CASE_DEFINE(regression, 6015, xtest_tee_test_6015, "Storage isolation"); + +struct test_6016_thread_arg { + ADBG_Case_t *case_t; + uint32_t storage_id; + char file_name[8]; + TEEC_Session session; +}; + +static void *test_6016_thread(void *arg) +{ + struct test_6016_thread_arg *a = arg; + TEEC_Session sess = a->session; + uint32_t obj = 0; + uint8_t out[10] = { }; + uint32_t count = 0; + + /* create */ + if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, + fs_create(&sess, a->file_name, sizeof(a->file_name), + TEE_DATA_FLAG_ACCESS_WRITE, 0, data_01, + sizeof(data_01), &obj, a->storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, fs_close(&sess, obj))) + goto exit; + + /* write new data */ + if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, + fs_open(&sess, a->file_name, sizeof(a->file_name), + TEE_DATA_FLAG_ACCESS_WRITE, &obj, a->storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, + fs_write(&sess, obj, data_00, sizeof(data_00)))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, fs_close(&sess, obj))) + goto exit; + + /* verify */ + if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, + fs_open(&sess, a->file_name, sizeof(a->file_name), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, a->storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, + fs_read(&sess, obj, out, 10, &count))) + goto exit; + + (void)ADBG_EXPECT_BUFFER(a->case_t, data_00, 10, out, count); + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(a->case_t, fs_unlink(&sess, obj))) + goto exit; + +exit: + return NULL; +} + + +#define NUM_THREADS 3 +static void xtest_tee_test_6016_loop(ADBG_Case_t *c, uint32_t storage_id) +{ + struct test_6016_thread_arg arg[NUM_THREADS] = { }; + uint32_t orig = 0; + size_t i = 0; + size_t n = 0; + size_t m = 0; + pthread_t thr[NUM_THREADS] = { }; + + for (m = 0; m < NUM_THREADS; m++) + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&arg[m].session, + &storage_ta_uuid, NULL, &orig))) + goto out; + + for (n = 0; n < NUM_THREADS; n++) { + arg[n].case_t = c; + arg[n].storage_id = storage_id; + snprintf(arg[n].file_name, sizeof(arg[n].file_name), + "file_%zu", n); + if (!ADBG_EXPECT(c, 0, pthread_create(thr + n, NULL, + test_6016_thread, arg + n))) + goto out; + } + +out: + for (i = 0; i < n; i++) + ADBG_EXPECT(c, 0, pthread_join(thr[i], NULL)); + for (i = 0; i < m; i++) + TEEC_CloseSession(&arg[i].session); +} + +/* concurency */ +static void xtest_tee_test_6016_single(ADBG_Case_t *c, uint32_t storage_id) +{ + int i = 0; + int loops = 8; + + Do_ADBG_Log(" threads: %d, loops: %d", NUM_THREADS, loops); + for (i = 0; i < loops; i++) + xtest_tee_test_6016_loop(c, storage_id); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6016) +ADBG_CASE_DEFINE(regression, 6016, xtest_tee_test_6016, "Storage concurency"); + +static void xtest_tee_test_6017_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + TEE_ObjectInfo obj_info1 = { }; + TEE_ObjectInfo obj_info2 = { }; + uint32_t obj = 0; + uint32_t orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE, 0, NULL, + 0, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_write(&sess, obj, data_00, sizeof(data_00)))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_get_obj_info(&sess, obj, &obj_info1))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_get_obj_info(&sess, obj, &obj_info2))) + goto exit; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + obj_info1.dataSize, ==, obj_info2.dataSize)) + goto exit; + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6017) +ADBG_CASE_DEFINE(regression, 6017, xtest_tee_test_6017, + "Test Persistent objects info"); + +static void xtest_tee_test_6018_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + TEE_ObjectInfo obj_info1 = { }; + TEE_ObjectInfo obj_info2 = { }; + uint32_t obj = 0; + uint32_t orig = 0; + uint8_t block[32 * 1024] = { }; + size_t num_blocks = 0; + size_t block_size = 0; + size_t n = 0; + + if (storage_is(storage_id, TEE_STORAGE_PRIVATE_RPMB)) { + /* RPMB FS is a bit resource constrained */ + num_blocks = 10; + block_size = 1024; + } else { + num_blocks = 20; + block_size = sizeof(block); + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE, 0, NULL, + 0, &obj, storage_id))) + goto exit; + + for (n = 0; n < num_blocks; n++) { + memset(block, n, block_size); + + Do_ADBG_Log("writing %zu", n); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_write(&sess, obj, block, block_size))) + goto exit; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_get_obj_info(&sess, obj, &obj_info1))) + goto exit; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + obj_info1.dataSize, ==, block_size * num_blocks)) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_get_obj_info(&sess, obj, &obj_info2))) + goto exit; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + obj_info1.dataSize, ==, obj_info2.dataSize)) + goto exit; + + for (n = 0; n < num_blocks; n++) { + uint8_t br[block_size]; + uint32_t count = 0; + + memset(br, 0, sizeof(br)); + memset(block, n, block_size); + + Do_ADBG_Log("reading %zu", n); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_read(&sess, obj, br, sizeof(br), &count))) + goto exit; + if (!ADBG_EXPECT_BUFFER(c, block, block_size, br, count)) + goto exit; + } + + /* clean */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6018) +ADBG_CASE_DEFINE(regression, 6018, xtest_tee_test_6018, "Large object"); + +static void xtest_tee_test_6019_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Session sess = { }; + TEEC_Session sess2 = { }; + uint32_t orig = 0; + uint32_t obj = 0; + uint32_t obj2 = 0; + uint8_t out[10] = { }; + uint32_t count = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig))) + return; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&sess2, &storage2_ta_uuid, NULL, + &orig))) + goto exit3; + + /* TA #1 creates a persistent object */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_OVERWRITE, 0, data_00, + sizeof(data_00), &obj, storage_id))) + goto exit2; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit1; + + /* TA #2 creates a persistent object */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_create(&sess2, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_OVERWRITE, 0, data_01, + sizeof(data_01), &obj2, storage_id))) + goto exit1; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess2, obj2))) + goto exit; + + /* TA #1 open and read */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess, obj, out, 10, &count))) + goto exit; + + /* verify */ + (void)ADBG_EXPECT_BUFFER(c, data_00, 10, out, count); + + /* TA #2 open and read */ + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + fs_open(&sess2, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE_META, &obj2, storage_id))) + goto exit; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_read(&sess2, obj2, out, 10, &count))) + goto exit; + + /* verify */ + (void)ADBG_EXPECT_BUFFER(c, data_01, 10, out, count); + +exit: + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess2, obj2)); +exit1: + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); +exit2: + TEEC_CloseSession(&sess2); +exit3: + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6019) +ADBG_CASE_DEFINE(regression, 6019, xtest_tee_test_6019, "Storage independence"); + +/* + * According to the GP spec V1.1, the object_id in create/open/rename + * functions is not allowed to reside in the shared memory. + * + * The function below replicates fs_open/fs_create/fs_rename but using + * specific commands to ask the TA to use the client object ID buffer + * from the shared memory when accessing the object through target APIs. + * The TA is not expected to use such references and gets killed by the TEE. + */ +static TEEC_Result fs_access_with_bad_object_id_ref(TEEC_Session *sess, + uint32_t command, + void *id, uint32_t id_size, + uint32_t flags, + uint32_t attr, + void *data, uint32_t data_size, + uint32_t *obj, + uint32_t storage_id) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t org = 0; + + switch (command) { + case TA_STORAGE_CMD_OPEN_ID_IN_SHM: + op.params[0].tmpref.buffer = id; + op.params[0].tmpref.size = id_size; + op.params[1].value.a = flags; + op.params[1].value.b = 0; + op.params[2].value.a = storage_id; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INOUT, + TEEC_VALUE_INPUT, + TEEC_NONE); + break; + case TA_STORAGE_CMD_CREATE_ID_IN_SHM: + op.params[0].tmpref.buffer = id; + op.params[0].tmpref.size = id_size; + op.params[1].value.a = flags; + op.params[1].value.b = 0; + op.params[2].value.a = attr; + op.params[2].value.b = storage_id; + op.params[3].tmpref.buffer = data; + op.params[3].tmpref.size = data_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INOUT, + TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT); + break; + case TA_STORAGE_CMD_CREATEOVER_ID_IN_SHM: + op.params[0].tmpref.buffer = id; + op.params[0].tmpref.size = id_size; + op.params[1].value.a = storage_id; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + break; + case TA_STORAGE_CMD_RENAME_ID_IN_SHM: + op.params[0].value.a = *obj; + op.params[1].tmpref.buffer = id; + op.params[1].tmpref.size = id_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE); + break; + default: + return TEE_ERROR_GENERIC; + } + + res = TEEC_InvokeCommand(sess, command, &op, &org); + + switch (command) { + case TA_STORAGE_CMD_OPEN_ID_IN_SHM: + case TA_STORAGE_CMD_CREATE_ID_IN_SHM: + if (res == TEEC_SUCCESS) + *obj = op.params[1].value.b; + break; + default: + break; + } + + return res; +} + +static void xtest_tee_test_6020_single(ADBG_Case_t *c, uint32_t storage_id) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session sess = { }; + uint32_t orig = 0; + uint32_t obj = 0; + + /* + * Invalid open request from the TA (object ID reference in SHM) + */ + res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + res = fs_create(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_OVERWRITE, + 0, + data_00, sizeof(data_00), + &obj, + storage_id); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit1; + if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_close(&sess, obj))) + goto exit1; + + res = fs_access_with_bad_object_id_ref(&sess, + TA_STORAGE_CMD_OPEN_ID_IN_SHM, + file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, + 0, + NULL, 0, + &obj, + storage_id); + + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, res); + + /* + * Invalid create-overwrite request from the TA (object ID reference in SHM) + */ + TEEC_CloseSession(&sess); + res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + res = fs_access_with_bad_object_id_ref(&sess, + TA_STORAGE_CMD_CREATEOVER_ID_IN_SHM, + file_01, sizeof(file_01), + 0, + 0, + NULL, 0, + NULL, + storage_id); + + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, res); + + /* + * Invalid rename request from the TA (object ID reference in SHM) + */ + TEEC_CloseSession(&sess); + res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + res = fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, + &obj, + storage_id); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit1; + + res = fs_access_with_bad_object_id_ref(&sess, + TA_STORAGE_CMD_RENAME_ID_IN_SHM, + file_01, sizeof(file_01) - 1, + 0, + 0, + NULL, 0, + &obj, + 0); + + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, res); + + /* + * Invalid creation request from the TA (object ID reference in SHM) + */ + TEEC_CloseSession(&sess); + res = xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return; + + res = fs_open(&sess, file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, + &obj, + storage_id); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto exit1; + + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); + + res = fs_access_with_bad_object_id_ref(&sess, + TA_STORAGE_CMD_CREATE_ID_IN_SHM, + file_01, sizeof(file_01), + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_OVERWRITE, + 0, + data_00, sizeof(data_00), + &obj, + storage_id); + + ADBG_EXPECT_TEEC_RESULT(c, TEE_ERROR_TARGET_DEAD, res); + TEEC_CloseSession(&sess); + return; +exit1: + ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)); + TEEC_CloseSession(&sess); +} +DEFINE_TEST_MULTIPLE_STORAGE_IDS(xtest_tee_test_6020) +ADBG_CASE_DEFINE(regression, 6020, xtest_tee_test_6020, + "Object IDs in SHM (negative)"); diff --git a/optee/optee_test/host/xtest/regression_8000.c b/optee/optee_test/host/xtest/regression_8000.c new file mode 100644 index 0000000..c7bc0a6 --- /dev/null +++ b/optee/optee_test/host/xtest/regression_8000.c @@ -0,0 +1,760 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, Linaro Limited + */ +#include "xtest_test.h" +#include "xtest_helpers.h" + +#include +#include +#include +#include +#include +#include +#include + +#define WITH_HKDF 1 +#define WITH_CONCAT_KDF 1 +#define WITH_PBKDF2 1 + +/* + * HKDF test data from RFC 5869 + */ + +/* A.1 SHA-256 */ + +static const uint8_t hkdf_a1_ikm[] = { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b +}; + +static const uint8_t hkdf_a1_salt[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c +}; + +static const uint8_t hkdf_a1_info[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9 +}; + +static const uint8_t hkdf_a1_okm[] = { + 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, + 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, + 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, + 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, + 0x58, 0x65 +}; + +/* A.2 SHA-256 */ +static const uint8_t hkdf_a2_ikm[] = { + 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 +}; + +static const uint8_t hkdf_a2_salt[] = { + 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 +}; + +static const uint8_t hkdf_a2_info[] = { + 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 +}; + +static const uint8_t hkdf_a2_okm[] = { + 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, + 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, + 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, + 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, + 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, + 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, + 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, + 0x1d, 0x87 +}; + +/* A.3 SHA-256 */ +#define hkdf_a3_ikm hkdf_a1_ikm +static const uint8_t hkdf_a3_salt[] = {}; + +static const uint8_t hkdf_a3_info[] = {}; + +static const uint8_t hkdf_a3_okm[] = { + 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, + 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, + 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, + 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, + 0x96, 0xc8 +}; + +/* A.4 SHA-1 */ +static const uint8_t hkdf_a4_ikm[] = { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b +}; + +static const uint8_t hkdf_a4_salt[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c +}; + +static const uint8_t hkdf_a4_info[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9 +}; + +static const uint8_t hkdf_a4_okm[] = { + 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, + 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, + 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, + 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, + 0xf8, 0x96 +}; + +/* A.5 SHA-1 */ +#define hkdf_a5_ikm hkdf_a2_ikm +#define hkdf_a5_salt hkdf_a2_salt +#define hkdf_a5_info hkdf_a2_info +static const uint8_t hkdf_a5_okm[] = { + 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, + 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, + 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, + 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, + 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, + 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, + 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, + 0xd3, 0xb4 +}; + +/* A.6 SHA-1 */ +#define hkdf_a6_ikm hkdf_a1_ikm +static const uint8_t hkdf_a6_salt[] = {}; + +static const uint8_t hkdf_a6_info[] = {}; + +static const uint8_t hkdf_a6_okm[] = { + 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, + 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, + 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, + 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, + 0x49, 0x18 +}; + +/* A.7 SHA-1 */ +static const uint8_t hkdf_a7_ikm[] = { + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c +}; + +static const uint8_t hkdf_a7_salt[] = {}; + +static const uint8_t hkdf_a7_info[] = {}; + +static const uint8_t hkdf_a7_okm[] = { + 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, + 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, + 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, + 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, + 0xfc, 0x48 +}; + +/* + * Concat KDF (NIST SP 800-56A R1) + * + * Test vector from: + * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-37 + * appendix C + */ +static const uint8_t concat_kdf_1_z[] = { + 158, 86, 217, 29, 129, 113, 53, 211, + 114, 131, 66, 131, 191, 132, 38, 156, + 251, 49, 110, 163, 218, 128, 106, 72, + 246, 218, 167, 121, 140, 254, 144, 196 +}; + +static const uint8_t concat_kdf_1_other_info[] = { + 0, 0, 0, 7, 65, 49, 50, 56, + 71, 67, 77, 0, 0, 0, 5, 65, + 108, 105, 99, 101, 0, 0, 0, 3, + 66, 111, 98, 0, 0, 0, 128 +}; + +static const uint8_t concat_kdf_1_derived_key[] = { + 86, 170, 141, 234, 248, 35, 109, 32, + 92, 34, 40, 205, 113, 167, 16, 26 +}; + +/* + * PKCS #5 2.0 / RFC 2898 Key Derivation Function 2 (PBKDF2) + * Test vectors from RFC 6070 https://www.ietf.org/rfc/rfc6070.txt + */ + +/* 1 */ +static const uint8_t pbkdf2_1_password[] = { + 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' +}; + +static const uint8_t pbkdf2_1_salt[] = { + 's', 'a', 'l', 't' +}; + +#define pbkdf2_1_iteration_count 1 +static const uint8_t pbkdf2_1_dkm[] = { + 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 +}; + +/* 2 */ +#define pbkdf2_2_password pbkdf2_1_password +#define pbkdf2_2_salt pbkdf2_1_salt +#define pbkdf2_2_iteration_count 2 +static const uint8_t pbkdf2_2_dkm[] = { + 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 +}; + +/* 3 */ +#define pbkdf2_3_password pbkdf2_1_password +#define pbkdf2_3_salt pbkdf2_1_salt +#define pbkdf2_3_iteration_count 4096 +static const uint8_t pbkdf2_3_dkm[] = { + 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 +}; + +/* 4 */ +#define pbkdf2_4_password pbkdf2_1_password +#define pbkdf2_4_salt pbkdf2_1_salt +#define pbkdf2_4_iteration_count 16777216 +static const uint8_t pbkdf2_4_dkm[] = { + 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, + 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, + 0x26, 0x34, 0xe9, 0x84 +}; + +/* 5 */ +static const uint8_t pbkdf2_5_password[] = { + 'p', 'a', 's', 's', 'w', 'o', 'r', 'd', + 'P', 'A', 'S', 'S', 'W', 'O', 'R', 'D', + 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' +}; + +static const uint8_t pbkdf2_5_salt[] = { + 's', 'a', 'l', 't', 'S', 'A', 'L', 'T', + 's', 'a', 'l', 't', 'S', 'A', 'L', 'T', + 's', 'a', 'l', 't', 'S', 'A', 'L', 'T', + 's', 'a', 'l', 't', 'S', 'A', 'L', 'T', + 's', 'a', 'l', 't' +}; + +#define pbkdf2_5_iteration_count 4096 +static const uint8_t pbkdf2_5_dkm[] = { + 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 +}; + +/* 6 */ +static const uint8_t pbkdf2_6_password[] = { + 'p', 'a', 's', 's', '\0', 'w', 'o', 'r', + 'd', +}; + +static const uint8_t pbkdf2_6_salt[] = { + 's', 'a', '\0', 'l', 't' +}; + +#define pbkdf2_6_iteration_count 4096 +static const uint8_t pbkdf2_6_dkm[] = { + 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 +}; + +#ifdef WITH_HKDF +static void xtest_test_derivation_hkdf(ADBG_Case_t *c, TEEC_Session *session) +{ + size_t n = 0; +#define TEST_HKDF_DATA(section, algo, id, oeb /* omit empty bufs */) \ + { \ + section, algo, \ + hkdf_##id##_ikm, sizeof(hkdf_##id##_ikm), \ + (oeb && !sizeof(hkdf_##id##_salt)) ? NULL : hkdf_##id##_salt, sizeof(hkdf_##id##_salt), \ + (oeb && !sizeof(hkdf_##id##_info)) ? NULL : hkdf_##id##_info, sizeof(hkdf_##id##_info), \ + hkdf_##id##_okm, sizeof(hkdf_##id##_okm), \ + } + static struct hkdf_case { + const char *subcase_name; + uint32_t algo; + const uint8_t *ikm; + size_t ikm_len; + const uint8_t *salt; + size_t salt_len; + const uint8_t *info; + size_t info_len; + const uint8_t *okm; + size_t okm_len; + } hkdf_cases[] = { + TEST_HKDF_DATA("A.1 (SHA-256)", + TEE_ALG_HKDF_SHA256_DERIVE_KEY, a1, false), + TEST_HKDF_DATA("A.2 (SHA-256)", + TEE_ALG_HKDF_SHA256_DERIVE_KEY, a2, false), + TEST_HKDF_DATA("A.3 (SHA-256) [1]", + TEE_ALG_HKDF_SHA256_DERIVE_KEY, a3, false), + TEST_HKDF_DATA("A.3 (SHA-256) [2]", + TEE_ALG_HKDF_SHA256_DERIVE_KEY, a3, true), + TEST_HKDF_DATA("A.4 (SHA-1)", + TEE_ALG_HKDF_SHA1_DERIVE_KEY, a4, false), + TEST_HKDF_DATA("A.5 (SHA-1)", + TEE_ALG_HKDF_SHA1_DERIVE_KEY, a5, false), + TEST_HKDF_DATA("A.6 (SHA-1) [1]", + TEE_ALG_HKDF_SHA1_DERIVE_KEY, a6, false), + TEST_HKDF_DATA("A.6 (SHA-1) [2]", + TEE_ALG_HKDF_SHA1_DERIVE_KEY, a6, true), + TEST_HKDF_DATA("A.7 (SHA-1) [1]", + TEE_ALG_HKDF_SHA1_DERIVE_KEY, a7, false), + TEST_HKDF_DATA("A.7 (SHA-1) [2]", + TEE_ALG_HKDF_SHA1_DERIVE_KEY, a7, true), + }; + size_t max_size = 2048; + + for (n = 0; n < sizeof(hkdf_cases) / sizeof(struct hkdf_case); n++) { + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle key_handle = TEE_HANDLE_NULL; + TEE_ObjectHandle sv_handle = TEE_HANDLE_NULL; + TEE_Attribute params[4] = { }; + size_t param_count = 0; + uint8_t out[2048] = { }; + size_t out_size = 0; + const struct hkdf_case *hc = &hkdf_cases[n]; + + Do_ADBG_BeginSubCase(c, "HKDF RFC 5869 %s", hc->subcase_name); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, session, &op, + hc->algo, TEE_MODE_DERIVE, max_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, session, + TEE_TYPE_HKDF_IKM, max_size, &key_handle))) + goto out; + + xtest_add_attr(¶m_count, params, TEE_ATTR_HKDF_IKM, hc->ikm, + hc->ikm_len); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, session, + key_handle, params, param_count))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, session, op, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, session, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, session, + TEE_TYPE_GENERIC_SECRET, hc->okm_len * 8, + &sv_handle))) + goto out; + + param_count = 0; + + if (hc->salt) + xtest_add_attr(¶m_count, params, TEE_ATTR_HKDF_SALT, + hc->salt, hc->salt_len); + if (hc->info) + xtest_add_attr(¶m_count, params, TEE_ATTR_HKDF_INFO, + hc->info, hc->info_len); + + params[param_count].attributeID = TEE_ATTR_HKDF_OKM_LENGTH; + params[param_count].content.value.a = hc->okm_len; + params[param_count].content.value.b = 0; + param_count++; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, session, op, sv_handle, + params, param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, session, + sv_handle, TEE_ATTR_SECRET_VALUE, out, + &out_size))) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, hc->okm, hc->okm_len, out, out_size)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, session, + sv_handle))) + goto out; + out: + Do_ADBG_EndSubCase(c, "HKDF RFC 5869 %s", hc->subcase_name); + } +} +#endif /* WITH_HKDF */ + +#ifdef WITH_CONCAT_KDF +static void xtest_test_derivation_concat_kdf(ADBG_Case_t *c, TEEC_Session *session) +{ + size_t n = 0; +#define TEST_CONCAT_KDF_DATA(name, algo, id, oeb /* omit empty bufs */) \ + { \ + name, algo, \ + concat_kdf_##id##_z, sizeof(concat_kdf_##id##_z), \ + (oeb && !sizeof(concat_kdf_##id##_other_info)) ? NULL \ + : concat_kdf_##id##_other_info, \ + sizeof(concat_kdf_##id##_other_info), \ + concat_kdf_##id##_derived_key, sizeof(concat_kdf_##id##_derived_key), \ + } + static struct concat_kdf_case { + const char *subcase_name; + uint32_t algo; + const uint8_t *shared_secret; + size_t shared_secret_len; + const uint8_t *other_info; + size_t other_info_len; + const uint8_t *derived_key; + size_t derived_key_len; + } concat_kdf_cases[] = { + TEST_CONCAT_KDF_DATA("JWA-37 C (SHA-256)", + TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY, 1, false), + }; + size_t max_size = 2048; + + for (n = 0; + n < sizeof(concat_kdf_cases) / sizeof(struct concat_kdf_case); + n++) { + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle key_handle = TEE_HANDLE_NULL; + TEE_ObjectHandle sv_handle = TEE_HANDLE_NULL; + TEE_Attribute params[4] = { }; + size_t param_count = 0; + uint8_t out[2048] = { }; + size_t out_size = 0; + const struct concat_kdf_case *cc = &concat_kdf_cases[n]; + + Do_ADBG_BeginSubCase(c, "Concat KDF %s", cc->subcase_name); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, session, &op, + cc->algo, TEE_MODE_DERIVE, max_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, session, + TEE_TYPE_CONCAT_KDF_Z, max_size, &key_handle))) + goto out; + + xtest_add_attr(¶m_count, params, TEE_ATTR_CONCAT_KDF_Z, + cc->shared_secret, cc->shared_secret_len); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, session, + key_handle, params, param_count))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, session, op, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, session, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, session, + TEE_TYPE_GENERIC_SECRET, cc->derived_key_len * + 8, &sv_handle))) + goto out; + + param_count = 0; + + if (cc->other_info) + xtest_add_attr(¶m_count, params, + TEE_ATTR_CONCAT_KDF_OTHER_INFO, + cc->other_info, cc->other_info_len); + + params[param_count].attributeID = TEE_ATTR_CONCAT_KDF_DKM_LENGTH; + params[param_count].content.value.a = cc->derived_key_len; + params[param_count].content.value.b = 0; + param_count++; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, session, op, sv_handle, + params, param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, session, + sv_handle, TEE_ATTR_SECRET_VALUE, out, + &out_size))) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, cc->derived_key, cc->derived_key_len, + out, out_size)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, session, + sv_handle))) + goto out; +out: + Do_ADBG_EndSubCase(c, "Concat KDF %s", cc->subcase_name); + } +} +#endif /* WITH_CONCAT_KDF */ + +#ifdef WITH_PBKDF2 +static void xtest_test_derivation_pbkdf2(ADBG_Case_t *c, TEEC_Session *session) +{ + size_t n = 0; +#define TEST_PBKDF2_DATA(level, section, algo, id, oeb /* omit empty bufs */) \ + { \ + level, section, algo, \ + pbkdf2_##id##_password, sizeof(pbkdf2_##id##_password), \ + (oeb && !sizeof(pbkdf2_##id##_salt)) ? NULL : pbkdf2_##id##_salt, sizeof(pbkdf2_##id##_salt), \ + pbkdf2_##id##_iteration_count, \ + pbkdf2_##id##_dkm, sizeof(pbkdf2_##id##_dkm), \ + } +#define _TO_STR(n) #n +#define TO_STR(n) _TO_STR(n) +#define RFC6070_TEST(l, n) \ + TEST_PBKDF2_DATA(l, "RFC 6070 " TO_STR(n) " (HMAC-SHA1)", \ + TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY, n, false) + static struct pbkdf2_case { + unsigned int level; + const char *subcase_name; + uint32_t algo; + const uint8_t *password; + size_t password_len; + const uint8_t *salt; + size_t salt_len; + uint32_t iteration_count; + const uint8_t *dkm; + size_t dkm_len; + } pbkdf2_cases[] = { + RFC6070_TEST(0, 1), RFC6070_TEST(0, 2), RFC6070_TEST(0, 3), + RFC6070_TEST(15, 4), /* Lengthy! (2 min on HiKey @1.2GHz) */ + RFC6070_TEST(0, 5), RFC6070_TEST(0, 6) + }; + size_t max_size = 2048; + + for (n = 0; n < sizeof(pbkdf2_cases) / sizeof(struct pbkdf2_case); n++) { + TEE_OperationHandle op = TEE_HANDLE_NULL; + TEE_ObjectHandle key_handle = TEE_HANDLE_NULL; + TEE_ObjectHandle sv_handle = TEE_HANDLE_NULL; + TEE_Attribute params[4] = { }; + size_t param_count = 0; + uint8_t out[2048] = { }; + size_t out_size = 0; + const struct pbkdf2_case *pc = &pbkdf2_cases[n]; + + if (pc->level > level) + continue; + + Do_ADBG_BeginSubCase(c, "PBKDF2 %s", pc->subcase_name); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_operation(c, session, &op, + pc->algo, TEE_MODE_DERIVE, max_size))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, session, + TEE_TYPE_PBKDF2_PASSWORD, max_size, + &key_handle))) + goto out; + + xtest_add_attr(¶m_count, params, TEE_ATTR_PBKDF2_PASSWORD, + pc->password, pc->password_len); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_populate_transient_object(c, session, + key_handle, params, param_count))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_set_operation_key(c, session, op, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, session, + key_handle))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_allocate_transient_object(c, session, + TEE_TYPE_GENERIC_SECRET, pc->dkm_len * 8, + &sv_handle))) + goto out; + + param_count = 0; + + if (pc->salt) + xtest_add_attr(¶m_count, params, + TEE_ATTR_PBKDF2_SALT, pc->salt, + pc->salt_len); + + params[param_count].attributeID = TEE_ATTR_PBKDF2_DKM_LENGTH; + params[param_count].content.value.a = pc->dkm_len; + params[param_count].content.value.b = 0; + param_count++; + + params[param_count].attributeID = + TEE_ATTR_PBKDF2_ITERATION_COUNT; + params[param_count].content.value.a = pc->iteration_count; + params[param_count].content.value.b = 0; + param_count++; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_derive_key(c, session, op, sv_handle, + params, param_count))) + goto out; + + out_size = sizeof(out); + memset(out, 0, sizeof(out)); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_get_object_buffer_attribute(c, session, + sv_handle, TEE_ATTR_SECRET_VALUE, + out, &out_size))) + goto out; + + if (!ADBG_EXPECT_BUFFER(c, pc->dkm, pc->dkm_len, out, out_size)) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_operation(c, session, op))) + goto out; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + ta_crypt_cmd_free_transient_object(c, session, + sv_handle))) + goto out; +out: + Do_ADBG_EndSubCase(c, "PBKDF2 %s", pc->subcase_name); + } +} +#endif /* WITH_PBKDF2 */ + +static TEEC_Result enc_fs_km_self_test(TEEC_Session *sess) +{ + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t org = 0; + + res = TEEC_InvokeCommand(sess, CMD_SELF_TESTS, &op, &org); + return res; +} + +static void xtest_tee_test_8001(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, + xtest_teec_open_session(&session, &crypt_user_ta_uuid, NULL, + &ret_orig))) + return; + +#ifdef WITH_HKDF + xtest_test_derivation_hkdf(c, &session); +#endif +#ifdef WITH_CONCAT_KDF + xtest_test_derivation_concat_kdf(c, &session); +#endif +#ifdef WITH_PBKDF2 + xtest_test_derivation_pbkdf2(c, &session); +#endif + + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 8001, xtest_tee_test_8001, + "Test TEE Internal API key derivation extensions"); + +/* secure storage key manager self test */ +static void xtest_tee_test_8002(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session sess = { }; + uint32_t orig = 0; + + res = xtest_teec_open_session(&sess, + &enc_fs_key_manager_test_ta_uuid, + NULL, &orig); + if (res != TEEC_SUCCESS) { + Do_ADBG_Log("Ignore test due to TA does not exist"); + return; + } + + if (!ADBG_EXPECT_TEEC_SUCCESS( + c, enc_fs_km_self_test(&sess))) + goto exit; + +exit: + TEEC_CloseSession(&sess); +} +ADBG_CASE_DEFINE(regression, 8002, xtest_tee_test_8002, + "Secure Storage Key Manager API Self Test"); diff --git a/optee/optee_test/host/xtest/regression_8100.c b/optee/optee_test/host/xtest/regression_8100.c new file mode 100644 index 0000000..ed34bcd --- /dev/null +++ b/optee/optee_test/host/xtest/regression_8100.c @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2018, Linaro Limited */ + +#include "xtest_test.h" +#include "xtest_helpers.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_FOUND +#include +#include +#include +#include +#endif + +#include "regression_8100_ca_crt.h" +#include "regression_8100_mid_crt.h" +#include "regression_8100_my_crt.h" +#include "regression_8100_my_csr.h" + +#ifdef CFG_TA_MBEDTLS + +static void test_8101(ADBG_Case_t *c __maybe_unused) +{ +#ifdef CFG_TA_MBEDTLS_SELF_TEST + TEEC_Session session = { }; + uint32_t ret_orig = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_SELF_TESTS, + NULL, &ret_orig)); + TEEC_CloseSession(&session); +#else + Do_ADBG_Log("CFG_TA_MBEDTLS_SELF_TEST not set, test skipped"); +#endif +} +ADBG_CASE_DEFINE(regression, 8101, test_8101, "TA mbedTLS self tests"); + +static int __printf(2, 3) myasprintf(char **strp, const char *fmt, ...) +{ + char *str = NULL; + int rc = 0; + va_list ap; + + va_start(ap, fmt); + rc = vsnprintf(str, rc, fmt, ap); + va_end(ap); + if (rc <= 0) + goto out; + + str = malloc(rc); + if (!str) { + rc = -1; + goto out; + } + + va_start(ap, fmt); + rc = vsnprintf(str, rc, fmt, ap); + va_end(ap); + if (rc <= 0) + free(str); + else + *strp = str; + +out: + return rc; +} + +static void test_8102(ADBG_Case_t *c) +{ + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + char *chain = NULL; + int clen = 0; + char *trust = NULL; + int tlen = 0; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + clen = myasprintf(&chain, "%*s\n%*s", + (int)regression_8100_my_crt_size, + regression_8100_my_crt, + (int)regression_8100_mid_crt_size, + regression_8100_mid_crt); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, clen, !=, -1)) + goto out; + tlen = myasprintf(&trust, "%*s", (int)regression_8100_ca_crt_size, + regression_8100_ca_crt); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, tlen, !=, -1)) + goto out; + + op.params[0].tmpref.buffer = chain; + op.params[0].tmpref.size = clen; + op.params[1].tmpref.buffer = trust; + op.params[1].tmpref.size = tlen; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_NONE, TEEC_NONE); + + ADBG_EXPECT_TEEC_SUCCESS(c, + TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_CHECK_CERT, + &op, &ret_orig)); +out: + free(chain); + free(trust); + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 8102, test_8102, "TA mbedTLS test cert chain"); + +#ifdef OPENSSL_FOUND +static void osslerr(void) +{ + while (true) { + unsigned long e = 0; + char b[256] = { }; + const char *f = NULL; + int l = 0; + + e = ERR_get_error_line(&f, &l); + if (!e) + return; + ERR_error_string_n(e, b, sizeof(b)); + Do_ADBG_Log("%s:%d \"%s\"", f, l, b); + } +} + +static bool get_cert(ADBG_Case_t *c, const char *crt_str, X509 **crt) +{ + bool ret = false; + size_t slen = strlen(crt_str) + 1; + BIO *buf = BIO_new(BIO_s_mem()); + size_t b = 0; + + if (!ADBG_EXPECT_NOT_NULL(c, buf)) + goto out; + + b = BIO_write(buf, crt_str, slen); + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, b, ==, slen)) + goto out; + + if (!PEM_read_bio_X509(buf, crt, 0, NULL)) + goto out; + + ret = true; +out: + if (!ret) + osslerr(); + BIO_free(buf); + return ret; +} + +static bool push_cert(ADBG_Case_t *c, const char *crt_str, STACK_OF(X509) *cs) +{ + X509 *crt = NULL; + int rc = 0; + + if (!get_cert(c, crt_str, &crt)) + return false; + rc = sk_X509_push(cs, crt); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, rc, >, 0)) { + osslerr(); + X509_free(crt); + return false; + } + + return true; +} + +static bool check(ADBG_Case_t *c, STACK_OF(X509) *trusted, + STACK_OF(X509) *untrusted, X509 *crt) +{ + bool ret = false; + X509_STORE *store = NULL; + X509_STORE_CTX *csc = NULL; + X509_VERIFY_PARAM *pm = NULL; + int i = 0; + time_t vfy_time = 0; + + pm = X509_VERIFY_PARAM_new(); + vfy_time = 1526898005; /* Mon, 21 May 2018 10:20:05 +0000 */ + X509_VERIFY_PARAM_set_time(pm, vfy_time); + + store = X509_STORE_new(); + if (!ADBG_EXPECT_NOT_NULL(c, store)) + goto out; + X509_STORE_set_flags(store, 0); + if (!ADBG_EXPECT_TRUE(c, X509_STORE_set1_param(store, pm))) + goto out; + + csc = X509_STORE_CTX_new(); + if (!ADBG_EXPECT_NOT_NULL(c, csc)) + goto out; + + if (!ADBG_EXPECT_TRUE(c, X509_STORE_CTX_init(csc, store, crt, + untrusted))) + goto out; + X509_STORE_CTX_trusted_stack(csc, trusted); + + i = X509_verify_cert(csc); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, i, >, 0)) + goto out; + i = X509_STORE_CTX_get_error(csc); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, i, ==, X509_V_OK)) + goto out; + ret = true; +out: + if (!ret) + osslerr(); + X509_VERIFY_PARAM_free(pm); + X509_STORE_free(store); + X509_STORE_CTX_free(csc); + return ret; +} + +static bool verify_cert(ADBG_Case_t *c, const char *ca, const char *mid, + const char *cert) +{ + bool ret = false; + STACK_OF(X509) *trusted = NULL; + STACK_OF(X509) *untrusted = NULL; + X509 *crt = NULL; + + trusted = sk_X509_new_null(); + if (!ADBG_EXPECT_NOT_NULL(c, trusted)) + goto out; + untrusted = sk_X509_new_null(); + if (!ADBG_EXPECT_NOT_NULL(c, untrusted)) + goto out; + + if (!ADBG_EXPECT_TRUE(c, get_cert(c, cert, &crt))) + goto out; + if (!ADBG_EXPECT_TRUE(c, push_cert(c, mid, untrusted))) + goto out; + if (!ADBG_EXPECT_TRUE(c, push_cert(c, ca, trusted))) + goto out; + + ret = ADBG_EXPECT_TRUE(c, check(c, trusted, untrusted, crt)); +out: + if (!ret) + osslerr(); + X509_free(crt); + sk_X509_pop_free(untrusted, X509_free); + sk_X509_pop_free(trusted, X509_free); + return ret; +} +#else /*!OPENSSL_FOUND*/ +static bool verify_cert(ADBG_Case_t *c, const char *ca, + const char *mid, const char *cert) +{ + UNUSED(c); + UNUSED(ca); + UNUSED(mid); + UNUSED(cert); + Do_ADBG_Log("OpenSSL not available, skipping certificate verification"); + return true; +} +#endif + +static void test_8103(ADBG_Case_t *c) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Session session = { }; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + char *csr = NULL; + int clen = 0; + char cert[2048]; + char chain[4096]; + char *ca = NULL; + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, xtest_teec_open_session( + &session, &crypt_user_ta_uuid, + NULL, &ret_orig))) + return; + + clen = myasprintf(&csr, "%*s", (int)regression_8100_my_csr_size, + regression_8100_my_csr); + if (!ADBG_EXPECT_COMPARE_SIGNED(c, clen, >=, 0)) + goto out; + op.params[0].tmpref.buffer = csr; + op.params[0].tmpref.size = clen; + op.params[1].tmpref.buffer = cert; + op.params[1].tmpref.size = sizeof(cert); + op.params[2].tmpref.buffer = chain; + op.params[2].tmpref.size = sizeof(chain); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE); + res = TEEC_InvokeCommand(&session, TA_CRYPT_CMD_MBEDTLS_SIGN_CERT, &op, + &ret_orig); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + goto out; + + myasprintf(&ca, "%*s", (int)regression_8100_ca_crt_size, + regression_8100_ca_crt); + if (!ADBG_EXPECT_NOT_NULL(c, ca)) + goto out; + verify_cert(c, ca, op.params[2].tmpref.buffer, + op.params[1].tmpref.buffer); +out: + free(ca); + free(csr); + TEEC_CloseSession(&session); +} +ADBG_CASE_DEFINE(regression, 8103, test_8103, + "TA mbedTLS process certificate request"); +#endif /*CFG_TA_MBEDTLS*/ diff --git a/optee/optee_test/host/xtest/sdp_basic.c b/optee/optee_test/host/xtest/sdp_basic.c new file mode 100644 index 0000000..c8abd51 --- /dev/null +++ b/optee/optee_test/host/xtest/sdp_basic.c @@ -0,0 +1,697 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crypto_common.h" +#include "sdp_basic.h" +#include "xtest_helpers.h" +#include "xtest_test.h" + +/* + * SDP basic test setup overview. + * + * - A dedicated trusted application (SDP basic TA) supports 3 commands: + * - 'inject' data from a nonsecure buffer into a secure buffer + * - 'transform' data inside a secure buffer (bitwise invert + unsigned incr) + * - 'dump' data from a secure buffer into a nonsecure buffer + + * - This test client application (CA) invokes the TA for these 3 operations, + * inject random value, trasforming them then dump them. + * + * To do so, CA allocates a 'SDP secure buffer' and invoke the TA for these 3 + * operations (inject then transform then dump) over the allocate buffer. + * + * The secure buffer is currently allocation through ION support adn + * registered to OP-TEE and as shared memory. + * + * To enhance test coverage against buffer alignement usecase, the CA invokes + * the TA with a variable offset inside the buffer. As CA injects random data + * into the buffer, the CA uses one of the random bytes to set the value of the + * offset in the accessed secure buffer. + * + * For debugging support, the CA may map (in nonsecure world) the secure + * buffer to read its content. As this is unsafe on a hardened platform, this + * operation is default disable. When enable, error only print out a warning + * trace but does not actually fail the test. This also give an easy way to + * check that some HW complains on access violation when nonsecure accesses + * secure data. + */ + +struct tee_ctx { + TEEC_Context ctx; + TEEC_Session sess; +}; + +int allocate_dma_buffer(size_t size, const char *heap_name, int verbosity) +{ + const char *default_dev = DEFAULT_HEAP_NAME; + char *mem_sec_dev = (char *)default_dev; + struct dma_heap_allocation_data data = { 0 }; + int fd_mem_sec; + int fd = -1; + + if (heap_name != NULL) + mem_sec_dev = (char *)heap_name; + + fd_mem_sec = open(mem_sec_dev, O_RDWR | O_SYNC); + if (fd_mem_sec == -1) { + fprintf(stderr, "Error: failed to open %s\n", mem_sec_dev); + verbose("Seems no DMA buf heap is available.\n"); + return -1; + } + + data.len = size; + data.fd_flags = O_RDWR | O_CLOEXEC; + data.heap_flags = 0; + + if (ioctl(fd_mem_sec, DMA_HEAP_IOCTL_ALLOC, &data) == -1) { + fprintf(stderr, "Error: DMA buf allocate API failed\n"); + goto out; + } + + fd = data.fd; + +out: + close(fd_mem_sec); + return fd; +} + +static void finalize_tee_ctx(struct tee_ctx *ctx) +{ + if (!ctx) + return; + + TEEC_CloseSession(&ctx->sess); + TEEC_FinalizeContext(&ctx->ctx); +} + +static int create_tee_ctx(struct tee_ctx *ctx, enum test_target_ta target_ta) +{ + TEEC_Result teerc = TEEC_ERROR_GENERIC; + const TEEC_UUID *uuid = NULL; + uint32_t err_origin = 0; + + switch (target_ta) { + case TEST_NS_TO_TA: + case TEST_TA_TO_TA: + case TEST_TA_TO_PTA: + uuid = &sdp_basic_ta_uuid; + break; + case TEST_NS_TO_PTA: + uuid = &pta_invoke_tests_ta_uuid; + break; + default: + return -1; + } + + teerc = TEEC_InitializeContext(NULL, &ctx->ctx); + if (teerc != TEEC_SUCCESS) + return -1; + + teerc = TEEC_OpenSession(&ctx->ctx, &ctx->sess, uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin); + if (teerc != TEEC_SUCCESS) { + fprintf(stderr, "Error: open session to target test %s failed %x %d\n", + (target_ta == TEST_NS_TO_PTA) ? "pTA" : "TA", + teerc, err_origin); + + TEEC_FinalizeContext(&ctx->ctx); + } + return (teerc == TEEC_SUCCESS) ? 0 : -1; +} + +static int tee_register_buffer(struct tee_ctx *ctx, void **shm_ref, int fd) +{ + TEEC_Result teerc = TEEC_ERROR_GENERIC; + TEEC_SharedMemory *shm = malloc(sizeof(*shm)); + + if (!shm) + return 1; + + shm->flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT; + teerc = TEEC_RegisterSharedMemoryFileDescriptor(&ctx->ctx, shm, fd); + if (teerc != TEEC_SUCCESS) { + fprintf(stderr, "Error: TEEC_RegisterMemoryFileDescriptor() failed %x\n", + teerc); + return 1; + } + + *shm_ref = shm; + return 0; +} + +static void tee_deregister_buffer(struct tee_ctx *ctx, void *shm_ref) +{ + (void)ctx; + + if (!shm_ref) + return; + + TEEC_ReleaseSharedMemory((TEEC_SharedMemory *)shm_ref); + free(shm_ref); +} + +static int inject_sdp_data(struct tee_ctx *ctx, + void *in, size_t offset, size_t len, void *shm_ref, int ind) +{ + TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref; + TEEC_Result teerc = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t err_origin = 0; + unsigned int cmd = 0; + + switch (ind) { + case TEST_NS_TO_TA: + cmd = TA_SDP_BASIC_CMD_INJECT; + break; + case TEST_TA_TO_TA: + cmd = TA_SDP_BASIC_CMD_INVOKE_INJECT; + break; + case TEST_TA_TO_PTA: + cmd = TA_SDP_BASIC_CMD_PTA_INJECT; + break; + case TEST_NS_TO_PTA: + cmd = PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC; + break; + default: + return -1; + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_NONE, TEEC_NONE); + + op.params[0].tmpref.buffer = in; + op.params[0].tmpref.size = len; + + op.params[1].memref.parent = shm; + op.params[1].memref.size = len; + op.params[1].memref.offset = offset; + + teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin); + if (teerc != TEEC_SUCCESS) + fprintf(stderr, "Error: invoke SDP test TA (inject) failed %x %d\n", + teerc, err_origin); + + return (teerc == TEEC_SUCCESS) ? 0 : -1; +} + +static int transform_sdp_data(struct tee_ctx *ctx, + size_t offset, size_t len, void *shm_ref, int ind) +{ + TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref; + TEEC_Result teerc = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t err_origin = 0; + unsigned int cmd = 0; + + switch (ind) { + case TEST_NS_TO_TA: + cmd = TA_SDP_BASIC_CMD_TRANSFORM; + break; + case TEST_TA_TO_TA: + cmd = TA_SDP_BASIC_CMD_INVOKE_TRANSFORM; + break; + case TEST_TA_TO_PTA: + cmd = TA_SDP_BASIC_CMD_PTA_TRANSFORM; + break; + case TEST_NS_TO_PTA: + cmd = PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC; + break; + default: + return -1; + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INOUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + op.params[0].memref.parent = shm; + op.params[0].memref.size = len; + op.params[0].memref.offset = offset; + + teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin); + if (teerc != TEEC_SUCCESS) + fprintf(stderr, "Error: invoke SDP test TA (transform) failed %x %d\n", + teerc, err_origin); + + return (teerc == TEEC_SUCCESS) ? 0 : -1; +} + +static int dump_sdp_data(struct tee_ctx *ctx, + void *out, size_t offset, size_t len, void *shm_ref, int ind) +{ + TEEC_SharedMemory *shm = (TEEC_SharedMemory *)shm_ref; + TEEC_Result teerc = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t err_origin = 0; + unsigned int cmd = 0; + + switch (ind) { + case TEST_NS_TO_TA: + cmd = TA_SDP_BASIC_CMD_DUMP; + break; + case TEST_TA_TO_TA: + cmd = TA_SDP_BASIC_CMD_INVOKE_DUMP; + break; + case TEST_TA_TO_PTA: + cmd = TA_SDP_BASIC_CMD_PTA_DUMP; + break; + case TEST_NS_TO_PTA: + cmd = PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC; + break; + default: + return -1; + } + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + op.params[0].memref.parent = shm; + op.params[0].memref.size = len; + op.params[0].memref.offset = offset; + + op.params[1].tmpref.buffer = out; + op.params[1].tmpref.size = len; + + teerc = TEEC_InvokeCommand(&ctx->sess, cmd, &op, &err_origin); + if (teerc != TEEC_SUCCESS) + fprintf(stderr, "Error: invoke SDP test TA (dump) failed %x %d\n", + teerc, err_origin); + + return (teerc == TEEC_SUCCESS) ? 0 : -1; +} + +static int check_sdp_dumped(struct tee_ctx *ctx, void *ref, size_t len, + void *out) +{ + char *bref = (char *)ref; + char *data = (char *)out; + int err = 0; + + (void)ctx; + + while(len--) + if (*data++ != (unsigned char)(~(*bref++) + 1)) + err++; + + return err; +} + +/* + * Consider 32kByte + 1 of random data is sufficient for an accurate test + * whatever the test buffer size is. Random buffer is read as a ring buffer. + */ +#define RANDOM_BUFFER_SIZE (32 * 1024 + 1) +static int get_random_bytes(char *out, size_t len) +{ + static char *rand_buf = NULL; + static size_t rand_idx = 0; + int rc = 0; + + if (!rand_buf) { + const char rand_dev[] = "/dev/urandom"; + int fd = 0; + + rand_buf = malloc(RANDOM_BUFFER_SIZE); + if (!rand_buf) { + fprintf(stderr, "failed to random buffer memory (%d bytes)\n", + RANDOM_BUFFER_SIZE); + return -1; + } + + fd = open(rand_dev, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "failed to open %s\n", rand_dev); + return -1; + } + + rc = read(fd, rand_buf, RANDOM_BUFFER_SIZE); + if (rc != RANDOM_BUFFER_SIZE) { + fprintf(stderr, "failed to read %d bytes from %s\n", + RANDOM_BUFFER_SIZE, rand_dev); + close(fd); + return -1; + } + close(fd); + } + + while (len) { + size_t t_len = (RANDOM_BUFFER_SIZE < len) ? RANDOM_BUFFER_SIZE : len; + + if ((rand_idx + t_len) > RANDOM_BUFFER_SIZE) { + int sz_end = RANDOM_BUFFER_SIZE - rand_idx; + int sz_beg = t_len - sz_end; + + memcpy(out, rand_buf + rand_idx, sz_end); + memcpy(out + sz_end, rand_buf , sz_beg); + rand_idx = sz_beg; + } else { + memcpy(out, rand_buf + rand_idx, t_len); + rand_idx += t_len; + } + len -= t_len; + } + return 0; +} + + +int sdp_basic_test(enum test_target_ta ta, size_t size, size_t loop, + const char *heap_name, int rnd_offset, int verbosity) +{ + struct tee_ctx *ctx = NULL; + unsigned char *test_buf = NULL; + unsigned char *ref_buf = NULL; + void *shm_ref = NULL; + unsigned int err = 1; + int fd = -1; + size_t sdp_size = size; + size_t offset = 0; + size_t loop_cnt = 0; + + if (!loop) { + fprintf(stderr, "Error: null loop value\n"); + return 1; + } + + /* reduce size to enable offset tests (max offset is 255 bytes) */ + if (rnd_offset) + size -= 255; + + test_buf = malloc(size); + ref_buf = malloc(size); + if (!test_buf || !ref_buf) { + verbose("failed to allocate memory\n"); + goto bail1; + } + + fd = allocate_buffer(sdp_size, heap_name, verbosity); + if (fd < 0) { + verbose("Failed to allocate SDP buffer (%zu bytes) in %s: %d\n", + sdp_size, heap_name, fd); + goto bail1; + } + + /* register secure buffer to TEE */ + ctx = malloc(sizeof(*ctx)); + if (!ctx) + goto bail1; + if (create_tee_ctx(ctx, ta)) + goto bail1; + if (tee_register_buffer(ctx, &shm_ref, fd)) + goto bail2; + + /* release registered fd: tee should still hold refcount on resource */ + close(fd); + fd = -1; + + /* invoke trusted application with secure buffer as memref parameter */ + for (loop_cnt = loop; loop_cnt; loop_cnt--) { + /* get an buffer of random-like values */ + if (get_random_bytes((char *)ref_buf, size)) + goto bail2; + memcpy(test_buf, ref_buf, size); + /* random offset [0 255] */ + offset = (unsigned int)*ref_buf; + + /* TA writes into SDP buffer */ + if (inject_sdp_data(ctx, test_buf, offset, size, shm_ref, ta)) + goto bail2; + + /* TA reads/writes into SDP buffer */ + if (transform_sdp_data(ctx, offset, size, shm_ref, ta)) + goto bail2; + + /* TA reads into SDP buffer */ + if (dump_sdp_data(ctx, test_buf, offset, size, shm_ref, ta)) + goto bail2; + + /* check dumped data are the expected ones */ + if (check_sdp_dumped(ctx, ref_buf, size, test_buf)) { + fprintf(stderr, "check SDP data: %d errors\n", err); + goto bail2; + } + } + + err = 0; +bail2: + if (fd >= 0) + close(fd); + if (shm_ref) + tee_deregister_buffer(ctx, shm_ref); + finalize_tee_ctx(ctx); +bail1: + free(ctx); + free(ref_buf); + free(test_buf); + return err; +} + +static int invoke_out_of_bounds(struct tee_ctx *ctx, + TEEC_SharedMemory *in, TEEC_SharedMemory *out, + size_t offset, size_t size, + bool valid_ref, int verbosity) +{ + TEEC_Result teerc = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t orig = 0; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_PARTIAL_INPUT, + TEEC_MEMREF_PARTIAL_OUTPUT, + TEEC_NONE, TEEC_NONE); + + op.params[0].memref.parent = in; + op.params[0].memref.offset = 0; + op.params[0].memref.size = size; + + op.params[1].memref.parent = out; + op.params[1].memref.offset = offset; + op.params[1].memref.size = size; + + teerc = TEEC_InvokeCommand(&ctx->sess, TA_SDP_BASIC_CMD_INJECT, + &op, &orig); + + /* + * Invocation with invalid references should be nicely rejected by + * the TEE. + * Invocation with valid references should reach the TA, whatever + * result is. + */ + if ((valid_ref && orig != TEEC_ORIGIN_TRUSTED_APP) || + (!valid_ref && ((orig == TEEC_ORIGIN_TRUSTED_APP) || + (teerc != TEEC_ERROR_GENERIC && + teerc != TEEC_ERROR_BAD_PARAMETERS)))) + goto error; + + verbose("Out of bounds memref test successful:\n"); + verbose("Shm size 0x%zx, offset 0x%zx/size 0x%zx: %s/0x%x from %s\n", + out->size, offset, size, + Do_ADBG_GetEnumName(teerc, ADBG_EnumTable_TEEC_Result), teerc, + Do_ADBG_GetEnumName(orig, ADBG_EnumTable_TEEC_ErrorOrigin)); + return 0; + +error: + fprintf(stderr, "Out of bounds memref test FAILURE:\n"); + fprintf(stderr, + "Shm size 0x%zx, offset 0x%zx/size 0x%zx: %s/0x%x from %s\n", + out->size, offset, size, + Do_ADBG_GetEnumName(teerc, ADBG_EnumTable_TEEC_Result), teerc, + Do_ADBG_GetEnumName(orig, ADBG_EnumTable_TEEC_ErrorOrigin)); + return 1; +} + +int sdp_out_of_bounds_memref_test(size_t size, const char *heap_name, + int verbosity) +{ + struct tee_ctx ctx = { }; + int err = 0; + int fd = -1; + TEEC_Result teerc = TEEC_ERROR_GENERIC; + TEEC_SharedMemory in = { }; + TEEC_SharedMemory *out = NULL; + + if (create_tee_ctx(&ctx, TEST_NS_TO_TA)) + return -1; + + fd = allocate_buffer(size, heap_name, verbosity); + if (fd < 0) { + verbose("SDP alloc failed (%zu bytes) in %s: %d\n", + size, heap_name, fd); + err = 1; + goto bail; + } + if (tee_register_buffer(&ctx, (void **)&out, fd)) { + err = 1; + goto bail; + } + + /* + * The ION driver will decide how much SDP memory is being allocated. + * Rely on this size to test out of bounds reference cases. + */ + size = out->size; + + in.size = size; + in.flags = TEEC_MEM_INPUT; + teerc = TEEC_AllocateSharedMemory(&ctx.ctx, &in); + if (teerc) { + verbose("failed to allocate memory\n"); + goto bail; + } + + if (verbosity) { + /* Valid case: reference inside allocated buffer: last byte */ + err += invoke_out_of_bounds(&ctx, &in, out, size - 1, 1, + true, verbosity); + } + + /* Reference overflows allocated buffer by 1 byte */ + err += invoke_out_of_bounds(&ctx, &in, out, size - 1, 2, + false, verbosity); + + /* Reference oveflows allocated buffer by more than 4kB byte */ + err += invoke_out_of_bounds(&ctx, &in, out, size - 1, 5000, + false, verbosity); + + /* Offset exceeds allocated buffer size value by 1 byte */ + err += invoke_out_of_bounds(&ctx, &in, out, size, 1, + false, verbosity); + + /* Offset exceeds allocated size value by 4kByte */ + err += invoke_out_of_bounds(&ctx, &in, out, size, 4096, + false, verbosity); + + /* Offset + size overflows offset value */ + err += invoke_out_of_bounds(&ctx, &in, out, 2, ~0, + false, verbosity); + + TEEC_ReleaseSharedMemory(&in); +bail: + tee_deregister_buffer(&ctx, out); + if (fd >= 0) + close(fd); + finalize_tee_ctx(&ctx); + + return err; +} + +#define _TO_STR(x) #x +#define TO_STR(x) _TO_STR(x) + +static void usage(const char *progname, size_t size, int loop, const char *heap_name) +{ + fprintf(stderr, "Usage: %s [OPTION]\n", progname); + fprintf(stderr, + "Testing basic accesses to secure buffer (SDP) on OP-TEE.\n" + "Allocates a secure buffer and invoke a TA to access it.\n" + "TA is used to init/transform/dump the secure buffer.\n" + "CA check dumped content.\n\n"); + + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -h|--help Print this help and exit\n"); + fprintf(stderr, " -v Be verbose\n"); + fprintf(stderr, " -s SIZE SDP buffer byte size [%zu]\n", size); + fprintf(stderr, " -n LOOP Test loop iterations [%u]\n", loop); + fprintf(stderr, " --heap-name NAME Target heap name [%s]\n", heap_name); + fprintf(stderr, " --no-offset No random offset [0 255] in buffer\n"); +} + +#define NEXT_ARG(i) \ + do { \ + if (++i == argc) { \ + fprintf(stderr, "%s: %s: missing argument\n", \ + argv[0], argv[i-1]); \ + return 1; \ + } \ + } while (0); + +#define CHECK_RESULT(_res, _exp, _action) \ + if ((_res) == (_exp)) { \ + verbose("Test passed\n"); \ + } else { \ + verbose("Test failed!\n"); \ + _action; \ + } + +int sdp_basic_runner_cmd_parser(int argc, char *argv[]) +{ + size_t test_size = 5000; + size_t test_loop = 1000; + const char *heap_name = DEFAULT_HEAP_NAME; + int rnd_offset = 1; + int verbosity = 1; + int err = 0; + int i = 0; + + /* Parse command line */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + usage(argv[0], test_size, test_loop, heap_name); + return 0; + } + } + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-v")) { + verbosity++; + } else if (!strcmp(argv[i], "-s")) { + NEXT_ARG(i); + test_size = atoi(argv[i]); + } else if (!strcmp(argv[i], "-n")) { + NEXT_ARG(i); + test_loop = atoi(argv[i]); + } else if (!strcmp(argv[i], "--heap-name")) { + NEXT_ARG(i); + heap_name = argv[i]; + } else if (!strcmp(argv[i], "--no-offset")) { + rnd_offset = 0; + } else { + fprintf(stderr, "%s: invalid argument: %s\n", + argv[0], argv[i]); + usage(argv[0], test_size, test_loop, heap_name); + return 1; + } + } + + verbose("\nSecure Data Path basic access: " + "NS invokes SDP TA\n"); + err = sdp_basic_test(TEST_NS_TO_TA, test_size, test_loop, heap_name, + rnd_offset, verbosity); + CHECK_RESULT(err, 0, return 1); + + verbose("\nSecure Data Path basic access: " + "SDP TA invokes SDP TA\n"); + err = sdp_basic_test(TEST_TA_TO_TA, test_size, test_loop, heap_name, + rnd_offset, verbosity); + CHECK_RESULT(err, 0, return 1); + + verbose("\nSecure Data Path basic access: " + "SDP TA invokes SDP pTA\n"); + err = sdp_basic_test(TEST_TA_TO_PTA, test_size, test_loop, heap_name, + rnd_offset, verbosity); + CHECK_RESULT(err, 0, return 1); + + verbose("\nSecure Data Path basic access: " + "NS invokes SDP pTA (shall fail)\n"); + err = sdp_basic_test(TEST_NS_TO_PTA, test_size, test_loop, heap_name, + rnd_offset, verbosity); + CHECK_RESULT(err, 1, return 1); + + verbose("\nSecure Data Path basic access: " + "Invoke TA with out of bounds buffer references\n"); + err = sdp_out_of_bounds_memref_test(test_size, heap_name, verbosity); + CHECK_RESULT(err, 0, return 1); + + return 0; +} diff --git a/optee/optee_test/host/xtest/sdp_basic.h b/optee/optee_test/host/xtest/sdp_basic.h new file mode 100644 index 0000000..268d861 --- /dev/null +++ b/optee/optee_test/host/xtest/sdp_basic.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2017, Linaro Limited + * All rights reserved. + */ + +#ifndef XTEST_SDP_BASIC_H +#define XTEST_SDP_BASIC_H + +#include +#include +#include +#define DEFAULT_HEAP_NAME "/dev/dma_heap/sdp" + +#include "ta_sdp_basic.h" + +enum test_target_ta { + TEST_NS_TO_TA, + TEST_NS_TO_PTA, + TEST_TA_TO_TA, + TEST_TA_TO_PTA, +}; + +int allocate_dma_buffer(size_t size, const char *heap_name, int verbosity); +static inline int allocate_buffer(size_t size, const char *heap_name, + int verbosity) +{ + return allocate_dma_buffer(size, heap_name, verbosity); +} +int sdp_basic_test(enum test_target_ta ta, + size_t size, size_t loop, const char *heap_name, + int rnd_offset, int verbosity); + +int sdp_out_of_bounds_memref_test(size_t size, const char *heap_name, + int verbosity); + +#endif /* XTEST_SDP_BASIC_H */ diff --git a/optee/optee_test/host/xtest/sock_server.c b/optee/optee_test/host/xtest/sock_server.c new file mode 100644 index 0000000..20ad6fc --- /dev/null +++ b/optee/optee_test/host/xtest/sock_server.c @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sock_server.h" + +struct server_state { + struct sock_state *socks; + struct pollfd *fds; + nfds_t nfds; + bool got_quit; + struct sock_io_cb *cb; +}; + +#define SOCK_BUF_SIZE 512 + +struct sock_state { + bool (*cb)(struct server_state *srvst, size_t idx); + struct sock_server_bind *serv; +}; + +static bool server_io_cb(struct server_state *srvst, size_t idx) +{ + short revents = srvst->fds[idx].revents; + short *events = &srvst->fds[idx].events; + struct sock_io_cb *cb = srvst->cb; + int fd = 0; + + fd = srvst->fds[idx].fd; + if (revents & POLLIN) { + if (!cb->read) + *events &= ~POLLIN; + else if (!cb->read(cb->ptr, fd, events)) + goto close; + } + + if (revents & POLLOUT) { + if (!cb->write) + *events &= ~POLLOUT; + else if (!cb->write(cb->ptr, fd, events)) + goto close; + } + + if (!(revents & ~(POLLIN | POLLOUT))) + return true; +close: + if (close(fd)) { + warn("server_io_cb: close(%d)", fd); + return false; + } + srvst->fds[idx].fd = -1; + return true; +} + +static bool server_add_state(struct server_state *srvst, + bool (*cb)(struct server_state *srvst, size_t idx), + struct sock_server_bind *serv, int fd, + short poll_events) +{ + void *p = NULL; + size_t n = 0; + + for (n = 0; n < srvst->nfds; n++) { + if (srvst->fds[n].fd == -1) { + srvst->socks[n].cb = cb; + srvst->socks[n].serv = serv; + srvst->fds[n].fd = fd; + srvst->fds[n].events = poll_events; + srvst->fds[n].revents = 0; + return true; + } + } + + p = realloc(srvst->socks, sizeof(*srvst->socks) * (srvst->nfds + 1)); + if (!p) + return false; + srvst->socks = p; + srvst->socks[srvst->nfds].cb = cb; + srvst->socks[srvst->nfds].serv = serv; + + p = realloc(srvst->fds, sizeof(*srvst->fds) * (srvst->nfds + 1)); + if (!p) + return false; + srvst->fds = p; + srvst->fds[srvst->nfds].fd = fd; + srvst->fds[srvst->nfds].events = poll_events; + srvst->fds[srvst->nfds].revents = 0; + + srvst->nfds++; + return true; +} + +static bool tcp_server_accept_cb(struct server_state *srvst, size_t idx) +{ + short revents = srvst->fds[idx].revents; + struct sockaddr_storage sass = { }; + struct sockaddr *sa = (struct sockaddr *)&sass; + socklen_t len = sizeof(sass); + int fd = 0; + short io_events = POLLIN | POLLOUT; + + if (!(revents & POLLIN)) + return false; + + fd = accept(srvst->fds[idx].fd, sa, &len); + if (fd == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK || + errno == ECONNABORTED) + return true; + return false; + } + + if (srvst->cb->accept && + !srvst->cb->accept(srvst->cb->ptr, fd, &io_events)) { + if (close(fd)) + warn("server_accept_cb: close(%d)", fd); + return true; + } + + return server_add_state(srvst, server_io_cb, srvst->socks[idx].serv, + fd, io_events); +} + +static bool udp_server_cb(struct server_state *srvst, size_t idx) +{ + short revents = srvst->fds[idx].revents; + + if (!(revents & POLLIN)) + return false; + + return srvst->cb->accept(srvst->cb->ptr, srvst->fds[idx].fd, NULL); +} + +static bool server_quit_cb(struct server_state *srvst, size_t idx) +{ + (void)idx; + srvst->got_quit = true; + return true; +} + +static void sock_server(struct sock_server *ts, + bool (*cb)(struct server_state *srvst, size_t idx)) +{ + struct server_state srvst = { .cb = ts->cb }; + int pres = 0; + size_t n = 0; + char b = 0; + + sock_server_lock(ts); + + for (n = 0; n < ts->num_binds; n++) { + if (!server_add_state(&srvst, cb, ts->bind + n, + ts->bind[n].fd, POLLIN)) + goto bad; + } + + if (!server_add_state(&srvst, server_quit_cb, NULL, + ts->quit_fd, POLLIN)) + goto bad; + + while (true) { + sock_server_unlock(ts); + /* + * First sleep 5 ms to make it easier to test send timeouts + * due to this rate limit. + */ + poll(NULL, 0, 5); + pres = poll(srvst.fds, srvst.nfds, -1); + sock_server_lock(ts); + if (pres < 0) + goto bad; + + for (n = 0; pres && n < srvst.nfds; n++) { + if (srvst.fds[n].revents) { + pres--; + if (!srvst.socks[n].cb(&srvst, n)) + goto bad; + } + } + + if (srvst.got_quit) + goto out; + } + +bad: + ts->error = true; +out: + for (n = 0; n < srvst.nfds; n++) { + /* Don't close accept and quit fds */ + if (srvst.fds[n].fd != -1 && srvst.socks[n].serv && + srvst.fds[n].fd != srvst.socks[n].serv->fd) { + if (close(srvst.fds[n].fd)) + warn("sock_server: close(%d)", srvst.fds[n].fd); + } + } + free(srvst.socks); + free(srvst.fds); + if (read(ts->quit_fd, &b, 1) != 1) + ts->error = true; + + sock_server_unlock(ts); +} + +static void *sock_server_stream(void *arg) +{ + sock_server(arg, tcp_server_accept_cb); + return NULL; +} + +static void *sock_server_dgram(void *arg) +{ + sock_server(arg, udp_server_cb); + return NULL; +} + +static void sock_server_add_fd(struct sock_server *ts, struct addrinfo *ai) +{ + struct sock_server_bind serv = { }; + struct sockaddr_storage sass = { }; + struct sockaddr *sa = (struct sockaddr *)&sass; + struct sockaddr_in *sain = (struct sockaddr_in *)&sass; + struct sockaddr_in6 *sain6 = (struct sockaddr_in6 *)&sass; + void *src = NULL; + socklen_t len = sizeof(sass); + struct sock_server_bind *p = NULL; + + serv.fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (serv.fd < 0) + return; + + if (bind(serv.fd, ai->ai_addr, ai->ai_addrlen)) + goto bad; + + if (ai->ai_socktype == SOCK_STREAM && listen(serv.fd, 5)) + goto bad; + + if (getsockname(serv.fd, sa, &len)) + goto bad; + + switch (sa->sa_family) { + case AF_INET: + src = &sain->sin_addr; + serv.port = ntohs(sain->sin_port); + break; + case AF_INET6: + src = &sain6->sin6_addr; + serv.port = ntohs(sain6->sin6_port); + default: + goto bad; + } + + if (!inet_ntop(sa->sa_family, src, serv.host, sizeof(serv.host))) + goto bad; + + p = realloc(ts->bind, sizeof(*p) * (ts->num_binds + 1)); + if (!p) + goto bad; + + ts->bind = p; + p[ts->num_binds] = serv; + ts->num_binds++; + return; +bad: + if (close(serv.fd)) + warn("sock_server_add_fd: close(%d)", serv.fd); +} + +void sock_server_uninit(struct sock_server *ts) +{ + size_t n = 0; + int e = 0; + + if (ts->stop_fd != -1) { + if (close(ts->stop_fd)) + warn("sock_server_uninit: close(%d)", ts->stop_fd); + ts->stop_fd = -1; + e = pthread_join(ts->thr, NULL); + if (e) + warnx("sock_server_uninit: pthread_join: %s", + strerror(e)); + } + + e = pthread_mutex_destroy(&ts->mu); + if (e) + warnx("sock_server_uninit: pthread_mutex_destroy: %s", + strerror(e)); + + for (n = 0; n < ts->num_binds; n++) + if (close(ts->bind[n].fd)) + warn("sock_server_uninit: close(%d)", ts->bind[n].fd); + free(ts->bind); + if (ts->quit_fd != -1 && close(ts->quit_fd)) + warn("sock_server_uninit: close(%d)", ts->quit_fd); + memset(ts, 0, sizeof(*ts)); + ts->quit_fd = -1; + ts->stop_fd = -1; +} + +static bool sock_server_init(struct sock_server *ts, struct sock_io_cb *cb, + int socktype) +{ + struct addrinfo hints = { }; + struct addrinfo *ai = NULL; + struct addrinfo *ai0 = NULL; + int fd_pair[2] = { }; + int e = 0; + + memset(ts, 0, sizeof(*ts)); + ts->quit_fd = -1; + ts->stop_fd = -1; + ts->cb = cb; + + e = pthread_mutex_init(&ts->mu, NULL); + if (e) { + warnx("sock_server_init: pthread_mutex_init: %s", strerror(e)); + return false; + } + + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = socktype; + + if (getaddrinfo(NULL, "0", &hints, &ai0)) + return false; + + for (ai = ai0; ai; ai = ai->ai_next) + sock_server_add_fd(ts, ai); + + freeaddrinfo(ai0); + + if (!ts->num_binds) + return false; + + if (pipe(fd_pair)) { + sock_server_uninit(ts); + return false; + } + + ts->quit_fd = fd_pair[0]; + + if (socktype == SOCK_STREAM) + e = pthread_create(&ts->thr, NULL, sock_server_stream, ts); + else + e = pthread_create(&ts->thr, NULL, sock_server_dgram, ts); + if (e) { + warnx("sock_server_init: pthread_create: %s", strerror(e)); + if (close(fd_pair[1])) + warn("sock_server_init: close(%d)", fd_pair[1]); + sock_server_uninit(ts); + return false; + } + + ts->stop_fd = fd_pair[1]; + return true; +} + +bool sock_server_init_tcp(struct sock_server *sock_serv, struct sock_io_cb *cb) +{ + return sock_server_init(sock_serv, cb, SOCK_STREAM); +} + +bool sock_server_init_udp(struct sock_server *sock_serv, struct sock_io_cb *cb) +{ + return sock_server_init(sock_serv, cb, SOCK_DGRAM); +} + +void sock_server_lock(struct sock_server *ts) +{ + int e = pthread_mutex_lock(&ts->mu); + + if (e) + errx(1, "sock_server_lock: pthread_mutex_lock: %s", strerror(e)); +} + +void sock_server_unlock(struct sock_server *ts) +{ + int e = pthread_mutex_unlock(&ts->mu); + + if (e) + errx(1, "sock_server_unlock: pthread_mutex_unlock: %s", + strerror(e)); +} diff --git a/optee/optee_test/host/xtest/sock_server.h b/optee/optee_test/host/xtest/sock_server.h new file mode 100644 index 0000000..6960794 --- /dev/null +++ b/optee/optee_test/host/xtest/sock_server.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2016, Linaro Limited + */ + +#ifndef XTEST_SOCK_SERVER_H +#define XTEST_SOCK_SERVER_H + +#include +#include +#include + +struct sock_server_bind { + int fd; + char host[255]; + int port; +}; + +struct sock_server { + struct sock_server_bind *bind; + size_t num_binds; + int quit_fd; + int stop_fd; + pthread_t thr; + pthread_mutex_t mu; + bool error; + struct sock_io_cb *cb; +}; + +struct sock_io_cb { + bool (*accept)(void *ptr, int fd, short *events); + bool (*read)(void *ptr, int fd, short *events); + bool (*write)(void *ptr, int fd, short *events); + void *ptr; +}; + +bool sock_server_init_tcp(struct sock_server *sock_serv, struct sock_io_cb *cb); +bool sock_server_init_udp(struct sock_server *sock_serv, struct sock_io_cb *cb); +void sock_server_uninit(struct sock_server *sock_serv); +void sock_server_lock(struct sock_server *sock_serv); +void sock_server_unlock(struct sock_server *sock_serv); + +#endif /*XTEST_SOCK_SERVER_H*/ diff --git a/optee/optee_test/host/xtest/stats.c b/optee/optee_test/host/xtest/stats.c new file mode 100644 index 0000000..03df6aa --- /dev/null +++ b/optee/optee_test/host/xtest/stats.c @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xtest_helpers.h" +#include "xtest_test.h" +#include "stats.h" + +#define STATS_UUID { 0xd96a5b40, 0xe2c7, 0xb1af, \ + { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } + +#define STATS_CMD_PAGER_STATS 0 +#define STATS_CMD_ALLOC_STATS 1 +#define STATS_CMD_MEMLEAK_STATS 2 +#define STATS_CMD_TA_STATS 3 + +#define TEE_ALLOCATOR_DESC_LENGTH 32 +struct malloc_stats { + char desc[TEE_ALLOCATOR_DESC_LENGTH]; + uint32_t allocated; /* Bytes currently allocated */ + uint32_t max_allocated; /* Tracks max value of allocated */ + uint32_t size; /* Total size for this allocator */ + uint32_t num_alloc_fail; /* Number of failed alloc requests */ + uint32_t biggest_alloc_fail; /* Size of biggest failed alloc */ + uint32_t biggest_alloc_fail_used; /* Alloc bytes when above occurred */ +}; + +struct ta_dump_stats { + TEEC_UUID uuid; + uint32_t panicked; /* True if TA has panicked */ + uint32_t sess_count; /* Number of opened session */ + struct malloc_stats heap; +}; + +static const char *stats_progname = "xtest --stats"; + +static int usage(void) +{ + fprintf(stderr, "Usage: %s [OPTION]\n", stats_progname); + fprintf(stderr, "Displays statistics from OP-TEE\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -h|--help Print this help and exit\n"); + fprintf(stderr, " --pager Print pager statistics\n"); + fprintf(stderr, " --alloc Print allocation statistics\n"); + fprintf(stderr, " --memleak Dump memory leak data on secure console\n"); + fprintf(stderr, " --ta Print loaded TAs context\n"); + + return EXIT_FAILURE; +} + +static void open_sess(TEEC_Context *ctx, TEEC_Session *sess) +{ + TEEC_UUID uuid = STATS_UUID; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t eo = 0; + + res = TEEC_InitializeContext(NULL, ctx); + if (res) + errx(EXIT_FAILURE, "TEEC_InitializeContext: %#"PRIx32, res); + + res = TEEC_OpenSession(ctx, sess, &uuid, TEEC_LOGIN_PUBLIC, NULL, + NULL, &eo); + if (res) + errx(EXIT_FAILURE, + "TEEC_OpenSession: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); +} + +static int close_sess(TEEC_Context *ctx, TEEC_Session *sess) +{ + TEEC_CloseSession(sess); + TEEC_FinalizeContext(ctx); + + return EXIT_SUCCESS; +} + +static int stat_pager(int argc, char *argv[]) +{ + TEEC_Context ctx = { }; + TEEC_Session sess = { }; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t eo = 0; + TEEC_Operation op = { }; + + UNUSED(argv); + if (argc != 1) + return usage(); + + open_sess(&ctx, &sess); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_VALUE_OUTPUT, + TEEC_VALUE_OUTPUT, TEEC_NONE); + + res = TEEC_InvokeCommand(&sess, STATS_CMD_PAGER_STATS, &op, &eo); + if (res) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + printf("Pager statistics (Number of):\n"); + printf("Unlocked pages: %"PRId32"\n", op.params[0].value.a); + printf("Page pool size: %"PRId32"\n", op.params[0].value.b); + printf("R/O faults: %"PRId32"\n", op.params[1].value.a); + printf("R/W faults: %"PRId32"\n", op.params[1].value.b); + printf("Hidden faults: %"PRId32"\n", op.params[2].value.a); + printf("Zi pages released: %"PRId32"\n", op.params[2].value.b); + + return close_sess(&ctx, &sess); +} + +static int stat_alloc(int argc, char *argv[]) +{ + TEEC_Context ctx = { }; + TEEC_Session sess = { }; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t eo = 0; + TEEC_Operation op = { }; + struct malloc_stats *stats = NULL; + size_t stats_size_bytes = 0; + size_t n = 0; + + UNUSED(argv); + if (argc != 1) + return usage(); + + open_sess(&ctx, &sess); + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(&sess, STATS_CMD_ALLOC_STATS, &op, &eo); + if (res != TEEC_ERROR_SHORT_BUFFER) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + stats_size_bytes = op.params[1].tmpref.size; + if (stats_size_bytes % sizeof(*stats)) + errx(EXIT_FAILURE, + "STATS_CMD_PAGER_STATS: %zu not a multiple of %zu", + stats_size_bytes, sizeof(*stats)); + stats = calloc(1, stats_size_bytes); + if (!stats) + err(EXIT_FAILURE, "calloc(1, %zu)", stats_size_bytes); + + op.params[1].tmpref.buffer = stats; + op.params[1].tmpref.size = stats_size_bytes; + res = TEEC_InvokeCommand(&sess, STATS_CMD_ALLOC_STATS, &op, &eo); + if (res) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + if (op.params[1].tmpref.size != stats_size_bytes) + errx(EXIT_FAILURE, + "STATS_CMD_PAGER_STATS: expected size %zu, got %zu", + stats_size_bytes, op.params[1].tmpref.size); + + for (n = 0; n < stats_size_bytes / sizeof(*stats); n++) { + if (n) + printf("\n"); + printf("Pool: %*s\n", + (int)strnlen(stats[n].desc, sizeof(stats[n].desc)), + stats[n].desc); + printf("Bytes allocated: %"PRId32"\n", + stats[n].allocated); + printf("Max bytes allocated: %"PRId32"\n", + stats[n].max_allocated); + printf("Size of pool: %"PRId32"\n", + stats[n].size); + printf("Number of failed allocations: %"PRId32"\n", + stats[n].num_alloc_fail); + printf("Size of larges allocation failure: %"PRId32"\n", + stats[n].biggest_alloc_fail); + printf("Total bytes allocated at that failure: %"PRId32"\n", + stats[n].biggest_alloc_fail_used); + } + + free(stats); + + return close_sess(&ctx, &sess); +} + +static int stat_memleak(int argc, char *argv[]) +{ + TEEC_Context ctx = { }; + TEEC_Session sess = { }; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t eo = 0; + + UNUSED(argv); + if (argc != 1) + return usage(); + + open_sess(&ctx, &sess); + + res = TEEC_InvokeCommand(&sess, STATS_CMD_MEMLEAK_STATS, NULL, &eo); + if (res) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + return close_sess(&ctx, &sess); +} + +static int stat_loaded_ta(int argc, char *argv[]) +{ + TEEC_Context ctx = { }; + TEEC_Session sess = { }; + TEEC_Result res = TEEC_ERROR_GENERIC; + uint32_t eo = 0; + TEEC_Operation op = { }; + void *buff = NULL; + struct ta_dump_stats *stats = NULL; + size_t stats_size_bytes = 0; + size_t n = 0; + uint32_t retry_count = 10; + + UNUSED(argv); + if (argc != 1) + return usage(); + + open_sess(&ctx, &sess); +retry: + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE, TEEC_NONE); + res = TEEC_InvokeCommand(&sess, STATS_CMD_TA_STATS, &op, &eo); + if (res != TEEC_ERROR_SHORT_BUFFER) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + stats_size_bytes = op.params[0].tmpref.size; + if (stats_size_bytes == 0) { + printf("No loaded TA found"); + goto out; + } + + if (stats_size_bytes % sizeof(*stats)) + errx(EXIT_FAILURE, + "STATS_CMD_TA_STATS: %zu not a multiple of %zu", + stats_size_bytes, sizeof(*stats)); + + /* Always allocate two more in case TA loaded after size querying */ + stats_size_bytes += 2 * sizeof(*stats); + + stats = realloc(buff, stats_size_bytes); + if (!stats) + errx(EXIT_FAILURE, "realloc(%zu) failed", stats_size_bytes); + buff = stats; + + op.params[0].tmpref.buffer = stats; + op.params[0].tmpref.size = stats_size_bytes; + res = TEEC_InvokeCommand(&sess, STATS_CMD_TA_STATS, &op, &eo); + if (res == TEEC_ERROR_SHORT_BUFFER && retry_count > 0) { + retry_count--; + goto retry; + } + + if (res) + errx(EXIT_FAILURE, + "TEEC_InvokeCommand: res %#"PRIx32" err_orig %#"PRIx32, + res, eo); + + for (n = 0; n < op.params[0].tmpref.size / sizeof(*stats); n++) { + if (n) + printf("\n"); + printf("ta(%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x)\n", + stats[n].uuid.timeLow, stats[n].uuid.timeMid, + stats[n].uuid.timeHiAndVersion, + stats[n].uuid.clockSeqAndNode[0], + stats[n].uuid.clockSeqAndNode[1], + stats[n].uuid.clockSeqAndNode[2], + stats[n].uuid.clockSeqAndNode[3], + stats[n].uuid.clockSeqAndNode[4], + stats[n].uuid.clockSeqAndNode[5], + stats[n].uuid.clockSeqAndNode[6], + stats[n].uuid.clockSeqAndNode[7]); + printf("\tpanicked(%"PRId32") -- True if TA has panicked\n", + stats[n].panicked); + printf("\tsession number(%"PRId32")\n", stats[n].sess_count); + printf("\tHeap Status:\n"); + printf("\t\tBytes allocated: %"PRId32"\n", + stats[n].heap.allocated); + printf("\t\tMax bytes allocated: %"PRId32"\n", + stats[n].heap.max_allocated); + printf("\t\tSize of pool: %"PRId32"\n", + stats[n].heap.size); + printf("\t\tNumber of failed allocations: %"PRId32"\n", + stats[n].heap.num_alloc_fail); + printf("\t\tSize of larges allocation failure: %"PRId32"\n", + stats[n].heap.biggest_alloc_fail); + printf("\t\tTotal bytes allocated at that failure: %"PRId32"\n", + stats[n].heap.biggest_alloc_fail_used); + } + +out: + free(buff); + return close_sess(&ctx, &sess); +} + +int stats_runner_cmd_parser(int argc, char *argv[]) +{ + if (argc > 1) { + if (!strcmp(argv[1], "--pager")) + return stat_pager(argc - 1, argv + 1); + if (!strcmp(argv[1], "--alloc")) + return stat_alloc(argc - 1, argv + 1); + if (!strcmp(argv[1], "--memleak")) + return stat_memleak(argc - 1, argv + 1); + if (!strcmp(argv[1], "--ta")) + return stat_loaded_ta(argc - 1, argv + 1); + } + + return usage(); +} diff --git a/optee/optee_test/host/xtest/stats.h b/optee/optee_test/host/xtest/stats.h new file mode 100644 index 0000000..f48ca06 --- /dev/null +++ b/optee/optee_test/host/xtest/stats.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019, Linaro Limited + * + */ + +#ifndef STATS_H +#define STATS_H + +int stats_runner_cmd_parser(int argc, char *argv[]); + +#endif /*STATS_H*/ diff --git a/optee/optee_test/host/xtest/xtest_helpers.c b/optee/optee_test/host/xtest/xtest_helpers.c new file mode 100644 index 0000000..6506fc1 --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_helpers.c @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xtest_helpers.h" +#include "xtest_test.h" + +/* Round up the even multiple of size, size has to be a multiple of 2 */ +#define ROUNDUP(v, size) (((v) + (size - 1)) & ~(size - 1)) + +TEEC_Context xtest_teec_ctx; + +TEEC_Result xtest_teec_ctx_init(void) +{ + return TEEC_InitializeContext(xtest_tee_name, &xtest_teec_ctx); +} + +TEEC_Result xtest_teec_open_session(TEEC_Session *session, + const TEEC_UUID *uuid, TEEC_Operation *op, + uint32_t *ret_orig) +{ + return TEEC_OpenSession(&xtest_teec_ctx, session, uuid, + TEEC_LOGIN_PUBLIC, NULL, op, ret_orig); +} + +void xtest_teec_ctx_deinit(void) +{ + TEEC_FinalizeContext(&xtest_teec_ctx); +} + +TEEC_Result ta_crypt_cmd_allocate_operation(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle *oph, + uint32_t algo, uint32_t mode, + uint32_t max_key_size) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = 0; + op.params[0].value.b = algo; + op.params[1].value.a = mode; + op.params[1].value.b = max_key_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_VALUE_INPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ALLOCATE_OPERATION, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *oph = (TEE_OperationHandle)(uintptr_t)op.params[0].value.a; + + return res; +} + +TEEC_Result ta_crypt_cmd_allocate_transient_object(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectType obj_type, + uint32_t max_obj_size, + TEE_ObjectHandle *o) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = obj_type; + op.params[0].value.b = max_obj_size; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_ALLOCATE_TRANSIENT_OBJECT, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *o = (TEE_ObjectHandle)(uintptr_t)op.params[1].value.a; + + return res; +} + +void xtest_add_attr(size_t *attr_count, TEE_Attribute *attrs, uint32_t attr_id, + const void *buf, size_t len) +{ + attrs[*attr_count].attributeID = attr_id; + attrs[*attr_count].content.ref.buffer = (void *)buf; + attrs[*attr_count].content.ref.length = len; + (*attr_count)++; +} + +void xtest_add_attr_value(size_t *attr_count, TEE_Attribute *attrs, + uint32_t attr_id, uint32_t value_a, uint32_t value_b) +{ + attrs[*attr_count].attributeID = attr_id; + attrs[*attr_count].content.value.a = value_a; + attrs[*attr_count].content.value.b = value_b; + (*attr_count)++; +} + +struct tee_attr_packed { + uint32_t attr_id; + uint32_t a; + uint32_t b; +}; + +TEE_Result pack_attrs(const TEE_Attribute *attrs, uint32_t attr_count, + uint8_t **buf, size_t *blen) +{ + struct tee_attr_packed *a = NULL; + uint8_t *b = NULL; + size_t bl = 0; + size_t n = 0; + + *buf = NULL; + *blen = 0; + if (attr_count == 0) + return TEE_SUCCESS; + + bl = sizeof(uint32_t) + sizeof(struct tee_attr_packed) * attr_count; + for (n = 0; n < attr_count; n++) { + if ((attrs[n].attributeID & TEE_ATTR_BIT_VALUE) != 0) + continue; /* Only memrefs need to be updated */ + + if (!attrs[n].content.ref.buffer) + continue; + + /* Make room for padding */ + bl += ROUNDUP(attrs[n].content.ref.length, 4); + } + + b = calloc(1, bl); + if (!b) + return TEE_ERROR_OUT_OF_MEMORY; + + *buf = b; + *blen = bl; + + *(uint32_t *)(void *)b = attr_count; + b += sizeof(uint32_t); + a = (struct tee_attr_packed *)(void *)b; + b += sizeof(struct tee_attr_packed) * attr_count; + + for (n = 0; n < attr_count; n++) { + a[n].attr_id = attrs[n].attributeID; + if (attrs[n].attributeID & TEE_ATTR_BIT_VALUE) { + a[n].a = attrs[n].content.value.a; + a[n].b = attrs[n].content.value.b; + continue; + } + + a[n].b = attrs[n].content.ref.length; + + if (!attrs[n].content.ref.buffer) { + a[n].a = 0; + continue; + } + + memcpy(b, attrs[n].content.ref.buffer, + attrs[n].content.ref.length); + + /* Make buffer pointer relative to *buf */ + a[n].a = (uint32_t)(uintptr_t)(b - *buf); + + /* Round up to good alignment */ + b += ROUNDUP(attrs[n].content.ref.length, 4); + } + + return TEE_SUCCESS; +} + +TEEC_Result ta_crypt_cmd_populate_transient_object(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectHandle o, + const TEE_Attribute *attrs, + uint32_t attr_count) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + uint8_t *buf = NULL; + size_t blen = 0; + + res = pack_attrs(attrs, attr_count, &buf, &blen); + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + assert((uintptr_t)o <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)o; + + op.params[1].tmpref.buffer = buf; + op.params[1].tmpref.size = blen; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_POPULATE_TRANSIENT_OBJECT, &op, + &ret_orig); + + if (res != TEEC_SUCCESS && res != TEEC_ERROR_TARGET_DEAD) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + free(buf); + return res; +} + +TEE_Result ta_crypt_cmd_set_operation_key(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, + TEE_ObjectHandle key) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + assert((uintptr_t)key <= UINT32_MAX); + op.params[0].value.b = (uint32_t)(uintptr_t)key; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_SET_OPERATION_KEY, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +TEEC_Result ta_crypt_cmd_free_transient_object(ADBG_Case_t *c, TEEC_Session *s, + TEE_ObjectHandle o) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)o <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)o; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_FREE_TRANSIENT_OBJECT, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +TEEC_Result ta_crypt_cmd_derive_key(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph, TEE_ObjectHandle o, + const TEE_Attribute *params, + uint32_t paramCount) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + uint8_t *buf = NULL; + size_t blen = 0; + + res = pack_attrs(params, paramCount, &buf, &blen); + + if (!ADBG_EXPECT_TEEC_SUCCESS(c, res)) + return res; + + assert((uintptr_t)oph <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + assert((uintptr_t)o <= UINT32_MAX); + op.params[0].value.b = (uint32_t)(uintptr_t)o; + + op.params[1].tmpref.buffer = buf; + op.params[1].tmpref.size = blen; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_INPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_DERIVE_KEY, &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + free(buf); + return res; +} + +TEEC_Result ta_crypt_cmd_get_object_buffer_attribute(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectHandle o, + uint32_t attr_id, + void *buf, size_t *blen) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + assert((uintptr_t)o <= UINT32_MAX); + op.params[0].value.a = (uint32_t)(uintptr_t)o; + op.params[0].value.b = attr_id; + + op.params[1].tmpref.buffer = buf; + op.params[1].tmpref.size = *blen; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_GET_OBJECT_BUFFER_ATTRIBUTE, + &op, &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + if (res == TEEC_SUCCESS) + *blen = op.params[1].tmpref.size; + + return res; +} + +TEEC_Result ta_crypt_cmd_free_operation(ADBG_Case_t *c, TEEC_Session *s, + TEE_OperationHandle oph) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + + op.params[0].value.a = (uint32_t)(uintptr_t)oph; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_NONE, TEEC_NONE, + TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_FREE_OPERATION, &op, + &ret_orig); + + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + } + + return res; +} + +bool ta_crypt_cmd_is_algo_supported(ADBG_Case_t *c, TEEC_Session *s, + uint32_t algo, uint32_t element) +{ + TEEC_Result res = TEEC_ERROR_GENERIC; + TEEC_Operation op = TEEC_OPERATION_INITIALIZER; + uint32_t ret_orig = 0; + TEEC_Result st = TEEC_ERROR_GENERIC; + + op.params[0].value.a = algo; + op.params[0].value.b = element; + + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INPUT, TEEC_VALUE_OUTPUT, + TEEC_NONE, TEEC_NONE); + + res = TEEC_InvokeCommand(s, TA_CRYPT_CMD_IS_ALGO_SUPPORTED, &op, + &ret_orig); + if (res != TEEC_SUCCESS) { + (void)ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, TEEC_ORIGIN_TRUSTED_APP, + ret_orig); + return res; + } + + st = op.params[1].value.a; + ADBG_EXPECT_TRUE(c, st == TEEC_SUCCESS || + st == TEEC_ERROR_NOT_SUPPORTED); + if (st == TEE_SUCCESS) + return true; + return false; +} + +TEEC_Result ta_os_test_cmd_client_identity(TEEC_Session *session, + uint32_t *login, + TEEC_UUID *client_uuid) +{ + TEEC_Operation operation = { }; + TEEC_Result result = TEEC_ERROR_GENERIC; + + operation.params[1].tmpref.buffer = client_uuid; + operation.params[1].tmpref.size = sizeof(*client_uuid); + + operation.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, TEEC_NONE); + + result = TEEC_InvokeCommand(session, TA_OS_TEST_CMD_CLIENT_IDENTITY, + &operation, NULL); + + if (result != TEEC_SUCCESS) + return result; + + *login = operation.params[0].value.a; + + return TEEC_SUCCESS; +} + +void xtest_mutex_init(pthread_mutex_t *mutex) +{ + int e = pthread_mutex_init(mutex, NULL); + + if (e) + errx(1, "pthread_mutex_init: %s", strerror(e)); +} + +void xtest_mutex_destroy(pthread_mutex_t *mutex) +{ + int e = pthread_mutex_destroy(mutex); + + if (e) + errx(1, "pthread_mutex_destroy: %s", strerror(e)); +} + +void xtest_mutex_lock(pthread_mutex_t *mutex) +{ + int e = pthread_mutex_lock(mutex); + + if (e) + errx(1, "pthread_mutex_lock: %s", strerror(e)); +} + +void xtest_mutex_unlock(pthread_mutex_t *mutex) +{ + int e = pthread_mutex_unlock(mutex); + + if (e) + errx(1, "pthread_mutex_unlock: %s", strerror(e)); +} + +void xtest_barrier_init(pthread_barrier_t *barrier, unsigned count) +{ + int e = pthread_barrier_init(barrier, NULL, count); + + if (e) + errx(1, "pthread_barrier_init: %s", strerror(e)); +} + +void xtest_barrier_destroy(pthread_barrier_t *barrier) +{ + int e = pthread_barrier_destroy(barrier); + + if (e) + errx(1, "pthread_barrier_destroy: %s", strerror(e)); +} + +int xtest_barrier_wait(pthread_barrier_t *barrier) +{ + int e = pthread_barrier_wait(barrier); + + if (e && e != PTHREAD_BARRIER_SERIAL_THREAD) + errx(1, "pthread _barrier_wait: %s", strerror(e)); + return e; +} diff --git a/optee/optee_test/host/xtest/xtest_helpers.h b/optee/optee_test/host/xtest/xtest_helpers.h new file mode 100644 index 0000000..888e4aa --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_helpers.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef XTEST_HELPERS_H +#define XTEST_HELPERS_H + +#include +#include +#include +#include +#include +#include + +extern unsigned int level; + +/* Global context to use if any context is needed as input to a function */ +extern TEEC_Context xtest_teec_ctx; + +/* + * Initializes the context above, should be called before the ADBG test + * cases are run. + */ +TEEC_Result xtest_teec_ctx_init(void); +void xtest_teec_ctx_deinit(void); + +/* Opens a session */ +TEEC_Result xtest_teec_open_session(TEEC_Session *session, + const TEEC_UUID *uuid, TEEC_Operation *op, + uint32_t *ret_orig); + +TEEC_Result xtest_teec_open_static_session(TEEC_Session *session, + TEEC_Operation *op, + uint32_t *ret_orig); + +#define TEEC_OPERATION_INITIALIZER { } + +/* IO access macro */ +#define IO(addr) (*((volatile unsigned long *)(addr))) + +#define UNUSED(x) (void)(x) +/* + * Helpers for commands towards the crypt TA + */ +TEEC_Result ta_crypt_cmd_allocate_operation(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle *oph, + uint32_t algo, + uint32_t mode, + uint32_t max_key_size); + +TEEC_Result ta_crypt_cmd_allocate_transient_object(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectType obj_type, uint32_t max_obj_size, + TEE_ObjectHandle *o); + +TEEC_Result ta_crypt_cmd_populate_transient_object(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectHandle o, + const TEE_Attribute *attrs, + uint32_t attr_count); + +TEE_Result ta_crypt_cmd_set_operation_key(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + TEE_ObjectHandle key); + +TEEC_Result ta_crypt_cmd_free_transient_object(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectHandle o); + +TEEC_Result ta_crypt_cmd_derive_key(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph, + TEE_ObjectHandle o, + const TEE_Attribute *params, + uint32_t paramCount); + +TEEC_Result ta_crypt_cmd_get_object_buffer_attribute(ADBG_Case_t *c, + TEEC_Session *s, + TEE_ObjectHandle o, + uint32_t attr_id, + void *buf, + size_t *blen); + +TEEC_Result ta_crypt_cmd_free_operation(ADBG_Case_t *c, + TEEC_Session *s, + TEE_OperationHandle oph); + +bool ta_crypt_cmd_is_algo_supported(ADBG_Case_t *c, TEEC_Session *s, + uint32_t alg, uint32_t element); + +TEEC_Result ta_os_test_cmd_client_identity(TEEC_Session *session, + uint32_t *login, + TEEC_UUID *client_uuid); + +void xtest_add_attr(size_t *attr_count, TEE_Attribute *attrs, + uint32_t attr_id, const void *buf, size_t len); +void xtest_add_attr_value(size_t *attr_count, TEE_Attribute *attrs, + uint32_t attr_id, uint32_t value_a, uint32_t value_b); + +TEE_Result pack_attrs(const TEE_Attribute *attrs, uint32_t attr_count, + uint8_t **buf, size_t *blen); + +void xtest_mutex_init(pthread_mutex_t *mutex); +void xtest_mutex_destroy(pthread_mutex_t *mutex); +void xtest_mutex_lock(pthread_mutex_t *mutex); +void xtest_mutex_unlock(pthread_mutex_t *mutex); + +void xtest_barrier_init(pthread_barrier_t *barrier, unsigned count); +void xtest_barrier_destroy(pthread_barrier_t *barrier); +int xtest_barrier_wait(pthread_barrier_t *barrier); + +#endif /*XTEST_HELPERS_H*/ diff --git a/optee/optee_test/host/xtest/xtest_main.c b/optee/optee_test/host/xtest/xtest_main.c new file mode 100644 index 0000000..9771ae0 --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_main.c @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_FOUND +#include +#include +#include +#endif + +#include +#include "xtest_test.h" +#include "xtest_helpers.h" + +/* include here shandalone tests */ +#include "crypto_common.h" +#include "install_ta.h" +#include "stats.h" + + +ADBG_SUITE_DEFINE(benchmark); +#ifdef WITH_GP_TESTS +ADBG_SUITE_DEFINE(gp); +#endif +#ifdef CFG_PKCS11_TA +ADBG_SUITE_DEFINE(pkcs11); +#endif +#ifdef CFG_SPMC_TESTS +ADBG_SUITE_DEFINE(ffa_spmc); +#endif +ADBG_SUITE_DEFINE(regression); + +char *xtest_tee_name = NULL; +unsigned int level = 0; +static const char glevel[] = "0"; + +#ifdef WITH_GP_TESTS +#define GP_SUITE "+gp" +#else +#define GP_SUITE "" +#endif + +#ifdef CFG_PKCS11_TA +#define PKCS11_SUITE "+pkcs11" +#else +#define PKCS11_SUITE "" +#endif + +#ifdef CFG_SPMC_TESTS +#define FFA_SPMC_SUITE "+ffa_spmc" +#else +#define FFA_SPMC_SUITE "" +#endif + +static char gsuitename[] = "regression" GP_SUITE PKCS11_SUITE FFA_SPMC_SUITE; + +void usage(char *program); + +void usage(char *program) +{ + printf("Usage: %s [[-x] ]...]\n", program); + printf("\n"); + printf("options:\n"); + printf("\t-d TEE identifier. Use default TEE if not set\n"); + printf("\t-l Test level [0-15]. Values higher than 0 enable\n"); + printf("\t optional tests. Default: 0. All tests: 15.\n"); + printf("\t-t Available test suites: regression benchmark"); +#ifdef WITH_GP_TESTS + printf(" gp"); +#endif +#ifdef CFG_PKCS11_TA + printf(" pkcs11"); +#endif +#ifdef CFG_SPMC_TESTS + printf(" ffa_spmc"); +#endif + printf("\n"); + printf("\t To run several suites, use multiple names\n"); + printf("\t separated by a '+')\n"); + printf("\t Default value: '%s'\n", gsuitename); + printf("\t-h Show usage\n"); + printf("\t Add to the list of tests to be run.\n"); + printf("\t A substring match is performed. May be specified\n"); + printf("\t several times. If no tests are given, all the\n"); + printf("\t tests are added.\n"); + printf("\t-x Exclude from the list of tests to be\n"); + printf("\t run. A substring match is performed. May be\n"); + printf("\t specified several times.\n"); + printf("applets:\n"); + printf("\t--sha-perf [opts] Deprecated, same as --hash-perf\n"); + printf("\t--hash-perf [opts] Hash performance testing tool (-h for usage)\n"); + printf("\t--aes-perf [opts] AES performance testing tool (-h for usage)\n"); +#ifdef CFG_SECSTOR_TA_MGMT_PTA + printf("\t--install-ta [directory or list of TAs]\n"); + printf("\t Install TAs\n"); +#endif +#ifdef CFG_SECURE_DATA_PATH + printf("\t--sdp-basic [opts] Basic Secure Data Path test setup ('-h' for usage)\n"); +#endif + printf("\t--stats [opts] Various statistics ('-h' for usage)\n"); + printf("\n"); + printf("Examples:\n"); + printf("\txtest -t regression 4001 4003\n"); + printf("\t run regression tests 4001 and 4003\n"); + printf("\txtest -t regression -x 1027 -x 1028\n"); + printf("\t run all regression tests but 1027 and 1028\n"); + printf("\n"); +} + +static void init_ossl(void) +{ +#ifdef OPENSSL_FOUND + OPENSSL_init(); + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); +#endif +} + +int main(int argc, char *argv[]) +{ + int opt = 0; + int index = 0; + TEEC_Result tee_res = TEEC_ERROR_GENERIC; + int ret = 0; + char *p = (char *)glevel; + char *test_suite = (char *)gsuitename; + char *token = NULL; + ADBG_Suite_Definition_t all = { + .SuiteID_p = NULL, + .cases = TAILQ_HEAD_INITIALIZER(all.cases), + }; + bool exclusion = false; + size_t last_gen_option = 1; + + opterr = 0; + + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) + warn("signal(SIGPIPE, SIG_IGN)"); + + if (signal(SIGHUP, SIG_IGN) == SIG_ERR) + warn("signal(SIGPIPE, SIG_IGN)"); + + init_ossl(); + + if (argc > 1 && !strcmp(argv[1], "--sha-perf")) + return hash_perf_runner_cmd_parser(argc-1, &argv[1]); + else if (argc > 1 && !strcmp(argv[1], "--hash-perf")) + return hash_perf_runner_cmd_parser(argc-1, &argv[1]); + else if (argc > 1 && !strcmp(argv[1], "--aes-perf")) + return aes_perf_runner_cmd_parser(argc-1, &argv[1]); +#ifdef CFG_SECSTOR_TA_MGMT_PTA + else if (argc > 1 && !strcmp(argv[1], "--install-ta")) + return install_ta_runner_cmd_parser(argc - 1, argv + 1); +#endif +#ifdef CFG_SECURE_DATA_PATH + else if (argc > 1 && !strcmp(argv[1], "--sdp-basic")) + return sdp_basic_runner_cmd_parser(argc-1, &argv[1]); +#endif + else if (argc > 1 && !strcmp(argv[1], "--stats")) + return stats_runner_cmd_parser(argc - 1, &argv[1]); + + while ((opt = getopt(argc, argv, "d:l:t:h")) != -1) { + switch (opt) { + case 'd': + xtest_tee_name = optarg; + last_gen_option = optind; + break; + case 'l': + p = optarg; + last_gen_option = optind; + break; + case 't': + test_suite = optarg; + last_gen_option = optind; + break; + case 'h': + usage(argv[0]); + return 0; + case '?': + if (optopt == 'x') { + /* + * The -x option is not processed here, + * it is part of the test IDs. + */ + goto next; + } + /* option not recognized */ + usage(argv[0]); + return -1; + default: + usage(argv[0]); + return -1; + } + } +next: + + for (index = last_gen_option; index < argc; index++) { + if (!strcmp(argv[index], "-x")) { + exclusion = true; + continue; + } + printf("Test ID: %s%s\n", exclusion ? "-x " : "", argv[index]); + exclusion = false; + } + + if (p) + level = atoi(p); + else + level = 0; + printf("Run test suite with level=%d\n", level); + + printf("\nTEE test application started over %s TEE instance\n", + xtest_tee_name ? xtest_tee_name : "default"); + + tee_res = xtest_teec_ctx_init(); + if (tee_res != TEEC_SUCCESS) { + fprintf(stderr, "Failed to open TEE context: 0x%" PRIx32 "\n", + tee_res); + return -1; + } + + /* Concatenate all the selected suites into 'all' */ + for (token = test_suite; ; token = NULL) { + + token = strtok(token, "+"); + if (!token) + break; + + if (!strcmp(token, "regression")) + ret = Do_ADBG_AppendToSuite(&all, &ADBG_Suite_regression); + else if (!strcmp(token, "benchmark")) + ret = Do_ADBG_AppendToSuite(&all, &ADBG_Suite_benchmark); +#ifdef WITH_GP_TESTS + else if (!strcmp(token, "gp")) + ret = Do_ADBG_AppendToSuite(&all, &ADBG_Suite_gp); +#endif +#ifdef CFG_PKCS11_TA + else if (!strcmp(token, "pkcs11")) + ret = Do_ADBG_AppendToSuite(&all, &ADBG_Suite_pkcs11); +#endif +#ifdef CFG_SPMC_TESTS + else if (!strcmp(token, "ffa_spmc")) + ret = Do_ADBG_AppendToSuite(&all, &ADBG_Suite_ffa_spmc); +#endif + else { + fprintf(stderr, "Unkown test suite: %s\n", token); + ret = -1; + } + if (ret < 0) + goto err; + } + + /* Run the tests */ + ret = Do_ADBG_RunSuite(&all, argc - last_gen_option, argv + last_gen_option); + +err: + free((void *)all.SuiteID_p); + xtest_teec_ctx_deinit(); + + printf("TEE test application done!\n"); + return ret; +} diff --git a/optee/optee_test/host/xtest/xtest_test.c b/optee/optee_test/host/xtest/xtest_test.c new file mode 100644 index 0000000..7beecff --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_test.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#include "xtest_test.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <__tee_isocket_defines.h> +#include <__tee_tcpsocket_defines.h> +#include <__tee_udpsocket_defines.h> + +ADBG_ENUM_TABLE_DEFINE_BEGIN(TEEC_Result) +ADBG_ENUM_TABLE_ENTRY(TEEC_SUCCESS), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_CORRUPT_OBJECT), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_CORRUPT_OBJECT_2), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_STORAGE_NOT_AVAILABLE), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_STORAGE_NOT_AVAILABLE_2), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_GENERIC), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_ACCESS_DENIED), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_CANCEL), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_ACCESS_CONFLICT), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_EXCESS_DATA), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_BAD_FORMAT), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_BAD_PARAMETERS), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_BAD_STATE), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_ITEM_NOT_FOUND), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_NOT_IMPLEMENTED), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_NOT_SUPPORTED), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_NO_DATA), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_OUT_OF_MEMORY), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_BUSY), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_COMMUNICATION), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_SECURITY), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_SHORT_BUFFER), +ADBG_ENUM_TABLE_ENTRY(TEEC_ERROR_EXTERNAL_CANCEL), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_OVERFLOW), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_TARGET_DEAD), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_STORAGE_NO_SPACE), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_MAC_INVALID), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_SIGNATURE_INVALID), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_TIME_NOT_SET), +ADBG_ENUM_TABLE_ENTRY(TEE_ERROR_TIME_NEEDS_RESET), +ADBG_ENUM_TABLE_ENTRY(TEE_ISOCKET_ERROR_PROTOCOL), +ADBG_ENUM_TABLE_ENTRY(TEE_ISOCKET_ERROR_REMOTE_CLOSED), +ADBG_ENUM_TABLE_ENTRY(TEE_ISOCKET_ERROR_TIMEOUT), +ADBG_ENUM_TABLE_ENTRY(TEE_ISOCKET_ERROR_OUT_OF_RESOURCES), +ADBG_ENUM_TABLE_ENTRY(TEE_ISOCKET_ERROR_LARGE_BUFFER), +ADBG_ENUM_TABLE_ENTRY(TEE_ISOCKET_WARNING_PROTOCOL), +ADBG_ENUM_TABLE_ENTRY(TEE_ISOCKET_ERROR_HOSTNAME), +ADBG_ENUM_TABLE_ENTRY(TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND) +ADBG_ENUM_TABLE_DEFINE_END(TEEC_Result); + +ADBG_ENUM_TABLE_DEFINE_BEGIN(TEEC_ErrorOrigin) +ADBG_ENUM_TABLE_ENTRY(TEEC_ORIGIN_API), +ADBG_ENUM_TABLE_ENTRY(TEEC_ORIGIN_COMMS), +ADBG_ENUM_TABLE_ENTRY(TEEC_ORIGIN_TEE), +ADBG_ENUM_TABLE_ENTRY(TEEC_ORIGIN_TRUSTED_APP) +ADBG_ENUM_TABLE_DEFINE_END(TEEC_ErrorOrigin); + +#ifdef CFG_PKCS11_TA +ADBG_ENUM_TABLE_DEFINE_BEGIN(CK_RV) +ADBG_ENUM_TABLE_ENTRY(CKR_OK), +ADBG_ENUM_TABLE_ENTRY(CKR_CANCEL), +ADBG_ENUM_TABLE_ENTRY(CKR_HOST_MEMORY), +ADBG_ENUM_TABLE_ENTRY(CKR_SLOT_ID_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_GENERAL_ERROR), +ADBG_ENUM_TABLE_ENTRY(CKR_FUNCTION_FAILED), +ADBG_ENUM_TABLE_ENTRY(CKR_ARGUMENTS_BAD), +ADBG_ENUM_TABLE_ENTRY(CKR_NO_EVENT), +ADBG_ENUM_TABLE_ENTRY(CKR_NEED_TO_CREATE_THREADS), +ADBG_ENUM_TABLE_ENTRY(CKR_CANT_LOCK), +ADBG_ENUM_TABLE_ENTRY(CKR_ATTRIBUTE_READ_ONLY), +ADBG_ENUM_TABLE_ENTRY(CKR_ATTRIBUTE_SENSITIVE), +ADBG_ENUM_TABLE_ENTRY(CKR_ATTRIBUTE_TYPE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_ATTRIBUTE_VALUE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_ACTION_PROHIBITED), +ADBG_ENUM_TABLE_ENTRY(CKR_DATA_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_DATA_LEN_RANGE), +ADBG_ENUM_TABLE_ENTRY(CKR_DEVICE_ERROR), +ADBG_ENUM_TABLE_ENTRY(CKR_DEVICE_MEMORY), +ADBG_ENUM_TABLE_ENTRY(CKR_DEVICE_REMOVED), +ADBG_ENUM_TABLE_ENTRY(CKR_ENCRYPTED_DATA_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_ENCRYPTED_DATA_LEN_RANGE), +ADBG_ENUM_TABLE_ENTRY(CKR_FUNCTION_CANCELED), +ADBG_ENUM_TABLE_ENTRY(CKR_FUNCTION_NOT_PARALLEL), +ADBG_ENUM_TABLE_ENTRY(CKR_FUNCTION_NOT_SUPPORTED), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_HANDLE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_SIZE_RANGE), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_TYPE_INCONSISTENT), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_NOT_NEEDED), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_CHANGED), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_NEEDED), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_INDIGESTIBLE), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_FUNCTION_NOT_PERMITTED), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_NOT_WRAPPABLE), +ADBG_ENUM_TABLE_ENTRY(CKR_KEY_UNEXTRACTABLE), +ADBG_ENUM_TABLE_ENTRY(CKR_MECHANISM_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_MECHANISM_PARAM_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_OBJECT_HANDLE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_OPERATION_ACTIVE), +ADBG_ENUM_TABLE_ENTRY(CKR_OPERATION_NOT_INITIALIZED), +ADBG_ENUM_TABLE_ENTRY(CKR_PIN_INCORRECT), +ADBG_ENUM_TABLE_ENTRY(CKR_PIN_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_PIN_LEN_RANGE), +ADBG_ENUM_TABLE_ENTRY(CKR_PIN_EXPIRED), +ADBG_ENUM_TABLE_ENTRY(CKR_PIN_LOCKED), +ADBG_ENUM_TABLE_ENTRY(CKR_SESSION_CLOSED), +ADBG_ENUM_TABLE_ENTRY(CKR_SESSION_COUNT), +ADBG_ENUM_TABLE_ENTRY(CKR_SESSION_HANDLE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_SESSION_PARALLEL_NOT_SUPPORTED), +ADBG_ENUM_TABLE_ENTRY(CKR_SESSION_READ_ONLY), +ADBG_ENUM_TABLE_ENTRY(CKR_SESSION_EXISTS), +ADBG_ENUM_TABLE_ENTRY(CKR_SESSION_READ_ONLY_EXISTS), +ADBG_ENUM_TABLE_ENTRY(CKR_SESSION_READ_WRITE_SO_EXISTS), +ADBG_ENUM_TABLE_ENTRY(CKR_SIGNATURE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_SIGNATURE_LEN_RANGE), +ADBG_ENUM_TABLE_ENTRY(CKR_TEMPLATE_INCOMPLETE), +ADBG_ENUM_TABLE_ENTRY(CKR_TEMPLATE_INCONSISTENT), +ADBG_ENUM_TABLE_ENTRY(CKR_TOKEN_NOT_PRESENT), +ADBG_ENUM_TABLE_ENTRY(CKR_TOKEN_NOT_RECOGNIZED), +ADBG_ENUM_TABLE_ENTRY(CKR_TOKEN_WRITE_PROTECTED), +ADBG_ENUM_TABLE_ENTRY(CKR_UNWRAPPING_KEY_HANDLE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_UNWRAPPING_KEY_SIZE_RANGE), +ADBG_ENUM_TABLE_ENTRY(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT), +ADBG_ENUM_TABLE_ENTRY(CKR_USER_ALREADY_LOGGED_IN), +ADBG_ENUM_TABLE_ENTRY(CKR_USER_NOT_LOGGED_IN), +ADBG_ENUM_TABLE_ENTRY(CKR_USER_PIN_NOT_INITIALIZED), +ADBG_ENUM_TABLE_ENTRY(CKR_USER_TYPE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_USER_ANOTHER_ALREADY_LOGGED_IN), +ADBG_ENUM_TABLE_ENTRY(CKR_USER_TOO_MANY_TYPES), +ADBG_ENUM_TABLE_ENTRY(CKR_WRAPPED_KEY_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_WRAPPED_KEY_LEN_RANGE), +ADBG_ENUM_TABLE_ENTRY(CKR_WRAPPING_KEY_HANDLE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_WRAPPING_KEY_SIZE_RANGE), +ADBG_ENUM_TABLE_ENTRY(CKR_WRAPPING_KEY_TYPE_INCONSISTENT), +ADBG_ENUM_TABLE_ENTRY(CKR_RANDOM_SEED_NOT_SUPPORTED), +ADBG_ENUM_TABLE_ENTRY(CKR_RANDOM_NO_RNG), +ADBG_ENUM_TABLE_ENTRY(CKR_DOMAIN_PARAMS_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_CURVE_NOT_SUPPORTED), +ADBG_ENUM_TABLE_ENTRY(CKR_BUFFER_TOO_SMALL), +ADBG_ENUM_TABLE_ENTRY(CKR_SAVED_STATE_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_INFORMATION_SENSITIVE), +ADBG_ENUM_TABLE_ENTRY(CKR_STATE_UNSAVEABLE), +ADBG_ENUM_TABLE_ENTRY(CKR_CRYPTOKI_NOT_INITIALIZED), +ADBG_ENUM_TABLE_ENTRY(CKR_CRYPTOKI_ALREADY_INITIALIZED), +ADBG_ENUM_TABLE_ENTRY(CKR_MUTEX_BAD), +ADBG_ENUM_TABLE_ENTRY(CKR_MUTEX_NOT_LOCKED), +ADBG_ENUM_TABLE_ENTRY(CKR_NEW_PIN_MODE), +ADBG_ENUM_TABLE_ENTRY(CKR_NEXT_OTP), +ADBG_ENUM_TABLE_ENTRY(CKR_EXCEEDED_MAX_ITERATIONS), +ADBG_ENUM_TABLE_ENTRY(CKR_FIPS_SELF_TEST_FAILED), +ADBG_ENUM_TABLE_ENTRY(CKR_LIBRARY_LOAD_FAILED), +ADBG_ENUM_TABLE_ENTRY(CKR_PIN_TOO_WEAK), +ADBG_ENUM_TABLE_ENTRY(CKR_PUBLIC_KEY_INVALID), +ADBG_ENUM_TABLE_ENTRY(CKR_FUNCTION_REJECTED), +ADBG_ENUM_TABLE_ENTRY(CKR_VENDOR_DEFINED) +ADBG_ENUM_TABLE_DEFINE_END(CK_RV); +#endif /*CFG_PKCS11_TA*/ + +#define ECC_SELF_TEST_UUID \ + { 0xf34f4f3c, 0xab30, 0x4573, \ + { 0x91, 0xBF, 0x3C, 0x57, 0x02, 0x4D, 0x51, 0x99 } } + +const TEEC_UUID crypt_user_ta_uuid = TA_CRYPT_UUID; +const TEEC_UUID os_test_ta_uuid = TA_OS_TEST_UUID; +const TEEC_UUID create_fail_test_ta_uuid = TA_CREATE_FAIL_TEST_UUID; +const TEEC_UUID ecc_test_ta_uuid = ECC_SELF_TEST_UUID; +const TEEC_UUID pta_invoke_tests_ta_uuid = PTA_INVOKE_TESTS_UUID; +const TEEC_UUID rpc_test_ta_uuid = TA_RPC_TEST_UUID; +const TEEC_UUID sims_test_ta_uuid = TA_SIMS_TEST_UUID; +const TEEC_UUID miss_test_ta_uuid = TA_MISS_TEST_UUID; +const TEEC_UUID sims_keepalive_test_ta_uuid = TA_SIMS_KEEP_ALIVE_TEST_UUID; +const TEEC_UUID storage_ta_uuid = TA_STORAGE_UUID; +const TEEC_UUID storage2_ta_uuid = TA_STORAGE2_UUID; +const TEEC_UUID enc_fs_key_manager_test_ta_uuid = ENC_FS_KEY_MANAGER_TEST_UUID; +const TEEC_UUID concurrent_ta_uuid = TA_CONCURRENT_UUID; +const TEEC_UUID concurrent_large_ta_uuid = TA_CONCURRENT_LARGE_UUID; +const TEEC_UUID storage_benchmark_ta_uuid = TA_STORAGE_BENCHMARK_UUID; +const TEEC_UUID socket_ta_uuid = TA_SOCKET_UUID; +const TEEC_UUID sdp_basic_ta_uuid = TA_SDP_BASIC_UUID; +const TEEC_UUID tpm_log_test_ta_uuid = TA_TPM_LOG_TEST_UUID; +const TEEC_UUID supp_plugin_test_ta_uuid = TA_SUPP_PLUGIN_UUID; +const TEEC_UUID large_ta_uuid = TA_LARGE_UUID; +const TEEC_UUID bti_test_ta_uuid = TA_BTI_UUID; +const TEEC_UUID subkey1_ta_uuid = TA_SUBKEY1_UUID; +const TEEC_UUID subkey2_ta_uuid = TA_SUBKEY2_UUID; diff --git a/optee/optee_test/host/xtest/xtest_test.h b/optee/optee_test/host/xtest/xtest_test.h new file mode 100644 index 0000000..50fc2b5 --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_test.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2016, Linaro Limited + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef XTEST_TEST_H +#define XTEST_TEST_H +#include +#include + +#ifdef CFG_PKCS11_TA +#include +#endif + +ADBG_SUITE_DECLARE(benchmark); +#ifdef WITH_GP_TESTS +ADBG_SUITE_DECLARE(gp); +#endif +#ifdef CFG_PKCS11_TA +ADBG_SUITE_DECLARE(pkcs11); +#endif +#ifdef CFG_SPMC_TESTS +ADBG_SUITE_DECLARE(ffa_spmc); +#endif +ADBG_SUITE_DECLARE(regression); + +/* TEEC_Result */ +ADBG_ENUM_TABLE_DECLARE(TEEC_Result); + +#define ADBG_EXPECT_TEEC_RESULT(c, exp, got) \ + ADBG_EXPECT_ENUM(c, exp, got, ADBG_EnumTable_TEEC_Result) + +#define ADBG_EXPECT_TEEC_SUCCESS(c, got) \ + ADBG_EXPECT_ENUM(c, TEEC_SUCCESS, got, ADBG_EnumTable_TEEC_Result) + +/* TEEC_ErrorOrigin */ +ADBG_ENUM_TABLE_DECLARE(TEEC_ErrorOrigin); + +#define ADBG_EXPECT_TEEC_ERROR_ORIGIN(c, exp, got) \ + ADBG_EXPECT_ENUM(c, exp, got, ADBG_EnumTable_TEEC_ErrorOrigin) + +#ifdef CFG_PKCS11_TA +/* CK_RV */ +ADBG_ENUM_TABLE_DECLARE(CK_RV); + +#define ADBG_EXPECT_CK_RESULT(c, exp, got) \ + ADBG_EXPECT_ENUM(c, exp, got, ADBG_EnumTable_CK_RV) + +#define ADBG_EXPECT_CK_OK(c, got) \ + ADBG_EXPECT_ENUM(c, CKR_OK, got, ADBG_EnumTable_CK_RV) +#endif + +extern const char crypt_user_ta[]; +extern const unsigned int crypt_user_ta_size; + +extern const char os_test_ta[]; +extern const unsigned int os_test_ta_size; + +extern const char create_fail_test_ta[]; +extern const unsigned int create_fail_test_ta_size; + +extern const char rpc_test_ta[]; +extern const unsigned int rpc_test_ta_size; + +extern const char sims_test_ta[]; +extern const unsigned int sims_test_ta_size; + +extern const char gp_tta_testing_client_api_ta[]; +extern const unsigned int gp_tta_testing_client_api_ta_size; + +extern const char gp_tta_answer_success_to_open_session_invoke_ta[]; +extern const unsigned int gp_tta_answer_success_to_open_session_invoke_ta_size; + +extern const char gp_tta_answer_error_to_invoke_ta[]; +extern const unsigned int gp_tta_answer_error_to_invoke_ta_size; + +extern const char gp_tta_answer_error_to_open_session_ta[]; +extern const unsigned int gp_tta_answer_error_to_open_session_ta_size; + +extern const char gp_tta_check_open_session_with_4_parameters_ta[]; +extern const unsigned int gp_tta_check_open_session_with_4_parameters_ta_size; + +extern const char gp_tta_ds_ta[]; +extern const unsigned int gp_tta_ds_ta_size; + +extern const char storage_ta[]; +extern const unsigned int storage_ta_size; + +extern const char gp_tta_time_ta[]; +extern const unsigned int gp_tta_time_ta_size; + +extern const char gp_tta_tcf_ta[]; +extern const unsigned int gp_tta_tcf_ta_size; + +extern const char gp_tta_crypto_ta[]; +extern const unsigned int gp_tta_crypto_ta_size; + +extern const char gp_tta_arithm_ta[]; +extern const unsigned int gp_tta_arithm_ta_size; + +extern const char gp_tta_ica_ta[]; +extern const unsigned int gp_tta_ica_ta_size; + +extern const char gp_tta_ica2_ta[]; +extern const unsigned int gp_tta_ica2_ta_size; + +extern const char gp_tta_tcf_singleinstance_ta[]; +extern const unsigned int gp_tta_tcf_singleinstance_ta_size; + +extern const char gp_tta_tcf_multipleinstance_ta[]; +extern const unsigned int gp_tta_tcf_multipleinstance_ta_size; + +extern const TEEC_UUID crypt_user_ta_uuid; +extern const TEEC_UUID os_test_ta_uuid; +extern const TEEC_UUID create_fail_test_ta_uuid; +extern const TEEC_UUID rpc_test_ta_uuid; +extern const TEEC_UUID sims_test_ta_uuid; +extern const TEEC_UUID miss_test_ta_uuid; +extern const TEEC_UUID sims_keepalive_test_ta_uuid; +extern const TEEC_UUID gp_tta_testing_client_api_uuid; +extern const TEEC_UUID gp_tta_answer_success_to_open_session_invoke_uuid; +extern const TEEC_UUID gp_tta_answer_error_to_invoke_uuid; +extern const TEEC_UUID gp_tta_answer_error_to_open_session_uuid; +extern const TEEC_UUID gp_tta_check_OpenSession_with_4_parameters_uuid; +extern const TEEC_UUID gp_tta_ds_uuid; +extern const TEEC_UUID storage_ta_uuid; +extern const TEEC_UUID storage2_ta_uuid; +extern const TEEC_UUID enc_fs_key_manager_test_ta_uuid; +extern const TEEC_UUID ecc_test_ta_uuid; +extern const TEEC_UUID pta_invoke_tests_ta_uuid; +extern const TEEC_UUID gp_tta_time_uuid; +extern const TEEC_UUID concurrent_ta_uuid; +extern const TEEC_UUID concurrent_large_ta_uuid; +extern const TEEC_UUID storage_benchmark_ta_uuid; +extern const TEEC_UUID socket_ta_uuid; +extern const TEEC_UUID sdp_basic_ta_uuid; +extern const TEEC_UUID tpm_log_test_ta_uuid; +extern const TEEC_UUID supp_plugin_test_ta_uuid; +extern const TEEC_UUID large_ta_uuid; +extern const TEEC_UUID bti_test_ta_uuid; +extern const TEEC_UUID subkey1_ta_uuid; +extern const TEEC_UUID subkey2_ta_uuid; +extern char *xtest_tee_name; + +#endif /*XTEST_TEST_H*/ diff --git a/optee/optee_test/host/xtest/xtest_uuid_helpers.c b/optee/optee_test/host/xtest/xtest_uuid_helpers.c new file mode 100644 index 0000000..1b43e10 --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_uuid_helpers.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#ifdef OPENSSL_FOUND +#include +#endif +#include +#include +#include +#include +#include "xtest_uuid_helpers.h" + +static int hex(char c) +{ + char lc = tolower(c); + + if (isdigit(lc)) + return lc - '0'; + if (isxdigit(lc)) + return lc - 'a' + 10; + return -1; +} + +static uint32_t parse_hex(const char *s, size_t nchars, uint32_t *res) +{ + uint32_t v = 0; + size_t n = 0; + int c = 0; + + for (n = 0; n < nchars; n++) { + c = hex(s[n]); + if (c == -1) { + *res = TEE_ERROR_BAD_FORMAT; + goto out; + } + v = (v << 4) + c; + } + *res = TEE_SUCCESS; +out: + return v; +} + +TEEC_Result xtest_uuid_from_str(TEEC_UUID *uuid, const char *s) +{ + TEEC_Result res = TEEC_SUCCESS; + TEEC_UUID u = { }; + const char *p = s; + size_t i = 0; + + if (!p || strnlen(p, 37) != 36) + return TEEC_ERROR_BAD_FORMAT; + if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-') + return TEEC_ERROR_BAD_FORMAT; + + u.timeLow = parse_hex(p, 8, &res); + if (res) + goto out; + p += 9; + u.timeMid = parse_hex(p, 4, &res); + if (res) + goto out; + p += 5; + u.timeHiAndVersion = parse_hex(p, 4, &res); + if (res) + goto out; + p += 5; + for (i = 0; i < 8; i++) { + u.clockSeqAndNode[i] = parse_hex(p, 2, &res); + if (res) + goto out; + if (i == 1) + p += 3; + else + p += 2; + } + *uuid = u; +out: + return res; +} + +#define UUID_STR_LEN 37 + +char *xtest_uuid_to_allocated_str(const TEEC_UUID *uuid) +{ + char *s = NULL; + + s = malloc(UUID_STR_LEN); + if (!s) + return NULL; + + sprintf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid->timeLow, + uuid->timeMid, uuid->timeHiAndVersion, uuid->clockSeqAndNode[0], + uuid->clockSeqAndNode[1], uuid->clockSeqAndNode[2], + uuid->clockSeqAndNode[3], uuid->clockSeqAndNode[4], + uuid->clockSeqAndNode[5], uuid->clockSeqAndNode[6], + uuid->clockSeqAndNode[7]); + + return s; +} + +#ifdef OPENSSL_FOUND +TEEC_Result xtest_uuid_v5(TEEC_UUID *uuid, const TEEC_UUID *ns, + const void *name, size_t size) +{ + TEEC_Result res = TEEC_SUCCESS; + EVP_MD_CTX *mdctx = NULL; + const EVP_MD *md = NULL; + unsigned char hash[EVP_MAX_MD_SIZE] = { }; + unsigned int md_len = 0; + unsigned char nsbe[16] = { }; + uint32_t be32 = 0; + uint16_t be16 = 0; + int ret = 0; + + /* Convert from host to big endian */ + be32 = htobe32(ns->timeLow); + memcpy(&nsbe[0], &be32, sizeof(be32)); + be16 = htobe16(ns->timeMid); + memcpy(&nsbe[4], &be16, sizeof(be16)); + be16 = htobe16(ns->timeHiAndVersion); + memcpy(&nsbe[6], &be16, sizeof(be16)); + memcpy(&nsbe[8], &ns->clockSeqAndNode, sizeof(ns->clockSeqAndNode)); + + mdctx = EVP_MD_CTX_create(); + if (!mdctx) + return TEEC_ERROR_OUT_OF_MEMORY; + md = EVP_sha1(); + if (!md) { + res = TEEC_ERROR_NOT_SUPPORTED; + goto out; + } + ret = EVP_DigestInit_ex(mdctx, md, NULL); + if (!ret) { + res = TEEC_ERROR_GENERIC; + goto out; + } + ret = EVP_DigestUpdate(mdctx, nsbe, sizeof(nsbe)); + if (!ret) { + res = TEEC_ERROR_GENERIC; + goto out; + } + ret = EVP_DigestUpdate(mdctx, name, size); + if (!ret) { + res = TEEC_ERROR_GENERIC; + goto out; + } + ret = EVP_DigestFinal_ex(mdctx, hash, &md_len); + if (!ret) { + res = TEEC_ERROR_GENERIC; + goto out; + } + + /* Mark it as UUIDv5 */ + hash[6] = (hash[6] & 0x0F) | 0x50; + hash[8] = (hash[8] & 0x3F) | 0x80; + + /* Convert from big endian to host */ + memcpy(&be32, &hash[0], sizeof(uint32_t)); + uuid->timeLow = be32toh(be32); + memcpy(&be16, &hash[4], sizeof(uint16_t)); + uuid->timeMid = be16toh(be16); + memcpy(&be16, &hash[6], sizeof(uint16_t)); + uuid->timeHiAndVersion = be16toh(be16); + memcpy(uuid->clockSeqAndNode, &hash[8], sizeof(uuid->clockSeqAndNode)); +out: + EVP_MD_CTX_destroy(mdctx); + return res; +} +#endif /*OPENSSL_FOUND*/ diff --git a/optee/optee_test/host/xtest/xtest_uuid_helpers.h b/optee/optee_test/host/xtest/xtest_uuid_helpers.h new file mode 100644 index 0000000..505b55f --- /dev/null +++ b/optee/optee_test/host/xtest/xtest_uuid_helpers.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + */ + +#ifndef XTEST_UUID_HELPERS_H +#define XTEST_UUID_HELPERS_H + +#include +#include +#include + +/* + * Convert a UUID string @s into a TEEC_UUID @uuid + * Expected format for @s is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + * 'x' being any hexadecimal digit (0-9a-fA-F) + */ +TEEC_Result xtest_uuid_from_str(TEEC_UUID *uuid, const char *s); + +/* + * Convert a TEEC_UUID @uuid into an allocated UUID string @return + * Expected format for @return is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + * 'x' being any hexadecimal digit (0-9a-fA-F) + */ +char *xtest_uuid_to_allocated_str(const TEEC_UUID *uuid); + +#ifdef OPENSSL_FOUND +/* + * Form UUIDv5 from given name space and name. + */ +TEEC_Result xtest_uuid_v5(TEEC_UUID *uuid, const TEEC_UUID *ns, + const void *name, size_t size); +#endif /*OPENSSL_FOUND*/ +#endif diff --git a/optee/optee_test/scripts/checkpatch.sh b/optee/optee_test/scripts/checkpatch.sh new file mode 100755 index 0000000..505706d --- /dev/null +++ b/optee/optee_test/scripts/checkpatch.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +if [ -z "$OPTEE_OS_PATH" ]; then + OPTEE_OS_PATH="../optee_os"; +fi + +source $OPTEE_OS_PATH/scripts/checkpatch.sh "$@" diff --git a/optee/optee_test/scripts/common.mk b/optee/optee_test/scripts/common.mk new file mode 100644 index 0000000..fb5eb3e --- /dev/null +++ b/optee/optee_test/scripts/common.mk @@ -0,0 +1,11 @@ +# Makefile script used in various OP-TEE test components + +# Since 'clean' make rules rely on 'rmdir', removed directories shall +# not end with 'current directory' (./ or .) subpath information. +# This macro remove trailing './' info from input path. +define strip-trailing-slashes-and-dots +$(eval _o := $(patsubst %/,%,$(patsubst %/.,%,$(1))))$(if \ + $(filter-out $(1),$(_o)),$(call strip-trailing-slashes-and-dots,$(_o)),$(_o)) +endef + +PYTHON3 ?= python3 diff --git a/optee/optee_test/scripts/file_to_c.py b/optee/optee_test/scripts/file_to_c.py new file mode 100755 index 0000000..b4ce2a2 --- /dev/null +++ b/optee/optee_test/scripts/file_to_c.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2018, Linaro Limited +# + +def get_args(): + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('--name', required=True, + help='Name of variable in C file') + parser.add_argument('--out', required=True, help='Name of C file') + parser.add_argument('--inf', required=True, help='Name of in file') + + return parser.parse_args() + +def main(): + import array + + args = get_args() + + inf = open(args.inf, 'r') + f = open(args.out, 'w') + + f.write("/* automatically generated */\n") + f.write("#include \n") + f.write("#include \n\n") + + f.write("const uint8_t " + args.name + "[] = {\n") + i = 0 + for x in array.array("B", map(ord, (inf.read()))): + f.write("0x" + '{0:02x}'.format(x) + ",") + i = i + 1 + if i % 8 == 0: + f.write("\n") + else: + f.write(" ") + + f.write("'\\0'};\n") + f.write("const size_t " + args.name + "_size = sizeof(" + + args.name + ") - 1;\n") + + f.close() + inf.close() + +if __name__ == "__main__": + main() diff --git a/optee/optee_test/scripts/rsp_to_gcm_test.py b/optee/optee_test/scripts/rsp_to_gcm_test.py new file mode 100755 index 0000000..e4418be --- /dev/null +++ b/optee/optee_test/scripts/rsp_to_gcm_test.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +modes = {'encrypt': 0, 'decrypt': 1} + +limited = False + + +def to_compound_str(val): + assert len(val) % 2 == 0, "Only even sized values supported" + if len(val) > 0: + import re + a = re.findall('..', val) + b = "(const uint8_t []){" + for s in a: + b += "0x" + s + ", " + b += "}, " + repr(len(val) / 2) + "," + else: + b = "NULL, 0," + return b + + +def generate_case(outf, myvars, mode): + if 'PT' not in myvars: + myvars['PT'] = '' + if 'FAIL' in myvars: + return + if limited and myvars['Count'] != '0': + return + # Skip cases not supported by GP + if len(myvars['Tag']) / 2 < 96 / 8: + return + + outf.write('{ TEE_ALG_AES_GCM, ' + mode + ', TEE_TYPE_AES,\n') + outf.write('/* Key */ ' + to_compound_str(myvars['Key']) + '\n') + outf.write('/* IV */ ' + to_compound_str(myvars['IV']) + '\n') + outf.write('0,\n') + outf.write('/* AAD */ ' + to_compound_str(myvars['AAD']) + '\n') + outf.write('0,\n') + outf.write('/* PT */ ' + to_compound_str(myvars['PT']) + '\n') + outf.write('/* CT */ ' + to_compound_str(myvars['CT']) + '\n') + outf.write('/* Tag */ ' + to_compound_str(myvars['Tag']) + '\n') + outf.write(repr(myvars['Line']) + '},\n') + + +def get_args(): + import argparse + + parser = argparse.ArgumentParser() + + parser.add_argument('--inf', required=True, + type=argparse.FileType('r'), + help='Name of input RSP file') + + parser.add_argument('--outf', required=True, + type=argparse.FileType('w'), + help='Name of output C file') + + parser.add_argument('--mode', required=True, choices=modes.keys(), + help='mode: encrypt or decrypt') + + parser.add_argument('--limited', action="store_true", + help='Only run one test case from each group') + + return parser.parse_args() + + +def main(): + import re + global limited + args = get_args() + inf = args.inf + outf = args.outf + myvars = {} + line_num = 0 + + if args.mode == "encrypt": + mode = "TEE_MODE_ENCRYPT" + else: + mode = "TEE_MODE_DECRYPT" + + limited = args.limited + + for line in inf: + line_num += 1 + myl = line.strip() + if len(myl) == 0: + continue + if re.match('^#', myl): + continue + if re.match('^\[', myl): + continue + s = re.split('\W+', myl) + if len(s) == 0: + continue + name = s[0] + if name == 'Count': + if len(myvars) > 1: + generate_case(outf, myvars, mode) + myvars = {} + myvars['Line'] = line_num + + if len(s) < 2: + myvars[s[0]] = '' + else: + myvars[s[0]] = s[1] + + if len(s) < 2: + continue + val = s[1] + + if len(myvars) > 1: + generate_case(outf, myvars, mode) + + +if __name__ == "__main__": + main() diff --git a/optee/optee_test/ta/Android.mk b/optee/optee_test/ta/Android.mk new file mode 100644 index 0000000..5c069fe --- /dev/null +++ b/optee/optee_test/ta/Android.mk @@ -0,0 +1,2 @@ +LOCAL_PATH := $(call my-dir) +include $(call all-makefiles-under, $(LOCAL_PATH)) diff --git a/optee/optee_test/ta/CMakeLists.txt b/optee/optee_test/ta/CMakeLists.txt new file mode 100644 index 0000000..9301067 --- /dev/null +++ b/optee/optee_test/ta/CMakeLists.txt @@ -0,0 +1,28 @@ +project (xtest-ta-headers C) + +add_library(${PROJECT_NAME} INTERFACE) + +target_include_directories(${PROJECT_NAME} + INTERFACE include + INTERFACE aes_perf/include + INTERFACE concurrent/include + INTERFACE concurrent_large/include + INTERFACE create_fail_test/include + INTERFACE crypt/include + INTERFACE enc_fs/include + INTERFACE os_test/include + INTERFACE rpc_test/include + INTERFACE sdp_basic/include + INTERFACE hash_perf/include + INTERFACE sims/include + INTERFACE miss/include + INTERFACE sims_keepalive/include + INTERFACE socket/include + INTERFACE storage_benchmark/include + INTERFACE tpm_log_test/include + INTERFACE bti_test/include + INTERFACE supp_plugin/include + INTERFACE large/include + INTERFACE subkey1/include + INTERFACE subkey2/include +) diff --git a/optee/optee_test/ta/Makefile b/optee/optee_test/ta/Makefile new file mode 100644 index 0000000..33ed949 --- /dev/null +++ b/optee/optee_test/ta/Makefile @@ -0,0 +1,64 @@ +# Normally this makefile shouldn't be called directly and we expect the output +# path to be on a certain location to fit together with the other OP-TEE +# gits and helper scripts. + +include ../scripts/common.mk +out-dir := $(call strip-trailing-slashes-and-dots,$(O)) +ifeq ($(out-dir),) +$(error invalid output directory (O=$(O))) +endif + +include $(TA_DEV_KIT_DIR)/mk/conf.mk + +# Prevent use of LDFLAGS from the environment. For example, yocto exports +# LDFLAGS that are suitable for the client applications, not for TAs +LDFLAGS= + +TA_DIRS := create_fail_test \ + crypt \ + os_test_lib \ + os_test_lib_dl \ + os_test \ + rpc_test \ + sims \ + miss \ + sims_keepalive \ + storage \ + storage2 \ + concurrent \ + concurrent_large \ + storage_benchmark \ + hash_perf \ + aes_perf \ + socket \ + supp_plugin \ + large \ + subkey1 \ + subkey2 + +ifeq ($(CFG_SECURE_DATA_PATH),y) +TA_DIRS += sdp_basic +endif + +ifeq ($(CFG_TA_BTI),y) +TA_DIRS += bti_test +endif + +.PHONY: all +all: ta + +.PHONY: ta +ta: + $(q)$(foreach dir,$(TA_DIRS), $(MAKE) -C $(dir) O=$(out-dir)/ta/$(dir) &&) true + +# remove build directories including ta// directories. +# Note: $(out-dir) may be a relative path. +RMDIR := rmdir --ignore-fail-on-non-empty +define rm-build-subdir +echo `[ -d $1 ] && { cd $1; $(RMDIR) $(out-dir)/ta $(out-dir) 2> /dev/null; true; }` > /dev/null +endef + +.PHONY: clean +clean: + $(q)$(foreach dir,$(TA_DIRS), [ ! -d $(dir) ] || $(MAKE) -C $(dir) O=$(out-dir)/ta/$(dir) $@ &&) true + $(q)$(foreach dir,$(TA_DIRS), $(call rm-build-subdir,$(dir));) diff --git a/optee/optee_test/ta/aes_perf/Android.mk b/optee/optee_test/ta/aes_perf/Android.mk new file mode 100644 index 0000000..8fc8de6 --- /dev/null +++ b/optee/optee_test/ta/aes_perf/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := e626662e-c0e2-485c-b8c8-09fbce6edf3d.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/aes_perf/Makefile b/optee/optee_test/ta/aes_perf/Makefile new file mode 100644 index 0000000..4038866 --- /dev/null +++ b/optee/optee_test/ta/aes_perf/Makefile @@ -0,0 +1,4 @@ +BINARY = e626662e-c0e2-485c-b8c8-09fbce6edf3d + +include ../ta_common.mk + diff --git a/optee/optee_test/ta/aes_perf/include/ta_aes_perf.h b/optee/optee_test/ta/aes_perf/include/ta_aes_perf.h new file mode 100644 index 0000000..997d840 --- /dev/null +++ b/optee/optee_test/ta/aes_perf/include/ta_aes_perf.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_AES_PERF_H +#define TA_AES_PERF_H + +#define TA_AES_PERF_UUID { 0xe626662e, 0xc0e2, 0x485c, \ + { 0xb8, 0xc8, 0x09, 0xfb, 0xce, 0x6e, 0xdf, 0x3d } } + +/* + * Commands implemented by the TA + */ + +#define TA_AES_PERF_CMD_PREPARE_KEY 0 +#define TA_AES_PERF_CMD_PROCESS 1 +#define TA_AES_PERF_CMD_PROCESS_SDP 2 + +/* + * Supported AES modes of operation + */ + +#define TA_AES_ECB 0 +#define TA_AES_CBC 1 +#define TA_AES_CTR 2 +#define TA_AES_XTS 3 +#define TA_AES_GCM 4 + +/* + * AES key sizes + */ +#define AES_128 128 +#define AES_192 192 +#define AES_256 256 + +#endif /* TA_AES_PERF_H */ diff --git a/optee/optee_test/ta/aes_perf/include/ta_aes_perf_priv.h b/optee/optee_test/ta/aes_perf/include/ta_aes_perf_priv.h new file mode 100644 index 0000000..1d144c3 --- /dev/null +++ b/optee/optee_test/ta/aes_perf/include/ta_aes_perf_priv.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_EAS_PERF_PRIV_H +#define TA_EAS_PERF_PRIV_H + +#include + +TEE_Result cmd_prepare_key(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_process(uint32_t param_types, TEE_Param params[4], bool sdp); +void cmd_clean_res(void); + +#endif /* TA_EAS_PERF_PRIV_H */ diff --git a/optee/optee_test/ta/aes_perf/include/user_ta_header_defines.h b/optee/optee_test/ta/aes_perf/include/user_ta_header_defines.h new file mode 100644 index 0000000..f84858f --- /dev/null +++ b/optee/optee_test/ta/aes_perf/include/user_ta_header_defines.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include "ta_aes_perf.h" + +#define TA_UUID TA_AES_PERF_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \ + TA_FLAG_SECURE_DATA_PATH | \ + TA_FLAG_CACHE_MAINTENANCE) + +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif diff --git a/optee/optee_test/ta/aes_perf/sub.mk b/optee/optee_test/ta/aes_perf/sub.mk new file mode 100644 index 0000000..8553db6 --- /dev/null +++ b/optee/optee_test/ta/aes_perf/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +srcs-y += ta_entry.c +srcs-y += ta_aes_perf.c diff --git a/optee/optee_test/ta/aes_perf/ta_aes_perf.c b/optee/optee_test/ta/aes_perf/ta_aes_perf.c new file mode 100644 index 0000000..b16d070 --- /dev/null +++ b/optee/optee_test/ta/aes_perf/ta_aes_perf.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "ta_aes_perf.h" +#include "ta_aes_perf_priv.h" + +#define CHECK(res, name, action) do { \ + if ((res) != TEE_SUCCESS) { \ + DMSG(name ": 0x%08x", (res)); \ + action \ + } \ + } while(0) + +#define TAG_LEN 128 + +static uint8_t iv[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF }; +static int use_iv; + +static TEE_OperationHandle crypto_op = NULL; +static uint32_t algo; + +static bool is_inbuf_a_secure_memref(TEE_Param *param) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* + * Check secure attribute for the referenced buffer + * Trust core on validity of the memref size: test only 1st byte + * instead of the overall buffer, and if it's not secure, assume + * the buffer is nonsecure. + */ + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER | + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_SECURE, + param->memref.buffer, 1); + return (res == TEE_SUCCESS); +} + +static bool is_outbuf_a_secure_memref(TEE_Param *param) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + /* + * Check secure attribute for the referenced buffer + * Trust core on validity of the memref size: test only 1st byte + * instead of the overall buffer, and if it's not secure, assume + * the buffer is nonsecure. + */ + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_SECURE, + param->memref.buffer, 1); + return (res == TEE_SUCCESS); +} + +#if defined(CFG_CACHE_API) +static TEE_Result flush_memref_buffer(TEE_Param *param) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + res = TEE_CacheFlush(param->memref.buffer, + param->memref.size); + CHECK(res, "TEE_CacheFlush(in)", return res;); + return res; +} +#else +static __maybe_unused TEE_Result flush_memref_buffer(TEE_Param *param __unused) +{ + return TEE_SUCCESS; +} +#endif /* CFG_CACHE_API */ + +TEE_Result cmd_process(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + bool use_sdp) +{ + TEE_Result res = TEE_ERROR_GENERIC; + int n = 0; + int unit = 0; + void *in = NULL; + void *out = NULL; + size_t insz = 0; + size_t outsz = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE); + bool secure_in = false; + bool secure_out = false; + TEE_Result (*do_update)(TEE_OperationHandle, const void *, size_t, + void *, size_t *) = NULL; + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if (use_sdp) { + /* + * Whatever is expected as memory reference, it is mandatory + * for SDP aware trusted applications of safely indentify all + * memory reference parameters. Hence these tests must be part + * of the performance test setup. + */ + secure_in = is_inbuf_a_secure_memref(¶ms[0]); + secure_out = is_outbuf_a_secure_memref(¶ms[1]); + + /* + * We could invalidate only the caches. We prefer to flush + * them in case 2 sub-buffers are accessed by TAs from a single + * allocated SDP memory buffer, and those are not cache-aligned. + * Invalidating might cause data loss in cache lines. Hence + * rather flush them all before accessing (in read or write). + */ + if (secure_in) { + res = flush_memref_buffer(¶ms[0]); + CHECK(res, "pre-flush in memref param", return res;); + } + if (secure_out) { + res = flush_memref_buffer(¶ms[1]); + CHECK(res, "pre-flush out memref param", return res;); + } + } + + in = params[0].memref.buffer; + insz = params[0].memref.size; + out = params[1].memref.buffer; + outsz = params[1].memref.size; + n = params[2].value.a; + unit = params[2].value.b; + if (!unit) + unit = insz; + + if (algo == TEE_ALG_AES_GCM) + do_update = TEE_AEUpdate; + else + do_update = TEE_CipherUpdate; + + while (n--) { + uint32_t i = 0; + for (i = 0; i < insz / unit; i++) { + res = do_update(crypto_op, in, unit, out, &outsz); + CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;); + in = (void *)((uintptr_t)in + unit); + out = (void *)((uintptr_t)out + unit); + } + if (insz % unit) { + res = do_update(crypto_op, in, insz % unit, out, &outsz); + CHECK(res, "TEE_CipherUpdate/TEE_AEUpdate", return res;); + } + } + + if (secure_out) { + /* intentionally flush output data from cache for SDP buffers */ + res = flush_memref_buffer(¶ms[1]); + CHECK(res, "post-flush out memref param", return res;); + } + + return TEE_SUCCESS; +} + +TEE_Result cmd_prepare_key(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle hkey = TEE_HANDLE_NULL; + TEE_ObjectHandle hkey2 = TEE_HANDLE_NULL; + TEE_Attribute attr = { }; + uint32_t mode = 0; + uint32_t op_keysize = 0; + uint32_t keysize = 0; + const uint8_t *ivp = NULL; + size_t ivlen = 0; + static uint8_t aes_key[] = { 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 }; + static uint8_t aes_key2[] = { 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 }; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + mode = params[0].value.a ? TEE_MODE_DECRYPT : TEE_MODE_ENCRYPT; + keysize = params[0].value.b; + op_keysize = keysize; + + switch (params[1].value.a) { + case TA_AES_ECB: + algo = TEE_ALG_AES_ECB_NOPAD; + use_iv = 0; + break; + case TA_AES_CBC: + algo = TEE_ALG_AES_CBC_NOPAD; + use_iv = 1; + break; + case TA_AES_CTR: + algo = TEE_ALG_AES_CTR; + use_iv = 1; + break; + case TA_AES_XTS: + algo = TEE_ALG_AES_XTS; + use_iv = 1; + op_keysize *= 2; + break; + case TA_AES_GCM: + algo = TEE_ALG_AES_GCM; + use_iv = 1; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + cmd_clean_res(); + + res = TEE_AllocateOperation(&crypto_op, algo, mode, op_keysize); + CHECK(res, "TEE_AllocateOperation", return res;); + + res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize, &hkey); + CHECK(res, "TEE_AllocateTransientObject", return res;); + + attr.attributeID = TEE_ATTR_SECRET_VALUE; + attr.content.ref.buffer = aes_key; + attr.content.ref.length = keysize / 8; + + res = TEE_PopulateTransientObject(hkey, &attr, 1); + CHECK(res, "TEE_PopulateTransientObject", return res;); + + if (algo == TEE_ALG_AES_XTS) { + res = TEE_AllocateTransientObject(TEE_TYPE_AES, keysize, + &hkey2); + CHECK(res, "TEE_AllocateTransientObject", return res;); + + attr.content.ref.buffer = aes_key2; + + res = TEE_PopulateTransientObject(hkey2, &attr, 1); + CHECK(res, "TEE_PopulateTransientObject", return res;); + + res = TEE_SetOperationKey2(crypto_op, hkey, hkey2); + CHECK(res, "TEE_SetOperationKey2", return res;); + + TEE_FreeTransientObject(hkey2); + } else { + res = TEE_SetOperationKey(crypto_op, hkey); + CHECK(res, "TEE_SetOperationKey", return res;); + } + + TEE_FreeTransientObject(hkey); + + if (use_iv) { + ivp = iv; + ivlen = sizeof(iv); + } else { + ivp = NULL; + ivlen = 0; + } + + if (algo == TEE_ALG_AES_GCM) { + return TEE_AEInit(crypto_op, ivp, ivlen, TAG_LEN, 0, 0); + } else { + TEE_CipherInit(crypto_op, ivp, ivlen); + return TEE_SUCCESS; + } +} + +void cmd_clean_res(void) +{ + if (crypto_op) + TEE_FreeOperation(crypto_op); +} diff --git a/optee/optee_test/ta/aes_perf/ta_entry.c b/optee/optee_test/ta/aes_perf/ta_entry.c new file mode 100644 index 0000000..be3ceef --- /dev/null +++ b/optee/optee_test/ta/aes_perf/ta_entry.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include +#include + +#include "ta_aes_perf.h" +#include "ta_aes_perf_priv.h" + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; + + cmd_clean_res(); +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + (void)pSessionContext; + + switch (nCommandID) { + case TA_AES_PERF_CMD_PREPARE_KEY: + return cmd_prepare_key(nParamTypes, pParams); + + case TA_AES_PERF_CMD_PROCESS: + return cmd_process(nParamTypes, pParams, false); + case TA_AES_PERF_CMD_PROCESS_SDP: +#ifdef CFG_SECURE_DATA_PATH + return cmd_process(nParamTypes, pParams, true); +#else + EMSG("Invalid SDP commands: TA was built without SDP support"); + return TEE_ERROR_NOT_SUPPORTED; +#endif + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/bti_test/Android.mk b/optee/optee_test/ta/bti_test/Android.mk new file mode 100644 index 0000000..6e04d4c --- /dev/null +++ b/optee/optee_test/ta/bti_test/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 3616069b-504d-4044-9497-feb84a073a14 +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/bti_test/Makefile b/optee/optee_test/ta/bti_test/Makefile new file mode 100644 index 0000000..0c68758 --- /dev/null +++ b/optee/optee_test/ta/bti_test/Makefile @@ -0,0 +1,2 @@ +BINARY = 3616069b-504d-4044-9497-feb84a073a14 +include ../ta_common.mk diff --git a/optee/optee_test/ta/bti_test/bti_stubs_a64.S b/optee/optee_test/ta/bti_test/bti_stubs_a64.S new file mode 100644 index 0000000..376a1f6 --- /dev/null +++ b/optee/optee_test/ta/bti_test/bti_stubs_a64.S @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include + +FUNC call_using_blr , : , , , no_bti + bti c + stp x29, x30, [sp, #-16]! + blr x0 + ldp x29, x30, [sp], #16 + ret +END_FUNC call_using_blr + +FUNC call_using_br , : , , , no_bti + bti c + br x0 +END_FUNC call_using_br + +FUNC call_using_br_x16 , : , , , no_bti + bti c + mov x16, x0 + br x16 +END_FUNC call_using_br_x16 + +FUNC bti_j , : , , , no_bti + bti j + ret +END_FUNC bti_j + +FUNC bti_c , : , , , no_bti + bti c + ret +END_FUNC bti_c + +FUNC bti_jc , : , , , no_bti + bti jc + ret +END_FUNC bti_jc + +FUNC bti_none , : , , , no_bti + ret +END_FUNC bti_none + +emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI diff --git a/optee/optee_test/ta/bti_test/include/ta_arm_bti.h b/optee/optee_test/ta/bti_test/include/ta_arm_bti.h new file mode 100644 index 0000000..6af21d0 --- /dev/null +++ b/optee/optee_test/ta/bti_test/include/ta_arm_bti.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_ARM_BTI_H +#define TA_ARM_BTI_H + +#define TA_BTI_UUID { 0x3616069b, 0x504d, 0x4044, \ + { 0x94, 0x97, 0xfe, 0xb8, 0x4a, 0x07, 0x3a, 0x14} } + +/* + * Commands implemented by the TA + */ +#define TA_TEST_USING_BLR 0 +#define TA_TEST_USING_BR 1 +#define TA_TEST_USING_BR_X16 2 +#define TA_FEAT_BTI_IMPLEMENTED 3 + +/* + * Parameter values + */ +#define TA_FUNC_BTI_C 0 +#define TA_FUNC_BTI_J 1 +#define TA_FUNC_BTI_JC 2 +#define TA_FUNC_BTI_NONE 3 + +#endif /* TA_ARM_BTI_H */ diff --git a/optee/optee_test/ta/bti_test/include/ta_arm_bti_priv.h b/optee/optee_test/ta/bti_test/include/ta_arm_bti_priv.h new file mode 100644 index 0000000..4638ccd --- /dev/null +++ b/optee/optee_test/ta/bti_test/include/ta_arm_bti_priv.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_ARM_BTI_PRIVATE_H +#define TA_ARM_BTI_PRIVATE_H + +#include + +TEE_Result test_bti(uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]); + +#endif /* TA_ARM_BTI_PRIVATE_H */ diff --git a/optee/optee_test/ta/bti_test/include/user_ta_header_defines.h b/optee/optee_test/ta/bti_test/include/user_ta_header_defines.h new file mode 100644 index 0000000..9fb2f54 --- /dev/null +++ b/optee/optee_test/ta/bti_test/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include "ta_arm_bti.h" + +#define TA_UUID TA_BTI_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif diff --git a/optee/optee_test/ta/bti_test/sub.mk b/optee/optee_test/ta/bti_test/sub.mk new file mode 100644 index 0000000..48be924 --- /dev/null +++ b/optee/optee_test/ta/bti_test/sub.mk @@ -0,0 +1,7 @@ +global-incdirs-y += include + +srcs-y += ta_entry.c +ifeq ($(sm),ta_arm64) +srcs-$(CFG_TA_BTI) += bti_stubs_a64.S +srcs-$(CFG_TA_BTI) += ta_arm_bti.c +endif diff --git a/optee/optee_test/ta/bti_test/ta_arm_bti.c b/optee/optee_test/ta/bti_test/ta_arm_bti.c new file mode 100644 index 0000000..668b64a --- /dev/null +++ b/optee/optee_test/ta/bti_test/ta_arm_bti.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include + +void call_using_blr(void (*)(void)); +void call_using_br(void (*)(void)); +void call_using_br_x16(void (*)(void)); +void bti_j(void); +void bti_c(void); +void bti_jc(void); +void bti_none(void); + +TEE_Result test_bti(uint32_t nCommandID, uint32_t nParamTypes, TEE_Param pParams[4]) +{ + void (*func)(void) = NULL; + + if (nParamTypes != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0)) + return TEE_ERROR_GENERIC; + + switch (pParams[0].value.a) { + case TA_FUNC_BTI_C: + func = bti_c; + break; + case TA_FUNC_BTI_J: + func = bti_j; + break; + case TA_FUNC_BTI_JC: + func = bti_jc; + break; + case TA_FUNC_BTI_NONE: + func = bti_none; + break; + default: + break; + } + + switch (nCommandID) { + case TA_TEST_USING_BLR : + call_using_blr(func); + break; + case TA_TEST_USING_BR : + call_using_br(func); + break; + case TA_TEST_USING_BR_X16 : + call_using_br_x16(func); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/bti_test/ta_entry.c b/optee/optee_test/ta/bti_test/ta_entry.c new file mode 100644 index 0000000..5a4f66f --- /dev/null +++ b/optee/optee_test/ta/bti_test/ta_entry.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes __unused, + TEE_Param pParams[4] __unused, + void **ppSessionContext __unused) +{ + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext __unused) +{ +} + +static TEE_Result check_bti_implemented(uint32_t param_types, + TEE_Param params[4]) +{ + bool implemented = false; + TEE_Result res = TEE_ERROR_GENERIC; + + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + res = TEE_GetPropertyAsBool( + TEE_PROPSET_TEE_IMPLEMENTATION, + "org.trustedfirmware.optee.cpu.feat_bti_implemented", + &implemented); + if (res == TEE_SUCCESS && implemented) + params[0].value.a = 1; + + if (res == TEE_ERROR_ITEM_NOT_FOUND) { + params[0].value.a = 0; + res = TEE_SUCCESS; + } + + return res; +} + +__weak TEE_Result test_bti(uint32_t nCommandID __unused, + uint32_t nParamTypes __unused, + TEE_Param pParams[4] __unused) +{ + return TEE_ERROR_NOT_IMPLEMENTED; +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext __unused, + uint32_t nCommandID, + uint32_t nParamTypes, + TEE_Param pParams[4] ) +{ + TEE_Result res = TEE_SUCCESS; + + switch (nCommandID) { + case TA_TEST_USING_BLR : + case TA_TEST_USING_BR : + case TA_TEST_USING_BR_X16 : + res = test_bti(nCommandID, nParamTypes, pParams); + break; + case TA_FEAT_BTI_IMPLEMENTED : + res = check_bti_implemented(nParamTypes, pParams); + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + return res; +} diff --git a/optee/optee_test/ta/concurrent/Android.mk b/optee/optee_test/ta/concurrent/Android.mk new file mode 100644 index 0000000..06cc783 --- /dev/null +++ b/optee/optee_test/ta/concurrent/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := e13010e0-2ae1-11e5-896a-0002a5d5c51b.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/concurrent/Makefile b/optee/optee_test/ta/concurrent/Makefile new file mode 100644 index 0000000..42eb54e --- /dev/null +++ b/optee/optee_test/ta/concurrent/Makefile @@ -0,0 +1,2 @@ +BINARY = e13010e0-2ae1-11e5-896a-0002a5d5c51b +include ../ta_common.mk diff --git a/optee/optee_test/ta/concurrent/include/ta_concurrent.h b/optee/optee_test/ta/concurrent/include/ta_concurrent.h new file mode 100644 index 0000000..44e8fe3 --- /dev/null +++ b/optee/optee_test/ta/concurrent/include/ta_concurrent.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_CONCURRENT_H +#define TA_CONCURRENT_H + +/* This UUID is generated with the ITU-T UUID generator at + http://www.itu.int/ITU-T/asn1/uuid.html */ +#define TA_CONCURRENT_UUID { 0xe13010e0, 0x2ae1, 0x11e5, \ + { 0x89, 0x6a, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } } + +struct ta_concurrent_shm { + uint32_t active_count; +}; + +/* + * Busy loops and updates max concurrency. params[0].memref should contain + * a struct ta_concurent_shm which can be used to tell how many instances + * of this function is running in parallel. + * + * in/out params[0].memref + * in/out params[1].value.a (input) number times to calcule the hash + * in/out params[1].value.b (output) max concurency + */ + +#define TA_CONCURRENT_CMD_BUSY_LOOP 0 + +/* + * Calculates a sha-256 hash over param[2].memref and stores the result in + * params[3].memref. params[0].memref should contain a struct + * ta_concurent_shm which can be used to tell how many instances of this + * function is running in parallel. + * + * in/out params[0].memref + * in/out params[1].value.a (input) number times to calcule the hash + * in/out params[1].value.b (output) max concurency + * in params[2].memref + * out params[3].memref + */ +#define TA_CONCURRENT_CMD_SHA256 1 + +#endif /*TA_OS_TEST_H */ diff --git a/optee/optee_test/ta/concurrent/include/user_ta_header_defines.h b/optee/optee_test/ta/concurrent/include/user_ta_header_defines.h new file mode 100644 index 0000000..3cf164e --- /dev/null +++ b/optee/optee_test/ta/concurrent/include/user_ta_header_defines.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include + +#define TA_UUID TA_CONCURRENT_UUID + +#define TA_FLAGS ( TA_FLAG_EXEC_DDR | TA_FLAG_MULTI_SESSION) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_test/ta/concurrent/sub.mk b/optee/optee_test/ta/concurrent/sub.mk new file mode 100644 index 0000000..d5e3f32 --- /dev/null +++ b/optee/optee_test/ta/concurrent/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/concurrent/ta_entry.c b/optee/optee_test/ta/concurrent/ta_entry.c new file mode 100644 index 0000000..aa8a286 --- /dev/null +++ b/optee/optee_test/ta/concurrent/ta_entry.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types, + TEE_Param params[4], + void **session_ctx) +{ + (void)param_types; + (void)params; + (void)session_ctx; + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *session_ctx) +{ + (void)session_ctx; +} + +static uint32_t inc_active_count(struct ta_concurrent_shm *shm) +{ + return atomic_inc32(&shm->active_count); +} + +static uint32_t dec_active_count(struct ta_concurrent_shm *shm) +{ + return atomic_dec32(&shm->active_count); +} + +static TEE_Result ta_entry_busy_loop(uint32_t param_types, TEE_Param params[4]) +{ + size_t num_rounds = 0; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size < sizeof(struct ta_concurrent_shm)) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.b = inc_active_count(params[0].memref.buffer); + + num_rounds = params[1].value.a; + while (num_rounds) { + volatile size_t n = 1000; + + while (n) + n--; + + num_rounds--; + } + + dec_active_count(params[0].memref.buffer); + return TEE_SUCCESS; +} + +static TEE_Result ta_entry_sha256(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle op = TEE_HANDLE_NULL; + void *out = NULL; + size_t out_len = 0; + size_t num_rounds = 0; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size < sizeof(struct ta_concurrent_shm)) + return TEE_ERROR_BAD_PARAMETERS; + if (params[3].memref.size < TEE_SHA256_HASH_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.b = inc_active_count(params[0].memref.buffer); + + out_len = params[3].memref.size; + out = TEE_Malloc(out_len, 0); + if (!out) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); + if (res != TEE_SUCCESS) + goto out; + + + num_rounds = params[1].value.a; + while (num_rounds) { + TEE_ResetOperation(op); + res = TEE_DigestDoFinal(op, params[2].memref.buffer, + params[2].memref.size, out, &out_len); + num_rounds--; + } + + TEE_MemMove(params[3].memref.buffer, out, out_len); + params[3].memref.size = out_len; + +out: + if (out) + TEE_Free(out); + if (op) + TEE_FreeOperation(op); + dec_active_count(params[0].memref.buffer); + return res; +} + +TEE_Result TA_InvokeCommandEntryPoint(void *session_ctx, + uint32_t cmd_id, uint32_t param_types, + TEE_Param params[4]) +{ + (void)session_ctx; + + switch (cmd_id) { + case TA_CONCURRENT_CMD_BUSY_LOOP: + return ta_entry_busy_loop(param_types, params); + case TA_CONCURRENT_CMD_SHA256: + return ta_entry_sha256(param_types, params); + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/concurrent_large/Android.mk b/optee/optee_test/ta/concurrent_large/Android.mk new file mode 100644 index 0000000..029306a --- /dev/null +++ b/optee/optee_test/ta/concurrent_large/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 5ce0c432-0ab0-40e5-a056-782ca0e6aba2.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/concurrent_large/Makefile b/optee/optee_test/ta/concurrent_large/Makefile new file mode 100644 index 0000000..c3fda13 --- /dev/null +++ b/optee/optee_test/ta/concurrent_large/Makefile @@ -0,0 +1,2 @@ +BINARY = 5ce0c432-0ab0-40e5-a056-782ca0e6aba2 +include ../ta_common.mk diff --git a/optee/optee_test/ta/concurrent_large/include/ta_concurrent_large.h b/optee/optee_test/ta/concurrent_large/include/ta_concurrent_large.h new file mode 100644 index 0000000..e740267 --- /dev/null +++ b/optee/optee_test/ta/concurrent_large/include/ta_concurrent_large.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_CONCURRENT_LARGE_H +#define TA_CONCURRENT_LARGE_H + +#include + +/* 5ce0c432-0ab0-40e5-a056-782ca0e6aba2 */ +#define TA_CONCURRENT_LARGE_UUID { 0x5ce0c432, 0x0ab0, 0x40e5, \ + { 0xa0,0x56, 0x78, 0x2c, 0xa0, 0xe6, 0xab, 0xa2 } } + +#endif /*TA_CONCURRENT_LARGE_H */ diff --git a/optee/optee_test/ta/concurrent_large/include/user_ta_header_defines.h b/optee/optee_test/ta/concurrent_large/include/user_ta_header_defines.h new file mode 100644 index 0000000..f914acd --- /dev/null +++ b/optee/optee_test/ta/concurrent_large/include/user_ta_header_defines.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include + +#define TA_UUID TA_CONCURRENT_LARGE_UUID + +#define TA_FLAGS ( TA_FLAG_EXEC_DDR | TA_FLAG_MULTI_SESSION) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (2 * 1024 * 1024) + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_test/ta/concurrent_large/sub.mk b/optee/optee_test/ta/concurrent_large/sub.mk new file mode 100644 index 0000000..cabd18e --- /dev/null +++ b/optee/optee_test/ta/concurrent_large/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +global-incdirs-y += ../concurrent/include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/concurrent_large/ta_entry.c b/optee/optee_test/ta/concurrent_large/ta_entry.c new file mode 100644 index 0000000..2be5b9e --- /dev/null +++ b/optee/optee_test/ta/concurrent_large/ta_entry.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015-2016, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types, + TEE_Param params[4], + void **session_ctx) +{ + (void)param_types; + (void)params; + (void)session_ctx; + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *session_ctx) +{ + (void)session_ctx; +} + +static uint32_t inc_active_count(struct ta_concurrent_shm *shm) +{ + return atomic_inc32(&shm->active_count); +} + +static uint32_t dec_active_count(struct ta_concurrent_shm *shm) +{ + return atomic_dec32(&shm->active_count); +} + +static TEE_Result ta_entry_busy_loop(uint32_t param_types, TEE_Param params[4]) +{ + size_t num_rounds = 0; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size < sizeof(struct ta_concurrent_shm)) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.b = inc_active_count(params[0].memref.buffer); + + num_rounds = params[1].value.a; + while (num_rounds) { + volatile size_t n = 1000; + + while (n) + n--; + + num_rounds--; + } + + dec_active_count(params[0].memref.buffer); + return TEE_SUCCESS; +} + +static TEE_Result ta_entry_sha256(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle op = TEE_HANDLE_NULL; + void *out = NULL; + size_t out_len = 0; + size_t num_rounds = 0; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size < sizeof(struct ta_concurrent_shm)) + return TEE_ERROR_BAD_PARAMETERS; + if (params[3].memref.size < TEE_SHA256_HASH_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.b = inc_active_count(params[0].memref.buffer); + + out_len = params[3].memref.size; + out = TEE_Malloc(out_len, 0); + if (!out) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); + if (res != TEE_SUCCESS) + goto out; + + + num_rounds = params[1].value.a; + while (num_rounds) { + TEE_ResetOperation(op); + res = TEE_DigestDoFinal(op, params[2].memref.buffer, + params[2].memref.size, out, &out_len); + num_rounds--; + } + + TEE_MemMove(params[3].memref.buffer, out, out_len); + params[3].memref.size = out_len; + +out: + if (out) + TEE_Free(out); + if (op) + TEE_FreeOperation(op); + dec_active_count(params[0].memref.buffer); + return res; +} + +TEE_Result TA_InvokeCommandEntryPoint(void *session_ctx, + uint32_t cmd_id, uint32_t param_types, + TEE_Param params[4]) +{ + (void)session_ctx; + + switch (cmd_id) { + case TA_CONCURRENT_CMD_BUSY_LOOP: + return ta_entry_busy_loop(param_types, params); + case TA_CONCURRENT_CMD_SHA256: + return ta_entry_sha256(param_types, params); + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/create_fail_test/Android.mk b/optee/optee_test/ta/create_fail_test/Android.mk new file mode 100644 index 0000000..c0c6bba --- /dev/null +++ b/optee/optee_test/ta/create_fail_test/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := c3f6e2c0-3548-11e1-b86c-0800200c9a66.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/create_fail_test/Makefile b/optee/optee_test/ta/create_fail_test/Makefile new file mode 100644 index 0000000..1df9e2c --- /dev/null +++ b/optee/optee_test/ta/create_fail_test/Makefile @@ -0,0 +1,2 @@ +BINARY = c3f6e2c0-3548-11e1-b86c-0800200c9a66 +include ../ta_common.mk diff --git a/optee/optee_test/ta/create_fail_test/include/ta_create_fail_test.h b/optee/optee_test/ta/create_fail_test/include/ta_create_fail_test.h new file mode 100644 index 0000000..f1d6b0d --- /dev/null +++ b/optee/optee_test/ta/create_fail_test/include/ta_create_fail_test.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef TA_CREATE_FAIL_TEST_H +#define TA_CREATE_FAIL_TEST_H + +/* This UUID is generated with the ITU-T UUID generator at + http://www.itu.int/ITU-T/asn1/uuid.html */ +#define TA_CREATE_FAIL_TEST_UUID { 0xc3f6e2c0, 0x3548, 0x11e1, \ + { 0xb8, 0x6c, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } } + +#endif /*TA_CREATE_FAIL_TEST_H */ diff --git a/optee/optee_test/ta/create_fail_test/include/user_ta_header_defines.h b/optee/optee_test/ta/create_fail_test/include/user_ta_header_defines.h new file mode 100644 index 0000000..f88b4ea --- /dev/null +++ b/optee/optee_test/ta/create_fail_test/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_CREATE_FAIL_TEST_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR) +#define TA_STACK_SIZE (1 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/create_fail_test/sub.mk b/optee/optee_test/ta/create_fail_test/sub.mk new file mode 100644 index 0000000..d5e3f32 --- /dev/null +++ b/optee/optee_test/ta/create_fail_test/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/create_fail_test/ta_entry.c b/optee/optee_test/ta/create_fail_test/ta_entry.c new file mode 100644 index 0000000..f9ed7d7 --- /dev/null +++ b/optee/optee_test/ta/create_fail_test/ta_entry.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include +#include + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_ERROR_GENERIC; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, + uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + (void)pSessionContext; + (void)nCommandID; + (void)nParamTypes; + (void)pParams; + return TEE_ERROR_NOT_SUPPORTED; +} diff --git a/optee/optee_test/ta/crypt/Android.mk b/optee/optee_test/ta/crypt/Android.mk new file mode 100644 index 0000000..bc9e445 --- /dev/null +++ b/optee/optee_test/ta/crypt/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := cb3e5ba0-adf1-11e0-998b-0002a5d5c51b.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/crypt/Makefile b/optee/optee_test/ta/crypt/Makefile new file mode 100644 index 0000000..383c6d5 --- /dev/null +++ b/optee/optee_test/ta/crypt/Makefile @@ -0,0 +1,2 @@ +BINARY = cb3e5ba0-adf1-11e0-998b-0002a5d5c51b +include ../ta_common.mk diff --git a/optee/optee_test/ta/crypt/aes_impl.c b/optee/optee_test/ta/crypt/aes_impl.c new file mode 100644 index 0000000..90ffb66 --- /dev/null +++ b/optee/optee_test/ta/crypt/aes_impl.c @@ -0,0 +1,1249 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +/* #define FULL_UNROLL */ + +#include "aes_impl.h" + +typedef unsigned long u32; +typedef unsigned char u8; + +static const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; + +static const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; + +static const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; + +static const u32 Te3[256] = { + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; + +static const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; + +static const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; + +static const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; + +static const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; + +static const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; + +static const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; + +static const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, +/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +#define GETU32(plaintext) (((u32)(plaintext)[0] << 24) ^ \ + ((u32)(plaintext)[1] << 16) ^ \ + ((u32)(plaintext)[2] << 8) ^ \ + ((u32)(plaintext)[3])) + +#define PUTU32(ciphertext, st) { (ciphertext)[0] = (u8)((st) >> 24); \ + (ciphertext)[1] = (u8)((st) >> 16); \ + (ciphertext)[2] = (u8)((st) >> 8); \ + (ciphertext)[3] = (u8)(st); } + +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int rijndaelSetupEncrypt(u32 *rk, const u8 *key, int keybits) +{ + int i = 0; + u32 temp = 0; + + rk[0] = GETU32(key); + rk[1] = GETU32(key + 4); + rk[2] = GETU32(key + 8); + rk[3] = GETU32(key + 12); + if (keybits == 128) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24)] & 0x000000ff) ^ rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) + return 10; + rk += 4; + } + } + rk[4] = GETU32(key + 16); + rk[5] = GETU32(key + 20); + if (keybits == 192) { + for (;;) { + temp = rk[5]; + rk[6] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24)] & 0x000000ff) ^ rcon[i]; + rk[7] = rk[1] ^ rk[6]; + rk[8] = rk[2] ^ rk[7]; + rk[9] = rk[3] ^ rk[8]; + if (++i == 8) + return 12; + rk[10] = rk[4] ^ rk[9]; + rk[11] = rk[5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(key + 24); + rk[7] = GETU32(key + 28); + if (keybits == 256) { + for (;;) { + temp = rk[7]; + rk[8] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24)] & 0x000000ff) ^ rcon[i]; + rk[9] = rk[1] ^ rk[8]; + rk[10] = rk[2] ^ rk[9]; + rk[11] = rk[3] ^ rk[10]; + if (++i == 7) + return 14; + temp = rk[11]; + rk[12] = rk[4] ^ + (Te4[(temp >> 24)] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp) & 0xff] & 0x000000ff); + rk[13] = rk[5] ^ rk[12]; + rk[14] = rk[6] ^ rk[13]; + rk[15] = rk[7] ^ rk[14]; + rk += 8; + } + } + return 0; +} + +/** + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int rijndaelSetupDecrypt(u32 *rk, const u8 *key, int keybits) +{ + int nrounds = 0; + int i = 0; + int j = 0; + u32 temp = 0; + +/* expand the cipher key: */ + nrounds = rijndaelSetupEncrypt(rk, key, keybits); +/* invert the order of the round keys: */ + for (i = 0, j = 4 * nrounds; i < j; i += 4, j -= 4) { + temp = rk[i]; + rk[i] = rk[j]; + rk[j] = temp; + temp = rk[i + 1]; + rk[i + 1] = rk[j + 1]; + rk[j + 1] = temp; + temp = rk[i + 2]; + rk[i + 2] = rk[j + 2]; + rk[j + 2] = temp; + temp = rk[i + 3]; + rk[i + 3] = rk[j + 3]; + rk[j + 3] = temp; + } +/* apply the inverse MixColumn transform to all round keys + but the first and the last: */ + for (i = 1; i < nrounds; i++) { + rk += 4; + rk[0] = + Td0[Te4[(rk[0] >> 24)] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0]) & 0xff] & 0xff]; + rk[1] = + Td0[Te4[(rk[1] >> 24)] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1]) & 0xff] & 0xff]; + rk[2] = + Td0[Te4[(rk[2] >> 24)] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2]) & 0xff] & 0xff]; + rk[3] = + Td0[Te4[(rk[3] >> 24)] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3]) & 0xff] & 0xff]; + } + return nrounds; +} + +void rijndaelEncrypt(const u32 *rk, int nrounds, const u8 plaintext[16], + u8 ciphertext[16]) +{ + u32 s0 = 0; + u32 s1 = 0; + u32 s2 = 0; + u32 s3 = 0; + u32 t0 = 0; + u32 t1 = 0; + u32 t2 = 0; + u32 t3 = 0; +#ifndef FULL_UNROLL + int r = 0; +#endif /* ?FULL_UNROLL */ +/* + * map byte array block to cipher state + * and add initial round key: +*/ + s0 = GETU32(plaintext) ^ rk[0]; + s1 = GETU32(plaintext + 4) ^ rk[1]; + s2 = GETU32(plaintext + 8) ^ rk[2]; + s3 = GETU32(plaintext + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[4]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[5]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[6]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[7]; + /* round 2: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[8]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[9]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; + if (nrounds > 10) { + /* round 10: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; + if (nrounds > 12) { + /* round 12: */ + s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; + s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; + s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; + s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; + t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; + t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; + t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; + } + } + rk += nrounds << 2; +#else /* !FULL_UNROLL */ + /* + * nrounds - 1 full rounds: + */ + r = nrounds >> 1; + for (;;) { + t0 = Te0[(s0 >> 24)] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[4]; + t1 = Te0[(s1 >> 24)] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[5]; + t2 = Te0[(s2 >> 24)] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[6]; + t3 = Te0[(s3 >> 24)] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[7]; + rk += 8; + if (--r == 0) + break; + s0 = Te0[(t0 >> 24)] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[0]; + s1 = Te0[(t1 >> 24)] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[1]; + s2 = Te0[(t2 >> 24)] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[2]; + s3 = Te0[(t3 >> 24)] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[3]; + } +#endif /* ?FULL_UNROLL */ +/* +* apply last round and +* map cipher state to byte array block: +*/ + s0 = (Te4[(t0 >> 24)] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[t3 & 0xff] & 0x000000ff) ^ rk[0]; + PUTU32(ciphertext, s0); + s1 = (Te4[(t1 >> 24)] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[t0 & 0xff] & 0x000000ff) ^ rk[1]; + PUTU32(ciphertext + 4, s1); + s2 = (Te4[(t2 >> 24)] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[t1 & 0xff] & 0x000000ff) ^ rk[2]; + PUTU32(ciphertext + 8, s2); + s3 = (Te4[(t3 >> 24)] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[t2 & 0xff] & 0x000000ff) ^ rk[3]; + PUTU32(ciphertext + 12, s3); +} + +void rijndaelDecrypt(const u32 *rk, int nrounds, const u8 ciphertext[16], + u8 plaintext[16]) +{ + u32 s0 = 0; + u32 s1 = 0; + u32 s2 = 0; + u32 s3 = 0; + u32 t0 = 0; + u32 t1 = 0; + u32 t2 = 0; + u32 t3 = 0; +#ifndef FULL_UNROLL + int r = 0; +#endif /* ?FULL_UNROLL */ + +/* +* map byte array block to cipher state +* and add initial round key: +*/ + s0 = GETU32(ciphertext) ^ rk[0]; + s1 = GETU32(ciphertext + 4) ^ rk[1]; + s2 = GETU32(ciphertext + 8) ^ rk[2]; + s3 = GETU32(ciphertext + 12) ^ rk[3]; +#ifdef FULL_UNROLL + /* round 1: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[4]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[5]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[6]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[7]; + /* round 2: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[8]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[9]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; + /* round 3: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; + /* round 4: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; + /* round 5: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; + /* round 6: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; + /* round 7: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; + /* round 8: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; + /* round 9: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; + if (nrounds > 10) { + /* round 10: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; + /* round 11: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; + if (nrounds > 12) { + /* round 12: */ + s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; + s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; + s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; + s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; + /* round 13: */ + t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; + t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; + t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; + t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; + } + } + rk += nrounds << 2; +#else /* !FULL_UNROLL */ + /* + * nrounds - 1 full rounds: + */ + r = nrounds >> 1; + for (;;) { + t0 = Td0[(s0 >> 24)] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[4]; + t1 = Td0[(s1 >> 24)] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[5]; + t2 = Td0[(s2 >> 24)] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[6]; + t3 = Td0[(s3 >> 24)] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[7]; + rk += 8; + if (--r == 0) + break; + s0 = Td0[(t0 >> 24)] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[0]; + s1 = Td0[(t1 >> 24)] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[1]; + s2 = Td0[(t2 >> 24)] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[2]; + s3 = Td0[(t3 >> 24)] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[3]; + } +#endif /* ?FULL_UNROLL */ +/* +* apply last round and +* map cipher state to byte array block: +*/ + s0 = (Td4[(t0 >> 24)] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1) & 0xff] & 0x000000ff) ^ rk[0]; + PUTU32(plaintext, s0); + s1 = (Td4[(t1 >> 24)] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2) & 0xff] & 0x000000ff) ^ rk[1]; + PUTU32(plaintext + 4, s1); + s2 = (Td4[(t2 >> 24)] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3) & 0xff] & 0x000000ff) ^ rk[2]; + PUTU32(plaintext + 8, s2); + s3 = (Td4[(t3 >> 24)] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0) & 0xff] & 0x000000ff) ^ rk[3]; + PUTU32(plaintext + 12, s3); +} diff --git a/optee/optee_test/ta/crypt/aes_taf.c b/optee/optee_test/ta/crypt/aes_taf.c new file mode 100644 index 0000000..5744014 --- /dev/null +++ b/optee/optee_test/ta/crypt/aes_taf.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include "aes_taf.h" +#include "aes_impl.h" + +/* Encryption/decryption key */ +const unsigned char key[KEYLENGTH(AES_256)] = { + 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 +}; + +/* Encryption/decryption buffer */ +unsigned long rk[RKLENGTH(AES_256)]; + +TEE_Result ta_entry_aes256ecb_encrypt(uint32_t param_types, TEE_Param params[4]) +{ + size_t n_input_blocks = 0; + size_t i = 0; + + /* + * It is expected that memRef[0] is input buffer and memRef[1] is + * output buffer. + */ + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Check that input buffer is whole mult. of block size, in bits */ + if ((params[0].memref.size << 8) % AES_BLOCK_SIZE != 0) + return TEE_ERROR_BAD_PARAMETERS; + + /* Check that output buffer is whole mult. of block size, in bits */ + if ((params[1].memref.size << 8) % AES_BLOCK_SIZE != 0) + return TEE_ERROR_BAD_PARAMETERS; + + /* Set up for encryption */ + (void)rijndaelSetupEncrypt(rk, key, AES_256); + + n_input_blocks = params[0].memref.size / (AES_BLOCK_SIZE / 8); + + for (i = 0; i < n_input_blocks; i++) { + const unsigned char *ciphertext = params[0].memref.buffer; + unsigned char *plaintext = params[1].memref.buffer; + + rijndaelEncrypt(rk, NROUNDS(AES_256), + &ciphertext[i * (AES_BLOCK_SIZE / 8)], + &plaintext[i * (AES_BLOCK_SIZE / 8)]); + } + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_aes256ecb_decrypt(uint32_t param_types, TEE_Param params[4]) +{ + size_t n_input_blocks = 0; + size_t i = 0; + + /* + * It is expected that memRef[0] is input buffer and memRef[1] is + * output buffer. + */ + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + /* Check that input buffer is whole mult. of block size, in bits */ + if ((params[0].memref.size << 8) % AES_BLOCK_SIZE != 0) + return TEE_ERROR_BAD_PARAMETERS; + + /* Check that output buffer is whole mult. of block size, in bits */ + if ((params[1].memref.size << 8) % AES_BLOCK_SIZE != 0) + return TEE_ERROR_BAD_PARAMETERS; + + /* Set up for decryption */ + (void)rijndaelSetupDecrypt(rk, key, AES_256); + + n_input_blocks = params[0].memref.size / (AES_BLOCK_SIZE / 8); + + for (i = 0; i < n_input_blocks; i++) { + const unsigned char *ciphertext = params[0].memref.buffer; + unsigned char *plaintext = params[1].memref.buffer; + + rijndaelDecrypt(rk, NROUNDS(AES_256), + &ciphertext[i * (AES_BLOCK_SIZE / 8)], + &plaintext[i * (AES_BLOCK_SIZE / 8)]); + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/crypt/arith_taf.c b/optee/optee_test/ta/crypt/arith_taf.c new file mode 100644 index 0000000..e07fd79 --- /dev/null +++ b/optee/optee_test/ta/crypt/arith_taf.c @@ -0,0 +1,622 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* Copyright (c) 2018, Linaro Limited */ + +#include +#include +#include +#include +#include + +#include "handle.h" + +#define HT_BIGINT BIT(31) +#define HT_FMMCTX BIT(30) +#define HT_FMMVAR BIT(29) +#define HT_MASK (HT_BIGINT | HT_FMMCTX | HT_FMMVAR) + +#define CHECK_PT(t0, t1, t2, t3) do { \ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_##t0, \ + TEE_PARAM_TYPE_##t1, \ + TEE_PARAM_TYPE_##t2, \ + TEE_PARAM_TYPE_##t3); \ + \ + if ((param_types) != exp_pt) { \ + EMSG("Unpexteded param_types 0x%" PRIx32 ", exptected 0x%" PRIx32, (param_types), exp_pt); \ + return TEE_ERROR_BAD_PARAMETERS; \ + } \ + } while (0) + +static struct handle_db hdb = HANDLE_DB_INITIALIZER; + +static void *lookup_handle(uint32_t type, uint32_t handle) +{ + void *ptr = NULL; + + if ((handle & HT_MASK) == type) + ptr = handle_lookup(&hdb, handle & ~HT_MASK); + + if (!ptr) + EMSG("Invalid handle 0x%" PRIx32, handle); + + return ptr; +} + +static bool get_handle(uint32_t type, void *ptr, uint32_t *handle) +{ + switch (type) { + case HT_BIGINT: + case HT_FMMCTX: + case HT_FMMVAR: + break; + default: + EMSG("Invalid type 0x%" PRIx32, type); + return false; + } + + int h = handle_get(&hdb, ptr); + + if (h < 0) { + EMSG("Failed to allocate handle"); + return false; + } + + *handle = (uint32_t)h | type; + return true; +} + +static void *put_handle(uint32_t handle) +{ + void *ptr = handle_put(&hdb, handle & ~HT_MASK); + + if (!ptr) + EMSG("Invalid handle 0x%" PRIx32, handle); + + return ptr; +} + +TEE_Result ta_entry_arith_new_var(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + size_t len = TEE_BigIntSizeInU32(params[0].value.a); + TEE_BigInt *big_int = TEE_Malloc(len * sizeof(TEE_BigInt), 0); + + if (!big_int) + return TEE_ERROR_OUT_OF_MEMORY; + + if (!get_handle(HT_BIGINT, big_int, ¶ms[1].value.a)) { + TEE_Free(big_int); + return TEE_ERROR_OUT_OF_MEMORY; + } + + TEE_BigIntInit(big_int, len); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_new_fmm_ctx(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_BigInt *modulus = NULL; + uint32_t len = 0; + TEE_BigIntFMMContext *ctx = NULL; + + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + modulus = lookup_handle(HT_BIGINT, params[0].value.b); + if (!modulus) + return TEE_ERROR_BAD_PARAMETERS; + + len = TEE_BigIntFMMContextSizeInU32(params[0].value.a); + ctx = TEE_Malloc(len * sizeof(*ctx), 0); + + if (!get_handle(HT_FMMCTX, ctx, ¶ms[1].value.a)) { + TEE_Free(ctx); + return TEE_ERROR_OUT_OF_MEMORY; + } + + TEE_BigIntInitFMMContext(ctx, len, modulus); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_new_fmm_var(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + size_t len = TEE_BigIntFMMSizeInU32(params[0].value.a); + TEE_BigIntFMM *fmm = TEE_Malloc(len * sizeof(*fmm), 0); + + if (!fmm) + return TEE_ERROR_OUT_OF_MEMORY; + + if (!get_handle(HT_FMMVAR, fmm, ¶ms[1].value.a)) { + TEE_Free(fmm); + return TEE_ERROR_OUT_OF_MEMORY; + } + + TEE_BigIntInitFMM(fmm, len); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_free_handle(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, NONE, NONE, NONE); + + void *ptr = put_handle(params[0].value.a & ~HT_MASK); + + if (!ptr) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_Free(ptr); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_from_octet_string(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, MEMREF_INPUT, NONE, NONE); + + TEE_BigInt *big_int = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!big_int) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_BigIntConvertFromOctetString(big_int, + params[1].memref.buffer, + params[1].memref.size, + params[0].value.b); +} + +TEE_Result ta_entry_arith_from_s32(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, NONE, NONE, NONE); + + TEE_BigInt *big_int = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!big_int) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_BigIntConvertFromS32(big_int, params[0].value.b); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_get_value(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, MEMREF_OUTPUT, NONE); + + TEE_BigInt *big_int = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!big_int) + return TEE_ERROR_BAD_PARAMETERS; + + if (TEE_BigIntCmpS32(big_int, 0) < 0) + params[1].value.a = -1; + else + params[1].value.a = 1; + + return TEE_BigIntConvertToOctetString(params[2].memref.buffer, + ¶ms[2].memref.size, big_int); +} + +TEE_Result ta_entry_arith_get_value_s32(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + TEE_BigInt *big_int = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!big_int) + return TEE_ERROR_BAD_PARAMETERS; + + int32_t v = 0; + TEE_Result res = TEE_BigIntConvertToS32(&v, big_int); + + if (!res) + params[1].value.a = v; + + return res; +} + +TEE_Result ta_entry_arith_get_bit(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + TEE_BigInt *big_int = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!big_int) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.a = TEE_BigIntGetBit(big_int, params[0].value.b); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_get_bit_count(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + TEE_BigInt *big_int = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!big_int) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.a = TEE_BigIntGetBitCount(big_int); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_set_bit(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, NONE, NONE); + + TEE_BigInt *big_int = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!big_int) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_BigIntSetBit(big_int, params[0].value.b, params[1].value.a); +} + +TEE_Result ta_entry_arith_shift_right(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, NONE, NONE); + + TEE_BigInt *op = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *dest = lookup_handle(HT_BIGINT, params[1].value.a); + + if (!op || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_BigIntShiftRight(dest, op, params[0].value.b); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_cmp(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + TEE_BigInt *op1 = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *op2 = lookup_handle(HT_BIGINT, params[0].value.b); + + if (!op1 || !op2) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.a = TEE_BigIntCmp(op1, op2); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_cmp_s32(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + TEE_BigInt *op = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!op) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.a = TEE_BigIntCmpS32(op, params[0].value.b); + + return TEE_SUCCESS; +} + +static TEE_Result ternary_func(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + void (*func)(TEE_BigInt *dest, + const TEE_BigInt *op1, + const TEE_BigInt *op2, + const TEE_BigInt *n)) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, NONE, NONE); + + TEE_BigInt *op1 = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *op2 = lookup_handle(HT_BIGINT, params[0].value.b); + TEE_BigInt *n = lookup_handle(HT_BIGINT, params[1].value.a); + TEE_BigInt *dest = lookup_handle(HT_BIGINT, params[1].value.b); + + if (!op1 || !op2 || !n || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + func(dest, op1, op2, n); + + return TEE_SUCCESS; +} + +static TEE_Result binary_func(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + void (*func)(TEE_BigInt *dest, + const TEE_BigInt *op1, + const TEE_BigInt *op2)) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, NONE, NONE); + + TEE_BigInt *op1 = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *op2 = lookup_handle(HT_BIGINT, params[0].value.b); + TEE_BigInt *dest = lookup_handle(HT_BIGINT, params[1].value.a); + + if (!op1 || !op2 || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + func(dest, op1, op2); + + return TEE_SUCCESS; +} + +static TEE_Result unary_func(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + void (*func)(TEE_BigInt *dest, + const TEE_BigInt *op)) +{ + CHECK_PT(VALUE_INPUT, NONE, NONE, NONE); + + TEE_BigInt *op = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *dest = lookup_handle(HT_BIGINT, params[0].value.b); + + if (!op || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + func(dest, op); + + return TEE_SUCCESS; +} + +static TEE_Result unary_func_res(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS], + TEE_Result (*func)(TEE_BigInt *dest, + const TEE_BigInt *op)) +{ + CHECK_PT(VALUE_INPUT, NONE, NONE, NONE); + + TEE_BigInt *op = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *dest = lookup_handle(HT_BIGINT, params[0].value.b); + + if (!op || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + return func(dest, op); +} + +TEE_Result ta_entry_arith_add(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return binary_func(param_types, params, TEE_BigIntAdd); +} + +TEE_Result ta_entry_arith_sub(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return binary_func(param_types, params, TEE_BigIntSub); +} + +TEE_Result ta_entry_arith_mul(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return binary_func(param_types, params, TEE_BigIntMul); +} + +TEE_Result ta_entry_arith_neg(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return unary_func(param_types, params, TEE_BigIntNeg); +} + +TEE_Result ta_entry_arith_assign(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return unary_func_res(param_types, params, TEE_BigIntAssign); +} + +TEE_Result ta_entry_arith_abs(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return unary_func_res(param_types, params, TEE_BigIntAbs); +} + +TEE_Result ta_entry_arith_sqr(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return unary_func(param_types, params, TEE_BigIntSquare); +} + +TEE_Result ta_entry_arith_div(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, NONE, NONE); + + TEE_BigInt *op1 = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *op2 = lookup_handle(HT_BIGINT, params[0].value.b); + TEE_BigInt *dest_q = lookup_handle(HT_BIGINT, params[1].value.a); + TEE_BigInt *dest_r = lookup_handle(HT_BIGINT, params[1].value.b); + + if (!op1 || !op2 || !dest_q || !dest_r) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_BigIntDiv(dest_q, dest_r, op1, op2); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_mod(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return binary_func(param_types, params, TEE_BigIntMod); +} + +TEE_Result ta_entry_arith_addmod(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return ternary_func(param_types, params, TEE_BigIntAddMod); +} + +TEE_Result ta_entry_arith_submod(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return ternary_func(param_types, params, TEE_BigIntSubMod); +} + +TEE_Result ta_entry_arith_mulmod(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return ternary_func(param_types, params, TEE_BigIntMulMod); +} + +TEE_Result ta_entry_arith_sqrmod(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return binary_func(param_types, params, TEE_BigIntSquareMod); +} + +TEE_Result ta_entry_arith_invmod(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + return binary_func(param_types, params, TEE_BigIntInvMod); +} + +TEE_Result ta_entry_arith_expmod(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, VALUE_INPUT, NONE); + + TEE_BigInt *op1 = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *op2 = lookup_handle(HT_BIGINT, params[0].value.b); + TEE_BigInt *n = lookup_handle(HT_BIGINT, params[1].value.a); + TEE_BigIntFMMContext *ctx = lookup_handle(HT_FMMCTX, params[1].value.b); + TEE_BigInt *dest = lookup_handle(HT_BIGINT, params[2].value.a); + + if (!op1 || !op2 || !n || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_BigIntExpMod(dest, op1, op2, n, ctx); +} + +TEE_Result ta_entry_arith_is_rel_prime(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + TEE_BigInt *op1 = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *op2 = lookup_handle(HT_BIGINT, params[0].value.b); + + if (!op1 || !op2) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.a = TEE_BigIntRelativePrime(op1, op2); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_compute_egcd(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, VALUE_INPUT, NONE); + + TEE_BigInt *op1 = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *op2 = lookup_handle(HT_BIGINT, params[0].value.b); + TEE_BigInt *dest_gcd = lookup_handle(HT_BIGINT, params[2].value.a); + TEE_BigInt *dest_u = NULL; + TEE_BigInt *dest_v = NULL; + + if (!op1 || !op2 || !dest_gcd) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[1].value.a != TA_CRYPT_ARITH_INVALID_HANDLE) { + dest_u = lookup_handle(HT_BIGINT, params[1].value.a); + if (!dest_u) + return TEE_ERROR_BAD_PARAMETERS; + } + if (params[1].value.b != TA_CRYPT_ARITH_INVALID_HANDLE) { + dest_v = lookup_handle(HT_BIGINT, params[1].value.b); + if (!dest_v) + return TEE_ERROR_BAD_PARAMETERS; + } + + TEE_BigIntComputeExtendedGcd(dest_gcd, dest_u, dest_v, op1, op2); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_is_prime(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_OUTPUT, NONE, NONE); + + TEE_BigInt *op = lookup_handle(HT_BIGINT, params[0].value.a); + + if (!op) + return TEE_ERROR_BAD_PARAMETERS; + + params[1].value.a = TEE_BigIntIsProbablePrime(op, params[0].value.b); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_to_fmm(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, NONE, NONE); + + TEE_BigInt *src = lookup_handle(HT_BIGINT, params[0].value.a); + TEE_BigInt *n = lookup_handle(HT_BIGINT, params[0].value.b); + TEE_BigIntFMMContext *ctx = lookup_handle(HT_FMMCTX, params[1].value.a); + TEE_BigIntFMM *dest = lookup_handle(HT_FMMVAR, params[1].value.b); + + if (!src || !n | !ctx || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_BigIntConvertToFMM(dest, src, n, ctx); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_from_fmm(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, NONE, NONE); + + TEE_BigIntFMM *src = lookup_handle(HT_FMMVAR, params[0].value.a); + TEE_BigInt *n = lookup_handle(HT_BIGINT, params[0].value.b); + TEE_BigIntFMMContext *ctx = lookup_handle(HT_FMMCTX, params[1].value.a); + TEE_BigInt *dest = lookup_handle(HT_BIGINT, params[1].value.b); + + if (!src || !n | !ctx || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_BigIntConvertFromFMM(dest, src, n, ctx); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_arith_compute_fmm(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + CHECK_PT(VALUE_INPUT, VALUE_INPUT, VALUE_INPUT, NONE); + + TEE_BigIntFMM *op1 = lookup_handle(HT_FMMVAR, params[0].value.a); + TEE_BigIntFMM *op2 = lookup_handle(HT_FMMVAR, params[0].value.b); + TEE_BigInt *n = lookup_handle(HT_BIGINT, params[1].value.a); + TEE_BigIntFMMContext *ctx = lookup_handle(HT_FMMCTX, params[1].value.b); + TEE_BigIntFMM *dest = lookup_handle(HT_FMMVAR, params[2].value.a); + + if (!op1 || !op2 || !n | !ctx || !dest) + return TEE_ERROR_BAD_PARAMETERS; + + TEE_BigIntComputeFMM(dest, op1, op2, n, ctx); + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/crypt/cryp_taf.c b/optee/optee_test/ta/crypt/cryp_taf.c new file mode 100644 index 0000000..bea45b7 --- /dev/null +++ b/optee/optee_test/ta/crypt/cryp_taf.c @@ -0,0 +1,824 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * Copyright (c) 2022, Linaro Limited. + */ + +#include +#include +#include +#include +#include +#include + +#include "handle.h" + +#define ASSERT_PARAM_TYPE(pt) \ +do { \ + if ((pt) != param_type) \ + return TEE_ERROR_BAD_PARAMETERS; \ +} while (0) + +static struct handle_db op_db = HANDLE_DB_INITIALIZER; +static struct handle_db obj_db = HANDLE_DB_INITIALIZER; + +static uint32_t op_handle_get(TEE_OperationHandle h) +{ + int rc = handle_get(&op_db, h); + + if (rc < 0) { + EMSG("Failed to allocate handle"); + TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); + } + + /* +1 since 0 (TEE_HANDLE_NULL) is invalid */ + return rc + 1; +} + +static TEE_OperationHandle op_handle_put(uint32_t val) +{ + void *h = NULL; + + if (val) { + h = handle_put(&op_db, val - 1); + if (!h) { + EMSG("Invalid handle 0x%"PRIx32, val); + TEE_Panic(TEE_ERROR_BAD_PARAMETERS); + } + } + + return h; +} + +static TEE_OperationHandle op_handle_lookup(uint32_t val) +{ + void *h = NULL; + + if (val) { + h = handle_lookup(&op_db, val - 1); + if (!h) { + EMSG("Invalid handle 0x%"PRIx32, val); + TEE_Panic(TEE_ERROR_BAD_PARAMETERS); + } + } + + return h; +} + +static uint32_t obj_handle_get(TEE_ObjectHandle h) +{ + int rc = handle_get(&obj_db, h); + + if (rc < 0) { + EMSG("Failed to allocate handle"); + TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); + } + + /* +1 since 0 (TEE_HANDLE_NULL) is invalid */ + return rc + 1; +} + +static TEE_ObjectHandle obj_handle_put(uint32_t val) +{ + void *h = NULL; + + if (val) { + h = handle_put(&obj_db, val - 1); + if (!h) { + EMSG("Invalid handle 0x%"PRIx32, val); + TEE_Panic(TEE_ERROR_BAD_PARAMETERS); + } + } + + return h; +} + +static TEE_ObjectHandle obj_handle_lookup(uint32_t val) +{ + void *h = NULL; + + if (val) { + h = handle_lookup(&obj_db, val - 1); + if (!h) { + EMSG("Invalid handle 0x%"PRIx32, val); + TEE_Panic(TEE_ERROR_BAD_PARAMETERS); + } + } + + return h; +} + +TEE_Result ta_entry_allocate_operation(uint32_t param_type, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationHandle op = TEE_HANDLE_NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + res = TEE_AllocateOperation(&op, + params[0].value.b, params[1].value.a, + params[1].value.b); + params[0].value.a = op_handle_get(op); + return res; +} + +TEE_Result ta_entry_free_operation(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_put(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + TEE_FreeOperation(op); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_get_operation_info(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + if (params[1].memref.size < sizeof(TEE_OperationInfo)) + return TEE_ERROR_SHORT_BUFFER; + params[1].memref.size = sizeof(TEE_OperationInfo); + + TEE_GetOperationInfo(op, params[1].memref.buffer); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_reset_operation(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + TEE_ResetOperation(op); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_set_operation_key(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_ObjectHandle key = obj_handle_lookup(params[0].value.b); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + return TEE_SetOperationKey(op, key); +} + +TEE_Result ta_entry_set_operation_key2(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_ObjectHandle key1 = obj_handle_lookup(params[0].value.b); + TEE_ObjectHandle key2 = obj_handle_lookup(params[1].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + return TEE_SetOperationKey2(op, key1, key2); +} + +TEE_Result ta_entry_copy_operation(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle dst = op_handle_lookup(params[0].value.a); + TEE_OperationHandle src = op_handle_lookup(params[0].value.b); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + + TEE_CopyOperation(dst, src); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_digest_update(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + TEE_DigestUpdate(op, params[1].memref.buffer, params[1].memref.size); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_digest_do_final(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); + + return TEE_DigestDoFinal(op, + params[1].memref.buffer, params[1].memref.size, + params[2].memref.buffer, ¶ms[2].memref.size); +} + +TEE_Result ta_entry_digest_extract(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + return TEE_DigestExtract(op, params[1].memref.buffer, + ¶ms[1].memref.size); +} + +TEE_Result ta_entry_cipher_init(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + void *buffer = NULL; + size_t size = 0; + + if (param_type == TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + buffer = NULL; + size = 0; + } else if (param_type == TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + buffer = params[1].memref.buffer; + size = params[1].memref.size; + } else + return TEE_ERROR_BAD_PARAMETERS; + + TEE_CipherInit(op, buffer, size); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_cipher_update(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); + + return TEE_CipherUpdate(op, + params[1].memref.buffer, params[1].memref.size, + params[2].memref.buffer, ¶ms[2].memref.size); +} + +TEE_Result ta_entry_cipher_do_final(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); + + return TEE_CipherDoFinal(op, + params[1].memref.buffer, params[1].memref.size, + params[2].memref.buffer, ¶ms[2].memref.size); +} + +TEE_Result ta_entry_mac_init(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + void *buffer = NULL; + size_t size = 0; + + if (param_type == TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + buffer = NULL; + size = 0; + } else if (param_type == TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + buffer = params[1].memref.buffer; + size = params[1].memref.size; + } else + return TEE_ERROR_BAD_PARAMETERS; + + TEE_MACInit(op, buffer, size); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_mac_update(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + TEE_MACUpdate(op, params[1].memref.buffer, params[1].memref.size); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_mac_final_compute(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); + + return TEE_MACComputeFinal(op, + params[1].memref.buffer, params[1].memref.size, + params[2].memref.buffer, ¶ms[2].memref.size); +} + +TEE_Result ta_entry_mac_final_compare(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE)); + + return TEE_MACCompareFinal(op, + params[1].memref.buffer, params[1].memref.size, + params[2].memref.buffer, params[2].memref.size); +} + +TEE_Result ta_entry_allocate_transient_object(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle o = TEE_HANDLE_NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + res = TEE_AllocateTransientObject(params[0].value.a, params[0].value.b, + &o); + if (res == TEE_SUCCESS) + params[1].value.a = obj_handle_get(o); + return res; +} + +TEE_Result ta_entry_free_transient_object(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_ObjectHandle o = obj_handle_put(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + TEE_FreeTransientObject(o); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_reset_transient_object(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + TEE_ResetTransientObject(o); + return TEE_SUCCESS; +} + +struct attr_packed { + uint32_t id; + uint32_t a; + uint32_t b; +}; + +static TEE_Result unpack_attrs(const uint8_t *buf, size_t blen, + TEE_Attribute **attrs, uint32_t *attr_count) +{ + TEE_Result res = TEE_SUCCESS; + TEE_Attribute *a = NULL; + const struct attr_packed *ap = NULL; + size_t num_attrs = 0; + const size_t num_attrs_size = sizeof(uint32_t); + + if (blen == 0) + goto out; + + if (((uintptr_t)buf & 0x3) != 0 || blen < num_attrs_size) + return TEE_ERROR_BAD_PARAMETERS; + num_attrs = *(uint32_t *) (void *)buf; + if ((blen - num_attrs_size) < (num_attrs * sizeof(*ap))) + return TEE_ERROR_BAD_PARAMETERS; + ap = (const struct attr_packed *)(const void *)(buf + num_attrs_size); + + if (num_attrs > 0) { + size_t n; + + a = TEE_Malloc(num_attrs * sizeof(TEE_Attribute), 0); + if (!a) + return TEE_ERROR_OUT_OF_MEMORY; + for (n = 0; n < num_attrs; n++) { + uintptr_t p; + + a[n].attributeID = ap[n].id; + if (ap[n].id & TEE_ATTR_FLAG_VALUE) { + a[n].content.value.a = ap[n].a; + a[n].content.value.b = ap[n].b; + continue; + } + + a[n].content.ref.length = ap[n].b; + p = (uintptr_t)ap[n].a; + if (p) { + if ((p + a[n].content.ref.length) > blen) { + res = TEE_ERROR_BAD_PARAMETERS; + goto out; + } + p += (uintptr_t)buf; + } + a[n].content.ref.buffer = (void *)p; + } + } + + res = TEE_SUCCESS; +out: + if (res == TEE_SUCCESS) { + *attrs = a; + *attr_count = num_attrs; + } else { + TEE_Free(a); + } + return res; +} + +TEE_Result ta_entry_populate_transient_object(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + res = TEE_PopulateTransientObject(o, attrs, attr_count); + TEE_Free(attrs); + return res; +} + +TEE_Result ta_entry_copy_object_attributes(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_ObjectHandle dst = obj_handle_lookup(params[0].value.a); + TEE_ObjectHandle src = obj_handle_lookup(params[0].value.b); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + return TEE_CopyObjectAttributes1(dst, src); +} + +TEE_Result ta_entry_generate_key(uint32_t param_type, TEE_Param params[4]) +{ + TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + res = TEE_GenerateKey(o, params[0].value.b, attrs, attr_count); + TEE_Free(attrs); + return res; +} + +TEE_Result ta_entry_asymmetric_encrypt(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT)); + + res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + res = TEE_AsymmetricEncrypt(op, attrs, attr_count, + params[2].memref.buffer, params[2].memref.size, + params[3].memref.buffer, ¶ms[3].memref.size); + TEE_Free(attrs); + return res; +} + +TEE_Result ta_entry_asymmetric_decrypt(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT)); + + res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + res = TEE_AsymmetricDecrypt(op, attrs, attr_count, + params[2].memref.buffer, params[2].memref.size, + params[3].memref.buffer, ¶ms[3].memref.size); + TEE_Free(attrs); + return res; +} + +TEE_Result ta_entry_asymmetric_sign_digest(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT)); + + res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + res = TEE_AsymmetricSignDigest(op, attrs, attr_count, + params[2].memref.buffer, params[2].memref.size, + params[3].memref.buffer, ¶ms[3].memref.size); + TEE_Free(attrs); + return res; +} + +TEE_Result ta_entry_asymmetric_verify_digest(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT)); + + res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + res = TEE_AsymmetricVerifyDigest(op, attrs, attr_count, + params[2].memref.buffer, params[2].memref.size, + params[3].memref.buffer, params[3].memref.size); + TEE_Free(attrs); + return res; +} + +TEE_Result ta_entry_derive_key(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_ObjectHandle key = obj_handle_lookup(params[0].value.b); + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute *attrs = NULL; + uint32_t attr_count = 0; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + res = unpack_attrs(params[1].memref.buffer, params[1].memref.size, + &attrs, &attr_count); + if (res != TEE_SUCCESS) + return res; + + TEE_DeriveKey(op, attrs, attr_count, key); + TEE_Free(attrs); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_random_number_generate(uint32_t param_type, + TEE_Param params[4]) +{ + void *buf = NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + buf = TEE_Malloc(params[0].memref.size, 0); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_GenerateRandom(buf, params[0].memref.size); + TEE_MemMove(params[0].memref.buffer, buf, params[0].memref.size); + TEE_Free(buf); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_ae_init(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE)); + return TEE_AEInit(op, params[1].memref.buffer, params[1].memref.size, + params[0].value.b * 8, /* tag_len in bits */ + params[2].value.a, params[2].value.b); +} + +TEE_Result ta_entry_ae_update_aad(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + TEE_AEUpdateAAD(op, params[1].memref.buffer, params[1].memref.size); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_ae_update(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)); + + TEE_AEUpdate(op, params[1].memref.buffer, params[1].memref.size, + params[2].memref.buffer, ¶ms[2].memref.size); + return TEE_SUCCESS; +} + +TEE_Result ta_entry_ae_encrypt_final(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_Result res = TEE_ERROR_OUT_OF_MEMORY; + void *b2 = NULL; + void *b3 = NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT)); + + b2 = TEE_Malloc(params[2].memref.size, 0); + b3 = TEE_Malloc(params[3].memref.size, 0); + if (!b2 || !b3) + goto out; + + res = TEE_AEEncryptFinal(op, params[1].memref.buffer, + params[1].memref.size, b2, + ¶ms[2].memref.size, b3, + ¶ms[3].memref.size); + if (!res) { + TEE_MemMove(params[2].memref.buffer, b2, params[2].memref.size); + TEE_MemMove(params[3].memref.buffer, b3, params[3].memref.size); + } +out: + TEE_Free(b2); + TEE_Free(b3); + return res; +} + +TEE_Result ta_entry_ae_decrypt_final(uint32_t param_type, TEE_Param params[4]) +{ + TEE_OperationHandle op = op_handle_lookup(params[0].value.a); + TEE_Result res = TEE_ERROR_OUT_OF_MEMORY; + void *b2 = NULL; + void *b3 = NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_MEMREF_INPUT)); + + b2 = TEE_Malloc(params[2].memref.size, 0); + b3 = TEE_Malloc(params[3].memref.size, 0); + if (!b2 || !b3) + goto out; + + TEE_MemMove(b3, params[3].memref.buffer, params[3].memref.size); + res = TEE_AEDecryptFinal(op, params[1].memref.buffer, + params[1].memref.size, b2, + ¶ms[2].memref.size, b3, + params[3].memref.size); + if (!res) + TEE_MemMove(params[2].memref.buffer, b2, params[2].memref.size); +out: + TEE_Free(b2); + TEE_Free(b3); + + return res; +} + +TEE_Result ta_entry_get_object_buffer_attribute(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + return TEE_GetObjectBufferAttribute(o, params[0].value.b, + params[1].memref.buffer, ¶ms[1].memref.size); +} + +TEE_Result ta_entry_get_object_value_attribute(uint32_t param_type, + TEE_Param params[4]) +{ + TEE_ObjectHandle o = obj_handle_lookup(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + return TEE_GetObjectValueAttribute(o, params[0].value.b, + ¶ms[1].value.a, ¶ms[1].value.b); +} + +TEE_Result ta_entry_is_algo_supported(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]) +{ + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + params[1].value.a = TEE_IsAlgorithmSupported(params[0].value.a, + params[0].value.b); + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/crypt/derive_key_taf.c b/optee/optee_test/ta/crypt/derive_key_taf.c new file mode 100644 index 0000000..04bb34a --- /dev/null +++ b/optee/optee_test/ta/crypt/derive_key_taf.c @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2019, Linaro Limited + */ + +#include +#include +#include + +#include "derive_key_taf.h" + +#define TA_DERIVED_KEY_MIN_SIZE 16 +#define TA_DERIVED_KEY_MAX_SIZE 32 +#define TA_DERIVED_EXTRA_DATA_MAX_SIZE 1024 + +static const TEE_UUID system_uuid = PTA_SYSTEM_UUID; + +/* + * Helper function that just derives a key. + */ +static TEE_Result derive_unique_key(TEE_TASessionHandle session, + uint8_t *key, uint16_t key_size, + uint8_t *extra, uint16_t extra_size) +{ + TEE_Param params[TEE_NUM_PARAMS] = { 0 }; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t ret_origin = 0; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + if (extra && extra_size > 0) { + params[0].memref.buffer = extra; + params[0].memref.size = extra_size; + } + + params[1].memref.buffer = key; + params[1].memref.size = key_size; + + res = TEE_InvokeTACommand(session, TEE_TIMEOUT_INFINITE, + PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY, + param_types, params, &ret_origin); + if (res != TEE_SUCCESS) + EMSG("Failure when calling PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY"); + + return res; +} + +TEE_Result derive_ta_unique_key_test(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + size_t i = 0; + TEE_Result res_final = TEE_SUCCESS; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_TASessionHandle session = TEE_HANDLE_NULL; + uint8_t big_key[64] = { }; + uint8_t extra_key_data[] = { "My dummy data" }; + uint8_t key1[32] = { }; + uint8_t key2[32] = { }; + uint32_t ret_origin = 0; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &session, &ret_origin); + + if (res != TEE_SUCCESS) + return res; + + /* + * Testing for successful calls to the PTA and that two calls with same + * input data generates the same output data (keys). + */ + res = derive_unique_key(session, key1, sizeof(key1), NULL, 0); + if (res != TEE_SUCCESS) + res_final = TEE_ERROR_GENERIC; + + res = derive_unique_key(session, key2, sizeof(key2), NULL, 0); + if (res != TEE_SUCCESS) + res_final = TEE_ERROR_GENERIC; + + if (TEE_MemCompare(key1, key2, sizeof(key1)) != 0) + res_final = TEE_ERROR_GENERIC; + + TEE_MemFill(key1, 0, sizeof(key1)); + TEE_MemFill(key2, 0, sizeof(key2)); + + /* + * Testing for successful calls to the PTA and that two calls with same + * input data generates the same output data (keys). Here we are using + * extra data also. + */ + res = derive_unique_key(session, key1, sizeof(key1), extra_key_data, + sizeof(extra_key_data)); + if (res != TEE_SUCCESS) + res_final = TEE_ERROR_GENERIC; + + res = derive_unique_key(session, key2, sizeof(key2), extra_key_data, + sizeof(extra_key_data)); + if (res != TEE_SUCCESS) + res_final = TEE_ERROR_GENERIC; + + if (TEE_MemCompare(key1, key2, sizeof(key1)) != 0) + res_final = TEE_ERROR_GENERIC; + + TEE_MemFill(key1, 0, sizeof(key1)); + TEE_MemFill(key2, 0, sizeof(key2)); + + /* + * Testing for successful calls to the PTA and that two calls with + * different input data do not generate the same output data (keys). We + * do that by using one key with and one key without extra data. + */ + res = derive_unique_key(session, key1, sizeof(key1), extra_key_data, + sizeof(extra_key_data)); + if (res != TEE_SUCCESS) + res_final = TEE_ERROR_GENERIC; + + res = derive_unique_key(session, key2, sizeof(key2), NULL, 0); + if (res != TEE_SUCCESS) + res_final = TEE_ERROR_GENERIC; + + /* They should not be equal */ + if (TEE_MemCompare(key1, key2, sizeof(key1)) == 0) + res_final = TEE_ERROR_GENERIC; + + TEE_MemFill(key1, 0, sizeof(key1)); + TEE_MemFill(key2, 0, sizeof(key2)); + + /* + * Testing limits for extra data size (if this would success, then we + * would overwrite the buffer extra_key_data also). + */ + res = derive_unique_key(session, key1, sizeof(key1), extra_key_data, + TA_DERIVED_EXTRA_DATA_MAX_SIZE + 1); + /* This shall fail */ + if (res == TEE_SUCCESS) + res_final = TEE_ERROR_GENERIC; + + TEE_MemFill(key1, 0, sizeof(key1)); + + /* Testing limits. */ + for (i = 0; i < sizeof(big_key); i++) { + uint8_t *extra = NULL; + uint8_t extra_size = 0; + + TEE_MemFill(big_key, 0, sizeof(big_key)); + + /* Alternate between using and not using extra data. */ + if (i % 2) { + extra = extra_key_data; + extra_size = sizeof(extra_key_data); + } + + res = derive_unique_key(session, big_key, i, extra, extra_size); + if (i < TA_DERIVED_KEY_MIN_SIZE) { + if (res != TEE_SUCCESS) + continue; + + EMSG("Small key test iteration %zu failed", i); + res_final = TEE_ERROR_GENERIC; + break; + } + + if (i > TA_DERIVED_KEY_MAX_SIZE) { + if (res != TEE_SUCCESS) + continue; + + EMSG("Big key test iteration %zu failed", i); + res_final = TEE_ERROR_GENERIC; + break; + } + + if (res != TEE_SUCCESS) { + res_final = TEE_ERROR_GENERIC; + break; + } + } + + TEE_CloseTASession(session); + + return res_final; +} + +TEE_Result derive_ta_unique_key_test_shm(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_TASessionHandle session = TEE_HANDLE_NULL; + uint32_t ret_origin = 0; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &session, &ret_origin); + + if (res != TEE_SUCCESS) + return res; + + /* + * Testing for unsuccessful calls to the PTA. They should be + * unsuccessful since we are using an out buffer coming from normal + * world. + */ + res = TEE_InvokeTACommand(session, TEE_TIMEOUT_INFINITE, + PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY, + param_types, params, &ret_origin); + TEE_CloseTASession(session); + + return res; +} diff --git a/optee/optee_test/ta/crypt/handle.c b/optee/optee_test/ta/crypt/handle.c new file mode 100644 index 0000000..cafb413 --- /dev/null +++ b/optee/optee_test/ta/crypt/handle.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, Linaro Limited + */ + +#include +#include "handle.h" + +/* + * Define the initial capacity of the database. It should be a low number + * multiple of 2 since some databases a likely to only use a few handles. + * Since the algorithm doubles up when growing it shouldn't cause a + * noticeable overhead on large databases. + */ +#define HANDLE_DB_INITIAL_MAX_PTRS 4 + +void handle_db_destroy(struct handle_db *db) +{ + if (db) { + TEE_Free(db->ptrs); + db->ptrs = NULL; + db->max_ptrs = 0; + } +} + +int handle_get(struct handle_db *db, void *ptr) +{ + size_t n = 0; + void *p = NULL; + size_t new_max_ptrs = 0; + + if (!db || !ptr) + return -1; + + /* Try to find an empty location */ + for (n = 0; n < db->max_ptrs; n++) { + if (!db->ptrs[n]) { + db->ptrs[n] = ptr; + return n; + } + } + + /* No location available, grow the ptrs array */ + if (db->max_ptrs) + new_max_ptrs = db->max_ptrs * 2; + else + new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; + p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *)); + if (!p) + return -1; + db->ptrs = p; + TEE_MemFill(db->ptrs + db->max_ptrs, 0, + (new_max_ptrs - db->max_ptrs) * sizeof(void *)); + db->max_ptrs = new_max_ptrs; + + /* Since n stopped at db->max_ptrs there is an empty location there */ + db->ptrs[n] = ptr; + return n; +} + +void *handle_put(struct handle_db *db, int handle) +{ + void *p = NULL; + + if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) + return NULL; + + p = db->ptrs[handle]; + db->ptrs[handle] = NULL; + return p; +} + +void *handle_lookup(struct handle_db *db, int handle) +{ + if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) + return NULL; + + return db->ptrs[handle]; +} diff --git a/optee/optee_test/ta/crypt/handle.h b/optee/optee_test/ta/crypt/handle.h new file mode 100644 index 0000000..e3fad39 --- /dev/null +++ b/optee/optee_test/ta/crypt/handle.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + */ +#ifndef __HANDLE_H +#define __HANDLE_H + +#include + +struct handle_db { + void **ptrs; + size_t max_ptrs; +}; + +#define HANDLE_DB_INITIALIZER { NULL, 0 } + +/* + * Frees all internal data structures of the database, but does not free + * the db pointer. The database is safe to reuse after it's destroyed, it + * will just be empty again. + */ +void handle_db_destroy(struct handle_db *db); + +/* + * Allocates a new handle and assigns the supplied pointer to it, + * ptr must not be NULL. + * The function returns + * >= 0 on success and + * -1 on failure + */ +int handle_get(struct handle_db *db, void *ptr); + +/* + * Deallocates a handle. Returns the assiciated pointer of the handle + * the the handle was valid or NULL if it's invalid. + */ +void *handle_put(struct handle_db *db, int handle); + +/* + * Returns the assiciated pointer of the handle if the handle is a valid + * handle. + * Returns NULL on failure. + */ +void *handle_lookup(struct handle_db *db, int handle); + +#endif /*__HANDLE_H*/ diff --git a/optee/optee_test/ta/crypt/include/aes_impl.h b/optee/optee_test/ta/crypt/include/aes_impl.h new file mode 100644 index 0000000..bc5bf63 --- /dev/null +++ b/optee/optee_test/ta/crypt/include/aes_impl.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef AES_IMPL_H +#define AES_IMPL_H + +int rijndaelSetupEncrypt(unsigned long *rk, const unsigned char *key, + int keybits); + +int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key, + int keybits); + +void rijndaelEncrypt(const unsigned long *rk, int nrounds, + const unsigned char plaintext[16], + unsigned char ciphertext[16]); + +void rijndaelDecrypt(const unsigned long *rk, int nrounds, + const unsigned char ciphertext[16], + unsigned char plaintext[16]); + +#define AES_BLOCK_SIZE 128 + +#define AES_128 128 +#define AES_192 192 +#define AES_256 256 + +#define KEYLENGTH(keybits) ((keybits)/8) +#define RKLENGTH(keybits) ((keybits)/8+28) +#define NROUNDS(keybits) ((keybits)/32+6) + +#endif diff --git a/optee/optee_test/ta/crypt/include/aes_taf.h b/optee/optee_test/ta/crypt/include/aes_taf.h new file mode 100644 index 0000000..2165512 --- /dev/null +++ b/optee/optee_test/ta/crypt/include/aes_taf.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef AES_TAF_H +#define AES_TAF_H + +#include + +/* params[0] is input buffer and params[1] is output buffer */ +TEE_Result ta_entry_aes256ecb_encrypt(uint32_t param_types, + TEE_Param params[4]); + +/* params[0] is input buffer and params[1] is output buffer */ +TEE_Result ta_entry_aes256ecb_decrypt(uint32_t param_types, + TEE_Param params[4]); + +#endif diff --git a/optee/optee_test/ta/crypt/include/arith_taf.h b/optee/optee_test/ta/crypt/include/arith_taf.h new file mode 100644 index 0000000..f99bd92 --- /dev/null +++ b/optee/optee_test/ta/crypt/include/arith_taf.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited */ + +#ifndef __ARITH_TAF_H +#define __ARITH_TAF_H + +#include + +TEE_Result ta_entry_arith_new_var(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_new_fmm_ctx(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_new_fmm_var(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_free_handle(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_from_octet_string(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_from_s32(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_get_value(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_get_value_s32(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_get_bit(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_get_bit_count(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_set_bit(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_assign(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_abs(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_shift_right(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_cmp(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_cmp_s32(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_add(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_sub(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_mul(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_neg(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_sqr(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_div(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_mod(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_addmod(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_submod(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_mulmod(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_sqrmod(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_invmod(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_expmod(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_is_rel_prime(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_compute_egcd(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_is_prime(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_to_fmm(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_from_fmm(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_arith_compute_fmm(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); + +#endif /*__ARITH_TAF_H*/ diff --git a/optee/optee_test/ta/crypt/include/cryp_taf.h b/optee/optee_test/ta/crypt/include/cryp_taf.h new file mode 100644 index 0000000..31752a4 --- /dev/null +++ b/optee/optee_test/ta/crypt/include/cryp_taf.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef CRYP_TAF_H +#define CRYP_TAF_H + +#include + +TEE_Result ta_entry_allocate_operation(uint32_t param_type, TEE_Param params[4] +); + +TEE_Result ta_entry_free_operation(uint32_t param_type, TEE_Param params[4] +); + +TEE_Result ta_entry_get_operation_info(uint32_t param_type, TEE_Param params[4] +); + +TEE_Result ta_entry_reset_operation(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_set_operation_key(uint32_t param_type, TEE_Param params[4] +); + +TEE_Result ta_entry_set_operation_key2(uint32_t param_type, TEE_Param params[4] +); + +TEE_Result ta_entry_copy_operation(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_digest_update(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_digest_do_final(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_digest_extract(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_cipher_init(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_cipher_update(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_cipher_do_final(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_mac_init(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_mac_update(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_mac_final_compute(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_mac_final_compare(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_allocate_transient_object(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_free_transient_object(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_reset_transient_object(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_populate_transient_object(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_copy_object_attributes(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_generate_key(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_asymmetric_encrypt(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_asymmetric_decrypt(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_asymmetric_sign_digest(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_asymmetric_verify_digest(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_derive_key(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_random_number_generate(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_ae_init(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_ae_update_aad(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_ae_update(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_ae_encrypt_final(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_ae_decrypt_final(uint32_t param_type, TEE_Param params[4]); + +TEE_Result ta_entry_get_object_buffer_attribute(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_get_object_value_attribute(uint32_t param_type, + TEE_Param params[4]); + +TEE_Result ta_entry_is_algo_supported(uint32_t param_type, TEE_Param params[4]); +#endif /*CRYP_TAF_H */ diff --git a/optee/optee_test/ta/crypt/include/derive_key_taf.h b/optee/optee_test/ta/crypt/include/derive_key_taf.h new file mode 100644 index 0000000..6fccf3a --- /dev/null +++ b/optee/optee_test/ta/crypt/include/derive_key_taf.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef DERIVE_KEY_TAF_H +#define DERIVE_KEY_TAF_H + +#include + +TEE_Result derive_ta_unique_key_test(uint32_t param_types, + TEE_Param params[4]); +TEE_Result derive_ta_unique_key_test_shm(uint32_t param_types, + TEE_Param params[4]); +#endif diff --git a/optee/optee_test/ta/crypt/include/mbedtls_taf.h b/optee/optee_test/ta/crypt/include/mbedtls_taf.h new file mode 100644 index 0000000..03752fd --- /dev/null +++ b/optee/optee_test/ta/crypt/include/mbedtls_taf.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* Copyright (c) 2018, Linaro Limited */ + +#ifndef __MBEDTLS_TAF_H +#define __MBEDTLS_TAF_H + +#include + +TEE_Result ta_entry_mbedtls_self_tests(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_mbedtls_check_cert(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); +TEE_Result ta_entry_mbedtls_sign_cert(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]); + +#endif /*__MBEDTLS_TAF_H*/ diff --git a/optee/optee_test/ta/crypt/include/seed_rng_taf.h b/optee/optee_test/ta/crypt/include/seed_rng_taf.h new file mode 100644 index 0000000..f7db59a --- /dev/null +++ b/optee/optee_test/ta/crypt/include/seed_rng_taf.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef SEED_RNG_TAF_H +#define SEED_RNG_TAF_H + +#include + +TEE_Result seed_rng_pool(uint32_t param_types, TEE_Param params[4]); + +#endif /* SEED_RNG_TAF_H */ diff --git a/optee/optee_test/ta/crypt/include/sha2_impl.h b/optee/optee_test/ta/crypt/include/sha2_impl.h new file mode 100644 index 0000000..2bba3d1 --- /dev/null +++ b/optee/optee_test/ta/crypt/include/sha2_impl.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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 project 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 PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 "stdint.h" + +#ifndef SHA2_IMPL_H +#define SHA2_IMPL_H + +#define SHA224_DIGEST_SIZE (224 / 8) +#define SHA256_DIGEST_SIZE (256 / 8) + +#define SHA256_BLOCK_SIZE (512 / 8) +#define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE + +struct sha224_ctx { + unsigned int tot_len; + unsigned int len; + unsigned char block[2 * SHA224_BLOCK_SIZE]; + uint32_t h[8]; +}; + +struct sha256_ctx { + unsigned int tot_len; + unsigned int len; + unsigned char block[2 * SHA256_BLOCK_SIZE]; + uint32_t h[8]; +}; + +void sha224_init(struct sha224_ctx *ctx); +void sha224_update(struct sha224_ctx *ctx, const unsigned char *message, + unsigned int len); +void sha224_final(struct sha224_ctx *ctx, unsigned char *digest); +void sha224(const unsigned char *message, unsigned int len, + unsigned char *digest); + +void sha256_init(struct sha256_ctx *ctx); +void sha256_update(struct sha256_ctx *ctx, const unsigned char *message, + unsigned int len); +void sha256_final(struct sha256_ctx *ctx, unsigned char *digest); +void sha256(const unsigned char *message, unsigned int len, + unsigned char *digest); + +void sha256_transf(struct sha256_ctx *ctx, const unsigned char *message, + unsigned int block_nb); +#endif diff --git a/optee/optee_test/ta/crypt/include/sha2_taf.h b/optee/optee_test/ta/crypt/include/sha2_taf.h new file mode 100644 index 0000000..caa8b24 --- /dev/null +++ b/optee/optee_test/ta/crypt/include/sha2_taf.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef SHA2_TAF_H +#define SHA2_TAF_H + +#include + +/* params[0] is input buffer and params[1] is output buffer */ +TEE_Result ta_entry_sha224(uint32_t param_types, TEE_Param params[4]); + +/* params[0] is input buffer and params[1] is output buffer */ +TEE_Result ta_entry_sha256(uint32_t param_types, TEE_Param params[4]); + +#endif diff --git a/optee/optee_test/ta/crypt/include/ta_crypt.h b/optee/optee_test/ta/crypt/include/ta_crypt.h new file mode 100644 index 0000000..edb8168 --- /dev/null +++ b/optee/optee_test/ta/crypt/include/ta_crypt.h @@ -0,0 +1,654 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef TA_CRYPT_H +#define TA_CRYPT_H + +/* This UUID is generated with the ITU-T UUID generator at + http://www.itu.int/ITU-T/asn1/uuid.html */ +#define TA_CRYPT_UUID { 0xcb3e5ba0, 0xadf1, 0x11e0, \ + { 0x99, 0x8b, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } } + +#define TA_CRYPT_CMD_SHA224 1 +#define TA_CRYPT_CMD_SHA256 2 +#define TA_CRYPT_CMD_AES256ECB_ENC 3 +#define TA_CRYPT_CMD_AES256ECB_DEC 4 + +/* + * TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, + * uint32_t algorithm, uint32_t mode, uint32_t maxKeySize); + * in/out params[0].value.a = operation + * in/out params[0].value.b = algorithm + * in params[1].value.a = mode + * in params[2].value.b = maxKeySize + */ +#define TA_CRYPT_CMD_ALLOCATE_OPERATION 5 + +/* + * void TEE_FreeOperation(TEE_OperationHandle operation); + * in params[0].value.a = operation + */ +#define TA_CRYPT_CMD_FREE_OPERATION 6 + +/* + * void TEE_GetOperationInfo(TEE_OperationHandle operation, + * TEE_OperationInfo* operationInfo); + * in params[0].value.a = operation + * out params[1].memref = operationInfo + */ +#define TA_CRYPT_CMD_GET_OPERATION_INFO 7 + +/* + * void TEE_ResetOperation(TEE_OperationHandle operation); + * in params[0].value.a = operation + */ +#define TA_CRYPT_CMD_RESET_OPERATION 8 + +/* + * TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, + * TEE_ObjectHandle key); + * in params[0].value.a = operation + * in params[0].value.b = key + */ +#define TA_CRYPT_CMD_SET_OPERATION_KEY 9 + +/* + * TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, + * TEE_ObjectHandle key1, TEE_ObjectHandle key2); + * in params[0].value.a = operation + * in params[0].value.b = key1 + * in params[0].value.a = key2 + */ +#define TA_CRYPT_CMD_SET_OPERATION_KEY2 10 + +/* + * void TEE_CopyOperation(TEE_OperationHandle dstOperation, + * TEE_OperationHandle srcOperation); + * in params[0].value.a = dstOperation + * in params[0].value.b = srcOperation + */ +#define TA_CRYPT_CMD_COPY_OPERATION 11 + +/* + * void TEE_DigestUpdate(TEE_OperationHandle operation, + * void *chunk, size_t chunkSize); + * in params[0].value.a = operation + * in params[1].memref = chunk + */ +#define TA_CRYPT_CMD_DIGEST_UPDATE 12 + +/* + * TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, + * const void *chunk, size_t chunkLen, + * void *hash, size_t *hashLen); + * in params[0].value.a = operation + * in params[1].memref = chunk + * out params[2].memref = hash + */ +#define TA_CRYPT_CMD_DIGEST_DO_FINAL 13 + +/* + * void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, + * size_t IVLen); + * in params[0].value.a = operation + * in params[1].memref = IV + */ +#define TA_CRYPT_CMD_CIPHER_INIT 14 + +/* + * TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, + * const void *srcData, size_t srcLen, + * void *destData, size_t *destLen); + * in params[0].value.a = operation + * in params[1].memref = srcData + * out params[2].memref = dstData + */ +#define TA_CRYPT_CMD_CIPHER_UPDATE 15 + +/* + * TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, + * const void *srcData, size_t srcLen, + * void *destData, size_t *destLen); + * in params[0].value.a = operation + * in params[1].memref = srcData + * out params[2].memref = destData + */ +#define TA_CRYPT_CMD_CIPHER_DO_FINAL 16 + +/* + * void TEE_MACInit(TEE_OperationHandle operation, + * const void *IV, size_t IVLen); + * in params[0].value.a = operation + * in params[1].memref = IV + */ +#define TA_CRYPT_CMD_MAC_INIT 17 + +/* + * void TEE_MACUpdate(TEE_OperationHandle operation, + * const void *chunk, size_t chunkSize); + * in params[0].value.a = operation + * in params[1].memref = chunk + */ +#define TA_CRYPT_CMD_MAC_UPDATE 18 + +/* + * TEE_Result TEE_MACFinalCompute(TEE_OperationHandle operation, + * const void *message, size_t messageLen, + * void *mac, size_t *macLen); + * in params[0].value.a = operation + * in params[1].memref = message + * out params[2].memref = mac + */ +#define TA_CRYPT_CMD_MAC_FINAL_COMPUTE 19 + +/* + * TEE_Result TEE_MACFinalCompare(TEE_OperationHandle operation, + * const void *message, size_t messageLen, + * const void *mac, size_t *macLen); + * in params[0].value.a = operation + * in params[1].memref = message + * in params[2].memref = mac + */ +#define TA_CRYPT_CMD_MAC_FINAL_COMPARE 20 + +/* + * TEE_Result TEE_AllocateTransientObject(TEE_ObjectType objectType, + * uint32_t maxObjectSize, TEE_ObjectHandle* object); + * in params[0].value.a = objectType + * in params[0].value.b = maxObjectSize + * out params[1].value.a = object; + */ +#define TA_CRYPT_CMD_ALLOCATE_TRANSIENT_OBJECT 21 + +/* + * void TEE_FreeTransientObject(TEE_ObjectHandle object); + * in params[0].value.a = object + */ +#define TA_CRYPT_CMD_FREE_TRANSIENT_OBJECT 22 + +/* + * void TEE_ResetTransientObject(TEE_ObjectHandle object); + * in params[0].value.a = object + */ +#define TA_CRYPT_CMD_RESET_TRANSIENT_OBJECT 23 + +/* + * TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, + * TEE_Attribute *attrs, uint32_t attrCount); + * in params[0].value.a = object + * in params[1].memref = attrs + */ +#define TA_CRYPT_CMD_POPULATE_TRANSIENT_OBJECT 24 + +/* + * void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, + * TEE_ObjectHandle srcObject); + * in params[0].value.a = destObject + * in params[0].value.b = srcObject + */ +#define TA_CRYPT_CMD_COPY_OBJECT_ATTRIBUTES 25 + +/* + * TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, + * TEE_Attribute *params, uint32_t paramCount); + * in params[0].value.a = object + * in params[0].value.b = keySize + * in params[1].memref = params + */ +#define TA_CRYPT_CMD_GENERATE_KEY 26 + +/* + * 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); + * in params[0].value.a = operation + * in params[1].memref = params + * in params[2].memref = srcData + * out params[3].memref = destData + */ +#define TA_CRYPT_CMD_ASYMMETRIC_ENCRYPT 27 + +/* + * 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) + * in params[0].value.a = operation + * in params[1].memref = params + * in params[2].memref = srcData + * out params[3].memref = destData + */ +#define TA_CRYPT_CMD_ASYMMETRIC_DECRYPT 28 + +/* + * 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) + * in params[0].value.a = operation + * in params[1].memref = params + * in params[2].memref = digest + * out params[3].memref = signature + */ +#define TA_CRYPT_CMD_ASYMMETRIC_SIGN_DIGEST 29 + +/* + * 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) + * in params[0].value.a = operation + * in params[1].memref = params + * in params[2].memref = digest + * in params[3].memref = signature + */ +#define TA_CRYPT_CMD_ASYMMETRIC_VERIFY_DIGEST 30 + +/* + * void TEE_DeriveKey(TEE_OperationHandle operation, + * const TEE_Attribute *params, uint32_t paramCount, + * TEE_ObjectHandle derivedKey) + * in params[0].value.a = operation + * in params[1].memref = params + * in params[0].value.b = derivedKey + */ +#define TA_CRYPT_CMD_DERIVE_KEY 31 + +/* + * void TEE_RandomNumberGenerate(void *randomBuffer, size_t randomBufferLen); + * out params[0].memref = randomBuffer + */ +#define TA_CRYPT_CMD_RANDOM_NUMBER_GENERATE 32 + +/* + * TEE_Result TEE_AEInit(TEE_OperationHandle operation, + * const void* nonce, size_t nonceLen, + * uint32_t tagLen, uint32_t AADLen, uint32_t payloadLen); + * in params[0].value.a = operation + * in params[1].memref = nonce + * in params[0].value.b = tagLen + * in params[2].value.a = AADLen + * in params[2].value.b = payloadLen + */ +#define TA_CRYPT_CMD_AE_INIT 33 + +/* + * void TEE_AEUpdateAAD(TEE_OperationHandle operation, + * void* AADdata, size_t AADdataLen); + * in params[0].value.a = operation + * in params[1].memref = AADdata + */ +#define TA_CRYPT_CMD_AE_UPDATE_AAD 34 + +/* + * TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, + * const void* srcData, size_t srcLen, + * void* destData, size_t *destLen); + * in params[0].value.a = operation + * in params[1].memref = srcData + * out params[2].memref = destData + */ +#define TA_CRYPT_CMD_AE_UPDATE 35 + +/* + * TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, + * const void* srcData, size_t srcLen, + * void* destData, size_t* destLen, + * void* tag, size_t* tagLen); + * in params[0].value[0].a = operation + * in params[1].memref = srcData + * out params[2].memref = destData + * out params[3].memref = tag + */ +#define TA_CRYPT_CMD_AE_ENCRYPT_FINAL 36 + +/* + * TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, + * const void* srcData, size_t srcLen, + * void* destData, size_t *destLen, + * const void* tag, size_t tagLen); + * in params[0].value.a = operation + * in params[1].memref = srcData + * out params[2].memref = destData + * in params[3].memref = tag + */ +#define TA_CRYPT_CMD_AE_DECRYPT_FINAL 37 + +/* + * TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, + * uint32_t attributeID, void* buffer, size_t* size); + * in params[0].value.a = object + * in params[0].value.b = attributeID + * out params[1].memrefs = buffer + */ +#define TA_CRYPT_CMD_GET_OBJECT_BUFFER_ATTRIBUTE 38 + +/* + * TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, + * uint32_t attributeID, void* buffer, size_t* size); + * in params[0].value.a = object + * in params[0].value.b = attributeID + * out params[1].value.a = value a + * out params[1].value.b = value b + */ +#define TA_CRYPT_CMD_GET_OBJECT_VALUE_ATTRIBUTE 39 + +/* To set or get a global value */ +#define TA_CRYPT_CMD_SETGLOBAL 40 +#define TA_CRYPT_CMD_GETGLOBAL 41 + +/* If mbedtls is compiled with MBEDTLS_SELF_TEST, run the self tests */ +#define TA_CRYPT_CMD_MBEDTLS_SELF_TESTS 42 + +/* + * in params[0].memref = cert-chain + * in params[1].memref = trust-anchor-cert + */ +#define TA_CRYPT_CMD_MBEDTLS_CHECK_CERT 43 + +/* + * in params[0].memref = Certificate request in PKCS#10 format + * out params[1].memref = Signed certificate in X.509 format + * out params[2].memref = Certificate chain + */ +#define TA_CRYPT_CMD_MBEDTLS_SIGN_CERT 44 + +/* + * system pTA is used for adding entropy to RNG pool */ +#define TA_CRYPT_CMD_SEED_RNG_POOL 45 + +/* + * Testing arithmetical interface. + * + * Coding of signed 32-bit values: + * a int32_t with its bit pattern stored in a 32-bit value + */ + +#define TA_CRYPT_ARITH_INVALID_HANDLE 0xffffffff + +/* + * in params[0].value.a: Number of bits + * out params[1].value.b: Handle to bignum variable + */ +#define TA_CRYPT_CMD_ARITH_NEW_VAR 46 + +/* + * in params[0].value.a: Number of bits + * in params[0].value.b: Handle to bignum variable modulus + * out params[1].value.a: Handle to FMM context + */ +#define TA_CRYPT_CMD_ARITH_NEW_FMM_CTX 47 + +/* + * in params[0].value.a: Number of bits + * out params[1].value.a: Handle to FMM variable + */ +#define TA_CRYPT_CMD_ARITH_NEW_FMM_VAR 48 + +/* + * in params[0].value.a: Handle to bignum variable, FMM context, or + * FMM variable + */ +#define TA_CRYPT_CMD_ARITH_FREE_HANDLE 49 + + +/* + * in params[0].value.a: Handle to bignum variable + * in params[0].value.b: S32 representing the sign of the value + * in params[1].memref: octet string representing the value + */ +#define TA_CRYPT_CMD_ARITH_FROM_OCTET_STRING 50 + +/* + * in params[0].value.a: Handle to bignum variable + * in params[0].value.b: S32 representing the value + */ +#define TA_CRYPT_CMD_ARITH_FROM_S32 51 + +/* + * in params[0].value.a: Handle to bignum variable + * out params[1].value.a: S32 representing the sign of the value + * out params[2].memref: octet string representing the value + */ +#define TA_CRYPT_CMD_ARITH_GET_VALUE 52 + +/* + * in params[0].value.a: Handle to bignum variable + * out params[1].value.a: S32 the value + */ +#define TA_CRYPT_CMD_ARITH_GET_VALUE_S32 53 + +/* + * in params[0].value.a: Handle to bignum variable + * in params[0].value.b: Bit number + * out params[1].value.a: Bit value + */ +#define TA_CRYPT_CMD_ARITH_GET_BIT 54 + +/* + * in params[0].value.a: Handle to bignum variable + * out params[1].value.a: Bit count + */ +#define TA_CRYPT_CMD_ARITH_GET_BIT_COUNT 55 + +/* + * in params[0].value.a: handle op + * in params[0].value.b: number of bits + * in params[1].value.a: handle result + */ +#define TA_CRYPT_CMD_ARITH_SHIFT_RIGHT 56 + +/* + * in params[0].value.a: handle op1 + * in params[0].value.b: handle op2 + * out params[1].value.a: result + */ +#define TA_CRYPT_CMD_ARITH_CMP 57 + +/* + * in params[0].value.a: handle op + * in params[0].value.b: S32 shortVal + * out params[1].value.a: result + */ +#define TA_CRYPT_CMD_ARITH_CMP_S32 58 + +/* + * in params[0].value.a: handle a + * in params[0].value.b: handle b + * in params[1].value.a: handle result + */ +#define TA_CRYPT_CMD_ARITH_ADD 59 + +/* + * in params[0].value.a: handle a + * in params[0].value.b: handle b + * in params[1].value.a: handle result + */ +#define TA_CRYPT_CMD_ARITH_SUB 60 + +/* + * in params[0].value.a: handle a + * in params[0].value.b: handle b + * in params[1].value.a: handle result + */ +#define TA_CRYPT_CMD_ARITH_MUL 61 + +/* + * in params[0].value.a: handle a + * in params[0].value.b: handle result + */ +#define TA_CRYPT_CMD_ARITH_NEG 62 + +/* + * in params[0].value.a: handle a + * in params[0].value.b: handle result + */ +#define TA_CRYPT_CMD_ARITH_SQR 63 + +/* + * in params[0].value.a: handle op1 + * in params[0].value.b: handle op2 + * in params[1].value.a: handle result Q + * in params[1].value.b: handle result R + */ +#define TA_CRYPT_CMD_ARITH_DIV 64 + +/* + * in params[0].value.a: handle op + * in params[0].value.b: handle n + * in params[1].value.a: handle result + */ +#define TA_CRYPT_CMD_ARITH_MOD 65 + +/* + * in params[0].value.a: handle op1 + * in params[0].value.b: handle op2 + * in params[1].value.a: handle n + * in params[1].value.b: handle result + */ +#define TA_CRYPT_CMD_ARITH_ADDMOD 66 + +/* + * in params[0].value.a: handle op1 + * in params[0].value.b: handle op2 + * in params[1].value.a: handle n + * in params[1].value.b: handle result + */ +#define TA_CRYPT_CMD_ARITH_SUBMOD 67 + +/* + * in params[0].value.a: handle op1 + * in params[0].value.b: handle op2 + * in params[1].value.a: handle n + * in params[1].value.b: handle result + */ +#define TA_CRYPT_CMD_ARITH_MULMOD 68 + +/* + * in params[0].value.a: handle op + * in params[0].value.b: handle n + * in params[1].value.a: handle result + */ +#define TA_CRYPT_CMD_ARITH_SQRMOD 69 + +/* + * in params[0].value.a: handle op + * in params[0].value.b: handle n + * in params[1].value.a: handle result + */ +#define TA_CRYPT_CMD_ARITH_INVMOD 70 + +/* + * in params[0].value.a: handle op + * in params[0].value.b: handle n + * in params[1].value.a: bool result + */ +#define TA_CRYPT_CMD_ARITH_IS_RELATIVE_PRIME 71 + +/* + * in params[0].value.a: handle op1 + * in params[0].value.b: handle op2 + * in params[1].value.a: handle result u + * in params[1].value.b: handle result v + * in params[2].value.a: handle result gcd + */ +#define TA_CRYPT_CMD_ARITH_COMPUTE_EGCD 72 + +/* + * in params[0].value.a: handle op + * in params[0].value.b: confidence level + * out params[1].value.a: S32 result + */ +#define TA_CRYPT_CMD_ARITH_IS_PRIME 73 + +/* + * in params[0].value.a: handle src + * in params[0].value.b: handle n + * in params[1].value.a: handle FMM context + * in params[1].value.b: handle result FMM variable + */ +#define TA_CRYPT_CMD_ARITH_TO_FMM 74 + +/* + * in params[0].value.a: handle FMM src + * in params[0].value.b: handle bigint n + * in params[1].value.a: handle FMM context + * in params[1].value.b: handle result bigint + */ +#define TA_CRYPT_CMD_ARITH_FROM_FMM 75 + +/* + * in params[0].value.a: handle FMM op1 + * in params[0].value.b: handle FMM op2 + * in params[1].value.a: handle bigint n + * in params[1].value.b: handle FMM context + * in params[2].value.a: handle FMM result + */ +#define TA_CRYPT_CMD_ARITH_COMPUTE_FMM 76 + +/* + * system PTA is used for deriving device and TA unique keys. This function in + * the "crypt" TA is testing the key derivation. + */ +#define TA_CRYPT_CMD_DERIVE_TA_UNIQUE_KEY 77 + +/* + * system PTA is used for deriving device and TA unique keys. This function in + * the "crypt" TA is testing the key derivation. This function tries to derive + * keys by using shared memory buffers (something that shall fail). + * + * in params[0].memref.buffer Buffer for extra data + * in params[0].memref.size Size of extra data + * out params[1].memref.buffer Buffer for the derived key + * out params[1].memref.size Size of the derived key + */ +#define TA_CRYPT_CMD_DERIVE_TA_UNIQUE_KEY_SHM 78 + +/* + * in params[0].value.a: algorithm + * in params[0].value.b: element + * out params[1].value.a: TEE_IsAlgorithmSupported() return status + */ +#define TA_CRYPT_CMD_IS_ALGO_SUPPORTED 79 + +/* + * TEE_Result TEE_DigestExtract(TEE_OperationHandle operation, + * void *hash, size_t *hashLen); + * in params[0].value.a = operation + * out params[1].memref = hash + */ +#define TA_CRYPT_CMD_DIGEST_EXTRACT 80 + +/* + * in params[0].value.a: handle a + * in params[0].value.b: handle result + */ +#define TA_CRYPT_CMD_ARITH_ABS 81 + +/* + * in params[0].value.a: handle a + * in params[0].value.b: handle result + * in params[1].value.a: Bit value + */ +#define TA_CRYPT_CMD_ARITH_SET_BIT 82 + +/* + * in params[0].value.a: handle a + * in params[0].value.b: handle result + */ +#define TA_CRYPT_CMD_ARITH_ASSIGN 83 + +/* + * in params[0].value.a: handle op1 + * in params[0].value.b: handle op2 + * in params[1].value.a: handle n + * in params[1].value.b: handle FMM context + * in params[2].value.a: handle result + */ +#define TA_CRYPT_CMD_ARITH_EXPMOD 84 + +#endif /*TA_CRYPT_H */ diff --git a/optee/optee_test/ta/crypt/include/user_ta_header_defines.h b/optee/optee_test/ta/crypt/include/user_ta_header_defines.h new file mode 100644 index 0000000..ac83ae0 --- /dev/null +++ b/optee/optee_test/ta/crypt/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_CRYPT_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR) +#define TA_STACK_SIZE (32 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/crypt/mbedtls_taf.c b/optee/optee_test/ta/crypt/mbedtls_taf.c new file mode 100644 index 0000000..ad6492b --- /dev/null +++ b/optee/optee_test/ta/crypt/mbedtls_taf.c @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* Copyright (c) 2018, Linaro Limited */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* From ca_crt.c */ +extern const uint8_t ca_crt[]; +extern const size_t ca_crt_size; +/* From mid_crt.c */ +extern const uint8_t mid_crt[]; +extern const size_t mid_crt_size; +/* From mid_key.c */ +extern const uint8_t mid_key[]; +extern const size_t mid_key_size; + +TEE_Result +ta_entry_mbedtls_self_tests(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_type != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + +#ifdef CFG_TA_MBEDTLS_SELF_TEST +#define DO_MBEDTLS_SELF_TEST(x) do { \ + if (mbedtls_##x##_self_test(1)) { \ + EMSG("mbedtls_%s_self_test: failed", #x); \ + return TEE_ERROR_GENERIC; \ + } \ + } while (0) + + DO_MBEDTLS_SELF_TEST(aes); + DO_MBEDTLS_SELF_TEST(des); + DO_MBEDTLS_SELF_TEST(md5); + DO_MBEDTLS_SELF_TEST(sha1); + DO_MBEDTLS_SELF_TEST(sha256); + DO_MBEDTLS_SELF_TEST(base64); + DO_MBEDTLS_SELF_TEST(mpi); + DO_MBEDTLS_SELF_TEST(rsa); + DO_MBEDTLS_SELF_TEST(x509); + + return TEE_SUCCESS; +#else + return TEE_ERROR_NOT_IMPLEMENTED; +#endif +} + +TEE_Result ta_entry_mbedtls_check_cert(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + int ret = 0; + uint32_t flags = 0; + mbedtls_x509_crt crt = { }; + mbedtls_x509_crt trust_crt = { }; + + if (param_type != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_x509_crt_init(&crt); + mbedtls_x509_crt_init(&trust_crt); + + ret = mbedtls_x509_crt_parse(&crt, params[0].memref.buffer, + params[0].memref.size); + if (ret) { + EMSG("mbedtls_x509_crt_parse: failed: %#x", ret); + return TEE_ERROR_BAD_FORMAT; + } + + ret = mbedtls_x509_crt_parse(&trust_crt, params[1].memref.buffer, + params[1].memref.size); + if (ret) { + EMSG("mbedtls_x509_crt_parse: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + ret = mbedtls_x509_crt_verify(&crt, &trust_crt, NULL, NULL, &flags, + NULL, NULL); + if (ret) { + EMSG("mbedtls_x509_crt_verify: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + + } + +out: + mbedtls_x509_crt_free(&trust_crt); + mbedtls_x509_crt_free(&crt); + + return res; +} + +static int f_rng(void *rng __unused, unsigned char *output, size_t output_len) +{ + TEE_GenerateRandom(output, output_len); + return 0; +} + +static TEE_Result write_cert(mbedtls_x509write_cert *crt, void *buf, + size_t *blen) +{ + int ret = 0; + void *b = NULL; + size_t bl = 1024; + + ret = mbedtls_x509write_crt_pem(crt, buf, *blen, f_rng, NULL); + if (!ret) + return TEE_SUCCESS; + + if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) { + EMSG("mbedtls_x509write_crt_pem: failed: %#x", ret); + return TEE_ERROR_GENERIC; + } + + /* + * We were called with a too small buffer, let's find out how + * large it has to be. + */ + while (true) { + b = TEE_Malloc(bl, TEE_MALLOC_FILL_ZERO); + if (!b) + return TEE_ERROR_OUT_OF_MEMORY; + ret = mbedtls_x509write_crt_pem(crt, b, bl, f_rng, NULL); + if (!ret) { + *blen = strlen(b) + 1; + TEE_Free(b); + return TEE_ERROR_SHORT_BUFFER; + } + TEE_Free(b); + if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) { + EMSG("mbedtls_x509write_crt_pem: failed: %#x", ret); + return TEE_ERROR_GENERIC; + } + bl *= 2; + } +} + +static TEE_Result parse_issuer_cert(mbedtls_x509_crt *crt) +{ + int ret = 0; + unsigned char *buf = NULL; + + buf = TEE_Malloc(mid_crt_size + 1, TEE_MALLOC_FILL_ZERO); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(buf, mid_crt, mid_crt_size); + ret = mbedtls_x509_crt_parse(crt, buf, mid_crt_size + 1); + TEE_Free(buf); + if (ret) { + EMSG("mbedtls_x509_crt_parse: failed: %#x", ret); + return TEE_ERROR_BAD_FORMAT; + } + + return TEE_SUCCESS; +} + +static TEE_Result parse_issuer_key(mbedtls_pk_context *pk) +{ + int ret = 0; + unsigned char *buf = NULL; + + buf = TEE_Malloc(mid_key_size + 1, TEE_MALLOC_FILL_ZERO); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(buf, mid_key, mid_key_size); + ret = mbedtls_pk_parse_key(pk, buf, mid_key_size + 1, NULL, 0); + TEE_Free(buf); + if (ret) { + EMSG("mbedtls_pk_parse_key: failed: %#x", ret); + return TEE_ERROR_BAD_FORMAT; + } + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_mbedtls_sign_cert(uint32_t param_type, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result res = TEE_SUCCESS; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + char name[256] = { 0 }; + mbedtls_mpi serial = { }; + mbedtls_x509_crt issuer_crt = { }; + mbedtls_pk_context issuer_key = { }; + mbedtls_x509write_cert crt = { }; + mbedtls_x509_csr csr = { }; + int ret = 0; + size_t sz = 0; + + if (param_type != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + mbedtls_mpi_init(&serial); + mbedtls_x509_crt_init(&issuer_crt); + mbedtls_pk_init(&issuer_key); + mbedtls_x509write_crt_init(&crt); + mbedtls_x509_csr_init(&csr); + + ret = parse_issuer_cert(&issuer_crt); + if (ret) + goto out; + ret = parse_issuer_key(&issuer_key); + if (ret) + goto out; + + ret = mbedtls_mpi_lset(&serial, 1); + if (ret) { + EMSG("mbedtls_mpi_read_string: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + ret = mbedtls_x509_csr_parse(&csr, params[0].memref.buffer, + params[0].memref.size); + if (ret) { + EMSG("mbedtls_x509_csr_parse: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + /* Extract and set subject name */ + ret = mbedtls_x509_dn_gets(name, sizeof(name), &csr.subject); + if (ret < 0) { + EMSG("mbedtls_x509_dn_gets: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + ret = mbedtls_x509write_crt_set_subject_name(&crt, name); + if (ret) { + EMSG("mbedtls_x509write_crt_set_subject_name: failed: %#x", + ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + /* Extract and set issuer name */ + ret = mbedtls_x509_dn_gets(name, sizeof(name), &issuer_crt.subject); + if (ret < 0) { + EMSG("mbedtls_x509_dn_gets: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + ret = mbedtls_x509write_crt_set_issuer_name(&crt, name); + if (ret) { + EMSG("mbedtls_x509write_crt_set_issuer_name: failed: %#x", + ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + mbedtls_x509write_crt_set_md_alg(&crt, csr.sig_md); + mbedtls_x509write_crt_set_subject_key(&crt, &csr.pk); + mbedtls_x509write_crt_set_issuer_key(&crt, &issuer_key); + + ret = mbedtls_x509write_crt_set_serial(&crt, &serial); + if (ret) { + EMSG("mbedtls_x509write_crt_set_serial: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + ret = mbedtls_x509write_crt_set_validity(&crt, "19700101000000", + "20301231235959"); + if (ret) { + EMSG("mbedtls_x509write_crt_set_validity: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + ret = mbedtls_x509write_crt_set_basic_constraints(&crt, 0, 0); + if (ret) { + EMSG("mbedtls_x509write_crt_set_validity: failed: %#x", ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + ret = mbedtls_x509write_crt_set_subject_key_identifier(&crt); + if (ret) { + EMSG("mbedtls_x509write_crt_set_subject_key_identifier: failed: %#x", + ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + ret = mbedtls_x509write_crt_set_authority_key_identifier(&crt); + if (ret) { + EMSG("mbedtls_x509write_crt_set_authority_key_identifier: failed: %#x", + ret); + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + + sz = params[1].memref.size; + res = write_cert(&crt, params[1].memref.buffer, &sz); + if (res && res != TEE_ERROR_SHORT_BUFFER) + goto out; + params[1].memref.size = sz; + + ret = snprintf(params[2].memref.buffer, params[2].memref.size, + "%*s\n%*s", (int)mid_crt_size, (char *)mid_crt, + (int)ca_crt_size, (char *)ca_crt); + if (ret < 0) { + res = TEE_ERROR_BAD_FORMAT; + goto out; + } + if ((size_t)ret >= params[2].memref.size) + res = TEE_ERROR_SHORT_BUFFER; + params[2].memref.size = ret + 1; + +out: + mbedtls_mpi_free(&serial); + mbedtls_x509_crt_free(&issuer_crt); + mbedtls_pk_free(&issuer_key); + mbedtls_x509write_crt_free(&crt); + mbedtls_x509_csr_free(&csr); + return res; +} diff --git a/optee/optee_test/ta/crypt/seed_rng_taf.c b/optee/optee_test/ta/crypt/seed_rng_taf.c new file mode 100644 index 0000000..2f05421 --- /dev/null +++ b/optee/optee_test/ta/crypt/seed_rng_taf.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include + +#include "seed_rng_taf.h" + +TEE_Result seed_rng_pool(uint32_t param_types, TEE_Param params[4]) +{ + static const TEE_UUID system_uuid = PTA_SYSTEM_UUID; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t ret_orig = 0; + + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + if (!params[0].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("TEE_OpenTASession failed"); + goto cleanup_return; + } + + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + PTA_SYSTEM_ADD_RNG_ENTROPY, + param_types, params, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("TEE_InvokeTACommand failed"); + goto cleanup_return; + } + +cleanup_return: + TEE_CloseTASession(sess); + return res; +} diff --git a/optee/optee_test/ta/crypt/sha2_impl.c b/optee/optee_test/ta/crypt/sha2_impl.c new file mode 100644 index 0000000..7a21913 --- /dev/null +++ b/optee/optee_test/ta/crypt/sha2_impl.c @@ -0,0 +1,531 @@ +// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must 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 project 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 PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 "sha2_impl.h" + +#define SHFR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) +#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n))) +#define CH(x, y, z) ((x & y) ^ (~x & z)) +#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) + +#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) +#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) + +#define UNPACK32(x, str) \ + { \ + *((str) + 3) = (uint8_t) ((x)); \ + *((str) + 2) = (uint8_t) ((x) >> 8); \ + *((str) + 1) = (uint8_t) ((x) >> 16); \ + *((str) + 0) = (uint8_t) ((x) >> 24); \ + } + +#define PACK32(str, x) \ + { \ + *(x) = ((uint32_t) *((str) + 3)) \ + | ((uint32_t) *((str) + 2) << 8) \ + | ((uint32_t) *((str) + 1) << 16) \ + | ((uint32_t) *((str) + 0) << 24); \ + } + +/* Macros used for loops unrolling */ +#define SHA256_SCR(i) \ +{ \ + w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \ + + SHA256_F3(w[i - 15]) + w[i - 16]; \ +} + +#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \ +{ \ + t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \ + + sha256_k[j] + w[j]; \ + t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \ + wv[d] += t1; \ + wv[h] = t1 + t2; \ +} + +uint32_t sha224_h0[8] = { + 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, + 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 +}; + +uint32_t sha256_h0[8] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +uint32_t sha256_k[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/* SHA-256 functions */ +void sha256_transf(struct sha256_ctx *ctx, const unsigned char *message, + unsigned int block_nb) +{ + uint32_t w[64] = { }; + uint32_t wv[8] = { }; + uint32_t t1 = 0; + uint32_t t2 = 0; + const unsigned char *sub_block = NULL; + int i = 0; +#ifndef UNROLL_LOOPS + int j = 0; +#endif + + for (i = 0; i < (int)block_nb; i++) { + sub_block = message + (i << 6); + +#ifndef UNROLL_LOOPS + for (j = 0; j < 16; j++) + PACK32(&sub_block[j << 2], &w[j]); + + for (j = 16; j < 64; j++) + SHA256_SCR(j); + + for (j = 0; j < 8; j++) + wv[j] = ctx->h[j]; + + for (j = 0; j < 64; j++) { + t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + + sha256_k[j] + w[j]; + t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) + ctx->h[j] += wv[j]; +#else + PACK32(&sub_block[0], &w[0]); + PACK32(&sub_block[4], &w[1]); + PACK32(&sub_block[8], &w[2]); + PACK32(&sub_block[12], &w[3]); + PACK32(&sub_block[16], &w[4]); + PACK32(&sub_block[20], &w[5]); + PACK32(&sub_block[24], &w[6]); + PACK32(&sub_block[28], &w[7]); + PACK32(&sub_block[32], &w[8]); + PACK32(&sub_block[36], &w[9]); + PACK32(&sub_block[40], &w[10]); + PACK32(&sub_block[44], &w[11]); + PACK32(&sub_block[48], &w[12]); + PACK32(&sub_block[52], &w[13]); + PACK32(&sub_block[56], &w[14]); + PACK32(&sub_block[60], &w[15]); + + SHA256_SCR(16); + SHA256_SCR(17); + SHA256_SCR(18); + SHA256_SCR(19); + SHA256_SCR(20); + SHA256_SCR(21); + SHA256_SCR(22); + SHA256_SCR(23); + SHA256_SCR(24); + SHA256_SCR(25); + SHA256_SCR(26); + SHA256_SCR(27); + SHA256_SCR(28); + SHA256_SCR(29); + SHA256_SCR(30); + SHA256_SCR(31); + SHA256_SCR(32); + SHA256_SCR(33); + SHA256_SCR(34); + SHA256_SCR(35); + SHA256_SCR(36); + SHA256_SCR(37); + SHA256_SCR(38); + SHA256_SCR(39); + SHA256_SCR(40); + SHA256_SCR(41); + SHA256_SCR(42); + SHA256_SCR(43); + SHA256_SCR(44); + SHA256_SCR(45); + SHA256_SCR(46); + SHA256_SCR(47); + SHA256_SCR(48); + SHA256_SCR(49); + SHA256_SCR(50); + SHA256_SCR(51); + SHA256_SCR(52); + SHA256_SCR(53); + SHA256_SCR(54); + SHA256_SCR(55); + SHA256_SCR(56); + SHA256_SCR(57); + SHA256_SCR(58); + SHA256_SCR(59); + SHA256_SCR(60); + SHA256_SCR(61); + SHA256_SCR(62); + SHA256_SCR(63); + + wv[0] = ctx->h[0]; + wv[1] = ctx->h[1]; + wv[2] = ctx->h[2]; + wv[3] = ctx->h[3]; + wv[4] = ctx->h[4]; + wv[5] = ctx->h[5]; + wv[6] = ctx->h[6]; + wv[7] = ctx->h[7]; + + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 0); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 1); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 2); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 3); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 4); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 5); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 6); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 7); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 8); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 9); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 10); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 11); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 12); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 13); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 14); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 15); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 16); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 17); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 18); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 19); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 20); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 21); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 22); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 23); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 24); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 25); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 26); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 27); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 28); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 29); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 30); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 31); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 32); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 33); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 34); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 35); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 36); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 37); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 38); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 39); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 40); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 41); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 42); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 43); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 44); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 45); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 46); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 47); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 48); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 49); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 50); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 51); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 52); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 53); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 54); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 55); + SHA256_EXP(0, 1, 2, 3, 4, 5, 6, 7, 56); + SHA256_EXP(7, 0, 1, 2, 3, 4, 5, 6, 57); + SHA256_EXP(6, 7, 0, 1, 2, 3, 4, 5, 58); + SHA256_EXP(5, 6, 7, 0, 1, 2, 3, 4, 59); + SHA256_EXP(4, 5, 6, 7, 0, 1, 2, 3, 60); + SHA256_EXP(3, 4, 5, 6, 7, 0, 1, 2, 61); + SHA256_EXP(2, 3, 4, 5, 6, 7, 0, 1, 62); + SHA256_EXP(1, 2, 3, 4, 5, 6, 7, 0, 63); + + ctx->h[0] += wv[0]; + ctx->h[1] += wv[1]; + ctx->h[2] += wv[2]; + ctx->h[3] += wv[3]; + ctx->h[4] += wv[4]; + ctx->h[5] += wv[5]; + ctx->h[6] += wv[6]; + ctx->h[7] += wv[7]; +#endif + } +} + +void sha256(const unsigned char *message, + unsigned int len, unsigned char *digest) +{ + struct sha256_ctx ctx = { }; + + sha256_init(&ctx); + sha256_update(&ctx, message, len); + sha256_final(&ctx, digest); +} + +void sha256_init(struct sha256_ctx *ctx) +{ +#ifndef UNROLL_LOOPS + int i = 0; + + for (i = 0; i < 8; i++) + ctx->h[i] = sha256_h0[i]; +#else + ctx->h[0] = sha256_h0[0]; + ctx->h[1] = sha256_h0[1]; + ctx->h[2] = sha256_h0[2]; + ctx->h[3] = sha256_h0[3]; + ctx->h[4] = sha256_h0[4]; + ctx->h[5] = sha256_h0[5]; + ctx->h[6] = sha256_h0[6]; + ctx->h[7] = sha256_h0[7]; +#endif + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha256_update(struct sha256_ctx *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb = 0; + unsigned int new_len = 0; + unsigned int rem_len = 0; + unsigned int tmp_len = 0; + const unsigned char *shifted_message = NULL; + unsigned long int i = 0; + + tmp_len = SHA256_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + for (i = 0; i < rem_len; i++) + ctx->block[ctx->len + i] = message[i]; + + if (ctx->len + len < SHA256_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA256_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha256_transf(ctx, ctx->block, 1); + sha256_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA256_BLOCK_SIZE; + + for (i = 0; i < rem_len; i++) + ctx->block[i] = shifted_message[(block_nb << 6) + i]; + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void sha256_final(struct sha256_ctx *ctx, unsigned char *digest) +{ + unsigned int block_nb = 0; + unsigned int pm_len = 0; + unsigned int len_b = 0; + unsigned long int i_m = 0; +#ifndef UNROLL_LOOPS + int i = 0; +#endif + + block_nb = 1; + if ((SHA256_BLOCK_SIZE - 9) < (ctx->len % SHA256_BLOCK_SIZE)) + block_nb++; + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + for (i_m = 0; i_m < pm_len - ctx->len; i_m++) + ctx->block[ctx->len + i_m] = 0; + + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha256_transf(ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0; i < 8; i++) + UNPACK32(ctx->h[i], &digest[i << 2]); +#else + UNPACK32(ctx->h[0], &digest[0]); + UNPACK32(ctx->h[1], &digest[4]); + UNPACK32(ctx->h[2], &digest[8]); + UNPACK32(ctx->h[3], &digest[12]); + UNPACK32(ctx->h[4], &digest[16]); + UNPACK32(ctx->h[5], &digest[20]); + UNPACK32(ctx->h[6], &digest[24]); + UNPACK32(ctx->h[7], &digest[28]); +#endif +} + +/* SHA-224 functions */ +void sha224(const unsigned char *message, unsigned int len, + unsigned char *digest) +{ + struct sha224_ctx ctx = { }; + + sha224_init(&ctx); + sha224_update(&ctx, message, len); + sha224_final(&ctx, digest); +} + +void sha224_init(struct sha224_ctx *ctx) +{ +#ifndef UNROLL_LOOPS + int i = 0; + + for (i = 0; i < 8; i++) + ctx->h[i] = sha224_h0[i]; +#else + ctx->h[0] = sha224_h0[0]; + ctx->h[1] = sha224_h0[1]; + ctx->h[2] = sha224_h0[2]; + ctx->h[3] = sha224_h0[3]; + ctx->h[4] = sha224_h0[4]; + ctx->h[5] = sha224_h0[5]; + ctx->h[6] = sha224_h0[6]; + ctx->h[7] = sha224_h0[7]; +#endif + + ctx->len = 0; + ctx->tot_len = 0; +} + +void sha224_update(struct sha224_ctx *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb = 0; + unsigned int new_len = 0; + unsigned int rem_len = 0; + unsigned int tmp_len = 0; + const unsigned char *shifted_message = NULL; + unsigned long int i = 0; + + tmp_len = SHA224_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + for (i = 0; i < rem_len; i++) + ctx->block[ctx->len + i] = message[i]; + + if (ctx->len + len < SHA224_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA224_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha256_transf((struct sha256_ctx *)ctx, ctx->block, 1); + sha256_transf((struct sha256_ctx *)ctx, shifted_message, block_nb); + + rem_len = new_len % SHA224_BLOCK_SIZE; + + for (i = 0; i < rem_len; i++) + ctx->block[i] = shifted_message[(block_nb << 6) + i]; + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void sha224_final(struct sha224_ctx *ctx, unsigned char *digest) +{ + unsigned int block_nb = 0; + unsigned int pm_len = 0; + unsigned int len_b = 0; + unsigned long int i_m = 0; +#ifndef UNROLL_LOOPS + int i = 0; +#endif + + block_nb = 1; + if ((SHA224_BLOCK_SIZE - 9) < (ctx->len % SHA224_BLOCK_SIZE)) + block_nb++; + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + for (i_m = 0; i_m < pm_len - ctx->len; i_m++) + ctx->block[ctx->len + i_m] = 0; + + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha256_transf((struct sha256_ctx *)ctx, ctx->block, block_nb); + +#ifndef UNROLL_LOOPS + for (i = 0; i < 7; i++) + UNPACK32(ctx->h[i], &digest[i << 2]); +#else + UNPACK32(ctx->h[0], &digest[0]); + UNPACK32(ctx->h[1], &digest[4]); + UNPACK32(ctx->h[2], &digest[8]); + UNPACK32(ctx->h[3], &digest[12]); + UNPACK32(ctx->h[4], &digest[16]); + UNPACK32(ctx->h[5], &digest[20]); + UNPACK32(ctx->h[6], &digest[24]); +#endif +} diff --git a/optee/optee_test/ta/crypt/sha2_taf.c b/optee/optee_test/ta/crypt/sha2_taf.c new file mode 100644 index 0000000..8025814 --- /dev/null +++ b/optee/optee_test/ta/crypt/sha2_taf.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include "sha2_taf.h" +#include "sha2_impl.h" + +TEE_Result ta_entry_sha224(uint32_t param_types, TEE_Param params[4]) +{ + /* + * It is expected that memRef[0] is input buffer and memRef[1] is + * output buffer. + */ + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[1].memref.size < SHA224_DIGEST_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + sha224((unsigned char *)params[0].memref.buffer, + (unsigned int)params[0].memref.size, + (unsigned char *)params[1].memref.buffer); + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_sha256(uint32_t param_types, TEE_Param params[4]) +{ + /* + * It is expected that memRef[0] is input buffer and memRef[1] is + * output buffer. + */ + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[1].memref.size < SHA256_DIGEST_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + sha256((unsigned char *)params[0].memref.buffer, + (unsigned int)params[0].memref.size, + (unsigned char *)params[1].memref.buffer); + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/crypt/sub.mk b/optee/optee_test/ta/crypt/sub.mk new file mode 100644 index 0000000..6e4debf --- /dev/null +++ b/optee/optee_test/ta/crypt/sub.mk @@ -0,0 +1,31 @@ +global-incdirs-y += include +srcs-y += aes_impl.c +srcs-y += aes_taf.c +srcs-y += cryp_taf.c +srcs-y += derive_key_taf.c +srcs-y += sha2_impl.c +srcs-y += sha2_taf.c +srcs-y += seed_rng_taf.c +srcs-y += ta_entry.c +srcs-$(CFG_TA_MBEDTLS) += mbedtls_taf.c +srcs-y += arith_taf.c +srcs-y += handle.c + +CRYPT_FILE_TO_C_SCRIPT = ../../scripts/file_to_c.py +CRYPT_CA_CRT = ../../certs/ca.crt +CRYPT_MID_CRT = ../../certs/mid.crt +CRYPT_MID_KEY = ../../certs/mid.key + +define crypt_embed_file +# 1 prefix/name +# 2 infile +gensrcs-y += embed-file-$(1) +produce-embed-file-$(1) = $(1).c +depends-embed-file-$(1) := $(FILE_TO_C_SCRIPT) $(2) +recipe-embed-file-$(1) := $(CRYPT_FILE_TO_C_SCRIPT) --inf $(2) --out $(sub-dir-out)/$(1).c --name $(1) +cleanfiles += $(sub-dir-out)/$(1).c +endef + +$(eval $(call crypt_embed_file,ca_crt,../../cert/ca.crt)) +$(eval $(call crypt_embed_file,mid_crt,../../cert/mid.crt)) +$(eval $(call crypt_embed_file,mid_key,../../cert/mid.key)) diff --git a/optee/optee_test/ta/crypt/ta_entry.c b/optee/optee_test/ta/crypt/ta_entry.c new file mode 100644 index 0000000..b997b0c --- /dev/null +++ b/optee/optee_test/ta/crypt/ta_entry.c @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static TEE_Result set_global(uint32_t param_types, TEE_Param params[4]); +static TEE_Result get_global(uint32_t param_types, TEE_Param params[4]); +static int _globalvalue; + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; +} + +/* + * To provoke the linker to produce R_ARM_ABS32 relocations we need to + * pre-initilize a pointer to the function and then also call the function + * directly. + */ +static TEE_Result (*ta_cmd_entries[])(uint32_t, TEE_Param *) = { + [TA_CRYPT_CMD_SHA224] = ta_entry_sha224, + [TA_CRYPT_CMD_SHA256] = ta_entry_sha256, +}; + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + static bool use_fptr = false; + + (void)pSessionContext; + + switch (nCommandID) { + case TA_CRYPT_CMD_SHA224: + use_fptr = !use_fptr; + if (use_fptr) + return ta_cmd_entries[nCommandID](nParamTypes, pParams); + else + return ta_entry_sha224(nParamTypes, pParams); + + case TA_CRYPT_CMD_SHA256: + use_fptr = !use_fptr; + if (use_fptr) + return ta_cmd_entries[nCommandID](nParamTypes, pParams); + else + return ta_entry_sha256(nParamTypes, pParams); + + case TA_CRYPT_CMD_AES256ECB_ENC: + return ta_entry_aes256ecb_encrypt(nParamTypes, pParams); + + case TA_CRYPT_CMD_AES256ECB_DEC: + return ta_entry_aes256ecb_decrypt(nParamTypes, pParams); + + case TA_CRYPT_CMD_ALLOCATE_OPERATION: + return ta_entry_allocate_operation(nParamTypes, pParams); + + case TA_CRYPT_CMD_FREE_OPERATION: + return ta_entry_free_operation(nParamTypes, pParams); + + case TA_CRYPT_CMD_GET_OPERATION_INFO: + return ta_entry_get_operation_info(nParamTypes, pParams); + + case TA_CRYPT_CMD_RESET_OPERATION: + return ta_entry_reset_operation(nParamTypes, pParams); + + case TA_CRYPT_CMD_SET_OPERATION_KEY: + return ta_entry_set_operation_key(nParamTypes, pParams); + + case TA_CRYPT_CMD_SET_OPERATION_KEY2: + return ta_entry_set_operation_key2(nParamTypes, pParams); + + case TA_CRYPT_CMD_COPY_OPERATION: + return ta_entry_copy_operation(nParamTypes, pParams); + + case TA_CRYPT_CMD_DIGEST_UPDATE: + return ta_entry_digest_update(nParamTypes, pParams); + + case TA_CRYPT_CMD_DIGEST_DO_FINAL: + return ta_entry_digest_do_final(nParamTypes, pParams); + + case TA_CRYPT_CMD_DIGEST_EXTRACT: + return ta_entry_digest_extract(nParamTypes, pParams); + + case TA_CRYPT_CMD_CIPHER_INIT: + return ta_entry_cipher_init(nParamTypes, pParams); + + case TA_CRYPT_CMD_CIPHER_UPDATE: + return ta_entry_cipher_update(nParamTypes, pParams); + + case TA_CRYPT_CMD_CIPHER_DO_FINAL: + return ta_entry_cipher_do_final(nParamTypes, pParams); + + case TA_CRYPT_CMD_MAC_INIT: + return ta_entry_mac_init(nParamTypes, pParams); + + case TA_CRYPT_CMD_MAC_UPDATE: + return ta_entry_mac_update(nParamTypes, pParams); + + case TA_CRYPT_CMD_MAC_FINAL_COMPUTE: + return ta_entry_mac_final_compute(nParamTypes, pParams); + + case TA_CRYPT_CMD_MAC_FINAL_COMPARE: + return ta_entry_mac_final_compare(nParamTypes, pParams); + + case TA_CRYPT_CMD_ALLOCATE_TRANSIENT_OBJECT: + return ta_entry_allocate_transient_object(nParamTypes, pParams); + + case TA_CRYPT_CMD_FREE_TRANSIENT_OBJECT: + return ta_entry_free_transient_object(nParamTypes, pParams); + + case TA_CRYPT_CMD_RESET_TRANSIENT_OBJECT: + return ta_entry_reset_transient_object(nParamTypes, pParams); + + case TA_CRYPT_CMD_POPULATE_TRANSIENT_OBJECT: + return ta_entry_populate_transient_object(nParamTypes, pParams); + + case TA_CRYPT_CMD_COPY_OBJECT_ATTRIBUTES: + return ta_entry_copy_object_attributes(nParamTypes, pParams); + + case TA_CRYPT_CMD_GENERATE_KEY: + return ta_entry_generate_key(nParamTypes, pParams); + + case TA_CRYPT_CMD_ASYMMETRIC_ENCRYPT: + return ta_entry_asymmetric_encrypt(nParamTypes, pParams); + + case TA_CRYPT_CMD_ASYMMETRIC_DECRYPT: + return ta_entry_asymmetric_decrypt(nParamTypes, pParams); + + case TA_CRYPT_CMD_ASYMMETRIC_SIGN_DIGEST: + return ta_entry_asymmetric_sign_digest(nParamTypes, pParams); + + case TA_CRYPT_CMD_ASYMMETRIC_VERIFY_DIGEST: + return ta_entry_asymmetric_verify_digest(nParamTypes, pParams); + + case TA_CRYPT_CMD_DERIVE_KEY: + return ta_entry_derive_key(nParamTypes, pParams); + + case TA_CRYPT_CMD_RANDOM_NUMBER_GENERATE: + return ta_entry_random_number_generate(nParamTypes, pParams); + + case TA_CRYPT_CMD_AE_INIT: + return ta_entry_ae_init(nParamTypes, pParams); + + case TA_CRYPT_CMD_AE_UPDATE_AAD: + return ta_entry_ae_update_aad(nParamTypes, pParams); + + case TA_CRYPT_CMD_AE_UPDATE: + return ta_entry_ae_update(nParamTypes, pParams); + + case TA_CRYPT_CMD_AE_ENCRYPT_FINAL: + return ta_entry_ae_encrypt_final(nParamTypes, pParams); + + case TA_CRYPT_CMD_AE_DECRYPT_FINAL: + return ta_entry_ae_decrypt_final(nParamTypes, pParams); + + case TA_CRYPT_CMD_GET_OBJECT_BUFFER_ATTRIBUTE: + return ta_entry_get_object_buffer_attribute(nParamTypes, + pParams); + case TA_CRYPT_CMD_GET_OBJECT_VALUE_ATTRIBUTE: + return ta_entry_get_object_value_attribute(nParamTypes, + pParams); + case TA_CRYPT_CMD_SETGLOBAL: + return set_global(nParamTypes, pParams); + + case TA_CRYPT_CMD_GETGLOBAL: + return get_global(nParamTypes, pParams); + +#ifdef CFG_TA_MBEDTLS + case TA_CRYPT_CMD_MBEDTLS_SELF_TESTS: + return ta_entry_mbedtls_self_tests(nParamTypes, pParams); + case TA_CRYPT_CMD_MBEDTLS_CHECK_CERT: + return ta_entry_mbedtls_check_cert(nParamTypes, pParams); + case TA_CRYPT_CMD_MBEDTLS_SIGN_CERT: + return ta_entry_mbedtls_sign_cert(nParamTypes, pParams); +#endif + case TA_CRYPT_CMD_SEED_RNG_POOL: + return seed_rng_pool(nParamTypes, pParams); + case TA_CRYPT_CMD_DERIVE_TA_UNIQUE_KEY: + return derive_ta_unique_key_test(nParamTypes, pParams); + case TA_CRYPT_CMD_DERIVE_TA_UNIQUE_KEY_SHM: + return derive_ta_unique_key_test_shm(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_NEW_VAR: + return ta_entry_arith_new_var(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_NEW_FMM_CTX: + return ta_entry_arith_new_fmm_ctx(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_NEW_FMM_VAR: + return ta_entry_arith_new_fmm_var(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_FREE_HANDLE: + return ta_entry_arith_free_handle(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_FROM_OCTET_STRING: + return ta_entry_arith_from_octet_string(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_FROM_S32: + return ta_entry_arith_from_s32(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_GET_VALUE: + return ta_entry_arith_get_value(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_GET_VALUE_S32: + return ta_entry_arith_get_value_s32(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_GET_BIT: + return ta_entry_arith_get_bit(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_SET_BIT: + return ta_entry_arith_set_bit(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_GET_BIT_COUNT: + return ta_entry_arith_get_bit_count(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_ABS: + return ta_entry_arith_abs(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_ASSIGN: + return ta_entry_arith_assign(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_SHIFT_RIGHT: + return ta_entry_arith_shift_right(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_CMP: + return ta_entry_arith_cmp(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_CMP_S32: + return ta_entry_arith_cmp_s32(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_ADD: + return ta_entry_arith_add(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_SUB: + return ta_entry_arith_sub(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_MUL: + return ta_entry_arith_mul(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_NEG: + return ta_entry_arith_neg(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_SQR: + return ta_entry_arith_sqr(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_DIV: + return ta_entry_arith_div(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_MOD: + return ta_entry_arith_mod(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_ADDMOD: + return ta_entry_arith_addmod(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_SUBMOD: + return ta_entry_arith_submod(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_MULMOD: + return ta_entry_arith_mulmod(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_SQRMOD: + return ta_entry_arith_sqrmod(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_INVMOD: + return ta_entry_arith_invmod(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_EXPMOD: + return ta_entry_arith_expmod(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_IS_RELATIVE_PRIME: + return ta_entry_arith_is_rel_prime(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_COMPUTE_EGCD: + return ta_entry_arith_compute_egcd(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_IS_PRIME: + return ta_entry_arith_is_prime(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_TO_FMM: + return ta_entry_arith_to_fmm(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_FROM_FMM: + return ta_entry_arith_from_fmm(nParamTypes, pParams); + case TA_CRYPT_CMD_ARITH_COMPUTE_FMM: + return ta_entry_arith_compute_fmm(nParamTypes, pParams); + case TA_CRYPT_CMD_IS_ALGO_SUPPORTED: + return ta_entry_is_algo_supported(nParamTypes, pParams); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} + +static TEE_Result set_global(uint32_t param_types, TEE_Param params[4]) +{ + int i = 0; + + /* Param 0 is a memref, input/output */ + if (TEE_PARAM_TYPE_VALUE_INPUT != TEE_PARAM_TYPE_GET(param_types, 0)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Other parameters must be of type TEE_PARAM_TYPE_NONE */ + for (i = 1; i < 4; i++) { + if (TEE_PARAM_TYPE_NONE != TEE_PARAM_TYPE_GET(param_types, i)) + return TEE_ERROR_BAD_PARAMETERS; + } + + _globalvalue = params[0].value.a; + return TEE_SUCCESS; +} + +static TEE_Result get_global(uint32_t param_types, TEE_Param params[4]) +{ + int i = 0; + + /* Param 0 is a memref, input/output */ + if (TEE_PARAM_TYPE_VALUE_OUTPUT != TEE_PARAM_TYPE_GET(param_types, 0)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Other parameters must be of type TEE_PARAM_TYPE_NONE */ + for (i = 1; i < 4; i++) { + if (TEE_PARAM_TYPE_NONE != TEE_PARAM_TYPE_GET(param_types, i)) + return TEE_ERROR_BAD_PARAMETERS; + } + + params[0].value.a = _globalvalue; + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/enc_fs/include/enc_fs_key_manager_test.h b/optee/optee_test/ta/enc_fs/include/enc_fs_key_manager_test.h new file mode 100644 index 0000000..0dc2442 --- /dev/null +++ b/optee/optee_test/ta/enc_fs/include/enc_fs_key_manager_test.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + */ +#ifndef ENC_FS_KEY_MANAGER_TEST_H +#define ENC_FS_KEY_MANAGER_TEST_H + +/* This UUID is generated with uuidgen + the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html */ +#define ENC_FS_KEY_MANAGER_TEST_UUID \ + { 0x17E5E280, 0xD12E, 0x11E4, \ + { 0xA4, 0x1A, 0x00, 0x02, 0xA5, 0xD5, 0xC5, 0x1B } } +/* The TAFs ID implemented in this TA */ +#define CMD_SELF_TESTS 0 + +#endif /*ENC_FS_KEY_MANAGER_TEST_H*/ diff --git a/optee/optee_test/ta/hash_perf/Android.mk b/optee/optee_test/ta/hash_perf/Android.mk new file mode 100644 index 0000000..6469095 --- /dev/null +++ b/optee/optee_test/ta/hash_perf/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 614789f2-39c0-4ebf-b235-92b32ac107ed.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/hash_perf/Makefile b/optee/optee_test/ta/hash_perf/Makefile new file mode 100644 index 0000000..c6e15a4 --- /dev/null +++ b/optee/optee_test/ta/hash_perf/Makefile @@ -0,0 +1,3 @@ +BINARY = 614789f2-39c0-4ebf-b235-92b32ac107ed +include ../ta_common.mk + diff --git a/optee/optee_test/ta/hash_perf/include/ta_hash_perf.h b/optee/optee_test/ta/hash_perf/include/ta_hash_perf.h new file mode 100644 index 0000000..a13ffdf --- /dev/null +++ b/optee/optee_test/ta/hash_perf/include/ta_hash_perf.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_HASH_PERF_H +#define TA_HASH_PERF_H + +#define TA_HASH_PERF_UUID { 0x614789f2, 0x39c0, 0x4ebf, \ + { 0xb2, 0x35, 0x92, 0xb3, 0x2a, 0xc1, 0x07, 0xed } } + +/* + * Commands implemented by the TA + */ + +#define TA_HASH_PERF_CMD_PREPARE_OP 0 +#define TA_HASH_PERF_CMD_PROCESS 1 + +/* + * Supported algorithms + */ + +#define TA_SHA_SHA1 0 +#define TA_SHA_SHA224 1 +#define TA_SHA_SHA256 2 +#define TA_SHA_SHA384 3 +#define TA_SHA_SHA512 4 +#define TA_SM3 5 +#define TA_HMAC_SHA1 6 +#define TA_HMAC_SHA224 7 +#define TA_HMAC_SHA256 8 +#define TA_HMAC_SHA384 9 +#define TA_HMAC_SHA512 10 +#define TA_HMAC_SM3 11 + +#endif /* TA_HASH_PERF_H */ diff --git a/optee/optee_test/ta/hash_perf/include/ta_hash_perf_priv.h b/optee/optee_test/ta/hash_perf/include/ta_hash_perf_priv.h new file mode 100644 index 0000000..b9059b4 --- /dev/null +++ b/optee/optee_test/ta/hash_perf/include/ta_hash_perf_priv.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_HASH_PERF_PRIV_H +#define TA_HASH_PERF_PRIV_H + +#include + +TEE_Result cmd_prepare_op(uint32_t param_types, TEE_Param params[4]); +TEE_Result cmd_process(uint32_t param_types, TEE_Param params[4]); +void cmd_clean_res(void); + +#endif /* TA_HASH_PERF_PRIV_H */ diff --git a/optee/optee_test/ta/hash_perf/include/user_ta_header_defines.h b/optee/optee_test/ta/hash_perf/include/user_ta_header_defines.h new file mode 100644 index 0000000..494afc0 --- /dev/null +++ b/optee/optee_test/ta/hash_perf/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include "ta_hash_perf.h" + +#define TA_UUID TA_HASH_PERF_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif diff --git a/optee/optee_test/ta/hash_perf/sub.mk b/optee/optee_test/ta/hash_perf/sub.mk new file mode 100644 index 0000000..d7d5236 --- /dev/null +++ b/optee/optee_test/ta/hash_perf/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +srcs-y += ta_hash_perf.c +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/hash_perf/ta_entry.c b/optee/optee_test/ta/hash_perf/ta_entry.c new file mode 100644 index 0000000..167c7de --- /dev/null +++ b/optee/optee_test/ta/hash_perf/ta_entry.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include + +#include "ta_hash_perf.h" +#include "ta_hash_perf_priv.h" + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; + + cmd_clean_res(); +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + (void)pSessionContext; + + switch (nCommandID) { + case TA_HASH_PERF_CMD_PREPARE_OP: + return cmd_prepare_op(nParamTypes, pParams); + + case TA_HASH_PERF_CMD_PROCESS: + return cmd_process(nParamTypes, pParams); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/hash_perf/ta_hash_perf.c b/optee/optee_test/ta/hash_perf/ta_hash_perf.c new file mode 100644 index 0000000..302b87c --- /dev/null +++ b/optee/optee_test/ta/hash_perf/ta_hash_perf.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include + +#include "ta_hash_perf.h" +#include "ta_hash_perf_priv.h" + +#define CHECK(res, name, action) do { \ + if ((res) != TEE_SUCCESS) { \ + DMSG(name ": %#08"PRIx32, (res));\ + action \ + } \ + } while(0) + +static TEE_OperationHandle digest_op; + +static bool is_mac(uint32_t algo) +{ + switch (algo) { + 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: + case TEE_ALG_HMAC_SM3: + return true; + default: + return false; + } +} + +TEE_Result cmd_process(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_OperationInfo info = { }; + int n = 0; + void *in = NULL; + void *out = NULL; + size_t insz = 0; + size_t outsz = 0; + uint32_t offset = 0; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + offset = params[2].value.b; + in = (uint8_t *)params[0].memref.buffer + offset; + insz = params[0].memref.size - offset; + out = params[1].memref.buffer; + outsz = params[1].memref.size; + n = params[2].value.a; + + TEE_GetOperationInfo(digest_op, &info); + + if (is_mac(info.algorithm)) { + while (n--) { + TEE_MACInit(digest_op, NULL, 0); + res = TEE_MACComputeFinal(digest_op, in, insz, out, &outsz); + CHECK(res, "TEE_MACComputeFinal", return res;); + } + } else { + while (n--) { + res = TEE_DigestDoFinal(digest_op, in, insz, out, &outsz); + CHECK(res, "TEE_DigestDoFinal", return res;); + } + } + + return TEE_SUCCESS; +} + +TEE_Result cmd_prepare_op(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectHandle hkey = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Attribute attr = { }; + uint32_t key_type = TEE_TYPE_HMAC_SHA1; + uint32_t mac_key_size = 512; + uint32_t max_key_size = 0; + uint32_t algo = 0; + static uint8_t mac_key[] = { + 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 + }; + uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != exp_param_types) + return TEE_ERROR_BAD_PARAMETERS; + + switch (params[0].value.a) { + case TA_SHA_SHA1: + algo = TEE_ALG_SHA1; + break; + case TA_SHA_SHA224: + algo = TEE_ALG_SHA224; + break; + case TA_SHA_SHA256: + algo = TEE_ALG_SHA256; + break; + case TA_SHA_SHA384: + algo = TEE_ALG_SHA384; + break; + case TA_SHA_SHA512: + algo = TEE_ALG_SHA512; + break; + case TA_SM3: + algo = TEE_ALG_SM3; + break; + case TA_HMAC_SHA1: + key_type = TEE_TYPE_HMAC_SHA1; + algo = TEE_ALG_HMAC_SHA1; + max_key_size = 512; + break; + case TA_HMAC_SHA224: + key_type = TEE_TYPE_HMAC_SHA224; + algo = TEE_ALG_HMAC_SHA224; + max_key_size = 512; + break; + case TA_HMAC_SHA256: + key_type = TEE_TYPE_HMAC_SHA256; + algo = TEE_ALG_HMAC_SHA256; + max_key_size = 512; + break; + case TA_HMAC_SHA384: + key_type = TEE_TYPE_HMAC_SHA384; + algo = TEE_ALG_HMAC_SHA384; + max_key_size = 1024; + break; + case TA_HMAC_SHA512: + key_type = TEE_TYPE_HMAC_SHA512; + algo = TEE_ALG_HMAC_SHA512; + max_key_size = 1024; + break; + case TA_HMAC_SM3: + key_type = TEE_TYPE_HMAC_SM3; + algo = TEE_ALG_HMAC_SM3; + max_key_size = 512; + break; + default: + return TEE_ERROR_BAD_PARAMETERS; + } + + if (digest_op) + TEE_FreeOperation(digest_op); + + if (is_mac(algo)) { + res = TEE_AllocateOperation(&digest_op, algo, TEE_MODE_MAC, max_key_size); + CHECK(res, "TEE_AllocateOperation", return res;); + + res = TEE_AllocateTransientObject(key_type, max_key_size, &hkey); + CHECK(res, "TEE_AllocateTransientObject", return res;); + + attr.attributeID = TEE_ATTR_SECRET_VALUE; + attr.content.ref.buffer = mac_key; + attr.content.ref.length = mac_key_size / 8; + + res = TEE_PopulateTransientObject(hkey, &attr, 1); + CHECK(res, "TEE_PopulateTransientObject", return res;); + + res = TEE_SetOperationKey(digest_op, hkey); + CHECK(res, "TEE_SetOperationKey", return res;); + + TEE_FreeTransientObject(hkey); + } else { + res = TEE_AllocateOperation(&digest_op, algo, TEE_MODE_DIGEST, 0); + CHECK(res, "TEE_AllocateOperation", return res;); + } + return TEE_SUCCESS; +} + +void cmd_clean_res(void) +{ + if (digest_op) + TEE_FreeOperation(digest_op); +} diff --git a/optee/optee_test/ta/identity_subkey2.bin b/optee/optee_test/ta/identity_subkey2.bin new file mode 100644 index 0000000000000000000000000000000000000000..073038936ad1de9aa9ccfa0ff94b4fe77e39f430 GIT binary patch literal 628 zcmV-)0*n1fQ&dj_0000$0RR9nNkMQR0004=FKZlne3S8z^!B1{Z{2{zIZf4sI<65FW}GdK7E7vf<`~J5%_ChX%WI6 zN+-~=X~8@{`g>m+skFK0DX>w-xH69$hjavsS}|YgfD4i~3Ai%*7zT|NB^YT;!8~}$ zJ`^;W2LO%x2B=6lVCLhLI4RXc4-Duv-sds&Ia+j`2`AX!83hAn4c8#>Yw$-Lq-UO(8mf?zP}e;=1v#3R#J({g+)!NrVjLZCLLdLOiE5jh^Tb#Gu*Qn#`rpM7gJ4rUlO&)wX>wvS#{w OamA}HT9c#=0RRD-OBr(j literal 0 HcmV?d00001 diff --git a/optee/optee_test/ta/identity_subkey2.pem b/optee/optee_test/ta/identity_subkey2.pem new file mode 100644 index 0000000..f6f81be --- /dev/null +++ b/optee/optee_test/ta/identity_subkey2.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC763IBu3IGr6Ik +EQ05B3A48R2WO9RLNV8TM6hDgGdF9h4CBN6yDbYoxK54hqz1vKKIiAuWxsdKEt2z +ac3kWC/91fH7pSsTZERiW8NZHGm0I3fecp8N+85rlQUKBa1Ejbaa3yWm3UZYOg2r +jFrGg3nJiFEI2ORsfYongfvAbWZh22rjD9fSOaBPZQTXRpNKt+qbYxXYj/l26YKS +yi7lgd6nGqqQklDXPToFOZqXxrKGVmtH7YPFpOs5MbVHxV7nESELLAMlRG/w00+l +ytj9l11LSYQM5W1Y7xxCPKc0jZ7oEMSg2dqazKXQRLmnXqYFzxzVtn0wsmb6e3HF +qy5ak6QNAgMBAAECggEARD5k0Kw55KOzxlVK8AL7hjJKBF0F46omNNr1qE3hM08F +5sXN+etw061ZjvuZpEQ04lBFpSPbC9N+H8G0u9Aq3YvsrO52jjxDeVTJxHrFCF45 +EdeeW32uoPMlOVaGbfbo8aVIDykcer3aaQo3jRACEmYmx4e8rImKun5B5sfT/oUI +6Jp8i5zRF2M+yqczmqRbonqoRVa9WWyGT8pxfm5uaYg7/BFE9p6XfwTE8Y1qYyxI +r19uGIqnS5mR3E2qPyizs4DkabMWmKNflOr0Y28h7TgEqwTcJaSM7wDrSlQnCNF4 +FGdKOY/omRHtxx2z9bd9XQ0fjZmloxIBLO3fX4pUIQKBgQDnq7x87j/aFk8HlAi6 +KzmtxPTu/bwxiLvcNDtDz6l7K1+icl1kuQ6zQP827u7IS/l2MRbkred70Dt5OGOs +XWysCQZM9kl8Cq7uXJ7vnu9xT+2R5v7sqaqgVAY8hxW4zFtGrrfT8sZgRWTXILBR +UlsWfy2EwqAwNA7FB0AdJMVWdwKBgQDPp3+zoQOIkM+ImdR0gp+kzI2H1WqvO25y +3WNy8xTqfy/qNlST6tuCDzfZ6S8KqaP+V+QomgMjRjAsggGCNiRMFtYHpTgLm9wC +XnwYtv3qIMUqTmnpH3hCPQ7PEEKedfht9p1D1DtBZsrQncqFtoORFqisawvlwDuU +kzstSlqGmwKBgExhQ5CQ4D5f0oh2FvaCH88Zu4M75psSMJWmJs/xnDf+kdY2DHKT +zLPuvvX2ioVA/ysnfhvA9ivM+H67x6jhWF3Tz9756DpcL1Zo9QGdjeX26yWKWgve +2GFpsnCsPM4jmghQvEzFov/EgT2oClmVZHCjV3eIz1V1JFVzUYEKSYF7AoGAXR9S +h223tfCrASlrO2ywxyjsd3PfygGvAFgEFzKnuJmdFT2UJFl4YxUMCO8np3J4FsG3 +kfWvXoxFYlBS+N/q2yyKgxc20Q3uVimlITg/GlXj1Zsgp+jy91GGaJl0Jrfk1vt3 +f0mX4TaF0ZRRlDFLQy+UKO5AgaH5liGIskDb4+0CgYBQJgTr44ymDm7bBvtOtNhn +DLUPV1DtllwlCE8SJDuK26xyru63+/jzHTR0ofRod4uzHVhLNkVnYvtB1qxqXuLw +9eNkxZoIFmTrtaE8YSCqloGPMCPzKtsj1XwwzxJL09bnP7/2hhI+B21Z1bx38ChE +WDZvUMeBvqiaIph64XI8yQ== +-----END PRIVATE KEY----- diff --git a/optee/optee_test/ta/include/ta_storage.h b/optee/optee_test/ta/include/ta_storage.h new file mode 100644 index 0000000..a4b1bc8 --- /dev/null +++ b/optee/optee_test/ta/include/ta_storage.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef __TA_STORAGE_H +#define __TA_STORAGE_H + +#define TA_STORAGE_UUID { 0xb689f2a7, 0x8adf, 0x477a, \ + { 0x9f, 0x99, 0x32, 0xe9, 0x0c, 0x0a, 0xd0, 0xa2 } } +#define TA_STORAGE2_UUID { 0x731e279e, 0xaafb, 0x4575, \ + { 0xa7, 0x71, 0x38, 0xca, 0xa6, 0xf0, 0xcc, 0xa6 } } + +struct ta_storage_obj_info { + uint32_t object_type; + uint32_t object_size; + uint32_t max_object_size; + uint32_t object_usage; + uint32_t data_size; + uint32_t data_position; + uint32_t handle_flags; +}; + +#define TA_STORAGE_CMD_OPEN 0 +#define TA_STORAGE_CMD_CLOSE 1 +#define TA_STORAGE_CMD_READ 2 +#define TA_STORAGE_CMD_WRITE 3 +#define TA_STORAGE_CMD_CREATE 4 +#define TA_STORAGE_CMD_SEEK 5 +#define TA_STORAGE_CMD_UNLINK 6 +#define TA_STORAGE_CMD_RENAME 7 +#define TA_STORAGE_CMD_TRUNC 8 +#define TA_STORAGE_CMD_ALLOC_ENUM 9 +#define TA_STORAGE_CMD_FREE_ENUM 10 +#define TA_STORAGE_CMD_RESET_ENUM 11 +#define TA_STORAGE_CMD_START_ENUM 12 +#define TA_STORAGE_CMD_NEXT_ENUM 13 +#define TA_STORAGE_CMD_CREATE_OVERWRITE 14 +#define TA_STORAGE_CMD_KEY_IN_PERSISTENT 15 +#define TA_STORAGE_CMD_LOOP 16 +#define TA_STORAGE_CMD_RESTRICT_USAGE 17 +#define TA_STORAGE_CMD_ALLOC_OBJ 18 +#define TA_STORAGE_CMD_FREE_OBJ 19 +#define TA_STORAGE_CMD_RESET_OBJ 20 +#define TA_STORAGE_CMD_GET_OBJ_INFO 21 +#define TA_STORAGE_CMD_OPEN_ID_IN_SHM 22 +#define TA_STORAGE_CMD_CREATE_ID_IN_SHM 23 +#define TA_STORAGE_CMD_CREATEOVER_ID_IN_SHM 24 +#define TA_STORAGE_CMD_RENAME_ID_IN_SHM 25 + +#endif /*__TA_STORAGE_H*/ diff --git a/optee/optee_test/ta/large/Android.mk b/optee/optee_test/ta/large/Android.mk new file mode 100644 index 0000000..065f59b --- /dev/null +++ b/optee/optee_test/ta/large/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 25497083-a58a-4fc5-8a72-1ad7b69b8562.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/large/Makefile b/optee/optee_test/ta/large/Makefile new file mode 100644 index 0000000..4a4e936 --- /dev/null +++ b/optee/optee_test/ta/large/Makefile @@ -0,0 +1,2 @@ +BINARY = 25497083-a58a-4fc5-8a72-1ad7b69b8562 +include ../ta_common.mk diff --git a/optee/optee_test/ta/large/include/ta_large.h b/optee/optee_test/ta/large/include/ta_large.h new file mode 100644 index 0000000..bbbf0eb --- /dev/null +++ b/optee/optee_test/ta/large/include/ta_large.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#ifndef TA_LARGE_H +#define TA_LARGE_H + +#define TA_LARGE_UUID { 0x25497083, 0xa58a, 0x4fc5, \ + { 0x8a, 0x72, 0x1a, 0xd7, 0xb6, 0x9b, 0x85, 0x62 } } + +#endif /*TA_LARGE_H */ diff --git a/optee/optee_test/ta/large/include/user_ta_header_defines.h b/optee/optee_test/ta/large/include/user_ta_header_defines.h new file mode 100644 index 0000000..a3ba142 --- /dev/null +++ b/optee/optee_test/ta/large/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include + +#define TA_UUID TA_LARGE_UUID + +#define TA_FLAGS (TA_FLAG_MULTI_SESSION) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (2 * 1024) + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_test/ta/large/sub.mk b/optee/optee_test/ta/large/sub.mk new file mode 100644 index 0000000..d5e3f32 --- /dev/null +++ b/optee/optee_test/ta/large/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/large/ta_entry.c b/optee/optee_test/ta/large/ta_entry.c new file mode 100644 index 0000000..94c348f --- /dev/null +++ b/optee/optee_test/ta/large/ta_entry.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include +#include + +/* + * Declare a large buffer likely to span mutiple translation tables. + * + * Ideally we'd like to have one that is slightly larger than 2MiB since + * that would guarantee this. But that would consume yet another static + * translation table (MAX_XLAT_TABLES) which would typically only be needed + * when loading this TA but would cause a permanent increase in the OP-TEE + * memory footprint. + * + * So we settle with this size, it should quite often be enough if + * configured with CFG_TA_ASLR=y. It will be 100% effective with + * CFG_WITH_LPAE=n. + */ +static const uint8_t large_buffer[1024 * 1024 ] = { 1 }; + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types, + TEE_Param params[4], + void **session_ctx) +{ + (void)param_types; + (void)params; + + /* Don't let the linker garbage collect this symbol. */ + *session_ctx = (void *)large_buffer; + + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *session_ctx) +{ + (void)session_ctx; +} + +TEE_Result TA_InvokeCommandEntryPoint(void *session_ctx, + uint32_t cmd_id, uint32_t param_types, + TEE_Param params[4]) +{ + (void)session_ctx; + (void)cmd_id; + (void)param_types; + (void)params; + + return TEE_ERROR_GENERIC; +} diff --git a/optee/optee_test/ta/mid_level_subkey.bin b/optee/optee_test/ta/mid_level_subkey.bin new file mode 100644 index 0000000000000000000000000000000000000000..bf33282f2de069e327d19ce462d8394d94a64ff3 GIT binary patch literal 1320 zcmeYW4)JGZU|?`yWMDAxbSzL{U|{@O{8{r~`M!*t=VI;?=J+j+j+425ugz@s^_zbd z%V+tfn!l(HobPz#6fSh3Sq=o!jdw%tY4jWLhWbcKo2`zpFPt8NB$I{$z(OcYydj<6UvuYJq+UdbejD ztNxqcn(^S*2Te^QshQvVSDccljK49{ri~@oBg-=VV*Bequ0aAm$4iQZFFrLrGKqO> z1Ix0D)=ldk@-zfxaW7=w^yx!=Yn4dJ{TeoN%i`7H^D8|HjhE`55dAi{6QhNdS1#wpvPKQ{7RI$?Pr z=F7BOIRzKb{{j?lP=V-Y?4k+tuGNXJlZ^%}j~UNi9pwi7zfq%1*5W1q&&_1527!w#q#( zrSolGz}Xj%cpNoFYnQVh&tH-AQ17vT`P=tQ*Z1DKbFl6ce{v&UeeFa>*3wS0DeyedE8!KifX& z&X-`3i9dOke^<*FHQ+C2aGV%1)4pz1n0(cnzc1`3ZL8aUSxajg%jV$eU!E41x;xz8 zTDJVLY3v$C8~0?*U51Qi&%3QJ-#yjtb3jhuH?wx6p3Limj}CoQx%_COVU)SqZeP2s{LCJ^I-!M^O19->hFJNix6J(E1hez z*FL_>l(#eF_t$wF1%<*?CieaLv$gM@)l%`l$1a#Ev!C1+v2KM_q{mUI1%W+nU-so^ zu~v&Y00SJ9Wbk)bCWbJTynU(>qwTUiQ2iJ33pc+ye)>vg<;>olf7?Ps?v%N1_$O3! zIOOfS_w(O9W4kT8L1^BAnG0{}7FT9ODJ)QwdKDv-xX!G);U$NxT~gh|=?iZ>yHNkX zE;=xN9NtXv;F>pE59{&oRDqodAq0e gg8TM%D>L=5=7d!~?2ip+essR;A8nbzc@&st0h;kYsQ>@~ literal 0 HcmV?d00001 diff --git a/optee/optee_test/ta/mid_level_subkey.pem b/optee/optee_test/ta/mid_level_subkey.pem new file mode 100644 index 0000000..cf1757c --- /dev/null +++ b/optee/optee_test/ta/mid_level_subkey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCl1sCRM+jO0pnx +71oh6TZWIc0B3tHd0Sf3ncAGTPe7nuTzkCoGSKAL2O0i3URoJy1TkJFUAnTt5Shc +K0SrKQekEK20619VJyD/STVbYJlu9K1j0hOf0rsthAlig/eYBk6Der0wyRqoR/Mv +eVUv6B+hs+rHy9RpeZmNuf2GVVTcdkWw/hJyw1Tt7u+f7uYG2x2wEp7AmaHaLXN5 +aFogoCEa6lwSYa42e4DpCB0+Yn6Rl6HY5tB//4TgXLUOeY8cGmoAF6QqEfuSFDLs +C/NdzAdIZqWzmDXEnt/ct9+g1PspuMgdgYztvIXQR7eHOjYnVoNgqkwH4zGZ8UPd +T1s5aAnFAgMBAAECgf9hi4gWkz8d1dKizxRjvWWoTC03aFy37Z3n7ZK+QoNs0khf +K/kqiEQtr7otnQDKUsL2+HmPI1ijykkp9bcO3cQk2yiOcOfZFABCaY5IIwm7WGTV +UA8y1GWBq2dPmU/uzJopCSNXcEgG6HPnVieiuvSCqJhBxEtrji0nYrrbVzE/2Eo3 +vVesMCiCNRCOKk48nL/mvg0I2cCC64HgEmPEPrtSw5onW9qffr0U3T9v+YIh03cU +XZX50zb7WahO8zc8dElG7pYPBBLkNj+OJaf+uY8CLZtCXvZeMR0PStcclRY4jSNM +gTdthynRwaUv8YvP/AvmO7di364Q5210IvJMhYECgYEAwDclFy+8lWoF5cvfW353 +okUItN24kiiFFUYcPL59Cn47gYj2OpHfDHgAhIOwrQRUewTRe7FnHv3ZspbIA3Wo +3thcl/ktzjV5qJ+OGfx3oLhhKT3QE4yM8kAf0qsn+FgonTmzhmk7A4/moZeAVJKc +K08ZO/NdhEseIPfM2LAktkECgYEA3N7mPLCCZqCODYml4raXv+XuiW1cpBSGPVsn +08Vq9EO0awJ2iw6ZCJWYizIiDMr2oVQmArdWMDANerrFzDUOrw7GktolyJ6fzssH +td5F+uJX9h+nneuSvEyiJr7ujysfkRwxGrkaicUp9cVNT+UpHgtX1PCxodVartfy +0Z6i2oUCgYBjmW9/tz2p0nlh3KVNPJfzHoBnb+he294x6tVg6HfUgxqEgZrNOJ7y +UBA8mhxnWrIH2LRPutorZfBzKMxVdpddeZFpMjX4/x6eMKcqcfbu8ftuqlfyeUbj +lDSpLgUVG2FYLvkGceqhauRf4SgfKqT/kAoMVYukrGPdQ2oC8irjwQKBgQClsASR +ZGv+JtVJbIfnocgGqaseps6HO+pT3qzq3T7VjHCskcVxnXrJiMdNLEeEx0DqVyDI +itX6AiIqfi/hd6/TPMdT5JfRfsUtMPtQwDRI90C7HpX0DoMeBHLjk/mLpvLgPYDM +pi01SpWmi+LqW2NT6XhzAjiOyWlknhTGkTVjrQKBgQCJVvrVYee7hlpBakLXxD2b +IxKqN10sFvyYqRIzFpPN7gfYbAdMR+XXqeZNrELuUfu7tc+/owxEsD4/acU11Iw2 ++20qRTXPXQPDpojBBZO6wjF2gDac1orASVLgs5ty5wq1GUdNJ08X5hdHEJBhjLFq +c/T1OLxYSMmMqDQ1pqYsYA== +-----END PRIVATE KEY----- diff --git a/optee/optee_test/ta/miss/Android.mk b/optee/optee_test/ta/miss/Android.mk new file mode 100644 index 0000000..234434d --- /dev/null +++ b/optee/optee_test/ta/miss/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 528938ce-fc59-11e8-8eb2-f2801f1b9fd1.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/miss/Makefile b/optee/optee_test/ta/miss/Makefile new file mode 100644 index 0000000..34fb718 --- /dev/null +++ b/optee/optee_test/ta/miss/Makefile @@ -0,0 +1,2 @@ +BINARY = 528938ce-fc59-11e8-8eb2-f2801f1b9fd1 +include ../ta_common.mk diff --git a/optee/optee_test/ta/miss/include/ta_miss_test.h b/optee/optee_test/ta/miss/include/ta_miss_test.h new file mode 100644 index 0000000..07d1a3d --- /dev/null +++ b/optee/optee_test/ta/miss/include/ta_miss_test.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2019, Mentor Graphics Corporation + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef TA_MISS_TEST_H +#define TA_MISS_TEST_H + +/* This UUID is generated with uuidgen */ +#define TA_MISS_TEST_UUID { 0x528938ce, 0xfc59, 0x11e8, \ + { 0x8e, 0xb2, 0xf2, 0x80, 0x1f, 0x1b, 0x9f, 0xd1 } } + +#endif /* TA_MISS_TEST_H */ diff --git a/optee/optee_test/ta/miss/include/user_ta_header_defines.h b/optee/optee_test/ta/miss/include/user_ta_header_defines.h new file mode 100644 index 0000000..73d0522 --- /dev/null +++ b/optee/optee_test/ta/miss/include/user_ta_header_defines.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019, Mentor Graphics Corporation + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_NAME "MISS" +#define TA_UUID TA_MISS_TEST_UUID + +#define TA_FLAGS (0UL) +#define TA_STACK_SIZE (32 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/miss/sub.mk b/optee/optee_test/ta/miss/sub.mk new file mode 100644 index 0000000..695892f --- /dev/null +++ b/optee/optee_test/ta/miss/sub.mk @@ -0,0 +1,6 @@ +global-incdirs-y += include +global-incdirs-y += ../sims/include +global-incdirs-y += ../sims_keepalive/include + +srcs-y += ta_entry.c +srcs-y += ta_miss.c diff --git a/optee/optee_test/ta/miss/ta_entry.c b/optee/optee_test/ta/miss/ta_entry.c new file mode 100644 index 0000000..304d952 --- /dev/null +++ b/optee/optee_test/ta/miss/ta_entry.c @@ -0,0 +1 @@ +#include "../sims/ta_entry.c" diff --git a/optee/optee_test/ta/miss/ta_miss.c b/optee/optee_test/ta/miss/ta_miss.c new file mode 100644 index 0000000..5006c64 --- /dev/null +++ b/optee/optee_test/ta/miss/ta_miss.c @@ -0,0 +1 @@ +#include "../sims/ta_sims.c" diff --git a/optee/optee_test/ta/os_test/Android.mk b/optee/optee_test/ta/os_test/Android.mk new file mode 100644 index 0000000..39a82a3 --- /dev/null +++ b/optee/optee_test/ta/os_test/Android.mk @@ -0,0 +1,5 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 5b9e0e40-2636-11e1-ad9e-0002a5d5c51b.ta +local_module_deps := ffd2bded-ab7d-4988-95ee-e4962fff7154.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/os_test/Makefile b/optee/optee_test/ta/os_test/Makefile new file mode 100644 index 0000000..2190912 --- /dev/null +++ b/optee/optee_test/ta/os_test/Makefile @@ -0,0 +1,13 @@ +include $(TA_DEV_KIT_DIR)/mk/conf.mk + +BINARY = 5b9e0e40-2636-11e1-ad9e-0002a5d5c51b + +# Hack: to locate the os_test library, we assume that its output path +# follows the same scheme as the output path of the os_test application. +# Therefore, simply replacing os_test by os_test_lib in the absolute path +# should get us a valid path +LDADD = -L$(subst os_test,os_test_lib,$(abspath $(link-out-dir))) -los_test + +LDADD += -ldl + +include ../ta_common.mk diff --git a/optee/optee_test/ta/os_test/attestation.c b/optee/optee_test/ta/os_test/attestation.c new file mode 100644 index 0000000..521324c --- /dev/null +++ b/optee/optee_test/ta/os_test/attestation.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021, Huawei Technologies Co., Ltd + */ +#include +#include +#include + +#include "os_test.h" + +TEE_Result ta_entry_attestation(uint32_t param_types, TEE_Param params[4]) +{ + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + TEE_UUID att_uuid = PTA_ATTESTATION_UUID; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t ret_orig = 0; + + res = TEE_OpenTASession(&att_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, + &ret_orig); + if (res) + goto out; + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + PTA_ATTESTATION_HASH_TA_MEMORY, param_types, + params, &ret_orig); +out: + TEE_CloseTASession(sess); + return res; +} diff --git a/optee/optee_test/ta/os_test/cxx_tests.cpp b/optee/optee_test/ta/os_test/cxx_tests.cpp new file mode 100644 index 0000000..1761843 --- /dev/null +++ b/optee/optee_test/ta/os_test/cxx_tests.cpp @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020 Huawei Technologies Co., Ltd + */ + +extern "C" { + +#include +#include +#include +#include + +#include "cxx_tests.h" +#include "os_test.h" + +}; + +class CtorTest { +public: + CtorTest() : val(1) {} + + int val; +}; + +static CtorTest ctor_test; + +TEE_Result ta_entry_cxx_ctor_main(void) +{ + if (ctor_test.val != 1) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_cxx_ctor_shlib(void) +{ + return os_test_shlib_cxx_ctor(); +} + +TEE_Result ta_entry_cxx_ctor_shlib_dl(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Result (*ctor_test_fn)(void); + void *handle = NULL; + + handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba", + RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); + if (!handle) + return TEE_ERROR_GENERIC; + + ctor_test_fn = (TEE_Result (*)(void))dlsym(handle, + "os_test_shlib_dl_cxx_ctor"); + if (ctor_test_fn) + res = ctor_test_fn(); + + dlclose(handle); + return res; +} + +class MyException { +}; + +TEE_Result ta_entry_cxx_exc_main(void) +{ + try { + throw MyException(); + } catch (MyException &e) { + return TEE_SUCCESS; + } + + return TEE_ERROR_GENERIC; +} + +class MixedFrameException { +}; + +void throw_mfe(void) +{ + throw MixedFrameException(); +} + +class MixedFrameExceptionTest { +public: + MixedFrameExceptionTest() {} + + bool test(); +}; + +bool MixedFrameExceptionTest::test() +{ + try { + throwing_c_func(); + } catch (MixedFrameException e) { + return true; + } + return false; +} + +TEE_Result ta_entry_cxx_exc_mixed(void) +{ + MixedFrameExceptionTest test; + + if (test.test()) + return TEE_SUCCESS; + + return TEE_ERROR_GENERIC; +} diff --git a/optee/optee_test/ta/os_test/cxx_tests.h b/optee/optee_test/ta/os_test/cxx_tests.h new file mode 100644 index 0000000..a27c37e --- /dev/null +++ b/optee/optee_test/ta/os_test/cxx_tests.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2020 Huawei Technologies Co., Ltd + */ + +#ifndef CXX_TESTS_H +#define CXX_TESTS_H + +void throw_mfe(void); +void throwing_c_func(void); + +#endif /* CXX_TESTS_H */ diff --git a/optee/optee_test/ta/os_test/cxx_tests_c.c b/optee/optee_test/ta/os_test/cxx_tests_c.c new file mode 100644 index 0000000..2e3d0a9 --- /dev/null +++ b/optee/optee_test/ta/os_test/cxx_tests_c.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020 Huawei Technologies Co., Ltd + */ + +#include "cxx_tests.h" + +void throwing_c_func(void) +{ + throw_mfe(); +} diff --git a/optee/optee_test/ta/os_test/include/init.h b/optee/optee_test/ta/os_test/include/init.h new file mode 100644 index 0000000..0401f61 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/init.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef INIT_H +#define INIT_H + +#include + +TEE_Result ta_entry_init(uint32_t param_types, TEE_Param params[4]); + +#endif diff --git a/optee/optee_test/ta/os_test/include/os_test.h b/optee/optee_test/ta/os_test/include/os_test.h new file mode 100644 index 0000000..a3defc8 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/os_test.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef OS_TEST_H +#define OS_TEST_H + +#include + +TEE_Result ta_entry_basic(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_client_with_timeout(uint32_t param_types, + TEE_Param params[4]); +TEE_Result ta_entry_panic(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_client(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_params_access_rights(uint32_t p_types, TEE_Param params[4]); +TEE_Result ta_entry_wait(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_bad_mem_access(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_ta2ta_memref(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_ta2ta_memref_mix(uint32_t param_types, + TEE_Param params[4]); +TEE_Result ta_entry_params(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_null_memref(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_call_lib(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_call_lib_panic(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_call_lib_dl(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_call_lib_dl_panic(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_get_global_var(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_client_identity(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_tls_test_main(void); +TEE_Result ta_entry_tls_test_shlib(void); +TEE_Result ta_entry_dl_phdr(void); +TEE_Result ta_entry_dl_phdr_dl(void); +TEE_Result ta_entry_cxx_ctor_main(void); +TEE_Result ta_entry_cxx_ctor_shlib(void); +TEE_Result ta_entry_cxx_ctor_shlib_dl(void); +TEE_Result ta_entry_cxx_exc_main(void); +TEE_Result ta_entry_cxx_exc_mixed(void); +TEE_Result ta_entry_pauth_test_nop(void); +TEE_Result ta_entry_pauth_corrupt_pac(void); +TEE_Result ta_entry_attestation(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_entry_memtag_use_after_free(void); +TEE_Result ta_entry_memtag_invalid_tag(void); +TEE_Result ta_entry_memtag_double_free(void); +TEE_Result ta_entry_memtag_buffer_overrun(void); + +#endif /*OS_TEST_H */ diff --git a/optee/optee_test/ta/os_test/include/ta_os_test.h b/optee/optee_test/ta/os_test/include/ta_os_test.h new file mode 100644 index 0000000..95edcd9 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/ta_os_test.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef TA_OS_TEST_H +#define TA_OS_TEST_H + +/* This UUID is generated with the ITU-T UUID generator at + http://www.itu.int/ITU-T/asn1/uuid.html */ +#define TA_OS_TEST_UUID { 0x5b9e0e40, 0x2636, 0x11e1, \ + { 0xad, 0x9e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } } + +#define TA_OS_TEST_CMD_INIT 0 +#define TA_OS_TEST_CMD_CLIENT_WITH_TIMEOUT 1 +#define TA_OS_TEST_CMD_BASIC 5 +#define TA_OS_TEST_CMD_PANIC 6 +#define TA_OS_TEST_CMD_CLIENT 7 +#define TA_OS_TEST_CMD_PARAMS_ACCESS 8 +#define TA_OS_TEST_CMD_WAIT 9 +#define TA_OS_TEST_CMD_BAD_MEM_ACCESS 10 +#define TA_OS_TEST_CMD_TA2TA_MEMREF 11 +#define TA_OS_TEST_CMD_TA2TA_MEMREF_MIX 12 +#define TA_OS_TEST_CMD_PARAMS 13 +#define TA_OS_TEST_CMD_CALL_LIB 14 +#define TA_OS_TEST_CMD_CALL_LIB_PANIC 15 +#define TA_OS_TEST_CMD_CALL_LIB_DL 16 +#define TA_OS_TEST_CMD_CALL_LIB_DL_PANIC 17 +#define TA_OS_TEST_CMD_GET_GLOBAL_VAR 18 +#define TA_OS_TEST_CMD_NULL_MEMREF_PARAMS 19 +#define TA_OS_TEST_CMD_CLIENT_IDENTITY 20 +#define TA_OS_TEST_CMD_TLS_TEST_MAIN 21 +#define TA_OS_TEST_CMD_TLS_TEST_SHLIB 22 +#define TA_OS_TEST_CMD_DL_PHDR 23 +#define TA_OS_TEST_CMD_DL_PHDR_DL 24 +#define TA_OS_TEST_CMD_CXX_CTOR_MAIN 25 +#define TA_OS_TEST_CMD_CXX_CTOR_SHLIB 26 +#define TA_OS_TEST_CMD_CXX_CTOR_SHLIB_DL 27 +#define TA_OS_TEST_CMD_CXX_EXC_MAIN 28 +#define TA_OS_TEST_CMD_CXX_EXC_MIXED 29 +#define TA_OS_TEST_CMD_PAUTH_NOP 30 +#define TA_OS_TEST_CMD_PAUTH_CORRUPT_PAC 31 +#define TA_OS_TEST_CMD_ATTESTATION 32 +#define TA_OS_TEST_CMD_MEMTAG_USE_AFTER_FREE 33 +#define TA_OS_TEST_CMD_MEMTAG_INVALID_TAG 34 +#define TA_OS_TEST_CMD_MEMTAG_DOUBLE_FREE 35 +#define TA_OS_TEST_CMD_MEMTAG_BUFFER_OVERRUN 36 + +#endif /*TA_OS_TEST_H */ diff --git a/optee/optee_test/ta/os_test/include/tb_asserts.h b/optee/optee_test/ta/os_test/include/tb_asserts.h new file mode 100644 index 0000000..de476b9 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/tb_asserts.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef TB_ASSERTS_H +#define TB_ASSERTS_H + +#include +#include "tb_macros.h" + +/* + * TB_ASSERT_MSG general assert function with a message. + */ +#define TB_ASSERT_MSG(cond, str) \ +do { \ + if (!(cond)) { \ + EMSG("Assertion failed at line %d in file:\n%s\n", \ + __LINE__, __FILE__); \ + EMSG("Message: %s\n", str); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT general assert function. + */ +#define TB_ASSERT(cond) \ +do { \ + if (!(cond)) { \ + EMSG("Assertion failed at line %d in file:\n%s\n", \ + __LINE__, __FILE__); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_EQ_SHORT checks that src equals the short value. + */ +#define TB_ASSERT_EQ_SHORT(src, short) \ +do { \ + if (((short) == 0) && (__mpanum_size((mpanum)src) != 0)) { \ + EMSG("Assertion failed at line %d in file:\n%s\n", \ + __LINE__, __FILE__); \ + EMSG("short == 0, but size != 0\n"); \ + HALT; \ + } else if (__mpanum_size((mpanum)src) > 1) { \ + EMSG("Assertion failed at line %d in file:\n%s\n", \ + __LINE__, __FILE__); \ + EMSG("size > 1, cannot be equal to a short.\n"); \ + HALT; \ + } else if ( \ + (int)(__mpanum_lsw((mpanum)src)*__mpanum_sign((mpanum)src)) != \ + (int)(short)) { \ + EMSG("Assertion failed at line %d in file:\n%s\n", \ + __LINE__, __FILE__); \ + EMSG("short == %d, but src == %d\n", (short), \ + (int)(__mpanum_lsw((mpanum)src) \ + *__mpanum_sign((mpanum)src))); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_STR_EQ checks that the two strings a and b are equal. + */ +#define TB_ASSERT_STR_EQ(a, b) \ +do { \ + if (my_strcmp((a), (b)) != 0) { \ + EMSG("Assertion failed %s != %s\n", (a), (b)); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_HEX_VALUE checks that a prints to the string v in hex. + */ +#define TB_ASSERT_HEX_PRINT_VALUE(a, v) \ +do { \ + char *_str_; \ + _str_ = TEE_BigIntConvertToString(NULL, \ + TEE_STRING_MODE_HEX_UC, (a)); \ + TB_ASSERT_STR_EQ(_str_, (v)); \ + TEE_Free(_str_); \ +} while (0) + +/* + * TB_ASSERT_POINTER_NULL(p) checks that p is null + */ +#define TB_ASSERT_POINTER_NULL(p) \ +do { \ + if ((p) != 0) { \ + EMSG("Assertion failed, pointer was not null.\n"); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_POINTERS_EQ checks that p, q are pointing to the same element + */ +#define TB_ASSERT_POINTERS_EQ(p, q) \ +do { \ + if ((p) != (q)) { \ + EMSG("Assertion failed, pointers are not equal.\n"); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_POINTERS_NEQ checks that p, q are not pointing to the same element + */ +#define TB_ASSERT_POINTERS_NEQ(p, q) \ +do { \ + if ((p) == (q)) { \ + EMSG("Assertion failed, pointers are equal.\n"); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_BIGINT_EQ Checks that a and b are equal + */ +#define TB_ASSERT_BIGINT_EQ(a, b) \ +do { \ + if (TEE_BigIntCmp((a), (b)) != 0) { \ + EMSG("Assertion failed, numbers are not equal.\n"); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_BIGINT_NEQ Checks that a and b are different + */ +#define TB_ASSERT_BIGINT_NEQ(a, b) \ +do { \ + if (TEE_BigIntCmp((a), (b)) == 0) { \ + EMSG("Assertion failed, numbers are equal.\n"); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_BIGINT_LESS Checks that a < b + */ +#define TB_ASSERT_BIGINT_LESS(a, b) \ +do { \ + if (TEE_BigIntCmp((a), (b)) >= 0) { \ + EMSG("Assertion failed, first is not less than second.\n"); \ + HALT; \ + }; \ +} while (0) + +/* + * TB_ASSERT_INT_EQ Checks that a and be are equal + */ +#define TB_ASSERT_INT_EQ(a, b) \ +do { \ + if ((a) != (b)) { \ + EMSG("Assertion failed, numbers are not equal.\n"); \ + HALT; \ + }; \ +} while (0) + +#endif diff --git a/optee/optee_test/ta/os_test/include/tb_macros.h b/optee/optee_test/ta/os_test/include/tb_macros.h new file mode 100644 index 0000000..cd7f0b9 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/tb_macros.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ +#ifndef TB_MACROS_H +#define TB_MACROS_H + +#include + +#define TB_HEADER(str) \ + printf("\n*********** TESTBENCH ***********" \ + "\n*** RUNNING: <<< %s >>>" \ + "\n*********************************\n\n", str) + +#define TB_FOOTER(str) \ + printf("\n*********** TESTBENCH ***********" \ + "\n*** PASSED: <<< %s >>>" \ + "\n*********************************\n\n", str) + +#define TB_INFO(str) printf("*** INFO : %s \n", (str)) + +#define HALT \ + { \ + printf("\n*** FAILED ***" \ + "\nTestbench halted at line %d in function %s\n", \ + __LINE__, __func__); \ + printf("\nWaiting for keypress to enable debugging.\n"); \ + TEE_Panic(0); \ + } + +#define STARTING \ + printf("\n*********** TESTBENCH ***********" \ + "\n*** For the GlobalPlatform Math API" \ + "\n*********************************\n\n") + +#define ALL_PASSED \ + printf("\n*********** TESTBENCH ***********" \ + "\n*** ALL TESTS PASSED ***" \ + "\n*********************************\n\n") + +/* + * DEF_BIGINT defines and initialize a BigInt with name and size. + */ +#define DEF_BIGINT(name, size) \ + TEE_BigInt *name; \ + size_t name##_size; \ + name##_size = TEE_BigIntSizeInU32(size); \ + name = (TEE_BigInt *)TEE_Malloc(name##_size * sizeof(TEE_BigInt), 0); \ + TEE_BigIntInit(name, name##_size) + +/* + * DEL_BIGINT frees the BigInt. + */ +#define DEL_BIGINT(name) TEE_Free(name) + +/* + * TB_PRINT_BIGINT prints the mpanum in base 16. + */ +#define TB_PRINT_BIGINT(n) \ +do { \ + char *str; \ + str = TEE_BigIntConvertToString(NULL, TEE_STRING_MODE_HEX_UC, 0, (n)); \ + printf("%s\n", str); \ + TEE_Free(str); \ +} while (0) + +#endif diff --git a/optee/optee_test/ta/os_test/include/testframework.h b/optee/optee_test/ta/os_test/include/testframework.h new file mode 100644 index 0000000..00f383b --- /dev/null +++ b/optee/optee_test/ta/os_test/include/testframework.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef GUARD_testframework_H +#define GUARD_testframework_H + +#include "tee_internal_api.h" + +#include "tee_arith_internal.h" + +#include "tb_macros.h" +#include "tb_asserts.h" + +/* define the max size of generated numbers */ +/* this is number of hex chars in the number */ +#define MAX_RAND_DIGITS 256 +#define MAX_RAND_STRING_SIZE (MAX_RAND_DIGITS + 2) + +size_t my_strlen(const char *string); +int my_strcmp(const char *s1, const char *s2); +size_t my_strlcpy(char *dst, const char *src, size_t siz); + +void tb_set_random_value(TEE_BigInt *a, char *str, int allow_neg); +void tb_get_random_str(char *str, int allow_neg); + +void tb_main(void); + +void tb_var(void); +void tb_conv(void); +void tb_cmp(void); +void tb_addsub(void); +void tb_mul(void); +void tb_shift(void); +void tb_div(void); +void tb_gcd(void); +void tb_modulus(void); +void tb_fmm(void); +void tb_prime(void); + +int TEE_BigIntConvertFromString(TEE_BigInt *dest, const char *src); +char *TEE_BigIntConvertToString(char *dest, int mode, const TEE_BigInt *src); + +#endif /* include guard */ diff --git a/optee/optee_test/ta/os_test/include/user_ta_header_defines.h b/optee/optee_test/ta/os_test/include/user_ta_header_defines.h new file mode 100644 index 0000000..36709e0 --- /dev/null +++ b/optee/optee_test/ta/os_test/include/user_ta_header_defines.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include +#include + +#define TA_UUID TA_OS_TEST_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \ + TA_FLAG_MULTI_SESSION) + +#define TA_STACK_SIZE (8 * 1024) +#define TA_DATA_SIZE (900 * 1024) + +#define TA_CURRENT_TA_EXT_PROPERTIES \ + { "myprop.true", USER_TA_PROP_TYPE_BOOL, &(const bool){ true } }, \ + { "myprop.42", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 42 } }, \ + { "myprop.123", USER_TA_PROP_TYPE_UUID, \ + &(const TEE_UUID) {1, 2, 3 } }, \ + { "myprop.1234", USER_TA_PROP_TYPE_IDENTITY, \ + &(const TEE_Identity) { 1, { 2, 3, 4 } } }, \ + { "myprop.hello", USER_TA_PROP_TYPE_STRING, \ + "hello property, larger than 80 characters, so that it checks that it is not truncated by anything in the source code which may be wrong" }, \ + { "myprop.binaryblock", USER_TA_PROP_TYPE_BINARY_BLOCK, \ + "SGVsbG8gd29ybGQh" }, \ + { "myprop.binaryblock.1byte-ones", USER_TA_PROP_TYPE_BINARY_BLOCK, \ + "/w==" }, \ + { "myprop.binaryblock.2byte-ones", USER_TA_PROP_TYPE_BINARY_BLOCK, \ + "//8=" }, \ + { "myprop.binaryblock.3byte-ones", USER_TA_PROP_TYPE_BINARY_BLOCK, \ + "////" }, \ + { "myprop.binaryblock.4byte-ones", USER_TA_PROP_TYPE_BINARY_BLOCK, \ + "/////w==" }, \ + { "myprop.binaryblock.empty1", USER_TA_PROP_TYPE_BINARY_BLOCK, \ + "" }, \ + { "myprop.binaryblock.empty2", USER_TA_PROP_TYPE_BINARY_BLOCK, \ + "====" }, \ + { "myprop.binaryblock.empty3", USER_TA_PROP_TYPE_BINARY_BLOCK, \ + "-%@&" /* Only invalid code */}, +#endif diff --git a/optee/optee_test/ta/os_test/init.c b/optee/optee_test/ta/os_test/init.c new file mode 100644 index 0000000..1ca413f --- /dev/null +++ b/optee/optee_test/ta/os_test/init.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ +#include +#include +#include + +TEE_Result ta_entry_init(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Time date; + (void)param_types; + (void)params; + + return TEE_GetTAPersistentTime(&date); +} diff --git a/optee/optee_test/ta/os_test/os_test.c b/optee/optee_test/ta/os_test/os_test.c new file mode 100644 index 0000000..134ad22 --- /dev/null +++ b/optee/optee_test/ta/os_test/os_test.c @@ -0,0 +1,1575 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * Copyright (c) 2022, Linaro Limited. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os_test.h" +#include "test_float_subj.h" +#include "os_test_lib.h" + +#define STATS_UUID \ + { 0xd96a5b40, 0xe2c7, 0xb1af, \ + { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } + +#define STATS_CMD_PAGER_STATS 0 + +#define PAGER_PAGE_COUNT_THRESHOLD ((128 * 1024) / 4096) + +enum p_type { + P_TYPE_BOOL, + P_TYPE_INT, + P_TYPE_UUID, + P_TYPE_IDENTITY, + P_TYPE_STRING, + P_TYPE_BINARY_BLOCK, +}; + +struct p_attr { + const char *str; + enum p_type type; + bool retrieved; +}; + +static TEE_Result check_returned_prop( + int line __maybe_unused, char *prop_name __maybe_unused, + TEE_Result return_res, TEE_Result expected_res, + uint32_t return_len, uint32_t expected_len) +{ + if (return_res != expected_res) { + EMSG("From line %d (property name=%s): return_res=0x%x vs expected_res=0x%x", + line, (prop_name ? prop_name : "unknown"), + (unsigned int)return_res, (unsigned int)expected_res); + return TEE_ERROR_GENERIC; + } + if (return_len != expected_len) { + EMSG("From line %d (property name=%s): return_len=%u vs expected_res=%u", + line, (prop_name ? prop_name : "unknown"), + return_len, expected_len); + return TEE_ERROR_GENERIC; + } + return TEE_SUCCESS; +} + +static TEE_Result check_binprop_ones(size_t size, char *bbuf, size_t bblen) +{ + char ones[4] = { 0xff, 0xff, 0xff, 0xff }; + + if (size > 4 || bblen != size) { + EMSG("Size error (size=%zu, bblen=%zu)", size, bblen); + return TEE_ERROR_GENERIC; + } + if (strncmp(bbuf, ones, bblen)) { + EMSG("Unexpected content"); + DHEXDUMP(bbuf, bblen); + return TEE_ERROR_GENERIC; + } + return TEE_SUCCESS; +} + +static TEE_Result get_binblock_property(TEE_PropSetHandle h, + char *nbuf __unused, char **bbuf, size_t *bblen) +{ + TEE_Result res = TEE_ERROR_GENERIC; + size_t block_len = 0; + + *bbuf = NULL; + *bblen = 0; + res = TEE_GetPropertyAsBinaryBlock(h, NULL, *bbuf, &block_len); + + if (res == TEE_SUCCESS && !block_len) + return TEE_SUCCESS; + + if (res != TEE_ERROR_SHORT_BUFFER) { + EMSG("TEE_GetPropertyAsBinaryBlock() size query returned 0x%x", + (unsigned int)res); + return res ? res : TEE_ERROR_GENERIC; + } + + *bbuf = TEE_Malloc(block_len, TEE_MALLOC_FILL_ZERO); + if (!bbuf) + return TEE_ERROR_OUT_OF_MEMORY; + + res = TEE_GetPropertyAsBinaryBlock(h, NULL, *bbuf, &block_len); + if (res != TEE_SUCCESS) + EMSG("TEE_GetPropertyAsBinaryBlock(\"%s\") returned 0x%x", + nbuf, (unsigned int)res); + else + *bblen = block_len; + + return res; +} + +static TEE_Result print_properties(TEE_PropSetHandle h, + TEE_PropSetHandle prop_set, + struct p_attr *p_attrs, size_t num_p_attrs) +{ +TEE_Result res = TEE_ERROR_GENERIC; +size_t n = 0; + +TEE_StartPropertyEnumerator(h, prop_set); + +while (true) { + char nbuf[256] = { }; + char nbuf_small[256] = { }; + char vbuf[256] = { }; + char vbuf2[256] = { }; + size_t nblen = sizeof(nbuf); + size_t nblen_small = 0; + size_t vblen = sizeof(vbuf); + size_t vblen2 = sizeof(vbuf2); + char *bbuf = NULL; + size_t bblen = 0; + + res = TEE_GetPropertyName(h, nbuf, &nblen); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetPropertyName returned 0x%x\n", + (unsigned int)res); + return res; + } + if (nblen != strlen(nbuf) + 1) { + EMSG("Name has wrong size: %zu vs %zu", + nblen, strlen(nbuf) + 1); + return TEE_ERROR_GENERIC; + } + + + /* Get the property name with a very small buffer */ + nblen_small = 2; + res = TEE_GetPropertyName(h, nbuf_small, &nblen_small); + res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER, + nblen_small, nblen); + if (res != TEE_SUCCESS) + return res; + + /* Get the property name with almost the correct buffer */ + nblen_small = nblen - 1; + res = TEE_GetPropertyName(h, nbuf_small, &nblen_small); + res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER, + nblen_small, nblen); + if (res != TEE_SUCCESS) + return res; + + /* Get the property name with the exact buffer length */ + nblen_small = nblen; + res = TEE_GetPropertyName(h, nbuf_small, &nblen_small); + res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS, + nblen_small, nblen); + if (res != TEE_SUCCESS) + return res; + + /* Get the property value */ + res = TEE_GetPropertyAsString(h, NULL, vbuf, &vblen); + res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS, + vblen, strlen(vbuf) + 1); + if (res != TEE_SUCCESS) + return res; + + res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2); + res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS, + vblen2, strlen(vbuf2) + 1); + if (res != TEE_SUCCESS) + return res; + + if (strcmp(vbuf, vbuf2) != 0) { + EMSG("String of \"%s\" differs\n", nbuf); + return TEE_ERROR_GENERIC; + } + + /* Get the property with a very small buffer */ + if (vblen > 1) { + vblen2 = 1; + res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2); + res = check_returned_prop(__LINE__, nbuf, res, + TEE_ERROR_SHORT_BUFFER, + vblen2, vblen); + if (res != TEE_SUCCESS) + return res; + } + + /* Get the property with almost the correct buffer */ + vblen2 = vblen - 1; + res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2); + res = check_returned_prop(__LINE__, nbuf, res, TEE_ERROR_SHORT_BUFFER, + vblen2, vblen); + if (res != TEE_SUCCESS) + return res; + + /* Get the property name with the exact buffer length */ + vblen2 = vblen; + res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2); + res = check_returned_prop(__LINE__, nbuf, res, TEE_SUCCESS, vblen2, vblen); + if (res != TEE_SUCCESS) + return res; + + /* check specific myprop.hello property, which is larger than 80 */ + if (!strcmp("myprop.hello", nbuf) && + vblen2 != 1 + strlen("hello property, larger than 80 characters, so that it checks that it is not truncated by anything in the source code which may be wrong")) { + EMSG("TEE_GetPropertyAsString(\"%s\") is truncated - returned \"%s\"\n", + nbuf, vbuf); + return TEE_ERROR_GENERIC; + } + + DMSG("Found \"%s\" value \"%s\"\n", nbuf, vbuf); + + for (n = 0; n < num_p_attrs; n++) { + if (strcmp(nbuf, p_attrs[n].str) != 0) + continue; + + if (p_attrs[n].retrieved) { + EMSG("Value \"%s\" already retrieved\n", + p_attrs[n].str); + return TEE_ERROR_GENERIC; + } + p_attrs[n].retrieved = true; + + switch (p_attrs[n].type) { + case P_TYPE_BOOL: + { + bool v = false; + + res = + TEE_GetPropertyAsBool(h, NULL, &v); + if (res != TEE_SUCCESS) { + EMSG( + "TEE_GetPropertyAsBool(\"%s\") returned 0x%x\n", + nbuf, (unsigned int)res); + return res; + } + } + break; + + case P_TYPE_INT: + { + uint32_t v = 0; + + res = TEE_GetPropertyAsU32(h, NULL, &v); + if (res != TEE_SUCCESS) { + EMSG( + "TEE_GetPropertyAsU32(\"%s\") returned 0x%x\n", + nbuf, (unsigned int)res); + return res; + } + } + break; + + case P_TYPE_UUID: + { + TEE_UUID v = { }; + + res = + TEE_GetPropertyAsUUID(h, NULL, &v); + if (res != TEE_SUCCESS) { + EMSG( + "TEE_GetPropertyAsUUID(\"%s\") returned 0x%x\n", + nbuf, (unsigned int)res); + return res; + } + } + break; + + case P_TYPE_IDENTITY: + { + TEE_Identity v = { }; + + res = + TEE_GetPropertyAsIdentity(h, NULL, + &v); + if (res != TEE_SUCCESS) { + EMSG( + "TEE_GetPropertyAsIdentity(\"%s\") returned 0x%x\n", + nbuf, (unsigned int)res); + return res; + } + } + break; + + case P_TYPE_STRING: + /* Already read as string */ + break; + + case P_TYPE_BINARY_BLOCK: + res = get_binblock_property(h, nbuf, &bbuf, &bblen); + if (res) + return res; + + if (!strcmp("myprop.binaryblock", nbuf)) { + const char exp_bin_value[] = "Hello world!"; + + if (bblen != strlen(exp_bin_value) || + TEE_MemCompare(exp_bin_value, bbuf, + bblen)) { + EMSG("Binary buffer of \"%s\" differs from \"%s\"", + nbuf, exp_bin_value); + EMSG("Got \"%s\"", bbuf); + return TEE_ERROR_GENERIC; + } + } else if (!strcmp("myprop.binaryblock.1byte-ones", + nbuf)) { + res = check_binprop_ones(1, bbuf, bblen); + if (res) + return res; + } else if (!strcmp("myprop.binaryblock.2byte-ones", + nbuf)) { + res = check_binprop_ones(2, bbuf, bblen); + if (res) + return res; + } else if (!strcmp("myprop.binaryblock.3byte-ones", + nbuf)) { + res = check_binprop_ones(3, bbuf, bblen); + if (res) + return res; + } else if (!strcmp("myprop.binaryblock.4byte-ones", + nbuf)) { + res = check_binprop_ones(4, bbuf, bblen); + if (res) + return res; + } else if (!strcmp("myprop.binaryblock.empty1", nbuf) || + !strcmp("myprop.binaryblock.empty2", nbuf) || + !strcmp("myprop.binaryblock.empty3", nbuf)) { + if (bblen) { + EMSG("Property \"%s\": %zu byte(s)", + nbuf, bblen); + return TEE_ERROR_GENERIC; + } + } else { + EMSG("Unexpected property \"%s\"", nbuf); + TEE_Panic(0); + } + + TEE_Free(bbuf); + break; + + default: + EMSG("Unknown type (%d) for \"%s\"\n", + p_attrs[n].type, p_attrs[n].str); + return TEE_ERROR_GENERIC; + } + } + + res = TEE_GetNextProperty(h); + if (res != TEE_SUCCESS) { + if (res == TEE_ERROR_ITEM_NOT_FOUND) + return TEE_SUCCESS; + return res; + } +} +} + +static TEE_Result test_malloc(void) +{ + void *p = TEE_Malloc(4, 0); + + if (p == NULL) { + EMSG("TEE_Malloc failed\n"); + return TEE_ERROR_OUT_OF_MEMORY; + } + TEE_Free(p); + TEE_Free(NULL); + + return TEE_SUCCESS; +} + +static TEE_Result test_properties(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_PropSetHandle h = TEE_HANDLE_NULL; + struct p_attr p_attrs[] = { + {"gpd.ta.appID", P_TYPE_UUID}, + {"gpd.ta.singleInstance", P_TYPE_BOOL}, + {"gpd.ta.multiSession", P_TYPE_BOOL}, + {"gpd.ta.instanceKeepAlive", P_TYPE_BOOL}, + {"gpd.ta.dataSize", P_TYPE_INT}, + {"gpd.ta.stackSize", P_TYPE_INT}, + {"gpd.ta.version", P_TYPE_STRING}, + {"gpd.ta.description", P_TYPE_STRING}, + {"gpd.client.identity", P_TYPE_IDENTITY}, + {"gpd.tee.apiversion", P_TYPE_STRING}, + {"gpd.tee.description", P_TYPE_STRING}, + {"gpd.tee.deviceID", P_TYPE_UUID}, + {"gpd.tee.systemTime.protectionLevel", P_TYPE_INT}, + {"gpd.tee.TAPersistentTime.protectionLevel", P_TYPE_INT}, + {"gpd.tee.arith.maxBigIntSize", P_TYPE_INT}, + {"gpd.tee.cryptography.ecc", P_TYPE_BOOL}, + {"gpd.tee.trustedStorage.antiRollback.protectionLevel", P_TYPE_INT}, + {"gpd.tee.trustedos.implementation.version", P_TYPE_STRING}, + {"gpd.tee.trustedos.implementation.binaryversion", P_TYPE_INT}, + {"gpd.tee.trustedos.manufacturer", P_TYPE_STRING}, + {"gpd.tee.firmware.implementation.version", P_TYPE_STRING}, + {"gpd.tee.firmware.implementation.binaryversion", P_TYPE_INT}, + {"gpd.tee.firmware.manufacturer", P_TYPE_STRING}, + {"myprop.true", P_TYPE_BOOL}, + {"myprop.42", P_TYPE_INT}, + {"myprop.123", P_TYPE_UUID}, + {"myprop.1234", P_TYPE_IDENTITY}, + {"myprop.hello", P_TYPE_STRING}, + {"myprop.binaryblock", P_TYPE_BINARY_BLOCK}, + {"myprop.binaryblock.1byte-ones", P_TYPE_BINARY_BLOCK}, + {"myprop.binaryblock.2byte-ones", P_TYPE_BINARY_BLOCK}, + {"myprop.binaryblock.3byte-ones", P_TYPE_BINARY_BLOCK}, + {"myprop.binaryblock.4byte-ones", P_TYPE_BINARY_BLOCK}, + {"myprop.binaryblock.empty1", P_TYPE_BINARY_BLOCK}, + {"myprop.binaryblock.empty2", P_TYPE_BINARY_BLOCK}, + {"myprop.binaryblock.empty3", P_TYPE_BINARY_BLOCK}, + }; + const size_t num_p_attrs = sizeof(p_attrs) / sizeof(p_attrs[0]); + size_t n = 0; + + res = TEE_AllocatePropertyEnumerator(&h); + if (res != TEE_SUCCESS) { + EMSG("TEE_AllocatePropertyEnumerator: returned 0x%x\n", + (unsigned int)res); + return TEE_ERROR_GENERIC; + } + + printf("Getting properties for current TA\n"); + res = print_properties(h, TEE_PROPSET_CURRENT_TA, p_attrs, num_p_attrs); + if (res != TEE_SUCCESS) + goto cleanup_return; + + printf("Getting properties for current client\n"); + res = print_properties(h, TEE_PROPSET_CURRENT_CLIENT, p_attrs, + num_p_attrs); + if (res != TEE_SUCCESS) + goto cleanup_return; + + printf("Getting properties for implementation\n"); + res = print_properties(h, TEE_PROPSET_TEE_IMPLEMENTATION, p_attrs, + num_p_attrs); + if (res != TEE_SUCCESS) + goto cleanup_return; + + for (n = 0; n < num_p_attrs; n++) { + if (!p_attrs[n].retrieved) { + EMSG("\"%s\" not retrieved\n", p_attrs[n].str); + res = TEE_ERROR_GENERIC; + goto cleanup_return; + } + } + +cleanup_return: + TEE_FreePropertyEnumerator(h); + return res; +} + +static TEE_Result test_mem_access_right(uint32_t param_types, + TEE_Param params[4]) +{ + static const TEE_UUID test_uuid = TA_OS_TEST_UUID; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t ret_orig = 0; + uint32_t l_pts = 0; + TEE_Param l_params[4] = { }; + uint8_t buf[32] = { }; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + TEE_UUID *uuid = NULL; + + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0)) + return TEE_ERROR_GENERIC; + + /* test access rights on memref parameter */ + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + params[0].memref.buffer, + params[0].memref.size); + if (res != TEE_SUCCESS) + return res; + + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ, + params[0].memref.buffer, + params[0].memref.size); + if (res != TEE_ERROR_ACCESS_DENIED) + return TEE_ERROR_GENERIC; + + /* test access rights on private read-only and read-write memory */ + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ, + (void *)&test_uuid, sizeof(test_uuid)); + if (res != TEE_SUCCESS) + return res; + + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_WRITE, + (void *)&test_uuid, sizeof(test_uuid)); + if (res == TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE, + &ret_orig, sizeof(ret_orig)); + if (res != TEE_SUCCESS) + return res; + + uuid = TEE_Malloc(sizeof(*uuid), 0); + if (!uuid) + return TEE_ERROR_OUT_OF_MEMORY; + + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE, + uuid, sizeof(*uuid)); + TEE_Free(uuid); + if (res != TEE_SUCCESS) + return res; + + /* test access rights on invalid memory (at least lower 256kB) */ + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ, + NULL, 1); + if (res == TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ, + (void*)(256 * 1024), 1); + if (res == TEE_SUCCESS) + return TEE_ERROR_GENERIC; + + res = TEE_OpenTASession(&test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("test_mem_access_right: TEE_OpenTASession failed\n"); + goto cleanup_return; + } + + l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0); + l_params[0].memref.buffer = buf; + l_params[0].memref.size = sizeof(buf); + l_params[1].memref.buffer = NULL; + l_params[1].memref.size = 0; + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + TA_OS_TEST_CMD_PARAMS_ACCESS, + l_pts, l_params, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("test_mem_access_right: TEE_InvokeTACommand failed\n"); + goto cleanup_return; + } + +cleanup_return: + TEE_CloseTASession(sess); + return res; +} + +static TEE_Result test_time(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Time t = { }; + TEE_Time sys_t = { }; + static const TEE_Time null_time = { 0, 0 }; + static const TEE_Time wrap_time = { UINT32_MAX, 999 }; + + TEE_GetSystemTime(&sys_t); + printf("system time %u.%03u\n", (unsigned int)sys_t.seconds, + (unsigned int)sys_t.millis); + + TEE_GetREETime(&t); + printf("REE time %u.%03u\n", (unsigned int)t.seconds, + (unsigned int)t.millis); + + res = TEE_GetTAPersistentTime(&t); + switch (res) { + case TEE_SUCCESS: + printf("Stored TA time %u.%03u\n", (unsigned int)t.seconds, + (unsigned int)t.millis); + break; + case TEE_ERROR_OVERFLOW: + EMSG("Stored TA time overflowed %u.%03u\n", + (unsigned int)t.seconds, (unsigned int)t.millis); + break; + case TEE_ERROR_TIME_NOT_SET: + EMSG("TA time not stored\n"); + break; + case TEE_ERROR_TIME_NEEDS_RESET: + EMSG("TA time needs reset\n"); + break; + default: + return res; + } + + res = TEE_SetTAPersistentTime(&null_time); + if (res != TEE_SUCCESS) { + EMSG("TEE_SetTAPersistentTime: failed\n"); + return res; + } + + res = TEE_GetTAPersistentTime(&t); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetTAPersistentTime null: failed\n"); + return res; + } + printf("TA time %u.%03u\n", (unsigned int)t.seconds, + (unsigned int)t.millis); + /* + * The time between TEE_SetTAPersistentTime() and + * TEE_GetTAPersistentTime() should be much less than 1 second, in fact + * it's not even a millisecond. + */ + if (t.seconds > 1 || t.millis >= 1000) { + EMSG("Unexpected stored TA time %u.%03u\n", + (unsigned int)t.seconds, (unsigned int)t.millis); + return TEE_ERROR_BAD_STATE; + } + + res = TEE_SetTAPersistentTime(&wrap_time); + if (res != TEE_SUCCESS) { + EMSG("TEE_SetTAPersistentTime wrap: failed\n"); + return res; + } + + res = TEE_Wait(1000); + if (res != TEE_SUCCESS) + EMSG("TEE_Wait wrap: failed\n"); + + res = TEE_GetTAPersistentTime(&t); + if (res != TEE_ERROR_OVERFLOW) { + EMSG("TEE_GetTAPersistentTime: failed\n"); + return TEE_ERROR_BAD_STATE; + } + printf("TA time %u.%03u\n", (unsigned int)t.seconds, + (unsigned int)t.millis); + + if (t.seconds > sys_t.seconds) { + EMSG("Unexpected wrapped time %u.%03u (sys_t %u.%03u)\n", + (unsigned int)t.seconds, (unsigned int)t.millis, + (unsigned int)sys_t.seconds, (unsigned int)sys_t.millis); + return TEE_ERROR_BAD_STATE; + } + + return TEE_SUCCESS; +} + +#ifdef CFG_TA_FLOAT_SUPPORT +static bool my_dcmpeq(double v1, double v2, double prec) +{ + return v1 > (v2 - prec) && v1 < (v2 + prec); +} + +static bool my_fcmpeq(float v1, float v2, float prec) +{ + return v1 > (v2 - prec) && v1 < (v2 + prec); +} + + +static TEE_Result test_float(void) +{ +#define VAL1 2.6 +#define VAL1_INT 2 +#define VAL2 5.3 +#define DPREC 0.000000000000001 +#define FPREC 0.000001 +#define EXPECT(expr) do { \ + if (!(expr)) { \ + EMSG("Expression %s failed", #expr); \ + return TEE_ERROR_GENERIC; \ + } \ + } while (0) + + IMSG("Testing floating point operations"); + + EXPECT(my_dcmpeq(test_float_dadd(VAL1, VAL2), VAL1 + VAL2, DPREC)); + EXPECT(my_dcmpeq(test_float_ddiv(VAL1, VAL2), VAL1 / VAL2, DPREC)); + EXPECT(my_dcmpeq(test_float_dmul(VAL1, VAL2), VAL1 * VAL2, DPREC)); + EXPECT(my_dcmpeq(test_float_drsub(VAL1, VAL2), VAL2 - VAL1, DPREC)); + EXPECT(my_dcmpeq(test_float_dsub(VAL1, VAL2), VAL1 - VAL2, DPREC)); + + EXPECT(test_float_dcmpeq(VAL1, VAL1) == 1); + EXPECT(test_float_dcmplt(VAL1, VAL2) == 1); + EXPECT(test_float_dcmple(VAL1, VAL1) == 1); + EXPECT(test_float_dcmpge(VAL1, VAL1) == 1); + EXPECT(test_float_dcmpgt(VAL2, VAL1) == 1); + + EXPECT(my_fcmpeq(test_float_fadd(VAL1, VAL2), VAL1 + VAL2, FPREC)); + EXPECT(my_fcmpeq(test_float_fdiv(VAL1, VAL2), VAL1 / VAL2, FPREC)); + EXPECT(my_fcmpeq(test_float_fmul(VAL1, VAL2), VAL1 * VAL2, FPREC)); + EXPECT(my_fcmpeq(test_float_frsub(VAL1, VAL2), VAL2 - VAL1, FPREC)); + EXPECT(my_fcmpeq(test_float_fsub(VAL1, VAL2), VAL1 - VAL2, FPREC)); + + EXPECT(test_float_fcmpeq(VAL1, VAL1) == 1); + EXPECT(test_float_fcmplt(VAL1, VAL2) == 1); + EXPECT(test_float_fcmple(VAL1, VAL1) == 1); + EXPECT(test_float_fcmpge(VAL1, VAL1) == 1); + EXPECT(test_float_fcmpgt(VAL2, VAL1) == 1); + + EXPECT(test_float_d2iz(VAL1) == VAL1_INT); + EXPECT(test_float_d2uiz(VAL1) == VAL1_INT); + EXPECT(test_float_d2lz(VAL1) == VAL1_INT); + EXPECT(test_float_d2ulz(VAL1) == VAL1_INT); + + EXPECT(test_float_f2iz(VAL1) == VAL1_INT); + EXPECT(test_float_f2uiz(VAL1) == VAL1_INT); + EXPECT(test_float_f2lz(VAL1) == VAL1_INT); + EXPECT(test_float_f2ulz(VAL1) == VAL1_INT); + + EXPECT(my_fcmpeq(test_float_d2f(VAL1), VAL1, FPREC)); + EXPECT(my_dcmpeq(test_float_f2d(VAL1), VAL1, FPREC)); + + EXPECT(my_dcmpeq(test_float_i2d(VAL1_INT), VAL1_INT, DPREC)); + EXPECT(my_dcmpeq(test_float_ui2d(VAL1_INT), VAL1_INT, DPREC)); + EXPECT(my_dcmpeq(test_float_l2d(VAL1_INT), VAL1_INT, DPREC)); + EXPECT(my_dcmpeq(test_float_ul2d(VAL1_INT), VAL1_INT, DPREC)); + + EXPECT(my_fcmpeq(test_float_i2f(VAL1_INT), VAL1_INT, FPREC)); + EXPECT(my_fcmpeq(test_float_ui2f(VAL1_INT), VAL1_INT, FPREC)); + EXPECT(my_fcmpeq(test_float_l2f(VAL1_INT), VAL1_INT, FPREC)); + EXPECT(my_fcmpeq(test_float_ul2f(VAL1_INT), VAL1_INT, FPREC)); + return TEE_SUCCESS; +} +#else /*CFG_TA_FLOAT_SUPPORT*/ +static TEE_Result test_float(void) +{ + IMSG("Floating point disabled"); + return TEE_SUCCESS; +} +#endif /*CFG_TA_FLOAT_SUPPORT*/ + +#if defined(CFG_TA_BGET_TEST) +/* From libutils */ +int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *)); + +static void *malloc_wrapper(size_t size) +{ + return tee_map_zi(size, 0); +} + +static void free_wrapper(void *ptr __unused) +{ +} + +static bool optee_pager_with_small_pool(void) +{ + uint32_t ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + static const TEE_UUID uuid = STATS_UUID; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Param params[4] = { }; + uint32_t eo = 0; + bool rc = false; + + res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, + &eo); + if (res) + return false; + + res = TEE_InvokeTACommand(sess, 0, STATS_CMD_PAGER_STATS, + ptypes, params, &eo); + if (res == TEE_SUCCESS && + params[0].value.b && params[0].value.b <= PAGER_PAGE_COUNT_THRESHOLD) + rc = true; + + TEE_CloseTASession(sess); + + return rc; +} + +static TEE_Result test_bget(void) +{ + if (optee_pager_with_small_pool()) { + IMSG("Skip testing bget due to pager pool constraints"); + return TEE_SUCCESS; + } + + DMSG("Testing bget"); + if (bget_main_test(malloc_wrapper, free_wrapper)) { + EMSG("bget_main_test failed"); + return TEE_ERROR_GENERIC; + } + DMSG("Bget OK"); + return TEE_SUCCESS; +} +#else +static TEE_Result test_bget(void) +{ + IMSG("Bget test disabled"); + return TEE_SUCCESS; +} +#endif + + +static __noinline __noreturn void call_longjmp(jmp_buf env) +{ + DMSG("Calling longjmp"); + longjmp(env, 1); + EMSG("error: longjmp returned to calling function"); +} + +static TEE_Result test_setjmp(void) +{ + jmp_buf env = { }; + + if (setjmp(env)) { + IMSG("Returned via longjmp"); + return TEE_SUCCESS; + } else { + call_longjmp(env); + return TEE_ERROR_GENERIC; + } +} + +TEE_Result ta_entry_basic(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + printf("ta_entry_basic: enter\n"); + + res = test_malloc(); + if (res != TEE_SUCCESS) + return res; + + res = test_properties(); + if (res != TEE_SUCCESS) + return res; + + res = test_mem_access_right(param_types, params); + if (res != TEE_SUCCESS) + return res; + + res = test_time(); + if (res != TEE_SUCCESS) + return res; + + res = test_float(); + if (res != TEE_SUCCESS) + return res; + + res = test_setjmp(); + if (res != TEE_SUCCESS) + return res; + + res = test_bget(); + if (res != TEE_SUCCESS) + return res; + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_panic(uint32_t param_types, TEE_Param params[4]) +{ + volatile bool mytrue = true; + (void)param_types; + (void)params; + + printf("ta_entry_panic: enter\n"); + /* + * Somewhat clumsy way of avoiding compile errors if TEE_Panic() has + * the __noreturn attribute. + */ + if (mytrue) + TEE_Panic(0xbeef); + + /* + * Should not be reached, but if it is the testsuite can detect that + * TEE_Panic() returned instead of panicking the TA. + */ + return TEE_SUCCESS; +} + +TEE_Result ta_entry_client_with_timeout(uint32_t param_types, + TEE_Param params[4]) +{ + static const TEE_UUID os_test_uuid = TA_OS_TEST_UUID; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + uint32_t ret_orig = 0; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + EMSG("ta_entry_client_with_timeout: bad parameters\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + + res = TEE_OpenTASession(&os_test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG( + "ta_entry_client_with_timeout: TEE_OpenTASession failed\n"); + return res; + } + + res = + TEE_InvokeTACommand(sess, params[0].value.a / 2, + TA_OS_TEST_CMD_WAIT, param_types, params, + &ret_orig); + + if (ret_orig != TEE_ORIGIN_TRUSTED_APP || res != TEE_ERROR_CANCEL) { + EMSG("ta_entry_client_with_timeout: TEE_InvokeTACommand: " + "res 0x%x ret_orig 0x%x\n", (unsigned int)res, + (unsigned int)ret_orig); + res = TEE_ERROR_GENERIC; + } else + res = TEE_SUCCESS; + + TEE_CloseTASession(sess); + return res; + +} + +TEE_Result ta_entry_client(uint32_t param_types, TEE_Param params[4]) +{ + static const TEE_UUID crypt_uuid = TA_CRYPT_UUID; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t l_pts = 0; + TEE_Param l_params[4] = { }; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + uint32_t ret_orig = 0; + static const uint8_t sha256_in[] = { 'a', 'b', 'c' }; + static const uint8_t sha256_out[] = { + 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 + }; + uint8_t out[32] = { 0 }; + void *in = NULL; + + (void)param_types; + (void)params; + + printf("ta_entry_client: enter\n"); + + in = TEE_Malloc(sizeof(sha256_in), 0); + if (in == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + TEE_MemMove(in, sha256_in, sizeof(sha256_in)); + + res = TEE_OpenTASession(&crypt_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("ta_entry_client: TEE_OpenTASession failed\n"); + goto cleanup_return; + } + + l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0); + l_params[0].memref.buffer = in; + l_params[0].memref.size = sizeof(sha256_in); + l_params[1].memref.buffer = out; + l_params[1].memref.size = sizeof(out); + + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + TA_CRYPT_CMD_SHA256, l_pts, l_params, + &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("ta_entry_client: TEE_InvokeTACommand failed\n"); + goto cleanup_return; + } + + if (TEE_MemCompare(sha256_out, out, sizeof(sha256_out)) != 0) { + EMSG("ta_entry_client: out parameter failed\n"); + res = TEE_ERROR_GENERIC; + goto cleanup_return; + } + +cleanup_return: + TEE_Free(in); + TEE_CloseTASession(sess); + return res; +} + +TEE_Result ta_entry_params_access_rights(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0)) + return TEE_ERROR_GENERIC; + + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_ANY_OWNER, + params[0].memref.buffer, + params[0].memref.size); + if (res != TEE_SUCCESS) + return res; + + res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ, + params[0].memref.buffer, + params[0].memref.size); + if (res != TEE_ERROR_ACCESS_DENIED) + return TEE_ERROR_GENERIC; + if (params[1].memref.buffer || params[1].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_wait(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_SUCCESS; + (void)param_types; + + printf("ta_entry_wait: waiting %d\n", (unsigned int)params[0].value.a); + /* Wait */ + res = TEE_Wait(params[0].value.a); + + return res; +} + +static void undef_instr(void) +{ +#if defined(ARM64) + __asm__(".word 0x0"); +#elif defined(ARM32) + __asm__(".word 0xe7ffffff"); +#elif defined(RV64) || defined(RV32) + __asm__(".word 0x0"); +#else +#error "Unsupported architecture" +#endif +} + +TEE_Result ta_entry_bad_mem_access(uint32_t param_types, TEE_Param params[4]) +{ + long int stack = 0; + long int stack_addr = (long int)&stack; + void (*volatile null_fn_ptr)(void) = NULL; + char *zero_size_malloc = NULL; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0) && + param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, 0, 0)) + return TEE_ERROR_GENERIC; + + switch (params[0].value.a) { + case 1: + *((volatile uint32_t *)0) = 0; + break; + case 2: + *((uint32_t *)(stack_addr + 0x40000000)) = 0; + break; + case 3: + null_fn_ptr(); + break; + case 4: + ((void (*)(void))(stack_addr + 0x40000000)) (); + break; + case 5: + undef_instr(); + break; + case 6: + zero_size_malloc = TEE_Malloc(0, 0); + if (!zero_size_malloc) + return TEE_ERROR_GENERIC; + if (*zero_size_malloc) + return TEE_ERROR_GENERIC; + break; + case 7: + zero_size_malloc = TEE_Malloc(0, 0); + if (!zero_size_malloc) + return TEE_ERROR_GENERIC; + *zero_size_malloc = 0; + break; + default: + break; + } + + return TEE_SUCCESS; +} + +static void incr_values(size_t bufsize, uint8_t *a, uint8_t *b, uint8_t *c) +{ + size_t i = 0; + + for (i = 0; i < bufsize; i++) { + a[i]++; b[i]++; c[i]++; + } +} + +#define TA2TA_BUF_SIZE (2 * 1024) +TEE_Result ta_entry_ta2ta_memref(uint32_t param_types, TEE_Param params[4]) +{ + static const TEE_UUID test_uuid = TA_OS_TEST_UUID; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + TEE_Param l_params[4] = { }; + uint8_t in[TA2TA_BUF_SIZE] = { }; + uint8_t inout[TA2TA_BUF_SIZE] = { }; + uint8_t out[TA2TA_BUF_SIZE] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t ret_orig = 0; + uint32_t l_pts = 0; + size_t i = 0; + + (void)params; + + if (param_types != TEE_PARAM_TYPES(0, 0, 0, 0)) + return TEE_ERROR_GENERIC; + + res = TEE_OpenTASession(&test_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("TEE_OpenTASession failed"); + goto cleanup_return; + } + + l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, 0); + l_params[0].memref.buffer = in; + l_params[0].memref.size = TA2TA_BUF_SIZE; + l_params[1].memref.buffer = inout; + l_params[1].memref.size = TA2TA_BUF_SIZE; + l_params[2].memref.buffer = out; + l_params[2].memref.size = TA2TA_BUF_SIZE; + + /* Initialize buffers */ + for (i = 0; i < TA2TA_BUF_SIZE; i++) { + in[i] = 5; + inout[i] = 10; + out[i] = 0; + } + + /* + * TA will compute: out = ++inout + in + * Expected values after this step: in: 5, inout: 11, out: 16 + */ + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + TA_OS_TEST_CMD_TA2TA_MEMREF_MIX, + l_pts, l_params, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("TEE_InvokeTACommand failed"); + goto cleanup_return; + } + + /* + * Increment all values by one. + * Expected values after this step: in: 6, inout: 12, out: 17 + */ + incr_values(TA2TA_BUF_SIZE, in, inout, out); + + /* + * TA will compute: out = ++inout + in + * Expected values after this step: in: 6, inout: 13, out: 19 + */ + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + TA_OS_TEST_CMD_TA2TA_MEMREF_MIX, + l_pts, l_params, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("TEE_InvokeTACommand failed"); + goto cleanup_return; + } + + /* Check the actual values */ + for (i = 0; i < TA2TA_BUF_SIZE; i++) { + if (in[i] != 6 || inout[i] != 13 || out[i] != 19) { + EMSG("Unexpected value in buffer(s)"); + DHEXDUMP(in, TA2TA_BUF_SIZE); + DHEXDUMP(inout, TA2TA_BUF_SIZE); + DHEXDUMP(out, TA2TA_BUF_SIZE); + return TEE_ERROR_GENERIC; + } + } + +cleanup_return: + TEE_CloseTASession(sess); + return res; +} + +TEE_Result ta_entry_ta2ta_memref_mix(uint32_t param_types, TEE_Param params[4]) +{ + uint8_t *in = NULL; + uint8_t *inout = NULL; + uint8_t *out = NULL; + size_t bufsize = 0; + size_t i = 0; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, 0)) + return TEE_ERROR_GENERIC; + + bufsize = params[0].memref.size; + if (params[1].memref.size != bufsize || + params[2].memref.size != bufsize) + return TEE_ERROR_GENERIC; + + in = params[0].memref.buffer; + inout = params[1].memref.buffer; + out = params[2].memref.buffer; + + for (i = 0; i < bufsize; i++) + out[i] = ++inout[i] + in[i]; + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_params(uint32_t param_types, TEE_Param params[4]) +{ + size_t n = 0; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT)) + return TEE_ERROR_BAD_PARAMETERS; + + for (n = 0; n < TEE_NUM_PARAMS; n++) + if (!params[n].memref.buffer || !params[n].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_null_memref(uint32_t param_types, TEE_Param params[4]) +{ + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT)) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * Tests how client can provide null or non-null memref parameters + * param[0] expected as a 0 byte input mapped memeref. + * param[1] expected as a 0 byte input not-mapped memeref. + * param[2] expected as a 0 byte output mapped memeref. + * param[3] expected as a 0 byte output not-mapped memeref. + */ + if (!params[0].memref.buffer || params[0].memref.size || + params[1].memref.buffer || params[1].memref.size || + !params[2].memref.buffer || params[2].memref.size || + params[3].memref.buffer || params[3].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_call_lib(uint32_t param_types, + TEE_Param params[4] __unused) +{ + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (os_test_shlib_add(1, 2) != 3) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_call_lib_panic(uint32_t param_types, + TEE_Param params[4] __unused) +{ + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + os_test_shlib_panic(); + + return TEE_ERROR_GENERIC; +} + +TEE_Result ta_entry_call_lib_dl(uint32_t param_types __maybe_unused, + TEE_Param params[4] __unused) +{ + int (*add_func)(int a, int b) = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + void *handle = NULL; + void *hnull = NULL; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba", + RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); + if (!handle) + return TEE_ERROR_GENERIC; + + add_func = dlsym(handle, "os_test_shlib_dl_add"); + if (!add_func) + goto err; + if (add_func(3, 4) != 7) + goto err; + + hnull = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); + if (!hnull) + goto err; + + add_func = dlsym(hnull, "os_test_shlib_dl_add"); + if (!add_func) + goto err; + if (add_func(5, 6) != 11) + goto err; + + res = TEE_SUCCESS; + dlclose(hnull); +err: + dlclose(handle); + return res; +} + +TEE_Result ta_entry_call_lib_dl_panic(uint32_t param_types __maybe_unused, + TEE_Param params[4] __unused) +{ + int (*panic_func)(void) = NULL; + void *handle = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba", + RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); + if (!handle) + return res; + + panic_func = dlsym(handle, "os_test_shlib_dl_panic"); + if (!panic_func) + goto err; + panic_func(); + return TEE_ERROR_GENERIC; +err: + dlclose(handle); + return res; +} + +/* ELF initialization/finalization test */ + +volatile int os_test_global; + +static void __attribute__((constructor)) os_test_init(void) +{ + os_test_global *= 10; + os_test_global += 1; + DMSG("os_test_global=%d", os_test_global); +} + +TEE_Result ta_entry_get_global_var(uint32_t param_types, TEE_Param params[4]) +{ + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + params[0].value.a = os_test_global; + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_client_identity(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_Identity identity = { }; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[1].memref.size < sizeof(TEE_UUID)) { + params[1].memref.size = sizeof(TEE_UUID); + return TEE_ERROR_SHORT_BUFFER; + } + + res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, + "gpd.client.identity", &identity); + if (res != TEE_SUCCESS) { + EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); + return res; + } + + params[0].value.a = identity.login; + memcpy(params[1].memref.buffer, &identity.uuid, sizeof(TEE_UUID)); + params[1].memref.size = sizeof(TEE_UUID); + + return res; +} + +#if defined(WITH_TLS_TESTS) +__thread int os_test_tls_a; +__thread int os_test_tls_b = 42; + +TEE_Result ta_entry_tls_test_main(void) +{ + if (os_test_tls_a != 0) { + EMSG("os_test_tls_a=%d, expected 0", os_test_tls_a); + return TEE_ERROR_GENERIC; + } + if (os_test_tls_b != 42) { + EMSG("os_test_tls_b=%d, expected 42", os_test_tls_b); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_tls_test_shlib(void) +{ + if (os_test_shlib_tls_a != 0) { + EMSG("os_test_shlib_tls_a=%d, expected 0", os_test_shlib_tls_a); + return TEE_ERROR_GENERIC; + } + if (os_test_shlib_tls_b != 123) { + EMSG("os_test_shlib_tls_b=%d, expected 123", + os_test_shlib_tls_b); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} +#else +TEE_Result ta_entry_tls_test_main(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +TEE_Result ta_entry_tls_test_shlib(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} +#endif + +static int iterate_hdr_cb(struct dl_phdr_info *info __maybe_unused, + size_t size __unused, void *data) +{ + int *count = data; + + (*count)++; + IMSG("ELF module index: %d", *count); + IMSG(" dlpi_addr=%p", (void *)info->dlpi_addr); + IMSG(" dlpi_name='%s'", info->dlpi_name); + IMSG(" dlpi_phdr=%p", (void *)info->dlpi_phdr); + IMSG(" dlpi_phnum=%hu", info->dlpi_phnum); + IMSG(" dlpi_adds=%llu", info->dlpi_adds); + IMSG(" dlpi_subs=%llu", info->dlpi_subs); + IMSG(" dlpi_tls_modid=%zu", info->dlpi_tls_modid); + IMSG(" dlpi_tls_data=%p", info->dlpi_tls_data); + + return 123; +} + +static TEE_Result expect_dl_count_ge(size_t exp_count) +{ + int st = 0; + size_t count = 0; + + st = dl_iterate_phdr(iterate_hdr_cb, (void *)&count); + if (st != 123) { + /* + * dl_iterate_phdr() should return the last value returned by + * the callback + */ + EMSG("Expected return value 123, got %d", st); + return TEE_ERROR_GENERIC; + } + if (count < exp_count) { + /* + * Expect >= and not == since there could be more shared + * libraries (for instance, CFG_ULIBS_SHARED=y) + */ + EMSG("Expected count > %zu, got: %zu", exp_count, count); + return TEE_ERROR_GENERIC; + } + + return TEE_SUCCESS; +} + +TEE_Result ta_entry_dl_phdr(void) +{ + return expect_dl_count_ge(2); +} + +TEE_Result ta_entry_dl_phdr_dl(void) +{ + TEE_Result res = TEE_ERROR_GENERIC; + void *handle = NULL; + + handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba", + RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); + if (!handle) + return TEE_ERROR_GENERIC; + + res = expect_dl_count_ge(3); + dlclose(handle); + + return res; +} + +TEE_Result ta_entry_memtag_use_after_free(void) +{ + uint32_t *p = NULL; + + if (!memtag_is_enabled()) + return TEE_ERROR_NOT_SUPPORTED; + + p = TEE_Malloc(sizeof(*p), TEE_MALLOC_FILL_ZERO); + *p = 43; + TEE_Free(p); + (*p) += 2; + return TEE_ERROR_GENERIC; +} + +TEE_Result ta_entry_memtag_invalid_tag(void) +{ + uint32_t *p = NULL; + uint32_t *p2 = NULL; + + if (!memtag_is_enabled()) + return TEE_ERROR_NOT_SUPPORTED; + + p = TEE_Malloc(sizeof(*p), TEE_MALLOC_FILL_ZERO); + + if (!memtag_get_tag(p)) { + EMSG("missing tag in %p", (void *)p); + goto err; + } + *p = 32; + + p2 = memtag_insert_tag(p, (memtag_get_tag(p) + 1) & 0xf); + *p2 = 42; + EMSG("Expected to crash when writing to %p which was allocated as %p", + (void *)p2, (void *)p); +err: + TEE_Free(p); + return TEE_ERROR_GENERIC; +} + +TEE_Result ta_entry_memtag_double_free(void) +{ + uint32_t *p = NULL; + + if (!memtag_is_enabled()) + return TEE_ERROR_NOT_SUPPORTED; + + p = TEE_Malloc(sizeof(*p), TEE_MALLOC_FILL_ZERO); + *p = 43; + TEE_Free(p); + TEE_Free(p); + return TEE_ERROR_GENERIC; +} + +TEE_Result ta_entry_memtag_buffer_overrun(void) +{ + uint64_t *p = NULL; + + if (!memtag_is_enabled()) + return TEE_ERROR_NOT_SUPPORTED; + + p = TEE_Malloc(sizeof(*p) * 2, TEE_MALLOC_FILL_ZERO); + p[2] += 44; + TEE_Free(p); + return TEE_ERROR_GENERIC; +} diff --git a/optee/optee_test/ta/os_test/pauth_a64.S b/optee/optee_test/ta/os_test/pauth_a64.S new file mode 100644 index 0000000..c191051 --- /dev/null +++ b/optee/optee_test/ta/os_test/pauth_a64.S @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include + +/* + * void corrupt_pac(void) + * + * The function corrupts a single bit of the PAC to ensure that the + * authentication will fail. paciasp calculates and adds the PAC to the + * link register and autiasp is used to authenticate the PAC. + */ +FUNC corrupt_pac , : + paciasp + /* Flip a random bit in PAC field of the return address */ + eor lr, lr , 1 << 58 + autiasp + ret +END_FUNC corrupt_pac + +emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI diff --git a/optee/optee_test/ta/os_test/sub.mk b/optee/optee_test/ta/os_test/sub.mk new file mode 100644 index 0000000..0b080c0 --- /dev/null +++ b/optee/optee_test/ta/os_test/sub.mk @@ -0,0 +1,30 @@ +cppflags-$(CFG_TA_FLOAT_SUPPORT) += -DCFG_TA_FLOAT_SUPPORT=1 +cppflags-$(WITH_TLS_TESTS) += -DWITH_TLS_TESTS=1 +cppflags-$(WITH_CXX_TESTS) += -DWITH_CXX_TESTS=1 + +global-incdirs-y += include +global-incdirs-y += ../crypt/include +global-incdirs-y += ../os_test_lib/include +cflags-y += -Wno-float-equal +srcs-y += init.c +srcs-y += os_test.c +srcs-y += ta_entry.c +srcs-$(CFG_TA_FLOAT_SUPPORT) += test_float_subj.c +ifeq ($(WITH_CXX_TESTS),y) +# Profiling (-pg) is disabled for C++ tests because in case it is used for +# function tracing (CFG_FTRACE_SUPPORT=y) then the exception handling code in +# the C++ runtime won't be able to unwind the (modified) stack. +# https://github.com/OP-TEE/optee_os/issues/4022 +srcs-y += cxx_tests.cpp +cxxflags-remove-cxx_tests.cpp-y += -pg +srcs-y += cxx_tests_c.c +cflags-remove-cxx_tests_c.c-y += -pg +endif +ifeq ($(sm),ta_arm64) +srcs-$(CFG_TA_PAUTH) += pauth_a64.S +srcs-$(CFG_TA_PAUTH) += ta_arm_pauth.c +# -march=armv8.3-a enables the non-nops instructions for PAC. We are using one +# such instruction in the PAC test. +cflags-$(CFG_TA_PAUTH) += -march=armv8.3-a +endif +srcs-y += attestation.c diff --git a/optee/optee_test/ta/os_test/ta_arm_pauth.c b/optee/optee_test/ta/os_test/ta_arm_pauth.c new file mode 100644 index 0000000..86986dc --- /dev/null +++ b/optee/optee_test/ta/os_test/ta_arm_pauth.c @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include +#include +#include +#include + +void corrupt_pac(void); + +/* Assuming VA_MASK considering maximum 48 bit of VA */ +#define VA_MASK 0xfffff0000000000 + +static uint64_t sign_using_keyia(uint64_t ptr) +{ + asm volatile("paciza %0 " : "+r" (ptr)); + return ptr; +} + +TEE_Result ta_entry_pauth_test_nop(void) +{ + uint64_t pac = 0; + bool implemented = false; + TEE_Result res = TEE_ERROR_GENERIC; + + res = TEE_GetPropertyAsBool( + TEE_PROPSET_TEE_IMPLEMENTATION, + "org.trustedfirmware.optee.cpu.feat_pauth_implemented", + &implemented); + if (res != TEE_SUCCESS) + return res; + + if (!implemented) + return TEE_ERROR_NOT_SUPPORTED; + + /* Check if PAC instruction generates the authentication code */ + for (int i = 0; i < 10; i++) + pac |= sign_using_keyia(i) & VA_MASK; + + if (implemented && pac) + return TEE_SUCCESS; + + return TEE_ERROR_GENERIC; +} + +TEE_Result ta_entry_pauth_corrupt_pac(void) +{ + corrupt_pac(); + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/os_test/ta_entry.c b/optee/optee_test/ta/os_test/ta_entry.c new file mode 100644 index 0000000..092b357 --- /dev/null +++ b/optee/optee_test/ta/os_test/ta_entry.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ +#include +#include +#include +#include +#include +#include + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + DMSG("TA_CreateEntryPoint"); + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ + DMSG("TA_DestroyEntryPoint"); +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + DMSG("TA_OpenSessionEntryPoint"); + TEE_UnmaskCancellation(); + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; + DMSG("TA_CloseSessionEntryPoint"); +} + +__weak TEE_Result ta_entry_pauth_test_nop(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +__weak TEE_Result ta_entry_pauth_corrupt_pac(void) +{ + return TEE_ERROR_NOT_SUPPORTED; +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + (void)pSessionContext; + + switch (nCommandID) { + case TA_OS_TEST_CMD_INIT: + return ta_entry_init(nParamTypes, pParams); + + case TA_OS_TEST_CMD_CLIENT_WITH_TIMEOUT: + return ta_entry_client_with_timeout(nParamTypes, pParams); + + case TA_OS_TEST_CMD_BASIC: + return ta_entry_basic(nParamTypes, pParams); + + case TA_OS_TEST_CMD_PANIC: + return ta_entry_panic(nParamTypes, pParams); + + case TA_OS_TEST_CMD_CLIENT: + return ta_entry_client(nParamTypes, pParams); + + case TA_OS_TEST_CMD_PARAMS_ACCESS: + return ta_entry_params_access_rights(nParamTypes, pParams); + + case TA_OS_TEST_CMD_WAIT: + return ta_entry_wait(nParamTypes, pParams); + + case TA_OS_TEST_CMD_BAD_MEM_ACCESS: + return ta_entry_bad_mem_access(nParamTypes, pParams); + + case TA_OS_TEST_CMD_TA2TA_MEMREF: + return ta_entry_ta2ta_memref(nParamTypes, pParams); + + case TA_OS_TEST_CMD_TA2TA_MEMREF_MIX: + return ta_entry_ta2ta_memref_mix(nParamTypes, pParams); + + case TA_OS_TEST_CMD_PARAMS: + return ta_entry_params(nParamTypes, pParams); + + case TA_OS_TEST_CMD_NULL_MEMREF_PARAMS: + return ta_entry_null_memref(nParamTypes, pParams); + + case TA_OS_TEST_CMD_CALL_LIB: + return ta_entry_call_lib(nParamTypes, pParams); + + case TA_OS_TEST_CMD_CALL_LIB_PANIC: + return ta_entry_call_lib_panic(nParamTypes, pParams); + + case TA_OS_TEST_CMD_CALL_LIB_DL: + return ta_entry_call_lib_dl(nParamTypes, pParams); + + case TA_OS_TEST_CMD_CALL_LIB_DL_PANIC: + return ta_entry_call_lib_dl_panic(nParamTypes, pParams); + + case TA_OS_TEST_CMD_GET_GLOBAL_VAR: + return ta_entry_get_global_var(nParamTypes, pParams); + + case TA_OS_TEST_CMD_CLIENT_IDENTITY: + return ta_entry_client_identity(nParamTypes, pParams); + + case TA_OS_TEST_CMD_TLS_TEST_MAIN: + return ta_entry_tls_test_main(); + + case TA_OS_TEST_CMD_TLS_TEST_SHLIB: + return ta_entry_tls_test_shlib(); + + case TA_OS_TEST_CMD_DL_PHDR: + return ta_entry_dl_phdr(); + + case TA_OS_TEST_CMD_DL_PHDR_DL: + return ta_entry_dl_phdr_dl(); + +#if defined(WITH_CXX_TESTS) + case TA_OS_TEST_CMD_CXX_CTOR_MAIN: + return ta_entry_cxx_ctor_main(); + + case TA_OS_TEST_CMD_CXX_CTOR_SHLIB: + return ta_entry_cxx_ctor_shlib(); + + case TA_OS_TEST_CMD_CXX_CTOR_SHLIB_DL: + return ta_entry_cxx_ctor_shlib_dl(); + + case TA_OS_TEST_CMD_CXX_EXC_MAIN: + return ta_entry_cxx_exc_main(); + + case TA_OS_TEST_CMD_CXX_EXC_MIXED: + return ta_entry_cxx_exc_mixed(); +#else + case TA_OS_TEST_CMD_CXX_CTOR_MAIN: + case TA_OS_TEST_CMD_CXX_CTOR_SHLIB: + case TA_OS_TEST_CMD_CXX_CTOR_SHLIB_DL: + case TA_OS_TEST_CMD_CXX_EXC_MAIN: + case TA_OS_TEST_CMD_CXX_EXC_MIXED: + return TEE_ERROR_NOT_SUPPORTED; +#endif + +#if defined(CFG_TA_PAUTH) + case TA_OS_TEST_CMD_PAUTH_NOP: + return ta_entry_pauth_test_nop(); + + case TA_OS_TEST_CMD_PAUTH_CORRUPT_PAC: + return ta_entry_pauth_corrupt_pac(); +#else + case TA_OS_TEST_CMD_PAUTH_NOP: + case TA_OS_TEST_CMD_PAUTH_CORRUPT_PAC: + return TEE_ERROR_NOT_SUPPORTED; +#endif + case TA_OS_TEST_CMD_MEMTAG_USE_AFTER_FREE: + return ta_entry_memtag_use_after_free(); + case TA_OS_TEST_CMD_MEMTAG_INVALID_TAG: + return ta_entry_memtag_invalid_tag(); + case TA_OS_TEST_CMD_MEMTAG_DOUBLE_FREE: + return ta_entry_memtag_double_free(); + case TA_OS_TEST_CMD_MEMTAG_BUFFER_OVERRUN: + return ta_entry_memtag_buffer_overrun(); + + case TA_OS_TEST_CMD_ATTESTATION: + return ta_entry_attestation(nParamTypes, pParams); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/os_test/test_float_subj.c b/optee/optee_test/ta/os_test/test_float_subj.c new file mode 100644 index 0000000..872afb7 --- /dev/null +++ b/optee/optee_test/ta/os_test/test_float_subj.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include "test_float_subj.h" + +double test_float_dadd(double a, double b) +{ + return a + b; +} + +double test_float_ddiv(double n, double d) +{ + return n / d; +} + +double test_float_dmul(double a, double b) +{ + return a * b; +} + +double test_float_drsub(double a, double b) +{ + return b - a; +} + +double test_float_dsub(double a, double b) +{ + return a - b; +} + +int test_float_dcmpeq(double a, double b) +{ + return a == b; +} + +int test_float_dcmplt(double a, double b) +{ + return a < b; +} + +int test_float_dcmple(double a, double b) +{ + return a <= b; +} + +int test_float_dcmpge(double a, double b) +{ + return a >= b; +} + +int test_float_dcmpgt(double a, double b) +{ + return a > b; +} + +float test_float_fadd(float a, float b) +{ + return a + b; +} + +float test_float_fdiv(float n, float d) +{ + return n / d; +} + +float test_float_fmul(float a, float b) +{ + return a * b; +} + +float test_float_frsub(float a, float b) +{ + return b - a; +} + +float test_float_fsub(float a, float b) +{ + return a - b; +} + +int test_float_fcmpeq(float a, float b) +{ + return a == b; +} + +int test_float_fcmplt(float a, float b) +{ + return a < b; +} + +int test_float_fcmple(float a, float b) +{ + return a <= b; +} + +int test_float_fcmpge(float a, float b) +{ + return a >= b; +} + +int test_float_fcmpgt(float a, float b) +{ + return a > b; +} + +int test_float_d2iz(double a) +{ + return a; +} + +unsigned test_float_d2uiz(double a) +{ + return a; +} + +long long test_float_d2lz(double a) +{ + return a; +} + +unsigned long long test_float_d2ulz(double a) +{ + return a; +} + +int test_float_f2iz(float a) +{ + return a; +} + +unsigned test_float_f2uiz(float a) +{ + return a; +} + +long long test_float_f2lz(float a) +{ + return a; +} + +unsigned long long test_float_f2ulz(float a) +{ + return a; +} + +float test_float_d2f(double a) +{ + return a; +} + +double test_float_f2d(float a) +{ + return a; +} + +double test_float_i2d(int a) +{ + return a; +} + +double test_float_ui2d(unsigned a) +{ + return a; +} + +double test_float_l2d(long long a) +{ + return a; +} + +double test_float_ul2d(unsigned long long a) +{ + return a; +} + +float test_float_i2f(int a) +{ + return a; +} + +float test_float_ui2f(unsigned a) +{ + return a; +} + +float test_float_l2f(long long a) +{ + return a; +} + +float test_float_ul2f(unsigned long long a) +{ + return a; +} diff --git a/optee/optee_test/ta/os_test/test_float_subj.h b/optee/optee_test/ta/os_test/test_float_subj.h new file mode 100644 index 0000000..1c73a3c --- /dev/null +++ b/optee/optee_test/ta/os_test/test_float_subj.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef TEST_FLOAT_SUBJ_H +#define TEST_FLOAT_SUBJ_H + +double test_float_dadd(double a, double b); +double test_float_ddiv(double a, double b); +double test_float_dmul(double a, double b); +double test_float_drsub(double a, double b); +double test_float_dsub(double a, double b); +int test_float_dcmpeq(double a, double b); +int test_float_dcmplt(double a, double b); +int test_float_dcmple(double a, double b); +int test_float_dcmpge(double a, double b); +int test_float_dcmpgt(double a, double b); +float test_float_fadd(float a, float b); +float test_float_fdiv(float a, float b); +float test_float_fmul(float a, float b); +float test_float_frsub(float a, float b); +float test_float_fsub(float a, float b); +int test_float_fcmpeq(float a, float b); +int test_float_fcmplt(float a, float b); +int test_float_fcmple(float a, float b); +int test_float_fcmpge(float a, float b); +int test_float_fcmpgt(float a, float b); +int test_float_d2iz(double a); +unsigned test_float_d2uiz(double a); +long long test_float_d2lz(double a); +unsigned long long test_float_d2ulz(double a); +int test_float_f2iz(float a); +unsigned test_float_f2uiz(float a); +long long test_float_f2lz(float a); +unsigned long long test_float_f2ulz(float a); +float test_float_d2f(double a); +double test_float_f2d(float a); +double test_float_i2d(int a); +double test_float_ui2d(unsigned a); +double test_float_l2d(long long a); +double test_float_ul2d(unsigned long long a); +float test_float_i2f(int a); +float test_float_ui2f(unsigned a); +float test_float_l2f(long long a); +float test_float_ul2f(unsigned long long a); + +#endif /*TEST_FLOAT_SUBJ_H*/ diff --git a/optee/optee_test/ta/os_test_lib/Android.mk b/optee/optee_test/ta/os_test_lib/Android.mk new file mode 100644 index 0000000..e5adb9f --- /dev/null +++ b/optee/optee_test/ta/os_test_lib/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := ffd2bded-ab7d-4988-95ee-e4962fff7154.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/os_test_lib/Makefile b/optee/optee_test/ta/os_test_lib/Makefile new file mode 100644 index 0000000..f040dc9 --- /dev/null +++ b/optee/optee_test/ta/os_test_lib/Makefile @@ -0,0 +1,5 @@ +include $(TA_DEV_KIT_DIR)/mk/conf.mk + +SHLIBNAME = libos_test +SHLIBUUID = ffd2bded-ab7d-4988-95ee-e4962fff7154 +include ../ta_common.mk diff --git a/optee/optee_test/ta/os_test_lib/include/os_test_lib.h b/optee/optee_test/ta/os_test_lib/include/os_test_lib.h new file mode 100644 index 0000000..7ba189e --- /dev/null +++ b/optee/optee_test/ta/os_test_lib/include/os_test_lib.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2018, Linaro Limited + */ + +#ifndef _OS_TEST_LIB_H_ +#define _OS_TEST_LIB_H_ + +#include + +int os_test_shlib_add(int a, int b); +void os_test_shlib_panic(void); + +#if defined(WITH_TLS_TESTS) +extern __thread int os_test_shlib_tls_a; +extern __thread int os_test_shlib_tls_b; +#endif + +TEE_Result os_test_shlib_cxx_ctor(void); + +#endif /* _OS_TEST_LIB_H_ */ diff --git a/optee/optee_test/ta/os_test_lib/os_test_lib.c b/optee/optee_test/ta/os_test_lib/os_test_lib.c new file mode 100644 index 0000000..7eaee6c --- /dev/null +++ b/optee/optee_test/ta/os_test_lib/os_test_lib.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +#include "os_test_lib.h" +#include +#include + +extern int os_test_global; + +static void __attribute__((constructor)) os_test_shlib_init(void) +{ + os_test_global *= 10; + os_test_global += 2; + DMSG("os_test_global=%d", os_test_global); +} + +#if defined(WITH_TLS_TESTS) +__thread int os_test_shlib_tls_a; +__thread int os_test_shlib_tls_b = 123; +#endif + +int os_test_shlib_add(int a, int b) +{ + return a + b; +} + +void os_test_shlib_panic(void) +{ + TEE_Panic(0); +} diff --git a/optee/optee_test/ta/os_test_lib/os_test_lib_cxx.cpp b/optee/optee_test/ta/os_test_lib/os_test_lib_cxx.cpp new file mode 100644 index 0000000..1a57b4b --- /dev/null +++ b/optee/optee_test/ta/os_test_lib/os_test_lib_cxx.cpp @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2020 Huawei Technologies Co., Ltd + */ + +extern "C" { +#include "os_test_lib.h" +#include +} + +class OsTestLibCtorTest { +public: + OsTestLibCtorTest() : val(2) {} + + int val; +}; + +static OsTestLibCtorTest os_test_lib_ctor_test; + +TEE_Result os_test_shlib_cxx_ctor(void) +{ + if (os_test_lib_ctor_test.val != 2) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/os_test_lib/sub.mk b/optee/optee_test/ta/os_test_lib/sub.mk new file mode 100644 index 0000000..528f0fa --- /dev/null +++ b/optee/optee_test/ta/os_test_lib/sub.mk @@ -0,0 +1,8 @@ +cppflags-$(WITH_TLS_TESTS) += -DWITH_TLS_TESTS=1 +global-incdirs-y += include +srcs-y += os_test_lib.c +ifeq ($(WITH_CXX_TESTS),y) +ifneq ($(COMPILER),clang) +srcs-y += os_test_lib_cxx.cpp +endif +endif diff --git a/optee/optee_test/ta/os_test_lib_dl/Android.mk b/optee/optee_test/ta/os_test_lib_dl/Android.mk new file mode 100644 index 0000000..60508a0 --- /dev/null +++ b/optee/optee_test/ta/os_test_lib_dl/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := b3091a65-9751-4784-abf7-0298a7cc35ba.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/os_test_lib_dl/Makefile b/optee/optee_test/ta/os_test_lib_dl/Makefile new file mode 100644 index 0000000..61793af --- /dev/null +++ b/optee/optee_test/ta/os_test_lib_dl/Makefile @@ -0,0 +1,5 @@ +include $(TA_DEV_KIT_DIR)/mk/conf.mk + +SHLIBNAME = libos_test_dl +SHLIBUUID = b3091a65-9751-4784-abf7-0298a7cc35ba +include ../ta_common.mk diff --git a/optee/optee_test/ta/os_test_lib_dl/include/os_test_lib_dl.h b/optee/optee_test/ta/os_test_lib_dl/include/os_test_lib_dl.h new file mode 100644 index 0000000..a9db7c3 --- /dev/null +++ b/optee/optee_test/ta/os_test_lib_dl/include/os_test_lib_dl.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef _OS_TEST_LIB_DL_H_ +#define _OS_TEST_LIB_DL_H_ + +#include + +int os_test_shlib_dl_add(int a, int b); +void os_test_shlib_dl_panic(void); +TEE_Result os_test_shlib_dl_cxx_ctor(void); + +#endif /* _OS_TEST_LIB_DL_H_ */ diff --git a/optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl.c b/optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl.c new file mode 100644 index 0000000..5e90c42 --- /dev/null +++ b/optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018-2019, Linaro Limited + */ + +#include +#include +#include + +extern int os_test_global; + +static void __attribute__((constructor)) os_test_shlib_dl_init(void) +{ + os_test_global *= 10; + os_test_global += 3; + DMSG("os_test_global=%d", os_test_global); +} + +int os_test_shlib_dl_add(int a, int b) +{ + return a + b; +} + +void os_test_shlib_dl_panic(void) +{ + TEE_Panic(0); +} diff --git a/optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl_cxx.cpp b/optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl_cxx.cpp new file mode 100644 index 0000000..15c4b87 --- /dev/null +++ b/optee/optee_test/ta/os_test_lib_dl/os_test_lib_dl_cxx.cpp @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2018, Linaro Limited + */ + +extern "C" { +#include "os_test_lib_dl.h" +#include +} + +class OsTestLibDlCtorTest { +public: + OsTestLibDlCtorTest() : val(2) {} + + int val; +}; + +static OsTestLibDlCtorTest os_test_lib_dl_ctor_test; + +TEE_Result os_test_shlib_dl_cxx_ctor(void) +{ + if (os_test_lib_dl_ctor_test.val != 2) + return TEE_ERROR_GENERIC; + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/os_test_lib_dl/sub.mk b/optee/optee_test/ta/os_test_lib_dl/sub.mk new file mode 100644 index 0000000..346e06d --- /dev/null +++ b/optee/optee_test/ta/os_test_lib_dl/sub.mk @@ -0,0 +1,7 @@ +global-incdirs-y += include +srcs-y += os_test_lib_dl.c +ifeq ($(WITH_CXX_TESTS),y) +ifneq ($(COMPILER),clang) +srcs-y += os_test_lib_dl_cxx.cpp +endif +endif diff --git a/optee/optee_test/ta/rpc_test/Android.mk b/optee/optee_test/ta/rpc_test/Android.mk new file mode 100644 index 0000000..1b570f3 --- /dev/null +++ b/optee/optee_test/ta/rpc_test/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := d17f73a0-36ef-11e1-984a-0002a5d5c51b.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/rpc_test/Makefile b/optee/optee_test/ta/rpc_test/Makefile new file mode 100644 index 0000000..c68b8e4 --- /dev/null +++ b/optee/optee_test/ta/rpc_test/Makefile @@ -0,0 +1,2 @@ +BINARY = d17f73a0-36ef-11e1-984a-0002a5d5c51b +include ../ta_common.mk diff --git a/optee/optee_test/ta/rpc_test/include/ta_rpc.h b/optee/optee_test/ta/rpc_test/include/ta_rpc.h new file mode 100644 index 0000000..23c8fbb --- /dev/null +++ b/optee/optee_test/ta/rpc_test/include/ta_rpc.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef TA_RPC_H +#define TA_RPC_H + +#include +#include + +TEE_Result rpc_sha224(bool sec_mem, uint32_t nParamTypes, TEE_Param pParams[4]); +TEE_Result rpc_sha256(bool sec_mem, uint32_t nParamTypes, TEE_Param pParams[4]); +TEE_Result rpc_aes256ecb_encrypt(bool sec_mem, uint32_t nParamTypes, + TEE_Param pParams[4]); +TEE_Result rpc_aes256ecb_decrypt(bool sec_mem, uint32_t nParamTypes, + TEE_Param pParams[4]); +TEE_Result rpc_open(void *session_context, uint32_t param_types, + TEE_Param params[4]); + +#endif diff --git a/optee/optee_test/ta/rpc_test/include/ta_rpc_test.h b/optee/optee_test/ta/rpc_test/include/ta_rpc_test.h new file mode 100644 index 0000000..647424c --- /dev/null +++ b/optee/optee_test/ta/rpc_test/include/ta_rpc_test.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef TA_RPC_TEST_H +#define TA_RPC_TEST_H + +/* This UUID is generated with the ITU-T UUID generator at + http://www.itu.int/ITU-T/asn1/uuid.html */ +#define TA_RPC_TEST_UUID { 0xd17f73a0, 0x36ef, 0x11e1, \ + { 0x98, 0x4a, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } } + +#define TA_RPC_CMD_CRYPT_SHA224 1 +#define TA_RPC_CMD_CRYPT_SHA256 2 +#define TA_RPC_CMD_CRYPT_AES256ECB_ENC 3 +#define TA_RPC_CMD_CRYPT_AES256ECB_DEC 4 +#define TA_RPC_CMD_OPEN 5 +#define TA_RPC_CMD_CRYPT_PRIVMEM_SHA224 6 +#define TA_RPC_CMD_CRYPT_PRIVMEM_SHA256 7 +#define TA_RPC_CMD_CRYPT_PRIVMEM_AES256ECB_ENC 8 +#define TA_RPC_CMD_CRYPT_PRIVMEM_AES256ECB_DEC 9 + +#endif diff --git a/optee/optee_test/ta/rpc_test/include/user_ta_header_defines.h b/optee/optee_test/ta/rpc_test/include/user_ta_header_defines.h new file mode 100644 index 0000000..f95b211 --- /dev/null +++ b/optee/optee_test/ta/rpc_test/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_RPC_TEST_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR) +#define TA_STACK_SIZE (4 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/rpc_test/sub.mk b/optee/optee_test/ta/rpc_test/sub.mk new file mode 100644 index 0000000..468d8ec --- /dev/null +++ b/optee/optee_test/ta/rpc_test/sub.mk @@ -0,0 +1,5 @@ +global-incdirs-y += include +global-incdirs-y += ../crypt/include +global-incdirs-y += ../sims/include +srcs-y += ta_entry.c +srcs-y += ta_rpc.c diff --git a/optee/optee_test/ta/rpc_test/ta_entry.c b/optee/optee_test/ta/rpc_test/ta_entry.c new file mode 100644 index 0000000..26f4ed0 --- /dev/null +++ b/optee/optee_test/ta/rpc_test/ta_entry.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include +#include +#include + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + (void)pSessionContext; + + switch (nCommandID) { + case TA_RPC_CMD_CRYPT_SHA224: + return rpc_sha224(false, nParamTypes, pParams); + + case TA_RPC_CMD_CRYPT_SHA256: + return rpc_sha256(false, nParamTypes, pParams); + + case TA_RPC_CMD_CRYPT_AES256ECB_ENC: + return rpc_aes256ecb_encrypt(false, nParamTypes, pParams); + + case TA_RPC_CMD_CRYPT_AES256ECB_DEC: + return rpc_aes256ecb_decrypt(false, nParamTypes, pParams); + + case TA_RPC_CMD_OPEN: + return rpc_open(pSessionContext, nParamTypes, pParams); + + case TA_RPC_CMD_CRYPT_PRIVMEM_SHA224: + return rpc_sha224(true, nParamTypes, pParams); + + case TA_RPC_CMD_CRYPT_PRIVMEM_SHA256: + return rpc_sha256(true, nParamTypes, pParams); + + case TA_RPC_CMD_CRYPT_PRIVMEM_AES256ECB_ENC: + return rpc_aes256ecb_encrypt(true, nParamTypes, pParams); + + case TA_RPC_CMD_CRYPT_PRIVMEM_AES256ECB_DEC: + return rpc_aes256ecb_decrypt(true, nParamTypes, pParams); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/rpc_test/ta_rpc.c b/optee/optee_test/ta/rpc_test/ta_rpc.c new file mode 100644 index 0000000..15dc092 --- /dev/null +++ b/optee/optee_test/ta/rpc_test/ta_rpc.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ +#include + +#include +#include +#include +#include +#include + +static TEE_UUID cryp_uuid = TA_CRYPT_UUID; + +static TEE_Result rpc_call_cryp(bool sec_mem, uint32_t nParamTypes, + TEE_Param pParams[4], uint32_t cmd) +{ + TEE_TASessionHandle cryp_session = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t origin = 0; + TEE_Param params[4] = { }; + size_t n = 0; + uint32_t types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + + res = TEE_OpenTASession(&cryp_uuid, TEE_TIMEOUT_INFINITE, types, + params, &cryp_session, &origin); + + if (res != TEE_SUCCESS) { + EMSG("rpc_sha256 - TEE_OpenTASession returned 0x%x\n", + (unsigned int)res); + return res; + } + + types = nParamTypes; + if (sec_mem) { + TEE_MemFill(params, 0, sizeof(params)); + for (n = 0; n < 4; n++) { + switch (TEE_PARAM_TYPE_GET(types, n)) { + case TEE_PARAM_TYPE_VALUE_INPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].value = pParams[n].value; + break; + + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + params[n].memref.buffer = + TEE_Malloc(pParams[n].memref.size, 0); + if (!params[n].memref.buffer) + TEE_Panic(0); + params[n].memref.size = pParams[n].memref.size; + if (TEE_PARAM_TYPE_GET(types, n) != + TEE_PARAM_TYPE_MEMREF_OUTPUT) + TEE_MemMove(params[n].memref.buffer, + pParams[n].memref.buffer, + pParams[n].memref.size); + break; + default: + break; + } + } + } else { + TEE_MemMove(params, pParams, sizeof(params)); + } + + res = TEE_InvokeTACommand(cryp_session, TEE_TIMEOUT_INFINITE, cmd, + types, params, &origin); + if (res != TEE_SUCCESS) { + EMSG("rpc_call_cryp - TEE_InvokeTACommand returned 0x%x\n", + (unsigned int)res); + } + + TEE_CloseTASession(cryp_session); + + if (sec_mem) { + for (n = 0; n < 4; n++) { + switch (TEE_PARAM_TYPE_GET(types, n)) { + case TEE_PARAM_TYPE_VALUE_INOUT: + case TEE_PARAM_TYPE_VALUE_OUTPUT: + pParams[n].value = params[n].value; + break; + + case TEE_PARAM_TYPE_MEMREF_INPUT: + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + if (TEE_PARAM_TYPE_GET(types, n) != + TEE_PARAM_TYPE_MEMREF_INPUT) + TEE_MemMove(pParams[n].memref.buffer, + params[n].memref.buffer, + params[n].memref.size); + pParams[n].memref.size = params[n].memref.size; + TEE_Free(params[n].memref.buffer); + break; + default: + break; + } + } + + } + + return res; +} + +TEE_Result rpc_sha224(bool sec_mem, uint32_t nParamTypes, TEE_Param pParams[4]) +{ + return rpc_call_cryp(sec_mem, nParamTypes, pParams, + TA_CRYPT_CMD_SHA224); +} + +TEE_Result rpc_sha256(bool sec_mem, uint32_t nParamTypes, TEE_Param pParams[4]) +{ + return rpc_call_cryp(sec_mem, nParamTypes, pParams, + TA_CRYPT_CMD_SHA256); +} + +TEE_Result rpc_aes256ecb_encrypt(bool sec_mem, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + return rpc_call_cryp(sec_mem, nParamTypes, pParams, + TA_CRYPT_CMD_AES256ECB_ENC); +} + +TEE_Result rpc_aes256ecb_decrypt(bool sec_mem, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + return rpc_call_cryp(sec_mem, nParamTypes, pParams, + TA_CRYPT_CMD_AES256ECB_DEC); +} + +TEE_Result rpc_open(void *session_context, uint32_t param_types, + TEE_Param params[4]) +{ + TEE_TASessionHandle session = TEE_HANDLE_NULL; + uint32_t orig = 0; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_UUID uuid = TA_SIMS_TEST_UUID; + uint32_t types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + TEE_Param par[4] = { }; + + (void)session_context; + (void)param_types; + + res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &session, + &orig); + + if (res != TEE_SUCCESS) + return res; + + TEE_MemFill(params, 0, sizeof(TEE_Param) * 4); + res = + TEE_InvokeTACommand(session, TEE_TIMEOUT_INFINITE, + TA_SIMS_CMD_GET_COUNTER, types, par, &orig); + + if (res != TEE_SUCCESS) + goto exit; + +exit: + TEE_CloseTASession(session); + + return res; +} diff --git a/optee/optee_test/ta/sdp_basic/Android.mk b/optee/optee_test/ta/sdp_basic/Android.mk new file mode 100644 index 0000000..e31e2a6 --- /dev/null +++ b/optee/optee_test/ta/sdp_basic/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 12345678-5b69-11e4-9dbb-101f74f00099.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/sdp_basic/Makefile b/optee/optee_test/ta/sdp_basic/Makefile new file mode 100644 index 0000000..9995a1a --- /dev/null +++ b/optee/optee_test/ta/sdp_basic/Makefile @@ -0,0 +1,4 @@ +BINARY = 12345678-5b69-11e4-9dbb-101f74f00099 + +include ../ta_common.mk + diff --git a/optee/optee_test/ta/sdp_basic/include/ta_sdp_basic.h b/optee/optee_test/ta/sdp_basic/include/ta_sdp_basic.h new file mode 100644 index 0000000..50fa17b --- /dev/null +++ b/optee/optee_test/ta/sdp_basic/include/ta_sdp_basic.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_SDP_BASIC_H +#define TA_SDP_BASIC_H + +#define TA_SDP_BASIC_UUID { 0x12345678, 0x5b69, 0x11e4, \ + { 0x9d, 0xbb, 0x10, 0x1f, 0x74, 0xf0, 0x00, 0x99 } } + +#define TA_SDP_BASIC_CMD_INJECT 0 +#define TA_SDP_BASIC_CMD_TRANSFORM 1 +#define TA_SDP_BASIC_CMD_DUMP 2 + +#define TA_SDP_BASIC_CMD_INVOKE_INJECT 3 +#define TA_SDP_BASIC_CMD_INVOKE_TRANSFORM 4 +#define TA_SDP_BASIC_CMD_INVOKE_DUMP 5 + +#define TA_SDP_BASIC_CMD_PTA_INJECT 6 +#define TA_SDP_BASIC_CMD_PTA_TRANSFORM 7 +#define TA_SDP_BASIC_CMD_PTA_DUMP 8 + +#endif /* TA_SDP_BASIC_H */ diff --git a/optee/optee_test/ta/sdp_basic/include/user_ta_header_defines.h b/optee/optee_test/ta/sdp_basic/include/user_ta_header_defines.h new file mode 100644 index 0000000..3a44c23 --- /dev/null +++ b/optee/optee_test/ta/sdp_basic/include/user_ta_header_defines.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include "ta_sdp_basic.h" + +#define TA_UUID TA_SDP_BASIC_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \ + TA_FLAG_SECURE_DATA_PATH | \ + TA_FLAG_CACHE_MAINTENANCE) + +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/sdp_basic/sub.mk b/optee/optee_test/ta/sdp_basic/sub.mk new file mode 100644 index 0000000..7982705 --- /dev/null +++ b/optee/optee_test/ta/sdp_basic/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ta_sdp_basic.c diff --git a/optee/optee_test/ta/sdp_basic/ta_sdp_basic.c b/optee/optee_test/ta/sdp_basic/ta_sdp_basic.c new file mode 100644 index 0000000..1f9485e --- /dev/null +++ b/optee/optee_test/ta/sdp_basic/ta_sdp_basic.c @@ -0,0 +1,369 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Basic Secure Data Path access test commands: + * - command INJECT: copy from non secure input into secure output. + * - command TRANSFROM: read, transform and write from/to secure in/out. + * - command DUMP: copy from secure input into non secure output. + */ + +static TEE_Result cmd_inject(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_ERROR_GENERIC; + const int sec_idx = 1; /* highlight secure buffer index */ + const int ns_idx = 0; /* highlight nonsecure buffer index */ + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) { + EMSG("bad parameters %x", (unsigned)types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[sec_idx].memref.size < params[ns_idx].memref.size) + return TEE_ERROR_SHORT_BUFFER; + + /* + * We could rely on the TEE to provide consistent buffer/size values + * to reference a buffer with a unique and consistent secure attribute + * value. Hence it is safe enough (and more optimal) to test only the + * secure attribute of a single byte of it. Yet, since the current + * test does not deal with performance, let check the secure attribute + * of each byte of the buffer. + */ + rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER | + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_NONSECURE, + params[ns_idx].memref.buffer, + params[ns_idx].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CheckMemoryAccessRights(nsec) failed %x", rc); + return rc; + } + + rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_SECURE, + params[sec_idx].memref.buffer, + params[sec_idx].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CheckMemoryAccessRights(secure) failed %x", rc); + return rc; + } + + +#ifdef CFG_CACHE_API + /* + * we should invalidate cache (here we assume buffer were not + * filled through cpu core caches. We flush buffers so that + * cache is not corrupted in cache target buffer not aligned + * on cache line size. + */ + rc = TEE_CacheFlush(params[sec_idx].memref.buffer, + params[sec_idx].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x", + params[sec_idx].memref.buffer, + params[sec_idx].memref.size, rc); + return rc; + } +#endif /* CFG_CACHE_API */ + + /* inject data */ + TEE_MemMove(params[sec_idx].memref.buffer, + params[ns_idx].memref.buffer, + params[sec_idx].memref.size); + +#ifdef CFG_CACHE_API + rc = TEE_CacheFlush(params[sec_idx].memref.buffer, + params[sec_idx].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x", + params[sec_idx].memref.buffer, + params[sec_idx].memref.size, rc); + return rc; + } +#endif /* CFG_CACHE_API */ + + return rc; +} + +static TEE_Result cmd_transform(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_ERROR_GENERIC; + unsigned char *p = NULL; + size_t sz = 0; + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + /* + * We could rely on the TEE to provide consistent buffer/size values + * to reference a buffer with a unique and consistent secure attribute + * value. Hence it is safe enough (and more optimal) to test only the + * secure attribute of a single byte of it. Yet, since the current + * test does not deal with performance, let check the secure attribute + * of each byte of the buffer. + */ + rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER | + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_SECURE, + params[0].memref.buffer, + params[0].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CheckMemoryAccessRights(secure) failed %x", rc); + return rc; + } + + +#ifdef CFG_CACHE_API + /* + * we should invalidate cache (here we assume buffer were not + * filled through cpu core caches. We flush buffers so that + * cache is not corrupted in cache target buffer not aligned + * on cache line size. + */ + rc = TEE_CacheFlush(params[0].memref.buffer, + params[0].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x", + params[0].memref.buffer, + params[0].memref.size, rc); + return rc; + } +#endif /* CFG_CACHE_API */ + + /* transform the data */ + p = (unsigned char *)params[0].memref.buffer; + sz = params[0].memref.size; + for (; sz; sz--, p++) + *p = ~(*p) + 1; + +#ifdef CFG_CACHE_API + rc = TEE_CacheFlush(params[0].memref.buffer, + params[0].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x", + params[0].memref.buffer, + params[0].memref.size, rc); + return rc; + } +#endif /* CFG_CACHE_API */ + + return rc; +} + +static TEE_Result cmd_dump(uint32_t types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_ERROR_GENERIC; + const int sec_idx = 0; /* highlight secure buffer index */ + const int ns_idx = 1; /* highlight nonsecure buffer index */ + + if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[ns_idx].memref.size < params[sec_idx].memref.size) + return TEE_ERROR_SHORT_BUFFER; + + /* + * We could rely on the TEE to provide consistent buffer/size values + * to reference a buffer with a unique and consistent secure attribute + * value. Hence it is safe enough (and more optimal) to test only the + * secure attribute of a single byte of it. Yet, since the current + * test does not deal with performance, let check the secure attribute + * of each byte of the buffer. + */ + rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER | + TEE_MEMORY_ACCESS_WRITE | + TEE_MEMORY_ACCESS_NONSECURE, + params[ns_idx].memref.buffer, + params[ns_idx].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CheckMemoryAccessRights(nsec) failed %x", rc); + return rc; + } + + rc = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_ANY_OWNER | + TEE_MEMORY_ACCESS_READ | + TEE_MEMORY_ACCESS_SECURE, + params[sec_idx].memref.buffer, + params[sec_idx].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CheckMemoryAccessRights(secure) failed %x", rc); + return rc; + } + +#ifdef CFG_CACHE_API + /* + * we should invalidate cache (here we assume buffer were not + * filled through cpu core caches. We flush buffers so that + * cache is not corrupted in cache target buffer not aligned + * on cache line size. + */ + rc = TEE_CacheFlush(params[sec_idx].memref.buffer, + params[sec_idx].memref.size); + if (rc != TEE_SUCCESS) { + EMSG("TEE_CacheFlush(%p, %x) failed: 0x%x", + params[sec_idx].memref.buffer, + params[sec_idx].memref.size, rc); + return rc; + } +#endif /* CFG_CACHE_API */ + + /* dump the data */ + TEE_MemMove(params[ns_idx].memref.buffer, + params[sec_idx].memref.buffer, + params[sec_idx].memref.size); + + return rc; +} + +static TEE_Result cmd_invoke(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS], + uint32_t nCommandID) +{ + const TEE_UUID uuid = TA_SDP_BASIC_UUID; + static TEE_TASessionHandle sess = TEE_HANDLE_NULL; + uint32_t ret_orig = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (sess == TEE_HANDLE_NULL) { + res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("SDP basic test TA: TEE_OpenTASession() FAILED \n"); + goto cleanup_return; + } + + } + + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + nCommandID, nParamTypes, pParams, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("SDP basic test TA: TEE_OpenTASession() FAILED %x/%d\n", + res, ret_orig); + } + +cleanup_return: + if (res != TEE_SUCCESS) { + TEE_CloseTASession(sess); + sess = TEE_HANDLE_NULL; + } + return res; +} + +static TEE_Result cmd_invoke_pta(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS], + uint32_t nCommandID) +{ + const TEE_UUID uuid = PTA_INVOKE_TESTS_UUID; + static TEE_TASessionHandle sess = TEE_HANDLE_NULL; + uint32_t ret_orig = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + if (sess == TEE_HANDLE_NULL) { + res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("SDP basic test TA: TEE_OpenTASession() FAILED \n"); + goto cleanup_return; + } + + } + + res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, + nCommandID, nParamTypes, pParams, &ret_orig); + if (res != TEE_SUCCESS) { + EMSG("SDP basic test TA: TEE_OpenTASession() FAILED %x/%d\n", + res, ret_orig); + } + +cleanup_return: + if (res != TEE_SUCCESS) { + TEE_CloseTASession(sess); + sess = TEE_HANDLE_NULL; + } + return res; +} + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; +} + +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[TEE_NUM_PARAMS]) +{ + (void)pSessionContext; + + switch (nCommandID) { + case TA_SDP_BASIC_CMD_INJECT: + return cmd_inject(nParamTypes, pParams); + case TA_SDP_BASIC_CMD_TRANSFORM: + return cmd_transform(nParamTypes, pParams); + case TA_SDP_BASIC_CMD_DUMP: + return cmd_dump(nParamTypes, pParams); + + case TA_SDP_BASIC_CMD_INVOKE_INJECT: + return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_INJECT); + case TA_SDP_BASIC_CMD_INVOKE_TRANSFORM: + return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_TRANSFORM); + case TA_SDP_BASIC_CMD_INVOKE_DUMP: + return cmd_invoke(nParamTypes, pParams, TA_SDP_BASIC_CMD_DUMP); + + case TA_SDP_BASIC_CMD_PTA_INJECT: + return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC); + case TA_SDP_BASIC_CMD_PTA_TRANSFORM: + return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC); + case TA_SDP_BASIC_CMD_PTA_DUMP: + return cmd_invoke_pta(nParamTypes, pParams, PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/sims/Android.mk b/optee/optee_test/ta/sims/Android.mk new file mode 100644 index 0000000..52aa62f --- /dev/null +++ b/optee/optee_test/ta/sims/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := e6a33ed4-562b-463a-bb7e-ff5e15a493c8.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/sims/Makefile b/optee/optee_test/ta/sims/Makefile new file mode 100644 index 0000000..70ab763 --- /dev/null +++ b/optee/optee_test/ta/sims/Makefile @@ -0,0 +1,2 @@ +BINARY = e6a33ed4-562b-463a-bb7e-ff5e15a493c8 +include ../ta_common.mk diff --git a/optee/optee_test/ta/sims/include/ta_sims.h b/optee/optee_test/ta/sims/include/ta_sims.h new file mode 100644 index 0000000..c3f6900 --- /dev/null +++ b/optee/optee_test/ta/sims/include/ta_sims.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef TA_SIMS_H +#define TA_SIMS_H + +#include +#include + +TEE_Result sims_open_session(void **ctx); +TEE_Result sims_open_ta_session(void *ctx, uint32_t nParamTypes, + TEE_Param pParams[4]); +void sims_close_session(void *ctx); +TEE_Result sims_read(uint32_t nParamTypes, TEE_Param pParams[4]); +TEE_Result sims_write(uint32_t nParamTypes, TEE_Param pParams[4]); +TEE_Result sims_get_counter(void *session_context, uint32_t param_types, + TEE_Param params[4]); +TEE_Result sims_entry_panic(void *session_context, uint32_t nParamTypes, + TEE_Param pParams[4]); + +#endif diff --git a/optee/optee_test/ta/sims/include/ta_sims_test.h b/optee/optee_test/ta/sims/include/ta_sims_test.h new file mode 100644 index 0000000..4bd9d33 --- /dev/null +++ b/optee/optee_test/ta/sims/include/ta_sims_test.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef TA_SIMS_TEST_H +#define TA_SIMS_TEST_H + +/* This UUID is generated with uuidgen */ +#define TA_SIMS_TEST_UUID { 0xe6a33ed4, 0x562b, 0x463a, \ + { 0xbb, 0x7e, 0xff, 0x5e, 0x15, 0xa4, 0x93, 0xc8 } } + +#define TA_SIMS_CMD_READ 1 +#define TA_SIMS_CMD_WRITE 2 +#define TA_SIMS_CMD_GET_COUNTER 3 +#define TA_SIMS_CMD_PANIC 4 +#define TA_SIMS_OPEN_TA_SESSION 5 + +#endif diff --git a/optee/optee_test/ta/sims/include/user_ta_header_defines.h b/optee/optee_test/ta/sims/include/user_ta_header_defines.h new file mode 100644 index 0000000..bc58488 --- /dev/null +++ b/optee/optee_test/ta/sims/include/user_ta_header_defines.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_SIMS_TEST_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \ + TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_MULTI_SESSION) +#define TA_STACK_SIZE (4 * 1024) +#define TA_DATA_SIZE (64 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/sims/sub.mk b/optee/optee_test/ta/sims/sub.mk new file mode 100644 index 0000000..bbdeb62 --- /dev/null +++ b/optee/optee_test/ta/sims/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += include +global-incdirs-y += ../sims_keepalive/include +srcs-y += ta_entry.c +srcs-y += ta_sims.c diff --git a/optee/optee_test/ta/sims/ta_entry.c b/optee/optee_test/ta/sims/ta_entry.c new file mode 100644 index 0000000..18d18dc --- /dev/null +++ b/optee/optee_test/ta/sims/ta_entry.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include +#include +#include + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + return sims_open_session(ppSessionContext); +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + sims_close_session(pSessionContext); +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + switch (nCommandID) { + case TA_SIMS_OPEN_TA_SESSION: + return sims_open_ta_session(pSessionContext, + nParamTypes, pParams); + + case TA_SIMS_CMD_READ: + return sims_read(nParamTypes, pParams); + + case TA_SIMS_CMD_WRITE: + return sims_write(nParamTypes, pParams); + + case TA_SIMS_CMD_GET_COUNTER: + return sims_get_counter(pSessionContext, nParamTypes, pParams); + + case TA_SIMS_CMD_PANIC: + return sims_entry_panic(pSessionContext, nParamTypes, pParams); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/sims/ta_sims.c b/optee/optee_test/ta/sims/ta_sims.c new file mode 100644 index 0000000..0e8e5b2 --- /dev/null +++ b/optee/optee_test/ta/sims/ta_sims.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include +#include + +#define TA_SIMS_MAX_STORAGE 4 + +struct sims_bucket { + uint32_t size; + void *data; +}; + +struct sims_session { + TEE_TASessionHandle sess; + uint32_t counter; + uint32_t array[2048]; +}; + +static struct sims_bucket storage[TA_SIMS_MAX_STORAGE] = { {0} }; + +static uint32_t counter; + +TEE_Result sims_open_ta_session(void *session_context, uint32_t param_types, + TEE_Param params[4]) +{ + TEE_UUID *uuid = NULL; + TEE_Result res = TEE_SUCCESS; + TEE_TASessionHandle sess = TEE_HANDLE_NULL; + uint32_t ret_orig = 0; + struct sims_session *ctx = (struct sims_session *)session_context; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].memref.size != sizeof(*uuid)) + return TEE_ERROR_BAD_PARAMETERS; + + uuid = TEE_Malloc(sizeof(*uuid), TEE_MALLOC_FILL_ZERO); + if (!uuid) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_MemMove(uuid, params[0].memref.buffer, params[0].memref.size); + + res = TEE_OpenTASession(uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &sess, &ret_orig); + TEE_Free(uuid); + if (res != TEE_SUCCESS) + return res; + + ctx->sess = sess; + ctx->counter++; + + return TEE_SUCCESS; +} + +TEE_Result sims_open_session(void **ctx) +{ + struct sims_session *context = + TEE_Malloc(sizeof(struct sims_session), TEE_MALLOC_FILL_ZERO); + + if (context == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + context->sess = TEE_HANDLE_NULL; + context->counter = counter; + *ctx = context; + + counter++; + + return TEE_SUCCESS; +} + +void sims_close_session(void *ctx) +{ + TEE_TASessionHandle sess = ((struct sims_session *)ctx)->sess; + + if (sess != TEE_HANDLE_NULL) + TEE_CloseTASession(sess); + + TEE_Free(ctx); +} + +TEE_Result sims_read(uint32_t param_types, TEE_Param params[4]) +{ + uint32_t index = 0; + void *p = NULL; + + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0)) + return TEE_ERROR_BAD_PARAMETERS; + + index = params[0].value.a; + if (index >= TA_SIMS_MAX_STORAGE) + return TEE_ERROR_BAD_PARAMETERS; + + if (storage[index].size > params[1].memref.size) + return TEE_ERROR_OVERFLOW; + + p = TEE_Malloc(16000, 0); + if (p == NULL) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_MemMove(params[1].memref.buffer, storage[index].data, + params[1].memref.size); + + TEE_Free(p); + + return TEE_SUCCESS; +} + +TEE_Result sims_write(uint32_t param_types, TEE_Param params[4]) +{ + uint32_t index = 0; + + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0)) + return TEE_ERROR_BAD_PARAMETERS; + + index = params[0].value.a; + if (index >= TA_SIMS_MAX_STORAGE) + return TEE_ERROR_BAD_PARAMETERS; + + if (storage[index].data != NULL) + TEE_Free(storage[index].data); + + storage[index].data = TEE_Malloc(params[1].memref.size, 0); + if (storage[index].data == NULL) { + storage[index].size = 0; + return TEE_ERROR_OUT_OF_MEMORY; + } + storage[index].size = params[1].memref.size; + + TEE_MemMove(storage[index].data, params[1].memref.buffer, + params[1].memref.size); + + return TEE_SUCCESS; +} + +TEE_Result sims_get_counter(void *session_context, uint32_t param_types, + TEE_Param params[4]) +{ + struct sims_session *ctx = (struct sims_session *)session_context; + + if (param_types != + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 0, 0, 0)) + return TEE_ERROR_BAD_PARAMETERS; + + params[0].value.a = ctx->counter; + + return TEE_SUCCESS; +} + +TEE_Result sims_entry_panic(void *session_context, uint32_t param_types, + TEE_Param params[4]) +{ + uint32_t ret_orig = 0; + TEE_Result res = TEE_SUCCESS; + struct sims_session *ctx = (struct sims_session *)session_context; + + if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[0].memref.buffer && params[0].memref.size) { + res = sims_open_ta_session(session_context, + param_types, params); + if (res != TEE_SUCCESS) + return res; + + params[0].memref.buffer = NULL; + params[0].memref.size = 0; + + /* Trigger panic to remote TA */ + (void)TEE_InvokeTACommand(ctx->sess, TEE_TIMEOUT_INFINITE, + TA_SIMS_CMD_PANIC, + param_types, params, + &ret_orig); + } else { + TEE_Panic(0xbeef); /* Trigger panic to current TA */ + } + + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/sims_keepalive/Android.mk b/optee/optee_test/ta/sims_keepalive/Android.mk new file mode 100644 index 0000000..9ca1077 --- /dev/null +++ b/optee/optee_test/ta/sims_keepalive/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := a4c04d50-f180-11e8-8eb2-f2801f1b9fd1.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/sims_keepalive/Makefile b/optee/optee_test/ta/sims_keepalive/Makefile new file mode 100644 index 0000000..171f80d --- /dev/null +++ b/optee/optee_test/ta/sims_keepalive/Makefile @@ -0,0 +1,2 @@ +BINARY = a4c04d50-f180-11e8-8eb2-f2801f1b9fd1 +include ../ta_common.mk diff --git a/optee/optee_test/ta/sims_keepalive/include/ta_sims_keepalive_test.h b/optee/optee_test/ta/sims_keepalive/include/ta_sims_keepalive_test.h new file mode 100644 index 0000000..01a829b --- /dev/null +++ b/optee/optee_test/ta/sims_keepalive/include/ta_sims_keepalive_test.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2019, Mentor Graphics Corporation + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef TA_SIMS_KEEP_ALIVE_TEST_H +#define TA_SIMS_KEEP_ALIVE_TEST_H + +/* This UUID is generated with uuidgen */ +#define TA_SIMS_KEEP_ALIVE_TEST_UUID { 0xa4c04d50, 0xf180, 0x11e8, \ + { 0x8e, 0xb2, 0xf2, 0x80, 0x1f, 0x1b, 0x9f, 0xd1 } } + +#endif /* TA_SIMS_KEEP_ALIVE_TEST_H */ diff --git a/optee/optee_test/ta/sims_keepalive/include/user_ta_header_defines.h b/optee/optee_test/ta/sims_keepalive/include/user_ta_header_defines.h new file mode 100644 index 0000000..e414a30 --- /dev/null +++ b/optee/optee_test/ta/sims_keepalive/include/user_ta_header_defines.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019, Mentor Graphics Corporation + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_NAME "SIMS_KEEPALIVE" +#define TA_UUID TA_SIMS_KEEP_ALIVE_TEST_UUID + +#define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_MULTI_SESSION | \ + TA_FLAG_INSTANCE_KEEP_ALIVE) +#define TA_STACK_SIZE (4 * 1024) +#define TA_DATA_SIZE (64 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/sims_keepalive/sub.mk b/optee/optee_test/ta/sims_keepalive/sub.mk new file mode 100644 index 0000000..acbd063 --- /dev/null +++ b/optee/optee_test/ta/sims_keepalive/sub.mk @@ -0,0 +1,6 @@ +global-incdirs-y += include +global-incdirs-y += ../sims/include +global-incdirs-y += ../sims_keepalive/include + +srcs-y += ta_entry.c +srcs-y += ta_sims_keepalive.c diff --git a/optee/optee_test/ta/sims_keepalive/ta_entry.c b/optee/optee_test/ta/sims_keepalive/ta_entry.c new file mode 100644 index 0000000..304d952 --- /dev/null +++ b/optee/optee_test/ta/sims_keepalive/ta_entry.c @@ -0,0 +1 @@ +#include "../sims/ta_entry.c" diff --git a/optee/optee_test/ta/sims_keepalive/ta_sims_keepalive.c b/optee/optee_test/ta/sims_keepalive/ta_sims_keepalive.c new file mode 100644 index 0000000..5006c64 --- /dev/null +++ b/optee/optee_test/ta/sims_keepalive/ta_sims_keepalive.c @@ -0,0 +1 @@ +#include "../sims/ta_sims.c" diff --git a/optee/optee_test/ta/socket/Android.mk b/optee/optee_test/ta/socket/Android.mk new file mode 100644 index 0000000..446afda --- /dev/null +++ b/optee/optee_test/ta/socket/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 873bcd08-c2c3-11e6-a937-d0bf9c45c61c.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/socket/Makefile b/optee/optee_test/ta/socket/Makefile new file mode 100644 index 0000000..48db92a --- /dev/null +++ b/optee/optee_test/ta/socket/Makefile @@ -0,0 +1,2 @@ +BINARY = 873bcd08-c2c3-11e6-a937-d0bf9c45c61c +include ../ta_common.mk diff --git a/optee/optee_test/ta/socket/include/ta_socket.h b/optee/optee_test/ta/socket/include/ta_socket.h new file mode 100644 index 0000000..4a45eb7 --- /dev/null +++ b/optee/optee_test/ta/socket/include/ta_socket.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + */ + +#ifndef __TA_SOCKET_H +#define __TA_SOCKET_H + +#define TA_SOCKET_UUID { 0x873bcd08, 0xc2c3, 0x11e6, { \ + 0xa9, 0x37, 0xd0, 0xbf, 0x9c, 0x45, 0xc6, 0x1c } } + +/* + * Opens a TCP socket and returns an opaque handle + * + * [in] params[0].value.a ipVersion + * [in] params[0].value.b server port + * [in] params[1].memref server address + * [out] params[2].memref handle + * [out] params[3].value.a protocol error + */ +#define TA_SOCKET_CMD_TCP_OPEN 0 + +/* + * Opens a UDP socket and returns an opaque handle + * + * [in] params[0].value.a ipVersion + * [in] params[0].value.b server port + * [in] params[1].memref server address + * [out] params[2].memref handle + * [out] params[3].value.a protocol error + */ +#define TA_SOCKET_CMD_UDP_OPEN 1 + +/* + * Closes a socket + * + * [in] params[0].memref handle + */ +#define TA_SOCKET_CMD_CLOSE 2 + +/* + * Send data on socket + * + * [in] params[0].memref handle + * [in] params[1].memref data + * [in] params[2].value.a timeout + * [out] params[2].value.b sent bytes + */ +#define TA_SOCKET_CMD_SEND 3 + +/* + * Receive data on socket + * + * [in] params[0].memref handle + * [out] params[1].memref data + * [in] params[2].value.a timeout + */ +#define TA_SOCKET_CMD_RECV 4 + +/* + * Retrieve protocol error from socket + * + * [in] params[0].memref handle + * [out] params[1].value.a error code + */ +#define TA_SOCKET_CMD_ERROR 5 + +/* + * Ioctl on socket + * + * [in] params[0].memref handle + * [in/out] params[1].memref data + * [in] params[2].value.a command code + */ +#define TA_SOCKET_CMD_IOCTL 6 + +#endif /*__TA_SOCKET_H*/ diff --git a/optee/optee_test/ta/socket/include/user_ta_header_defines.h b/optee/optee_test/ta/socket/include/user_ta_header_defines.h new file mode 100644 index 0000000..5abd235 --- /dev/null +++ b/optee/optee_test/ta/socket/include/user_ta_header_defines.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include + +#define TA_UUID TA_SOCKET_UUID + +#define TA_FLAGS ( TA_FLAG_EXEC_DDR | TA_FLAG_MULTI_SESSION) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_test/ta/socket/sub.mk b/optee/optee_test/ta/socket/sub.mk new file mode 100644 index 0000000..d5e3f32 --- /dev/null +++ b/optee/optee_test/ta/socket/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/socket/ta_entry.c b/optee/optee_test/ta/socket/ta_entry.c new file mode 100644 index 0000000..698aa6a --- /dev/null +++ b/optee/optee_test/ta/socket/ta_entry.c @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2016, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types, + TEE_Param params[4], + void **session_ctx) +{ + (void)param_types; + (void)params; + (void)session_ctx; + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *session_ctx) +{ + (void)session_ctx; +} + +struct sock_handle { + TEE_iSocketHandle ctx; + TEE_iSocket *socket; +}; + +static TEE_Result ta_entry_tcp_open(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct sock_handle h = { }; + TEE_tcpSocket_Setup setup = { }; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[2].memref.size < sizeof(struct sock_handle)) { + params[2].memref.size = sizeof(struct sock_handle); + return TEE_ERROR_SHORT_BUFFER; + } + + setup.ipVersion = params[0].value.a; + setup.server_port = params[0].value.b; + setup.server_addr = strndup(params[1].memref.buffer, + params[1].memref.size); + if (!setup.server_addr) + return TEE_ERROR_OUT_OF_MEMORY; + + h.socket = TEE_tcpSocket; + res = h.socket->open(&h.ctx, &setup, ¶ms[3].value.a); + free(setup.server_addr); + if (res == TEE_SUCCESS) { + memcpy(params[2].memref.buffer, &h, sizeof(h)); + params[2].memref.size = sizeof(h); + } + return res; +} + +static TEE_Result ta_entry_udp_open(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct sock_handle h = { }; + TEE_udpSocket_Setup setup = { }; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[2].memref.size < sizeof(struct sock_handle)) { + params[2].memref.size = sizeof(struct sock_handle); + return TEE_ERROR_SHORT_BUFFER; + } + + setup.ipVersion = params[0].value.a; + setup.server_port = params[0].value.b; + setup.server_addr = strndup(params[1].memref.buffer, + params[1].memref.size); + if (!setup.server_addr) + return TEE_ERROR_OUT_OF_MEMORY; + + h.socket = TEE_udpSocket; + res = h.socket->open(&h.ctx, &setup, ¶ms[3].value.a); + free(setup.server_addr); + if (res == TEE_SUCCESS) { + memcpy(params[2].memref.buffer, &h, sizeof(h)); + params[2].memref.size = sizeof(h); + } + return res; +} + +static TEE_Result ta_entry_close(uint32_t param_types, TEE_Param params[4]) +{ + struct sock_handle *h = NULL; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size != sizeof(struct sock_handle)) + return TEE_ERROR_BAD_PARAMETERS; + + h = params[0].memref.buffer; + return h->socket->close(h->ctx); +} + +static TEE_Result ta_entry_send(uint32_t param_types, TEE_Param params[4]) +{ + struct sock_handle *h = NULL; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_NONE); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size != sizeof(*h)) + return TEE_ERROR_BAD_PARAMETERS; + + h = params[0].memref.buffer; + params[2].value.b = params[1].memref.size; + return h->socket->send(h->ctx, params[1].memref.buffer, + ¶ms[2].value.b, params[2].value.a); +} + +static TEE_Result ta_entry_recv(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_SUCCESS; + struct sock_handle *h = NULL; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE); + uint32_t sz = 0; + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size != sizeof(struct sock_handle)) + return TEE_ERROR_BAD_PARAMETERS; + + h = params[0].memref.buffer; + sz = params[1].memref.size; + res = h->socket->recv(h->ctx, params[1].memref.buffer, &sz, + params[2].value.a); + params[1].memref.size = sz; + return res; +} + +static TEE_Result ta_entry_error(uint32_t param_types, TEE_Param params[4]) +{ + struct sock_handle *h = NULL; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size != sizeof(struct sock_handle)) + return TEE_ERROR_BAD_PARAMETERS; + + h = params[0].memref.buffer; + params[1].value.a = h->socket->error(h->ctx); + return TEE_SUCCESS; +} + +static TEE_Result ta_entry_ioctl(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_SUCCESS; + struct sock_handle *h = NULL; + uint32_t req_param_types = + TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE); + uint32_t sz = 0; + + if (param_types != req_param_types) { + EMSG("got param_types 0x%x, expected 0x%x", + param_types, req_param_types); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (params[0].memref.size != sizeof(struct sock_handle)) + return TEE_ERROR_BAD_PARAMETERS; + + h = params[0].memref.buffer; + sz = params[1].memref.size; + res = h->socket->ioctl(h->ctx, params[2].value.a, + params[1].memref.buffer, &sz); + params[1].memref.size = sz; + return res; +} + + + +TEE_Result TA_InvokeCommandEntryPoint(void *session_ctx, + uint32_t cmd_id, uint32_t param_types, + TEE_Param params[4]) +{ + (void)session_ctx; + + switch (cmd_id) { + case TA_SOCKET_CMD_TCP_OPEN: + return ta_entry_tcp_open(param_types, params); + case TA_SOCKET_CMD_UDP_OPEN: + return ta_entry_udp_open(param_types, params); + case TA_SOCKET_CMD_CLOSE: + return ta_entry_close(param_types, params); + case TA_SOCKET_CMD_SEND: + return ta_entry_send(param_types, params); + case TA_SOCKET_CMD_RECV: + return ta_entry_recv(param_types, params); + case TA_SOCKET_CMD_ERROR: + return ta_entry_error(param_types, params); + case TA_SOCKET_CMD_IOCTL: + return ta_entry_ioctl(param_types, params); + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/storage/Android.mk b/optee/optee_test/ta/storage/Android.mk new file mode 100644 index 0000000..c19b55d --- /dev/null +++ b/optee/optee_test/ta/storage/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := b689f2a7-8adf-477a-9f99-32e90c0ad0a2.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/storage/Makefile b/optee/optee_test/ta/storage/Makefile new file mode 100644 index 0000000..b30802f --- /dev/null +++ b/optee/optee_test/ta/storage/Makefile @@ -0,0 +1,2 @@ +BINARY = b689f2a7-8adf-477a-9f99-32e90c0ad0a2 +include ../ta_common.mk diff --git a/optee/optee_test/ta/storage/include/storage.h b/optee/optee_test/ta/storage/include/storage.h new file mode 100644 index 0000000..ecbda8a --- /dev/null +++ b/optee/optee_test/ta/storage/include/storage.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef STORAGE_H +#define STORAGE_H + +#include + +TEE_Result ta_storage_cmd_open(uint32_t command, uint32_t param_types, + TEE_Param params[4]); +TEE_Result ta_storage_cmd_create(uint32_t command, uint32_t param_types, + TEE_Param params[4]); +TEE_Result ta_storage_cmd_create_overwrite(uint32_t command, + uint32_t param_types, + TEE_Param params[4]); +TEE_Result ta_storage_cmd_close(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_read(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_write(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_seek(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_unlink(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_rename(uint32_t command, uint32_t param_types, + TEE_Param params[4]); +TEE_Result ta_storage_cmd_trunc(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_alloc_enum(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_free_enum(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_reset_enum(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_start_enum(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_next_enum(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_key_in_persistent(uint32_t param_types, + TEE_Param params[4]); +TEE_Result ta_storage_cmd_loop(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_restrict_usage(uint32_t param_types, + TEE_Param params[4]); +TEE_Result ta_storage_cmd_alloc_obj(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_free_obj(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_reset_obj(uint32_t param_types, TEE_Param params[4]); +TEE_Result ta_storage_cmd_get_obj_info(uint32_t param_types, + TEE_Param params[4]); + +#endif /*STORAGE_H */ diff --git a/optee/optee_test/ta/storage/include/user_ta_header_defines.h b/optee/optee_test/ta/storage/include/user_ta_header_defines.h new file mode 100644 index 0000000..1d92759 --- /dev/null +++ b/optee/optee_test/ta/storage/include/user_ta_header_defines.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_STORAGE_UUID + +/* + * This is important to have TA_FLAG_SINGLE_INSTANCE && !TA_FLAG_MULTI_SESSION + * as it is used by the ytest + */ +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \ + TA_FLAG_MULTI_SESSION) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (64 * 1024) + +#endif diff --git a/optee/optee_test/ta/storage/storage.c b/optee/optee_test/ta/storage/storage.c new file mode 100644 index 0000000..93548a3 --- /dev/null +++ b/optee/optee_test/ta/storage/storage.c @@ -0,0 +1,664 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include "storage.h" +#include "ta_storage.h" + +#include +#include + +#define ASSERT_PARAM_TYPE(pt) \ +do { \ + if ((pt) != param_types) \ + return TEE_ERROR_BAD_PARAMETERS; \ +} while (0) + +#define VAL2HANDLE(v) (void *)(uintptr_t)(v) + +TEE_Result ta_storage_cmd_open(uint32_t command, + uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle o = TEE_HANDLE_NULL; + void *object_id = NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE)); + + switch (command) { + case TA_STORAGE_CMD_OPEN: + if (params[0].memref.buffer) { + object_id = TEE_Malloc(params[0].memref.size, 0); + if (!object_id) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_MemMove(object_id, params[0].memref.buffer, + params[0].memref.size); + } + break; + case TA_STORAGE_CMD_OPEN_ID_IN_SHM: + object_id = params[0].memref.buffer; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + res = TEE_OpenPersistentObject(params[2].value.a, + object_id, params[0].memref.size, + params[1].value.a, &o); + + params[1].value.b = (uintptr_t)o; + + if (command == TA_STORAGE_CMD_OPEN) + TEE_Free(object_id); + + return res; +} + +TEE_Result ta_storage_cmd_create(uint32_t command, + uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle o = TEE_HANDLE_NULL; + void *object_id = NULL; + TEE_ObjectHandle ref_handle = TEE_HANDLE_NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT)); + + switch (command) { + case TA_STORAGE_CMD_CREATE: + if (params[0].memref.buffer) { + object_id = TEE_Malloc(params[0].memref.size, 0); + if (!object_id) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_MemMove(object_id, params[0].memref.buffer, + params[0].memref.size); + } + break; + case TA_STORAGE_CMD_CREATE_ID_IN_SHM: + object_id = params[0].memref.buffer; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + ref_handle = (TEE_ObjectHandle)(uintptr_t)params[2].value.a; + + res = TEE_CreatePersistentObject(params[2].value.b, + object_id, params[0].memref.size, + params[1].value.a, ref_handle, + params[3].memref.buffer, + params[3].memref.size, &o); + + if (command == TA_STORAGE_CMD_CREATE) + TEE_Free(object_id); + + params[1].value.b = (uintptr_t)o; + + return res; +} + +TEE_Result ta_storage_cmd_create_overwrite(uint32_t command, + uint32_t param_types, + TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle o = TEE_HANDLE_NULL; + void *object_id = NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + switch (command) { + case TA_STORAGE_CMD_CREATE_OVERWRITE: + object_id = TEE_Malloc(params[0].memref.size, 0); + if (!object_id) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_MemMove(object_id, params[0].memref.buffer, + params[0].memref.size); + break; + case TA_STORAGE_CMD_CREATEOVER_ID_IN_SHM: + object_id = params[0].memref.buffer; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + res = TEE_CreatePersistentObject(params[1].value.a, + object_id, params[0].memref.size, + TEE_DATA_FLAG_OVERWRITE, + NULL, NULL, 0, &o); + TEE_CloseObject(o); + + if (command == TA_STORAGE_CMD_CREATE_OVERWRITE) + TEE_Free(object_id); + + return res; +} + +TEE_Result ta_storage_cmd_close(uint32_t param_types, TEE_Param params[4]) +{ + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + TEE_CloseObject((TEE_ObjectHandle)(uintptr_t)params[0].value.a); + + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_read(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectHandle o = VAL2HANDLE(params[1].value.a); + TEE_Result res = TEE_SUCCESS; + size_t sz = 0; + void *b0 = NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + b0 = TEE_Malloc(params[0].memref.size, 0); + if (!b0) + return TEE_ERROR_OUT_OF_MEMORY; + + sz = params[1].value.b; + res = TEE_ReadObjectData(o, b0, params[0].memref.size, &sz); + params[1].value.b = sz; + if (!res) + TEE_MemMove(params[0].memref.buffer, b0, params[0].memref.size); + TEE_Free(b0); + + return res; +} + +TEE_Result ta_storage_cmd_write(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectHandle o = VAL2HANDLE(params[1].value.a); + TEE_Result res = TEE_SUCCESS; + void *b0 = NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + b0 = TEE_Malloc(params[0].memref.size, 0); + if (!b0) + return TEE_ERROR_OUT_OF_MEMORY; + TEE_MemMove(b0, params[0].memref.buffer, params[0].memref.size); + + res = TEE_WriteObjectData(o, b0, params[0].memref.size); + TEE_Free(b0); + + return res; +} + +TEE_Result ta_storage_cmd_seek(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectInfo info; + TEE_ObjectHandle o = VAL2HANDLE(params[0].value.a); + int32_t offs = 0; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + offs = *(int32_t *)¶ms[0].value.b; + res = TEE_SeekObjectData(o, offs, params[1].value.a); + if (res != TEE_SUCCESS) + return res; + res = TEE_GetObjectInfo1(o, &info); + + params[1].value.b = info.dataPosition; + + return res; +} + +TEE_Result ta_storage_cmd_unlink(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectHandle o = VAL2HANDLE(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + TEE_CloseAndDeletePersistentObject1(o); + + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_rename(uint32_t command, uint32_t param_types, + TEE_Param params[4]) +{ + TEE_ObjectHandle o = VAL2HANDLE(params[0].value.a); + void *object_id = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + switch (command) { + case TA_STORAGE_CMD_RENAME: + if (params[0].memref.buffer) { + object_id = TEE_Malloc(params[1].memref.size, 0); + if (!object_id) + return TEE_ERROR_OUT_OF_MEMORY; + + TEE_MemMove(object_id, params[1].memref.buffer, + params[1].memref.size); + } + break; + case TA_STORAGE_CMD_RENAME_ID_IN_SHM: + object_id = params[1].memref.buffer; + break; + default: + return TEE_ERROR_NOT_SUPPORTED; + } + + res = TEE_RenamePersistentObject(o, object_id, params[1].memref.size); + + if (command == TA_STORAGE_CMD_RENAME) + TEE_Free(object_id); + + return res; +} + +TEE_Result ta_storage_cmd_trunc(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectHandle o = VAL2HANDLE(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + return TEE_TruncateObjectData(o, params[0].value.b); +} + +TEE_Result ta_storage_cmd_alloc_enum(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectEnumHandle oe = TEE_HANDLE_NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + res = TEE_AllocatePersistentObjectEnumerator(&oe); + params[0].value.a = (uintptr_t)oe; + return res; +} + +TEE_Result ta_storage_cmd_free_enum(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectEnumHandle oe = VAL2HANDLE(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + TEE_FreePersistentObjectEnumerator(oe); + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_reset_enum(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectEnumHandle oe = VAL2HANDLE(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + TEE_ResetPersistentObjectEnumerator(oe); + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_start_enum(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectEnumHandle oe = VAL2HANDLE(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + return TEE_StartPersistentObjectEnumerator(oe, params[0].value.b); +} + +TEE_Result ta_storage_cmd_next_enum(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectEnumHandle oe = VAL2HANDLE(params[0].value.a); + TEE_Result res = TEE_SUCCESS; + TEE_ObjectInfo *obj = NULL; + void *b2 = NULL; + + if (TEE_PARAM_TYPE_GET(param_types, 0) != TEE_PARAM_TYPE_VALUE_INPUT) + return TEE_ERROR_BAD_PARAMETERS; + if (TEE_PARAM_TYPE_GET(param_types, 2) != TEE_PARAM_TYPE_MEMREF_OUTPUT) + return TEE_ERROR_BAD_PARAMETERS; + if (TEE_PARAM_TYPE_GET(param_types, 3) != TEE_PARAM_TYPE_NONE) + return TEE_ERROR_BAD_PARAMETERS; + + if (params[2].memref.size < TEE_OBJECT_ID_MAX_LEN) + return TEE_ERROR_SHORT_BUFFER; + + if (TEE_PARAM_TYPE_GET(param_types, 1) == TEE_PARAM_TYPE_NONE) + obj = NULL; + else if (TEE_PARAM_TYPE_GET(param_types, 1) == + TEE_PARAM_TYPE_MEMREF_OUTPUT) { + if (params[1].memref.size < sizeof(TEE_ObjectInfo)) { + params[1].memref.size = sizeof(TEE_ObjectInfo); + return TEE_ERROR_SHORT_BUFFER; + } + params[1].memref.size = sizeof(TEE_ObjectInfo); + obj = TEE_Malloc(sizeof(TEE_ObjectInfo), 0); + if (!obj) + return TEE_ERROR_OUT_OF_MEMORY; + } else + return TEE_ERROR_BAD_PARAMETERS; + + b2 = TEE_Malloc(params[2].memref.size, 0); + if (!b2) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + + res = TEE_GetNextPersistentObject(oe, obj, b2, ¶ms[2].memref.size); + if (res) + goto out; + + TEE_MemMove(params[2].memref.buffer, b2, params[2].memref.size); + if (obj) + TEE_MemMove(params[1].memref.buffer, obj, sizeof(*obj)); +out: + TEE_Free(b2); + TEE_Free(obj); + + return res; +} + +static TEE_Result check_obj(TEE_ObjectInfo *o1, TEE_ObjectInfo *o2) +{ + if ((o1->objectType != o2->objectType) || + (o1->objectSize != o2->objectSize) || + (o1->maxObjectSize != o2->maxObjectSize) || + (o1->objectUsage != o2->objectUsage)) + return TEE_ERROR_GENERIC; + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_key_in_persistent(uint32_t param_types, + TEE_Param params[4]) +{ + TEE_Result result = TEE_SUCCESS; + TEE_ObjectHandle transient_key = TEE_HANDLE_NULL; + TEE_ObjectHandle persistent_key = TEE_HANDLE_NULL; + TEE_ObjectHandle key = TEE_HANDLE_NULL; + TEE_OperationHandle encrypt_op = TEE_HANDLE_NULL; + TEE_ObjectInfo keyInfo; + TEE_ObjectInfo keyInfo2; + TEE_ObjectInfo keyInfo3; + uint32_t alg = TEE_ALG_AES_CBC_NOPAD; + void *IV = NULL; + size_t IVlen = 16; + size_t key_size = 256; + uint32_t objectID = 1; + uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_SHARE_READ | + TEE_DATA_FLAG_SHARE_WRITE; + + TEE_MemFill(&keyInfo, 0, sizeof(keyInfo)); + TEE_MemFill(&keyInfo2, 0, sizeof(keyInfo2)); + TEE_MemFill(&keyInfo3, 0, sizeof(keyInfo3)); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + result = TEE_AllocateTransientObject(TEE_TYPE_AES, key_size, + &transient_key); + if (result != TEE_SUCCESS) { + EMSG("Failed to Allocate transient object handle : 0x%x", + result); + goto cleanup1; + } + + result = TEE_GenerateKey(transient_key, key_size, NULL, 0); + if (result != TEE_SUCCESS) { + EMSG("Failed to generate a transient key: 0x%x", result); + goto cleanup2; + } + + TEE_GetObjectInfo1(transient_key, &keyInfo); + result = TEE_CreatePersistentObject(params[0].value.a, + &objectID, sizeof(objectID), + flags, transient_key, NULL, 0, + &persistent_key); + if (result != TEE_SUCCESS) { + EMSG("Failed to create a persistent key: 0x%x", result); + goto cleanup2; + } + + TEE_GetObjectInfo1(persistent_key, &keyInfo2); + result = check_obj(&keyInfo, &keyInfo2); + if (result != TEE_SUCCESS) { + EMSG("keyInfo and keyInfo2 are different"); + goto cleanup2; + } + + TEE_CloseAndDeletePersistentObject1(persistent_key); + + /* Transform the transient object into a persistent object */ + result = TEE_CreatePersistentObject(params[0].value.a, + &objectID, sizeof(objectID), + flags, transient_key, NULL, 0, + NULL); + if (result != TEE_SUCCESS) { + EMSG("Failed to create a persistent key: 0x%x", result); + goto cleanup2; + } + persistent_key = transient_key; + transient_key = TEE_HANDLE_NULL; + + TEE_GetObjectInfo1(persistent_key, &keyInfo2); + result = check_obj(&keyInfo, &keyInfo2); + if (result != TEE_SUCCESS) { + EMSG("keyInfo and keyInfo2 are different"); + goto cleanup2; + } + + TEE_CloseObject(persistent_key); + + result = TEE_OpenPersistentObject(params[0].value.a, + &objectID, sizeof(objectID), + flags, &key); + if (result != TEE_SUCCESS) { + EMSG("Failed to open persistent key: 0x%x", result); + goto cleanup2; + } + + TEE_GetObjectInfo(key, &keyInfo3); + result = check_obj(&keyInfo3, &keyInfo2); + if (result != TEE_SUCCESS) { + EMSG("keyInfo2 and keyInfo3 are different"); + goto cleanup2; + } + + result = TEE_AllocateOperation(&encrypt_op, alg, TEE_MODE_ENCRYPT, + keyInfo3.maxObjectSize); + if (result != TEE_SUCCESS) { + EMSG("Failed to allocate an operation: 0x%x", result); + goto cleanup3; + } + + result = TEE_SetOperationKey(encrypt_op, key); + if (result != TEE_SUCCESS) { + EMSG("Failed to set operation key: 0x%x", result); + goto cleanup4; + } + + IV = TEE_Malloc(IVlen, 0); + if (!IV) { + EMSG("Out of memory for IV."); + result = TEE_ERROR_OUT_OF_MEMORY; + goto cleanup4; + } + + TEE_CipherInit(encrypt_op, IV, IVlen); + TEE_Free(IV); + +cleanup4: + TEE_FreeOperation(encrypt_op); +cleanup3: + TEE_CloseAndDeletePersistentObject1(key); +cleanup2: + TEE_FreeTransientObject(transient_key); +cleanup1: + return result; +} + +TEE_Result ta_storage_cmd_loop(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectHandle object = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + int object_id = 0; + uint32_t flags = TEE_DATA_FLAG_OVERWRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META; + int i = 0; + + (void)params; + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + for (i = 0; i < 20; i++) { + DMSG("\n\nLOOP : %d", i); + object = TEE_HANDLE_NULL; + object_id = i; + res = TEE_CreatePersistentObject(params[0].value.a, + &object_id, sizeof(int), flags, + TEE_HANDLE_NULL, NULL, 0, + &object); + + if (res != TEE_SUCCESS) { + EMSG("FAIL"); + return res; + } + + res = TEE_CloseAndDeletePersistentObject1(object); + if (res != TEE_SUCCESS) { + EMSG("FAIL"); + return res; + } + } + + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_restrict_usage(uint32_t param_types, + TEE_Param params[4]) +{ + TEE_ObjectHandle o = TEE_HANDLE_NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + o = (TEE_ObjectHandle)(uintptr_t)params[0].value.a; + TEE_RestrictObjectUsage1(o, params[0].value.b); + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_alloc_obj(uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle o = TEE_HANDLE_NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + res = TEE_AllocateTransientObject(params[0].value.a, params[0].value.b, + &o); + params[1].value.a = (uint32_t)(uintptr_t)o; + return res; +} + +TEE_Result ta_storage_cmd_free_obj(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectHandle o = TEE_HANDLE_NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + o = (TEE_ObjectHandle)(uintptr_t)params[0].value.a; + TEE_FreeTransientObject(o); + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_reset_obj(uint32_t param_types, TEE_Param params[4]) +{ + TEE_ObjectHandle o = TEE_HANDLE_NULL; + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)); + + o = (TEE_ObjectHandle)(uintptr_t)params[0].value.a; + TEE_ResetTransientObject(o); + return TEE_SUCCESS; +} + +TEE_Result ta_storage_cmd_get_obj_info(uint32_t param_types, + TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct ta_storage_obj_info oi = { }; + TEE_ObjectInfo info = { }; + TEE_ObjectHandle o = VAL2HANDLE(params[0].value.a); + + ASSERT_PARAM_TYPE(TEE_PARAM_TYPES + (TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE)); + + if (params[1].memref.size < sizeof(oi)) + return TEE_ERROR_SHORT_BUFFER; + res = TEE_GetObjectInfo1(o, &info); + if (!res) { + params[1].memref.size = sizeof(oi); + oi.object_type = info.objectType; + oi.object_size = info.objectSize; + oi.max_object_size = info.maxObjectSize; + oi.object_usage = info.objectUsage; + oi.data_size = info.dataSize; + oi.data_position = info.dataPosition; + oi.handle_flags = info.handleFlags; + TEE_MemMove(params[1].memref.buffer, &oi, sizeof(oi)); + } + + return res; +} diff --git a/optee/optee_test/ta/storage/sub.mk b/optee/optee_test/ta/storage/sub.mk new file mode 100644 index 0000000..2aef410 --- /dev/null +++ b/optee/optee_test/ta/storage/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += include +global-incdirs-y += ../include +srcs-y += storage.c +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/storage/ta_entry.c b/optee/optee_test/ta/storage/ta_entry.c new file mode 100644 index 0000000..c507c61 --- /dev/null +++ b/optee/optee_test/ta/storage/ta_entry.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + */ + +#include +#include + +#include "storage.h" + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + (void)pSessionContext; + + switch (nCommandID) { + case TA_STORAGE_CMD_OPEN: + case TA_STORAGE_CMD_OPEN_ID_IN_SHM: + return ta_storage_cmd_open(nCommandID, nParamTypes, pParams); + + case TA_STORAGE_CMD_CLOSE: + return ta_storage_cmd_close(nParamTypes, pParams); + + case TA_STORAGE_CMD_READ: + return ta_storage_cmd_read(nParamTypes, pParams); + + case TA_STORAGE_CMD_WRITE: + return ta_storage_cmd_write(nParamTypes, pParams); + + case TA_STORAGE_CMD_CREATE: + case TA_STORAGE_CMD_CREATE_ID_IN_SHM: + return ta_storage_cmd_create(nCommandID, nParamTypes, pParams); + + case TA_STORAGE_CMD_CREATE_OVERWRITE: + case TA_STORAGE_CMD_CREATEOVER_ID_IN_SHM: + return ta_storage_cmd_create_overwrite(nCommandID, nParamTypes, pParams); + + case TA_STORAGE_CMD_SEEK: + return ta_storage_cmd_seek(nParamTypes, pParams); + + case TA_STORAGE_CMD_UNLINK: + return ta_storage_cmd_unlink(nParamTypes, pParams); + + case TA_STORAGE_CMD_RENAME: + case TA_STORAGE_CMD_RENAME_ID_IN_SHM: + return ta_storage_cmd_rename(nCommandID, nParamTypes, pParams); + + case TA_STORAGE_CMD_TRUNC: + return ta_storage_cmd_trunc(nParamTypes, pParams); + + case TA_STORAGE_CMD_ALLOC_ENUM: + return ta_storage_cmd_alloc_enum(nParamTypes, pParams); + + case TA_STORAGE_CMD_FREE_ENUM: + return ta_storage_cmd_free_enum(nParamTypes, pParams); + + case TA_STORAGE_CMD_RESET_ENUM: + return ta_storage_cmd_reset_enum(nParamTypes, pParams); + + case TA_STORAGE_CMD_START_ENUM: + return ta_storage_cmd_start_enum(nParamTypes, pParams); + + case TA_STORAGE_CMD_NEXT_ENUM: + return ta_storage_cmd_next_enum(nParamTypes, pParams); + + case TA_STORAGE_CMD_KEY_IN_PERSISTENT: + return ta_storage_cmd_key_in_persistent(nParamTypes, pParams); + + case TA_STORAGE_CMD_LOOP: + return ta_storage_cmd_loop(nParamTypes, pParams); + + case TA_STORAGE_CMD_RESTRICT_USAGE: + return ta_storage_cmd_restrict_usage(nParamTypes, pParams); + + case TA_STORAGE_CMD_ALLOC_OBJ: + return ta_storage_cmd_alloc_obj(nParamTypes, pParams); + + case TA_STORAGE_CMD_FREE_OBJ: + return ta_storage_cmd_free_obj(nParamTypes, pParams); + + case TA_STORAGE_CMD_RESET_OBJ: + return ta_storage_cmd_reset_obj(nParamTypes, pParams); + + case TA_STORAGE_CMD_GET_OBJ_INFO: + return ta_storage_cmd_get_obj_info(nParamTypes, pParams); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/ta/storage2/Android.mk b/optee/optee_test/ta/storage2/Android.mk new file mode 100644 index 0000000..b123bf8 --- /dev/null +++ b/optee/optee_test/ta/storage2/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 731e279e-aafb-4575-a771-38caa6f0cca6.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/storage2/Makefile b/optee/optee_test/ta/storage2/Makefile new file mode 100644 index 0000000..65f7795 --- /dev/null +++ b/optee/optee_test/ta/storage2/Makefile @@ -0,0 +1,2 @@ +BINARY = 731e279e-aafb-4575-a771-38caa6f0cca6 +include ../ta_common.mk diff --git a/optee/optee_test/ta/storage2/include/storage.h b/optee/optee_test/ta/storage2/include/storage.h new file mode 100644 index 0000000..da39a88 --- /dev/null +++ b/optee/optee_test/ta/storage2/include/storage.h @@ -0,0 +1 @@ +#include "../storage/include/storage.h" diff --git a/optee/optee_test/ta/storage2/include/user_ta_header_defines.h b/optee/optee_test/ta/storage2/include/user_ta_header_defines.h new file mode 100644 index 0000000..9ccd47e --- /dev/null +++ b/optee/optee_test/ta/storage2/include/user_ta_header_defines.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2016, Linaro Limited + */ +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include "ta_storage.h" + +#define TA_UUID TA_STORAGE2_UUID + +/* + * This is important to have TA_FLAG_SINGLE_INSTANCE && !TA_FLAG_MULTI_SESSION + * as it is used by the ytest + */ +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR | \ + TA_FLAG_SINGLE_INSTANCE) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif diff --git a/optee/optee_test/ta/storage2/storage.c b/optee/optee_test/ta/storage2/storage.c new file mode 100644 index 0000000..a6070b5 --- /dev/null +++ b/optee/optee_test/ta/storage2/storage.c @@ -0,0 +1 @@ +#include "../storage/storage.c" diff --git a/optee/optee_test/ta/storage2/sub.mk b/optee/optee_test/ta/storage2/sub.mk new file mode 100644 index 0000000..2aef410 --- /dev/null +++ b/optee/optee_test/ta/storage2/sub.mk @@ -0,0 +1,4 @@ +global-incdirs-y += include +global-incdirs-y += ../include +srcs-y += storage.c +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/storage2/ta_entry.c b/optee/optee_test/ta/storage2/ta_entry.c new file mode 100644 index 0000000..993605c --- /dev/null +++ b/optee/optee_test/ta/storage2/ta_entry.c @@ -0,0 +1 @@ +#include "../storage/ta_entry.c" diff --git a/optee/optee_test/ta/storage_benchmark/Android.mk b/optee/optee_test/ta/storage_benchmark/Android.mk new file mode 100644 index 0000000..c3eeb76 --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := f157cda0-550c-11e5-a6fa-0002a5d5c51b.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/storage_benchmark/Makefile b/optee/optee_test/ta/storage_benchmark/Makefile new file mode 100644 index 0000000..eb7cf0d --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/Makefile @@ -0,0 +1,2 @@ +BINARY = f157cda0-550c-11e5-a6fa-0002a5d5c51b +include ../ta_common.mk diff --git a/optee/optee_test/ta/storage_benchmark/benchmark.c b/optee/optee_test/ta/storage_benchmark/benchmark.c new file mode 100644 index 0000000..0027309 --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/benchmark.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include +#include +#include +#include + +#define DEFAULT_CHUNK_SIZE (1 << 10) +#define DEFAULT_DATA_SIZE (1024) + +#define SCRAMBLE(x) ((x & 0xff) ^ 0xaa) + +#define ASSERT_PARAM_TYPE(pt_in, pt_expect) \ +do { \ + if ((pt_in) != (pt_expect)) \ + return TEE_ERROR_BAD_PARAMETERS; \ +} while (0) + +static uint8_t filename[] = "BenchmarkTestFile"; + +static void fill_buffer(uint8_t *buf, size_t size) +{ + size_t i = 0; + + if (!buf) + return; + + for (i = 0; i < size; i++) + buf[i] = SCRAMBLE(i); +} + +static TEE_Result verify_buffer(uint8_t *buf, size_t size) +{ + size_t i = 0; + + if (!buf) + return TEE_ERROR_BAD_PARAMETERS; + + for (i = 0; i < size; i++) { + uint8_t expect_data = SCRAMBLE(i); + + if (expect_data != buf[i]) { + return TEE_ERROR_CORRUPT_OBJECT; + } + } + + return TEE_SUCCESS; +} + +static inline uint32_t tee_time_to_ms(TEE_Time t) +{ + return t.seconds * 1000 + t.millis; +} + +static inline uint32_t get_delta_time_in_ms(TEE_Time start, TEE_Time stop) +{ + return tee_time_to_ms(stop) - tee_time_to_ms(start); +} + +static TEE_Result prepare_test_file(size_t data_size, uint8_t *chunk_buf, + size_t chunk_size) +{ + size_t remain_bytes = data_size; + TEE_Result res = TEE_SUCCESS; + TEE_ObjectHandle object = TEE_HANDLE_NULL; + + res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, + filename, sizeof(filename), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META | + TEE_DATA_FLAG_OVERWRITE, + NULL, NULL, 0, &object); + if (res != TEE_SUCCESS) { + EMSG("Failed to create persistent object, res=0x%08x", + res); + goto exit; + } + + while (remain_bytes) { + size_t write_size = 0; + + if (remain_bytes < chunk_size) + write_size = remain_bytes; + else + write_size = chunk_size; + res = TEE_WriteObjectData(object, chunk_buf, write_size); + if (res != TEE_SUCCESS) { + EMSG("Failed to write data, res=0x%08x", res); + goto exit_close_object; + } + remain_bytes -= write_size; + } +exit_close_object: + TEE_CloseObject(object); +exit: + return res; +} + +static TEE_Result test_write(TEE_ObjectHandle object, size_t data_size, + uint8_t *chunk_buf, size_t chunk_size, + uint32_t *spent_time_in_ms) +{ + TEE_Time start_time = { }; + TEE_Time stop_time = { }; + size_t remain_bytes = data_size; + TEE_Result res = TEE_SUCCESS; + + TEE_GetSystemTime(&start_time); + + while (remain_bytes) { + size_t write_size = 0; + + DMSG("Write data, remain bytes: %zu", remain_bytes); + if (chunk_size > remain_bytes) + write_size = remain_bytes; + else + write_size = chunk_size; + res = TEE_WriteObjectData(object, chunk_buf, write_size); + if (res != TEE_SUCCESS) { + EMSG("Failed to write data, res=0x%08x", res); + goto exit; + } + remain_bytes -= write_size; + } + + TEE_GetSystemTime(&stop_time); + + *spent_time_in_ms = get_delta_time_in_ms(start_time, stop_time); + + IMSG("start: %u.%u(s), stop: %u.%u(s), delta: %u(ms)", + start_time.seconds, start_time.millis, + stop_time.seconds, stop_time.millis, + *spent_time_in_ms); + +exit: + return res; +} + +static TEE_Result test_read(TEE_ObjectHandle object, size_t data_size, + uint8_t *chunk_buf, size_t chunk_size, + uint32_t *spent_time_in_ms) +{ + TEE_Time start_time = { }; + TEE_Time stop_time = { }; + size_t remain_bytes = data_size; + TEE_Result res = TEE_SUCCESS; + size_t read_bytes = 0; + + TEE_GetSystemTime(&start_time); + + while (remain_bytes) { + size_t read_size = 0; + + DMSG("Read data, remain bytes: %zu", remain_bytes); + if (remain_bytes < chunk_size) + read_size = remain_bytes; + else + read_size = chunk_size; + res = TEE_ReadObjectData(object, chunk_buf, read_size, + &read_bytes); + if (res != TEE_SUCCESS) { + EMSG("Failed to read data, res=0x%08x", res); + goto exit; + } + + remain_bytes -= read_size; + } + + TEE_GetSystemTime(&stop_time); + + *spent_time_in_ms = get_delta_time_in_ms(start_time, stop_time); + + IMSG("start: %u.%u(s), stop: %u.%u(s), delta: %u(ms)", + start_time.seconds, start_time.millis, + stop_time.seconds, stop_time.millis, + *spent_time_in_ms); + +exit: + return res; +} + +static TEE_Result test_rewrite(TEE_ObjectHandle object, size_t data_size, + uint8_t *chunk_buf, size_t chunk_size, + uint32_t *spent_time_in_ms) +{ + TEE_Time start_time = { }; + TEE_Time stop_time = { }; + size_t remain_bytes = data_size; + TEE_Result res = TEE_SUCCESS; + size_t read_bytes = 0; + + TEE_GetSystemTime(&start_time); + + while (remain_bytes) { + size_t write_size = 0; + int32_t negative_chunk_size = 0; + + if (remain_bytes < chunk_size) + write_size = remain_bytes; + else + write_size = chunk_size; + negative_chunk_size = -(int32_t)write_size; + + /* Read a chunk */ + res = TEE_ReadObjectData(object, chunk_buf, write_size, + &read_bytes); + if (res != TEE_SUCCESS) { + EMSG("Failed to read data, res=0x%08x", res); + goto exit; + } + + if (read_bytes != write_size) { + EMSG("Partial data read, bytes=%zu", read_bytes); + res = TEE_ERROR_CORRUPT_OBJECT; + goto exit; + } + + /* Seek to the position before read */ + res = TEE_SeekObjectData(object, negative_chunk_size, + TEE_DATA_SEEK_CUR); + if (res != TEE_SUCCESS) { + EMSG("Failed to seek to previous offset"); + goto exit; + } + + /* Write a chunk*/ + res = TEE_WriteObjectData(object, chunk_buf, write_size); + if (res != TEE_SUCCESS) { + EMSG("Failed to write data, res=0x%08x", res); + goto exit; + } + + remain_bytes -= write_size; + } + + TEE_GetSystemTime(&stop_time); + + *spent_time_in_ms = get_delta_time_in_ms(start_time, stop_time); + + IMSG("start: %u.%u(s), stop: %u.%u(s), delta: %u(ms)", + start_time.seconds, start_time.millis, + stop_time.seconds, stop_time.millis, + *spent_time_in_ms); + +exit: + return res; +} + +static TEE_Result verify_file_data(TEE_ObjectHandle object, size_t data_size, + uint8_t *chunk_buf, size_t chunk_size) +{ + TEE_Result res = TEE_ERROR_GENERIC; + size_t tmp_data_size = data_size; + + res = TEE_SeekObjectData(object, 0, TEE_DATA_SEEK_SET); + if (res != TEE_SUCCESS) { + EMSG("Failed to seek to offset 0"); + goto exit; + } + + TEE_MemFill(chunk_buf, 0, chunk_size); + + tmp_data_size = data_size; + while (tmp_data_size > 0) { + size_t read_bytes = 0; + + res = TEE_ReadObjectData(object, chunk_buf, chunk_size, + &read_bytes); + if (res != TEE_SUCCESS) { + EMSG("Failed to read data, res=0x%08x", res); + goto exit; + } + + if (read_bytes != chunk_size) { + EMSG("Data size not match"); + res = TEE_ERROR_CORRUPT_OBJECT; + goto exit; + } + + res = verify_buffer(chunk_buf, chunk_size); + if (res != TEE_SUCCESS) { + EMSG("Verify data failed, res=0x%08x", res); + goto exit; + } + + tmp_data_size -= chunk_size; + } + +exit: + return res; +} + +static TEE_Result ta_stroage_benchmark_chunk_access_test(uint32_t nCommandID, + uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + size_t data_size = 0; + size_t chunk_size = 0; + TEE_ObjectHandle object = TEE_HANDLE_NULL; + uint8_t *chunk_buf = NULL; + uint32_t *spent_time_in_ms = ¶ms[2].value.a; + bool do_verify = false; + + ASSERT_PARAM_TYPE(param_types, TEE_PARAM_TYPES( + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE)); + + data_size = params[0].value.a; + chunk_size = params[0].value.b; + do_verify = params[1].value.a; + + if (data_size == 0) + data_size = DEFAULT_DATA_SIZE; + + if (chunk_size == 0) + chunk_size = DEFAULT_CHUNK_SIZE; + + IMSG("command id: %u, test data size: %zd, chunk size: %zd\n", + nCommandID, data_size, chunk_size); + + chunk_buf = TEE_Malloc(chunk_size, TEE_MALLOC_FILL_ZERO); + if (!chunk_buf) { + EMSG("Failed to allocate memory"); + res = TEE_ERROR_OUT_OF_MEMORY; + goto exit; + } + + fill_buffer(chunk_buf, chunk_size); + res = prepare_test_file(data_size, chunk_buf, chunk_size); + if (res != TEE_SUCCESS) { + EMSG("Failed to create test file, res=0x%08x", + res); + goto exit_free_chunk_buf; + } + + res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, + filename, sizeof(filename), + TEE_DATA_FLAG_ACCESS_READ | + TEE_DATA_FLAG_ACCESS_WRITE | + TEE_DATA_FLAG_ACCESS_WRITE_META, + &object); + if (res != TEE_SUCCESS) { + EMSG("Failed to open persistent object, res=0x%08x", + res); + goto exit_remove_object; + } + + switch (nCommandID) { + case TA_STORAGE_BENCHMARK_CMD_TEST_READ: + res = test_read(object, data_size, chunk_buf, + chunk_size, spent_time_in_ms); + break; + + case TA_STORAGE_BENCHMARK_CMD_TEST_WRITE: + res = test_write(object, data_size, chunk_buf, + chunk_size, spent_time_in_ms); + break; + + case TA_STORAGE_BENCHMARK_CMD_TEST_REWRITE: + res = test_rewrite(object, data_size, chunk_buf, + chunk_size, spent_time_in_ms); + break; + + default: + res = TEE_ERROR_BAD_PARAMETERS; + } + + if (res != TEE_SUCCESS) + goto exit_remove_object; + + if (do_verify) + res = verify_file_data(object, data_size, + chunk_buf, chunk_size); + + +exit_remove_object: + TEE_CloseAndDeletePersistentObject1(object); +exit_free_chunk_buf: + TEE_Free(chunk_buf); +exit: + + return res; +} + +TEE_Result ta_storage_benchmark_cmd_handler(uint32_t nCommandID, + uint32_t param_types, TEE_Param params[4]) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + switch (nCommandID) { + case TA_STORAGE_BENCHMARK_CMD_TEST_READ: + case TA_STORAGE_BENCHMARK_CMD_TEST_WRITE: + case TA_STORAGE_BENCHMARK_CMD_TEST_REWRITE: + res = ta_stroage_benchmark_chunk_access_test(nCommandID, + param_types, params); + break; + + default: + res = TEE_ERROR_BAD_PARAMETERS; + } + + return res; +} + diff --git a/optee/optee_test/ta/storage_benchmark/include/storage_benchmark.h b/optee/optee_test/ta/storage_benchmark/include/storage_benchmark.h new file mode 100644 index 0000000..f1d9d87 --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/include/storage_benchmark.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef STORAGE_BENCHMARK_H +#define STORAGE_BENCHMARK_H + +#include + +TEE_Result ta_storage_benchmark_cmd_handler(uint32_t nCommandID, + uint32_t param_types, TEE_Param params[4]); + +#endif /*STORAGE_BENCHMARK_H */ diff --git a/optee/optee_test/ta/storage_benchmark/include/ta_storage_benchmark.h b/optee/optee_test/ta/storage_benchmark/include/ta_storage_benchmark.h new file mode 100644 index 0000000..2aa5890 --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/include/ta_storage_benchmark.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef TA_STORAGE_BENCHMARK_H +#define TA_STORAGE_BENCHMARK_H + +#define TA_STORAGE_BENCHMARK_UUID { 0xf157cda0, 0x550c, 0x11e5,\ + { 0xa6, 0xfa, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } } + +enum storage_benchmark_cmd { + TA_STORAGE_BENCHMARK_CMD_TEST_READ, + TA_STORAGE_BENCHMARK_CMD_TEST_WRITE, + TA_STORAGE_BENCHMARK_CMD_TEST_REWRITE, +}; + +#endif /* TA_STORAGE_BENCHMARK_H */ diff --git a/optee/optee_test/ta/storage_benchmark/include/user_ta_header_defines.h b/optee/optee_test/ta/storage_benchmark/include/user_ta_header_defines.h new file mode 100644 index 0000000..f78e26d --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include "ta_storage_benchmark.h" + +#define TA_UUID TA_STORAGE_BENCHMARK_UUID + +#define TA_FLAGS (TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif diff --git a/optee/optee_test/ta/storage_benchmark/sub.mk b/optee/optee_test/ta/storage_benchmark/sub.mk new file mode 100644 index 0000000..504159e --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +srcs-y += benchmark.c +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/storage_benchmark/ta_entry.c b/optee/optee_test/ta/storage_benchmark/ta_entry.c new file mode 100644 index 0000000..a88d8be --- /dev/null +++ b/optee/optee_test/ta/storage_benchmark/ta_entry.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + */ + +#include + +#include +#include + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes, + TEE_Param pParams[4], + void **ppSessionContext) +{ + (void)nParamTypes; + (void)pParams; + (void)ppSessionContext; + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext) +{ + (void)pSessionContext; +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext, + uint32_t nCommandID, uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + (void)pSessionContext; + + return ta_storage_benchmark_cmd_handler(nCommandID, nParamTypes, pParams); +} diff --git a/optee/optee_test/ta/subkey1/Makefile b/optee/optee_test/ta/subkey1/Makefile new file mode 100644 index 0000000..bc9378f --- /dev/null +++ b/optee/optee_test/ta/subkey1/Makefile @@ -0,0 +1,8 @@ +BINARY = 5c206987-16a3-59cc-ab0f-64b9cfc9e758 + +TA_SIGN_KEY = ../mid_level_subkey.pem +TA_SUBKEY_BIN = ../mid_level_subkey.bin +TA_SUBKEY_ARGS = --subkey $(TA_SUBKEY_BIN) --name subkey1_ta +TA_SUBKEY_DEPS = $(TA_SUBKEY_BIN) + +include ../ta_common.mk diff --git a/optee/optee_test/ta/subkey1/include/ta_subkey1.h b/optee/optee_test/ta/subkey1/include/ta_subkey1.h new file mode 100644 index 0000000..b8a13d9 --- /dev/null +++ b/optee/optee_test/ta/subkey1/include/ta_subkey1.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef TA_SUBKEY1_H +#define TA_SUBKEY1_H + +#define TA_SUBKEY1_UUID { 0x5c206987, 0x16a3, 0x59cc, \ + { 0xab, 0x0f, 0x64, 0xb9, 0xcf, 0xc9, 0xe7, 0x58 } } + +#endif /*TA_SUBKEY1_H */ diff --git a/optee/optee_test/ta/subkey1/include/user_ta_header_defines.h b/optee/optee_test/ta/subkey1/include/user_ta_header_defines.h new file mode 100644 index 0000000..5c6e779 --- /dev/null +++ b/optee/optee_test/ta/subkey1/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include + +#define TA_UUID TA_SUBKEY1_UUID + +#define TA_FLAGS (TA_FLAG_MULTI_SESSION) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (2 * 1024) + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_test/ta/subkey1/sub.mk b/optee/optee_test/ta/subkey1/sub.mk new file mode 100644 index 0000000..d5e3f32 --- /dev/null +++ b/optee/optee_test/ta/subkey1/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/subkey1/ta_entry.c b/optee/optee_test/ta/subkey1/ta_entry.c new file mode 100644 index 0000000..9699fc7 --- /dev/null +++ b/optee/optee_test/ta/subkey1/ta_entry.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types __unused, + TEE_Param params[4] __unused, + void **session_ctx __unused) +{ + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *session_ctx __unused) +{ +} + +TEE_Result TA_InvokeCommandEntryPoint(void *session_ctx __unused, + uint32_t cmd_id __unused, + uint32_t param_types __unused, + TEE_Param params[4] __unused) +{ + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/subkey2/Makefile b/optee/optee_test/ta/subkey2/Makefile new file mode 100644 index 0000000..aaa3453 --- /dev/null +++ b/optee/optee_test/ta/subkey2/Makefile @@ -0,0 +1,8 @@ +BINARY = a720ccbb-51da-417d-b82e-e5445d474a7a + +TA_SIGN_KEY = ../identity_subkey2.pem +TA_SUBKEY_BIN = ../identity_subkey2.bin +TA_SUBKEY_ARGS = --subkey $(TA_SUBKEY_BIN) +TA_SUBKEY_DEPS = $(TA_SUBKEY_BIN) + +include ../ta_common.mk diff --git a/optee/optee_test/ta/subkey2/include/ta_subkey2.h b/optee/optee_test/ta/subkey2/include/ta_subkey2.h new file mode 100644 index 0000000..31e906d --- /dev/null +++ b/optee/optee_test/ta/subkey2/include/ta_subkey2.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#ifndef TA_SUBKEY2_H +#define TA_SUBKEY2_H + +#define TA_SUBKEY2_UUID { 0xa720ccbb, 0x51da, 0x417d, \ + { 0xb8, 0x2e, 0xe5, 0x44, 0x5d, 0x47, 0x4a, 0x7a } } + +#endif /*TA_SUBKEY2_H */ diff --git a/optee/optee_test/ta/subkey2/include/user_ta_header_defines.h b/optee/optee_test/ta/subkey2/include/user_ta_header_defines.h new file mode 100644 index 0000000..5409748 --- /dev/null +++ b/optee/optee_test/ta/subkey2/include/user_ta_header_defines.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022, Linaro Limited + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include + +#define TA_UUID TA_SUBKEY2_UUID + +#define TA_FLAGS (TA_FLAG_MULTI_SESSION) +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (2 * 1024) + +#endif /*USER_TA_HEADER_DEFINES_H*/ diff --git a/optee/optee_test/ta/subkey2/sub.mk b/optee/optee_test/ta/subkey2/sub.mk new file mode 100644 index 0000000..d5e3f32 --- /dev/null +++ b/optee/optee_test/ta/subkey2/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/subkey2/ta_entry.c b/optee/optee_test/ta/subkey2/ta_entry.c new file mode 100644 index 0000000..a88d70e --- /dev/null +++ b/optee/optee_test/ta/subkey2/ta_entry.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022, Linaro Limited + */ + +#include +#include + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types __unused, + TEE_Param params[4] __unused, + void **session_ctx __unused) +{ + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *session_ctx __unused) +{ +} + +TEE_Result TA_InvokeCommandEntryPoint(void *session_ctx __unused, + uint32_t cmd_id __unused, + uint32_t param_types __unused, + TEE_Param params[4] __unused) +{ + return TEE_SUCCESS; +} diff --git a/optee/optee_test/ta/subkey_notes.txt b/optee/optee_test/ta/subkey_notes.txt new file mode 100644 index 0000000..4e61d9f --- /dev/null +++ b/optee/optee_test/ta/subkey_notes.txt @@ -0,0 +1,73 @@ +Subkey +====== + +A TA or a subkey can be signed with a subkey instead of the root key. Here +we're trying to describe the relationship between the different subkeys and +keys used for the subkey test TAs. + +We start with a two level subkey hierachy to be able to test more when the +subkey chain consist of more than a single subkey signed with the root key. + +The relationship of the different subkeys and TAs are as follows: +root_key +|-- identity_subkey2 +| `-- subkey2_ta +`-- top_level_subkey + `-- mid_level_subkey + `-- subkey1_ta + +The keys themselves where generated using: + +openssl genrsa -out top_level_subkey.pem +openssl genrsa -out mid_level_subkey.pem +openssl genrsa -out identity_subkey2.pem + +The top level subkey is signed with the root key using (where the UUID is +generated): + +../../optee_os/scripts/sign_encrypt.py sign-subkey \ + --uuid f04fa996-148a-453c-b037-1dcfbad120a6 \ + --key ../../optee_os/keys/default_ta.pem --in top_level_subkey.pem \ + --out top_level_subkey.bin --max-depth 4 --name-size 64 \ + --subkey-version 1 + +The mid level subkey has to have a UUID in the namespace of the top level +level subkey. The UUID is determined as +UUIDv5_SHA512(f04fa996-148a-453c-b037-1dcfbad120a6, "mid_level_subkey") = +1a5948c5-1aa0-518c-86f4-be6f6a057b16 +where UUIDv5_SHA512() denotes the UUIDv5 scheme with SHA512 used instead of +SHA1 and truncated to 20 bytes + +The sign script can do this with: + +../../optee_os/scripts/sign_encrypt.py subkey-uuid --in top_level_subkey.bin \ + --name mid_level_subkey +Subkey UUID: f04fa996-148a-453c-b037-1dcfbad120a6 +Next subkey UUID: 1a5948c5-1aa0-518c-86f4-be6f6a057b16 + +The mid level subkey is signed using: + +../../optee_os/scripts/sign_encrypt.py sign-subkey \ + --uuid 1a5948c5-1aa0-518c-86f4-be6f6a057b16 \ + --key top_level_subkey.pem --subkey top_level_subkey.bin \ + --name-size 64 --subkey-version 1 \ + --name mid_level_subkey \ + --in mid_level_subkey.pem --out mid_level_subkey.bin + +The UUID of subkey1 TA is calculated using: + +../../optee_os/scripts/sign_encrypt.py subkey-uuid --in mid_level_subkey.bin \ + --name subkey1_ta +Subkey UUID: f04fa996-148a-453c-b037-1dcfbad120a6 +Subkey UUID: 1a5948c5-1aa0-518c-86f4-be6f6a057b16 +Next subkey UUID: 5c206987-16a3-59cc-ab0f-64b9cfc9e758 + +Subkey1 TA is signed as part of the build process. + +The identity_subkey2 subkey is signed using (where the UUID is generated): + +../../optee_os/scripts/sign_encrypt.py sign-subkey \ + --uuid a720ccbb-51da-417d-b82e-e5445d474a7a \ + --key ../../optee_os/keys/default_ta.pem --in identity_subkey2.pem \ + --out identity_subkey2.bin --max-depth 0 --name-size 0 \ + --subkey-version 1 diff --git a/optee/optee_test/ta/supp_plugin/Android.mk b/optee/optee_test/ta/supp_plugin/Android.mk new file mode 100644 index 0000000..bb5792b --- /dev/null +++ b/optee/optee_test/ta/supp_plugin/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := 380231ac-fb99-47ad-a689-9e017eb6e78a.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/supp_plugin/Makefile b/optee/optee_test/ta/supp_plugin/Makefile new file mode 100644 index 0000000..5c1965b --- /dev/null +++ b/optee/optee_test/ta/supp_plugin/Makefile @@ -0,0 +1,2 @@ +BINARY = 380231ac-fb99-47ad-a689-9e017eb6e78a +include ../ta_common.mk diff --git a/optee/optee_test/ta/supp_plugin/include/ta_supp_plugin.h b/optee/optee_test/ta/supp_plugin/include/ta_supp_plugin.h new file mode 100644 index 0000000..fd05255 --- /dev/null +++ b/optee/optee_test/ta/supp_plugin/include/ta_supp_plugin.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021 Open Mobile Platform LLC + */ + +#ifndef TA_SUPP_PLUGIN_H +#define TA_SUPP_PLUGIN_H + +#define TA_SUPP_PLUGIN_UUID { 0x380231ac, 0xfb99, 0x47ad, \ + { 0xa6, 0x89, 0x9e, 0x01, 0x7e, 0xb6, 0xe7, 0x8a } } + +#define TA_SUPP_PLUGIN_CMD_PASS_VALUES 0 +#define TA_SUPP_PLUGIN_CMD_WRITE_ARR 1 +#define TA_SUPP_PLUGIN_CMD_GET_ARR 2 +#define TA_SUPP_PLUGIN_CMD_BAD_UUID 3 +#define TA_SUPP_PLUGIN_CMD_BAD_IN_DATA 4 +#define TA_SUPP_PLUGIN_CMD_BAD_IN_LEN 5 +#define TA_SUPP_PLUGIN_CMD_UNKNOWN_UUID 6 + +#endif /* TA_SUPP_PLUGIN_H */ diff --git a/optee/optee_test/ta/supp_plugin/include/user_ta_header_defines.h b/optee/optee_test/ta/supp_plugin/include/user_ta_header_defines.h new file mode 100644 index 0000000..0003c92 --- /dev/null +++ b/optee/optee_test/ta/supp_plugin/include/user_ta_header_defines.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2021 Open Mobile Platform LLC + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include +#include + +#define TA_UUID TA_SUPP_PLUGIN_UUID +#define TA_FLAGS 0 +#define TA_STACK_SIZE (8 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/supp_plugin/sub.mk b/optee/optee_test/ta/supp_plugin/sub.mk new file mode 100644 index 0000000..dd01461 --- /dev/null +++ b/optee/optee_test/ta/supp_plugin/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +global-incdirs-y += ../../host/supp_plugin/include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/supp_plugin/ta_entry.c b/optee/optee_test/ta/supp_plugin/ta_entry.c new file mode 100644 index 0000000..b6a2d99 --- /dev/null +++ b/optee/optee_test/ta/supp_plugin/ta_entry.c @@ -0,0 +1,169 @@ +//SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2021 Open Mobile Platform LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const TEE_UUID uuid = TEST_PLUGIN_UUID; + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes __unused, + TEE_Param pParams[4] __unused, + void **ppSessionContext __unused) +{ + /* check the plugin was loaded */ + return tee_invoke_supp_plugin(&uuid, TEST_PLUGIN_CMD_PING, 0, NULL, 0, + NULL); +} + +void TA_CloseSessionEntryPoint(void *pSessionContext __unused) +{ +} + +static TEE_Result pass_values(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result res = TEE_ERROR_GENERIC; + size_t outlen = 0; + struct add_op { + uint32_t a; + uint32_t b; + } values = { 0 }; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + values.a = params[0].value.a; + values.b = params[0].value.b; + + res = tee_invoke_supp_plugin(&uuid, TEST_PLUGIN_CMD_PASS_VALUES, + params[1].value.a, (void *)&values, + sizeof(struct add_op), &outlen); + params[0].value.a = values.a; + + return res; +} + +static TEE_Result write_array(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result res = TEE_ERROR_GENERIC; + size_t outlen = 0; + uint8_t *d = params[0].memref.buffer; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_invoke_supp_plugin(&uuid, TEST_PLUGIN_CMD_WRITE_ARR, 0, + params[0].memref.buffer, + params[0].memref.size, &outlen); + params[1].value.a = d[0]; + + return res; +} + +static TEE_Result get_array(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Result res = TEE_ERROR_GENERIC; + size_t outlen = 0; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + res = tee_invoke_supp_plugin(&uuid, TEST_PLUGIN_CMD_GET_ARR, 0, + params[0].memref.buffer, + params[0].memref.size, + &outlen); + params[1].value.a = (uint32_t)outlen; + + return res; +} + +static TEE_Result bad_input_uuid(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + char data[32] = { }; + size_t inlen = sizeof(data); + + return tee_invoke_supp_plugin(NULL, 0, 0, data, inlen, NULL); +} + +static TEE_Result bad_input_data(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + return tee_invoke_supp_plugin(&uuid, 0, 0, NULL, 10, NULL); +} + +static TEE_Result bad_input_inlen(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused) +{ + char data[32] = { }; + + return tee_invoke_supp_plugin(&uuid, 0, 0, data, 0, NULL); +} + +static TEE_Result call_unknown_plugin(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] + __unused) +{ + const TEE_UUID nulluuid = { }; + char data[32] = { }; + size_t inlen = sizeof(data); + + return tee_invoke_supp_plugin(&nulluuid, 0, 0, data, inlen, NULL); +} + +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext __unused, + uint32_t nCommandID, + uint32_t nParamTypes, + TEE_Param pParams[4]) +{ + switch (nCommandID) { + case TA_SUPP_PLUGIN_CMD_PASS_VALUES: + return pass_values(nParamTypes, pParams); + case TA_SUPP_PLUGIN_CMD_WRITE_ARR: + return write_array(nParamTypes, pParams); + case TA_SUPP_PLUGIN_CMD_GET_ARR: + return get_array(nParamTypes, pParams); + case TA_SUPP_PLUGIN_CMD_BAD_UUID: + return bad_input_uuid(nParamTypes, pParams); + case TA_SUPP_PLUGIN_CMD_BAD_IN_DATA: + return bad_input_data(nParamTypes, pParams); + case TA_SUPP_PLUGIN_CMD_BAD_IN_LEN: + return bad_input_inlen(nParamTypes, pParams); + case TA_SUPP_PLUGIN_CMD_UNKNOWN_UUID: + return call_unknown_plugin(nParamTypes, pParams); + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} diff --git a/optee/optee_test/ta/ta_common.mk b/optee/optee_test/ta/ta_common.mk new file mode 100644 index 0000000..b8ce142 --- /dev/null +++ b/optee/optee_test/ta/ta_common.mk @@ -0,0 +1,3 @@ +# Note that it is important that that $(BINARY) is set before we include +# ta_dev_kit.mk. In the optee_test this is done in the individual TA Makefiles. +include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk diff --git a/optee/optee_test/ta/top_level_subkey.bin b/optee/optee_test/ta/top_level_subkey.bin new file mode 100644 index 0000000000000000000000000000000000000000..5e6d13d5b87f7a64877459176f012efe26d5df1e GIT binary patch literal 628 zcmV-)0*n1fQ&dj_0000$0RR9nNkMQR0005?bMqH15^9S0;_UgCM=|# zh04#2ac4mSiMM`uHWaV90!`tT_!G8&opkEqHRd0*I>Jca~QNNPD}(TD5&MN$w<$8>WO(d9M7k^{AX1g6nD zg0A5VfKqA;p$D?^_;{`A#|7a`H?X64{U7)MfWTYny*0PN!y-PjmQFjm zYQj0Y`YYkWXHqY4ETvR>Jq(7oyb7>7VWIA&Yo*ip`P^g#YHb?(%>2hcJyj5;={;}$ zp(AndPpOs^ibXuIHyzKq(IBQk00001000040000mNkMP|0000m0RYfE000010RR9n z0szoG0RR9400000>t77O$z@S@VigySio5T|OZPdxDr`1i7?!C%#gZ2WEx4q3cAa*B zb!X`#Y4{)In2rW>J)0%)_GRJTeeU-@9`wGUbonltx^XY+)CUh+wN$CxIHW6TV)gQJ zCl&X`h?*m0&-Z;C@#0B3Y;i4TvL)uLgX z#r=mDO1Z-|xs|y@f<2RQ6wmZP5?|7^PcaM)(%VJ)RCo=$a=EDxu_8hWM;rxO OOXzq1K7ZIZ0RRC@Q5@L- literal 0 HcmV?d00001 diff --git a/optee/optee_test/ta/top_level_subkey.pem b/optee/optee_test/ta/top_level_subkey.pem new file mode 100644 index 0000000..e24bb8f --- /dev/null +++ b/optee/optee_test/ta/top_level_subkey.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDrXwzAyWVRd2IV +F42Ku+/GS/c5vipsNl8Ylqk+xZIXBi24pHh2nXaAdWfpI2n4H+WYjgZzPZsl8PZl +4d597vc+HvS+oXT5Lpq6cS/q1AcPW7VUqdw4pCtqYvXycicV98aIfBM1VAnTV9oU +0s+0YMOAnPcjdeXacFhOuLCC5BAzZLZb8YEO0sg5wFz0ltpscNHN/jh2MXMN0wJy +WNAoLrenCpwoNVxTkkvkRjlH7TcJTiyBODCIanWoov64MwV/rAVWwyzaxf2HF0q5 +wzW5lblEgj2TcRTP9EASX9K0TzEMDdLbRfpUeA27crm8//liM6uxIkIKRxwFWkvo +d/8+f9g3AgMBAAECggEAR1Wu4U0Ikoi6psbVJJtx/6jtXEhIxjQyXRroX3h0ntrG +B6R9SAHQNP2gSRXtG4DbToGY7dtZhsXBf75VdthygZbTOWVotM7NoT0Ft0ecfiie +y/KRJm+HIv6sKNc1BmDqgFoOXkbClZWWKGJ+Bd6f0f6AnnQwfiQ3d2BdSsZBLLm/ +/VpGJ+/z85+9ZRGgkgi73omMtMC7NJqgkCzQXo2rnnpczH5zr7CqWPN7YQsgD/Gg +uOHMc+9Y3HOpn4CtxludDnG+DPfGzWZtjmQL/sGDb2GC1qJ6qwRjTCPAYWGfhkim +wJSZRnWSeTKuOcNF9cqVawEfpgd3mn29Arfb67jlPQKBgQDvKTGBZlXeY/EbH3dl +e1CDfPKv6y9cdvQ4MofmYwgkifpQ5vgzSiD0S8iRlclpRCdy1bQv87RhctyGQgIx +vYx6vpElxH1EZur2AT3wAcsJqS0+iKyBgZb2qeAtuVdyHFUbvzkWPuOjiku296SB +EgzNn8UG7WRhi0oGYpNS+bBOTQKBgQD78YywYlCDerQ5GlqP6mnro00bg6zjfPW6 +x3AjcsdxDbASC02ke253r9JIqvX6GyXnmtgND32ffk/jUARo0i8RGxGmzMuivglM +3hVHOntszM4+NrUeOd1F5Uxi3dOZ2B0hRSJ82IWc9O2p+BmKt5oH6n9/76A1Zwd0 +q4yLlrNqkwKBgDHHiDdf3pWohcHYfdiQn0SPGFCHilcbp1+fHOxWRpacZY67VIQQ +dOWEdJ3g6IhRmEhttNCaUDxMVRxY1u4Vfwz5Z2rOCCjZpyRHQ+YV6XX8UZ+HgSh/ +mbWDzFaYElx9CzX4SmCX/HfIzFOsHgCDikiubaswdEldXa4QjIujzw+tAoGARon5 +twS/wCAhx38ebf7Wyxe8pgB27nZ1ImdmeTZQqtGHQ3YQtgWtByud96SOHAlv0mmj +Jfz5Uid+XIlxwptefC6VAZuDRDxqxC/Fy1yPZAXvlLGigiT3U/OAMIolDYTZmxAN +OOEyf6B/zj/dft4q7R51ti80Lt960eqZ/hcigqsCgYAIPhl6ctItLaDJFgmYvBUf +25woVlzIMgQlLo+YNhX/Kn+BFjOeKP2AlEa+4VJBoHLoBGeIjL1pWOGFYQf3hDWW +BOnaeaVqmLGdvjWgWHMRiPL/HxWH1wVH/1SUfrzxwoYJMU6WUaeRH4qQR0vCqvTA +vOIVA8zQNiPC6XXxTeICPw== +-----END PRIVATE KEY----- diff --git a/optee/optee_test/ta/tpm_log_test/Android.mk b/optee/optee_test/ta/tpm_log_test/Android.mk new file mode 100644 index 0000000..7a786bd --- /dev/null +++ b/optee/optee_test/ta/tpm_log_test/Android.mk @@ -0,0 +1,4 @@ +LOCAL_PATH := $(call my-dir) + +local_module := ee90d523-90ad-46a0-859d-8eea0b150086.ta +include $(BUILD_OPTEE_MK) diff --git a/optee/optee_test/ta/tpm_log_test/Makefile b/optee/optee_test/ta/tpm_log_test/Makefile new file mode 100644 index 0000000..dd4028d --- /dev/null +++ b/optee/optee_test/ta/tpm_log_test/Makefile @@ -0,0 +1,2 @@ +BINARY = ee90d523-90ad-46a0-859d-8eea0b150086 +include ../ta_common.mk diff --git a/optee/optee_test/ta/tpm_log_test/include/ta_tpm_log.h b/optee/optee_test/ta/tpm_log_test/include/ta_tpm_log.h new file mode 100644 index 0000000..b95f213 --- /dev/null +++ b/optee/optee_test/ta/tpm_log_test/include/ta_tpm_log.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + */ + +#ifndef TA_TPM_LOG_H +#define TA_TPM_LOG_H + +#include +#include + +#endif /* TA_TPM_LOG_H */ diff --git a/optee/optee_test/ta/tpm_log_test/include/ta_tpm_log_test.h b/optee/optee_test/ta/tpm_log_test/include/ta_tpm_log_test.h new file mode 100644 index 0000000..2d7d67c --- /dev/null +++ b/optee/optee_test/ta/tpm_log_test/include/ta_tpm_log_test.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + */ + +#ifndef TA_TPM_LOG_TEST_H +#define TA_TPM_LOG_TEST_H + +/* + * This UUID is generated with the ITU-T UUID generator at + * http://www.uuidgenerator.net + */ +#define TA_TPM_LOG_TEST_UUID { 0xee90d523, 0x90ad, 0x46a0, \ + { 0x85, 0x9d, 0x8e, 0xea, 0x0b, 0x15, 0x00, 0x86 } } + +#define TA_TPM_TEST_GET_LOG 1 +#define TA_TPM_TEST_SHORT_BUF 2 + +#endif /* TA_TPM_LOG_TEST_H */ diff --git a/optee/optee_test/ta/tpm_log_test/include/user_ta_header_defines.h b/optee/optee_test/ta/tpm_log_test/include/user_ta_header_defines.h new file mode 100644 index 0000000..cfdd69b --- /dev/null +++ b/optee/optee_test/ta/tpm_log_test/include/user_ta_header_defines.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_TPM_LOG_TEST_UUID + +#define TA_FLAGS 0 +#define TA_STACK_SIZE (4 * 1024) +#define TA_DATA_SIZE (32 * 1024) + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/optee/optee_test/ta/tpm_log_test/sub.mk b/optee/optee_test/ta/tpm_log_test/sub.mk new file mode 100644 index 0000000..d5e3f32 --- /dev/null +++ b/optee/optee_test/ta/tpm_log_test/sub.mk @@ -0,0 +1,2 @@ +global-incdirs-y += include +srcs-y += ta_entry.c diff --git a/optee/optee_test/ta/tpm_log_test/ta_entry.c b/optee/optee_test/ta/tpm_log_test/ta_entry.c new file mode 100644 index 0000000..83106a1 --- /dev/null +++ b/optee/optee_test/ta/tpm_log_test/ta_entry.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#define LOG_SIZE 1024 + +static TEE_Result invoke_system_pta(uint32_t cmd_id, uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const TEE_UUID system_uuid = PTA_SYSTEM_UUID; + TEE_TASessionHandle session = TEE_HANDLE_NULL; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t ret_origin = 0; + + res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &session, &ret_origin); + if (res != TEE_SUCCESS) + return res; + + res = TEE_InvokeTACommand(session, TEE_TIMEOUT_INFINITE, + cmd_id, param_types, params, &ret_origin); + + TEE_CloseTASession(session); + + return res; +} + +/* + * Test case for the use of right parameters. + */ +static TEE_Result test_with_right_parameters(void) +{ + unsigned char buf[LOG_SIZE] = { 0 }; + const uint32_t param_types = TEE_PARAM_TYPES( + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = { 0 }; + uint32_t field = 0; + unsigned char *digestptr = NULL; + unsigned int i = 0; + + params[0].memref.buffer = (void *)buf; + params[0].memref.size = LOG_SIZE; + + if (invoke_system_pta(PTA_SYSTEM_GET_TPM_EVENT_LOG, + param_types, params) == TEE_SUCCESS) { + DMSG("Received %i bytes of event log", params[0].memref.size); + DMSG("Parsing the event log header:"); + + memcpy(&field, &buf[0], sizeof(uint32_t)); + DMSG("\tPCRIndex = 0x%" PRIx32, field); + + /* + * PCR Index must be 0 on the header. + * Ref. Section 5.3 of TCG EFI Protocol Specification. + * Family 2.0 Level 00 Revision 00.13. March 30, 2016 + */ + if (field != 0) { + EMSG("PCRIndex must be 0"); + return TEE_ERROR_GENERIC; + } + + memcpy(&field, &buf[4], sizeof(uint32_t)); + DMSG("\tEventType = 0x%" PRIx32, field); + + /* + * Event type must be EV_NO_ACTION on the header. + * Ref. Section 5.3 of TCG EFI Protocol Specification. + * Family 2.0 Level 00 Revision 00.13. March 30, 2016 + */ + if (field != 3) { + EMSG("EventType must be 3 (EV_NO_ACTION)"); + return TEE_ERROR_GENERIC; + } + + /* + * Header digest must be formed of 20 bytes set to 0. + * Ref. Section 5.3 of TCG EFI Protocol Specification. + * Family 2.0 Level 00 Revision 00.12. March 30, 2016 + */ + digestptr = &buf[8]; + for (i = 0; i < 20; i++) { + if (*(digestptr + i) != 0) { + EMSG("Digest byte %i must be 0", i); + return TEE_ERROR_GENERIC; + } + } + + DMSG("--> Digest value passed"); + return TEE_SUCCESS; + } + return TEE_ERROR_ACCESS_DENIED; +} + +/* + * Test case for short buffer. + */ +static TEE_Result test_short_buffer(void) +{ + unsigned char buf[LOG_SIZE] = { 0 }; + const uint32_t param_types = TEE_PARAM_TYPES( + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = { 0 }; + unsigned int i = 0; + + params[0].memref.buffer = (void *)buf; + params[0].memref.size = 1; + + if (invoke_system_pta(PTA_SYSTEM_GET_TPM_EVENT_LOG, param_types, + params) != TEE_ERROR_SHORT_BUFFER) { + return TEE_ERROR_GENERIC; + } + + for (i = 0; i < LOG_SIZE; i++) { + if (buf[i] != 0) { + EMSG("Buf is expected to be all zeroed"); + return TEE_ERROR_GENERIC; + } + } + + return TEE_SUCCESS; +} + +/* + * Trusted Application Entry Points + */ + +/* Called each time a new instance is created */ +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +/* Called each time an instance is destroyed */ +void TA_DestroyEntryPoint(void) +{ +} + +/* Called each time a session is opened */ +TEE_Result TA_OpenSessionEntryPoint(uint32_t nParamTypes __unused, + TEE_Param pParams[4] __unused, + void **ppSessionContext __unused) +{ + return TEE_SUCCESS; +} + +/* Called each time a session is closed */ +void TA_CloseSessionEntryPoint(void *pSessionContext __unused) +{ +} + +/* Called when a command is invoked */ +TEE_Result TA_InvokeCommandEntryPoint(void *pSessionContext __unused, + uint32_t nCommandID, + uint32_t nParamTypes __unused, + TEE_Param pParams[4] __unused) +{ + switch (nCommandID) { + case TA_TPM_TEST_GET_LOG: + return test_with_right_parameters(); + + case TA_TPM_TEST_SHORT_BUF: + return test_short_buffer(); + + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/optee/optee_test/typedefs.checkpatch b/optee/optee_test/typedefs.checkpatch new file mode 100644 index 0000000..ea65adc --- /dev/null +++ b/optee/optee_test/typedefs.checkpatch @@ -0,0 +1,2 @@ +TEE_Result +TEE_UUID diff --git a/optee/samples/LICENSE b/optee/samples/LICENSE new file mode 100644 index 0000000..8fb3635 --- /dev/null +++ b/optee/samples/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (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/optee/samples/Makefile b/optee/samples/Makefile new file mode 100644 index 0000000..da3f40b --- /dev/null +++ b/optee/samples/Makefile @@ -0,0 +1,35 @@ +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# Input variables +# CROSS_COMPILE: The cross compiler. +# TA_DEV_KIT_DIR: The base directory of the TA-devkit. +# OPTEE_CLIENT_EXPORT: The base directory points to optee client's +# header files and libraries +# O: The base directory for build objects filetree. + +SAMPLE_APPS_LIST := $(subst /,,$(dir $(wildcard */Makefile))) + +.PHONY: all +all: sample_apps + +.PHONY: clean +clean: clean-apps + +sample_apps: + @for apps in $(SAMPLE_APPS_LIST); do \ + $(MAKE) -C $$apps \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O) || exit 1; \ + done + +clean-apps: + @for apps in $(SAMPLE_APPS_LIST); do \ + $(MAKE) -C $$apps \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O) \ + clean || exit 1; \ + done diff --git a/optee/samples/hwkey-agent/LICENSE b/optee/samples/hwkey-agent/LICENSE new file mode 100644 index 0000000..8fb3635 --- /dev/null +++ b/optee/samples/hwkey-agent/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (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/optee/samples/hwkey-agent/Makefile b/optee/samples/hwkey-agent/Makefile new file mode 100644 index 0000000..7deda53 --- /dev/null +++ b/optee/samples/hwkey-agent/Makefile @@ -0,0 +1,35 @@ +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# Input variables +# CROSS_COMPILE: The cross compiler. +# TA_DEV_KIT_DIR: The base directory of the TA-devkit. +# OPTEE_CLIENT_EXPORT: The base directory points to optee client's +# header files and libraries +# O: The base directory for build objects filetree. + +TARGET_DIR := $(notdir $(shell pwd)) + +.PHONY: all +all: + $(MAKE) -C ta \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + O=$(O)/ta/$(TARGET_DIR) + $(MAKE) -C host \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O)/ca/$(TARGET_DIR) \ + --no-builtin-variables + +.PHONY: clean +clean: + $(MAKE) -C ta \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + O=$(O)/ta/$(TARGET_DIR) \ + clean + $(MAKE) -C host \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O)/ca/$(TARGET_DIR) \ + clean + rm -rf $(O)/ca/$(TARGET_DIR) diff --git a/optee/samples/hwkey-agent/README b/optee/samples/hwkey-agent/README new file mode 100644 index 0000000..41aa80d --- /dev/null +++ b/optee/samples/hwkey-agent/README @@ -0,0 +1,75 @@ +********************************************************************** + Linux for Tegra + OP-TEE hwkey-agent sample app + README +********************************************************************** +This README provides an overview of the hwkey-app and how to +compile and use it. + +---------------------------------------------------------------------- +hwkey-app Overview +---------------------------------------------------------------------- + +The CA sample program named 'hwkey-app' that is intended to work with +the 'hwkey-agent' TA to provide encryption and decryption function +with the keys provided by TA. + +Using the user-defined key in EKB: +The CA must use the TEE Client API to communicate with the TA and send +the request with payload to TA to perform the crypto operation. Once +TA receives the request, it processes the data and uses the crypto +library to perform the operations with the user-defined key. This is a +software-based crypto operation provided by TA. + +Hardware-based RNG (Random Number Generator): +The CA can be used to query random numbers from the TA. The TA handles +the HW RNG to extract random numbers and return them to the CA. + +---------------------------------------------------------------------- +How to compile +---------------------------------------------------------------------- +The build depends on the build result of optee_os and optee_client. + +* Cross compiling on host machine +The input variables of the Makefile: +CROSS_COMPILE: The cross compiler. +TA_DEV_KIT_DIR: The base directory of the TA-devkit. +OPTEE_CLIENT_EXPORT: The base directory points to optee client's + header files and libraries +O: The base directory for build objects filetree. + + +An example of cross compiling on host machine. +$ make CROSS_COMPILE=$(CROSS_COMPILE) \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O) + +---------------------------------------------------------------------- +How to use hwkey-app +---------------------------------------------------------------------- +Check the command usage with "--help" parameter. +$ nvhwkey-app --help +Usage: nvhwkey-app [OPTION...] -e [-d] -i -o + or + nvhwkey-app -r + + -d Decryption mode + -e Encryption mode + -i, --in=file Input file for encrypt/decrypt + -o, --out=outfile Output file + -r, --get_random=len Get random number (input random number length) + -?, --help Give this help list + --usage Give a short usage message + +---------------------------------------------------------------------- +Example +---------------------------------------------------------------------- +An example of a file encryption. +$ nvhwkey-app -e -i -o + +An example of a file decryption. +$ nvhwkey-app -d -i -o + +An example of getting random numbers from secure RNG. +$ nvhwkey-app -r 16 diff --git a/optee/samples/hwkey-agent/host/Makefile b/optee/samples/hwkey-agent/host/Makefile new file mode 100644 index 0000000..b7c2113 --- /dev/null +++ b/optee/samples/hwkey-agent/host/Makefile @@ -0,0 +1,37 @@ +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# Input variables +# CROSS_COMPILE: The cross compiler. +# OPTEE_CLIENT_EXPORT: The base directory points to optee client's +# header files and libraries +# O: The base directory for build objects filetree. + +CC ?= $(CROSS_COMPILE)gcc + +CFLAGS += -Wall -I../ta/include -I./include +CFLAGS += -I$(OPTEE_CLIENT_EXPORT)/include +CFLAGS += -fstack-protector-strong +LDADD += -lteec -L$(OPTEE_CLIENT_EXPORT)/lib + +SRCS = hwkey_agent_ca.c +OBJS = $(patsubst %.c,$(O)/%.o,$(SRCS)) +BINARY = nvhwkey-app + +.PHONY: all install +all: $(BINARY) install + +$(BINARY): $(OBJS) + $(CC) -o $(O)/$@ $< $(LDADD) + +$(O)/%.o: %.c + mkdir -p $(O) + $(CC) $(CFLAGS) -c $< -o $@ + +install: $(BINARY) + mkdir -p $(OPTEE_CLIENT_EXPORT)/sbin + cp $(O)/$(BINARY) $(OPTEE_CLIENT_EXPORT)/sbin + +.PHONY: clean +clean: + rm -f $(OBJS) $(O)/$(BINARY) $(OPTEE_CLIENT_EXPORT)/sbin/$(BINARY) diff --git a/optee/samples/hwkey-agent/host/hwkey_agent_ca.c b/optee/samples/hwkey-agent/host/hwkey_agent_ca.c new file mode 100644 index 0000000..0454e5e --- /dev/null +++ b/optee/samples/hwkey-agent/host/hwkey_agent_ca.c @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AES_BLOCK_SIZE 16 +#define CRYPTO_PAYLOAD_SIZE 4096 +#define RNG_SRV_DATA_SIZE 2048 + +/* + * Note that, the default_iv can be a input factor of the CA program. + */ +static uint8_t default_iv[AES_BLOCK_SIZE] = { + 0x36, 0xeb, 0x39, 0xfe, 0x3a, 0xcf, 0x1a, 0xf5, + 0x68, 0xc1, 0xb8, 0xe6, 0xf4, 0x8e, 0x5c, 0x79, +}; + +static char args_doc[] = "-e [-d] -i -o or -r "; + +static struct argp_option options[] = { + { 0, 'e', 0, 0, "Encryption mode"}, + { 0, 'd', 0, 0, "Decryption mode"}, + {"in", 'i', "file", 0, "Input file for encrypt/decrypt"}, + {"out", 'o', "outfile", 0, "Output file" }, + {"get_random", 'r', "len", 0, "Get random number (input random number length)"}, + { 0 } +}; + +struct arguments { + bool encryption; + char* in_file; + char* out_file; + bool get_random; + int rng_size; +}; + +static error_t parse_opt(int key, char *arg, struct argp_state *state) +{ + struct arguments *argus = state->input; + + switch (key) { + case 'e': + argus->encryption = true; + break; + case 'd': + argus->encryption = false; + break; + case 'i': + if (arg) + argus->in_file = strdup(arg); + break; + case 'o': + if (arg) + argus->out_file = strdup(arg); + break; + case 'r': + argus->get_random = true; + if (arg) + argus->rng_size = atoi(arg); + else + argus->rng_size = 16; + break; + case ARGP_KEY_ARG: + case ARGP_KEY_END: + if (state->argc <= 1) + argp_usage(state); + if (argus->in_file && state->argc <= 5) + argp_usage(state); + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, 0, 0, 0, 0 }; + +typedef struct hwkey_ca_ctx { + TEEC_Context ctx; + TEEC_Session sess; + FILE *infptr; + FILE *outfptr; + struct arguments *argus; +} hwkey_ca_ctx_t; +static hwkey_ca_ctx_t ca_sess; + +static uint8_t iv[AES_BLOCK_SIZE] = { 0 }; + +static TEEC_Result prepare_tee_session(hwkey_ca_ctx_t *ctx) +{ + TEEC_UUID uuid = HWKEY_AGENT_TA_UUID; + uint32_t origin; + TEEC_Result rc; + + rc = TEEC_InitializeContext(NULL, &ctx->ctx); + if (rc != TEEC_SUCCESS) + goto tee_session_fail; + + rc = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &origin); + if (rc != TEEC_SUCCESS) { + TEEC_FinalizeContext(&ctx->ctx); + goto tee_session_fail; + } + +tee_session_fail: + return rc; +} + +static void terminate_tee_session(hwkey_ca_ctx_t *ctx) +{ + TEEC_CloseSession(&ctx->sess); + TEEC_FinalizeContext(&ctx->ctx); + + if (ctx->infptr != NULL) + fclose(ctx->infptr); + if (ctx->outfptr != NULL) + fclose(ctx->outfptr); + if (ctx->argus->in_file) + free(ctx->argus->in_file); + if (ctx->argus->out_file) + free(ctx->argus->out_file); +} + +static void fail_handler(int i) +{ + terminate_tee_session(&ca_sess); + + exit(i); +} + +static void crypto_srv_handler(hwkey_ca_ctx_t *ctx, bool enc, uint8_t *in_data, + int data_len, FILE *outfptr, uint8_t *out_data) +{ + TEEC_Operation op; + TEEC_Result rc; + uint32_t origin, cmd_id; + + memset(&op, 0, sizeof(op)); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE); + op.params[0].tmpref.buffer = &iv; + op.params[0].tmpref.size = AES_BLOCK_SIZE; + op.params[1].tmpref.buffer = in_data; + op.params[1].tmpref.size = data_len; + op.params[2].tmpref.buffer = out_data; + op.params[2].tmpref.size = CRYPTO_PAYLOAD_SIZE; + + if (enc) + cmd_id = HWKEY_AGENT_TA_CMD_ENCRYPTION; + else + cmd_id = HWKEY_AGENT_TA_CMD_DECRYPTION; + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ctx->sess, cmd_id, &op, &origin); + if (rc != TEEC_SUCCESS) { + printf("TEEC_InvokeCommand failed 0x%x origin 0x%x\n", rc, + origin); + fail_handler(1); + } + + /* Write output buffer to file. */ + fwrite(out_data, op.params[2].tmpref.size, 1, outfptr); + + /* Update IV for the next block. */ + if (enc) + memcpy(iv, out_data, AES_BLOCK_SIZE); + else + memcpy(iv, in_data, AES_BLOCK_SIZE); +} + +static void handle_file_encryption(hwkey_ca_ctx_t *ctx) +{ + uint8_t *input_buf, *output_buf; + + /* Create and open the input/output files */ + ctx->infptr = fopen(ctx->argus->in_file, "rb"); + if (ctx->infptr == NULL) { + printf("Fail to open the input file: %s\n", + ctx->argus->in_file); + fail_handler(1); + } + + ctx->outfptr = fopen(ctx->argus->out_file, "wb"); + if (ctx->outfptr == NULL) { + printf("Fail to open the output file: %s\n", + ctx->argus->out_file); + fail_handler(1); + } + + input_buf = calloc(1, CRYPTO_PAYLOAD_SIZE); + output_buf = calloc(1, CRYPTO_PAYLOAD_SIZE); + if ((input_buf == NULL) || (output_buf == NULL)) { + printf("Fail to allocate buffers.\n"); + fail_handler(1); + } + + /* Copy the IV for the first block. */ + memcpy(iv, default_iv, AES_BLOCK_SIZE); + + do { + int f_rc; + + f_rc = fread(input_buf, 1, CRYPTO_PAYLOAD_SIZE, ctx->infptr); + if (f_rc < 0) { + printf("Unexpected failure when reading input file.\n"); + fail_handler(1); + } + + crypto_srv_handler(ctx, ctx->argus->encryption, input_buf, f_rc, + ctx->outfptr, output_buf); + + if (f_rc < CRYPTO_PAYLOAD_SIZE) + break; + } while(true); + + free(input_buf); + free(output_buf); +} + +static void dump_random_num(const uint8_t *ptr, size_t len) +{ + const uint8_t *addr = ptr; + size_t count; + size_t i; + + for (count = 0 ; count < len; count += 16) { + for (i = 0; i < MIN(len - count, 16); i++) + fprintf(stderr, "%02hhx", *(addr + i)); + fprintf(stderr, "\n"); + addr += 16; + } +} + +static void handle_get_random(hwkey_ca_ctx_t *ctx) +{ + TEEC_Operation op; + TEEC_Result rc; + uint8_t *rng_buff; + uint32_t origin; + + if (ctx->argus->rng_size == 0) + return; + + if (ctx->argus->rng_size > RNG_SRV_DATA_SIZE) { + printf("%s: the maximum random number lenght is %d.\n", + __func__, RNG_SRV_DATA_SIZE); + return; + } + + rng_buff = calloc(1, ctx->argus->rng_size); + if (rng_buff == NULL) { + printf("%s: calloc fail.\n", __func__); + return; + } + + memset(&op, 0, sizeof(op)); + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, + TEEC_NONE, + TEEC_NONE); + op.params[0].tmpref.buffer = rng_buff; + op.params[0].tmpref.size = ctx->argus->rng_size; + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ctx->sess, HWKEY_AGENT_TA_CMD_GET_RANDOM, + &op, &origin); + if (rc != TEEC_SUCCESS) { + printf("TEEC_InvokeCommand failed 0x%x origin 0x%x\n", rc, + origin); + goto err_get_random; + } + + if (op.params[0].tmpref.size > 0) + dump_random_num(rng_buff, op.params[0].tmpref.size); + else + printf("%s: get_random fail.\n", __func__); + +err_get_random: + free(rng_buff); +} + +int main(int argc, char *argv[]) +{ + struct arguments argus; + + /* Initialize the arguments */ + argus.in_file = NULL; + argus.out_file = NULL; + argus.encryption = false; + argus.get_random = false; + + /* Handle the break signal */ + signal(SIGINT, fail_handler); + + /* Handle the input parameters */ + argp_parse(&argp, argc, argv, 0, 0, &argus); + ca_sess.argus = &argus; + + if(prepare_tee_session(&ca_sess)) + goto err_out; + + if (argus.in_file) + handle_file_encryption(&ca_sess); + + if (argus.get_random) + handle_get_random(&ca_sess); + +err_out: + terminate_tee_session(&ca_sess); + + return 0; +} diff --git a/optee/samples/hwkey-agent/host/tool/gen_ekb/README b/optee/samples/hwkey-agent/host/tool/gen_ekb/README new file mode 100644 index 0000000..611bddc --- /dev/null +++ b/optee/samples/hwkey-agent/host/tool/gen_ekb/README @@ -0,0 +1,129 @@ +********************************************************************** + Linux for Tegra + Tool: gen_ekb.py + README +********************************************************************** +This README provides an overview of the "gen_ekb.py" tool to generate +an EKS image file "eks.img". It has a pre-defined layout of EKB that +includes a CMAC text, a random IV, and encrypted user data. The Jetson +user key PTA in OP-TEE extracts the EKB that generated by this script. + +---------------------------------------------------------------------- +Dependency +---------------------------------------------------------------------- +- Python version 3.6 or above +- Python cryptography modules pyca/cryptography and pycrypto. You can +install that via "apt" or "pip" command on your Linux host machine. + +$> apt-get install python3-cryptography +or +$> pip install cryptography + +and + +$> pip install pycrypto +---------------------------------------------------------------------- +Tool: gen_ekb.py overview +---------------------------------------------------------------------- + +Note that You can define a specific mechanism to encapsulate the EKB +contents depending on the requirement. This tool will introduce a demo +that shows how to encrypt a symmetric key with a random IV +(initial vector) that is used to encrypt the key with AES-CBC +algorithm and generate an authentication code EKB_cmac that can be +used to verify the EKB content to make sure it's not modified. + +The script shows how to perform the following steps to generate the +EKB blob. + +The EKB layout: +---------------------------------------------------------- +| ekb-size | magic-id | ver-major | ver-minor | +---------------------------------------------------------- +| cmac | +---------------------------------------------------------- +| cont-data-len | cont-magic-id | reserved | +---------------------------------------------------------- +| iv | +---------------------------------------------------------- +| tag1 | key1-len | key1 | +---------------------------------------------------------- +| key1(continued) | tag2 | key2-len | +---------------------------------------------------------- +| key2(continued) | +---------------------------------------------------------- +| key2(continued) | tag3 | key3-len | +---------------------------------------------------------- +| ... | +---------------------------------------------------------- +| end-tag(\0\0\0\0) | end-tag-len(\0\0\0\0) | +---------------------------------------------------------- + +* Each row in the first four rows occupies 16 bytes +* The tag, key length and key data are encrypted and saved after "iv" +* The zeroes at the end of the EKB image indicate the end of user data +* Normally EKB saves user keys so the term "key" is used in above diagram. + Technically any user data can be saved in EKB. + +The steps of EKB generation: +* Derive RK (Root Key) + * Need a fixed vector FV_for_ekb + * Deriving RK (Root Key) from fuse key(T194: KEK2, T234: OEM_K2) + * EKB_RK = AES-128-ECB(fuse_key, FV_for_ekb) +* Generate DKs (Derived keys) that follows NIST-SP-800-108 KDF scheme + * EKB_EK = NIST-SP-800-108(EKB_RK, ...) + * EKB_AK = NIST-SP-800-108(EKB_RK, ...) +* Acquire EKB content ciphertext + * EKB_ciphertext = AES-128-CBC(iv=Random_IV, key=EKB_EK, + user data) +* Acquire EKB_cmac code + * EKB_content = Random_IV + EKB_ciphertext + * EKB_cmac = AES-CMAC(key=EKB_AK, EKB_content) +* Generate EKB blob (eks.img) + * EKB_blob = EKB_header + EKB_cmac + EKB_content + +---------------------------------------------------------------------- +Default EKB Binary +---------------------------------------------------------------------- + +The default EKB binary is located at: +/bootloader/eks_t194.img +/bootloader/eks_t234.img + +---------------------------------------------------------------------- +How to use the script +---------------------------------------------------------------------- + +This program is a sample program that generates the EKB that works with +TEE sample: sample/hwkey-agent + +To generate the sample EKB for EKS partition yourself, run "example.sh". + +To view usage: +$ python gen_ekb.py --help + +The input options: +-chip: specify chip: t194|t234 +-kek2_kek: kek2 key (16 bytes) file in hex format [t194 only] +-oem_k1_key: oem_k1 key (32 bytes) file in hex format [t234 only] +-fv: fixed vectors (16 bytes) file for ekb in hex format +-in_sym_key: 16-bytes symmetric key file in hex format +-in_sym_key2: 16-bytes symmetric key file in hex format +-out: where the eks image file is stored + +Following the command for example. +$ python3 gen_ekb.py + -chip t194 \ + -key2_key kek2_key_file \ + -fv fv_for_ekb_file \ + -in_sym_key user_key_file \ + -in_sym_key2 user2_key_file \ + -out eks.img + +$ python3 gen_ekb.py + -chip t234 \ + -oem_k1_key oem_k1_key_file \ + -fv fv_for_ekb_file \ + -in_sym_key user_key_file \ + -in_sym_key2 user2_key_file \ + -out eks.img diff --git a/optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh b/optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh new file mode 100755 index 0000000..6b9e346 --- /dev/null +++ b/optee/samples/hwkey-agent/host/tool/gen_ekb/example.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# [T194 example] +# This is default KEK2 root key for unfused board +echo "00000000000000000000000000000000" > kek2.key + +# This is the fixed vector for deriving EKB root key from fuse. +# It is expected user to replace the FV below with a user specific +# FV, and code the exact same user specific FV into OP-TEE. +echo "bad66eb4484983684b992fe54a648bb8" > fv_ekb_t194 + +# Generate user-defined symmetric key files +# openssl rand -rand /dev/urandom -hex 16 > sym_t194.key +# openssl rand -rand /dev/urandom -hex 16 > sym2_t194.key +echo "00000000000000000000000000000000" > sym_t194.key +echo "00000000000000000000000000000000" > sym2_t194.key + +python3 gen_ekb.py -chip t194 -kek2_key kek2.key \ + -fv fv_ekb_t194 \ + -in_sym_key sym_t194.key \ + -in_sym_key2 sym2_t194.key \ + -out eks_t194.img + +# [T234 example] +# Fill your OEM_K1 fuse key value +echo "2d4a614e645267556b58703273357638792f423f4428472b4b6250655368566d" > oem_k1.key + +# This is the fixed vector for deriving EKB root key from fuse. +# It is expected user to replace the FV below with a user specific +# FV, and code the exact same user specific FV into OP-TEE. +echo "bad66eb4484983684b992fe54a648bb8" > fv_ekb_t234 + +# Generate user-defined symmetric key files +# openssl rand -rand /dev/urandom -hex 32 > sym_t234.key # kernel/kernel-dtb encryption key +# openssl rand -rand /dev/urandom -hex 16 > sym2_t234.key # disk encryption key +echo "0000000000000000000000000000000000000000000000000000000000000000" > sym_t234.key +echo "f0e0d0c0b0a001020304050607080900" > sym2_t234.key +echo "ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221100ffeeddccbbaa99887766554433221100" > device_id.cert # Not used + +python3 gen_ekb.py -chip t234 -oem_k1_key oem_k1.key \ + -fv fv_ekb_t234 \ + -in_sym_key sym_t234.key \ + -in_sym_key2 sym2_t234.key \ + -in_device_id device_id.cert \ + -out eks_t234.img diff --git a/optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py b/optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py new file mode 100755 index 0000000..434ea10 --- /dev/null +++ b/optee/samples/hwkey-agent/host/tool/gen_ekb/gen_ekb.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2021-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# Version History +# +# 1.0: Initial version with T194 support +# 1.1: Add T234 support +# 1.2: Refactored EKB structure to make it more generic +# 1.3: Removed UEFI encryption and authentication keys from EKB (moved to MB2-BCT instead) +# 1.4: Support both OEM_K1 and OEM_K2 keys as the root key of EKB image (T234 only) +# + +import argparse +import codecs +import os.path +import struct +import sys + +from Crypto.Cipher import AES +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import cmac +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from math import ceil + +#EKS image version +version_major = 1 +version_minor = 0 + +# EKB key types +ekb_kernel_encryption_key = 1; +ekb_disk_encryption_key = 2; +ekb_device_id_cert = 3; + +def pkcs7_padding(plain_text): + block_size = AES.block_size + number_of_bytes_to_pad = block_size - len(plain_text) % block_size + padding_str = number_of_bytes_to_pad * bytes([number_of_bytes_to_pad]) + padded_plain_text = plain_text + padding_str + return padded_plain_text + +def ekb_cmac_gen(key, msg): + c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) + c.update(msg) + return c.finalize() + +def ekb_encrypt(content, key, iv): + cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend()) + encryptor = cipher.encryptor() + return encryptor.update(content) + encryptor.finalize() + +def generateBlob(content, key_ek, key_ak): + content_header_fmt = " contentmaxsize: + raise Exception("Content is too big") + + # generate a random iv, then encrypt the key data content + # join the iv and content header, calc cmac on the total data + iv = os.getrandom(16, os.GRND_NONBLOCK) + encrypted_content = ekb_encrypt(content, key_ek, iv) + data = b"".join([iv, encrypted_content]) + content_header = struct.pack(content_header_fmt, len(encrypted_content), b"EEKB") + data = b"".join([content_header, data]) + ekb_cmac = ekb_cmac_gen(key_ak, data) + + # if size is less than 1K, then padding it to 1024 + ekb_size = len(ekb_cmac) + len(content_header) + len(iv) + len(encrypted_content) + ekb_header_wo_size_field + if ekb_size < 1024: + pad_char = (1024 - ekb_size) % 256 + encrypted_content += bytes([pad_char]) * (1024 - ekb_size) + + # pack the ekb image with header + eks_len = ekb_header_wo_size_field + len(ekb_cmac) + len(content_header) + len(iv) + len(encrypted_content) + header = struct.pack(ekb_header_fmt, eks_len, b"NVEKBP\0\0", version_major, version_minor) + blob = header + ekb_cmac + content_header + iv + encrypted_content + return blob + +def nist_sp_800_108_with_CMAC(key, context=b"", label=b"", len=16): + okm = b"" + output_block = b"" + for count in range(ceil(len/16)): + data = b"".join([bytes([count+1]), label.encode(encoding="utf8"), bytes([0]), context.encode(encoding="utf8"), int(len*8).to_bytes(4, byteorder="big")]) + c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) + c.update(data) + output_block = c.finalize() + okm += output_block + return okm[:len] + +def gen_ekb_rk(fuse_key, fv): + rk = AES.new(fuse_key, AES.MODE_ECB) + return rk.encrypt(fv) + +def load_file_check_size(f, size=16): + with open(f, 'rb') as fd: + content = fd.read().strip() + key = codecs.decode(content, 'hex') + if len(key) != size: + raise Exception("Wrong size") + return key + +def pack_key(f, tag): + fmt = " +#include +#include +#include +#include + +#define AES128_KEY_BIT_SIZE 128 +#define AES128_KEY_BYTE_SIZE (AES128_KEY_BIT_SIZE / 8) + +typedef struct hwkey_srv_session { + bool enc_mode; + bool initialized; + uint8_t ekb_key[AES128_KEY_BYTE_SIZE]; + TEE_OperationHandle op_handle; + TEE_ObjectHandle key_handle; +} hwkey_srv_sess_t; + +static TEE_Result invoke_jetson_user_key_pta(uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + static TEE_TASessionHandle sess = TEE_HANDLE_NULL; + static const TEE_UUID uuid = JETSON_USER_KEY_UUID; + + if (sess == TEE_HANDLE_NULL) { + TEE_Result rc = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &sess, NULL); + + if (rc) + return rc; + } + + return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, + param_types, params, NULL); +} + +static TEE_Result prepare_crypto_op(hwkey_srv_sess_t *sess) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param pta_params[TEE_NUM_PARAMS] = { }; + TEE_Attribute attr; + uint32_t mode; + + /* Query EKB key. */ + pta_params[0].value.a = EKB_USER_KEY_DISK_ENCRYPTION; + pta_params[1].memref.buffer = sess->ekb_key; + pta_params[1].memref.size = AES128_KEY_BYTE_SIZE; + rc = invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_GET_EKB_KEY, + param_types, pta_params); + if (rc) + return rc; + + /* Prepare AES OP. */ + if (sess->enc_mode) + mode = TEE_MODE_ENCRYPT; + else + mode = TEE_MODE_DECRYPT; + + rc = TEE_AllocateOperation(&sess->op_handle, + TEE_ALG_AES_CTR, + mode, + AES128_KEY_BIT_SIZE); + if (rc != TEE_SUCCESS) { + EMSG("%s: TEE_AllocationOperation failed.", __func__); + sess->op_handle = TEE_HANDLE_NULL; + goto err; + } + + rc = TEE_AllocateTransientObject(TEE_TYPE_AES, + AES128_KEY_BIT_SIZE, + &sess->key_handle); + if (rc != TEE_SUCCESS) { + EMSG("%s: TEE_AllocateTransientObject failed.", __func__); + sess->key_handle = TEE_HANDLE_NULL; + goto err; + } + + TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, + sess->ekb_key, AES128_KEY_BYTE_SIZE); + + rc = TEE_PopulateTransientObject(sess->key_handle, &attr, 1); + if (rc != TEE_SUCCESS) { + EMSG("%s: TEE_PopulateTransientObject failed.", __func__); + goto err; + } + + rc = TEE_SetOperationKey(sess->op_handle, sess->key_handle); + if (rc != TEE_SUCCESS) { + EMSG("%s: TEE_SetOperationKey failed.", __func__); + goto err; + } + + return rc; + +err: + if (sess->op_handle != TEE_HANDLE_NULL) + TEE_FreeOperation(sess->op_handle); + sess->op_handle = TEE_HANDLE_NULL; + + if (sess->key_handle != TEE_HANDLE_NULL) + TEE_FreeTransientObject(sess->key_handle); + sess->key_handle = TEE_HANDLE_NULL; + + return rc; +} + +static TEE_Result hwkey_crypto_op(hwkey_srv_sess_t *sess, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + if ((params[0].memref.size != AES128_KEY_BYTE_SIZE) || + (params[2].memref.size < params[1].memref.size)) + return TEE_ERROR_BAD_PARAMETERS; + + if (!sess->initialized) { + rc = prepare_crypto_op(sess); + if (rc == TEE_SUCCESS) + sess->initialized = true; + else + return rc; + } + + /* Init cipher with IV. */ + TEE_CipherInit(sess->op_handle, + params[0].memref.buffer, + params[0].memref.size); + + /* Cipher update. */ + rc = TEE_CipherUpdate(sess->op_handle, + params[1].memref.buffer, params[1].memref.size, + params[2].memref.buffer, ¶ms[2].memref.size); + + return rc; +} + +static TEE_Result hwkey_get_rng_op(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint32_t pta_pa = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param pta_params[TEE_NUM_PARAMS] = { }; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + + /* Query random bytes. */ + pta_params[0].memref.buffer = params[0].memref.buffer; + pta_params[0].memref.size = params[0].memref.size; + rc = invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_GET_RANDOM, + pta_pa, pta_params); + if (rc) + return rc; + + params[0].memref.size = pta_params[0].memref.size; + + return rc; +} + +TEE_Result TA_CreateEntryPoint(void) +{ + /* Nothing to do */ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ + /* Nothing to do */ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types, + TEE_Param __unused params[TEE_NUM_PARAMS], + void __unused **session) +{ + hwkey_srv_sess_t *sess; + + sess = TEE_Malloc(sizeof(*sess), TEE_MALLOC_FILL_ZERO); + if (!sess) + return TEE_ERROR_OUT_OF_MEMORY; + + *session = (void*)sess; + + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *session) +{ + hwkey_srv_sess_t *sess; + + sess = (hwkey_srv_sess_t*)session; + + if (sess->key_handle != TEE_HANDLE_NULL) + TEE_FreeTransientObject(sess->key_handle); + if (sess->op_handle != TEE_HANDLE_NULL) + TEE_FreeOperation(sess->op_handle); + + TEE_Free(sess); +} + +TEE_Result TA_InvokeCommandEntryPoint(void *session, + uint32_t cmd, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + hwkey_srv_sess_t *sess = (hwkey_srv_sess_t*)session; + + switch (cmd) { + case HWKEY_AGENT_TA_CMD_ENCRYPTION: + sess->enc_mode = true; + return hwkey_crypto_op(sess, param_types, params); + case HWKEY_AGENT_TA_CMD_DECRYPTION: + sess->enc_mode = false; + return hwkey_crypto_op(sess, param_types, params); + case HWKEY_AGENT_TA_CMD_GET_RANDOM: + return hwkey_get_rng_op(param_types, params); + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} diff --git a/optee/samples/hwkey-agent/ta/include/hwkey_agent_ta.h b/optee/samples/hwkey-agent/ta/include/hwkey_agent_ta.h new file mode 100644 index 0000000..f5bd745 --- /dev/null +++ b/optee/samples/hwkey-agent/ta/include/hwkey_agent_ta.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __HWKEY_AGENT_TA_H__ +#define __HWKEY_AGENT_TA_H__ + +/* + * Each trusted app UUID should have a unique UUID that is + * generated from a UUID generator such as + * https://www.uuidgenerator.net/ + * + * UUID : {82154947-c1bc-4bdf-b89d-04f93c0ea97c} + */ +#define HWKEY_AGENT_TA_UUID \ + { 0x82154947, 0xc1bc, 0x4bdf, \ + { 0xb8, 0x9d, 0x04, 0xf9, 0x3c, 0x0e, 0xa9, 0x7c} } + +/* + * HWKEY_AGENT_TA_CMD_ENCRYPTION - Data encryption by EKB USER KEY + * param[0] in (memref) IV data, IV size + * param[1] in (memref) payload, payload size + * param[2] out (memref) output_buf, output_buf size + * param[3] unused + */ +#define HWKEY_AGENT_TA_CMD_ENCRYPTION 0 + +/* + * HWKEY_AGENT_TA_CMD_DECRYPTION - Data decryption by EKB USER KEY + * param[0] in (memref) IV data, IV size + * param[1] in (memref) payload, payload size + * param[2] out (memref) output_buf, output_buf size + * param[3] unused + */ +#define HWKEY_AGENT_TA_CMD_DECRYPTION 1 + +/* + * HWKEY_AGENT_TA_CMD_GET_RANDOM - Get random bytes from RNG + * param[0] out (memref) RNG data, RNG size + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define HWKEY_AGENT_TA_CMD_GET_RANDOM 2 + +#endif diff --git a/optee/samples/hwkey-agent/ta/sub.mk b/optee/samples/hwkey-agent/ta/sub.mk new file mode 100644 index 0000000..ded8152 --- /dev/null +++ b/optee/samples/hwkey-agent/ta/sub.mk @@ -0,0 +1,5 @@ +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +global-incdirs-y += include +srcs-y += hwkey_agent_ta.c diff --git a/optee/samples/hwkey-agent/ta/user_ta_header_defines.h b/optee/samples/hwkey-agent/ta/user_ta_header_defines.h new file mode 100644 index 0000000..8c09b76 --- /dev/null +++ b/optee/samples/hwkey-agent/ta/user_ta_header_defines.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021-2022, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __USER_TA_HEADER_DEFINES_H__ +#define __USER_TA_HEADER_DEFINES_H__ + +#include + +#define TA_UUID HWKEY_AGENT_TA_UUID +#define TA_FLAGS TA_FLAG_SINGLE_INSTANCE +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (16 * 1024) + +#endif diff --git a/optee/samples/luks-srv/LICENSE b/optee/samples/luks-srv/LICENSE new file mode 100644 index 0000000..8fb3635 --- /dev/null +++ b/optee/samples/luks-srv/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (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/optee/samples/luks-srv/Makefile b/optee/samples/luks-srv/Makefile new file mode 100644 index 0000000..dd71d34 --- /dev/null +++ b/optee/samples/luks-srv/Makefile @@ -0,0 +1,39 @@ +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# Input variables +# CROSS_COMPILE: The cross compiler. +# TA_DEV_KIT_DIR: The base directory of the TA-devkit. +# OPTEE_CLIENT_EXPORT: The base directory points to optee client's +# header files and libraries +# O: The base directory for build objects filetree. + +TARGET_DIR := $(notdir $(shell pwd)) + +.PHONY: all +all: early_ta_dir + $(MAKE) -C ta \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + O=$(O)/early_ta/$(TARGET_DIR) + $(MAKE) -C host \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O)/ca/$(TARGET_DIR) \ + --no-builtin-variables + +early_ta_dir: + mkdir -p $(O)/early_ta + +.PHONY: clean +clean: + $(MAKE) -C ta \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + O=$(O)/early_ta/$(TARGET_DIR) \ + clean + $(MAKE) -C host \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O)/ca/$(TARGET_DIR) \ + clean + rm -rf $(O)/early_ta/$(TARGET_DIR) + rm -rf $(O)/ca/$(TARGET_DIR) diff --git a/optee/samples/luks-srv/README b/optee/samples/luks-srv/README new file mode 100644 index 0000000..effbde8 --- /dev/null +++ b/optee/samples/luks-srv/README @@ -0,0 +1,65 @@ +********************************************************************** + Linux for Tegra + OP-TEE luks-srv sample app + README +********************************************************************** +This README provides an overview of the luks-srv sample TA/CA and how +to compile and use it. + +---------------------------------------------------------------------- +luks-srv-app CA Overview +---------------------------------------------------------------------- + +The luks-srv-app is a sample CA program that can be used to query the +hardware-based passphrase from the TA. Then the third party OSS LUKS +utility e.g. "cryptsetup" can use the passphrase to unlock the +encrypted disks during the boot process. Once the boot process is done +, the CA can send LUKS_SRV_TA_CMD_SRV_DOWN command to TA. This command +tells the luks-srv TA not to respond to any LUKS_GET passphrase command +again until reboot. This allows the passphrase to be extracted during +boot (e.g. in initrd) but then prevents any form of later +attack/malicious-code that attempts to obtain the passphrase again. + +---------------------------------------------------------------------- +How to compile +---------------------------------------------------------------------- +The build depends on the build result of optee_os and optee_client. + +* Cross compiling on host machine +The input variables of the Makefile: +CROSS_COMPILE: The cross compiler. +TA_DEV_KIT_DIR: The base directory of the TA-devkit. +OPTEE_CLIENT_EXPORT: The base directory points to optee client's + header files and libraries +O: The base directory for build objects filetree. + + +An example of cross compiling on host machine. +$ make CROSS_COMPILE=$(CROSS_COMPILE) \ + TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR) \ + OPTEE_CLIENT_EXPORT=$(OPTEE_CLIENT_EXPORT) \ + O=$(O) + +---------------------------------------------------------------------- +How to use luks-srv-app +---------------------------------------------------------------------- +Check the command usage with "--help" parameter. +$ nvluks-srv-app --help +Usage: nvluks-srv-app [OPTION...] -c -u | -n + + -c, --context-string=CONTEXT STRING + The context string for passphrase + generation (Max length: 40). + -n, --no-pass-response No passphrase response after this command. + -u, --get-unique-pass Get unique passphrase. + -?, --help Give this help list. + --usage Give a short usage message. + +---------------------------------------------------------------------- +Example +---------------------------------------------------------------------- +An example of querying a unique per-device passphrase. +$ luks-srv-app -u -c "${DISK_UUID}" + +An example of sending NO_PASS_RESPONSE command +$ luks-srv-app -n diff --git a/optee/samples/luks-srv/host/Makefile b/optee/samples/luks-srv/host/Makefile new file mode 100644 index 0000000..c9a2dcc --- /dev/null +++ b/optee/samples/luks-srv/host/Makefile @@ -0,0 +1,42 @@ +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# Input variables +# CROSS_COMPILE: The cross compiler. +# OPTEE_CLIENT_EXPORT: The base directory points to optee client's +# header files and libraries +# O: The base directory for build objects filetree. + +CC ?= $(CROSS_COMPILE)gcc +LD ?= $(CROSS_COMPILE)ld +STRIP ?= $(CROSS_COMPILE)strip + +CFLAGS += -Wall -I../ta/include -I./include +CFLAGS += -I$(OPTEE_CLIENT_EXPORT)/include +CFLAGS += -fstack-protector-strong +LDADD += -pthread -lpthread +LDADD += -lteec -L$(OPTEE_CLIENT_EXPORT)/lib +LDFLAGS := -static + +SRCS = luks_srv_ca.c +OBJS = $(patsubst %.c,$(O)/%.o,$(SRCS)) +BINARY = nvluks-srv-app + +.PHONY: all install +all: $(BINARY) install + +$(BINARY): $(OBJS) + $(CC) $(LDFLAGS) -o $(O)/$@ $< $(LDADD) + $(STRIP) $(O)/$@ + +$(O)/%.o: %.c + mkdir -p $(O) + $(CC) $(CFLAGS) -c $< -o $@ + +install: $(BINARY) + mkdir -p $(OPTEE_CLIENT_EXPORT)/sbin + cp $(O)/$(BINARY) $(OPTEE_CLIENT_EXPORT)/sbin + +.PHONY: clean +clean: + rm -f $(OBJS) $(O)/$(BINARY) $(OPTEE_CLIENT_EXPORT)/sbin/$(BINARY) diff --git a/optee/samples/luks-srv/host/luks_srv_ca.c b/optee/samples/luks-srv/host/luks_srv_ca.c new file mode 100644 index 0000000..49bc029 --- /dev/null +++ b/optee/samples/luks-srv/host/luks_srv_ca.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2023, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef enum { + OPT_NONE, + OPT_NO_PASS_RESPONSE, + OPT_GENERIC_PASSPHRASE, + OPT_UNIQUE_PASSPHRASE, +} LUKS_APP_OPT_t; + +static char args_doc[] = "-c -u | -n"; + +static struct argp_option options[] = { + {"context-string", 'c', "CONTEXT STRING", 0, "The context string for passphrase generation (Max length: 40)."}, + {"get-generic-pass", 'g', 0, 0, "Get generic passphrase."}, + {"get-unique-pass", 'u', 0 , 0, "Get unique passphrase."}, + {"no-pass-response", 'n', 0, 0, "No passphrase response after this command."}, + { 0 } +}; + +struct arguments { + char *context_str; + LUKS_APP_OPT_t opt; +}; + +static error_t parse_opt(int key, char *arg, struct argp_state *state) +{ + struct arguments *argus = state->input; + + switch (key) { + case 'c': + argus->context_str = strdup(arg); + break; + case 'g': + argus->opt = OPT_GENERIC_PASSPHRASE; + break; + case 'u': + argus->opt = OPT_UNIQUE_PASSPHRASE; + break; + case 'n': + argus->opt = OPT_NO_PASS_RESPONSE; + break; + case ARGP_KEY_ARG: + if (state->argc < 1) + argp_usage(state); + case ARGP_KEY_END: + if (!argus->context_str || + strlen(argus->context_str) > LUKS_SRV_CONTEXT_STR_LEN) + if (OPT_NO_PASS_RESPONSE != argus->opt) + argp_usage(state); + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, 0, 0, 0, 0 }; + +typedef struct luks_ca_ctx { + TEEC_Context ctx; + TEEC_Session sess; +} luks_ca_ctx_t; + +static void prepare_tee_session(luks_ca_ctx_t *ctx) +{ + TEEC_UUID uuid = LUKS_SRV_TA_UUID; + uint32_t origin; + TEEC_Result rc; + + rc = TEEC_InitializeContext(NULL, &ctx->ctx); + if (rc != TEEC_SUCCESS) + errx(1, "TEEC_InitializeContext failed with code 0x%x", rc); + + rc = TEEC_OpenSession(&ctx->ctx, &ctx->sess, &uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &origin); + if (rc != TEEC_SUCCESS) { + TEEC_FinalizeContext(&ctx->ctx); + errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x", + rc, origin); + } +} + +static void terminate_tee_session(luks_ca_ctx_t *ctx) +{ + TEEC_CloseSession(&ctx->sess); + TEEC_FinalizeContext(&ctx->ctx); +} + +static void luks_srv_app_handler(struct arguments *argus, luks_ca_ctx_t *ctx) +{ + TEEC_Operation op; + TEEC_Result rc; + uint32_t origin, cmd_id; + uint32_t i; + uint8_t passphrase[LUKS_SRV_PASSPHRASE_LEN]; + + memset(&op, 0, sizeof(op)); + + switch (argus->opt) { + case OPT_NO_PASS_RESPONSE: + cmd_id = LUKS_SRV_TA_CMD_SRV_DOWN; + break; + case OPT_GENERIC_PASSPHRASE: + cmd_id = LUKS_SRV_TA_CMD_GET_GENERIC_PASS; + break; + case OPT_UNIQUE_PASSPHRASE: + cmd_id = LUKS_SRV_TA_CMD_GET_UNIQUE_PASS; + break; + default: + printf("nvluks-srv: unknown option!\n"); + return; + } + + if ((LUKS_SRV_TA_CMD_GET_UNIQUE_PASS == cmd_id) || + (LUKS_SRV_TA_CMD_GET_GENERIC_PASS == cmd_id)) { + op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT, + TEEC_MEMREF_TEMP_OUTPUT, + TEEC_NONE, + TEEC_NONE); + op.params[0].tmpref.buffer = argus->context_str; + op.params[0].tmpref.size = strlen(argus->context_str); + op.params[1].tmpref.buffer = passphrase; + op.params[1].tmpref.size = LUKS_SRV_PASSPHRASE_LEN; + } + + /* Send command to TA. */ + rc = TEEC_InvokeCommand(&ctx->sess, cmd_id, &op, &origin); + if (rc != TEEC_SUCCESS) { + printf("TEEC_InvokeCommand failed 0x%x origin 0x%x\n", rc, + origin); + return; + } + + if ((LUKS_SRV_TA_CMD_GET_UNIQUE_PASS == cmd_id) || + (LUKS_SRV_TA_CMD_GET_GENERIC_PASS == cmd_id)) { + for (i = 0; i < LUKS_SRV_PASSPHRASE_LEN; i ++) + fprintf(stdout, "%02x", passphrase[i]); + fprintf(stdout, "\n"); + } + + if (argus->context_str) + free(argus->context_str); +} + +int main(int argc, char *argv[]) +{ + struct arguments argus = { + .context_str = NULL, + .opt = OPT_NONE, + }; + luks_ca_ctx_t ca_sess; + + /* Handle the input parameters */ + argp_parse(&argp, argc, argv, 0, 0, &argus); + + prepare_tee_session(&ca_sess); + + luks_srv_app_handler(&argus, &ca_sess); + + terminate_tee_session(&ca_sess); + + return 0; +} diff --git a/optee/samples/luks-srv/host/tool/gen_luks_passphrase/README b/optee/samples/luks-srv/host/tool/gen_luks_passphrase/README new file mode 100644 index 0000000..db4665c --- /dev/null +++ b/optee/samples/luks-srv/host/tool/gen_luks_passphrase/README @@ -0,0 +1,67 @@ +********************************************************************** + Linux for Tegra + Tool: gen_luks_passphrase.py + README +********************************************************************** +This README provides an overview of the "gen_luks_passphrase.py" +script to generate a passphrase for creating disk image, which is then +flashed onto the device. It uses the same procedures with the TA in +the OP-TEE, so the passphrase is identical on both sides. + +---------------------------------------------------------------------- +Dependency +---------------------------------------------------------------------- + +This script depends on a Python cryptography module, +"pyca/cryptography". You can install that via "apt" or "pip" command +on your Linux host machine. + +$> apt-get install python3-cryptography +or +$> pip install cryptography + +---------------------------------------------------------------------- +Tool: gen_luks_passphrase.py overview +---------------------------------------------------------------------- +The script shows how to generate a passphrase based on the key source +from EKB. You can reference the steps below. Note that you can define +the procedures like key source or KDF (Key Derivation Function) for +the passphrase generation and implement the same in the Trusty TA. + +The steps of passphrase generation: + 1. Derive the LUKS key: + luks_key = KDF(ekb_key, + label_str="luks-srv-ecid", + context_str="${ECID}") + 2. Generate the passphrase: + passphrase = KDF(luks_key, + label_str="luks-srv-passphrase", + context_str="device's UUID or user's input str") +The KDF (Key Derivation Function) is the NIST-SP-800-108. + +---------------------------------------------------------------------- +How to use the script +---------------------------------------------------------------------- +To view usage: +$ python3 gen_luks_passphrase.py --help + +The input options: + -h, --help Show this help message and exit. + -c CONTEXT_STRING, --context-string CONTEXT_STRING + The context string (max 40 byts) for + generating passphrase. + -e ECID, --ecid ECID The ECID (Embedded chip ID) of the chip. + -k KEY_FILE, --key-file KEY_FILE + The key (16 bytes) file in hex format. + -u, --unique-pass Generate a unique passphrase. + +The command example: +$ python3 gen_luks_passphrase.py -k ekb.key \ + -u \ + -e "${ECID}" \ + -c "${DISK_UUID}" + +Use with cryptsetup to create encryption disk or to unlock disk: +$ gen_luks_passphrase.ph ... | cryptsetup ... luksFormat ... +or +$ gen_luks_passphrase.ph ... | cryptsetup ... luksOpen ... diff --git a/optee/samples/luks-srv/host/tool/gen_luks_passphrase/example.sh b/optee/samples/luks-srv/host/tool/gen_luks_passphrase/example.sh new file mode 100755 index 0000000..15b444a --- /dev/null +++ b/optee/samples/luks-srv/host/tool/gen_luks_passphrase/example.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# This is the default ekb key. +echo "00000000000000000000000000000000" > ekb.key + +# Generate a unique passphrase. +python3 gen_luks_passphrase.py -k ekb.key \ + -c "UUID of the disk" \ + -u \ + -e "0x880219116451e2c60c00000001ff0140" + diff --git a/optee/samples/luks-srv/host/tool/gen_luks_passphrase/gen_luks_passphrase.py b/optee/samples/luks-srv/host/tool/gen_luks_passphrase/gen_luks_passphrase.py new file mode 100755 index 0000000..d2094ac --- /dev/null +++ b/optee/samples/luks-srv/host/tool/gen_luks_passphrase/gen_luks_passphrase.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +import argparse +import codecs +import os.path +import struct +import sys + +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import cmac +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from math import ceil + +def nist_sp_800_108_with_CMAC(key, context=b"", label=b"", len=16): + okm = b"" + output_block = b"" + for count in range(ceil(len/16)): + data = b"".join([bytes([count+1]), label.encode(encoding="utf8"), bytes([0]), context.encode(encoding="utf8"), int(len*8).to_bytes(4, byteorder="big")]) + c = cmac.CMAC(algorithms.AES(key), backend=default_backend()) + c.update(data) + output_block = c.finalize() + okm += output_block + return okm[:len] + +def load_file_check_size(f, size=16): + with open(f, 'rb') as fd: + content = fd.read().strip() + if content.startswith(b'0x') or content.startswith(b'0X'): + content = content[2:] + key = codecs.decode(content, 'hex') + if len(key) != size: + raise Exception("Wrong size") + return key + +def main(): + global verbose + + parser = argparse.ArgumentParser(description=''' + Generates LUKS passphrase by using a key file which indicates a key from EKB. + The key file includes one user-defined 16-bytes symmetric key. + ''') + + parser.add_argument('-c', '--context-string', nargs=1, required=True, type=str, help="The context string (max 40 byts) for generating passphrase.") + parser.add_argument('-e', '--ecid', nargs=1, type=str, help="The ECID (Embedded chip ID) of the chip.") + parser.add_argument('-k', '--key-file', nargs=1, help="The key (16 bytes) file in hex format.") + parser.add_argument('-u', '--unique-pass', default=False, action='store_true', help="Generate a unique passphrase.") + parser.add_argument('-g', '--generic-pass', dest='unique-pass', action='store_false', help="Generate a generic passphrase.") + + args = parser.parse_args() + + if len(args.context_string[0]) > 40: + raise Exception("The max context string length is 40 bytes.\n") + + if args.unique_pass: + if not args.ecid: + raise Exception("The ECID is needed for the unique passphrase.\n") + if len(args.ecid[0]) > 34: + raise Exception("The max ECID string length is 32 bytes (34 bytes if \"0x\" is included).\n") + ecid_str = ''.join(str(c) for c in args.ecid) + ecid_int = int(ecid_str, 16) + # use the lower 100 bits as ECID + clear_bits = 0xfffffff + ecid_int &= ~(clear_bits << 100) + ecid_str = "%032x" % ecid_int + + if not args.key_file: + # key file doesn't been specified; use the default key + key = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + elif all(map(os.path.exists, [args.key_file[0]])): + # load key file + key = load_file_check_size(args.key_file[0]) + else: + raise Exception("%s cannot be opened.\n" % args.key_file[0]) + + # Derive LUKS key + if args.unique_pass: + label_str = "luks-srv-ecid" + luks_key = nist_sp_800_108_with_CMAC(key, ecid_str, label_str) + else: + label_str = "luks-srv-generic" + context_str = "generic-key" + luks_key = nist_sp_800_108_with_CMAC(key, context_str, label_str) + + # Generate passphrase + if args.unique_pass: + label_str = "luks-srv-passphrase-unique" + else: + label_str = "luks-srv-passphrase-generic" + context_str = ''.join(str(c) for c in args.context_string) + passphrase = nist_sp_800_108_with_CMAC(luks_key, context_str, label_str) + print("%s" % passphrase.hex()) + +if __name__ == "__main__": + main() + diff --git a/optee/samples/luks-srv/ta/Makefile b/optee/samples/luks-srv/ta/Makefile new file mode 100644 index 0000000..9170d0b --- /dev/null +++ b/optee/samples/luks-srv/ta/Makefile @@ -0,0 +1,7 @@ +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +# The UUID for the luks-srv TA +BINARY=b83d14a8-7128-49df-9624-35f14f65ca6c + +include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk diff --git a/optee/samples/luks-srv/ta/include/luks_srv_ta.h b/optee/samples/luks-srv/ta/include/luks_srv_ta.h new file mode 100644 index 0000000..3972ce4 --- /dev/null +++ b/optee/samples/luks-srv/ta/include/luks_srv_ta.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __LUKS_SRV_TA_H__ +#define __LUKS_SRV_TA_H__ + +/* + * Each trusted app UUID should have a unique UUID that is + * generated from a UUID generator such as + * https://www.uuidgenerator.net/ + * + * UUID : {b83d14a8-7128-49df-9624-35f14f65ca6c} + */ +#define LUKS_SRV_TA_UUID \ + { 0xb83d14a8, 0x7128, 0x49df, \ + { 0x96, 0x24, 0x35, 0xf1, 0x4f, 0x65, 0xca, 0x6c } } + +#define LUKS_SRV_CONTEXT_STR_LEN 40 +#define LUKS_SRV_PASSPHRASE_LEN 16 + +/* + * LUKS_SRV_TA_CMD_GET_UNIQUE_PASS - Get unique passphrase + * param[0] in (memref) context string, length + * param[1] out (memref) passphrase, size + * param[2] unused + * param[3] unused + */ +#define LUKS_SRV_TA_CMD_GET_UNIQUE_PASS 0 + +/* + * LUKS_SRV_TA_CMD_SRV_DOWN - Turn off the service + * param[0] unused + * param[1] unused + * param[2] unused + * param[3] unused + */ +#define LUKS_SRV_TA_CMD_SRV_DOWN 1 + +/* + * LUKS_SRV_TA_CMD_GET_GENERIC_PASS - Get generic passphrase + * param[0] in (memref) context string, length + * param[1] out (memref) passphrase, size + * param[2] unused + * param[3] unused + */ +#define LUKS_SRV_TA_CMD_GET_GENERIC_PASS 2 + +#endif diff --git a/optee/samples/luks-srv/ta/luks_srv_ta.c b/optee/samples/luks-srv/ta/luks_srv_ta.c new file mode 100644 index 0000000..f3fe3cd --- /dev/null +++ b/optee/samples/luks-srv/ta/luks_srv_ta.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2023, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +#define AES128_KEY_BIT_SIZE 128 +#define AES128_KEY_BYTE_SIZE (AES128_KEY_BIT_SIZE / 8) + +static uint8_t luks_key[AES128_KEY_BYTE_SIZE] = { 0 }; + +static TEE_Result invoke_jetson_user_key_pta(uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + static TEE_TASessionHandle sess = TEE_HANDLE_NULL; + static const TEE_UUID uuid = JETSON_USER_KEY_UUID; + + if (sess == TEE_HANDLE_NULL) { + TEE_Result rc = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, + 0, NULL, &sess, NULL); + + if (rc) + return rc; + } + + return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, + param_types, params, NULL); +} + +static TEE_Result luks_srv_gen_unique_pass(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + uint32_t pa_for_luks_key, pa_for_pass; + TEE_Param params_for_luks_key[TEE_NUM_PARAMS] = { }; + TEE_Param params_for_pass[TEE_NUM_PARAMS] = { }; + char label_str_for_luks_key[] = "luks-srv-ecid"; + char label_str_for_pass[] = "luks-srv-passphrase-unique"; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + if ((params[0].memref.size > LUKS_SRV_CONTEXT_STR_LEN) || + (params[1].memref.size > LUKS_SRV_PASSPHRASE_LEN)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Generate a unique LUKS key */ + pa_for_luks_key = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE); + params_for_luks_key[0].value.a = EKB_USER_KEY_DISK_ENCRYPTION; + params_for_luks_key[1].memref.buffer = label_str_for_luks_key; + params_for_luks_key[1].memref.size = strlen(label_str_for_luks_key); + params_for_luks_key[2].memref.buffer = luks_key; + params_for_luks_key[2].memref.size = AES128_KEY_BYTE_SIZE; + rc = invoke_jetson_user_key_pta( + JETSON_USER_KEY_CMD_GEN_UNIQUE_KEY_BY_EKB, + pa_for_luks_key, params_for_luks_key); + if (rc) + return rc; + + /* Generate the device unique passphrase. */ + pa_for_pass = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT); + params_for_pass[0].memref.buffer = luks_key; + params_for_pass[0].memref.size = AES128_KEY_BYTE_SIZE; + params_for_pass[1].memref.buffer = params[0].memref.buffer; + params_for_pass[1].memref.size = params[0].memref.size; + params_for_pass[2].memref.buffer = label_str_for_pass; + params_for_pass[2].memref.size = strlen(label_str_for_pass); + params_for_pass[3].memref.buffer = params[1].memref.buffer; + params_for_pass[3].memref.size = params[1].memref.size; + rc = invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_GEN_KEY, + pa_for_pass, params_for_pass); + + return rc; +} + +static TEE_Result luks_srv_gen_generic_pass(uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc = TEE_SUCCESS; + uint32_t disk_key_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param params_for_disk_key[TEE_NUM_PARAMS] = { }; + uint8_t disk_key[AES128_KEY_BYTE_SIZE] = { 0 }; + uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + char label_str_for_generic_key[] = "luks-srv-generic"; + char context_str_for_generic_key[] = "generic-key"; + uint32_t pt_for_generic_key; + TEE_Param params_for_generic_key[TEE_NUM_PARAMS] = { }; + uint8_t generic_key[AES128_KEY_BIT_SIZE] = { 0 }; + char label_str_for_pass[] = "luks-srv-passphrase-generic"; + uint32_t pt_for_generic_pass; + TEE_Param params_for_generic_pass[TEE_NUM_PARAMS] = { }; + + if (exp_pt != param_types) + return TEE_ERROR_BAD_PARAMETERS; + if ((params[0].memref.size > LUKS_SRV_CONTEXT_STR_LEN) || + (params[1].memref.size > LUKS_SRV_PASSPHRASE_LEN)) + return TEE_ERROR_BAD_PARAMETERS; + + /* Get disk key from EKB. */ + params_for_disk_key[0].value.a = EKB_USER_KEY_DISK_ENCRYPTION; + params_for_disk_key[1].memref.buffer = disk_key; + params_for_disk_key[1].memref.size = AES128_KEY_BYTE_SIZE; + rc = invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_GET_EKB_KEY, + disk_key_pt, params_for_disk_key); + if (rc) + return rc; + + /* Generate a generic LUKS key. */ + pt_for_generic_key = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT); + params_for_generic_key[0].memref.buffer = params_for_disk_key[1].memref.buffer; + params_for_generic_key[0].memref.size = params_for_disk_key[1].memref.size; + params_for_generic_key[1].memref.buffer = context_str_for_generic_key; + params_for_generic_key[1].memref.size = strlen(context_str_for_generic_key); + params_for_generic_key[2].memref.buffer = label_str_for_generic_key; + params_for_generic_key[2].memref.size = strlen(label_str_for_generic_key); + params_for_generic_key[3].memref.buffer = generic_key; + params_for_generic_key[3].memref.size = AES128_KEY_BYTE_SIZE; + rc = invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_GEN_KEY, + pt_for_generic_key, + params_for_generic_key); + if (rc) + return rc; + + /* Generate the generic passphrase. */ + pt_for_generic_pass = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_OUTPUT); + params_for_generic_pass[0].memref.buffer = params_for_generic_key[3].memref.buffer; + params_for_generic_pass[0].memref.size = params_for_generic_key[3].memref.size; + params_for_generic_pass[1].memref.buffer = params[0].memref.buffer; + params_for_generic_pass[1].memref.size = params[0].memref.size; + params_for_generic_pass[2].memref.buffer = label_str_for_pass; + params_for_generic_pass[2].memref.size = strlen(label_str_for_pass); + params_for_generic_pass[3].memref.buffer = params[1].memref.buffer; + params_for_generic_pass[3].memref.size = params[1].memref.size; + rc = invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_GEN_KEY, + pt_for_generic_pass, + params_for_generic_pass); + + return rc; +} + +TEE_Result TA_CreateEntryPoint(void) +{ + /* Nothing to do */ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ + /* Nothing to do */ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types, + TEE_Param __unused params[TEE_NUM_PARAMS], + void __unused **session) +{ + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void __unused *session) +{ +} + +TEE_Result TA_InvokeCommandEntryPoint(void __unused *session, + uint32_t cmd, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + TEE_Result rc; + uint32_t pa_luks_srv_flag; + TEE_Param params_lusk_srv_flag[TEE_NUM_PARAMS] = { }; + + /* Check LUKS SRV flag */ + pa_luks_srv_flag = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + params_lusk_srv_flag[0].value.a = LUKS_SRV_FLAG; + rc = invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_GET_FLAG, + pa_luks_srv_flag, + params_lusk_srv_flag); + if (rc) + return rc; + + if (!params_lusk_srv_flag[1].value.a) + return TEE_ERROR_ACCESS_DENIED; + + switch (cmd) { + case LUKS_SRV_TA_CMD_GET_UNIQUE_PASS: + return luks_srv_gen_unique_pass(param_types, params); + case LUKS_SRV_TA_CMD_GET_GENERIC_PASS: + return luks_srv_gen_generic_pass(param_types, params); + case LUKS_SRV_TA_CMD_SRV_DOWN: + pa_luks_srv_flag = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + params_lusk_srv_flag[0].value.a = LUKS_SRV_FLAG; + params_lusk_srv_flag[0].value.b = false; + invoke_jetson_user_key_pta(JETSON_USER_KEY_CMD_SET_FLAG, + pa_luks_srv_flag, + params_lusk_srv_flag); + return TEE_SUCCESS; + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} diff --git a/optee/samples/luks-srv/ta/sub.mk b/optee/samples/luks-srv/ta/sub.mk new file mode 100644 index 0000000..d1d3a71 --- /dev/null +++ b/optee/samples/luks-srv/ta/sub.mk @@ -0,0 +1,5 @@ +# Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause + +global-incdirs-y += include +srcs-y += luks_srv_ta.c diff --git a/optee/samples/luks-srv/ta/user_ta_header_defines.h b/optee/samples/luks-srv/ta/user_ta_header_defines.h new file mode 100644 index 0000000..660ebc4 --- /dev/null +++ b/optee/samples/luks-srv/ta/user_ta_header_defines.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021-2022, NVIDIA Corporation & AFFILIATES. All rights reserved. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef __USER_TA_HEADER_DEFINES_H__ +#define __USER_TA_HEADER_DEFINES_H__ + +#include + +#define TA_UUID LUKS_SRV_TA_UUID +#define TA_FLAGS TA_FLAG_SINGLE_INSTANCE +#define TA_STACK_SIZE (2 * 1024) +#define TA_DATA_SIZE (16 * 1024) + +#endif diff --git a/optee/tegra194-optee.dts b/optee/tegra194-optee.dts new file mode 100644 index 0000000..415898d --- /dev/null +++ b/optee/tegra194-optee.dts @@ -0,0 +1,72 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + */ + +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + + /* MB2 fills the non-secure memory chucks here in order to + * enable the dynamic shared memory in OP-TEE. + * Example: + * nsec-memory@ { + * device_type = "memory"; + * reg = ; + * }; + */ + + /* MB2 will fill the address and size of EKB blob */ + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + + ekb-blob@0 { + compatible = "jetson-ekb-blob"; + reg = <0 0 0 0>; + }; + }; + + efuse@03820000 { + compatible = "nvidia,tegra194-efuse"; + reg = <0x0 0x03820000 0x0 0x600>; + status = "disabled"; + secure-status = "okay"; + }; + + se0@03ac0000 { + compatible = "nvidia,tegra194-se0"; + reg = <0x0 0x03ac0000 0x0 0x2000>; + status = "disabled"; + secure-status = "okay"; + }; + + se0-rng1@03ae0000 { + compatible = "nvidia,tegra194-se0-elp-rng1"; + reg = <0x0 0x03ae0000 0x0 0x10000>; + status = "disabled"; + secure-status = "okay"; + }; + + stmm-device-mappings { + uuid = <0xed32d533 0x99e64209 0x9cc02d72 0xcdd998a7>; + description = "UEFI-mm"; + + device-regions { + combuart-t194 { + base-address = <0x00000000 0x0c198000>; + pages-count = <0x1>; + attributes = <0x3>; /* read-write */ + }; + + qspi0-t194 { + base-address = <0x00000000 0x03270000>; + pages-count = <0x10>; + attributes = <0x3>; /* read-write */ + }; + }; + }; +}; diff --git a/optee/tegra234-optee.dts b/optee/tegra234-optee.dts new file mode 100644 index 0000000..19d4274 --- /dev/null +++ b/optee/tegra234-optee.dts @@ -0,0 +1,130 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. + */ + +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + + /* MB2 fills the non-secure memory chucks here in order to + * enable the dynamic shared memory in OP-TEE. + * Example: + * nsec-memory@ { + * device_type = "memory"; + * reg = ; + * }; + */ + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + + /* MB2 will fill the DICE identities in the DICE node. */ + dice { + compatible = "nvidia,dice-identity"; + status = "disabled"; + secure-status = "disabled"; + #address-cells = <2>; + #size-cells = <2>; + + eca-csr@0 { + compatible = "nvidia,dice-eca-csr"; + reg = <0 0 0 0>; + status = "disabled"; + secure-status = "disabled"; + }; + + device-id-cert@0 { + compatible = "nvidia,dice-device-id-cert"; + reg = <0 0 0 0>; + status = "disabled"; + secure-status = "disabled"; + }; + + device-id-key-pub@0 { + compatible = "nvidia,dice-device-id-key-pub"; + reg = <0 0 0 0>; + status = "disabled"; + secure-status = "disabled"; + }; + + alias-key-cert@0 { + compatible = "nvidia,dice-alias-key-cert"; + reg = <0 0 0 0>; + status = "disabled"; + secure-status = "disabled"; + }; + + alias-key-pub@0 { + compatible = "nvidia,dice-alias-key-pub"; + reg = <0 0 0 0>; + status = "disabled"; + secure-status = "disabled"; + }; + + alias-key-priv@0 { + compatible = "nvidia,dice-alias-key-priv"; + reg = <0 0 0 0>; + status = "disabled"; + secure-status = "disabled"; + }; + }; + + /* MB2 will fill the address and size of EKB blob. */ + ekb-blob@0 { + compatible = "jetson-ekb-blob"; + reg = <0 0 0 0>; + }; + + /* MB2 will fill the address and size. */ + tpm-event-log@0 { + compatible = "arm,tpm_event_log"; + tpm_event_log_addr = <0x0 0x0>; + tpm_event_log_size = <0x0>; + }; + }; + + efuse@03810000 { + compatible = "nvidia,tegra234-efuse"; + reg = <0x0 0x03810000 0x0 0x600>; + status = "disabled"; + secure-status = "okay"; + }; + + se0@03b50000 { + compatible = "nvidia,tegra234-se0"; + reg = <0x0 0x03b50000 0x0 0x30000>; + status = "disabled"; + secure-status = "okay"; + }; + + rng1@03b70000 { + compatible = "nvidia,tegra234-rng1"; + reg = <0x0 0x03b70000 0x0 0x10000>; + status = "disabled"; + secure-status = "okay"; + }; + + stmm-device-mappings { + uuid = <0xed32d533 0x99e64209 0x9cc02d72 0xcdd998a7>; + description = "UEFI-mm"; + + device-regions { + combuart-t234 { + base-address = <0x00000000 0x0c198000>; + pages-count = <0x1>; + attributes = <0x3>; /* read-write */ + }; + + qspi0-t234 { + base-address = <0x00000000 0x03270000>; + pages-count = <0x10>; + attributes = <0x3>; /* read-write */ + }; + }; + }; +}; diff --git a/optee_src_build.sh b/optee_src_build.sh new file mode 100755 index 0000000..61306f2 --- /dev/null +++ b/optee_src_build.sh @@ -0,0 +1,183 @@ +#!/bin/bash + +# Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION 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 ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (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 script builds optee sources in the current working directory. +# Usage: ./${SCRIPT_NAME}.sh [OPTIONS] +set -e + +# shellcheck disable=SC2046 +SCRIPT_DIR="$(dirname $(readlink -f "${0}"))" +SCRIPT_NAME="$(basename "${0}")" + +source "${SCRIPT_DIR}/nvcommon_build.sh" + +function usage { + cat <

    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 z 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